From de0c6c02cb6a4608e01357c8a9f213a1e0a19425 Mon Sep 17 00:00:00 2001 From: Matteo Golin Date: Tue, 30 Jun 2026 10:22:59 -0400 Subject: [PATCH 1/3] apps/games/NXDoom: Original Chocolate DOOM source This commit adds the original Chocolate DOOM source which forms a basis for the NuttX port of DOOM. Signed-off-by: Matteo Golin --- games/NXDoom/.devcontainer/.gitignore | 4 + games/NXDoom/.devcontainer/Dockerfile | 39 + games/NXDoom/.devcontainer/devcontainer.json | 45 + .../NXDoom/.devcontainer/initialize-linux.sh | 9 + games/NXDoom/.github/CONTRIBUTING.md | 101 + games/NXDoom/.github/ISSUE_TEMPLATE.md | 28 + games/NXDoom/.github/workflows/cpp-linter.yml | 54 + games/NXDoom/.github/workflows/cppcheck.yml | 23 + games/NXDoom/.github/workflows/main.yml | 152 + games/NXDoom/.gitignore | 67 + games/NXDoom/.gitmodules | 3 + games/NXDoom/.lvimrc | 32 + games/NXDoom/.travis.sh | 19 + games/NXDoom/AUTHORS | 7 + games/NXDoom/CMakeLists.txt | 105 + games/NXDoom/CODE_OF_CONDUCT.md | 74 + games/NXDoom/COPYING.md | 361 + games/NXDoom/ChangeLog | 5 + games/NXDoom/HACKING.md | 256 + games/NXDoom/Makefile.am | 62 + games/NXDoom/NEWS.md | 1492 ++ games/NXDoom/NOT-BUGS.md | 149 + games/NXDoom/PHILOSOPHY.md | 214 + games/NXDoom/README.Music.md | 173 + games/NXDoom/README.Strife.md | 124 + games/NXDoom/README.md | 102 + games/NXDoom/RELEASE_NOTES.md | 35 + games/NXDoom/TODO.md | 36 + games/NXDoom/autogen.sh | 4 + games/NXDoom/check-extern.sh | 6 + games/NXDoom/cmake/FindFluidSynth.cmake | 106 + games/NXDoom/cmake/FindSDL2.cmake | 114 + games/NXDoom/cmake/FindSDL2_mixer.cmake | 88 + games/NXDoom/cmake/FindSDL2_net.cmake | 88 + games/NXDoom/cmake/FindSampleRate.cmake | 67 + games/NXDoom/cmake/Findm.cmake | 36 + games/NXDoom/cmake/config.h.cin | 12 + games/NXDoom/configure.ac | 335 + games/NXDoom/data/.gitignore | 7 + games/NXDoom/data/Makefile.am | 39 + games/NXDoom/data/README | 16 + games/NXDoom/data/convert-icon | 72 + games/NXDoom/data/doom.ico | Bin 0 -> 43344 bytes games/NXDoom/data/doom.png | Bin 0 -> 4551 bytes games/NXDoom/data/heretic.ico | Bin 0 -> 44563 bytes games/NXDoom/data/heretic.png | Bin 0 -> 5090 bytes games/NXDoom/data/hexen.ico | Bin 0 -> 44747 bytes games/NXDoom/data/hexen.png | Bin 0 -> 5033 bytes games/NXDoom/data/setup.ico | Bin 0 -> 45885 bytes games/NXDoom/data/setup.png | Bin 0 -> 5654 bytes games/NXDoom/data/strife.ico | Bin 0 -> 44131 bytes games/NXDoom/data/strife.png | Bin 0 -> 4966 bytes games/NXDoom/data/wadfile.png | Bin 0 -> 8681 bytes games/NXDoom/man/.gitignore | 16 + games/NXDoom/man/CMDLINE.template | 8 + games/NXDoom/man/CMDLINE.template.md | 8 + games/NXDoom/man/INSTALL.template | 316 + games/NXDoom/man/Makefile.am | 226 + games/NXDoom/man/bash-completion/.gitignore | 5 + games/NXDoom/man/bash-completion/Makefile.am | 52 + .../man/bash-completion/doom.template.in | 51 + .../man/bash-completion/heretic.template.in | 48 + .../man/bash-completion/hexen.template.in | 45 + .../man/bash-completion/strife.template.in | 48 + games/NXDoom/man/default.cfg.template | 50 + games/NXDoom/man/docgen | 624 + games/NXDoom/man/doom.template | 45 + games/NXDoom/man/environ.man | 34 + games/NXDoom/man/extra.cfg.template | 28 + games/NXDoom/man/heretic.template | 47 + games/NXDoom/man/hexen.template | 47 + games/NXDoom/man/iwad_paths.man | 73 + games/NXDoom/man/server.template | 55 + games/NXDoom/man/setup.template | 46 + games/NXDoom/man/simplecpp | 228 + games/NXDoom/man/strife.template | 91 + games/NXDoom/man/wikipages | 7 + games/NXDoom/opl/.gitignore | 7 + games/NXDoom/opl/CMakeLists.txt | 28 + games/NXDoom/opl/Makefile.am | 21 + games/NXDoom/opl/examples/.gitignore | 7 + games/NXDoom/opl/examples/Makefile.am | 8 + games/NXDoom/opl/examples/droplay.c | 210 + games/NXDoom/opl/ioperm_sys.c | 355 + games/NXDoom/opl/ioperm_sys.h | 28 + games/NXDoom/opl/opl.c | 530 + games/NXDoom/opl/opl.h | 153 + games/NXDoom/opl/opl3.c | 1377 ++ games/NXDoom/opl/opl3.h | 150 + games/NXDoom/opl/opl_internal.h | 71 + games/NXDoom/opl/opl_linux.c | 103 + games/NXDoom/opl/opl_obsd.c | 118 + games/NXDoom/opl/opl_queue.c | 285 + games/NXDoom/opl/opl_queue.h | 39 + games/NXDoom/opl/opl_sdl.c | 521 + games/NXDoom/opl/opl_timer.c | 250 + games/NXDoom/opl/opl_timer.h | 33 + games/NXDoom/opl/opl_win32.c | 192 + games/NXDoom/pcsound/.gitignore | 8 + games/NXDoom/pcsound/CMakeLists.txt | 24 + games/NXDoom/pcsound/Makefile.am | 15 + games/NXDoom/pcsound/pcsound.c | 119 + games/NXDoom/pcsound/pcsound.h | 38 + games/NXDoom/pcsound/pcsound_bsd.c | 321 + games/NXDoom/pcsound/pcsound_internal.h | 62 + games/NXDoom/pcsound/pcsound_linux.c | 171 + games/NXDoom/pcsound/pcsound_sdl.c | 254 + games/NXDoom/pcsound/pcsound_win32.c | 106 + games/NXDoom/pkg/.gitignore | 3 + games/NXDoom/pkg/Makefile.am | 25 + games/NXDoom/pkg/config.make.in | 30 + games/NXDoom/pkg/osx/.gitignore | 10 + games/NXDoom/pkg/osx/AppController.h | 45 + games/NXDoom/pkg/osx/AppController.m | 146 + games/NXDoom/pkg/osx/Execute.h | 24 + games/NXDoom/pkg/osx/Execute.m | 226 + games/NXDoom/pkg/osx/GNUmakefile | 132 + games/NXDoom/pkg/osx/IWADController.h | 57 + games/NXDoom/pkg/osx/IWADController.m | 482 + games/NXDoom/pkg/osx/Info.plist.in | 104 + games/NXDoom/pkg/osx/LauncherManager.h | 51 + games/NXDoom/pkg/osx/LauncherManager.m | 410 + games/NXDoom/pkg/osx/PkgInfo | 1 + games/NXDoom/pkg/osx/Resources/app.png | Bin 0 -> 4597 bytes .../osx/Resources/launcher.nib/designable.nib | 607 + .../Resources/launcher.nib/keyedobjects.nib | Bin 0 -> 31078 bytes games/NXDoom/pkg/osx/cp-with-libs | 107 + games/NXDoom/pkg/osx/disk/background.png | Bin 0 -> 227363 bytes games/NXDoom/pkg/osx/disk/dir.DS_Store | Bin 0 -> 28196 bytes games/NXDoom/pkg/osx/dmgfix | 67 + games/NXDoom/pkg/osx/main.m | 24 + games/NXDoom/pkg/style.html | 48 + games/NXDoom/pkg/win32/.gitignore | 2 + games/NXDoom/pkg/win32/GNUmakefile | 65 + games/NXDoom/pkg/win32/README | 2 + games/NXDoom/pkg/win32/cp-with-libs | 200 + games/NXDoom/rpm.spec.in | 121 + games/NXDoom/src/.gitignore | 22 + games/NXDoom/src/CMakeLists.txt | 287 + games/NXDoom/src/Doom.desktop.in | 8 + games/NXDoom/src/Doom.metainfo.xml.in | 74 + games/NXDoom/src/Doom_Screensaver.desktop.in | 10 + games/NXDoom/src/Heretic.desktop.in | 8 + games/NXDoom/src/Heretic.metainfo.xml.in | 47 + games/NXDoom/src/Hexen.desktop.in | 8 + games/NXDoom/src/Hexen.metainfo.xml.in | 47 + games/NXDoom/src/Makefile.am | 299 + games/NXDoom/src/Strife.desktop.in | 8 + games/NXDoom/src/Strife.metainfo.xml.in | 48 + games/NXDoom/src/aes_prng.c | 956 ++ games/NXDoom/src/aes_prng.h | 32 + games/NXDoom/src/d_dedicated.c | 47 + games/NXDoom/src/d_event.c | 63 + games/NXDoom/src/d_event.h | 147 + games/NXDoom/src/d_iwad.c | 1047 ++ games/NXDoom/src/d_iwad.h | 53 + games/NXDoom/src/d_loop.c | 881 + games/NXDoom/src/d_loop.h | 96 + games/NXDoom/src/d_mode.c | 233 + games/NXDoom/src/d_mode.h | 112 + games/NXDoom/src/d_ticcmd.h | 56 + games/NXDoom/src/deh_defs.h | 85 + games/NXDoom/src/deh_io.c | 357 + games/NXDoom/src/deh_io.h | 33 + games/NXDoom/src/deh_main.c | 519 + games/NXDoom/src/deh_main.h | 48 + games/NXDoom/src/deh_mapping.c | 200 + games/NXDoom/src/deh_mapping.h | 93 + games/NXDoom/src/deh_str.c | 433 + games/NXDoom/src/deh_str.h | 45 + games/NXDoom/src/deh_text.c | 113 + games/NXDoom/src/doom-res.rc.in | 30 + games/NXDoom/src/doom/.gitignore | 5 + games/NXDoom/src/doom/CMakeLists.txt | 91 + games/NXDoom/src/doom/Makefile.am | 83 + games/NXDoom/src/doom/am_map.c | 1374 ++ games/NXDoom/src/doom/am_map.h | 49 + games/NXDoom/src/doom/d_englsh.h | 693 + games/NXDoom/src/doom/d_items.c | 128 + games/NXDoom/src/doom/d_items.h | 41 + games/NXDoom/src/doom/d_main.c | 2002 +++ games/NXDoom/src/doom/d_main.h | 53 + games/NXDoom/src/doom/d_net.c | 287 + games/NXDoom/src/doom/d_player.h | 209 + games/NXDoom/src/doom/d_textur.h | 43 + games/NXDoom/src/doom/d_think.h | 68 + games/NXDoom/src/doom/deh_ammo.c | 103 + games/NXDoom/src/doom/deh_bexstr.c | 376 + games/NXDoom/src/doom/deh_cheat.c | 146 + games/NXDoom/src/doom/deh_doom.c | 48 + games/NXDoom/src/doom/deh_frame.c | 161 + games/NXDoom/src/doom/deh_misc.c | 228 + games/NXDoom/src/doom/deh_misc.h | 79 + games/NXDoom/src/doom/deh_ptr.c | 142 + games/NXDoom/src/doom/deh_sound.c | 102 + games/NXDoom/src/doom/deh_thing.c | 131 + games/NXDoom/src/doom/deh_weapon.c | 101 + games/NXDoom/src/doom/doom_icon.c | 2736 ++++ games/NXDoom/src/doom/doomdata.h | 213 + games/NXDoom/src/doom/doomdef.c | 28 + games/NXDoom/src/doom/doomdef.h | 168 + games/NXDoom/src/doom/doomstat.c | 35 + games/NXDoom/src/doom/doomstat.h | 277 + games/NXDoom/src/doom/dstrings.c | 73 + games/NXDoom/src/doom/dstrings.h | 41 + games/NXDoom/src/doom/f_finale.c | 718 + games/NXDoom/src/doom/f_finale.h | 45 + games/NXDoom/src/doom/f_wipe.c | 294 + games/NXDoom/src/doom/f_wipe.h | 63 + games/NXDoom/src/doom/g_game.c | 2408 +++ games/NXDoom/src/doom/g_game.h | 88 + games/NXDoom/src/doom/hu_lib.c | 347 + games/NXDoom/src/doom/hu_lib.h | 182 + games/NXDoom/src/doom/hu_stuff.c | 707 + games/NXDoom/src/doom/hu_stuff.h | 68 + games/NXDoom/src/doom/info.c | 4662 ++++++ games/NXDoom/src/doom/info.h | 1331 ++ games/NXDoom/src/doom/m_menu.c | 2128 +++ games/NXDoom/src/doom/m_menu.h | 62 + games/NXDoom/src/doom/m_random.c | 72 + games/NXDoom/src/doom/m_random.h | 40 + games/NXDoom/src/doom/p_ceilng.c | 324 + games/NXDoom/src/doom/p_doors.c | 779 + games/NXDoom/src/doom/p_enemy.c | 2024 +++ games/NXDoom/src/doom/p_floor.c | 561 + games/NXDoom/src/doom/p_inter.c | 931 ++ games/NXDoom/src/doom/p_inter.h | 30 + games/NXDoom/src/doom/p_lights.c | 350 + games/NXDoom/src/doom/p_local.h | 305 + games/NXDoom/src/doom/p_map.c | 1445 ++ games/NXDoom/src/doom/p_maputl.c | 1002 ++ games/NXDoom/src/doom/p_mobj.c | 1072 ++ games/NXDoom/src/doom/p_mobj.h | 284 + games/NXDoom/src/doom/p_plats.c | 304 + games/NXDoom/src/doom/p_pspr.c | 887 + games/NXDoom/src/doom/p_pspr.h | 75 + games/NXDoom/src/doom/p_saveg.c | 1888 +++ games/NXDoom/src/doom/p_saveg.h | 65 + games/NXDoom/src/doom/p_setup.c | 833 + games/NXDoom/src/doom/p_setup.h | 39 + games/NXDoom/src/doom/p_sight.c | 394 + games/NXDoom/src/doom/p_spec.c | 1519 ++ games/NXDoom/src/doom/p_spec.h | 637 + games/NXDoom/src/doom/p_switch.c | 641 + games/NXDoom/src/doom/p_telept.c | 132 + games/NXDoom/src/doom/p_tick.c | 153 + games/NXDoom/src/doom/p_tick.h | 33 + games/NXDoom/src/doom/p_user.c | 379 + games/NXDoom/src/doom/r_bsp.c | 583 + games/NXDoom/src/doom/r_bsp.h | 61 + games/NXDoom/src/doom/r_data.c | 904 + games/NXDoom/src/doom/r_data.h | 55 + games/NXDoom/src/doom/r_defs.h | 448 + games/NXDoom/src/doom/r_draw.c | 959 ++ games/NXDoom/src/doom/r_draw.h | 104 + games/NXDoom/src/doom/r_local.h | 45 + games/NXDoom/src/doom/r_main.c | 890 + games/NXDoom/src/doom/r_main.h | 165 + games/NXDoom/src/doom/r_plane.c | 449 + games/NXDoom/src/doom/r_plane.h | 76 + games/NXDoom/src/doom/r_segs.c | 743 + games/NXDoom/src/doom/r_segs.h | 34 + games/NXDoom/src/doom/r_sky.c | 52 + games/NXDoom/src/doom/r_sky.h | 37 + games/NXDoom/src/doom/r_state.h | 127 + games/NXDoom/src/doom/r_things.c | 982 ++ games/NXDoom/src/doom/r_things.h | 65 + games/NXDoom/src/doom/s_sound.c | 724 + games/NXDoom/src/doom/s_sound.h | 89 + games/NXDoom/src/doom/sounds.c | 229 + games/NXDoom/src/doom/sounds.h | 227 + games/NXDoom/src/doom/st_lib.c | 283 + games/NXDoom/src/doom/st_lib.h | 209 + games/NXDoom/src/doom/st_stuff.c | 1367 ++ games/NXDoom/src/doom/st_stuff.h | 69 + games/NXDoom/src/doom/statdump.c | 357 + games/NXDoom/src/doom/statdump.h | 23 + games/NXDoom/src/doom/wi_stuff.c | 1833 +++ games/NXDoom/src/doom/wi_stuff.h | 48 + games/NXDoom/src/doomkeys.h | 156 + games/NXDoom/src/doomtype.h | 145 + games/NXDoom/src/gusconf.c | 301 + games/NXDoom/src/gusconf.h | 29 + games/NXDoom/src/heretic-res.rc.in | 30 + games/NXDoom/src/heretic/.gitignore | 6 + games/NXDoom/src/heretic/CMakeLists.txt | 77 + games/NXDoom/src/heretic/Makefile.am | 72 + games/NXDoom/src/heretic/am_data.h | 103 + games/NXDoom/src/heretic/am_map.c | 1535 ++ games/NXDoom/src/heretic/am_map.h | 124 + games/NXDoom/src/heretic/ct_chat.c | 477 + games/NXDoom/src/heretic/ct_chat.h | 38 + games/NXDoom/src/heretic/d_main.c | 1171 ++ games/NXDoom/src/heretic/d_net.c | 218 + games/NXDoom/src/heretic/deh_ammo.c | 113 + games/NXDoom/src/heretic/deh_frame.c | 335 + games/NXDoom/src/heretic/deh_htext.c | 845 + games/NXDoom/src/heretic/deh_htic.c | 182 + games/NXDoom/src/heretic/deh_htic.h | 56 + games/NXDoom/src/heretic/deh_sound.c | 108 + games/NXDoom/src/heretic/deh_thing.c | 144 + games/NXDoom/src/heretic/deh_weapon.c | 122 + games/NXDoom/src/heretic/doomdata.h | 192 + games/NXDoom/src/heretic/doomdef.h | 858 + games/NXDoom/src/heretic/dstrings.h | 244 + games/NXDoom/src/heretic/f_finale.c | 436 + games/NXDoom/src/heretic/g_game.c | 2284 +++ games/NXDoom/src/heretic/heretic_icon.c | 2736 ++++ games/NXDoom/src/heretic/in_lude.c | 1075 ++ games/NXDoom/src/heretic/info.c | 5600 +++++++ games/NXDoom/src/heretic/info.h | 1584 ++ games/NXDoom/src/heretic/m_random.c | 76 + games/NXDoom/src/heretic/m_random.h | 37 + games/NXDoom/src/heretic/mn_menu.c | 1824 +++ games/NXDoom/src/heretic/p_action.h | 151 + games/NXDoom/src/heretic/p_ceilng.c | 256 + games/NXDoom/src/heretic/p_doors.c | 380 + games/NXDoom/src/heretic/p_enemy.c | 2711 +++ games/NXDoom/src/heretic/p_floor.c | 461 + games/NXDoom/src/heretic/p_inter.c | 1488 ++ games/NXDoom/src/heretic/p_lights.c | 280 + games/NXDoom/src/heretic/p_local.h | 292 + games/NXDoom/src/heretic/p_map.c | 1696 ++ games/NXDoom/src/heretic/p_maputl.c | 779 + games/NXDoom/src/heretic/p_mobj.c | 1626 ++ games/NXDoom/src/heretic/p_plats.c | 259 + games/NXDoom/src/heretic/p_pspr.c | 1907 +++ games/NXDoom/src/heretic/p_saveg.c | 1925 +++ games/NXDoom/src/heretic/p_setup.c | 709 + games/NXDoom/src/heretic/p_sight.c | 355 + games/NXDoom/src/heretic/p_spec.c | 1306 ++ games/NXDoom/src/heretic/p_spec.h | 390 + games/NXDoom/src/heretic/p_switch.c | 409 + games/NXDoom/src/heretic/p_telept.c | 164 + games/NXDoom/src/heretic/p_tick.c | 167 + games/NXDoom/src/heretic/p_user.c | 1017 ++ games/NXDoom/src/heretic/r_bsp.c | 489 + games/NXDoom/src/heretic/r_data.c | 732 + games/NXDoom/src/heretic/r_draw.c | 490 + games/NXDoom/src/heretic/r_local.h | 487 + games/NXDoom/src/heretic/r_main.c | 818 + games/NXDoom/src/heretic/r_plane.c | 511 + games/NXDoom/src/heretic/r_segs.c | 661 + games/NXDoom/src/heretic/r_things.c | 1017 ++ games/NXDoom/src/heretic/s_sound.c | 607 + games/NXDoom/src/heretic/s_sound.h | 40 + games/NXDoom/src/heretic/sb_bar.c | 1283 ++ games/NXDoom/src/heretic/sounds.c | 249 + games/NXDoom/src/heretic/sounds.h | 291 + games/NXDoom/src/hexen-res.rc.in | 30 + games/NXDoom/src/hexen/.gitignore | 5 + games/NXDoom/src/hexen/CMakeLists.txt | 78 + games/NXDoom/src/hexen/Makefile.am | 71 + games/NXDoom/src/hexen/a_action.c | 1341 ++ games/NXDoom/src/hexen/am_data.h | 109 + games/NXDoom/src/hexen/am_map.c | 1544 ++ games/NXDoom/src/hexen/am_map.h | 128 + games/NXDoom/src/hexen/ct_chat.c | 497 + games/NXDoom/src/hexen/ct_chat.h | 38 + games/NXDoom/src/hexen/d_net.c | 283 + games/NXDoom/src/hexen/f_finale.c | 387 + games/NXDoom/src/hexen/g_game.c | 2347 +++ games/NXDoom/src/hexen/h2_main.c | 1227 ++ games/NXDoom/src/hexen/h2def.h | 1121 ++ games/NXDoom/src/hexen/hexen_icon.c | 2736 ++++ games/NXDoom/src/hexen/in_lude.c | 607 + games/NXDoom/src/hexen/info.c | 13654 ++++++++++++++++ games/NXDoom/src/hexen/info.h | 3626 ++++ games/NXDoom/src/hexen/m_random.c | 80 + games/NXDoom/src/hexen/m_random.h | 37 + games/NXDoom/src/hexen/mn_menu.c | 1952 +++ games/NXDoom/src/hexen/p_acs.c | 1996 +++ games/NXDoom/src/hexen/p_action.h | 240 + games/NXDoom/src/hexen/p_anim.c | 477 + games/NXDoom/src/hexen/p_ceilng.c | 303 + games/NXDoom/src/hexen/p_doors.c | 319 + games/NXDoom/src/hexen/p_enemy.c | 5428 ++++++ games/NXDoom/src/hexen/p_floor.c | 946 ++ games/NXDoom/src/hexen/p_inter.c | 2231 +++ games/NXDoom/src/hexen/p_lights.c | 369 + games/NXDoom/src/hexen/p_local.h | 429 + games/NXDoom/src/hexen/p_map.c | 2338 +++ games/NXDoom/src/hexen/p_maputl.c | 1072 ++ games/NXDoom/src/hexen/p_mobj.c | 2469 +++ games/NXDoom/src/hexen/p_plats.c | 277 + games/NXDoom/src/hexen/p_pspr.c | 2476 +++ games/NXDoom/src/hexen/p_setup.c | 1273 ++ games/NXDoom/src/hexen/p_sight.c | 398 + games/NXDoom/src/hexen/p_spec.c | 1202 ++ games/NXDoom/src/hexen/p_spec.h | 586 + games/NXDoom/src/hexen/p_switch.c | 172 + games/NXDoom/src/hexen/p_telept.c | 190 + games/NXDoom/src/hexen/p_things.c | 537 + games/NXDoom/src/hexen/p_tick.c | 151 + games/NXDoom/src/hexen/p_user.c | 1643 ++ games/NXDoom/src/hexen/po_man.c | 1505 ++ games/NXDoom/src/hexen/r_bsp.c | 508 + games/NXDoom/src/hexen/r_data.c | 689 + games/NXDoom/src/hexen/r_draw.c | 558 + games/NXDoom/src/hexen/r_local.h | 554 + games/NXDoom/src/hexen/r_main.c | 830 + games/NXDoom/src/hexen/r_plane.c | 579 + games/NXDoom/src/hexen/r_segs.c | 654 + games/NXDoom/src/hexen/r_things.c | 1044 ++ games/NXDoom/src/hexen/s_sound.c | 1014 ++ games/NXDoom/src/hexen/s_sound.h | 94 + games/NXDoom/src/hexen/sb_bar.c | 2000 +++ games/NXDoom/src/hexen/sc_man.c | 465 + games/NXDoom/src/hexen/sn_sonix.c | 535 + games/NXDoom/src/hexen/sounds.c | 313 + games/NXDoom/src/hexen/sounds.h | 321 + games/NXDoom/src/hexen/st_start.c | 310 + games/NXDoom/src/hexen/st_start.h | 41 + games/NXDoom/src/hexen/sv_save.c | 3508 ++++ games/NXDoom/src/hexen/textdefs.h | 172 + games/NXDoom/src/hexen/xddefs.h | 189 + games/NXDoom/src/i_cdmus.c | 79 + games/NXDoom/src/i_cdmus.h | 41 + games/NXDoom/src/i_endoom.c | 79 + games/NXDoom/src/i_endoom.h | 29 + games/NXDoom/src/i_flmusic.c | 332 + games/NXDoom/src/i_glob.c | 373 + games/NXDoom/src/i_glob.h | 44 + games/NXDoom/src/i_input.c | 473 + games/NXDoom/src/i_input.h | 49 + games/NXDoom/src/i_joystick.c | 826 + games/NXDoom/src/i_joystick.h | 115 + games/NXDoom/src/i_main.c | 79 + games/NXDoom/src/i_musicpack.c | 1496 ++ games/NXDoom/src/i_oplmusic.c | 1898 +++ games/NXDoom/src/i_pcsound.c | 338 + games/NXDoom/src/i_sdlmusic.c | 473 + games/NXDoom/src/i_sdlsound.c | 1146 ++ games/NXDoom/src/i_sound.c | 540 + games/NXDoom/src/i_sound.h | 300 + games/NXDoom/src/i_swap.h | 43 + games/NXDoom/src/i_system.c | 470 + games/NXDoom/src/i_system.h | 86 + games/NXDoom/src/i_timer.c | 82 + games/NXDoom/src/i_timer.h | 42 + games/NXDoom/src/i_video.c | 1537 ++ games/NXDoom/src/i_video.h | 110 + games/NXDoom/src/i_videohr.c | 257 + games/NXDoom/src/i_videohr.h | 35 + games/NXDoom/src/i_winmusic.c | 1920 +++ games/NXDoom/src/m_argv.c | 556 + games/NXDoom/src/m_argv.h | 53 + games/NXDoom/src/m_bbox.c | 54 + games/NXDoom/src/m_bbox.h | 47 + games/NXDoom/src/m_cheat.c | 89 + games/NXDoom/src/m_cheat.h | 62 + games/NXDoom/src/m_config.c | 2811 ++++ games/NXDoom/src/m_config.h | 43 + games/NXDoom/src/m_controls.c | 457 + games/NXDoom/src/m_controls.h | 194 + games/NXDoom/src/m_fixed.c | 62 + games/NXDoom/src/m_fixed.h | 39 + games/NXDoom/src/m_misc.c | 965 ++ games/NXDoom/src/m_misc.h | 107 + games/NXDoom/src/manifest.xml | 12 + games/NXDoom/src/memio.c | 197 + games/NXDoom/src/memio.h | 38 + games/NXDoom/src/midifallback.c | 370 + games/NXDoom/src/midifallback.h | 47 + games/NXDoom/src/midifile.c | 838 + games/NXDoom/src/midifile.h | 232 + games/NXDoom/src/mus2mid.c | 736 + games/NXDoom/src/mus2mid.h | 29 + games/NXDoom/src/net_client.c | 1229 ++ games/NXDoom/src/net_client.h | 53 + games/NXDoom/src/net_common.c | 527 + games/NXDoom/src/net_common.h | 106 + games/NXDoom/src/net_dedicated.c | 80 + games/NXDoom/src/net_dedicated.h | 25 + games/NXDoom/src/net_defs.h | 276 + games/NXDoom/src/net_gui.c | 434 + games/NXDoom/src/net_gui.h | 29 + games/NXDoom/src/net_io.c | 147 + games/NXDoom/src/net_io.h | 61 + games/NXDoom/src/net_loop.c | 231 + games/NXDoom/src/net_loop.h | 27 + games/NXDoom/src/net_packet.c | 328 + games/NXDoom/src/net_packet.h | 45 + games/NXDoom/src/net_petname.c | 118 + games/NXDoom/src/net_petname.h | 18 + games/NXDoom/src/net_query.c | 1006 ++ games/NXDoom/src/net_query.h | 45 + games/NXDoom/src/net_sdl.c | 441 + games/NXDoom/src/net_sdl.h | 26 + games/NXDoom/src/net_server.c | 2097 +++ games/NXDoom/src/net_server.h | 42 + games/NXDoom/src/net_structrw.c | 676 + games/NXDoom/src/net_structrw.h | 55 + games/NXDoom/src/p_rejectpad.c | 81 + games/NXDoom/src/p_rejectpad.h | 28 + games/NXDoom/src/setup-res.rc.in | 28 + games/NXDoom/src/setup/.gitignore | 7 + games/NXDoom/src/setup/CMakeLists.txt | 32 + games/NXDoom/src/setup/Makefile.am | 42 + games/NXDoom/src/setup/Setup.desktop.in | 8 + games/NXDoom/src/setup/compatibility.c | 51 + games/NXDoom/src/setup/compatibility.h | 24 + games/NXDoom/src/setup/display.c | 289 + games/NXDoom/src/setup/display.h | 26 + games/NXDoom/src/setup/execute.c | 429 + games/NXDoom/src/setup/execute.h | 40 + games/NXDoom/src/setup/joystick.c | 1365 ++ games/NXDoom/src/setup/joystick.h | 32 + games/NXDoom/src/setup/keyboard.c | 448 + games/NXDoom/src/setup/keyboard.h | 23 + games/NXDoom/src/setup/mainmenu.c | 346 + games/NXDoom/src/setup/mode.c | 384 + games/NXDoom/src/setup/mode.h | 31 + games/NXDoom/src/setup/mouse.c | 176 + games/NXDoom/src/setup/mouse.h | 23 + games/NXDoom/src/setup/multiplayer.c | 1191 ++ games/NXDoom/src/setup/multiplayer.h | 29 + games/NXDoom/src/setup/setup-manifest.xml.in | 48 + games/NXDoom/src/setup/setup_icon.c | 2736 ++++ games/NXDoom/src/setup/sound.c | 410 + games/NXDoom/src/setup/sound.h | 24 + games/NXDoom/src/setup/txt_joyaxis.c | 654 + games/NXDoom/src/setup/txt_joyaxis.h | 90 + games/NXDoom/src/setup/txt_joybinput.c | 780 + games/NXDoom/src/setup/txt_joybinput.h | 40 + games/NXDoom/src/setup/txt_keyinput.c | 185 + games/NXDoom/src/setup/txt_keyinput.h | 38 + games/NXDoom/src/setup/txt_mouseinput.c | 184 + games/NXDoom/src/setup/txt_mouseinput.h | 38 + games/NXDoom/src/sha1.c | 321 + games/NXDoom/src/sha1.h | 40 + games/NXDoom/src/strife-res.rc.in | 30 + games/NXDoom/src/strife/.gitignore | 5 + games/NXDoom/src/strife/CMakeLists.txt | 92 + games/NXDoom/src/strife/Makefile.am | 85 + games/NXDoom/src/strife/am_map.c | 1415 ++ games/NXDoom/src/strife/am_map.h | 49 + games/NXDoom/src/strife/d_englsh.h | 593 + games/NXDoom/src/strife/d_items.c | 159 + games/NXDoom/src/strife/d_items.h | 42 + games/NXDoom/src/strife/d_main.c | 2191 +++ games/NXDoom/src/strife/d_main.h | 64 + games/NXDoom/src/strife/d_net.c | 290 + games/NXDoom/src/strife/d_player.h | 249 + games/NXDoom/src/strife/d_textur.h | 43 + games/NXDoom/src/strife/d_think.h | 68 + games/NXDoom/src/strife/deh_ammo.c | 103 + games/NXDoom/src/strife/deh_cheat.c | 148 + games/NXDoom/src/strife/deh_frame.c | 159 + games/NXDoom/src/strife/deh_misc.c | 228 + games/NXDoom/src/strife/deh_misc.h | 79 + games/NXDoom/src/strife/deh_ptr.c | 142 + games/NXDoom/src/strife/deh_sound.c | 102 + games/NXDoom/src/strife/deh_strife.c | 47 + games/NXDoom/src/strife/deh_thing.c | 132 + games/NXDoom/src/strife/deh_weapon.c | 102 + games/NXDoom/src/strife/doomdata.h | 225 + games/NXDoom/src/strife/doomdef.c | 28 + games/NXDoom/src/strife/doomdef.h | 291 + games/NXDoom/src/strife/doomstat.c | 35 + games/NXDoom/src/strife/doomstat.h | 281 + games/NXDoom/src/strife/dstrings.c | 73 + games/NXDoom/src/strife/dstrings.h | 41 + games/NXDoom/src/strife/f_finale.c | 1047 ++ games/NXDoom/src/strife/f_finale.h | 48 + games/NXDoom/src/strife/f_wipe.c | 292 + games/NXDoom/src/strife/f_wipe.h | 63 + games/NXDoom/src/strife/g_game.c | 2534 +++ games/NXDoom/src/strife/g_game.h | 89 + games/NXDoom/src/strife/hu_lib.c | 474 + games/NXDoom/src/strife/hu_lib.h | 185 + games/NXDoom/src/strife/hu_stuff.c | 687 + games/NXDoom/src/strife/hu_stuff.h | 75 + games/NXDoom/src/strife/info.c | 11041 +++++++++++++ games/NXDoom/src/strife/info.h | 2219 +++ games/NXDoom/src/strife/m_menu.c | 2466 +++ games/NXDoom/src/strife/m_menu.h | 104 + games/NXDoom/src/strife/m_random.c | 80 + games/NXDoom/src/strife/m_random.h | 39 + games/NXDoom/src/strife/m_saves.c | 482 + games/NXDoom/src/strife/m_saves.h | 55 + games/NXDoom/src/strife/p_ceilng.c | 343 + games/NXDoom/src/strife/p_dialog.c | 1413 ++ games/NXDoom/src/strife/p_dialog.h | 102 + games/NXDoom/src/strife/p_doors.c | 1370 ++ games/NXDoom/src/strife/p_enemy.c | 3388 ++++ games/NXDoom/src/strife/p_floor.c | 597 + games/NXDoom/src/strife/p_inter.c | 1411 ++ games/NXDoom/src/strife/p_inter.h | 32 + games/NXDoom/src/strife/p_lights.c | 372 + games/NXDoom/src/strife/p_local.h | 311 + games/NXDoom/src/strife/p_map.c | 1643 ++ games/NXDoom/src/strife/p_maputl.c | 1056 ++ games/NXDoom/src/strife/p_mobj.c | 1360 ++ games/NXDoom/src/strife/p_mobj.h | 330 + games/NXDoom/src/strife/p_plats.c | 358 + games/NXDoom/src/strife/p_pspr.c | 1003 ++ games/NXDoom/src/strife/p_pspr.h | 86 + games/NXDoom/src/strife/p_saveg.c | 2208 +++ games/NXDoom/src/strife/p_saveg.h | 62 + games/NXDoom/src/strife/p_setup.c | 808 + games/NXDoom/src/strife/p_setup.h | 37 + games/NXDoom/src/strife/p_sight.c | 360 + games/NXDoom/src/strife/p_spec.c | 1984 +++ games/NXDoom/src/strife/p_spec.h | 678 + games/NXDoom/src/strife/p_switch.c | 1078 ++ games/NXDoom/src/strife/p_telept.c | 151 + games/NXDoom/src/strife/p_tick.c | 160 + games/NXDoom/src/strife/p_tick.h | 33 + games/NXDoom/src/strife/p_user.c | 920 ++ games/NXDoom/src/strife/r_bsp.c | 583 + games/NXDoom/src/strife/r_bsp.h | 61 + games/NXDoom/src/strife/r_data.c | 1010 ++ games/NXDoom/src/strife/r_data.h | 56 + games/NXDoom/src/strife/r_defs.h | 448 + games/NXDoom/src/strife/r_draw.c | 968 ++ games/NXDoom/src/strife/r_draw.h | 111 + games/NXDoom/src/strife/r_local.h | 45 + games/NXDoom/src/strife/r_main.c | 944 ++ games/NXDoom/src/strife/r_main.h | 164 + games/NXDoom/src/strife/r_plane.c | 447 + games/NXDoom/src/strife/r_plane.h | 76 + games/NXDoom/src/strife/r_segs.c | 754 + games/NXDoom/src/strife/r_segs.h | 34 + games/NXDoom/src/strife/r_sky.c | 54 + games/NXDoom/src/strife/r_sky.h | 37 + games/NXDoom/src/strife/r_state.h | 127 + games/NXDoom/src/strife/r_things.c | 1067 ++ games/NXDoom/src/strife/r_things.h | 66 + games/NXDoom/src/strife/s_sound.c | 825 + games/NXDoom/src/strife/s_sound.h | 95 + games/NXDoom/src/strife/sounds.c | 227 + games/NXDoom/src/strife/sounds.h | 222 + games/NXDoom/src/strife/st_lib.c | 326 + games/NXDoom/src/strife/st_lib.h | 221 + games/NXDoom/src/strife/st_stuff.c | 1605 ++ games/NXDoom/src/strife/st_stuff.h | 80 + games/NXDoom/src/strife/strife_icon.c | 2736 ++++ games/NXDoom/src/strife/wi_stuff.c | 1836 +++ games/NXDoom/src/strife/wi_stuff.h | 51 + games/NXDoom/src/tables.c | 2227 +++ games/NXDoom/src/tables.h | 96 + games/NXDoom/src/v_diskicon.c | 160 + games/NXDoom/src/v_diskicon.h | 32 + games/NXDoom/src/v_patch.h | 50 + games/NXDoom/src/v_video.c | 1023 ++ games/NXDoom/src/v_video.h | 108 + games/NXDoom/src/w_checksum.c | 88 + games/NXDoom/src/w_checksum.h | 27 + games/NXDoom/src/w_file.c | 84 + games/NXDoom/src/w_file.h | 86 + games/NXDoom/src/w_file_posix.c | 176 + games/NXDoom/src/w_file_stdc.c | 96 + games/NXDoom/src/w_file_win32.c | 204 + games/NXDoom/src/w_main.c | 268 + games/NXDoom/src/w_main.h | 30 + games/NXDoom/src/w_merge.c | 722 + games/NXDoom/src/w_merge.h | 44 + games/NXDoom/src/w_wad.c | 629 + games/NXDoom/src/w_wad.h | 78 + games/NXDoom/src/z_native.c | 506 + games/NXDoom/src/z_zone.c | 552 + games/NXDoom/src/z_zone.h | 73 + games/NXDoom/textscreen/.gitignore | 6 + games/NXDoom/textscreen/CMakeLists.txt | 33 + games/NXDoom/textscreen/Doxyfile | 2451 +++ games/NXDoom/textscreen/Makefile.am | 41 + games/NXDoom/textscreen/examples/.gitignore | 8 + games/NXDoom/textscreen/examples/Makefile.am | 11 + games/NXDoom/textscreen/examples/calculator.c | 180 + games/NXDoom/textscreen/examples/guitest.c | 308 + games/NXDoom/textscreen/fonts/Makefile.am | 18 + games/NXDoom/textscreen/fonts/README | 38 + games/NXDoom/textscreen/fonts/codepage.h | 113 + games/NXDoom/textscreen/fonts/convert-font | 104 + games/NXDoom/textscreen/fonts/large.h | 2060 +++ games/NXDoom/textscreen/fonts/large.png | Bin 0 -> 7837 bytes games/NXDoom/textscreen/fonts/normal.h | 524 + games/NXDoom/textscreen/fonts/normal.png | Bin 0 -> 3783 bytes games/NXDoom/textscreen/fonts/small.h | 140 + games/NXDoom/textscreen/fonts/small.png | Bin 0 -> 1750 bytes games/NXDoom/textscreen/textscreen.h | 48 + games/NXDoom/textscreen/txt_button.c | 127 + games/NXDoom/textscreen/txt_button.h | 74 + games/NXDoom/textscreen/txt_checkbox.c | 142 + games/NXDoom/textscreen/txt_checkbox.h | 76 + games/NXDoom/textscreen/txt_conditional.c | 168 + games/NXDoom/textscreen/txt_conditional.h | 63 + games/NXDoom/textscreen/txt_desktop.c | 386 + games/NXDoom/textscreen/txt_desktop.h | 108 + games/NXDoom/textscreen/txt_dropdown.c | 305 + games/NXDoom/textscreen/txt_dropdown.h | 69 + games/NXDoom/textscreen/txt_fileselect.c | 836 + games/NXDoom/textscreen/txt_fileselect.h | 79 + games/NXDoom/textscreen/txt_gui.c | 480 + games/NXDoom/textscreen/txt_gui.h | 40 + games/NXDoom/textscreen/txt_inputbox.c | 347 + games/NXDoom/textscreen/txt_inputbox.h | 76 + games/NXDoom/textscreen/txt_io.c | 176 + games/NXDoom/textscreen/txt_io.h | 41 + games/NXDoom/textscreen/txt_label.c | 200 + games/NXDoom/textscreen/txt_label.h | 83 + games/NXDoom/textscreen/txt_main.h | 203 + games/NXDoom/textscreen/txt_radiobutton.c | 143 + games/NXDoom/textscreen/txt_radiobutton.h | 79 + games/NXDoom/textscreen/txt_scrollpane.c | 586 + games/NXDoom/textscreen/txt_scrollpane.h | 59 + games/NXDoom/textscreen/txt_sdl.c | 990 ++ games/NXDoom/textscreen/txt_sdl.h | 45 + games/NXDoom/textscreen/txt_separator.c | 114 + games/NXDoom/textscreen/txt_separator.h | 65 + games/NXDoom/textscreen/txt_spinctrl.c | 426 + games/NXDoom/textscreen/txt_spinctrl.h | 78 + games/NXDoom/textscreen/txt_strut.c | 72 + games/NXDoom/textscreen/txt_strut.h | 54 + games/NXDoom/textscreen/txt_table.c | 1244 ++ games/NXDoom/textscreen/txt_table.h | 245 + games/NXDoom/textscreen/txt_utf8.c | 154 + games/NXDoom/textscreen/txt_utf8.h | 26 + games/NXDoom/textscreen/txt_widget.c | 326 + games/NXDoom/textscreen/txt_widget.h | 179 + games/NXDoom/textscreen/txt_window.c | 596 + games/NXDoom/textscreen/txt_window.h | 221 + games/NXDoom/textscreen/txt_window_action.c | 169 + games/NXDoom/textscreen/txt_window_action.h | 89 + games/NXDoom/vcpkg.json | 10 + games/NXDoom/win32/win_opendir.c | 360 + games/NXDoom/win32/win_opendir.h | 110 + 728 files changed, 332623 insertions(+) create mode 100644 games/NXDoom/.devcontainer/.gitignore create mode 100644 games/NXDoom/.devcontainer/Dockerfile create mode 100644 games/NXDoom/.devcontainer/devcontainer.json create mode 100755 games/NXDoom/.devcontainer/initialize-linux.sh create mode 100644 games/NXDoom/.github/CONTRIBUTING.md create mode 100644 games/NXDoom/.github/ISSUE_TEMPLATE.md create mode 100644 games/NXDoom/.github/workflows/cpp-linter.yml create mode 100644 games/NXDoom/.github/workflows/cppcheck.yml create mode 100644 games/NXDoom/.github/workflows/main.yml create mode 100644 games/NXDoom/.gitignore create mode 100644 games/NXDoom/.gitmodules create mode 100644 games/NXDoom/.lvimrc create mode 100755 games/NXDoom/.travis.sh create mode 100644 games/NXDoom/AUTHORS create mode 100644 games/NXDoom/CMakeLists.txt create mode 100644 games/NXDoom/CODE_OF_CONDUCT.md create mode 100644 games/NXDoom/COPYING.md create mode 100644 games/NXDoom/ChangeLog create mode 100644 games/NXDoom/HACKING.md create mode 100644 games/NXDoom/Makefile.am create mode 100644 games/NXDoom/NEWS.md create mode 100644 games/NXDoom/NOT-BUGS.md create mode 100644 games/NXDoom/PHILOSOPHY.md create mode 100644 games/NXDoom/README.Music.md create mode 100644 games/NXDoom/README.Strife.md create mode 100644 games/NXDoom/README.md create mode 100644 games/NXDoom/RELEASE_NOTES.md create mode 100644 games/NXDoom/TODO.md create mode 100755 games/NXDoom/autogen.sh create mode 100755 games/NXDoom/check-extern.sh create mode 100644 games/NXDoom/cmake/FindFluidSynth.cmake create mode 100644 games/NXDoom/cmake/FindSDL2.cmake create mode 100644 games/NXDoom/cmake/FindSDL2_mixer.cmake create mode 100644 games/NXDoom/cmake/FindSDL2_net.cmake create mode 100644 games/NXDoom/cmake/FindSampleRate.cmake create mode 100644 games/NXDoom/cmake/Findm.cmake create mode 100644 games/NXDoom/cmake/config.h.cin create mode 100644 games/NXDoom/configure.ac create mode 100644 games/NXDoom/data/.gitignore create mode 100644 games/NXDoom/data/Makefile.am create mode 100644 games/NXDoom/data/README create mode 100755 games/NXDoom/data/convert-icon create mode 100644 games/NXDoom/data/doom.ico create mode 100644 games/NXDoom/data/doom.png create mode 100644 games/NXDoom/data/heretic.ico create mode 100644 games/NXDoom/data/heretic.png create mode 100644 games/NXDoom/data/hexen.ico create mode 100644 games/NXDoom/data/hexen.png create mode 100644 games/NXDoom/data/setup.ico create mode 100644 games/NXDoom/data/setup.png create mode 100644 games/NXDoom/data/strife.ico create mode 100644 games/NXDoom/data/strife.png create mode 100644 games/NXDoom/data/wadfile.png create mode 100644 games/NXDoom/man/.gitignore create mode 100644 games/NXDoom/man/CMDLINE.template create mode 100644 games/NXDoom/man/CMDLINE.template.md create mode 100644 games/NXDoom/man/INSTALL.template create mode 100644 games/NXDoom/man/Makefile.am create mode 100644 games/NXDoom/man/bash-completion/.gitignore create mode 100644 games/NXDoom/man/bash-completion/Makefile.am create mode 100644 games/NXDoom/man/bash-completion/doom.template.in create mode 100644 games/NXDoom/man/bash-completion/heretic.template.in create mode 100644 games/NXDoom/man/bash-completion/hexen.template.in create mode 100644 games/NXDoom/man/bash-completion/strife.template.in create mode 100644 games/NXDoom/man/default.cfg.template create mode 100755 games/NXDoom/man/docgen create mode 100644 games/NXDoom/man/doom.template create mode 100644 games/NXDoom/man/environ.man create mode 100644 games/NXDoom/man/extra.cfg.template create mode 100644 games/NXDoom/man/heretic.template create mode 100644 games/NXDoom/man/hexen.template create mode 100644 games/NXDoom/man/iwad_paths.man create mode 100644 games/NXDoom/man/server.template create mode 100644 games/NXDoom/man/setup.template create mode 100755 games/NXDoom/man/simplecpp create mode 100644 games/NXDoom/man/strife.template create mode 100644 games/NXDoom/man/wikipages create mode 100644 games/NXDoom/opl/.gitignore create mode 100644 games/NXDoom/opl/CMakeLists.txt create mode 100644 games/NXDoom/opl/Makefile.am create mode 100644 games/NXDoom/opl/examples/.gitignore create mode 100644 games/NXDoom/opl/examples/Makefile.am create mode 100644 games/NXDoom/opl/examples/droplay.c create mode 100644 games/NXDoom/opl/ioperm_sys.c create mode 100644 games/NXDoom/opl/ioperm_sys.h create mode 100644 games/NXDoom/opl/opl.c create mode 100644 games/NXDoom/opl/opl.h create mode 100644 games/NXDoom/opl/opl3.c create mode 100644 games/NXDoom/opl/opl3.h create mode 100644 games/NXDoom/opl/opl_internal.h create mode 100644 games/NXDoom/opl/opl_linux.c create mode 100644 games/NXDoom/opl/opl_obsd.c create mode 100644 games/NXDoom/opl/opl_queue.c create mode 100644 games/NXDoom/opl/opl_queue.h create mode 100644 games/NXDoom/opl/opl_sdl.c create mode 100644 games/NXDoom/opl/opl_timer.c create mode 100644 games/NXDoom/opl/opl_timer.h create mode 100644 games/NXDoom/opl/opl_win32.c create mode 100644 games/NXDoom/pcsound/.gitignore create mode 100644 games/NXDoom/pcsound/CMakeLists.txt create mode 100644 games/NXDoom/pcsound/Makefile.am create mode 100644 games/NXDoom/pcsound/pcsound.c create mode 100644 games/NXDoom/pcsound/pcsound.h create mode 100644 games/NXDoom/pcsound/pcsound_bsd.c create mode 100644 games/NXDoom/pcsound/pcsound_internal.h create mode 100644 games/NXDoom/pcsound/pcsound_linux.c create mode 100644 games/NXDoom/pcsound/pcsound_sdl.c create mode 100644 games/NXDoom/pcsound/pcsound_win32.c create mode 100644 games/NXDoom/pkg/.gitignore create mode 100644 games/NXDoom/pkg/Makefile.am create mode 100644 games/NXDoom/pkg/config.make.in create mode 100644 games/NXDoom/pkg/osx/.gitignore create mode 100644 games/NXDoom/pkg/osx/AppController.h create mode 100644 games/NXDoom/pkg/osx/AppController.m create mode 100644 games/NXDoom/pkg/osx/Execute.h create mode 100644 games/NXDoom/pkg/osx/Execute.m create mode 100644 games/NXDoom/pkg/osx/GNUmakefile create mode 100644 games/NXDoom/pkg/osx/IWADController.h create mode 100644 games/NXDoom/pkg/osx/IWADController.m create mode 100644 games/NXDoom/pkg/osx/Info.plist.in create mode 100644 games/NXDoom/pkg/osx/LauncherManager.h create mode 100644 games/NXDoom/pkg/osx/LauncherManager.m create mode 100644 games/NXDoom/pkg/osx/PkgInfo create mode 100644 games/NXDoom/pkg/osx/Resources/app.png create mode 100644 games/NXDoom/pkg/osx/Resources/launcher.nib/designable.nib create mode 100644 games/NXDoom/pkg/osx/Resources/launcher.nib/keyedobjects.nib create mode 100755 games/NXDoom/pkg/osx/cp-with-libs create mode 100644 games/NXDoom/pkg/osx/disk/background.png create mode 100644 games/NXDoom/pkg/osx/disk/dir.DS_Store create mode 100755 games/NXDoom/pkg/osx/dmgfix create mode 100644 games/NXDoom/pkg/osx/main.m create mode 100644 games/NXDoom/pkg/style.html create mode 100644 games/NXDoom/pkg/win32/.gitignore create mode 100644 games/NXDoom/pkg/win32/GNUmakefile create mode 100644 games/NXDoom/pkg/win32/README create mode 100755 games/NXDoom/pkg/win32/cp-with-libs create mode 100644 games/NXDoom/rpm.spec.in create mode 100644 games/NXDoom/src/.gitignore create mode 100644 games/NXDoom/src/CMakeLists.txt create mode 100644 games/NXDoom/src/Doom.desktop.in create mode 100644 games/NXDoom/src/Doom.metainfo.xml.in create mode 100644 games/NXDoom/src/Doom_Screensaver.desktop.in create mode 100644 games/NXDoom/src/Heretic.desktop.in create mode 100644 games/NXDoom/src/Heretic.metainfo.xml.in create mode 100644 games/NXDoom/src/Hexen.desktop.in create mode 100644 games/NXDoom/src/Hexen.metainfo.xml.in create mode 100644 games/NXDoom/src/Makefile.am create mode 100644 games/NXDoom/src/Strife.desktop.in create mode 100644 games/NXDoom/src/Strife.metainfo.xml.in create mode 100644 games/NXDoom/src/aes_prng.c create mode 100644 games/NXDoom/src/aes_prng.h create mode 100644 games/NXDoom/src/d_dedicated.c create mode 100644 games/NXDoom/src/d_event.c create mode 100644 games/NXDoom/src/d_event.h create mode 100644 games/NXDoom/src/d_iwad.c create mode 100644 games/NXDoom/src/d_iwad.h create mode 100644 games/NXDoom/src/d_loop.c create mode 100644 games/NXDoom/src/d_loop.h create mode 100644 games/NXDoom/src/d_mode.c create mode 100644 games/NXDoom/src/d_mode.h create mode 100644 games/NXDoom/src/d_ticcmd.h create mode 100644 games/NXDoom/src/deh_defs.h create mode 100644 games/NXDoom/src/deh_io.c create mode 100644 games/NXDoom/src/deh_io.h create mode 100644 games/NXDoom/src/deh_main.c create mode 100644 games/NXDoom/src/deh_main.h create mode 100644 games/NXDoom/src/deh_mapping.c create mode 100644 games/NXDoom/src/deh_mapping.h create mode 100644 games/NXDoom/src/deh_str.c create mode 100644 games/NXDoom/src/deh_str.h create mode 100644 games/NXDoom/src/deh_text.c create mode 100644 games/NXDoom/src/doom-res.rc.in create mode 100644 games/NXDoom/src/doom/.gitignore create mode 100644 games/NXDoom/src/doom/CMakeLists.txt create mode 100644 games/NXDoom/src/doom/Makefile.am create mode 100644 games/NXDoom/src/doom/am_map.c create mode 100644 games/NXDoom/src/doom/am_map.h create mode 100644 games/NXDoom/src/doom/d_englsh.h create mode 100644 games/NXDoom/src/doom/d_items.c create mode 100644 games/NXDoom/src/doom/d_items.h create mode 100644 games/NXDoom/src/doom/d_main.c create mode 100644 games/NXDoom/src/doom/d_main.h create mode 100644 games/NXDoom/src/doom/d_net.c create mode 100644 games/NXDoom/src/doom/d_player.h create mode 100644 games/NXDoom/src/doom/d_textur.h create mode 100644 games/NXDoom/src/doom/d_think.h create mode 100644 games/NXDoom/src/doom/deh_ammo.c create mode 100644 games/NXDoom/src/doom/deh_bexstr.c create mode 100644 games/NXDoom/src/doom/deh_cheat.c create mode 100644 games/NXDoom/src/doom/deh_doom.c create mode 100644 games/NXDoom/src/doom/deh_frame.c create mode 100644 games/NXDoom/src/doom/deh_misc.c create mode 100644 games/NXDoom/src/doom/deh_misc.h create mode 100644 games/NXDoom/src/doom/deh_ptr.c create mode 100644 games/NXDoom/src/doom/deh_sound.c create mode 100644 games/NXDoom/src/doom/deh_thing.c create mode 100644 games/NXDoom/src/doom/deh_weapon.c create mode 100644 games/NXDoom/src/doom/doom_icon.c create mode 100644 games/NXDoom/src/doom/doomdata.h create mode 100644 games/NXDoom/src/doom/doomdef.c create mode 100644 games/NXDoom/src/doom/doomdef.h create mode 100644 games/NXDoom/src/doom/doomstat.c create mode 100644 games/NXDoom/src/doom/doomstat.h create mode 100644 games/NXDoom/src/doom/dstrings.c create mode 100644 games/NXDoom/src/doom/dstrings.h create mode 100644 games/NXDoom/src/doom/f_finale.c create mode 100644 games/NXDoom/src/doom/f_finale.h create mode 100644 games/NXDoom/src/doom/f_wipe.c create mode 100644 games/NXDoom/src/doom/f_wipe.h create mode 100644 games/NXDoom/src/doom/g_game.c create mode 100644 games/NXDoom/src/doom/g_game.h create mode 100644 games/NXDoom/src/doom/hu_lib.c create mode 100644 games/NXDoom/src/doom/hu_lib.h create mode 100644 games/NXDoom/src/doom/hu_stuff.c create mode 100644 games/NXDoom/src/doom/hu_stuff.h create mode 100644 games/NXDoom/src/doom/info.c create mode 100644 games/NXDoom/src/doom/info.h create mode 100644 games/NXDoom/src/doom/m_menu.c create mode 100644 games/NXDoom/src/doom/m_menu.h create mode 100644 games/NXDoom/src/doom/m_random.c create mode 100644 games/NXDoom/src/doom/m_random.h create mode 100644 games/NXDoom/src/doom/p_ceilng.c create mode 100644 games/NXDoom/src/doom/p_doors.c create mode 100644 games/NXDoom/src/doom/p_enemy.c create mode 100644 games/NXDoom/src/doom/p_floor.c create mode 100644 games/NXDoom/src/doom/p_inter.c create mode 100644 games/NXDoom/src/doom/p_inter.h create mode 100644 games/NXDoom/src/doom/p_lights.c create mode 100644 games/NXDoom/src/doom/p_local.h create mode 100644 games/NXDoom/src/doom/p_map.c create mode 100644 games/NXDoom/src/doom/p_maputl.c create mode 100644 games/NXDoom/src/doom/p_mobj.c create mode 100644 games/NXDoom/src/doom/p_mobj.h create mode 100644 games/NXDoom/src/doom/p_plats.c create mode 100644 games/NXDoom/src/doom/p_pspr.c create mode 100644 games/NXDoom/src/doom/p_pspr.h create mode 100644 games/NXDoom/src/doom/p_saveg.c create mode 100644 games/NXDoom/src/doom/p_saveg.h create mode 100644 games/NXDoom/src/doom/p_setup.c create mode 100644 games/NXDoom/src/doom/p_setup.h create mode 100644 games/NXDoom/src/doom/p_sight.c create mode 100644 games/NXDoom/src/doom/p_spec.c create mode 100644 games/NXDoom/src/doom/p_spec.h create mode 100644 games/NXDoom/src/doom/p_switch.c create mode 100644 games/NXDoom/src/doom/p_telept.c create mode 100644 games/NXDoom/src/doom/p_tick.c create mode 100644 games/NXDoom/src/doom/p_tick.h create mode 100644 games/NXDoom/src/doom/p_user.c create mode 100644 games/NXDoom/src/doom/r_bsp.c create mode 100644 games/NXDoom/src/doom/r_bsp.h create mode 100644 games/NXDoom/src/doom/r_data.c create mode 100644 games/NXDoom/src/doom/r_data.h create mode 100644 games/NXDoom/src/doom/r_defs.h create mode 100644 games/NXDoom/src/doom/r_draw.c create mode 100644 games/NXDoom/src/doom/r_draw.h create mode 100644 games/NXDoom/src/doom/r_local.h create mode 100644 games/NXDoom/src/doom/r_main.c create mode 100644 games/NXDoom/src/doom/r_main.h create mode 100644 games/NXDoom/src/doom/r_plane.c create mode 100644 games/NXDoom/src/doom/r_plane.h create mode 100644 games/NXDoom/src/doom/r_segs.c create mode 100644 games/NXDoom/src/doom/r_segs.h create mode 100644 games/NXDoom/src/doom/r_sky.c create mode 100644 games/NXDoom/src/doom/r_sky.h create mode 100644 games/NXDoom/src/doom/r_state.h create mode 100644 games/NXDoom/src/doom/r_things.c create mode 100644 games/NXDoom/src/doom/r_things.h create mode 100644 games/NXDoom/src/doom/s_sound.c create mode 100644 games/NXDoom/src/doom/s_sound.h create mode 100644 games/NXDoom/src/doom/sounds.c create mode 100644 games/NXDoom/src/doom/sounds.h create mode 100644 games/NXDoom/src/doom/st_lib.c create mode 100644 games/NXDoom/src/doom/st_lib.h create mode 100644 games/NXDoom/src/doom/st_stuff.c create mode 100644 games/NXDoom/src/doom/st_stuff.h create mode 100644 games/NXDoom/src/doom/statdump.c create mode 100644 games/NXDoom/src/doom/statdump.h create mode 100644 games/NXDoom/src/doom/wi_stuff.c create mode 100644 games/NXDoom/src/doom/wi_stuff.h create mode 100644 games/NXDoom/src/doomkeys.h create mode 100644 games/NXDoom/src/doomtype.h create mode 100644 games/NXDoom/src/gusconf.c create mode 100644 games/NXDoom/src/gusconf.h create mode 100644 games/NXDoom/src/heretic-res.rc.in create mode 100644 games/NXDoom/src/heretic/.gitignore create mode 100644 games/NXDoom/src/heretic/CMakeLists.txt create mode 100644 games/NXDoom/src/heretic/Makefile.am create mode 100644 games/NXDoom/src/heretic/am_data.h create mode 100644 games/NXDoom/src/heretic/am_map.c create mode 100644 games/NXDoom/src/heretic/am_map.h create mode 100644 games/NXDoom/src/heretic/ct_chat.c create mode 100644 games/NXDoom/src/heretic/ct_chat.h create mode 100644 games/NXDoom/src/heretic/d_main.c create mode 100644 games/NXDoom/src/heretic/d_net.c create mode 100644 games/NXDoom/src/heretic/deh_ammo.c create mode 100644 games/NXDoom/src/heretic/deh_frame.c create mode 100644 games/NXDoom/src/heretic/deh_htext.c create mode 100644 games/NXDoom/src/heretic/deh_htic.c create mode 100644 games/NXDoom/src/heretic/deh_htic.h create mode 100644 games/NXDoom/src/heretic/deh_sound.c create mode 100644 games/NXDoom/src/heretic/deh_thing.c create mode 100644 games/NXDoom/src/heretic/deh_weapon.c create mode 100644 games/NXDoom/src/heretic/doomdata.h create mode 100644 games/NXDoom/src/heretic/doomdef.h create mode 100644 games/NXDoom/src/heretic/dstrings.h create mode 100644 games/NXDoom/src/heretic/f_finale.c create mode 100644 games/NXDoom/src/heretic/g_game.c create mode 100644 games/NXDoom/src/heretic/heretic_icon.c create mode 100644 games/NXDoom/src/heretic/in_lude.c create mode 100644 games/NXDoom/src/heretic/info.c create mode 100644 games/NXDoom/src/heretic/info.h create mode 100644 games/NXDoom/src/heretic/m_random.c create mode 100644 games/NXDoom/src/heretic/m_random.h create mode 100644 games/NXDoom/src/heretic/mn_menu.c create mode 100644 games/NXDoom/src/heretic/p_action.h create mode 100644 games/NXDoom/src/heretic/p_ceilng.c create mode 100644 games/NXDoom/src/heretic/p_doors.c create mode 100644 games/NXDoom/src/heretic/p_enemy.c create mode 100644 games/NXDoom/src/heretic/p_floor.c create mode 100644 games/NXDoom/src/heretic/p_inter.c create mode 100644 games/NXDoom/src/heretic/p_lights.c create mode 100644 games/NXDoom/src/heretic/p_local.h create mode 100644 games/NXDoom/src/heretic/p_map.c create mode 100644 games/NXDoom/src/heretic/p_maputl.c create mode 100644 games/NXDoom/src/heretic/p_mobj.c create mode 100644 games/NXDoom/src/heretic/p_plats.c create mode 100644 games/NXDoom/src/heretic/p_pspr.c create mode 100644 games/NXDoom/src/heretic/p_saveg.c create mode 100644 games/NXDoom/src/heretic/p_setup.c create mode 100644 games/NXDoom/src/heretic/p_sight.c create mode 100644 games/NXDoom/src/heretic/p_spec.c create mode 100644 games/NXDoom/src/heretic/p_spec.h create mode 100644 games/NXDoom/src/heretic/p_switch.c create mode 100644 games/NXDoom/src/heretic/p_telept.c create mode 100644 games/NXDoom/src/heretic/p_tick.c create mode 100644 games/NXDoom/src/heretic/p_user.c create mode 100644 games/NXDoom/src/heretic/r_bsp.c create mode 100644 games/NXDoom/src/heretic/r_data.c create mode 100644 games/NXDoom/src/heretic/r_draw.c create mode 100644 games/NXDoom/src/heretic/r_local.h create mode 100644 games/NXDoom/src/heretic/r_main.c create mode 100644 games/NXDoom/src/heretic/r_plane.c create mode 100644 games/NXDoom/src/heretic/r_segs.c create mode 100644 games/NXDoom/src/heretic/r_things.c create mode 100644 games/NXDoom/src/heretic/s_sound.c create mode 100644 games/NXDoom/src/heretic/s_sound.h create mode 100644 games/NXDoom/src/heretic/sb_bar.c create mode 100644 games/NXDoom/src/heretic/sounds.c create mode 100644 games/NXDoom/src/heretic/sounds.h create mode 100644 games/NXDoom/src/hexen-res.rc.in create mode 100644 games/NXDoom/src/hexen/.gitignore create mode 100644 games/NXDoom/src/hexen/CMakeLists.txt create mode 100644 games/NXDoom/src/hexen/Makefile.am create mode 100644 games/NXDoom/src/hexen/a_action.c create mode 100644 games/NXDoom/src/hexen/am_data.h create mode 100644 games/NXDoom/src/hexen/am_map.c create mode 100644 games/NXDoom/src/hexen/am_map.h create mode 100644 games/NXDoom/src/hexen/ct_chat.c create mode 100644 games/NXDoom/src/hexen/ct_chat.h create mode 100644 games/NXDoom/src/hexen/d_net.c create mode 100644 games/NXDoom/src/hexen/f_finale.c create mode 100644 games/NXDoom/src/hexen/g_game.c create mode 100644 games/NXDoom/src/hexen/h2_main.c create mode 100644 games/NXDoom/src/hexen/h2def.h create mode 100644 games/NXDoom/src/hexen/hexen_icon.c create mode 100644 games/NXDoom/src/hexen/in_lude.c create mode 100644 games/NXDoom/src/hexen/info.c create mode 100644 games/NXDoom/src/hexen/info.h create mode 100644 games/NXDoom/src/hexen/m_random.c create mode 100644 games/NXDoom/src/hexen/m_random.h create mode 100644 games/NXDoom/src/hexen/mn_menu.c create mode 100644 games/NXDoom/src/hexen/p_acs.c create mode 100644 games/NXDoom/src/hexen/p_action.h create mode 100644 games/NXDoom/src/hexen/p_anim.c create mode 100644 games/NXDoom/src/hexen/p_ceilng.c create mode 100644 games/NXDoom/src/hexen/p_doors.c create mode 100644 games/NXDoom/src/hexen/p_enemy.c create mode 100644 games/NXDoom/src/hexen/p_floor.c create mode 100644 games/NXDoom/src/hexen/p_inter.c create mode 100644 games/NXDoom/src/hexen/p_lights.c create mode 100644 games/NXDoom/src/hexen/p_local.h create mode 100644 games/NXDoom/src/hexen/p_map.c create mode 100644 games/NXDoom/src/hexen/p_maputl.c create mode 100644 games/NXDoom/src/hexen/p_mobj.c create mode 100644 games/NXDoom/src/hexen/p_plats.c create mode 100644 games/NXDoom/src/hexen/p_pspr.c create mode 100644 games/NXDoom/src/hexen/p_setup.c create mode 100644 games/NXDoom/src/hexen/p_sight.c create mode 100644 games/NXDoom/src/hexen/p_spec.c create mode 100644 games/NXDoom/src/hexen/p_spec.h create mode 100644 games/NXDoom/src/hexen/p_switch.c create mode 100644 games/NXDoom/src/hexen/p_telept.c create mode 100644 games/NXDoom/src/hexen/p_things.c create mode 100644 games/NXDoom/src/hexen/p_tick.c create mode 100644 games/NXDoom/src/hexen/p_user.c create mode 100644 games/NXDoom/src/hexen/po_man.c create mode 100644 games/NXDoom/src/hexen/r_bsp.c create mode 100644 games/NXDoom/src/hexen/r_data.c create mode 100644 games/NXDoom/src/hexen/r_draw.c create mode 100644 games/NXDoom/src/hexen/r_local.h create mode 100644 games/NXDoom/src/hexen/r_main.c create mode 100644 games/NXDoom/src/hexen/r_plane.c create mode 100644 games/NXDoom/src/hexen/r_segs.c create mode 100644 games/NXDoom/src/hexen/r_things.c create mode 100644 games/NXDoom/src/hexen/s_sound.c create mode 100644 games/NXDoom/src/hexen/s_sound.h create mode 100644 games/NXDoom/src/hexen/sb_bar.c create mode 100644 games/NXDoom/src/hexen/sc_man.c create mode 100644 games/NXDoom/src/hexen/sn_sonix.c create mode 100644 games/NXDoom/src/hexen/sounds.c create mode 100644 games/NXDoom/src/hexen/sounds.h create mode 100644 games/NXDoom/src/hexen/st_start.c create mode 100644 games/NXDoom/src/hexen/st_start.h create mode 100644 games/NXDoom/src/hexen/sv_save.c create mode 100644 games/NXDoom/src/hexen/textdefs.h create mode 100644 games/NXDoom/src/hexen/xddefs.h create mode 100644 games/NXDoom/src/i_cdmus.c create mode 100644 games/NXDoom/src/i_cdmus.h create mode 100644 games/NXDoom/src/i_endoom.c create mode 100644 games/NXDoom/src/i_endoom.h create mode 100644 games/NXDoom/src/i_flmusic.c create mode 100644 games/NXDoom/src/i_glob.c create mode 100644 games/NXDoom/src/i_glob.h create mode 100644 games/NXDoom/src/i_input.c create mode 100644 games/NXDoom/src/i_input.h create mode 100644 games/NXDoom/src/i_joystick.c create mode 100644 games/NXDoom/src/i_joystick.h create mode 100644 games/NXDoom/src/i_main.c create mode 100644 games/NXDoom/src/i_musicpack.c create mode 100644 games/NXDoom/src/i_oplmusic.c create mode 100644 games/NXDoom/src/i_pcsound.c create mode 100644 games/NXDoom/src/i_sdlmusic.c create mode 100644 games/NXDoom/src/i_sdlsound.c create mode 100644 games/NXDoom/src/i_sound.c create mode 100644 games/NXDoom/src/i_sound.h create mode 100644 games/NXDoom/src/i_swap.h create mode 100644 games/NXDoom/src/i_system.c create mode 100644 games/NXDoom/src/i_system.h create mode 100644 games/NXDoom/src/i_timer.c create mode 100644 games/NXDoom/src/i_timer.h create mode 100644 games/NXDoom/src/i_video.c create mode 100644 games/NXDoom/src/i_video.h create mode 100644 games/NXDoom/src/i_videohr.c create mode 100644 games/NXDoom/src/i_videohr.h create mode 100644 games/NXDoom/src/i_winmusic.c create mode 100644 games/NXDoom/src/m_argv.c create mode 100644 games/NXDoom/src/m_argv.h create mode 100644 games/NXDoom/src/m_bbox.c create mode 100644 games/NXDoom/src/m_bbox.h create mode 100644 games/NXDoom/src/m_cheat.c create mode 100644 games/NXDoom/src/m_cheat.h create mode 100644 games/NXDoom/src/m_config.c create mode 100644 games/NXDoom/src/m_config.h create mode 100644 games/NXDoom/src/m_controls.c create mode 100644 games/NXDoom/src/m_controls.h create mode 100644 games/NXDoom/src/m_fixed.c create mode 100644 games/NXDoom/src/m_fixed.h create mode 100644 games/NXDoom/src/m_misc.c create mode 100644 games/NXDoom/src/m_misc.h create mode 100644 games/NXDoom/src/manifest.xml create mode 100644 games/NXDoom/src/memio.c create mode 100644 games/NXDoom/src/memio.h create mode 100644 games/NXDoom/src/midifallback.c create mode 100644 games/NXDoom/src/midifallback.h create mode 100644 games/NXDoom/src/midifile.c create mode 100644 games/NXDoom/src/midifile.h create mode 100644 games/NXDoom/src/mus2mid.c create mode 100644 games/NXDoom/src/mus2mid.h create mode 100644 games/NXDoom/src/net_client.c create mode 100644 games/NXDoom/src/net_client.h create mode 100644 games/NXDoom/src/net_common.c create mode 100644 games/NXDoom/src/net_common.h create mode 100644 games/NXDoom/src/net_dedicated.c create mode 100644 games/NXDoom/src/net_dedicated.h create mode 100644 games/NXDoom/src/net_defs.h create mode 100644 games/NXDoom/src/net_gui.c create mode 100644 games/NXDoom/src/net_gui.h create mode 100644 games/NXDoom/src/net_io.c create mode 100644 games/NXDoom/src/net_io.h create mode 100644 games/NXDoom/src/net_loop.c create mode 100644 games/NXDoom/src/net_loop.h create mode 100644 games/NXDoom/src/net_packet.c create mode 100644 games/NXDoom/src/net_packet.h create mode 100644 games/NXDoom/src/net_petname.c create mode 100644 games/NXDoom/src/net_petname.h create mode 100644 games/NXDoom/src/net_query.c create mode 100644 games/NXDoom/src/net_query.h create mode 100644 games/NXDoom/src/net_sdl.c create mode 100644 games/NXDoom/src/net_sdl.h create mode 100644 games/NXDoom/src/net_server.c create mode 100644 games/NXDoom/src/net_server.h create mode 100644 games/NXDoom/src/net_structrw.c create mode 100644 games/NXDoom/src/net_structrw.h create mode 100644 games/NXDoom/src/p_rejectpad.c create mode 100644 games/NXDoom/src/p_rejectpad.h create mode 100644 games/NXDoom/src/setup-res.rc.in create mode 100644 games/NXDoom/src/setup/.gitignore create mode 100644 games/NXDoom/src/setup/CMakeLists.txt create mode 100644 games/NXDoom/src/setup/Makefile.am create mode 100644 games/NXDoom/src/setup/Setup.desktop.in create mode 100644 games/NXDoom/src/setup/compatibility.c create mode 100644 games/NXDoom/src/setup/compatibility.h create mode 100644 games/NXDoom/src/setup/display.c create mode 100644 games/NXDoom/src/setup/display.h create mode 100644 games/NXDoom/src/setup/execute.c create mode 100644 games/NXDoom/src/setup/execute.h create mode 100644 games/NXDoom/src/setup/joystick.c create mode 100644 games/NXDoom/src/setup/joystick.h create mode 100644 games/NXDoom/src/setup/keyboard.c create mode 100644 games/NXDoom/src/setup/keyboard.h create mode 100644 games/NXDoom/src/setup/mainmenu.c create mode 100644 games/NXDoom/src/setup/mode.c create mode 100644 games/NXDoom/src/setup/mode.h create mode 100644 games/NXDoom/src/setup/mouse.c create mode 100644 games/NXDoom/src/setup/mouse.h create mode 100644 games/NXDoom/src/setup/multiplayer.c create mode 100644 games/NXDoom/src/setup/multiplayer.h create mode 100644 games/NXDoom/src/setup/setup-manifest.xml.in create mode 100644 games/NXDoom/src/setup/setup_icon.c create mode 100644 games/NXDoom/src/setup/sound.c create mode 100644 games/NXDoom/src/setup/sound.h create mode 100644 games/NXDoom/src/setup/txt_joyaxis.c create mode 100644 games/NXDoom/src/setup/txt_joyaxis.h create mode 100644 games/NXDoom/src/setup/txt_joybinput.c create mode 100644 games/NXDoom/src/setup/txt_joybinput.h create mode 100644 games/NXDoom/src/setup/txt_keyinput.c create mode 100644 games/NXDoom/src/setup/txt_keyinput.h create mode 100644 games/NXDoom/src/setup/txt_mouseinput.c create mode 100644 games/NXDoom/src/setup/txt_mouseinput.h create mode 100644 games/NXDoom/src/sha1.c create mode 100644 games/NXDoom/src/sha1.h create mode 100644 games/NXDoom/src/strife-res.rc.in create mode 100644 games/NXDoom/src/strife/.gitignore create mode 100644 games/NXDoom/src/strife/CMakeLists.txt create mode 100644 games/NXDoom/src/strife/Makefile.am create mode 100644 games/NXDoom/src/strife/am_map.c create mode 100644 games/NXDoom/src/strife/am_map.h create mode 100644 games/NXDoom/src/strife/d_englsh.h create mode 100644 games/NXDoom/src/strife/d_items.c create mode 100644 games/NXDoom/src/strife/d_items.h create mode 100644 games/NXDoom/src/strife/d_main.c create mode 100644 games/NXDoom/src/strife/d_main.h create mode 100644 games/NXDoom/src/strife/d_net.c create mode 100644 games/NXDoom/src/strife/d_player.h create mode 100644 games/NXDoom/src/strife/d_textur.h create mode 100644 games/NXDoom/src/strife/d_think.h create mode 100644 games/NXDoom/src/strife/deh_ammo.c create mode 100644 games/NXDoom/src/strife/deh_cheat.c create mode 100644 games/NXDoom/src/strife/deh_frame.c create mode 100644 games/NXDoom/src/strife/deh_misc.c create mode 100644 games/NXDoom/src/strife/deh_misc.h create mode 100644 games/NXDoom/src/strife/deh_ptr.c create mode 100644 games/NXDoom/src/strife/deh_sound.c create mode 100644 games/NXDoom/src/strife/deh_strife.c create mode 100644 games/NXDoom/src/strife/deh_thing.c create mode 100644 games/NXDoom/src/strife/deh_weapon.c create mode 100644 games/NXDoom/src/strife/doomdata.h create mode 100644 games/NXDoom/src/strife/doomdef.c create mode 100644 games/NXDoom/src/strife/doomdef.h create mode 100644 games/NXDoom/src/strife/doomstat.c create mode 100644 games/NXDoom/src/strife/doomstat.h create mode 100644 games/NXDoom/src/strife/dstrings.c create mode 100644 games/NXDoom/src/strife/dstrings.h create mode 100644 games/NXDoom/src/strife/f_finale.c create mode 100644 games/NXDoom/src/strife/f_finale.h create mode 100644 games/NXDoom/src/strife/f_wipe.c create mode 100644 games/NXDoom/src/strife/f_wipe.h create mode 100644 games/NXDoom/src/strife/g_game.c create mode 100644 games/NXDoom/src/strife/g_game.h create mode 100644 games/NXDoom/src/strife/hu_lib.c create mode 100644 games/NXDoom/src/strife/hu_lib.h create mode 100644 games/NXDoom/src/strife/hu_stuff.c create mode 100644 games/NXDoom/src/strife/hu_stuff.h create mode 100644 games/NXDoom/src/strife/info.c create mode 100644 games/NXDoom/src/strife/info.h create mode 100644 games/NXDoom/src/strife/m_menu.c create mode 100644 games/NXDoom/src/strife/m_menu.h create mode 100644 games/NXDoom/src/strife/m_random.c create mode 100644 games/NXDoom/src/strife/m_random.h create mode 100644 games/NXDoom/src/strife/m_saves.c create mode 100644 games/NXDoom/src/strife/m_saves.h create mode 100644 games/NXDoom/src/strife/p_ceilng.c create mode 100644 games/NXDoom/src/strife/p_dialog.c create mode 100644 games/NXDoom/src/strife/p_dialog.h create mode 100644 games/NXDoom/src/strife/p_doors.c create mode 100644 games/NXDoom/src/strife/p_enemy.c create mode 100644 games/NXDoom/src/strife/p_floor.c create mode 100644 games/NXDoom/src/strife/p_inter.c create mode 100644 games/NXDoom/src/strife/p_inter.h create mode 100644 games/NXDoom/src/strife/p_lights.c create mode 100644 games/NXDoom/src/strife/p_local.h create mode 100644 games/NXDoom/src/strife/p_map.c create mode 100644 games/NXDoom/src/strife/p_maputl.c create mode 100644 games/NXDoom/src/strife/p_mobj.c create mode 100644 games/NXDoom/src/strife/p_mobj.h create mode 100644 games/NXDoom/src/strife/p_plats.c create mode 100644 games/NXDoom/src/strife/p_pspr.c create mode 100644 games/NXDoom/src/strife/p_pspr.h create mode 100644 games/NXDoom/src/strife/p_saveg.c create mode 100644 games/NXDoom/src/strife/p_saveg.h create mode 100644 games/NXDoom/src/strife/p_setup.c create mode 100644 games/NXDoom/src/strife/p_setup.h create mode 100644 games/NXDoom/src/strife/p_sight.c create mode 100644 games/NXDoom/src/strife/p_spec.c create mode 100644 games/NXDoom/src/strife/p_spec.h create mode 100644 games/NXDoom/src/strife/p_switch.c create mode 100644 games/NXDoom/src/strife/p_telept.c create mode 100644 games/NXDoom/src/strife/p_tick.c create mode 100644 games/NXDoom/src/strife/p_tick.h create mode 100644 games/NXDoom/src/strife/p_user.c create mode 100644 games/NXDoom/src/strife/r_bsp.c create mode 100644 games/NXDoom/src/strife/r_bsp.h create mode 100644 games/NXDoom/src/strife/r_data.c create mode 100644 games/NXDoom/src/strife/r_data.h create mode 100644 games/NXDoom/src/strife/r_defs.h create mode 100644 games/NXDoom/src/strife/r_draw.c create mode 100644 games/NXDoom/src/strife/r_draw.h create mode 100644 games/NXDoom/src/strife/r_local.h create mode 100644 games/NXDoom/src/strife/r_main.c create mode 100644 games/NXDoom/src/strife/r_main.h create mode 100644 games/NXDoom/src/strife/r_plane.c create mode 100644 games/NXDoom/src/strife/r_plane.h create mode 100644 games/NXDoom/src/strife/r_segs.c create mode 100644 games/NXDoom/src/strife/r_segs.h create mode 100644 games/NXDoom/src/strife/r_sky.c create mode 100644 games/NXDoom/src/strife/r_sky.h create mode 100644 games/NXDoom/src/strife/r_state.h create mode 100644 games/NXDoom/src/strife/r_things.c create mode 100644 games/NXDoom/src/strife/r_things.h create mode 100644 games/NXDoom/src/strife/s_sound.c create mode 100644 games/NXDoom/src/strife/s_sound.h create mode 100644 games/NXDoom/src/strife/sounds.c create mode 100644 games/NXDoom/src/strife/sounds.h create mode 100644 games/NXDoom/src/strife/st_lib.c create mode 100644 games/NXDoom/src/strife/st_lib.h create mode 100644 games/NXDoom/src/strife/st_stuff.c create mode 100644 games/NXDoom/src/strife/st_stuff.h create mode 100644 games/NXDoom/src/strife/strife_icon.c create mode 100644 games/NXDoom/src/strife/wi_stuff.c create mode 100644 games/NXDoom/src/strife/wi_stuff.h create mode 100644 games/NXDoom/src/tables.c create mode 100644 games/NXDoom/src/tables.h create mode 100644 games/NXDoom/src/v_diskicon.c create mode 100644 games/NXDoom/src/v_diskicon.h create mode 100644 games/NXDoom/src/v_patch.h create mode 100644 games/NXDoom/src/v_video.c create mode 100644 games/NXDoom/src/v_video.h create mode 100644 games/NXDoom/src/w_checksum.c create mode 100644 games/NXDoom/src/w_checksum.h create mode 100644 games/NXDoom/src/w_file.c create mode 100644 games/NXDoom/src/w_file.h create mode 100644 games/NXDoom/src/w_file_posix.c create mode 100644 games/NXDoom/src/w_file_stdc.c create mode 100644 games/NXDoom/src/w_file_win32.c create mode 100644 games/NXDoom/src/w_main.c create mode 100644 games/NXDoom/src/w_main.h create mode 100644 games/NXDoom/src/w_merge.c create mode 100644 games/NXDoom/src/w_merge.h create mode 100644 games/NXDoom/src/w_wad.c create mode 100644 games/NXDoom/src/w_wad.h create mode 100644 games/NXDoom/src/z_native.c create mode 100644 games/NXDoom/src/z_zone.c create mode 100644 games/NXDoom/src/z_zone.h create mode 100644 games/NXDoom/textscreen/.gitignore create mode 100644 games/NXDoom/textscreen/CMakeLists.txt create mode 100644 games/NXDoom/textscreen/Doxyfile create mode 100644 games/NXDoom/textscreen/Makefile.am create mode 100644 games/NXDoom/textscreen/examples/.gitignore create mode 100644 games/NXDoom/textscreen/examples/Makefile.am create mode 100644 games/NXDoom/textscreen/examples/calculator.c create mode 100644 games/NXDoom/textscreen/examples/guitest.c create mode 100644 games/NXDoom/textscreen/fonts/Makefile.am create mode 100644 games/NXDoom/textscreen/fonts/README create mode 100644 games/NXDoom/textscreen/fonts/codepage.h create mode 100755 games/NXDoom/textscreen/fonts/convert-font create mode 100644 games/NXDoom/textscreen/fonts/large.h create mode 100644 games/NXDoom/textscreen/fonts/large.png create mode 100644 games/NXDoom/textscreen/fonts/normal.h create mode 100644 games/NXDoom/textscreen/fonts/normal.png create mode 100644 games/NXDoom/textscreen/fonts/small.h create mode 100644 games/NXDoom/textscreen/fonts/small.png create mode 100644 games/NXDoom/textscreen/textscreen.h create mode 100644 games/NXDoom/textscreen/txt_button.c create mode 100644 games/NXDoom/textscreen/txt_button.h create mode 100644 games/NXDoom/textscreen/txt_checkbox.c create mode 100644 games/NXDoom/textscreen/txt_checkbox.h create mode 100644 games/NXDoom/textscreen/txt_conditional.c create mode 100644 games/NXDoom/textscreen/txt_conditional.h create mode 100644 games/NXDoom/textscreen/txt_desktop.c create mode 100644 games/NXDoom/textscreen/txt_desktop.h create mode 100644 games/NXDoom/textscreen/txt_dropdown.c create mode 100644 games/NXDoom/textscreen/txt_dropdown.h create mode 100644 games/NXDoom/textscreen/txt_fileselect.c create mode 100644 games/NXDoom/textscreen/txt_fileselect.h create mode 100644 games/NXDoom/textscreen/txt_gui.c create mode 100644 games/NXDoom/textscreen/txt_gui.h create mode 100644 games/NXDoom/textscreen/txt_inputbox.c create mode 100644 games/NXDoom/textscreen/txt_inputbox.h create mode 100644 games/NXDoom/textscreen/txt_io.c create mode 100644 games/NXDoom/textscreen/txt_io.h create mode 100644 games/NXDoom/textscreen/txt_label.c create mode 100644 games/NXDoom/textscreen/txt_label.h create mode 100644 games/NXDoom/textscreen/txt_main.h create mode 100644 games/NXDoom/textscreen/txt_radiobutton.c create mode 100644 games/NXDoom/textscreen/txt_radiobutton.h create mode 100644 games/NXDoom/textscreen/txt_scrollpane.c create mode 100644 games/NXDoom/textscreen/txt_scrollpane.h create mode 100644 games/NXDoom/textscreen/txt_sdl.c create mode 100644 games/NXDoom/textscreen/txt_sdl.h create mode 100644 games/NXDoom/textscreen/txt_separator.c create mode 100644 games/NXDoom/textscreen/txt_separator.h create mode 100644 games/NXDoom/textscreen/txt_spinctrl.c create mode 100644 games/NXDoom/textscreen/txt_spinctrl.h create mode 100644 games/NXDoom/textscreen/txt_strut.c create mode 100644 games/NXDoom/textscreen/txt_strut.h create mode 100644 games/NXDoom/textscreen/txt_table.c create mode 100644 games/NXDoom/textscreen/txt_table.h create mode 100644 games/NXDoom/textscreen/txt_utf8.c create mode 100644 games/NXDoom/textscreen/txt_utf8.h create mode 100644 games/NXDoom/textscreen/txt_widget.c create mode 100644 games/NXDoom/textscreen/txt_widget.h create mode 100644 games/NXDoom/textscreen/txt_window.c create mode 100644 games/NXDoom/textscreen/txt_window.h create mode 100644 games/NXDoom/textscreen/txt_window_action.c create mode 100644 games/NXDoom/textscreen/txt_window_action.h create mode 100644 games/NXDoom/vcpkg.json create mode 100644 games/NXDoom/win32/win_opendir.c create mode 100644 games/NXDoom/win32/win_opendir.h diff --git a/games/NXDoom/.devcontainer/.gitignore b/games/NXDoom/.devcontainer/.gitignore new file mode 100644 index 00000000000..70fdefc7613 --- /dev/null +++ b/games/NXDoom/.devcontainer/.gitignore @@ -0,0 +1,4 @@ +*.xauth +wads/ +prefs/ +share/ \ No newline at end of file diff --git a/games/NXDoom/.devcontainer/Dockerfile b/games/NXDoom/.devcontainer/Dockerfile new file mode 100644 index 00000000000..589a6cede5b --- /dev/null +++ b/games/NXDoom/.devcontainer/Dockerfile @@ -0,0 +1,39 @@ +FROM ubuntu + +######### Apt dependencies + +ARG system_apt_dependencies="build-essential gdb automake autoconf libtool git pkg-config python3 python3-pip sudo" +ARG choco_apt_dependencies="gcc make libsdl2-dev libsdl2-net-dev libsdl2-mixer-dev" +ARG choco_apt_dependencies_optional="libflac-dev libfluidsynth-dev libpng-dev libsamplerate-dev libvorbis-dev" +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -qq $system_apt_dependencies $choco_apt_dependencies $choco_apt_dependencies_optional + +########## Install Pillow (PIL) via pip, not apt + +ARG choco_pip_dependencies="pillow" +RUN pip install $choco_pip_dependencies + +########## Container user setup + +ARG USERNAME=chocodev +ARG USER_UID=1000 +ARG USER_GID=$USER_UID +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME + +# Add sudo support +RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +# Add the user to the audio group, to have ALSA sound access +# TODO: pulseaudio, so this isn't necessary? +RUN addgroup $USERNAME audio + +# Use bash, not sh. Yuck. +RUN chsh $USERNAME -s /bin/bash + +USER $USERNAME + +# Make sure we actually own our own local share stuff +RUN mkdir -p /home/$USERNAME/.local/share && \ + chown -R $USERNAME:$USERNAME /home/$USERNAME/.local diff --git a/games/NXDoom/.devcontainer/devcontainer.json b/games/NXDoom/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..cca038698e1 --- /dev/null +++ b/games/NXDoom/.devcontainer/devcontainer.json @@ -0,0 +1,45 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/docker-existing-dockerfile +{ + "name": "Doom Dev Container", + "context": "..", + "dockerFile": "./Dockerfile", + + "extensions": [ + "yzhang.markdown-all-in-one", + "bierner.markdown-preview-github-styles", + "dotjoshjohnson.xml", + + "eamodio.gitlens", + "npxms.hide-gitignored", // Note: need to run its command manually + + // Build tooling + "ms-vscode.cpptools", + "cschlosser.doxdocgen", + "austin.code-gnu-global", + "jeff-hykin.better-cpp-syntax", // Note: runs locally + "ms-vscode.cpptools-themes", // Note: runs locally + ], + + // Required to not bleed "root" permission files into the host volume + "containerUser": "chocodev", + + // VSCode on Linux specific, for creating X11 and sound forwarding + // Comment out manually if working on non-Linux + "initializeCommand": "${localWorkspaceFolder}/.devcontainer/initialize-linux.sh", + "mounts": [ + "source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind", + "source=${localWorkspaceFolder}/.devcontainer/prefs,target=/home/chocodev/.local/share/chocolate-doom,type=bind", + ], + "containerEnv": { + "DISPLAY": "${localEnv:DISPLAY}", + "XAUTHORITY": "${containerWorkspaceFolder}/.devcontainer/share/devcontainer.xauth", + }, + "runArgs": [ + // "--gpus", "all", // Uncomment for GPU support + "--device", "/dev/snd", + // TODO: pulseaudio? https://github.com/mviereck/x11docker/wiki/Container-sound:-ALSA-or-Pulseaudio + ] + + // TODO: X11/sound forwarding configs for MacOS (XQuartz) and Windows (Xming) +} diff --git a/games/NXDoom/.devcontainer/initialize-linux.sh b/games/NXDoom/.devcontainer/initialize-linux.sh new file mode 100755 index 00000000000..7a4275d36d3 --- /dev/null +++ b/games/NXDoom/.devcontainer/initialize-linux.sh @@ -0,0 +1,9 @@ +#!/bin/bash +HERE=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) + +### Create the xauth file allowing the container to interact with a forwarded X11 +XAUTH="$HERE/share/devcontainer.xauth"; +touch "$XAUTH" +xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - + +### TODO: pulseaudio pasthrough \ No newline at end of file diff --git a/games/NXDoom/.github/CONTRIBUTING.md b/games/NXDoom/.github/CONTRIBUTING.md new file mode 100644 index 00000000000..ad3a1c110d5 --- /dev/null +++ b/games/NXDoom/.github/CONTRIBUTING.md @@ -0,0 +1,101 @@ +Thanks for contributing to Chocolate Doom! Whatever your contribution, +whether it's code or just a bug report, it's greatly appreciated. + +The project is governed by the +[Contributor Covenant](http://contributor-covenant.org/version/1/4/) +version 1.4. By contributing to the project you agree to abide by its +terms. To report violations, please send an email to fraggle@gmail.com. + +### Reporting bugs + +Before reporting a bug, it's worth checking if this really is a bug. +Chocolate Doom's mission is to reproduce the Vanilla (DOS) versions of +the Doom engine games, bugs and all. Check out the +[NOT-BUGS](../NOT-BUGS.md) file for a list of common issues which aren't +really bugs at all. You might also try searching [the GitHub issues +list](https://github.com/chocolate-doom/chocolate-doom/issues) to see +if your bug has already been reported. + +If you're confident that you've found a real bug (or even if you're +not sure!) please go ahead and [file an issue on +GitHub](https://github.com/chocolate-doom/chocolate-doom/issues/new). +You'll need a GitHub account, but it's pretty easy to sign up. + +Please try to give as much information as possible: + +* What version of Chocolate Doom are you using? Check the title bar of + the window for the version number. + +* Chocolate Doom runs on many different operating systems (not just + Windows!). Please say which operating system and what version of it + you're using. + +* Please say which game you're playing (Doom 1, Doom 2, Heretic, + Hexen, Strife, etc.) and if you're using any fan-made WADs or mods, + please say which mods (and where they can be downloaded!). It helps + to give the full command line you're using to start the game. + +* Please mention if you have any special configuration you think may be + relevant, too. + +### Feature requests + +Chocolate Doom is always open to new feature requests; however, please +be aware that the project is designed around a deliberately limited +[philosophy](../PHILOSOPHY.md), and many features common in other source +ports will not be accepted. Here are a few common requests which are +often rejected: + +* "High resolution" rendering (greater than 320x200 display). + +* An option to disable Vanilla limits, such as the visplane rendering + limit. + +* Ability to play "No Rest For The Living", the expansion pack which + comes with the XBLA / BFG Edition of Doom. + +If you're not sure whether your feature is in line with the project +philosophy, don't worry - just ask anyway! +To make a feature request, [file an issue on +GitHub](https://github.com/chocolate-doom/chocolate-doom/issues/new). + +### Bug fixes / code submission + +Thank you for contributing code to Chocolate Doom! Please check the +following guidelines before opening a pull request: + +* All code must be licensed under [the GNU General Public License, + version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). + Please don't reuse code that isn't GPL, or that is GPLv3 licensed. + Be aware that by submitting your code to the project, you're agreeing + to license it under the GPL. + +* Please follow the coding style guidelines described in the + [HACKING](../HACKING.md) file. + +* Please don't make unnecessary changes which just change formatting + without any actual change to program logic. While being consistent + is nice, such changes destroy the ability to use the `git blame` + command to see when code was last changed. + +* The guidelines given above in the "feature requests" section also + apply here. New features which aren't in line with the project + philosophy are likely to be rejected. If you're not sure, open a + feature request first and ask before you start implementing your + feature. + +* Follow the guidelines for [how to write a Git commit + message](http://chris.beams.io/posts/git-commit/). In short: the + first line should be a short summary; keep to an 80 column limit; + use the imperative mood ("fix bug X", rather than "fixed bug X" or + "fixing bug X"). If your change fixes a particular subsystem, + prefix the summary with that subsystem: eg. "doom: Fix bug X" or + "textscreen: Change size of X". + +* If you're making a change related to a bug, reference the GitHub + issue number in the commit message, eg. "This is a partial fix + for #646". This will link your commit into the issue comments. If + your change is a fix for the bug, put the word "fixes" before the + issue number to automatically close the issue once your change + is merged. + diff --git a/games/NXDoom/.github/ISSUE_TEMPLATE.md b/games/NXDoom/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..101a5b33797 --- /dev/null +++ b/games/NXDoom/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,28 @@ + + +### Background + +Version of Chocolate Doom: + +Operating System and version: + +Game: (Doom/Heretic/Hexen/Strife/other) + +Any loaded WADs and mods (please include full command line): + +### Bug description + +Observed behavior: + +Expected behavior: + diff --git a/games/NXDoom/.github/workflows/cpp-linter.yml b/games/NXDoom/.github/workflows/cpp-linter.yml new file mode 100644 index 00000000000..931e0421ad8 --- /dev/null +++ b/games/NXDoom/.github/workflows/cpp-linter.yml @@ -0,0 +1,54 @@ +# Workflow syntax: +# https://help.github.com/en/articles/workflow-syntax-for-github-actions +name: cpp-linter + +on: + pull_request: + types: [opened, reopened, synchronize] + push: + branches: + - master + +jobs: + cpp-linter: + strategy: + matrix: + compiler: [clang] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install libfluidsynth-dev libpng-dev libsamplerate0-dev libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev ninja-build + - name: Run cmake to generate compilation database + run: cmake -S . -B . -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=1 + - uses: cpp-linter/cpp-linter-action@v2 + id: linter + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + style: file + lines-changed-only: true + version: 16 + tidy-checks: >- + boost-* + ,bugprone-* + ,performance-* + ,readability-* + ,portability-* + ,modernize-* + ,clang-analyzer-* + ,cppcoreguidelines-* + ,-cppcoreguidelines-avoid-magic-numbers + ,-cppcoreguidelines-init-variables + ,-readability-identifier-length + ,-readability-isolate-declaration + ,-readability-magic-numbers + + - name: Fail fast?! + if: steps.linter.outputs.checks-failed > 0 + run: | + echo "Some files failed the linting checks! Fail fast disabled until false positive issue is fixed" + + - name: Check no extern used in .c files + run: | + ./check-extern.sh diff --git a/games/NXDoom/.github/workflows/cppcheck.yml b/games/NXDoom/.github/workflows/cppcheck.yml new file mode 100644 index 00000000000..213afba019d --- /dev/null +++ b/games/NXDoom/.github/workflows/cppcheck.yml @@ -0,0 +1,23 @@ +name: cppcheck + +on: + pull_request: + types: [opened, reopened, synchronize] + push: + branches: + - master + +jobs: + cppcheck: + runs-on: ubuntu-22.04 + + steps: + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install cppcheck + + - uses: actions/checkout@v6 + + - name: Run cppcheck + env: + ANALYZE: true + run: $GITHUB_WORKSPACE/.travis.sh diff --git a/games/NXDoom/.github/workflows/main.yml b/games/NXDoom/.github/workflows/main.yml new file mode 100644 index 00000000000..b9a1a51c5dd --- /dev/null +++ b/games/NXDoom/.github/workflows/main.yml @@ -0,0 +1,152 @@ +name: Continuous Integration + +on: + push: + branches: + - "master" + tags: + - "*" + paths-ignore: + - "**.md" + pull_request: + branches: + - "master" + paths-ignore: + - "**.md" + workflow_dispatch: + +jobs: + build: + name: ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + defaults: + run: + shell: ${{ matrix.config.shell }} + strategy: + fail-fast: false + matrix: + config: + - name: Linux GCC + os: ubuntu-latest + compiler: gcc + shell: bash + + - name: macOS Clang + os: macos-latest + compiler: clang + shell: bash + + - name: macOS x86 Clang + os: macos-15-intel + compiler: clang + shell: bash + + - name: MSYS2 UCRT64 + os: windows-latest + compiler: gcc + shell: 'msys2 {0}' + msystem: ucrt64 + msys-env: mingw-w64-ucrt-x86_64 + artifacts: true + pkg-path: pkg/win32/*.zip + pkg-dir: pkg/win32 + + steps: + - name: Install pandoc + if: runner.os == 'Windows' + shell: cmd + run: choco install pandoc + + - name: Install dependencies (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install \ + libsdl2-dev \ + libsdl2-mixer-dev \ + libsdl2-net-dev \ + libpng-dev \ + libsamplerate0-dev \ + libfluidsynth-dev + + - name: Install dependencies (macOS) + if: runner.os == 'macOS' + run: | + brew install \ + automake \ + sdl2 \ + sdl2_mixer \ + sdl2_net \ + libpng \ + libsamplerate \ + fluid-synth + + - name: Install dependencies (MSYS2) + if: runner.os == 'Windows' + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.config.msystem }} + update: true + path-type: inherit + install: >- + autotools + zip + ${{ matrix.config.msys-env }}-python-pip + ${{ matrix.config.msys-env }}-gcc + ${{ matrix.config.msys-env }}-SDL2 + ${{ matrix.config.msys-env }}-SDL2_mixer + ${{ matrix.config.msys-env }}-SDL2_net + ${{ matrix.config.msys-env }}-libpng + ${{ matrix.config.msys-env }}-libsamplerate + ${{ matrix.config.msys-env }}-fluidsynth + + - uses: actions/checkout@v6 + with: + submodules: true + + - name: Configure + env: + CC: ${{ matrix.config.compiler }} + run: | + ./autogen.sh + + - name: Build + run: make -j4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Test + run: | + pip install pyyaml + PREFIX=`sed -n '/PROGRAM_PREFIX/p' ${PWD}/config.h | cut -d '"' -f 2` + make -j4 -C quickcheck check SOURCE_PORT=$PWD/src/${PREFIX}doom + + - name: Package + if: ${{ matrix.config.artifacts }} + run: | + cd ${{ matrix.config.pkg-dir }} + make + + - name: Upload artifacts + if: ${{ matrix.config.artifacts }} + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.config.name }} + path: ${{ matrix.config.pkg-path }} + + - name: Extract Package String + if: ${{ contains(github.ref, 'tags') }} + run: | + PACKAGE_STRING=`sed -n '/PACKAGE_STRING/p' ${PWD}/config.h | cut -d '"' -f 2` + echo "PACKAGE_STRING=${PACKAGE_STRING}" >> $GITHUB_ENV + + - name: Release + if: ${{ contains(github.ref, 'tags') && matrix.config.artifacts }} + uses: ncipollo/release-action@v1 + with: + name: ${{ env.PACKAGE_STRING }} + bodyFile: RELEASE_NOTES.md + allowUpdates: true + artifacts: ${{ matrix.config.pkg-path }} diff --git a/games/NXDoom/.gitignore b/games/NXDoom/.gitignore new file mode 100644 index 00000000000..c41a753969d --- /dev/null +++ b/games/NXDoom/.gitignore @@ -0,0 +1,67 @@ +CMDLINE +INSTALL +Makefile +Makefile.in +TAGS +aclocal.m4 +autom4te.cache +autotools +bin +config.h +config.hin +config.log +config.status +configure +lib +obj +rpm.spec +stamp-h +stamp-h.in +stamp-h1 +tags +\#*\# +DOOM*.png +HTIC*.png +HEXEN*.png +STRIFE*.png +DOOM*.pcx +HTIC*.pcx +HEXEN*.pcx +STRIFE*.pcx + +# CMake-specific ignores +/.vs +/build* +/CMakeSettings.json +/out + +# These are the default patterns globally ignored by Subversion: +*.o +*.lo +*.la +*.al +.libs +*.so +*.so.[0-9]* +*.a +*.pyc +*.pyo +*.rej +*~ +.#* +.*.swp +.DS_store + +# Ignore GNU Global tags and html files +GPATH +GRTAGS +GTAGS +/HTML/ + +# VSCode settings + +/.vscode/ + +# clangd settings +/.cache/clangd +compile_commands.json diff --git a/games/NXDoom/.gitmodules b/games/NXDoom/.gitmodules new file mode 100644 index 00000000000..7a381cfd44c --- /dev/null +++ b/games/NXDoom/.gitmodules @@ -0,0 +1,3 @@ +[submodule "quickcheck"] + path = quickcheck + url = https://github.com/chocolate-doom/quickcheck.git diff --git a/games/NXDoom/.lvimrc b/games/NXDoom/.lvimrc new file mode 100644 index 00000000000..63e46133525 --- /dev/null +++ b/games/NXDoom/.lvimrc @@ -0,0 +1,32 @@ +" Local vimrc configuration file. Install the localvimrc.vim vim script. +set expandtab +set tabstop=8 +set softtabstop=4 +set shiftwidth=4 + +" Add all tag files to tags path. + +let topdir = findfile("configure.ac", ".;") +let topdir = substitute(topdir, "configure.ac", "", "") + +" Check tags file in current dir: +set tags+=tags + +" Add tag files in parent directories: +let tagfiles = findfile("tags", ".;", -1) + +" Add tag files for libraries: +call add(tagfiles, topdir . "opl/tags") +call add(tagfiles, topdir . "pcsound/tags") +call add(tagfiles, topdir . "textscreen/tags") + +for tagfile in tagfiles + " Don't go beyond the project top level when adding parent dirs: + if stridx(tagfile, topdir) >= 0 + exec "set tags+=" . tagfile + endif +endfor + +unlet topdir +unlet tagfiles + diff --git a/games/NXDoom/.travis.sh b/games/NXDoom/.travis.sh new file mode 100755 index 00000000000..683d9bea636 --- /dev/null +++ b/games/NXDoom/.travis.sh @@ -0,0 +1,19 @@ +#!/bin/sh +if [ "$ANALYZE" = "true" ] ; then + # -D__GNUC__ is required for cppcheck to know about noreturn functions + cppcheck --error-exitcode=1 -j2 -UTESTING -D__GNUC__ -Iopl -Isrc -Isrc/setup opl pcsound src textscreen 2> stderr.txt + RET=$? + if [ -s stderr.txt ] + then + cat stderr.txt + fi + exit $RET +else + set -e + ./autogen.sh --enable-werror + make -j4 + make install DESTDIR=/tmp/whatever + make dist + PREFIX=`sed -n '/PROGRAM_PREFIX/p' ${PWD}/config.h | cut -d '"' -f 2` + make -j4 -C quickcheck check SOURCE_PORT=$PWD/src/${PREFIX}doom +fi diff --git a/games/NXDoom/AUTHORS b/games/NXDoom/AUTHORS new file mode 100644 index 00000000000..6324caae4a9 --- /dev/null +++ b/games/NXDoom/AUTHORS @@ -0,0 +1,7 @@ +Simon Howard +James Haley +Samuel Villarreal +Fabian Greffrath +Jonathan Dowland +Alexey Khokholov +Turo Lamminen diff --git a/games/NXDoom/CMakeLists.txt b/games/NXDoom/CMakeLists.txt new file mode 100644 index 00000000000..da58daca2d0 --- /dev/null +++ b/games/NXDoom/CMakeLists.txt @@ -0,0 +1,105 @@ +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +cmake_minimum_required(VERSION 3.7.2) +project("Chocolate Doom" VERSION 3.1.1 LANGUAGES C) + +set(CMAKE_C_STANDARD 99) + +# Autotools variables +set(top_srcdir ${CMAKE_CURRENT_SOURCE_DIR}) +set(top_builddir ${CMAKE_CURRENT_BINARY_DIR}) + +# AC_INIT variables +set(PACKAGE_NAME "${PROJECT_NAME}") +set(PACKAGE_TARNAME "chocolate-doom") +set(PACKAGE_VERSION "${PROJECT_VERSION}") +set(PACKAGE_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") +set(PACKAGE_BUGREPORT "chocolate-doom-dev-list@chocolate-doom.org") + +string(REGEX REPLACE " Doom$" "" PACKAGE_SHORTNAME "${PACKAGE_NAME}") +set(PACKAGE_COPYRIGHT "Copyright (C) 1993-2025") +set(PACKAGE_LICENSE "GNU General Public License, version 2") + +# Any settings that should apply to all targets in this directory and all +# subdirectories should go here. Use judiciously. +if(MSVC) + add_definitions("/D_CRT_SECURE_NO_WARNINGS" "/D_CRT_SECURE_NO_DEPRECATE" + "/D_CRT_NONSTDC_NO_DEPRECATE") +else() + add_compile_options("-Wall" "-Wdeclaration-after-statement" + "-Wredundant-decls") +endif() + +option(CMAKE_FIND_PACKAGE_PREFER_CONFIG + "Lookup package config files before using find modules" On) + +option(ENABLE_SDL2_NET "Enable SDL2_net" On) +option(ENABLE_SDL2_MIXER "Enable SDL2_mixer" On) + +if (NOT DEFINED EMSCRIPTEN) + find_package(SDL2 2.0.14) +endif() +if(ENABLE_SDL2_MIXER) + if (NOT DEFINED EMSCRIPTEN) + find_package(SDL2_mixer 2.0.2) + endif() +else() + add_compile_definitions(DISABLE_SDL2MIXER=1) +endif() + +if(ENABLE_SDL2_NET) + if (NOT DEFINED EMSCRIPTEN) + find_package(SDL2_net 2.0.0) + endif() +else() + add_compile_definitions(DISABLE_SDL2NET=1) +endif() + + +# Check for libsamplerate. +find_package(SampleRate) +if(SampleRate_FOUND) + set(HAVE_LIBSAMPLERATE TRUE) +endif() + +# Check for libpng. +find_package(PNG) +if(PNG_FOUND) + set(HAVE_LIBPNG TRUE) +endif() + +# Check for FluidSynth. +find_package(FluidSynth 2.2.0) +if(FluidSynth_FOUND AND ENABLE_SDL2_MIXER) + set(HAVE_FLUIDSYNTH TRUE) +endif() + +find_package(m) + +include(CheckSymbolExists) +include(CheckIncludeFile) +check_symbol_exists(strcasecmp "strings.h" HAVE_DECL_STRCASECMP) +check_symbol_exists(strncasecmp "strings.h" HAVE_DECL_STRNCASECMP) +check_include_file("dirent.h" HAVE_DIRENT_H) + +string(CONCAT WINDOWS_RC_VERSION "${PROJECT_VERSION_MAJOR}, " + "${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}, 0") + +# Without a hyphen. This is used for the bash-completion scripts. +string(TOLOWER "${PACKAGE_SHORTNAME}" PROGRAM_SPREFIX) + +# With a hyphen, used almost everywhere else. +set(PROGRAM_PREFIX "${PROGRAM_SPREFIX}-") + +configure_file(cmake/config.h.cin config.h) + +configure_file(src/doom-res.rc.in src/doom-res.rc) +configure_file(src/heretic-res.rc.in src/heretic-res.rc) +configure_file(src/hexen-res.rc.in src/hexen-res.rc) +configure_file(src/setup-res.rc.in src/setup-res.rc) +configure_file(src/setup/setup-manifest.xml.in src/setup/setup-manifest.xml) +configure_file(src/strife-res.rc.in src/strife-res.rc) + +foreach(SUBDIR textscreen opl pcsound src) + add_subdirectory("${SUBDIR}") +endforeach() diff --git a/games/NXDoom/CODE_OF_CONDUCT.md b/games/NXDoom/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..895dcfd49f0 --- /dev/null +++ b/games/NXDoom/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at fraggle@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/games/NXDoom/COPYING.md b/games/NXDoom/COPYING.md new file mode 100644 index 00000000000..28fbecabf5c --- /dev/null +++ b/games/NXDoom/COPYING.md @@ -0,0 +1,361 @@ +### 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. + +### 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. + + one line to give the program's name and an idea of what it does. + Copyright (C) yyyy name of author + + 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. + + signature of Ty Coon, 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](https://www.gnu.org/licenses/lgpl.html) instead of this +License. diff --git a/games/NXDoom/ChangeLog b/games/NXDoom/ChangeLog new file mode 100644 index 00000000000..59a73a4b6a4 --- /dev/null +++ b/games/NXDoom/ChangeLog @@ -0,0 +1,5 @@ +Chocolate Doom's version history is stored in Git. For a full +change log, clone the repository on Github: + + https://github.com/chocolate-doom/chocolate-doom + diff --git a/games/NXDoom/HACKING.md b/games/NXDoom/HACKING.md new file mode 100644 index 00000000000..792136e8262 --- /dev/null +++ b/games/NXDoom/HACKING.md @@ -0,0 +1,256 @@ +# Coding style guidelines + +The coding style guidelines for Chocolate Doom are designed to keep the +style of the original source code. This maintains consistency throughout +the program, and does not require the original code to be changed. Some +of these guidelines are stricter than what was done in the original +source; follow these when writing new code only: there is no need to +change existing code to fit them. + +You should set tabs to *display* as eight spaces, not four. However, +*indentation* should be four spaces. If possible, do not use tab +characters at all. There is a utility called “expand” which will remove +tab characters. For the reasoning behind this, see: +http://www.jwz.org/doc/tabs-vs-spaces.html + +Please write code to an 80 column limit so that it fits within a standard +80 column terminal. Do not leave trailing whitespace at the end of lines. + +Functions should be named like this: `AB_FunctionName`. The `AB` prefix +denotes the subsystem (`AM_` for automap, `G_` for game, etc). If a +function is static, you can omit the prefix and just name it like +`FunctionName`. Functions and global variables should always be made +static if possible. + +Put `_t` on the end of types created with typedef. Type names like this +should be all lowercase and have the subsystem name at the start. An +example of this is `txt_window_t`. When creating structures, always +typedef them. + +Do not use Hungarian notation. + +Do not use the goto statement. + +Use C++-style comments, ie. `//` comments, not `/* ... */` comments. +I don’t care that this isn’t standard ANSI C. + +Variables should be named like this: `my_variable_name`, not like this: +`MyVariableName`. In pointer variable declarations, place the `*` next +to the variable name, not the type. + +When casting variables from one type to another, put a space after the +last closing brace. + +When using an if, do, while, or for statement, always use the { } braces +even when they are not necessary. For example, do this: + +```c +if (condition) +{ + body; +} +``` + +Not this: + +```c +if (condition) // NO + body; +``` + +Write code like this: + +```c +typedef struct +{ + int member1; + char *member2; +} my_structure_t; + +void FunctionName(int argument, int arg2, int arg3, int arg4, int arg5, + int arg6, int arg7) +{ + int assign_var; + + assign_var = arg2 + arg3 * arg4 * (arg5 + arg6); + + if (foo && !bar || baz && qux || !(foo && bar && baz)) + { + body; + } + else if (xyz + 4 < abc * 4 + 3) + { + body; + } + else + { + body; + } + + if (very_long_condition_like_this_one_that_forces_a_line_break + && other_condition) + { + body; + } + + switch (argument) + { + case FIRST: + code; + break; + + case SECOND: + code; + break; + + default: + break; + } + + for (a = 0; a < 10; ++a) + { + FunctionCall(arg1, arg2, arg3, arg4, + arg_split_onto_second_line); + } + + while (a < 10) + { + loop_body; + } + + do + { + + } while (condition); +} +``` + +## Editor-specific default settings + +If you use vim, you can put this into your `.vimrc` (or install the +`localvimrc` script): + +``` +set expandtab +set tabstop=8 +set softtabstop=4 +set shiftwidth=4 +``` + +Or, if you use Emacs, put this in your `.emacs`: + +```lisp +(add-hook 'c-mode-hook (lambda () + (when (and buffer-file-name + (string-match "chocolate-doom" buffer-file-name)) + (c-set-style "bsd") + (setq indent-tabs-mode nil) + (setq tab-width 8) + (setq c-basic-offset 4)))) +``` + +## Security + +The C standard library has a number of unsafe functions that should be +avoided when writing code for Chocolate Doom. These are: + +Unsafe function | Safer alternative +------------------|------------------------ +`gets()` | `fgets(.., stdin)` +`sprintf` | `M_snprintf()` +`snprintf` | `M_snprintf()` +`vsprintf` | `M_vsnprintf()` +`vsnprintf` | `M_vsnprintf()` +`strcpy()` | `M_StringCopy()` +`strncpy()` | `M_StringCopy()` +`strcat()` | `M_StringConcat()` +`strncat()` | `M_StringConcat()` +`strdup()` | `M_StringDuplicate()` +`realloc()` | `I_Realloc()` + +Lots of the code includes calls to DEH_String() to simulate string +replacement by the Dehacked tool. Be careful when using Dehacked +replacements of printf format strings. For example, do not do this: + +```c +printf(DEH_String("foo %s"), s); +sprintf(mybuf, DEH_String("bar %s"), t); +``` + +Instead do this: + +```c +DEH_printf("foo %s", s); +DEH_snprintf(mybuf, sizeof(mybuf), "bar %s", t); +``` + +This does the format string replacement safely in a way that checks +the arguments securely. + +## Portability + +Chocolate Doom is designed to be cross-platform and work on different +Operating Systems and processors. Bear this in mind when writing code. + +Do not use the `long` type (its size differs across platforms; use +`int` or `int64_t` depending on which you want). + +Use Doom’s byte data type for byte data. `int` is assumed to be a +32-bit integer, and `short` is a 16-bit integer. You can also use the +ISO C99 data types: `intN_t` and `uintN_t` where N is 8, 16, 32, 64. + +Be careful with platform dependencies: do not use Windows API +functions, for example. Use SDL where possible. + +Preprocessor `#defines` are set that can be used to identify the OS +if necessary: `_WIN32` for Windows and `__MACOSX__` for Mac OS X. Others +are set through SDL. Try to avoid this if possible. + +Be careful of endianness! Doom has `SHORT()` and `LONG()` macros that +do endianness conversion. Never assume that integer types have a +particular byte ordering. Similarly, never assume that fields +inside a structure are aligned in a particular way. This is most +relevant when reading or writing data to a file or a network pipe. + +For signed integers, you shouldn’t assume that `(i >> n)` is the same as +`(i / (1 << n))`. However, most processors handle bitshifts of signed +integers properly, so it’s not a huge problem. + +Due to Microsoft implementation of the Unicode support in C standard +library you should use these wrappers to support non-latin paths and +filenames on Windows. + +C library function | Wrapper +-------------------|------------------- +`fopen()` | `M_fopen()` +`remove()` | `M_remove()` +`rename()` | `M_rename()` +`stat()` | `M_stat()` +`mkdir()` | `M_MakeDirectory()` +`getenv()` | `M_getenv()` + +## GNU GPL and licensing + +All code submitted to the project must be licensed under the GNU GPLv2 or a +compatible license. If you use code that you haven’t 100% written +yourself, say so. Add a copyright header to the start of every file. Use +this template: + +``` +// +// Copyright(C) YEAR Author's name +// +// 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. +// +// +// *File description goes here* +// +``` diff --git a/games/NXDoom/Makefile.am b/games/NXDoom/Makefile.am new file mode 100644 index 00000000000..4cad870c51f --- /dev/null +++ b/games/NXDoom/Makefile.am @@ -0,0 +1,62 @@ +AUX_DIST_GEN = \ + $(ac_aux_dir)/install-sh \ + $(ac_aux_dir)/missing + +CMAKE_FILES= \ + CMakeLists.txt \ + cmake/FindSDL2.cmake \ + cmake/FindSDL2_mixer.cmake \ + cmake/FindSDL2_net.cmake \ + cmake/FindFluidSynth.cmake \ + cmake/Findm.cmake \ + cmake/FindSampleRate.cmake \ + cmake/config.h.cin + +DOC_FILES= \ + COPYING.md \ + README.md \ + README.Music.md \ + NEWS.md \ + PHILOSOPHY.md \ + ChangeLog + +EXTRA_DIST= \ + $(AUX_DIST_GEN) \ + $(CMAKE_FILES) \ + $(DOC_FILES) \ + NOT-BUGS.md \ + README.Strife.md \ + .lvimrc \ + HACKING.md \ + TODO.md \ + rpm.spec \ + win32/win_opendir.c \ + win32/win_opendir.h + +doomdocsdir = ${docdir}/../${PROGRAM_PREFIX}doom +doomdocs_DATA = $(DOC_FILES) NOT-BUGS.md + +hereticdocsdir = ${docdir}/../${PROGRAM_PREFIX}heretic +hereticdocs_DATA = $(DOC_FILES) + +hexendocsdir = ${docdir}/../${PROGRAM_PREFIX}hexen +hexendocs_DATA = $(DOC_FILES) + +strifedocsdir = ${docdir}/../${PROGRAM_PREFIX}strife +strifedocs_DATA = $(DOC_FILES) README.Strife.md + +MAINTAINERCLEANFILES = $(AUX_DIST_GEN) + +SUBDIRS=textscreen opl pcsound data src man + +DIST_SUBDIRS=pkg $(SUBDIRS) + +if HAVE_DOC + +INSTALL : man/INSTALL.template man/simplecpp + $(srcdir)/man/simplecpp -DDOOM -DHERETIC -DHEXEN -DSTRIFE \ + -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \ + -DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \ + < $(srcdir)/man/INSTALL.template > $@ + +endif diff --git a/games/NXDoom/NEWS.md b/games/NXDoom/NEWS.md new file mode 100644 index 00000000000..9fa55a749e0 --- /dev/null +++ b/games/NXDoom/NEWS.md @@ -0,0 +1,1492 @@ +## 3.1.1 (2025-08-14) + +### General + * Fix compilation on GCC 15 (thanks Fabian). + * Hide public IP addresses for privacy. + * Use native OpenGL texture format for better performance (thanks Fabian). + * Improved directory handling on Windows (thank Roman Fomin): + * Fixes problems with postfix "." for non-relative paths. + * Support for long NTFS paths (up to 32768 characters). + * Fixed metainfo files for latest AppStream spec compliance (thanks Fabian). + * Add option to enable or disable smooth pixel scaling (thanks StevenSYS). + * Allow spaces in GUS patch folder path (thanks Michael Day). + * Add support for non-US backslash key (thanks Michael Day). + * Never let SDL Mixer use native midi on Windows (thanks Michael Day). + * Use $TMPDIR to find tempdir on Unix (thanks Mr. Myth). + * Improve man page formatting (thanks g-branden-robinson). + +### Build systems + * Can now be built with Emscripten (thanks James Baicoianu). + * Misc. improvements (thanks suve, Emmanuel Ferdman, Gabriele Simoni, et al.) + +### Setup + * Use correct EGA palette colors (thanks Henrique Jorge). + +### Doom + * Initial support for Doom version 1.5 (thanks Michael Francis). + +### Heretic + * Fix crash after loading too many saved games (thanks Noseey). + +### Hexen + * Fix crash with Heresiarch fireballs if player has never touched a wall (thank Noseey). + +### Strife + * Initialize floor->type and floor->crush fields in EV_BuildStairs() (thanks Fabian). + +## 3.1.0 (2024-08-01) + +### General + * Drag and drop loading of WAD, Dehacked and demo files is now supported on + Windows - simply drag the files onto chocolate-doom.exe (thanks Fabian). + * WAD file autoloading was added - WAD and DEH files can be copied into + an autoload folder to be automatically included on every game start. + * Music pack configuration has been significantly simplified. By simply + copying .flac/.ogg music files into a folder they will be automatically + detected by filename and used. + * Music packs can now be used with OPL as a fallback, and music pack + config files can have any name ending in '.cfg'. + * MP3 music packs are now supported. + * Network synchronization now uses a PID controller by default, which + makes games more smooth and more stable, especially for Internet play. + * UDP hole punching is now used to make servers behind NAT gateways + automatically accessible to the Internet. + * OPL emulation now uses Nuked OPL3 v1.8 (thanks nukeykt) + * Allow simultaneous PC speaker emulation and OPL emulation + (thanks Michael Day). + * The setup tool now uses "Romero Blue" as a background (see the wiki: + for more info). + * The 0 and 5 keys on the number pad can now be bound independently + of any other keyboard key (thanks BlooD2ool). + * With aspect ratio correction disabled, the game can scale to any + arbitrary size and remove all black borders in full screen mode. + (thanks chungy) + * The executable's location is now checked when looking for IWADs. + * The IWAD files installed by Steam-on-Linux are now detected (thanks + chungy). + * It's now possible to use `-response` to load response files. + * Default savegame name now includes the WAD filename (thanks Fabian). + * Mouse movement is no longer read when the game window is inactive + (thanks Julia Nechaevskaya). + * Chocolate Doom now by default generates a "pet name" for the user + to respect privacy (thanks Jon!) + * The Freedoom single-player IWAD files are now officially supported, + since recent versions changed all levels to be vanilla compatible. + * Add native support for the FluidSynth midi synthesizer. + * Add a fsynth_gain config key to fine tune the FluidSynth output level + (thanks Fabian). + * Redesign of native MIDI support in Windows (thanks ceski and Roman Fomin): + - Emulates DMX MPU-401 feature set by default, change with + `winmm_complevel`. + - MIDI device reset between songs using "GM System On", change with + `winmm_reset_type`. + - Configurable delay after reset for legacy MIDI hardware (e.g. Roland + SC-55), change with `winmm_reset_delay`. + * Add improved gamepad support via the SDL\_GameController interface. This + includes support for analog triggers, modern dual-stick default bindings + (based on Unity Doom), descriptive button names for common controller types + and configurable dead zones for stick axes. (Michael Day). + * All games now have shiny new icons! + * The -display parameter was added to specify the display number on which to show the screen (thanks Robin Emeršič). + +### Build systems + * SDL2_mixer and SDL2_net can now be optionally disabled to increase + portability to systems that might not support audio or networking + (thanks turol). + * Travis CI was replaced with GitHub Actions (thanks Michael Francis). + * mingw CI was added for automatic Windows-building (thanks turol). + * A cpp-linter CI was added to improve the quality and formatting of code + (thanks turol). + * The `--disable-zpool` autoconf argument for disabling memory pooling was + added to make debugging easier (thanks turol). + * Python 2 has been deprecated and Python 3 is now used exclusively + (thanks Fabian). + +### Refactorings + * CMake project files have been added, replacing the Microsoft Visual + Studio and Code::Blocks files. CMake maintains support for multiple + IDEs and versions thereof, and reduces developer overhead when updating + Chocolate Doom (huge thanks to AlexMax for this work). + * Source code has been retrofitted to fix many compiler warnings and + add const annotations to many variables (thanks turol). + * Several functions have been hardened against incomplete reads and + error conditions, and made safer (thanks turol). + * Man page generation has been reworked to use autoconf macro + substitution, making it eaiser for downstream forks to change the + project name (thanks Jon). + * We now print a meaningful error message when a savegame cannot be + loaded (thanks Zodomaniac, chungy). + * There's now a log file feature for the network code to aid in tracking + down multiplayer bugs. + * AppData files were updated to the AppStream standard (thanks Mike). + * Many abuses of the extern keyword have been cleaned up to prevent + undefined behavior (thanks turol). + * Install of bash completion scripts was fixed (thanks Mike Swanson). + +### Bug fixes + * Fixed an exception thrown by the Windows kernel when debugging with + GDB (thanks AXDOOMER). + * Loop metadata now works properly with music packs on Windows. + * Mouse movement is ignored when the game window isn't active (thanks + Julia Nechaevskaya). + * A bug was fixed where music would not play after pausing on an + intermission screen (thanks Julia Nechaevskaya). + * Timeouts when connecting to a network server were fixed (thanks + @bradc6). + * A long-standing bug where some visplane overflows caused crashes was + fixed (thanks Michael Francis). + * A multiplayer deadlock bug where clients would stop sending tics after + missing tics from the server was fixed. There are both client- and + server- side fixes to fix the problem when playing with older versions + (thanks MadDog and Mortrixs for help tracking this down). + * The macOS launcher now quits automatically when all windows are closed. + * The mouse speed calibration thermometer was fixed. + * Some improvements have been made to PC speaker emulation to better match + Vanilla (thanks NY00123). + * Filenames and paths with non-latin characters now work on Windows + (thanks Roman Fomin). + * Properly handle orphan carriage returns when parsing deh files + (thanks Michael Day). + +### Doom + * Doom 1.2 demo support was added (thanks James Canete!) + * Map33 intermission screen and map33-map35 automap names are + emulated (thanks CapnClever). + * We now exit gracefully when player starts are missing (thanks Michael + Francis). + * We now exit gracefully on levels with a boss brain and no boss spitter + things (thanks Jason Benaim). + * It's now possible to play multiplayer with gameversion=1.2. + * When the game hits the limit for the number of wall scrollers, a count + of the number of scrollers is now displayed (thanks Jon). + * Sector special 17 (random light flicker) is now accurately emulated to + only appear in gameversion > 1.2 (thanks tpoppins). + * Fixed mouse events causing unwanted key presses (thanks Michael Day). + * French Doom II files doom2f.wad and french.deh are now automatically + detected (thanks Acts19quiz). + * Mouse buttons are now bindable to run (thanks Archenoth). + * The "Sky never changes in Doom II" bug is now accurately emulated + (thanks Michael Francis). + * Mouse buttons are now bindable to turn left/right (thanks Fabian). + * Fix possible undefined behavior and accurately emulate vanilla when -skill + parameter is given a negative value (thanks Henrique Jorge). + +### Heretic + * P\_FindNextHighestFloor was changed to match vanilla behavior (thanks + AXDOOMER). + * WAD hash table is now generated for speed (thanks Michael Francis). + * HHE level name replacements now apply on the intermission screen + (thanks ETTiNGRiNDER). + * Mouse buttons are now bindable to scroll through inventory and + "use artifact" (thanks Michael Day). + * Mouse buttons are now bindable to run (thanks Archenoth). + * Multiplayer demo playback was fixed (thanks Ryan Krafnick). + * The GOG.com release is now detected (thanks Mike Swanson). + * Mouse buttons are now bindable to turn left/right (thanks Fabian). + * Fix NULL backsector crash (thanks kitchen-ace and Julia Nechaevskaya). + +### Hexen + * ACS code has been hardened against potential security vulnerabilities. + * WAD hash table is now generated for speed (thanks AXDOOMER). + * Mouse buttons are now bindable to scroll through inventory and + "use artifact" (thanks Michael Day). + * Mouse buttons are now bindable to run (thanks Archenoth). + * Multiplayer demo playback was fixed (thanks Ryan Krafnick). + * The GOG.com release is now detected (thanks Mike Swanson). + * Mouse buttons are now bindable to turn left/right (thanks Fabian). + * Fixed demo desyncs in P_LookForPlayers (thanks Michael Day) + * Add support for two different v1.1 variants through -gameversion + argument (thank NY00123). + +### Strife + * Sehacked replacements of the "empty slot" string now work. + * VOICES.WAD is now found in a case-insensitive way (thanks Michael Francis). + * PC speaker sound effects are now supported (thanks ceski). + * Mouse buttons are now bindable to turn left/right (thanks Fabian). + * Fixed demo desyncs in P_LookForPlayers (thanks Michael Day) + * Fix possible undefined behavior and accurately emulate vanilla when -skill + parameter is given a negative value (thanks Henrique Jorge). + +## 3.0.1 (2020-06-24) + +This is a point release that includes two security fixes related to Chocolate +Doom server logic. + +Thanks to Michał Dardas from LogicalTrust for discovering the vulnerability. + +### Bug fixes + * ([CVE-2020-14983](https://nvd.nist.gov/vuln/detail/CVE-2020-14983)) Fixed a vulnerability where + an unchecked `num_players` field in the server logic could allow a malicious attacker to trigger + arbitrary code execution against Chocolate Doom servers. + * Fixed an issue where a client could crash if the server sent an invalid `ticdup` setting. + +## 3.0.0 (2017-12-30) + + Chocolate Doom 3.0 is a new major revision. The main change is that + the codebase has been ported to SDL 2.0. This brings a number of + benefits, although there have also been some other minor changes (all + listed below). + + Huge thanks go to the entire Chocolate Doom team for working on the + port to SDL2, and to all the testers who have found and reported bugs + during its development. + +### General + * All screen scaling is now performed in hardware, meaning that the + game can run in arbitrary window sizes in high quality. It can also + scale to very large resolutions sizes without using large amounts of + CPU or suffering degraded performance (thanks Fabian). + * It is now possible to switch between windowed and full screen modes + while the game is running by pressing alt + enter (thanks Jon) + * Windows binaries now ship with several previously-optional DLLs. + This means it is now possible to take PNG screenshots and to use + digital music packs (FLAC/Ogg Vorbis formats). + * The game now remembers your preferred monitor and will start on the + same monitor you were using the last time you played. Windows appear + centered on the screen. + * The OS X launcher was tweaked somewhat, and now uses proper path + controls for choosing files. FreeDM was added as an IWAD. + * Configuration files on Mac OS X and Unix are now stored in locations + compliant with the XDG standard (thanks chungy): + - On Unix: `~/.local/share/chocolate-doom/` + - On OS X: `~/Library/Application Support/chocolate-doom/` + * Icons when the game is running are now a higher resolution. + * Keyboard input is improved and uses the new SDL input API; on + systems with on-screen keyboards, this should activate the on-screen + keyboard when it is appropriate. + * Menu navigation with the joystick is now much more practical, and + it’s possible to bind a joystick axis to look up/down in games which + support it (thanks Jon, Wintermute0110). + * Several command line options were removed that were judged to be + useless: `-grabmouse`, `-novert` and `-nonovert`. The mouse grabbing + and novert settings can still be configured in the setup tool. + * There is no longer any option in the setup tool to specify a screen + resolution, since in full screen mode the game just runs at the + desktop resolution without changing screen modes. If necessary, the + config file options `fullscreen_width` and `fullscreen_height` can + be used to explicitly set a screen resolution. + * There is no longer a soft dependency on Zenity on Unix systems; the + SDL API is now used to display error dialogs. + * Joysticks are identified more precisely using GUID now. + * A new parameter, `-savedir` allows users to specify a directory from + which to load and save games. (thanks CapnClever) + * The midiproc code from Eternity Engine has been imported, improving + native MIDI playback on Windows and fixing a long-standing bug with + music volume adjustment (thanks AlexMax, Quasar). + * VGA “porch” emulation was added (thanks Jon). + * The codebase now compiles with OpenWatcom (thanks Stephen Finniss). + +### Doom + * The GOG install of Doom 3: BFG Edition is now detected (thanks chungy) + * A `-shorttics` command line parameter was added that simulates + recording a vanilla demo without actually recording a demo. + +### Hexen + * The CD audio option for music playback has been removed; the CD + playback API has been removed from SDL 2.0. However, it is possible + to use digital music packs as an alternative. + +### Strife + * `voices.wad` is now correctly loaded before PWADs (thanks + @Catoptromancy) + +### libtextscreen + * On OS X on machines with retina displays, text screens are rendered + using a high detail font. + * File selector widgets now look more visually distinctive. + * There is now a convenience widget for conditionally hiding widgets. + * Font handling was restructured to be based around PNG format fonts + which are converted during the build and can be more easily edited. + * Handling of code pages was cleaned up, so it is easier to change the + code to work with a different code page now. + * Lots of the UI code was changed to use UTF-8 strings. + * File extensions when using the Zenity file selector are now case + insensitive (thanks Jon). + +## 2.3.0 (2016-12-29) + +### General + * Bash completion scripts are included (thanks Fabian) + * The OS X launcher now supports the .lmp file format (thanks Jon) + * Pitch-shifting from early versions of Doom, Heretic, and Hexen. + is now supported (thanks Jon) + * Aspect ratio-corrected 1600×1200 PNGs are now written (thanks Jon) + * OPL emulation is more accurate (thanks Nuke.YKT) + * DMX bugs with GUS cards are now better emulated (thanks Nuke.YKT) + * The disk activity floppy disk icon is now shown (thanks Fabian, Jon) + * Checksum calculations are fixed on big endian systems, allowing + multiplayer games to be played in mixed little/big-endian + environments (thanks GhostlyDeath, njankowski) + * The NES30, SNES30, and SFC30 gamepads are detected and configured + automatically by the Setup tool. The automap can also be configured + to a joystick button (thanks Jon) + * The vanilla limit of 4046 lumps per WAD is now enforced (thanks + Jon, Quasar, Edward-san) + * Solidsegs overflow is emulated like in vanilla (thanks Quasar) + * Multiple capitalizations are now tried when searching for WAD files, + for convenience when running on case sensitive filesystems (thanks + Fabian). + * A new command line argument, `-strictdemos`, was added, to allow + more careful control over demo format extensions. Such extensions + are now forbidden in WAD files and warning messages are shown. + +### Build systems + * There is better compatibility with BSD Make (thanks R.Rebello) + * `./configure --with-PACKAGE` checks were repaired to behave + logically, rather than disabling the feature (thanks R.Rebello) + * Games are now installed to ${bindir} by default, eg. + /usr/local/bin, rather than /usr/local/games (thanks chungy) + * Visual Studio 2015 is now supported (thanks Azarien) + * SDL headers and libraries can now exist in the Microsoft Visual + Studio project directory (thanks Quasar) + * CodeBlocks projects were repaired by removing non-existent files + from the project files (thanks krystalgamer) + +### Doom + * Chex Quest’s level warp cheat (LEESNYDER##) now behaves more like + like the original EXE (thanks Nuke.YKT) + * It’s now possible to start multiplayer Chex Quest games. + * Freedoom: Phase 1 <= 0.10.1 can now be loaded with mods, with + -gameversion older than ultimate (thanks Fabian, chungy) + * The IWAD order preference for GOG.com installs matches vanilla + Final Doom: doom2, plutonia, tnt, doom (thanks chungy) + * There are better safety checks against write failures when saving + a game, such as when the directory is read-only (thanks + terrorcide) + * Versions 1.666, 1.7, and 1.8 are emulated (thanks Nuke.YKT) + * Crashes are now handled more gracefully when a linedef references + nonexistent sidedefs (thanks Fabian) + +### Heretic + * Map names were added for Episode 6, fixing a crash after completing + a level in this episode (thanks J.Benaim) + * Support for unlimited demo/savegames was added (thanks CapnClever) + * Demo support is expanded: `-demoextend` allows demos to last longer + than a single level; `-shortticfix` adjusts low-resolution turning + to match Doom’s handling, and there is now `-maxdemo` and `-longtics` + support (thanks CapnClever) + +### Hexen + * The MRJONES cheat code returns an identical string to vanilla, and + enables fully reproducible builds (thanks Fabian) + * An issue was fixed where the game crashed while killing the + Wraithverge in 64-bit builds (thanks J.Benaim) + * Support for unlimited demo/savegames was added (thanks CapnClever) + * Mouse buttons for strafe left/right and move backward were added, + as well as a “Double click acts as use” mouse option (thanks + CapnClever) + * Demo support is expanded: `-demoextend` allows demos to last longer + than a single level; `-shortticfix` adjusts low-resolution turning + to match Doom’s handling, and there is now `-maxdemo` and `-longtics` + support (thanks CapnClever) + +### Strife + * Support was added for automatic loading of the IWAD from the GOG.com + release of Strife: Veteran Edition on Windows (thanks chungy) + * Jumping can now be bound to a mouse button (thanks Gez) + * Gibbing logic was changed to match vanilla behavior (thanks Quasar) + * Several constants differences from vanilla were fixed (thanks + Nuke.YKT, Quasar) + * When using -iwad, voices.wad from the IWAD’s directory is prefered + over auto-detected DOS/Steam/GOG.com installs (thanks Quasar) + +### libtextscreen + * The API for creating and managing tables and columns was simplified. + * It’s now possible to cycle through tables with the tab key. + * Windows can now have multiple columns. + +## 2.2.1 (2015-09-10) + + Chocolate Doom has not seen a great deal of “stable” patch releases + in its history. While the development tree sees major new features + and changes, the purpose of this release, and hopefully others to + follow like it, is to repair some deficiencies that existed + in 2.2.0. + +### General + * Preferences for the OS X launcher are now stored with a unique + name to not conflict with other applications. (thanks + Xeriphas1994) + * Unix desktop entry files are now brought up to full desktop entry + specification compliance. (thanks chungy, Fabian) + * Unix AppData entries are now included, allowing software centers + to display detailed information about the engines. (thanks chungy) + * Partial XDG base directory specification compliance on Unix + systems now exist to search for IWAD paths. One benefit is that + $HOME/.local/share/games/doom is now a valid location to store and + automatically find IWADs. (thanks chungy) + +### Build systems + * The Microsoft Visual Studio build system was not fully functional + in 2.2.0 and has been fixed. (thanks Linguica) + * The autoconf build system checks for windres only for Windows + toolchains. Some Linux distributions mistakingly include the + program in their native toolchains. (thanks Fabian) + * A compiler hint for packed structs has been added, which otherwise + broke the games when built under recent GCC releases for + Windows. (thanks Fabian) + +### Doom + * The GOG.com releases of The Ultimate Doom, Doom II, and Final Doom + are now detected and supported on Windows. (thanks chungy) + * An integer overflow was used in spawn angle calculation, undefined + C behavior which broke with Clang optimization. (thanks David + Majnemer for insight) + +### Setup tool + * The help URL for the level warp menu now points to the proper wiki + page, rather than the multiplayer page. + * The manifest has been updated for Windows 10 compatibility. + (thanks chungy) + +## 2.2.0 (2015-06-09) + + * The Hexen four level demo IWAD is now supported. Thanks to Fabian + Greffrath for his careful investigation and emulation of the demo + game’s behavior in developing this. + * OPL music playback has been improved in a number of ways to match + the behavior of Vanilla Doom’s DMX library much more closely. OPL3 + playback is also now supported. Thanks go to Alexey Khokholov for + his excellent research into the Vanilla DMX library that enabled + these improvements. + * New gamepad configurations: + - PS4 DualShock 4 (thanks Matt “3nT” Davis). + - Xbox One controller on Linux (thanks chungy). + - “Super Joy Box 7” USB/PC gameport adapter. + * The Doom reload hack has been added back. See the wiki for more + context on this: http://doomwiki.org/wiki/Reload_hack + * The IWAD file from Strife: Veteran Edition is now detected + automatically (thanks chungy). + * It’s now possible to build outside of the source directory (thanks + Dave Murphy). + * MSVC project files were brought up to date (thanks dbrackett16). + * M_StringDuplicate() has been added as a safer replacement for + strdup() (thanks Quasar). M_StringCopy() now handles short buffers + more gracefully. + * The netgame discrepancy window is now dismissed by pressing enter + to proceed, not escape (thanks AXDOOMER). + * A couple of source files that were in the previous release and + were GPL3 have been replaced by GPL2 equivalents. Previous + releases that included these files should be retroactively + considered GPL3. + +### Bug fixes + * A long-standing bug that could cause every display frame to be + rendered twice was fixed (thanks Linguica, Harha, AXDOOMER). + * Lots of endianness fixes were integrated that were found by Ronald + Lasmanowicz during development of his Wii port of Chocolate Doom, + including a fix for a bug that could cause monsters to become + partially invisible. + * DeHackEd files without a newline character at the EOF are now + correctly parsed (thanks Fabian). + * An infinite loop that could occur in the weapon cycling code was + fixed (thanks raithe, Fabian). + * Mouse input triggered by cursor warp was fixed (thanks Super6-4). + * Loop tags in substitute music files are ignored if both of the + loop tags are equal to zero. This makes us consistent with other + source ports that support the tags. + * It’s now possible to more conveniently play back demo .lmp files + with names that end in the all-caps “.LMP” (thanks Ioan Chera). + * Some code that accessed memory after freeing it was fixed. Two new + parameters, -zonezero and -zonescan, were added to try to help + detect these cases. + * Mistaken assumptions about representations of booleans that + affected some ARM systems were fixed (thanks floppes). + * memcpy() uses on overlapping memory were changed to use memmove(), + fixing abort traps on OpenBSD (thanks ryan-sg). + * Hyphens in manpages were fixed (thanks chungy, Fabian). + * Lots of compiler build warnings were fixed (thanks Fabian). + +### Setup tool + * The setup tool now has help buttons for its various different + screens, which link to articles on the wiki that give more + information (thanks to chungy for helping to put the wiki pages + together). + * A fix was applied for a buffer overrun that could occur if the + user had lots of IWAD files installed (thanks Fabian). + * A crash related to username lookup was fixed. + * It’s now possible to connect via the setup tool to multiplayer + servers that are not listening on the default port (thanks + AXDOOMER). + +### Doom + * Sky transitions when emulating the id anthology version of the + Final Doom executable were fixed (thanks AXDOOMER, Fabian, + chungy). + * Structure fields in the stair-building functions were fixed to be + deterministic, fixing a desync in mm09-512.lmp (thanks Fabian). + +### Hexen + * A bug with texture names that had long names was fixed (thanks + ETTiNGRiNDER). + * Minotaur spawn time is now stored in little endian format, fixing + a bug that affected compatibility with Vanilla savegames on big + endian systems. + * Code that starts ACS scripts is no longer compiler-dependent. + +### Strife (all these are thanks to Quasar) + * Sound priority was changed, so that the ticking sound that Stalker + enemies make while active matches Vanilla behavior (thanks + GeoffLedak). + * Minor fixes to game behavior to match Vanilla, discovered during + development of Strife: Veteran edition. + * Behavior of descending stairs was fixed to match Vanilla. + * Inventory items beyond the 8-bit range are now allowed in + netgames. + * Automap behavior better matches Vanilla now. + * Multiplayer name changes were fixed. + * Sound origin behavior for switches was fixed. + * Teleport beacon behavior was fixed. + * Default Strife skill level and screen size were changed to match + Vanilla. + * Bug was fixed where Rowan would not always take Beldin’s ring. + * Totally-invisible objects are now displayed correctly, and a + Vanilla glitch with Shadow Acolytes is correctly emulated. + * The level name for MAP29 (Entity’s Lair) was fixed (thanks + chungy). + +### libtextscreen + * The main loop now exits immediately once all windows are closed + (thanks AXDOOMER). + * The large font is no longer selected based entirely on screen + size. + +## 2.1.0 (2014-10-22) + + Chocolate Doom now supports high-quality substitute music packs that + are used in place of the original MIDI music tracks. I’m hoping to + put together high-quality recordings of the music for all supported + games using the Roland SC-55 synthesizer originally used to compose + Doom’s music (thanks twipley and MusicallyInspired). + + Support for joysticks and gamepads has been significantly improved + in this version. Most gamepads should now work; if they don’t, + please report a bug. A number of gamepads are now automatically + detected and configured automatically; if yours is not, you can help + by sending in details. See the following page: + + http://www.chocolate-doom.org/wiki/index.php/Adding_your_gamepad + + OPL MIDI playback has been significantly improved, and problems with + most tracks should now be resolved. Multi-track MIDI files now play + back properly, MIDI tempo meta events are now supported and problems + with stuttering when playing certain tracks have been fixed. If you + still have problems with OPL playback, let me know. + + Also of note is that Chocolate Doom now has a document that + describes the philosophy of the project and the reasoning behind its + design (see PHILOSOPHY distributed with the source). + +### Other new features + * There is now a -dehlump command line parameter to load Dehacked + files contained inside WAD files (thanks Fabian Greffrath). + * PNG format screenshots are now supported, and there is a dedicated + key binding for taking screenshots without needing to always use + -devparm (thanks Fabian Greffrath). The PrintScreen key can be + used as a key binding (thanks AXDOOMER). + * There is now a config file variable (snd_maxslicetime_ms) to + control the sound buffer size, and the default is more precise to + reduce sound latency (thanks Holering). + * You can now use an external command for music playback (thanks + Holering). + * All games now detect if you’re tring to play using the wrong type + of IWAD (doom.wad with Hexen, etc.) and exit with a helpful error + message. A couple of users made this mistake after the 2.0 release + introduced support for the new games. + * The OS X app now associates with .hhe and .seh files. + * There is now a -nodes parameter that automatically starts a + netgame when a desired number of players have joined the game. + * There is now more extensive documentation about music + configuration (README.Music). + * On Linux, a GUI pop-up is used when the game quits with an error + to show the error message (thanks Willy Barro). + * There are now Linux .desktop files for all supported games (thanks + Mike Swanson). + * The -geometry command line parameter can now be used to specify + fullscreen or windowed modes, eg. -geometry 640x480w or -geometry + 1024x768f. (thanks Mike Swanson) + +### Doom + * Minor workarounds were added to allow the BFG Edition IWADs to be + used without crashing the game (thanks Fabian Greffrath). + * GUS patch files included with the BFG Edition are now + automatically detected. + * The “no fog on spawn west” Vanilla bug is now correctly emulated + (thanks xttl). + * Behavior of older versions of Doom back to v1.666 can now be + emulated. + * The new Freedoom IWAD names are now recognized and supported. + * Freedoom’s DEHACKED lump can now be parsed and is automatically + loaded when a Freedoom IWAD file is used (thanks Fabian + Greffrath). A new command line parameter, -nodeh, can be used to + prevent this from being loaded. + * Behavior of the M_EPI4 menu item is now correctly emulated based + on game version (thanks AXDOOMER). + * IDCLEV up to MAP40 is now supported, to match Vanilla (thanks + AXDOOMER). + * Level warping on the command line (-warp) to episodes higher than + 4 is possible, matching Vanilla behavior (thanks plumsinus). + * The -cdrom command line parameter writes savegames to the correct + directory now, matching Vanilla Doom behavior (thanks AXDOOMER). + * The Doom II mission pack to use can now be specified manually on + the command line with the -pack parameter (thanks chungy) + +### Heretic + * Weapon cycling keys for mouse and joystick were fixed (thanks + Sander van Dijk). + * The -timedemo parameter has been fixed, and -playdemo now handles + full paths correctly. + * A bug when panning the map was fixed (thanks Chris Fielder). + * A savegame bug where plat_t structures were not restored correctly + was fixed (thanks romeroyakovlev). + * Rebinding of the pause key was fixed (thanks Fabian Greffrath). + +### Hexen + * Music workarounds have been added so that it is possible to play + using the Mac version of the Hexen IWAD file. + * Weapon cycling keys for mouse and joystick were fixed (thanks + Sander van Dijk). + * The -timedemo parameter has been fixed, and -playdemo now handles + full paths correctly. + * There are now key bindings to allow the artifact keys to be + rebound (thanks Fabian Greffrath). + * Rebinding of the pause key was fixed (thanks Fabian Greffrath). + * Maximum level number was extended to MAP60, allowing multiplayer + games using the Deathkings add-on. + * The startup screen can now be aborted by pressing escape, like in + Vanilla. + * Desync when playing back DEMO1 was fixed (thanks alexey.lysiuk). + +### Strife + * “Show mission” key is configured properly in setup (thanks Sander + van Dijk). + * Default music volume level now matches Vanilla (thanks AXDOOMER). + * Teleport beacon allegiance was fixed to match Vanilla (thanks + Quasar). + * The stair building code now more closely matches Vanilla (thanks + Quasar). + * Torpedo weapon changing behavior now matches Vanilla (thanks + Quasar). + +### Cleanups + * The copyright headers at the top of all source files have been + vastly simplified. + * Unsafe string functions have been eliminated from the codebase. + Thanks to Theo de Raadt for calling out Chocolate Doom by name + (alongside many other packages) for still using unsafe functions + like strcpy: http://marc.info/?l=openbsd-tech&m=138733933417096 + * vldoor_e enum values are now namespaced to avoid potential + conflicts with POSIX standard functions. + +### Bug fixes + * WAD and Dehacked checksums are now sent to clients and checked + correctly when setting up netgames. + * A bug was fixed that caused sound not to work in multiplayer games + (thanks to everyone who reported this, and for AXDOOMER and Quasar + for help in fixing it). + * The “D_DDTBLU disease” bug affecting certain MIDI files has been + fixed (thanks plumsinus, Brad Harding and Quasar). + * Calculation of the -devparm “ticker” dots was fixed to match + Vanilla behavior (thanks _bruce_ and AXDOOMER). + * The PC speaker code now supports the full range of sound + frequencies (thanks Gez). + * Annoying “jumping” behavior when grabbing the mouse cursor was + fixed. + * The screen is now initialized at the native bit depth by default, + to avoid problems with systems that don’t handle 8-bit + screenbuffers very well any more. + * The --docdir argument to the configure script is now honored + (thanks Jan Engelhardt). + * Various issues with the build were fixed (thanks Jan Engelhardt + and Fabian Greffrath). + * Backwards parameters were fixed in the sound code (thanks + proteal). + * A crash was fixed when running fullscreen with the -2 parameter + (thanks Fabian Greffrath). + * A crash when using large values of snd_channels was fixed (thanks + AXDOOMER). + * A resource leak in the BSD PC speaker code was fixed (thanks + Edward-san). + * Windows resource files were fixed for Windows 7 (thanks Brad + Harding). + * A hard to trigger crash caused by a realloc() in the WAD code was + fixed (thanks Fabian Greffrath for debugging). + * A bug has been fixed where Chocolate Doom would stay running in + the background on Windows after quitting. SDL_Quit() is called now + (thanks johnsirett, Brad Harding, Quasar). + * String replacements in dehacked lumps can now be overridden if a + subsequent dehacked patch replaces the same string. + +### libtextscreen + * Clicking on scrollbars now jumps to the correct position (thanks + AXDOOMER). + * A use-after-free bug has been fixed where a click in a window that + causes the window to close could lead to a crash (thanks DuClare). + * Characters that are unprintable in the Extended ASCII chart are + just ignored when they’re typed, rather than appearing as an + upside-down question mark (thanks AXDOOMER). + +## 2.0.0 (2013-12-09) + + This is version 2.0 of Chocolate Doom! This new major version is + released to celeberate the 20th anniversary of the first release of + Doom in 1993. Happy Birthday Doom! + + This new version has some major changes compared to the 1.0 series: + + * The codebase now includes Chocolate Heretic and Chocolate + Hexen. These are based on the GPL source code released by Raven + Software. + * Also included is Chocolate Strife. This was developed through a + mammoth four year reverse engineering project conducted by James + “Quasar” Haley and Samuel “Kaiser” Villareal. The result is the + most accurate reproduction of Strife to date, including full demo + and savegame compatibility. See README.Strife for more + information. + +### Minor features that are nonetheless worth mentioning + * Chocolate Doom now includes a -statdump command line option, which + emulates the output of the statdump.exe tool. This is used to + implement a form of regression testing (statcheck) that directly + compares against the Vanilla behavior. + * Chocolate Heretic includes HHE patch file support, and I believe + is the first Heretic port to include this feature. + * GUS “pseudo-emulation” is now supported. This does not fully + emulate a GUS, but Doom’s DMXGUS lump can be used to generate a + Timidity configuration file that plays music using the GUS patch + set. + * The setup tool now includes a built-in server browser, for use + when selecting a server to join. + + Version 2.0 of Chocolate Doom has been in development for a long + time, and there have been many bugs fixed over this time, too many + to list here. Thanks to all the people who have tested it and + diligently reported bugs over this time, and to all the people who + have tested the beta releases over the past couple of months. Your + contributions have been essential and invaluable. + +## 1.7.0 (2012-06-09) + + * Fixed gnome-screensaver desktop file (thanks Rahul Sundaram). + * Updated COPYING to current version of GPL2 (thanks Rahul + Sundaram). + * Running servers now re-resolve the address of the master server + occasionally, to adapt to DNS address changes. + * Error dialog is no longer shown on OS X when running from the + console. + * The Makefiles no longer use GNU make extensions, so the package + builds on OpenBSD. + * There is now an OPL MIDI debug option (-opldev), useful for when + developing GENMIDI lumps. + * A workaround for SDL mouse lag is now only used on Windows (where + it is needed), and not on other systems. This fixes Chocolate Doom + on AmigaOS (thanks Timo Sievänen). + * UTF-8 usernames are supported, and Windows usernames with + non-ASCII characters are now supported (thanks AXDOOMER). + +### Compatibility + * Palette accuracy is reduced to 6 bits per channel, to more + accurately emulate the PC VGA hardware (thanks GhostlyDeath). + * Fixed teleport behavior when emulating the alternate Final Doom + executable (-gameversion final2) (thanks xttl). + +### Bugs fixed + * Fixed weapon cycling keys when playing in Shareware Doom and using + the IDKFA cheat (thanks AXDOOMER). + * Fixed the default mouse buttons in the setup tool (thanks + AXDOOMER). + * Chat macros now work when vanilla_keyboard_mapping is turned off. + * Default chat macros were fixed in the setup tool. + * Ping time calculation was fixed for LAN search, and made more + accurate for all searches. + * Fixed bug with detection of IWAD type by filename (thanks mether). + +### libtextscreen + * There is now limited UTF-8 text support in the textscreen library, + used in the label and input box widgets. + * Scroll bar behavior was fixed (thanks AXDOOMER). + * Input boxes stop editing and save when they lose their focus, + correcting a previous counterintuitive behavior (thanks Twelve). + * The numeric keypad now works properly when entering text values + (thanks Twelve). + +## 1.6.0 (2011-05-17) + + * The instructions in the INSTALL file are now customized for + different platforms, and each binary package contains a version + with instructions specific to the platform that it is targetting. + This should help to avoid confusion that some users have reported + experiencing. + * The display settings window in the setup tool has been reorganised + to a better arrangement. + * It is now possible to load .lmp files (and play back demos) with + long filenames (thanks blzut3). + * In the setup tool, it is now possible to hold down shift when + changing key/mouse/joystick bindings to prevent other bindings to + the same key from being cleared (thanks myk). + * The joystick menu in the setup tool now has a test button (thanks + AXDOOMER). + * Specifying the -privateserver option implies -server (thanks + Porsche Monty). + * The Mac OS X .dmg package now has a background and looks generally + more polished. + * In Mac OS X, it is now possible to simply double click an IWAD + file in the Finder to configure its location within the launcher. + * Freedesktop.org desktop files are now installed for Doom and the + setup tool, which will appear in the main menu on desktop + environments such as Gnome and KDE (thanks Adrián Chaves + Fernández). + * The Chex Quest dehacked patch (chex.deh) will now be detected if + it is in the same directory as the IWAD file. + +### Compatibility + * Added support for the alternate version of the Final Doom + executable included in some later versions of the Id Anthology. + This version fixed the demo loop crash that occurred with the + “original” Final Doom executable. + + This executable can be selected on the command line with + -gameversion final2. It has been made the default when playing + with the Final Doom IWADs (the original behavior can be selected + with -gameversion final). (thanks Porsche Monty, Enjay). + * Very short sound effects are not played, to better emulate the + behavior of DMX in Vanilla Doom (thanks to Quasar for help in + investigating this). + * The null sector dereference emulation code has been imported from + Prboom+ - this fixes a desync with CLNJ-506.LMP (thanks entryway). + * The IDMUS cheat doesn’t work when emulating the v1.9 executable + (thanks AXDOOMER). + +### Bugs fixed + * Menu navigation when using joystick/joypad (thanks AXDOOMER). + * For configuration file value for shift keys, use scan code for + right shift, not left shift (thanks AXDOOMER). + * Default joystick buttons for the setup tool now match Vanilla + (thanks twipley). + * Visual Studio project files work again (thanks GhostlyDeath). + * The default sfx/music volume set by the setup tool is now 8 + instead of 15, matching the game itself. (thanks AXDOOMER). + * Weapon cycling from the shotgun to the chaingun in Doom 1 now + works properly (thanks AXDOOMER). + * MIDI playback that locked up when using an empty MUS / MIDI file + (thanks AXDOOMER). + * Default sampling rate used by setup tool changed to 44100Hz, to + match the game default (thanks AXDOOMER). + * Cheat codes and menu hot keys now work when shift is held down or + capslock turned on (thanks AXDOOMER). + +### libtextscreen + * The background on GUI controls now lights up when hovering over + them, so that it is more obvious what you are selecting. + * It is now possible to type a “+” in input boxes (thanks AXDOOMER). + * It is possible to use the mouse wheel to scroll through scroll + panes. + * Clicking on scroll bars now moves the scroll handle to a matching + location. + * Clicking outside a dropdown list popup window now dismisses the + window. + * Window hotkeys that are an alphabetical letter now work when shift + is held down or capslock turned on (thanks AXDOOMER). + +## 1.5.0 (2011-01-02) + + Big changes in this version: + + * The DOSbox OPL emulator (DBOPL) has been imported to replace the + older FMOPL code. The quality of OPL emulation is now therefore + much better. + * The game can now run in screen modes at any color depth (not just + 8-bit modes). This is mainly to work around problems with Windows + Vista/7, where 8-bit color modes don’t always work properly. + * Multiplayer servers now register themselves with an Internet + master server. Use the -search command line parameter to find + servers on the Internet to play on. You can also use DoomSeeker + (http://skulltag.net/doomseeker/) which supports this + functionality. + * When running in windowed mode, it is now possible to dynamically + resize the window by dragging the window borders. + * Names can be specified for servers with the -servername command + line parameter. + * There are now keyboard, mouse and joystick bindings to cycle + through available weapons, making play with joypads or mobile + devices (ie. without a proper keyboard) much more practical. + * There is now a key binding to change the multiplayer spy key + (usually F12). + * The setup tool now has a “warp” button on the main menu, like + Vanilla setup.exe (thanks Proteh). + * Up to 8 mouse buttons are now supported (including the + mousewheel). + * A new command line parameter has been added (-solo-net) which can + be used to simulate being in a single player netgame. + * There is now a configuration file parameter to set the OPL I/O + port, for cards that don’t use port 0x388. + * The Python scripts used for building Chocolate Doom now work with + Python 3 (but also continue to work with Python 2) (thanks arin). + * There is now a NOT-BUGS file included that lists some common + Vanilla Doom bugs/limitations that you might encounter (thanks to + Sander van Dijk for feedback). + +### Compatibility + * The -timer and -avg options now work the same as Vanilla when + playing back demos (thanks xttl) + * A texture lookup bug was fixed that caused the wrong sky to be + displayed in Spooky01.wad (thanks Porsche Monty). + * The HacX v1.2 IWAD file is now supported, and can be used + standalone without the need for the Doom II IWAD (thanks atyth). + * The I_Error function doesn’t display “Error:” before the error + message, matching the Vanilla behavior. “Error” has also been + removed from the title of the dialog box that appears on Windows + when this happens. This is desirable as not all such messages are + actually errors (thanks Proteh). + * The setup tool now passes through all command line arguments when + launching the game (thanks AXDOOMER). + * Demo loop behavior (ie. whether to play DEMO4) now depends on the + version being emulated. When playing Final Doom the game will + exit unexpectedly as it tries to play the fourth demo - this is + Vanilla behaviour (thanks AXDOOMER). + +### Bugs fixed + * A workaround has been a bug in old versions of SDL_mixer (v1.2.8 + and earlier) that could cause the game to lock up. Please upgrade + to a newer version if you haven’t already. + * It is now possible to use OPL emulation at 11025Hz sound sampling + rate, due to the new OPL emulator (thanks Porsche Monty). + * The span renderer function (used for drawing floors and ceilings) + now behaves the same as Vanilla Doom, so screenshots are + pixel-perfect identical to Vanilla Doom (thanks Porsche Monty). + * The zone memory system now aligns allocated memory to 8-byte + boundaries on 64-bit systems, which may fix crashes on systems + such as sparc64 (thanks Ryan Freeman and Edd Barrett). + * The configure script now checks for libm, fixing compile problems + on Fedora Linux (thanks Sander van Dijk). + * Sound distortion with certain music files when played back using + OPL (eg. Heretic title screen). + * Error in Windows when reading response files (thanks Porsche + Monty, xttl, Janizdreg). + * Windows Vista/7 8-bit color mode issues (the default is now to run + in 32-bit color depth on these versions) (thanks to everybody who + reported this and helped test the fix). + * Screen borders no longer flash when running on widescreen + monitors, if you choose a true-color screen mode (thanks exp(x)). + * The controller player in a netgame is the first player to join, + instead of just being someone who gets lucky. + * Command line arguments that take an option now check that an + option is provided (thanks Sander van Dijk). + * Skill level names in the setup tool are now written the same as + they are on the in-game “new game” menu (thanks AXDOOMER). + * There is no longer a limit on the lengths of filenames provided to + the -record command line parameter (thanks AXDOOMER). + * Window title is not lost in setup tool when changing video driver + (thanks AXDOOMER). + +### libtextscreen + * The font used for the textscreen library can be forced by setting + the TEXTSCREEN_FONT environment variable to “small” or “normal”. + * Tables or scroll panes that don’t contain any selectable widgets + are now themselves not selectable (thanks Proteh). + * The actions displayed at the bottom of windows are now laid out in + a more aesthetically pleasing way. + +## 1.4.0 (2010-07-10) + + The biggest change in this version is the addition of OPL emulation. + This emulates Vanilla Doom’s MIDI playback when using a Yamaha OPL + synthesizer chip, as was found on SoundBlaster compatible cards. + + A software OPL emulator is included as most modern computers do not + have a hardware OPL chip any more. If you do have one, you can + configure Chocolate Doom to use it; see README.OPL. + + The OPL playback feature is not yet perfect or 100% complete, but is + judged to be good enough for general use. If you find music that + does not play back properly, please report it as a bug. + +### Other changes + * The REJECT overflow emulation code from PrBoom+ has been + imported. This fixes demo desync on some demos, although + others will still desync. + * Warnings are now generated for invalid dehacked replacements of + printf format strings. Some potential buffer overflows are also + checked. + * The installation instructions (INSTALL file) have been clarified + and made more platform-agnostic. + * The mouse is no longer warped to the center of the screen when the + demo sequence advances. + * Key bindings can now be changed for the demo recording quit key + (normally ‘q’) and the multiplayer messaging keys (normally ‘t’, + ‘g’, ‘i’, ‘b’ and ‘r’). + +## 1.3.0 (2010-02-10) + + * Chocolate Doom now runs on Windows Mobile/Windows CE! + * It is possible to rebind most/all of the keys that control the + menu, shortcuts, automap and weapon switching. The main reason + for this is to support the Windows CE port and other platforms + where a full keyboard may not be present. + * Chocolate Doom now includes a proper Mac OS X package; it is no + longer necessary to compile binaries for this system by hand. The + package includes a simple graphical launcher program and can be + installed simply by dragging the “Chocolate Doom” icon to the + Applications folder. (thanks to Rikard Lang for extensive testing + and feedback) + * The video mode auto-adjust code will automatically choose windowed + mode if no fullscreen video modes are available. + * The zone memory size is automatically reduced on systems with a + small amount of memory. + * The “join game” window in the setup tool now has an option to + automatically join a game on the local network. + * Chocolate Doom includes some initial hacks for compiling under + SDL 1.3. + * Recent versions of SDL_mixer include rewritten MIDI code on Mac OS + X. If you are using a version of SDL_mixer with the new code, + music will now be enabled by default. + * Windows Vista and Windows 7 no longer prompt for elevated + privileges when running the setup tool (thanks hobbs and MikeRS). + * The Windows binaries now have better looking icons (thanks + MikeRS). + * Magic values specified using the -spechit command line parameter + can now be hexadecimal. + * DOOMWADDIR/DOOMWADPATH can now specify the complete path to IWAD + files, rather than the path to the directory that contains them. + * When recording shorttics demos, errors caused by the reduced + turning resolution are carried forward, possibly making turning + smoother. + * The source tarball can now be used to build an RPM package: + rpmbuild -tb chocolate-doom-VER.tar.gz + +### Compatibility + * The A_BossDeath behavior in v1.9 emulation mode was fixed (thanks + entryway) + * The “loading” disk icon is drawn more like how it is drawn in + Vanilla Doom, also fixing a bug with chook3.wad. + * Desync on 64-bit systems with ep1-0500.lmp has (at long last) been + fixed (thanks exp(x)). + * Donut overrun emulation code imported from Prboom+ (thanks + entryway). + * The correct level name should now be shown in the automap for + pl2.wad MAP33 (thanks Janizdreg). + * In Chex Quest, the green radiation suit colormap is now used + instead of the red colormaps normally used when taking damage or + using the berserk pack. This matches Vanilla chex.exe behavior + (thanks Fuzztooth). + * Impassible glass now displays and works the same as in Vanilla, + fixing wads such as OTTAWAU.WAD (thanks Never_Again). + +### Bugs fixed + * Memory-mapped WAD I/O is disabled by default, as it caused various + issues, including a slowdown/crash with Plutonia 2 MAP23. It can + be explicitly re-enabled using the “-mmap” command line parameter. + * Crash when saving games due to the ~/.chocolate-doom/savegames + directory not being created (thanks to everyone who reported + this). + * Chocolate Doom will now run under Win95/98, as the + SetProcessAffinityMask function is looked up dynamically. + * Compilation under Linux with older versions of libc will now work + (the semantics for sched_setaffinity were different in older + versions) + * Sound clipping when using libsamplerate was improved (thanks David + Flater) + * The audio buffer size is now calculated based on the sample rate, + so there is not a noticeable delay when using a lower sample rate. + * The manpage documentation for the DOOMWADPATH variable was fixed + (thanks MikeRS). + * Compilation with FEATURE_MULTIPLAYER and FEATURE_SOUND disabled + was fixed. + * Fixed crash when using the donut special type and the joining + linedef is one sided (thanks Alexander Waldmann). + * Key settings in a configuration file that are out of range do not + cause a crash (thanks entryway). + * Fix ear-piercing whistle when playing the MAP05 MIDI music using + timidity with EAWPATS (thanks entryway / HackNeyed). + +### libtextscreen + * There is now a second, small textscreen font, so that the ENDOOM + screen and setup tool can be used on low resolution devices + (eg. PDAs/embedded devices) + * The textscreen library now has a scrollable pane widget. Thanks to + LionsPhil for contributing code to scroll up and down using the + keyboard. + * Doxygen documentation was added for the textscreen library. + +## 1.2.1 (2008-12-10) + + This version just fixes a crash at the intermission screen when + playing Doom 1 levels. + +## 1.2.0 (2008-12-10) + + Happy 15th Birthday, Doom! + + * Chocolate Doom now has an icon that is not based on the + proprietary Doom artwork. + * There is now memory-mapped WAD I/O support, which should be useful + on some embedded systems. + * Chex quest emulation support is now included, although an + auxiliary dehacked patch is needed (chexdeh.zip in the idgames + archive). + +### Compatibility + * The armor class is always set to 2 when picking up a megasphere + (thanks entryway). + * The quit screen prompts to quit “to dos” instead of just to quit + (thanks MikeRS) + * The “dimensional shambler” quit message was fixed. + * Fix crash related to A_BFGSpray with NULL target when using + dehacked patches - discovered with insaned2.deh (thanks CSonicGo) + * NUL characters are stripped from dehacked files, to ensure correct + behavior with some dehacked patches (eg. the one with portal.wad). + +### Bugs fixed + * “Python Image Library” should have been “Python Imaging Library” + (thanks exp(x)). + * The setup tool should no longer ask for elevated permissions on + Windows Vista (this fix possibly may not work). + * The application icon is set properly when running under Windows XP + with the “Luna” theme. + * Fix compilation under Cygwin to detect libraries and headers from + the correct environment. + * The video code does not try to read SDL events before SDL has been + properly initialised - this was causing problems with some older + versions of SDL. + +## 1.1.1 (2008-04-20) + + The previous release (v1.1.0) included a bug that broke compilation + when libsamplerate support was enabled. The only change in this + version is to fix this bug. + +## 1.1.0 (2008-04-19) + + * The video mode code has been radically restructured. The video + mode is now chosen by directly specifying the mode to use; the + scale factor is then chosen to fit the screen. This is helpful + when using widescreen monitors (thanks Linguica) + * MSVC build project files (thanks GhostlyDeath and entryway). + * Unix manpage improvements; the manpage now lists the environment + variables that Chocolate Doom uses. Manpages have been added for + chocolate-setup and chocolate-server, from the versions for the + Debian Chocolate Doom package (thanks Jon Dowland). + * INSTALL file with installation instructions for installing + Chocolate Doom on Unix systems. + * Support for high quality resampling of sound effects using + libsamplerate (thanks David Flater). + * A low pass filter is applied when doing sound resampling in an + attempt to filter out high frequency noise from the resampling + process. + * R_Main progress box is not displayed if stdout is a file (produces + cleaner output). + * Client/server version checking can be disabled to allow different + versions of Chocolate Doom to play together, or Chocolate Doom + clients to play with Strawberry Doom clients. + * Unix manpages are now generated for the Chocolate Doom + configuration files. + * The BSD PC speaker driver now works on FreeBSD. + +### Compatibility + * Use the same spechits compatibility value as PrBoom+, for + consistency (thanks Lemonzest). + * The intercepts overrun code has been refactored to work on big + endian machines. + * The default startup delay has been set to one second, to allow + time for the screen to settle before starting the game (some + monitors have a delay before they come back on after changing + modes). + * If a savegame buffer overrun occurs, the savegame does not get + saved and existing savegames are not overwritten (same behaviour + as Vanilla). + +### Bugs fixed + * Desync with STRAIN demos and dehacked Misc values not being set + properly (thanks Lemonzest) + * Don’t grab the mouse if the mouse is disabled via -nomouse or + use_mouse in the configuration file (thanks MikeRS). + * Don’t center the mouse on startup if the mouse is disabled (thanks + Siggi). + * Reset the palette when the window is restored to clear any screen + corruption (thanks Catoptromancy). + * mus2mid.c should use `MEM_SEEK_SET`, not `SEEK_SET` (thanks + Russell) + * Fast/Respawn options were not being exchanged when starting + netgames (thanks GhostlyDeath). + * Letterbox mode is more accurately described as “pillarboxed” or + “windowboxed” where appropriate (thanks MikeRS) + * Process affinity mask is set to 1 on Windows, to work around a bug + in SDL_mixer that can cause crashes on multi-core machines (thanks + entryway). + * Bugs in the joystick configuration dialog in the setup tool have + been fixed. + +## 1.0.0 (2007-12-10) + + This release is dedicated to Dylan “Toke” McIntosh, who was + tragically killed in a car crash in 2006. I knew Dylan from IRC and + the Doomworld forums for several years, and he had a deep passion + for this game. He was also a huge help for me while developing + Chocolate Doom, as he helped point out a lot of small quirks in + Vanilla Doom that I didn’t know about. His death is a great loss. + RIP Toke. + + This is the first release to reach full feature parity with Vanilla + Doom. As a result, I have made this version 1.0.0, so Chocolate + Doom is no longer beta! + +### Big new features + * Multiplayer! This version includes an entirely new multiplayer + engine, based on a packet server architecture. I’d like to thank + joe, pritch, Meph and myk, and everyone else who has helped test + the new code for their support, feedback and help in testing this. + The new code still needs more testing, and I’m eager to hear any + feedback on this. + * A working setup tool. This has the same look and feel as the + original setup.exe. I hope people like it! Note that it has some + advantages over the original setup.exe - for example, you can use + the mouse. + +### Other new features + * New mus conversion code thanks to Ben Ryves. This converts the + Doom .mus format to .mid a lot better. As one example, tnt.wad + Map02 is now a lot closer to how Vanilla says. Also, the music on + the deca.wad titlescreen now plays! + * x3, x4 and x5 display scale (thanks to MikeRS for x5 scale). + * Fullscreen “letterbox” mode allows Chocolate Doom to run on + machines where 1.6:1 aspect ratio modes are unavailable + (320x200/640x400). The game runs in 320x240/640x480 instead, with + black borders. The system automatically adjusts to this if closer + modes are unavailable. + * Aspect ratio correction: you can (also) run at 640x480 without + black borders at the top and bottom of the screen. + * PC speaker sound effect support. Chocolate Doom can output real + PC speaker sounds on Linux, or emulate a PC speaker through the + sound card. + * Working three-screen mode, as seen in early versions of Doom! To + test this out, put three computers on a LAN and type: + + chocolate-doom -server + chocolate-doom -autojoin -left + chocolate-doom -autojoin -right + + * Allow a delay to be specified on startup, to allow the display to + settle after changing modes before starting the game. + * Allow the full path and filename to be specified when loading + demos: It is now possible to type “chocolate-doom -playdemo + /tmp/foo.lmp” for example. + * Savegames are now stored in separate directories depending on the + IWAD: eg. the savegames for Doom II are stored in a different + place to those for Doom I, Final Doom, etc. (this does not affect + Windows). + * New mouse acceleration code works based on a threshold and + acceleration. Hopefully this should be closer to what the DOS + drivers do. There is a ‘test’ feature in the setup tool to help + in configuring this. + * New “-nwtmerge” command line option that emulates NWT’s “-merge” + option. This allows TiC’s Obituary TC to be played. + * The ENDOOM screen no longer closes automatically, you have to + click the window to make it go away. + * Spechit overrun fixes and improvements. Thanks to entryway for + his continued research on this topic (and because I stole your + improvements :-). Thanks to Quasar for reporting a bug as well. + * Multiple dehacked patches can be specified on the command line, in + the same way as with WADs - eg. -deh foo.deh bar.deh baz.deh. + * Default zone memory size increased to 16MB; this can be controlled + using the -mb command-line option. + * It is now possible to record demos of unlimited length (by + default, the Vanilla limit still applies, but it can now be + disabled). + * Autoadjusting the screen mode can now be disabled. + * On Windows, the registry is queried to detect installed versions + of Doom and automatically locate IWAD files. IWADs installed + through Steam are also autodetected. + * Added DOOMWADPATH that can be used like PATH to specify multiple + locations in which to search for IWAD files. Also, “-iwad” is now + enhanced, so that eg. “-iwad doom.wad” will now search all IWAD + search paths for “doom.wad”. + * Improved mouse tracking that should no longer lag. Thanks to + entryway for research into this. + * The SDL driver can now be specified in the configuration file. + The setup tool has an option on Windows to select between DirectX + and windib. + * Joystick support. + * Configuration file option to change the sound sample rate. + * More than three mouse buttons are now supported. + +### Portability improvements + * Chocolate Doom now compiles and runs cleanly on MacOS X. Huge + thanks go to Insomniak who kindly gave me an account on his + machine so that I could debug this remotely. Big thanks also go + to athanatos on the Doomworld forums for his patience in testing + various ideas as I tried to get Chocolate Doom up and running on + MacOS. + * Chocolate Doom now compiles and runs natively on AMD64. + * Chocolate Doom now compiles and runs on Solaris/SPARC, including + the Sun compiler. Thanks to Mike Spooner for some portability + fixes. + * Improved audio rate conversion, so that sound should play properly + on machines that don’t support low bitrate output. + +### Compatibility fixes + * Check for IWADs in the same order as Vanilla Doom. + * Dehacked code will now not allow string replacements to be longer + than those possible through DOS dehacked. + * Fix sound effects playing too loud on level 8 (thanks to myk for + his continued persistence in getting me to fix this) + * Save demos when quitting normally - it is no longer necessary to + press ‘q’ to quit and save a demo. + * Fix spacing of -devparm mode dots. + * Fix sky behavior to be the same as Vanilla Doom - when playing in + Doom II, the skies never change from the sky on the first level + unless the player loads from a savegame. + * Make -nomouse and config file use_mouse work again. + * Fix the -nomusic command-line parameter. Make the snd_sfxdevice + snd_musicdevice values in the configuration file work, so that it + is possible to disable sound, as with Vanilla. + * Repeat key presses when the key is held down (this is the Vanilla + behavior) - thanks to Mad_Mac for pointing this out. + * Don’t print a list of all arguments read from response files - + Vanilla doesn’t do this. + * Autorun only when joyb_speed >= 10, not >= 4. Thanks to Janizdreg + for this. + * Emulate a bug in DOS dehacked that can overflow the dehacked frame + table and corrupt the weaponinfo table. Note that this means + Batman Doom will no longer play properly (identical behavior to + Vanilla); vbatman.deh needs to also be applied to fix it. (Thanks + grazza) + * Allow dehacked 2.3 patches to be loaded. + * Add more dehacked string replacements. + * Compatibility option to enable or disable native key mappings. + This means that people with non-US keyboards can decide whether to + use their correct native mapping or behave like Vanilla mapping + (which assumes all keyboards are US). + * Emulate overflow bug in P_FindNextHighestFloor. Thanks to + entryway for the fix for this. + * Add -netdemo command line parameter, for playing back netgame + demos recorded with a single player. + * The numeric keypad now behaves like Vanilla Doom does. + * Fix some crashes when loading from savegames. + * Add intercepts overrun emulation from PrBoom-plus. Thanks again + to entryway for his research on this subject. + * Add playeringame overrun emulation. + +### Bugs fixed + * Fix crash when starting new levels due to the intermission screen + being drawn after the WI_ subsystem is shut down (thanks pritch + and joe) + * Catch failures to initialise sound properly, and fail gracefully. + * Fix crasher in 1427uv01.lmp (thanks ultdoomer) + * Fix crash in udm1.wad. + * Fix crash when loading a savegame with revenant tracer missiles. + * Fix crash when loading a savegame when a mancubus was in the + middle of firing. + * Fix Doom 1 E1-3 intermission screen animations. + * Fix loading of dehacked “sound” sections. + * Make sure that modified copyright banners always end in a newline + - this fixes a bug with av.wad (thanks myk) + * Added missing quit message (“are you sure you want to quit this + great game?”). + * Fix when playing long sound effects - the death sound in + marina.wad now plays properly, for example. + * Fix buffer overrun on the quicksave prompt screen that caused a + mysterious cycling character to appear. + * IDCLEV should not work in net games (thanks Janizdreg) + * Stop music playing at the ENDOOM screen. + * Fix sound sample rate conversion crash. + * Fix “pop” heard at the end of sound effects. + * Fix crash when playing long sounds. + * Fix bug with -timedemo accuracy over multi-level demos. + * Fix bug with the automap always following player 1 in multiplayer + mode (thanks Janizdreg). + +## 0.1.4 (2006-02-13) + + * NWT-style merging command line options (allows Mordeth to be played) + * Unix manpage (thanks Jon Dowland) + * Dehacked improvements/fixes: + * Allow changing the names of graphic lumps used in menu, status bar + intermission screen, etc. + * Allow changing skies, animated flats + textures + * Allow changing more startup strings. + * Allow text replacements on music + sfx lump names + * Fix for plutonia map12 crash. + * Fix bug with playing long sfx at odd sample rates. + * Big Endian fixes (for MacOS X). Thanks to athanatos for helping + find some of these. + * Install into /usr/games, rather than /usr/bin (thanks Jon Dowland) + +## 0.1.3 (2006-01-20) + + * Imported the spechit overrun emulation code from prboom-plus. Thanks to + Andrey Budko for this. + * New show_endoom option in the chocolate-doom.cfg config file allows + the ENDOOM screen to be disabled. + * Chocolate Doom is now savegame-compatible with Vanilla Doom. + + * Fixes for big endian machines (thanks locust) + * Fixed the behavior of the dehacked maximum health setting. + * Fix the “-skill 0” hack to play without any items (thanks to Janizdreg + for pointing out that this was nonfunctional) + * Fix playing of sounds at odd sample rates (again). Sound effects + at any sample rate now play, but only sounds with valid headers. + This is the *real* way Vanilla Doom behaves. Thanks to myk for + pointing out the incorrect behavior. + +## 0.1.2 (2005-10-29) + + * Silence sounds at odd sample rates (rather than bombing out); this + is the way Vanilla Doom behaves. + * Handle multiple replacements of the same sprite in a PWAD. + * Support specifying a specific version to emulate via the command line + (-gameversion) + * Fix help screen orderings and skull positions. Behave exactly as + the original executables do. + +## 0.1.1 (2005-10-18) + + * Display startup “banners” if they have been modified through + dehacked. + * Dehacked “Misc” section support. + +### Bugs fixed + * Doom 1 skies always using Episode 1 sky + * Crash when switching applications while running fullscreen + * Lost soul bounce logic (do not bounce in Registered/Shareware) + * Mouse buttons mapped incorrectly (button 1 is right, 2 is middle) + * Music not pausing when game is paused, when using SDL_mixer’s + native MIDI playback. + * Pink icon on startup (palette should be fully set before anything is + loaded) + +## 0.1.0 (2005-10-09) + + * Dehacked support + * WAD merging for TCs + * ENDOOM display + * Fix bug with invalid MUS files causing crashes + * Final Doom fixes + +## 0.0.4 (2005-09-27) + + * Application icon and version info included in Windows .exe files + * Fixes for non-x86 architectures + * Fix uac_dead.wad (platform drop on e1m8 should occur when all + bosses die, not just barons) + * Fix “loading” icon to work for all graphics modes + +## 0.0.3 (2005-09-17) + + * Mouse acceleration code to emulate the behaviour of old DOS mouse + drivers (thanks to Toke for information about this and + suggestions) + * Lock surfaces properly when we have to (fixes crash under + Windows 98) + +## 0.0.2 (2005-09-13) + + * Remove temporary MIDI files generated by sound code. + * Fix sound not playing at the right volume + * Allow alt-tab away while running in fullscreen under Windows + * Add second configuration file (chocolate-doom.cfg) to allow + chocolate-doom specific settings. + * Fix switches not changing in Ultimate Doom + +## 0.0.1 (2005-09-07) + + First beta release diff --git a/games/NXDoom/NOT-BUGS.md b/games/NXDoom/NOT-BUGS.md new file mode 100644 index 00000000000..1ef97e3df73 --- /dev/null +++ b/games/NXDoom/NOT-BUGS.md @@ -0,0 +1,149 @@ +The aim of Chocolate Doom is to behave as closely to Vanilla Doom as +possible. As a result, you may experience problems that you would +also experience when using Vanilla Doom. These are not “bugs” as +Chocolate Doom is behaving as intended. + +This is not intended to be a comprehensive list of Vanilla Doom bugs. +For more information, consult the “engine bugs” page of the Doom Wiki. + +## Game exits after title screen with message about game version + +The game may exit after the title screen is shown, with a message like +the following: + + Demo is from a different game version! + (read 2, should be 109) + + *** You may need to upgrade your version of Doom to v1.9. *** + See: https://www.doomworld.com/classicdoom/info/patches.php + This appears to be v1.0/v1.1/v1.2. + +This usually indicates that your IWAD file that you are using to play +the game (usually named doom.wad or doom2.wad) is out of date. +Chocolate Doom only supports versions 1.666 through 1.9. + +To fix the problem, you must upgrade your IWAD file, preferably +to 1.9. The URL in the message has downloadable upgrade patches that +you can use to upgrade. + +## Game exits in demo loop when playing Final Doom + +When playing with the Final Doom IWAD files (tnt.wad, plutonia.wad), +if you leave the game at the title screen to play through the demo +loop, it will eventually exit with the following error message: + + W_GetNumForName: demo4 not found! + +This is the same behavior as the Vanilla executables that were +bundled with Final Doom. When Ultimate Doom was developed, a fourth +demo was added to the demo loop, and this change was retained in the +Final Doom version of the executable. However, the Final Doom IWADs +do not include a fourth demo, so the game crashes. + +An alternate version of Final Doom was included in the Id Anthology +boxed set, and this version of the game fixed this bug. However, this +version also changes the teleport behavior, so the default is to +emulate the most commonly distributed version of the game. To use +the alternate version, run with: + + chocolate-doom -gameversion final2 + +## Game exits when accessing the options menu + +The game may exit with the message “Bad V_DrawPatch” when accessing +the options menu, if you have your mouse sensitivity set high. + +The Doom options menu has a slider that allows the mouse sensitivity +to be controlled; however, it has only a very limited range. It is +common for experienced players to set a mouse sensitivity that is much +higher than what can be set via the options menu. The setup program +allows a larger range of values to be set. + +However, setting very high sensitivity values causes the game to exit +when accessing the options menu under Vanilla Doom. Because Chocolate +Doom aims to emulate Vanilla Doom as closely as possible, it does the +same thing. + +One solution to the problem is to set a lower mouse sensitivity. +Alternatively, all of the settings in the options menu can be +controlled through Doom’s key bindings anyway: + +Option | Key +---------------------------|----- +End game | F7 +Messages on/off | F8 +Graphic detail high/low | F5 +Screen size smaller/larger | -/+ +Sound volume menu | F4 + +## Game exits with “Savegame buffer overrun” when saving the game + +If you are playing on a particularly large level, it is possible that +when you save the game, the game will quit with the message “Savegame +buffer overrun”. + +Vanilla Doom has a limited size memory buffer that it uses for saving +games. If you are playing on a large level, the buffer may be too +small for the entire savegame to fit. Chocolate Doom allows the limit +to be disabled: in the setup tool, go to the “compatibility” menu and +disable the “Vanilla savegame limit” option. + +If this error happens to you, your game has not been lost! A file +named temp.dsg is saved; rename this to doomsav0.dsg to make it appear +in the first slot in the “load game” menu. (On Unix systems, you will +need to look in the .chocolate-doom/savegames directory in your home +directory) + +## Game ends suddenly when recording a demo + +If you are recording a very long demo, the game may exit suddenly. +Vanilla Doom has a limited size memory buffer that it uses to save the +demo into. When the buffer is full, the game exits. You can tell if +this happens, as the demo file will be around 131,072 bytes in size. + +You can work around this by using the -maxdemo command line parameter +to specify a larger buffer size. Alternatively, the limit can be +disabled: in the setup tool, go to the compatibility menu and disable +the “Vanilla demo limit” option. + +## Game exits with a message about “visplanes” + +The game may exit with one of these messages: + + R_FindPlane: no more visplanes + R_DrawPlanes: visplane overflow (129) + +This is known as the “visplane overflow” limit and is one of the most +well-known Vanilla Doom engine limits. You should only ever experience +this when trying to play an add-on level. The level you are trying to +play is too complex; it was most likely designed to work with a limit +removing source port. + +More information can be found here (archived link): https://archive.is/s6h7V + +## IDMUS## cheat doesn’t work with shareware/registered Doom IWADs + +The IDMUS cheat allows the in-game music to be changed. However, in +the original v1.9 this cheat didn’t work properly when playing with +the Doom 1 (shareware and registered) IWADs. This bug was fixed in +the Ultimate Doom and Final Doom executables. + +Chocolate Doom emulates this bug. When playing with the shareware or +registered Doom IWADs, the IDMUS cheat therefore does not work +properly. If you are playing with the Ultimate Doom IWAD, the +Ultimate Doom executable is emulated by default, so the cheat works +properly. + +## Some graphics are wrong when playing with BFG Edition IWADs + +If you are playing using the IWAD files from Doom 3: BFG Edition, you +may notice that certain graphics appear strange or wrong. This +includes the title screen, and parts of the options menu. + +The IWAD files in the new BFG Edition have had some significant +changes from the IWAD files in older releases. Some of the graphics +lumps have been removed or changed, and the Doom 2 secret levels are +also censored. Chocolate Doom includes some small workarounds that +allow the game to run, but for the best experience, it’s best to get a +copy of the classic versions of the IWADs. These are still available +to buy from Steam or GOG.com. diff --git a/games/NXDoom/PHILOSOPHY.md b/games/NXDoom/PHILOSOPHY.md new file mode 100644 index 00000000000..afd1e68d180 --- /dev/null +++ b/games/NXDoom/PHILOSOPHY.md @@ -0,0 +1,214 @@ +Chocolate Doom has been designed around a careful and deliberate +philosophy that attempts to recreate the original (“Vanilla”) DOS +executables for Doom, Heretic, Hexen and Strife. This document +describes some of that philosophy and the reasoning behind it. + +This document is descriptive, not proscriptive. + +# Vanilla behavior + +Ideally Chocolate Doom aims to recreate the behavior of the Vanilla +binaries, but different aspects of Vanilla behavior are held to +varying degrees of importance. It can be imagined as different “tiers” +of compatibility: + + * The game and gameplay itself is of central importance. Here, the + Vanilla behavior ought to be maintained as accurately as possible. + This includes the look, feel and sound, and things like demo + compatibility. + * The surrounding aspects of the game that aren’t part of the central + gameplay experience can be extended as long as there’s a good + reason and Vanilla behavior is respected. + * The setup tool is not required to reproduce the behavior of the + Vanilla setup tool, even though it reproduces its look and feel. + +“Vanilla” is defined as: + + * DOS Doom 1.9 (although there are actually multiple “1.9”s). + * DOS Heretic 1.3. + * DOS Hexen 1.1 (although there are actually two known “1.1”s). + * DOS Strife 1.31. + * DOS Chex Quest. + +Compatibility with older versions of the DOS binaries is also a +secondary goal (though not pre-release versions). Other ports (either +official or unofficial) are out of scope: this includes console ports, +non-DOS ports, Doom 95 and Doom 3: BFG Edition. + +# Compatibility + +Chocolate Doom aims to be compatible with Vanilla Doom in several +different ways. Examples are: + + * Bug compatibility: the aim is to emulate compatibility of the + original game down to bugs that were present in the DOS + executables. This includes maintaining the limitations of the + original engine: for example, the infamous “visplane overflow” bug + is intentionally still present, where other source ports have + removed it; this allows mappers targeting Vanilla Doom to use + Chocolate Doom as a faithful substitute. + * Demo compatibility: Doom was one of the first games to develop a + ‘speedrunning’ community, and thousands of recordings of Doom + gameplay (`.lmp` demo files) exist in the Compet-N archive. Chocolate + Doom aims for the highest standard of demo compatibility with + Vanilla Doom, a goal that is often complicated by obscure behavior + that can be difficult to reproduce. + * Configuration file compatibility: Chocolate Doom uses the same + configuration file format as Vanilla Doom, such that a user should + be able to reuse their existing Vanilla configuration file without + making any changes. Extra non-Vanilla options are stored in a + separate configuration file. + * Savegame file compatibility: Chocolate Doom uses the same savegame + file format as Vanilla, such that it should be possible to import + and use existing savegame files. + +# DOS tools + +Chocolate Doom includes some features that aren’t part of Vanilla Doom +but exist for compatibility with DOS tools that interact with it. +These are considered part of the Vanilla experience and ought to be +treated as such. Some examples are: + + * The novert setting, which reproduces the functionality of + `novert.exe`. + * The `-deh` parameter, which loads Dehacked patches like dehacked.exe + does under DOS. Chocolate Doom imposes the same limitations that + Vanilla Dehacked does. + +# Exceptions + +Chocolate Doom differs from Vanilla Doom in a number of ways. In most +cases these are subtle, minor differences. Nonetheless they deserve +some explanation and justification. Here are some examples of +situations where changes are considered acceptable: + + 1. Vanilla behavior can be broken that is harmful, eg. can damage the + player’s computer, or is just outright misleading. For example: + + - Vanilla uses unbounded sprintf and strcpy (security issue). + - Vanilla has crashes that force the user to reboot the machine. + - Vanilla has an out of memory message that recommends tweaking + CONFIG.SYS. As Chocolate Doom doesn’t run under DOS, reproducing + this message would not be helpful. + + 2. Subtly extending behavior is okay where it’s not clear what the + Vanilla behavior is anyway. For example: + + - Opening the menu releases mouse grab in Chocolate Doom. + - Chocolate Hexen’s graphical startup screen runs in a window. + + 3. Supporting obsolete technology is not a goal: it’s considered + acceptable that Chocolate Doom does not support every type of + hardware from 1993. However, Chocolate Doom should aim to recreate + the functionality in a modern way. Examples of technologies that + aren’t supported are: + + - No support for IPX networks, but TCP/IP is supported instead. + - No support for dial-up/serial connections; modern operating + systems have features that do that for you. + - No MS-DOS version. + + 4. Changes are acceptable that allow the player to be able play the + game. For example: + + - There are new key bindings for actions that can’t be rebound with + Vanilla Doom, because it’s useful for portability to machines + that don’t have a full keyboard. + - There are additional mouse and joystick button bindings that let + you perform actions with them that can only be done with the + keyboard in Vanilla Doom. + - Chocolate Doom includes some hacks to support the Doom 3: BFG + Edition IWAD files. The assumption is that being able to at least + play is better than nothing, even if it’s not Vanilla behavior. + - Chocolate Strife does not emulate the save bug from + Vanilla 1.31, which could corrupt saves when overwriting a slot, + if the old slot was not part of the current game’s progression. + Vanilla behavior is unexpected and potentially devastating. + + 5. Adding extra options to Vanilla functionality is acceptable as long + as the defaults match Vanilla, it doesn’t change gameplay and + there’s a good reason for it. For example: + + - PNG screenshots are supported because PCX is an obsolete format. + - Chocolate Doom has the vanilla_keyboard_mapping option that + allows the user to use the native keyboard mapping for their + computer, rather than always assuming a US layout. + + 6. Changing configuration file defaults is acceptable where there’s a + very good reason. For example: + + - Vanilla Doom defaults to no sound or music if a configuration + file is not found. Chocolate Doom defaults to having sound + effects and music turned on by default, because modern computers + support these; there’s no need to configure hardware IRQ settings + to get sound working. + + 7. Things can be changed if they’re really just inconsequential. For + example: + + - The startup messages in Chocolate Doom are not identical to + Vanilla Doom and are not necessarily in the same order. + - Vanilla Doom has command line options named `-comdev`, `-shdev` + and `-regdev` used by id internally for development; these have + been removed. + + 8. Expansions to the vanilla demo formats are allowed, to make + recording and playback of vanilla gameplay more convenient, with + the following restrictions: + + - Such expansions are not supported in WAD files (they are not + an editing feature for WAD authors to use). + - Support for these features can be completely disabled using the + `-strictdemos` command line argument. + - A warning is shown to the user on the console (stdout) when a + demo using one of these features is recorded or played back. + +A good litmus test of when it’s acceptable to break from Vanilla +behavior is to ask the question: “Although this is Vanilla behavior, +is there anyone who would want this?” + +For example, emulating Vanilla bugs like the visplane overflow bug is +something that is useful for people making Vanilla format maps. On the +other hand, painstakingly emulating Vanilla Doom by starting with no +sound or music by default is not helpful to anyone. + +# Minimalism + +Chocolate Doom aims to be minimalist and straightforward to configure; +in particular, the setup tool should have a sane interface. Part of +the inspiration for Chocolate Doom came from Boom’s complicated maze +of options menus (and a desire to avoid them). Too many preferences +lead to a bad user interface; see Havoc Pennington’s essay on Free +Software UI: + + http://ometer.com/free-software-ui.html + +Chocolate Doom has some options that are quite obscure and only really +of interest to a small number of people. In these cases, the options +are hidden away in configuration files and deliberately not exposed in +the setup tool. The assumption is that if you care enough about those +obscure features, editing a configuration file by hand should not be a +huge problem for you. + +Also inspirational was the README file from Havoc’s Metacity window +manager, where the list of features begins: + + > Boring window manager for the adult in you. Many window managers + > are like Marshmallow Froot Loops; Metacity is like Cheerios. + +I’d like to think that Chocolate Doom’s philosophy towards features is +similar. The idea is for a source port that is boring. I find the best +software - both proprietary and open source - is software that is +“egoless”: it does a job well without pretentions about its importance +or delusions of grandeur. A couple of other notable examples of +software that I feel embody this spirit of design in a beautiful way +are Marco Pesenti Gritti’s Epiphany web browser and Evince PDF viewer. + +# Other philosophical aspects + +Chocolate Doom aims for maximal portability. That includes running on +many different CPUs, different operating systems and different devices +(ie. not just a desktop machine with a keyboard and mouse). + +Chocolate Doom is and will always remain Free Software. It will never +include code that is not compatible with the GNU GPL. diff --git a/games/NXDoom/README.Music.md b/games/NXDoom/README.Music.md new file mode 100644 index 00000000000..7c1b2925c15 --- /dev/null +++ b/games/NXDoom/README.Music.md @@ -0,0 +1,173 @@ +Doom has a memorable and atmospheric soundtrack. Like many games of +the era, it is MIDI-based. Chocolate Doom includes a number of +different options for music playback, detailed below. + +# Native MIDI playback + +Most modern operating systems have some kind of built-in support for +MIDI playback; some have very good quality MIDI playback (Mac OS X for +example). To use this, choose “Native MIDI” in the sound configuration +dialog in the setup tool. + +# Timidity + +Timidity is a software-based MIDI synthesizer, and a version of it is +included in the SDL2_mixer library used by Chocolate Doom. To use +Timidity for MIDI playback, first download a sound font. An example of +a good quality sound font is the eawpats font, which can be downloaded +from the idgames archive as sounds/eawpats.zip: + + https://www.doomworld.com/idgames/sounds/eawpats + +Having installed a sound font, select “Native MIDI” in the sound +configuration dialog in the setup tool, and use the “Timidity +configuration file” widget below to enter the path to the Timidity +configuration file (normally named timidity.cfg). + +# Gravis Ultrasound (GUS) + +The Gravis Ultrasound (GUS) was a PC sound card popular in the ’90s, +notable for having wavetable synthesis that provided MIDI playback +that was superior to most other cards of the era. Chocolate Doom +includes a “pseudo-GUS emulation” feature that simulates the GUS +(using Timidity, under the hood). + +To use this feature you need a copy of the GUS patch files that were +distributed with the original GUS patches. If you have Doom 3: BFG +Edition, these patches are included with its version of classic Doom, +and are automatically detected. Otherwise, they can be downloaded +from the idgames archive as music/dgguspat.zip: + + https://www.doomworld.com/idgames/music/dgguspat + +Having downloaded the patches, select “GUS (emulated)” in the sound +configuration dialog in the setup tool, and use the “GUS patch path” +widget to enter the path to the directory containing the patch files. + +For the music not to sound weird, you will almost certainly want to +load gusgonna.wad (sounds/gusgonna.zip in the idgames archive) when +you run the game, to work around a bug in vanilla Doom's instrument +mappings parser: + + https://www.doomworld.com/idgames/sounds/gusgonna + +By default a GUS card with 1024KB is simulated; to simulate a 256KB, +512KB or 768KB card instead, change the gus_ram_kb option in +chocolate-doom.cfg. + +# OPL (Soundblaster / Adlib) + +Most people playing Doom in the ’90s had Soundblaster-compatible sound +cards, which used the Yamaha OPL series of chips for FM-based MIDI +synthesis. Chocolate Doom includes the ability to emulate these chips +for a retro experience. OPL emulation is the default MIDI playback, +but can be selected in the setup tool as “OPL (Adlib/SB)”. + +Most modern computers do not include an OPL chip any more, as CPUs are +fast enough to do decent software MIDI synthesis. However, no software +emulator sounds exactly like a real (hardware) OPL chip, and a few +cards do have real hardware OPL. If you have such a card, here’s how +to configure Chocolate Doom to use it. + +## Sound cards with OPL chips + +If you have an ISA sound card, it almost certainly includes an OPL +chip. Modern computers don’t have slots for ISA cards though, so you +must be running a pretty old machine. + +If you have a PCI sound card, you probably don’t have an OPL chip. +However, there are some exceptions to this. The following cards are +known to include “legacy” OPL support: + + * C-Media CMI8738 (*) + * Forte Media FM801 + * Cards based on the Yamaha YMF724 (*) + +Other cards that apparently have OPL support but have not been tested: + + * S3 SonicVibes + * AZTech PCI 168 (AZT 3328 chipset) + * ESS Solo-1 sound cards (ES1938, ES1946, ES1969 chipset) + * Conexant Riptide Audio/Modem combo cards + * Cards based on the Crystal Semiconductors CS4281 + * Cards based on the Avance Logic ALS300 + * Cards based on the Avance Logic ALS4000 + +If you desperately want hardware OPL music, you may be able to find +one of these cards for sale cheap on eBay. + +For the cards listed above with (\*) next to them, OPL support is +disabled by default and must be explictly enabled in software. See +sections below for operating system-specific instructions on how you +may be able to do this. + +If your machine is not a PC, you don’t have an OPL chip, and you will +have to use the software OPL. + +## Operating System support + +If you’re certain that you have a sound card with hardware OPL, you +may need to take extra steps to configure your operating system to +allow access to it. To do hardware OPL, Chocolate Doom must access +the chip directly, which is usually not possible in modern operating +systems unless you are running as the superuser (root/Administrator). + +### Microsoft Windows + +On modern Windows systems it is not possible to directly access the +OPL chip, even when running as Administrator. Fortunately, it is +possible to use the “ioperm.sys” driver developed for Cygwin (look for +iopermsys-0.2.1.tar.bz2): + + http://openwince.sourceforge.net/ioperm/ + +It is not necessary to have Cygwin installed to use this. Copy the +ioperm.sys file into the same directory as the Chocolate Doom +executable and it should be automatically loaded. + +You can confirm that hardware OPL is working by checking for this +message in stdout.txt: + + OPL_Init: Using driver 'Win32'. + +If you have a C-Media CMI8738, you may need to enable the `FM_EN` +flag in Windows Device Manager to access hardware OPL output. See +[this](http://www.vogons.org/viewtopic.php?f=46&t=36445) thread on +vogons.org for some more information. + +### Linux + +If you are using a system based on the Linux kernel, you can access +the OPL chip directly, but you must be running as root. You can +confirm that hardware OPL is working, by checking for this message on +startup: + + OPL_Init: Using driver 'Linux'. + +If you are using one of the PCI cards in the list above with a (*) +next to it, you may need to manually enable FM legacy support. Add +the following to your /etc/modprobe.conf file to do this: + + options snd-ymfpci fm_port=0x388 + options snd-cmipci fm_port=0x388 + +### OpenBSD/NetBSD + +You must be running as root to access the hardware OPL directly. You +can confirm that hardware OPL is working by checking for this message +on startup: + + OPL_Init: Using driver 'OpenBSD'. + +There is no native OPL backend for FreeBSD yet. Sorry! + +# Other options + +If you have some other favorite MIDI playback option that isn’t +listed above, you can set a hook to invoke an external command for +MIDI playback using the ‘snd_musiccmd’ configuration file option. For +example, set: + + snd_musiccmd "aplaymidi -p 128:0" + +in your chocolate-doom.cfg file. diff --git a/games/NXDoom/README.Strife.md b/games/NXDoom/README.Strife.md new file mode 100644 index 00000000000..c770449b98d --- /dev/null +++ b/games/NXDoom/README.Strife.md @@ -0,0 +1,124 @@ +```````````````````````````````````````````````````````````````````````` + + Samuel ‘Kaiser’ Villarreal and James ‘Quasar’ Haley Present + + C H O C O L A T E + ______________________________._________________________ + / _____/\__ ___/\______ \ \_ _____/\_ _____/ + \_____ \ | | | _/ || __) | __)_ + / \ | | | | \ || \ | \ + /_______ / |____| |____|_ /___|\___ / /_______ / + \/ \/ \/ \/ + +```````````````````````````````````````````````````````````````````````` + +## What is it? + +Chocolate Strife is the most accurate and complete recreation of Rogue +Entertainment’s “Strife: Quest for the Sigil.” It was created through more +than four years of reverse engineering effort with the blessings of the +original programmers of the game. + + +## Why? + +The source code for Strife was lost, which means, unlike the code for all the +other commercial DOOM-engine games, it cannot be released. The only access we +have to the code is the binary executable file. Tools such as IDA Pro have +been employed to disassemble and decompile the executable, which was cross- +referenced against the Linux DOOM and DOS Heretic sources and painstakingly +combed over multiple times, instruction-by-instruction, to ensure that the +resulting Chocolate Doom-based executable is as close as possible to the +original. + + +## Is it Legal? + +Chocolate Strife was originally reverse-engineered from the DOS Strife +binaries. Although reverse engineering is legally a protected activity, this +nonetheless left some open questions about its legal status. + +In 2014, a new commercial release of Strife was published (Strife: Veteran +Edition) based on the Chocolate Strife code, and developed by the authors of +Chocolate Strife under commercial license. The release of Strife: Veteran +Edition, along with its GPL-licensed source code, constitutes tacit approval +for the legal status of Chocolate Strife by its current copyright holder. + + +## Is it Perfect? + +Almost, but not entirely! That’s where you come in. Help us by reporting any +discrepancies you may notice between this executable and the vanilla DOS +program! + +However, do *not* report any glitch that you can replicate in the vanilla EXE +as a bug. The point of Chocolate Strife, like Chocolate Doom before it, is to +be as bug-compatible with the original game as possible. Also be aware that +some glitches are impossible to compatibly recreate, and wherever this is the +case, Chocolate Strife has erred on the side of not crashing the program, +for example by initializing pointers to NULL rather than using them without +setting a value first. + + +## What are some known problems? + +The demo version is *not* supported, and there are not any current plans to +support it in the future, due to the vast number of differences (the demo +version of Strife is based on an earlier version of Rogue’s +codebase). + +The commercial Strife IWAD version 1.1 may run, but also exhibit issues. Like +the demo version, there are no current plans to fully support it. Make sure +your copy is updated to at least 1.2. Strife: Veteran Edition already +includes the required version. + + +## How do I use it? + +From the Run box or a command line, issue a command to Chocolate Strife just +like you would run Chocolate Doom. Most of the same command line parameters +are supported. + +voices.wad will be read from the same directory as the IWAD, if it can be +found. If it is not found, then voices will be disabled just as would happen +with the vanilla executable. Do not add voices.wad using -file, as that is +redundant and unnecessary. + +Some new command-line parameters in Chocolate Strife include the following: + + - -nograph + - Disables the graphical introduction sequence. -devparm implies this. + + - -novoice + - Disables voices even if voices.wad can be found. + + - -work + - Enables Rogue’s playtesting mode. Automatic godmode, and pressing the + inventory drop key will toggle noclipping. + + - -flip + - Flips player gun graphics. This is buggy, however, because it does not + reverse the graphics’ x offsets (this is an accurate emulation of the + vanilla engine’s behavior). + + - -random + - Randomizes the timing and location of item respawns in deathmatch, when + item respawning is enabled. + + +## Copyright + +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. + +See the “COPYING” file for the full license text. The source code for this +program is available from the same location where you downloaded this package. + +Aside from Chocolate Doom, portions of the code are derived from the Eternity +Engine, Copyright 2011 Team Eternity, as published under the GNU GPL. diff --git a/games/NXDoom/README.md b/games/NXDoom/README.md new file mode 100644 index 00000000000..59dfc826378 --- /dev/null +++ b/games/NXDoom/README.md @@ -0,0 +1,102 @@ +# Chocolate Doom + +Chocolate Doom aims to accurately reproduce the original DOS version of +Doom and other games based on the Doom engine in a form that can be +run on modern computers. + +Originally, Chocolate Doom was only a Doom source port. The project +now includes ports of Heretic and Hexen, and Strife. + +Chocolate Doom’s aims are: + + * To always be 100% Free and Open Source software. + * Portability to as many different operating systems as possible. + * Accurate reproduction of the original DOS versions of the games, + including bugs. + * Compatibility with the DOS demo, configuration and savegame files. + * To provide an accurate retro “feel” (display and input should + behave the same). + +More information about the philosophy and design behind Chocolate Doom +can be found in the PHILOSOPHY file distributed with the source code. + +## Setting up gameplay + +For instructions on how to set up Chocolate Doom for play, see the +INSTALL file. + +## Configuration File + +Chocolate Doom is compatible with the DOS Doom configuration file +(normally named `default.cfg`). Existing configuration files for DOS +Doom should therefore simply work out of the box. However, Chocolate +Doom also provides some extra settings. These are stored in a +separate file named `chocolate-doom.cfg`. + +The configuration can be edited using the chocolate-setup tool. + +## Command line options + +Chocolate Doom supports a number of command line parameters, including +some extras that were not originally suported by the DOS versions. For +binary distributions, see the CMDLINE file included with your +download; more information is also available on the Chocolate Doom +website. + +## Playing TCs + +With Vanilla Doom there is no way to include sprites in PWAD files. +Chocolate Doom’s ‘-file’ command line option behaves exactly the same +as Vanilla Doom, and trying to play TCs by adding the WAD files using +‘-file’ will not work. + +Many Total Conversions (TCs) are distributed as a PWAD file which must +be merged into the main IWAD. Typically a copy of DEUSF.EXE is +included which performs this merge. Chocolate Doom includes a new +option, ‘-merge’, which will simulate this merge. Essentially, the +WAD directory is merged in memory, removing the need to modify the +IWAD on disk. + +To play TCs using Chocolate Doom, run like this: + +``` +chocolate-doom -merge thetc.wad +``` + +Here are some examples: + +``` +chocolate-doom -merge batman.wad -deh batman.deh vbatman.deh (Batman Doom) +chocolate-doom -merge aoddoom1.wad -deh aoddoom1.deh (Army of Darkness Doom) +``` + +## Other information + + * Chocolate Doom includes a number of different options for music + playback. See the README.Music file for more details. + + * More information, including information about how to play various + classic TCs, is available on the Chocolate Doom website: + + https://www.chocolate-doom.org/ + + You are encouraged to sign up and contribute any useful information + you may have regarding the port! + + * Chocolate Doom is not perfect. Although it aims to accurately + emulate and reproduce the DOS executables, some behavior can be very + difficult to reproduce. Because of the nature of the project, you + may also encounter Vanilla Doom bugs; these are intentionally + present; see the NOT-BUGS file for more information. + + New bug reports, feedback, questions or suggestions can be submitted + to the issue tracker on Github: + + https://github.com/chocolate-doom/chocolate-doom/issues + + * Source code patches are welcome, but please follow the style + guidelines - see the file named HACKING included with the source + distribution. + + * Chocolate Doom is distributed under the GNU GPL. See the COPYING + file for more information. diff --git a/games/NXDoom/RELEASE_NOTES.md b/games/NXDoom/RELEASE_NOTES.md new file mode 100644 index 00000000000..a366537f98b --- /dev/null +++ b/games/NXDoom/RELEASE_NOTES.md @@ -0,0 +1,35 @@ +## 3.1.1 (2025-08-14) + +### General + * Fix compilation on GCC 15 (thanks Fabian). + * Hide public IP addresses for privacy. + * Use native OpenGL texture format for better performance (thanks Fabian). + * Improved directory handling on Windows (thank Roman Fomin): + * Fixes problems with postfix "." for non-relative paths. + * Support for long NTFS paths (up to 32768 characters). + * Fixed metainfo files for latest AppStream spec compliance (thanks Fabian). + * Add option to enable or disable smooth pixel scaling (thanks StevenSYS). + * Allow spaces in GUS patch folder path (thanks Michael Day). + * Add support for non-US backslash key (thanks Michael Day). + * Never let SDL Mixer use native midi on Windows (thanks Michael Day). + * Use $TMPDIR to find tempdir on Unix (thanks Mr. Myth). + * Improve man page formatting (thanks g-branden-robinson). + +### Build systems + * Can now be built with Emscripten (thanks James Baicoianu). + * Misc. improvements (thanks suve, Emmanuel Ferdman, Gabriele Simoni, et al.) + +### Setup + * Use correct EGA palette colors (thanks Henrique Jorge). + +### Doom + * Initial support for Doom version 1.5 (thanks Michael Francis). + +### Heretic + * Fix crash after loading too many saved games (thanks Noseey). + +### Hexen + * Fix crash with Heresiarch fireballs if player has never touched a wall (thank Noseey). + +### Strife + * Initialize floor->type and floor->crush fields in EV_BuildStairs() (thanks Fabian). diff --git a/games/NXDoom/TODO.md b/games/NXDoom/TODO.md new file mode 100644 index 00000000000..3f40d47357a --- /dev/null +++ b/games/NXDoom/TODO.md @@ -0,0 +1,36 @@ +This is Chocolate Doom’s “to do” list. Note that this is kind of an arbitrary +and unstructured wish list of features and improvements. The bug tracker +(http://chocolate-doom.org/bugs) has more feature requests. + +* Multiplayer: + - Use UPnP to automatically configure port forwarding for NATed + networks. + - Multiplayer options and configuration file (server name, etc) +* Improve multiplayer startup: + - Select an IWAD automatically from the server’s game type rather than + all players having to specify -iwad. + - Send list of WADs to load instead of all clients having to specify -file. + - Same applies to dehacked patches and wad merging parameters. +* Portability improvements: + - Test on and fix for architectures where `((-2) >> 1) != -1` + - Use size-specific types (eg. `int32_t` instead of int) + - Don’t make structure packing assumptions when loading levels. + - Port to every OS and architecture under the sun + - Port to Emscripten and release a web-based version. +* Video capture mode + - Real-time recording of gameplay + - Batch conversion of demos into videos +* Heretic/Hexen/Strife: + - Merge r_draw.c to common version and delete duplicates + - Heretic v1.2 emulation (if possible) + - Hexen v1.0 emulation (if possible/necessary) + - Strife v1.1 emulation (for demo IWAD support) + - Screensaver mode + +Crazy pie in the sky ideas: + +* Automatic WAD installer - download and run TCs from a list automatically + (automating the current “instructions on wiki” system). +* Textscreen interface to the Compet-N database: menu driven system to + automatically download and play speedruns. +* DWANGO-like interface for finding players and setting up games. diff --git a/games/NXDoom/autogen.sh b/games/NXDoom/autogen.sh new file mode 100755 index 00000000000..b0763a5c131 --- /dev/null +++ b/games/NXDoom/autogen.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +autoreconf -fi +./configure "$@" diff --git a/games/NXDoom/check-extern.sh b/games/NXDoom/check-extern.sh new file mode 100755 index 00000000000..b5ad848dab4 --- /dev/null +++ b/games/NXDoom/check-extern.sh @@ -0,0 +1,6 @@ +#!/bin/sh +EXTERN="$(grep -e 'extern[^A-Za-z0-9_]' $(find . -name *.c))" +if [ -n "$EXTERN" ] ; then + echo "extern found in .c files:\n${EXTERN}" + exit 1 +fi diff --git a/games/NXDoom/cmake/FindFluidSynth.cmake b/games/NXDoom/cmake/FindFluidSynth.cmake new file mode 100644 index 00000000000..6702af983f7 --- /dev/null +++ b/games/NXDoom/cmake/FindFluidSynth.cmake @@ -0,0 +1,106 @@ +# FindFluidSynth +# --------- +# +# Try to find the FluidSynth library. +# +# This will define the following variables: +# +# ``FluidSynth_FOUND`` +# System has FluidSynth. +# +# ``FluidSynth_VERSION`` +# The version of FluidSynth. +# +# ``FluidSynth_INCLUDE_DIRS`` +# This should be passed to target_include_directories() if +# the target is not used for linking. +# +# ``FluidSynth_LIBRARIES`` +# The FluidSynth library. +# This can be passed to target_link_libraries() instead of +# the ``FluidSynth::libfluidsynth`` target +# +# If ``FluidSynth_FOUND`` is TRUE, the following imported target +# will be available: +# +# ``FluidSynth::libfluidsynth`` +# The FluidSynth library +# +#============================================================================= +# Copyright 2018 Christophe Giboudeaux +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +# Cache variable that allows you to point CMake at a directory containing +# an extracted development library. +set(FluidSynth_DIR "${FluidSynth_DIR}" + CACHE PATH "Location of FluidSynth library directory") + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_FluidSynth QUIET fluidsynth>=${FluidSynth_FIND_VERSION}) + +find_library(FluidSynth_LIBRARIES + NAMES fluidsynth + HINTS + "${FluidSynth_DIR}/lib" + ${PC_FluidSynth_LIBDIR} +) + +find_path(FluidSynth_INCLUDE_DIRS + NAMES fluidsynth.h + HINTS + "${FluidSynth_DIR}/include" + ${PC_FluidSynth_INCLUDEDIR} +) + +if(NOT FluidSynth_VERSION) + if(EXISTS "${FluidSynth_INCLUDE_DIRS}/fluidsynth/version.h") + file(STRINGS "${FluidSynth_INCLUDE_DIRS}/fluidsynth/version.h" _FLUIDSYNTH_VERSION_H + REGEX "^#define[ ]+FLUIDSYNTH_VERSION[ ]+\"[0-9].[0-9].[0-9]\"") + string(REGEX REPLACE "^#define[ ]+FLUIDSYNTH_VERSION[ ]+\"([0-9].[0-9].[0-9])\".*" "\\1" FluidSynth_VERSION "${_FLUIDSYNTH_VERSION_H}") + unset(_FLUIDSYNTH_VERSION_H) + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(FluidSynth + FOUND_VAR FluidSynth_FOUND + REQUIRED_VARS FluidSynth_LIBRARIES FluidSynth_INCLUDE_DIRS + VERSION_VAR FluidSynth_VERSION +) + +if(FluidSynth_FOUND AND NOT TARGET FluidSynth::libfluidsynth) + add_library(FluidSynth::libfluidsynth UNKNOWN IMPORTED) + set_target_properties(FluidSynth::libfluidsynth PROPERTIES + IMPORTED_LOCATION "${FluidSynth_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${FluidSynth_INCLUDE_DIRS}" + ) + if(WIN32 AND FluidSynth_DIR) + # On Windows, we need to figure out the location of our library files + # so we can copy and package them. + set(FluidSynth_DLL_DIR "${FluidSynth_DIR}/bin" CACHE INTERNAL "") + endif() +endif() diff --git a/games/NXDoom/cmake/FindSDL2.cmake b/games/NXDoom/cmake/FindSDL2.cmake new file mode 100644 index 00000000000..25006950a0e --- /dev/null +++ b/games/NXDoom/cmake/FindSDL2.cmake @@ -0,0 +1,114 @@ +# FindSDL2.cmake +# +# Copyright (c) 2018, Alex Mayfield +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Currently works with the following generators: +# - Unix Makefiles (Linux, MSYS2) +# - Ninja (Linux, MSYS2) +# - Visual Studio + +# Cache variable that allows you to point CMake at a directory containing +# an extracted development library. +set(SDL2_DIR "${SDL2_DIR}" CACHE PATH "Location of SDL2 library directory") + +# Use pkg-config to find library locations in *NIX environments. +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_search_module(PC_SDL2 QUIET sdl2) +endif() + +# Find the include directory. +find_path(SDL2_INCLUDE_DIR "SDL_version.h" + HINTS "${SDL2_DIR}/include" ${PC_SDL2_INCLUDE_DIRS}) + +# Find the version. Taken and modified from CMake's FindSDL.cmake. +if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL_version.h") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}") + set(SDL2_VERSION "${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH}") + unset(SDL2_VERSION_MAJOR_LINE) + unset(SDL2_VERSION_MINOR_LINE) + unset(SDL2_VERSION_PATCH_LINE) + unset(SDL2_VERSION_MAJOR) + unset(SDL2_VERSION_MINOR) + unset(SDL2_VERSION_PATCH) +endif() + +# Find the SDL2 and SDL2main libraries +if(CMAKE_SIZEOF_VOID_P STREQUAL 8) + find_library(SDL2_LIBRARY "SDL2" + HINTS "${SDL2_DIR}/lib/x64" ${PC_SDL2_LIBRARY_DIRS}) + find_library(SDL2_MAIN_LIBRARY "SDL2main" + HINTS "${SDL2_DIR}/lib/x64" ${PC_SDL2_LIBRARY_DIRS}) +else() + find_library(SDL2_LIBRARY "SDL2" + HINTS "${SDL2_DIR}/lib/x86" ${PC_SDL2_LIBRARY_DIRS}) + find_library(SDL2_MAIN_LIBRARY "SDL2main" + HINTS "${SDL2_DIR}/lib/x86" ${PC_SDL2_LIBRARY_DIRS}) +endif() +set(SDL2_LIBRARIES "${SDL2_MAIN_LIBRARY}" "${SDL2_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SDL2 + FOUND_VAR SDL2_FOUND + REQUIRED_VARS SDL2_INCLUDE_DIR SDL2_LIBRARIES + VERSION_VAR SDL2_VERSION +) + +if(SDL2_FOUND) + # SDL2 imported target. + add_library(SDL2::SDL2 UNKNOWN IMPORTED) + set_target_properties(SDL2::SDL2 PROPERTIES + INTERFACE_COMPILE_OPTIONS "${PC_SDL2_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}" + IMPORTED_LOCATION "${SDL2_LIBRARY}") + + # SDL2main imported target. + if(MINGW) + # Gross hack to get mingw32 first in the linker order. + add_library(SDL2::_SDL2main_detail UNKNOWN IMPORTED) + set_target_properties(SDL2::_SDL2main_detail PROPERTIES + IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}") + + # Ensure that SDL2main comes before SDL2 in the linker order. CMake + # isn't smart enough to keep proper ordering for indirect dependencies + # so we have to spell it out here. + target_link_libraries(SDL2::_SDL2main_detail INTERFACE SDL2::SDL2) + + add_library(SDL2::SDL2main INTERFACE IMPORTED) + set_target_properties(SDL2::SDL2main PROPERTIES + IMPORTED_LIBNAME mingw32) + target_link_libraries(SDL2::SDL2main INTERFACE SDL2::_SDL2main_detail) + else() + add_library(SDL2::SDL2main UNKNOWN IMPORTED) + set_target_properties(SDL2::SDL2main PROPERTIES + IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}") + endif() +endif() diff --git a/games/NXDoom/cmake/FindSDL2_mixer.cmake b/games/NXDoom/cmake/FindSDL2_mixer.cmake new file mode 100644 index 00000000000..3328c6c3801 --- /dev/null +++ b/games/NXDoom/cmake/FindSDL2_mixer.cmake @@ -0,0 +1,88 @@ +# FindSDL2_mixer.cmake +# +# Copyright (c) 2018, Alex Mayfield +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Currently works with the following generators: +# - Unix Makefiles (Linux, MSYS2) +# - Ninja (Linux, MSYS2) +# - Visual Studio + +# Cache variable that allows you to point CMake at a directory containing +# an extracted development library. +set(SDL2_MIXER_DIR "${SDL2_MIXER_DIR}" CACHE PATH "Location of SDL2_mixer library directory") + +# Use pkg-config to find library locations in *NIX environments. +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_search_module(PC_SDL2_MIXER QUIET SDL2_mixer) +endif() + +# Find the include directory. +find_path(SDL2_MIXER_INCLUDE_DIR "SDL_mixer.h" + HINTS "${SDL2_MIXER_DIR}/include" ${PC_SDL2_MIXER_INCLUDE_DIRS}) + +# Find the version. Taken and modified from CMake's FindSDL.cmake. +if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}") + set(SDL2_MIXER_VERSION "${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH}") + unset(SDL2_MIXER_VERSION_MAJOR_LINE) + unset(SDL2_MIXER_VERSION_MINOR_LINE) + unset(SDL2_MIXER_VERSION_PATCH_LINE) + unset(SDL2_MIXER_VERSION_MAJOR) + unset(SDL2_MIXER_VERSION_MINOR) + unset(SDL2_MIXER_VERSION_PATCH) +endif() + +# Find the library. +if(CMAKE_SIZEOF_VOID_P STREQUAL 8) + find_library(SDL2_MIXER_LIBRARY "SDL2_mixer" + HINTS "${SDL2_MIXER_DIR}/lib/x64" ${PC_SDL2_MIXER_LIBRARY_DIRS}) +else() + find_library(SDL2_MIXER_LIBRARY "SDL2_mixer" + HINTS "${SDL2_MIXER_DIR}/lib/x86" ${PC_SDL2_MIXER_LIBRARY_DIRS}) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SDL2_mixer + FOUND_VAR SDL2_MIXER_FOUND + REQUIRED_VARS SDL2_MIXER_INCLUDE_DIR SDL2_MIXER_LIBRARY + VERSION_VAR SDL2_MIXER_VERSION +) + +if(SDL2_MIXER_FOUND) + # Imported target. + add_library(SDL2_mixer::SDL2_mixer UNKNOWN IMPORTED) + set_target_properties(SDL2_mixer::SDL2_mixer PROPERTIES + INTERFACE_COMPILE_OPTIONS "${PC_SDL2_MIXER_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_MIXER_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES SDL2::SDL2 + IMPORTED_LOCATION "${SDL2_MIXER_LIBRARY}") +endif() diff --git a/games/NXDoom/cmake/FindSDL2_net.cmake b/games/NXDoom/cmake/FindSDL2_net.cmake new file mode 100644 index 00000000000..96b6cd72229 --- /dev/null +++ b/games/NXDoom/cmake/FindSDL2_net.cmake @@ -0,0 +1,88 @@ +# FindSDL2_net.cmake +# +# Copyright (c) 2018, Alex Mayfield +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Currently works with the following generators: +# - Unix Makefiles (Linux, MSYS2) +# - Ninja (Linux, MSYS2) +# - Visual Studio + +# Cache variable that allows you to point CMake at a directory containing +# an extracted development library. +set(SDL2_NET_DIR "${SDL2_NET_DIR}" CACHE PATH "Location of SDL2_net library directory") + +# Use pkg-config to find library locations in *NIX environments. +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_search_module(PC_SDL2_NET QUIET SDL2_net) +endif() + +# Find the include directory. +find_path(SDL2_NET_INCLUDE_DIR "SDL_net.h" + HINTS "${SDL2_NET_DIR}/include" ${PC_SDL2_NET_INCLUDE_DIRS}) + +# Find the version. Taken and modified from CMake's FindSDL.cmake. +if(SDL2_NET_INCLUDE_DIR AND EXISTS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h") + file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_NET_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_NET_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_NET_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_NET_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MAJOR "${SDL2_NET_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_NET_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MINOR "${SDL2_NET_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_NET_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_PATCH "${SDL2_NET_VERSION_PATCH_LINE}") + set(SDL2_NET_VERSION "${SDL2_NET_VERSION_MAJOR}.${SDL2_NET_VERSION_MINOR}.${SDL2_NET_VERSION_PATCH}") + unset(SDL2_NET_VERSION_MAJOR_LINE) + unset(SDL2_NET_VERSION_MINOR_LINE) + unset(SDL2_NET_VERSION_PATCH_LINE) + unset(SDL2_NET_VERSION_MAJOR) + unset(SDL2_NET_VERSION_MINOR) + unset(SDL2_NET_VERSION_PATCH) +endif() + +# Find the library. +if(CMAKE_SIZEOF_VOID_P STREQUAL 8) + find_library(SDL2_NET_LIBRARY "SDL2_net" + HINTS "${SDL2_NET_DIR}/lib/x64" ${PC_SDL2_NET_LIBRARY_DIRS}) +else() + find_library(SDL2_NET_LIBRARY "SDL2_net" + HINTS "${SDL2_NET_DIR}/lib/x86" ${PC_SDL2_NET_LIBRARY_DIRS}) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SDL2_net + FOUND_VAR SDL2_NET_FOUND + REQUIRED_VARS SDL2_NET_INCLUDE_DIR SDL2_NET_LIBRARY + VERSION_VAR SDL2_NET_VERSION +) + +if(SDL2_NET_FOUND) + # Imported target. + add_library(SDL2_net::SDL2_net UNKNOWN IMPORTED) + set_target_properties(SDL2_net::SDL2_net PROPERTIES + INTERFACE_COMPILE_OPTIONS "${PC_SDL2_NET_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_NET_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES SDL2::SDL2 + IMPORTED_LOCATION "${SDL2_NET_LIBRARY}") +endif() diff --git a/games/NXDoom/cmake/FindSampleRate.cmake b/games/NXDoom/cmake/FindSampleRate.cmake new file mode 100644 index 00000000000..bd72802a080 --- /dev/null +++ b/games/NXDoom/cmake/FindSampleRate.cmake @@ -0,0 +1,67 @@ +# Findsamplerate.cmake +# +# Copyright (c) 2018, Alex Mayfield +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Currently works with the following generators: +# - Unix Makefiles (Linux, MSYS2) +# - Ninja (Linux, MSYS2) +# - Visual Studio + +# Use pkg-config to find library locations in *NIX environments. +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_search_module(PC_SAMPLERATE QUIET samplerate) +endif() + +# Find the include directory. +find_path(SAMPLERATE_INCLUDE_DIR "samplerate.h" + HINTS ${PC_SAMPLERATE_INCLUDE_DIRS}) + +# Find the version. I don't know if there is a correct way to find this on +# Windows - the config.h in the tarball is wrong for 0.1.19. +if(PC_SAMPLERATE_VERSION) + set(SAMPLERATE_VERSION "${PC_SAMPLERATE_VERSION}") +endif() + +# Find the library. +find_library(SAMPLERATE_LIBRARY "samplerate" + HINTS ${PC_SAMPLERATE_LIBRARY_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SampleRate + FOUND_VAR SampleRate_FOUND + REQUIRED_VARS SAMPLERATE_INCLUDE_DIR SAMPLERATE_LIBRARY + VERSION_VAR SAMPLERATE_VERSION +) + +if(SampleRate_FOUND) + # Imported target. + add_library(SampleRate::samplerate UNKNOWN IMPORTED) + set_target_properties(SampleRate::samplerate PROPERTIES + INTERFACE_COMPILE_OPTIONS "${PC_SAMPLERATE_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${SAMPLERATE_INCLUDE_DIR}" + IMPORTED_LOCATION "${SAMPLERATE_LIBRARY}") +endif() diff --git a/games/NXDoom/cmake/Findm.cmake b/games/NXDoom/cmake/Findm.cmake new file mode 100644 index 00000000000..f7a1cfa57d5 --- /dev/null +++ b/games/NXDoom/cmake/Findm.cmake @@ -0,0 +1,36 @@ +# Findm.cmake +# +# Copyright (c) 2018, Alex Mayfield +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Finds libm, so we can link against it for math functions. If libm doesn't +# exist, linking against the m target will have no effect. + +find_library(M_LIBRARY m) + +add_library(m INTERFACE) +if(M_LIBRARY) + target_link_libraries(m INTERFACE "${M_LIBRARY}") +endif() diff --git a/games/NXDoom/cmake/config.h.cin b/games/NXDoom/cmake/config.h.cin new file mode 100644 index 00000000000..6c67239fd9d --- /dev/null +++ b/games/NXDoom/cmake/config.h.cin @@ -0,0 +1,12 @@ +#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@" +#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@" +#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" +#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@" +#cmakedefine PROGRAM_PREFIX "@PROGRAM_PREFIX@" + +#cmakedefine HAVE_FLUIDSYNTH +#cmakedefine HAVE_LIBSAMPLERATE +#cmakedefine HAVE_LIBPNG +#cmakedefine HAVE_DIRENT_H +#cmakedefine01 HAVE_DECL_STRCASECMP +#cmakedefine01 HAVE_DECL_STRNCASECMP diff --git a/games/NXDoom/configure.ac b/games/NXDoom/configure.ac new file mode 100644 index 00000000000..26e6958d577 --- /dev/null +++ b/games/NXDoom/configure.ac @@ -0,0 +1,335 @@ +AC_INIT(Chocolate Doom, 3.1.1, + chocolate-doom-dev-list@chocolate-doom.org, chocolate-doom) + +PACKAGE_SHORTNAME=${PACKAGE_NAME% Doom} +PACKAGE_SHORTDESC="Conservative source port" +PACKAGE_COPYRIGHT="Copyright (C) 1993-2025" +PACKAGE_LICENSE="GNU General Public License, version 2" +PACKAGE_MAINTAINER="Simon Howard" +PACKAGE_URL="https://www.chocolate-doom.org/" +PACKAGE_RDNS="org.chocolate_doom" +PACKAGE_BUGREPORT="https://github.com/chocolate-doom/chocolate-doom/issues" + +dnl Check for Emscripten environment so we can set necessary environment variables +AC_ARG_ENABLE( + [emscripten], + [AS_HELP_STRING([--enable-emscripten=@<:@no/yes@:>@],[compile to JavaScript using Emscripten])],, + [AS_CASE([$CC], + [*emcc.py], [enable_emscripten="yes"], + [*emcc], [enable_emscripten="yes"], + [enable_emscripten="no"] + ) + ] +) + +AS_IF([test "x$enable_emscripten" = "xyes"], + AC_MSG_NOTICE([auto-detected use of Emscripten]) + SDL_CFLAGS="-s USE_SDL=2" + SDL_LIBS="-s USE_SDL=2" + SDLMIXER_CFLAGS="-s USE_SDL=2 -s USE_SDL_MIXER=2" + SDLMIXER_LIBS="-s USE_SDL=2 -s USE_SDL_MIXER=2" + SDLNET_CFLAGS="-s USE_SDL=2 -s USE_SDL_NET=2" + SDLNET_LIBS="-s USE_SDL=2 -s USE_SDL_NET=2" + EM_LDFLAGS="-s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_RUNTIME_METHODS=[ccall,cwrap,FS,ENV,PATH,ERRNO_CODES] -s FORCE_FILESYSTEM" +) + +AC_CONFIG_AUX_DIR(autotools) +AC_CANONICAL_HOST + +orig_CFLAGS="$CFLAGS" + +AM_PROG_AR +AC_PROG_CC_C99 +AC_PROG_RANLIB +AC_CHECK_PROG(HAVE_PYTHON, python3, true, false) + +OPT_LEVEL=2 + +# If this is gcc, we have some options we'd like to turn on. Turn on +# optimisation and debugging symbols. + +if test "$GCC" = "yes" +then + WARNINGS="-Wall -Wdeclaration-after-statement -Wredundant-decls" + CFLAGS="-O$OPT_LEVEL -g $WARNINGS $orig_CFLAGS" +fi + +AC_CANONICAL_TARGET +TARGET_OS="" +AS_CASE([$target_cpu], + [x86_64], + [ + TARGET_OS="x64" + ], + [aarch64*|arm*], + [ + TARGET_OS="arm" + ], + [i?86|arm*], + [ + TARGET_OS="32" + ]) +AC_SUBST([TARGET_OS]) + +PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.14]) +# Check for SDL2_mixer +AC_ARG_ENABLE([sdl2mixer], +AS_HELP_STRING([--disable-sdl2mixer], [Disable SDL2_mixer support]) +) +AS_IF([test "x$enable_sdl2mixer" != xno], [ + PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])], [ + AC_DEFINE([DISABLE_SDL2MIXER], [1], [SDL2_mixer disabled]) +]) + +# Check for networking +AC_ARG_ENABLE([sdl2net], +AS_HELP_STRING([--disable-sdl2net], [Disable SDL2_net support]) +) +AS_IF([test "x$enable_sdl2net" != xno], [ + PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])], [ + AC_DEFINE([DISABLE_SDL2NET], [1], [SDL2_net disabled]) +]) + +# Check for bash-completion. +AC_ARG_ENABLE([bash-completion], +AS_HELP_STRING([--disable-bash-completion], [Disable bash-completion]) +) +AS_IF([test "x$enable_bash_completion" != xno], [ + AS_IF([test "x$HAVE_PYTHON" = xfalse], [ + AC_MSG_WARN([Building bash-completion requires Python, but Python not found]) + enable_bash_completion=no + ]) +]) + +# Check for doc. +AC_ARG_ENABLE([doc], +AS_HELP_STRING([--disable-doc], [Disable documentation]) +) +AS_IF([test "x$enable_doc" != xno], [ + AS_IF([test "x$HAVE_PYTHON" = xfalse], [ + AC_MSG_WARN([Building documentation requires Python, but Python not found]) + enable_doc=no + ]) +]) + +# Check for fonts. +AC_ARG_ENABLE([fonts], +AS_HELP_STRING([--disable-fonts], [Disable fonts]) +) +AS_IF([test "x$enable_fonts" != xno], [ + AS_IF([test "x$HAVE_PYTHON" = xfalse], [ + AC_MSG_WARN([Building fonts require Python, but Python not found]) + enable_fonts=no + ]) +]) + +# Check for icons. +AC_ARG_ENABLE([icons], +AS_HELP_STRING([--disable-icons], [Disable icons]) +) +AS_IF([test "x$enable_icons" != xno], [ + AS_IF([test "x$HAVE_PYTHON" = xfalse], [ + AC_MSG_WARN([Building icons require Python, but Python not found]) + enable_icons=no + ]) +]) + +# Check for memory pool debugging. +AC_ARG_ENABLE([zpool], +AS_HELP_STRING([--disable-zpool], [Disable memory pools for debugging]) +) +AS_IF([test "x$enable_zpool" != xno], [], [ + AC_DEFINE([DISABLE_ZPOOL], [1], [Memory pooling disabled]) +]) + +# Check for libsamplerate. +AC_ARG_WITH([libsamplerate], +AS_HELP_STRING([--without-libsamplerate], + [Build without libsamplerate @<:@default=check@:>@]), +[], +[ + [with_libsamplerate=check] +]) +AS_IF([test "x$with_libsamplerate" != xno], [ + PKG_CHECK_MODULES(SAMPLERATE, samplerate >= 0.1.8, [ + AC_DEFINE([HAVE_LIBSAMPLERATE], [1], [libsamplerate installed]) + ], [ + AS_IF([test "x$with_libsamplerate" != xcheck], [AC_MSG_FAILURE( + [--with-libsamplerate was given, but test for libsamplerate failed]) + ]) + ]) +]) + +# Check for libpng. +AC_ARG_WITH([libpng], +AS_HELP_STRING([--without-libpng], + [Build without libpng @<:@default=check@:>@]), +[], +[ + [with_libpng=check] +]) +AS_IF([test "x$with_libpng" != xno], [ + PKG_CHECK_MODULES(PNG, libpng >= 1.2.50, [ + AC_DEFINE([HAVE_LIBPNG], [1], [libpng installed]) + ], [ + AS_IF([test "x$with_libpng" != xcheck], [AC_MSG_FAILURE( + [--with-libpng was given, but test for libpng failed]) + ]) + ]) +]) + +# Check for fluidsynth. +AC_ARG_WITH([fluidsynth], +AS_HELP_STRING([--without-fluidsynth], + [Build without fluidsynth @<:@default=check@:>@]), +[], +[ + [with_fluidsynth=check] +]) +AS_IF([test "x$with_fluidsynth" != xno] && [test "x$enable_sdl2mixer" != xno], [ + PKG_CHECK_MODULES(FLUIDSYNTH, fluidsynth >= 2.2.0, [ + AC_DEFINE([HAVE_FLUIDSYNTH], [1], [fluidsynth installed]) + ], [ + AS_IF([test "x$with_fluidsynth" != xcheck], [AC_MSG_FAILURE( + [--with-fluidsynth was given, but test for fluidsynth failed]) + ]) + ]) +]) + +# TODO: We currently link everything against libraries that don't need it. +# Use the specific library CFLAGS/LIBS variables instead of setting them here. +CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-} ${PNG_CFLAGS:-} ${FLUIDSYNTH_CFLAGS:-}" +LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-} ${FLUIDSYNTH_LIBS:-}" +case "$host" in + *-*-mingw* | *-*-cygwin* | *-*-msvc* ) + LDFLAGS="$LDFLAGS -lwinmm -lshlwapi" + ;; + *) +esac + +AC_CHECK_LIB(m, log) + +AC_CHECK_HEADERS([dirent.h linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h]) +AC_CHECK_FUNCS(mmap ioperm) +AC_CHECK_DECLS([strcasecmp, strncasecmp], [], [], [[#include ]]) + +# OpenBSD I/O i386 library for I/O port access. +# (64 bit has the same thing with a different name!) + +AC_CHECK_LIB(i386, i386_iopl) +AC_CHECK_LIB(amd64, amd64_iopl) + +case "$host" in + *-*-mingw* | *-*-cygwin* | *-*-msvc* ) + AC_CHECK_TOOL(WINDRES, windres, ) + ;; + *) + WINDRES= + ;; +esac + +AC_CHECK_TOOL(OBJDUMP, objdump, ) +AC_CHECK_TOOL(STRIP, strip, ) + +AC_ARG_ENABLE([werror], AS_HELP_STRING([--enable-werror], [Treat warnings as errors])) + +AS_IF([test "x$enable_werror" = "xyes"], [ + CFLAGS="$CFLAGS -Werror" +]) + +AM_CONDITIONAL(HAVE_WINDRES, test "$WINDRES" != "") +AM_CONDITIONAL(HAVE_BASH_COMPLETION, [test "x$enable_bash_completion" != xno]) +AM_CONDITIONAL(HAVE_DOC, [test "x$enable_doc" != xno]) +AM_CONDITIONAL(HAVE_FONTS, [test "x$enable_fonts" != xno]) +AM_CONDITIONAL(HAVE_ICONS, [test "x$enable_icons" != xno]) +AM_CONDITIONAL(HAVE_ZPOOL, [test "x$enable_zpool" != xno]) + +dnl Automake v1.8.0 is required, please upgrade! + +AM_INIT_AUTOMAKE([1.8.0 foreign]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +WINDOWS_RC_VERSION=`echo $PACKAGE_VERSION | sed 's/-.*//; s/\./, /g; s/$/, 0/'` + +dnl Without a hyphen. This is used for the bash-completion scripts. +PROGRAM_SPREFIX=$(echo $PACKAGE_SHORTNAME | tr A-Z a-z) + +dnl With a hyphen, used almost everywhere else. +PROGRAM_PREFIX=${PROGRAM_SPREFIX}- + +AC_SUBST(PROGRAM_PREFIX) +AC_DEFINE_UNQUOTED(PROGRAM_PREFIX, "$PROGRAM_PREFIX", + Change this when you create your awesome forked version) +AC_SUBST(PROGRAM_SPREFIX) + +AC_CONFIG_HEADERS(config.h:config.hin) + +AC_SUBST(WINDOWS_RC_VERSION) +AC_SUBST(SDLMIXER_CFLAGS) +AC_SUBST(SDLMIXER_LIBS) +AC_SUBST(EM_LDFLAGS) + +AC_SUBST(SDLNET_CFLAGS) +AC_SUBST(SDLNET_LIBS) + +AC_SUBST(ac_aux_dir) + +AC_SUBST(PACKAGE_SHORTNAME) +AC_SUBST(PACKAGE_SHORTDESC) +AC_SUBST(PACKAGE_COPYRIGHT) +AC_SUBST(PACKAGE_LICENSE) +AC_SUBST(PACKAGE_MAINTAINER) +AC_SUBST(PACKAGE_URL) +AC_SUBST(PACKAGE_RDNS) +AC_SUBST(PACKAGE_BUGREPORT) + +dnl Shut up the datarootdir warnings. +AC_DEFUN([AC_DATAROOTDIR_CHECKED]) + +AS_IF([test "x$enable_emscripten" = "xyes"], + EXEEXT=".html" +) + +AC_CONFIG_FILES([ +Makefile +man/Makefile +man/bash-completion/Makefile +man/bash-completion/doom.template +man/bash-completion/heretic.template +man/bash-completion/hexen.template +man/bash-completion/strife.template +opl/Makefile +opl/examples/Makefile +pcsound/Makefile +pkg/Makefile +pkg/config.make +pkg/osx/Info.plist +rpm.spec +data/Makefile +src/Makefile +src/doom-res.rc +src/Doom.metainfo.xml +src/Doom.desktop +src/Doom_Screensaver.desktop +src/doom/Makefile +src/heretic-res.rc +src/Heretic.metainfo.xml +src/Heretic.desktop +src/heretic/Makefile +src/hexen-res.rc +src/Hexen.metainfo.xml +src/Hexen.desktop +src/hexen/Makefile +src/setup-res.rc +src/setup/Makefile +src/setup/Setup.desktop +src/setup/setup-manifest.xml +src/strife-res.rc +src/Strife.metainfo.xml +src/Strife.desktop +src/strife/Makefile +textscreen/Makefile +textscreen/examples/Makefile +textscreen/fonts/Makefile +]) +AC_OUTPUT diff --git a/games/NXDoom/data/.gitignore b/games/NXDoom/data/.gitignore new file mode 100644 index 00000000000..f1bc7677ac0 --- /dev/null +++ b/games/NXDoom/data/.gitignore @@ -0,0 +1,7 @@ +Makefile.in +Makefile +*-doom.png +*-heretic.png +*-hexen.png +*-setup.png +*-strife.png diff --git a/games/NXDoom/data/Makefile.am b/games/NXDoom/data/Makefile.am new file mode 100644 index 00000000000..1b6a44c0c5f --- /dev/null +++ b/games/NXDoom/data/Makefile.am @@ -0,0 +1,39 @@ + +EXTRA_DIST= \ + README \ + doom.ico \ + doom.png \ + heretic.ico \ + heretic.png \ + hexen.ico \ + hexen.png \ + setup.ico \ + setup.png \ + strife.ico \ + strife.png \ + wadfile.png \ + convert-icon + +iconsdir = $(prefix)/share/icons/hicolor/128x128/apps +icons_DATA = @PROGRAM_PREFIX@doom.png \ + @PROGRAM_PREFIX@heretic.png \ + @PROGRAM_PREFIX@hexen.png \ + @PROGRAM_PREFIX@setup.png \ + @PROGRAM_PREFIX@strife.png + +@PROGRAM_PREFIX@doom.png : doom.png + cp $(top_srcdir)/data/doom.png $@ + +@PROGRAM_PREFIX@heretic.png : heretic.png + cp $(top_srcdir)/data/heretic.png $@ + +@PROGRAM_PREFIX@hexen.png : hexen.png + cp $(top_srcdir)/data/hexen.png $@ + +@PROGRAM_PREFIX@setup.png : setup.png + cp $(top_srcdir)/data/setup.png $@ + +@PROGRAM_PREFIX@strife.png : strife.png + cp $(top_srcdir)/data/strife.png $@ + +CLEANFILES = $(icons_DATA) diff --git a/games/NXDoom/data/README b/games/NXDoom/data/README new file mode 100644 index 00000000000..c3be61a62ff --- /dev/null +++ b/games/NXDoom/data/README @@ -0,0 +1,16 @@ +The Chocolate Doom icon is based on an image by Chris Metcalf +(http://www.chrismetcalf.org/) which is copyrighted to him: + + http://www.flickr.com/photos/laffy4k/448920776/ + +Chris has kindly agreed that the Chocolate Doom icon may be used under +the GNU GPL, so the copyright status of the icon is the same as that of +the rest of the project. + +The "foo8.ico" files are 8-bit depth only, while the "foo.ico" files +contain full 32-bit versions, scaled to different sizes and with proper +alpha masks (as well as the 8-bit versions). The 8-bit versions are +used when setting the icon within SDL, as SDL under Windows displays +full color icons in a very poor quality. The full-color versions are +used in the resource files. + diff --git a/games/NXDoom/data/convert-icon b/games/NXDoom/data/convert-icon new file mode 100755 index 00000000000..4ecb1955e47 --- /dev/null +++ b/games/NXDoom/data/convert-icon @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# +# Copyright(C) 2005-2014 Simon Howard +# +# 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. +# +# +# Converts images into C structures to be inserted in programs +# + +import sys +import os +import re + +try: + import Image +except ImportError: + try: + from PIL import Image + except ImportError: + print("WARNING: Could not update %s. " + "Please install the Python Imaging library or Pillow." + % sys.argv[2]) + sys.exit(0) + + +def convert_image(filename, output_filename): + + im = Image.open(filename) + + outfile = open(output_filename, "w") + + size = im.size + + struct_name = os.path.basename(output_filename) + struct_name = re.sub(re.compile("\\..*$"), "", struct_name) + struct_name = re.sub(re.compile("\W"), "_", struct_name) + + outfile.write("static int %s_w = %i;\n" % (struct_name, size[0])) + outfile.write("static int %s_h = %i;\n" % (struct_name, size[1])) + + outfile.write("\n") + outfile.write("static const unsigned int %s_data[] = {\n" % (struct_name)) + + elements_on_line = 0 + + outfile.write(" ") + + for y in range(size[1]): + for x in range(size[0]): + val = im.getpixel((x, y)) + outfile.write("0x%02x%02x%02x%02x, " % val) + elements_on_line += 1 + + if elements_on_line >= 6: + elements_on_line = 0 + outfile.write("\n") + outfile.write(" ") + + outfile.write("\n") + outfile.write("};\n") + +convert_image(sys.argv[1], sys.argv[2]) + diff --git a/games/NXDoom/data/doom.ico b/games/NXDoom/data/doom.ico new file mode 100644 index 0000000000000000000000000000000000000000..9d89a959ae3aaf4f752f47f3a8585c1c5416db35 GIT binary patch literal 43344 zcmeIb2|SeD`#(PRHdL}EW8Zh#vW%?|(klCsLS(C~Wh^O62^EDbEz+hWk;IIplosu_ zG=r!f+eB$(n)5sN?cq~BdGz%8`u6+%|IfTSnfpHXea`iMpZ#3dbq0fBz_4PF4+BOR z6C;Yjc);)T=Z{}|F=H@q;XOXS@$2~67|d!Z3`SUZ{Q4|>u2~s_QHB9||EvTC6J?0O z7#NISOB-P@(w-Ph!s=C~>~jR>z@*vD%}mxJu}GMOWbL^9EX-5X+}y-)eQ0ZccGv;& zrU(+@^7+AcIW6uZePNyA`4;=w#Z*Q2t{2Q;G&k1`KKjyW`=I;7oQ#~S7ykG%WcvKV zrGa-j?{Y3(I-f%t)ZyFNv}?m)<@rmEpO$R+IA?x>iD;^s_`<*c<1U>R%<$xyXHK~6 zr|SAbYs)5C>o?ni4lL?E!M$}kvlVlcLFQ8VNbOloCd|@|8G|OmqVvss<{R#r#XNsh z#qj1CVc+Ef!ujf{jH#w3b52{fN;}a5sO{ zs$JM83muq3-?>x*_X2Any5kkci=SutNV9ukopYt<=gpqg8DTNYHu?4*gI1S%muJ-) zg+UC|0SrdJ(9k}$WKV!<$0LK3OXio;2v}Temnso$SpX zH|t<;kCLheQ%y9S_o_kv7x;y$e~56eZqp}`SQ+% zSQhD9K1auRL^#=UznF4jbq)uwImDyGM3pn;q@BsW+R|U<<+*ir_cOzf*e8mnPd2d` z1$lQSl-x@>e|o{AbymrE-F{W^LPscv{od^-p7EbaP_8Ip=zn+6&|n*u`2#Ply8NxM zaKG{_zIj!?@J4<2$vsi=92`b*VP&igk2TE9mc2|M8`X{&8Za~MU34Ufz|MMu`FbXK zVf9C8LFNx79Gy#bt>^}MBWx>&NBdVbe|YQKI(Dd}nLlca9X&{uk=}T(iNdSoQs3P+ z*Gr?aWWVIf)#;4q!xkUT*X2064HLzBr7OCfgNfLhzDH^IN0ytE&xIxXMOT_~nKGMmh;ykgu})S~=zD-s5e6EcETO!%LA zKdpUorrt09NHznFu<=rX6Z4uC*Iq1QYW{R%dqqz00u%lXPoMV9i)t4p|8d)!Lq`JQd{{WpRAJ%X2B z*$XaLK);|=l(mpiV_EhE3}$W62Jy`iO9wy*qJ z`&et_Cnrw|wWTY-G0DQez1lG%;w{aoFfbyFi?`=RxHHSgkxy#toNhgQuOIG_nCbV) z0#Bg7|I~RW;axzB&yDLt?M;szNe3hb-&}hBzAx>SLP{j%wcYNw5&m(ipZd9!hkLB# z9SMsq=)=8Mv=;ugu5HmF=2@`oHZBl|=zj1TdtWL)_ml2!7x_^pqI>;$tsO-#)emxy zMpO9>l09CD6>tQxD_O6qOD|hXeD8h5=Vi+&_16}A72Bj2`E<7*8gTgZEK#rPprv&% zyVCPc9oED7f|5hQP1mJ_bQAsfc;qB(RrIR@Pu8oDsTUXNFd1+%d0pH&n5(I|56cwq zz4d9oP*oL6`zfDJzq*j58&w@62ihEaUp)`h?9ySiN-i1*9*mLy@V2+&AXEP>O;6Lx zdVgX{HcDF$z3 z2*3M&sbb_CbwS*&IcZGl*Bv=-w<2=cq%z+iIPiL*?}(Rc0+-I_O5JH)Q2KJ$NY5`Q7$$md4Ihg~!pvcBb!SFcH1IkZFDb zpT#@_@lEn7nAG?yb(k5uIqUSUn@jIodChs3{c2aLEr0myE{Uc5gR9hX@2!7zDwWS5 zujToGKPlr~mv3pHSN^+ASMM#}F^hgrexWw2-pI#+aMjVq4|hDv-)*W*8hl`IGQAGN zSht5B1?>p!Ph^HyL^(9emk%?CzM)>ygk~mJip4zDW>R^*qsQsou@dvgj6d zsmDWlp+yJk53WxsTcr3xlk$h<;HQ>kqiZoqA=zg;R_8~R2eCDh>~G&V?AU){5#=D6 zy~=81S9gZGqeH@*=Ux>uo-(`pWiL1Fx!P*y>d7?!J&!3F(WvnG`ZZXPt74hc`mYy}|;0B|0+=dv-lP1qb^yWQv zsuAsN6}Ehn?ZA0doI#qxB^p=r!T(E%s z*cRv9T;r}6Nu|ZoTWX8v7WM1O%dxd7))WuZi=Cp1=L*XupGm9DOxsgDr>IXiQKCkP zK7@0>Wun;6C|-yS?X2IoYEQhfre@ss@&ku_-QC4 zSM(HK+xI4{0yBen^6`^+649>(W1`1hr9zxG+PQBBlm*D={6QRix% zhI>C&Ivn3(ckKA_x|$ls#3JQ2*-_kg>rV=8X%*Ra?j6}LqFe!&zpc4^VV~oI;7jq2 zmzdiWS?}fB*j|cXd1+RgqKK!zk-E~Eh;T{8cZ~C-MQdm@-ApS``g~=6Ol=&e@wpFj z9QA<#u(#JbNIG;ZGqdJ|aoiI{9t^S6*V4+$P=+Ockw6mbix)5US!=P{c@eiOGLS#B# z3k&spaZm{RLY`ga7%YA5xsrk}8ij>vX=$lP3LV#L?Ii9ck`D11@Ge-8e)Q<4d4$K( zmU%7PI-lfQFg4NI8*B<~+~s&N()p{U7wv0x*^vy_B*RS@ign3~ zQ!1*|q>)XGXIgNw)TEX9PjW1YrTwYt`{R{$baaYlTduNsPmK69i&ha|$uNI`&Bl$U z9E3H6Hnj;{QlC|$-Au>WHe9haIk*0gU0+W7g^G&4tlY&53oN2Al1yAA6i%tK)Xhx| zx}p(vx-B}U(}sZO-(I8kj=kp)Z-7zV)**}1&&SZo*(bV9GHD9{m!#ziyj`=7JER~i_d0Q z>R&nMf^x!c({-i2>z%{LmbyIde%aqEtU0vEp=8U;mX&Ajn3_7KVJx_nBk@8K&C)@y z_dK-Q7h|_~>DDNka$#G+7um{>s&ii1w0&^v+12*JNw4$fouL&c4kWGRF5NQLdw8T^ z{!@I*{SS_h&(&M%rn0i=6z;jX>Q&X8*4CI2`=@cs3$)apCVWhsdrwz~$(15EH{VYjs1+S{~`^OUz{E&hjv4lo4K7Z{9Z&I=oRRf78RE>i3N#o|M$? z{=jE?m)zT$J4HuF4)$JIaxL-ZC#^pOtlwT~R}L$M6}{U$)qTOGx!iv4d46+E=fApw z=MwnjQbkOh9jt)CFh)M146+9D9TlRvX{o(mtg?W57`Fdr4GT)v;PJXkEW(t*MfGJp zZ)V|$CGa9-KNmIO^xPsKL77WS4R}al5@g5Br?Sv5QL?tI>hy#OimxL3$K|@nMHMp4 zqA^BF(Vj4pg`-`_aYX;RhZtsjG=Z14U2HzvY#4djmp`$90mDcj64>cS&S;x$pv^;* z6QT_Juu#-6@V#U|pOLh82ExWnQN(1Sw%N44x+fTBy58w~82mw|=)QRdWRmd>Mo`7A z!!)1DW_ff0%_HM*^8>b&4b<5@&Jp!vl*)QsY(+gb%7^!aS=j>%FN0GLcVi61#1EeA zU9fleidy@q(xYjX%nS`r&uXLxgwizzD#Q3Wopw+tVeS?FGPCvx0q^8!5Aid5CLO{&jq{s^V*^(Wu;BqX}4 zX@26SIh=l9Do66X#e5-~g^{U9VctCIsz75R!R}&b6TN%Tt%sU%zZT2B=S|1^qdB$K zUmo)Yc)5A>bx1Lm=Dp`rV{+ADO<|!L5}R;C!?SCxjcctfu59yV#EUM-0tZOeW^R|!w*ahmR+|L{2tps_f^=5tZgykq)3`u`37Q_lhb7?vkxh3lt;omX#MQ&ln&sV;3<0VsZ-^bCAJ*3!n?FgJc zxZ)CJJUY@fOZXn;UXp?1kp&RSy9<|%!u;emiK~ORnP0LgSw))oxBb-Cb&=Sdhe_PD zjzCXwJS%21BYytst@2%QE}w_{^UAsp_j^QMF7l_nHhq8l8D~wt;B7WMz7T_FO<6#F z08Fbs+pRy!JHkyfVJ=$@>H1uz(k1xb%5@&uvl&B1sKH_+d#_SkNYn!9LiJ@s{4P|h zj)%DS%mYGt2^l?0U%FZvkQ>wCI(ciN2LqlfWax7*weF36^iXSqEjzWJnPA?t_tQ-_ zj&7AM%d!x*6g{do2XnDn)WvFly0vpfR5JKON=%aMnevf=;7rMC93G^t@oI}P*1n%P z0PF6>_{$6?RR!#XQC!d$M*Y#2jEmsL`u07XGg=TXSV7eL=A#6|3W|zx=$=FLeUS4pi z@?b;jP_xFEPOXRaOD>_{`Q#Mt5@!4MXn7(wJv$XH;BI$t-Yc-GqrRZ^>6V z>eT^vY7Xq+Q|xA@FS_*vQ_K-rMh(0;`rz|ou5Jx#P*m>XV^OBTlH@m9^Y8erEc(I# zT-8B>#nHgeHG9o$i(CW(5?SO0anZfWy7QVI-r~R+c=05*k((&HUS=-x$TmLq@VT2D z=ewH5%lyQLnA;5a#Ja&b;aGJL@usosu2N)qP|w{t&nbn3(RI{;U8K3#W1-{% zMRh_nsV;Q0+e5v0v2qF9hPj&#T^=3nXe^nV5=1>kse97bR3b)W&b#@9$QC&m^8SPp zeu40k#Wcx_a3{r?D7N_O00TiMWg$(l0<)VPb4QWZW?;H_GgGy71#EU>9dD}kVn=Ul zy6?rtF6q!z;7FFguN^&m7A+wjc2ODou&EzA`T9B4NG$ka@OmTQEA6_?Odt&TQ5KgM zDK{OD;jLVjGN1N@g?#dUElEh9<`oGjOa@_FSPGmY#Wbi1pZAbTcIw(53z2NAVDk8~ zrp6lfDztg7+sN3eo&ss=+e1>}N4SX{Iw8vrHqB3#W8?q8gv&EXB+GKEM7w@jP^+YX zVHIGbItZ7QCUq@~BvAH5)qM8QRVTclQl0>TS$MIHGWRQ<2f)gk?9w;SRh~T9tg)3^ zVU%>|69YN&44s>nEtOlFN68A(v$YL4A8@zkYzI<~ZJ3zu2u_@6*hy17v9xO;8?90I zi=$62TP(@irF!q)qWdHU@Pp<%-YLd2jPYT6&Z0i6E z9&5$IJ7@m@vu?52mi@f=gYB3c*7>_Vc<9Hx>2KS28zj>n33=ota?;K0PU5ODl(v2w{#xBBRk05>ygt)hVx4d3kCp_$BA z(OPq8a`ok;Eg!MoaxN zz=@A#5fZ{*{qmOFWH_om%i_kYLWO98^?Nl8C5G@NfvDfXS*Ff{<-n_Mf$NA_Pd=5@ z98zRfh^|IkFKm6R_$6F4H-^t~xr~lo(YZA=Q+7g&lU0NN?A5(1jd2vyfsLEQf>|-b z!;~`HgKT(#`FL#Ub+W%i4l~UItIlw58K+e`k+6r#Pi!V)?SxqAUSXeOaj|MVR2kb< z9QdnoLUy)~wY}O;=|lxnwZk#~Oa>Yq{tiL{^gK!IB77Z7q}*Zg4k>A{P(+5r{OIu# zNF(htz<4qlq<3gO80_dsKFBaKm%vfu9*w&`?-(mhQjBvByAoT{$OWcs%8qRel-(-v z4O%pn=d{8KV1MlI)W=%uRWdtk0X?jHFpgdx-D-zYv0WAID;)H#%xIBGdsug3V{6%jaOG3~c zWU{2rN?Df@AV^tfijSyHHWLaYTDL@#w)HL$l_YZEqbeALFHpohsI%8J2k#|CE#jhi zprb7&pLT)iLTij<)kX$bKZ@rPIIVOkWd?kU=m)oRFyP`<*$A^gnz>myr0xz&C}0ro zqSUV+W-2U-CY#DV&?5WiA6K9zELw!&B!-{XA)3n%GTm85d)%tYLEXwpS?5SGZAe*8 z{qk~=BgU$8BeuBBJ(qn2h0EYH+a6NiHcN`BgSuTTNs#wJfN)AS!vQv0JUgB+N?@a! z-%~^Ad*m#+RxP6{5?Y=TCegXb! zEmP%5ofTB`bv+#g0S?Zad@(J1v2G0eE{$Hhz4g-zR|;Ei9SiO@3;oVqi|g^eyuwc@ zAw=DIw8m$In1WS=*y@gC1HDDG>QAt9ZOA%oD?s$a6tG8Lm{(g1?mumGTTQJE+7v^= z#^2XRI(XRd%Q6X`jxm%h0WBUXdl6GLwgj^&22124HeR87>a#vlI&EHy?eOrTMyzIw z#WFv693j9+k7wAzkH3`6eAS0xb7c=_83TNUj}Pzd#45-`r|b|UBb|x^#_q!Cmu@p& z*ZI_=yB>7#S`l#6wEX#tY4+sC^R{Ie)wz)=eMEIIw#$;tFZmctJDj}mAc*B!Ok33M zKZ|C!ki-);nzNj`z>a{W9;MHR-EH9jCGOn^PQZ!x;0jLI6qEZ%U&1cE<4p*6R6fHo zML!SN9J=+%Anu+^jVX?DRIkHyma9E1!sB7oQGN_T5t9-@6=P}Vrhgh_jVy}Dq{NLK z+d^F+!-j?Zfgh#!t$8*FZB1t}JD~(KLb#2gQwr4siP)UJt<~1bWeDs|@r=aBm?$_2 z)o6p&J>G&Hf6^6S+gEGt`(C$h`+Q~EeQBD=Cl#Xgvlw9oYJ~k&c7n`eO}Ie3STpFt z63<32+IFrQ+oCZHXYY(f>QR=p{;=JW_{{AoS*j5BB7#cP#U`4ht|E0dg|sh&gVwVm zFEGkQh|MGKN)&d^%5}OFwxbMB_h2blg%6+BAak%_hT?fR2I{e~vCu&_rFonyR*UaR#` z_RI=#zPOpt;|W(k&6whOk;h)>M@4q*p1tFZq^i^KseTU`XE@a^tdFiBk{Ci|DOo+z z43!ux8+D_9ci@19sjACx)^2U**{-|!i%cJIZkuZ@h{tp}4_|)O(6x&YCirll_mViv z+QxPA4j7SCJD(9#>$(U`S)4-;Sixu>7CKI zWoCEHEgdj-G-#4WTH0PEn)!#(Hg9}q6N{@4W|5On z-~$|Ni>u~{!nNBeE(<2JIdr|}wA2fj!t^M(Q9{HPG_x~GhGj=KQkd2b7ck;<1o;M3 zQp_IU?nIF^sA5i-XsnxUN@qOzO_&lKr|)dPid(2iF^w$QOn&2qk*~+pG#;qIG73|S z$=E{M#ReW7ao!Kk$Wf%2agB-?2c|pEqFg+k3uBq-%pGq+6=20){d(66Z+vYoF;|y1 zv{aaBOL>d+;}0zKx{fz-IAbQHPFsaB(@i@3<>qi*>0>O>SDk}nroUiV$$>wpG^@L; zo{x$8AjyCc-h7E`AZA)X&EC&%>$gmWIpz11z*N+`^Qx z+`#8FZ%?ZBt2s!u?xh^I<6B3SDX!0m#_H5^?xQfl@^HsQ+BU1~#cft$qI`PZS74KQ zzs^57HG+ETaLgRqDc_MD`>?KF73nnSnrA>6gFGd6|q2M4xI8yXL@+4yNHdC7@GMpA=FR4S8=S=?m$-# z0VZmN)f`!*q~_}|@y(@L#S*dd;!HSGE>}-X7bbF68pN4w3;Q`ivZf~EY}(zL#(;S# z1q_>o@R--LX^%e~jz(7DC}_;feG(MYAxlO$gHV11#ai2Z^8_=!xnrYFjrF`G@F6%D z=3<@!QBo$i89Dh}&*1y4C@C7on2C>#%HaC(fo@N(!W>${bDA#fTXR@2#hirMgyCxo z`xraOI-0v`2p?<~T&8_GwSAXTa15c|pYaui2@a2rWGPI5f+P4c`&namAoZM;WlrlH z2PU78?bk>9W&QMUv$vlj&!+8BAFI$!d;nLOaJrU!yiSg!w5em)mWyo~LmSvVt*U*` zYosvK9~N`k4DX0VSnpyb%x;uPDlT|*wk;}pH97fO&zoj;SIt?o4q##bQn2)VIvbO% zk3)3iWhOk_ZBR>+qj`KeE@~;gq{W7eEo~u_$boF!|M#}wqga~W28OJ@K!W(D^_)uO_4k#x21OQ zwpHIeOf!x$);(OoB#{p{1@w2tj2A+mCeRFhsTp|CMC z(;4uZmr%k8HU2Nk45j55kEAW5E%l(R%L;rCD?oE2MXXuLLFP!_iM9I(!`EliTDaid zIjcIq%puG!TeSL*I~DnlHOF+4+sG6-adv`F*q&_5F$0KZjdnPp*1yVOj`W_q+r=#; zQee_tJY&(;!mB$l!K?x8tvBv6;IAHxnPbmLKSXd!&-!w=iPrOJ+oCsq^YAN@${^BQ z&5iU|a~ydnS-xqEiK`i?c5%4T%-p=9t-j<9FX4+{g2WCt@Gdf{`gw`nl{;4`!>!I&>!Wpc^LHAWhK zhsG+{7L zr4D3iN+e{+%kSm=?zPEFQRRy%OGTQ2Hue$F7rq0Q3tR){e1*V@=NwqS=rpifm<=?g z5>qB$`0fi<>GB~(u?~Qwp%(rYsJXX-75v5Dq_I>o>CkttOL3Y?4u>3$5 z(24H`hKp|kLxFOjAeT9H{^lizq&JKJB#oT(bdVR52#)OB4_rbCz)-Lb=m)G?1M*H} zfn&)TKwq~NwfLr1aSiNHqn7j7?OZyg}zN{52H@pSZ z_0D8X687Dfpp3@zP%{Sx1_nTXe?NHo^eHGWF9#=1oB&Yk0Kx(TfX}A%%I{vAycE`p z4OpVN14!y@1wxuT0anc&2*Yb083!P&9sm}K+X5k-n1IO_zWXAe730UJfd})1EWuy@ zMxytTXTE!F@>0p}EMCIw2w1EY0YsM{2K?%~frwEmOe+G27^lGNaKNJ;v2*f;@4gsB zk>;C5k+bDmSMZ#oIq zaOZ&aTp3^^*I}R~89!zH{2qpw{3W8QNE^@)eu4IRdO{7r5L<<|b5p(|u#)#8+V`#D zE&w)*PNDtZGOgZr$qb<4h@OapH5#` z{TdPJYbWy1*f9W>J^nJ82Z}@P+wxGAJX}2$-{0RC)-EMVsZ-GY9LdAUl>jX7{sHuk zKpe#Ju|d=B88GI*Hi<)3;>gdZuU|%#(jNj7c?5f&1BARSz}op9!1=eMIJBLcfHCa% zC-P8|NU!-`&Z(}2jbQr7c=Bf+p}vLSRmB<*Wp@-9dbguo>27I7#}+gXfl{C-nf3GX zo0Su#*L+0B8zhhL;LD(^)&@j59tYmGMZgMjh4XF$MuJ3Ow73%Bmec`x>0IJe@_v6` z*b=61{|QXwu{-iAcyr$##B9n#^Qg^p18X+lgX!0TW!Ofv4a&)!{Q2}(-yovn-Jf~j z6Rv^2=g#0l>RwQu8H{ojV}BH=!}-WW8|8T?}G58n;<0i1_%m+^9`$}$+|ny1|{S! z{B-&v&Xq)&$S>gQJiacEiF);Q8$|j<%ujwovY$UEy?GCwkVnA%_Rru!Q!l7*cm}TA z>;Us)3LEJ@c#XK@aokofXod# zIy%6kM~~2X0kl2=+1c43H8mCB@p!OjXCMgjIn?p9=?m*dWeaNu0Lf)uKn~{v#C3N9 zAys!EsqG0Q^>zS$c_$zs=LkeJwgEmFd%!JW1BA6BvVS&xUiDpBSfgX;yaAb02pJun z_B-;<|1IfDSsW=+buIxSCdUBZ(h#8Ha0UI2%wtp>ipIagxs9^JW%Rp%Rute?-f`|{ zDJlm}xai&{I;#9Y? zcwV=Pcux0Hk&GU7k+dES;ln*z!iT$;38!}JV3WIbu?M>Kg%Z0Bm&A7|%kH=SRjd*+ zMK6)Hr-tw|bS%*ox)1c1+<|MSTDX?I0ZjRe(6y)~-vxADw|dbTbX~iV>m)k2b6k)C zaM<{lzn*_FNktTn``^i+CtVLr;94443!Cy^{#zMv*aXtA<}W6DjfBiMzm`E$y9vk^ zjsjKBmr#b1X=Tt8KJd%=i^!IdMPpO`J&9_&p_2{dKq+tlYcpXVYzY= zviAR42KAL>pjI#`3RaP+k2N=sx@MR~e?@K~v-~`B&?ouqMo3ZG65xA%p(Pm%zA*ipro}_VF7Y z^fYh%rA}&!ru};U%PL9e{>@i1tT(Fz=Z}Vi<j7jB=}#HfuDkuHij&ZGh}8O~{}op7G21 zix^dr(DlMsGOSyD50EO?p)$B>Ujasjk0xn;Q zSikW;x~4#6*rZbeR^eb@*z^gN0k@(N=3g}_gMlCcC`q39<@ztO66O#0zND@HBZH0e z1JKi8hsxlpTZYPTIejNu9}LVN!?i~>DuX^;+aTkGqGbNB=f8?bl6Hjaov&orxVaI$ zd*q19;AU735E+pAfXHBK_5c{ceGOf>?=UfDDM%Ikdj4x+{>c8{S2Aqe_89axxu7!a zb~^(y!VXT>2T$AuxbAxL&3GXzb?(>mx2Yz{c#op{hZ8dFKXw^iGfl`aQ5NkL>w%fl z{crkeWZaaIzWD3;+r#|f{^f)WGEO6)w<8b?zxMb>hSzr;z}|op-}I9cRu%gj0_`-h2sa$>xYlqve<{6#m_kptph86;$ie>s2GlxJ@;YpLMK%@GigPXhsYG_bc|2qd5D1ukMujVhIkFODjYguIfTXlH=P%-fbGWxziLfZ=lPav=F4P^DafrzRb5L9#q zLP{<`Ol=duDmnokNn5}#wGoJFhyL{b)c11osss^)SL6atal6TNF4ia$%$IVRyk25( z7%Y_8Jb5jscMxzX_)K0SX?&mV&t4<%imW&Z=8HQ_riV2-4i-qeOER!FTfd|K*Lp&yMc~(4N$PJK(7U~ zV}Pc|O`z;pg|D2w0WrL_eIKb)#1EFO>KoII)1k|?!KD7YAqwEhB zDf&(sxa7COa&iScszDXsr~9+l%VRoptmArWEMmK=%pytGjKkY6>TPd2t>yDHOJ&oe zR2kcQ@iMk|e;6dJ%TuvN87HxNM^t|{zu)m3(!bC#n8@D|ki3z73Pe}r3d7_+g*XPo zHFrF~+y8$4A7emLA-_mjq?WEKTt`lUTb z*K!@8YfHpknkiaj#j8G#@437Hn%Jl4-VdTH*IUwn?*AAF-h%pz8ejs~8Y}p(Lfzr` zJ`kecv*aD$3$lhfK19!l*f}7&zKvXY=$??n!Ytsl;25yrO+@W8W&(qZIB^Wo9sE6p zI=Du>j_%*Afcseg6vIm1{bMsBJCdf9M9r8ov@e(vgGd9=RlSYsz)bkZ_n`hM1~cBI z8Ixa9qHYYC|4)TMC8ifhUmOK0TifA!{TkFi|8oqcya#7YehJB2V+vxg(S5fcVNg2p z5y%xoJr;t&@6|71Sk9L^WAckh-WfymTT@|BJu@<{*ZwasEayKwWAckiHH;zqj#FV+ zS~vn!s>Z&>0QI;3q%IlpADJ=vMWpYIA^P#DFlb&KL3P=G!SE02l953A%*ii*e@s$p z0JS6d5eDt+RCLb`v0eC833W3^;+KGseHDDwJR4 z&wbw?V9>Am4D_1le~UrQz2$Gm2YrEznUi1R;TUSeF$D(q<9C5UI~~QKbK@h>D*f=6 za*$7_pnJ)PoyU*H2ff8vGbg_`lppRnPlbV)y%_|bEJZQsUw#jaRPO@ql5a669e+Q$ z7yTm)x{Hs`ocwx?W2h~{6c}nwc!1_Bt3cR^VqkD}2=1BIK@1H*^X8|?a!@`o1m(Xm zB?cYAoSBo~0LpLtr=89ZFw~v#ME87~iy(%$bHI4XZ4`sfdCFwJq;_Wb&wcP8W6%-I zo;mrAAB~}UgDEiFI_HDh(jfcRHx79M6R1-~Fd%gavDZTSC5?-S{1bcmf5o7^`ZxE<3EFx)Bh1!Tf{6vNFlZ?JsHT@(XSmnQlp?c!n7&gq93pngVk$@!U+ zf92yb)JAFw3=PG8sQv=Ma5G~YSPu0R2nP4GJCpsAZrKM^mx0)7eT(4+z`^y;Qf%SO z$-nB!7^?F?Y{`Cr;a+I~=)Pl%VyMdY2gX7VQ4H5pw}M?KE|2$1H$MVn!J6+dQ~_Ox z6IsWpVK2{|{A-~6hz%K{xA_5v2RF8(c54U*;)wuY1Z~w23`kvSf&EhWi6UTFJ%YCB z|6r&F+Ct+tZOB?w6?Y#$>$y)O-B^!?U{~V4%en#n5@z4cxx4 z9lW^VKG~)bo6hR2EwE1A2Pz_@AFksRMayPReitY|v~&CshRBrb;C;uq{%isRQVvL6 znrPEVzjQo&AC&v`lxrXbu^Tfdzx(qsROj{`21S=)@Zqfw_|W4ChB~*PI=~-ccwD?0 zXe+;(a{YkpYsiaL%$)olFUC+CO+;__9fp&|`Jk<7H)wtm4w@c@f#(gu;OVU$;7N5L zs4fl%hZC~EQr&LUPW12AK(b<$Gbg`y)0j*+ZQRcE2N3eNZ6NW)TM(Jn1HzI>VAp|XASt~D95_?~;trI8Z9A@m^$z7= z)w-*|YV~>G=9Ufow`GDL-%Q}^ejKVyX6AG6)d+oPXb8N0`*u?IjOa=b-7|9U-Me?7 zp`iiXzI_|KeEAZDw;%#kh-^h>Hkt5tc zfBqa02n5uAd_w;G{Cw0F;MlQaAR{9KWMySd%J1jy29AX807(&vGgf~TjDjg@D?@;q zML5t{wHvH-i3jG+acIz69|cs+p}ny!Y1F3Ztf4Tp!{8N`6!p*<@kGGfKQGa-qy@%B|RRE)qCe#iDu^o|G zeHko(ZB*I*GFToC{hE+_==~zVCAS60tUUqDBH^6*&-;?AuK;dn-yv?A3M^teChsHh zJgPeo+m82B*MR>nMno@kR7iI>kX@4p__ZR(gC-uZi>w6#8asgehWu~tbBfsjJ{2FJ zu<_h~?!))yOV~kdZa~@Y;t(P0j@EZN{x5now?2NY>i(cp!Kr~HYj>ypXM*$w z0!hrgpnHkIp&lXqq>%qk%75Sf-(&!pk3qL4%;aA(2E&G2|ND1lc=(QQ#7@fqhA0>& z?X=*HT6lT@68`=C%fSBx1JWudaT1EB?4;3<2mk&j$SLO7{U>DE!82*lpa}me${n*) zkW05$hCxB@FdCHM-|>)YuOfHI4hc)qkZiY9dLkTv-w)Vnz@ROii2I+w@T+M^OI_(z zhkN9R?}iriqd?BhSqAk2h#$$J!O&S zsLk3x=77Hf+Ob^$W_;tmkUztL4fN6c5eJU*56{@X$aMTDi?%^ML+d}|K%fdNhc<{S zpbaA83pzCi=YFalI4(&4ZTOX-uPfr``Li4tB5eS*pM&_JFYNyW2M*9SbGmYxsdxo3 z60{j4{S*f}N)Ldp=51&j0_{VfAFc^f2Y!)*uiJwC!pz@>Umn^_j@wQCJqMb)O+e-x z6-Zrx_J`Zr$Lqj9A{@d`&iFZMp#ja^NSnBy2$d^Ff4)lRWIq-e; zYaDzxE+8Ci_1mxea4h@Ng*4g%hxKG#3uK;>84!k-+h zgY%=A>ffhJS5gw%g-i5K%Ypj#KY;q}@iPE^#KDj1fhn9HO*=n;9IWQf|9$wS`%oX+ z={V5X*^AnU%>)P5zZ1V)Kai9jn3e<0kUp@iaokSsf1ZQ0zpwliA$H`viD@{{3>!fG z{bzy$OP=3|Ulrn4`qS?DZ#dB0JqYxh=|9cEkNU)^`U4BzbHA-_T`S34uj7Fd zqf?Fx8ZJ%aXOn!lUih8^Gw8!MQ~0J!S4x+Ho^>)E2l%bo;MPeOu)e-~k^=*1?{8r8 zXi5$=H#I~2*Qe#cjPEz%H-Px{#?O2CI}Y&Pd7$;`DwG48`Yx0MBX@YNB0T$JDh@O^ zxBh9%{`VZ1!abzv%4w$JrHrA^0dmgEG#o^3JBiwvA{^A8bOJVa;CagM{2^n+FB5Wr z^J@Fc{6Nd26_$O)v>dE}XTi=CzUk7HGKKg}pxys897Ot^2Cr_cndG1@54Hs-c=iRf zp+`7C+QRo^qc-FOIWu}X4iG=e>ExWLc&U}J?2+?Hr{N$f@HBen%-0-5*c^lS$NdNl zH@E#|Y+UB^5(ypMD2_!$I`UGoXXG{u>VP8#Dj(qqu{% zh41GFI)3e_9Y1pJ>fdo-4ExCGDXJDrAO_#3p`VT;Q?Z;_3h}nG>ysqE)4F{2S z*{BZ$!hyFD8V>g0&!gvG zea%6nLoP6Zei4W-ON31p92XpcO?~Gi2e_Rih<(BzARHiVVSH@-4+n<99q8EjJqP;GH{)wP6XG8;Q{_8d zy3#HXKXTUCG#te4y@2|ke9b|W+X-MK+=z03x6hdz8|zPub6^zKF*!e&;6M+K7vJmJ zbcF8xKKz?t*}Fpg({Qji;R5J==KKu@(e5Y5{cs=$c!#`i<_9PT+wM-z55~`kyASnD zP2hW7n>MUJ)0NXq#Y=lY?8td@({QkFe<6AX-PasMd!7PD67c*z=!wzTo2&r!Dqc3024rLY^t<~_93VCrGlg%ubYh&(fbeJt+-~dyw;!~F+J;t8RreeeSH1)% zi+jNF3uKUfx)r2kKLN+`YQc&8>mWPtD#*yX4APEX072mwz~-%IfHVBP99#QL;OLYF ze0)+sSZET6faf^JgeQZz-O0ZVKjLqP_}cyP#~-NQ;DqnsxXt&t|09`91|uUQ;PKh(ig9&s0duVcoCdCcMc#vg@+Cu0x>Z$AS^5l1O)|wl#~?o zoL+pyZgAkh0n{&Y-@bjn4L^c&!sigd{x$vy|49Tt@Sqzl-noPXTf+KT#LPT)tL zL+&GIAWz`0tE-zV`w9GrA1QJ+@U4?_R!wm{zLquqob%lEmH0X50#abKg6GtlY{!BB4v)8QH_M}@$dHW1ev>n zz|pwa-&X&1ECPW3##mtBupbS}T@C`*;N!q$XBHZqw`YP4-f6(V4#wN=2RNHVptn9A zn8N4RZ%F~`HYbDCZU?|B=LDc{9SzT`-UXBl!+?T*2$0tc20ANu0RyXDKo9!4>Y0at zWy^O0aaA86qOcW6DQ^REs$M`z-S)TPpNF+V{X7wWvafwuzyJQ<#&e+QkLUG$+K3D@ zHNH)kE|NF5av+ekt4DnW{~{ao=jD>!0^{$XerP|6N6zY&wXFv{(68-B@$4dNfXv1^ z=#RJOhw;A~KkriLcL?zz{?9*>pIgx%jYoX;eiXk@#vP64*NpyQJg1l~8ZW4O;D_=5 z;{Uz%|KIZexBmbCwf(ch{$FhQ5wL3SYaqMf8j!F$HyMOYkl#AAg1*amG+x2(#$+7w zoQP>QU>9Buea5|k6?|XCh4@Xpn0X%H5ZeI#uI+)vo=&jT{q{HU;ww)zUa&6d9k7mvzxN*719YHdqYjL;^bT6*GnJXVNtbf2FuQqC>|xf~;*2+@@t5+Nr)G zv_s7(piR{v;JLD%f3u>2*9&J-0O7AToB#j- literal 0 HcmV?d00001 diff --git a/games/NXDoom/data/doom.png b/games/NXDoom/data/doom.png new file mode 100644 index 0000000000000000000000000000000000000000..3f6b37b1d80a722b4dd5189b4b730be48cf27dca GIT binary patch literal 4551 zcmV;&5jgINP)xn1SUMhFNA*}hzB4-<^g0xVksfnjlqGCcw@9)j5j#D%+BoW?#%AY^z`&?`c`$$ zkB7Q+_jGmjWvb`YQ2mu!UAJ?px<0=;=lp)>)M;R>vBnx}tg*%#YplqLsXRFm*!ruV z{iG?`;}Q~rG~yshAPG|vfu!V&n2=IPNgO1FDT!-L5^)KVMD{+WF)0j598#K65}8tR zjY&vJ(qz&Uf(TNIhG8D$Z)5~kHl-#^rdLcuZwS&1l6u1gH|qS#m;ZhF{e!%oj_Xr( z;-7!*b0_9z;{TbLOr9V~5JG~a^^uYQAt9v%NrIFTQnc)I)-4mU_ft!H2@=hHB&nHR zSRa56cm`+Y5)9_tN7ke zmyj(~R9%KrB{Yutl#X;vOR2gBWd?Bmoh7_>;lEX#J`}18iM3J#i<2>Bg_5!=;KDmg zs!km`2CYeXCK48Cy!!nc^$WIZTY6J7y{>)a>!O1005)=&mFmx8346-VK034QDo+)0RRt{ zD%e@~zkwghB=A35yC~Kym;Osn{UYX$&jA1)I`t9Uxw`6`{zN)~m3$RfvsT;V3!l0V z_uOkaB){-W_ac7j=RMPJ?Hc&E)g1u9BljG^Bd0$G0C?c^{g8!X+wb#|c^}~)u518M z+bC651+?CwTFVn#ulhf|08ld|YAugVsa$oJ8-1iFBIIk$cu=8GaWBWH)_bN0fLzsZ zmn*dfgdJZps`Z}mt@O?FGldqQtORJ)<#(50mMSnC4P3syiKU%t*JFu*<((=TqIs9! z``{MlVgTnHS8r_K^4+rU`PPdKY?K@B`tte?mVbH$@u?*4-p=B!8#&+f`I^A>T+?$Y zR}Cy(d>>P@Gbmo^%2+&ahJG-5cno`BV(ENgda7HP;vh(NtW+htmnH6l$oMgBgIv z7~WVdDPa)`1Bkj*8bBzjfU(p`S$FVL=U#*a;b)fNGUNjHPr!k5D^j9*4D7Qy9-^{vADPhT_3*Si^XC{ zr_%s{QmKSeY4E`#jyNME*iAtCk6;?5LT3PmVIY@lj@Si&bUKas`T2qKA|l+nbqnQk z^9DOcplRB``Nd)}OioU=Z7UXwC=?1^Qgj#Rz+_?@9NmY%9fU$<0ABDNrPFCFEG+b$ z7ZG7~b=C6;)ie$B^Ya54fu?Dgn3(X~m(S;s&*%Hji*ttAOdUEmdLKMug~k9((?mX> z_k`~#lgVIlaj|D!M1CYO%#j8zTi8Wo}R|BW5+tS6A@NcRtBn*HBH0R z)Kpg^7__ahwY7z8w)0hgUDt5`$3BAOM1RI~P*Q3DLI{-0<$>Tknwgow@#Dwc^w{=>a}%4Jo9?=%X*hN26jCYgHiSwk3j_%vu)DiE6nsZBGc#^L zXLWVex6bb+&N-6FB&yY_>&Nd$ckkYX5CWWYJpAy(NG6l}&T|w}W&rZ-zeG|`K#FE` z&xzoHtaVl|Ll)NT?Qo-fAOQ9(FBt-A$vN;u25Gx5nFO^(@|-DRrY_zF8iqYxj593_ zL7H~p#uPAl45jG>m=gAsGUQH8)0$VTR6rt^v!i|lDTJGsBsA?jv`7 zzIC7Hv3vKC=dmOKY;0M-0SrXUwqItiTgwVx4p!F&AWxv=3D^%lTG9pqpZws<0pZ&v zmmhrVqfYAH4Rktf4ikLZyBrLBQaFN0odHODB-I#xG)n-I&O+4TGmt_PP}lq%Kl#mN zg>!@`Yy%KLYz*JtuSyE1h#5cmt;eg9+BSf77a|WonpJ?bzV-`WFdc9G#>=?$_-~?= znzaK*WJeasnR^^W?b~3FE41>lmYHcHozLO;+I2koUq8m9@BRp}Mt$V)Rh9tCOt1dR zL&S;g`^o?IbFbh>zxuoli28z09`IYYJ9*7)Z{Ty^`YSy7_Jt9`XE2HI(8}d#jR_2* z*ssS^_>WINHxl?H3AyP7eDkG0#^3(#AHrn%NZ?CSTLma~1F^3z!Zw3@&`)ETjW9K={#g0|RL7Ga+&A z?_LEn%#p%(w*TOn=W&OQLlO@Zek4nPpj^ENue^;H{^n1>40ELLL4^Fw4Bq|tC$ZI- zg9Hx@ek2VbNI(DMm)^vSfBjX!eobo>@U8v8wMR~)N=eHIT-f`AuhI<+MRAmBLW7aMS_6I+b-N9}oFaY@NM&u7azFWrer4 z*jZTU3qDCgIg_!D0Z@?%NMi=Gx-}4WSokVS0JV`o>kb40zZH_-lfSTf8|VJ~>vjSw z?VXb!#kYR%_mNv%^o0*1m|U~r0t|$jjAPrF#*vscAa!u~45ZKmly?UQ8QUk(U$Nf` zp9na%asy|-@fUzSNVFS#Ymh0q@Ey=qieuZzba)5-!H=jH5H$Q|osNOvJIlvbZeV(2 z(-*$8y%j#$%QYEC&YW_+gF)b{Yy*VQ4IB=BGp^91!6&E#zO$U($@heRX6ySM@Ie4E zLX~3JF{dC}y@NjBN7D-k8a|=#*1i{f5Uk?e2ma?b-oVRGo%e+AK&(m~d2`Y#3HpQ| z(JCNl_?@6Vw{?N26Ob~=L>kkC$Qe| zoj<4sy27`2p#~iVk%V+%cZW|3>j1S?K!EUF1LzUt0mvIZ?CaN3sM696q5Z{AND^I^bhZ6+i@>^@1;`FZfnndPWS}4FMm4lzvuxUvVZu*00N;-90fDpa?WvIK=APUc=G+=J28Tu@THZiU-;HG zh6ZsIWXvuJ+OI)IF%A$s{Jo7pFZfO*uM@uY-3NTfRkVLbKk%L78d5`1=xyGC)1#_~*AnOJO1s~Eb z0es-Q-|+6z?G3-Btq}lx*vA@?bOYU|76%63uRq`M1O4IKp8(+l49wY}Kx*B<0O7X+ z^n?Fc`LZW`VgzSAfggMl6exTUDV-)R9ByC$@LlLW@Xv0%f#*K)mN$IoqI}^?INib4 z;roYAjJu6W6;kg81_j^k(d!QXi@o~u`+)EKv0-rVNvQ#-bpwNhPu=_TpV|60UOsaH z5Y15VUif^1keKZQz6csVvvX3T(6#{vh7Wkc|DDZ$!b?xT*^KZJJmH^uwT{Gs=mFnu zCm=xh1nZ9z6-k{N7&Lt6=C;6pe(QC-@bp`I!n@w^(+~6mpR98uK=@!FC%B+M%Bz5& z;I|IxA_C5B{-X!{CO}{a_--UHNcaSmO)=#L5Ey(y8~hia{?{%YJ63T!9DE6DX6NAG zJL3aXN$vaqLBhAc{oz}g3=f~&&Y+;+TmLj3!A4-<@WJqf!s~eE>5INyx>}rY>TAQp zx2o%4;YW5rNRaRez}a7a+iK+b^y*E1v>#Wm8+?LMwYmzHfQXC2n4!-3Dj28aZdlR_vFPZ;0@ByV&00FYIJ9t0y@Hu||sNlc< z+5)5u8a`9n22kD?5EOg@vt#)qgfB(`pF^b|7@AOU5HoOE@No#?N3aA48a@Gs^T{U$ zl?Ac-Dj+EMV22bwQ`i%r+6@d4K7k!t`082!A($pEDEN|K!^a_m&y-q#+P8xPgm1+G z4%?G&=c%p@sJ1U4Q20(8!0`eO3w*%ZuSn{=fPmpQy^6yJKbq6T1q|OR0WdQ7(uKWG z_~Zp&T_ZqY2@ouNrwSMqe2aSk@L4DP=vDy%!Y2S^h8RBl;773v2pT@IaKrZ~_8s_< z91<2ZeAf#I8~iSHek**6YzYt`d;-D=->2AbYriOxy4FX)@CgjkIGpe!X#hdPCt|29 z^Fs+=MzakNEPMj6{`v%rJZpo$aVZ%x_^boI$`U|bDA;Wn1p}YJP~X&X_3JZ8{z?OS zQlfApj?MQ|_VHnX@AW&?NudD%{x@YX_|EZWnWON-6pE6=l+J{VVTNyCpCW~-FJQm$ zn++<$BqMM}hXB5vUXeo67Z4PD0^rQOJIN(FE=1Gp2fZyh9jrind!jDEO`J zR-6Hhg#&&mxm9KJ($LDLS3)44n2JM=k4`eOBonz&l>*XdT_t+~*ihGgHR6$zsNLzH;T#cQMvj lV~sV|SYwSf)>sFr{{x~w9vdc(ZGHd%002ovPDHLkV1m}tje-CG literal 0 HcmV?d00001 diff --git a/games/NXDoom/data/heretic.ico b/games/NXDoom/data/heretic.ico new file mode 100644 index 0000000000000000000000000000000000000000..90ddf8582bcb7e4c222b130d63d23a1117105256 GIT binary patch literal 44563 zcmeHw2|U!__xGT(M=7F2$-ZVC>x^~AzVCa;mYs?idqkF^R1}fYN~;zz(Y_MVA~O>0 z8EKg^&3*1?#8G?m;*Xwo7+|P3FIq$ojd+s@BP$(wUEEMv`gc3y=OQKLK z;dfr%(R|Ph6zU+nwqU_%KARnd;*&$6L`6sQHSoDoH55uo>04eLg)%fjp|IG|yp#b7 z^(qvF+F)aak9%48Vz zMDDgZS@aa@(b4&={3{-8mXqCVYP(cCr-Ms#Wc9P#JI|5c9_gnI+c-YH_v%e`!v1x) zdA6N-e6lR&r9*O)R-9Aau_^yu-`#P7Ps#G@jS_DK+C3gEKl!?B*`)M0-&vZ?mKK!9CNyV;QKjw>K|bofnQHc3H=`wUbFvK_=B}Q5 z#9*0G2Jf6|<51Br2VX6@GQ_cTZf8rUzSPp)TWy-9@~$|iN=b5^o_OJ-T~Y zg9)vT(1tCWJxBl5(+0FvTad6O-<6J8%-pG+)TLDY_Zn;$y3RH#wx)@2H0Fa1yfcLK zA8T=?TPMET!rG+r=GC_KWxYEc51{|4H8yoK7Wah=+ z)&Dx6nE3ql9Sd#w_QI&99Po8RNe{TW?)KNscKNQ=A~Vgl$6ZS@mwGZRn>={tIDAgJ zXlv9gif3Ra{kVH%-nsCDJ$J7*7fE(Bm9Ey3knh8~xOpZ~ouX2j;t8>w_*5BJ0OyYcSWc_8wO+taFfJ5uGE_6no$m zU4Rs`Igr#irz?*1!d_Om{*Gc`39IbzO#a;PD@lr8I);*5 z&-e$TlovHdHJUHphIYD+W~seO}&hM zSJJ)o+qGKyYUgw)2E9tpX&lEM^m}3`NwM1=mkGOjzD-S~Eet|=zQ5dmuH&P-1=gqU z%j26*PB+9~eSH45Qs(Zr3%YK95epH#r@wYLWy_;So}awqM^=`yXX+CN4u81$j%*#F z^U{suT=cr4^LZcNhk4w1yZF%Hx`y*ng|2JkOQH^=9zV_6v8M5h{B6&K&6y_y(stY# zI2<>7@tb3w3&YBYsUpzwzQf^F%f>OQ9-c!j}FP~iJAfxv2eA_OfyJLCR;NbA(gu&|# zrKHn0U*tY>O<2XvuIj!<d67ET4dYx zS5>)ft@G}l?>xWFMd<8BKC2+*9xs*hNBbMDh=rn#E`GhnD=F}N!M#<-TaO6Xys2A} z&nv%j`6iv`(T6|rNb-S%lC`TFQp^e;U&lIeyRu||*m;;kV@;{^8+KzVE$_{Si;B$U z=Ncb7&5r-jvshb9!QyUhV{~9a%hofW)`T+EcHdeV&{OrEOng=xtFGFt#Ie)v&@Es5U@A*1a)WnLA}r4%9@sRIe0 zKD@rNyMObItlNq)(Yr5R-hIdU?d!APrsV6$Kx1Kt24^-cEk>lU4SR$=hJZHl@lQow1 zujpvYYbRL>7KcZJp7SOiyG^87ugLeFHC|Mo{p$9mC%jJ!PV>;1|{UL8Ag#uW@5n0@8cmsNdNguk*#&CAsp z>5jo&K73Mwt3`r%mvr!+Onvy{C$AsacZ8@d)=ONlvu4G*m@=uI`7BWh?XA+1GV`?d zhh^Grs@}3Ce<*IGJGi_Ledy33qtD{aPoAv6@l}djo8_b;FS9jt>hnn}P`uYctN^iQP zJIycS7{0A*ktuSB>3ww-*;Fo^07#+aR)y?cwDV-^6X(z0qSImj zb&3s@+p6wcDJH+tx)YUOm`!=!R&}Z}PD5TnA$s8E_6^%o21h*3t$u@tWXQ`OJ$6j_ zW32xBr-~&vlAg6x;R+<2=5CW+FITc=xiFz_R;&He=FUzh5=C-H20OL!&b@=qBkM73 z%Pd4wNl~*#;={ti@*d9^FmHZnHDg z*!4nrP;l^um}j>GRxl$OU*FVAmo8Z}UuUKpxt0>27;K2y_e`E9?9VM)eW=&^#EBCZ z`wB36a~JJ;7WMgE|L)wcj~x_BTwPoiNOM)s%QRThzS-*Tqv+7k&^?h``JZVfhi?~r zzE7>_*eqUiqx+8^i?gL2&A{ZaZ{(yK^+#`yKBLodrY{B4RwGf@&_J{ouyUoYyDEfg z;|Yt1h*(9D6uLZP^9pbpHYWyyDP})CIwLw4GRU@@slXczFKj&z~C$${n&K=k(IQj_4%3uc__p>U4_#_@rHB zxt?EVzzHS`A-d6x8#i=@F7oLnR}{fU>+W6@6BEOicU(kV0`}eq!>3Q4R8#Ow=xiqK z+o*<`(@Q4%JfTRw3}9|g!`SY3fH22(mn_cF4&K1_>FwiJA>s40HE`(2@aJZ;>GO63F5WRyT%xep2zK%Kf$f2- zjwZ7SmiToY@hpOzpQ>E->ZZzvrnz75gh0y$lMvekLG#i?Qb%OU0~UDud#Odt&(gqzvsY!8QM&3uK?eU zC%JnU=ib?%%zd~jakEtKhv4g-gAwF=4O{o$5^B#9w_jJiPdD`J>^ZSIm+n7&C?mO8 zdrtoj-YeV&szcco*vdOKr(;Dqs>^}|mp(~0OC>hZoiP#f_%3fj(OdTEWy)MEk(ZV$ zx-*oVcjv?cW4|m_eAtr)`r*YZIq1u1^Ju~?B`4OL*duxJxHQdSsn&YZ;D@~}cU~qG zT)$)0RXV%r#)r3h3B+3mU)}05*E)9M&T6IJ*o611iX$bY`@FV2Bpl+WcQ=!U5=?RG zDB5}`l%eEkkB@XkQY}v~4|5TlBYGoDtv^-eH*HiwaVBTII!RfBzRm^r6#N9vaf&N+^Odl1yph`fH&x~d)=v}cf&VtR7t@jk4aK*#h_TYk;3XJlFF^9I!a*t zd0c;BK3SuU`6ev5DYL0xOKWFD4$R2W`00DW#!L||)s&Tm$V(comj$s)IYA+02yDBc z80HSiQALejAT=k;`Ij-dP_r6(VyXOeKe4`1vh^C}qpSQY;2qYp@XnP*1eVVl5oSu8 z)-Js$m?4rO;N3&cY@%l0Yj->$rCO1>x5*A1dHC@KddK@SjkRlIkKfb)WYtIY1M9p7 z-xWFT`rKy8uh?N@ypzLO?MZmf@fabuJNv`t-Cq}%`dCqZ&f`?q43Z9~(rr}A_6+YC zUSBq>OQc?TYm7RH?U-{!jA-7d%^c``zwhX?PoKLb6_1_sdcF2M=QABI+C}-uY62m) z?10E2KNd%3j?B5HN!B3jHDBrz`^BNw33XDh>AlA?lTG}4WQiM_Ydv~LFlTpZ(q2#^ zdvz5fR-f;Y^nMtU)+FDczl$dPNt)lgr^Wp66`$VnBd`TrGemrRmt1^f^Yk_c-Je8r zYyFV$%qjh7bM4GMQq*dpT_QIZ(Ig(GM9o6MFQ}1o3hq4Sewp5!I%nP9CY*nyF>r;W zX;uSwN#vc~10!o2Nr^l{(#I&)_yIv8S95s=ctBda!|j%^2u)+)%$Lu6J8K0_f0hh= z-LpevAx+=$C>_K9GM@ZdZR zAboQNJ#P*F>7i=1w~0xD?016??n56SAJk0zT2fB#`1B@bpyixgWBm?xn!e=_<IK#IGFcr`%W%t!mWah*mJpGvg@j+& zallG~5=yK^d**%(rnYx2blPb_?wULQtG#CX(9S0QQtUoj#G-)SJ8rO>E+(_?c9ZsJ zZrXYu^<0F&+niIxPID90ad@BBba)wTlWnj~bcl-BH?6m35SVB=+Pt)jdpFIb39-qX z@Q4v(I{X?=9hFq=jN9F^mWZbfZnLe@9lPP+uj?B>Epg(oNP=?Zo%@`9wDu>bt zMT~qemt1wBb|&orB-x-tQk0Ln!Hh4x+4{BME|E0s(bnp6?0QOR5X)u36jg$|3MU5g zcx?v3^1U9W^#k)4O3g|lom}t|Wf$KWt*F(#`wREnc|nx(&mAjxOR+NbrB=r&JPLhW zqHS_5gQuGx^4(iS?xLiYpHJ_U(Ua&A+2{H4nYqlO)>MPsbQ6;DU*%4;LjjUfpL8(@kZX6t%bf-0khpW}B?{=FCppV!q|*`!|EE1bLe; zOUnCIc6<}IiU(ayQ#>i;h9%e~9wLSCU@TsGBnn|XY1&MMk zip=#S7vH{+&-X8gc*L=jr1lP8Y^C5dMX3Zl?+kwW9Dg5i^6O?E(cP5HWS}bGO}IFM zq4OU0Uq=19W5u8o6DfDchwfu_loO;m^z?-@Y3a`s9n+rhEh&aiwAl21y|CzlK<*0* z5kb0tlSoiTp}~b)D8le-q7KV8Uux0&8M|86=&j2M)H}Apee3StCi(;8p07ItnkzQZ z`_1(fY3+yet?7@-y`GZIj<$)~@-7~Em34@4LhF5zcNY;<*$s1FWurf}=FMO;xDeNV zREdrDVZ#cpqWD_W2cF~X$znC9wUt^f0CJw@k;Jota2*T3MBhu(Z`E5x`^Y>J!Jm~b z(wZfIrhGZ=+R;>z4tLh|sU!!u=3o`bS*Nurg@d$LwYN2v*c6z3B0L+6JS&HAn;+kTxdfIZBGEY|kyw!89OdG3nxpAiazcrD@|raj98LR@2^vKl zO?#8FhAwRsq#Nn;rpS=b-X>BOUTumOPiY`38u7(HJ$$Mu%zMj*3+0OzQkUr0veXCZ~y?_r`KSr|zlrcS>NnmO))aaswGI?&FO>2`h<_&31c!iCC%P$ig z3W^jlUI&N9Ue=le`!AGBDW_JvP=)gHup1LBS`cJBw?q%UddBwlbKw)#^wi$2%E&%7roA(hH-FL>J#E&jWyM3ibsScLMQvfB zX2uE=$=39j38^E=F5#w?ULIj$WlV6I>&)L^J;Jgd{9yV)7b;li>eQMQBueoP7 z@fW(y?TPKRuDqv@U7#`Nl-I!x{5~G+DEM+p@^dcufK5Q}-KP5ky&@%=r){xa^U`b* zmcIUS+dEMUn-j&HlQ!ZoqvbQ~x#cGm=(F^)vT%#u zeci&tdm?Vej>iw_`6>%o4!nfR;Wc&PCJuCdd_?mGu7-DsL>}Hf-b~SK$sKco)O)R) zxmogNSI=qkRX#GKHOezZ5U%^pPv?v7gHttn*A7>zIDNsaC27rJ?007fx-e&}zM`ay zrY?Pd+`W3uT}p1PXjvGw>Z`$mkQ1GKp!e3cjjC{EC@*^zc-m}mS#MX0!?l^TwigHJ zGCrHR5@%*78)&A8RPH4{S+Px!b|Jr|SA(OYN4jFo(wHbG)wh>;pPgfIY1>Y$ommzV zz56&%^6>V7t5BYcX2C3-;mBIj*2^Q4v-3`|Ce`j}qmi@NYJo;CBZ2^j$VaKfhV{Gr zmQmFzUgo9^FcI_xgO~;cvH4_yN+$hFb9z5%EK(g}~u(E0Mm?g|$$Ux;sFJsANq~x^%f#L6|%F%g9+nYUuFuBsEoU$AcDbmD@WqG1X|VP=7kBcTQ|A3A=d!evN4|GsKhrmRX0qQRtX4#z070c3F5cM1 zIbT0eX2xED%g&B3vzzQftemw(@>9HRc+-ZTW$q>mFgcn(JDi!!j|@b1Ld9~?>`vZGqbO805c}V;T{prMD<%msFtgk zP=?&1_S9GV0(qL)Z0uQDYJ-bWZbuSNXKEb`@u6m#2xG%xQ_h8B?yBKYOqhb!z4>b^ zhG=24l$OziYPe=&gce!%v(mR7x7Y-y%d8d2G1r)zU#3v_?g^`U4%bn{YG8)*w3=kV zDSo=^7D!S03e0{#-q=gRYy^2*fhP%4Vnm*~=b2kEw2DaC{lnKdX{*iZ{AwF6@C-ez z;6hr6{=7(JLh7P`PNFrp{kk-m>mVV2-#++`1p4k zRw}hzKHbGWAIeu-k+W*VQ<%uLB`D<-5#s*+P--H6csKks;*7M(HDsvG#IV`fvOpoJ zMyrO4oE2nqN0gG@Y#L|0>wQtv;*JW+!qZwcskNxjX(D#AGd{34&Fb(~r*NjVD=&C1 zMcq`>(Hh%!e0K6Hf+5n=xCl%&v$f>6rBT^+WN6vsJ(tDavtY2hCCzi_{xFR zBeTZp95~`lt$MK5L4uN=!{vjb&WSv*U+GOz^2z`&cF{lzOPfy_6S-?ib~!f&hi3|e;c{!Q9cM=d@sqpZ#FJqXmgTB2E#-jb*A^Zd+wIMYtwCLbECi$81kDT*mIv;f-p#@o z9Y%d^COw~tUr9+Puf3~5LxtOMT;rytsn^bKg#`%Gm}^euW6yWJw0Bg_6v;3UKjQqH zg)n20VjyMVeP$FK_dR6RRNfP{U(%Yq*tadA@qUnfzL1U*Drnca5YeNJtld%?6iHI( zSEQYmaZ?@;6>GjwdaB5*c5wP*Bd}ayO4&WDP@BrM|9z8LZOHcgbq>@ei%BF_+R|(2 z6rJXXo=~I|9CeP{%7HhtoA@hcxi<4eb@k|xaq}{Znfh4?DsT`kyAHdc!$>+@GQ}GY z3&O)1r*=VoXE@X^5u3|71%pv%(nSh)yyPUv%g8YKvtgFzIisGlV}@k0bh7gaQgxpq z6ah*oEOv2U(!7h_Hy_*=>rY)0(wW=%X}!o3J@`7wh{g>UjbC(LIfhf%kkrXpv9((Y>^?8J4iyxOXb}LW}Pe}MQk|Vgg7eU$T zOom9M8ndPloSQ-(H1q5^%M2?qm0^mR)%0@Pt1DjXZ?hFEQfCG?Ft;uw91h<2I3mY) zEmdFW(ibr}EUwiF4kZ#J7Sm^KMZIIgTWqRN zhppye8>I`!+-Z1oHX$gy=hZCC#W-FS&Sb4srv2IR^HY2(nV#|zmZ+!bZG9dt%vv~~ zCJHNf+>5JpN?HGorD;O|3gTHnF>FAyp6~6t>%p{5oK|STad#mBA18EOkk*N^u$kS< z8X0kuk7 zLxkzd9a-AIJ(dN|%vZ%|AM8h5s=E$%G5K>Q`z!2!VqY?V-Peh?fy>{}=ZFfXR_fOd zjhi~OqYfuEX!zmSZrFp!U*2bkq#Ec5;@^@r277t71)-ku(M=+VJqO=Q^nEmsz) z1#`Q(3Cnh!uh%>}bZz5|CWGFD1ClgTMWRl#;w_Dy1%g4S&lw_iYBW!Bfecf-JyQTH zCgs2jf822J{xB=YX!fRK!%W+DH#93=oS&#m#tE@R9b51Hymd~EVQ>Yx$eYUj9)Y&) zb+e*yZOVGPqs4>eR0C!LH zioCv7o){6nK2$MB<1m}*ENamjnpYB&N0a8`!=F_jQAz`6LcM|<@eYwzu5yaYn>mmuya#fN>+*CEhp{C|Ut(u$imIIU0UM)gA)Ka_Lp3(5E zHf}pgKfB$k*g9K!9kuE$@p0dpL>u3AdhXOfXZVC$d>UrM!8Wcgu5z|{J65s?-I@FN z+A(k8SE5?6%*QBqPHj{}#^AMv#5WWT)FKfYZ#{EtDQ8_ZpG^(Y zoaL`aAG)9zyM5lW4;(f;Y9){hWYfC~qHl3pUxn7jx3+;|I4pA^n7XOs01>JbAzpad z2uk|Jr~)r|ZCF_Noevd0xWJn+It_P{6w0Wyy-a zVMBg;+M_vw+>pYcE34B~e}_49co-xrRNOyQ5qp&K%mS_rdmzWn-K(GFW5bQ59IkL; zjI879Wx^<8Id{W@dhcu>t+_67Va~e4lnW0_Ur;WyB)<#p-&r9}Fplz8NmhKzT4qSK zJc;!8I~2|~S>h#uAEe`it@$^)+s{^8$JY; zg@11Z@ZSuz!|ZubCc9Kkl&-ma5UQFxt<6g7EwUjMYzOwATg67(KfI-{qByfjzIMjI zC7$IL5D|~Ck=5_7=}?($HnBhNh;yY@MMyTcxG#|C<0ALA1`)j;R%TZ3LP3LOJh1QD5c7TV3;MA(OS|vhYq>+{ zefKz-Yk~9Uzn7!Qy# z%-vN0&Q>0nSjhroYiWSd94$i%?Y?=^YvWl}{Z*Tta25b5!y-@(;N9f`&Q%8BT%<FEQIGR$|b2D*150p^N5Fv-vaW;)u8B(LrFQ~q@= z*K7{)TM3Xda7PP)J~0Cr)CU9O5=&r(!2%mY1E8oK@KgLT)(M-#gF^vQhFxhsu-!}m zHo4)zGQ$%%nV2)$Ww~zPPv3V5%-vD8qZF)9%K!yAc_1Y|5v+#R3NayJz}wCl__??N zL$mPGNoD$qS7BoB`)Y)>ImmfmHIa6^Vlj#^2@=^R+@iUsLJ3I;7R?re3~Y0MXIJj4>|9 z>cEvO04CaKMjaL#<^u*F6Y7vvcbIbdn%I>@XS^ktScmb!xubI#ti!Bq&RWfzE>%U~tq07#=cVV1;*A8*dM!UoF>k znKC|Dizs5C_X;pphXY|1&?036Oj9V(KkLT83hxiwLR*JXhnb!(Sgz$soJ{A>^7@w1 zL}aZRtHWkX3efD|39wD;fWg@i23ELuLtvq;2dv;6f{b%zovD{^U=v4N6&TD|50N^o z%QgaySI2-&UJS6>5X`^|pK1;4;2bqJ&Xsk1rcA$)?P_8~Xc!o)!!zOlnvVsu0#m{`XcRulWx#4(7>i9f@8^7XuugZBpd z2S86x4|w$O5$Njd0ynPT08Qr`LEVvBu&1&Llx*D!;-X_fbYv9BOil(-fvbBam-DlH z2~--4jEsPxp&>>ch-}c?+Y4G-TN!czv;+ju1PyH3vdw*8m28QoAIEaw1|Jy@m@02a#Hf&~)RKvXkn=j3vJ zmKRW4S1Mw#jUhK6GR0zpl3#vD-uYR1ldn&A`I6?vb;@2Rz!IZvV1eoyu-yG9<2xe9 zEO)OP{SIXtCHGp!cOi5Nn6DJGe=?mv%Nwn2kHdtWp`ingji`7W`Yh*ILzS?q`Y39$ z^Sy}C-;*FZ^`oHn`oN!+H=Wl304OR-WLgqZHX?_K!i0rsTn>X9Kwl`|A?bg@pPXKZ zoraE6pPIH~znZo~zlxSEOg8<>n%4cxHLd!UG%fp;)XfGI)lCQF)l3HzRPp`tYPfzG zRTG$uk<=%u;cNZ7yrOkHx{BPNYFr4gcHqYwLND#$?5bG?*ob z1AOE%M*YY>8XvqAn5`1|VOz+noBnqFx)^T~viF}%gK4H1z{f8IcqqRh^_xbE0@GMw zC{zBuKPagEe*Jn_ACe2+ilKj)NCPfk0^rg`8FCsz1Ag6NU`kl@SARhE8sFq+MRjxX z@3ue2z?X!q<&$Z^ZC3y$d16q;g8B@ohrq)9P!+%ph*3ggSVP(&dw2?qtmj4&^8{k%wd>mXD`k#q37@V~OhDS!_P=p4fDq&!$?1Q{pOC*q{vm_U?L4GqN9Op zCIL97#RIRE{=mb}2RN)*3G8EifRl&g-{xvfUANz^-_kjTgzWbw(=gT+V|{Ys*qppx zATrG4d1b2ki1aBqJ6%4(&h=Lx(ZT))8bxF%7Pa=^39b$p*IVz2}7N_vmyg|S6ouC)JnevxiI z;FAv>&m(0_E_bSV_y zzXY3c2NQK0$T*w?lD0?To_#IQ4ZjLxollSEH4=e#NHdUkJIBZiX{G^$7C)=knbH?pN&uKh5H zTc6n^Vz9kZM7LOZs`dSe=aBh@jzT5>iG^%Tospcu~41TX*l_dg5) z6X2YTcBAQ_;8 zmind>k^q|O%YdSa+L!5~-$2iD1UbL^B@cRdYYh6L~Nz<^vWxM(qH`#`KToB~>-8X`>%+=rH19YQ;Dw{TUBNrxpO?{m^#d zn+|l02h&}1fO*yI@$v989#mAPk$xkm5yn3JXFQmg07IfEFg(71aZWyw2mIdI!0Zqg zw3GO2O#g@nHFfQ2!{5}zdBok)ZdC9410L+malqiB3@|(|@=fOl?K{SF(Y4&bw3ZW? zU{t@GmnQR|uBJ0>^qb>cM-Us1pYdSlfM@6n5gyDiqjq?RjS3C}*EDEDf)OCcR_x_Ft>+$hm>tP14*P-4Ov3)W9W^V!Y;4laUFg^`!U=SXx zl)syo#@2^19yHXakA4d?_YuVY_v2dsWp^^pp6Z} z1KttZdQO^KC-R`7rZ;W)TbX-|_&B;U>~#LlgEg>;uw&?35!)a$w^1ED!h@+Zltmlo zGkCyx$^UI`Md%;n0j)8O^jmt3FwPBr!h`i%XND~eLub4~A6V#)@?h$t!LUI>c)$n9 zj*sadwS%TQX4>$#w(=hFbM<7{G5x3=tkb=KZfEeQJy0}m^c)28fDhLmotK~;6)r;V zZ*%L!by`ycJ8ksa+W3wjHc~(1!7^{AR| zX~W;n-hTwKi~1Q4rd4Yhc54U^MrA(0;5a-_t8)g1TP?Ai_&)UJL2=1Aoo!r>mI>v(qMvt+d*44&M zAN@`%M;PZ;KjOjF0~lP|!m#T@&e04j!vXemB+x$@1dK}E#^)u212}-tI>v)J>`PYq zScc6Xq7%^5!A~3gj?O_Np#g!T=U$U|@bUA9ediEBKd)i%p#7i#U@s&A{iZl*-ybzT zFJUg*0}Er=2H(zTt@RDQ+fQS3Os9>0XV>5n#0K$aJYeqZA3ei^JQ$tJ8DFQ3PDGE7 zX@e6kz)}~>m|JbX*+Wj;i(+-nrjLHN&=JO&+YfkH5fluxdK-ZHoAV4F^x8^+r@K4w zaCHUPt108-0eg8RurxIU_69h{dEn%I99GwS+UR%jST%y!X#R)?*9{p!r>7axc?M!# z2m4Dka9$G%oMHpv+>-9buFfiepk=1k;t%chMnn; zc=)He^+)p3kM^R7j%>R0S8m?nBaCy?Y2*RXkxdurd!L6IO!0A)X){PoB!GyZP=Kt30q|To5{{{a*f@|97YE{3MZzPK>G`|=@GSG@AdWd00y83h#hlHO%3B5 zI5jmDtXZ=L4Sw z9;stG=|}7kL`^FGRKtd9NdI)Z_u{kgwg|Cj!sw;qDczxa=i zmp{>e1e8LC)mEGX25Y()b|8rDh@?#|m;=YCl3Oh>PIxrodL7`C4FJ-1y8%AAXZ*T^ z%~3EP+IK9&Z35e3wVxO3Bmx=R3LuD19!(kqz`eu{ z2&u;aImhbnuJedFfd$J$fxPqnzplggc*R{IZ@xgu_0ad%B|M-_lgEeuj>@0Ejf=lQ zkulE(;>KxUnPCc8s-Fy&Uwu6(JoF!43j|cwKs;AZDM4QxFi$R& zF$eRjtnT|c1^?Y0^Yo`1oi@GtV4wfugLPK_uzAK43Z6iEYqYNWm0rxl7upe>0~*0? zPnG>{J(2gkPLgrG`gkfy%CU(gX1cFm7`u63v0mPq|BlLk-~K;|03we;weo6XvR*6Y}Gv39oAg zy2}1Et#p&s^!qMJ!Tfkq_jQ%}K@vxQ>YI*1(_wBMRw!-a)*Xrumk zqrQoHFzy86pEzcZrmZ0X5I;r4CJn7F24q#RFMpT*|MopA=(mB`d;Jau#t?%sJ3IsQ z?_;2@CO&O?kze6sYxtMV+kb)q;)`kwZ4eQEGbH8&VlVT%7@+?k|8_<=hTqPZ?c!80 z!0REgNk)BPM{NuKI}9|{CH`3Z+Zo}Z&E0>1fteaGF&eWI`8x(i`ij8FK<+=9546-J z{}})F#-lceQ^mk^`#fN}5yq#1b`7JpGT&ohks<(NUd;WE#)6i*)F0#D0s4-OofAz3 z1N=T7V7h~Eod3xfSZ$mOtc!X6qxnEvL;8>L?+9apO+07%6$bda*#KWT2jC|7n@+^Q zvX~cGmvR3`bE1xh%pc_60@_SY5d&krQ9G*xJkTxx$^t*Yz-lKqu-?rHV_Ydu83SDn z*+0g=lgX&f=u|MUvd{%4h^^UiZpc5BhbChH?H4WgZ~?15oWR&XY07KkpXA>e2kp~v zQ^Ua85yn$I3+)6ETQw*Pj`=)~^#dHVf3&FK1eSZDEhHYU0}R>V*K4D$hTI=(e;2$p z!+&)u7+8A1cvuZEo)^Tx6sJ1MKeX2y>jyZK<-q&^Cj$c$8+k@-gehTw{&W1hn%MwX z)2U%#>8~|v>jyC~wN?S9$QVHQ|AqnHYB?}F%*nt2=LlnFPEkg}!2QCn$y2A24j8zuzw){XieB{Kwkg+unr{*A}s1 z`V|KFZ5E7}9|#7xR845-HyZn6tRLVKmyOE@xb(&2>%y3P@UyXi=nkf@2@a0*=-9jw?{EB$<<-lX->odmnktWAK>y9eYZCL69xuol|RP6uai6Qb(|Uo z#s^$RZJr?p#>EEXHuPf{;PPQi9>f;_$_FM}guY)Je=!z*)lSoOe}%IL!{&Y}7#N;_ zHs5zW7#JAt!jIeFBlfxo21tCUG5Nr_9Px9Sur^MR6UWBE*uK#at@_8>-_I4=?7K`2 z1O28zfW*8(FfiC}4Q*wit{AcP{pL$yQ~~{9zsUzi`xbt`HcpTeCyxaqO|?J9zrUL| zBi7PXFu-072fAIM3=A-rU7@ZV`e~100CnaD4Qk`^fzeSI19-B0@DmJ-HP!zZ{{bF8 zAi#ZU80g-OAGMYKhJj(FJ@nx~{5bT1(N2T$wUHqsos;-(ZTzRP@F)3S={4#z@hc2G zY#e}2cRJ91wC+0$#^!^ubzw|C&~K50h<6*kyw_lYT=wOFlsQftfj!k0!}T6ZZ?I zaDG6}+RU-Ke~ka&6)QpTieF>k8Xf>NpO$`y!LP=Gnd7K0%a1THhjH*N_2K$~#JRxg z{W1PS{6~FWeuaT^d^jTp-53U#W&*GXum^e`wgd|>7cW7BzTLIbHX|pszt#(62GD zD_IZykIsIFfjx|cKelJGOIY!@wGkh0G3rkRF|ffH00$V?7l~0a`HaQdz~GPZA0D!b z;j{EB46Ld)Gh#4K#K3lA?D*cpyEdRUbp1OFH2e1hPaiMf;q3u5Nt?fu50LpluQL=_x|soI z6XcBP=jTi|&<10=`uDHOjSP!m#G3pk3|9KX-xAtY46LiRz_YDQz^Wn-SnbLNcAJs_ zvVTVWwQX{vfn{+Fu-puPYiLt2uq+4wR_ncii^XUx<9|9|Kx{C6Mdx(gj|z_jQQ^PF zU@9`wRCFjm>IaAo#&q%bt8$|wM}5xzBnF5L#;@p{uKO`jF<{K^?oVNW*kDW-f4?d> zHYOIt!r%7zlNca27{8)(y6%&DNZ{$yr{KwxCxA>MGknfk@3ex}J9j|q?K|KOj5*8r zg!$XIZZUiSFI~I@nqUlC#JBM%{Ed_Y`)a_R-Ibsk{#Hs2^r5SQabe4M?E<>FMcN&~;r#jYKjeQG9REmc zYNXAPPb5v|KQS~A>{u5EO0qKkSpU~Hi-2*LVu6LrYDTj4hzB7txgad(LuQL45esmv+)h*+41@J?^ zwjbT+USbQRoi9Rvy!0R5|I_>ns6xL($RFbW{3H73D?~8vBR+dSx<6Oik8xj6BlU;( zdBj{8_ZR7G{Neq7`Tw*1|KIlixBvhDI{vxg{4Zu)46HJr0vX4XK-_ZwcoH>2e(TT@ z`Ysa~_vKyBj^9I`TY}pOxJ7NC&v*#1gzqo+CVqEc%(Mc`7ITDt*KWW({RvR@yZqh# zWoA{-UmO0;!yjD#xJ9ji1ilbBZ+;Dy`&>|5^ctuJTpz!O zJSXK)4`wfQfcytA-baVt`R=}q;~6kV+yn5!XB-P&0G-J8@9#S|z_k_rj>aG4f05c> zzuWPnweA1Jwb@G?{+RsZm`4KYo|Qn!X&X?mF9Gs)TY;=~F_5+@0#fFifrM!xjE7JF ze+xVh{{HtyAflfO7GrY2BHayOp>`HPVvGEzNf5?H5l~$R<*sPP@0QG0ilzNZPMfa# zcDc{nJhu-4*DY^>Q{gLMpZ5Zu=?nmij6N6}q8AvidkpkfKLYSKIDl5zJ)j=k4pahK zfs*enAm@IaA=e;t=YNu<9h+g?l{z45yb~;hGLevW_POceZz|>D6M7VklX|rclgOIb z)sN7IYoDl@tnF1Xh)x^yxWbXzmsGg zFE5jHte2EFIU*;9ErY+j@$cWi2>d<*quPs!|ByJ#$%*Ye`u%?a DT6H_( literal 0 HcmV?d00001 diff --git a/games/NXDoom/data/heretic.png b/games/NXDoom/data/heretic.png new file mode 100644 index 0000000000000000000000000000000000000000..2b51d2a0561feaca626dd1bd87c6be276b4df77d GIT binary patch literal 5090 zcmZWtcQ_l~*N+vksxfOdwzkx$)+Q*54zp_1E}9zA#ugFOYK_{XW>qP*wTOy{S*`Jl z8nqH%vu0346TH5^_x3&ao?G<4 z0s@}vZXMU}=Y|oXZ(IqBFBUA1;z(P?U5JlGC% z|DM8OCzIkXmZ^rb(wEExF&c;J8W^Jo81xflc%m5T63^&ZKwQS?5dAldLK1%Xp2T#i zM3Mesr^fdAnR_Dij# zjsLIWmRY`m0RQYzK&^YYkEc4wC5F5M%O>>Nf_v<145TKcCtex(xP5wRW(W2K%cgHx z6*Zdp7`oRq*!0*|YkM@Ji0luI(pnTNTEhjnsSC~tg#k_#T}A1#$2zb{*2g1^|;j-esZblmG-6XZT&Q8 zJR$HA#ZA16ZDGA;1n3*9wg<0A6Rt-!P#T8tELboy1AwIZcr0WTpB)8zSG>??e((5% zwZ75zbTzN{_-;i}gXNX2X3~av_Y}V>{-iT7t5caF*RddC{^9&$40PNn6Z!MuywoFs z4a;BD!HpgAxN5D%46IdyqoOJ-f4q(BwFi87TwP5W{RoRn?hHH7tZjs_#U?IqJM|nN zH#X^iv*RVNPu8^!hHW;BT=D{vJ~7(PRH=4Dk7q+s%U(|6tP=BI!$dM9wHNK8S|*N; zrwa>Lg3SsYNWoC5g_ha=VGG>m9^5w|6zP7p{>Mz`NXaIfzxD9&`m@h- z*xeRduEJSK9AsuCxby5av~SEzdw5Rhs1@PW0jC)ikOx2Cf0hhFw;nC0JRWA(oep#D zq9(2G@ybzZQm0euajJs@;H&>JyTVrr3Q!cjYqvS<*MAV0 z5o$zfSB22~36&35p$|2Anzb8BiD$o=KyG(O52rS_s6+lYb&+6K&8NpPK|z8;V~Ho^ z0Se$PYL;C!Ize(@p%)b*NxO-Xja(k3FUSIHVgA;5=XL<4U$ursBzrrcM%)caec5K2 z&D(n|L~M84ji)uCtMQy|e_cA^sG}f>%iDK`wuFwpwC?u3wdV5-B|9ZYQWrdllo>tz z!H~^}2Qjtn@bgZie^Bh)w6t@FjYLC7jcCGk_+($%sxlu?)Mg4>tbyO&1|s+8=SN|i zHE@P{yVO+P&W5JqQ>GQ$-7=#APl@YM%9LocUFxa0|xwb%5O2T$k|;KSWBHw;VgEqay%d#5g}A;-mP% z0g0aJPl$voh=2REHat(>ZNcY;si+;4Tn0OY8zk+fDO;ViRq#o5{x9?ovX3fxR~y>#7LYre&HdF6qwOPn&m?CR;lL=iWi zyDK0=J_o4C_Yh~jz2u`t$tXS%=DRYYu<)?TF*UEynKauglV76+qyFf&c{!IHC>Y)@ zlB|^GqnG$uQiZPER)cy8V{O#qW>{~MetGN*PBKM&g4kZz>sy|7d6IQxSfSB>#i#!? zMXRY-=5u)P?gn+rfNbi~{77%(#{POOGQiD5xc`#7 zhR%MyC2P&CzDp}BE0`jy)8p;-9n0!*Md?zFCIb)8Jk!9u^&dB~@}#bfGkN|Ar_J-D z!tI%sUcF1OuZjDd9UB{a+dn=n!T)I6as5D}+%j>0b;RnLNGC})=lgj@`udiZ{`q-w z#+?^1DeH0H`V%k3WJ`B1z;ofIwqN-TZ1t_J1MBPSqp(C!@b;{0WM^OuLV~OXU;8t- zd}DuqUxc`|z1`T z8!#A+OmIk1|BoN{CL?BMW_;jq&VuZTS50@tq(mSQZVI>?(A?fK_>?XS@{*5eEcBHDEXRO2n3?? z3$LI!p+P%oVq(J9!NJ=vyr_SF1UfSN_(u+l6u}lS+b9E3k$WM=a;=vW}r+?I+a<=SJWZ(2&xQe z;Z(wwBKxoD=?5anUr^ZDkL}f2n%ww0d%F4ypLX{?)3KPNWYyYqNtOxek2wk^`TZa2 zKAMacdAdHw9y}A2wKd7F%QG3{T0a0%+o_VjykY5wlfRzKy!BSKdz{}-?0o$>njlEl zg*BT(vkp@n2|Qw6K=QQrS#*h>Wo|Tj$_x4TZdBZN{W>X0=%)g#m$MYLjf_;l26qOZ~>RR0+T&I;go zP+toD+S1#X7q(Qx@eA#r7=>-euPv73O#XOQ-HRN z5QClxP3A$lT^W;f#a#>n=bYM=zMs*4dE9${k*=FKBT{urj<9 zy6o+2FI8L4U?>y2)5z%m6hL38Uqs{Ve7rcz&5=}@84Y;Xcye5<&-Rq9`q8>pkVkR& zSvyF);6yiOne(TToz|zDiwVLPHtt3r5ib0v+KXV9CG!$mT9+tWJJlKCTcoB=ey`H) zJEOu8kM*Pu-%~D})8y56uIN7q+necT`59^c?()karKAk4;|tz^78Ls3I!y?EeYae} zsf+VZ8d;TCy*CZfzFlVX%;xr~QC{8IZpP;P$IC3xLtfQ0m)O1|(}d4IV?f|=aSHb@ zkQ}C~<)GfQ!)cw32-@_u1_gKA=DeeB`rrXYL<}vFx4$8Ifrtmn`~YI532gVaLS74x#H@IEXDy5P!B- zOOEC7gHnueH?4CtAfI>zU4NP)u28to!`Pe+$U+zeq{KxaMivR~qA<@~EF^PVTyjQS zMDgkO{6l4)W@Nwx+tI5^3@;z5!M|%IWS|wfsfiEs|1|HTv=UiLEXj*^m@#27Uk4=PzEB{s(KhavZ@f zCRkpt_|{qzFi@pycp6JiMmvJ5idiuDN1%6vK9`F|cKo{uGS0KvfbDR)0%0A{+u-Uu zct~q8kpYEOz~-3oLfN6ges*knJgRjt;f0v71sA={Ym8VBauqUC<|&s0#g22Ip2n@j z*Zts*%^%N+SSdOHNr)+UrS z?hn-|ck*5s!WGKqx)sq@cKN>SJZc?X{T8{QU^7K=V$#cv(D<;|+y%P19qw~Fd2jm7 z*Nuk1Z^IoIgy;|oC%$84q!`oGF0NSpHcNevqV*WEBPMz-m5GNAIs^HOfj69W5r3_- z2JSA3jdTbfUO(KgXM6^t)F57$Xoe>NpU2p~+`1iUcPJg-HgY!fj~_ zq}4|H=a<~~y@eSlBnAZt`A=y|u$Rit~D%AZm4SV=Fv^o@k6P5Y(|^(@VK#|JY2 zLp*=f74wJ%BJC}c;L(^~NmlV;UK^LY+-Ao^&z;W#T)1|Z%2WNRZeyNuw0qZxcbKd` zkI-PbWsug;N-10Nsx3~5#O7P{^|IM1;V$??E$CVP6kH^S@~ZMf0|(jZruI4R#1u|Q z+E4W-Vk#e+9+8Z>v?6mM*HEG() z!IgVY$k#3pmNF$x+TvJ9Ey&~EiDTwf{>p@m?nl4lL~}>gt}_&1AtlBXaToUlH|-k~ zlTV`ZKpphdpMjnQc)!L01E@-o@}%QcWvQ#!Z#HPFv)j@5wf}H%%96A*ND<I&x@ zw3sq#ARDr<#%BFqC+U-3gVO3o_d6CQiSky|vCstj&Gf)zjJ?r`J;VN{-Xg4A4`kSF z28l8GM9+%a+h1HPYKq1&<_~oiY@my88NM+#J`DqM2R)beaNXeNEdIgx`1jf5I!S`G zDy3Ve(Rn&|Bgjl7np2?OG5PCwxP30G^#U0tB>h4xK1EclupKH&^XmX=EU;aq3XYd` z@oTSfK!bPo>Z#53k_vRJam8~iUSUf%%>7uS;3zm_dfXrZrkTjVpsAvzbzSZo!8@|r zJB=*!!gavBS0|>6KdNU^yFJWgG(zxEJe-(QOHRH5%2&F&_bq3_q!7~=9!LfRqBLng z1>R%ua0R+B{2g=O;rBrlBVFe8v}n#ntVW121z=JVrV%PRK>8yz!ukH39Y)2H=uejp z=~*lHHB;^ou9dJMC0I8QOHVHF2E?ac`KoIKfIPkcY%K;`iy|dOepxw^gy^DA$$F*u zZ8CT?YS;{`OIbQ7<<{n^j(O|Lgo~@H5SsdX$82Sw8XZFhXW7uDUPOlQ*f6(rF?ap# zn8mSf{hM8(L>9^T^%Lt=LF`>_|4#W5T?)N%NjqLu$(R7qp}%J1qQ(fRCW{*}5KAR+ z=PVONrt8_!dH%kIA?)+iGZl=p?)9sF_;6xXXrz;q+pv=AJ=ywa%T3DgB z9VT-*mU7 zP!_GQB@;OKVhtq7fix~YjJb_j>J4)^?EnS^OtC;LLd43V6l$8Di?wv1EpT_uJTu;ykk_*P~^Ju z{}1p11%9vNTj) zektUEi{KS5tZuvlqRMHo-A{T$6u|7yOMG^Wx6S}^luQPijC z>wFe^6VO4d&rlD@T+TZN7_mmWX-7#!bK>tMpGUM8?Fg{z=z4UE+tKp!MXn-qq|nsK zp5+-PJU@xB!3ytx7ty;n!_tl8cUcZAz|dWLRlajaB6i3B=G1asTzQKECoctcycth z3*KiHB9*_qsfG`p0t(0fNB8%hBVywvdH;mfanIfe;0}zWuSTcwQbl$(UPo-fGHu+M zi5^ntnQ^~yBS*4zhR={BGdC8Of2`s;uPQoPCI~_(%RR!Y7x=`zfb~9KCLPbiycN!V z^S7M$74%)xC>dNTvJ&?DYD)jv1{Wko$( zQPDz~QjAQ_|2!jZxw*H?$M^n!|NouW>+qcCdCocS_xo(`^WGj5iVZa#h5Xo1VyJJj zDAXEwjlm4%eWs#No^mJ@KmSmE(@YeqMiGS)6C27Ohwm-ZMxj(yzvrbiNVUiYe;V_n4cR;PgGtG(vU z+n+l{zn9J|UqOmb=8-C&QL|NP$qa#;(gsO8I}Ye*beCPZdh%0goSk>LqiA>6%P%!d z^J|Xw+0NO{kH7RgtZAHP{rkTua*w+?KQE&Ud~MRSnVT|ugLSyGktXaX@2lL&W3o`i@JZBR-TC&^Gtu-T1tt zGV*S1oj&^u275uf)4rNFt?`7$*+u?hjTpbhQl`8G4|Nk3bowqoog#;oaO=m5Z`VrH zE7^Us6b#~tAKvzbeV(_1qR@bjeM!CE?%A|Fgb_zfl=r?tZ4b_mPNjEWPz8!L`{b!IV??iO$}r9kG3yJL0-GP)@a7xN*VGdar^^Blj*BZxo;x?)i2m@gdLS z;3op*XPVA?dk?rxDYUD&<*>;AWz4kF>uoM8BHE3%oRTh!?h@XraCGsj zR+o0EHV%zb%)qeF=NF0$qvA`izp%KoQC!yA{ncd+jTUA1t${0#*6P$NVLMCmqO*m0 zB7u@hTY2l!j*hJUdk?)geeTW6aGrfTrtgJ1F{`QD4?IhA{J7=t#!aj0K8hZA`J$`( zV$F_{j#n|e3RIL!uXFC}`rv)crCRUy)h{P!%HJ+j>HpS;zP9Vz#yn@H&sOnYbd_E7aMq?ry>M^XgZd zcg50kPe>c}d``&>S|~4~d)9}5ZwzI7O1cGJ+&ZN}pTf8tpQK{&;Ow~oa;r!$Pf5Ur z>-{Ch4oRXW6$z(`#O{Q4;2xK?2^W!D%~}{OaqqkY7;K!LH@Ysr@UW;x8&uhdJa5t- z%us2r;VP>85K!N9iMj7}_>q|SEMejHlZNw@UY?eqNDR!%U#!tR-|>ULfRUyVY%L>k z-r@etAPe+1EMKrv!Fw{f0D(dvlcZI^h} zVtu!?XHV-`*b;5+F=wH!(e+Btf{sS3@V0CXv#L#o8~YB%?5NrrQoDcus>}PAwB8b1 zu2|V$g^TNZ*0oP5zCXo&d)ya&VZEqi<{iw@qXcE6=`?1xYyF{KmfQU*G%uez;kUFJNcTHiyxJMuF5 zyp3_z%&oXK8&TuO=k;n2TrTg*?vnd5@3!*C>x)__yce+K=W3Xho`TE$q*-Ij~Yb7`-mkvYPD|(}>t@&yM;`i*S3Z6ds zx9yI!#AqshxUX=e>FbC2_3s*v?LT6n^3tud?)3-z*5|u4;7HAZ%Jxbg5k3Fru946A!q<*b%LeUof;(!|P6fR#oAt_W4=ggcHY{Tg*OQ`NDG7t9 zRcB<|x0XxR*J+i^DHtL)bsx4K6@yx4=mDzCV9r=bB;)~#V^m@BfAdx?(7ox)112!6hZ3azHo zt`{5kNm;6M#C!`r>-6f;iDg~X(jB%ZZXR8fh53k)KK5yC_JQ~XzESeu#1b8~j%eoM z#N}qGoeOub`Si4|bW4xHj*lOMjujMGrr*BvWARODy_kxa22qP+AZgSlSsI3i;xCN$#GcF%7{2GPn*)0&T%B`?ZSUaDMBTF8S& zhdlAhI%o%MgqQLLef_-lket7zm6cU-cy}w=kqbrb%ig=!L_WoKOI6kU%&e@^ydaKO zXEzZ^99>tRHw%=@NJ&`P*f_T72#ScTp_awQY9;7ypA-7djzB&P!R_sO@~|{&F5h5O zU44Du^Qkc;*}*yRG)~5z264<`l_bB(CxUn8SmfOXoII4?6`mb{>1^W z_3O7+Rka%UH5@N@Jxa^H;lQX6C{Mj0!ZiP;njp6&;=|?FjfE}E&HQ*g-tZLhi1%O# zO=n+Dj_2C7CkjHjzTqSbjU=51O0XKf<`Sw)XRB>78i&tyI2Z5(4irv*agFo^am?c*KR2 z6dj~*6iTHYC(3xx`mWWHR-8Y7-c2XL)OxS5TUA9~wSbAx<{2R&Avvj3pVh0AlQ_^} zRZ|biz2GorupPBsyQp)=wr#4~+KnHh=5odzT+;j?ET^%tveMM?op!ooSMIhTdef^} z`6*_}{r&w)uu*QjTvm;+F*)X;_n8LoE( zOmg+ODfi#Jk;`%?_g|zTZRv-ttEn3d6BHC&6%i5P8Yy>lMq>V9B~nOfdskQ2#ZLkx z`9MYkzdp^VkR|q=vfA{)RX-=Y|Y1K)4_uWl?q$98EF^&*gZXO7YaT5O+B# zj^rGGlBj&}z_tkvG$Emv^tKy9>Iv_+_Xarh#~gqq+df~v(q?I<8#id6p`jtP(0Ik)!^?T}HN4s>GueS1tii)b+uxHO6 zVZ*Pc9ALUvA={=IH8nMc8>v1@_%}qR`Q_!?mn%1^pBY^GY{eoo-S7{~UGaPO?|(I4 zCF=gM0F!gh4j)dCZv8Qt3@X`v2>ME9ekWree6&8t*h$El<8`c0Nu@_Fz2;I|Ks zS}|_koNBQ{B$OUt+jt#gX6EGVEdKT}M|a~cwS*HV0Ntw3w!+>t?QAgR~)0>t~=j!Bv&sw@qEpb z=%yUO+vm)eyB$xC99-KW@uL6n8s{3v%_R}BnJ1&GvQA!m+SyeKu<}{zMd(xR1s@-; za*-{$bc9boFNyvYR#@E#j>y^F1wC@USWE zalvDk5Z`yaF9&#v`^v>Tl=lZTJ964bN(&w`i6kT~nQ`*ds@*OzdI5O}PTr{SINEbY z^&)7nFjJSOl__dx%SzY0avN_67;7eO9I?S3bG2x>GhILu2hpFU@s} zwyK`kx^C8~`jVi5bCDNYGi%Fyn)yz+o>e;?>AEkj;H!W33Fcy_4 z!vW638@qPDucThO{eEZcbQ&$3UdqTl=em9eJVJ29DLts57ON<3Ky}VS2{U;H8|kih zC_}I5GyKloLzP#!i+0cgKDIbZb=X#2h) z;P!R;-~N^!S~L|uHRT;AGoifm+TO#n#it*5U}WP%QBF&uM7sK}j7(@Eq-14k4dBGh zgKljs>Sz<1gMLrzz66QzrZpSn^?R)_vrW@Iq-kMLcU{lwDqBVdiCIT?Cvk}`U$D2~ ziCNa|N`P|0Qq`}nYnF5E`^LSAYY?Y+mx|x*h6&96+xVAZr(y0`bq}+;~5w(1l zi}T+HWPQs$7rJ&DCFQf{QML^t?OR*n`(74CLhyqOmi=Rd{m zRhjuR(vzKMub~H_a>S9Ci7&A3 zPSOJc^=2Mr`&W>fd6?RQ38B+b&o@%vESef4V4M?BvsPp3JPD?)aFE%}3ip|meBQhn zdyWM#IP)02+`xoS_Lr0{s;vVGK+&p}Os0Izj;y2U_S_!@MoV9Z`yLU)z_c08lyW_b;U7C%U zJ)B0FHo9+1Hs)2wNF0&LCozR~2~9l`LVt~2FW%u|DK~{${#xOP%@ zlKm@;3uvXE)MO2w(_0GB6anc+hn!|RTIH`D5N3KDWZQ76-dIL2C%|jpltXeIwYHZ9 z!TiUqQ=e7@9LrkU_R2PU)#-34<~QG7ok}#PSp$2`S<|L~XnlrK7Y`ih4Ur72Zj#02 zX%`B#YS-?SuiEdd=qOo6>yNoxv#&ggE?F5ab-gt<_=K5!BhTPh?)CB11%6JOuYZ0A z7cj}rS^2Jqztxm~n|*vmqN#@^%_b`}H1Z;ENZ1Lxx|dwluNP%xmYdVSDhUH;fq7O_ ztraunr6FYOb=x$HM7I_TMn29o2@|ppdm`~9oRELWx-uX$Pl~4Rr7LWaZWeJ(v9_@< zB_Z23aY@IgUBalmK0{5B0PEdaZE-F)^3tcdaY?XQD`(D87qp#Wz!4|Jn4f@~&wl#W zmV+is){wTgad5e!8c2*fE4A*PBck+vTMg!#u#4$|VJDWmfvx0nq9J9zm+zOzvx!tr zLuRU{0k-Y4?M>e!LJr+VO#PJ?;ttcBdWom^sXcmVs=d$;I6|(R5d`FZ&nlSw3qOi_^DmO^uoY-uJYKzRz={-;X(0cz-ahGT_Lx zEoYlHgyt*H^Mi}^1|c$DI~%RLd~JtLrOJ#s9_sgNRkBXi##HomTIGM)TV7`rBef)g zJ9hAhFS}(^8`U!Ft2P(KSr#iNb8@}?K61X!n}<3jgE^9^muWH88Nh^a@QA^F6%GJjyqhiv;5_bcON+7A5FcdIDfesZa4ax zZ{)?^epiJSlAO$zL`p@HH?g{s&m@4RqZZA{mWAHFVu|2@-S}Q6s_QwL9dF$ONvLQ~gY> z*>@mpAl}{KWR)!^`6;e^A-?zw7wUQnHF@uc_?uq>W>&AEt55sro2|dm6!#z#Ro+r< ziHEBoejzq;i}8b}F&QWfj@vua^9(=toq^U=8bt=zx&(J-yC(ihV&S6#Pgi>Q*IIW< zt3w;dLutEo%|^IqU`)R7lMfrF#J@bX^NkegZh&>|ml>ziFMG;aup8J3;3NDl=LVH4 ziNxO)_01(4EwWlV3hmxUjN7Pe`n6XAkmcUf;|0;Pz?NjU(_-0L+`ardd{qXxeI3ZVP{mnu8hL_Ovfd-E@8@?+>)^Qfgl{9H_zTX z(9dz?NkC(FV>b1cd3;Gy{5QQG?>uu}ks6LWzO~V2Iu$#PaL`xp4_xQ0>vTDt;i2sR zigJDLh1s*P5%?`?OAVG??mQ8dzxBn_`E{YDnZY$}0VQSJklVt{eYZXNOm4rkC>h`D zBp&~GZ}{Pyd$%M4O+Cs^&z0cWc0`75a&HQEfQt0uw{^ALa_f&988!R9qXnG5qIK>J zSHqq)#&E4Z@@=Ddp1whb(Fa$KX9X7m51un1u0571SxX}Ky*3o79#Cp45YOv4kz{-| zF?UKrZwYGlQ%iadaIfPqShnr5@`G1c5gQtK>~>Lj%9(BW%*>Sh2c!tGyzLy1u1w(> zEG&1YT-Lt3a7y!LxTKsgEq9Z$Dr_`1ncD5JrB8mwk_EHSDz^+Y`7l%ZUK0d&grB)6 zf)At@p(%yu&T};suu;0ch616z`{g2p`8iLnRB_zWVpmnDFeRzGp;ATh7DKPDKjGSK zdG{~Eg`CtxXF(9jVpQo&1FIvy0Tz(4I=B`x5V86ls@=EBH z^_42+R}aT$NtMi7tJ+qIjpMqCdh31E{xz+j2U-1MzG8P>YG#(1oX|+{do5`??Z&qN9mp&l*Gn$MiXY@uK=$+0# z`1E2kWQRR=(sU|_Tt?wjXSx^*h98b#pKME zqe*c~Am2JmjA`rKe}843KD(f!kJ@`fX1;Fs+k_Nqr6U`PPp~|{GN4j~H1m?AU7CXS znfoD(EM9}c&#AN`l_=SY0MB{ldQ;*nQYgOcH`suV&q{W;h?4<_+xn8ds#D8FD0d4q zyvdL4jv<3-I*I%+rN4Sp{oUG+PmLLrx6;q>W=}{OfppLI^QcAv)GQ-rS-Famv_a9} zyo4uK(bK_0a%DHs;URH1k1BI*d@RD`bn!9V*R;NR=*@`Jp;Y_E8VWO~NO#T>%YZz4 zUJBKLtGI!6atNbeom=jv!T~vUzMUylBc_rjDv%yP7@RN7yzRyb`@SB&=b9+$VP|0E zBv?sJqc6%i9d@}(1Kw_#8Rw7t`8EIrET;UmB?%v{Xb@frU=BdEjl<_!`u4JP<3xK;B{kfI1 z!;`UvG@Z8r)}LaIYo^xIZn(EtUxnKjeAzvPPCOV`ix-)dl2#dKgAp$$t=z1iC^7Ut zCwzbVQ*OHJ8-!TRY`}dZ-EpNL78S7h`r?X!cR}7xFYXmLYf*rq zJ$z%0Qjbo1D?hrY;?sc((#0>4*|mrp!ePirGa@M4Tjj@w)9gR0if-$5xIHyYoypgW zf_=*o=S|c3y5Z8zg32nbnpk^-N{;I2kMuBAruG5A8Y15B&T=#AsHr0olKqyzH1A6dnIU3~e}B*|oc49~ zett&8dQP{x)1vg2rkTY>)0X7&@Gy%k4c4!C9Xa@g)_p6UY97%2ZJlaOY}>Pa&l809 z%xrZmGaw-%o8FHBd2Hn#73jd{+V#xq>w3K%k0&smc%%+gKGC{5MMvi4wbGb5E8IvV z=JSlu>BW26isJUz#KvaDmwaXFlgNh$5(Pe>y9J8P!tXKHlovTH-}hpd*uf+FsP6_gFOR%Ei{a(y6St8XJ2R-GN`%fg{-G1yB6bAJ5y3(5FwiCdQ{XEiN|C z7)3r;wb-a>ZQg6YqJ59oCs3Eai&njKXG+CUIF@2RepCT=W!_) zH$G0t+thc~!jvO!<7#(eeBli=eRbkN_ZP3Q+F_4DbviZ^Ocrlc}EWqAhEpl}Fd;*TZA?=H{V z@ik_(vbf{oYjYTJC0#v@m$aY8)jni~9jsMXJ(avMiNE=J?BJIV^nvB7)8txLXeGF8 zHCeL1Zwq&Slg&jQN(zxpv5S4(6mm$sFq%fOj*=?L&=5E?4WwA-^MoP>G5grIB#Oql^V7;3+jL6VDM8a>p2Xw<=_~!VqH<(|kGoXa zg_&z|HzxKNoXWhs!rfd>gxdQ$vNETlf;tB-v&DuCw$`i1BSS3%1P3=<5Ov`WuCw26 z!4cQ12OhRcQ2Y30aZ@Rg_V5LBW!_2syDxbKGgXk}5-6dU}>@zk!6=crP zTH;bp{SY~5ZWebunX1hDJf3QuL^UNApP5$tSc76oH(ODX99Q_d|NKg48VO1O$<<|i zDA$edn8C9A=4B2{E35(Usq)()fpLiJ5PjgZM*M6m*Lcwf-XFV#dM@cdvbt3%kbgw5 zCXkMnV17t5$@Doz&rxLyp0*=o4&(;nilHEn|H8#7l+6P5@|<&HTcKPKcp#E3UZza# zUbw_pKD*5XSbqrGkd-)J*TL47RSyW z5>vC|hBa)O1!fjKr~M!*_yA;|L1*dx3aZKzZ`5bLK~3Y8x)^q91zMj-7K&zr8tm>i zot_&Bn6C(s_jaXBZxCgqaVG3s#>(#uo!(%>co9T?X7Q zAP%Um2u7MI+MvkvR1)Rjrh7NKZ=u#T#Fq!G2{}+15b2}G@Eb6``pq?!YRUmu)af(H zQzB^zS$FSNxVL~O@2Mip-q2}~XX006)CIpuDmeEX_Dt9SiJ6lXI$d=WT`1+i$&2tX z{^Wi4)FGxKer^i&6+Ysa^b$)~r6x!a>NQA^xlog#Ap?b7#|x6;G$8-GZ90K`-kK(F zfE8wL;30G6mM@&bzk$(N#KVB}_~fLM7e;Tu%zgFpX9h)UpAUN;dRU!$t~`TPyKJ*r<@jIh6MliPtfOET(DJB+mU6*9ze4` zl;wPDvooe1iO_x!1?>c(dEt;zApD0yLBqo0DMN{sAN7YzCxFO1+dG?}usVkz@0mlC z_1G^U>z*Shvm!@OYDJE)`0{K%#nr@7#YVCO<@GyfiC6)&&;o$vp9gpehJYVu00gmm zfW)H>M7cD8u;hxJBLzlX5L5zpqs5m2Zqh=4AsPc5pAjI8szX@XWA~_HBUz$a$Znj3 z7cA=rc=${KhR^VaIt*EG2>wNRevRmD-%U~r0|H7R055(NU<7UgG^PjOATHcQBUT-JvYweE z1x8(n=qBwJ(~JfDirWA|_BJ5OuLcAeKY-?a2=NF5+=8ZnptyES{6+Lqc1!9c0};(b zKv*pf4C8{-ffdXKXmMMBSM(dRyxy{`eZJv^V1aWsSnit(7C3DKCN}ZFbV(GD(e?t` zCaZyhen`$Jut&0?sTWW7^z?uaA3lKh@85%m4tS1~fQW`a5K&nUM77pIS}cSA*8;565+I_V7&xlfNLElcaXr5_86b1u z&;R3C_mOu-3XHl?aXwC#UXTuibYp?U{5?QGD+Y+0?t*p20`Yk}VLl4*X~k|BRcs_{ z5>Lfg#M9OpZ)jer(eX^AR_5D=J*_q1+RinIk%_{T(1@lt$Bj;0si|u=Y#e0#paw5}X0=>*VXwt!o} z6s|LdL+i|6v>_z!{M+>tmDiW!rI!OVF&!ocxF#?9WgA4i@yI?QAo=_C^Q#7x6XaIH z^}Ye1vGo8$h=l8$`A=;S2=jm%`T!8Z!8r;0LqKx*Z^O^88eC4Cy$0|~Cjc~_4%?^& zyjTiA^DP}}gJ23|F-L(AuPbY9XZ44aOT}3IIr_eUT4=d|qA&Qljfdaca0DdGDL~*| z{!^dxOSo2!u4k;gfOGg8}gy>lhJEhyQyT;+*PEm387oiHB9|lkorqcj;FFF81i2P~7Yl{`;RUZ(0<6$k zh{q3Y2$%p~Igj7&Uy^o0xrBBC5YOc5>c>7u+Q5l!1sHKS4F0zoWBVU7n}n* z2abXryY_1_r>#j~_v6Yb!u_gSNId(9qDp z;tNilIt6lba{)AV17tE8By9)+L4M@6(e;d#7c+>@71Q!#@e2z2UO;M&KOm{N0%>gz zAg#9!@XOl+0eL$hrsV~Qa!UcPlnoG@6Pr6$eWULawW4!GP4}|+285>&G0pnhYoyHR zddA96cKx!8(u>tsTma%`djY>@I8bvv%eqGR7&X`8p=-$7sJa%ht_5}D0YNq7#8~i- zzHb)sFx1%pGE>*<+!P06;NN zqLY%4x)DB13?>tpM))uc3bhjQcS!nw;fGQ8x5Y{?e~FcHZpR@>(y1LU?%2*N?$AyU zvu`Je*me*_m$nl{U?MGP=NGnV7ZkQ`7ZO_BE-Yx(P7<_wDJZ+zX1us!Wmi5!<{5JS zM9#1n$TMOEAWuh}2lsblz{hJabOyu@@pVFIUDml)gjXu{$zkhAdL!9WtSrjECLyu2qB*&}|00R#C$EaW$b&*FavgOHHTxZ5Yp zUPHx5IQClSqnvWI?v!JP(J z-ZaR&TaF2X0%j9X#z6iCo}~~N1VopOyM2D;^;ABV%pn-^*l&kmz#oEgl;e;V9)E&C z8kYv!J^=U#Mt{r;v1PRJj(>iY04gGTL15sO34t)YX2F2Pp9KWWeK-$Rjldv++X-Z_ z$KiSJ=ebD~9e?`*szFo%ML(AOX9$L{Kj?tF0C+KvSacxb(&5?Q1cb-8X8Kl>2|KDhvZ6^67Hc<~bq$XRn}eK7io z4!q*aUW~@;ck?8TNUEqtBp8N)I6EHTC7%Ia321^ZbO~TZW8ix5VrX7qUc<2f<(#ZF z>JJ$36KG#VE1HV%_y`O_Dp7zSu@;_#s-P^g91tX(S@VK*o)AxkFnj_S^p7yWb&?;- zY$cs(zl-na_e8YFR0-{P);U91?I;jXDFXzBZ-7sBFFZ5-F&;+4faY@rJOXpUEVyrD zW!%QS{)lSFQ4#qi0)wzt2@uq%1463VKaGds_2EYtu)HUr3}p#x-^9wU7%8|JhT*>WaZLUS z2E5D)2*c36iSRI^`}KG8?m-2wvk%<{dvYs)e{>O87gY!nx19r9(=Pz>#*@HxZ5FU! zxgD$t+68<9w*h9w`8l3I44!d? z6rg-c$q7iPxd2fm2SAWs0{CT?0Esyfzb&5{-9Aw*lppqev znd|{LxIZI&I+BD9w*x5W9mykgjIQ^0^GI27^Fsh5h#G_e5xr0#tOI3>TET!{BM|VZ z1^`}V|1lF@5$b2;JOH11=+)8n{%(GLVw=9r#*WHG$uG+m#8FG;MLj=l7~FJ3*Y9DD z+Ny?K@=i6IG%NZW{<0?`$Dz%(MK zkV2vGTtf-o{_pqy7zOYOtBZL=tOt2WR)c8ag@YKFu)>yuSfK@jI6;d+oWT4+Jipl> zFLB-=AD`(UAFuHs)WHo35Mbgp8Wg}A4hrH728FQtgF+a+L1FZqK@wVbPz0?#D9SUG zND|IxCW|aQlJ;MRGrdOm39fav-}W(~=N#JJReIHxKQ#TkB`MEC~~J>*~F0A*N+J;t#7=AYsqj5QpX zEcnrqjsrYmOQHT_3>*Z^SoRZ$ermip2;(LXevFjUz>wVR7dSwjFc#`l5xp%ULmMv+ zLOA0|qd!*KWdI{#|6T6(0}fCIiiU8r&eu>5HW3^I@g|c8zs&LhMECR)4p1l04bR4i z?h*Z6uZ^7m4g$QB2R}~6Z2&nxjo<+FfWzndVfo`kaS-60J8AUC%efCA`ajkgkhBiU zDBxKb$^!nEI0z6-Ck=jH`BekF@Qi`rfDwQ?Uo@2UK)EZHHx=4W1w%R0A9CQ|=?8w? zJh(3m*?$c05Bz-dCJ}zm0Ynyn;D8lA$&wEtIA92|Fopah90Yl7fH5}($YaBXWV+w? zI3m$((%^@3{{cRE&mo<=@MV_$03v@L!XXCs!)CY!A+p!M?gxHor#FY^2GHO+3T=Gg zUd^(>8QP~O6MjAg?*YVygN1{vH{=^0{(wUpgx!xNv&8dm9TNvWK3ky9a|g<^PryBT z?w|H)zDcA%QE}}6BG>vEhX+64@Dla`v;a?SuOG$G^k@ z%L{F#zw1H9K4t%ovAl%RfUFsmTi+clki%NhIwuHLT)v!Nm zArAc`W9e^k5SmQ*BL;@_R)65YFSiQd#N(h%Vm`Frd<$&{s{oE<1@o(h_GuQsCc_Awm#CH!KK8w&@1 zOV$|zv8_hr8a$#)Ck=j4t=NGfz26WHqMF;F?E3@DW>ZkL4C(;m|8i{|;=O+!OBmiA z0F9jEzRNYZ#U~Md?YIHNMspYk5uE}kH@^pUhtRfljCJWx{L*kg2o(Y}p%Gw2*8g;# z=8>?QH2RC{#1Ba8ZDQG(4&yL9mVUJ^jmc}Ua2Ptr{dAs2Y?>tPCk=iHoumOoZ#t38H&O?!A5c7F1VPgIl+5 zfoIR2fyTy0)^%xVDL8lT96;=tj~_qI(gPqDAWZ{6=i?_72`~*K@M~=|`@#DvU zLZPti$A{rRdh{sE7GUq*y&yX~8|38VjKII%b0tWR2m#w-6DDo^D4B-QHB9}1y6Jl8 zBp(PY9b>@)hZt5ewAujg`vWzTbwJhF4;U>921Zsvz;Iz8&^1SF*P(7-a|P7nyMo!e z?m)$GB~a3L2MW5&fuOuC5Q0fU(GJLJucc4c_`%Kg`hZ9LN7Ocq=+TGu?TD_Qs2TOA z`-n{dzs`_P-SE4}e~h#X5Y$cn)B8vplLq7#3*=q^!^V z={`aO*=1M%bpJp2$L>9ZHviFo$R6h37(YZ+-yW@1SAl7G6Uz<+u^o|J0)3z1994BG z0`sFVdP_&1(h(Fv%OFF=_fgezEJn_eU_#7kc3~^ft zRGm-%d|w9oUP&$gGBGH}E^QH6L!Z596Of*t2&Cr41BtnDK-`!NL=9sBNk0Y%&xrwPLi{yP$ex3+DRt6J4B4q z!Y2mhf2IE~DS+@}(5(qI@}Gu6aUl8s{!b1aM$sFw(=vf69;OjHEqLPwj2?ib|9<~b z;D12@ezhQDqH>_~NK){3CjO8F;q}kS7v_i4S{Fe%B*FamM3VD%{$-Me_eaudXEAA* zH&HysTb||P_)lp7eceWE_@F=P|AGeNg@2;u z5ZU ztNus>G@%&Ab=n2jJj8Z*$bR_$f(8@CW4z^uZFYxgfZ@9hcz9sk1$+*R21u+iUi`lQ z$v6Ysc&bgq3Nd*?O z>VX7q`7dcOQ9Q<5o)zoj2O6OH-i_E)4buQagg%WtJ#g>$9@jXSjol39&Uy&#qEACU z+2ohJ@_6B&Xt^PKV;E!fI}LCm(Dnqzc^I}U`-29MPk`|j2)JX=E`Q!{j{_OpR$##0 z1T@h_&>no=knh$n&I=R8W4z`0XAj$4|44%izoY?{W%rBNn_mAd8c5={10C)bpo%#M zl3Ge5N;b#ODvV_t^)HIPJKhwCMb-Ta$pritP)-tvM<0YDJO4q(ML8G{BmkzcO|INYi4 zbD@ki7YNXXTb#QSh+@hhuWSbI4aIW(9U6=m{)v_og0V0WTfTA80LGr-W%&{G03x~> z#_;WiafvG7c>$gs{^5CHqIitAys&cch+XM;Xn=*WkcMd>z(a>)9>zo(2ahyf_$OM9 zq_Tk(TW8pB;csa`D*4mC@FNZQ(TJ~=^FOA+MDZAJd6H@vAgTTy4S40&Ksng0A^(R_ zJkpOe;DdAEk2BMdAHm<9oyQCRM9Yb&g|mDn{+V1 z_tV+=?`bemJjPpIR6P>fXa6+~pe_vHMNpNi~$F2qhz6fqUZqhC4zo80x*`nxE;%1cIeFX z`KL1zvL5^s8jKhIiIx-BB!BmL8BK!_7<&q` zmuiP&e<6&s!aoM27N@X#nG!AbRKV!avb+h|drbW9~;9kkqrF9q>26FBc8t z|6OLq|KpWsLK=L9^zi;mUio)vz}g>Se3xOp^F;9&Z+S`WBp{)a_$L~OXlw<7>Q?}t z$~Qnzf=Pi1{ija;7Oy-O4e+>ga7`SNsiL91!H>H4@xnjRa#AqPA+Ct6N=4)pngu_k|}K?)GjJ_GlK#Ig6r z@4ni9cV0kffS2}xduA@&JIL_+J-^mBP85&vmY31n41LBn|AGcTuZc+f&9Ql;zm^}c zXaM7L{;X&ES?@ev_$OLUR&VQfpR<3L1{1|&yya!}(}1l0wtt-lU-@09k|W z|2hpOipO}%-+%NHw6wkkPoA}drYA2z!^2ikTGk9x6DYloq(*SP@-e8o^8kJqr2$ml ztOeI8w?T2q4Ul*A8pzJO2=-(bfo;2wgUsyXApg(_kdu1^WM$`rJsJB!P*^H(_lg8g z?!my;X&rD}z7F{Kg@Uk%SP&ga260hwAUP)fU*rD}e>=q2?%lh0EWg2F-@zf9?;-z3 z8jS{edwaqC`}aqDAd&C7A>VUBeDP{(YDRqVii?ZE>C>mdi4!LP;#0VL_im7wmx zBSC0rDA>7kCo4`bIW`7t+qRA67nz!x`mf=S;5qDbh~WMs{=@#02>!?qp#c(u81Vre z#{bcyN33|nh#w-75d0C`N8=wG8w=9Y(^)==h)<};a#xTVANT(i_#?O>H0bK;8o?il zfBf|6QID?$tb)F* zD}nC(wZLehFVMH}272aRK-bI@h^smP5d~WysbUZ0)f|C}meaq6|18nPEc<7~pX^5; z*3s7!ea^$Gf2gg|bt5p0cmJAbIiziZY7m(1e4FJf_$Sz)Z8#o&iw*jEvHZ|}^&E-S zJ=^Iv;Ddf`zj_YiZUA}5o6sLG>6g#{ZTyLv(C-l9hxkAL3Vs6Ak0H+ypS@o_$HBOH z$a4XmgkL^K!?>8pb76yRzkL25{{Qay|F8f58~^|RI{&%h`Y$;@9ayKl0<-N)fb`-M zBT38*`PSiL=(|j2Jy&wRGV%<0PuwCGaKmq|5R`qvVpv|yz5J)=l9u^M%pd4??E)4h zy#Sh?w|;sqweT?X*M{GD_!sv-ZZT^hvtTE1+}#D#JZ=L;m&%bOyQG*Uqb1FW0#19n zfTmaV$TQ?UIXh@8DFJmr%3iGUx_)WI=|J9k50G25 z8^~Dhgz*q|z;A)4!S8=>1EO=c0ukda@S7)_fsp=2fW#L0r%3?DMj>iOL%u7R_1zMJ z>V`>+EBJSGvEBOSzFYQ3;GFRRIPB~M%hKKgn@t_SD)}Xh4bcYXM?VL1!&(6R1_#jd ze+;zOJ_H(G4M25e9Z+0tB1O9NPUuP%kq(l8 zfb>wr00ADqdH=kbcXRvg-R|7(&D}Tq$0j~7(W9f`qyYc`bO!p`X4e|^pHNX;W3QUa z@U;)amliX6{_a(~+G$-_fNJt0s9l2L}t)zo!-#Wsl3EoZq7< zIKBQCI$zb=G*fLI^8|DW+}UcN(7KuC)kpP+DwXO{iseU$E5ub>P?#pwOOJ!ek5SO< z#ltiiQ)g{gW3Lo_uavONZm{$R85h<>XXD?LxG?-pD8SYqsOL1%36tnN&ZYyEx9}9Bo7(%%r!qS>jGf=`tA%*|C~#X_zjaw zylONR#YBunDZJvEYuY8h_56pWa;K1Z{Q6mN!-|z(R=_AAE=X%;Uc4apr_iXYRa6B$kJaO_238F>ifQItaJHp8K`0gJa)d?L=MHpUz;vK(@btnTP`Wq+}kBG-_Hvg^t z;I=Ep6YW(_nosGhg67x`Vt;QrwZ;5|A;0*a)fJ)mj0-5St;532duKT$_}cC2p4;m= zh|VllN3q3=on+L~z0Y!>@3vY~+3a@Z6-$x8GW3V}AHFpGhJrgy8IIc4rFUnZv4e(F zhpELILMKT_tYUPV?f)ijZ5!PyYJ?IMp4K7UCrB#(0xBc7O5&++xN9zNd={+ZR&%oX zYtN(**%`wp=X1KbVNx?mS}8YvwWX8)My$%_*Jk^8vQF2*HQA52FAnNH)oP98<*gn# zjaKI(KXAg`Iu(P(EJ^6q4`geV2fmGu9(~6tLh4%C%t?ELgFB>;HmOM&1#jmif_hBW z%89>2KCG(Hc!B`0CCRxAog8luL{9~3ZC(VWo(3%zsfQM8F#3%fu6nqSlhgiW;RI_G z_&5WeR-u8%Eff^rH~ybti<;ESLD|WbyrJ@#%f?b(BJplLvPmW5cs{>yYKny-u$D0z zC`cl5wEL8!&MXqO%B3IOie;Iq{G2P*$h_^E%Y*IISXgs|`ACV76)4 zZL!L6*oo_Z*<~`66>0-bEnypEpSijlD0H7bY6l#oDC6V@))E;i=BEFB{k0Wlbjq>- zJ+ZxaP-~Y77K-otwcY?#90^6Oh>sH`U*!0?G{jBiMZM!3y=;rA@QG8}Pd%G&>`*2f zX6VS+1DiZ28Ftwp?H~HUq=p$w4Gg@P;+leOhRz${{;=9cVLxfKxW&b}oNYT)?oYXm zk|$IwU7dHrzF6PPGL)8=2a%RrJ!aA8{#ED6pd7wu|57ap62tFB7$An<8QIz53gXWhmR3}pgF8Zc5?Mq<+269| zfzhi9JR2KNcm)LojndYRp0I;JRt8^M>*F$x74MV>L@&_)%>-7EshdJ`TpvF!+ilm5 z-Q3({vnyRyFg7s>b0bSzP5Fb&(CZ}7iPK2fOmZNqALd0&B^g@whB13mpFM5$w4@#yF%PdysB)XuF}7e3S* z9Oe3@RD_nFR_ppwGqD9;At9MdZQ<3Nk`Qjipihd>pU}EIoMw-?K5H)SM}_=&Z~)hi z6-|1bpYJ%iQ7uv_r=_K3E}k`@f|Pxen=6n6sh_qF9+jh|qw`Z5_y76^sB&6#)nib! zYN49Ix35_{F9K$YF-z9@zs*uQ5=0Xr(l-3ODU zPPK_9mUrn2YetF135UDBRN3-=b@VbMi%7B-?76D4Rh|TIF?D4-{3K1gyVyVSSs+DP zbQfSk%w%3`Y@gpw*yX^0)G13TjtPG?zgG^v47_kMLdY^?|F(+uOLY=Z_m(TOSY7QK z9yVIBDQfT85wk98|2-R~TJ0q?*QTuSq$3t55;*fLU{ZEg4h1A;%j|r8bHq_k%tlDO zL9OvR1G?nYxoU~A=|JLTD3Fw3G*ly$Oo0KYh2fq}d6Lm# z3$HM67ktOa8z3vy(?&-%ZrD{pnhKqvgdnTOoPR`Z8zWv7-zTU~CGEEzgo0z+CCNP8 z3GgQ;#+YBvAj+s})V5HMUIZXS)l>&~mbt1!)n7_Ci4;cGZ{gcM6*w)URx9sJ98-Lp{9mJU~ZPCYa-Qlk2 zQne_{sLrM9j;;)7cIP3CEAe0g`ZUGNv@;wC&ZqxK=FzaF7j3q1sT|?m0XBsXvCBCL zR@ttC5q)sZ^Z`@E&?L9H^q)!h0))g?^IEi2!1wKX;=<&+-WNBl%pp2ISLl7e9`dJO z*9%&EI?6h4v$U07@6k5ZehJ$MJvl7XAkL*^jwMA9F=WbZ4xg7@Lm{3TW5m}&3l{FnPAa}nqh;ViOH3QfgH#cIt#Kg9srEQ_6*7`Z zdO{yX+x9pS*jXgZT?Q_OJY(i09jio1rdr#MRTMyIiZCzEYA9!^h;Afn;{Cm1IUJJ; zXf4cr_kwuUQ7!*Ek?UyQ*!O*;-IGPAm;lZie<+tfRClMAjPGoY+!ugkhAO0ZXAT)IjjVV~VEdzphjK}SWFHAu=w8uGwC}gT25;8KAf)=G*H2x$ z%R@qY;i>(=n!_3+EVi0cfKTUlU*J^@B?YpC6HVnxQk{|A6Geekhmw7HLilTaXnXYB zmY6f#D>~VAg z_B{3Vm-N^hG|yKmO&3jCDZ2PPfp&E2i45HRp1Rx~Ug*wy1OtWVTjGfB{74TN))G^K zyuB}~_AWFx5w^^VxOd1n(I(dWQ!MJ9^H!a z@6n4@hw3ao@Okiyk;tdSRA4mKO21sp@&`>Pu!O#v-de{+3p-rxqM*Gwo%WP}n2G7d8Hy+tBm)PBwyeotChnqc%Ozx;=k1g8V3W33o>k% z3*`rFO>z1NggN(KX=-q;_tVym>0X#x4&C2bB@NZ$8%vi<(8V=sz7w7*X%o`RikJmi zHjnMMz|J>iheFl!Qt77fQ#ZdD(t*M#{H~1#LnUdSUYqoM*TQqj;ztDe=SH}zr^P+S zwJe|1u;;~AIFstdK+3|Ez$iZv%9I5m!o?0rBrWm>d)Jx;q1MVbPhFh8X-asGuc(n1 z8QltqWJmsh>>ms*u4UOSq6hsh%~gbF%?M8yNHwZ^U_JjLbuI^Q-C4Y6Vz1`7(2HF4 z6Cfh*pw6y3Xw^@z7W^}+BTjYI6yc|@yIx$F4p%4mUX!gAl}wJ5!L}_A2RAh}_fcJr zEe|4J&EG*J6L;HCVc6xxb;$TTUW9-UaZQHc$%;U*;8&B)7WdarEqke06%Pmr(Ws7> zkAm^%KgsKFbiJ!wxPDZ3So7T>dvx~nPK^HFxOBHEYPi*?mP6=rIC35i;Xkq1#23_`xR!CV_^}}KTCagVQw8ss;E5g4D&mkdt$VjW{vk2`<8w*JZ|uSmpm7Fh8DC(0 z(GYjQnpzOl#ftmq$?%G>C3C@%OB7{+Ms71e zVDwR0;#)*v^o;h9+;)DYS62o%g!$`?{|8J+6IFC_L0U6!O7CF`yi{QK%#En3VMM zxeWmd^#op{qWXM(c0CFuBY;9NFnm704xf7rSLfNaMQ1bGh&)F4FsBI@u zsB=16s+%`ZZ-7m2-mRvz54npJBBX1Rlhp30(AuLy{E?N~k;Mi^;lLv;y_a%=NLdvQG6f!4--I6kj0Yrw zy?aNk|-K2mXR zi&tqhL8MPMr<@XVFfx75esH*SGghGo_3`CvUtz}FjJ2)v_B`5+%>{@cXuvPD>@fF^a zDjYQWFsIN&P7$|FgLQ-Ox=kB5H8C*|;4yzhTPRfKRS#}bC*@y@$2G%75M;sF%Gski zc-|`OW@@9G)YPd<6B~w3i*)f6yLR3>F-z`sz8ssa&fD7BD#9W6+Dza~!u1T9lVfFV zl*6UGSoso%2OAA&?~UH&usq%_Y?@t8zgbu_n>91EQrTZFMb2*KuD1b8ml`DsLnSga zL7b^r;>zV&tKiN`{N(r}H<^? z8LeYDpc1GheBTX!>uYxM^b(2#)@h8DxdcI^RM&{y@Dt;ru53h^cAXw=ASiqHO0<8`St^P1&E(u8Zv)LpMd!_Byo6Q{c!MaVP`RY- zSO(M6cs(Wf^JA~{Z+$vxU6FOUo-EG)2zqxu=E{wZh9W_OimVvQD{t1IirzeZvd33B zfdXCCe8jIJE0XfcMt`@iiRY(V+=fc2&*Q0NVXoZih{+DoD?zzikA3hq*d-uuJDr7M zcfY46I#jyhJl=WCT?pJONjzhzlBh5z8^^XSUi_9Xh$N*-4AB;pJY%M|4`l>=I}Ypm z5GK(`dZv76y_g~X+W!W5vB|OCy)~UF?-$G}SO}hs`N}?ha^B+od}%x*9i^PfU6PC- z58Go$E&C{?)*CK>+ZtJzgFc!xBKGCV)~_bUs$+#cm676#WmI4+@QFhDXs?4!8<>)&_?1%;oM@+`d1`JJar6x|drMNm|wQSA!=? zgq+SF4Xk@q72OyehJH~bv3F_>`JD8o9deS)O>VEL>zZjJo#&r%)Fj+do%z)1l5!`X z)%q|NH5d9p(B5Wu^@)8K=@lwaYI#XwUN3S3hgqzyZa2Pnt%}NFZ}kZwRjlK-QnE7D zjCzCi-dnmyZsoAQDvD%o+!{wYCs;__cs?bjgm!)1qZHZmO4Jk{=i7unPG2~&yYo~i zIyQ`ee)O!DA{WFQzLB!0jikk1;50+H19_c)V zA-_v=j%3&CDB3qPr%-Vhi@jWhcVai~oH4IPsa5xEj&&}m4fOXu36|9?2WzSl6%tFr@cJ)g4Ao98|QM& zAH_ZNS*L&7x8jy$M_x(A(~m{06%-G1<8(H0xxl(8}0C#%=B7AXOPzZV|EdFg>u_DQB1j;q8s_{sl=|;s7jT)UT?I6 z+I4?Nu24z*r>mO_yv=%nuEmY#4ig9GGHEgz?+Lq3PJT*E=Emf4-xM8BJ8C)eB+gze_6DOioVkA;rNh2cWv#ygqW~w0e8aiDcxgInp&L+V6b|X3*vYqM;LE2+ zP;L94dDNeDe^hYLc8QWR&e|>I5d0|ax`%C#+`USsi%VkNTy^kBFPDhC>u|fd&ppwe z)#d|@GpqZdFouu(A<4H+@3imhyOcC+z+$8ojY+Gie-?d;yze@S=$*bIVQ*4KYLDfH zs-#|Or#x@Q=LNSfoS0+Gaw}+k+(HSp6Z>5GM8H+%8DDW)IO z;gwYs2(UH9Z+S%*?D~Q{l|M@QQ0)ynZ?EL=a}`Vn=2^4c3U&G@>TMUUk?>fgM$(y- z)CL6+%VzCal%6~G+({}ythtUqJSp)5YGUHpWtoW5+d0>&l3U5V7lIyS>f0Z)Ykru~ z=2>&YPC8#dyY9656T_DhDDsocmZL4Zj5(l@^m`V z>c=kEkKyBe&^SZ7H^+-BgjSThL>tQ@vDd62kO(*=9&r~pJd(bKcn1OG6u7q} zdklfuKpvNtpA`~R+j*rayU*CN>Rj-{$lXG4b&kw$zE&+S=O{jE#+fbuymwfz~xNcvxPs z{df`U6o_8GeqBA)>n=^F5=s@>MasYF^!fAWbLT~^tgJTekQ8=!A7F!Jwmo{Z(Thm@ zuBgc&8o@>qPSifui}Rv%;lYv2sv|4}n`#dB-m~BRCa#6F)n!LcSCVtNu&8KzdsGsJ z`u>Z@QtX{>j9K$(_zWzb(HK^GMp7bz?h+Tf9G7XVH-vEXmKo`@so9-qO-oDW+qZ8^ z+)iq0Q@&A3eDafe$f@8B{$`{KI_Bo|g?1^S?d|(iE>Oot!zS>LJAHobFA8zQ-k&#+#Bh?<6`BMx)z?%kNS3{`6u0{l~`BvJdz zSy@@y6MQ^84@Rf0%FIY(&_zW>+GF=-?>+(^`lRXDm{rAxN~dm9>Y?sO zaNtn0tPO2YBRagtmnOVU(bm>hWh8bz)?RQ2{#80LOBD((EE%M0fJT$U;Cs*QQm)6) zLr72Ex#=yX3k~cX994twX6)z^uMId$3YBD9n%h5x>}3wtT|H#GSZy7uNXt$hq8msW zFfwvvQ%!y2{2Uqn(D-b zddt>cpo!l{G*eh8X9`CeJ1?)6$0rlh$(?}*XUF>eOk;LI z4IS{MNo}e7_-@c^K49d4Z_?$_y0!iQY6mZ!RZQ3pv_%z=-(+4l=p<3~^DIT<@ zkD5mo;#QkrGY5?=l}X^`(K8%XA|x0w-Pzk>)B^_LFh&@mcrW zwLMyhCQ&P_l{G@|{aALX$kd4OR$$>+9-!Pmbhm1@v+!=mGm1M&both_=nU?t3u)bB zY4@)VI@%1_Mm^b0bc%(5>8=QIe}H;mCZ$4aYrAqL=4Azo!Tqt4Lk{#u9)t;H1goo? z#CWMYir>9%9Qj~DxqqLA5~hU9or`ayI+5t{8&@(qFg|nqLZ2wC zcaJN1zS$a?tJ%jl_-5xJ*$~G^WVh5K)B4wEYU`*HvYHlfT|KE#z2=%QI(LsR$58yX zSNQS`IYS0hZp@}A)Skt=JuxMCH2;Is6D*+TKq0$?e!LtSH{H|LKFB7$xJO=k`U$4K* zEelR=%#y`&UN&hkw}D9H9mDP@sg*lECy`0(Wr*(VV%A1CDjW2L*&aCIvTusScSxGR zKOl~tQT)x2@Ph)lulB%#Bv9_;v$rz$9gH&SNVC1{`!umm#BgafNY2_$PyWj)+ ztxfOe#m=AJ!LcSSVpz2@AySc@_oTIr>H25KDKk_r5D_P(818WKzdFQ+f)bcQJUszi zKAKxgwho{h$m(3XYTj19y%lmjHOeoS$rMGvVS>eD4WIBsDK(Ptd$fOKzj)^9xhLD6 zk?Bm4nC;x;UmZt}7tK18vxa}aFC#%TTPXA8k*bsVWLfzYr6vt>FC+L+8%%uhG~U*2 z_g9+Q$e6(I>s*$_M1_CEK!%9xxG5)=PI$S>V>je) z93UBAKhw?nz+b)@#jb;8)24dV;_JTWbrz#Cb_|`xD;3TWUB?zHXCjhMHsEmfdTEqj z+U4O={Nf{zlXU~Hu64>G9qJOfFc>Z!INc(C9!oe8o}Kw2@){Rf=9m!$7sm9F4~cAz z5MNo4ZQ{9bEZz*0@T?B$=|Q`Z$}3r}!_TiD3yQdT2bD3B%+38M(h2Kxm5x~QARkKB zWP0sp&D&c#RLhB4^4YK=o5Rdc@}oow2ow?1Zxp9s?fIj|OeuT8Rk1{$!bA(9*?! z(p>_zBgItu!@TkQU=^j&+yjdCSkUWq#A(jK_o1(swsz^l#VENchlNoZES3+1JfY7C zvGH_E5|;5GdMjbKbu{_j*}*W$voDw^6^M?$rY@ct1vQB-#`!Zmh%B(4s@Ttw1XX`- z-pY(5%dF&d8*>ortrjnOpJq8a_ekq_w0b4KR}5y5V)THgzi7cjwax46l%8 zwAZ*-6bAFjt*57VFbvDASozA?@o_+LveTzS#N7@@s45}2AK=97poTh%Huf5=3GPn_M0bc)Z)v17PKJhqM+p9!sRi$^Lj2EOh0Uy=!J;cpfuIJQ`*dKfuB9S~tmw z1-(#`)zl(_UStlJezz4hH!c(+gm&X*OU)%H?2VoBURXr2CA&%(bM-oH#pgurJUHZw z+3bq1(CIZtUp{R>E8=%N_06ZJl*WeO$$l-lcV}f=n7gJ_<7D2y&4L^Bx$@cMwoz=w zyG~Bt@{`+(8uRIvTG@7Oq`qW+nxrS(dSXG-tT#~`D}=qI&WpYnJK>9;op&q9KNOFl z?~HtL_mtEQ;^W2R0rU6r<%cL0Ca0TPs)ir8;Xh(H*~P)WrhTnEFYi?G$6FasoocVl zi`?;t5AnM+x@$>c)#TIG9?&B?O!|s$QO}rJ)51SoW6y1E`kq)Q6iv_gaoEaQ@XEua)FThhS{hMIL{&pY3c(_K&+bT(17fbCx2i45iW`}p0a`ZZS#7UQB@NbzPRj38F}@KGX;$u)%=_*dCrnHPd6T(UlE=o1x<)sHV4mhH^N|;P zCr)b{dOyRKVLO98q(XAttICQ_8*Ib(QLI4aHl)oHIToMnO+Bjqu9CUsm;Oxc1SQQEk0L*`TkgEi`~p)X$9$JALT!-X^=;5li_ z`{~tts-TNPSo=*iLydOF2i|4IkIsKOwQa(i_U0KLKeyW=x@Y7i;cjOXK~E4aQy4&) z>MlX}gk;a;i>YlUo=+SC0)`A1>x~v)e3F~`bbdDDb(|*F++>X9GZANabXhO77?#^_fl}CFd%jWm5!0Tj(mq~dSx4e&5~+xHmZ}1t zkBI_v;cIIOYvk-V#4=9!ObXzk+tlq}phcZN^hK*Ky4X#24jkUUm=gPBeyY%I>Vbi= z+U~`(e(me=wxPBn9aqn;K?(ArWg3mipHCE;K6-p7*c(j%}v*6%?t{ku}R zXNu}}Qm+~?rhEgFSIBWINVi#?>a(rfQd7a1uaAzjPlt_Odz15W+9*IxfSNk#sonTK zY8qoT{Y9Y)H*PVEBa2l<`(4+Tq(tN5ff4lNN8QK;>W1Mif5u@mGoOLu-e%h9VG@E( z<3(=-=zL$q>UfwBP57qlA%d*llnZ{(VYuf%=N;smm93f2K(};`Np<8L3Z-)EUvO-k zlA^picC1Aqv(Gcmyd&*KaV#OdM>=N8K)>rmLu`}# z%Xh=uBjk!s3g@rUblFtPXpI_@_x1AZGi^?6adVt}(P6aM(|f}}KqWMrSI)0=&SGER z6yMyVmZG;&`Ez|-ej~GC!$Ed@nmRQ$So?9mk8APqGFqn43;k@~pxQj&weQ;X;hn78 zuvLqRS)^xGD^T_6^RAI*dRmrQ57uXbgf|YK=rx31?Cm*sGeJId7#Qu=v^U)|1)k4g zh69|m8@f4)^IOC(!L2~!e!$iy66*JxHOt;NtJ*d>P_Y89u0a!*zEq}9bb@St?i;q@ z?}fZ)aU6y&y|}5(ME3aHbh$Hjq2W!uQjBVemS%ZyE-O}v zyeZG!X*hUy52@)yR!&jGix-zeQ^WaqU7en?U^2z9y9O6Xx`Hl|$9OuRTi#f7x8|M2 zTB-WB%KIO2xlSryi>i;F|1f9W(l2zPz>{=%non$P&iimXMd$Kh5}N8)nRL-7uwz}B z$wh(b!xePHgx4KxET-dj*iM|$xF{TVtBL*&u|6^)pvXv=ARw~%BCY?vAsD_^|Frf| z$C0)zgaeK*jUvs7PG#HCp6D)Qio4F@zT=rjzaK6+1h_#*5jpP607^5q#J){U{q&zwi~y6JVaJ&ldK^5B88w-YFb zTqbV`mc&op_^sZxJKQ0?U`jsV{f!6Z&)g=AicFgC#@SP`#+KR*j&5fqoKjC%1LYGs zC`v8PX|R#8m{-V02%%1L`(5m+ z@o_V$;XzkWx!H7y_wmf+rVl5(zrB3+!Ol4PwEX;#jl5VEyDs~eh4bd#1!uT&Dq^#< z>$8ToHifTKz+Y|5aDKeS}I;&jjeLXw@4_PY233v$EfAjc3mooLpFPw7CoKTieWs({LrJj zH+6(2Im|R2_t28HU{vLiyly_#TVv+1K4gSm-bCb6@v&7o*Kp4?4e{*POsy zuHIGhj4SnyUPARQ(c#&+xJfxN5U3j_#eJL4hqD9WWL{nt%5Wgvs{DelI9n<~%9@X2 z#|ehuhePK~*GwvAI0B6fnaeJ6N?GB30g z&40kyIh55&P@0p`b!ko%j)!p<(wld-y&{RfdNNY`OWkUR3(XDQ z-Wnk(lxw_q{$}e7A#^XFB}&bmh@aV;D8d%2EoX~If^m__P`!39Yll?wYhm3?jmim< z$${4eTefLx`x4PHQ3Y+|eG@W|k`sSp7$)~g$_NVLyWpO>Hh4l?)1J(j>!w$>bY22no>oNm(HtG z(pRsA;+#Hq%%ZTV;VR{hmWQ^3(OvmnQ}?Hu&clWEDlvMx#qfN`0F(|tyy-n&kw_M9 z9FrDV9O>6k?O`&V@5I!p`(daMBx@0dge62@(VW?rJru6oE`@Kk$dt-Bd{rVEL+2{) zd>lPY8A>YUL_aFbnM&L%dcT2V1RO6fG3nw|M@l%;nn9=pfLb@1x^$IH5~|8YbFdisfn9V>Ji z!n_u{))8dnc>yB(x%$OXF{B<@y-VYHRB)F@g<@BnhjlXG-h!+ zhCJWBYM1wD#G323?GE>Ts81dLpy{jG^|86ispwr#h{WJy7N3$Q2CTjAqcVJXPh__x z+**vZvaQdt-0emoUsBJNlVOg?W5W43;13qbq&i5<2f6gU5g|^5?e4j$Lk% z#XMXHM>iH{@@(ga3oMn$Nh(!dS@A)a1{EK&^3j4q*@m0QuE&<9NikH2$$k5Q5E}7! z@K0IWRTSS;_fn+{mnjzU1| zbNaBNFHgh7#tq1-*EH2j*1u4RetOr#+D5{MjG2_b+sG)k(`#LO9J=Hh<9uLRMW@wh z_5m|rdzbr!Q7l*%{ud_AUo z+|#e+jf2laWx4VTPQFEWcUi7&)t6c6;!E6V@}20AUOpawa5&x>`b zzCuUKrBbxu@<6D{Gfx2(3_Mqdz2{%C9>;bJ4!DqNj|_DQx8}aQ<)zKZcI7Cyzgzo@ z>vMSBe0hv=l`-cm-KUE|?eHG%;|B4m24-HtUK3tX`t&*4I)meObF)28)M)g;$qxxK zF7l0N4?C7Z%sX)!(J{5wpySuHchp6lagvyiaM)R{df6gje*Tl!^=GE4yhD`!+4yOb z@3ao=)S#7!#Q63qk3wF@AeHPrOHTKlq&a%uxL|s}$WKA6`xbWRGz|~EnARG8F|GZ| z#UZV5KtpqogbE7LS<>&`ZrD_#(Hhi!`JmComYV9C(cGc44uXf=jod5Ztls6Qnhj!d zvRMtLdJXVhJIlFZ$@Ym*DBzJ+kh0HB_41AQIB}{|(xEDQCww0I^}CY@d85l`{95FE zpV{yhPwIu4db(GKgn805-xogRU&WP^^CG>@JmcCuf!#ERLS8gEn_7=28@h6>ZK4d8 zs)R+%L(3O|ccd5U?TwyJrB2r*L5%_L-7D2ma@|Z&^Ih@=HB~SiuH@v|mR!-jPw<3L zc%Od3K*br2OQT|%Trb4YlQ=CugT|$y!gItBq*^Xgez+99?TABX&cewQ@SFJ6`SD)W4!JT*a_+ar}cSu|bzGtGREHO+*u)#X2=N)wEOW=nEt4%BaM) z~55E>$Qzh$9&_qJH*%do1wMe*r78S5b8f#xNOYmv&{v}g=m+i4~o+N4h z!}0uUpmzHd7t#ivwe4kr^=7q=8GH5nA|?;`JBEC6^yGKnERWZuJyp+hcxaUt(lf_>5S!uWWnOFmr-WSSkmS=m!^?QABIDsQ&qP<*Qol!gwH);o|9pL#r8cq3F| z8`ZIs7~b{$DKE*>qRqO7-g675pm%yyomJr=3%B}4MWrrWmpOwPjjE`j& zkZQa2;cUSDsoudx@2knq&nzA$3T!FNnhSNf`|?~Pf$1U&PT%Jbh9^3DI=3fUSu{;l zUd|Y|zmW{p(xe;wTQzqP#?FflkiIlpoJ7kUAKtLgT&jI9i@^p$&Q%M9yZ zYY3i-LemuVVrZt`<83;EwWobRR4!gc#NsFRs!6U@?!z$#Q`9C;to;iGXsFRNABuMh zmv2|}KTCOfuW!=ifczvQ(;i=)smx$!FVwCL^1d{x0t$T47irJpOe8;QgPJc5^kd*# zznL97sG7+H4uY*So7b=Lua3gh4%D{q*$OS8YzhtZN);$}CD{9TLf9@AKc=lse52|9 z&ME$DxzK&GeVhG{V52qChr+$kSEf#fdZE^G`xTujk)kDNgYEXyzgJhs2FSxE9I-Wz z9`_NIvtL$fpr7?US2!=)z5~BLu+>yPss@k6@2EbX<52IKh)wCG3?Ce!5$oWVL~g0z zy>LdNxC9BHm5CzV#f?}!Xaj0@?$)vO(17JJj7)TkSG=tzTUhq^wsi<^O~aQL3}Ae& z(!e(xhk<@HfrceQN3<*9ISthPvd9t~hLfnz4=ykweT->vN^V0%k!?EF{iZ5rJ`Yyj z;v^2Qu7?gbDDJ*3oA6lBde9{&@QyQKn;Z$Wyh%c@oV^6I1j+2!VfnTGOvLI=48p1b z0(%w}6yYf&6EB4H%-IrpeHh+(> zAF$pjq2R=DxkC1|@#0n)|0ANQ7eidcA{=M@C{BmmjEft?P`^snvHDnH+Ys+}k;OT9 zz~=qB)Op@VhtW~z{ciQ_Jz<@_zfXP_H1}P%IqJRG%PeA$=}6yhQLMjVCiprjmG@M* zo~{eyWA?q-jqh*L5Y_u;-xqLrF(kKExaEawhrmOH>s-upXGv|C6q;Z1?Vs<` z2oaNzHku_m6?Z1*de{+n=lrVl0&d_q7siG6N)r4h&s?1I?t`=uu%?@Mlcb*#%Ni8? z>{ixN%2qfSzz&Z|VPSv;acjnXpeu7OdQO7}if>s9#I~#hk}KLkp7~aN zZf?ye1&Xz}{)I^iK!DS6;B(C8Z*6d}tHpe)J`ay}lnMiI~7dYz5f+M>{ zft8vB(Bh&6`^7kcl(=5fx9E2|_~Om!>1i-NJ`Tpl#z03$2PiHs2I=YPAS5INc${zq z4i=8(->T0b6X?hwWD7V%O#q{i4PfHa2TUT?fQn5MFp5|Ka%K%cCl%oMt@_mB0mrFC zeZeL=4e;f+AMQHx%(v?E8C~~fQHudI;y!>$IT~yi@dk_vk+3Zvz^E7j&piQ!h>!EP z>dX6MNLBrxACq(Lwh*&#)8jU;SK&BNr?ga1Txz;e6>iCZv>KL8-XPWj4} z>($C*DY#}Wty?niSdMHhZv8{*tZwI9=ih37X)4 zt#f`ZrAlONLHfAhegYgb)&ohA7eHHE8)#@~02faA04psuaKh98EaCAZ?F(=#RjSc% z02b2R;N81-0Qyma;{05&f0raMkdpw{(^ElZWhE#qECjpR>2ZBuE_(_nI90?4s5fWkZ3;LgqKK!KGW)YsJkucKB#gmfK_R-BB|_gA;`t#e^s zl}cnkLHh8u)CX^0zXHm9P|*$Xc>er3P~>C+br0?XbG2PS5Vnu>@gwvR5m2er;UEE~ zk~_iko-TlV9L@Fv>;2l`kj`#kt*-^1K79)A-N^-Vj8u>hSPOn+e2NOHRqo^20uG4o z026OsfwwP*!Q9*@P<}5D6y@FqBg4bsQDXyWsC@twcaY-7*^jg@F059G>{Un~2W41+ z7CQ+zt|^7X1NxVOeNuuzcH26j#kPHU4F5>`5+b`R4TZ>Y`ytW?LM!BbJgh1K4d@b} zu$>S$c2}+&KhnOW_@2rGVie$OeJqWurTMYc#}BnHp;2inNdy#p1N%RT{IKBblDd-g9|Kl-IXLUQ@I{)46v#H1A3Yy&oj7kZBO4tnu7~jDiBYcd2 zaqj11$lLH6=irX1#r?rHey1DXf_L?GCHD>&Is4*yajU#JA(LBJZvE>YS+z1gFsP)= z&?|jewu_(ouw5$1dUZSh8|QFQL48Eg|CWNZjqqU%u*k!*%!fe%&;s&zNcnI0uyF6) z$4f6X$jcxw{GSRpJ^u&~y#TH(KMU)!aq4OREUr9EqR*Dr$$$D@l4+OZTG_vNJERWM z#?SW8$0&mNr+$%pl28Uj_{t^Tay1M{8^5D}M0Q`|JH`K!$-f4}uk_E)^mY7^z7f7u z_%9v>(FuGD23`iC=Rb?T0JA7&NlsmQ4@loaBx`{p>kg0z_oBGa^FWz}7RQTy4F*02 z;h*kbkVOomw0+&Otc>){PqGGZZ(a*5G*oarZFO}uFjtjd<_A~9@GJNWvWa03egT0& zk#Zdfa<&H=Vtl}Kw<0LMn-5xAT5vGjg!&9)$OCH&Z~%t`dXVoWTpp7=^n%~Lf3AK{ zLhRxgRl4;!eZgrP6Pz4BIy#Emvzs3_fw+*fAUZe@RFsthgbrn8W#Hbud*IL>#pUtv zEB%XbNMI2C4FW?-un(A-nZd#Eu)Y?E(Nln39E?DLjR8nAP=UKS*~>6E9W-7Z4?J`N zFIMCAz2~A_5*T&nO<)NIL?%FBIBv2Z$4_H07|`9_4G!*60ycVDxOd@w%=&Nhf_sPH zPxmjzBZ+~od+_b<*X zh0%sQI0D07ZVFIQkc;ERLw($Ux(GLDeb@*Z9@GF8J~rTU+!j1}@&w9z;XsU%7zcyY z*0tbQ)*lHzDGZ{wLSQJoo{H-m`S)RF8rVQth6Bp4?3>qsgPJPfX?GXs?d`?E5EkGI z$KPkY=dbiHDIkNnJ{gOi>-SX@}Z$vhKpU*ljI8F~R;VES=m64B{3L)izBuM8x3 zm*taR>0e4v7K6w`OE5U}oP=ffbv-4djn_XHVHXFz&XvqIfBJCtXI4NL@yi z%YbyJ@p60gO37dgyT$T3-L6=$mCJhhoK`LZkn`9tpZ_=a&nO?*B6p%0aOxERw!L?t z%MUJmIwf1N6G-dNd@klMk)xQMdSCN>_0t$WyK+bFb%|ga)3*Xa0Kq2T-y1L!(Jy#AGkkSqw zsa6jhtWfjA6exQ3-I6)kbw%8+BT3*;Yb1wZ(^(F~hOZVD?czv!g^QQzWnu)sx4%E} z9J0PFqELQ+q9A=EdJ4o=bP$$hJ;hEGifrTO0x$pj`7fgY7pr2fIOWzw2?~;*Dq`fM zi(=bI7sa=c{8ixbinfrpxmcC6e-~LqXy`sI@ozu!jmYOx(60f}!N?#5>Sb_#4v0Qz zg-!@*6Y1l3!7sd>X6{GeMxMpN4&^08hlAKE{}T>KAOBb2M_`wLurJy4z6Xc@EAS(* zi$mC#bXebugV6s0`XjK5Lj5CRClrM`xF5kmn2P$hjUQ2J+W$EI5!i(x?1-InNmubB zI0#YwzVR9S$1hoBd`lX{U<-vL)t>UPq2pz2y$}*N3?f;_j?fjo$&A2F^AaT zzlMV>gq;uSO?aRVlNZ8YRB#vEzkeTRH@|)3`gf0|-${Q7I=VR}>d&^=l{g@<^Aba! zsm%m99jw6C4FINw!O39=4u~u$M!w;@a1f;Yed9-xo_-Few_Sn5ZiX$ueD^NE3CBCf zrZqTQKcYWHd?Ow`dbEr~h_5G5<6ywyAWps>7)lER+3h4>tgXKlekS@k)g7PpzDw`n zR#FVkPoV|seWT9?LLaurIQbjV`K`vGq__wKx;TOxSFhk?<5MT?ar)quYpVd|?^}PQ zm>K5~AC4s)td&KC$?6|SCG#`*T zy&LLcON$DZ=kyW|h`;2@{o%L5&&o81_&Y4&phmX=B%XE$(-8h89LzP90qZ7wa7bGX z6hVKKyViOTr|H!g2&uQ%3g!9u` z!T}jechVAY@1d{vDd2$XkTRt83pkFDvDDYshZ|2S+$=bss)~|g91iEa+`hWU@o(Gy z+u)aHXP!fJldEw+=ib2C59+GXfE~i`Y-#$p`GDYX4BC$n`_?UJQ$p6In6qbq0Nf{5 z@6&w06Ml}JbJ}dgIJ?729B!vw1dEG{V4%Mba6o@zEpdME_U+qc91wfVZfFBT=0i2y z3y^gQSx=FDdL<6XI1>7e{Ld~fmN~??XeACoC#}K9*$;@wjl;ogj{*({*CXbjz2y;T zfwq+6&@YY+&ItnrspYlxVPhjW2IuY)4v5b&vJd`F{#k*Wbq=w4Ea4F6e-a1x%6~)8 z`+*`i6AlMtEFpFnWIoHX(SxSCTHJg5%K!tWQa5LTu z_Aqbzn@#I?!>=O1KDS@+v!CEf9G2$8(%P!Sz7=N^T*3j1#R7iHO+X0BlPmdF1m4x< zcaDEmL5?}Z2l0Dw7<)N_dk4tBm%~FqgnS)X;`#mwhu;amnlQ&4VsrZ*9FhXvKurO( z{lgOL=e*4G{U;oLC;YobIOh-_&F{rwja3u5CmdEfH! z|JAEkalQZv2?^lh#fu;*DQOx0K7J?sh#vxjO4=9wQcDH_CiNR%T&EK80XwzwzPOIi zfK9jbi|hZw|LwPj(B@zIf1WRYV*F6@ADtFCR0o%B*r^%`)B^^VuOn?y2s$CY9q+z90)Fidql`P2 zPTCuA?o9*R#r-}PF<-EmaUY--bpqV_SO0dMgn2)p60ie21~>lSby$y-#R%eN0r-t> z{rx(t3G`_)dH-ure!I4+N7E#y`dPrD8~}DI`U9q2et=QV7tqW2fE`lafL6i_P>XrM z_+fWIDdYy}>H1v-#^L~SZadr>Od;et_-zP&?T-5Cq0s%2Z{F*My?U=5JUp!)_+nDc z7c;Kp_3VwTQ_m|Yht3f(+qNM=%SSJGOdBzrM)iH)Q`q&<80OuX!#m`oM(AWOxcwTG z|JMHBqyWN?!LTOO^7nHTiV!*f_xtzIVHLd*KP`D!{9#%4(}EXjVD{7;v-Rc3Kj$j?QCwF)kKm5P zKH>b}$OxC;|M$=Uf#GN2|J8c`6Zj*xNd)gDAHW}_!GAOU2=3w#cO(XM$=78m?~K%U zj)VVJ{1MwI;$O1lWAd{!ko_+l{|N41^TYfZ8X$Ybug>G2tuMdr$Jajuci|PW;H!O6 zf1Cz?4*y*g>%gvUU)pL{ukTCe2<}13+rGLz?(BMzLe+5cHoZb3+XdnY|7l61U zekl@EBrpb48ywxQ1CGLP8|Y6b1+T62*ZSUZAOqLQpB=xyT2B$l{{!Rf5xe(4(E!1n z5Bj|D5P$Zebva}T9z1w}i$6zf5s1&7Ba9LMxpDC4@K>V#f4K&}MFRwP9*8^QBZl}J zA~ZPfEbboNHq>4Z>ZI;rx!@ym^DOCl3t`0SxrD?1wqL z5W6fA7yVB(K>YHNH4(}EiP&fnf9hi}7b}AQmo)fu^Iwf|(`TP+BfTXM;xk$5+x|$?x}4Oe8pHKi3VBMGr=x8@-Jv0 z33Ipn>U;dz`n#Dv=Q_dpApJ#yGqxsRc6Jt*_XM%SucW~<`0mZrm7ov$=k;LanuzQR zh#&WTI7e3Q3oFNg#cqW!3*Eg zE8?@e3;Mmf95%=KRPTa$BA50?gfBvT*;mq_w6qlXIoJVl7_0InkM!s8SKmntkbF0* zX@JZHf6M(~?DebVaZq1f1%1dr`}`i%QUyJ54Om(a+S^)jIdKpg@RFc{tcl2autbB# z`Z~b3Wj$^j_}JSn?~PYelKxR%5Q8~be{~%HY<*3(&$)iSMS~HT8xrv~M%IIqhm3JC z1RA0|U#y8sG(ddu5kApYPkVW9yq9+e=ZpU>nF+~3`?K)>YCSD>QkYwGDemCQanRS* z0Ty5mAcO`!$E|Vsha_Mg)s<`F%5fmJV;hc7M0lhn{vhY(^<`iFuh9U}7yT+8KU-g$ z^K-7HuhBrAg97wD{hU)4p+RnD2F~{%$-#8}QsNghNRA3$-WQUg|M?PsfaK{Cg|gvN zJi|&FAUe}OssGa9ggIe3VcZ5g$=}9-rK%{vz?h$vpV<%Zfx=($4~WlqbZ`J@d(;G4 zni@a|j3eMCTaV+FFrvM zTUm)ea@<`100=>T9*M=l<>LA)4uowpK5k#+-L?srpLuCLSV@CM$QxqEXIl#}Qj-3H2D#d@%EZ$xO28XNru?tl9I>+zAp z_>`@B_<{zF52|6T zH~f7NxF$+Kz0p7E6PM=xpT^%nhys^u??-7+o_%c@f8+oe2e+@JLHwaD5ZV;JN2j_( zgFiX`4TWLucHz(Y27iPGnbBwehCgx=doBP-Lw)*6J<@7@;u6j)zyBouMxvi{9sVc{ zT=px07tgxE=!o4)KIhiQ#XSAQIQW*_h{SSzFAe@A z{>I{;b4@PCuKfWT{7L*xB(~#X#*loQe~Jcw5`R-E>gAZT-$esNr}|HG;ZNdkCQS`i z#@+oc8vN6G@F(#%m!SdXGTZ+s4gMtly-%9Ki~b&ffqPkBPbcW^Xa)@x`Jka3DS0qn zJr6Wimw-q0_hF8M`=I`Q6{ta%fzteJkeiVNZl=V5jQB8+5^)x!B}9X(>6buyaw14c zhyw}mH{*Qa@83CC8~`@(caaXk{MCn{ee8s-74UX-2LA3Y;EabWIOpm1$Mio)yxr38 zDj{)$ORKk`9n zfaD-XVknpJNAg4 zk&(DeB&HO>-`w~B?sp->VJ@cs3-~Y502%Mdd_eMmd<}mj-vbg)i@bM)4&^Xc(bw?5 zbm{VLntDfp^)Wwi zZ`ayDBKQ7sx9c!|P^X7yRC(Yy@N#3;+kODq!JI0$e<*fR|4l@QE1yG5j~tYvSTO zk$AF|F|4bPfAu~wuKmw_t!^8E;aA_|&(=r!-o}3da2nO&Vgp!z{4A43=1UU5z z0E_00<-(wZ{MMl+j9vD{-RChXS-yun$EcbDHZ$nJnDL`P6V?|nul(D6=G|$4m{}jj zT^|7Ir(XbJ%i6!)-?=9P#%sghdH93--)06az^WDj45HowfrE8``#|+_Vbl5lw&6do zyx)IW%c}noli&O|Nj(LZ1F6#p+5VqTDFo>MRIq-F?DHt{TA@4t3#!Ka7XYdW?SJ{- zrr3N)kO6D|g!bP5Zx*}gzd_iH|9ZjG|LX=# z`>*Xk<-exiV&=0%|ycc-?ch7%$$L{}f_FeyFY&-u;TetrQoh?Et zmIR)SB5qO*Y2W<$idp7$5hlqx2tQqtr0Qn&R8oNLRAhUoX;M1<^N9o}b4&Yi6HKsv40PEYb!vFvP literal 0 HcmV?d00001 diff --git a/games/NXDoom/data/setup.png b/games/NXDoom/data/setup.png new file mode 100644 index 0000000000000000000000000000000000000000..3a775d24ba96063062dd1ab5ac2ef813a6a64423 GIT binary patch literal 5654 zcmV+x7U}7UP)}X31psnVzk?XL_qT-~FSydb($Nt4XF$lkWF< zW~#dCELHXU>MUQKIt3I}R8d70Ra8+$6;*IzGBYOv>so*A`&Gf-D6J*7-BtmA2RIrOufo z2%089LjMzj08Ky$0TKiu1cVm1&-ksINOV8N#TOuLd>;uKkFV)}0OjO71qfpifuJf7 zh=}OAhJZ>4s2Tw5uC|q}y!xdBo}3)e1aTRe0zjq9`mDoMIy2`PGX}<`7JLaBQ^hF* zA^&e>c809HEwVD^7OS##`+od&XA?XlW3moIs_Y6!O^F3A zt5PEC7^E4%wtqHZ<8ymtWuF%cX#$zXs5C>;BCw_tQEm^SbB zks!7;4}wVV3D_+beE*AQqOzh4P5av5@p#k59|}b9%s~$V5fR&V`^C#Kzp);jEnR4D z?@t?lETUms(;z%!VE{lR_32K#q!|Fk^}@bz?#U>xsQ>^h@{M7rEBytWRc^=I{iE;( z^)CHYE0@AO!wmp9amieC?{7;Rf2PZh*5Ls5d-S%)Wgj>Wv*+s_k`qpv58E5>WQ^ZG z8o|qLLjZtfv#YS|l;Z&a3r|@9G2%@)zhqL6BW&K=3qWq8R9Y1fe}#f^cWfw-{_X{U zU_>AociZ^tn$%w5We65(s64ug4$H zpGmX;X(d3scD>mI)i(w;9LBEZJ~RylQidf0T807$YvWgW_r7+xtpMj7`w#VESC2n! zeqG)$di~+p@0PA1wCvmqTbUC*9Ui=RXfSR3;h=`*!SSApKM+CFYj2^fx)NT`ApY9q zfhJO0K`vnMHLLhjajT2CNK^9PO^ihOHs&a`^1=W*eEI_zBA~;Y-NTq<@d4oQ z6ykUJ!qB2t)b2AMe<&2eX!PM!&uADCAu`0sA4xOS3mRQyTy(~O1(gnX!vejd;S4d8 zYqrY{D`#jO$^0}hnQBU`sCHV=JQ$1_gBg|C6wGni(K-@DP&H=&3S)Sx%_oILUKl{3 zOQr$jMHNt#JV|>TymHMKp#g|kN}zIk(lDhi7iP?w6>DP=5eNX0hz;i=K^W}shi_yA zvDO&rVTJM1h!9|mp}MXP7OOS7k068wE&4JE5kV6I;ZO)&ZEboy(qAYs(jX!TO@j~u zW##3la978@yrMzGy{Mu^Uq0#S=!D! zxujJAMCr@_a5xOV-w&J329L)R0~!z3SZ`=(fZOd(h_7iHB9Tb!@9^QnaJgLQ>+3@( z6iSF6pC+IWEQv%SP*pWyX{RSkAWIc$y!*z6Us zJ1Ssvl*48(gM)YA8@GL>SOpjghr{rAJo=qhRyGN)84(dWJ3BEtItq)$g1WjoSS(X7 z_^ehdTrL*?z~}S9=QBTe#1Ll$J39=B^dp$2Q+a0qkw^rCgX1H10l?*Qp{AzBbXr7& z_V#x8{o@zdFakwUOs8kHT2WeBny}65^su z)>cz>vZ5#`D=SNB1ZLX`{r&y$cqYH7bCP-SH$ zX3Uro`#lx-hB)UaDJcPqdqabW5`LReUtb^k`ubwO6-B|4B}-6JlDrKeQ_>tknxJA)DLt9&0+B!dzIOlLWod^U1v3~rKsHdj~nx=tsj>U@?!|8M$ahlU1 zX$G)iqPPZK{CO*H(_$SC?eUI?MZj4(dD zo@O^1YRchk^+J#UV-_%Q5aZxX0b?92x|Ahpt&v&he2IuSfGA8#G=!wv^_A$Raf3XutXM}M7%LV2M%<4iO`|xE;Vk58!KOZEw1SrCnF6r|F6yeL2 zR6jrwzI;hDfFk_-Q2zA-^pzs~94Wtg0s2Z2ehwwE3IK}m$-UVy$* zgfB@FCyFEhET`}nFPMW{Z}=RlD#|7v4FF(p$cOL$cq8^5Y%d7-fb41Fa(w4M_`MtP zzSB-jdq}hDEAZiqz6!>z$2@#MavLDm#s1Po^D-XRvZW_L1o|Pg@G%b`klhQ&A^e)E za+GE>=vHO@*slzig*fpcchh=K+n zG>G5;NQ93$_<-zT;W>iuu-UNu8U&etzTiF4}j))|oAInaWw+g`%k`3=|Zf#;=NNUC5-heul+W5?>z`u%0S$f z_V^043dp{nzwXA*O&Pw|=f@>i+>8s>T$>R-K-lx|1Gx0^|H75m-46fgm}&S#1R}!P zFJGkJUYZ|FOl|VZTu8nnD7sA7pSM`d&*uXGJ-r@$_!D2mQ&0a5WKd57pW?P}-S#pr zyySZHdj?IxHGlV4pgH~5Kqo2~4B^r%ZpK@C5158; zXy5);TyxWUgu@Y2@DH_h;RpBs3JI523*@B{$g2W?tl)!ygDqY7;6-1>mM6Dmm9`K9 z>+gC9+h5x?3BJ{$;Id0TjVFG2A6|QLGj_cATRi^Qy}0Bv=fP@?ZxicP&g*aP#eEO{ zI&1jbp5K8hu33+^!@UVi!G!#Yq2eX25m>$S0usbc`SwXu@#Qri#J%77I_$RO z4J#o8+B>?j?0ug`AQYWAItu@|d9$(U=l5dag2tpk_w8@NRoC5)Lx;QKQsi(tZ20S+ z9zjFBJ0<*3D2)3b{tf={)C)+wuXOlv|3KUcigPCyWFs(}JAdMKa0QQUegz-;#1&{c z)IKT6ac9h?N$_Vj)Z)*-`$OX}P6@xGvlmz0 z@ZGH70~}0*@}?w^SOu7aZ)|6rW6!~XN!39-kf)!0(a0paB;57wuc5xqov|pdtF6X2 zZ@mTvd|eFBzqm7HvA^}X?Re+FA!GwTwpWC~gbLY`{(86>_(1f*5#w02Xi+Swcpz=< zU1)AOoB)5;j5?h6v9q(T$3MRE1DM%hlmZL@LwiRrdU`xb<224`fEoD4Hb(M|;9b!R zNPr)0sn=BNF5ihjJG*)&wf4_?|LIA?rs~=O!26ajg8|U}(sjG_2EMxO+{&k2$s& z7!{xa90`1o{^Tzi(8>zeq<;SJh}RT+eL#p0@$dnL(o$#Auz_F@Q-v>E`P~ah0Usa? zM(@UnFzRcojpSqhcK&OR=?6QzcJEJs4*<0_l}W?;d}HrQ_&`4Q0@A=I0`@nxCxtP0 z&P>$T*Nle+(A3<9f9!ZOYxp~M?m>Hdcl1bgP<3_HXsDmuiy$Jjck~_sd1*`^lEWBVK&!;%m^{+CJel$31+UD*zaT zph*or1AgP&8Ti?Tbto-yq=Y|lxo2++?%A*zBi^yZG$*b{je|2FIIyFDp9N$n_8+?Y zCR6Z*5O9^1;?bXc4|TQiADl{b@9Lk9OAWuqU4b90zrhrIBEr(ejkx}*^AppYxSl7y z0r|av4DdlfRYj>O_{RGD##wl3^Fvs+bRj0fpXlV72!HXSd3f~UZ({bWI@3-hB0_1Y z1KGnb)LuXq@Ck(bANjp$_{Orn&W$Y_@5lGD2n)npp z3nB32Gdto=HvjH?L(-1IHGh>pC^Q3nqr3RWU#-X4XD%}Zf8sJ23}O4u-FWHm|3YhP zN7QZ1P~)z|{CP9+f%l(^<)@wqi$$4I`o?ni-WGiOp5H{zG;?o&GeU4+yA&4E44`b@ zD&t!b8Q~LvMaR#^i%gE3y+%#RnyRNsCUx-Oz;T|j8P#Pz{jG!0CVsSk?IGj z@!thb-Oq2Rufd(`uEu*#Uz`>EH~()x?s?z|cn0Dpd@$kLHv!)W9`d|eSdGA`-1+fh zmNGDlEBY(Flc%S50I$EXH|t{m&D{rb24A-1y&Zf6@C`9b82|>R8J~ww?d0j~?$5fx z*V7yS5$NfLFSj=!-xWMX_=cFJ6cjatbRNF$-hr&UhrNA+iSdDHgfCZ8OMoMVZ-^KtN+t$-JgxtX=Fp2H}xnB$cju^fnrj!7dQsdY7A_`|<(1%bck`aC= z9KrC&Xk5b63m+uc50GEO!lwv7CdCOdj35p^pu3OT+PgD4hB`X?bq5uYBluH0)uSbe zRe*j0jv9PJiW3BYi9mG2xQ%c4$rfC5<%K9Mae#`0>($U?Lc|;Yi2rPZ#{?h#=1^1?C4h+IRj$DGm@fCY8!x_<+p&KhFk) z9CaxU5O?M|e7TK)y!me6v`Mi;a3_lJlS|@9qcHvO4JkH|z=Sz^@&&%k3Lp;#gybwc zZi}0*FQ4ESY!#4u=|&JYb7#K5m*@zR``I`NB5u_$I~jBI$cIl5Q#zNUp@J#_3<+)p zm<{;>Uv4!}kOlw%f?EJ)Ow}e6zFZZo0RR(?0FvMr8-Y?4GlBwy4-^dm03f&my**r5 z@PVQM#3Z-^V#ag{g#jNZ8bE@GDIjJ+p}+@<1~5s)c+?1vefWSx18^|;^W>(IZUjos z;5(VTiKC?%z&xkFUsm4Ph!~H9I=y#(qjRk9s2ubZB+UR$Di>!qI=sQmA>~Og1&m8H zP4Ml$z>+GQarBPboTOJupFL^eCj*-GQ>vi6eJ&vY4gr1a)@1J;0SR|fR_;9uXR1?) w{AJ7DgU=kDqb#bZqKYc2sG^E0s;DgW|5Y=g%lS4jEC2ui07*qoM6N<$f{5&*2LJ#7 literal 0 HcmV?d00001 diff --git a/games/NXDoom/data/strife.ico b/games/NXDoom/data/strife.ico new file mode 100644 index 0000000000000000000000000000000000000000..85ef389ec584dae829ec91c5ae28f299c8280ebb GIT binary patch literal 44131 zcmeIb2|QKX8$WzBcN-`fG99xrOGP1)QVB)KJX8vmDf1jM4;eCrhARzJ;T~K935^34*R3SapU3z za5zhJ%)l^`-#ZP5BcpSytRwm0**M%zVH}Q|dnA7b-Pb9N!%0eh&ZB!{Rd6^ZrIGv+ zWgJe<8ixzns-ZgX54Jy0(epNKRMEn&VrdpuwUNUaRHuN^CY80@T^qVmJ>vNFyaKN$Hii{^`%|usrLO zB_Su{_X-?hrkhrC(w-PKr^`S^Y4*YwENfL5RBTip1#@%9q-!N!%y^W$aNfzQ%-ezo zc~3Ghed7Fdp5fzy+o~#7HEiXC4vXqQ(jUBUSjf-PBzSKzn^HU@*jY5=n#m0xrDiKbt0in-E}3>!$=rR-!apu1XsR-#`e;y3h*Q+x-B4P?i6dTT9un@% zeFMHZOP=!Z?&YKyo2Q+uS)IOR-y_x!%Uum(8F|`UZ58ki1}vFw z2IVAW4Hjz1D>t^ascPhxWX1l$w|WhQ99_j$h*z&Nq5BrSsY_F2wV+l=w{zX&KNkI= zx|pPu9V&6Tajn^Z>b4AyE7!djE!q8yH+wP9=19$g zft&lu4aS?#ONrwSG&I0snKx{?FOJ67Y_uK_?EC0kS7RN{cp^W$v){Syk?#8qO2(IO z6`X8ZaW#2k{+zulF6|QC)^vJ3YpRI~`KC2PbgREFX(s9R4dPlQeRGB!$-(QM43diC zdTVBFB)#IkDckdyo14i$;AGgGZG$JxN!;9le#%Rq-mIB1Re?@(PTH(AiF<36Ogrx^ zkH{8KWH{41HKXP&k^lbC<+DvykFCS!;L7ZYgxJ~g2M-40ITWhqun3h~4m&4UTJc04 z>OP}p%Uh{*XSxz!Daq``l&PYkt%G6NYaTXNo9=a4dUWN9>6Ta4T+vTY+7iH7SmT`V zlsTMzDsHeUoAVOUF!cUz1@Zfqjm8@cCB<=E3eIU|X$pkyWuiPg*K|s!evDw}U4hQK zb?nPm%L#}J%$nyrulik>c9;0=g<6+ytrW+Fvrju_YIIKSfzF3pdW7O@`MJ^hMsMmr zs@=~>5I;50u*)l*MUZ9Hifeftj;2m#BH8&}Y;S6otZOfmbu@Qq>aF7qKYc~s&5BDi zo06YE-5zI}Kfqup<07qarC7S!m^-r$43kJ%WtT2ZFJ;yx)OnY2lJmNXogLEJO3tc< zt7p_H_-NWZe7MW?z`hgRxyPxc)Cb$u!_^9M-*?7l>5)Z>6rnxa+^+2Co1KcC_CrF| zvFdx+mi6?^SO56o-H;(Sv|OA@p(x}YKh)emeS=2Yo;UC9*0m|7JtXRB8ttmc7W-tT zc}#J*j~whG5Vk+*#_~PhM2-g2B91iXTb}y@7#aHlss1i6E3V1B7hm(tz_I`B?8n-U z^Ymv{hu`llN@u^YN`2`)0{w%2>`wAp^3u*s zt?6BEPt*NtGTSfOmf7cZ+&s^|%*S_KC|9<@!0T+Ld}yrr$;HlkC>cnH1fSb z*V>9zQ^1aGus4F!>6u?hQT#G-+!;ok0TFKvUvG=lf*Wun2Ob zyLHWZIk78SJ@m?|mLK5U<;Bxg`*M2HnJd{ntqyyO?AzZbp6g{}eOu&5w>2m;(sY;A zE#Ya?N*@~StCx?|{PTvao}nP2ZbkbF>17pK{-xZPZ+$q``@|_T-IeTRSovXliAu6+wR-koK}{@6`EG}O4VR|3uD&0kF74(V5SXRu z%;|5JHtVjVn&-g%r=f;8=__H!2473>Q_Kl-)r-j>E#H|baVama#M9X;y;wVmLp7+~ z&3aes?Sd_;~3pAyj?2kRK*<^XN;MIV-UP(-kqowd&m!Q+(99`K#^L&?G zZFl^5Lz-#-D$~K1o$Us?cb^7sJ1xFFQVY_Xo8{$hQM2znQ(jqE{`{1XaD#@X1W_?6 z;@U2%fz1YuV|!XuT5FPh`bws^Irh&qj417%vO{#n&Z)%~QmpJa=CIrKxSSnxOK14r zvyfbg6J_?lL}zx1HGCc}?4H>^-2dj*Ki;lpnb&J@@Q-)#7d>h&vvu4rv#qIc)mznz1p+2sk=EfaxJNRPHob$eLFs} zx$Ndvo6U}!?!EF_`Sa(M=lchF<>i+*#gM{^bE~&VG|pe;U=^99rY0)C6*9>KR{C_3b&9bfAKwUXoXJqR`DY%GF6+iqU?NL}Sg}?lf6P z{dB&&j^W}h1_lJG`lk8wP6w|JZPpHxSI`3Y{s+f}+8oLvxmIRcgl9OSO6I;Z>RjU$ zf5>o--iHV7$*1_{%zd!3?eX683+xxsACu}NzS)` z6u!N7cjdNE2R27{L@tO}op5cn3U~YZa(8iF?vr!6lqLO%jqdwz@2p#J{gYn%N20CB z)n|JNsw$5R_;?3*M_qfi%W+MZT2AzA>IQ~X#b?{D&X{KGx+d_t+2X55-yG!kIsa+l zHcPeM-a{nPJ-4IPrYeuTTdyA9U~h3|Ba853D0lCvsk1-N3-Srz|mD zUhi1KGqwyP4w=K98|+^!xyUZ@0{yZ^GOkmL%gCytSWL^XkUbFRsyz6%j2gd9L#4r3 z>HI2Ja%yMyIu%xScD|%7F?Pm+f`X3>#A0uLlEt%fgJ3!$7gq`GBp2f(^a-Qc@lx-lQo;0 zn@?3J_TMYB=WzG%NJ>oP=F&UpE?&2K1M?zwNRycfZ5$7lay z+XRXm}YLh5aCAo(W@4Gq;7xH;xmO(}LVMwzXfPsCXqI1m{a7})3X0>{y2=OBdZ zoiB5p&Tet=EJjAg^`xmI~(<%UtD^qz-V28NoN^j=mYFKd3C@9R!oIBRa+ z`}gk~U82xEnB})`WmO2HkT^NENOwQt(7f|=l$Nd+Wj3rM&M>`#*t`7d_3grUUNP4d z@DX%x&ro8Dh*3PApP$mzm@C6SjZMHuNjU!G`Sa&_yjCbveK!Ot=?Rzi-wuc`nz0gB zx%VoC4i#$TRIAe&!OOJX z*X~soO<9R6FRE#4YfBdNDUJ_N%6U#ecP|VnVG8u^ys3UcO@)<{v+zB`+pey*ON~o2{xpW(SoY!DYn)>FW>_^vvj9#NTYiDiQvL$P^_)#K;&h=~#*>FnbRL$fe!D-&rT z4-LuMz4DERWm4S%+`P)GQ%h}Yr}yac%?dhV8IqvYReJVzXGxlyv>SzpY@1QiF*|P5RKIuY>Cp&}> z2+vo%&=An=6j<(CRg#gpX#>yV-OoLHbG78fjy_|n$*?jw_%2T0Aog)JV|CjfnJtg^ znzHn;Xc7bhtxneLRk13m7|2My(;N`}P+&*7(*h@stHP;~=a&~LtH0GMtc|MDFu$HV zAUdeFJCk1I>9)?N7J;oF5H5ryZKI?f9b2Ob>knlviok z-#ormb^{mpKBHZh8(vC$RQZ$Jyw>eTWux!`y<}bci`hd@gxjuF%2%};+NO!98(y>Q zc&eRA*u7$=jrN(G(}_ne7hEXtdQN!yF0-IeSCOgL$VXjGU;WK~p>T&g#hj-NY!75n z4p-Ra=qMgGv&1d3y+F~WvJJBaxY6Ns zy+wS6ljq(oz~vAPNqQG5IPTBEiNGIyJ4otZPM)if967lnA^TLNj;_J!bJvOe8VLk> zm^T+EQWT%AGbA&scS>=kZL6u8`e8E@+z!%tYjHy7uf|$$ z9oIDOlZoo8vWl-ATDBjv$+a9z7zlroPUP7_WM`eyHXV1cfU=74TIkeF*OohLPcN&e z)O@p|%9M0g{W)QgBFU*xliE-%0xc2;cowA_COdn|R;m_VPl_sV3r{189Jyxf-Mg^3 z0Qc66G+lP}&2%4G4-v=buA4qQsxV#E6KWMmzAG*6)9b$o-q-f#UA#=poh?1}_|(?) z`=34(SLjJDm)o&ae`Y0qi^r#3p>>4iRXS5Oc&0Uo7WpkkFYDlON}1pQ(M70-yLtV} za0;*TLq-$UkcEy{=6+&QKA!V7BcZC2u;u<7-}$lddQR?#4>wYJ7us@@{MYPZ;dEGK zZc(~N&1agbPLb{oQcAE}8QsBf%7;E_3Bn^{*sQd4Q^F07a80*CZ_-faHN=l;ZPS%h z%OyNJ->bQL4&Iz6rWjb1k@NNj$CmqpgK6T|<4t6azayq3;1J&eOsMz>j+UA*iG~lv zu)XIp<~z^y%r-C)@sURDT3H+d1L>&dZ*}=vs_P6szQOG_oO0``hPU*vj3iE36k_nN ztIB#xdpXy&NbIAVmaX<&{b5y*?=xMhrG*JDV7oU1*J_tJPm;Emw-<-=)Xj@ERf!F)J*v1v^HyeJV&CGo_Vye(L>cDZDck`>zB_kW4wTkC z-cHJX$JyLhC$FX_YG}mNr(zdRD0o1;j4>-I^ZgZ@=9e-=f#z zGjy!i+@Vy0oiT@)&4Os&MI<-8ep{b*y0WOyCb_H0F|akLwuQcXxi;0~zYxgJMSNoIifldasgA|3q_tKFh`&y!lC z=J?`P^-OV1Dz2JQaF5r@ftxxzr|43v?iJu>9iea^OKy1fDSOD`qKiIp>Jm1&hV<~g z^YQoX2M=?E?2wGoQn!i6FNj;{IZyk_niTg#3^_#8*{EFwx2OihKJizNH&v0&U)1W* zGV^U{D;uv5Z-?XH5J!+{9N&Va56l#ZGkrR2mInC7La1FKkzJM9F`B!-%q$X-)j$L0 zZZxn4D0wqj9@T1*&wQsk_&{vEtkjK=&Kakl@hcYV6sj3DrMKNzd4IV@Q^j+>Y5MDK zb_f2GRX(+K8%co_uWBLul&0PJQ}uYUKKU{i$8!X~;54(gm|Vd?qmavMlEyvjGkF)h zxj(d}YzVnQO-99dnYipsjw-NVA-$Fg^qj~p!!9{4K6Y)_;oi(~Vs+_3px#D9z z^-|z8!r=36i`f}Yw}~?Y^BdhA3ff!m9=zx1)QZaKR*Y+N@i9M2wl%1$vsm+WnM14Cx+oM#(EeI5n%%$BxNH`UUaH&?f| zXbWvLG)4&N8FakWTIu`iihA#GL+9Dl7Ehf^2Agw5JXaq!qEZ-d4=lf8WemAfb-jyA zaI-=vvr3xwrFd6oyLDK|qz~7KpJqA5u0cKSSj}R|@`*^8|1_3RJQo{TcomgQ<(n)> zRrFQ0$5KOkD}tOqwvf8#3HjXe3Cymrojs^aHArN^-c!JXkmZkFN|Qv}UWIAydtIft zn7eru`(~^owlO`1-C{ylf!pA;vvJ*}h{oT0R_g}%N~W^uCPpn4|f8nVB-=ex2(QOneMd_Iq& z`punB2~jYpTXK$nTOTdoX=6#0-HIHwpYk9$B`#m2+_7~HFHkHE4royTY7Hj z-9vxJUlsRmAIYEb&q0I4>W$uR^N?fxE;^xk)U1YRe(tLfZ-G)p4B>R@w3}|C65BZyE|7*LB<#JnxLlR4W}4ft}8{tjc;@%{slo% zvP#a>;pP$pRz=cO(t@?VTXY9|v)c!|rHbSm|#z2VJSy)oA3N+#XO%nzuDf+7p4E?z42&&e_f2?UNVv1>sDVJVH;6IK(Lz* zHBC-lpGV%k4_B=r4r#w<-^kdeN$t2U;aS}-S4N3E;`7{Q=PWe7&aA+{;Cx&8u`ye& ztn^6wz1JIs22*8>cJ;JvInzpin#8u| zqk2@$;@O21!2?wPv)FA314TY|Aq0}p3gRURqgGT>@k0LuGj^K+chZBliJSGQyvpcIuWh7*P}n? zL$mg7!XE)!ymy=ZfyROyo>mFlPPN&#`Fv%WFH>6gyR^Lxy=LmYl=1)uPi#;_y~ZTs zG@5Gm*^#R7p9BMQi32Mk}I z77;IKj{oqSu)TmR`KLwK5mfnyGvdz7%;-J}b{}6=^=2PF{!<^G$#Je3?%ZbL6+88+ ziT46mVu79gYER<%(7wGhEN2vNh$}j}-^scmPRsL^x)gOVz4V6r`6pT=|Nb6)-H8}N zIUR1xT;B*`#RStQ5&6bzKHlOVXkxQM{ikt2qs3+F9p0itm3_NVOYn^^I;qfhhfH8? zpK2T0d^2OygE;)FPqJI?2dR3mlfliMi&hkMXWrd1H1cl0V9%kt!kBuztHLo^vcmR_ z>~S|bv({|GC#f=dluCt~-C>P$Npxv9HoCUxRd!EF^p7txQMWDRyQA*$;?0v}fg)U{ z(DK(Ygo0_b<%CG>pT4Hl8ylars=m4(And(#XR9qeMv_l0)wZzI{J7o<9dA13%aXB2 zAC=oiO_iK2;?qQBvTN4JJWHIJtRa3>gL5CUJ6X=4Ju=fn=cDwLu%a8Kse+ zjYOZbK6O^ND6{U1o!wfF|7696`sNN&-6QZkO(M=Y?nGj26f1ITL^3KWLw&e<_rWKv zEX5KBERht@OF`1-lq`x!zhcUPTNHsTO4ptHSeXq_v2E!}88z<(8#gHP7A@;NHu8Ke zRYHA^_MFEDNpxD5?8=Mwr7p&LIAT#FII_NLE26wEa9KL^50Ho??~< zX1Tm{1NOinFz2dU8?Rjfr)J^flOs+d0g$)5?t%0>n9XWbr!!MSiPLvz`{Pk(!=%I7$)s?p|eY{~pI= z)pSNKx0PiP`J6AEWGlt$^3;#On?KuJiejqpiR*e>qi%d4DhMwpid-_Cn!GN!MNw|P z52d!1sF$7#Nmth3sh)@Fy~OX-S5y&dhU^_#}9T4=(rZ zp4GOW4o!c)(7(TY*E8>XX_-Nu)Gik0RaeVe@%TuGDwFom)`8`euAN*yq@1!CJ>mT4 z#5o^I*JaE!KVmv}3$Awxj&2(hy;@i8{^dHQ z^F!|%8PhIecRpVr_Zd&(9o}PXwUqZUZRJ)E7&BLd-DusNtL#np($V8(RZfMi#SAo* z(Ct5p_uF^To~1*6bxW_G#2`m~+oRY+pR}liw*{8wmo_Wwn>e3uDe@93aQ7K(k@=*g zv~DW*G@}0_!g{pUVd);sF?oi@hf{y7ab-RBN6-aIS4n{_9TID%q}<$lhEjVcaFh2m z?_Ql8TSwW}+=Lm@q5W0#IXkbMR191|BoyLb+Nf z944Qs|45%gsm+d9N|S%k^inO>efX$PkL94I?ID$`PxrRcqwa_c*x+4mdXk(`cavR< z%Cg_Tx`1hDVMb|AW%iaA)G{QF9iiMF9(chnLhZ0URSpfEuO(hi8LrUU`L4%CKM+eJR&W1}@Un`FMxLX`#d$K@I{n ztG7_|FZ$8Hm@emDrKi59+_uAs4k;Lxddv(|p&kbpicy@paVSt8h$iiOXJwuM*Ns1< zCA3Bn=X5UcK3^eGdyNh2dko9aph&ij$ng>JeC@#%mA2$qibMc$K;U)S)KD3YMe`4w z+VbaPpH%)LKRngq}1_csDy$yhzKpR2CBrs_^n}HH0tb3*YIcdmz{Cdn`dw51vlBN9ax%h;>oXxqANc z+Iukv1^cm}6&&(eQ3F-3NU*~>a#G~e452~Dp^)aEe@-1HP$ zf*R5(YZd!i^-3#>JX=%z(8RlzICJ=*5K~Cr&Q|)PH)az>*7-2*Gs8XFMx1$22wQXM z)$M96a=@gFIK@0ds_!m&h|wppOB972Wv-o=i>L%GB&-XtkTq?lNT z1gx72LshouldN(mGY-%t4y-T>s=_~Fnz>a}Z2BEE&WaWJk+JnZ(wp3C^4npOvrjjR z(n)QR(e#$IXEF0H$6s~2$8>2gRSfBzGAT1Gk(|JgLx+~7F87v(&yH)zqM%ZIlQ6vw zJ)4%)diitc`Dj8h4{mB1Zsl>xZFON*#t&EHi|X6iTFa1f16LnSWLd|ZrnqrQXS`-E zF~#gmaOib4-b-Vm*dRt zR^eZ0mU44d6g|LHY}oSPFq%7Jm&`#+vf8URvkO-xu9`J#10r6)!gqBOeC(sS{jWN?bd6nRLX#__e%A6O`bRw+A35efJ$ zb8-Hy^xb8rllYolBX_&fmU#x66^nG$F9lc9&rSZUBHBUf ze74AmX@QV!T0CJcq76-ETeU?`25%oWDXuKCm%?<6=by#l85w$8WF%*y7J(MUp)1xK z2X^OI~5|j`evsP18^@~%=&K@hU zM>S0kpMykeR8sco;HjaPugtS$AW56tTdEaaoQGpg`9!o`CjvLELuD7a%v^bhGAmsC z)lSyZ>BWwFD80JW(x)v`0x#W;Ou)aoF}t1Pu(=UV-j1Jqu_8(Nks+zhIQD$;a~v^B zLim>RV=tk@uP+vbJ$#eN@_3KSy_5L|8t@*QmLG~QqFb?Q_eqzNly@AIzHRMA-tWtv zq?byD&%ycH$|q3CT$~~E`)_2wc&x|z+U-pV8xP9)>k3>GH&`1>Ww zyw?vQ2W8_aCAU*+>IC0dUkQ$zA1>@8UAyo^X-nu~gX#-T&ytwPPZOjxg$bYN+^-d7 z^VJ$8T=1-o3psr*ZL6)6aC-jZo971x`kq-0*KIjbaF0W~OppTP9()qinZ10K{!>RK z%$MoiUaBHzgT@nbq^JmTx58~&uc2~L+3e5~bd3DBklWXYvljZn;gG{u&eV}a%a8fT zyz3GR`>xz1ww<{ti%oM=SWHkd$W39=&rMmRi;`Au(j5IuEMp!U&2m}iMe}6>a32TY zOa@?&17Ha!15@A-F#1t}!4rT{J1=_lfiVa8eYr6L7XU`fh#LU5@LpgI9vCfyNjEoU z%wwZj9=qI_C078jGPpg8fWs^i*wK1}&Hwdi87z7~c-|p5M&t$nRtA?*1mNv10NXM( zV3*l8N(YO<)!5Mr#~koE<;I8=0emR~qk}`k71)I3fg`GCqzr@W<37K{EjLE;9spK` z)Y%qTX5H1D>9d3p|Lh5reP-p64{4u$q!xb}?y{Emd;4FoH7b{%t6ql>T|ulz0lp=4P9Mb@Z`x8xN+kKoH%g;!otG9&E5`d zJdz8?JT{u;RtT`;k#_`?uXCldjm@Ci8MKB4~e3H8BGXe{^y%z-HR ze1t_FA7PliEFN3VczJGz!eVR;8CwTO>>zC{Ssd2?O&yDN{Dblj78VO#8W}IY z)PYax2aY2>z!CZJyLB)b{CfF3&V|KGuK|3i1Ap)`uy1hz_RR-@W0O6wn7!FpGUoW5Ev#?nFHo(_)(0G+a zMe|QMuq{zQ}R@PgP6^?hV` z+WsCY9@j!{eKVZ7Qw3=`xp3svIj{;p1~!Kx;81V`So)^F99zzK`Gox1C&=*zK7RZN zFJHa{Og4D^`ZYXy^oS-GAjcy}O-+R(M~;BEw>S77vf*q0< z_JYKE8xT@H2t2EH!cwI@uw5^K_l#HGM4kr#+#n7=AqguRlf$@CQbK7|4nqq-b0ptk>Hmhm#k($PaU3jdW_K)Y zWp^lTWwk}=Kxr$>K9sCWTbZp&TbV3T+FjbZ$fC5B(fnR3qgiR|LX*B!H*0dobYuZKrWZJrRp%2j3w)AcQ z3wGRn@w@foT}uf3=SJ4QcIiKaxu{0zM(AK}~kwlt2Hy#a4CjX*-?-ByG_8&_F_pv^j z{K9#p`=>N8ncewq{`2~j5SCsa(La2l0q>X%>?^keo46`X7GxJ)3mozWz;1c&yL@0a z`+fX;ekBB&JpF}+Y$~uxZ3Q-w^}wOD3(=u9BJ=Vu19o09q+2=h4Gk<7#jk$1{qY?t zA&3@ymbbsq5O524BOU{-U!0}_r(xtM4IGl|VQhQ&H}wkymJl%A%QrN9)h2mD9|N0^ z+z1T<%aLBE>+dw|{(by{hf4?&cSiI--=zVq3-IRgXlxmPNnK|E0kt z1Z=(VJsLz}9)ggj{m8ljwFis_4#TK#`UUIW->+XRyo9i_Vq`t>g$D85epv5(1e7%l zVZ}Nf5R%oT(ZH^}2e@OKf$Q_y;tL-ZTm63hQjsMDO!p=86%E_NPk`|*OPZ|yg$4lw zf8dEDpmoRF5xv?M8e)22@xI@G|0|+P2r7?9^lumqQYBPy@^S+k+kG?|G>ol4BH$YE zA8SEtpO(*SpTB6p9~%O8+u!g1t71wB*m~#-4YCzf@C)$)H+Kgb4XdJVfJn-7P|`*6 zu0;^=h29^bA?Y3PoEV_Zo1FH)U%x_p2|=rIWWDr-2K&<&;c%b}jRtN1qp;5Z)L-vH z)e!g+-T?pUfsye6&E1?1zhD2_#1aCgzxY@NGS%N&Hx_5N+X z;Bxx?`qw9y5X_M7b1V&5n^Y8-7m%)Covi3cgKJ48&BKwK9b;4*8s$K0YrBIq`c{av=`kFRr?<7YlyI?tP>pa z>%rm5LomyF2&$P+K_%@zY&&`bOcU~8i_gV(zgz#sr_DXs8nL~-9f{OH(;;JeCSFc`$bLY;%v17-;$HxakLqoyR(h@?0gTOm5cHnpGKU4mq6RY>b zhYz%b)!Wn40~87c>gwvCqM`!w^73f)pFDXIl9Q7mK0Y225)#1J*cif`9l-lgOz-d3 zFR;e@j?kLDAdK|iE7a^jdb2HvuG73SDFDI(vjm= zngFx7J}eg7fv&m!vVLbQoh(vLMcfGXgAI)>EjfaIIdq(pdiqWu0Z2xHf|K|F6 zlme<1?H?lj;5881b_uQ7T|wbMIf&@xjpSuKLC*RPh#BP5@@%UPfsADVNE+Ru<=N#9 zW4x&RReq1XPho#yC9je@;N_ixYqb+_$RHic3I|}7wgYBKTUaE%f84|5i)4r8_FVn*=m( z9KkCmoy04|E&J8_CgVPAe4*lSK9iBKx-mTkW-Bs7X;e?akHay}8A<5$e}Dg%ae&h% zF9#ppO2x-?P`QqDP&uPIs2mX;RQ52GLOZBz!5!4ahfxabptAaRP+9yssLb9SR3;5@#_cyRP83_XL+Xbxy$>(4 zA^449n{^K-y#eG9xl z>xA3^=v`6TSwA#U^y9DPo6OP!x8=GN9>%xieYgi ziDoy%d_#T-gXP50&l6csrs>Uo5d(V+>9bAp)30OLJ8|^$M%9xAvp?(Ieue@0)<;!nq@U1Y_R=kMm_<6CKfa(d_X;t7*DFHhyWEe*sMoDsKerKJ`EB(~BmM ze!+x#GN!lv2E#?<6R{lWjzy8~7}@%1dPB^o;CmQE6@lHKFfN8gcC{16f5F6hvS|K@ z-uG`9vMIp3#+at><5WZbSRvKG8~YmYuKCC(PxssRu*GfMwltyiCnNfipU8JHWORW* zB7tV#7x-#y<%w)U{vGmv$FOwOxZ~0y`zI5|f1#9mGEJW|9)_>_^w$_TR_T4ymN>%N zzKem$VdCgtl3Gv3{7?Q7hBH*)Sgk+eWAmjy2(CbL!~5^f56q4eNB`2ada}gb5kH+@ z!hqQU_8|YGF@2g{&Hy;anIBjVKAy1lBYL8qOtTyO48vtAEQzcHJ~i7BJHnW8iPI`$ z#GddS46IHQN590Wdh+t}&vu7#Ff2=}gViSPG#dow+r+zE<8K%^N^XFLpRqp!nO0}D{qGN$=vVRn?SF|f<%0Y0pjX3M~QwZ4a8vFoD= zqkrX@dNQWt{vHOE6BRU{FMYFJG`;^f7*Jc{jjTgH&Le(cn4k0aFf4YPIR39bS5L-O+t3Dm^gZmo8 zvb$vP@;*rOiNow3UofayIDpuZ3J^$Z8L>sBAY0Tp7`PLOz@3id5Wk6|U+H2!8M9lB z#UN8gruo}_jltCB0Eng3g3yT;SmBWY3Yz91ZW#gmQIEdCz;mnzcu!GjIsp#jr)_$9-8( za|BEr{i>Ji$(Rq~_b?ddK8C0WkH29s@D2wx-z3;>Y5Vs+t)dHjM_&NnaU?ULIqqv& zgY)pj(XV!`o{ZVt#>24h!p(0meBB=~Ti};*Nf7l3A>@nvWi9#z16T0G(XWwPPsV&S ze}qA+unFu=WP(d{Bsc^GfsLO(>~!-5Lq|{0ws8fu-A=IDH3gPlMRW9+bsUBPA2M`*zg!jM+*s+cS3V-Me>CSy>6CrKRxV#S3`$>>2GiH#Zk9U%m{OAM=?r zXJ~d{KR-WkadCl&hzQuddp86h4up`95C{zlg^8gahpR*MWAtLS>Myo)>=?6IWAtNx zt*x!2^ke?lH*emA>({T-=s$h>G-PIG(&+d1_Xo7oB^*6^6ws!JV7Gf0gd+?SN&l0! z?qQ5ZDwRsZfcc9zHa7l^e$0;?<9%&yEff_M(fr51(4Uc!LGuMjOiYBNq$Eg5Ng1X8 zz)o|Bb9ID>!=V$_e#DfWKdj#F0&;rpu*Sd>wpj&(=H4J$T5swLt90E#cDoy_)OH1B zBX3w|>H0l&uOZ_Z;p5Yo>7=KO#3kN@^C-u%b^k^V9n z?T1Cux_5;|J}A4?(fmL#-w~m$*{}fhQAvYrSnuBW)%hG0N4p!AYMp?MJ}*bl3vRsx zOvt~3U-by69eO=_9xID^nIq=g@p1eX@b9khD7cciobyMykQ;>@^@b8 z2%+dlrwgo7XuQ-r``3B&9D{&9!e$PV`dNQJFKC2(nvDAX9hKuht?E|wL0Byq z1lAt{{&l{WgemehBLa{ioNYsWl1~W@L zH;+%jzq_L5-x98Sq_a;u@?D>1P;0MRz?%;ny$Rha9xpoAI5xbKvwhYkV^!0#Z0CbF zV#bvOVg2%^Ur9@JiU@q0GFv&7V%oUYM7aDrD*t=>|0D-6c?^X$;YNR7;czpt{C~d_ z!-p~a#{9IDQ1V4-)K3eYxQliVz|wzz|8d}d!2xdb%Zi-l*Yr6}zmts6xvvr%I%d=V zPSQo^#wP7+`YdD9R&?&G#JcUW;{O7}@0P*oUeU>$F%oY$>UWlobXBQe`JN>q-!m-! z@QeRhEC3dV_{9f}H3G#Wh9N(+P?UlJ`JxR27MD2ci{^{@qoKIO&;Do(9>^EX4Pd@2 zO3vumprYe<>HoLS@tz`$=%@czJow^^7l`oxDi0h<6Q&pW8GrcC3MgQ@x%OG9(YY6{_J5|?A$-*!O@XeaE>VChl<66{~I27Paggymk@sBTZP4X z|0)l-68lGDeq)diE9S@gZ+YNDnY8hL>E+>3TjQ_r;4dH8uKyhmCKLbFVPtRp9Pj^= zcEFSRi5Bbpmv7GhhzGtyllK0FuOa-`k>Bl4c);yd3>@mtz`n*D*cH&8I>^_GUCt0C zedNQp1L?PPfnC`W*mpz$yYKUVHXis*p8O}AJ3QjE`vV^Ec;2M#zwno@-;|#OkN5NbZ9khA{3j8A-Y{*iOq$Q{I6PoqZ8YM)jO{rv z>hJgy9`J|&`}Uw;YX|;=lh*!4ZX*0Qzw&z?%Y$43qU{~G$eI5uQf9A*!KjuMD|D@p;yM^!< zA;0Zk;lU4NB(B}5X$KO>?^;^V5yTa=XnP@zl@CUFAZLWIzx~RWe;ghl zIdP);_s_~*RWVH4Yw1^bAer?J*4iAV?E@vZaR)69V_Y6cX#oCkHQ?jXzO#ReXZQ{e zCK12<{b984?8tsoKjMMxnHQk_*;jg#w#koqfMNG6La`hp`$GMc2Wao&pS`Dvx~}wa zm=-hfBOa`{-VNrq4z&HR^h|cr{Kd!Rfub4k1Xg~I1;OzD0uQ1-Od9@mkA`9Gqmj6g z@pzycdzKbIvdh})hddBA4gkK`=fIcL_Ejv&Pk4alMXsdDTmP#*9;WRz_9GrR`g((d zlkK=XP}*(@V!ogEL_={X*uH4L#DlnQWM@P3XUgR1|297zhK(rh2HWfGdpuZiXApdR zooIWXeUAsKR^G5QsU8H$jhX;wBD4vH* z+pCUdb4{B({M+h>LGyFm&v-ltI1>C_9w>)rgV3KS*5qUhtPH*mUyq5)RSjUNWejaR z;7$6A2Rvw>KHd!S-)*kPCl9|)!!T{Hy&v&l|JiF05$66454InQgQXeGG#;!9zVh99 zK~!VkXglCZc?ae;rp-jjH$N-a^z|?pe~#Pw84uKNw}Vew@;~B%qMkJ@$sYW%jpg*@;kRfWrtLNP zt31GDq>V-IKqu!u=w}wg_CJeY+wnrsNG*WP$u~h2?E$GAn+Hl!*Fioq55&)n?2q|F z`vUU8_}P1!sOy%k!?3e$WWUXS!UJp{&L6E8eyUIWT9<}=FeVD$&&suWJ4}l?n^Ybk zAB>;TIZ@a5cMOB|=eWB`;{o!)m?(TdE7$J*FdRVpyiO_)kPpVs=$xqQFZ%|d`6K!! zNzX?hboIdV_dRfb0HCTLpt293{1f`^?1lR;o1v=VC6qmDggZ6QAg}f%oNIUor=B#! zvHMLBUs4MxH%sBcPH`oZa79GC<)fwABg6a`)( z(QqjA2pkTJnKb-Zyd4&6*U`~IiyQnBJ4kayM*pz*$5*djL4SWg)YR0B#z114*8=n%NMxq*|D6GTTx)As50_VR@A@NimO z|lw$Zz4Gq9+-(H9c@Po;I{}?Xp590yW-m(7B z)YSA{{3H^I7Eg=4cZ?5(g@xb6pO%(Ji$}%YIkrbNmd4`uwAlm69!`)D6fkM+Uk>dt zy>Vv%Y_SQWrERv6VC{bltPZ8XUcVIdt*2x#af^pd)?u&_CDpy5u--Bl)Y1L=2cuz! zLlj#3gu}Ldp|BQxqjH6wCoI!(2T2s?D!$DHC?E{PweQvAUTg z?Lk<-j20{S4Q(i%mr-~(x?WC;L;K!!Y_D$N9c93b;@ZA{ydwsI; zvn)q(hX@}Q|NK4rnZ#{r*Rhzr?_FQGbSLflVi~{hUZ>~VLA%Z&AO79z|KXq9_W$4e z|F8Z3|F!?mL*qZ+`Z&-CYyn}NYapP0b~JITVBb1aN4}ljwCiH}H%G5w_wlHv!aVM+ zC}!Lm)Y0=&rp14|&bR3}%;(cVan}Z*=Kltk?=1b>b^gt#P`oz!&ch_mfAhFCKyYI; z=*7GTDYG&VHMldHgtq3uJiG>Qu5yPRvF~B|?#j_?*nLa3=fZs6?Fj#F+ViqD)qlG# ztaAev2p9nax<@DK9mv}~`TKRf0yMXx?`TXSevTD?eYfL#bKC!kbMtw&Pn!Ir6G4EL z#wS5iHxb0O6F^MsD2QkxyM{(AEK!RA!A;R}`#4(nrvb?*`rIPSB2c2b#fc zuqB`w?G5o7)_XL;TIWVU-{64N`)gsP)f153{Rkw@AAqP~B~7lu#?F6|mg?L=`>x~w z_xe=iM~=R+EEk+VQTTqP+>P!p#n*eimRslbYL$|6qwG4@H!C){zLr+DYh0#eS1YMt zTQ9D(_nD}i%_9+6>jz7hTU7~3npF#k8C3E9P7={6tT(FR2kv_M<50U8uZ|7we(%^xYyB1O`oL7KP);wCbhv`t&bjuWf4 z!&-hxsQ=&B9=z9 zNaL8Yl@2^D7FzpSi}+eww$f-V+E>~S0ui(hT+iRm|4|8Q+1Ga9E2rXnjvI*WiFRBc z%d1;Qp8Ub7SGMzd)?A;d6CeBIkM5nCNWPF7&FmE|1c63$_|aM*&}gj@EoiOLLCdjd zJ2a8TacN1fk)U}@v^3KP;Rj?}{!fii@iaAGQ}uKs98mRzsviKnv?Dq8@RR@fT7FwD z=qgzzP6{xQO?)?<9o@U_Csqn&87=r$sp9K{SL)0EWa|9J3?P%u+-2(A@xdRe_LpEWLn7RgI25{&{C;93#FPl1jEL0CP zua{hQjV6p0O2(>yXMS|j)Tv{q#hP!-0F0FYbA|Fs_`SF9;+H=3Hr%?)k;60iL9lK* zE%566GS8h`TG_X6YK-6e_&e{$@a>F3KH|210x;J^)&95}cifZGq=hF&VJ z`v2O=zg779k;{PDMyatXp!E*bTAtW?b>pWOpyp|6EssrUxw;Z|H<4aMSgbYuK}$=O zmCNy}^=qaFSg3j{;Y!UVX!w`BYWSXaEDQp#coIh6XU;8XCZWYiIxiu2>jAtM7aR59+4UcjH#qEs47F-(8(Z z;x^}KeZ|56&X>Xg7!f#M+}vPHyYv8OyGVbbXZ6Zz4)m$#S*GSo3H)K;JEXC=iYmWxD)AUG!9T|t2h1!ZSbfU4O z&5hXzcO`88ZAT-jfif9g?cHES6ysrj7eibNf0g?(HcRK7~2U}GTfHNf)X7x;tDzl z2>d#g{OLxVMjp{36=~*ar*b%B(~SixjRhwnE8#$gZGy^`vv`#fS_`(5z_OFrDv4z$ zC|4ck7ZvIB2+V$COYir3GFAnMY+U}kuFLZBGRb6;d_Lc}`FiEMHN0of9;T+IR;3Su z0MGMQK4;IKC7aDMH#bMUUSE~IHBSg9mUy0r@B6F1qp(s6%d+r&pOKM~w$~JWzxLW| z&Hy~mV_~5= zV;3Ns%`!bb-Em$b!nt$jSYB@4;K&GU+wM5OL?XfH=;*3_#bS}ArKNRJtS`%g(bN?z z)}Q{i9g39!w1Xcho6WLw=gv*%B_hnu&bEC*ZQEvgdb%Scux*=kI^Fiz;^HEUi;J7i z%d!+Za&;WbyLRL)R%{Hw_k9)@7u&**l*{GVwQJWk^AZtGojOIaxc>Zp+qRjUoZOTV zSe8X9)xMz`X<=c3LZNWYylmUzx}6CUPCT4Nu`mGN_gPw6+7N!ETrS7%-MiO4E+Wj# z%xtPywk(TWE{A2Ue;briBoc{h<^^!&$`!6$xw7tY+qSv!`bm<>__&IV8-VZo6pO`8 z!H+aPKF*#!d)Dk15l){z-BF!v+cslkW9u40r)`D#`FZmBwM+dS$L6;EH<3wi&X~4K zMhzec0+yGTJAxl+Vq${puDfn!yBqkCEX!hKWCYc+LPJDWZFi!%xjE+M=2o_C+vcvj z?qX!5eH+50j5&gWAfQ|>cLhJv#KZ(5LJ$PZ&dzRF=U+>fWs%8bs8*{h{rFyV>Cz>F zAi%OL?!5C(GMP-zd2WS_8Gx?*I~mJCRKugE1CY?mhX^7Pc99BKXdGya`$pj~-lPaM ze~g66Ffkr^2Q@kfny-jyY-cOq#lmel*7#OFVhcLy<2epRcLzbD;m~P)&5Sf(S(8i^ z$xJP@yt=00{0W+IL|$ddo1(5SB04}>4q&0Mu#^MJLMa3nJV@*fuRN8y|hu z_NwEJuwK2LZhTh7ZI_RG)plz>Xs|RW&EB+xZsq8Sjl$6b9ECR(Cm$Z%ApS$W4<8GKw8~AJD(kJ+hgPVzONaofCMn(D%elu)91`R+rZpIM)U>m>?J{YtB zvu%JO{APSZGFJj<0o4ZhAi^I=188jn3_AS5>;>qS8#IJ(N`?(UZ8`kQs&pT-?Jmv-fbZINk!$Zvghgw~Gf2mu+B$F5EyNfeJ4pP>ndC0}vgBHN|C% zZ_a1Ayb$o~50yekZm%VUA;qT(=o9>!>+safyE%GgZxi|&_^nTQGfumGdQ}PGx0D<{ z|9w2oM-MEqXNL-3_10@OVL0D-gl6bm}N zY50x`m>SgpEA@Zfg+j?^a?IX*?_e;ifZm^cM00H629~O+O~X&%^6<^a*T4@qgH6NN zLBL}NYNVVde1$?G)a$TV3TFm2^N$~VFkS-C6MRHCn%~<|oj;jbCZ&Qk@DWx!el~zV zHRAF3J$3HAS+9XF5-zx`*ELHh#z(C6dj|vU2)f!2&;@)%b7EmZ9f zQ-QrM{OJ*wNA9li_FH^xwf4!6;3I-kg6j%J5po%8ZSP>{2)e2b&;@+gw+89iVxY)H)j{Kwrs0F}5`dmY^}@~0`}sxJ;wvxQ%rD+^hF#fO zOGzNyK3(JXhiX^V&)vgUA}9gR6H4WP?1+mICGspbz8uY1_rY?b^dvtqWiO$rN9Gev0Lq zbxruK;ZEU)=@hP~DObbvac~3~UKh|kd?dW-w~o*E?B0F(T#`RKw1Xq(8w)qrfxljB zf3xtTYxaDhT-AtP9mj-XU;y305A%RGPhIYdZ@*X;{`Lo>eC^pZRhKP;AI6u^2x{RH zxB)H!dV`M$@4W6jX}j8&fgK5aessd(3r{8a>3Owf@T2aaA80By2}=S)ikB<6i#dGh zM8F4co$U+!XkTGD;7i|yZ~jn+lb5#uew2qF2vygd1;n5V=pKH!EqrkQId0pr&=>g8 zJVEXI9C|U}&;P|`xw9Za$ZmHqwRlqPE)S;5B>l*0=Eu+ zYkbFo2k!9ri%(Vg%wsOQa^1rhV6h@R^F(mUJnwe|Ux4d#;Hci$^WaTg&!Vm4(uGB33&0O$KCsEo_HX^ zTW_}3&0lNy=jVOC^gX|0_yRn*zd!IzdIHTZ4n?gCXEX4ZYw+B$_M>_)&j$SN-v=Dn zXY;8C91h+T)^>g%%v{v`-&x^XFZi4C??n`F^K6@r$dQ4Gqg;K2@=+5Ay;J4o0yyjluDNlYy@1wm2k;R{IdJf1bxruI0QLy~kvGAo-$CEt zn{ETd%MsK8{3!k>-k%6xGy+=={}cDX=O1az_|RSO zi35;I(AQ$W6~4(|6gBS%>Jfev|M7cm?!V3Ae~5;r`ZF_0gJL>wXD4VzyFD zj0ihN;NV`xzRA_suvPE}v;=7U=>z;I&Qw5 z{3x7BhWP4UYnu4LAJ8_y_P~$wOeY{^Tf`E+!Ct@{dn};Cc0@WMq@3;V=R-WIyCoF|y zi5d8VX#nwoAB7VZIF1;AZ_WbZI~K6b@T2sOQY0+47rwy~ARaSwB_rL29+)_RLArA>r(aj)Lj?pK{QJjYcR+2;CeCB7^A+aLZ`;pug98fvJa kh8k+9p@tf2sIAfe16Om4l7&%U(*OVf07*qoM6N<$g6ECEtpET3 literal 0 HcmV?d00001 diff --git a/games/NXDoom/data/wadfile.png b/games/NXDoom/data/wadfile.png new file mode 100644 index 0000000000000000000000000000000000000000..a5888438812c0b270fb26bf1ed949b896b37ba8e GIT binary patch literal 8681 zcmZu%cQoA3*Z$aL5xo-xLDcA?vuYyId$+Pml<3jR5;X`SqD4#8=q*~XLZY`Qs|2gF zI>G8c-}mo#&XjZJ%$b>c=FT(sK6heuw4RdOyMGS=021|QDtdP<;=e)wxvRV6Z3gZd zLicB;UI4&l^+EAN^7Ci^7_8m) zZZUuLE$@QpsS?{VOoGS<&p>{Up}~kaJa$uYEt(gD z+<%QM>$W|f&-}au1VDZd;uW4Mh5mU#c7yE+y}C(rGW300A`bD}IZnJ`626f^GViOH z!x~ME&ExgoicTv`!@rD(EEz9eQte-F&ln5lnAspk-hm1f{{f@Z|tB9iP3%rh9m@k|H^*jUrqBA{HF z$+1i*pGq5FUpoJs$k#6+A&mYP$7l1ti{mv*O}b(dVA<1dxLc9ztu#U_bhJm#cQI~k zHh@So&@PD_WSYY^B5G?I#Xo}NPkO{$;P{R|YZ)_aXwh`QloPye%EZLfl(rB0x0D-n z7K&XIG``%hM=aj_{n{~%zQqL;j+Afra%r%c5#%3mm>%^W6AwbG=9H^Y%Af3}=N5mR zZ;Y(WIowiQUOr$CVq4k^-uE8~^l|l`+du)ifvYSye_PsuL1zocZvlYKb7yxy%(PcY zHQ|A70|j2?O-(LiX$ts6(_Ir`UT3sOJ+U*Jez2et5z#BEY;&2xz>n+6#;QVU51}Xx zhl*pBt;YU{I{kVAL?Trntgq!t$#vf1Pn1%7;O%A`eAjaZ>7YdWM*%<_`o(Xz zqTDegZYm!*Sb@fzb{gkx_Mq*o#cnK&7;x)junxv9Y0n2P1}mI!xRP^vp^%$z!?cQ> z>mmRo(3hV{A}{rHl~}q|;RQ8^NpaT-+F}gnBNs=~chHm6W)=wrqu*6vR&vf~AE=?> zV!P;zg*TrAG5i5-@{qS|QC)T}uU(cZ+=3a6o;t&37E(TQgdS}@RR}iDZzlS3&Hzxn z(R$7q<&;g7X+`pRh+`coR3rM`MbWMT^IA^pvDP~=K{KP5_|lWyv{Dh|Xbb2n!;x%s zuUB=iX2NPZ*-Ia^8e4^eqtY{OMWu)`LCem`GQls4jIdD_m}65!>Ke`8o1(dzwzi6_ zAF0*Ym1vfb%?E#h%q$#9EJUn#mF}gWjh0YkPY8t%6pqJcDli&k^9N#J`331Al&M~= zquK7BZgr@N-)VDkG6&&Ba35~h z5+&p%{z5cK)|ECJ8avU%E$^ZZ^B zK9VI1aPF{p{>)L}B>1F|4?wsU$5}NdhG=JkLGA;L3y2ghZH%-;%&&d9s{<}=8t2#1 zX6bm;m*ov|G^-D2ZM7%)O4*H5lI(C&B_K zSdBYwWHE5i4|JP^As?+ZJsxs5C!>c-#&caJYl`H}DgIH{?3tP7DD-?*#G?+4y~?rI z7iGG(VljQ9I<*a#H2Hbc`M|Y#?Ic}`%Wvt32ym|hu5aLp*XtbtsMfuXpjS!HOT<|a zAji{Gd1V=QjaAE%NfD1%YSROATtD4T)UZw>-82RA*uSJ$exMVnMJg-785I0^+1Do! zyGaBNvT2OYE*-ZiofXQ^5Xz2c7A4OWfsU# zK8#Z+O`Y9@mGa}}9+ps9Ib4<0iA*x`v7lj7ke9~pfUH1C$PoYczbpjQppciKNBk*L%9KO6*;n=ZU}D=uB!4z4nD^%LS2V0_gx!yiaH;yp$xYEKZ%}4M)7p-xR*y?PHk3kem7diis+iRX zej5md?3=w?Y|ec7t*ES}V%#xm%X@hczhb--CQg)87j}2T*KdO@nlBy-Sl$Q-Shh#Z z&s$c*I6fk{RWp6=aQAP>W!9Lw%xwOJTkiQF*T`U)QP}J;jx3Q*JPvh#%9}x@9_?0; zncxn4=f^EOyv2(BsxwO4FK=1QbHnM$`Llm-*@la$Cl!<~f!A4GR3eIVuAkKI+osz) z?ZTv0KW+5Z61Q2AZGU~^l0B_9t1isc&$Fx$v~3Q{1OIfB$D-fv`yF)R?;6;W-pR^s z47PDx{2tg6R#;js-e-}*>&rd1Wf#OKG`2eB|rgWT0K(Y*24j0gRt z@bK%lVA<=zaqL{jd1%vjFOqDrUu9NrK#W<8W-~ed*QKZ*+vGZ`rE)B+?-b_9WW4s3 zq@=824)Xg}x#5SOf`V+3DAdi8;m<-IfPlQOop4w!+Gvt55lZuMydz{oKJ@M4~9B!0})}V zsdk@#Y!$ekm7?U{948JZFq>Hr9asS2AJ!l0`CmR5b1)52AHRLGzsiYq~aNP@}cptl@yRJpd$pUkcHCn9s@nat!H zHo>?V!b1QO-;%^uWtZ`UkiNAB^7}Hy(#1W51Bu#l+xcL4{%zO)lm7s&V`kpmZr#wj`QU9xbOJ*PBMb{K)`CWfF zgwj?&3{jU{8PqSmS_-kQLzzAh@2b5(V=YNQRB!d1B z0wg=lTZNQ$2Lu7O{049^+W{Upq|qO=fC4FS=)(@BZT-Sz1ZA-Nh&cG91e+r2dZdoY zvDoxLK%J5}TKO)2mSn@bDopcn7s`Rj?V=62TtNqKOlg}K1!cf_8hrx>hO$uW3Oj4- zZHNi%GfyB_m)TPwNC?hPzw&uZ+n}53?yB2+_o6_BUw;=m2;Hx+acqhg(-dYR6{aV4 zcXtPHZsPnuxYZk~0XN zC`|i`xV`=Cgm}|&NK3kd*GRcATK5xMUWyMCFhWgLhq?oZ_Tpto!yPQL3T&;lDCSCx zszJ%BCJ6grLr4ev@*>c_1+9HXnrR8oXJjf3dTb!#cx4^^mLZ_-UW#Rb5mh>63M!r; zLM(ONR)~J{`P1X6IVGmNdwvr49v!zStO1$WL^^__s>d4qN&u!LxbUdLH>U*tQ!VA5*D9DD{N{+NHm?ip)E<88v1BW74YMcro zr+vhF;b{a&^`& z)11^BP)ttW@FA4`biREV368q{B%Qat>(Po%+iArY4hU=dD2Ch!4l0hDpM4e+W=wh0 z)W*r|&%E*rUQpX+?q*>kvM;$3HqJerS;9=YFWr1^pI0C*(1{#av_(UP;xpts(^!Wr z#B|B8r>c5io}@A{Q0Xk7vA8j9l<)h`v~j=X4y7G7F+>v`Ns_*!HL_oE!emW+3UVhc z!Ou_PCPACkn_}^mRgw+-R3_f-ljf!BxF3*|nOWAt$|#Bb$|CXfOU68k!pkSig`8SF zBDCl1zHbv0;b7Y9IzzR>1wEsA)D0`727Ey;IG-5!rmlU?cT~r#KXflSUZgxP4z8x~ z*sG^|{Z2Q6ZRay1PVWg4g<+A$W^$!>Hm4KbL`ysXB93bbB+w3G)PYJm6$JewYR-A5 zl6k)xfa221Co!j*FJb~2&f|A;48Rqfn)Et4EJ60}u2<@TWbojL_FG)hPA(%fpLKT~ z%xWk1eikChsgi>!la>;{`jAQHPdmsR`F7xZBIP*C-%F6g zPY1ru-X2*}z8_R)4|EY&{TP46=zQ_Kr|L*7tsqP4li|eOiOS%3W~xTMRGrHcnIWa6 ztMr_ZEuXl21c-K~SxJ}H{;VHKKr?VvlVYth!wkx9E(}m&1UAmQKCMqj@CjO9;*gp3 z2aLuI>)LF3k80z&^DECNRy{uF)g~?Ya}r?I2RsWrpvG6IKF^0#lYM<8MC`mgUl--} zB=d%!RlZA_`0;u(fXYnUY!az%+XA}OH=E@67{{4{s_)AVfiEB&+nl{EvIi(m?C%+P zw>YB3N?Vj_A`9#Z257%YCS*OZAYYI*EOl~gGK1<4?Jpymg zx``0EL4XxjLj;@6T!0qF;*&pj@*4yQ(LL_Q&m;HyTGQL{yX?^u=q%v`kt=Q~EV7Ycc1&HJ?#|=9Qp||>PWhLf1hqdX~^r1bYsS!4;V$qj6 zI){jEVH}{Wr~MljPR{liveJvq!|%@UaF^-2n5F>EA_Y|6WgiB=8-1Fj+x7^}$HICz zxAdFNmOhDh{lY`7`jBvv&I>F@$Gv4tGPv7xvA%z|d?c-*nxf@N6-Ut#ZP?e}n2-dd z@fLJ#?)!8Jn!ic`LyUnY$-pzl&YX_Ksc9xK$;UV@M9KpjB=vfAs~=BFyICc38rq## z=3Bo#&N;?Ee{O7F`W?pvX-SxCbMJ3)n4L@?lQFT`jLnwh$20||2CM}j<4>#&l<+>Z zB5jg$??N7BD!-n80^QmwoWkYRPAwJRC!<$1T63o2jZyM%>}t?fPIft)k3H54^Z*h| zz7q;br59y7?xa4CM+tRCR99r>@-R5X&dwCP znBrpzeH8nWD7~U6C*xCSh$OBMP>0d24j}$RdS@6#Pz&R%#rBuQ5@;CRIdc+#bx9<1 zn^mF^>nhl~6vHlxt51lxp0_YcEfOa>X_=vyh2!kk&+VF^;^=mfvBt!z&rUN*MRUT*k-PcWo%3~;FeYyj9479nRX@L}r zF(AB|-`+S3OI@}nt#A$I(L}<$Yl%!cuF4WX&_}Pm8;@O}8S-RL`V7>4U4oi-y4hX{ zdjJkXFN=2+nWEL00 zRxq8pcIb4tb;IFT4RF(IgIU#9pSpZ_M_LULw?;cC2v`ISihxyR=sv-xB-q`k)ClBN zT>GN}&l;?YG@)FrF%`uM9Gz7)hhGQzdlxBm@V~MAlF0o;@@e1`TjX}0oqzP#$RF&z zW{CTFmkfs@E@ApbEKu~p>$`n?dLWeOtjcLveex$ZNlTFaVB7VI+YT2X{4A$YzW9(y zx?U6=Hyx*w$P~;19SMtT9zNeRjQr@Vx%zo-3{u(H@ejxgji@out1#0lqN_fch)#N+ zTeY#HS`?ZC86_qhf~_eV*-=aWRU@m1_{7uF<0lzd&l0H#G?83_dq}YZ_pUOWu}7J< z0XXIx50XA8y!gqiR>DtY!X;iaJ{0f>xf@`sMGk)_ojRF!ssYsyaqgt1_GeMUE8zX`{W zT{-2oJ?*+@)PF;ka#Vc}+iNPfp^YBI#o!q96BrI#&DU;GR?gql_5Z4Fvkwo*hl~Gu z$yt~F@cWC4>WLgOoxCQLHC~Y2U_8*UqDNY7mTCFX0A+()BwzVsEtHk9{YjEHBzvJZCN!WxY_F8m~4Unqdy*QHABK`zu=F+4yPuD3OJxg~onSI}Vp3$z!#%pa2 ziM@lYq9PYU&dt-$i+C}Y-3W7-!+3%W4fjRGyeGN$!uopDxj(&E`yh)E z(<+%Y4D@pSEAtiI3Rp+oZJ?l?DPZO}VpW<{**SdXgS4@U1VlcdsR)Uhf9VqvZnfs> zS_$`e?CX1M=j;~L+eiAOOf|ajv6%}~-g6A!M4Rk>E?kaef>e#9)TcAsp+Q@R47G=~ z(|EEcrpPl+U6`GY_oVSjb!`i!Plu40$M0%l3Wq56`vkm^x1(tNPM%t1*G{W4k)CA_ zwa|&j?)zIiqy#DVPEc+}O>^^B7z-m2*#$^ng+6@Q&dx~Y2~2Sus-9pNQp%ENwYTF+ zn5F-1dyrfVJG0KP6;gX{LtlIwUon*6dC>MJ-_d*6-6UrxS+q<9?|nR(j?xga_=A5f zGw$UPo(YZYi=P|mY(f`JJ{vtruUi)6O`{Fiba>8z`W3U@(+m7WwwM?F{0Os`KrZK3 z%}SsHBc*t|^Z}}2M!Fq<&aFYW`YgV=Q2R<@#C-5oiD8>5t=WIpbwN_?RVO~|#8NRD z=%B~_=qnPg_oe+moqBz9BFds%87`}KTI5uQ}g_@ znipjn_&$il8z4)huyT|K5Ke9#IM_c6bm5BJa19DImGGc_+E|=wQue`kictWyc*EEG zWMAj(<;sSzd4>gJMcT8F@?Y&SwJ3=p;$*sKlJPo{jlh5Gi%u#=u(WLF8fR65!bC1u zzYxRtn1Tyzcf6mZ*F)UaJYK#}RV{trMl6%0J^$y5^=w3wWmYFan5jE&s2vtaFbplo zqgE038*VdkzXo(>h}pK_XM;USZrNdFVPaITU{h+&q*z1DwC*n6h}Id`PlETK4h=#H zsjA^x>xIAWW+>>;IJuncrAN$?iWS#6{GaTNS)Cs{S=QWZARV!*`bm1Qz-49|T(1QY z%XmUsMWR?Rpjptt3#{tt(Z|f%%!g4iA@1;ARJ&a9(5jAlhr>lG2H3kq1Oa7iG*K6y|Fc9~|#?TN7gqsoxm!y<`NXtf8agXDbdiAh?4T`^|q{4rnpt zv}&=L=sIbs6*Kt z5KF|^E5oq;`ll@n{ciNI<<{!F5hdzTKtRM_9q*25}glry{lDf#o4Q!j~<2=2I)cMQMjQV z_34s88u!_3#`Ae)h`n?+Y0>zgOYbP`z4ju0%|GdXw@Zys83!B;+gv*lzMDUAe&p<; z`N#)2oCcH%70q{FwgP%^uOMTHHUi;QngoSYZsjt7Z9TncD(?P6iN*?Nsh|`N3 zP!|#zz5={<46~|=*81>}u2~jt7{<#EQk-(zsR#2;1ce5R{p`nhsw`Wo5om1&VB8g{ zt4gAED<}Z6E7h7#S$QZZF)SkVyFsA`k3QY;E|R~B-+W_85@TCn8R$Pq>5^e|A1XYE z!Q3|*v?sMIXU^Kqau-;ou6>!Cm*;cuYq4fVlJGRK+CL;JI@hy){ z8daDti|H#hCvh{>1?cT#0Xd-g*il830Wl%Y%nd0SKQ5VffYA9s3`IMSF!!Lyy*&X9 zena7mg}Ra7G{!U>5ho-kO`n$NkDQ`-hC=LZ39CQxzTZB7x83~8m3J5)Px{-Nist>@@JqSY98azgU&!jk0`YAOjo zcy#Hxfs^i<-O`cI4kn2!ZX$97fPx>D3;=fMr&WoWM^ov*CdtJ#(?8(_1>}ui{2hNS zn>H)Bb;tR8*VK!3!$wgt>`5NuJh=>m9exVyg)ztanfkeBVi0>v{a~kzw=Kj;CE5fx zd8fR{{B*$mYz;3pUx6u4fk}ndl7IRMs8=gP#Gb%wK856}{9WnXplBiG{sn~T0&r!E zB8(e?6qAC<`N2)O4-lNRvTR=#{6uQ#lCG0C9=g(KAg1d;le0(?`iv>ahDNKCi1PHg z-tTn9N#kzSAA{UYFGlfKz;|>k2u48E!dC(kuZL1mDn)4wc0V0cQL}U0g~@JEc&lo z+?V_bm1Uxt-a`>Yg5%>Ry77;B!9f;P6f<(Un*(`9vbR+}y@~IB$L&U2cy9 zODHjb9GpSj{ByqR9+v*Bl%${V{$fw*TejVa>BWeG*KMG7w){2A3Ete?oa9N=_~soL zJzi4G=$MT87gf1VZC=_mX0Y)-McS~-M1nzEi8tuPkgeOBT)_}RS}fS4`h-h)ND^u} zZ%RY(oUNe~_#^h}ac7b!-jG;4do9iy4OD6;eM>5s6!t|PzG40%h}0Tff1lvx$7s4Y z;GTmaTmv&vr0^t{PrK-JZ%)~QxPBAmqMvRFkI=7QtPXbM?Xl#Yhr;6Qr0qD2^Ii=~ zSjT#LZ+h5|H5eA%Lyu0MWgh~}*t_ZTDTdfHT&H!x`w;f^ire&{W%Nq8HQye~*C)U| z2Yhw+z4Y~BUeP;(=w2QiJy*=gQYc+?d%KkjtTb%$i-(W4-~GS<)K#@qDwSa2{{x5e Bj!^&r literal 0 HcmV?d00001 diff --git a/games/NXDoom/man/.gitignore b/games/NXDoom/man/.gitignore new file mode 100644 index 00000000000..d974b54eb01 --- /dev/null +++ b/games/NXDoom/man/.gitignore @@ -0,0 +1,16 @@ +CMDLINE.doom +CMDLINE.doom.md +CMDLINE.heretic +CMDLINE.heretic.md +CMDLINE.hexen +CMDLINE.hexen.md +CMDLINE.strife +CMDLINE.strife.md +INSTALL.doom +INSTALL.heretic +INSTALL.hexen +INSTALL.strife +Makefile.in +Makefile +*.6 +*.5 diff --git a/games/NXDoom/man/CMDLINE.template b/games/NXDoom/man/CMDLINE.template new file mode 100644 index 00000000000..2c59938366a --- /dev/null +++ b/games/NXDoom/man/CMDLINE.template @@ -0,0 +1,8 @@ +== Command line parameters == + +This is a full list of the supported command line parameters. A number of +additional parameters are supported in addition to those present in the DOS +version. + +@content + diff --git a/games/NXDoom/man/CMDLINE.template.md b/games/NXDoom/man/CMDLINE.template.md new file mode 100644 index 00000000000..b7c800a7023 --- /dev/null +++ b/games/NXDoom/man/CMDLINE.template.md @@ -0,0 +1,8 @@ +# Command line parameters + +This is a full list of the supported command line parameters. A number of +additional parameters are supported in addition to those present in the DOS +version. + +@content + diff --git a/games/NXDoom/man/INSTALL.template b/games/NXDoom/man/INSTALL.template new file mode 100644 index 00000000000..c889cbdbef0 --- /dev/null +++ b/games/NXDoom/man/INSTALL.template @@ -0,0 +1,316 @@ +#ifdef DOOM +#define DEFAULT_IWAD doom2.wad +#elif HERETIC +#define DEFAULT_IWAD heretic.wad +#elif HEXEN +#define DEFAULT_IWAD hexen.wad +#elif STRIFE +#define DEFAULT_IWAD strife1.wad +#endif +# LONG_GAME_NAME installation + +These are instructions for how to install and set up LONG_GAME_NAME +for play. + +#if !PRECOMPILED +# Building LONG_GAME_NAME + +Before you can play LONG_GAME_NAME, you need to compile a binary that +you can run. For compilation, LONG_GAME_NAME requires the following +to be installed: + + * A C compiler (gcc is recommended) + * make (GNU make is recommended) + * SDL2 (see https://www.libsdl.org/) + * SDL2_mixer (see https://www.libsdl.org/projects/SDL_mixer/) + * SDL2_net (see https://www.libsdl.org/projects/SDL_net/) + * Python (optional) + +Follow the standard instructions for installing an autotools-based +package: + + 1. Run `./configure` to initialize the package. + 2. Run `make` to compile the package. + 3. Run `make install` to install the package. + +An automated build script is available that installs the necessary +dependencies and builds the source code automatically. See the build +instructions on the website. + +Advanced topics such as cross-compilation are beyond the scope of this +document. Please see the GNU autoconf / automake documentation for more +information. + +#endif +# Obtaining an IWAD file + +To play, you need an IWAD file. This file contains the game data +(graphics, sounds, etc). The full versions of the games are +proprietary and need to be bought. The IWAD file has one of the +following names: + +| IWAD | Game | +| -------------------------- | ------------------------------- | +#if DOOM +| doom1.wad | Shareware Doom | +| doom.wad | Registered / Ultimate Doom | +| doom2.wad | Doom 2 | +| tnt.wad | Final Doom: TNT: Evilution | +| plutonia.wad | Final Doom: Plutonia Experiment | +| chex.wad | Chex Quest | +| freedoom1.wad | Freedoom: Phase 1 | +| freedoom2.wad | Freedoom: Phase 2 | +| freedm.wad | FreeDM | +#endif +#if HERETIC +| heretic1.wad | Shareware Heretic | +| heretic.wad | Registered / Commercial Heretic | +#endif +#if HEXEN +| hexen.wad | Hexen | +#endif +#if STRIFE +| strife1.wad (+voices.wad) | Strife | +#endif + +#if DOOM +If you don’t have a copy of a commercial version, you can download +the shareware version of Doom (extract the file named doom1.wad): + + * https://www.doomworld.com/idgames/idstuff/doom/win95/doom95 + (idstuff/doom/win95/doom95.zip in your nearest /idgames mirror) + +#endif +If you have a commercial version on a CD-ROM, obtaining the IWAD +file is usually straightforward. Simply locate the IWAD file on the +disc and copy it off. + +#if !__MACOSX__ +#if DOOM +The Doom games are available to purchase for download on Steam +(https://store.steampowered.com/), all releases containing the classic +games including Doom 3: BFG Edition are supported. +#endif +#if HERETIC +Heretic is available to purchase for download on Steam +(https://store.steampowered.com/). +#endif +#if HEXEN +Hexen and its expansion pack are available to purchase for download on +Steam (https://store.steampowered.com/). +#endif +#if STRIFE +Strife: Veteran Edition is available to purchase for download on Steam +(https://store.steampowered.com/). +#endif +#if !_WIN32 +For Steam on Linux, you need to enable “Steam Play” for all titles in +order to install the games. You may do this from the Steam menu, +Setup, and the Steam Play tab. +#endif +LONG_GAME_NAME will autodetect IWADs installed by Steam and you do not +need to do anything. +#else +The Doom, Heretic, Hexen, and Strife games are available to purchase +for download on Steam (https://store.steampowered.com/), but are only +available for Windows. To find the IWAD files on a Windows or Wine +system, look in the Steam directory (usually within “Program Files”), +under the “steamapps/common” path. +#endif + +#if DOOM || STRIFE +The Doom and Strife: Veteran Edition games are available for purchase +on GOG.com (https://www.gog.com/). +#if _WIN32 +LONG_GAME_NAME will autodetect IWADs from the standalone or GOG Galaxy +installers and you do not need to do anything. +#else +The games are only available for Windows, but you may find the IWAD +files on a Windows or Wine system, typically within the “C:\GOG Games” +or “C:\Program Files\GOG Galaxy” directories. +#endif + +#endif +#if DOOM || HERETIC +Older floppy disk versions are harder to deal with. The easiest way +to install from floppies is to run the original installer program +inside an emulator such as DOSbox (https://www.dosbox.com/). +As an alternative to using an emulator, it is possible to extract the +files manually. On the install disk(s), you will find several files +with numbered extensions (eg. “doom_se.1”). + +From the command line it is possible to combine these files into a +single large file, using a command similar to the following: + +#if _WIN32 + copy doom_se.1+doom_se.2+doom_se.3+doom_se.4+doom_se.5 doom_se.lzh +#else + cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.lzh +#endif + +The resulting file is an LHA archive file, and it can be extracted +using an LHA archive tool (there is one available for almost every +operating system). + +#endif +# Running the game + +#if __MACOSX__ +Once you have an IWAD file, you can specify its location within the +graphical launcher program. Click the “Configure...” button, and then +click “Set...” for each IWAD to choose its location. From the main +launcher dialog you can then choose which game you want to play and +click the “Launch” button to start the game. + +If you are an advanced user and like to run Doom from the command +line, you can use the “Command Prompt...” menu item to open a Terminal +window. The DOOMWADPATH environment variable is preconfigured +to point to the locations of the IWAD files set within the launcher. +You can launch the game with a specific IWAD file by typing, for +example: + + LONG_EXE_NAME -iwad tnt.wad +#else +LONG_GAME_NAME needs to know where to find your IWAD file. To do this, +do one of the following: + +#if _WIN32 + * Within Explorer, simply place the IWAD file in the same folder as + the LONG_GAME_NAME files, and double-click `LONG_EXE_NAME.exe`. + + * Run LONG_GAME_NAME from the command prompt with the `-iwad` command + line parameter to specify the IWAD file to use, eg. + + LONG_EXE_NAME -iwad c:\games\DEFAULT_IWAD + + * Set the environment variable DOOMWADDIR to the location of a + directory containing your IWAD files. + + * If you have multiple IWADs in different directories, set the + environment variable DOOMWADPATH to be a semicolon-separated list + of directories to search (similar to the PATH environment + variable). +#else + * Run LONG_GAME_NAME from the Unix console with the `-iwad` command + line parameter to specify the IWAD file to use, eg. + + LONG_EXE_NAME -iwad /root/DEFAULT_IWAD + + * Put the file into one of the following directories: + + $HOME/.local/share/games/doom + /usr/share/doom + /usr/share/games/doom + /usr/local/share/doom + /usr/local/share/games/doom + + * Set the environment variable DOOMWADDIR to specify the path to a + directory containing your IWAD files. + + * If you have multiple IWADs in different directories, set the + environment variable DOOMWADPATH to be a colon-separated list of + directories to search (similar to the Unix PATH environment + variable). +#endif +#endif + +#if DOOM +# Playing with Freedoom + +Freedoom is an open content project to create a Doom engine-based game +that is entirely free software. The website can be found here: + + https://freedoom.github.io/ + +Check out the [Chocolate Doom wiki’s page on +Freedoom](https://www.chocolate-doom.org/wiki/index.php/Freedoom) +for more information. + +# Playing with Chex Quest + +Chex Quest is a game based on Doom with some minor modifications that +was distributed with boxes of Chex cereal in 1997. It is possible to +play Chex Quest using LONG_GAME_NAME. To do this, the following files +are needed: + + * The IWAD file “chex.wad”, from the Chex Quest CD. + + * The dehacked patch “chex.deh”, which can be found here: + https://www.doomworld.com/idgames/themes/chex/chexdeh + (themes/chex/chexdeh.zip in your nearest /idgames mirror) + +Copy these files into a directory together and use the `-iwad` command +line parameter to specify the Chex Quest IWAD file: + + LONG_EXE_NAME -iwad chex.wad + +#endif +# Installing upgrades + +#if DOOM +LONG_GAME_NAME requires a version 1.9 IWAD file. Generally, if you +install a recent version of Doom you should have a version 1.9 IWAD. +#elif HERETIC +LONG_GAME_NAME requires a version 1.2 (Shareware) or version 1.3 +(Shadow of the Serpent Riders) IWAD file. Generally, if you install a +recent version of Heretic you should have a version 1.2 or 1.3 IWAD. +#elif HEXEN +LONG_GAME_NAME requires a version 1.1 IWAD file. Generally, if you +install a recent version of Hexen you should have a version 1.1 IWAD. +#elif STRIFE +LONG_GAME_NAME requires a version 1.2 IWAD file. Generally, if you +install a recent version of Strife you should have a version 1.2 IWAD. +Please note that Strife version 1.3 does not update the IWAD, if your +version.txt file says “STRIFE(TM) VERSION 1.3”, you are still good. +#endif +However, if you are installing from a very old CD version or from +floppy disks, you might find you have an older version. + +The most obvious symptom of an out of date IWAD file is that the game +will exit at the title screen before the demo starts, with the message +“Demo is from a different game version!”. If this happens, your IWAD +file is out of date and you need to upgrade. + +Upgrade patches are available that will update your game to the latest +version, the following sites have the patches: + +#if DOOM + * http://www.doom2.net/doom2/utils.html + * http://www.gamers.org/pub/idgames/idstuff/doom + * http://www.gamers.org/pub/idgames/idstuff/doom2 +#elif HERETIC + * http://www.gamers.org/pub/idgames/idstuff/heretic +#elif HEXEN + * http://www.gamers.org/pub/idgames/idstuff/hexen +#elif STRIFE + * http://www.gamers.org/pub/idgames/roguestuff +#endif + +Please see the +[Doom Wiki’s page on game patches](https://doomwiki.org/wiki/Game_patch) +for more information. + +#if _WIN32 +As the patches are binary patches that run as DOS executables, on +recent 64-bit versions of Windows you will need to use a DOS emulator +(such as DOSBox) to run them. +#else +As the patches are binary patches that run as DOS executables, you +will need to use a DOS emulator (such as DOSBox) to run them. +#endif + +# Music support + +LONG_GAME_NAME includes OPL emulation code that accurately reproduces +the way that the in-game music sounded under DOS when using an +Adlib/Soundblaster card. This is, however, not to everyone’s taste. + +LONG_GAME_NAME includes a number of different options for better +quality MIDI playback; see the file README.Music for more details of +how to set these up. + +#if !PRECOMPILED +When compiling from source, be sure to compile and install Timidity +before installing SDL2_mixer. + +#endif diff --git a/games/NXDoom/man/Makefile.am b/games/NXDoom/man/Makefile.am new file mode 100644 index 00000000000..2e1e0474562 --- /dev/null +++ b/games/NXDoom/man/Makefile.am @@ -0,0 +1,226 @@ +SUBDIRS = bash-completion + +MANPAGE_GEN_FILES = environ.man \ + iwad_paths.man \ + doom.template \ + heretic.template \ + hexen.template \ + strife.template \ + docgen \ + default.cfg.template \ + extra.cfg.template \ + server.template \ + setup.template + +doomdocsdir = ${docdir}/../${PROGRAM_PREFIX}doom +hereticdocsdir = ${docdir}/../${PROGRAM_PREFIX}heretic +hexendocsdir = ${docdir}/../${PROGRAM_PREFIX}hexen +strifedocsdir = ${docdir}/../${PROGRAM_PREFIX}strife + +if HAVE_DOC + +GENERATED_MAN_PAGES = \ + @PROGRAM_PREFIX@doom.6 \ + default.cfg.5 \ + @PROGRAM_PREFIX@doom.cfg.5 \ + @PROGRAM_PREFIX@heretic.6 \ + heretic.cfg.5 \ + @PROGRAM_PREFIX@heretic.cfg.5 \ + @PROGRAM_PREFIX@hexen.6 \ + hexen.cfg.5 \ + @PROGRAM_PREFIX@hexen.cfg.5 \ + @PROGRAM_PREFIX@strife.6 \ + strife.cfg.5 \ + @PROGRAM_PREFIX@strife.cfg.5 \ + @PROGRAM_PREFIX@server.6 + +SETUP_MAN_PAGES = \ + @PROGRAM_PREFIX@doom-setup.6 \ + @PROGRAM_PREFIX@heretic-setup.6 \ + @PROGRAM_PREFIX@hexen-setup.6 \ + @PROGRAM_PREFIX@strife-setup.6 + +man_MANS = $(GENERATED_MAN_PAGES) \ + $(SETUP_MAN_PAGES) + +doomdocs_DATA = INSTALL.doom CMDLINE.doom +hereticdocs_DATA = INSTALL.heretic CMDLINE.heretic +hexendocs_DATA = INSTALL.hexen CMDLINE.hexen +strifedocs_DATA = INSTALL.strife CMDLINE.strife + +if HAVE_WINDRES + +WIN32=-D_WIN32 + +doomdocs_DATA += CMDLINE.doom.md +hereticdocs_DATA += CMDLINE.heretic.md +hexendocs_DATA += CMDLINE.hexen.md +strifedocs_DATA += CMDLINE.strife.md + +endif + +CLEANFILES = $(GENERATED_MAN_PAGES) $(SETUP_MAN_PAGES) \ + $(doomdocs_DATA) $(hereticdocs_DATA) \ + $(hexendocs_DATA) $(strifedocs_DATA) +DOCGEN = $(srcdir)/docgen +DOCGEN_COMMON_ARGS = -n "@PROGRAM_SPREFIX@" \ + -s "@PACKAGE_NAME@" \ + -z "@PACKAGE_SHORTNAME@" \ + -v "@VERSION@" + +@PROGRAM_PREFIX@doom.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g doom -m $(srcdir)/doom.template \ + $(top_srcdir)/src $(top_srcdir)/src/doom > $@ + +default.cfg.5: $(top_srcdir)/src $(srcdir)/default.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g doom -m $(srcdir)/default.cfg.template \ + -c default $(top_srcdir)/src/m_config.c > $@ + +@PROGRAM_PREFIX@doom.cfg.5: $(top_srcdir)/src extra.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g doom -m $(srcdir)/extra.cfg.template \ + -c extended $(top_srcdir)/src/m_config.c > $@ + +CMDLINE.doom : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/doom + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -p $(srcdir)/CMDLINE.template \ + $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@ + +CMDLINE.doom.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/doom + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -M $(srcdir)/CMDLINE.template.md \ + $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@ + +CMDLINE.doom.wikitext : $(top_srcdir)/src $(top_srcdir)/src/doom + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -w $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@ + +INSTALL.doom: INSTALL.template + $(srcdir)/simplecpp -DDOOM $(WIN32) \ + -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \ + -DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \ + -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ + +@PROGRAM_PREFIX@heretic.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) heretic.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g heretic -m $(srcdir)/heretic.template \ + $(top_srcdir)/src $(top_srcdir)/src/heretic > $@ + +heretic.cfg.5: $(top_srcdir)/src $(srcdir)/default.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g heretic -m $(srcdir)/default.cfg.template \ + -c default $(top_srcdir)/src/m_config.c > $@ + +@PROGRAM_PREFIX@heretic.cfg.5: $(top_srcdir)/src extra.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g heretic -m $(srcdir)/extra.cfg.template \ + -c extended $(top_srcdir)/src/m_config.c > $@ + +CMDLINE.heretic : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/heretic + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -p $(srcdir)/CMDLINE.template \ + $(top_srcdir)/src/ $(top_srcdir)/src/heretic/ > $@ + +CMDLINE.heretic.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/heretic + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -M $(srcdir)/CMDLINE.template.md \ + $(top_srcdir)/src/ $(top_srcdir)/src/heretic/ > $@ + +INSTALL.heretic: INSTALL.template + $(srcdir)/simplecpp -DHERETIC $(WIN32) \ + -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Heretic" \ + -DLONG_EXE_NAME="@PROGRAM_PREFIX@heretic" \ + -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ + + +@PROGRAM_PREFIX@hexen.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g hexen -m $(srcdir)/hexen.template \ + $(top_srcdir)/src $(top_srcdir)/src/hexen > $@ + +hexen.cfg.5: $(top_srcdir)/src default.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g hexen -m $(srcdir)/default.cfg.template \ + -c default $(top_srcdir)/src/m_config.c > $@ + +@PROGRAM_PREFIX@hexen.cfg.5: $(top_srcdir)/src extra.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g hexen -m $(srcdir)/extra.cfg.template \ + -c extended $(top_srcdir)/src/m_config.c > $@ + +CMDLINE.hexen : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/hexen + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -p $(srcdir)/CMDLINE.template \ + $(top_srcdir)/src/ $(top_srcdir)/src/hexen/ > $@ + +CMDLINE.hexen.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/hexen + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -M $(srcdir)/CMDLINE.template.md \ + $(top_srcdir)/src/ $(top_srcdir)/src/hexen/ > $@ + +INSTALL.hexen: INSTALL.template + $(srcdir)/simplecpp -DHEXEN $(WIN32) \ + -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Hexen" \ + -DLONG_EXE_NAME="@PROGRAM_PREFIX@hexen" \ + -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ + +@PROGRAM_PREFIX@strife.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g strife -m $(srcdir)/strife.template \ + $(top_srcdir)/src $(top_srcdir)/src/strife > $@ + +@PROGRAM_PREFIX@server.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g server -m $(srcdir)/server.template \ + $(top_srcdir)/src > $@ + +$(SETUP_MAN_PAGES): $(top_srcdir)/src $(MANPAGE_GEN_FILES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g $(patsubst @PROGRAM_PREFIX@%-setup.6,%,$@) \ + -m $(srcdir)/setup.template \ + $(top_srcdir)/src > $@ + +strife.cfg.5: $(top_srcdir)/src default.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g strife -m $(srcdir)/default.cfg.template \ + -c default $(top_srcdir)/src/m_config.c > $@ + +@PROGRAM_PREFIX@strife.cfg.5: $(top_srcdir)/src extra.cfg.template + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g strife -m $(srcdir)/extra.cfg.template \ + -c extended $(top_srcdir)/src/m_config.c > $@ + +CMDLINE.strife : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/strife + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -p $(srcdir)/CMDLINE.template \ + $(top_srcdir)/src/ $(top_srcdir)/src/strife/ > $@ + +CMDLINE.strife.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/strife + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -M $(srcdir)/CMDLINE.template.md \ + $(top_srcdir)/src/ $(top_srcdir)/src/strife/ > $@ + +INSTALL.strife: INSTALL.template + $(srcdir)/simplecpp -DSTRIFE $(WIN32) \ + -DLONG_EXE_NAME="@PROGRAM_PREFIX@strife" \ + -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Strife" \ + -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ + + +INSTALL: INSTALL.template + $(srcdir)//simplecpp -DDOOM -DHERETIC -DHEXEN -DSTRIFE \ + -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \ + -DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \ + -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ + +endif + +EXTRA_DIST = $(man_MANS) $(MANPAGE_GEN_FILES) \ + wikipages \ + CMDLINE.template \ + CMDLINE.template.md \ + INSTALL.template \ + simplecpp + diff --git a/games/NXDoom/man/bash-completion/.gitignore b/games/NXDoom/man/bash-completion/.gitignore new file mode 100644 index 00000000000..488df26aad6 --- /dev/null +++ b/games/NXDoom/man/bash-completion/.gitignore @@ -0,0 +1,5 @@ +*doom +*heretic +*hexen +*strife +*.template diff --git a/games/NXDoom/man/bash-completion/Makefile.am b/games/NXDoom/man/bash-completion/Makefile.am new file mode 100644 index 00000000000..a79fe6239b2 --- /dev/null +++ b/games/NXDoom/man/bash-completion/Makefile.am @@ -0,0 +1,52 @@ +bashcompletiondir=@datadir@/bash-completion/completions + +BASH_COMPLETION_TEMPLATES = \ + doom.template \ + heretic.template \ + hexen.template \ + strife.template + +if HAVE_BASH_COMPLETION + +BASH_COMPLETION_SCRIPTLETS = \ + @PROGRAM_PREFIX@doom \ + @PROGRAM_PREFIX@heretic \ + @PROGRAM_PREFIX@hexen \ + @PROGRAM_PREFIX@strife + +bashcompletion_DATA = $(BASH_COMPLETION_SCRIPTLETS) +CLEANFILES = $(BASH_COMPLETION_SCRIPTLETS) + +DOCGEN = $(top_srcdir)/man/docgen +DOCGEN_COMMON_ARGS = -n "@PROGRAM_SPREFIX@" -s "@PACKAGE_NAME@" -z "@PACKAGE_SHORTNAME@" + +@PROGRAM_PREFIX@doom: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g doom -b doom.template \ + $(top_srcdir)/src $(top_srcdir)/src/doom > $@ + +@PROGRAM_PREFIX@heretic: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g heretic -b heretic.template \ + $(top_srcdir)/src $(top_srcdir)/src/heretic > $@ + +@PROGRAM_PREFIX@hexen: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g hexen -b hexen.template \ + $(top_srcdir)/src $(top_srcdir)/src/hexen > $@ + +@PROGRAM_PREFIX@strife: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) + $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ + -g strife -b strife.template \ + $(top_srcdir)/src $(top_srcdir)/src/strife > $@ + +EXTRA_DIST = \ + $(BASH_COMPLETION_TEMPLATES) \ + $(BASH_COMPLETION_SCRIPTLETS) + +else + +EXTRA_DIST = \ + $(BASH_COMPLETION_TEMPLATES) + +endif diff --git a/games/NXDoom/man/bash-completion/doom.template.in b/games/NXDoom/man/bash-completion/doom.template.in new file mode 100644 index 00000000000..6db3baf059d --- /dev/null +++ b/games/NXDoom/man/bash-completion/doom.template.in @@ -0,0 +1,51 @@ +# bash completion for @PACKAGE_SHORTNAME@ Doom -*- shell-script -*- + +_@PROGRAM_SPREFIX@_doom() +{ + local cur prev words cword + _init_completion || return + + # Save the previous switch on the command line in the prevsw variable + local i prevsw="" + for (( i=1; $cword > 1 && i <= $cword; i++ )); do + if [[ ${words[i]} == -* ]]; then + prevsw=${words[i]} + fi + done + + # Allow adding more than one file with the same extension to the same switch + case $prevsw in + -config|-extraconfig) + _filedir cfg + ;; + -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) + _filedir wad + ;; + -playdemo|-timedemo) + _filedir lmp + ;; + -deh) + _filedir '@(bex|deh)' + ;; + esac + + case $prev in + -pack) + COMPREPLY=(doom2 tnt plutonia) + ;; + -gameversion) + COMPREPLY=(1.666 1.7 1.8 1.9 ultimate final final2 hacx chex) + ;; + -setmem) + COMPREPLY=(dos622 dos71 dosbox) + ;; + esac + + if [[ $cur == -* ]]; then + COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) + fi +} && + +complete -F _@PROGRAM_SPREFIX@_doom @PROGRAM_PREFIX@doom + +# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/bash-completion/heretic.template.in b/games/NXDoom/man/bash-completion/heretic.template.in new file mode 100644 index 00000000000..a46b19cc31c --- /dev/null +++ b/games/NXDoom/man/bash-completion/heretic.template.in @@ -0,0 +1,48 @@ +# bash completion for @PACKAGE_SHORTNAME@ Heretic -*- shell-script -*- + +_@PROGRAM_SPREFIX@_heretic() +{ + local cur prev words cword + _init_completion || return + + # Save the previous switch on the command line in the prevsw variable + local i prevsw="" + for (( i=1; $cword > 1 && i <= $cword; i++ )); do + if [[ ${words[i]} == -* ]]; then + prevsw=${words[i]} + fi + done + + # Allow adding more than one file with the same extension to the same switch + case $prevsw in + -config|-extraconfig) + _filedir cfg + ;; + -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) + _filedir wad + ;; + -playdemo|-timedemo) + _filedir lmp + ;; + -deh) + _filedir hhe + ;; + esac + + case $prev in + -hhever) + COMPREPLY=(1.0 1.2 1.3) + ;; + -setmem) + COMPREPLY=(dos622 dos71 dosbox) + ;; + esac + + if [[ $cur == -* ]]; then + COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) + fi +} && + +complete -F _@PROGRAM_SPREFIX@_heretic @PROGRAM_PREFIX@heretic + +# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/bash-completion/hexen.template.in b/games/NXDoom/man/bash-completion/hexen.template.in new file mode 100644 index 00000000000..e93fc71cbeb --- /dev/null +++ b/games/NXDoom/man/bash-completion/hexen.template.in @@ -0,0 +1,45 @@ +# bash completion for @PACKAGE_SHORTNAME@ Hexen -*- shell-script -*- + +_@PROGRAM_SPREFIX@_hexen() +{ + local cur prev words cword + _init_completion || return + + # Save the previous switch on the command line in the prevsw variable + local i prevsw="" + for (( i=1; $cword > 1 && i <= $cword; i++ )); do + if [[ ${words[i]} == -* ]]; then + prevsw=${words[i]} + fi + done + + # Allow adding more than one file with the same extension to the same switch + case $prevsw in + -config|-extraconfig) + _filedir cfg + ;; + -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) + _filedir wad + ;; + -playdemo|-timedemo) + _filedir lmp + ;; + esac + + case $prev in + -gameversion) + COMPREPLY=(1.1 1.1r2) + ;; + -setmem) + COMPREPLY=(dos622 dos71 dosbox) + ;; + esac + + if [[ $cur == -* ]]; then + COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) + fi +} && + +complete -F _@PROGRAM_SPREFIX@_hexen @PROGRAM_PREFIX@hexen + +# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/bash-completion/strife.template.in b/games/NXDoom/man/bash-completion/strife.template.in new file mode 100644 index 00000000000..a044ef0b742 --- /dev/null +++ b/games/NXDoom/man/bash-completion/strife.template.in @@ -0,0 +1,48 @@ +# bash completion for @PACKAGE_SHORTNAME@ Strife -*- shell-script -*- + +_@PROGRAM_SPREFIX@_strife() +{ + local cur prev words cword + _init_completion || return + + # Save the previous switch on the command line in the prevsw variable + local i prevsw="" + for (( i=1; $cword > 1 && i <= $cword; i++ )); do + if [[ ${words[i]} == -* ]]; then + prevsw=${words[i]} + fi + done + + # Allow adding more than one file with the same extension to the same switch + case $prevsw in + -config|-extraconfig) + _filedir cfg + ;; + -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) + _filedir wad + ;; + -playdemo|-timedemo) + _filedir lmp + ;; + -deh) + _filedir seh + ;; + esac + + case $prev in + -gameversion) + COMPREPLY=(1.2 1.31) + ;; + -setmem) + COMPREPLY=(dos622 dos71 dosbox) + ;; + esac + + if [[ $cur == -* ]]; then + COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) + fi +} && + +complete -F _@PROGRAM_SPREFIX@_strife @PROGRAM_PREFIX@strife + +# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/default.cfg.template b/games/NXDoom/man/default.cfg.template new file mode 100644 index 00000000000..5d07322a6f5 --- /dev/null +++ b/games/NXDoom/man/default.cfg.template @@ -0,0 +1,50 @@ +.TH @CFGFILE@ 5 2017-11-30 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@CFGFILE@ \- @PACKAGE_SHORTNAME@ @GAME_UPPER@ configuration file +.SH DESCRIPTION +.PP +\fI@CFGFILE@\fR +is the configuration file for \fB@PROGRAM_SPREFIX@\-@GAME@\fR(6). The configuration +options stored in the file are the same as those stored in the +original DOS Vanilla @GAME_UPPER@. +Extra @PACKAGE_SHORTNAME@ @GAME_UPPER@-specific options are stored in a separate +configuration file, \fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. +.PP +\fI@CFGFILE@\fR is normally stored in the user's home directory, +as \fI~/.local/share/@PROGRAM_SPREFIX@\-@GAME@/@CFGFILE@\fR. The path can be +overridden using the \fBXDG_DATA_HOME\fR environment variable (see the XDG +Base Directory Specification). +.PP +The \fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) tool provides a simple to use front-end +for editing \fI@CFGFILE@\fR. +.SH FILE FORMAT +The file is a plain-text file, consisting of a list of configuration +options and their values, separated by whitespace. Each option is stored +on a separate line. Options have different types; an option may have +either an integer, floating point or string value. If the option is +of a string type, the value is surrounded by quotes ("). +.PP +For example: +.RS +.PP +.EX +integer_value 1 +integer_value2 1 +floating_point_value 4.2 +string_value "hello world" +.EE +.RE +.PP +Invalid lines or comments in the file will be ignored, but it is advisable +not to put them in the file; the file is rewritten from scratch every time +the game exits, so any invalid lines or comments will be lost. +.PP +Some options are used for keyboard key bindings; these are stored as +integer values containing the keyboard scan code of the key to be bound to. +Boolean values are also stored as integers, with a value of zero usually +indicating "false" and a non-zero value indicating "true". +@content +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6), +\fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR(5), +\fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) diff --git a/games/NXDoom/man/docgen b/games/NXDoom/man/docgen new file mode 100755 index 00000000000..8760e8f72c6 --- /dev/null +++ b/games/NXDoom/man/docgen @@ -0,0 +1,624 @@ +#!/usr/bin/env python3 +# +# Chocolate Doom self-documentation tool. This works similar to javadoc +# or doxygen, but documents command line parameters and configuration +# file values, generating documentation in Unix manpage, wikitext and +# plain text forms. +# +# Comments are read from the source code in the following form: +# +# //! +# // @arg +# // @category Category +# // @platform +# // +# // Long description of the parameter +# // +# +# something_involving = M_CheckParm("-param"); +# +# For configuration file values: +# +# //! @begin_config_file myconfig +# +# //! +# // Description of the configuration file value. +# // +# +# CONFIG_VARIABLE_INT(my_variable, c_variable), +# + +import io +import sys +import os +import re +import glob +import getopt + +TEXT_WRAP_WIDTH = 78 +INCLUDE_STATEMENT_RE = re.compile(r"@include\s+(\S+)") + +# Use appropriate stdout function for Python 2 or 3 + +def stdout(buf): + if sys.version_info.major < 3: + sys.stdout.write(buf) + else: + sys.stdout.buffer.write(buf) + +# Find the maximum width of a list of parameters (for plain text output) + +def parameter_list_width(params): + w = 0 + + for p in params: + pw = len(p.name) + 5 + + if p.args: + pw += len(p.args) + + if pw > w: + w = pw + + return w + +class ConfigFile: + def __init__(self, filename): + self.filename = filename + self.variables = [] + + def add_variable(self, variable): + self.variables.append(variable) + + def manpage_output(self): + result = ".SH CONFIGURATION VARIABLES\n" + + for v in self.variables: + result += ".TP\n" + result += v.manpage_output() + + return result + + def plaintext_output(self): + result = "" + + w = parameter_list_width(self.variables) + + for p in self.variables: + result += p.plaintext_output(w) + + result = result.rstrip() + "\n" + + return result + +class Category: + def __init__(self, description): + self.description = description + self.params = [] + + def add_param(self, param): + self.params.append(param) + + # Plain text output + + def plaintext_output(self): + result = "=== %s ===\n\n" % self.description + + self.params.sort() + + w = parameter_list_width(self.params) + + for p in self.params: + if p.should_show(): + result += p.plaintext_output(w) + + result = result.rstrip() + "\n" + + return result + + def markdown_output(self): + result = "## %s\n\n| Parameter | Description |\n| - | - |\n" % self.description + + self.params.sort() + + for p in self.params: + if p.should_show(): + result += p.markdown_output() + + result = result.rstrip() + "\n" + + return result + + def completion_output(self): + result = "" + + self.params.sort() + + for p in self.params: + if p.should_show(): + result += p.completion_output(0) + + result = result.rstrip() + + return result + + def manpage_output(self): + result = ".SH " + self.description.upper() + "\n" + + self.params.sort() + + for p in self.params: + if p.should_show(): + result += ".TP\n" + result += p.manpage_output() + + return result + + def wiki_output(self): + result = "=== %s ===\n" % self.description + + self.params.sort() + + for p in self.params: + if p.should_show(): + result += "; " + p.wiki_output() + "\n" + + # Escape special HTML characters + + result = result.replace("&", "&") + result = result.replace("<", "<") + result = result.replace(">", ">") + + return result + +categories = ( + (None, Category("General options")), + ("game", Category("Game start options")), + ("video", Category("Display options")), + ("net", Category("Networking options")), + ("mod", Category("Dehacked and WAD merging")), + ("demo", Category("Demo options")), + ("compat", Category("Compatibility")), + ("obscure", Category("Obscure and less-used options")), +) + +wikipages = [] +config_files = {} + +# Show options that are in Vanilla Doom? Or only new options? + +show_vanilla_options = True + +class Parameter: + def __lt__(self, other): + return self.name < other.name + + def __init__(self): + self.text = "" + self.name = "" + self.args = None + self.platform = None + self.category = None + self.vanilla_option = False + self.games = None + + def should_show(self): + return not self.vanilla_option or show_vanilla_options + + def add_text(self, text): + if len(text) <= 0: + pass + elif text[0] == "@": + match = re.match(r'@(\S+)\s*(.*)', text) + + if not match: + raise "Malformed option line: %s" % text + + option_type = match.group(1) + data = match.group(2) + + if option_type == "arg": + self.args = data + elif option_type == "platform": + self.platform = data + elif option_type == "category": + self.category = data + elif option_type == "vanilla": + self.vanilla_option = True + elif option_type == "game": + self.games = re.split(r'\s+', data.strip()) + else: + raise "Unknown option type '%s'" % option_type + + else: + self.text += text + " " + + def _games_only_text(self, pattern="(%s only)"): + if not match_game and self.games: + games_list = ", ".join(map(str.capitalize, self.games)) + return " " + (pattern % games_list) + else: + return "" + + def manpage_output(self): + if self.args: + # Special cases -- GBR is not proud. + if self.args == "[ | ]": + result = ".BR " + self.name + " \\~\\c\n" \ + + ".RI [ x\\~y | xy ]\n" + elif self.args == "": + result = ".BI " + self.name + "\\~ W x H\n" + elif self.args == " ": + result = ".BI " + self.name + "\\~ \"x y\"\n" + elif self.args == "": + result = ".BI " + self.name + "\\~ \"file\\~\\c\n" \ + + "\\&.\\|.\\|.\n" + elif self.args == " ": + result = ".BI " + self.name \ + + "\\~ \"save-num demo-name\"\n" + else: + self.args = re.sub(r'[<>]', '', self.args) + result = ".BI " + self.name + "\\~ " + self.args + "\n" + else: + result = ".B " + self.name + "\n" + + if self.platform: + result += "[%s only] " % self.platform + + escaped = re.sub(r'\\', r'\\\\', self.text) + + result += escaped + self._games_only_text() + "\n" + + return result + + def wiki_output(self): + result = self.name + + if self.args: + result += " " + self.args + + result += ": " + + result += add_wiki_links(self.text) + + if self.platform: + result += "'''(%s only)'''" % self.platform + result += self._games_only_text("'''(%s only)'''") + + return result + + def markdown_output(self): + if self.args: + name = "%s %s" % (self.name, self.args) + else: + name = "%s" % self.name + + name = name.replace("|", "\\|") + + text = self.text + if self.platform: + text += " (%s only)" % self.platform + + text = text.replace("|", "\\|") + + result = "| %s | %s |\n" % (name, text) + + # html escape + result = result.replace("<", "<") + result = result.replace(">", ">") + + return result + + def plaintext_output(self, indent): + # Build the first line, with the argument on + start = " " + self.name + if self.args: + start += " " + self.args + + # pad up to the plaintext width + start += " " * (indent - len(start)) + + # Build the description text + description = self.text + if self.platform: + description += " (%s only)" % self.platform + description += self._games_only_text() + + # Build the complete text for the argument + # Split the description into words and add a word at a time + result = "" + words = [word for word in re.split(r'\s+', description) if word] + maxlen = TEXT_WRAP_WIDTH - indent + outlines = [[]] + for word in words: + linelen = sum(len(w) + 1 for w in outlines[-1]) + if linelen + len(word) > maxlen: + outlines.append([]) + outlines[-1].append(word) + + linesep = "\n" + " " * indent + + return (start + + linesep.join(" ".join(line) for line in outlines) + + "\n\n") + + def completion_output(self, w): + + result = self.name + " " + + return result + +# Read list of wiki pages + +def read_wikipages(): + f = io.open("wikipages", encoding='UTF-8') + + try: + for line in f: + line = line.rstrip() + + line = re.sub(r'\#.*$', '', line) + + if not re.match(r'^\s*$', line): + wikipages.append(line) + finally: + f.close() + +# Add wiki page links + +def add_wiki_links(text): + def replace_name(m): + linktext = m.group(1) + if linktext == pagename: + return '[[%s]]' % pagename + else: + return '[[%s|%s]]' % (pagename, linktext) + + for pagename in wikipages: + text = re.sub(r'\b(%s)\b' % re.escape(pagename), replace_name, + text, count=0, flags=re.IGNORECASE) + + return text + +def add_parameter(param, line, config_file): + + # If we're only targeting a particular game, check this is one of + # the ones we're targeting. + + if match_game and param.games and match_game not in param.games: + return + + # Is this documenting a command line parameter? + + match = re.search(r'(M_CheckParm(WithArgs)|M_ParmExists)?\s*\(\s*"(.*?)"', + line) + + if match: + param.name = match.group(3) + category = dict(categories)[param.category] + category.add_param(param) + return + + # Documenting a configuration file variable? + + match = re.search(r'CONFIG_VARIABLE_\S+\s*\(\s*(\S+?)\),', line) + + if match: + param.name = match.group(1) + config_file.add_variable(param) + return + + raise Exception(param.text) + +def process_file(filename): + + current_config_file = None + + f = io.open(filename, encoding='UTF-8') + + try: + param = None + waiting_for_checkparm = False + + for line in f: + line = line.rstrip() + + # Ignore empty lines + + if re.match(r'\s*$', line): + continue + + # Currently reading a doc comment? + + if param: + # End of doc comment + + if not re.match(r'\s*//', line): + waiting_for_checkparm = True + + # The first non-empty line after the documentation comment + # ends must contain the thing being documented. + + if waiting_for_checkparm: + add_parameter(param, line, current_config_file) + param = None + else: + # More documentation text + + munged_line = re.sub(r'\s*\/\/\s*', '', line, count=1) + munged_line = re.sub(r'\s*$', '', munged_line) + param.add_text(munged_line) + + # Check for start of a doc comment + + if re.search("//!", line): + match = re.search(r"@begin_config_file\s*(\S+)", line) + + if match: + # Beginning a configuration file + tagname = match.group(1) + current_config_file = ConfigFile(tagname) + config_files[tagname] = current_config_file + else: + # Start of a normal comment + param = Parameter() + waiting_for_checkparm = False + finally: + f.close() + +def process_files(path): + # Process all C source files. + + if os.path.isdir(path): + files = glob.glob(path + "/*.c") + + for filename in files: + process_file(filename) + else: + # Special case to allow a single file to be specified as a target + + process_file(path) + +def print_template(template_file, substs, content): + f = io.open(template_file, encoding='UTF-8') + + try: + for line in f: + match = INCLUDE_STATEMENT_RE.search(line) + if match: + filename = match.group(1) + filename = os.path.join(os.path.dirname(template_file), + filename) + print_template(filename, substs, content) + else: + line = line.replace("@content", content) + for k,v in substs.items(): + line = line.replace(k,v) + stdout(line.rstrip().encode('UTF-8') + b'\n') + finally: + f.close() + +def manpage_output(targets, substs, template_file): + + content = "" + + for t in targets: + content += t.manpage_output() + + content = content.replace("-", "\\-") + + print_template(template_file, substs, content) + +def wiki_output(targets, _, template): + read_wikipages() + + for t in targets: + stdout(t.wiki_output().encode('UTF-8') + b'\n') + +def markdown_output(targets, substs, template_file): + content = "" + + for t in targets: + content += t.markdown_output() + "\n" + + print_template(template_file, substs, content) + +def plaintext_output(targets, substs, template_file): + + content = "" + + for t in targets: + content += t.plaintext_output() + "\n" + + print_template(template_file, substs, content) + +def completion_output(targets, substs, template_file): + + content = "" + + for t in targets: + content += t.completion_output() + "\n" + + print_template(template_file, substs, content) + +def usage(): + print("Usage: %s [-V] [-c tag] [-g game] -n program_name -s package_name [ -z shortname ] ( -M | -m | -w | -p ) ..." \ + % sys.argv[0]) + print(" -c : Provide documentation for the specified configuration file") + print(" (matches the given tag name in the source file)") + print(" -s : Package name, e.g. Chocolate Doom (for substitution)") + print(" -z : Package short-name, e.g. Chocolate (for substitution)") + print(" -v : Package version, e.g. 7.0 (for substitution)") + print(" -n : Program name, e.g. chocolate (for substitution)") + print(" -M : Markdown output") + print(" -m : Manpage output") + print(" -w : Wikitext output") + print(" -p : Plaintext output") + print(" -b : Bash-Completion output") + print(" -V : Don't show Vanilla Doom options") + print(" -g : Only document options for specified game.") + sys.exit(0) + +# Parse command line + +opts, args = getopt.getopt(sys.argv[1:], "n:s:z:v:M:m:wp:b:c:g:V") + +output_function = None +template = None +doc_config_file = None +match_game = None +substs = {} + +for opt in opts: + if opt[0] == "-n": + substs["@PROGRAM_SPREFIX@"] = opt[1] + if opt[0] == "-s": + substs["@PACKAGE_NAME@"] = opt[1] + if opt[0] == "-z": + substs["@PACKAGE_SHORTNAME@"] = opt[1] + if opt[0] == "-v": + substs["@VERSION@"] = opt[1] + if opt[0] == "-m": + output_function = manpage_output + template = opt[1] + elif opt[0] == "-M": + output_function = markdown_output + template = opt[1] + elif opt[0] == "-w": + output_function = wiki_output + elif opt[0] == "-p": + output_function = plaintext_output + template = opt[1] + elif opt[0] == "-b": + output_function = completion_output + template = opt[1] + elif opt[0] == "-V": + show_vanilla_options = False + elif opt[0] == "-c": + doc_config_file = opt[1] + elif opt[0] == "-g": + match_game = opt[1] + substs["@GAME@"] = opt[1] + substs["@GAME_UPPER@"] = opt[1].title() + if "doom" == opt[1]: + substs["@CFGFILE@"] = "default.cfg" + else: + substs["@CFGFILE@"] = opt[1] + ".cfg" + +if output_function == None or len(args) < 1: + usage() +else: + # Process specified files + + for path in args: + process_files(path) + + # Build a list of things to document + if doc_config_file: + documentation_targets = [config_files[doc_config_file]] + else: + documentation_targets = [c for _, c in categories] + + # Generate the output + output_function(documentation_targets, substs, template) + diff --git a/games/NXDoom/man/doom.template b/games/NXDoom/man/doom.template new file mode 100644 index 00000000000..bbf1c62aafa --- /dev/null +++ b/games/NXDoom/man/doom.template @@ -0,0 +1,45 @@ +.TH @PROGRAM_SPREFIX@\-doom 6 2018-01-09 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-doom \- historically compatible Doom engine +.SH SYNOPSIS +.B @PROGRAM_SPREFIX@\-doom +.RI [ options ] +.SH DESCRIPTION +.PP +@PACKAGE_SHORTNAME@ Doom is a port of Id Software's 1993 game +.I Doom +that is designed to behave as similarly to the original DOS version of +Doom as is possible. +@content +.SH IWAD SEARCH PATHS +@include iwad_paths.man +.SH ENVIRONMENT +This section describes environment variables that control +@PACKAGE_SHORTNAME@ Doom's behavior. +@include environ.man +.SH FILES +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/default.cfg +The main configuration file for @PACKAGE_NAME@. +See \fBdefault.cfg\fR(5). +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-doom.cfg +Extra configuration values that are specific to @PACKAGE_NAME@ and not +present in Vanilla Doom. +See \fB@PROGRAM_SPREFIX@\-doom.cfg\fR(5). +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-server\fR(6), +\fB@PROGRAM_SPREFIX@\-setup\fR(6), +\fB@PROGRAM_SPREFIX@\-heretic\fR(6), +\fB@PROGRAM_SPREFIX@\-hexen\fR(6), +\fB@PROGRAM_SPREFIX@\-strife\fR(6) +.SH AUTHOR +Chocolate Doom is written and maintained by Simon Howard. +It is based on the LinuxDoom source code, released by Id Software. +.SH COPYRIGHT +Copyright \(co id Software Inc. +Copyright \(co 2005-2016 Simon Howard. +.PP +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License . +There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/environ.man b/games/NXDoom/man/environ.man new file mode 100644 index 00000000000..414f5037e66 --- /dev/null +++ b/games/NXDoom/man/environ.man @@ -0,0 +1,34 @@ +.TP +.I DOOMWADDIR +.TQ +.I DOOMWADPATH +See section \(lqIWAD SEARCH PATHS\(rq above. +.TP +.I PCSOUND_DRIVER +When running in PC speaker sound effect mode, this environment variable +specifies a PC speaker driver to use for sound effect playback. +Valid options are +.RB \(lq Linux \(rq +for the Linux console mode driver, +.RB \(lq BSD \(rq +for the NetBSD/OpenBSD PC speaker driver, +and +.RB \(lq SDL \(rq +for SDL-based emulated PC speaker playback (using the digital output). +.TP +.I OPL_DRIVER +When using OPL MIDI playback, this environment variable specifies an +OPL backend driver to use. +Valid options are +.RB \(lq SDL \(rq +for an SDL-based software emulated OPL chip, +.RB \(lq Linux \(rq +for the Linux hardware OPL driver, +and +.RB \(lq OpenBSD \(rq +for the OpenBSD/NetBSD hardware OPL driver. +.IP +Generally speaking, a real hardware OPL chip sounds better than software +emulation; however, modern machines do not often include one. +If present, it may still require extra work to set up and elevated +security privileges to access. diff --git a/games/NXDoom/man/extra.cfg.template b/games/NXDoom/man/extra.cfg.template new file mode 100644 index 00000000000..de6f40666fe --- /dev/null +++ b/games/NXDoom/man/extra.cfg.template @@ -0,0 +1,28 @@ +.TH @PROGRAM_SPREFIX@\-@GAME@.cfg 5 2024-01-23 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-@GAME@.cfg \- @PACKAGE_SHORTNAME@ @GAME_UPPER@ configuration file +.SH DESCRIPTION +.PP +\fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR +is a configuration file for \fB@PROGRAM_SPREFIX@\-@GAME@\fR(6). This file acts +as an auxiliary configuration file; the main configuration options +are stored in \fB@CFGFILE@\fR, which contains the same configuration +options as Vanilla @GAME_UPPER@ (for compatibility). \fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR +contains configuration options that are specific to @PACKAGE_SHORTNAME@\-@GAME_UPPER@ +only. +.PP +\fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR is normally stored in the user's home directory, +as \fI~/.local/share/@PROGRAM_SPREFIX@\-@GAME@/@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. The path can be +overridden using the \fBXDG_DATA_HOME\fR environment variable (see the XDG +Base Directory Specification). +.PP +The \fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) tool provides a simple to use front-end +for editing \fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. +.SH FILE FORMAT +.PP +The file format is the same as that used for \fB@CFGFILE@\fR(5). +@content +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6), +\fB@CFGFILE@\fR(5), +\fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) diff --git a/games/NXDoom/man/heretic.template b/games/NXDoom/man/heretic.template new file mode 100644 index 00000000000..394af610436 --- /dev/null +++ b/games/NXDoom/man/heretic.template @@ -0,0 +1,47 @@ +.TH @PROGRAM_SPREFIX@\-heretic 6 2017-11-27 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-heretic \- historically compatible Heretic engine +.SH SYNOPSIS +.B @PROGRAM_SPREFIX@\-heretic +.RI [ options ] +.SH DESCRIPTION +.PP +@PACKAGE_SHORTNAME@ Heretic is a port of Raven Software's 1994 game +.I Heretic +that aims to behave as similar to the original DOS version of Heretic as +possible. +@content +.SH IWAD SEARCH PATHS +@include iwad_paths.man +.SH ENVIRONMENT +This section describes environment variables that control +@PACKAGE_SHORTNAME@ Heretic's behavior. +@include environ.man +.SH FILES +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/heretic.cfg +The main configuration file for @PACKAGE_SHORTNAME@ Heretic. +See \fBheretic.cfg\fR(5). +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-heretic.cfg +Extra configuration values that are specific to @PACKAGE_SHORTNAME@ Heretic and not +present in Vanilla Heretic. +See \fB@PROGRAM_SPREFIX@\-heretic.cfg\fR(5). +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-doom\fR(6), +\fB@PROGRAM_SPREFIX@\-hexen\fR(6), +\fB@PROGRAM_SPREFIX@\-server\fR(6), +\fB@PROGRAM_SPREFIX@\-setup\fR(6) +.SH AUTHOR +Chocolate Heretic is part of the Chocolate Doom project, written and +maintained by Simon Howard. +It is based on the Heretic source code, +released by Raven Software. +.SH COPYRIGHT +Copyright \(co id Software Inc. +Copyright \(co Raven Software Inc. +Copyright \(co 2005-2013 Simon Howard. +.PP +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License . +There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/hexen.template b/games/NXDoom/man/hexen.template new file mode 100644 index 00000000000..22e900f017c --- /dev/null +++ b/games/NXDoom/man/hexen.template @@ -0,0 +1,47 @@ +.TH @PROGRAM_SPREFIX@\-hexen 6 2017-11-27 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-hexen \- historically compatible Hexen engine +.SH SYNOPSIS +.B @PROGRAM_SPREFIX@\-hexen +.RI [ options ] +.SH DESCRIPTION +.PP +@PACKAGE_SHORTNAME@ Hexen is a port of Raven Software's 1995 game +.I Hexen +that aims to behave as similar to the original DOS version of Hexen as +possible. +@content +.SH IWAD SEARCH PATHS +@include iwad_paths.man +.SH ENVIRONMENT +This section describes environment variables that control +@PACKAGE_SHORTNAME@ Hexen's behavior. +@include environ.man +.SH FILES +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/hexen.cfg +The main configuration file for @PACKAGE_SHORTNAME@ Hexen. +See \fBhexen.cfg\fR(5). +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-hexen.cfg +Extra configuration values that are specific to @PACKAGE_SHORTNAME@ +Hexen and not present in Vanilla Hexen. +See \fB@PROGRAM_SPREFIX@\-hexen.cfg\fR(5). +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-doom\fR(6), +\fB@PROGRAM_SPREFIX@\-heretic\fR(6), +\fB@PROGRAM_SPREFIX@\-server\fR(6), +\fB@PROGRAM_SPREFIX@\-setup\fR(6) +.SH AUTHOR +Chocolate Hexen is part of the Chocolate Doom project, written and +maintained by Simon Howard. +It is based on the Hexen source code, +released by Raven Software. +.SH COPYRIGHT +Copyright \(co id Software Inc. +Copyright \(co Raven Software Inc. +Copyright \(co 2005-2013 Simon Howard. +.PP +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License . +There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/iwad_paths.man b/games/NXDoom/man/iwad_paths.man new file mode 100644 index 00000000000..5b4268094ad --- /dev/null +++ b/games/NXDoom/man/iwad_paths.man @@ -0,0 +1,73 @@ +To play, an IWAD file is needed. +This is a large file containing all of the levels, graphics, +sound effects, music and other material that make up the game. +IWAD files are named according to the game; the standard names are: +.TP +.IR doom.wad ,\~\c +.IR doom1.wad ,\~\c +.IR doom2.wad ,\~\c +.IR tnt.wad ,\~\c +.I plutonia.wad +Doom, Doom II, Final Doom +.TP +.IR heretic.wad ,\~\c +.IR hexen.wad ,\~\c +.I strife.wad +Heretic, Hexen and Strife (commercial Doom engine games). +.TP +.IR hacx.wad ,\~\c +.I chex.wad +Hacx and Chex Quest - more obscure games based on the Doom engine. +.TP +.IR freedm.wad ,\~\c +.IR freedoom1.wad ,\~\c +.I freedoom2.wad +The Freedoom open content IWAD files. +.LP +The following directory paths are searched in order to find an IWAD: +.TP +Current working directory +Any IWAD files found in the current working directory will be used in +preference to IWADs found in any other directories. +.TP +.I DOOMWADDIR +This environment variable can be set to contain a path to a single +directory in which to look for IWAD files. +This environment variable is supported by most Doom source ports. +.TP +.I DOOMWADPATH +This environment variable, if set, can contain a colon-separated list of +directories in which to look for IWAD files, or alternatively full paths to +specific IWAD files. +.TP +.I $HOME/.local/share/games/doom +Writeable directory in the user's home directory. +The path can be overridden using the +.I \%XDG_DATA_HOME +environment variable (see the XDG Base Directory Specification). +.TP +.I /usr/local/share/doom +.TQ +.I /usr/local/share/games/doom +.TQ +.I /usr/share/doom +.TQ +.I /usr/share/games/doom +System-wide locations that can be accessed by all users. +The path +.I /usr/share/games/doom +is a standard path that is supported by most Doom source ports. +These paths can be overridden using the +.I \%XDG_DATA_DIRS +environment variable (see the XDG Base Directory Specification). +.LP +The above can be overridden on a one-time basis by using the +.B \-iwad +command line parameter to provide the path to an IWAD file to use.This +parameter can also be used to specify the name of a particular IWAD to use +from one of the above paths. +For example, +.RB \(lq "\-iwad doom.wad" \(rq +will search the above paths for the file +.I doom.wad +to use. diff --git a/games/NXDoom/man/server.template b/games/NXDoom/man/server.template new file mode 100644 index 00000000000..7ce2a3b3708 --- /dev/null +++ b/games/NXDoom/man/server.template @@ -0,0 +1,55 @@ +.TH @PROGRAM_SPREFIX@\-server 6 2018-01-15 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-server \- dedicated server for @PROGRAM_SPREFIX@\-doom +.SH SYNOPSIS +.B @PROGRAM_SPREFIX@\-server +.RI [ options ] +.SH DESCRIPTION +.PP +@PACKAGE_NAME@ is a modern Doom engine designed to behave +as similarly to the original Doom game as is possible. +.PP +.I \%@PROGRAM_SPREFIX@\-server +is a dedicated server for @PACKAGE_SHORTNAME@. +It is equivalent to running +\fB@PROGRAM_SPREFIX@-doom\fR(6) +with the +.B \%\-dedicated +option. +.PP +Game options are not specified to the server, which merely acts to +retransmit data between players in the game; parameters for the +game should be specified by the first player to connect to the server, +who is designated the controlling player. +.SH OPTIONS +.TP +.B \-ignoreversion +Ignore version mismatches between the server and the client. +Using this option may cause game desyncs to occur, +or differences in protocol may mean the netgame will simply not function +at all. +.TP +.BI \-port\~ n +Use UDP port +.I n +for communications instead of the default (2342). +.TP +.B \-privateserver +Don't register with the global master server. +.TP +.BI \-servername\~ name +Specify a name for the server. +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@-doom\fR(6), +\fB@PROGRAM_SPREFIX@-setup\fR(6) +.SH AUTHOR +Chocolate Doom is written and maintained by Simon Howard. +.PP +This manual was written by Jonathan Dowland. +.SH COPYRIGHT +Copyright \(co id Software Inc. +Copyright \(co 2005-8 Simon Howard. +.PP +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License . +There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/setup.template b/games/NXDoom/man/setup.template new file mode 100644 index 00000000000..1fd057c66bc --- /dev/null +++ b/games/NXDoom/man/setup.template @@ -0,0 +1,46 @@ +.TH @PROGRAM_SPREFIX@\-@GAME@-setup 6 2017-11-30 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-@GAME@-setup \- configuration tool for @PROGRAM_SPREFIX@\-@GAME@ +.SH SYNOPSIS +.B @PROGRAM_SPREFIX@\-@GAME@-setup +.RI [ options ] +.SH DESCRIPTION +.PP +@PACKAGE_SHORTNAME@ @GAME_UPPER@ is a modern @GAME_UPPER@ engine +designed to behave as similarly to the original @GAME_UPPER@ game as is +possible. +.PP +.I @PROGRAM_SPREFIX@\-@GAME@-setup +is a tool for configuring @PACKAGE_SHORTNAME@ @GAME_UPPER@. +It provides a menu-based interface for the display, joystick, keyboard, +mouse, sound and compatibility settings. +.PP +.I @PROGRAM_SPREFIX@\-@GAME@-setup +can also be used to start and join network games. +.PP +.SH OPTIONS +.TP +.BI \-config\~ file +Load configuration from the specified file, +instead of +.IR @CFGFILE@ . +.TP +.BI \-extraconfig\~ file +Load extra configuration from the specified file, +instead of +.IR @PROGRAM_SPREFIX@\-@GAME@.cfg . +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6), +\fBdefault.cfg\fR(5), +\fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR(5) +.SH AUTHOR +Chocolate Doom is written and maintained by Simon Howard. +.PP +This manual was written by Jonathan Dowland. +.SH COPYRIGHT +Copyright \(co id Software Inc. +Copyright \(co 2005-8 Simon Howard. +.PP +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License . +There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/simplecpp b/games/NXDoom/man/simplecpp new file mode 100755 index 00000000000..7749c269a71 --- /dev/null +++ b/games/NXDoom/man/simplecpp @@ -0,0 +1,228 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Contributors to the Freedoom project. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the freedoom project nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +# simple cpp-style preprocessor +# +# Understands most features of the C preprocessor, including: +# #if .. #elif .. #else .. #endif +# - with expressions +# #ifdef +# #define +# #include +# + +import collections +import io +import sys +import re + +debug = False +defines = collections.defaultdict(lambda: False) + +command_re = re.compile(r"\#(\w+)(\s+(.*))?") +include_re = re.compile(r"\s*\"(.*)\"\s*") +define_re = re.compile(r"\s*(\S+)\s*(.*?)\s*$") + +def debug_msg(message): + if debug: + sys.stderr.write(message) + +# Parse command line options + +def parse_cmdline(): + for arg in sys.argv[1:]: + if not arg.startswith("-D"): + continue + + name = arg[2:] + if '=' in name: + name, value = name.split('=', 1) + else: + value = True + + defines[name] = value + +def parse_stream(stream): + result = read_block(stream, False) + + if result is not None: + raise Exception("Mismatched #if in '%s'" % stream.name) + +def parse_file(filename): + f = io.open(filename, encoding='UTF-8') + + try: + parse_stream(f) + finally: + f.close() + +# Evaluate an expression using Python's eval() function. + +def eval_expr(expr): + expr = expr.replace("||", " or ") \ + .replace("&&", " and ") \ + .replace("!", "not ") + + code = compile(expr, "", "eval") + result = eval(code, {}, defines) + return result + +# #include + +def cmd_include(arg): + # Extract the filename + + match = include_re.match(arg) + + if not match: + raise Exception("Invalid 'include' command") + + filename = match.group(1) + + # Open the file and process it + + parse_file(filename) + +# #define + +def cmd_define(arg): + match = define_re.match(arg) + name = match.group(1) + value = match.group(2) + if value == '': + value = True + + defines[name] = value + +# #undef + +def cmd_undef(arg): + if arg in defines: + del defines[arg] + +# #ifdef/#ifndef + +def cmd_ifdef(arg, command, stream, ignore): + + # Get the define name + + debug_msg("%s %s >\n" % (command, arg)) + + # Should we ignore the contents of this block? + + sub_ignore = not eval_expr(arg) + + if "n" in command: + sub_ignore = not sub_ignore + + # Parse the block + + result, newarg = read_block(stream, ignore or sub_ignore) + + debug_msg("%s %s < (%s)\n" % (command, arg, result)) + + # There may be a second "else" block to parse: + + if result == "else": + debug_msg("%s %s else >\n" % (command, arg)) + result, arg = read_block(stream, ignore or (not sub_ignore)) + debug_msg("%s %s else < (%s)\n" % (command, arg, result)) + + if result == "elif": + debug_msg("%s %s elif %s>\n" % (command, arg, newarg)) + cmd_ifdef(newarg, "if", stream, ignore or (not sub_ignore)) + result = "endif" + + # Should end in an endif: + + if result != "endif": + raise Exception("'if' block did not end in an 'endif'") + +commands = { + "include" : cmd_include, + "define" : cmd_define, + "undef" : cmd_undef, + "if" : cmd_ifdef, + "ifdef" : cmd_ifdef, + "ifn" : cmd_ifdef, + "ifndef" : cmd_ifdef, +} + +# Recursive block reading function +# if 'ignore' argument is 1, contents are ignored + +def read_block(stream, ignore): + + for line in stream: + + # Remove newline + + line = line[0:-1] + + # Check if this line has a command + + match = command_re.match(line) + + if match: + command = match.group(1) + arg = match.group(3) + + if command in ("else", "elif", "endif"): + return (command, arg) + elif command not in commands: + raise Exception("Unknown command: '%s'" % \ + command) + + # Get the callback function. + + func = commands[command] + + # Invoke the callback function. #ifdef commands + # are a special case and need extra arguments. + # Other commands are only executed if we are not + # ignoring this block. + + if func == cmd_ifdef: + cmd_ifdef(arg, command=command, + stream=stream, + ignore=ignore) + elif not ignore: + func(arg) + else: + if not ignore: + for key, value in defines.items(): + if isinstance(value, str): + line = line.replace(key, value) + print(line) + +parse_cmdline() +parse_stream(sys.stdin) + diff --git a/games/NXDoom/man/strife.template b/games/NXDoom/man/strife.template new file mode 100644 index 00000000000..51defaecba5 --- /dev/null +++ b/games/NXDoom/man/strife.template @@ -0,0 +1,91 @@ +.TH @PROGRAM_SPREFIX@\-strife 6 2018-01-15 "@PACKAGE_NAME@ @VERSION@" +.SH NAME +@PROGRAM_SPREFIX@\-strife \- historically compatible Strife engine +.SH SYNOPSIS +.B @PROGRAM_SPREFIX@\-strife +.RI [ options ] +.SH DESCRIPTION +.PP +@PACKAGE_SHORTNAME@ Strife is an accurate and complete recreation of +Rogue Entertainment's +.IR "Strife: Quest for the Sigil" . +It was created through +more than two years of reverse engineering effort with the blessings +of the original programmers of the game; +see section \(lqHISTORY\(rq below. +@content +.SH IWAD SEARCH PATHS +@include iwad_paths.man +.SH ENVIRONMENT +This section describes environment variables that control +@PACKAGE_SHORTNAME@ Strife's behavior. +@include environ.man +.SH FILES +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/strife.cfg +The main configuration file for @PACKAGE_SHORTNAME@ Strife. +See \fBstrife.cfg\fR(5). +.TP +.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-strife.cfg +Extra configuration values that are specific to @PACKAGE_SHORTNAME@ +Strife and not present in Vanilla Strife. +See \fB@PROGRAM_SPREFIX@\-strife.cfg\fR(5). +.SH SEE ALSO +\fB@PROGRAM_SPREFIX@\-doom\fR(6), +\fB@PROGRAM_SPREFIX@\-server\fR(6), +\fB@PROGRAM_SPREFIX@\-setup\fR(6) +.SH HISTORY +The source code for Strife was lost, which means, unlike the code for +all the other commercial games using the Doom engine, it cannot be +released. +The only access we have to the code is the binary executable file. +Reverse engineering tools were employed to disassemble and decompile the +executables, which were cross-referenced against the Linux Doom and +DOS Heretic sources and painstakingly combed over multiple times, +instruction by instruction, to ensure that the resulting +Chocolate-Doom-based executable is as close as possible to the original. +.SH LEGALITY +Reverse engineering is a protected activity so long as the original code +is not used directly in the product. +Due to the vast amount of information lost through the process of +compilation, and the need to refactor large portions of code in order to +eliminate non-portable idioms or to adapt them properly to Chocolate +Doom's framework, the resulting code behaves the same, but is not the +.I same +code. +.PP +In addition, James Monroe and John Carmack have both stated that they +have no objections to the project. +Because they are the original authors of the code, and neither Rogue nor +their publisher, Velocity, Inc., exist any longer as legal entities, +this is effectively legal permission. +.SH BUGS +@PACKAGE_SHORTNAME@ Strife is almost, but not entirely perfect, in +recreating the behavior of Vanilla Strife. +Help us by reporting any discrepancies you might notice between this +executable and the vanilla DOS program. +.PP +However, do +.I not +report any glitch that you can replicate in the vanilla EXE as a bug. +The point of @PACKAGE_SHORTNAME@ Strife, like Chocolate Doom before it, +is to be as bug-compatible with the original game as possible. +Also be aware that some glitches are impossible to compatibly recreate, +and wherever this is the case, @PACKAGE_SHORTNAME@ Strife has erred on +the side of not crashing the program, for example by initializing +pointers to +.I NULL +rather than using them without setting a value first. +.SH AUTHORS +Chocolate Strife is part of the Chocolate Doom project. +It was reverse engineered from the DOS versions of Strife by James Haley +and Samuel Villarreal. +Chocolate Doom was written and maintained by Simon Howard, and is based +on the LinuxDoom source code released by Id Software. +.SH COPYRIGHT +Copyright \(co id Software Inc. +Copyright \(co 2005-2013 Simon Howard, James Haley, Samuel Villarreal. +.PP +This is free software. You may redistribute copies of it under the terms of +the GNU General Public License . +There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/wikipages b/games/NXDoom/man/wikipages new file mode 100644 index 00000000000..429c47dde06 --- /dev/null +++ b/games/NXDoom/man/wikipages @@ -0,0 +1,7 @@ +# This is a list of wiki pages to automatically link to when generating +# wikitext output. +Dehacked +Doom 1.91 +Merging +Multiplayer +Three screen mode diff --git a/games/NXDoom/opl/.gitignore b/games/NXDoom/opl/.gitignore new file mode 100644 index 00000000000..8aac4e778ff --- /dev/null +++ b/games/NXDoom/opl/.gitignore @@ -0,0 +1,7 @@ +Makefile.in +Makefile +.deps +libopl.a +*.rc +tags +TAGS diff --git a/games/NXDoom/opl/CMakeLists.txt b/games/NXDoom/opl/CMakeLists.txt new file mode 100644 index 00000000000..289ca279d49 --- /dev/null +++ b/games/NXDoom/opl/CMakeLists.txt @@ -0,0 +1,28 @@ +add_library(opl STATIC + opl_internal.h + opl.c opl.h + opl_linux.c + opl_obsd.c + opl_queue.c opl_queue.h + opl_sdl.c + opl_timer.c opl_timer.h + opl_win32.c + ioperm_sys.c ioperm_sys.h + opl3.c opl3.h) +target_include_directories(opl + INTERFACE "." + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") +if (DEFINED EMSCRIPTEN) + if(ENABLE_SDL2_MIXER) + set_target_properties(opl PROPERTIES COMPILE_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") + set_target_properties(opl PROPERTIES LINK_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") + else() + set_target_properties(opl PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") + set_target_properties(opl PROPERTIES LINK_FLAGS "-s USE_SDL=2") + endif() +else() + target_link_libraries(opl SDL2::SDL2) + if(ENABLE_SDL2_MIXER) + target_link_libraries(opl SDL2_mixer::SDL2_mixer) + endif() +endif() diff --git a/games/NXDoom/opl/Makefile.am b/games/NXDoom/opl/Makefile.am new file mode 100644 index 00000000000..430953e3348 --- /dev/null +++ b/games/NXDoom/opl/Makefile.am @@ -0,0 +1,21 @@ + +AM_CFLAGS=@SDLMIXER_CFLAGS@ + +EXTRA_DIST=CMakeLists.txt + +SUBDIRS = . examples + +noinst_LIBRARIES=libopl.a + +libopl_a_SOURCES = \ + opl_internal.h \ + opl.c opl.h \ + opl_linux.c \ + opl_obsd.c \ + opl_queue.c opl_queue.h \ + opl_sdl.c \ + opl_timer.c opl_timer.h \ + opl_win32.c \ + ioperm_sys.c ioperm_sys.h \ + opl3.c opl3.h + diff --git a/games/NXDoom/opl/examples/.gitignore b/games/NXDoom/opl/examples/.gitignore new file mode 100644 index 00000000000..4d589c73824 --- /dev/null +++ b/games/NXDoom/opl/examples/.gitignore @@ -0,0 +1,7 @@ +Makefile.in +Makefile +.deps +droplay +*.exe +tags +TAGS diff --git a/games/NXDoom/opl/examples/Makefile.am b/games/NXDoom/opl/examples/Makefile.am new file mode 100644 index 00000000000..9afcd513c74 --- /dev/null +++ b/games/NXDoom/opl/examples/Makefile.am @@ -0,0 +1,8 @@ + +AM_CFLAGS = -I$(top_srcdir)/opl + +noinst_PROGRAMS=droplay + +droplay_LDADD = ../libopl.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ +droplay_SOURCES = droplay.c + diff --git a/games/NXDoom/opl/examples/droplay.c b/games/NXDoom/opl/examples/droplay.c new file mode 100644 index 00000000000..16e10c3c9b2 --- /dev/null +++ b/games/NXDoom/opl/examples/droplay.c @@ -0,0 +1,210 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Demonstration program for OPL library to play back DRO +// format files. +// + + +#include +#include +#include + +#include "SDL.h" + +#include "opl.h" + +#define HEADER_STRING "DBRAWOPL" +#define ADLIB_PORT 0x388 + +void WriteReg(unsigned int reg, unsigned int val) +{ + int i; + + // This was recorded from an OPL2, but we are probably playing + // back on an OPL3, so we need to enable the original OPL2 + // channels. Doom does this already, but other games don't. + + if ((reg & 0xf0) == OPL_REGS_FEEDBACK) + { + val |= 0x30; + } + + OPL_WritePort(OPL_REGISTER_PORT, reg); + + for (i=0; i<6; ++i) + { + OPL_ReadPort(OPL_REGISTER_PORT); + } + + OPL_WritePort(OPL_DATA_PORT, val); + + for (i=0; i<35; ++i) + { + OPL_ReadPort(OPL_REGISTER_PORT); + } +} + +void ClearAllRegs(void) +{ + int i; + + for (i=0; i<=0xff; ++i) + { + WriteReg(i, 0x00); + } +} + +void Init(void) +{ + if (SDL_Init(SDL_INIT_TIMER) < 0) + { + fprintf(stderr, "Unable to initialise SDL timer\n"); + exit(-1); + } + + if (!OPL_Init(ADLIB_PORT)) + { + fprintf(stderr, "Unable to initialise OPL layer\n"); + exit(-1); + } +} + +void Shutdown(void) +{ + OPL_Shutdown(); +} + +struct timer_data +{ + int running; + FILE *fstream; +}; + +void TimerCallback(void *data) +{ + struct timer_data *timer_data = data; + int delay; + + if (!timer_data->running) + { + return; + } + + // Read data until we must make a delay. + + for (;;) + { + int reg, val; + + // End of file? + + if (feof(timer_data->fstream)) + { + timer_data->running = 0; + return; + } + + reg = fgetc(timer_data->fstream); + val = fgetc(timer_data->fstream); + + // Register value of 0 or 1 indicates a delay. + + if (reg == 0x00) + { + delay = val; + break; + } + else if (reg == 0x01) + { + val |= (fgetc(timer_data->fstream) << 8); + delay = val; + break; + } + else + { + WriteReg(reg, val); + } + } + + // Schedule the next timer callback. + + OPL_SetCallback(delay * OPL_MS, TimerCallback, timer_data); +} + +void PlayFile(char *filename) +{ + struct timer_data timer_data; + int running; + char buf[8]; + + timer_data.fstream = fopen(filename, "rb"); + + if (timer_data.fstream == NULL) + { + fprintf(stderr, "Failed to open %s\n", filename); + exit(-1); + } + + if (fread(buf, 1, 8, timer_data.fstream) < 8) + { + fprintf(stderr, "failed to read raw OPL header\n"); + exit(-1); + } + + if (strncmp(buf, HEADER_STRING, 8) != 0) + { + fprintf(stderr, "Raw OPL header not found\n"); + exit(-1); + } + + fseek(timer_data.fstream, 28, SEEK_SET); + timer_data.running = 1; + + // Start callback loop sequence. + + OPL_SetCallback(0, TimerCallback, &timer_data); + + // Sleep until the playback finishes. + + do + { + OPL_Lock(); + running = timer_data.running; + OPL_Unlock(); + + SDL_Delay(100 * OPL_MS); + } while (running); + + fclose(timer_data.fstream); +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + printf("Usage: %s \n", argv[0]); + exit(-1); + } + + Init(); + + PlayFile(argv[1]); + + ClearAllRegs(); + Shutdown(); + + return 0; +} + diff --git a/games/NXDoom/opl/ioperm_sys.c b/games/NXDoom/opl/ioperm_sys.c new file mode 100644 index 00000000000..6d0c63a5c9c --- /dev/null +++ b/games/NXDoom/opl/ioperm_sys.c @@ -0,0 +1,355 @@ +// +// Copyright(C) 2002, 2003 Marcel Telka +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Interface to the ioperm.sys driver, based on code from the +// Cygwin ioperm library. +// + +#ifdef _WIN32 + +#include + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include + +#include "ioperm_sys.h" + +#define IOPERM_FILE L"\\\\.\\ioperm" + +#define IOCTL_IOPERM \ + CTL_CODE(FILE_DEVICE_UNKNOWN, 0xA00, METHOD_BUFFERED, FILE_ANY_ACCESS) + +struct ioperm_data +{ + unsigned long from; + unsigned long num; + int turn_on; +}; + +// Function pointers for advapi32.dll. This DLL does not exist on +// Windows 9x, so they are dynamically loaded from the DLL at runtime. + +// haleyjd 09/09/10: Moved calling conventions into ()'s + +static SC_HANDLE (WINAPI *MyOpenSCManagerW)(wchar_t *lpMachineName, + wchar_t *lpDatabaseName, + DWORD dwDesiredAccess) = NULL; +static SC_HANDLE (WINAPI *MyCreateServiceW)(SC_HANDLE hSCManager, + wchar_t *lpServiceName, + wchar_t *lpDisplayName, + DWORD dwDesiredAccess, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + wchar_t *lpBinaryPathName, + wchar_t *lpLoadOrderGroup, + LPDWORD lpdwTagId, + wchar_t *lpDependencies, + wchar_t *lpServiceStartName, + wchar_t *lpPassword); +static SC_HANDLE (WINAPI *MyOpenServiceW)(SC_HANDLE hSCManager, + wchar_t *lpServiceName, + DWORD dwDesiredAccess); +static BOOL (WINAPI *MyStartServiceW)(SC_HANDLE hService, + DWORD dwNumServiceArgs, + wchar_t **lpServiceArgVectors); +static BOOL (WINAPI *MyControlService)(SC_HANDLE hService, + DWORD dwControl, + LPSERVICE_STATUS lpServiceStatus); +static BOOL (WINAPI *MyCloseServiceHandle)(SC_HANDLE hSCObject); +static BOOL (WINAPI *MyDeleteService)(SC_HANDLE hService); + +static struct +{ + char *name; + void **fn; +} dll_functions[] = { + { "OpenSCManagerW", (void **) &MyOpenSCManagerW }, + { "CreateServiceW", (void **) &MyCreateServiceW }, + { "OpenServiceW", (void **) &MyOpenServiceW }, + { "StartServiceW", (void **) &MyStartServiceW }, + { "ControlService", (void **) &MyControlService }, + { "CloseServiceHandle", (void **) &MyCloseServiceHandle }, + { "DeleteService", (void **) &MyDeleteService }, +}; + +// Globals + +static SC_HANDLE scm = NULL; +static SC_HANDLE svc = NULL; +static int service_was_created = 0; +static int service_was_started = 0; + +static int LoadLibraryPointers(void) +{ + HMODULE dll; + int i; + + // Already loaded? + + if (MyOpenSCManagerW != NULL) + { + return 1; + } + + dll = LoadLibraryW(L"advapi32.dll"); + + if (dll == NULL) + { + fprintf(stderr, "LoadLibraryPointers: Failed to open advapi32.dll\n"); + return 0; + } + + for (i = 0; i < sizeof(dll_functions) / sizeof(*dll_functions); ++i) + { + *dll_functions[i].fn = GetProcAddress(dll, dll_functions[i].name); + + if (*dll_functions[i].fn == NULL) + { + fprintf(stderr, "LoadLibraryPointers: Failed to get address " + "for '%s'\n", dll_functions[i].name); + return 0; + } + } + + return 1; +} + +int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on) +{ + HANDLE h; + struct ioperm_data ioperm_data; + DWORD BytesReturned; + BOOL r; + + h = CreateFileW(IOPERM_FILE, GENERIC_READ, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (h == INVALID_HANDLE_VALUE) + { + errno = ENODEV; + return -1; + } + + ioperm_data.from = from; + ioperm_data.num = num; + ioperm_data.turn_on = turn_on; + + r = DeviceIoControl(h, IOCTL_IOPERM, + &ioperm_data, sizeof ioperm_data, + NULL, 0, + &BytesReturned, NULL); + + if (!r) + { + errno = EPERM; + } + + CloseHandle(h); + + return r != 0; +} + +// Load ioperm.sys driver. +// Returns 1 for success, 0 for failure. +// Remember to call IOperm_UninstallDriver to uninstall the driver later. + +int IOperm_InstallDriver(void) +{ + wchar_t driver_path[MAX_PATH]; + int error; + int result = 1; + + if (!LoadLibraryPointers()) + { + return 0; + } + + scm = MyOpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if (scm == NULL) + { + error = GetLastError(); + fprintf(stderr, "IOperm_InstallDriver: OpenSCManager failed (%i).\n", + error); + return 0; + } + + // Get the full path to the driver file. + + GetFullPathNameW(L"ioperm.sys", MAX_PATH, driver_path, NULL); + + // Create the service. + + svc = MyCreateServiceW(scm, + L"ioperm", + L"ioperm support for Cygwin driver", + SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, + driver_path, + NULL, + NULL, + NULL, + NULL, + NULL); + + if (svc == NULL) + { + error = GetLastError(); + + if (error != ERROR_SERVICE_EXISTS) + { + fprintf(stderr, + "IOperm_InstallDriver: Failed to create service (%i).\n", + error); + } + else + { + svc = MyOpenServiceW(scm, L"ioperm", SERVICE_ALL_ACCESS); + + if (svc == NULL) + { + error = GetLastError(); + + fprintf(stderr, + "IOperm_InstallDriver: Failed to open service (%i).\n", + error); + } + } + + if (svc == NULL) + { + MyCloseServiceHandle(scm); + return 0; + } + } + else + { + service_was_created = 1; + } + + // Start the service. If the service already existed, it might have + // already been running as well. + + if (!MyStartServiceW(svc, 0, NULL)) + { + error = GetLastError(); + + if (error != ERROR_SERVICE_ALREADY_RUNNING) + { + fprintf(stderr, "IOperm_InstallDriver: Failed to start service (%i).\n", + error); + + result = 0; + } + else + { + printf("IOperm_InstallDriver: ioperm driver already running.\n"); + } + } + else + { + printf("IOperm_InstallDriver: ioperm driver installed.\n"); + service_was_started = 1; + } + + // If we failed to start the driver running, we need to clean up + // before finishing. + + if (result == 0) + { + IOperm_UninstallDriver(); + } + + return result; +} + +int IOperm_UninstallDriver(void) +{ + SERVICE_STATUS stat; + int result = 1; + int error; + + // If we started the service, stop it. + + if (service_was_started) + { + if (!MyControlService(svc, SERVICE_CONTROL_STOP, &stat)) + { + error = GetLastError(); + + if (error == ERROR_SERVICE_NOT_ACTIVE) + { + fprintf(stderr, + "IOperm_UninstallDriver: Service not active? (%i)\n", + error); + } + else + { + fprintf(stderr, + "IOperm_UninstallDriver: Failed to stop service (%i).\n", + error); + result = 0; + } + } + } + + // If we created the service, delete it. + + if (service_was_created) + { + if (!MyDeleteService(svc)) + { + error = GetLastError(); + + fprintf(stderr, + "IOperm_UninstallDriver: DeleteService failed (%i).\n", + error); + + result = 0; + } + else if (service_was_started) + { + printf("IOperm_UnInstallDriver: ioperm driver uninstalled.\n"); + } + } + + // Close handles. + + if (svc != NULL) + { + MyCloseServiceHandle(svc); + svc = NULL; + } + + if (scm != NULL) + { + MyCloseServiceHandle(scm); + scm = NULL; + } + + service_was_created = 0; + service_was_started = 0; + + return result; +} + +#endif /* #ifndef _WIN32 */ + diff --git a/games/NXDoom/opl/ioperm_sys.h b/games/NXDoom/opl/ioperm_sys.h new file mode 100644 index 00000000000..1a27c3f122f --- /dev/null +++ b/games/NXDoom/opl/ioperm_sys.h @@ -0,0 +1,28 @@ +// +// Copyright(C) 2002, 2003 Marcel Telka +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Interface to the ioperm.sys driver, based on code from the +// Cygwin ioperm library. +// + +#ifndef IOPERM_SYS_H +#define IOPERM_SYS_H + +int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on); +int IOperm_InstallDriver(void); +int IOperm_UninstallDriver(void); + +#endif /* #ifndef IOPERM_SYS_H */ + diff --git a/games/NXDoom/opl/opl.c b/games/NXDoom/opl/opl.c new file mode 100644 index 00000000000..e99821cbb16 --- /dev/null +++ b/games/NXDoom/opl/opl.c @@ -0,0 +1,530 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL interface. +// + +#include "config.h" + +#include +#include +#include + +#include "SDL.h" + +#include "opl.h" +#include "opl_internal.h" + +//#define OPL_DEBUG_TRACE + +#ifdef EMSCRIPTEN +#include +#endif + + +static opl_driver_t *drivers[] = +{ +#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) + &opl_linux_driver, +#endif +#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64) + &opl_openbsd_driver, +#endif +#ifdef _WIN32 + &opl_win32_driver, +#endif +#ifndef DISABLE_SDL2MIXER + &opl_sdl_driver, +#endif // DISABLE_SDL2MIXER + NULL +}; + +static opl_driver_t *driver = NULL; +static int init_stage_reg_writes = 1; + +unsigned int opl_sample_rate = 22050; + +// +// Init/shutdown code. +// + +// Initialize the specified driver and detect an OPL chip. Returns +// true if an OPL is detected. + +static opl_init_result_t InitDriver(opl_driver_t *_driver, + unsigned int port_base) +{ + opl_init_result_t result1, result2; + + // Initialize the driver. + + if (!_driver->init_func(port_base)) + { + return OPL_INIT_NONE; + } + + // The driver was initialized okay, so we now have somewhere + // to write to. It doesn't mean there's an OPL chip there, + // though. Perform the detection sequence to make sure. + // (it's done twice, like how Doom does it). + + driver = _driver; + init_stage_reg_writes = 1; + + result1 = OPL_Detect(); + result2 = OPL_Detect(); + if (result1 == OPL_INIT_NONE || result2 == OPL_INIT_NONE) + { + printf("OPL_Init: No OPL detected using '%s' driver.\n", _driver->name); + _driver->shutdown_func(); + driver = NULL; + return OPL_INIT_NONE; + } + + init_stage_reg_writes = 0; + + printf("OPL_Init: Using driver '%s'.\n", driver->name); + + return result2; +} + +// Find a driver automatically by trying each in the list. + +static opl_init_result_t AutoSelectDriver(unsigned int port_base) +{ + int i; + opl_init_result_t result; + + for (i = 0; drivers[i] != NULL; ++i) + { + result = InitDriver(drivers[i], port_base); + if (result != OPL_INIT_NONE) + { + return result; + } + } + + printf("OPL_Init: Failed to find a working driver.\n"); + + return OPL_INIT_NONE; +} + +// Initialize the OPL library. Return value indicates type of OPL chip +// detected, if any. + +opl_init_result_t OPL_Init(unsigned int port_base) +{ + char *driver_name; + int i; + int result; + + driver_name = getenv("OPL_DRIVER"); + + if (driver_name != NULL) + { + // Search the list until we find the driver with this name. + + for (i=0; drivers[i] != NULL; ++i) + { + if (!strcmp(driver_name, drivers[i]->name)) + { + result = InitDriver(drivers[i], port_base); + if (result) + { + return result; + } + else + { + printf("OPL_Init: Failed to initialize " + "driver: '%s'.\n", driver_name); + return OPL_INIT_NONE; + } + } + } + + printf("OPL_Init: unknown driver: '%s'.\n", driver_name); + + return OPL_INIT_NONE; + } + else + { + return AutoSelectDriver(port_base); + } +} + +// Shut down the OPL library. + +void OPL_Shutdown(void) +{ + if (driver != NULL) + { + driver->shutdown_func(); + driver = NULL; + } +} + +// Set the sample rate used for software OPL emulation. + +void OPL_SetSampleRate(unsigned int rate) +{ + opl_sample_rate = rate; +} + +void OPL_WritePort(opl_port_t port, unsigned int value) +{ + if (driver != NULL) + { +#ifdef OPL_DEBUG_TRACE + printf("OPL_write: %i, %x\n", port, value); + fflush(stdout); +#endif + driver->write_port_func(port, value); + } +} + +unsigned int OPL_ReadPort(opl_port_t port) +{ + if (driver != NULL) + { + unsigned int result; + +#ifdef OPL_DEBUG_TRACE + printf("OPL_read: %i...\n", port); + fflush(stdout); +#endif + + result = driver->read_port_func(port); + +#ifdef OPL_DEBUG_TRACE + printf("OPL_read: %i -> %x\n", port, result); + fflush(stdout); +#endif + + return result; + } + else + { + return 0; + } +} + +// +// Higher-level functions, based on the lower-level functions above +// (register write, etc). +// + +unsigned int OPL_ReadStatus(void) +{ + return OPL_ReadPort(OPL_REGISTER_PORT); +} + +// Write an OPL register value + +void OPL_WriteRegister(int reg, int value) +{ + int i; + + if (reg & 0x100) + { + OPL_WritePort(OPL_REGISTER_PORT_OPL3, reg); + } + else + { + OPL_WritePort(OPL_REGISTER_PORT, reg); + } + + // For timing, read the register port six times after writing the + // register number to cause the appropriate delay + + for (i=0; i<6; ++i) + { + // An oddity of the Doom OPL code: at startup initialization, + // the spacing here is performed by reading from the register + // port; after initialization, the data port is read, instead. + + if (init_stage_reg_writes) + { + OPL_ReadPort(OPL_REGISTER_PORT); + } + else + { + OPL_ReadPort(OPL_DATA_PORT); + } + } + + OPL_WritePort(OPL_DATA_PORT, value); + + // Read the register port 24 times after writing the value to + // cause the appropriate delay + + for (i=0; i<24; ++i) + { + OPL_ReadStatus(); + } +} + +// Detect the presence of an OPL chip + +opl_init_result_t OPL_Detect(void) +{ + int result1, result2; + int i; + + // Reset both timers: + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); + + // Enable interrupts: + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); + + // Read status + result1 = OPL_ReadStatus(); + + // Set timer: + OPL_WriteRegister(OPL_REG_TIMER1, 0xff); + + // Start timer 1: + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x21); + + // Wait for 80 microseconds + // This is how Doom does it: + + for (i=0; i<200; ++i) + { + OPL_ReadStatus(); + } + + OPL_Delay(1 * OPL_MS); + + // Read status + result2 = OPL_ReadStatus(); + + // Reset both timers: + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); + + // Enable interrupts: + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); + + if ((result1 & 0xe0) == 0x00 && (result2 & 0xe0) == 0xc0) + { + result1 = OPL_ReadPort(OPL_REGISTER_PORT); + result2 = OPL_ReadPort(OPL_REGISTER_PORT_OPL3); + if (result1 == 0x00) + { + return OPL_INIT_OPL3; + } + else + { + return OPL_INIT_OPL2; + } + } + else + { + return OPL_INIT_NONE; + } +} + +// Initialize registers on startup + +void OPL_InitRegisters(int opl3) +{ + int r; + + // Initialize level registers + + for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) + { + OPL_WriteRegister(r, 0x3f); + } + + // Initialize other registers + // These two loops write to registers that actually don't exist, + // but this is what Doom does ... + // Similarly, the <= is also intenational. + + for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) + { + OPL_WriteRegister(r, 0x00); + } + + // More registers ... + + for (r=1; r < OPL_REGS_LEVEL; ++r) + { + OPL_WriteRegister(r, 0x00); + } + + // Re-initialize the low registers: + + // Reset both timers and enable interrupts: + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); + OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); + + // "Allow FM chips to control the waveform of each operator": + OPL_WriteRegister(OPL_REG_WAVEFORM_ENABLE, 0x20); + + if (opl3) + { + OPL_WriteRegister(OPL_REG_NEW, 0x01); + + // Initialize level registers + + for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) + { + OPL_WriteRegister(r | 0x100, 0x3f); + } + + // Initialize other registers + // These two loops write to registers that actually don't exist, + // but this is what Doom does ... + // Similarly, the <= is also intenational. + + for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) + { + OPL_WriteRegister(r | 0x100, 0x00); + } + + // More registers ... + + for (r=1; r < OPL_REGS_LEVEL; ++r) + { + OPL_WriteRegister(r | 0x100, 0x00); + } + } + + // Keyboard split point on (?) + OPL_WriteRegister(OPL_REG_FM_MODE, 0x40); + + if (opl3) + { + OPL_WriteRegister(OPL_REG_NEW, 0x01); + } +} + +// +// Timer functions. +// + +void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data) +{ + if (driver != NULL) + { + driver->set_callback_func(us, callback, data); + } +} + +void OPL_ClearCallbacks(void) +{ + if (driver != NULL) + { + driver->clear_callbacks_func(); + } +} + +void OPL_Lock(void) +{ + if (driver != NULL) + { + driver->lock_func(); + } +} + +void OPL_Unlock(void) +{ + if (driver != NULL) + { + driver->unlock_func(); + } +} + +typedef struct +{ + int finished; + + SDL_mutex *mutex; + SDL_cond *cond; +} delay_data_t; + +static void DelayCallback(void *_delay_data) +{ + delay_data_t *delay_data = _delay_data; + + SDL_LockMutex(delay_data->mutex); + delay_data->finished = 1; + + SDL_CondSignal(delay_data->cond); + + SDL_UnlockMutex(delay_data->mutex); +} + +// Delay for specified number of microseconds after OPL subsystem is initialized + +void OPL_Delay(uint64_t us) +{ + delay_data_t delay_data; + + if (driver == NULL) + { + return; + } + + // Create a callback that will signal this thread after the + // specified time. + + // Note that this is not just a simple time-based delay, it will ensure + // that the OPL system is initialized and the queue has begun processing + // before releasing the mutex lock + + delay_data.finished = 0; + delay_data.mutex = SDL_CreateMutex(); + delay_data.cond = SDL_CreateCond(); + + OPL_SetCallback(us, DelayCallback, &delay_data); + + // Wait until the callback is invoked. + + SDL_LockMutex(delay_data.mutex); + + while (!delay_data.finished) + { + SDL_CondWait(delay_data.cond, delay_data.mutex); +#ifdef EMSCRIPTEN + // Use async sleep to avoid locking browser main thread + emscripten_sleep(us / 1000); +#endif + } + + SDL_UnlockMutex(delay_data.mutex); + + // Clean up. + + SDL_DestroyMutex(delay_data.mutex); + SDL_DestroyCond(delay_data.cond); +} + +void OPL_SetPaused(int paused) +{ + if (driver != NULL) + { + driver->set_paused_func(paused); + } +} + +void OPL_AdjustCallbacks(float value) +{ + if (driver != NULL) + { + driver->adjust_callbacks_func(value); + } +} + diff --git a/games/NXDoom/opl/opl.h b/games/NXDoom/opl/opl.h new file mode 100644 index 00000000000..deaa442dde2 --- /dev/null +++ b/games/NXDoom/opl/opl.h @@ -0,0 +1,153 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL interface. +// + + +#ifndef OPL_OPL_H +#define OPL_OPL_H + +#include + +typedef void (*opl_callback_t)(void *data); + +// Result from OPL_Init(), indicating what type of OPL chip was detected, +// if any. +typedef enum +{ + OPL_INIT_NONE, + OPL_INIT_OPL2, + OPL_INIT_OPL3, +} opl_init_result_t; + +typedef enum +{ + OPL_REGISTER_PORT = 0, + OPL_DATA_PORT = 1, + OPL_REGISTER_PORT_OPL3 = 2 +} opl_port_t; + +#define OPL_NUM_OPERATORS 21 +#define OPL_NUM_VOICES 9 + +#define OPL_REG_WAVEFORM_ENABLE 0x01 +#define OPL_REG_TIMER1 0x02 +#define OPL_REG_TIMER2 0x03 +#define OPL_REG_TIMER_CTRL 0x04 +#define OPL_REG_FM_MODE 0x08 +#define OPL_REG_NEW 0x105 + +// Operator registers (21 of each): + +#define OPL_REGS_TREMOLO 0x20 +#define OPL_REGS_LEVEL 0x40 +#define OPL_REGS_ATTACK 0x60 +#define OPL_REGS_SUSTAIN 0x80 +#define OPL_REGS_WAVEFORM 0xE0 + +// Voice registers (9 of each): + +#define OPL_REGS_FREQ_1 0xA0 +#define OPL_REGS_FREQ_2 0xB0 +#define OPL_REGS_FEEDBACK 0xC0 + +// Times + +#define OPL_SECOND ((uint64_t) 1000 * 1000) +#define OPL_MS ((uint64_t) 1000) +#define OPL_US ((uint64_t) 1) + +// +// Low-level functions. +// + +// Initialize the OPL subsystem. + +opl_init_result_t OPL_Init(unsigned int port_base); + +// Shut down the OPL subsystem. + +void OPL_Shutdown(void); + +// Set the sample rate used for software emulation. + +void OPL_SetSampleRate(unsigned int rate); + +// Write to one of the OPL I/O ports: + +void OPL_WritePort(opl_port_t port, unsigned int value); + +// Read from one of the OPL I/O ports: + +unsigned int OPL_ReadPort(opl_port_t port); + +// +// Higher-level functions. +// + +// Read the cuurrent status byte of the OPL chip. + +unsigned int OPL_ReadStatus(void); + +// Write to an OPL register. + +void OPL_WriteRegister(int reg, int value); + +// Perform a detection sequence to determine that an +// OPL chip is present. + +opl_init_result_t OPL_Detect(void); + +// Initialize all registers, performed on startup. + +void OPL_InitRegisters(int opl3); + +// +// Timer callback functions. +// + +// Set a timer callback. After the specified number of microseconds +// have elapsed, the callback will be invoked. + +void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data); + +// Adjust callback times by the specified factor. For example, a value of +// 0.5 will halve all remaining times. + +void OPL_AdjustCallbacks(float factor); + +// Clear all OPL callbacks that have been set. + +void OPL_ClearCallbacks(void); + +// Begin critical section, during which, OPL callbacks will not be +// invoked. + +void OPL_Lock(void); + +// End critical section. + +void OPL_Unlock(void); + +// Block until the specified number of microseconds have elapsed. + +void OPL_Delay(uint64_t us); + +// Pause the OPL callbacks. + +void OPL_SetPaused(int paused); + +#endif + diff --git a/games/NXDoom/opl/opl3.c b/games/NXDoom/opl/opl3.c new file mode 100644 index 00000000000..f5bca4c4e04 --- /dev/null +++ b/games/NXDoom/opl/opl3.c @@ -0,0 +1,1377 @@ +// +// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) +// +// 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. +// +// +// Nuked OPL3 emulator. +// Thanks: +// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): +// Feedback and Rhythm part calculation information. +// forums.submarine.org.uk(carbon14, opl3): +// Tremolo and phase generator calculation information. +// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): +// OPL2 ROMs. +// siliconpr0n.org(John McMaster, digshadow): +// YMF262 and VRC VII decaps and die shots. +// +// version: 1.8 +// + +#include +#include +#include +#include "opl3.h" + +#define RSM_FRAC 10 + +// Channel types + +enum { + ch_2op = 0, + ch_4op = 1, + ch_4op2 = 2, + ch_drum = 3 +}; + +// Envelope key types + +enum { + egk_norm = 0x01, + egk_drum = 0x02 +}; + + +// +// logsin table +// + +static const Bit16u logsinrom[256] = { + 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, + 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365, + 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, + 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261, + 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, + 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd, + 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, + 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166, + 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, + 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118, + 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, + 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db, + 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, + 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9, + 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, + 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081, + 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, + 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060, + 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, + 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045, + 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, + 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f, + 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, + 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e, + 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, + 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011, + 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, + 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007, + 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, + 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002, + 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 +}; + +// +// exp table +// + +static const Bit16u exprom[256] = { + 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, + 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9, + 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f, + 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756, + 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e, + 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706, + 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0, + 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba, + 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695, + 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671, + 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e, + 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b, + 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609, + 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8, + 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8, + 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8, + 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589, + 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b, + 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d, + 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530, + 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514, + 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8, + 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc, + 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2, + 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8, + 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e, + 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475, + 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d, + 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445, + 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d, + 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416, + 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 +}; + +// +// freq mult table multiplied by 2 +// +// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 +// + +static const Bit8u mt[16] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 +}; + +// +// ksl table +// + +static const Bit8u kslrom[16] = { + 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 +}; + +static const Bit8u kslshift[4] = { + 8, 1, 2, 0 +}; + +// +// envelope generator constants +// + +static const Bit8u eg_incstep[4][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } +}; + +// +// address decoding +// + +static const Bit8s ad_slot[0x20] = { + 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, + 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const Bit8u ch_slot[18] = { + 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 +}; + +// +// Envelope generator +// + +typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope); +typedef void(*envelope_genfunc)(opl3_slot *slott); + +static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) +{ + if (level > 0x1fff) + { + level = 0x1fff; + } + return (exprom[level & 0xff] << 1) >> (level >> 8); +} + +static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + Bit16u neg = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + neg = 0xffff; + } + if (phase & 0x100) + { + out = logsinrom[(phase & 0xff) ^ 0xff]; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; +} + +static Bit16s OPL3_EnvelopeCalcSin1(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + out = 0x1000; + } + else if (phase & 0x100) + { + out = logsinrom[(phase & 0xff) ^ 0xff]; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin2(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x100) + { + out = logsinrom[(phase & 0xff) ^ 0xff]; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin3(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x100) + { + out = 0x1000; + } + else + { + out = logsinrom[phase & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + Bit16u neg = 0; + phase &= 0x3ff; + if ((phase & 0x300) == 0x100) + { + neg = 0xffff; + } + if (phase & 0x200) + { + out = 0x1000; + } + else if (phase & 0x80) + { + out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + } + else + { + out = logsinrom[(phase << 1) & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; +} + +static Bit16s OPL3_EnvelopeCalcSin5(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + out = 0x1000; + } + else if (phase & 0x80) + { + out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + } + else + { + out = logsinrom[(phase << 1) & 0xff]; + } + return OPL3_EnvelopeCalcExp(out + (envelope << 3)); +} + +static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope) +{ + Bit16u neg = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + neg = 0xffff; + } + return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg; +} + +static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope) +{ + Bit16u out = 0; + Bit16u neg = 0; + phase &= 0x3ff; + if (phase & 0x200) + { + neg = 0xffff; + phase = (phase & 0x1ff) ^ 0x1ff; + } + out = phase << 3; + return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; +} + +static const envelope_sinfunc envelope_sin[8] = { + OPL3_EnvelopeCalcSin0, + OPL3_EnvelopeCalcSin1, + OPL3_EnvelopeCalcSin2, + OPL3_EnvelopeCalcSin3, + OPL3_EnvelopeCalcSin4, + OPL3_EnvelopeCalcSin5, + OPL3_EnvelopeCalcSin6, + OPL3_EnvelopeCalcSin7 +}; + +enum envelope_gen_num +{ + envelope_gen_num_attack = 0, + envelope_gen_num_decay = 1, + envelope_gen_num_sustain = 2, + envelope_gen_num_release = 3 +}; + +static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) +{ + Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) + - ((0x08 - slot->channel->block) << 5); + if (ksl < 0) + { + ksl = 0; + } + slot->eg_ksl = (Bit8u)ksl; +} + +static void OPL3_EnvelopeCalc(opl3_slot *slot) +{ + Bit8u nonzero; + Bit8u rate; + Bit8u rate_hi; + Bit8u rate_lo; + Bit8u reg_rate = 0; + Bit8u ks; + Bit8u eg_shift, shift; + Bit16u eg_rout; + Bit16s eg_inc; + Bit8u eg_off; + Bit8u reset = 0; + slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; + if (slot->key && slot->eg_gen == envelope_gen_num_release) + { + reset = 1; + reg_rate = slot->reg_ar; + } + else + { + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + reg_rate = slot->reg_ar; + break; + case envelope_gen_num_decay: + reg_rate = slot->reg_dr; + break; + case envelope_gen_num_sustain: + if (!slot->reg_type) + { + reg_rate = slot->reg_rr; + } + break; + case envelope_gen_num_release: + reg_rate = slot->reg_rr; + break; + } + } + slot->pg_reset = reset; + ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); + nonzero = (reg_rate != 0); + rate = ks + (reg_rate << 2); + rate_hi = rate >> 2; + rate_lo = rate & 0x03; + if (rate_hi & 0x10) + { + rate_hi = 0x0f; + } + eg_shift = rate_hi + slot->chip->eg_add; + shift = 0; + if (nonzero) + { + if (rate_hi < 12) + { + if (slot->chip->eg_state) + { + switch (eg_shift) + { + case 12: + shift = 1; + break; + case 13: + shift = (rate_lo >> 1) & 0x01; + break; + case 14: + shift = rate_lo & 0x01; + break; + default: + break; + } + } + } + else + { + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; + if (shift & 0x04) + { + shift = 0x03; + } + if (!shift) + { + shift = slot->chip->eg_state; + } + } + } + eg_rout = slot->eg_rout; + eg_inc = 0; + eg_off = 0; + // Instant attack + if (reset && rate_hi == 0x0f) + { + eg_rout = 0x00; + } + // Envelope off + if ((slot->eg_rout & 0x1f8) == 0x1f8) + { + eg_off = 1; + } + if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) + { + eg_rout = 0x1ff; + } + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + if (!slot->eg_rout) + { + slot->eg_gen = envelope_gen_num_decay; + } + else if (slot->key && shift > 0 && rate_hi != 0x0f) + { + eg_inc = ((~slot->eg_rout) << shift) >> 4; + } + break; + case envelope_gen_num_decay: + if ((slot->eg_rout >> 4) == slot->reg_sl) + { + slot->eg_gen = envelope_gen_num_sustain; + } + else if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + case envelope_gen_num_sustain: + case envelope_gen_num_release: + if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + } + slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; + // Key off + if (reset) + { + slot->eg_gen = envelope_gen_num_attack; + } + if (!slot->key) + { + slot->eg_gen = envelope_gen_num_release; + } +} + +static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) +{ + slot->key |= type; +} + +static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) +{ + slot->key &= ~type; +} + +// +// Phase Generator +// + +static void OPL3_PhaseGenerate(opl3_slot *slot) +{ + opl3_chip *chip; + Bit16u f_num; + Bit32u basefreq; + Bit8u rm_xor, n_bit; + Bit32u noise; + Bit16u phase; + + chip = slot->chip; + f_num = slot->channel->f_num; + if (slot->reg_vib) + { + Bit8s range; + Bit8u vibpos; + + range = (f_num >> 7) & 7; + vibpos = slot->chip->vibpos; + + if (!(vibpos & 3)) + { + range = 0; + } + else if (vibpos & 1) + { + range >>= 1; + } + range >>= slot->chip->vibshift; + + if (vibpos & 4) + { + range = -range; + } + f_num += range; + } + basefreq = (f_num << slot->channel->block) >> 1; + phase = (Bit16u)(slot->pg_phase >> 9); + if (slot->pg_reset) + { + slot->pg_phase = 0; + } + slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; + // Rhythm mode + noise = chip->noise; + slot->pg_phase_out = phase; + if (slot->slot_num == 13) // hh + { + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; + } + if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc + { + chip->rm_tc_bit3 = (phase >> 3) & 1; + chip->rm_tc_bit5 = (phase >> 5) & 1; + } + if (chip->rhy & 0x20) + { + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); + switch (slot->slot_num) + { + case 13: // hh + slot->pg_phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + { + slot->pg_phase_out |= 0xd0; + } + else + { + slot->pg_phase_out |= 0x34; + } + break; + case 16: // sd + slot->pg_phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); + break; + case 17: // tc + slot->pg_phase_out = (rm_xor << 9) | 0x80; + break; + default: + break; + } + } + n_bit = ((noise >> 14) ^ noise) & 0x01; + chip->noise = (noise >> 1) | (n_bit << 22); +} + +// +// Slot +// + +static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) +{ + if ((data >> 7) & 0x01) + { + slot->trem = &slot->chip->tremolo; + } + else + { + slot->trem = (Bit8u*)&slot->chip->zeromod; + } + slot->reg_vib = (data >> 6) & 0x01; + slot->reg_type = (data >> 5) & 0x01; + slot->reg_ksr = (data >> 4) & 0x01; + slot->reg_mult = data & 0x0f; +} + +static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) +{ + slot->reg_ksl = (data >> 6) & 0x03; + slot->reg_tl = data & 0x3f; + OPL3_EnvelopeUpdateKSL(slot); +} + +static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) +{ + slot->reg_ar = (data >> 4) & 0x0f; + slot->reg_dr = data & 0x0f; +} + +static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) +{ + slot->reg_sl = (data >> 4) & 0x0f; + if (slot->reg_sl == 0x0f) + { + slot->reg_sl = 0x1f; + } + slot->reg_rr = data & 0x0f; +} + +static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) +{ + slot->reg_wf = data & 0x07; + if (slot->chip->newm == 0x00) + { + slot->reg_wf &= 0x03; + } +} + +static void OPL3_SlotGenerate(opl3_slot *slot) +{ + slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); +} + +static void OPL3_SlotCalcFB(opl3_slot *slot) +{ + if (slot->channel->fb != 0x00) + { + slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb); + } + else + { + slot->fbmod = 0; + } + slot->prout = slot->out; +} + +// +// Channel +// + +static void OPL3_ChannelSetupAlg(opl3_channel *channel); + +static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) +{ + opl3_channel *channel6; + opl3_channel *channel7; + opl3_channel *channel8; + Bit8u chnum; + + chip->rhy = data & 0x3f; + if (chip->rhy & 0x20) + { + channel6 = &chip->channel[6]; + channel7 = &chip->channel[7]; + channel8 = &chip->channel[8]; + channel6->out[0] = &channel6->slots[1]->out; + channel6->out[1] = &channel6->slots[1]->out; + channel6->out[2] = &chip->zeromod; + channel6->out[3] = &chip->zeromod; + channel7->out[0] = &channel7->slots[0]->out; + channel7->out[1] = &channel7->slots[0]->out; + channel7->out[2] = &channel7->slots[1]->out; + channel7->out[3] = &channel7->slots[1]->out; + channel8->out[0] = &channel8->slots[0]->out; + channel8->out[1] = &channel8->slots[0]->out; + channel8->out[2] = &channel8->slots[1]->out; + channel8->out[3] = &channel8->slots[1]->out; + for (chnum = 6; chnum < 9; chnum++) + { + chip->channel[chnum].chtype = ch_drum; + } + OPL3_ChannelSetupAlg(channel6); + OPL3_ChannelSetupAlg(channel7); + OPL3_ChannelSetupAlg(channel8); + //hh + if (chip->rhy & 0x01) + { + OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum); + } + //tc + if (chip->rhy & 0x02) + { + OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum); + } + //tom + if (chip->rhy & 0x04) + { + OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum); + } + //sd + if (chip->rhy & 0x08) + { + OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum); + } + //bd + if (chip->rhy & 0x10) + { + OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum); + } + else + { + OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum); + } + } + else + { + for (chnum = 6; chnum < 9; chnum++) + { + chip->channel[chnum].chtype = ch_2op; + OPL3_ChannelSetupAlg(&chip->channel[chnum]); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[0], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[1], egk_drum); + } + } +} + +static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) +{ + if (channel->chip->newm && channel->chtype == ch_4op2) + { + return; + } + channel->f_num = (channel->f_num & 0x300) | data; + channel->ksv = (channel->block << 1) + | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); + OPL3_EnvelopeUpdateKSL(channel->slots[0]); + OPL3_EnvelopeUpdateKSL(channel->slots[1]); + if (channel->chip->newm && channel->chtype == ch_4op) + { + channel->pair->f_num = channel->f_num; + channel->pair->ksv = channel->ksv; + OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); + } +} + +static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) +{ + if (channel->chip->newm && channel->chtype == ch_4op2) + { + return; + } + channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8); + channel->block = (data >> 2) & 0x07; + channel->ksv = (channel->block << 1) + | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); + OPL3_EnvelopeUpdateKSL(channel->slots[0]); + OPL3_EnvelopeUpdateKSL(channel->slots[1]); + if (channel->chip->newm && channel->chtype == ch_4op) + { + channel->pair->f_num = channel->f_num; + channel->pair->block = channel->block; + channel->pair->ksv = channel->ksv; + OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); + } +} + +static void OPL3_ChannelSetupAlg(opl3_channel *channel) +{ + if (channel->chtype == ch_drum) + { + if (channel->ch_num == 7 || channel->ch_num == 8) + { + channel->slots[0]->mod = &channel->chip->zeromod; + channel->slots[1]->mod = &channel->chip->zeromod; + return; + } + switch (channel->alg & 0x01) + { + case 0x00: + channel->slots[0]->mod = &channel->slots[0]->fbmod; + channel->slots[1]->mod = &channel->slots[0]->out; + break; + case 0x01: + channel->slots[0]->mod = &channel->slots[0]->fbmod; + channel->slots[1]->mod = &channel->chip->zeromod; + break; + } + return; + } + if (channel->alg & 0x08) + { + return; + } + if (channel->alg & 0x04) + { + channel->pair->out[0] = &channel->chip->zeromod; + channel->pair->out[1] = &channel->chip->zeromod; + channel->pair->out[2] = &channel->chip->zeromod; + channel->pair->out[3] = &channel->chip->zeromod; + switch (channel->alg & 0x03) + { + case 0x00: + channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; + channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; + channel->slots[0]->mod = &channel->pair->slots[1]->out; + channel->slots[1]->mod = &channel->slots[0]->out; + channel->out[0] = &channel->slots[1]->out; + channel->out[1] = &channel->chip->zeromod; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x01: + channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; + channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; + channel->slots[0]->mod = &channel->chip->zeromod; + channel->slots[1]->mod = &channel->slots[0]->out; + channel->out[0] = &channel->pair->slots[1]->out; + channel->out[1] = &channel->slots[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x02: + channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; + channel->pair->slots[1]->mod = &channel->chip->zeromod; + channel->slots[0]->mod = &channel->pair->slots[1]->out; + channel->slots[1]->mod = &channel->slots[0]->out; + channel->out[0] = &channel->pair->slots[0]->out; + channel->out[1] = &channel->slots[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x03: + channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; + channel->pair->slots[1]->mod = &channel->chip->zeromod; + channel->slots[0]->mod = &channel->pair->slots[1]->out; + channel->slots[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->pair->slots[0]->out; + channel->out[1] = &channel->slots[0]->out; + channel->out[2] = &channel->slots[1]->out; + channel->out[3] = &channel->chip->zeromod; + break; + } + } + else + { + switch (channel->alg & 0x01) + { + case 0x00: + channel->slots[0]->mod = &channel->slots[0]->fbmod; + channel->slots[1]->mod = &channel->slots[0]->out; + channel->out[0] = &channel->slots[1]->out; + channel->out[1] = &channel->chip->zeromod; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + case 0x01: + channel->slots[0]->mod = &channel->slots[0]->fbmod; + channel->slots[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->slots[0]->out; + channel->out[1] = &channel->slots[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; + break; + } + } +} + +static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) +{ + channel->fb = (data & 0x0e) >> 1; + channel->con = data & 0x01; + channel->alg = channel->con; + if (channel->chip->newm) + { + if (channel->chtype == ch_4op) + { + channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con); + channel->alg = 0x08; + OPL3_ChannelSetupAlg(channel->pair); + } + else if (channel->chtype == ch_4op2) + { + channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con); + channel->pair->alg = 0x08; + OPL3_ChannelSetupAlg(channel); + } + else + { + OPL3_ChannelSetupAlg(channel); + } + } + else + { + OPL3_ChannelSetupAlg(channel); + } + if (channel->chip->newm) + { + channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; + channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; + } + else + { + channel->cha = channel->chb = (Bit16u)~0; + } +} + +static void OPL3_ChannelKeyOn(opl3_channel *channel) +{ + if (channel->chip->newm) + { + if (channel->chtype == ch_4op) + { + OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm); + } + else if (channel->chtype == ch_2op || channel->chtype == ch_drum) + { + OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + } + } + else + { + OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); + } +} + +static void OPL3_ChannelKeyOff(opl3_channel *channel) +{ + if (channel->chip->newm) + { + if (channel->chtype == ch_4op) + { + OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm); + } + else if (channel->chtype == ch_2op || channel->chtype == ch_drum) + { + OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + } + } + else + { + OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); + } +} + +static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data) +{ + Bit8u bit; + Bit8u chnum; + for (bit = 0; bit < 6; bit++) + { + chnum = bit; + if (bit >= 3) + { + chnum += 9 - 3; + } + if ((data >> bit) & 0x01) + { + chip->channel[chnum].chtype = ch_4op; + chip->channel[chnum + 3].chtype = ch_4op2; + } + else + { + chip->channel[chnum].chtype = ch_2op; + chip->channel[chnum + 3].chtype = ch_2op; + } + } +} + +static Bit16s OPL3_ClipSample(Bit32s sample) +{ + if (sample > 32767) + { + sample = 32767; + } + else if (sample < -32768) + { + sample = -32768; + } + return (Bit16s)sample; +} + +void OPL3_Generate(opl3_chip *chip, Bit16s *buf) +{ + Bit8u ii; + Bit8u jj; + Bit16s accm; + Bit8u shift = 0; + + buf[1] = OPL3_ClipSample(chip->mixbuff[1]); + + for (ii = 0; ii < 15; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + chip->mixbuff[0] = 0; + for (ii = 0; ii < 18; ii++) + { + accm = 0; + for (jj = 0; jj < 4; jj++) + { + accm += *chip->channel[ii].out[jj]; + } + chip->mixbuff[0] += (Bit16s)(accm & chip->channel[ii].cha); + } + + for (ii = 15; ii < 18; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + buf[0] = OPL3_ClipSample(chip->mixbuff[0]); + + for (ii = 18; ii < 33; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + chip->mixbuff[1] = 0; + for (ii = 0; ii < 18; ii++) + { + accm = 0; + for (jj = 0; jj < 4; jj++) + { + accm += *chip->channel[ii].out[jj]; + } + chip->mixbuff[1] += (Bit16s)(accm & chip->channel[ii].chb); + } + + for (ii = 33; ii < 36; ii++) + { + OPL3_SlotCalcFB(&chip->slot[ii]); + OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); + } + + if ((chip->timer & 0x3f) == 0x3f) + { + chip->tremolopos = (chip->tremolopos + 1) % 210; + } + if (chip->tremolopos < 105) + { + chip->tremolo = chip->tremolopos >> chip->tremoloshift; + } + else + { + chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift; + } + + if ((chip->timer & 0x3ff) == 0x3ff) + { + chip->vibpos = (chip->vibpos + 1) & 7; + } + + chip->timer++; + + chip->eg_add = 0; + if (chip->eg_timer) + { + while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) + { + shift++; + } + if (shift > 12) + { + chip->eg_add = 0; + } + else + { + chip->eg_add = shift + 1; + } + } + + if (chip->eg_timerrem || chip->eg_state) + { + if (chip->eg_timer == 0xfffffffff) + { + chip->eg_timer = 0; + chip->eg_timerrem = 1; + } + else + { + chip->eg_timer++; + chip->eg_timerrem = 0; + } + } + + chip->eg_state ^= 1; + + while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) + { + if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200)) + { + break; + } + chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, + chip->writebuf[chip->writebuf_cur].data); + chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; + } + chip->writebuf_samplecnt++; +} + +void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) +{ + while (chip->samplecnt >= chip->rateratio) + { + chip->oldsamples[0] = chip->samples[0]; + chip->oldsamples[1] = chip->samples[1]; + OPL3_Generate(chip, chip->samples); + chip->samplecnt -= chip->rateratio; + } + buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + + chip->samples[0] * chip->samplecnt) / chip->rateratio); + buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + + chip->samples[1] * chip->samplecnt) / chip->rateratio); + chip->samplecnt += 1 << RSM_FRAC; +} + +void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) +{ + Bit8u slotnum; + Bit8u channum; + + memset(chip, 0, sizeof(opl3_chip)); + for (slotnum = 0; slotnum < 36; slotnum++) + { + chip->slot[slotnum].chip = chip; + chip->slot[slotnum].mod = &chip->zeromod; + chip->slot[slotnum].eg_rout = 0x1ff; + chip->slot[slotnum].eg_out = 0x1ff; + chip->slot[slotnum].eg_gen = envelope_gen_num_release; + chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod; + chip->slot[slotnum].slot_num = slotnum; + } + for (channum = 0; channum < 18; channum++) + { + chip->channel[channum].slots[0] = &chip->slot[ch_slot[channum]]; + chip->channel[channum].slots[1] = &chip->slot[ch_slot[channum] + 3]; + chip->slot[ch_slot[channum]].channel = &chip->channel[channum]; + chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum]; + if ((channum % 9) < 3) + { + chip->channel[channum].pair = &chip->channel[channum + 3]; + } + else if ((channum % 9) < 6) + { + chip->channel[channum].pair = &chip->channel[channum - 3]; + } + chip->channel[channum].chip = chip; + chip->channel[channum].out[0] = &chip->zeromod; + chip->channel[channum].out[1] = &chip->zeromod; + chip->channel[channum].out[2] = &chip->zeromod; + chip->channel[channum].out[3] = &chip->zeromod; + chip->channel[channum].chtype = ch_2op; + chip->channel[channum].cha = 0xffff; + chip->channel[channum].chb = 0xffff; + chip->channel[channum].ch_num = channum; + OPL3_ChannelSetupAlg(&chip->channel[channum]); + } + chip->noise = 1; + chip->rateratio = (samplerate << RSM_FRAC) / 49716; + chip->tremoloshift = 4; + chip->vibshift = 1; +} + +void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) +{ + Bit8u high = (reg >> 8) & 0x01; + Bit8u regm = reg & 0xff; + switch (regm & 0xf0) + { + case 0x00: + if (high) + { + switch (regm & 0x0f) + { + case 0x04: + OPL3_ChannelSet4Op(chip, v); + break; + case 0x05: + chip->newm = v & 0x01; + break; + } + } + else + { + switch (regm & 0x0f) + { + case 0x08: + chip->nts = (v >> 6) & 0x01; + break; + } + } + break; + case 0x20: + case 0x30: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0x40: + case 0x50: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0x60: + case 0x70: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0x80: + case 0x90: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0xe0: + case 0xf0: + if (ad_slot[regm & 0x1f] >= 0) + { + OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); + } + break; + case 0xa0: + if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v); + } + break; + case 0xb0: + if (regm == 0xbd && !high) + { + chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2; + chip->vibshift = ((v >> 6) & 0x01) ^ 1; + OPL3_ChannelUpdateRhythm(chip, v); + } + else if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v); + if (v & 0x20) + { + OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]); + } + else + { + OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]); + } + } + break; + case 0xc0: + if ((regm & 0x0f) < 9) + { + OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v); + } + break; + } +} + +void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) +{ + Bit64u time1, time2; + + if (chip->writebuf[chip->writebuf_last].reg & 0x200) + { + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, + chip->writebuf[chip->writebuf_last].data); + + chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; + } + + chip->writebuf[chip->writebuf_last].reg = reg | 0x200; + chip->writebuf[chip->writebuf_last].data = v; + time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; + time2 = chip->writebuf_samplecnt; + + if (time1 < time2) + { + time1 = time2; + } + + chip->writebuf[chip->writebuf_last].time = time1; + chip->writebuf_lasttime = time1; + chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; +} + +void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) +{ + Bit32u i; + + for(i = 0; i < numsamples; i++) + { + OPL3_GenerateResampled(chip, sndptr); + sndptr += 2; + } +} diff --git a/games/NXDoom/opl/opl3.h b/games/NXDoom/opl/opl3.h new file mode 100644 index 00000000000..2a64037a5ab --- /dev/null +++ b/games/NXDoom/opl/opl3.h @@ -0,0 +1,150 @@ +// +// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) +// +// 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. +// +// +// Nuked OPL3 emulator. +// Thanks: +// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): +// Feedback and Rhythm part calculation information. +// forums.submarine.org.uk(carbon14, opl3): +// Tremolo and phase generator calculation information. +// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): +// OPL2 ROMs. +// siliconpr0n.org(John McMaster, digshadow): +// YMF262 and VRC VII decaps and die shots. +// +// version: 1.8 +// + +#ifndef OPL_OPL3_H +#define OPL_OPL3_H + +#include + +#define OPL_WRITEBUF_SIZE 1024 +#define OPL_WRITEBUF_DELAY 2 + +typedef uintptr_t Bitu; +typedef intptr_t Bits; +typedef uint64_t Bit64u; +typedef int64_t Bit64s; +typedef uint32_t Bit32u; +typedef int32_t Bit32s; +typedef uint16_t Bit16u; +typedef int16_t Bit16s; +typedef uint8_t Bit8u; +typedef int8_t Bit8s; + +typedef struct _opl3_slot opl3_slot; +typedef struct _opl3_channel opl3_channel; +typedef struct _opl3_chip opl3_chip; + +struct _opl3_slot { + opl3_channel *channel; + opl3_chip *chip; + Bit16s out; + Bit16s fbmod; + Bit16s *mod; + Bit16s prout; + Bit16s eg_rout; + Bit16s eg_out; + Bit8u eg_inc; + Bit8u eg_gen; + Bit8u eg_rate; + Bit8u eg_ksl; + Bit8u *trem; + Bit8u reg_vib; + Bit8u reg_type; + Bit8u reg_ksr; + Bit8u reg_mult; + Bit8u reg_ksl; + Bit8u reg_tl; + Bit8u reg_ar; + Bit8u reg_dr; + Bit8u reg_sl; + Bit8u reg_rr; + Bit8u reg_wf; + Bit8u key; + Bit32u pg_reset; + Bit32u pg_phase; + Bit16u pg_phase_out; + Bit8u slot_num; +}; + +struct _opl3_channel { + opl3_slot *slots[2]; + opl3_channel *pair; + opl3_chip *chip; + Bit16s *out[4]; + Bit8u chtype; + Bit16u f_num; + Bit8u block; + Bit8u fb; + Bit8u con; + Bit8u alg; + Bit8u ksv; + Bit16u cha, chb; + Bit8u ch_num; +}; + +typedef struct _opl3_writebuf { + Bit64u time; + Bit16u reg; + Bit8u data; +} opl3_writebuf; + +struct _opl3_chip { + opl3_channel channel[18]; + opl3_slot slot[36]; + Bit16u timer; + Bit64u eg_timer; + Bit8u eg_timerrem; + Bit8u eg_state; + Bit8u eg_add; + Bit8u newm; + Bit8u nts; + Bit8u rhy; + Bit8u vibpos; + Bit8u vibshift; + Bit8u tremolo; + Bit8u tremolopos; + Bit8u tremoloshift; + Bit32u noise; + Bit16s zeromod; + Bit32s mixbuff[2]; + Bit8u rm_hh_bit2; + Bit8u rm_hh_bit3; + Bit8u rm_hh_bit7; + Bit8u rm_hh_bit8; + Bit8u rm_tc_bit3; + Bit8u rm_tc_bit5; + //OPL3L + Bit32s rateratio; + Bit32s samplecnt; + Bit16s oldsamples[2]; + Bit16s samples[2]; + + Bit64u writebuf_samplecnt; + Bit32u writebuf_cur; + Bit32u writebuf_last; + Bit64u writebuf_lasttime; + opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; +}; + +void OPL3_Generate(opl3_chip *chip, Bit16s *buf); +void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf); +void OPL3_Reset(opl3_chip *chip, Bit32u samplerate); +void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); +void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); +#endif diff --git a/games/NXDoom/opl/opl_internal.h b/games/NXDoom/opl/opl_internal.h new file mode 100644 index 00000000000..68fd0b82f19 --- /dev/null +++ b/games/NXDoom/opl/opl_internal.h @@ -0,0 +1,71 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL internal interface. +// + + +#ifndef OPL_INTERNAL_H +#define OPL_INTERNAL_H + +#include "opl.h" + +typedef int (*opl_init_func)(unsigned int port_base); +typedef void (*opl_shutdown_func)(void); +typedef unsigned int (*opl_read_port_func)(opl_port_t port); +typedef void (*opl_write_port_func)(opl_port_t port, unsigned int value); +typedef void (*opl_set_callback_func)(uint64_t us, + opl_callback_t callback, + void *data); +typedef void (*opl_clear_callbacks_func)(void); +typedef void (*opl_lock_func)(void); +typedef void (*opl_unlock_func)(void); +typedef void (*opl_set_paused_func)(int paused); +typedef void (*opl_adjust_callbacks_func)(float value); + +typedef struct +{ + const char *name; + + opl_init_func init_func; + opl_shutdown_func shutdown_func; + opl_read_port_func read_port_func; + opl_write_port_func write_port_func; + opl_set_callback_func set_callback_func; + opl_clear_callbacks_func clear_callbacks_func; + opl_lock_func lock_func; + opl_unlock_func unlock_func; + opl_set_paused_func set_paused_func; + opl_adjust_callbacks_func adjust_callbacks_func; +} opl_driver_t; + +// Sample rate to use when doing software emulation. + +extern unsigned int opl_sample_rate; + + +#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) +extern opl_driver_t opl_linux_driver; +#endif +#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64) +extern opl_driver_t opl_openbsd_driver; +#endif +#ifdef _WIN32 +extern opl_driver_t opl_win32_driver; +#endif +extern opl_driver_t opl_sdl_driver; + + +#endif /* #ifndef OPL_INTERNAL_H */ + diff --git a/games/NXDoom/opl/opl_linux.c b/games/NXDoom/opl/opl_linux.c new file mode 100644 index 00000000000..03160fa1bfc --- /dev/null +++ b/games/NXDoom/opl/opl_linux.c @@ -0,0 +1,103 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL Linux interface. +// + +#include "config.h" + +#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) + +#include +#include +#include +#include +#include + +#include "opl.h" +#include "opl_internal.h" +#include "opl_timer.h" + +static unsigned int opl_port_base; + +static int OPL_Linux_Init(unsigned int port_base) +{ + // Try to get permissions: + + if (ioperm(port_base, 3, 1) < 0) + { + fprintf(stderr, "Failed to get I/O port permissions for 0x%x: %s\n", + port_base, strerror(errno)); + + if (errno == EPERM) + { + fprintf(stderr, + "\tYou may need to run the program as root in order\n" + "\tto acquire I/O port permissions for OPL MIDI playback.\n"); + } + + return 0; + } + + opl_port_base = port_base; + + // Start callback thread + + if (!OPL_Timer_StartThread()) + { + ioperm(port_base, 2, 0); + return 0; + } + + return 1; +} + +static void OPL_Linux_Shutdown(void) +{ + // Stop callback thread + + OPL_Timer_StopThread(); + + // Release permissions + + ioperm(opl_port_base, 2, 0); +} + +static unsigned int OPL_Linux_PortRead(opl_port_t port) +{ + return inb(opl_port_base + port); +} + +static void OPL_Linux_PortWrite(opl_port_t port, unsigned int value) +{ + outb(value, opl_port_base + port); +} + +opl_driver_t opl_linux_driver = +{ + "Linux", + OPL_Linux_Init, + OPL_Linux_Shutdown, + OPL_Linux_PortRead, + OPL_Linux_PortWrite, + OPL_Timer_SetCallback, + OPL_Timer_ClearCallbacks, + OPL_Timer_Lock, + OPL_Timer_Unlock, + OPL_Timer_SetPaused, + OPL_Timer_AdjustCallbacks, +}; + +#endif /* #if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) */ + diff --git a/games/NXDoom/opl/opl_obsd.c b/games/NXDoom/opl/opl_obsd.c new file mode 100644 index 00000000000..39e0c156066 --- /dev/null +++ b/games/NXDoom/opl/opl_obsd.c @@ -0,0 +1,118 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL OpenBSD interface (also NetBSD) +// + +#include "config.h" + +// OpenBSD has a i386_iopl on i386 and amd64_iopl on x86_64, +// even though they do the same thing. Take care of this +// here, and map set_iopl to point to the appropriate name. + +#if defined(HAVE_LIBI386) + +#include +#include +#include +#define set_iopl i386_iopl + +#elif defined(HAVE_LIBAMD64) + +#include +#include +#include +#define set_iopl amd64_iopl + +#else +#define NO_OBSD_DRIVER +#endif + +// If the above succeeded, proceed with the rest. + +#ifndef NO_OBSD_DRIVER + +#include +#include +#include +#include + +#include "opl.h" +#include "opl_internal.h" +#include "opl_timer.h" + +static unsigned int opl_port_base; + +static int OPL_OpenBSD_Init(unsigned int port_base) +{ + // Try to get permissions: + + if (set_iopl(3) < 0) + { + fprintf(stderr, "Failed to get raise I/O privilege level: " + "check that you are running as root.\n"); + return 0; + } + + opl_port_base = port_base; + + // Start callback thread + + if (!OPL_Timer_StartThread()) + { + set_iopl(0); + return 0; + } + + return 1; +} + +static void OPL_OpenBSD_Shutdown(void) +{ + // Stop callback thread + + OPL_Timer_StopThread(); + + // Release I/O port permissions: + + set_iopl(0); +} + +static unsigned int OPL_OpenBSD_PortRead(opl_port_t port) +{ + return inb(opl_port_base + port); +} + +static void OPL_OpenBSD_PortWrite(opl_port_t port, unsigned int value) +{ + outb(opl_port_base + port, value); +} + +opl_driver_t opl_openbsd_driver = +{ + "OpenBSD", + OPL_OpenBSD_Init, + OPL_OpenBSD_Shutdown, + OPL_OpenBSD_PortRead, + OPL_OpenBSD_PortWrite, + OPL_Timer_SetCallback, + OPL_Timer_ClearCallbacks, + OPL_Timer_Lock, + OPL_Timer_Unlock, + OPL_Timer_SetPaused, + OPL_Timer_AdjustCallbacks, +}; + +#endif /* #ifndef NO_OBSD_DRIVER */ + diff --git a/games/NXDoom/opl/opl_queue.c b/games/NXDoom/opl/opl_queue.c new file mode 100644 index 00000000000..e948b641315 --- /dev/null +++ b/games/NXDoom/opl/opl_queue.c @@ -0,0 +1,285 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Queue of waiting callbacks, stored in a binary min heap, so that we +// can always get the first callback. +// + +#include +#include +#include + +#include "opl_queue.h" + +#define MAX_OPL_QUEUE 64 + +typedef struct +{ + opl_callback_t callback; + void *data; + uint64_t time; +} opl_queue_entry_t; + +struct opl_callback_queue_s +{ + opl_queue_entry_t entries[MAX_OPL_QUEUE]; + unsigned int num_entries; +}; + +opl_callback_queue_t *OPL_Queue_Create(void) +{ + opl_callback_queue_t *queue; + + queue = malloc(sizeof(opl_callback_queue_t)); + queue->num_entries = 0; + + return queue; +} + +void OPL_Queue_Destroy(opl_callback_queue_t *queue) +{ + free(queue); +} + +int OPL_Queue_IsEmpty(opl_callback_queue_t *queue) +{ + return queue->num_entries == 0; +} + +void OPL_Queue_Clear(opl_callback_queue_t *queue) +{ + queue->num_entries = 0; +} + +void OPL_Queue_Push(opl_callback_queue_t *queue, + opl_callback_t callback, void *data, + uint64_t time) +{ + int entry_id; + int parent_id; + + if (queue->num_entries >= MAX_OPL_QUEUE) + { + fprintf(stderr, "OPL_Queue_Push: Exceeded maximum callbacks\n"); + return; + } + + // Add to last queue entry. + + entry_id = queue->num_entries; + ++queue->num_entries; + + // Shift existing entries down in the heap. + + while (entry_id > 0) + { + parent_id = (entry_id - 1) / 2; + + // Is the heap condition satisfied? + + if (time >= queue->entries[parent_id].time) + { + break; + } + + // Move the existing entry down in the heap. + + memcpy(&queue->entries[entry_id], + &queue->entries[parent_id], + sizeof(opl_queue_entry_t)); + + // Advance to the parent. + + entry_id = parent_id; + } + + // Insert new callback data. + + queue->entries[entry_id].callback = callback; + queue->entries[entry_id].data = data; + queue->entries[entry_id].time = time; +} + +int OPL_Queue_Pop(opl_callback_queue_t *queue, + opl_callback_t *callback, void **data) +{ + opl_queue_entry_t *entry; + int child1, child2; + int i, next_i; + + // Empty? + + if (queue->num_entries <= 0) + { + return 0; + } + + // Store the result: + + *callback = queue->entries[0].callback; + *data = queue->entries[0].data; + + // Decrease the heap size, and keep pointer to the last entry in + // the heap, which must now be percolated down from the top. + + --queue->num_entries; + entry = &queue->entries[queue->num_entries]; + + // Percolate down. + + i = 0; + + for (;;) + { + child1 = i * 2 + 1; + child2 = i * 2 + 2; + + if (child1 < queue->num_entries + && queue->entries[child1].time < entry->time) + { + // Left child is less than entry. + // Use the minimum of left and right children. + + if (child2 < queue->num_entries + && queue->entries[child2].time < queue->entries[child1].time) + { + next_i = child2; + } + else + { + next_i = child1; + } + } + else if (child2 < queue->num_entries + && queue->entries[child2].time < entry->time) + { + // Right child is less than entry. Go down the right side. + + next_i = child2; + } + else + { + // Finished percolating. + break; + } + + // Percolate the next value up and advance. + + memcpy(&queue->entries[i], + &queue->entries[next_i], + sizeof(opl_queue_entry_t)); + i = next_i; + } + + // Store the old last-entry at its new position. + + memcpy(&queue->entries[i], entry, sizeof(opl_queue_entry_t)); + + return 1; +} + +uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue) +{ + if (queue->num_entries > 0) + { + return queue->entries[0].time; + } + else + { + return 0; + } +} + +void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue, + uint64_t time, float factor) +{ + int64_t offset; + int i; + + for (i = 0; i < queue->num_entries; ++i) + { + offset = queue->entries[i].time - time; + queue->entries[i].time = time + (uint64_t) (offset / factor); + } +} + +#ifdef TEST + +#include + +static void PrintQueueNode(opl_callback_queue_t *queue, int node, int depth) +{ + int i; + + if (node >= queue->num_entries) + { + return; + } + + for (i=0; ientries[node].time); + + PrintQueueNode(queue, node * 2 + 1, depth + 1); + PrintQueueNode(queue, node * 2 + 2, depth + 1); +} + +static void PrintQueue(opl_callback_queue_t *queue) +{ + PrintQueueNode(queue, 0, 0); +} + +int main() +{ + opl_callback_queue_t *queue; + int iteration; + + queue = OPL_Queue_Create(); + + for (iteration=0; iteration<5000; ++iteration) + { + opl_callback_t callback; + void *data; + unsigned int time; + unsigned int newtime; + int i; + + for (i=0; i= time); + time = newtime; + } + + assert(OPL_Queue_IsEmpty(queue)); + assert(!OPL_Queue_Pop(queue, &callback, &data)); + } +} + +#endif + diff --git a/games/NXDoom/opl/opl_queue.h b/games/NXDoom/opl/opl_queue.h new file mode 100644 index 00000000000..8b4f0dbee36 --- /dev/null +++ b/games/NXDoom/opl/opl_queue.h @@ -0,0 +1,39 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL callback queue. +// + +#ifndef OPL_QUEUE_H +#define OPL_QUEUE_H + +#include "opl.h" + +typedef struct opl_callback_queue_s opl_callback_queue_t; + +opl_callback_queue_t *OPL_Queue_Create(void); +int OPL_Queue_IsEmpty(opl_callback_queue_t *queue); +void OPL_Queue_Clear(opl_callback_queue_t *queue); +void OPL_Queue_Destroy(opl_callback_queue_t *queue); +void OPL_Queue_Push(opl_callback_queue_t *queue, + opl_callback_t callback, void *data, + uint64_t time); +int OPL_Queue_Pop(opl_callback_queue_t *queue, + opl_callback_t *callback, void **data); +uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue); +void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue, + uint64_t time, float factor); + +#endif /* #ifndef OPL_QUEUE_H */ + diff --git a/games/NXDoom/opl/opl_sdl.c b/games/NXDoom/opl/opl_sdl.c new file mode 100644 index 00000000000..2517de15c0a --- /dev/null +++ b/games/NXDoom/opl/opl_sdl.c @@ -0,0 +1,521 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL SDL interface. +// + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "SDL.h" +#ifndef DISABLE_SDL2MIXER +#include "SDL_mixer.h" +#endif // DISABLE_SDL2MIXER + +#include "opl3.h" + +#include "opl.h" +#include "opl_internal.h" + +#include "opl_queue.h" + + +#ifndef DISABLE_SDL2MIXER + + +#define MAX_SOUND_SLICE_TIME 100 /* ms */ + +typedef struct +{ + unsigned int rate; // Number of times the timer is advanced per sec. + unsigned int enabled; // Non-zero if timer is enabled. + unsigned int value; // Last value that was set. + uint64_t expire_time; // Calculated time that timer will expire. +} opl_timer_t; + +// When the callback mutex is locked using OPL_Lock, callback functions +// are not invoked. + +static SDL_mutex *callback_mutex = NULL; + +// Queue of callbacks waiting to be invoked. + +static opl_callback_queue_t *callback_queue; + +// Mutex used to control access to the callback queue. + +static SDL_mutex *callback_queue_mutex = NULL; + +// Current time, in us since startup: + +static uint64_t current_time; + +// If non-zero, playback is currently paused. + +static int opl_sdl_paused; + +// Time offset (in us) due to the fact that callbacks +// were previously paused. + +static uint64_t pause_offset; + +// OPL software emulator structure. + +static opl3_chip opl_chip; +static int opl_opl3mode; + +// Temporary mixing buffer used by the mixing callback. + +static uint8_t *mix_buffer = NULL; + +// Register number that was written. + +static int register_num = 0; + +// Timers; DBOPL does not do timer stuff itself. + +static opl_timer_t timer1 = { 12500, 0, 0, 0 }; +static opl_timer_t timer2 = { 3125, 0, 0, 0 }; + +// SDL parameters. + +static int sdl_was_initialized = 0; +static int mixing_freq, mixing_channels; +static Uint16 mixing_format; + +static int SDLIsInitialized(void) +{ + int freq, channels; + Uint16 format; + + return Mix_QuerySpec(&freq, &format, &channels); +} + +// Advance time by the specified number of samples, invoking any +// callback functions as appropriate. + +static void AdvanceTime(unsigned int nsamples) +{ + opl_callback_t callback; + void *callback_data; + uint64_t us; + + SDL_LockMutex(callback_queue_mutex); + + // Advance time. + + us = ((uint64_t) nsamples * OPL_SECOND) / mixing_freq; + current_time += us; + + if (opl_sdl_paused) + { + pause_offset += us; + } + + // Are there callbacks to invoke now? Keep invoking them + // until there are no more left. + + while (!OPL_Queue_IsEmpty(callback_queue) + && current_time >= OPL_Queue_Peek(callback_queue) + pause_offset) + { + // Pop the callback from the queue to invoke it. + + if (!OPL_Queue_Pop(callback_queue, &callback, &callback_data)) + { + break; + } + + // The mutex stuff here is a bit complicated. We must + // hold callback_mutex when we invoke the callback (so that + // the control thread can use OPL_Lock() to prevent callbacks + // from being invoked), but we must not be holding + // callback_queue_mutex, as the callback must be able to + // call OPL_SetCallback to schedule new callbacks. + + SDL_UnlockMutex(callback_queue_mutex); + + SDL_LockMutex(callback_mutex); + callback(callback_data); + SDL_UnlockMutex(callback_mutex); + + SDL_LockMutex(callback_queue_mutex); + } + + SDL_UnlockMutex(callback_queue_mutex); +} + +// Call the OPL emulator code to fill the specified buffer. + +static void FillBuffer(uint8_t *buffer, unsigned int nsamples) +{ + // This seems like a reasonable assumption. mix_buffer is + // 1 second long, which should always be much longer than the + // SDL mix buffer. + assert(nsamples < mixing_freq); + + // OPL output is generated into temporary buffer and then mixed + // (to avoid overflows etc.) + OPL3_GenerateStream(&opl_chip, (Bit16s *) mix_buffer, nsamples); + SDL_MixAudioFormat(buffer, mix_buffer, AUDIO_S16SYS, nsamples * 4, + SDL_MIX_MAXVOLUME); +} + +// Callback function to fill a new sound buffer: + +static void OPL_Mix_Callback(int chan, void *stream, int len, void *udata) +{ + unsigned int filled, buffer_samples; + Uint8 *buffer = (Uint8*)stream; + + // Repeatedly call the OPL emulator update function until the buffer is + // full. + filled = 0; + buffer_samples = len / 4; + + while (filled < buffer_samples) + { + uint64_t next_callback_time; + uint64_t nsamples; + + SDL_LockMutex(callback_queue_mutex); + + // Work out the time until the next callback waiting in + // the callback queue must be invoked. We can then fill the + // buffer with this many samples. + + if (opl_sdl_paused || OPL_Queue_IsEmpty(callback_queue)) + { + nsamples = buffer_samples - filled; + } + else + { + next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset; + + nsamples = (next_callback_time - current_time) * mixing_freq; + nsamples = (nsamples + OPL_SECOND - 1) / OPL_SECOND; + + if (nsamples > buffer_samples - filled) + { + nsamples = buffer_samples - filled; + } + } + + SDL_UnlockMutex(callback_queue_mutex); + + // Add emulator output to buffer. + + FillBuffer(buffer + filled * 4, nsamples); + filled += nsamples; + + // Invoke callbacks for this point in time. + + AdvanceTime(nsamples); + } +} + +static void OPL_SDL_Shutdown(void) +{ + Mix_HookMusic(NULL, NULL); + + if (sdl_was_initialized) + { + Mix_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + OPL_Queue_Destroy(callback_queue); + free(mix_buffer); + sdl_was_initialized = 0; + } + +/* + if (opl_chip != NULL) + { + OPLDestroy(opl_chip); + opl_chip = NULL; + } + */ + + if (callback_mutex != NULL) + { + SDL_DestroyMutex(callback_mutex); + callback_mutex = NULL; + } + + if (callback_queue_mutex != NULL) + { + SDL_DestroyMutex(callback_queue_mutex); + callback_queue_mutex = NULL; + } +} + +static unsigned int GetSliceSize(void) +{ + int limit; + int n; + + limit = (opl_sample_rate * MAX_SOUND_SLICE_TIME) / 1000; + + // Try all powers of two, not exceeding the limit. + + for (n=0;; ++n) + { + // 2^n <= limit < 2^n+1 ? + + if ((1 << (n + 1)) > limit) + { + return (1 << n); + } + } + + // Should never happen? + + return 1024; +} + +static int OPL_SDL_Init(unsigned int port_base) +{ + // Check if SDL_mixer has been opened already + // If not, we must initialize it now + + if (!SDLIsInitialized()) + { + if (SDL_Init(SDL_INIT_AUDIO) < 0) + { + fprintf(stderr, "Unable to set up sound.\n"); + return 0; + } + + if (Mix_OpenAudioDevice(opl_sample_rate, AUDIO_S16SYS, 2, GetSliceSize(), NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) + { + fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError()); + + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return 0; + } + + SDL_PauseAudio(0); + + // When this module shuts down, it has the responsibility to + // shut down SDL. + + sdl_was_initialized = 1; + } + else + { + sdl_was_initialized = 0; + } + + opl_sdl_paused = 0; + pause_offset = 0; + + // Queue structure of callbacks to invoke. + + callback_queue = OPL_Queue_Create(); + current_time = 0; + + // Get the mixer frequency, format and number of channels. + + Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels); + + // Only supports AUDIO_S16SYS + + if (mixing_format != AUDIO_S16SYS || mixing_channels != 2) + { + fprintf(stderr, + "OPL_SDL only supports native signed 16-bit LSB, " + "stereo format!\n"); + + OPL_SDL_Shutdown(); + return 0; + } + + // Mix buffer: four bytes per sample (16 bits * 2 channels): + mix_buffer = malloc(mixing_freq * 4); + + // Create the emulator structure: + + OPL3_Reset(&opl_chip, mixing_freq); + opl_opl3mode = 0; + + callback_mutex = SDL_CreateMutex(); + callback_queue_mutex = SDL_CreateMutex(); + + // Set postmix that adds the OPL music. This is deliberately done + // as a postmix and not using Mix_HookMusic() as the latter disables + // normal SDL_mixer music mixing. + Mix_RegisterEffect(MIX_CHANNEL_POST, OPL_Mix_Callback, NULL, NULL); + + return 1; +} + +static unsigned int OPL_SDL_PortRead(opl_port_t port) +{ + unsigned int result = 0; + + if (port == OPL_REGISTER_PORT_OPL3) + { + return 0xff; + } + + if (timer1.enabled && current_time > timer1.expire_time) + { + result |= 0x80; // Either have expired + result |= 0x40; // Timer 1 has expired + } + + if (timer2.enabled && current_time > timer2.expire_time) + { + result |= 0x80; // Either have expired + result |= 0x20; // Timer 2 has expired + } + + return result; +} + +static void OPLTimer_CalculateEndTime(opl_timer_t *timer) +{ + int tics; + + // If the timer is enabled, calculate the time when the timer + // will expire. + + if (timer->enabled) + { + tics = 0x100 - timer->value; + timer->expire_time = current_time + + ((uint64_t) tics * OPL_SECOND) / timer->rate; + } +} + +static void WriteRegister(unsigned int reg_num, unsigned int value) +{ + switch (reg_num) + { + case OPL_REG_TIMER1: + timer1.value = value; + OPLTimer_CalculateEndTime(&timer1); + break; + + case OPL_REG_TIMER2: + timer2.value = value; + OPLTimer_CalculateEndTime(&timer2); + break; + + case OPL_REG_TIMER_CTRL: + if (value & 0x80) + { + timer1.enabled = 0; + timer2.enabled = 0; + } + else + { + if ((value & 0x40) == 0) + { + timer1.enabled = (value & 0x01) != 0; + OPLTimer_CalculateEndTime(&timer1); + } + + if ((value & 0x20) == 0) + { + timer2.enabled = (value & 0x02) != 0; + OPLTimer_CalculateEndTime(&timer2); + } + } + + break; + + case OPL_REG_NEW: + opl_opl3mode = value & 0x01; + + default: + OPL3_WriteRegBuffered(&opl_chip, reg_num, value); + break; + } +} + +static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value) +{ + if (port == OPL_REGISTER_PORT) + { + register_num = value; + } + else if (port == OPL_REGISTER_PORT_OPL3) + { + register_num = value | 0x100; + } + else if (port == OPL_DATA_PORT) + { + WriteRegister(register_num, value); + } +} + +static void OPL_SDL_SetCallback(uint64_t us, opl_callback_t callback, + void *data) +{ + SDL_LockMutex(callback_queue_mutex); + OPL_Queue_Push(callback_queue, callback, data, + current_time - pause_offset + us); + SDL_UnlockMutex(callback_queue_mutex); +} + +static void OPL_SDL_ClearCallbacks(void) +{ + SDL_LockMutex(callback_queue_mutex); + OPL_Queue_Clear(callback_queue); + SDL_UnlockMutex(callback_queue_mutex); +} + +static void OPL_SDL_Lock(void) +{ + SDL_LockMutex(callback_mutex); +} + +static void OPL_SDL_Unlock(void) +{ + SDL_UnlockMutex(callback_mutex); +} + +static void OPL_SDL_SetPaused(int paused) +{ + opl_sdl_paused = paused; +} + +static void OPL_SDL_AdjustCallbacks(float factor) +{ + SDL_LockMutex(callback_queue_mutex); + OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor); + SDL_UnlockMutex(callback_queue_mutex); +} + +opl_driver_t opl_sdl_driver = +{ + "SDL", + OPL_SDL_Init, + OPL_SDL_Shutdown, + OPL_SDL_PortRead, + OPL_SDL_PortWrite, + OPL_SDL_SetCallback, + OPL_SDL_ClearCallbacks, + OPL_SDL_Lock, + OPL_SDL_Unlock, + OPL_SDL_SetPaused, + OPL_SDL_AdjustCallbacks, +}; + + +#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/opl/opl_timer.c b/games/NXDoom/opl/opl_timer.c new file mode 100644 index 00000000000..2c4ce273ea7 --- /dev/null +++ b/games/NXDoom/opl/opl_timer.c @@ -0,0 +1,250 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL timer thread. +// Once started using OPL_Timer_StartThread, the thread sleeps, +// waking up to invoke callbacks set using OPL_Timer_SetCallback. +// + +#include "SDL.h" + +#include "opl_timer.h" +#include "opl_queue.h" + +typedef enum +{ + THREAD_STATE_STOPPED, + THREAD_STATE_RUNNING, + THREAD_STATE_STOPPING, +} thread_state_t; + +static SDL_Thread *timer_thread = NULL; +static thread_state_t timer_thread_state; +static uint64_t current_time; + +// If non-zero, callbacks are currently paused. + +static int opl_timer_paused; + +// Offset in microseconds to adjust time due to the fact that playback +// was paused. + +static uint64_t pause_offset = 0; + +// Queue of callbacks waiting to be invoked. +// The callback queue mutex is held while the callback queue structure +// or current_time is being accessed. + +static opl_callback_queue_t *callback_queue; +static SDL_mutex *callback_queue_mutex; + +// The timer mutex is held while timer callback functions are being +// invoked, so that the calling code can prevent clashes. + +static SDL_mutex *timer_mutex; + +// Returns true if there is a callback at the head of the queue ready +// to be invoked. Otherwise, next_time is set to the time when the +// timer thread must wake up again to check. + +static int CallbackWaiting(uint64_t *next_time) +{ + // If paused, just wait in 50ms increments until unpaused. + // Update pause_offset so after we unpause, the callback + // times will be right. + + if (opl_timer_paused) + { + *next_time = current_time + 50 * OPL_MS; + pause_offset += 50 * OPL_MS; + return 0; + } + + // If there are no queued callbacks, sleep for 50ms at a time + // until a callback is added. + + if (OPL_Queue_IsEmpty(callback_queue)) + { + *next_time = current_time + 50 * OPL_MS; + return 0; + } + + // Read the time of the first callback in the queue. + // If the time for the callback has not yet arrived, + // we must sleep until the callback time. + + *next_time = OPL_Queue_Peek(callback_queue) + pause_offset; + + return *next_time <= current_time; +} + +static uint64_t GetNextTime(void) +{ + opl_callback_t callback; + void *callback_data; + uint64_t next_time; + int have_callback; + + // Keep running through callbacks until there are none ready to + // run. When we run out of callbacks, next_time will be set. + + do + { + SDL_LockMutex(callback_queue_mutex); + + // Check if the callback at the head of the list is ready to + // be invoked. If so, pop from the head of the queue. + + have_callback = CallbackWaiting(&next_time); + + if (have_callback) + { + OPL_Queue_Pop(callback_queue, &callback, &callback_data); + } + + SDL_UnlockMutex(callback_queue_mutex); + + // Now invoke the callback, if we have one. + // The timer mutex is held while the callback is invoked. + + if (have_callback) + { + SDL_LockMutex(timer_mutex); + callback(callback_data); + SDL_UnlockMutex(timer_mutex); + } + } while (have_callback); + + return next_time; +} + +static int ThreadFunction(void *unused) +{ + uint64_t next_time; + uint64_t now; + + // Keep running until OPL_Timer_StopThread is called. + + while (timer_thread_state == THREAD_STATE_RUNNING) + { + // Get the next time that we must sleep until, and + // wait until that time. + + next_time = GetNextTime(); + now = SDL_GetTicks() * OPL_MS; + + if (next_time > now) + { + SDL_Delay((next_time - now) / OPL_MS); + } + + // Update the current time. + + SDL_LockMutex(callback_queue_mutex); + current_time = next_time; + SDL_UnlockMutex(callback_queue_mutex); + } + + timer_thread_state = THREAD_STATE_STOPPED; + + return 0; +} + +static void InitResources(void) +{ + callback_queue = OPL_Queue_Create(); + timer_mutex = SDL_CreateMutex(); + callback_queue_mutex = SDL_CreateMutex(); +} + +static void FreeResources(void) +{ + OPL_Queue_Destroy(callback_queue); + SDL_DestroyMutex(callback_queue_mutex); + SDL_DestroyMutex(timer_mutex); +} + +int OPL_Timer_StartThread(void) +{ + InitResources(); + + timer_thread_state = THREAD_STATE_RUNNING; + current_time = SDL_GetTicks(); + opl_timer_paused = 0; + pause_offset = 0; + + timer_thread = SDL_CreateThread(ThreadFunction, "OPL timer thread", NULL); + + if (timer_thread == NULL) + { + timer_thread_state = THREAD_STATE_STOPPED; + FreeResources(); + + return 0; + } + + return 1; +} + +void OPL_Timer_StopThread(void) +{ + timer_thread_state = THREAD_STATE_STOPPING; + + while (timer_thread_state != THREAD_STATE_STOPPED) + { + SDL_Delay(1); + } + + FreeResources(); +} + +void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data) +{ + SDL_LockMutex(callback_queue_mutex); + OPL_Queue_Push(callback_queue, callback, data, + current_time + us - pause_offset); + SDL_UnlockMutex(callback_queue_mutex); +} + +void OPL_Timer_ClearCallbacks(void) +{ + SDL_LockMutex(callback_queue_mutex); + OPL_Queue_Clear(callback_queue); + SDL_UnlockMutex(callback_queue_mutex); +} + +void OPL_Timer_AdjustCallbacks(float factor) +{ + SDL_LockMutex(callback_queue_mutex); + OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor); + SDL_UnlockMutex(callback_queue_mutex); +} + +void OPL_Timer_Lock(void) +{ + SDL_LockMutex(timer_mutex); +} + +void OPL_Timer_Unlock(void) +{ + SDL_UnlockMutex(timer_mutex); +} + +void OPL_Timer_SetPaused(int paused) +{ + SDL_LockMutex(callback_queue_mutex); + opl_timer_paused = paused; + SDL_UnlockMutex(callback_queue_mutex); +} + diff --git a/games/NXDoom/opl/opl_timer.h b/games/NXDoom/opl/opl_timer.h new file mode 100644 index 00000000000..adf815038df --- /dev/null +++ b/games/NXDoom/opl/opl_timer.h @@ -0,0 +1,33 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL timer thread. +// + +#ifndef OPL_TIMER_H +#define OPL_TIMER_H + +#include "opl.h" + +int OPL_Timer_StartThread(void); +void OPL_Timer_StopThread(void); +void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data); +void OPL_Timer_ClearCallbacks(void); +void OPL_Timer_Lock(void); +void OPL_Timer_Unlock(void); +void OPL_Timer_SetPaused(int paused); +void OPL_Timer_AdjustCallbacks(float factor); + +#endif /* #ifndef OPL_TIMER_H */ + diff --git a/games/NXDoom/opl/opl_win32.c b/games/NXDoom/opl/opl_win32.c new file mode 100644 index 00000000000..f0fd31c3655 --- /dev/null +++ b/games/NXDoom/opl/opl_win32.c @@ -0,0 +1,192 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// OPL Win32 native interface. +// + +#include "config.h" + +#ifdef _WIN32 + +#include + +#define WIN32_LEAN_AND_MEAN +#include + +#include "opl.h" +#include "opl_internal.h" +#include "opl_timer.h" + +#include "ioperm_sys.h" + +static unsigned int opl_port_base; + +// MingW? + +#if defined(__GNUC__) && defined(__i386__) + +static unsigned int OPL_Win32_PortRead(opl_port_t port) +{ + unsigned char result; + + __asm__ volatile ( + "movl %1, %%edx\n" + "inb %%dx, %%al\n" + "movb %%al, %0" + : "=m" (result) + : "r" (opl_port_base + port) + : "edx", "al", "memory" + ); + + return result; +} + +static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) +{ + __asm__ volatile ( + "movl %0, %%edx\n" + "movb %1, %%al\n" + "outb %%al, %%dx" + : + : "r" (opl_port_base + port), "r" ((unsigned char) value) + : "edx", "al" + ); +} + +// haleyjd 20110417: MSVC version +#elif defined(_MSC_VER) && defined(_M_IX86) + +static unsigned int OPL_Win32_PortRead(opl_port_t port) +{ + unsigned char result; + opl_port_t dst_port = opl_port_base + port; + + __asm + { + mov edx, dword ptr [dst_port] + in al, dx + mov byte ptr [result], al + } + + return result; +} + +static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) +{ + opl_port_t dst_port = opl_port_base + port; + + __asm + { + mov edx, dword ptr [dst_port] + mov al, byte ptr [value] + out dx, al + } +} + +#else + +// Not x86, or don't know how to do port R/W on this compiler. + +#define NO_PORT_RW + +static unsigned int OPL_Win32_PortRead(opl_port_t port) +{ + return 0; +} + +static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) +{ +} + +#endif + +static int OPL_Win32_Init(unsigned int port_base) +{ + + OSVERSIONINFO version_info; + + opl_port_base = port_base; + + // Check the OS version. + + memset(&version_info, 0, sizeof(version_info)); + version_info.dwOSVersionInfoSize = sizeof(version_info); + + GetVersionEx(&version_info); + +#ifndef NO_PORT_RW + // On NT-based systems, we must acquire I/O port permissions + // using the ioperm.sys driver. + + if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Install driver. + + if (!IOperm_InstallDriver()) + { + return 0; + } + + // Open port range. + + if (!IOperm_EnablePortRange(opl_port_base, 2, 1)) + { + IOperm_UninstallDriver(); + return 0; + } + } + + // Start callback thread + + if (!OPL_Timer_StartThread()) + { + IOperm_UninstallDriver(); + return 0; + } + + return 1; + +#endif + + return 0; +} + +static void OPL_Win32_Shutdown(void) +{ + // Stop callback thread + + OPL_Timer_StopThread(); + + // Unload IOperm library. + + IOperm_UninstallDriver(); +} + +opl_driver_t opl_win32_driver = +{ + "Win32", + OPL_Win32_Init, + OPL_Win32_Shutdown, + OPL_Win32_PortRead, + OPL_Win32_PortWrite, + OPL_Timer_SetCallback, + OPL_Timer_ClearCallbacks, + OPL_Timer_Lock, + OPL_Timer_Unlock, + OPL_Timer_SetPaused, + OPL_Timer_AdjustCallbacks, +}; + +#endif /* #ifdef _WIN32 */ + diff --git a/games/NXDoom/pcsound/.gitignore b/games/NXDoom/pcsound/.gitignore new file mode 100644 index 00000000000..022c663ee09 --- /dev/null +++ b/games/NXDoom/pcsound/.gitignore @@ -0,0 +1,8 @@ +Makefile.in +Makefile +.deps +libpcsound.a +*.rc +tags +TAGS + diff --git a/games/NXDoom/pcsound/CMakeLists.txt b/games/NXDoom/pcsound/CMakeLists.txt new file mode 100644 index 00000000000..6f199018110 --- /dev/null +++ b/games/NXDoom/pcsound/CMakeLists.txt @@ -0,0 +1,24 @@ +add_library(pcsound STATIC + pcsound.c pcsound.h + pcsound_bsd.c + pcsound_sdl.c + pcsound_linux.c + pcsound_win32.c + pcsound_internal.h) +target_include_directories(pcsound + INTERFACE "." + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") +if (DEFINED EMSCRIPTEN) + if(ENABLE_SDL2_MIXER) + set_target_properties(pcsound PROPERTIES COMPILE_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") + set_target_properties(pcsound PROPERTIES LINK_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") + else() + set_target_properties(pcsound PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") + set_target_properties(pcsound PROPERTIES LINK_FLAGS "-s USE_SDL=2") + endif() +else() + target_link_libraries(pcsound SDL2::SDL2) + if(ENABLE_SDL2_MIXER) + target_link_libraries(pcsound SDL2_mixer::SDL2_mixer) + endif() +endif() diff --git a/games/NXDoom/pcsound/Makefile.am b/games/NXDoom/pcsound/Makefile.am new file mode 100644 index 00000000000..12b2ae49d60 --- /dev/null +++ b/games/NXDoom/pcsound/Makefile.am @@ -0,0 +1,15 @@ + +AM_CFLAGS=@SDLMIXER_CFLAGS@ + +EXTRA_DIST=CMakeLists.txt + +noinst_LIBRARIES=libpcsound.a + +libpcsound_a_SOURCES = \ + pcsound.c pcsound.h \ + pcsound_bsd.c \ + pcsound_sdl.c \ + pcsound_linux.c \ + pcsound_win32.c \ + pcsound_internal.h + diff --git a/games/NXDoom/pcsound/pcsound.c b/games/NXDoom/pcsound/pcsound.c new file mode 100644 index 00000000000..b57fe73a614 --- /dev/null +++ b/games/NXDoom/pcsound/pcsound.c @@ -0,0 +1,119 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker interface. +// + +#include +#include +#include + +#include "config.h" +#include "pcsound.h" +#include "pcsound_internal.h" + + +static pcsound_driver_t *drivers[] = +{ +#ifdef HAVE_LINUX_KD_H + &pcsound_linux_driver, +#endif +#ifdef HAVE_BSD_SPEAKER + &pcsound_bsd_driver, +#endif +#ifdef _WIN32 + &pcsound_win32_driver, +#endif +#ifndef DISABLE_SDL2MIXER + &pcsound_sdl_driver, +#endif // DISABLE_SDL2MIXER + NULL, +}; + +static pcsound_driver_t *pcsound_driver = NULL; + +int pcsound_sample_rate; + +void PCSound_SetSampleRate(int rate) +{ + pcsound_sample_rate = rate; +} + +int PCSound_Init(pcsound_callback_func callback_func) +{ + char *driver_name; + int i; + + if (pcsound_driver != NULL) + { + return 1; + } + + // Check if the environment variable is set + + driver_name = getenv("PCSOUND_DRIVER"); + + if (driver_name != NULL) + { + for (i=0; drivers[i] != NULL; ++i) + { + if (!strcmp(drivers[i]->name, driver_name)) + { + // Found the driver! + + if (drivers[i]->init_func(callback_func)) + { + pcsound_driver = drivers[i]; + } + else + { + printf("Failed to initialize PC sound driver: %s\n", + drivers[i]->name); + break; + } + } + } + } + else + { + // Try all drivers until we find a working one + + for (i=0; drivers[i] != NULL; ++i) + { + if (drivers[i]->init_func(callback_func)) + { + pcsound_driver = drivers[i]; + break; + } + } + } + + if (pcsound_driver != NULL) + { + printf("Using PC sound driver: %s\n", pcsound_driver->name); + return 1; + } + else + { + printf("Failed to find a working PC sound driver.\n"); + return 0; + } +} + +void PCSound_Shutdown(void) +{ + pcsound_driver->shutdown_func(); + pcsound_driver = NULL; +} + diff --git a/games/NXDoom/pcsound/pcsound.h b/games/NXDoom/pcsound/pcsound.h new file mode 100644 index 00000000000..4d567f2400a --- /dev/null +++ b/games/NXDoom/pcsound/pcsound.h @@ -0,0 +1,38 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker interface. +// + +#ifndef PCSOUND_H +#define PCSOUND_H + +typedef void (*pcsound_callback_func)(int *duration, int *frequency); + +// Initialise the PC speaker subsystem. The given function is called +// periodically to request more sound data to play. + +int PCSound_Init(pcsound_callback_func callback_func); + +// Shut down the PC speaker subsystem. + +void PCSound_Shutdown(void); + +// Set the preferred output sample rate when emulating a PC speaker. +// This must be called before PCSound_Init. + +void PCSound_SetSampleRate(int rate); + +#endif /* #ifndef PCSOUND_H */ + diff --git a/games/NXDoom/pcsound/pcsound_bsd.c b/games/NXDoom/pcsound/pcsound_bsd.c new file mode 100644 index 00000000000..a3055e7db62 --- /dev/null +++ b/games/NXDoom/pcsound/pcsound_bsd.c @@ -0,0 +1,321 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker driver for [Open]BSD +// (Should be NetBSD as well, but untested). +// + +#include "config.h" + +// OpenBSD/NetBSD: + +#ifdef HAVE_DEV_ISA_SPKRIO_H +#define HAVE_BSD_SPEAKER +#include +#endif + +// FreeBSD + +#ifdef HAVE_DEV_SPEAKER_SPEAKER_H +#define HAVE_BSD_SPEAKER +#include +#endif + +#ifdef HAVE_BSD_SPEAKER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SDL.h" +#include "SDL_thread.h" + +#include "pcsound.h" +#include "pcsound_internal.h" + +#define SPEAKER_DEVICE "/dev/speaker" + +// +// This driver is far more complicated than it should be, because +// OpenBSD has sucky support for threads. Because multithreading +// is done in userspace, invoking the ioctl to make the speaker +// beep will lock all threads until the beep has completed. +// +// Thus, to get the beeping to occur in real-time, we must invoke +// the ioctl in a separate process. To do this, a separate +// sound server is forked that listens on a socket for tones to +// play. When a tone is received, a reply is sent back to the +// main process and the tone played. +// +// Meanwhile, back in the main process, there is a sound thread +// that runs, invoking the pcsound callback function to get +// more tones. This blocks on the sound server socket, waiting +// for replies. In this way, when the sound server finishes +// playing a tone, the next one is sent. +// +// This driver is a bit less accurate than the others, because +// we can only specify sound durations in 1/100ths of a second, +// as opposed to the normal millisecond durations. + +static pcsound_callback_func callback; +static int sound_server_pid; +static int sleep_adjust = 0; +static int sound_thread_running; +static SDL_Thread *sound_thread_handle; +static int sound_server_pipe[2]; + +// Play a sound, checking how long the system call takes to complete +// and autoadjusting for drift. + +static void AdjustedBeep(int speaker_handle, int ms, int freq) +{ + unsigned int start_time; + unsigned int end_time; + unsigned int actual_time; + tone_t tone; + + // Adjust based on previous error to keep the tempo right + + if (sleep_adjust > ms) + { + sleep_adjust -= ms; + return; + } + else + { + ms -= sleep_adjust; + } + + // Invoke the system call and time how long it takes + + start_time = SDL_GetTicks(); + + tone.duration = ms / 10; // in 100ths of a second + tone.frequency = freq; + + // Always a positive duration + + if (tone.duration < 1) + { + tone.duration = 1; + } + + if (ioctl(speaker_handle, SPKRTONE, &tone) != 0) + { + perror("ioctl"); + return; + } + + end_time = SDL_GetTicks(); + + if (end_time > start_time) + { + actual_time = end_time - start_time; + } + else + { + actual_time = ms; + } + + if (actual_time < ms) + { + actual_time = ms; + } + + // Save sleep_adjust for next time + + sleep_adjust = actual_time - ms; +} + +static void SoundServer(int speaker_handle) +{ + tone_t tone; + int result; + + // Run in a loop, invoking the callback + + for (;;) + { + result = read(sound_server_pipe[1], &tone, sizeof(tone_t)); + + if (result < 0) + { + perror("read"); + return; + } + + // Send back a response, so the main process knows to send another + + write(sound_server_pipe[1], &tone, sizeof(tone_t)); + + // Beep! (blocks until complete) + + AdjustedBeep(speaker_handle, tone.duration, tone.frequency); + } +} + +// Start up the sound server. Returns non-zero if successful. + +static int StartSoundServer(void) +{ + int result; + int speaker_handle; + + // Try to open the speaker device + + speaker_handle = open(SPEAKER_DEVICE, O_WRONLY); + + if (speaker_handle == -1) + { + // Don't have permissions for the console device? + + fprintf(stderr, "StartSoundServer: Failed to open '%s': %s\n", + SPEAKER_DEVICE, strerror(errno)); + return 0; + } + + // Create a pipe for communications + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sound_server_pipe) < 0) + { + perror("socketpair"); + close(speaker_handle); + return 0; + } + + // Start a separate process to generate PC speaker output + // We can't use the SDL threading functions because OpenBSD's + // threading sucks :-( + + result = fork(); + + if (result < 0) + { + fprintf(stderr, "Failed to fork sound server!\n"); + close(speaker_handle); + return 0; + } + else if (result == 0) + { + // This is the child (sound server) + + SoundServer(speaker_handle); + close(speaker_handle); + + exit(0); + } + else + { + // This is the parent + + sound_server_pid = result; + close(speaker_handle); + } + + return 1; +} + +static void StopSoundServer(void) +{ + int status; + + kill(sound_server_pid, SIGINT); + waitpid(sound_server_pid, &status, 0); +} + +static int SoundThread(void *unused) +{ + tone_t tone; + int duration; + int frequency; + + while (sound_thread_running) + { + // Get the next frequency to play + + callback(&duration, &frequency); + +//printf("dur: %i, freq: %i\n", duration, frequency); + + // Build up a tone structure and send to the sound server + + tone.frequency = frequency; + tone.duration = duration; + + if (write(sound_server_pipe[0], &tone, sizeof(tone_t)) < 0) + { + perror("write"); + break; + } + + // Wait until the sound server responds before sending another + + if (read(sound_server_pipe[0], &tone, sizeof(tone_t)) < 0) + { + perror("read"); + break; + } + } + + return 0; +} + +static int PCSound_BSD_Init(pcsound_callback_func callback_func) +{ + callback = callback_func; + + if (!StartSoundServer()) + { + fprintf(stderr, "PCSound_BSD_Init: Failed to start sound server.\n"); + return 0; + } + + sound_thread_running = 1; + sound_thread_handle = + SDL_CreateThread(SoundThread, "PC speaker thread", NULL); + + return 1; +} + +static void PCSound_BSD_Shutdown(void) +{ + // Stop the sound thread + + sound_thread_running = 0; + + SDL_WaitThread(sound_thread_handle, NULL); + + // Stop the sound server + + StopSoundServer(); +} + +pcsound_driver_t pcsound_bsd_driver = +{ + "BSD", + PCSound_BSD_Init, + PCSound_BSD_Shutdown, +}; + +#endif /* #ifdef HAVE_BSD_SPEAKER */ + diff --git a/games/NXDoom/pcsound/pcsound_internal.h b/games/NXDoom/pcsound/pcsound_internal.h new file mode 100644 index 00000000000..7611c595f4c --- /dev/null +++ b/games/NXDoom/pcsound/pcsound_internal.h @@ -0,0 +1,62 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker interface. +// + +#ifndef PCSOUND_INTERNAL_H +#define PCSOUND_INTERNAL_H + +#include "pcsound.h" + +#ifdef HAVE_DEV_ISA_SPKRIO_H +#define HAVE_BSD_SPEAKER +#endif +#ifdef HAVE_DEV_SPEAKER_SPEAKER_H +#define HAVE_BSD_SPEAKER +#endif + +#define PCSOUND_8253_FREQUENCY 1193280 + +typedef struct pcsound_driver_s pcsound_driver_t; +typedef int (*pcsound_init_func)(pcsound_callback_func callback); +typedef void (*pcsound_shutdown_func)(void); + +struct pcsound_driver_s +{ + const char *name; + pcsound_init_func init_func; + pcsound_shutdown_func shutdown_func; +}; + +extern int pcsound_sample_rate; + + +#ifdef _WIN32 +extern pcsound_driver_t pcsound_win32_driver; +#endif + +#ifdef HAVE_BSD_SPEAKER +extern pcsound_driver_t pcsound_bsd_driver; +#endif + +#ifdef HAVE_LINUX_KD_H +extern pcsound_driver_t pcsound_linux_driver; +#endif + +extern pcsound_driver_t pcsound_sdl_driver; + + +#endif /* #ifndef PCSOUND_INTERNAL_H */ + diff --git a/games/NXDoom/pcsound/pcsound_linux.c b/games/NXDoom/pcsound/pcsound_linux.c new file mode 100644 index 00000000000..7cb59c9b9c0 --- /dev/null +++ b/games/NXDoom/pcsound/pcsound_linux.c @@ -0,0 +1,171 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker driver for Linux. +// + +#include "config.h" + +#ifdef HAVE_LINUX_KD_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SDL.h" +#include "SDL_thread.h" + +#include "pcsound.h" +#include "pcsound_internal.h" + +#define CONSOLE_DEVICE "/dev/console" + +static int console_handle; +static pcsound_callback_func callback; +static int sound_thread_running = 0; +static SDL_Thread *sound_thread_handle; +static int sleep_adjust = 0; + +static void AdjustedSleep(unsigned int ms) +{ + unsigned int start_time; + unsigned int end_time; + unsigned int actual_time; + + // Adjust based on previous error to keep the tempo right + + if (sleep_adjust > ms) + { + sleep_adjust -= ms; + return; + } + else + { + ms -= sleep_adjust; + } + + // Do the sleep and record how long it takes + + start_time = SDL_GetTicks(); + + SDL_Delay(ms); + + end_time = SDL_GetTicks(); + + if (end_time > start_time) + { + actual_time = end_time - start_time; + } + else + { + actual_time = ms; + } + + if (actual_time < ms) + { + actual_time = ms; + } + + // Save sleep_adjust for next time + + sleep_adjust = actual_time - ms; +} + +static int SoundThread(void *unused) +{ + int current_freq = 0; + int frequency; + int duration; + int cycles; + + while (sound_thread_running) + { + callback(&duration, &frequency); + + if (current_freq != frequency) + { + current_freq = frequency; + if (frequency != 0) + { + cycles = PCSOUND_8253_FREQUENCY / frequency; + } + else + { + cycles = 0; + } + + ioctl(console_handle, KIOCSOUND, cycles); + } + + AdjustedSleep(duration); + } + + return 0; +} + +static int PCSound_Linux_Init(pcsound_callback_func callback_func) +{ + // Try to open the console + + console_handle = open(CONSOLE_DEVICE, O_WRONLY); + + if (console_handle == -1) + { + // Don't have permissions for the console device? + + fprintf(stderr, "PCSound_Linux_Init: Failed to open '%s': %s\n", + CONSOLE_DEVICE, strerror(errno)); + return 0; + } + + if (ioctl(console_handle, KIOCSOUND, 0) < 0) + { + // KIOCSOUND not supported: non-PC linux? + + close(console_handle); + return 0; + } + + // Start a thread up to generate PC speaker output + + callback = callback_func; + sound_thread_running = 1; + + sound_thread_handle = + SDL_CreateThread(SoundThread, "PC speaker thread", NULL); + + return 1; +} + +static void PCSound_Linux_Shutdown(void) +{ + sound_thread_running = 0; + SDL_WaitThread(sound_thread_handle, NULL); + close(console_handle); +} + +pcsound_driver_t pcsound_linux_driver = +{ + "Linux", + PCSound_Linux_Init, + PCSound_Linux_Shutdown, +}; + +#endif /* #ifdef HAVE_LINUX_KD_H */ + diff --git a/games/NXDoom/pcsound/pcsound_sdl.c b/games/NXDoom/pcsound/pcsound_sdl.c new file mode 100644 index 00000000000..d38a97b8245 --- /dev/null +++ b/games/NXDoom/pcsound/pcsound_sdl.c @@ -0,0 +1,254 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker interface. +// + +#include +#include + +#include "config.h" + +#include "SDL.h" + +#include "pcsound.h" +#include "pcsound_internal.h" + + +#ifndef DISABLE_SDL2MIXER + +#include "SDL_mixer.h" + + +#define MAX_SOUND_SLICE_TIME 70 /* ms */ +#define SQUARE_WAVE_AMP 0x2000 + +// If true, we initialized SDL and have the responsibility to shut it +// down + +static int sdl_was_initialized = 0; + +// Callback function to invoke when we want new sound data + +static pcsound_callback_func callback; + +// Output sound format + +static int mixing_freq; +static Uint16 mixing_format; +static int mixing_channels; + +// Currently playing sound +// current_remaining is the number of remaining samples that must be played +// before we invoke the callback to get the next frequency. + +static int current_remaining; +static int current_freq; + +static int phase_offset = 0; + +// Mixer function that does the PC speaker emulation + +static void PCSound_Mix_Callback(int chan, void *stream, int len, void *udata) +{ + Sint16 *leftptr; + Sint16 *rightptr; + Sint16 this_value; + int frequency; + int i; + int nsamples; + + // Number of samples is quadrupled, because of 16-bit and stereo + + nsamples = len / 4; + + leftptr = (Sint16 *) stream; + rightptr = ((Sint16 *) stream) + 1; + + // Fill the output buffer + + for (i=0; i limit) + { + return (1 << n); + } + } + + // Should never happen? + + return 1024; +} + +static int PCSound_SDL_Init(pcsound_callback_func callback_func) +{ + int slicesize; + + // Check if SDL_mixer has been opened already + // If not, we must initialize it now + + if (!SDLIsInitialized()) + { + if (SDL_Init(SDL_INIT_AUDIO) < 0) + { + fprintf(stderr, "Unable to set up sound.\n"); + return 0; + } + + slicesize = GetSliceSize(); + + if (Mix_OpenAudioDevice(pcsound_sample_rate, AUDIO_S16SYS, 2, slicesize, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) + { + fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError()); + + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return 0; + } + + SDL_PauseAudio(0); + + // When this module shuts down, it has the responsibility to + // shut down SDL. + + sdl_was_initialized = 1; + } + + // Get the mixer frequency, format and number of channels. + + Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels); + + // Only supports AUDIO_S16SYS + + if (mixing_format != AUDIO_S16SYS || mixing_channels != 2) + { + fprintf(stderr, + "PCSound_SDL only supports native signed 16-bit LSB, " + "stereo format!\n"); + + PCSound_SDL_Shutdown(); + return 0; + } + + callback = callback_func; + current_freq = 0; + current_remaining = 0; + + Mix_RegisterEffect(MIX_CHANNEL_POST, PCSound_Mix_Callback, NULL, NULL); + + return 1; +} + +pcsound_driver_t pcsound_sdl_driver = +{ + "SDL", + PCSound_SDL_Init, + PCSound_SDL_Shutdown, +}; + + +#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/pcsound/pcsound_win32.c b/games/NXDoom/pcsound/pcsound_win32.c new file mode 100644 index 00000000000..91885f685cf --- /dev/null +++ b/games/NXDoom/pcsound/pcsound_win32.c @@ -0,0 +1,106 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// PC speaker interface. +// + +#ifdef _WIN32 + +#include "SDL.h" +#include "SDL_thread.h" +#include + +#include "pcsound.h" +#include "pcsound_internal.h" + +static SDL_Thread *sound_thread_handle; +static int sound_thread_running; +static pcsound_callback_func callback; + +static int SoundThread(void *unused) +{ + int frequency; + int duration; + + while (sound_thread_running) + { + callback(&duration, &frequency); + + if (frequency != 0) + { + Beep(frequency, duration); + } + else + { + Sleep(duration); + } + } + + return 0; +} + +static int PCSound_Win32_Init(pcsound_callback_func callback_func) +{ + OSVERSIONINFO osvi; + BOOL result; + + // Temporarily disabled - the Windows scheduler is strange and + // stupid. + + return 0; + + // Find the OS version + + osvi.dwOSVersionInfoSize = sizeof(osvi); + + result = GetVersionEx(&osvi); + + if (!result) + { + return 0; + } + + // Beep() ignores its arguments on win9x, so this driver will + // not work there. + if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) + { + return 0; + } + + // Start a thread to play sound. + + callback = callback_func; + sound_thread_running = 1; + + sound_thread_handle = + SDL_CreateThread(SoundThread, "PC speaker thread", NULL); + + return 1; +} + +static void PCSound_Win32_Shutdown(void) +{ + sound_thread_running = 0; + SDL_WaitThread(sound_thread_handle, NULL); +} + +pcsound_driver_t pcsound_win32_driver = +{ + "Windows", + PCSound_Win32_Init, + PCSound_Win32_Shutdown, +}; + +#endif /* #ifdef _WIN32 */ + diff --git a/games/NXDoom/pkg/.gitignore b/games/NXDoom/pkg/.gitignore new file mode 100644 index 00000000000..a1dd1cde42a --- /dev/null +++ b/games/NXDoom/pkg/.gitignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in +config.make diff --git a/games/NXDoom/pkg/Makefile.am b/games/NXDoom/pkg/Makefile.am new file mode 100644 index 00000000000..3a287b2464f --- /dev/null +++ b/games/NXDoom/pkg/Makefile.am @@ -0,0 +1,25 @@ + +OSX_FILES= \ +osx/Resources/app.png \ +osx/Resources/launcher.nib/designable.nib \ +osx/Resources/launcher.nib/keyedobjects.nib \ +osx/disk/dir.DS_Store \ +osx/disk/background.png \ +osx/GNUmakefile \ +osx/Info.plist.in \ +osx/PkgInfo \ +osx/cp-with-libs \ +osx/dmgfix \ +osx/main.m \ +osx/AppController.m osx/AppController.h \ +osx/Execute.m osx/Execute.h \ +osx/IWADController.m osx/IWADController.h \ +osx/LauncherManager.m osx/LauncherManager.h + +WIN32_FILES= \ +win32/GNUmakefile \ +win32/cp-with-libs \ +win32/README + +EXTRA_DIST=style.html $(OSX_FILES) $(WIN32_FILES) + diff --git a/games/NXDoom/pkg/config.make.in b/games/NXDoom/pkg/config.make.in new file mode 100644 index 00000000000..972be10e461 --- /dev/null +++ b/games/NXDoom/pkg/config.make.in @@ -0,0 +1,30 @@ +# Shared file included by the makefiles used to build packages. +# This contains various information needed by the makefiles, +# and is autogenerated by configure to include various +# necessary details. + +# Tools needed: + +CC = @CC@ +OBJDUMP = @OBJDUMP@ +STRIP = @STRIP@ +LDFLAGS = @LDFLAGS@ + +# Package name and version number: + +PROGRAM_PREFIX = @PROGRAM_PREFIX@ +PACKAGE = @PACKAGE@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ + +TARGET_OS = @TARGET_OS@ + +# Documentation files to distribute with packages. + +DOC_FILES = README.md \ + README.Music.md \ + COPYING.md \ + NEWS.md + diff --git a/games/NXDoom/pkg/osx/.gitignore b/games/NXDoom/pkg/osx/.gitignore new file mode 100644 index 00000000000..a2b2f72de8d --- /dev/null +++ b/games/NXDoom/pkg/osx/.gitignore @@ -0,0 +1,10 @@ +Info.plist +app.iconset +app.icns +wadfile.iconset +wadfile.icns +launcher +*.o +*.d +*.dmg +staging diff --git a/games/NXDoom/pkg/osx/AppController.h b/games/NXDoom/pkg/osx/AppController.h new file mode 100644 index 00000000000..37340ca2cb7 --- /dev/null +++ b/games/NXDoom/pkg/osx/AppController.h @@ -0,0 +1,45 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef LAUNCHER_APPCONTROLLER_H +#define LAUNCHER_APPCONTROLLER_H + +#include + +#include "LauncherManager.h" + +@interface AppController : NSObject +{ + LauncherManager *launcherManager; + BOOL filesAdded; +} + ++ (void)initialize; + +- (id)init; +- (void)dealloc; + +- (void)awakeFromNib; + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotif; +- (BOOL)applicationShouldTerminate:(id)sender; +- (void)applicationWillTerminate:(NSNotification *)aNotif; +- (BOOL)application:(NSApplication *)application openFile:(NSString *)fileName; + +- (void)showPrefPanel:(id)sender; + +@end + +#endif + diff --git a/games/NXDoom/pkg/osx/AppController.m b/games/NXDoom/pkg/osx/AppController.m new file mode 100644 index 00000000000..428eb9d0755 --- /dev/null +++ b/games/NXDoom/pkg/osx/AppController.m @@ -0,0 +1,146 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include "AppController.h" + +#include "config.h" + +@implementation AppController + ++ (void)initialize +{ + NSMutableDictionary *defaults = [NSMutableDictionary dictionary]; + + /* + * Register your app's defaults here by adding objects to the + * dictionary, eg + * + * [defaults setObject:anObject forKey:keyForThatObject]; + * + */ + + [[NSUserDefaults standardUserDefaults] registerDefaults:defaults]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (id)init +{ + if ((self = [super init])) + { + } + + self->filesAdded = NO; + + return self; +} + +- (void)dealloc +{ + [super dealloc]; +} + +- (void)awakeFromNib +{ + [[NSApp mainMenu] setTitle:@PACKAGE_NAME]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotif +{ +// Uncomment if your application is Renaissance-based +// [NSBundle loadGSMarkupNamed:@"Main" owner:self]; +} + +- (BOOL)applicationShouldTerminate:(id)sender +{ + return YES; +} + +- (void)applicationWillTerminate:(NSNotification *)aNotif +{ +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)_ { + return YES; +} + +- (BOOL) application:(NSApplication *) application + openFile:(NSString *) fileName +{ + NSString *extension; + + // This may be an IWAD. If so, add it to the IWAD configuration; + // don't add it like a PWAD. + + if ([self->launcherManager addIWADPath: fileName]) + { + return YES; + } + + // If this is the first file added, clear out the existing + // command line. This allows us to select multiple files + // in the finder and open them all together (for TCs, etc). + + if (!self->filesAdded) + { + [self->launcherManager clearCommandLine]; + } + + // Add file with appropriate command line option based on extension: + + extension = [fileName pathExtension]; + + if (![extension caseInsensitiveCompare: @"wad"]) + { + [self->launcherManager addFileToCommandLine: fileName + forArgument: @"-merge"]; + } + else if (![extension caseInsensitiveCompare: @"lmp"]) + { + [self->launcherManager addFileToCommandLine: fileName + forArgument: @"-playdemo"]; + } + else if (![extension caseInsensitiveCompare: @"deh"]) + { + [self->launcherManager addFileToCommandLine: fileName + forArgument: @"-deh"]; + [self->launcherManager selectGameByName: "doom"]; + } + else if (![extension caseInsensitiveCompare: @"hhe"]) + { + [self->launcherManager addFileToCommandLine: fileName + forArgument: @"-deh"]; + [self->launcherManager selectGameByName: "heretic"]; + } + else if (![extension caseInsensitiveCompare: @"seh"]) + { + [self->launcherManager addFileToCommandLine: fileName + forArgument: @"-deh"]; + [self->launcherManager selectGameByName: "strife"]; + } + else + { + return NO; + } + + self->filesAdded = YES; + + return YES; +} + +- (void)showPrefPanel:(id)sender +{ +} + +@end + diff --git a/games/NXDoom/pkg/osx/Execute.h b/games/NXDoom/pkg/osx/Execute.h new file mode 100644 index 00000000000..fbb19c6f8c9 --- /dev/null +++ b/games/NXDoom/pkg/osx/Execute.h @@ -0,0 +1,24 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef LAUNCHER_EXECUTE_H +#define LAUNCHER_EXECUTE_H + +void SetProgramLocation(const char *path); +void ExecuteProgram(const char *executable, const char *iwad, const char *args); +void OpenTerminalWindow(const char *doomwadpath); +void OpenDocumentation(const char *filename); + +#endif /* #ifndef LAUNCHER_EXECUTE_H */ + diff --git a/games/NXDoom/pkg/osx/Execute.m b/games/NXDoom/pkg/osx/Execute.m new file mode 100644 index 00000000000..2d5d59310ac --- /dev/null +++ b/games/NXDoom/pkg/osx/Execute.m @@ -0,0 +1,226 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "config.h" + +#define RESPONSE_FILE "/tmp/launcher.rsp" +#define TEMP_SCRIPT "/tmp/tempscript.sh" +#define WINDOW_TITLE PACKAGE_STRING " command prompt" + +static char *executable_path; + +// Called on startup to save the location of the launcher program +// (within a package, other executables should be in the same directory) + +void SetProgramLocation(const char *path) +{ + char *p; + + executable_path = strdup(path); + + p = strrchr(executable_path, '/'); + *p = '\0'; +} + +// Write out the response file containing command line arguments. + +static void WriteResponseFile(const char *iwad, const char *args) +{ + FILE *fstream; + + fstream = fopen(RESPONSE_FILE, "w"); + + if (iwad != NULL) + { + fprintf(fstream, "-iwad \"%s\"", iwad); + } + + if (args != NULL) + { + fprintf(fstream, "%s", args); + } + + fclose(fstream); +} + +static void DoExec(const char *executable, const char *iwad, const char *args) +{ + char *argv[3]; + + asprintf(&argv[0], "%s/%s", executable_path, executable); + + if (iwad != NULL || args != NULL) + { + WriteResponseFile(iwad, args); + + argv[1] = "@" RESPONSE_FILE; + argv[2] = NULL; + } + else + { + argv[1] = NULL; + } + + execv(argv[0], argv); + exit(-1); +} + +// Execute the specified executable contained in the same directory +// as the launcher, with the specified arguments. + +void ExecuteProgram(const char *executable, const char *iwad, const char *args) +{ + pid_t childpid; + char *homedir; + + childpid = fork(); + + if (childpid == 0) + { + signal(SIGCHLD, SIG_DFL); + + // Change directory to home dir before launch, so that any demos + // are saved somewhere sensible. + + homedir = getenv("HOME"); + + if (homedir != NULL) + { + chdir(homedir); + } + + DoExec(executable, iwad, args); + } + else + { + signal(SIGCHLD, SIG_IGN); + } +} + +// Write a sequence of commands that will display the specified message +// via shell commands. + +static void WriteMessage(FILE *script, char *msg) +{ + char *p; + + fprintf(script, "echo \""); + + for (p=msg; *p != '\0'; ++p) + { + // Start new line? + + if (*p == '\n') + { + fprintf(script, "\"\necho \""); + continue; + } + + // Escaped character? + + if (*p == '\\' || *p == '\"') + { + fprintf(script, "\\"); + } + + fprintf(script, "%c", *p); + } + + fprintf(script, "\"\n"); +} + +// Open a terminal window with the PATH set appropriately, and DOOMWADPATH +// set to the specified value. + +void OpenTerminalWindow(const char *doomwadpath) +{ + FILE *stream; + + // Generate a shell script that sets the PATH to include the location + // where the Doom binaries are, and DOOMWADPATH to include the + // IWAD files that have been configured in the launcher interface. + // The script then deletes itself and starts a shell. + + stream = fopen(TEMP_SCRIPT, "w"); + + fprintf(stream, "#!/bin/sh\n"); + //fprintf(stream, "set -x\n"); + fprintf(stream, "PATH=\"%s:$PATH\"\n", executable_path); + + // MANPATH is set to point to the directory within the bundle that + // contains the Unix manpages. However, the bundle name or path to + // it can contain a space, and OS X doesn't like this! As a + // workaround, create a symlink in /tmp to point to the real directory, + // and put *this* in MANPATH. + + fprintf(stream, "rm -f \"/tmp/%s.man\"\n", PACKAGE_TARNAME); + fprintf(stream, "ln -s \"%s/man\" \"/tmp/%s.man\"\n", + executable_path, PACKAGE_TARNAME); + fprintf(stream, "MANPATH=\"/tmp/%s.man:$(manpath)\"\n", PACKAGE_TARNAME); + fprintf(stream, "export MANPATH\n"); + + fprintf(stream, "DOOMWADPATH=\"%s\"\n", doomwadpath); + fprintf(stream, "export DOOMWADPATH\n"); + fprintf(stream, "rm -f \"%s\"\n", TEMP_SCRIPT); + + // Window title to something more interesting than "tempscript": + fprintf(stream, "echo -en \"\\033]0;%s\\a\"\n", WINDOW_TITLE); + + // Display a useful message: + + fprintf(stream, "clear\n"); + WriteMessage(stream, + "\n" + "This command line has the PATH variable configured so that you may\n" + "launch the game with whatever parameters you desire.\n" + "\n" + "For example:\n" + "\n" + " " PACKAGE_TARNAME " -iwad doom2.wad -file sid.wad -warp 1\n" + "\n" + "Type 'exit' to exit.\n"); + + fprintf(stream, "exec $SHELL\n"); + fprintf(stream, "\n"); + + fclose(stream); + + chmod(TEMP_SCRIPT, 0755); + + // Tell the terminal to open a window to run the script. + + [[NSWorkspace sharedWorkspace] openFile: @TEMP_SCRIPT + withApplication: @"Terminal"]; +} + +void OpenDocumentation(const char *filename) +{ + NSString *path; + + path = [NSString stringWithFormat: @"%s/Documentation/%s", + executable_path, filename]; + + [[NSWorkspace sharedWorkspace] openFile: path]; +} + diff --git a/games/NXDoom/pkg/osx/GNUmakefile b/games/NXDoom/pkg/osx/GNUmakefile new file mode 100644 index 00000000000..55d7ac81011 --- /dev/null +++ b/games/NXDoom/pkg/osx/GNUmakefile @@ -0,0 +1,132 @@ +# Makefile for building the OS X launcher program and DMG package. + +include ../config.make + +DOC_FILES += README.Strife.md NOT-BUGS.md + +export MACOSX_DEPLOYMENT_TARGET=10.7 + +ifeq ($(TARGET_OS),arm) + POSTFIX=arm64 +else + POSTFIX=x86 +endif + +STAGING_DIR=staging +DMG=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-$(POSTFIX).dmg + +TOPLEVEL=../.. +TOPLEVEL_DOCS=$(patsubst %,../../%,$(DOC_FILES)) + +# DMG file containing package: + +$(DMG) : tmp.dmg + rm -f $@ + sleep 2 # pause to workaround occasional "Can’t get disk" (-1728) issues + ./dmgfix "$(realpath tmp.dmg)" "$(PACKAGE_STRING)" "$(PACKAGE_NAME).app" + hdiutil convert -format UDBZ -o $@ tmp.dmg + rm -f tmp.dmg + +tmp.dmg : $(STAGING_DIR) + rm -f $@ + hdiutil makehybrid -hfs -hfs-volume-name "$(PACKAGE_STRING)" \ + -hfs-openfolder $(STAGING_DIR) $(STAGING_DIR) \ + -o tmp.dmg + +# Staging dir build for package: + +APP_DIR=$(STAGING_DIR)/$(PACKAGE_NAME).app + +APP_TOP_DIR=$(APP_DIR)/Contents +APP_BIN_DIR=$(APP_DIR)/Contents/MacOS +SRC_INFO_PLIST=Info.plist + +APP_DOC_DIR=$(APP_BIN_DIR)/Documentation +APP_DOC_RELDIR=$(patsubst $(STAGING_DIR)/%,%,$(APP_DOC_DIR)) + +$(STAGING_DIR): launcher $(TOPLEVEL_DOCS) app.icns wadfile.icns + rm -rf $(STAGING_DIR) + mkdir $(STAGING_DIR) + + mkdir -p "$(APP_TOP_DIR)" + cp -R Resources "$(APP_TOP_DIR)" + cp app.icns wadfile.icns "$(APP_TOP_DIR)/Resources" + cp $(TOPLEVEL)/data/doom.png "$(APP_TOP_DIR)/Resources/128x128.png" + cp PkgInfo "$(APP_TOP_DIR)" + cp $(SRC_INFO_PLIST) "$(APP_TOP_DIR)" + + mkdir -p "$(APP_BIN_DIR)" + + mkdir -p "$(APP_DOC_DIR)" + cp $(TOPLEVEL_DOCS) "$(APP_DOC_DIR)" + + mv "$(APP_DOC_DIR)/README.md" "$(APP_DOC_DIR)/README" + mv "$(APP_DOC_DIR)/COPYING.md" "$(APP_DOC_DIR)/COPYING" + ln -s "$(APP_DOC_RELDIR)/COPYING" "$(STAGING_DIR)/Software License" + ln -s "$(APP_DOC_RELDIR)/README" "$(STAGING_DIR)/README" + ln -s /Applications "$(STAGING_DIR)" + + cp launcher "$(APP_BIN_DIR)" + $(STRIP) "$(APP_BIN_DIR)/launcher" + + ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom "$(APP_BIN_DIR)" + $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)doom" + ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic "$(APP_BIN_DIR)" + $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)heretic" + ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen "$(APP_BIN_DIR)" + $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)hexen" + ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)strife "$(APP_BIN_DIR)" + $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)strife" + ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)" + $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup" + + $(TOPLEVEL)/man/simplecpp -DPRECOMPILED -D__MACOSX__ \ + -DDOOM -DHERETIC -DHEXEN -DSTRIFE \ + < $(TOPLEVEL)/man/INSTALL.template \ + > "$(APP_DOC_DIR)/INSTALL" + + mkdir -p "$(APP_BIN_DIR)/man/man5" "$(APP_BIN_DIR)/man/man6" + cp $(TOPLEVEL)/man/*.5 "$(APP_BIN_DIR)/man/man5" + cp $(TOPLEVEL)/man/*.6 "$(APP_BIN_DIR)/man/man6" + for game in doom heretic hexen strife; do \ + cp $(TOPLEVEL)/man/CMDLINE.$$game \ + "$(APP_DOC_DIR)/CMDLINE-$$game"; \ + done + cp disk/dir.DS_Store $(STAGING_DIR)/.DS_Store + cp disk/background.png $(STAGING_DIR)/background.png + +app.icns: $(TOPLEVEL)/data/doom.png + mkdir -p app.iconset + sips -z 64 64 $< --out app.iconset/icon_32x32@2x.png + iconutil -c icns app.iconset + +wadfile.icns: $(TOPLEVEL)/data/wadfile.png + mkdir -p wadfile.iconset + sips -z 64 64 $< --out wadfile.iconset/icon_32x32@2x.png + iconutil -c icns wadfile.iconset + +clean : launcher_clean + rm -f $(DMG) + rm -rf $(STAGING_DIR) + rm -rf app.icns app.iconset wadfile.icns wadfile.iconset + +# Launcher build: +CFLAGS = -Wall -I$(TOPLEVEL) +LDFLAGS = -framework Cocoa + +LAUNCHER_OBJS= \ + AppController.o \ + Execute.o \ + IWADController.o \ + LauncherManager.o \ + main.o + +launcher : $(LAUNCHER_OBJS) + $(CC) $(LDFLAGS) $(LAUNCHER_OBJS) -o $@ + +%.o : %.m + $(CC) -c $(CFLAGS) $^ -o $@ + +launcher_clean : + rm -f $(LAUNCHER_OBJS) launcher + diff --git a/games/NXDoom/pkg/osx/IWADController.h b/games/NXDoom/pkg/osx/IWADController.h new file mode 100644 index 00000000000..404bffad0a2 --- /dev/null +++ b/games/NXDoom/pkg/osx/IWADController.h @@ -0,0 +1,57 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef LAUNCHER_IWADCONTROLLER_H +#define LAUNCHER_IWADCONTROLLER_H + +#include +#include + +@interface IWADController : NSObject +{ + id iwadSelector; + id configWindow; + + id chex; + id doom1; + id doom2; + id plutonia; + id tnt; + id freedoom1; + id freedoom2; + id freedm; + + id heretic; + id hexen; + id strife; +} + +- (void) closeConfigWindow: (id)sender; +- (void) openConfigWindow: (id)sender; +- (NSString *) getIWADLocation; +- (NSString *) autoloadPath; +- (void) awakeFromNib; +- (BOOL) setDropdownList; +- (void) setDropdownSelection; +- (void) saveConfig; +- (char *) doomWadPath; +- (void) setEnvironment; +- (const char *) getGameName; +- (BOOL) addIWADPath: (NSString *) path; +- (BOOL) selectGameByName: (const char *) name; + +@end + +#endif /* #ifndef LAUNCHER_IWADCONTROLLER_H */ + diff --git a/games/NXDoom/pkg/osx/IWADController.m b/games/NXDoom/pkg/osx/IWADController.m new file mode 100644 index 00000000000..c131105c374 --- /dev/null +++ b/games/NXDoom/pkg/osx/IWADController.m @@ -0,0 +1,482 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include +#include + +#include "config.h" +#include "IWADController.h" + +typedef enum +{ + IWAD_DOOM1, + IWAD_DOOM2, + IWAD_TNT, + IWAD_PLUTONIA, + IWAD_CHEX, + IWAD_HERETIC, + IWAD_HEXEN, + IWAD_STRIFE, + IWAD_FREEDOOM1, + IWAD_FREEDOOM2, + IWAD_FREEDM, + NUM_IWAD_TYPES +} IWAD; + +static NSString *IWADLabels[NUM_IWAD_TYPES] = +{ + @"Doom", + @"Doom II: Hell on Earth", + @"Final Doom: TNT: Evilution", + @"Final Doom: Plutonia Experiment", + @"Chex Quest", + @"Heretic", + @"Hexen", + @"Strife", + @"Freedoom: Phase 1", + @"Freedoom: Phase 2", + @"FreeDM", +}; + +static NSString *IWADFilenames[NUM_IWAD_TYPES + 1] = +{ + @"doom.wad", + @"doom2.wad", + @"tnt.wad", + @"plutonia.wad", + @"chex.wad", + @"heretic.wad", + @"hexen.wad", + @"strife.wad", + @"freedoom1.wad", + @"freedoom2.wad", + @"freedm.wad", + @"undefined" +}; + +@implementation IWADController + +- (void) getIWADList: (NSPathControl **) iwadList +{ + iwadList[IWAD_DOOM1] = self->doom1; + iwadList[IWAD_DOOM2] = self->doom2; + iwadList[IWAD_TNT] = self->tnt; + iwadList[IWAD_PLUTONIA] = self->plutonia; + iwadList[IWAD_CHEX] = self->chex; + iwadList[IWAD_HERETIC] = self->heretic; + iwadList[IWAD_HEXEN] = self->hexen; + iwadList[IWAD_STRIFE] = self->strife; + iwadList[IWAD_FREEDOOM1] = self->freedoom1; + iwadList[IWAD_FREEDOOM2] = self->freedoom2; + iwadList[IWAD_FREEDM] = self->freedm; +} + +- (IWAD) getSelectedIWAD +{ + unsigned int i; + + for (i=0; iiwadSelector titleOfSelectedItem] == IWADLabels[i]) + { + return i; + } + } + + return NUM_IWAD_TYPES; +} + +// Get the location of the selected IWAD. + +- (NSString *) getIWADLocation +{ + IWAD selectedIWAD; + NSPathControl *iwadList[NUM_IWAD_TYPES]; + + selectedIWAD = [self getSelectedIWAD]; + + if (selectedIWAD == NUM_IWAD_TYPES) + { + return nil; + } + else + { + [self getIWADList: iwadList]; + + return [[iwadList[selectedIWAD] URL] path]; + } +} + +static const char *NameForIWAD(IWAD iwad) +{ + switch (iwad) + { + case IWAD_HERETIC: + return "heretic"; + + case IWAD_HEXEN: + return "hexen"; + + case IWAD_STRIFE: + return "strife"; + + default: + return "doom"; + } +} + +// Get the name used for the executable for the selected IWAD. + +- (const char *) getGameName +{ + return NameForIWAD([self getSelectedIWAD]); +} + +- (void) setIWADConfig +{ + NSPathControl *iwadList[NUM_IWAD_TYPES]; + NSUserDefaults *defaults; + NSString *key; + NSString *value; + unsigned int i; + + [self getIWADList: iwadList]; + + // Load IWAD filename paths + + defaults = [NSUserDefaults standardUserDefaults]; + + for (i=0; iiwadSelector selectItemWithTitle:IWADLabels[i]]; + break; + } + } +} + +// Set the dropdown list to include an entry for each IWAD that has +// been configured. Returns true if at least one IWAD is configured. + +- (BOOL) setDropdownList +{ + NSPathControl *iwadList[NUM_IWAD_TYPES]; + BOOL have_wads; + id location; + unsigned int i; + unsigned int enabled_wads; + + // Build the new list. + + [self getIWADList: iwadList]; + [self->iwadSelector removeAllItems]; + + enabled_wads = 0; + + for (i=0; i 0) + { + [self->iwadSelector addItemWithTitle: IWADLabels[i]]; + ++enabled_wads; + } + } + + // Enable/disable the dropdown depending on whether there + // were any configured IWADs. + + have_wads = enabled_wads > 0; + [self->iwadSelector setEnabled: have_wads]; + + // Restore the old selection. + + [self setDropdownSelection]; + + return have_wads; +} + +- (void) saveConfig +{ + NSPathControl *iwadList[NUM_IWAD_TYPES]; + IWAD selectedIWAD; + NSUserDefaults *defaults; + NSString *key; + NSString *value; + unsigned int i; + + [self getIWADList: iwadList]; + + // Store all IWAD locations to user defaults. + + defaults = [NSUserDefaults standardUserDefaults]; + + for (i=0; iconfigWindow isVisible]) + { + [self->configWindow makeKeyAndOrderFront: sender]; + } +} + +// Callback method invoked when the close button is clicked. + +- (void) closeConfigWindow: (id)sender +{ + [self->configWindow orderOut: sender]; + [self saveConfig]; + [self setDropdownList]; +} + +- (void) awakeFromNib +{ + [self->configWindow center]; + + // Set configuration for all IWADs from configuration file. + + [self setIWADConfig]; + + // Populate the dropdown IWAD list. + + if ([self setDropdownList]) + { + [self setDropdownSelection]; + } +} + +// Generate a value to set for the DOOMWADPATH environment variable +// that contains each of the configured IWAD files. + +- (char *) doomWadPath +{ + NSPathControl *iwadList[NUM_IWAD_TYPES]; + NSString *location; + unsigned int i; + BOOL first; + char *env; + size_t env_len; + + [self getIWADList: iwadList]; + + // Calculate length of environment string. + + env_len = 0; + + for (i=0; i 0) + { + env_len += [location length] + 1; + } + } + + // Build string. + + env = malloc(env_len); + strlcpy(env, "", env_len); + + first = YES; + + for (i=0; i 0) + { + if (!first) + { + strlcat(env, ":", env_len); + } + + strlcat(env, [location UTF8String], env_len); + first = NO; + } + } + + return env; +} + +- (NSString *) autoloadPath +{ + NSArray *array = NSSearchPathForDirectoriesInDomains( + NSApplicationSupportDirectory, NSUserDomainMask, YES); + if ([array count] == 0) + { + return nil; + } + + IWAD selectedIWAD = [self getSelectedIWAD]; + if (selectedIWAD == NUM_IWAD_TYPES) + { + return nil; + } + + NSString *base = [array objectAtIndex:0]; + return [NSString pathWithComponents: + [NSArray arrayWithObjects: base, @PACKAGE_TARNAME, @"autoload", + IWADFilenames[selectedIWAD], nil]]; +} + +// Set the DOOMWADPATH environment variable to contain the path to each +// of the configured IWAD files. + +- (void) setEnvironment +{ + char *doomwadpath; + char *env; + + // Get the value for the path. + + doomwadpath = [self doomWadPath]; + + asprintf(&env, "DOOMWADPATH=%s", doomwadpath); + + free(doomwadpath); + + // Load into environment: + + putenv(env); + + //free(env); +} + +// Examine a path to a WAD and determine whether it is an IWAD file. +// If so, it is added to the IWAD configuration, and true is returned. + +- (BOOL) addIWADPath: (NSString *) path +{ + NSPathControl *iwadList[NUM_IWAD_TYPES]; + NSArray *pathComponents; + NSString *filename; + unsigned int i; + + [self getIWADList: iwadList]; + + // Find an IWAD file that matches the filename in the path that we + // have been given. + + pathComponents = [path pathComponents]; + filename = [pathComponents objectAtIndex: [pathComponents count] - 1]; + + for (i = 0; i < NUM_IWAD_TYPES; ++i) + { + if ([filename caseInsensitiveCompare: IWADFilenames[i]] == 0) + { + // Configure this IWAD. + + [iwadList[i] setURL: [NSURL fileURLWithPath: path]]; + + // Rebuild dropdown list and select the new IWAD. + + [self setDropdownList]; + [self->iwadSelector selectItemWithTitle:IWADLabels[i]]; + return YES; + } + } + + // No IWAD found with this name. + + return NO; +} + +- (BOOL) selectGameByName: (const char *) name +{ + NSPathControl *iwadList[NUM_IWAD_TYPES]; + NSString *location; + const char *name2; + int i; + + // Already selected an IWAD of the desired type? Just return + // success. + if (!strcmp(name, [self getGameName])) + { + return YES; + } + + // Search through the configured IWADs and try to select the + // desired game. + [self getIWADList: iwadList]; + + for (i = 0; i < NUM_IWAD_TYPES; ++i) + { + location = [[iwadList[i] URL] path]; + name2 = NameForIWAD(i); + + if (!strcmp(name, name2) + && location != nil && [location length] > 0) + { + [self->iwadSelector selectItemWithTitle:IWADLabels[i]]; + return YES; + } + } + + // User hasn't configured any WAD(s) for the desired game type. + return NO; +} + +@end + diff --git a/games/NXDoom/pkg/osx/Info.plist.in b/games/NXDoom/pkg/osx/Info.plist.in new file mode 100644 index 00000000000..13da040dd8a --- /dev/null +++ b/games/NXDoom/pkg/osx/Info.plist.in @@ -0,0 +1,104 @@ + + + + + CFBundleIdentifier + org.chocolate-doom.launcher + CFBundleDevelopmentRegion + English + CFBundleDisplayName + @PACKAGE_NAME@ + CFBundleExecutable + launcher + CFBundleGetInfoString + @PACKAGE_STRING@ + CFBundleIconFile + app.icns + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + @PACKAGE_NAME@ + CFBundlePackageType + APPL + CFBundleShortVersionString + @PACKAGE_VERSION@ + CFBundleVersion + @PACKAGE_VERSION@ + NSHighResolutionCapable + true + NSPrincipalClass + NSApplication + NSMainNibFile + launcher + NSHumanReadableCopyright + Copyright (C) 1993-2015, id Software and Raven Software, Simon Howard, James Haley, Samuel Villarreal and other contributors. + +Licensed under the GNU GPL v2. + + + + CFBundleDocumentTypes + + + CFBundleTypeName + Doom WAD file + CFBundleTypeIconFile + wadfile.icns + CFBundleTypeRole + Viewer + CFBundleTypeExtensions + + wad + + + + CFBundleTypeName + Doom demo recording + CFBundleTypeIconFile + wadfile.icns + CFBundleTypeRole + Viewer + CFBundleTypeExtensions + + lmp + + + + CFBundleTypeName + Doom Dehacked patch + CFBundleTypeIconFile + wadfile.icns + CFBundleTypeRole + Viewer + CFBundleTypeExtensions + + deh + + + + CFBundleTypeName + Heretic HHE patch + CFBundleTypeIconFile + wadfile.icns + CFBundleTypeRole + Viewer + CFBundleTypeExtensions + + hhe + + + + CFBundleTypeName + Strife Sehacked patch + CFBundleTypeIconFile + wadfile.icns + CFBundleTypeRole + Viewer + CFBundleTypeExtensions + + seh + + + + + diff --git a/games/NXDoom/pkg/osx/LauncherManager.h b/games/NXDoom/pkg/osx/LauncherManager.h new file mode 100644 index 00000000000..fb8a5cf5d86 --- /dev/null +++ b/games/NXDoom/pkg/osx/LauncherManager.h @@ -0,0 +1,51 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef LAUNCHER_LAUNCHERMANAGER_H +#define LAUNCHER_LAUNCHERMANAGER_H + +#include +#include +#include "IWADController.h" + +@interface LauncherManager : NSObject +{ + IWADController *iwadController; + + id launcherWindow; + id launchButton; + + id commandLineArguments; +} + +- (void) launch: (id)sender; +- (void) runSetup: (id)sender; +- (void) awakeFromNib; +- (void) clearCommandLine; +- (BOOL) addIWADPath: (NSString *) path; +- (void) addFileToCommandLine: (NSString *) fileName + forArgument: (NSString *) args; +- (BOOL) selectGameByName: (const char *) name; +- (void) openTerminal: (id) sender; + +- (void) openREADME: (id) sender; +- (void) openINSTALL: (id) sender; +- (void) openCMDLINE: (id) sender; +- (void) openCOPYING: (id) sender; +- (void) openDocumentation: (id) sender; + +@end + +#endif /* #ifndef LAUNCHER_LAUNCHERMANAGER_H */ + diff --git a/games/NXDoom/pkg/osx/LauncherManager.m b/games/NXDoom/pkg/osx/LauncherManager.m new file mode 100644 index 00000000000..4e6e33e5296 --- /dev/null +++ b/games/NXDoom/pkg/osx/LauncherManager.m @@ -0,0 +1,410 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include "Execute.h" +#include "LauncherManager.h" +#include "config.h" + +@implementation LauncherManager + +// Save configuration. Invoked when we launch the game or quit. + +- (void) saveConfig +{ + NSUserDefaults *defaults; + + // Save IWAD configuration and selected IWAD. + + [self->iwadController saveConfig]; + + // Save command line arguments. + + defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:[self->commandLineArguments stringValue] + forKey:@"command_line_args"]; +} + +// Load configuration, invoked on startup. + +- (void) setConfig +{ + NSUserDefaults *defaults; + NSString *args; + + defaults = [NSUserDefaults standardUserDefaults]; + + args = [defaults stringForKey:@"command_line_args"]; + + if (args != nil) + { + [self->commandLineArguments setStringValue:args]; + } +} + +// Get the next command line argument from the command line. +// The position counter used to iterate over arguments is in 'pos'. +// The index of the argument that was found is saved in arg_pos. + +static NSString *GetNextArgument(NSString *commandLine, int *pos, int *arg_pos) +{ + NSRange arg_range; + + // Skip past any whitespace + + while (*pos < [commandLine length] + && isspace([commandLine characterAtIndex: *pos])) + { + ++*pos; + } + + if (*pos >= [commandLine length]) + { + *arg_pos = *pos; + return nil; + } + + // We are at the start of the argument. This may be a quoted + // string argument, or a "normal" one. + + if ([commandLine characterAtIndex: *pos] == '\"') + { + // Quoted string, skip past first quote + + ++*pos; + + // Save start position: + + *arg_pos = *pos; + + while (*pos < [commandLine length] + && [commandLine characterAtIndex: *pos] != '\"') + { + ++*pos; + } + + // Unexpected end of string? + + if (*pos >= [commandLine length]) + { + return nil; + } + + arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos); + + // Skip past last quote + + ++*pos; + } + else + { + // Normal argument + + // Save position: + + *arg_pos = *pos; + + // Read until end: + + while (*pos < [commandLine length] + && !isspace([commandLine characterAtIndex: *pos])) + { + ++*pos; + } + + arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos); + } + + return [commandLine substringWithRange: arg_range]; +} + +// Given the specified command line argument, find the index +// to insert the new file within the command line. Returns -1 if the +// argument is not already within the arguments string. + +static int GetFileInsertIndex(NSString *commandLine, NSString *needle) +{ + NSString *arg; + int arg_pos; + int pos; + + pos = 0; + + // Find the command line parameter we are searching + // for (-merge, -deh, etc) + + for (;;) + { + arg = GetNextArgument(commandLine, &pos, &arg_pos); + + // Searched to end of string and never found? + + if (arg == nil) + { + return -1; + } + + if (![arg caseInsensitiveCompare: needle]) + { + break; + } + } + + // Now skip over existing files. For example, if we + // have -file foo.wad bar.wad, the new file should be appended + // to the end of the list. + + for (;;) + { + arg = GetNextArgument(commandLine, &pos, &arg_pos); + + // If we search to the end of the string now, it is fine; + // the new string should be added to the end of the command + // line. Otherwise, if we find an argument that begins + // with '-', it is a new command line parameter and the end + // of the list. + + if (arg == nil || [arg characterAtIndex: 0] == '-') + { + break; + } + } + + // arg_pos should now contain the offset to insert the new filename. + + return arg_pos; +} + +// Given the specified string, append a filename, quoted if necessary. + +static NSString *AppendQuotedFilename(NSString *str, NSString *fileName) +{ + int i; + + // Search the filename for spaces, and quote if necessary. + + for (i=0; i<[fileName length]; ++i) + { + if (isspace([fileName characterAtIndex: i])) + { + str = [str stringByAppendingString: @" \""]; + str = [str stringByAppendingString: fileName]; + str = [str stringByAppendingString: @"\" "]; + + return str; + } + } + + str = [str stringByAppendingString: @" "]; + str = [str stringByAppendingString: fileName]; + + return str; +} + +// Clear out the existing command line options. +// Invoked before the first file is added. + +- (void) clearCommandLine +{ + [self->commandLineArguments setStringValue: @""]; +} + +// Add a file to the command line to load with the game. + +- (void) addFileToCommandLine: (NSString *) fileName + forArgument: (NSString *) arg +{ + NSString *commandLine; + int insert_pos; + + // Get the current command line + + commandLine = [self->commandLineArguments stringValue]; + + // Find the location to insert the new filename: + + insert_pos = GetFileInsertIndex(commandLine, arg); + + // If position < 0, we should add the new argument and filename + // to the end. Otherwise, append the new filename to the existing + // list of files. + + if (insert_pos < 0) + { + commandLine = [commandLine stringByAppendingString: @" "]; + commandLine = [commandLine stringByAppendingString: arg]; + commandLine = AppendQuotedFilename(commandLine, fileName); + } + else + { + NSString *start; + NSString *end; + + // Divide existing command line in half: + + start = [commandLine substringToIndex: insert_pos]; + end = [commandLine substringFromIndex: insert_pos]; + + // Construct new command line: + + commandLine = AppendQuotedFilename(start, fileName); + commandLine = [commandLine stringByAppendingString: @" "]; + commandLine = [commandLine stringByAppendingString: end]; + } + + [self->commandLineArguments setStringValue: commandLine]; +} + +- (void) launch: (id)sender +{ + NSString *iwad; + NSString *args; + char *executable_name; + const char *game_name; + + [self saveConfig]; + + iwad = [self->iwadController getIWADLocation]; + args = [self->commandLineArguments stringValue]; + + if (iwad == nil) + { + NSRunAlertPanel(@"No IWAD selected", + @"You have not selected an IWAD (game) file.\n\n" + "You must configure and select a valid IWAD file " + "in order to launch the game.", + @"OK", nil, nil); + return; + } + + game_name = [self->iwadController getGameName]; + asprintf(&executable_name, "%s%s", PROGRAM_PREFIX, game_name); + + ExecuteProgram(executable_name, [iwad UTF8String], + [args UTF8String]); + [NSApp terminate:sender]; +} + +// Invoked when the "Setup Tool" button is clicked, to run the setup tool: + +- (void) runSetup: (id)sender +{ + const char *game_name; + char *arg; + + [self saveConfig]; + [self->iwadController setEnvironment]; + + // Provide the -game command line parameter to select the game + // to configure, based on the game selected in the dropdown. + + game_name = [self->iwadController getGameName]; + asprintf(&arg, "-game %s", game_name); + + ExecuteProgram(PROGRAM_PREFIX "setup", NULL, arg); + + free(arg); +} + +// Invoked when the "Terminal" option is selected from the menu, to open +// a terminal window. + +- (void) openTerminal: (id) sender +{ + char *doomwadpath; + + [self saveConfig]; + + doomwadpath = [self->iwadController doomWadPath]; + + OpenTerminalWindow(doomwadpath); + + free(doomwadpath); +} + +- (void) openREADME: (id) sender +{ + OpenDocumentation("README"); +} + +- (void) openINSTALL: (id) sender +{ + OpenDocumentation("INSTALL"); +} + +- (void) openCMDLINE: (id) sender +{ + const char *game_name; + char filename[32]; + + // We need to open the appropriate doc file for the currently + // selected game. + + game_name = [self->iwadController getGameName]; + snprintf(filename, sizeof(filename), "CMDLINE-%s", game_name); + + OpenDocumentation(filename); +} + +- (void) openCOPYING: (id) sender +{ + OpenDocumentation("COPYING"); +} + +- (void) openDocumentation: (id) sender +{ + OpenDocumentation(""); +} + +- (void) openAutoload: (id) sender +{ + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *path = [self->iwadController autoloadPath]; + + if (path == nil) + { + return; + } + + if (![fm fileExistsAtPath:path]) + { + [fm createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:nil]; + } + + [[NSWorkspace sharedWorkspace] openFile:path withApplication:@"Finder"]; +} + +- (void) awakeFromNib +{ + [self->launcherWindow setTitle: @PACKAGE_NAME " Launcher"]; + [self->launcherWindow center]; + [self->launcherWindow setDefaultButtonCell: [self->launchButton cell]]; + [self setConfig]; +} + +- (BOOL) addIWADPath: (NSString *) path +{ + return [self->iwadController addIWADPath: path]; +} + +- (BOOL) selectGameByName: (const char *) name +{ + return [self->iwadController selectGameByName: name]; +} + +@end + diff --git a/games/NXDoom/pkg/osx/PkgInfo b/games/NXDoom/pkg/osx/PkgInfo new file mode 100644 index 00000000000..6f749b0f376 --- /dev/null +++ b/games/NXDoom/pkg/osx/PkgInfo @@ -0,0 +1 @@ +APPL???? diff --git a/games/NXDoom/pkg/osx/Resources/app.png b/games/NXDoom/pkg/osx/Resources/app.png new file mode 100644 index 0000000000000000000000000000000000000000..5b932e8cf86ca68c79b71a41458df6c1809011f3 GIT binary patch literal 4597 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L009O7009O8&C@fy00007bV*G`2iXY` z5H$-ml?{Rb01kT^*L4B9(Mi*Z$G7)9>>>&-=XZ_k9EZ&oALE{*MeOwZAT4*KV)&8Snop z01?oD2oM7TfCH3(GEl7nsnl+}2Jp`YNP3gO>p%indCSc={naD)eD~f&Q`6G_dj6#{ z(Dd%>uDxVvXxIS4HK0Nb;GYe|n_)l!8i6%G|H18dH06(OGA)~}AGrxx_v5*z;_L0{ zv4+Nzuk6};V9(EfdH-X;F<`pJh*x{3P$xC-e*=IBgn$)y|MSh?+_oh8?w|kqL9D7v z)UOc@Xb@~f^K4eET*dNrm*Q3mOqIN2*L?H~p9PKrQ#DD+HFl&LJ7%5K{wxxj(|rrD z_LfiG@bP2)M}nK)^#MM4>sQ!(#deCWN=4B4=x1&t5b!fRFvt@R@4zTdM#Ei~SGo`M zj@RnM0eqkCNL;2%Qrl?R)N9PTZ&hZ}MYxT>7W|qYe)G$>Y+18-?dmPp(9yM)^uT_K zQzuxlVKaWwBH7nXw7HE$>mt@%eicq7&*f{DZd!HOw$`VgeWACO?ZCB(h7Voc)b!oU zB7xQ2*=*W$J)su-n+76XAb6!#j2*!Gf4}S7w_d$=(UpnSTbOwL1*VU_h9l{;ZM+ge z5E$9FlcNXrG2QnX@#c1fs>O-%NnU#9Dc-Yb=~A`1EBo5M?oq&47xr!beJ*&_fwH>v z=FZsmC5D{XH(N;6*!F5nT~vKY7bw^WuVSXEj1b)1 zQxb%yvyu_je5?Pyv*BF|4gKk`4me!+nLSH za(r~0gx|3} z9=zmWwlGz8T`p7~(m8@}1vc#b%{_Nir;mjM)u26UFnD}~!O;m63EJ8haqZhTQ<@wk zIoQMVk3YiR*Lw))Dy~(=b{w8NGR5+sjo#3PS4@#uaVgehpZ@TkW6v-1=`lwMUvk_O z&a&}}3%d%UI%=zJH+4q0uMFz#`!l&|@06_Eg^f|F3*M-?&HAT*@%_7+b-UfnB*~?d zy!!fK%9$kZxpq72H*ThD{U*}0Ssr_OCwmU`V@NIqvr5UTV%jc>BJo)FNj5BMK=mw^ zZQMpWm87YCDfj;V`IkEVdRW#YmkgB!@qF5zbp)QtNxG^UT{kUnd{;;jIGimeYa@$Q z1AO55>QfKj)uKD?f*>LY(Ad_=+NEu5yZTyQ=@}%MO7X%oPt$*>hmbB|RvmnP z1J`vqJT}9L={&tBGU$p3qKIYN%nbFgc=aVzig|#5g(oS}#r4o#SwZ~Lu-vHlTR#82 zE$i+EnreM%o`f`@<<77E!&lZf2yaUdA7El^4A*se`GuWKjF0nbcQ10az|`mod~S(U zW|ore5Y$!Ns>5J1M>1=YGcBfb72dug!Czi?6_c4F5)M_{WbDu$-uZ!#X|M0zlZl4o zYx~QRC`uxtC~|$&p(;w`JPA=0=iP`Rhf1P!MO;*#Jvs45AYE&W$o1Ve9t*3EW1$#+ zD$~a~a(IF#d&gPa=%+IlM3*G8WsAe(84@9#235wVYaBf}L)5R4&Rdwa!#mfs(cqUk zI(UMJP@-fTuN0?1Znh1pg?Cc&UnH{7h;$!#lAYDyiwqCl1-V@1*swY%6LqRq4GeOE(em^mR zAx&|8Ya6qnCVp3r&a)gzbA(#(V!iWFo8xCc^^dpzWV9%Z{r2Sn)~#BBu1d&~$i|K+ z9qYF6wsl=-ibVfJ7EL!usx7Qo+Cf)KlnpDF@{#vk&9bhQcnG+z$Nm!;9@#s>k+BS! zqDeM6jx5Q=HbW8OeqB}#gSlJMC47dApo%=6nxILuQR<$nhC#&8{I!^cg$y`A4jA7# zRCp{s*!Ss?VMxRxeDQ-@x&9-cAlSB?N-mAw*~|5Yj%1g}O^uMAEV4Sbi2lhL9)9{o zuHUwikfCwi)-|k7<`D2GI3maLV&;(4-h2CZ@7eM0j>e6$CZih0nd~a30Gu8LGyzpK z<~J#=D4h?0TN|_rKfV9K?%n@(8-vp&-gfy``d<7U-~9U5dGDr9Y)|6kRGQhcO=rwc zAQ;4ROoDzN%NBRg7H_~GZ=p0ZftAY2*MtDHy| zX{@?5_!S(pLTgJ5&#@>bM@UVLGg~NgB3-1@lb9$RuUa8sX|HBmH7;a@;nA4 zO+fV)GN7EbhN%aj0)c0Lx8qiIrk`*y$YYQEmV#Nuth#iyM#1&yK9)jLMcQKlI^upN zvlTjG63NMNvLy>e6e-ybBk2PBkEO_$ZS1N`xsc}*AG>kGeZSfu(RyC&O!!6cL4xRKvj%+J}T+z zSvwx}034vwbKuZ(ZTXq2qmsq0iCN-}&3u0ICVu&+muQdq=x7WQ@hMbn2T_pF6&Xzt zaXknc3ga^+_8d#m)f}QN=3`Y`lqb56(;U|EQl;HM(ej*%W=Qh@$W;lyz5sx>umtB}rDSds{`e9N`39h^)({Mg+;ei9HY&#R;-CaX@*;nSLMm*nQx zfStiP^yoYQnai8b+NN0uAoIg}e)`PqxBcxE*Q~X+P0ki6TNaVZ5t6P)wqzjy)A1T=-|e1#1wL+D|Tu2!8HuSh7O(AF9Py~sUx|KeWYHDDBoih@wJr$?&R;E^)` zTH^Qu(KFfhir9k#^98?ZlYJoxxj+#}$%>LYIFu$=u_=^ox)#HM{tWGLKk2;1rp0kI zMIu+W7%Zjms~%(dBI$y~(ujef3FOQQ!4k;YmAj$;1TbFfHGW5+DrwTZKm-YV`kCoo za?c+21XUCy2^{APi28BXtL@#S|LKk&{W#*+mo?!-zQ&u8!_H1?jz67(qy6lZuP znc}6fDO_N~>JUrY4K7_B#HUF##dX>eK3Wq7i3Yt=3%oqHM05qg71jBZv@3e}jZ;?Y zGh`I~Yyh4tVyKdMzCJKl$a!GY*Vfgq9-q-Rt&bwhBFS`_v8>5Jd792v9|_kbHLFlE z9mXar1pP9i0HL5v#d1+(fw5$T=74C`5>q|>5*JT36m+dF<0|+J`E+U(TbTF!R38vg z6-A=#%=H6rApjRB0HdG#&aeI&*tqg5@Bc=NHkz1Bnq0G`fqlI>UfDlGYm<&F3oL3f zNM$TmE(uUE9pVv%P*5Wp)+m&!Jk^~&v;ctTfvbl!B4O>!=%9=E3<@nwFS9<$AkOp0C)hF>v%>`AskZY1JLEu0K}?DB&_1qRf^&h1x**_Hv%v>7tH{Z zgCnK=*KhK@);jGFbk z3NC`H`!phfzj8*dq_t(>g7ja|>S9Z%Cl zFA_e(fTn>@cPSOe>FckON=rn-^J_p;M08CO&u63OVxkOWN0VA5pUvtazeKTAMbi{S zv5bd6-_R86SBB_p3(?xzjx1UD4GGV)87;OQUs%9%->qsA;W`Fn$tIJYVCa~F>&k>f zX9pz9B8Db8a|`-60^rpE%$B9Kd%6}Eu6q3WB#Ya9j80aF#bPwa6%50NuDC#zTxNu7 z6&yjqtW;36#db|TPW|`Vw(DxLM5L|;3I&CHULX`WcQC4^(A*L!7fffmj?oJOp!V`? zZ(q8*bCY+~`>tuiaTTVsRa`62%lj&1^EO*IwK8-f$HvtW6i*`LSFo%iN0Qj}TOg-x z)Nwpj6VGy)^Id^Rzzw%FPuzOvuCE>Ln;x25&|eGy8_3`Lvj<*%|K_b=w;8)4zN-S=bDU}MuV?IVsrdiZt(0w>_mW2XXmgB05-`L1wd+#H?t zdOrNghyTU0oTEVU%`o8B0>}?=R#-gdCC$>G?9DY$>HC8=O?fI1{kiL^pr2Q2Iewm z0(pO=eejZ{>DI#oDJmm5x|YR>H8fJGm{_KTNQsfLG#$+XimGw&@bPn6XdMHn;d3(} zD7u?>gHxaV+H-gA>797FHUwsBnRhSNh3Xqy(YBq6B17k*78*iT_8v?!natrhE}=-2 zXsm^mU49gwK{i*WBCj8VL-iIq-_vCY|2Y^a34Zh7aOJ>9Z+q~L@+rwo)W)0YxxVLO z0N6nB<}d&2gZut?<8=r74pJ)0MB|;bGzch)PPvq!FngS!5x^?tn9Wp>)g|Y%&{GnT z1pI2<>jjZy#h<(H(Se7){o~y`YLZFS9Zj9{x)=a+2XUoRK1+LR7(ozla#NUPl|MW^ z$u(OWFufRxS0-=8Ni>$3O=4XDz`R3?swcanv)a^WzV^(WdwNbwX7*h2dn*9uPU6ds zV`7>%g+hf`Q#*!kbIlb|{A!M4qbF%x9-&%HGE=ab$vWo)-~m-ZI2BmdHq4&ka_hpNFq(1+k==^MykS3QWS3@)RJ=*`s?LXT6K%L86P%>{7fDM%LcH4nQ@6Z)T2d3$0^|NAG zCqci=#AFgfE#lZN2ohF#hT7`RJV!7#kg9s}AwM3_+|ik#=YZ!RVyTg5OHaJA?s}tKa*R_nIcv8qmVUO6FV# zdR$~7+k0Lg?`vs_<5mk8{s^m + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Select a game: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Command line arguments: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + WAD + wad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WAD + wad + + + + + + + + + diff --git a/games/NXDoom/pkg/osx/Resources/launcher.nib/keyedobjects.nib b/games/NXDoom/pkg/osx/Resources/launcher.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..7e7859ae3ed051b76c381ded90e1a05bbd97aa25 GIT binary patch literal 31078 zcmeEv2Xqrh5a{hnI>{$v4%3@0+qm1ZCHLNC%T2cBf=w|l!WOQ$P(pw^LJ7S?D4~WH z2qc8wA@mx02@nV&5JCt6k`O}R&z@XFOY;AJ|God-|28L|?)G-d&d$!x%ngOr<;L1N zZ|`#yqA(?*#FT`h<$dG@-MbAi)YKZQD!X^9D(q({s;kZIR!~z^YJ|&~-Ri2Uttm8m z(YjW61|_9rlr7~zb)(!UFDjkNp!8HGl|>a$71aCGP--$Yh5Cq^L(Qj_Q!A*I)ECrN zYA3aqIzSz!PEaSQv(zQ(I(3)&iTZ_lh+3g`s1xdpx*%`lhx}0}3Pa&23dJD}ibshk z3F%M<%0WF)8LC9@p&{sfG!zX(!x4vgGy;8q#-I<;G&Bp%Msv}}XgOMe)}hbQRie`!CiI$62i`Iy~6m1Y~73~)t5giqs7M&4Y6x|ekC%Ps2 zS@b~kSoB2nLiAEB70bld;@0BM;x1w*v9s7q>@5x!hlpduvEo#*PMjm|E-n-oiOa<0 z;sN4;;^AUWJYGCWJXt(j{E>L6c%^ui_;c|W;!Wbc;)CKt;*;W2;&b9}#ovo>i|>nn z7C#dIEx{6zgptT4tfaHVMq(>*mZ&6ZNw6eD5+~6}QYAV`t|U)VC@GQ@OAL~}k}^rT zq`#y_GEg!|GE_25@_}TeWUOSIWU^$6WTs@6WS(TcWU*w4WQAm<`s=nv>I^dx#RJ%ye@&!gwlAJYryCG;x#Q+hSMhW?!1OmCsL(%b0W^g;R% zeV9H%pQO*zSLko(tMoPcJNifZ9{m&jkp6>yO8-f}kV>SqR4TQUwwAV$wv~30c9trn zc2Xy)r&KBRlCGAnm9CR+kZzRjkRFmAmL8E_mVPh&S^9_csq}9dB||bs)>_s^W+Ste zxygKFVX|;poGewQljX|tWJR)aS%s`pHb^#9Hca-RY?5rUY?^GAY_4pfY?bU&*;?5; z*_X0yvhA|nvOTh+vQx6JWfx_aWY;Wm85&tp$<$irOJ)PLluBbZGMkvq%ob)VvyIu# z>|k~>yO`a~9%e7IkNJw(&m3S5GKZMM%n{}&bBsC8oM28erEOU-I&s<i7`th|-nTHadTM&4H5PTpSLLEcf`N#0rBMc!3zBe#_+ID_o+eM1XUO&POnH_(Tb?7&llRK%R#{(O{tab8F_fIL zq*_o`R7;AbT2aN zrs{RZ;@a$j@_IvUKHCz$niRC@3N&u`o@5vd_dBNQql$_QwYA1VW4W(QVfzZ7DTbjSUqXv|!YHG8)6_pp%*5;WIBds~i4d&4gJo=tTD|tMPlfVa$ zr}B6@k8Yo#6hN~bW#0n`BTuFlR2VoBCkEW3s$oScDj<}ep&ThE%9(P>Gxc8yt-6~| z4Yj@D(fZoDstOaaOQ4-=_eRpsQ0@T0gHi%Y$|@6g7E_)a&BcGqwxYZ#6{V(pC|}Bt z@}~l*Kq?5D2U8(bC>2J9QxQ}o6-7l;F;pxSM`@^d_|;O0R1!>$6e<<&rNJPWSe5~! zlFxQc)o0ZjYP6MghMK+wMFwr1p+Z}1sH`*gH5zJwEK}o5V_mr+H&vffFi3BF&(PFK zw$U(u83rJ-rT~U0pY0?x(SQ``i)svpN*IAUfMI%u+$v9bhE%E{D}7nIaCQ6LN#3>(2%IL~KWH9n=U8(eNk zDX1;uq#VV`xB;A;tGD0=!fzcnh+|l6-DeO*aTXlKO7qzcLx%YHd3z{)0|SS8D2Dj? zs67;_AitqQK?q&a0E2=OgMvtgt0K9ezOty)Py+*OLa_G`wXcuTPaOo0cn1uPwYSrIeBCN0o6cID0OHOXV`S zJg$%{jvZ?-nS1wgU)lzj-JvD$D2%;5B^#LrCDGf~X7(;n^P6Iyq ztPRYA@^YAu$yFsV8OoCj23OVB#Tsi&DgY4I*H;^A2o?FPW2!zADAX7Y<;79u#*)ek zkO?x<+R9o(U2V3>jDxX^t0ZDn%(djKWSkugj+~<`^4WGnhNuF8j{!bp7<~L;NK~q! zLoZXqsNsM+NAc7M>H}&dHHsPygnvklrN+Uem_SXWCXopYm^aD@5vZD~@&<7R9ILBp zV0M6n5Q!?Osj9Cmj;SiIs)5mmCrb-z3W{LHq#29K3^fhtL6?Lap&1NTgNzcb*91vz zEv7(@T5t-k71zds>&mg#Y$Qd&XzLB-K)IqoQ33-S%$%d9Qq!pEK*kJeCN+zi4Xh@^ z4FlX)KpMUi5p#&NhaTalm6Z)=&9%;Ft(8O*8T5l|VJc^7H9(n3AI+ua!9(Qx5^65x zdLH`zm|8$Bq!v+&sU@&zenKrHY$0Tlt_kAgTwe`(0mLk(pst|2s)XEv0T*s@UAT5E z&9&v)XPe;lEHW`txO<*jMSThoRs*Cp)MwOMY8|y09?dB=)|q;*0MUjq2kmVQJqlW} z8Dz4z(%)Mhpz`wx@S#%SOXE*~LdA->4qTUW)OzYmY6En?k=jIUrnY3J>b0?1@DURO za8jy@4dtu_*O8^T&S$7?&~7`m18yjbffQYx&BF^bP0t1{kwb;XIO}uzhu1bOxL!!g*nRSymLBd%*dczBQUGI1h*OOQrP*$v6SeL`RKv+DteHc%lb2RT-qc z8%2pjiw&`Hrt9LqWmQQ82be1&ui*42<jB0MB=!4=fR#lt!9O1gu}Mg^eGtEfWw zECQ{46AYAEQ0xPQvl3w^TL9P8&|VG3fC1VVK${z(RT*3_f%Dr<_sMs%_pN}>YPeGc z3x$y?hvyovDum_3^c?A<3J&s(^m|w6w+Px2cuF{8Y?i^Ap@604KHM*bvlQxvaAgqS zR{`H+;A%bGD}i%!D5mGr1YAuxkoyG6j}1_&;E7@ZmgzYHl`L(fPb0K@5AG4%1j@zj zVfW|*M~FCC947XL>+#S}0X3NN6t0H~*BYTVQ%-36u?cE_z?DECTqD$zvu4hic)S<* zRR>qgfkLv1l2)~V&2xCBtl??%XMj&rI@P;WSI?T1uI;@XTAQ#?jHt;s7M+^>uz~Kk zjoO>gJzp6&ow-~Hl2ZJJTmXF7m3}R`E;&aj;P3a6^OC!8_KoB!{9bOtCk^m#ln26l z6Awy&52kO;l2s&JA!AVvzhqqA#It$KO#P5HW<4O00GG&Yl+X*gTLA|dS%bh+)A-fH zIk8Ln3Qv1d=2*TiQPA6=_jh!l6c;A!IYKGcuv-r|QKvXB-qQ1|<)QccR!-?uUEO>6 z`+pg#o9~iwFpNq4J(U{a;r+SyeeX}a*LXknzTVuz`=a;H-sim+!=0Z*(?uIaJHf-T zO>~@6z_)Fpy`rtc*&5Lf`2C{kxmP9J#DiBQoXA^IgG3V!)iubJx$Kkq+BnAvzZ$tk z+Bc3=KY?p+j)b|ykP-WD7@7BDnstqH!ZbR}NhiE6IYgH!UYS{00LcipFqxIL0KXi*4}PtUY2Fjus!$JM z4Bs*n#5Q7;SPPm-M=8WnVn1?r1f>x31;BQKV^B~fy4s2RjZ>X56>cKU}lF~YbU|%Y< zl|@Pqh1y#Ms~fSINE?cJoG#cxsNM0R`kDczYsBUS?<@oMR2y&**nr2?1x7>-8`uz7 zGvmMp(1G7Im+B34l)^~X0B7F^>wPpe9z3u!!CGAi#_1|BAlHMHw*x$|2dQJ!*VK9H z8(2?nga7p*^*i+!LP&~Qpw_4(vPF)_9jQ?ucwpmDGWcC{Q6E$Se%E^Nx_*GhgP(OS zT8vhqFTlUL7aal5>Sc5j{fHi+XIO+S!JFC@J7F*Iqeg-6G!ys2CAdF+503=z=|^}8 zUV}H`z2GH1k8j|g@NXhYBp0<4*@-+wfub0Z4!od!MKz*fqH*B&Tq0TvI^dA#tmua5 zzUWUe4Sr39*b_!EL7W9X%>LqG;tArp;IrH$-Y-5YzA1hvej#Zg=^}9lZ=_bzT~Y!* z$I;+nTrSxNzQpt3J^Y=f>2@$a0Wfa4bU%6sJpp`s>*zi7Y5ErZ8~ErtO5LSlQk}Fw zS|=SXog-Z%-7P&My)AtzlY{q7Ez^L#67ZL&IJ^`NCiOUIT`Eqk|oujQ#wYDwHCE@XdTnKsPzY}KWTlS_3buv8|OCK zHvQU+Z}VB3lWiWhwQlR%HoNVhw)5KVY+}!b6CvhjYPU)Qnc3RNsK&Shi z+jI`;T-147=k=YhbirNRx@2@2(q(Cv<6VC1YST5oYjxK-UBBvj-=>{Sq)k7Y88*9Y zeza|E8*Xc~ongD%_MW1xB1%!N_(-u|@zAb|U4mV`-D10wc7NGB+h^I2uwQ3?&4F2grHa>P- z?8!LmxU9Ijao08Wni9=w&BJ)V_#yFo5+n&p2~!g;YP)KSw5zla69W>5ChkwNOwuRK zP5Lg`Ex9InTMAA|Oqrf?HPtb-GIg_#(rIOQplvD{9%#@sD=(!A`v z<$1sLi0d)4$L*eeJxBMv(95~kpk7CMcj{fU^8#JLl7im~ zwT1Hw9~Q+F%`W<>II?&~@sEZu!!*O4zF~c*^}SmXRx-Wh$I^(>S*7=lF~+&ZU;8EW zTiEZ9GF{nb?c#oJi;>ia&A8Z@hbtE_P)~NVV zt4CXnt{HuCOvsppABsOTet2@M&)7L*UyLgrcXYh>_*vthPbivjbfRkFM-yL8>O1M= zWdF$vrqEL=r(BpCF?Hp%R@2^_c58ad^i4AqGsew$GBbbXky*a87S3j7*U!H3QSwJy z=5(7gWzO@trE|~Ei=MY`ewX=U=l}6>@yBNtL@rpnu8n3Qj{o|URYrg(0 z_OmT(J=ZQ?*KXbT&#BMrKfm`ypD!+~Pg=k4%fK(!ZgAW%e`D*7<2Ip9gEu|gT)O$j zmfS6;w!7crBL%y=P<39z3T#ckF!X`O_D&E?m0U^Wu$5#h310F2DTil>t}& z`i27|e%v+o+N|qct}pr4_1kqf{BP{M8GG~iclz(Xxm9%Qr|)aOe|~%94=sL}b;tJ3 zs=MmDJATys`1QRW_iq1G{nKCfNB`XF=lKs@9&Gp}@|WWeyFa}BYt64OA5D1N@$rf$ zzEAf3miF8A-z$Fq>yL3yJ3d|cXW*ZQp5;8d^Vh)V(&r!j?fUn&7fCO!zN~oplIvu0 zLG7Y;gCi-WzK;0wV!;Wsl-dQJ4_EL@k#D9(`>3y8aXl@e_EWB}TrssfNF8eQLoES= z;5CQVQNf{g96VGu;GeS1XW0hVRFjX++&y&)tO>zA741#Mcq>%IyJUiLjyf;+Vw*gb z#F_UAb&k3~T@=uY5`r7#Do{cGn4Y^#U1@L#3jWPy)MYSMu2R=1S8!-Hx*JXIXlU2u z0GmZS@CuR7X)y zsXr->dPe;PyV<|NoA!cwNv%Z`*j*TjkQhm*VkD(B$O17)4&Dt7vO+BpD|q+Pz&TY_ zY%CHY4Fd|w1*WFe82TD&Y7E73#U%#tnWh*j>q!J6pKVPX$>3qFET}UydQw4jqU-DG zswxEssL%m~Y~uRY8=*gNBf=P)J*BMxH@qqI(9kPkGWb}VT+J|E1fU6%2J~VL0A0YSR$m7=2@e4ms|Kc3)f!3A2Y79UotjN*{StmgMpBWSJLhUm zkBFo=H_nB#ZzZEFI1kRb6`EpU!6Gh*MNQsbWQ|%AZ?8in_?XB~D@j}8)-`X?o-|-t zayc#S8`PEh6WM^l3y~>ghwPC9>ITNI6AXe2az$=n24m`5q=cdHB6F|OP*GKBEK05_ z65QL33(q`FFhg)l6Qjo@x(K~0IF4kSp32*F>08!$UljDrlt!UNXB zfo{&j8X|-g=gTQMKh71T)ss`71>{tKrW*MmUy%C7;jZQUxd1LO7rd4RMJ0TkMFG$( z5Cx%N6heH`jj=XhGK^wXeNB;p_@Oy3PQ`fx77c?9aUjxXOsS!$tfHW%Oqd8L0!0d< zVRA4xKEDJ-P_E{HVujv(gr=kyfue@NZk1nMRh?B$2GycE*qRMM1JNKZoQvQh zxhO80i{WCqI8MXG=d)f#RTWC&UpFYL3m~*nSXEF{tgME~X{p$7x@>%K6&84 z0-r$@@K;q*R$O0Oq4M_itsc~WaD8ckx_VIUfPvlyKfl7-ih)H10mVMGg#$rp*$D76 zwHl3LfUnZ~O<;}mr^df|udRt{GS_O;1Xhx9GYQd1G>Xh;(;}@m)Gb9L(P+vQ!Yc3u zLYxr&4D^NQX8>6bYcv*(gU$5>A?UUlO+=H>Bw-ntf~JyXheY`V zr2zp~5U8k1V+C-omRy2pp@B%QWcz%TDfXoT9N2bG4 z^buK+P50)Z`HlC;Ok9TMHBN%&1=cLKi58%Ru)w|&+vL(X-P@v#YCj>`NY=`CM;rS# zM;p;vY7&H3n<9Sc5JHTpg78dbv7+2qX;6Sht*;>XI!9PSjB zuNjLd1d(9{mu11_Sb!ey+Po4SM2FB}vQ$B6g#5I^)?7B%x)0ne4J}KyQKeLKndTF*B0TC3G1y z*Ei@Yx<aI#5Pe=lgK zd=~iW698d-Uw@Nf1a=X`_w$AXkYR_9q1V7b8V07(6EKcO3FgsAK!+Gd#3&jKjwB2Q z(S0z9O5yAw`W4C1BY~x(M}Q&V%DGv~fM;M2s2z?GNiDn^7W6p7qxxV~Jmj57cSipo38;~yL$_dgSPZ{-< z3ebf0)r!ojs`7upT#3CJF!wRTyqc>rVP5$P=0VM@_X#A~AtuyGqR79Zj>F94tqeyu zqHeN4iI|xfU%~Y!H1sfKrH~-8A+I@oMUX1$Do$8x+NTJ!0L0x}(DS~&a2gm8Fm$MS z3X3`jl3rjH@HYPeVR?a^tzVJZjIQjy&qjqpm!% z<&hna9C+l&BWE7D^2nV>o;>p6ksptOc@)8;SRQG4l**$F9%b_=k4HUu)SE|rcvQ%v zQXW6i>y|DOWHp;a=0#CXDb*sszu*<2Vjh zff0=$=K@Hc6T=>;F~2FLpb~alkR8(o3@fs#X@%@xzUZ?eFEK$ z;>5kRIZ?6AB=j~8EP$LFAuk6gGV6mX!>ffpD!321VLi)*94nJ$Yu?Hee<8G@xpCaE z-lkTD8k5*Hw_5~${LRpABsYPZ!wqZDLNFF!9w1^6=TWtI8{Uq0Py_HTyc>S^f=PUX zY;QsIoA&aiw5Pa1)diI#`JAYROk;H|H9iIWo0D4Y0rUCrdInAtzlZQh*d^*@(sCA_$ z1GtGiYTKMfxPasjnz9E20>HFT2?n%p0O&@a02nLSRgoE>C~8;~g*gvPu8J(gkSi## zPh>%~V+Rof;U-H_3z3zmCEg@zC9)Q^7PS$zg%DJGQ3p{+Q72JnQ5R8Hk&Vb!q!8J0 zi@4?78g4zeh1&%qwVyl2o#M`N7rAe^Z@F9C9qvB&hJyV={=k zi5wdzgUGFMGH^?|C5@84m`J(_U$57sxKUDlynO}J>K`Rl#Nf*!hDfR?NEA$M1~O*D zke7jq}G2S#S%!d6iBHT4FFQs04ZyLl+U>@^4Tu0lTuw?4_-TCK{Gvr{}VmK zM8lit8QDb7Ms7nRJzqA{GxlBds0I7wU+8H8^t2G@nJ$_E^sEPZ)&o78xXt-&=hx{0 z|Bj)~Skz3;?Egg0e9^~EgQAje7|=L->p%wg8g zh9jTb!R>s@v;m!HsB9)?<9{M%n`nCzF?*Vb*~{%|BxZLrF$dm7jQ@Yp0WE=;mI5)S zL|+3jyMUNoK+HbwtGA3zEv!;~4XS2x&c2NtVe@F_01#ag!RAr)4KF!LHr}R$`+vlywHY>@0Gm_I*qrH3uu*8W!S6z-tJvl(2%YE7 zy@8M)SX=5q)85D*mUAKoZ)Z;%GlZ0Y(Aj2$E`R`=k9cNkX0Re|fDr~BY{++FsS>N- zg5_oI(i>Q+h;^Y>3)9Sxyr%F@EZdr484XxoY{v3R_XLx|dnZD1V$E9+y2f373qs(V zQUwXiC2>=|8=-b)2xS98-!vn1Jv)J@taqZ5E6#fhIybo+Z=w?j(^dt(GFZKR$>}@! z)7}i7et^!m&FFlWLrmkohIisqA+CH2KDW8=-^9mP@VW?M6+pZI@5HBr89u`RpIgoN z{LljeAcGX?@Rn8GD>#{X%f!5RgvmJ}9!*qUgJ0+#_oK-?YC2@!QiMS-PV#=#(4ev0~#B;=R8`m1~!lt$67w$ph zTJv+$S|k4C9czsbVEXSSS|?a*I+3+TyjHvp)|&gU*4zgr{gC_hEgKtRZ#FG7;`MJ^ zXkOn)iZ_e5G|{rNiI(5ECylf`Zl-15YqSuz9NFbHtUmv2ZFUAyIt!#67oPx99swzj zfRx|4KOnO4x=GU)Udt*rBj)S>M9g{dg(hOYX(Hw??pY%-e>M|y;~m79bm+g>XI+4p zE&?(4#6JNsPl1@HK+JRQZ+M68t;D>t7Z5-APxL$%KWU=p&qjK91g~dPjTF6Xrs&0M z6g6&bRHkL>Ur6c-By}YuNn{cWAn65=^n%Oh5$2KTABbu;Z6ua&BkFa(xTKZD8fH59 z#U<^Uj2jJ)q&%VpFF21R=9690rD3wSX?VTr6&Lt__IrzLn*H9Uxej|vIDyIjj>T8v zB5{3FP4bB0k;SWu61?*&e^5hy0&0H$xQy5~>q$wF=sxUjn-nFF}}Eu&HsHU3WBtuVtWh2UgqhEq%M0}!l;aseB#w4m0Y zP`wkuG)el~5VYn|t5*>Oo&|xK5-6AgD#2IuPWtNvEf5Yb{>Lf7=ei!Jw12-&-(5f=?%ZM0Bm2e+?q@5b>tIh9smedRPAMvOQ zH!Rzvz04bQl?)LYfJeiI8mi94j0V993U6IVfo zhmr#?xtdd-gN7>PAlZg|B|9WLCA%QiLCDky#(=OeeWWu>0y;RZ~H(71Y(&z~$g3#=>heZ6p^6 zs1S%Mpl|?20+WBDu1yScmt28-9Kx<^$cuvrLa2#dVXw05rsO-xEe_yAU+Z|Zy?az4 zygLi=C0GoqY9P%*;0q+AR2D<(gK#sgpwduohRYqiNb)1WC6XJ-qnLLPe#JC=l3yeb z3E`n+_;?h}qbN=d%zo1e2{@#CK;)~cT6lH4X-1nt{vEjRlt7LnTuAsA$S))>%^=6~ zNW-Z!6O6@%^wO+S_|x1mEuq@bQqplE={V(|JEmLER%RV1^C$^APOmrCrT5Q+Y_bXx zNipxe4fNiQ^sXblr@yOrx)TC$X#lTt zs0pAP9_79ROw(khg9w^5AnKXK zsD);^Y@|M$&LPwn@u&ovzD1SMc_t>)z3ASA`eM_l_T`bGDP4^&pbL>Nk9P8C7Z(Vx zDc7YB$}Fm{3vPr`N*f6jBah1e1xgiNZ3d-`NBw}wi@Y@gy{)Qof46&f9{k1h@R8bCy$`W#vq_Q3yOE7zn2AX*H<-lxsYB&x_qBU z!~dnr<@5@(E{E}GD5uVAc#$3^M0!D=txh<(XFW}t``!U(<6EiBr@WnVpHPGNWKmz+#o1SB`82~lsA_>KtNdb z=sTumZ-Qyro5rbo!n9UE0!2wZsIH!*e=TH`MkObk0k{tU9uNRC34q!E2;jF@0L&un zY}d$6A;(I{Gd5HfnSjNl#3pM~&8c|?z@8Iea|keq2ELmbspu78bA>fCrK-lDD6T3J z61jxHov?0O6VhVMFE44Er#S} z3xp^GDx~_N1yl+80#d3jQAYHf>WACG!lINWNVSqHl5_NSX^P~I)LxnEMIFQy;Oyc>oy2oQoyD6)UBu@_UB!<@Hj-8%TZxNEAqf@PNz(9#(&f?>(v{Lx zJX*!kkPy^@YsuL|wzLQ23x_}oZ7QT8W^kD>D7|5+?F)-z8LXk8=2!D*E$9$1J3;I4 z2=*tDFd{tql1CeOw24Ps!4?C%28;|IZ3FX(M>}AB6I3-Qzum&B2ul_$F|Z(jvfTq~ zzhEzet?-p#{vQCH0V)QjI7~vA8az5I2rJ}D%ma_XB8d1d=T<@7Zym(SHbQ`DJH%!7 zauXouVLyaUj&Ucz`FI_L*T8Ff6Fil-VfnrXezjk~A@v*hasDEKXC%a) zr9$`_w)~bnvVx5#kF2>NJUYgslRUc4qnq3;A?-!FhO+0;r>|FDGTVMgzmTq%eo55Y zXFOWNqodtZ3XGK`f!ZW#o2c?nq*`gNv`7kU0A2!nfCmR4?ET7?$6mS*_3Y1pX=OAcgtx*;)qiiKAIw6%IeH59OcEfnPW zYHMSSwL*CvVMVe40^BShO;7!wyL|1rcXF?B{X-ZgXNL3%;hylUiDw|P@Nc7uXL?d2 z2x@1;H_$zPx6yZPmw|XUq%0a^|_t^Uq}}xz~9M(W(fj? zlt&ksc+ey_Fg@WP7@8nAnIzj@pi!ov%2&RwzTP#F-zf_wQ`cM;1ar4}!2bi%pfSIc z?0gMr&>HY>uYh#6$<<>*I|61{qlPutEbm0oORr%I8V&w|nL}8dU?{IP;o5^LUv9nvyhZPIyG$k-0SA+;X^Mf7 z1Hj1SGEJ}sI}4_eFpGKs#smsMmz+21Ad=}_jY&zO?1n6}?o_RG1>|{a@GdG!R!2el zh77)e;*(iG0vW}ltHym*dN_5z^(d zk+M;;(Xuf@GN378s-XlE$*_WT;1~yn))_(Hp5@Uw9-XqLAQ}IxY%FCh8wYqzkWGX% zL}ej(B_UT#Sp%<2)j?%dg4t;veGRWAkT)@cy}Zh+Afdk$UWo8A-+G!z3<~u22~w;4 z0uaO|1x3cnx~kezMMA7O zV<5RkV8SJ^<=sZk;UsIBJv%NZvA`AN_P2`aENL6uM74h)SYP4U{S`JEK0C04RG{@ zqXdppIE--ggQJXU(_m4OMZV!zn%;Ou{=$7?QNHpE*N8$m3I4W%!y1m(aI}G=EgTTD5w(Y-0~{UU=mbY+IJ&^m6%HFXY~fJA zVMpLdm&36Va)fb%K`C!ADCJ;K%E6$NgFz_=gHjF#r5p@OIT)1ShH5e>O~#A)Cm59G zUrp!GeuuDJnHH_rKH=^jVO=n-4)6(AOa`S%12=pMc;W_oaw6E16TzOG2=?SeuqP*i zJvkBV$%$Z3P6T^$BG{7?!JeE5_T)scCnthEIT7s1iC|Ao1bcEK*pm~%o}37QG|0Ua zlMfmBup}QWfkjjtd|W4HB&Y|AJR%>T0>}QJ+j0CKPp}6z|NlJ=$*2AIJ1EEmP`xAifPHPPzT1EY0b1@+A{5!_Dlz+Bh!iL%yeP8GB%7YqhRb9 zd&Yt3#yB!gP%*}Zab?^XcgBP9WR#2-%mij4Gl`kZOkt)n)0pYZ3}z-X zix$JQnj9!kILWr977L*n-ClkL5hJt1ZFCKgISjA&Ck9~OT%VR$t`|~(}$ALT!;&CvKLwFp@ z<1ikF^EiUXkvxv#aWs!(cpS^)I38jg={(Nh zv7X17JkH{AHji_7+?~g{JkH~B4<7gAaW5YC=5aoc`|!Ac$AvsD;&CyL4Lt74;}Ra1 z^4Q4ZempMYaXF7GcwEWjDjrw!xId3;cwEclIv&^acmR(F@^}!B2lMzn9uML1`#c`X z<6%4=&SQ?pJda24_yZn~6>%;o8eyl$mzy`8GY%m+bhO%L7I2*x6vQca_ z)KQ9M<5&$F&nB>1HjzzcQ`l5i$ELCAYzC`mGubRQo6TXnv$<>@+k@@N_F{WO@rFK7 zf2oiyVvAV=+m|h2OIah^k1b=%*$TFjtzxU${%j3f%hs{=>;QHkJBS_3zQ+z>-)DzH z-KOCz$MWn5_5*e#JBl66j$uD!$Fk$t@$3Y4B0Gtl%uZpaveVe<>u*=xx>;$CpeRE!%g7I2UZ1ZB+Z!G7?A@|+Ry-vacPERZY%({B%yQoJE~PPe38p^REG zodc!0deFTgf>aE}`HgfrT?GaD>*-vM5=WEC&ka_mK6H<;x0Wg|cE+coH>K}xX`X``J{zK*uD0MG|a`vsEkbQe7PwxjM=%b*d ze4)HbK2$zRK1M!PK3+aiK3P6XzEr+NzDIsS{+;|6`3pw2y0y{^A>eQqPMX<=h+<80$<<8I?=<7E?VlVg)- z)7z$xO`%Ph%}|@sHq&k9+AOtMXS2;_zs)h5i?)<4wiVk-Y^AmqwsPARwk>U0+m5!K zY`fSx+WOjt*v8oQv|Vkx$M%fvHQUDuq-d>hQp6|{6+IRG6~h%%6^j&06sr}VDb^`A zC^jj!D7GnfDt0OMDE281C=MzPDUK+PDNZP^EAA-nDefyCC|=qjJMi|}(RNZhU%P0# zY`c6rqg|cdP`gof6Yb{OErfz!%k5U$eQLMHZmr$tcI)jn*zL7DVRy>zwB1>|Yj*eS zez%v{OYJS}<@T-Z9qpC&QT7^pJ(LH_vCp+Hx99A~+Rw0`WB-Z$XZD}lueaY|zteud z{So^!_CMG^cEAoT9XdETIrun)I`nsV-(jl5#|{e|7C9_-Sn9CMVY$Ofhff{WIIMN} z++n@Lc847fyBrQVTyePSaNXgC!*>qfJN)2q*WsSSeTN6#6x~9*6?Plm?aOX29TkqD zj+u_V9Q!%;cO2+A)p5P!HphLACmhc^UUamXg zXNj}a*}_@wZ0X$1ImNlaxu0{nbER{&bARVr=Q`&B&V!uCI!|++={(zcj`IrV9nQO) z_c-r!-tT=NP<2F1`KU7}rLT{JEUE{QHFE;^Sqmt2=Tm!2+l zF2h|mxa@SnJB%MUJhUGBL&c6sh9ab;b@Tq9hgT%%oM zT{W%=u8FS6uBom%*Y2*lu034qT!*`EaNXp(#dVwO4%c0-dtCRq?sq-y`ofKZvTGtY ziJR2T!cFeh!mXtn>(HjkYi zdpy4KIOuW2s8hEkS*njzb5-+I3sj3#i&aZht5u(?)~hzCHmSZ= z{igau^{47D)!(X@YNYO}c2c{mJ=I=nmAbdOkGfD@q&BEa)JAogx6r@2Y=Q|E_+jex`ozSZLl=@8cnd~#wXS&Z!pV>ZhptRp!pMyS!eUADZ_xaQ3FQ31CUiebJ z*jMaJ`^tPRd>P-?z8!o!`F8QO@eTCt<(uzY;9CTx084z0zGHl+_|Ej5?K{VJp6_Ab zqrS&|PxzklJ?(qe_q^{#-%GxieZTX)cQwju39I)roz z=@Q}+k`sp$hb{?i#KR4+swm4+#$o?-yPXULD>)yf(Z(d|>$C@FC&vhYt-O z9X>vMV)*3nso|@`zYaeWelGk%_@(e~!mo$Fh>%8DMp#9#5!MkA5z!HG5t@jEh{TAL z2wg;aggzoOqE|%kh&~YmBi2N$jrcrbeZ$+T1N&%21kZQhDSz5Mn%R%Y9do3heQsGx}IbCKsGFGgO8{3WVOlx>uKltYwblyj78lzWtClrl;aRTfnlRUK6mRTotsH8ASE zsL4@tqn1UjkNPU=K-8hAqfy7B&P3gcx*c^V>R#0Ss7KMFXi2m*nu)fIZXMk%+9}#4 z+CADcIv_eBIx#vqS{I!j-6Og@x-z;tx;DB#dT8{d=qb_DqGv|Wj{Z1$ZS?2S>!B>? z=IH&==c6x1Uyi;SeLeb4^wa2P(a)n_#-JEkOvjkcFoik%m`C3aiv&e+|tdt>*<9*n&h zdpY)M?6jX86E$-*>os3#4r&f-j%iM6e$hPAJkk8Fd8+wK z^LIQQZyWCs?-j3xqNUmKx$!;Xd&TF+7seOI8{-GWkBJ`}KR$j^{M7hm@tfke#BYn= z8NVm~aQx-?Z{n}T--y2z|8x9{1S$bTu~S(>*95l&&jjxTpM=bWoP^wj9tph@3KEJE zsuOAx1|$qhct2rS!UqXc5~e52N|=+dEn#QE?u5Mw`x6c&97#Bt@O8q4gj)$eB>b3g zU)w^v|Y6J+HP8RZJ;(p8?KGg7HSRJ60K2NrmfUgYX@qFYbR(YYo}>v zYBy=OYPV~5YWHZr(jL$r)gITL(SED_PJ3H>H_;-|GSMoLO>CXmF0n(RL!x7%cVbv# zWMWLBCb1;3Ut)P;Wn%xty2JsAL!eCS2Z=KhXD7}{oS(QbaZln`i3bu7B_2&Yk$5Wc zR^si%$4TNOX_5t$a&4L9o#d0`mlTi`oD`N6k(8E{k(8CxJ*h`hX;QzW0ZC($#wATi znw&H(X2WffY@OUTxqWiSNI63ZF7EWpv8elnE)TQdXy|P5C@! zeagm^%_(1{oKCrtdMfoy>bcYlsh3i(q+U(Eo_ZtoyVUPfe@MNXdN1{U>VwpWsgF{h zKtcMasn1fMr@qi3omeN;F}fByR@YkBPS;V_MQ5wC*E#B3bnZH(PNnnJ1?YlxVY*0N zj7|eZZIg96U4|}8*Im~`*IQShE7q0h`spfk)w){U0Nr5S5ZzGSa2>DvKsQP^MmJVB zUN=!USvM7m;m*{}*3Hq)(|xR4s9UUCs#~U8pEEPZOaCGL zkMuv&pQpdfz!~xk%M7awMTRybIU_Ygmyw>K&&bTk&gh=OXN=4koiQe3Y{vME2^o_z zreu7aaWvyZ#;J_c8D}#tWL(a;n(=MM&5R#1e$i8Uk)GCD=q>dv_15~f`VRU|`WU@N zpP<+3lk_Qih!N^D^uzTd^dt47^&jfT>nG`_>SyR@=|9#l*RRvB*KgEs(Qnu9)c>IW zQU8WBqTL;!Mv>?@V>3Z>E1{P-bXm1QaNa&D3UQWaeiUW*Ra}Gs`k7 zGy7-OW`2}8FZ1Kfg_(;omt-!@T$Z^a^UKWLnRhdP%DkWXbLKCZzh*wk{5|u}%x77m zELj$lWtnA_)gdb^D>Ex6D>tiWR(@7tmLaP&t0L>YtPxq0vZiEB&zhCBIcrbW!K`Ch zSF^s&x|ww=>tWXK*@|rYZ1-&MY@clZ?7-~Y?ELKF?2_z$*%jGU+5NNYvIl36&Yqq< zGy9|LdD-i-w`Bj1n(q9!=R1xAcwBKbb);yDrj9wfqH{EL)45VdI;7rxecrG4=kZ(f39d zoBAfiG&W(TsR=jDO$XD%^fGDquQe%Vz4_6knsl?n>@pck%B16Tiq6sn%A!kjg|5*Jx<%P^hwf1h<%&Rq?8MH7X(L+Fp*zYUt}fQ~aJ^kW*WV3t@otz)a3fu!Gfw@3{t^F}f6_nW zpZBx;%lh3OexCo>FYurFMgB{_#DC+L`S1M-sVX(3mIO&%X&?%ajzLaV5mCTYkGGD%y z#qy0Tmv3d2d@t+d2iYh;$rkxpw#s(dCA(#x9FW6uR8GigIVTt8l3bM=a$D}meaV$a zk}prCP+mx}yp~dVC*|_DR?+HOQ|oB3*4GeitYO+rBebQq)^-}D9kr8o)mZJJy|thA z*FhSu!!$uhYN95oRbQcFb-Yg0$vRc1>r9=k^K^kO(j~e~lXa!8*0q|V8#GlnYnrC( zHr=Tix>xt>K|QRQdQ4B~DLtd-^nzyTCB358^oHKjY`vrRG)Hswq2_76KG6a#)aP2H z#rjH1v{c_}nU?DZtw0r2Lk-kKZ3H10_0RwzXoOINp((-Le(90b4^jKg?Lz$8q@6imZ(%)l(n#$3$D z0xZO0EWuJNM>1Am6;@*n)*%J!u@R}*ge^$JFW8E0*nwThz#ius#d=E{F|V0|MmYjFz+8?l+_ym literal 0 HcmV?d00001 diff --git a/games/NXDoom/pkg/osx/cp-with-libs b/games/NXDoom/pkg/osx/cp-with-libs new file mode 100755 index 00000000000..f4869063f41 --- /dev/null +++ b/games/NXDoom/pkg/osx/cp-with-libs @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Copy a program to the specified destination, along +# with libraries it depends upon. + +src_bin=$1 +dest_dir=$2 + +# Returns true if the specified file is a dylib. + +is_dylib() { + case "$1" in + *.dylib) + true + ;; + *) + false + ;; + esac +} + +# Returns true if the specified file is in a system location +# (/System or /usr): + +is_sys_lib() { + case "$1" in + /System/*) + true + ;; + /usr/local/*) # homebrew/manual install + false + ;; + /usr/*) + true + ;; + *) + false + ;; + esac +} + +# Install the specified file to the location in dest_dir, along with +# any libraries it depends upon (recursively): + +install_with_deps() { + local src_file + local bin_name + local dest_file + local lib_name + + src_file=$1 + bin_name=$(basename "$src_file") + dest_file="$dest_dir/$bin_name" + + # Already copied into the package? Don't copy again. + # Prevents endless recursion. + + if [ -e "$dest_file" ]; then + return + fi + + echo "Installing $bin_name..." + + # Copy file into package. + + cp "$src_file" "$dest_file" + + # Copy libraries that this file depends on: + + otool -L "$src_file" | tail -n +2 | sed 's/^.//; s/ (.*//' | while read; do + # Don't copy system libraries + + if is_sys_lib "$REPLY"; then + continue + fi + + #echo " - $bin_name depends on $REPLY" + + # Copy this library into the package, and: + # recursively install any libraries that _this_ library depends on: + + install_with_deps "$REPLY" + + # Change destination binary to depend on the + # copy inside the package: + + lib_name=$(basename "$REPLY") + install_name_tool -change "$REPLY" "@executable_path/$lib_name" \ + "$dest_file" + done + + # If this is a library that we have installed, change its id: + + if is_dylib "$dest_file"; then + install_name_tool -id "@executable_path/$bin_name" "$dest_file" + fi + + # The install_name_tool calls above break signatures. Recent versions + # of macOS make signatures mandatory, even if just ad-hoc ones. + codesign --remove-signature "$dest_file" + codesign --force -s - "$dest_file" # ad-hoc signature +} + +# Install the file, and recursively install any libraries: + +install_with_deps "$src_bin" + diff --git a/games/NXDoom/pkg/osx/disk/background.png b/games/NXDoom/pkg/osx/disk/background.png new file mode 100644 index 0000000000000000000000000000000000000000..c7063aee73d9cf2f67ed6ea05ad8f9ea910fe7c7 GIT binary patch literal 227363 zcmV)&K#aeMP){zQ zmT57lM8bfCKrjf26o`xm;NbFAk9J}trs zkQHt`nO?nq-<9k4=F^cc@_aG^&^X;O*4}*fDI&6#0MHmqWRQrxV|L+I##jIp@v3S} zgotD;BHDNWpa7sMpn7z4G#ZVrU%zgQF~$O-s;UaRqBFTFVx!pDsK_SuI2apw?+=fT ziRixjAMoC>D?&Gj3?kV$MSvooh_Epc64@vTgNcas{mDkwMo&NWq=+2s?^$aBzlHY^>X!YA3=*B^u4M1Rq^$b`Rb~%>#@h4krw zYy?mh5mg1mFmwu9YY(alpsHG}K&?KmKdDDs>yuOwd*=cXv3kn34xIi^s_sL0FU0Uh z2mladutM3HdUK(%5hwt*cI=kVM^LJ{1 zT14HtuxO6++?ZST9udiy^L$Sg)~+tbXQt&Xyz_iF?v_i~tHN20nD8@?d@7q9?_IuE z*pV?v@; zQfarVXmGStst$X1(v_&eE3n?HN#iGFr`Na3*S6hNgSNL-gRg7WgaxmQRJ5;%i zE}RQIfiL9Lrm&voN5Qg3rRqafRZvA}nEu)x>eGmg(!sFWKCZhMjPtXzM)X{cAl0u> z`L|-Bs&25J%f@=5EubAi2&!=5PHH04yH-?%knSAsfr>OwJp>HC<|PBT=7QhQ!=~Mb zh@5_BA>wp&OV~SC2$$!-%X3l5^8%xEPzx?$VUI|N2%rc!$#QF$RS^IYnZ2*{vfw{- z-m7Y40TD%%j4?I}-o@}XL69O6Ab9ph$wmp0nR#D9kxUpXM4~bhiQW|eYN7-IjkVQ4 zs4%yW8zKVs1we4+p|A@U7$Abm{Qgl<08NtET9Y8Dh%54NBSeZ5J00DA`q9tsU%7X< zcd7ZTW&}b-O6RJos+QWrGSMI)>#qY>q?5e{n%k&rMLqauQ*5QM5yPCBTHo_xnH*uwSHYpLQ107_$CmTFGhIior& z@QgjXgjl{&*e{)fJ*cx`?iQVp;rv9v`8LfLX&$q^joYr5a(ArLXIrg}i&jti1)->j z65<^r2u0e*B_cxDQL^PbZ>U;rC!S9AK*OrP1D|;oQ zh(v^l(=4~vGkYRT)6{$KT+3~h7iDS>Ap&?~qc{ar(8`;KNJJ(~HhZr`DIyXzUk!;= z%ajwsD1;JK1wd^S6Inzg761&pt0kNe5sh~RRGB-o^bl;UsQ_GrW zVta5FEcj9}D!ZY8W}(zaq*aHtsxT4&njkenK$TVGR2FEE6Nbv^*q)ar_@&KE5K28t z&EY!Rqjs(vXDSPuX zYppS443)N;DzTI{JsBjj(pexHmcK}uO(P=O9!?QK5oWG4Rmzl{VE&>88LYvPDxx4r zRJqY+?L!zs8nK@;Gp5oULvS)|A}Eu1aDJW#ad>NuNt}&Z(vn+`6)fa<#|1)Axh~|E3L6x&pvkhxi9Zsz88_K zA&4j%>{|9wGGOnI$BzgzyUaT$-cc0AY0S*3a`VQGJkMVK;491MAeo(mtG>vJY%(1m zkB<-cE??W(zXS@ZeDmoq7kLH%!aN<_1_0+cNYE^IS?)^RA3#+{N4F7RoE3&BiCYWF zd3K(Y$Qn}`SSrVWnxwnFimtPF;TjBg2fO>XpMU;%bi9+sh#1EP0Cx7TD6@09isaeE zkV(>^cSVs;Y?PQ9_MjT>MugX{T?m-!Mk$cLkld-b&eAd%v zGo8TKRsW=sdZUE1(U|Y^Cg$^k7=AOIp>bs6vg3Qpnei{&3-R3Iqm^f};kXMPF)2Mf z*wm_2OWm{dLX=2@%KKOUDW$)z%!n!DzLlZYwwW5cy_r5!12fu+edCVdDYImm^5HNG z(v)}%Y`IAhOWU{p7na6j`7fOLzsqb-EKOo5P3N%qiHwaRV|MAo=5uFG zYg?S9|K^U}=)I?C&pC;LFDWU((?cgEOlon^hN zGP@IuH4^n^+-&#SZn}1@H8Fb|C4ea2Z6$8e&cj@5eUENElZ|d4AKns?C^7(g^}bgs z2mpESAA9(rz5V_D{R1L{#)vDJ{pjensvcavYNOZ{89*8JDNRE}GKP$G+0?t-|QoeR7}TYjIl|`AZdymVHRO(SYx{fSD4uqnToi48YP2dup6d3{E)p1-cdxH9N$ur zBA+1QVE3|(;&?E;@ywGqo_Q*XqsUSim8|eAGE7>!ZEcw5g^wd^2zPdNkbK(PJ9XwS7eSc2azLoY+ zBVtO;5Z%fBF{hYB5!TA&J&SYWZoHaE_FASiX&jbL@fO6yqRZYHY81})(n&QAJcph) z0M}d91zTusxVQ;ubs>arv}H+^f2juhv9uUVq1&>zW;ZGE=!8V2={Ga@%9vw4^9{37 z>$_;vaIAzpsEC9ZA6B+tjpSDq0i^Kw%67#-2vDsw1?`;QrDcO{i?J~pVV3GuT5B5` zynjfnHOsIwFl=YJzTHz_#t1T5d_8-!!e+{n{lh@8o}ao4)IE>ujcD+omx z`qikjokeDM$|o%D`D_Z>dWW>WA_LVa-@v-gO~mQ)5rm!gZ(U?xbUcJhU$z_elTDQ0 zX0Av5ZllrY#xqY}yLJy5QuZq1i$cWvA{XY8=q2!asAQ9IHXU8N|3M;?PmYUx+A+t2 z6f5$HE2e}75Q!`R1ka(3Q&9CqrV7Fi$q*5oLSYx8Wa5&uA9gRlQ>6AqgF;2u<`|zK9K$!D9 zvr+u&H+~0uuG}rOIqY2n99uXr21E^4f^VwWf!c1(v!)T%QxTabBdl=!3nd^Tof{E{ z1a>-O%z|i+DhPWbi#8VaA#6GCqYi9+>z~>cdmNsa2u;|7oJ0x=I~6fe(rfycol!M5 z21H?Z0*@Ucl8NfWNxUaxaJgSim3>iyaA{TJ-qBb$JMv7##QGK?TugrEcGRV%`Bb_* zKdrS}&Pd~4wpcG(VH6Se99)hf0#wKJL`rY%j66+Mg}ID}Ezu9cuPJ~`T2VIzow2f2 z5yb$62=-ohvWNuzrfyuuEGw%}q}*D8#k4xyvBV0N5lRiVnlV-aD-Chbe&(bGLKP*| zhDd0btpS)J;WI)aV}j+^yo)a~VR89Xb&<`a+gRRR*w%?O?nUs1rAl}C<@p<53wjH| zG>7HT6vR!({S<)3P89qkv#pB_<2IIDPxch-JWh2TV!!guPHKCfF1Pt?t{O)eP{_K7 z5m<%wY^br%RoK?Bp1C-jsGuUOm*%S_Ky8C%fOy*EZ*8oD`Q46fT*8tMp%KGtb}tgM`j|H=T^)WDqBVbhvAxSeR8M zopZ*hwKfH5sI^g94hSRS=u89k#rYh**J&yvy_HaX?awcwr9D zGBys@Rlr9QYMQ3O(#rB26e3$TtE^(RHm;(fqLscMM-~yBbKd(XG9i6O*x!2kktiJw z_O1k^{E1`0h&2yRN$h}RU~adr##2}MLF>xAxo!l(f1c>x@=#ie#xmuiBQ**QRCVVF zH%LL9+UVd2cV6lR?cNiSfMy{ZEzxr89s)?zLpNK&1hJ&JEAbUoV{Ce#Hnk41O+_8< zfNh#UKt!6+#mNFPvv9YD38+iB<^$vxXLzTLPV{gB=**=z*J8P7YY4&y92)_^^a?^z zWw^Tq;ZpvWO;EZaP4T?6pr%_#o4(CnL8x6sD=rd*&6^-%nhxOLlJ`zU%5n`RnrVoL z>|HitV`H*$Vxtr>B(N}hVJ?X&>xD!V>PGY|%+@TF(k{STgR=#Z$XZp!Yzn~63zD?G zTO#V)v!J4Z)G-p_YJX}ax)2fB6$SfvxC?;HKG4dLF~&p+Anchv``p+#P18`<;_0WJ z6z1U|HU{Hlw+1BD{>cD-5APYrh7hy7U>1W(NMjZD&p-Xh{?!MDdskIueWZN9Gqb(_ zd&@oqW(Ko3-#CbiIT5>&U;Vr(E&>_C3frb~)0xHmrP%N)Z?N-N0w`qJ^XIVJojzj^ z-hBCV8|*y;gpq7F647a_%9}cJ=L(O6f;WO%< znvQP8KAws-L|Y{Yt9*s}yhdG0oVdYEw%d1lx#;udU)2U%uUn>zKh++L|C+sh!Cmw2 zyWV95EyiJ;Wr=9ukg+9`O9hE&i1-%V0Ym`nbP}wet{O1XIPtmI^Q}s$`OQJ+C;fzK0NT6JOa%W^?R}oG!tGH}kd@ zr4L}~Hed24eJl;DJeQpoxXFUTRar$V9*%(_7?&KmRl~*i#45`SH(Ks%dv@#cHGRxb z>xwq8WsXL}9A2VIu*=tf855^vWECKU;<3(EVISC>0U!i>Te?gMAy=d>Bul)TW!%~p z)Ku6jd$Lg-zZLIP#Kh^`oqMj(jnkvoPipBYEpWWluy@3@sOILI)tNQRf6nY&o)!6| zT8O2=M>bX@0FBf1^5rYcTuetk&z#HB;eN=*4EAF1Nvf)d6H#B`plvjWlGNoBRb^iY zfQjN@cY9ncL488`~%XK*aq;26j5wLo!7+E*&z6R4Ieb z`7C$F*a&SlISiO(W1=`6)=DLrD2O^{&m1U4^z5fq>k_uoWGll@$k#XB+< zX(j3Z(#D8fWc{|yDn!4rF{m(yY$G#EKk01@aeX{4N$y`Gfwpa3=}NpgcFt!+T8sAp zu{X5Kvoscaq^Dzf3eCTt9&<{Oo`v|n9A8J!^?7U1xF0IY7 zi;L6|T;d2{Q-e9lY$2XvGtS!wx~3JmEe&u(oQ7^{)2tC_D08*e;@9MsYC=( zA0}V8)>ylDn`s27!tAE=UFoPiT}8O93(w5QVBXFD#5;hNlC@ItS=o)#s`KlG<(D+u z7#+Xr{?s7I4_Oa&o@A2j04TFpk$ikeCQ5fNf$GcSD4$NBd-{pNa5o+9*f_Pxph+n* zt00e*40c^nFlVJ!TjT}%C>a1^2t2SWpu!Org}2s5QDmdU#z|-p@+~LFw*ln#aTZ5D z;PXm+g^ij4!k|`%A`Ae4WRhf{s`=!&`~YN_#&HypjdphS0iejn;(cfwB?DER9^aCN zGHavQn0P!oQdRE@BC~&R**W*zjhg^4NTM(!0fW!%>SgV{h-i`+RY+4S0?$47tlGiB z^&YB(l3&mjWv;)f_s*F0veH%ADkOWoGFsw<$r4{)?af zm(z-XL@?*wt%wAg=yj~jxH_&diw?FL69#xzwVo7b0fuIULTp%>SUYm(w`n`&u13n2 zQ3%9N5kvtf>jU+A783wXJ4yz=z z)ej@H+uXm^hqmooTht}1mA$An!z=<(NxI$RZz2lr`&nLcV-KuUrsn5Z&Wq^i1U6hB z$o;IY&Qr=X%!X!D6a{;KFx(57iUF-$C9qUUDXK&yBFB?Sk>&T^|3D2aQiWu=f91ZR zuoL0i&)>Xt`*4tESUNCanmZzltx?r!?jjauhCD|Yg>{$}4iwTfGK9k<0>sI9RCYJd z5z(=D&pSJVG$~`i%nYFE&c3iOvM~TA!~Gzd-Ds5MQ&BK^wzEeex7%1OIS#UM5c1;H zIZo0vPSTL+?tI7~H^xTO@gW&|?b27})1 z#mp$oE=Mw|AuAml)DUF>_uz5qO%QMMNGJd<&WF?{`d)<_ZfIQvO;Er!Bb~ZtKvCF( zaEnc1ON~!?(JUB=r@M~g*h#F%KK*n|w5Sygi z=b(z560m*{V`(ba7nzn#88I2bOQEDpWQ$4t9u5dP?ju)a;s9IvD z%A_w{6wyIM6=jho$_-S=kc}cnKt=#$5vg34S_&-^C73aBx71w`sW8HIA^R5mLztO6 z+cImvUnoWSBb&wEeS+9l&$&j^Jrl>9rtf>YP+$EK9 zw3YCtT{}P(kaUHkNtga}9R*xht_Q?TdDk}4{nsjGb~=3e=I3Yc8MY}Ne^n|etZ*2d zrFGuS5=NXkX_|e)&J*#x574d2+NC|WNCXOID^z%hodWI)7Za9b9Z=(5?IJly&Bp7V z;C-*GpazoGDv;90wf>Z>&l|Z?Db~g4_{FMCKUi?n#=UraW-jt9K+57|fay?#5yWK^ z07W!5N`||}7$fWe36QesL{+Rc!!%J9&{@@pBAa-Z2fKI zlUycj$TD9`vuKH`0?77@uxklnEGvyvAJ(u)5kAc!jlmXgmoM)gTq?^Cnf@_{5^c0h zB3%e@3o%rX4+n9tk7^@9R02}9*Oo;@QW3o)A!;^s9br4=j0Jcd4x{^3hADU*UttFZgl>X%e2B40nu;tevQ;ce${rs=37h7J`-S5j60WNNOEo?{x3s_I%I0?RGJ zP)B~g&)arXl+ox;Bs;JLtq?YAn6Y*0P_GM0TjMMnJ!%D!&Bcj^8B0UoSDW7r7g=7x zEw6Y&%GNU%gxho#;<*z}bk@=;0JF~JHm}*?2L1w1wUVnFbu%0)i+pK+mT*Egq#a_z zn}Pk4(yR_qr7w}OHu%sHRYjPasb3Y|F3@`l8HI|eJe-)#(bb9!aprlfvZ!ii8EoJR z%32cji)hQ~SQWgJu6MK~x@%5Cn+jk~+n|bHwCWO7@2iO35E)~jl!aAoMJVMK5g}nc z5tS>m^dXxH%wH9_s4{;lue^5q)^r8o;22D2V z-5G1u8>@)hE96PzfD2fDRU0S$)snGdA!vFn!W71-s<3lm{{-TK(73|7F4}1gw6d|6 z?|JF|m3#8Zk+460{+a17!C*+n?CkDUqOA;R0swpGU6H2A-rnwWH*ShZ5;;VSV~YsZQjLoU z^9v;?s9u0E7+P{_Q-dvRRugoN4Xak+4bj#%l&Z2vq&tUUScCz1zMq}6cxk5Bo!}`a zDT%&KE2oj}q?@J$p0yu!etfVh3%b%KW?>?0Yy@}Swe=-_VMe~rCmO7w$gSh&Y()!t zwLzW7y)M3w&SyrMlHlD9j1r9ZDy`kWcx6y zXAi0%?Lls!Cz{y&ZgRA09Uj#h;ZX`LJ>8b+Fan%+d`0j4jo<5;x|^92o5c(9T+2P4 ze39S=uXaaX%LL(E8Z@vrz)BeMiQp5VhTMvAT#J_=Fp%}18gV)V zMDc!67PVOfln#4l#v~UM$!NV=pe1}2k;aG5jt`$7A3i4{)MQg^1B$N7;K< z>|cFg@6tVoH=jJd`OI+dQm}Xwnt9lm4tANHcSRJZHcGSUILb5cgMsKP%5M`TgQl;< z`=Y@~jZlKqB}uF*6#2Mbgn2fO;xvj=S4>@zh3p1Q24rj?dGbZBs^VR!uNGOelg4>o z9FHcK4#XgevWSq05QD`p2b0v^Ky^BuFR<3-001BWNkl&Sw5BBQj`A(;d=Yjqypge}7?dH70_PC$&9EuPVw+wiEr)V7)a((7ARWqN}{yYiRzuFyB7J#Y!6B{%7e5gFxp1;xoH*HTP~wPhOg3+A^>Z5r7c6 z4&XtjgE&X1UOl^f9c?l#;5>SIS&HF&_W1&uJ*-pJ%VJ42P(2uIrB)MIu}cP5nDOwH zb}O~0!y9&Yh5E-u5xUwApWQ%3fe>+VNy0muE(c|>EQmA{?`nbv0_0-TQDXjwtWFdm`6dZj!`DI%6u(pqGEs+2TZYq2GS z1a$TtktED{mZ@r1_%uy-hJzv--+uNn02u5Y2(zlsCS%V&O%g<^&DM}wBkWy1CB!sM zi=t4~!Z8c)A6yoZA{z?}02piHbRf(%(qGtzJicmeV3>%am_|`zOA|_?co-);$49qR zSjUG57$?I@^a8U31OpUBaTLWxo?BBKk0x3f3`x493c`*>rny(hvC6n<<{s_rUkW9e zB5MXB6=9PiB72uB8ykfsjR4k?hz^FAh|okas7^+=276bGjk=bHLZ}bkEPx0Y z5|EfGYwB585`b~Nd9g*@ETKko$8#M@ z4~N5it}v`LY5iv)*;WRLK)afJNV0FjY1dI~I|oh&|68euqM+Eu6$b$F)+ejZ)ehAB&Yc6YH6(U%5W+iA-Ip8%y?+8h~Puu*fqq(cYzNs-m}_x7KhKiin~V zjcF^eGh;mj4sDc%hdJ-PF9D{Oh!DNY0l-8tiogsDQ5F0PEN-A6SmML#ir6B|o_rCE z-SB>%SwxJXmcoKyZH$5BpJ3|T`uEAt-8+eQjqqgho&)EElkPmh=;k+n8XcK|e- zjA4PM<~=hDVosGEA0-15ML}Q(P`0X;1@5~g%dxlU{5sPed?z!O2BPj_Uc%~L1L_eP zz6VuNY>QIMPx!p#u`fsN(i1sgk$Zv&9O=@;9ANOVPtDT2*ONc$QXrr4o_fKqLT4n z9i)jhHjdLBRT&>2^*XCn)p=%SfZUKFV-P8d2gb%krX(vCQ1yW%WxixNohbN^NJs<% z^>PghshMxOq!?R60%5~X+k#Qf4ti4&qRuCtEZZ-Y%4J##bO83x&b9v3Zn*HPR2k>a zjrRNXu^dzi9CRu$$tvEw^)UP0J0l`c=*>xnZOIF6t~i|hEM2o3t0|p3>zU_0?P2?` zn=G>+1Q9)hZ>Q37fQLDX!&;aw|!m+|t4uNjIXji-HR0^Cq=_;tXsDNNe z1`!;X<@+fjmhz!;U6z?XWUyM75{$44m)=Y-nI+AZDw0sS-xlTCK4Kvj)+DEq$kM>++#Gb&#!rtq; zN1W>E&c8-~w9kBAaZt?ltzoxr+e42hnXe_30_$cz_O0jk2qA)96FoXtU#TBLegZ72 zSr65If@?`OcHoXY**&2r-CV_cG}O^z7ByaizHfpM$k@`X>0}~=5V|fZCSFRf+Q{y5 zCNy%U13IE~W|Bcf??r@*VyvoH?|A?~v&l$RO1c^G)+Ui1SQ|me=TUNfxOE*HyIr}mQd|MRrhyOL>x~G4%sw@b}Gkd zUbw!0DnV*LyLte;0ZzSXNSlK~UY*uG$0P3~VZb?ED!kwDSj(9gQc->Lsrg(>qKejgD zvO{T^m4;QRAA~LQWuCBV#iAj?jY@B>zSb3l+vO1I$ZSLu?`D}6-AY}oBISA2q4Oze zw8F@AvSU?5&IqQ}I~t30+galhOcKmTvm6njbF^(D3~K~**K9T$Bk@SaS~EI2eD=x5 z9(d)~7-O^Xk@qh65M4eEbJQ%CaqH&I$#fe2PLpVNkc zQdNEa)-9i9m#$t1q(BY_%Erbvipf}Gqq2m(cOse%d+gUFa@XaACl9NxMS?zVU7 zo-5bx@$AI=-OKkNl86U|Y;s&G^#BNvXVd9)6xNLM>^u)N0>EIH!p-N9(3mor$ho2@ z@=$cXx#OaEV2mk>!}$S>;&iyXH=T@%Y&x0VR@KOwnwvC9hX9&QM0_;w@Gl z-{|5~ROoCPOpAct%U509xYLc3pu&TRU<{I3Lb0a0fyK5_L1gk7GgO3k0(y<_&_pZj||RJjE6@v(vmJ471n zUh=N+MOG59wb9UsI2|7XAWcWro0iPZA}rpqcQ#HDG>I*tCP`v!6c2_0kY@}HC=!>A zo_`hy5h$M=hlx;;C`m=cyBq=I!44UWA```fC{FWy;_~Tm_YxpYMn~Qim#*HUp>z@A zezN1T@pOFXS@J>*QB~Ggz027*^L^A6(|{CK5oVvHX*w8YlVedS3NNg~K@0${n6Bd# zV((6Y^sBd3&zHtV<;XPdUqPEoo{CM6!MdJe8;-pQ=)K5S-)KDNmOd#e95*5XSbvN= zsPN8-q{}drYd=FODmztUV?Y#k3-5e^V3I%|-*`o`wmzMf^?6S8k*UZxgq_PvWH6Zy zYufVTYlh;JHt)*X;**(!YjhoMusJ6u0@=777G7XZ@NzT z?~(?H*^98)s!mxsq1xzC%}@nz}k#!f`Td% zg);Od2DHhtwxwmZ>bJUTiNfg*>%N}q>2A1$m;9ut@Us#Ur(_J+d~okr0>1fv;>LZ} zo&zE5uhXt5JxK}$*nqp7sW|~R8qo2L8rE~@PMt4Ck8`;pi*Tc=3UUTDtXHdDGCLVp z0g&rHFM@(L+V_mcD$RNoVzh#~LmzImsg{NSYS(1!AZ+FvltI)Ia|D3G&KH>>Bs8iZ zEh&X@vQxMspH7oBO_G#l!Ym6&z=6G!77qXd60{>^VQqx)KwbP+RXjUpM{L7ehH#w- zXOklpHP!&Y3?ikfASxUR0jdhSqISs!p6)14$runpK*Ca0^od1@#i`BVN!- zQcI_jBMJsmpc7bx95Vhl21)h5VCXp-bCP$j7(C`Rs`~g^6s1F=`m9^|l-W#)2Zq{1 zqkYHjVgr5Is5bi<*3yZOM_pXmw58H*$>pfZAkE;zx>wl#onEOZ09Wi$3&$1_kW2?7 zzx>Q!;TjDof^`-6@?0n_Pi&Rao_mco1b07f^z3R_ub8nKoIpfmRA%Is^JS^EB~y60 zQnP8<|K#rgP|x>bHWiRN{5B# ztnl%`#OcsG&)(reSCVT6^Q+}PzbiEq(F;0<2nPT@d&edU!H6ITRX7_T0e~?i(jrj{ zrGA5uYG*fSkximFjp9K~PlIGaB#A|w=Ma4i9u@Bj5f1=1vZkZ}#pBULM8a_yS))3m z*hR!ZWm9FZmcqdr0)y7ZsxB`)0>sv+21unWaE<1OhHP}=J)t7K*%Q4WdObyc!711U zsrLm#;Y$!9A~}d?91+yg_Ji$oeQ%HlZk3>_CEb}V?n6fo1hC2geQ$j z_41AexDJv*Lra#fBAP&qwH&0sU~TjW!kK>FtP5EK+wF@((DM`vU-+D}g0sMFaQbZt4|PjHs>8$Wu{lcuUK*wuo# z&WdU=3N+WooUPEjt%Y`p=LQB-Riz!bY?Mph9u)Lq26;UIa?^a=_AIZ0Hm~w3%-wD+ z+-T2P!M?O_Oq3)$flah1iV#B<4gNih(}6)4BsNV4@o;xK9rr5QL>3y^@ZJ@!$c?dN zXgnH;2y>aBfkaW1hBh`%5b=0Y{FR^kC%tE28pl^J?Y#EY4}8nl-234Dmm_Obq&Kyl z*&$-61u@vURF)eK))=C(ac{X?3}pX}uzV1KX>3J=SwwZ3yUKY$*RJkqmgTt%kw#zS z-WQ1YJAd%m(IgkquX*tL8@}qk-C>MGHcAP}J(uQe5z4}1`Yi>jpx>^<(#Gk~#OYx3mpbeJJOA*rw~nR& z;91`In)^i+8_()bF~f^ocX!Jc?AEYstMexrz!#YWUeN1h!2ydoJIc7ak{ zGe@^fa}#ZSCkuO*XT$x=hi zH@p&211(&f3;{9E#>(E9xGpH@UBT?UD}sMC@PM-`0(&aPRd5C6o9N$4W9Lc|RU&LQ?0i}S|%HVncB zsuk*reKoor8#Wvw&e1)TCE){vpixJ#cjX{plcKr?Nz@I#`^{hX=fC%x*cGahW%-lO z-Tt>9`s_oGJ{P|If8YCwZ+`7d)5Kzxsa6H|bl%eHvL%;j`L1C)3sz#AB789pB&5h} zt8&eY*NfMS*F{}+O*QcRu6gHgLyRpk8iYN}Mb2OmQP4Stl({E*hZ~GWAHTNCGXStr zT;eEZplNNAZU!+^#1#q^11ZvN)`KmDmMK7BOFFYOK9^7XI$^WXKl|KXS4`Kd2H z4FKQz`j`LJw|xsDq!ouavp+n%9Yyp%{nPh-=8%b+H@@zNfAB3kgLI3E{Gw)^pRBYhPGELy z}!pI_yoe zrsuavs%!K?Yxfk-JFT!LzN^6F&;*7CoTG?_0!g5?>~C0-95rn9f?X z6ChwIp#ktmzWWV95CXu*9(wAn-}tJ|;C%GckN)(BLrbBoh zPm9N&x&7XceBsBx|M*A#^fw_NGqeE(Ek7V*OLTlFN;k)Crd1vJi%pWQ^xP6p+A2gI;Qv}y zeh1+-C9yC&=Z1Ti5HXt^i+81P(yDS3Vz5wIb77B&Sy2$;a5yy9I_Ho~GTcJ|)WCIw z!d`^Q7$maRs;V(o6^xCLFtQOKghHkYn(=h@f;LKr`(=gq!Csh@*B)Fs*c%)kPXXY| z&mCUAdfghTL#=t?f9co%usNO6$>@`x|8i3b?(HPrOP&AutMB^gx4q%z_gxo2m}bQ< z{K~s)DOg`0d+13+*cf?4MCL$js>YasjS%%)-|+GW@4x)MKl)-`cmR0C16RKG!Rz;5 z+jCy5m7o9R-+bsxPxcP`^S6)R{`0@|fBnMWI@sH32vB{|Rh`6(N5XDJkrzVOAyO#i<$VP|;5ZM*p7MfAc4SgQn~l5dd&iqA!kZlqBr(?|buW zrkVTTCm#!f@M|Bu{-fXbCeQ3Wzwe`;|Lnu16nx!RKlnHP^4nhVl6#+f{_vmt+PmKW z!H)yLt;6Gg^sB$~H~;Dnx0Ri3)e3)65Z;O1S_$+v>t&KJU<^3Hk+PcN<4&I0Q%l~KT5WKH{%mE!^$dpeE^&?CA^kXg7`P{4mV>MJ z?Cf7IrlX4C46-aU&arohX0Us}?6}B-+2?)E-dP&~V6e8wM>ma$lHnczYOn~&NCPOX zs=^#f433K&stDzHGO61Xl^oWhh!`g1%kRC{O&jZ z!*~2P0OW=H+#^qX!|T544pFvix{OU1(w!~_msY4>S@PmMM?=oHK4q8UW9@5Mah?|i z;aAo*t9OnYv|n4iuRsmYu<9+w@CJ~4J+)5D$Rf^e+6#Es5IgLcjGcyU@I<9@HmX5X zMd?5nzhJ27)~r!~IGR?zQ`#A(!Y#6rSHARmgAO8ihV?_A_|k8^?_&==`iw3FLCEum zqx#ziuIyzb8;h$d?R_PU##fj{c$yN-J=V!$pm)=(ISVD?1Ub!H!-}ZRs0L2( z>m`fOE{E)RVA|-=eW9@J_M5GW(EV6NPx)IRY*w_dFoXb?$n1qb6 zHc|jLnc65daZEO9Ef?bT~8bkhAe2vmYdu zh}gS-_1=&E~Em3YcHL-UmMVxmwqG z{j2T+z#eN9XXbWZ_;>uyhr-{ldD*r9{3pKW{(G*ncjIYZ3&K!|ad$W)GkW^wF*Jjk zsy7cOGaGL<8zBU$4X*GOrX?t5`#Xc0)a{9^=Le@I?6JBTr-%QsRfd=Z#nP;%stgqx8v!pOcIwW3OJ`uYnmK`ox$1lRx+7*o4A| z{K+poc{DD~{Sf9<)ycH5mg0DswM~R+5)IS%6%Snf(i1lT;CDaxC;#bRe%tQOpdR~o zzW*bo85-HwzUIMGdN?*T(ApL1*XMZXE36m{yQ(bW@?ZOwy3pZ*M-(m)agGLgbCFBt zV(|dY(Kzv$CUdd>UIV(G6hy3@K%ole+QW6Orum(AZT-!4@qgB8dEwd4=huVYLNN7* zYks?;nv5>{NmYm)8t{CTuzRbTL!w&ZD8k`B2R715l4I=?=(X-b#X*_*16rJC-C@6d zJpICB&wlao8()0kFX z<7x4Kzw;yW2JxF;|Elos=Z_}8_>T8J`}}d?{6|0e=r6wGz4L}^pvYNZ$^Zalxv!by z{`9whUHEW3&HnZ;{L?Qz{=1^naKk!Enec+EC>b=$OF!|{pdUKVc(pnp2B2Y!dB({k7^85D< zQK+}|EC2cde5`RIo~`DoKiQPpIW zG)+qdUs=VM_3aUjA?J!gT!sLD?_*zj^2X8EJb2HK{+Vxh>o>gOJs8_~%PY#Zm!d4%O)9+EL86=g1On_*!)$^AfGA+VV%Bij zkT+T?Eg=>VfaGmbqi*9$&rwxSDOcU9fJ3|Rx-988hE%KikXf8R5yp90ZB?z#Puz@D zYvG+&o02mz5o&$kT`EM8O+>t1wjcDOYN7F5FYs)Rg>^A@diMyzk{}-%sK-@;u*CMU z_eGZO9+X*~s_|ftOeEfU@8H%gW?y8JC>hu&5>a76V=EgGCt02@jWbzmn^TO4z}N(S ztTP?=T-p1ZKk?S$d*!{;+&}W<&2XNjX^Mz8PFSLzjX`UvD2lIpK_JH2{HhHA{AjTB2iTNN?3&v4YU)=dKx#x zvnnH*)m#T%SH+T&9aPnAt_Yu(IO^6gm&^O;HfM0@52<YKhQj;JopS~+rCj=oTfR}mE8$N$4`x_&Tt_Xj`s#IuKSWM1`> ztAF+_uY1#L9(d%*n?Vr1>kmKkXTR%B_gvWnfNy)lE3W^{5B#eSeC9J>dU`x9u3p;t z_BTBEAHC(ZKl=~f8SWlgqbdL-A_@vfM8UO)!7lvK?|aiAO+NCe$8Ovnd6p7t0&w|Y z=a>J^fAP-uf8=*R{P8b7`qXGVP1E?L_g(*vZ+h*I{J>l4sNq>`^v3?!&?xI~uWPv7 zaP@uW*b`>ng0l1@Zu*+40xH_5`lx-ZybHoKn;tv5;AJ=4adUH2e}boQ`Qp+UJpUv5 zZa7Q-?LYe;*J($_+?gWBG;{9HK+^QqS0j3XM3w9MYDDJdQx6|K|CILvfWw_#V~mNC z5PN6#PdxtE{=vbe%U3`Fkn-tKJ{=ABt^nZp=(hI-5vg{K)Fn0o5yf!~09lr?XyLpy z6j|e0oaamXyNFm6g{q9Fg)x*w77>GIvfl3FX*S97VHy)+9LHf^JoE8rLPS@uTy{l~ zWz%#pOwvK9sZ@GmnN>O6xm4N1>hfu@Zk@}$E21bh)+#{Z{9pO+{#jsI`=LMey1($f zZzx$tZ5%}j5*cF;4-bz=ql3MHA+k||Xo`Fkf|NnjA6&ct`b%G}=T6?=i-=ffT`Wmw zD>nk?izFqItqrD`b=7wHbnYLPjg4YNbVW`?>+kCsBBGQiI4{vd$;`7DVKPxIc!b^h zCriuL++f49%F?MR@2uhrH0Ja)Z{?2X?H5E^}P1CfDa(5VSLIjMltoO+BW8KdB!)1Krop`FsET zeUCl;eDJpZmp}QIm)w&gqKN+bdp=fkjlSw7S1UM28CODWc%HRc+7N3aM?&RZy^yKI z(=3A%-5FaLiQWc_@j|D{+3x=#-qky?J&d^aoYpl#UpyX{yVT0@>qgEJLi78Q2j+I>>JhH?)~{GK^jX8)A=IWiyGH&p{gQmY@81Ef^r>deZ}dH zh%d4!Gb5rfyCNrJjg65^6sONT{gf(Py>@*sj>Ccpz=?p40K|B(lMHsU(NR7f85;qh ziDDv?jSmB@8mOi_JX?EYCZnT#GDbu|+Pidx$nLWvGA4=vz&jT#3hy#kWY@0WJJ`E4 zJw8+wL{tT1t#<_rtH|-;Z7*6lo@9mUVGVY6PG>m!`>qT>_=zutzyGVh|J$#4 z;7S_Xr*0h8Ai{gE?7rzW_cx3!&)yjm8yf{G_Ba_3(R4Cl_VwTs(ZS`b>2UW<&m$4u zs<}DiA)7};^cs0>bJ8oclKy>>FVA-i!^OU={h_M94}o(E%eZT+*=RdCx*J%59ZQ6l zzo4@BA`->PN$-p*tiTO3-3sTc4lc7c1;<%RsD>C4UaNji>nFl1LzRdDD#oGc(1|U= zd0_0Fp?|#y)jyrwpP6hSXxPX&Muu)( z89pRt(#&?8smWzH5SonOsHJkIb&Ee&jo-V{LZia{Np!1_3$$Q;90)#_>Jb! zTs_!%`%iwCX_q1?mp?YM=4KtMt<7_&;);NGuG+s|6@_!Q1nT(uooo)4OoUtLXFn0+ z-C#fC8MLfU3M9nR&twCoR*k#tsZ6v;?P~*LE9vdK3+{aNi@Df_o@o$qQ&V#N1}C!- zYjM@Kl4(ifiW?M-iENZiT@ETWvM?BVq3F_dI?eOk8nVWugJCk*yQi!a$n0_?Qx$Zq zQ?c>Zji)EmX=I2HtTl*eqa^5V!p!+J#M`WmY@E7c>WV}50)Qf31euQjbg+B5URuIl zL6sQ*jEUI0>G;SOS)C%0Pew?zcW|Y24XKK7k!N|H4TrmNl9oP7DFJIl#wIDKdYAwA zKl2}d?6Z%)|Bt@#=#w{Z9v*wo!!&;2`u;b+_Q5~%ov%aAYPsn>M^O}~3434UlX}%5 zVmcUvUFN+%9*q!b$WHkzc)66l-wF>)fMa(+-}7*65eK^2vzYz1*14{s<2M^G@wfzw zvy-l)pm@GDKQK`0tFZ6Gil_nrclx=8j5mGYeHE{;+O$&P>ipLb{tOtQ>M%d2P+CI_ zt?SzDGBd29J5EQ3B0k_~EWm0=%wn0khSa?X%jQMn?qvFBAi-|ra^h@9hO7i;1T7&_ zNTFh_FKhqyB;zrQD+-D&5UHX9hPuIMs0kP?18XIHn+7EqQ5&Jk#>_UMETu^}%hFL5 zR3xH0poj>;hD9PWrfi6TH(ZIxkWm0)52)Yx+6UkKrmwbfGC97LPe;e&8~_gX_oB$= z+&PpHkSe%X2ggzh#hH10XRmf$^JCroaa+o#*Nq`@o3{zE=W{$f0^NM5MYeDbwz+!r z1kJSC+Ap-j94ohfun4;l$P(ST;FpbP0TP{KwX9Pq7p*?urGlzk$w8MlXf~Vws=u+Y zuty}M64k`)gt?Z2agwBI8by(fVpLFJ(K;oB!Z?@pD~Loyg$X51B11%kMd1~|c?E!j zgUcd7WE7OW17C#WGERm?o^fSAArd06_kax~ev_+D1iTNw752fx3;hot5*e~qv)r>3 zd9EVH8mI!>ga&N+e!j>d)IL-Zk>Kzc3{n6P=0c>@iODJiiX35IXoWU0gv?$A8{13= zgOre>WMHCrxq-5_nyd|1^Onzu)=|(0#|~S*fj6(+FpLdAXJAJNLPfW?{+qaneg|y3 z@m;X1Rb@*SbE*01He*A9nqY?0-SEyAPuLb#U>|}L!&W8(pmDlOWV*~Up~WHr*7TY# zX?90l4R}79yHgO(XV$DK2p9Q?7D!DI_JpLMB3?wqJCPZ#IgaD~{R11PQ8LKJN5yok z^?mUFXYakE?l_J+(W>sAnVY_d97q66V9ul@Qh}DJoTXz~vV!Hc*0xr**U$Eo9M`+6 zwY~C_?Df;JpVyWwhhs^USILq|1xh4M5+K0r9C1Z7r0DzM%fGCy6%p^5HOUD2agg~;I^V_iyrD73< z@PeXJ{xr>=vo(ZFr!?KzwiR&Cc_Zl1se?g%cM)OSAY?0aay*v~`fC@?jQUz+>v+^Z4@yxfME!PNVc{1l)4_v!C zk#%LR3A;8CrKKpx$E*M8kG`CJ<^ylO{++MBEc3=N0XLJ95fms0*s;O1C`of=FU&-i zn3?<8hE9F(N1r+HnSZ#`{r#C=ee0U#1HkmalY9T{pAv%5|K~T~xAFXQ9Q%dCe$#Ru zXz|dc7s-rCFMfK1?qBF4K12YtWb?$F-`ljk85?V9{i@;XFFnT{-178+|M#nj_S2vI z=XYJcad5tTX1s_H(JUI(XN3&57v?Y^fDm2UGP6#$^|S0*tISKUnIm1Cr3bu#X_NmU zo*m-HX9OhJyV?lzejJfebD~9m0d*nH-q)$)+US%A`TA)j+hN|1^qR!ruOaK^1jeM=V z(P3B}2OAfHq-H9P<7|Z&iXI?Z9Wj7ZzR_B1YeF4s8~92|p>-V*%L7A7c}7RZnDOyR z04S#4cKfDh9Yf9QZn)sOOV8fD>!(zcby8Z zcP}tzN(xd^lr~dI{P&03c(L~%8QXtkEWa8VTJB^bVv$^1+U|>eo=&P@-(#ImXG^-@ zYf~tMc2+j0DA>KNWD#p7G|2NQ6v>6g^FZoOfj5matd2SJfwun7Jg?!&luvqmobyx( z^ZW8yeX1u1TR;7rekV`!%{)6zo*5P_w~&&TqU1&JDl+62PiHyo3-XduogxVLG*hgl z;a%sREu})l4zF1ViBirLQ*wwo07g;dHaH?$zIq)BT)D1djXtzzyAZ-!El2^NG10Dl zM-Lnw>-e6#AA05kZ@i{Z8te#Yn7K4CiikRDk~Q^-1@=?@O6grS@ za&pRAyJGn=W-@UIh<;EcCmf&1>9t;-7x+P0D({Mo-lu*(VPadgbPxcvv5hbeJS7lT zoO`|ya_sqoQP}VcWk8V1XC@OT&Gnv=z9+5aNE=TnM4+@D$5U$A(k1RR9qTA+_8jMp z>z4iIhhFXeUb$pYc|JH1j28~*Lqsna=(mSD03ewNb8z9AtaN)fqC`2XD6pfE-049I z=_kPlQ(Fw=2Ph;8#pI~P=5otY36$2x(+@ieg+el!q*nw{2-T@ihrn#vn%*a)AQSce z<{7xTTW$5NlM$%zHS;W^ZA4Kh4d%o2bhH;vBY;8%XSH2G#M=1L#?+WsC}*?%C8+a7 z8T!tB!*#hHY;(q4Z&eP@Yhx0<|M7%}r4V@Mty#Kl_YnZt{N(-*yz$yr;0Oo+-@Wgd zul?|G09d(n=r4Zjy_+82bH}FbhmK7Mfft^;?5#I%yzKndS%CPRd!G904;}@8yK8_?biZ-?r)C^Akddi`FfF?;CEobi>N&Z~d7)M?RM(4*%rW-g*AorI18<5XI)U zf7`U_u^oqwp47$;4U{&nU-_n2Uw!q(=XQL_<2#Pr``GTihsUdpDDc&i;mT#_ue#;B z3pcDu4B@B0@V#gDJfD5!M-T1%(L+10yl~a0e(sj%_8~y!n;oVv9!g2lqbmN1y*^_xF##{Fw)~ZvX0c z?%uuss5a)@)yv-S>g(S9hMPLPvB$RU`sVjHZQHSLvf8MWi_4Y_U4Qw7Z@=~BE0>L& zN<@U`em?i215N1adY?bN;%4tymou7&nHNhdD#ct3+Hn3f^Ex3=$R4?Xtmq4)gMpjn zqbKj&vLicr>-Ga%w;y=ltyjJCmdg-31+|ID8V!i~NK{JC3ko9Ez;N_r^?!Zkz7rGm z?A?-#okfVD{EjwZ5%d-?n4lH@lQ;LwzT6Ra(kBP579Xu+OR))AoGq6OVc=edDgDwmy5vwJl_yI62kGTfyx0wL2ew z&^$Z-JRw;x9>Tgw}OM^AS;alfUo}Gkz-?3 z0J!O@4R5*m;)0*-Qx}}O{0%SPc-_To`aBaRqTl_~zsp;}{A+BY`kVjbe@|BH-C3f~ z|HHSTt0rRe)@L4k>{<8smdBsXtl(g!bj8N?>((q!Ot`h5`{FmpCu{Qx>$vm1S$4;_ zwelD_uR;@0|Yo``F8jD-QEN4f!LT|IK2Adi`kI4bJnw{57`@zGMa4 z-H|kIelbUc!~_iD1>%sM6C>1ueu!+>PjTLnpT(sTSsMhw(9n=0G1oe>RtppfBR8?J z#8G4{`M&S_{ynML2z<5i+$Dm|#T!;^+kF%Owmy5fP#SbCf@Cd|$q0@uv8Ut*-gNCX zmu_e_{Pw>;bHf$q8ErD5C2}Xf`TC324qFy?KD7JZN0P1on|E(})s0sQ zA-%$6b{Aey2#N!Z+LX?f)kRU*Y}B-l?|XdD^J9rUxaQ(>KK!;D2TH+~C-;2mUmrA< z0N{@MpMKe8YXRV%t-IZ6l~VA@58tw8`JhsA)8l*p_ctDJw&3Yqhi- zwfQjs7@w?u;j4H2U%&944);__@!KE&nOEO%c@*ov`O59z`O$;!_#;p5c=6{9D&LGW_f`eycY6Rkg_zeo(yr+A9zK_b=@^ zcnkpc96Hf3a@mp*ztGCkDZl8KDibG51}H^x4^EeXXcMgN!Hbwl7w0CUq7 z=RCLX`FkGS4FLO&jMwVTa?u|dDBf_{Ib`YL^~;wImz+@I#T%CA@XUseqmF3G8tvp2 zO?!2_5Yp(Fto`;6H@hRnLhvV_`q*Hl1OVr(TJ~Rl{lmNVAKriH7yx|#o`*m2k#`n? zwi)~Wx83sES6l@EO39CZ=xul0{jjkX08WfgCDCLW@YS2q^Cu_IUA+tdUUBUuzy2TI zt+fGw^=ntmY+A7AVeDstn5o|^#y-K&EGal<XA2?8f`>=+^Dc-@ zCb%}&a0P+w0t}%me-Kh-Gx#SYM>sF#=obN++6RtlozU3_ExPP^i`X**p&s70uMsBI zZZEs+TnD3Gf9bh@o0b~f_2APtT(%B!ogCShyym(K^PukQZru2#ZzmRF@8J_yoWCMZ zCHk7{FJz*mF`wv-ue|cFznWlxyZ0YmGBQB9B10x(YaPvK`$`lHbl}*8J8;?gD~rWK zB4v)^gKxS1r(b^!F;}Z~&sS2a_rK{{DX~0x4rh|fAvrQ>Y}%2cJ9CCvJ3JbfB7{RXN}B-z#kr}oEV$T zTio?)S3J3W4*(oHIq}io`s_KYmR)`6d6!?b{-$d$Svop2$7O;GSSQnbd>Xy`7n3!3 z33#04n&=oVJS_vxZkHg=bOT${@5OHjyQRoxjMYv<6XX{ zVfEkTGO*RuexmQ1XO{W9`QkM{T-hd26Shn5;JH#ygJU6fx$wlWo8P+(!kJ&o~UKI!E08n zSh8YG)Tmmc{bE@N>3H4tJh!b>9$2z$h0*cmty=KMIjxSuja!L00u@e&=?=Be`c5-Qsm$I8C@I&u`{a|K%-7#4B_Y>H?kNc% zGF^E@kuOpAltdJHmk@haIxsV{$#IuB&EcGaVynsD1;F3Ed+XnP?XK+nWy9t3)-JjH z{FPt)_Lg=x2HQOu#@=B!aC<>~_bJn7M}(Nc?OirH^u^Eo#%=$0&yVigdUB$ge{1X0 zyMFb*{?%uH_di~-as5kE{-xJX^oz56WJ0^&=H1TnOQcjFg#8I%JYwdKAQFXmK`L%$ zY|@xh$mptII&2+T11`mg7&WHqQ)3++&DK&J8%WeAN~Oxs=50^9>XPYS|Nh91pStl9 z_ji`Go2WJ{F#r%V3RxT&9k1_g*)~Cln6=4I)|ycq`JRx{N0ffxpPXv7Ee}b2YuNdPGLt@BQt9FH1R6Guc=D(}e2>d~=%z*L=@xT0J{&4 zGA3hC%F`@*aOzk)UV1IE=P!hmQb?KbKPcyvCs5f-5#cOG@FyXuor?l9hoA*v0V5;< z&^-@7JDV?j;<*D8)kdYz=0HTTdGwhB*KS;umY>6&o1e}uVD0kZ_OQ}E_Uxe>FF!X4 ztN?zz<=HH#I(PLb{ll}xk9}#sdg(P?P}q}y8&SFR!;G_wh)#{l_F3@CwWzb~?-ZZTS3VZ(88|Mm zqhBe3h+!D|L2=cFO8}rgag2!$96Y>j*CBV#l^3r0@LR8E24gi7pkQFQZ|k1hH*E(1 zBEI*L=ic;+jfvNszW(+b5B&T)uD|h$LNn4|zw^-@`x2D(@(b52Upj0}oWJV7``3pU z;Mz;pMcRJr?x%JhIG&t*!J0~`0MI5jW}-%;da~oL<2WL#iR|^4p7U?_Jp%w^ll8y+ z%8!5cP1hC!?}3N5Z+>i7ayu8SjA9eTt(woHC#K@434pam^o_fo%EdRbR-KZvEnC-& zv|Ce3N|j4~gv~}27K75@J6?a&=lXbuGys57scv4n+4@N+ zQHg#tpRAcvyH4L=H~Th3oHGW4;)Ph7IqghbSkmjI*Xa#z(j{i1keOyTbr9yud;8+? zC4S;&N@`-2@);O~1m^o5+m&UzUUlsSYgY^da~#J+_8}E8}mn(Mt z_eXdB`=dMaXB7kQ%{O1d%xjko34yM%=Bqz={JH%ni23PV&pSJp?9|Lm1VR8{G4RHr z2>|yzyyM`}v5VF%d(SPGxBq@ZEb#VQU-6wgH$S)gAOLKAdgssm#%DUNbg)wT#h-oa zT%S`R@Na$PwRhaL1puDex&Ph2_+QtpS)rsnaO7CMk-)jPzVhnDLk&*TV#7203SWvr z&&o}$SF@s9o?_ZKGSMk@^RG(zB#B~2-Nwc{W;>Ih^%a27A8*S|BrGv{yD(=XR{l}gkt17Pmx%!v4 zz3P(g-RlEyyzY|oR;8mYvZ(Z}uk1P*;pg7|@{7)0nkojjEY!G(tJ+yt-{>%#Abls)zfBS1)SefW@yUDzGnXQhhrG zg;X9OAfr%93hDa=APVaVd&|B4<6Wl z^hDM3R?-f_zn7q46HYAaB+xpA?!VPwh$FMn^AtTkFnPb%-4OE-M}_doRQJ0E%c zxq~OhYs9={xP0v;=f3N8*NqMqC&x~>>wNEPuUI}>xpT{o!^furPpw-$^46O#x$2@- zhmP0AChGuj$9+$|@f8;jl)Ny~?|#kYzLJk@KQuPkFqQxXGi0qA?mndQq*6kt<;zCD z^yk0x-8(nkwQ1|ly$5TxW})DpvwHc>H(c?)xBgTyn5UyzE*3uj-+twL_dImh=ErvJ zJ6x?boMpXe!bQ>T6UUDdQBVkk5MEGXBBP^39DvChqx`^8rZIzwn#|;&(PkJ6DSRanQA#0% z5JD=?mtOGoA8h&O+aGcf;g|mKXNYX6GVGca$kOo>CrYJKrBX3EGCIC}({o?_{-f^X zfBf`^5P-;0eyikCiL5os^QH0;0fjhm{J3L7WdKM1i3r5d4CBC8g}`%$P%2Ld>5^n_ zJus6?M-kbHlgEV+nVdBd6O+sKd7c6U-!DQ-)1JaGs?{5wl3toTD-=tJSg+T$)*~Y$ z)|w~`0iakaRYq2fuH4Y3Q=gG)BrB4sf5R)Cf;eN|`NDZ2nmrXKPU(7ip<4A(DmCri z$X$TQi)2?h!%@9Pb*y^wh!d=LT=03S4>i4O*5Tdcdl<7GgX!!9v$f_d8ZW6lAe!?v zGaI9&n5`t+3;yc4u?EG8ACycSS)=2yt|MJ259>Ir*J=Rlc?r*?j>yIl05EW|GK`2q z)XB*g2$WI)KpY#Tlw%h&I?{2g&7j_lwK3L=A)-{m(YrL8&1N%^1I#PPOXVrgpEz+$ zdA=7E0JvG7(%LpcJvcZxP$)&snvR?0q5{YS=nWz&C78JhK*U;G6uu`tB4c&j+F6)Y zP)aQkG$LILykfz#maQe0Q89GY+ook<1kiL1pR{hfx z7j`sX<+n#iiO_FH?H)8HlAaGQy%xhQl0tbwG4KC5U`hD}oPYZSx0JNFS3CCEI$S-4 z17>-HFN#rUEz~ycc<%UjPHzyo)tN4!jnh3VRcRZfM3)Cz0bbvn5U2X*nGyn1UiF?6 z_Fc+xz_ooe?V$y9v;p~TIuT7wFNw1YOmO9v4eC-|z#N@4_Clrer_IdE{NnfevHvmb z4;tZ%_TF319jC+0W<24g*CK%j^B234%Aeh7-uy3+h{y_|P@KjkF^_9TRA;&4hKSAD zcvzo|n{^kZDd`g#Ddp(0mCV$vPP+X%C=C?LgC~w1otPLaH5vlZ4+0@@Xk;0aH97*s z!I42COV;{@l2<5|2KMEUBgtBiu2>BW((?gvr5{+MO&mEhR@`mFmwSFe>xe8JJ9;P#8c3&QeNE;&JIJQa}#Co|hh=@*WqEM_DW5Q~c znZt+*+H`Da(hFw!ToCcpK%>?rJ{D>Ih#5%UnLF6wnW%$bn>rh`m}Y~`Aa=)^9ib$V z&9LaxT=Yj|`m%^K_n^7xg&ZvWHLLv2i`o&hWa6+cgv!Rj?elKiIinlu8Mu$6^&(?L znNQ9+KNSI;%5^>|+MXcgq=P#b`s7dGv#YiUQ}rBXz~o*y7kMG%NZB$BD+35}+kDoy z%8>tG?o>+RMc1dF0|0w8q^CLU3@ZdmInmNfgG|Rf7X{|4WU&vd(fU!MwlnkGa?Tue z=WDP{GY)gtlkvAD!SQtP<_i`ME}}Z!nG?0(izkv??A86!7)(QsGF`FE83NUv(np9w zoIJG4T5WYiM1D|WwnoQ9Tx*2ILa|&fSrZ$hmFEkgble00<@tz0`30@xiSY>pE|&r! zrIfz4+8XWo1tH|f%JpXp4=*CtCXYw8Npj4XM9eHbpR9?SH9+)(l8&P&Y`Dmb$XaWM zMwSX8$ZBRX#xPMF$A}md3PMP!JZA}n5YEanbA4(;>v+lXRm{Z1%w*!orE{1pGc}q~ z7)6y*kV2hY9$b=fgSzaI(Xre9sYnB1+E>m^qFbv9@8_TqvbL;K9Km zAyDgx$@+y#irE4)4UDc_vg*8iu?!jAV!7xE$S-nskgYN8CSsmno)@4`BRP#iAgbQq ziAW|w6ett`lhuo7sko2c{la3~Gp0-GRD!g;5UlQOM7$bPW0NNiC4EG>_92&X{@tPe~I7_8CO z#zF{AT2qoh1`%^D4cN<><}+l*03ahHWQj5YPJ%@uMkD}oPew=~gd{S+m={-KB2I%# zCd)4D#unDs0@ItVAvl;C>;5hS7zg3|OK=C#CK z_yz(KB5!6AQXv2d2@JxOx~4&|V;CpI^fHntv!@lwm!G9*fWxC)(zKg68yOh*^gnSv z1z*7cG+j`bzyex}&zl=iE>kTQTlV3MFa@XbH zIHi;jqBOV!PgnM$yX}_|t&ZZTq5NWYzs{Ig%K)t7CL$Kg1MWR*w6(_Q7!lc87u*OT zd_TyHTvk5k*cigF$waX>##j?aneqcMArpc?6ev&$;YkscDnbah)-`9f#UDg*9Hp9{ zEQGST=t_`eCij4K90IVEzEny`<+>DHj2?weYqb}YiHze8B*WGkYuRaME2Wh3g+N49 zN(v$B^%^3@h7d9E0%K!lEhWlS&ca&bXbAwN5F!=PW^1%HhR9^)k%$f)<{tbw%nRI+ z-NSW>5F(3dMccHSKlOeelgtXZl%x`%5cVz z>JqSXR2E?`I)eepS@! zV`|Lkh>4A{L<}4ebDnTAWzA@%1HskZCbT=&{gO6TNESlaG?#?{)$yauth_)<_588p zzVD9=4+B8hth%#YrGBAUR8kfyBl7eZLgwxUGDI{wj>5X~3Xn5|nDkn((V-Un7WQh{t4uL3S95$>aZH%>KboAYOpKeAPfG=1(dez2rM7nWE zDU}q3;((CS;nf|UthF|dB19piL`0O5b(GnUO^@&Vvw!-r`}@zK@em+ETYg8lK|FIEQBbRMuo8e{NsmqMcOj+ zhSj6jU%HkFJ-^@@1CZGQF@rUltl?bgJf|$Fn;+fwsXzH!ckmzn>{I8RyNa1NJ+ke0 zKJx{4@b5qO$qnbMoYUiVBPJ06k=uLw`_G6z;VC;H)S{4ximYip3+_g8?My#nx!2rV z&?~XcjEIN}g-H<{%s`72JDt%KIkS8a^2|2pvs@9?v7^jvtwtds0eJ{fGBW@Hzo_*H zyDI$>?;vdxL;w&%Ivh)&0Kq~CAeK^cGExZ18cT)rgh*;E5}y&J5DefN$lHD!1qz9r zc>S)$+)XJV9RCP8i6^(KSQBSRV2g7ZVOG_-bHPJ+8cZmyI&nEdq68ge1|lHhgkT}r z_$Vo^!30Zei)fPm3XxU0pb&zSiW^|Q{l0BuQw;!k%gq;Geet=uq8N7~F=5(@hiMqa zttdUQB_gj1*!j4#XuhQ%m=r)k|GYV(vtmhxFDsLAPm0(&=fGLAA3V5YqS^$2*T3w- z>n>RfT}f?pdP9p=2hTHa<~^aGnLfkQy_a5mn{p-33SdN>2A?{EfK5y>ZREKiY}q)R z9#ioGummswp8fqTu1zY}SDK%n2ynJVgmY5h>sDYu6xGS2#}DrGgOcY5Dkv2PN9y$& z5tYhiXa6z_8ih5bB#~8K;1|j+!&mZ00Ki%U%+_e7d33>MvkQl5X##v5tA zqy%g&@oY=v$&%LAT8l`Hdes^Oz(U9%2#9%nVk(HWjYGds3W^nNOtTpli$z3~QVAh+ z9C406K`PG=in*jA6^mtN(sl~0O)6Yk@QYM_!9`A<@B2XzH>#Z4KEF@~1Supi8?p{z zX0lwZRP4=bTZ4$o3z)4nrgvc4KgZEG&5<70QHWxGrLZid5<(K` znYI+!k-s1^z$9eQ6M11vv)-)4OdzBaToj0>xBa94M0%lwTIc8I2%)6%AgL+<0M2Vk z{$%M9CXB;Ux-!L7{2W?Q0|VyDJ~|3DT5xM_S4+wnDJ_ubVEIg!FaslZ_^r(O{&f_N z%1%m@Qn}wpA%&3Ler`8l*!TI*iR}Qped_iG0PO7)cWltPUI=a*s#aS?TO8M;_9Wf& z5E;_WjrLHhmCDTD?#1g@{`P-(qbpclv1A|@nc{haMY+KhmryQq|@`4|CkCnxJF0%6)UIdfo6klh{ zmuUT~ExJZ!jb6ksT1xMf0?G^NEVf1;+qcycX-$673(7-rSkujVBaE2Y3&=wmg*7Rp z7Zf1duM@%g7==U>&MOa_4P(sE@CaEO$4x{Giqg$UDOI63NG5Jfo{Xag0DFG1!-=y- z2fnvr`7*bgdS2jpf$|H?5b5KV;_<15=Xpbeg8;ni@w+>Ql&xKT{?&`ly(E?JJXstZ z5kmTf5|Ndj&(`Xw0f6h)FR^5;Hoz2z4Jn~iDnXJLEC}i8v?Cr7gJQ+#usZR)=NGe_ zSsXPTJ^%mu%6&TyoXCFn_D#>;zUkSkE?V<@AA3_WK4kBGZ14SBckMlVqSlB?1%K7D zp=&p;ee=zi4GffxG0kSv^E{XQLm~1!VcYi}{j-1ik^B3PKJnI4K~dbi|A~G7-~ZX{ z4u0j2Km6$SL*KgliG$BiTH-a!hhKBu1#i0P(vHH;XZ9TX!2{3jI&`wyh$=;Y$x!90 zi_f|BWfzq_iHPOOz#shOzdp04C3yS2&Ch;s^Rri+zw(nmcZ<&~8DJ_)}%I9>7GP7}1k<5z@jh^XgRUs9z>4J`1&OsJ7bm=d; z2q7(;=>fWShi$G48{5JU?6qiJ8mc`=Ovwb2HkT~=NvO=E6jEl*&;`^qKdd@wlUgzI=LKiab63*UMm`{$lRC-xjV@#K!fpZw_SvopW(<0tbbmCv{e*72Sal=hluAk|*_)Fh@;P(4k-%vAAZU2$o`;UD6j(b1${PyUbBoLzJE;*~DRO0;QC$NHVR$(Ar7~N)aFyN<#p|#92TSM^UMq+l7S`fPPTQ zTQy^}HIY=FlrEvdMn@SsN;y623>CprR$+Ob>n5{ zY*;<=i{~)_kd3GD{mBww9zkc!kr6VJHC9NWrft*aUNK_Fv*X#zhxJM; z&NV2U6BtX@x;nDfQ|tc-L@tHq?ph=%?bdG_qlJ_`Gi}p8TWdJmVFE}=-)&dKj_ zIxT0H6|_b-t78CM9$9X5q?-*lce5fsL{S-CAw7T5bA)GfUWAzuIbAS>AbT!CPPw6( zbM5ZLWNmldR(F?SpM+WOxy4!UHc{39E`;plC36jT#IABx>zJ9X@m;J&i@{%$o9M{} zwc5{^i43!9(U|pdu{dKFBO-ENgVtJWEX$;B;#JpdSTZtn|Kod{3E8-A+52w25&*QZ z_dm90$NuB)t1jNK^5@@m^V;RZC&ngj`@z;tkM9P6iE86(KivA>TQ13dXnM4~)k>cs zz(Rcdr(b#Xg)74-{^mW~?tCzjPJH6ogI8a;5&-UgWS2X#cE!-AfBB7`Qodh!Wc$I- zeCY=O5NrGJGY4LA*_zkgaDfoG`N@6RU3~a$FLS}~j~{wAHG#qJ{lcvq)~+a4mTZ3d z&>#Qhm)$i#xqWxHAHg(xD#0MuPGA*2-2Q%uxeS9)gM1k42Z%|2vgU~36cN-2p6Ol*t+ zz(NoJfK*-rnj^}DK`kI1>o`QGtXC)sdDL*Jxh5*56v+2qG?qDJC{@_2oXP^`SK)F)> zh`^XuT=nLgFS&N( zDqt=Z{P({0%DW!kX)OW3iHWK)8UUv1Nxr8Unz5;9_3{EBUVrJiAA9#ru{PG)6(bd= zHf7su0km zs4@+cwQQ{|R|ZfBr`igMP`fXL@PncTFmWh^6jJ$8L4afpGg)G7j31P&(Hao}{6eYO z3~RMo+BHZ*pf(l&l$2@tA!QqdwG?S91qy+_FO`&1dWcBcW+7;{r%R~J4qIv4n`FvX!g= zKnPhVRX_+Sm5C$eZV!dW1k6sNPf7q5$_ui!?sHKu{PRBiECF3Z{K?i08UQUfAi13y?WWuW#_NDc>T)jFI_iS_UrXJ04OCKNR}TW zYYh@gAwT$*8-(<%)njAh&+IvN`1s^RT66SeCW62QlJnaRxcUYS!bnQLNq~p;2fKZ-NejG<}6qU+@ zez8bK1EP?g=%*z~WZND2o`chU+Ns-)a|6g?CP|-^UchF=kWOdqOpX0|(-*kFz(xj= z%6vz(L|{oM9}wfH0l6F@_cW(%J7qt2Ajg;S0$J4Ap%V;wnhjSXpP=*1-AE*-edS5r ze6sj0Q&K@fWSJ@9-*j{yPOk^i(N-EuNko{IQ@Y8=Oema;yX)aV*T2q;X~Bvk+Z3ts z8Qz<;x#gB-N#?x8@fJR4<^xw^E=#me*N*zWNjMayIQUCxT07*naRIQ1@#MW96 z7SI5qQeIXK!zl`xDA^OWs(8`{jI8gzB{JB)K*uK<*+N~pbSQDrlB>a0OIvpF_*m6Z ze`U#-EVRgr0STdmREpc0_J%4YDWy{)R7z%nZzi|&o}apE%TxQO>Y+P+`1s`Ey{^XfAhy%ckDm5P%MzSKZoZWOh~_I=#0V}ahgqL`kkHU zjPhmf1)>1qC=wC|2TGF=Ef*x$Ns|D?Ks&$4jI?w`EEBd#v9vo2?VbbxxOM%4Q|RrL9wKxM(W!p@Q%@us~ItI7)1?bwN%=e$eM&W zpR7g1`owWgt3q|u6u?WCjApvnD8%t&$B3w0u6Uku)ILH;CaPD*f`YG<@1E0CwN|S) zi`pWBwM5L;SRqxhR07~QYFKNm(SX1V$_te8lo9~K_lqb53K_@ov7?6ppgMMFV06`z zRp-wV9nFJ3?(&R|m|1J1wGB!GMn_~~w_L&~oERT>pIW|Z&GJ=i9bH*io3uuILD4Bl z5VJK6L=;k4qn+an%$`>O0IfqHYvPbwVY)FoVj`OhFRYHkdez}hI%=X2Ou0}`hdOKk zvqP;1hDWo#raV~9P8%Fqx^($cOSZgkEIYVl$>@^dN)*<}n2}|xWZEt6d46SRl*tAK z`?=qI&o}OTbkh@iCu?DTxSrm1&kiUkz1`vjw72iDCsN2B9t zKIW5bvpNna09Yztd7g=5YmK!Un5|`I)|R9YL7?(Gs+7X>B!jg&s@JNn1Ybzu1tliy z7zc$^E<$`8b} ztt4sX#;k_hO~x}_sy-tJOY?9(18%nAld+Yb^R;&!*5 z(|D*=5RoaM=ju7Kp7tbmauV<@qOx?^Cyf@Zwtu%!l}tD?X4g=WYujk+^Jq^}U`t3L zD>ZTo6IpoIw%9TUy2U$;*>6C~Nzm>yB90D~vr5|MPfles(7leHm}(ibp$g`eAlxJA z?s-XAz1wKJDG9n0x%<4FMCRuYRf<3JhHKvWnoIT{o!oig#ID2RPwhP77-+Sj+kW`? zAAIcAUicv(LZr=??|9f9x$xYjpZMvU*Q{Jts0@QYkT-<0?p2swlQ=GLT_B&HGL~#U z@M7G?v<*33p-+CyF%#lRWl8ebMqVI`(*om+ez1)V0y~6GAl*gMuAu}LNe?onghL|b zHSM3QnEP7`2oT$A%5YX=n==zG*zII1$7#_io;Fo8m-*j!b_mFmMECz`HBHTQyUW?> z3uLAqg+$0af_b{7r%AVu*$ay0;Uzk3#9_lP7X3nrt!1`RSYx6_qNcGK4X~2az!diRm_*kLf6$4KxUwOWcqcE;^R6=^5TDEiv z5gj{mvJvi|IB{@z={ZBo&Y5w+ph(o%5rxrlqdHa@TILoiAV!TTYqX9dB07BJ=*W^~ z7hZBj($NuzakJX2O#*XJ8W2*EHN@6NaVrgG4NBP|dnSb^u&pN6DL6{y6@9gS^^!e@ zP5{8>CwBk*yTb|s0K{PfQGEZt$CH~?^1^eMleNs`ls!xwI#h$0bkxWtz^v6#OS7=u zr9;GKbv#pqU~6m~ot&)y^}pQfcC@#?>Wb^H+<5(!8<`=}`VT(;&0Pmi0>HszlUf_k z3kC)&`6Z^c1%SOrj%7N9Z@c-@;Yz{b4f_usZOhEf63_2iP$rHR2x-p7=JnK+PQ@8$ z_8YM^nuwf;V+!81Nmn>-Gv)dDlUpfJ9nbq_U75Aj5da9~Aqo?RLP{?v67z|%3Fq4l z3=9qgMKp$)OO+8oVNIN&?hesce!*eQe!(qOS0hR$wxHeC zGStqw|7Qwba&b07BphO{r5GWiqBF=vHq<7SLaYBfs$b-n0cy!!5 zbW<+jOikPX01!qx3x;3+ic8#|%`pDV7w_1A(@q#Cp=ANhN^#$CylVAr5HCNoPm5dkp87I_>l1Lgn$l?~D;5Z=&SG=Mp4&(TnaFo`pOFc0^?+iOcel@EnVWKR2)auTD@GZlq$m$ z<72KQMTn%MUr32UE?qL}1ZJZ~_1OMrPzYccT((vSm7kscl-m$-YH|!1hzXeeLYbKS z(ttH)d@{+skVoenk_=3u zo>YFp4@$LKtyZrM3=9+tMYohDCa1L4YuBCUBxO7ySFT!POr*nx?+LO-dA{@lwwjp3 zX2V+R=-1t<@DqPorpyBd30)Pm=Ld<-jH>_uh?`YQ#^_iI%|OZ^6(P#5!!v}8^G;GS^NazdwdNF= zKp_>Ph?_M;;TOwpdbmDmhfJ`gT*o*7z(OjQcme;-9xqOEH!a@h1>oaS3It5KAuuhD zaZyfE4bR}D^sGCWrQw*Jb~#GkOJp(4*D{ey^P&(v>#3NX9-cl4(IJQ%gP_QMyu86iye{nk4@}i}6o>KPkK5L}A@&>SE$e=QhwpAW1m2 zjrMHi^eKTP0eZy+s}p3!*loLy>^gAVJ)mFz;4Q0{4)*-~K)LYSKmWSnfkKys!?|QN zayb#`ct*fXA9>pi7p+^KUEAKnCwCq=o>{@`FJ1Sp*IpxpL_{LGWJBxBXZIc7dw6W1 zTzJPVS7g!QL)#8)d1_xXjNbqD*DM`L?rVIqmZY58Q<}4QK&L2WFuTmne2`b{$VPWO zwEP0k&#qZaryge5dCWv)jY%xJTO`(6YefZcj>Ka_wAK>YtT4S*l-~AR0Qqs~9*~~zwqJJcQ@wjtPH`G)rbezlx3IwfxUH#% z9k|yPEcbevicUXkD!W3G-n>fP@k%?Pk#1$XQOqf}X0nv3!x&?=G14z0ibA1CWQ~rA zD2j~`qEIM0?1IT!6Qe-Eth~VUJY(v_eHFlBCKI zCF0=Fu;(cu6>F`vb(Nx8#{z}&JVZ<-*RzHcY%LlhvNi|;W)?`mER|=iZ8RDHP%H#V zldiR74Y9VCiuEa>lwT-|q(e4o?B!&Zv{~z*SONg6BWvAEbx^4FloY^ZjkP9q6fBcv z7X=Do;s}Ir`nSf!h{Ev^BPQWd%kc!3%KPx!UtTN~A9#G%@v$jm$+f;B;!vgVsgJzo ziQOk2d}`nRqhs}ET=2bB%Z9GI%-mS8cfYnhSt55eR|BV(~+7xuH}j zYW6!}8<5K|etsicF z%Pm)}TsoZZBP8z8T$ml~4(y<#AssQ_rqbI7X?2-kx-~=EpaRzDZfC+Z5#`ea9ie{5 zzailznoSy#$jQMka62K=aY$sN*r2eUXQY6@SDxod&sWS$q+*@YH(4^8IUzpugOb~A z$Qoj1GS0;$;wUxyKR~Uu)<#O9q;P12)ASKip^!RmppXiK#LXkHmH;gyFdALD zd|+res#lq995$Hk#8lJw{o&zZM<%1AFbb<~$oxXt^NWqz7!yUYv6extsep)?>a|*ej=#&I-u@+2ZIT{7xSrZw7Ht+kD{S+aDwRH{6@+-2F+=iI=S0KxD1aWbN4TBgOJSWpLQ&n5;>l(NYCbxPY}jH7=#{ z3Pom!8da&h>^ZuR3UrjmBWPAfyOVjU-E6*jXb<}jg zo$>dl*021(hHpRjhao@BP69P6ifLvI14?(Ij5iI@hLZ-7v)D2>pr{7 z=$4;cpe;ni>e%!7FL5cujChNgrBazWJX7@ud$L`0=RBr`d9aVIb@I7VN=!2%?3&O) zWHh8i0Mx8cud5C0g|eGDFmgR5RL}SokqrB3WB*$3X%2f zCSg;?t<~~qa$0v;Vhj?s^w!_)^HNADEfMq)2z9Aa2M8w_zLqzL3~hKz4tBsiho{T` zCA{^aPSD`A&&0*Q;8+M+k|0T;QxYgsf)Tse0&NmK z6LU*Vfm@C$U`kT}0E~HXjMFw4=R6Y;k(9EFav&+k=1le@9eg1KB8XOyo!qar7A2n+ zg~AN;!P%bNB_-cyS+#MEE)s~kX!x6(0*Jk~52AGOCdacxX`&;YMaGDL!hu!pG?8*F zxQUVG9WaxiNxHIIuu!faBUeq25JvSc^T* zX(h})bXJSfKhz`r-sQCR`QaU2)Rm66e<*2K-~c;XQ# zA5kb73goC+W9DWvE|$vW%21uGQ+snDE$9rBu06VW#o%3Ex+NrvR~3^itcFsXK8{C>vv@rm6rO$Hw=3zgQHA zN}waJF*;1S@vu=Hvkqh;o|u>jg1{*S0&uZZ^8LcmqelU-I5^rJ5i*lCiH-Dv;=u4S ztz#f7g+!S|awck8YnzdgzAh#t`m)8b!Car3Fh(~bEd>T%!;QRYhEc3NB|RlQ&+|Ml ziXtM4w6#R#C=yZ@if!}@aTLZ;B#WDkdK@<0 zmSc4c$c5s7C92jVA+S&=6A_V-%2!^&Rf$@ooRwy>rNI%lR>u)D#ZgmA85GJ<7&hwT zZgk3(0Tiv)C=|l;3Wz9_=PIq-2)dnkWOyjmrpM~!gv${!o9fY{LnBKHrOHeh6P^a@ zaj<$W|Wjpo#e6V9g@9vLZ@2b5o6=6dt6 z*3rmd354*x0003+sZ=hN%AAtpvo&6!42ULfvaxAnyCBmx9#x@K?|Qm?>coj) z_X2V|DpE>WTK&{ajIUt4Ibg?F~<3FGnuR zvu3Hl)VFmx+)RQ4TEtR49&{S`2@$=Ya@ z=p^A+${g4#nipw{OIt&K))A6>knXv=aZ3j?-}~RDP2Wl%Vk?Ty)q1oSL?rWUAs*`K zT`mZxTM+_hJksk7?7n7f>&@qmP&fIaw1GVz`g5+>xD}~)_!iKDKt#sGk)SvtT_6ly z^7Ng3P6;OQ|Fie*F_vv-_*5iBp9`nEA%!uvfZYI9cCxP$c z!^KlxS~V@V3nZc>QP+TY$gM2n%xbC8%H+`kW90VlTg*3=5`>ivGZ-HI9jtQJN7 zI`94a-Z%p!B9{li<>lq&Wqoo&i1^0)-;cz_Q95`qS|x?h?8f%n0K@Aqm5|sMxtP4$ zZ<~6TMfo3n;KSu&wLO1}$gwXV>-U?PO54=+ez!V(usXeOV3^}C!W4t1RBxZl#fg4%jRCSCJ9Yr$=T1yLw4pcv1cAXJL}>g- z3hfZ^RjX4~$u^mf-+7{@F|^K?)$-KLLcL3&)hxbchU^HCeUa~VwYK|@G{sh8Kq6HM z^+t765=TH{r)rPiervHuIymzU zSOd$-ZbpMIeV=Si&ELlyWUL@#|2xDiPcx|nPoU>x@H@w&->z1EQ`;a%JUyn&)Oz|y zcTIpsgCAkvRXtSlog{x(T)-5+4u^k%G=}pbl=7YjbpVao6 z;7HTZ(vE{poVVHF2n(In zObR0jsTWt6w~Xg%i-#wX*N<`8#!-)PmXUNFYO_w1{)$Qg;yg{l>yy9v>H{w!u<(M# zfIb<+cfZ^Hd?Ajbe0m}gheJkqrM1a1j|2h1r4$j7pSQ_p@YR)g&M}BUlo*F^a^r^l zY4I{siLImf{tKY4P#T6jbZ?QRsuB*&1d=o`ACh?w2_P#g;07*erR;LeR3{RdsMZ^d9&ti%x21oqp z;e$LIB}ODsNqFe@J6~bUklet&f=>4UedS0Jz|*$gpFjR&Od3;q_}UxyU;kikCxm7f z_FFJDiK$0qb$(XPSBpicx3S%;BmnFE+w$gVh`_!CFbR!F(v$)-634a%Gm&Vfr)LiU ztleKCAp3&YnN#Qd`t*J-v}W|ziJ2j$wnoI&dJTYC*-KSI+q6x+zIVS`o}^G80Yql8 zK&5J?``xZ->htqw!?ZbB6@!k>q{B_fZkh&(sH%;0Y%rC??42(F36aebn5L9orY3ne zH}-dPhobA6Rd>uVdzmEcd9h}eLL(_OZ32Mx={@J1rUYG3h>*Q4Paou9P-2^6V&}-< z?4AdJXHVYtzC5}A2mn&s5@5@fIKs?H>?5KTvD_Z&t z7uF@#4PH~syG4>`HynBXwQgcxbC>GlmAKOkB{_EcxZ#|MT~RJfq}e{pf%i1Eb+?_3 zw|QHRtY$jKpH8nnR{_XeS2EQkV&=zGW6T^gij+F;onnu^?Me4Th;Kc^9y=D@*cBw# zY3ugXoKajUZ;&Ia7N&y|kuvyk2I4cA9|1FupNJ4>3ehxELZ0B=pU>2`gOnMEz_0HP zj=W@%lsfxjk(~2&Oar@GA0Pt(vXBI^;2{@&q#<`W(N2E8YbX+tnW{(!;qC3HD0BHc zLGUgpmqB3*5sA?hvGc1UVrHkrHxrepYy2SsB-O*z^XP-W_>VsE;Wtjfo;y)+(%k*W zF(Z7nDd9CPiJ1&Ic@}nWYkqCeOrfX03@tUC{s`H|Mf0u!?}C9QrvTaKx@q zNC2_R*iz74>bR+rL{ez$tOA2XOq}}%2ofc#gu*jB&&&ovM6*O$j7e3K?oBNvK?LWr za44&SWZy#3rfCq7nVc&^vri(92@&^ojnlKMa(qH-OKlgWj{#U-?D}LwK{oa3SXcf;fQ_l}K&S>H6l$<*TJrU9Vg3I5c}=CUV&bEXB|l_Mt2*V$PWm07^C=v#ArRfcmTMiliJH9@kgpkHr=XwRteo=N77sD!gx1WrHy`%hvNs~Icl`lt6m|q zsHA$^i7;n|3=z(Fgl1}The`Mf-~3)}glGmaNvWAiNZzq?e)fbW#eGRB*v=OVDi!i<>Qk2wAb;x47@4N{SnTcbl+Vs9$RT2MgjE;b_(fO2)3pr?rK_uH~soSr=}uz2xAokQeK+M}>WTL*vRtM~>_#8WF$zMtE1i_9QPk zhT&Wvzg}l&KV80GWGcc9n{F?Q)%_Sk*lxF{r>A9AxfrHkT_h^1rJ1c$FxA-XxhS1S z07Q1yHpBQV$_l_FwgBjgQY1C|UEWQ7xgd7g7qgQ*O@SzL1NSvV=j zQZWhiI$q9Kh=?FXQM#fccI=#pY2FBDm^I64K1ans>U!|+X6gF?)?}SA&WJwCJRIcb z08?)XL6{!-#Zy1KKK!~lW$d6&yyw+#&%^Ws&%3)LK+mVh9LqXBZ0Ceao9pHX3x9dAI`h&f=ceu4+s3h&wKyh{XajNc`N_>Fa7$yjeqlgl%wI8F zUrFuKCehFpZArWu>T$>7n&A<)=(?{aBxags`J2*u*D?Z5H=8>{WIwow6mS$$I zs0y`3>6t(!<*5@xGh3s{mBePYZ^CK0T%SE^_Luw3({i!)#LG|hguIXQc{K6@DIU2N+)-YI%xC)pBL3_Z}>>HJzCi-@)92`YLv(KX?A9)~&BVr5<05CgX&Y46H3io;Yj3G4AILE|T@AtWmN}as`K6>=1 zn>oJx?9cuD1pGrk{xkVEfA1f?`Dgx{pZe}U{1vCGswlXBg6NBdzI3k0J7`;PG&YVI zOfN4liRkR?>^gC^O#FX!S%zwg`-~`6a*o8^7vz4IlfpH_w0INB{QYXWJ>!|6PuV z?_$(&Q&r{$uadc;0nF~+t^e5po^Jl9Ys_kF<|@#+TMrJP6FTXE!@!UYOa@+djPC~6 zkV=jseElp!z^TU};G9h}r8Er-(0l^qk5Co~?7m}4tC&iB{FB$apXyFEl@8-emDC5t zgG7@dGZ7JcBz`{T^*TcR?Q+fB;JKwX>vKhZZy;=%nS?sD?XC%aak4ypP(OZqS8q;F z7KF4sdC>KovUh_d0BGyoJD;laCGPf5LrnKhDk5@4Nyzt4m!h_-TU9&1+;i^2<^UEQ zGt^BoQ*L7)LZ-*>Ji%~ zJC~0?Q7qQb$4!W+GoSa~dfqIBRwOw|mi5NWMB=m_O3Xxl@N!et*w(6<jo`+c@XF z_e4z2I}tEQp#cC_l;n%2kKc6Ouhyrza=^~BqoE8SDHi1d5LE?Koi9v{*r{r}-{cGQ zjq9*9y_}O31?|J*__CNWNpZczE{ue&y1NTLZi5`~K3p8%{E~FzQMtC*xJG+Bg z)6Kai-nuS3?bAz6;*Wp=#nF`QH>4J0P8Q7`yzw~zRBz8U#i!@z-Z^#!BAO&qRY}Ei zT`o?V{YBXC9=!H`Ky3FLm9*dQo$I~b5hccUzlouap<(vJBIbOBgfUzY({V-0xgw=@ zcK&9Cciig^meq-*;9Q%M?CY>ZHw7dCK;fAv+lF$nI_Gyf|VG|WZ-p}XPX!N2l%fBx@({4+D&KhDyg`{oxdXkBNscYP8$Gpx__^8;$Z_0YJ~Ca=ay>W4DZ{FCNd6*6*%L0e3a)E8+%DL8d8M~29F|QF zlt)qw8AOy~Q*WPDg)3iswA*eCw5SA;cblg~ob{dWom9>j-e((FU9$tE++9~mU{)@PACKAGE_SHORTDESC@ + CC0-1.0 + GPL-2.0+ + @PACKAGE_MAINTAINER@ + @PACKAGE_URL@ + @PACKAGE_BUGREPORT@ + +

+ @PACKAGE_SHORTNAME@ Doom is a conservative, + historically-accurate Doom source port, which is compatible with + the thousands of mods and levels that were made before the Doom + source code was released. Unlike other source ports, the goal + is to preserve the original look, feel, limitations, and bugs of + the original DOS executable. +

+

+ Full support for single- and multi-player games is provided, for + all of the original Doom games, Chex Quest, and Hacx. Unlike + the original executable, network play is implemented on the IP + network stack, allowing it to function on modern LANs and the + Internet. +

+

+ The easiest way to run @PACKAGE_SHORTNAME@ Doom is to copy a + supported game file (known as a "WAD") to the root of your home + directory and launch the application. If you have trouble with + the automatic game file detection or need to manage multiple WAD + files, you can run the application from the command line with a + path to the selected game file: +

+

+ flatpak run @PACKAGE_RDNS@.Doom -iwad ~/PATH/TO/GAME.WAD +

+
+ + + https://www.chocolate-doom.org/wiki/images/9/97/GNOME_FreeDM_DEMO4.png + FreeDM, DM05: Metal + + + https://www.chocolate-doom.org/wiki/images/a/a6/GNOME_Doom_II_DEMO2.png + Doom II, Level 5: The Waste Tunnels + + + https://www.chocolate-doom.org/wiki/images/4/41/GNOME_Doomsday_of_UAC.png + Doomsday of UAC (uac_dead.wad) + + + https://www.chocolate-doom.org/wiki/images/2/2a/GNOME_Freedoom_DTWID_DEMO3.png + Doom the Way id Did, on Freedoom. Level 3-2: City of Corpses + + + + intense + intense + intense + intense + intense + + + + + + + + + + diff --git a/games/NXDoom/src/Doom_Screensaver.desktop.in b/games/NXDoom/src/Doom_Screensaver.desktop.in new file mode 100644 index 00000000000..deb7274aa54 --- /dev/null +++ b/games/NXDoom/src/Doom_Screensaver.desktop.in @@ -0,0 +1,10 @@ +[Desktop Entry] +Name=@PACKAGE_SHORTNAME@ Doom +Comment=@PACKAGE_SHORTDESC@ +TryExec=@PROGRAM_PREFIX@doom +Exec=@PROGRAM_PREFIX@doom +StartupNotify=false +Terminal=false +Type=Application +OnlyShowIn=GNOME;MATE; +Categories=Screensaver; diff --git a/games/NXDoom/src/Heretic.desktop.in b/games/NXDoom/src/Heretic.desktop.in new file mode 100644 index 00000000000..ed841628bf5 --- /dev/null +++ b/games/NXDoom/src/Heretic.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=@PACKAGE_SHORTNAME@ Heretic +Exec=@PROGRAM_PREFIX@heretic +Icon=@PROGRAM_PREFIX@heretic +Type=Application +Comment=@PACKAGE_SHORTDESC@ +Categories=Game;ActionGame; +Keywords=first;person;shooter;doom;vanilla; diff --git a/games/NXDoom/src/Heretic.metainfo.xml.in b/games/NXDoom/src/Heretic.metainfo.xml.in new file mode 100644 index 00000000000..9f4bdc316f5 --- /dev/null +++ b/games/NXDoom/src/Heretic.metainfo.xml.in @@ -0,0 +1,47 @@ + + + + @PACKAGE_RDNS@.Heretic + @PACKAGE_RDNS@.Heretic.desktop + @PACKAGE_SHORTNAME@ Heretic + @PACKAGE_SHORTDESC@ + CC0-1.0 + GPL-2.0+ + @PACKAGE_MAINTAINER@ + @PACKAGE_URL@ + @PACKAGE_BUGREPORT@ + +

+ @PACKAGE_SHORTNAME@ Heretic is a conservative, + historically-accurate Heretic source port, which is compatible + with mods and levels that were made before the Heretic source + code was released. Unlike other source ports, the goal is to + preserve the original look, feel, limitations, and bugs of the + original DOS executable. +

+

+ Full support for single- and multi-player games is provided. + Unlike the original executable, network play is implemented on + the IP network stack, allowing it to function on modern LANs and + the Internet. +

+
+ + + https://www.chocolate-doom.org/wiki/images/9/93/GNOME_Heretic_E5M4.png + Level E5M4: Courtyard + + + https://www.chocolate-doom.org/wiki/images/1/14/GNOME_Heretic_Shareware_DEMO3.png + Shareware Level E1M9: The Graveyard + + + https://www.chocolate-doom.org/wiki/images/3/34/GNOME_Heretic_E4M1.png + Level E4M1: Catafalque + + + https://www.chocolate-doom.org/wiki/images/4/42/GNOME_Heretic_Shareware_DEMO1.png + Shareware Level E1M3: The Gatehouse + + +
diff --git a/games/NXDoom/src/Hexen.desktop.in b/games/NXDoom/src/Hexen.desktop.in new file mode 100644 index 00000000000..4854efcae6a --- /dev/null +++ b/games/NXDoom/src/Hexen.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=@PACKAGE_SHORTNAME@ Hexen +Exec=@PROGRAM_PREFIX@hexen +Icon=@PROGRAM_PREFIX@hexen +Type=Application +Comment=@PACKAGE_SHORTDESC@ +Categories=Game;ActionGame; +Keywords=first;person;shooter;doom;vanilla; diff --git a/games/NXDoom/src/Hexen.metainfo.xml.in b/games/NXDoom/src/Hexen.metainfo.xml.in new file mode 100644 index 00000000000..93370152297 --- /dev/null +++ b/games/NXDoom/src/Hexen.metainfo.xml.in @@ -0,0 +1,47 @@ + + + + @PACKAGE_RDNS@.Hexen + @PACKAGE_RDNS@.Hexen.desktop + @PACKAGE_SHORTNAME@ Hexen + @PACKAGE_SHORTDESC@ + CC0-1.0 + GPL-2.0+ + @PACKAGE_MAINTAINER@ + @PACKAGE_URL@ + @PACKAGE_BUGREPORT@ + +

+ @PACKAGE_SHORTNAME@ Hexen is a conservative, + historically-accurate Hexen source port, which is compatible + with mods and levels that were made before the Hexen source code + was released. Unlike other source ports, the goal is to + preserve the original look, feel, limitations, and bugs of the + original DOS executable. +

+

+ Full support for single- and multi-player games is provided. + Unlike the original executable, network play is implemented on + the IP network stack, allowing it to function on modern LANs and + the Internet. +

+
+ + + https://www.chocolate-doom.org/wiki/images/0/0f/GNOME_Hexen_Guardian_of_Fire.png + Level "Guardian of Fire" + + + https://www.chocolate-doom.org/wiki/images/5/5c/GNOME_Hexen_Effluvium.png + Level "Effluvium" + + + https://www.chocolate-doom.org/wiki/images/c/c1/GNOME_Hexen_Dragon_Chapel.png + Level "Dragon Chapel" + + + https://www.chocolate-doom.org/wiki/images/a/a7/GNOME_Hexen_Darkmere.png + Level "Darkmere" + + +
diff --git a/games/NXDoom/src/Makefile.am b/games/NXDoom/src/Makefile.am new file mode 100644 index 00000000000..4fbade07b7a --- /dev/null +++ b/games/NXDoom/src/Makefile.am @@ -0,0 +1,299 @@ + +SUBDIRS = doom heretic hexen strife setup + +execgamesdir = ${bindir} + +execgames_PROGRAMS = @PROGRAM_PREFIX@doom \ + @PROGRAM_PREFIX@heretic \ + @PROGRAM_PREFIX@hexen \ + @PROGRAM_PREFIX@strife \ + @PROGRAM_PREFIX@server + +noinst_PROGRAMS = @PROGRAM_PREFIX@setup + +SETUP_BINARIES = @PROGRAM_PREFIX@doom-setup$(EXEEXT) \ + @PROGRAM_PREFIX@heretic-setup$(EXEEXT) \ + @PROGRAM_PREFIX@hexen-setup$(EXEEXT) \ + @PROGRAM_PREFIX@strife-setup$(EXEEXT) + +execgames_SCRIPTS = $(SETUP_BINARIES) + +AM_CFLAGS = -I$(top_srcdir)/textscreen \ + -I$(top_srcdir)/opl \ + -I$(top_srcdir)/pcsound \ + -I$(top_srcdir)/win32 \ + @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ + +# Common source files used by absolutely everything: + +COMMON_SOURCE_FILES=\ +i_main.c \ +i_system.c i_system.h \ +m_argv.c m_argv.h \ +m_misc.c m_misc.h + +# Dedicated server (chocolate-server): + +DEDSERV_FILES=\ +d_dedicated.c \ +d_iwad.c d_iwad.h \ +d_mode.c d_mode.h \ +deh_str.c deh_str.h \ +i_timer.c i_timer.h \ +m_config.c m_config.h \ +net_common.c net_common.h \ +net_dedicated.c net_dedicated.h \ +net_io.c net_io.h \ +net_packet.c net_packet.h \ +net_sdl.c net_sdl.h \ +net_query.c net_query.h \ +net_server.c net_server.h \ +net_structrw.c net_structrw.h \ +z_native.c z_zone.h + +@PROGRAM_PREFIX@server_SOURCES=$(COMMON_SOURCE_FILES) $(DEDSERV_FILES) +@PROGRAM_PREFIX@server_LDADD = @LDFLAGS@ @SDLNET_LIBS@ + +# Source files used by the game binaries (chocolate-doom, etc.) + +GAME_BASE_FILES=\ +aes_prng.c aes_prng.h \ +d_event.c d_event.h \ + doomkeys.h \ + doomtype.h \ +d_iwad.c d_iwad.h \ +d_loop.c d_loop.h \ +d_mode.c d_mode.h \ + d_ticcmd.h \ +deh_str.c deh_str.h \ +gusconf.c gusconf.h \ +i_cdmus.c i_cdmus.h \ +i_endoom.c i_endoom.h \ +i_flmusic.c \ +i_glob.c i_glob.h \ +i_input.c i_input.h \ +i_joystick.c i_joystick.h \ + i_swap.h \ +i_musicpack.c \ +i_oplmusic.c \ +i_pcsound.c \ +i_sdlmusic.c \ +i_sdlsound.c \ +i_sound.c i_sound.h \ +i_timer.c i_timer.h \ +i_video.c i_video.h \ +i_videohr.c i_videohr.h \ +i_winmusic.c \ +midifallback.c midifallback.h \ +midifile.c midifile.h \ +mus2mid.c mus2mid.h \ +m_bbox.c m_bbox.h \ +m_cheat.c m_cheat.h \ +m_config.c m_config.h \ +m_controls.c m_controls.h \ +m_fixed.c m_fixed.h \ +net_client.c net_client.h \ +net_common.c net_common.h \ +net_dedicated.c net_dedicated.h \ +net_defs.h \ +net_gui.c net_gui.h \ +net_io.c net_io.h \ +net_loop.c net_loop.h \ +net_packet.c net_packet.h \ +net_petname.c net_petname.h \ +net_query.c net_query.h \ +net_sdl.c net_sdl.h \ +net_server.c net_server.h \ +net_structrw.c net_structrw.h \ +p_rejectpad.c p_rejectpad.h \ +sha1.c sha1.h \ +memio.c memio.h \ +tables.c tables.h \ +v_diskicon.c v_diskicon.h \ +v_video.c v_video.h \ + v_patch.h \ +w_checksum.c w_checksum.h \ +w_main.c w_main.h \ +w_wad.c w_wad.h \ +w_file.c w_file.h \ +w_file_stdc.c \ +w_file_posix.c \ +w_file_win32.c \ +w_merge.c w_merge.h \ +$(top_builddir)/win32/win_opendir.c \ +$(top_builddir)/win32/win_opendir.h + + +MEMORY_NATIVE_SOURCE_FILES=\ +z_native.c z_zone.h + +MEMORY_ZONE_SOURCE_FILES=\ +z_zone.c z_zone.h + +if HAVE_ZPOOL +GAME_SOURCE_FILES=$(GAME_BASE_FILES) $(MEMORY_ZONE_SOURCE_FILES) +else +GAME_SOURCE_FILES=$(GAME_BASE_FILES) $(MEMORY_NATIVE_SOURCE_FILES) +endif + +DEHACKED_SOURCE_FILES = \ +deh_defs.h \ +deh_io.c deh_io.h \ +deh_main.c deh_main.h \ +deh_mapping.c deh_mapping.h \ +deh_text.c + +# Some games support dehacked patches, some don't: + +SOURCE_FILES = $(COMMON_SOURCE_FILES) $(GAME_SOURCE_FILES) +SOURCE_FILES_WITH_DEH = $(SOURCE_FILES) $(DEHACKED_SOURCE_FILES) + +EXTRA_LIBS = \ + $(top_builddir)/textscreen/libtextscreen.a \ + $(top_builddir)/pcsound/libpcsound.a \ + $(top_builddir)/opl/libopl.a \ + @LDFLAGS@ \ + @EM_LDFLAGS@ \ + @SDL_LIBS@ \ + @SDLMIXER_LIBS@ \ + @SDLNET_LIBS@ + +if HAVE_WINDRES +@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) doom-res.rc +else +@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) +endif + +@PROGRAM_PREFIX@doom_LDADD = doom/libdoom.a $(EXTRA_LIBS) + +if HAVE_WINDRES +@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH) heretic-res.rc +else +@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH) +endif + +@PROGRAM_PREFIX@heretic_LDADD = heretic/libheretic.a $(EXTRA_LIBS) + +if HAVE_WINDRES +@PROGRAM_PREFIX@hexen_SOURCES=$(SOURCE_FILES) hexen-res.rc +else +@PROGRAM_PREFIX@hexen_SOURCES=$(SOURCE_FILES) +endif + +@PROGRAM_PREFIX@hexen_LDADD = hexen/libhexen.a $(EXTRA_LIBS) + +if HAVE_WINDRES +@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES_WITH_DEH) strife-res.rc +else +@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES_WITH_DEH) +endif + +@PROGRAM_PREFIX@strife_LDADD = strife/libstrife.a $(EXTRA_LIBS) + +$(SETUP_BINARIES): @PROGRAM_PREFIX@setup$(EXEEXT) + cp @PROGRAM_PREFIX@setup$(EXEEXT) $@ + +# Make "make" aware of convenience libraries in subdirectories + +doom/libdoom.a: + $(MAKE) -C doom + +heretic/libheretic.a: + $(MAKE) -C heretic + +hexen/libhexen.a: + $(MAKE) -C hexen + +strife/libstrife.a: + $(MAKE) -C strife + +# Source files needed for chocolate-setup: + +SETUP_FILES= \ +deh_str.c deh_str.h \ +d_mode.c d_mode.h \ +d_iwad.c d_iwad.h \ +i_timer.c i_timer.h \ +m_config.c m_config.h \ +m_controls.c m_controls.h \ +net_io.c net_io.h \ +net_packet.c net_packet.h \ +net_petname.c net_petname.h \ +net_sdl.c net_sdl.h \ +net_query.c net_query.h \ +net_structrw.c net_structrw.h \ +z_native.c z_zone.h + +if HAVE_WINDRES +@PROGRAM_PREFIX@setup_SOURCES=$(SETUP_FILES) $(COMMON_SOURCE_FILES) setup-res.rc +else +@PROGRAM_PREFIX@setup_SOURCES=$(SETUP_FILES) $(COMMON_SOURCE_FILES) +endif +@PROGRAM_PREFIX@setup_LDADD = setup/libsetup.a \ + $(top_builddir)/textscreen/libtextscreen.a \ + @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ @SDLNET_LIBS@ + +EXTRA_DIST = \ + CMakeLists.txt \ + Doom_Screensaver.desktop.in \ + manifest.xml + +metainfodir = $(prefix)/share/metainfo +metainfo_DATA = \ + @PACKAGE_RDNS@.Doom.metainfo.xml \ + @PACKAGE_RDNS@.Heretic.metainfo.xml \ + @PACKAGE_RDNS@.Hexen.metainfo.xml \ + @PACKAGE_RDNS@.Strife.metainfo.xml + +@PACKAGE_RDNS@.Doom.metainfo.xml : Doom.metainfo.xml + cp Doom.metainfo.xml $@ + +@PACKAGE_RDNS@.Heretic.metainfo.xml : Heretic.metainfo.xml + cp Heretic.metainfo.xml $@ + +@PACKAGE_RDNS@.Hexen.metainfo.xml : Hexen.metainfo.xml + cp Hexen.metainfo.xml $@ + +@PACKAGE_RDNS@.Strife.metainfo.xml : Strife.metainfo.xml + cp Strife.metainfo.xml $@ + +appdir = $(prefix)/share/applications +app_DATA = \ + @PACKAGE_RDNS@.Doom.desktop \ + @PACKAGE_RDNS@.Heretic.desktop \ + @PACKAGE_RDNS@.Hexen.desktop \ + @PACKAGE_RDNS@.Strife.desktop + +@PACKAGE_RDNS@.Doom.desktop : Doom.desktop + cp Doom.desktop $@ + +@PACKAGE_RDNS@.Heretic.desktop : Heretic.desktop + cp Heretic.desktop $@ + +@PACKAGE_RDNS@.Hexen.desktop : Hexen.desktop + cp Hexen.desktop $@ + +@PACKAGE_RDNS@.Strife.desktop : Strife.desktop + cp Strife.desktop $@ + +screensaverdir = $(prefix)/share/applications/screensavers +screensaver_DATA = @PACKAGE_RDNS@.Doom_Screensaver.desktop + +@PACKAGE_RDNS@.Doom_Screensaver.desktop: Doom_Screensaver.desktop + cp Doom_Screensaver.desktop $@ + +CLEANFILES = $(execgames_SCRIPTS) $(metainfo_DATA) $(app_DATA) $(screensaver_DATA) + +.rc.o: + $(WINDRES) $< -o $@ +%.o : %.rc + $(WINDRES) $< -o $@ + +midiread : midifile.c + $(CC) -DTEST $(CFLAGS) @LDFLAGS@ midifile.c -o $@ + +MUS2MID_SRC_FILES = mus2mid.c memio.c z_native.c i_system.c m_argv.c m_misc.c +mus2mid : $(MUS2MID_SRC_FILES) + $(CC) -DSTANDALONE -I$(top_builddir) $(CFLAGS) @LDFLAGS@ \ + $(MUS2MID_SRC_FILES) -o $@ + diff --git a/games/NXDoom/src/Strife.desktop.in b/games/NXDoom/src/Strife.desktop.in new file mode 100644 index 00000000000..862d20749c3 --- /dev/null +++ b/games/NXDoom/src/Strife.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=@PACKAGE_SHORTNAME@ Strife +Exec=@PROGRAM_PREFIX@strife +Icon=@PROGRAM_PREFIX@strife +Type=Application +Comment=@PACKAGE_SHORTDESC@ +Categories=Game;ActionGame; +Keywords=first;person;shooter;doom;vanilla; diff --git a/games/NXDoom/src/Strife.metainfo.xml.in b/games/NXDoom/src/Strife.metainfo.xml.in new file mode 100644 index 00000000000..4fdd16a708c --- /dev/null +++ b/games/NXDoom/src/Strife.metainfo.xml.in @@ -0,0 +1,48 @@ + + + + @PACKAGE_RDNS@.Strife + @PACKAGE_RDNS@.Strife.desktop + @PACKAGE_SHORTNAME@ Strife + @PACKAGE_SHORTDESC@ + CC0-1.0 + GPL-2.0+ + @PACKAGE_MAINTAINER@ + @PACKAGE_URL@ + @PACKAGE_BUGREPORT@ + +

+ @PACKAGE_SHORTNAME@ Strife is a conservative, + historically-accurate recreation of the Strife engine. It is + completely compatible with the original game and mods created + with the original engine in mind. Made with a great reverse + engineering effort, it has the goal of preserving the original + look, feel, limitations, and bugs of the original DOS + executable. +

+

+ Full support for single- and multi-player games is provided. + Unlike the original executable, network play is implemented on + the IP network stack, allowing it to function on modern LANs and + the Internet. +

+
+ + + https://www.chocolate-doom.org/wiki/images/b/b2/GNOME_Strife_Rowan.png + Talking to Rowan + + + https://www.chocolate-doom.org/wiki/images/1/1f/GNOME_Strife_Town.png + The Town + + + https://www.chocolate-doom.org/wiki/images/8/8a/GNOME_Strife_Opening.png + Opening Cinematic + + + https://www.chocolate-doom.org/wiki/images/c/c4/GNOME_Strife_Sewage.png + In the sewage + + +
diff --git a/games/NXDoom/src/aes_prng.c b/games/NXDoom/src/aes_prng.c new file mode 100644 index 00000000000..aad0a38a1be --- /dev/null +++ b/games/NXDoom/src/aes_prng.c @@ -0,0 +1,956 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// This implements a cryptographically secure pseudorandom number +// generator for implementing secure demos. The approach taken is to +// use the AES (Rijndael) stream cipher in "counter" mode, encrypting +// an incrementing counter. The cipher key acts as the random seed. +// Cryptanalysis of AES used in this way has shown it to be an +// effective PRNG (see: Empirical Evidence concerning AES, Hellekalek +// & Wegenkittl, 2003). +// +// AES implementation is taken from the Linux kernel's AES +// implementation, found in crypto/aes_generic.c. It has been hacked +// up to work independently. +// + +#include + +#include "aes_prng.h" +#include "doomtype.h" +#include "i_swap.h" + +/* + * Cryptographic API. + * + * AES Cipher Algorithm. + * + * Based on Brian Gladman's code. + * + * Linux developers: + * Alexander Kjeldaas + * Herbert Valerio Riedel + * Kyle McMartin + * Adam J. Richter (conversion to 2.5 API). + * + * 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. + * + * --------------------------------------------------------------------------- + * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * --------------------------------------------------------------------------- + */ + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEYLENGTH (15 * 16) +#define AES_MAX_KEYLENGTH_U32 (AES_MAX_KEYLENGTH / sizeof(uint32_t)) + +/* + * Please ensure that the first two fields are 16-byte aligned + * relative to the start of the structure, i.e., don't move them! + */ +typedef struct +{ + uint32_t key_enc[AES_MAX_KEYLENGTH_U32]; + uint32_t key_dec[AES_MAX_KEYLENGTH_U32]; + uint32_t key_length; +} aes_context_t; + +static inline uint8_t get_byte(const uint32_t x, const unsigned n) +{ + return x >> (n << 3); +} + +static const uint32_t rco_tab[10] = { 1, 2, 4, 8, 16, 32, 64, 128, 27, 54 }; + +static const uint32_t crypto_ft_tab[4][256] = { + { + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, + 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, + 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, + 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, + 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, + 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, + 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, + 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, + 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, + 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, + 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, + 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, + 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, + 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, + 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, + 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, + 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, + 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, + 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, + 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, + 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, + 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, + 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, + 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, + 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, + 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, + 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, + 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, + 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, + 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, + 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, + 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, + 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, + 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, + }, { + 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, + 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, + 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, + 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, + 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, + 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, + 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, + 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, + 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, + 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, + 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, + 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, + 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, + 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, + 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, + 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, + 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, + 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, + 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, + 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, + 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, + 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, + 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, + 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, + 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, + 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, + 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81, + 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, + 0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, + 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, + 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, + 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, + 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, + 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, + 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, + 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, + 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, + 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83, + 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, + 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, + 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, + 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, + 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, + 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, + 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, + 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, + 0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, + 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, + 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, + 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, + 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, + 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, + 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, + 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12, + 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, + 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, + 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, + 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, + 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, + 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, + 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, + 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, + 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, + 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a, + }, { + 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, + 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, + 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, + 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, + 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, + 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, + 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, + 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, + 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, + 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, + 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, + 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, + 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, + 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, + 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, + 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, + 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, + 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, + 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, + 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, + 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, + 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, + 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, + 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, + 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, + 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, + 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f, + 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, + 0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, + 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, + 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, + 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, + 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, + 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, + 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, + 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, + 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, + 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388, + 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, + 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, + 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, + 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, + 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, + 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, + 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, + 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, + 0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, + 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, + 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, + 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, + 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, + 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, + 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, + 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e, + 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, + 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, + 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, + 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, + 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, + 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, + 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, + 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, + 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f, + 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16, + }, { + 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, + 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, + 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, + 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, + 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, + 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, + 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, + 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, + 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, + 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, + 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, + 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, + 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, + 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, + 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, + 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, + 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, + 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, + 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, + 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, + 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, + 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, + 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, + 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, + 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, + 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, + 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f, + 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, + 0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f, + 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, + 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, + 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, + 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, + 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, + 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, + 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, + 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, + 0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888, + 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, + 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, + 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, + 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, + 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, + 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, + 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, + 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, + 0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, + 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, + 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, + 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, + 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, + 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, + 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, + 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e, + 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, + 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, + 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, + 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, + 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, + 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, + 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, + 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, + 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, + 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616, + } +}; + +static const uint32_t crypto_fl_tab[4][256] = { + { + 0x00000063, 0x0000007c, 0x00000077, 0x0000007b, + 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5, + 0x00000030, 0x00000001, 0x00000067, 0x0000002b, + 0x000000fe, 0x000000d7, 0x000000ab, 0x00000076, + 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d, + 0x000000fa, 0x00000059, 0x00000047, 0x000000f0, + 0x000000ad, 0x000000d4, 0x000000a2, 0x000000af, + 0x0000009c, 0x000000a4, 0x00000072, 0x000000c0, + 0x000000b7, 0x000000fd, 0x00000093, 0x00000026, + 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc, + 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1, + 0x00000071, 0x000000d8, 0x00000031, 0x00000015, + 0x00000004, 0x000000c7, 0x00000023, 0x000000c3, + 0x00000018, 0x00000096, 0x00000005, 0x0000009a, + 0x00000007, 0x00000012, 0x00000080, 0x000000e2, + 0x000000eb, 0x00000027, 0x000000b2, 0x00000075, + 0x00000009, 0x00000083, 0x0000002c, 0x0000001a, + 0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0, + 0x00000052, 0x0000003b, 0x000000d6, 0x000000b3, + 0x00000029, 0x000000e3, 0x0000002f, 0x00000084, + 0x00000053, 0x000000d1, 0x00000000, 0x000000ed, + 0x00000020, 0x000000fc, 0x000000b1, 0x0000005b, + 0x0000006a, 0x000000cb, 0x000000be, 0x00000039, + 0x0000004a, 0x0000004c, 0x00000058, 0x000000cf, + 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb, + 0x00000043, 0x0000004d, 0x00000033, 0x00000085, + 0x00000045, 0x000000f9, 0x00000002, 0x0000007f, + 0x00000050, 0x0000003c, 0x0000009f, 0x000000a8, + 0x00000051, 0x000000a3, 0x00000040, 0x0000008f, + 0x00000092, 0x0000009d, 0x00000038, 0x000000f5, + 0x000000bc, 0x000000b6, 0x000000da, 0x00000021, + 0x00000010, 0x000000ff, 0x000000f3, 0x000000d2, + 0x000000cd, 0x0000000c, 0x00000013, 0x000000ec, + 0x0000005f, 0x00000097, 0x00000044, 0x00000017, + 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d, + 0x00000064, 0x0000005d, 0x00000019, 0x00000073, + 0x00000060, 0x00000081, 0x0000004f, 0x000000dc, + 0x00000022, 0x0000002a, 0x00000090, 0x00000088, + 0x00000046, 0x000000ee, 0x000000b8, 0x00000014, + 0x000000de, 0x0000005e, 0x0000000b, 0x000000db, + 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a, + 0x00000049, 0x00000006, 0x00000024, 0x0000005c, + 0x000000c2, 0x000000d3, 0x000000ac, 0x00000062, + 0x00000091, 0x00000095, 0x000000e4, 0x00000079, + 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d, + 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9, + 0x0000006c, 0x00000056, 0x000000f4, 0x000000ea, + 0x00000065, 0x0000007a, 0x000000ae, 0x00000008, + 0x000000ba, 0x00000078, 0x00000025, 0x0000002e, + 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6, + 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f, + 0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a, + 0x00000070, 0x0000003e, 0x000000b5, 0x00000066, + 0x00000048, 0x00000003, 0x000000f6, 0x0000000e, + 0x00000061, 0x00000035, 0x00000057, 0x000000b9, + 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e, + 0x000000e1, 0x000000f8, 0x00000098, 0x00000011, + 0x00000069, 0x000000d9, 0x0000008e, 0x00000094, + 0x0000009b, 0x0000001e, 0x00000087, 0x000000e9, + 0x000000ce, 0x00000055, 0x00000028, 0x000000df, + 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d, + 0x000000bf, 0x000000e6, 0x00000042, 0x00000068, + 0x00000041, 0x00000099, 0x0000002d, 0x0000000f, + 0x000000b0, 0x00000054, 0x000000bb, 0x00000016, + }, { + 0x00006300, 0x00007c00, 0x00007700, 0x00007b00, + 0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500, + 0x00003000, 0x00000100, 0x00006700, 0x00002b00, + 0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600, + 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00, + 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000, + 0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00, + 0x00009c00, 0x0000a400, 0x00007200, 0x0000c000, + 0x0000b700, 0x0000fd00, 0x00009300, 0x00002600, + 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00, + 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100, + 0x00007100, 0x0000d800, 0x00003100, 0x00001500, + 0x00000400, 0x0000c700, 0x00002300, 0x0000c300, + 0x00001800, 0x00009600, 0x00000500, 0x00009a00, + 0x00000700, 0x00001200, 0x00008000, 0x0000e200, + 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500, + 0x00000900, 0x00008300, 0x00002c00, 0x00001a00, + 0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000, + 0x00005200, 0x00003b00, 0x0000d600, 0x0000b300, + 0x00002900, 0x0000e300, 0x00002f00, 0x00008400, + 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00, + 0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00, + 0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900, + 0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00, + 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00, + 0x00004300, 0x00004d00, 0x00003300, 0x00008500, + 0x00004500, 0x0000f900, 0x00000200, 0x00007f00, + 0x00005000, 0x00003c00, 0x00009f00, 0x0000a800, + 0x00005100, 0x0000a300, 0x00004000, 0x00008f00, + 0x00009200, 0x00009d00, 0x00003800, 0x0000f500, + 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100, + 0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200, + 0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00, + 0x00005f00, 0x00009700, 0x00004400, 0x00001700, + 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00, + 0x00006400, 0x00005d00, 0x00001900, 0x00007300, + 0x00006000, 0x00008100, 0x00004f00, 0x0000dc00, + 0x00002200, 0x00002a00, 0x00009000, 0x00008800, + 0x00004600, 0x0000ee00, 0x0000b800, 0x00001400, + 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00, + 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00, + 0x00004900, 0x00000600, 0x00002400, 0x00005c00, + 0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200, + 0x00009100, 0x00009500, 0x0000e400, 0x00007900, + 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00, + 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900, + 0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00, + 0x00006500, 0x00007a00, 0x0000ae00, 0x00000800, + 0x0000ba00, 0x00007800, 0x00002500, 0x00002e00, + 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600, + 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00, + 0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00, + 0x00007000, 0x00003e00, 0x0000b500, 0x00006600, + 0x00004800, 0x00000300, 0x0000f600, 0x00000e00, + 0x00006100, 0x00003500, 0x00005700, 0x0000b900, + 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00, + 0x0000e100, 0x0000f800, 0x00009800, 0x00001100, + 0x00006900, 0x0000d900, 0x00008e00, 0x00009400, + 0x00009b00, 0x00001e00, 0x00008700, 0x0000e900, + 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00, + 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00, + 0x0000bf00, 0x0000e600, 0x00004200, 0x00006800, + 0x00004100, 0x00009900, 0x00002d00, 0x00000f00, + 0x0000b000, 0x00005400, 0x0000bb00, 0x00001600, + }, { + 0x00630000, 0x007c0000, 0x00770000, 0x007b0000, + 0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000, + 0x00300000, 0x00010000, 0x00670000, 0x002b0000, + 0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000, + 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000, + 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000, + 0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000, + 0x009c0000, 0x00a40000, 0x00720000, 0x00c00000, + 0x00b70000, 0x00fd0000, 0x00930000, 0x00260000, + 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000, + 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000, + 0x00710000, 0x00d80000, 0x00310000, 0x00150000, + 0x00040000, 0x00c70000, 0x00230000, 0x00c30000, + 0x00180000, 0x00960000, 0x00050000, 0x009a0000, + 0x00070000, 0x00120000, 0x00800000, 0x00e20000, + 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000, + 0x00090000, 0x00830000, 0x002c0000, 0x001a0000, + 0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000, + 0x00520000, 0x003b0000, 0x00d60000, 0x00b30000, + 0x00290000, 0x00e30000, 0x002f0000, 0x00840000, + 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000, + 0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000, + 0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000, + 0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000, + 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000, + 0x00430000, 0x004d0000, 0x00330000, 0x00850000, + 0x00450000, 0x00f90000, 0x00020000, 0x007f0000, + 0x00500000, 0x003c0000, 0x009f0000, 0x00a80000, + 0x00510000, 0x00a30000, 0x00400000, 0x008f0000, + 0x00920000, 0x009d0000, 0x00380000, 0x00f50000, + 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000, + 0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000, + 0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000, + 0x005f0000, 0x00970000, 0x00440000, 0x00170000, + 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000, + 0x00640000, 0x005d0000, 0x00190000, 0x00730000, + 0x00600000, 0x00810000, 0x004f0000, 0x00dc0000, + 0x00220000, 0x002a0000, 0x00900000, 0x00880000, + 0x00460000, 0x00ee0000, 0x00b80000, 0x00140000, + 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000, + 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000, + 0x00490000, 0x00060000, 0x00240000, 0x005c0000, + 0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000, + 0x00910000, 0x00950000, 0x00e40000, 0x00790000, + 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000, + 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000, + 0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000, + 0x00650000, 0x007a0000, 0x00ae0000, 0x00080000, + 0x00ba0000, 0x00780000, 0x00250000, 0x002e0000, + 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000, + 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000, + 0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000, + 0x00700000, 0x003e0000, 0x00b50000, 0x00660000, + 0x00480000, 0x00030000, 0x00f60000, 0x000e0000, + 0x00610000, 0x00350000, 0x00570000, 0x00b90000, + 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000, + 0x00e10000, 0x00f80000, 0x00980000, 0x00110000, + 0x00690000, 0x00d90000, 0x008e0000, 0x00940000, + 0x009b0000, 0x001e0000, 0x00870000, 0x00e90000, + 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000, + 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000, + 0x00bf0000, 0x00e60000, 0x00420000, 0x00680000, + 0x00410000, 0x00990000, 0x002d0000, 0x000f0000, + 0x00b00000, 0x00540000, 0x00bb0000, 0x00160000, + }, { + 0x63000000, 0x7c000000, 0x77000000, 0x7b000000, + 0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000, + 0x30000000, 0x01000000, 0x67000000, 0x2b000000, + 0xfe000000, 0xd7000000, 0xab000000, 0x76000000, + 0xca000000, 0x82000000, 0xc9000000, 0x7d000000, + 0xfa000000, 0x59000000, 0x47000000, 0xf0000000, + 0xad000000, 0xd4000000, 0xa2000000, 0xaf000000, + 0x9c000000, 0xa4000000, 0x72000000, 0xc0000000, + 0xb7000000, 0xfd000000, 0x93000000, 0x26000000, + 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000, + 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000, + 0x71000000, 0xd8000000, 0x31000000, 0x15000000, + 0x04000000, 0xc7000000, 0x23000000, 0xc3000000, + 0x18000000, 0x96000000, 0x05000000, 0x9a000000, + 0x07000000, 0x12000000, 0x80000000, 0xe2000000, + 0xeb000000, 0x27000000, 0xb2000000, 0x75000000, + 0x09000000, 0x83000000, 0x2c000000, 0x1a000000, + 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000, + 0x52000000, 0x3b000000, 0xd6000000, 0xb3000000, + 0x29000000, 0xe3000000, 0x2f000000, 0x84000000, + 0x53000000, 0xd1000000, 0x00000000, 0xed000000, + 0x20000000, 0xfc000000, 0xb1000000, 0x5b000000, + 0x6a000000, 0xcb000000, 0xbe000000, 0x39000000, + 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000, + 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000, + 0x43000000, 0x4d000000, 0x33000000, 0x85000000, + 0x45000000, 0xf9000000, 0x02000000, 0x7f000000, + 0x50000000, 0x3c000000, 0x9f000000, 0xa8000000, + 0x51000000, 0xa3000000, 0x40000000, 0x8f000000, + 0x92000000, 0x9d000000, 0x38000000, 0xf5000000, + 0xbc000000, 0xb6000000, 0xda000000, 0x21000000, + 0x10000000, 0xff000000, 0xf3000000, 0xd2000000, + 0xcd000000, 0x0c000000, 0x13000000, 0xec000000, + 0x5f000000, 0x97000000, 0x44000000, 0x17000000, + 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000, + 0x64000000, 0x5d000000, 0x19000000, 0x73000000, + 0x60000000, 0x81000000, 0x4f000000, 0xdc000000, + 0x22000000, 0x2a000000, 0x90000000, 0x88000000, + 0x46000000, 0xee000000, 0xb8000000, 0x14000000, + 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000, + 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000, + 0x49000000, 0x06000000, 0x24000000, 0x5c000000, + 0xc2000000, 0xd3000000, 0xac000000, 0x62000000, + 0x91000000, 0x95000000, 0xe4000000, 0x79000000, + 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000, + 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000, + 0x6c000000, 0x56000000, 0xf4000000, 0xea000000, + 0x65000000, 0x7a000000, 0xae000000, 0x08000000, + 0xba000000, 0x78000000, 0x25000000, 0x2e000000, + 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000, + 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000, + 0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000, + 0x70000000, 0x3e000000, 0xb5000000, 0x66000000, + 0x48000000, 0x03000000, 0xf6000000, 0x0e000000, + 0x61000000, 0x35000000, 0x57000000, 0xb9000000, + 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000, + 0xe1000000, 0xf8000000, 0x98000000, 0x11000000, + 0x69000000, 0xd9000000, 0x8e000000, 0x94000000, + 0x9b000000, 0x1e000000, 0x87000000, 0xe9000000, + 0xce000000, 0x55000000, 0x28000000, 0xdf000000, + 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000, + 0xbf000000, 0xe6000000, 0x42000000, 0x68000000, + 0x41000000, 0x99000000, 0x2d000000, 0x0f000000, + 0xb0000000, 0x54000000, 0xbb000000, 0x16000000, + } +}; + +/* initialise the key schedule from the user supplied key */ + +static uint32_t aes_ror32(uint32_t word, unsigned int shift) +{ + return (word >> shift) | (word << (32 - shift)); +} + +#define cpu_to_le32(x) SDL_SwapLE32(x) +#define le32_to_cpu(x) SDL_SwapLE32(x) + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y, x) do { \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= aes_ror32(u ^ t, 8) ^ \ + aes_ror32(v ^ t, 16) ^ \ + aes_ror32(t, 24); \ +} while (0) + +#define ls_box(x) \ + crypto_fl_tab[0][get_byte(x, 0)] ^ \ + crypto_fl_tab[1][get_byte(x, 1)] ^ \ + crypto_fl_tab[2][get_byte(x, 2)] ^ \ + crypto_fl_tab[3][get_byte(x, 3)] + +#define loop4(i) do { \ + t = aes_ror32(t, 8); \ + t = ls_box(t) ^ rco_tab[i]; \ + t ^= ctx->key_enc[4 * i]; \ + ctx->key_enc[4 * i + 4] = t; \ + t ^= ctx->key_enc[4 * i + 1]; \ + ctx->key_enc[4 * i + 5] = t; \ + t ^= ctx->key_enc[4 * i + 2]; \ + ctx->key_enc[4 * i + 6] = t; \ + t ^= ctx->key_enc[4 * i + 3]; \ + ctx->key_enc[4 * i + 7] = t; \ +} while (0) + +#define loop6(i) do { \ + t = aes_ror32(t, 8); \ + t = ls_box(t) ^ rco_tab[i]; \ + t ^= ctx->key_enc[6 * i]; \ + ctx->key_enc[6 * i + 6] = t; \ + t ^= ctx->key_enc[6 * i + 1]; \ + ctx->key_enc[6 * i + 7] = t; \ + t ^= ctx->key_enc[6 * i + 2]; \ + ctx->key_enc[6 * i + 8] = t; \ + t ^= ctx->key_enc[6 * i + 3]; \ + ctx->key_enc[6 * i + 9] = t; \ + t ^= ctx->key_enc[6 * i + 4]; \ + ctx->key_enc[6 * i + 10] = t; \ + t ^= ctx->key_enc[6 * i + 5]; \ + ctx->key_enc[6 * i + 11] = t; \ +} while (0) + +#define loop8tophalf(i) do { \ + t = aes_ror32(t, 8); \ + t = ls_box(t) ^ rco_tab[i]; \ + t ^= ctx->key_enc[8 * i]; \ + ctx->key_enc[8 * i + 8] = t; \ + t ^= ctx->key_enc[8 * i + 1]; \ + ctx->key_enc[8 * i + 9] = t; \ + t ^= ctx->key_enc[8 * i + 2]; \ + ctx->key_enc[8 * i + 10] = t; \ + t ^= ctx->key_enc[8 * i + 3]; \ + ctx->key_enc[8 * i + 11] = t; \ +} while (0) + +#define loop8(i) do { \ + loop8tophalf(i); \ + t = ctx->key_enc[8 * i + 4] ^ ls_box(t); \ + ctx->key_enc[8 * i + 12] = t; \ + t ^= ctx->key_enc[8 * i + 5]; \ + ctx->key_enc[8 * i + 13] = t; \ + t ^= ctx->key_enc[8 * i + 6]; \ + ctx->key_enc[8 * i + 14] = t; \ + t ^= ctx->key_enc[8 * i + 7]; \ + ctx->key_enc[8 * i + 15] = t; \ +} while (0) + +/** + * AES_ExpandKey - Expands the AES key as described in FIPS-197 + * @ctx: The location where the computed key will be stored. + * @in_key: The supplied key. + * @key_len: The length of the supplied key. + * + * Returns 0 on success. The function fails only if an invalid key size (or + * pointer) is supplied. + * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes + * key schedule plus a 16 bytes key which is used before the first round). + * The decryption key is prepared for the "Equivalent Inverse Cipher" as + * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is + * for the initial combination, the second slot for the first round and so on. + */ +static int AES_ExpandKey(aes_context_t *ctx, const uint8_t *in_key, + unsigned int key_len) +{ + const uint32_t *key = (const uint32_t *)in_key; + uint32_t i, t, u, v, w, j; + + if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 && + key_len != AES_KEYSIZE_256) + return -1; + + ctx->key_length = key_len; + + ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]); + ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]); + ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]); + ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]); + + switch (key_len) { + case AES_KEYSIZE_128: + t = ctx->key_enc[3]; + for (i = 0; i < 10; ++i) + loop4(i); + break; + + case AES_KEYSIZE_192: + ctx->key_enc[4] = le32_to_cpu(key[4]); + t = ctx->key_enc[5] = le32_to_cpu(key[5]); + for (i = 0; i < 8; ++i) + loop6(i); + break; + + case AES_KEYSIZE_256: + ctx->key_enc[4] = le32_to_cpu(key[4]); + ctx->key_enc[5] = le32_to_cpu(key[5]); + ctx->key_enc[6] = le32_to_cpu(key[6]); + t = ctx->key_enc[7] = le32_to_cpu(key[7]); + for (i = 0; i < 6; ++i) + loop8(i); + loop8tophalf(i); + break; + } + + ctx->key_dec[0] = ctx->key_enc[key_len + 24]; + ctx->key_dec[1] = ctx->key_enc[key_len + 25]; + ctx->key_dec[2] = ctx->key_enc[key_len + 26]; + ctx->key_dec[3] = ctx->key_enc[key_len + 27]; + + for (i = 4; i < key_len + 24; ++i) { + j = key_len + 24 - (i & ~3) + (i & 3); + imix_col(ctx->key_dec[j], ctx->key_enc[i]); + } + return 0; +} + +/** + * AES_SetKey - Set the AES key. + * @ctx: AES context struct. + * @in_key: The input key. + * @key_len: The size of the key. + * + * Returns 0 on success, on failure -1 is returned. + * The function uses AES_ExpandKey() to expand the key. + */ +static int AES_SetKey(aes_context_t *ctx, const uint8_t *in_key, + unsigned int key_len) +{ + int ret; + + ret = AES_ExpandKey(ctx, in_key, key_len); + if (!ret) + return 0; + + return -1; +} + +/* encrypt a block of text */ + +#define f_rn(bo, bi, n, k) do { \ + bo[n] = crypto_ft_tab[0][get_byte(bi[n], 0)] ^ \ + crypto_ft_tab[1][get_byte(bi[(n + 1) & 3], 1)] ^ \ + crypto_ft_tab[2][get_byte(bi[(n + 2) & 3], 2)] ^ \ + crypto_ft_tab[3][get_byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ +} while (0) + +#define f_nround(bo, bi, k) do {\ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4; \ +} while (0) + +#define f_rl(bo, bi, n, k) do { \ + bo[n] = crypto_fl_tab[0][get_byte(bi[n], 0)] ^ \ + crypto_fl_tab[1][get_byte(bi[(n + 1) & 3], 1)] ^ \ + crypto_fl_tab[2][get_byte(bi[(n + 2) & 3], 2)] ^ \ + crypto_fl_tab[3][get_byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ +} while (0) + +#define f_lround(bo, bi, k) do {\ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, k); \ + f_rl(bo, bi, 2, k); \ + f_rl(bo, bi, 3, k); \ +} while (0) + +static void AES_Encrypt(aes_context_t *ctx, uint8_t *out, + const uint8_t *in) +{ + const uint32_t *src = (const uint32_t *)in; + uint32_t *dst = (uint32_t *)out; + uint32_t b0[4], b1[4]; + const uint32_t *kp = ctx->key_enc + 4; + const int key_len = ctx->key_length; + + b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0]; + b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1]; + b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2]; + b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3]; + + if (key_len > 24) { + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + } + + if (key_len > 16) { + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + } + + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_lround(b0, b1, kp); + + dst[0] = cpu_to_le32(b0[0]); + dst[1] = cpu_to_le32(b0[1]); + dst[2] = cpu_to_le32(b0[2]); + dst[3] = cpu_to_le32(b0[3]); +} + +static boolean prng_enabled = false; +static aes_context_t prng_context; +static uint32_t prng_input_counter; +static uint32_t prng_values[4]; +static unsigned int prng_value_index = 0; + +// Initialize Pseudo-RNG using the specified 128-bit key. + +void PRNG_Start(prng_seed_t key) +{ + AES_SetKey(&prng_context, key, sizeof(prng_seed_t)); + prng_value_index = 4; + prng_input_counter = 0; + prng_enabled = true; +} + +void PRNG_Stop(void) +{ + prng_enabled = false; +} + +// Generate a set of new PRNG values by encrypting a new block. + +static void PRNG_Generate(void) +{ + byte input[16], output[16]; + unsigned int i; + + // Input for the cipher is a consecutively increasing 32-bit counter. + + for (i = 0; i < 4; ++i) + { + input[4*i] = prng_input_counter & 0xff; + input[4*i + 1] = (prng_input_counter >> 8) & 0xff; + input[4*i + 2] = (prng_input_counter >> 16) & 0xff; + input[4*i + 3] = (prng_input_counter >> 24) & 0xff; + ++prng_input_counter; + } + + AES_Encrypt(&prng_context, output, input); + + for (i = 0; i < 4; ++i) + { + prng_values[i] = output[4*i] + | (output[4*i + 1] << 8) + | (output[4*i + 2] << 16) + | (output[4*i + 3] << 24); + } + + prng_value_index = 0; +} + +// Read a random 32-bit integer from the PRNG. + +unsigned int PRNG_Random(void) +{ + unsigned int result; + + if (!prng_enabled) + { + return 0; + } + + if (prng_value_index >= 4) + { + PRNG_Generate(); + } + + result = prng_values[prng_value_index]; + ++prng_value_index; + + return result; +} + diff --git a/games/NXDoom/src/aes_prng.h b/games/NXDoom/src/aes_prng.h new file mode 100644 index 00000000000..f255db17561 --- /dev/null +++ b/games/NXDoom/src/aes_prng.h @@ -0,0 +1,32 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Pseudo-random number generator for secure demos. +// + +#ifndef __AES_PRNG_H__ +#define __AES_PRNG_H__ + +#include "doomtype.h" + +// Nonce value used as random seed for secure demos. + +typedef byte prng_seed_t[16]; + +void PRNG_Start(prng_seed_t seed); +void PRNG_Stop(void); +unsigned int PRNG_Random(void); + +#endif /* #ifndef __AES_PRNG_H__ */ + diff --git a/games/NXDoom/src/d_dedicated.c b/games/NXDoom/src/d_dedicated.c new file mode 100644 index 00000000000..72220049965 --- /dev/null +++ b/games/NXDoom/src/d_dedicated.c @@ -0,0 +1,47 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Code specific to the standalone dedicated server. +// + +#include +#include +#include + +#include "config.h" + +#include "m_argv.h" +#include "net_defs.h" + +#include "net_dedicated.h" +#include "net_server.h" +#include "z_zone.h" + +void NET_CL_Run(void) +{ + // No client present :-) + // + // This is here because the server code sometimes runs this + // to let the client do some processing if it needs to. + // In a standalone dedicated server, we don't have a client. +} + +void D_DoomMain(void) +{ + printf(PACKAGE_NAME " standalone dedicated server\n"); + + Z_Init(); + + NET_DedicatedServer(); +} + diff --git a/games/NXDoom/src/d_event.c b/games/NXDoom/src/d_event.c new file mode 100644 index 00000000000..3eef57282a8 --- /dev/null +++ b/games/NXDoom/src/d_event.c @@ -0,0 +1,63 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: Event handling. +// +// Events are asynchronous inputs generally generated by the game user. +// Events can be discarded if no responder claims them +// + +#include +#include "d_event.h" + +#define MAXEVENTS 64 + +static event_t events[MAXEVENTS]; +static int eventhead; +static int eventtail; + +// +// D_PostEvent +// Called by the I/O functions when input is detected +// +void D_PostEvent (event_t* ev) +{ + events[eventhead] = *ev; + eventhead = (eventhead + 1) % MAXEVENTS; +} + +// Read an event from the queue. + +event_t *D_PopEvent(void) +{ + event_t *result; + + // No more events waiting. + + if (eventtail == eventhead) + { + return NULL; + } + + result = &events[eventtail]; + + // Advance to the next event in the queue. + + eventtail = (eventtail + 1) % MAXEVENTS; + + return result; +} + + diff --git a/games/NXDoom/src/d_event.h b/games/NXDoom/src/d_event.h new file mode 100644 index 00000000000..bc1050aeb9d --- /dev/null +++ b/games/NXDoom/src/d_event.h @@ -0,0 +1,147 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __D_EVENT__ +#define __D_EVENT__ + + +#include "doomtype.h" + + +// +// Event handling. +// + +// Input event types. +typedef enum +{ + // Key press/release events. + // data1: Key code (from doomkeys.h) of the key that was + // pressed or released. This is the key as it appears + // on a US keyboard layout, and does not change with + // layout. + // For ev_keydown only: + // data2: ASCII representation of the key that was pressed that + // changes with the keyboard layout; eg. if 'Z' is + // pressed on a German keyboard, data1='y',data2='z'. + // Not affected by modifier keys. + // data3: ASCII input, fully modified according to keyboard + // layout and any modifier keys that are held down. + // Only set if I_StartTextInput() has been called. + ev_keydown, + ev_keyup, + + // Mouse movement event. + // data1: Bitfield of buttons currently held down. + // (bit 0 = left; bit 1 = right; bit 2 = middle). + // data2: X axis mouse movement (turn). + // data3: Y axis mouse movement (forward/backward). + ev_mouse, + + // Joystick state. + // data1: Bitfield of buttons currently pressed. + // data2: X axis mouse movement (turn). + // data3: Y axis mouse movement (forward/backward). + // data4: Third axis mouse movement (strafe). + // data5: Fourth axis mouse movement (look) + // data6: Dpad and analog stick direction. + ev_joystick, + + // Quit event. Triggered when the user clicks the "close" button + // to terminate the application. + ev_quit +} evtype_t; + +// Event structure. +typedef struct +{ + evtype_t type; + + // Event-specific data; see the descriptions given above. + int data1, data2, data3, data4, data5, data6; +} event_t; + + +// +// Button/action code definitions. +// +typedef enum +{ + // Press "Fire". + BT_ATTACK = 1, + // Use button, to open doors, activate switches. + BT_USE = 2, + + // Flag: game events, not really buttons. + BT_SPECIAL = 128, + BT_SPECIALMASK = 3, + + // Flag, weapon change pending. + // If true, the next 3 bits hold weapon num. + BT_CHANGE = 4, + // The 3bit weapon mask and shift, convenience. + BT_WEAPONMASK = (8+16+32), + BT_WEAPONSHIFT = 3, + + // Pause the game. + BTS_PAUSE = 1, + // Save the game at each console. + BTS_SAVEGAME = 2, + + // Savegame slot numbers + // occupy the second byte of buttons. + BTS_SAVEMASK = (4+8+16), + BTS_SAVESHIFT = 2, + +} buttoncode_t; + +// villsa [STRIFE] Strife specific buttons +// TODO - not finished +typedef enum +{ + // Player view look up + BT2_LOOKUP = 1, + // Player view look down + BT2_LOOKDOWN = 2, + // Center player's view + BT2_CENTERVIEW = 4, + // Use inventory item + BT2_INVUSE = 8, + // Drop inventory item + BT2_INVDROP = 16, + // Jump up and down + BT2_JUMP = 32, + // Use medkit + BT2_HEALTH = 128, + +} buttoncode2_t; + + + + +// Called by IO functions when input is detected. +void D_PostEvent (event_t *ev); + +// Read an event from the event queue + +event_t *D_PopEvent(void); + + +#endif + diff --git a/games/NXDoom/src/d_iwad.c b/games/NXDoom/src/d_iwad.c new file mode 100644 index 00000000000..e05b75f0fc3 --- /dev/null +++ b/games/NXDoom/src/d_iwad.c @@ -0,0 +1,1047 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Search for and locate an IWAD file, and initialize according +// to the IWAD type. +// + +#include +#include +#include +#include + +#include "deh_str.h" +#include "doomkeys.h" +#include "d_iwad.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" +#include "w_wad.h" +#include "z_zone.h" + +static const iwad_t iwads[] = +{ + { "doom2.wad", doom2, commercial, "Doom II" }, + { "plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment" }, + { "tnt.wad", pack_tnt, commercial, "Final Doom: TNT: Evilution" }, + { "doom.wad", doom, retail, "Doom" }, + { "doom1.wad", doom, shareware, "Doom Shareware" }, + { "doom2f.wad", doom2, commercial, "Doom II: L'Enfer sur Terre" }, + { "chex.wad", pack_chex, retail, "Chex Quest" }, + { "hacx.wad", pack_hacx, commercial, "Hacx" }, + { "freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" }, + { "freedoom1.wad", doom, retail, "Freedoom: Phase 1" }, + { "freedm.wad", doom2, commercial, "FreeDM" }, + { "heretic.wad", heretic, retail, "Heretic" }, + { "heretic1.wad", heretic, shareware, "Heretic Shareware" }, + { "hexen.wad", hexen, commercial, "Hexen" }, + //{ "strife0.wad", strife, commercial, "Strife" }, // haleyjd: STRIFE-FIXME + { "strife1.wad", strife, commercial, "Strife" }, +}; + +boolean D_IsIWADName(const char *name) +{ + int i; + + for (i = 0; i < arrlen(iwads); i++) + { + if (!strcasecmp(name, iwads[i].name)) + { + return true; + } + } + + return false; +} + +// Array of locations to search for IWAD files +// +// "128 IWAD search directories should be enough for anybody". + +#define MAX_IWAD_DIRS 128 + +static boolean iwad_dirs_built = false; +static const char *iwad_dirs[MAX_IWAD_DIRS]; +static int num_iwad_dirs = 0; + +static void AddIWADDir(const char *dir) +{ + if (num_iwad_dirs < MAX_IWAD_DIRS) + { + iwad_dirs[num_iwad_dirs] = dir; + ++num_iwad_dirs; + } +} + +// This is Windows-specific code that automatically finds the location +// of installed IWAD files. The registry is inspected to find special +// keys installed by the Windows installers for various CD versions +// of Doom. From these keys we can deduce where to find an IWAD. + +#if defined(_WIN32) && !defined(_WIN32_WCE) + +#define WIN32_LEAN_AND_MEAN +#include + +typedef struct +{ + HKEY root; + char *path; + char *value; +} registry_value_t; + +#define UNINSTALLER_STRING "\\uninstl.exe /S " + +// Keys installed by the various CD editions. These are actually the +// commands to invoke the uninstaller and look like this: +// +// C:\Program Files\Path\uninstl.exe /S C:\Program Files\Path +// +// With some munging we can find where Doom was installed. + +// [AlexMax] From the persepctive of a 64-bit executable, 32-bit registry +// keys are located in a different spot. +#if _WIN64 +#define SOFTWARE_KEY "Software\\Wow6432Node" +#else +#define SOFTWARE_KEY "Software" +#endif + +static registry_value_t uninstall_values[] = +{ + // Ultimate Doom, CD version (Depths of Doom trilogy) + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" + "Uninstall\\Ultimate Doom for Windows 95", + "UninstallString", + }, + + // Doom II, CD version (Depths of Doom trilogy) + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" + "Uninstall\\Doom II for Windows 95", + "UninstallString", + }, + + // Final Doom + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" + "Uninstall\\Final Doom for Windows 95", + "UninstallString", + }, + + // Shareware version + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" + "Uninstall\\Doom Shareware for Windows 95", + "UninstallString", + }, +}; + +// Values installed by the GOG.com and Collector's Edition versions + +static registry_value_t root_path_keys[] = +{ + // Doom Collector's Edition + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\Activision\\DOOM Collector's Edition\\v1.0", + "INSTALLPATH", + }, + + // Doom II + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1435848814", + "PATH", + }, + + // Doom 3: BFG Edition + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1135892318", + "PATH", + }, + + // Final Doom + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1435848742", + "PATH", + }, + + // Ultimate Doom + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1435827232", + "PATH", + }, + + // Strife: Veteran Edition + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1432899949", + "PATH", + }, + + // Heretic + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1290366318", + "PATH", + }, + + // Hexen + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1247951670", + "PATH", + }, + + // Hexen: Deathkings of a Dark Citadel + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1983497091", + "PATH", + }, + + // Heretic + Hexen Rerelease + + { + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\GOG.com\\Games\\1776058590", + "PATH" + }, +}; + +// Subdirectories of the above install path, where IWADs are installed. + +static char *root_path_subdirs[] = +{ + "Doom2", + "Final Doom", + "Ultimate Doom", + "Plutonia", + "TNT", + "base\\wads", + "dos\\base\\heretic", + "dos\\base\\hexen", + ".", +}; + +// Location where Steam is installed + +static registry_value_t steam_install_location = +{ + HKEY_LOCAL_MACHINE, + SOFTWARE_KEY "\\Valve\\Steam", + "InstallPath", +}; + +// Subdirs of the steam install directory where IWADs are found + +static char *steam_install_subdirs[] = +{ + "steamapps\\common\\doom 2\\base", + "steamapps\\common\\doom 2\\finaldoombase", + "steamapps\\common\\final doom\\base", + "steamapps\\common\\ultimate doom\\base", + "steamapps\\common\\heretic shadow of the serpent riders\\base", + "steamapps\\common\\hexen\\base", + "steamapps\\common\\hexen deathkings of the dark citadel\\base", + + // From Doom 3: BFG Edition: + + "steamapps\\common\\DOOM 3 BFG Edition\\base\\wads", + + // From Heretic + Hexen Rerelease: + + "steamapps\\common\\Heretic + Hexen\\dos\\base\\heretic", + "steamapps\\common\\Heretic + Hexen\\dos\\base\\hexen", + + // From Strife: Veteran Edition: + + "steamapps\\common\\Strife", +}; + +#define STEAM_BFG_GUS_PATCHES \ + "steamapps\\common\\DOOM 3 BFG Edition\\base\\classicmusic\\instruments" + +static char *GetRegistryString(registry_value_t *reg_val) +{ + HKEY key; + DWORD len; + DWORD valtype; + char *result; + + // Open the key (directory where the value is stored) + + if (RegOpenKeyEx(reg_val->root, reg_val->path, + 0, KEY_READ, &key) != ERROR_SUCCESS) + { + return NULL; + } + + result = NULL; + + // Find the type and length of the string, and only accept strings. + + if (RegQueryValueEx(key, reg_val->value, + NULL, &valtype, NULL, &len) == ERROR_SUCCESS + && valtype == REG_SZ) + { + // Allocate a buffer for the value and read the value + + result = malloc(len + 1); + + if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, + (unsigned char *) result, &len) != ERROR_SUCCESS) + { + free(result); + result = NULL; + } + else + { + // Ensure the value is null-terminated + result[len] = '\0'; + } + } + + // Close the key + + RegCloseKey(key); + + return result; +} + +// Check for the uninstall strings from the CD versions + +static void CheckUninstallStrings(void) +{ + unsigned int i; + + for (i=0; i 0) + { + return; + } + + install_path = GetRegistryString(&steam_install_location); + + if (install_path == NULL) + { + return; + } + + patch_path = M_StringJoin(install_path, "\\", STEAM_BFG_GUS_PATCHES, + NULL); + test_patch_path = M_StringJoin(patch_path, "\\ACBASS.PAT", NULL); + + // Does acbass.pat exist? If so, then set gus_patch_path. + if (M_FileExists(test_patch_path)) + { + M_SetVariable("gus_patch_path", patch_path); + } + + free(test_patch_path); + free(patch_path); + free(install_path); +} + +// Default install directories for DOS Doom + +static void CheckDOSDefaults(void) +{ + // These are the default install directories used by the deice + // installer program: + + AddIWADDir("\\doom2"); // Doom II + AddIWADDir("\\plutonia"); // Final Doom + AddIWADDir("\\tnt"); + AddIWADDir("\\doom_se"); // Ultimate Doom + AddIWADDir("\\doom"); // Shareware / Registered Doom + AddIWADDir("\\dooms"); // Shareware versions + AddIWADDir("\\doomsw"); + + AddIWADDir("\\heretic"); // Heretic + AddIWADDir("\\hrtic_se"); // Heretic Shareware from Quake disc + + AddIWADDir("\\hexen"); // Hexen + AddIWADDir("\\hexendk"); // Hexen Deathkings of the Dark Citadel + + AddIWADDir("\\strife"); // Strife +} + +#endif + +// Returns true if the specified path is a path to a file +// of the specified name. + +static boolean DirIsFile(const char *path, const char *filename) +{ + return strchr(path, DIR_SEPARATOR) != NULL + && !strcasecmp(M_BaseName(path), filename); +} + +// Check if the specified directory contains the specified IWAD +// file, returning the full path to the IWAD if found, or NULL +// if not found. + +static char *CheckDirectoryHasIWAD(const char *dir, const char *iwadname) +{ + char *filename; + char *probe; + + // As a special case, the "directory" may refer directly to an + // IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH. + + probe = M_FileCaseExists(dir); + if (DirIsFile(dir, iwadname) && probe != NULL) + { + return probe; + } + + // Construct the full path to the IWAD if it is located in + // this directory, and check if it exists. + + if (!strcmp(dir, ".")) + { + filename = M_StringDuplicate(iwadname); + } + else + { + filename = M_StringJoin(dir, DIR_SEPARATOR_S, iwadname, NULL); + } + + free(probe); + probe = M_FileCaseExists(filename); + free(filename); + if (probe != NULL) + { + return probe; + } + + return NULL; +} + +// Search a directory to try to find an IWAD +// Returns the location of the IWAD if found, otherwise NULL. + +static char *SearchDirectoryForIWAD(const char *dir, int mask, GameMission_t *mission) +{ + char *filename; + size_t i; + + for (i=0; i +static void AddXdgDirs(void) +{ + const char *env; + char *tmp_env; + + // Quote: + // > $XDG_DATA_HOME defines the base directory relative to which + // > user specific data files should be stored. If $XDG_DATA_HOME + // > is either not set or empty, a default equal to + // > $HOME/.local/share should be used. + env = getenv("XDG_DATA_HOME"); + tmp_env = NULL; + + if (env == NULL) + { + const char *homedir = getenv("HOME"); + if (homedir == NULL) + { + homedir = "/"; + } + + tmp_env = M_StringJoin(homedir, "/.local/share", NULL); + env = tmp_env; + } + + // We support $XDG_DATA_HOME/games/doom (which will usually be + // ~/.local/share/games/doom) as a user-writeable extension to + // the usual /usr/share/games/doom location. + AddIWADDir(M_StringJoin(env, "/games/doom", NULL)); + free(tmp_env); + + // Quote: + // > $XDG_DATA_DIRS defines the preference-ordered set of base + // > directories to search for data files in addition to the + // > $XDG_DATA_HOME base directory. The directories in $XDG_DATA_DIRS + // > should be seperated with a colon ':'. + // > + // > If $XDG_DATA_DIRS is either not set or empty, a value equal to + // > /usr/local/share/:/usr/share/ should be used. + env = getenv("XDG_DATA_DIRS"); + if (env == NULL) + { + // (Trailing / omitted from paths, as it is added below) + env = "/usr/local/share:/usr/share"; + } + + // The "standard" location for IWADs on Unix that is supported by most + // source ports is /usr/share/games/doom - we support this through the + // XDG_DATA_DIRS mechanism, through which it can be overridden. + AddIWADPath(env, "/games/doom"); + AddIWADPath(env, "/doom"); + + // The convention set by RBDOOM-3-BFG is to install Doom 3: BFG + // Edition into this directory, under which includes the Doom + // Classic WADs. + AddIWADPath(env, "/games/doom3bfg/base/wads"); +} + +#ifndef __MACOSX__ +// Steam on Linux allows installing some select Windows games, +// including the classic Doom series (running DOSBox via Wine). We +// could parse *.vdf files to more accurately detect installation +// locations, but the defaults are likely to be good enough for just +// about everyone. +static void AddSteamDirs(void) +{ + const char *homedir; + char *steampath; + + homedir = getenv("HOME"); + if (homedir == NULL) + { + homedir = "/"; + } + steampath = M_StringJoin(homedir, "/.steam/root/steamapps/common", NULL); + + AddIWADPath(steampath, "/Doom 2/base"); + AddIWADPath(steampath, "/Doom 2/finaldoombase"); + AddIWADPath(steampath, "/Master Levels of Doom/doom2"); + AddIWADPath(steampath, "/Ultimate Doom/base"); + AddIWADPath(steampath, "/Final Doom/base"); + AddIWADPath(steampath, "/DOOM 3 BFG Edition/base/wads"); + AddIWADPath(steampath, "/Heretic Shadow of the Serpent Riders/base"); + AddIWADPath(steampath, "/Hexen/base"); + AddIWADPath(steampath, "/Hexen Deathkings of the Dark Citadel/base"); + AddIWADPath(steampath, "/Heretic + Hexen/dos/base/heretic"); + AddIWADPath(steampath, "/Heretic + Hexen/dos/base/hexen"); + AddIWADPath(steampath, "/Strife"); + free(steampath); +} +#endif // __MACOSX__ +#endif // !_WIN32 + +// +// Build a list of IWAD files +// + +static void BuildIWADDirList(void) +{ + char *env; + + if (iwad_dirs_built) + { + return; + } + + // Look in the current directory. Doom always does this. + AddIWADDir("."); + + // Next check the directory where the executable is located. This might + // be different from the current directory. + AddIWADDir(M_DirName(myargv[0])); + + // Add DOOMWADDIR if it is in the environment + env = M_getenv("DOOMWADDIR"); + if (env != NULL) + { + AddIWADDir(env); + } + + // Add dirs from DOOMWADPATH: + env = M_getenv("DOOMWADPATH"); + if (env != NULL) + { + AddIWADPath(env, ""); + } + +#ifdef _WIN32 + + // Search the registry and find where IWADs have been installed. + + CheckUninstallStrings(); + CheckInstallRootPaths(); + CheckSteamEdition(); + CheckDOSDefaults(); + + // Check for GUS patches installed with the BFG edition! + + CheckSteamGUSPatches(); + +#else + AddXdgDirs(); +#ifndef __MACOSX__ + AddSteamDirs(); +#endif +#endif + + // Don't run this function again. + + iwad_dirs_built = true; +} + +// +// Searches WAD search paths for an WAD with a specific filename. +// + +char *D_FindWADByName(const char *name) +{ + char *path; + char *probe; + int i; + + // Absolute path? + + probe = M_FileCaseExists(name); + if (probe != NULL) + { + return probe; + } + + BuildIWADDirList(); + + // Search through all IWAD paths for a file with the given name. + + for (i=0; i + // + + iwadparm = M_CheckParmWithArgs("-iwad", 1); + + if (iwadparm) + { + // Search through IWAD dirs for an IWAD with the given name. + + iwadfile = myargv[iwadparm + 1]; + + result = D_FindWADByName(iwadfile); + + if (result == NULL) + { + I_Error("IWAD file '%s' not found!", iwadfile); + } + + *mission = IdentifyIWADByName(result, mask); + } + else + { + // Search through the list and look for an IWAD + + result = NULL; + + BuildIWADDirList(); + + for (i=0; result == NULL && i +#include + +#include "d_event.h" +#include "d_loop.h" +#include "d_ticcmd.h" + +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" + +#include "m_argv.h" +#include "m_fixed.h" + +#include "net_client.h" +#include "net_gui.h" +#include "net_io.h" +#include "net_query.h" +#include "net_server.h" +#include "net_sdl.h" +#include "net_loop.h" + +// The complete set of data for a particular tic. + +typedef struct +{ + ticcmd_t cmds[NET_MAXPLAYERS]; + boolean ingame[NET_MAXPLAYERS]; +} ticcmd_set_t; + +// Maximum time that we wait in TryRunTics() for netgame data to be +// received before we bail out and render a frame anyway. +// Vanilla Doom used 20 for this value, but we use a smaller value +// instead for better responsiveness of the menu when we're stuck. +#define MAX_NETGAME_STALL_TICS 5 + +// +// gametic is the tic about to (or currently being) run +// maketic is the tic that hasn't had control made for it yet +// recvtic is the latest tic received from the server. +// +// a gametic cannot be run until ticcmds are received for it +// from all players. +// + +static ticcmd_set_t ticdata[BACKUPTICS]; + +// The index of the next tic to be made (with a call to BuildTiccmd). + +static int maketic; + +// The number of complete tics received from the server so far. + +static int recvtic; + +// The number of tics that have been run (using RunTic) so far. + +int gametic; + +// When set to true, a single tic is run each time TryRunTics() is called. +// This is used for -timedemo mode. + +boolean singletics = false; + +// Index of the local player. + +static int localplayer; + +// Used for original sync code. + +static int skiptics = 0; + +// Reduce the bandwidth needed by sampling game input less and transmitting +// less. If ticdup is 2, sample half normal, 3 = one third normal, etc. + +int ticdup; + +// Amount to offset the timer for game sync. + +fixed_t offsetms; + +// Use new client syncronisation code + +static boolean new_sync = true; + +// Callback functions for loop code. + +static loop_interface_t *loop_interface = NULL; + +// Current players in the multiplayer game. +// This is distinct from playeringame[] used by the game code, which may +// modify playeringame[] when playing back multiplayer demos. + +static boolean local_playeringame[NET_MAXPLAYERS]; + +// Requested player class "sent" to the server on connect. +// If we are only doing a single player game then this needs to be remembered +// and saved in the game settings. + +static int player_class; + + +// 35 fps clock adjusted by offsetms milliseconds + +static int GetAdjustedTime(void) +{ + int time_ms; + + time_ms = I_GetTimeMS(); + + if (new_sync) + { + // Use the adjustments from net_client.c only if we are + // using the new sync mode. + + time_ms += (offsetms / FRACUNIT); + } + + return (time_ms * TICRATE) / 1000; +} + +static boolean BuildNewTic(void) +{ + int gameticdiv; + ticcmd_t cmd; + + gameticdiv = gametic/ticdup; + + I_StartTic (); + loop_interface->ProcessEvents(); + + // Always run the menu + + loop_interface->RunMenu(); + + if (drone) + { + // In drone mode, do not generate any ticcmds. + + return false; + } + + if (new_sync) + { + // If playing single player, do not allow tics to buffer + // up very far + + if (!net_client_connected && maketic - gameticdiv > 2) + return false; + + // Never go more than ~200ms ahead + + if (maketic - gameticdiv > 8) + return false; + } + else + { + if (maketic - gameticdiv >= 5) + return false; + } + + //printf ("mk:%i ",maketic); + memset(&cmd, 0, sizeof(ticcmd_t)); + loop_interface->BuildTiccmd(&cmd, maketic); + + if (net_client_connected) + { + NET_CL_SendTiccmd(&cmd, maketic); + } + + ticdata[maketic % BACKUPTICS].cmds[localplayer] = cmd; + ticdata[maketic % BACKUPTICS].ingame[localplayer] = true; + + ++maketic; + + return true; +} + +// +// NetUpdate +// Builds ticcmds for console player, +// sends out a packet +// +int lasttime; + +void NetUpdate (void) +{ + int nowtime; + int newtics; + int i; + + // If we are running with singletics (timing a demo), this + // is all done separately. + + if (singletics) + return; + + // Run network subsystems + + NET_CL_Run(); + NET_SV_Run(); + + // check time + nowtime = GetAdjustedTime() / ticdup; + newtics = nowtime - lasttime; + + lasttime = nowtime; + + if (skiptics <= newtics) + { + newtics -= skiptics; + skiptics = 0; + } + else + { + skiptics -= newtics; + newtics = 0; + } + + // build new ticcmds for console player + + for (i=0 ; iconsoleplayer = 0; + settings->num_players = 1; + settings->player_classes[0] = player_class; + + //! + // @category net + // + // Use original network client sync code rather than the improved + // sync code. + // + settings->new_sync = !M_ParmExists("-oldsync"); + + //! + // @category net + // @arg + // + // Send n extra tics in every packet as insurance against dropped + // packets. + // + + i = M_CheckParmWithArgs("-extratics", 1); + + if (i > 0) + settings->extratics = atoi(myargv[i+1]); + else + settings->extratics = 1; + + //! + // @category net + // @arg + // + // Reduce the resolution of the game by a factor of n, reducing + // the amount of network bandwidth needed. + // + + i = M_CheckParmWithArgs("-dup", 1); + + if (i > 0) + settings->ticdup = atoi(myargv[i+1]); + else + settings->ticdup = 1; + + if (net_client_connected) + { + // Send our game settings and block until game start is received + // from the server. + + NET_CL_StartGame(settings); + BlockUntilStart(settings, callback); + + // Read the game settings that were received. + + NET_CL_GetSettings(settings); + } + + if (drone) + { + settings->consoleplayer = 0; + } + + // Set the local player and playeringame[] values. + + localplayer = settings->consoleplayer; + + for (i = 0; i < NET_MAXPLAYERS; ++i) + { + local_playeringame[i] = i < settings->num_players; + } + + // Copy settings to global variables. + + ticdup = settings->ticdup; + new_sync = settings->new_sync; + + if (ticdup < 1) + { + I_Error("D_StartNetGame: invalid ticdup value (%d)", ticdup); + } + + // TODO: Message disabled until we fix new_sync. + //if (!new_sync) + //{ + // printf("Syncing netgames like Vanilla Doom.\n"); + //} +} + +boolean D_InitNetGame(net_connect_data_t *connect_data) +{ + boolean result = false; + net_addr_t *addr = NULL; + int i; + + // Call D_QuitNetGame on exit: + + I_AtExit(D_QuitNetGame, true); + + player_class = connect_data->player_class; + + //! + // @category net + // + // Start a multiplayer server, listening for connections. + // + + if (M_CheckParm("-server") > 0 + || M_CheckParm("-privateserver") > 0) + { + NET_SV_Init(); + NET_SV_AddModule(&net_loop_server_module); + NET_SV_AddModule(&net_sdl_module); + NET_SV_RegisterWithMaster(); + + net_loop_client_module.InitClient(); + addr = net_loop_client_module.ResolveAddress(NULL); + NET_ReferenceAddress(addr); + } + else + { + //! + // @category net + // + // Automatically search the local LAN for a multiplayer + // server and join it. + // + + i = M_CheckParm("-autojoin"); + + if (i > 0) + { + addr = NET_FindLANServer(); + + if (addr == NULL) + { + I_Error("No server found on local LAN"); + } + } + + //! + // @arg
+ // @category net + // + // Connect to a multiplayer server running on the given + // address. + // + + i = M_CheckParmWithArgs("-connect", 1); + + if (i > 0) + { + net_sdl_module.InitClient(); + addr = net_sdl_module.ResolveAddress(myargv[i+1]); + NET_ReferenceAddress(addr); + + if (addr == NULL) + { + I_Error("Unable to resolve '%s'\n", myargv[i+1]); + } + } + } + + if (addr != NULL) + { + if (M_CheckParm("-drone") > 0) + { + connect_data->drone = true; + } + + if (!NET_CL_Connect(addr, connect_data)) + { + I_Error("D_InitNetGame: Failed to connect to %s:\n%s\n", + NET_AddrToString(addr), net_client_reject_reason); + } + + printf("D_InitNetGame: Connected to %s\n", NET_AddrToString(addr)); + NET_ReleaseAddress(addr); + + // Wait for launch message received from server. + + NET_WaitForLaunch(); + + result = true; + } + + return result; +} + + +// +// D_QuitNetGame +// Called before quitting to leave a net game +// without hanging the other players +// +void D_QuitNetGame (void) +{ + NET_SV_Shutdown(); + NET_CL_Disconnect(); +} + +static int GetLowTic(void) +{ + int lowtic; + + lowtic = maketic; + + if (net_client_connected) + { + if (drone || recvtic < lowtic) + { + lowtic = recvtic; + } + } + + return lowtic; +} + +static int frameon; +static int frameskip[4]; +static int oldnettics; + +static void OldNetSync(void) +{ + unsigned int i; + int keyplayer = -1; + + frameon++; + + // ideally maketic should be 1 - 3 tics above lowtic + // if we are consistantly slower, speed up time + + for (i=0 ; i recvtic; + oldnettics = maketic; + + if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) + { + skiptics = 1; + // printf ("+"); + } + } +} + +// Returns true if there are players in the game: + +static boolean PlayersInGame(void) +{ + boolean result = false; + unsigned int i; + + // If we are connected to a server, check if there are any players + // in the game. + + if (net_client_connected) + { + for (i = 0; i < NET_MAXPLAYERS; ++i) + { + result = result || local_playeringame[i]; + } + } + + // Whether single or multi-player, unless we are running as a drone, + // we are in the game. + + if (!drone) + { + result = true; + } + + return result; +} + +// When using ticdup, certain values must be cleared out when running +// the duplicate ticcmds. + +static void TicdupSquash(ticcmd_set_t *set) +{ + ticcmd_t *cmd; + unsigned int i; + + for (i = 0; i < NET_MAXPLAYERS ; ++i) + { + cmd = &set->cmds[i]; + cmd->chatchar = 0; + if (cmd->buttons & BT_SPECIAL) + cmd->buttons = 0; + } +} + +// When running in single player mode, clear all the ingame[] array +// except the local player. + +static void SinglePlayerClear(ticcmd_set_t *set) +{ + unsigned int i; + + for (i = 0; i < NET_MAXPLAYERS; ++i) + { + if (i != localplayer) + { + set->ingame[i] = false; + } + } +} + +// +// TryRunTics +// + +void TryRunTics (void) +{ + int i; + int lowtic; + int entertic; + static int oldentertics; + int realtics; + int availabletics; + int counts; + + // get real tics + entertic = I_GetTime() / ticdup; + realtics = entertic - oldentertics; + oldentertics = entertic; + + // in singletics mode, run a single tic every time this function + // is called. + + if (singletics) + { + BuildNewTic(); + } + else + { + NetUpdate (); + } + + lowtic = GetLowTic(); + + availabletics = lowtic - gametic/ticdup; + + // decide how many tics to run + + if (new_sync) + { + counts = availabletics; + } + else + { + // decide how many tics to run + if (realtics < availabletics-1) + counts = realtics+1; + else if (realtics < availabletics) + counts = realtics; + else + counts = availabletics; + + if (counts < 1) + counts = 1; + + if (net_client_connected) + { + OldNetSync(); + } + } + + if (counts < 1) + counts = 1; + + // wait for new tics if needed + while (!PlayersInGame() || lowtic < gametic/ticdup + counts) + { + NetUpdate (); + + lowtic = GetLowTic(); + + if (lowtic < gametic/ticdup) + I_Error ("TryRunTics: lowtic < gametic"); + + // Still no tics to run? Sleep until some are available. + if (lowtic < gametic/ticdup + counts) + { + // If we're in a netgame, we might spin forever waiting for + // new network data to be received. So don't stay in here + // forever - give the menu a chance to work. + if (I_GetTime() / ticdup - entertic >= MAX_NETGAME_STALL_TICS) + { + return; + } + + I_Sleep(1); + } + } + + // run the count * ticdup dics + while (counts--) + { + ticcmd_set_t *set; + + if (!PlayersInGame()) + { + return; + } + + set = &ticdata[(gametic / ticdup) % BACKUPTICS]; + + if (!net_client_connected) + { + SinglePlayerClear(set); + } + + for (i=0 ; i lowtic) + I_Error ("gametic>lowtic"); + + memcpy(local_playeringame, set->ingame, sizeof(local_playeringame)); + + loop_interface->RunTic(set->cmds, set->ingame); + gametic++; + + // modify command for duplicated tics + + TicdupSquash(set); + } + + NetUpdate (); // check for new console commands + } +} + +void D_RegisterLoopCallbacks(loop_interface_t *i) +{ + loop_interface = i; +} + +// TODO: Move nonvanilla demo functions into a dedicated file. +#include "m_misc.h" +#include "w_wad.h" + +static boolean StrictDemos(void) +{ + //! + // @category demo + // + // When recording or playing back demos, disable any extensions + // of the vanilla demo format - record demos as vanilla would do, + // and play back demos as vanilla would do. + // + return M_ParmExists("-strictdemos"); +} + +// If the provided conditional value is true, we're trying to record +// a demo file that will include a non-vanilla extension. The function +// will return true if the conditional is true and it's allowed to use +// this extension (no extensions are allowed if -strictdemos is given +// on the command line). A warning is shown on the console using the +// provided string describing the non-vanilla expansion. +boolean D_NonVanillaRecord(boolean conditional, const char *feature) +{ + if (!conditional || StrictDemos()) + { + return false; + } + + printf("Warning: Recording a demo file with a non-vanilla extension " + "(%s). Use -strictdemos to disable this extension.\n", + feature); + + return true; +} + +// Returns true if the given lump number corresponds to data from a .lmp +// file, as opposed to a WAD. +static boolean IsDemoFile(int lumpnum) +{ + char *lower; + boolean result; + + lower = M_StringDuplicate(lumpinfo[lumpnum]->wad_file->path); + M_ForceLowercase(lower); + result = M_StringEndsWith(lower, ".lmp"); + free(lower); + + return result; +} + +// If the provided conditional value is true, we're trying to play back +// a demo that includes a non-vanilla extension. We return true if the +// conditional is true and it's allowed to use this extension, checking +// that: +// - The -strictdemos command line argument is not provided. +// - The given lumpnum identifying the demo to play back identifies a +// demo that comes from a .lmp file, not a .wad file. +// - Before proceeding, a warning is shown to the user on the console. +boolean D_NonVanillaPlayback(boolean conditional, int lumpnum, + const char *feature) +{ + if (!conditional || StrictDemos()) + { + return false; + } + + if (!IsDemoFile(lumpnum)) + { + printf("Warning: WAD contains demo with a non-vanilla extension " + "(%s)\n", feature); + return false; + } + + printf("Warning: Playing back a demo file with a non-vanilla extension " + "(%s). Use -strictdemos to disable this extension.\n", + feature); + + return true; +} + diff --git a/games/NXDoom/src/d_loop.h b/games/NXDoom/src/d_loop.h new file mode 100644 index 00000000000..c154be3a643 --- /dev/null +++ b/games/NXDoom/src/d_loop.h @@ -0,0 +1,96 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Main loop stuff. +// + +#ifndef __D_LOOP__ +#define __D_LOOP__ + +#include "net_defs.h" +#include "m_fixed.h" + + +// Callback function invoked while waiting for the netgame to start. +// The callback is invoked when new players are ready. The callback +// should return true, or return false to abort startup. + +typedef boolean (*netgame_startup_callback_t)(int ready_players, + int num_players); + +typedef struct +{ + // Read events from the event queue, and process them. + + void (*ProcessEvents)(); + + // Given the current input state, fill in the fields of the specified + // ticcmd_t structure with data for a new tic. + + void (*BuildTiccmd)(ticcmd_t *cmd, int maketic); + + // Advance the game forward one tic, using the specified player input. + + void (*RunTic)(ticcmd_t *cmds, boolean *ingame); + + // Run the menu (runs independently of the game). + + void (*RunMenu)(); +} loop_interface_t; + +// Register callback functions for the main loop code to use. +void D_RegisterLoopCallbacks(loop_interface_t *i); + +// Create any new ticcmds and broadcast to other players. +void NetUpdate (void); + +// Broadcasts special packets to other players +// to notify of game exit +void D_QuitNetGame (void); + +//? how many ticks to run? +void TryRunTics (void); + +// Called at start of game loop to initialize timers +void D_StartGameLoop(void); + +// Initialize networking code and connect to server. + +boolean D_InitNetGame(net_connect_data_t *connect_data); + +// Start game with specified settings. The structure will be updated +// with the actual settings for the game. + +void D_StartNetGame(net_gamesettings_t *settings, + netgame_startup_callback_t callback); + +extern boolean singletics; +extern int gametic, ticdup; + +// Check if it is permitted to record a demo with a non-vanilla feature. +boolean D_NonVanillaRecord(boolean conditional, const char *feature); + +// Check if it is permitted to play back a demo with a non-vanilla feature. +boolean D_NonVanillaPlayback(boolean conditional, int lumpnum, + const char *feature); + +void D_ReceiveTic(ticcmd_t *ticcmds, boolean *playeringame); + + +extern fixed_t offsetms; + + +#endif + diff --git a/games/NXDoom/src/d_mode.c b/games/NXDoom/src/d_mode.c new file mode 100644 index 00000000000..95f6bb18248 --- /dev/null +++ b/games/NXDoom/src/d_mode.c @@ -0,0 +1,233 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: +// Functions and definitions relating to the game type and operational +// mode. +// + +#include "doomtype.h" +#include "d_mode.h" + +// Valid game mode/mission combinations, with the number of +// episodes/maps for each. + +static struct +{ + GameMission_t mission; + GameMode_t mode; + int episode; + int map; +} valid_modes[] = { + { pack_chex, retail, 1, 5 }, + { doom, shareware, 1, 9 }, + { doom, registered, 3, 9 }, + { doom, retail, 4, 9 }, + { doom2, commercial, 1, 32 }, + { pack_tnt, commercial, 1, 32 }, + { pack_plut, commercial, 1, 32 }, + { pack_hacx, commercial, 1, 32 }, + { heretic, shareware, 1, 9 }, + { heretic, registered, 3, 9 }, + { heretic, retail, 5, 9 }, + { hexen, commercial, 1, 60 }, + { strife, commercial, 1, 34 }, +}; + +// Check that a gamemode+gamemission received over the network is valid. + +boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode) +{ + int i; + + for (i=0; i= 1 && map <= 3; + } + else if (mode == registered && episode == 4) + { + return map == 1; + } + } + + // Find the table entry for this mission/mode combination. + + for (i=0; i= 1 && episode <= valid_modes[i].episode + && map >= 1 && map <= valid_modes[i].map; + } + } + + // Unknown mode/mission combination + + return false; +} + +// Get the number of valid episodes for the specified mission/mode. + +int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode) +{ + int episode; + + episode = 1; + + while (D_ValidEpisodeMap(mission, mode, episode, 1)) + { + ++episode; + } + + return episode - 1; +} + +// Table of valid versions + +static struct { + GameMission_t mission; + GameVersion_t version; +} valid_versions[] = { + { doom, exe_doom_1_2 }, + { doom, exe_doom_1_5 }, + { doom, exe_doom_1_666 }, + { doom, exe_doom_1_7 }, + { doom, exe_doom_1_8 }, + { doom, exe_doom_1_9 }, + { doom, exe_hacx }, + { doom, exe_ultimate }, + { doom, exe_final }, + { doom, exe_final2 }, + { doom, exe_chex }, + { heretic, exe_heretic_1_3 }, + { hexen, exe_hexen_1_1 }, + { hexen, exe_hexen_1_1r2 }, + { strife, exe_strife_1_2 }, + { strife, exe_strife_1_31 }, +}; + +boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version) +{ + int i; + + // All Doom variants can use the Doom versions. + + if (mission == doom2 || mission == pack_plut || mission == pack_tnt + || mission == pack_hacx || mission == pack_chex) + { + mission = doom; + } + + for (i=0; i +#include +#include +#include +#include + +#include "m_misc.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "deh_defs.h" +#include "deh_io.h" + +typedef enum +{ + DEH_INPUT_FILE, + DEH_INPUT_LUMP +} deh_input_type_t; + +struct deh_context_s +{ + deh_input_type_t type; + char *filename; + + // If the input comes from a memory buffer, pointer to the memory + // buffer. + unsigned char *input_buffer; + size_t input_buffer_len; + unsigned int input_buffer_pos; + int lumpnum; + + // If the input comes from a file, the file stream for reading + // data. + FILE *stream; + + // Current line number that we have reached: + int linenum; + + // Used by DEH_ReadLine: + boolean last_was_newline; + char *readbuffer; + int readbuffer_size; + + // Error handling. + boolean had_error; +}; + +static deh_context_t *DEH_NewContext(void) +{ + deh_context_t *context; + + context = Z_Malloc(sizeof(*context), PU_STATIC, NULL); + + // Initial read buffer size of 128 bytes + + context->readbuffer_size = 128; + context->readbuffer = Z_Malloc(context->readbuffer_size, PU_STATIC, NULL); + context->linenum = 0; + context->last_was_newline = true; + + context->had_error = false; + + return context; +} + +// Open a dehacked file for reading +// Returns NULL if open failed + +deh_context_t *DEH_OpenFile(const char *filename) +{ + FILE *fstream; + deh_context_t *context; + + fstream = M_fopen(filename, "r"); + + if (fstream == NULL) + return NULL; + + context = DEH_NewContext(); + + context->type = DEH_INPUT_FILE; + context->stream = fstream; + context->filename = M_StringDuplicate(filename); + + return context; +} + +// Open a WAD lump for reading. + +deh_context_t *DEH_OpenLump(int lumpnum) +{ + deh_context_t *context; + void *lump; + + lump = W_CacheLumpNum(lumpnum, PU_STATIC); + + context = DEH_NewContext(); + + context->type = DEH_INPUT_LUMP; + context->lumpnum = lumpnum; + context->input_buffer = lump; + context->input_buffer_len = W_LumpLength(lumpnum); + context->input_buffer_pos = 0; + + context->filename = malloc(9); + M_StringCopy(context->filename, lumpinfo[lumpnum]->name, 9); + + return context; +} + +// Close dehacked file + +void DEH_CloseFile(deh_context_t *context) +{ + if (context->type == DEH_INPUT_FILE) + { + fclose(context->stream); + } + else if (context->type == DEH_INPUT_LUMP) + { + W_ReleaseLumpNum(context->lumpnum); + } + + free(context->filename); + Z_Free(context->readbuffer); + Z_Free(context); +} + +int DEH_GetCharFile(deh_context_t *context) +{ + if (feof(context->stream)) + { + // end of file + + return -1; + } + + return fgetc(context->stream); +} + +int DEH_GetCharLump(deh_context_t *context) +{ + int result; + + if (context->input_buffer_pos >= context->input_buffer_len) + { + return -1; + } + + result = context->input_buffer[context->input_buffer_pos]; + ++context->input_buffer_pos; + + return result; +} + +// Reads a single character from a dehacked file + +int DEH_GetChar(deh_context_t *context) +{ + int result = 0; + boolean last_was_cr = false; + + // Track the current line number + + if (context->last_was_newline) + { + ++context->linenum; + } + + // Read characters, converting CRLF to LF + + do + { + switch (context->type) + { + case DEH_INPUT_FILE: + result = DEH_GetCharFile(context); + break; + + case DEH_INPUT_LUMP: + result = DEH_GetCharLump(context); + break; + } + + // Handle \r characters not paired with \n + if (last_was_cr && result != '\n') + { + switch (context->type) + { + case DEH_INPUT_FILE: + ungetc(result, context->stream); + break; + + case DEH_INPUT_LUMP: + --context->input_buffer_pos; + break; + } + + return '\r'; + } + + last_was_cr = result == '\r'; + + } while (last_was_cr); + + context->last_was_newline = result == '\n'; + + return result; +} + +// Increase the read buffer size + +static void IncreaseReadBuffer(deh_context_t *context) +{ + char *newbuffer; + int newbuffer_size; + + newbuffer_size = context->readbuffer_size * 2; + newbuffer = Z_Malloc(newbuffer_size, PU_STATIC, NULL); + + memcpy(newbuffer, context->readbuffer, context->readbuffer_size); + + Z_Free(context->readbuffer); + + context->readbuffer = newbuffer; + context->readbuffer_size = newbuffer_size; +} + +// Read a whole line + +char *DEH_ReadLine(deh_context_t *context, boolean extended) +{ + int c; + int pos; + boolean escaped = false; + + for (pos = 0;;) + { + c = DEH_GetChar(context); + + if (c < 0 && pos == 0) + { + // end of file + + return NULL; + } + + // cope with lines of any length: increase the buffer size + + if (pos >= context->readbuffer_size) + { + IncreaseReadBuffer(context); + } + + // extended string support + if (extended && c == '\\') + { + c = DEH_GetChar(context); + + // "\n" in the middle of a string indicates an internal linefeed + if (c == 'n') + { + context->readbuffer[pos] = '\n'; + ++pos; + continue; + } + + // values to be assigned may be split onto multiple lines by ending + // each line that is to be continued with a backslash + if (c == '\n') + { + escaped = true; + continue; + } + } + + // blanks before the backslash are included in the string + // but indentation after the linefeed is not + if (escaped && c >= 0 && isspace(c) && c != '\n') + { + continue; + } + else + { + escaped = false; + } + + if (c == '\n' || c < 0) + { + // end of line: a full line has been read + + context->readbuffer[pos] = '\0'; + break; + } + else if (c != '\0') + { + // normal character; don't allow NUL characters to be + // added. + + context->readbuffer[pos] = (char) c; + ++pos; + } + } + + return context->readbuffer; +} + +void DEH_Warning(deh_context_t *context, const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + + fprintf(stderr, "%s:%i: warning: ", context->filename, context->linenum); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n"); + + va_end(args); +} + +void DEH_Error(deh_context_t *context, const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + + fprintf(stderr, "%s:%i: ", context->filename, context->linenum); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n"); + + va_end(args); + + context->had_error = true; +} + +boolean DEH_HadError(deh_context_t *context) +{ + return context->had_error; +} + diff --git a/games/NXDoom/src/deh_io.h b/games/NXDoom/src/deh_io.h new file mode 100644 index 00000000000..de6720e61f6 --- /dev/null +++ b/games/NXDoom/src/deh_io.h @@ -0,0 +1,33 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dehacked I/O code (does all reads from dehacked files) +// + +#ifndef DEH_IO_H +#define DEH_IO_H + +#include "deh_defs.h" + +deh_context_t *DEH_OpenFile(const char *filename); +deh_context_t *DEH_OpenLump(int lumpnum); +void DEH_CloseFile(deh_context_t *context); +int DEH_GetChar(deh_context_t *context); +char *DEH_ReadLine(deh_context_t *context, boolean extended); +void DEH_Error(deh_context_t *context, const char *msg, ...) PRINTF_ATTR(2, 3); +void DEH_Warning(deh_context_t *context, const char *msg, ...) PRINTF_ATTR(2, 3); +boolean DEH_HadError(deh_context_t *context); + +#endif /* #ifndef DEH_IO_H */ + diff --git a/games/NXDoom/src/deh_main.c b/games/NXDoom/src/deh_main.c new file mode 100644 index 00000000000..3ef8a25c323 --- /dev/null +++ b/games/NXDoom/src/deh_main.c @@ -0,0 +1,519 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Main dehacked code +// + +#include +#include +#include +#include + +#include "doomtype.h" +#include "i_glob.h" +#include "i_system.h" +#include "d_iwad.h" +#include "m_argv.h" +#include "w_wad.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" + + +static boolean deh_initialized = false; + +// If true, we can parse [STRINGS] sections in BEX format. + +boolean deh_allow_extended_strings = false; + +// If true, we can do long string replacements. + +boolean deh_allow_long_strings = false; + +// If true, we can do cheat replacements longer than the originals. + +boolean deh_allow_long_cheats = false; + +// If false, dehacked cheat replacements are ignored. + +boolean deh_apply_cheats = true; + +void DEH_Checksum(sha1_digest_t digest) +{ + sha1_context_t sha1_context; + unsigned int i; + + SHA1_Init(&sha1_context); + + for (i=0; deh_section_types[i] != NULL; ++i) + { + if (deh_section_types[i]->sha1_hash != NULL) + { + deh_section_types[i]->sha1_hash(&sha1_context); + } + } + + SHA1_Final(digest, &sha1_context); +} + +// Called on startup to call the Init functions + +static void InitializeSections(void) +{ + unsigned int i; + + for (i=0; deh_section_types[i] != NULL; ++i) + { + if (deh_section_types[i]->init != NULL) + { + deh_section_types[i]->init(); + } + } +} + +static void DEH_Init(void) +{ + //! + // @category mod + // + // Ignore cheats in dehacked files. + // + + if (M_CheckParm("-nocheats") > 0) + { + deh_apply_cheats = false; + } + + // Call init functions for all the section definitions. + InitializeSections(); + + deh_initialized = true; +} + +// Given a section name, get the section structure which corresponds + +static deh_section_t *GetSectionByName(char *name) +{ + unsigned int i; + + // we explicitely do not recognize [STRINGS] sections at all + // if extended strings are not allowed + + if (!deh_allow_extended_strings && !strncasecmp("[STRINGS]", name, 9)) + { + return NULL; + } + + for (i=0; deh_section_types[i] != NULL; ++i) + { + if (!strcasecmp(deh_section_types[i]->name, name)) + { + return deh_section_types[i]; + } + } + + return NULL; +} + +// Is the string passed just whitespace? + +static boolean IsWhitespace(char *s) +{ + for (; *s; ++s) + { + if (!isspace(*s)) + return false; + } + + return true; +} + +// Strip whitespace from the start and end of a string + +static char *CleanString(char *s) +{ + char *strending; + + // Leading whitespace + + while (*s && isspace(*s)) + ++s; + + // Trailing whitespace + + strending = s + strlen(s) - 1; + + while (strlen(s) > 0 && isspace(*strending)) + { + *strending = '\0'; + --strending; + } + + return s; +} + +// This pattern is used a lot of times in different sections, +// an assignment is essentially just a statement of the form: +// +// Variable Name = Value +// +// The variable name can include spaces or any other characters. +// The string is split on the '=', essentially. +// +// Returns true if read correctly + +boolean DEH_ParseAssignment(char *line, char **variable_name, char **value) +{ + char *p; + + // find the equals + + p = strchr(line, '='); + + if (p == NULL) + { + return false; + } + + // variable name at the start + // turn the '=' into a \0 to terminate the string here + + *p = '\0'; + *variable_name = CleanString(line); + + // value immediately follows the '=' + + *value = CleanString(p+1); + + return true; +} + +static boolean CheckSignatures(deh_context_t *context) +{ + size_t i; + char *line; + + // Read the first line + + line = DEH_ReadLine(context, false); + + if (line == NULL) + { + return false; + } + + // Check all signatures to see if one matches + + for (i=0; deh_signatures[i] != NULL; ++i) + { + if (!strcmp(deh_signatures[i], line)) + { + return true; + } + } + + return false; +} + +// Parses a comment string in a dehacked file. + +static void DEH_ParseComment(char *comment) +{ + // + // Welcome, to the super-secret Chocolate Doom-specific Dehacked + // overrides function. + // + // Putting these magic comments into your Dehacked lumps will + // allow you to go beyond the normal limits of Vanilla Dehacked. + // Because of this, these comments are deliberately undocumented, + // and if you're using them you should be aware that your mod + // is not compatible with Vanilla Doom and you're probably a + // very naughty person. + // + + // Allow comments containing this special value to allow string + // replacements longer than those permitted by DOS dehacked. + // This allows us to use a dehacked patch for doing string + // replacements for emulating Chex Quest. + // + // If you use this, your dehacked patch may not work in Vanilla + // Doom. + + if (strstr(comment, "*allow-long-strings*") != NULL) + { + deh_allow_long_strings = true; + } + + // Allow magic comments to allow longer cheat replacements than + // those permitted by DOS dehacked. This is also for Chex + // Quest. + + if (strstr(comment, "*allow-long-cheats*") != NULL) + { + deh_allow_long_cheats = true; + } + + // Allow magic comments to allow parsing [STRINGS] section + // that are usually only found in BEX format files. This allows + // for substitution of map and episode names when loading + // Freedoom/FreeDM IWADs. + + if (strstr(comment, "*allow-extended-strings*") != NULL) + { + deh_allow_extended_strings = true; + } +} + +// Parses a dehacked file by reading from the context + +static void DEH_ParseContext(deh_context_t *context) +{ + deh_section_t *current_section = NULL; + char section_name[20]; + void *tag = NULL; + boolean extended; + char *line; + + // Read the header and check it matches the signature + + if (!CheckSignatures(context)) + { + DEH_Error(context, "This is not a valid dehacked patch file!"); + } + + // Read the file + + while (!DEH_HadError(context)) + { + // Read the next line. We only allow the special extended parsing + // for the BEX [STRINGS] section. + extended = current_section != NULL + && !strcasecmp(current_section->name, "[STRINGS]"); + line = DEH_ReadLine(context, extended); + + // end of file? + + if (line == NULL) + { + return; + } + + while (line[0] != '\0' && isspace(line[0])) + ++line; + + if (line[0] == '#') + { + // comment + + DEH_ParseComment(line); + continue; + } + + if (IsWhitespace(line)) + { + if (current_section != NULL) + { + // end of section + + if (current_section->end != NULL) + { + current_section->end(context, tag); + } + + //printf("end %s tag\n", current_section->name); + current_section = NULL; + } + } + else + { + if (current_section != NULL) + { + // parse this line + + current_section->line_parser(context, line, tag); + } + else + { + // possibly the start of a new section + + sscanf(line, "%19s", section_name); + + current_section = GetSectionByName(section_name); + + if (current_section != NULL) + { + tag = current_section->start(context, line); + //printf("started %s tag\n", section_name); + } + else + { + //printf("unknown section name %s\n", section_name); + } + } + } + } +} + +// Parses a dehacked file + +int DEH_LoadFile(const char *filename) +{ + deh_context_t *context; + boolean had_error; + + if (!deh_initialized) + { + DEH_Init(); + } + + // Before parsing a new file, reset special override flags to false. + // Magic comments should only apply to the file in which they were + // defined, and shouldn't carry over to subsequent files as well. + deh_allow_long_strings = false; + deh_allow_long_cheats = false; + deh_allow_extended_strings = false; + + printf(" loading %s\n", filename); + + context = DEH_OpenFile(filename); + + if (context == NULL) + { + fprintf(stderr, "DEH_LoadFile: Unable to open %s\n", filename); + return 0; + } + + DEH_ParseContext(context); + + had_error = DEH_HadError(context); + + DEH_CloseFile(context); + + if (had_error) + { + I_Error("Error parsing dehacked file"); + } + + return 1; +} + +// Load all dehacked patches from the given directory. +void DEH_AutoLoadPatches(const char *path) +{ + const char *filename; + glob_t *glob; + + glob = I_StartMultiGlob(path, GLOB_FLAG_NOCASE|GLOB_FLAG_SORTED, + "*.deh", "*.hhe", "*.seh", NULL); + for (;;) + { + filename = I_NextGlob(glob); + if (filename == NULL) + { + break; + } + printf(" [autoload]"); + DEH_LoadFile(filename); + } + + I_EndGlob(glob); +} + +// Load dehacked file from WAD lump. +// If allow_long is set, allow long strings and cheats just for this lump. + +int DEH_LoadLump(int lumpnum, boolean allow_long, boolean allow_error) +{ + deh_context_t *context; + boolean had_error; + + if (!deh_initialized) + { + DEH_Init(); + } + + // Reset all special flags to defaults. + deh_allow_long_strings = allow_long; + deh_allow_long_cheats = allow_long; + deh_allow_extended_strings = false; + + context = DEH_OpenLump(lumpnum); + + if (context == NULL) + { + fprintf(stderr, "DEH_LoadFile: Unable to open lump %i\n", lumpnum); + return 0; + } + + DEH_ParseContext(context); + + had_error = DEH_HadError(context); + + DEH_CloseFile(context); + + // If there was an error while parsing, abort with an error, but allow + // errors to just be ignored if allow_error=true. + if (!allow_error && had_error) + { + I_Error("Error parsing dehacked lump"); + } + + return 1; +} + +int DEH_LoadLumpByName(const char *name, boolean allow_long, boolean allow_error) +{ + int lumpnum; + + lumpnum = W_CheckNumForName(name); + + if (lumpnum == -1) + { + fprintf(stderr, "DEH_LoadLumpByName: '%s' lump not found\n", name); + return 0; + } + + return DEH_LoadLump(lumpnum, allow_long, allow_error); +} + +// Check the command line for -deh argument, and others. +void DEH_ParseCommandLine(void) +{ + char *filename; + int p; + + //! + // @arg + // @category mod + // + // Load the given dehacked patch(es) + // + + p = M_CheckParm("-deh"); + + if (p > 0) + { + ++p; + + while (p < myargc && myargv[p][0] != '-') + { + filename = D_TryFindWADByName(myargv[p]); + DEH_LoadFile(filename); + free(filename); + ++p; + } + } +} + diff --git a/games/NXDoom/src/deh_main.h b/games/NXDoom/src/deh_main.h new file mode 100644 index 00000000000..9ab8704020a --- /dev/null +++ b/games/NXDoom/src/deh_main.h @@ -0,0 +1,48 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dehacked entrypoint and common code +// + +#ifndef DEH_MAIN_H +#define DEH_MAIN_H + +#include "doomtype.h" +#include "deh_str.h" +#include "sha1.h" + +// These are the limits that dehacked uses (from dheinit.h in the dehacked +// source). If these limits are exceeded, it does not generate an error, but +// a warning is displayed. + +#define DEH_VANILLA_NUMSTATES 966 +#define DEH_VANILLA_NUMSFX 107 + +void DEH_ParseCommandLine(void); +int DEH_LoadFile(const char *filename); +void DEH_AutoLoadPatches(const char *path); +int DEH_LoadLump(int lumpnum, boolean allow_long, boolean allow_error); +int DEH_LoadLumpByName(const char *name, boolean allow_long, boolean allow_error); + +boolean DEH_ParseAssignment(char *line, char **variable_name, char **value); + +void DEH_Checksum(sha1_digest_t digest); + +extern boolean deh_allow_extended_strings; +extern boolean deh_allow_long_strings; +extern boolean deh_allow_long_cheats; +extern boolean deh_apply_cheats; + +#endif /* #ifndef DEH_MAIN_H */ + diff --git a/games/NXDoom/src/deh_mapping.c b/games/NXDoom/src/deh_mapping.c new file mode 100644 index 00000000000..f96508b9c7d --- /dev/null +++ b/games/NXDoom/src/deh_mapping.c @@ -0,0 +1,200 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dehacked "mapping" code +// Allows the fields in structures to be mapped out and accessed by +// name +// + +#include +#include +#include + +#include "doomtype.h" +#include "i_system.h" +#include "m_misc.h" + +#include "deh_mapping.h" + +static deh_mapping_entry_t *GetMappingEntryByName(deh_context_t *context, + deh_mapping_t *mapping, + char *name) +{ + int i; + + for (i=0; mapping->entries[i].name != NULL; ++i) + { + deh_mapping_entry_t *entry = &mapping->entries[i]; + + if (!strcasecmp(entry->name, name)) + { + if (entry->location == NULL) + { + DEH_Warning(context, "Field '%s' is unsupported", name); + return NULL; + } + + return entry; + } + } + + // Not found. + + DEH_Warning(context, "Field named '%s' not found", name); + + return NULL; +} + +// +// Get the location of the specified field in the specified structure. +// + +static void *GetStructField(void *structptr, + deh_mapping_t *mapping, + deh_mapping_entry_t *entry) +{ + unsigned int offset; + + offset = (uint8_t *)entry->location - (uint8_t *)mapping->base; + + return (uint8_t *)structptr + offset; +} + +// +// Set the value of a particular field in a structure by name +// + +boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, + void *structptr, char *name, int value) +{ + deh_mapping_entry_t *entry; + void *location; + + entry = GetMappingEntryByName(context, mapping, name); + + if (entry == NULL) + { + return false; + } + + // Sanity check: + + if (entry->is_string) + { + DEH_Error(context, "Tried to set '%s' as integer (BUG)", name); + return false; + } + + location = GetStructField(structptr, mapping, entry); + + // printf("Setting %p::%s to %i (%i bytes)\n", + // structptr, name, value, entry->size); + + // Set field content based on its type: + + switch (entry->size) + { + case 1: + * ((uint8_t *) location) = value; + break; + case 2: + * ((uint16_t *) location) = value; + break; + case 4: + * ((uint32_t *) location) = value; + break; + default: + DEH_Error(context, "Unknown field type for '%s' (BUG)", name); + return false; + } + + return true; +} + +// +// Set the value of a string field in a structure by name +// + +boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, + void *structptr, char *name, char *value) +{ + deh_mapping_entry_t *entry; + void *location; + + entry = GetMappingEntryByName(context, mapping, name); + + if (entry == NULL) + { + return false; + } + + // Sanity check: + + if (!entry->is_string) + { + DEH_Error(context, "Tried to set '%s' as string (BUG)", name); + return false; + } + + location = GetStructField(structptr, mapping, entry); + + // Copy value into field: + + M_StringCopy(location, value, entry->size); + + return true; +} + +void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping, + void *structptr) +{ + int i; + + // Go through each mapping + + for (i=0; mapping->entries[i].name != NULL; ++i) + { + deh_mapping_entry_t *entry = &mapping->entries[i]; + void *location; + + if (entry->location == NULL) + { + // Unsupported field + + continue; + } + + // Add in data for this field + + location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base); + + switch (entry->size) + { + case 1: + SHA1_UpdateInt32(context, *((uint8_t *) location)); + break; + case 2: + SHA1_UpdateInt32(context, *((uint16_t *) location)); + break; + case 4: + SHA1_UpdateInt32(context, *((uint32_t *) location)); + break; + default: + I_Error("Unknown dehacked mapping field type for '%s' (BUG)", + entry->name); + break; + } + } +} + diff --git a/games/NXDoom/src/deh_mapping.h b/games/NXDoom/src/deh_mapping.h new file mode 100644 index 00000000000..e71468c4fe1 --- /dev/null +++ b/games/NXDoom/src/deh_mapping.h @@ -0,0 +1,93 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dehacked "mapping" code +// Allows the fields in structures to be mapped out and accessed by +// name +// + +#ifndef DEH_MAPPING_H +#define DEH_MAPPING_H + +#include "doomtype.h" +#include "deh_io.h" +#include "sha1.h" + +#define DEH_BEGIN_MAPPING(mapping_name, structname) \ + static structname deh_mapping_base; \ + static deh_mapping_t mapping_name = \ + { \ + &deh_mapping_base, \ + { + +#define DEH_MAPPING(deh_name, fieldname) \ + {deh_name, &deh_mapping_base.fieldname, \ + sizeof(deh_mapping_base.fieldname), \ + false}, + +#define DEH_MAPPING_STRING(deh_name, fieldname) \ + {deh_name, &deh_mapping_base.fieldname, \ + sizeof(deh_mapping_base.fieldname), \ + true}, + +#define DEH_UNSUPPORTED_MAPPING(deh_name) \ + {deh_name, NULL, -1, false}, + +#define DEH_END_MAPPING \ + {NULL, NULL, -1} \ + } \ + }; + + + +#define MAX_MAPPING_ENTRIES 32 + +typedef struct deh_mapping_s deh_mapping_t; +typedef struct deh_mapping_entry_s deh_mapping_entry_t; + +struct deh_mapping_entry_s +{ + // field name + + const char *name; + + // location relative to the base in the deh_mapping_t struct + // If this is NULL, it is an unsupported mapping + + void *location; + + // field size + + int size; + + // if true, this is a string value. + + boolean is_string; +}; + +struct deh_mapping_s +{ + void *base; + deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES]; +}; + +boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, + void *structptr, char *name, int value); +boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, + void *structptr, char *name, char *value); +void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping, + void *structptr); + +#endif /* #ifndef DEH_MAPPING_H */ + diff --git a/games/NXDoom/src/deh_str.c b/games/NXDoom/src/deh_str.c new file mode 100644 index 00000000000..76af188ae0c --- /dev/null +++ b/games/NXDoom/src/deh_str.c @@ -0,0 +1,433 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses Text substitution sections in dehacked files +// + +#include +#include +#include +#include + +#include "doomtype.h" +#include "deh_str.h" +#include "m_misc.h" + +#include "z_zone.h" + +typedef struct +{ + char *from_text; + char *to_text; +} deh_substitution_t; + +static deh_substitution_t **hash_table = NULL; +static int hash_table_entries; +static int hash_table_length = -1; + +// This is the algorithm used by glib + +static unsigned int strhash(const char *s) +{ + const char *p = s; + unsigned int h = *p; + + if (h) + { + for (p += 1; *p; p++) + h = (h << 5) - h + *p; + } + + return h; +} + +static deh_substitution_t *SubstitutionForString(const char *s) +{ + int entry; + + // Fallback if we have not initialized the hash table yet + if (hash_table_length < 0) + return NULL; + + entry = strhash(s) % hash_table_length; + + while (hash_table[entry] != NULL) + { + if (!strcmp(hash_table[entry]->from_text, s)) + { + // substitution found! + return hash_table[entry]; + } + + entry = (entry + 1) % hash_table_length; + } + + // no substitution found + return NULL; +} + +// Look up a string to see if it has been replaced with something else +// This will be used throughout the program to substitute text + +const char *DEH_String(const char *s) +{ + deh_substitution_t *subst; + + subst = SubstitutionForString(s); + + if (subst != NULL) + { + return subst->to_text; + } + else + { + return s; + } +} + +static void InitHashTable(void) +{ + // init hash table + + hash_table_entries = 0; + hash_table_length = 16; + hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length, + PU_STATIC, NULL); + memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length); +} + +static void DEH_AddToHashtable(deh_substitution_t *sub); + +static void IncreaseHashtable(void) +{ + deh_substitution_t **old_table; + int old_table_length; + int i; + + // save the old table + + old_table = hash_table; + old_table_length = hash_table_length; + + // double the size + + hash_table_length *= 2; + hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length, + PU_STATIC, NULL); + memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length); + + // go through the old table and insert all the old entries + + for (i=0; i 6) + { + IncreaseHashtable(); + } + + // find where to insert it + entry = strhash(sub->from_text) % hash_table_length; + + while (hash_table[entry] != NULL) + { + entry = (entry + 1) % hash_table_length; + } + + hash_table[entry] = sub; + ++hash_table_entries; +} + +void DEH_AddStringReplacement(const char *from_text, const char *to_text) +{ + deh_substitution_t *sub; + size_t len; + + // Initialize the hash table if this is the first time + if (hash_table_length < 0) + { + InitHashTable(); + } + + // Check to see if there is an existing substitution already in place. + sub = SubstitutionForString(from_text); + + if (sub != NULL) + { + Z_Free(sub->to_text); + + len = strlen(to_text) + 1; + sub->to_text = Z_Malloc(len, PU_STATIC, NULL); + memcpy(sub->to_text, to_text, len); + } + else + { + // We need to allocate a new substitution. + sub = Z_Malloc(sizeof(*sub), PU_STATIC, 0); + + // We need to create our own duplicates of the provided strings. + len = strlen(from_text) + 1; + sub->from_text = Z_Malloc(len, PU_STATIC, NULL); + memcpy(sub->from_text, from_text, len); + + len = strlen(to_text) + 1; + sub->to_text = Z_Malloc(len, PU_STATIC, NULL); + memcpy(sub->to_text, to_text, len); + + DEH_AddToHashtable(sub); + } +} + +typedef enum +{ + FORMAT_ARG_INVALID, + FORMAT_ARG_INT, + FORMAT_ARG_FLOAT, + FORMAT_ARG_CHAR, + FORMAT_ARG_STRING, + FORMAT_ARG_PTR, + FORMAT_ARG_SAVE_POS +} format_arg_t; + +// Get the type of a format argument. +// We can mix-and-match different format arguments as long as they +// are for the same data type. + +static format_arg_t FormatArgumentType(char c) +{ + switch (c) + { + case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': + return FORMAT_ARG_INT; + + case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': + case 'a': case 'A': + return FORMAT_ARG_FLOAT; + + case 'c': case 'C': + return FORMAT_ARG_CHAR; + + case 's': case 'S': + return FORMAT_ARG_STRING; + + case 'p': + return FORMAT_ARG_PTR; + + case 'n': + return FORMAT_ARG_SAVE_POS; + + default: + return FORMAT_ARG_INVALID; + } +} + +// Given the specified string, get the type of the first format +// string encountered. + +static format_arg_t NextFormatArgument(const char **str) +{ + format_arg_t argtype; + + // Search for the '%' starting the next string. + + while (**str != '\0') + { + if (**str == '%') + { + ++*str; + + // Don't stop for double-%s. + + if (**str != '%') + { + break; + } + } + + ++*str; + } + + // Find the type of the format string. + + while (**str != '\0') + { + argtype = FormatArgumentType(**str); + + if (argtype != FORMAT_ARG_INVALID) + { + ++*str; + + return argtype; + } + + ++*str; + } + + // Stop searching, we have reached the end. + + *str = NULL; + + return FORMAT_ARG_INVALID; +} + +// Check if the specified argument type is a valid replacement for +// the original. + +static boolean ValidArgumentReplacement(format_arg_t original, + format_arg_t replacement) +{ + // In general, the original and replacement types should be + // identical. However, there are some cases where the replacement + // is valid and the types don't match. + + // Characters can be represented as ints. + + if (original == FORMAT_ARG_CHAR && replacement == FORMAT_ARG_INT) + { + return true; + } + + // Strings are pointers. + + if (original == FORMAT_ARG_STRING && replacement == FORMAT_ARG_PTR) + { + return true; + } + + return original == replacement; +} + +// Return true if the specified string contains no format arguments. + +static boolean ValidFormatReplacement(const char *original, const char *replacement) +{ + const char *rover1; + const char *rover2; + int argtype1, argtype2; + + // Check each argument in turn and compare types. + + rover1 = original; rover2 = replacement; + + for (;;) + { + argtype1 = NextFormatArgument(&rover1); + argtype2 = NextFormatArgument(&rover2); + + if (argtype2 == FORMAT_ARG_INVALID) + { + // No more arguments left to read from the replacement string. + + break; + } + else if (argtype1 == FORMAT_ARG_INVALID) + { + // Replacement string has more arguments than the original. + + return false; + } + else if (!ValidArgumentReplacement(argtype1, argtype2)) + { + // Not a valid replacement argument. + + return false; + } + } + + return true; +} + +// Get replacement format string, checking arguments. + +static const char *FormatStringReplacement(const char *s) +{ + const char *repl; + + repl = DEH_String(s); + + if (!ValidFormatReplacement(s, repl)) + { + printf("WARNING: Unsafe dehacked replacement provided for " + "printf format string: %s\n", s); + + return s; + } + + return repl; +} + +// printf(), performing a replacement on the format string. + +void DEH_printf(const char *fmt, ...) +{ + va_list args; + const char *repl; + + repl = FormatStringReplacement(fmt); + + va_start(args, fmt); + + vprintf(repl, args); + + va_end(args); +} + +// fprintf(), performing a replacement on the format string. + +void DEH_fprintf(FILE *fstream, const char *fmt, ...) +{ + va_list args; + const char *repl; + + repl = FormatStringReplacement(fmt); + + va_start(args, fmt); + + vfprintf(fstream, repl, args); + + va_end(args); +} + +// snprintf(), performing a replacement on the format string. + +void DEH_snprintf(char *buffer, size_t len, const char *fmt, ...) +{ + va_list args; + const char *repl; + + repl = FormatStringReplacement(fmt); + + va_start(args, fmt); + + M_vsnprintf(buffer, len, repl, args); + + va_end(args); +} + diff --git a/games/NXDoom/src/deh_str.h b/games/NXDoom/src/deh_str.h new file mode 100644 index 00000000000..d547de6b9f4 --- /dev/null +++ b/games/NXDoom/src/deh_str.h @@ -0,0 +1,45 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dehacked string replacements +// + +#ifndef DEH_STR_H +#define DEH_STR_H + +#include + +#include "doomtype.h" + +// Used to do dehacked text substitutions throughout the program + +const char *DEH_String(const char *s) PRINTF_ARG_ATTR(1); +void DEH_printf(const char *fmt, ...) PRINTF_ATTR(1, 2); +void DEH_fprintf(FILE *fstream, const char *fmt, ...) PRINTF_ATTR(2, 3); +void DEH_snprintf(char *buffer, size_t len, const char *fmt, ...) PRINTF_ATTR(3, 4); +void DEH_AddStringReplacement(const char *from_text, const char *to_text); + + +#if 0 +// Static macro versions of the functions above + +#define DEH_String(x) (x) +#define DEH_printf printf +#define DEH_fprintf fprintf +#define DEH_snprintf snprintf + +#endif + +#endif /* #ifndef DEH_STR_H */ + diff --git a/games/NXDoom/src/deh_text.c b/games/NXDoom/src/deh_text.c new file mode 100644 index 00000000000..9e621b43832 --- /dev/null +++ b/games/NXDoom/src/deh_text.c @@ -0,0 +1,113 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses Text substitution sections in dehacked files +// + +#include +#include +#include + +#include "doomtype.h" + +#include "z_zone.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" + +// Given a string length, find the maximum length of a +// string that can replace it. + +static int TXT_MaxStringLength(int len) +{ + // Enough bytes for the string and the NUL terminator + + len += 1; + + // All strings in doom.exe are on 4-byte boundaries, so we may be able + // to support a slightly longer string. + // Extend up to the next 4-byte boundary + + len += (4 - (len % 4)) % 4; + + // Less one for the NUL terminator. + + return len - 1; +} + +static void *DEH_TextStart(deh_context_t *context, char *line) +{ + char *from_text, *to_text; + int fromlen, tolen; + int i; + + if (sscanf(line, "Text %i %i", &fromlen, &tolen) != 2) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + // Only allow string replacements that are possible in Vanilla Doom. + // Chocolate Doom is unforgiving! + + if (!deh_allow_long_strings && tolen > TXT_MaxStringLength(fromlen)) + { + DEH_Error(context, "Replacement string is longer than the maximum " + "possible in doom.exe"); + return NULL; + } + + from_text = malloc(fromlen + 1); + to_text = malloc(tolen + 1); + + // read in the "from" text + + for (i=0; i + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" + +1 VERSIONINFO +PRODUCTVERSION @WINDOWS_RC_VERSION@ +FILEVERSION @WINDOWS_RC_VERSION@ +FILETYPE 1 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "@PACKAGE_VERSION@.0" + VALUE "FileDescription", "@PACKAGE_STRING@" + VALUE "InternalName", "@PACKAGE_TARNAME@" + VALUE "CompanyName", "@PACKAGE_BUGREPORT@" + VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" + VALUE "ProductName", "@PACKAGE_NAME@" + VALUE "ProductVersion", "@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + diff --git a/games/NXDoom/src/doom/.gitignore b/games/NXDoom/src/doom/.gitignore new file mode 100644 index 00000000000..d4e88e5a219 --- /dev/null +++ b/games/NXDoom/src/doom/.gitignore @@ -0,0 +1,5 @@ +Makefile +Makefile.in +.deps +tags +TAGS diff --git a/games/NXDoom/src/doom/CMakeLists.txt b/games/NXDoom/src/doom/CMakeLists.txt new file mode 100644 index 00000000000..6e878a0f139 --- /dev/null +++ b/games/NXDoom/src/doom/CMakeLists.txt @@ -0,0 +1,91 @@ +add_library(doom STATIC + am_map.c am_map.h + deh_ammo.c + deh_bexstr.c + deh_cheat.c + deh_doom.c + deh_frame.c + deh_misc.c deh_misc.h + deh_ptr.c + deh_sound.c + deh_thing.c + deh_weapon.c + d_englsh.h + d_items.c d_items.h + d_main.c d_main.h + d_net.c + doomdata.h + doomdef.c doomdef.h + doomstat.c doomstat.h + d_player.h + dstrings.c dstrings.h + d_textur.h + d_think.h + f_finale.c f_finale.h + f_wipe.c f_wipe.h + g_game.c g_game.h + hu_lib.c hu_lib.h + hu_stuff.c hu_stuff.h + info.c info.h + m_menu.c m_menu.h + m_random.c m_random.h + p_ceilng.c + p_doors.c + p_enemy.c + p_floor.c + p_inter.c p_inter.h + p_lights.c + p_local.h + p_map.c + p_maputl.c + p_mobj.c p_mobj.h + p_plats.c + p_pspr.c p_pspr.h + p_saveg.c p_saveg.h + p_setup.c p_setup.h + p_sight.c + p_spec.c p_spec.h + p_switch.c + p_telept.c + p_tick.c p_tick.h + p_user.c + r_bsp.c r_bsp.h + r_data.c r_data.h + r_defs.h + r_draw.c r_draw.h + r_local.h + r_main.c r_main.h + r_plane.c r_plane.h + r_segs.c r_segs.h + r_sky.c r_sky.h + r_state.h + r_things.c r_things.h + s_sound.c s_sound.h + sounds.c sounds.h + statdump.c statdump.h + st_lib.c st_lib.h + st_stuff.c st_stuff.h + wi_stuff.c wi_stuff.h) + +target_include_directories(doom PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") + +if (DEFINED EMSCRIPTEN) + set(SDL_FLAGS "-s USE_SDL=2") + if(ENABLE_SDL2_MIXER) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") + endif() + if(ENABLE_SDL2_NET) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") + endif() +else() + set(SDL_LINK_LIBS SDL2::SDL2) + if(ENABLE_SDL2_MIXER) + list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) + endif() + if(ENABLE_SDL2_NET) + list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) + endif() +endif() +target_link_libraries(doom ${SDL_LINK_LIBS}) +set_target_properties(doom PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") +set_target_properties(doom PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/doom/Makefile.am b/games/NXDoom/src/doom/Makefile.am new file mode 100644 index 00000000000..1f4e8c48efc --- /dev/null +++ b/games/NXDoom/src/doom/Makefile.am @@ -0,0 +1,83 @@ +AM_CFLAGS = -I$(top_srcdir)/src @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ + +EXTRA_DIST = \ + CMakeLists.txt \ + doom_icon.c + +noinst_LIBRARIES=libdoom.a + +libdoom_a_SOURCES = \ +am_map.c am_map.h \ +deh_ammo.c \ +deh_bexstr.c \ +deh_cheat.c \ +deh_doom.c \ +deh_frame.c \ +deh_misc.c deh_misc.h \ +deh_ptr.c \ +deh_sound.c \ +deh_thing.c \ +deh_weapon.c \ + d_englsh.h \ +d_items.c d_items.h \ +d_main.c d_main.h \ +d_net.c \ + doomdata.h \ +doomdef.c doomdef.h \ +doomstat.c doomstat.h \ + d_player.h \ +dstrings.c dstrings.h \ + d_textur.h \ + d_think.h \ +f_finale.c f_finale.h \ +f_wipe.c f_wipe.h \ +g_game.c g_game.h \ +hu_lib.c hu_lib.h \ +hu_stuff.c hu_stuff.h \ +info.c info.h \ +m_menu.c m_menu.h \ +m_random.c m_random.h \ +p_ceilng.c \ +p_doors.c \ +p_enemy.c \ +p_floor.c \ +p_inter.c p_inter.h \ +p_lights.c \ + p_local.h \ +p_map.c \ +p_maputl.c \ +p_mobj.c p_mobj.h \ +p_plats.c \ +p_pspr.c p_pspr.h \ +p_saveg.c p_saveg.h \ +p_setup.c p_setup.h \ +p_sight.c \ +p_spec.c p_spec.h \ +p_switch.c \ +p_telept.c \ +p_tick.c p_tick.h \ +p_user.c \ +r_bsp.c r_bsp.h \ +r_data.c r_data.h \ + r_defs.h \ +r_draw.c r_draw.h \ + r_local.h \ +r_main.c r_main.h \ +r_plane.c r_plane.h \ +r_segs.c r_segs.h \ +r_sky.c r_sky.h \ + r_state.h \ +r_things.c r_things.h \ +s_sound.c s_sound.h \ +sounds.c sounds.h \ +statdump.c statdump.h \ +st_lib.c st_lib.h \ +st_stuff.c st_stuff.h \ +wi_stuff.c wi_stuff.h + +if HAVE_ICONS + +doom_icon.c : $(top_builddir)/data/doom.png + $(top_builddir)/data/convert-icon $(top_builddir)/data/doom.png $@ + +endif diff --git a/games/NXDoom/src/doom/am_map.c b/games/NXDoom/src/doom/am_map.c new file mode 100644 index 00000000000..150098edafb --- /dev/null +++ b/games/NXDoom/src/doom/am_map.c @@ -0,0 +1,1374 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: the automap code +// + + +#include + +#include "deh_main.h" + +#include "z_zone.h" +#include "doomkeys.h" +#include "doomdef.h" +#include "st_stuff.h" +#include "p_local.h" +#include "w_wad.h" + +#include "m_cheat.h" +#include "m_controls.h" +#include "m_misc.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" + +// Needs access to LFB. +#include "v_video.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "dstrings.h" + +#include "am_map.h" + + +// For use if I do walls with outsides/insides +#define REDS (256-5*16) +#define REDRANGE 16 +#define BLUES (256-4*16+8) +#define BLUERANGE 8 +#define GREENS (7*16) +#define GREENRANGE 16 +#define GRAYS (6*16) +#define GRAYSRANGE 16 +#define BROWNS (4*16) +#define BROWNRANGE 16 +#define YELLOWS (256-32+7) +#define YELLOWRANGE 1 +#define BLACK 0 +#define WHITE (256-47) + +// Automap colors +#define BACKGROUND BLACK +#define YOURCOLORS WHITE +#define YOURRANGE 0 +#define WALLCOLORS REDS +#define WALLRANGE REDRANGE +#define TSWALLCOLORS GRAYS +#define TSWALLRANGE GRAYSRANGE +#define FDWALLCOLORS BROWNS +#define FDWALLRANGE BROWNRANGE +#define CDWALLCOLORS YELLOWS +#define CDWALLRANGE YELLOWRANGE +#define THINGCOLORS GREENS +#define THINGRANGE GREENRANGE +#define SECRETWALLCOLORS WALLCOLORS +#define SECRETWALLRANGE WALLRANGE +#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) +#define GRIDRANGE 0 +#define XHAIRCOLORS GRAYS + +// drawing stuff + +#define AM_NUMMARKPOINTS 10 + +// scale on entry +#define INITSCALEMTOF (.2*FRACUNIT) +// how much the automap moves window per tic in frame-buffer coordinates +// moves 140 pixels in 1 second +#define F_PANINC 4 +// how much zoom-in per tic +// goes to 2x in 1 second +#define M_ZOOMIN ((int) (1.02*FRACUNIT)) +// how much zoom-out per tic +// pulls out to 0.5x in 1 second +#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) + +// translates between frame-buffer and map distances +#define FTOM(x) FixedMul(((x)<>FRACBITS) +// translates between frame-buffer and map coordinates +#define CXMTOF(x) (f_x + MTOF((x)-m_x)) +#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) + +// the following is crap +#define LINE_NEVERSEE ML_DONTDRAW + +typedef struct +{ + int x, y; +} fpoint_t; + +typedef struct +{ + fpoint_t a, b; +} fline_t; + +typedef struct +{ + fixed_t x,y; +} mpoint_t; + +typedef struct +{ + mpoint_t a, b; +} mline_t; + +typedef struct +{ + fixed_t slp, islp; +} islope_t; + + + +// +// The vector graphics for the automap. +// A line drawing of the player pointing right, +// starting from the middle. +// +#define R ((8*PLAYERRADIUS)/7) +mline_t player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/4 } }, // -----> + { { R, 0 }, { R-R/2, -R/4 } }, + { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> + { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> + { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } +}; +#undef R + +#define R ((8*PLAYERRADIUS)/7) +mline_t cheat_player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/6 } }, // -----> + { { R, 0 }, { R-R/2, -R/6 } }, + { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> + { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> + { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, + { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> + { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, + { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, + { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> + { { -R/6, -R/6 }, { 0, -R/6 } }, + { { 0, -R/6 }, { 0, R/4 } }, + { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> + { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, + { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } +}; +#undef R + +#define R (FRACUNIT) +mline_t triangle_guy[] = { + { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } }, + { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } }, + { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } } +}; +#undef R + +#define R (FRACUNIT) +mline_t thintriangle_guy[] = { + { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, + { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, + { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } +}; +#undef R + + + + +static int cheating = 0; +static int grid = 0; + +boolean automapactive = false; +static int finit_width = SCREENWIDTH; +static int finit_height = SCREENHEIGHT - ST_HEIGHT; + +// location of window on screen +static int f_x; +static int f_y; + +// size of window on screen +static int f_w; +static int f_h; + +static int lightlev; // used for funky strobing effect +static pixel_t* fb; // pseudo-frame buffer +static int amclock; + +static mpoint_t m_paninc; // how far the window pans each tic (map coords) +static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) +static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) + +static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) +static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) + +// +// width/height of window on map (map coords) +// +static fixed_t m_w; +static fixed_t m_h; + +// based on level size +static fixed_t min_x; +static fixed_t min_y; +static fixed_t max_x; +static fixed_t max_y; + +static fixed_t max_w; // max_x-min_x, +static fixed_t max_h; // max_y-min_y + +// based on player size +static fixed_t min_w; +static fixed_t min_h; + + +static fixed_t min_scale_mtof; // used to tell when to stop zooming out +static fixed_t max_scale_mtof; // used to tell when to stop zooming in + +// old stuff for recovery later +static fixed_t old_m_w, old_m_h; +static fixed_t old_m_x, old_m_y; + +// old location used by the Follower routine +static mpoint_t f_oldloc; + +// used by MTOF to scale from map-to-frame-buffer coords +static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; +// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) +static fixed_t scale_ftom; + +static player_t *plr; // the player represented by an arrow + +static patch_t *marknums[10]; // numbers used for marking by the automap +static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are +static int markpointnum = 0; // next point to be assigned + +static int followplayer = 1; // specifies whether to follow the player around + +cheatseq_t cheat_amap = CHEAT("iddt", 0); + +static boolean stopped = true; + +// Calculates the slope and slope according to the x-axis of a line +// segment in map coordinates (with the upright y-axis n' all) so +// that it can be used with the brain-dead drawing stuff. + +void +AM_getIslope +( mline_t* ml, + islope_t* is ) +{ + int dx, dy; + + dy = ml->a.y - ml->b.y; + dx = ml->b.x - ml->a.x; + if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); + else is->islp = FixedDiv(dx, dy); + if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); + else is->slp = FixedDiv(dy, dx); + +} + +// +// +// +void AM_activateNewScale(void) +{ + m_x += m_w/2; + m_y += m_h/2; + m_w = FTOM(f_w); + m_h = FTOM(f_h); + m_x -= m_w/2; + m_y -= m_h/2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + +// +// +// +void AM_saveScaleAndLoc(void) +{ + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; +} + +// +// +// +void AM_restoreScaleAndLoc(void) +{ + + m_w = old_m_w; + m_h = old_m_h; + if (!followplayer) + { + m_x = old_m_x; + m_y = old_m_y; + } else { + m_x = plr->mo->x - m_w/2; + m_y = plr->mo->y - m_h/2; + } + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // Change the scaling multipliers + scale_mtof = FixedDiv(f_w< max_x) + max_x = vertexes[i].x; + + if (vertexes[i].y < min_y) + min_y = vertexes[i].y; + else if (vertexes[i].y > max_y) + max_y = vertexes[i].y; + } + + max_w = max_x - min_x; + max_h = max_y - min_y; + + min_w = 2*PLAYERRADIUS; // const? never changed? + min_h = 2*PLAYERRADIUS; + + a = FixedDiv(f_w< max_x) + m_x = max_x - m_w/2; + else if (m_x + m_w/2 < min_x) + m_x = min_x - m_w/2; + + if (m_y + m_h/2 > max_y) + m_y = max_y - m_h/2; + else if (m_y + m_h/2 < min_y) + m_y = min_y - m_h/2; + + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + + +// +// +// +void AM_initVariables(void) +{ + int pnum; + static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 }; + + automapactive = true; + fb = I_VideoBuffer; + + f_oldloc.x = INT_MAX; + amclock = 0; + lightlev = 0; + + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; + + m_w = FTOM(f_w); + m_h = FTOM(f_h); + + // find player to center on initially + if (playeringame[consoleplayer]) + { + plr = &players[consoleplayer]; + } + else + { + plr = &players[0]; + + for (pnum=0;pnummo->x - m_w/2; + m_y = plr->mo->y - m_h/2; + AM_changeWindowLoc(); + + // for saving & restoring + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + + // inform the status bar of the change + ST_Responder(&st_notify); + +} + +// +// +// +void AM_loadPics(void) +{ + int i; + char namebuf[9]; + + for (i=0;i<10;i++) + { + DEH_snprintf(namebuf, 9, "AMMNUM%d", i); + marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); + } + +} + +void AM_unloadPics(void) +{ + int i; + char namebuf[9]; + + for (i=0;i<10;i++) + { + DEH_snprintf(namebuf, 9, "AMMNUM%d", i); + W_ReleaseLumpName(namebuf); + } +} + +void AM_clearMarks(void) +{ + int i; + + for (i=0;i max_scale_mtof) + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +} + + + + +// +// +// +void AM_Stop (void) +{ + static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 }; + + AM_unloadPics(); + automapactive = false; + ST_Responder(&st_notify); + stopped = true; +} + +// +// +// +void AM_Start (void) +{ + static int lastlevel = -1, lastepisode = -1; + + if (!stopped) AM_Stop(); + stopped = false; + if (lastlevel != gamemap || lastepisode != gameepisode) + { + AM_LevelInit(); + lastlevel = gamemap; + lastepisode = gameepisode; + } + AM_initVariables(); + AM_loadPics(); +} + +// +// set the window scale to the maximum size +// +void AM_minOutWindowScale(void) +{ + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + +// +// set the window scale to the minimum size +// +void AM_maxOutWindowScale(void) +{ + scale_mtof = max_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + + +// +// Handle events (user inputs) in automap mode +// +boolean +AM_Responder +( event_t* ev ) +{ + + int rc; + static int bigstate=0; + static char buffer[20]; + int key; + + rc = false; + + if (ev->type == ev_joystick && joybautomap >= 0 + && (ev->data1 & (1 << joybautomap)) != 0) + { + joywait = I_GetTime() + 5; + + if (!automapactive) + { + AM_Start (); + viewactive = false; + } + else + { + bigstate = 0; + viewactive = true; + AM_Stop (); + } + + return true; + } + + if (!automapactive) + { + if (ev->type == ev_keydown && ev->data1 == key_map_toggle) + { + AM_Start (); + viewactive = false; + rc = true; + } + } + else if (ev->type == ev_keydown) + { + rc = true; + key = ev->data1; + + if (key == key_map_east) // pan right + { + if (!followplayer) m_paninc.x = FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_west) // pan left + { + if (!followplayer) m_paninc.x = -FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_north) // pan up + { + if (!followplayer) m_paninc.y = FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_south) // pan down + { + if (!followplayer) m_paninc.y = -FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_zoomout) // zoom out + { + mtof_zoommul = M_ZOOMOUT; + ftom_zoommul = M_ZOOMIN; + } + else if (key == key_map_zoomin) // zoom in + { + mtof_zoommul = M_ZOOMIN; + ftom_zoommul = M_ZOOMOUT; + } + else if (key == key_map_toggle) + { + bigstate = 0; + viewactive = true; + AM_Stop (); + } + else if (key == key_map_maxzoom) + { + bigstate = !bigstate; + if (bigstate) + { + AM_saveScaleAndLoc(); + AM_minOutWindowScale(); + } + else AM_restoreScaleAndLoc(); + } + else if (key == key_map_follow) + { + followplayer = !followplayer; + f_oldloc.x = INT_MAX; + if (followplayer) + plr->message = DEH_String(AMSTR_FOLLOWON); + else + plr->message = DEH_String(AMSTR_FOLLOWOFF); + } + else if (key == key_map_grid) + { + grid = !grid; + if (grid) + plr->message = DEH_String(AMSTR_GRIDON); + else + plr->message = DEH_String(AMSTR_GRIDOFF); + } + else if (key == key_map_mark) + { + M_snprintf(buffer, sizeof(buffer), "%s %d", + DEH_String(AMSTR_MARKEDSPOT), markpointnum); + plr->message = buffer; + AM_addMark(); + } + else if (key == key_map_clearmark) + { + AM_clearMarks(); + plr->message = DEH_String(AMSTR_MARKSCLEARED); + } + else + { + rc = false; + } + + if ((!deathmatch || gameversion <= exe_doom_1_8) + && cht_CheckCheat(&cheat_amap, ev->data2)) + { + rc = false; + cheating = (cheating + 1) % 3; + } + } + else if (ev->type == ev_keyup) + { + rc = false; + key = ev->data1; + + if (key == key_map_east) + { + if (!followplayer) m_paninc.x = 0; + } + else if (key == key_map_west) + { + if (!followplayer) m_paninc.x = 0; + } + else if (key == key_map_north) + { + if (!followplayer) m_paninc.y = 0; + } + else if (key == key_map_south) + { + if (!followplayer) m_paninc.y = 0; + } + else if (key == key_map_zoomout || key == key_map_zoomin) + { + mtof_zoommul = FRACUNIT; + ftom_zoommul = FRACUNIT; + } + } + + return rc; + +} + + +// +// Zooming +// +void AM_changeWindowScale(void) +{ + + // Change the scaling multipliers + scale_mtof = FixedMul(scale_mtof, mtof_zoommul); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + + if (scale_mtof < min_scale_mtof) + AM_minOutWindowScale(); + else if (scale_mtof > max_scale_mtof) + AM_maxOutWindowScale(); + else + AM_activateNewScale(); +} + + +// +// +// +void AM_doFollowPlayer(void) +{ + + if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) + { + m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; + m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + f_oldloc.x = plr->mo->x; + f_oldloc.y = plr->mo->y; + + // m_x = FTOM(MTOF(plr->mo->x - m_w/2)); + // m_y = FTOM(MTOF(plr->mo->y - m_h/2)); + // m_x = plr->mo->x - m_w/2; + // m_y = plr->mo->y - m_h/2; + + } + +} + +// +// +// +void AM_updateLightLev(void) +{ + static int nexttic = 0; + //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; + static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; + static int litelevelscnt = 0; + + // Change light level + if (amclock>nexttic) + { + lightlev = litelevels[litelevelscnt++]; + if (litelevelscnt == arrlen(litelevels)) litelevelscnt = 0; + nexttic = amclock + 6 - (amclock % 6); + } + +} + + +// +// Updates on Game Tick +// +void AM_Ticker (void) +{ + + if (!automapactive) + return; + + amclock++; + + if (followplayer) + AM_doFollowPlayer(); + + // Change the zoom if necessary + if (ftom_zoommul != FRACUNIT) + AM_changeWindowScale(); + + // Change x,y location + if (m_paninc.x || m_paninc.y) + AM_changeWindowLoc(); + + // Update light level + // AM_updateLightLev(); + +} + + +// +// Clear automap frame buffer. +// +void AM_clearFB(int color) +{ + memset(fb, color, f_w*f_h*sizeof(*fb)); +} + + +// +// Automap clipping of lines. +// +// Based on Cohen-Sutherland clipping algorithm but with a slightly +// faster reject and precalculated slopes. If the speed is needed, +// use a hash algorithm to handle the common cases. +// +boolean +AM_clipMline +( mline_t* ml, + fline_t* fl ) +{ + enum + { + LEFT =1, + RIGHT =2, + BOTTOM =4, + TOP =8 + }; + + register int outcode1 = 0; + register int outcode2 = 0; + register int outside; + + fpoint_t tmp; + int dx; + int dy; + + +#define DOOUTCODE(oc, mx, my) \ + (oc) = 0; \ + if ((my) < 0) (oc) |= TOP; \ + else if ((my) >= f_h) (oc) |= BOTTOM; \ + if ((mx) < 0) (oc) |= LEFT; \ + else if ((mx) >= f_w) (oc) |= RIGHT; + + + // do trivial rejects and outcodes + if (ml->a.y > m_y2) + outcode1 = TOP; + else if (ml->a.y < m_y) + outcode1 = BOTTOM; + + if (ml->b.y > m_y2) + outcode2 = TOP; + else if (ml->b.y < m_y) + outcode2 = BOTTOM; + + if (outcode1 & outcode2) + return false; // trivially outside + + if (ml->a.x < m_x) + outcode1 |= LEFT; + else if (ml->a.x > m_x2) + outcode1 |= RIGHT; + + if (ml->b.x < m_x) + outcode2 |= LEFT; + else if (ml->b.x > m_x2) + outcode2 |= RIGHT; + + if (outcode1 & outcode2) + return false; // trivially outside + + // transform to frame-buffer coordinates. + fl->a.x = CXMTOF(ml->a.x); + fl->a.y = CYMTOF(ml->a.y); + fl->b.x = CXMTOF(ml->b.x); + fl->b.y = CYMTOF(ml->b.y); + + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + + if (outcode1 & outcode2) + return false; + + while (outcode1 | outcode2) + { + // may be partially inside box + // find an outside point + if (outcode1) + outside = outcode1; + else + outside = outcode2; + + // clip to each side + if (outside & TOP) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx*(fl->a.y))/dy; + tmp.y = 0; + } + else if (outside & BOTTOM) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy; + tmp.y = f_h-1; + } + else if (outside & RIGHT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx; + tmp.x = f_w-1; + } + else if (outside & LEFT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy*(-fl->a.x))/dx; + tmp.x = 0; + } + else + { + tmp.x = 0; + tmp.y = 0; + } + + if (outside == outcode1) + { + fl->a = tmp; + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + } + else + { + fl->b = tmp; + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + } + + if (outcode1 & outcode2) + return false; // trivially outside + } + + return true; +} +#undef DOOUTCODE + + +// +// Classic Bresenham w/ whatever optimizations needed for speed +// +void +AM_drawFline +( fline_t* fl, + int color ) +{ + register int x; + register int y; + register int dx; + register int dy; + register int sx; + register int sy; + register int ax; + register int ay; + register int d; + + static int fuck = 0; + + // For debugging only + if ( fl->a.x < 0 || fl->a.x >= f_w + || fl->a.y < 0 || fl->a.y >= f_h + || fl->b.x < 0 || fl->b.x >= f_w + || fl->b.y < 0 || fl->b.y >= f_h) + { + DEH_fprintf(stderr, "fuck %d \r", fuck++); + return; + } + +#define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) + + dx = fl->b.x - fl->a.x; + ax = 2 * (dx<0 ? -dx : dx); + sx = dx<0 ? -1 : 1; + + dy = fl->b.y - fl->a.y; + ay = 2 * (dy<0 ? -dy : dy); + sy = dy<0 ? -1 : 1; + + x = fl->a.x; + y = fl->a.y; + + if (ax > ay) + { + d = ay - ax/2; + while (1) + { + PUTDOT(x,y,color); + if (x == fl->b.x) return; + if (d>=0) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } + else + { + d = ax - ay/2; + while (1) + { + PUTDOT(x, y, color); + if (y == fl->b.y) return; + if (d >= 0) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } +} + + +// +// Clip lines, draw visible part sof lines. +// +void +AM_drawMline +( mline_t* ml, + int color ) +{ + static fline_t fl; + + if (AM_clipMline(ml, &fl)) + AM_drawFline(&fl, color); // draws it on frame buffer using fb coords +} + + + +// +// Draws flat (floor/ceiling tile) aligned grid lines. +// +void AM_drawGrid(int color) +{ + fixed_t x, y; + fixed_t start, end; + mline_t ml; + + // Figure out start of vertical gridlines + start = m_x; + if ((start-bmaporgx)%(MAPBLOCKUNITS<x; + l.a.y = lines[i].v1->y; + l.b.x = lines[i].v2->x; + l.b.y = lines[i].v2->y; + if (cheating || (lines[i].flags & ML_MAPPED)) + { + if ((lines[i].flags & LINE_NEVERSEE) && !cheating) + continue; + if (!lines[i].backsector) + { + AM_drawMline(&l, WALLCOLORS+lightlev); + } + else + { + if (lines[i].special == 39) + { // teleporters + AM_drawMline(&l, WALLCOLORS+WALLRANGE/2); + } + else if (lines[i].flags & ML_SECRET) // secret door + { + if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev); + else AM_drawMline(&l, WALLCOLORS+lightlev); + } + else if (lines[i].backsector->floorheight + != lines[i].frontsector->floorheight) { + AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change + } + else if (lines[i].backsector->ceilingheight + != lines[i].frontsector->ceilingheight) { + AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change + } + else if (cheating) { + AM_drawMline(&l, TSWALLCOLORS+lightlev); + } + } + } + else if (plr->powers[pw_allmap]) + { + if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3); + } + } +} + + +// +// Rotation in 2D. +// Used to rotate player arrow line character. +// +void +AM_rotate +( fixed_t* x, + fixed_t* y, + angle_t a ) +{ + fixed_t tmpx; + + tmpx = + FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT]) + - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]); + + *y = + FixedMul(*x,finesine[a>>ANGLETOFINESHIFT]) + + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]); + + *x = tmpx; +} + +void +AM_drawLineCharacter +( mline_t* lineguy, + int lineguylines, + fixed_t scale, + angle_t angle, + int color, + fixed_t x, + fixed_t y ) +{ + int i; + mline_t l; + + for (i=0;imo->angle, WHITE, plr->mo->x, plr->mo->y); + else + AM_drawLineCharacter + (player_arrow, arrlen(player_arrow), 0, plr->mo->angle, + WHITE, plr->mo->x, plr->mo->y); + return; + } + + for (i=0;ipowers[pw_invisibility]) + color = 246; // *close* to black + else + color = their_colors[their_color]; + + AM_drawLineCharacter + (player_arrow, arrlen(player_arrow), 0, p->mo->angle, + color, p->mo->x, p->mo->y); + } + +} + +void +AM_drawThings +( int colors, + int colorrange) +{ + int i; + mobj_t* t; + + for (i=0;iangle, colors+lightlev, t->x, t->y); + t = t->snext; + } + } +} + +void AM_drawMarks(void) +{ + int i, fx, fy, w, h; + + for (i=0;iwidth); + // h = SHORT(marknums[i]->height); + w = 5; // because something's wrong with the wad, i guess + h = 6; // because something's wrong with the wad, i guess + fx = CXMTOF(markpoints[i].x); + fy = CYMTOF(markpoints[i].y); + if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) + V_DrawPatch(fx, fy, marknums[i]); + } + } + +} + +void AM_drawCrosshair(int color) +{ + fb[(f_w*(f_h+1))/2] = color; // single point for now + +} + +void AM_Drawer (void) +{ + if (!automapactive) return; + + AM_clearFB(BACKGROUND); + if (grid) + AM_drawGrid(GRIDCOLORS); + AM_drawWalls(); + AM_drawPlayers(); + if (cheating==2) + AM_drawThings(THINGCOLORS, THINGRANGE); + AM_drawCrosshair(XHAIRCOLORS); + + AM_drawMarks(); + + V_MarkRect(f_x, f_y, f_w, f_h); + +} diff --git a/games/NXDoom/src/doom/am_map.h b/games/NXDoom/src/doom/am_map.h new file mode 100644 index 00000000000..572d2389bc2 --- /dev/null +++ b/games/NXDoom/src/doom/am_map.h @@ -0,0 +1,49 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// AutoMap module. +// + +#ifndef __AMMAP_H__ +#define __AMMAP_H__ + +#include "d_event.h" +#include "m_cheat.h" + +// Used by ST StatusBar stuff. +#define AM_MSGHEADER (('a'<<24)+('m'<<16)) +#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) +#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) + + +// Called by main loop. +boolean AM_Responder (event_t* ev); + +// Called by main loop. +void AM_Ticker (void); + +// Called by main loop, +// called instead of view drawer if automap active. +void AM_Drawer (void); + +// Called to force the automap to quit +// if the level is completed while it is up. +void AM_Stop (void); + + +extern cheatseq_t cheat_amap; + + +#endif diff --git a/games/NXDoom/src/doom/d_englsh.h b/games/NXDoom/src/doom/d_englsh.h new file mode 100644 index 00000000000..cfb05722c5c --- /dev/null +++ b/games/NXDoom/src/doom/d_englsh.h @@ -0,0 +1,693 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Printed strings for translation. +// English language support (default). +// + +#ifndef __D_ENGLSH__ +#define __D_ENGLSH__ + +// +// Printed strings for translation +// + +// +// D_Main.C +// +#define D_DEVSTR "Development mode ON.\n" +#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n" + +// +// M_Menu.C +// +#define PRESSKEY "press a key." +#define PRESSYN "press y or n." +#define QUITMSG "are you sure you want to\nquit this great game?" +#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY +#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY +#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY +#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY +#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN +#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN + +#define NEWGAME \ +"you can't start a new game\n"\ +"while in a network game.\n\n"PRESSKEY + +#define NIGHTMARE \ +"are you sure? this skill level\n"\ +"isn't even remotely fair.\n\n"PRESSYN + +#define SWSTRING \ +"this is the shareware version of doom.\n\n"\ +"you need to order the entire trilogy.\n\n"PRESSKEY + +#define MSGOFF "Messages OFF" +#define MSGON "Messages ON" +#define NETEND "you can't end a netgame!\n\n"PRESSKEY +#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN + +#define DOSY "(press y to quit to dos.)" + +#define DETAILHI "High detail" +#define DETAILLO "Low detail" +#define GAMMALVL0 "Gamma correction OFF" +#define GAMMALVL1 "Gamma correction level 1" +#define GAMMALVL2 "Gamma correction level 2" +#define GAMMALVL3 "Gamma correction level 3" +#define GAMMALVL4 "Gamma correction level 4" +#define EMPTYSTRING "empty slot" + +// +// P_inter.C +// +#define GOTARMOR "Picked up the armor." +#define GOTMEGA "Picked up the MegaArmor!" +#define GOTHTHBONUS "Picked up a health bonus." +#define GOTARMBONUS "Picked up an armor bonus." +#define GOTSTIM "Picked up a stimpack." +#define GOTMEDINEED "Picked up a medikit that you REALLY need!" +#define GOTMEDIKIT "Picked up a medikit." +#define GOTSUPER "Supercharge!" + +#define GOTBLUECARD "Picked up a blue keycard." +#define GOTYELWCARD "Picked up a yellow keycard." +#define GOTREDCARD "Picked up a red keycard." +#define GOTBLUESKUL "Picked up a blue skull key." +#define GOTYELWSKUL "Picked up a yellow skull key." +#define GOTREDSKULL "Picked up a red skull key." + +#define GOTINVUL "Invulnerability!" +#define GOTBERSERK "Berserk!" +#define GOTINVIS "Partial Invisibility" +#define GOTSUIT "Radiation Shielding Suit" +#define GOTMAP "Computer Area Map" +#define GOTVISOR "Light Amplification Visor" +#define GOTMSPHERE "MegaSphere!" + +#define GOTCLIP "Picked up a clip." +#define GOTCLIPBOX "Picked up a box of bullets." +#define GOTROCKET "Picked up a rocket." +#define GOTROCKBOX "Picked up a box of rockets." +#define GOTCELL "Picked up an energy cell." +#define GOTCELLBOX "Picked up an energy cell pack." +#define GOTSHELLS "Picked up 4 shotgun shells." +#define GOTSHELLBOX "Picked up a box of shotgun shells." +#define GOTBACKPACK "Picked up a backpack full of ammo!" + +#define GOTBFG9000 "You got the BFG9000! Oh, yes." +#define GOTCHAINGUN "You got the chaingun!" +#define GOTCHAINSAW "A chainsaw! Find some meat!" +#define GOTLAUNCHER "You got the rocket launcher!" +#define GOTPLASMA "You got the plasma gun!" +#define GOTSHOTGUN "You got the shotgun!" +#define GOTSHOTGUN2 "You got the super shotgun!" + +// +// P_Doors.C +// +#define PD_BLUEO "You need a blue key to activate this object" +#define PD_REDO "You need a red key to activate this object" +#define PD_YELLOWO "You need a yellow key to activate this object" +#define PD_BLUEK "You need a blue key to open this door" +#define PD_REDK "You need a red key to open this door" +#define PD_YELLOWK "You need a yellow key to open this door" + +// +// G_game.C +// +#define GGSAVED "game saved." + +// +// HU_stuff.C +// +#define HUSTR_MSGU "[Message unsent]" + +#define HUSTR_E1M1 "E1M1: Hangar" +#define HUSTR_E1M2 "E1M2: Nuclear Plant" +#define HUSTR_E1M3 "E1M3: Toxin Refinery" +#define HUSTR_E1M4 "E1M4: Command Control" +#define HUSTR_E1M5 "E1M5: Phobos Lab" +#define HUSTR_E1M6 "E1M6: Central Processing" +#define HUSTR_E1M7 "E1M7: Computer Station" +#define HUSTR_E1M8 "E1M8: Phobos Anomaly" +#define HUSTR_E1M9 "E1M9: Military Base" + +#define HUSTR_E2M1 "E2M1: Deimos Anomaly" +#define HUSTR_E2M2 "E2M2: Containment Area" +#define HUSTR_E2M3 "E2M3: Refinery" +#define HUSTR_E2M4 "E2M4: Deimos Lab" +#define HUSTR_E2M5 "E2M5: Command Center" +#define HUSTR_E2M6 "E2M6: Halls of the Damned" +#define HUSTR_E2M7 "E2M7: Spawning Vats" +#define HUSTR_E2M8 "E2M8: Tower of Babel" +#define HUSTR_E2M9 "E2M9: Fortress of Mystery" + +#define HUSTR_E3M1 "E3M1: Hell Keep" +#define HUSTR_E3M2 "E3M2: Slough of Despair" +#define HUSTR_E3M3 "E3M3: Pandemonium" +#define HUSTR_E3M4 "E3M4: House of Pain" +#define HUSTR_E3M5 "E3M5: Unholy Cathedral" +#define HUSTR_E3M6 "E3M6: Mt. Erebus" +#define HUSTR_E3M7 "E3M7: Limbo" +#define HUSTR_E3M8 "E3M8: Dis" +#define HUSTR_E3M9 "E3M9: Warrens" + +#define HUSTR_E4M1 "E4M1: Hell Beneath" +#define HUSTR_E4M2 "E4M2: Perfect Hatred" +#define HUSTR_E4M3 "E4M3: Sever The Wicked" +#define HUSTR_E4M4 "E4M4: Unruly Evil" +#define HUSTR_E4M5 "E4M5: They Will Repent" +#define HUSTR_E4M6 "E4M6: Against Thee Wickedly" +#define HUSTR_E4M7 "E4M7: And Hell Followed" +#define HUSTR_E4M8 "E4M8: Unto The Cruel" +#define HUSTR_E4M9 "E4M9: Fear" + +#define HUSTR_1 "level 1: entryway" +#define HUSTR_2 "level 2: underhalls" +#define HUSTR_3 "level 3: the gantlet" +#define HUSTR_4 "level 4: the focus" +#define HUSTR_5 "level 5: the waste tunnels" +#define HUSTR_6 "level 6: the crusher" +#define HUSTR_7 "level 7: dead simple" +#define HUSTR_8 "level 8: tricks and traps" +#define HUSTR_9 "level 9: the pit" +#define HUSTR_10 "level 10: refueling base" +#define HUSTR_11 "level 11: 'o' of destruction!" + +#define HUSTR_12 "level 12: the factory" +#define HUSTR_13 "level 13: downtown" +#define HUSTR_14 "level 14: the inmost dens" +#define HUSTR_15 "level 15: industrial zone" +#define HUSTR_16 "level 16: suburbs" +#define HUSTR_17 "level 17: tenements" +#define HUSTR_18 "level 18: the courtyard" +#define HUSTR_19 "level 19: the citadel" +#define HUSTR_20 "level 20: gotcha!" + +#define HUSTR_21 "level 21: nirvana" +#define HUSTR_22 "level 22: the catacombs" +#define HUSTR_23 "level 23: barrels o' fun" +#define HUSTR_24 "level 24: the chasm" +#define HUSTR_25 "level 25: bloodfalls" +#define HUSTR_26 "level 26: the abandoned mines" +#define HUSTR_27 "level 27: monster condo" +#define HUSTR_28 "level 28: the spirit world" +#define HUSTR_29 "level 29: the living end" +#define HUSTR_30 "level 30: icon of sin" + +#define HUSTR_31 "level 31: wolfenstein" +#define HUSTR_32 "level 32: grosse" + +#define PHUSTR_1 "level 1: congo" +#define PHUSTR_2 "level 2: well of souls" +#define PHUSTR_3 "level 3: aztec" +#define PHUSTR_4 "level 4: caged" +#define PHUSTR_5 "level 5: ghost town" +#define PHUSTR_6 "level 6: baron's lair" +#define PHUSTR_7 "level 7: caughtyard" +#define PHUSTR_8 "level 8: realm" +#define PHUSTR_9 "level 9: abattoire" +#define PHUSTR_10 "level 10: onslaught" +#define PHUSTR_11 "level 11: hunted" + +#define PHUSTR_12 "level 12: speed" +#define PHUSTR_13 "level 13: the crypt" +#define PHUSTR_14 "level 14: genesis" +#define PHUSTR_15 "level 15: the twilight" +#define PHUSTR_16 "level 16: the omen" +#define PHUSTR_17 "level 17: compound" +#define PHUSTR_18 "level 18: neurosphere" +#define PHUSTR_19 "level 19: nme" +#define PHUSTR_20 "level 20: the death domain" + +#define PHUSTR_21 "level 21: slayer" +#define PHUSTR_22 "level 22: impossible mission" +#define PHUSTR_23 "level 23: tombstone" +#define PHUSTR_24 "level 24: the final frontier" +#define PHUSTR_25 "level 25: the temple of darkness" +#define PHUSTR_26 "level 26: bunker" +#define PHUSTR_27 "level 27: anti-christ" +#define PHUSTR_28 "level 28: the sewers" +#define PHUSTR_29 "level 29: odyssey of noises" +#define PHUSTR_30 "level 30: the gateway of hell" + +#define PHUSTR_31 "level 31: cyberden" +#define PHUSTR_32 "level 32: go 2 it" + +#define THUSTR_1 "level 1: system control" +#define THUSTR_2 "level 2: human bbq" +#define THUSTR_3 "level 3: power control" +#define THUSTR_4 "level 4: wormhole" +#define THUSTR_5 "level 5: hanger" +#define THUSTR_6 "level 6: open season" +#define THUSTR_7 "level 7: prison" +#define THUSTR_8 "level 8: metal" +#define THUSTR_9 "level 9: stronghold" +#define THUSTR_10 "level 10: redemption" +#define THUSTR_11 "level 11: storage facility" + +#define THUSTR_12 "level 12: crater" +#define THUSTR_13 "level 13: nukage processing" +#define THUSTR_14 "level 14: steel works" +#define THUSTR_15 "level 15: dead zone" +#define THUSTR_16 "level 16: deepest reaches" +#define THUSTR_17 "level 17: processing area" +#define THUSTR_18 "level 18: mill" +#define THUSTR_19 "level 19: shipping/respawning" +#define THUSTR_20 "level 20: central processing" + +#define THUSTR_21 "level 21: administration center" +#define THUSTR_22 "level 22: habitat" +#define THUSTR_23 "level 23: lunar mining project" +#define THUSTR_24 "level 24: quarry" +#define THUSTR_25 "level 25: baron's den" +#define THUSTR_26 "level 26: ballistyx" +#define THUSTR_27 "level 27: mount pain" +#define THUSTR_28 "level 28: heck" +#define THUSTR_29 "level 29: river styx" +#define THUSTR_30 "level 30: last call" + +#define THUSTR_31 "level 31: pharaoh" +#define THUSTR_32 "level 32: caribbean" + +#define HUSTR_CHATMACRO1 "I'm ready to kick butt!" +#define HUSTR_CHATMACRO2 "I'm OK." +#define HUSTR_CHATMACRO3 "I'm not looking too good!" +#define HUSTR_CHATMACRO4 "Help!" +#define HUSTR_CHATMACRO5 "You suck!" +#define HUSTR_CHATMACRO6 "Next time, scumbag..." +#define HUSTR_CHATMACRO7 "Come here!" +#define HUSTR_CHATMACRO8 "I'll take care of it." +#define HUSTR_CHATMACRO9 "Yes" +#define HUSTR_CHATMACRO0 "No" + +#define HUSTR_TALKTOSELF1 "You mumble to yourself" +#define HUSTR_TALKTOSELF2 "Who's there?" +#define HUSTR_TALKTOSELF3 "You scare yourself" +#define HUSTR_TALKTOSELF4 "You start to rave" +#define HUSTR_TALKTOSELF5 "You've lost it..." + +#define HUSTR_MESSAGESENT "[Message Sent]" + +// The following should NOT be changed unless it seems +// just AWFULLY necessary + +#define HUSTR_PLRGREEN "Green: " +#define HUSTR_PLRINDIGO "Indigo: " +#define HUSTR_PLRBROWN "Brown: " +#define HUSTR_PLRRED "Red: " + +#define HUSTR_KEYGREEN 'g' +#define HUSTR_KEYINDIGO 'i' +#define HUSTR_KEYBROWN 'b' +#define HUSTR_KEYRED 'r' + +// +// AM_map.C +// + +#define AMSTR_FOLLOWON "Follow Mode ON" +#define AMSTR_FOLLOWOFF "Follow Mode OFF" + +#define AMSTR_GRIDON "Grid ON" +#define AMSTR_GRIDOFF "Grid OFF" + +#define AMSTR_MARKEDSPOT "Marked Spot" +#define AMSTR_MARKSCLEARED "All Marks Cleared" + +// +// ST_stuff.C +// + +#define STSTR_MUS "Music Change" +#define STSTR_NOMUS "IMPOSSIBLE SELECTION" +#define STSTR_DQDON "Degreelessness Mode On" +#define STSTR_DQDOFF "Degreelessness Mode Off" + +#define STSTR_KFAADDED "Very Happy Ammo Added" +#define STSTR_FAADDED "Ammo (no keys) Added" + +#define STSTR_NCON "No Clipping Mode ON" +#define STSTR_NCOFF "No Clipping Mode OFF" + +#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" +#define STSTR_BEHOLDX "Power-up Toggled" + +#define STSTR_CHOPPERS "... doesn't suck - GM" +#define STSTR_CLEV "Changing Level..." + +// +// F_Finale.C +// +#define E1TEXT \ +"Once you beat the big badasses and\n"\ +"clean out the moon base you're supposed\n"\ +"to win, aren't you? Aren't you? Where's\n"\ +"your fat reward and ticket home? What\n"\ +"the hell is this? It's not supposed to\n"\ +"end this way!\n"\ +"\n" \ +"It stinks like rotten meat, but looks\n"\ +"like the lost Deimos base. Looks like\n"\ +"you're stuck on The Shores of Hell.\n"\ +"The only way out is through.\n"\ +"\n"\ +"To continue the DOOM experience, play\n"\ +"The Shores of Hell and its amazing\n"\ +"sequel, Inferno!\n" + + +#define E2TEXT \ +"You've done it! The hideous cyber-\n"\ +"demon lord that ruled the lost Deimos\n"\ +"moon base has been slain and you\n"\ +"are triumphant! But ... where are\n"\ +"you? You clamber to the edge of the\n"\ +"moon and look down to see the awful\n"\ +"truth.\n" \ +"\n"\ +"Deimos floats above Hell itself!\n"\ +"You've never heard of anyone escaping\n"\ +"from Hell, but you'll make the bastards\n"\ +"sorry they ever heard of you! Quickly,\n"\ +"you rappel down to the surface of\n"\ +"Hell.\n"\ +"\n" \ +"Now, it's on to the final chapter of\n"\ +"DOOM! -- Inferno." + + +#define E3TEXT \ +"The loathsome spiderdemon that\n"\ +"masterminded the invasion of the moon\n"\ +"bases and caused so much death has had\n"\ +"its ass kicked for all time.\n"\ +"\n"\ +"A hidden doorway opens and you enter.\n"\ +"You've proven too tough for Hell to\n"\ +"contain, and now Hell at last plays\n"\ +"fair -- for you emerge from the door\n"\ +"to see the green fields of Earth!\n"\ +"Home at last.\n" \ +"\n"\ +"You wonder what's been happening on\n"\ +"Earth while you were battling evil\n"\ +"unleashed. It's good that no Hell-\n"\ +"spawn could have come through that\n"\ +"door with you ..." + + +#define E4TEXT \ +"the spider mastermind must have sent forth\n"\ +"its legions of hellspawn before your\n"\ +"final confrontation with that terrible\n"\ +"beast from hell. but you stepped forward\n"\ +"and brought forth eternal damnation and\n"\ +"suffering upon the horde as a true hero\n"\ +"would in the face of something so evil.\n"\ +"\n"\ +"besides, someone was gonna pay for what\n"\ +"happened to daisy, your pet rabbit.\n"\ +"\n"\ +"but now, you see spread before you more\n"\ +"potential pain and gibbitude as a nation\n"\ +"of demons run amok among our cities.\n"\ +"\n"\ +"next stop, hell on earth!" + + +// after level 6, put this: + +#define C1TEXT \ +"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ +"STARPORT. BUT SOMETHING IS WRONG. THE\n" \ +"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ +"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ +"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ +"\n"\ +"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ +"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ +"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ +"OF THE STARBASE AND FIND THE CONTROLLING\n" \ +"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ +"HOSTAGE." + +// After level 11, put this: + +#define C2TEXT \ +"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ +"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\ +"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\ +"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\ +"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\ +"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\ +"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\ +"THAT YOU HAVE SAVED YOUR SPECIES.\n"\ +"\n"\ +"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\ +"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\ +"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\ +"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\ +"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\ +"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\ +"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\ +"UP AND RETURN TO THE FRAY." + + +// After level 20, put this: + +#define C3TEXT \ +"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\ +"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\ +"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\ +"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\ +"TEETH AND PLUNGE THROUGH IT.\n"\ +"\n"\ +"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\ +"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\ +"GOT TO GO THROUGH HELL TO GET TO IT?" + + +// After level 29, put this: + +#define C4TEXT \ +"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\ +"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\ +"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\ +"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\ +"UP AND DIES, ITS THRASHING LIMBS\n"\ +"DEVASTATING UNTOLD MILES OF HELL'S\n"\ +"SURFACE.\n"\ +"\n"\ +"YOU'VE DONE IT. THE INVASION IS OVER.\n"\ +"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\ +"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\ +"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\ +"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\ +"HOME. REBUILDING EARTH OUGHT TO BE A\n"\ +"LOT MORE FUN THAN RUINING IT WAS.\n" + + + +// Before level 31, put this: + +#define C5TEXT \ +"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\ +"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\ +"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\ +"WHO THE INMATES OF THIS CORNER OF HELL\n"\ +"WILL BE." + + +// Before level 32, put this: + +#define C6TEXT \ +"CONGRATULATIONS, YOU'VE FOUND THE\n"\ +"SUPER SECRET LEVEL! YOU'D BETTER\n"\ +"BLAZE THROUGH THIS ONE!\n" + + +// after map 06 + +#define P1TEXT \ +"You gloat over the steaming carcass of the\n"\ +"Guardian. With its death, you've wrested\n"\ +"the Accelerator from the stinking claws\n"\ +"of Hell. You relax and glance around the\n"\ +"room. Damn! There was supposed to be at\n"\ +"least one working prototype, but you can't\n"\ +"see it. The demons must have taken it.\n"\ +"\n"\ +"You must find the prototype, or all your\n"\ +"struggles will have been wasted. Keep\n"\ +"moving, keep fighting, keep killing.\n"\ +"Oh yes, keep living, too." + + +// after map 11 + +#define P2TEXT \ +"Even the deadly Arch-Vile labyrinth could\n"\ +"not stop you, and you've gotten to the\n"\ +"prototype Accelerator which is soon\n"\ +"efficiently and permanently deactivated.\n"\ +"\n"\ +"You're good at that kind of thing." + + +// after map 20 + +#define P3TEXT \ +"You've bashed and battered your way into\n"\ +"the heart of the devil-hive. Time for a\n"\ +"Search-and-Destroy mission, aimed at the\n"\ +"Gatekeeper, whose foul offspring is\n"\ +"cascading to Earth. Yeah, he's bad. But\n"\ +"you know who's worse!\n"\ +"\n"\ +"Grinning evilly, you check your gear, and\n"\ +"get ready to give the bastard a little Hell\n"\ +"of your own making!" + +// after map 30 + +#define P4TEXT \ +"The Gatekeeper's evil face is splattered\n"\ +"all over the place. As its tattered corpse\n"\ +"collapses, an inverted Gate forms and\n"\ +"sucks down the shards of the last\n"\ +"prototype Accelerator, not to mention the\n"\ +"few remaining demons. You're done. Hell\n"\ +"has gone back to pounding bad dead folks \n"\ +"instead of good live ones. Remember to\n"\ +"tell your grandkids to put a rocket\n"\ +"launcher in your coffin. If you go to Hell\n"\ +"when you die, you'll need it for some\n"\ +"final cleaning-up ..." + +// before map 31 + +#define P5TEXT \ +"You've found the second-hardest level we\n"\ +"got. Hope you have a saved game a level or\n"\ +"two previous. If not, be prepared to die\n"\ +"aplenty. For master marines only." + +// before map 32 + +#define P6TEXT \ +"Betcha wondered just what WAS the hardest\n"\ +"level we had ready for ya? Now you know.\n"\ +"No one gets out alive." + + +#define T1TEXT \ +"You've fought your way out of the infested\n"\ +"experimental labs. It seems that UAC has\n"\ +"once again gulped it down. With their\n"\ +"high turnover, it must be hard for poor\n"\ +"old UAC to buy corporate health insurance\n"\ +"nowadays..\n"\ +"\n"\ +"Ahead lies the military complex, now\n"\ +"swarming with diseased horrors hot to get\n"\ +"their teeth into you. With luck, the\n"\ +"complex still has some warlike ordnance\n"\ +"laying around." + + +#define T2TEXT \ +"You hear the grinding of heavy machinery\n"\ +"ahead. You sure hope they're not stamping\n"\ +"out new hellspawn, but you're ready to\n"\ +"ream out a whole herd if you have to.\n"\ +"They might be planning a blood feast, but\n"\ +"you feel about as mean as two thousand\n"\ +"maniacs packed into one mad killer.\n"\ +"\n"\ +"You don't plan to go down easy." + + +#define T3TEXT \ +"The vista opening ahead looks real damn\n"\ +"familiar. Smells familiar, too -- like\n"\ +"fried excrement. You didn't like this\n"\ +"place before, and you sure as hell ain't\n"\ +"planning to like it now. The more you\n"\ +"brood on it, the madder you get.\n"\ +"Hefting your gun, an evil grin trickles\n"\ +"onto your face. Time to take some names." + +#define T4TEXT \ +"Suddenly, all is silent, from one horizon\n"\ +"to the other. The agonizing echo of Hell\n"\ +"fades away, the nightmare sky turns to\n"\ +"blue, the heaps of monster corpses start \n"\ +"to evaporate along with the evil stench \n"\ +"that filled the air. Jeeze, maybe you've\n"\ +"done it. Have you really won?\n"\ +"\n"\ +"Something rumbles in the distance.\n"\ +"A blue light begins to glow inside the\n"\ +"ruined skull of the demon-spitter." + + +#define T5TEXT \ +"What now? Looks totally different. Kind\n"\ +"of like King Tut's condo. Well,\n"\ +"whatever's here can't be any worse\n"\ +"than usual. Can it? Or maybe it's best\n"\ +"to let sleeping gods lie.." + + +#define T6TEXT \ +"Time for a vacation. You've burst the\n"\ +"bowels of hell and by golly you're ready\n"\ +"for a break. You mutter to yourself,\n"\ +"Maybe someone else can kick Hell's ass\n"\ +"next time around. Ahead lies a quiet town,\n"\ +"with peaceful flowing water, quaint\n"\ +"buildings, and presumably no Hellspawn.\n"\ +"\n"\ +"As you step off the transport, you hear\n"\ +"the stomp of a cyberdemon's iron shoe." + + + +// +// Character cast strings F_FINALE.C +// +#define CC_ZOMBIE "ZOMBIEMAN" +#define CC_SHOTGUN "SHOTGUN GUY" +#define CC_HEAVY "HEAVY WEAPON DUDE" +#define CC_IMP "IMP" +#define CC_DEMON "DEMON" +#define CC_LOST "LOST SOUL" +#define CC_CACO "CACODEMON" +#define CC_HELL "HELL KNIGHT" +#define CC_BARON "BARON OF HELL" +#define CC_ARACH "ARACHNOTRON" +#define CC_PAIN "PAIN ELEMENTAL" +#define CC_REVEN "REVENANT" +#define CC_MANCU "MANCUBUS" +#define CC_ARCH "ARCH-VILE" +#define CC_SPIDER "THE SPIDER MASTERMIND" +#define CC_CYBER "THE CYBERDEMON" +#define CC_HERO "OUR HERO" + + +#endif diff --git a/games/NXDoom/src/doom/d_items.c b/games/NXDoom/src/doom/d_items.c new file mode 100644 index 00000000000..33f310c63b3 --- /dev/null +++ b/games/NXDoom/src/doom/d_items.c @@ -0,0 +1,128 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// + + +// We are referring to sprite numbers. +#include "info.h" + +#include "d_items.h" + + +// +// PSPRITE ACTIONS for waepons. +// This struct controls the weapon animations. +// +// Each entry is: +// ammo/amunition type +// upstate +// downstate +// readystate +// atkstate, i.e. attack/fire/hit frame +// flashstate, muzzle flash +// +weaponinfo_t weaponinfo[NUMWEAPONS] = +{ + { + // fist + am_noammo, + S_PUNCHUP, + S_PUNCHDOWN, + S_PUNCH, + S_PUNCH1, + S_NULL + }, + { + // pistol + am_clip, + S_PISTOLUP, + S_PISTOLDOWN, + S_PISTOL, + S_PISTOL1, + S_PISTOLFLASH + }, + { + // shotgun + am_shell, + S_SGUNUP, + S_SGUNDOWN, + S_SGUN, + S_SGUN1, + S_SGUNFLASH1 + }, + { + // chaingun + am_clip, + S_CHAINUP, + S_CHAINDOWN, + S_CHAIN, + S_CHAIN1, + S_CHAINFLASH1 + }, + { + // missile launcher + am_misl, + S_MISSILEUP, + S_MISSILEDOWN, + S_MISSILE, + S_MISSILE1, + S_MISSILEFLASH1 + }, + { + // plasma rifle + am_cell, + S_PLASMAUP, + S_PLASMADOWN, + S_PLASMA, + S_PLASMA1, + S_PLASMAFLASH1 + }, + { + // bfg 9000 + am_cell, + S_BFGUP, + S_BFGDOWN, + S_BFG, + S_BFG1, + S_BFGFLASH1 + }, + { + // chainsaw + am_noammo, + S_SAWUP, + S_SAWDOWN, + S_SAW, + S_SAW1, + S_NULL + }, + { + // super shotgun + am_shell, + S_DSGUNUP, + S_DSGUNDOWN, + S_DSGUN, + S_DSGUN1, + S_DSGUNFLASH1 + }, +}; + + + + + + + + diff --git a/games/NXDoom/src/doom/d_items.h b/games/NXDoom/src/doom/d_items.h new file mode 100644 index 00000000000..3d22a063030 --- /dev/null +++ b/games/NXDoom/src/doom/d_items.h @@ -0,0 +1,41 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Items: key cards, artifacts, weapon, ammunition. +// + + +#ifndef __D_ITEMS__ +#define __D_ITEMS__ + +#include "doomdef.h" + + + +// Weapon info: sprite frames, ammunition use. +typedef struct +{ + ammotype_t ammo; + int upstate; + int downstate; + int readystate; + int atkstate; + int flashstate; + +} weaponinfo_t; + +extern weaponinfo_t weaponinfo[NUMWEAPONS]; + +#endif diff --git a/games/NXDoom/src/doom/d_main.c b/games/NXDoom/src/doom/d_main.c new file mode 100644 index 00000000000..014e4872134 --- /dev/null +++ b/games/NXDoom/src/doom/d_main.c @@ -0,0 +1,2002 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM main program (D_DoomMain) and game loop (D_DoomLoop), +// plus functions to determine game mode (shareware, registered), +// parse command line parameters, configure game parameters (turbo), +// and call the startup functions. +// + + +#include +#include +#include +#include + +#include "config.h" +#include "deh_main.h" +#include "doomdef.h" +#include "doomstat.h" + +#include "dstrings.h" +#include "sounds.h" + +#include "d_iwad.h" + +#include "z_zone.h" +#include "w_main.h" +#include "w_wad.h" +#include "s_sound.h" +#include "v_diskicon.h" +#include "v_video.h" + +#include "f_finale.h" +#include "f_wipe.h" + +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_menu.h" +#include "p_saveg.h" + +#include "i_endoom.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" + +#include "g_game.h" + +#include "hu_stuff.h" +#include "wi_stuff.h" +#include "st_stuff.h" +#include "am_map.h" +#include "net_client.h" +#include "net_dedicated.h" +#include "net_query.h" + +#include "p_setup.h" +#include "r_local.h" +#include "statdump.h" + +#include "d_main.h" + +#include "doom_icon.c" + +// +// D-DoomLoop() +// Not a globally visible function, +// just included for source reference, +// called by D_DoomMain, never exits. +// Manages timing and IO, +// calls all ?_Responder, ?_Ticker, and ?_Drawer, +// calls I_GetTime, I_StartFrame, and I_StartTic +// +void D_DoomLoop (void); + +static char *gamedescription; + +// Location where savegames are stored + +char * savegamedir; + +// location of IWAD and WAD files + +char * iwadfile; + + +boolean devparm; // started game with -devparm +boolean nomonsters; // checkparm of -nomonsters +boolean respawnparm; // checkparm of -respawn +boolean fastparm; // checkparm of -fast + + + +skill_t startskill; +int startepisode; +int startmap; +boolean autostart; +int startloadgame; + +boolean advancedemo; + +// Store demo, do not accept any inputs +boolean storedemo; + +// If true, the main game loop has started. +boolean main_loop_started = false; + +int show_endoom = 1; +int show_diskicon = 1; + + +void D_ConnectNetGame(void); +void D_CheckNetGame(void); + + +// +// D_ProcessEvents +// Send all the events of the given timestamp down the responder chain +// +void D_ProcessEvents (void) +{ + event_t* ev; + + // IF STORE DEMO, DO NOT ACCEPT INPUT + if (storedemo) + return; + + while ((ev = D_PopEvent()) != NULL) + { + if (M_Responder (ev)) + continue; // menu ate the event + G_Responder (ev); + } +} + + + + +// +// D_Display +// draw current display, possibly wiping it from the previous +// + +// wipegamestate can be set to -1 to force a wipe on the next draw +gamestate_t wipegamestate = GS_DEMOSCREEN; + +boolean D_Display (void) +{ + static boolean viewactivestate = false; + static boolean menuactivestate = false; + static boolean inhelpscreensstate = false; + static boolean fullscreen = false; + static gamestate_t oldgamestate = -1; + static int borderdrawcount; + int y; + boolean wipe; + boolean redrawsbar; + + redrawsbar = false; + + // change the view size if needed + if (setsizeneeded) + { + R_ExecuteSetViewSize (); + oldgamestate = -1; // force background redraw + borderdrawcount = 3; + } + + // save the current screen if about to wipe + if (gamestate != wipegamestate) + { + wipe = true; + wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + } + else + wipe = false; + + if (gamestate == GS_LEVEL && gametic) + HU_Erase(); + + // do buffered drawing + switch (gamestate) + { + case GS_LEVEL: + if (!gametic) + break; + if (automapactive) + AM_Drawer (); + if (wipe || (viewheight != SCREENHEIGHT && fullscreen)) + redrawsbar = true; + if (inhelpscreensstate && !inhelpscreens) + redrawsbar = true; // just put away the help screen + ST_Drawer (viewheight == SCREENHEIGHT, redrawsbar ); + fullscreen = viewheight == SCREENHEIGHT; + break; + + case GS_INTERMISSION: + WI_Drawer (); + break; + + case GS_FINALE: + F_Drawer (); + break; + + case GS_DEMOSCREEN: + D_PageDrawer (); + break; + } + + // draw buffered stuff to screen + I_UpdateNoBlit (); + + // draw the view directly + if (gamestate == GS_LEVEL && !automapactive && gametic) + R_RenderPlayerView (&players[displayplayer]); + + if (gamestate == GS_LEVEL && gametic) + HU_Drawer (); + + // clean up border stuff + if (gamestate != oldgamestate && gamestate != GS_LEVEL) + I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); + + // see if the border needs to be initially drawn + if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) + { + viewactivestate = false; // view was not active + R_FillBackScreen (); // draw the pattern into the back screen + } + + // see if the border needs to be updated to the screen + if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != SCREENWIDTH) + { + if (menuactive || menuactivestate || !viewactivestate) + borderdrawcount = 3; + if (borderdrawcount) + { + R_DrawViewBorder (); // erase old menu stuff + borderdrawcount--; + } + + } + + if (testcontrols) + { + // Box showing current mouse speed + + V_DrawMouseSpeedBox(testcontrols_mousespeed); + } + + menuactivestate = menuactive; + viewactivestate = viewactive; + inhelpscreensstate = inhelpscreens; + oldgamestate = wipegamestate = gamestate; + + // draw pause pic + if (paused) + { + if (automapactive) + y = 4; + else + y = viewwindowy+4; + V_DrawPatchDirect(viewwindowx + (scaledviewwidth - 68) / 2, y, + W_CacheLumpName (DEH_String("M_PAUSE"), PU_CACHE)); + } + + + // menus go directly to the screen + M_Drawer (); // menu is drawn even on top of everything + NetUpdate (); // send out any new accumulation + + return wipe; +} + +static void EnableLoadingDisk(void) +{ + const char *disk_lump_name; + + if (show_diskicon) + { + if (M_CheckParm("-cdrom") > 0) + { + disk_lump_name = DEH_String("STCDROM"); + } + else + { + disk_lump_name = DEH_String("STDISK"); + } + + V_EnableLoadingDisk(disk_lump_name, + SCREENWIDTH - LOADING_DISK_W, + SCREENHEIGHT - LOADING_DISK_H); + } +} + +// +// Add configuration file variable bindings. +// + + +static const char * const chat_macro_defaults[10] = +{ + HUSTR_CHATMACRO0, + HUSTR_CHATMACRO1, + HUSTR_CHATMACRO2, + HUSTR_CHATMACRO3, + HUSTR_CHATMACRO4, + HUSTR_CHATMACRO5, + HUSTR_CHATMACRO6, + HUSTR_CHATMACRO7, + HUSTR_CHATMACRO8, + HUSTR_CHATMACRO9 +}; + + +void D_BindVariables(void) +{ + int i; + + M_ApplyPlatformDefaults(); + + I_BindInputVariables(); + I_BindVideoVariables(); + I_BindJoystickVariables(); + I_BindSoundVariables(); + + M_BindBaseControls(); + M_BindWeaponControls(); + M_BindMapControls(); + M_BindMenuControls(); + M_BindChatControls(MAXPLAYERS); + + key_multi_msgplayer[0] = HUSTR_KEYGREEN; + key_multi_msgplayer[1] = HUSTR_KEYINDIGO; + key_multi_msgplayer[2] = HUSTR_KEYBROWN; + key_multi_msgplayer[3] = HUSTR_KEYRED; + + NET_BindVariables(); + + M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); + M_BindIntVariable("sfx_volume", &sfxVolume); + M_BindIntVariable("music_volume", &musicVolume); + M_BindIntVariable("show_messages", &showMessages); + M_BindIntVariable("screenblocks", &screenblocks); + M_BindIntVariable("detaillevel", &detailLevel); + M_BindIntVariable("snd_channels", &snd_channels); + M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); + M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); + M_BindIntVariable("show_endoom", &show_endoom); + M_BindIntVariable("show_diskicon", &show_diskicon); + + // Multiplayer chat macros + + for (i=0; i<10; ++i) + { + char buf[12]; + + chat_macros[i] = M_StringDuplicate(chat_macro_defaults[i]); + M_snprintf(buf, sizeof(buf), "chatmacro%i", i); + M_BindStringVariable(buf, &chat_macros[i]); + } +} + +// +// D_GrabMouseCallback +// +// Called to determine whether to grab the mouse pointer +// + +boolean D_GrabMouseCallback(void) +{ + // Drone players don't need mouse focus + + if (drone) + return false; + + // when menu is active or game is paused, release the mouse + + if (menuactive || paused) + return false; + + // only grab mouse when playing levels (but not demos) + + return (gamestate == GS_LEVEL) && !demoplayback && !advancedemo; +} + +// +// D_RunFrame +// +void D_RunFrame() +{ + int nowtime; + int tics; + static int wipestart; + static boolean wipe; + + if (wipe) + { + do + { + nowtime = I_GetTime (); + tics = nowtime - wipestart; + I_Sleep(1); + } while (tics <= 0); + + wipestart = nowtime; + wipe = !wipe_ScreenWipe(wipe_Melt + , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); + I_UpdateNoBlit (); + M_Drawer (); // menu is drawn even on top of wipes + I_FinishUpdate (); // page flip or blit buffer + return; + } + + // frame syncronous IO operations + I_StartFrame (); + + TryRunTics (); // will run at least one tic + + S_UpdateSounds (players[consoleplayer].mo);// move positional sounds + + // Update display, next frame, with current state if no profiling is on + if (screenvisible && !nodrawers) + { + if ((wipe = D_Display ())) + { + // start wipe on this frame + wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + + wipestart = I_GetTime () - 1; + } else { + // normal update + I_FinishUpdate (); // page flip or blit buffer + } + } +} + +// +// D_DoomLoop +// +void D_DoomLoop (void) +{ + if (gamevariant == bfgedition && + (demorecording || (gameaction == ga_playdemo) || netgame)) + { + printf(" WARNING: You are playing using one of the Doom Classic\n" + " IWAD files shipped with the Doom 3: BFG Edition. These are\n" + " known to be incompatible with the regular IWAD files and\n" + " may cause demos and network games to get out of sync.\n"); + } + + if (demorecording) + G_BeginRecording (); + + main_loop_started = true; + + I_SetWindowTitle(gamedescription); + I_GraphicsCheckCommandLine(); + I_SetGrabMouseCallback(D_GrabMouseCallback); + I_RegisterWindowIcon(doom_icon_data, doom_icon_w, doom_icon_h); + I_InitGraphics(); + EnableLoadingDisk(); + + TryRunTics(); + + V_RestoreBuffer(); + R_ExecuteSetViewSize(); + + D_StartGameLoop(); + + if (testcontrols) + { + wipegamestate = gamestate; + } + + while (1) + { + D_RunFrame(); + } +} + + + +// +// DEMO LOOP +// +int demosequence; +int pagetic; +const char *pagename; + + +// +// D_PageTicker +// Handles timing for warped projection +// +void D_PageTicker (void) +{ + if (--pagetic < 0) + D_AdvanceDemo (); +} + + + +// +// D_PageDrawer +// +void D_PageDrawer (void) +{ + V_DrawPatch (0, 0, W_CacheLumpName(pagename, PU_CACHE)); +} + + +// +// D_AdvanceDemo +// Called after each demo or intro demosequence finishes +// +void D_AdvanceDemo (void) +{ + advancedemo = true; +} + + +// +// This cycles through the demo sequences. +// FIXME - version dependend demo numbers? +// +void D_DoAdvanceDemo (void) +{ + players[consoleplayer].playerstate = PST_LIVE; // not reborn + advancedemo = false; + usergame = false; // no save / end game here + paused = false; + gameaction = ga_nothing; + + // The Ultimate Doom executable changed the demo sequence to add + // a DEMO4 demo. Final Doom was based on Ultimate, so also + // includes this change; however, the Final Doom IWADs do not + // include a DEMO4 lump, so the game bombs out with an error + // when it reaches this point in the demo sequence. + + // However! There is an alternate version of Final Doom that + // includes a fixed executable. + + if (gameversion == exe_ultimate || gameversion == exe_final) + demosequence = (demosequence+1)%7; + else + demosequence = (demosequence+1)%6; + + switch (demosequence) + { + case 0: + if ( gamemode == commercial ) + pagetic = TICRATE * 11; + else + pagetic = 170; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("TITLEPIC"); + if ( gamemode == commercial ) + S_StartMusic(mus_dm2ttl); + else + S_StartMusic (mus_intro); + break; + case 1: + G_DeferedPlayDemo(DEH_String("demo1")); + break; + case 2: + pagetic = 200; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("CREDIT"); + break; + case 3: + G_DeferedPlayDemo(DEH_String("demo2")); + break; + case 4: + gamestate = GS_DEMOSCREEN; + if ( gamemode == commercial) + { + pagetic = TICRATE * 11; + pagename = DEH_String("TITLEPIC"); + S_StartMusic(mus_dm2ttl); + } + else + { + pagetic = 200; + + if (gameversion >= exe_ultimate) + pagename = DEH_String("CREDIT"); + else + pagename = DEH_String("HELP2"); + } + break; + case 5: + G_DeferedPlayDemo(DEH_String("demo3")); + break; + // THE DEFINITIVE DOOM Special Edition demo + case 6: + G_DeferedPlayDemo(DEH_String("demo4")); + break; + } + + // The Doom 3: BFG Edition version of doom2.wad does not have a + // TITLETPIC lump. Use INTERPIC instead as a workaround. + if (gamevariant == bfgedition && !strcasecmp(pagename, "TITLEPIC") + && W_CheckNumForName("titlepic") < 0) + { + pagename = DEH_String("INTERPIC"); + } +} + + + +// +// D_StartTitle +// +void D_StartTitle (void) +{ + gameaction = ga_nothing; + demosequence = -1; + D_AdvanceDemo (); +} + +// Strings for dehacked replacements of the startup banner +// +// These are from the original source: some of them are perhaps +// not used in any dehacked patches + +static const char *banners[] = +{ + // doom2.wad + " " + "DOOM 2: Hell on Earth v%i.%i" + " ", + // doom2.wad v1.666 + " " + "DOOM 2: Hell on Earth v%i.%i66" + " ", + // doom1.wad + " " + "DOOM Shareware Startup v%i.%i" + " ", + // doom.wad + " " + "DOOM Registered Startup v%i.%i" + " ", + // Registered DOOM uses this + " " + "DOOM System Startup v%i.%i" + " ", + // Doom v1.666 + " " + "DOOM System Startup v%i.%i66" + " " + // doom.wad (Ultimate DOOM) + " " + "The Ultimate DOOM Startup v%i.%i" + " ", + // tnt.wad + " " + "DOOM 2: TNT - Evilution v%i.%i" + " ", + // plutonia.wad + " " + "DOOM 2: Plutonia Experiment v%i.%i" + " ", +}; + +// +// Get game name: if the startup banner has been replaced, use that. +// Otherwise, use the name given +// + +static char *GetGameName(const char *gamename) +{ + size_t i; + + for (i=0; iname, "MAP01", 8)) + { + gamemission = doom2; + break; + } + else if (!strncasecmp(lumpinfo[i]->name, "E1M1", 8)) + { + gamemission = doom; + break; + } + } + + if (gamemission == none) + { + // Still no idea. I don't think this is going to work. + + I_Error("Unknown or invalid IWAD file."); + } + } + + // Make sure gamemode is set up correctly + + if (logical_gamemission == doom) + { + // Doom 1. But which version? + + if (W_CheckNumForName("E4M1") > 0) + { + // Ultimate Doom + + gamemode = retail; + } + else if (W_CheckNumForName("E3M1") > 0) + { + gamemode = registered; + } + else + { + gamemode = shareware; + } + } + else + { + int p; + + // Doom 2 of some kind. + gamemode = commercial; + + // We can manually override the gamemission that we got from the + // IWAD detection code. This allows us to eg. play Plutonia 2 + // with Freedoom and get the right level names. + + //! + // @category compat + // @arg + // + // Explicitly specify a Doom II "mission pack" to run as, instead of + // detecting it based on the filename. Valid values are: "doom2", + // "tnt" and "plutonia". + // + p = M_CheckParmWithArgs("-pack", 1); + if (p > 0) + { + SetMissionForPackName(myargv[p + 1]); + } + } +} + +// Set the gamedescription string + +static void D_SetGameDescription(void) +{ + if (logical_gamemission == doom) + { + // Doom 1. But which version? + + if (gamevariant == freedoom) + { + gamedescription = GetGameName("Freedoom: Phase 1"); + } + else if (gamemode == retail) + { + // Ultimate Doom + + gamedescription = GetGameName("The Ultimate DOOM"); + } + else if (gamemode == registered) + { + gamedescription = GetGameName("DOOM Registered"); + } + else if (gamemode == shareware) + { + gamedescription = GetGameName("DOOM Shareware"); + } + } + else + { + // Doom 2 of some kind. But which mission? + + if (gamevariant == freedm) + { + gamedescription = GetGameName("FreeDM"); + } + else if (gamevariant == freedoom) + { + gamedescription = GetGameName("Freedoom: Phase 2"); + } + else if (logical_gamemission == doom2) + { + gamedescription = GetGameName("DOOM 2: Hell on Earth"); + } + else if (logical_gamemission == pack_plut) + { + gamedescription = GetGameName("DOOM 2: Plutonia Experiment"); + } + else if (logical_gamemission == pack_tnt) + { + gamedescription = GetGameName("DOOM 2: TNT - Evilution"); + } + } + + if (gamedescription == NULL) + { + gamedescription = M_StringDuplicate("Unknown"); + } +} + +// print title for every printed line +char title[128]; + +static boolean D_AddFile(char *filename) +{ + wad_file_t *handle; + + printf(" adding %s\n", filename); + handle = W_AddFile(filename); + + return handle != NULL; +} + +// Copyright message banners +// Some dehacked mods replace these. These are only displayed if they are +// replaced by dehacked. + +static const char *copyright_banners[] = +{ + "===========================================================================\n" + "ATTENTION: This version of DOOM has been modified. If you would like to\n" + "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n" + " You will not receive technical support for modified games.\n" + " press enter to continue\n" + "===========================================================================\n", + + "===========================================================================\n" + " Commercial product - do not distribute!\n" + " Please report software piracy to the SPA: 1-800-388-PIR8\n" + "===========================================================================\n", + + "===========================================================================\n" + " Shareware!\n" + "===========================================================================\n" +}; + +// Prints a message only if it has been modified by dehacked. + +void PrintDehackedBanners(void) +{ + size_t i; + + for (i=0; i + // @category compat + // + // Emulate a specific version of Doom. Valid values are "1.2", + // "1.5", "1.666", "1.7", "1.8", "1.9", "ultimate", "final", + // "final2", "hacx" and "chex". + // + + p = M_CheckParmWithArgs("-gameversion", 1); + + if (p) + { + for (i=0; gameversions[i].description != NULL; ++i) + { + if (!strcmp(myargv[p+1], gameversions[i].cmdline)) + { + gameversion = gameversions[i].version; + break; + } + } + + if (gameversions[i].description == NULL) + { + printf("Supported game versions:\n"); + + for (i=0; gameversions[i].description != NULL; ++i) + { + printf("\t%s (%s)\n", gameversions[i].cmdline, + gameversions[i].description); + } + + I_Error("Unknown game version '%s'", myargv[p+1]); + } + } + else + { + // Determine automatically + + if (gamemission == pack_chex) + { + // chex.exe - identified by iwad filename + + gameversion = exe_chex; + } + else if (gamemission == pack_hacx) + { + // hacx.exe: identified by iwad filename + + gameversion = exe_hacx; + } + else if (gamemode == shareware || gamemode == registered + || (gamemode == commercial && gamemission == doom2)) + { + // original + gameversion = exe_doom_1_9; + + // Detect version from demo lump + for (i = 1; i <= 3; ++i) + { + M_snprintf(demolumpname, 6, "demo%i", i); + if (W_CheckNumForName(demolumpname) > 0) + { + demolump = W_CacheLumpName(demolumpname, PU_STATIC); + demoversion = demolump[0]; + W_ReleaseLumpName(demolumpname); + status = true; + switch (demoversion) + { + case 0: + case 1: + case 2: + case 3: + case 4: + gameversion = exe_doom_1_2; + break; + case 106: + gameversion = exe_doom_1_666; + break; + case 107: + gameversion = exe_doom_1_7; + break; + case 108: + gameversion = exe_doom_1_8; + break; + case 109: + gameversion = exe_doom_1_9; + break; + default: + status = false; + break; + } + if (status) + { + break; + } + } + } + } + else if (gamemode == retail) + { + gameversion = exe_ultimate; + } + else if (gamemode == commercial) + { + // Final Doom: tnt or plutonia + // Defaults to emulating the first Final Doom executable, + // which has the crash in the demo loop; however, having + // this as the default should mean that it plays back + // most demos correctly. + + gameversion = exe_final; + } + } + + // Deathmatch 2.0 did not exist until Doom v1.4 + if (gameversion <= exe_doom_1_2 && deathmatch == 2) + { + deathmatch = 1; + } + + // The original exe does not support retail - 4th episode not supported + + if (gameversion < exe_ultimate && gamemode == retail) + { + gamemode = registered; + } + + // EXEs prior to the Final Doom exes do not support Final Doom. + + if (gameversion < exe_final && gamemode == commercial + && (gamemission == pack_tnt || gamemission == pack_plut)) + { + gamemission = doom2; + } +} + +void PrintGameVersion(void) +{ + int i; + + for (i=0; gameversions[i].description != NULL; ++i) + { + if (gameversions[i].version == gameversion) + { + printf("Emulating the behavior of the " + "'%s' executable.\n", gameversions[i].description); + break; + } + } +} + +// Function called at exit to display the ENDOOM screen + +static void D_Endoom(void) +{ + byte *endoom; + + // Don't show ENDOOM if we have it disabled, or we're running + // in screensaver or control test mode. Only show it once the + // game has actually started. + + if (!show_endoom || !main_loop_started + || screensaver_mode || M_CheckParm("-testcontrols") > 0) + { + return; + } + + endoom = W_CacheLumpName(DEH_String("ENDOOM"), PU_STATIC); + + I_Endoom(endoom); +} + +boolean IsFrenchIWAD(void) +{ + return (gamemission == doom2 && W_CheckNumForName("M_RDTHIS") < 0 + && W_CheckNumForName("M_EPISOD") < 0 && W_CheckNumForName("M_EPI1") < 0 + && W_CheckNumForName("M_EPI2") < 0 && W_CheckNumForName("M_EPI3") < 0 + && W_CheckNumForName("WIOSTF") < 0 && W_CheckNumForName("WIOBJ") >= 0); +} + +// Load dehacked patches needed for certain IWADs. +static void LoadIwadDeh(void) +{ + // The Freedoom IWADs have DEHACKED lumps that must be loaded. + if (gamevariant == freedoom || gamevariant == freedm) + { + // Old versions of Freedoom (before 2014-09) did not have technically + // valid DEHACKED lumps, so ignore errors and just continue if this + // is an old IWAD. + DEH_LoadLumpByName("DEHACKED", false, true); + } + + // If this is the HACX IWAD, we need to load the DEHACKED lump. + if (gameversion == exe_hacx) + { + if (!DEH_LoadLumpByName("DEHACKED", true, false)) + { + I_Error("DEHACKED lump not found. Please check that this is the " + "Hacx v1.2 IWAD."); + } + } + + // Chex Quest needs a separate Dehacked patch which must be downloaded + // and installed next to the IWAD. + if (gameversion == exe_chex) + { + char *chex_deh = NULL; + char *dirname; + + // Look for chex.deh in the same directory as the IWAD file. + dirname = M_DirName(iwadfile); + chex_deh = M_StringJoin(dirname, DIR_SEPARATOR_S, "chex.deh", NULL); + free(dirname); + + // If the dehacked patch isn't found, try searching the WAD + // search path instead. We might find it... + if (!M_FileExists(chex_deh)) + { + free(chex_deh); + chex_deh = D_FindWADByName("chex.deh"); + } + + // Still not found? + if (chex_deh == NULL) + { + I_Error("Unable to find Chex Quest dehacked file (chex.deh).\n" + "The dehacked file is required in order to emulate\n" + "chex.exe correctly. It can be found in your nearest\n" + "/idgames repository mirror at:\n\n" + " themes/chex/chexdeh.zip"); + } + + if (!DEH_LoadFile(chex_deh)) + { + I_Error("Failed to load chex.deh needed for emulating chex.exe."); + } + } + + if (IsFrenchIWAD()) + { + char *french_deh = NULL; + char *dirname; + + // Look for french.deh in the same directory as the IWAD file. + dirname = M_DirName(iwadfile); + french_deh = M_StringJoin(dirname, DIR_SEPARATOR_S, "french.deh", NULL); + printf("French version\n"); + free(dirname); + + // If the dehacked patch isn't found, try searching the WAD + // search path instead. We might find it... + if (!M_FileExists(french_deh)) + { + free(french_deh); + french_deh = D_FindWADByName("french.deh"); + } + + // Still not found? + if (french_deh == NULL) + { + I_Error("Unable to find French Doom II dehacked file\n" + "(french.deh). The dehacked file is required in order to\n" + "emulate French doom2.exe correctly. It can be found in\n" + "your nearest /idgames repository mirror at:\n\n" + " utils/exe_edit/patches/french.zip"); + } + + if (!DEH_LoadFile(french_deh)) + { + I_Error("Failed to load french.deh needed for emulating French\n" + "doom2.exe."); + } + } +} + +static void G_CheckDemoStatusAtExit (void) +{ + G_CheckDemoStatus(); +} + +// +// D_DoomMain +// +void D_DoomMain (void) +{ + int p; + char file[256]; + char demolumpname[9]; + + I_AtExit(D_Endoom, false); + + // print banner + + I_PrintBanner(PACKAGE_STRING); + + DEH_printf("Z_Init: Init zone memory allocation daemon. \n"); + Z_Init (); + + //! + // @category net + // + // Start a dedicated server, routing packets but not participating + // in the game itself. + // + + if (M_CheckParm("-dedicated") > 0) + { + printf("Dedicated server mode.\n"); + NET_DedicatedServer(); + + // Never returns + } + + //! + // @category net + // + // Query the Internet master server for a global list of active + // servers. + // + + if (M_CheckParm("-search")) + { + NET_MasterQuery(); + exit(0); + } + + //! + // @arg
+ // @category net + // + // Query the status of the server running on the given IP + // address. + // + + p = M_CheckParmWithArgs("-query", 1); + + if (p) + { + NET_QueryAddress(myargv[p+1]); + exit(0); + } + + //! + // @category net + // + // Search the local LAN for running servers. + // + + if (M_CheckParm("-localsearch")) + { + NET_LANQuery(); + exit(0); + } + + //! + // @category game + // @vanilla + // + // Disable monsters. + // + + nomonsters = M_CheckParm ("-nomonsters"); + + //! + // @category game + // @vanilla + // + // Monsters respawn after being killed. + // + + respawnparm = M_CheckParm ("-respawn"); + + //! + // @category game + // @vanilla + // + // Monsters move faster. + // + + fastparm = M_CheckParm ("-fast"); + + //! + // @vanilla + // + // Developer mode. F1 saves a screenshot in the current working + // directory. + // + + devparm = M_CheckParm ("-devparm"); + + I_DisplayFPSDots(devparm); + + //! + // @category net + // @vanilla + // + // Start a deathmatch game. + // + + if (M_CheckParm ("-deathmatch")) + deathmatch = 1; + + //! + // @category net + // @vanilla + // + // Start a deathmatch 2.0 game. Weapons do not stay in place and + // all items respawn after 30 seconds. + // + + if (M_CheckParm ("-altdeath")) + deathmatch = 2; + + if (devparm) + DEH_printf(D_DEVSTR); + + // find which dir to use for config files + +#ifdef _WIN32 + + //! + // @category obscure + // @platform windows + // @vanilla + // + // Save configuration data and savegames in c:\doomdata, + // allowing play from CD. + // + + if (M_ParmExists("-cdrom")) + { + printf(D_CDROM); + + M_SetConfigDir("c:\\doomdata\\"); + } + else +#endif + { + // Auto-detect the configuration dir. + + M_SetConfigDir(NULL); + } + + //! + // @category game + // @arg + // @vanilla + // + // Turbo mode. The player's speed is multiplied by x%. If unspecified, + // x defaults to 200. Values are rounded up to 10 and down to 400. + // + + if ( (p=M_CheckParm ("-turbo")) ) + { + int scale = 200; + + if (p 400) + scale = 400; + DEH_printf("turbo scale: %i%%\n", scale); + forwardmove[0] = forwardmove[0]*scale/100; + forwardmove[1] = forwardmove[1]*scale/100; + sidemove[0] = sidemove[0]*scale/100; + sidemove[1] = sidemove[1]*scale/100; + } + + // init subsystems + DEH_printf("V_Init: allocate screens.\n"); + V_Init (); + + // Load configuration files before initialising other subsystems. + DEH_printf("M_LoadDefaults: Load system defaults.\n"); + M_SetConfigFilenames("default.cfg", PROGRAM_PREFIX "doom.cfg"); + D_BindVariables(); + M_LoadDefaults(); + + // Save configuration at exit. + I_AtExit(M_SaveDefaults, false); + + // Find main IWAD file and load it. + iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission); + + // None found? + + if (iwadfile == NULL) + { + I_Error("Game mode indeterminate. No IWAD file was found. Try\n" + "specifying one with the '-iwad' command line parameter.\n"); + } + + modifiedgame = false; + + DEH_printf("W_Init: Init WADfiles.\n"); + D_AddFile(iwadfile); + + W_CheckCorrectIWAD(doom); + + // Now that we've loaded the IWAD, we can figure out what gamemission + // we're playing and which version of Vanilla Doom we need to emulate. + D_IdentifyVersion(); + InitGameVersion(); + + // Check which IWAD variant we are using. + + if (W_CheckNumForName("FREEDOOM") >= 0) + { + if (W_CheckNumForName("FREEDM") >= 0) + { + gamevariant = freedm; + } + else + { + gamevariant = freedoom; + } + } + else if (W_CheckNumForName("DMENUPIC") >= 0) + { + gamevariant = bfgedition; + } + + //! + // @category mod + // + // Disable automatic loading of Dehacked patches for certain + // IWAD files. + // + if (!M_ParmExists("-nodeh")) + { + // Some IWADs have dehacked patches that need to be loaded for + // them to be played properly. + LoadIwadDeh(); + } + + // Doom 3: BFG Edition includes modified versions of the classic + // IWADs which can be identified by an additional DMENUPIC lump. + // Furthermore, the M_GDHIGH lumps have been modified in a way that + // makes them incompatible to Vanilla Doom and the modified version + // of doom2.wad is missing the TITLEPIC lump. + // We specifically check for DMENUPIC here, before PWADs have been + // loaded which could probably include a lump of that name. + + if (gamevariant == bfgedition) + { + printf("BFG Edition: Using workarounds as needed.\n"); + + // BFG Edition changes the names of the secret levels to + // censor the Wolfenstein references. It also has an extra + // secret level (MAP33). In Vanilla Doom (meaning the DOS + // version), MAP33 overflows into the Plutonia level names + // array, so HUSTR_33 is actually PHUSTR_1. + DEH_AddStringReplacement(HUSTR_31, "level 31: idkfa"); + DEH_AddStringReplacement(HUSTR_32, "level 32: keen"); + DEH_AddStringReplacement(PHUSTR_1, "level 33: betray"); + + // The BFG edition doesn't have the "low detail" menu option (fair + // enough). But bizarrely, it reuses the M_GDHIGH patch as a label + // for the options menu (says "Fullscreen:"). Why the perpetrators + // couldn't just add a new graphic lump and had to reuse this one, + // I don't know. + // + // The end result is that M_GDHIGH is too wide and causes the game + // to crash. As a workaround to get a minimum level of support for + // the BFG edition IWADs, use the "ON"/"OFF" graphics instead. + DEH_AddStringReplacement("M_GDHIGH", "M_MSGON"); + DEH_AddStringReplacement("M_GDLOW", "M_MSGOFF"); + + // The BFG edition's "Screen Size:" graphic has also been changed + // to say "Gamepad:". Fortunately, it (along with the original + // Doom IWADs) has an unused graphic that says "Display". So we + // can swap this in instead, and it kind of makes sense. + DEH_AddStringReplacement("M_SCRNSZ", "M_DISP"); + } + + //! + // @category mod + // + // Disable auto-loading of .wad and .deh files. + // + if (!M_ParmExists("-noautoload") && gamemode != shareware) + { + char *autoload_dir; + + // common auto-loaded files for all Doom flavors + + if (gamemission < pack_chex) + { + autoload_dir = M_GetAutoloadDir("doom-all"); + if (autoload_dir != NULL) + { + DEH_AutoLoadPatches(autoload_dir); + W_AutoLoadWADs(autoload_dir); + free(autoload_dir); + } + } + + // auto-loaded files per IWAD + autoload_dir = M_GetAutoloadDir(D_SaveGameIWADName(gamemission, gamevariant)); + if (autoload_dir != NULL) + { + DEH_AutoLoadPatches(autoload_dir); + W_AutoLoadWADs(autoload_dir); + free(autoload_dir); + } + } + + // Load Dehacked patches specified on the command line with -deh. + // Note that there's a very careful and deliberate ordering to how + // Dehacked patches are loaded. The order we use is: + // 1. IWAD dehacked patches. + // 2. Command line dehacked patches specified with -deh. + // 3. PWAD dehacked patches in DEHACKED lumps. + DEH_ParseCommandLine(); + + // Load PWAD files. + modifiedgame = W_ParseCommandLine(); + + // Debug: +// W_PrintDirectory(); + + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp. + // + + p = M_CheckParmWithArgs ("-playdemo", 1); + + if (!p) + { + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp, determining the framerate + // of the screen. + // + p = M_CheckParmWithArgs("-timedemo", 1); + + } + + if (p) + { + char *uc_filename = strdup(myargv[p + 1]); + M_ForceUppercase(uc_filename); + + // With Vanilla you have to specify the file without extension, + // but make that optional. + if (M_StringEndsWith(uc_filename, ".LMP")) + { + M_StringCopy(file, myargv[p + 1], sizeof(file)); + } + else + { + DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p+1]); + } + + free(uc_filename); + + if (D_AddFile(file)) + { + M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, + sizeof(demolumpname)); + } + else + { + // If file failed to load, still continue trying to play + // the demo in the same way as Vanilla Doom. This makes + // tricks like "-playdemo demo1" possible. + + M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); + } + + printf("Playing demo %s.\n", file); + } + + I_AtExit(G_CheckDemoStatusAtExit, true); + + // Generate the WAD hash table. Speed things up a bit. + W_GenerateHashTable(); + + // Load DEHACKED lumps from WAD files - but only if we give the right + // command line parameter. + + //! + // @category mod + // + // Load Dehacked patches from DEHACKED lumps contained in one of the + // loaded PWAD files. + // + if (M_ParmExists("-dehlump")) + { + int i, loaded = 0; + int numiwadlumps = numlumps; + + while (!W_IsIWADLump(lumpinfo[numiwadlumps - 1])) + { + numiwadlumps--; + } + + for (i = numiwadlumps; i < numlumps; ++i) + { + if (!strncmp(lumpinfo[i]->name, "DEHACKED", 8)) + { + DEH_LoadLump(i, false, false); + loaded++; + } + } + + printf(" loaded %i DEHACKED lumps from PWAD files.\n", loaded); + } + + // Set the gamedescription string. This is only possible now that + // we've finished loading Dehacked patches. + D_SetGameDescription(); + + savegamedir = M_GetSaveGameDir(D_SaveGameIWADName(gamemission, gamevariant)); + + // Check for -file in shareware + if (modifiedgame && (gamevariant != freedoom)) + { + // These are the lumps that will be checked in IWAD, + // if any one is not present, execution will be aborted. + char name[23][8]= + { + "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9", + "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9", + "dphoof","bfgga0","heada1","cybra1","spida1d1" + }; + int i; + + if ( gamemode == shareware) + I_Error(DEH_String("\nYou cannot -file with the shareware " + "version. Register!")); + + // Check for fake IWAD with right name, + // but w/o all the lumps of the registered version. + if (gamemode == registered) + for (i = 0;i < 23; i++) + if (W_CheckNumForName(name[i])<0) + I_Error(DEH_String("\nThis is not the registered version.")); + } + + if (W_CheckNumForName("SS_START") >= 0 + || W_CheckNumForName("FF_END") >= 0) + { + I_PrintDivider(); + printf(" WARNING: The loaded WAD file contains modified sprites or\n" + " floor textures. You may want to use the '-merge' command\n" + " line option instead of '-file'.\n"); + } + + I_PrintStartupBanner(gamedescription); + PrintDehackedBanners(); + + DEH_printf("I_Init: Setting up machine state.\n"); + I_CheckIsScreensaver(); + I_InitTimer(); + I_InitJoystick(); + I_InitSound(doom); + I_InitMusic(); + + printf ("NET_Init: Init network subsystem.\n"); + NET_Init (); + + // Initial netgame startup. Connect to server etc. + D_ConnectNetGame(); + + // get skill / episode / map from parms + startskill = sk_medium; + startepisode = 1; + startmap = 1; + autostart = false; + + //! + // @category game + // @arg + // @vanilla + // + // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of + // 0 disables all monsters. + // + + p = M_CheckParmWithArgs("-skill", 1); + + if (p) + { + startskill = myargv[p+1][0]-'1'; + autostart = true; + } + + //! + // @category game + // @arg + // @vanilla + // + // Start playing episode n (1-4). + // + + p = M_CheckParmWithArgs("-episode", 1); + + if (p) + { + startepisode = myargv[p+1][0]-'0'; + startmap = 1; + autostart = true; + } + + timelimit = 0; + + //! + // @arg + // @category net + // @vanilla + // + // For multiplayer games: exit each level after n minutes. + // + + p = M_CheckParmWithArgs("-timer", 1); + + if (p) + { + timelimit = atoi(myargv[p+1]); + } + + //! + // @category net + // @vanilla + // + // Austin Virtual Gaming: end levels after 20 minutes. + // + + p = M_CheckParm ("-avg"); + + if (p) + { + timelimit = 20; + } + + //! + // @category game + // @arg [ | ] + // @vanilla + // + // Start a game immediately, warping to ExMy (Doom 1) or MAPxy + // (Doom 2). + // + + p = M_CheckParmWithArgs("-warp", 1); + + if (p) + { + if (gamemode == commercial) + startmap = atoi (myargv[p+1]); + else + { + startepisode = myargv[p+1][0]-'0'; + + if (p + 2 < myargc) + { + startmap = myargv[p+2][0]-'0'; + } + else + { + startmap = 1; + } + } + autostart = true; + } + + // Undocumented: + // Invoked by setup to test the controls. + + p = M_CheckParm("-testcontrols"); + + if (p > 0) + { + startepisode = 1; + startmap = 1; + autostart = true; + testcontrols = true; + } + + // Check for load game parameter + // We do this here and save the slot number, so that the network code + // can override it or send the load slot to other players. + + //! + // @category game + // @arg + // @vanilla + // + // Load the game in slot s. + // + + p = M_CheckParmWithArgs("-loadgame", 1); + + if (p) + { + startloadgame = atoi(myargv[p+1]); + } + else + { + // Not loading a game + startloadgame = -1; + } + + DEH_printf("M_Init: Init miscellaneous info.\n"); + M_Init (); + + DEH_printf("R_Init: Init DOOM refresh daemon - "); + R_Init (); + + DEH_printf("\nP_Init: Init Playloop state.\n"); + P_Init (); + + DEH_printf("S_Init: Setting up sound.\n"); + S_Init (sfxVolume * 8, musicVolume * 8); + + DEH_printf("D_CheckNetGame: Checking network game status.\n"); + D_CheckNetGame (); + + PrintGameVersion(); + + DEH_printf("HU_Init: Setting up heads up display.\n"); + HU_Init (); + + DEH_printf("ST_Init: Init status bar.\n"); + ST_Init (); + + // If Doom II without a MAP01 lump, this is a store demo. + // Moved this here so that MAP01 isn't constantly looked up + // in the main loop. + + if (gamemode == commercial && W_CheckNumForName("map01") < 0) + storedemo = true; + + if (M_CheckParmWithArgs("-statdump", 1)) + { + I_AtExit(StatDump, true); + DEH_printf("External statistics registered.\n"); + } + + //! + // @arg + // @category demo + // @vanilla + // + // Record a demo named x.lmp. + // + + p = M_CheckParmWithArgs("-record", 1); + + if (p) + { + G_RecordDemo (myargv[p+1]); + autostart = true; + } + + p = M_CheckParmWithArgs("-playdemo", 1); + if (p) + { + singledemo = true; // quit after one demo + G_DeferedPlayDemo (demolumpname); + D_DoomLoop (); // never returns + } + + p = M_CheckParmWithArgs("-timedemo", 1); + if (p) + { + G_TimeDemo (demolumpname); + D_DoomLoop (); // never returns + } + + if (startloadgame >= 0) + { + M_StringCopy(file, P_SaveGameFile(startloadgame), sizeof(file)); + G_LoadGame(file); + } + + if (gameaction != ga_loadgame ) + { + if (autostart || netgame) + G_InitNew (startskill, startepisode, startmap); + else + D_StartTitle (); // start up intro loop + } + + D_DoomLoop (); // never returns +} + diff --git a/games/NXDoom/src/doom/d_main.h b/games/NXDoom/src/doom/d_main.h new file mode 100644 index 00000000000..8e430f85fad --- /dev/null +++ b/games/NXDoom/src/doom/d_main.h @@ -0,0 +1,53 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System specific interface stuff. +// + + +#ifndef __D_MAIN__ +#define __D_MAIN__ + +#include "doomdef.h" + + + + +// Read events from all input devices + +void D_ProcessEvents (void); + + +// +// BASE LEVEL +// +void D_PageTicker (void); +void D_PageDrawer (void); +void D_AdvanceDemo (void); +void D_DoAdvanceDemo (void); +void D_StartTitle (void); + +// +// GLOBAL VARIABLES +// + +extern gameaction_t gameaction; +extern boolean advancedemo; + +extern const char *pagename; + + +#endif + diff --git a/games/NXDoom/src/doom/d_net.c b/games/NXDoom/src/doom/d_net.c new file mode 100644 index 00000000000..f8969fe0289 --- /dev/null +++ b/games/NXDoom/src/doom/d_net.c @@ -0,0 +1,287 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM Network game communication and protocol, +// all OS independend parts. +// + +#include + +#include "d_main.h" +#include "m_argv.h" +#include "m_menu.h" +#include "m_misc.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "g_game.h" +#include "doomdef.h" +#include "doomstat.h" +#include "w_checksum.h" +#include "w_wad.h" + +#include "deh_main.h" + +#include "d_loop.h" + +ticcmd_t *netcmds; + +// Called when a player leaves the game + +static void PlayerQuitGame(player_t *player) +{ + static char exitmsg[80]; + unsigned int player_num; + + player_num = player - players; + + // Do this the same way as Vanilla Doom does, to allow dehacked + // replacements of this message + + M_StringCopy(exitmsg, DEH_String("Player 1 left the game"), + sizeof(exitmsg)); + + exitmsg[7] += player_num; + + playeringame[player_num] = false; + players[consoleplayer].message = exitmsg; + + // TODO: check if it is sensible to do this: + + if (demorecording) + { + G_CheckDemoStatus (); + } +} + +static void RunTic(ticcmd_t *cmds, boolean *ingame) +{ + unsigned int i; + + // Check for player quits. + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!demoplayback && playeringame[i] && !ingame[i]) + { + PlayerQuitGame(&players[i]); + } + } + + netcmds = cmds; + + // check that there are players in the game. if not, we cannot + // run a tic. + + if (advancedemo) + D_DoAdvanceDemo (); + + G_Ticker (); +} + +static loop_interface_t doom_loop_interface = { + D_ProcessEvents, + G_BuildTiccmd, + RunTic, + M_Ticker +}; + + +// Load game settings from the specified structure and +// set global variables. + +static void LoadGameSettings(net_gamesettings_t *settings) +{ + unsigned int i; + + deathmatch = settings->deathmatch; + startepisode = settings->episode; + startmap = settings->map; + startskill = settings->skill; + startloadgame = settings->loadgame; + lowres_turn = settings->lowres_turn; + nomonsters = settings->nomonsters; + fastparm = settings->fast_monsters; + respawnparm = settings->respawn_monsters; + timelimit = settings->timelimit; + consoleplayer = settings->consoleplayer; + + if (lowres_turn) + { + printf("NOTE: Turning resolution is reduced; this is probably " + "because there is a client recording a Vanilla demo.\n"); + } + + for (i = 0; i < MAXPLAYERS; ++i) + { + playeringame[i] = i < settings->num_players; + } +} + +// Save the game settings from global variables to the specified +// game settings structure. + +static void SaveGameSettings(net_gamesettings_t *settings) +{ + // Fill in game settings structure with appropriate parameters + // for the new game + + settings->deathmatch = deathmatch; + settings->episode = startepisode; + settings->map = startmap; + settings->skill = startskill; + settings->loadgame = startloadgame; + settings->gameversion = gameversion; + settings->nomonsters = nomonsters; + settings->fast_monsters = fastparm; + settings->respawn_monsters = respawnparm; + settings->timelimit = timelimit; + + settings->lowres_turn = (M_ParmExists("-record") + && !M_ParmExists("-longtics")) + || M_ParmExists("-shorttics"); +} + +static void InitConnectData(net_connect_data_t *connect_data) +{ + boolean shorttics; + + connect_data->max_players = MAXPLAYERS; + connect_data->drone = false; + + //! + // @category net + // + // Run as the left screen in three screen mode. + // + + if (M_CheckParm("-left") > 0) + { + viewangleoffset = ANG90; + connect_data->drone = true; + } + + //! + // @category net + // + // Run as the right screen in three screen mode. + // + + if (M_CheckParm("-right") > 0) + { + viewangleoffset = ANG270; + connect_data->drone = true; + } + + // + // Connect data + // + + // Game type fields: + + connect_data->gamemode = gamemode; + connect_data->gamemission = gamemission; + + //! + // @category demo + // + // Play with low turning resolution to emulate demo recording. + // + + shorttics = M_ParmExists("-shorttics"); + + // Are we recording a demo? Possibly set lowres turn mode + + connect_data->lowres_turn = (M_ParmExists("-record") + && !M_ParmExists("-longtics")) + || shorttics; + + // Read checksums of our WAD directory and dehacked information + + W_Checksum(connect_data->wad_sha1sum); + DEH_Checksum(connect_data->deh_sha1sum); + + // Are we playing with the Freedoom IWAD? + + connect_data->is_freedoom = W_CheckNumForName("FREEDOOM") >= 0; +} + +void D_ConnectNetGame(void) +{ + net_connect_data_t connect_data; + + InitConnectData(&connect_data); + netgame = D_InitNetGame(&connect_data); + + //! + // @category net + // + // Start the game playing as though in a netgame with a single + // player. This can also be used to play back single player netgame + // demos. + // + + if (M_CheckParm("-solo-net") > 0) + { + netgame = true; + } +} + +// +// D_CheckNetGame +// Works out player numbers among the net participants +// +void D_CheckNetGame (void) +{ + net_gamesettings_t settings; + + if (netgame) + { + autostart = true; + } + + D_RegisterLoopCallbacks(&doom_loop_interface); + + SaveGameSettings(&settings); + D_StartNetGame(&settings, NULL); + LoadGameSettings(&settings); + + DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", + startskill, deathmatch, startmap, startepisode); + + DEH_printf("player %i of %i (%i nodes)\n", + consoleplayer+1, settings.num_players, settings.num_players); + + // Show players here; the server might have specified a time limit + + if (timelimit > 0 && deathmatch) + { + // Gross hack to work like Vanilla: + + if (timelimit == 20 && M_CheckParm("-avg")) + { + DEH_printf("Austin Virtual Gaming: Levels will end " + "after 20 minutes\n"); + } + else + { + DEH_printf("Levels will end after %d minute", timelimit); + if (timelimit > 1) + printf("s"); + printf(".\n"); + } + } +} + diff --git a/games/NXDoom/src/doom/d_player.h b/games/NXDoom/src/doom/d_player.h new file mode 100644 index 00000000000..d78482d0e00 --- /dev/null +++ b/games/NXDoom/src/doom/d_player.h @@ -0,0 +1,209 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __D_PLAYER__ +#define __D_PLAYER__ + + +// The player data structure depends on a number +// of other structs: items (internal inventory), +// animation states (closely tied to the sprites +// used to represent them, unfortunately). +#include "d_items.h" +#include "p_pspr.h" + +// In addition, the player is just a special +// case of the generic moving object/actor. +#include "p_mobj.h" + +// Finally, for odd reasons, the player input +// is buffered within the player data struct, +// as commands per game tick. +#include "d_ticcmd.h" + +#include "net_defs.h" + + + + +// +// Player states. +// +typedef enum +{ + // Playing or camping. + PST_LIVE, + // Dead on the ground, view follows killer. + PST_DEAD, + // Ready to restart/respawn??? + PST_REBORN + +} playerstate_t; + + +// +// Player internal flags, for cheats and debug. +// +typedef enum +{ + // No clipping, walk through barriers. + CF_NOCLIP = 1, + // No damage, no health loss. + CF_GODMODE = 2, + // Not really a cheat, just a debug aid. + CF_NOMOMENTUM = 4 + +} cheat_t; + + +// +// Extended player object info: player_t +// +typedef struct player_s +{ + mobj_t* mo; + playerstate_t playerstate; + ticcmd_t cmd; + + // Determine POV, + // including viewpoint bobbing during movement. + // Focal origin above r.z + fixed_t viewz; + // Base height above floor for viewz. + fixed_t viewheight; + // Bob/squat speed. + fixed_t deltaviewheight; + // bounded/scaled total momentum. + fixed_t bob; + + // This is only used between levels, + // mo->health is used during levels. + int health; + int armorpoints; + // Armor type is 0-2. + int armortype; + + // Power ups. invinc and invis are tic counters. + int powers[NUMPOWERS]; + boolean cards[NUMCARDS]; + boolean backpack; + + // Frags, kills of other players. + int frags[MAXPLAYERS]; + weapontype_t readyweapon; + + // Is wp_nochange if not changing. + weapontype_t pendingweapon; + + int weaponowned[NUMWEAPONS]; + int ammo[NUMAMMO]; + int maxammo[NUMAMMO]; + + // True if button down last tic. + int attackdown; + int usedown; + + // Bit flags, for cheats and debug. + // See cheat_t, above. + int cheats; + + // Refired shots are less accurate. + int refire; + + // For intermission stats. + int killcount; + int itemcount; + int secretcount; + + // Hint messages. + const char *message; + + // For screen flashing (red or bright). + int damagecount; + int bonuscount; + + // Who did damage (NULL for floors/ceilings). + mobj_t* attacker; + + // So gun flashes light up areas. + int extralight; + + // Current PLAYPAL, ??? + // can be set to REDCOLORMAP for pain, etc. + int fixedcolormap; + + // Player skin colorshift, + // 0-3 for which color to draw player. + int colormap; + + // Overlay view sprites (gun, etc). + pspdef_t psprites[NUMPSPRITES]; + + // True if secret level has been done. + boolean didsecret; + +} player_t; + + +// +// INTERMISSION +// Structure passed e.g. to WI_Start(wb) +// +typedef struct +{ + boolean in; // whether the player is in game + + // Player stats, kills, collected items etc. + int skills; + int sitems; + int ssecret; + int stime; + int frags[4]; + int score; // current score on entry, modified on return + +} wbplayerstruct_t; + +typedef struct +{ + int epsd; // episode # (0-2) + + // if true, splash the secret level + boolean didsecret; + + // previous and next levels, origin 0 + int last; + int next; + + int maxkills; + int maxitems; + int maxsecret; + int maxfrags; + + // the par time + int partime; + + // index of this player in game + int pnum; + + wbplayerstruct_t plyr[MAXPLAYERS]; + +} wbstartstruct_t; + + +#endif diff --git a/games/NXDoom/src/doom/d_textur.h b/games/NXDoom/src/doom/d_textur.h new file mode 100644 index 00000000000..1afe040eb04 --- /dev/null +++ b/games/NXDoom/src/doom/d_textur.h @@ -0,0 +1,43 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Typedefs related to to textures etc., +// isolated here to make it easier separating modules. +// + + +#ifndef __D_TEXTUR__ +#define __D_TEXTUR__ + +#include "doomtype.h" + + + + +// +// Flats? +// +// a pic is an unmasked block of pixels +typedef struct +{ + byte width; + byte height; + byte data; +} pic_t; + + + + +#endif diff --git a/games/NXDoom/src/doom/d_think.h b/games/NXDoom/src/doom/d_think.h new file mode 100644 index 00000000000..0966ad96023 --- /dev/null +++ b/games/NXDoom/src/doom/d_think.h @@ -0,0 +1,68 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// MapObj data. Map Objects or mobjs are actors, entities, +// thinker, take-your-pick... anything that moves, acts, or +// suffers state changes of more or less violent nature. +// + + +#ifndef __D_THINK__ +#define __D_THINK__ + + + + + +// +// Experimental stuff. +// To compile this as "ANSI C with classes" +// we will need to handle the various +// action functions cleanly. +// +typedef void (*actionf_v)(); +typedef void (*actionf_p1)( void* ); +typedef void (*actionf_p2)( void*, void* ); + +typedef union +{ + actionf_v acv; + actionf_p1 acp1; + actionf_p2 acp2; + +} actionf_t; + + + + + +// Historically, "think_t" is yet another +// function pointer to a routine to handle +// an actor. +typedef actionf_t think_t; + + +// Doubly linked list of actors. +typedef struct thinker_s +{ + struct thinker_s* prev; + struct thinker_s* next; + think_t function; + +} thinker_t; + + + +#endif diff --git a/games/NXDoom/src/doom/deh_ammo.c b/games/NXDoom/src/doom/deh_ammo.c new file mode 100644 index 00000000000..dd8bee54678 --- /dev/null +++ b/games/NXDoom/src/doom/deh_ammo.c @@ -0,0 +1,103 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Ammo" sections in dehacked files +// + +#include +#include +#include + +#include "doomdef.h" +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "p_local.h" + +static void *DEH_AmmoStart(deh_context_t *context, char *line) +{ + int ammo_number = 0; + + if (sscanf(line, "Ammo %i", &ammo_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (ammo_number < 0 || ammo_number >= NUMAMMO) + { + DEH_Warning(context, "Invalid ammo number: %i", ammo_number); + return NULL; + } + + return &maxammo[ammo_number]; +} + +static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + int ivalue; + int ammo_number; + + if (tag == NULL) + return; + + ammo_number = ((int *) tag) - maxammo; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + // maxammo + + if (!strcasecmp(variable_name, "Per ammo")) + clipammo[ammo_number] = ivalue; + else if (!strcasecmp(variable_name, "Max ammo")) + maxammo[ammo_number] = ivalue; + else + { + DEH_Warning(context, "Field named '%s' not found", variable_name); + } +} + +static void DEH_AmmoSHA1Hash(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" + +#include "dstrings.h" + +typedef struct { + const char *macro; + const char *string; +} bex_string_t; + +// mnemonic keys table +static const bex_string_t bex_stringtable[] = { + // part 1 - general initialization and prompts + {"D_DEVSTR", D_DEVSTR}, + {"D_CDROM", D_CDROM}, + {"QUITMSG", QUITMSG}, + {"LOADNET", LOADNET}, + {"QLOADNET", QLOADNET}, + {"QSAVESPOT", QSAVESPOT}, + {"SAVEDEAD", SAVEDEAD}, + {"QSPROMPT", QSPROMPT}, + {"QLPROMPT", QLPROMPT}, + {"NEWGAME", NEWGAME}, + {"NIGHTMARE", NIGHTMARE}, + {"SWSTRING", SWSTRING}, + {"MSGOFF", MSGOFF}, + {"MSGON", MSGON}, + {"NETEND", NETEND}, + {"ENDGAME", ENDGAME}, + {"DETAILHI", DETAILHI}, + {"DETAILLO", DETAILLO}, + {"GAMMALVL0", GAMMALVL0}, + {"GAMMALVL1", GAMMALVL1}, + {"GAMMALVL2", GAMMALVL2}, + {"GAMMALVL3", GAMMALVL3}, + {"GAMMALVL4", GAMMALVL4}, + {"EMPTYSTRING", EMPTYSTRING}, + {"GGSAVED", GGSAVED}, + {"SAVEGAMENAME", SAVEGAMENAME}, + // part 2 - messages when the player gets things + {"GOTARMOR", GOTARMOR}, + {"GOTMEGA", GOTMEGA}, + {"GOTHTHBONUS", GOTHTHBONUS}, + {"GOTARMBONUS", GOTARMBONUS}, + {"GOTSTIM", GOTSTIM}, + {"GOTMEDINEED", GOTMEDINEED}, + {"GOTMEDIKIT", GOTMEDIKIT}, + {"GOTSUPER", GOTSUPER}, + {"GOTBLUECARD", GOTBLUECARD}, + {"GOTYELWCARD", GOTYELWCARD}, + {"GOTREDCARD", GOTREDCARD}, + {"GOTBLUESKUL", GOTBLUESKUL}, + {"GOTYELWSKUL", GOTYELWSKUL}, + {"GOTREDSKULL", GOTREDSKULL}, + {"GOTINVUL", GOTINVUL}, + {"GOTBERSERK", GOTBERSERK}, + {"GOTINVIS", GOTINVIS}, + {"GOTSUIT", GOTSUIT}, + {"GOTMAP", GOTMAP}, + {"GOTVISOR", GOTVISOR}, + {"GOTMSPHERE", GOTMSPHERE}, + {"GOTCLIP", GOTCLIP}, + {"GOTCLIPBOX", GOTCLIPBOX}, + {"GOTROCKET", GOTROCKET}, + {"GOTROCKBOX", GOTROCKBOX}, + {"GOTCELL", GOTCELL}, + {"GOTCELLBOX", GOTCELLBOX}, + {"GOTSHELLS", GOTSHELLS}, + {"GOTSHELLBOX", GOTSHELLBOX}, + {"GOTBACKPACK", GOTBACKPACK}, + {"GOTBFG9000", GOTBFG9000}, + {"GOTCHAINGUN", GOTCHAINGUN}, + {"GOTCHAINSAW", GOTCHAINSAW}, + {"GOTLAUNCHER", GOTLAUNCHER}, + {"GOTPLASMA", GOTPLASMA}, + {"GOTSHOTGUN", GOTSHOTGUN}, + {"GOTSHOTGUN2", GOTSHOTGUN2}, + // part 3 - messages when keys are needed + {"PD_BLUEO", PD_BLUEO}, + {"PD_REDO", PD_REDO}, + {"PD_YELLOWO", PD_YELLOWO}, + {"PD_BLUEK", PD_BLUEK}, + {"PD_REDK", PD_REDK}, + {"PD_YELLOWK", PD_YELLOWK}, + // part 4 - multiplayer messaging + {"HUSTR_MSGU", HUSTR_MSGU}, + {"HUSTR_MESSAGESENT", HUSTR_MESSAGESENT}, + {"HUSTR_CHATMACRO0", HUSTR_CHATMACRO0}, + {"HUSTR_CHATMACRO1", HUSTR_CHATMACRO1}, + {"HUSTR_CHATMACRO2", HUSTR_CHATMACRO2}, + {"HUSTR_CHATMACRO3", HUSTR_CHATMACRO3}, + {"HUSTR_CHATMACRO4", HUSTR_CHATMACRO4}, + {"HUSTR_CHATMACRO5", HUSTR_CHATMACRO5}, + {"HUSTR_CHATMACRO6", HUSTR_CHATMACRO6}, + {"HUSTR_CHATMACRO7", HUSTR_CHATMACRO7}, + {"HUSTR_CHATMACRO8", HUSTR_CHATMACRO8}, + {"HUSTR_CHATMACRO9", HUSTR_CHATMACRO9}, + {"HUSTR_TALKTOSELF1", HUSTR_TALKTOSELF1}, + {"HUSTR_TALKTOSELF2", HUSTR_TALKTOSELF2}, + {"HUSTR_TALKTOSELF3", HUSTR_TALKTOSELF3}, + {"HUSTR_TALKTOSELF4", HUSTR_TALKTOSELF4}, + {"HUSTR_TALKTOSELF5", HUSTR_TALKTOSELF5}, + {"HUSTR_PLRGREEN", HUSTR_PLRGREEN}, + {"HUSTR_PLRINDIGO", HUSTR_PLRINDIGO}, + {"HUSTR_PLRBROWN", HUSTR_PLRBROWN}, + {"HUSTR_PLRRED", HUSTR_PLRRED}, + // part 5 - level names in the automap + {"HUSTR_E1M1", HUSTR_E1M1}, + {"HUSTR_E1M2", HUSTR_E1M2}, + {"HUSTR_E1M3", HUSTR_E1M3}, + {"HUSTR_E1M4", HUSTR_E1M4}, + {"HUSTR_E1M5", HUSTR_E1M5}, + {"HUSTR_E1M6", HUSTR_E1M6}, + {"HUSTR_E1M7", HUSTR_E1M7}, + {"HUSTR_E1M8", HUSTR_E1M8}, + {"HUSTR_E1M9", HUSTR_E1M9}, + {"HUSTR_E2M1", HUSTR_E2M1}, + {"HUSTR_E2M2", HUSTR_E2M2}, + {"HUSTR_E2M3", HUSTR_E2M3}, + {"HUSTR_E2M4", HUSTR_E2M4}, + {"HUSTR_E2M5", HUSTR_E2M5}, + {"HUSTR_E2M6", HUSTR_E2M6}, + {"HUSTR_E2M7", HUSTR_E2M7}, + {"HUSTR_E2M8", HUSTR_E2M8}, + {"HUSTR_E2M9", HUSTR_E2M9}, + {"HUSTR_E3M1", HUSTR_E3M1}, + {"HUSTR_E3M2", HUSTR_E3M2}, + {"HUSTR_E3M3", HUSTR_E3M3}, + {"HUSTR_E3M4", HUSTR_E3M4}, + {"HUSTR_E3M5", HUSTR_E3M5}, + {"HUSTR_E3M6", HUSTR_E3M6}, + {"HUSTR_E3M7", HUSTR_E3M7}, + {"HUSTR_E3M8", HUSTR_E3M8}, + {"HUSTR_E3M9", HUSTR_E3M9}, + {"HUSTR_E4M1", HUSTR_E4M1}, + {"HUSTR_E4M2", HUSTR_E4M2}, + {"HUSTR_E4M3", HUSTR_E4M3}, + {"HUSTR_E4M4", HUSTR_E4M4}, + {"HUSTR_E4M5", HUSTR_E4M5}, + {"HUSTR_E4M6", HUSTR_E4M6}, + {"HUSTR_E4M7", HUSTR_E4M7}, + {"HUSTR_E4M8", HUSTR_E4M8}, + {"HUSTR_E4M9", HUSTR_E4M9}, + {"HUSTR_1", HUSTR_1}, + {"HUSTR_2", HUSTR_2}, + {"HUSTR_3", HUSTR_3}, + {"HUSTR_4", HUSTR_4}, + {"HUSTR_5", HUSTR_5}, + {"HUSTR_6", HUSTR_6}, + {"HUSTR_7", HUSTR_7}, + {"HUSTR_8", HUSTR_8}, + {"HUSTR_9", HUSTR_9}, + {"HUSTR_10", HUSTR_10}, + {"HUSTR_11", HUSTR_11}, + {"HUSTR_12", HUSTR_12}, + {"HUSTR_13", HUSTR_13}, + {"HUSTR_14", HUSTR_14}, + {"HUSTR_15", HUSTR_15}, + {"HUSTR_16", HUSTR_16}, + {"HUSTR_17", HUSTR_17}, + {"HUSTR_18", HUSTR_18}, + {"HUSTR_19", HUSTR_19}, + {"HUSTR_20", HUSTR_20}, + {"HUSTR_21", HUSTR_21}, + {"HUSTR_22", HUSTR_22}, + {"HUSTR_23", HUSTR_23}, + {"HUSTR_24", HUSTR_24}, + {"HUSTR_25", HUSTR_25}, + {"HUSTR_26", HUSTR_26}, + {"HUSTR_27", HUSTR_27}, + {"HUSTR_28", HUSTR_28}, + {"HUSTR_29", HUSTR_29}, + {"HUSTR_30", HUSTR_30}, + {"HUSTR_31", HUSTR_31}, + {"HUSTR_32", HUSTR_32}, + {"PHUSTR_1", PHUSTR_1}, + {"PHUSTR_2", PHUSTR_2}, + {"PHUSTR_3", PHUSTR_3}, + {"PHUSTR_4", PHUSTR_4}, + {"PHUSTR_5", PHUSTR_5}, + {"PHUSTR_6", PHUSTR_6}, + {"PHUSTR_7", PHUSTR_7}, + {"PHUSTR_8", PHUSTR_8}, + {"PHUSTR_9", PHUSTR_9}, + {"PHUSTR_10", PHUSTR_10}, + {"PHUSTR_11", PHUSTR_11}, + {"PHUSTR_12", PHUSTR_12}, + {"PHUSTR_13", PHUSTR_13}, + {"PHUSTR_14", PHUSTR_14}, + {"PHUSTR_15", PHUSTR_15}, + {"PHUSTR_16", PHUSTR_16}, + {"PHUSTR_17", PHUSTR_17}, + {"PHUSTR_18", PHUSTR_18}, + {"PHUSTR_19", PHUSTR_19}, + {"PHUSTR_20", PHUSTR_20}, + {"PHUSTR_21", PHUSTR_21}, + {"PHUSTR_22", PHUSTR_22}, + {"PHUSTR_23", PHUSTR_23}, + {"PHUSTR_24", PHUSTR_24}, + {"PHUSTR_25", PHUSTR_25}, + {"PHUSTR_26", PHUSTR_26}, + {"PHUSTR_27", PHUSTR_27}, + {"PHUSTR_28", PHUSTR_28}, + {"PHUSTR_29", PHUSTR_29}, + {"PHUSTR_30", PHUSTR_30}, + {"PHUSTR_31", PHUSTR_31}, + {"PHUSTR_32", PHUSTR_32}, + {"THUSTR_1", THUSTR_1}, + {"THUSTR_2", THUSTR_2}, + {"THUSTR_3", THUSTR_3}, + {"THUSTR_4", THUSTR_4}, + {"THUSTR_5", THUSTR_5}, + {"THUSTR_6", THUSTR_6}, + {"THUSTR_7", THUSTR_7}, + {"THUSTR_8", THUSTR_8}, + {"THUSTR_9", THUSTR_9}, + {"THUSTR_10", THUSTR_10}, + {"THUSTR_11", THUSTR_11}, + {"THUSTR_12", THUSTR_12}, + {"THUSTR_13", THUSTR_13}, + {"THUSTR_14", THUSTR_14}, + {"THUSTR_15", THUSTR_15}, + {"THUSTR_16", THUSTR_16}, + {"THUSTR_17", THUSTR_17}, + {"THUSTR_18", THUSTR_18}, + {"THUSTR_19", THUSTR_19}, + {"THUSTR_20", THUSTR_20}, + {"THUSTR_21", THUSTR_21}, + {"THUSTR_22", THUSTR_22}, + {"THUSTR_23", THUSTR_23}, + {"THUSTR_24", THUSTR_24}, + {"THUSTR_25", THUSTR_25}, + {"THUSTR_26", THUSTR_26}, + {"THUSTR_27", THUSTR_27}, + {"THUSTR_28", THUSTR_28}, + {"THUSTR_29", THUSTR_29}, + {"THUSTR_30", THUSTR_30}, + {"THUSTR_31", THUSTR_31}, + {"THUSTR_32", THUSTR_32}, + // part 6 - messages as a result of toggling states + {"AMSTR_FOLLOWON", AMSTR_FOLLOWON}, + {"AMSTR_FOLLOWOFF", AMSTR_FOLLOWOFF}, + {"AMSTR_GRIDON", AMSTR_GRIDON}, + {"AMSTR_GRIDOFF", AMSTR_GRIDOFF}, + {"AMSTR_MARKEDSPOT", AMSTR_MARKEDSPOT}, + {"AMSTR_MARKSCLEARED", AMSTR_MARKSCLEARED}, + {"STSTR_MUS", STSTR_MUS}, + {"STSTR_NOMUS", STSTR_NOMUS}, + {"STSTR_DQDON", STSTR_DQDON}, + {"STSTR_DQDOFF", STSTR_DQDOFF}, + {"STSTR_KFAADDED", STSTR_KFAADDED}, + {"STSTR_FAADDED", STSTR_FAADDED}, + {"STSTR_NCON", STSTR_NCON}, + {"STSTR_NCOFF", STSTR_NCOFF}, + {"STSTR_BEHOLD", STSTR_BEHOLD}, + {"STSTR_BEHOLDX", STSTR_BEHOLDX}, + {"STSTR_CHOPPERS", STSTR_CHOPPERS}, + {"STSTR_CLEV", STSTR_CLEV}, + // part 7 - episode intermission texts + {"E1TEXT", E1TEXT}, + {"E2TEXT", E2TEXT}, + {"E3TEXT", E3TEXT}, + {"E4TEXT", E4TEXT}, + {"C1TEXT", C1TEXT}, + {"C2TEXT", C2TEXT}, + {"C3TEXT", C3TEXT}, + {"C4TEXT", C4TEXT}, + {"C5TEXT", C5TEXT}, + {"C6TEXT", C6TEXT}, + {"P1TEXT", P1TEXT}, + {"P2TEXT", P2TEXT}, + {"P3TEXT", P3TEXT}, + {"P4TEXT", P4TEXT}, + {"P5TEXT", P5TEXT}, + {"P6TEXT", P6TEXT}, + {"T1TEXT", T1TEXT}, + {"T2TEXT", T2TEXT}, + {"T3TEXT", T3TEXT}, + {"T4TEXT", T4TEXT}, + {"T5TEXT", T5TEXT}, + {"T6TEXT", T6TEXT}, + // part 8 - creature names for the finale + {"CC_ZOMBIE", CC_ZOMBIE}, + {"CC_SHOTGUN", CC_SHOTGUN}, + {"CC_HEAVY", CC_HEAVY}, + {"CC_IMP", CC_IMP}, + {"CC_DEMON", CC_DEMON}, + {"CC_LOST", CC_LOST}, + {"CC_CACO", CC_CACO}, + {"CC_HELL", CC_HELL}, + {"CC_BARON", CC_BARON}, + {"CC_ARACH", CC_ARACH}, + {"CC_PAIN", CC_PAIN}, + {"CC_REVEN", CC_REVEN}, + {"CC_MANCU", CC_MANCU}, + {"CC_ARCH", CC_ARCH}, + {"CC_SPIDER", CC_SPIDER}, + {"CC_CYBER", CC_CYBER}, + {"CC_HERO", CC_HERO}, + // part 9 - intermission tiled backgrounds + {"BGFLATE1", "FLOOR4_8"}, + {"BGFLATE2", "SFLR6_1"}, + {"BGFLATE3", "MFLR8_4"}, + {"BGFLATE4", "MFLR8_3"}, + {"BGFLAT06", "SLIME16"}, + {"BGFLAT11", "RROCK14"}, + {"BGFLAT20", "RROCK07"}, + {"BGFLAT30", "RROCK17"}, + {"BGFLAT15", "RROCK13"}, + {"BGFLAT31", "RROCK19"}, + {"BGCASTCALL", "BOSSBACK"}, +}; + +static void *DEH_BEXStrStart(deh_context_t *context, char *line) +{ + char s[10]; + + if (sscanf(line, "%9s", s) == 0 || strncmp("[STRINGS]", s, sizeof(s))) + { + DEH_Warning(context, "Parse error on section start"); + } + + return NULL; +} + +static void DEH_BEXStrParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + int i; + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + for (i = 0; i < arrlen(bex_stringtable); i++) + { + if (!strcmp(bex_stringtable[i].macro, variable_name)) + { + DEH_AddStringReplacement(bex_stringtable[i].string, value); + } + } +} + +deh_section_t deh_section_bexstr = +{ + "[STRINGS]", + NULL, + DEH_BEXStrStart, + DEH_BEXStrParseLine, + NULL, + NULL, +}; diff --git a/games/NXDoom/src/doom/deh_cheat.c b/games/NXDoom/src/doom/deh_cheat.c new file mode 100644 index 00000000000..8e269c04ef8 --- /dev/null +++ b/games/NXDoom/src/doom/deh_cheat.c @@ -0,0 +1,146 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Cheat" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "am_map.h" +#include "st_stuff.h" + +typedef struct +{ + const char *name; + cheatseq_t *seq; +} deh_cheat_t; + +static deh_cheat_t allcheats[] = +{ + {"Change music", &cheat_mus }, + {"Chainsaw", &cheat_choppers }, + {"God mode", &cheat_god }, + {"Ammo & Keys", &cheat_ammo }, + {"Ammo", &cheat_ammonokey }, + {"No Clipping 1", &cheat_noclip }, + {"No Clipping 2", &cheat_commercial_noclip }, + {"Invincibility", &cheat_powerup[0] }, + {"Berserk", &cheat_powerup[1] }, + {"Invisibility", &cheat_powerup[2] }, + {"Radiation Suit", &cheat_powerup[3] }, + {"Auto-map", &cheat_powerup[4] }, + {"Lite-Amp Goggles", &cheat_powerup[5] }, + {"BEHOLD menu", &cheat_powerup[6] }, + {"Level Warp", &cheat_clev }, + {"Player Position", &cheat_mypos }, + {"Map cheat", &cheat_amap }, +}; + +static deh_cheat_t *FindCheatByName(char *name) +{ + size_t i; + + for (i=0; i= cheat->seq->sequence_len) + { + DEH_Warning(context, "Cheat sequence longer than supported by " + "Vanilla dehacked"); + break; + } + + if (deh_apply_cheats) + { + cheat->seq->sequence[i] = unsvalue[i]; + } + ++i; + + // Absolute limit - don't exceed + + if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars) + { + DEH_Error(context, "Cheat sequence too long!"); + return; + } + } + + if (deh_apply_cheats) + { + cheat->seq->sequence[i] = '\0'; + } +} + +deh_section_t deh_section_cheat = +{ + "Cheat", + NULL, + DEH_CheatStart, + DEH_CheatParseLine, + NULL, + NULL, +}; + diff --git a/games/NXDoom/src/doom/deh_doom.c b/games/NXDoom/src/doom/deh_doom.c new file mode 100644 index 00000000000..b7ff04a738a --- /dev/null +++ b/games/NXDoom/src/doom/deh_doom.c @@ -0,0 +1,48 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Top-level dehacked definitions for Doom dehacked. +// + +#include +#include "deh_defs.h" +#include "deh_main.h" + +const char *deh_signatures[] = +{ + "Patch File for DeHackEd v2.3", + "Patch File for DeHackEd v3.0", + NULL +}; + + +// +// List of section types: +// + +deh_section_t *deh_section_types[] = +{ + &deh_section_ammo, + &deh_section_cheat, + &deh_section_frame, + &deh_section_misc, + &deh_section_pointer, + &deh_section_sound, + &deh_section_text, + &deh_section_thing, + &deh_section_weapon, + &deh_section_bexstr, + NULL +}; + diff --git a/games/NXDoom/src/doom/deh_frame.c b/games/NXDoom/src/doom/deh_frame.c new file mode 100644 index 00000000000..e1cd59da717 --- /dev/null +++ b/games/NXDoom/src/doom/deh_frame.c @@ -0,0 +1,161 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Frame" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" +#include "d_items.h" +#include "info.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "deh_mapping.h" + +DEH_BEGIN_MAPPING(state_mapping, state_t) + DEH_MAPPING("Sprite number", sprite) + DEH_MAPPING("Sprite subnumber", frame) + DEH_MAPPING("Duration", tics) + DEH_MAPPING("Next frame", nextstate) + DEH_MAPPING("Unknown 1", misc1) + DEH_MAPPING("Unknown 2", misc2) + DEH_UNSUPPORTED_MAPPING("Codep frame") +DEH_END_MAPPING + +static void *DEH_FrameStart(deh_context_t *context, char *line) +{ + int frame_number = 0; + state_t *state; + + if (sscanf(line, "Frame %i", &frame_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (frame_number < 0 || frame_number >= NUMSTATES) + { + DEH_Warning(context, "Invalid frame number: %i", frame_number); + return NULL; + } + + if (frame_number >= DEH_VANILLA_NUMSTATES) + { + DEH_Warning(context, "Attempt to modify frame %i: this will cause " + "problems in Vanilla dehacked.", frame_number); + } + + state = &states[frame_number]; + + return state; +} + +// Simulate a frame overflow: Doom has 967 frames in the states[] array, but +// DOS dehacked internally only allocates memory for 966. As a result, +// attempts to set frame 966 (the last frame) will overflow the dehacked +// array and overwrite the weaponinfo[] array instead. +// +// This is noticable in Batman Doom where it is impossible to switch weapons +// away from the fist once selected. + +static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value) +{ + if (!strcasecmp(varname, "Duration")) + { + weaponinfo[0].ammo = value; + } + else if (!strcasecmp(varname, "Codep frame")) + { + weaponinfo[0].upstate = value; + } + else if (!strcasecmp(varname, "Next frame")) + { + weaponinfo[0].downstate = value; + } + else if (!strcasecmp(varname, "Unknown 1")) + { + weaponinfo[0].readystate = value; + } + else if (!strcasecmp(varname, "Unknown 2")) + { + weaponinfo[0].atkstate = value; + } + else + { + DEH_Error(context, "Unable to simulate frame overflow: field '%s'", + varname); + } +} + +static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) +{ + state_t *state; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + state = (state_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + // all values are integers + + ivalue = atoi(value); + + if (state == &states[NUMSTATES - 1]) + { + DEH_FrameOverflow(context, variable_name, ivalue); + } + else + { + // set the appropriate field + + DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); + } +} + +static void DEH_FrameSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "deh_misc.h" + +// Dehacked: "Initial Health" +// This is the initial health a player has when starting anew. +// See G_PlayerReborn in g_game.c + +int deh_initial_health = DEH_DEFAULT_INITIAL_HEALTH; + +// Dehacked: "Initial bullets" +// This is the number of bullets the player has when starting anew. +// See G_PlayerReborn in g_game.c + +int deh_initial_bullets = DEH_DEFAULT_INITIAL_BULLETS; + +// Dehacked: "Max Health" +// This is the maximum health that can be reached using health +// potions. See P_TouchSpecialThing in p_inter.c + +int deh_max_health = DEH_DEFAULT_MAX_HEALTH; + +// Dehacked: "Max Armor" +// This is the maximum armor which can be reached by picking up +// armor helmets. See P_TouchSpecialThing in p_inter.c + +int deh_max_armor = DEH_DEFAULT_MAX_ARMOR; + +// Dehacked: "Green Armor Class" +// This is the armor class that is given when picking up the green +// armor or an armor helmet. See P_TouchSpecialThing in p_inter.c +// +// DOS dehacked only modifies the behavior of the green armor shirt, +// the armor class set by armor helmets is not affected. + +int deh_green_armor_class = DEH_DEFAULT_GREEN_ARMOR_CLASS; + +// Dehacked: "Blue Armor Class" +// This is the armor class that is given when picking up the blue +// armor or a megasphere. See P_TouchSpecialThing in p_inter.c +// +// DOS dehacked only modifies the MegaArmor behavior and not +// the MegaSphere, which always gives armor type 2. + +int deh_blue_armor_class = DEH_DEFAULT_BLUE_ARMOR_CLASS; + +// Dehacked: "Max soulsphere" +// The maximum health which can be reached by picking up the +// soulsphere. See P_TouchSpecialThing in p_inter.c + +int deh_max_soulsphere = DEH_DEFAULT_MAX_SOULSPHERE; + +// Dehacked: "Soulsphere health" +// The amount of health bonus that picking up a soulsphere +// gives. See P_TouchSpecialThing in p_inter.c + +int deh_soulsphere_health = DEH_DEFAULT_SOULSPHERE_HEALTH; + +// Dehacked: "Megasphere health" +// This is what the health is set to after picking up a +// megasphere. See P_TouchSpecialThing in p_inter.c + +int deh_megasphere_health = DEH_DEFAULT_MEGASPHERE_HEALTH; + +// Dehacked: "God mode health" +// This is what the health value is set to when cheating using +// the IDDQD god mode cheat. See ST_Responder in st_stuff.c + +int deh_god_mode_health = DEH_DEFAULT_GOD_MODE_HEALTH; + +// Dehacked: "IDFA Armor" +// This is what the armor is set to when using the IDFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idfa_armor = DEH_DEFAULT_IDFA_ARMOR; + +// Dehacked: "IDFA Armor Class" +// This is what the armor class is set to when using the IDFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idfa_armor_class = DEH_DEFAULT_IDFA_ARMOR_CLASS; + +// Dehacked: "IDKFA Armor" +// This is what the armor is set to when using the IDKFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idkfa_armor = DEH_DEFAULT_IDKFA_ARMOR; + +// Dehacked: "IDKFA Armor Class" +// This is what the armor class is set to when using the IDKFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idkfa_armor_class = DEH_DEFAULT_IDKFA_ARMOR_CLASS; + +// Dehacked: "BFG Cells/Shot" +// This is the number of CELLs firing the BFG uses up. +// See P_CheckAmmo and A_FireBFG in p_pspr.c + +int deh_bfg_cells_per_shot = DEH_DEFAULT_BFG_CELLS_PER_SHOT; + +// Dehacked: "Monsters infight" +// This controls whether monsters can harm other monsters of the same +// species. For example, whether an imp fireball will damage other +// imps. The value of this in dehacked patches is weird - '202' means +// off, while '221' means on. +// +// See PIT_CheckThing in p_map.c + +int deh_species_infighting = DEH_DEFAULT_SPECIES_INFIGHTING; + +static struct +{ + const char *deh_name; + int *value; +} misc_settings[] = { + {"Initial Health", &deh_initial_health}, + {"Initial Bullets", &deh_initial_bullets}, + {"Max Health", &deh_max_health}, + {"Max Armor", &deh_max_armor}, + {"Green Armor Class", &deh_green_armor_class}, + {"Blue Armor Class", &deh_blue_armor_class}, + {"Max Soulsphere", &deh_max_soulsphere}, + {"Soulsphere Health", &deh_soulsphere_health}, + {"Megasphere Health", &deh_megasphere_health}, + {"God Mode Health", &deh_god_mode_health}, + {"IDFA Armor", &deh_idfa_armor}, + {"IDFA Armor Class", &deh_idfa_armor_class}, + {"IDKFA Armor", &deh_idkfa_armor}, + {"IDKFA Armor Class", &deh_idkfa_armor_class}, + {"BFG Cells/Shot", &deh_bfg_cells_per_shot}, +}; + +static void *DEH_MiscStart(deh_context_t *context, char *line) +{ + return NULL; +} + +static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + int ivalue; + size_t i; + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + if (!strcasecmp(variable_name, "Monsters Infight")) + { + // See notes above. + + if (ivalue == 202) + { + deh_species_infighting = 0; + } + else if (ivalue == 221) + { + deh_species_infighting = 1; + } + else + { + DEH_Warning(context, + "Invalid value for 'Monsters Infight': %i", ivalue); + } + + return; + } + + for (i=0; i +#include +#include + +#include "doomtype.h" +#include "info.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" + +static actionf_t codeptrs[NUMSTATES]; + +static int CodePointerIndex(actionf_t *ptr) +{ + int i; + + for (i=0; i= NUMSTATES) + { + DEH_Warning(context, "Invalid frame number: %i", frame_number); + return NULL; + } + + return &states[frame_number]; +} + +static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag) +{ + state_t *state; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + state = (state_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + DEH_Warning(context, "Failed to parse assignment"); + return; + } + +// printf("Set %s to %s for state\n", variable_name, value); + + // all values are integers + + ivalue = atoi(value); + + // set the appropriate field + + if (!strcasecmp(variable_name, "Codep frame")) + { + if (ivalue < 0 || ivalue >= NUMSTATES) + { + DEH_Warning(context, "Invalid state '%i'", ivalue); + } + else + { + state->action = codeptrs[ivalue]; + } + } + else + { + DEH_Warning(context, "Unknown variable name '%s'", variable_name); + } +} + +static void DEH_PointerSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" +#include "sounds.h" + +DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t) + DEH_UNSUPPORTED_MAPPING("Offset") + DEH_UNSUPPORTED_MAPPING("Zero/One") + DEH_MAPPING("Value", priority) + DEH_MAPPING("Zero 1", link) + DEH_MAPPING("Zero 2", pitch) + DEH_MAPPING("Zero 3", volume) + DEH_UNSUPPORTED_MAPPING("Zero 4") + DEH_MAPPING("Neg. One 1", usefulness) + DEH_MAPPING("Neg. One 2", lumpnum) +DEH_END_MAPPING + +static void *DEH_SoundStart(deh_context_t *context, char *line) +{ + int sound_number = 0; + + if (sscanf(line, "Sound %i", &sound_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (sound_number < 0 || sound_number >= NUMSFX) + { + DEH_Warning(context, "Invalid sound number: %i", sound_number); + return NULL; + } + + if (sound_number >= DEH_VANILLA_NUMSFX) + { + DEH_Warning(context, "Attempt to modify SFX %i. This will cause " + "problems in Vanilla dehacked.", sound_number); + } + + return &S_sfx[sound_number]; +} + +static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag) +{ + sfxinfo_t *sfx; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + sfx = (sfxinfo_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + // all values are integers + + ivalue = atoi(value); + + // Set the field value + + DEH_SetMapping(context, &sound_mapping, sfx, variable_name, ivalue); +} + +deh_section_t deh_section_sound = +{ + "Sound", + NULL, + DEH_SoundStart, + DEH_SoundParseLine, + NULL, + NULL, +}; + diff --git a/games/NXDoom/src/doom/deh_thing.c b/games/NXDoom/src/doom/deh_thing.c new file mode 100644 index 00000000000..a6baff1d7d6 --- /dev/null +++ b/games/NXDoom/src/doom/deh_thing.c @@ -0,0 +1,131 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Thing" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" + +#include "info.h" + +DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t) + DEH_MAPPING("ID #", doomednum) + DEH_MAPPING("Initial frame", spawnstate) + DEH_MAPPING("Hit points", spawnhealth) + DEH_MAPPING("First moving frame", seestate) + DEH_MAPPING("Alert sound", seesound) + DEH_MAPPING("Reaction time", reactiontime) + DEH_MAPPING("Attack sound", attacksound) + DEH_MAPPING("Injury frame", painstate) + DEH_MAPPING("Pain chance", painchance) + DEH_MAPPING("Pain sound", painsound) + DEH_MAPPING("Close attack frame", meleestate) + DEH_MAPPING("Far attack frame", missilestate) + DEH_MAPPING("Death frame", deathstate) + DEH_MAPPING("Exploding frame", xdeathstate) + DEH_MAPPING("Death sound", deathsound) + DEH_MAPPING("Speed", speed) + DEH_MAPPING("Width", radius) + DEH_MAPPING("Height", height) + DEH_MAPPING("Mass", mass) + DEH_MAPPING("Missile damage", damage) + DEH_MAPPING("Action sound", activesound) + DEH_MAPPING("Bits", flags) + DEH_MAPPING("Respawn frame", raisestate) +DEH_END_MAPPING + +static void *DEH_ThingStart(deh_context_t *context, char *line) +{ + int thing_number = 0; + mobjinfo_t *mobj; + + if (sscanf(line, "Thing %i", &thing_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + // dehacked files are indexed from 1 + --thing_number; + + if (thing_number < 0 || thing_number >= NUMMOBJTYPES) + { + DEH_Warning(context, "Invalid thing number: %i", thing_number); + return NULL; + } + + mobj = &mobjinfo[thing_number]; + + return mobj; +} + +static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) +{ + mobjinfo_t *mobj; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + mobj = (mobjinfo_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + +// printf("Set %s to %s for mobj\n", variable_name, value); + + // all values are integers + + ivalue = atoi(value); + + // Set the field value + + DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); +} + +static void DEH_ThingSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include +#include + +#include "doomtype.h" + +#include "d_items.h" + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" + +DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t) + DEH_MAPPING("Ammo type", ammo) + DEH_MAPPING("Deselect frame", upstate) + DEH_MAPPING("Select frame", downstate) + DEH_MAPPING("Bobbing frame", readystate) + DEH_MAPPING("Shooting frame", atkstate) + DEH_MAPPING("Firing frame", flashstate) +DEH_END_MAPPING + +static void *DEH_WeaponStart(deh_context_t *context, char *line) +{ + int weapon_number = 0; + + if (sscanf(line, "Weapon %i", &weapon_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (weapon_number < 0 || weapon_number >= NUMWEAPONS) + { + DEH_Warning(context, "Invalid weapon number: %i", weapon_number); + return NULL; + } + + return &weaponinfo[weapon_number]; +} + +static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + weaponinfo_t *weapon; + int ivalue; + + if (tag == NULL) + return; + + weapon = (weaponinfo_t *) tag; + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); +} + +static void DEH_WeaponSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "i_timer.h" +#include "d_mode.h" + +// +// Global parameters/defines. +// +// DOOM version +#define DOOM_VERSION 109 + +// Version code for cph's longtics hack ("v1.91") +#define DOOM_191_VERSION 111 + + +// If rangecheck is undefined, +// most parameter validation debugging code will not be compiled +#define RANGECHECK + +// The maximum number of players, multiplayer/networking. +#define MAXPLAYERS 4 + +// The current state of the game: whether we are +// playing, gazing at the intermission screen, +// the game final animation, or a demo. +typedef enum +{ + GS_LEVEL, + GS_INTERMISSION, + GS_FINALE, + GS_DEMOSCREEN, +} gamestate_t; + +typedef enum +{ + ga_nothing, + ga_loadlevel, + ga_newgame, + ga_loadgame, + ga_savegame, + ga_playdemo, + ga_completed, + ga_victory, + ga_worlddone, + ga_screenshot +} gameaction_t; + +// +// Difficulty/skill settings/filters. +// + +// Skill flags. +#define MTF_EASY 1 +#define MTF_NORMAL 2 +#define MTF_HARD 4 + +// Deaf monsters/do not react to sound. +#define MTF_AMBUSH 8 + + +// +// Key cards. +// +typedef enum +{ + it_bluecard, + it_yellowcard, + it_redcard, + it_blueskull, + it_yellowskull, + it_redskull, + + NUMCARDS + +} card_t; + + + +// The defined weapons, +// including a marker indicating +// user has not changed weapon. +typedef enum +{ + wp_fist, + wp_pistol, + wp_shotgun, + wp_chaingun, + wp_missile, + wp_plasma, + wp_bfg, + wp_chainsaw, + wp_supershotgun, + + NUMWEAPONS, + + // No pending weapon change. + wp_nochange + +} weapontype_t; + + +// Ammunition types defined. +typedef enum +{ + am_clip, // Pistol / chaingun ammo. + am_shell, // Shotgun / double barreled shotgun. + am_cell, // Plasma rifle, BFG. + am_misl, // Missile launcher. + NUMAMMO, + am_noammo // Unlimited for chainsaw / fist. + +} ammotype_t; + + +// Power up artifacts. +typedef enum +{ + pw_invulnerability, + pw_strength, + pw_invisibility, + pw_ironfeet, + pw_allmap, + pw_infrared, + NUMPOWERS + +} powertype_t; + + + +// +// Power up durations, +// how many seconds till expiration, +// assuming TICRATE is 35 ticks/second. +// +typedef enum +{ + INVULNTICS = (30*TICRATE), + INVISTICS = (60*TICRATE), + INFRATICS = (120*TICRATE), + IRONTICS = (60*TICRATE) + +} powerduration_t; + +#endif // __DOOMDEF__ diff --git a/games/NXDoom/src/doom/doomstat.c b/games/NXDoom/src/doom/doomstat.c new file mode 100644 index 00000000000..f8e83f3cb93 --- /dev/null +++ b/games/NXDoom/src/doom/doomstat.c @@ -0,0 +1,35 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Put all global tate variables here. +// + +#include + +#include "doomstat.h" + + +// Game Mode - identify IWAD as shareware, retail etc. +GameMode_t gamemode = indetermined; +GameMission_t gamemission = doom; +GameVersion_t gameversion = exe_final2; +GameVariant_t gamevariant = vanilla; + +// Set if homebrew PWAD stuff has been added. +boolean modifiedgame; + + + + diff --git a/games/NXDoom/src/doom/doomstat.h b/games/NXDoom/src/doom/doomstat.h new file mode 100644 index 00000000000..689f595035e --- /dev/null +++ b/games/NXDoom/src/doom/doomstat.h @@ -0,0 +1,277 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// All the global variables that store the internal state. +// Theoretically speaking, the internal state of the engine +// should be found by looking at the variables collected +// here, and every relevant module will have to include +// this header file. +// In practice, things are a bit messy. +// + + +#ifndef __D_STATE__ +#define __D_STATE__ + +// We need globally shared data structures, +// for defining the global state variables. +#include "doomdata.h" +#include "d_loop.h" + +// We need the playr data structure as well. +#include "d_player.h" + +// Game mode/mission +#include "d_mode.h" + +#include "net_defs.h" + + + +// ------------------------ +// Command line parameters. +// +extern boolean nomonsters; // checkparm of -nomonsters +extern boolean respawnparm; // checkparm of -respawn +extern boolean fastparm; // checkparm of -fast + +extern boolean devparm; // DEBUG: launched with -devparm + + +// ----------------------------------------------------- +// Game Mode - identify IWAD as shareware, retail etc. +// +extern GameMode_t gamemode; +extern GameMission_t gamemission; +extern GameVersion_t gameversion; +extern GameVariant_t gamevariant; + +// Convenience macro. +// 'gamemission' can be equal to pack_chex or pack_hacx, but these are +// just modified versions of doom and doom2, and should be interpreted +// as the same most of the time. + +#define logical_gamemission \ + (gamemission == pack_chex ? doom : \ + gamemission == pack_hacx ? doom2 : gamemission) + +// Set if homebrew PWAD stuff has been added. +extern boolean modifiedgame; + + +// ------------------------------------------- +// Selected skill type, map etc. +// + +// Defaults for menu, methinks. +extern skill_t startskill; +extern int startepisode; +extern int startmap; + +// Savegame slot to load on startup. This is the value provided to +// the -loadgame option. If this has not been provided, this is -1. + +extern int startloadgame; + +extern boolean autostart; + +// Selected by user. +extern skill_t gameskill; +extern int gameepisode; +extern int gamemap; + +// If non-zero, exit the level after this number of minutes +extern int timelimit; + +// Nightmare mode flag, single player. +extern boolean respawnmonsters; + +// Netgame? Only true if >1 player. +extern boolean netgame; + +// 0=Cooperative; 1=Deathmatch; 2=Altdeath +extern int deathmatch; + +// ------------------------- +// Internal parameters for sound rendering. +// These have been taken from the DOS version, +// but are not (yet) supported with Linux +// (e.g. no sound volume adjustment with menu. + +// From m_menu.c: +// Sound FX volume has default, 0 - 15 +// Music volume has default, 0 - 15 +// These are multiplied by 8. +extern int sfxVolume; +extern int musicVolume; + +// Current music/sfx card - index useless +// w/o a reference LUT in a sound module. +// Ideally, this would use indices found +// in: /usr/include/linux/soundcard.h +extern int snd_MusicDevice; +extern int snd_SfxDevice; +// Config file? Same disclaimer as above. +extern int snd_DesiredMusicDevice; +extern int snd_DesiredSfxDevice; + + +// ------------------------- +// Status flags for refresh. +// + +// Depending on view size - no status bar? +// Note that there is no way to disable the +// status bar explicitely. +extern boolean statusbaractive; + +extern boolean automapactive; // In AutoMap mode? +extern boolean menuactive; // Menu overlayed? +extern boolean paused; // Game Pause? + + +extern boolean viewactive; + +extern boolean nodrawers; + + +extern boolean testcontrols; +extern int testcontrols_mousespeed; + + + + +// This one is related to the 3-screen display mode. +// ANG90 = left side, ANG270 = right +extern int viewangleoffset; + +// Player taking events, and displaying. +extern int consoleplayer; +extern int displayplayer; + + +// ------------------------------------- +// Scores, rating. +// Statistics on a given map, for intermission. +// +extern int totalkills; +extern int totalitems; +extern int totalsecret; + +// Timer, for scores. +extern int levelstarttic; // gametic at level start +extern int leveltime; // tics in game play for par + + + +// -------------------------------------- +// DEMO playback/recording related stuff. +// No demo, there is a human player in charge? +// Disable save/end game? +extern boolean usergame; + +//? +extern boolean demoplayback; +extern boolean demorecording; + +// Round angleturn in ticcmds to the nearest 256. This is used when +// recording Vanilla demos in netgames. + +extern boolean lowres_turn; + +// Quit after playing a demo from cmdline. +extern boolean singledemo; + + + + +//? +extern gamestate_t gamestate; + + + + + + +//----------------------------- +// Internal parameters, fixed. +// These are set by the engine, and not changed +// according to user inputs. Partly load from +// WAD, partly set at startup time. + + + +// Bookkeeping on players - state. +extern player_t players[MAXPLAYERS]; + +// Alive? Disconnected? +extern boolean playeringame[MAXPLAYERS]; + + +// Player spawn spots for deathmatch. +#define MAX_DM_STARTS 10 +extern mapthing_t deathmatchstarts[MAX_DM_STARTS]; +extern mapthing_t* deathmatch_p; + +// Player spawn spots. +extern mapthing_t playerstarts[MAXPLAYERS]; +extern boolean playerstartsingame[MAXPLAYERS]; +// Intermission stats. +// Parameters for world map / intermission. +extern wbstartstruct_t wminfo; + + + + + + + +//----------------------------------------- +// Internal parameters, used for engine. +// + +// File handling stuff. +extern char *savegamedir; + +// if true, load all graphics at level load +extern boolean precache; + + +// wipegamestate can be set to -1 +// to force a wipe on the next draw +extern gamestate_t wipegamestate; + +extern int mouseSensitivity; + +extern int bodyqueslot; + + + +// Needed to store the number of the dummy sky flat. +// Used for rendering, +// as well as tracking projectiles etc. +extern int skyflatnum; + + + +// Netgame stuff (buffers and pointers, i.e. indices). + + +extern int rndindex; + +extern ticcmd_t *netcmds; + + +#endif diff --git a/games/NXDoom/src/doom/dstrings.c b/games/NXDoom/src/doom/dstrings.c new file mode 100644 index 00000000000..86433ab280f --- /dev/null +++ b/games/NXDoom/src/doom/dstrings.c @@ -0,0 +1,73 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Globally defined strings. +// + + + +#include "dstrings.h" + +const char *doom1_endmsg[] = +{ + "are you sure you want to\nquit this great game?", + "please don't leave, there's more\ndemons to toast!", + "let's beat it -- this is turning\ninto a bloodbath!", + "i wouldn't leave if i were you.\ndos is much worse.", + "you're trying to say you like dos\nbetter than me, right?", + "don't leave yet -- there's a\ndemon around that corner!", + "ya know, next time you come in here\ni'm gonna toast ya.", + "go ahead and leave. see if i care.", +}; + +const char *doom2_endmsg[] = +{ + // QuitDOOM II messages + "are you sure you want to\nquit this great game?", + "you want to quit?\nthen, thou hast lost an eighth!", + "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!", + "get outta here and go back\nto your boring programs.", + "if i were your boss, i'd \n deathmatch ya in a minute!", + "look, bud. you leave now\nand you forfeit your body count!", + "just leave. when you come\nback, i'll be waiting with a bat.", + "you're lucky i don't smack\nyou for thinking about leaving.", +}; + +#if 0 + +// UNUSED messages included in the source release + +char* endmsg[] = +{ + // DOOM1 + QUITMSG, + // FinalDOOM? + "fuck you, pussy!\nget the fuck out!", + "you quit and i'll jizz\nin your cystholes!", + "if you leave, i'll make\nthe lord drink my jizz.", + "hey, ron! can we say\n'fuck' in the game?", + "i'd leave: this is just\nmore monsters and levels.\nwhat a load.", + "suck it down, asshole!\nyou're a fucking wimp!", + "don't quit now! we're \nstill spending your money!", + + // Internal debug. Different style, too. + "THIS IS NO MESSAGE!\nPage intentionally left blank." +}; + +#endif + + + + diff --git a/games/NXDoom/src/doom/dstrings.h b/games/NXDoom/src/doom/dstrings.h new file mode 100644 index 00000000000..81115792a29 --- /dev/null +++ b/games/NXDoom/src/doom/dstrings.h @@ -0,0 +1,41 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: +// DOOM strings, by language. +// + + +#ifndef __DSTRINGS__ +#define __DSTRINGS__ + + +// All important printed strings. + +#include "d_englsh.h" + +// Misc. other strings. +#define SAVEGAMENAME "doomsav" + + +// QuitDOOM messages +// 8 per each game type +#define NUM_QUITMESSAGES 8 + +extern const char *doom1_endmsg[]; +extern const char *doom2_endmsg[]; + + +#endif diff --git a/games/NXDoom/src/doom/f_finale.c b/games/NXDoom/src/doom/f_finale.c new file mode 100644 index 00000000000..0acd6e398cc --- /dev/null +++ b/games/NXDoom/src/doom/f_finale.c @@ -0,0 +1,718 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Game completion, final screen animation. +// + + +#include +#include +#include + +// Functions. +#include "deh_main.h" +#include "i_system.h" +#include "i_swap.h" +#include "z_zone.h" +#include "v_video.h" +#include "w_wad.h" +#include "s_sound.h" + +// Data. +#include "d_main.h" +#include "dstrings.h" +#include "sounds.h" + +#include "doomstat.h" +#include "r_state.h" + +typedef enum +{ + F_STAGE_TEXT, + F_STAGE_ARTSCREEN, + F_STAGE_CAST, +} finalestage_t; + +// ? +//#include "doomstat.h" +//#include "r_local.h" +//#include "f_finale.h" + +// Stage of animation: +finalestage_t finalestage; + +unsigned int finalecount; + +#define TEXTSPEED 3 +#define TEXTWAIT 250 + +typedef struct +{ + GameMission_t mission; + int episode, level; + const char *background; + const char *text; +} textscreen_t; + +static textscreen_t textscreens[] = +{ + { doom, 1, 8, "FLOOR4_8", E1TEXT}, + { doom, 2, 8, "SFLR6_1", E2TEXT}, + { doom, 3, 8, "MFLR8_4", E3TEXT}, + { doom, 4, 8, "MFLR8_3", E4TEXT}, + + { doom2, 1, 6, "SLIME16", C1TEXT}, + { doom2, 1, 11, "RROCK14", C2TEXT}, + { doom2, 1, 20, "RROCK07", C3TEXT}, + { doom2, 1, 30, "RROCK17", C4TEXT}, + { doom2, 1, 15, "RROCK13", C5TEXT}, + { doom2, 1, 31, "RROCK19", C6TEXT}, + + { pack_tnt, 1, 6, "SLIME16", T1TEXT}, + { pack_tnt, 1, 11, "RROCK14", T2TEXT}, + { pack_tnt, 1, 20, "RROCK07", T3TEXT}, + { pack_tnt, 1, 30, "RROCK17", T4TEXT}, + { pack_tnt, 1, 15, "RROCK13", T5TEXT}, + { pack_tnt, 1, 31, "RROCK19", T6TEXT}, + + { pack_plut, 1, 6, "SLIME16", P1TEXT}, + { pack_plut, 1, 11, "RROCK14", P2TEXT}, + { pack_plut, 1, 20, "RROCK07", P3TEXT}, + { pack_plut, 1, 30, "RROCK17", P4TEXT}, + { pack_plut, 1, 15, "RROCK13", P5TEXT}, + { pack_plut, 1, 31, "RROCK19", P6TEXT}, +}; + +const char *finaletext; +const char *finaleflat; + +void F_StartCast (void); +void F_CastTicker (void); +boolean F_CastResponder (event_t *ev); +void F_CastDrawer (void); + +// +// F_StartFinale +// +void F_StartFinale (void) +{ + size_t i; + + gameaction = ga_nothing; + gamestate = GS_FINALE; + viewactive = false; + automapactive = false; + + if (logical_gamemission == doom) + { + S_ChangeMusic(mus_victor, true); + } + else + { + S_ChangeMusic(mus_read_m, true); + } + + // Find the right screen and set the text and background + + for (i=0; imission == doom) + { + screen->level = 5; + } + + if (logical_gamemission == screen->mission + && (logical_gamemission != doom || gameepisode == screen->episode) + && gamemap == screen->level) + { + finaletext = screen->text; + finaleflat = screen->background; + } + } + + // Do dehacked substitutions of strings + + finaletext = DEH_String(finaletext); + finaleflat = DEH_String(finaleflat); + + finalestage = F_STAGE_TEXT; + finalecount = 0; + +} + + + +boolean F_Responder (event_t *event) +{ + if (finalestage == F_STAGE_CAST) + return F_CastResponder (event); + + return false; +} + + +// +// F_Ticker +// +void F_Ticker (void) +{ + size_t i; + + // check for skipping + if ( (gamemode == commercial) + && ( finalecount > 50) ) + { + // go on to the next level + for (i=0 ; istrlen (finaletext)*TEXTSPEED + TEXTWAIT) + { + finalecount = 0; + finalestage = F_STAGE_ARTSCREEN; + wipegamestate = -1; // force a wipe + if (gameepisode == 3) + S_StartMusic (mus_bunny); + } +} + + + +// +// F_TextWrite +// + +#include "hu_stuff.h" + + +void F_TextWrite (void) +{ + byte* src; + pixel_t* dest; + + int x,y,w; + signed int count; + const char *ch; + int c; + int cx; + int cy; + + // erase the entire screen to a tiled background + src = W_CacheLumpName ( finaleflat , PU_CACHE); + dest = I_VideoBuffer; + + for (y=0 ; y= HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + if (cx+w > SCREENWIDTH) + break; + V_DrawPatch(cx, cy, hu_font[c]); + cx+=w; + } + +} + +// +// Final DOOM 2 animation +// Casting by id Software. +// in order of appearance +// +typedef struct +{ + const char *name; + mobjtype_t type; +} castinfo_t; + +castinfo_t castorder[] = { + {CC_ZOMBIE, MT_POSSESSED}, + {CC_SHOTGUN, MT_SHOTGUY}, + {CC_HEAVY, MT_CHAINGUY}, + {CC_IMP, MT_TROOP}, + {CC_DEMON, MT_SERGEANT}, + {CC_LOST, MT_SKULL}, + {CC_CACO, MT_HEAD}, + {CC_HELL, MT_KNIGHT}, + {CC_BARON, MT_BRUISER}, + {CC_ARACH, MT_BABY}, + {CC_PAIN, MT_PAIN}, + {CC_REVEN, MT_UNDEAD}, + {CC_MANCU, MT_FATSO}, + {CC_ARCH, MT_VILE}, + {CC_SPIDER, MT_SPIDER}, + {CC_CYBER, MT_CYBORG}, + {CC_HERO, MT_PLAYER}, + + {NULL,0} +}; + +int castnum; +int casttics; +state_t* caststate; +boolean castdeath; +int castframes; +int castonmelee; +boolean castattacking; + + +// +// F_StartCast +// +void F_StartCast (void) +{ + wipegamestate = -1; // force a screen wipe + castnum = 0; + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + casttics = caststate->tics; + castdeath = false; + finalestage = F_STAGE_CAST; + castframes = 0; + castonmelee = 0; + castattacking = false; + S_ChangeMusic(mus_evil, true); +} + + +// +// F_CastTicker +// +void F_CastTicker (void) +{ + int st; + int sfx; + + if (--casttics > 0) + return; // not time to change state yet + + if (caststate->tics == -1 || caststate->nextstate == S_NULL) + { + // switch from deathstate to next monster + castnum++; + castdeath = false; + if (castorder[castnum].name == NULL) + castnum = 0; + if (mobjinfo[castorder[castnum].type].seesound) + S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound); + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + castframes = 0; + } + else + { + // just advance to next state in animation + if (caststate == &states[S_PLAY_ATK1]) + goto stopattack; // Oh, gross hack! + st = caststate->nextstate; + caststate = &states[st]; + castframes++; + + // sound hacks.... + switch (st) + { + case S_PLAY_ATK1: sfx = sfx_dshtgn; break; + case S_POSS_ATK2: sfx = sfx_pistol; break; + case S_SPOS_ATK2: sfx = sfx_shotgn; break; + case S_VILE_ATK2: sfx = sfx_vilatk; break; + case S_SKEL_FIST2: sfx = sfx_skeswg; break; + case S_SKEL_FIST4: sfx = sfx_skepch; break; + case S_SKEL_MISS2: sfx = sfx_skeatk; break; + case S_FATT_ATK8: + case S_FATT_ATK5: + case S_FATT_ATK2: sfx = sfx_firsht; break; + case S_CPOS_ATK2: + case S_CPOS_ATK3: + case S_CPOS_ATK4: sfx = sfx_shotgn; break; + case S_TROO_ATK3: sfx = sfx_claw; break; + case S_SARG_ATK2: sfx = sfx_sgtatk; break; + case S_BOSS_ATK2: + case S_BOS2_ATK2: + case S_HEAD_ATK2: sfx = sfx_firsht; break; + case S_SKULL_ATK2: sfx = sfx_sklatk; break; + case S_SPID_ATK2: + case S_SPID_ATK3: sfx = sfx_shotgn; break; + case S_BSPI_ATK2: sfx = sfx_plasma; break; + case S_CYBER_ATK2: + case S_CYBER_ATK4: + case S_CYBER_ATK6: sfx = sfx_rlaunc; break; + case S_PAIN_ATK3: sfx = sfx_sklatk; break; + default: sfx = 0; break; + } + + if (sfx) + S_StartSound (NULL, sfx); + } + + if (castframes == 12) + { + // go into attack frame + castattacking = true; + if (castonmelee) + caststate=&states[mobjinfo[castorder[castnum].type].meleestate]; + else + caststate=&states[mobjinfo[castorder[castnum].type].missilestate]; + castonmelee ^= 1; + if (caststate == &states[S_NULL]) + { + if (castonmelee) + caststate= + &states[mobjinfo[castorder[castnum].type].meleestate]; + else + caststate= + &states[mobjinfo[castorder[castnum].type].missilestate]; + } + } + + if (castattacking) + { + if (castframes == 24 + || caststate == &states[mobjinfo[castorder[castnum].type].seestate] ) + { + stopattack: + castattacking = false; + castframes = 0; + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + } + } + + casttics = caststate->tics; + if (casttics == -1) + casttics = 15; +} + + +// +// F_CastResponder +// + +boolean F_CastResponder (event_t* ev) +{ + if (ev->type != ev_keydown) + return false; + + if (castdeath) + return true; // already in dying frames + + // go into death frame + castdeath = true; + caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; + casttics = caststate->tics; + castframes = 0; + castattacking = false; + if (mobjinfo[castorder[castnum].type].deathsound) + S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound); + + return true; +} + + +void F_CastPrint (const char *text) +{ + const char *ch; + int c; + int cx; + int w; + int width; + + // find width + ch = text; + width = 0; + + while (ch) + { + c = *ch++; + if (!c) + break; + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE) + { + width += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + width += w; + } + + // draw it + cx = SCREENWIDTH/2-width/2; + ch = text; + while (ch) + { + c = *ch++; + if (!c) + break; + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + V_DrawPatch(cx, 180, hu_font[c]); + cx+=w; + } + +} + + +// +// F_CastDrawer +// + +void F_CastDrawer (void) +{ + spritedef_t* sprdef; + spriteframe_t* sprframe; + int lump; + boolean flip; + patch_t* patch; + + // erase the entire screen to a background + V_DrawPatch (0, 0, W_CacheLumpName (DEH_String("BOSSBACK"), PU_CACHE)); + + F_CastPrint (DEH_String(castorder[castnum].name)); + + // draw the current frame in the middle of the screen + sprdef = &sprites[caststate->sprite]; + sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK]; + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + + patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE); + if (flip) + V_DrawPatchFlipped(SCREENWIDTH/2, 170, patch); + else + V_DrawPatch(SCREENWIDTH/2, 170, patch); +} + + +// +// F_DrawPatchCol +// +void +F_DrawPatchCol +( int x, + patch_t* patch, + int col ) +{ + column_t* column; + byte* source; + pixel_t* dest; + pixel_t* desttop; + int count; + + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); + desttop = I_VideoBuffer + x; + + // step through the posts in a column + while (column->topdelta != 0xff ) + { + source = (byte *)column + 3; + dest = desttop + column->topdelta*SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = *source++; + dest += SCREENWIDTH; + } + column = (column_t *)( (byte *)column + column->length + 4 ); + } +} + + +// +// F_BunnyScroll +// +void F_BunnyScroll (void) +{ + signed int scrolled; + int x; + patch_t* p1; + patch_t* p2; + char name[10]; + int stage; + static int laststage; + + p1 = W_CacheLumpName (DEH_String("PFUB2"), PU_LEVEL); + p2 = W_CacheLumpName (DEH_String("PFUB1"), PU_LEVEL); + + V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); + + scrolled = (SCREENWIDTH - ((signed int) finalecount-230)/2); + if (scrolled > SCREENWIDTH) + scrolled = SCREENWIDTH; + if (scrolled < 0) + scrolled = 0; + + for ( x=0 ; x 6) + stage = 6; + if (stage > laststage) + { + S_StartSound (NULL, sfx_pistol); + laststage = stage; + } + + DEH_snprintf(name, 10, "END%i", stage); + V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, + (SCREENHEIGHT - 8 * 8) / 2, + W_CacheLumpName (name,PU_CACHE)); +} + +static void F_ArtScreenDrawer(void) +{ + const char *lumpname; + + if (gameepisode == 3) + { + F_BunnyScroll(); + } + else + { + switch (gameepisode) + { + case 1: + if (gameversion >= exe_ultimate) + { + lumpname = "CREDIT"; + } + else + { + lumpname = "HELP2"; + } + break; + case 2: + lumpname = "VICTORY2"; + break; + case 4: + lumpname = "ENDPIC"; + break; + default: + return; + } + + lumpname = DEH_String(lumpname); + + V_DrawPatch (0, 0, W_CacheLumpName(lumpname, PU_CACHE)); + } +} + +// +// F_Drawer +// +void F_Drawer (void) +{ + switch (finalestage) + { + case F_STAGE_CAST: + F_CastDrawer(); + break; + case F_STAGE_TEXT: + F_TextWrite(); + break; + case F_STAGE_ARTSCREEN: + F_ArtScreenDrawer(); + break; + } +} + + diff --git a/games/NXDoom/src/doom/f_finale.h b/games/NXDoom/src/doom/f_finale.h new file mode 100644 index 00000000000..daa71c32a3e --- /dev/null +++ b/games/NXDoom/src/doom/f_finale.h @@ -0,0 +1,45 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __F_FINALE__ +#define __F_FINALE__ + + +#include "doomtype.h" +#include "d_event.h" +// +// FINALE +// + +// Called by main loop. +boolean F_Responder (event_t* ev); + +// Called by main loop. +void F_Ticker (void); + +// Called by main loop. +void F_Drawer (void); + + +void F_StartFinale (void); + + + + +#endif diff --git a/games/NXDoom/src/doom/f_wipe.c b/games/NXDoom/src/doom/f_wipe.c new file mode 100644 index 00000000000..0fa7754dd58 --- /dev/null +++ b/games/NXDoom/src/doom/f_wipe.c @@ -0,0 +1,294 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Mission begin melt/wipe screen special effect. +// + +#include + +#include "z_zone.h" +#include "i_video.h" +#include "v_video.h" +#include "m_random.h" + +#include "doomtype.h" + +#include "f_wipe.h" + +// +// SCREEN WIPE PACKAGE +// + +// when zero, stop the wipe +static boolean go = 0; + +static pixel_t* wipe_scr_start; +static pixel_t* wipe_scr_end; +static pixel_t* wipe_scr; + + +void +wipe_shittyColMajorXform +( dpixel_t* array, + int width, + int height ) +{ + int x; + int y; + dpixel_t* dest; + + dest = (dpixel_t*) Z_Malloc(width*height*sizeof(*dest), PU_STATIC, 0); + + for(y=0;y *e) + { + newval = *w - ticks; + if (newval < *e) + *w = *e; + else + *w = newval; + changed = true; + } + else if (*w < *e) + { + newval = *w + ticks; + if (newval > *e) + *w = *e; + else + *w = newval; + changed = true; + } + } + w++; + e++; + } + + return !changed; + +} + +int +wipe_exitColorXForm +( int width, + int height, + int ticks ) +{ + return 0; +} + + +static int* y; + +int +wipe_initMelt +( int width, + int height, + int ticks ) +{ + int i, r; + + // copy start screen to main screen + memcpy(wipe_scr, wipe_scr_start, width*height*sizeof(*wipe_scr)); + + // makes this wipe faster (in theory) + // to have stuff in column-major format + wipe_shittyColMajorXform((dpixel_t*)wipe_scr_start, width/2, height); + wipe_shittyColMajorXform((dpixel_t*)wipe_scr_end, width/2, height); + + // setup initial column positions + // (y<0 => not ready to scroll yet) + y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0); + y[0] = -(M_Random()%16); + for (i=1;i 0) y[i] = 0; + else if (y[i] == -16) y[i] = -15; + } + + return 0; +} + +int +wipe_doMelt +( int width, + int height, + int ticks ) +{ + int i; + int j; + int dy; + int idx; + + dpixel_t* s; + dpixel_t* d; + boolean done = true; + + width/=2; + + while (ticks--) + { + for (i=0;i= height) dy = height - y[i]; + s = &((dpixel_t *)wipe_scr_end)[i*height+y[i]]; + d = &((dpixel_t *)wipe_scr)[y[i]*width+i]; + idx = 0; + for (j=dy;j;j--) + { + d[idx] = *(s++); + idx += width; + } + y[i] += dy; + s = &((dpixel_t *)wipe_scr_start)[i*height]; + d = &((dpixel_t *)wipe_scr)[y[i]*width+i]; + idx = 0; + for (j=height-y[i];j;j--) + { + d[idx] = *(s++); + idx += width; + } + done = false; + } + } + } + + return done; + +} + +int +wipe_exitMelt +( int width, + int height, + int ticks ) +{ + Z_Free(y); + Z_Free(wipe_scr_start); + Z_Free(wipe_scr_end); + return 0; +} + +int +wipe_StartScreen +( int x, + int y, + int width, + int height ) +{ + wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_start), PU_STATIC, NULL); + I_ReadScreen(wipe_scr_start); + return 0; +} + +int +wipe_EndScreen +( int x, + int y, + int width, + int height ) +{ + wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_end), PU_STATIC, NULL); + I_ReadScreen(wipe_scr_end); + V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr. + return 0; +} + +int +wipe_ScreenWipe +( int wipeno, + int x, + int y, + int width, + int height, + int ticks ) +{ + int rc; + static int (*wipes[])(int, int, int) = + { + wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm, + wipe_initMelt, wipe_doMelt, wipe_exitMelt + }; + + // initial stuff + if (!go) + { + go = 1; + // wipe_scr = (pixel_t *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG + wipe_scr = I_VideoBuffer; + (*wipes[wipeno*3])(width, height, ticks); + } + + // do a piece of wipe-in + V_MarkRect(0, 0, width, height); + rc = (*wipes[wipeno*3+1])(width, height, ticks); + // V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG + + // final stuff + if (rc) + { + go = 0; + (*wipes[wipeno*3+2])(width, height, ticks); + } + + return !go; +} + diff --git a/games/NXDoom/src/doom/f_wipe.h b/games/NXDoom/src/doom/f_wipe.h new file mode 100644 index 00000000000..f48a9ca6515 --- /dev/null +++ b/games/NXDoom/src/doom/f_wipe.h @@ -0,0 +1,63 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Mission start screen wipe/melt, special effects. +// + + +#ifndef __F_WIPE_H__ +#define __F_WIPE_H__ + +// +// SCREEN WIPE PACKAGE +// + +enum +{ + // simple gradual pixel change for 8-bit only + wipe_ColorXForm, + + // weird screen melt + wipe_Melt, + + wipe_NUMWIPES +}; + +int +wipe_StartScreen +( int x, + int y, + int width, + int height ); + + +int +wipe_EndScreen +( int x, + int y, + int width, + int height ); + + +int +wipe_ScreenWipe +( int wipeno, + int x, + int y, + int width, + int height, + int ticks ); + +#endif diff --git a/games/NXDoom/src/doom/g_game.c b/games/NXDoom/src/doom/g_game.c new file mode 100644 index 00000000000..4258712179a --- /dev/null +++ b/games/NXDoom/src/doom/g_game.c @@ -0,0 +1,2408 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// + + + +#include +#include +#include + +#include "doomdef.h" +#include "doomkeys.h" +#include "doomstat.h" + +#include "deh_main.h" +#include "deh_misc.h" + +#include "z_zone.h" +#include "f_finale.h" +#include "m_argv.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_menu.h" +#include "m_random.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_input.h" +#include "i_swap.h" +#include "i_video.h" + +#include "p_setup.h" +#include "p_saveg.h" +#include "p_tick.h" + +#include "d_main.h" + +#include "wi_stuff.h" +#include "hu_stuff.h" +#include "st_stuff.h" +#include "am_map.h" +#include "statdump.h" + +// Needs access to LFB. +#include "v_video.h" + +#include "w_wad.h" + +#include "p_local.h" + +#include "s_sound.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +// SKY handling - still the wrong place. +#include "r_data.h" +#include "r_sky.h" + + + +#include "g_game.h" + + +#define SAVEGAMESIZE 0x2c000 + +void G_ReadDemoTiccmd (ticcmd_t* cmd); +void G_WriteDemoTiccmd (ticcmd_t* cmd); +void G_PlayerReborn (int player); + +void G_DoReborn (int playernum); + +void G_DoLoadLevel (void); +void G_DoNewGame (void); +void G_DoPlayDemo (void); +void G_DoCompleted (void); +void G_DoVictory (void); +void G_DoWorldDone (void); +void G_DoSaveGame (void); + +// Gamestate the last time G_Ticker was called. + +gamestate_t oldgamestate; + +gameaction_t gameaction; +gamestate_t gamestate; +skill_t gameskill; +boolean respawnmonsters; +int gameepisode; +int gamemap; + +// If non-zero, exit the level after this number of minutes. + +int timelimit; + +boolean paused; +boolean sendpause; // send a pause event next tic +boolean sendsave; // send a save event next tic +boolean usergame; // ok to save / end game + +boolean timingdemo; // if true, exit with report on completion +boolean nodrawers; // for comparative timing purposes +int starttime; // for comparative timing purposes + +boolean viewactive; + +int deathmatch; // only if started as net death +boolean netgame; // only true if packets are broadcast +boolean playeringame[MAXPLAYERS]; +player_t players[MAXPLAYERS]; + +boolean turbodetected[MAXPLAYERS]; + +int consoleplayer; // player taking events and displaying +int displayplayer; // view being displayed +int levelstarttic; // gametic at level start +int totalkills, totalitems, totalsecret; // for intermission + +char *demoname; +boolean demorecording; +boolean longtics; // cph's doom 1.91 longtics hack +boolean lowres_turn; // low resolution turning for longtics +boolean demoplayback; +boolean netdemo; +byte* demobuffer; +byte* demo_p; +byte* demoend; +boolean singledemo; // quit after playing a demo from cmdline + +boolean precache = true; // if true, load all graphics at start + +boolean testcontrols = false; // Invoked by setup to test controls +int testcontrols_mousespeed; + + + +wbstartstruct_t wminfo; // parms for world map / intermission + +byte consistancy[MAXPLAYERS][BACKUPTICS]; + +#define MAXPLMOVE (forwardmove[1]) + +#define TURBOTHRESHOLD 0x32 + +fixed_t forwardmove[2] = {0x19, 0x32}; +fixed_t sidemove[2] = {0x18, 0x28}; +fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn + +static int *weapon_keys[] = { + &key_weapon1, + &key_weapon2, + &key_weapon3, + &key_weapon4, + &key_weapon5, + &key_weapon6, + &key_weapon7, + &key_weapon8 +}; + +// Set to -1 or +1 to switch to the previous or next weapon. + +static int next_weapon = 0; + +// Used for prev/next weapon keys. + +static const struct +{ + weapontype_t weapon; + weapontype_t weapon_num; +} weapon_order_table[] = { + { wp_fist, wp_fist }, + { wp_chainsaw, wp_fist }, + { wp_pistol, wp_pistol }, + { wp_shotgun, wp_shotgun }, + { wp_supershotgun, wp_shotgun }, + { wp_chaingun, wp_chaingun }, + { wp_missile, wp_missile }, + { wp_plasma, wp_plasma }, + { wp_bfg, wp_bfg } +}; + +#define SLOWTURNTICS 6 + +#define NUMKEYS 256 +#define MAX_JOY_BUTTONS 20 + +static boolean gamekeydown[NUMKEYS]; +static int turnheld; // for accelerative turning + +static boolean mousearray[MAX_MOUSE_BUTTONS + 1]; +static boolean *mousebuttons = &mousearray[1]; // allow [-1] + +// mouse values are used once +int mousex; +int mousey; + +static int dclicktime; +static boolean dclickstate; +static int dclicks; +static int dclicktime2; +static boolean dclickstate2; +static int dclicks2; + +// joystick values are repeated +static int joyxmove; +static int joyymove; +static int joystrafemove; +static boolean joyarray[MAX_JOY_BUTTONS + 1]; +static boolean *joybuttons = &joyarray[1]; // allow [-1] + +static int savegameslot; +static char savedescription[32]; + +#define BODYQUESIZE 32 + +mobj_t* bodyque[BODYQUESIZE]; +int bodyqueslot; + +int vanilla_savegame_limit = 1; +int vanilla_demo_limit = 1; + +int G_CmdChecksum (ticcmd_t* cmd) +{ + size_t i; + int sum = 0; + + for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++) + sum += ((int *)cmd)[i]; + + return sum; +} + +static boolean WeaponSelectable(weapontype_t weapon) +{ + // Can't select the super shotgun in Doom 1. + + if (weapon == wp_supershotgun && logical_gamemission == doom) + { + return false; + } + + // These weapons aren't available in shareware. + + if ((weapon == wp_plasma || weapon == wp_bfg) + && gamemission == doom && gamemode == shareware) + { + return false; + } + + // Can't select a weapon if we don't own it. + + if (!players[consoleplayer].weaponowned[weapon]) + { + return false; + } + + // Can't select the fist if we have the chainsaw, unless + // we also have the berserk pack. + + if (weapon == wp_fist + && players[consoleplayer].weaponowned[wp_chainsaw] + && !players[consoleplayer].powers[pw_strength]) + { + return false; + } + + return true; +} + +static int G_NextWeapon(int direction) +{ + weapontype_t weapon; + int start_i, i; + + // Find index in the table. + + if (players[consoleplayer].pendingweapon == wp_nochange) + { + weapon = players[consoleplayer].readyweapon; + } + else + { + weapon = players[consoleplayer].pendingweapon; + } + + for (i=0; i= arrlen(weapon_order_table)) { + I_Error("Internal error: weapon %d not present in weapon_order_table", weapon); + } + + // Switch weapon. Don't loop forever. + start_i = i; + do + { + i += direction; + i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); + } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon)); + + return weapon_order_table[i].weapon_num; +} + +// +// G_BuildTiccmd +// Builds a ticcmd from all of the available inputs +// or reads it from the demo buffer. +// If recording a demo, write it out +// +void G_BuildTiccmd (ticcmd_t* cmd, int maketic) +{ + int i; + boolean strafe; + boolean bstrafe; + int speed; + int tspeed; + int forward; + int side; + + memset(cmd, 0, sizeof(ticcmd_t)); + + cmd->consistancy = + consistancy[consoleplayer][maketic%BACKUPTICS]; + + strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] + || joybuttons[joybstrafe]; + + // fraggle: support the old "joyb_speed = 31" hack which + // allowed an autorun effect + + speed = key_speed >= NUMKEYS + || joybspeed >= MAX_JOY_BUTTONS + || gamekeydown[key_speed] + || joybuttons[joybspeed] + || mousebuttons[mousebspeed]; + + forward = side = 0; + + // use two stage accelerative turning + // on the keyboard and joystick + if (joyxmove < 0 + || joyxmove > 0 + || gamekeydown[key_right] + || gamekeydown[key_left] + || mousebuttons[mousebturnright] + || mousebuttons[mousebturnleft]) + turnheld += ticdup; + else + turnheld = 0; + + if (turnheld < SLOWTURNTICS) + tspeed = 2; // slow turn + else + tspeed = speed; + + // let movement keys cancel each other out + if (strafe) + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + { + // fprintf(stderr, "strafe right\n"); + side += sidemove[speed]; + } + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + { + // fprintf(stderr, "strafe left\n"); + side -= sidemove[speed]; + } + if (use_analog && joyxmove) + { + joyxmove = joyxmove * joystick_move_sensitivity / 10; + joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; + joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; + side += FixedMul(sidemove[speed], joyxmove); + } + else if (joystick_move_sensitivity) + { + if (joyxmove > 0) + side += sidemove[speed]; + if (joyxmove < 0) + side -= sidemove[speed]; + } + } + else + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + cmd->angleturn -= angleturn[tspeed]; + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + cmd->angleturn += angleturn[tspeed]; + if (use_analog && joyxmove) + { + // Cubic response curve allows for finer control when stick + // deflection is small. + joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); + joyxmove = joyxmove * joystick_turn_sensitivity / 10; + cmd->angleturn -= FixedMul(angleturn[1], joyxmove); + } + else if (joystick_turn_sensitivity) + { + if (joyxmove > 0) + cmd->angleturn -= angleturn[tspeed]; + if (joyxmove < 0) + cmd->angleturn += angleturn[tspeed]; + } + } + + if (gamekeydown[key_up]) + { + // fprintf(stderr, "up\n"); + forward += forwardmove[speed]; + } + if (gamekeydown[key_down]) + { + // fprintf(stderr, "down\n"); + forward -= forwardmove[speed]; + } + + if (use_analog && joyymove) + { + joyymove = joyymove * joystick_move_sensitivity / 10; + joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; + joyymove = (joyymove < -FRACUNIT) ? -FRACUNIT : joyymove; + forward -= FixedMul(forwardmove[speed], joyymove); + } + else if (joystick_move_sensitivity) + { + if (joyymove < 0) + forward += forwardmove[speed]; + if (joyymove > 0) + forward -= forwardmove[speed]; + } + + if (gamekeydown[key_strafeleft] + || joybuttons[joybstrafeleft] + || mousebuttons[mousebstrafeleft]) + { + side -= sidemove[speed]; + } + + if (gamekeydown[key_straferight] + || joybuttons[joybstraferight] + || mousebuttons[mousebstraferight]) + { + side += sidemove[speed]; + } + + if (use_analog && joystrafemove) + { + joystrafemove = joystrafemove * joystick_move_sensitivity / 10; + joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; + joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; + side += FixedMul(sidemove[speed], joystrafemove); + } + else if (joystick_move_sensitivity) + { + if (joystrafemove < 0) + side -= sidemove[speed]; + if (joystrafemove > 0) + side += sidemove[speed]; + } + + // buttons + cmd->chatchar = HU_dequeueChatChar(); + + if (gamekeydown[key_fire] || mousebuttons[mousebfire] + || joybuttons[joybfire]) + cmd->buttons |= BT_ATTACK; + + if (gamekeydown[key_use] + || joybuttons[joybuse] + || mousebuttons[mousebuse]) + { + cmd->buttons |= BT_USE; + // clear double clicks if hit use button + dclicks = 0; + } + + // If the previous or next weapon button is pressed, the + // next_weapon variable is set to change weapons when + // we generate a ticcmd. Choose a new weapon. + + if (gamestate == GS_LEVEL && next_weapon != 0) + { + i = G_NextWeapon(next_weapon); + cmd->buttons |= BT_CHANGE; + cmd->buttons |= i << BT_WEAPONSHIFT; + } + else + { + // Check weapon keys. + + for (i=0; ibuttons |= BT_CHANGE; + cmd->buttons |= i< 1 ) + { + dclickstate = mousebuttons[mousebforward]; + if (dclickstate) + dclicks++; + if (dclicks == 2) + { + cmd->buttons |= BT_USE; + dclicks = 0; + } + else + dclicktime = 0; + } + else + { + dclicktime += ticdup; + if (dclicktime > 20) + { + dclicks = 0; + dclickstate = 0; + } + } + + // strafe double click + bstrafe = + mousebuttons[mousebstrafe] + || joybuttons[joybstrafe]; + if (bstrafe != dclickstate2 && dclicktime2 > 1 ) + { + dclickstate2 = bstrafe; + if (dclickstate2) + dclicks2++; + if (dclicks2 == 2) + { + cmd->buttons |= BT_USE; + dclicks2 = 0; + } + else + dclicktime2 = 0; + } + else + { + dclicktime2 += ticdup; + if (dclicktime2 > 20) + { + dclicks2 = 0; + dclickstate2 = 0; + } + } + } + + forward += mousey; + + if (strafe) + side += mousex*2; + else + cmd->angleturn -= mousex*0x8; + + if (mousex == 0) + { + // No movement in the previous frame + + testcontrols_mousespeed = 0; + } + + mousex = mousey = 0; + + if (forward > MAXPLMOVE) + forward = MAXPLMOVE; + else if (forward < -MAXPLMOVE) + forward = -MAXPLMOVE; + if (side > MAXPLMOVE) + side = MAXPLMOVE; + else if (side < -MAXPLMOVE) + side = -MAXPLMOVE; + + cmd->forwardmove += forward; + cmd->sidemove += side; + + // special buttons + if (sendpause) + { + sendpause = false; + cmd->buttons = BT_SPECIAL | BTS_PAUSE; + } + + if (sendsave) + { + sendsave = false; + cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<angleturn + carry; + + // round angleturn to the nearest 256 unit boundary + // for recording demos with single byte values for turn + + cmd->angleturn = (desired_angleturn + 128) & 0xff00; + + // Carry forward the error from the reduced resolution to the + // next tic, so that successive small movements can accumulate. + + carry = desired_angleturn - cmd->angleturn; + } +} + + +// +// G_DoLoadLevel +// +void G_DoLoadLevel (void) +{ + int i; + + // Set the sky map. + // First thing, we have a dummy sky texture name, + // a flat. The data is in the WAD only because + // we look for an actual index, instead of simply + // setting one. + + skyflatnum = R_FlatNumForName(DEH_String(SKYFLATNAME)); + + // The "Sky never changes in Doom II" bug was fixed in + // the id Anthology version of doom2.exe for Final Doom. + if ((gamemode == commercial) + && (gameversion == exe_final2 || gameversion == exe_chex)) + { + const char *skytexturename; + + if (gamemap < 12) + { + skytexturename = "SKY1"; + } + else if (gamemap < 21) + { + skytexturename = "SKY2"; + } + else + { + skytexturename = "SKY3"; + } + + skytexturename = DEH_String(skytexturename); + + skytexture = R_TextureNumForName(skytexturename); + } + + levelstarttic = gametic; // for time calculation + + if (wipegamestate == GS_LEVEL) + wipegamestate = -1; // force a wipe + + gamestate = GS_LEVEL; + + for (i=0 ; itype == ev_keydown + && ev->data1 == key_spy && (singledemo || !deathmatch) ) + { + // spy mode + do + { + displayplayer++; + if (displayplayer == MAXPLAYERS) + displayplayer = 0; + } while (!playeringame[displayplayer] && displayplayer != consoleplayer); + return true; + } + + // any other key pops up menu if in demos + if (gameaction == ga_nothing && !singledemo && + (demoplayback || gamestate == GS_DEMOSCREEN) + ) + { + if (ev->type == ev_keydown || + (ev->type == ev_mouse && ev->data1) || + (ev->type == ev_joystick && ev->data1) ) + { + M_StartControlPanel (); + joywait = I_GetTime() + 5; + return true; + } + return false; + } + + if (gamestate == GS_LEVEL) + { +#if 0 + if (devparm && ev->type == ev_keydown && ev->data1 == ';') + { + G_DeathMatchSpawnPlayer (0); + return true; + } +#endif + if (HU_Responder (ev)) + return true; // chat ate the event + if (ST_Responder (ev)) + return true; // status window ate it + if (AM_Responder (ev)) + return true; // automap ate it + } + + if (gamestate == GS_FINALE) + { + if (F_Responder (ev)) + return true; // finale ate the event + } + + if (testcontrols && ev->type == ev_mouse) + { + // If we are invoked by setup to test the controls, save the + // mouse speed so that we can display it on-screen. + // Perform a low pass filter on this so that the thermometer + // appears to move smoothly. + + testcontrols_mousespeed = abs(ev->data2); + } + + // If the next/previous weapon keys are pressed, set the next_weapon + // variable to change weapons when the next ticcmd is generated. + + if (ev->type == ev_keydown && ev->data1 == key_prevweapon) + { + next_weapon = -1; + } + else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) + { + next_weapon = 1; + } + + switch (ev->type) + { + case ev_keydown: + if (ev->data1 == key_pause) + { + sendpause = true; + } + else if (ev->data1 data1] = true; + } + + return true; // eat key down events + + case ev_keyup: + if (ev->data1 data1] = false; + return false; // always let key up events filter down + + case ev_mouse: + SetMouseButtons(ev->data1); + mousex = ev->data2*(mouseSensitivity+5)/10; + mousey = ev->data3*(mouseSensitivity+5)/10; + return true; // eat events + + case ev_joystick: + SetJoyButtons(ev->data1); + joyxmove = ev->data2; + joyymove = ev->data3; + joystrafemove = ev->data4; + return true; // eat events + + default: + break; + } + + return false; +} + + + +// +// G_Ticker +// Make ticcmd_ts for the players. +// +void G_Ticker (void) +{ + int i; + int buf; + ticcmd_t* cmd; + + // do player reborns if needed + for (i=0 ; iforwardmove > TURBOTHRESHOLD) + { + turbodetected[i] = true; + } + + if ((gametic & 31) == 0 + && ((gametic >> 5) % MAXPLAYERS) == i + && turbodetected[i]) + { + static char turbomessage[80]; + M_snprintf(turbomessage, sizeof(turbomessage), + "%s is turbo!", player_names[i]); + players[consoleplayer].message = turbomessage; + turbodetected[i] = false; + } + + if (netgame && !netdemo && !(gametic%ticdup) ) + { + if (gametic > BACKUPTICS + && consistancy[i][buf] != cmd->consistancy) + { + I_Error ("consistency failure (%i should be %i)", + cmd->consistancy, consistancy[i][buf]); + } + if (players[i].mo) + consistancy[i][buf] = players[i].mo->x; + else + consistancy[i][buf] = rndindex; + } + } + } + + // check for special buttons + for (i=0 ; i>BTS_SAVESHIFT; + gameaction = ga_savegame; + break; + } + } + } + } + + // Have we just finished displaying an intermission screen? + + if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION) + { + WI_End(); + } + + oldgamestate = gamestate; + + // do main actions + switch (gamestate) + { + case GS_LEVEL: + P_Ticker (); + ST_Ticker (); + AM_Ticker (); + HU_Ticker (); + break; + + case GS_INTERMISSION: + WI_Ticker (); + break; + + case GS_FINALE: + F_Ticker (); + break; + + case GS_DEMOSCREEN: + D_PageTicker (); + break; + } +} + + +// +// PLAYER STRUCTURE FUNCTIONS +// also see P_SpawnPlayer in P_Things +// + +// +// G_InitPlayer +// Called at the start. +// Called by the game initialization functions. +// +void G_InitPlayer (int player) +{ + // clear everything else to defaults + G_PlayerReborn (player); +} + + + +// +// G_PlayerFinishLevel +// Can when a player completes a level. +// +void G_PlayerFinishLevel (int player) +{ + player_t* p; + + p = &players[player]; + + memset (p->powers, 0, sizeof (p->powers)); + memset (p->cards, 0, sizeof (p->cards)); + p->mo->flags &= ~MF_SHADOW; // cancel invisibility + p->extralight = 0; // cancel gun flashes + p->fixedcolormap = 0; // cancel ir gogles + p->damagecount = 0; // no palette changes + p->bonuscount = 0; +} + + +// +// G_PlayerReborn +// Called after a player dies +// almost everything is cleared and initialized +// +void G_PlayerReborn (int player) +{ + player_t* p; + int i; + int frags[MAXPLAYERS]; + int killcount; + int itemcount; + int secretcount; + + memcpy (frags,players[player].frags,sizeof(frags)); + killcount = players[player].killcount; + itemcount = players[player].itemcount; + secretcount = players[player].secretcount; + + p = &players[player]; + memset (p, 0, sizeof(*p)); + + memcpy (players[player].frags, frags, sizeof(players[player].frags)); + players[player].killcount = killcount; + players[player].itemcount = itemcount; + players[player].secretcount = secretcount; + + p->usedown = p->attackdown = true; // don't do anything immediately + p->playerstate = PST_LIVE; + p->health = deh_initial_health; // Use dehacked value + p->readyweapon = p->pendingweapon = wp_pistol; + p->weaponowned[wp_fist] = true; + p->weaponowned[wp_pistol] = true; + p->ammo[am_clip] = deh_initial_bullets; + + for (i=0 ; imaxammo[i] = maxammo[i]; + +} + +// +// G_CheckSpot +// Returns false if the player cannot be respawned +// at the given mapthing_t spot +// because something is occupying it +// +void P_SpawnPlayer (mapthing_t* mthing); + +boolean +G_CheckSpot +( int playernum, + mapthing_t* mthing ) +{ + fixed_t x; + fixed_t y; + subsector_t* ss; + mobj_t* mo; + int i; + + if (!players[playernum].mo) + { + // first spawn of level, before corpses + for (i=0 ; ix == mthing->x << FRACBITS + && players[i].mo->y == mthing->y << FRACBITS) + return false; + return true; + } + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + if (!P_CheckPosition (players[playernum].mo, x, y) ) + return false; + + // flush an old corpse if needed + if (bodyqueslot >= BODYQUESIZE) + P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); + bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; + bodyqueslot++; + + // spawn a teleport fog + ss = R_PointInSubsector (x,y); + + + // The code in the released source looks like this: + // + // an = ( ANG45 * (((unsigned int) mthing->angle)/45) ) + // >> ANGLETOFINESHIFT; + // mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] + // , ss->sector->floorheight + // , MT_TFOG); + // + // But 'an' can be a signed value in the DOS version. This means that + // we get a negative index and the lookups into finecosine/finesine + // end up dereferencing values in finetangent[]. + // A player spawning on a deathmatch start facing directly west spawns + // "silently" with no spawn fog. Emulate this. + // + // This code is imported from PrBoom+. + + { + fixed_t xa, ya; + signed int an; + + // This calculation overflows in Vanilla Doom, but here we deliberately + // avoid integer overflow as it is undefined behavior, so the value of + // 'an' will always be positive. + an = (ANG45 >> ANGLETOFINESHIFT) * ((signed int) mthing->angle / 45); + + switch (an) + { + case 4096: // -4096: + xa = finetangent[2048]; // finecosine[-4096] + ya = finetangent[0]; // finesine[-4096] + break; + case 5120: // -3072: + xa = finetangent[3072]; // finecosine[-3072] + ya = finetangent[1024]; // finesine[-3072] + break; + case 6144: // -2048: + xa = finesine[0]; // finecosine[-2048] + ya = finetangent[2048]; // finesine[-2048] + break; + case 7168: // -1024: + xa = finesine[1024]; // finecosine[-1024] + ya = finetangent[3072]; // finesine[-1024] + break; + case 0: + case 1024: + case 2048: + case 3072: + xa = finecosine[an]; + ya = finesine[an]; + break; + case 8192: // 360 deg: + xa = tantoangle[0]; // finecosine[8192] + ya = finesine[8192]; // finesine[8192] + break; + default: + I_Error("G_CheckSpot: unexpected angle %d\n", an); + xa = ya = 0; + break; + } + mo = P_SpawnMobj(x + 20 * xa, y + 20 * ya, + ss->sector->floorheight, MT_TFOG); + } + + if (players[consoleplayer].viewz != 1) + S_StartSound (mo, sfx_telept); // don't start sound on first frame + + return true; +} + + +// +// G_DeathMatchSpawnPlayer +// Spawns a player at one of the random death match spots +// called at level load and each death +// +void G_DeathMatchSpawnPlayer (int playernum) +{ + int i,j; + int selections; + + selections = deathmatch_p - deathmatchstarts; + if (selections < 4) + I_Error ("Only %i deathmatch spots, 4 required", selections); + + for (j=0 ; j<20 ; j++) + { + i = P_Random() % selections; + if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) + { + deathmatchstarts[i].type = playernum+1; + P_SpawnPlayer (&deathmatchstarts[i]); + return; + } + } + + // no good spot, so the player will probably get stuck + P_SpawnPlayer (&playerstarts[playernum]); +} + +// +// G_DoReborn +// +void G_DoReborn (int playernum) +{ + int i; + + if (!netgame) + { + // reload the level from scratch + gameaction = ga_loadlevel; + } + else + { + // respawn at the start + + // first dissasociate the corpse + players[playernum].mo->player = NULL; + + // spawn at random spot if in death match + if (deathmatch) + { + G_DeathMatchSpawnPlayer (playernum); + return; + } + + if (G_CheckSpot (playernum, &playerstarts[playernum]) ) + { + P_SpawnPlayer (&playerstarts[playernum]); + return; + } + + // try to spawn at one of the other players spots + for (i=0 ; i SAVEGAMESIZE) + { + I_Error("Savegame buffer overrun"); + } + + // Finish up, close the savegame file. + + fclose(save_stream); + + if (recovery_savegame_file != NULL) + { + // We failed to save to the normal location, but we wrote a + // recovery file to the temp directory. Now we can bomb out + // with an error. + I_Error("Failed to open savegame file '%s' for writing.\n" + "But your game has been saved to '%s' for recovery.", + temp_savegame_file, recovery_savegame_file); + } + + // Now rename the temporary savegame file to the actual savegame + // file, overwriting the old savegame if there was one there. + + M_remove(savegame_file); + M_rename(temp_savegame_file, savegame_file); + + gameaction = ga_nothing; + M_StringCopy(savedescription, "", sizeof(savedescription)); + + players[consoleplayer].message = DEH_String(GGSAVED); + + // draw the pattern into the back screen + R_FillBackScreen (); +} + + +// +// G_InitNew +// Can be called by the startup code or the menu task, +// consoleplayer, displayplayer, playeringame[] should be set. +// +skill_t d_skill; +int d_episode; +int d_map; + +void +G_DeferedInitNew +( skill_t skill, + int episode, + int map) +{ + d_skill = skill; + d_episode = episode; + d_map = map; + gameaction = ga_newgame; +} + + +void G_DoNewGame (void) +{ + demoplayback = false; + netdemo = false; + netgame = false; + deathmatch = false; + playeringame[1] = playeringame[2] = playeringame[3] = 0; + respawnparm = false; + fastparm = false; + nomonsters = false; + consoleplayer = 0; + G_InitNew (d_skill, d_episode, d_map); + gameaction = ga_nothing; +} + + +void +G_InitNew +( skill_t skill, + int episode, + int map ) +{ + const char *skytexturename; + int i; + + if (paused) + { + paused = false; + S_ResumeSound (); + } + + /* + // Note: This commented-out block of code was added at some point + // between the DOS version(s) and the Doom source release. It isn't + // found in disassemblies of the DOS version and causes IDCLEV and + // the -warp command line parameter to behave differently. + // This is left here for posterity. + + // This was quite messy with SPECIAL and commented parts. + // Supposedly hacks to make the latest edition work. + // It might not work properly. + if (episode < 1) + episode = 1; + + if ( gamemode == retail ) + { + if (episode > 4) + episode = 4; + } + else if ( gamemode == shareware ) + { + if (episode > 1) + episode = 1; // only start episode 1 on shareware + } + else + { + if (episode > 3) + episode = 3; + } + */ + + if (skill > sk_nightmare) + skill = sk_nightmare; + + if (gameversion >= exe_ultimate) + { + if (episode == 0) + { + episode = 4; + } + } + else + { + if (episode < 1) + { + episode = 1; + } + if (episode > 3) + { + episode = 3; + } + } + + if (episode > 1 && gamemode == shareware) + { + episode = 1; + } + + if (map < 1) + map = 1; + + if ( (map > 9) + && ( gamemode != commercial) ) + map = 9; + + M_ClearRandom (); + + if (skill == sk_nightmare || respawnparm ) + respawnmonsters = true; + else + respawnmonsters = false; + + if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) ) + { + for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) + states[i].tics >>= 1; + mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT; + mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; + mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; + } + else if (skill != sk_nightmare && gameskill == sk_nightmare) + { + for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) + states[i].tics <<= 1; + mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT; + mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT; + mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; + } + + // force players to be initialized upon first level load + for (i=0 ; iforwardmove = ((signed char)*demo_p++); + cmd->sidemove = ((signed char)*demo_p++); + + // If this is a longtics demo, read back in higher resolution + + if (longtics) + { + cmd->angleturn = *demo_p++; + cmd->angleturn |= (*demo_p++) << 8; + } + else + { + cmd->angleturn = ((unsigned char) *demo_p++)<<8; + } + + cmd->buttons = (unsigned char)*demo_p++; +} + +// Increase the size of the demo buffer to allow unlimited demos + +static void IncreaseDemoBuffer(void) +{ + int current_length; + byte *new_demobuffer; + byte *new_demop; + int new_length; + + // Find the current size + + current_length = demoend - demobuffer; + + // Generate a new buffer twice the size + new_length = current_length * 2; + + new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); + new_demop = new_demobuffer + (demo_p - demobuffer); + + // Copy over the old data + + memcpy(new_demobuffer, demobuffer, current_length); + + // Free the old buffer and point the demo pointers at the new buffer. + + Z_Free(demobuffer); + + demobuffer = new_demobuffer; + demo_p = new_demop; + demoend = demobuffer + new_length; +} + +void G_WriteDemoTiccmd (ticcmd_t* cmd) +{ + byte *demo_start; + + if (gamekeydown[key_demo_quit]) // press q to end demo recording + G_CheckDemoStatus (); + + demo_start = demo_p; + + *demo_p++ = cmd->forwardmove; + *demo_p++ = cmd->sidemove; + + // If this is a longtics demo, record in higher resolution + + if (longtics) + { + *demo_p++ = (cmd->angleturn & 0xff); + *demo_p++ = (cmd->angleturn >> 8) & 0xff; + } + else + { + *demo_p++ = cmd->angleturn >> 8; + } + + *demo_p++ = cmd->buttons; + + // reset demo pointer back + demo_p = demo_start; + + if (demo_p > demoend - 16) + { + if (vanilla_demo_limit) + { + // no more space + G_CheckDemoStatus (); + return; + } + else + { + // Vanilla demo limit disabled: unlimited + // demo lengths! + + IncreaseDemoBuffer(); + } + } + + G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same +} + + + +// +// G_RecordDemo +// +void G_RecordDemo (const char *name) +{ + size_t demoname_size; + int i; + int maxsize; + + usergame = false; + demoname_size = strlen(name) + 5; + demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); + M_snprintf(demoname, demoname_size, "%s.lmp", name); + maxsize = 0x20000; + + //! + // @arg + // @category demo + // @vanilla + // + // Specify the demo buffer size (KiB) + // + + i = M_CheckParmWithArgs("-maxdemo", 1); + if (i) + maxsize = atoi(myargv[i+1])*1024; + demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL); + demoend = demobuffer + maxsize; + + demorecording = true; +} + +// Get the demo version code appropriate for the version set in gameversion. +int G_VanillaVersionCode(void) +{ + switch (gameversion) + { + case exe_doom_1_666: + return 106; + case exe_doom_1_7: + return 107; + case exe_doom_1_8: + return 108; + case exe_doom_1_9: + default: // All other versions are variants on v1.9: + return 109; + } +} + +void G_BeginRecording (void) +{ + int i; + + demo_p = demobuffer; + + //! + // @category demo + // + // Record a high resolution "Doom 1.91" demo. + // + + longtics = D_NonVanillaRecord(M_ParmExists("-longtics"), + "Doom 1.91 demo format"); + + // If not recording a longtics demo, record in low res + lowres_turn = !longtics; + + if (longtics) + { + *demo_p++ = DOOM_191_VERSION; + } + else if (gameversion > exe_doom_1_2) + { + *demo_p++ = G_VanillaVersionCode(); + } + + *demo_p++ = gameskill; + *demo_p++ = gameepisode; + *demo_p++ = gamemap; + if (longtics || gameversion > exe_doom_1_2) + { + *demo_p++ = deathmatch; + *demo_p++ = respawnparm; + *demo_p++ = fastparm; + *demo_p++ = nomonsters; + *demo_p++ = consoleplayer; + } + + for (i=0 ; i= 0 && version <= 4) + { + return "v1.0/v1.1/v1.2"; + } + else + { + M_snprintf(resultbuf, sizeof(resultbuf), + "%i.%i (unknown)", version / 100, version % 100); + return resultbuf; + } +} + +void G_DoPlayDemo (void) +{ + skill_t skill; + int i, lumpnum, episode, map; + int demoversion; + boolean olddemo = false; + + lumpnum = W_GetNumForName(defdemoname); + gameaction = ga_nothing; + demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC); + demo_p = demobuffer; + + demoversion = *demo_p++; + + if (demoversion >= 0 && demoversion <= 4) + { + olddemo = true; + demo_p--; + } + + longtics = false; + + // Longtics demos use the modified format that is generated by cph's + // hacked "v1.91" doom exe. This is a non-vanilla extension. + if (D_NonVanillaPlayback(demoversion == DOOM_191_VERSION, lumpnum, + "Doom 1.91 demo format")) + { + longtics = true; + } + else if (demoversion != G_VanillaVersionCode() && + !(gameversion <= exe_doom_1_2 && olddemo)) + { + const char *message = "Demo is from a different game version!\n" + "(read %i, should be %i)\n" + "\n" + "*** You may need to upgrade your version " + "of Doom to v1.9. ***\n" + " See: https://www.doomworld.com/classicdoom" + "/info/patches.php\n" + " This appears to be %s."; + + I_Error(message, demoversion, G_VanillaVersionCode(), + DemoVersionDescription(demoversion)); + } + + skill = *demo_p++; + episode = *demo_p++; + map = *demo_p++; + if (!olddemo) + { + deathmatch = *demo_p++; + respawnparm = *demo_p++; + fastparm = *demo_p++; + nomonsters = *demo_p++; + consoleplayer = *demo_p++; + } + else + { + deathmatch = 0; + respawnparm = 0; + fastparm = 0; + nomonsters = 0; + consoleplayer = 0; + } + + + for (i=0 ; i 0 + || M_CheckParm("-netdemo") > 0) + { + netgame = true; + netdemo = true; + } + + // don't spend a lot of time in loadlevel + precache = false; + G_InitNew (skill, episode, map); + precache = true; + starttime = I_GetTime (); + + usergame = false; + demoplayback = true; +} + +// +// G_TimeDemo +// +void G_TimeDemo (char* name) +{ + //! + // @category video + // @vanilla + // + // Disable rendering the screen entirely. + // + + nodrawers = M_CheckParm ("-nodraw"); + + timingdemo = true; + singletics = true; + + defdemoname = name; + gameaction = ga_playdemo; +} + + +/* +=================== += += G_CheckDemoStatus += += Called after a death or level completion to allow demos to be cleaned up += Returns true if a new demo loop action will take place +=================== +*/ + +boolean G_CheckDemoStatus (void) +{ + int endtime; + + if (timingdemo) + { + float fps; + int realtics; + + endtime = I_GetTime (); + realtics = endtime - starttime; + fps = ((float) gametic * TICRATE) / realtics; + + // Prevent recursive calls + timingdemo = false; + demoplayback = false; + + I_Error ("timed %i gametics in %i realtics (%f fps)", + gametic, realtics, fps); + } + + if (demoplayback) + { + W_ReleaseLumpName(defdemoname); + demoplayback = false; + netdemo = false; + netgame = false; + deathmatch = false; + playeringame[1] = playeringame[2] = playeringame[3] = 0; + respawnparm = false; + fastparm = false; + nomonsters = false; + consoleplayer = 0; + + if (singledemo) + I_Quit (); + else + D_AdvanceDemo (); + + return true; + } + + if (demorecording) + { + *demo_p++ = DEMOMARKER; + M_WriteFile (demoname, demobuffer, demo_p - demobuffer); + Z_Free (demobuffer); + demorecording = false; + I_Error ("Demo %s recorded",demoname); + } + + return false; +} + + + diff --git a/games/NXDoom/src/doom/g_game.h b/games/NXDoom/src/doom/g_game.h new file mode 100644 index 00000000000..1e8729d18f2 --- /dev/null +++ b/games/NXDoom/src/doom/g_game.h @@ -0,0 +1,88 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Duh. +// + + +#ifndef __G_GAME__ +#define __G_GAME__ + +#include "doomdef.h" +#include "d_event.h" +#include "d_ticcmd.h" +#include "m_fixed.h" + + +// +// GAME +// +void G_DeathMatchSpawnPlayer (int playernum); + +void G_InitNew (skill_t skill, int episode, int map); + +// Can be called by the startup code or M_Responder. +// A normal game starts at map 1, +// but a warp test can start elsewhere +void G_DeferedInitNew (skill_t skill, int episode, int map); + +void G_DeferedPlayDemo (const char* demo); + +// Can be called by the startup code or M_Responder, +// calls P_SetupLevel or W_EnterWorld. +void G_LoadGame (char* name); + +void G_DoLoadGame (void); + +// Called by M_Responder. +void G_SaveGame (int slot, char* description); + +// Only called by startup code. +void G_RecordDemo (const char* name); + +void G_BeginRecording (void); + +void G_PlayDemo (char* name); +void G_TimeDemo (char* name); +boolean G_CheckDemoStatus (void); + +void G_ExitLevel (void); +void G_SecretExitLevel (void); + +void G_WorldDone (void); + +// Read current data from inputs and build a player movement command. + +void G_BuildTiccmd (ticcmd_t *cmd, int maketic); + +void G_Ticker (void); +boolean G_Responder (event_t* ev); + +void G_ScreenShot (void); + +void G_DrawMouseSpeedBox(void); +int G_VanillaVersionCode(void); + +extern int vanilla_savegame_limit; +extern int vanilla_demo_limit; + +extern fixed_t forwardmove[2]; +extern fixed_t sidemove[2]; + +extern boolean sendpause; + + +#endif + diff --git a/games/NXDoom/src/doom/hu_lib.c b/games/NXDoom/src/doom/hu_lib.c new file mode 100644 index 00000000000..d32c2004d2e --- /dev/null +++ b/games/NXDoom/src/doom/hu_lib.c @@ -0,0 +1,347 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: heads-up text and input code +// + + +#include + +#include "doomdef.h" +#include "doomkeys.h" +#include "doomstat.h" + +#include "v_video.h" +#include "i_swap.h" + +#include "hu_lib.h" +#include "r_local.h" +#include "r_draw.h" + +// boolean : whether the screen is always erased +#define noterased viewwindowx + + +void HUlib_init(void) +{ +} + +void HUlib_clearTextLine(hu_textline_t* t) +{ + t->len = 0; + t->l[0] = 0; + t->needsupdate = true; +} + +void +HUlib_initTextLine +( hu_textline_t* t, + int x, + int y, + patch_t** f, + int sc ) +{ + t->x = x; + t->y = y; + t->f = f; + t->sc = sc; + HUlib_clearTextLine(t); +} + +boolean +HUlib_addCharToTextLine +( hu_textline_t* t, + char ch ) +{ + + if (t->len == HU_MAXLINELENGTH) + return false; + else + { + t->l[t->len++] = ch; + t->l[t->len] = 0; + t->needsupdate = 4; + return true; + } + +} + +boolean HUlib_delCharFromTextLine(hu_textline_t* t) +{ + + if (!t->len) return false; + else + { + t->l[--t->len] = 0; + t->needsupdate = 4; + return true; + } + +} + +void +HUlib_drawTextLine +( hu_textline_t* l, + boolean drawcursor ) +{ + + int i; + int w; + int x; + unsigned char c; + + // draw the new stuff + x = l->x; + for (i=0;ilen;i++) + { + c = toupper(l->l[i]); + if (c != ' ' + && c >= l->sc + && c <= '_') + { + w = SHORT(l->f[c - l->sc]->width); + if (x+w > SCREENWIDTH) + break; + V_DrawPatchDirect(x, l->y, l->f[c - l->sc]); + x += w; + } + else + { + x += 4; + if (x >= SCREENWIDTH) + break; + } + } + + // draw the cursor if requested + if (drawcursor + && x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH) + { + V_DrawPatchDirect(x, l->y, l->f['_' - l->sc]); + } +} + + +// sorta called by HU_Erase and just better darn get things straight +void HUlib_eraseTextLine(hu_textline_t* l) +{ + int lh; + int y; + int yoffset; + + // Only erases when NOT in automap and the screen is reduced, + // and the text must either need updating or refreshing + // (because of a recent change back from the automap) + + if (!automapactive && + viewwindowx && l->needsupdate) + { + lh = SHORT(l->f[0]->height) + 1; + for (y=l->y,yoffset=y*SCREENWIDTH ; yy+lh ; y++,yoffset+=SCREENWIDTH) + { + if (y < viewwindowy || y >= viewwindowy + viewheight) + R_VideoErase(yoffset, SCREENWIDTH); // erase entire line + else + { + R_VideoErase(yoffset, viewwindowx); // erase left border + R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); + // erase right border + } + } + } + + if (l->needsupdate) l->needsupdate--; + +} + +void +HUlib_initSText +( hu_stext_t* s, + int x, + int y, + int h, + patch_t** font, + int startchar, + boolean* on ) +{ + + int i; + + s->h = h; + s->on = on; + s->laston = true; + s->cl = 0; + for (i=0;il[i], + x, y - i*(SHORT(font[0]->height)+1), + font, startchar); + +} + +void HUlib_addLineToSText(hu_stext_t* s) +{ + + int i; + + // add a clear line + if (++s->cl == s->h) + s->cl = 0; + HUlib_clearTextLine(&s->l[s->cl]); + + // everything needs updating + for (i=0 ; ih ; i++) + s->l[i].needsupdate = 4; + +} + +void +HUlib_addMessageToSText +( hu_stext_t* s, + const char* prefix, + const char* msg ) +{ + HUlib_addLineToSText(s); + if (prefix) + while (*prefix) + HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++)); + + while (*msg) + HUlib_addCharToTextLine(&s->l[s->cl], *(msg++)); +} + +void HUlib_drawSText(hu_stext_t* s) +{ + int i, idx; + hu_textline_t *l; + + if (!*s->on) + return; // if not on, don't draw + + // draw everything + for (i=0 ; ih ; i++) + { + idx = s->cl - i; + if (idx < 0) + idx += s->h; // handle queue of lines + + l = &s->l[idx]; + + // need a decision made here on whether to skip the draw + HUlib_drawTextLine(l, false); // no cursor, please + } + +} + +void HUlib_eraseSText(hu_stext_t* s) +{ + + int i; + + for (i=0 ; ih ; i++) + { + if (s->laston && !*s->on) + s->l[i].needsupdate = 4; + HUlib_eraseTextLine(&s->l[i]); + } + s->laston = *s->on; + +} + +void +HUlib_initIText +( hu_itext_t* it, + int x, + int y, + patch_t** font, + int startchar, + boolean* on ) +{ + it->lm = 0; // default left margin is start of text + it->on = on; + it->laston = true; + HUlib_initTextLine(&it->l, x, y, font, startchar); +} + + +// The following deletion routines adhere to the left margin restriction +void HUlib_delCharFromIText(hu_itext_t* it) +{ + if (it->l.len != it->lm) + HUlib_delCharFromTextLine(&it->l); +} + +void HUlib_eraseLineFromIText(hu_itext_t* it) +{ + while (it->lm != it->l.len) + HUlib_delCharFromTextLine(&it->l); +} + +// Resets left margin as well +void HUlib_resetIText(hu_itext_t* it) +{ + it->lm = 0; + HUlib_clearTextLine(&it->l); +} + +void +HUlib_addPrefixToIText +( hu_itext_t* it, + char* str ) +{ + while (*str) + HUlib_addCharToTextLine(&it->l, *(str++)); + it->lm = it->l.len; +} + +// wrapper function for handling general keyed input. +// returns true if it ate the key +boolean +HUlib_keyInIText +( hu_itext_t* it, + unsigned char ch ) +{ + ch = toupper(ch); + + if (ch >= ' ' && ch <= '_') + HUlib_addCharToTextLine(&it->l, (char) ch); + else + if (ch == KEY_BACKSPACE) + HUlib_delCharFromIText(it); + else + if (ch != KEY_ENTER) + return false; // did not eat key + + return true; // ate the key + +} + +void HUlib_drawIText(hu_itext_t* it) +{ + + hu_textline_t *l = &it->l; + + if (!*it->on) + return; + HUlib_drawTextLine(l, true); // draw the line w/ cursor + +} + +void HUlib_eraseIText(hu_itext_t* it) +{ + if (it->laston && !*it->on) + it->l.needsupdate = 4; + HUlib_eraseTextLine(&it->l); + it->laston = *it->on; +} + diff --git a/games/NXDoom/src/doom/hu_lib.h b/games/NXDoom/src/doom/hu_lib.h new file mode 100644 index 00000000000..ca5eb8d8c81 --- /dev/null +++ b/games/NXDoom/src/doom/hu_lib.h @@ -0,0 +1,182 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// + +#ifndef __HULIB__ +#define __HULIB__ + +// We are referring to patches. +#include "r_defs.h" + +// font stuff +#define HU_CHARERASE KEY_BACKSPACE + +#define HU_MAXLINES 4 +#define HU_MAXLINELENGTH 80 + +// +// Typedefs of widgets +// + +// Text Line widget +// (parent of Scrolling Text and Input Text widgets) +typedef struct +{ + // left-justified position of scrolling text window + int x; + int y; + + patch_t** f; // font + int sc; // start character + char l[HU_MAXLINELENGTH+1]; // line of text + int len; // current line length + + // whether this line needs to be udpated + int needsupdate; + +} hu_textline_t; + + + +// Scrolling Text window widget +// (child of Text Line widget) +typedef struct +{ + hu_textline_t l[HU_MAXLINES]; // text lines to draw + int h; // height in lines + int cl; // current line number + + // pointer to boolean stating whether to update window + boolean* on; + boolean laston; // last value of *->on. + +} hu_stext_t; + + + +// Input Text Line widget +// (child of Text Line widget) +typedef struct +{ + hu_textline_t l; // text line to input on + + // left margin past which I am not to delete characters + int lm; + + // pointer to boolean stating whether to update window + boolean* on; + boolean laston; // last value of *->on; + +} hu_itext_t; + + +// +// Widget creation, access, and update routines +// + +// initializes heads-up widget library +void HUlib_init(void); + +// +// textline code +// + +// clear a line of text +void HUlib_clearTextLine(hu_textline_t *t); + +void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc); + +// returns success +boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); + +// returns success +boolean HUlib_delCharFromTextLine(hu_textline_t *t); + +// draws tline +void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor); + +// erases text line +void HUlib_eraseTextLine(hu_textline_t *l); + + +// +// Scrolling Text window widget routines +// + +// ? +void +HUlib_initSText +( hu_stext_t* s, + int x, + int y, + int h, + patch_t** font, + int startchar, + boolean* on ); + +// add a new line +void HUlib_addLineToSText(hu_stext_t* s); + +// ? +void +HUlib_addMessageToSText +( hu_stext_t* s, + const char* prefix, + const char* msg ); + +// draws stext +void HUlib_drawSText(hu_stext_t* s); + +// erases all stext lines +void HUlib_eraseSText(hu_stext_t* s); + +// Input Text Line widget routines +void +HUlib_initIText +( hu_itext_t* it, + int x, + int y, + patch_t** font, + int startchar, + boolean* on ); + +// enforces left margin +void HUlib_delCharFromIText(hu_itext_t* it); + +// enforces left margin +void HUlib_eraseLineFromIText(hu_itext_t* it); + +// resets line and left margin +void HUlib_resetIText(hu_itext_t* it); + +// left of left-margin +void +HUlib_addPrefixToIText +( hu_itext_t* it, + char* str ); + +// whether eaten +boolean +HUlib_keyInIText +( hu_itext_t* it, + unsigned char ch ); + +void HUlib_drawIText(hu_itext_t* it); + +// erases all itext lines +void HUlib_eraseIText(hu_itext_t* it); + +#endif diff --git a/games/NXDoom/src/doom/hu_stuff.c b/games/NXDoom/src/doom/hu_stuff.c new file mode 100644 index 00000000000..bb20029649a --- /dev/null +++ b/games/NXDoom/src/doom/hu_stuff.c @@ -0,0 +1,707 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Heads-up displays +// + + +#include +#include + +#include "doomdef.h" +#include "doomkeys.h" + +#include "z_zone.h" + +#include "deh_main.h" +#include "i_input.h" +#include "i_swap.h" +#include "i_video.h" + +#include "hu_stuff.h" +#include "hu_lib.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_menu.h" +#include "w_wad.h" + +#include "s_sound.h" + +#include "doomstat.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +// +// Locally used constants, shortcuts. +// +#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1]) +#define HU_TITLE2 (mapnames_commercial[gamemap-1]) +#define HU_TITLEP (mapnames_commercial[gamemap-1 + 32]) +#define HU_TITLET (mapnames_commercial[gamemap-1 + 64]) +#define HU_TITLE_CHEX (mapnames_chex[(gameepisode-1)*9+gamemap-1]) +#define HU_TITLEHEIGHT 1 +#define HU_TITLEX 0 +#define HU_TITLEY (167 - SHORT(hu_font[0]->height)) + +#define HU_INPUTTOGGLE 't' +#define HU_INPUTX HU_MSGX +#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1)) +#define HU_INPUTWIDTH 64 +#define HU_INPUTHEIGHT 1 + + + +char *chat_macros[10]; + +const char *player_names[] = +{ + HUSTR_PLRGREEN, + HUSTR_PLRINDIGO, + HUSTR_PLRBROWN, + HUSTR_PLRRED +}; + +char chat_char; // remove later. +static player_t* plr; +patch_t* hu_font[HU_FONTSIZE]; +static hu_textline_t w_title; +boolean chat_on; +static hu_itext_t w_chat; +static boolean always_off = false; +static char chat_dest[MAXPLAYERS]; +static hu_itext_t w_inputbuffer[MAXPLAYERS]; + +static boolean message_on; +boolean message_dontfuckwithme; +static boolean message_nottobefuckedwith; + +static hu_stext_t w_message; +static int message_counter; + + +static boolean headsupactive = false; + +// +// Builtin map names. +// The actual names can be found in DStrings.h. +// + +const char *mapnames[] = // DOOM shareware/registered/retail (Ultimate) names. +{ + + HUSTR_E1M1, + HUSTR_E1M2, + HUSTR_E1M3, + HUSTR_E1M4, + HUSTR_E1M5, + HUSTR_E1M6, + HUSTR_E1M7, + HUSTR_E1M8, + HUSTR_E1M9, + + HUSTR_E2M1, + HUSTR_E2M2, + HUSTR_E2M3, + HUSTR_E2M4, + HUSTR_E2M5, + HUSTR_E2M6, + HUSTR_E2M7, + HUSTR_E2M8, + HUSTR_E2M9, + + HUSTR_E3M1, + HUSTR_E3M2, + HUSTR_E3M3, + HUSTR_E3M4, + HUSTR_E3M5, + HUSTR_E3M6, + HUSTR_E3M7, + HUSTR_E3M8, + HUSTR_E3M9, + + HUSTR_E4M1, + HUSTR_E4M2, + HUSTR_E4M3, + HUSTR_E4M4, + HUSTR_E4M5, + HUSTR_E4M6, + HUSTR_E4M7, + HUSTR_E4M8, + HUSTR_E4M9, + + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL" +}; + +const char *mapnames_chex[] = // Chex Quest names. +{ + + HUSTR_E1M1, + HUSTR_E1M2, + HUSTR_E1M3, + HUSTR_E1M4, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + HUSTR_E1M5, + + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL", + "NEWLEVEL" +}; + +// List of names for levels in commercial IWADs +// (doom2.wad, plutonia.wad, tnt.wad). These are stored in a +// single large array; WADs like pl2.wad have a MAP33, and rely on +// the layout in the Vanilla executable, where it is possible to +// overflow the end of one array into the next. + +const char *mapnames_commercial[] = +{ + // DOOM 2 map names. + + HUSTR_1, + HUSTR_2, + HUSTR_3, + HUSTR_4, + HUSTR_5, + HUSTR_6, + HUSTR_7, + HUSTR_8, + HUSTR_9, + HUSTR_10, + HUSTR_11, + + HUSTR_12, + HUSTR_13, + HUSTR_14, + HUSTR_15, + HUSTR_16, + HUSTR_17, + HUSTR_18, + HUSTR_19, + HUSTR_20, + + HUSTR_21, + HUSTR_22, + HUSTR_23, + HUSTR_24, + HUSTR_25, + HUSTR_26, + HUSTR_27, + HUSTR_28, + HUSTR_29, + HUSTR_30, + HUSTR_31, + HUSTR_32, + + // Plutonia WAD map names. + + PHUSTR_1, + PHUSTR_2, + PHUSTR_3, + PHUSTR_4, + PHUSTR_5, + PHUSTR_6, + PHUSTR_7, + PHUSTR_8, + PHUSTR_9, + PHUSTR_10, + PHUSTR_11, + + PHUSTR_12, + PHUSTR_13, + PHUSTR_14, + PHUSTR_15, + PHUSTR_16, + PHUSTR_17, + PHUSTR_18, + PHUSTR_19, + PHUSTR_20, + + PHUSTR_21, + PHUSTR_22, + PHUSTR_23, + PHUSTR_24, + PHUSTR_25, + PHUSTR_26, + PHUSTR_27, + PHUSTR_28, + PHUSTR_29, + PHUSTR_30, + PHUSTR_31, + PHUSTR_32, + + // TNT WAD map names. + + THUSTR_1, + THUSTR_2, + THUSTR_3, + THUSTR_4, + THUSTR_5, + THUSTR_6, + THUSTR_7, + THUSTR_8, + THUSTR_9, + THUSTR_10, + THUSTR_11, + + THUSTR_12, + THUSTR_13, + THUSTR_14, + THUSTR_15, + THUSTR_16, + THUSTR_17, + THUSTR_18, + THUSTR_19, + THUSTR_20, + + THUSTR_21, + THUSTR_22, + THUSTR_23, + THUSTR_24, + THUSTR_25, + THUSTR_26, + THUSTR_27, + THUSTR_28, + THUSTR_29, + THUSTR_30, + THUSTR_31, + THUSTR_32, + + // Emulation: TNT maps 33-35 can be warped to and played if they exist + // so include blank names instead of spilling over + "", + "", + "" +}; + +void HU_Init(void) +{ + + int i; + int j; + char buffer[9]; + + // load the heads-up font + j = HU_FONTSTART; + for (i=0;i= 33) + { + s = ""; + } + break; + case pack_plut: + s = HU_TITLEP; + break; + case pack_tnt: + s = HU_TITLET; + break; + default: + s = "Unknown level"; + break; + } + + if (logical_gamemission == doom && gameversion == exe_chex) + { + s = HU_TITLE_CHEX; + } + + // dehacked substitution to get modified level name + + s = DEH_String(s); + + while (*s) + HUlib_addCharToTextLine(&w_title, *(s++)); + + // create the chat widget + HUlib_initIText(&w_chat, + HU_INPUTX, HU_INPUTY, + hu_font, + HU_FONTSTART, &chat_on); + + // create the inputbuffer widgets + for (i=0 ; imessage && !message_nottobefuckedwith) + || (plr->message && message_dontfuckwithme)) + { + HUlib_addMessageToSText(&w_message, 0, plr->message); + plr->message = 0; + message_on = true; + message_counter = HU_MSGTIMEOUT; + message_nottobefuckedwith = message_dontfuckwithme; + message_dontfuckwithme = 0; + } + + } // else message_on = false; + + // check for incoming chat characters + if (netgame) + { + for (i=0 ; i exe_doom_1_2) + S_StartSound(0, sfx_tink); + } + HUlib_resetIText(&w_inputbuffer[i]); + } + } + players[i].cmd.chatchar = 0; + } + } + } + +} + +#define QUEUESIZE 128 + +static char chatchars[QUEUESIZE]; +static int head = 0; +static int tail = 0; + + +void HU_queueChatChar(char c) +{ + if (((head + 1) & (QUEUESIZE-1)) == tail) + { + plr->message = DEH_String(HUSTR_MSGU); + } + else + { + chatchars[head] = c; + head = (head + 1) & (QUEUESIZE-1); + } +} + +char HU_dequeueChatChar(void) +{ + char c; + + if (head != tail) + { + c = chatchars[tail]; + tail = (tail + 1) & (QUEUESIZE-1); + } + else + { + c = 0; + } + + return c; +} + +static void StartChatInput(int dest) +{ + chat_on = true; + HUlib_resetIText(&w_chat); + HU_queueChatChar(HU_BROADCAST); + + I_StartTextInput(0, 8, SCREENWIDTH, 16); +} + +static void StopChatInput(void) +{ + chat_on = false; + I_StopTextInput(); +} + +boolean HU_Responder(event_t *ev) +{ + + static char lastmessage[HU_MAXLINELENGTH+1]; + const char *macromessage; + boolean eatkey = false; + static boolean altdown = false; + unsigned char c; + int i; + int numplayers; + + static int num_nobrainers = 0; + + numplayers = 0; + for (i=0 ; idata1 == KEY_RSHIFT) + { + return false; + } + else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT) + { + altdown = ev->type == ev_keydown; + return false; + } + + if (ev->type != ev_keydown) + return false; + + if (!chat_on) + { + if (ev->data1 == key_message_refresh) + { + message_on = true; + message_counter = HU_MSGTIMEOUT; + eatkey = true; + } + else if (netgame && ev->data2 == key_multi_msg) + { + eatkey = true; + StartChatInput(HU_BROADCAST); + } + else if (netgame && numplayers > 2) + { + for (i=0; idata2 == key_multi_msgplayer[i]) + { + if (playeringame[i] && i!=consoleplayer) + { + eatkey = true; + StartChatInput(i + 1); + break; + } + else if (i == consoleplayer) + { + num_nobrainers++; + if (num_nobrainers < 3) + plr->message = DEH_String(HUSTR_TALKTOSELF1); + else if (num_nobrainers < 6) + plr->message = DEH_String(HUSTR_TALKTOSELF2); + else if (num_nobrainers < 9) + plr->message = DEH_String(HUSTR_TALKTOSELF3); + else if (num_nobrainers < 32) + plr->message = DEH_String(HUSTR_TALKTOSELF4); + else + plr->message = DEH_String(HUSTR_TALKTOSELF5); + } + } + } + } + } + else + { + // send a macro + if (altdown) + { + c = ev->data1 - '0'; + if (c > 9) + return false; + // fprintf(stderr, "got here\n"); + macromessage = chat_macros[c]; + + // kill last message with a '\n' + HU_queueChatChar(KEY_ENTER); // DEBUG!!! + + // send the macro message + while (*macromessage) + HU_queueChatChar(*macromessage++); + HU_queueChatChar(KEY_ENTER); + + // leave chat mode and notify that it was sent + StopChatInput(); + M_StringCopy(lastmessage, chat_macros[c], sizeof(lastmessage)); + plr->message = lastmessage; + eatkey = true; + } + else + { + c = ev->data3; + + eatkey = HUlib_keyInIText(&w_chat, c); + if (eatkey) + { + // static unsigned char buf[20]; // DEBUG + HU_queueChatChar(c); + + // M_snprintf(buf, sizeof(buf), "KEY: %d => %d", ev->data1, c); + // plr->message = buf; + } + if (c == KEY_ENTER) + { + StopChatInput(); + if (w_chat.l.len) + { + M_StringCopy(lastmessage, w_chat.l.l, sizeof(lastmessage)); + plr->message = lastmessage; + } + } + else if (c == KEY_ESCAPE) + { + StopChatInput(); + } + } + } + + return eatkey; +} diff --git a/games/NXDoom/src/doom/hu_stuff.h b/games/NXDoom/src/doom/hu_stuff.h new file mode 100644 index 00000000000..c5757af6717 --- /dev/null +++ b/games/NXDoom/src/doom/hu_stuff.h @@ -0,0 +1,68 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Head up display +// + +#ifndef __HU_STUFF_H__ +#define __HU_STUFF_H__ + +#include "d_event.h" +#include "v_patch.h" + + +// +// Globally visible constants. +// +#define HU_FONTSTART '!' // the first font characters +#define HU_FONTEND '_' // the last font characters + +// Calculate # of glyphs in font. +#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) + +#define HU_BROADCAST 5 + +#define HU_MSGX 0 +#define HU_MSGY 0 +#define HU_MSGWIDTH 64 // in characters +#define HU_MSGHEIGHT 1 // in lines + +#define HU_MSGTIMEOUT (4*TICRATE) + +// +// HEADS UP TEXT +// + +void HU_Init(void); +void HU_Start(void); + +boolean HU_Responder(event_t* ev); + +void HU_Ticker(void); +void HU_Drawer(void); +char HU_dequeueChatChar(void); +void HU_Erase(void); + +extern const char *player_names[4]; +extern char *chat_macros[10]; + +extern patch_t *hu_font[HU_FONTSIZE]; + +extern boolean message_dontfuckwithme; + +extern boolean chat_on; + + +#endif + diff --git a/games/NXDoom/src/doom/info.c b/games/NXDoom/src/doom/info.c new file mode 100644 index 00000000000..11ea1abf7c9 --- /dev/null +++ b/games/NXDoom/src/doom/info.c @@ -0,0 +1,4662 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Thing frame/state LUT, +// generated by multigen utilitiy. +// This one is the original DOOM version, preserved. +// + +#include +#include + +// Data. +#include "sounds.h" +#include "m_fixed.h" + +#include "info.h" + +#include "p_mobj.h" + +const char *sprnames[] = { + "TROO","SHTG","PUNG","PISG","PISF","SHTF","SHT2","CHGG","CHGF","MISG", + "MISF","SAWG","PLSG","PLSF","BFGG","BFGF","BLUD","PUFF","BAL1","BAL2", + "PLSS","PLSE","MISL","BFS1","BFE1","BFE2","TFOG","IFOG","PLAY","POSS", + "SPOS","VILE","FIRE","FATB","FBXP","SKEL","MANF","FATT","CPOS","SARG", + "HEAD","BAL7","BOSS","BOS2","SKUL","SPID","BSPI","APLS","APBX","CYBR", + "PAIN","SSWV","KEEN","BBRN","BOSF","ARM1","ARM2","BAR1","BEXP","FCAN", + "BON1","BON2","BKEY","RKEY","YKEY","BSKU","RSKU","YSKU","STIM","MEDI", + "SOUL","PINV","PSTR","PINS","MEGA","SUIT","PMAP","PVIS","CLIP","AMMO", + "ROCK","BROK","CELL","CELP","SHEL","SBOX","BPAK","BFUG","MGUN","CSAW", + "LAUN","PLAS","SHOT","SGN2","COLU","SMT2","GOR1","POL2","POL5","POL4", + "POL3","POL1","POL6","GOR2","GOR3","GOR4","GOR5","SMIT","COL1","COL2", + "COL3","COL4","CAND","CBRA","COL6","TRE1","TRE2","ELEC","CEYE","FSKU", + "COL5","TBLU","TGRN","TRED","SMBT","SMGT","SMRT","HDB1","HDB2","HDB3", + "HDB4","HDB5","HDB6","POB1","POB2","BRS1","TLMP","TLP2", NULL +}; + + +// Doesn't work with g++, needs actionf_p1 +void A_Light0(); +void A_WeaponReady(); +void A_Lower(); +void A_Raise(); +void A_Punch(); +void A_ReFire(); +void A_FirePistol(); +void A_Light1(); +void A_FireShotgun(); +void A_Light2(); +void A_FireShotgun2(); +void A_CheckReload(); +void A_OpenShotgun2(); +void A_LoadShotgun2(); +void A_CloseShotgun2(); +void A_FireCGun(); +void A_GunFlash(); +void A_FireMissile(); +void A_Saw(); +void A_FirePlasma(); +void A_BFGsound(); +void A_FireBFG(); +void A_BFGSpray(); +void A_Explode(); +void A_Pain(); +void A_PlayerScream(); +void A_Fall(); +void A_XScream(); +void A_Look(); +void A_Chase(); +void A_FaceTarget(); +void A_PosAttack(); +void A_Scream(); +void A_SPosAttack(); +void A_VileChase(); +void A_VileStart(); +void A_VileTarget(); +void A_VileAttack(); +void A_StartFire(); +void A_Fire(); +void A_FireCrackle(); +void A_Tracer(); +void A_SkelWhoosh(); +void A_SkelFist(); +void A_SkelMissile(); +void A_FatRaise(); +void A_FatAttack1(); +void A_FatAttack2(); +void A_FatAttack3(); +void A_BossDeath(); +void A_CPosAttack(); +void A_CPosRefire(); +void A_TroopAttack(); +void A_SargAttack(); +void A_HeadAttack(); +void A_BruisAttack(); +void A_SkullAttack(); +void A_Metal(); +void A_SpidRefire(); +void A_BabyMetal(); +void A_BspiAttack(); +void A_Hoof(); +void A_CyberAttack(); +void A_PainAttack(); +void A_PainDie(); +void A_KeenDie(); +void A_BrainPain(); +void A_BrainScream(); +void A_BrainDie(); +void A_BrainAwake(); +void A_BrainSpit(); +void A_SpawnSound(); +void A_SpawnFly(); +void A_BrainExplode(); + + +state_t states[NUMSTATES] = { + {SPR_TROO,0,-1,{NULL},S_NULL,0,0}, // S_NULL + {SPR_SHTG,4,0,{A_Light0},S_NULL,0,0}, // S_LIGHTDONE + {SPR_PUNG,0,1,{A_WeaponReady},S_PUNCH,0,0}, // S_PUNCH + {SPR_PUNG,0,1,{A_Lower},S_PUNCHDOWN,0,0}, // S_PUNCHDOWN + {SPR_PUNG,0,1,{A_Raise},S_PUNCHUP,0,0}, // S_PUNCHUP + {SPR_PUNG,1,4,{NULL},S_PUNCH2,0,0}, // S_PUNCH1 + {SPR_PUNG,2,4,{A_Punch},S_PUNCH3,0,0}, // S_PUNCH2 + {SPR_PUNG,3,5,{NULL},S_PUNCH4,0,0}, // S_PUNCH3 + {SPR_PUNG,2,4,{NULL},S_PUNCH5,0,0}, // S_PUNCH4 + {SPR_PUNG,1,5,{A_ReFire},S_PUNCH,0,0}, // S_PUNCH5 + {SPR_PISG,0,1,{A_WeaponReady},S_PISTOL,0,0},// S_PISTOL + {SPR_PISG,0,1,{A_Lower},S_PISTOLDOWN,0,0}, // S_PISTOLDOWN + {SPR_PISG,0,1,{A_Raise},S_PISTOLUP,0,0}, // S_PISTOLUP + {SPR_PISG,0,4,{NULL},S_PISTOL2,0,0}, // S_PISTOL1 + {SPR_PISG,1,6,{A_FirePistol},S_PISTOL3,0,0},// S_PISTOL2 + {SPR_PISG,2,4,{NULL},S_PISTOL4,0,0}, // S_PISTOL3 + {SPR_PISG,1,5,{A_ReFire},S_PISTOL,0,0}, // S_PISTOL4 + {SPR_PISF,32768,7,{A_Light1},S_LIGHTDONE,0,0}, // S_PISTOLFLASH + {SPR_SHTG,0,1,{A_WeaponReady},S_SGUN,0,0}, // S_SGUN + {SPR_SHTG,0,1,{A_Lower},S_SGUNDOWN,0,0}, // S_SGUNDOWN + {SPR_SHTG,0,1,{A_Raise},S_SGUNUP,0,0}, // S_SGUNUP + {SPR_SHTG,0,3,{NULL},S_SGUN2,0,0}, // S_SGUN1 + {SPR_SHTG,0,7,{A_FireShotgun},S_SGUN3,0,0}, // S_SGUN2 + {SPR_SHTG,1,5,{NULL},S_SGUN4,0,0}, // S_SGUN3 + {SPR_SHTG,2,5,{NULL},S_SGUN5,0,0}, // S_SGUN4 + {SPR_SHTG,3,4,{NULL},S_SGUN6,0,0}, // S_SGUN5 + {SPR_SHTG,2,5,{NULL},S_SGUN7,0,0}, // S_SGUN6 + {SPR_SHTG,1,5,{NULL},S_SGUN8,0,0}, // S_SGUN7 + {SPR_SHTG,0,3,{NULL},S_SGUN9,0,0}, // S_SGUN8 + {SPR_SHTG,0,7,{A_ReFire},S_SGUN,0,0}, // S_SGUN9 + {SPR_SHTF,32768,4,{A_Light1},S_SGUNFLASH2,0,0}, // S_SGUNFLASH1 + {SPR_SHTF,32769,3,{A_Light2},S_LIGHTDONE,0,0}, // S_SGUNFLASH2 + {SPR_SHT2,0,1,{A_WeaponReady},S_DSGUN,0,0}, // S_DSGUN + {SPR_SHT2,0,1,{A_Lower},S_DSGUNDOWN,0,0}, // S_DSGUNDOWN + {SPR_SHT2,0,1,{A_Raise},S_DSGUNUP,0,0}, // S_DSGUNUP + {SPR_SHT2,0,3,{NULL},S_DSGUN2,0,0}, // S_DSGUN1 + {SPR_SHT2,0,7,{A_FireShotgun2},S_DSGUN3,0,0}, // S_DSGUN2 + {SPR_SHT2,1,7,{NULL},S_DSGUN4,0,0}, // S_DSGUN3 + {SPR_SHT2,2,7,{A_CheckReload},S_DSGUN5,0,0}, // S_DSGUN4 + {SPR_SHT2,3,7,{A_OpenShotgun2},S_DSGUN6,0,0}, // S_DSGUN5 + {SPR_SHT2,4,7,{NULL},S_DSGUN7,0,0}, // S_DSGUN6 + {SPR_SHT2,5,7,{A_LoadShotgun2},S_DSGUN8,0,0}, // S_DSGUN7 + {SPR_SHT2,6,6,{NULL},S_DSGUN9,0,0}, // S_DSGUN8 + {SPR_SHT2,7,6,{A_CloseShotgun2},S_DSGUN10,0,0}, // S_DSGUN9 + {SPR_SHT2,0,5,{A_ReFire},S_DSGUN,0,0}, // S_DSGUN10 + {SPR_SHT2,1,7,{NULL},S_DSNR2,0,0}, // S_DSNR1 + {SPR_SHT2,0,3,{NULL},S_DSGUNDOWN,0,0}, // S_DSNR2 + {SPR_SHT2,32776,5,{A_Light1},S_DSGUNFLASH2,0,0}, // S_DSGUNFLASH1 + {SPR_SHT2,32777,4,{A_Light2},S_LIGHTDONE,0,0}, // S_DSGUNFLASH2 + {SPR_CHGG,0,1,{A_WeaponReady},S_CHAIN,0,0}, // S_CHAIN + {SPR_CHGG,0,1,{A_Lower},S_CHAINDOWN,0,0}, // S_CHAINDOWN + {SPR_CHGG,0,1,{A_Raise},S_CHAINUP,0,0}, // S_CHAINUP + {SPR_CHGG,0,4,{A_FireCGun},S_CHAIN2,0,0}, // S_CHAIN1 + {SPR_CHGG,1,4,{A_FireCGun},S_CHAIN3,0,0}, // S_CHAIN2 + {SPR_CHGG,1,0,{A_ReFire},S_CHAIN,0,0}, // S_CHAIN3 + {SPR_CHGF,32768,5,{A_Light1},S_LIGHTDONE,0,0}, // S_CHAINFLASH1 + {SPR_CHGF,32769,5,{A_Light2},S_LIGHTDONE,0,0}, // S_CHAINFLASH2 + {SPR_MISG,0,1,{A_WeaponReady},S_MISSILE,0,0}, // S_MISSILE + {SPR_MISG,0,1,{A_Lower},S_MISSILEDOWN,0,0}, // S_MISSILEDOWN + {SPR_MISG,0,1,{A_Raise},S_MISSILEUP,0,0}, // S_MISSILEUP + {SPR_MISG,1,8,{A_GunFlash},S_MISSILE2,0,0}, // S_MISSILE1 + {SPR_MISG,1,12,{A_FireMissile},S_MISSILE3,0,0}, // S_MISSILE2 + {SPR_MISG,1,0,{A_ReFire},S_MISSILE,0,0}, // S_MISSILE3 + {SPR_MISF,32768,3,{A_Light1},S_MISSILEFLASH2,0,0}, // S_MISSILEFLASH1 + {SPR_MISF,32769,4,{NULL},S_MISSILEFLASH3,0,0}, // S_MISSILEFLASH2 + {SPR_MISF,32770,4,{A_Light2},S_MISSILEFLASH4,0,0}, // S_MISSILEFLASH3 + {SPR_MISF,32771,4,{A_Light2},S_LIGHTDONE,0,0}, // S_MISSILEFLASH4 + {SPR_SAWG,2,4,{A_WeaponReady},S_SAWB,0,0}, // S_SAW + {SPR_SAWG,3,4,{A_WeaponReady},S_SAW,0,0}, // S_SAWB + {SPR_SAWG,2,1,{A_Lower},S_SAWDOWN,0,0}, // S_SAWDOWN + {SPR_SAWG,2,1,{A_Raise},S_SAWUP,0,0}, // S_SAWUP + {SPR_SAWG,0,4,{A_Saw},S_SAW2,0,0}, // S_SAW1 + {SPR_SAWG,1,4,{A_Saw},S_SAW3,0,0}, // S_SAW2 + {SPR_SAWG,1,0,{A_ReFire},S_SAW,0,0}, // S_SAW3 + {SPR_PLSG,0,1,{A_WeaponReady},S_PLASMA,0,0}, // S_PLASMA + {SPR_PLSG,0,1,{A_Lower},S_PLASMADOWN,0,0}, // S_PLASMADOWN + {SPR_PLSG,0,1,{A_Raise},S_PLASMAUP,0,0}, // S_PLASMAUP + {SPR_PLSG,0,3,{A_FirePlasma},S_PLASMA2,0,0}, // S_PLASMA1 + {SPR_PLSG,1,20,{A_ReFire},S_PLASMA,0,0}, // S_PLASMA2 + {SPR_PLSF,32768,4,{A_Light1},S_LIGHTDONE,0,0}, // S_PLASMAFLASH1 + {SPR_PLSF,32769,4,{A_Light1},S_LIGHTDONE,0,0}, // S_PLASMAFLASH2 + {SPR_BFGG,0,1,{A_WeaponReady},S_BFG,0,0}, // S_BFG + {SPR_BFGG,0,1,{A_Lower},S_BFGDOWN,0,0}, // S_BFGDOWN + {SPR_BFGG,0,1,{A_Raise},S_BFGUP,0,0}, // S_BFGUP + {SPR_BFGG,0,20,{A_BFGsound},S_BFG2,0,0}, // S_BFG1 + {SPR_BFGG,1,10,{A_GunFlash},S_BFG3,0,0}, // S_BFG2 + {SPR_BFGG,1,10,{A_FireBFG},S_BFG4,0,0}, // S_BFG3 + {SPR_BFGG,1,20,{A_ReFire},S_BFG,0,0}, // S_BFG4 + {SPR_BFGF,32768,11,{A_Light1},S_BFGFLASH2,0,0}, // S_BFGFLASH1 + {SPR_BFGF,32769,6,{A_Light2},S_LIGHTDONE,0,0}, // S_BFGFLASH2 + {SPR_BLUD,2,8,{NULL},S_BLOOD2,0,0}, // S_BLOOD1 + {SPR_BLUD,1,8,{NULL},S_BLOOD3,0,0}, // S_BLOOD2 + {SPR_BLUD,0,8,{NULL},S_NULL,0,0}, // S_BLOOD3 + {SPR_PUFF,32768,4,{NULL},S_PUFF2,0,0}, // S_PUFF1 + {SPR_PUFF,1,4,{NULL},S_PUFF3,0,0}, // S_PUFF2 + {SPR_PUFF,2,4,{NULL},S_PUFF4,0,0}, // S_PUFF3 + {SPR_PUFF,3,4,{NULL},S_NULL,0,0}, // S_PUFF4 + {SPR_BAL1,32768,4,{NULL},S_TBALL2,0,0}, // S_TBALL1 + {SPR_BAL1,32769,4,{NULL},S_TBALL1,0,0}, // S_TBALL2 + {SPR_BAL1,32770,6,{NULL},S_TBALLX2,0,0}, // S_TBALLX1 + {SPR_BAL1,32771,6,{NULL},S_TBALLX3,0,0}, // S_TBALLX2 + {SPR_BAL1,32772,6,{NULL},S_NULL,0,0}, // S_TBALLX3 + {SPR_BAL2,32768,4,{NULL},S_RBALL2,0,0}, // S_RBALL1 + {SPR_BAL2,32769,4,{NULL},S_RBALL1,0,0}, // S_RBALL2 + {SPR_BAL2,32770,6,{NULL},S_RBALLX2,0,0}, // S_RBALLX1 + {SPR_BAL2,32771,6,{NULL},S_RBALLX3,0,0}, // S_RBALLX2 + {SPR_BAL2,32772,6,{NULL},S_NULL,0,0}, // S_RBALLX3 + {SPR_PLSS,32768,6,{NULL},S_PLASBALL2,0,0}, // S_PLASBALL + {SPR_PLSS,32769,6,{NULL},S_PLASBALL,0,0}, // S_PLASBALL2 + {SPR_PLSE,32768,4,{NULL},S_PLASEXP2,0,0}, // S_PLASEXP + {SPR_PLSE,32769,4,{NULL},S_PLASEXP3,0,0}, // S_PLASEXP2 + {SPR_PLSE,32770,4,{NULL},S_PLASEXP4,0,0}, // S_PLASEXP3 + {SPR_PLSE,32771,4,{NULL},S_PLASEXP5,0,0}, // S_PLASEXP4 + {SPR_PLSE,32772,4,{NULL},S_NULL,0,0}, // S_PLASEXP5 + {SPR_MISL,32768,1,{NULL},S_ROCKET,0,0}, // S_ROCKET + {SPR_BFS1,32768,4,{NULL},S_BFGSHOT2,0,0}, // S_BFGSHOT + {SPR_BFS1,32769,4,{NULL},S_BFGSHOT,0,0}, // S_BFGSHOT2 + {SPR_BFE1,32768,8,{NULL},S_BFGLAND2,0,0}, // S_BFGLAND + {SPR_BFE1,32769,8,{NULL},S_BFGLAND3,0,0}, // S_BFGLAND2 + {SPR_BFE1,32770,8,{A_BFGSpray},S_BFGLAND4,0,0}, // S_BFGLAND3 + {SPR_BFE1,32771,8,{NULL},S_BFGLAND5,0,0}, // S_BFGLAND4 + {SPR_BFE1,32772,8,{NULL},S_BFGLAND6,0,0}, // S_BFGLAND5 + {SPR_BFE1,32773,8,{NULL},S_NULL,0,0}, // S_BFGLAND6 + {SPR_BFE2,32768,8,{NULL},S_BFGEXP2,0,0}, // S_BFGEXP + {SPR_BFE2,32769,8,{NULL},S_BFGEXP3,0,0}, // S_BFGEXP2 + {SPR_BFE2,32770,8,{NULL},S_BFGEXP4,0,0}, // S_BFGEXP3 + {SPR_BFE2,32771,8,{NULL},S_NULL,0,0}, // S_BFGEXP4 + {SPR_MISL,32769,8,{A_Explode},S_EXPLODE2,0,0}, // S_EXPLODE1 + {SPR_MISL,32770,6,{NULL},S_EXPLODE3,0,0}, // S_EXPLODE2 + {SPR_MISL,32771,4,{NULL},S_NULL,0,0}, // S_EXPLODE3 + {SPR_TFOG,32768,6,{NULL},S_TFOG01,0,0}, // S_TFOG + {SPR_TFOG,32769,6,{NULL},S_TFOG02,0,0}, // S_TFOG01 + {SPR_TFOG,32768,6,{NULL},S_TFOG2,0,0}, // S_TFOG02 + {SPR_TFOG,32769,6,{NULL},S_TFOG3,0,0}, // S_TFOG2 + {SPR_TFOG,32770,6,{NULL},S_TFOG4,0,0}, // S_TFOG3 + {SPR_TFOG,32771,6,{NULL},S_TFOG5,0,0}, // S_TFOG4 + {SPR_TFOG,32772,6,{NULL},S_TFOG6,0,0}, // S_TFOG5 + {SPR_TFOG,32773,6,{NULL},S_TFOG7,0,0}, // S_TFOG6 + {SPR_TFOG,32774,6,{NULL},S_TFOG8,0,0}, // S_TFOG7 + {SPR_TFOG,32775,6,{NULL},S_TFOG9,0,0}, // S_TFOG8 + {SPR_TFOG,32776,6,{NULL},S_TFOG10,0,0}, // S_TFOG9 + {SPR_TFOG,32777,6,{NULL},S_NULL,0,0}, // S_TFOG10 + {SPR_IFOG,32768,6,{NULL},S_IFOG01,0,0}, // S_IFOG + {SPR_IFOG,32769,6,{NULL},S_IFOG02,0,0}, // S_IFOG01 + {SPR_IFOG,32768,6,{NULL},S_IFOG2,0,0}, // S_IFOG02 + {SPR_IFOG,32769,6,{NULL},S_IFOG3,0,0}, // S_IFOG2 + {SPR_IFOG,32770,6,{NULL},S_IFOG4,0,0}, // S_IFOG3 + {SPR_IFOG,32771,6,{NULL},S_IFOG5,0,0}, // S_IFOG4 + {SPR_IFOG,32772,6,{NULL},S_NULL,0,0}, // S_IFOG5 + {SPR_PLAY,0,-1,{NULL},S_NULL,0,0}, // S_PLAY + {SPR_PLAY,0,4,{NULL},S_PLAY_RUN2,0,0}, // S_PLAY_RUN1 + {SPR_PLAY,1,4,{NULL},S_PLAY_RUN3,0,0}, // S_PLAY_RUN2 + {SPR_PLAY,2,4,{NULL},S_PLAY_RUN4,0,0}, // S_PLAY_RUN3 + {SPR_PLAY,3,4,{NULL},S_PLAY_RUN1,0,0}, // S_PLAY_RUN4 + {SPR_PLAY,4,12,{NULL},S_PLAY,0,0}, // S_PLAY_ATK1 + {SPR_PLAY,32773,6,{NULL},S_PLAY_ATK1,0,0}, // S_PLAY_ATK2 + {SPR_PLAY,6,4,{NULL},S_PLAY_PAIN2,0,0}, // S_PLAY_PAIN + {SPR_PLAY,6,4,{A_Pain},S_PLAY,0,0}, // S_PLAY_PAIN2 + {SPR_PLAY,7,10,{NULL},S_PLAY_DIE2,0,0}, // S_PLAY_DIE1 + {SPR_PLAY,8,10,{A_PlayerScream},S_PLAY_DIE3,0,0}, // S_PLAY_DIE2 + {SPR_PLAY,9,10,{A_Fall},S_PLAY_DIE4,0,0}, // S_PLAY_DIE3 + {SPR_PLAY,10,10,{NULL},S_PLAY_DIE5,0,0}, // S_PLAY_DIE4 + {SPR_PLAY,11,10,{NULL},S_PLAY_DIE6,0,0}, // S_PLAY_DIE5 + {SPR_PLAY,12,10,{NULL},S_PLAY_DIE7,0,0}, // S_PLAY_DIE6 + {SPR_PLAY,13,-1,{NULL},S_NULL,0,0}, // S_PLAY_DIE7 + {SPR_PLAY,14,5,{NULL},S_PLAY_XDIE2,0,0}, // S_PLAY_XDIE1 + {SPR_PLAY,15,5,{A_XScream},S_PLAY_XDIE3,0,0}, // S_PLAY_XDIE2 + {SPR_PLAY,16,5,{A_Fall},S_PLAY_XDIE4,0,0}, // S_PLAY_XDIE3 + {SPR_PLAY,17,5,{NULL},S_PLAY_XDIE5,0,0}, // S_PLAY_XDIE4 + {SPR_PLAY,18,5,{NULL},S_PLAY_XDIE6,0,0}, // S_PLAY_XDIE5 + {SPR_PLAY,19,5,{NULL},S_PLAY_XDIE7,0,0}, // S_PLAY_XDIE6 + {SPR_PLAY,20,5,{NULL},S_PLAY_XDIE8,0,0}, // S_PLAY_XDIE7 + {SPR_PLAY,21,5,{NULL},S_PLAY_XDIE9,0,0}, // S_PLAY_XDIE8 + {SPR_PLAY,22,-1,{NULL},S_NULL,0,0}, // S_PLAY_XDIE9 + {SPR_POSS,0,10,{A_Look},S_POSS_STND2,0,0}, // S_POSS_STND + {SPR_POSS,1,10,{A_Look},S_POSS_STND,0,0}, // S_POSS_STND2 + {SPR_POSS,0,4,{A_Chase},S_POSS_RUN2,0,0}, // S_POSS_RUN1 + {SPR_POSS,0,4,{A_Chase},S_POSS_RUN3,0,0}, // S_POSS_RUN2 + {SPR_POSS,1,4,{A_Chase},S_POSS_RUN4,0,0}, // S_POSS_RUN3 + {SPR_POSS,1,4,{A_Chase},S_POSS_RUN5,0,0}, // S_POSS_RUN4 + {SPR_POSS,2,4,{A_Chase},S_POSS_RUN6,0,0}, // S_POSS_RUN5 + {SPR_POSS,2,4,{A_Chase},S_POSS_RUN7,0,0}, // S_POSS_RUN6 + {SPR_POSS,3,4,{A_Chase},S_POSS_RUN8,0,0}, // S_POSS_RUN7 + {SPR_POSS,3,4,{A_Chase},S_POSS_RUN1,0,0}, // S_POSS_RUN8 + {SPR_POSS,4,10,{A_FaceTarget},S_POSS_ATK2,0,0}, // S_POSS_ATK1 + {SPR_POSS,5,8,{A_PosAttack},S_POSS_ATK3,0,0}, // S_POSS_ATK2 + {SPR_POSS,4,8,{NULL},S_POSS_RUN1,0,0}, // S_POSS_ATK3 + {SPR_POSS,6,3,{NULL},S_POSS_PAIN2,0,0}, // S_POSS_PAIN + {SPR_POSS,6,3,{A_Pain},S_POSS_RUN1,0,0}, // S_POSS_PAIN2 + {SPR_POSS,7,5,{NULL},S_POSS_DIE2,0,0}, // S_POSS_DIE1 + {SPR_POSS,8,5,{A_Scream},S_POSS_DIE3,0,0}, // S_POSS_DIE2 + {SPR_POSS,9,5,{A_Fall},S_POSS_DIE4,0,0}, // S_POSS_DIE3 + {SPR_POSS,10,5,{NULL},S_POSS_DIE5,0,0}, // S_POSS_DIE4 + {SPR_POSS,11,-1,{NULL},S_NULL,0,0}, // S_POSS_DIE5 + {SPR_POSS,12,5,{NULL},S_POSS_XDIE2,0,0}, // S_POSS_XDIE1 + {SPR_POSS,13,5,{A_XScream},S_POSS_XDIE3,0,0}, // S_POSS_XDIE2 + {SPR_POSS,14,5,{A_Fall},S_POSS_XDIE4,0,0}, // S_POSS_XDIE3 + {SPR_POSS,15,5,{NULL},S_POSS_XDIE5,0,0}, // S_POSS_XDIE4 + {SPR_POSS,16,5,{NULL},S_POSS_XDIE6,0,0}, // S_POSS_XDIE5 + {SPR_POSS,17,5,{NULL},S_POSS_XDIE7,0,0}, // S_POSS_XDIE6 + {SPR_POSS,18,5,{NULL},S_POSS_XDIE8,0,0}, // S_POSS_XDIE7 + {SPR_POSS,19,5,{NULL},S_POSS_XDIE9,0,0}, // S_POSS_XDIE8 + {SPR_POSS,20,-1,{NULL},S_NULL,0,0}, // S_POSS_XDIE9 + {SPR_POSS,10,5,{NULL},S_POSS_RAISE2,0,0}, // S_POSS_RAISE1 + {SPR_POSS,9,5,{NULL},S_POSS_RAISE3,0,0}, // S_POSS_RAISE2 + {SPR_POSS,8,5,{NULL},S_POSS_RAISE4,0,0}, // S_POSS_RAISE3 + {SPR_POSS,7,5,{NULL},S_POSS_RUN1,0,0}, // S_POSS_RAISE4 + {SPR_SPOS,0,10,{A_Look},S_SPOS_STND2,0,0}, // S_SPOS_STND + {SPR_SPOS,1,10,{A_Look},S_SPOS_STND,0,0}, // S_SPOS_STND2 + {SPR_SPOS,0,3,{A_Chase},S_SPOS_RUN2,0,0}, // S_SPOS_RUN1 + {SPR_SPOS,0,3,{A_Chase},S_SPOS_RUN3,0,0}, // S_SPOS_RUN2 + {SPR_SPOS,1,3,{A_Chase},S_SPOS_RUN4,0,0}, // S_SPOS_RUN3 + {SPR_SPOS,1,3,{A_Chase},S_SPOS_RUN5,0,0}, // S_SPOS_RUN4 + {SPR_SPOS,2,3,{A_Chase},S_SPOS_RUN6,0,0}, // S_SPOS_RUN5 + {SPR_SPOS,2,3,{A_Chase},S_SPOS_RUN7,0,0}, // S_SPOS_RUN6 + {SPR_SPOS,3,3,{A_Chase},S_SPOS_RUN8,0,0}, // S_SPOS_RUN7 + {SPR_SPOS,3,3,{A_Chase},S_SPOS_RUN1,0,0}, // S_SPOS_RUN8 + {SPR_SPOS,4,10,{A_FaceTarget},S_SPOS_ATK2,0,0}, // S_SPOS_ATK1 + {SPR_SPOS,32773,10,{A_SPosAttack},S_SPOS_ATK3,0,0}, // S_SPOS_ATK2 + {SPR_SPOS,4,10,{NULL},S_SPOS_RUN1,0,0}, // S_SPOS_ATK3 + {SPR_SPOS,6,3,{NULL},S_SPOS_PAIN2,0,0}, // S_SPOS_PAIN + {SPR_SPOS,6,3,{A_Pain},S_SPOS_RUN1,0,0}, // S_SPOS_PAIN2 + {SPR_SPOS,7,5,{NULL},S_SPOS_DIE2,0,0}, // S_SPOS_DIE1 + {SPR_SPOS,8,5,{A_Scream},S_SPOS_DIE3,0,0}, // S_SPOS_DIE2 + {SPR_SPOS,9,5,{A_Fall},S_SPOS_DIE4,0,0}, // S_SPOS_DIE3 + {SPR_SPOS,10,5,{NULL},S_SPOS_DIE5,0,0}, // S_SPOS_DIE4 + {SPR_SPOS,11,-1,{NULL},S_NULL,0,0}, // S_SPOS_DIE5 + {SPR_SPOS,12,5,{NULL},S_SPOS_XDIE2,0,0}, // S_SPOS_XDIE1 + {SPR_SPOS,13,5,{A_XScream},S_SPOS_XDIE3,0,0}, // S_SPOS_XDIE2 + {SPR_SPOS,14,5,{A_Fall},S_SPOS_XDIE4,0,0}, // S_SPOS_XDIE3 + {SPR_SPOS,15,5,{NULL},S_SPOS_XDIE5,0,0}, // S_SPOS_XDIE4 + {SPR_SPOS,16,5,{NULL},S_SPOS_XDIE6,0,0}, // S_SPOS_XDIE5 + {SPR_SPOS,17,5,{NULL},S_SPOS_XDIE7,0,0}, // S_SPOS_XDIE6 + {SPR_SPOS,18,5,{NULL},S_SPOS_XDIE8,0,0}, // S_SPOS_XDIE7 + {SPR_SPOS,19,5,{NULL},S_SPOS_XDIE9,0,0}, // S_SPOS_XDIE8 + {SPR_SPOS,20,-1,{NULL},S_NULL,0,0}, // S_SPOS_XDIE9 + {SPR_SPOS,11,5,{NULL},S_SPOS_RAISE2,0,0}, // S_SPOS_RAISE1 + {SPR_SPOS,10,5,{NULL},S_SPOS_RAISE3,0,0}, // S_SPOS_RAISE2 + {SPR_SPOS,9,5,{NULL},S_SPOS_RAISE4,0,0}, // S_SPOS_RAISE3 + {SPR_SPOS,8,5,{NULL},S_SPOS_RAISE5,0,0}, // S_SPOS_RAISE4 + {SPR_SPOS,7,5,{NULL},S_SPOS_RUN1,0,0}, // S_SPOS_RAISE5 + {SPR_VILE,0,10,{A_Look},S_VILE_STND2,0,0}, // S_VILE_STND + {SPR_VILE,1,10,{A_Look},S_VILE_STND,0,0}, // S_VILE_STND2 + {SPR_VILE,0,2,{A_VileChase},S_VILE_RUN2,0,0}, // S_VILE_RUN1 + {SPR_VILE,0,2,{A_VileChase},S_VILE_RUN3,0,0}, // S_VILE_RUN2 + {SPR_VILE,1,2,{A_VileChase},S_VILE_RUN4,0,0}, // S_VILE_RUN3 + {SPR_VILE,1,2,{A_VileChase},S_VILE_RUN5,0,0}, // S_VILE_RUN4 + {SPR_VILE,2,2,{A_VileChase},S_VILE_RUN6,0,0}, // S_VILE_RUN5 + {SPR_VILE,2,2,{A_VileChase},S_VILE_RUN7,0,0}, // S_VILE_RUN6 + {SPR_VILE,3,2,{A_VileChase},S_VILE_RUN8,0,0}, // S_VILE_RUN7 + {SPR_VILE,3,2,{A_VileChase},S_VILE_RUN9,0,0}, // S_VILE_RUN8 + {SPR_VILE,4,2,{A_VileChase},S_VILE_RUN10,0,0}, // S_VILE_RUN9 + {SPR_VILE,4,2,{A_VileChase},S_VILE_RUN11,0,0}, // S_VILE_RUN10 + {SPR_VILE,5,2,{A_VileChase},S_VILE_RUN12,0,0}, // S_VILE_RUN11 + {SPR_VILE,5,2,{A_VileChase},S_VILE_RUN1,0,0}, // S_VILE_RUN12 + {SPR_VILE,32774,0,{A_VileStart},S_VILE_ATK2,0,0}, // S_VILE_ATK1 + {SPR_VILE,32774,10,{A_FaceTarget},S_VILE_ATK3,0,0}, // S_VILE_ATK2 + {SPR_VILE,32775,8,{A_VileTarget},S_VILE_ATK4,0,0}, // S_VILE_ATK3 + {SPR_VILE,32776,8,{A_FaceTarget},S_VILE_ATK5,0,0}, // S_VILE_ATK4 + {SPR_VILE,32777,8,{A_FaceTarget},S_VILE_ATK6,0,0}, // S_VILE_ATK5 + {SPR_VILE,32778,8,{A_FaceTarget},S_VILE_ATK7,0,0}, // S_VILE_ATK6 + {SPR_VILE,32779,8,{A_FaceTarget},S_VILE_ATK8,0,0}, // S_VILE_ATK7 + {SPR_VILE,32780,8,{A_FaceTarget},S_VILE_ATK9,0,0}, // S_VILE_ATK8 + {SPR_VILE,32781,8,{A_FaceTarget},S_VILE_ATK10,0,0}, // S_VILE_ATK9 + {SPR_VILE,32782,8,{A_VileAttack},S_VILE_ATK11,0,0}, // S_VILE_ATK10 + {SPR_VILE,32783,20,{NULL},S_VILE_RUN1,0,0}, // S_VILE_ATK11 + {SPR_VILE,32794,10,{NULL},S_VILE_HEAL2,0,0}, // S_VILE_HEAL1 + {SPR_VILE,32795,10,{NULL},S_VILE_HEAL3,0,0}, // S_VILE_HEAL2 + {SPR_VILE,32796,10,{NULL},S_VILE_RUN1,0,0}, // S_VILE_HEAL3 + {SPR_VILE,16,5,{NULL},S_VILE_PAIN2,0,0}, // S_VILE_PAIN + {SPR_VILE,16,5,{A_Pain},S_VILE_RUN1,0,0}, // S_VILE_PAIN2 + {SPR_VILE,16,7,{NULL},S_VILE_DIE2,0,0}, // S_VILE_DIE1 + {SPR_VILE,17,7,{A_Scream},S_VILE_DIE3,0,0}, // S_VILE_DIE2 + {SPR_VILE,18,7,{A_Fall},S_VILE_DIE4,0,0}, // S_VILE_DIE3 + {SPR_VILE,19,7,{NULL},S_VILE_DIE5,0,0}, // S_VILE_DIE4 + {SPR_VILE,20,7,{NULL},S_VILE_DIE6,0,0}, // S_VILE_DIE5 + {SPR_VILE,21,7,{NULL},S_VILE_DIE7,0,0}, // S_VILE_DIE6 + {SPR_VILE,22,7,{NULL},S_VILE_DIE8,0,0}, // S_VILE_DIE7 + {SPR_VILE,23,5,{NULL},S_VILE_DIE9,0,0}, // S_VILE_DIE8 + {SPR_VILE,24,5,{NULL},S_VILE_DIE10,0,0}, // S_VILE_DIE9 + {SPR_VILE,25,-1,{NULL},S_NULL,0,0}, // S_VILE_DIE10 + {SPR_FIRE,32768,2,{A_StartFire},S_FIRE2,0,0}, // S_FIRE1 + {SPR_FIRE,32769,2,{A_Fire},S_FIRE3,0,0}, // S_FIRE2 + {SPR_FIRE,32768,2,{A_Fire},S_FIRE4,0,0}, // S_FIRE3 + {SPR_FIRE,32769,2,{A_Fire},S_FIRE5,0,0}, // S_FIRE4 + {SPR_FIRE,32770,2,{A_FireCrackle},S_FIRE6,0,0}, // S_FIRE5 + {SPR_FIRE,32769,2,{A_Fire},S_FIRE7,0,0}, // S_FIRE6 + {SPR_FIRE,32770,2,{A_Fire},S_FIRE8,0,0}, // S_FIRE7 + {SPR_FIRE,32769,2,{A_Fire},S_FIRE9,0,0}, // S_FIRE8 + {SPR_FIRE,32770,2,{A_Fire},S_FIRE10,0,0}, // S_FIRE9 + {SPR_FIRE,32771,2,{A_Fire},S_FIRE11,0,0}, // S_FIRE10 + {SPR_FIRE,32770,2,{A_Fire},S_FIRE12,0,0}, // S_FIRE11 + {SPR_FIRE,32771,2,{A_Fire},S_FIRE13,0,0}, // S_FIRE12 + {SPR_FIRE,32770,2,{A_Fire},S_FIRE14,0,0}, // S_FIRE13 + {SPR_FIRE,32771,2,{A_Fire},S_FIRE15,0,0}, // S_FIRE14 + {SPR_FIRE,32772,2,{A_Fire},S_FIRE16,0,0}, // S_FIRE15 + {SPR_FIRE,32771,2,{A_Fire},S_FIRE17,0,0}, // S_FIRE16 + {SPR_FIRE,32772,2,{A_Fire},S_FIRE18,0,0}, // S_FIRE17 + {SPR_FIRE,32771,2,{A_Fire},S_FIRE19,0,0}, // S_FIRE18 + {SPR_FIRE,32772,2,{A_FireCrackle},S_FIRE20,0,0}, // S_FIRE19 + {SPR_FIRE,32773,2,{A_Fire},S_FIRE21,0,0}, // S_FIRE20 + {SPR_FIRE,32772,2,{A_Fire},S_FIRE22,0,0}, // S_FIRE21 + {SPR_FIRE,32773,2,{A_Fire},S_FIRE23,0,0}, // S_FIRE22 + {SPR_FIRE,32772,2,{A_Fire},S_FIRE24,0,0}, // S_FIRE23 + {SPR_FIRE,32773,2,{A_Fire},S_FIRE25,0,0}, // S_FIRE24 + {SPR_FIRE,32774,2,{A_Fire},S_FIRE26,0,0}, // S_FIRE25 + {SPR_FIRE,32775,2,{A_Fire},S_FIRE27,0,0}, // S_FIRE26 + {SPR_FIRE,32774,2,{A_Fire},S_FIRE28,0,0}, // S_FIRE27 + {SPR_FIRE,32775,2,{A_Fire},S_FIRE29,0,0}, // S_FIRE28 + {SPR_FIRE,32774,2,{A_Fire},S_FIRE30,0,0}, // S_FIRE29 + {SPR_FIRE,32775,2,{A_Fire},S_NULL,0,0}, // S_FIRE30 + {SPR_PUFF,1,4,{NULL},S_SMOKE2,0,0}, // S_SMOKE1 + {SPR_PUFF,2,4,{NULL},S_SMOKE3,0,0}, // S_SMOKE2 + {SPR_PUFF,1,4,{NULL},S_SMOKE4,0,0}, // S_SMOKE3 + {SPR_PUFF,2,4,{NULL},S_SMOKE5,0,0}, // S_SMOKE4 + {SPR_PUFF,3,4,{NULL},S_NULL,0,0}, // S_SMOKE5 + {SPR_FATB,32768,2,{A_Tracer},S_TRACER2,0,0}, // S_TRACER + {SPR_FATB,32769,2,{A_Tracer},S_TRACER,0,0}, // S_TRACER2 + {SPR_FBXP,32768,8,{NULL},S_TRACEEXP2,0,0}, // S_TRACEEXP1 + {SPR_FBXP,32769,6,{NULL},S_TRACEEXP3,0,0}, // S_TRACEEXP2 + {SPR_FBXP,32770,4,{NULL},S_NULL,0,0}, // S_TRACEEXP3 + {SPR_SKEL,0,10,{A_Look},S_SKEL_STND2,0,0}, // S_SKEL_STND + {SPR_SKEL,1,10,{A_Look},S_SKEL_STND,0,0}, // S_SKEL_STND2 + {SPR_SKEL,0,2,{A_Chase},S_SKEL_RUN2,0,0}, // S_SKEL_RUN1 + {SPR_SKEL,0,2,{A_Chase},S_SKEL_RUN3,0,0}, // S_SKEL_RUN2 + {SPR_SKEL,1,2,{A_Chase},S_SKEL_RUN4,0,0}, // S_SKEL_RUN3 + {SPR_SKEL,1,2,{A_Chase},S_SKEL_RUN5,0,0}, // S_SKEL_RUN4 + {SPR_SKEL,2,2,{A_Chase},S_SKEL_RUN6,0,0}, // S_SKEL_RUN5 + {SPR_SKEL,2,2,{A_Chase},S_SKEL_RUN7,0,0}, // S_SKEL_RUN6 + {SPR_SKEL,3,2,{A_Chase},S_SKEL_RUN8,0,0}, // S_SKEL_RUN7 + {SPR_SKEL,3,2,{A_Chase},S_SKEL_RUN9,0,0}, // S_SKEL_RUN8 + {SPR_SKEL,4,2,{A_Chase},S_SKEL_RUN10,0,0}, // S_SKEL_RUN9 + {SPR_SKEL,4,2,{A_Chase},S_SKEL_RUN11,0,0}, // S_SKEL_RUN10 + {SPR_SKEL,5,2,{A_Chase},S_SKEL_RUN12,0,0}, // S_SKEL_RUN11 + {SPR_SKEL,5,2,{A_Chase},S_SKEL_RUN1,0,0}, // S_SKEL_RUN12 + {SPR_SKEL,6,0,{A_FaceTarget},S_SKEL_FIST2,0,0}, // S_SKEL_FIST1 + {SPR_SKEL,6,6,{A_SkelWhoosh},S_SKEL_FIST3,0,0}, // S_SKEL_FIST2 + {SPR_SKEL,7,6,{A_FaceTarget},S_SKEL_FIST4,0,0}, // S_SKEL_FIST3 + {SPR_SKEL,8,6,{A_SkelFist},S_SKEL_RUN1,0,0}, // S_SKEL_FIST4 + {SPR_SKEL,32777,0,{A_FaceTarget},S_SKEL_MISS2,0,0}, // S_SKEL_MISS1 + {SPR_SKEL,32777,10,{A_FaceTarget},S_SKEL_MISS3,0,0}, // S_SKEL_MISS2 + {SPR_SKEL,10,10,{A_SkelMissile},S_SKEL_MISS4,0,0}, // S_SKEL_MISS3 + {SPR_SKEL,10,10,{A_FaceTarget},S_SKEL_RUN1,0,0}, // S_SKEL_MISS4 + {SPR_SKEL,11,5,{NULL},S_SKEL_PAIN2,0,0}, // S_SKEL_PAIN + {SPR_SKEL,11,5,{A_Pain},S_SKEL_RUN1,0,0}, // S_SKEL_PAIN2 + {SPR_SKEL,11,7,{NULL},S_SKEL_DIE2,0,0}, // S_SKEL_DIE1 + {SPR_SKEL,12,7,{NULL},S_SKEL_DIE3,0,0}, // S_SKEL_DIE2 + {SPR_SKEL,13,7,{A_Scream},S_SKEL_DIE4,0,0}, // S_SKEL_DIE3 + {SPR_SKEL,14,7,{A_Fall},S_SKEL_DIE5,0,0}, // S_SKEL_DIE4 + {SPR_SKEL,15,7,{NULL},S_SKEL_DIE6,0,0}, // S_SKEL_DIE5 + {SPR_SKEL,16,-1,{NULL},S_NULL,0,0}, // S_SKEL_DIE6 + {SPR_SKEL,16,5,{NULL},S_SKEL_RAISE2,0,0}, // S_SKEL_RAISE1 + {SPR_SKEL,15,5,{NULL},S_SKEL_RAISE3,0,0}, // S_SKEL_RAISE2 + {SPR_SKEL,14,5,{NULL},S_SKEL_RAISE4,0,0}, // S_SKEL_RAISE3 + {SPR_SKEL,13,5,{NULL},S_SKEL_RAISE5,0,0}, // S_SKEL_RAISE4 + {SPR_SKEL,12,5,{NULL},S_SKEL_RAISE6,0,0}, // S_SKEL_RAISE5 + {SPR_SKEL,11,5,{NULL},S_SKEL_RUN1,0,0}, // S_SKEL_RAISE6 + {SPR_MANF,32768,4,{NULL},S_FATSHOT2,0,0}, // S_FATSHOT1 + {SPR_MANF,32769,4,{NULL},S_FATSHOT1,0,0}, // S_FATSHOT2 + {SPR_MISL,32769,8,{NULL},S_FATSHOTX2,0,0}, // S_FATSHOTX1 + {SPR_MISL,32770,6,{NULL},S_FATSHOTX3,0,0}, // S_FATSHOTX2 + {SPR_MISL,32771,4,{NULL},S_NULL,0,0}, // S_FATSHOTX3 + {SPR_FATT,0,15,{A_Look},S_FATT_STND2,0,0}, // S_FATT_STND + {SPR_FATT,1,15,{A_Look},S_FATT_STND,0,0}, // S_FATT_STND2 + {SPR_FATT,0,4,{A_Chase},S_FATT_RUN2,0,0}, // S_FATT_RUN1 + {SPR_FATT,0,4,{A_Chase},S_FATT_RUN3,0,0}, // S_FATT_RUN2 + {SPR_FATT,1,4,{A_Chase},S_FATT_RUN4,0,0}, // S_FATT_RUN3 + {SPR_FATT,1,4,{A_Chase},S_FATT_RUN5,0,0}, // S_FATT_RUN4 + {SPR_FATT,2,4,{A_Chase},S_FATT_RUN6,0,0}, // S_FATT_RUN5 + {SPR_FATT,2,4,{A_Chase},S_FATT_RUN7,0,0}, // S_FATT_RUN6 + {SPR_FATT,3,4,{A_Chase},S_FATT_RUN8,0,0}, // S_FATT_RUN7 + {SPR_FATT,3,4,{A_Chase},S_FATT_RUN9,0,0}, // S_FATT_RUN8 + {SPR_FATT,4,4,{A_Chase},S_FATT_RUN10,0,0}, // S_FATT_RUN9 + {SPR_FATT,4,4,{A_Chase},S_FATT_RUN11,0,0}, // S_FATT_RUN10 + {SPR_FATT,5,4,{A_Chase},S_FATT_RUN12,0,0}, // S_FATT_RUN11 + {SPR_FATT,5,4,{A_Chase},S_FATT_RUN1,0,0}, // S_FATT_RUN12 + {SPR_FATT,6,20,{A_FatRaise},S_FATT_ATK2,0,0}, // S_FATT_ATK1 + {SPR_FATT,32775,10,{A_FatAttack1},S_FATT_ATK3,0,0}, // S_FATT_ATK2 + {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK4,0,0}, // S_FATT_ATK3 + {SPR_FATT,6,5,{A_FaceTarget},S_FATT_ATK5,0,0}, // S_FATT_ATK4 + {SPR_FATT,32775,10,{A_FatAttack2},S_FATT_ATK6,0,0}, // S_FATT_ATK5 + {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK7,0,0}, // S_FATT_ATK6 + {SPR_FATT,6,5,{A_FaceTarget},S_FATT_ATK8,0,0}, // S_FATT_ATK7 + {SPR_FATT,32775,10,{A_FatAttack3},S_FATT_ATK9,0,0}, // S_FATT_ATK8 + {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK10,0,0}, // S_FATT_ATK9 + {SPR_FATT,6,5,{A_FaceTarget},S_FATT_RUN1,0,0}, // S_FATT_ATK10 + {SPR_FATT,9,3,{NULL},S_FATT_PAIN2,0,0}, // S_FATT_PAIN + {SPR_FATT,9,3,{A_Pain},S_FATT_RUN1,0,0}, // S_FATT_PAIN2 + {SPR_FATT,10,6,{NULL},S_FATT_DIE2,0,0}, // S_FATT_DIE1 + {SPR_FATT,11,6,{A_Scream},S_FATT_DIE3,0,0}, // S_FATT_DIE2 + {SPR_FATT,12,6,{A_Fall},S_FATT_DIE4,0,0}, // S_FATT_DIE3 + {SPR_FATT,13,6,{NULL},S_FATT_DIE5,0,0}, // S_FATT_DIE4 + {SPR_FATT,14,6,{NULL},S_FATT_DIE6,0,0}, // S_FATT_DIE5 + {SPR_FATT,15,6,{NULL},S_FATT_DIE7,0,0}, // S_FATT_DIE6 + {SPR_FATT,16,6,{NULL},S_FATT_DIE8,0,0}, // S_FATT_DIE7 + {SPR_FATT,17,6,{NULL},S_FATT_DIE9,0,0}, // S_FATT_DIE8 + {SPR_FATT,18,6,{NULL},S_FATT_DIE10,0,0}, // S_FATT_DIE9 + {SPR_FATT,19,-1,{A_BossDeath},S_NULL,0,0}, // S_FATT_DIE10 + {SPR_FATT,17,5,{NULL},S_FATT_RAISE2,0,0}, // S_FATT_RAISE1 + {SPR_FATT,16,5,{NULL},S_FATT_RAISE3,0,0}, // S_FATT_RAISE2 + {SPR_FATT,15,5,{NULL},S_FATT_RAISE4,0,0}, // S_FATT_RAISE3 + {SPR_FATT,14,5,{NULL},S_FATT_RAISE5,0,0}, // S_FATT_RAISE4 + {SPR_FATT,13,5,{NULL},S_FATT_RAISE6,0,0}, // S_FATT_RAISE5 + {SPR_FATT,12,5,{NULL},S_FATT_RAISE7,0,0}, // S_FATT_RAISE6 + {SPR_FATT,11,5,{NULL},S_FATT_RAISE8,0,0}, // S_FATT_RAISE7 + {SPR_FATT,10,5,{NULL},S_FATT_RUN1,0,0}, // S_FATT_RAISE8 + {SPR_CPOS,0,10,{A_Look},S_CPOS_STND2,0,0}, // S_CPOS_STND + {SPR_CPOS,1,10,{A_Look},S_CPOS_STND,0,0}, // S_CPOS_STND2 + {SPR_CPOS,0,3,{A_Chase},S_CPOS_RUN2,0,0}, // S_CPOS_RUN1 + {SPR_CPOS,0,3,{A_Chase},S_CPOS_RUN3,0,0}, // S_CPOS_RUN2 + {SPR_CPOS,1,3,{A_Chase},S_CPOS_RUN4,0,0}, // S_CPOS_RUN3 + {SPR_CPOS,1,3,{A_Chase},S_CPOS_RUN5,0,0}, // S_CPOS_RUN4 + {SPR_CPOS,2,3,{A_Chase},S_CPOS_RUN6,0,0}, // S_CPOS_RUN5 + {SPR_CPOS,2,3,{A_Chase},S_CPOS_RUN7,0,0}, // S_CPOS_RUN6 + {SPR_CPOS,3,3,{A_Chase},S_CPOS_RUN8,0,0}, // S_CPOS_RUN7 + {SPR_CPOS,3,3,{A_Chase},S_CPOS_RUN1,0,0}, // S_CPOS_RUN8 + {SPR_CPOS,4,10,{A_FaceTarget},S_CPOS_ATK2,0,0}, // S_CPOS_ATK1 + {SPR_CPOS,32773,4,{A_CPosAttack},S_CPOS_ATK3,0,0}, // S_CPOS_ATK2 + {SPR_CPOS,32772,4,{A_CPosAttack},S_CPOS_ATK4,0,0}, // S_CPOS_ATK3 + {SPR_CPOS,5,1,{A_CPosRefire},S_CPOS_ATK2,0,0}, // S_CPOS_ATK4 + {SPR_CPOS,6,3,{NULL},S_CPOS_PAIN2,0,0}, // S_CPOS_PAIN + {SPR_CPOS,6,3,{A_Pain},S_CPOS_RUN1,0,0}, // S_CPOS_PAIN2 + {SPR_CPOS,7,5,{NULL},S_CPOS_DIE2,0,0}, // S_CPOS_DIE1 + {SPR_CPOS,8,5,{A_Scream},S_CPOS_DIE3,0,0}, // S_CPOS_DIE2 + {SPR_CPOS,9,5,{A_Fall},S_CPOS_DIE4,0,0}, // S_CPOS_DIE3 + {SPR_CPOS,10,5,{NULL},S_CPOS_DIE5,0,0}, // S_CPOS_DIE4 + {SPR_CPOS,11,5,{NULL},S_CPOS_DIE6,0,0}, // S_CPOS_DIE5 + {SPR_CPOS,12,5,{NULL},S_CPOS_DIE7,0,0}, // S_CPOS_DIE6 + {SPR_CPOS,13,-1,{NULL},S_NULL,0,0}, // S_CPOS_DIE7 + {SPR_CPOS,14,5,{NULL},S_CPOS_XDIE2,0,0}, // S_CPOS_XDIE1 + {SPR_CPOS,15,5,{A_XScream},S_CPOS_XDIE3,0,0}, // S_CPOS_XDIE2 + {SPR_CPOS,16,5,{A_Fall},S_CPOS_XDIE4,0,0}, // S_CPOS_XDIE3 + {SPR_CPOS,17,5,{NULL},S_CPOS_XDIE5,0,0}, // S_CPOS_XDIE4 + {SPR_CPOS,18,5,{NULL},S_CPOS_XDIE6,0,0}, // S_CPOS_XDIE5 + {SPR_CPOS,19,-1,{NULL},S_NULL,0,0}, // S_CPOS_XDIE6 + {SPR_CPOS,13,5,{NULL},S_CPOS_RAISE2,0,0}, // S_CPOS_RAISE1 + {SPR_CPOS,12,5,{NULL},S_CPOS_RAISE3,0,0}, // S_CPOS_RAISE2 + {SPR_CPOS,11,5,{NULL},S_CPOS_RAISE4,0,0}, // S_CPOS_RAISE3 + {SPR_CPOS,10,5,{NULL},S_CPOS_RAISE5,0,0}, // S_CPOS_RAISE4 + {SPR_CPOS,9,5,{NULL},S_CPOS_RAISE6,0,0}, // S_CPOS_RAISE5 + {SPR_CPOS,8,5,{NULL},S_CPOS_RAISE7,0,0}, // S_CPOS_RAISE6 + {SPR_CPOS,7,5,{NULL},S_CPOS_RUN1,0,0}, // S_CPOS_RAISE7 + {SPR_TROO,0,10,{A_Look},S_TROO_STND2,0,0}, // S_TROO_STND + {SPR_TROO,1,10,{A_Look},S_TROO_STND,0,0}, // S_TROO_STND2 + {SPR_TROO,0,3,{A_Chase},S_TROO_RUN2,0,0}, // S_TROO_RUN1 + {SPR_TROO,0,3,{A_Chase},S_TROO_RUN3,0,0}, // S_TROO_RUN2 + {SPR_TROO,1,3,{A_Chase},S_TROO_RUN4,0,0}, // S_TROO_RUN3 + {SPR_TROO,1,3,{A_Chase},S_TROO_RUN5,0,0}, // S_TROO_RUN4 + {SPR_TROO,2,3,{A_Chase},S_TROO_RUN6,0,0}, // S_TROO_RUN5 + {SPR_TROO,2,3,{A_Chase},S_TROO_RUN7,0,0}, // S_TROO_RUN6 + {SPR_TROO,3,3,{A_Chase},S_TROO_RUN8,0,0}, // S_TROO_RUN7 + {SPR_TROO,3,3,{A_Chase},S_TROO_RUN1,0,0}, // S_TROO_RUN8 + {SPR_TROO,4,8,{A_FaceTarget},S_TROO_ATK2,0,0}, // S_TROO_ATK1 + {SPR_TROO,5,8,{A_FaceTarget},S_TROO_ATK3,0,0}, // S_TROO_ATK2 + {SPR_TROO,6,6,{A_TroopAttack},S_TROO_RUN1,0,0}, // S_TROO_ATK3 + {SPR_TROO,7,2,{NULL},S_TROO_PAIN2,0,0}, // S_TROO_PAIN + {SPR_TROO,7,2,{A_Pain},S_TROO_RUN1,0,0}, // S_TROO_PAIN2 + {SPR_TROO,8,8,{NULL},S_TROO_DIE2,0,0}, // S_TROO_DIE1 + {SPR_TROO,9,8,{A_Scream},S_TROO_DIE3,0,0}, // S_TROO_DIE2 + {SPR_TROO,10,6,{NULL},S_TROO_DIE4,0,0}, // S_TROO_DIE3 + {SPR_TROO,11,6,{A_Fall},S_TROO_DIE5,0,0}, // S_TROO_DIE4 + {SPR_TROO,12,-1,{NULL},S_NULL,0,0}, // S_TROO_DIE5 + {SPR_TROO,13,5,{NULL},S_TROO_XDIE2,0,0}, // S_TROO_XDIE1 + {SPR_TROO,14,5,{A_XScream},S_TROO_XDIE3,0,0}, // S_TROO_XDIE2 + {SPR_TROO,15,5,{NULL},S_TROO_XDIE4,0,0}, // S_TROO_XDIE3 + {SPR_TROO,16,5,{A_Fall},S_TROO_XDIE5,0,0}, // S_TROO_XDIE4 + {SPR_TROO,17,5,{NULL},S_TROO_XDIE6,0,0}, // S_TROO_XDIE5 + {SPR_TROO,18,5,{NULL},S_TROO_XDIE7,0,0}, // S_TROO_XDIE6 + {SPR_TROO,19,5,{NULL},S_TROO_XDIE8,0,0}, // S_TROO_XDIE7 + {SPR_TROO,20,-1,{NULL},S_NULL,0,0}, // S_TROO_XDIE8 + {SPR_TROO,12,8,{NULL},S_TROO_RAISE2,0,0}, // S_TROO_RAISE1 + {SPR_TROO,11,8,{NULL},S_TROO_RAISE3,0,0}, // S_TROO_RAISE2 + {SPR_TROO,10,6,{NULL},S_TROO_RAISE4,0,0}, // S_TROO_RAISE3 + {SPR_TROO,9,6,{NULL},S_TROO_RAISE5,0,0}, // S_TROO_RAISE4 + {SPR_TROO,8,6,{NULL},S_TROO_RUN1,0,0}, // S_TROO_RAISE5 + {SPR_SARG,0,10,{A_Look},S_SARG_STND2,0,0}, // S_SARG_STND + {SPR_SARG,1,10,{A_Look},S_SARG_STND,0,0}, // S_SARG_STND2 + {SPR_SARG,0,2,{A_Chase},S_SARG_RUN2,0,0}, // S_SARG_RUN1 + {SPR_SARG,0,2,{A_Chase},S_SARG_RUN3,0,0}, // S_SARG_RUN2 + {SPR_SARG,1,2,{A_Chase},S_SARG_RUN4,0,0}, // S_SARG_RUN3 + {SPR_SARG,1,2,{A_Chase},S_SARG_RUN5,0,0}, // S_SARG_RUN4 + {SPR_SARG,2,2,{A_Chase},S_SARG_RUN6,0,0}, // S_SARG_RUN5 + {SPR_SARG,2,2,{A_Chase},S_SARG_RUN7,0,0}, // S_SARG_RUN6 + {SPR_SARG,3,2,{A_Chase},S_SARG_RUN8,0,0}, // S_SARG_RUN7 + {SPR_SARG,3,2,{A_Chase},S_SARG_RUN1,0,0}, // S_SARG_RUN8 + {SPR_SARG,4,8,{A_FaceTarget},S_SARG_ATK2,0,0}, // S_SARG_ATK1 + {SPR_SARG,5,8,{A_FaceTarget},S_SARG_ATK3,0,0}, // S_SARG_ATK2 + {SPR_SARG,6,8,{A_SargAttack},S_SARG_RUN1,0,0}, // S_SARG_ATK3 + {SPR_SARG,7,2,{NULL},S_SARG_PAIN2,0,0}, // S_SARG_PAIN + {SPR_SARG,7,2,{A_Pain},S_SARG_RUN1,0,0}, // S_SARG_PAIN2 + {SPR_SARG,8,8,{NULL},S_SARG_DIE2,0,0}, // S_SARG_DIE1 + {SPR_SARG,9,8,{A_Scream},S_SARG_DIE3,0,0}, // S_SARG_DIE2 + {SPR_SARG,10,4,{NULL},S_SARG_DIE4,0,0}, // S_SARG_DIE3 + {SPR_SARG,11,4,{A_Fall},S_SARG_DIE5,0,0}, // S_SARG_DIE4 + {SPR_SARG,12,4,{NULL},S_SARG_DIE6,0,0}, // S_SARG_DIE5 + {SPR_SARG,13,-1,{NULL},S_NULL,0,0}, // S_SARG_DIE6 + {SPR_SARG,13,5,{NULL},S_SARG_RAISE2,0,0}, // S_SARG_RAISE1 + {SPR_SARG,12,5,{NULL},S_SARG_RAISE3,0,0}, // S_SARG_RAISE2 + {SPR_SARG,11,5,{NULL},S_SARG_RAISE4,0,0}, // S_SARG_RAISE3 + {SPR_SARG,10,5,{NULL},S_SARG_RAISE5,0,0}, // S_SARG_RAISE4 + {SPR_SARG,9,5,{NULL},S_SARG_RAISE6,0,0}, // S_SARG_RAISE5 + {SPR_SARG,8,5,{NULL},S_SARG_RUN1,0,0}, // S_SARG_RAISE6 + {SPR_HEAD,0,10,{A_Look},S_HEAD_STND,0,0}, // S_HEAD_STND + {SPR_HEAD,0,3,{A_Chase},S_HEAD_RUN1,0,0}, // S_HEAD_RUN1 + {SPR_HEAD,1,5,{A_FaceTarget},S_HEAD_ATK2,0,0}, // S_HEAD_ATK1 + {SPR_HEAD,2,5,{A_FaceTarget},S_HEAD_ATK3,0,0}, // S_HEAD_ATK2 + {SPR_HEAD,32771,5,{A_HeadAttack},S_HEAD_RUN1,0,0}, // S_HEAD_ATK3 + {SPR_HEAD,4,3,{NULL},S_HEAD_PAIN2,0,0}, // S_HEAD_PAIN + {SPR_HEAD,4,3,{A_Pain},S_HEAD_PAIN3,0,0}, // S_HEAD_PAIN2 + {SPR_HEAD,5,6,{NULL},S_HEAD_RUN1,0,0}, // S_HEAD_PAIN3 + {SPR_HEAD,6,8,{NULL},S_HEAD_DIE2,0,0}, // S_HEAD_DIE1 + {SPR_HEAD,7,8,{A_Scream},S_HEAD_DIE3,0,0}, // S_HEAD_DIE2 + {SPR_HEAD,8,8,{NULL},S_HEAD_DIE4,0,0}, // S_HEAD_DIE3 + {SPR_HEAD,9,8,{NULL},S_HEAD_DIE5,0,0}, // S_HEAD_DIE4 + {SPR_HEAD,10,8,{A_Fall},S_HEAD_DIE6,0,0}, // S_HEAD_DIE5 + {SPR_HEAD,11,-1,{NULL},S_NULL,0,0}, // S_HEAD_DIE6 + {SPR_HEAD,11,8,{NULL},S_HEAD_RAISE2,0,0}, // S_HEAD_RAISE1 + {SPR_HEAD,10,8,{NULL},S_HEAD_RAISE3,0,0}, // S_HEAD_RAISE2 + {SPR_HEAD,9,8,{NULL},S_HEAD_RAISE4,0,0}, // S_HEAD_RAISE3 + {SPR_HEAD,8,8,{NULL},S_HEAD_RAISE5,0,0}, // S_HEAD_RAISE4 + {SPR_HEAD,7,8,{NULL},S_HEAD_RAISE6,0,0}, // S_HEAD_RAISE5 + {SPR_HEAD,6,8,{NULL},S_HEAD_RUN1,0,0}, // S_HEAD_RAISE6 + {SPR_BAL7,32768,4,{NULL},S_BRBALL2,0,0}, // S_BRBALL1 + {SPR_BAL7,32769,4,{NULL},S_BRBALL1,0,0}, // S_BRBALL2 + {SPR_BAL7,32770,6,{NULL},S_BRBALLX2,0,0}, // S_BRBALLX1 + {SPR_BAL7,32771,6,{NULL},S_BRBALLX3,0,0}, // S_BRBALLX2 + {SPR_BAL7,32772,6,{NULL},S_NULL,0,0}, // S_BRBALLX3 + {SPR_BOSS,0,10,{A_Look},S_BOSS_STND2,0,0}, // S_BOSS_STND + {SPR_BOSS,1,10,{A_Look},S_BOSS_STND,0,0}, // S_BOSS_STND2 + {SPR_BOSS,0,3,{A_Chase},S_BOSS_RUN2,0,0}, // S_BOSS_RUN1 + {SPR_BOSS,0,3,{A_Chase},S_BOSS_RUN3,0,0}, // S_BOSS_RUN2 + {SPR_BOSS,1,3,{A_Chase},S_BOSS_RUN4,0,0}, // S_BOSS_RUN3 + {SPR_BOSS,1,3,{A_Chase},S_BOSS_RUN5,0,0}, // S_BOSS_RUN4 + {SPR_BOSS,2,3,{A_Chase},S_BOSS_RUN6,0,0}, // S_BOSS_RUN5 + {SPR_BOSS,2,3,{A_Chase},S_BOSS_RUN7,0,0}, // S_BOSS_RUN6 + {SPR_BOSS,3,3,{A_Chase},S_BOSS_RUN8,0,0}, // S_BOSS_RUN7 + {SPR_BOSS,3,3,{A_Chase},S_BOSS_RUN1,0,0}, // S_BOSS_RUN8 + {SPR_BOSS,4,8,{A_FaceTarget},S_BOSS_ATK2,0,0}, // S_BOSS_ATK1 + {SPR_BOSS,5,8,{A_FaceTarget},S_BOSS_ATK3,0,0}, // S_BOSS_ATK2 + {SPR_BOSS,6,8,{A_BruisAttack},S_BOSS_RUN1,0,0}, // S_BOSS_ATK3 + {SPR_BOSS,7,2,{NULL},S_BOSS_PAIN2,0,0}, // S_BOSS_PAIN + {SPR_BOSS,7,2,{A_Pain},S_BOSS_RUN1,0,0}, // S_BOSS_PAIN2 + {SPR_BOSS,8,8,{NULL},S_BOSS_DIE2,0,0}, // S_BOSS_DIE1 + {SPR_BOSS,9,8,{A_Scream},S_BOSS_DIE3,0,0}, // S_BOSS_DIE2 + {SPR_BOSS,10,8,{NULL},S_BOSS_DIE4,0,0}, // S_BOSS_DIE3 + {SPR_BOSS,11,8,{A_Fall},S_BOSS_DIE5,0,0}, // S_BOSS_DIE4 + {SPR_BOSS,12,8,{NULL},S_BOSS_DIE6,0,0}, // S_BOSS_DIE5 + {SPR_BOSS,13,8,{NULL},S_BOSS_DIE7,0,0}, // S_BOSS_DIE6 + {SPR_BOSS,14,-1,{A_BossDeath},S_NULL,0,0}, // S_BOSS_DIE7 + {SPR_BOSS,14,8,{NULL},S_BOSS_RAISE2,0,0}, // S_BOSS_RAISE1 + {SPR_BOSS,13,8,{NULL},S_BOSS_RAISE3,0,0}, // S_BOSS_RAISE2 + {SPR_BOSS,12,8,{NULL},S_BOSS_RAISE4,0,0}, // S_BOSS_RAISE3 + {SPR_BOSS,11,8,{NULL},S_BOSS_RAISE5,0,0}, // S_BOSS_RAISE4 + {SPR_BOSS,10,8,{NULL},S_BOSS_RAISE6,0,0}, // S_BOSS_RAISE5 + {SPR_BOSS,9,8,{NULL},S_BOSS_RAISE7,0,0}, // S_BOSS_RAISE6 + {SPR_BOSS,8,8,{NULL},S_BOSS_RUN1,0,0}, // S_BOSS_RAISE7 + {SPR_BOS2,0,10,{A_Look},S_BOS2_STND2,0,0}, // S_BOS2_STND + {SPR_BOS2,1,10,{A_Look},S_BOS2_STND,0,0}, // S_BOS2_STND2 + {SPR_BOS2,0,3,{A_Chase},S_BOS2_RUN2,0,0}, // S_BOS2_RUN1 + {SPR_BOS2,0,3,{A_Chase},S_BOS2_RUN3,0,0}, // S_BOS2_RUN2 + {SPR_BOS2,1,3,{A_Chase},S_BOS2_RUN4,0,0}, // S_BOS2_RUN3 + {SPR_BOS2,1,3,{A_Chase},S_BOS2_RUN5,0,0}, // S_BOS2_RUN4 + {SPR_BOS2,2,3,{A_Chase},S_BOS2_RUN6,0,0}, // S_BOS2_RUN5 + {SPR_BOS2,2,3,{A_Chase},S_BOS2_RUN7,0,0}, // S_BOS2_RUN6 + {SPR_BOS2,3,3,{A_Chase},S_BOS2_RUN8,0,0}, // S_BOS2_RUN7 + {SPR_BOS2,3,3,{A_Chase},S_BOS2_RUN1,0,0}, // S_BOS2_RUN8 + {SPR_BOS2,4,8,{A_FaceTarget},S_BOS2_ATK2,0,0}, // S_BOS2_ATK1 + {SPR_BOS2,5,8,{A_FaceTarget},S_BOS2_ATK3,0,0}, // S_BOS2_ATK2 + {SPR_BOS2,6,8,{A_BruisAttack},S_BOS2_RUN1,0,0}, // S_BOS2_ATK3 + {SPR_BOS2,7,2,{NULL},S_BOS2_PAIN2,0,0}, // S_BOS2_PAIN + {SPR_BOS2,7,2,{A_Pain},S_BOS2_RUN1,0,0}, // S_BOS2_PAIN2 + {SPR_BOS2,8,8,{NULL},S_BOS2_DIE2,0,0}, // S_BOS2_DIE1 + {SPR_BOS2,9,8,{A_Scream},S_BOS2_DIE3,0,0}, // S_BOS2_DIE2 + {SPR_BOS2,10,8,{NULL},S_BOS2_DIE4,0,0}, // S_BOS2_DIE3 + {SPR_BOS2,11,8,{A_Fall},S_BOS2_DIE5,0,0}, // S_BOS2_DIE4 + {SPR_BOS2,12,8,{NULL},S_BOS2_DIE6,0,0}, // S_BOS2_DIE5 + {SPR_BOS2,13,8,{NULL},S_BOS2_DIE7,0,0}, // S_BOS2_DIE6 + {SPR_BOS2,14,-1,{NULL},S_NULL,0,0}, // S_BOS2_DIE7 + {SPR_BOS2,14,8,{NULL},S_BOS2_RAISE2,0,0}, // S_BOS2_RAISE1 + {SPR_BOS2,13,8,{NULL},S_BOS2_RAISE3,0,0}, // S_BOS2_RAISE2 + {SPR_BOS2,12,8,{NULL},S_BOS2_RAISE4,0,0}, // S_BOS2_RAISE3 + {SPR_BOS2,11,8,{NULL},S_BOS2_RAISE5,0,0}, // S_BOS2_RAISE4 + {SPR_BOS2,10,8,{NULL},S_BOS2_RAISE6,0,0}, // S_BOS2_RAISE5 + {SPR_BOS2,9,8,{NULL},S_BOS2_RAISE7,0,0}, // S_BOS2_RAISE6 + {SPR_BOS2,8,8,{NULL},S_BOS2_RUN1,0,0}, // S_BOS2_RAISE7 + {SPR_SKUL,32768,10,{A_Look},S_SKULL_STND2,0,0}, // S_SKULL_STND + {SPR_SKUL,32769,10,{A_Look},S_SKULL_STND,0,0}, // S_SKULL_STND2 + {SPR_SKUL,32768,6,{A_Chase},S_SKULL_RUN2,0,0}, // S_SKULL_RUN1 + {SPR_SKUL,32769,6,{A_Chase},S_SKULL_RUN1,0,0}, // S_SKULL_RUN2 + {SPR_SKUL,32770,10,{A_FaceTarget},S_SKULL_ATK2,0,0}, // S_SKULL_ATK1 + {SPR_SKUL,32771,4,{A_SkullAttack},S_SKULL_ATK3,0,0}, // S_SKULL_ATK2 + {SPR_SKUL,32770,4,{NULL},S_SKULL_ATK4,0,0}, // S_SKULL_ATK3 + {SPR_SKUL,32771,4,{NULL},S_SKULL_ATK3,0,0}, // S_SKULL_ATK4 + {SPR_SKUL,32772,3,{NULL},S_SKULL_PAIN2,0,0}, // S_SKULL_PAIN + {SPR_SKUL,32772,3,{A_Pain},S_SKULL_RUN1,0,0}, // S_SKULL_PAIN2 + {SPR_SKUL,32773,6,{NULL},S_SKULL_DIE2,0,0}, // S_SKULL_DIE1 + {SPR_SKUL,32774,6,{A_Scream},S_SKULL_DIE3,0,0}, // S_SKULL_DIE2 + {SPR_SKUL,32775,6,{NULL},S_SKULL_DIE4,0,0}, // S_SKULL_DIE3 + {SPR_SKUL,32776,6,{A_Fall},S_SKULL_DIE5,0,0}, // S_SKULL_DIE4 + {SPR_SKUL,9,6,{NULL},S_SKULL_DIE6,0,0}, // S_SKULL_DIE5 + {SPR_SKUL,10,6,{NULL},S_NULL,0,0}, // S_SKULL_DIE6 + {SPR_SPID,0,10,{A_Look},S_SPID_STND2,0,0}, // S_SPID_STND + {SPR_SPID,1,10,{A_Look},S_SPID_STND,0,0}, // S_SPID_STND2 + {SPR_SPID,0,3,{A_Metal},S_SPID_RUN2,0,0}, // S_SPID_RUN1 + {SPR_SPID,0,3,{A_Chase},S_SPID_RUN3,0,0}, // S_SPID_RUN2 + {SPR_SPID,1,3,{A_Chase},S_SPID_RUN4,0,0}, // S_SPID_RUN3 + {SPR_SPID,1,3,{A_Chase},S_SPID_RUN5,0,0}, // S_SPID_RUN4 + {SPR_SPID,2,3,{A_Metal},S_SPID_RUN6,0,0}, // S_SPID_RUN5 + {SPR_SPID,2,3,{A_Chase},S_SPID_RUN7,0,0}, // S_SPID_RUN6 + {SPR_SPID,3,3,{A_Chase},S_SPID_RUN8,0,0}, // S_SPID_RUN7 + {SPR_SPID,3,3,{A_Chase},S_SPID_RUN9,0,0}, // S_SPID_RUN8 + {SPR_SPID,4,3,{A_Metal},S_SPID_RUN10,0,0}, // S_SPID_RUN9 + {SPR_SPID,4,3,{A_Chase},S_SPID_RUN11,0,0}, // S_SPID_RUN10 + {SPR_SPID,5,3,{A_Chase},S_SPID_RUN12,0,0}, // S_SPID_RUN11 + {SPR_SPID,5,3,{A_Chase},S_SPID_RUN1,0,0}, // S_SPID_RUN12 + {SPR_SPID,32768,20,{A_FaceTarget},S_SPID_ATK2,0,0}, // S_SPID_ATK1 + {SPR_SPID,32774,4,{A_SPosAttack},S_SPID_ATK3,0,0}, // S_SPID_ATK2 + {SPR_SPID,32775,4,{A_SPosAttack},S_SPID_ATK4,0,0}, // S_SPID_ATK3 + {SPR_SPID,32775,1,{A_SpidRefire},S_SPID_ATK2,0,0}, // S_SPID_ATK4 + {SPR_SPID,8,3,{NULL},S_SPID_PAIN2,0,0}, // S_SPID_PAIN + {SPR_SPID,8,3,{A_Pain},S_SPID_RUN1,0,0}, // S_SPID_PAIN2 + {SPR_SPID,9,20,{A_Scream},S_SPID_DIE2,0,0}, // S_SPID_DIE1 + {SPR_SPID,10,10,{A_Fall},S_SPID_DIE3,0,0}, // S_SPID_DIE2 + {SPR_SPID,11,10,{NULL},S_SPID_DIE4,0,0}, // S_SPID_DIE3 + {SPR_SPID,12,10,{NULL},S_SPID_DIE5,0,0}, // S_SPID_DIE4 + {SPR_SPID,13,10,{NULL},S_SPID_DIE6,0,0}, // S_SPID_DIE5 + {SPR_SPID,14,10,{NULL},S_SPID_DIE7,0,0}, // S_SPID_DIE6 + {SPR_SPID,15,10,{NULL},S_SPID_DIE8,0,0}, // S_SPID_DIE7 + {SPR_SPID,16,10,{NULL},S_SPID_DIE9,0,0}, // S_SPID_DIE8 + {SPR_SPID,17,10,{NULL},S_SPID_DIE10,0,0}, // S_SPID_DIE9 + {SPR_SPID,18,30,{NULL},S_SPID_DIE11,0,0}, // S_SPID_DIE10 + {SPR_SPID,18,-1,{A_BossDeath},S_NULL,0,0}, // S_SPID_DIE11 + {SPR_BSPI,0,10,{A_Look},S_BSPI_STND2,0,0}, // S_BSPI_STND + {SPR_BSPI,1,10,{A_Look},S_BSPI_STND,0,0}, // S_BSPI_STND2 + {SPR_BSPI,0,20,{NULL},S_BSPI_RUN1,0,0}, // S_BSPI_SIGHT + {SPR_BSPI,0,3,{A_BabyMetal},S_BSPI_RUN2,0,0}, // S_BSPI_RUN1 + {SPR_BSPI,0,3,{A_Chase},S_BSPI_RUN3,0,0}, // S_BSPI_RUN2 + {SPR_BSPI,1,3,{A_Chase},S_BSPI_RUN4,0,0}, // S_BSPI_RUN3 + {SPR_BSPI,1,3,{A_Chase},S_BSPI_RUN5,0,0}, // S_BSPI_RUN4 + {SPR_BSPI,2,3,{A_Chase},S_BSPI_RUN6,0,0}, // S_BSPI_RUN5 + {SPR_BSPI,2,3,{A_Chase},S_BSPI_RUN7,0,0}, // S_BSPI_RUN6 + {SPR_BSPI,3,3,{A_BabyMetal},S_BSPI_RUN8,0,0}, // S_BSPI_RUN7 + {SPR_BSPI,3,3,{A_Chase},S_BSPI_RUN9,0,0}, // S_BSPI_RUN8 + {SPR_BSPI,4,3,{A_Chase},S_BSPI_RUN10,0,0}, // S_BSPI_RUN9 + {SPR_BSPI,4,3,{A_Chase},S_BSPI_RUN11,0,0}, // S_BSPI_RUN10 + {SPR_BSPI,5,3,{A_Chase},S_BSPI_RUN12,0,0}, // S_BSPI_RUN11 + {SPR_BSPI,5,3,{A_Chase},S_BSPI_RUN1,0,0}, // S_BSPI_RUN12 + {SPR_BSPI,32768,20,{A_FaceTarget},S_BSPI_ATK2,0,0}, // S_BSPI_ATK1 + {SPR_BSPI,32774,4,{A_BspiAttack},S_BSPI_ATK3,0,0}, // S_BSPI_ATK2 + {SPR_BSPI,32775,4,{NULL},S_BSPI_ATK4,0,0}, // S_BSPI_ATK3 + {SPR_BSPI,32775,1,{A_SpidRefire},S_BSPI_ATK2,0,0}, // S_BSPI_ATK4 + {SPR_BSPI,8,3,{NULL},S_BSPI_PAIN2,0,0}, // S_BSPI_PAIN + {SPR_BSPI,8,3,{A_Pain},S_BSPI_RUN1,0,0}, // S_BSPI_PAIN2 + {SPR_BSPI,9,20,{A_Scream},S_BSPI_DIE2,0,0}, // S_BSPI_DIE1 + {SPR_BSPI,10,7,{A_Fall},S_BSPI_DIE3,0,0}, // S_BSPI_DIE2 + {SPR_BSPI,11,7,{NULL},S_BSPI_DIE4,0,0}, // S_BSPI_DIE3 + {SPR_BSPI,12,7,{NULL},S_BSPI_DIE5,0,0}, // S_BSPI_DIE4 + {SPR_BSPI,13,7,{NULL},S_BSPI_DIE6,0,0}, // S_BSPI_DIE5 + {SPR_BSPI,14,7,{NULL},S_BSPI_DIE7,0,0}, // S_BSPI_DIE6 + {SPR_BSPI,15,-1,{A_BossDeath},S_NULL,0,0}, // S_BSPI_DIE7 + {SPR_BSPI,15,5,{NULL},S_BSPI_RAISE2,0,0}, // S_BSPI_RAISE1 + {SPR_BSPI,14,5,{NULL},S_BSPI_RAISE3,0,0}, // S_BSPI_RAISE2 + {SPR_BSPI,13,5,{NULL},S_BSPI_RAISE4,0,0}, // S_BSPI_RAISE3 + {SPR_BSPI,12,5,{NULL},S_BSPI_RAISE5,0,0}, // S_BSPI_RAISE4 + {SPR_BSPI,11,5,{NULL},S_BSPI_RAISE6,0,0}, // S_BSPI_RAISE5 + {SPR_BSPI,10,5,{NULL},S_BSPI_RAISE7,0,0}, // S_BSPI_RAISE6 + {SPR_BSPI,9,5,{NULL},S_BSPI_RUN1,0,0}, // S_BSPI_RAISE7 + {SPR_APLS,32768,5,{NULL},S_ARACH_PLAZ2,0,0}, // S_ARACH_PLAZ + {SPR_APLS,32769,5,{NULL},S_ARACH_PLAZ,0,0}, // S_ARACH_PLAZ2 + {SPR_APBX,32768,5,{NULL},S_ARACH_PLEX2,0,0}, // S_ARACH_PLEX + {SPR_APBX,32769,5,{NULL},S_ARACH_PLEX3,0,0}, // S_ARACH_PLEX2 + {SPR_APBX,32770,5,{NULL},S_ARACH_PLEX4,0,0}, // S_ARACH_PLEX3 + {SPR_APBX,32771,5,{NULL},S_ARACH_PLEX5,0,0}, // S_ARACH_PLEX4 + {SPR_APBX,32772,5,{NULL},S_NULL,0,0}, // S_ARACH_PLEX5 + {SPR_CYBR,0,10,{A_Look},S_CYBER_STND2,0,0}, // S_CYBER_STND + {SPR_CYBR,1,10,{A_Look},S_CYBER_STND,0,0}, // S_CYBER_STND2 + {SPR_CYBR,0,3,{A_Hoof},S_CYBER_RUN2,0,0}, // S_CYBER_RUN1 + {SPR_CYBR,0,3,{A_Chase},S_CYBER_RUN3,0,0}, // S_CYBER_RUN2 + {SPR_CYBR,1,3,{A_Chase},S_CYBER_RUN4,0,0}, // S_CYBER_RUN3 + {SPR_CYBR,1,3,{A_Chase},S_CYBER_RUN5,0,0}, // S_CYBER_RUN4 + {SPR_CYBR,2,3,{A_Chase},S_CYBER_RUN6,0,0}, // S_CYBER_RUN5 + {SPR_CYBR,2,3,{A_Chase},S_CYBER_RUN7,0,0}, // S_CYBER_RUN6 + {SPR_CYBR,3,3,{A_Metal},S_CYBER_RUN8,0,0}, // S_CYBER_RUN7 + {SPR_CYBR,3,3,{A_Chase},S_CYBER_RUN1,0,0}, // S_CYBER_RUN8 + {SPR_CYBR,4,6,{A_FaceTarget},S_CYBER_ATK2,0,0}, // S_CYBER_ATK1 + {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_ATK3,0,0}, // S_CYBER_ATK2 + {SPR_CYBR,4,12,{A_FaceTarget},S_CYBER_ATK4,0,0}, // S_CYBER_ATK3 + {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_ATK5,0,0}, // S_CYBER_ATK4 + {SPR_CYBR,4,12,{A_FaceTarget},S_CYBER_ATK6,0,0}, // S_CYBER_ATK5 + {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_RUN1,0,0}, // S_CYBER_ATK6 + {SPR_CYBR,6,10,{A_Pain},S_CYBER_RUN1,0,0}, // S_CYBER_PAIN + {SPR_CYBR,7,10,{NULL},S_CYBER_DIE2,0,0}, // S_CYBER_DIE1 + {SPR_CYBR,8,10,{A_Scream},S_CYBER_DIE3,0,0}, // S_CYBER_DIE2 + {SPR_CYBR,9,10,{NULL},S_CYBER_DIE4,0,0}, // S_CYBER_DIE3 + {SPR_CYBR,10,10,{NULL},S_CYBER_DIE5,0,0}, // S_CYBER_DIE4 + {SPR_CYBR,11,10,{NULL},S_CYBER_DIE6,0,0}, // S_CYBER_DIE5 + {SPR_CYBR,12,10,{A_Fall},S_CYBER_DIE7,0,0}, // S_CYBER_DIE6 + {SPR_CYBR,13,10,{NULL},S_CYBER_DIE8,0,0}, // S_CYBER_DIE7 + {SPR_CYBR,14,10,{NULL},S_CYBER_DIE9,0,0}, // S_CYBER_DIE8 + {SPR_CYBR,15,30,{NULL},S_CYBER_DIE10,0,0}, // S_CYBER_DIE9 + {SPR_CYBR,15,-1,{A_BossDeath},S_NULL,0,0}, // S_CYBER_DIE10 + {SPR_PAIN,0,10,{A_Look},S_PAIN_STND,0,0}, // S_PAIN_STND + {SPR_PAIN,0,3,{A_Chase},S_PAIN_RUN2,0,0}, // S_PAIN_RUN1 + {SPR_PAIN,0,3,{A_Chase},S_PAIN_RUN3,0,0}, // S_PAIN_RUN2 + {SPR_PAIN,1,3,{A_Chase},S_PAIN_RUN4,0,0}, // S_PAIN_RUN3 + {SPR_PAIN,1,3,{A_Chase},S_PAIN_RUN5,0,0}, // S_PAIN_RUN4 + {SPR_PAIN,2,3,{A_Chase},S_PAIN_RUN6,0,0}, // S_PAIN_RUN5 + {SPR_PAIN,2,3,{A_Chase},S_PAIN_RUN1,0,0}, // S_PAIN_RUN6 + {SPR_PAIN,3,5,{A_FaceTarget},S_PAIN_ATK2,0,0}, // S_PAIN_ATK1 + {SPR_PAIN,4,5,{A_FaceTarget},S_PAIN_ATK3,0,0}, // S_PAIN_ATK2 + {SPR_PAIN,32773,5,{A_FaceTarget},S_PAIN_ATK4,0,0}, // S_PAIN_ATK3 + {SPR_PAIN,32773,0,{A_PainAttack},S_PAIN_RUN1,0,0}, // S_PAIN_ATK4 + {SPR_PAIN,6,6,{NULL},S_PAIN_PAIN2,0,0}, // S_PAIN_PAIN + {SPR_PAIN,6,6,{A_Pain},S_PAIN_RUN1,0,0}, // S_PAIN_PAIN2 + {SPR_PAIN,32775,8,{NULL},S_PAIN_DIE2,0,0}, // S_PAIN_DIE1 + {SPR_PAIN,32776,8,{A_Scream},S_PAIN_DIE3,0,0}, // S_PAIN_DIE2 + {SPR_PAIN,32777,8,{NULL},S_PAIN_DIE4,0,0}, // S_PAIN_DIE3 + {SPR_PAIN,32778,8,{NULL},S_PAIN_DIE5,0,0}, // S_PAIN_DIE4 + {SPR_PAIN,32779,8,{A_PainDie},S_PAIN_DIE6,0,0}, // S_PAIN_DIE5 + {SPR_PAIN,32780,8,{NULL},S_NULL,0,0}, // S_PAIN_DIE6 + {SPR_PAIN,12,8,{NULL},S_PAIN_RAISE2,0,0}, // S_PAIN_RAISE1 + {SPR_PAIN,11,8,{NULL},S_PAIN_RAISE3,0,0}, // S_PAIN_RAISE2 + {SPR_PAIN,10,8,{NULL},S_PAIN_RAISE4,0,0}, // S_PAIN_RAISE3 + {SPR_PAIN,9,8,{NULL},S_PAIN_RAISE5,0,0}, // S_PAIN_RAISE4 + {SPR_PAIN,8,8,{NULL},S_PAIN_RAISE6,0,0}, // S_PAIN_RAISE5 + {SPR_PAIN,7,8,{NULL},S_PAIN_RUN1,0,0}, // S_PAIN_RAISE6 + {SPR_SSWV,0,10,{A_Look},S_SSWV_STND2,0,0}, // S_SSWV_STND + {SPR_SSWV,1,10,{A_Look},S_SSWV_STND,0,0}, // S_SSWV_STND2 + {SPR_SSWV,0,3,{A_Chase},S_SSWV_RUN2,0,0}, // S_SSWV_RUN1 + {SPR_SSWV,0,3,{A_Chase},S_SSWV_RUN3,0,0}, // S_SSWV_RUN2 + {SPR_SSWV,1,3,{A_Chase},S_SSWV_RUN4,0,0}, // S_SSWV_RUN3 + {SPR_SSWV,1,3,{A_Chase},S_SSWV_RUN5,0,0}, // S_SSWV_RUN4 + {SPR_SSWV,2,3,{A_Chase},S_SSWV_RUN6,0,0}, // S_SSWV_RUN5 + {SPR_SSWV,2,3,{A_Chase},S_SSWV_RUN7,0,0}, // S_SSWV_RUN6 + {SPR_SSWV,3,3,{A_Chase},S_SSWV_RUN8,0,0}, // S_SSWV_RUN7 + {SPR_SSWV,3,3,{A_Chase},S_SSWV_RUN1,0,0}, // S_SSWV_RUN8 + {SPR_SSWV,4,10,{A_FaceTarget},S_SSWV_ATK2,0,0}, // S_SSWV_ATK1 + {SPR_SSWV,5,10,{A_FaceTarget},S_SSWV_ATK3,0,0}, // S_SSWV_ATK2 + {SPR_SSWV,32774,4,{A_CPosAttack},S_SSWV_ATK4,0,0}, // S_SSWV_ATK3 + {SPR_SSWV,5,6,{A_FaceTarget},S_SSWV_ATK5,0,0}, // S_SSWV_ATK4 + {SPR_SSWV,32774,4,{A_CPosAttack},S_SSWV_ATK6,0,0}, // S_SSWV_ATK5 + {SPR_SSWV,5,1,{A_CPosRefire},S_SSWV_ATK2,0,0}, // S_SSWV_ATK6 + {SPR_SSWV,7,3,{NULL},S_SSWV_PAIN2,0,0}, // S_SSWV_PAIN + {SPR_SSWV,7,3,{A_Pain},S_SSWV_RUN1,0,0}, // S_SSWV_PAIN2 + {SPR_SSWV,8,5,{NULL},S_SSWV_DIE2,0,0}, // S_SSWV_DIE1 + {SPR_SSWV,9,5,{A_Scream},S_SSWV_DIE3,0,0}, // S_SSWV_DIE2 + {SPR_SSWV,10,5,{A_Fall},S_SSWV_DIE4,0,0}, // S_SSWV_DIE3 + {SPR_SSWV,11,5,{NULL},S_SSWV_DIE5,0,0}, // S_SSWV_DIE4 + {SPR_SSWV,12,-1,{NULL},S_NULL,0,0}, // S_SSWV_DIE5 + {SPR_SSWV,13,5,{NULL},S_SSWV_XDIE2,0,0}, // S_SSWV_XDIE1 + {SPR_SSWV,14,5,{A_XScream},S_SSWV_XDIE3,0,0}, // S_SSWV_XDIE2 + {SPR_SSWV,15,5,{A_Fall},S_SSWV_XDIE4,0,0}, // S_SSWV_XDIE3 + {SPR_SSWV,16,5,{NULL},S_SSWV_XDIE5,0,0}, // S_SSWV_XDIE4 + {SPR_SSWV,17,5,{NULL},S_SSWV_XDIE6,0,0}, // S_SSWV_XDIE5 + {SPR_SSWV,18,5,{NULL},S_SSWV_XDIE7,0,0}, // S_SSWV_XDIE6 + {SPR_SSWV,19,5,{NULL},S_SSWV_XDIE8,0,0}, // S_SSWV_XDIE7 + {SPR_SSWV,20,5,{NULL},S_SSWV_XDIE9,0,0}, // S_SSWV_XDIE8 + {SPR_SSWV,21,-1,{NULL},S_NULL,0,0}, // S_SSWV_XDIE9 + {SPR_SSWV,12,5,{NULL},S_SSWV_RAISE2,0,0}, // S_SSWV_RAISE1 + {SPR_SSWV,11,5,{NULL},S_SSWV_RAISE3,0,0}, // S_SSWV_RAISE2 + {SPR_SSWV,10,5,{NULL},S_SSWV_RAISE4,0,0}, // S_SSWV_RAISE3 + {SPR_SSWV,9,5,{NULL},S_SSWV_RAISE5,0,0}, // S_SSWV_RAISE4 + {SPR_SSWV,8,5,{NULL},S_SSWV_RUN1,0,0}, // S_SSWV_RAISE5 + {SPR_KEEN,0,-1,{NULL},S_KEENSTND,0,0}, // S_KEENSTND + {SPR_KEEN,0,6,{NULL},S_COMMKEEN2,0,0}, // S_COMMKEEN + {SPR_KEEN,1,6,{NULL},S_COMMKEEN3,0,0}, // S_COMMKEEN2 + {SPR_KEEN,2,6,{A_Scream},S_COMMKEEN4,0,0}, // S_COMMKEEN3 + {SPR_KEEN,3,6,{NULL},S_COMMKEEN5,0,0}, // S_COMMKEEN4 + {SPR_KEEN,4,6,{NULL},S_COMMKEEN6,0,0}, // S_COMMKEEN5 + {SPR_KEEN,5,6,{NULL},S_COMMKEEN7,0,0}, // S_COMMKEEN6 + {SPR_KEEN,6,6,{NULL},S_COMMKEEN8,0,0}, // S_COMMKEEN7 + {SPR_KEEN,7,6,{NULL},S_COMMKEEN9,0,0}, // S_COMMKEEN8 + {SPR_KEEN,8,6,{NULL},S_COMMKEEN10,0,0}, // S_COMMKEEN9 + {SPR_KEEN,9,6,{NULL},S_COMMKEEN11,0,0}, // S_COMMKEEN10 + {SPR_KEEN,10,6,{A_KeenDie},S_COMMKEEN12,0,0},// S_COMMKEEN11 + {SPR_KEEN,11,-1,{NULL},S_NULL,0,0}, // S_COMMKEEN12 + {SPR_KEEN,12,4,{NULL},S_KEENPAIN2,0,0}, // S_KEENPAIN + {SPR_KEEN,12,8,{A_Pain},S_KEENSTND,0,0}, // S_KEENPAIN2 + {SPR_BBRN,0,-1,{NULL},S_NULL,0,0}, // S_BRAIN + {SPR_BBRN,1,36,{A_BrainPain},S_BRAIN,0,0}, // S_BRAIN_PAIN + {SPR_BBRN,0,100,{A_BrainScream},S_BRAIN_DIE2,0,0}, // S_BRAIN_DIE1 + {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE3,0,0}, // S_BRAIN_DIE2 + {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE4,0,0}, // S_BRAIN_DIE3 + {SPR_BBRN,0,-1,{A_BrainDie},S_NULL,0,0}, // S_BRAIN_DIE4 + {SPR_SSWV,0,10,{A_Look},S_BRAINEYE,0,0}, // S_BRAINEYE + {SPR_SSWV,0,181,{A_BrainAwake},S_BRAINEYE1,0,0}, // S_BRAINEYESEE + {SPR_SSWV,0,150,{A_BrainSpit},S_BRAINEYE1,0,0}, // S_BRAINEYE1 + {SPR_BOSF,32768,3,{A_SpawnSound},S_SPAWN2,0,0}, // S_SPAWN1 + {SPR_BOSF,32769,3,{A_SpawnFly},S_SPAWN3,0,0}, // S_SPAWN2 + {SPR_BOSF,32770,3,{A_SpawnFly},S_SPAWN4,0,0}, // S_SPAWN3 + {SPR_BOSF,32771,3,{A_SpawnFly},S_SPAWN1,0,0}, // S_SPAWN4 + {SPR_FIRE,32768,4,{A_Fire},S_SPAWNFIRE2,0,0}, // S_SPAWNFIRE1 + {SPR_FIRE,32769,4,{A_Fire},S_SPAWNFIRE3,0,0}, // S_SPAWNFIRE2 + {SPR_FIRE,32770,4,{A_Fire},S_SPAWNFIRE4,0,0}, // S_SPAWNFIRE3 + {SPR_FIRE,32771,4,{A_Fire},S_SPAWNFIRE5,0,0}, // S_SPAWNFIRE4 + {SPR_FIRE,32772,4,{A_Fire},S_SPAWNFIRE6,0,0}, // S_SPAWNFIRE5 + {SPR_FIRE,32773,4,{A_Fire},S_SPAWNFIRE7,0,0}, // S_SPAWNFIRE6 + {SPR_FIRE,32774,4,{A_Fire},S_SPAWNFIRE8,0,0}, // S_SPAWNFIRE7 + {SPR_FIRE,32775,4,{A_Fire},S_NULL,0,0}, // S_SPAWNFIRE8 + {SPR_MISL,32769,10,{NULL},S_BRAINEXPLODE2,0,0}, // S_BRAINEXPLODE1 + {SPR_MISL,32770,10,{NULL},S_BRAINEXPLODE3,0,0}, // S_BRAINEXPLODE2 + {SPR_MISL,32771,10,{A_BrainExplode},S_NULL,0,0}, // S_BRAINEXPLODE3 + {SPR_ARM1,0,6,{NULL},S_ARM1A,0,0}, // S_ARM1 + {SPR_ARM1,32769,7,{NULL},S_ARM1,0,0}, // S_ARM1A + {SPR_ARM2,0,6,{NULL},S_ARM2A,0,0}, // S_ARM2 + {SPR_ARM2,32769,6,{NULL},S_ARM2,0,0}, // S_ARM2A + {SPR_BAR1,0,6,{NULL},S_BAR2,0,0}, // S_BAR1 + {SPR_BAR1,1,6,{NULL},S_BAR1,0,0}, // S_BAR2 + {SPR_BEXP,32768,5,{NULL},S_BEXP2,0,0}, // S_BEXP + {SPR_BEXP,32769,5,{A_Scream},S_BEXP3,0,0}, // S_BEXP2 + {SPR_BEXP,32770,5,{NULL},S_BEXP4,0,0}, // S_BEXP3 + {SPR_BEXP,32771,10,{A_Explode},S_BEXP5,0,0}, // S_BEXP4 + {SPR_BEXP,32772,10,{NULL},S_NULL,0,0}, // S_BEXP5 + {SPR_FCAN,32768,4,{NULL},S_BBAR2,0,0}, // S_BBAR1 + {SPR_FCAN,32769,4,{NULL},S_BBAR3,0,0}, // S_BBAR2 + {SPR_FCAN,32770,4,{NULL},S_BBAR1,0,0}, // S_BBAR3 + {SPR_BON1,0,6,{NULL},S_BON1A,0,0}, // S_BON1 + {SPR_BON1,1,6,{NULL},S_BON1B,0,0}, // S_BON1A + {SPR_BON1,2,6,{NULL},S_BON1C,0,0}, // S_BON1B + {SPR_BON1,3,6,{NULL},S_BON1D,0,0}, // S_BON1C + {SPR_BON1,2,6,{NULL},S_BON1E,0,0}, // S_BON1D + {SPR_BON1,1,6,{NULL},S_BON1,0,0}, // S_BON1E + {SPR_BON2,0,6,{NULL},S_BON2A,0,0}, // S_BON2 + {SPR_BON2,1,6,{NULL},S_BON2B,0,0}, // S_BON2A + {SPR_BON2,2,6,{NULL},S_BON2C,0,0}, // S_BON2B + {SPR_BON2,3,6,{NULL},S_BON2D,0,0}, // S_BON2C + {SPR_BON2,2,6,{NULL},S_BON2E,0,0}, // S_BON2D + {SPR_BON2,1,6,{NULL},S_BON2,0,0}, // S_BON2E + {SPR_BKEY,0,10,{NULL},S_BKEY2,0,0}, // S_BKEY + {SPR_BKEY,32769,10,{NULL},S_BKEY,0,0}, // S_BKEY2 + {SPR_RKEY,0,10,{NULL},S_RKEY2,0,0}, // S_RKEY + {SPR_RKEY,32769,10,{NULL},S_RKEY,0,0}, // S_RKEY2 + {SPR_YKEY,0,10,{NULL},S_YKEY2,0,0}, // S_YKEY + {SPR_YKEY,32769,10,{NULL},S_YKEY,0,0}, // S_YKEY2 + {SPR_BSKU,0,10,{NULL},S_BSKULL2,0,0}, // S_BSKULL + {SPR_BSKU,32769,10,{NULL},S_BSKULL,0,0}, // S_BSKULL2 + {SPR_RSKU,0,10,{NULL},S_RSKULL2,0,0}, // S_RSKULL + {SPR_RSKU,32769,10,{NULL},S_RSKULL,0,0}, // S_RSKULL2 + {SPR_YSKU,0,10,{NULL},S_YSKULL2,0,0}, // S_YSKULL + {SPR_YSKU,32769,10,{NULL},S_YSKULL,0,0}, // S_YSKULL2 + {SPR_STIM,0,-1,{NULL},S_NULL,0,0}, // S_STIM + {SPR_MEDI,0,-1,{NULL},S_NULL,0,0}, // S_MEDI + {SPR_SOUL,32768,6,{NULL},S_SOUL2,0,0}, // S_SOUL + {SPR_SOUL,32769,6,{NULL},S_SOUL3,0,0}, // S_SOUL2 + {SPR_SOUL,32770,6,{NULL},S_SOUL4,0,0}, // S_SOUL3 + {SPR_SOUL,32771,6,{NULL},S_SOUL5,0,0}, // S_SOUL4 + {SPR_SOUL,32770,6,{NULL},S_SOUL6,0,0}, // S_SOUL5 + {SPR_SOUL,32769,6,{NULL},S_SOUL,0,0}, // S_SOUL6 + {SPR_PINV,32768,6,{NULL},S_PINV2,0,0}, // S_PINV + {SPR_PINV,32769,6,{NULL},S_PINV3,0,0}, // S_PINV2 + {SPR_PINV,32770,6,{NULL},S_PINV4,0,0}, // S_PINV3 + {SPR_PINV,32771,6,{NULL},S_PINV,0,0}, // S_PINV4 + {SPR_PSTR,32768,-1,{NULL},S_NULL,0,0}, // S_PSTR + {SPR_PINS,32768,6,{NULL},S_PINS2,0,0}, // S_PINS + {SPR_PINS,32769,6,{NULL},S_PINS3,0,0}, // S_PINS2 + {SPR_PINS,32770,6,{NULL},S_PINS4,0,0}, // S_PINS3 + {SPR_PINS,32771,6,{NULL},S_PINS,0,0}, // S_PINS4 + {SPR_MEGA,32768,6,{NULL},S_MEGA2,0,0}, // S_MEGA + {SPR_MEGA,32769,6,{NULL},S_MEGA3,0,0}, // S_MEGA2 + {SPR_MEGA,32770,6,{NULL},S_MEGA4,0,0}, // S_MEGA3 + {SPR_MEGA,32771,6,{NULL},S_MEGA,0,0}, // S_MEGA4 + {SPR_SUIT,32768,-1,{NULL},S_NULL,0,0}, // S_SUIT + {SPR_PMAP,32768,6,{NULL},S_PMAP2,0,0}, // S_PMAP + {SPR_PMAP,32769,6,{NULL},S_PMAP3,0,0}, // S_PMAP2 + {SPR_PMAP,32770,6,{NULL},S_PMAP4,0,0}, // S_PMAP3 + {SPR_PMAP,32771,6,{NULL},S_PMAP5,0,0}, // S_PMAP4 + {SPR_PMAP,32770,6,{NULL},S_PMAP6,0,0}, // S_PMAP5 + {SPR_PMAP,32769,6,{NULL},S_PMAP,0,0}, // S_PMAP6 + {SPR_PVIS,32768,6,{NULL},S_PVIS2,0,0}, // S_PVIS + {SPR_PVIS,1,6,{NULL},S_PVIS,0,0}, // S_PVIS2 + {SPR_CLIP,0,-1,{NULL},S_NULL,0,0}, // S_CLIP + {SPR_AMMO,0,-1,{NULL},S_NULL,0,0}, // S_AMMO + {SPR_ROCK,0,-1,{NULL},S_NULL,0,0}, // S_ROCK + {SPR_BROK,0,-1,{NULL},S_NULL,0,0}, // S_BROK + {SPR_CELL,0,-1,{NULL},S_NULL,0,0}, // S_CELL + {SPR_CELP,0,-1,{NULL},S_NULL,0,0}, // S_CELP + {SPR_SHEL,0,-1,{NULL},S_NULL,0,0}, // S_SHEL + {SPR_SBOX,0,-1,{NULL},S_NULL,0,0}, // S_SBOX + {SPR_BPAK,0,-1,{NULL},S_NULL,0,0}, // S_BPAK + {SPR_BFUG,0,-1,{NULL},S_NULL,0,0}, // S_BFUG + {SPR_MGUN,0,-1,{NULL},S_NULL,0,0}, // S_MGUN + {SPR_CSAW,0,-1,{NULL},S_NULL,0,0}, // S_CSAW + {SPR_LAUN,0,-1,{NULL},S_NULL,0,0}, // S_LAUN + {SPR_PLAS,0,-1,{NULL},S_NULL,0,0}, // S_PLAS + {SPR_SHOT,0,-1,{NULL},S_NULL,0,0}, // S_SHOT + {SPR_SGN2,0,-1,{NULL},S_NULL,0,0}, // S_SHOT2 + {SPR_COLU,32768,-1,{NULL},S_NULL,0,0}, // S_COLU + {SPR_SMT2,0,-1,{NULL},S_NULL,0,0}, // S_STALAG + {SPR_GOR1,0,10,{NULL},S_BLOODYTWITCH2,0,0}, // S_BLOODYTWITCH + {SPR_GOR1,1,15,{NULL},S_BLOODYTWITCH3,0,0}, // S_BLOODYTWITCH2 + {SPR_GOR1,2,8,{NULL},S_BLOODYTWITCH4,0,0}, // S_BLOODYTWITCH3 + {SPR_GOR1,1,6,{NULL},S_BLOODYTWITCH,0,0}, // S_BLOODYTWITCH4 + {SPR_PLAY,13,-1,{NULL},S_NULL,0,0}, // S_DEADTORSO + {SPR_PLAY,18,-1,{NULL},S_NULL,0,0}, // S_DEADBOTTOM + {SPR_POL2,0,-1,{NULL},S_NULL,0,0}, // S_HEADSONSTICK + {SPR_POL5,0,-1,{NULL},S_NULL,0,0}, // S_GIBS + {SPR_POL4,0,-1,{NULL},S_NULL,0,0}, // S_HEADONASTICK + {SPR_POL3,32768,6,{NULL},S_HEADCANDLES2,0,0}, // S_HEADCANDLES + {SPR_POL3,32769,6,{NULL},S_HEADCANDLES,0,0}, // S_HEADCANDLES2 + {SPR_POL1,0,-1,{NULL},S_NULL,0,0}, // S_DEADSTICK + {SPR_POL6,0,6,{NULL},S_LIVESTICK2,0,0}, // S_LIVESTICK + {SPR_POL6,1,8,{NULL},S_LIVESTICK,0,0}, // S_LIVESTICK2 + {SPR_GOR2,0,-1,{NULL},S_NULL,0,0}, // S_MEAT2 + {SPR_GOR3,0,-1,{NULL},S_NULL,0,0}, // S_MEAT3 + {SPR_GOR4,0,-1,{NULL},S_NULL,0,0}, // S_MEAT4 + {SPR_GOR5,0,-1,{NULL},S_NULL,0,0}, // S_MEAT5 + {SPR_SMIT,0,-1,{NULL},S_NULL,0,0}, // S_STALAGTITE + {SPR_COL1,0,-1,{NULL},S_NULL,0,0}, // S_TALLGRNCOL + {SPR_COL2,0,-1,{NULL},S_NULL,0,0}, // S_SHRTGRNCOL + {SPR_COL3,0,-1,{NULL},S_NULL,0,0}, // S_TALLREDCOL + {SPR_COL4,0,-1,{NULL},S_NULL,0,0}, // S_SHRTREDCOL + {SPR_CAND,32768,-1,{NULL},S_NULL,0,0}, // S_CANDLESTIK + {SPR_CBRA,32768,-1,{NULL},S_NULL,0,0}, // S_CANDELABRA + {SPR_COL6,0,-1,{NULL},S_NULL,0,0}, // S_SKULLCOL + {SPR_TRE1,0,-1,{NULL},S_NULL,0,0}, // S_TORCHTREE + {SPR_TRE2,0,-1,{NULL},S_NULL,0,0}, // S_BIGTREE + {SPR_ELEC,0,-1,{NULL},S_NULL,0,0}, // S_TECHPILLAR + {SPR_CEYE,32768,6,{NULL},S_EVILEYE2,0,0}, // S_EVILEYE + {SPR_CEYE,32769,6,{NULL},S_EVILEYE3,0,0}, // S_EVILEYE2 + {SPR_CEYE,32770,6,{NULL},S_EVILEYE4,0,0}, // S_EVILEYE3 + {SPR_CEYE,32769,6,{NULL},S_EVILEYE,0,0}, // S_EVILEYE4 + {SPR_FSKU,32768,6,{NULL},S_FLOATSKULL2,0,0}, // S_FLOATSKULL + {SPR_FSKU,32769,6,{NULL},S_FLOATSKULL3,0,0}, // S_FLOATSKULL2 + {SPR_FSKU,32770,6,{NULL},S_FLOATSKULL,0,0}, // S_FLOATSKULL3 + {SPR_COL5,0,14,{NULL},S_HEARTCOL2,0,0}, // S_HEARTCOL + {SPR_COL5,1,14,{NULL},S_HEARTCOL,0,0}, // S_HEARTCOL2 + {SPR_TBLU,32768,4,{NULL},S_BLUETORCH2,0,0}, // S_BLUETORCH + {SPR_TBLU,32769,4,{NULL},S_BLUETORCH3,0,0}, // S_BLUETORCH2 + {SPR_TBLU,32770,4,{NULL},S_BLUETORCH4,0,0}, // S_BLUETORCH3 + {SPR_TBLU,32771,4,{NULL},S_BLUETORCH,0,0}, // S_BLUETORCH4 + {SPR_TGRN,32768,4,{NULL},S_GREENTORCH2,0,0}, // S_GREENTORCH + {SPR_TGRN,32769,4,{NULL},S_GREENTORCH3,0,0}, // S_GREENTORCH2 + {SPR_TGRN,32770,4,{NULL},S_GREENTORCH4,0,0}, // S_GREENTORCH3 + {SPR_TGRN,32771,4,{NULL},S_GREENTORCH,0,0}, // S_GREENTORCH4 + {SPR_TRED,32768,4,{NULL},S_REDTORCH2,0,0}, // S_REDTORCH + {SPR_TRED,32769,4,{NULL},S_REDTORCH3,0,0}, // S_REDTORCH2 + {SPR_TRED,32770,4,{NULL},S_REDTORCH4,0,0}, // S_REDTORCH3 + {SPR_TRED,32771,4,{NULL},S_REDTORCH,0,0}, // S_REDTORCH4 + {SPR_SMBT,32768,4,{NULL},S_BTORCHSHRT2,0,0}, // S_BTORCHSHRT + {SPR_SMBT,32769,4,{NULL},S_BTORCHSHRT3,0,0}, // S_BTORCHSHRT2 + {SPR_SMBT,32770,4,{NULL},S_BTORCHSHRT4,0,0}, // S_BTORCHSHRT3 + {SPR_SMBT,32771,4,{NULL},S_BTORCHSHRT,0,0}, // S_BTORCHSHRT4 + {SPR_SMGT,32768,4,{NULL},S_GTORCHSHRT2,0,0}, // S_GTORCHSHRT + {SPR_SMGT,32769,4,{NULL},S_GTORCHSHRT3,0,0}, // S_GTORCHSHRT2 + {SPR_SMGT,32770,4,{NULL},S_GTORCHSHRT4,0,0}, // S_GTORCHSHRT3 + {SPR_SMGT,32771,4,{NULL},S_GTORCHSHRT,0,0}, // S_GTORCHSHRT4 + {SPR_SMRT,32768,4,{NULL},S_RTORCHSHRT2,0,0}, // S_RTORCHSHRT + {SPR_SMRT,32769,4,{NULL},S_RTORCHSHRT3,0,0}, // S_RTORCHSHRT2 + {SPR_SMRT,32770,4,{NULL},S_RTORCHSHRT4,0,0}, // S_RTORCHSHRT3 + {SPR_SMRT,32771,4,{NULL},S_RTORCHSHRT,0,0}, // S_RTORCHSHRT4 + {SPR_HDB1,0,-1,{NULL},S_NULL,0,0}, // S_HANGNOGUTS + {SPR_HDB2,0,-1,{NULL},S_NULL,0,0}, // S_HANGBNOBRAIN + {SPR_HDB3,0,-1,{NULL},S_NULL,0,0}, // S_HANGTLOOKDN + {SPR_HDB4,0,-1,{NULL},S_NULL,0,0}, // S_HANGTSKULL + {SPR_HDB5,0,-1,{NULL},S_NULL,0,0}, // S_HANGTLOOKUP + {SPR_HDB6,0,-1,{NULL},S_NULL,0,0}, // S_HANGTNOBRAIN + {SPR_POB1,0,-1,{NULL},S_NULL,0,0}, // S_COLONGIBS + {SPR_POB2,0,-1,{NULL},S_NULL,0,0}, // S_SMALLPOOL + {SPR_BRS1,0,-1,{NULL},S_NULL,0,0}, // S_BRAINSTEM + {SPR_TLMP,32768,4,{NULL},S_TECHLAMP2,0,0}, // S_TECHLAMP + {SPR_TLMP,32769,4,{NULL},S_TECHLAMP3,0,0}, // S_TECHLAMP2 + {SPR_TLMP,32770,4,{NULL},S_TECHLAMP4,0,0}, // S_TECHLAMP3 + {SPR_TLMP,32771,4,{NULL},S_TECHLAMP,0,0}, // S_TECHLAMP4 + {SPR_TLP2,32768,4,{NULL},S_TECH2LAMP2,0,0}, // S_TECH2LAMP + {SPR_TLP2,32769,4,{NULL},S_TECH2LAMP3,0,0}, // S_TECH2LAMP2 + {SPR_TLP2,32770,4,{NULL},S_TECH2LAMP4,0,0}, // S_TECH2LAMP3 + {SPR_TLP2,32771,4,{NULL},S_TECH2LAMP,0,0} // S_TECH2LAMP4 +}; + + +mobjinfo_t mobjinfo[NUMMOBJTYPES] = { + + { // MT_PLAYER + -1, // doomednum + S_PLAY, // spawnstate + 100, // spawnhealth + S_PLAY_RUN1, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_PLAY_PAIN, // painstate + 255, // painchance + sfx_plpain, // painsound + S_NULL, // meleestate + S_PLAY_ATK1, // missilestate + S_PLAY_DIE1, // deathstate + S_PLAY_XDIE1, // xdeathstate + sfx_pldeth, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 56*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_POSSESSED + 3004, // doomednum + S_POSS_STND, // spawnstate + 20, // spawnhealth + S_POSS_RUN1, // seestate + sfx_posit1, // seesound + 8, // reactiontime + sfx_pistol, // attacksound + S_POSS_PAIN, // painstate + 200, // painchance + sfx_popain, // painsound + 0, // meleestate + S_POSS_ATK1, // missilestate + S_POSS_DIE1, // deathstate + S_POSS_XDIE1, // xdeathstate + sfx_podth1, // deathsound + 8, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_posact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_POSS_RAISE1 // raisestate + }, + + { // MT_SHOTGUY + 9, // doomednum + S_SPOS_STND, // spawnstate + 30, // spawnhealth + S_SPOS_RUN1, // seestate + sfx_posit2, // seesound + 8, // reactiontime + 0, // attacksound + S_SPOS_PAIN, // painstate + 170, // painchance + sfx_popain, // painsound + 0, // meleestate + S_SPOS_ATK1, // missilestate + S_SPOS_DIE1, // deathstate + S_SPOS_XDIE1, // xdeathstate + sfx_podth2, // deathsound + 8, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_posact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_SPOS_RAISE1 // raisestate + }, + + { // MT_VILE + 64, // doomednum + S_VILE_STND, // spawnstate + 700, // spawnhealth + S_VILE_RUN1, // seestate + sfx_vilsit, // seesound + 8, // reactiontime + 0, // attacksound + S_VILE_PAIN, // painstate + 10, // painchance + sfx_vipain, // painsound + 0, // meleestate + S_VILE_ATK1, // missilestate + S_VILE_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_vildth, // deathsound + 15, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 500, // mass + 0, // damage + sfx_vilact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_NULL // raisestate + }, + + { // MT_FIRE + -1, // doomednum + S_FIRE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_UNDEAD + 66, // doomednum + S_SKEL_STND, // spawnstate + 300, // spawnhealth + S_SKEL_RUN1, // seestate + sfx_skesit, // seesound + 8, // reactiontime + 0, // attacksound + S_SKEL_PAIN, // painstate + 100, // painchance + sfx_popain, // painsound + S_SKEL_FIST1, // meleestate + S_SKEL_MISS1, // missilestate + S_SKEL_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_skedth, // deathsound + 10, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 500, // mass + 0, // damage + sfx_skeact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_SKEL_RAISE1 // raisestate + }, + + { // MT_TRACER + -1, // doomednum + S_TRACER, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_skeatk, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_TRACEEXP1, // deathstate + S_NULL, // xdeathstate + sfx_barexp, // deathsound + 10*FRACUNIT, // speed + 11*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 10, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_SMOKE + -1, // doomednum + S_SMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_FATSO + 67, // doomednum + S_FATT_STND, // spawnstate + 600, // spawnhealth + S_FATT_RUN1, // seestate + sfx_mansit, // seesound + 8, // reactiontime + 0, // attacksound + S_FATT_PAIN, // painstate + 80, // painchance + sfx_mnpain, // painsound + 0, // meleestate + S_FATT_ATK1, // missilestate + S_FATT_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_mandth, // deathsound + 8, // speed + 48*FRACUNIT, // radius + 64*FRACUNIT, // height + 1000, // mass + 0, // damage + sfx_posact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_FATT_RAISE1 // raisestate + }, + + { // MT_FATSHOT + -1, // doomednum + S_FATSHOT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_firsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_FATSHOTX1, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 20*FRACUNIT, // speed + 6*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 8, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_CHAINGUY + 65, // doomednum + S_CPOS_STND, // spawnstate + 70, // spawnhealth + S_CPOS_RUN1, // seestate + sfx_posit2, // seesound + 8, // reactiontime + 0, // attacksound + S_CPOS_PAIN, // painstate + 170, // painchance + sfx_popain, // painsound + 0, // meleestate + S_CPOS_ATK1, // missilestate + S_CPOS_DIE1, // deathstate + S_CPOS_XDIE1, // xdeathstate + sfx_podth2, // deathsound + 8, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_posact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_CPOS_RAISE1 // raisestate + }, + + { // MT_TROOP + 3001, // doomednum + S_TROO_STND, // spawnstate + 60, // spawnhealth + S_TROO_RUN1, // seestate + sfx_bgsit1, // seesound + 8, // reactiontime + 0, // attacksound + S_TROO_PAIN, // painstate + 200, // painchance + sfx_popain, // painsound + S_TROO_ATK1, // meleestate + S_TROO_ATK1, // missilestate + S_TROO_DIE1, // deathstate + S_TROO_XDIE1, // xdeathstate + sfx_bgdth1, // deathsound + 8, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_bgact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_TROO_RAISE1 // raisestate + }, + + { // MT_SERGEANT + 3002, // doomednum + S_SARG_STND, // spawnstate + 150, // spawnhealth + S_SARG_RUN1, // seestate + sfx_sgtsit, // seesound + 8, // reactiontime + sfx_sgtatk, // attacksound + S_SARG_PAIN, // painstate + 180, // painchance + sfx_dmpain, // painsound + S_SARG_ATK1, // meleestate + 0, // missilestate + S_SARG_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_sgtdth, // deathsound + 10, // speed + 30*FRACUNIT, // radius + 56*FRACUNIT, // height + 400, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_SARG_RAISE1 // raisestate + }, + + { // MT_SHADOWS + 58, // doomednum + S_SARG_STND, // spawnstate + 150, // spawnhealth + S_SARG_RUN1, // seestate + sfx_sgtsit, // seesound + 8, // reactiontime + sfx_sgtatk, // attacksound + S_SARG_PAIN, // painstate + 180, // painchance + sfx_dmpain, // painsound + S_SARG_ATK1, // meleestate + 0, // missilestate + S_SARG_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_sgtdth, // deathsound + 10, // speed + 30*FRACUNIT, // radius + 56*FRACUNIT, // height + 400, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_SHADOW|MF_COUNTKILL, // flags + S_SARG_RAISE1 // raisestate + }, + + { // MT_HEAD + 3005, // doomednum + S_HEAD_STND, // spawnstate + 400, // spawnhealth + S_HEAD_RUN1, // seestate + sfx_cacsit, // seesound + 8, // reactiontime + 0, // attacksound + S_HEAD_PAIN, // painstate + 128, // painchance + sfx_dmpain, // painsound + 0, // meleestate + S_HEAD_ATK1, // missilestate + S_HEAD_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_cacdth, // deathsound + 8, // speed + 31*FRACUNIT, // radius + 56*FRACUNIT, // height + 400, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags + S_HEAD_RAISE1 // raisestate + }, + + { // MT_BRUISER + 3003, // doomednum + S_BOSS_STND, // spawnstate + 1000, // spawnhealth + S_BOSS_RUN1, // seestate + sfx_brssit, // seesound + 8, // reactiontime + 0, // attacksound + S_BOSS_PAIN, // painstate + 50, // painchance + sfx_dmpain, // painsound + S_BOSS_ATK1, // meleestate + S_BOSS_ATK1, // missilestate + S_BOSS_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_brsdth, // deathsound + 8, // speed + 24*FRACUNIT, // radius + 64*FRACUNIT, // height + 1000, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_BOSS_RAISE1 // raisestate + }, + + { // MT_BRUISERSHOT + -1, // doomednum + S_BRBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_firsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BRBALLX1, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 15*FRACUNIT, // speed + 6*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 8, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_KNIGHT + 69, // doomednum + S_BOS2_STND, // spawnstate + 500, // spawnhealth + S_BOS2_RUN1, // seestate + sfx_kntsit, // seesound + 8, // reactiontime + 0, // attacksound + S_BOS2_PAIN, // painstate + 50, // painchance + sfx_dmpain, // painsound + S_BOS2_ATK1, // meleestate + S_BOS2_ATK1, // missilestate + S_BOS2_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_kntdth, // deathsound + 8, // speed + 24*FRACUNIT, // radius + 64*FRACUNIT, // height + 1000, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_BOS2_RAISE1 // raisestate + }, + + { // MT_SKULL + 3006, // doomednum + S_SKULL_STND, // spawnstate + 100, // spawnhealth + S_SKULL_RUN1, // seestate + 0, // seesound + 8, // reactiontime + sfx_sklatk, // attacksound + S_SKULL_PAIN, // painstate + 256, // painchance + sfx_dmpain, // painsound + 0, // meleestate + S_SKULL_ATK1, // missilestate + S_SKULL_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 8, // speed + 16*FRACUNIT, // radius + 56*FRACUNIT, // height + 50, // mass + 3, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_SPIDER + 7, // doomednum + S_SPID_STND, // spawnstate + 3000, // spawnhealth + S_SPID_RUN1, // seestate + sfx_spisit, // seesound + 8, // reactiontime + sfx_shotgn, // attacksound + S_SPID_PAIN, // painstate + 40, // painchance + sfx_dmpain, // painsound + 0, // meleestate + S_SPID_ATK1, // missilestate + S_SPID_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_spidth, // deathsound + 12, // speed + 128*FRACUNIT, // radius + 100*FRACUNIT, // height + 1000, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_NULL // raisestate + }, + + { // MT_BABY + 68, // doomednum + S_BSPI_STND, // spawnstate + 500, // spawnhealth + S_BSPI_SIGHT, // seestate + sfx_bspsit, // seesound + 8, // reactiontime + 0, // attacksound + S_BSPI_PAIN, // painstate + 128, // painchance + sfx_dmpain, // painsound + 0, // meleestate + S_BSPI_ATK1, // missilestate + S_BSPI_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_bspdth, // deathsound + 12, // speed + 64*FRACUNIT, // radius + 64*FRACUNIT, // height + 600, // mass + 0, // damage + sfx_bspact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_BSPI_RAISE1 // raisestate + }, + + { // MT_CYBORG + 16, // doomednum + S_CYBER_STND, // spawnstate + 4000, // spawnhealth + S_CYBER_RUN1, // seestate + sfx_cybsit, // seesound + 8, // reactiontime + 0, // attacksound + S_CYBER_PAIN, // painstate + 20, // painchance + sfx_dmpain, // painsound + 0, // meleestate + S_CYBER_ATK1, // missilestate + S_CYBER_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_cybdth, // deathsound + 16, // speed + 40*FRACUNIT, // radius + 110*FRACUNIT, // height + 1000, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_NULL // raisestate + }, + + { // MT_PAIN + 71, // doomednum + S_PAIN_STND, // spawnstate + 400, // spawnhealth + S_PAIN_RUN1, // seestate + sfx_pesit, // seesound + 8, // reactiontime + 0, // attacksound + S_PAIN_PAIN, // painstate + 128, // painchance + sfx_pepain, // painsound + 0, // meleestate + S_PAIN_ATK1, // missilestate + S_PAIN_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_pedth, // deathsound + 8, // speed + 31*FRACUNIT, // radius + 56*FRACUNIT, // height + 400, // mass + 0, // damage + sfx_dmact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags + S_PAIN_RAISE1 // raisestate + }, + + { // MT_WOLFSS + 84, // doomednum + S_SSWV_STND, // spawnstate + 50, // spawnhealth + S_SSWV_RUN1, // seestate + sfx_sssit, // seesound + 8, // reactiontime + 0, // attacksound + S_SSWV_PAIN, // painstate + 170, // painchance + sfx_popain, // painsound + 0, // meleestate + S_SSWV_ATK1, // missilestate + S_SSWV_DIE1, // deathstate + S_SSWV_XDIE1, // xdeathstate + sfx_ssdth, // deathsound + 8, // speed + 20*FRACUNIT, // radius + 56*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_posact, // activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_SSWV_RAISE1 // raisestate + }, + + { // MT_KEEN + 72, // doomednum + S_KEENSTND, // spawnstate + 100, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_KEENPAIN, // painstate + 256, // painchance + sfx_keenpn, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_COMMKEEN, // deathstate + S_NULL, // xdeathstate + sfx_keendt, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 72*FRACUNIT, // height + 10000000, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SHOOTABLE|MF_COUNTKILL, // flags + S_NULL // raisestate + }, + + { // MT_BOSSBRAIN + 88, // doomednum + S_BRAIN, // spawnstate + 250, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_BRAIN_PAIN, // painstate + 255, // painchance + sfx_bospn, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BRAIN_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_bosdth, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 10000000, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE, // flags + S_NULL // raisestate + }, + + { // MT_BOSSSPIT + 89, // doomednum + S_BRAINEYE, // spawnstate + 1000, // spawnhealth + S_BRAINEYESEE, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 32*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOSECTOR, // flags + S_NULL // raisestate + }, + + { // MT_BOSSTARGET + 87, // doomednum + S_NULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 32*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOSECTOR, // flags + S_NULL // raisestate + }, + + { // MT_SPAWNSHOT + -1, // doomednum + S_SPAWN1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_bospit, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 10*FRACUNIT, // speed + 6*FRACUNIT, // radius + 32*FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + + { // MT_SPAWNFIRE + -1, // doomednum + S_SPAWNFIRE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_BARREL + 2035, // doomednum + S_BAR1, // spawnstate + 20, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BEXP, // deathstate + S_NULL, // xdeathstate + sfx_barexp, // deathsound + 0, // speed + 10*FRACUNIT, // radius + 42*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD, // flags + S_NULL // raisestate + }, + + { // MT_TROOPSHOT + -1, // doomednum + S_TBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_firsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_TBALLX1, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 10*FRACUNIT, // speed + 6*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_HEADSHOT + -1, // doomednum + S_RBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_firsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_RBALLX1, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 10*FRACUNIT, // speed + 6*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_ROCKET + -1, // doomednum + S_ROCKET, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_rlaunc, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_EXPLODE1, // deathstate + S_NULL, // xdeathstate + sfx_barexp, // deathsound + 20*FRACUNIT, // speed + 11*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 20, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_PLASMA + -1, // doomednum + S_PLASBALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_plasma, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_PLASEXP, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 25*FRACUNIT, // speed + 13*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_BFG + -1, // doomednum + S_BFGSHOT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BFGLAND, // deathstate + S_NULL, // xdeathstate + sfx_rxplod, // deathsound + 25*FRACUNIT, // speed + 13*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 100, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_ARACHPLAZ + -1, // doomednum + S_ARACH_PLAZ, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_plasma, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_ARACH_PLEX, // deathstate + S_NULL, // xdeathstate + sfx_firxpl, // deathsound + 25*FRACUNIT, // speed + 13*FRACUNIT, // radius + 8*FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_PUFF + -1, // doomednum + S_PUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_BLOOD + -1, // doomednum + S_BLOOD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_TFOG + -1, // doomednum + S_TFOG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_IFOG + -1, // doomednum + S_IFOG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_TELEPORTMAN + 14, // doomednum + S_NULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOSECTOR, // flags + S_NULL // raisestate + }, + + { // MT_EXTRABFG + -1, // doomednum + S_BFGEXP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC0 + 2018, // doomednum + S_ARM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC1 + 2019, // doomednum + S_ARM2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC2 + 2014, // doomednum + S_BON1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_MISC3 + 2015, // doomednum + S_BON2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_MISC4 + 5, // doomednum + S_BKEY, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_MISC5 + 13, // doomednum + S_RKEY, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_MISC6 + 6, // doomednum + S_YKEY, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_MISC7 + 39, // doomednum + S_YSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_MISC8 + 38, // doomednum + S_RSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_MISC9 + 40, // doomednum + S_BSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOTDMATCH, // flags + S_NULL // raisestate + }, + + { // MT_MISC10 + 2011, // doomednum + S_STIM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC11 + 2012, // doomednum + S_MEDI, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC12 + 2013, // doomednum + S_SOUL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_INV + 2022, // doomednum + S_PINV, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_MISC13 + 2023, // doomednum + S_PSTR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_INS + 2024, // doomednum + S_PINS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_MISC14 + 2025, // doomednum + S_SUIT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC15 + 2026, // doomednum + S_PMAP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_MISC16 + 2045, // doomednum + S_PVIS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_MEGA + 83, // doomednum + S_MEGA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_COUNTITEM, // flags + S_NULL // raisestate + }, + + { // MT_CLIP + 2007, // doomednum + S_CLIP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC17 + 2048, // doomednum + S_AMMO, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC18 + 2010, // doomednum + S_ROCK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC19 + 2046, // doomednum + S_BROK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC20 + 2047, // doomednum + S_CELL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC21 + 17, // doomednum + S_CELP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC22 + 2008, // doomednum + S_SHEL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC23 + 2049, // doomednum + S_SBOX, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC24 + 8, // doomednum + S_BPAK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC25 + 2006, // doomednum + S_BFUG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_CHAINGUN + 2002, // doomednum + S_MGUN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC26 + 2005, // doomednum + S_CSAW, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC27 + 2003, // doomednum + S_LAUN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC28 + 2004, // doomednum + S_PLAS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_SHOTGUN + 2001, // doomednum + S_SHOT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_SUPERSHOTGUN + 82, // doomednum + S_SHOT2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MISC29 + 85, // doomednum + S_TECHLAMP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC30 + 86, // doomednum + S_TECH2LAMP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC31 + 2028, // doomednum + S_COLU, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC32 + 30, // doomednum + S_TALLGRNCOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC33 + 31, // doomednum + S_SHRTGRNCOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC34 + 32, // doomednum + S_TALLREDCOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC35 + 33, // doomednum + S_SHRTREDCOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC36 + 37, // doomednum + S_SKULLCOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC37 + 36, // doomednum + S_HEARTCOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC38 + 41, // doomednum + S_EVILEYE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC39 + 42, // doomednum + S_FLOATSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC40 + 43, // doomednum + S_TORCHTREE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC41 + 44, // doomednum + S_BLUETORCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC42 + 45, // doomednum + S_GREENTORCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC43 + 46, // doomednum + S_REDTORCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC44 + 55, // doomednum + S_BTORCHSHRT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC45 + 56, // doomednum + S_GTORCHSHRT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC46 + 57, // doomednum + S_RTORCHSHRT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC47 + 47, // doomednum + S_STALAGTITE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC48 + 48, // doomednum + S_TECHPILLAR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC49 + 34, // doomednum + S_CANDLESTIK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC50 + 35, // doomednum + S_CANDELABRA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC51 + 49, // doomednum + S_BLOODYTWITCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 68*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC52 + 50, // doomednum + S_MEAT2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 84*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC53 + 51, // doomednum + S_MEAT3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 84*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC54 + 52, // doomednum + S_MEAT4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 68*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC55 + 53, // doomednum + S_MEAT5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 52*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC56 + 59, // doomednum + S_MEAT2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 84*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC57 + 60, // doomednum + S_MEAT4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 68*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC58 + 61, // doomednum + S_MEAT3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 52*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC59 + 62, // doomednum + S_MEAT5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 52*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC60 + 63, // doomednum + S_BLOODYTWITCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 68*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC61 + 22, // doomednum + S_HEAD_DIE6, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC62 + 15, // doomednum + S_PLAY_DIE7, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC63 + 18, // doomednum + S_POSS_DIE5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC64 + 21, // doomednum + S_SARG_DIE6, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC65 + 23, // doomednum + S_SKULL_DIE6, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC66 + 20, // doomednum + S_TROO_DIE5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC67 + 19, // doomednum + S_SPOS_DIE5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC68 + 10, // doomednum + S_PLAY_XDIE9, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC69 + 12, // doomednum + S_PLAY_XDIE9, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC70 + 28, // doomednum + S_HEADSONSTICK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC71 + 24, // doomednum + S_GIBS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + 0, // flags + S_NULL // raisestate + }, + + { // MT_MISC72 + 27, // doomednum + S_HEADONASTICK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC73 + 29, // doomednum + S_HEADCANDLES, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC74 + 25, // doomednum + S_DEADSTICK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC75 + 26, // doomednum + S_LIVESTICK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC76 + 54, // doomednum + S_BIGTREE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC77 + 70, // doomednum + S_BBAR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_MISC78 + 73, // doomednum + S_HANGNOGUTS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 88*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC79 + 74, // doomednum + S_HANGBNOBRAIN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 88*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC80 + 75, // doomednum + S_HANGTLOOKDN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 64*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC81 + 76, // doomednum + S_HANGTSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 64*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC82 + 77, // doomednum + S_HANGTLOOKUP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 64*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC83 + 78, // doomednum + S_HANGTNOBRAIN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 64*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MISC84 + 79, // doomednum + S_COLONGIBS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_MISC85 + 80, // doomednum + S_SMALLPOOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_MISC86 + 81, // doomednum + S_BRAINSTEM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 16*FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + } +}; + diff --git a/games/NXDoom/src/doom/info.h b/games/NXDoom/src/doom/info.h new file mode 100644 index 00000000000..c426d07bf25 --- /dev/null +++ b/games/NXDoom/src/doom/info.h @@ -0,0 +1,1331 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Thing frame/state LUT, +// generated by multigen utilitiy. +// This one is the original DOOM version, preserved. +// + +#ifndef __INFO__ +#define __INFO__ + +// Needed for action function pointer handling. +#include "d_think.h" + +typedef enum +{ + SPR_TROO, + SPR_SHTG, + SPR_PUNG, + SPR_PISG, + SPR_PISF, + SPR_SHTF, + SPR_SHT2, + SPR_CHGG, + SPR_CHGF, + SPR_MISG, + SPR_MISF, + SPR_SAWG, + SPR_PLSG, + SPR_PLSF, + SPR_BFGG, + SPR_BFGF, + SPR_BLUD, + SPR_PUFF, + SPR_BAL1, + SPR_BAL2, + SPR_PLSS, + SPR_PLSE, + SPR_MISL, + SPR_BFS1, + SPR_BFE1, + SPR_BFE2, + SPR_TFOG, + SPR_IFOG, + SPR_PLAY, + SPR_POSS, + SPR_SPOS, + SPR_VILE, + SPR_FIRE, + SPR_FATB, + SPR_FBXP, + SPR_SKEL, + SPR_MANF, + SPR_FATT, + SPR_CPOS, + SPR_SARG, + SPR_HEAD, + SPR_BAL7, + SPR_BOSS, + SPR_BOS2, + SPR_SKUL, + SPR_SPID, + SPR_BSPI, + SPR_APLS, + SPR_APBX, + SPR_CYBR, + SPR_PAIN, + SPR_SSWV, + SPR_KEEN, + SPR_BBRN, + SPR_BOSF, + SPR_ARM1, + SPR_ARM2, + SPR_BAR1, + SPR_BEXP, + SPR_FCAN, + SPR_BON1, + SPR_BON2, + SPR_BKEY, + SPR_RKEY, + SPR_YKEY, + SPR_BSKU, + SPR_RSKU, + SPR_YSKU, + SPR_STIM, + SPR_MEDI, + SPR_SOUL, + SPR_PINV, + SPR_PSTR, + SPR_PINS, + SPR_MEGA, + SPR_SUIT, + SPR_PMAP, + SPR_PVIS, + SPR_CLIP, + SPR_AMMO, + SPR_ROCK, + SPR_BROK, + SPR_CELL, + SPR_CELP, + SPR_SHEL, + SPR_SBOX, + SPR_BPAK, + SPR_BFUG, + SPR_MGUN, + SPR_CSAW, + SPR_LAUN, + SPR_PLAS, + SPR_SHOT, + SPR_SGN2, + SPR_COLU, + SPR_SMT2, + SPR_GOR1, + SPR_POL2, + SPR_POL5, + SPR_POL4, + SPR_POL3, + SPR_POL1, + SPR_POL6, + SPR_GOR2, + SPR_GOR3, + SPR_GOR4, + SPR_GOR5, + SPR_SMIT, + SPR_COL1, + SPR_COL2, + SPR_COL3, + SPR_COL4, + SPR_CAND, + SPR_CBRA, + SPR_COL6, + SPR_TRE1, + SPR_TRE2, + SPR_ELEC, + SPR_CEYE, + SPR_FSKU, + SPR_COL5, + SPR_TBLU, + SPR_TGRN, + SPR_TRED, + SPR_SMBT, + SPR_SMGT, + SPR_SMRT, + SPR_HDB1, + SPR_HDB2, + SPR_HDB3, + SPR_HDB4, + SPR_HDB5, + SPR_HDB6, + SPR_POB1, + SPR_POB2, + SPR_BRS1, + SPR_TLMP, + SPR_TLP2, + NUMSPRITES + +} spritenum_t; + +typedef enum +{ + S_NULL, + S_LIGHTDONE, + S_PUNCH, + S_PUNCHDOWN, + S_PUNCHUP, + S_PUNCH1, + S_PUNCH2, + S_PUNCH3, + S_PUNCH4, + S_PUNCH5, + S_PISTOL, + S_PISTOLDOWN, + S_PISTOLUP, + S_PISTOL1, + S_PISTOL2, + S_PISTOL3, + S_PISTOL4, + S_PISTOLFLASH, + S_SGUN, + S_SGUNDOWN, + S_SGUNUP, + S_SGUN1, + S_SGUN2, + S_SGUN3, + S_SGUN4, + S_SGUN5, + S_SGUN6, + S_SGUN7, + S_SGUN8, + S_SGUN9, + S_SGUNFLASH1, + S_SGUNFLASH2, + S_DSGUN, + S_DSGUNDOWN, + S_DSGUNUP, + S_DSGUN1, + S_DSGUN2, + S_DSGUN3, + S_DSGUN4, + S_DSGUN5, + S_DSGUN6, + S_DSGUN7, + S_DSGUN8, + S_DSGUN9, + S_DSGUN10, + S_DSNR1, + S_DSNR2, + S_DSGUNFLASH1, + S_DSGUNFLASH2, + S_CHAIN, + S_CHAINDOWN, + S_CHAINUP, + S_CHAIN1, + S_CHAIN2, + S_CHAIN3, + S_CHAINFLASH1, + S_CHAINFLASH2, + S_MISSILE, + S_MISSILEDOWN, + S_MISSILEUP, + S_MISSILE1, + S_MISSILE2, + S_MISSILE3, + S_MISSILEFLASH1, + S_MISSILEFLASH2, + S_MISSILEFLASH3, + S_MISSILEFLASH4, + S_SAW, + S_SAWB, + S_SAWDOWN, + S_SAWUP, + S_SAW1, + S_SAW2, + S_SAW3, + S_PLASMA, + S_PLASMADOWN, + S_PLASMAUP, + S_PLASMA1, + S_PLASMA2, + S_PLASMAFLASH1, + S_PLASMAFLASH2, + S_BFG, + S_BFGDOWN, + S_BFGUP, + S_BFG1, + S_BFG2, + S_BFG3, + S_BFG4, + S_BFGFLASH1, + S_BFGFLASH2, + S_BLOOD1, + S_BLOOD2, + S_BLOOD3, + S_PUFF1, + S_PUFF2, + S_PUFF3, + S_PUFF4, + S_TBALL1, + S_TBALL2, + S_TBALLX1, + S_TBALLX2, + S_TBALLX3, + S_RBALL1, + S_RBALL2, + S_RBALLX1, + S_RBALLX2, + S_RBALLX3, + S_PLASBALL, + S_PLASBALL2, + S_PLASEXP, + S_PLASEXP2, + S_PLASEXP3, + S_PLASEXP4, + S_PLASEXP5, + S_ROCKET, + S_BFGSHOT, + S_BFGSHOT2, + S_BFGLAND, + S_BFGLAND2, + S_BFGLAND3, + S_BFGLAND4, + S_BFGLAND5, + S_BFGLAND6, + S_BFGEXP, + S_BFGEXP2, + S_BFGEXP3, + S_BFGEXP4, + S_EXPLODE1, + S_EXPLODE2, + S_EXPLODE3, + S_TFOG, + S_TFOG01, + S_TFOG02, + S_TFOG2, + S_TFOG3, + S_TFOG4, + S_TFOG5, + S_TFOG6, + S_TFOG7, + S_TFOG8, + S_TFOG9, + S_TFOG10, + S_IFOG, + S_IFOG01, + S_IFOG02, + S_IFOG2, + S_IFOG3, + S_IFOG4, + S_IFOG5, + S_PLAY, + S_PLAY_RUN1, + S_PLAY_RUN2, + S_PLAY_RUN3, + S_PLAY_RUN4, + S_PLAY_ATK1, + S_PLAY_ATK2, + S_PLAY_PAIN, + S_PLAY_PAIN2, + S_PLAY_DIE1, + S_PLAY_DIE2, + S_PLAY_DIE3, + S_PLAY_DIE4, + S_PLAY_DIE5, + S_PLAY_DIE6, + S_PLAY_DIE7, + S_PLAY_XDIE1, + S_PLAY_XDIE2, + S_PLAY_XDIE3, + S_PLAY_XDIE4, + S_PLAY_XDIE5, + S_PLAY_XDIE6, + S_PLAY_XDIE7, + S_PLAY_XDIE8, + S_PLAY_XDIE9, + S_POSS_STND, + S_POSS_STND2, + S_POSS_RUN1, + S_POSS_RUN2, + S_POSS_RUN3, + S_POSS_RUN4, + S_POSS_RUN5, + S_POSS_RUN6, + S_POSS_RUN7, + S_POSS_RUN8, + S_POSS_ATK1, + S_POSS_ATK2, + S_POSS_ATK3, + S_POSS_PAIN, + S_POSS_PAIN2, + S_POSS_DIE1, + S_POSS_DIE2, + S_POSS_DIE3, + S_POSS_DIE4, + S_POSS_DIE5, + S_POSS_XDIE1, + S_POSS_XDIE2, + S_POSS_XDIE3, + S_POSS_XDIE4, + S_POSS_XDIE5, + S_POSS_XDIE6, + S_POSS_XDIE7, + S_POSS_XDIE8, + S_POSS_XDIE9, + S_POSS_RAISE1, + S_POSS_RAISE2, + S_POSS_RAISE3, + S_POSS_RAISE4, + S_SPOS_STND, + S_SPOS_STND2, + S_SPOS_RUN1, + S_SPOS_RUN2, + S_SPOS_RUN3, + S_SPOS_RUN4, + S_SPOS_RUN5, + S_SPOS_RUN6, + S_SPOS_RUN7, + S_SPOS_RUN8, + S_SPOS_ATK1, + S_SPOS_ATK2, + S_SPOS_ATK3, + S_SPOS_PAIN, + S_SPOS_PAIN2, + S_SPOS_DIE1, + S_SPOS_DIE2, + S_SPOS_DIE3, + S_SPOS_DIE4, + S_SPOS_DIE5, + S_SPOS_XDIE1, + S_SPOS_XDIE2, + S_SPOS_XDIE3, + S_SPOS_XDIE4, + S_SPOS_XDIE5, + S_SPOS_XDIE6, + S_SPOS_XDIE7, + S_SPOS_XDIE8, + S_SPOS_XDIE9, + S_SPOS_RAISE1, + S_SPOS_RAISE2, + S_SPOS_RAISE3, + S_SPOS_RAISE4, + S_SPOS_RAISE5, + S_VILE_STND, + S_VILE_STND2, + S_VILE_RUN1, + S_VILE_RUN2, + S_VILE_RUN3, + S_VILE_RUN4, + S_VILE_RUN5, + S_VILE_RUN6, + S_VILE_RUN7, + S_VILE_RUN8, + S_VILE_RUN9, + S_VILE_RUN10, + S_VILE_RUN11, + S_VILE_RUN12, + S_VILE_ATK1, + S_VILE_ATK2, + S_VILE_ATK3, + S_VILE_ATK4, + S_VILE_ATK5, + S_VILE_ATK6, + S_VILE_ATK7, + S_VILE_ATK8, + S_VILE_ATK9, + S_VILE_ATK10, + S_VILE_ATK11, + S_VILE_HEAL1, + S_VILE_HEAL2, + S_VILE_HEAL3, + S_VILE_PAIN, + S_VILE_PAIN2, + S_VILE_DIE1, + S_VILE_DIE2, + S_VILE_DIE3, + S_VILE_DIE4, + S_VILE_DIE5, + S_VILE_DIE6, + S_VILE_DIE7, + S_VILE_DIE8, + S_VILE_DIE9, + S_VILE_DIE10, + S_FIRE1, + S_FIRE2, + S_FIRE3, + S_FIRE4, + S_FIRE5, + S_FIRE6, + S_FIRE7, + S_FIRE8, + S_FIRE9, + S_FIRE10, + S_FIRE11, + S_FIRE12, + S_FIRE13, + S_FIRE14, + S_FIRE15, + S_FIRE16, + S_FIRE17, + S_FIRE18, + S_FIRE19, + S_FIRE20, + S_FIRE21, + S_FIRE22, + S_FIRE23, + S_FIRE24, + S_FIRE25, + S_FIRE26, + S_FIRE27, + S_FIRE28, + S_FIRE29, + S_FIRE30, + S_SMOKE1, + S_SMOKE2, + S_SMOKE3, + S_SMOKE4, + S_SMOKE5, + S_TRACER, + S_TRACER2, + S_TRACEEXP1, + S_TRACEEXP2, + S_TRACEEXP3, + S_SKEL_STND, + S_SKEL_STND2, + S_SKEL_RUN1, + S_SKEL_RUN2, + S_SKEL_RUN3, + S_SKEL_RUN4, + S_SKEL_RUN5, + S_SKEL_RUN6, + S_SKEL_RUN7, + S_SKEL_RUN8, + S_SKEL_RUN9, + S_SKEL_RUN10, + S_SKEL_RUN11, + S_SKEL_RUN12, + S_SKEL_FIST1, + S_SKEL_FIST2, + S_SKEL_FIST3, + S_SKEL_FIST4, + S_SKEL_MISS1, + S_SKEL_MISS2, + S_SKEL_MISS3, + S_SKEL_MISS4, + S_SKEL_PAIN, + S_SKEL_PAIN2, + S_SKEL_DIE1, + S_SKEL_DIE2, + S_SKEL_DIE3, + S_SKEL_DIE4, + S_SKEL_DIE5, + S_SKEL_DIE6, + S_SKEL_RAISE1, + S_SKEL_RAISE2, + S_SKEL_RAISE3, + S_SKEL_RAISE4, + S_SKEL_RAISE5, + S_SKEL_RAISE6, + S_FATSHOT1, + S_FATSHOT2, + S_FATSHOTX1, + S_FATSHOTX2, + S_FATSHOTX3, + S_FATT_STND, + S_FATT_STND2, + S_FATT_RUN1, + S_FATT_RUN2, + S_FATT_RUN3, + S_FATT_RUN4, + S_FATT_RUN5, + S_FATT_RUN6, + S_FATT_RUN7, + S_FATT_RUN8, + S_FATT_RUN9, + S_FATT_RUN10, + S_FATT_RUN11, + S_FATT_RUN12, + S_FATT_ATK1, + S_FATT_ATK2, + S_FATT_ATK3, + S_FATT_ATK4, + S_FATT_ATK5, + S_FATT_ATK6, + S_FATT_ATK7, + S_FATT_ATK8, + S_FATT_ATK9, + S_FATT_ATK10, + S_FATT_PAIN, + S_FATT_PAIN2, + S_FATT_DIE1, + S_FATT_DIE2, + S_FATT_DIE3, + S_FATT_DIE4, + S_FATT_DIE5, + S_FATT_DIE6, + S_FATT_DIE7, + S_FATT_DIE8, + S_FATT_DIE9, + S_FATT_DIE10, + S_FATT_RAISE1, + S_FATT_RAISE2, + S_FATT_RAISE3, + S_FATT_RAISE4, + S_FATT_RAISE5, + S_FATT_RAISE6, + S_FATT_RAISE7, + S_FATT_RAISE8, + S_CPOS_STND, + S_CPOS_STND2, + S_CPOS_RUN1, + S_CPOS_RUN2, + S_CPOS_RUN3, + S_CPOS_RUN4, + S_CPOS_RUN5, + S_CPOS_RUN6, + S_CPOS_RUN7, + S_CPOS_RUN8, + S_CPOS_ATK1, + S_CPOS_ATK2, + S_CPOS_ATK3, + S_CPOS_ATK4, + S_CPOS_PAIN, + S_CPOS_PAIN2, + S_CPOS_DIE1, + S_CPOS_DIE2, + S_CPOS_DIE3, + S_CPOS_DIE4, + S_CPOS_DIE5, + S_CPOS_DIE6, + S_CPOS_DIE7, + S_CPOS_XDIE1, + S_CPOS_XDIE2, + S_CPOS_XDIE3, + S_CPOS_XDIE4, + S_CPOS_XDIE5, + S_CPOS_XDIE6, + S_CPOS_RAISE1, + S_CPOS_RAISE2, + S_CPOS_RAISE3, + S_CPOS_RAISE4, + S_CPOS_RAISE5, + S_CPOS_RAISE6, + S_CPOS_RAISE7, + S_TROO_STND, + S_TROO_STND2, + S_TROO_RUN1, + S_TROO_RUN2, + S_TROO_RUN3, + S_TROO_RUN4, + S_TROO_RUN5, + S_TROO_RUN6, + S_TROO_RUN7, + S_TROO_RUN8, + S_TROO_ATK1, + S_TROO_ATK2, + S_TROO_ATK3, + S_TROO_PAIN, + S_TROO_PAIN2, + S_TROO_DIE1, + S_TROO_DIE2, + S_TROO_DIE3, + S_TROO_DIE4, + S_TROO_DIE5, + S_TROO_XDIE1, + S_TROO_XDIE2, + S_TROO_XDIE3, + S_TROO_XDIE4, + S_TROO_XDIE5, + S_TROO_XDIE6, + S_TROO_XDIE7, + S_TROO_XDIE8, + S_TROO_RAISE1, + S_TROO_RAISE2, + S_TROO_RAISE3, + S_TROO_RAISE4, + S_TROO_RAISE5, + S_SARG_STND, + S_SARG_STND2, + S_SARG_RUN1, + S_SARG_RUN2, + S_SARG_RUN3, + S_SARG_RUN4, + S_SARG_RUN5, + S_SARG_RUN6, + S_SARG_RUN7, + S_SARG_RUN8, + S_SARG_ATK1, + S_SARG_ATK2, + S_SARG_ATK3, + S_SARG_PAIN, + S_SARG_PAIN2, + S_SARG_DIE1, + S_SARG_DIE2, + S_SARG_DIE3, + S_SARG_DIE4, + S_SARG_DIE5, + S_SARG_DIE6, + S_SARG_RAISE1, + S_SARG_RAISE2, + S_SARG_RAISE3, + S_SARG_RAISE4, + S_SARG_RAISE5, + S_SARG_RAISE6, + S_HEAD_STND, + S_HEAD_RUN1, + S_HEAD_ATK1, + S_HEAD_ATK2, + S_HEAD_ATK3, + S_HEAD_PAIN, + S_HEAD_PAIN2, + S_HEAD_PAIN3, + S_HEAD_DIE1, + S_HEAD_DIE2, + S_HEAD_DIE3, + S_HEAD_DIE4, + S_HEAD_DIE5, + S_HEAD_DIE6, + S_HEAD_RAISE1, + S_HEAD_RAISE2, + S_HEAD_RAISE3, + S_HEAD_RAISE4, + S_HEAD_RAISE5, + S_HEAD_RAISE6, + S_BRBALL1, + S_BRBALL2, + S_BRBALLX1, + S_BRBALLX2, + S_BRBALLX3, + S_BOSS_STND, + S_BOSS_STND2, + S_BOSS_RUN1, + S_BOSS_RUN2, + S_BOSS_RUN3, + S_BOSS_RUN4, + S_BOSS_RUN5, + S_BOSS_RUN6, + S_BOSS_RUN7, + S_BOSS_RUN8, + S_BOSS_ATK1, + S_BOSS_ATK2, + S_BOSS_ATK3, + S_BOSS_PAIN, + S_BOSS_PAIN2, + S_BOSS_DIE1, + S_BOSS_DIE2, + S_BOSS_DIE3, + S_BOSS_DIE4, + S_BOSS_DIE5, + S_BOSS_DIE6, + S_BOSS_DIE7, + S_BOSS_RAISE1, + S_BOSS_RAISE2, + S_BOSS_RAISE3, + S_BOSS_RAISE4, + S_BOSS_RAISE5, + S_BOSS_RAISE6, + S_BOSS_RAISE7, + S_BOS2_STND, + S_BOS2_STND2, + S_BOS2_RUN1, + S_BOS2_RUN2, + S_BOS2_RUN3, + S_BOS2_RUN4, + S_BOS2_RUN5, + S_BOS2_RUN6, + S_BOS2_RUN7, + S_BOS2_RUN8, + S_BOS2_ATK1, + S_BOS2_ATK2, + S_BOS2_ATK3, + S_BOS2_PAIN, + S_BOS2_PAIN2, + S_BOS2_DIE1, + S_BOS2_DIE2, + S_BOS2_DIE3, + S_BOS2_DIE4, + S_BOS2_DIE5, + S_BOS2_DIE6, + S_BOS2_DIE7, + S_BOS2_RAISE1, + S_BOS2_RAISE2, + S_BOS2_RAISE3, + S_BOS2_RAISE4, + S_BOS2_RAISE5, + S_BOS2_RAISE6, + S_BOS2_RAISE7, + S_SKULL_STND, + S_SKULL_STND2, + S_SKULL_RUN1, + S_SKULL_RUN2, + S_SKULL_ATK1, + S_SKULL_ATK2, + S_SKULL_ATK3, + S_SKULL_ATK4, + S_SKULL_PAIN, + S_SKULL_PAIN2, + S_SKULL_DIE1, + S_SKULL_DIE2, + S_SKULL_DIE3, + S_SKULL_DIE4, + S_SKULL_DIE5, + S_SKULL_DIE6, + S_SPID_STND, + S_SPID_STND2, + S_SPID_RUN1, + S_SPID_RUN2, + S_SPID_RUN3, + S_SPID_RUN4, + S_SPID_RUN5, + S_SPID_RUN6, + S_SPID_RUN7, + S_SPID_RUN8, + S_SPID_RUN9, + S_SPID_RUN10, + S_SPID_RUN11, + S_SPID_RUN12, + S_SPID_ATK1, + S_SPID_ATK2, + S_SPID_ATK3, + S_SPID_ATK4, + S_SPID_PAIN, + S_SPID_PAIN2, + S_SPID_DIE1, + S_SPID_DIE2, + S_SPID_DIE3, + S_SPID_DIE4, + S_SPID_DIE5, + S_SPID_DIE6, + S_SPID_DIE7, + S_SPID_DIE8, + S_SPID_DIE9, + S_SPID_DIE10, + S_SPID_DIE11, + S_BSPI_STND, + S_BSPI_STND2, + S_BSPI_SIGHT, + S_BSPI_RUN1, + S_BSPI_RUN2, + S_BSPI_RUN3, + S_BSPI_RUN4, + S_BSPI_RUN5, + S_BSPI_RUN6, + S_BSPI_RUN7, + S_BSPI_RUN8, + S_BSPI_RUN9, + S_BSPI_RUN10, + S_BSPI_RUN11, + S_BSPI_RUN12, + S_BSPI_ATK1, + S_BSPI_ATK2, + S_BSPI_ATK3, + S_BSPI_ATK4, + S_BSPI_PAIN, + S_BSPI_PAIN2, + S_BSPI_DIE1, + S_BSPI_DIE2, + S_BSPI_DIE3, + S_BSPI_DIE4, + S_BSPI_DIE5, + S_BSPI_DIE6, + S_BSPI_DIE7, + S_BSPI_RAISE1, + S_BSPI_RAISE2, + S_BSPI_RAISE3, + S_BSPI_RAISE4, + S_BSPI_RAISE5, + S_BSPI_RAISE6, + S_BSPI_RAISE7, + S_ARACH_PLAZ, + S_ARACH_PLAZ2, + S_ARACH_PLEX, + S_ARACH_PLEX2, + S_ARACH_PLEX3, + S_ARACH_PLEX4, + S_ARACH_PLEX5, + S_CYBER_STND, + S_CYBER_STND2, + S_CYBER_RUN1, + S_CYBER_RUN2, + S_CYBER_RUN3, + S_CYBER_RUN4, + S_CYBER_RUN5, + S_CYBER_RUN6, + S_CYBER_RUN7, + S_CYBER_RUN8, + S_CYBER_ATK1, + S_CYBER_ATK2, + S_CYBER_ATK3, + S_CYBER_ATK4, + S_CYBER_ATK5, + S_CYBER_ATK6, + S_CYBER_PAIN, + S_CYBER_DIE1, + S_CYBER_DIE2, + S_CYBER_DIE3, + S_CYBER_DIE4, + S_CYBER_DIE5, + S_CYBER_DIE6, + S_CYBER_DIE7, + S_CYBER_DIE8, + S_CYBER_DIE9, + S_CYBER_DIE10, + S_PAIN_STND, + S_PAIN_RUN1, + S_PAIN_RUN2, + S_PAIN_RUN3, + S_PAIN_RUN4, + S_PAIN_RUN5, + S_PAIN_RUN6, + S_PAIN_ATK1, + S_PAIN_ATK2, + S_PAIN_ATK3, + S_PAIN_ATK4, + S_PAIN_PAIN, + S_PAIN_PAIN2, + S_PAIN_DIE1, + S_PAIN_DIE2, + S_PAIN_DIE3, + S_PAIN_DIE4, + S_PAIN_DIE5, + S_PAIN_DIE6, + S_PAIN_RAISE1, + S_PAIN_RAISE2, + S_PAIN_RAISE3, + S_PAIN_RAISE4, + S_PAIN_RAISE5, + S_PAIN_RAISE6, + S_SSWV_STND, + S_SSWV_STND2, + S_SSWV_RUN1, + S_SSWV_RUN2, + S_SSWV_RUN3, + S_SSWV_RUN4, + S_SSWV_RUN5, + S_SSWV_RUN6, + S_SSWV_RUN7, + S_SSWV_RUN8, + S_SSWV_ATK1, + S_SSWV_ATK2, + S_SSWV_ATK3, + S_SSWV_ATK4, + S_SSWV_ATK5, + S_SSWV_ATK6, + S_SSWV_PAIN, + S_SSWV_PAIN2, + S_SSWV_DIE1, + S_SSWV_DIE2, + S_SSWV_DIE3, + S_SSWV_DIE4, + S_SSWV_DIE5, + S_SSWV_XDIE1, + S_SSWV_XDIE2, + S_SSWV_XDIE3, + S_SSWV_XDIE4, + S_SSWV_XDIE5, + S_SSWV_XDIE6, + S_SSWV_XDIE7, + S_SSWV_XDIE8, + S_SSWV_XDIE9, + S_SSWV_RAISE1, + S_SSWV_RAISE2, + S_SSWV_RAISE3, + S_SSWV_RAISE4, + S_SSWV_RAISE5, + S_KEENSTND, + S_COMMKEEN, + S_COMMKEEN2, + S_COMMKEEN3, + S_COMMKEEN4, + S_COMMKEEN5, + S_COMMKEEN6, + S_COMMKEEN7, + S_COMMKEEN8, + S_COMMKEEN9, + S_COMMKEEN10, + S_COMMKEEN11, + S_COMMKEEN12, + S_KEENPAIN, + S_KEENPAIN2, + S_BRAIN, + S_BRAIN_PAIN, + S_BRAIN_DIE1, + S_BRAIN_DIE2, + S_BRAIN_DIE3, + S_BRAIN_DIE4, + S_BRAINEYE, + S_BRAINEYESEE, + S_BRAINEYE1, + S_SPAWN1, + S_SPAWN2, + S_SPAWN3, + S_SPAWN4, + S_SPAWNFIRE1, + S_SPAWNFIRE2, + S_SPAWNFIRE3, + S_SPAWNFIRE4, + S_SPAWNFIRE5, + S_SPAWNFIRE6, + S_SPAWNFIRE7, + S_SPAWNFIRE8, + S_BRAINEXPLODE1, + S_BRAINEXPLODE2, + S_BRAINEXPLODE3, + S_ARM1, + S_ARM1A, + S_ARM2, + S_ARM2A, + S_BAR1, + S_BAR2, + S_BEXP, + S_BEXP2, + S_BEXP3, + S_BEXP4, + S_BEXP5, + S_BBAR1, + S_BBAR2, + S_BBAR3, + S_BON1, + S_BON1A, + S_BON1B, + S_BON1C, + S_BON1D, + S_BON1E, + S_BON2, + S_BON2A, + S_BON2B, + S_BON2C, + S_BON2D, + S_BON2E, + S_BKEY, + S_BKEY2, + S_RKEY, + S_RKEY2, + S_YKEY, + S_YKEY2, + S_BSKULL, + S_BSKULL2, + S_RSKULL, + S_RSKULL2, + S_YSKULL, + S_YSKULL2, + S_STIM, + S_MEDI, + S_SOUL, + S_SOUL2, + S_SOUL3, + S_SOUL4, + S_SOUL5, + S_SOUL6, + S_PINV, + S_PINV2, + S_PINV3, + S_PINV4, + S_PSTR, + S_PINS, + S_PINS2, + S_PINS3, + S_PINS4, + S_MEGA, + S_MEGA2, + S_MEGA3, + S_MEGA4, + S_SUIT, + S_PMAP, + S_PMAP2, + S_PMAP3, + S_PMAP4, + S_PMAP5, + S_PMAP6, + S_PVIS, + S_PVIS2, + S_CLIP, + S_AMMO, + S_ROCK, + S_BROK, + S_CELL, + S_CELP, + S_SHEL, + S_SBOX, + S_BPAK, + S_BFUG, + S_MGUN, + S_CSAW, + S_LAUN, + S_PLAS, + S_SHOT, + S_SHOT2, + S_COLU, + S_STALAG, + S_BLOODYTWITCH, + S_BLOODYTWITCH2, + S_BLOODYTWITCH3, + S_BLOODYTWITCH4, + S_DEADTORSO, + S_DEADBOTTOM, + S_HEADSONSTICK, + S_GIBS, + S_HEADONASTICK, + S_HEADCANDLES, + S_HEADCANDLES2, + S_DEADSTICK, + S_LIVESTICK, + S_LIVESTICK2, + S_MEAT2, + S_MEAT3, + S_MEAT4, + S_MEAT5, + S_STALAGTITE, + S_TALLGRNCOL, + S_SHRTGRNCOL, + S_TALLREDCOL, + S_SHRTREDCOL, + S_CANDLESTIK, + S_CANDELABRA, + S_SKULLCOL, + S_TORCHTREE, + S_BIGTREE, + S_TECHPILLAR, + S_EVILEYE, + S_EVILEYE2, + S_EVILEYE3, + S_EVILEYE4, + S_FLOATSKULL, + S_FLOATSKULL2, + S_FLOATSKULL3, + S_HEARTCOL, + S_HEARTCOL2, + S_BLUETORCH, + S_BLUETORCH2, + S_BLUETORCH3, + S_BLUETORCH4, + S_GREENTORCH, + S_GREENTORCH2, + S_GREENTORCH3, + S_GREENTORCH4, + S_REDTORCH, + S_REDTORCH2, + S_REDTORCH3, + S_REDTORCH4, + S_BTORCHSHRT, + S_BTORCHSHRT2, + S_BTORCHSHRT3, + S_BTORCHSHRT4, + S_GTORCHSHRT, + S_GTORCHSHRT2, + S_GTORCHSHRT3, + S_GTORCHSHRT4, + S_RTORCHSHRT, + S_RTORCHSHRT2, + S_RTORCHSHRT3, + S_RTORCHSHRT4, + S_HANGNOGUTS, + S_HANGBNOBRAIN, + S_HANGTLOOKDN, + S_HANGTSKULL, + S_HANGTLOOKUP, + S_HANGTNOBRAIN, + S_COLONGIBS, + S_SMALLPOOL, + S_BRAINSTEM, + S_TECHLAMP, + S_TECHLAMP2, + S_TECHLAMP3, + S_TECHLAMP4, + S_TECH2LAMP, + S_TECH2LAMP2, + S_TECH2LAMP3, + S_TECH2LAMP4, + NUMSTATES +} statenum_t; + + +typedef struct +{ + spritenum_t sprite; + int frame; + int tics; + // void (*action) (); + actionf_t action; + statenum_t nextstate; + int misc1; + int misc2; +} state_t; + +extern state_t states[NUMSTATES]; +extern const char *sprnames[]; + +typedef enum { + MT_PLAYER, + MT_POSSESSED, + MT_SHOTGUY, + MT_VILE, + MT_FIRE, + MT_UNDEAD, + MT_TRACER, + MT_SMOKE, + MT_FATSO, + MT_FATSHOT, + MT_CHAINGUY, + MT_TROOP, + MT_SERGEANT, + MT_SHADOWS, + MT_HEAD, + MT_BRUISER, + MT_BRUISERSHOT, + MT_KNIGHT, + MT_SKULL, + MT_SPIDER, + MT_BABY, + MT_CYBORG, + MT_PAIN, + MT_WOLFSS, + MT_KEEN, + MT_BOSSBRAIN, + MT_BOSSSPIT, + MT_BOSSTARGET, + MT_SPAWNSHOT, + MT_SPAWNFIRE, + MT_BARREL, + MT_TROOPSHOT, + MT_HEADSHOT, + MT_ROCKET, + MT_PLASMA, + MT_BFG, + MT_ARACHPLAZ, + MT_PUFF, + MT_BLOOD, + MT_TFOG, + MT_IFOG, + MT_TELEPORTMAN, + MT_EXTRABFG, + MT_MISC0, + MT_MISC1, + MT_MISC2, + MT_MISC3, + MT_MISC4, + MT_MISC5, + MT_MISC6, + MT_MISC7, + MT_MISC8, + MT_MISC9, + MT_MISC10, + MT_MISC11, + MT_MISC12, + MT_INV, + MT_MISC13, + MT_INS, + MT_MISC14, + MT_MISC15, + MT_MISC16, + MT_MEGA, + MT_CLIP, + MT_MISC17, + MT_MISC18, + MT_MISC19, + MT_MISC20, + MT_MISC21, + MT_MISC22, + MT_MISC23, + MT_MISC24, + MT_MISC25, + MT_CHAINGUN, + MT_MISC26, + MT_MISC27, + MT_MISC28, + MT_SHOTGUN, + MT_SUPERSHOTGUN, + MT_MISC29, + MT_MISC30, + MT_MISC31, + MT_MISC32, + MT_MISC33, + MT_MISC34, + MT_MISC35, + MT_MISC36, + MT_MISC37, + MT_MISC38, + MT_MISC39, + MT_MISC40, + MT_MISC41, + MT_MISC42, + MT_MISC43, + MT_MISC44, + MT_MISC45, + MT_MISC46, + MT_MISC47, + MT_MISC48, + MT_MISC49, + MT_MISC50, + MT_MISC51, + MT_MISC52, + MT_MISC53, + MT_MISC54, + MT_MISC55, + MT_MISC56, + MT_MISC57, + MT_MISC58, + MT_MISC59, + MT_MISC60, + MT_MISC61, + MT_MISC62, + MT_MISC63, + MT_MISC64, + MT_MISC65, + MT_MISC66, + MT_MISC67, + MT_MISC68, + MT_MISC69, + MT_MISC70, + MT_MISC71, + MT_MISC72, + MT_MISC73, + MT_MISC74, + MT_MISC75, + MT_MISC76, + MT_MISC77, + MT_MISC78, + MT_MISC79, + MT_MISC80, + MT_MISC81, + MT_MISC82, + MT_MISC83, + MT_MISC84, + MT_MISC85, + MT_MISC86, + NUMMOBJTYPES + +} mobjtype_t; + +typedef struct +{ + int doomednum; + int spawnstate; + int spawnhealth; + int seestate; + int seesound; + int reactiontime; + int attacksound; + int painstate; + int painchance; + int painsound; + int meleestate; + int missilestate; + int deathstate; + int xdeathstate; + int deathsound; + int speed; + int radius; + int height; + int mass; + int damage; + int activesound; + int flags; + int raisestate; + +} mobjinfo_t; + +extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; + +#endif diff --git a/games/NXDoom/src/doom/m_menu.c b/games/NXDoom/src/doom/m_menu.c new file mode 100644 index 00000000000..71b47cbf6e2 --- /dev/null +++ b/games/NXDoom/src/doom/m_menu.c @@ -0,0 +1,2128 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM selection menu, options, episode etc. +// Sliders and icons. Kinda widget stuff. +// + + +#include +#include + + +#include "doomdef.h" +#include "doomkeys.h" +#include "dstrings.h" + +#include "d_main.h" +#include "deh_main.h" + +#include "i_input.h" +#include "i_joystick.h" +#include "i_swap.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "m_misc.h" +#include "v_video.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "r_local.h" + + +#include "hu_stuff.h" + +#include "g_game.h" + +#include "m_argv.h" +#include "m_controls.h" +#include "p_saveg.h" +#include "p_setup.h" + +#include "s_sound.h" + +#include "doomstat.h" + +// Data. +#include "sounds.h" + +#include "m_menu.h" + + +// +// defaulted values +// +int mouseSensitivity = 5; + +// Show messages has default, 0 = off, 1 = on +int showMessages = 1; + + +// Blocky mode, has default, 0 = high, 1 = normal +int detailLevel = 0; +int screenblocks = 9; + +// temp for screenblocks (0-9) +int screenSize; + +// -1 = no quicksave slot picked! +int quickSaveSlot; + + // 1 = message to be printed +int messageToPrint; +// ...and here is the message string! +const char *messageString; + +// message x & y +int messx; +int messy; +int messageLastMenuActive; + +// timed message = no input from user +boolean messageNeedsInput; + +void (*messageRoutine)(int response); + +char gammamsg[5][26] = +{ + GAMMALVL0, + GAMMALVL1, + GAMMALVL2, + GAMMALVL3, + GAMMALVL4 +}; + +// we are going to be entering a savegame string +int saveStringEnter; +int saveSlot; // which slot to save in +int saveCharIndex; // which char we're editing +static boolean joypadSave = false; // was the save action initiated by joypad? +// old save description before edit +char saveOldString[SAVESTRINGSIZE]; + +boolean inhelpscreens; +boolean menuactive; + +#define SKULLXOFF -32 +#define LINEHEIGHT 16 + +char savegamestrings[10][SAVESTRINGSIZE]; + +char endstring[160]; + +static boolean opldev; + +// +// MENU TYPEDEFS +// +typedef struct +{ + // 0 = no cursor here, 1 = ok, 2 = arrows ok + short status; + + char name[10]; + + // choice = menu item #. + // if status = 2, + // choice=0:leftarrow,1:rightarrow + void (*routine)(int choice); + + // hotkey in menu + char alphaKey; +} menuitem_t; + + + +typedef struct menu_s +{ + short numitems; // # of menu items + struct menu_s* prevMenu; // previous menu + menuitem_t* menuitems; // menu items + void (*routine)(); // draw routine + short x; + short y; // x,y of menu + short lastOn; // last item user was on in menu +} menu_t; + +short itemOn; // menu item skull is on +short skullAnimCounter; // skull animation counter +short whichSkull; // which skull to draw + +// graphic name of skulls +// warning: initializer-string for array of chars is too long +const char *skullName[2] = {"M_SKULL1","M_SKULL2"}; + +// current menudef +menu_t* currentMenu; + +// +// PROTOTYPES +// +static void M_NewGame(int choice); +static void M_Episode(int choice); +static void M_ChooseSkill(int choice); +static void M_LoadGame(int choice); +static void M_SaveGame(int choice); +static void M_Options(int choice); +static void M_EndGame(int choice); +static void M_ReadThis(int choice); +static void M_ReadThis2(int choice); +static void M_QuitDOOM(int choice); + +static void M_ChangeMessages(int choice); +static void M_ChangeSensitivity(int choice); +static void M_SfxVol(int choice); +static void M_MusicVol(int choice); +static void M_ChangeDetail(int choice); +static void M_SizeDisplay(int choice); +static void M_Sound(int choice); + +static void M_FinishReadThis(int choice); +static void M_LoadSelect(int choice); +static void M_SaveSelect(int choice); +static void M_ReadSaveStrings(void); +static void M_QuickSave(void); +static void M_QuickLoad(void); + +static void M_DrawMainMenu(void); +static void M_DrawReadThis1(void); +static void M_DrawReadThis2(void); +static void M_DrawNewGame(void); +static void M_DrawEpisode(void); +static void M_DrawOptions(void); +static void M_DrawSound(void); +static void M_DrawLoad(void); +static void M_DrawSave(void); + +static void M_DrawSaveLoadBorder(int x,int y); +static void M_SetupNextMenu(menu_t *menudef); +static void M_DrawThermo(int x,int y,int thermWidth,int thermDot); +static void M_WriteText(int x, int y, const char *string); +static int M_StringWidth(const char *string); +static int M_StringHeight(const char *string); +static void M_StartMessage(const char *string, void *routine, boolean input); +static void M_ClearMenus (void); + + + + +// +// DOOM MENU +// +enum +{ + newgame = 0, + options, + loadgame, + savegame, + readthis, + quitdoom, + main_end +} main_e; + +menuitem_t MainMenu[]= +{ + {1,"M_NGAME",M_NewGame,'n'}, + {1,"M_OPTION",M_Options,'o'}, + {1,"M_LOADG",M_LoadGame,'l'}, + {1,"M_SAVEG",M_SaveGame,'s'}, + // Another hickup with Special edition. + {1,"M_RDTHIS",M_ReadThis,'r'}, + {1,"M_QUITG",M_QuitDOOM,'q'} +}; + +menu_t MainDef = +{ + main_end, + NULL, + MainMenu, + M_DrawMainMenu, + 97,64, + 0 +}; + + +// +// EPISODE SELECT +// +enum +{ + ep1, + ep2, + ep3, + ep4, + ep_end +} episodes_e; + +menuitem_t EpisodeMenu[]= +{ + {1,"M_EPI1", M_Episode,'k'}, + {1,"M_EPI2", M_Episode,'t'}, + {1,"M_EPI3", M_Episode,'i'}, + {1,"M_EPI4", M_Episode,'t'} +}; + +menu_t EpiDef = +{ + ep_end, // # of menu items + &MainDef, // previous menu + EpisodeMenu, // menuitem_t -> + M_DrawEpisode, // drawing routine -> + 48,63, // x,y + ep1 // lastOn +}; + +// +// NEW GAME +// +enum +{ + killthings, + toorough, + hurtme, + violence, + nightmare, + newg_end +} newgame_e; + +menuitem_t NewGameMenu[]= +{ + {1,"M_JKILL", M_ChooseSkill, 'i'}, + {1,"M_ROUGH", M_ChooseSkill, 'h'}, + {1,"M_HURT", M_ChooseSkill, 'h'}, + {1,"M_ULTRA", M_ChooseSkill, 'u'}, + {1,"M_NMARE", M_ChooseSkill, 'n'} +}; + +menu_t NewDef = +{ + newg_end, // # of menu items + &EpiDef, // previous menu + NewGameMenu, // menuitem_t -> + M_DrawNewGame, // drawing routine -> + 48,63, // x,y + hurtme // lastOn +}; + + + +// +// OPTIONS MENU +// +enum +{ + endgame, + messages, + detail, + scrnsize, + option_empty1, + mousesens, + option_empty2, + soundvol, + opt_end +} options_e; + +menuitem_t OptionsMenu[]= +{ + {1,"M_ENDGAM", M_EndGame,'e'}, + {1,"M_MESSG", M_ChangeMessages,'m'}, + {1,"M_DETAIL", M_ChangeDetail,'g'}, + {2,"M_SCRNSZ", M_SizeDisplay,'s'}, + {-1,"",0,'\0'}, + {2,"M_MSENS", M_ChangeSensitivity,'m'}, + {-1,"",0,'\0'}, + {1,"M_SVOL", M_Sound,'s'} +}; + +menu_t OptionsDef = +{ + opt_end, + &MainDef, + OptionsMenu, + M_DrawOptions, + 60,37, + 0 +}; + +// +// Read This! MENU 1 & 2 +// +enum +{ + rdthsempty1, + read1_end +} read_e; + +menuitem_t ReadMenu1[] = +{ + {1,"",M_ReadThis2,0} +}; + +menu_t ReadDef1 = +{ + read1_end, + &MainDef, + ReadMenu1, + M_DrawReadThis1, + 280,185, + 0 +}; + +enum +{ + rdthsempty2, + read2_end +} read_e2; + +menuitem_t ReadMenu2[]= +{ + {1,"",M_FinishReadThis,0} +}; + +menu_t ReadDef2 = +{ + read2_end, + &ReadDef1, + ReadMenu2, + M_DrawReadThis2, + 330,175, + 0 +}; + +// +// SOUND VOLUME MENU +// +enum +{ + sfx_vol, + sfx_empty1, + music_vol, + sfx_empty2, + sound_end +} sound_e; + +menuitem_t SoundMenu[]= +{ + {2,"M_SFXVOL",M_SfxVol,'s'}, + {-1,"",0,'\0'}, + {2,"M_MUSVOL",M_MusicVol,'m'}, + {-1,"",0,'\0'} +}; + +menu_t SoundDef = +{ + sound_end, + &OptionsDef, + SoundMenu, + M_DrawSound, + 80,64, + 0 +}; + +// +// LOAD GAME MENU +// +enum +{ + load1, + load2, + load3, + load4, + load5, + load6, + load_end +} load_e; + +menuitem_t LoadMenu[]= +{ + {1,"", M_LoadSelect,'1'}, + {1,"", M_LoadSelect,'2'}, + {1,"", M_LoadSelect,'3'}, + {1,"", M_LoadSelect,'4'}, + {1,"", M_LoadSelect,'5'}, + {1,"", M_LoadSelect,'6'} +}; + +menu_t LoadDef = +{ + load_end, + &MainDef, + LoadMenu, + M_DrawLoad, + 80,54, + 0 +}; + +// +// SAVE GAME MENU +// +menuitem_t SaveMenu[]= +{ + {1,"", M_SaveSelect,'1'}, + {1,"", M_SaveSelect,'2'}, + {1,"", M_SaveSelect,'3'}, + {1,"", M_SaveSelect,'4'}, + {1,"", M_SaveSelect,'5'}, + {1,"", M_SaveSelect,'6'} +}; + +menu_t SaveDef = +{ + load_end, + &MainDef, + SaveMenu, + M_DrawSave, + 80,54, + 0 +}; + + +// +// M_ReadSaveStrings +// read the strings from the savegame files +// +void M_ReadSaveStrings(void) +{ + FILE *handle; + int i; + char name[256]; + + for (i = 0;i < load_end;i++) + { + int retval; + M_StringCopy(name, P_SaveGameFile(i), sizeof(name)); + + handle = M_fopen(name, "rb"); + if (handle == NULL) + { + M_StringCopy(savegamestrings[i], EMPTYSTRING, SAVESTRINGSIZE); + LoadMenu[i].status = 0; + continue; + } + retval = fread(&savegamestrings[i], 1, SAVESTRINGSIZE, handle); + fclose(handle); + LoadMenu[i].status = retval == SAVESTRINGSIZE; + } +} + + +// +// M_LoadGame & Cie. +// +void M_DrawLoad(void) +{ + int i; + + V_DrawPatchDirect(72, 28, + W_CacheLumpName(DEH_String("M_LOADG"), PU_CACHE)); + + for (i = 0;i < load_end; i++) + { + M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); + M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + } +} + + + +// +// Draw border for the savegame description +// +void M_DrawSaveLoadBorder(int x,int y) +{ + int i; + + V_DrawPatchDirect(x - 8, y + 7, + W_CacheLumpName(DEH_String("M_LSLEFT"), PU_CACHE)); + + for (i = 0;i < 24;i++) + { + V_DrawPatchDirect(x, y + 7, + W_CacheLumpName(DEH_String("M_LSCNTR"), PU_CACHE)); + x += 8; + } + + V_DrawPatchDirect(x, y + 7, + W_CacheLumpName(DEH_String("M_LSRGHT"), PU_CACHE)); +} + + + +// +// User wants to load this game +// +void M_LoadSelect(int choice) +{ + char name[256]; + + M_StringCopy(name, P_SaveGameFile(choice), sizeof(name)); + + G_LoadGame (name); + M_ClearMenus (); +} + +// +// Selected from DOOM menu +// +void M_LoadGame (int choice) +{ + if (netgame) + { + M_StartMessage(DEH_String(LOADNET),NULL,false); + return; + } + + M_SetupNextMenu(&LoadDef); + M_ReadSaveStrings(); +} + + +// +// M_SaveGame & Cie. +// +void M_DrawSave(void) +{ + int i; + + V_DrawPatchDirect(72, 28, W_CacheLumpName(DEH_String("M_SAVEG"), PU_CACHE)); + for (i = 0;i < load_end; i++) + { + M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); + M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + } + + if (saveStringEnter) + { + i = M_StringWidth(savegamestrings[saveSlot]); + M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_"); + } +} + +// +// M_Responder calls this when user is finished +// +void M_DoSave(int slot) +{ + G_SaveGame (slot,savegamestrings[slot]); + M_ClearMenus (); + + // PICK QUICKSAVE SLOT YET? + if (quickSaveSlot == -2) + quickSaveSlot = slot; +} + +// +// Generate a default save slot name when the user saves to +// an empty slot via the joypad. +// +static void SetDefaultSaveName(int slot) +{ + // map from IWAD or PWAD? + if (W_IsIWADLump(maplumpinfo) && strcmp(savegamedir, "")) + { + M_snprintf(savegamestrings[itemOn], SAVESTRINGSIZE, + "%s", maplumpinfo->name); + } + else + { + char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo)); + char *ext = strrchr(wadname, '.'); + + if (ext != NULL) + { + *ext = '\0'; + } + + M_snprintf(savegamestrings[itemOn], SAVESTRINGSIZE, + "%s (%s)", maplumpinfo->name, + wadname); + free(wadname); + } + M_ForceUppercase(savegamestrings[itemOn]); + joypadSave = false; +} + +// +// User wants to save. Start string input for M_Responder +// +void M_SaveSelect(int choice) +{ + int x, y; + + // we are going to be intercepting all chars + saveStringEnter = 1; + + // We need to turn on text input: + x = LoadDef.x - 11; + y = LoadDef.y + choice * LINEHEIGHT - 4; + I_StartTextInput(x, y, x + 8 + 24 * 8 + 8, y + LINEHEIGHT - 2); + + saveSlot = choice; + M_StringCopy(saveOldString,savegamestrings[choice], SAVESTRINGSIZE); + if (!strcmp(savegamestrings[choice], EMPTYSTRING)) + { + savegamestrings[choice][0] = 0; + + if (joypadSave) + { + SetDefaultSaveName(choice); + } + } + saveCharIndex = strlen(savegamestrings[choice]); +} + +// +// Selected from DOOM menu +// +void M_SaveGame (int choice) +{ + if (!usergame) + { + M_StartMessage(DEH_String(SAVEDEAD),NULL,false); + return; + } + + if (gamestate != GS_LEVEL) + return; + + M_SetupNextMenu(&SaveDef); + M_ReadSaveStrings(); +} + + + +// +// M_QuickSave +// +static char tempstring[90]; + +void M_QuickSaveResponse(int key) +{ + if (key == key_menu_confirm) + { + M_DoSave(quickSaveSlot); + S_StartSound(NULL,sfx_swtchx); + } +} + +void M_QuickSave(void) +{ + if (!usergame) + { + S_StartSound(NULL,sfx_oof); + return; + } + + if (gamestate != GS_LEVEL) + return; + + if (quickSaveSlot < 0) + { + M_StartControlPanel(); + M_ReadSaveStrings(); + M_SetupNextMenu(&SaveDef); + quickSaveSlot = -2; // means to pick a slot now + return; + } + DEH_snprintf(tempstring, sizeof(tempstring), + QSPROMPT, savegamestrings[quickSaveSlot]); + M_StartMessage(tempstring, M_QuickSaveResponse, true); +} + + + +// +// M_QuickLoad +// +void M_QuickLoadResponse(int key) +{ + if (key == key_menu_confirm) + { + M_LoadSelect(quickSaveSlot); + S_StartSound(NULL,sfx_swtchx); + } +} + + +void M_QuickLoad(void) +{ + if (netgame) + { + M_StartMessage(DEH_String(QLOADNET),NULL,false); + return; + } + + if (quickSaveSlot < 0) + { + M_StartMessage(DEH_String(QSAVESPOT),NULL,false); + return; + } + DEH_snprintf(tempstring, sizeof(tempstring), + QLPROMPT, savegamestrings[quickSaveSlot]); + M_StartMessage(tempstring, M_QuickLoadResponse, true); +} + + + + +// +// Read This Menus +// Had a "quick hack to fix romero bug" +// +void M_DrawReadThis1(void) +{ + inhelpscreens = true; + + V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP2"), PU_CACHE)); +} + + + +// +// Read This Menus - optional second page. +// +void M_DrawReadThis2(void) +{ + inhelpscreens = true; + + // We only ever draw the second page if this is + // gameversion == exe_doom_1_9 and gamemode == registered + + V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE)); +} + +void M_DrawReadThisCommercial(void) +{ + inhelpscreens = true; + + V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP"), PU_CACHE)); +} + + +// +// Change Sfx & Music volumes +// +void M_DrawSound(void) +{ + V_DrawPatchDirect (60, 38, W_CacheLumpName(DEH_String("M_SVOL"), PU_CACHE)); + + M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), + 16,sfxVolume); + + M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), + 16,musicVolume); +} + +void M_Sound(int choice) +{ + M_SetupNextMenu(&SoundDef); +} + +void M_SfxVol(int choice) +{ + switch(choice) + { + case 0: + if (sfxVolume) + sfxVolume--; + break; + case 1: + if (sfxVolume < 15) + sfxVolume++; + break; + } + + S_SetSfxVolume(sfxVolume * 8); +} + +void M_MusicVol(int choice) +{ + switch(choice) + { + case 0: + if (musicVolume) + musicVolume--; + break; + case 1: + if (musicVolume < 15) + musicVolume++; + break; + } + + S_SetMusicVolume(musicVolume * 8); +} + + + + +// +// M_DrawMainMenu +// +void M_DrawMainMenu(void) +{ + V_DrawPatchDirect(94, 2, + W_CacheLumpName(DEH_String("M_DOOM"), PU_CACHE)); +} + + + + +// +// M_NewGame +// +void M_DrawNewGame(void) +{ + V_DrawPatchDirect(96, 14, W_CacheLumpName(DEH_String("M_NEWG"), PU_CACHE)); + V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_SKILL"), PU_CACHE)); +} + +void M_NewGame(int choice) +{ + if (netgame && !demoplayback) + { + M_StartMessage(DEH_String(NEWGAME),NULL,false); + return; + } + + // Chex Quest disabled the episode select screen, as did Doom II. + + if (gamemode == commercial || gameversion == exe_chex) + M_SetupNextMenu(&NewDef); + else + M_SetupNextMenu(&EpiDef); +} + + +// +// M_Episode +// +int epi; + +void M_DrawEpisode(void) +{ + V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_EPISOD"), PU_CACHE)); +} + +void M_VerifyNightmare(int key) +{ + if (key != key_menu_confirm) + return; + + G_DeferedInitNew(nightmare,epi+1,1); + M_ClearMenus (); +} + +void M_ChooseSkill(int choice) +{ + if (choice == nightmare) + { + M_StartMessage(DEH_String(NIGHTMARE),M_VerifyNightmare,true); + return; + } + + G_DeferedInitNew(choice,epi+1,1); + M_ClearMenus (); +} + +void M_Episode(int choice) +{ + if ( (gamemode == shareware) + && choice) + { + M_StartMessage(DEH_String(SWSTRING),NULL,false); + M_SetupNextMenu(&ReadDef1); + return; + } + + epi = choice; + M_SetupNextMenu(&NewDef); +} + + + +// +// M_Options +// +static const char *detailNames[2] = {"M_GDHIGH","M_GDLOW"}; +static const char *msgNames[2] = {"M_MSGOFF","M_MSGON"}; + +void M_DrawOptions(void) +{ + V_DrawPatchDirect(108, 15, W_CacheLumpName(DEH_String("M_OPTTTL"), + PU_CACHE)); + + V_DrawPatchDirect(OptionsDef.x + 175, OptionsDef.y + LINEHEIGHT * detail, + W_CacheLumpName(DEH_String(detailNames[detailLevel]), + PU_CACHE)); + + V_DrawPatchDirect(OptionsDef.x + 120, OptionsDef.y + LINEHEIGHT * messages, + W_CacheLumpName(DEH_String(msgNames[showMessages]), + PU_CACHE)); + + M_DrawThermo(OptionsDef.x, OptionsDef.y + LINEHEIGHT * (mousesens + 1), + 10, mouseSensitivity); + + M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), + 9,screenSize); +} + +void M_Options(int choice) +{ + M_SetupNextMenu(&OptionsDef); +} + + + +// +// Toggle messages on/off +// +void M_ChangeMessages(int choice) +{ + // warning: unused parameter `int choice' + choice = 0; + showMessages = 1 - showMessages; + + if (!showMessages) + players[consoleplayer].message = DEH_String(MSGOFF); + else + players[consoleplayer].message = DEH_String(MSGON); + + message_dontfuckwithme = true; +} + + +// +// M_EndGame +// +void M_EndGameResponse(int key) +{ + if (key != key_menu_confirm) + return; + + currentMenu->lastOn = itemOn; + M_ClearMenus (); + D_StartTitle (); +} + +void M_EndGame(int choice) +{ + choice = 0; + if (!usergame) + { + S_StartSound(NULL,sfx_oof); + return; + } + + if (netgame) + { + M_StartMessage(DEH_String(NETEND),NULL,false); + return; + } + + M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true); +} + + + + +// +// M_ReadThis +// +void M_ReadThis(int choice) +{ + choice = 0; + M_SetupNextMenu(&ReadDef1); +} + +void M_ReadThis2(int choice) +{ + choice = 0; + M_SetupNextMenu(&ReadDef2); +} + +void M_FinishReadThis(int choice) +{ + choice = 0; + M_SetupNextMenu(&MainDef); +} + + + + +// +// M_QuitDOOM +// +int quitsounds[8] = +{ + sfx_pldeth, + sfx_dmpain, + sfx_popain, + sfx_slop, + sfx_telept, + sfx_posit1, + sfx_posit3, + sfx_sgtatk +}; + +int quitsounds2[8] = +{ + sfx_vilact, + sfx_getpow, + sfx_boscub, + sfx_slop, + sfx_skeswg, + sfx_kntdth, + sfx_bspact, + sfx_sgtatk +}; + + + +void M_QuitResponse(int key) +{ + if (key != key_menu_confirm) + return; + if (!netgame) + { + if (gamemode == commercial) + S_StartSound(NULL,quitsounds2[(gametic>>2)&7]); + else + S_StartSound(NULL,quitsounds[(gametic>>2)&7]); + I_WaitVBL(105); + } + I_Quit (); +} + + +static const char *M_SelectEndMessage(void) +{ + const char **endmsg; + + if (logical_gamemission == doom) + { + // Doom 1 + + endmsg = doom1_endmsg; + } + else + { + // Doom 2 + + endmsg = doom2_endmsg; + } + + return endmsg[gametic % NUM_QUITMESSAGES]; +} + + +void M_QuitDOOM(int choice) +{ + DEH_snprintf(endstring, sizeof(endstring), "%s\n\n" DOSY, + DEH_String(M_SelectEndMessage())); + + M_StartMessage(endstring,M_QuitResponse,true); +} + + + + +void M_ChangeSensitivity(int choice) +{ + switch(choice) + { + case 0: + if (mouseSensitivity) + mouseSensitivity--; + break; + case 1: + if (mouseSensitivity < 9) + mouseSensitivity++; + break; + } +} + + + + +void M_ChangeDetail(int choice) +{ + choice = 0; + detailLevel = 1 - detailLevel; + + R_SetViewSize (screenblocks, detailLevel); + + if (!detailLevel) + players[consoleplayer].message = DEH_String(DETAILHI); + else + players[consoleplayer].message = DEH_String(DETAILLO); +} + + + + +void M_SizeDisplay(int choice) +{ + switch(choice) + { + case 0: + if (screenSize > 0) + { + screenblocks--; + screenSize--; + } + break; + case 1: + if (screenSize < 8) + { + screenblocks++; + screenSize++; + } + break; + } + + + R_SetViewSize (screenblocks, detailLevel); +} + + + + +// +// Menu Functions +// +void +M_DrawThermo +( int x, + int y, + int thermWidth, + int thermDot ) +{ + int xx; + int i; + + xx = x; + V_DrawPatchDirect(xx, y, W_CacheLumpName(DEH_String("M_THERML"), PU_CACHE)); + xx += 8; + for (i=0;i= HU_FONTSIZE) + w += 4; + else + w += SHORT (hu_font[c]->width); + } + + return w; +} + + + +// +// Find string height from hu_font chars +// +int M_StringHeight(const char* string) +{ + size_t i; + int h; + int height = SHORT(hu_font[0]->height); + + h = height; + for (i = 0;i < strlen(string);i++) + if (string[i] == '\n') + h += height; + + return h; +} + + +// +// Write a string using the hu_font +// +void +M_WriteText +( int x, + int y, + const char *string) +{ + int w; + const char *ch; + int c; + int cx; + int cy; + + + ch = string; + cx = x; + cy = y; + + while(1) + { + c = *ch++; + if (!c) + break; + if (c == '\n') + { + cx = x; + cy += 12; + continue; + } + + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c>= HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + if (cx+w > SCREENWIDTH) + break; + V_DrawPatchDirect(cx, cy, hu_font[c]); + cx+=w; + } +} + +// These keys evaluate to a "null" key in Vanilla Doom that allows weird +// jumping in the menus. Preserve this behavior for accuracy. + +static boolean IsNullKey(int key) +{ + return key == KEY_PAUSE || key == KEY_CAPSLOCK + || key == KEY_SCRLCK || key == KEY_NUMLOCK; +} + +// +// CONTROL PANEL +// + +// +// M_Responder +// +boolean M_Responder (event_t* ev) +{ + int ch; + int key; + int i; + static int mousewait = 0; + static int mousey = 0; + static int lasty = 0; + static int mousex = 0; + static int lastx = 0; + int dir; + + // In testcontrols mode, none of the function keys should do anything + // - the only key is escape to quit. + + if (testcontrols) + { + if (ev->type == ev_quit + || (ev->type == ev_keydown + && (ev->data1 == key_menu_activate || ev->data1 == key_menu_quit))) + { + I_Quit(); + return true; + } + + return false; + } + + // "close" button pressed on window? + if (ev->type == ev_quit) + { + // First click on close button = bring up quit confirm message. + // Second click on close button = confirm quit + + if (menuactive && messageToPrint && messageRoutine == M_QuitResponse) + { + M_QuitResponse(key_menu_confirm); + } + else + { + S_StartSound(NULL,sfx_swtchn); + M_QuitDOOM(0); + } + + return true; + } + + // key is the key pressed, ch is the actual character typed + + ch = 0; + key = -1; + + if (ev->type == ev_joystick) + { + // Simulate key presses from joystick events to interact with the menu. + + if (menuactive) + { + if (JOY_GET_DPAD(ev->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_DPAD(ev->data6); + } + else if (JOY_GET_LSTICK(ev->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_LSTICK(ev->data6); + } + else + { + dir = JOY_GET_RSTICK(ev->data6); + } + + if (dir & JOY_DIR_UP) + { + key = key_menu_up; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_DOWN) + { + key = key_menu_down; + joywait = I_GetTime() + 5; + } + if (dir & JOY_DIR_LEFT) + { + key = key_menu_left; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_RIGHT) + { + key = key_menu_right; + joywait = I_GetTime() + 5; + } + +#define JOY_BUTTON_MAPPED(x) ((x) >= 0) +#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (ev->data1 & (1 << (x))) != 0) + + if (JOY_BUTTON_PRESSED(joybfire)) + { + // Simulate a 'Y' keypress when Doom show a Y/N dialog with Fire button. + if (messageToPrint && messageNeedsInput) + { + key = key_menu_confirm; + } + // Simulate pressing "Enter" when we are supplying a save slot name + else if (saveStringEnter) + { + key = KEY_ENTER; + } + else + { + // if selecting a save slot via joypad, set a flag + if (currentMenu == &SaveDef) + { + joypadSave = true; + } + key = key_menu_forward; + } + joywait = I_GetTime() + 5; + } + if (JOY_BUTTON_PRESSED(joybuse)) + { + // Simulate a 'N' keypress when Doom show a Y/N dialog with Use button. + if (messageToPrint && messageNeedsInput) + { + key = key_menu_abort; + } + // If user was entering a save name, back out + else if (saveStringEnter) + { + key = KEY_ESCAPE; + } + else + { + key = key_menu_back; + } + joywait = I_GetTime() + 5; + } + } + if (JOY_BUTTON_PRESSED(joybmenu)) + { + key = key_menu_activate; + joywait = I_GetTime() + 5; + } + } + else + { + if (ev->type == ev_mouse && mousewait < I_GetTime() && menuactive) + { + mousey += ev->data3; + if (mousey < lasty-30) + { + key = key_menu_down; + mousewait = I_GetTime() + 5; + mousey = lasty -= 30; + } + else if (mousey > lasty+30) + { + key = key_menu_up; + mousewait = I_GetTime() + 5; + mousey = lasty += 30; + } + + mousex += ev->data2; + if (mousex < lastx-30) + { + key = key_menu_left; + mousewait = I_GetTime() + 5; + mousex = lastx -= 30; + } + else if (mousex > lastx+30) + { + key = key_menu_right; + mousewait = I_GetTime() + 5; + mousex = lastx += 30; + } + + if (ev->data1&1) + { + key = key_menu_forward; + mousewait = I_GetTime() + 15; + } + + if (ev->data1&2) + { + key = key_menu_back; + mousewait = I_GetTime() + 15; + } + } + else + { + if (ev->type == ev_keydown) + { + key = ev->data1; + ch = ev->data2; + } + } + } + + if (key == -1) + return false; + + // Save Game string input + if (saveStringEnter) + { + switch(key) + { + case KEY_BACKSPACE: + if (saveCharIndex > 0) + { + saveCharIndex--; + savegamestrings[saveSlot][saveCharIndex] = 0; + } + break; + + case KEY_ESCAPE: + saveStringEnter = 0; + I_StopTextInput(); + M_StringCopy(savegamestrings[saveSlot], saveOldString, + SAVESTRINGSIZE); + break; + + case KEY_ENTER: + saveStringEnter = 0; + I_StopTextInput(); + if (savegamestrings[saveSlot][0]) + M_DoSave(saveSlot); + break; + + default: + // Savegame name entry. This is complicated. + // Vanilla has a bug where the shift key is ignored when entering + // a savegame name. If vanilla_keyboard_mapping is on, we want + // to emulate this bug by using ev->data1. But if it's turned off, + // it implies the user doesn't care about Vanilla emulation: + // instead, use ev->data3 which gives the fully-translated and + // modified key input. + + if (ev->type != ev_keydown) + { + break; + } + if (vanilla_keyboard_mapping) + { + ch = ev->data1; + } + else + { + ch = ev->data3; + } + + ch = toupper(ch); + + if (ch != ' ' + && (ch - HU_FONTSTART < 0 || ch - HU_FONTSTART >= HU_FONTSIZE)) + { + break; + } + + if (ch >= 32 && ch <= 127 && + saveCharIndex < SAVESTRINGSIZE-1 && + M_StringWidth(savegamestrings[saveSlot]) < + (SAVESTRINGSIZE-2)*8) + { + savegamestrings[saveSlot][saveCharIndex++] = ch; + savegamestrings[saveSlot][saveCharIndex] = 0; + } + break; + } + return true; + } + + // Take care of any messages that need input + if (messageToPrint) + { + if (messageNeedsInput) + { + if (key != ' ' && key != KEY_ESCAPE + && key != key_menu_confirm && key != key_menu_abort) + { + return false; + } + } + + menuactive = messageLastMenuActive; + messageToPrint = 0; + if (messageRoutine) + messageRoutine(key); + + menuactive = false; + S_StartSound(NULL,sfx_swtchx); + return true; + } + + if ((devparm && key == key_menu_help) || + (key != 0 && key == key_menu_screenshot)) + { + G_ScreenShot (); + return true; + } + + // F-Keys + if (!menuactive) + { + if (key == key_menu_decscreen) // Screen size down + { + if (automapactive || chat_on) + return false; + M_SizeDisplay(0); + S_StartSound(NULL,sfx_stnmov); + return true; + } + else if (key == key_menu_incscreen) // Screen size up + { + if (automapactive || chat_on) + return false; + M_SizeDisplay(1); + S_StartSound(NULL,sfx_stnmov); + return true; + } + else if (key == key_menu_help) // Help key + { + M_StartControlPanel (); + + if (gameversion >= exe_ultimate) + currentMenu = &ReadDef2; + else + currentMenu = &ReadDef1; + + itemOn = 0; + S_StartSound(NULL,sfx_swtchn); + return true; + } + else if (key == key_menu_save) // Save + { + M_StartControlPanel(); + S_StartSound(NULL,sfx_swtchn); + M_SaveGame(0); + return true; + } + else if (key == key_menu_load) // Load + { + M_StartControlPanel(); + S_StartSound(NULL,sfx_swtchn); + M_LoadGame(0); + return true; + } + else if (key == key_menu_volume) // Sound Volume + { + M_StartControlPanel (); + currentMenu = &SoundDef; + itemOn = sfx_vol; + S_StartSound(NULL,sfx_swtchn); + return true; + } + else if (key == key_menu_detail) // Detail toggle + { + M_ChangeDetail(0); + S_StartSound(NULL,sfx_swtchn); + return true; + } + else if (key == key_menu_qsave) // Quicksave + { + S_StartSound(NULL,sfx_swtchn); + M_QuickSave(); + return true; + } + else if (key == key_menu_endgame) // End game + { + S_StartSound(NULL,sfx_swtchn); + M_EndGame(0); + return true; + } + else if (key == key_menu_messages) // Toggle messages + { + M_ChangeMessages(0); + S_StartSound(NULL,sfx_swtchn); + return true; + } + else if (key == key_menu_qload) // Quickload + { + S_StartSound(NULL,sfx_swtchn); + M_QuickLoad(); + return true; + } + else if (key == key_menu_quit) // Quit DOOM + { + S_StartSound(NULL,sfx_swtchn); + M_QuitDOOM(0); + return true; + } + else if (key == key_menu_gamma) // gamma toggle + { + usegamma++; + if (usegamma > 4) + usegamma = 0; + players[consoleplayer].message = DEH_String(gammamsg[usegamma]); + I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); + return true; + } + } + + // Pop-up menu? + if (!menuactive) + { + if (key == key_menu_activate) + { + M_StartControlPanel (); + S_StartSound(NULL,sfx_swtchn); + return true; + } + return false; + } + + // Keys usable within menu + + if (key == key_menu_down) + { + // Move down to next item + + do + { + if (itemOn+1 > currentMenu->numitems-1) + itemOn = 0; + else itemOn++; + S_StartSound(NULL,sfx_pstop); + } while(currentMenu->menuitems[itemOn].status==-1); + + return true; + } + else if (key == key_menu_up) + { + // Move back up to previous item + + do + { + if (!itemOn) + itemOn = currentMenu->numitems-1; + else itemOn--; + S_StartSound(NULL,sfx_pstop); + } while(currentMenu->menuitems[itemOn].status==-1); + + return true; + } + else if (key == key_menu_left) + { + // Slide slider left + + if (currentMenu->menuitems[itemOn].routine && + currentMenu->menuitems[itemOn].status == 2) + { + S_StartSound(NULL,sfx_stnmov); + currentMenu->menuitems[itemOn].routine(0); + } + return true; + } + else if (key == key_menu_right) + { + // Slide slider right + + if (currentMenu->menuitems[itemOn].routine && + currentMenu->menuitems[itemOn].status == 2) + { + S_StartSound(NULL,sfx_stnmov); + currentMenu->menuitems[itemOn].routine(1); + } + return true; + } + else if (key == key_menu_forward) + { + // Activate menu item + + if (currentMenu->menuitems[itemOn].routine && + currentMenu->menuitems[itemOn].status) + { + currentMenu->lastOn = itemOn; + if (currentMenu->menuitems[itemOn].status == 2) + { + currentMenu->menuitems[itemOn].routine(1); // right arrow + S_StartSound(NULL,sfx_stnmov); + } + else + { + currentMenu->menuitems[itemOn].routine(itemOn); + S_StartSound(NULL,sfx_pistol); + } + } + return true; + } + else if (key == key_menu_activate) + { + // Deactivate menu + + currentMenu->lastOn = itemOn; + M_ClearMenus (); + S_StartSound(NULL,sfx_swtchx); + return true; + } + else if (key == key_menu_back) + { + // Go back to previous menu + + currentMenu->lastOn = itemOn; + if (currentMenu->prevMenu) + { + currentMenu = currentMenu->prevMenu; + itemOn = currentMenu->lastOn; + S_StartSound(NULL,sfx_swtchn); + } + return true; + } + + // Keyboard shortcut? + // Vanilla Doom has a weird behavior where it jumps to the scroll bars + // when the certain keys are pressed, so emulate this. + + else if (ch != 0 || IsNullKey(key)) + { + for (i = itemOn+1;i < currentMenu->numitems;i++) + { + if (currentMenu->menuitems[i].alphaKey == ch) + { + itemOn = i; + S_StartSound(NULL,sfx_pstop); + return true; + } + } + + for (i = 0;i <= itemOn;i++) + { + if (currentMenu->menuitems[i].alphaKey == ch) + { + itemOn = i; + S_StartSound(NULL,sfx_pstop); + return true; + } + } + } + + return false; +} + + + +// +// M_StartControlPanel +// +void M_StartControlPanel (void) +{ + // intro might call this repeatedly + if (menuactive) + return; + + menuactive = 1; + currentMenu = &MainDef; // JDC + itemOn = currentMenu->lastOn; // JDC +} + +// Display OPL debug messages - hack for GENMIDI development. + +static void M_DrawOPLDev(void) +{ + char debug[1024]; + char *curr, *p; + int line; + + I_OPL_DevMessages(debug, sizeof(debug)); + curr = debug; + line = 0; + + for (;;) + { + p = strchr(curr, '\n'); + + if (p != NULL) + { + *p = '\0'; + } + + M_WriteText(0, line * 8, curr); + ++line; + + if (p == NULL) + { + break; + } + + curr = p + 1; + } +} + +// +// M_Drawer +// Called after the view has been rendered, +// but before it has been blitted. +// +void M_Drawer (void) +{ + static short x; + static short y; + unsigned int i; + unsigned int max; + char string[80]; + const char *name; + int start; + + inhelpscreens = false; + + // Horiz. & Vertically center string and print it. + if (messageToPrint) + { + start = 0; + y = SCREENHEIGHT/2 - M_StringHeight(messageString) / 2; + while (messageString[start] != '\0') + { + boolean foundnewline = false; + + for (i = 0; messageString[start + i] != '\0'; i++) + { + if (messageString[start + i] == '\n') + { + M_StringCopy(string, messageString + start, + sizeof(string)); + if (i < sizeof(string)) + { + string[i] = '\0'; + } + + foundnewline = true; + start += i + 1; + break; + } + } + + if (!foundnewline) + { + M_StringCopy(string, messageString + start, sizeof(string)); + start += strlen(string); + } + + x = SCREENWIDTH/2 - M_StringWidth(string) / 2; + M_WriteText(x, y, string); + y += SHORT(hu_font[0]->height); + } + + return; + } + + if (opldev) + { + M_DrawOPLDev(); + } + + if (!menuactive) + return; + + if (currentMenu->routine) + currentMenu->routine(); // call Draw routine + + // DRAW MENU + x = currentMenu->x; + y = currentMenu->y; + max = currentMenu->numitems; + + for (i=0;imenuitems[i].name); + + if (name[0] && W_CheckNumForName(name) > 0) + { + V_DrawPatchDirect (x, y, W_CacheLumpName(name, PU_CACHE)); + } + y += LINEHEIGHT; + } + + + // DRAW SKULL + V_DrawPatchDirect(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT, + W_CacheLumpName(DEH_String(skullName[whichSkull]), + PU_CACHE)); +} + + +// +// M_ClearMenus +// +void M_ClearMenus (void) +{ + menuactive = 0; + // if (!netgame && usergame && paused) + // sendpause = true; +} + + + + +// +// M_SetupNextMenu +// +void M_SetupNextMenu(menu_t *menudef) +{ + currentMenu = menudef; + itemOn = currentMenu->lastOn; +} + + +// +// M_Ticker +// +void M_Ticker (void) +{ + if (--skullAnimCounter <= 0) + { + whichSkull ^= 1; + skullAnimCounter = 8; + } +} + + +// +// M_Init +// +void M_Init (void) +{ + currentMenu = &MainDef; + menuactive = 0; + itemOn = currentMenu->lastOn; + whichSkull = 0; + skullAnimCounter = 10; + screenSize = screenblocks - 3; + messageToPrint = 0; + messageString = NULL; + messageLastMenuActive = menuactive; + quickSaveSlot = -1; + + // Here we could catch other version dependencies, + // like HELP1/2, and four episodes. + + // The same hacks were used in the original Doom EXEs. + + if (gameversion >= exe_ultimate) + { + MainMenu[readthis].routine = M_ReadThis2; + ReadDef2.prevMenu = NULL; + } + + if (gameversion >= exe_final && gameversion <= exe_final2) + { + ReadDef2.routine = M_DrawReadThisCommercial; + } + + if (gamemode == commercial) + { + MainMenu[readthis] = MainMenu[quitdoom]; + MainDef.numitems--; + MainDef.y += 8; + NewDef.prevMenu = &MainDef; + ReadDef1.routine = M_DrawReadThisCommercial; + ReadDef1.x = 330; + ReadDef1.y = 165; + ReadMenu1[rdthsempty1].routine = M_FinishReadThis; + } + + // Versions of doom.exe before the Ultimate Doom release only had + // three episodes; if we're emulating one of those then don't try + // to show episode four. If we are, then do show episode four + // (should crash if missing). + if (gameversion < exe_ultimate) + { + EpiDef.numitems--; + } + // chex.exe shows only one episode. + else if (gameversion == exe_chex) + { + EpiDef.numitems = 1; + } + + opldev = M_CheckParm("-opldev") > 0; +} + diff --git a/games/NXDoom/src/doom/m_menu.h b/games/NXDoom/src/doom/m_menu.h new file mode 100644 index 00000000000..2c7867f128b --- /dev/null +++ b/games/NXDoom/src/doom/m_menu.h @@ -0,0 +1,62 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Menu widget stuff, episode selection and such. +// + + +#ifndef __M_MENU__ +#define __M_MENU__ + + + +#include "d_event.h" + +// +// MENUS +// +// Called by main loop, +// saves config file and calls I_Quit when user exits. +// Even when the menu is not displayed, +// this can resize the view and change game parameters. +// Does all the real work of the menu interaction. +boolean M_Responder (event_t *ev); + + +// Called by main loop, +// only used for menu (skull cursor) animation. +void M_Ticker (void); + +// Called by main loop, +// draws the menus directly into the screen buffer. +void M_Drawer (void); + +// Called by D_DoomMain, +// loads the config file. +void M_Init (void); + +// Called by intro code to force menu up upon a keypress, +// does nothing if menu is already up. +void M_StartControlPanel (void); + + +extern int detailLevel; +extern int screenblocks; + +extern boolean inhelpscreens; +extern int showMessages; + + +#endif diff --git a/games/NXDoom/src/doom/m_random.c b/games/NXDoom/src/doom/m_random.c new file mode 100644 index 00000000000..b4f59b33f47 --- /dev/null +++ b/games/NXDoom/src/doom/m_random.c @@ -0,0 +1,72 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Random number LUT. +// + +// +// M_Random +// Returns a 0-255 number +// + +static const unsigned char rndtable[256] = { + 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 , + 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 , + 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 , + 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 , + 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 , + 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 , + 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 , + 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 , + 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 , + 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 , + 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 , + 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 , + 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 , + 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 , + 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 , + 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 , + 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 , + 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 , + 120, 163, 236, 249 +}; + +int rndindex = 0; +int prndindex = 0; + +// Which one is deterministic? +int P_Random (void) +{ + prndindex = (prndindex+1)&0xff; + return rndtable[prndindex]; +} + +int M_Random (void) +{ + rndindex = (rndindex+1)&0xff; + return rndtable[rndindex]; +} + +void M_ClearRandom (void) +{ + rndindex = prndindex = 0; +} + +// inspired by the same routine in Eternity, thanks haleyjd +int P_SubRandom (void) +{ + int r = P_Random(); + return r - P_Random(); +} diff --git a/games/NXDoom/src/doom/m_random.h b/games/NXDoom/src/doom/m_random.h new file mode 100644 index 00000000000..902691f1d5f --- /dev/null +++ b/games/NXDoom/src/doom/m_random.h @@ -0,0 +1,40 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __M_RANDOM__ +#define __M_RANDOM__ + + +#include "doomtype.h" + + +// Returns a number from 0 to 255, +// from a lookup table. +int M_Random (void); + +// As M_Random, but used only by the play simulation. +int P_Random (void); + +// Fix randoms for demos. +void M_ClearRandom (void); + +// Defined version of P_Random() - P_Random() +int P_SubRandom (void); + +#endif diff --git a/games/NXDoom/src/doom/p_ceilng.c b/games/NXDoom/src/doom/p_ceilng.c new file mode 100644 index 00000000000..d1e61c898b4 --- /dev/null +++ b/games/NXDoom/src/doom/p_ceilng.c @@ -0,0 +1,324 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising) +// + + + +#include "z_zone.h" +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "sounds.h" + +// +// CEILINGS +// + + +ceiling_t* activeceilings[MAXCEILINGS]; + + +// +// T_MoveCeiling +// + +void T_MoveCeiling (ceiling_t* ceiling) +{ + result_e res; + + switch(ceiling->direction) + { + case 0: + // IN STASIS + break; + case 1: + // UP + res = T_MovePlane(ceiling->sector, + ceiling->speed, + ceiling->topheight, + false,1,ceiling->direction); + + if (!(leveltime&7)) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + break; + default: + S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); + // ? + break; + } + } + + if (res == pastdest) + { + switch(ceiling->type) + { + case raiseToHighest: + P_RemoveActiveCeiling(ceiling); + break; + + case silentCrushAndRaise: + S_StartSound(&ceiling->sector->soundorg, sfx_pstop); + case fastCrushAndRaise: + case crushAndRaise: + ceiling->direction = -1; + break; + + default: + break; + } + + } + break; + + case -1: + // DOWN + res = T_MovePlane(ceiling->sector, + ceiling->speed, + ceiling->bottomheight, + ceiling->crush,1,ceiling->direction); + + if (!(leveltime&7)) + { + switch(ceiling->type) + { + case silentCrushAndRaise: break; + default: + S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); + } + } + + if (res == pastdest) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + S_StartSound(&ceiling->sector->soundorg, sfx_pstop); + case crushAndRaise: + ceiling->speed = CEILSPEED; + case fastCrushAndRaise: + ceiling->direction = 1; + break; + + case lowerAndCrush: + case lowerToFloor: + P_RemoveActiveCeiling(ceiling); + break; + + default: + break; + } + } + else // ( res != pastdest ) + { + if (res == crushed) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + case crushAndRaise: + case lowerAndCrush: + ceiling->speed = CEILSPEED / 8; + break; + + default: + break; + } + } + } + break; + } +} + + +// +// EV_DoCeiling +// Move a ceiling up/down and all around! +// +int +EV_DoCeiling +( line_t* line, + ceiling_e type ) +{ + int secnum; + int rtn; + sector_t* sec; + ceiling_t* ceiling; + + secnum = -1; + rtn = 0; + + // Reactivate in-stasis ceilings...for certain types. + switch(type) + { + case fastCrushAndRaise: + case silentCrushAndRaise: + case crushAndRaise: + P_ActivateInStasisCeiling(line); + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + // new door thinker + rtn = 1; + ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); + P_AddThinker (&ceiling->thinker); + sec->specialdata = ceiling; + ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = false; + + switch(type) + { + case fastCrushAndRaise: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); + ceiling->direction = -1; + ceiling->speed = CEILSPEED * 2; + break; + + case silentCrushAndRaise: + case crushAndRaise: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + case lowerAndCrush: + case lowerToFloor: + ceiling->bottomheight = sec->floorheight; + if (type != lowerToFloor) + ceiling->bottomheight += 8*FRACUNIT; + ceiling->direction = -1; + ceiling->speed = CEILSPEED; + break; + + case raiseToHighest: + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + ceiling->speed = CEILSPEED; + break; + } + + ceiling->tag = sec->tag; + ceiling->type = type; + P_AddActiveCeiling(ceiling); + } + return rtn; +} + + +// +// Add an active ceiling +// +void P_AddActiveCeiling(ceiling_t* c) +{ + int i; + + for (i = 0; i < MAXCEILINGS;i++) + { + if (activeceilings[i] == NULL) + { + activeceilings[i] = c; + return; + } + } +} + + + +// +// Remove a ceiling's thinker +// +void P_RemoveActiveCeiling(ceiling_t* c) +{ + int i; + + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] == c) + { + activeceilings[i]->sector->specialdata = NULL; + P_RemoveThinker (&activeceilings[i]->thinker); + activeceilings[i] = NULL; + break; + } + } +} + + + +// +// Restart a ceiling that's in-stasis +// +void P_ActivateInStasisCeiling(line_t* line) +{ + int i; + + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] + && (activeceilings[i]->tag == line->tag) + && (activeceilings[i]->direction == 0)) + { + activeceilings[i]->direction = activeceilings[i]->olddirection; + activeceilings[i]->thinker.function.acp1 + = (actionf_p1)T_MoveCeiling; + } + } +} + + + +// +// EV_CeilingCrushStop +// Stop a ceiling from crushing! +// +int EV_CeilingCrushStop(line_t *line) +{ + int i; + int rtn; + + rtn = 0; + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] + && (activeceilings[i]->tag == line->tag) + && (activeceilings[i]->direction != 0)) + { + activeceilings[i]->olddirection = activeceilings[i]->direction; + activeceilings[i]->thinker.function.acv = (actionf_v)NULL; + activeceilings[i]->direction = 0; // in-stasis + rtn = 1; + } + } + + + return rtn; +} diff --git a/games/NXDoom/src/doom/p_doors.c b/games/NXDoom/src/doom/p_doors.c new file mode 100644 index 00000000000..b0947248abe --- /dev/null +++ b/games/NXDoom/src/doom/p_doors.c @@ -0,0 +1,779 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Door animation code (opening/closing) +// + + + +#include "z_zone.h" +#include "doomdef.h" +#include "deh_main.h" +#include "p_local.h" +#include "i_system.h" + +#include "s_sound.h" + + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +#if 0 +// +// Sliding door frame information +// +slidename_t slideFrameNames[MAXSLIDEDOORS] = +{ + {"GDOORF1","GDOORF2","GDOORF3","GDOORF4", // front + "GDOORB1","GDOORB2","GDOORB3","GDOORB4"}, // back + + {"\0","\0","\0","\0"} +}; +#endif + + +// +// VERTICAL DOORS +// + +// +// T_VerticalDoor +// +void T_VerticalDoor (vldoor_t* door) +{ + result_e res; + + switch(door->direction) + { + case 0: + // WAITING + if (!--door->topcountdown) + { + switch(door->type) + { + case vld_blazeRaise: + door->direction = -1; // time to go back down + S_StartSound(&door->sector->soundorg, sfx_bdcls); + break; + + case vld_normal: + door->direction = -1; // time to go back down + S_StartSound(&door->sector->soundorg, sfx_dorcls); + break; + + case vld_close30ThenOpen: + door->direction = 1; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + + default: + break; + } + } + break; + + case 2: + // INITIAL WAIT + if (!--door->topcountdown) + { + switch(door->type) + { + case vld_raiseIn5Mins: + door->direction = 1; + door->type = vld_normal; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + + default: + break; + } + } + break; + + case -1: + // DOWN + res = T_MovePlane(door->sector, + door->speed, + door->sector->floorheight, + false,1,door->direction); + if (res == pastdest) + { + switch(door->type) + { + case vld_blazeRaise: + case vld_blazeClose: + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); // unlink and free + S_StartSound(&door->sector->soundorg, sfx_bdcls); + break; + + case vld_normal: + case vld_close: + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); // unlink and free + break; + + case vld_close30ThenOpen: + door->direction = 0; + door->topcountdown = TICRATE*30; + break; + + default: + break; + } + } + else if (res == crushed) + { + switch(door->type) + { + case vld_blazeClose: + case vld_close: // DO NOT GO BACK UP! + break; + + default: + door->direction = 1; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + } + } + break; + + case 1: + // UP + res = T_MovePlane(door->sector, + door->speed, + door->topheight, + false,1,door->direction); + + if (res == pastdest) + { + switch(door->type) + { + case vld_blazeRaise: + case vld_normal: + door->direction = 0; // wait at top + door->topcountdown = door->topwait; + break; + + case vld_close30ThenOpen: + case vld_blazeOpen: + case vld_open: + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); // unlink and free + break; + + default: + break; + } + } + break; + } +} + + +// +// EV_DoLockedDoor +// Move a locked door up/down +// + +int +EV_DoLockedDoor +( line_t* line, + vldoor_e type, + mobj_t* thing ) +{ + player_t* p; + + p = thing->player; + + if (!p) + return 0; + + switch(line->special) + { + case 99: // Blue Lock + case 133: + if (!p->cards[it_bluecard] && !p->cards[it_blueskull]) + { + p->message = DEH_String(PD_BLUEO); + S_StartSound(NULL,sfx_oof); + return 0; + } + break; + + case 134: // Red Lock + case 135: + if (!p->cards[it_redcard] && !p->cards[it_redskull]) + { + p->message = DEH_String(PD_REDO); + S_StartSound(NULL,sfx_oof); + return 0; + } + break; + + case 136: // Yellow Lock + case 137: + if (!p->cards[it_yellowcard] && + !p->cards[it_yellowskull]) + { + p->message = DEH_String(PD_YELLOWO); + S_StartSound(NULL,sfx_oof); + return 0; + } + break; + } + + return EV_DoDoor(line,type); +} + + +int +EV_DoDoor +( line_t* line, + vldoor_e type ) +{ + int secnum,rtn; + sector_t* sec; + vldoor_t* door; + + secnum = -1; + rtn = 0; + + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + + // new door thinker + rtn = 1; + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + + door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; + door->sector = sec; + door->type = type; + door->topwait = VDOORWAIT; + door->speed = VDOORSPEED; + + switch(type) + { + case vld_blazeClose: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->direction = -1; + door->speed = VDOORSPEED * 4; + S_StartSound(&door->sector->soundorg, sfx_bdcls); + break; + + case vld_close: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->direction = -1; + S_StartSound(&door->sector->soundorg, sfx_dorcls); + break; + + case vld_close30ThenOpen: + door->topheight = sec->ceilingheight; + door->direction = -1; + S_StartSound(&door->sector->soundorg, sfx_dorcls); + break; + + case vld_blazeRaise: + case vld_blazeOpen: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->speed = VDOORSPEED * 4; + if (door->topheight != sec->ceilingheight) + S_StartSound(&door->sector->soundorg, sfx_bdopn); + break; + + case vld_normal: + case vld_open: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + if (door->topheight != sec->ceilingheight) + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + + default: + break; + } + + } + return rtn; +} + + +// +// EV_VerticalDoor : open a door manually, no tag value +// +void +EV_VerticalDoor +( line_t* line, + mobj_t* thing ) +{ + player_t* player; + sector_t* sec; + vldoor_t* door; + int side; + + side = 0; // only front sides can be used + + // Check for locks + player = thing->player; + + switch(line->special) + { + case 26: // Blue Lock + case 32: + if ( !player ) + return; + + if (!player->cards[it_bluecard] && !player->cards[it_blueskull]) + { + player->message = DEH_String(PD_BLUEK); + S_StartSound(NULL,sfx_oof); + return; + } + break; + + case 27: // Yellow Lock + case 34: + if ( !player ) + return; + + if (!player->cards[it_yellowcard] && + !player->cards[it_yellowskull]) + { + player->message = DEH_String(PD_YELLOWK); + S_StartSound(NULL,sfx_oof); + return; + } + break; + + case 28: // Red Lock + case 33: + if ( !player ) + return; + + if (!player->cards[it_redcard] && !player->cards[it_redskull]) + { + player->message = DEH_String(PD_REDK); + S_StartSound(NULL,sfx_oof); + return; + } + break; + } + + // if the sector has an active thinker, use it + + if (line->sidenum[side^1] == -1) + { + I_Error("EV_VerticalDoor: DR special type on 1-sided linedef"); + } + + sec = sides[ line->sidenum[side^1]] .sector; + + if (sec->specialdata) + { + door = sec->specialdata; + switch(line->special) + { + case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s + case 26: + case 27: + case 28: + case 117: + if (door->direction == -1) + door->direction = 1; // go back up + else + { + if (!thing->player) + return; // JDC: bad guys never close doors + + // When is a door not a door? + // In Vanilla, door->direction is set, even though + // "specialdata" might not actually point at a door. + + if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor) + { + door->direction = -1; // start going down immediately + } + else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise) + { + // Erm, this is a plat, not a door. + // This notably causes a problem in ep1-0500.lmp where + // a plat and a door are cross-referenced; the door + // doesn't open on 64-bit. + // The direction field in vldoor_t corresponds to the wait + // field in plat_t. Let's set that to -1 instead. + + plat_t *plat; + + plat = (plat_t *) door; + plat->wait = -1; + } + else + { + // This isn't a door OR a plat. Now we're in trouble. + + fprintf(stderr, "EV_VerticalDoor: Tried to close " + "something that wasn't a door.\n"); + + // Try closing it anyway. At least it will work on 32-bit + // machines. + + door->direction = -1; + } + } + return; + } + } + + // for proper sound + switch(line->special) + { + case 117: // BLAZING DOOR RAISE + case 118: // BLAZING DOOR OPEN + S_StartSound(&sec->soundorg,sfx_bdopn); + break; + + case 1: // NORMAL DOOR SOUND + case 31: + S_StartSound(&sec->soundorg,sfx_doropn); + break; + + default: // LOCKED DOOR SOUND + S_StartSound(&sec->soundorg,sfx_doropn); + break; + } + + + // new door thinker + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; + door->sector = sec; + door->direction = 1; + door->speed = VDOORSPEED; + door->topwait = VDOORWAIT; + + switch(line->special) + { + case 1: + case 26: + case 27: + case 28: + door->type = vld_normal; + break; + + case 31: + case 32: + case 33: + case 34: + door->type = vld_open; + line->special = 0; + break; + + case 117: // blazing door raise + door->type = vld_blazeRaise; + door->speed = VDOORSPEED*4; + break; + case 118: // blazing door open + door->type = vld_blazeOpen; + line->special = 0; + door->speed = VDOORSPEED*4; + break; + } + + // find the top and bottom of the movement range + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; +} + + +// +// Spawn a door that closes after 30 seconds +// +void P_SpawnDoorCloseIn30 (sector_t* sec) +{ + vldoor_t* door; + + door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + + P_AddThinker (&door->thinker); + + sec->specialdata = door; + sec->special = 0; + + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + door->sector = sec; + door->direction = 0; + door->type = vld_normal; + door->speed = VDOORSPEED; + door->topcountdown = 30 * TICRATE; +} + +// +// Spawn a door that opens after 5 minutes +// +void +P_SpawnDoorRaiseIn5Mins +( sector_t* sec, + int secnum ) +{ + vldoor_t* door; + + door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + + P_AddThinker (&door->thinker); + + sec->specialdata = door; + sec->special = 0; + + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + door->sector = sec; + door->direction = 2; + door->type = vld_raiseIn5Mins; + door->speed = VDOORSPEED; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->topwait = VDOORWAIT; + door->topcountdown = 5 * 60 * TICRATE; +} + + + +// UNUSED +// Separate into p_slidoor.c? + +#if 0 // ABANDONED TO THE MISTS OF TIME!!! +// +// EV_SlidingDoor : slide a door horizontally +// (animate midtexture, then set noblocking line) +// + + +slideframe_t slideFrames[MAXSLIDEDOORS]; + +void P_InitSlidingDoorFrames(void) +{ + int i; + int f1; + int f2; + int f3; + int f4; + + // DOOM II ONLY... + if ( gamemode != commercial) + return; + + for (i = 0;i < MAXSLIDEDOORS; i++) + { + if (!slideFrameNames[i].frontFrame1[0]) + break; + + f1 = R_TextureNumForName(slideFrameNames[i].frontFrame1); + f2 = R_TextureNumForName(slideFrameNames[i].frontFrame2); + f3 = R_TextureNumForName(slideFrameNames[i].frontFrame3); + f4 = R_TextureNumForName(slideFrameNames[i].frontFrame4); + + slideFrames[i].frontFrames[0] = f1; + slideFrames[i].frontFrames[1] = f2; + slideFrames[i].frontFrames[2] = f3; + slideFrames[i].frontFrames[3] = f4; + + f1 = R_TextureNumForName(slideFrameNames[i].backFrame1); + f2 = R_TextureNumForName(slideFrameNames[i].backFrame2); + f3 = R_TextureNumForName(slideFrameNames[i].backFrame3); + f4 = R_TextureNumForName(slideFrameNames[i].backFrame4); + + slideFrames[i].backFrames[0] = f1; + slideFrames[i].backFrames[1] = f2; + slideFrames[i].backFrames[2] = f3; + slideFrames[i].backFrames[3] = f4; + } +} + + +// +// Return index into "slideFrames" array +// for which door type to use +// +int P_FindSlidingDoorType(line_t* line) +{ + int i; + int val; + + for (i = 0;i < MAXSLIDEDOORS;i++) + { + val = sides[line->sidenum[0]].midtexture; + if (val == slideFrames[i].frontFrames[0]) + return i; + } + + return -1; +} + +void T_SlidingDoor (slidedoor_t* door) +{ + switch(door->status) + { + case sd_opening: + if (!door->timer--) + { + if (++door->frame == SNUMFRAMES) + { + // IF DOOR IS DONE OPENING... + sides[door->line->sidenum[0]].midtexture = 0; + sides[door->line->sidenum[1]].midtexture = 0; + door->line->flags &= ML_BLOCKING^0xff; + + if (door->type == sdt_openOnly) + { + door->frontsector->specialdata = NULL; + P_RemoveThinker (&door->thinker); + break; + } + + door->timer = SDOORWAIT; + door->status = sd_waiting; + } + else + { + // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... + door->timer = SWAITTICS; + + sides[door->line->sidenum[0]].midtexture = + slideFrames[door->whichDoorIndex]. + frontFrames[door->frame]; + sides[door->line->sidenum[1]].midtexture = + slideFrames[door->whichDoorIndex]. + backFrames[door->frame]; + } + } + break; + + case sd_waiting: + // IF DOOR IS DONE WAITING... + if (!door->timer--) + { + // CAN DOOR CLOSE? + if (door->frontsector->thinglist != NULL || + door->backsector->thinglist != NULL) + { + door->timer = SDOORWAIT; + break; + } + + //door->frame = SNUMFRAMES-1; + door->status = sd_closing; + door->timer = SWAITTICS; + } + break; + + case sd_closing: + if (!door->timer--) + { + if (--door->frame < 0) + { + // IF DOOR IS DONE CLOSING... + door->line->flags |= ML_BLOCKING; + door->frontsector->specialdata = NULL; + P_RemoveThinker (&door->thinker); + break; + } + else + { + // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... + door->timer = SWAITTICS; + + sides[door->line->sidenum[0]].midtexture = + slideFrames[door->whichDoorIndex]. + frontFrames[door->frame]; + sides[door->line->sidenum[1]].midtexture = + slideFrames[door->whichDoorIndex]. + backFrames[door->frame]; + } + } + break; + } +} + + + +void +EV_SlidingDoor +( line_t* line, + mobj_t* thing ) +{ + sector_t* sec; + slidedoor_t* door; + + // DOOM II ONLY... + if (gamemode != commercial) + return; + + // Make sure door isn't already being animated + sec = line->frontsector; + door = NULL; + if (sec->specialdata) + { + if (!thing->player) + return; + + door = sec->specialdata; + if (door->type == sdt_openAndClose) + { + if (door->status == sd_waiting) + door->status = sd_closing; + } + else + return; + } + + // Init sliding door vars + if (!door) + { + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + + door->type = sdt_openAndClose; + door->status = sd_opening; + door->whichDoorIndex = P_FindSlidingDoorType(line); + + if (door->whichDoorIndex < 0) + I_Error("EV_SlidingDoor: Can't use texture for sliding door!"); + + door->frontsector = sec; + door->backsector = line->backsector; + door->thinker.function = T_SlidingDoor; + door->timer = SWAITTICS; + door->frame = 0; + door->line = line; + } +} +#endif diff --git a/games/NXDoom/src/doom/p_enemy.c b/games/NXDoom/src/doom/p_enemy.c new file mode 100644 index 00000000000..c6acf390e78 --- /dev/null +++ b/games/NXDoom/src/doom/p_enemy.c @@ -0,0 +1,2024 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Enemy thinking, AI. +// Action Pointer Functions +// that are associated with states/frames. +// + +#include +#include + +#include "m_random.h" +#include "i_system.h" + +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +#include "g_game.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "sounds.h" + + + + +typedef enum +{ + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS + +} dirtype_t; + + +// +// P_NewChaseDir related LUT. +// +dirtype_t opposite[] = +{ + DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, + DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR +}; + +dirtype_t diags[] = +{ + DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST +}; + + + + + +void A_Fall (mobj_t *actor); + + +// +// ENEMY THINKING +// Enemies are allways spawned +// with targetplayer = -1, threshold = 0 +// Most monsters are spawned unaware of all players, +// but some can be made preaware +// + + +// +// Called by P_NoiseAlert. +// Recursively traverse adjacent sectors, +// sound blocking lines cut off traversal. +// + +mobj_t* soundtarget; + +void +P_RecursiveSound +( sector_t* sec, + int soundblocks ) +{ + int i; + line_t* check; + sector_t* other; + + // wake up all monsters in this sector + if (sec->validcount == validcount + && sec->soundtraversed <= soundblocks+1) + { + return; // already flooded + } + + sec->validcount = validcount; + sec->soundtraversed = soundblocks+1; + sec->soundtarget = soundtarget; + + for (i=0 ;ilinecount ; i++) + { + check = sec->lines[i]; + if (! (check->flags & ML_TWOSIDED) ) + continue; + + P_LineOpening (check); + + if (openrange <= 0) + continue; // closed door + + if ( sides[ check->sidenum[0] ].sector == sec) + other = sides[ check->sidenum[1] ] .sector; + else + other = sides[ check->sidenum[0] ].sector; + + if (check->flags & ML_SOUNDBLOCK) + { + if (!soundblocks) + P_RecursiveSound (other, 1); + } + else + P_RecursiveSound (other, soundblocks); + } +} + + + +// +// P_NoiseAlert +// If a monster yells at a player, +// it will alert other monsters to the player. +// +void +P_NoiseAlert +( mobj_t* target, + mobj_t* emmiter ) +{ + soundtarget = target; + validcount++; + P_RecursiveSound (emmiter->subsector->sector, 0); +} + + + + +// +// P_CheckMeleeRange +// +boolean P_CheckMeleeRange (mobj_t* actor) +{ + mobj_t* pl; + fixed_t dist; + fixed_t range; + + if (!actor->target) + return false; + + pl = actor->target; + dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); + + if (gameversion < exe_doom_1_5) + range = MELEERANGE; + else + range = MELEERANGE-20*FRACUNIT+pl->info->radius; + + if (dist >= range) + return false; + + + if (! P_CheckSight (actor, actor->target) ) + return false; + + return true; +} + +// +// P_CheckMissileRange +// +boolean P_CheckMissileRange (mobj_t* actor) +{ + fixed_t dist; + + if (! P_CheckSight (actor, actor->target) ) + return false; + + if ( actor->flags & MF_JUSTHIT ) + { + // the target just hit the enemy, + // so fight back! + actor->flags &= ~MF_JUSTHIT; + return true; + } + + if (actor->reactiontime) + return false; // do not attack yet + + // OPTIMIZE: get this from a global checksight + dist = P_AproxDistance ( actor->x-actor->target->x, + actor->y-actor->target->y) - 64*FRACUNIT; + + if (!actor->info->meleestate) + dist -= 128*FRACUNIT; // no melee attack, so fire more + + dist >>= FRACBITS; + + if (actor->type == MT_VILE) + { + if (dist > 14*64) + return false; // too far away + } + + + if (actor->type == MT_UNDEAD) + { + if (dist < 196) + return false; // close for fist attack + dist >>= 1; + } + + + if (actor->type == MT_CYBORG + || actor->type == MT_SPIDER + || actor->type == MT_SKULL) + { + dist >>= 1; + } + + if (dist > 200) + dist = 200; + + if (actor->type == MT_CYBORG && dist > 160) + dist = 160; + + if (P_Random () < dist) + return false; + + return true; +} + + +// +// P_Move +// Move in the current direction, +// returns false if the move is blocked. +// +fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; +fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; + +boolean P_Move (mobj_t* actor) +{ + fixed_t tryx; + fixed_t tryy; + + line_t* ld; + + // warning: 'catch', 'throw', and 'try' + // are all C++ reserved words + boolean try_ok; + boolean good; + + if (actor->movedir == DI_NODIR) + return false; + + if ((unsigned)actor->movedir >= 8) + I_Error ("Weird actor->movedir!"); + + tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; + tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; + + try_ok = P_TryMove (actor, tryx, tryy); + + if (!try_ok) + { + // open any specials + if (actor->flags & MF_FLOAT && floatok) + { + // must adjust height + if (actor->z < tmfloorz) + actor->z += FLOATSPEED; + else + actor->z -= FLOATSPEED; + + actor->flags |= MF_INFLOAT; + return true; + } + + if (!numspechit) + return false; + + actor->movedir = DI_NODIR; + good = false; + while (numspechit--) + { + ld = spechit[numspechit]; + // if the special is not a door + // that can be opened, + // return false + if (P_UseSpecialLine (actor, ld,0)) + good = true; + } + return good; + } + else + { + actor->flags &= ~MF_INFLOAT; + } + + + if (! (actor->flags & MF_FLOAT) ) + actor->z = actor->floorz; + return true; +} + + +// +// TryWalk +// Attempts to move actor on +// in its current (ob->moveangle) direction. +// If blocked by either a wall or an actor +// returns FALSE +// If move is either clear or blocked only by a door, +// returns TRUE and sets... +// If a door is in the way, +// an OpenDoor call is made to start it opening. +// +boolean P_TryWalk (mobj_t* actor) +{ + if (!P_Move (actor)) + { + return false; + } + + actor->movecount = P_Random()&15; + return true; +} + + + + +void P_NewChaseDir (mobj_t* actor) +{ + fixed_t deltax; + fixed_t deltay; + + dirtype_t d[3]; + + int tdir; + dirtype_t olddir; + + dirtype_t turnaround; + + if (!actor->target) + I_Error ("P_NewChaseDir: called with no target"); + + olddir = actor->movedir; + turnaround=opposite[olddir]; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + + if (deltax>10*FRACUNIT) + d[1]= DI_EAST; + else if (deltax<-10*FRACUNIT) + d[1]= DI_WEST; + else + d[1]=DI_NODIR; + + if (deltay<-10*FRACUNIT) + d[2]= DI_SOUTH; + else if (deltay>10*FRACUNIT) + d[2]= DI_NORTH; + else + d[2]=DI_NODIR; + + // try direct route + if (d[1] != DI_NODIR + && d[2] != DI_NODIR) + { + actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; + if (actor->movedir != (int) turnaround && P_TryWalk(actor)) + return; + } + + // try other directions + if (P_Random() > 200 + || abs(deltay)>abs(deltax)) + { + tdir=d[1]; + d[1]=d[2]; + d[2]=tdir; + } + + if (d[1]==turnaround) + d[1]=DI_NODIR; + if (d[2]==turnaround) + d[2]=DI_NODIR; + + if (d[1]!=DI_NODIR) + { + actor->movedir = d[1]; + if (P_TryWalk(actor)) + { + // either moved forward or attacked + return; + } + } + + if (d[2]!=DI_NODIR) + { + actor->movedir =d[2]; + + if (P_TryWalk(actor)) + return; + } + + // there is no direct path to the player, + // so pick another direction. + if (olddir!=DI_NODIR) + { + actor->movedir =olddir; + + if (P_TryWalk(actor)) + return; + } + + // randomly determine direction of search + if (P_Random()&1) + { + for ( tdir=DI_EAST; + tdir<=DI_SOUTHEAST; + tdir++ ) + { + if (tdir != (int) turnaround) + { + actor->movedir =tdir; + + if ( P_TryWalk(actor) ) + return; + } + } + } + else + { + for ( tdir=DI_SOUTHEAST; + tdir != (DI_EAST-1); + tdir-- ) + { + if (tdir != (int) turnaround) + { + actor->movedir = tdir; + + if ( P_TryWalk(actor) ) + return; + } + } + } + + if (turnaround != DI_NODIR) + { + actor->movedir =turnaround; + if ( P_TryWalk(actor) ) + return; + } + + actor->movedir = DI_NODIR; // can not move +} + + + +// +// P_LookForPlayers +// If allaround is false, only look 180 degrees in front. +// Returns true if a player is targeted. +// +boolean +P_LookForPlayers +( mobj_t* actor, + boolean allaround ) +{ + int c; + int stop; + player_t* player; + angle_t an; + fixed_t dist; + + c = 0; + stop = (actor->lastlook-1)&3; + + for ( ; ; actor->lastlook = (actor->lastlook+1)&3 ) + { + if (!playeringame[actor->lastlook]) + continue; + + if (c++ == 2 + || actor->lastlook == stop) + { + // done looking + return false; + } + + player = &players[actor->lastlook]; + + if (player->health <= 0) + continue; // dead + + if (!P_CheckSight (actor, player->mo)) + continue; // out of sight + + if (!allaround) + { + an = R_PointToAngle2 (actor->x, + actor->y, + player->mo->x, + player->mo->y) + - actor->angle; + + if (an > ANG90 && an < ANG270) + { + dist = P_AproxDistance (player->mo->x - actor->x, + player->mo->y - actor->y); + // if real close, react anyway + if (dist > MELEERANGE) + continue; // behind back + } + } + + actor->target = player->mo; + return true; + } + + return false; +} + + +// +// A_KeenDie +// DOOM II special, map 32. +// Uses special tag 666. +// +void A_KeenDie (mobj_t* mo) +{ + thinker_t* th; + mobj_t* mo2; + line_t junk; + + A_Fall (mo); + + // scan the remaining thinkers + // to see if all Keens are dead + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2 != mo + && mo2->type == mo->type + && mo2->health > 0) + { + // other Keen not dead + return; + } + } + + junk.tag = 666; + EV_DoDoor(&junk, vld_open); +} + + +// +// ACTION ROUTINES +// + +// +// A_Look +// Stay in state until a player is sighted. +// +void A_Look (mobj_t* actor) +{ + mobj_t* targ; + + actor->threshold = 0; // any shot will wake up + targ = actor->subsector->sector->soundtarget; + + if (targ + && (targ->flags & MF_SHOOTABLE) ) + { + actor->target = targ; + + if ( actor->flags & MF_AMBUSH ) + { + if (P_CheckSight (actor, actor->target)) + goto seeyou; + } + else + goto seeyou; + } + + + if (!P_LookForPlayers (actor, false) ) + return; + + // go into chase state + seeyou: + if (actor->info->seesound) + { + int sound; + + switch (actor->info->seesound) + { + case sfx_posit1: + case sfx_posit2: + case sfx_posit3: + sound = sfx_posit1+P_Random()%3; + break; + + case sfx_bgsit1: + case sfx_bgsit2: + sound = sfx_bgsit1+P_Random()%2; + break; + + default: + sound = actor->info->seesound; + break; + } + + if (actor->type==MT_SPIDER + || actor->type == MT_CYBORG) + { + // full volume + S_StartSound (NULL, sound); + } + else + S_StartSound (actor, sound); + } + + P_SetMobjState (actor, actor->info->seestate); +} + + +// +// A_Chase +// Actor has a melee attack, +// so it tries to close as fast as possible +// +void A_Chase (mobj_t* actor) +{ + int delta; + + if (actor->reactiontime) + actor->reactiontime--; + + + // modify target threshold + if (actor->threshold) + { + if (gameversion > exe_doom_1_2 && + (!actor->target || actor->target->health <= 0)) + { + actor->threshold = 0; + } + else + actor->threshold--; + } + + // turn towards movement direction if not there yet + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANG90/2; + else if (delta < 0) + actor->angle += ANG90/2; + } + + if (!actor->target + || !(actor->target->flags&MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor,true)) + return; // got a new target + + P_SetMobjState (actor, actor->info->spawnstate); + return; + } + + // do not attack twice in a row + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare && !fastparm) + P_NewChaseDir (actor); + return; + } + + // check for melee attack + if (actor->info->meleestate + && P_CheckMeleeRange (actor)) + { + if (actor->info->attacksound) + S_StartSound (actor, actor->info->attacksound); + + P_SetMobjState (actor, actor->info->meleestate); + return; + } + + // check for missile attack + if (actor->info->missilestate) + { + if (gameskill < sk_nightmare + && !fastparm && actor->movecount) + { + goto nomissile; + } + + if (!P_CheckMissileRange (actor)) + goto nomissile; + + P_SetMobjState (actor, actor->info->missilestate); + actor->flags |= MF_JUSTATTACKED; + return; + } + + // ? + nomissile: + // possibly choose another target + if (netgame + && !actor->threshold + && !P_CheckSight (actor, actor->target) ) + { + if (P_LookForPlayers(actor,true)) + return; // got a new target + } + + // chase towards player + if (--actor->movecount<0 + || !P_Move (actor)) + { + P_NewChaseDir (actor); + } + + // make active sound + if (actor->info->activesound + && P_Random () < 3) + { + S_StartSound (actor, actor->info->activesound); + } +} + + +// +// A_FaceTarget +// +void A_FaceTarget (mobj_t* actor) +{ + if (!actor->target) + return; + + actor->flags &= ~MF_AMBUSH; + + actor->angle = R_PointToAngle2 (actor->x, + actor->y, + actor->target->x, + actor->target->y); + + if (actor->target->flags & MF_SHADOW) + actor->angle += P_SubRandom() << 21; +} + + +// +// A_PosAttack +// +void A_PosAttack (mobj_t* actor) +{ + int angle; + int damage; + int slope; + + if (!actor->target) + return; + + A_FaceTarget (actor); + angle = actor->angle; + slope = P_AimLineAttack (actor, angle, MISSILERANGE); + + S_StartSound (actor, sfx_pistol); + angle += P_SubRandom() << 20; + damage = ((P_Random()%5)+1)*3; + P_LineAttack (actor, angle, MISSILERANGE, slope, damage); +} + +void A_SPosAttack (mobj_t* actor) +{ + int i; + int angle; + int bangle; + int damage; + int slope; + + if (!actor->target) + return; + + S_StartSound (actor, sfx_shotgn); + A_FaceTarget (actor); + bangle = actor->angle; + slope = P_AimLineAttack (actor, bangle, MISSILERANGE); + + for (i=0 ; i<3 ; i++) + { + angle = bangle + (P_SubRandom() << 20); + damage = ((P_Random()%5)+1)*3; + P_LineAttack (actor, angle, MISSILERANGE, slope, damage); + } +} + +void A_CPosAttack (mobj_t* actor) +{ + int angle; + int bangle; + int damage; + int slope; + + if (!actor->target) + return; + + S_StartSound (actor, sfx_shotgn); + A_FaceTarget (actor); + bangle = actor->angle; + slope = P_AimLineAttack (actor, bangle, MISSILERANGE); + + angle = bangle + (P_SubRandom() << 20); + damage = ((P_Random()%5)+1)*3; + P_LineAttack (actor, angle, MISSILERANGE, slope, damage); +} + +void A_CPosRefire (mobj_t* actor) +{ + // keep firing unless target got out of sight + A_FaceTarget (actor); + + if (P_Random () < 40) + return; + + if (!actor->target + || actor->target->health <= 0 + || !P_CheckSight (actor, actor->target) ) + { + P_SetMobjState (actor, actor->info->seestate); + } +} + + +void A_SpidRefire (mobj_t* actor) +{ + // keep firing unless target got out of sight + A_FaceTarget (actor); + + if (P_Random () < 10) + return; + + if (!actor->target + || actor->target->health <= 0 + || !P_CheckSight (actor, actor->target) ) + { + P_SetMobjState (actor, actor->info->seestate); + } +} + +void A_BspiAttack (mobj_t *actor) +{ + if (!actor->target) + return; + + A_FaceTarget (actor); + + // launch a missile + P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ); +} + + +// +// A_TroopAttack +// +void A_TroopAttack (mobj_t* actor) +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + if (P_CheckMeleeRange (actor)) + { + S_StartSound (actor, sfx_claw); + damage = (P_Random()%8+1)*3; + P_DamageMobj (actor->target, actor, actor, damage); + return; + } + + + // launch a missile + P_SpawnMissile (actor, actor->target, MT_TROOPSHOT); +} + + +void A_SargAttack (mobj_t* actor) +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + + if (gameversion >= exe_doom_1_5) + { + if (!P_CheckMeleeRange (actor)) + return; + } + + damage = ((P_Random()%10)+1)*4; + + if (gameversion <= exe_doom_1_2) + P_LineAttack(actor, actor->angle, MELEERANGE, 0, damage); + else + P_DamageMobj (actor->target, actor, actor, damage); +} + +void A_HeadAttack (mobj_t* actor) +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + if (P_CheckMeleeRange (actor)) + { + damage = (P_Random()%6+1)*10; + P_DamageMobj (actor->target, actor, actor, damage); + return; + } + + // launch a missile + P_SpawnMissile (actor, actor->target, MT_HEADSHOT); +} + +void A_CyberAttack (mobj_t* actor) +{ + if (!actor->target) + return; + + A_FaceTarget (actor); + P_SpawnMissile (actor, actor->target, MT_ROCKET); +} + + +void A_BruisAttack (mobj_t* actor) +{ + int damage; + + if (!actor->target) + return; + + if (P_CheckMeleeRange (actor)) + { + S_StartSound (actor, sfx_claw); + damage = (P_Random()%8+1)*10; + P_DamageMobj (actor->target, actor, actor, damage); + return; + } + + // launch a missile + P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT); +} + + +// +// A_SkelMissile +// +void A_SkelMissile (mobj_t* actor) +{ + mobj_t* mo; + + if (!actor->target) + return; + + A_FaceTarget (actor); + actor->z += 16*FRACUNIT; // so missile spawns higher + mo = P_SpawnMissile (actor, actor->target, MT_TRACER); + actor->z -= 16*FRACUNIT; // back to normal + + mo->x += mo->momx; + mo->y += mo->momy; + mo->tracer = actor->target; +} + +int TRACEANGLE = 0xc000000; + +void A_Tracer (mobj_t* actor) +{ + angle_t exact; + fixed_t dist; + fixed_t slope; + mobj_t* dest; + mobj_t* th; + + if (gametic & 3) + return; + + // spawn a puff of smoke behind the rocket + P_SpawnPuff (actor->x, actor->y, actor->z); + + th = P_SpawnMobj (actor->x-actor->momx, + actor->y-actor->momy, + actor->z, MT_SMOKE); + + th->momz = FRACUNIT; + th->tics -= P_Random()&3; + if (th->tics < 1) + th->tics = 1; + + // adjust direction + dest = actor->tracer; + + if (!dest || dest->health <= 0) + return; + + // change angle + exact = R_PointToAngle2 (actor->x, + actor->y, + dest->x, + dest->y); + + if (exact != actor->angle) + { + if (exact - actor->angle > 0x80000000) + { + actor->angle -= TRACEANGLE; + if (exact - actor->angle < 0x80000000) + actor->angle = exact; + } + else + { + actor->angle += TRACEANGLE; + if (exact - actor->angle > 0x80000000) + actor->angle = exact; + } + } + + exact = actor->angle>>ANGLETOFINESHIFT; + actor->momx = FixedMul (actor->info->speed, finecosine[exact]); + actor->momy = FixedMul (actor->info->speed, finesine[exact]); + + // change slope + dist = P_AproxDistance (dest->x - actor->x, + dest->y - actor->y); + + dist = dist / actor->info->speed; + + if (dist < 1) + dist = 1; + slope = (dest->z+40*FRACUNIT - actor->z) / dist; + + if (slope < actor->momz) + actor->momz -= FRACUNIT/8; + else + actor->momz += FRACUNIT/8; +} + + +void A_SkelWhoosh (mobj_t* actor) +{ + if (!actor->target) + return; + A_FaceTarget (actor); + S_StartSound (actor,sfx_skeswg); +} + +void A_SkelFist (mobj_t* actor) +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + + if (P_CheckMeleeRange (actor)) + { + damage = ((P_Random()%10)+1)*6; + S_StartSound (actor, sfx_skepch); + P_DamageMobj (actor->target, actor, actor, damage); + } +} + + + +// +// PIT_VileCheck +// Detect a corpse that could be raised. +// +mobj_t* corpsehit; +mobj_t* vileobj; +fixed_t viletryx; +fixed_t viletryy; + +boolean PIT_VileCheck (mobj_t* thing) +{ + int maxdist; + boolean check; + + if (!(thing->flags & MF_CORPSE) ) + return true; // not a monster + + if (thing->tics != -1) + return true; // not lying still yet + + if (thing->info->raisestate == S_NULL) + return true; // monster doesn't have a raise state + + maxdist = thing->info->radius + mobjinfo[MT_VILE].radius; + + if ( abs(thing->x - viletryx) > maxdist + || abs(thing->y - viletryy) > maxdist ) + return true; // not actually touching + + corpsehit = thing; + corpsehit->momx = corpsehit->momy = 0; + corpsehit->height <<= 2; + check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); + corpsehit->height >>= 2; + + if (!check) + return true; // doesn't fit here + + return false; // got one, so stop checking +} + + + +// +// A_VileChase +// Check for ressurecting a body +// +void A_VileChase (mobj_t* actor) +{ + int xl; + int xh; + int yl; + int yh; + + int bx; + int by; + + mobjinfo_t* info; + mobj_t* temp; + + if (actor->movedir != DI_NODIR) + { + // check for corpses to raise + viletryx = + actor->x + actor->info->speed*xspeed[actor->movedir]; + viletryy = + actor->y + actor->info->speed*yspeed[actor->movedir]; + + xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT; + xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT; + yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT; + yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT; + + vileobj = actor; + for (bx=xl ; bx<=xh ; bx++) + { + for (by=yl ; by<=yh ; by++) + { + // Call PIT_VileCheck to check + // whether object is a corpse + // that canbe raised. + if (!P_BlockThingsIterator(bx,by,PIT_VileCheck)) + { + // got one! + temp = actor->target; + actor->target = corpsehit; + A_FaceTarget (actor); + actor->target = temp; + + P_SetMobjState (actor, S_VILE_HEAL1); + S_StartSound (corpsehit, sfx_slop); + info = corpsehit->info; + + P_SetMobjState (corpsehit,info->raisestate); + corpsehit->height <<= 2; + corpsehit->flags = info->flags; + corpsehit->health = info->spawnhealth; + corpsehit->target = NULL; + + return; + } + } + } + } + + // Return to normal attack. + A_Chase (actor); +} + + +// +// A_VileStart +// +void A_VileStart (mobj_t* actor) +{ + S_StartSound (actor, sfx_vilatk); +} + + +// +// A_Fire +// Keep fire in front of player unless out of sight +// +void A_Fire (mobj_t* actor); + +void A_StartFire (mobj_t* actor) +{ + S_StartSound(actor,sfx_flamst); + A_Fire(actor); +} + +void A_FireCrackle (mobj_t* actor) +{ + S_StartSound(actor,sfx_flame); + A_Fire(actor); +} + +void A_Fire (mobj_t* actor) +{ + mobj_t* dest; + mobj_t* target; + unsigned an; + + dest = actor->tracer; + if (!dest) + return; + + target = P_SubstNullMobj(actor->target); + + // don't move it if the vile lost sight + if (!P_CheckSight (target, dest) ) + return; + + an = dest->angle >> ANGLETOFINESHIFT; + + P_UnsetThingPosition (actor); + actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]); + actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]); + actor->z = dest->z; + P_SetThingPosition (actor); +} + + + +// +// A_VileTarget +// Spawn the hellfire +// +void A_VileTarget (mobj_t* actor) +{ + mobj_t* fog; + + if (!actor->target) + return; + + A_FaceTarget (actor); + + fog = P_SpawnMobj (actor->target->x, + actor->target->x, + actor->target->z, MT_FIRE); + + actor->tracer = fog; + fog->target = actor; + fog->tracer = actor->target; + A_Fire (fog); +} + + + + +// +// A_VileAttack +// +void A_VileAttack (mobj_t* actor) +{ + mobj_t* fire; + int an; + + if (!actor->target) + return; + + A_FaceTarget (actor); + + if (!P_CheckSight (actor, actor->target) ) + return; + + S_StartSound (actor, sfx_barexp); + P_DamageMobj (actor->target, actor, actor, 20); + actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; + + an = actor->angle >> ANGLETOFINESHIFT; + + fire = actor->tracer; + + if (!fire) + return; + + // move the fire between the vile and the player + fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); + fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); + P_RadiusAttack (fire, actor, 70 ); +} + + + + +// +// Mancubus attack, +// firing three missiles (bruisers) +// in three different directions? +// Doesn't look like it. +// +#define FATSPREAD (ANG90/8) + +void A_FatRaise (mobj_t *actor) +{ + A_FaceTarget (actor); + S_StartSound (actor, sfx_manatk); +} + + +void A_FatAttack1 (mobj_t* actor) +{ + mobj_t* mo; + mobj_t* target; + int an; + + A_FaceTarget (actor); + + // Change direction to ... + actor->angle += FATSPREAD; + target = P_SubstNullMobj(actor->target); + P_SpawnMissile (actor, target, MT_FATSHOT); + + mo = P_SpawnMissile (actor, target, MT_FATSHOT); + mo->angle += FATSPREAD; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = FixedMul (mo->info->speed, finecosine[an]); + mo->momy = FixedMul (mo->info->speed, finesine[an]); +} + +void A_FatAttack2 (mobj_t* actor) +{ + mobj_t* mo; + mobj_t* target; + int an; + + A_FaceTarget (actor); + // Now here choose opposite deviation. + actor->angle -= FATSPREAD; + target = P_SubstNullMobj(actor->target); + P_SpawnMissile (actor, target, MT_FATSHOT); + + mo = P_SpawnMissile (actor, target, MT_FATSHOT); + mo->angle -= FATSPREAD*2; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = FixedMul (mo->info->speed, finecosine[an]); + mo->momy = FixedMul (mo->info->speed, finesine[an]); +} + +void A_FatAttack3 (mobj_t* actor) +{ + mobj_t* mo; + mobj_t* target; + int an; + + A_FaceTarget (actor); + + target = P_SubstNullMobj(actor->target); + + mo = P_SpawnMissile (actor, target, MT_FATSHOT); + mo->angle -= FATSPREAD/2; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = FixedMul (mo->info->speed, finecosine[an]); + mo->momy = FixedMul (mo->info->speed, finesine[an]); + + mo = P_SpawnMissile (actor, target, MT_FATSHOT); + mo->angle += FATSPREAD/2; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = FixedMul (mo->info->speed, finecosine[an]); + mo->momy = FixedMul (mo->info->speed, finesine[an]); +} + + +// +// SkullAttack +// Fly at the player like a missile. +// +#define SKULLSPEED (20*FRACUNIT) + +void A_SkullAttack (mobj_t* actor) +{ + mobj_t* dest; + angle_t an; + int dist; + + if (!actor->target) + return; + + dest = actor->target; + actor->flags |= MF_SKULLFLY; + + S_StartSound (actor, actor->info->attacksound); + A_FaceTarget (actor); + an = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul (SKULLSPEED, finecosine[an]); + actor->momy = FixedMul (SKULLSPEED, finesine[an]); + dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); + dist = dist / SKULLSPEED; + + if (dist < 1) + dist = 1; + actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist; +} + + +// +// A_PainShootSkull +// Spawn a lost soul and launch it at the target +// +void +A_PainShootSkull +( mobj_t* actor, + angle_t angle ) +{ + fixed_t x; + fixed_t y; + fixed_t z; + + mobj_t* newmobj; + angle_t an; + int prestep; + int count; + thinker_t* currentthinker; + + // count total number of skull currently on the level + count = 0; + + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + && ((mobj_t *)currentthinker)->type == MT_SKULL) + count++; + currentthinker = currentthinker->next; + } + + // if there are allready 20 skulls on the level, + // don't spit another one + if (count > 20) + return; + + + // okay, there's playe for another one + an = angle >> ANGLETOFINESHIFT; + + prestep = + 4*FRACUNIT + + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2; + + x = actor->x + FixedMul (prestep, finecosine[an]); + y = actor->y + FixedMul (prestep, finesine[an]); + z = actor->z + 8*FRACUNIT; + + newmobj = P_SpawnMobj (x , y, z, MT_SKULL); + + // Check for movements. + if (!P_TryMove (newmobj, newmobj->x, newmobj->y)) + { + // kill it immediately + P_DamageMobj (newmobj,actor,actor,10000); + return; + } + + newmobj->target = actor->target; + A_SkullAttack (newmobj); +} + + +// +// A_PainAttack +// Spawn a lost soul and launch it at the target +// +void A_PainAttack (mobj_t* actor) +{ + if (!actor->target) + return; + + A_FaceTarget (actor); + A_PainShootSkull (actor, actor->angle); +} + + +void A_PainDie (mobj_t* actor) +{ + A_Fall (actor); + A_PainShootSkull (actor, actor->angle+ANG90); + A_PainShootSkull (actor, actor->angle+ANG180); + A_PainShootSkull (actor, actor->angle+ANG270); +} + + + + + + +void A_Scream (mobj_t* actor) +{ + int sound; + + switch (actor->info->deathsound) + { + case 0: + return; + + case sfx_podth1: + case sfx_podth2: + case sfx_podth3: + sound = sfx_podth1 + P_Random ()%3; + break; + + case sfx_bgdth1: + case sfx_bgdth2: + sound = sfx_bgdth1 + P_Random ()%2; + break; + + default: + sound = actor->info->deathsound; + break; + } + + // Check for bosses. + if (actor->type==MT_SPIDER + || actor->type == MT_CYBORG) + { + // full volume + S_StartSound (NULL, sound); + } + else + S_StartSound (actor, sound); +} + + +void A_XScream (mobj_t* actor) +{ + S_StartSound (actor, sfx_slop); +} + +void A_Pain (mobj_t* actor) +{ + if (actor->info->painsound) + S_StartSound (actor, actor->info->painsound); +} + + + +void A_Fall (mobj_t *actor) +{ + // actor is on ground, it can be walked over + actor->flags &= ~MF_SOLID; + + // So change this if corpse objects + // are meant to be obstacles. +} + + +// +// A_Explode +// +void A_Explode (mobj_t* thingy) +{ + P_RadiusAttack(thingy, thingy->target, 128); +} + +// Check whether the death of the specified monster type is allowed +// to trigger the end of episode special action. +// +// This behavior changed in v1.9, the most notable effect of which +// was to break uac_dead.wad + +static boolean CheckBossEnd(mobjtype_t motype) +{ + if (gameversion < exe_ultimate) + { + if (gamemap != 8) + { + return false; + } + + // Baron death on later episodes is nothing special. + + if (motype == MT_BRUISER && gameepisode != 1) + { + return false; + } + + return true; + } + else + { + // New logic that appeared in Ultimate Doom. + // Looks like the logic was overhauled while adding in the + // episode 4 support. Now bosses only trigger on their + // specific episode. + + switch(gameepisode) + { + case 1: + return gamemap == 8 && motype == MT_BRUISER; + + case 2: + return gamemap == 8 && motype == MT_CYBORG; + + case 3: + return gamemap == 8 && motype == MT_SPIDER; + + case 4: + return (gamemap == 6 && motype == MT_CYBORG) + || (gamemap == 8 && motype == MT_SPIDER); + + default: + return gamemap == 8; + } + } +} + +// +// A_BossDeath +// Possibly trigger special effects +// if on first boss level +// +void A_BossDeath (mobj_t* mo) +{ + thinker_t* th; + mobj_t* mo2; + line_t junk; + int i; + + if ( gamemode == commercial) + { + if (gamemap != 7) + return; + + if ((mo->type != MT_FATSO) + && (mo->type != MT_BABY)) + return; + } + else + { + if (!CheckBossEnd(mo->type)) + { + return; + } + } + + // make sure there is a player alive for victory + for (i=0 ; i 0) + break; + + if (i==MAXPLAYERS) + return; // no one left alive, so do not end game + + // scan the remaining thinkers to see + // if all bosses are dead + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2 != mo + && mo2->type == mo->type + && mo2->health > 0) + { + // other boss not dead + return; + } + } + + // victory! + if ( gamemode == commercial) + { + if (gamemap == 7) + { + if (mo->type == MT_FATSO) + { + junk.tag = 666; + EV_DoFloor(&junk,lowerFloorToLowest); + return; + } + + if (mo->type == MT_BABY) + { + junk.tag = 667; + EV_DoFloor(&junk,raiseToTexture); + return; + } + } + } + else + { + switch(gameepisode) + { + case 1: + junk.tag = 666; + EV_DoFloor (&junk, lowerFloorToLowest); + return; + break; + + case 4: + switch(gamemap) + { + case 6: + junk.tag = 666; + EV_DoDoor (&junk, vld_blazeOpen); + return; + break; + + case 8: + junk.tag = 666; + EV_DoFloor (&junk, lowerFloorToLowest); + return; + break; + } + } + } + + G_ExitLevel (); +} + + +void A_Hoof (mobj_t* mo) +{ + S_StartSound (mo, sfx_hoof); + A_Chase (mo); +} + +void A_Metal (mobj_t* mo) +{ + S_StartSound (mo, sfx_metal); + A_Chase (mo); +} + +void A_BabyMetal (mobj_t* mo) +{ + S_StartSound (mo, sfx_bspwlk); + A_Chase (mo); +} + +void +A_OpenShotgun2 +( player_t* player, + pspdef_t* psp ) +{ + S_StartSound (player->mo, sfx_dbopn); +} + +void +A_LoadShotgun2 +( player_t* player, + pspdef_t* psp ) +{ + S_StartSound (player->mo, sfx_dbload); +} + +void +A_ReFire +( player_t* player, + pspdef_t* psp ); + +void +A_CloseShotgun2 +( player_t* player, + pspdef_t* psp ) +{ + S_StartSound (player->mo, sfx_dbcls); + A_ReFire(player,psp); +} + + + +mobj_t* braintargets[32]; +int numbraintargets; +int braintargeton = 0; + +void A_BrainAwake (mobj_t* mo) +{ + thinker_t* thinker; + mobj_t* m; + + // find all the target spots + numbraintargets = 0; + braintargeton = 0; + + for (thinker = thinkercap.next ; + thinker != &thinkercap ; + thinker = thinker->next) + { + if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) + continue; // not a mobj + + m = (mobj_t *)thinker; + + if (m->type == MT_BOSSTARGET ) + { + braintargets[numbraintargets] = m; + numbraintargets++; + } + } + + S_StartSound (NULL,sfx_bossit); +} + + +void A_BrainPain (mobj_t* mo) +{ + S_StartSound (NULL,sfx_bospn); +} + + +void A_BrainScream (mobj_t* mo) +{ + int x; + int y; + int z; + mobj_t* th; + + for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8) + { + y = mo->y - 320*FRACUNIT; + z = 128 + P_Random()*2*FRACUNIT; + th = P_SpawnMobj (x,y,z, MT_ROCKET); + th->momz = P_Random()*512; + + P_SetMobjState (th, S_BRAINEXPLODE1); + + th->tics -= P_Random()&7; + if (th->tics < 1) + th->tics = 1; + } + + S_StartSound (NULL,sfx_bosdth); +} + + + +void A_BrainExplode (mobj_t* mo) +{ + int x; + int y; + int z; + mobj_t* th; + + x = mo->x + P_SubRandom() * 2048; + y = mo->y; + z = 128 + P_Random()*2*FRACUNIT; + th = P_SpawnMobj (x,y,z, MT_ROCKET); + th->momz = P_Random()*512; + + P_SetMobjState (th, S_BRAINEXPLODE1); + + th->tics -= P_Random()&7; + if (th->tics < 1) + th->tics = 1; +} + + +void A_BrainDie (mobj_t* mo) +{ + G_ExitLevel (); +} + +void A_BrainSpit (mobj_t* mo) +{ + mobj_t* targ; + mobj_t* newmobj; + + static int easy = 0; + + easy ^= 1; + if (gameskill <= sk_easy && (!easy)) + return; + + // shoot a cube at current target + targ = braintargets[braintargeton]; + if (numbraintargets == 0) + { + I_Error("A_BrainSpit: numbraintargets was 0 (vanilla crashes here)"); + } + braintargeton = (braintargeton+1)%numbraintargets; + + // spawn brain missile + newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT); + newmobj->target = targ; + newmobj->reactiontime = + ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics; + + S_StartSound(NULL, sfx_bospit); +} + + + +void A_SpawnFly (mobj_t* mo); + +// travelling cube sound +void A_SpawnSound (mobj_t* mo) +{ + S_StartSound (mo,sfx_boscub); + A_SpawnFly(mo); +} + +void A_SpawnFly (mobj_t* mo) +{ + mobj_t* newmobj; + mobj_t* fog; + mobj_t* targ; + int r; + mobjtype_t type; + + if (--mo->reactiontime) + return; // still flying + + targ = P_SubstNullMobj(mo->target); + + // First spawn teleport fog. + fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE); + S_StartSound (fog, sfx_telept); + + // Randomly select monster to spawn. + r = P_Random (); + + // Probability distribution (kind of :), + // decreasing likelihood. + if ( r<50 ) + type = MT_TROOP; + else if (r<90) + type = MT_SERGEANT; + else if (r<120) + type = MT_SHADOWS; + else if (r<130) + type = MT_PAIN; + else if (r<160) + type = MT_HEAD; + else if (r<162) + type = MT_VILE; + else if (r<172) + type = MT_UNDEAD; + else if (r<192) + type = MT_BABY; + else if (r<222) + type = MT_FATSO; + else if (r<246) + type = MT_KNIGHT; + else + type = MT_BRUISER; + + newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type); + if (P_LookForPlayers (newmobj, true) ) + P_SetMobjState (newmobj, newmobj->info->seestate); + + // telefrag anything in this spot + P_TeleportMove (newmobj, newmobj->x, newmobj->y); + + // remove self (i.e., cube). + P_RemoveMobj (mo); +} + + + +void A_PlayerScream (mobj_t* mo) +{ + // Default death sound. + int sound = sfx_pldeth; + + if ( (gamemode == commercial) + && (mo->health < -50)) + { + // IF THE PLAYER DIES + // LESS THAN -50% WITHOUT GIBBING + sound = sfx_pdiehi; + } + + S_StartSound (mo, sound); +} diff --git a/games/NXDoom/src/doom/p_floor.c b/games/NXDoom/src/doom/p_floor.c new file mode 100644 index 00000000000..2bf42e55d79 --- /dev/null +++ b/games/NXDoom/src/doom/p_floor.c @@ -0,0 +1,561 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Floor animation: raising stairs. +// + + + +#include "z_zone.h" +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" +// Data. +#include "sounds.h" + +//e6y +#define STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE 10 + +// +// FLOORS +// + +// +// Move a plane (floor or ceiling) and check for crushing +// +result_e +T_MovePlane +( sector_t* sector, + fixed_t speed, + fixed_t dest, + boolean crush, + int floorOrCeiling, + int direction ) +{ + boolean flag; + fixed_t lastpos; + + switch(floorOrCeiling) + { + case 0: + // FLOOR + switch(direction) + { + case -1: + // DOWN + if (sector->floorheight - speed < dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + sector->floorheight =lastpos; + P_ChangeSector(sector,crush); + //return crushed; + } + return pastdest; + } + else + { + lastpos = sector->floorheight; + sector->floorheight -= speed; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + } + } + break; + + case 1: + // UP + if (sector->floorheight + speed > dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + //return crushed; + } + return pastdest; + } + else + { + // COULD GET CRUSHED + lastpos = sector->floorheight; + sector->floorheight += speed; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + if (crush == true) + return crushed; + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + } + } + break; + } + break; + + case 1: + // CEILING + switch(direction) + { + case -1: + // DOWN + if (sector->ceilingheight - speed < dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector,crush); + + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + //return crushed; + } + return pastdest; + } + else + { + // COULD GET CRUSHED + lastpos = sector->ceilingheight; + sector->ceilingheight -= speed; + flag = P_ChangeSector(sector,crush); + + if (flag == true) + { + if (crush == true) + return crushed; + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + } + } + break; + + case 1: + // UP + if (sector->ceilingheight + speed > dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + //return crushed; + } + return pastdest; + } + else + { + lastpos = sector->ceilingheight; + sector->ceilingheight += speed; + flag = P_ChangeSector(sector,crush); +// UNUSED +#if 0 + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + } +#endif + } + break; + } + break; + + } + return ok; +} + + +// +// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) +// +void T_MoveFloor(floormove_t* floor) +{ + result_e res; + + res = T_MovePlane(floor->sector, + floor->speed, + floor->floordestheight, + floor->crush,0,floor->direction); + + if (!(leveltime&7)) + S_StartSound(&floor->sector->soundorg, sfx_stnmov); + + if (res == pastdest) + { + floor->sector->specialdata = NULL; + + if (floor->direction == 1) + { + switch(floor->type) + { + case donutRaise: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + else if (floor->direction == -1) + { + switch(floor->type) + { + case lowerAndChange: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + P_RemoveThinker(&floor->thinker); + + S_StartSound(&floor->sector->soundorg, sfx_pstop); + } + +} + +// +// HANDLE FLOOR TYPES +// +int +EV_DoFloor +( line_t* line, + floor_e floortype ) +{ + int secnum; + int rtn; + int i; + sector_t* sec; + floormove_t* floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // new floor thinker + rtn = 1; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = floortype; + floor->crush = false; + + switch(floortype) + { + case lowerFloor: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindHighestFloorSurrounding(sec); + break; + + case lowerFloorToLowest: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindLowestFloorSurrounding(sec); + break; + + case turboLower: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED * 4; + floor->floordestheight = + P_FindHighestFloorSurrounding(sec); + if (gameversion <= exe_doom_1_2 || + floor->floordestheight != sec->floorheight) + floor->floordestheight += 8*FRACUNIT; + break; + + case raiseFloorCrush: + floor->crush = true; + case raiseFloor: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindLowestCeilingSurrounding(sec); + if (floor->floordestheight > sec->ceilingheight) + floor->floordestheight = sec->ceilingheight; + floor->floordestheight -= (8*FRACUNIT)* + (floortype == raiseFloorCrush); + break; + + case raiseFloorTurbo: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED*4; + floor->floordestheight = + P_FindNextHighestFloor(sec,sec->floorheight); + break; + + case raiseFloorToNearest: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindNextHighestFloor(sec,sec->floorheight); + break; + + case raiseFloor24: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 24 * FRACUNIT; + break; + case raiseFloor512: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 512 * FRACUNIT; + break; + + case raiseFloor24AndChange: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 24 * FRACUNIT; + sec->floorpic = line->frontsector->floorpic; + sec->special = line->frontsector->special; + break; + + case raiseToTexture: + { + int minsize = INT_MAX; + side_t* side; + + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + for (i = 0; i < sec->linecount; i++) + { + if (twoSided (secnum, i) ) + { + side = getSide(secnum,i,0); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < + minsize) + minsize = + textureheight[side->bottomtexture]; + side = getSide(secnum,i,1); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < + minsize) + minsize = + textureheight[side->bottomtexture]; + } + } + floor->floordestheight = + floor->sector->floorheight + minsize; + } + break; + + case lowerAndChange: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindLowestFloorSurrounding(sec); + floor->texture = sec->floorpic; + + for (i = 0; i < sec->linecount; i++) + { + if ( twoSided(secnum, i) ) + { + if (getSide(secnum,i,0)->sector-sectors == secnum) + { + sec = getSector(secnum,i,1); + + if (sec->floorheight == floor->floordestheight) + { + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + else + { + sec = getSector(secnum,i,0); + + if (sec->floorheight == floor->floordestheight) + { + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + } + } + default: + break; + } + } + return rtn; +} + + + + +// +// BUILD A STAIRCASE! +// +int +EV_BuildStairs +( line_t* line, + stair_e type ) +{ + int secnum; + int height; + int i; + int newsecnum; + int texture; + int ok; + int rtn; + + sector_t* sec; + sector_t* tsec; + + floormove_t* floor; + + fixed_t stairsize = 0; + fixed_t speed = 0; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // new floor thinker + rtn = 1; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->direction = 1; + floor->sector = sec; + switch(type) + { + case build8: + speed = FLOORSPEED/4; + stairsize = 8*FRACUNIT; + break; + case turbo16: + speed = FLOORSPEED*4; + stairsize = 16*FRACUNIT; + break; + } + floor->speed = speed; + height = sec->floorheight + stairsize; + floor->floordestheight = height; + // Initialize + floor->type = lowerFloor; + // e6y + // Uninitialized crush field will not be equal to 0 or 1 (true) + // with high probability. So, initialize it with any other value + floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; + + texture = sec->floorpic; + + // Find next sector to raise + // 1. Find 2-sided line with same sector side[0] + // 2. Other side is the next sector to raise + do + { + ok = 0; + for (i = 0;i < sec->linecount;i++) + { + if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) + continue; + + tsec = (sec->lines[i])->frontsector; + newsecnum = tsec-sectors; + + if (secnum != newsecnum) + continue; + + tsec = (sec->lines[i])->backsector; + newsecnum = tsec - sectors; + + if (tsec->floorpic != texture) + continue; + + height += stairsize; + + if (tsec->specialdata) + continue; + + sec = tsec; + secnum = newsecnum; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + + P_AddThinker (&floor->thinker); + + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->direction = 1; + floor->sector = sec; + floor->speed = speed; + floor->floordestheight = height; + // Initialize + floor->type = lowerFloor; + // e6y + // Uninitialized crush field will not be equal to 0 or 1 (true) + // with high probability. So, initialize it with any other value + floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; + ok = 1; + break; + } + } while(ok); + } + return rtn; +} + diff --git a/games/NXDoom/src/doom/p_inter.c b/games/NXDoom/src/doom/p_inter.c new file mode 100644 index 00000000000..b6e403298d7 --- /dev/null +++ b/games/NXDoom/src/doom/p_inter.c @@ -0,0 +1,931 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handling interactions (i.e., collisions). +// + + + + +// Data. +#include "doomdef.h" +#include "dstrings.h" +#include "sounds.h" + +#include "deh_main.h" +#include "deh_misc.h" +#include "doomstat.h" + +#include "m_random.h" +#include "i_system.h" + +#include "am_map.h" + +#include "p_local.h" + +#include "s_sound.h" + +#include "p_inter.h" + + +#define BONUSADD 6 + + + + +// a weapon is found with two clip loads, +// a big item has five clip loads +int maxammo[NUMAMMO] = {200, 50, 300, 50}; +int clipammo[NUMAMMO] = {10, 4, 20, 1}; + + +// +// GET STUFF +// + +// +// P_GiveAmmo +// Num is the number of clip loads, +// not the individual count (0= 1/2 clip). +// Returns false if the ammo can't be picked up at all +// + +boolean +P_GiveAmmo +( player_t* player, + ammotype_t ammo, + int num ) +{ + int oldammo; + + if (ammo == am_noammo) + return false; + + if (ammo >= NUMAMMO) + I_Error ("P_GiveAmmo: bad type %i", ammo); + + if ( player->ammo[ammo] == player->maxammo[ammo] ) + return false; + + if (num) + num *= clipammo[ammo]; + else + num = clipammo[ammo]/2; + + if (gameskill == sk_baby + || gameskill == sk_nightmare) + { + // give double ammo in trainer mode, + // you'll need in nightmare + num <<= 1; + } + + + oldammo = player->ammo[ammo]; + player->ammo[ammo] += num; + + if (player->ammo[ammo] > player->maxammo[ammo]) + player->ammo[ammo] = player->maxammo[ammo]; + + // If non zero ammo, + // don't change up weapons, + // player was lower on purpose. + if (oldammo) + return true; + + // We were down to zero, + // so select a new weapon. + // Preferences are not user selectable. + switch (ammo) + { + case am_clip: + if (player->readyweapon == wp_fist) + { + if (player->weaponowned[wp_chaingun]) + player->pendingweapon = wp_chaingun; + else + player->pendingweapon = wp_pistol; + } + break; + + case am_shell: + if (player->readyweapon == wp_fist + || player->readyweapon == wp_pistol) + { + if (player->weaponowned[wp_shotgun]) + player->pendingweapon = wp_shotgun; + } + break; + + case am_cell: + if (player->readyweapon == wp_fist + || player->readyweapon == wp_pistol) + { + if (player->weaponowned[wp_plasma]) + player->pendingweapon = wp_plasma; + } + break; + + case am_misl: + if (player->readyweapon == wp_fist) + { + if (player->weaponowned[wp_missile]) + player->pendingweapon = wp_missile; + } + default: + break; + } + + return true; +} + + +// +// P_GiveWeapon +// The weapon name may have a MF_DROPPED flag ored in. +// +boolean +P_GiveWeapon +( player_t* player, + weapontype_t weapon, + boolean dropped ) +{ + boolean gaveammo; + boolean gaveweapon; + + if (netgame + && (deathmatch!=2) + && !dropped ) + { + // leave placed weapons forever on net games + if (player->weaponowned[weapon]) + return false; + + player->bonuscount += BONUSADD; + player->weaponowned[weapon] = true; + + if (deathmatch) + P_GiveAmmo (player, weaponinfo[weapon].ammo, 5); + else + P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); + player->pendingweapon = weapon; + + if (player == &players[consoleplayer]) + S_StartSound (NULL, sfx_wpnup); + return false; + } + + if (weaponinfo[weapon].ammo != am_noammo) + { + // give one clip with a dropped weapon, + // two clips with a found weapon + if (dropped) + gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1); + else + gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); + } + else + gaveammo = false; + + if (player->weaponowned[weapon]) + gaveweapon = false; + else + { + gaveweapon = true; + player->weaponowned[weapon] = true; + player->pendingweapon = weapon; + } + + return (gaveweapon || gaveammo); +} + + + +// +// P_GiveBody +// Returns false if the body isn't needed at all +// +boolean +P_GiveBody +( player_t* player, + int num ) +{ + if (player->health >= MAXHEALTH) + return false; + + player->health += num; + if (player->health > MAXHEALTH) + player->health = MAXHEALTH; + player->mo->health = player->health; + + return true; +} + + + +// +// P_GiveArmor +// Returns false if the armor is worse +// than the current armor. +// +boolean +P_GiveArmor +( player_t* player, + int armortype ) +{ + int hits; + + hits = armortype*100; + if (player->armorpoints >= hits) + return false; // don't pick up + + player->armortype = armortype; + player->armorpoints = hits; + + return true; +} + + + +// +// P_GiveCard +// +void +P_GiveCard +( player_t* player, + card_t card ) +{ + if (player->cards[card]) + return; + + player->bonuscount = BONUSADD; + player->cards[card] = 1; +} + + +// +// P_GivePower +// +boolean +P_GivePower +( player_t* player, + int /*powertype_t*/ power ) +{ + if (power == pw_invulnerability) + { + player->powers[power] = INVULNTICS; + return true; + } + + if (power == pw_invisibility) + { + player->powers[power] = INVISTICS; + player->mo->flags |= MF_SHADOW; + return true; + } + + if (power == pw_infrared) + { + player->powers[power] = INFRATICS; + return true; + } + + if (power == pw_ironfeet) + { + player->powers[power] = IRONTICS; + return true; + } + + if (power == pw_strength) + { + P_GiveBody (player, 100); + player->powers[power] = 1; + return true; + } + + if (player->powers[power]) + return false; // already got it + + player->powers[power] = 1; + return true; +} + + + +// +// P_TouchSpecialThing +// +void +P_TouchSpecialThing +( mobj_t* special, + mobj_t* toucher ) +{ + player_t* player; + int i; + fixed_t delta; + int sound; + + delta = special->z - toucher->z; + + if (delta > toucher->height + || delta < -8*FRACUNIT) + { + // out of reach + return; + } + + + sound = sfx_itemup; + player = toucher->player; + + // Dead thing touching. + // Can happen with a sliding player corpse. + if (toucher->health <= 0) + return; + + // Identify by sprite. + switch (special->sprite) + { + // armor + case SPR_ARM1: + if (!P_GiveArmor (player, deh_green_armor_class)) + return; + player->message = DEH_String(GOTARMOR); + break; + + case SPR_ARM2: + if (!P_GiveArmor (player, deh_blue_armor_class)) + return; + player->message = DEH_String(GOTMEGA); + break; + + // bonus items + case SPR_BON1: + player->health++; // can go over 100% + if (player->health > deh_max_health) + player->health = deh_max_health; + player->mo->health = player->health; + player->message = DEH_String(GOTHTHBONUS); + break; + + case SPR_BON2: + player->armorpoints++; // can go over 100% + if (player->armorpoints > deh_max_armor && gameversion > exe_doom_1_2) + player->armorpoints = deh_max_armor; + // deh_green_armor_class only applies to the green armor shirt; + // for the armor helmets, armortype 1 is always used. + if (!player->armortype) + player->armortype = 1; + player->message = DEH_String(GOTARMBONUS); + break; + + case SPR_SOUL: + player->health += deh_soulsphere_health; + if (player->health > deh_max_soulsphere) + player->health = deh_max_soulsphere; + player->mo->health = player->health; + player->message = DEH_String(GOTSUPER); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + case SPR_MEGA: + if (gamemode != commercial) + return; + player->health = deh_megasphere_health; + player->mo->health = player->health; + // We always give armor type 2 for the megasphere; dehacked only + // affects the MegaArmor. + P_GiveArmor (player, 2); + player->message = DEH_String(GOTMSPHERE); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + // cards + // leave cards for everyone + case SPR_BKEY: + if (!player->cards[it_bluecard]) + player->message = DEH_String(GOTBLUECARD); + P_GiveCard (player, it_bluecard); + if (!netgame) + break; + return; + + case SPR_YKEY: + if (!player->cards[it_yellowcard]) + player->message = DEH_String(GOTYELWCARD); + P_GiveCard (player, it_yellowcard); + if (!netgame) + break; + return; + + case SPR_RKEY: + if (!player->cards[it_redcard]) + player->message = DEH_String(GOTREDCARD); + P_GiveCard (player, it_redcard); + if (!netgame) + break; + return; + + case SPR_BSKU: + if (!player->cards[it_blueskull]) + player->message = DEH_String(GOTBLUESKUL); + P_GiveCard (player, it_blueskull); + if (!netgame) + break; + return; + + case SPR_YSKU: + if (!player->cards[it_yellowskull]) + player->message = DEH_String(GOTYELWSKUL); + P_GiveCard (player, it_yellowskull); + if (!netgame) + break; + return; + + case SPR_RSKU: + if (!player->cards[it_redskull]) + player->message = DEH_String(GOTREDSKULL); + P_GiveCard (player, it_redskull); + if (!netgame) + break; + return; + + // medikits, heals + case SPR_STIM: + if (!P_GiveBody (player, 10)) + return; + player->message = DEH_String(GOTSTIM); + break; + + case SPR_MEDI: + if (!P_GiveBody (player, 25)) + return; + + if (player->health < 25) + player->message = DEH_String(GOTMEDINEED); + else + player->message = DEH_String(GOTMEDIKIT); + break; + + + // power ups + case SPR_PINV: + if (!P_GivePower (player, pw_invulnerability)) + return; + player->message = DEH_String(GOTINVUL); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + case SPR_PSTR: + if (!P_GivePower (player, pw_strength)) + return; + player->message = DEH_String(GOTBERSERK); + if (player->readyweapon != wp_fist) + player->pendingweapon = wp_fist; + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + case SPR_PINS: + if (!P_GivePower (player, pw_invisibility)) + return; + player->message = DEH_String(GOTINVIS); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + case SPR_SUIT: + if (!P_GivePower (player, pw_ironfeet)) + return; + player->message = DEH_String(GOTSUIT); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + case SPR_PMAP: + if (!P_GivePower (player, pw_allmap)) + return; + player->message = DEH_String(GOTMAP); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + case SPR_PVIS: + if (!P_GivePower (player, pw_infrared)) + return; + player->message = DEH_String(GOTVISOR); + if (gameversion > exe_doom_1_2) + sound = sfx_getpow; + break; + + // ammo + case SPR_CLIP: + if (special->flags & MF_DROPPED) + { + if (!P_GiveAmmo (player,am_clip,0)) + return; + } + else + { + if (!P_GiveAmmo (player,am_clip,1)) + return; + } + player->message = DEH_String(GOTCLIP); + break; + + case SPR_AMMO: + if (!P_GiveAmmo (player, am_clip,5)) + return; + player->message = DEH_String(GOTCLIPBOX); + break; + + case SPR_ROCK: + if (!P_GiveAmmo (player, am_misl,1)) + return; + player->message = DEH_String(GOTROCKET); + break; + + case SPR_BROK: + if (!P_GiveAmmo (player, am_misl,5)) + return; + player->message = DEH_String(GOTROCKBOX); + break; + + case SPR_CELL: + if (!P_GiveAmmo (player, am_cell,1)) + return; + player->message = DEH_String(GOTCELL); + break; + + case SPR_CELP: + if (!P_GiveAmmo (player, am_cell,5)) + return; + player->message = DEH_String(GOTCELLBOX); + break; + + case SPR_SHEL: + if (!P_GiveAmmo (player, am_shell,1)) + return; + player->message = DEH_String(GOTSHELLS); + break; + + case SPR_SBOX: + if (!P_GiveAmmo (player, am_shell,5)) + return; + player->message = DEH_String(GOTSHELLBOX); + break; + + case SPR_BPAK: + if (!player->backpack) + { + for (i=0 ; imaxammo[i] *= 2; + player->backpack = true; + } + for (i=0 ; imessage = DEH_String(GOTBACKPACK); + break; + + // weapons + case SPR_BFUG: + if (!P_GiveWeapon (player, wp_bfg, false) ) + return; + player->message = DEH_String(GOTBFG9000); + sound = sfx_wpnup; + break; + + case SPR_MGUN: + if (!P_GiveWeapon(player, wp_chaingun, + (special->flags & MF_DROPPED) != 0)) + return; + player->message = DEH_String(GOTCHAINGUN); + sound = sfx_wpnup; + break; + + case SPR_CSAW: + if (!P_GiveWeapon (player, wp_chainsaw, false) ) + return; + player->message = DEH_String(GOTCHAINSAW); + sound = sfx_wpnup; + break; + + case SPR_LAUN: + if (!P_GiveWeapon (player, wp_missile, false) ) + return; + player->message = DEH_String(GOTLAUNCHER); + sound = sfx_wpnup; + break; + + case SPR_PLAS: + if (!P_GiveWeapon (player, wp_plasma, false) ) + return; + player->message = DEH_String(GOTPLASMA); + sound = sfx_wpnup; + break; + + case SPR_SHOT: + if (!P_GiveWeapon(player, wp_shotgun, + (special->flags & MF_DROPPED) != 0)) + return; + player->message = DEH_String(GOTSHOTGUN); + sound = sfx_wpnup; + break; + + case SPR_SGN2: + if (!P_GiveWeapon(player, wp_supershotgun, + (special->flags & MF_DROPPED) != 0)) + return; + player->message = DEH_String(GOTSHOTGUN2); + sound = sfx_wpnup; + break; + + default: + I_Error ("P_SpecialThing: Unknown gettable thing"); + } + + if (special->flags & MF_COUNTITEM) + player->itemcount++; + P_RemoveMobj (special); + player->bonuscount += BONUSADD; + if (player == &players[consoleplayer]) + S_StartSound (NULL, sound); +} + + +// +// KillMobj +// +void +P_KillMobj +( mobj_t* source, + mobj_t* target ) +{ + mobjtype_t item; + mobj_t* mo; + + target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); + + if (target->type != MT_SKULL) + target->flags &= ~MF_NOGRAVITY; + + target->flags |= MF_CORPSE|MF_DROPOFF; + target->height >>= 2; + + if (source && source->player) + { + // count for intermission + if (target->flags & MF_COUNTKILL) + source->player->killcount++; + + if (target->player) + source->player->frags[target->player-players]++; + } + else if (!netgame && (target->flags & MF_COUNTKILL) ) + { + // count all monster deaths, + // even those caused by other monsters + players[0].killcount++; + } + + if (target->player) + { + // count environment kills against you + if (!source) + target->player->frags[target->player-players]++; + + target->flags &= ~MF_SOLID; + target->player->playerstate = PST_DEAD; + P_DropWeapon (target->player); + + if (target->player == &players[consoleplayer] + && automapactive) + { + // don't die in auto map, + // switch view prior to dying + AM_Stop (); + } + + } + + if (target->health < -target->info->spawnhealth + && target->info->xdeathstate) + { + P_SetMobjState (target, target->info->xdeathstate); + } + else + P_SetMobjState (target, target->info->deathstate); + target->tics -= P_Random()&3; + + if (target->tics < 1) + target->tics = 1; + + // I_StartSound (&actor->r, actor->info->deathsound); + + // In Chex Quest, monsters don't drop items. + + if (gameversion == exe_chex) + { + return; + } + + // Drop stuff. + // This determines the kind of object spawned + // during the death frame of a thing. + switch (target->type) + { + case MT_WOLFSS: + case MT_POSSESSED: + item = MT_CLIP; + break; + + case MT_SHOTGUY: + item = MT_SHOTGUN; + break; + + case MT_CHAINGUY: + item = MT_CHAINGUN; + break; + + default: + return; + } + + mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item); + mo->flags |= MF_DROPPED; // special versions of items +} + + + + +// +// P_DamageMobj +// Damages both enemies and players +// "inflictor" is the thing that caused the damage +// creature or missile, can be NULL (slime, etc) +// "source" is the thing to target after taking damage +// creature or NULL +// Source and inflictor are the same for melee attacks. +// Source can be NULL for slime, barrel explosions +// and other environmental stuff. +// +void +P_DamageMobj +( mobj_t* target, + mobj_t* inflictor, + mobj_t* source, + int damage ) +{ + unsigned ang; + int saved; + player_t* player; + fixed_t thrust; + int temp; + + if ( !(target->flags & MF_SHOOTABLE) ) + return; // shouldn't happen... + + if (target->health <= 0) + return; + + if ( target->flags & MF_SKULLFLY ) + { + target->momx = target->momy = target->momz = 0; + } + + player = target->player; + if (player && gameskill == sk_baby) + damage >>= 1; // take half damage in trainer mode + + + // Some close combat weapons should not + // inflict thrust and push the victim out of reach, + // thus kick away unless using the chainsaw. + if (inflictor + && !(target->flags & MF_NOCLIP) + && (!source + || !source->player + || source->player->readyweapon != wp_chainsaw)) + { + ang = R_PointToAngle2 ( inflictor->x, + inflictor->y, + target->x, + target->y); + + thrust = damage*(FRACUNIT>>3)*100/target->info->mass; + + // make fall forwards sometimes + if ( damage < 40 + && damage > target->health + && target->z - inflictor->z > 64*FRACUNIT + && (P_Random ()&1) ) + { + ang += ANG180; + thrust *= 4; + } + + ang >>= ANGLETOFINESHIFT; + target->momx += FixedMul (thrust, finecosine[ang]); + target->momy += FixedMul (thrust, finesine[ang]); + } + + // player specific + if (player) + { + // end of game hell hack + if (target->subsector->sector->special == 11 + && damage >= target->health) + { + damage = target->health - 1; + } + + + // Below certain threshold, + // ignore damage in GOD mode, or with INVUL power. + if ( damage < 1000 + && ( (player->cheats&CF_GODMODE) + || player->powers[pw_invulnerability] ) ) + { + return; + } + + if (player->armortype) + { + if (player->armortype == 1) + saved = damage/3; + else + saved = damage/2; + + if (player->armorpoints <= saved) + { + // armor is used up + saved = player->armorpoints; + player->armortype = 0; + } + player->armorpoints -= saved; + damage -= saved; + } + player->health -= damage; // mirror mobj health here for Dave + if (player->health < 0) + player->health = 0; + + player->attacker = source; + player->damagecount += damage; // add damage after armor / invuln + + if (player->damagecount > 100) + player->damagecount = 100; // teleport stomp does 10k points... + + temp = damage < 100 ? damage : 100; + + if (player == &players[consoleplayer]) + I_Tactile (40,10,40+temp*2); + } + + // do the damage + target->health -= damage; + if (target->health <= 0) + { + P_KillMobj (source, target); + return; + } + + if ( (P_Random () < target->info->painchance) + && !(target->flags&MF_SKULLFLY) ) + { + target->flags |= MF_JUSTHIT; // fight back! + + P_SetMobjState (target, target->info->painstate); + } + + target->reactiontime = 0; // we're awake now... + + if ( (!target->threshold || target->type == MT_VILE) + && source && (source != target || gameversion < exe_doom_1_5) + && source->type != MT_VILE) + { + // if not intent on another player, + // chase after this one + target->target = source; + target->threshold = BASETHRESHOLD; + if (target->state == &states[target->info->spawnstate] + && target->info->seestate != S_NULL) + P_SetMobjState (target, target->info->seestate); + } + +} + diff --git a/games/NXDoom/src/doom/p_inter.h b/games/NXDoom/src/doom/p_inter.h new file mode 100644 index 00000000000..5764d5dab51 --- /dev/null +++ b/games/NXDoom/src/doom/p_inter.h @@ -0,0 +1,30 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __P_INTER__ +#define __P_INTER__ + + + + +boolean P_GivePower(player_t*, int); + + + +#endif diff --git a/games/NXDoom/src/doom/p_lights.c b/games/NXDoom/src/doom/p_lights.c new file mode 100644 index 00000000000..863338dcf3c --- /dev/null +++ b/games/NXDoom/src/doom/p_lights.c @@ -0,0 +1,350 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handle Sector base lighting effects. +// Muzzle flash? +// + + + +#include "z_zone.h" +#include "m_random.h" + +#include "doomdef.h" +#include "p_local.h" + + +// State. +#include "r_state.h" + +// +// FIRELIGHT FLICKER +// + +// +// T_FireFlicker +// +void T_FireFlicker (fireflicker_t* flick) +{ + int amount; + + if (--flick->count) + return; + + amount = (P_Random()&3)*16; + + if (flick->sector->lightlevel - amount < flick->minlight) + flick->sector->lightlevel = flick->minlight; + else + flick->sector->lightlevel = flick->maxlight - amount; + + flick->count = 4; +} + + + +// +// P_SpawnFireFlicker +// +void P_SpawnFireFlicker (sector_t* sector) +{ + fireflicker_t* flick; + + // Note that we are resetting sector attributes. + // Nothing special about it during gameplay. + sector->special = 0; + + flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); + + P_AddThinker (&flick->thinker); + + flick->thinker.function.acp1 = (actionf_p1) T_FireFlicker; + flick->sector = sector; + flick->maxlight = sector->lightlevel; + flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16; + flick->count = 4; +} + + + +// +// BROKEN LIGHT FLASHING +// + + +// +// T_LightFlash +// Do flashing lights. +// +void T_LightFlash (lightflash_t* flash) +{ + if (--flash->count) + return; + + if (flash->sector->lightlevel == flash->maxlight) + { + flash-> sector->lightlevel = flash->minlight; + flash->count = (P_Random()&flash->mintime)+1; + } + else + { + flash-> sector->lightlevel = flash->maxlight; + flash->count = (P_Random()&flash->maxtime)+1; + } + +} + + + + +// +// P_SpawnLightFlash +// After the map has been loaded, scan each sector +// for specials that spawn thinkers +// +void P_SpawnLightFlash (sector_t* sector) +{ + lightflash_t* flash; + + // nothing special about it during gameplay + sector->special = 0; + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + + P_AddThinker (&flash->thinker); + + flash->thinker.function.acp1 = (actionf_p1) T_LightFlash; + flash->sector = sector; + flash->maxlight = sector->lightlevel; + + flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); + flash->maxtime = 64; + flash->mintime = 7; + flash->count = (P_Random()&flash->maxtime)+1; +} + + + +// +// STROBE LIGHT FLASHING +// + + +// +// T_StrobeFlash +// +void T_StrobeFlash (strobe_t* flash) +{ + if (--flash->count) + return; + + if (flash->sector->lightlevel == flash->minlight) + { + flash-> sector->lightlevel = flash->maxlight; + flash->count = flash->brighttime; + } + else + { + flash-> sector->lightlevel = flash->minlight; + flash->count =flash->darktime; + } + +} + + + +// +// P_SpawnStrobeFlash +// After the map has been loaded, scan each sector +// for specials that spawn thinkers +// +void +P_SpawnStrobeFlash +( sector_t* sector, + int fastOrSlow, + int inSync ) +{ + strobe_t* flash; + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + + P_AddThinker (&flash->thinker); + + flash->sector = sector; + flash->darktime = fastOrSlow; + flash->brighttime = STROBEBRIGHT; + flash->thinker.function.acp1 = (actionf_p1) T_StrobeFlash; + flash->maxlight = sector->lightlevel; + flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); + + if (flash->minlight == flash->maxlight) + flash->minlight = 0; + + // nothing special about it during gameplay + sector->special = 0; + + if (!inSync) + flash->count = (P_Random()&7)+1; + else + flash->count = 1; +} + + +// +// Start strobing lights (usually from a trigger) +// +void EV_StartLightStrobing(line_t* line) +{ + int secnum; + sector_t* sec; + + secnum = -1; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + P_SpawnStrobeFlash (sec,SLOWDARK, 0); + } +} + + + +// +// TURN LINE'S TAG LIGHTS OFF +// +void EV_TurnTagLightsOff(line_t* line) +{ + int i; + int j; + int min; + sector_t* sector; + sector_t* tsec; + line_t* templine; + + sector = sectors; + + for (j = 0;j < numsectors; j++, sector++) + { + if (sector->tag == line->tag) + { + min = sector->lightlevel; + for (i = 0;i < sector->linecount; i++) + { + templine = sector->lines[i]; + tsec = getNextSector(templine,sector); + if (!tsec) + continue; + if (tsec->lightlevel < min) + min = tsec->lightlevel; + } + sector->lightlevel = min; + } + } +} + + +// +// TURN LINE'S TAG LIGHTS ON +// +void +EV_LightTurnOn +( line_t* line, + int bright ) +{ + int i; + int j; + sector_t* sector; + sector_t* temp; + line_t* templine; + + sector = sectors; + + for (i=0;itag == line->tag) + { + // bright = 0 means to search + // for highest light level + // surrounding sector + if (!bright) + { + for (j = 0;j < sector->linecount; j++) + { + templine = sector->lines[j]; + temp = getNextSector(templine,sector); + + if (!temp) + continue; + + if (temp->lightlevel > bright) + bright = temp->lightlevel; + } + } + sector-> lightlevel = bright; + } + } +} + + +// +// Spawn glowing light +// + +void T_Glow(glow_t* g) +{ + switch(g->direction) + { + case -1: + // DOWN + g->sector->lightlevel -= GLOWSPEED; + if (g->sector->lightlevel <= g->minlight) + { + g->sector->lightlevel += GLOWSPEED; + g->direction = 1; + } + break; + + case 1: + // UP + g->sector->lightlevel += GLOWSPEED; + if (g->sector->lightlevel >= g->maxlight) + { + g->sector->lightlevel -= GLOWSPEED; + g->direction = -1; + } + break; + } +} + + +void P_SpawnGlowingLight(sector_t* sector) +{ + glow_t* g; + + g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); + + P_AddThinker(&g->thinker); + + g->sector = sector; + g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); + g->maxlight = sector->lightlevel; + g->thinker.function.acp1 = (actionf_p1) T_Glow; + g->direction = -1; + + sector->special = 0; +} + diff --git a/games/NXDoom/src/doom/p_local.h b/games/NXDoom/src/doom/p_local.h new file mode 100644 index 00000000000..41159676223 --- /dev/null +++ b/games/NXDoom/src/doom/p_local.h @@ -0,0 +1,305 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Play functions, animation, global header. +// + + +#ifndef __P_LOCAL__ +#define __P_LOCAL__ + +#ifndef __R_LOCAL__ +#include "r_local.h" +#endif + +#define FLOATSPEED (FRACUNIT*4) + + +#define MAXHEALTH 100 +#define VIEWHEIGHT (41*FRACUNIT) + +// mapblocks are used to check movement +// against lines and things +#define MAPBLOCKUNITS 128 +#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) +#define MAPBLOCKSHIFT (FRACBITS+7) +#define MAPBMASK (MAPBLOCKSIZE-1) +#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) + + +// player radius for movement checking +#define PLAYERRADIUS 16*FRACUNIT + +// MAXRADIUS is for precalculated sector block boxes +// the spider demon is larger, +// but we do not have any moving sectors nearby +#define MAXRADIUS 32*FRACUNIT + +#define GRAVITY FRACUNIT +#define MAXMOVE (30*FRACUNIT) + +#define USERANGE (64*FRACUNIT) +#define MELEERANGE (64*FRACUNIT) +#define MISSILERANGE (32*64*FRACUNIT) + +// follow a player exlusively for 3 seconds +#define BASETHRESHOLD 100 + + + +// +// P_TICK +// + +// both the head and tail of the thinker list +extern thinker_t thinkercap; + + +void P_InitThinkers (void); +void P_AddThinker (thinker_t* thinker); +void P_RemoveThinker (thinker_t* thinker); + + +// +// P_PSPR +// +void P_SetupPsprites (player_t* curplayer); +void P_MovePsprites (player_t* curplayer); +void P_DropWeapon (player_t* player); + + +// +// P_USER +// +void P_PlayerThink (player_t* player); + + +// +// P_MOBJ +// +#define ONFLOORZ INT_MIN +#define ONCEILINGZ INT_MAX + +// Time interval for item respawning. +#define ITEMQUESIZE 128 + +extern mapthing_t itemrespawnque[ITEMQUESIZE]; +extern int itemrespawntime[ITEMQUESIZE]; +extern int iquehead; +extern int iquetail; + + +void P_RespawnSpecials (void); + +mobj_t* +P_SpawnMobj +( fixed_t x, + fixed_t y, + fixed_t z, + mobjtype_t type ); + +void P_RemoveMobj (mobj_t* th); +mobj_t* P_SubstNullMobj (mobj_t* th); +boolean P_SetMobjState (mobj_t* mobj, statenum_t state); +void P_MobjThinker (mobj_t* mobj); + +void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); +void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); +mobj_t* P_SpawnMissile (mobj_t* source, mobj_t* dest, mobjtype_t type); +void P_SpawnPlayerMissile (mobj_t* source, mobjtype_t type); + + +// +// P_ENEMY +// +void P_NoiseAlert (mobj_t* target, mobj_t* emmiter); + + +// +// P_MAPUTL +// +typedef struct +{ + fixed_t x; + fixed_t y; + fixed_t dx; + fixed_t dy; + +} divline_t; + +typedef struct +{ + fixed_t frac; // along trace line + boolean isaline; + union { + mobj_t* thing; + line_t* line; + } d; +} intercept_t; + +// Extended MAXINTERCEPTS, to allow for intercepts overrun emulation. + +#define MAXINTERCEPTS_ORIGINAL 128 +#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61) + +extern intercept_t intercepts[MAXINTERCEPTS]; +extern intercept_t* intercept_p; + +typedef boolean (*traverser_t) (intercept_t *in); + +fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); +int P_PointOnLineSide (fixed_t x, fixed_t y, line_t* line); +int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t* line); +void P_MakeDivline (line_t* li, divline_t* dl); +fixed_t P_InterceptVector (divline_t* v2, divline_t* v1); +int P_BoxOnLineSide (fixed_t* tmbox, line_t* ld); + +extern fixed_t opentop; +extern fixed_t openbottom; +extern fixed_t openrange; +extern fixed_t lowfloor; + +void P_LineOpening (line_t* linedef); + +boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); +boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ); + +#define PT_ADDLINES 1 +#define PT_ADDTHINGS 2 +#define PT_EARLYOUT 4 + +extern divline_t trace; + +boolean +P_PathTraverse +( fixed_t x1, + fixed_t y1, + fixed_t x2, + fixed_t y2, + int flags, + boolean (*trav) (intercept_t *)); + +void P_UnsetThingPosition (mobj_t* thing); +void P_SetThingPosition (mobj_t* thing); + + +// +// P_MAP +// + +// If "floatok" true, move would be ok +// if within "tmfloorz - tmceilingz". +extern boolean floatok; +extern fixed_t tmfloorz; +extern fixed_t tmceilingz; + + +extern line_t* ceilingline; + +// fraggle: I have increased the size of this buffer. In the original Doom, +// overrunning past this limit caused other bits of memory to be overwritten, +// affecting demo playback. However, in doing so, the limit was still +// exceeded. So we have to support more than 8 specials. +// +// We keep the original limit, to detect what variables in memory were +// overwritten (see SpechitOverrun()) + +#define MAXSPECIALCROSS 20 +#define MAXSPECIALCROSS_ORIGINAL 8 + +extern line_t* spechit[MAXSPECIALCROSS]; +extern int numspechit; + +boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); +boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); +boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y); +void P_SlideMove (mobj_t* mo); +boolean P_CheckSight (mobj_t* t1, mobj_t* t2); +void P_UseLines (player_t* player); + +boolean P_ChangeSector (sector_t* sector, boolean crunch); + +extern mobj_t* linetarget; // who got hit (or NULL) + + +extern fixed_t attackrange; + +// slopes to top and bottom of target +extern fixed_t topslope; +extern fixed_t bottomslope; + + +fixed_t +P_AimLineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance ); + +void +P_LineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance, + fixed_t slope, + int damage ); + +void +P_RadiusAttack +( mobj_t* spot, + mobj_t* source, + int damage ); + + + +// +// P_SETUP +// +extern byte* rejectmatrix; // for fast sight rejection +extern short* blockmaplump; // offsets in blockmap are from here +extern short* blockmap; +extern int bmapwidth; +extern int bmapheight; // in mapblocks +extern fixed_t bmaporgx; +extern fixed_t bmaporgy; // origin of block map +extern mobj_t** blocklinks; // for thing chains + + + +// +// P_INTER +// +extern int maxammo[NUMAMMO]; +extern int clipammo[NUMAMMO]; + +void +P_TouchSpecialThing +( mobj_t* special, + mobj_t* toucher ); + +void +P_DamageMobj +( mobj_t* target, + mobj_t* inflictor, + mobj_t* source, + int damage ); + + +// +// P_SPEC +// +#include "p_spec.h" + + +#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/doom/p_map.c b/games/NXDoom/src/doom/p_map.c new file mode 100644 index 00000000000..425416ce7fc --- /dev/null +++ b/games/NXDoom/src/doom/p_map.c @@ -0,0 +1,1445 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard, Andrey Budko +// +// 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. +// +// DESCRIPTION: +// Movement, collision handling. +// Shooting and aiming. +// + +#include +#include + +#include "deh_misc.h" + +#include "m_bbox.h" +#include "m_random.h" +#include "i_system.h" + +#include "doomdef.h" +#include "m_argv.h" +#include "m_misc.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" +// Data. +#include "sounds.h" + +// Spechit overrun magic value. +// +// This is the value used by PrBoom-plus. I think the value below is +// actually better and works with more demos. However, I think +// it's better for the spechits emulation to be compatible with +// PrBoom-plus, at least so that the big spechits emulation list +// on Doomworld can also be used with Chocolate Doom. + +#define DEFAULT_SPECHIT_MAGIC 0x01C09C98 + +// This is from a post by myk on the Doomworld forums, +// outputted from entryway's spechit_magic generator for +// s205n546.lmp. The _exact_ value of this isn't too +// important; as long as it is in the right general +// range, it will usually work. Otherwise, we can use +// the generator (hacked doom2.exe) and provide it +// with -spechit. + +//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8 + + +fixed_t tmbbox[4]; +mobj_t* tmthing; +int tmflags; +fixed_t tmx; +fixed_t tmy; + + +// If "floatok" true, move would be ok +// if within "tmfloorz - tmceilingz". +boolean floatok; + +fixed_t tmfloorz; +fixed_t tmceilingz; +fixed_t tmdropoffz; + +// keep track of the line that lowers the ceiling, +// so missiles don't explode against sky hack walls +line_t* ceilingline; + +// keep track of special lines as they are hit, +// but don't process them until the move is proven valid + +line_t* spechit[MAXSPECIALCROSS]; +int numspechit; + + + +// +// TELEPORT MOVE +// + +// +// PIT_StompThing +// +boolean PIT_StompThing (mobj_t* thing) +{ + fixed_t blockdist; + + if (!(thing->flags & MF_SHOOTABLE) ) + return true; + + blockdist = thing->radius + tmthing->radius; + + if ( abs(thing->x - tmx) >= blockdist + || abs(thing->y - tmy) >= blockdist ) + { + // didn't hit it + return true; + } + + // don't clip against self + if (thing == tmthing) + return true; + + // monsters don't stomp things except on boss level + if ( !tmthing->player && gamemap != 30) + return false; + + P_DamageMobj (thing, tmthing, tmthing, 10000); + + return true; +} + + +// +// P_TeleportMove +// +boolean +P_TeleportMove +( mobj_t* thing, + fixed_t x, + fixed_t y ) +{ + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + + subsector_t* newsubsec; + + // kill anything occupying the position + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector (x,y); + ceilingline = NULL; + + // The base floor/ceiling is from the subsector + // that contains the point. + // Any contacted lines the step closer together + // will adjust them. + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + // stomp on any things contacted + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + for (bx=xl ; bx<=xh ; bx++) + for (by=yl ; by<=yh ; by++) + if (!P_BlockThingsIterator(bx,by,PIT_StompThing)) + return false; + + // the move is ok, + // so link the thing into its new position + P_UnsetThingPosition (thing); + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + P_SetThingPosition (thing); + + return true; +} + + +// +// MOVEMENT ITERATOR FUNCTIONS +// + +static void SpechitOverrun(line_t *ld); + +// +// PIT_CheckLine +// Adjusts tmfloorz and tmceilingz as lines are contacted +// +boolean PIT_CheckLine (line_t* ld) +{ + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] + || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] + || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) + return true; + + if (P_BoxOnLineSide (tmbbox, ld) != -1) + return true; + + // A line has been hit + + // The moving thing's destination position will cross + // the given line. + // If this should not be allowed, return false. + // If the line is special, keep track of it + // to process later if the move is proven ok. + // NOTE: specials are NOT sorted by order, + // so two special lines that are only 8 pixels apart + // could be crossed in either order. + + if (!ld->backsector) + return false; // one sided line + + if (!(tmthing->flags & MF_MISSILE) ) + { + if ( ld->flags & ML_BLOCKING ) + return false; // explicitly blocking everything + + if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS ) + return false; // block monsters only + } + + // set openrange, opentop, openbottom + P_LineOpening (ld); + + // adjust floor / ceiling heights + if (opentop < tmceilingz) + { + tmceilingz = opentop; + ceilingline = ld; + } + + if (openbottom > tmfloorz) + tmfloorz = openbottom; + + if (lowfloor < tmdropoffz) + tmdropoffz = lowfloor; + + // if contacted a special line, add it to the list + if (ld->special) + { + spechit[numspechit] = ld; + numspechit++; + + // fraggle: spechits overrun emulation code from prboom-plus + if (numspechit > MAXSPECIALCROSS_ORIGINAL) + { + SpechitOverrun(ld); + } + } + + return true; +} + +// +// PIT_CheckThing +// +boolean PIT_CheckThing (mobj_t* thing) +{ + fixed_t blockdist; + boolean solid; + int damage; + + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) )) + return true; + + blockdist = thing->radius + tmthing->radius; + + if ( abs(thing->x - tmx) >= blockdist + || abs(thing->y - tmy) >= blockdist ) + { + // didn't hit it + return true; + } + + // don't clip against self + if (thing == tmthing) + return true; + + // check for skulls slamming into things + if (tmthing->flags & MF_SKULLFLY) + { + damage = ((P_Random()%8)+1)*tmthing->info->damage; + + P_DamageMobj (thing, tmthing, tmthing, damage); + + tmthing->flags &= ~MF_SKULLFLY; + tmthing->momx = tmthing->momy = tmthing->momz = 0; + + P_SetMobjState (tmthing, tmthing->info->spawnstate); + + return false; // stop moving + } + + + // missiles can hit other things + if (tmthing->flags & MF_MISSILE) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z+tmthing->height < thing->z) + return true; // underneath + + if (tmthing->target + && (tmthing->target->type == thing->type || + (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)|| + (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) ) + { + // Don't hit same species as originator. + if (thing == tmthing->target) + return true; + + // sdh: Add deh_species_infighting here. We can override the + // "monsters of the same species cant hurt each other" behavior + // through dehacked patches + + if (thing->type != MT_PLAYER && !deh_species_infighting) + { + // Explode, but do no damage. + // Let players missile other players. + return false; + } + } + + if (! (thing->flags & MF_SHOOTABLE) ) + { + // didn't do any damage + return !(thing->flags & MF_SOLID); + } + + // damage / explode + damage = ((P_Random()%8)+1)*tmthing->info->damage; + P_DamageMobj (thing, tmthing, tmthing->target, damage); + + // don't traverse any more + return false; + } + + // check for special pickup + if (thing->flags & MF_SPECIAL) + { + solid = (thing->flags & MF_SOLID) != 0; + if (tmflags&MF_PICKUP) + { + // can remove thing + P_TouchSpecialThing (thing, tmthing); + } + return !solid; + } + + return !(thing->flags & MF_SOLID); +} + + +// +// MOVEMENT CLIPPING +// + +// +// P_CheckPosition +// This is purely informative, nothing is modified +// (except things picked up). +// +// in: +// a mobj_t (can be valid or invalid) +// a position to be checked +// (doesn't need to be related to the mobj_t->x,y) +// +// during: +// special things are touched if MF_PICKUP +// early out on solid lines? +// +// out: +// newsubsec +// floorz +// ceilingz +// tmdropoffz +// the lowest point contacted +// (monsters won't move to a dropoff) +// speciallines[] +// numspeciallines +// +boolean +P_CheckPosition +( mobj_t* thing, + fixed_t x, + fixed_t y ) +{ + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + subsector_t* newsubsec; + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector (x,y); + ceilingline = NULL; + + // The base floor / ceiling is from the subsector + // that contains the point. + // Any contacted lines the step closer together + // will adjust them. + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + if ( tmflags & MF_NOCLIP ) + return true; + + // Check things first, possibly picking things up. + // The bounding box is extended by MAXRADIUS + // because mobj_ts are grouped into mapblocks + // based on their origin point, and can overlap + // into adjacent blocks by up to MAXRADIUS units. + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + for (bx=xl ; bx<=xh ; bx++) + for (by=yl ; by<=yh ; by++) + if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) + return false; + + // check lines + xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + + for (bx=xl ; bx<=xh ; bx++) + for (by=yl ; by<=yh ; by++) + if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) + return false; + + return true; +} + + +// +// P_TryMove +// Attempt to move to a new position, +// crossing special lines unless MF_TELEPORT is set. +// +boolean +P_TryMove +( mobj_t* thing, + fixed_t x, + fixed_t y ) +{ + fixed_t oldx; + fixed_t oldy; + int side; + int oldside; + line_t* ld; + + floatok = false; + if (!P_CheckPosition (thing, x, y)) + return false; // solid wall or thing + + if ( !(thing->flags & MF_NOCLIP) ) + { + if (tmceilingz - tmfloorz < thing->height) + return false; // doesn't fit + + floatok = true; + + if ( !(thing->flags&MF_TELEPORT) + &&tmceilingz - thing->z < thing->height) + return false; // mobj must lower itself to fit + + if ( !(thing->flags&MF_TELEPORT) + && tmfloorz - thing->z > 24*FRACUNIT ) + return false; // too big a step up + + if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) + && tmfloorz - tmdropoffz > 24*FRACUNIT ) + return false; // don't stand over a dropoff + } + + // the move is ok, + // so link the thing into its new position + P_UnsetThingPosition (thing); + + oldx = thing->x; + oldy = thing->y; + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + P_SetThingPosition (thing); + + // if any special lines were hit, do the effect + if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) ) + { + while (numspechit--) + { + // see if the line was crossed + ld = spechit[numspechit]; + side = P_PointOnLineSide (thing->x, thing->y, ld); + oldside = P_PointOnLineSide (oldx, oldy, ld); + if (side != oldside) + { + if (ld->special) + P_CrossSpecialLine (ld-lines, oldside, thing); + } + } + } + + return true; +} + + +// +// P_ThingHeightClip +// Takes a valid thing and adjusts the thing->floorz, +// thing->ceilingz, and possibly thing->z. +// This is called for all nearby monsters +// whenever a sector changes height. +// If the thing doesn't fit, +// the z will be set to the lowest value +// and false will be returned. +// +boolean P_ThingHeightClip (mobj_t* thing) +{ + boolean onfloor; + + onfloor = (thing->z == thing->floorz); + + P_CheckPosition (thing, thing->x, thing->y); + // what about stranding a monster partially off an edge? + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + + if (onfloor) + { + // walking monsters rise and fall with the floor + thing->z = thing->floorz; + } + else + { + // don't adjust a floating monster unless forced to + if (thing->z+thing->height > thing->ceilingz) + thing->z = thing->ceilingz - thing->height; + } + + if (thing->ceilingz - thing->floorz < thing->height) + return false; + + return true; +} + + + +// +// SLIDE MOVE +// Allows the player to slide along any angled walls. +// +fixed_t bestslidefrac; +fixed_t secondslidefrac; + +line_t* bestslideline; +line_t* secondslideline; + +mobj_t* slidemo; + +fixed_t tmxmove; +fixed_t tmymove; + + + +// +// P_HitSlideLine +// Adjusts the xmove / ymove +// so that the next move will slide along the wall. +// +void P_HitSlideLine (line_t* ld) +{ + int side; + + angle_t lineangle; + angle_t moveangle; + angle_t deltaangle; + + fixed_t movelen; + fixed_t newlen; + + + if (ld->slopetype == ST_HORIZONTAL) + { + tmymove = 0; + return; + } + + if (ld->slopetype == ST_VERTICAL) + { + tmxmove = 0; + return; + } + + side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); + + lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); + + if (side == 1) + lineangle += ANG180; + + moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); + deltaangle = moveangle-lineangle; + + if (deltaangle > ANG180) + deltaangle += ANG180; + // I_Error ("SlideLine: ang>ANG180"); + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance (tmxmove, tmymove); + newlen = FixedMul (movelen, finecosine[deltaangle]); + + tmxmove = FixedMul (newlen, finecosine[lineangle]); + tmymove = FixedMul (newlen, finesine[lineangle]); +} + + +// +// PTR_SlideTraverse +// +boolean PTR_SlideTraverse (intercept_t* in) +{ + line_t* li; + + if (!in->isaline) + I_Error ("PTR_SlideTraverse: not a line?"); + + li = in->d.line; + + if ( ! (li->flags & ML_TWOSIDED) ) + { + if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) + { + // don't hit the back side + return true; + } + goto isblocking; + } + + // set openrange, opentop, openbottom + P_LineOpening (li); + + if (openrange < slidemo->height) + goto isblocking; // doesn't fit + + if (opentop - slidemo->z < slidemo->height) + goto isblocking; // mobj is too high + + if (openbottom - slidemo->z > 24*FRACUNIT ) + goto isblocking; // too big a step up + + // this line doesn't block movement + return true; + + // the line does block movement, + // see if it is closer than best so far + isblocking: + if (in->frac < bestslidefrac) + { + secondslidefrac = bestslidefrac; + secondslideline = bestslideline; + bestslidefrac = in->frac; + bestslideline = li; + } + + return false; // stop +} + + + +// +// P_SlideMove +// The momx / momy move is bad, so try to slide +// along a wall. +// Find the first line hit, move flush to it, +// and slide along it +// +// This is a kludgy mess. +// +void P_SlideMove (mobj_t* mo) +{ + fixed_t leadx; + fixed_t leady; + fixed_t trailx; + fixed_t traily; + fixed_t newx; + fixed_t newy; + int hitcount; + + slidemo = mo; + hitcount = 0; + + retry: + if (++hitcount == 3) + goto stairstep; // don't loop forever + + + // trace along the three leading corners + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT+1; + + P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, + PT_ADDLINES, PTR_SlideTraverse ); + P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, + PT_ADDLINES, PTR_SlideTraverse ); + P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, + PT_ADDLINES, PTR_SlideTraverse ); + + // move up to the wall + if (bestslidefrac == FRACUNIT+1) + { + // the move most have hit the middle, so stairstep + stairstep: + if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) + P_TryMove (mo, mo->x + mo->momx, mo->y); + return; + } + + // fudge a bit to make sure it doesn't hit + bestslidefrac -= 0x800; + if (bestslidefrac > 0) + { + newx = FixedMul (mo->momx, bestslidefrac); + newy = FixedMul (mo->momy, bestslidefrac); + + if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) + goto stairstep; + } + + // Now continue along the wall. + // First calculate remainder. + bestslidefrac = FRACUNIT-(bestslidefrac+0x800); + + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; + + if (bestslidefrac <= 0) + return; + + tmxmove = FixedMul (mo->momx, bestslidefrac); + tmymove = FixedMul (mo->momy, bestslidefrac); + + P_HitSlideLine (bestslideline); // clip the moves + + mo->momx = tmxmove; + mo->momy = tmymove; + + if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove)) + { + goto retry; + } +} + + +// +// P_LineAttack +// +mobj_t* linetarget; // who got hit (or NULL) +mobj_t* shootthing; + +// Height if not aiming up or down +// ???: use slope for monsters? +fixed_t shootz; + +int la_damage; +fixed_t attackrange; + +fixed_t aimslope; + + +// +// PTR_AimTraverse +// Sets linetaget and aimslope when a target is aimed at. +// +boolean +PTR_AimTraverse (intercept_t* in) +{ + line_t* li; + mobj_t* th; + fixed_t slope; + fixed_t thingtopslope; + fixed_t thingbottomslope; + fixed_t dist; + + if (in->isaline) + { + li = in->d.line; + + if ( !(li->flags & ML_TWOSIDED) ) + return false; // stop + + // Crosses a two sided line. + // A two sided line will restrict + // the possible target ranges. + P_LineOpening (li); + + if (openbottom >= opentop) + return false; // stop + + dist = FixedMul (attackrange, in->frac); + + if (li->backsector == NULL + || li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv (openbottom - shootz , dist); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->backsector == NULL + || li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv (opentop - shootz , dist); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // shot continues + } + + // shoot a thing + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + + if (!(th->flags&MF_SHOOTABLE)) + return true; // corpse or something + + // check angles to see if the thing can be aimed at + dist = FixedMul (attackrange, in->frac); + thingtopslope = FixedDiv (th->z+th->height - shootz , dist); + + if (thingtopslope < bottomslope) + return true; // shot over the thing + + thingbottomslope = FixedDiv (th->z - shootz, dist); + + if (thingbottomslope > topslope) + return true; // shot under the thing + + // this thing can be hit! + if (thingtopslope > topslope) + thingtopslope = topslope; + + if (thingbottomslope < bottomslope) + thingbottomslope = bottomslope; + + aimslope = (thingtopslope+thingbottomslope)/2; + linetarget = th; + + return false; // don't go any farther +} + + +// +// PTR_ShootTraverse +// +boolean PTR_ShootTraverse (intercept_t* in) +{ + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t frac; + + line_t* li; + + mobj_t* th; + + fixed_t slope; + fixed_t dist; + fixed_t thingtopslope; + fixed_t thingbottomslope; + + if (in->isaline) + { + li = in->d.line; + + if (li->special) + P_ShootSpecialLine (shootthing, li); + + if ( !(li->flags & ML_TWOSIDED) ) + goto hitline; + + // crosses a two sided line + P_LineOpening (li); + + dist = FixedMul (attackrange, in->frac); + + // e6y: emulation of missed back side on two-sided lines. + // backsector can be NULL when emulating missing back side. + + if (li->backsector == NULL) + { + slope = FixedDiv (openbottom - shootz , dist); + if (slope > aimslope) + goto hitline; + + slope = FixedDiv (opentop - shootz , dist); + if (slope < aimslope) + goto hitline; + } + else + { + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv (openbottom - shootz , dist); + if (slope > aimslope) + goto hitline; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv (opentop - shootz , dist); + if (slope < aimslope) + goto hitline; + } + } + + // shot continues + return true; + + + // hit line + hitline: + // position a bit closer + frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); + x = trace.x + FixedMul (trace.dx, frac); + y = trace.y + FixedMul (trace.dy, frac); + z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); + + if (li->frontsector->ceilingpic == skyflatnum) + { + // don't shoot the sky! + if (z > li->frontsector->ceilingheight) + return false; + + // it's a sky hack wall + if (li->backsector && li->backsector->ceilingpic == skyflatnum) + return false; + } + + // Spawn bullet puffs. + P_SpawnPuff (x,y,z); + + // don't go any farther + return false; + } + + // shoot a thing + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + + if (!(th->flags&MF_SHOOTABLE)) + return true; // corpse or something + + // check angles to see if the thing can be aimed at + dist = FixedMul (attackrange, in->frac); + thingtopslope = FixedDiv (th->z+th->height - shootz , dist); + + if (thingtopslope < aimslope) + return true; // shot over the thing + + thingbottomslope = FixedDiv (th->z - shootz, dist); + + if (thingbottomslope > aimslope) + return true; // shot under the thing + + + // hit thing + // position a bit closer + frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); + + x = trace.x + FixedMul (trace.dx, frac); + y = trace.y + FixedMul (trace.dy, frac); + z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); + + // Spawn bullet puffs or blod spots, + // depending on target type. + if (in->d.thing->flags & MF_NOBLOOD) + P_SpawnPuff (x,y,z); + else + P_SpawnBlood (x,y,z, la_damage); + + if (la_damage) + P_DamageMobj (th, shootthing, shootthing, la_damage); + + // don't go any farther + return false; + +} + + +// +// P_AimLineAttack +// +fixed_t +P_AimLineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance ) +{ + fixed_t x2; + fixed_t y2; + + t1 = P_SubstNullMobj(t1); + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + + x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; + y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; + shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; + + // can't shoot outside view angles + topslope = (SCREENHEIGHT/2)*FRACUNIT/(SCREENWIDTH/2); + bottomslope = -(SCREENHEIGHT/2)*FRACUNIT/(SCREENWIDTH/2); + + attackrange = distance; + linetarget = NULL; + + P_PathTraverse ( t1->x, t1->y, + x2, y2, + PT_ADDLINES|PT_ADDTHINGS, + PTR_AimTraverse ); + + if (linetarget) + return aimslope; + + return 0; +} + + +// +// P_LineAttack +// If damage == 0, it is just a test trace +// that will leave linetarget set. +// +void +P_LineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance, + fixed_t slope, + int damage ) +{ + fixed_t x2; + fixed_t y2; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + la_damage = damage; + x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; + y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; + shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; + attackrange = distance; + aimslope = slope; + + P_PathTraverse ( t1->x, t1->y, + x2, y2, + PT_ADDLINES|PT_ADDTHINGS, + PTR_ShootTraverse ); +} + + + +// +// USE LINES +// +mobj_t* usething; + +boolean PTR_UseTraverse (intercept_t* in) +{ + int side; + + if (!in->d.line->special) + { + P_LineOpening (in->d.line); + if (openrange <= 0) + { + S_StartSound (usething, sfx_noway); + + // can't use through a wall + return false; + } + // not a special line, but keep checking + return true ; + } + + side = 0; + if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) + side = 1; + + // return false; // don't use back side + + P_UseSpecialLine (usething, in->d.line, side); + + // can't use for than one special line in a row + return false; +} + + +// +// P_UseLines +// Looks for special lines in front of the player to activate. +// +void P_UseLines (player_t* player) +{ + int angle; + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + usething = player->mo; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; + y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; + + P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); +} + + +// +// RADIUS ATTACK +// +mobj_t* bombsource; +mobj_t* bombspot; +int bombdamage; + + +// +// PIT_RadiusAttack +// "bombsource" is the creature +// that caused the explosion at "bombspot". +// +boolean PIT_RadiusAttack (mobj_t* thing) +{ + fixed_t dx; + fixed_t dy; + fixed_t dist; + + if (!(thing->flags & MF_SHOOTABLE) ) + return true; + + // Boss spider and cyborg + // take no damage from concussion. + if (thing->type == MT_CYBORG + || thing->type == MT_SPIDER) + return true; + + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + + dist = dx>dy ? dx : dy; + dist = (dist - thing->radius) >> FRACBITS; + + if (dist < 0) + dist = 0; + + if (dist >= bombdamage) + return true; // out of range + + if ( P_CheckSight (thing, bombspot) ) + { + // must be in direct path + P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist); + } + + return true; +} + + +// +// P_RadiusAttack +// Source is the creature that caused the explosion at spot. +// +void +P_RadiusAttack +( mobj_t* spot, + mobj_t* source, + int damage ) +{ + int x; + int y; + + int xl; + int xh; + int yl; + int yh; + + fixed_t dist; + + dist = (damage+MAXRADIUS)<y + dist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; + bombspot = spot; + bombsource = source; + bombdamage = damage; + + for (y=yl ; y<=yh ; y++) + for (x=xl ; x<=xh ; x++) + P_BlockThingsIterator (x, y, PIT_RadiusAttack ); +} + + + +// +// SECTOR HEIGHT CHANGING +// After modifying a sectors floor or ceiling height, +// call this routine to adjust the positions +// of all things that touch the sector. +// +// If anything doesn't fit anymore, true will be returned. +// If crunch is true, they will take damage +// as they are being crushed. +// If Crunch is false, you should set the sector height back +// the way it was and call P_ChangeSector again +// to undo the changes. +// +boolean crushchange; +boolean nofit; + + +// +// PIT_ChangeSector +// +boolean PIT_ChangeSector (mobj_t* thing) +{ + mobj_t* mo; + + if (P_ThingHeightClip (thing)) + { + // keep checking + return true; + } + + + // crunch bodies to giblets + if (thing->health <= 0) + { + P_SetMobjState (thing, S_GIBS); + + if (gameversion > exe_doom_1_2) + thing->flags &= ~MF_SOLID; + thing->height = 0; + thing->radius = 0; + + // keep checking + return true; + } + + // crunch dropped items + if (thing->flags & MF_DROPPED) + { + P_RemoveMobj (thing); + + // keep checking + return true; + } + + if (! (thing->flags & MF_SHOOTABLE) ) + { + // assume it is bloody gibs or something + return true; + } + + nofit = true; + + if (crushchange && !(leveltime&3) ) + { + P_DamageMobj(thing,NULL,NULL,10); + + // spray blood in a random direction + mo = P_SpawnMobj (thing->x, + thing->y, + thing->z + thing->height/2, MT_BLOOD); + + mo->momx = P_SubRandom() << 12; + mo->momy = P_SubRandom() << 12; + } + + // keep checking (crush other things) + return true; +} + + + +// +// P_ChangeSector +// +boolean +P_ChangeSector +( sector_t* sector, + boolean crunch ) +{ + int x; + int y; + + nofit = false; + crushchange = crunch; + + // re-check heights for all things near the moving sector + for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) + for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) + P_BlockThingsIterator (x, y, PIT_ChangeSector); + + + return nofit; +} + +// Code to emulate the behavior of Vanilla Doom when encountering an overrun +// of the spechit array. This is by Andrey Budko (e6y) and comes from his +// PrBoom plus port. A big thanks to Andrey for this. + +static void SpechitOverrun(line_t *ld) +{ + static unsigned int baseaddr = 0; + unsigned int addr; + + if (baseaddr == 0) + { + int p; + + // This is the first time we have had an overrun. Work out + // what base address we are going to use. + // Allow a spechit value to be specified on the command line. + + //! + // @category compat + // @arg + // + // Use the specified magic value when emulating spechit overruns. + // + + p = M_CheckParmWithArgs("-spechit", 1); + + if (p > 0) + { + M_StrToInt(myargv[p+1], (int *) &baseaddr); + } + else + { + baseaddr = DEFAULT_SPECHIT_MAGIC; + } + } + + // Calculate address used in doom2.exe + + addr = baseaddr + (ld - lines) * 0x3E; + + switch(numspechit) + { + case 9: + case 10: + case 11: + case 12: + tmbbox[numspechit-9] = addr; + break; + case 13: + crushchange = addr; + break; + case 14: + nofit = addr; + break; + default: + fprintf(stderr, "SpechitOverrun: Warning: unable to emulate" + "an overrun where numspechit=%i\n", + numspechit); + break; + } +} + diff --git a/games/NXDoom/src/doom/p_maputl.c b/games/NXDoom/src/doom/p_maputl.c new file mode 100644 index 00000000000..cb74c942f23 --- /dev/null +++ b/games/NXDoom/src/doom/p_maputl.c @@ -0,0 +1,1002 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// Copyright(C) 2005, 2006 Andrey Budko +// +// 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. +// +// DESCRIPTION: +// Movement/collision utility functions, +// as used by function in p_map.c. +// BLOCKMAP Iterator functions, +// and some PIT_* functions to use for iteration. +// + + + +#include + + +#include "m_bbox.h" +#include "m_misc.h" + +#include "doomdef.h" +#include "doomstat.h" +#include "p_local.h" + + +// State. +#include "r_state.h" + +// +// P_AproxDistance +// Gives an estimation of distance (not exact) +// + +fixed_t +P_AproxDistance +( fixed_t dx, + fixed_t dy ) +{ + dx = abs(dx); + dy = abs(dy); + if (dx < dy) + return dx+dy-(dx>>1); + return dx+dy-(dy>>1); +} + + +// +// P_PointOnLineSide +// Returns 0 or 1 +// +int +P_PointOnLineSide +( fixed_t x, + fixed_t y, + line_t* line ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!line->dx) + { + if (x <= line->v1->x) + return line->dy > 0; + + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->v1->y) + return line->dx < 0; + + return line->dx > 0; + } + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = FixedMul ( line->dy>>FRACBITS , dx ); + right = FixedMul ( dy , line->dx>>FRACBITS ); + + if (right < left) + return 0; // front side + return 1; // back side +} + + + +// +// P_BoxOnLineSide +// Considers the line to be infinite +// Returns side 0 or 1, -1 if box crosses the line. +// +int +P_BoxOnLineSide +( fixed_t* tmbox, + line_t* ld ) +{ + int p1 = 0; + int p2 = 0; + + switch (ld->slopetype) + { + case ST_HORIZONTAL: + p1 = tmbox[BOXTOP] > ld->v1->y; + p2 = tmbox[BOXBOTTOM] > ld->v1->y; + if (ld->dx < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + + case ST_VERTICAL: + p1 = tmbox[BOXRIGHT] < ld->v1->x; + p2 = tmbox[BOXLEFT] < ld->v1->x; + if (ld->dy < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + + case ST_POSITIVE: + p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); + break; + + case ST_NEGATIVE: + p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); + break; + } + + if (p1 == p2) + return p1; + return -1; +} + + +// +// P_PointOnDivlineSide +// Returns 0 or 1. +// +int +P_PointOnDivlineSide +( fixed_t x, + fixed_t y, + divline_t* line ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!line->dx) + { + if (x <= line->x) + return line->dy > 0; + + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->y) + return line->dx < 0; + + return line->dx > 0; + } + + dx = (x - line->x); + dy = (y - line->y); + + // try to quickly decide by looking at sign bits + if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) + { + if ( (line->dy ^ dx) & 0x80000000 ) + return 1; // (left is negative) + return 0; + } + + left = FixedMul ( line->dy>>8, dx>>8 ); + right = FixedMul ( dy>>8 , line->dx>>8 ); + + if (right < left) + return 0; // front side + return 1; // back side +} + + + +// +// P_MakeDivline +// +void +P_MakeDivline +( line_t* li, + divline_t* dl ) +{ + dl->x = li->v1->x; + dl->y = li->v1->y; + dl->dx = li->dx; + dl->dy = li->dy; +} + + + +// +// P_InterceptVector +// Returns the fractional intercept point +// along the first divline. +// This is only called by the addthings +// and addlines traversers. +// +fixed_t +P_InterceptVector +( divline_t* v2, + divline_t* v1 ) +{ +#if 1 + fixed_t frac; + fixed_t num; + fixed_t den; + + den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); + + if (den == 0) + return 0; + // I_Error ("P_InterceptVector: parallel"); + + num = + FixedMul ( (v1->x - v2->x)>>8 ,v1->dy ) + +FixedMul ( (v2->y - v1->y)>>8, v1->dx ); + + frac = FixedDiv (num , den); + + return frac; +#else // UNUSED, float debug. + float frac; + float num; + float den; + float v1x; + float v1y; + float v1dx; + float v1dy; + float v2x; + float v2y; + float v2dx; + float v2dy; + + v1x = (float)v1->x/FRACUNIT; + v1y = (float)v1->y/FRACUNIT; + v1dx = (float)v1->dx/FRACUNIT; + v1dy = (float)v1->dy/FRACUNIT; + v2x = (float)v2->x/FRACUNIT; + v2y = (float)v2->y/FRACUNIT; + v2dx = (float)v2->dx/FRACUNIT; + v2dy = (float)v2->dy/FRACUNIT; + + den = v1dy*v2dx - v1dx*v2dy; + + if (den == 0) + return 0; // parallel + + num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; + frac = num / den; + + return frac*FRACUNIT; +#endif +} + + +// +// P_LineOpening +// Sets opentop and openbottom to the window +// through a two sided line. +// OPTIMIZE: keep this precalculated +// +fixed_t opentop; +fixed_t openbottom; +fixed_t openrange; +fixed_t lowfloor; + + +void P_LineOpening (line_t* linedef) +{ + sector_t* front; + sector_t* back; + + if (linedef->sidenum[1] == -1) + { + // single sided line + openrange = 0; + return; + } + + front = linedef->frontsector; + back = linedef->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; + } + + openrange = opentop - openbottom; +} + + +// +// THING POSITION SETTING +// + + +// +// P_UnsetThingPosition +// Unlinks a thing from block map and sectors. +// On each position change, BLOCKMAP and other +// lookups maintaining lists ot things inside +// these structures need to be updated. +// +void P_UnsetThingPosition (mobj_t* thing) +{ + int blockx; + int blocky; + + if ( ! (thing->flags & MF_NOSECTOR) ) + { + // inert things don't need to be in blockmap? + // unlink from subsector + if (thing->snext) + thing->snext->sprev = thing->sprev; + + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + } + + if ( ! (thing->flags & MF_NOBLOCKMAP) ) + { + // inert things don't need to be in blockmap + // unlink from block map + if (thing->bnext) + thing->bnext->bprev = thing->bprev; + + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; + + if (blockx>=0 && blockx < bmapwidth + && blocky>=0 && blocky bnext; + } + } + } +} + + +// +// P_SetThingPosition +// Links a thing into both a block and a subsector +// based on it's x y. +// Sets thing->subsector properly +// +void +P_SetThingPosition (mobj_t* thing) +{ + subsector_t* ss; + sector_t* sec; + int blockx; + int blocky; + mobj_t** link; + + + // link into subsector + ss = R_PointInSubsector (thing->x,thing->y); + thing->subsector = ss; + + if ( ! (thing->flags & MF_NOSECTOR) ) + { + // invisible things don't go into the sector links + sec = ss->sector; + + thing->sprev = NULL; + thing->snext = sec->thinglist; + + if (sec->thinglist) + sec->thinglist->sprev = thing; + + sec->thinglist = thing; + } + + + // link into blockmap + if ( ! (thing->flags & MF_NOBLOCKMAP) ) + { + // inert things don't need to be in blockmap + blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; + + if (blockx>=0 + && blockx < bmapwidth + && blocky>=0 + && blocky < bmapheight) + { + link = &blocklinks[blocky*bmapwidth+blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) + (*link)->bprev = thing; + + *link = thing; + } + else + { + // thing is off the map + thing->bnext = thing->bprev = NULL; + } + } +} + + + +// +// BLOCK MAP ITERATORS +// For each line/thing in the given mapblock, +// call the passed PIT_* function. +// If the function returns false, +// exit with false without checking anything else. +// + + +// +// P_BlockLinesIterator +// The validcount flags are used to avoid checking lines +// that are marked in multiple mapblocks, +// so increment validcount before the first call +// to P_BlockLinesIterator, then make one or more calls +// to it. +// +boolean +P_BlockLinesIterator +( int x, + int y, + boolean(*func)(line_t*) ) +{ + int offset; + short* list; + line_t* ld; + + if (x<0 + || y<0 + || x>=bmapwidth + || y>=bmapheight) + { + return true; + } + + offset = y*bmapwidth+x; + + offset = *(blockmap+offset); + + for ( list = blockmaplump+offset ; *list != -1 ; list++) + { + ld = &lines[*list]; + + if (ld->validcount == validcount) + continue; // line has already been checked + + ld->validcount = validcount; + + if ( !func(ld) ) + return false; + } + return true; // everything was checked +} + + +// +// P_BlockThingsIterator +// +boolean +P_BlockThingsIterator +( int x, + int y, + boolean(*func)(mobj_t*) ) +{ + mobj_t* mobj; + + if ( x<0 + || y<0 + || x>=bmapwidth + || y>=bmapheight) + { + return true; + } + + LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); + + for (mobj = blocklinks[y*bmapwidth+x] ; + mobj ; + mobj = mobj->bnext) + { + if (!func( mobj ) ) + return false; + } + return true; +} + + + +// +// INTERCEPT ROUTINES +// +intercept_t intercepts[MAXINTERCEPTS]; +intercept_t* intercept_p; + +divline_t trace; +boolean earlyout; +int ptflags; + +static void InterceptsOverrun(int num_intercepts, intercept_t *intercept); + +// +// PIT_AddLineIntercepts. +// Looks for lines in the given block +// that intercept the given trace +// to add to the intercepts list. +// +// A line is crossed if its endpoints +// are on opposite sides of the trace. +// Returns true if earlyout and a solid line hit. +// +boolean +PIT_AddLineIntercepts (line_t* ld) +{ + int s1; + int s2; + fixed_t frac; + divline_t dl; + + // avoid precision problems with two routines + if ( trace.dx > FRACUNIT*16 + || trace.dy > FRACUNIT*16 + || trace.dx < -FRACUNIT*16 + || trace.dy < -FRACUNIT*16) + { + s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); + } + else + { + s1 = P_PointOnLineSide (trace.x, trace.y, ld); + s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); + } + + if (s1 == s2) + return true; // line isn't crossed + + // hit the line + P_MakeDivline (ld, &dl); + frac = P_InterceptVector (&trace, &dl); + + if (frac < 0) + return true; // behind source + + // try to early out the check + if (earlyout + && frac < FRACUNIT + && !ld->backsector) + { + return false; // stop checking + } + + + intercept_p->frac = frac; + intercept_p->isaline = true; + intercept_p->d.line = ld; + InterceptsOverrun(intercept_p - intercepts, intercept_p); + intercept_p++; + + return true; // continue +} + + + +// +// PIT_AddThingIntercepts +// +boolean PIT_AddThingIntercepts (mobj_t* thing) +{ + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + int s1; + int s2; + + boolean tracepositive; + + divline_t dl; + + fixed_t frac; + + tracepositive = (trace.dx ^ trace.dy)>0; + + // check a corner to corner crossection for hit + if (tracepositive) + { + x1 = thing->x - thing->radius; + y1 = thing->y + thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y - thing->radius; + } + else + { + x1 = thing->x - thing->radius; + y1 = thing->y - thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y + thing->radius; + } + + s1 = P_PointOnDivlineSide (x1, y1, &trace); + s2 = P_PointOnDivlineSide (x2, y2, &trace); + + if (s1 == s2) + return true; // line isn't crossed + + dl.x = x1; + dl.y = y1; + dl.dx = x2-x1; + dl.dy = y2-y1; + + frac = P_InterceptVector (&trace, &dl); + + if (frac < 0) + return true; // behind source + + intercept_p->frac = frac; + intercept_p->isaline = false; + intercept_p->d.thing = thing; + InterceptsOverrun(intercept_p - intercepts, intercept_p); + intercept_p++; + + return true; // keep going +} + + +// +// P_TraverseIntercepts +// Returns true if the traverser function returns true +// for all lines. +// +boolean +P_TraverseIntercepts +( traverser_t func, + fixed_t maxfrac ) +{ + int count; + fixed_t dist; + intercept_t* scan; + intercept_t* in; + + count = intercept_p - intercepts; + + in = 0; // shut up compiler warning + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts ; scanfrac < dist) + { + dist = scan->frac; + in = scan; + } + } + + if (dist > maxfrac) + return true; // checked everything in range + +#if 0 // UNUSED + { + // don't check these yet, there may be others inserted + in = scan = intercepts; + for ( scan = intercepts ; scanfrac > maxfrac) + *in++ = *scan; + intercept_p = in; + return false; + } +#endif + + if ( !func (in) ) + return false; // don't bother going farther + + in->frac = INT_MAX; + } + + return true; // everything was traversed +} + + +// Intercepts Overrun emulation, from PrBoom-plus. +// Thanks to Andrey Budko (entryway) for researching this and his +// implementation of Intercepts Overrun emulation in PrBoom-plus +// which this is based on. + +typedef struct +{ + int len; + void *addr; + boolean int16_array; +} intercepts_overrun_t; + +// Intercepts memory table. This is where various variables are located +// in memory in Vanilla Doom. When the intercepts table overflows, we +// need to write to them. +// +// Almost all of the values to overwrite are 32-bit integers, except for +// playerstarts, which is effectively an array of 16-bit integers and +// must be treated differently. + +static intercepts_overrun_t intercepts_overrun[] = +{ + {4, NULL, false}, + {4, NULL, /* &earlyout, */ false}, + {4, NULL, /* &intercept_p, */ false}, + {4, &lowfloor, false}, + {4, &openbottom, false}, + {4, &opentop, false}, + {4, &openrange, false}, + {4, NULL, false}, + {120, NULL, /* &activeplats, */ false}, + {8, NULL, false}, + {4, &bulletslope, false}, + {4, NULL, /* &swingx, */ false}, + {4, NULL, /* &swingy, */ false}, + {4, NULL, false}, + {40, &playerstarts, true}, + {4, NULL, /* &blocklinks, */ false}, + {4, &bmapwidth, false}, + {4, NULL, /* &blockmap, */ false}, + {4, &bmaporgx, false}, + {4, &bmaporgy, false}, + {4, NULL, /* &blockmaplump, */ false}, + {4, &bmapheight, false}, + {0, NULL, false}, +}; + +// Overwrite a specific memory location with a value. + +static void InterceptsMemoryOverrun(int location, int value) +{ + int i, offset; + int index; + void *addr; + + i = 0; + offset = 0; + + // Search down the array until we find the right entry + + while (intercepts_overrun[i].len != 0) + { + if (offset + intercepts_overrun[i].len > location) + { + addr = intercepts_overrun[i].addr; + + // Write the value to the memory location. + // 16-bit and 32-bit values are written differently. + + if (addr != NULL) + { + if (intercepts_overrun[i].int16_array) + { + index = (location - offset) / 2; + ((short *) addr)[index] = value & 0xffff; + ((short *) addr)[index + 1] = (value >> 16) & 0xffff; + } + else + { + index = (location - offset) / 4; + ((int *) addr)[index] = value; + } + } + + break; + } + + offset += intercepts_overrun[i].len; + ++i; + } +} + +// Emulate overruns of the intercepts[] array. + +static void InterceptsOverrun(int num_intercepts, intercept_t *intercept) +{ + int location; + + if (num_intercepts <= MAXINTERCEPTS_ORIGINAL) + { + // No overrun + + return; + } + + location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12; + + // Overwrite memory that is overwritten in Vanilla Doom, using + // the values from the intercept structure. + // + // Note: the ->d.{thing,line} member should really have its + // address translated into the correct address value for + // Vanilla Doom. + + InterceptsMemoryOverrun(location, intercept->frac); + InterceptsMemoryOverrun(location + 4, intercept->isaline); + InterceptsMemoryOverrun(location + 8, (intptr_t) intercept->d.thing); +} + + +// +// P_PathTraverse +// Traces a line from x1,y1 to x2,y2, +// calling the traverser function for each. +// Returns true if the traverser function returns true +// for all lines. +// +boolean +P_PathTraverse +( fixed_t x1, + fixed_t y1, + fixed_t x2, + fixed_t y2, + int flags, + boolean (*trav) (intercept_t *)) +{ + fixed_t xt1; + fixed_t yt1; + fixed_t xt2; + fixed_t yt2; + + fixed_t xstep; + fixed_t ystep; + + fixed_t partial; + + fixed_t xintercept; + fixed_t yintercept; + + int mapx; + int mapy; + + int mapxstep; + int mapystep; + + int count; + + earlyout = (flags & PT_EARLYOUT) != 0; + + validcount++; + intercept_p = intercepts; + + if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) + x1 += FRACUNIT; // don't side exactly on a line + + if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) + y1 += FRACUNIT; // don't side exactly on a line + + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1>>MAPBLOCKSHIFT; + yt1 = y1>>MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2>>MAPBLOCKSHIFT; + yt2 = y2>>MAPBLOCKSHIFT; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); + ystep = FixedDiv (y2-y1,abs(x2-x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); + ystep = FixedDiv (y2-y1,abs(x2-x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256*FRACUNIT; + } + + yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); + + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); + xstep = FixedDiv (x2-x1,abs(y2-y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); + xstep = FixedDiv (x2-x1,abs(y2-y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256*FRACUNIT; + } + xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); + + // Step through map blocks. + // Count is present to prevent a round off error + // from skipping the break. + mapx = xt1; + mapy = yt1; + + for (count = 0 ; count < 64 ; count++) + { + if (flags & PT_ADDLINES) + { + if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) + return false; // early out + } + + if (flags & PT_ADDTHINGS) + { + if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) + return false; // early out + } + + if (mapx == xt2 + && mapy == yt2) + { + break; + } + + if ( (yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ( (xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + + } + // go through the sorted list + return P_TraverseIntercepts ( trav, FRACUNIT ); +} + + + diff --git a/games/NXDoom/src/doom/p_mobj.c b/games/NXDoom/src/doom/p_mobj.c new file mode 100644 index 00000000000..481c52822d1 --- /dev/null +++ b/games/NXDoom/src/doom/p_mobj.c @@ -0,0 +1,1072 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Moving object handling. Spawn functions. +// + +#include + +#include "i_system.h" +#include "z_zone.h" +#include "m_random.h" + +#include "doomdef.h" +#include "p_local.h" +#include "sounds.h" + +#include "st_stuff.h" +#include "hu_stuff.h" + +#include "s_sound.h" + +#include "doomstat.h" + + +void G_PlayerReborn (int player); +void P_SpawnMapThing (mapthing_t* mthing); + + +// +// P_SetMobjState +// Returns true if the mobj is still present. +// +int test; + +// Use a heuristic approach to detect infinite state cycles: Count the number +// of times the loop in P_SetMobjState() executes and exit with an error once +// an arbitrary very large limit is reached. + +#define MOBJ_CYCLE_LIMIT 1000000 + +boolean +P_SetMobjState +( mobj_t* mobj, + statenum_t state ) +{ + state_t* st; + int cycle_counter = 0; + + do + { + if (state == S_NULL) + { + mobj->state = (state_t *) S_NULL; + P_RemoveMobj (mobj); + return false; + } + + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // Modified handling. + // Call action functions when the state is set + if (st->action.acp1) + st->action.acp1(mobj); + + state = st->nextstate; + + if (cycle_counter++ > MOBJ_CYCLE_LIMIT) + { + I_Error("P_SetMobjState: Infinite state cycle detected!"); + } + } while (!mobj->tics); + + return true; +} + + +// +// P_ExplodeMissile +// +void P_ExplodeMissile (mobj_t* mo) +{ + mo->momx = mo->momy = mo->momz = 0; + + P_SetMobjState (mo, mobjinfo[mo->type].deathstate); + + mo->tics -= P_Random()&3; + + if (mo->tics < 1) + mo->tics = 1; + + mo->flags &= ~MF_MISSILE; + + if (mo->info->deathsound) + S_StartSound (mo, mo->info->deathsound); +} + + +// +// P_XYMovement +// +#define STOPSPEED 0x1000 +#define FRICTION 0xe800 + +void P_XYMovement (mobj_t* mo) +{ + fixed_t ptryx; + fixed_t ptryy; + player_t* player; + fixed_t xmove; + fixed_t ymove; + + if (!mo->momx && !mo->momy) + { + if (mo->flags & MF_SKULLFLY) + { + // the skull slammed into something + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + + P_SetMobjState (mo, mo->info->spawnstate); + } + return; + } + + player = mo->player; + + if (mo->momx > MAXMOVE) + mo->momx = MAXMOVE; + else if (mo->momx < -MAXMOVE) + mo->momx = -MAXMOVE; + + if (mo->momy > MAXMOVE) + mo->momy = MAXMOVE; + else if (mo->momy < -MAXMOVE) + mo->momy = -MAXMOVE; + + xmove = mo->momx; + ymove = mo->momy; + + do + { + if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) + { + ptryx = mo->x + xmove/2; + ptryy = mo->y + ymove/2; + xmove >>= 1; + ymove >>= 1; + } + else + { + ptryx = mo->x + xmove; + ptryy = mo->y + ymove; + xmove = ymove = 0; + } + + if (!P_TryMove (mo, ptryx, ptryy)) + { + // blocked move + if (mo->player) + { // try to slide along it + P_SlideMove (mo); + } + else if (mo->flags & MF_MISSILE) + { + // explode a missile + if (ceilingline && + ceilingline->backsector && + ceilingline->backsector->ceilingpic == skyflatnum) + { + // Hack to prevent missiles exploding + // against the sky. + // Does not handle sky floors. + P_RemoveMobj (mo); + return; + } + P_ExplodeMissile (mo); + } + else + mo->momx = mo->momy = 0; + } + } while (xmove || ymove); + + // slow down + if (player && player->cheats & CF_NOMOMENTUM) + { + // debug option for no sliding at all + mo->momx = mo->momy = 0; + return; + } + + if (mo->flags & (MF_MISSILE | MF_SKULLFLY) ) + return; // no friction for missiles ever + + if (mo->z > mo->floorz) + return; // no friction when airborne + + if (mo->flags & MF_CORPSE) + { + // do not stop sliding + // if halfway off a step with some momentum + if (mo->momx > FRACUNIT/4 + || mo->momx < -FRACUNIT/4 + || mo->momy > FRACUNIT/4 + || mo->momy < -FRACUNIT/4) + { + if (mo->floorz != mo->subsector->sector->floorheight) + return; + } + } + + if (mo->momx > -STOPSPEED + && mo->momx < STOPSPEED + && mo->momy > -STOPSPEED + && mo->momy < STOPSPEED + && (!player + || (player->cmd.forwardmove== 0 + && player->cmd.sidemove == 0 ) ) ) + { + // if in a walking frame, stop moving + if ( player&&(unsigned)((player->mo->state - states)- S_PLAY_RUN1) < 4) + P_SetMobjState (player->mo, S_PLAY); + + mo->momx = 0; + mo->momy = 0; + } + else + { + mo->momx = FixedMul (mo->momx, FRICTION); + mo->momy = FixedMul (mo->momy, FRICTION); + } +} + +// +// P_ZMovement +// +void P_ZMovement (mobj_t* mo) +{ + fixed_t dist; + fixed_t delta; + + // check for smooth step up + if (mo->player && mo->z < mo->floorz) + { + mo->player->viewheight -= mo->floorz-mo->z; + + mo->player->deltaviewheight + = (VIEWHEIGHT - mo->player->viewheight)>>3; + } + + // adjust height + mo->z += mo->momz; + + if ( mo->flags & MF_FLOAT + && mo->target) + { + // float down towards target if too close + if ( !(mo->flags & MF_SKULLFLY) + && !(mo->flags & MF_INFLOAT) ) + { + dist = P_AproxDistance (mo->x - mo->target->x, + mo->y - mo->target->y); + + delta =(mo->target->z + (mo->height>>1)) - mo->z; + + if (delta<0 && dist < -(delta*3) ) + mo->z -= FLOATSPEED; + else if (delta>0 && dist < (delta*3) ) + mo->z += FLOATSPEED; + } + + } + + // clip movement + if (mo->z <= mo->floorz) + { + // hit the floor + + // Note (id): + // somebody left this after the setting momz to 0, + // kinda useless there. + // + // cph - This was the a bug in the linuxdoom-1.10 source which + // caused it not to sync Doom 2 v1.9 demos. Someone + // added the above comment and moved up the following code. So + // demos would desync in close lost soul fights. + // Note that this only applies to original Doom 1 or Doom2 demos - not + // Final Doom and Ultimate Doom. So we test demo_compatibility *and* + // gamemission. (Note we assume that Doom1 is always Ult Doom, which + // seems to hold for most published demos.) + // + // fraggle - cph got the logic here slightly wrong. There are three + // versions of Doom 1.9: + // + // * The version used in registered doom 1.9 + doom2 - no bounce + // * The version used in ultimate doom - has bounce + // * The version used in final doom - has bounce + // + // So we need to check that this is either retail or commercial + // (but not doom2) + + int correct_lost_soul_bounce = gameversion >= exe_ultimate; + + if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) + { + // the skull slammed into something + mo->momz = -mo->momz; + } + + if (mo->momz < 0) + { + if (mo->player + && mo->momz < -GRAVITY*8) + { + // Squat down. + // Decrease viewheight for a moment + // after hitting the ground (hard), + // and utter appropriate sound. + mo->player->deltaviewheight = mo->momz>>3; + S_StartSound (mo, sfx_oof); + } + mo->momz = 0; + } + mo->z = mo->floorz; + + + // cph 2001/05/26 - + // See lost soul bouncing comment above. We need this here for bug + // compatibility with original Doom2 v1.9 - if a soul is charging and + // hit by a raising floor this incorrectly reverses its Y momentum. + // + + if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) + mo->momz = -mo->momz; + + if ( (mo->flags & MF_MISSILE) + && !(mo->flags & MF_NOCLIP) ) + { + P_ExplodeMissile (mo); + return; + } + } + else if (! (mo->flags & MF_NOGRAVITY) ) + { + if (mo->momz == 0) + mo->momz = -GRAVITY*2; + else + mo->momz -= GRAVITY; + } + + if (mo->z + mo->height > mo->ceilingz) + { + // hit the ceiling + if (mo->momz > 0) + mo->momz = 0; + { + mo->z = mo->ceilingz - mo->height; + } + + if (mo->flags & MF_SKULLFLY) + { // the skull slammed into something + mo->momz = -mo->momz; + } + + if ( (mo->flags & MF_MISSILE) + && !(mo->flags & MF_NOCLIP) ) + { + P_ExplodeMissile (mo); + return; + } + } +} + + + +// +// P_NightmareRespawn +// +void +P_NightmareRespawn (mobj_t* mobj) +{ + fixed_t x; + fixed_t y; + fixed_t z; + subsector_t* ss; + mobj_t* mo; + mapthing_t* mthing; + + x = mobj->spawnpoint.x << FRACBITS; + y = mobj->spawnpoint.y << FRACBITS; + + // somthing is occupying it's position? + if (!P_CheckPosition (mobj, x, y) ) + return; // no respwan + + // spawn a teleport fog at old spot + // because of removal of the body? + mo = P_SpawnMobj (mobj->x, + mobj->y, + mobj->subsector->sector->floorheight , MT_TFOG); + // initiate teleport sound + S_StartSound (mo, sfx_telept); + + // spawn a teleport fog at the new spot + ss = R_PointInSubsector (x,y); + + mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG); + + S_StartSound (mo, sfx_telept); + + // spawn the new monster + mthing = &mobj->spawnpoint; + + // spawn it + if (mobj->info->flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + // inherit attributes from deceased one + mo = P_SpawnMobj (x,y,z, mobj->type); + mo->spawnpoint = mobj->spawnpoint; + mo->angle = ANG45 * (mthing->angle/45); + + if (mthing->options & MTF_AMBUSH) + mo->flags |= MF_AMBUSH; + + mo->reactiontime = 18; + + // remove the old monster, + P_RemoveMobj (mobj); +} + + +// +// P_MobjThinker +// +void P_MobjThinker (mobj_t* mobj) +{ + // momentum movement + if (mobj->momx + || mobj->momy + || (mobj->flags&MF_SKULLFLY) ) + { + P_XYMovement (mobj); + + // FIXME: decent NOP/NULL/Nil function pointer please. + if (mobj->thinker.function.acv == (actionf_v) (-1)) + return; // mobj was removed + } + if ( (mobj->z != mobj->floorz) + || mobj->momz ) + { + P_ZMovement (mobj); + + // FIXME: decent NOP/NULL/Nil function pointer please. + if (mobj->thinker.function.acv == (actionf_v) (-1)) + return; // mobj was removed + } + + + // cycle through states, + // calling action functions at transitions + if (mobj->tics != -1) + { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState (mobj, mobj->state->nextstate) ) + return; // freed itself + } + else + { + // check for nightmare respawn + if (! (mobj->flags & MF_COUNTKILL) ) + return; + + if (!respawnmonsters) + return; + + mobj->movecount++; + + if (mobj->movecount < 12*TICRATE) + return; + + if ( leveltime&31 ) + return; + + if (P_Random () > 4) + return; + + P_NightmareRespawn (mobj); + } + +} + + +// +// P_SpawnMobj +// +mobj_t* +P_SpawnMobj +( fixed_t x, + fixed_t y, + fixed_t z, + mobjtype_t type ) +{ + mobj_t* mobj; + state_t* st; + mobjinfo_t* info; + + mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); + memset (mobj, 0, sizeof (*mobj)); + info = &mobjinfo[type]; + + mobj->type = type; + mobj->info = info; + mobj->x = x; + mobj->y = y; + mobj->radius = info->radius; + mobj->height = info->height; + mobj->flags = info->flags; + mobj->health = info->spawnhealth; + + if (gameskill != sk_nightmare) + mobj->reactiontime = info->reactiontime; + + mobj->lastlook = P_Random () % MAXPLAYERS; + // do not set the state with P_SetMobjState, + // because action routines can not be called yet + st = &states[info->spawnstate]; + + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // set subsector and/or block links + P_SetThingPosition (mobj); + + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + + if (z == ONFLOORZ) + mobj->z = mobj->floorz; + else if (z == ONCEILINGZ) + mobj->z = mobj->ceilingz - mobj->info->height; + else + mobj->z = z; + + mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; + + P_AddThinker (&mobj->thinker); + + return mobj; +} + + +// +// P_RemoveMobj +// +mapthing_t itemrespawnque[ITEMQUESIZE]; +int itemrespawntime[ITEMQUESIZE]; +int iquehead; +int iquetail; + + +void P_RemoveMobj (mobj_t* mobj) +{ + if ((mobj->flags & MF_SPECIAL) + && !(mobj->flags & MF_DROPPED) + && (mobj->type != MT_INV) + && (mobj->type != MT_INS)) + { + itemrespawnque[iquehead] = mobj->spawnpoint; + itemrespawntime[iquehead] = leveltime; + iquehead = (iquehead+1)&(ITEMQUESIZE-1); + + // lose one off the end? + if (iquehead == iquetail) + iquetail = (iquetail+1)&(ITEMQUESIZE-1); + } + + // unlink from sector and block lists + P_UnsetThingPosition (mobj); + + // stop any playing sound + S_StopSound (mobj); + + // free block + P_RemoveThinker ((thinker_t*)mobj); +} + + + + +// +// P_RespawnSpecials +// +void P_RespawnSpecials (void) +{ + fixed_t x; + fixed_t y; + fixed_t z; + + subsector_t* ss; + mobj_t* mo; + mapthing_t* mthing; + + int i; + + // only respawn items in deathmatch + if (deathmatch != 2) + return; // + + // nothing left to respawn? + if (iquehead == iquetail) + return; + + // wait at least 30 seconds + if (leveltime - itemrespawntime[iquetail] < 30*TICRATE) + return; + + mthing = &itemrespawnque[iquetail]; + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + // spawn a teleport fog at the new spot + ss = R_PointInSubsector (x,y); + mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); + S_StartSound (mo, sfx_itmbk); + + // find which type to spawn + for (i=0 ; i< NUMMOBJTYPES ; i++) + { + if (mthing->type == mobjinfo[i].doomednum) + break; + } + + if (i >= NUMMOBJTYPES) + { + I_Error("P_RespawnSpecials: Failed to find mobj type with doomednum " + "%d when respawning thing. This would cause a buffer overrun " + "in vanilla Doom", mthing->type); + } + + // spawn it + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + mo = P_SpawnMobj (x,y,z, i); + mo->spawnpoint = *mthing; + mo->angle = ANG45 * (mthing->angle/45); + + // pull it from the que + iquetail = (iquetail+1)&(ITEMQUESIZE-1); +} + + + + +// +// P_SpawnPlayer +// Called when a player is spawned on the level. +// Most of the player structure stays unchanged +// between levels. +// +void P_SpawnPlayer (mapthing_t* mthing) +{ + player_t* p; + fixed_t x; + fixed_t y; + fixed_t z; + + mobj_t* mobj; + + int i; + + if (mthing->type == 0) + { + return; + } + + // not playing? + if (!playeringame[mthing->type-1]) + return; + + p = &players[mthing->type-1]; + + if (p->playerstate == PST_REBORN) + G_PlayerReborn (mthing->type-1); + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = ONFLOORZ; + mobj = P_SpawnMobj (x,y,z, MT_PLAYER); + + // set color translations for player sprites + if (mthing->type > 1) + mobj->flags |= (mthing->type-1)<angle = ANG45 * (mthing->angle/45); + mobj->player = p; + mobj->health = p->health; + + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + p->message = NULL; + p->damagecount = 0; + p->bonuscount = 0; + p->extralight = 0; + p->fixedcolormap = 0; + p->viewheight = VIEWHEIGHT; + + // setup gun psprite + P_SetupPsprites (p); + + // give all cards in death match mode + if (deathmatch) + for (i=0 ; icards[i] = true; + + if (mthing->type-1 == consoleplayer) + { + // wake up the status bar + ST_Start (); + // wake up the heads up text + HU_Start (); + } +} + + +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +void P_SpawnMapThing (mapthing_t* mthing) +{ + int i; + int bit; + mobj_t* mobj; + fixed_t x; + fixed_t y; + fixed_t z; + + // count deathmatch start positions + if (mthing->type == 11) + { + if (deathmatch_p < &deathmatchstarts[10]) + { + memcpy (deathmatch_p, mthing, sizeof(*mthing)); + deathmatch_p++; + } + return; + } + + if (mthing->type <= 0) + { + // Thing type 0 is actually "player -1 start". + // For some reason, Vanilla Doom accepts/ignores this. + + return; + } + + // check for players specially + if (mthing->type <= 4) + { + // save spots for respawning in network games + playerstarts[mthing->type-1] = *mthing; + playerstartsingame[mthing->type-1] = true; + if (!deathmatch) + P_SpawnPlayer (mthing); + + return; + } + + // check for appropriate skill level + if (!netgame && (mthing->options & 16) ) + return; + + if (gameskill == sk_baby) + bit = 1; + else if (gameskill == sk_nightmare) + bit = 4; + else + // avoid undefined behavior (left shift by negative value and rhs too big) + // by accurately emulating what doom.exe did: reduce mod 32. + // For more details check: + // https://github.com/chocolate-doom/chocolate-doom/issues/1677 + bit = (int) (1U << ((gameskill - 1) & 0x1F)); + + if (!(mthing->options & bit) ) + return; + + // find which type to spawn + for (i=0 ; i< NUMMOBJTYPES ; i++) + if (mthing->type == mobjinfo[i].doomednum) + break; + + if (i==NUMMOBJTYPES) + I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)", + mthing->type, + mthing->x, mthing->y); + + // don't spawn keycards and players in deathmatch + if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) + return; + + // don't spawn any monsters if -nomonsters + if (nomonsters + && ( i == MT_SKULL + || (mobjinfo[i].flags & MF_COUNTKILL)) ) + { + return; + } + + // spawn it + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + mobj = P_SpawnMobj (x,y,z, i); + mobj->spawnpoint = *mthing; + + if (mobj->tics > 0) + mobj->tics = 1 + (P_Random () % mobj->tics); + if (mobj->flags & MF_COUNTKILL) + totalkills++; + if (mobj->flags & MF_COUNTITEM) + totalitems++; + + mobj->angle = ANG45 * (mthing->angle/45); + if (mthing->options & MTF_AMBUSH) + mobj->flags |= MF_AMBUSH; +} + + + +// +// GAME SPAWN FUNCTIONS +// + + +// +// P_SpawnPuff +// + +void +P_SpawnPuff +( fixed_t x, + fixed_t y, + fixed_t z ) +{ + mobj_t* th; + + z += (P_SubRandom() << 10); + + th = P_SpawnMobj (x,y,z, MT_PUFF); + th->momz = FRACUNIT; + th->tics -= P_Random()&3; + + if (th->tics < 1) + th->tics = 1; + + // don't make punches spark on the wall + if (attackrange == MELEERANGE) + P_SetMobjState (th, S_PUFF3); +} + + + +// +// P_SpawnBlood +// +void +P_SpawnBlood +( fixed_t x, + fixed_t y, + fixed_t z, + int damage ) +{ + mobj_t* th; + + z += (P_SubRandom() << 10); + th = P_SpawnMobj (x,y,z, MT_BLOOD); + th->momz = FRACUNIT*2; + th->tics -= P_Random()&3; + + if (th->tics < 1) + th->tics = 1; + + if (damage <= 12 && damage >= 9) + P_SetMobjState (th,S_BLOOD2); + else if (damage < 9) + P_SetMobjState (th,S_BLOOD3); +} + + + +// +// P_CheckMissileSpawn +// Moves the missile forward a bit +// and possibly explodes it right there. +// +void P_CheckMissileSpawn (mobj_t* th) +{ + th->tics -= P_Random()&3; + if (th->tics < 1) + th->tics = 1; + + // move a little forward so an angle can + // be computed if it immediately explodes + th->x += (th->momx>>1); + th->y += (th->momy>>1); + th->z += (th->momz>>1); + + if (!P_TryMove (th, th->x, th->y)) + P_ExplodeMissile (th); +} + +// Certain functions assume that a mobj_t pointer is non-NULL, +// causing a crash in some situations where it is NULL. Vanilla +// Doom did not crash because of the lack of proper memory +// protection. This function substitutes NULL pointers for +// pointers to a dummy mobj, to avoid a crash. + +mobj_t *P_SubstNullMobj(mobj_t *mobj) +{ + if (mobj == NULL) + { + static mobj_t dummy_mobj; + + dummy_mobj.x = 0; + dummy_mobj.y = 0; + dummy_mobj.z = 0; + dummy_mobj.flags = 0; + + mobj = &dummy_mobj; + } + + return mobj; +} + +// +// P_SpawnMissile +// +mobj_t* +P_SpawnMissile +( mobj_t* source, + mobj_t* dest, + mobjtype_t type ) +{ + mobj_t* th; + angle_t an; + int dist; + + th = P_SpawnMobj (source->x, + source->y, + source->z + 4*8*FRACUNIT, type); + + if (th->info->seesound) + S_StartSound (th, th->info->seesound); + + th->target = source; // where it came from + an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); + + // fuzzy player + if (dest->flags & MF_SHADOW) + an += P_SubRandom() << 20; + + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul (th->info->speed, finecosine[an]); + th->momy = FixedMul (th->info->speed, finesine[an]); + + dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + + if (dist < 1) + dist = 1; + + th->momz = (dest->z - source->z) / dist; + P_CheckMissileSpawn (th); + + return th; +} + + +// +// P_SpawnPlayerMissile +// Tries to aim at a nearby monster +// +void +P_SpawnPlayerMissile +( mobj_t* source, + mobjtype_t type ) +{ + mobj_t* th; + angle_t an; + + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t slope; + + // see which target is to be aimed at + an = source->angle; + slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); + + if (!linetarget) + { + an += 1<<26; + slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); + + if (!linetarget) + { + an -= 2<<26; + slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); + } + + if (!linetarget) + { + an = source->angle; + slope = 0; + } + } + + x = source->x; + y = source->y; + z = source->z + 4*8*FRACUNIT; + + th = P_SpawnMobj (x,y,z, type); + + if (th->info->seesound) + S_StartSound (th, th->info->seesound); + + th->target = source; + th->angle = an; + th->momx = FixedMul( th->info->speed, + finecosine[an>>ANGLETOFINESHIFT]); + th->momy = FixedMul( th->info->speed, + finesine[an>>ANGLETOFINESHIFT]); + th->momz = FixedMul( th->info->speed, slope); + + P_CheckMissileSpawn (th); +} + diff --git a/games/NXDoom/src/doom/p_mobj.h b/games/NXDoom/src/doom/p_mobj.h new file mode 100644 index 00000000000..90ed764b91c --- /dev/null +++ b/games/NXDoom/src/doom/p_mobj.h @@ -0,0 +1,284 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Map Objects, MObj, definition and handling. +// + + +#ifndef __P_MOBJ__ +#define __P_MOBJ__ + +// Basics. +#include "tables.h" +#include "m_fixed.h" + +// We need the thinker_t stuff. +#include "d_think.h" + +// We need the WAD data structure for Map things, +// from the THINGS lump. +#include "doomdata.h" + +// States are tied to finite states are +// tied to animation frames. +// Needs precompiled tables/data structures. +#include "info.h" + + + + + + +// +// NOTES: mobj_t +// +// mobj_ts are used to tell the refresh where to draw an image, +// tell the world simulation when objects are contacted, +// and tell the sound driver how to position a sound. +// +// The refresh uses the next and prev links to follow +// lists of things in sectors as they are being drawn. +// The sprite, frame, and angle elements determine which patch_t +// is used to draw the sprite if it is visible. +// The sprite and frame values are allmost allways set +// from state_t structures. +// The statescr.exe utility generates the states.h and states.c +// files that contain the sprite/frame numbers from the +// statescr.txt source file. +// The xyz origin point represents a point at the bottom middle +// of the sprite (between the feet of a biped). +// This is the default origin position for patch_ts grabbed +// with lumpy.exe. +// A walking creature will have its z equal to the floor +// it is standing on. +// +// The sound code uses the x,y, and subsector fields +// to do stereo positioning of any sound effited by the mobj_t. +// +// The play simulation uses the blocklinks, x,y,z, radius, height +// to determine when mobj_ts are touching each other, +// touching lines in the map, or hit by trace lines (gunshots, +// lines of sight, etc). +// The mobj_t->flags element has various bit flags +// used by the simulation. +// +// Every mobj_t is linked into a single sector +// based on its origin coordinates. +// The subsector_t is found with R_PointInSubsector(x,y), +// and the sector_t can be found with subsector->sector. +// The sector links are only used by the rendering code, +// the play simulation does not care about them at all. +// +// Any mobj_t that needs to be acted upon by something else +// in the play world (block movement, be shot, etc) will also +// need to be linked into the blockmap. +// If the thing has the MF_NOBLOCK flag set, it will not use +// the block links. It can still interact with other things, +// but only as the instigator (missiles will run into other +// things, but nothing can run into a missile). +// Each block in the grid is 128*128 units, and knows about +// every line_t that it contains a piece of, and every +// interactable mobj_t that has its origin contained. +// +// A valid mobj_t is a mobj_t that has the proper subsector_t +// filled in for its xy coordinates and is linked into the +// sector from which the subsector was made, or has the +// MF_NOSECTOR flag set (the subsector_t needs to be valid +// even if MF_NOSECTOR is set), and is linked into a blockmap +// block or has the MF_NOBLOCKMAP flag set. +// Links should only be modified by the P_[Un]SetThingPosition() +// functions. +// Do not change the MF_NO? flags while a thing is valid. +// +// Any questions? +// + +// +// Misc. mobj flags +// +typedef enum +{ + // Call P_SpecialThing when touched. + MF_SPECIAL = 1, + // Blocks. + MF_SOLID = 2, + // Can be hit. + MF_SHOOTABLE = 4, + // Don't use the sector links (invisible but touchable). + MF_NOSECTOR = 8, + // Don't use the blocklinks (inert but displayable) + MF_NOBLOCKMAP = 16, + + // Not to be activated by sound, deaf monster. + MF_AMBUSH = 32, + // Will try to attack right back. + MF_JUSTHIT = 64, + // Will take at least one step before attacking. + MF_JUSTATTACKED = 128, + // On level spawning (initial position), + // hang from ceiling instead of stand on floor. + MF_SPAWNCEILING = 256, + // Don't apply gravity (every tic), + // that is, object will float, keeping current height + // or changing it actively. + MF_NOGRAVITY = 512, + + // Movement flags. + // This allows jumps from high places. + MF_DROPOFF = 0x400, + // For players, will pick up items. + MF_PICKUP = 0x800, + // Player cheat. ??? + MF_NOCLIP = 0x1000, + // Player: keep info about sliding along walls. + MF_SLIDE = 0x2000, + // Allow moves to any height, no gravity. + // For active floaters, e.g. cacodemons, pain elementals. + MF_FLOAT = 0x4000, + // Don't cross lines + // ??? or look at heights on teleport. + MF_TELEPORT = 0x8000, + // Don't hit same species, explode on block. + // Player missiles as well as fireballs of various kinds. + MF_MISSILE = 0x10000, + // Dropped by a demon, not level spawned. + // E.g. ammo clips dropped by dying former humans. + MF_DROPPED = 0x20000, + // Use fuzzy draw (shadow demons or spectres), + // temporary player invisibility powerup. + MF_SHADOW = 0x40000, + // Flag: don't bleed when shot (use puff), + // barrels and shootable furniture shall not bleed. + MF_NOBLOOD = 0x80000, + // Don't stop moving halfway off a step, + // that is, have dead bodies slide down all the way. + MF_CORPSE = 0x100000, + // Floating to a height for a move, ??? + // don't auto float to target's height. + MF_INFLOAT = 0x200000, + + // On kill, count this enemy object + // towards intermission kill total. + // Happy gathering. + MF_COUNTKILL = 0x400000, + + // On picking up, count this item object + // towards intermission item total. + MF_COUNTITEM = 0x800000, + + // Special handling: skull in flight. + // Neither a cacodemon nor a missile. + MF_SKULLFLY = 0x1000000, + + // Don't spawn this object + // in death match mode (e.g. key cards). + MF_NOTDMATCH = 0x2000000, + + // Player sprites in multiplayer modes are modified + // using an internal color lookup table for re-indexing. + // If 0x4 0x8 or 0xc, + // use a translation table for player colormaps + MF_TRANSLATION = 0xc000000, + // Hmm ???. + MF_TRANSSHIFT = 26 + +} mobjflag_t; + + +// Map Object definition. +typedef struct mobj_s +{ + // List: thinker links. + thinker_t thinker; + + // Info for drawing: position. + fixed_t x; + fixed_t y; + fixed_t z; + + // More list: links in sector (if needed) + struct mobj_s* snext; + struct mobj_s* sprev; + + //More drawing info: to determine current sprite. + angle_t angle; // orientation + spritenum_t sprite; // used to find patch_t and flip value + int frame; // might be ORed with FF_FULLBRIGHT + + // Interaction info, by BLOCKMAP. + // Links in blocks (if needed). + struct mobj_s* bnext; + struct mobj_s* bprev; + + struct subsector_s* subsector; + + // The closest interval over all contacted Sectors. + fixed_t floorz; + fixed_t ceilingz; + + // For movement checking. + fixed_t radius; + fixed_t height; + + // Momentums, used to update position. + fixed_t momx; + fixed_t momy; + fixed_t momz; + + // If == validcount, already checked. + int validcount; + + mobjtype_t type; + mobjinfo_t* info; // &mobjinfo[mobj->type] + + int tics; // state tic counter + state_t* state; + int flags; + int health; + + // Movement direction, movement generation (zig-zagging). + int movedir; // 0-7 + int movecount; // when 0, select a new dir + + // Thing being chased/attacked (or NULL), + // also the originator for missiles. + struct mobj_s* target; + + // Reaction time: if non 0, don't attack yet. + // Used by player to freeze a bit after teleporting. + int reactiontime; + + // If >0, the target will be chased + // no matter what (even if shot) + int threshold; + + // Additional info record for player avatars only. + // Only valid if type == MT_PLAYER + struct player_s* player; + + // Player number last looked for. + int lastlook; + + // For nightmare respawn. + mapthing_t spawnpoint; + + // Thing being chased/attacked for tracers. + struct mobj_s* tracer; + +} mobj_t; + + + +#endif diff --git a/games/NXDoom/src/doom/p_plats.c b/games/NXDoom/src/doom/p_plats.c new file mode 100644 index 00000000000..9e773d55cbd --- /dev/null +++ b/games/NXDoom/src/doom/p_plats.c @@ -0,0 +1,304 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Plats (i.e. elevator platforms) code, raising/lowering. +// + +#include + +#include "i_system.h" +#include "z_zone.h" +#include "m_random.h" + +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "sounds.h" + + +plat_t* activeplats[MAXPLATS]; + + + +// +// Move a plat up and down +// +void T_PlatRaise(plat_t* plat) +{ + result_e res; + + switch(plat->status) + { + case up: + res = T_MovePlane(plat->sector, + plat->speed, + plat->high, + plat->crush,0,1); + + if (plat->type == raiseAndChange + || plat->type == raiseToNearestAndChange) + { + if (!(leveltime&7)) + S_StartSound(&plat->sector->soundorg, sfx_stnmov); + } + + + if (res == crushed && (!plat->crush)) + { + plat->count = plat->wait; + plat->status = down; + S_StartSound(&plat->sector->soundorg, sfx_pstart); + } + else + { + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound(&plat->sector->soundorg, sfx_pstop); + + switch(plat->type) + { + case blazeDWUS: + case downWaitUpStay: + P_RemoveActivePlat(plat); + break; + + case raiseAndChange: + case raiseToNearestAndChange: + P_RemoveActivePlat(plat); + break; + + default: + break; + } + } + } + break; + + case down: + res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1); + + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound(&plat->sector->soundorg,sfx_pstop); + } + break; + + case waiting: + if (!--plat->count) + { + if (plat->sector->floorheight == plat->low) + plat->status = up; + else + plat->status = down; + S_StartSound(&plat->sector->soundorg,sfx_pstart); + } + case in_stasis: + break; + } +} + + +// +// Do Platforms +// "amount" is only used for SOME platforms. +// +int +EV_DoPlat +( line_t* line, + plattype_e type, + int amount ) +{ + plat_t* plat; + int secnum; + int rtn; + sector_t* sec; + + secnum = -1; + rtn = 0; + + + // Activate all plats that are in_stasis + switch(type) + { + case perpetualRaise: + P_ActivateInStasis(line->tag); + break; + + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + if (sec->specialdata) + continue; + + // Find lowest & highest floors around sector + rtn = 1; + plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); + P_AddThinker(&plat->thinker); + + plat->type = type; + plat->sector = sec; + plat->sector->specialdata = plat; + plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise; + plat->crush = false; + plat->tag = line->tag; + + switch(type) + { + case raiseToNearestAndChange: + plat->speed = PLATSPEED/2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = P_FindNextHighestFloor(sec,sec->floorheight); + plat->wait = 0; + plat->status = up; + // NO MORE DAMAGE, IF APPLICABLE + sec->special = 0; + + S_StartSound(&sec->soundorg,sfx_stnmov); + break; + + case raiseAndChange: + plat->speed = PLATSPEED/2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = sec->floorheight + amount*FRACUNIT; + plat->wait = 0; + plat->status = up; + + S_StartSound(&sec->soundorg,sfx_stnmov); + break; + + case downWaitUpStay: + plat->speed = PLATSPEED * 4; + plat->low = P_FindLowestFloorSurrounding(sec); + + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = sec->floorheight; + plat->wait = TICRATE*PLATWAIT; + plat->status = down; + S_StartSound(&sec->soundorg,sfx_pstart); + break; + + case blazeDWUS: + plat->speed = PLATSPEED * 8; + plat->low = P_FindLowestFloorSurrounding(sec); + + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = sec->floorheight; + plat->wait = TICRATE*PLATWAIT; + plat->status = down; + S_StartSound(&sec->soundorg,sfx_pstart); + break; + + case perpetualRaise: + plat->speed = PLATSPEED; + plat->low = P_FindLowestFloorSurrounding(sec); + + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = P_FindHighestFloorSurrounding(sec); + + if (plat->high < sec->floorheight) + plat->high = sec->floorheight; + + plat->wait = TICRATE*PLATWAIT; + plat->status = P_Random()&1; + + S_StartSound(&sec->soundorg,sfx_pstart); + break; + } + P_AddActivePlat(plat); + } + return rtn; +} + + + +void P_ActivateInStasis(int tag) +{ + int i; + + for (i = 0;i < MAXPLATS;i++) + if (activeplats[i] + && (activeplats[i])->tag == tag + && (activeplats[i])->status == in_stasis) + { + (activeplats[i])->status = (activeplats[i])->oldstatus; + (activeplats[i])->thinker.function.acp1 + = (actionf_p1) T_PlatRaise; + } +} + +void EV_StopPlat(line_t* line) +{ + int j; + + for (j = 0;j < MAXPLATS;j++) + if (activeplats[j] + && ((activeplats[j])->status != in_stasis) + && ((activeplats[j])->tag == line->tag)) + { + (activeplats[j])->oldstatus = (activeplats[j])->status; + (activeplats[j])->status = in_stasis; + (activeplats[j])->thinker.function.acv = (actionf_v)NULL; + } +} + +void P_AddActivePlat(plat_t* plat) +{ + int i; + + for (i = 0;i < MAXPLATS;i++) + if (activeplats[i] == NULL) + { + activeplats[i] = plat; + return; + } + I_Error ("P_AddActivePlat: no more plats!"); +} + +void P_RemoveActivePlat(plat_t* plat) +{ + int i; + for (i = 0;i < MAXPLATS;i++) + if (plat == activeplats[i]) + { + (activeplats[i])->sector->specialdata = NULL; + P_RemoveThinker(&(activeplats[i])->thinker); + activeplats[i] = NULL; + + return; + } + I_Error ("P_RemoveActivePlat: can't find plat!"); +} diff --git a/games/NXDoom/src/doom/p_pspr.c b/games/NXDoom/src/doom/p_pspr.c new file mode 100644 index 00000000000..c8c1776ca04 --- /dev/null +++ b/games/NXDoom/src/doom/p_pspr.c @@ -0,0 +1,887 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Weapon sprite animation, weapon objects. +// Action functions for weapons. +// + + +#include "doomdef.h" +#include "d_event.h" + +#include "deh_misc.h" + +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +// State. +#include "doomstat.h" + +// Data. +#include "sounds.h" + +#include "p_pspr.h" + +#define LOWERSPEED FRACUNIT*6 +#define RAISESPEED FRACUNIT*6 + +#define WEAPONBOTTOM 128*FRACUNIT +#define WEAPONTOP 32*FRACUNIT + + + +// +// P_SetPsprite +// +void +P_SetPsprite +( player_t* player, + int position, + statenum_t stnum ) +{ + pspdef_t* psp; + state_t* state; + + psp = &player->psprites[position]; + + do + { + if (!stnum) + { + // object removed itself + psp->state = NULL; + break; + } + + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; // could be 0 + + if (state->misc1) + { + // coordinate set + psp->sx = state->misc1 << FRACBITS; + psp->sy = state->misc2 << FRACBITS; + } + + // Call action routine. + // Modified handling. + if (state->action.acp2) + { + state->action.acp2(player, psp); + if (!psp->state) + break; + } + + stnum = psp->state->nextstate; + + } while (!psp->tics); + // an initial state of 0 could cycle through +} + + + +// +// P_CalcSwing +// +fixed_t swingx; +fixed_t swingy; + +void P_CalcSwing (player_t* player) +{ + fixed_t swing; + int angle; + + // OPTIMIZE: tablify this. + // A LUT would allow for different modes, + // and add flexibility. + + swing = player->bob; + + angle = (FINEANGLES/70*leveltime)&FINEMASK; + swingx = FixedMul ( swing, finesine[angle]); + + angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; + swingy = -FixedMul ( swingx, finesine[angle]); +} + + + +// +// P_BringUpWeapon +// Starts bringing the pending weapon up +// from the bottom of the screen. +// Uses player +// +void P_BringUpWeapon (player_t* player) +{ + statenum_t newstate; + + if (player->pendingweapon == wp_nochange) + player->pendingweapon = player->readyweapon; + + if (player->pendingweapon == wp_chainsaw) + S_StartSound (player->mo, sfx_sawup); + + newstate = weaponinfo[player->pendingweapon].upstate; + + player->pendingweapon = wp_nochange; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + + P_SetPsprite (player, ps_weapon, newstate); +} + +// +// P_CheckAmmo +// Returns true if there is enough ammo to shoot. +// If not, selects the next weapon to use. +// +boolean P_CheckAmmo (player_t* player) +{ + ammotype_t ammo; + int count; + + ammo = weaponinfo[player->readyweapon].ammo; + + // Minimal amount for one shot varies. + if (player->readyweapon == wp_bfg) + count = deh_bfg_cells_per_shot; + else if (player->readyweapon == wp_supershotgun) + count = 2; // Double barrel. + else + count = 1; // Regular. + + // Some do not need ammunition anyway. + // Return if current ammunition sufficient. + if (ammo == am_noammo || player->ammo[ammo] >= count) + return true; + + // Out of ammo, pick a weapon to change to. + // Preferences are set here. + do + { + if (player->weaponowned[wp_plasma] + && player->ammo[am_cell] + && (gamemode != shareware) ) + { + player->pendingweapon = wp_plasma; + } + else if (player->weaponowned[wp_supershotgun] + && player->ammo[am_shell]>2 + && (gamemode == commercial) ) + { + player->pendingweapon = wp_supershotgun; + } + else if (player->weaponowned[wp_chaingun] + && player->ammo[am_clip]) + { + player->pendingweapon = wp_chaingun; + } + else if (player->weaponowned[wp_shotgun] + && player->ammo[am_shell]) + { + player->pendingweapon = wp_shotgun; + } + else if (player->ammo[am_clip]) + { + player->pendingweapon = wp_pistol; + } + else if (player->weaponowned[wp_chainsaw]) + { + player->pendingweapon = wp_chainsaw; + } + else if (player->weaponowned[wp_missile] + && player->ammo[am_misl]) + { + player->pendingweapon = wp_missile; + } + else if (player->weaponowned[wp_bfg] + && player->ammo[am_cell]>40 + && (gamemode != shareware) ) + { + player->pendingweapon = wp_bfg; + } + else + { + // If everything fails. + player->pendingweapon = wp_fist; + } + + } while (player->pendingweapon == wp_nochange); + + // Now set appropriate weapon overlay. + P_SetPsprite (player, + ps_weapon, + weaponinfo[player->readyweapon].downstate); + + return false; +} + + +// +// P_FireWeapon. +// +void P_FireWeapon (player_t* player) +{ + statenum_t newstate; + + if (!P_CheckAmmo (player)) + return; + + P_SetMobjState (player->mo, S_PLAY_ATK1); + newstate = weaponinfo[player->readyweapon].atkstate; + P_SetPsprite (player, ps_weapon, newstate); + P_NoiseAlert (player->mo, player->mo); +} + + + +// +// P_DropWeapon +// Player died, so put the weapon away. +// +void P_DropWeapon (player_t* player) +{ + P_SetPsprite (player, + ps_weapon, + weaponinfo[player->readyweapon].downstate); +} + + + +// +// A_WeaponReady +// The player can fire the weapon +// or change to another weapon at this time. +// Follows after getting weapon up, +// or after previous attack/fire sequence. +// +void +A_WeaponReady +( player_t* player, + pspdef_t* psp ) +{ + statenum_t newstate; + int angle; + + // get out of attack state + if (player->mo->state == &states[S_PLAY_ATK1] + || player->mo->state == &states[S_PLAY_ATK2] ) + { + P_SetMobjState (player->mo, S_PLAY); + } + + if (player->readyweapon == wp_chainsaw + && psp->state == &states[S_SAW]) + { + S_StartSound (player->mo, sfx_sawidl); + } + + // check for change + // if player is dead, put the weapon away + if (player->pendingweapon != wp_nochange || !player->health) + { + // change weapon + // (pending weapon should allready be validated) + newstate = weaponinfo[player->readyweapon].downstate; + P_SetPsprite (player, ps_weapon, newstate); + return; + } + + // check for fire + // the missile launcher and bfg do not auto fire + if (player->cmd.buttons & BT_ATTACK) + { + if ( !player->attackdown + || (player->readyweapon != wp_missile + && player->readyweapon != wp_bfg) ) + { + player->attackdown = true; + P_FireWeapon (player); + return; + } + } + else + player->attackdown = false; + + // bob the weapon based on movement speed + angle = (128*leveltime)&FINEMASK; + psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); + angle &= FINEANGLES/2-1; + psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); +} + + + +// +// A_ReFire +// The player can re-fire the weapon +// without lowering it entirely. +// +void A_ReFire +( player_t* player, + pspdef_t* psp ) +{ + + // check for fire + // (if a weaponchange is pending, let it go through instead) + if ( (player->cmd.buttons & BT_ATTACK) + && player->pendingweapon == wp_nochange + && player->health) + { + player->refire++; + P_FireWeapon (player); + } + else + { + player->refire = 0; + P_CheckAmmo (player); + } +} + + +void +A_CheckReload +( player_t* player, + pspdef_t* psp ) +{ + P_CheckAmmo (player); +#if 0 + if (player->ammo[am_shell]<2) + P_SetPsprite (player, ps_weapon, S_DSNR1); +#endif +} + + + +// +// A_Lower +// Lowers current weapon, +// and changes weapon at bottom. +// +void +A_Lower +( player_t* player, + pspdef_t* psp ) +{ + psp->sy += LOWERSPEED; + + // Is already down. + if (psp->sy < WEAPONBOTTOM ) + return; + + // Player is dead. + if (player->playerstate == PST_DEAD) + { + psp->sy = WEAPONBOTTOM; + + // don't bring weapon back up + return; + } + + // The old weapon has been lowered off the screen, + // so change the weapon and start raising it + if (!player->health) + { + // Player is dead, so keep the weapon off screen. + P_SetPsprite (player, ps_weapon, S_NULL); + return; + } + + player->readyweapon = player->pendingweapon; + + P_BringUpWeapon (player); +} + + +// +// A_Raise +// +void +A_Raise +( player_t* player, + pspdef_t* psp ) +{ + statenum_t newstate; + + psp->sy -= RAISESPEED; + + if (psp->sy > WEAPONTOP ) + return; + + psp->sy = WEAPONTOP; + + // The weapon has been raised all the way, + // so change to the ready state. + newstate = weaponinfo[player->readyweapon].readystate; + + P_SetPsprite (player, ps_weapon, newstate); +} + + + +// +// A_GunFlash +// +void +A_GunFlash +( player_t* player, + pspdef_t* psp ) +{ + P_SetMobjState (player->mo, S_PLAY_ATK2); + P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); +} + + + +// +// WEAPON ATTACKS +// + + +// +// A_Punch +// +void +A_Punch +( player_t* player, + pspdef_t* psp ) +{ + angle_t angle; + int damage; + int slope; + + damage = (P_Random ()%10+1)<<1; + + if (player->powers[pw_strength]) + damage *= 10; + + angle = player->mo->angle; + angle += P_SubRandom() << 18; + slope = P_AimLineAttack (player->mo, angle, MELEERANGE); + P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); + + // turn to face target + if (linetarget) + { + S_StartSound (player->mo, sfx_punch); + player->mo->angle = R_PointToAngle2 (player->mo->x, + player->mo->y, + linetarget->x, + linetarget->y); + } +} + + +// +// A_Saw +// +void +A_Saw +( player_t* player, + pspdef_t* psp ) +{ + angle_t angle; + int damage; + int slope; + + damage = 2*(P_Random ()%10+1); + angle = player->mo->angle; + angle += P_SubRandom() << 18; + + // use meleerange + 1 se the puff doesn't skip the flash + slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1); + P_LineAttack (player->mo, angle, MELEERANGE+1, slope, damage); + + if (!linetarget) + { + S_StartSound (player->mo, sfx_sawful); + return; + } + S_StartSound (player->mo, sfx_sawhit); + + // turn to face target + angle = R_PointToAngle2 (player->mo->x, player->mo->y, + linetarget->x, linetarget->y); + if (angle - player->mo->angle > ANG180) + { + if ((signed int) (angle - player->mo->angle) < -ANG90/20) + player->mo->angle = angle + ANG90/21; + else + player->mo->angle -= ANG90/20; + } + else + { + if (angle - player->mo->angle > ANG90/20) + player->mo->angle = angle - ANG90/21; + else + player->mo->angle += ANG90/20; + } + player->mo->flags |= MF_JUSTATTACKED; +} + +// Doom does not check the bounds of the ammo array. As a result, +// it is possible to use an ammo type > 4 that overflows into the +// maxammo array and affects that instead. Through dehacked, for +// example, it is possible to make a weapon that decreases the max +// number of ammo for another weapon. Emulate this. + +static void DecreaseAmmo(player_t *player, int ammonum, int amount) +{ + if (ammonum < NUMAMMO) + { + player->ammo[ammonum] -= amount; + } + else + { + player->maxammo[ammonum - NUMAMMO] -= amount; + } +} + + +// +// A_FireMissile +// +void +A_FireMissile +( player_t* player, + pspdef_t* psp ) +{ + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); + P_SpawnPlayerMissile (player->mo, MT_ROCKET); +} + + +// +// A_FireBFG +// +void +A_FireBFG +( player_t* player, + pspdef_t* psp ) +{ + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, + deh_bfg_cells_per_shot); + P_SpawnPlayerMissile (player->mo, MT_BFG); +} + + + +// +// A_FirePlasma +// +void +A_FirePlasma +( player_t* player, + pspdef_t* psp ) +{ + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); + + P_SetPsprite (player, + ps_flash, + weaponinfo[player->readyweapon].flashstate+(P_Random ()&1) ); + + P_SpawnPlayerMissile (player->mo, MT_PLASMA); +} + + + +// +// P_BulletSlope +// Sets a slope so a near miss is at aproximately +// the height of the intended target +// +fixed_t bulletslope; + + +void P_BulletSlope (mobj_t* mo) +{ + angle_t an; + + // see which target is to be aimed at + an = mo->angle; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + + if (!linetarget) + { + an += 1<<26; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + if (!linetarget) + { + an -= 2<<26; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + } + } +} + + +// +// P_GunShot +// +void +P_GunShot +( mobj_t* mo, + boolean accurate ) +{ + angle_t angle; + int damage; + + damage = 5*(P_Random ()%3+1); + angle = mo->angle; + + if (!accurate) + angle += P_SubRandom() << 18; + + P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage); +} + + +// +// A_FirePistol +// +void +A_FirePistol +( player_t* player, + pspdef_t* psp ) +{ + S_StartSound (player->mo, sfx_pistol); + + P_SetMobjState (player->mo, S_PLAY_ATK2); + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); + + P_SetPsprite (player, + ps_flash, + weaponinfo[player->readyweapon].flashstate); + + P_BulletSlope (player->mo); + P_GunShot (player->mo, !player->refire); +} + + +// +// A_FireShotgun +// +void +A_FireShotgun +( player_t* player, + pspdef_t* psp ) +{ + int i; + + S_StartSound (player->mo, sfx_shotgn); + P_SetMobjState (player->mo, S_PLAY_ATK2); + + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); + + P_SetPsprite (player, + ps_flash, + weaponinfo[player->readyweapon].flashstate); + + P_BulletSlope (player->mo); + + for (i=0 ; i<7 ; i++) + P_GunShot (player->mo, false); +} + + + +// +// A_FireShotgun2 +// +void +A_FireShotgun2 +( player_t* player, + pspdef_t* psp ) +{ + int i; + angle_t angle; + int damage; + + + S_StartSound (player->mo, sfx_dshtgn); + P_SetMobjState (player->mo, S_PLAY_ATK2); + + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 2); + + P_SetPsprite (player, + ps_flash, + weaponinfo[player->readyweapon].flashstate); + + P_BulletSlope (player->mo); + + for (i=0 ; i<20 ; i++) + { + damage = 5*(P_Random ()%3+1); + angle = player->mo->angle; + angle += P_SubRandom() << ANGLETOFINESHIFT; + P_LineAttack (player->mo, + angle, + MISSILERANGE, + bulletslope + (P_SubRandom() << 5), damage); + } +} + + +// +// A_FireCGun +// +void +A_FireCGun +( player_t* player, + pspdef_t* psp ) +{ + S_StartSound (player->mo, sfx_pistol); + + if (!player->ammo[weaponinfo[player->readyweapon].ammo]) + return; + + P_SetMobjState (player->mo, S_PLAY_ATK2); + DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); + + P_SetPsprite (player, + ps_flash, + weaponinfo[player->readyweapon].flashstate + + psp->state + - &states[S_CHAIN1] ); + + P_BulletSlope (player->mo); + + P_GunShot (player->mo, !player->refire); +} + + + +// +// ? +// +void A_Light0 (player_t *player, pspdef_t *psp) +{ + player->extralight = 0; +} + +void A_Light1 (player_t *player, pspdef_t *psp) +{ + player->extralight = 1; +} + +void A_Light2 (player_t *player, pspdef_t *psp) +{ + player->extralight = 2; +} + + +// +// A_BFGSpray +// Spawn a BFG explosion on every monster in view +// +void A_BFGSpray (mobj_t* mo) +{ + int i; + int j; + int damage; + angle_t an; + + // offset angles from its attack angle + for (i=0 ; i<40 ; i++) + { + an = mo->angle - ANG90/2 + ANG90/40*i; + + // mo->target is the originator (player) + // of the missile + P_AimLineAttack (mo->target, an, 16*64*FRACUNIT); + + if (!linetarget) + continue; + + P_SpawnMobj (linetarget->x, + linetarget->y, + linetarget->z + (linetarget->height>>2), + MT_EXTRABFG); + + damage = 0; + for (j=0;j<15;j++) + damage += (P_Random()&7) + 1; + + P_DamageMobj (linetarget, mo->target,mo->target, damage); + } +} + + +// +// A_BFGsound +// +void +A_BFGsound +( player_t* player, + pspdef_t* psp ) +{ + S_StartSound (player->mo, sfx_bfg); +} + + + +// +// P_SetupPsprites +// Called at start of level for each player. +// +void P_SetupPsprites (player_t* player) +{ + int i; + + // remove all psprites + for (i=0 ; ipsprites[i].state = NULL; + + // spawn the gun + player->pendingweapon = player->readyweapon; + P_BringUpWeapon (player); +} + + + + +// +// P_MovePsprites +// Called every tic by player thinking routine. +// +void P_MovePsprites (player_t* player) +{ + int i; + pspdef_t* psp; + + psp = &player->psprites[0]; + for (i=0 ; istate) + { + // drop tic count and possibly change state + + // a -1 tic count never changes + if (psp->tics != -1) + { + psp->tics--; + if (!psp->tics) + P_SetPsprite (player, i, psp->state->nextstate); + } + } + } + + player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; + player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; +} + + diff --git a/games/NXDoom/src/doom/p_pspr.h b/games/NXDoom/src/doom/p_pspr.h new file mode 100644 index 00000000000..2616bd4760d --- /dev/null +++ b/games/NXDoom/src/doom/p_pspr.h @@ -0,0 +1,75 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Sprite animation. +// + + +#ifndef __P_PSPR__ +#define __P_PSPR__ + +// Basic data types. +// Needs fixed point, and BAM angles. +#include "m_fixed.h" +#include "tables.h" + + +// +// Needs to include the precompiled +// sprite animation tables. +// Header generated by multigen utility. +// This includes all the data for thing animation, +// i.e. the Thing Atrributes table +// and the Frame Sequence table. +#include "info.h" + + + +// +// Frame flags: +// handles maximum brightness (torches, muzzle flare, light sources) +// +#define FF_FULLBRIGHT 0x8000 // flag in thing->frame +#define FF_FRAMEMASK 0x7fff + + + +// +// Overlay psprites are scaled shapes +// drawn directly on the view screen, +// coordinates are given for a 320*200 view screen. +// +typedef enum +{ + ps_weapon, + ps_flash, + NUMPSPRITES + +} psprnum_t; + +typedef struct +{ + state_t* state; // a NULL state means not active + int tics; + fixed_t sx; + fixed_t sy; + +} pspdef_t; + + +extern fixed_t bulletslope; + + +#endif diff --git a/games/NXDoom/src/doom/p_saveg.c b/games/NXDoom/src/doom/p_saveg.c new file mode 100644 index 00000000000..1192bff90bb --- /dev/null +++ b/games/NXDoom/src/doom/p_saveg.c @@ -0,0 +1,1888 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Archiving: SaveGame I/O. +// + + +#include +#include + +#include "dstrings.h" +#include "deh_main.h" +#include "i_system.h" +#include "z_zone.h" +#include "p_local.h" +#include "p_saveg.h" + +// State. +#include "doomstat.h" +#include "g_game.h" +#include "m_misc.h" +#include "r_state.h" + +FILE *save_stream; +int savegamelength; +boolean savegame_error; + +// Get the filename of a temporary file to write the savegame to. After +// the file has been successfully saved, it will be renamed to the +// real file. + +char *P_TempSaveGameFile(void) +{ + static char *filename = NULL; + + if (filename == NULL) + { + filename = M_StringJoin(savegamedir, "temp.dsg", NULL); + } + + return filename; +} + +// Get the filename of the save game file to use for the specified slot. + +char *P_SaveGameFile(int slot) +{ + static char *filename = NULL; + static size_t filename_size = 0; + char basename[32]; + + if (filename == NULL) + { + filename_size = strlen(savegamedir) + 32; + filename = malloc(filename_size); + } + + DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot); + M_snprintf(filename, filename_size, "%s%s", savegamedir, basename); + + return filename; +} + +// Endian-safe integer read/write functions + +static byte saveg_read8(void) +{ + byte result = -1; + + if (fread(&result, 1, 1, save_stream) < 1) + { + if (!savegame_error) + { + fprintf(stderr, "saveg_read8: Unexpected end of file while " + "reading save game\n"); + + savegame_error = true; + } + } + + return result; +} + +static void saveg_write8(byte value) +{ + if (fwrite(&value, 1, 1, save_stream) < 1) + { + if (!savegame_error) + { + fprintf(stderr, "saveg_write8: Error while writing save game\n"); + + savegame_error = true; + } + } +} + +static short saveg_read16(void) +{ + int result; + + result = saveg_read8(); + result |= saveg_read8() << 8; + + return result; +} + +static void saveg_write16(short value) +{ + saveg_write8(value & 0xff); + saveg_write8((value >> 8) & 0xff); +} + +static int saveg_read32(void) +{ + int result; + + result = saveg_read8(); + result |= saveg_read8() << 8; + result |= saveg_read8() << 16; + result |= saveg_read8() << 24; + + return result; +} + +static void saveg_write32(int value) +{ + saveg_write8(value & 0xff); + saveg_write8((value >> 8) & 0xff); + saveg_write8((value >> 16) & 0xff); + saveg_write8((value >> 24) & 0xff); +} + +// Pad to 4-byte boundaries + +static void saveg_read_pad(void) +{ + unsigned long pos; + int padding; + int i; + + pos = ftell(save_stream); + + padding = (4 - (pos & 3)) & 3; + + for (i=0; ix = saveg_read16(); + + // short y; + str->y = saveg_read16(); + + // short angle; + str->angle = saveg_read16(); + + // short type; + str->type = saveg_read16(); + + // short options; + str->options = saveg_read16(); +} + +static void saveg_write_mapthing_t(mapthing_t *str) +{ + // short x; + saveg_write16(str->x); + + // short y; + saveg_write16(str->y); + + // short angle; + saveg_write16(str->angle); + + // short type; + saveg_write16(str->type); + + // short options; + saveg_write16(str->options); +} + +// +// actionf_t +// + +static void saveg_read_actionf_t(actionf_t *str) +{ + // actionf_p1 acp1; + str->acp1 = saveg_readp(); +} + +static void saveg_write_actionf_t(actionf_t *str) +{ + // actionf_p1 acp1; + saveg_writep(str->acp1); +} + +// +// think_t +// +// This is just an actionf_t. +// + +#define saveg_read_think_t saveg_read_actionf_t +#define saveg_write_think_t saveg_write_actionf_t + +// +// thinker_t +// + +static void saveg_read_thinker_t(thinker_t *str) +{ + // struct thinker_s* prev; + str->prev = saveg_readp(); + + // struct thinker_s* next; + str->next = saveg_readp(); + + // think_t function; + saveg_read_think_t(&str->function); +} + +static void saveg_write_thinker_t(thinker_t *str) +{ + // struct thinker_s* prev; + saveg_writep(str->prev); + + // struct thinker_s* next; + saveg_writep(str->next); + + // think_t function; + saveg_write_think_t(&str->function); +} + +// +// mobj_t +// + +static void saveg_read_mobj_t(mobj_t *str) +{ + int pl; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // fixed_t x; + str->x = saveg_read32(); + + // fixed_t y; + str->y = saveg_read32(); + + // fixed_t z; + str->z = saveg_read32(); + + // struct mobj_s* snext; + str->snext = saveg_readp(); + + // struct mobj_s* sprev; + str->sprev = saveg_readp(); + + // angle_t angle; + str->angle = saveg_read32(); + + // spritenum_t sprite; + str->sprite = saveg_read_enum(); + + // int frame; + str->frame = saveg_read32(); + + // struct mobj_s* bnext; + str->bnext = saveg_readp(); + + // struct mobj_s* bprev; + str->bprev = saveg_readp(); + + // struct subsector_s* subsector; + str->subsector = saveg_readp(); + + // fixed_t floorz; + str->floorz = saveg_read32(); + + // fixed_t ceilingz; + str->ceilingz = saveg_read32(); + + // fixed_t radius; + str->radius = saveg_read32(); + + // fixed_t height; + str->height = saveg_read32(); + + // fixed_t momx; + str->momx = saveg_read32(); + + // fixed_t momy; + str->momy = saveg_read32(); + + // fixed_t momz; + str->momz = saveg_read32(); + + // int validcount; + str->validcount = saveg_read32(); + + // mobjtype_t type; + str->type = saveg_read_enum(); + + // mobjinfo_t* info; + str->info = saveg_readp(); + + // int tics; + str->tics = saveg_read32(); + + // state_t* state; + str->state = &states[saveg_read32()]; + + // int flags; + str->flags = saveg_read32(); + + // int health; + str->health = saveg_read32(); + + // int movedir; + str->movedir = saveg_read32(); + + // int movecount; + str->movecount = saveg_read32(); + + // struct mobj_s* target; + str->target = saveg_readp(); + + // int reactiontime; + str->reactiontime = saveg_read32(); + + // int threshold; + str->threshold = saveg_read32(); + + // struct player_s* player; + pl = saveg_read32(); + + if (pl > 0) + { + str->player = &players[pl - 1]; + str->player->mo = str; + } + else + { + str->player = NULL; + } + + // int lastlook; + str->lastlook = saveg_read32(); + + // mapthing_t spawnpoint; + saveg_read_mapthing_t(&str->spawnpoint); + + // struct mobj_s* tracer; + str->tracer = saveg_readp(); +} + +static void saveg_write_mobj_t(mobj_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // fixed_t x; + saveg_write32(str->x); + + // fixed_t y; + saveg_write32(str->y); + + // fixed_t z; + saveg_write32(str->z); + + // struct mobj_s* snext; + saveg_writep(str->snext); + + // struct mobj_s* sprev; + saveg_writep(str->sprev); + + // angle_t angle; + saveg_write32(str->angle); + + // spritenum_t sprite; + saveg_write_enum(str->sprite); + + // int frame; + saveg_write32(str->frame); + + // struct mobj_s* bnext; + saveg_writep(str->bnext); + + // struct mobj_s* bprev; + saveg_writep(str->bprev); + + // struct subsector_s* subsector; + saveg_writep(str->subsector); + + // fixed_t floorz; + saveg_write32(str->floorz); + + // fixed_t ceilingz; + saveg_write32(str->ceilingz); + + // fixed_t radius; + saveg_write32(str->radius); + + // fixed_t height; + saveg_write32(str->height); + + // fixed_t momx; + saveg_write32(str->momx); + + // fixed_t momy; + saveg_write32(str->momy); + + // fixed_t momz; + saveg_write32(str->momz); + + // int validcount; + saveg_write32(str->validcount); + + // mobjtype_t type; + saveg_write_enum(str->type); + + // mobjinfo_t* info; + saveg_writep(str->info); + + // int tics; + saveg_write32(str->tics); + + // state_t* state; + saveg_write32(str->state - states); + + // int flags; + saveg_write32(str->flags); + + // int health; + saveg_write32(str->health); + + // int movedir; + saveg_write32(str->movedir); + + // int movecount; + saveg_write32(str->movecount); + + // struct mobj_s* target; + saveg_writep(str->target); + + // int reactiontime; + saveg_write32(str->reactiontime); + + // int threshold; + saveg_write32(str->threshold); + + // struct player_s* player; + if (str->player) + { + saveg_write32(str->player - players + 1); + } + else + { + saveg_write32(0); + } + + // int lastlook; + saveg_write32(str->lastlook); + + // mapthing_t spawnpoint; + saveg_write_mapthing_t(&str->spawnpoint); + + // struct mobj_s* tracer; + saveg_writep(str->tracer); +} + + +// +// ticcmd_t +// + +static void saveg_read_ticcmd_t(ticcmd_t *str) +{ + + // signed char forwardmove; + str->forwardmove = saveg_read8(); + + // signed char sidemove; + str->sidemove = saveg_read8(); + + // short angleturn; + str->angleturn = saveg_read16(); + + // short consistancy; + str->consistancy = saveg_read16(); + + // byte chatchar; + str->chatchar = saveg_read8(); + + // byte buttons; + str->buttons = saveg_read8(); +} + +static void saveg_write_ticcmd_t(ticcmd_t *str) +{ + + // signed char forwardmove; + saveg_write8(str->forwardmove); + + // signed char sidemove; + saveg_write8(str->sidemove); + + // short angleturn; + saveg_write16(str->angleturn); + + // short consistancy; + saveg_write16(str->consistancy); + + // byte chatchar; + saveg_write8(str->chatchar); + + // byte buttons; + saveg_write8(str->buttons); +} + +// +// pspdef_t +// + +static void saveg_read_pspdef_t(pspdef_t *str) +{ + int state; + + // state_t* state; + state = saveg_read32(); + + if (state > 0) + { + str->state = &states[state]; + } + else + { + str->state = NULL; + } + + // int tics; + str->tics = saveg_read32(); + + // fixed_t sx; + str->sx = saveg_read32(); + + // fixed_t sy; + str->sy = saveg_read32(); +} + +static void saveg_write_pspdef_t(pspdef_t *str) +{ + // state_t* state; + if (str->state) + { + saveg_write32(str->state - states); + } + else + { + saveg_write32(0); + } + + // int tics; + saveg_write32(str->tics); + + // fixed_t sx; + saveg_write32(str->sx); + + // fixed_t sy; + saveg_write32(str->sy); +} + +// +// player_t +// + +static void saveg_read_player_t(player_t *str) +{ + int i; + + // mobj_t* mo; + str->mo = saveg_readp(); + + // playerstate_t playerstate; + str->playerstate = saveg_read_enum(); + + // ticcmd_t cmd; + saveg_read_ticcmd_t(&str->cmd); + + // fixed_t viewz; + str->viewz = saveg_read32(); + + // fixed_t viewheight; + str->viewheight = saveg_read32(); + + // fixed_t deltaviewheight; + str->deltaviewheight = saveg_read32(); + + // fixed_t bob; + str->bob = saveg_read32(); + + // int health; + str->health = saveg_read32(); + + // int armorpoints; + str->armorpoints = saveg_read32(); + + // int armortype; + str->armortype = saveg_read32(); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i] = saveg_read32(); + } + + // boolean cards[NUMCARDS]; + for (i=0; icards[i] = saveg_read32(); + } + + // boolean backpack; + str->backpack = saveg_read32(); + + // int frags[MAXPLAYERS]; + for (i=0; ifrags[i] = saveg_read32(); + } + + // weapontype_t readyweapon; + str->readyweapon = saveg_read_enum(); + + // weapontype_t pendingweapon; + str->pendingweapon = saveg_read_enum(); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i] = saveg_read32(); + } + + // int ammo[NUMAMMO]; + for (i=0; iammo[i] = saveg_read32(); + } + + // int maxammo[NUMAMMO]; + for (i=0; imaxammo[i] = saveg_read32(); + } + + // int attackdown; + str->attackdown = saveg_read32(); + + // int usedown; + str->usedown = saveg_read32(); + + // int cheats; + str->cheats = saveg_read32(); + + // int refire; + str->refire = saveg_read32(); + + // int killcount; + str->killcount = saveg_read32(); + + // int itemcount; + str->itemcount = saveg_read32(); + + // int secretcount; + str->secretcount = saveg_read32(); + + // char* message; + str->message = saveg_readp(); + + // int damagecount; + str->damagecount = saveg_read32(); + + // int bonuscount; + str->bonuscount = saveg_read32(); + + // mobj_t* attacker; + str->attacker = saveg_readp(); + + // int extralight; + str->extralight = saveg_read32(); + + // int fixedcolormap; + str->fixedcolormap = saveg_read32(); + + // int colormap; + str->colormap = saveg_read32(); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // boolean didsecret; + str->didsecret = saveg_read32(); +} + +static void saveg_write_player_t(player_t *str) +{ + int i; + + // mobj_t* mo; + saveg_writep(str->mo); + + // playerstate_t playerstate; + saveg_write_enum(str->playerstate); + + // ticcmd_t cmd; + saveg_write_ticcmd_t(&str->cmd); + + // fixed_t viewz; + saveg_write32(str->viewz); + + // fixed_t viewheight; + saveg_write32(str->viewheight); + + // fixed_t deltaviewheight; + saveg_write32(str->deltaviewheight); + + // fixed_t bob; + saveg_write32(str->bob); + + // int health; + saveg_write32(str->health); + + // int armorpoints; + saveg_write32(str->armorpoints); + + // int armortype; + saveg_write32(str->armortype); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i]); + } + + // boolean cards[NUMCARDS]; + for (i=0; icards[i]); + } + + // boolean backpack; + saveg_write32(str->backpack); + + // int frags[MAXPLAYERS]; + for (i=0; ifrags[i]); + } + + // weapontype_t readyweapon; + saveg_write_enum(str->readyweapon); + + // weapontype_t pendingweapon; + saveg_write_enum(str->pendingweapon); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i]); + } + + // int ammo[NUMAMMO]; + for (i=0; iammo[i]); + } + + // int maxammo[NUMAMMO]; + for (i=0; imaxammo[i]); + } + + // int attackdown; + saveg_write32(str->attackdown); + + // int usedown; + saveg_write32(str->usedown); + + // int cheats; + saveg_write32(str->cheats); + + // int refire; + saveg_write32(str->refire); + + // int killcount; + saveg_write32(str->killcount); + + // int itemcount; + saveg_write32(str->itemcount); + + // int secretcount; + saveg_write32(str->secretcount); + + // char* message; + saveg_writep(str->message); + + // int damagecount; + saveg_write32(str->damagecount); + + // int bonuscount; + saveg_write32(str->bonuscount); + + // mobj_t* attacker; + saveg_writep(str->attacker); + + // int extralight; + saveg_write32(str->extralight); + + // int fixedcolormap; + saveg_write32(str->fixedcolormap); + + // int colormap; + saveg_write32(str->colormap); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // boolean didsecret; + saveg_write32(str->didsecret); +} + + +// +// ceiling_t +// + +static void saveg_read_ceiling_t(ceiling_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // ceiling_e type; + str->type = saveg_read_enum(); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // fixed_t bottomheight; + str->bottomheight = saveg_read32(); + + // fixed_t topheight; + str->topheight = saveg_read32(); + + // fixed_t speed; + str->speed = saveg_read32(); + + // boolean crush; + str->crush = saveg_read32(); + + // int direction; + str->direction = saveg_read32(); + + // int tag; + str->tag = saveg_read32(); + + // int olddirection; + str->olddirection = saveg_read32(); +} + +static void saveg_write_ceiling_t(ceiling_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // ceiling_e type; + saveg_write_enum(str->type); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // fixed_t bottomheight; + saveg_write32(str->bottomheight); + + // fixed_t topheight; + saveg_write32(str->topheight); + + // fixed_t speed; + saveg_write32(str->speed); + + // boolean crush; + saveg_write32(str->crush); + + // int direction; + saveg_write32(str->direction); + + // int tag; + saveg_write32(str->tag); + + // int olddirection; + saveg_write32(str->olddirection); +} + +// +// vldoor_t +// + +static void saveg_read_vldoor_t(vldoor_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // vldoor_e type; + str->type = saveg_read_enum(); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // fixed_t topheight; + str->topheight = saveg_read32(); + + // fixed_t speed; + str->speed = saveg_read32(); + + // int direction; + str->direction = saveg_read32(); + + // int topwait; + str->topwait = saveg_read32(); + + // int topcountdown; + str->topcountdown = saveg_read32(); +} + +static void saveg_write_vldoor_t(vldoor_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // vldoor_e type; + saveg_write_enum(str->type); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // fixed_t topheight; + saveg_write32(str->topheight); + + // fixed_t speed; + saveg_write32(str->speed); + + // int direction; + saveg_write32(str->direction); + + // int topwait; + saveg_write32(str->topwait); + + // int topcountdown; + saveg_write32(str->topcountdown); +} + +// +// floormove_t +// + +static void saveg_read_floormove_t(floormove_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // floor_e type; + str->type = saveg_read_enum(); + + // boolean crush; + str->crush = saveg_read32(); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int direction; + str->direction = saveg_read32(); + + // int newspecial; + str->newspecial = saveg_read32(); + + // short texture; + str->texture = saveg_read16(); + + // fixed_t floordestheight; + str->floordestheight = saveg_read32(); + + // fixed_t speed; + str->speed = saveg_read32(); +} + +static void saveg_write_floormove_t(floormove_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // floor_e type; + saveg_write_enum(str->type); + + // boolean crush; + saveg_write32(str->crush); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int direction; + saveg_write32(str->direction); + + // int newspecial; + saveg_write32(str->newspecial); + + // short texture; + saveg_write16(str->texture); + + // fixed_t floordestheight; + saveg_write32(str->floordestheight); + + // fixed_t speed; + saveg_write32(str->speed); +} + +// +// plat_t +// + +static void saveg_read_plat_t(plat_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // fixed_t speed; + str->speed = saveg_read32(); + + // fixed_t low; + str->low = saveg_read32(); + + // fixed_t high; + str->high = saveg_read32(); + + // int wait; + str->wait = saveg_read32(); + + // int count; + str->count = saveg_read32(); + + // plat_e status; + str->status = saveg_read_enum(); + + // plat_e oldstatus; + str->oldstatus = saveg_read_enum(); + + // boolean crush; + str->crush = saveg_read32(); + + // int tag; + str->tag = saveg_read32(); + + // plattype_e type; + str->type = saveg_read_enum(); +} + +static void saveg_write_plat_t(plat_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // fixed_t speed; + saveg_write32(str->speed); + + // fixed_t low; + saveg_write32(str->low); + + // fixed_t high; + saveg_write32(str->high); + + // int wait; + saveg_write32(str->wait); + + // int count; + saveg_write32(str->count); + + // plat_e status; + saveg_write_enum(str->status); + + // plat_e oldstatus; + saveg_write_enum(str->oldstatus); + + // boolean crush; + saveg_write32(str->crush); + + // int tag; + saveg_write32(str->tag); + + // plattype_e type; + saveg_write_enum(str->type); +} + +// +// lightflash_t +// + +static void saveg_read_lightflash_t(lightflash_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int count; + str->count = saveg_read32(); + + // int maxlight; + str->maxlight = saveg_read32(); + + // int minlight; + str->minlight = saveg_read32(); + + // int maxtime; + str->maxtime = saveg_read32(); + + // int mintime; + str->mintime = saveg_read32(); +} + +static void saveg_write_lightflash_t(lightflash_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int count; + saveg_write32(str->count); + + // int maxlight; + saveg_write32(str->maxlight); + + // int minlight; + saveg_write32(str->minlight); + + // int maxtime; + saveg_write32(str->maxtime); + + // int mintime; + saveg_write32(str->mintime); +} + +// +// strobe_t +// + +static void saveg_read_strobe_t(strobe_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int count; + str->count = saveg_read32(); + + // int minlight; + str->minlight = saveg_read32(); + + // int maxlight; + str->maxlight = saveg_read32(); + + // int darktime; + str->darktime = saveg_read32(); + + // int brighttime; + str->brighttime = saveg_read32(); +} + +static void saveg_write_strobe_t(strobe_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int count; + saveg_write32(str->count); + + // int minlight; + saveg_write32(str->minlight); + + // int maxlight; + saveg_write32(str->maxlight); + + // int darktime; + saveg_write32(str->darktime); + + // int brighttime; + saveg_write32(str->brighttime); +} + +// +// glow_t +// + +static void saveg_read_glow_t(glow_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int minlight; + str->minlight = saveg_read32(); + + // int maxlight; + str->maxlight = saveg_read32(); + + // int direction; + str->direction = saveg_read32(); +} + +static void saveg_write_glow_t(glow_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int minlight; + saveg_write32(str->minlight); + + // int maxlight; + saveg_write32(str->maxlight); + + // int direction; + saveg_write32(str->direction); +} + +// +// Write the header for a savegame +// + +void P_WriteSaveGameHeader(char *description) +{ + char name[VERSIONSIZE]; + int i; + + for (i=0; description[i] != '\0'; ++i) + saveg_write8(description[i]); + for (; i> 16) & 0xff); + saveg_write8((leveltime >> 8) & 0xff); + saveg_write8(leveltime & 0xff); +} + +// +// Read the header for a savegame +// + +boolean P_ReadSaveGameHeader(void) +{ + int i; + byte a, b, c; + char vcheck[VERSIONSIZE]; + char read_vcheck[VERSIONSIZE]; + + // skip the description field + + for (i=0; ifloorheight >> FRACBITS); + saveg_write16(sec->ceilingheight >> FRACBITS); + saveg_write16(sec->floorpic); + saveg_write16(sec->ceilingpic); + saveg_write16(sec->lightlevel); + saveg_write16(sec->special); // needed? + saveg_write16(sec->tag); // needed? + } + + + // do lines + for (i=0, li = lines ; iflags); + saveg_write16(li->special); + saveg_write16(li->tag); + for (j=0 ; j<2 ; j++) + { + if (li->sidenum[j] == -1) + continue; + + si = &sides[li->sidenum[j]]; + + saveg_write16(si->textureoffset >> FRACBITS); + saveg_write16(si->rowoffset >> FRACBITS); + saveg_write16(si->toptexture); + saveg_write16(si->bottomtexture); + saveg_write16(si->midtexture); + } + } +} + + + +// +// P_UnArchiveWorld +// +void P_UnArchiveWorld (void) +{ + int i; + int j; + sector_t* sec; + line_t* li; + side_t* si; + + // do sectors + for (i=0, sec = sectors ; ifloorheight = saveg_read16() << FRACBITS; + sec->ceilingheight = saveg_read16() << FRACBITS; + sec->floorpic = saveg_read16(); + sec->ceilingpic = saveg_read16(); + sec->lightlevel = saveg_read16(); + sec->special = saveg_read16(); // needed? + sec->tag = saveg_read16(); // needed? + sec->specialdata = 0; + sec->soundtarget = 0; + } + + // do lines + for (i=0, li = lines ; iflags = saveg_read16(); + li->special = saveg_read16(); + li->tag = saveg_read16(); + for (j=0 ; j<2 ; j++) + { + if (li->sidenum[j] == -1) + continue; + si = &sides[li->sidenum[j]]; + si->textureoffset = saveg_read16() << FRACBITS; + si->rowoffset = saveg_read16() << FRACBITS; + si->toptexture = saveg_read16(); + si->bottomtexture = saveg_read16(); + si->midtexture = saveg_read16(); + } + } +} + + + + + +// +// Thinkers +// +typedef enum +{ + tc_end, + tc_mobj + +} thinkerclass_t; + + +// +// P_ArchiveThinkers +// +void P_ArchiveThinkers (void) +{ + thinker_t* th; + + // save off the current thinkers + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + { + saveg_write8(tc_mobj); + saveg_write_pad(); + saveg_write_mobj_t((mobj_t *) th); + + continue; + } + + // I_Error ("P_ArchiveThinkers: Unknown thinker function"); + } + + // add a terminating marker + saveg_write8(tc_end); +} + + + +// +// P_UnArchiveThinkers +// +void P_UnArchiveThinkers (void) +{ + byte tclass; + thinker_t* currentthinker; + thinker_t* next; + mobj_t* mobj; + + // remove all the current thinkers + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + next = currentthinker->next; + + if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + P_RemoveMobj ((mobj_t *)currentthinker); + else + Z_Free (currentthinker); + + currentthinker = next; + } + P_InitThinkers (); + + // read in saved thinkers + while (1) + { + tclass = saveg_read8(); + switch (tclass) + { + case tc_end: + return; // end of list + + case tc_mobj: + saveg_read_pad(); + mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); + saveg_read_mobj_t(mobj); + + mobj->target = NULL; + mobj->tracer = NULL; + P_SetThingPosition (mobj); + mobj->info = &mobjinfo[mobj->type]; + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; + P_AddThinker (&mobj->thinker); + break; + + default: + I_Error ("Unknown tclass %i in savegame",tclass); + } + + } + +} + + +// +// P_ArchiveSpecials +// +enum +{ + tc_ceiling, + tc_door, + tc_floor, + tc_plat, + tc_flash, + tc_strobe, + tc_glow, + tc_endspecials + +} specials_e; + + + +// +// Things to handle: +// +// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list +// T_VerticalDoor, (vldoor_t: sector_t * swizzle), +// T_MoveFloor, (floormove_t: sector_t * swizzle), +// T_LightFlash, (lightflash_t: sector_t * swizzle), +// T_StrobeFlash, (strobe_t: sector_t *), +// T_Glow, (glow_t: sector_t *), +// T_PlatRaise, (plat_t: sector_t *), - active list +// +void P_ArchiveSpecials (void) +{ + thinker_t* th; + int i; + + // save off the current thinkers + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acv == (actionf_v)NULL) + { + for (i = 0; i < MAXCEILINGS;i++) + if (activeceilings[i] == (ceiling_t *)th) + break; + + if (ifunction.acp1 == (actionf_p1)T_MoveCeiling) + { + saveg_write8(tc_ceiling); + saveg_write_pad(); + saveg_write_ceiling_t((ceiling_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_VerticalDoor) + { + saveg_write8(tc_door); + saveg_write_pad(); + saveg_write_vldoor_t((vldoor_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_MoveFloor) + { + saveg_write8(tc_floor); + saveg_write_pad(); + saveg_write_floormove_t((floormove_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_PlatRaise) + { + saveg_write8(tc_plat); + saveg_write_pad(); + saveg_write_plat_t((plat_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_LightFlash) + { + saveg_write8(tc_flash); + saveg_write_pad(); + saveg_write_lightflash_t((lightflash_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_StrobeFlash) + { + saveg_write8(tc_strobe); + saveg_write_pad(); + saveg_write_strobe_t((strobe_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_Glow) + { + saveg_write8(tc_glow); + saveg_write_pad(); + saveg_write_glow_t((glow_t *) th); + continue; + } + } + + // add a terminating marker + saveg_write8(tc_endspecials); + +} + + +// +// P_UnArchiveSpecials +// +void P_UnArchiveSpecials (void) +{ + byte tclass; + ceiling_t* ceiling; + vldoor_t* door; + floormove_t* floor; + plat_t* plat; + lightflash_t* flash; + strobe_t* strobe; + glow_t* glow; + + + // read in saved thinkers + while (1) + { + tclass = saveg_read8(); + + switch (tclass) + { + case tc_endspecials: + return; // end of list + + case tc_ceiling: + saveg_read_pad(); + ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL); + saveg_read_ceiling_t(ceiling); + ceiling->sector->specialdata = ceiling; + + if (ceiling->thinker.function.acp1) + ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; + + P_AddThinker (&ceiling->thinker); + P_AddActiveCeiling(ceiling); + break; + + case tc_door: + saveg_read_pad(); + door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL); + saveg_read_vldoor_t(door); + door->sector->specialdata = door; + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + P_AddThinker (&door->thinker); + break; + + case tc_floor: + saveg_read_pad(); + floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); + saveg_read_floormove_t(floor); + floor->sector->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; + P_AddThinker (&floor->thinker); + break; + + case tc_plat: + saveg_read_pad(); + plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); + saveg_read_plat_t(plat); + plat->sector->specialdata = plat; + + if (plat->thinker.function.acp1) + plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise; + + P_AddThinker (&plat->thinker); + P_AddActivePlat(plat); + break; + + case tc_flash: + saveg_read_pad(); + flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); + saveg_read_lightflash_t(flash); + flash->thinker.function.acp1 = (actionf_p1)T_LightFlash; + P_AddThinker (&flash->thinker); + break; + + case tc_strobe: + saveg_read_pad(); + strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); + saveg_read_strobe_t(strobe); + strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; + P_AddThinker (&strobe->thinker); + break; + + case tc_glow: + saveg_read_pad(); + glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); + saveg_read_glow_t(glow); + glow->thinker.function.acp1 = (actionf_p1)T_Glow; + P_AddThinker (&glow->thinker); + break; + + default: + I_Error ("P_UnarchiveSpecials:Unknown tclass %i " + "in savegame",tclass); + } + + } + +} + diff --git a/games/NXDoom/src/doom/p_saveg.h b/games/NXDoom/src/doom/p_saveg.h new file mode 100644 index 00000000000..518a5b70658 --- /dev/null +++ b/games/NXDoom/src/doom/p_saveg.h @@ -0,0 +1,65 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Savegame I/O, archiving, persistence. +// + + +#ifndef __P_SAVEG__ +#define __P_SAVEG__ + +#include + +#define SAVEGAME_EOF 0x1d +#define VERSIONSIZE 16 + +// maximum size of a savegame description + +#define SAVESTRINGSIZE 24 + +// temporary filename to use while saving. + +char *P_TempSaveGameFile(void); + +// filename to use for a savegame slot + +char *P_SaveGameFile(int slot); + +// Savegame file header read/write functions + +boolean P_ReadSaveGameHeader(void); +void P_WriteSaveGameHeader(char *description); + +// Savegame end-of-file read/write functions + +boolean P_ReadSaveGameEOF(void); +void P_WriteSaveGameEOF(void); + +// Persistent storage/archiving. +// These are the load / save game routines. +void P_ArchivePlayers (void); +void P_UnArchivePlayers (void); +void P_ArchiveWorld (void); +void P_UnArchiveWorld (void); +void P_ArchiveThinkers (void); +void P_UnArchiveThinkers (void); +void P_ArchiveSpecials (void); +void P_UnArchiveSpecials (void); + +extern FILE *save_stream; +extern boolean savegame_error; + + +#endif diff --git a/games/NXDoom/src/doom/p_setup.c b/games/NXDoom/src/doom/p_setup.c new file mode 100644 index 00000000000..fbb1a180d53 --- /dev/null +++ b/games/NXDoom/src/doom/p_setup.c @@ -0,0 +1,833 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Do all the WAD I/O, get map description, +// set up initial state and misc. LUTs. +// + + + +#include +#include + +#include "z_zone.h" + +#include "deh_main.h" +#include "i_swap.h" +#include "m_argv.h" +#include "m_bbox.h" + +#include "g_game.h" + +#include "i_system.h" +#include "w_wad.h" + +#include "doomdef.h" +#include "p_local.h" +#include "p_rejectpad.h" + +#include "s_sound.h" + +#include "doomstat.h" + + +void P_SpawnMapThing (mapthing_t* mthing); + + +// +// MAP related Lookup tables. +// Store VERTEXES, LINEDEFS, SIDEDEFS, etc. +// +int numvertexes; +vertex_t* vertexes; + +int numsegs; +seg_t* segs; + +int numsectors; +sector_t* sectors; + +int numsubsectors; +subsector_t* subsectors; + +int numnodes; +node_t* nodes; + +int numlines; +line_t* lines; + +int numsides; +side_t* sides; + +static int totallines; + +// BLOCKMAP +// Created from axis aligned bounding box +// of the map, a rectangular array of +// blocks of size ... +// Used to speed up collision detection +// by spatial subdivision in 2D. +// +// Blockmap size. +int bmapwidth; +int bmapheight; // size in mapblocks +short* blockmap; // int for larger maps +// offsets in blockmap are from here +short* blockmaplump; +// origin of block map +fixed_t bmaporgx; +fixed_t bmaporgy; +// for thing chains +mobj_t** blocklinks; + + +// REJECT +// For fast sight rejection. +// Speeds up enemy AI by skipping detailed +// LineOf Sight calculation. +// Without special effect, this could be +// used as a PVS lookup as well. +// +byte* rejectmatrix; + + +// Maintain single and multi player starting spots. +#define MAX_DEATHMATCH_STARTS 10 + +mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS]; +mapthing_t* deathmatch_p; +mapthing_t playerstarts[MAXPLAYERS]; +boolean playerstartsingame[MAXPLAYERS]; + + + + + +// +// P_LoadVertexes +// +void P_LoadVertexes (int lump) +{ + byte* data; + int i; + mapvertex_t* ml; + vertex_t* li; + + // Determine number of lumps: + // total lump length / vertex record length. + numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t); + + // Allocate zone memory for buffer. + vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0); + + // Load data into cache. + data = W_CacheLumpNum (lump, PU_STATIC); + + ml = (mapvertex_t *)data; + li = vertexes; + + // Copy and convert vertex coordinates, + // internal representation as fixed. + for (i=0 ; ix = SHORT(ml->x)<y = SHORT(ml->y)<v1 = &vertexes[SHORT(ml->v1)]; + li->v2 = &vertexes[SHORT(ml->v2)]; + + li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + side = SHORT(ml->side); + + // e6y: check for wrong indexes + if ((unsigned)ldef->sidenum[side] >= (unsigned)numsides) + { + I_Error("P_LoadSegs: linedef %d for seg %d references a non-existent sidedef %d", + linedef, i, (unsigned)ldef->sidenum[side]); + } + + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; + + if (ldef-> flags & ML_TWOSIDED) + { + sidenum = ldef->sidenum[side ^ 1]; + + // If the sidenum is out of range, this may be a "glass hack" + // impassible window. Point at side #0 (this may not be + // the correct Vanilla behavior; however, it seems to work for + // OTTAWAU.WAD, which is the one place I've seen this trick + // used). + + if (sidenum < 0 || sidenum >= numsides) + { + li->backsector = GetSectorAtNullAddress(); + } + else + { + li->backsector = sides[sidenum].sector; + } + } + else + { + li->backsector = 0; + } + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadSubsectors +// +void P_LoadSubsectors (int lump) +{ + byte* data; + int i; + mapsubsector_t* ms; + subsector_t* ss; + + numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t); + subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0); + data = W_CacheLumpNum (lump,PU_STATIC); + + ms = (mapsubsector_t *)data; + memset (subsectors,0, numsubsectors*sizeof(subsector_t)); + ss = subsectors; + + for (i=0 ; inumlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); + } + + W_ReleaseLumpNum(lump); +} + + + +// +// P_LoadSectors +// +void P_LoadSectors (int lump) +{ + byte* data; + int i; + mapsector_t* ms; + sector_t* ss; + + numsectors = W_LumpLength (lump) / sizeof(mapsector_t); + sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0); + memset (sectors, 0, numsectors*sizeof(sector_t)); + data = W_CacheLumpNum (lump,PU_STATIC); + + ms = (mapsector_t *)data; + ss = sectors; + for (i=0 ; ifloorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = R_FlatNumForName(ms->floorpic); + ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); + ss->lightlevel = SHORT(ms->lightlevel); + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + ss->thinglist = NULL; + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadNodes +// +void P_LoadNodes (int lump) +{ + byte* data; + int i; + int j; + int k; + mapnode_t* mn; + node_t* no; + + numnodes = W_LumpLength (lump) / sizeof(mapnode_t); + nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0); + data = W_CacheLumpNum (lump,PU_STATIC); + + mn = (mapnode_t *)data; + no = nodes; + + for (i=0 ; ix = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); + for (k=0 ; k<4 ; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k])<type)) + { + case 68: // Arachnotron + case 64: // Archvile + case 88: // Boss Brain + case 89: // Boss Shooter + case 69: // Hell Knight + case 67: // Mancubus + case 71: // Pain Elemental + case 65: // Former Human Commando + case 66: // Revenant + case 84: // Wolf SS + spawn = false; + break; + } + } + if (spawn == false) + break; + + // Do spawn all other stuff. + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + spawnthing.options = SHORT(mt->options); + + P_SpawnMapThing(&spawnthing); + } + + if (!deathmatch) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !playerstartsingame[i]) + { + I_Error("P_LoadThings: Player %d start missing (vanilla crashes here)", i + 1); + } + playerstartsingame[i] = false; + } + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadLineDefs +// Also counts secret lines for intermissions. +// +void P_LoadLineDefs (int lump) +{ + byte* data; + int i; + maplinedef_t* mld; + line_t* ld; + vertex_t* v1; + vertex_t* v2; + + numlines = W_LumpLength (lump) / sizeof(maplinedef_t); + lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0); + memset (lines, 0, numlines*sizeof(line_t)); + data = W_CacheLumpNum (lump,PU_STATIC); + + mld = (maplinedef_t *)data; + ld = lines; + for (i=0 ; iflags = SHORT(mld->flags); + ld->special = SHORT(mld->special); + ld->tag = SHORT(mld->tag); + v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; + v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else + { + if (FixedDiv (ld->dy , ld->dx) > 0) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + } + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + + if (ld->sidenum[0] != -1) + ld->frontsector = sides[ld->sidenum[0]].sector; + else + ld->frontsector = 0; + + if (ld->sidenum[1] != -1) + ld->backsector = sides[ld->sidenum[1]].sector; + else + ld->backsector = 0; + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadSideDefs +// +void P_LoadSideDefs (int lump) +{ + byte* data; + int i; + mapsidedef_t* msd; + side_t* sd; + + numsides = W_LumpLength (lump) / sizeof(mapsidedef_t); + sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0); + memset (sides, 0, numsides*sizeof(side_t)); + data = W_CacheLumpNum (lump,PU_STATIC); + + msd = (mapsidedef_t *)data; + sd = sides; + for (i=0 ; itextureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<toptexture = R_TextureNumForName(msd->toptexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->sector = §ors[SHORT(msd->sector)]; + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadBlockMap +// +void P_LoadBlockMap (int lump) +{ + int i; + int count; + int lumplen; + + lumplen = W_LumpLength(lump); + count = lumplen / 2; + + blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); + W_ReadLump(lump, blockmaplump); + blockmap = blockmaplump + 4; + + // Swap all short integers to native byte ordering. + + for (i=0; ifirstline]; + ss->sector = seg->sidedef->sector; + } + + // count number of lines in each sector + li = lines; + totallines = 0; + for (i=0 ; ifrontsector->linecount++; + + if (li->backsector && li->backsector != li->frontsector) + { + li->backsector->linecount++; + totallines++; + } + } + + // build line tables for each sector + linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0); + + for (i=0; ifrontsector != NULL) + { + sector = li->frontsector; + + sector->lines[sector->linecount] = li; + ++sector->linecount; + } + + if (li->backsector != NULL && li->frontsector != li->backsector) + { + sector = li->backsector; + + sector->lines[sector->linecount] = li; + ++sector->linecount; + } + } + + // Generate bounding boxes for sectors + + sector = sectors; + for (i=0 ; ilinecount; j++) + { + li = sector->lines[j]; + + M_AddToBox (bbox, li->v1->x, li->v1->y); + M_AddToBox (bbox, li->v2->x, li->v2->y); + } + + // set the degenmobj_t to the middle of the bounding box + sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2; + sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2; + + // adjust bounding box to map blocks + block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; + block = block >= bmapheight ? bmapheight-1 : block; + sector->blockbox[BOXTOP]=block; + + block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXBOTTOM]=block; + + block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; + block = block >= bmapwidth ? bmapwidth-1 : block; + sector->blockbox[BOXRIGHT]=block; + + block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXLEFT]=block; + } + +} + + +static void P_LoadReject(int lumpnum) +{ + int minlength; + int lumplen; + + // Calculate the size that the REJECT lump *should* be. + + minlength = (numsectors * numsectors + 7) / 8; + + // If the lump meets the minimum length, it can be loaded directly. + // Otherwise, we need to allocate a buffer of the correct size + // and pad it with appropriate data. + + lumplen = W_LumpLength(lumpnum); + + if (lumplen >= minlength) + { + rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + else + { + rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); + W_ReadLump(lumpnum, rejectmatrix); + + PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); + } +} + +// pointer to the current map lump info struct +lumpinfo_t *maplumpinfo; + +// +// P_SetupLevel +// +void +P_SetupLevel +( int episode, + int map, + int playermask, + skill_t skill) +{ + int i; + char lumpname[9]; + int lumpnum; + + totalkills = totalitems = totalsecret = wminfo.maxfrags = 0; + wminfo.partime = 180; + for (i=0 ; id.line; + + // + // crosses a two sided line + // + P_LineOpening(li); + + if (openbottom >= opentop) // quick test for totally closed doors + return false; // stop + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - sightzstart, in->frac); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - sightzstart, in->frac); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // keep going +} + + +// +// P_DivlineSide +// Returns side 0 (front), 1 (back), or 2 (on). +// +int +P_DivlineSide +( fixed_t x, + fixed_t y, + divline_t* node ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!node->dx) + { + if (x==node->x) + return 2; + + if (x <= node->x) + return node->dy > 0; + + return node->dy < 0; + } + + if (!node->dy) + { + if (x==node->y) + return 2; + + if (y <= node->y) + return node->dx < 0; + + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + + left = (node->dy>>FRACBITS) * (dx>>FRACBITS); + right = (dy>>FRACBITS) * (node->dx>>FRACBITS); + + if (right < left) + return 0; // front side + + if (left == right) + return 2; + return 1; // back side +} + + +// +// P_InterceptVector2 +// Returns the fractional intercept point +// along the first divline. +// This is only called by the addthings and addlines traversers. +// +fixed_t +P_InterceptVector2 +( divline_t* v2, + divline_t* v1 ) +{ + fixed_t frac; + fixed_t num; + fixed_t den; + + den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); + + if (den == 0) + return 0; + // I_Error ("P_InterceptVector: parallel"); + + num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + + FixedMul ( (v2->y - v1->y)>>8 , v1->dx); + frac = FixedDiv (num , den); + + return frac; +} + +// +// P_CrossSubsector +// Returns true +// if strace crosses the given subsector successfully. +// +boolean P_CrossSubsector (int num) +{ + seg_t* seg; + line_t* line; + int s1; + int s2; + int count; + subsector_t* sub; + sector_t* front; + sector_t* back; + fixed_t opentop; + fixed_t openbottom; + divline_t divl; + vertex_t* v1; + vertex_t* v2; + fixed_t frac; + fixed_t slope; + +#ifdef RANGECHECK + if (num>=numsubsectors) + I_Error ("P_CrossSubsector: ss %i with numss = %i", + num, + numsubsectors); +#endif + + sub = &subsectors[num]; + + // check lines + count = sub->numlines; + seg = &segs[sub->firstline]; + + for ( ; count ; seg++, count--) + { + line = seg->linedef; + + // allready checked other side? + if (line->validcount == validcount) + continue; + + line->validcount = validcount; + + v1 = line->v1; + v2 = line->v2; + s1 = P_DivlineSide (v1->x,v1->y, &strace); + s2 = P_DivlineSide (v2->x, v2->y, &strace); + + // line isn't crossed? + if (s1 == s2) + continue; + + divl.x = v1->x; + divl.y = v1->y; + divl.dx = v2->x - v1->x; + divl.dy = v2->y - v1->y; + s1 = P_DivlineSide (strace.x, strace.y, &divl); + s2 = P_DivlineSide (t2x, t2y, &divl); + + // line isn't crossed? + if (s1 == s2) + continue; + + // Backsector may be NULL if this is an "impassible + // glass" hack line. + + if (line->backsector == NULL) + { + return false; + } + + // stop because it is not two sided anyway + // might do this after updating validcount? + if ( !(line->flags & ML_TWOSIDED) ) + return false; + + // crosses a two sided line + front = seg->frontsector; + back = seg->backsector; + + // no wall to block sight with? + if (front->floorheight == back->floorheight + && front->ceilingheight == back->ceilingheight) + continue; + + // possible occluder + // because of ceiling height differences + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + + // because of ceiling height differences + if (front->floorheight > back->floorheight) + openbottom = front->floorheight; + else + openbottom = back->floorheight; + + // quick test for totally closed doors + if (openbottom >= opentop) + return false; // stop + + frac = P_InterceptVector2 (&strace, &divl); + + if (front->floorheight != back->floorheight) + { + slope = FixedDiv (openbottom - sightzstart , frac); + if (slope > bottomslope) + bottomslope = slope; + } + + if (front->ceilingheight != back->ceilingheight) + { + slope = FixedDiv (opentop - sightzstart , frac); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + } + // passed the subsector ok + return true; +} + + + +// +// P_CrossBSPNode +// Returns true +// if strace crosses the given node successfully. +// +boolean P_CrossBSPNode (int bspnum) +{ + node_t* bsp; + int side; + + if (bspnum & NF_SUBSECTOR) + { + if (bspnum == -1) + return P_CrossSubsector (0); + else + return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); + } + + bsp = &nodes[bspnum]; + + // decide which side the start point is on + side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp); + if (side == 2) + side = 0; // an "on" should cross both sides + + // cross the starting side + if (!P_CrossBSPNode (bsp->children[side]) ) + return false; + + // the partition plane is crossed here + if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp)) + { + // the line doesn't touch the other side + return true; + } + + // cross the ending side + return P_CrossBSPNode (bsp->children[side^1]); +} + + +// +// P_CheckSight +// Returns true +// if a straight line between t1 and t2 is unobstructed. +// Uses REJECT. +// +boolean +P_CheckSight +( mobj_t* t1, + mobj_t* t2 ) +{ + int s1; + int s2; + int pnum; + int bytenum; + int bitnum; + + // First check for trivial rejection. + + // Determine subsector entries in REJECT table. + s1 = (t1->subsector->sector - sectors); + s2 = (t2->subsector->sector - sectors); + pnum = s1*numsectors + s2; + bytenum = pnum>>3; + bitnum = 1 << (pnum&7); + + // Check in REJECT table. + if (rejectmatrix[bytenum]&bitnum) + { + sightcounts[0]++; + + // can't possibly be connected + return false; + } + + // An unobstructed LOS is possible. + // Now look from eyes of t1 to any part of t2. + sightcounts[1]++; + + validcount++; + + sightzstart = t1->z + t1->height - (t1->height>>2); + topslope = (t2->z+t2->height) - sightzstart; + bottomslope = (t2->z) - sightzstart; + + if (gameversion <= exe_doom_1_2) + { + return P_PathTraverse(t1->x, t1->y, t2->x, t2->y, + PT_EARLYOUT | PT_ADDLINES, PTR_SightTraverse); + } + + strace.x = t1->x; + strace.y = t1->y; + t2x = t2->x; + t2y = t2->y; + strace.dx = t2->x - t1->x; + strace.dy = t2->y - t1->y; + + // the head node is the last node output + return P_CrossBSPNode (numnodes-1); +} + + diff --git a/games/NXDoom/src/doom/p_spec.c b/games/NXDoom/src/doom/p_spec.c new file mode 100644 index 00000000000..8d890ce2e64 --- /dev/null +++ b/games/NXDoom/src/doom/p_spec.c @@ -0,0 +1,1519 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Implements special effects: +// Texture animation, height or lighting changes +// according to adjacent sectors, respective +// utility functions, etc. +// Line Tag handling. Line and Sector triggers. +// + + +#include + +#include "doomdef.h" +#include "doomstat.h" + +#include "deh_main.h" +#include "i_system.h" +#include "z_zone.h" +#include "m_argv.h" +#include "m_misc.h" +#include "m_random.h" +#include "w_wad.h" + +#include "r_local.h" +#include "p_local.h" + +#include "g_game.h" + +#include "s_sound.h" + +// State. +#include "r_state.h" + +// Data. +#include "sounds.h" + + +// +// Animating textures and planes +// There is another anim_t used in wi_stuff, unrelated. +// +typedef struct +{ + boolean istexture; + int picnum; + int basepic; + int numpics; + int speed; + +} anim_t; + +// +// source animation definition +// +typedef struct +{ + int istexture; // if false, it is a flat + char endname[9]; + char startname[9]; + int speed; +} animdef_t; + + + +#define MAXANIMS 32 + + +// +// P_InitPicAnims +// + +// Floor/ceiling animation sequences, +// defined by first and last frame, +// i.e. the flat (64x64 tile) name to +// be used. +// The full animation sequence is given +// using all the flats between the start +// and end entry, in the order found in +// the WAD file. +// +animdef_t animdefs[] = +{ + {false, "NUKAGE3", "NUKAGE1", 8}, + {false, "FWATER4", "FWATER1", 8}, + {false, "SWATER4", "SWATER1", 8}, + {false, "LAVA4", "LAVA1", 8}, + {false, "BLOOD3", "BLOOD1", 8}, + + // DOOM II flat animations. + {false, "RROCK08", "RROCK05", 8}, + {false, "SLIME04", "SLIME01", 8}, + {false, "SLIME08", "SLIME05", 8}, + {false, "SLIME12", "SLIME09", 8}, + + {true, "BLODGR4", "BLODGR1", 8}, + {true, "SLADRIP3", "SLADRIP1", 8}, + + {true, "BLODRIP4", "BLODRIP1", 8}, + {true, "FIREWALL", "FIREWALA", 8}, + {true, "GSTFONT3", "GSTFONT1", 8}, + {true, "FIRELAVA", "FIRELAV3", 8}, + {true, "FIREMAG3", "FIREMAG1", 8}, + {true, "FIREBLU2", "FIREBLU1", 8}, + {true, "ROCKRED3", "ROCKRED1", 8}, + + {true, "BFALL4", "BFALL1", 8}, + {true, "SFALL4", "SFALL1", 8}, + {true, "WFALL4", "WFALL1", 8}, + {true, "DBRAIN4", "DBRAIN1", 8}, + + {-1, "", "", 0}, +}; + +anim_t anims[MAXANIMS]; +anim_t* lastanim; + + +// +// Animating line specials +// +#define MAXLINEANIMS 64 +// version <= 1.2 did not have a limit and could handle up to 66 scrolling +// linedefs before displaying adverse effects. All other versions have a limit +// of 64. +#define MAXLINEANIMS1_2 66 + +short numlinespecials; +line_t *linespeciallist[MAXLINEANIMS1_2]; + + + +void P_InitPicAnims (void) +{ + int i; + + + // Init animation + lastanim = anims; + for (i=0 ; animdefs[i].istexture != -1 ; i++) + { + const char *startname, *endname; + + startname = DEH_String(animdefs[i].startname); + endname = DEH_String(animdefs[i].endname); + + if (animdefs[i].istexture) + { + // different episode ? + if (R_CheckTextureNumForName(startname) == -1) + continue; + + lastanim->picnum = R_TextureNumForName(endname); + lastanim->basepic = R_TextureNumForName(startname); + } + else + { + if (W_CheckNumForName(startname) == -1) + continue; + + lastanim->picnum = R_FlatNumForName(endname); + lastanim->basepic = R_FlatNumForName(startname); + } + + lastanim->istexture = animdefs[i].istexture; + lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; + + if (lastanim->numpics < 2) + I_Error ("P_InitPicAnims: bad cycle from %s to %s", + startname, endname); + + lastanim->speed = animdefs[i].speed; + lastanim++; + } + +} + + + +// +// UTILITIES +// + + + +// +// getSide() +// Will return a side_t* +// given the number of the current sector, +// the line number, and the side (0/1) that you want. +// +side_t* +getSide +( int currentSector, + int line, + int side ) +{ + return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; +} + + +// +// getSector() +// Will return a sector_t* +// given the number of the current sector, +// the line number and the side (0/1) that you want. +// +sector_t* +getSector +( int currentSector, + int line, + int side ) +{ + return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; +} + + +// +// twoSided() +// Given the sector number and the line number, +// it will tell you whether the line is two-sided or not. +// +int +twoSided +( int sector, + int line ) +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} + + + + +// +// getNextSector() +// Return sector_t * of sector next to current. +// NULL if not two-sided line +// +sector_t* +getNextSector +( line_t* line, + sector_t* sec ) +{ + if (!(line->flags & ML_TWOSIDED)) + return NULL; + + if (line->frontsector == sec) + return line->backsector; + + return line->frontsector; +} + + + +// +// P_FindLowestFloorSurrounding() +// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +fixed_t P_FindLowestFloorSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t floor = sec->floorheight; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight < floor) + floor = other->floorheight; + } + return floor; +} + + + +// +// P_FindHighestFloorSurrounding() +// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +fixed_t P_FindHighestFloorSurrounding(sector_t *sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t floor = -500*FRACUNIT; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight > floor) + floor = other->floorheight; + } + return floor; +} + + + +// +// P_FindNextHighestFloor +// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS +// Note: this should be doable w/o a fixed array. + +// Thanks to entryway for the Vanilla overflow emulation. + +// 20 adjoining sectors max! +#define MAX_ADJOINING_SECTORS 20 + +fixed_t +P_FindNextHighestFloor +( sector_t* sec, + int currentheight ) +{ + int i; + int h; + int min; + line_t* check; + sector_t* other; + fixed_t height = currentheight; + fixed_t heightlist[MAX_ADJOINING_SECTORS + 2]; + + for (i=0, h=0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight > height) + { + // Emulation of memory (stack) overflow + if (h == MAX_ADJOINING_SECTORS + 1) + { + height = other->floorheight; + } + else if (h == MAX_ADJOINING_SECTORS + 2) + { + // Fatal overflow: game crashes at 22 sectors + I_Error("Sector with more than 22 adjoining sectors. " + "Vanilla will crash here"); + } + + heightlist[h++] = other->floorheight; + } + } + + // Find lowest height in list + if (!h) + { + return currentheight; + } + + min = heightlist[0]; + + // Range checking? + for (i = 1; i < h; i++) + { + if (heightlist[i] < min) + { + min = heightlist[i]; + } + } + + return min; +} + +// +// FIND LOWEST CEILING IN THE SURROUNDING SECTORS +// +fixed_t +P_FindLowestCeilingSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t height = INT_MAX; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->ceilingheight < height) + height = other->ceilingheight; + } + return height; +} + + +// +// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS +// +fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t height = 0; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->ceilingheight > height) + height = other->ceilingheight; + } + return height; +} + + + +// +// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO +// +int +P_FindSectorFromLineTag +( line_t* line, + int start ) +{ + int i; + + for (i=start+1;itag) + return i; + + return -1; +} + + + + +// +// Find minimum light from an adjacent sector +// +int +P_FindMinSurroundingLight +( sector_t* sector, + int max ) +{ + int i; + int min; + line_t* line; + sector_t* check; + + min = max; + for (i=0 ; i < sector->linecount ; i++) + { + line = sector->lines[i]; + check = getNextSector(line,sector); + + if (!check) + continue; + + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} + + + +// +// EVENTS +// Events are operations triggered by using, crossing, +// or shooting special lines, or by timed thinkers. +// + +// +// P_CrossSpecialLine - TRIGGER +// Called every time a thing origin is about +// to cross a line with a non 0 special. +// +void +P_CrossSpecialLine +( int linenum, + int side, + mobj_t* thing ) +{ + line_t* line; + int ok; + + line = &lines[linenum]; + + if (gameversion <= exe_doom_1_2) + { + if (line->special > 98 && line->special != 104) + { + return; + } + } + else + { + // Triggers that other things can activate + if (!thing->player) + { + // Things that should NOT trigger specials... + switch(thing->type) + { + case MT_ROCKET: + case MT_PLASMA: + case MT_BFG: + case MT_TROOPSHOT: + case MT_HEADSHOT: + case MT_BRUISERSHOT: + return; + + default: break; + } + } + } + + if (!thing->player) + { + ok = 0; + switch(line->special) + { + case 39: // TELEPORT TRIGGER + case 97: // TELEPORT RETRIGGER + case 125: // TELEPORT MONSTERONLY TRIGGER + case 126: // TELEPORT MONSTERONLY RETRIGGER + case 4: // RAISE DOOR + case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER + case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER + ok = 1; + break; + } + if (!ok) + return; + } + + + // Note: could use some const's here. + switch (line->special) + { + // TRIGGERS. + // All from here to RETRIGGERS. + case 2: + // Open Door + EV_DoDoor(line,vld_open); + line->special = 0; + break; + + case 3: + // Close Door + EV_DoDoor(line,vld_close); + line->special = 0; + break; + + case 4: + // Raise Door + EV_DoDoor(line,vld_normal); + line->special = 0; + break; + + case 5: + // Raise Floor + EV_DoFloor(line,raiseFloor); + line->special = 0; + break; + + case 6: + // Fast Ceiling Crush & Raise + EV_DoCeiling(line,fastCrushAndRaise); + line->special = 0; + break; + + case 8: + // Build Stairs + EV_BuildStairs(line,build8); + line->special = 0; + break; + + case 10: + // PlatDownWaitUp + EV_DoPlat(line,downWaitUpStay,0); + line->special = 0; + break; + + case 12: + // Light Turn On - brightest near + EV_LightTurnOn(line,0); + line->special = 0; + break; + + case 13: + // Light Turn On 255 + EV_LightTurnOn(line,255); + line->special = 0; + break; + + case 16: + // Close Door 30 + EV_DoDoor(line,vld_close30ThenOpen); + line->special = 0; + break; + + case 17: + // Start Light Strobing + EV_StartLightStrobing(line); + line->special = 0; + break; + + case 19: + // Lower Floor + EV_DoFloor(line,lowerFloor); + line->special = 0; + break; + + case 22: + // Raise floor to nearest height and change texture + EV_DoPlat(line,raiseToNearestAndChange,0); + line->special = 0; + break; + + case 25: + // Ceiling Crush and Raise + EV_DoCeiling(line,crushAndRaise); + line->special = 0; + break; + + case 30: + // Raise floor to shortest texture height + // on either side of lines. + EV_DoFloor(line,raiseToTexture); + line->special = 0; + break; + + case 35: + // Lights Very Dark + EV_LightTurnOn(line,35); + line->special = 0; + break; + + case 36: + // Lower Floor (TURBO) + EV_DoFloor(line,turboLower); + line->special = 0; + break; + + case 37: + // LowerAndChange + EV_DoFloor(line,lowerAndChange); + line->special = 0; + break; + + case 38: + // Lower Floor To Lowest + EV_DoFloor( line, lowerFloorToLowest ); + line->special = 0; + break; + + case 39: + // TELEPORT! + EV_Teleport( line, side, thing ); + line->special = 0; + break; + + case 40: + // RaiseCeilingLowerFloor + EV_DoCeiling( line, raiseToHighest ); + EV_DoFloor( line, lowerFloorToLowest ); + line->special = 0; + break; + + case 44: + // Ceiling Crush + EV_DoCeiling( line, lowerAndCrush ); + line->special = 0; + break; + + case 52: + // EXIT! + G_ExitLevel (); + break; + + case 53: + // Perpetual Platform Raise + EV_DoPlat(line,perpetualRaise,0); + line->special = 0; + break; + + case 54: + // Platform Stop + EV_StopPlat(line); + line->special = 0; + break; + + case 56: + // Raise Floor Crush + EV_DoFloor(line,raiseFloorCrush); + line->special = 0; + break; + + case 57: + // Ceiling Crush Stop + EV_CeilingCrushStop(line); + line->special = 0; + break; + + case 58: + // Raise Floor 24 + EV_DoFloor(line,raiseFloor24); + line->special = 0; + break; + + case 59: + // Raise Floor 24 And Change + EV_DoFloor(line,raiseFloor24AndChange); + line->special = 0; + break; + + case 104: + // Turn lights off in sector(tag) + EV_TurnTagLightsOff(line); + line->special = 0; + break; + + case 108: + // Blazing Door Raise (faster than TURBO!) + EV_DoDoor (line,vld_blazeRaise); + line->special = 0; + break; + + case 109: + // Blazing Door Open (faster than TURBO!) + EV_DoDoor (line,vld_blazeOpen); + line->special = 0; + break; + + case 100: + // Build Stairs Turbo 16 + EV_BuildStairs(line,turbo16); + line->special = 0; + break; + + case 110: + // Blazing Door Close (faster than TURBO!) + EV_DoDoor (line,vld_blazeClose); + line->special = 0; + break; + + case 119: + // Raise floor to nearest surr. floor + EV_DoFloor(line,raiseFloorToNearest); + line->special = 0; + break; + + case 121: + // Blazing PlatDownWaitUpStay + EV_DoPlat(line,blazeDWUS,0); + line->special = 0; + break; + + case 124: + // Secret EXIT + G_SecretExitLevel (); + break; + + case 125: + // TELEPORT MonsterONLY + if (!thing->player) + { + EV_Teleport( line, side, thing ); + line->special = 0; + } + break; + + case 130: + // Raise Floor Turbo + EV_DoFloor(line,raiseFloorTurbo); + line->special = 0; + break; + + case 141: + // Silent Ceiling Crush & Raise + EV_DoCeiling(line,silentCrushAndRaise); + line->special = 0; + break; + + // RETRIGGERS. All from here till end. + case 72: + // Ceiling Crush + EV_DoCeiling( line, lowerAndCrush ); + break; + + case 73: + // Ceiling Crush and Raise + EV_DoCeiling(line,crushAndRaise); + break; + + case 74: + // Ceiling Crush Stop + EV_CeilingCrushStop(line); + break; + + case 75: + // Close Door + EV_DoDoor(line,vld_close); + break; + + case 76: + // Close Door 30 + EV_DoDoor(line,vld_close30ThenOpen); + break; + + case 77: + // Fast Ceiling Crush & Raise + EV_DoCeiling(line,fastCrushAndRaise); + break; + + case 79: + // Lights Very Dark + EV_LightTurnOn(line,35); + break; + + case 80: + // Light Turn On - brightest near + EV_LightTurnOn(line,0); + break; + + case 81: + // Light Turn On 255 + EV_LightTurnOn(line,255); + break; + + case 82: + // Lower Floor To Lowest + EV_DoFloor( line, lowerFloorToLowest ); + break; + + case 83: + // Lower Floor + EV_DoFloor(line,lowerFloor); + break; + + case 84: + // LowerAndChange + EV_DoFloor(line,lowerAndChange); + break; + + case 86: + // Open Door + EV_DoDoor(line,vld_open); + break; + + case 87: + // Perpetual Platform Raise + EV_DoPlat(line,perpetualRaise,0); + break; + + case 88: + // PlatDownWaitUp + EV_DoPlat(line,downWaitUpStay,0); + break; + + case 89: + // Platform Stop + EV_StopPlat(line); + break; + + case 90: + // Raise Door + EV_DoDoor(line,vld_normal); + break; + + case 91: + // Raise Floor + EV_DoFloor(line,raiseFloor); + break; + + case 92: + // Raise Floor 24 + EV_DoFloor(line,raiseFloor24); + break; + + case 93: + // Raise Floor 24 And Change + EV_DoFloor(line,raiseFloor24AndChange); + break; + + case 94: + // Raise Floor Crush + EV_DoFloor(line,raiseFloorCrush); + break; + + case 95: + // Raise floor to nearest height + // and change texture. + EV_DoPlat(line,raiseToNearestAndChange,0); + break; + + case 96: + // Raise floor to shortest texture height + // on either side of lines. + EV_DoFloor(line,raiseToTexture); + break; + + case 97: + // TELEPORT! + EV_Teleport( line, side, thing ); + break; + + case 98: + // Lower Floor (TURBO) + EV_DoFloor(line,turboLower); + break; + + case 105: + // Blazing Door Raise (faster than TURBO!) + EV_DoDoor (line,vld_blazeRaise); + break; + + case 106: + // Blazing Door Open (faster than TURBO!) + EV_DoDoor (line,vld_blazeOpen); + break; + + case 107: + // Blazing Door Close (faster than TURBO!) + EV_DoDoor (line,vld_blazeClose); + break; + + case 120: + // Blazing PlatDownWaitUpStay. + EV_DoPlat(line,blazeDWUS,0); + break; + + case 126: + // TELEPORT MonsterONLY. + if (!thing->player) + EV_Teleport( line, side, thing ); + break; + + case 128: + // Raise To Nearest Floor + EV_DoFloor(line,raiseFloorToNearest); + break; + + case 129: + // Raise Floor Turbo + EV_DoFloor(line,raiseFloorTurbo); + break; + } +} + + + +// +// P_ShootSpecialLine - IMPACT SPECIALS +// Called when a thing shoots a special line. +// +void +P_ShootSpecialLine +( mobj_t* thing, + line_t* line ) +{ + int ok; + + // Impacts that other things can activate. + if (!thing->player) + { + ok = 0; + switch(line->special) + { + case 46: + // OPEN DOOR IMPACT + ok = 1; + break; + } + if (!ok) + return; + } + + switch(line->special) + { + case 24: + // RAISE FLOOR + EV_DoFloor(line,raiseFloor); + P_ChangeSwitchTexture(line,0); + break; + + case 46: + // OPEN DOOR + EV_DoDoor(line,vld_open); + P_ChangeSwitchTexture(line,1); + break; + + case 47: + // RAISE FLOOR NEAR AND CHANGE + EV_DoPlat(line,raiseToNearestAndChange,0); + P_ChangeSwitchTexture(line,0); + break; + } +} + + + +// +// P_PlayerInSpecialSector +// Called every tic frame +// that the player origin is in a special sector +// +void P_PlayerInSpecialSector (player_t* player) +{ + sector_t* sector; + + sector = player->mo->subsector->sector; + + // Falling, not all the way down yet? + if (player->mo->z != sector->floorheight) + return; + + // Has hitten ground. + switch (sector->special) + { + case 5: + // HELLSLIME DAMAGE + if (!player->powers[pw_ironfeet]) + if (!(leveltime&0x1f)) + P_DamageMobj (player->mo, NULL, NULL, 10); + break; + + case 7: + // NUKAGE DAMAGE + if (!player->powers[pw_ironfeet]) + if (!(leveltime&0x1f)) + P_DamageMobj (player->mo, NULL, NULL, 5); + break; + + case 16: + // SUPER HELLSLIME DAMAGE + case 4: + // STROBE HURT + if (!player->powers[pw_ironfeet] + || (P_Random()<5) ) + { + if (!(leveltime&0x1f)) + P_DamageMobj (player->mo, NULL, NULL, 20); + } + break; + + case 9: + // SECRET SECTOR + player->secretcount++; + sector->special = 0; + break; + + case 11: + // EXIT SUPER DAMAGE! (for E1M8 finale) + player->cheats &= ~CF_GODMODE; + + if (!(leveltime&0x1f)) + P_DamageMobj (player->mo, NULL, NULL, 20); + + if (player->health <= 10) + G_ExitLevel(); + break; + + default: + I_Error ("P_PlayerInSpecialSector: " + "unknown special %i", + sector->special); + break; + }; +} + + + + +// +// P_UpdateSpecials +// Animate planes, scroll walls, etc. +// +boolean levelTimer; +int levelTimeCount; + +void P_UpdateSpecials (void) +{ + anim_t* anim; + int pic; + int i; + line_t* line; + + + // LEVEL TIMER + if (levelTimer == true) + { + levelTimeCount--; + if (!levelTimeCount) + G_ExitLevel(); + } + + // ANIMATE FLATS AND TEXTURES GLOBALLY + for (anim = anims ; anim < lastanim ; anim++) + { + for (i=anim->basepic ; ibasepic+anim->numpics ; i++) + { + pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); + if (anim->istexture) + texturetranslation[i] = pic; + else + flattranslation[i] = pic; + } + } + + + // ANIMATE LINE SPECIALS + for (i = 0; i < numlinespecials; i++) + { + line = linespeciallist[i]; + switch(line->special) + { + case 48: + // EFFECT FIRSTCOL SCROLL + + sides[line->sidenum[0]].textureoffset += FRACUNIT; + break; + } + } + + + // DO BUTTONS + for (i = 0; i < MAXBUTTONS; i++) + if (buttonlist[i].btimer) + { + buttonlist[i].btimer--; + if (!buttonlist[i].btimer) + { + switch(buttonlist[i].where) + { + case top: + sides[buttonlist[i].line->sidenum[0]].toptexture = + buttonlist[i].btexture; + break; + + case middle: + sides[buttonlist[i].line->sidenum[0]].midtexture = + buttonlist[i].btexture; + break; + + case bottom: + sides[buttonlist[i].line->sidenum[0]].bottomtexture = + buttonlist[i].btexture; + break; + } + S_StartSound(&buttonlist[i].soundorg,sfx_swtchn); + memset(&buttonlist[i],0,sizeof(button_t)); + } + } +} + + +// +// Donut overrun emulation +// +// Derived from the code from PrBoom+. Thanks go to Andrey Budko (entryway) +// as usual :-) +// + +#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000 +#define DONUT_FLOORPIC_DEFAULT 0x16 + +static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic, + line_t *line, sector_t *pillar_sector) +{ + static int first = 1; + static int tmp_s3_floorheight; + static int tmp_s3_floorpic; + + if (first) + { + int p; + + // This is the first time we have had an overrun. + first = 0; + + // Default values + tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT; + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + + //! + // @category compat + // @arg + // + // Use the specified magic values when emulating behavior caused + // by memory overruns from improperly constructed donuts. + // In Vanilla Doom this can differ depending on the operating + // system. The default (if this option is not specified) is to + // emulate the behavior when running under Windows 98. + + p = M_CheckParmWithArgs("-donut", 2); + + if (p > 0) + { + // Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008 + // + // C:\>debug + // -d 0:0 + // + // DOS 6.22: + // 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) + // DOS 7.1: + // 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) + // Win98: + // 0000:0000 (00 00 00 00) 65 04 70 00-(16 00) + // DOSBox under XP: + // 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + + M_StrToInt(myargv[p + 1], &tmp_s3_floorheight); + M_StrToInt(myargv[p + 2], &tmp_s3_floorpic); + + if (tmp_s3_floorpic >= numflats) + { + fprintf(stderr, + "DonutOverrun: The second parameter for \"-donut\" " + "switch should be greater than 0 and less than number " + "of flats (%d). Using default value (%d) instead. \n", + numflats, DONUT_FLOORPIC_DEFAULT); + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + } + } + } + + /* + fprintf(stderr, + "Linedef: %d; Sector: %d; " + "New floor height: %d; New floor pic: %d\n", + line->iLineID, pillar_sector->iSectorID, + tmp_s3_floorheight >> 16, tmp_s3_floorpic); + */ + + *s3_floorheight = (fixed_t) tmp_s3_floorheight; + *s3_floorpic = (short) tmp_s3_floorpic; +} + + +// +// Special Stuff that can not be categorized +// +int EV_DoDonut(line_t* line) +{ + sector_t* s1; + sector_t* s2; + sector_t* s3; + int secnum; + int rtn; + int i; + floormove_t* floor; + fixed_t s3_floorheight; + short s3_floorpic; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + s1 = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (s1->specialdata) + continue; + + rtn = 1; + s2 = getNextSector(s1->lines[0],s1); + + // Vanilla Doom does not check if the linedef is one sided. The + // game does not crash, but reads invalid memory and causes the + // sector floor to move "down" to some unknown height. + // DOSbox prints a warning about an invalid memory access. + // + // I'm not sure exactly what invalid memory is being read. This + // isn't something that should be done, anyway. + // Just print a warning and return. + + if (s2 == NULL) + { + fprintf(stderr, + "EV_DoDonut: linedef had no second sidedef! " + "Unexpected behavior may occur in Vanilla Doom. \n"); + break; + } + + for (i = 0; i < s2->linecount; i++) + { + s3 = s2->lines[i]->backsector; + + if (s3 == s1) + continue; + + if (s3 == NULL) + { + // e6y + // s3 is NULL, so + // s3->floorheight is an int at 0000:0000 + // s3->floorpic is a short at 0000:0008 + // Trying to emulate + + fprintf(stderr, + "EV_DoDonut: WARNING: emulating buffer overrun due to " + "NULL back sector. " + "Unexpected behavior may occur in Vanilla Doom.\n"); + + DonutOverrun(&s3_floorheight, &s3_floorpic, line, s1); + } + else + { + s3_floorheight = s3->floorheight; + s3_floorpic = s3->floorpic; + } + + // Spawn rising slime + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s2->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = donutRaise; + floor->crush = false; + floor->direction = 1; + floor->sector = s2; + floor->speed = FLOORSPEED / 2; + floor->texture = s3_floorpic; + floor->newspecial = 0; + floor->floordestheight = s3_floorheight; + + // Spawn lowering donut-hole + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s1->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = lowerFloor; + floor->crush = false; + floor->direction = -1; + floor->sector = s1; + floor->speed = FLOORSPEED / 2; + floor->floordestheight = s3_floorheight; + break; + } + } + return rtn; +} + + + +// +// SPECIAL SPAWNING +// + +// +// P_SpawnSpecials +// After the map has been loaded, scan for specials +// that spawn thinkers +// + +static unsigned int NumScrollers() +{ + unsigned int i, scrollers = 0; + + for (i = 0; i < numlines; i++) + { + if (48 == lines[i].special) + { + scrollers++; + } + } + return scrollers; +} + +// Parses command line parameters. +void P_SpawnSpecials (void) +{ + sector_t* sector; + int i; + short maxlineanims = (gameversion <= exe_doom_1_2) ? MAXLINEANIMS1_2 + : MAXLINEANIMS; + + // See if -TIMER was specified. + + if (timelimit > 0 && deathmatch) + { + levelTimer = true; + levelTimeCount = timelimit * 60 * TICRATE; + } + else + { + levelTimer = false; + } + + // Init special SECTORs. + sector = sectors; + for (i=0 ; ispecial) + continue; + + switch (sector->special) + { + case 1: + // FLICKERING LIGHTS + P_SpawnLightFlash (sector); + break; + + case 2: + // STROBE FAST + P_SpawnStrobeFlash(sector,FASTDARK,0); + break; + + case 3: + // STROBE SLOW + P_SpawnStrobeFlash(sector,SLOWDARK,0); + break; + + case 4: + // STROBE FAST/DEATH SLIME + P_SpawnStrobeFlash(sector,FASTDARK,0); + sector->special = 4; + break; + + case 8: + // GLOWING LIGHT + P_SpawnGlowingLight(sector); + break; + case 9: + // SECRET SECTOR + totalsecret++; + break; + + case 10: + // DOOR CLOSE IN 30 SECONDS + P_SpawnDoorCloseIn30 (sector); + break; + + case 12: + // SYNC STROBE SLOW + P_SpawnStrobeFlash (sector, SLOWDARK, 1); + break; + + case 13: + // SYNC STROBE FAST + P_SpawnStrobeFlash (sector, FASTDARK, 1); + break; + + case 14: + // DOOR RAISE IN 5 MINUTES + P_SpawnDoorRaiseIn5Mins (sector, i); + break; + + case 17: + // first introduced in official v1.4 beta + if (gameversion > exe_doom_1_2) + { + P_SpawnFireFlicker(sector); + } + break; + } + } + + + // Init line EFFECTs + numlinespecials = 0; + for (i = 0;i < numlines; i++) + { + switch(lines[i].special) + { + case 48: + if (numlinespecials >= maxlineanims) + { + I_Error("P_SpawnSpecials: Too many scrolling wall linedefs " + "(%d)! (Vanilla limit is %d)", NumScrollers(), + maxlineanims); + } + // EFFECT FIRSTCOL SCROLL+ + linespeciallist[numlinespecials] = &lines[i]; + numlinespecials++; + break; + } + } + + + // Init other misc stuff + for (i = 0;i < MAXCEILINGS;i++) + activeceilings[i] = NULL; + + for (i = 0;i < MAXPLATS;i++) + activeplats[i] = NULL; + + for (i = 0;i < MAXBUTTONS;i++) + memset(&buttonlist[i],0,sizeof(button_t)); + + // UNUSED: no horizonal sliders. + // P_InitSlidingDoorFrames(); +} diff --git a/games/NXDoom/src/doom/p_spec.h b/games/NXDoom/src/doom/p_spec.h new file mode 100644 index 00000000000..a1343bfa398 --- /dev/null +++ b/games/NXDoom/src/doom/p_spec.h @@ -0,0 +1,637 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// Implements special effects: +// Texture animation, height or lighting changes +// according to adjacent sectors, respective +// utility functions, etc. +// + + +#ifndef __P_SPEC__ +#define __P_SPEC__ + + +// +// End-level timer (-TIMER option) +// +extern boolean levelTimer; +extern int levelTimeCount; + + +// Define values for map objects +#define MO_TELEPORTMAN 14 + + +// at game start +void P_InitPicAnims (void); + +// at map load +void P_SpawnSpecials (void); + +// every tic +void P_UpdateSpecials (void); + +// when needed +boolean +P_UseSpecialLine +( mobj_t* thing, + line_t* line, + int side ); + +void +P_ShootSpecialLine +( mobj_t* thing, + line_t* line ); + +void +P_CrossSpecialLine +( int linenum, + int side, + mobj_t* thing ); + +void P_PlayerInSpecialSector (player_t* player); + +int +twoSided +( int sector, + int line ); + +sector_t* +getSector +( int currentSector, + int line, + int side ); + +side_t* +getSide +( int currentSector, + int line, + int side ); + +fixed_t P_FindLowestFloorSurrounding(sector_t* sec); +fixed_t P_FindHighestFloorSurrounding(sector_t* sec); + +fixed_t +P_FindNextHighestFloor +( sector_t* sec, + int currentheight ); + +fixed_t P_FindLowestCeilingSurrounding(sector_t* sec); +fixed_t P_FindHighestCeilingSurrounding(sector_t* sec); + +int +P_FindSectorFromLineTag +( line_t* line, + int start ); + +int +P_FindMinSurroundingLight +( sector_t* sector, + int max ); + +sector_t* +getNextSector +( line_t* line, + sector_t* sec ); + + +// +// SPECIAL +// +int EV_DoDonut(line_t* line); + + + +// +// P_LIGHTS +// +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int count; + int maxlight; + int minlight; + +} fireflicker_t; + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int count; + int maxlight; + int minlight; + int maxtime; + int mintime; + +} lightflash_t; + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int count; + int minlight; + int maxlight; + int darktime; + int brighttime; + +} strobe_t; + + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int minlight; + int maxlight; + int direction; + +} glow_t; + + +#define GLOWSPEED 8 +#define STROBEBRIGHT 5 +#define FASTDARK 15 +#define SLOWDARK 35 + +void P_SpawnFireFlicker (sector_t* sector); +void T_LightFlash (lightflash_t* flash); +void P_SpawnLightFlash (sector_t* sector); +void T_StrobeFlash (strobe_t* flash); + +void +P_SpawnStrobeFlash +( sector_t* sector, + int fastOrSlow, + int inSync ); + +void EV_StartLightStrobing(line_t* line); +void EV_TurnTagLightsOff(line_t* line); + +void +EV_LightTurnOn +( line_t* line, + int bright ); + +void T_Glow(glow_t* g); +void P_SpawnGlowingLight(sector_t* sector); + + + + +// +// P_SWITCH +// +typedef struct +{ + char name1[9]; + char name2[9]; + short episode; + +} switchlist_t; + + +typedef enum +{ + top, + middle, + bottom + +} bwhere_e; + + +typedef struct +{ + line_t* line; + bwhere_e where; + int btexture; + int btimer; + degenmobj_t *soundorg; + +} button_t; + + + + + // max # of wall switches in a level +#define MAXSWITCHES 50 + + // 4 players, 4 buttons each at once, max. +#define MAXBUTTONS 16 + + // 1 second, in ticks. +#define BUTTONTIME 35 + +extern button_t buttonlist[MAXBUTTONS]; + +void +P_ChangeSwitchTexture +( line_t* line, + int useAgain ); + +void P_InitSwitchList(void); + + +// +// P_PLATS +// +typedef enum +{ + up, + down, + waiting, + in_stasis + +} plat_e; + + + +typedef enum +{ + perpetualRaise, + downWaitUpStay, + raiseAndChange, + raiseToNearestAndChange, + blazeDWUS + +} plattype_e; + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + fixed_t speed; + fixed_t low; + fixed_t high; + int wait; + int count; + plat_e status; + plat_e oldstatus; + boolean crush; + int tag; + plattype_e type; + +} plat_t; + + + +#define PLATWAIT 3 +#define PLATSPEED FRACUNIT +#define MAXPLATS 30 + + +extern plat_t* activeplats[MAXPLATS]; + +void T_PlatRaise(plat_t* plat); + +int +EV_DoPlat +( line_t* line, + plattype_e type, + int amount ); + +void P_AddActivePlat(plat_t* plat); +void P_RemoveActivePlat(plat_t* plat); +void EV_StopPlat(line_t* line); +void P_ActivateInStasis(int tag); + + +// +// P_DOORS +// +typedef enum +{ + vld_normal, + vld_close30ThenOpen, + vld_close, + vld_open, + vld_raiseIn5Mins, + vld_blazeRaise, + vld_blazeOpen, + vld_blazeClose + +} vldoor_e; + + + +typedef struct +{ + thinker_t thinker; + vldoor_e type; + sector_t* sector; + fixed_t topheight; + fixed_t speed; + + // 1 = up, 0 = waiting at top, -1 = down + int direction; + + // tics to wait at the top + int topwait; + // (keep in case a door going down is reset) + // when it reaches 0, start going down + int topcountdown; + +} vldoor_t; + + + +#define VDOORSPEED FRACUNIT*2 +#define VDOORWAIT 150 + +void +EV_VerticalDoor +( line_t* line, + mobj_t* thing ); + +int +EV_DoDoor +( line_t* line, + vldoor_e type ); + +int +EV_DoLockedDoor +( line_t* line, + vldoor_e type, + mobj_t* thing ); + +void T_VerticalDoor (vldoor_t* door); +void P_SpawnDoorCloseIn30 (sector_t* sec); + +void +P_SpawnDoorRaiseIn5Mins +( sector_t* sec, + int secnum ); + + + +#if 0 // UNUSED +// +// Sliding doors... +// +typedef enum +{ + sd_opening, + sd_waiting, + sd_closing + +} sd_e; + + + +typedef enum +{ + sdt_openOnly, + sdt_closeOnly, + sdt_openAndClose + +} sdt_e; + + + + +typedef struct +{ + thinker_t thinker; + sdt_e type; + line_t* line; + int frame; + int whichDoorIndex; + int timer; + sector_t* frontsector; + sector_t* backsector; + sd_e status; + +} slidedoor_t; + + + +typedef struct +{ + char frontFrame1[9]; + char frontFrame2[9]; + char frontFrame3[9]; + char frontFrame4[9]; + char backFrame1[9]; + char backFrame2[9]; + char backFrame3[9]; + char backFrame4[9]; + +} slidename_t; + + + +typedef struct +{ + int frontFrames[4]; + int backFrames[4]; + +} slideframe_t; + + + +// how many frames of animation +#define SNUMFRAMES 4 + +#define SDOORWAIT 35*3 +#define SWAITTICS 4 + +// how many diff. types of anims +#define MAXSLIDEDOORS 5 + +void P_InitSlidingDoorFrames(void); + +void +EV_SlidingDoor +( line_t* line, + mobj_t* thing ); +#endif + + + +// +// P_CEILNG +// +typedef enum +{ + lowerToFloor, + raiseToHighest, + lowerAndCrush, + crushAndRaise, + fastCrushAndRaise, + silentCrushAndRaise + +} ceiling_e; + + + +typedef struct +{ + thinker_t thinker; + ceiling_e type; + sector_t* sector; + fixed_t bottomheight; + fixed_t topheight; + fixed_t speed; + boolean crush; + + // 1 = up, 0 = waiting, -1 = down + int direction; + + // ID + int tag; + int olddirection; + +} ceiling_t; + + + + + +#define CEILSPEED FRACUNIT +#define CEILWAIT 150 +#define MAXCEILINGS 30 + +extern ceiling_t* activeceilings[MAXCEILINGS]; + +int +EV_DoCeiling +( line_t* line, + ceiling_e type ); + +void T_MoveCeiling (ceiling_t* ceiling); +void P_AddActiveCeiling(ceiling_t* c); +void P_RemoveActiveCeiling(ceiling_t* c); +int EV_CeilingCrushStop(line_t* line); +void P_ActivateInStasisCeiling(line_t* line); + + +// +// P_FLOOR +// +typedef enum +{ + // lower floor to highest surrounding floor + lowerFloor, + + // lower floor to lowest surrounding floor + lowerFloorToLowest, + + // lower floor to highest surrounding floor VERY FAST + turboLower, + + // raise floor to lowest surrounding CEILING + raiseFloor, + + // raise floor to next highest surrounding floor + raiseFloorToNearest, + + // raise floor to shortest height texture around it + raiseToTexture, + + // lower floor to lowest surrounding floor + // and change floorpic + lowerAndChange, + + raiseFloor24, + raiseFloor24AndChange, + raiseFloorCrush, + + // raise to next highest floor, turbo-speed + raiseFloorTurbo, + donutRaise, + raiseFloor512 + +} floor_e; + + + + +typedef enum +{ + build8, // slowly build by 8 + turbo16 // quickly build by 16 + +} stair_e; + + + +typedef struct +{ + thinker_t thinker; + floor_e type; + boolean crush; + sector_t* sector; + int direction; + int newspecial; + short texture; + fixed_t floordestheight; + fixed_t speed; + +} floormove_t; + + + +#define FLOORSPEED FRACUNIT + +typedef enum +{ + ok, + crushed, + pastdest + +} result_e; + +result_e +T_MovePlane +( sector_t* sector, + fixed_t speed, + fixed_t dest, + boolean crush, + int floorOrCeiling, + int direction ); + +int +EV_BuildStairs +( line_t* line, + stair_e type ); + +int +EV_DoFloor +( line_t* line, + floor_e floortype ); + +void T_MoveFloor( floormove_t* floor); + +// +// P_TELEPT +// +int +EV_Teleport +( line_t* line, + int side, + mobj_t* thing ); + +#endif diff --git a/games/NXDoom/src/doom/p_switch.c b/games/NXDoom/src/doom/p_switch.c new file mode 100644 index 00000000000..b9ef2195aad --- /dev/null +++ b/games/NXDoom/src/doom/p_switch.c @@ -0,0 +1,641 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: +// Switches, buttons. Two-state animation. Exits. +// + +#include + +#include "i_system.h" +#include "deh_main.h" +#include "doomdef.h" +#include "p_local.h" + +#include "g_game.h" + +#include "s_sound.h" + +// Data. +#include "sounds.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + + +// +// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE +// +switchlist_t alphSwitchList[] = +{ + // Doom shareware episode 1 switches + {"SW1BRCOM", "SW2BRCOM", 1}, + {"SW1BRN1", "SW2BRN1", 1}, + {"SW1BRN2", "SW2BRN2", 1}, + {"SW1BRNGN", "SW2BRNGN", 1}, + {"SW1BROWN", "SW2BROWN", 1}, + {"SW1COMM", "SW2COMM", 1}, + {"SW1COMP", "SW2COMP", 1}, + {"SW1DIRT", "SW2DIRT", 1}, + {"SW1EXIT", "SW2EXIT", 1}, + {"SW1GRAY", "SW2GRAY", 1}, + {"SW1GRAY1", "SW2GRAY1", 1}, + {"SW1METAL", "SW2METAL", 1}, + {"SW1PIPE", "SW2PIPE", 1}, + {"SW1SLAD", "SW2SLAD", 1}, + {"SW1STARG", "SW2STARG", 1}, + {"SW1STON1", "SW2STON1", 1}, + {"SW1STON2", "SW2STON2", 1}, + {"SW1STONE", "SW2STONE", 1}, + {"SW1STRTN", "SW2STRTN", 1}, + + // Doom registered episodes 2&3 switches + {"SW1BLUE", "SW2BLUE", 2}, + {"SW1CMT", "SW2CMT", 2}, + {"SW1GARG", "SW2GARG", 2}, + {"SW1GSTON", "SW2GSTON", 2}, + {"SW1HOT", "SW2HOT", 2}, + {"SW1LION", "SW2LION", 2}, + {"SW1SATYR", "SW2SATYR", 2}, + {"SW1SKIN", "SW2SKIN", 2}, + {"SW1VINE", "SW2VINE", 2}, + {"SW1WOOD", "SW2WOOD", 2}, + + // Doom II switches + {"SW1PANEL", "SW2PANEL", 3}, + {"SW1ROCK", "SW2ROCK", 3}, + {"SW1MET2", "SW2MET2", 3}, + {"SW1WDMET", "SW2WDMET", 3}, + {"SW1BRIK", "SW2BRIK", 3}, + {"SW1MOD1", "SW2MOD1", 3}, + {"SW1ZIM", "SW2ZIM", 3}, + {"SW1STON6", "SW2STON6", 3}, + {"SW1TEK", "SW2TEK", 3}, + {"SW1MARB", "SW2MARB", 3}, + {"SW1SKULL", "SW2SKULL", 3}, +}; + +int switchlist[MAXSWITCHES * 2]; +int numswitches; +button_t buttonlist[MAXBUTTONS]; + +// +// P_InitSwitchList +// Only called at game initialization. +// +void P_InitSwitchList(void) +{ + int i, slindex, episode; + + // Note that this is called "episode" here but it's actually something + // quite different. As we progress from Shareware->Registered->Doom II + // we support more switch textures. + switch (gamemode) + { + case registered: + case retail: + episode = 2; + break; + case commercial: + episode = 3; + break; + default: + episode = 1; + break; + } + + slindex = 0; + + for (i = 0; i < arrlen(alphSwitchList); i++) + { + if (alphSwitchList[i].episode <= episode) + { + switchlist[slindex++] = + R_TextureNumForName(DEH_String(alphSwitchList[i].name1)); + switchlist[slindex++] = + R_TextureNumForName(DEH_String(alphSwitchList[i].name2)); + } + } + + numswitches = slindex / 2; + switchlist[slindex] = -1; +} + + +// +// Start a button counting down till it turns off. +// +void +P_StartButton +( line_t* line, + bwhere_e w, + int texture, + int time ) +{ + int i; + + // See if button is already pressed + for (i = 0;i < MAXBUTTONS;i++) + { + if (buttonlist[i].btimer + && buttonlist[i].line == line) + { + + return; + } + } + + + + for (i = 0;i < MAXBUTTONS;i++) + { + if (!buttonlist[i].btimer) + { + buttonlist[i].line = line; + buttonlist[i].where = w; + buttonlist[i].btexture = texture; + buttonlist[i].btimer = time; + buttonlist[i].soundorg = &line->frontsector->soundorg; + return; + } + } + + I_Error("P_StartButton: no button slots left!"); +} + + + + + +// +// Function that changes wall texture. +// Tell it if switch is ok to use again (1=yes, it's a button). +// +void +P_ChangeSwitchTexture +( line_t* line, + int useAgain ) +{ + int texTop; + int texMid; + int texBot; + int i; + int sound; + + if (!useAgain) + line->special = 0; + + texTop = sides[line->sidenum[0]].toptexture; + texMid = sides[line->sidenum[0]].midtexture; + texBot = sides[line->sidenum[0]].bottomtexture; + + sound = sfx_swtchn; + + // EXIT SWITCH? + if (line->special == 11) + sound = sfx_swtchx; + + for (i = 0;i < numswitches*2;i++) + { + if (switchlist[i] == texTop) + { + S_StartSound(buttonlist->soundorg,sound); + sides[line->sidenum[0]].toptexture = switchlist[i^1]; + + if (useAgain) + P_StartButton(line,top,switchlist[i],BUTTONTIME); + + return; + } + else + { + if (switchlist[i] == texMid) + { + S_StartSound(buttonlist->soundorg,sound); + sides[line->sidenum[0]].midtexture = switchlist[i^1]; + + if (useAgain) + P_StartButton(line, middle,switchlist[i],BUTTONTIME); + + return; + } + else + { + if (switchlist[i] == texBot) + { + S_StartSound(buttonlist->soundorg,sound); + sides[line->sidenum[0]].bottomtexture = switchlist[i^1]; + + if (useAgain) + P_StartButton(line, bottom,switchlist[i],BUTTONTIME); + + return; + } + } + } + } +} + + + + + + +// +// P_UseSpecialLine +// Called when a thing uses a special line. +// Only the front sides of lines are usable. +// +boolean +P_UseSpecialLine +( mobj_t* thing, + line_t* line, + int side ) +{ + + // Err... + // Use the back sides of VERY SPECIAL lines... + if (side) + { + switch(line->special) + { + case 124: + // Sliding door open&close + // UNUSED? + break; + + default: + return false; + break; + } + } + + + // Switches that other things can activate. + if (!thing->player) + { + // never open secret doors + if (line->flags & ML_SECRET) + return false; + + switch(line->special) + { + case 1: // MANUAL DOOR RAISE + case 32: // MANUAL BLUE + case 33: // MANUAL RED + case 34: // MANUAL YELLOW + break; + + default: + return false; + break; + } + } + + + // do something + switch (line->special) + { + // MANUALS + case 1: // Vertical Door + case 26: // Blue Door/Locked + case 27: // Yellow Door /Locked + case 28: // Red Door /Locked + + case 31: // Manual door open + case 32: // Blue locked door open + case 33: // Red locked door open + case 34: // Yellow locked door open + + case 117: // Blazing door raise + case 118: // Blazing door open + EV_VerticalDoor (line, thing); + break; + + //UNUSED - Door Slide Open&Close + // case 124: + // EV_SlidingDoor (line, thing); + // break; + + // SWITCHES + case 7: + // Build Stairs + if (EV_BuildStairs(line,build8)) + P_ChangeSwitchTexture(line,0); + break; + + case 9: + // Change Donut + if (EV_DoDonut(line)) + P_ChangeSwitchTexture(line,0); + break; + + case 11: + // Exit level + P_ChangeSwitchTexture(line,0); + G_ExitLevel (); + break; + + case 14: + // Raise Floor 32 and change texture + if (EV_DoPlat(line,raiseAndChange,32)) + P_ChangeSwitchTexture(line,0); + break; + + case 15: + // Raise Floor 24 and change texture + if (EV_DoPlat(line,raiseAndChange,24)) + P_ChangeSwitchTexture(line,0); + break; + + case 18: + // Raise Floor to next highest floor + if (EV_DoFloor(line, raiseFloorToNearest)) + P_ChangeSwitchTexture(line,0); + break; + + case 20: + // Raise Plat next highest floor and change texture + if (EV_DoPlat(line,raiseToNearestAndChange,0)) + P_ChangeSwitchTexture(line,0); + break; + + case 21: + // PlatDownWaitUpStay + if (EV_DoPlat(line,downWaitUpStay,0)) + P_ChangeSwitchTexture(line,0); + break; + + case 23: + // Lower Floor to Lowest + if (EV_DoFloor(line,lowerFloorToLowest)) + P_ChangeSwitchTexture(line,0); + break; + + case 29: + // Raise Door + if (EV_DoDoor(line,vld_normal)) + P_ChangeSwitchTexture(line,0); + break; + + case 41: + // Lower Ceiling to Floor + if (EV_DoCeiling(line,lowerToFloor)) + P_ChangeSwitchTexture(line,0); + break; + + case 71: + // Turbo Lower Floor + if (EV_DoFloor(line,turboLower)) + P_ChangeSwitchTexture(line,0); + break; + + case 49: + // Ceiling Crush And Raise + if (EV_DoCeiling(line,crushAndRaise)) + P_ChangeSwitchTexture(line,0); + break; + + case 50: + // Close Door + if (EV_DoDoor(line,vld_close)) + P_ChangeSwitchTexture(line,0); + break; + + case 51: + // Secret EXIT + P_ChangeSwitchTexture(line,0); + G_SecretExitLevel (); + break; + + case 55: + // Raise Floor Crush + if (EV_DoFloor(line,raiseFloorCrush)) + P_ChangeSwitchTexture(line,0); + break; + + case 101: + // Raise Floor + if (EV_DoFloor(line,raiseFloor)) + P_ChangeSwitchTexture(line,0); + break; + + case 102: + // Lower Floor to Surrounding floor height + if (EV_DoFloor(line,lowerFloor)) + P_ChangeSwitchTexture(line,0); + break; + + case 103: + // Open Door + if (EV_DoDoor(line,vld_open)) + P_ChangeSwitchTexture(line,0); + break; + + case 111: + // Blazing Door Raise (faster than TURBO!) + if (EV_DoDoor (line,vld_blazeRaise)) + P_ChangeSwitchTexture(line,0); + break; + + case 112: + // Blazing Door Open (faster than TURBO!) + if (EV_DoDoor (line,vld_blazeOpen)) + P_ChangeSwitchTexture(line,0); + break; + + case 113: + // Blazing Door Close (faster than TURBO!) + if (EV_DoDoor (line,vld_blazeClose)) + P_ChangeSwitchTexture(line,0); + break; + + case 122: + // Blazing PlatDownWaitUpStay + if (EV_DoPlat(line,blazeDWUS,0)) + P_ChangeSwitchTexture(line,0); + break; + + case 127: + // Build Stairs Turbo 16 + if (EV_BuildStairs(line,turbo16)) + P_ChangeSwitchTexture(line,0); + break; + + case 131: + // Raise Floor Turbo + if (EV_DoFloor(line,raiseFloorTurbo)) + P_ChangeSwitchTexture(line,0); + break; + + case 133: + // BlzOpenDoor BLUE + case 135: + // BlzOpenDoor RED + case 137: + // BlzOpenDoor YELLOW + if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) + P_ChangeSwitchTexture(line,0); + break; + + case 140: + // Raise Floor 512 + if (EV_DoFloor(line,raiseFloor512)) + P_ChangeSwitchTexture(line,0); + break; + + // BUTTONS + case 42: + // Close Door + if (EV_DoDoor(line,vld_close)) + P_ChangeSwitchTexture(line,1); + break; + + case 43: + // Lower Ceiling to Floor + if (EV_DoCeiling(line,lowerToFloor)) + P_ChangeSwitchTexture(line,1); + break; + + case 45: + // Lower Floor to Surrounding floor height + if (EV_DoFloor(line,lowerFloor)) + P_ChangeSwitchTexture(line,1); + break; + + case 60: + // Lower Floor to Lowest + if (EV_DoFloor(line,lowerFloorToLowest)) + P_ChangeSwitchTexture(line,1); + break; + + case 61: + // Open Door + if (EV_DoDoor(line,vld_open)) + P_ChangeSwitchTexture(line,1); + break; + + case 62: + // PlatDownWaitUpStay + if (EV_DoPlat(line,downWaitUpStay,1)) + P_ChangeSwitchTexture(line,1); + break; + + case 63: + // Raise Door + if (EV_DoDoor(line,vld_normal)) + P_ChangeSwitchTexture(line,1); + break; + + case 64: + // Raise Floor to ceiling + if (EV_DoFloor(line,raiseFloor)) + P_ChangeSwitchTexture(line,1); + break; + + case 66: + // Raise Floor 24 and change texture + if (EV_DoPlat(line,raiseAndChange,24)) + P_ChangeSwitchTexture(line,1); + break; + + case 67: + // Raise Floor 32 and change texture + if (EV_DoPlat(line,raiseAndChange,32)) + P_ChangeSwitchTexture(line,1); + break; + + case 65: + // Raise Floor Crush + if (EV_DoFloor(line,raiseFloorCrush)) + P_ChangeSwitchTexture(line,1); + break; + + case 68: + // Raise Plat to next highest floor and change texture + if (EV_DoPlat(line,raiseToNearestAndChange,0)) + P_ChangeSwitchTexture(line,1); + break; + + case 69: + // Raise Floor to next highest floor + if (EV_DoFloor(line, raiseFloorToNearest)) + P_ChangeSwitchTexture(line,1); + break; + + case 70: + // Turbo Lower Floor + if (EV_DoFloor(line,turboLower)) + P_ChangeSwitchTexture(line,1); + break; + + case 114: + // Blazing Door Raise (faster than TURBO!) + if (EV_DoDoor (line,vld_blazeRaise)) + P_ChangeSwitchTexture(line,1); + break; + + case 115: + // Blazing Door Open (faster than TURBO!) + if (EV_DoDoor (line,vld_blazeOpen)) + P_ChangeSwitchTexture(line,1); + break; + + case 116: + // Blazing Door Close (faster than TURBO!) + if (EV_DoDoor (line,vld_blazeClose)) + P_ChangeSwitchTexture(line,1); + break; + + case 123: + // Blazing PlatDownWaitUpStay + if (EV_DoPlat(line,blazeDWUS,0)) + P_ChangeSwitchTexture(line,1); + break; + + case 132: + // Raise Floor Turbo + if (EV_DoFloor(line,raiseFloorTurbo)) + P_ChangeSwitchTexture(line,1); + break; + + case 99: + // BlzOpenDoor BLUE + case 134: + // BlzOpenDoor RED + case 136: + // BlzOpenDoor YELLOW + if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) + P_ChangeSwitchTexture(line,1); + break; + + case 138: + // Light Turn On + EV_LightTurnOn(line,255); + P_ChangeSwitchTexture(line,1); + break; + + case 139: + // Light Turn Off + EV_LightTurnOn(line,35); + P_ChangeSwitchTexture(line,1); + break; + + } + + return true; +} + diff --git a/games/NXDoom/src/doom/p_telept.c b/games/NXDoom/src/doom/p_telept.c new file mode 100644 index 00000000000..8e2d5e16c98 --- /dev/null +++ b/games/NXDoom/src/doom/p_telept.c @@ -0,0 +1,132 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Teleportation. +// + + + + +#include "doomdef.h" +#include "doomstat.h" + +#include "s_sound.h" + +#include "p_local.h" + + +// Data. +#include "sounds.h" + +// State. +#include "r_state.h" + + + +// +// TELEPORTATION +// +int +EV_Teleport +( line_t* line, + int side, + mobj_t* thing ) +{ + int i; + int tag; + mobj_t* m; + mobj_t* fog; + unsigned an; + thinker_t* thinker; + sector_t* sector; + fixed_t oldx; + fixed_t oldy; + fixed_t oldz; + + // don't teleport missiles + if (thing->flags & MF_MISSILE) + return 0; + + // Don't teleport if hit back of line, + // so you can get out of teleporter. + if (side == 1) + return 0; + + + tag = line->tag; + for (i = 0; i < numsectors; i++) + { + if (sectors[ i ].tag == tag ) + { + for (thinker = thinkercap.next; + thinker != &thinkercap; + thinker = thinker->next) + { + // not a mobj + if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + m = (mobj_t *)thinker; + + // not a teleportman + if (m->type != MT_TELEPORTMAN ) + continue; + + sector = m->subsector->sector; + // wrong sector + if (sector-sectors != i ) + continue; + + oldx = thing->x; + oldy = thing->y; + oldz = thing->z; + + if (!P_TeleportMove (thing, m->x, m->y)) + return 0; + + // The first Final Doom executable does not set thing->z + // when teleporting. This quirk is unique to this + // particular version; the later version included in + // some versions of the Id Anthology fixed this. + + if (gameversion != exe_final) + thing->z = thing->floorz; + + if (thing->player) + thing->player->viewz = thing->z+thing->player->viewheight; + + // spawn teleport fog at source and destination + fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); + S_StartSound (fog, sfx_telept); + an = m->angle >> ANGLETOFINESHIFT; + fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] + , thing->z, MT_TFOG); + + // emit sound, where? + S_StartSound (fog, sfx_telept); + + // don't move for a bit + if (thing->player) + thing->reactiontime = 18; + + thing->angle = m->angle; + thing->momx = thing->momy = thing->momz = 0; + return 1; + } + } + } + return 0; +} + diff --git a/games/NXDoom/src/doom/p_tick.c b/games/NXDoom/src/doom/p_tick.c new file mode 100644 index 00000000000..5a93b80f13b --- /dev/null +++ b/games/NXDoom/src/doom/p_tick.c @@ -0,0 +1,153 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Archiving: SaveGame I/O. +// Thinker, Ticker. +// + + +#include "z_zone.h" +#include "p_local.h" + +#include "doomstat.h" + + +int leveltime; + +// +// THINKERS +// All thinkers should be allocated by Z_Malloc +// so they can be operated on uniformly. +// The actual structures will vary in size, +// but the first element must be thinker_t. +// + + + +// Both the head and tail of the thinker list. +thinker_t thinkercap; + + +// +// P_InitThinkers +// +void P_InitThinkers (void) +{ + thinkercap.prev = thinkercap.next = &thinkercap; +} + + + + +// +// P_AddThinker +// Adds a new thinker at the end of the list. +// +void P_AddThinker (thinker_t* thinker) +{ + thinkercap.prev->next = thinker; + thinker->next = &thinkercap; + thinker->prev = thinkercap.prev; + thinkercap.prev = thinker; +} + + + +// +// P_RemoveThinker +// Deallocation is lazy -- it will not actually be freed +// until its thinking turn comes up. +// +void P_RemoveThinker (thinker_t* thinker) +{ + // FIXME: NOP. + thinker->function.acv = (actionf_v)(-1); +} + + + +// +// P_AllocateThinker +// Allocates memory and adds a new thinker at the end of the list. +// +void P_AllocateThinker (thinker_t* thinker) +{ +} + + + +// +// P_RunThinkers +// +void P_RunThinkers (void) +{ + thinker_t *currentthinker, *nextthinker; + + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + if ( currentthinker->function.acv == (actionf_v)(-1) ) + { + // time to remove it + nextthinker = currentthinker->next; + currentthinker->next->prev = currentthinker->prev; + currentthinker->prev->next = currentthinker->next; + Z_Free(currentthinker); + } + else + { + if (currentthinker->function.acp1) + currentthinker->function.acp1 (currentthinker); + nextthinker = currentthinker->next; + } + currentthinker = nextthinker; + } +} + + + +// +// P_Ticker +// + +void P_Ticker (void) +{ + int i; + + // run the tic + if (paused) + return; + + // pause if in menu and at least one tic has been run + if ( !netgame + && menuactive + && !demoplayback + && players[consoleplayer].viewz != 1) + { + return; + } + + + for (i=0 ; i>= ANGLETOFINESHIFT; + + player->mo->momx += FixedMul(move,finecosine[angle]); + player->mo->momy += FixedMul(move,finesine[angle]); +} + + + + +// +// P_CalcHeight +// Calculate the walking / running height adjustment +// +void P_CalcHeight (player_t* player) +{ + int angle; + fixed_t bob; + + // Regular movement bobbing + // (needs to be calculated for gun swing + // even if not on ground) + // OPTIMIZE: tablify angle + // Note: a LUT allows for effects + // like a ramp with low health. + player->bob = + FixedMul (player->mo->momx, player->mo->momx) + + FixedMul (player->mo->momy,player->mo->momy); + + player->bob >>= 2; + + if (player->bob>MAXBOB) + player->bob = MAXBOB; + + if ((player->cheats & CF_NOMOMENTUM) || !onground) + { + player->viewz = player->mo->z + VIEWHEIGHT; + + if (player->viewz > player->mo->ceilingz-4*FRACUNIT) + player->viewz = player->mo->ceilingz-4*FRACUNIT; + + player->viewz = player->mo->z + player->viewheight; + return; + } + + angle = (FINEANGLES/20*leveltime)&FINEMASK; + bob = FixedMul ( player->bob/2, finesine[angle]); + + + // move viewheight + if (player->playerstate == PST_LIVE) + { + player->viewheight += player->deltaviewheight; + + if (player->viewheight > VIEWHEIGHT) + { + player->viewheight = VIEWHEIGHT; + player->deltaviewheight = 0; + } + + if (player->viewheight < VIEWHEIGHT/2) + { + player->viewheight = VIEWHEIGHT/2; + if (player->deltaviewheight <= 0) + player->deltaviewheight = 1; + } + + if (player->deltaviewheight) + { + player->deltaviewheight += FRACUNIT/4; + if (!player->deltaviewheight) + player->deltaviewheight = 1; + } + } + player->viewz = player->mo->z + player->viewheight + bob; + + if (player->viewz > player->mo->ceilingz-4*FRACUNIT) + player->viewz = player->mo->ceilingz-4*FRACUNIT; +} + + + +// +// P_MovePlayer +// +void P_MovePlayer (player_t* player) +{ + ticcmd_t* cmd; + + cmd = &player->cmd; + + player->mo->angle += (cmd->angleturn<mo->z <= player->mo->floorz); + + if (cmd->forwardmove && onground) + P_Thrust (player, player->mo->angle, cmd->forwardmove*2048); + + if (cmd->sidemove && onground) + P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048); + + if ( (cmd->forwardmove || cmd->sidemove) + && player->mo->state == &states[S_PLAY] ) + { + P_SetMobjState (player->mo, S_PLAY_RUN1); + } +} + + + +// +// P_DeathThink +// Fall on your face when dying. +// Decrease POV height to floor height. +// +#define ANG5 (ANG90/18) + +void P_DeathThink (player_t* player) +{ + angle_t angle; + angle_t delta; + + P_MovePsprites (player); + + // fall to the ground + if (player->viewheight > 6*FRACUNIT) + player->viewheight -= FRACUNIT; + + if (player->viewheight < 6*FRACUNIT) + player->viewheight = 6*FRACUNIT; + + player->deltaviewheight = 0; + onground = (player->mo->z <= player->mo->floorz); + P_CalcHeight (player); + + if (player->attacker && player->attacker != player->mo) + { + angle = R_PointToAngle2 (player->mo->x, + player->mo->y, + player->attacker->x, + player->attacker->y); + + delta = angle - player->mo->angle; + + if (delta < ANG5 || delta > (unsigned)-ANG5) + { + // Looking at killer, + // so fade damage flash down. + player->mo->angle = angle; + + if (player->damagecount) + player->damagecount--; + } + else if (delta < ANG180) + player->mo->angle += ANG5; + else + player->mo->angle -= ANG5; + } + else if (player->damagecount) + player->damagecount--; + + + if (player->cmd.buttons & BT_USE) + player->playerstate = PST_REBORN; +} + + + +// +// P_PlayerThink +// +void P_PlayerThink (player_t* player) +{ + ticcmd_t* cmd; + weapontype_t newweapon; + + // fixme: do this in the cheat code + if (player->cheats & CF_NOCLIP) + player->mo->flags |= MF_NOCLIP; + else + player->mo->flags &= ~MF_NOCLIP; + + // chain saw run forward + cmd = &player->cmd; + if (player->mo->flags & MF_JUSTATTACKED) + { + cmd->angleturn = 0; + cmd->forwardmove = 0xc800/512; + cmd->sidemove = 0; + player->mo->flags &= ~MF_JUSTATTACKED; + } + + + if (player->playerstate == PST_DEAD) + { + P_DeathThink (player); + return; + } + + // Move around. + // Reactiontime is used to prevent movement + // for a bit after a teleport. + if (player->mo->reactiontime) + player->mo->reactiontime--; + else + P_MovePlayer (player); + + P_CalcHeight (player); + + if (player->mo->subsector->sector->special) + P_PlayerInSpecialSector (player); + + // Check for weapon change. + + // A special event has no other buttons. + if (cmd->buttons & BT_SPECIAL) + cmd->buttons = 0; + + if (cmd->buttons & BT_CHANGE) + { + // The actual changing of the weapon is done + // when the weapon psprite can do it + // (read: not in the middle of an attack). + newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT; + + if (newweapon == wp_fist + && player->weaponowned[wp_chainsaw] + && !(player->readyweapon == wp_chainsaw + && player->powers[pw_strength])) + { + newweapon = wp_chainsaw; + } + + if ( (gamemode == commercial) + && newweapon == wp_shotgun + && player->weaponowned[wp_supershotgun] + && player->readyweapon != wp_supershotgun) + { + newweapon = wp_supershotgun; + } + + + if (player->weaponowned[newweapon] + && newweapon != player->readyweapon) + { + // Do not go to plasma or BFG in shareware, + // even if cheated. + if ((newweapon != wp_plasma + && newweapon != wp_bfg) + || (gamemode != shareware) ) + { + player->pendingweapon = newweapon; + } + } + } + + // check for use + if (cmd->buttons & BT_USE) + { + if (!player->usedown) + { + P_UseLines (player); + player->usedown = true; + } + } + else + player->usedown = false; + + // cycle psprites + P_MovePsprites (player); + + // Counters, time dependend power ups. + + // Strength counts up to diminish fade. + if (player->powers[pw_strength]) + player->powers[pw_strength]++; + + if (player->powers[pw_invulnerability]) + player->powers[pw_invulnerability]--; + + if (player->powers[pw_invisibility]) + if (! --player->powers[pw_invisibility] ) + player->mo->flags &= ~MF_SHADOW; + + if (player->powers[pw_infrared]) + player->powers[pw_infrared]--; + + if (player->powers[pw_ironfeet]) + player->powers[pw_ironfeet]--; + + if (player->damagecount) + player->damagecount--; + + if (player->bonuscount) + player->bonuscount--; + + + // Handling colormaps. + if (player->powers[pw_invulnerability]) + { + if (player->powers[pw_invulnerability] > 4*32 + || (player->powers[pw_invulnerability]&8) ) + player->fixedcolormap = INVERSECOLORMAP; + else + player->fixedcolormap = 0; + } + else if (player->powers[pw_infrared]) + { + if (player->powers[pw_infrared] > 4*32 + || (player->powers[pw_infrared]&8) ) + { + // almost full bright + player->fixedcolormap = 1; + } + else + player->fixedcolormap = 0; + } + else + player->fixedcolormap = 0; +} + + diff --git a/games/NXDoom/src/doom/r_bsp.c b/games/NXDoom/src/doom/r_bsp.c new file mode 100644 index 00000000000..755d2eefc67 --- /dev/null +++ b/games/NXDoom/src/doom/r_bsp.c @@ -0,0 +1,583 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// BSP traversal, handling of LineSegs for rendering. +// + + + + +#include "doomdef.h" + +#include "m_bbox.h" + +#include "i_system.h" + +#include "r_main.h" +#include "r_plane.h" +#include "r_things.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +//#include "r_local.h" + + + +seg_t* curline; +side_t* sidedef; +line_t* linedef; +sector_t* frontsector; +sector_t* backsector; + +drawseg_t drawsegs[MAXDRAWSEGS]; +drawseg_t* ds_p; + + +void +R_StoreWallRange +( int start, + int stop ); + + + + +// +// R_ClearDrawSegs +// +void R_ClearDrawSegs (void) +{ + ds_p = drawsegs; +} + + + +// +// ClipWallSegment +// Clips the given range of columns +// and includes it in the new clip list. +// +typedef struct +{ + int first; + int last; + +} cliprange_t; + +// We must expand MAXSEGS to the theoretical limit of the number of solidsegs +// that can be generated in a scene by the DOOM engine. This was determined by +// Lee Killough during BOOM development to be a function of the screensize. +// The simplest thing we can do, other than fix this bug, is to let the game +// render overage and then bomb out by detecting the overflow after the +// fact. -haleyjd +//#define MAXSEGS 32 +#define MAXSEGS (SCREENWIDTH / 2 + 1) + +// newend is one past the last valid seg +cliprange_t* newend; +cliprange_t solidsegs[MAXSEGS]; + + + + +// +// R_ClipSolidWallSegment +// Does handle solid walls, +// e.g. single sided LineDefs (middle texture) +// that entirely block the view. +// +void +R_ClipSolidWallSegment +( int first, + int last ) +{ + cliprange_t* next; + cliprange_t* start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first-1) + start++; + + if (first < start->first) + { + if (last < start->first-1) + { + // Post is entirely visible (above start), + // so insert a new clippost. + R_StoreWallRange (first, last); + next = newend; + newend++; + + while (next != start) + { + *next = *(next-1); + next--; + } + next->first = first; + next->last = last; + return; + } + + // There is a fragment above *start. + R_StoreWallRange (first, start->first - 1); + // Now adjust the clip size. + start->first = first; + } + + // Bottom contained in start? + if (last <= start->last) + return; + + next = start; + while (last >= (next+1)->first-1) + { + // There is a fragment between two posts. + R_StoreWallRange (next->last + 1, (next+1)->first - 1); + next++; + + if (last <= next->last) + { + // Bottom is contained in next. + // Adjust the clip size. + start->last = next->last; + goto crunch; + } + } + + // There is a fragment after *next. + R_StoreWallRange (next->last + 1, last); + // Adjust the clip size. + start->last = last; + + // Remove start+1 to next from the clip list, + // because start now covers their area. + crunch: + if (next == start) + { + // Post just extended past the bottom of one post. + return; + } + + + while (next++ != newend) + { + // Remove a post. + *++start = *next; + } + + newend = start+1; +} + + + +// +// R_ClipPassWallSegment +// Clips the given range of columns, +// but does not includes it in the clip list. +// Does handle windows, +// e.g. LineDefs with upper and lower texture. +// +void +R_ClipPassWallSegment +( int first, + int last ) +{ + cliprange_t* start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first-1) + start++; + + if (first < start->first) + { + if (last < start->first-1) + { + // Post is entirely visible (above start). + R_StoreWallRange (first, last); + return; + } + + // There is a fragment above *start. + R_StoreWallRange (first, start->first - 1); + } + + // Bottom contained in start? + if (last <= start->last) + return; + + while (last >= (start+1)->first-1) + { + // There is a fragment between two posts. + R_StoreWallRange (start->last + 1, (start+1)->first - 1); + start++; + + if (last <= start->last) + return; + } + + // There is a fragment after *next. + R_StoreWallRange (start->last + 1, last); +} + + + +// +// R_ClearClipSegs +// +void R_ClearClipSegs (void) +{ + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs+2; +} + +// +// R_AddLine +// Clips the given segment +// and adds any visible pieces to the line list. +// +void R_AddLine (seg_t* line) +{ + int x1; + int x2; + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + curline = line; + + // OPTIMIZE: quickly reject orthogonal back sides. + angle1 = R_PointToAngle (line->v1->x, line->v1->y); + angle2 = R_PointToAngle (line->v2->x, line->v2->y); + + // Clip to view edges. + // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). + span = angle1 - angle2; + + // Back side? I.e. backface culling? + if (span >= ANG180) + return; + + // Global angle needed by segcalc. + rw_angle1 = angle1; + angle1 -= viewangle; + angle2 -= viewangle; + + tspan = angle1 + clipangle; + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + angle2 = -clipangle; + } + + // The seg is in the view range, + // but not necessarily visible. + angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; + angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; + + // Does not cross a pixel? + if (x1 == x2) + return; + + backsector = line->backsector; + + // Single sided line? + if (!backsector) + goto clipsolid; + + // Closed door. + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + goto clipsolid; + + // Window. + if (backsector->ceilingheight != frontsector->ceilingheight + || backsector->floorheight != frontsector->floorheight) + goto clippass; + + // Reject empty lines used for triggers + // and special events. + // Identical floor and ceiling on both sides, + // identical light levels on both sides, + // and no middle texture. + if (backsector->ceilingpic == frontsector->ceilingpic + && backsector->floorpic == frontsector->floorpic + && backsector->lightlevel == frontsector->lightlevel + && curline->sidedef->midtexture == 0) + { + return; + } + + + clippass: + R_ClipPassWallSegment (x1, x2-1); + return; + + clipsolid: + R_ClipSolidWallSegment (x1, x2-1); +} + + +// +// R_CheckBBox +// Checks BSP node/subtree bounding box. +// Returns true +// if some part of the bbox might be visible. +// +int checkcoord[12][4] = +{ + {3,0,2,1}, + {3,0,2,0}, + {3,1,2,0}, + {0}, + {2,0,2,1}, + {0,0,0,0}, + {3,1,3,0}, + {0}, + {2,0,3,1}, + {2,1,3,1}, + {2,1,3,0} +}; + + +boolean R_CheckBBox (fixed_t* bspcoord) +{ + int boxx; + int boxy; + int boxpos; + + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + cliprange_t* start; + + int sx1; + int sx2; + + // Find the corners of the box + // that define the edges from current viewpoint. + if (viewx <= bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx < bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy >= bspcoord[BOXTOP]) + boxy = 0; + else if (viewy > bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy<<2)+boxx; + if (boxpos == 5) + return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + // check clip list for an open space + angle1 = R_PointToAngle (x1, y1) - viewangle; + angle2 = R_PointToAngle (x2, y2) - viewangle; + + span = angle1 - angle2; + + // Sitting on a line? + if (span >= ANG180) + return true; + + tspan = angle1 + clipangle; + + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle2 = -clipangle; + } + + + // Find the first clippost + // that touches the source post + // (adjacent pixels are touching). + angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; + angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; + sx1 = viewangletox[angle1]; + sx2 = viewangletox[angle2]; + + // Does not cross a pixel. + if (sx1 == sx2) + return false; + sx2--; + + start = solidsegs; + while (start->last < sx2) + start++; + + if (sx1 >= start->first + && sx2 <= start->last) + { + // The clippost contains the new span. + return false; + } + + return true; +} + + + +// +// R_Subsector +// Determine floor/ceiling planes. +// Add sprites of things in sector. +// Draw one or more line segments. +// +void R_Subsector (int num) +{ + int count; + seg_t* line; + subsector_t* sub; + +#ifdef RANGECHECK + if (num>=numsubsectors) + I_Error ("R_Subsector: ss %i with numss = %i", + num, + numsubsectors); +#endif + + sscount++; + sub = &subsectors[num]; + frontsector = sub->sector; + count = sub->numlines; + line = &segs[sub->firstline]; + + if (frontsector->floorheight < viewz) + { + floorplane = R_FindPlane (frontsector->floorheight, + frontsector->floorpic, + frontsector->lightlevel); + } + else + floorplane = NULL; + + if (frontsector->ceilingheight > viewz + || frontsector->ceilingpic == skyflatnum) + { + ceilingplane = R_FindPlane (frontsector->ceilingheight, + frontsector->ceilingpic, + frontsector->lightlevel); + } + else + ceilingplane = NULL; + + R_AddSprites (frontsector); + + while (count--) + { + R_AddLine (line); + line++; + } + + // check for solidsegs overflow - extremely unsatisfactory! + if(newend > &solidsegs[32]) + I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); +} + + + + +// +// RenderBSPNode +// Renders all subsectors below a given node, +// traversing subtree recursively. +// Just call with BSP root. +void R_RenderBSPNode (int bspnum) +{ + node_t* bsp; + int side; + + // Found a subsector? + if (bspnum & NF_SUBSECTOR) + { + if (bspnum == -1) + R_Subsector (0); + else + R_Subsector (bspnum&(~NF_SUBSECTOR)); + return; + } + + bsp = &nodes[bspnum]; + + // Decide which side the view point is on. + side = R_PointOnSide (viewx, viewy, bsp); + + // Recursively divide front space. + R_RenderBSPNode (bsp->children[side]); + + // Possibly divide back space. + if (R_CheckBBox (bsp->bbox[side^1])) + R_RenderBSPNode (bsp->children[side^1]); +} + + diff --git a/games/NXDoom/src/doom/r_bsp.h b/games/NXDoom/src/doom/r_bsp.h new file mode 100644 index 00000000000..1723e686147 --- /dev/null +++ b/games/NXDoom/src/doom/r_bsp.h @@ -0,0 +1,61 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh module, BSP traversal and handling. +// + + +#ifndef __R_BSP__ +#define __R_BSP__ + + + +extern seg_t* curline; +extern side_t* sidedef; +extern line_t* linedef; +extern sector_t* frontsector; +extern sector_t* backsector; + +extern int rw_x; +extern int rw_stopx; + +extern boolean segtextured; + +// false if the back side is the same plane +extern boolean markfloor; +extern boolean markceiling; + +extern boolean skymap; + +extern drawseg_t drawsegs[MAXDRAWSEGS]; +extern drawseg_t* ds_p; + +extern lighttable_t** hscalelight; +extern lighttable_t** vscalelight; +extern lighttable_t** dscalelight; + + +typedef void (*drawfunc_t) (int start, int stop); + + +// BSP? +void R_ClearClipSegs (void); +void R_ClearDrawSegs (void); + + +void R_RenderBSPNode (int bspnum); + + +#endif diff --git a/games/NXDoom/src/doom/r_data.c b/games/NXDoom/src/doom/r_data.c new file mode 100644 index 00000000000..7f1bbbe00ae --- /dev/null +++ b/games/NXDoom/src/doom/r_data.c @@ -0,0 +1,904 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Preparation of data for rendering, +// generation of lookups, caching, retrieval by name. +// + +#include + +#include "deh_main.h" +#include "i_swap.h" +#include "i_system.h" +#include "z_zone.h" + + +#include "w_wad.h" + +#include "doomdef.h" +#include "m_misc.h" +#include "r_local.h" +#include "p_local.h" + +#include "doomstat.h" +#include "r_sky.h" + + +#include "r_data.h" + +// +// Graphics. +// DOOM graphics for walls and sprites +// is stored in vertical runs of opaque pixels (posts). +// A column is composed of zero or more posts, +// a patch or sprite is composed of zero or more columns. +// + + + +// +// Texture definition. +// Each texture is composed of one or more patches, +// with patches being lumps stored in the WAD. +// The lumps are referenced by number, and patched +// into the rectangular texture space using origin +// and possibly other attributes. +// +typedef PACKED_STRUCT ( +{ + short originx; + short originy; + short patch; + short stepdir; + short colormap; +}) mappatch_t; + + +// +// Texture definition. +// A DOOM wall texture is a list of patches +// which are to be combined in a predefined order. +// +typedef PACKED_STRUCT ( +{ + char name[8]; + int masked; + short width; + short height; + int obsolete; + short patchcount; + mappatch_t patches[1]; +}) maptexture_t; + + +// A single patch from a texture definition, +// basically a rectangular area within +// the texture rectangle. +typedef struct +{ + // Block origin (allways UL), + // which has allready accounted + // for the internal origin of the patch. + short originx; + short originy; + int patch; +} texpatch_t; + + +// A maptexturedef_t describes a rectangular texture, +// which is composed of one or more mappatch_t structures +// that arrange graphic patches. + +typedef struct texture_s texture_t; + +struct texture_s +{ + // Keep name for switch changing, etc. + char name[8]; + short width; + short height; + + // Index in textures list + + int index; + + // Next in hash table chain + + texture_t *next; + + // All the patches[patchcount] + // are drawn back to front into the cached texture. + short patchcount; + texpatch_t patches[1]; +}; + + + +int firstflat; +int lastflat; +int numflats; + +int firstpatch; +int lastpatch; +int numpatches; + +int firstspritelump; +int lastspritelump; +int numspritelumps; + +int numtextures; +texture_t** textures; +texture_t** textures_hashtable; + + +int* texturewidthmask; +// needed for texture pegging +fixed_t* textureheight; +int* texturecompositesize; +short** texturecolumnlump; +unsigned short** texturecolumnofs; +byte** texturecomposite; + +// for global animation +int* flattranslation; +int* texturetranslation; + +// needed for pre rendering +fixed_t* spritewidth; +fixed_t* spriteoffset; +fixed_t* spritetopoffset; + +lighttable_t *colormaps; + + +// +// MAPTEXTURE_T CACHING +// When a texture is first needed, +// it counts the number of composite columns +// required in the texture and allocates space +// for a column directory and any new columns. +// The directory will simply point inside other patches +// if there is only one patch in a given column, +// but any columns with multiple patches +// will have new column_ts generated. +// + + + +// +// R_DrawColumnInCache +// Clip and draw a column +// from a patch into a cached post. +// +void +R_DrawColumnInCache +( column_t* patch, + byte* cache, + int originy, + int cacheheight ) +{ + int count; + int position; + byte* source; + + while (patch->topdelta != 0xff) + { + source = (byte *)patch + 3; + count = patch->length; + position = originy + patch->topdelta; + + if (position < 0) + { + count += position; + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + if (count > 0) + memcpy (cache + position, source, count); + + patch = (column_t *)( (byte *)patch + patch->length + 4); + } +} + + + +// +// R_GenerateComposite +// Using the texture definition, +// the composite texture is created from the patches, +// and each column is cached. +// +void R_GenerateComposite (int texnum) +{ + byte* block; + texture_t* texture; + texpatch_t* patch; + patch_t* realpatch; + int x; + int x1; + int x2; + int i; + column_t* patchcol; + short* collump; + unsigned short* colofs; + + texture = textures[texnum]; + + block = Z_Malloc (texturecompositesize[texnum], + PU_STATIC, + &texturecomposite[texnum]); + + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + + // Composite the columns together. + for (i=0 , patch = texture->patches; + ipatchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1<0) + x = 0; + else + x = x1; + + if (x2 > texture->width) + x2 = texture->width; + + for ( ; x= 0) + continue; + + patchcol = (column_t *)((byte *)realpatch + + LONG(realpatch->columnofs[x-x1])); + R_DrawColumnInCache (patchcol, + block + colofs[x], + patch->originy, + texture->height); + } + + } + + // Now that the texture has been built in column cache, + // it is purgable from zone memory. + Z_ChangeTag (block, PU_CACHE); +} + + + +// +// R_GenerateLookup +// +void R_GenerateLookup (int texnum) +{ + texture_t* texture; + byte* patchcount; // patchcount[texture->width] + texpatch_t* patch; + patch_t* realpatch; + int x; + int x1; + int x2; + int i; + short* collump; + unsigned short* colofs; + + texture = textures[texnum]; + + // Composited texture not created yet. + texturecomposite[texnum] = 0; + + texturecompositesize[texnum] = 0; + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + + // Now count the number of columns + // that are covered by more than one patch. + // Fill in the lump / offset, so columns + // with only a single patch are all done. + patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); + memset (patchcount, 0, texture->width); + + for (i=0 , patch = texture->patches; + ipatchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1 < 0) + x = 0; + else + x = x1; + + if (x2 > texture->width) + x2 = texture->width; + for ( ; xpatch; + colofs[x] = LONG(realpatch->columnofs[x-x1])+3; + } + } + + for (x=0 ; xwidth ; x++) + { + if (!patchcount[x]) + { + printf ("R_GenerateLookup: column without a patch (%s)\n", + texture->name); + return; + } + // I_Error ("R_GenerateLookup: column without a patch"); + + if (patchcount[x] > 1) + { + // Use the cached block. + collump[x] = -1; + colofs[x] = texturecompositesize[texnum]; + + if (texturecompositesize[texnum] > 0x10000-texture->height) + { + I_Error ("R_GenerateLookup: texture %i is >64k", + texnum); + } + + texturecompositesize[texnum] += texture->height; + } + } + + Z_Free(patchcount); +} + + + + +// +// R_GetColumn +// +byte* +R_GetColumn +( int tex, + int col ) +{ + int lump; + int ofs; + + col &= texturewidthmask[tex]; + lump = texturecolumnlump[tex][col]; + ofs = texturecolumnofs[tex][col]; + + if (lump > 0) + return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs; + + if (!texturecomposite[tex]) + R_GenerateComposite (tex); + + return texturecomposite[tex] + ofs; +} + + +static void GenerateTextureHashTable(void) +{ + texture_t **rover; + int i; + int key; + + textures_hashtable + = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); + + memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); + + // Add all textures to hash table + + for (i=0; iindex = i; + + // Vanilla Doom does a linear search of the texures array + // and stops at the first entry it finds. If there are two + // entries with the same name, the first one in the array + // wins. The new entry must therefore be added at the end + // of the hash chain, so that earlier entries win. + + key = W_LumpNameHash(textures[i]->name) % numtextures; + + rover = &textures_hashtable[key]; + + while (*rover != NULL) + { + rover = &(*rover)->next; + } + + // Hook into hash table + + textures[i]->next = NULL; + *rover = textures[i]; + } +} + + +// +// R_InitTextures +// Initializes the texture list +// with the textures from the world map. +// +void R_InitTextures (void) +{ + maptexture_t* mtexture; + texture_t* texture; + mappatch_t* mpatch; + texpatch_t* patch; + + int i; + int j; + + int* maptex; + int* maptex2; + int* maptex1; + + char name[9]; + char* names; + char* name_p; + + int* patchlookup; + + int nummappatches; + int offset; + int maxoff; + int maxoff2; + int numtextures1; + int numtextures2; + + int* directory; + + int temp1; + int temp2; + int temp3; + + + // Load the patch names from pnames.lmp. + name[8] = 0; + names = W_CacheLumpName (DEH_String("PNAMES"), PU_STATIC); + nummappatches = LONG ( *((int *)names) ); + name_p = names + 4; + patchlookup = Z_Malloc(nummappatches*sizeof(*patchlookup), PU_STATIC, NULL); + + for (i = 0; i < nummappatches; i++) + { + M_StringCopy(name, name_p + i * 8, sizeof(name)); + patchlookup[i] = W_CheckNumForName(name); + } + W_ReleaseLumpName(DEH_String("PNAMES")); + + // Load the map texture definitions from textures.lmp. + // The data is contained in one or two lumps, + // TEXTURE1 for shareware, plus TEXTURE2 for commercial. + maptex = maptex1 = W_CacheLumpName (DEH_String("TEXTURE1"), PU_STATIC); + numtextures1 = LONG(*maptex); + maxoff = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE1"))); + directory = maptex+1; + + if (W_CheckNumForName (DEH_String("TEXTURE2")) != -1) + { + maptex2 = W_CacheLumpName (DEH_String("TEXTURE2"), PU_STATIC); + numtextures2 = LONG(*maptex2); + maxoff2 = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE2"))); + } + else + { + maptex2 = NULL; + numtextures2 = 0; + maxoff2 = 0; + } + numtextures = numtextures1 + numtextures2; + + textures = Z_Malloc (numtextures * sizeof(*textures), PU_STATIC, 0); + texturecolumnlump = Z_Malloc (numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0); + texturecolumnofs = Z_Malloc (numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0); + texturecomposite = Z_Malloc (numtextures * sizeof(*texturecomposite), PU_STATIC, 0); + texturecompositesize = Z_Malloc (numtextures * sizeof(*texturecompositesize), PU_STATIC, 0); + texturewidthmask = Z_Malloc (numtextures * sizeof(*texturewidthmask), PU_STATIC, 0); + textureheight = Z_Malloc (numtextures * sizeof(*textureheight), PU_STATIC, 0); + + // Really complex printing shit... + temp1 = W_GetNumForName (DEH_String("S_START")); // P_??????? + temp2 = W_GetNumForName (DEH_String("S_END")) - 1; + temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64); + + // If stdout is a real console, use the classic vanilla "filling + // up the box" effect, which uses backspace to "step back" inside + // the box. If stdout is a file, don't draw the box. + + if (I_ConsoleStdout()) + { + printf("["); + for (i = 0; i < temp3 + 9; i++) + printf(" "); + printf("]"); + for (i = 0; i < temp3 + 10; i++) + printf("\b"); + } + + for (i=0 ; i maxoff) + I_Error ("R_InitTextures: bad texture directory"); + + mtexture = (maptexture_t *) ( (byte *)maptex + offset); + + texture = textures[i] = + Z_Malloc (sizeof(texture_t) + + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), + PU_STATIC, 0); + + texture->width = SHORT(mtexture->width); + texture->height = SHORT(mtexture->height); + texture->patchcount = SHORT(mtexture->patchcount); + + memcpy (texture->name, mtexture->name, sizeof(texture->name)); + mpatch = &mtexture->patches[0]; + patch = &texture->patches[0]; + + for (j=0 ; jpatchcount ; j++, mpatch++, patch++) + { + patch->originx = SHORT(mpatch->originx); + patch->originy = SHORT(mpatch->originy); + patch->patch = patchlookup[SHORT(mpatch->patch)]; + if (patch->patch == -1) + { + I_Error ("R_InitTextures: Missing patch in texture %s", + texture->name); + } + } + texturecolumnlump[i] = Z_Malloc (texture->width*sizeof(**texturecolumnlump), PU_STATIC,0); + texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(**texturecolumnofs), PU_STATIC,0); + + j = 1; + while (j*2 <= texture->width) + j<<=1; + + texturewidthmask[i] = j-1; + textureheight[i] = texture->height<width)<leftoffset)<topoffset)<name, name, 8) ) + return texture->index; + + texture = texture->next; + } + + return -1; +} + + + +// +// R_TextureNumForName +// Calls R_CheckTextureNumForName, +// aborts with error message. +// +int R_TextureNumForName(const char *name) +{ + int i; + + i = R_CheckTextureNumForName (name); + + if (i==-1) + { + I_Error ("R_TextureNumForName: %s not found", + name); + } + return i; +} + + + + +// +// R_PrecacheLevel +// Preloads all relevant graphics for the level. +// +int flatmemory; +int texturememory; +int spritememory; + +void R_PrecacheLevel (void) +{ + char* flatpresent; + char* texturepresent; + char* spritepresent; + + int i; + int j; + int k; + int lump; + + texture_t* texture; + thinker_t* th; + spriteframe_t* sf; + + if (demoplayback) + return; + + // Precache flats. + flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); + memset (flatpresent,0,numflats); + + for (i=0 ; isize; + W_CacheLumpNum(lump, PU_CACHE); + } + } + + Z_Free(flatpresent); + + // Precache textures. + texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); + memset (texturepresent,0, numtextures); + + for (i=0 ; ipatchcount ; j++) + { + lump = texture->patches[j].patch; + texturememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump , PU_CACHE); + } + } + + Z_Free(texturepresent); + + // Precache sprites. + spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); + memset (spritepresent,0, numsprites); + + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + spritepresent[((mobj_t *)th)->sprite] = 1; + } + + spritememory = 0; + for (i=0 ; ilump[k]; + spritememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump , PU_CACHE); + } + } + } + + Z_Free(spritepresent); +} + + + + diff --git a/games/NXDoom/src/doom/r_data.h b/games/NXDoom/src/doom/r_data.h new file mode 100644 index 00000000000..1b273088d50 --- /dev/null +++ b/games/NXDoom/src/doom/r_data.h @@ -0,0 +1,55 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh module, data I/O, caching, retrieval of graphics +// by name. +// + + +#ifndef __R_DATA__ +#define __R_DATA__ + +#include "r_defs.h" +#include "r_state.h" + + +// Retrieve column data for span blitting. +byte* +R_GetColumn +( int tex, + int col ); + + +// I/O, setting up the stuff. +void R_InitData (void); +void R_PrecacheLevel (void); + + +// Retrieval. +// Floor/ceiling opaque texture tiles, +// lookup by name. For animation? +int R_FlatNumForName(const char *name); + + +// Called by P_Ticker for switches and animations, +// returns the texture number for the texture name. +int R_TextureNumForName(const char *name); +int R_CheckTextureNumForName(const char *name); + + +extern int numflats; + + +#endif diff --git a/games/NXDoom/src/doom/r_defs.h b/games/NXDoom/src/doom/r_defs.h new file mode 100644 index 00000000000..d87ca38a9f6 --- /dev/null +++ b/games/NXDoom/src/doom/r_defs.h @@ -0,0 +1,448 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh/rendering module, shared data struct definitions. +// + + +#ifndef __R_DEFS__ +#define __R_DEFS__ + + +// Screenwidth. +#include "doomdef.h" + +// Some more or less basic data types +// we depend on. +#include "m_fixed.h" + +// We rely on the thinker data struct +// to handle sound origins in sectors. +#include "d_think.h" +// SECTORS do store MObjs anyway. +#include "p_mobj.h" + +#include "i_video.h" + +#include "v_patch.h" + + + + +// Silhouette, needed for clipping Segs (mainly) +// and sprites representing things. +#define SIL_NONE 0 +#define SIL_BOTTOM 1 +#define SIL_TOP 2 +#define SIL_BOTH 3 + +#define MAXDRAWSEGS 256 + + + + + +// +// INTERNAL MAP TYPES +// used by play and refresh +// + +// +// Your plain vanilla vertex. +// Note: transformed values not buffered locally, +// like some DOOM-alikes ("wt", "WebView") did. +// +typedef struct +{ + fixed_t x; + fixed_t y; + +} vertex_t; + + +// Forward of LineDefs, for Sectors. +struct line_s; + +// Each sector has a degenmobj_t in its center +// for sound origin purposes. +// I suppose this does not handle sound from +// moving objects (doppler), because +// position is prolly just buffered, not +// updated. +typedef struct +{ + thinker_t thinker; // not used for anything + fixed_t x; + fixed_t y; + fixed_t z; + +} degenmobj_t; + +// +// The SECTORS record, at runtime. +// Stores things/mobjs. +// +typedef struct +{ + fixed_t floorheight; + fixed_t ceilingheight; + short floorpic; + short ceilingpic; + short lightlevel; + short special; + short tag; + + // 0 = untraversed, 1,2 = sndlines -1 + int soundtraversed; + + // thing that made a sound (or null) + mobj_t* soundtarget; + + // mapblock bounding box for height changes + int blockbox[4]; + + // origin for any sounds played by the sector + degenmobj_t soundorg; + + // if == validcount, already checked + int validcount; + + // list of mobjs in sector + mobj_t* thinglist; + + // thinker_t for reversable actions + void* specialdata; + + int linecount; + struct line_s** lines; // [linecount] size + +} sector_t; + + + + +// +// The SideDef. +// + +typedef struct +{ + // add this to the calculated texture column + fixed_t textureoffset; + + // add this to the calculated texture top + fixed_t rowoffset; + + // Texture indices. + // We do not maintain names here. + short toptexture; + short bottomtexture; + short midtexture; + + // Sector the SideDef is facing. + sector_t* sector; + +} side_t; + + + +// +// Move clipping aid for LineDefs. +// +typedef enum +{ + ST_HORIZONTAL, + ST_VERTICAL, + ST_POSITIVE, + ST_NEGATIVE + +} slopetype_t; + + + +typedef struct line_s +{ + // Vertices, from v1 to v2. + vertex_t* v1; + vertex_t* v2; + + // Precalculated v2 - v1 for side checking. + fixed_t dx; + fixed_t dy; + + // Animation related. + short flags; + short special; + short tag; + + // Visual appearance: SideDefs. + // sidenum[1] will be -1 if one sided + short sidenum[2]; + + // Neat. Another bounding box, for the extent + // of the LineDef. + fixed_t bbox[4]; + + // To aid move clipping. + slopetype_t slopetype; + + // Front and back sector. + // Note: redundant? Can be retrieved from SideDefs. + sector_t* frontsector; + sector_t* backsector; + + // if == validcount, already checked + int validcount; + + // thinker_t for reversable actions + void* specialdata; +} line_t; + + + + +// +// A SubSector. +// References a Sector. +// Basically, this is a list of LineSegs, +// indicating the visible walls that define +// (all or some) sides of a convex BSP leaf. +// +typedef struct subsector_s +{ + sector_t* sector; + short numlines; + short firstline; + +} subsector_t; + + + +// +// The LineSeg. +// +typedef struct +{ + vertex_t* v1; + vertex_t* v2; + + fixed_t offset; + + angle_t angle; + + side_t* sidedef; + line_t* linedef; + + // Sector references. + // Could be retrieved from linedef, too. + // backsector is NULL for one sided lines + sector_t* frontsector; + sector_t* backsector; + +} seg_t; + + + +// +// BSP node. +// +typedef struct +{ + // Partition line. + fixed_t x; + fixed_t y; + fixed_t dx; + fixed_t dy; + + // Bounding box for each child. + fixed_t bbox[2][4]; + + // If NF_SUBSECTOR its a subsector. + unsigned short children[2]; + +} node_t; + + + + +// PC direct to screen pointers +//B UNUSED - keep till detailshift in r_draw.c resolved +//extern byte* destview; +//extern byte* destscreen; + + + + + +// +// OTHER TYPES +// + +// This could be wider for >8 bit display. +// Indeed, true color support is posibble +// precalculating 24bpp lightmap/colormap LUT. +// from darkening PLAYPAL to all black. +// Could even us emore than 32 levels. +typedef pixel_t lighttable_t; + + + + +// +// ? +// +typedef struct drawseg_s +{ + seg_t* curline; + int x1; + int x2; + + fixed_t scale1; + fixed_t scale2; + fixed_t scalestep; + + // 0=none, 1=bottom, 2=top, 3=both + int silhouette; + + // do not clip sprites above this + fixed_t bsilheight; + + // do not clip sprites below this + fixed_t tsilheight; + + // Pointers to lists for sprite clipping, + // all three adjusted so [x1] is first value. + short* sprtopclip; + short* sprbottomclip; + short* maskedtexturecol; + +} drawseg_t; + + + +// A vissprite_t is a thing +// that will be drawn during a refresh. +// I.e. a sprite object that is partly visible. +typedef struct vissprite_s +{ + // Doubly linked list. + struct vissprite_s* prev; + struct vissprite_s* next; + + int x1; + int x2; + + // for line side calculation + fixed_t gx; + fixed_t gy; + + // global bottom / top for silhouette clipping + fixed_t gz; + fixed_t gzt; + + // horizontal position of x1 + fixed_t startfrac; + + fixed_t scale; + + // negative if flipped + fixed_t xiscale; + + fixed_t texturemid; + int patch; + + // for color translation and shadow draw, + // maxbright frames as well + lighttable_t* colormap; + + int mobjflags; + +} vissprite_t; + + +// +// Sprites are patches with a special naming convention +// so they can be recognized by R_InitSprites. +// The base name is NNNNFx or NNNNFxFx, with +// x indicating the rotation, x = 0, 1-7. +// The sprite and frame specified by a thing_t +// is range checked at run time. +// A sprite is a patch_t that is assumed to represent +// a three dimensional object and may have multiple +// rotations pre drawn. +// Horizontal flipping is used to save space, +// thus NNNNF2F5 defines a mirrored patch. +// Some sprites will only have one picture used +// for all views: NNNNF0 +// +typedef struct +{ + // If false use 0 for any position. + // Note: as eight entries are available, + // we might as well insert the same name eight times. + boolean rotate; + + // Lump to use for view angles 0-7. + short lump[8]; + + // Flip bit (1 = flip) to use for view angles 0-7. + byte flip[8]; + +} spriteframe_t; + + + +// +// A sprite definition: +// a number of animation frames. +// +typedef struct +{ + int numframes; + spriteframe_t* spriteframes; + +} spritedef_t; + + + +// +// Now what is a visplane, anyway? +// +typedef struct +{ + fixed_t height; + int picnum; + int lightlevel; + int minx; + int maxx; + + // leave pads for [minx-1]/[maxx+1] + + byte pad1; + // Here lies the rub for all + // dynamic resize/change of resolution. + byte top[SCREENWIDTH]; + byte pad2; + byte pad3; + // See above. + byte bottom[SCREENWIDTH]; + byte pad4; + +} visplane_t; + + + + +#endif diff --git a/games/NXDoom/src/doom/r_draw.c b/games/NXDoom/src/doom/r_draw.c new file mode 100644 index 00000000000..4fc41b5d51e --- /dev/null +++ b/games/NXDoom/src/doom/r_draw.c @@ -0,0 +1,959 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The actual span/column drawing functions. +// Here find the main potential for optimization, +// e.g. inline assembly, different algorithms. +// + + + + +#include "doomdef.h" +#include "deh_main.h" + +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" + +#include "r_local.h" + +// Needs access to LFB (guess what). +#include "v_video.h" + +// State. +#include "doomstat.h" + + +// ? +#define MAXWIDTH 1120 +#define MAXHEIGHT 832 + +// status bar height at bottom of screen +#define SBARHEIGHT 32 + +// +// All drawing to the view buffer is accomplished in this file. +// The other refresh files only know about ccordinates, +// not the architecture of the frame buffer. +// Conveniently, the frame buffer is a linear one, +// and we need only the base address, +// and the total size == width*height*depth/8., +// + + +byte* viewimage; +int viewwidth; +int scaledviewwidth; +int viewheight; +int viewwindowx; +int viewwindowy; +pixel_t* ylookup[MAXHEIGHT]; +int columnofs[MAXWIDTH]; + +// Color tables for different players, +// translate a limited part to another +// (color ramps used for suit colors). +// +byte translations[3][256]; + +// Backing buffer containing the bezel drawn around the screen and +// surrounding background. + +static pixel_t *background_buffer = NULL; + + +// +// R_DrawColumn +// Source is the top of the column to scale. +// +lighttable_t* dc_colormap; +int dc_x; +int dc_yl; +int dc_yh; +fixed_t dc_iscale; +fixed_t dc_texturemid; + +// first pixel in a column (possibly virtual) +byte* dc_source; + +// just for profiling +int dccount; + +// +// A column is a vertical slice/span from a wall texture that, +// given the DOOM style restrictions on the view orientation, +// will always have constant z depth. +// Thus a special case loop for very fast rendering can +// be used. It has also been used with Wolfenstein 3D. +// +void R_DrawColumn (void) +{ + int count; + pixel_t* dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + // Zero length, column does not exceed a pixel. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + // Framebuffer destination address. + // Use ylookup LUT to avoid multiply with ScreenWidth. + // Use columnofs LUT for subwindows? + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Determine scaling, + // which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + // Inner loop that does the actual texture mapping, + // e.g. a DDA-lile scaling. + // This is as fast as it gets. + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; + + dest += SCREENWIDTH; + frac += fracstep; + + } while (count--); +} + + + +// UNUSED. +// Loop unrolled. +#if 0 +void R_DrawColumn (void) +{ + int count; + byte* source; + byte* dest; + byte* colormap; + + unsigned frac; + unsigned fracstep; + unsigned fracstep2; + unsigned fracstep3; + unsigned fracstep4; + + count = dc_yh - dc_yl + 1; + + source = dc_source; + colormap = dc_colormap; + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale<<9; + frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; + + fracstep2 = fracstep+fracstep; + fracstep3 = fracstep2+fracstep; + fracstep4 = fracstep3+fracstep; + + while (count >= 8) + { + dest[0] = colormap[source[frac>>25]]; + dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; + dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; + dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]]; + + frac += fracstep4; + + dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; + dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; + dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; + dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; + + frac += fracstep4; + dest += SCREENWIDTH*8; + count -= 8; + } + + while (count > 0) + { + *dest = colormap[source[frac>>25]]; + dest += SCREENWIDTH; + frac += fracstep; + count--; + } +} +#endif + + +void R_DrawColumnLow (void) +{ + int count; + pixel_t* dest; + pixel_t* dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + { + + I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } + // dccount++; +#endif + // Blocky mode, need to multiply by 2. + x = dc_x << 1; + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x+1]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + do + { + // Hack. Does not work corretly. + *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + frac += fracstep; + + } while (count--); +} + + +// +// Spectre/Invisibility. +// +#define FUZZTABLE 50 +#define FUZZOFF (SCREENWIDTH) + + +int fuzzoffset[FUZZTABLE] = +{ + FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, + FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, + FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF, + FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, + FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF, + FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF, + FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF +}; + +int fuzzpos = 0; + + +// +// Framebuffer postprocessing. +// Creates a fuzzy image by copying pixels +// from adjacent ones to left and right. +// Used with an all black colormap, this +// could create the SHADOW effect, +// i.e. spectres and invisible players. +// +void R_DrawFuzzColumn (void) +{ + int count; + pixel_t* dest; + + // Adjust borders. Low... + if (!dc_yl) + dc_yl = 1; + + // .. and high. + if (dc_yh == viewheight-1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + { + I_Error ("R_DrawFuzzColumn: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks like an attempt at dithering, + // using the colormap #6 (of 0-31, a bit + // brighter than average). + do + { + // Lookup framebuffer, and retrieve + // a pixel that is either one column + // left or right of the current one. + // Add index from colormap to index. + *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; + + // Clamp table lookup index. + if (++fuzzpos == FUZZTABLE) + fuzzpos = 0; + + dest += SCREENWIDTH; + } while (count--); +} + +// low detail mode version + +void R_DrawFuzzColumnLow (void) +{ + int count; + pixel_t* dest; + pixel_t* dest2; + int x; + + // Adjust borders. Low... + if (!dc_yl) + dc_yl = 1; + + // .. and high. + if (dc_yh == viewheight-1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + + // low detail mode, need to multiply by 2 + + x = dc_x << 1; + +#ifdef RANGECHECK + if ((unsigned)x >= SCREENWIDTH + || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + { + I_Error ("R_DrawFuzzColumn: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } +#endif + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x+1]; + + // Looks like an attempt at dithering, + // using the colormap #6 (of 0-31, a bit + // brighter than average). + do + { + // Lookup framebuffer, and retrieve + // a pixel that is either one column + // left or right of the current one. + // Add index from colormap to index. + *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; + *dest2 = colormaps[6*256+dest2[fuzzoffset[fuzzpos]]]; + + // Clamp table lookup index. + if (++fuzzpos == FUZZTABLE) + fuzzpos = 0; + + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + } while (count--); +} + + + + + +// +// R_DrawTranslatedColumn +// Used to draw player sprites +// with the green colorramp mapped to others. +// Could be used with different translation +// tables, e.g. the lighter colored version +// of the BaronOfHell, the HellKnight, uses +// identical sprites, kinda brightened up. +// +byte* dc_translation; +byte* translationtables; + +void R_DrawTranslatedColumn (void) +{ + int count; + pixel_t* dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + { + I_Error ( "R_DrawColumn: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } + +#endif + + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + // Here we do an additional index re-mapping. + do + { + // Translation tables are used + // to map certain colorramps to other ones, + // used with PLAY sprites. + // Thus the "green" ramp of the player 0 sprite + // is mapped to gray, red, black/indigo. + *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + dest += SCREENWIDTH; + + frac += fracstep; + } while (count--); +} + +void R_DrawTranslatedColumnLow (void) +{ + int count; + pixel_t* dest; + pixel_t* dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + count = dc_yh - dc_yl; + if (count < 0) + return; + + // low detail, need to scale by 2 + x = dc_x << 1; + +#ifdef RANGECHECK + if ((unsigned)x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + { + I_Error ( "R_DrawColumn: %i to %i at %i", + dc_yl, dc_yh, x); + } + +#endif + + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x+1]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + // Here we do an additional index re-mapping. + do + { + // Translation tables are used + // to map certain colorramps to other ones, + // used with PLAY sprites. + // Thus the "green" ramp of the player 0 sprite + // is mapped to gray, red, black/indigo. + *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + *dest2 = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + + frac += fracstep; + } while (count--); +} + + + + +// +// R_InitTranslationTables +// Creates the translation tables to map +// the green color ramp to gray, brown, red. +// Assumes a given structure of the PLAYPAL. +// Could be read from a lump instead. +// +void R_InitTranslationTables (void) +{ + int i; + + translationtables = Z_Malloc (256*3, PU_STATIC, 0); + + // translate just the 16 green colors + for (i=0 ; i<256 ; i++) + { + if (i >= 0x70 && i<= 0x7f) + { + // map green ramp to gray, brown, red + translationtables[i] = 0x60 + (i&0xf); + translationtables [i+256] = 0x40 + (i&0xf); + translationtables [i+512] = 0x20 + (i&0xf); + } + else + { + // Keep all other colors as is. + translationtables[i] = translationtables[i+256] + = translationtables[i+512] = i; + } + } +} + + + + +// +// R_DrawSpan +// With DOOM style restrictions on view orientation, +// the floors and ceilings consist of horizontal slices +// or spans with constant z depth. +// However, rotation around the world z axis is possible, +// thus this mapping, while simpler and faster than +// perspective correct texture mapping, has to traverse +// the texture at an angle in all but a few cases. +// In consequence, flats are not stored by column (like walls), +// and the inner loop has to step in texture space u and v. +// +int ds_y; +int ds_x1; +int ds_x2; + +lighttable_t* ds_colormap; + +fixed_t ds_xfrac; +fixed_t ds_yfrac; +fixed_t ds_xstep; +fixed_t ds_ystep; + +// start of a 64*64 tile image +byte* ds_source; + +// just for profiling +int dscount; + + +// +// Draws the actual span. +void R_DrawSpan (void) +{ + unsigned int position, step; + pixel_t *dest; + int count; + int spot; + unsigned int xtemp, ytemp; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 + || ds_x1<0 + || ds_x2>=SCREENWIDTH + || (unsigned)ds_y>SCREENHEIGHT) + { + I_Error( "R_DrawSpan: %i to %i at %i", + ds_x1,ds_x2,ds_y); + } +// dscount++; +#endif + + // Pack position and step variables into a single 32-bit integer, + // with x in the top 16 bits and y in the bottom 16 bits. For + // each 16-bit part, the top 6 bits are the integer part and the + // bottom 10 bits are the fractional part of the pixel position. + + position = ((ds_xfrac << 10) & 0xffff0000) + | ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) + | ((ds_ystep >> 6) & 0x0000ffff); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + + // We do not check for zero spans here? + count = ds_x2 - ds_x1; + + do + { + // Calculate current texture index in u,v. + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + // Lookup pixel from flat texture tile, + // re-index using light/colormap. + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + + } while (count--); +} + + + +// UNUSED. +// Loop unrolled by 4. +#if 0 +void R_DrawSpan (void) +{ + unsigned position, step; + + byte* source; + byte* colormap; + pixel_t* dest; + + unsigned count; + usingned spot; + unsigned value; + unsigned temp; + unsigned xtemp; + unsigned ytemp; + + position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff); + step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff); + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; + + while (count >= 4) + { + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[0] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[1] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[2] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[3] = colormap[source[spot]]; + + count -= 4; + dest += 4; + } + while (count > 0) + { + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + *dest++ = colormap[source[spot]]; + count--; + } +} +#endif + + +// +// Again.. +// +void R_DrawSpanLow (void) +{ + unsigned int position, step; + unsigned int xtemp, ytemp; + pixel_t *dest; + int count; + int spot; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 + || ds_x1<0 + || ds_x2>=SCREENWIDTH + || (unsigned)ds_y>SCREENHEIGHT) + { + I_Error( "R_DrawSpan: %i to %i at %i", + ds_x1,ds_x2,ds_y); + } +// dscount++; +#endif + + position = ((ds_xfrac << 10) & 0xffff0000) + | ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) + | ((ds_ystep >> 6) & 0x0000ffff); + + count = (ds_x2 - ds_x1); + + // Blocky mode, need to multiply by 2. + ds_x1 <<= 1; + ds_x2 <<= 1; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + + do + { + // Calculate current texture index in u,v. + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + // Lowres/blocky mode does it twice, + // while scale is adjusted appropriately. + *dest++ = ds_colormap[ds_source[spot]]; + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + + } while (count--); +} + +// +// R_InitBuffer +// Creats lookup tables that avoid +// multiplies and other hazzles +// for getting the framebuffer address +// of a pixel to draw. +// +void +R_InitBuffer +( int width, + int height ) +{ + int i; + + // Handle resize, + // e.g. smaller view windows + // with border and/or status bar. + viewwindowx = (SCREENWIDTH-width) >> 1; + + // Column offset. For windows. + for (i=0 ; i> 1; + + // Preclaculate all row offsets. + for (i=0 ; i +#include + + +#include "doomdef.h" +#include "d_loop.h" + +#include "m_bbox.h" +#include "m_menu.h" + +#include "r_local.h" +#include "r_sky.h" + + + + + +// Fineangles in the SCREENWIDTH wide window. +#define FIELDOFVIEW 2048 + + + +int viewangleoffset; + +// increment every time a check is made +int validcount = 1; + + +lighttable_t* fixedcolormap; + +int centerx; +int centery; + +fixed_t centerxfrac; +fixed_t centeryfrac; +fixed_t projection; + +// just for profiling purposes +int framecount; + +int sscount; +int linecount; +int loopcount; + +fixed_t viewx; +fixed_t viewy; +fixed_t viewz; + +angle_t viewangle; + +fixed_t viewcos; +fixed_t viewsin; + +player_t* viewplayer; + +// 0 = high, 1 = low +int detailshift; + +// +// precalculated math tables +// +angle_t clipangle; + +// The viewangletox[viewangle + FINEANGLES/4] lookup +// maps the visible view angles to screen X coordinates, +// flattening the arc to a flat projection plane. +// There will be many angles mapped to the same X. +int viewangletox[FINEANGLES/2]; + +// The xtoviewangleangle[] table maps a screen pixel +// to the lowest viewangle that maps back to x ranges +// from clipangle to -clipangle. +angle_t xtoviewangle[SCREENWIDTH+1]; + +lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +lighttable_t* scalelightfixed[MAXLIGHTSCALE]; +lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ]; + +// bumped light from gun blasts +int extralight; + + + +void (*colfunc) (void); +void (*basecolfunc) (void); +void (*fuzzcolfunc) (void); +void (*transcolfunc) (void); +void (*spanfunc) (void); + + + +// +// R_AddPointToBox +// Expand a given bbox +// so that it encloses a given point. +// +void +R_AddPointToBox +( int x, + int y, + fixed_t* box ) +{ + if (x< box[BOXLEFT]) + box[BOXLEFT] = x; + if (x> box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y< box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + if (y> box[BOXTOP]) + box[BOXTOP] = y; +} + + +// +// R_PointOnSide +// Traverse BSP (sub) tree, +// check point against partition plane. +// Returns side 0 (front) or 1 (back). +// +int +R_PointOnSide +( fixed_t x, + fixed_t y, + node_t* node ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!node->dx) + { + if (x <= node->x) + return node->dy > 0; + + return node->dy < 0; + } + if (!node->dy) + { + if (y <= node->y) + return node->dx < 0; + + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + + // Try to quickly decide by looking at sign bits. + if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 ) + { + if ( (node->dy ^ dx) & 0x80000000 ) + { + // (left is negative) + return 1; + } + return 0; + } + + left = FixedMul ( node->dy>>FRACBITS , dx ); + right = FixedMul ( dy , node->dx>>FRACBITS ); + + if (right < left) + { + // front side + return 0; + } + // back side + return 1; +} + + +int +R_PointOnSegSide +( fixed_t x, + fixed_t y, + seg_t* line ) +{ + fixed_t lx; + fixed_t ly; + fixed_t ldx; + fixed_t ldy; + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + lx = line->v1->x; + ly = line->v1->y; + + ldx = line->v2->x - lx; + ldy = line->v2->y - ly; + + if (!ldx) + { + if (x <= lx) + return ldy > 0; + + return ldy < 0; + } + if (!ldy) + { + if (y <= ly) + return ldx < 0; + + return ldx > 0; + } + + dx = (x - lx); + dy = (y - ly); + + // Try to quickly decide by looking at sign bits. + if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 ) + { + if ( (ldy ^ dx) & 0x80000000 ) + { + // (left is negative) + return 1; + } + return 0; + } + + left = FixedMul ( ldy>>FRACBITS , dx ); + right = FixedMul ( dy , ldx>>FRACBITS ); + + if (right < left) + { + // front side + return 0; + } + // back side + return 1; +} + + +// +// R_PointToAngle +// To get a global angle from cartesian coordinates, +// the coordinates are flipped until they are in +// the first octant of the coordinate system, then +// the y (<=x) is scaled and divided by x to get a +// tangent (slope) value which is looked up in the +// tantoangle[] table. + +// + + + + +angle_t +R_PointToAngle +( fixed_t x, + fixed_t y ) +{ + x -= viewx; + y -= viewy; + + if ( (!x) && (!y) ) + return 0; + + if (x>= 0) + { + // x >=0 + if (y>= 0) + { + // y>= 0 + + if (x>y) + { + // octant 0 + return tantoangle[ SlopeDiv(y,x)]; + } + else + { + // octant 1 + return ANG90-1-tantoangle[ SlopeDiv(x,y)]; + } + } + else + { + // y<0 + y = -y; + + if (x>y) + { + // octant 8 + return -tantoangle[SlopeDiv(y,x)]; + } + else + { + // octant 7 + return ANG270+tantoangle[ SlopeDiv(x,y)]; + } + } + } + else + { + // x<0 + x = -x; + + if (y>= 0) + { + // y>= 0 + if (x>y) + { + // octant 3 + return ANG180-1-tantoangle[ SlopeDiv(y,x)]; + } + else + { + // octant 2 + return ANG90+ tantoangle[ SlopeDiv(x,y)]; + } + } + else + { + // y<0 + y = -y; + + if (x>y) + { + // octant 4 + return ANG180+tantoangle[ SlopeDiv(y,x)]; + } + else + { + // octant 5 + return ANG270-1-tantoangle[ SlopeDiv(x,y)]; + } + } + } + return 0; +} + + +angle_t +R_PointToAngle2 +( fixed_t x1, + fixed_t y1, + fixed_t x2, + fixed_t y2 ) +{ + viewx = x1; + viewy = y1; + + return R_PointToAngle (x2, y2); +} + + +fixed_t +R_PointToDist +( fixed_t x, + fixed_t y ) +{ + int angle; + fixed_t dx; + fixed_t dy; + fixed_t temp; + fixed_t dist; + fixed_t frac; + + dx = abs(x - viewx); + dy = abs(y - viewy); + + if (dy>dx) + { + temp = dx; + dx = dy; + dy = temp; + } + + // Fix crashes in udm1.wad + + if (dx != 0) + { + frac = FixedDiv(dy, dx); + } + else + { + frac = 0; + } + + angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT; + + // use as cosine + dist = FixedDiv (dx, finesine[angle] ); + + return dist; +} + + + + +// +// R_InitPointToAngle +// +void R_InitPointToAngle (void) +{ + // UNUSED - now getting from tables.c +#if 0 + int i; + long t; + float f; +// +// slope (tangent) to angle lookup +// + for (i=0 ; i<=SLOPERANGE ; i++) + { + f = atan( (float)i/SLOPERANGE )/(3.141592657*2); + t = 0xffffffff*f; + tantoangle[i] = t; + } +#endif +} + + +// +// R_ScaleFromGlobalAngle +// Returns the texture mapping scale +// for the current line (horizontal span) +// at the given angle. +// rw_distance must be calculated first. +// +fixed_t R_ScaleFromGlobalAngle (angle_t visangle) +{ + fixed_t scale; + angle_t anglea; + angle_t angleb; + int sinea; + int sineb; + fixed_t num; + int den; + + // UNUSED +#if 0 +{ + fixed_t dist; + fixed_t z; + fixed_t sinv; + fixed_t cosv; + + sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; + dist = FixedDiv (rw_distance, sinv); + cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; + z = abs(FixedMul (dist, cosv)); + scale = FixedDiv(projection, z); + return scale; +} +#endif + + anglea = ANG90 + (visangle-viewangle); + angleb = ANG90 + (visangle-rw_normalangle); + + // both sines are allways positive + sinea = finesine[anglea>>ANGLETOFINESHIFT]; + sineb = finesine[angleb>>ANGLETOFINESHIFT]; + num = FixedMul(projection,sineb)< num>>FRACBITS) + { + scale = FixedDiv (num, den); + + if (scale > 64*FRACUNIT) + scale = 64*FRACUNIT; + else if (scale < 256) + scale = 256; + } + else + scale = 64*FRACUNIT; + + return scale; +} + + + +// +// R_InitTables +// +void R_InitTables (void) +{ + // UNUSED: now getting from tables.c +#if 0 + int i; + float a; + float fv; + int t; + + // viewangle tangent table + for (i=0 ; i FRACUNIT*2) + t = -1; + else if (finetangent[i] < -FRACUNIT*2) + t = viewwidth+1; + else + { + t = FixedMul (finetangent[i], focallength); + t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS; + + if (t < -1) + t = -1; + else if (t>viewwidth+1) + t = viewwidth+1; + } + viewangletox[i] = t; + } + + // Scan viewangletox[] to generate xtoviewangle[]: + // xtoviewangle will give the smallest view angle + // that maps to x. + for (x=0;x<=viewwidth;x++) + { + i = 0; + while (viewangletox[i]>x) + i++; + xtoviewangle[x] = (i<>= LIGHTSCALESHIFT; + level = startmap - scale/DISTMAP; + + if (level < 0) + level = 0; + + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS-1; + + zlight[i][j] = colormaps + level*256; + } + } +} + + + +// +// R_SetViewSize +// Do not really change anything here, +// because it might be in the middle of a refresh. +// The change will take effect next refresh. +// +boolean setsizeneeded; +int setblocks; +int setdetail; + + +void +R_SetViewSize +( int blocks, + int detail ) +{ + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; +} + + +// +// R_ExecuteSetViewSize +// +void R_ExecuteSetViewSize (void) +{ + fixed_t cosadj; + fixed_t dy; + int i; + int j; + int level; + int startmap; + + setsizeneeded = false; + + if (setblocks == 11) + { + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; + } + else + { + scaledviewwidth = setblocks*32; + viewheight = (setblocks*168/10)&~7; + } + + detailshift = setdetail; + viewwidth = scaledviewwidth>>detailshift; + + centery = viewheight/2; + centerx = viewwidth/2; + centerxfrac = centerx<>ANGLETOFINESHIFT]); + distscale[i] = FixedDiv (FRACUNIT,cosadj); + } + + // Calculate the light levels to use + // for each level / scale combination. + for (i=0 ; i< LIGHTLEVELS ; i++) + { + startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; + for (j=0 ; j= NUMCOLORMAPS) + level = NUMCOLORMAPS-1; + + scalelight[i][j] = colormaps + level*256; + } + } +} + + + +// +// R_Init +// + + + +void R_Init (void) +{ + R_InitData (); + printf ("."); + R_InitPointToAngle (); + printf ("."); + R_InitTables (); + // viewwidth / viewheight / detailLevel are set by the defaults + printf ("."); + + R_SetViewSize (screenblocks, detailLevel); + R_InitPlanes (); + printf ("."); + R_InitLightTables (); + printf ("."); + R_InitSkyMap (); + R_InitTranslationTables (); + printf ("."); + + framecount = 0; +} + + +// +// R_PointInSubsector +// +subsector_t* +R_PointInSubsector +( fixed_t x, + fixed_t y ) +{ + node_t* node; + int side; + int nodenum; + + // single subsector is a special case + if (!numnodes) + return subsectors; + + nodenum = numnodes-1; + + while (! (nodenum & NF_SUBSECTOR) ) + { + node = &nodes[nodenum]; + side = R_PointOnSide (x, y, node); + nodenum = node->children[side]; + } + + return &subsectors[nodenum & ~NF_SUBSECTOR]; +} + + + +// +// R_SetupFrame +// +void R_SetupFrame (player_t* player) +{ + int i; + + viewplayer = player; + viewx = player->mo->x; + viewy = player->mo->y; + viewangle = player->mo->angle + viewangleoffset; + extralight = player->extralight; + + viewz = player->viewz; + + viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; + viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; + + sscount = 0; + + if (player->fixedcolormap) + { + fixedcolormap = + colormaps + + player->fixedcolormap*256; + + walllights = scalelightfixed; + + for (i=0 ; i +#include + +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" + +#include "doomdef.h" +#include "doomstat.h" + +#include "r_local.h" +#include "r_sky.h" + + + +planefunction_t floorfunc; +planefunction_t ceilingfunc; + +// +// opening +// + +// Here comes the obnoxious "visplane". +#define MAXVISPLANES 128 +visplane_t visplanes[MAXVISPLANES]; +visplane_t* lastvisplane; +visplane_t* floorplane; +visplane_t* ceilingplane; + +// ? +#define MAXOPENINGS SCREENWIDTH*64 +short openings[MAXOPENINGS]; +short* lastopening; + + +// +// Clip values are the solid pixel bounding the range. +// floorclip starts out SCREENHEIGHT +// ceilingclip starts out -1 +// +short floorclip[SCREENWIDTH]; +short ceilingclip[SCREENWIDTH]; + +// +// spanstart holds the start of a plane span +// initialized to 0 at start +// +int spanstart[SCREENHEIGHT]; +int spanstop[SCREENHEIGHT]; + +// +// texture mapping +// +lighttable_t** planezlight; +fixed_t planeheight; + +fixed_t yslope[SCREENHEIGHT]; +fixed_t distscale[SCREENWIDTH]; +fixed_t basexscale; +fixed_t baseyscale; + +fixed_t cachedheight[SCREENHEIGHT]; +fixed_t cacheddistance[SCREENHEIGHT]; +fixed_t cachedxstep[SCREENHEIGHT]; +fixed_t cachedystep[SCREENHEIGHT]; + + + +// +// R_InitPlanes +// Only at game startup. +// +void R_InitPlanes (void) +{ + // Doh! +} + + +// +// R_MapPlane +// +// Uses global vars: +// planeheight +// ds_source +// basexscale +// baseyscale +// viewx +// viewy +// +// BASIC PRIMITIVE +// +void +R_MapPlane +( int y, + int x1, + int x2 ) +{ + angle_t angle; + fixed_t distance; + fixed_t length; + unsigned index; + +#ifdef RANGECHECK + if (x2 < x1 + || x1 < 0 + || x2 >= viewwidth + || y > viewheight) + { + I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); + } +#endif + + if (planeheight != cachedheight[y]) + { + cachedheight[y] = planeheight; + distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]); + ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale); + ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale); + } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + length = FixedMul (distance,distscale[x1]); + angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; + ds_xfrac = viewx + FixedMul(finecosine[angle], length); + ds_yfrac = -viewy - FixedMul(finesine[angle], length); + + if (fixedcolormap) + ds_colormap = fixedcolormap; + else + { + index = distance >> LIGHTZSHIFT; + + if (index >= MAXLIGHTZ ) + index = MAXLIGHTZ-1; + + ds_colormap = planezlight[index]; + } + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + // high or low detail + spanfunc (); +} + + +// +// R_ClearPlanes +// At begining of frame. +// +void R_ClearPlanes (void) +{ + int i; + angle_t angle; + + // opening / clipping determination + for (i=0 ; i>ANGLETOFINESHIFT; + + // scale will be unit scale at SCREENWIDTH/2 distance + basexscale = FixedDiv (finecosine[angle],centerxfrac); + baseyscale = -FixedDiv (finesine[angle],centerxfrac); +} + + + + +// +// R_FindPlane +// +visplane_t* +R_FindPlane +( fixed_t height, + int picnum, + int lightlevel ) +{ + visplane_t* check; + + if (picnum == skyflatnum) + { + height = 0; // all skys map together + lightlevel = 0; + } + + for (check=visplanes; checkheight + && picnum == check->picnum + && lightlevel == check->lightlevel) + { + break; + } + } + + + if (check < lastvisplane) + return check; + + if (lastvisplane - visplanes == MAXVISPLANES) + I_Error ("R_FindPlane: no more visplanes"); + + lastvisplane++; + + check->height = height; + check->picnum = picnum; + check->lightlevel = lightlevel; + check->minx = SCREENWIDTH; + check->maxx = -1; + + memset (check->top,0xff,sizeof(check->top)); + + return check; +} + + +// +// R_CheckPlane +// +visplane_t* +R_CheckPlane +( visplane_t* pl, + int start, + int stop ) +{ + int intrl; + int intrh; + int unionl; + int unionh; + int x; + + if (start < pl->minx) + { + intrl = pl->minx; + unionl = start; + } + else + { + unionl = pl->minx; + intrl = start; + } + + if (stop > pl->maxx) + { + intrh = pl->maxx; + unionh = stop; + } + else + { + unionh = pl->maxx; + intrh = stop; + } + + for (x=intrl ; x<= intrh ; x++) + if (pl->top[x] != 0xff) + break; + + if (x > intrh) + { + pl->minx = unionl; + pl->maxx = unionh; + + // use the same one + return pl; + } + + // make a new visplane + lastvisplane->height = pl->height; + lastvisplane->picnum = pl->picnum; + lastvisplane->lightlevel = pl->lightlevel; + + if (lastvisplane - visplanes == MAXVISPLANES) + I_Error ("R_CheckPlane: no more visplanes"); + + pl = lastvisplane++; + pl->minx = start; + pl->maxx = stop; + + memset (pl->top,0xff,sizeof(pl->top)); + + return pl; +} + + +// +// R_MakeSpans +// +void +R_MakeSpans +( int x, + int t1, + int b1, + int t2, + int b2 ) +{ + while (t1 < t2 && t1<=b1) + { + R_MapPlane (t1,spanstart[t1],x-1); + t1++; + } + while (b1 > b2 && b1>=t1) + { + R_MapPlane (b1,spanstart[b1],x-1); + b1--; + } + + while (t2 < t1 && t2<=b2) + { + spanstart[t2] = x; + t2++; + } + while (b2 > b1 && b2>=t2) + { + spanstart[b2] = x; + b2--; + } +} + + + +// +// R_DrawPlanes +// At the end of each frame. +// +void R_DrawPlanes (void) +{ + visplane_t* pl; + int light; + int x; + int stop; + int angle; + int lumpnum; + +#ifdef RANGECHECK + if (ds_p - drawsegs > MAXDRAWSEGS) + I_Error ("R_DrawPlanes: drawsegs overflow (%td)", + ds_p - drawsegs); + + if (lastvisplane - visplanes > MAXVISPLANES) + I_Error ("R_DrawPlanes: visplane overflow (%td)", + lastvisplane - visplanes); + + if (lastopening - openings > MAXOPENINGS) + I_Error ("R_DrawPlanes: opening overflow (%td)", + lastopening - openings); +#endif + + for (pl = visplanes ; pl < lastvisplane ; pl++) + { + if (pl->minx > pl->maxx) + continue; + + + // sky flat + if (pl->picnum == skyflatnum) + { + dc_iscale = pspriteiscale>>detailshift; + + // Sky is allways drawn full bright, + // i.e. colormaps[0] is used. + // Because of this hack, sky is not affected + // by INVUL inverse mapping. + dc_colormap = colormaps; + dc_texturemid = skytexturemid; + for (x=pl->minx ; x <= pl->maxx ; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + + if (dc_yl <= dc_yh) + { + angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; + dc_x = x; + dc_source = R_GetColumn(skytexture, angle); + colfunc (); + } + } + continue; + } + + // regular flat + lumpnum = firstflat + flattranslation[pl->picnum]; + ds_source = W_CacheLumpNum(lumpnum, PU_STATIC); + + planeheight = abs(pl->height-viewz); + light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (light >= LIGHTLEVELS) + light = LIGHTLEVELS-1; + + if (light < 0) + light = 0; + + planezlight = zlight[light]; + + pl->top[pl->maxx+1] = 0xff; + pl->top[pl->minx-1] = 0xff; + + stop = pl->maxx + 1; + + for (x=pl->minx ; x<= stop ; x++) + { + R_MakeSpans(x,pl->top[x-1], + pl->bottom[x-1], + pl->top[x], + pl->bottom[x]); + } + + W_ReleaseLumpNum(lumpnum); + } +} diff --git a/games/NXDoom/src/doom/r_plane.h b/games/NXDoom/src/doom/r_plane.h new file mode 100644 index 00000000000..57b50e5bc5e --- /dev/null +++ b/games/NXDoom/src/doom/r_plane.h @@ -0,0 +1,76 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh, visplane stuff (floor, ceilings). +// + + +#ifndef __R_PLANE__ +#define __R_PLANE__ + + +#include "r_data.h" + + + +// Visplane related. +extern short* lastopening; + + +typedef void (*planefunction_t) (int top, int bottom); + +extern planefunction_t floorfunc; +extern planefunction_t ceilingfunc_t; + +extern short floorclip[SCREENWIDTH]; +extern short ceilingclip[SCREENWIDTH]; + +extern fixed_t yslope[SCREENHEIGHT]; +extern fixed_t distscale[SCREENWIDTH]; + +void R_InitPlanes (void); +void R_ClearPlanes (void); + +void +R_MapPlane +( int y, + int x1, + int x2 ); + +void +R_MakeSpans +( int x, + int t1, + int b1, + int t2, + int b2 ); + +void R_DrawPlanes (void); + +visplane_t* +R_FindPlane +( fixed_t height, + int picnum, + int lightlevel ); + +visplane_t* +R_CheckPlane +( visplane_t* pl, + int start, + int stop ); + + + +#endif diff --git a/games/NXDoom/src/doom/r_segs.c b/games/NXDoom/src/doom/r_segs.c new file mode 100644 index 00000000000..06881a52072 --- /dev/null +++ b/games/NXDoom/src/doom/r_segs.c @@ -0,0 +1,743 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// All the clipping: columns, horizontal spans, sky columns. +// + + + + + + +#include +#include + +#include "i_system.h" + +#include "doomdef.h" +#include "doomstat.h" + +#include "r_local.h" +#include "r_sky.h" + + +// OPTIMIZE: closed two sided lines as single sided + +// True if any of the segs textures might be visible. +boolean segtextured; + +// False if the back side is the same plane. +boolean markfloor; +boolean markceiling; + +boolean maskedtexture; +int toptexture; +int bottomtexture; +int midtexture; + + +angle_t rw_normalangle; +// angle to line origin +int rw_angle1; + +// +// regular wall +// +int rw_x; +int rw_stopx; +angle_t rw_centerangle; +fixed_t rw_offset; +fixed_t rw_distance; +fixed_t rw_scale; +fixed_t rw_scalestep; +fixed_t rw_midtexturemid; +fixed_t rw_toptexturemid; +fixed_t rw_bottomtexturemid; + +int worldtop; +int worldbottom; +int worldhigh; +int worldlow; + +fixed_t pixhigh; +fixed_t pixlow; +fixed_t pixhighstep; +fixed_t pixlowstep; + +fixed_t topfrac; +fixed_t topstep; + +fixed_t bottomfrac; +fixed_t bottomstep; + + +lighttable_t** walllights; + +short* maskedtexturecol; + + + +// +// R_RenderMaskedSegRange +// +void +R_RenderMaskedSegRange +( drawseg_t* ds, + int x1, + int x2 ) +{ + unsigned index; + column_t* col; + int lightnum; + int texnum; + + // Calculate light table. + // Use different light tables + // for horizontal / vertical / diagonal. Diagonal? + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + curline = ds->curline; + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = texturetranslation[curline->sidedef->midtexture]; + + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS-1]; + else + walllights = scalelight[lightnum]; + + maskedtexturecol = ds->maskedtexturecol; + + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + + // find positioning + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + { + dc_texturemid = frontsector->floorheight > backsector->floorheight + ? frontsector->floorheight : backsector->floorheight; + dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; + } + else + { + dc_texturemid =frontsector->ceilingheightceilingheight + ? frontsector->ceilingheight : backsector->ceilingheight; + dc_texturemid = dc_texturemid - viewz; + } + dc_texturemid += curline->sidedef->rowoffset; + + if (fixedcolormap) + dc_colormap = fixedcolormap; + + // draw the columns + for (dc_x = x1 ; dc_x <= x2 ; dc_x++) + { + // calculate lighting + if (maskedtexturecol[dc_x] != SHRT_MAX) + { + if (!fixedcolormap) + { + index = spryscale>>LIGHTSCALESHIFT; + + if (index >= MAXLIGHTSCALE ) + index = MAXLIGHTSCALE-1; + + dc_colormap = walllights[index]; + } + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)( + (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3); + + R_DrawMaskedColumn (col); + maskedtexturecol[dc_x] = SHRT_MAX; + } + spryscale += rw_scalestep; + } + +} + + + + +// +// R_RenderSegLoop +// Draws zero, one, or two textures (and possibly a masked +// texture) for walls. +// Can draw or mark the starting pixel of floor and ceiling +// textures. +// CALLED: CORE LOOPING ROUTINE. +// +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1<>HEIGHTBITS; + + // no space above wall? + if (yl < ceilingclip[rw_x]+1) + yl = ceilingclip[rw_x]+1; + + if (markceiling) + { + top = ceilingclip[rw_x]+1; + bottom = yl-1; + + if (bottom >= floorclip[rw_x]) + bottom = floorclip[rw_x]-1; + + if (top <= bottom) + { + ceilingplane->top[rw_x] = top; + ceilingplane->bottom[rw_x] = bottom; + } + } + + yh = bottomfrac>>HEIGHTBITS; + + if (yh >= floorclip[rw_x]) + yh = floorclip[rw_x]-1; + + if (markfloor) + { + top = yh+1; + bottom = floorclip[rw_x]-1; + if (top <= ceilingclip[rw_x]) + top = ceilingclip[rw_x]+1; + if (top <= bottom) + { + floorplane->top[rw_x] = top; + floorplane->bottom[rw_x] = bottom; + } + } + + // texturecolumn and lighting are independent of wall tiers + if (segtextured) + { + // calculate texture offset + angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; + texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance); + texturecolumn >>= FRACBITS; + // calculate lighting + index = rw_scale>>LIGHTSCALESHIFT; + + if (index >= MAXLIGHTSCALE ) + index = MAXLIGHTSCALE-1; + + dc_colormap = walllights[index]; + dc_x = rw_x; + dc_iscale = 0xffffffffu / (unsigned)rw_scale; + } + else + { + // purely to shut up the compiler + + texturecolumn = 0; + } + + // draw the wall tiers + if (midtexture) + { + // single sided line + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_source = R_GetColumn(midtexture,texturecolumn); + colfunc (); + ceilingclip[rw_x] = viewheight; + floorclip[rw_x] = -1; + } + else + { + // two sided line + if (toptexture) + { + // top wall + mid = pixhigh>>HEIGHTBITS; + pixhigh += pixhighstep; + + if (mid >= floorclip[rw_x]) + mid = floorclip[rw_x]-1; + + if (mid >= yl) + { + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_source = R_GetColumn(toptexture,texturecolumn); + colfunc (); + ceilingclip[rw_x] = mid; + } + else + ceilingclip[rw_x] = yl-1; + } + else + { + // no top wall + if (markceiling) + ceilingclip[rw_x] = yl-1; + } + + if (bottomtexture) + { + // bottom wall + mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; + pixlow += pixlowstep; + + // no space above wall? + if (mid <= ceilingclip[rw_x]) + mid = ceilingclip[rw_x]+1; + + if (mid <= yh) + { + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_source = R_GetColumn(bottomtexture, + texturecolumn); + colfunc (); + floorclip[rw_x] = mid; + } + else + floorclip[rw_x] = yh+1; + } + else + { + // no bottom wall + if (markfloor) + floorclip[rw_x] = yh+1; + } + + if (maskedtexture) + { + // save texturecol + // for backdrawing of masked mid texture + maskedtexturecol[rw_x] = texturecolumn; + } + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; + } +} + + + + +// +// R_StoreWallRange +// A wall segment will be drawn +// between start and stop pixels (inclusive). +// +void +R_StoreWallRange +( int start, + int stop ) +{ + fixed_t hyp; + fixed_t sineval; + angle_t distangle, offsetangle; + fixed_t vtop; + int lightnum; + + // don't overflow and crash + if (ds_p == &drawsegs[MAXDRAWSEGS]) + return; + +#ifdef RANGECHECK + if (start >=viewwidth || start > stop) + I_Error ("Bad R_RenderWallRange: %i to %i", start , stop); +#endif + + sidedef = curline->sidedef; + linedef = curline->linedef; + + // mark the segment as visible for auto map + linedef->flags |= ML_MAPPED; + + // calculate rw_distance for scale calculation + rw_normalangle = curline->angle + ANG90; + offsetangle = abs((int)rw_normalangle-(int)rw_angle1); + + if (offsetangle > ANG90) + offsetangle = ANG90; + + distangle = ANG90 - offsetangle; + hyp = R_PointToDist (curline->v1->x, curline->v1->y); + sineval = finesine[distangle>>ANGLETOFINESHIFT]; + rw_distance = FixedMul (hyp, sineval); + + + ds_p->x1 = rw_x = start; + ds_p->x2 = stop; + ds_p->curline = curline; + rw_stopx = stop+1; + + // calculate scale at both ends and step + ds_p->scale1 = rw_scale = + R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]); + + if (stop > start ) + { + ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]); + ds_p->scalestep = rw_scalestep = + (ds_p->scale2 - rw_scale) / (stop-start); + } + else + { + // UNUSED: try to fix the stretched line bug +#if 0 + if (rw_distance < FRACUNIT/2) + { + fixed_t trx,try; + fixed_t gxt,gyt; + + trx = curline->v1->x - viewx; + try = curline->v1->y - viewy; + + gxt = FixedMul(trx,viewcos); + gyt = -FixedMul(try,viewsin); + ds_p->scale1 = FixedDiv(projection, gxt-gyt)<scale2 = ds_p->scale1; + } + + // calculate texture boundaries + // and decide if floor / ceiling marks are needed + worldtop = frontsector->ceilingheight - viewz; + worldbottom = frontsector->floorheight - viewz; + + midtexture = toptexture = bottomtexture = maskedtexture = 0; + ds_p->maskedtexturecol = NULL; + + if (!backsector) + { + // single sided line + midtexture = texturetranslation[sidedef->midtexture]; + // a single sided line is terminal, so it must mark ends + markfloor = markceiling = true; + if (linedef->flags & ML_DONTPEGBOTTOM) + { + vtop = frontsector->floorheight + + textureheight[sidedef->midtexture]; + // bottom of texture at bottom + rw_midtexturemid = vtop - viewz; + } + else + { + // top of texture at top + rw_midtexturemid = worldtop; + } + rw_midtexturemid += sidedef->rowoffset; + + ds_p->silhouette = SIL_BOTH; + ds_p->sprtopclip = screenheightarray; + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->tsilheight = INT_MIN; + } + else + { + // two sided line + ds_p->sprtopclip = ds_p->sprbottomclip = NULL; + ds_p->silhouette = 0; + + if (frontsector->floorheight > backsector->floorheight) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = frontsector->floorheight; + } + else if (backsector->floorheight > viewz) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + // ds_p->sprbottomclip = negonearray; + } + + if (frontsector->ceilingheight < backsector->ceilingheight) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = frontsector->ceilingheight; + } + else if (backsector->ceilingheight < viewz) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + // ds_p->sprtopclip = screenheightarray; + } + + if (backsector->ceilingheight <= frontsector->floorheight) + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } + + if (backsector->floorheight >= frontsector->ceilingheight) + { + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT_MIN; + ds_p->silhouette |= SIL_TOP; + } + + worldhigh = backsector->ceilingheight - viewz; + worldlow = backsector->floorheight - viewz; + + // hack to allow height changes in outdoor areas + if (frontsector->ceilingpic == skyflatnum + && backsector->ceilingpic == skyflatnum) + { + worldtop = worldhigh; + } + + + if (worldlow != worldbottom + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel) + { + markfloor = true; + } + else + { + // same plane on both sides + markfloor = false; + } + + + if (worldhigh != worldtop + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel) + { + markceiling = true; + } + else + { + // same plane on both sides + markceiling = false; + } + + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + { + // closed door + markceiling = markfloor = true; + } + + + if (worldhigh < worldtop) + { + // top texture + toptexture = texturetranslation[sidedef->toptexture]; + if (linedef->flags & ML_DONTPEGTOP) + { + // top of texture at top + rw_toptexturemid = worldtop; + } + else + { + vtop = + backsector->ceilingheight + + textureheight[sidedef->toptexture]; + + // bottom of texture + rw_toptexturemid = vtop - viewz; + } + } + if (worldlow > worldbottom) + { + // bottom texture + bottomtexture = texturetranslation[sidedef->bottomtexture]; + + if (linedef->flags & ML_DONTPEGBOTTOM ) + { + // bottom of texture at bottom + // top of texture at top + rw_bottomtexturemid = worldtop; + } + else // top of texture at top + rw_bottomtexturemid = worldlow; + } + rw_toptexturemid += sidedef->rowoffset; + rw_bottomtexturemid += sidedef->rowoffset; + + // allocate space for masked texture tables + if (sidedef->midtexture) + { + // masked midtexture + maskedtexture = true; + ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; + } + } + + // calculate rw_offset (only needed for textured lines) + segtextured = midtexture | toptexture | bottomtexture | maskedtexture; + + if (segtextured) + { + offsetangle = rw_normalangle-rw_angle1; + + if (offsetangle > ANG180) + offsetangle = -offsetangle; + + if (offsetangle > ANG90) + offsetangle = ANG90; + + sineval = finesine[offsetangle >>ANGLETOFINESHIFT]; + rw_offset = FixedMul (hyp, sineval); + + if (rw_normalangle-rw_angle1 < ANG180) + rw_offset = -rw_offset; + + rw_offset += sidedef->textureoffset + curline->offset; + rw_centerangle = ANG90 + viewangle - rw_normalangle; + + // calculate light table + // use different light tables + // for horizontal / vertical / diagonal + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + if (!fixedcolormap) + { + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS-1]; + else + walllights = scalelight[lightnum]; + } + } + + // if a floor / ceiling plane is on the wrong side + // of the view plane, it is definitely invisible + // and doesn't need to be marked. + + + if (frontsector->floorheight >= viewz) + { + // above view plane + markfloor = false; + } + + if (frontsector->ceilingheight <= viewz + && frontsector->ceilingpic != skyflatnum) + { + // below view plane + markceiling = false; + } + + + // calculate incremental stepping values for texture edges + worldtop >>= 4; + worldbottom >>= 4; + + topstep = -FixedMul (rw_scalestep, worldtop); + topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); + + bottomstep = -FixedMul (rw_scalestep,worldbottom); + bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + + if (backsector) + { + worldhigh >>= 4; + worldlow >>= 4; + + if (worldhigh < worldtop) + { + pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); + pixhighstep = -FixedMul (rw_scalestep,worldhigh); + } + + if (worldlow > worldbottom) + { + pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); + pixlowstep = -FixedMul (rw_scalestep,worldlow); + } + } + + // render it + if (markceiling) + ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); + + if (markfloor) + floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); + + R_RenderSegLoop (); + + + // save sprite clipping info + if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) + && !ds_p->sprtopclip) + { + memcpy (lastopening, ceilingclip+start, sizeof(*lastopening)*(rw_stopx-start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) + && !ds_p->sprbottomclip) + { + memcpy (lastopening, floorclip+start, sizeof(*lastopening)*(rw_stopx-start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if (maskedtexture && !(ds_p->silhouette&SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + } + if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + } + ds_p++; +} + diff --git a/games/NXDoom/src/doom/r_segs.h b/games/NXDoom/src/doom/r_segs.h new file mode 100644 index 00000000000..8e6a768f454 --- /dev/null +++ b/games/NXDoom/src/doom/r_segs.h @@ -0,0 +1,34 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh module, drawing LineSegs from BSP. +// + + +#ifndef __R_SEGS__ +#define __R_SEGS__ + + +extern lighttable_t **walllights; + + +void +R_RenderMaskedSegRange +( drawseg_t* ds, + int x1, + int x2 ); + + +#endif diff --git a/games/NXDoom/src/doom/r_sky.c b/games/NXDoom/src/doom/r_sky.c new file mode 100644 index 00000000000..bcd5a75bb50 --- /dev/null +++ b/games/NXDoom/src/doom/r_sky.c @@ -0,0 +1,52 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Sky rendering. The DOOM sky is a texture map like any +// wall, wrapping around. A 1024 columns equal 360 degrees. +// The default sky map is 256 columns and repeats 4 times +// on a 320 screen? +// +// + + + +// Needed for FRACUNIT. +#include "m_fixed.h" + +// Needed for Flat retrieval. +#include "r_data.h" + + +#include "r_sky.h" + +// +// sky mapping +// +int skyflatnum; +int skytexture; +int skytexturemid; + + + +// +// R_InitSkyMap +// Called whenever the view size changes. +// +void R_InitSkyMap (void) +{ + // skyflatnum = R_FlatNumForName ( SKYFLATNAME ); + skytexturemid = SCREENHEIGHT/2*FRACUNIT; +} + diff --git a/games/NXDoom/src/doom/r_sky.h b/games/NXDoom/src/doom/r_sky.h new file mode 100644 index 00000000000..8ad6680aa5f --- /dev/null +++ b/games/NXDoom/src/doom/r_sky.h @@ -0,0 +1,37 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Sky rendering. +// + + +#ifndef __R_SKY__ +#define __R_SKY__ + + + +// SKY, store the number for name. +#define SKYFLATNAME "F_SKY1" + +// The sky map is 256*128*4 maps. +#define ANGLETOSKYSHIFT 22 + +extern int skytexture; +extern int skytexturemid; + +// Called whenever the view size changes. +void R_InitSkyMap (void); + +#endif diff --git a/games/NXDoom/src/doom/r_state.h b/games/NXDoom/src/doom/r_state.h new file mode 100644 index 00000000000..2a60e2fe8e1 --- /dev/null +++ b/games/NXDoom/src/doom/r_state.h @@ -0,0 +1,127 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh/render internal state variables (global). +// + + +#ifndef __R_STATE__ +#define __R_STATE__ + +// Need data structure definitions. +#include "d_player.h" +#include "r_data.h" + + + + + + +// +// Refresh internal data structures, +// for rendering. +// + +// needed for texture pegging +extern fixed_t* textureheight; + +// needed for pre rendering (fracs) +extern fixed_t* spritewidth; + +extern fixed_t* spriteoffset; +extern fixed_t* spritetopoffset; + +extern lighttable_t* colormaps; + +extern int viewwidth; +extern int scaledviewwidth; +extern int viewheight; + +extern int firstflat; + +// for global animation +extern int* flattranslation; +extern int* texturetranslation; + + +// Sprite.... +extern int firstspritelump; +extern int lastspritelump; +extern int numspritelumps; + + + +// +// Lookup tables for map data. +// +extern int numsprites; +extern spritedef_t* sprites; + +extern int numvertexes; +extern vertex_t* vertexes; + +extern int numsegs; +extern seg_t* segs; + +extern int numsectors; +extern sector_t* sectors; + +extern int numsubsectors; +extern subsector_t* subsectors; + +extern int numnodes; +extern node_t* nodes; + +extern int numlines; +extern line_t* lines; + +extern int numsides; +extern side_t* sides; + + +// +// POV data. +// +extern fixed_t viewx; +extern fixed_t viewy; +extern fixed_t viewz; + +extern angle_t viewangle; +extern player_t* viewplayer; + + +// ? +extern angle_t clipangle; + +extern int viewangletox[FINEANGLES/2]; +extern angle_t xtoviewangle[SCREENWIDTH+1]; +//extern fixed_t finetangent[FINEANGLES/2]; + +extern fixed_t rw_distance; +extern angle_t rw_normalangle; + + + +// angle to line origin +extern int rw_angle1; + +// Segs count? +extern int sscount; + +extern visplane_t* floorplane; +extern visplane_t* ceilingplane; + + +#endif diff --git a/games/NXDoom/src/doom/r_things.c b/games/NXDoom/src/doom/r_things.c new file mode 100644 index 00000000000..5533fd9bf48 --- /dev/null +++ b/games/NXDoom/src/doom/r_things.c @@ -0,0 +1,982 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh of things, i.e. objects represented by sprites. +// + + + + +#include +#include + + +#include "deh_main.h" +#include "doomdef.h" + +#include "i_swap.h" +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" + +#include "r_local.h" + +#include "doomstat.h" + + + +#define MINZ (FRACUNIT*4) +#define BASEYCENTER (SCREENHEIGHT/2) + +//void R_DrawColumn (void); +//void R_DrawFuzzColumn (void); + + + +typedef struct +{ + int x1; + int x2; + + int column; + int topclip; + int bottomclip; + +} maskdraw_t; + + + +// +// Sprite rotation 0 is facing the viewer, +// rotation 1 is one angle turn CLOCKWISE around the axis. +// This is not the same as the angle, +// which increases counter clockwise (protractor). +// There was a lot of stuff grabbed wrong, so I changed it... +// +fixed_t pspritescale; +fixed_t pspriteiscale; + +lighttable_t** spritelights; + +// constant arrays +// used for psprite clipping and initializing clipping +short negonearray[SCREENWIDTH]; +short screenheightarray[SCREENWIDTH]; + + +// +// INITIALIZATION FUNCTIONS +// + +// variables used to look up +// and range check thing_t sprites patches +spritedef_t* sprites; +int numsprites; + +spriteframe_t sprtemp[29]; +int maxframe; +const char *spritename; + + + + +// +// R_InstallSpriteLump +// Local function for R_InitSprites. +// +void +R_InstallSpriteLump +( int lump, + unsigned frame, + unsigned rotation, + boolean flipped ) +{ + int r; + + if (frame >= 29 || rotation > 8) + I_Error("R_InstallSpriteLump: " + "Bad frame characters in lump %i", lump); + + if ((int)frame > maxframe) + maxframe = frame; + + if (rotation == 0) + { + // the lump should be used for all rotations + if (sprtemp[frame].rotate == false) + I_Error ("R_InitSprites: Sprite %s frame %c has " + "multip rot=0 lump", spritename, 'A'+frame); + + if (sprtemp[frame].rotate == true) + I_Error ("R_InitSprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", spritename, 'A'+frame); + + sprtemp[frame].rotate = false; + for (r=0 ; r<8 ; r++) + { + sprtemp[frame].lump[r] = lump - firstspritelump; + sprtemp[frame].flip[r] = (byte)flipped; + } + return; + } + + // the lump is only used for one rotation + if (sprtemp[frame].rotate == false) + I_Error ("R_InitSprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", spritename, 'A'+frame); + + sprtemp[frame].rotate = true; + + // make 0 based + rotation--; + if (sprtemp[frame].lump[rotation] != -1) + I_Error ("R_InitSprites: Sprite %s : %c : %c " + "has two lumps mapped to it", + spritename, 'A'+frame, '1'+rotation); + + sprtemp[frame].lump[rotation] = lump - firstspritelump; + sprtemp[frame].flip[rotation] = (byte)flipped; +} + + + + +// +// R_InitSpriteDefs +// Pass a null terminated list of sprite names +// (4 chars exactly) to be used. +// Builds the sprite rotation matrixes to account +// for horizontally flipped sprites. +// Will report an error if the lumps are inconsistant. +// Only called at startup. +// +// Sprite lump names are 4 characters for the actor, +// a letter for the frame, and a number for the rotation. +// A sprite that is flippable will have an additional +// letter/number appended. +// The rotation character can be 0 to signify no rotations. +// +void R_InitSpriteDefs(const char **namelist) +{ + const char **check; + int i; + int l; + int frame; + int rotation; + int start; + int end; + int patched; + + // count the number of sprite names + check = namelist; + while (*check != NULL) + check++; + + numsprites = check-namelist; + + if (!numsprites) + return; + + sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); + + start = firstspritelump-1; + end = lastspritelump+1; + + // scan all the lump names for each of the names, + // noting the highest frame letter. + // Just compare 4 characters as ints + for (i=0 ; iname, spritename, 4)) + { + frame = lumpinfo[l]->name[4] - 'A'; + rotation = lumpinfo[l]->name[5] - '0'; + + if (modifiedgame) + patched = W_GetNumForName (lumpinfo[l]->name); + else + patched = l; + + R_InstallSpriteLump (patched, frame, rotation, false); + + if (lumpinfo[l]->name[6]) + { + frame = lumpinfo[l]->name[6] - 'A'; + rotation = lumpinfo[l]->name[7] - '0'; + R_InstallSpriteLump (l, frame, rotation, true); + } + } + } + + // check the frames that were found for completeness + if (maxframe == -1) + { + sprites[i].numframes = 0; + continue; + } + + maxframe++; + + for (frame = 0 ; frame < maxframe ; frame++) + { + switch ((int)sprtemp[frame].rotate) + { + case -1: + // no rotations were found for that frame at all + I_Error ("R_InitSprites: No patches found " + "for %s frame %c", spritename, frame+'A'); + break; + + case 0: + // only the first rotation is needed + break; + + case 1: + // must have all 8 frames + for (rotation=0 ; rotation<8 ; rotation++) + if (sprtemp[frame].lump[rotation] == -1) + I_Error ("R_InitSprites: Sprite %s frame %c " + "is missing rotations", + spritename, frame+'A'); + break; + } + } + + // allocate space for the frames present and copy sprtemp to it + sprites[i].numframes = maxframe; + sprites[i].spriteframes = + Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); + } + +} + + + + +// +// GAME FUNCTIONS +// +vissprite_t vissprites[MAXVISSPRITES]; +vissprite_t* vissprite_p; +int newvissprite; + + + +// +// R_InitSprites +// Called at program start. +// +void R_InitSprites(const char **namelist) +{ + int i; + + for (i=0 ; itopdelta != 0xff ; ) + { + // calculate unclipped screen coordinates + // for post + topscreen = sprtopscreen + spryscale*column->topdelta; + bottomscreen = topscreen + spryscale*column->length; + + dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x]-1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x]+1; + + if (dc_yl <= dc_yh) + { + dc_source = (byte *)column + 3; + dc_texturemid = basetexturemid - (column->topdelta<topdelta; + + // Drawn by either R_DrawColumn + // or (SHADOW) R_DrawFuzzColumn. + colfunc (); + } + column = (column_t *)( (byte *)column + column->length + 4); + } + + dc_texturemid = basetexturemid; +} + + + +// +// R_DrawVisSprite +// mfloorclip and mceilingclip should also be set. +// +void +R_DrawVisSprite +( vissprite_t* vis, + int x1, + int x2 ) +{ + column_t* column; + int texturecolumn; + fixed_t frac; + patch_t* patch; + + + patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); + + dc_colormap = vis->colormap; + + if (!dc_colormap) + { + // NULL colormap = shadow draw + colfunc = fuzzcolfunc; + } + else if (vis->mobjflags & MF_TRANSLATION) + { + colfunc = transcolfunc; + dc_translation = translationtables - 256 + + ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) ); + } + + dc_iscale = abs(vis->xiscale)>>detailshift; + dc_texturemid = vis->texturemid; + frac = vis->startfrac; + spryscale = vis->scale; + sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); + + for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) + { + texturecolumn = frac>>FRACBITS; +#ifdef RANGECHECK + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error ("R_DrawSpriteRange: bad texturecolumn"); +#endif + column = (column_t *) ((byte *)patch + + LONG(patch->columnofs[texturecolumn])); + R_DrawMaskedColumn (column); + } + + colfunc = basecolfunc; +} + + + +// +// R_ProjectSprite +// Generates a vissprite for a thing +// if it might be visible. +// +void R_ProjectSprite (mobj_t* thing) +{ + fixed_t tr_x; + fixed_t tr_y; + + fixed_t gxt; + fixed_t gyt; + + fixed_t tx; + fixed_t tz; + + fixed_t xscale; + + int x1; + int x2; + + spritedef_t* sprdef; + spriteframe_t* sprframe; + int lump; + + unsigned rot; + boolean flip; + + int index; + + vissprite_t* vis; + + angle_t ang; + fixed_t iscale; + + // transform the origin point + tr_x = thing->x - viewx; + tr_y = thing->y - viewy; + + gxt = FixedMul(tr_x,viewcos); + gyt = -FixedMul(tr_y,viewsin); + + tz = gxt-gyt; + + // thing is behind view plane? + if (tz < MINZ) + return; + + xscale = FixedDiv(projection, tz); + + gxt = -FixedMul(tr_x,viewsin); + gyt = FixedMul(tr_y,viewcos); + tx = -(gyt+gxt); + + // too far off the side? + if (abs(tx)>(tz<<2)) + return; + + // decide which patch to use for sprite relative to player +#ifdef RANGECHECK + if ((unsigned int) thing->sprite >= (unsigned int) numsprites) + I_Error ("R_ProjectSprite: invalid sprite number %i ", + thing->sprite); +#endif + sprdef = &sprites[thing->sprite]; +#ifdef RANGECHECK + if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) + I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", + thing->sprite, thing->frame); +#endif + sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; + + if (sprframe->rotate) + { + // choose a different rotation based on player view + ang = R_PointToAngle (thing->x, thing->y); + rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; + lump = sprframe->lump[rot]; + flip = (boolean)sprframe->flip[rot]; + } + else + { + // use single rotation for all views + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + } + + // calculate edges of the shape + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; + + // off the right side? + if (x1 > viewwidth) + return; + + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; + + // off the left side + if (x2 < 0) + return; + + // store information in a vissprite + vis = R_NewVisSprite (); + vis->mobjflags = thing->flags; + vis->scale = xscale<gx = thing->x; + vis->gy = thing->y; + vis->gz = thing->z; + vis->gzt = thing->z + spritetopoffset[lump]; + vis->texturemid = vis->gzt - viewz; + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + iscale = FixedDiv (FRACUNIT, xscale); + + if (flip) + { + vis->startfrac = spritewidth[lump]-1; + vis->xiscale = -iscale; + } + else + { + vis->startfrac = 0; + vis->xiscale = iscale; + } + + if (vis->x1 > x1) + vis->startfrac += vis->xiscale*(vis->x1-x1); + vis->patch = lump; + + // get light level + if (thing->flags & MF_SHADOW) + { + // shadow draw + vis->colormap = NULL; + } + else if (fixedcolormap) + { + // fixed map + vis->colormap = fixedcolormap; + } + else if (thing->frame & FF_FULLBRIGHT) + { + // full bright + vis->colormap = colormaps; + } + + else + { + // diminished light + index = xscale>>(LIGHTSCALESHIFT-detailshift); + + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE-1; + + vis->colormap = spritelights[index]; + } +} + + + + +// +// R_AddSprites +// During BSP traversal, this adds sprites by sector. +// +void R_AddSprites (sector_t* sec) +{ + mobj_t* thing; + int lightnum; + + // BSP is traversed by subsector. + // A sector might have been split into several + // subsectors during BSP building. + // Thus we check whether its already added. + if (sec->validcount == validcount) + return; + + // Well, now it will be done. + sec->validcount = validcount; + + lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS-1]; + else + spritelights = scalelight[lightnum]; + + // Handle all things in sector. + for (thing = sec->thinglist ; thing ; thing = thing->snext) + R_ProjectSprite (thing); +} + + +// +// R_DrawPSprite +// +void R_DrawPSprite (pspdef_t* psp) +{ + fixed_t tx; + int x1; + int x2; + spritedef_t* sprdef; + spriteframe_t* sprframe; + int lump; + boolean flip; + vissprite_t* vis; + vissprite_t avis; + + // decide which patch to use +#ifdef RANGECHECK + if ( (unsigned)psp->state->sprite >= (unsigned int) numsprites) + I_Error ("R_ProjectSprite: invalid sprite number %i ", + psp->state->sprite); +#endif + sprdef = &sprites[psp->state->sprite]; +#ifdef RANGECHECK + if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", + psp->state->sprite, psp->state->frame); +#endif + sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; + + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + + // calculate edges of the shape + tx = psp->sx-(SCREENWIDTH/2)*FRACUNIT; + + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; + + // off the right side + if (x1 > viewwidth) + return; + + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; + + // off the left side + if (x2 < 0) + return; + + // store information in a vissprite + vis = &avis; + vis->mobjflags = 0; + vis->texturemid = (BASEYCENTER<sy-spritetopoffset[lump]); + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + vis->scale = pspritescale<xiscale = -pspriteiscale; + vis->startfrac = spritewidth[lump]-1; + } + else + { + vis->xiscale = pspriteiscale; + vis->startfrac = 0; + } + + if (vis->x1 > x1) + vis->startfrac += vis->xiscale*(vis->x1-x1); + + vis->patch = lump; + + if (viewplayer->powers[pw_invisibility] > 4*32 + || viewplayer->powers[pw_invisibility] & 8) + { + // shadow draw + vis->colormap = NULL; + } + else if (fixedcolormap) + { + // fixed color + vis->colormap = fixedcolormap; + } + else if (psp->state->frame & FF_FULLBRIGHT) + { + // full bright + vis->colormap = colormaps; + } + else + { + // local light + vis->colormap = spritelights[MAXLIGHTSCALE-1]; + } + + R_DrawVisSprite (vis, vis->x1, vis->x2); +} + + + +// +// R_DrawPlayerSprites +// +void R_DrawPlayerSprites (void) +{ + int i; + int lightnum; + pspdef_t* psp; + + // get light level + lightnum = + (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + +extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS-1]; + else + spritelights = scalelight[lightnum]; + + // clip to screen bounds + mfloorclip = screenheightarray; + mceilingclip = negonearray; + + // add all active psprites + for (i=0, psp=viewplayer->psprites; + istate) + R_DrawPSprite (psp); + } +} + + + + +// +// R_SortVisSprites +// +vissprite_t vsprsortedhead; + + +void R_SortVisSprites (void) +{ + int i; + int count; + vissprite_t* ds; + vissprite_t* best; + static vissprite_t unsorted; + fixed_t bestscale; + + count = vissprite_p - vissprites; + + unsorted.next = unsorted.prev = &unsorted; + + if (!count) + return; + + for (ds=vissprites ; dsnext = ds+1; + ds->prev = ds-1; + } + + vissprites[0].prev = &unsorted; + unsorted.next = &vissprites[0]; + (vissprite_p-1)->next = &unsorted; + unsorted.prev = vissprite_p-1; + + // pull the vissprites out by scale + + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i=0 ; inext) + { + if (ds->scale < bestscale) + { + bestscale = ds->scale; + best = ds; + } + } + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; + } +} + + + +// +// R_DrawSprite +// +void R_DrawSprite (vissprite_t* spr) +{ + drawseg_t* ds; + short clipbot[SCREENWIDTH]; + short cliptop[SCREENWIDTH]; + int x; + int r1; + int r2; + fixed_t scale; + fixed_t lowscale; + int silhouette; + + for (x = spr->x1 ; x<=spr->x2 ; x++) + clipbot[x] = cliptop[x] = -2; + + // Scan drawsegs from end to start for obscuring segs. + // The first drawseg that has a greater scale + // is the clip seg. + for (ds=ds_p-1 ; ds >= drawsegs ; ds--) + { + // determine if the drawseg obscures the sprite + if (ds->x1 > spr->x2 + || ds->x2 < spr->x1 + || (!ds->silhouette + && !ds->maskedtexturecol) ) + { + // does not cover sprite + continue; + } + + r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; + r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->scale + || ( lowscale < spr->scale + && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) + { + // masked mid texture? + if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, r1, r2); + // seg is behind sprite + continue; + } + + + // clip this piece of the sprite + silhouette = ds->silhouette; + + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == 1) + { + // bottom sil + for (x=r1 ; x<=r2 ; x++) + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + } + else if (silhouette == 2) + { + // top sil + for (x=r1 ; x<=r2 ; x++) + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == 3) + { + // both + for (x=r1 ; x<=r2 ; x++) + { + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + } + + } + + // all clipping has been performed, so draw the sprite + + // check for unclipped columns + for (x = spr->x1 ; x<=spr->x2 ; x++) + { + if (clipbot[x] == -2) + clipbot[x] = viewheight; + + if (cliptop[x] == -2) + cliptop[x] = -1; + } + + mfloorclip = clipbot; + mceilingclip = cliptop; + R_DrawVisSprite (spr, spr->x1, spr->x2); +} + + + + +// +// R_DrawMasked +// +void R_DrawMasked (void) +{ + vissprite_t* spr; + drawseg_t* ds; + + R_SortVisSprites (); + + if (vissprite_p > vissprites) + { + // draw all vissprites back to front + for (spr = vsprsortedhead.next ; + spr != &vsprsortedhead ; + spr=spr->next) + { + + R_DrawSprite (spr); + } + } + + // render any remaining masked mid textures + for (ds=ds_p-1 ; ds >= drawsegs ; ds--) + if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, ds->x1, ds->x2); + + // draw the psprites on top of everything + // but does not draw on side views + if (!viewangleoffset) + R_DrawPlayerSprites (); +} + + + diff --git a/games/NXDoom/src/doom/r_things.h b/games/NXDoom/src/doom/r_things.h new file mode 100644 index 00000000000..fc51c34a4eb --- /dev/null +++ b/games/NXDoom/src/doom/r_things.h @@ -0,0 +1,65 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Rendering of moving objects, sprites. +// + + +#ifndef __R_THINGS__ +#define __R_THINGS__ + + + +#define MAXVISSPRITES 128 + +extern vissprite_t vissprites[MAXVISSPRITES]; +extern vissprite_t* vissprite_p; +extern vissprite_t vsprsortedhead; + +// Constant arrays used for psprite clipping +// and initializing clipping. +extern short negonearray[SCREENWIDTH]; +extern short screenheightarray[SCREENWIDTH]; + +// vars for R_DrawMaskedColumn +extern short* mfloorclip; +extern short* mceilingclip; +extern fixed_t spryscale; +extern fixed_t sprtopscreen; + +extern fixed_t pspritescale; +extern fixed_t pspriteiscale; + + +void R_DrawMaskedColumn (column_t* column); + + +void R_SortVisSprites (void); + +void R_AddSprites (sector_t* sec); +void R_AddPSprites (void); +void R_DrawSprites (void); +void R_InitSprites(const char **namelist); +void R_ClearSprites (void); +void R_DrawMasked (void); + +void +R_ClipVisSprite +( vissprite_t* vis, + int xl, + int xh ); + + +#endif diff --git a/games/NXDoom/src/doom/s_sound.c b/games/NXDoom/src/doom/s_sound.c new file mode 100644 index 00000000000..76748892ab9 --- /dev/null +++ b/games/NXDoom/src/doom/s_sound.c @@ -0,0 +1,724 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// + +#include +#include + +#include "i_sound.h" +#include "i_system.h" + +#include "deh_str.h" + +#include "doomstat.h" +#include "doomtype.h" + +#include "sounds.h" +#include "s_sound.h" + +#include "m_misc.h" +#include "m_random.h" +#include "m_argv.h" + +#include "p_local.h" +#include "w_wad.h" +#include "z_zone.h" + +// when to clip out sounds +// Does not fit the large outdoor areas. + +#define S_CLIPPING_DIST (1200 * FRACUNIT) + +// Distance tp origin when sounds should be maxed out. +// This should relate to movement clipping resolution +// (see BLOCKMAP handling). +// In the source code release: (160*FRACUNIT). Changed back to the +// Vanilla value of 200 (why was this changed?) + +#define S_CLOSE_DIST (200 * FRACUNIT) + +// The range over which sound attenuates + +#define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS) + +// Stereo separation + +#define S_STEREO_SWING (96 * FRACUNIT) + +#define NORM_PRIORITY 64 +#define NORM_SEP 128 + +typedef struct +{ + // sound information (if null, channel avail.) + sfxinfo_t *sfxinfo; + + // origin of sound + mobj_t *origin; + + // handle of the sound being played + int handle; + + int pitch; + +} channel_t; + +// The set of channels available + +static channel_t *channels; + +// Maximum volume of a sound effect. +// Internal default is max out of 0-15. + +int sfxVolume = 8; + +// Maximum volume of music. + +int musicVolume = 8; + +// Internal volume level, ranging from 0-127 + +static int snd_SfxVolume; + +// Whether songs are mus_paused + +static boolean mus_paused; + +// Music currently being played + +static musicinfo_t *mus_playing = NULL; + +// Number of channels to use + +int snd_channels = 8; + +// +// Initializes sound stuff, including volume +// Sets channels, SFX and music volume, +// allocates channel buffer, sets S_sfx lookup. +// + +void S_Init(int sfxVolume, int musicVolume) +{ + int i; + + if (gameversion == exe_doom_1_666) + { + if (logical_gamemission == doom) + { + I_SetOPLDriverVer(opl_doom1_1_666); + } + else + { + I_SetOPLDriverVer(opl_doom2_1_666); + } + } + else + { + I_SetOPLDriverVer(opl_doom_1_9); + } + + I_PrecacheSounds(S_sfx, NUMSFX); + + S_SetSfxVolume(sfxVolume); + S_SetMusicVolume(musicVolume); + + // Allocating the internal channels for mixing + // (the maximum numer of sounds rendered + // simultaneously) within zone memory. + channels = Z_Malloc(snd_channels*sizeof(channel_t), PU_STATIC, 0); + + // Free all channels for use + for (i=0 ; isfxinfo) + { + // stop the sound playing + + if (I_SoundIsPlaying(c->handle)) + { + I_StopSound(c->handle); + } + + // check to see if other channels are playing the sound + + for (i=0; isfxinfo == channels[i].sfxinfo) + { + break; + } + } + + // degrade usefulness of sound data + + c->sfxinfo->usefulness--; + c->sfxinfo = NULL; + c->origin = NULL; + } +} + +// +// Per level startup code. +// Kills playing sounds at start of level, +// determines music if any, changes music. +// + +void S_Start(void) +{ + int cnum; + int mnum; + + // kill all playing sounds at start of level + // (trust me - a good idea) + for (cnum=0 ; cnumpriority >= sfxinfo->priority) + { + break; + } + } + + if (cnum == snd_channels) + { + // FUCK! No lower priority. Sorry, Charlie. + return -1; + } + else + { + // Otherwise, kick out lower priority. + S_StopChannel(cnum); + } + } + + c = &channels[cnum]; + + // channel is decided to be cnum. + c->sfxinfo = sfxinfo; + c->origin = origin; + + return cnum; +} + +// +// Changes volume and stereo-separation variables +// from the norm of a sound effect to be played. +// If the sound is not audible, returns a 0. +// Otherwise, modifies parameters and returns 1. +// + +static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, + int *vol, int *sep) +{ + fixed_t approx_dist; + fixed_t adx; + fixed_t ady; + angle_t angle; + + // calculate the distance to sound origin + // and clip it if necessary + adx = abs(listener->x - source->x); + ady = abs(listener->y - source->y); + + // From _GG1_ p.428. Appox. eucledian distance fast. + approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1); + + if (gamemap != 8 && approx_dist > S_CLIPPING_DIST) + { + return 0; + } + + // angle of source to listener + angle = R_PointToAngle2(listener->x, + listener->y, + source->x, + source->y); + + if (angle > listener->angle) + { + angle = angle - listener->angle; + } + else + { + angle = angle + (0xffffffff - listener->angle); + } + + angle >>= ANGLETOFINESHIFT; + + // stereo separation + *sep = 128 - (FixedMul(S_STEREO_SWING, finesine[angle]) >> FRACBITS); + + // volume calculation + if (approx_dist < S_CLOSE_DIST) + { + *vol = snd_SfxVolume; + } + else if (gamemap == 8) + { + if (approx_dist > S_CLIPPING_DIST) + { + approx_dist = S_CLIPPING_DIST; + } + + *vol = 15+ ((snd_SfxVolume-15) + *((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) + / S_ATTENUATOR; + } + else + { + // distance effect + *vol = (snd_SfxVolume + * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) + / S_ATTENUATOR; + } + + return (*vol > 0); +} + +// clamp supplied integer to the range 0 <= x <= 255. + +static int Clamp(int x) +{ + if (x < 0) + { + return 0; + } + else if (x > 255) + { + return 255; + } + return x; +} + +void S_StartSound(void *origin_p, int sfx_id) +{ + sfxinfo_t *sfx; + mobj_t *origin; + int rc; + int sep; + int pitch; + int cnum; + int volume; + + origin = (mobj_t *) origin_p; + volume = snd_SfxVolume; + + // check for bogus sound # + if (sfx_id < 1 || sfx_id > NUMSFX) + { + I_Error("Bad sfx #: %d", sfx_id); + } + + sfx = &S_sfx[sfx_id]; + + // Initialize sound parameters + pitch = NORM_PITCH; + if (sfx->link) + { + volume += sfx->volume; + pitch = sfx->pitch; + + if (volume < 1) + { + return; + } + + if (volume > snd_SfxVolume) + { + volume = snd_SfxVolume; + } + } + + + // Check to see if it is audible, + // and if not, modify the params + if (origin && origin != players[consoleplayer].mo) + { + rc = S_AdjustSoundParams(players[consoleplayer].mo, + origin, + &volume, + &sep); + + if (origin->x == players[consoleplayer].mo->x + && origin->y == players[consoleplayer].mo->y) + { + sep = NORM_SEP; + } + + if (!rc) + { + return; + } + } + else + { + sep = NORM_SEP; + } + + // hacks to vary the sfx pitches + if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit) + { + pitch += 8 - (M_Random()&15); + } + else if (sfx_id != sfx_itemup && sfx_id != sfx_tink) + { + pitch += 16 - (M_Random()&31); + } + pitch = Clamp(pitch); + + // kill old sound + S_StopSound(origin); + + // try to find a channel + cnum = S_GetChannel(origin, sfx); + + if (cnum < 0) + { + return; + } + + // increase the usefulness + if (sfx->usefulness++ < 0) + { + sfx->usefulness = 1; + } + + if (sfx->lumpnum < 0) + { + sfx->lumpnum = I_GetSfxLumpNum(sfx); + } + + channels[cnum].pitch = pitch; + channels[cnum].handle = I_StartSound(sfx, cnum, volume, sep, channels[cnum].pitch); +} + +// +// Stop and resume music, during game PAUSE. +// + +void S_PauseSound(void) +{ + if (mus_playing && !mus_paused) + { + I_PauseSong(); + mus_paused = true; + } +} + +void S_ResumeSound(void) +{ + if (mus_playing && mus_paused) + { + I_ResumeSong(); + mus_paused = false; + } +} + +// +// Updates music & sounds +// + +void S_UpdateSounds(mobj_t *listener) +{ + int audible; + int cnum; + int volume; + int sep; + sfxinfo_t* sfx; + channel_t* c; + + I_UpdateSound(); + + for (cnum=0; cnumsfxinfo; + + if (c->sfxinfo) + { + if (I_SoundIsPlaying(c->handle)) + { + // initialize parameters + volume = snd_SfxVolume; + sep = NORM_SEP; + + if (sfx->link) + { + volume += sfx->volume; + if (volume < 1) + { + S_StopChannel(cnum); + continue; + } + else if (volume > snd_SfxVolume) + { + volume = snd_SfxVolume; + } + } + + // check non-local sounds for distance clipping + // or modify their params + if (c->origin && listener != c->origin) + { + audible = S_AdjustSoundParams(listener, + c->origin, + &volume, + &sep); + + if (!audible) + { + S_StopChannel(cnum); + } + else + { + I_UpdateSoundParams(c->handle, volume, sep); + } + } + } + else + { + // if channel is allocated but sound has stopped, + // free it + S_StopChannel(cnum); + } + } + } +} + +void S_SetMusicVolume(int volume) +{ + if (volume < 0 || volume > 127) + { + I_Error("Attempt to set music volume at %d", + volume); + } + + I_SetMusicVolume(volume); +} + +void S_SetSfxVolume(int volume) +{ + if (volume < 0 || volume > 127) + { + I_Error("Attempt to set sfx volume at %d", volume); + } + + snd_SfxVolume = volume; +} + +// +// Starts some music with the music id found in sounds.h. +// + +void S_StartMusic(int m_id) +{ + S_ChangeMusic(m_id, false); +} + +void S_ChangeMusic(int musicnum, int looping) +{ + musicinfo_t *music = NULL; + char namebuf[9]; + void *handle; + + // The Doom IWAD file has two versions of the intro music: d_intro + // and d_introa. The latter is used for OPL playback. + + if (musicnum == mus_intro && (snd_musicdevice == SNDDEVICE_ADLIB + || snd_musicdevice == SNDDEVICE_SB) + && W_CheckNumForName("D_INTROA") >= 0) + { + musicnum = mus_introa; + } + + if (musicnum <= mus_None || musicnum >= NUMMUSIC) + { + I_Error("Bad music number %d", musicnum); + } + else + { + music = &S_music[musicnum]; + } + + if (mus_playing == music) + { + return; + } + + // shutdown old music + S_StopMusic(); + + // get lumpnum if neccessary + if (!music->lumpnum) + { + M_snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name)); + music->lumpnum = W_GetNumForName(namebuf); + } + + music->data = W_CacheLumpNum(music->lumpnum, PU_STATIC); + + handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum)); + music->handle = handle; + I_PlaySong(handle, looping); + + mus_playing = music; +} + +boolean S_MusicPlaying(void) +{ + return I_MusicIsPlaying(); +} + +void S_StopMusic(void) +{ + if (mus_playing) + { + if (mus_paused) + { + I_ResumeSong(); + } + + I_StopSong(); + I_UnRegisterSong(mus_playing->handle); + W_ReleaseLumpNum(mus_playing->lumpnum); + mus_playing->data = NULL; + mus_playing = NULL; + } +} + diff --git a/games/NXDoom/src/doom/s_sound.h b/games/NXDoom/src/doom/s_sound.h new file mode 100644 index 00000000000..bbd100a0c35 --- /dev/null +++ b/games/NXDoom/src/doom/s_sound.h @@ -0,0 +1,89 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The not so system specific sound interface. +// + + +#ifndef __S_SOUND__ +#define __S_SOUND__ + +#include "p_mobj.h" +#include "sounds.h" + +// +// Initializes sound stuff, including volume +// Sets channels, SFX and music volume, +// allocates channel buffer, sets S_sfx lookup. +// + +void S_Init(int sfxVolume, int musicVolume); + + +// Shut down sound + +void S_Shutdown(void); + + + +// +// Per level startup code. +// Kills playing sounds at start of level, +// determines music if any, changes music. +// + +void S_Start(void); + +// +// Start sound for thing at +// using from sounds.h +// + +void S_StartSound(void *origin, int sound_id); + +// Stop sound for thing at +void S_StopSound(mobj_t *origin); + + +// Start music using from sounds.h +void S_StartMusic(int music_id); + +// Start music using from sounds.h, +// and set whether looping +void S_ChangeMusic(int music_id, int looping); + +// query if music is playing +boolean S_MusicPlaying(void); + +// Stops the music fer sure. +void S_StopMusic(void); + +// Stop and resume music, during game PAUSE. +void S_PauseSound(void); +void S_ResumeSound(void); + + +// +// Updates music & sounds +// +void S_UpdateSounds(mobj_t *listener); + +void S_SetMusicVolume(int volume); +void S_SetSfxVolume(int volume); + +extern int snd_channels; + +#endif + diff --git a/games/NXDoom/src/doom/sounds.c b/games/NXDoom/src/doom/sounds.c new file mode 100644 index 00000000000..e976bc84480 --- /dev/null +++ b/games/NXDoom/src/doom/sounds.c @@ -0,0 +1,229 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Created by a sound utility. +// Kept as a sample, DOOM2 sounds. +// + + +#include + + +#include "doomtype.h" +#include "sounds.h" + +// +// Information about all the music +// + +#define MUSIC(name) \ + { name, 0, NULL, NULL } + +musicinfo_t S_music[] = +{ + MUSIC(NULL), + MUSIC("e1m1"), + MUSIC("e1m2"), + MUSIC("e1m3"), + MUSIC("e1m4"), + MUSIC("e1m5"), + MUSIC("e1m6"), + MUSIC("e1m7"), + MUSIC("e1m8"), + MUSIC("e1m9"), + MUSIC("e2m1"), + MUSIC("e2m2"), + MUSIC("e2m3"), + MUSIC("e2m4"), + MUSIC("e2m5"), + MUSIC("e2m6"), + MUSIC("e2m7"), + MUSIC("e2m8"), + MUSIC("e2m9"), + MUSIC("e3m1"), + MUSIC("e3m2"), + MUSIC("e3m3"), + MUSIC("e3m4"), + MUSIC("e3m5"), + MUSIC("e3m6"), + MUSIC("e3m7"), + MUSIC("e3m8"), + MUSIC("e3m9"), + MUSIC("inter"), + MUSIC("intro"), + MUSIC("bunny"), + MUSIC("victor"), + MUSIC("introa"), + MUSIC("runnin"), + MUSIC("stalks"), + MUSIC("countd"), + MUSIC("betwee"), + MUSIC("doom"), + MUSIC("the_da"), + MUSIC("shawn"), + MUSIC("ddtblu"), + MUSIC("in_cit"), + MUSIC("dead"), + MUSIC("stlks2"), + MUSIC("theda2"), + MUSIC("doom2"), + MUSIC("ddtbl2"), + MUSIC("runni2"), + MUSIC("dead2"), + MUSIC("stlks3"), + MUSIC("romero"), + MUSIC("shawn2"), + MUSIC("messag"), + MUSIC("count2"), + MUSIC("ddtbl3"), + MUSIC("ampie"), + MUSIC("theda3"), + MUSIC("adrian"), + MUSIC("messg2"), + MUSIC("romer2"), + MUSIC("tense"), + MUSIC("shawn3"), + MUSIC("openin"), + MUSIC("evil"), + MUSIC("ultima"), + MUSIC("read_m"), + MUSIC("dm2ttl"), + MUSIC("dm2int") +}; + + +// +// Information about all the sfx +// + +#define SOUND(name, priority) \ + { NULL, name, priority, NULL, -1, -1, 0, 0, -1, NULL } +#define SOUND_LINK(name, priority, link_id, pitch, volume) \ + { NULL, name, priority, &S_sfx[link_id], pitch, volume, 0, 0, -1, NULL } + +sfxinfo_t S_sfx[] = +{ + // S_sfx[0] needs to be a dummy for odd reasons. + SOUND("none", 0), + SOUND("pistol", 64), + SOUND("shotgn", 64), + SOUND("sgcock", 64), + SOUND("dshtgn", 64), + SOUND("dbopn", 64), + SOUND("dbcls", 64), + SOUND("dbload", 64), + SOUND("plasma", 64), + SOUND("bfg", 64), + SOUND("sawup", 64), + SOUND("sawidl", 118), + SOUND("sawful", 64), + SOUND("sawhit", 64), + SOUND("rlaunc", 64), + SOUND("rxplod", 70), + SOUND("firsht", 70), + SOUND("firxpl", 70), + SOUND("pstart", 100), + SOUND("pstop", 100), + SOUND("doropn", 100), + SOUND("dorcls", 100), + SOUND("stnmov", 119), + SOUND("swtchn", 78), + SOUND("swtchx", 78), + SOUND("plpain", 96), + SOUND("dmpain", 96), + SOUND("popain", 96), + SOUND("vipain", 96), + SOUND("mnpain", 96), + SOUND("pepain", 96), + SOUND("slop", 78), + SOUND("itemup", 78), + SOUND("wpnup", 78), + SOUND("oof", 96), + SOUND("telept", 32), + SOUND("posit1", 98), + SOUND("posit2", 98), + SOUND("posit3", 98), + SOUND("bgsit1", 98), + SOUND("bgsit2", 98), + SOUND("sgtsit", 98), + SOUND("cacsit", 98), + SOUND("brssit", 94), + SOUND("cybsit", 92), + SOUND("spisit", 90), + SOUND("bspsit", 90), + SOUND("kntsit", 90), + SOUND("vilsit", 90), + SOUND("mansit", 90), + SOUND("pesit", 90), + SOUND("sklatk", 70), + SOUND("sgtatk", 70), + SOUND("skepch", 70), + SOUND("vilatk", 70), + SOUND("claw", 70), + SOUND("skeswg", 70), + SOUND("pldeth", 32), + SOUND("pdiehi", 32), + SOUND("podth1", 70), + SOUND("podth2", 70), + SOUND("podth3", 70), + SOUND("bgdth1", 70), + SOUND("bgdth2", 70), + SOUND("sgtdth", 70), + SOUND("cacdth", 70), + SOUND("skldth", 70), + SOUND("brsdth", 32), + SOUND("cybdth", 32), + SOUND("spidth", 32), + SOUND("bspdth", 32), + SOUND("vildth", 32), + SOUND("kntdth", 32), + SOUND("pedth", 32), + SOUND("skedth", 32), + SOUND("posact", 120), + SOUND("bgact", 120), + SOUND("dmact", 120), + SOUND("bspact", 100), + SOUND("bspwlk", 100), + SOUND("vilact", 100), + SOUND("noway", 78), + SOUND("barexp", 60), + SOUND("punch", 64), + SOUND("hoof", 70), + SOUND("metal", 70), + SOUND_LINK("chgun", 64, sfx_pistol, 150, 0), + SOUND("tink", 60), + SOUND("bdopn", 100), + SOUND("bdcls", 100), + SOUND("itmbk", 100), + SOUND("flame", 32), + SOUND("flamst", 32), + SOUND("getpow", 60), + SOUND("bospit", 70), + SOUND("boscub", 70), + SOUND("bossit", 70), + SOUND("bospn", 70), + SOUND("bosdth", 70), + SOUND("manatk", 70), + SOUND("mandth", 70), + SOUND("sssit", 70), + SOUND("ssdth", 70), + SOUND("keenpn", 70), + SOUND("keendt", 70), + SOUND("skeact", 70), + SOUND("skesit", 70), + SOUND("skeatk", 70), + SOUND("radio", 60), +}; + diff --git a/games/NXDoom/src/doom/sounds.h b/games/NXDoom/src/doom/sounds.h new file mode 100644 index 00000000000..1e8afc4051c --- /dev/null +++ b/games/NXDoom/src/doom/sounds.h @@ -0,0 +1,227 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Created by the sound utility written by Dave Taylor. +// Kept as a sample, DOOM2 sounds. Frozen. +// + +#ifndef __SOUNDS__ +#define __SOUNDS__ + +#include "i_sound.h" + +// the complete set of sound effects +extern sfxinfo_t S_sfx[]; + +// the complete set of music +extern musicinfo_t S_music[]; + +// +// Identifiers for all music in game. +// + +typedef enum +{ + mus_None, + mus_e1m1, + mus_e1m2, + mus_e1m3, + mus_e1m4, + mus_e1m5, + mus_e1m6, + mus_e1m7, + mus_e1m8, + mus_e1m9, + mus_e2m1, + mus_e2m2, + mus_e2m3, + mus_e2m4, + mus_e2m5, + mus_e2m6, + mus_e2m7, + mus_e2m8, + mus_e2m9, + mus_e3m1, + mus_e3m2, + mus_e3m3, + mus_e3m4, + mus_e3m5, + mus_e3m6, + mus_e3m7, + mus_e3m8, + mus_e3m9, + mus_inter, + mus_intro, + mus_bunny, + mus_victor, + mus_introa, + mus_runnin, + mus_stalks, + mus_countd, + mus_betwee, + mus_doom, + mus_the_da, + mus_shawn, + mus_ddtblu, + mus_in_cit, + mus_dead, + mus_stlks2, + mus_theda2, + mus_doom2, + mus_ddtbl2, + mus_runni2, + mus_dead2, + mus_stlks3, + mus_romero, + mus_shawn2, + mus_messag, + mus_count2, + mus_ddtbl3, + mus_ampie, + mus_theda3, + mus_adrian, + mus_messg2, + mus_romer2, + mus_tense, + mus_shawn3, + mus_openin, + mus_evil, + mus_ultima, + mus_read_m, + mus_dm2ttl, + mus_dm2int, + NUMMUSIC +} musicenum_t; + + +// +// Identifiers for all sfx in game. +// + +typedef enum +{ + sfx_None, + sfx_pistol, + sfx_shotgn, + sfx_sgcock, + sfx_dshtgn, + sfx_dbopn, + sfx_dbcls, + sfx_dbload, + sfx_plasma, + sfx_bfg, + sfx_sawup, + sfx_sawidl, + sfx_sawful, + sfx_sawhit, + sfx_rlaunc, + sfx_rxplod, + sfx_firsht, + sfx_firxpl, + sfx_pstart, + sfx_pstop, + sfx_doropn, + sfx_dorcls, + sfx_stnmov, + sfx_swtchn, + sfx_swtchx, + sfx_plpain, + sfx_dmpain, + sfx_popain, + sfx_vipain, + sfx_mnpain, + sfx_pepain, + sfx_slop, + sfx_itemup, + sfx_wpnup, + sfx_oof, + sfx_telept, + sfx_posit1, + sfx_posit2, + sfx_posit3, + sfx_bgsit1, + sfx_bgsit2, + sfx_sgtsit, + sfx_cacsit, + sfx_brssit, + sfx_cybsit, + sfx_spisit, + sfx_bspsit, + sfx_kntsit, + sfx_vilsit, + sfx_mansit, + sfx_pesit, + sfx_sklatk, + sfx_sgtatk, + sfx_skepch, + sfx_vilatk, + sfx_claw, + sfx_skeswg, + sfx_pldeth, + sfx_pdiehi, + sfx_podth1, + sfx_podth2, + sfx_podth3, + sfx_bgdth1, + sfx_bgdth2, + sfx_sgtdth, + sfx_cacdth, + sfx_skldth, + sfx_brsdth, + sfx_cybdth, + sfx_spidth, + sfx_bspdth, + sfx_vildth, + sfx_kntdth, + sfx_pedth, + sfx_skedth, + sfx_posact, + sfx_bgact, + sfx_dmact, + sfx_bspact, + sfx_bspwlk, + sfx_vilact, + sfx_noway, + sfx_barexp, + sfx_punch, + sfx_hoof, + sfx_metal, + sfx_chgun, + sfx_tink, + sfx_bdopn, + sfx_bdcls, + sfx_itmbk, + sfx_flame, + sfx_flamst, + sfx_getpow, + sfx_bospit, + sfx_boscub, + sfx_bossit, + sfx_bospn, + sfx_bosdth, + sfx_manatk, + sfx_mandth, + sfx_sssit, + sfx_ssdth, + sfx_keenpn, + sfx_keendt, + sfx_skeact, + sfx_skesit, + sfx_skeatk, + sfx_radio, + NUMSFX +} sfxenum_t; + +#endif diff --git a/games/NXDoom/src/doom/st_lib.c b/games/NXDoom/src/doom/st_lib.c new file mode 100644 index 00000000000..832bb66d387 --- /dev/null +++ b/games/NXDoom/src/doom/st_lib.c @@ -0,0 +1,283 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The status bar widget code. +// + + +#include +#include + +#include "deh_main.h" +#include "doomdef.h" + +#include "z_zone.h" +#include "v_video.h" + +#include "i_swap.h" +#include "i_system.h" + +#include "w_wad.h" + +#include "st_stuff.h" +#include "st_lib.h" +#include "r_local.h" + + +// +// Hack display negative frags. +// Loads and store the stminus lump. +// +patch_t* sttminus; + +void STlib_init(void) +{ + if (W_CheckNumForName(DEH_String("STTMINUS")) >= 0) + sttminus = (patch_t *) W_CacheLumpName(DEH_String("STTMINUS"), PU_STATIC); + else + sttminus = NULL; +} + + +// ? +void +STlib_initNum +( st_number_t* n, + int x, + int y, + patch_t** pl, + int* num, + boolean* on, + int width ) +{ + n->x = x; + n->y = y; + n->oldnum = 0; + n->width = width; + n->num = num; + n->on = on; + n->p = pl; +} + + +// +// A fairly efficient way to draw a number +// based on differences from the old number. +// Note: worth the trouble? +// +void +STlib_drawNum +( st_number_t* n, + boolean refresh ) +{ + + int numdigits = n->width; + int num = *n->num; + + int w = SHORT(n->p[0]->width); + int h = SHORT(n->p[0]->height); + int x = n->x; + + int neg; + + n->oldnum = *n->num; + + neg = num < 0; + + if (neg) + { + if (numdigits == 2 && num < -9) + num = -9; + else if (numdigits == 3 && num < -99) + num = -99; + + num = -num; + } + + // clear the area + x = n->x - numdigits*w; + + if (n->y - ST_Y < 0) + I_Error("drawNum: n->y - ST_Y < 0"); + + V_CopyRect(x, n->y - ST_Y, st_backing_screen, w*numdigits, h, x, n->y); + + // if non-number, do not draw it + if (num == 1994) + return; + + x = n->x; + + // in the special case of 0, you draw 0 + if (!num) + V_DrawPatch(x - w, n->y, n->p[ 0 ]); + + // draw the new number + while (num && numdigits--) + { + x -= w; + V_DrawPatch(x, n->y, n->p[ num % 10 ]); + num /= 10; + } + + // draw a minus sign if necessary + if (neg && sttminus) + V_DrawPatch(x - 8, n->y, sttminus); +} + + +// +void +STlib_updateNum +( st_number_t* n, + boolean refresh ) +{ + if (*n->on) STlib_drawNum(n, refresh); +} + + +// +void +STlib_initPercent +( st_percent_t* p, + int x, + int y, + patch_t** pl, + int* num, + boolean* on, + patch_t* percent ) +{ + STlib_initNum(&p->n, x, y, pl, num, on, 3); + p->p = percent; +} + + + + +void +STlib_updatePercent +( st_percent_t* per, + int refresh ) +{ + if (refresh && *per->n.on) + V_DrawPatch(per->n.x, per->n.y, per->p); + + STlib_updateNum(&per->n, refresh); +} + + + +void +STlib_initMultIcon +( st_multicon_t* i, + int x, + int y, + patch_t** il, + int* inum, + boolean* on ) +{ + i->x = x; + i->y = y; + i->oldinum = -1; + i->inum = inum; + i->on = on; + i->p = il; +} + + + +void +STlib_updateMultIcon +( st_multicon_t* mi, + boolean refresh ) +{ + int w; + int h; + int x; + int y; + + if (*mi->on + && (mi->oldinum != *mi->inum || refresh) + && (*mi->inum!=-1)) + { + if (mi->oldinum != -1) + { + x = mi->x - SHORT(mi->p[mi->oldinum]->leftoffset); + y = mi->y - SHORT(mi->p[mi->oldinum]->topoffset); + w = SHORT(mi->p[mi->oldinum]->width); + h = SHORT(mi->p[mi->oldinum]->height); + + if (y - ST_Y < 0) + I_Error("updateMultIcon: y - ST_Y < 0"); + + V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); + } + V_DrawPatch(mi->x, mi->y, mi->p[*mi->inum]); + mi->oldinum = *mi->inum; + } +} + + + +void +STlib_initBinIcon +( st_binicon_t* b, + int x, + int y, + patch_t* i, + boolean* val, + boolean* on ) +{ + b->x = x; + b->y = y; + b->oldval = false; + b->val = val; + b->on = on; + b->p = i; +} + + + +void +STlib_updateBinIcon +( st_binicon_t* bi, + boolean refresh ) +{ + int x; + int y; + int w; + int h; + + if (*bi->on + && (bi->oldval != *bi->val || refresh)) + { + x = bi->x - SHORT(bi->p->leftoffset); + y = bi->y - SHORT(bi->p->topoffset); + w = SHORT(bi->p->width); + h = SHORT(bi->p->height); + + if (y - ST_Y < 0) + I_Error("updateBinIcon: y - ST_Y < 0"); + + if (*bi->val) + V_DrawPatch(bi->x, bi->y, bi->p); + else + V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); + + bi->oldval = *bi->val; + } + +} + diff --git a/games/NXDoom/src/doom/st_lib.h b/games/NXDoom/src/doom/st_lib.h new file mode 100644 index 00000000000..3a8f5212512 --- /dev/null +++ b/games/NXDoom/src/doom/st_lib.h @@ -0,0 +1,209 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The status bar widget code. +// + +#ifndef __STLIB__ +#define __STLIB__ + + +// We are referring to patches. +#include "r_defs.h" + +// +// Typedefs of widgets +// + +// Number widget + +typedef struct +{ + // upper right-hand corner + // of the number (right-justified) + int x; + int y; + + // max # of digits in number + int width; + + // last number value + int oldnum; + + // pointer to current value + int* num; + + // pointer to boolean stating + // whether to update number + boolean* on; + + // list of patches for 0-9 + patch_t** p; + + // user data + int data; + +} st_number_t; + + + +// Percent widget ("child" of number widget, +// or, more precisely, contains a number widget.) +typedef struct +{ + // number information + st_number_t n; + + // percent sign graphic + patch_t* p; + +} st_percent_t; + + + +// Multiple Icon widget +typedef struct +{ + // center-justified location of icons + int x; + int y; + + // last icon number + int oldinum; + + // pointer to current icon + int* inum; + + // pointer to boolean stating + // whether to update icon + boolean* on; + + // list of icons + patch_t** p; + + // user data + int data; + +} st_multicon_t; + + + + +// Binary Icon widget + +typedef struct +{ + // center-justified location of icon + int x; + int y; + + // last icon value + boolean oldval; + + // pointer to current icon status + boolean* val; + + // pointer to boolean + // stating whether to update icon + boolean* on; + + + patch_t* p; // icon + int data; // user data + +} st_binicon_t; + + + +// +// Widget creation, access, and update routines +// + +// Initializes widget library. +// More precisely, initialize STMINUS, +// everything else is done somewhere else. +// +void STlib_init(void); + + + +// Number widget routines +void +STlib_initNum +( st_number_t* n, + int x, + int y, + patch_t** pl, + int* num, + boolean* on, + int width ); + +void +STlib_updateNum +( st_number_t* n, + boolean refresh ); + + +// Percent widget routines +void +STlib_initPercent +( st_percent_t* p, + int x, + int y, + patch_t** pl, + int* num, + boolean* on, + patch_t* percent ); + + +void +STlib_updatePercent +( st_percent_t* per, + int refresh ); + + +// Multiple Icon widget routines +void +STlib_initMultIcon +( st_multicon_t* mi, + int x, + int y, + patch_t** il, + int* inum, + boolean* on ); + + +void +STlib_updateMultIcon +( st_multicon_t* mi, + boolean refresh ); + +// Binary Icon widget routines + +void +STlib_initBinIcon +( st_binicon_t* b, + int x, + int y, + patch_t* i, + boolean* val, + boolean* on ); + +void +STlib_updateBinIcon +( st_binicon_t* bi, + boolean refresh ); + +#endif diff --git a/games/NXDoom/src/doom/st_stuff.c b/games/NXDoom/src/doom/st_stuff.c new file mode 100644 index 00000000000..da9b8bcf8c3 --- /dev/null +++ b/games/NXDoom/src/doom/st_stuff.c @@ -0,0 +1,1367 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Status bar code. +// Does the face/direction indicator animatin. +// Does palette indicators as well (red pain/berserk, bright pickup) +// + + + +#include +#include + +#include "i_system.h" +#include "i_video.h" +#include "z_zone.h" +#include "m_misc.h" +#include "m_random.h" +#include "w_wad.h" + +#include "deh_main.h" +#include "deh_misc.h" +#include "doomdef.h" +#include "doomkeys.h" + +#include "g_game.h" + +#include "st_stuff.h" +#include "st_lib.h" +#include "r_local.h" + +#include "p_local.h" +#include "p_inter.h" + +#include "am_map.h" +#include "m_cheat.h" + +#include "s_sound.h" + +// Needs access to LFB. +#include "v_video.h" + +// State. +#include "doomstat.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +// +// STATUS BAR DATA +// + + +// Palette indices. +// For damage/bonus red-/gold-shifts +#define STARTREDPALS 1 +#define STARTBONUSPALS 9 +#define NUMREDPALS 8 +#define NUMBONUSPALS 4 +// Radiation suit, green shift. +#define RADIATIONPAL 13 + +// Location of status bar +#define ST_X 0 +#define ST_X2 104 + +#define ST_FX 143 +#define ST_FY 169 + +// Number of status faces. +#define ST_NUMPAINFACES 5 +#define ST_NUMSTRAIGHTFACES 3 +#define ST_NUMTURNFACES 2 +#define ST_NUMSPECIALFACES 3 + +#define ST_FACESTRIDE \ + (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES) + +#define ST_NUMEXTRAFACES 2 + +#define ST_NUMFACES \ + (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES) + +#define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES) +#define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES) +#define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1) +#define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1) +#define ST_GODFACE (ST_NUMPAINFACES*ST_FACESTRIDE) +#define ST_DEADFACE (ST_GODFACE+1) + +#define ST_FACESX 143 +#define ST_FACESY 168 + +#define ST_EVILGRINCOUNT (2*TICRATE) +#define ST_STRAIGHTFACECOUNT (TICRATE/2) +#define ST_TURNCOUNT (1*TICRATE) +#define ST_OUCHCOUNT (1*TICRATE) +#define ST_RAMPAGEDELAY (2*TICRATE) + +#define ST_MUCHPAIN 20 + + +// Location and size of statistics, +// justified according to widget type. +// Problem is, within which space? STbar? Screen? +// Note: this could be read in by a lump. +// Problem is, is the stuff rendered +// into a buffer, +// or into the frame buffer? + +// AMMO number pos. +#define ST_AMMOWIDTH 3 +#define ST_AMMOX 44 +#define ST_AMMOY 171 + +// HEALTH number pos. +#define ST_HEALTHWIDTH 3 +#define ST_HEALTHX 90 +#define ST_HEALTHY 171 + +// Weapon pos. +#define ST_ARMSX 111 +#define ST_ARMSY 172 +#define ST_ARMSBGX 104 +#define ST_ARMSBGY 168 +#define ST_ARMSXSPACE 12 +#define ST_ARMSYSPACE 10 + +// Frags pos. +#define ST_FRAGSX 138 +#define ST_FRAGSY 171 +#define ST_FRAGSWIDTH 2 + +// ARMOR number pos. +#define ST_ARMORWIDTH 3 +#define ST_ARMORX 221 +#define ST_ARMORY 171 + +// Key icon positions. +#define ST_KEY0WIDTH 8 +#define ST_KEY0HEIGHT 5 +#define ST_KEY0X 239 +#define ST_KEY0Y 171 +#define ST_KEY1WIDTH ST_KEY0WIDTH +#define ST_KEY1X 239 +#define ST_KEY1Y 181 +#define ST_KEY2WIDTH ST_KEY0WIDTH +#define ST_KEY2X 239 +#define ST_KEY2Y 191 + +// Ammunition counter. +#define ST_AMMO0WIDTH 3 +#define ST_AMMO0HEIGHT 6 +#define ST_AMMO0X 288 +#define ST_AMMO0Y 173 +#define ST_AMMO1WIDTH ST_AMMO0WIDTH +#define ST_AMMO1X 288 +#define ST_AMMO1Y 179 +#define ST_AMMO2WIDTH ST_AMMO0WIDTH +#define ST_AMMO2X 288 +#define ST_AMMO2Y 191 +#define ST_AMMO3WIDTH ST_AMMO0WIDTH +#define ST_AMMO3X 288 +#define ST_AMMO3Y 185 + +// Indicate maximum ammunition. +// Only needed because backpack exists. +#define ST_MAXAMMO0WIDTH 3 +#define ST_MAXAMMO0HEIGHT 5 +#define ST_MAXAMMO0X 314 +#define ST_MAXAMMO0Y 173 +#define ST_MAXAMMO1WIDTH ST_MAXAMMO0WIDTH +#define ST_MAXAMMO1X 314 +#define ST_MAXAMMO1Y 179 +#define ST_MAXAMMO2WIDTH ST_MAXAMMO0WIDTH +#define ST_MAXAMMO2X 314 +#define ST_MAXAMMO2Y 191 +#define ST_MAXAMMO3WIDTH ST_MAXAMMO0WIDTH +#define ST_MAXAMMO3X 314 +#define ST_MAXAMMO3Y 185 + +// Dimensions given in characters. +#define ST_MSGWIDTH 52 + +// graphics are drawn to a backing screen and blitted to the real screen +pixel_t *st_backing_screen; + +// main player in game +static player_t* plyr; + +// ST_Start() has just been called +static boolean st_firsttime; + +// lump number for PLAYPAL +static int lu_palette; + +// used for making messages go away +static int st_msgcounter=0; + +// whether left-side main status bar is active +static boolean st_statusbaron; + +// whether status bar chat is active +static boolean st_chat; + +// value of st_chat before message popped up +static boolean st_oldchat; + +// !deathmatch +static boolean st_notdeathmatch; + +// !deathmatch && st_statusbaron +static boolean st_armson; + +// !deathmatch +static boolean st_fragson; + +// main bar left +static patch_t* sbar; + +// main bar right, for doom 1.0 +static patch_t* sbarr; + +// 0-9, tall numbers +static patch_t* tallnum[10]; + +// tall % sign +static patch_t* tallpercent; + +// 0-9, short, yellow (,different!) numbers +static patch_t* shortnum[10]; + +// 3 key-cards, 3 skulls +static patch_t* keys[NUMCARDS]; + +// face status patches +static patch_t* faces[ST_NUMFACES]; + +// face background +static patch_t* faceback; + + // main bar right +static patch_t* armsbg; + +// weapon ownership patches +static patch_t* arms[6][2]; + +// ready-weapon widget +static st_number_t w_ready; + + // in deathmatch only, summary of frags stats +static st_number_t w_frags; + +// health widget +static st_percent_t w_health; + +// arms background +static st_binicon_t w_armsbg; + + +// weapon ownership widgets +static st_multicon_t w_arms[6]; + +// face status widget +static st_multicon_t w_faces; + +// keycard widgets +static st_multicon_t w_keyboxes[3]; + +// armor widget +static st_percent_t w_armor; + +// ammo widgets +static st_number_t w_ammo[4]; + +// max ammo widgets +static st_number_t w_maxammo[4]; + + + + // number of frags so far in deathmatch +static int st_fragscount; + +// used to use appopriately pained face +static int st_oldhealth = -1; + +// used for evil grin +static boolean oldweaponsowned[NUMWEAPONS]; + + // count until face changes +static int st_facecount = 0; + +// current face index, used by w_faces +static int st_faceindex = 0; + +// holds key-type for each key box on bar +static int keyboxes[3]; + +// a random number per tick +static int st_randomnumber; + +cheatseq_t cheat_mus = CHEAT("idmus", 2); +cheatseq_t cheat_god = CHEAT("iddqd", 0); +cheatseq_t cheat_ammo = CHEAT("idkfa", 0); +cheatseq_t cheat_ammonokey = CHEAT("idfa", 0); +cheatseq_t cheat_noclip = CHEAT("idspispopd", 0); +cheatseq_t cheat_commercial_noclip = CHEAT("idclip", 0); + +cheatseq_t cheat_powerup[7] = +{ + CHEAT("idbeholdv", 0), + CHEAT("idbeholds", 0), + CHEAT("idbeholdi", 0), + CHEAT("idbeholdr", 0), + CHEAT("idbeholda", 0), + CHEAT("idbeholdl", 0), + CHEAT("idbehold", 0), +}; + +cheatseq_t cheat_choppers = CHEAT("idchoppers", 0); +cheatseq_t cheat_clev = CHEAT("idclev", 2); +cheatseq_t cheat_mypos = CHEAT("idmypos", 0); + + +// +// STATUS BAR CODE +// +void ST_Stop(void); + +void ST_refreshBackground(void) +{ + + if (st_statusbaron) + { + V_UseBuffer(st_backing_screen); + + V_DrawPatch(ST_X, 0, sbar); + + // draw right side of bar if needed (Doom 1.0) + if (sbarr) + V_DrawPatch(ST_ARMSBGX, 0, sbarr); + + if (netgame) + V_DrawPatch(ST_FX, 0, faceback); + + V_RestoreBuffer(); + + V_CopyRect(ST_X, 0, st_backing_screen, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y); + } + +} + + +// Respond to keyboard input events, +// intercept cheats. +boolean +ST_Responder (event_t* ev) +{ + int i; + + // Filter automap on/off. + if (ev->type == ev_keyup + && ((ev->data1 & 0xffff0000) == AM_MSGHEADER)) + { + switch(ev->data1) + { + case AM_MSGENTERED: + st_firsttime = true; + break; + + case AM_MSGEXITED: + // fprintf(stderr, "AM exited\n"); + break; + } + } + + // if a user keypress... + else if (ev->type == ev_keydown) + { + if (!netgame && gameskill != sk_nightmare) + { + // 'dqd' cheat for toggleable god mode + if (cht_CheckCheat(&cheat_god, ev->data2)) + { + plyr->cheats ^= CF_GODMODE; + if (plyr->cheats & CF_GODMODE) + { + if (plyr->mo) + plyr->mo->health = deh_god_mode_health; + + plyr->health = deh_god_mode_health; + plyr->message = DEH_String(STSTR_DQDON); + } + else + plyr->message = DEH_String(STSTR_DQDOFF); + } + // 'fa' cheat for killer fucking arsenal + else if (cht_CheckCheat(&cheat_ammonokey, ev->data2)) + { + plyr->armorpoints = deh_idfa_armor; + plyr->armortype = deh_idfa_armor_class; + + for (i=0;iweaponowned[i] = true; + + for (i=0;iammo[i] = plyr->maxammo[i]; + + plyr->message = DEH_String(STSTR_FAADDED); + } + // 'kfa' cheat for key full ammo + else if (cht_CheckCheat(&cheat_ammo, ev->data2)) + { + plyr->armorpoints = deh_idkfa_armor; + plyr->armortype = deh_idkfa_armor_class; + + for (i=0;iweaponowned[i] = true; + + for (i=0;iammo[i] = plyr->maxammo[i]; + + for (i=0;icards[i] = true; + + plyr->message = DEH_String(STSTR_KFAADDED); + } + // 'mus' cheat for changing music + else if (cht_CheckCheat(&cheat_mus, ev->data2)) + { + + char buf[3]; + int musnum; + + plyr->message = DEH_String(STSTR_MUS); + cht_GetParam(&cheat_mus, buf); + + // Note: The original v1.9 had a bug that tried to play back + // the Doom II music regardless of gamemode. This was fixed + // in the Ultimate Doom executable so that it would work for + // the Doom 1 music as well. + + if (gamemode == commercial || gameversion < exe_ultimate) + { + musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1; + + if (((buf[0]-'0')*10 + buf[1]-'0') > 35 + && gameversion >= exe_doom_1_8) + plyr->message = DEH_String(STSTR_NOMUS); + else + S_ChangeMusic(musnum, 1); + } + else + { + musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1'); + + if (((buf[0]-'1')*9 + buf[1]-'1') > 31) + plyr->message = DEH_String(STSTR_NOMUS); + else + S_ChangeMusic(musnum, 1); + } + } + else if ( (logical_gamemission == doom + && cht_CheckCheat(&cheat_noclip, ev->data2)) + || (logical_gamemission != doom + && cht_CheckCheat(&cheat_commercial_noclip,ev->data2))) + { + // Noclip cheat. + // For Doom 1, use the idspipsopd cheat; for all others, use + // idclip + + plyr->cheats ^= CF_NOCLIP; + + if (plyr->cheats & CF_NOCLIP) + plyr->message = DEH_String(STSTR_NCON); + else + plyr->message = DEH_String(STSTR_NCOFF); + } + // 'behold?' power-up cheats + for (i=0;i<6;i++) + { + if (cht_CheckCheat(&cheat_powerup[i], ev->data2)) + { + if (!plyr->powers[i]) + P_GivePower( plyr, i); + else if (i!=pw_strength) + plyr->powers[i] = 1; + else + plyr->powers[i] = 0; + + plyr->message = DEH_String(STSTR_BEHOLDX); + } + } + + // 'behold' power-up menu + if (cht_CheckCheat(&cheat_powerup[6], ev->data2)) + { + plyr->message = DEH_String(STSTR_BEHOLD); + } + // 'choppers' invulnerability & chainsaw + else if (cht_CheckCheat(&cheat_choppers, ev->data2)) + { + plyr->weaponowned[wp_chainsaw] = true; + plyr->powers[pw_invulnerability] = true; + plyr->message = DEH_String(STSTR_CHOPPERS); + } + // 'mypos' for player position + else if (cht_CheckCheat(&cheat_mypos, ev->data2)) + { + static char buf[ST_MSGWIDTH]; + M_snprintf(buf, sizeof(buf), "ang=0x%x;x,y=(0x%x,0x%x)", + players[consoleplayer].mo->angle, + players[consoleplayer].mo->x, + players[consoleplayer].mo->y); + plyr->message = buf; + } + } + + // 'clev' change-level cheat + if (!netgame && cht_CheckCheat(&cheat_clev, ev->data2)) + { + char buf[3]; + int epsd; + int map; + + cht_GetParam(&cheat_clev, buf); + + if (gamemode == commercial) + { + epsd = 0; + map = (buf[0] - '0')*10 + buf[1] - '0'; + } + else + { + epsd = buf[0] - '0'; + map = buf[1] - '0'; + + // Chex.exe always warps to episode 1. + + if (gameversion == exe_chex) + { + if (epsd > 1) + { + epsd = 1; + } + if (map > 5) + { + map = 5; + } + } + } + + // Catch invalid maps. + if (gamemode != commercial) + { + if (epsd < 1) + { + return false; + } + if (epsd > 4) + { + return false; + } + if (epsd == 4 && gameversion < exe_ultimate) + { + return false; + } + if (map < 1) + { + return false; + } + if (map > 9) + { + return false; + } + } + else + { + if (map < 1) + { + return false; + } + if (map > 40) + { + return false; + } + } + + // So be it. + plyr->message = DEH_String(STSTR_CLEV); + G_DeferedInitNew(gameskill, epsd, map); + } + } + return false; +} + + + +int ST_calcPainOffset(void) +{ + int health; + static int lastcalc; + static int oldhealth = -1; + + health = plyr->health > 100 ? 100 : plyr->health; + + if (health != oldhealth) + { + lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101); + oldhealth = health; + } + return lastcalc; +} + + +// +// This is a not-very-pretty routine which handles +// the face states and their timing. +// the precedence of expressions is: +// dead > evil grin > turned head > straight ahead +// +void ST_updateFaceWidget(void) +{ + int i; + angle_t badguyangle; + angle_t diffang; + static int lastattackdown = -1; + static int priority = 0; + boolean doevilgrin; + + if (priority < 10) + { + // dead + if (!plyr->health) + { + priority = 9; + st_faceindex = ST_DEADFACE; + st_facecount = 1; + } + } + + if (priority < 9) + { + if (plyr->bonuscount) + { + // picking up bonus + doevilgrin = false; + + for (i=0;iweaponowned[i]) + { + doevilgrin = true; + oldweaponsowned[i] = plyr->weaponowned[i]; + } + } + if (doevilgrin) + { + // evil grin if just picked up weapon + priority = 8; + st_facecount = ST_EVILGRINCOUNT; + st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET; + } + } + + } + + if (priority < 8) + { + if (plyr->damagecount + && plyr->attacker + && plyr->attacker != plyr->mo) + { + // being attacked + priority = 7; + + if (plyr->health - st_oldhealth > ST_MUCHPAIN) + { + st_facecount = ST_TURNCOUNT; + st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; + } + else + { + badguyangle = R_PointToAngle2(plyr->mo->x, + plyr->mo->y, + plyr->attacker->x, + plyr->attacker->y); + + if (badguyangle > plyr->mo->angle) + { + // whether right or left + diffang = badguyangle - plyr->mo->angle; + i = diffang > ANG180; + } + else + { + // whether left or right + diffang = plyr->mo->angle - badguyangle; + i = diffang <= ANG180; + } // confusing, aint it? + + + st_facecount = ST_TURNCOUNT; + st_faceindex = ST_calcPainOffset(); + + if (diffang < ANG45) + { + // head-on + st_faceindex += ST_RAMPAGEOFFSET; + } + else if (i) + { + // turn face right + st_faceindex += ST_TURNOFFSET; + } + else + { + // turn face left + st_faceindex += ST_TURNOFFSET+1; + } + } + } + } + + if (priority < 7) + { + // getting hurt because of your own damn stupidity + if (plyr->damagecount) + { + if (plyr->health - st_oldhealth > ST_MUCHPAIN) + { + priority = 7; + st_facecount = ST_TURNCOUNT; + st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; + } + else + { + priority = 6; + st_facecount = ST_TURNCOUNT; + st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; + } + + } + + } + + if (priority < 6) + { + // rapid firing + if (plyr->attackdown) + { + if (lastattackdown==-1) + lastattackdown = ST_RAMPAGEDELAY; + else if (!--lastattackdown) + { + priority = 5; + st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; + st_facecount = 1; + lastattackdown = 1; + } + } + else + lastattackdown = -1; + + } + + if (priority < 5) + { + // invulnerability + if ((plyr->cheats & CF_GODMODE) + || plyr->powers[pw_invulnerability]) + { + priority = 4; + + st_faceindex = ST_GODFACE; + st_facecount = 1; + + } + + } + + // look left or look right if the facecount has timed out + if (!st_facecount) + { + st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3); + st_facecount = ST_STRAIGHTFACECOUNT; + priority = 0; + } + + st_facecount--; + +} + +void ST_updateWidgets(void) +{ + static int largeammo = 1994; // means "n/a" + int i; + + // must redirect the pointer if the ready weapon has changed. + // if (w_ready.data != plyr->readyweapon) + // { + if (weaponinfo[plyr->readyweapon].ammo == am_noammo) + w_ready.num = &largeammo; + else + w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo]; + //{ + // static int tic=0; + // static int dir=-1; + // if (!(tic&15)) + // plyr->ammo[weaponinfo[plyr->readyweapon].ammo]+=dir; + // if (plyr->ammo[weaponinfo[plyr->readyweapon].ammo] == -100) + // dir = 1; + // tic++; + // } + w_ready.data = plyr->readyweapon; + + // if (*w_ready.on) + // STlib_updateNum(&w_ready, true); + // refresh weapon change + // } + + // update keycard multiple widgets + for (i=0;i<3;i++) + { + keyboxes[i] = plyr->cards[i] ? i : -1; + + if (plyr->cards[i+3]) + keyboxes[i] = i+3; + } + + // refresh everything if this is him coming back to life + ST_updateFaceWidget(); + + // used by the w_armsbg widget + st_notdeathmatch = !deathmatch; + + // used by w_arms[] widgets + st_armson = st_statusbaron && !deathmatch; + + // used by w_frags widget + st_fragson = deathmatch && st_statusbaron; + st_fragscount = 0; + + for (i=0 ; ifrags[i]; + else + st_fragscount -= plyr->frags[i]; + } + + // get rid of chat window if up because of message + if (!--st_msgcounter) + st_chat = st_oldchat; + +} + +void ST_Ticker (void) +{ + + st_randomnumber = M_Random(); + ST_updateWidgets(); + st_oldhealth = plyr->health; + +} + +static int st_palette = 0; + +void ST_doPaletteStuff(void) +{ + + int palette; + byte* pal; + int cnt; + int bzc; + + cnt = plyr->damagecount; + + if (plyr->powers[pw_strength]) + { + // slowly fade the berzerk out + bzc = 12 - (plyr->powers[pw_strength]>>6); + + if (bzc > cnt) + cnt = bzc; + } + + if (cnt) + { + palette = (cnt+7)>>3; + + if (palette >= NUMREDPALS) + palette = NUMREDPALS-1; + + palette += STARTREDPALS; + } + + else if (plyr->bonuscount) + { + palette = (plyr->bonuscount+7)>>3; + + if (palette >= NUMBONUSPALS) + palette = NUMBONUSPALS-1; + + palette += STARTBONUSPALS; + } + + else if ( plyr->powers[pw_ironfeet] > 4*32 + || plyr->powers[pw_ironfeet]&8) + palette = RADIATIONPAL; + else + palette = 0; + + // In Chex Quest, the player never sees red. Instead, the + // radiation suit palette is used to tint the screen green, + // as though the player is being covered in goo by an + // attacking flemoid. + + if (gameversion == exe_chex + && palette >= STARTREDPALS && palette < STARTREDPALS + NUMREDPALS) + { + palette = RADIATIONPAL; + } + + if (palette != st_palette) + { + st_palette = palette; + pal = (byte *) W_CacheLumpNum (lu_palette, PU_CACHE)+palette*768; + I_SetPalette (pal); + } + +} + +void ST_drawWidgets(boolean refresh) +{ + int i; + + // used by w_arms[] widgets + st_armson = st_statusbaron && !deathmatch; + + // used by w_frags widget + st_fragson = deathmatch && st_statusbaron; + + STlib_updateNum(&w_ready, refresh); + + for (i=0;i<4;i++) + { + STlib_updateNum(&w_ammo[i], refresh); + STlib_updateNum(&w_maxammo[i], refresh); + } + + STlib_updatePercent(&w_health, refresh); + STlib_updatePercent(&w_armor, refresh); + + STlib_updateBinIcon(&w_armsbg, refresh); + + for (i=0;i<6;i++) + STlib_updateMultIcon(&w_arms[i], refresh); + + STlib_updateMultIcon(&w_faces, refresh); + + for (i=0;i<3;i++) + STlib_updateMultIcon(&w_keyboxes[i], refresh); + + STlib_updateNum(&w_frags, refresh); + +} + +void ST_doRefresh(void) +{ + + st_firsttime = false; + + // draw status bar background to off-screen buff + ST_refreshBackground(); + + // and refresh all widgets + ST_drawWidgets(true); + +} + +void ST_diffDraw(void) +{ + // update all widgets + ST_drawWidgets(false); +} + +void ST_Drawer (boolean fullscreen, boolean refresh) +{ + + st_statusbaron = (!fullscreen) || automapactive; + st_firsttime = st_firsttime || refresh; + + // Do red-/gold-shifts from damage/items + ST_doPaletteStuff(); + + // If just after ST_Start(), refresh all + if (st_firsttime) ST_doRefresh(); + // Otherwise, update as little as possible + else ST_diffDraw(); + +} + +typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + +// Iterates through all graphics to be loaded or unloaded, along with +// the variable they use, invoking the specified callback function. + +static void ST_loadUnloadGraphics(load_callback_t callback) +{ + + int i; + int j; + int facenum; + + char namebuf[9]; + + // Load the numbers, tall and short + for (i=0;i<10;i++) + { + DEH_snprintf(namebuf, 9, "STTNUM%d", i); + callback(namebuf, &tallnum[i]); + + DEH_snprintf(namebuf, 9, "STYSNUM%d", i); + callback(namebuf, &shortnum[i]); + } + + // Load percent key. + //Note: why not load STMINUS here, too? + + callback(DEH_String("STTPRCNT"), &tallpercent); + + // key cards + for (i=0;i= 0) + { + callback(DEH_String("STBAR"), &sbar); + sbarr = NULL; + } + else + { + callback(DEH_String("STMBARL"), &sbar); + callback(DEH_String("STMBARR"), &sbarr); + } + + // face states + facenum = 0; + for (i=0; iweaponowned[i]; + + for (i=0;i<3;i++) + keyboxes[i] = -1; + + STlib_init(); + +} + + + +void ST_createWidgets(void) +{ + + int i; + + // ready weapon ammo + STlib_initNum(&w_ready, + ST_AMMOX, + ST_AMMOY, + tallnum, + &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], + &st_statusbaron, + ST_AMMOWIDTH ); + + // the last weapon type + w_ready.data = plyr->readyweapon; + + // health percentage + STlib_initPercent(&w_health, + ST_HEALTHX, + ST_HEALTHY, + tallnum, + &plyr->health, + &st_statusbaron, + tallpercent); + + // arms background + STlib_initBinIcon(&w_armsbg, + ST_ARMSBGX, + ST_ARMSBGY, + armsbg, + &st_notdeathmatch, + &st_statusbaron); + + // weapons owned + for(i=0;i<6;i++) + { + STlib_initMultIcon(&w_arms[i], + ST_ARMSX+(i%3)*ST_ARMSXSPACE, + ST_ARMSY+(i/3)*ST_ARMSYSPACE, + arms[i], + &plyr->weaponowned[i+1], + &st_armson); + } + + // frags sum + STlib_initNum(&w_frags, + ST_FRAGSX, + ST_FRAGSY, + tallnum, + &st_fragscount, + &st_fragson, + ST_FRAGSWIDTH); + + // faces + STlib_initMultIcon(&w_faces, + ST_FACESX, + ST_FACESY, + faces, + &st_faceindex, + &st_statusbaron); + + // armor percentage - should be colored later + STlib_initPercent(&w_armor, + ST_ARMORX, + ST_ARMORY, + tallnum, + &plyr->armorpoints, + &st_statusbaron, tallpercent); + + // keyboxes 0-2 + STlib_initMultIcon(&w_keyboxes[0], + ST_KEY0X, + ST_KEY0Y, + keys, + &keyboxes[0], + &st_statusbaron); + + STlib_initMultIcon(&w_keyboxes[1], + ST_KEY1X, + ST_KEY1Y, + keys, + &keyboxes[1], + &st_statusbaron); + + STlib_initMultIcon(&w_keyboxes[2], + ST_KEY2X, + ST_KEY2Y, + keys, + &keyboxes[2], + &st_statusbaron); + + // ammo count (all four kinds) + STlib_initNum(&w_ammo[0], + ST_AMMO0X, + ST_AMMO0Y, + shortnum, + &plyr->ammo[0], + &st_statusbaron, + ST_AMMO0WIDTH); + + STlib_initNum(&w_ammo[1], + ST_AMMO1X, + ST_AMMO1Y, + shortnum, + &plyr->ammo[1], + &st_statusbaron, + ST_AMMO1WIDTH); + + STlib_initNum(&w_ammo[2], + ST_AMMO2X, + ST_AMMO2Y, + shortnum, + &plyr->ammo[2], + &st_statusbaron, + ST_AMMO2WIDTH); + + STlib_initNum(&w_ammo[3], + ST_AMMO3X, + ST_AMMO3Y, + shortnum, + &plyr->ammo[3], + &st_statusbaron, + ST_AMMO3WIDTH); + + // max ammo count (all four kinds) + STlib_initNum(&w_maxammo[0], + ST_MAXAMMO0X, + ST_MAXAMMO0Y, + shortnum, + &plyr->maxammo[0], + &st_statusbaron, + ST_MAXAMMO0WIDTH); + + STlib_initNum(&w_maxammo[1], + ST_MAXAMMO1X, + ST_MAXAMMO1Y, + shortnum, + &plyr->maxammo[1], + &st_statusbaron, + ST_MAXAMMO1WIDTH); + + STlib_initNum(&w_maxammo[2], + ST_MAXAMMO2X, + ST_MAXAMMO2Y, + shortnum, + &plyr->maxammo[2], + &st_statusbaron, + ST_MAXAMMO2WIDTH); + + STlib_initNum(&w_maxammo[3], + ST_MAXAMMO3X, + ST_MAXAMMO3Y, + shortnum, + &plyr->maxammo[3], + &st_statusbaron, + ST_MAXAMMO3WIDTH); + +} + +static boolean st_stopped = true; + + +void ST_Start (void) +{ + + if (!st_stopped) + ST_Stop(); + + ST_initData(); + ST_createWidgets(); + st_stopped = false; + +} + +void ST_Stop (void) +{ + if (st_stopped) + return; + + I_SetPalette (W_CacheLumpNum (lu_palette, PU_CACHE)); + + st_stopped = true; +} + +void ST_Init (void) +{ + ST_loadData(); + st_backing_screen = (pixel_t *) Z_Malloc(ST_WIDTH * ST_HEIGHT * sizeof(*st_backing_screen), PU_STATIC, 0); +} + diff --git a/games/NXDoom/src/doom/st_stuff.h b/games/NXDoom/src/doom/st_stuff.h new file mode 100644 index 00000000000..0cf28bb631e --- /dev/null +++ b/games/NXDoom/src/doom/st_stuff.h @@ -0,0 +1,69 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Status bar code. +// Does the face/direction indicator animatin. +// Does palette indicators as well (red pain/berserk, bright pickup) +// + +#ifndef __STSTUFF_H__ +#define __STSTUFF_H__ + +#include "doomtype.h" +#include "d_event.h" +#include "m_cheat.h" + +// Size of statusbar. +// Now sensitive for scaling. +#define ST_HEIGHT 32 +#define ST_WIDTH SCREENWIDTH +#define ST_Y (SCREENHEIGHT - ST_HEIGHT) + + +// +// STATUS BAR +// + +// Called by main loop. +boolean ST_Responder (event_t* ev); + +// Called by main loop. +void ST_Ticker (void); + +// Called by main loop. +void ST_Drawer (boolean fullscreen, boolean refresh); + +// Called when the console player is spawned on each level. +void ST_Start (void); + +// Called by startup code. +void ST_Init (void); + + + +extern pixel_t *st_backing_screen; +extern cheatseq_t cheat_mus; +extern cheatseq_t cheat_god; +extern cheatseq_t cheat_ammo; +extern cheatseq_t cheat_ammonokey; +extern cheatseq_t cheat_noclip; +extern cheatseq_t cheat_commercial_noclip; +extern cheatseq_t cheat_powerup[7]; +extern cheatseq_t cheat_choppers; +extern cheatseq_t cheat_clev; +extern cheatseq_t cheat_mypos; + + +#endif diff --git a/games/NXDoom/src/doom/statdump.c b/games/NXDoom/src/doom/statdump.c new file mode 100644 index 00000000000..ae6814a31f7 --- /dev/null +++ b/games/NXDoom/src/doom/statdump.c @@ -0,0 +1,357 @@ + /* + + Copyright(C) 2005-2014 Simon Howard + + 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. + + -- + + Functions for presenting the information captured from the statistics + buffer to a file. + + */ + +#include +#include +#include + +#include "d_player.h" +#include "d_mode.h" +#include "m_argv.h" +#include "m_misc.h" + +#include "statdump.h" + +/* Par times for E1M1-E1M9. */ +static const int doom1_par_times[] = +{ + 30, 75, 120, 90, 165, 180, 180, 30, 165, +}; + +/* Par times for MAP01-MAP09. */ +static const int doom2_par_times[] = +{ + 30, 90, 120, 120, 90, 150, 120, 120, 270, +}; + +/* Player colors. */ +static const char *player_colors[] = +{ + "Green", "Indigo", "Brown", "Red" +}; + +// Array of end-of-level statistics that have been captured. + +#define MAX_CAPTURES 32 +static wbstartstruct_t captured_stats[MAX_CAPTURES]; +static int num_captured_stats = 0; + +static GameMission_t discovered_gamemission = none; + +/* Try to work out whether this is a Doom 1 or Doom 2 game, by looking + * at the episode and map, and the par times. This is used to decide + * how to format the level name. Unfortunately, in some cases it is + * impossible to determine whether this is Doom 1 or Doom 2. */ + +static void DiscoverGamemode(const wbstartstruct_t *stats, int num_stats) +{ + int partime; + int level; + int i; + + if (discovered_gamemission != none) + { + return; + } + + for (i=0; i 0) + { + discovered_gamemission = doom; + return; + } + + /* This is episode 1. If this is level 10 or higher, + it must be Doom 2. */ + + if (level >= 9) + { + discovered_gamemission = doom2; + return; + } + + /* Try to work out if this is Doom 1 or Doom 2 by looking + at the par time. */ + + partime = stats[i].partime; + + if (partime == doom1_par_times[level] * TICRATE + && partime != doom2_par_times[level] * TICRATE) + { + discovered_gamemission = doom; + return; + } + + if (partime != doom1_par_times[level] * TICRATE + && partime == doom2_par_times[level] * TICRATE) + { + discovered_gamemission = doom2; + return; + } + } +} + +/* Returns the number of players active in the given stats buffer. */ + +static int GetNumPlayers(const wbstartstruct_t *stats) +{ + int i; + int num_players = 0; + + for (i=0; iplyr[i].in) + { + ++num_players; + } + } + + return num_players; +} + +static void PrintBanner(FILE *stream) +{ + fprintf(stream, "===========================================\n"); +} + +static void PrintPercentage(FILE *stream, int amount, int total) +{ + if (total == 0) + { + fprintf(stream, "0"); + } + else + { + fprintf(stream, "%i / %i", amount, total); + + // statdump.exe is a 16-bit program, so very occasionally an + // integer overflow can occur when doing this calculation with + // a large value. Therefore, cast to short to give the same + // output. + + fprintf(stream, " (%i%%)", (short) (amount * 100) / total); + } +} + +/* Display statistics for a single player. */ + +static void PrintPlayerStats(FILE *stream, const wbstartstruct_t *stats, + int player_num) +{ + const wbplayerstruct_t *player = &stats->plyr[player_num]; + + fprintf(stream, "Player %i (%s):\n", player_num + 1, + player_colors[player_num]); + + /* Kills percentage */ + + fprintf(stream, "\tKills: "); + PrintPercentage(stream, player->skills, stats->maxkills); + fprintf(stream, "\n"); + + /* Items percentage */ + + fprintf(stream, "\tItems: "); + PrintPercentage(stream, player->sitems, stats->maxitems); + fprintf(stream, "\n"); + + /* Secrets percentage */ + + fprintf(stream, "\tSecrets: "); + PrintPercentage(stream, player->ssecret, stats->maxsecret); + fprintf(stream, "\n"); +} + +/* Frags table for multiplayer games. */ + +static void PrintFragsTable(FILE *stream, const wbstartstruct_t *stats) +{ + int x, y; + + fprintf(stream, "Frags:\n"); + + /* Print header */ + + fprintf(stream, "\t\t"); + + for (x=0; xplyr[x].in) + { + continue; + } + + fprintf(stream, "%s\t", player_colors[x]); + } + + fprintf(stream, "\n"); + + fprintf(stream, "\t\t-------------------------------- VICTIMS\n"); + + /* Print table */ + + for (y=0; yplyr[y].in) + { + continue; + } + + fprintf(stream, "\t%s\t|", player_colors[y]); + + for (x=0; xplyr[x].in) + { + continue; + } + + fprintf(stream, "%i\t", stats->plyr[y].frags[x]); + } + + fprintf(stream, "\n"); + } + + fprintf(stream, "\t\t|\n"); + fprintf(stream, "\t KILLERS\n"); +} + +/* Displays the level name: MAPxy or ExMy, depending on game mode. */ + +static void PrintLevelName(FILE *stream, int episode, int level) +{ + PrintBanner(stream); + + switch (discovered_gamemission) + { + + case doom: + fprintf(stream, "E%iM%i\n", episode + 1, level + 1); + break; + case doom2: + fprintf(stream, "MAP%02i\n", level + 1); + break; + default: + case none: + fprintf(stream, "E%iM%i / MAP%02i\n", + episode + 1, level + 1, level + 1); + break; + } + + PrintBanner(stream); +} + +/* Print details of a statistics buffer to the given file. */ + +static void PrintStats(FILE *stream, const wbstartstruct_t *stats) +{ + short leveltime, partime; + int i; + + PrintLevelName(stream, stats->epsd, stats->last); + fprintf(stream, "\n"); + + leveltime = stats->plyr[0].stime / TICRATE; + partime = stats->partime / TICRATE; + fprintf(stream, "Time: %i:%02i", leveltime / 60, leveltime % 60); + fprintf(stream, " (par: %i:%02i)\n", partime / 60, partime % 60); + fprintf(stream, "\n"); + + for (i=0; iplyr[i].in) + { + PrintPlayerStats(stream, stats, i); + } + } + + if (GetNumPlayers(stats) >= 2) + { + PrintFragsTable(stream, stats); + } + + fprintf(stream, "\n"); +} + +void StatCopy(const wbstartstruct_t *stats) +{ + if (M_ParmExists("-statdump") && num_captured_stats < MAX_CAPTURES) + { + memcpy(&captured_stats[num_captured_stats], stats, + sizeof(wbstartstruct_t)); + ++num_captured_stats; + } +} + +void StatDump(void) +{ + FILE *dumpfile; + int i; + + //! + // @category compat + // @arg + // + // Dump statistics information to the specified file on the levels + // that were played. The output from this option matches the output + // from statdump.exe (see ctrlapi.zip in the /idgames archive). + // + + i = M_CheckParmWithArgs("-statdump", 1); + + if (i > 0) + { + printf("Statistics captured for %i level(s)\n", num_captured_stats); + + // We actually know what the real gamemission is, but this has + // to match the output from statdump.exe. + + DiscoverGamemode(captured_stats, num_captured_stats); + + // Allow "-" as output file, for stdout. + + if (strcmp(myargv[i + 1], "-") != 0) + { + dumpfile = M_fopen(myargv[i + 1], "w"); + } + else + { + dumpfile = stdout; + } + + for (i = 0; i < num_captured_stats; ++i) + { + PrintStats(dumpfile, &captured_stats[i]); + } + + if (dumpfile != stdout) + { + fclose(dumpfile); + } + } +} + diff --git a/games/NXDoom/src/doom/statdump.h b/games/NXDoom/src/doom/statdump.h new file mode 100644 index 00000000000..f4f11efe666 --- /dev/null +++ b/games/NXDoom/src/doom/statdump.h @@ -0,0 +1,23 @@ + /* + + Copyright(C) 2005-2014 Simon Howard + + 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. + + */ + +#ifndef DOOM_STATDUMP_H +#define DOOM_STATDUMP_H + +void StatCopy(const wbstartstruct_t *stats); +void StatDump(void); + +#endif /* #ifndef DOOM_STATDUMP_H */ diff --git a/games/NXDoom/src/doom/wi_stuff.c b/games/NXDoom/src/doom/wi_stuff.c new file mode 100644 index 00000000000..965cc557169 --- /dev/null +++ b/games/NXDoom/src/doom/wi_stuff.c @@ -0,0 +1,1833 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Intermission screens. +// + + +#include + +#include "z_zone.h" + +#include "m_misc.h" +#include "m_random.h" + +#include "deh_main.h" +#include "i_swap.h" +#include "i_system.h" + +#include "w_wad.h" + +#include "g_game.h" + +#include "r_local.h" +#include "s_sound.h" + +#include "doomstat.h" + +// Data. +#include "sounds.h" + +// Needs access to LFB. +#include "v_video.h" + +#include "wi_stuff.h" + +// +// Data needed to add patches to full screen intermission pics. +// Patches are statistics messages, and animations. +// Loads of by-pixel layout and placement, offsets etc. +// + + +// +// Different vetween registered DOOM (1994) and +// Ultimate DOOM - Final edition (retail, 1995?). +// This is supposedly ignored for commercial +// release (aka DOOM II), which had 34 maps +// in one episode. So there. +#define NUMEPISODES 4 +#define NUMMAPS 9 + + +// in tics +//U #define PAUSELEN (TICRATE*2) +//U #define SCORESTEP 100 +//U #define ANIMPERIOD 32 +// pixel distance from "(YOU)" to "PLAYER N" +//U #define STARDIST 10 +//U #define WK 1 + + +// GLOBAL LOCATIONS +#define WI_TITLEY 2 +#define WI_SPACINGY 33 + +// SINGPLE-PLAYER STUFF +#define SP_STATSX 50 +#define SP_STATSY 50 + +#define SP_TIMEX 16 +#define SP_TIMEY (SCREENHEIGHT-32) + + +// NET GAME STUFF +#define NG_STATSY 50 +#define NG_STATSX (32 + SHORT(star->width)/2 + 32*!dofrags) + +#define NG_SPACINGX 64 + + +// DEATHMATCH STUFF +#define DM_MATRIXX 42 +#define DM_MATRIXY 68 + +#define DM_SPACINGX 40 + +#define DM_TOTALSX 269 + +#define DM_KILLERSX 10 +#define DM_KILLERSY 100 +#define DM_VICTIMSX 5 +#define DM_VICTIMSY 50 + + + + +typedef enum +{ + ANIM_ALWAYS, + ANIM_RANDOM, + ANIM_LEVEL + +} animenum_t; + +typedef struct +{ + int x; + int y; + +} point_t; + + +// +// Animation. +// There is another anim_t used in p_spec. +// +typedef struct +{ + animenum_t type; + + // period in tics between animations + int period; + + // number of animation frames + int nanims; + + // location of animation + point_t loc; + + // ALWAYS: n/a, + // RANDOM: period deviation (<256), + // LEVEL: level + int data1; + + // ALWAYS: n/a, + // RANDOM: random base period, + // LEVEL: n/a + int data2; + + // actual graphics for frames of animations + patch_t* p[3]; + + // following must be initialized to zero before use! + + // next value of bcnt (used in conjunction with period) + int nexttic; + + // last drawn animation frame + int lastdrawn; + + // next frame number to animate + int ctr; + + // used by RANDOM and LEVEL when animating + int state; + +} anim_t; + + +static point_t lnodes[NUMEPISODES][NUMMAPS] = +{ + // Episode 0 World Map + { + { 185, 164 }, // location of level 0 (CJ) + { 148, 143 }, // location of level 1 (CJ) + { 69, 122 }, // location of level 2 (CJ) + { 209, 102 }, // location of level 3 (CJ) + { 116, 89 }, // location of level 4 (CJ) + { 166, 55 }, // location of level 5 (CJ) + { 71, 56 }, // location of level 6 (CJ) + { 135, 29 }, // location of level 7 (CJ) + { 71, 24 } // location of level 8 (CJ) + }, + + // Episode 1 World Map should go here + { + { 254, 25 }, // location of level 0 (CJ) + { 97, 50 }, // location of level 1 (CJ) + { 188, 64 }, // location of level 2 (CJ) + { 128, 78 }, // location of level 3 (CJ) + { 214, 92 }, // location of level 4 (CJ) + { 133, 130 }, // location of level 5 (CJ) + { 208, 136 }, // location of level 6 (CJ) + { 148, 140 }, // location of level 7 (CJ) + { 235, 158 } // location of level 8 (CJ) + }, + + // Episode 2 World Map should go here + { + { 156, 168 }, // location of level 0 (CJ) + { 48, 154 }, // location of level 1 (CJ) + { 174, 95 }, // location of level 2 (CJ) + { 265, 75 }, // location of level 3 (CJ) + { 130, 48 }, // location of level 4 (CJ) + { 279, 23 }, // location of level 5 (CJ) + { 198, 48 }, // location of level 6 (CJ) + { 140, 25 }, // location of level 7 (CJ) + { 281, 136 } // location of level 8 (CJ) + } + +}; + + +// +// Animation locations for episode 0 (1). +// Using patches saves a lot of space, +// as they replace 320x200 full screen frames. +// + +#define ANIM(type, period, nanims, x, y, nexttic) \ + { (type), (period), (nanims), { (x), (y) }, (nexttic), \ + 0, { NULL, NULL, NULL }, 0, 0, 0, 0 } + + +static anim_t epsd0animinfo[] = +{ + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0), +}; + +static anim_t epsd1animinfo[] = +{ + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7), + ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8), +}; + +static anim_t epsd2animinfo[] = +{ + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0), + ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0), +}; + +static int NUMANIMS[NUMEPISODES] = +{ + arrlen(epsd0animinfo), + arrlen(epsd1animinfo), + arrlen(epsd2animinfo), +}; + +static anim_t *anims[NUMEPISODES] = +{ + epsd0animinfo, + epsd1animinfo, + epsd2animinfo +}; + + +// +// GENERAL DATA +// + +// +// Locally used stuff. +// + +// States for single-player +#define SP_KILLS 0 +#define SP_ITEMS 2 +#define SP_SECRET 4 +#define SP_FRAGS 6 +#define SP_TIME 8 +#define SP_PAR ST_TIME + +#define SP_PAUSE 1 + +// in seconds +#define SHOWNEXTLOCDELAY 4 +//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY + + +// used to accelerate or skip a stage +static int acceleratestage; + +// wbs->pnum +static int me; + + // specifies current state +static stateenum_t state; + +// contains information passed into intermission +static wbstartstruct_t* wbs; + +static wbplayerstruct_t* plrs; // wbs->plyr[] + +// used for general timing +static int cnt; + +// used for timing of background animation +static int bcnt; + +// signals to refresh everything for one frame +static int firstrefresh; + +static int cnt_kills[MAXPLAYERS]; +static int cnt_items[MAXPLAYERS]; +static int cnt_secret[MAXPLAYERS]; +static int cnt_time; +static int cnt_par; +static int cnt_pause; + +// # of commercial levels +static int NUMCMAPS; + + +// +// GRAPHICS +// + +// You Are Here graphic +static patch_t* yah[3] = { NULL, NULL, NULL }; + +// splat +static patch_t* splat[2] = { NULL, NULL }; + +// %, : graphics +static patch_t* percent; +static patch_t* colon; + +// 0-9 graphic +static patch_t* num[10]; + +// minus sign +static patch_t* wiminus; + +// "Finished!" graphics +static patch_t* finished; + +// "Entering" graphic +static patch_t* entering; + +// "secret" +static patch_t* sp_secret; + + // "Kills", "Scrt", "Items", "Frags" +static patch_t* kills; +static patch_t* secret; +static patch_t* items; +static patch_t* frags; + +// Time sucks. +static patch_t* timepatch; +static patch_t* par; +static patch_t* sucks; + +// "killers", "victims" +static patch_t* killers; +static patch_t* victims; + +// "Total", your face, your dead face +static patch_t* total; +static patch_t* star; +static patch_t* bstar; + +// "red P[1..MAXPLAYERS]" +static patch_t* p[MAXPLAYERS]; + +// "gray P[1..MAXPLAYERS]" +static patch_t* bp[MAXPLAYERS]; + + // Name graphics of each level (centered) +static patch_t** lnames; + +// Buffer storing the backdrop +static patch_t *background; + +// +// CODE +// + +// slam background +void WI_slamBackground(void) +{ + V_DrawPatch(0, 0, background); +} + +// The ticker is used to detect keys +// because of timing issues in netgames. +boolean WI_Responder(event_t* ev) +{ + return false; +} + + +// Draws " Finished!" +void WI_drawLF(void) +{ + int y = WI_TITLEY; + + if (gamemode != commercial || wbs->last < NUMCMAPS) + { + // draw + V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2, + y, lnames[wbs->last]); + + // draw "Finished!" + y += (5*SHORT(lnames[wbs->last]->height))/4; + + V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); + } + else if (wbs->last == NUMCMAPS) + { + // MAP33 - draw "Finished!" only + V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); + } + else if (wbs->last > NUMCMAPS) + { + // > MAP33. Doom bombs out here with a Bad V_DrawPatch error. + // I'm pretty sure that doom2.exe is just reading into random + // bits of memory at this point, but let's try to be accurate + // anyway. This deliberately triggers a V_DrawPatch error. + + patch_t tmp = { SCREENWIDTH, SCREENHEIGHT, 1, 1, + { 0, 0, 0, 0, 0, 0, 0, 0 } }; + + V_DrawPatch(0, y, &tmp); + } +} + + + +// Draws "Entering " +void WI_drawEL(void) +{ + int y = WI_TITLEY; + + // draw "Entering" + V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2, + y, + entering); + + // draw level + y += (5*SHORT(lnames[wbs->next]->height))/4; + + V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2, + y, + lnames[wbs->next]); + +} + +void +WI_drawOnLnode +( int n, + patch_t* c[] ) +{ + + int i; + int left; + int top; + int right; + int bottom; + boolean fits = false; + + i = 0; + do + { + left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset); + top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset); + right = left + SHORT(c[i]->width); + bottom = top + SHORT(c[i]->height); + + if (left >= 0 + && right < SCREENWIDTH + && top >= 0 + && bottom < SCREENHEIGHT) + { + fits = true; + } + else + { + i++; + } + } while (!fits && i!=2 && c[i] != NULL); + + if (fits && i<2) + { + V_DrawPatch(lnodes[wbs->epsd][n].x, + lnodes[wbs->epsd][n].y, + c[i]); + } + else + { + // DEBUG + printf("Could not place patch on level %d", n+1); + } +} + + + +void WI_initAnimatedBack(void) +{ + int i; + anim_t* a; + + if (gamemode == commercial) + return; + + if (wbs->epsd > 2) + return; + + for (i=0;iepsd];i++) + { + a = &anims[wbs->epsd][i]; + + // init variables + a->ctr = -1; + + // specify the next time to draw it + if (a->type == ANIM_ALWAYS) + a->nexttic = bcnt + 1 + (M_Random()%a->period); + else if (a->type == ANIM_RANDOM) + a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1); + else if (a->type == ANIM_LEVEL) + a->nexttic = bcnt + 1; + } + +} + +void WI_updateAnimatedBack(void) +{ + int i; + anim_t* a; + + if (gamemode == commercial) + return; + + if (wbs->epsd > 2) + return; + + for (i=0;iepsd];i++) + { + a = &anims[wbs->epsd][i]; + + if (bcnt == a->nexttic) + { + switch (a->type) + { + case ANIM_ALWAYS: + if (++a->ctr >= a->nanims) a->ctr = 0; + a->nexttic = bcnt + a->period; + break; + + case ANIM_RANDOM: + a->ctr++; + if (a->ctr == a->nanims) + { + a->ctr = -1; + a->nexttic = bcnt+a->data2+(M_Random()%a->data1); + } + else a->nexttic = bcnt + a->period; + break; + + case ANIM_LEVEL: + // gawd-awful hack for level anims + if (!(state == StatCount && i == 7) + && wbs->next == a->data1) + { + a->ctr++; + if (a->ctr == a->nanims) a->ctr--; + a->nexttic = bcnt + a->period; + } + break; + } + } + + } + +} + +void WI_drawAnimatedBack(void) +{ + int i; + anim_t* a; + + if (gamemode == commercial) + return; + + if (wbs->epsd > 2) + return; + + for (i=0 ; iepsd] ; i++) + { + a = &anims[wbs->epsd][i]; + + if (a->ctr >= 0) + V_DrawPatch(a->loc.x, a->loc.y, a->p[a->ctr]); + } + +} + +// +// Draws a number. +// If digits > 0, then use that many digits minimum, +// otherwise only use as many as necessary. +// Returns new x position. +// + +int +WI_drawNum +( int x, + int y, + int n, + int digits ) +{ + + int fontwidth = SHORT(num[0]->width); + int neg; + int temp; + + if (digits < 0) + { + if (!n) + { + // make variable-length zeros 1 digit long + digits = 1; + } + else + { + // figure out # of digits in # + digits = 0; + temp = n; + + while (temp) + { + temp /= 10; + digits++; + } + } + } + + neg = n < 0; + if (neg) + n = -n; + + // if non-number, do not draw it + if (n == 1994) + return 0; + + // draw the new number + while (digits--) + { + x -= fontwidth; + V_DrawPatch(x, y, num[ n % 10 ]); + n /= 10; + } + + // draw a minus sign if necessary + if (neg && wiminus) + V_DrawPatch(x-=8, y, wiminus); + + return x; + +} + +void +WI_drawPercent +( int x, + int y, + int p ) +{ + if (p < 0) + return; + + V_DrawPatch(x, y, percent); + WI_drawNum(x, y, p, -1); +} + + + +// +// Display level completion time and par, +// or "sucks" message if overflow. +// +void +WI_drawTime +( int x, + int y, + int t ) +{ + + int div; + int n; + + if (t<0) + return; + + if (t <= 61*59) + { + div = 1; + + do + { + n = (t / div) % 60; + x = WI_drawNum(x, y, n, 2) - SHORT(colon->width); + div *= 60; + + // draw + if (div==60 || t / div) + V_DrawPatch(x, y, colon); + + } while (t / div); + } + else + { + // "sucks" + V_DrawPatch(x - SHORT(sucks->width), y, sucks); + } +} + + +void WI_End(void) +{ + void WI_unloadData(void); + WI_unloadData(); +} + +void WI_initNoState(void) +{ + state = NoState; + acceleratestage = 0; + cnt = 10; +} + +void WI_updateNoState(void) { + + WI_updateAnimatedBack(); + + if (!--cnt) + { + // Don't call WI_End yet. G_WorldDone doesnt immediately + // change gamestate, so WI_Drawer is still going to get + // run until that happens. If we do that after WI_End + // (which unloads all the graphics), we're in trouble. + //WI_End(); + G_WorldDone(); + } + +} + +static boolean snl_pointeron = false; + + +void WI_initShowNextLoc(void) +{ + state = ShowNextLoc; + acceleratestage = 0; + cnt = SHOWNEXTLOCDELAY * TICRATE; + + WI_initAnimatedBack(); +} + +void WI_updateShowNextLoc(void) +{ + WI_updateAnimatedBack(); + + if (!--cnt || acceleratestage) + WI_initNoState(); + else + snl_pointeron = (cnt & 31) < 20; +} + +void WI_drawShowNextLoc(void) +{ + + int i; + int last; + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + + if ( gamemode != commercial) + { + if (wbs->epsd > 2) + { + WI_drawEL(); + return; + } + + last = (wbs->last == 8) ? wbs->next - 1 : wbs->last; + + // draw a splat on taken cities. + for (i=0 ; i<=last ; i++) + WI_drawOnLnode(i, splat); + + // splat the secret level? + if (wbs->didsecret) + WI_drawOnLnode(8, splat); + + // draw flashing ptr + if (snl_pointeron) + WI_drawOnLnode(wbs->next, yah); + } + + // draws which level you are entering.. + if ( (gamemode != commercial) + || wbs->next != 30) + WI_drawEL(); + +} + +void WI_drawNoState(void) +{ + snl_pointeron = true; + WI_drawShowNextLoc(); +} + +int WI_fragSum(int playernum) +{ + int i; + int frags = 0; + + for (i=0 ; i 99) + dm_frags[i][j] = 99; + + if (dm_frags[i][j] < -99) + dm_frags[i][j] = -99; + + stillticking = true; + } + } + dm_totals[i] = WI_fragSum(i); + + if (dm_totals[i] > 99) + dm_totals[i] = 99; + + if (dm_totals[i] < -99) + dm_totals[i] = -99; + } + + } + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + dm_state++; + } + + } + else if (dm_state == 4) + { + if (acceleratestage) + { + S_StartSound(0, sfx_slop); + + if ( gamemode == commercial) + WI_initNoState(); + else + WI_initShowNextLoc(); + } + } + else if (dm_state & 1) + { + if (!--cnt_pause) + { + dm_state++; + cnt_pause = TICRATE; + } + } +} + + + +void WI_drawDeathmatchStats(void) +{ + + int i; + int j; + int x; + int y; + int w; + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + WI_drawLF(); + + // draw stat titles (top line) + V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2, + DM_MATRIXY-WI_SPACINGY+10, + total); + + V_DrawPatch(DM_KILLERSX, DM_KILLERSY, killers); + V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, victims); + + // draw P? + x = DM_MATRIXX + DM_SPACINGX; + y = DM_MATRIXY; + + for (i=0 ; iwidth)/2, + DM_MATRIXY - WI_SPACINGY, + p[i]); + + V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, + y, + p[i]); + + if (i == me) + { + V_DrawPatch(x-SHORT(p[i]->width)/2, + DM_MATRIXY - WI_SPACINGY, + bstar); + + V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, + y, + star); + } + } + else + { + // V_DrawPatch(x-SHORT(bp[i]->width)/2, + // DM_MATRIXY - WI_SPACINGY, bp[i]); + // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2, + // y, bp[i]); + } + x += DM_SPACINGX; + y += WI_SPACINGY; + } + + // draw stats + y = DM_MATRIXY+10; + w = SHORT(num[0]->width); + + for (i=0 ; imaxkills; + cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; + cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; + + if (dofrags) + cnt_frags[i] = WI_fragSum(i); + } + S_StartSound(0, sfx_barexp); + ng_state = 10; + } + + if (ng_state == 2) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (plrs[i].skills * 100) / wbs->maxkills) + cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; + else + stillticking = true; + } + + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + ng_state++; + } + } + else if (ng_state == 4) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (plrs[i].sitems * 100) / wbs->maxitems) + cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; + else + stillticking = true; + } + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + ng_state++; + } + } + else if (ng_state == 6) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (plrs[i].ssecret * 100) / wbs->maxsecret) + cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; + else + stillticking = true; + } + + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + ng_state += 1 + 2*!dofrags; + } + } + else if (ng_state == 8) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (fsum = WI_fragSum(i))) + cnt_frags[i] = fsum; + else + stillticking = true; + } + + if (!stillticking) + { + S_StartSound(0, sfx_pldeth); + ng_state++; + } + } + else if (ng_state == 10) + { + if (acceleratestage) + { + S_StartSound(0, sfx_sgcock); + if ( gamemode == commercial ) + WI_initNoState(); + else + WI_initShowNextLoc(); + } + } + else if (ng_state & 1) + { + if (!--cnt_pause) + { + ng_state++; + cnt_pause = TICRATE; + } + } +} + + + +void WI_drawNetgameStats(void) +{ + int i; + int x; + int y; + int pwidth = SHORT(percent->width); + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + + WI_drawLF(); + + // draw stat titles (top line) + V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width), + NG_STATSY, kills); + + V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width), + NG_STATSY, items); + + V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width), + NG_STATSY, secret); + + if (dofrags) + V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width), + NG_STATSY, frags); + + // draw stats + y = NG_STATSY + SHORT(kills->height); + + for (i=0 ; iwidth), y, p[i]); + + if (i == me) + V_DrawPatch(x-SHORT(p[i]->width), y, star); + + x += NG_SPACINGX; + WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX; + WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX; + WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX; + + if (dofrags) + WI_drawNum(x, y+10, cnt_frags[i], -1); + + y += WI_SPACINGY; + } + +} + +static int sp_state; + +void WI_initStats(void) +{ + state = StatCount; + acceleratestage = 0; + sp_state = 1; + cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1; + cnt_time = cnt_par = -1; + cnt_pause = TICRATE; + + WI_initAnimatedBack(); +} + +void WI_updateStats(void) +{ + + WI_updateAnimatedBack(); + + if (acceleratestage && sp_state != 10) + { + acceleratestage = 0; + cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; + cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; + cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; + cnt_time = plrs[me].stime / TICRATE; + cnt_par = wbs->partime / TICRATE; + S_StartSound(0, sfx_barexp); + sp_state = 10; + } + + if (sp_state == 2) + { + cnt_kills[0] += 2; + + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills) + { + cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + else if (sp_state == 4) + { + cnt_items[0] += 2; + + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems) + { + cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + else if (sp_state == 6) + { + cnt_secret[0] += 2; + + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret) + { + cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + + else if (sp_state == 8) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + cnt_time += 3; + + if (cnt_time >= plrs[me].stime / TICRATE) + cnt_time = plrs[me].stime / TICRATE; + + cnt_par += 3; + + if (cnt_par >= wbs->partime / TICRATE) + { + cnt_par = wbs->partime / TICRATE; + + if (cnt_time >= plrs[me].stime / TICRATE) + { + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + } + else if (sp_state == 10) + { + if (acceleratestage) + { + S_StartSound(0, sfx_sgcock); + + if (gamemode == commercial) + WI_initNoState(); + else + WI_initShowNextLoc(); + } + } + else if (sp_state & 1) + { + if (!--cnt_pause) + { + sp_state++; + cnt_pause = TICRATE; + } + } + +} + +void WI_drawStats(void) +{ + // line height + int lh; + + lh = (3*SHORT(num[0]->height))/2; + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + + WI_drawLF(); + + V_DrawPatch(SP_STATSX, SP_STATSY, kills); + WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]); + + V_DrawPatch(SP_STATSX, SP_STATSY+lh, items); + WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]); + + V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, sp_secret); + WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]); + + V_DrawPatch(SP_TIMEX, SP_TIMEY, timepatch); + WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time); + + if (wbs->epsd < 3) + { + V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par); + WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par); + } + +} + +void WI_checkForAccelerate(void) +{ + int i; + player_t *player; + + // check for button presses to skip delays + for (i=0, player = players ; icmd.buttons & BT_ATTACK) + { + if (!player->attackdown) + acceleratestage = 1; + player->attackdown = true; + } + else + player->attackdown = false; + if (player->cmd.buttons & BT_USE) + { + if (!player->usedown) + acceleratestage = 1; + player->usedown = true; + } + else + player->usedown = false; + } + } +} + + + +// Updates stuff each tick +void WI_Ticker(void) +{ + // counter for general background animation + bcnt++; + + if (bcnt == 1) + { + // intermission music + if ( gamemode == commercial ) + S_ChangeMusic(mus_dm2int, true); + else + S_ChangeMusic(mus_inter, true); + } + + WI_checkForAccelerate(); + + switch (state) + { + case StatCount: + if (deathmatch) WI_updateDeathmatchStats(); + else if (netgame) WI_updateNetgameStats(); + else WI_updateStats(); + break; + + case ShowNextLoc: + WI_updateShowNextLoc(); + break; + + case NoState: + WI_updateNoState(); + break; + } + +} + +typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + +// Common load/unload function. Iterates over all the graphics +// lumps to be loaded/unloaded into memory. + +static void WI_loadUnloadData(load_callback_t callback) +{ + int i, j; + char name[9]; + anim_t *a; + + if (gamemode == commercial) + { + for (i=0 ; iepsd, i); + callback(name, &lnames[i]); + } + + // you are here + callback(DEH_String("WIURH0"), &yah[0]); + + // you are here (alt.) + callback(DEH_String("WIURH1"), &yah[1]); + + // splat + callback(DEH_String("WISPLAT"), &splat[0]); + + if (wbs->epsd < 3) + { + for (j=0;jepsd];j++) + { + a = &anims[wbs->epsd][j]; + for (i=0;inanims;i++) + { + // MONDO HACK! + if (wbs->epsd != 1 || j != 8) + { + // animations + DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i); + callback(name, &a->p[i]); + } + else + { + // HACK ALERT! + a->p[i] = anims[1][4].p[i]; + } + } + } + } + } + + // More hacks on minus sign. + if (W_CheckNumForName(DEH_String("WIMINUS")) > 0) + callback(DEH_String("WIMINUS"), &wiminus); + else + wiminus = NULL; + + for (i=0;i<10;i++) + { + // numbers 0-9 + DEH_snprintf(name, 9, "WINUM%d", i); + callback(name, &num[i]); + } + + // percent sign + callback(DEH_String("WIPCNT"), &percent); + + // "finished" + callback(DEH_String("WIF"), &finished); + + // "entering" + callback(DEH_String("WIENTER"), &entering); + + // "kills" + callback(DEH_String("WIOSTK"), &kills); + + // "scrt" + callback(DEH_String("WIOSTS"), &secret); + + // "secret" + callback(DEH_String("WISCRT2"), &sp_secret); + + // french wad uses WIOBJ (?) + if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0) + { + // "items" + if (netgame && !deathmatch) + callback(DEH_String("WIOBJ"), &items); + else + callback(DEH_String("WIOSTI"), &items); + } else { + callback(DEH_String("WIOSTI"), &items); + } + + // "frgs" + callback(DEH_String("WIFRGS"), &frags); + + // ":" + callback(DEH_String("WICOLON"), &colon); + + // "time" + callback(DEH_String("WITIME"), &timepatch); + + // "sucks" + callback(DEH_String("WISUCKS"), &sucks); + + // "par" + callback(DEH_String("WIPAR"), &par); + + // "killers" (vertical) + callback(DEH_String("WIKILRS"), &killers); + + // "victims" (horiz) + callback(DEH_String("WIVCTMS"), &victims); + + // "total" + callback(DEH_String("WIMSTT"), &total); + + for (i=0 ; i= exe_ultimate && wbs->epsd == 3) + { + M_StringCopy(name, DEH_String("INTERPIC"), sizeof(name)); + } + else + { + DEH_snprintf(name, sizeof(name), "WIMAP%d", wbs->epsd); + } + + // Draw backdrop and save to a temporary buffer + + callback(name, &background); +} + +static void WI_loadCallback(const char *name, patch_t **variable) +{ + *variable = W_CacheLumpName(name, PU_STATIC); +} + +void WI_loadData(void) +{ + if (gamemode == commercial) + { + NUMCMAPS = 32; + lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS, + PU_STATIC, NULL); + } + else + { + lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS, + PU_STATIC, NULL); + } + + WI_loadUnloadData(WI_loadCallback); + + // These two graphics are special cased because we're sharing + // them with the status bar code + + // your face + star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC); + + // dead face + bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC); +} + +static void WI_unloadCallback(const char *name, patch_t **variable) +{ + W_ReleaseLumpName(name); + *variable = NULL; +} + +void WI_unloadData(void) +{ + WI_loadUnloadData(WI_unloadCallback); + + // We do not free these lumps as they are shared with the status + // bar code. + + // W_ReleaseLumpName("STFST01"); + // W_ReleaseLumpName("STFDEAD0"); +} + +void WI_Drawer (void) +{ + switch (state) + { + case StatCount: + if (deathmatch) + WI_drawDeathmatchStats(); + else if (netgame) + WI_drawNetgameStats(); + else + WI_drawStats(); + break; + + case ShowNextLoc: + WI_drawShowNextLoc(); + break; + + case NoState: + WI_drawNoState(); + break; + } +} + + +void WI_initVariables(wbstartstruct_t* wbstartstruct) +{ + + wbs = wbstartstruct; + +#ifdef RANGECHECKING + if (gamemode != commercial) + { + if (gameversion >= exe_ultimate) + RNGCHECK(wbs->epsd, 0, 3); + else + RNGCHECK(wbs->epsd, 0, 2); + } + else + { + RNGCHECK(wbs->last, 0, 8); + RNGCHECK(wbs->next, 0, 8); + } + RNGCHECK(wbs->pnum, 0, MAXPLAYERS); + RNGCHECK(wbs->pnum, 0, MAXPLAYERS); +#endif + + acceleratestage = 0; + cnt = bcnt = 0; + firstrefresh = 1; + me = wbs->pnum; + plrs = wbs->plyr; + + if (!wbs->maxkills) + wbs->maxkills = 1; + + if (!wbs->maxitems) + wbs->maxitems = 1; + + if (!wbs->maxsecret) + wbs->maxsecret = 1; + + if ( gameversion < exe_ultimate ) + if (wbs->epsd > 2) + wbs->epsd -= 3; +} + +void WI_Start(wbstartstruct_t* wbstartstruct) +{ + WI_initVariables(wbstartstruct); + WI_loadData(); + + if (deathmatch) + WI_initDeathmatchStats(); + else if (netgame) + WI_initNetgameStats(); + else + WI_initStats(); +} diff --git a/games/NXDoom/src/doom/wi_stuff.h b/games/NXDoom/src/doom/wi_stuff.h new file mode 100644 index 00000000000..296571f73a8 --- /dev/null +++ b/games/NXDoom/src/doom/wi_stuff.h @@ -0,0 +1,48 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Intermission. +// + +#ifndef __WI_STUFF__ +#define __WI_STUFF__ + +//#include "v_video.h" + +#include "doomdef.h" + +// States for the intermission + +typedef enum +{ + NoState = -1, + StatCount, + ShowNextLoc, +} stateenum_t; + +// Called by main loop, animate the intermission. +void WI_Ticker (void); + +// Called by main loop, +// draws the intermission directly into the screen buffer. +void WI_Drawer (void); + +// Setup for an intermission screen. +void WI_Start(wbstartstruct_t* wbstartstruct); + +// Shut down the intermission screen +void WI_End(void); + +#endif diff --git a/games/NXDoom/src/doomkeys.h b/games/NXDoom/src/doomkeys.h new file mode 100644 index 00000000000..1098c719dee --- /dev/null +++ b/games/NXDoom/src/doomkeys.h @@ -0,0 +1,156 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Key definitions +// + +#ifndef __DOOMKEYS__ +#define __DOOMKEYS__ + +// +// DOOM keyboard definition. +// This is the stuff configured by Setup.Exe. +// Most key data are simple ascii (uppercased). +// +#define KEY_RIGHTARROW 0xae +#define KEY_LEFTARROW 0xac +#define KEY_UPARROW 0xad +#define KEY_DOWNARROW 0xaf +#define KEY_ESCAPE 27 +#define KEY_ENTER 13 +#define KEY_TAB 9 +#define KEY_F1 (0x80+0x3b) +#define KEY_F2 (0x80+0x3c) +#define KEY_F3 (0x80+0x3d) +#define KEY_F4 (0x80+0x3e) +#define KEY_F5 (0x80+0x3f) +#define KEY_F6 (0x80+0x40) +#define KEY_F7 (0x80+0x41) +#define KEY_F8 (0x80+0x42) +#define KEY_F9 (0x80+0x43) +#define KEY_F10 (0x80+0x44) +#define KEY_F11 (0x80+0x57) +#define KEY_F12 (0x80+0x58) + +#define KEY_BACKSPACE 0x7f +#define KEY_PAUSE 0xff + +#define KEY_EQUALS 0x3d +#define KEY_MINUS 0x2d + +#define KEY_RSHIFT (0x80+0x36) +#define KEY_RCTRL (0x80+0x1d) +#define KEY_RALT (0x80+0x38) + +#define KEY_LALT KEY_RALT + +// new keys: + +#define KEY_CAPSLOCK (0x80+0x3a) +#define KEY_NUMLOCK (0x80+0x45) +#define KEY_SCRLCK (0x80+0x46) +#define KEY_PRTSCR (0x80+0x59) + +#define KEY_HOME (0x80+0x47) +#define KEY_END (0x80+0x4f) +#define KEY_PGUP (0x80+0x49) +#define KEY_PGDN (0x80+0x51) +#define KEY_INS (0x80+0x52) +#define KEY_DEL (0x80+0x53) + +#define KEYP_0 KEY_INS +#define KEYP_1 KEY_END +#define KEYP_2 KEY_DOWNARROW +#define KEYP_3 KEY_PGDN +#define KEYP_4 KEY_LEFTARROW +#define KEYP_5 (0x80+0x4c) +#define KEYP_6 KEY_RIGHTARROW +#define KEYP_7 KEY_HOME +#define KEYP_8 KEY_UPARROW +#define KEYP_9 KEY_PGUP + +#define KEYP_DIVIDE '/' +#define KEYP_PLUS '+' +#define KEYP_MINUS '-' +#define KEYP_MULTIPLY '*' +#define KEYP_PERIOD 0 +#define KEYP_EQUALS KEY_EQUALS +#define KEYP_ENTER KEY_ENTER + +#define KEY_NONUSBACKSLASH '\\' + +#define SCANCODE_TO_KEYS_ARRAY { \ + 0, 0, 0, 0, 'a', /* 0-9 */ \ + 'b', 'c', 'd', 'e', 'f', \ + 'g', 'h', 'i', 'j', 'k', /* 10-19 */ \ + 'l', 'm', 'n', 'o', 'p', \ + 'q', 'r', 's', 't', 'u', /* 20-29 */ \ + 'v', 'w', 'x', 'y', 'z', \ + '1', '2', '3', '4', '5', /* 30-39 */ \ + '6', '7', '8', '9', '0', \ + KEY_ENTER, KEY_ESCAPE, KEY_BACKSPACE, KEY_TAB, ' ', /* 40-49 */ \ + KEY_MINUS, KEY_EQUALS, '[', ']', '\\', \ + 0, ';', '\'', '`', ',', /* 50-59 */ \ + '.', '/', KEY_CAPSLOCK, KEY_F1, KEY_F2, \ + KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* 60-69 */ \ + KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, \ + KEY_PRTSCR, KEY_SCRLCK, KEY_PAUSE, KEY_INS, KEY_HOME, /* 70-79 */ \ + KEY_PGUP, KEY_DEL, KEY_END, KEY_PGDN, KEY_RIGHTARROW, \ + KEY_LEFTARROW, KEY_DOWNARROW, KEY_UPARROW, /* 80-89 */ \ + KEY_NUMLOCK, KEYP_DIVIDE, \ + KEYP_MULTIPLY, KEYP_MINUS, KEYP_PLUS, KEYP_ENTER, KEYP_1, \ + KEYP_2, KEYP_3, KEYP_4, KEYP_5, KEYP_6, /* 90-99 */ \ + KEYP_7, KEYP_8, KEYP_9, KEYP_0, KEYP_PERIOD, \ + KEY_NONUSBACKSLASH, 0, 0, KEYP_EQUALS, /* 100-103 */ \ +} + +// Default names for keys, to use in English or as fallback. +#define KEY_NAMES_ARRAY { \ + { KEY_BACKSPACE, "BACKSP" }, { KEY_TAB, "TAB" }, \ + { KEY_INS, "INS" }, { KEY_DEL, "DEL" }, \ + { KEY_PGUP, "PGUP" }, { KEY_PGDN, "PGDN" }, \ + { KEY_ENTER, "ENTER" }, { KEY_ESCAPE, "ESC" }, \ + { KEY_F1, "F1" }, { KEY_F2, "F2" }, \ + { KEY_F3, "F3" }, { KEY_F4, "F4" }, \ + { KEY_F5, "F5" }, { KEY_F6, "F6" }, \ + { KEY_F7, "F7" }, { KEY_F8, "F8" }, \ + { KEY_F9, "F9" }, { KEY_F10, "F10" }, \ + { KEY_F11, "F11" }, { KEY_F12, "F12" }, \ + { KEY_HOME, "HOME" }, { KEY_END, "END" }, \ + { KEY_MINUS, "-" }, { KEY_EQUALS, "=" }, \ + { KEY_NUMLOCK, "NUMLCK" }, { KEY_SCRLCK, "SCRLCK" }, \ + { KEY_PAUSE, "PAUSE" }, { KEY_PRTSCR, "PRTSC" }, \ + { KEY_UPARROW, "UP" }, { KEY_DOWNARROW, "DOWN" }, \ + { KEY_LEFTARROW, "LEFT" }, { KEY_RIGHTARROW, "RIGHT" }, \ + { KEY_RALT, "ALT" }, { KEY_LALT, "ALT" }, \ + { KEY_RSHIFT, "SHIFT" }, { KEY_CAPSLOCK, "CAPS" }, \ + { KEY_RCTRL, "CTRL" }, { KEYP_5, "NUM5" }, \ + { ' ', "SPACE" }, \ + { 'a', "A" }, { 'b', "B" }, { 'c', "C" }, { 'd', "D" }, \ + { 'e', "E" }, { 'f', "F" }, { 'g', "G" }, { 'h', "H" }, \ + { 'i', "I" }, { 'j', "J" }, { 'k', "K" }, { 'l', "L" }, \ + { 'm', "M" }, { 'n', "N" }, { 'o', "O" }, { 'p', "P" }, \ + { 'q', "Q" }, { 'r', "R" }, { 's', "S" }, { 't', "T" }, \ + { 'u', "U" }, { 'v', "V" }, { 'w', "W" }, { 'x', "X" }, \ + { 'y', "Y" }, { 'z', "Z" }, { '0', "0" }, { '1', "1" }, \ + { '2', "2" }, { '3', "3" }, { '4', "4" }, { '5', "5" }, \ + { '6', "6" }, { '7', "7" }, { '8', "8" }, { '9', "9" }, \ + { '[', "[" }, { ']', "]" }, { ';', ";" }, { '`', "`" }, \ + { ',', "," }, { '.', "." }, { '/', "/" }, { '\\', "\\" }, \ + { '\'', "\'" }, \ +} + +#endif // __DOOMKEYS__ + diff --git a/games/NXDoom/src/doomtype.h b/games/NXDoom/src/doomtype.h new file mode 100644 index 00000000000..d90cfec970b --- /dev/null +++ b/games/NXDoom/src/doomtype.h @@ -0,0 +1,145 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Simple basic typedefs, isolated here to make it easier +// separating modules. +// + + +#ifndef __DOOMTYPE__ +#define __DOOMTYPE__ + +#include "config.h" + +#if defined(_MSC_VER) && !defined(__cplusplus) +#define inline __inline +#endif + +// #define macros to provide functions missing in Windows. +// Outside Windows, we use strings.h for str[n]casecmp. + + +#if !HAVE_DECL_STRCASECMP || !HAVE_DECL_STRNCASECMP + +#include +#if !HAVE_DECL_STRCASECMP +#define strcasecmp stricmp +#endif +#if !HAVE_DECL_STRNCASECMP +#define strncasecmp strnicmp +#endif + +#else + +#include + +#endif + + +// +// The packed attribute forces structures to be packed into the minimum +// space necessary. If this is not done, the compiler may align structure +// fields differently to optimize memory access, inflating the overall +// structure size. It is important to use the packed attribute on certain +// structures where alignment is important, particularly data read/written +// to disk. +// + +#ifdef __GNUC__ + +#if defined(_WIN32) && !defined(__clang__) +#define PACKEDATTR __attribute__((packed,gcc_struct)) +#else +#define PACKEDATTR __attribute__((packed)) +#endif + +#define PRINTF_ATTR(fmt, first) __attribute__((format(printf, fmt, first))) +#define PRINTF_ARG_ATTR(x) __attribute__((format_arg(x))) +#define NORETURN __attribute__((noreturn)) + +#else +#if defined(_MSC_VER) +#define PACKEDATTR __pragma(pack(pop)) +#else +#define PACKEDATTR +#endif +#define PRINTF_ATTR(fmt, first) +#define PRINTF_ARG_ATTR(x) +#define NORETURN +#endif + +#ifdef __WATCOMC__ +#define PACKEDPREFIX _Packed +#elif defined(_MSC_VER) +#define PACKEDPREFIX __pragma(pack(push,1)) +#else +#define PACKEDPREFIX +#endif + +#define PACKED_STRUCT(...) PACKEDPREFIX struct __VA_ARGS__ PACKEDATTR + +// C99 integer types; with gcc we just use this. Other compilers +// should add conditional statements that define the C99 types. + +// What is really wanted here is stdint.h; however, some old versions +// of Solaris don't have stdint.h and only have inttypes.h (the +// pre-standardisation version). inttypes.h is also in the C99 +// standard and defined to include stdint.h, so include this. + +#include +#include + +#if defined(__cplusplus) || defined(__bool_true_false_are_defined) + +// The C++/C99 bool type (or _Bool that is) can only have two values: +// 0 or 1. However, the Doom source code assumes any non-zero value +// to evaluate to true, so we have to use an int type here. + +typedef int boolean; + +#else + +typedef enum +{ + false, + true +} boolean; + +#endif + +typedef uint8_t byte; +typedef uint8_t pixel_t; +typedef int16_t dpixel_t; + +#include + +#ifdef _WIN32 + +#define DIR_SEPARATOR '\\' +#define DIR_SEPARATOR_S "\\" +#define PATH_SEPARATOR ';' + +#else + +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_S "/" +#define PATH_SEPARATOR ':' + +#endif + +#define arrlen(array) (sizeof(array) / sizeof(*array)) + +#endif + diff --git a/games/NXDoom/src/gusconf.c b/games/NXDoom/src/gusconf.c new file mode 100644 index 00000000000..5cd1d62a970 --- /dev/null +++ b/games/NXDoom/src/gusconf.c @@ -0,0 +1,301 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// GUS emulation code. +// +// Actually emulating a GUS is far too much work; fortunately +// GUS "emulation" already exists in the form of Timidity, which +// supports GUS patch files. This code therefore converts Doom's +// DMXGUS lump into an equivalent Timidity configuration file. +// + + +#include +#include +#include +#include + +#include "m_misc.h" +#include "w_wad.h" +#include "z_zone.h" + +#define MAX_INSTRUMENTS 256 + +typedef struct +{ + char *patch_names[MAX_INSTRUMENTS]; + int used[MAX_INSTRUMENTS]; + int mapping[MAX_INSTRUMENTS]; + unsigned int count; +} gus_config_t; + +char *gus_patch_path = ""; +int gus_ram_kb = 1024; + +static unsigned int MappingIndex(void) +{ + unsigned int result = gus_ram_kb / 256; + + if (result < 1) + { + return 1; + } + else if (result > 4) + { + return 4; + } + else + { + return result; + } +} + +static int SplitLine(char *line, char **fields, unsigned int max_fields) +{ + unsigned int num_fields; + char *p; + + fields[0] = line; + num_fields = 1; + + for (p = line; *p != '\0'; ++p) + { + if (*p == ',') + { + *p = '\0'; + + // Skip spaces following the comma. + do + { + ++p; + } while (*p != '\0' && isspace(*p)); + + fields[num_fields] = p; + ++num_fields; + --p; + + if (num_fields >= max_fields) + { + break; + } + } + else if (*p == '#') + { + *p = '\0'; + break; + } + } + + // Strip off trailing whitespace from the end of the line. + p = fields[num_fields - 1] + strlen(fields[num_fields - 1]); + while (p > fields[num_fields - 1] && isspace(*(p - 1))) + { + --p; + *p = '\0'; + } + + return num_fields; +} + +static void ParseLine(gus_config_t *config, char *line) +{ + char *fields[6]; + unsigned int i; + unsigned int num_fields; + unsigned int instr_id, mapped_id; + + num_fields = SplitLine(line, fields, 6); + + if (num_fields < 6) + { + return; + } + + instr_id = atoi(fields[0]); + + // Skip non GM percussions. + if ((instr_id >= 128 && instr_id < 128 + 35) || instr_id > 128 + 81) + { + return; + } + + mapped_id = atoi(fields[MappingIndex()]); + + for (i = 0; i < config->count; i++) + { + if (config->used[i] == mapped_id) + { + break; + } + } + + if (i == config->count) + { + // DMX uses wrong patch name (we should use name of 'mapped_id' + // instrument, but DMX uses name of 'instr_id' instead). + free(config->patch_names[i]); + config->patch_names[i] = M_StringDuplicate(fields[5]); + config->used[i] = mapped_id; + config->count++; + } + config->mapping[instr_id] = i; +} + +static void ParseDMXConfig(char *dmxconf, gus_config_t *config) +{ + char *p, *newline; + unsigned int i; + + memset(config, 0, sizeof(gus_config_t)); + + for (i = 0; i < MAX_INSTRUMENTS; ++i) + { + config->mapping[i] = -1; + config->used[i] = -1; + } + + config->count = 0; + + p = dmxconf; + + for (;;) + { + newline = strchr(p, '\n'); + + if (newline != NULL) + { + *newline = '\0'; + } + + ParseLine(config, p); + + if (newline == NULL) + { + break; + } + else + { + p = newline + 1; + } + } +} + +static void FreeDMXConfig(gus_config_t *config) +{ + unsigned int i; + + for (i = 0; i < MAX_INSTRUMENTS; ++i) + { + free(config->patch_names[i]); + } +} + +static char *ReadDMXConfig(void) +{ + int lumpnum; + unsigned int len; + char *data; + + // TODO: This should be chosen based on gamemode == commercial: + + lumpnum = W_CheckNumForName("DMXGUS"); + + if (lumpnum < 0) + { + lumpnum = W_GetNumForName("DMXGUSC"); + } + + len = W_LumpLength(lumpnum); + data = Z_Malloc(len + 1, PU_STATIC, NULL); + W_ReadLump(lumpnum, data); + + data[len] = '\0'; + return data; +} + +static boolean WriteTimidityConfig(char *path, gus_config_t *config) +{ + FILE *fstream; + unsigned int i; + + fstream = M_fopen(path, "w"); + + if (fstream == NULL) + { + return false; + } + + fprintf(fstream, "# Autogenerated Timidity config.\n\n"); + + fprintf(fstream, "dir \"%s\"\n", gus_patch_path); + + fprintf(fstream, "\nbank 0\n\n"); + + for (i = 0; i < 128; ++i) + { + if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS + && config->patch_names[config->mapping[i]] != NULL) + { + fprintf(fstream, "%u %s\n", + i, config->patch_names[config->mapping[i]]); + } + } + + fprintf(fstream, "\ndrumset 0\n\n"); + + for (i = 128 + 35; i <= 128 + 81; ++i) + { + if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS + && config->patch_names[config->mapping[i]] != NULL) + { + fprintf(fstream, "%u %s\n", + i - 128, config->patch_names[config->mapping[i]]); + } + } + + fprintf(fstream, "\n"); + + fclose(fstream); + + return true; +} + +boolean GUS_WriteConfig(char *path) +{ + boolean result; + char *dmxconf; + gus_config_t config; + + if (!strcmp(gus_patch_path, "")) + { + printf("You haven't configured gus_patch_path.\n"); + printf("gus_patch_path needs to point to the location of " + "your GUS patch set.\n" + "To get a copy of the \"standard\" GUS patches, " + "download a copy of dgguspat.zip.\n"); + + return false; + } + + dmxconf = ReadDMXConfig(); + ParseDMXConfig(dmxconf, &config); + + result = WriteTimidityConfig(path, &config); + + FreeDMXConfig(&config); + Z_Free(dmxconf); + + return result; +} + diff --git a/games/NXDoom/src/gusconf.h b/games/NXDoom/src/gusconf.h new file mode 100644 index 00000000000..4efbe99524b --- /dev/null +++ b/games/NXDoom/src/gusconf.h @@ -0,0 +1,29 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// GUS emulation code. +// + +#ifndef __GUSCONF_H__ +#define __GUSCONF_H__ + +#include "doomtype.h" + +extern char *gus_patch_path; +extern int gus_ram_kb; + +boolean GUS_WriteConfig(char *path); + +#endif /* #ifndef __GUSCONF_H__ */ + diff --git a/games/NXDoom/src/heretic-res.rc.in b/games/NXDoom/src/heretic-res.rc.in new file mode 100644 index 00000000000..0cf43446d9e --- /dev/null +++ b/games/NXDoom/src/heretic-res.rc.in @@ -0,0 +1,30 @@ +1 ICON "@top_srcdir@/data/heretic.ico" + +#include + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" + +1 VERSIONINFO +PRODUCTVERSION @WINDOWS_RC_VERSION@ +FILEVERSION @WINDOWS_RC_VERSION@ +FILETYPE 1 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "@PACKAGE_VERSION@.0" + VALUE "FileDescription", "@PACKAGE_STRING@" + VALUE "InternalName", "@PACKAGE_TARNAME@" + VALUE "CompanyName", "@PACKAGE_BUGREPORT@" + VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" + VALUE "ProductName", "@PACKAGE_NAME@" + VALUE "ProductVersion", "@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + diff --git a/games/NXDoom/src/heretic/.gitignore b/games/NXDoom/src/heretic/.gitignore new file mode 100644 index 00000000000..76092240c0b --- /dev/null +++ b/games/NXDoom/src/heretic/.gitignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +.deps +tags +TAGS + diff --git a/games/NXDoom/src/heretic/CMakeLists.txt b/games/NXDoom/src/heretic/CMakeLists.txt new file mode 100644 index 00000000000..ac6d2fbaf90 --- /dev/null +++ b/games/NXDoom/src/heretic/CMakeLists.txt @@ -0,0 +1,77 @@ +add_library(heretic STATIC + am_data.h + am_map.c am_map.h + ct_chat.c ct_chat.h + deh_ammo.c + deh_frame.c + deh_htext.c + deh_htic.c deh_htic.h + deh_sound.c + deh_thing.c + deh_weapon.c + d_main.c + d_net.c + doomdata.h + doomdef.h + dstrings.h + f_finale.c + g_game.c + info.c info.h + in_lude.c + m_random.c m_random.h + mn_menu.c + p_action.h + p_ceilng.c + p_doors.c + p_enemy.c + p_floor.c + p_inter.c + p_lights.c + p_local.h + p_map.c + p_maputl.c + p_mobj.c + p_plats.c + p_pspr.c + p_saveg.c + p_setup.c + p_sight.c + p_spec.c p_spec.h + p_switch.c + p_telept.c + p_tick.c + p_user.c + r_bsp.c + r_data.c + r_draw.c + r_local.h + r_main.c + r_plane.c + r_segs.c + r_things.c + sb_bar.c + sounds.c sounds.h + s_sound.c s_sound.h) + +target_include_directories(heretic PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") + +if (DEFINED EMSCRIPTEN) + set(SDL_FLAGS "-s USE_SDL=2") + if(ENABLE_SDL2_MIXER) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") + endif() + if(ENABLE_SDL2_NET) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") + endif() +else() + set(SDL_LINK_LIBS SDL2::SDL2) + if(ENABLE_SDL2_MIXER) + list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) + endif() + if(ENABLE_SDL2_NET) + list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) + endif() +endif() +target_link_libraries(heretic textscreen ${SDL_LINK_LIBS}) +set_target_properties(heretic PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") +set_target_properties(heretic PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/heretic/Makefile.am b/games/NXDoom/src/heretic/Makefile.am new file mode 100644 index 00000000000..ac849d5e5fe --- /dev/null +++ b/games/NXDoom/src/heretic/Makefile.am @@ -0,0 +1,72 @@ + +AM_CFLAGS=-I$(top_srcdir)/src \ + -I$(top_srcdir)/textscreen \ + @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ + +EXTRA_DIST = \ + CMakeLists.txt \ + heretic_icon.c + +noinst_LIBRARIES=libheretic.a + +libheretic_a_SOURCES = \ + am_data.h \ +am_map.c am_map.h \ +ct_chat.c ct_chat.h \ +deh_ammo.c \ +deh_frame.c \ +deh_htext.c \ +deh_htic.c deh_htic.h \ +deh_sound.c \ +deh_thing.c \ +deh_weapon.c \ +d_main.c \ +d_net.c \ + doomdata.h \ + doomdef.h \ + dstrings.h \ +f_finale.c \ +g_game.c \ +info.c info.h \ +in_lude.c \ +m_random.c m_random.h \ +mn_menu.c \ + p_action.h \ +p_ceilng.c \ +p_doors.c \ +p_enemy.c \ +p_floor.c \ +p_inter.c \ +p_lights.c \ +p_local.h \ +p_map.c \ +p_maputl.c \ +p_mobj.c \ +p_plats.c \ +p_pspr.c \ +p_saveg.c \ +p_setup.c \ +p_sight.c \ +p_spec.c p_spec.h \ +p_switch.c \ +p_telept.c \ +p_tick.c \ +p_user.c \ +r_bsp.c \ +r_data.c \ +r_draw.c \ + r_local.h \ +r_main.c \ +r_plane.c \ +r_segs.c \ +r_things.c \ +sb_bar.c \ +sounds.c sounds.h \ +s_sound.c s_sound.h + +if HAVE_ICONS + +heretic_icon.c : $(top_builddir)/data/heretic.png + $(top_builddir)/data/convert-icon $(top_builddir)/data/heretic.png $@ + +endif diff --git a/games/NXDoom/src/heretic/am_data.h b/games/NXDoom/src/heretic/am_data.h new file mode 100644 index 00000000000..c5efb0894a9 --- /dev/null +++ b/games/NXDoom/src/heretic/am_data.h @@ -0,0 +1,103 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// AM_data.h : The vector graphics for the automap + +#ifndef __AMDATA_H__ +#define __AMDATA_H__ + +// a line drawing of the player pointing right, starting from the middle. + +#define R ((8*PLAYERRADIUS)/7) + +mline_t player_arrow[] = { + { { -R+R/4, 0 }, { 0, 0} }, // center line. + { { -R+R/4, R/8 }, { R, 0} }, // blade + { { -R+R/4, -R/8 }, { R, 0 } }, + { { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece + { { -R+R/8, -R/4 }, { -R+R/8, R/4 } }, + { { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors + { { -R+R/8, R/4 }, { -R+R/4, R/4} }, + { { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel + { { -R-R/4, R/8 }, { -R+R/8, R/8 } }, + { { -R-R/4, -R/8}, { -R+R/8, -R/8 } } + }; + +mline_t keysquare[] = { + { { 0, 0 }, { R/4, -R/2 } }, + { { R/4, -R/2 }, { R/2, -R/2 } }, + { { R/2, -R/2 }, { R/2, R/2 } }, + { { R/2, R/2 }, { R/4, R/2 } }, + { { R/4, R/2 }, { 0, 0 } }, // handle part type thing + { { 0, 0 }, { -R, 0 } }, // stem + { { -R, 0 }, { -R, -R/2 } }, // end lockpick part + { { -3*R/4, 0 }, { -3*R/4, -R/4 } } + }; + +/*mline_t player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/4 } }, // -----> + { { R, 0 }, { R-R/2, -R/4 } }, + { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> + { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> + { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } + }; +*/ +#undef R +#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) +#define NUMKEYSQUARELINES (sizeof(keysquare)/sizeof(mline_t)) + +#define R ((8*PLAYERRADIUS)/7) +mline_t cheat_player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/6 } }, // -----> + { { R, 0 }, { R-R/2, -R/6 } }, + { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> + { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> + { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, + { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> + { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, + { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, + { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> + { { -R/6, -R/6 }, { 0, -R/6 } }, + { { 0, -R/6 }, { 0, R/4 } }, + { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> + { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, + { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } + }; +#undef R +#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) + +#define R (FRACUNIT) +mline_t triangle_guy[] = { + { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } }, + { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } }, + { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } } + }; +#undef R +#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t)) + +#define R (FRACUNIT) +mline_t thintriangle_guy[] = { + { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, + { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, + { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } + }; +#undef R +#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) + +#endif diff --git a/games/NXDoom/src/heretic/am_map.c b/games/NXDoom/src/heretic/am_map.c new file mode 100644 index 00000000000..afc0c4222d1 --- /dev/null +++ b/games/NXDoom/src/heretic/am_map.c @@ -0,0 +1,1535 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// AM_map.c + +#include + +#include "doomdef.h" +#include "deh_str.h" +#include "i_timer.h" +#include "i_video.h" +#include "m_controls.h" +#include "p_local.h" +#include "am_map.h" +#include "am_data.h" + +#include "doomkeys.h" +#include "v_video.h" + +vertex_t KeyPoints[NUM_KEY_TYPES]; + +#define NUMALIAS 3 // Number of antialiased lines. + +const char *LevelNames[] = { + // EPISODE 1 - THE CITY OF THE DAMNED + "E1M1: THE DOCKS", + "E1M2: THE DUNGEONS", + "E1M3: THE GATEHOUSE", + "E1M4: THE GUARD TOWER", + "E1M5: THE CITADEL", + "E1M6: THE CATHEDRAL", + "E1M7: THE CRYPTS", + "E1M8: HELL'S MAW", + "E1M9: THE GRAVEYARD", + // EPISODE 2 - HELL'S MAW + "E2M1: THE CRATER", + "E2M2: THE LAVA PITS", + "E2M3: THE RIVER OF FIRE", + "E2M4: THE ICE GROTTO", + "E2M5: THE CATACOMBS", + "E2M6: THE LABYRINTH", + "E2M7: THE GREAT HALL", + "E2M8: THE PORTALS OF CHAOS", + "E2M9: THE GLACIER", + // EPISODE 3 - THE DOME OF D'SPARIL + "E3M1: THE STOREHOUSE", + "E3M2: THE CESSPOOL", + "E3M3: THE CONFLUENCE", + "E3M4: THE AZURE FORTRESS", + "E3M5: THE OPHIDIAN LAIR", + "E3M6: THE HALLS OF FEAR", + "E3M7: THE CHASM", + "E3M8: D'SPARIL'S KEEP", + "E3M9: THE AQUIFER", + // EPISODE 4: THE OSSUARY + "E4M1: CATAFALQUE", + "E4M2: BLOCKHOUSE", + "E4M3: AMBULATORY", + "E4M4: SEPULCHER", + "E4M5: GREAT STAIR", + "E4M6: HALLS OF THE APOSTATE", + "E4M7: RAMPARTS OF PERDITION", + "E4M8: SHATTERED BRIDGE", + "E4M9: MAUSOLEUM", + // EPISODE 5: THE STAGNANT DEMESNE + "E5M1: OCHRE CLIFFS", + "E5M2: RAPIDS", + "E5M3: QUAY", + "E5M4: COURTYARD", + "E5M5: HYDRATYR", + "E5M6: COLONNADE", + "E5M7: FOETID MANSE", + "E5M8: FIELD OF JUDGEMENT", + "E5M9: SKEIN OF D'SPARIL", + // EPISODE 6: unnamed + "E6M1: ", + "E6M2: ", + "E6M3: ", +}; + +static int cheating = 0; +static int grid = 0; + +boolean automapactive = false; +static int finit_width = SCREENWIDTH; +static int finit_height = SCREENHEIGHT - 42; +static int f_x, f_y; // location of window on screen +static int f_w, f_h; // size of window on screen +static int lightlev; // used for funky strobing effect +static byte *fb; // pseudo-frame buffer +static int amclock; + +static mpoint_t m_paninc; // how far the window pans each tic (map coords) +static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) +static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) + +static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) +static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) + +// width/height of window on map (map coords) +static fixed_t m_w, m_h; +static fixed_t min_x, min_y; // based on level size +static fixed_t max_x, max_y; // based on level size +static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y +static fixed_t min_w, min_h; // based on player size +static fixed_t min_scale_mtof; // used to tell when to stop zooming out +static fixed_t max_scale_mtof; // used to tell when to stop zooming in + +// old stuff for recovery later +static fixed_t old_m_w, old_m_h; +static fixed_t old_m_x, old_m_y; + +// old location used by the Follower routine +static mpoint_t f_oldloc; + +// used by MTOF to scale from map-to-frame-buffer coords +static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; +// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) +static fixed_t scale_ftom; + +static player_t *plr; // the player represented by an arrow +static vertex_t oldplr; + +//static patch_t *marknums[10]; // numbers used for marking by the automap +//static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are +//static int markpointnum = 0; // next point to be assigned + +static int followplayer = 1; // specifies whether to follow the player around + +static char cheat_amap[] = { 'r', 'a', 'v', 'm', 'a', 'p' }; + +static byte cheatcount = 0; + +static byte antialias[NUMALIAS][8] = { + {96, 97, 98, 99, 100, 101, 102, 103}, + {110, 109, 108, 107, 106, 105, 104, 103}, + {75, 76, 77, 78, 79, 80, 81, 103} +}; + +/* +static byte *aliasmax[NUMALIAS] = { + &antialias[0][7], &antialias[1][7], &antialias[2][7] +};*/ + +static byte *maplump; // pointer to the raw data for the automap background. +static short mapystart = 0; // y-value for the start of the map bitmap...used in the paralax stuff. +static short mapxstart = 0; //x-value for the bitmap. + +//byte screens[][SCREENWIDTH*SCREENHEIGHT]; +//void V_MarkRect (int x, int y, int width, int height); + +// Functions + +void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, + int NumLevels, unsigned short IntensityBits); + +// Calculates the slope and slope according to the x-axis of a line +// segment in map coordinates (with the upright y-axis n' all) so +// that it can be used with the brain-dead drawing stuff. + +// Ripped out for Heretic +/* +void AM_getIslope(mline_t *ml, islope_t *is) +{ + int dx, dy; + + dy = ml->a.y - ml->b.y; + dx = ml->b.x - ml->a.x; + if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); + else is->islp = FixedDiv(dx, dy); + if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); + else is->slp = FixedDiv(dy, dx); +} +*/ + +void AM_activateNewScale(void) +{ + m_x += m_w / 2; + m_y += m_h / 2; + m_w = FTOM(f_w); + m_h = FTOM(f_h); + m_x -= m_w / 2; + m_y -= m_h / 2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + +void AM_saveScaleAndLoc(void) +{ + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; +} + +void AM_restoreScaleAndLoc(void) +{ + + m_w = old_m_w; + m_h = old_m_h; + if (!followplayer) + { + m_x = old_m_x; + m_y = old_m_y; + } + else + { + m_x = plr->mo->x - m_w / 2; + m_y = plr->mo->y - m_h / 2; + } + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // Change the scaling multipliers + scale_mtof = FixedDiv(f_w << FRACBITS, m_w); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +} + +// adds a marker at the current location + +/* +void AM_addMark(void) +{ + markpoints[markpointnum].x = m_x + m_w/2; + markpoints[markpointnum].y = m_y + m_h/2; + markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; + +} +*/ +void AM_findMinMaxBoundaries(void) +{ + int i; + fixed_t a, b; + + min_x = min_y = INT_MAX; + max_x = max_y = -INT_MAX; + for (i = 0; i < numvertexes; i++) + { + if (vertexes[i].x < min_x) + min_x = vertexes[i].x; + else if (vertexes[i].x > max_x) + max_x = vertexes[i].x; + if (vertexes[i].y < min_y) + min_y = vertexes[i].y; + else if (vertexes[i].y > max_y) + max_y = vertexes[i].y; + } + max_w = max_x - min_x; + max_h = max_y - min_y; + min_w = 2 * PLAYERRADIUS; + min_h = 2 * PLAYERRADIUS; + + a = FixedDiv(f_w << FRACBITS, max_w); + b = FixedDiv(f_h << FRACBITS, max_h); + min_scale_mtof = a < b ? a : b; + + max_scale_mtof = FixedDiv(f_h << FRACBITS, 2 * PLAYERRADIUS); + +} + +void AM_changeWindowLoc(void) +{ + if (m_paninc.x || m_paninc.y) + { + followplayer = 0; + f_oldloc.x = INT_MAX; + } + + m_x += m_paninc.x; + m_y += m_paninc.y; + + if (m_x + m_w / 2 > max_x) + { + m_x = max_x - m_w / 2; + m_paninc.x = 0; + } + else if (m_x + m_w / 2 < min_x) + { + m_x = min_x - m_w / 2; + m_paninc.x = 0; + } + if (m_y + m_h / 2 > max_y) + { + m_y = max_y - m_h / 2; + m_paninc.y = 0; + } + else if (m_y + m_h / 2 < min_y) + { + m_y = min_y - m_h / 2; + m_paninc.y = 0; + } + + // The following code was commented out in the released Heretic source, + // but I believe we need to do this here to stop the background moving + // when we reach the map boundaries. (In the released source it's done + // in AM_clearFB). + mapxstart += MTOF(m_paninc.x+FRACUNIT/2); + mapystart -= MTOF(m_paninc.y+FRACUNIT/2); + if(mapxstart >= finit_width) + mapxstart -= finit_width; + if(mapxstart < 0) + mapxstart += finit_width; + if(mapystart >= finit_height) + mapystart -= finit_height; + if(mapystart < 0) + mapystart += finit_height; + // - end of code that was commented-out + + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + +void AM_initVariables(void) +{ + int pnum; + thinker_t *think; + mobj_t *mo; + + //static event_t st_notify = { ev_keyup, AM_MSGENTERED }; + + automapactive = true; + fb = I_VideoBuffer; + + f_oldloc.x = INT_MAX; + amclock = 0; + lightlev = 0; + + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; + + m_w = FTOM(f_w); + m_h = FTOM(f_h); + + // find player to center on initially + if (!playeringame[pnum = consoleplayer]) + for (pnum = 0; pnum < MAXPLAYERS; pnum++) + if (playeringame[pnum]) + break; + plr = &players[pnum]; + oldplr.x = plr->mo->x; + oldplr.y = plr->mo->y; + m_x = plr->mo->x - m_w / 2; + m_y = plr->mo->y - m_h / 2; + AM_changeWindowLoc(); + + // for saving & restoring + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + + // load in the location of keys, if in baby mode + + memset(KeyPoints, 0, sizeof(vertex_t) * 3); + if (gameskill == sk_baby) + { + for (think = thinkercap.next; think != &thinkercap; + think = think->next) + { + if (think->function != P_MobjThinker) + { //not a mobj + continue; + } + mo = (mobj_t *) think; + if (mo->type == MT_CKEY) + { + KeyPoints[0].x = mo->x; + KeyPoints[0].y = mo->y; + } + else if (mo->type == MT_AKYY) + { + KeyPoints[1].x = mo->x; + KeyPoints[1].y = mo->y; + } + else if (mo->type == MT_BKYY) + { + KeyPoints[2].x = mo->x; + KeyPoints[2].y = mo->y; + } + } + } + + // inform the status bar of the change +//c ST_Responder(&st_notify); +} + +void AM_loadPics(void) +{ + //int i; + //char namebuf[9]; +/* for (i=0;i<10;i++) + { + M_snprintf(namebuf, sizeof(namebuf), "AMMNUM%d", i); + marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); + }*/ + maplump = W_CacheLumpName(DEH_String("AUTOPAGE"), PU_STATIC); +} + +/*void AM_unloadPics(void) +{ + int i; + for (i=0;i<10;i++) Z_ChangeTag(marknums[i], PU_CACHE); + +}*/ + +/* +void AM_clearMarks(void) +{ + int i; + for (i=0;i max_scale_mtof) + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +} + +static boolean stopped = true; + +void AM_Stop(void) +{ + //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; + +// AM_unloadPics(); + automapactive = false; +// ST_Responder(&st_notify); + stopped = true; + BorderNeedRefresh = true; +} + +void AM_Start(void) +{ + static int lastlevel = -1, lastepisode = -1; + + if (!stopped) + AM_Stop(); + stopped = false; + if (gamestate != GS_LEVEL) + { + return; // don't show automap if we aren't in a game! + } + if (lastlevel != gamemap || lastepisode != gameepisode) + { + AM_LevelInit(); + lastlevel = gamemap; + lastepisode = gameepisode; + } + AM_initVariables(); + AM_loadPics(); +} + +// set the window scale to the maximum size + +void AM_minOutWindowScale(void) +{ + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + +// set the window scale to the minimum size + +void AM_maxOutWindowScale(void) +{ + scale_mtof = max_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + +boolean AM_Responder(event_t * ev) +{ + int rc; + int key; + static int bigstate = 0; + static int joywait = 0; + + key = ev->data1; + rc = false; + + if (ev->type == ev_joystick && joybautomap >= 0 + && (ev->data1 & (1 << joybautomap)) != 0 && joywait < I_GetTime()) + { + joywait = I_GetTime() + 5; + + if (!automapactive) + { + AM_Start (); + viewactive = false; + } + else + { + bigstate = 0; + viewactive = true; + AM_Stop (); + } + } + + if (!automapactive) + { + + if (ev->type == ev_keydown && key == key_map_toggle + && gamestate == GS_LEVEL) + { + AM_Start(); + viewactive = false; + // viewactive = true; + rc = true; + } + } + else if (ev->type == ev_keydown) + { + rc = true; + + if (key == key_map_east) // pan right + { + if (!followplayer) + m_paninc.x = FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_west) // pan left + { + if (!followplayer) + m_paninc.x = -FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_north) // pan up + { + if (!followplayer) + m_paninc.y = FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_south) // pan down + { + if (!followplayer) + m_paninc.y = -FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_zoomout) // zoom out + { + mtof_zoommul = M_ZOOMOUT; + ftom_zoommul = M_ZOOMIN; + } + else if (key == key_map_zoomin) // zoom in + { + mtof_zoommul = M_ZOOMIN; + ftom_zoommul = M_ZOOMOUT; + } + else if (key == key_map_toggle) // toggle map (tab) + { + bigstate = 0; + viewactive = true; + AM_Stop(); + } + else if (key == key_map_maxzoom) + { + bigstate = !bigstate; + if (bigstate) + { + AM_saveScaleAndLoc(); + AM_minOutWindowScale(); + } + else + AM_restoreScaleAndLoc(); + } + else if (key == key_map_follow) + { + followplayer = !followplayer; + f_oldloc.x = INT_MAX; + P_SetMessage(plr, + followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, + true); + } + /* + else if (key == key_map_grid) + { + grid = !grid; + plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF; + } + else if (key == key_map_mark) + { + M_snprintf(buffer, sizeof(buffer), "%s %d", + AMSTR_MARKEDSPOT, markpointnum); + plr->message = buffer; + AM_addMark(); + } + else if (key == key_map_clearmark) + { + AM_clearMarks(); + plr->message = AMSTR_MARKSCLEARED; + } + */ + else + { + rc = false; + } + + if (cheat_amap[cheatcount] == ev->data1 && !netgame) + cheatcount++; + else + cheatcount = 0; + if (cheatcount == 6) + { + cheatcount = 0; + rc = false; + cheating = (cheating + 1) % 3; + } + } + + else if (ev->type == ev_keyup) + { + rc = false; + + if (key == key_map_east) + { + if (!followplayer) + m_paninc.x = 0; + } + else if (key == key_map_west) + { + if (!followplayer) + m_paninc.x = 0; + } + else if (key == key_map_north) + { + if (!followplayer) + m_paninc.y = 0; + } + else if (key == key_map_south) + { + if (!followplayer) + m_paninc.y = 0; + } + else if (key == key_map_zoomout || key == key_map_zoomin) + { + mtof_zoommul = FRACUNIT; + ftom_zoommul = FRACUNIT; + } + } + + return rc; + +} + +void AM_changeWindowScale(void) +{ + + // Change the scaling multipliers + scale_mtof = FixedMul(scale_mtof, mtof_zoommul); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + + if (scale_mtof < min_scale_mtof) + AM_minOutWindowScale(); + else if (scale_mtof > max_scale_mtof) + AM_maxOutWindowScale(); + else + AM_activateNewScale(); +} + +void AM_doFollowPlayer(void) +{ + if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) + { +// m_x = FTOM(MTOF(plr->mo->x - m_w/2)); +// m_y = FTOM(MTOF(plr->mo->y - m_h/2)); +// m_x = plr->mo->x - m_w/2; +// m_y = plr->mo->y - m_h/2; + m_x = FTOM(MTOF(plr->mo->x)) - m_w / 2; + m_y = FTOM(MTOF(plr->mo->y)) - m_h / 2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // do the parallax parchment scrolling. +/* + dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point + dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y)); + + if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first + dmapx=0; //goes into the automap. + mapxstart += dmapx; + mapystart += dmapy; + + while(mapxstart >= finit_width) + mapxstart -= finit_width; + while(mapxstart < 0) + mapxstart += finit_width; + while(mapystart >= finit_height) + mapystart -= finit_height; + while(mapystart < 0) + mapystart += finit_height; +*/ + f_oldloc.x = plr->mo->x; + f_oldloc.y = plr->mo->y; + } +} + +// Ripped out for Heretic +/* +void AM_updateLightLev(void) +{ + static nexttic = 0; +//static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; + static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; + static int litelevelscnt = 0; + + // Change light level + if (amclock>nexttic) + { + lightlev = litelevels[litelevelscnt++]; + if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; + nexttic = amclock + 6 - (amclock % 6); + } +} +*/ + +void AM_Ticker(void) +{ + + if (!automapactive) + return; + + amclock++; + + if (followplayer) + AM_doFollowPlayer(); + + // Change the zoom if necessary + if (ftom_zoommul != FRACUNIT) + AM_changeWindowScale(); + + // Change x,y location + if (m_paninc.x || m_paninc.y) + AM_changeWindowLoc(); + // Update light level +// AM_updateLightLev(); + +} + +void AM_clearFB(int color) +{ + int i, j; + int dmapx; + int dmapy; + + if (followplayer) + { + dmapx = (MTOF(plr->mo->x) - MTOF(oldplr.x)); //fixed point + dmapy = (MTOF(oldplr.y) - MTOF(plr->mo->y)); + + oldplr.x = plr->mo->x; + oldplr.y = plr->mo->y; +// if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first +// dmapx=0; //goes into the automap. + mapxstart += dmapx >> 1; + mapystart += dmapy >> 1; + + while (mapxstart >= finit_width) + mapxstart -= finit_width; + while (mapxstart < 0) + mapxstart += finit_width; + while (mapystart >= finit_height) + mapystart -= finit_height; + while (mapystart < 0) + mapystart += finit_height; + } + else + { + // The released Heretic source does this here, but this causes a bug + // where the map background keeps moving when we reach the map + // boundaries. This is instead done in AM_changeWindowLoc. + /* + mapxstart += (MTOF(m_paninc.x) >> 1); + mapystart -= (MTOF(m_paninc.y) >> 1); + + if (mapxstart >= finit_width) + mapxstart -= finit_width; + if (mapxstart < 0) + mapxstart += finit_width; + if (mapystart >= finit_height) + mapystart -= finit_height; + if (mapystart < 0) + mapystart += finit_height; + */ + } + + //blit the automap background to the screen. + j = mapystart * finit_width; + for (i = 0; i < finit_height; i++) + { + memcpy(I_VideoBuffer + i * finit_width, maplump + j + mapxstart, + finit_width - mapxstart); + memcpy(I_VideoBuffer + i * finit_width + finit_width - mapxstart, + maplump + j, mapxstart); + j += finit_width; + if (j >= finit_height * finit_width) + j = 0; + } + +// memcpy(I_VideoBuffer, maplump, finit_width*finit_height); +// memset(fb, color, f_w*f_h); +} + +// Based on Cohen-Sutherland clipping algorithm but with a slightly +// faster reject and precalculated slopes. If I need the speed, will +// hash algorithm to the common cases. + +boolean AM_clipMline(mline_t * ml, fline_t * fl) +{ + enum + { LEFT = 1, RIGHT = 2, BOTTOM = 4, TOP = 8 }; + int outcode1 = 0, outcode2 = 0, outside; + fpoint_t tmp = { 0, 0 }; + int dx, dy; + +#define DOOUTCODE(oc, mx, my) \ + (oc) = 0; \ + if ((my) < 0) (oc) |= TOP; \ + else if ((my) >= f_h) (oc) |= BOTTOM; \ + if ((mx) < 0) (oc) |= LEFT; \ + else if ((mx) >= f_w) (oc) |= RIGHT + + // do trivial rejects and outcodes + if (ml->a.y > m_y2) + outcode1 = TOP; + else if (ml->a.y < m_y) + outcode1 = BOTTOM; + if (ml->b.y > m_y2) + outcode2 = TOP; + else if (ml->b.y < m_y) + outcode2 = BOTTOM; + if (outcode1 & outcode2) + return false; // trivially outside + + if (ml->a.x < m_x) + outcode1 |= LEFT; + else if (ml->a.x > m_x2) + outcode1 |= RIGHT; + if (ml->b.x < m_x) + outcode2 |= LEFT; + else if (ml->b.x > m_x2) + outcode2 |= RIGHT; + if (outcode1 & outcode2) + return false; // trivially outside + + // transform to frame-buffer coordinates. + fl->a.x = CXMTOF(ml->a.x); + fl->a.y = CYMTOF(ml->a.y); + fl->b.x = CXMTOF(ml->b.x); + fl->b.y = CYMTOF(ml->b.y); + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + if (outcode1 & outcode2) + return false; + + while (outcode1 | outcode2) + { + // may be partially inside box + // find an outside point + if (outcode1) + outside = outcode1; + else + outside = outcode2; + // clip to each side + if (outside & TOP) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx * (fl->a.y)) / dy; + tmp.y = 0; + } + else if (outside & BOTTOM) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx * (fl->a.y - f_h)) / dy; + tmp.y = f_h - 1; + } + else if (outside & RIGHT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy * (f_w - 1 - fl->a.x)) / dx; + tmp.x = f_w - 1; + } + else if (outside & LEFT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy * (-fl->a.x)) / dx; + tmp.x = 0; + } + if (outside == outcode1) + { + fl->a = tmp; + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + } + else + { + fl->b = tmp; + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + } + if (outcode1 & outcode2) + return false; // trivially outside + } + + return true; +} + +#undef DOOUTCODE + +// Classic Bresenham w/ whatever optimizations I need for speed + +void AM_drawFline(fline_t * fl, int color) +{ + + register int x, y, dx, dy, sx, sy, ax, ay, d; + static int fuck = 0; + + switch (color) + { + case WALLCOLORS: + DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[0][0], + 8, 3); + break; + case FDWALLCOLORS: + DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[1][0], + 8, 3); + break; + case CDWALLCOLORS: + DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[2][0], + 8, 3); + break; + default: + { + // For debugging only + if (fl->a.x < 0 || fl->a.x >= f_w + || fl->a.y < 0 || fl->a.y >= f_h + || fl->b.x < 0 || fl->b.x >= f_w + || fl->b.y < 0 || fl->b.y >= f_h) + { + fprintf(stderr, "fuck %d \r", fuck++); + return; + } + +#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO! + + dx = fl->b.x - fl->a.x; + ax = 2 * (dx < 0 ? -dx : dx); + sx = dx < 0 ? -1 : 1; + + dy = fl->b.y - fl->a.y; + ay = 2 * (dy < 0 ? -dy : dy); + sy = dy < 0 ? -1 : 1; + + x = fl->a.x; + y = fl->a.y; + + if (ax > ay) + { + d = ay - ax / 2; + while (1) + { + DOT(x, y, color); + if (x == fl->b.x) + return; + if (d >= 0) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } + else + { + d = ax - ay / 2; + while (1) + { + DOT(x, y, color); + if (y == fl->b.y) + return; + if (d >= 0) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } + } + } +} + +/* Wu antialiased line drawer. + * (X0,Y0),(X1,Y1) = line to draw + * BaseColor = color # of first color in block used for antialiasing, the + * 100% intensity version of the drawing color + * NumLevels = size of color block, with BaseColor+NumLevels-1 being the + * 0% intensity version of the drawing color + * IntensityBits = log base 2 of NumLevels; the # of bits used to describe + * the intensity of the drawing color. 2**IntensityBits==NumLevels + */ +void PUTDOT(short xx, short yy, byte * cc, byte * cm) +{ + static int oldyy; + static int oldyyshifted; + byte *oldcc = cc; + + if (xx < 32) + cc += 7 - (xx >> 2); + else if (xx > (finit_width - 32)) + cc += 7 - ((finit_width - xx) >> 2); +// if(cc==oldcc) //make sure that we don't double fade the corners. +// { + if (yy < 32) + cc += 7 - (yy >> 2); + else if (yy > (finit_height - 32)) + cc += 7 - ((finit_height - yy) >> 2); +// } + if (cc > cm && cm != NULL) + { + cc = cm; + } + else if (cc > oldcc + 6) // don't let the color escape from the fade table... + { + cc = oldcc + 6; + } + if (yy == oldyy + 1) + { + oldyy++; + oldyyshifted += 320; + } + else if (yy == oldyy - 1) + { + oldyy--; + oldyyshifted -= 320; + } + else if (yy != oldyy) + { + oldyy = yy; + oldyyshifted = yy * 320; + } + fb[oldyyshifted + xx] = *(cc); +// fb[(yy)*f_w+(xx)]=*(cc); +} + +void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, + int NumLevels, unsigned short IntensityBits) +{ + unsigned short IntensityShift, ErrorAdj, ErrorAcc; + unsigned short ErrorAccTemp, Weighting, WeightingComplementMask; + short DeltaX, DeltaY, Temp, XDir; + + /* Make sure the line runs top to bottom */ + if (Y0 > Y1) + { + Temp = Y0; + Y0 = Y1; + Y1 = Temp; + Temp = X0; + X0 = X1; + X1 = Temp; + } + /* Draw the initial pixel, which is always exactly intersected by + the line and so needs no weighting */ + PUTDOT(X0, Y0, &BaseColor[0], NULL); + + if ((DeltaX = X1 - X0) >= 0) + { + XDir = 1; + } + else + { + XDir = -1; + DeltaX = -DeltaX; /* make DeltaX positive */ + } + /* Special-case horizontal, vertical, and diagonal lines, which + require no weighting because they go right through the center of + every pixel */ + if ((DeltaY = Y1 - Y0) == 0) + { + /* Horizontal line */ + while (DeltaX-- != 0) + { + X0 += XDir; + PUTDOT(X0, Y0, &BaseColor[0], NULL); + } + return; + } + if (DeltaX == 0) + { + /* Vertical line */ + do + { + Y0++; + PUTDOT(X0, Y0, &BaseColor[0], NULL); + } + while (--DeltaY != 0); + return; + } + //diagonal line. + if (DeltaX == DeltaY) + { + do + { + X0 += XDir; + Y0++; + PUTDOT(X0, Y0, &BaseColor[0], NULL); + } + while (--DeltaY != 0); + return; + } + /* Line is not horizontal, diagonal, or vertical */ + ErrorAcc = 0; /* initialize the line error accumulator to 0 */ + /* # of bits by which to shift ErrorAcc to get intensity level */ + IntensityShift = 16 - IntensityBits; + /* Mask used to flip all bits in an intensity weighting, producing the + result (1 - intensity weighting) */ + WeightingComplementMask = NumLevels - 1; + /* Is this an X-major or Y-major line? */ + if (DeltaY > DeltaX) + { + /* Y-major line; calculate 16-bit fixed-point fractional part of a + pixel that X advances each time Y advances 1 pixel, truncating the + result so that we won't overrun the endpoint along the X axis */ + ErrorAdj = ((unsigned int) DeltaX << 16) / (unsigned int) DeltaY; + /* Draw all pixels other than the first and last */ + while (--DeltaY) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorAdj; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the X coord */ + X0 += XDir; + } + Y0++; /* Y-major, so always advance Y */ + /* The IntensityBits most significant bits of ErrorAcc give us the + intensity weighting for this pixel, and the complement of the + weighting for the paired pixel */ + Weighting = ErrorAcc >> IntensityShift; + PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); + PUTDOT(X0 + XDir, Y0, + &BaseColor[(Weighting ^ WeightingComplementMask)], + &BaseColor[7]); + } + /* Draw the final pixel, which is always exactly intersected by the line + and so needs no weighting */ + PUTDOT(X1, Y1, &BaseColor[0], NULL); + return; + } + /* It's an X-major line; calculate 16-bit fixed-point fractional part of a + pixel that Y advances each time X advances 1 pixel, truncating the + result to avoid overrunning the endpoint along the X axis */ + ErrorAdj = ((unsigned int) DeltaY << 16) / (unsigned int) DeltaX; + /* Draw all pixels other than the first and last */ + while (--DeltaX) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorAdj; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the Y coord */ + Y0++; + } + X0 += XDir; /* X-major, so always advance X */ + /* The IntensityBits most significant bits of ErrorAcc give us the + intensity weighting for this pixel, and the complement of the + weighting for the paired pixel */ + Weighting = ErrorAcc >> IntensityShift; + PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); + PUTDOT(X0, Y0 + 1, + &BaseColor[(Weighting ^ WeightingComplementMask)], + &BaseColor[7]); + + } + /* Draw the final pixel, which is always exactly intersected by the line + and so needs no weighting */ + PUTDOT(X1, Y1, &BaseColor[0], NULL); +} + +void AM_drawMline(mline_t * ml, int color) +{ + static fline_t fl; + + if (AM_clipMline(ml, &fl)) + AM_drawFline(&fl, color); // draws it on frame buffer using fb coords + +} + +void AM_drawGrid(int color) +{ + fixed_t x, y; + fixed_t start, end; + mline_t ml; + + // Figure out start of vertical gridlines + start = m_x; + if ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)) + start += (MAPBLOCKUNITS << FRACBITS) + - ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)); + end = m_x + m_w; + + // draw vertical gridlines + ml.a.y = m_y; + ml.b.y = m_y + m_h; + for (x = start; x < end; x += (MAPBLOCKUNITS << FRACBITS)) + { + ml.a.x = x; + ml.b.x = x; + AM_drawMline(&ml, color); + } + + // Figure out start of horizontal gridlines + start = m_y; + if ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)) + start += (MAPBLOCKUNITS << FRACBITS) + - ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)); + end = m_y + m_h; + + // draw horizontal gridlines + ml.a.x = m_x; + ml.b.x = m_x + m_w; + for (y = start; y < end; y += (MAPBLOCKUNITS << FRACBITS)) + { + ml.a.y = y; + ml.b.y = y; + AM_drawMline(&ml, color); + } +} + +void AM_drawWalls(void) +{ + int i; + static mline_t l; + + for (i = 0; i < numlines; i++) + { + l.a.x = lines[i].v1->x; + l.a.y = lines[i].v1->y; + l.b.x = lines[i].v2->x; + l.b.y = lines[i].v2->y; + if (cheating || (lines[i].flags & ML_MAPPED)) + { + if ((lines[i].flags & LINE_NEVERSEE) && !cheating) + continue; + if (!lines[i].backsector) + { + AM_drawMline(&l, WALLCOLORS + lightlev); + } + else + { + if (lines[i].special == 39) + { // teleporters + AM_drawMline(&l, WALLCOLORS + WALLRANGE / 2); + } + else if (lines[i].flags & ML_SECRET) // secret door + { + if (cheating) + AM_drawMline(&l, 0); + else + AM_drawMline(&l, WALLCOLORS + lightlev); + } + else if (lines[i].special > 25 && lines[i].special < 35) + { + switch (lines[i].special) + { + case 26: + case 32: + AM_drawMline(&l, BLUEKEY); + break; + case 27: + case 34: + AM_drawMline(&l, YELLOWKEY); + break; + case 28: + case 33: + AM_drawMline(&l, GREENKEY); + break; + default: + break; + } + } + else if (lines[i].backsector->floorheight + != lines[i].frontsector->floorheight) + { + AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change + } + else if (lines[i].backsector->ceilingheight + != lines[i].frontsector->ceilingheight) + { + AM_drawMline(&l, CDWALLCOLORS + lightlev); // ceiling level change + } + else if (cheating) + { + AM_drawMline(&l, TSWALLCOLORS + lightlev); + } + } + } + else if (plr->powers[pw_allmap]) + { + if (!(lines[i].flags & LINE_NEVERSEE)) + AM_drawMline(&l, GRAYS + 3); + } + } + +} + +void AM_rotate(fixed_t * x, fixed_t * y, angle_t a) +{ + fixed_t tmpx; + + tmpx = FixedMul(*x, finecosine[a >> ANGLETOFINESHIFT]) + - FixedMul(*y, finesine[a >> ANGLETOFINESHIFT]); + *y = FixedMul(*x, finesine[a >> ANGLETOFINESHIFT]) + + FixedMul(*y, finecosine[a >> ANGLETOFINESHIFT]); + *x = tmpx; +} + +void AM_drawLineCharacter(mline_t * lineguy, int lineguylines, fixed_t scale, + angle_t angle, int color, fixed_t x, fixed_t y) +{ + int i; + mline_t l; + + for (i = 0; i < lineguylines; i++) + { + l.a.x = lineguy[i].a.x; + l.a.y = lineguy[i].a.y; + if (scale) + { + l.a.x = FixedMul(scale, l.a.x); + l.a.y = FixedMul(scale, l.a.y); + } + if (angle) + AM_rotate(&l.a.x, &l.a.y, angle); + l.a.x += x; + l.a.y += y; + + l.b.x = lineguy[i].b.x; + l.b.y = lineguy[i].b.y; + if (scale) + { + l.b.x = FixedMul(scale, l.b.x); + l.b.y = FixedMul(scale, l.b.y); + } + if (angle) + AM_rotate(&l.b.x, &l.b.y, angle); + l.b.x += x; + l.b.y += y; + + AM_drawMline(&l, color); + } + +} + +void AM_drawPlayers(void) +{ + + int i; + player_t *p; + static int their_colors[] = { GREENKEY, YELLOWKEY, BLOODRED, BLUEKEY }; + int their_color = -1; + int color; + + if (!netgame) + { + /* + if (cheating) AM_drawLineCharacter(cheat_player_arrow, NUMCHEATPLYRLINES, 0, + plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); + *///cheat key player pointer is the same as non-cheat pointer.. + + AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, + WHITE, plr->mo->x, plr->mo->y); + return; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + their_color++; + p = &players[i]; + if (deathmatch && !singledemo && p != plr) + { + continue; + } + if (!playeringame[i]) + continue; + if (p->powers[pw_invisibility]) + color = 102; // *close* to the automap color + else + color = their_colors[their_color]; + AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, + color, p->mo->x, p->mo->y); + } +} + +void AM_drawThings(int colors, int colorrange) +{ + int i; + mobj_t *t; + + for (i = 0; i < numsectors; i++) + { + t = sectors[i].thinglist; + while (t) + { + AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, + 16 << FRACBITS, t->angle, colors + lightlev, + t->x, t->y); + t = t->snext; + } + } +} + +/* +void AM_drawMarks(void) +{ + int i, fx, fy, w, h; + + for (i=0;iwidth); + h = SHORT(marknums[i]->height); + fx = CXMTOF(markpoints[i].x); + fy = CYMTOF(markpoints[i].y); + if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) + V_DrawPatch(fx, fy, marknums[i]); + } + } +} +*/ + +void AM_drawkeys(void) +{ + if (KeyPoints[0].x != 0 || KeyPoints[0].y != 0) + { + AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY, + KeyPoints[0].x, KeyPoints[0].y); + } + if (KeyPoints[1].x != 0 || KeyPoints[1].y != 0) + { + AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY, + KeyPoints[1].x, KeyPoints[1].y); + } + if (KeyPoints[2].x != 0 || KeyPoints[2].y != 0) + { + AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY, + KeyPoints[2].x, KeyPoints[2].y); + } +} + +void AM_drawCrosshair(int color) +{ + fb[(f_w * (f_h + 1)) / 2] = color; // single point for now +} + +void AM_Drawer(void) +{ + const char *level_name; + int numepisodes; + + if (!automapactive) + return; + + UpdateState |= I_FULLSCRN; + AM_clearFB(BACKGROUND); + if (grid) + AM_drawGrid(GRIDCOLORS); + AM_drawWalls(); + AM_drawPlayers(); + if (cheating == 2) + AM_drawThings(THINGCOLORS, THINGRANGE); +// AM_drawCrosshair(XHAIRCOLORS); + +// AM_drawMarks(); + if (gameskill == sk_baby) + { + AM_drawkeys(); + } + + if (gamemode == retail) + { + numepisodes = 5; + } + else + { + numepisodes = 3; + } + + if (gameepisode <= numepisodes && gamemap < 10) + { + level_name = LevelNames[(gameepisode - 1) * 9 + gamemap - 1]; + MN_DrTextA(DEH_String(level_name), 20, 145); + } +// I_Update(); +// V_MarkRect(f_x, f_y, f_w, f_h); +} diff --git a/games/NXDoom/src/heretic/am_map.h b/games/NXDoom/src/heretic/am_map.h new file mode 100644 index 00000000000..aa535cc3007 --- /dev/null +++ b/games/NXDoom/src/heretic/am_map.h @@ -0,0 +1,124 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +#ifndef __AMMAP_H__ +#define __AMMAP_H__ + + +#include "r_local.h" + + +// For use if I do walls with outsides/insides +#define REDS 12*8 +#define REDRANGE 1 //16 +#define BLUES (256-4*16+8) +#define BLUERANGE 1 //8 +#define GREENS (33*8) +#define GREENRANGE 1 //16 +#define GRAYS (5*8) +#define GRAYSRANGE 1 //16 +#define BROWNS (14*8) +#define BROWNRANGE 1 //16 +#define YELLOWS 10*8 +#define YELLOWRANGE 1 +#define BLACK 0 +#define WHITE 4*8 +#define PARCH 13*8-1 +#define BLOODRED 150 +#define BLUEKEY 197 +#define YELLOWKEY 144 +#define GREENKEY 220 + +// Automap colors +#define BACKGROUND PARCH +#define YOURCOLORS WHITE +#define YOURRANGE 0 +#define WALLCOLORS REDS +#define WALLRANGE REDRANGE +#define TSWALLCOLORS GRAYS +#define TSWALLRANGE GRAYSRANGE +#define FDWALLCOLORS BROWNS +#define FDWALLRANGE BROWNRANGE +#define CDWALLCOLORS YELLOWS +#define CDWALLRANGE YELLOWRANGE +#define THINGCOLORS GREENS +#define THINGRANGE GREENRANGE +#define SECRETWALLCOLORS WALLCOLORS +#define SECRETWALLRANGE WALLRANGE +#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) +#define GRIDRANGE 0 +#define XHAIRCOLORS GRAYS + +// drawing stuff +#define FB 0 + +#define AM_NUMMARKPOINTS 10 + +#define AM_MSGHEADER (('a'<<24)+('m'<<16)) +#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) +#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) + +#define INITSCALEMTOF (.2*FRACUNIT) // scale on entry +// how much the automap moves window per tic in frame-buffer coordinates +#define F_PANINC 4 // moves 140 pixels in 1 second +// how much zoom-in per tic +#define M_ZOOMIN ((int) (1.02*FRACUNIT)) // goes to 2x in 1 second +// how much zoom-out per tic +#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) // pulls out to 0.5x in 1 second + +// translates between frame-buffer and map distances +#define FTOM(x) FixedMul(((x)<<16),scale_ftom) +#define MTOF(x) (FixedMul((x),scale_mtof)>>16) +// translates between frame-buffer and map coordinates +#define CXMTOF(x) (f_x + MTOF((x)-m_x)) +#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) + +// the following is crap +#define LINE_NEVERSEE ML_DONTDRAW + +typedef struct +{ + int x, y; +} fpoint_t; + +typedef struct +{ + fpoint_t a, b; +} fline_t; + +typedef vertex_t mpoint_t; + +typedef struct +{ + mpoint_t a, b; +} mline_t; + +typedef struct +{ + fixed_t slp, islp; +} islope_t; + +// extern int f_x, f_y, f_w, f_h; + + +extern boolean automapactive; +extern vertex_t KeyPoints[]; +extern const char *LevelNames[]; + + +void AM_Stop(void); + + +#endif diff --git a/games/NXDoom/src/heretic/ct_chat.c b/games/NXDoom/src/heretic/ct_chat.c new file mode 100644 index 00000000000..f0f8e5ff6bf --- /dev/null +++ b/games/NXDoom/src/heretic/ct_chat.c @@ -0,0 +1,477 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Chat mode +// + +#include +#include + +#include "doomdef.h" +#include "doomkeys.h" + +#include "deh_str.h" +#include "i_input.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +#define QUEUESIZE 128 +#define MESSAGESIZE 128 +#define MESSAGELEN 265 + +#define CT_PLR_GREEN 1 +#define CT_PLR_YELLOW 2 +#define CT_PLR_RED 3 +#define CT_PLR_BLUE 4 +#define CT_PLR_ALL 5 + +#define CT_ESCAPE 6 + +// Public data + + +boolean chatmodeon; + +// Private data + +void CT_queueChatChar(char ch); +void CT_ClearChatMessage(int player); +void CT_AddChar(int player, char c); +void CT_BackSpace(int player); + +int head; +int tail; +byte ChatQueue[QUEUESIZE]; +int chat_dest[MAXPLAYERS]; +char chat_msg[MAXPLAYERS][MESSAGESIZE]; +char plr_lastmsg[MAXPLAYERS][MESSAGESIZE + 9]; // add in the length of the pre-string +int msgptr[MAXPLAYERS]; +int msglen[MAXPLAYERS]; + +boolean cheated; + +static int FontABaseLump; + +const char *CT_FromPlrText[MAXPLAYERS] = { + "GREEN: ", + "YELLOW: ", + "RED: ", + "BLUE: " +}; + +char *chat_macros[10]; + +boolean altdown; +boolean shiftdown; + + +//=========================================================================== +// +// CT_Init +// +// Initialize chat mode data +//=========================================================================== + +void CT_Init(void) +{ + int i; + + head = 0; //initialize the queue index + tail = 0; + chatmodeon = false; + memset(ChatQueue, 0, QUEUESIZE); + for (i = 0; i < MAXPLAYERS; i++) + { + chat_dest[i] = 0; + msgptr[i] = 0; + memset(plr_lastmsg[i], 0, MESSAGESIZE); + memset(chat_msg[i], 0, MESSAGESIZE); + } + FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; + return; +} + +//=========================================================================== +// +// CT_Stop +// +//=========================================================================== + +void CT_Stop(void) +{ + chatmodeon = false; + I_StopTextInput(); + return; +} + +// These keys are allowed by Vanilla Heretic: + +static boolean ValidChatChar(char c) +{ + return (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || c == '!' || c == '?' + || c == ' ' || c == '\'' + || c == ',' || c == '.' + || c == '-' || c == '='; +} + +//=========================================================================== +// +// CT_Responder +// +//=========================================================================== + +boolean CT_Responder(event_t * ev) +{ + char *macro; + + int sendto; + + if (!netgame) + { + return false; + } + if (ev->data1 == KEY_LALT || ev->data2 == KEY_RALT) + { + altdown = (ev->type == ev_keydown); + return false; + } + if (ev->data1 == KEY_RSHIFT) + { + shiftdown = (ev->type == ev_keydown); + return false; + } + if (ev->type != ev_keydown) + { + return false; + } + if (!chatmodeon) + { + sendto = 0; + if (ev->data1 == key_multi_msg) + { + sendto = CT_PLR_ALL; + } + else if (ev->data1 == key_multi_msgplayer[0]) + { + sendto = CT_PLR_GREEN; + } + else if (ev->data1 == key_multi_msgplayer[1]) + { + sendto = CT_PLR_YELLOW; + } + else if (ev->data1 == key_multi_msgplayer[2]) + { + sendto = CT_PLR_RED; + } + else if (ev->data1 == key_multi_msgplayer[3]) + { + sendto = CT_PLR_BLUE; + } + if (sendto == 0 || (sendto != CT_PLR_ALL && !playeringame[sendto - 1]) + || sendto == consoleplayer + 1) + { + return false; + } + CT_queueChatChar(sendto); + chatmodeon = true; + I_StartTextInput(25, 10, SCREENWIDTH, 18); + return true; + } + else + { + if (altdown) + { + if (ev->data1 >= '0' && ev->data1 <= '9') + { + if (ev->data1 == '0') + { // macro 0 comes after macro 9 + ev->data1 = '9' + 1; + } + macro = chat_macros[ev->data1 - '1']; + CT_queueChatChar(KEY_ENTER); //send old message + CT_queueChatChar(chat_dest[consoleplayer]); // chose the dest. + while (*macro) + { + CT_queueChatChar(toupper(*macro++)); + } + CT_queueChatChar(KEY_ENTER); //send it off... + CT_Stop(); + return true; + } + } + if (ev->data1 == KEY_ENTER) + { + CT_queueChatChar(KEY_ENTER); + CT_Stop(); + return true; + } + else if (ev->data1 == KEY_ESCAPE) + { + CT_queueChatChar(CT_ESCAPE); + CT_Stop(); + return true; + } + else if (ev->data1 == KEY_BACKSPACE) + { + CT_queueChatChar(KEY_BACKSPACE); + return true; + } + else if (ValidChatChar(ev->data3)) + { + CT_queueChatChar(toupper(ev->data3)); + return true; + } + } + return false; +} + +//=========================================================================== +// +// CT_Ticker +// +//=========================================================================== + +void CT_Ticker(void) +{ + int i; + int j; + char c; + int numplayers; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + continue; + } + if ((c = players[i].cmd.chatchar) != 0) + { + if (c <= 5) + { + chat_dest[i] = c; + continue; + } + else if (c == CT_ESCAPE) + { + CT_ClearChatMessage(i); + } + else if (c == KEY_ENTER) + { + numplayers = 0; + for (j = 0; j < MAXPLAYERS; j++) + { + numplayers += playeringame[j]; + } + CT_AddChar(i, 0); // set the end of message character + if (numplayers > 2) + { + M_StringCopy(plr_lastmsg[i], DEH_String(CT_FromPlrText[i]), + sizeof(plr_lastmsg[i])); + M_StringConcat(plr_lastmsg[i], chat_msg[i], + sizeof(plr_lastmsg[i])); + } + else + { + M_StringCopy(plr_lastmsg[i], chat_msg[i], + sizeof(plr_lastmsg[i])); + } + if (i != consoleplayer && (chat_dest[i] == consoleplayer + 1 + || chat_dest[i] == CT_PLR_ALL) + && *chat_msg[i]) + { + P_SetMessage(&players[consoleplayer], plr_lastmsg[i], + true); + S_StartSound(NULL, sfx_chat); + } + else if (i == consoleplayer && (*chat_msg[i])) + { + if (numplayers > 1) + { + P_SetMessage(&players[consoleplayer], + DEH_String("-MESSAGE SENT-"), true); + S_StartSound(NULL, sfx_chat); + } + else + { + P_SetMessage(&players[consoleplayer], + DEH_String("THERE ARE NO OTHER PLAYERS IN THE GAME!"), + true); + S_StartSound(NULL, sfx_chat); + } + } + CT_ClearChatMessage(i); + } + else if (c == KEY_BACKSPACE) + { + CT_BackSpace(i); + } + else + { + CT_AddChar(i, c); + } + } + } + return; +} + +//=========================================================================== +// +// CT_Drawer +// +//=========================================================================== + +void CT_Drawer(void) +{ + int i; + int x; + patch_t *patch; + + if (chatmodeon) + { + x = 25; + for (i = 0; i < msgptr[consoleplayer]; i++) + { + if (chat_msg[consoleplayer][i] < 33) + { + x += 6; + } + else + { + patch = W_CacheLumpNum(FontABaseLump + + chat_msg[consoleplayer][i] - 33, + PU_CACHE); + V_DrawPatch(x, 10, patch); + x += patch->width; + } + } + V_DrawPatch(x, 10, W_CacheLumpName(DEH_String("FONTA59"), PU_CACHE)); + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } +} + +//=========================================================================== +// +// CT_queueChatChar +// +//=========================================================================== + +void CT_queueChatChar(char ch) +{ + if (((tail + 1) & (QUEUESIZE - 1)) == head) + { // the queue is full + return; + } + ChatQueue[tail] = ch; + tail = (tail + 1) & (QUEUESIZE - 1); +} + +//=========================================================================== +// +// CT_dequeueChatChar +// +//=========================================================================== + +char CT_dequeueChatChar(void) +{ + byte temp; + + if (head == tail) + { // queue is empty + return 0; + } + temp = ChatQueue[head]; + head = (head + 1) & (QUEUESIZE - 1); + return temp; +} + +//=========================================================================== +// +// CT_AddChar +// +//=========================================================================== + +void CT_AddChar(int player, char c) +{ + patch_t *patch; + + if (msgptr[player] + 1 >= MESSAGESIZE || msglen[player] >= MESSAGELEN) + { // full. + return; + } + chat_msg[player][msgptr[player]] = c; + msgptr[player]++; + if (c < 33) + { + msglen[player] += 6; + } + else + { + patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + msglen[player] += patch->width; + } +} + +//=========================================================================== +// +// CT_BackSpace +// +// Backs up a space, when the user hits (obviously) backspace +//=========================================================================== + +void CT_BackSpace(int player) +{ + patch_t *patch; + char c; + + if (msgptr[player] == 0) + { // message is already blank + return; + } + msgptr[player]--; + c = chat_msg[player][msgptr[player]]; + if (c < 33) + { + msglen[player] -= 6; + } + else + { + patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + msglen[player] -= patch->width; + } + chat_msg[player][msgptr[player]] = 0; +} + +//=========================================================================== +// +// CT_ClearChatMessage +// +// Clears out the data for the chat message, but the player's message +// is still saved in plrmsg. +//=========================================================================== + +void CT_ClearChatMessage(int player) +{ + memset(chat_msg[player], 0, MESSAGESIZE); + msgptr[player] = 0; + msglen[player] = 0; +} diff --git a/games/NXDoom/src/heretic/ct_chat.h b/games/NXDoom/src/heretic/ct_chat.h new file mode 100644 index 00000000000..75aaab2706b --- /dev/null +++ b/games/NXDoom/src/heretic/ct_chat.h @@ -0,0 +1,38 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Chat mode stuff +// + +#ifndef HERETIC_CT_CHAT_H +#define HERETIC_CT_CHAT_H + +#define CT_PLR_GREEN 1 +#define CT_PLR_YELLOW 2 +#define CT_PLR_RED 3 +#define CT_PLR_BLUE 4 +#define CT_PLR_ALL 5 + +#define CT_KEY_GREEN 'g' +#define CT_KEY_YELLOW 'y' +#define CT_KEY_RED 'r' +#define CT_KEY_BLUE 'b' +#define CT_KEY_ALL 't' + +extern char *chat_macros[10]; + +#endif /* #ifndef HERETIC_CT_CHAT_H */ + diff --git a/games/NXDoom/src/heretic/d_main.c b/games/NXDoom/src/heretic/d_main.c new file mode 100644 index 00000000000..9090df83af1 --- /dev/null +++ b/games/NXDoom/src/heretic/d_main.c @@ -0,0 +1,1171 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// D_main.c + +#include +#include + +#include "txt_main.h" +#include "txt_io.h" + +#include "net_client.h" + +#include "config.h" +#include "ct_chat.h" +#include "doomdef.h" +#include "deh_main.h" +#include "d_iwad.h" +#include "i_endoom.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_sound.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "s_sound.h" +#include "w_main.h" +#include "v_video.h" +#include "am_map.h" + +#include "heretic_icon.c" + +#define CT_KEY_GREEN 'g' +#define CT_KEY_YELLOW 'y' +#define CT_KEY_RED 'r' +#define CT_KEY_BLUE 'b' + +#define STARTUP_WINDOW_X 17 +#define STARTUP_WINDOW_Y 7 + +GameMode_t gamemode = indetermined; +const char *gamedescription = "unknown"; + +boolean nomonsters; // checkparm of -nomonsters +boolean respawnparm; // checkparm of -respawn +boolean debugmode; // checkparm of -debug +boolean ravpic; // checkparm of -ravpic +boolean cdrom; // true if cd-rom mode active +boolean noartiskip; // whether shift-enter skips an artifact + +skill_t startskill; +int startepisode; +int startmap; +int UpdateState; +static int graphical_startup = 1; +static boolean using_graphical_startup; +static boolean main_loop_started = false; +boolean autostart; + +boolean advancedemo; + +FILE *debugfile; + +static int show_endoom = 1; + +void D_ConnectNetGame(void); +void D_CheckNetGame(void); +void D_PageDrawer(void); +void D_AdvanceDemo(void); +boolean F_Responder(event_t * ev); + +//--------------------------------------------------------------------------- +// +// PROC D_ProcessEvents +// +// Send all the events of the given timestamp down the responder chain. +// +//--------------------------------------------------------------------------- + +void D_ProcessEvents(void) +{ + event_t *ev; + + while ((ev = D_PopEvent()) != NULL) + { + if (F_Responder(ev)) + { + continue; + } + if (MN_Responder(ev)) + { + continue; + } + G_Responder(ev); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawMessage +// +//--------------------------------------------------------------------------- + +void DrawMessage(void) +{ + player_t *player; + + player = &players[consoleplayer]; + if (player->messageTics <= 0 || !player->message) + { // No message + return; + } + MN_DrTextA(player->message, 160 - MN_TextAWidth(player->message) / 2, 1); +} + +//--------------------------------------------------------------------------- +// +// PROC D_Display +// +// Draw current display, possibly wiping it from the previous. +// +//--------------------------------------------------------------------------- + + +void D_Display(void) +{ + // Change the view size if needed + if (setsizeneeded) + { + R_ExecuteSetViewSize(); + } + +// +// do buffered drawing +// + switch (gamestate) + { + case GS_LEVEL: + if (!gametic) + break; + if (automapactive) + AM_Drawer(); + else + R_RenderPlayerView(&players[displayplayer]); + CT_Drawer(); + UpdateState |= I_FULLVIEW; + SB_Drawer(); + break; + case GS_INTERMISSION: + IN_Drawer(); + break; + case GS_FINALE: + F_Drawer(); + break; + case GS_DEMOSCREEN: + D_PageDrawer(); + break; + } + + if (testcontrols) + { + V_DrawMouseSpeedBox(testcontrols_mousespeed); + } + + if (paused && !MenuActive && !askforquit) + { + if (!netgame) + { + V_DrawPatch(160, viewwindowy + 5, W_CacheLumpName(DEH_String("PAUSED"), + PU_CACHE)); + } + else + { + V_DrawPatch(160, 70, W_CacheLumpName(DEH_String("PAUSED"), PU_CACHE)); + } + } + // Handle player messages + DrawMessage(); + + // Menu drawing + MN_Drawer(); + + // Send out any new accumulation + NetUpdate(); + + // Flush buffered stuff to screen + I_FinishUpdate(); +} + +// +// D_GrabMouseCallback +// +// Called to determine whether to grab the mouse pointer +// + +boolean D_GrabMouseCallback(void) +{ + // when menu is active or game is paused, release the mouse + + if (MenuActive || paused) + return false; + + // only grab mouse when playing levels (but not demos) + + return (gamestate == GS_LEVEL) && !demoplayback && !advancedemo; +} + +//--------------------------------------------------------------------------- +// +// PROC D_DoomLoop +// +//--------------------------------------------------------------------------- + +void D_DoomLoop(void) +{ + if (M_CheckParm("-debugfile")) + { + char filename[20]; + M_snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer); + debugfile = M_fopen(filename, "w"); + } + I_GraphicsCheckCommandLine(); + I_SetGrabMouseCallback(D_GrabMouseCallback); + I_RegisterWindowIcon(heretic_icon_data, heretic_icon_w, heretic_icon_h); + I_InitGraphics(); + + main_loop_started = true; + + while (1) + { + // Frame syncronous IO operations + I_StartFrame(); + + // Process one or more tics + // Will run at least one tic + TryRunTics(); + + // Move positional sounds + S_UpdateSounds(players[consoleplayer].mo); + D_Display(); + } +} + +/* +=============================================================================== + + DEMO LOOP + +=============================================================================== +*/ + +static int demosequence; +static int pagetic; +static const char *pagename; + + +/* +================ += += D_PageTicker += += Handles timing for warped projection += +================ +*/ + +void D_PageTicker(void) +{ + if (--pagetic < 0) + D_AdvanceDemo(); +} + + +/* +================ += += D_PageDrawer += +================ +*/ + +void D_PageDrawer(void) +{ + V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE)); + if (demosequence == 1) + { + V_DrawPatch(4, 160, W_CacheLumpName(DEH_String("ADVISOR"), PU_CACHE)); + } + UpdateState |= I_FULLSCRN; +} + +/* +================= += += D_AdvanceDemo += += Called after each demo or intro demosequence finishes +================= +*/ + +void D_AdvanceDemo(void) +{ + advancedemo = true; +} + +void D_DoAdvanceDemo(void) +{ + players[consoleplayer].playerstate = PST_LIVE; // don't reborn + advancedemo = false; + usergame = false; // can't save / end game here + paused = false; + gameaction = ga_nothing; + demosequence = (demosequence + 1) % 7; + switch (demosequence) + { + case 0: + pagetic = 210; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("TITLE"); + S_StartSong(mus_titl, false); + break; + case 1: + pagetic = 140; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("TITLE"); + break; + case 2: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo(DEH_String("demo1")); + break; + case 3: + pagetic = 200; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("CREDIT"); + break; + case 4: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo(DEH_String("demo2")); + break; + case 5: + pagetic = 200; + gamestate = GS_DEMOSCREEN; + if (gamemode == shareware) + { + pagename = DEH_String("ORDER"); + } + else + { + pagename = DEH_String("CREDIT"); + } + break; + case 6: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo(DEH_String("demo3")); + break; + } +} + + +/* +================= += += D_StartTitle += +================= +*/ + +void D_StartTitle(void) +{ + gameaction = ga_nothing; + demosequence = -1; + D_AdvanceDemo(); +} + + +/* +============== += += D_CheckRecordFrom += += -recordfrom +============== +*/ + +void D_CheckRecordFrom(void) +{ + int p; + char *filename; + + //! + // @vanilla + // @category demo + // @arg + // + // Load a game from the given savegame slot and record a demo from + // it. Equivalent to -loadgame -record . + + p = M_CheckParmWithArgs("-recordfrom", 2); + if (!p) + return; + + filename = SV_Filename(myargv[p + 1][0] - '0'); + G_LoadGame(filename); + G_DoLoadGame(); // load the gameskill etc info from savegame + + G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p + 2]); + D_DoomLoop(); // never returns + free(filename); +} + +/* +=============== += += D_AddFile += +=============== +*/ + +// MAPDIR should be defined as the directory that holds development maps +// for the -wart # # command + +#define MAPDIR "\\data\\" + +#define SHAREWAREWADNAME "heretic1.wad" + +char *iwadfile; + + +void wadprintf(void) +{ + if (debugmode) + { + return; + } +} + +boolean D_AddFile(char *file) +{ + wad_file_t *handle; + + printf(" adding %s\n", file); + + handle = W_AddFile(file); + + return handle != NULL; +} + +//========================================================== +// +// Startup Thermo code +// +//========================================================== +#define MSG_Y 9 +#define THERM_X 14 +#define THERM_Y 14 + +int thermMax; +int thermCurrent; +char smsg[80]; // status bar line + +// +// Heretic startup screen shit +// + +static int startup_line = STARTUP_WINDOW_Y; + +void hprintf(const char *string) +{ + if (using_graphical_startup) + { + TXT_BGColor(TXT_COLOR_CYAN, 0); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_GotoXY(STARTUP_WINDOW_X, startup_line); + ++startup_line; + TXT_Puts(string); + + TXT_UpdateScreen(); + } + + // haleyjd: shouldn't be WATCOMC-only + if (debugmode) + puts(string); +} + +void drawstatus(void) +{ + int i; + + TXT_GotoXY(1, 24); + TXT_BGColor(TXT_COLOR_BLUE, 0); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + for (i=0; smsg[i] != '\0'; ++i) + { + TXT_PutChar(smsg[i]); + } +} + +static void status(const char *string) +{ + if (using_graphical_startup) + { + M_StringConcat(smsg, string, sizeof(smsg)); + drawstatus(); + } +} + +void DrawThermo(void) +{ + static int last_progress = -1; + int progress; + int i; + + if (!using_graphical_startup) + { + return; + } + + // No progress? Don't update the screen. + + progress = (50 * thermCurrent) / thermMax + 2; + + if (last_progress == progress) + { + return; + } + + last_progress = progress; + + TXT_GotoXY(THERM_X, THERM_Y); + + TXT_FGColor(TXT_COLOR_BRIGHT_GREEN); + TXT_BGColor(TXT_COLOR_GREEN, 0); + + for (i = 0; i < progress; i++) + { + TXT_PutChar(0xdb); + } + + TXT_UpdateScreen(); +} + +void initStartup(void) +{ + byte *textScreen; + byte *loading; + + if (!graphical_startup || debugmode || testcontrols) + { + using_graphical_startup = false; + return; + } + + if (!TXT_Init()) + { + using_graphical_startup = false; + return; + } + + I_InitWindowTitle(); + I_InitWindowIcon(); + + // Blit main screen + textScreen = TXT_GetScreenData(); + loading = W_CacheLumpName(DEH_String("LOADING"), PU_CACHE); + memcpy(textScreen, loading, 4000); + + // Print version string + + TXT_BGColor(TXT_COLOR_RED, 0); + TXT_FGColor(TXT_COLOR_YELLOW); + TXT_GotoXY(46, 2); + TXT_Puts(HERETIC_VERSION_TEXT); + + TXT_UpdateScreen(); + + using_graphical_startup = true; +} + +static void finishStartup(void) +{ + if (using_graphical_startup) + { + TXT_Shutdown(); + } +} + +char tmsg[300]; +void tprintf(const char *msg, int initflag) +{ + printf("%s", msg); +} + +// haleyjd: moved up, removed WATCOMC code +void CleanExit(void) +{ + DEH_printf("Exited from HERETIC.\n"); + exit(1); +} + +void CheckAbortStartup(void) +{ + // haleyjd: removed WATCOMC + // haleyjd FIXME: this should actually work in text mode too, but how to + // get input before SDL video init? + if(using_graphical_startup) + { + if(TXT_GetChar() == 27) + CleanExit(); + } +} + +void IncThermo(void) +{ + thermCurrent++; + DrawThermo(); + CheckAbortStartup(); +} + +void InitThermo(int max) +{ + thermMax = max; + thermCurrent = 0; +} + +// +// Add configuration file variable bindings. +// + +void D_BindVariables(void) +{ + int i; + + M_ApplyPlatformDefaults(); + + I_BindInputVariables(); + I_BindVideoVariables(); + I_BindJoystickVariables(); + I_BindSoundVariables(); + + M_BindBaseControls(); + M_BindHereticControls(); + M_BindWeaponControls(); + M_BindChatControls(MAXPLAYERS); + + key_multi_msgplayer[0] = CT_KEY_GREEN; + key_multi_msgplayer[1] = CT_KEY_YELLOW; + key_multi_msgplayer[2] = CT_KEY_RED; + key_multi_msgplayer[3] = CT_KEY_BLUE; + + M_BindMenuControls(); + M_BindMapControls(); + + NET_BindVariables(); + + M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); + M_BindIntVariable("sfx_volume", &snd_MaxVolume); + M_BindIntVariable("music_volume", &snd_MusicVolume); + M_BindIntVariable("screenblocks", &screenblocks); + M_BindIntVariable("snd_channels", &snd_Channels); + M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); + M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); + M_BindIntVariable("show_endoom", &show_endoom); + M_BindIntVariable("graphical_startup", &graphical_startup); + + for (i=0; i<10; ++i) + { + char buf[12]; + + M_snprintf(buf, sizeof(buf), "chatmacro%i", i); + M_BindStringVariable(buf, &chat_macros[i]); + } +} + +// +// Called at exit to display the ENDOOM screen (ENDTEXT in Heretic) +// + +static void D_Endoom(void) +{ + byte *endoom_data; + + // Disable ENDOOM? + + if (!show_endoom || testcontrols || !main_loop_started) + { + return; + } + + endoom_data = W_CacheLumpName(DEH_String("ENDTEXT"), PU_STATIC); + + I_Endoom(endoom_data); +} + +//--------------------------------------------------------------------------- +// +// PROC D_DoomMain +// +//--------------------------------------------------------------------------- + +void D_DoomMain(void) +{ + GameMission_t gamemission; + int p; + char file[256]; + char demolumpname[9]; + + I_PrintBanner(PACKAGE_STRING); + + I_AtExit(D_Endoom, false); + + //! + // @category game + // @vanilla + // + // Disable monsters. + // + + nomonsters = M_ParmExists("-nomonsters"); + + //! + // @category game + // @vanilla + // + // Monsters respawn after being killed. + // + + respawnparm = M_ParmExists("-respawn"); + + //! + // @vanilla + // + // Take screenshots when F1 is pressed. + // + + ravpic = M_ParmExists("-ravpic"); + + //! + // @category obscure + // @vanilla + // + // Allow artifacts to be used when the run key is held down. + // + + noartiskip = M_ParmExists("-noartiskip"); + + debugmode = M_ParmExists("-debug"); + startskill = sk_medium; + startepisode = 1; + startmap = 1; + autostart = false; + +// +// get skill / episode / map from parms +// + + //! + // @vanilla + // @category net + // + // Start a deathmatch game. + // + + if (M_ParmExists("-deathmatch")) + { + deathmatch = true; + } + + //! + // @category game + // @arg + // @vanilla + // + // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of + // 0 disables all monsters. + // + + p = M_CheckParmWithArgs("-skill", 1); + if (p) + { + startskill = myargv[p + 1][0] - '1'; + autostart = true; + } + + //! + // @category game + // @arg + // @vanilla + // + // Start playing episode n (1-4). + // + + p = M_CheckParmWithArgs("-episode", 1); + if (p) + { + startepisode = myargv[p + 1][0] - '0'; + startmap = 1; + autostart = true; + } + + //! + // @category game + // @arg + // @vanilla + // + // Start a game immediately, warping to level ExMy. + // + + p = M_CheckParmWithArgs("-warp", 2); + if (p && p < myargc - 2) + { + startepisode = myargv[p + 1][0] - '0'; + startmap = myargv[p + 2][0] - '0'; + autostart = true; + } + +// +// init subsystems +// + DEH_printf("V_Init: allocate screens.\n"); + V_Init(); + + // Check for -CDROM + + cdrom = false; + +#ifdef _WIN32 + + //! + // @category obscure + // @platform windows + // @vanilla + // + // Save configuration data and savegames in c:\heretic.cd, + // allowing play from CD. + // + + if (M_CheckParm("-cdrom")) + { + cdrom = true; + } +#endif + + if (cdrom) + { + M_SetConfigDir(DEH_String("c:\\heretic.cd")); + } + else + { + M_SetConfigDir(NULL); + } + + // Load defaults before initing other systems + DEH_printf("M_LoadDefaults: Load system defaults.\n"); + D_BindVariables(); + M_SetConfigFilenames("heretic.cfg", PROGRAM_PREFIX "heretic.cfg"); + M_LoadDefaults(); + + I_AtExit(M_SaveDefaults, false); + + DEH_printf("Z_Init: Init zone memory allocation daemon.\n"); + Z_Init(); + + DEH_printf("W_Init: Init WADfiles.\n"); + + iwadfile = D_FindIWAD(IWAD_MASK_HERETIC, &gamemission); + + if (iwadfile == NULL) + { + I_Error("Game mode indeterminate. No IWAD was found. Try specifying\n" + "one with the '-iwad' command line parameter."); + } + + D_AddFile(iwadfile); + W_CheckCorrectIWAD(heretic); + + //! + // @category mod + // + // Disable auto-loading of .wad files. + // + if (!M_ParmExists("-noautoload")) + { + char *autoload_dir; + autoload_dir = M_GetAutoloadDir("heretic.wad"); + if (autoload_dir != NULL) + { + DEH_AutoLoadPatches(autoload_dir); + W_AutoLoadWADs(autoload_dir); + free(autoload_dir); + } + } + + // Load dehacked patches specified on the command line. + DEH_ParseCommandLine(); + + // Load PWAD files. + W_ParseCommandLine(); + + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp. + // + + p = M_CheckParmWithArgs("-playdemo", 1); + if (!p) + { + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp, determining the framerate + // of the screen. + // + + p = M_CheckParmWithArgs("-timedemo", 1); + } + + if (p) + { + char *uc_filename = strdup(myargv[p + 1]); + M_ForceUppercase(uc_filename); + + // In Vanilla, the filename must be specified without .lmp, + // but make that optional. + if (M_StringEndsWith(uc_filename, ".LMP")) + { + M_StringCopy(file, myargv[p + 1], sizeof(file)); + } + else + { + DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p + 1]); + } + + free(uc_filename); + + if (D_AddFile(file)) + { + M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, + sizeof(demolumpname)); + } + else + { + // The file failed to load, but copy the original arg as a + // demo name to make tricks like -playdemo demo1 possible. + M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); + } + + printf("Playing demo %s.\n", file); + } + + // Generate the WAD hash table. Speed things up a bit. + W_GenerateHashTable(); + + //! + // @category demo + // + // Record or playback a demo without automatically quitting + // after either level exit or player respawn. + // + + demoextend = M_ParmExists("-demoextend"); + + if (W_CheckNumForName(DEH_String("E2M1")) == -1) + { + gamemode = shareware; + gamedescription = "Heretic (shareware)"; + } + else if (W_CheckNumForName("EXTENDED") != -1) + { + // Presence of the EXTENDED lump indicates the retail version + + gamemode = retail; + gamedescription = "Heretic: Shadow of the Serpent Riders"; + } + else + { + gamemode = registered; + gamedescription = "Heretic (registered)"; + } + + I_SetWindowTitle(gamedescription); + + savegamedir = M_GetSaveGameDir("heretic.wad"); + + I_PrintStartupBanner(gamedescription); + + if (M_ParmExists("-testcontrols")) + { + startepisode = 1; + startmap = 1; + autostart = true; + testcontrols = true; + } + + I_InitTimer(); + I_InitSound(heretic); + I_InitMusic(); + + tprintf("NET_Init: Init network subsystem.\n", 1); + NET_Init (); + + D_ConnectNetGame(); + + // haleyjd: removed WATCOMC + initStartup(); + + // + // Build status bar line! + // + smsg[0] = 0; + if (deathmatch) + status(DEH_String("DeathMatch...")); + if (nomonsters) + status(DEH_String("No Monsters...")); + if (respawnparm) + status(DEH_String("Respawning...")); + if (autostart) + { + char temp[64]; + DEH_snprintf(temp, sizeof(temp), + "Warp to Episode %d, Map %d, Skill %d ", + startepisode, startmap, startskill + 1); + status(temp); + } + wadprintf(); // print the added wadfiles + + tprintf(DEH_String("MN_Init: Init menu system.\n"), 1); + MN_Init(); + + CT_Init(); + + tprintf(DEH_String("R_Init: Init Heretic refresh daemon."), 1); + hprintf(DEH_String("Loading graphics")); + R_Init(); + tprintf("\n", 0); + + tprintf(DEH_String("P_Init: Init Playloop state.\n"), 1); + hprintf(DEH_String("Init game engine.")); + P_Init(); + IncThermo(); + + tprintf(DEH_String("I_Init: Setting up machine state.\n"), 1); + I_CheckIsScreensaver(); + I_InitJoystick(); + IncThermo(); + + tprintf(DEH_String("S_Init: Setting up sound.\n"), 1); + S_Init(); + //IO_StartupTimer(); + S_Start(); + + tprintf(DEH_String("D_CheckNetGame: Checking network game status.\n"), 1); + hprintf(DEH_String("Checking network game status.")); + D_CheckNetGame(); + IncThermo(); + + // haleyjd: removed WATCOMC + + tprintf(DEH_String("SB_Init: Loading patches.\n"), 1); + SB_Init(); + IncThermo(); + +// +// start the appropriate game based on params +// + + D_CheckRecordFrom(); + + //! + // @arg + // @category demo + // @vanilla + // + // Record a demo named x.lmp. + // + + p = M_CheckParmWithArgs("-record", 1); + if (p) + { + G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p + 1]); + D_DoomLoop(); // Never returns + } + + p = M_CheckParmWithArgs("-playdemo", 1); + if (p) + { + singledemo = true; // Quit after one demo + G_DeferedPlayDemo(demolumpname); + D_DoomLoop(); // Never returns + } + + p = M_CheckParmWithArgs("-timedemo", 1); + if (p) + { + G_TimeDemo(demolumpname); + D_DoomLoop(); // Never returns + } + + //! + // @category game + // @arg + // @vanilla + // + // Load the game in savegame slot s. + // + + p = M_CheckParmWithArgs("-loadgame", 1); + if (p && p < myargc - 1) + { + char *filename; + + filename = SV_Filename(myargv[p + 1][0] - '0'); + G_LoadGame(filename); + free(filename); + } + + // Check valid episode and map + if (autostart || netgame) + { + if (!D_ValidEpisodeMap(heretic, gamemode, startepisode, startmap)) + { + startepisode = 1; + startmap = 1; + } + } + + if (gameaction != ga_loadgame) + { + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; + if (autostart || netgame) + { + G_InitNew(startskill, startepisode, startmap); + } + else + { + D_StartTitle(); + } + } + + finishStartup(); + + D_DoomLoop(); // Never returns +} diff --git a/games/NXDoom/src/heretic/d_net.c b/games/NXDoom/src/heretic/d_net.c new file mode 100644 index 00000000000..8aef319fed5 --- /dev/null +++ b/games/NXDoom/src/heretic/d_net.c @@ -0,0 +1,218 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM Network game communication and protocol, +// all OS independend parts. +// + +#include + +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "doomdef.h" +#include "m_argv.h" +#include "m_misc.h" +#include "w_checksum.h" + +#include "deh_main.h" + +#include "d_loop.h" + +ticcmd_t *netcmds; + + +// Called when a player leaves the game + +static void PlayerQuitGame(player_t *player) +{ + static char exitmsg[80]; + unsigned int player_num; + + player_num = player - players; + + // Note: + // The Heretic source code does this, which doesn't actually work. + // As a result, the exit message is never seen. + + M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg)); + exitmsg[7] += player_num; + players[consoleplayer].message = exitmsg; + + playeringame[player_num] = false; + players[consoleplayer].message = exitmsg; + + // TODO: check if it is sensible to do this: + + if (demorecording) + { + G_CheckDemoStatus (); + } +} + +static void RunTic(ticcmd_t *cmds, boolean *ingame) +{ + unsigned int i; + + // Check for player quits. + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!demoplayback && playeringame[i] && !ingame[i]) + { + PlayerQuitGame(&players[i]); + } + } + + netcmds = cmds; + + // check that there are players in the game. if not, we cannot + // run a tic. + + if (advancedemo) + D_DoAdvanceDemo (); + + G_Ticker (); +} + +static loop_interface_t doom_loop_interface = { + D_ProcessEvents, + G_BuildTiccmd, + RunTic, + MN_Ticker +}; + + +// Load game settings from the specified structure and +// set global variables. + +static void LoadGameSettings(net_gamesettings_t *settings) +{ + unsigned int i; + + deathmatch = settings->deathmatch; + ticdup = settings->ticdup; + startepisode = settings->episode; + startmap = settings->map; + startskill = settings->skill; + // TODO startloadgame = settings->loadgame; + lowres_turn = settings->lowres_turn; + nomonsters = settings->nomonsters; + respawnparm = settings->respawn_monsters; + consoleplayer = settings->consoleplayer; + + if (lowres_turn) + { + printf("NOTE: Turning resolution is reduced; this is probably " + "because there is a client recording a Vanilla demo.\n"); + } + + for (i = 0; i < MAXPLAYERS; ++i) + { + playeringame[i] = i < settings->num_players; + } +} + +// Save the game settings from global variables to the specified +// game settings structure. + +static void SaveGameSettings(net_gamesettings_t *settings) +{ + // Fill in game settings structure with appropriate parameters + // for the new game + + settings->deathmatch = deathmatch; + settings->episode = startepisode; + settings->map = startmap; + settings->skill = startskill; + // TODO settings->loadgame = startloadgame; + settings->gameversion = exe_heretic_1_3; + settings->nomonsters = nomonsters; + settings->respawn_monsters = respawnparm; + settings->timelimit = 0; + + settings->lowres_turn = M_ParmExists("-record") + && !M_ParmExists("-longtics"); +} + +static void InitConnectData(net_connect_data_t *connect_data) +{ + connect_data->drone = false; + connect_data->max_players = MAXPLAYERS; + + // + // Connect data + // + + // Game type fields: + + connect_data->gamemode = gamemode; + connect_data->gamemission = heretic; + + // Are we recording a demo? Possibly set lowres turn mode + + connect_data->lowres_turn = M_ParmExists("-record") + && !M_ParmExists("-longtics"); + + // Read checksums of our WAD directory and dehacked information + + W_Checksum(connect_data->wad_sha1sum); + DEH_Checksum(connect_data->deh_sha1sum); + + connect_data->is_freedoom = 0; +} + +void D_ConnectNetGame(void) +{ + net_connect_data_t connect_data; + + InitConnectData(&connect_data); + netgame = D_InitNetGame(&connect_data); + + //! + // @category net + // + // Start the game playing as though in a netgame with a single + // player. This can also be used to play back single player netgame + // demos. + // + + if (M_CheckParm("-solo-net") > 0) + { + netgame = true; + } +} + +// +// D_CheckNetGame +// Works out player numbers among the net participants +// + +void D_CheckNetGame (void) +{ + net_gamesettings_t settings; + + D_RegisterLoopCallbacks(&doom_loop_interface); + + if (netgame) + { + autostart = true; + } + + SaveGameSettings(&settings); + D_StartNetGame(&settings, NULL); + LoadGameSettings(&settings); +} + diff --git a/games/NXDoom/src/heretic/deh_ammo.c b/games/NXDoom/src/heretic/deh_ammo.c new file mode 100644 index 00000000000..39384d75d59 --- /dev/null +++ b/games/NXDoom/src/heretic/deh_ammo.c @@ -0,0 +1,113 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Ammo" sections in dehacked files +// + +#include +#include +#include + +#include "doomdef.h" +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "p_local.h" + +static void *DEH_AmmoStart(deh_context_t *context, char *line) +{ + int ammo_number = 0; + + if (sscanf(line, "Ammo %i", &ammo_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (ammo_number < 0 || ammo_number >= NUMAMMO) + { + DEH_Warning(context, "Invalid ammo number: %i", ammo_number); + return NULL; + } + + return &maxammo[ammo_number]; +} + +static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + int ivalue; + int ammo_number; + + if (tag == NULL) + return; + + ammo_number = ((int *) tag) - maxammo; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + if (!strcasecmp(variable_name, "Per ammo")) + { + // Heretic doesn't have a "per clip" ammo array, instead + // it is per weapon. However, the weapon number lines + // up with the ammo number if we add one. + + GetWeaponAmmo[ammo_number + 1] = ivalue; + } + else if (!strcasecmp(variable_name, "Max ammo")) + { + maxammo[ammo_number] = ivalue; + } + else + { + DEH_Warning(context, "Field named '%s' not found", variable_name); + } +} + +static void DEH_AmmoSHA1Hash(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "info.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "deh_mapping.h" +#include "deh_htic.h" + +#include "p_action.h" + +typedef struct +{ + int offsets[deh_hhe_num_versions]; + void (*func)(struct mobj_s *, struct player_s *, struct pspdef_s *); +} hhe_action_pointer_t; + +// Offsets of action pointers within the Heretic executables. +// Different versions have different offsets. +// (Seriously Greg, was this really necessary? What was wrong with the +// "copying action pointer from another frame" technique used in dehacked?) + +// Offset Action function +// v1.0 v1.2 v1.3 + +static const hhe_action_pointer_t action_pointers[] = +{ + { { 77680, 80144, 80208 }, A_AccTeleGlitter }, + { { 78608, 81104, 81168 }, A_AddPlayerCorpse }, + { { 115808, 118000, 118240 }, A_AddPlayerRain }, + { { 112272, 114480, 114720 }, A_BeakAttackPL1 }, + { { 112448, 114656, 114896 }, A_BeakAttackPL2 }, + { { 111856, 114176, 114416 }, A_BeakRaise }, + { { 111568, 113888, 114128 }, A_BeakReady }, + { { 74640, 77120, 77184 }, A_BeastAttack }, + { { 70480, 72992, 73056 }, A_BeastPuff }, + { { 73120, 75600, 75664 }, A_BlueSpark }, + { { 115456, 117648, 117888 }, A_BoltSpark }, + { { 77344, 79808, 79872 }, A_BossDeath }, + { { 69328, 71856, 71920 }, A_Chase }, + { { 0, 80976, 81040 }, A_CheckBurnGone }, + { { 78480, 80944, 81008 }, A_CheckSkullDone }, + { { 78448, 80912, 80976 }, A_CheckSkullFloor }, + { { 71376, 73888, 73952 }, A_ChicAttack }, + { { 71488, 74000, 74064 }, A_ChicChase }, + { { 71456, 73968, 74032 }, A_ChicLook }, + { { 71520, 74032, 74096 }, A_ChicPain }, + { { 75792, 78208, 78272 }, A_ClinkAttack }, + { { 108432, 110816, 111056 }, A_ContMobjSound }, + { { 114752, 116944, 117184 }, A_DeathBallImpact }, + { { 70016, 72528, 72592 }, A_DripBlood }, + { { 77472, 79936, 80000 }, A_ESound }, + { { 76784, 79248, 79312 }, A_Explode }, + { { 69872, 72400, 72464 }, A_FaceTarget }, + { { 71568, 74080, 74144 }, A_Feathers }, + { { 112928, 115136, 115376 }, A_FireBlasterPL1 }, + { { 113072, 115280, 115520 }, A_FireBlasterPL2 }, + { { 115232, 117424, 117664 }, A_FireCrossbowPL1 }, + { { 115312, 117504, 117744 }, A_FireCrossbowPL2 }, + { { 113152, 115360, 115600 }, A_FireGoldWandPL1 }, + { { 113296, 115504, 115744 }, A_FireGoldWandPL2 }, + { { 113760, 115968, 116208 }, A_FireMacePL1 }, + { { 114624, 116816, 117056 }, A_FireMacePL2 }, + { { 116368, 118544, 118784 }, A_FirePhoenixPL1 }, + { { 116736, 118896, 119136 }, A_FirePhoenixPL2 }, + { { 115568, 117760, 118000 }, A_FireSkullRodPL1 }, + { { 115648, 117840, 118080 }, A_FireSkullRodPL2 }, + { { 117120, 119280, 119520 }, A_FlameEnd }, + { { 78704, 81200, 81264 }, A_FlameSnd }, + { { 117152, 119312, 119552 }, A_FloatPuff }, + { { 78512, 81008, 81072 }, A_FreeTargMobj }, + { { 117184, 119344, 119584 }, A_GauntletAttack }, + { { 73232, 75712, 75776 }, A_GenWizard }, + { { 75872, 78304, 78368 }, A_GhostOff }, + { { 74752, 77232, 77296 }, A_HeadAttack }, + { { 75488, 77984, 78048 }, A_HeadFireGrow }, + { { 75328, 77824, 77888 }, A_HeadIceImpact }, + { { 116336, 118512, 118752 }, A_HideInCeiling }, + { { 78736, 81232, 81296 }, A_HideThing }, + { { 70976, 73488, 73552 }, A_ImpDeath }, + { { 70304, 72816, 72880 }, A_ImpExplode }, + { { 70592, 73104, 73168 }, A_ImpMeAttack }, + { { 70672, 73184, 73248 }, A_ImpMsAttack }, + { { 70880, 73392, 73456 }, A_ImpMsAttack2 }, + { { 71024, 73536, 73600 }, A_ImpXDeath1 }, + { { 71072, 73584, 73648 }, A_ImpXDeath2 }, + { { 77728, 80192, 80256 }, A_InitKeyGizmo }, + { { 116720, 118880, 119120 }, A_InitPhoenixPL2 }, + { { 70160, 72672, 72736 }, A_KnightAttack }, + { { 117648, 119824, 120064 }, A_Light0 }, + { { 69200, 71728, 71792 }, A_Look }, + { { 111760, 114080, 114320 }, A_Lower }, + { { 114032, 116224, 116464 }, A_MaceBallImpact }, + { { 114192, 116384, 116624 }, A_MaceBallImpact2 }, + { { 113904, 116112, 116352 }, A_MacePL1Check }, + { { 77104, 79568, 79632 }, A_MakePod }, + { { 73648, 76128, 76192 }, A_MinotaurAtk1 }, + { { 74112, 76592, 76656 }, A_MinotaurAtk2 }, + { { 74352, 76832, 76896 }, A_MinotaurAtk3 }, + { { 74032, 76512, 76576 }, A_MinotaurCharge }, + { { 73760, 76240, 76304 }, A_MinotaurDecide }, + { { 74528, 77008, 77072 }, A_MntrFloorFire }, + { { 71808, 74288, 74352 }, A_MummyAttack }, + { { 71920, 74400, 74464 }, A_MummyAttack2 }, + { { 72016, 74496, 74560 }, A_MummyFX1Seek }, + { { 72048, 74528, 74592 }, A_MummySoul }, + { { 76400, 78832, 78896 }, A_NoBlocking }, + { { 69984, 72496, 72560 }, A_Pain }, + { { 116496, 118656, 118896 }, A_PhoenixPuff }, + { { 76896, 79360, 79424 }, A_PodPain }, + { { 116272, 118448, 118688 }, A_RainImpact }, + { { 111920, 114240, 114480 }, A_Raise }, + { { 111696, 114016, 114256 }, A_ReFire }, + { { 77056, 79520, 79584 }, A_RemovePod }, + { { 116480, 0, 0 }, A_RemovedPhoenixFunc }, + { { 81952, 84464, 84528 }, A_RestoreArtifact }, + { { 82048, 84544, 84608 }, A_RestoreSpecialThing1 }, + { { 82128, 84592, 84656 }, A_RestoreSpecialThing2 }, + { { 76144, 78576, 78640 }, A_Scream }, + { { 117104, 119264, 119504 }, A_ShutdownPhoenixPL2 }, + { { 78288, 80752, 80816 }, A_SkullPop }, + { { 115776, 117968, 118208 }, A_SkullRodPL2Seek }, + { { 115984, 118176, 118416 }, A_SkullRodStorm }, + { { 75632, 78048, 78112 }, A_SnakeAttack }, + { { 75712, 78128, 78192 }, A_SnakeAttack2 }, + { { 72144, 74624, 74688 }, A_Sor1Chase }, + { { 72096, 74576, 74640 }, A_Sor1Pain }, + { { 73392, 75872, 75936 }, A_Sor2DthInit }, + { { 73424, 75904, 75968 }, A_Sor2DthLoop }, + { { 73584, 76064, 76128 }, A_SorDBon }, + { { 73552, 76032, 76096 }, A_SorDExp }, + { { 73520, 76000, 76064 }, A_SorDSph }, + { { 73488, 75968, 76032 }, A_SorRise }, + { { 73616, 76096, 76160 }, A_SorSightSnd }, + { { 73456, 75936, 76000 }, A_SorZap }, + { { 72480, 74960, 75024 }, A_SorcererRise }, + { { 115088, 117280, 117520 }, A_SpawnRippers }, + { { 77520, 79984, 80048 }, A_SpawnTeleGlitter }, + { { 77600, 80064, 80128 }, A_SpawnTeleGlitter2 }, + { { 72192, 74672, 74736 }, A_Srcr1Attack }, + { { 72896, 75376, 75440 }, A_Srcr2Attack }, + { { 72816, 75296, 75360 }, A_Srcr2Decide }, + { { 112640, 114848, 115088 }, A_StaffAttackPL1 }, + { { 112784, 114992, 115232 }, A_StaffAttackPL2 }, + { { 78752, 81248, 81312 }, A_UnHideThing }, + { { 78080, 80544, 80608 }, A_VolcBallImpact }, + { { 77856, 80320, 80384 }, A_VolcanoBlast }, + { { 77824, 80288, 80352 }, A_VolcanoSet }, + { { 111168, 113488, 113728 }, A_WeaponReady }, + { { 75168, 77664, 77728 }, A_WhirlwindSeek }, + { { 75888, 78320, 78384 }, A_WizAtk1 }, + { { 75920, 78352, 78416 }, A_WizAtk2 }, + { { 75952, 78384, 78448 }, A_WizAtk3 }, +}; + +DEH_BEGIN_MAPPING(state_mapping, state_t) + DEH_MAPPING("Sprite number", sprite) + DEH_MAPPING("Sprite subnumber", frame) + DEH_MAPPING("Duration", tics) + DEH_MAPPING("Next frame", nextstate) + DEH_MAPPING("Unknown 1", misc1) + DEH_MAPPING("Unknown 2", misc2) +DEH_END_MAPPING + +static void DEH_FrameInit(void) +{ + // Bit of a hack here: + DEH_HereticInit(); +} + +static void *DEH_FrameStart(deh_context_t *context, char *line) +{ + int frame_number = 0; + int mapped_frame_number; + state_t *state; + + if (sscanf(line, "Frame %i", &frame_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + // Map the HHE frame number (which assumes a Heretic 1.0 state table) + // to the internal frame number (which is is the Heretic 1.3 state table): + + mapped_frame_number = DEH_MapHereticFrameNumber(frame_number); + + if (mapped_frame_number < 0 || mapped_frame_number >= DEH_HERETIC_NUMSTATES) + { + DEH_Warning(context, "Invalid frame number: %i", frame_number); + return NULL; + } + + state = &states[mapped_frame_number]; + + return state; +} + +static boolean GetActionPointerForOffset(int offset, void (**result)(struct mobj_s *, struct player_s *, struct pspdef_s *)) +{ + int i; + + // Special case. + + if (offset == 0) + { + *result = NULL; + return true; + } + + for (i=0; iaction = func; + } + else + { + // "Next frame" numbers need to undergo mapping. + + if (!strcasecmp(variable_name, "Next frame")) + { + ivalue = DEH_MapHereticFrameNumber(ivalue); + } + + DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); + } +} + +static void DEH_FrameSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include +#include + +#include "doomtype.h" +#include "dstrings.h" + +#include "z_zone.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_htic.h" +#include "deh_main.h" + +// +// Ok, Greg, the action pointers thing was bad enough, but this really +// takes the biscuit. Why does HHE's text replacement address strings +// by offset??!! The dehacked way was much nicer, why change it? +// + +typedef struct +{ + unsigned int offsets[deh_hhe_num_versions]; + const char *string; +} hhe_string_t; + +// Offsets String +// v1.0 v1.2 v1.3 + +static const hhe_string_t strings[] = +{ + { { 228, 228, 228 }, "PLAYPAL" }, + { { 1240, 1252, 1252 }, "E1M1: THE DOCKS" }, + { { 1260, 1272, 1272 }, "E1M2: THE DUNGEONS" }, + { { 1280, 1292, 1292 }, "E1M3: THE GATEHOUSE" }, + { { 1304, 1316, 1316 }, "E1M4: THE GUARD TOWER" }, + { { 1328, 1340, 1340 }, "E1M5: THE CITADEL" }, + { { 1348, 1360, 1360 }, "E1M6: THE CATHEDRAL" }, + { { 1372, 1384, 1384 }, "E1M7: THE CRYPTS" }, + { { 1392, 1404, 1404 }, "E1M8: HELL'S MAW" }, + { { 1412, 1424, 1424 }, "E1M9: THE GRAVEYARD" }, + { { 1436, 1448, 1448 }, "E2M1: THE CRATER" }, + { { 1456, 1468, 1468 }, "E2M2: THE LAVA PITS" }, + { { 1480, 1492, 1492 }, "E2M3: THE RIVER OF FIRE" }, + { { 1508, 1520, 1520 }, "E2M4: THE ICE GROTTO" }, + { { 1532, 1544, 1544 }, "E2M5: THE CATACOMBS" }, + { { 1556, 1568, 1568 }, "E2M6: THE LABYRINTH" }, + { { 1580, 1592, 1592 }, "E2M7: THE GREAT HALL" }, + { { 1604, 1616, 1616 }, "E2M8: THE PORTALS OF CHAOS" }, + { { 1632, 1644, 1644 }, "E2M9: THE GLACIER" }, + { { 1652, 1664, 1664 }, "E3M1: THE STOREHOUSE" }, + { { 1676, 1688, 1688 }, "E3M2: THE CESSPOOL" }, + { { 1696, 1708, 1708 }, "E3M3: THE CONFLUENCE" }, + { { 1720, 1732, 1732 }, "E3M4: THE AZURE FORTRESS" }, + { { 1748, 1760, 1760 }, "E3M5: THE OPHIDIAN LAIR" }, + { { 1776, 1788, 1788 }, "E3M6: THE HALLS OF FEAR" }, + { { 1804, 1816, 1816 }, "E3M7: THE CHASM" }, + { { 1824, 1836, 1836 }, "E3M8: D'SPARIL'S KEEP" }, + { { 1848, 1860, 1860 }, "E3M9: THE AQUIFER" }, + { { 0, 1880, 1880 }, "E4M1: CATAFALQUE" }, + { { 0, 1900, 1900 }, "E4M2: BLOCKHOUSE" }, + { { 0, 1920, 1920 }, "E4M3: AMBULATORY" }, + { { 0, 1940, 1940 }, "E4M4: SEPULCHER" }, + { { 0, 1960, 1960 }, "E4M5: GREAT STAIR" }, + { { 0, 1980, 1980 }, "E4M6: HALLS OF THE APOSTATE" }, + { { 0, 2012, 2012 }, "E4M7: RAMPARTS OF PERDITION" }, + { { 0, 2044, 2044 }, "E4M8: SHATTERED BRIDGE" }, + { { 0, 2068, 2068 }, "E4M9: MAUSOLEUM" }, + { { 0, 2088, 2088 }, "E5M1: OCHRE CLIFFS" }, + { { 0, 2108, 2108 }, "E5M2: RAPIDS" }, + { { 0, 2124, 2124 }, "E5M3: QUAY" }, + { { 0, 2136, 2136 }, "E5M4: COURTYARD" }, + { { 0, 2156, 2156 }, "E5M5: HYDRATYR" }, + { { 0, 2172, 2172 }, "E5M6: COLONNADE" }, + { { 0, 2192, 2192 }, "E5M7: FOETID MANSE" }, + { { 0, 2212, 2212 }, "E5M8: FIELD OF JUDGEMENT" }, + { { 0, 2240, 2240 }, "E5M9: SKEIN OF D'SPARIL" }, + { { 1868, 2268, 2268 }, "AUTOPAGE" }, + { { 1880, 2280, 2280 }, "FOLLOW MODE ON" }, + { { 1896, 2296, 2296 }, "FOLLOW MODE OFF" }, + { { 1924, 2324, 2324 }, "GREEN: " }, + { { 1936, 2336, 2336 }, "YELLOW: " }, + { { 1948, 2348, 2348 }, "RED: " }, + { { 1956, 2356, 2356 }, "BLUE: " }, + { { 1964, 2364, 2364 }, "FONTA_S" }, + { { 1972, 2372, 2372 }, "-MESSAGE SENT-" }, + { { 1988, 2388, 2388 }, "THERE ARE NO OTHER PLAYERS IN THE GAME!" }, + { { 2028, 2428, 2428 }, "FONTA59" }, + { { 2036, 2504, 2504 }, "PAUSED" }, + { { 2072, 2540, 2540 }, "ADVISOR" }, + { { 2080, 2548, 2548 }, "TITLE" }, + { { 2088, 2556, 2556 }, "demo1" }, + { { 2096, 2564, 2564 }, "CREDIT" }, + { { 2104, 2572, 2572 }, "demo2" }, + { { 2112, 2580, 2580 }, "ORDER" }, + { { 2120, 2588, 2588 }, "demo3" }, + { { 2304, 2696, 2696 }, "Exited from HERETIC.\n" }, + { { 2412, 2800, 2800 }, "c:\\heretic.cd" }, + { { 2528, 2916, 2916 }, "Playing demo %s.lmp.\n" }, + { { 2592, 2980, 2980 }, "V_Init: allocate screens.\n" }, + { { 2620, 3008, 3008 }, "M_LoadDefaults: Load system defaults.\n" }, + { { 2660, 3048, 3048 }, "Z_Init: Init zone memory allocation daemon.\n" }, + { { 2708, 3096, 3096 }, "W_Init: Init WADfiles.\n" }, + { { 2732, 3120, 3120 }, "E2M1" }, + { { 0, 3128, 3128 }, "EXTENDED" }, + { { 2740, 3140, 3140 }, "LOADING" }, + { { 2748, 3148, 3148 }, "DeathMatch..." }, + { { 2764, 3164, 3164 }, "No Monsters..." }, + { { 2780, 3180, 3180 }, "Respawning..." }, + { { 2796, 3196, 3196 }, "Warp to Episode %d, Map %d, Skill %d " }, + { { 2836, 3236, 3236 }, "MN_Init: Init menu system.\n" }, + { { 2864, 3264, 3264 }, "R_Init: Init Heretic refresh daemon." }, + { { 2904, 3304, 3304 }, "Loading graphics" }, + { { 2924, 3324, 3324 }, "P_Init: Init Playloop state." }, + { { 2956, 3356, 3356 }, "Init game engine." }, + { { 2976, 3376, 3376 }, "I_Init: Setting up machine state.\n" }, + { { 3012, 3412, 3412 }, "D_CheckNetGame: Checking network game status.\n" }, + { { 3060, 3460, 3460 }, "Checking network game status." }, + { { 3092, 3492, 3492 }, "SB_Init: Loading patches.\n" }, + { { 0, 3752, 3752 }, "PLAYER 1 LEFT THE GAME" }, + { { 3508, 3932, 3932 }, "Network game synchronization aborted." }, + { { 0, 3972, 3972 }, "Different DOOM versions cannot play a net game!" }, + { { 3908, 4132, 4132 }, "SKY1" }, + { { 3916, 4140, 4140 }, "SKY2" }, + { { 3924, 4148, 4148 }, "SKY3" }, + { { 3736, 4196, 4196 }, "NET GAME" }, + { { 3748, 4208, 4208 }, "SAVE GAME" }, + { { 3760, 4220, 4220 }, "Only %i deathmatch spots, 4 required" }, + { { 3800, 4260, 4260 }, "version %i" }, + { { 3828, 4372, 4372 }, "c:\\heretic.cd\\hticsav%d.hsg" }, + { { 3856, 4400, 4400 }, "hticsav%d.hsg" }, + { { 3896, 4416, 4416 }, "GAME SAVED" }, + { { 4016, 4456, 4456 }, E1TEXT }, + { { 4536, 4976, 4976 }, E2TEXT }, + { { 5068, 5508, 5508 }, E3TEXT }, + { { 0, 6072, 6072 }, E4TEXT }, + { { 0, 6780, 6780 }, E5TEXT }, + { { 5632, 7468, 7468 }, "FLOOR25" }, + { { 5640, 7476, 7476 }, "FLATHUH1" }, + { { 5652, 7488, 7488 }, "FLTWAWA2" }, + { { 0, 7500, 7500 }, "FLOOR28" }, + { { 0, 7508, 7508 }, "FLOOR08" }, + { { 5664, 7516, 7516 }, "FONTA_S" }, + { { 5704, 7524, 7524 }, "PLAYPAL" }, + { { 5672, 7532, 7532 }, "FINAL1" }, + { { 5680, 7540, 7540 }, "FINAL2" }, + { { 5688, 7548, 7548 }, "E2PAL" }, + { { 5696, 7556, 7556 }, "E2END" }, + { { 7884, 7564, 7564 }, "TITLE" }, + { { 5712, 7572, 7572 }, "ORDER" }, + { { 0, 7580, 7580 }, "CREDIT" }, + { { 5720, 7588, 7588 }, "IMPX" }, + { { 5728, 7596, 7596 }, "ACLO" }, + { { 5736, 7604, 7604 }, "PTN1" }, + { { 5744, 7612, 7612 }, "SHLD" }, + { { 5752, 7620, 7620 }, "SHD2" }, + { { 5760, 7628, 7628 }, "BAGH" }, + { { 5768, 7636, 7636 }, "SPMP" }, + { { 5776, 7644, 7644 }, "INVS" }, + { { 5784, 7652, 7652 }, "PTN2" }, + { { 5792, 7660, 7660 }, "SOAR" }, + { { 5800, 7668, 7668 }, "INVU" }, + { { 5808, 7676, 7676 }, "PWBK" }, + { { 5816, 7684, 7684 }, "EGGC" }, + { { 5824, 7692, 7692 }, "EGGM" }, + { { 5832, 7700, 7700 }, "FX01" }, + { { 5840, 7708, 7708 }, "SPHL" }, + { { 5848, 7716, 7716 }, "TRCH" }, + { { 5856, 7724, 7724 }, "FBMB" }, + { { 5864, 7732, 7732 }, "XPL1" }, + { { 5872, 7740, 7740 }, "ATLP" }, + { { 5880, 7748, 7748 }, "PPOD" }, + { { 5888, 7756, 7756 }, "AMG1" }, + { { 5896, 7764, 7764 }, "SPSH" }, + { { 5904, 7772, 7772 }, "LVAS" }, + { { 5912, 7780, 7780 }, "SLDG" }, + { { 5920, 7788, 7788 }, "SKH1" }, + { { 5928, 7796, 7796 }, "SKH2" }, + { { 5936, 7804, 7804 }, "SKH3" }, + { { 5944, 7812, 7812 }, "SKH4" }, + { { 5952, 7820, 7820 }, "CHDL" }, + { { 5960, 7828, 7828 }, "SRTC" }, + { { 5968, 7836, 7836 }, "SMPL" }, + { { 5976, 7844, 7844 }, "STGS" }, + { { 5984, 7852, 7852 }, "STGL" }, + { { 5992, 7860, 7860 }, "STCS" }, + { { 6000, 7868, 7868 }, "STCL" }, + { { 6008, 7876, 7876 }, "KFR1" }, + { { 6016, 7884, 7884 }, "BARL" }, + { { 6024, 7892, 7892 }, "BRPL" }, + { { 6032, 7900, 7900 }, "MOS1" }, + { { 6040, 7908, 7908 }, "MOS2" }, + { { 6048, 7916, 7916 }, "WTRH" }, + { { 6056, 7924, 7924 }, "HCOR" }, + { { 6064, 7932, 7932 }, "KGZ1" }, + { { 6072, 7940, 7940 }, "KGZB" }, + { { 6080, 7948, 7948 }, "KGZG" }, + { { 6088, 7956, 7956 }, "KGZY" }, + { { 6096, 7964, 7964 }, "VLCO" }, + { { 6104, 7972, 7972 }, "VFBL" }, + { { 6112, 7980, 7980 }, "VTFB" }, + { { 6120, 7988, 7988 }, "SFFI" }, + { { 6128, 7996, 7996 }, "TGLT" }, + { { 6136, 8004, 8004 }, "TELE" }, + { { 6144, 8012, 8012 }, "STFF" }, + { { 6152, 8020, 8020 }, "PUF3" }, + { { 6160, 8028, 8028 }, "PUF4" }, + { { 6168, 8036, 8036 }, "BEAK" }, + { { 6176, 8044, 8044 }, "WGNT" }, + { { 6184, 8052, 8052 }, "GAUN" }, + { { 6192, 8060, 8060 }, "PUF1" }, + { { 6200, 8068, 8068 }, "WBLS" }, + { { 6208, 8076, 8076 }, "BLSR" }, + { { 6216, 8084, 8084 }, "FX18" }, + { { 6224, 8092, 8092 }, "FX17" }, + { { 6232, 8100, 8100 }, "WMCE" }, + { { 6240, 8108, 8108 }, "MACE" }, + { { 6248, 8116, 8116 }, "FX02" }, + { { 6256, 8124, 8124 }, "WSKL" }, + { { 6264, 8132, 8132 }, "HROD" }, + { { 6272, 8140, 8140 }, "FX00" }, + { { 6280, 8148, 8148 }, "FX20" }, + { { 6288, 8156, 8156 }, "FX21" }, + { { 6296, 8164, 8164 }, "FX22" }, + { { 6304, 8172, 8172 }, "FX23" }, + { { 6312, 8180, 8180 }, "GWND" }, + { { 6320, 8188, 8188 }, "PUF2" }, + { { 6328, 8196, 8196 }, "WPHX" }, + { { 6336, 8204, 8204 }, "PHNX" }, + { { 6344, 8212, 8212 }, "FX04" }, + { { 6352, 8220, 8220 }, "FX08" }, + { { 6360, 8228, 8228 }, "FX09" }, + { { 6368, 8236, 8236 }, "WBOW" }, + { { 6376, 8244, 8244 }, "CRBW" }, + { { 6384, 8252, 8252 }, "FX03" }, + { { 6392, 8260, 8260 }, "BLOD" }, + { { 6400, 8268, 8268 }, "PLAY" }, + { { 6408, 8276, 8276 }, "FDTH" }, + { { 6416, 8284, 8284 }, "BSKL" }, + { { 6424, 8292, 8292 }, "CHKN" }, + { { 6432, 8300, 8300 }, "MUMM" }, + { { 6440, 8308, 8308 }, "FX15" }, + { { 6448, 8316, 8316 }, "BEAS" }, + { { 6456, 8324, 8324 }, "FRB1" }, + { { 6464, 8332, 8332 }, "SNKE" }, + { { 6472, 8340, 8340 }, "SNFX" }, + { { 6480, 8348, 8348 }, "HEAD" }, + { { 6488, 8356, 8356 }, "FX05" }, + { { 6496, 8364, 8364 }, "FX06" }, + { { 6504, 8372, 8372 }, "FX07" }, + { { 6512, 8380, 8380 }, "CLNK" }, + { { 6520, 8388, 8388 }, "WZRD" }, + { { 6528, 8396, 8396 }, "FX11" }, + { { 6536, 8404, 8404 }, "FX10" }, + { { 6544, 8412, 8412 }, "KNIG" }, + { { 6552, 8420, 8420 }, "SPAX" }, + { { 6560, 8428, 8428 }, "RAXE" }, + { { 6568, 8436, 8436 }, "SRCR" }, + { { 6576, 8444, 8444 }, "FX14" }, + { { 6584, 8452, 8452 }, "SOR2" }, + { { 6592, 8460, 8460 }, "SDTH" }, + { { 6600, 8468, 8468 }, "FX16" }, + { { 6608, 8476, 8476 }, "MNTR" }, + { { 6616, 8484, 8484 }, "FX12" }, + { { 6624, 8492, 8492 }, "FX13" }, + { { 6632, 8500, 8500 }, "AKYY" }, + { { 6640, 8508, 8508 }, "BKYY" }, + { { 6648, 8516, 8516 }, "CKYY" }, + { { 6656, 8524, 8524 }, "AMG2" }, + { { 6664, 8532, 8532 }, "AMM1" }, + { { 6672, 8540, 8540 }, "AMM2" }, + { { 6680, 8548, 8548 }, "AMC1" }, + { { 6688, 8556, 8556 }, "AMC2" }, + { { 6696, 8564, 8564 }, "AMS1" }, + { { 6704, 8572, 8572 }, "AMS2" }, + { { 6712, 8580, 8580 }, "AMP1" }, + { { 6720, 8588, 8588 }, "AMP2" }, + { { 6728, 8596, 8596 }, "AMB1" }, + { { 6736, 8604, 8604 }, "AMB2" }, + { { 6744, 8612, 8612 }, "K" }, + { { 6748, 8616, 8616 }, "I" }, + { { 6752, 8620, 8620 }, "L" }, + { { 6756, 8624, 8624 }, "E" }, + { { 6760, 8628, 8628 }, "R" }, + { { 6764, 8632, 8632 }, "S" }, + { { 6768, 8636, 8636 }, "PLAYPAL" }, + { { 6776, 8644, 8644 }, "MAPE1" }, + { { 6784, 8652, 8652 }, "MAPE2" }, + { { 6792, 8660, 8660 }, "MAPE3" }, + { { 6800, 8668, 8668 }, "IN_X" }, + { { 6808, 8676, 8676 }, "IN_YAH" }, + { { 6816, 8684, 8684 }, "FONTB16" }, + { { 6824, 8692, 8692 }, "FONTB_S" }, + { { 6832, 8700, 8700 }, "FONTB13" }, + { { 6840, 8708, 8708 }, "FONTB15" }, + { { 6848, 8716, 8716 }, "FONTB05" }, + { { 6856, 8724, 8724 }, "FACEA0" }, + { { 6864, 8732, 8732 }, "FACEB0" }, + { { 6940, 8808, 8808 }, "FLOOR16" }, + { { 6948, 8816, 8816 }, "FINISHED" }, + { { 6960, 8828, 8828 }, "NOW ENTERING:" }, + { { 6976, 8844, 8844 }, "KILLS" }, + { { 6984, 8852, 8852 }, "ITEMS" }, + { { 6992, 8860, 8860 }, "SECRETS" }, + { { 7000, 8868, 8868 }, "TIME" }, + { { 7008, 8876, 8876 }, "BONUS" }, + { { 7016, 8884, 8884 }, "SECRET" }, + { { 7024, 8892, 8892 }, "TOTAL" }, + { { 7032, 8900, 8900 }, "VICTIMS" }, + { { 7040, 8908, 8908 }, ":" }, + { { 7044, 8912, 8912 }, "NEW GAME" }, + { { 7056, 8924, 8924 }, "OPTIONS" }, + { { 7064, 8932, 8932 }, "GAME FILES" }, + { { 7076, 8944, 8944 }, "INFO" }, + { { 7084, 8952, 8952 }, "QUIT GAME" }, + { { 7096, 8964, 8964 }, "CITY OF THE DAMNED" }, + { { 7116, 8984, 8984 }, "HELL'S MAW" }, + { { 7128, 8996, 8996 }, "THE DOME OF D'SPARIL" }, + { { 0, 9020, 9020 }, "THE OSSUARY" }, + { { 0, 9032, 9032 }, "THE STAGNANT DEMESNE" }, + { { 7152, 9056, 9056 }, "LOAD GAME" }, + { { 7164, 9068, 9068 }, "SAVE GAME" }, + { { 7176, 9080, 9080 }, "THOU NEEDETH A WET-NURSE" }, + { { 7204, 9108, 9108 }, "YELLOWBELLIES-R-US" }, + { { 7224, 9128, 9128 }, "BRINGEST THEM ONETH" }, + { { 7244, 9148, 9148 }, "THOU ART A SMITE-MEISTER" }, + { { 7272, 9176, 9176 }, "BLACK PLAGUE POSSESSES THEE" }, + { { 7300, 9204, 9204 }, "END GAME" }, + { { 7312, 9216, 9216 }, "MESSAGES : " }, + { { 7324, 9228, 9228 }, "MOUSE SENSITIVITY" }, + { { 7344, 9248, 9248 }, "MORE..." }, + { { 7352, 9256, 9256 }, "SCREEN SIZE" }, + { { 7364, 9268, 9268 }, "SFX VOLUME" }, + { { 7376, 9280, 9280 }, "MUSIC VOLUME" }, + { { 7416, 9296, 9296 }, "ARE YOU SURE YOU WANT TO QUIT?" }, + { { 7448, 9328, 9328 }, "ARE YOU SURE YOU WANT TO END THE GAME?" }, + { { 7488, 9368, 9368 }, "DO YOU WANT TO QUICKSAVE THE GAME NAMED" }, + { { 7528, 9408, 9408 }, "DO YOU WANT TO QUICKLOAD THE GAME NAMED" }, + { { 7392, 9448, 9448 }, "M_SKL00" }, + { { 7400, 9456, 9456 }, "FONTA_S" }, + { { 7408, 9464, 9464 }, "FONTB_S" }, + { { 7568, 9472, 9472 }, "?" }, + { { 7572, 9476, 9476 }, "M_SLCTR1" }, + { { 7584, 9488, 9488 }, "M_SLCTR2" }, + { { 7596, 9500, 9500 }, "M_HTIC" }, + { { 7604, 9508, 9508 }, "c:\\heretic.cd\\hticsav%d.hsg" }, + { { 7632, 9536, 9536 }, "hticsav%d.hsg" }, + { { 7652, 9556, 9556 }, "M_FSLOT" }, + { { 7660, 9564, 9564 }, "ON" }, + { { 7664, 9568, 9568 }, "OFF" }, + { { 0, 9572, 9572 }, "YOU CAN'T START A NEW GAME IN NETPLAY!" }, + { { 0, 9612, 9612 }, "YOU CAN'T LOAD A GAME IN NETPLAY!" }, + { { 7668, 9648, 9648 }, "MESSAGES ON" }, + { { 7680, 9660, 9660 }, "MESSAGES OFF" }, + { { 7748, 9676, 9676 }, "ONLY AVAILABLE IN THE REGISTERED VERSION" }, + { { 7792, 9720, 9720 }, "PLAYPAL" }, + { { 7800, 9728, 9728 }, "QUICKSAVING...." }, + { { 7816, 9744, 9744 }, "QUICKLOADING...." }, + { { 7836, 9764, 9764 }, "CHOOSE A QUICKSAVE SLOT" }, + { { 7860, 9788, 9788 }, "CHOOSE A QUICKLOAD SLOT" }, + { { 0, 9812, 9812 }, "TITLE" }, + { { 7892, 9820, 9820 }, "M_SLDLT" }, + { { 7900, 9828, 9828 }, "M_SLDMD1" }, + { { 7912, 9840, 9840 }, "M_SLDMD2" }, + { { 7924, 9852, 9852 }, "M_SLDRT" }, + { { 7932, 9860, 9860 }, "M_SLDKB" }, + { { 9016, 10944, 10944 }, "SCREEN SHOT" }, + { { 9028, 10956, 10956 }, "YOU NEED A BLUE KEY TO OPEN THIS DOOR" }, + { { 9068, 10996, 10996 }, "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" }, + { { 9108, 11036, 11036 }, "YOU NEED A GREEN KEY TO OPEN THIS DOOR" }, + { { 9244, 11172, 11172 }, "CRYSTAL VIAL" }, + { { 9260, 11188, 11188 }, "SILVER SHIELD" }, + { { 9276, 11204, 11204 }, "ENCHANTED SHIELD" }, + { { 9296, 11224, 11224 }, "BAG OF HOLDING" }, + { { 9312, 11240, 11240 }, "MAP SCROLL" }, + { { 9324, 11252, 11252 }, "BLUE KEY" }, + { { 9336, 11264, 11264 }, "YELLOW KEY" }, + { { 9348, 11276, 11276 }, "GREEN KEY" }, + { { 9360, 11288, 11288 }, "QUARTZ FLASK" }, + { { 9376, 11304, 11304 }, "WINGS OF WRATH" }, + { { 9392, 11320, 11320 }, "RING OF INVINCIBILITY" }, + { { 9416, 11344, 11344 }, "TOME OF POWER" }, + { { 9432, 11360, 11360 }, "SHADOWSPHERE" }, + { { 9448, 11376, 11376 }, "MORPH OVUM" }, + { { 9460, 11388, 11388 }, "MYSTIC URN" }, + { { 9472, 11400, 11400 }, "TORCH" }, + { { 9480, 11408, 11408 }, "TIME BOMB OF THE ANCIENTS" }, + { { 9508, 11436, 11436 }, "CHAOS DEVICE" }, + { { 9524, 11452, 11452 }, "WAND CRYSTAL" }, + { { 9540, 11468, 11468 }, "CRYSTAL GEODE" }, + { { 9556, 11484, 11484 }, "MACE SPHERES" }, + { { 9572, 11500, 11500 }, "PILE OF MACE SPHERES" }, + { { 9596, 11524, 11524 }, "ETHEREAL ARROWS" }, + { { 9612, 11540, 11540 }, "QUIVER OF ETHEREAL ARROWS" }, + { { 9640, 11568, 11568 }, "CLAW ORB" }, + { { 9652, 11580, 11580 }, "ENERGY ORB" }, + { { 9664, 11592, 11592 }, "LESSER RUNES" }, + { { 9680, 11608, 11608 }, "GREATER RUNES" }, + { { 9696, 11624, 11624 }, "FLAME ORB" }, + { { 9708, 11636, 11636 }, "INFERNO ORB" }, + { { 9720, 11648, 11648 }, "FIREMACE" }, + { { 9732, 11660, 11660 }, "ETHEREAL CROSSBOW" }, + { { 9752, 11680, 11680 }, "DRAGON CLAW" }, + { { 9764, 11692, 11692 }, "HELLSTAFF" }, + { { 9776, 11704, 11704 }, "PHOENIX ROD" }, + { { 9788, 11716, 11716 }, "GAUNTLETS OF THE NECROMANCER" }, + { { 10088, 12016, 12016 }, "FLTWAWA1" }, + { { 10100, 12028, 12028 }, "FLTFLWW1" }, + { { 10112, 12040, 12040 }, "FLTLAVA1" }, + { { 10124, 12052, 12052 }, "FLATHUH1" }, + { { 10136, 12064, 12064 }, "FLTSLUD1" }, + { { 10148, 12076, 12076 }, "END" }, + { { 10236, 12164, 12164 }, "texture2" }, + { { 10444, 12372, 12372 }, "PLAYPAL" }, + { { 10596, 12488, 12488 }, "PNAMES" }, + { { 10604, 12496, 12496 }, "TEXTURE1" }, + { { 10616, 12508, 12508 }, "TEXTURE2" }, + { { 10628, 12520, 12520 }, "S_END" }, + { { 10636, 12528, 12528 }, "S_START" }, + { { 10728, 12620, 12620 }, "F_START" }, + { { 10736, 12628, 12628 }, "F_END" }, + { { 10744, 12636, 12636 }, "COLORMAP" }, + { { 10756, 12648, 12648 }, "\nR_InitTextures " }, + { { 10776, 12668, 12668 }, "R_InitFlats\n" }, + { { 10792, 12684, 12684 }, "R_InitSpriteLumps " }, + { { 10948, 12772, 12772 }, "TINTTAB" }, + { { 10984, 12780, 12780 }, "FLOOR04" }, + { { 10992, 12788, 12788 }, "FLAT513" }, + { { 11000, 12796, 12796 }, "bordt" }, + { { 11008, 12804, 12804 }, "bordb" }, + { { 11016, 12812, 12812 }, "bordl" }, + { { 11024, 12820, 12820 }, "bordr" }, + { { 11032, 12828, 12828 }, "bordtl" }, + { { 11040, 12836, 12836 }, "bordtr" }, + { { 11048, 12844, 12844 }, "bordbr" }, + { { 11056, 12852, 12852 }, "bordbl" }, + { { 11064, 12860, 12860 }, "R_InitData " }, + { { 11076, 12872, 12872 }, "R_InitPointToAngle\n" }, + { { 11096, 12892, 12892 }, "R_InitTables " }, + { { 11112, 12908, 12908 }, "R_InitPlanes\n" }, + { { 11128, 12924, 12924 }, "R_InitLightTables " }, + { { 11148, 12944, 12944 }, "R_InitSkyMap\n" }, + { { 11164, 12960, 12960 }, "F_SKY1" }, + { { 12120, 13484, 13484 }, "LTFACE" }, + { { 12128, 13492, 13492 }, "RTFACE" }, + { { 12136, 13500, 13500 }, "BARBACK" }, + { { 12144, 13508, 13508 }, "INVBAR" }, + { { 12152, 13516, 13516 }, "CHAIN" }, + { { 12160, 13524, 13524 }, "STATBAR" }, + { { 12168, 13532, 13532 }, "LIFEBAR" }, + { { 12176, 13540, 13540 }, "LIFEGEM2" }, + { { 12188, 13552, 13552 }, "LIFEGEM0" }, + { { 12200, 13564, 13564 }, "LTFCTOP" }, + { { 12208, 13572, 13572 }, "RTFCTOP" }, + { { 12224, 13580, 13580 }, "SELECTBOX" }, + { { 12236, 13592, 13592 }, "INVGEML1" }, + { { 12248, 13604, 13604 }, "INVGEML2" }, + { { 12260, 13616, 13616 }, "INVGEMR1" }, + { { 12272, 13628, 13628 }, "INVGEMR2" }, + { { 12284, 13640, 13640 }, "BLACKSQ" }, + { { 12292, 13648, 13648 }, "ARMCLEAR" }, + { { 12304, 13660, 13660 }, "CHAINBACK" }, + { { 12316, 13672, 13672 }, "IN0" }, + { { 12320, 13676, 13676 }, "NEGNUM" }, + { { 12328, 13684, 13684 }, "FONTB16" }, + { { 12336, 13692, 13692 }, "SMALLIN0" }, + { { 12348, 13704, 13704 }, "PLAYPAL" }, + { { 12356, 13712, 13712 }, "SPINBK0" }, + { { 12364, 13720, 13720 }, "SPFLY0" }, + { { 12372, 13728, 13728 }, "LAME" }, + { { 12380, 13736, 13736 }, "*** SOUND DEBUG INFO ***" }, + { { 12408, 13764, 13764 }, "NAME" }, + { { 12416, 13772, 13772 }, "MO.T" }, + { { 12424, 13780, 13780 }, "MO.X" }, + { { 12432, 13788, 13788 }, "MO.Y" }, + { { 12440, 13796, 13796 }, "ID" }, + { { 12444, 13800, 13800 }, "PRI" }, + { { 12448, 13804, 13804 }, "DIST" }, + { { 12456, 13812, 13812 }, "------" }, + { { 12464, 13820, 13820 }, "%s" }, + { { 12468, 13824, 13824 }, "%d" }, + { { 12472, 13828, 13828 }, "GOD1" }, + { { 12480, 13836, 13836 }, "GOD2" }, + { { 12488, 13844, 13844 }, "useartia" }, + { { 12500, 13856, 13856 }, "ykeyicon" }, + { { 12512, 13868, 13868 }, "gkeyicon" }, + { { 12524, 13880, 13880 }, "bkeyicon" }, + { { 12216, 13892, 13892 }, "ARTIBOX" }, + { { 12536, 13900, 13900 }, "GOD MODE ON" }, + { { 12548, 13912, 13912 }, "GOD MODE OFF" }, + { { 12564, 13928, 13928 }, "NO CLIPPING ON" }, + { { 12580, 13944, 13944 }, "NO CLIPPING OFF" }, + { { 12596, 13960, 13960 }, "ALL WEAPONS" }, + { { 12608, 13972, 13972 }, "POWER OFF" }, + { { 12620, 13984, 13984 }, "POWER ON" }, + { { 12632, 13996, 13996 }, "FULL HEALTH" }, + { { 12644, 14008, 14008 }, "ALL KEYS" }, + { { 12656, 14020, 14020 }, "SOUND DEBUG ON" }, + { { 12672, 14036, 14036 }, "SOUND DEBUG OFF" }, + { { 12688, 14052, 14052 }, "TICKER ON" }, + { { 12700, 14064, 14064 }, "TICKER OFF" }, + { { 12712, 14076, 14076 }, "CHOOSE AN ARTIFACT ( A - J )" }, + { { 12744, 14108, 14108 }, "HOW MANY ( 1 - 9 )" }, + { { 12764, 14128, 14128 }, "YOU GOT IT" }, + { { 12776, 14140, 14140 }, "BAD INPUT" }, + { { 12788, 14152, 14152 }, "LEVEL WARP" }, + { { 12800, 14164, 14164 }, "CHICKEN OFF" }, + { { 12812, 14176, 14176 }, "CHICKEN ON" }, + { { 12824, 14188, 14188 }, "MASSACRE" }, + { { 12836, 14200, 14200 }, "CHEATER - YOU DON'T DESERVE WEAPONS" }, + { { 12872, 14236, 14236 }, "TRYING TO CHEAT, EH? NOW YOU DIE!" }, +}; + +// String offsets that are valid but we don't support. + +static const int unsupported_strings_1_0[] = +{ + 0, 4, 64, 104, 160, 200, 220, 236, + 244, 252, 272, 288, 296, 316, 332, 372, + 436, 500, 504, 536, 544, 560, 576, 584, + 592, 612, 640, 664, 708, 712, 744, 764, + 808, 820, 828, 840, 876, 884, 908, 952, + 992, 1028, 1036, 1048, 1088, 1128, 1160, 1192, + 1212, 1912, 2044, 2056, 2068, 2128, 2140, 2168, + 2184, 2196, 2212, 2228, 2240, 2252, 2260, 2264, + 2284, 2292, 2296, 2300, 2328, 2340, 2352, 2364, + 2372, 2384, 2388, 2404, 2428, 2436, 2444, 2464, + 2496, 2508, 2520, 2552, 2564, 2572, 2584, 3120, + 3128, 3140, 3184, 3220, 3248, 3252, 3256, 3280, + 3304, 3320, 3352, 3380, 3400, 3432, 3464, 3548, + 3600, 3624, 3664, 3696, 3812, 3872, 3932, 3940, + 3976, 3996, 6872, 6896, 7648, 7696, 7940, 7964, + 7968, 7992, 8020, 8028, 8052, 8056, 8076, 8088, + 8104, 8116, 8128, 8136, 8148, 8164, 8180, 8192, + 8204, 8220, 8232, 8248, 8264, 8276, 8292, 8308, + 8320, 8328, 8340, 8352, 8364, 8376, 8392, 8408, + 8424, 8436, 8448, 8460, 8472, 8488, 8504, 8520, + 8536, 8548, 8560, 8572, 8584, 8596, 8608, 8612, + 8624, 8648, 8660, 8668, 8680, 8708, 8720, 8728, + 8740, 8752, 8764, 8788, 8800, 8812, 8824, 8848, + 8860, 8864, 8868, 8876, 8888, 8896, 8916, 8944, + 8948, 8960, 8964, 8968, 8980, 9148, 9172, 9212, + 9216, 9220, 9820, 9860, 9892, 9940, 9972, 10012, + 10036, 10040, 10052, 10080, 10152, 10192, 10248, 10284, + 10320, 10360, 10392, 10452, 10488, 10508, 10556, 10644, + 10684, 10812, 10844, 10880, 10912, 10956, 11172, 11200, + 11232, 11272, 11312, 11348, 11380, 11404, 11436, 11492, + 11548, 11616, 11684, 11748, 11792, 11840, 11896, 11936, + 11980, 12028, 12072, 12908, 12924, 12956, 12960, 12968, + 12976, 13020, 13048, 13076, 13104, 13136, 13168, 13196, + 13240, 13272, 13292, 13296, 13308, 13312, 13320, 13324, + 13364, 13408, 13460, 13492, 13516, 13560, 13612, 13664, + 13700, 13744, 13796, 13848, 13884, 13940, 13996, 14040, + 14084, 14140, 14148, 14156, 14164, 14184, 14192, 14204, + 14208, 14212, 14256, 14272, 14284, 14296, 14300, 14312, + 14320, 14324, 14348, 14356, 14360, 14372, 14380, 14392, + 14432, 14440, 14444, 14472, 14496, 14516, 14536, 14548, + 14560, 14572, 14580, 14588, 14596, 14604, 14612, 14620, + 14636, 14660, 14704, 14740, 14748, 14756, 14760, 14768, + -1, +}; + +static const int unsupported_strings_1_2[] = +{ + 0, 4, 64, 104, 160, 200, 220, 236, + 244, 252, 272, 288, 296, 316, 332, 372, + 436, 500, 504, 536, 544, 560, 576, 584, + 592, 612, 640, 664, 708, 712, 744, 756, + 776, 820, 832, 840, 852, 888, 896, 920, + 964, 1004, 1040, 1048, 1060, 1100, 1140, 1172, + 1204, 1224, 2312, 2436, 2448, 2464, 2480, 2492, + 2512, 2524, 2536, 2596, 2608, 2636, 2652, 2656, + 2676, 2684, 2688, 2720, 2732, 2744, 2752, 2764, + 2772, 2776, 2792, 2816, 2824, 2832, 2852, 2884, + 2896, 2908, 2940, 2952, 2960, 2972, 3520, 3528, + 3540, 3584, 3620, 3648, 3652, 3656, 3680, 3704, + 3720, 3776, 3804, 3824, 3856, 3888, 4020, 4044, + 4084, 4116, 4156, 4272, 4288, 4296, 4332, 4352, + 4428, 4432, 8740, 8764, 9552, 9868, 9888, 9900, + 9916, 9928, 9940, 9948, 9960, 9976, 9992, 10004, + 10016, 10032, 10044, 10060, 10076, 10088, 10104, 10120, + 10132, 10140, 10152, 10164, 10176, 10188, 10204, 10220, + 10236, 10248, 10260, 10272, 10284, 10300, 10316, 10332, + 10348, 10360, 10372, 10384, 10396, 10408, 10420, 10424, + 10436, 10460, 10472, 10480, 10492, 10520, 10532, 10540, + 10552, 10564, 10576, 10600, 10612, 10624, 10636, 10660, + 10672, 10676, 10700, 10704, 10728, 10756, 10764, 10788, + 10792, 10796, 10804, 10816, 10824, 10844, 10872, 10876, + 10888, 10892, 10896, 10908, 11076, 11100, 11140, 11144, + 11148, 11748, 11788, 11820, 11868, 11900, 11940, 11964, + 11968, 11980, 12008, 12080, 12120, 12176, 12212, 12248, + 12288, 12320, 12380, 12400, 12448, 12536, 12576, 12704, + 12736, 12968, 13000, 13024, 13080, 13136, 13204, 13272, + 13336, 13380, 13428, 14272, 14288, 14320, 14324, 14332, + 14340, 14384, 14412, 14440, 14468, 14500, 14532, 14560, + 14604, 14636, 14656, 14696, 14740, 14792, 14824, 14848, + 14892, 14944, 14996, 15032, 15076, 15128, 15180, 15216, + 15272, 15328, 15372, 15416, 15472, 15480, 15488, 15496, + 15516, 15524, 15536, 15540, 15544, 15588, 15604, 15616, + 15628, 15632, 15644, 15652, 15656, 15680, 15688, 15692, + 15704, 15712, 15724, 15764, 15772, 15776, 15804, 15828, + 15848, 15868, 15880, 15892, 15904, 15912, 15920, 15928, + 15936, -1, +}; + +static const int unsupported_strings_1_3[] = +{ + 0, 4, 64, 104, 160, 200, 220, 236, + 244, 252, 272, 288, 296, 316, 332, 372, + 436, 500, 504, 536, 544, 560, 576, 584, + 592, 612, 640, 664, 708, 712, 744, 756, + 776, 820, 832, 840, 852, 888, 896, 920, + 964, 1004, 1040, 1048, 1060, 1100, 1140, 1172, + 1204, 1224, 2312, 2436, 2448, 2464, 2480, 2492, + 2512, 2524, 2536, 2596, 2608, 2636, 2652, 2656, + 2676, 2684, 2688, 2720, 2732, 2744, 2752, 2764, + 2772, 2776, 2792, 2816, 2824, 2832, 2852, 2884, + 2896, 2908, 2940, 2952, 2960, 2972, 3520, 3528, + 3540, 3584, 3620, 3648, 3652, 3656, 3680, 3704, + 3720, 3776, 3804, 3824, 3856, 3888, 4020, 4044, + 4084, 4116, 4156, 4272, 4288, 4296, 4332, 4352, + 4428, 4432, 8740, 8764, 9552, 9868, 9888, 9900, + 9916, 9928, 9940, 9948, 9960, 9976, 9992, 10004, + 10016, 10032, 10044, 10060, 10076, 10088, 10104, 10120, + 10132, 10140, 10152, 10164, 10176, 10188, 10204, 10220, + 10236, 10248, 10260, 10272, 10284, 10300, 10316, 10332, + 10348, 10360, 10372, 10384, 10396, 10408, 10420, 10424, + 10436, 10460, 10472, 10480, 10492, 10520, 10532, 10540, + 10552, 10564, 10576, 10600, 10612, 10624, 10636, 10660, + 10672, 10676, 10700, 10704, 10728, 10756, 10764, 10788, + 10792, 10796, 10804, 10816, 10824, 10844, 10872, 10876, + 10888, 10892, 10896, 10908, 11076, 11100, 11140, 11144, + 11148, 11748, 11788, 11820, 11868, 11900, 11940, 11964, + 11968, 11980, 12008, 12080, 12120, 12176, 12212, 12248, + 12288, 12320, 12380, 12400, 12448, 12536, 12576, 12704, + 12736, 12968, 13000, 13024, 13080, 13136, 13204, 13272, + 13336, 13380, 13428, 14272, 14288, 14320, 14324, 14332, + 14340, 14384, 14412, 14440, 14468, 14500, 14532, 14560, + 14604, 14636, 14656, 14696, 14740, 14792, 14824, 14848, + 14892, 14944, 14996, 15032, 15076, 15128, 15180, 15216, + 15272, 15328, 15372, 15416, 15472, 15480, 15488, 15496, + 15516, 15524, 15536, 15540, 15544, 15588, 15604, 15616, + 15628, 15632, 15644, 15652, 15656, 15680, 15688, 15692, + 15704, 15712, 15724, 15764, 15772, 15776, 15804, 15828, + 15848, 15868, 15880, 15892, 15904, 15912, 15920, 15928, + 15936, -1, +}; + +static const int *unsupported_strings[] = +{ + unsupported_strings_1_0, + unsupported_strings_1_2, + unsupported_strings_1_3, +}; + +static boolean StringIsUnsupported(unsigned int offset) +{ + const int *string_list; + int i; + + string_list = unsupported_strings[deh_hhe_version]; + + for (i=0; string_list[i] >= 0; ++i) + { + if ((unsigned int) string_list[i] == offset) + { + return true; + } + } + + return false; +} + +static boolean GetStringByOffset(unsigned int offset, const char **result) +{ + int i; + + for (i=0; i= 0; ++i) + { + if (string_list[i] == offset) + { + DEH_SuggestHereticVersion(v); + } + } + } +} + +static void *DEH_TextStart(deh_context_t *context, char *line) +{ + char *repl_text; + const char *orig_text; + int orig_offset, repl_len; + int i; + + if (sscanf(line, "Text %i %i", &orig_offset, &repl_len) != 2) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + repl_text = malloc(repl_len + 1); + + // read in the "to" text + + for (i=0; i MaxStringLength(strlen(orig_text))) + { + DEH_Error(context, "Replacement string is longer than the maximum " + "possible in heretic.exe"); + } + else + { + // Success. + + DEH_AddStringReplacement(orig_text, repl_text); + } + + // We must always free the replacement text. + free(repl_text); + + return NULL; +} + +static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag) +{ + // not used +} + +deh_section_t deh_section_heretic_text = +{ + "Text", + NULL, + DEH_TextStart, + DEH_TextParseLine, + NULL, + NULL, +}; + diff --git a/games/NXDoom/src/heretic/deh_htic.c b/games/NXDoom/src/heretic/deh_htic.c new file mode 100644 index 00000000000..94fb935ceca --- /dev/null +++ b/games/NXDoom/src/heretic/deh_htic.c @@ -0,0 +1,182 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Top-level dehacked definitions for Heretic dehacked (HHE). +// + +#include +#include +#include + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_htic.h" +#include "info.h" +#include "m_argv.h" + +const char *deh_signatures[] = +{ + "Patch File for HHE v1.0", + "Patch File for HHE v1.1", + NULL +}; + +static const char *hhe_versions[] = +{ + "1.0", "1.2", "1.3" +}; + +// Version number for patches. + +deh_hhe_version_t deh_hhe_version = deh_hhe_1_0; + + +// +// List of section types: +// + +deh_section_t *deh_section_types[] = +{ + &deh_section_ammo, + &deh_section_frame, +// &deh_section_pointer, TODO + &deh_section_sound, + &deh_section_heretic_text, + &deh_section_thing, + &deh_section_weapon, + NULL +}; + +static void SetHHEVersionByName(const char *name) +{ + int i; + + for (i=0; i + // @category mod + // + // Select the Heretic version number that was used to generate the + // HHE patch to be loaded. Patches for each of the Vanilla + // Heretic versions (1.0, 1.2, 1.3) can be loaded, but the correct + // version number must be specified. + + i = M_CheckParm("-hhever"); + + if (i > 0) + { + SetHHEVersionByName(myargv[i + 1]); + } + + // For v1.0 patches, we must apply a slight change to the states[] + // table. The table was changed between 1.0 and 1.3 to add two extra + // frames to the player "burning death" animation. + // + // If we are using a v1.0 patch, we must change the table to cut + // these out again. + + if (deh_hhe_version < deh_hhe_1_2) + { + states[S_PLAY_FDTH18].nextstate = S_NULL; + } +} + +int DEH_MapHereticThingType(int type) +{ + // Heretic 1.0 had an extra entry in the mobjinfo table that was removed + // in later versions. This has been added back into the table for + // compatibility. However, it also means that if we're loading a patch + // for a later version, we need to translate to the index used internally. + + if (deh_hhe_version > deh_hhe_1_0) + { + if (type >= MT_PHOENIXFX_REMOVED) + { + ++type; + } + } + + return type; +} + +int DEH_MapHereticFrameNumber(int frame) +{ + if (deh_hhe_version < deh_hhe_1_2) + { + // Between Heretic 1.0 and 1.2, two new frames + // were added to the "states" table, to extend the "flame death" + // animation displayed when the player is killed by fire. Therefore, + // we must map Heretic 1.0 frame numbers to corresponding indexes + // for our state table. + + if (frame >= S_PLAY_FDTH19) + { + frame = (frame - S_PLAY_FDTH19) + S_BLOODYSKULL1; + } + } + else + { + // After Heretic 1.2, three unused frames were removed from the + // states table, unused phoenix rod frames. Our state table includes + // these missing states for backwards compatibility. We must therefore + // adjust frame numbers for v1.2/v1.3 to corresponding indexes for + // our state table. + + if (frame >= S_PHOENIXFXIX_1) + { + frame = (frame - S_PHOENIXFXIX_1) + S_PHOENIXPUFF1; + } + } + + return frame; +} + +void DEH_SuggestHereticVersion(deh_hhe_version_t version) +{ + fprintf(stderr, + "\n" + "This patch may be for version %s. You are currently running in\n" + "Heretic %s mode. For %s mode, add this to your command line:\n" + "\n" + "\t-hhever %s\n" + "\n", + hhe_versions[version], + hhe_versions[deh_hhe_version], + hhe_versions[version], + hhe_versions[version]); +} + diff --git a/games/NXDoom/src/heretic/deh_htic.h b/games/NXDoom/src/heretic/deh_htic.h new file mode 100644 index 00000000000..978d9381567 --- /dev/null +++ b/games/NXDoom/src/heretic/deh_htic.h @@ -0,0 +1,56 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Common header for Heretic dehacked (HHE) support. +// + +#ifndef DEH_HTIC_H +#define DEH_HTIC_H + +#include "info.h" + +// HHE executable version. Loading HHE patches is (unfortunately) +// dependent on the version of the Heretic executable used to make them. + +typedef enum +{ + deh_hhe_1_0, + deh_hhe_1_2, + deh_hhe_1_3, + deh_hhe_num_versions +} deh_hhe_version_t; + +// HHE doesn't know about the last two states in the state table, so +// these are considered invalid. + +#define DEH_HERETIC_NUMSTATES (NUMSTATES - 2) + +// It also doesn't know about the last two things in the mobjinfo table +// (which correspond to the states above) + +#define DEH_HERETIC_NUMMOBJTYPES (NUMMOBJTYPES - 2) + +void DEH_HereticInit(void); +int DEH_MapHereticThingType(int type); +int DEH_MapHereticFrameNumber(int frame); +void DEH_SuggestHereticVersion(deh_hhe_version_t version); + +extern deh_hhe_version_t deh_hhe_version; + +// deh_htext.c: +extern deh_section_t deh_section_heretic_text; + + +#endif /* #ifndef DEH_HTIC_H */ + diff --git a/games/NXDoom/src/heretic/deh_sound.c b/games/NXDoom/src/heretic/deh_sound.c new file mode 100644 index 00000000000..c889cd66308 --- /dev/null +++ b/games/NXDoom/src/heretic/deh_sound.c @@ -0,0 +1,108 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Sound" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" + +#include "doomdef.h" +#include "i_sound.h" + +#include "sounds.h" + +DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t) + DEH_MAPPING_STRING("Name", name) + DEH_UNSUPPORTED_MAPPING("Special") + DEH_MAPPING("Value", priority) + DEH_MAPPING("Unknown 1", usefulness) + DEH_UNSUPPORTED_MAPPING("Unknown 2") + DEH_UNSUPPORTED_MAPPING("Unknown 3") + DEH_MAPPING("One/Two", numchannels) +DEH_END_MAPPING + +static void *DEH_SoundStart(deh_context_t *context, char *line) +{ + int sound_number = 0; + + if (sscanf(line, "Sound %i", &sound_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (sound_number < 0 || sound_number >= NUMSFX) + { + DEH_Warning(context, "Invalid sound number: %i", sound_number); + return NULL; + } + + if (sound_number >= DEH_VANILLA_NUMSFX) + { + DEH_Warning(context, "Attempt to modify SFX %i. This will cause " + "problems in Vanilla dehacked.", sound_number); + } + + return &S_sfx[sound_number]; +} + +static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag) +{ + sfxinfo_t *sfx; + char *variable_name, *value; + + if (tag == NULL) + return; + + sfx = (sfxinfo_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + // Set the field value: + + if (!strcasecmp(variable_name, "Name")) + { + DEH_SetStringMapping(context, &sound_mapping, sfx, + variable_name, value); + } + else + { + DEH_SetMapping(context, &sound_mapping, sfx, + variable_name, atoi(value)); + } +} + +deh_section_t deh_section_sound = +{ + "Sound", + NULL, + DEH_SoundStart, + DEH_SoundParseLine, + NULL, + NULL, +}; + diff --git a/games/NXDoom/src/heretic/deh_thing.c b/games/NXDoom/src/heretic/deh_thing.c new file mode 100644 index 00000000000..e9984fbdef7 --- /dev/null +++ b/games/NXDoom/src/heretic/deh_thing.c @@ -0,0 +1,144 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Thing" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" +#include "m_misc.h" + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" +#include "deh_htic.h" + +#include "info.h" + +DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t) + DEH_MAPPING("ID #", doomednum) + DEH_MAPPING("Initial frame", spawnstate) + DEH_MAPPING("Hit points", spawnhealth) + DEH_MAPPING("First moving frame", seestate) + DEH_MAPPING("Alert sound", seesound) + DEH_MAPPING("Reaction time", reactiontime) + DEH_MAPPING("Attack sound", attacksound) + DEH_MAPPING("Injury frame", painstate) + DEH_MAPPING("Pain chance", painchance) + DEH_MAPPING("Pain sound", painsound) + DEH_MAPPING("Close attack frame", meleestate) + DEH_MAPPING("Far attack frame", missilestate) + DEH_MAPPING("Burning frame", crashstate) + DEH_MAPPING("Death frame", deathstate) + DEH_MAPPING("Exploding frame", xdeathstate) + DEH_MAPPING("Death sound", deathsound) + DEH_MAPPING("Speed", speed) + DEH_MAPPING("Width", radius) + DEH_MAPPING("Height", height) + DEH_MAPPING("Mass", mass) + DEH_MAPPING("Missile damage", damage) + DEH_MAPPING("Action sound", activesound) + DEH_MAPPING("Bits 1", flags) + DEH_MAPPING("Bits 2", flags2) +DEH_END_MAPPING + +static void *DEH_ThingStart(deh_context_t *context, char *line) +{ + int orig_thing_number = 0, thing_number = 0; + mobjinfo_t *mobj; + + if (sscanf(line, "Thing %i", &orig_thing_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + // Translate to the correct thing number based on the exe version this + // patch was made for. Subtract one because HHE thing numbers are + // indexed from 1. + + thing_number = DEH_MapHereticThingType(orig_thing_number - 1); + + if (thing_number < 0 || thing_number >= DEH_HERETIC_NUMMOBJTYPES) + { + DEH_Warning(context, "Invalid thing number: %i", orig_thing_number); + return NULL; + } + + mobj = &mobjinfo[thing_number]; + + return mobj; +} + +static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) +{ + mobjinfo_t *mobj; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + mobj = (mobjinfo_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + // all values are integers + + ivalue = atoi(value); + + // If the value to be set is a frame, the frame number must + // undergo transformation from a Heretic 1.0 index to a + // Heretic 1.3 index. + + if (M_StrCaseStr(variable_name, "frame") != NULL) + { + ivalue = DEH_MapHereticFrameNumber(ivalue); + } + + // Set the field value + + DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); +} + +static void DEH_ThingSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include +#include + +#include "doomtype.h" +#include "m_misc.h" + +#include "doomdef.h" + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" +#include "deh_htic.h" + +DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t) + DEH_MAPPING("Ammo type", ammo) + DEH_MAPPING("Deselect frame", upstate) + DEH_MAPPING("Select frame", downstate) + DEH_MAPPING("Bobbing frame", readystate) + DEH_MAPPING("Shooting frame", atkstate) + DEH_MAPPING("Firing frame", holdatkstate) + DEH_MAPPING("Unknown frame", flashstate) +DEH_END_MAPPING + +static void *DEH_WeaponStart(deh_context_t *context, char *line) +{ + int weapon_number = 0; + + if (sscanf(line, "Weapon %i", &weapon_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (weapon_number < 0 || weapon_number >= NUMWEAPONS * 2) + { + DEH_Warning(context, "Invalid weapon number: %i", weapon_number); + return NULL; + } + + // Because of the tome of power, we have two levels of weapons: + + if (weapon_number < NUMWEAPONS) + { + return &wpnlev1info[weapon_number]; + } + else + { + return &wpnlev2info[weapon_number - NUMWEAPONS]; + } +} + +static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + weaponinfo_t *weapon; + int ivalue; + + if (tag == NULL) + return; + + weapon = (weaponinfo_t *) tag; + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + // If this is a frame field, we need to map from Heretic 1.0 frame + // numbers to Heretic 1.3 frame numbers. + + if (M_StrCaseStr(variable_name, "frame") != NULL) + { + ivalue = DEH_MapHereticFrameNumber(ivalue); + } + + DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); +} + +static void DEH_WeaponSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include +//haleyjd: removed WATCOMC +#include + +#define HERETIC_VERSION 130 +#define HERETIC_VERSION_TEXT "v1.3" + +// if rangecheck is undefined, most parameter validation debugging code +// will not be compiled +//#define RANGECHECK + +// all external data is defined here +#include "doomdata.h" + +// all important printed strings +#include "dstrings.h" + +// header generated by multigen utility +#include "info.h" + +// WAD file access +#include "w_wad.h" + +// fixed_t +#include "m_fixed.h" + +// angle_t +#include "tables.h" + +// events +#include "d_event.h" + +// gamemode/mission +#include "d_mode.h" + +// ticcmd_t +#include "d_ticcmd.h" + +#include "d_loop.h" + +#define SAVEGAMENAME "hticsav" + +/* +=============================================================================== + + GLOBAL TYPES + +=============================================================================== +*/ + +#define NUMARTIFCTS 28 +#define MAXPLAYERS 4 + +#define BT_ATTACK 1 +#define BT_USE 2 +#define BT_CHANGE 4 // if true, the next 3 bits hold weapon num +#define BT_WEAPONMASK (8+16+32) +#define BT_WEAPONSHIFT 3 + +#define BT_SPECIAL 128 // game events, not really buttons +#define BTS_SAVEMASK (4+8+16) +#define BTS_SAVESHIFT 2 +#define BT_SPECIALMASK 3 +#define BTS_PAUSE 1 // pause the game +#define BTS_SAVEGAME 2 // save the game at each console +// savegame slot numbers occupy the second byte of buttons + +typedef enum +{ + GS_LEVEL, + GS_INTERMISSION, + GS_FINALE, + GS_DEMOSCREEN +} gamestate_t; + +typedef enum +{ + ga_nothing, + ga_loadlevel, + ga_newgame, + ga_loadgame, + ga_savegame, + ga_playdemo, + ga_completed, + ga_victory, + ga_worlddone, + ga_screenshot +} gameaction_t; + +typedef enum +{ + wipe_0, + wipe_1, + wipe_2, + wipe_3, + wipe_4, + NUMWIPES, + wipe_random +} wipe_t; + +/* +=============================================================================== + + MAPOBJ DATA + +=============================================================================== +*/ + + +struct thinker_s; + +// think_t is a function pointer to a routine to handle an actor +typedef void (*think_t) (struct thinker_s *); + +typedef struct thinker_s +{ + struct thinker_s *prev, *next; + think_t function; +} thinker_t; + +typedef union +{ + int i; + struct mobj_s *m; +} specialval_t; + +struct player_s; + +typedef struct mobj_s +{ + thinker_t thinker; // thinker links + +// info for drawing + fixed_t x, y, z; + struct mobj_s *snext, *sprev; // links in sector (if needed) + angle_t angle; + spritenum_t sprite; // used to find patch_t and flip value + int frame; // might be ord with FF_FULLBRIGHT + +// interaction info + struct mobj_s *bnext, *bprev; // links in blocks (if needed) + struct subsector_s *subsector; + fixed_t floorz, ceilingz; // closest together of contacted secs + fixed_t radius, height; // for movement checking + fixed_t momx, momy, momz; // momentums + + int validcount; // if == validcount, already checked + + mobjtype_t type; + mobjinfo_t *info; // &mobjinfo[mobj->type] + int tics; // state tic counter + state_t *state; + int damage; // For missiles + int flags; + int flags2; // Heretic flags + specialval_t special1; // Special info + specialval_t special2; // Special info + int health; + int movedir; // 0-7 + int movecount; // when 0, select a new dir + struct mobj_s *target; // thing being chased/attacked (or NULL) + // also the originator for missiles + int reactiontime; // if non 0, don't attack yet + // used by player to freeze a bit after + // teleporting + int threshold; // if >0, the target will be chased + // no matter what (even if shot) + struct player_s *player; // only valid if type == MT_PLAYER + int lastlook; // player number last looked for + + mapthing_t spawnpoint; // for nightmare respawn +} mobj_t; + +// each sector has a degenmobj_t in it's center for sound origin purposes +typedef struct +{ + thinker_t thinker; // not used for anything + fixed_t x, y, z; +} degenmobj_t; + +// +// frame flags +// +#define FF_FULLBRIGHT 0x8000 // flag in thing->frame +#define FF_FRAMEMASK 0x7fff + +// --- mobj.flags --- + +#define MF_SPECIAL 1 // call P_SpecialThing when touched +#define MF_SOLID 2 +#define MF_SHOOTABLE 4 +#define MF_NOSECTOR 8 // don't use the sector links + // (invisible but touchable) +#define MF_NOBLOCKMAP 16 // don't use the blocklinks + // (inert but displayable) +#define MF_AMBUSH 32 +#define MF_JUSTHIT 64 // try to attack right back +#define MF_JUSTATTACKED 128 // take at least one step before attacking +#define MF_SPAWNCEILING 256 // hang from ceiling instead of floor +#define MF_NOGRAVITY 512 // don't apply gravity every tic + +// movement flags +#define MF_DROPOFF 0x400 // allow jumps from high places +#define MF_PICKUP 0x800 // for players to pick up items +#define MF_NOCLIP 0x1000 // player cheat +#define MF_SLIDE 0x2000 // keep info about sliding along walls +#define MF_FLOAT 0x4000 // allow moves to any height, no gravity +#define MF_TELEPORT 0x8000 // don't cross lines or look at heights +#define MF_MISSILE 0x10000 // don't hit same species, explode on block + +#define MF_DROPPED 0x20000 // dropped by a demon, not level spawned +#define MF_SHADOW 0x40000 // use translucent draw (shadow demons / invis) +#define MF_NOBLOOD 0x80000 // don't bleed when shot (use puff) +#define MF_CORPSE 0x100000 // don't stop moving halfway off a step +#define MF_INFLOAT 0x200000 // floating to a height for a move, don't + // auto float to target's height + +#define MF_COUNTKILL 0x400000 // count towards intermission kill total +#define MF_COUNTITEM 0x800000 // count towards intermission item total + +#define MF_SKULLFLY 0x1000000 // skull in flight +#define MF_NOTDMATCH 0x2000000 // don't spawn in death match (key cards) + +#define MF_TRANSLATION 0xc000000 // if 0x4 0x8 or 0xc, use a translation +#define MF_TRANSSHIFT 26 // table for player colormaps + +// --- mobj.flags2 --- + +#define MF2_LOGRAV 0x00000001 // alternate gravity setting +#define MF2_WINDTHRUST 0x00000002 // gets pushed around by the wind + // specials +#define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor +#define MF2_THRUGHOST 0x00000008 // missile will pass through ghosts +#define MF2_FLY 0x00000010 // fly mode is active +#define MF2_FOOTCLIP 0x00000020 // if feet are allowed to be clipped +#define MF2_SPAWNFLOAT 0x00000040 // spawn random float z +#define MF2_NOTELEPORT 0x00000080 // does not teleport +#define MF2_RIP 0x00000100 // missile rips through solid + // targets +#define MF2_PUSHABLE 0x00000200 // can be pushed by other moving + // mobjs +#define MF2_SLIDE 0x00000400 // slides against walls +#define MF2_ONMOBJ 0x00000800 // mobj is resting on top of another + // mobj +#define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, + // this flag will allow the mobj to + // pass over/under other mobjs. +#define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs +#define MF2_FEETARECLIPPED 0x00004000 // a mobj's feet are now being cut +#define MF2_BOSS 0x00008000 // mobj is a major boss +#define MF2_FIREDAMAGE 0x00010000 // does fire damage +#define MF2_NODMGTHRUST 0x00020000 // does not thrust target when + // damaging +#define MF2_TELESTOMP 0x00040000 // mobj can stomp another +#define MF2_FLOATBOB 0x00080000 // use float bobbing z movement +#define MF2_DONTDRAW 0X00100000 // don't generate a vissprite + +//============================================================================= +typedef enum +{ + PST_LIVE, // playing + PST_DEAD, // dead on the ground + PST_REBORN // ready to restart +} playerstate_t; + +// psprites are scaled shapes directly on the view screen +// coordinates are given for a 320*200 view screen +typedef enum +{ + ps_weapon, + ps_flash, + NUMPSPRITES +} psprnum_t; + +typedef struct pspdef_s +{ + state_t *state; // a NULL state means not active + int tics; + fixed_t sx, sy; +} pspdef_t; + +typedef enum +{ + key_yellow, + key_green, + key_blue, + NUM_KEY_TYPES +} keytype_t; + +typedef enum +{ + wp_staff, + wp_goldwand, + wp_crossbow, + wp_blaster, + wp_skullrod, + wp_phoenixrod, + wp_mace, + wp_gauntlets, + wp_beak, + NUMWEAPONS, + wp_nochange +} weapontype_t; + +#define AMMO_GWND_WIMPY 10 +#define AMMO_GWND_HEFTY 50 +#define AMMO_CBOW_WIMPY 5 +#define AMMO_CBOW_HEFTY 20 +#define AMMO_BLSR_WIMPY 10 +#define AMMO_BLSR_HEFTY 25 +#define AMMO_SKRD_WIMPY 20 +#define AMMO_SKRD_HEFTY 100 +#define AMMO_PHRD_WIMPY 1 +#define AMMO_PHRD_HEFTY 10 +#define AMMO_MACE_WIMPY 20 +#define AMMO_MACE_HEFTY 100 + +typedef enum +{ + am_goldwand, + am_crossbow, + am_blaster, + am_skullrod, + am_phoenixrod, + am_mace, + NUMAMMO, + am_noammo // staff, gauntlets +} ammotype_t; + +typedef struct +{ + ammotype_t ammo; + int upstate; + int downstate; + int readystate; + int atkstate; + int holdatkstate; + int flashstate; +} weaponinfo_t; + +extern weaponinfo_t wpnlev1info[NUMWEAPONS]; +extern weaponinfo_t wpnlev2info[NUMWEAPONS]; + +typedef enum +{ + arti_none, + arti_invulnerability, + arti_invisibility, + arti_health, + arti_superhealth, + arti_tomeofpower, + arti_torch, + arti_firebomb, + arti_egg, + arti_fly, + arti_teleport, + NUMARTIFACTS +} artitype_t; + +typedef enum +{ + pw_None, + pw_invulnerability, + pw_invisibility, + pw_allmap, + pw_infrared, + pw_weaponlevel2, + pw_flight, + pw_shield, + pw_health2, + NUMPOWERS +} powertype_t; + +#define INVULNTICS (30*35) +#define INVISTICS (60*35) +#define INFRATICS (120*35) +#define IRONTICS (60*35) +#define WPNLEV2TICS (40*35) +#define FLIGHTTICS (60*35) + +#define CHICKENTICS (40*35) + +#define MESSAGETICS (4*35) +#define BLINKTHRESHOLD (4*32) + +#define NUMINVENTORYSLOTS 14 +typedef struct +{ + int type; + int count; +} inventory_t; + +/* +================ += += player_t += +================ +*/ + +typedef struct player_s +{ + mobj_t *mo; + playerstate_t playerstate; + ticcmd_t cmd; + + fixed_t viewz; // focal origin above r.z + fixed_t viewheight; // base height above floor for viewz + fixed_t deltaviewheight; // squat speed + fixed_t bob; // bounded/scaled total momentum + + int flyheight; + int lookdir; + boolean centering; + int health; // only used between levels, mo->health + // is used during levels + int armorpoints, armortype; // armor type is 0-2 + + inventory_t inventory[NUMINVENTORYSLOTS]; + artitype_t readyArtifact; + int artifactCount; + int inventorySlotNum; + int powers[NUMPOWERS]; + boolean keys[NUM_KEY_TYPES]; + boolean backpack; + signed int frags[MAXPLAYERS]; // kills of other players + weapontype_t readyweapon; + weapontype_t pendingweapon; // wp_nochange if not changing + boolean weaponowned[NUMWEAPONS]; + int ammo[NUMAMMO]; + int maxammo[NUMAMMO]; + int attackdown, usedown; // true if button down last tic + int cheats; // bit flags + + int refire; // refired shots are less accurate + + int killcount, itemcount, secretcount; // for intermission + const char *message; // hint messages + int messageTics; // counter for showing messages + int damagecount, bonuscount; // for screen flashing + int flamecount; // for flame thrower duration + mobj_t *attacker; // who did damage (NULL for floors) + int extralight; // so gun flashes light up areas + int fixedcolormap; // can be set to REDCOLORMAP, etc + int colormap; // 0-3 for which color to draw player + pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) + boolean didsecret; // true if secret level has been done + int chickenTics; // player is a chicken if > 0 + int chickenPeck; // chicken peck countdown + mobj_t *rain1; // active rain maker 1 + mobj_t *rain2; // active rain maker 2 +} player_t; + +#define CF_NOCLIP 1 +#define CF_GODMODE 2 +#define CF_NOMOMENTUM 4 // not really a cheat, just a debug aid + +#define SBARHEIGHT 42 // status bar height at bottom of screen + + +/* +=============================================================================== + + GLOBAL VARIABLES + +=============================================================================== +*/ + +#define TELEFOGHEIGHT (32*FRACUNIT) + +extern gameaction_t gameaction; + +extern boolean paused; + +extern GameMode_t gamemode; + +extern boolean ExtendedWAD; // true if main WAD is the extended version + +extern boolean nomonsters; // checkparm of -nomonsters + +extern boolean respawnparm; // checkparm of -respawn + +extern boolean debugmode; // checkparm of -debug + +extern boolean usergame; // ok to save / end game + +extern boolean ravpic; // checkparm of -ravpic + +extern boolean altpal; // checkparm to use an alternate palette routine + +extern boolean cdrom; // true if cd-rom mode active ("-cdrom") + +extern boolean noartiskip; // whether shift-enter skips an artifact + +extern boolean viewactive; + +extern boolean deathmatch; // only if started as net death + +extern boolean netgame; // only true if >1 player + +extern boolean playeringame[MAXPLAYERS]; + +extern int consoleplayer; // player taking events and displaying + +extern int displayplayer; + +extern int viewangleoffset; // ANG90 = left side, ANG270 = right + +extern player_t players[MAXPLAYERS]; + +extern boolean DebugSound; // debug flag for displaying sound info + +extern int GetWeaponAmmo[NUMWEAPONS]; + +extern boolean demorecording; +extern boolean demoplayback; +extern boolean demoextend; // allow demos to persist through exit/respawn +extern int skytexture; + +// Truncate angleturn in ticcmds to nearest 256. +// Used when recording Vanilla demos in netgames. +extern boolean lowres_turn; + +extern gamestate_t gamestate; +extern skill_t gameskill; +extern boolean respawnmonsters; +extern int gameepisode; +extern int gamemap; +extern int prevmap; +extern int totalkills, totalitems, totalsecret; // for intermission +extern int levelstarttic; // gametic at level start +extern int leveltime; // tics in game play for par + +extern ticcmd_t *netcmds; + +#define SAVEGAMESIZE 0x30000 +#define SAVESTRINGSIZE 24 + +extern mapthing_t *deathmatch_p; +extern mapthing_t deathmatchstarts[10]; +extern mapthing_t playerstarts[MAXPLAYERS]; +extern boolean playerstartsingame[MAXPLAYERS]; + +extern int mouseSensitivity; + +extern boolean precache; // if true, load all graphics at level load + +extern boolean singledemo; // quit after playing a demo from cmdline + +extern int bodyqueslot; +extern skill_t startskill; +extern int startepisode; +extern int startmap; +extern boolean autostart; +extern boolean advancedemo; + +extern boolean testcontrols; +extern int testcontrols_mousespeed; + +extern int vanilla_savegame_limit; +extern int vanilla_demo_limit; + +/* +=============================================================================== + + GLOBAL FUNCTIONS + +=============================================================================== +*/ + +#include "z_zone.h" + +//---------- +//BASE LEVEL +//---------- +void D_DoomMain(void); +void CheckAbortStartup(void); +void IncThermo(void); +void InitThermo(int max); +void tprintf(const char *string, int initflag); +// not a globally visible function, just included for source reference +// calls all startup code +// parses command line options +// if not overrided, calls N_AdvanceDemo + +void D_DoomLoop(void); +// not a globally visible function, just included for source reference +// called by D_DoomMain, never exits +// manages timing and IO +// calls all ?_Responder, ?_Ticker, and ?_Drawer functions +// calls I_GetTime, I_StartFrame, and I_StartTic + +void D_StartTitle(void); + + +//--------- +//SYSTEM IO +//--------- +byte *I_AllocLow(int length); +// allocates from low memory under dos, just mallocs under unix + +// haleyjd: was WATCOMC, preserved for historical interest. +// This is similar to the -control structure in DOOM v1.4 and Strife. +#if 0 +extern boolean useexterndriver; + +#define EBT_FIRE 1 +#define EBT_OPENDOOR 2 +#define EBT_SPEED 4 +#define EBT_STRAFE 8 +#define EBT_MAP 0x10 +#define EBT_INVENTORYLEFT 0x20 +#define EBT_INVENTORYRIGHT 0x40 +#define EBT_USEARTIFACT 0x80 +#define EBT_FLYDROP 0x100 +#define EBT_CENTERVIEW 0x200 +#define EBT_PAUSE 0x400 +#define EBT_WEAPONCYCLE 0x800 + +typedef struct +{ + short vector; // Interrupt vector + + signed char moveForward; // forward/backward (maxes at 50) + signed char moveSideways; // strafe (maxes at 24) + short angleTurn; // turning speed (640 [slow] 1280 [fast]) + short angleHead; // head angle (+2080 [left] : 0 [center] : -2048 [right]) + signed char pitch; // look up/down (-110 : +90) + signed char flyDirection; // flyheight (+1/-1) + unsigned short buttons; // EBT_* flags +} externdata_t; +#endif + +//---- +//GAME +//---- + +void G_DeathMatchSpawnPlayer(int playernum); + +void G_InitNew(skill_t skill, int episode, int map); + +void G_DeferedInitNew(skill_t skill, int episode, int map); +// can be called by the startup code or M_Responder +// a normal game starts at map 1, but a warp test can start elsewhere + +void G_DeferedPlayDemo(const char *demo); + +void G_LoadGame(char *name); +// can be called by the startup code or M_Responder +// calls P_SetupLevel or W_EnterWorld +void G_DoLoadGame(void); + +void G_SaveGame(int slot, char *description); +// called by M_Responder + +#define SAVE_GAME_TERMINATOR 0x1d +// Support routines for saving games +char *SV_Filename(int slot); +void SV_Open(char *fileName); +void SV_OpenRead(char *fileName); +void SV_WriteSaveGameEOF(void); +void SV_Close(void); +void SV_Write(void *buffer, int size); +void SV_WriteByte(byte val); +void SV_WriteWord(unsigned short val); +void SV_WriteLong(unsigned int val); +void SV_Read(void *buffer, int size); +byte SV_ReadByte(void); +uint16_t SV_ReadWord(void); +uint32_t SV_ReadLong(void); + +extern char *savegamedir; + +void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, + const char *name); +// only called by startup code + +void G_PlayDemo(char *name); +void G_TimeDemo(char *name); +boolean G_CheckDemoStatus(void); +void D_DoAdvanceDemo(void); + +void G_ExitLevel(void); +void G_SecretExitLevel(void); + +void D_ProcessEvents(void); + +void G_WorldDone(void); + +void G_BuildTiccmd(ticcmd_t *cmd, int maketic); + +void G_Ticker(void); +boolean G_Responder(event_t * ev); + +void G_ScreenShot(void); + +//----- +//PLAY +//----- + +extern lumpinfo_t *maplumpinfo; + +void P_Ticker(void); +// called by C_Ticker +// can call G_PlayerExited +// carries out all thinking of monsters and players + +void P_SetupLevel(int episode, int map, int playermask, skill_t skill); +// called by W_Ticker + +void P_Init(void); +// called by startup code + +void P_ArchivePlayers(void); +void P_UnArchivePlayers(void); +void P_ArchiveWorld(void); +void P_UnArchiveWorld(void); +void P_ArchiveThinkers(void); +void P_UnArchiveThinkers(void); +void P_ArchiveSpecials(void); +void P_UnArchiveSpecials(void); +// load / save game routines + + +//------- +//REFRESH +//------- + +extern boolean setsizeneeded; + +extern boolean BorderNeedRefresh; +extern boolean BorderTopRefresh; + +extern int UpdateState; +// define the different areas for the dirty map +#define I_NOUPDATE 0 +#define I_FULLVIEW 1 +#define I_STATBAR 2 +#define I_MESSAGES 4 +#define I_FULLSCRN 8 + +void R_RenderPlayerView(player_t * player); +// called by G_Drawer + +void R_Init(void); +// called by startup code + +void R_DrawViewBorder(void); +void R_DrawTopBorder(void); +// if the view size is not full screen, draws a border around it + +void R_SetViewSize(int blocks, int detail); +// called by M_Responder + +int R_FlatNumForName(const char *name); + +int R_TextureNumForName(const char *name); +int R_CheckTextureNumForName(const char *name); +// called by P_Ticker for switches and animations +// returns the texture number for the texture name + + +//---- +//MISC +//---- +// returns the position of the given parameter in the arg list (0 if not found) + +int M_DrawText(int x, int y, boolean direct, char *string); + +//---------------------- +// Interlude (IN_lude.c) +//---------------------- + +extern boolean intermission; + +void IN_Start(void); +void IN_Ticker(void); +void IN_Drawer(void); + +//---------------------- +// Chat mode (CT_chat.c) +//---------------------- + +void CT_Init(void); +void CT_Drawer(void); +boolean CT_Responder(event_t * ev); +void CT_Ticker(void); +char CT_dequeueChatChar(void); + +extern boolean chatmodeon; +extern boolean ultimatemsg; + +//-------------------- +// Finale (F_finale.c) +//-------------------- + +void F_Drawer(void); +void F_Ticker(void); +void F_StartFinale(void); + +//---------------------- +// STATUS BAR (SB_bar.c) +//---------------------- + + +extern boolean inventory; +extern int curpos; +extern int inv_ptr; +extern int playerkeys; + + +void SB_Init(void); +boolean SB_Responder(event_t * event); +void SB_Ticker(void); +void SB_Drawer(void); + +//----------------- +// MENU (MN_menu.c) +//----------------- + +extern boolean askforquit; +extern boolean MenuActive; + +void MN_Init(void); +void MN_ActivateMenu(void); +void MN_DeactivateMenu(void); +boolean MN_Responder(event_t * event); +void MN_Ticker(void); +void MN_Drawer(void); +void MN_DrTextA(const char *text, int x, int y); +int MN_TextAWidth(const char *text); +void MN_DrTextB(const char *text, int x, int y); +int MN_TextBWidth(const char *text); + +#include "sounds.h" + +#endif // __DOOMDEF__ diff --git a/games/NXDoom/src/heretic/dstrings.h b/games/NXDoom/src/heretic/dstrings.h new file mode 100644 index 00000000000..54bb97607c0 --- /dev/null +++ b/games/NXDoom/src/heretic/dstrings.h @@ -0,0 +1,244 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// DStrings.h + +//--------------------------------------------------------------------------- +// +// P_inter.c +// +//--------------------------------------------------------------------------- + +// Keys + +#define TXT_GOTBLUEKEY "BLUE KEY" +#define TXT_GOTYELLOWKEY "YELLOW KEY" +#define TXT_GOTGREENKEY "GREEN KEY" + +// Artifacts + +#define TXT_ARTIHEALTH "QUARTZ FLASK" +#define TXT_ARTIFLY "WINGS OF WRATH" +#define TXT_ARTIINVULNERABILITY "RING OF INVINCIBILITY" +#define TXT_ARTITOMEOFPOWER "TOME OF POWER" +#define TXT_ARTIINVISIBILITY "SHADOWSPHERE" +#define TXT_ARTIEGG "MORPH OVUM" +#define TXT_ARTISUPERHEALTH "MYSTIC URN" +#define TXT_ARTITORCH "TORCH" +#define TXT_ARTIFIREBOMB "TIME BOMB OF THE ANCIENTS" +#define TXT_ARTITELEPORT "CHAOS DEVICE" + +// Items + +#define TXT_ITEMHEALTH "CRYSTAL VIAL" +#define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING" +#define TXT_ITEMSHIELD1 "SILVER SHIELD" +#define TXT_ITEMSHIELD2 "ENCHANTED SHIELD" +#define TXT_ITEMSUPERMAP "MAP SCROLL" + +// Ammo + +#define TXT_AMMOGOLDWAND1 "WAND CRYSTAL" +#define TXT_AMMOGOLDWAND2 "CRYSTAL GEODE" +#define TXT_AMMOMACE1 "MACE SPHERES" +#define TXT_AMMOMACE2 "PILE OF MACE SPHERES" +#define TXT_AMMOCROSSBOW1 "ETHEREAL ARROWS" +#define TXT_AMMOCROSSBOW2 "QUIVER OF ETHEREAL ARROWS" +#define TXT_AMMOBLASTER1 "CLAW ORB" +#define TXT_AMMOBLASTER2 "ENERGY ORB" +#define TXT_AMMOSKULLROD1 "LESSER RUNES" +#define TXT_AMMOSKULLROD2 "GREATER RUNES" +#define TXT_AMMOPHOENIXROD1 "FLAME ORB" +#define TXT_AMMOPHOENIXROD2 "INFERNO ORB" + +// Weapons + +#define TXT_WPNMACE "FIREMACE" +#define TXT_WPNCROSSBOW "ETHEREAL CROSSBOW" +#define TXT_WPNBLASTER "DRAGON CLAW" +#define TXT_WPNSKULLROD "HELLSTAFF" +#define TXT_WPNPHOENIXROD "PHOENIX ROD" +#define TXT_WPNGAUNTLETS "GAUNTLETS OF THE NECROMANCER" + +//--------------------------------------------------------------------------- +// +// SB_bar.c +// +//--------------------------------------------------------------------------- + +#define TXT_CHEATGODON "GOD MODE ON" +#define TXT_CHEATGODOFF "GOD MODE OFF" +#define TXT_CHEATNOCLIPON "NO CLIPPING ON" +#define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF" +#define TXT_CHEATWEAPONS "ALL WEAPONS" +#define TXT_CHEATFLIGHTON "FLIGHT ON" +#define TXT_CHEATFLIGHTOFF "FLIGHT OFF" +#define TXT_CHEATPOWERON "POWER ON" +#define TXT_CHEATPOWEROFF "POWER OFF" +#define TXT_CHEATHEALTH "FULL HEALTH" +#define TXT_CHEATKEYS "ALL KEYS" +#define TXT_CHEATSOUNDON "SOUND DEBUG ON" +#define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF" +#define TXT_CHEATTICKERON "TICKER ON" +#define TXT_CHEATTICKEROFF "TICKER OFF" +#define TXT_CHEATARTIFACTS1 "CHOOSE AN ARTIFACT ( A - J )" +#define TXT_CHEATARTIFACTS2 "HOW MANY ( 1 - 9 )" +#define TXT_CHEATARTIFACTS3 "YOU GOT IT" +#define TXT_CHEATARTIFACTSFAIL "BAD INPUT" +#define TXT_CHEATWARP "LEVEL WARP" +#define TXT_CHEATSCREENSHOT "SCREENSHOT" +#define TXT_CHEATCHICKENON "CHICKEN ON" +#define TXT_CHEATCHICKENOFF "CHICKEN OFF" +#define TXT_CHEATMASSACRE "MASSACRE" +#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!" +#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS" + +//--------------------------------------------------------------------------- +// +// P_doors.c +// +//--------------------------------------------------------------------------- + +#define TXT_NEEDBLUEKEY "YOU NEED A BLUE KEY TO OPEN THIS DOOR" +#define TXT_NEEDGREENKEY "YOU NEED A GREEN KEY TO OPEN THIS DOOR" +#define TXT_NEEDYELLOWKEY "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" + +//--------------------------------------------------------------------------- +// +// G_game.c +// +//--------------------------------------------------------------------------- + +#define TXT_GAMESAVED "GAME SAVED" + +//--------------------------------------------------------------------------- +// +// AM_map.c +// +//--------------------------------------------------------------------------- + +#define AMSTR_FOLLOWON "FOLLOW MODE ON" +#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF" + +#define AMSTR_GRIDON "Grid ON" +#define AMSTR_GRIDOFF "Grid OFF" + +#define AMSTR_MARKEDSPOT "Marked Spot" +#define AMSTR_MARKSCLEARED "All Marks Cleared" + +//--------------------------------------------------------------------------- +// +// F_finale.c +// +//--------------------------------------------------------------------------- + +#define E1TEXT "with the destruction of the iron\n"\ + "liches and their minions, the last\n"\ + "of the undead are cleared from this\n"\ + "plane of existence.\n\n"\ + "those creatures had to come from\n"\ + "somewhere, though, and you have the\n"\ + "sneaky suspicion that the fiery\n"\ + "portal of hell's maw opens onto\n"\ + "their home dimension.\n\n"\ + "to make sure that more undead\n"\ + "(or even worse things) don't come\n"\ + "through, you'll have to seal hell's\n"\ + "maw from the other side. of course\n"\ + "this means you may get stuck in a\n"\ + "very unfriendly world, but no one\n"\ + "ever said being a Heretic was easy!" + +#define E2TEXT "the mighty maulotaurs have proved\n"\ + "to be no match for you, and as\n"\ + "their steaming corpses slide to the\n"\ + "ground you feel a sense of grim\n"\ + "satisfaction that they have been\n"\ + "destroyed.\n\n"\ + "the gateways which they guarded\n"\ + "have opened, revealing what you\n"\ + "hope is the way home. but as you\n"\ + "step through, mocking laughter\n"\ + "rings in your ears.\n\n"\ + "was some other force controlling\n"\ + "the maulotaurs? could there be even\n"\ + "more horrific beings through this\n"\ + "gate? the sweep of a crystal dome\n"\ + "overhead where the sky should be is\n"\ + "certainly not a good sign...." + +#define E3TEXT "the death of d'sparil has loosed\n"\ + "the magical bonds holding his\n"\ + "creatures on this plane, their\n"\ + "dying screams overwhelming his own\n"\ + "cries of agony.\n\n"\ + "your oath of vengeance fulfilled,\n"\ + "you enter the portal to your own\n"\ + "world, mere moments before the dome\n"\ + "shatters into a million pieces.\n\n"\ + "but if d'sparil's power is broken\n"\ + "forever, why don't you feel safe?\n"\ + "was it that last shout just before\n"\ + "his death, the one that sounded\n"\ + "like a curse? or a summoning? you\n"\ + "can't really be sure, but it might\n"\ + "just have been a scream.\n\n"\ + "then again, what about the other\n"\ + "serpent riders?" + +#define E4TEXT "you thought you would return to your\n"\ + "own world after d'sparil died, but\n"\ + "his final act banished you to his\n"\ + "own plane. here you entered the\n"\ + "shattered remnants of lands\n"\ + "conquered by d'sparil. you defeated\n"\ + "the last guardians of these lands,\n"\ + "but now you stand before the gates\n"\ + "to d'sparil's stronghold. until this\n"\ + "moment you had no doubts about your\n"\ + "ability to face anything you might\n"\ + "encounter, but beyond this portal\n"\ + "lies the very heart of the evil\n"\ + "which invaded your world. d'sparil\n"\ + "might be dead, but the pit where he\n"\ + "was spawned remains. now you must\n"\ + "enter that pit in the hopes of\n"\ + "finding a way out. and somewhere,\n"\ + "in the darkest corner of d'sparil's\n"\ + "demesne, his personal bodyguards\n"\ + "await your arrival ..." + +#define E5TEXT "as the final maulotaur bellows his\n"\ + "death-agony, you realize that you\n"\ + "have never come so close to your own\n"\ + "destruction. not even the fight with\n"\ + "d'sparil and his disciples had been\n"\ + "this desperate. grimly you stare at\n"\ + "the gates which open before you,\n"\ + "wondering if they lead home, or if\n"\ + "they open onto some undreamed-of\n"\ + "horror. you find yourself wondering\n"\ + "if you have the strength to go on,\n"\ + "if nothing but death and pain await\n"\ + "you. but what else can you do, if\n"\ + "the will to fight is gone? can you\n"\ + "force yourself to continue in the\n"\ + "face of such despair? do you have\n"\ + "the courage? you find, in the end,\n"\ + "that it is not within you to\n"\ + "surrender without a fight. eyes\n"\ + "wide, you go to meet your fate." + diff --git a/games/NXDoom/src/heretic/f_finale.c b/games/NXDoom/src/heretic/f_finale.c new file mode 100644 index 00000000000..4508bd3a3c8 --- /dev/null +++ b/games/NXDoom/src/heretic/f_finale.c @@ -0,0 +1,436 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// F_finale.c + +#include + +#include "doomdef.h" +#include "deh_str.h" +#include "i_swap.h" +#include "i_video.h" +#include "s_sound.h" +#include "v_video.h" +#include "am_map.h" + +static int finalestage; // 0 = text, 1 = art screen +static int finalecount; + +#define TEXTSPEED 3 +#define TEXTWAIT 250 + +static const char *finaletext; +static const char *finaleflat; + +static int FontABaseLump; + + +/* +======================= += += F_StartFinale += +======================= +*/ + +void F_StartFinale(void) +{ + gameaction = ga_nothing; + gamestate = GS_FINALE; + viewactive = false; + automapactive = false; + players[consoleplayer].messageTics = 1; + players[consoleplayer].message = NULL; + + switch (gameepisode) + { + case 1: + finaleflat = DEH_String("FLOOR25"); + finaletext = DEH_String(E1TEXT); + break; + case 2: + finaleflat = DEH_String("FLATHUH1"); + finaletext = DEH_String(E2TEXT); + break; + case 3: + finaleflat = DEH_String("FLTWAWA2"); + finaletext = DEH_String(E3TEXT); + break; + case 4: + finaleflat = DEH_String("FLOOR28"); + finaletext = DEH_String(E4TEXT); + break; + case 5: + finaleflat = DEH_String("FLOOR08"); + finaletext = DEH_String(E5TEXT); + break; + } + + finalestage = 0; + finalecount = 0; + FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; + +// S_ChangeMusic(mus_victor, true); + S_StartSong(mus_cptd, true); +} + + + +boolean F_Responder(event_t * event) +{ + if (event->type != ev_keydown) + { + return false; + } + if (finalestage == 1 && gameepisode == 2) + { // we're showing the water pic, make any key kick to demo mode + finalestage++; + /* + memset((byte *) 0xa0000, 0, SCREENWIDTH * SCREENHEIGHT); + memset(I_VideoBuffer, 0, SCREENWIDTH * SCREENHEIGHT); + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + */ + return true; + } + return false; +} + + +/* +======================= += += F_Ticker += +======================= +*/ + +void F_Ticker(void) +{ + finalecount++; + if (!finalestage + && finalecount > strlen(finaletext) * TEXTSPEED + TEXTWAIT) + { + finalecount = 0; + if (!finalestage) + { + finalestage = 1; + } + +// wipegamestate = -1; // force a wipe +/* + if (gameepisode == 3) + S_StartMusic (mus_bunny); +*/ + } +} + + +/* +======================= += += F_TextWrite += +======================= +*/ + + +void F_TextWrite(void) +{ + byte *src, *dest; + int x, y; + int count; + const char *ch; + int c; + int cx, cy; + patch_t *w; + +// +// erase the entire screen to a tiled background +// + src = W_CacheLumpName(finaleflat, PU_CACHE); + dest = I_VideoBuffer; + for (y = 0; y < SCREENHEIGHT; y++) + { + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } + +// V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); + +// +// draw some of the text onto the screen +// + cx = 20; + cy = 5; + ch = finaletext; + + count = (finalecount - 10) / TEXTSPEED; + if (count < 0) + count = 0; + for (; count; count--) + { + c = *ch++; + if (!c) + break; + if (c == '\n') + { + cx = 20; + cy += 9; + continue; + } + + c = toupper(c); + if (c < 33) + { + cx += 5; + continue; + } + + w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + if (cx + SHORT(w->width) > SCREENWIDTH) + break; + V_DrawPatch(cx, cy, w); + cx += SHORT(w->width); + } + +} + + +void F_DrawPatchCol(int x, patch_t * patch, int col) +{ + column_t *column; + byte *source, *dest, *desttop; + int count; + + column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + desttop = I_VideoBuffer + x; + +// step through the posts in a column + + while (column->topdelta != 0xff) + { + source = (byte *) column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = *source++; + dest += SCREENWIDTH; + } + column = (column_t *) ((byte *) column + column->length + 4); + } +} + +/* +================== += += F_DemonScroll += +================== +*/ + +void F_DemonScroll(void) +{ + byte *p1, *p2; + static int yval = 0; + static int nextscroll = 0; + + if (finalecount < nextscroll) + { + return; + } + p1 = W_CacheLumpName(DEH_String("FINAL1"), PU_LEVEL); + p2 = W_CacheLumpName(DEH_String("FINAL2"), PU_LEVEL); + if (finalecount < 70) + { + memcpy(I_VideoBuffer, p1, SCREENHEIGHT * SCREENWIDTH); + nextscroll = finalecount; + return; + } + if (yval < 64000) + { + memcpy(I_VideoBuffer, p2 + SCREENHEIGHT * SCREENWIDTH - yval, yval); + memcpy(I_VideoBuffer + yval, p1, SCREENHEIGHT * SCREENWIDTH - yval); + yval += SCREENWIDTH; + nextscroll = finalecount + 3; + } + else + { //else, we'll just sit here and wait, for now + memcpy(I_VideoBuffer, p2, SCREENWIDTH * SCREENHEIGHT); + } +} + +/* +================== += += F_DrawUnderwater += +================== +*/ + +void F_DrawUnderwater(void) +{ + static boolean underwawa = false; + const char *lumpname; + byte *palette; + + // The underwater screen has its own palette, which is rather annoying. + // The palette doesn't correspond to the normal palette. Because of + // this, we must regenerate the lookup tables used in the video scaling + // code. + + switch (finalestage) + { + case 1: + if (!underwawa) + { + underwawa = true; + V_DrawFilledBox(0, 0, SCREENWIDTH, SCREENHEIGHT, 0); + lumpname = DEH_String("E2PAL"); + palette = W_CacheLumpName(lumpname, PU_STATIC); + I_SetPalette(palette); + W_ReleaseLumpName(lumpname); + V_DrawRawScreen(W_CacheLumpName(DEH_String("E2END"), PU_CACHE)); + } + paused = false; + MenuActive = false; + askforquit = false; + + break; + case 2: + if (underwawa) + { + lumpname = DEH_String("PLAYPAL"); + palette = W_CacheLumpName(lumpname, PU_STATIC); + I_SetPalette(palette); + W_ReleaseLumpName(lumpname); + underwawa = false; + } + V_DrawRawScreen(W_CacheLumpName(DEH_String("TITLE"), PU_CACHE)); + //D_StartTitle(); // go to intro/demo mode. + } +} + + +#if 0 +/* +================== += += F_BunnyScroll += +================== +*/ + +void F_BunnyScroll(void) +{ + int scrolled, x; + patch_t *p1, *p2; + char name[10]; + int stage; + static int laststage; + + p1 = W_CacheLumpName("PFUB2", PU_LEVEL); + p2 = W_CacheLumpName("PFUB1", PU_LEVEL); + + V_MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT); + + scrolled = 320 - (finalecount - 230) / 2; + if (scrolled > 320) + scrolled = 320; + if (scrolled < 0) + scrolled = 0; + + for (x = 0; x < SCREENWIDTH; x++) + { + if (x + scrolled < 320) + F_DrawPatchCol(x, p1, x + scrolled); + else + F_DrawPatchCol(x, p2, x + scrolled - 320); + } + + if (finalecount < 1130) + return; + if (finalecount < 1180) + { + V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, 0, + W_CacheLumpName("END0", PU_CACHE)); + laststage = 0; + return; + } + + stage = (finalecount - 1180) / 5; + if (stage > 6) + stage = 6; + if (stage > laststage) + { + S_StartSound(NULL, sfx_pistol); + laststage = stage; + } + + M_snprintf(name, sizeof(name), "END%i", stage); + V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, + W_CacheLumpName(name, PU_CACHE)); +} +#endif + +/* +======================= += += F_Drawer += +======================= +*/ + +void F_Drawer(void) +{ + UpdateState |= I_FULLSCRN; + if (!finalestage) + F_TextWrite(); + else + { + switch (gameepisode) + { + case 1: + if (gamemode == shareware) + { + V_DrawRawScreen(W_CacheLumpName("ORDER", PU_CACHE)); + } + else + { + V_DrawRawScreen(W_CacheLumpName("CREDIT", PU_CACHE)); + } + break; + case 2: + F_DrawUnderwater(); + break; + case 3: + F_DemonScroll(); + break; + case 4: // Just show credits screen for extended episodes + case 5: + V_DrawRawScreen(W_CacheLumpName("CREDIT", PU_CACHE)); + break; + } + } +} diff --git a/games/NXDoom/src/heretic/g_game.c b/games/NXDoom/src/heretic/g_game.c new file mode 100644 index 00000000000..01bcc4aebae --- /dev/null +++ b/games/NXDoom/src/heretic/g_game.c @@ -0,0 +1,2284 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// G_game.c + +#include +#include +#include +#include "doomdef.h" +#include "doomkeys.h" +#include "deh_str.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_timer.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +// Macros + +#define AM_STARTKEY 9 + +// Functions + +void G_ReadDemoTiccmd(ticcmd_t * cmd); +void G_WriteDemoTiccmd(ticcmd_t * cmd); +void G_PlayerReborn(int player); + +void G_DoReborn(int playernum); + +void G_DoLoadLevel(void); +void G_DoNewGame(void); +void G_DoPlayDemo(void); +void G_DoCompleted(void); +void G_DoVictory(void); +void G_DoWorldDone(void); +void G_DoSaveGame(void); + +void D_PageTicker(void); +void D_AdvanceDemo(void); + +static boolean InventoryMoveLeft(); +static boolean InventoryMoveRight(); + +struct +{ + int type; // mobjtype_t + int speed[2]; +} MonsterMissileInfo[] = { + { MT_IMPBALL, { 10, 20 } }, + { MT_MUMMYFX1, { 9, 18 } }, + { MT_KNIGHTAXE, { 9, 18 } }, + { MT_REDAXE, { 9, 18 } }, + { MT_BEASTBALL, { 12, 20 } }, + { MT_WIZFX1, { 18, 24 } }, + { MT_SNAKEPRO_A, { 14, 20 } }, + { MT_SNAKEPRO_B, { 14, 20 } }, + { MT_HEADFX1, { 13, 20 } }, + { MT_HEADFX3, { 10, 18 } }, + { MT_MNTRFX1, { 20, 26 } }, + { MT_MNTRFX2, { 14, 20 } }, + { MT_SRCRFX1, { 20, 28 } }, + { MT_SOR2FX1, { 20, 28 } }, + { -1, { -1, -1 } } // Terminator +}; + +gameaction_t gameaction; +gamestate_t gamestate; +skill_t gameskill; +boolean respawnmonsters; +int gameepisode; +int gamemap; +int prevmap; + +boolean paused; +boolean sendpause; // send a pause event next tic +boolean sendsave; // send a save event next tic +boolean usergame; // ok to save / end game + +boolean timingdemo; // if true, exit with report on completion +int starttime; // for comparative timing purposes + +boolean viewactive; + +boolean deathmatch; // only if started as net death +boolean netgame; // only true if packets are broadcast +boolean playeringame[MAXPLAYERS]; +player_t players[MAXPLAYERS]; + +int consoleplayer; // player taking events and displaying +int displayplayer; // view being displayed +int levelstarttic; // gametic at level start +int totalkills, totalitems, totalsecret; // for intermission + +int mouseSensitivity; + +char *demoname; +boolean demorecording; +boolean longtics; // specify high resolution turning in demos +boolean lowres_turn; +boolean shortticfix; // calculate lowres turning like doom +boolean demoplayback; +boolean netdemo; +boolean demoextend; +byte *demobuffer, *demo_p, *demoend; +boolean singledemo; // quit after playing a demo from cmdline + +boolean precache = true; // if true, load all graphics at start + +// TODO: Heretic uses 16-bit shorts for consistency? +byte consistancy[MAXPLAYERS][BACKUPTICS]; +char *savegamedir; + +boolean testcontrols = false; +int testcontrols_mousespeed; + + +// +// controls (have defaults) +// + + + +#define MAXPLMOVE 0x32 + +fixed_t forwardmove[2] = { 0x19, 0x32 }; +fixed_t sidemove[2] = { 0x18, 0x28 }; +fixed_t angleturn[3] = { 640, 1280, 320 }; // + slow turn + +static int *weapon_keys[] = +{ + &key_weapon1, + &key_weapon2, + &key_weapon3, + &key_weapon4, + &key_weapon5, + &key_weapon6, + &key_weapon7 +}; + +// Set to -1 or +1 to switch to the previous or next weapon. + +static int next_weapon = 0; + +// Used for prev/next weapon keys. + +static const struct +{ + weapontype_t weapon; + weapontype_t weapon_num; +} weapon_order_table[] = { + { wp_staff, wp_staff }, + { wp_gauntlets, wp_staff }, + { wp_goldwand, wp_goldwand }, + { wp_crossbow, wp_crossbow }, + { wp_blaster, wp_blaster }, + { wp_skullrod, wp_skullrod }, + { wp_phoenixrod, wp_phoenixrod }, + { wp_mace, wp_mace }, + { wp_beak, wp_beak }, +}; + +#define SLOWTURNTICS 6 + +#define NUMKEYS 256 +boolean gamekeydown[NUMKEYS]; +int turnheld; // for accelerative turning +int lookheld; + + +boolean mousearray[MAX_MOUSE_BUTTONS + 1]; +boolean *mousebuttons = &mousearray[1]; + // allow [-1] +int mousex, mousey; // mouse values are used once +int dclicktime, dclickstate, dclicks; +int dclicktime2, dclickstate2, dclicks2; + +#define MAX_JOY_BUTTONS 20 + +int joyxmove, joyymove; // joystick values are repeated +int joystrafemove; +int joylook; +boolean joyarray[MAX_JOY_BUTTONS + 1]; +boolean *joybuttons = &joyarray[1]; // allow [-1] + +int savegameslot; +char savedescription[32]; + +int vanilla_demo_limit = 1; + +int inventoryTics; + +// haleyjd: removed WATCOMC + +//============================================================================= +// Not used - ripped out for Heretic +/* +int G_CmdChecksum(ticcmd_t *cmd) +{ + int i; + int sum; + + sum = 0; + for(i = 0; i < sizeof(*cmd)/4-1; i++) + { + sum += ((int *)cmd)[i]; + } + return(sum); +} +*/ + +static boolean WeaponSelectable(weapontype_t weapon) +{ + if (weapon == wp_beak) + { + return false; + } + + return players[consoleplayer].weaponowned[weapon]; +} + +static int G_NextWeapon(int direction) +{ + weapontype_t weapon; + int start_i, i; + + // Find index in the table. + + if (players[consoleplayer].pendingweapon == wp_nochange) + { + weapon = players[consoleplayer].readyweapon; + } + else + { + weapon = players[consoleplayer].pendingweapon; + } + + for (i=0; i= arrlen(weapon_order_table)) { + I_Error("Internal error: weapon %d not present in weapon_order_table", weapon); + } + + // Switch weapon. Don't loop forever. + start_i = i; + do + { + i += direction; + i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); + } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon)); + + return weapon_order_table[i].weapon_num; +} + +/* +==================== += += G_BuildTiccmd += += Builds a ticcmd from all of the available inputs or reads it from the += demo buffer. += If recording a demo, write it out +==================== +*/ + + +boolean usearti = true; + +void G_BuildTiccmd(ticcmd_t *cmd, int maketic) +{ + int i; + boolean strafe, bstrafe; + int speed, tspeed, lspeed; + int forward, side; + int look, arti; + int flyheight; + + // haleyjd: removed externdriver crap + + memset(cmd, 0, sizeof(*cmd)); + //cmd->consistancy = + // consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS]; + cmd->consistancy = consistancy[consoleplayer][maketic % BACKUPTICS]; + +//printf ("cons: %i\n",cmd->consistancy); + + strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] + || joybuttons[joybstrafe]; + speed = joybspeed >= MAX_JOY_BUTTONS + || gamekeydown[key_speed] + || joybuttons[joybspeed] + || mousebuttons[mousebspeed]; + + // haleyjd: removed externdriver crap + + forward = side = look = arti = flyheight = 0; + +// +// use two stage accelerative turning on the keyboard and joystick +// + if (joyxmove < 0 || joyxmove > 0 + || gamekeydown[key_right] || gamekeydown[key_left] + || mousebuttons[mousebturnright] || mousebuttons[mousebturnleft]) + turnheld += ticdup; + else + turnheld = 0; + if (turnheld < SLOWTURNTICS) + tspeed = 2; // slow turn + else + tspeed = speed; + + if (gamekeydown[key_lookdown] || gamekeydown[key_lookup]) + { + lookheld += ticdup; + } + else + { + lookheld = 0; + } + if (lookheld < SLOWTURNTICS) + { + lspeed = 1; + } + else + { + lspeed = 2; + } + +// +// let movement keys cancel each other out +// + if (strafe) + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + side += sidemove[speed]; + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + side -= sidemove[speed]; + if (use_analog && joyxmove) + { + joyxmove = joyxmove * joystick_move_sensitivity / 10; + joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; + joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; + side += FixedMul(sidemove[speed], joyxmove); + } + else if (joystick_move_sensitivity) + { + if (joyxmove > 0) + side += sidemove[speed]; + if (joyxmove < 0) + side -= sidemove[speed]; + } + } + else + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + cmd->angleturn -= angleturn[tspeed]; + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + cmd->angleturn += angleturn[tspeed]; + if (use_analog && joyxmove) + { + // Cubic response curve allows for finer control when stick + // deflection is small. + joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); + joyxmove = joyxmove * joystick_turn_sensitivity / 10; + cmd->angleturn -= FixedMul(angleturn[1], joyxmove); + } + else if (joystick_turn_sensitivity) + { + if (joyxmove > 0) + cmd->angleturn -= angleturn[tspeed]; + if (joyxmove < 0) + cmd->angleturn += angleturn[tspeed]; + } + } + + if (gamekeydown[key_up]) + forward += forwardmove[speed]; + if (gamekeydown[key_down]) + forward -= forwardmove[speed]; + if (use_analog && joyymove) + { + joyymove = joyymove * joystick_move_sensitivity / 10; + joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; + joyymove = (joyymove < -FRACUNIT) ? FRACUNIT : joyymove; + forward -= FixedMul(forwardmove[speed], joyymove); + } + else if (joystick_move_sensitivity) + { + if (joyymove < 0) + forward += forwardmove[speed]; + if (joyymove > 0) + forward -= forwardmove[speed]; + } + if (gamekeydown[key_straferight] || mousebuttons[mousebstraferight] + || joybuttons[joybstraferight]) + side += sidemove[speed]; + if (gamekeydown[key_strafeleft] || mousebuttons[mousebstrafeleft] + || joybuttons[joybstrafeleft]) + side -= sidemove[speed]; + + if (use_analog && joystrafemove) + { + joystrafemove = joystrafemove * joystick_move_sensitivity / 10; + joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; + joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; + side += FixedMul(sidemove[speed], joystrafemove); + } + else if (joystick_move_sensitivity) + { + if (joystrafemove < 0) + side -= sidemove[speed]; + if (joystrafemove > 0) + side += sidemove[speed]; + } + // Look up/down/center keys + if (gamekeydown[key_lookup]) + { + look = lspeed; + } + if (gamekeydown[key_lookdown]) + { + look = -lspeed; + } + if (use_analog && joylook) + { + joylook = joylook * joystick_look_sensitivity / 10; + joylook = (joylook > FRACUNIT) ? FRACUNIT : joylook; + joylook = (joylook < -FRACUNIT) ? -FRACUNIT : joylook; + look = -FixedMul(2, joylook); + } + else if (joystick_look_sensitivity) + { + if (joylook < 0) + { + look = lspeed; + } + + if (joylook > 0) + { + look = -lspeed; + } + } + // haleyjd: removed externdriver crap + if (gamekeydown[key_lookcenter]) + { + look = TOCENTER; + } + + // haleyjd: removed externdriver crap + + // Fly up/down/drop keys + if (gamekeydown[key_flyup] || joybuttons[joybflyup]) + { + flyheight = 5; // note that the actual flyheight will be twice this + } + if (gamekeydown[key_flydown] || joybuttons[joybflydown]) + { + flyheight = -5; + } + if (gamekeydown[key_flycenter] || joybuttons[joybflycenter]) + { + flyheight = TOCENTER; + // haleyjd: removed externdriver crap + look = TOCENTER; + } + + // Use artifact key + if (gamekeydown[key_useartifact] || mousebuttons[mousebuseartifact] + || joybuttons[joybuseartifact]) + { + if (gamekeydown[key_speed] && !noartiskip) + { + if (players[consoleplayer].inventory[inv_ptr].type != arti_none) + { + gamekeydown[key_useartifact] = false; + mousebuttons[mousebuseartifact] = false; + cmd->arti = 0xff; // skip artifact code + } + } + else + { + if (inventory) + { + players[consoleplayer].readyArtifact = + players[consoleplayer].inventory[inv_ptr].type; + inventory = false; + cmd->arti = 0; + usearti = false; + } + else if (usearti) + { + cmd->arti = players[consoleplayer].inventory[inv_ptr].type; + usearti = false; + } + } + } + if (gamekeydown[key_arti_tome] && !cmd->arti + && !players[consoleplayer].powers[pw_weaponlevel2]) + { + gamekeydown[key_arti_tome] = false; + cmd->arti = arti_tomeofpower; + } + else if (gamekeydown[key_arti_quartz] && !cmd->arti + && (players[consoleplayer].mo->health < MAXHEALTH)) + { + gamekeydown[key_arti_quartz] = false; + cmd->arti = arti_health; + } + else if (gamekeydown[key_arti_urn] && !cmd->arti) + { + gamekeydown[key_arti_urn] = false; + cmd->arti = arti_superhealth; + } + else if (gamekeydown[key_arti_bomb] && !cmd->arti) + { + gamekeydown[key_arti_bomb] = false; + cmd->arti = arti_firebomb; + } + else if (gamekeydown[key_arti_ring] && !cmd->arti) + { + gamekeydown[key_arti_ring] = false; + cmd->arti = arti_invulnerability; + } + else if (gamekeydown[key_arti_chaosdevice] && !cmd->arti) + { + gamekeydown[key_arti_chaosdevice] = false; + cmd->arti = arti_teleport; + } + else if (gamekeydown[key_arti_shadowsphere] && !cmd->arti) + { + gamekeydown[key_arti_shadowsphere] = false; + cmd->arti = arti_invisibility; + } + else if (gamekeydown[key_arti_wings] && !cmd->arti) + { + gamekeydown[key_arti_wings] = false; + cmd->arti = arti_fly; + } + else if (gamekeydown[key_arti_torch] && !cmd->arti) + { + gamekeydown[key_arti_torch] = false; + cmd->arti = arti_torch; + } + else if (gamekeydown[key_arti_morph] && !cmd->arti) + { + gamekeydown[key_arti_morph] = false; + cmd->arti = arti_egg; + } + +// +// buttons +// + cmd->chatchar = CT_dequeueChatChar(); + + if (gamekeydown[key_fire] || mousebuttons[mousebfire] + || joybuttons[joybfire]) + cmd->buttons |= BT_ATTACK; + + if (gamekeydown[key_use] || joybuttons[joybuse] || mousebuttons[mousebuse]) + { + cmd->buttons |= BT_USE; + dclicks = 0; // clear double clicks if hit use button + } + + // If the previous or next weapon button is pressed, the + // next_weapon variable is set to change weapons when + // we generate a ticcmd. Choose a new weapon. + // (Can't weapon cycle when the player is a chicken) + + if (gamestate == GS_LEVEL + && players[consoleplayer].chickenTics == 0 && next_weapon != 0) + { + i = G_NextWeapon(next_weapon); + cmd->buttons |= BT_CHANGE; + cmd->buttons |= i << BT_WEAPONSHIFT; + } + else + { + for (i=0; ibuttons |= BT_CHANGE; + cmd->buttons |= i< 1) + { + dclickstate = mousebuttons[mousebforward]; + if (dclickstate) + dclicks++; + if (dclicks == 2) + { + cmd->buttons |= BT_USE; + dclicks = 0; + } + else + dclicktime = 0; + } + else + { + dclicktime += ticdup; + if (dclicktime > 20) + { + dclicks = 0; + dclickstate = 0; + } + } + + // + // strafe double click + // + + bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; + if (bstrafe != dclickstate2 && dclicktime2 > 1) + { + dclickstate2 = bstrafe; + if (dclickstate2) + dclicks2++; + if (dclicks2 == 2) + { + cmd->buttons |= BT_USE; + dclicks2 = 0; + } + else + dclicktime2 = 0; + } + else + { + dclicktime2 += ticdup; + if (dclicktime2 > 20) + { + dclicks2 = 0; + dclickstate2 = 0; + } + } + } + + if (strafe) + { + side += mousex * 2; + } + else + { + cmd->angleturn -= mousex * 0x8; + } + + // No mouse movement in previous frame? + + if (mousex == 0) + { + testcontrols_mousespeed = 0; + } + + forward += mousey; + mousex = mousey = 0; + + if (forward > MAXPLMOVE) + forward = MAXPLMOVE; + else if (forward < -MAXPLMOVE) + forward = -MAXPLMOVE; + if (side > MAXPLMOVE) + side = MAXPLMOVE; + else if (side < -MAXPLMOVE) + side = -MAXPLMOVE; + + cmd->forwardmove += forward; + cmd->sidemove += side; + if (players[consoleplayer].playerstate == PST_LIVE) + { + if (look < 0) + { + look += 16; + } + cmd->lookfly = look; + } + if (flyheight < 0) + { + flyheight += 16; + } + cmd->lookfly |= flyheight << 4; + +// +// special buttons +// + if (sendpause) + { + sendpause = false; + cmd->buttons = BT_SPECIAL | BTS_PAUSE; + } + + if (sendsave) + { + sendsave = false; + cmd->buttons = + BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT); + } + + if (lowres_turn) + { + if (shortticfix) + { + static signed short carry = 0; + signed short desired_angleturn; + + desired_angleturn = cmd->angleturn + carry; + + // round angleturn to the nearest 256 unit boundary + // for recording demos with single byte values for turn + + cmd->angleturn = (desired_angleturn + 128) & 0xff00; + + // Carry forward the error from the reduced resolution to the + // next tic, so that successive small movements can accumulate. + + carry = desired_angleturn - cmd->angleturn; + } + else + { + // truncate angleturn to the nearest 256 boundary + // for recording demos with single byte values for turn + cmd->angleturn &= 0xff00; + } + } +} + + +/* +============== += += G_DoLoadLevel += +============== +*/ + +void G_DoLoadLevel(void) +{ + int i; + + levelstarttic = gametic; // for time calculation + gamestate = GS_LEVEL; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].playerstate == PST_DEAD) + players[i].playerstate = PST_REBORN; + memset(players[i].frags, 0, sizeof(players[i].frags)); + } + + P_SetupLevel(gameepisode, gamemap, 0, gameskill); + displayplayer = consoleplayer; // view the guy you are playing + gameaction = ga_nothing; + Z_CheckHeap(); + +// +// clear cmd building stuff +// + + memset(gamekeydown, 0, sizeof(gamekeydown)); + joyxmove = joyymove = joystrafemove = joylook = 0; + mousex = mousey = 0; + sendpause = sendsave = paused = false; + memset(mousearray, 0, sizeof(mousearray)); + memset(joyarray, 0, sizeof(joyarray)); + + if (testcontrols) + { + P_SetMessage(&players[consoleplayer], "PRESS ESCAPE TO QUIT.", false); + } +} + +static void SetJoyButtons(unsigned int buttons_mask) +{ + int i; + player_t* plr; + + plr = &players[consoleplayer]; + + for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; + } + usearti = true; + } + } + + joybuttons[i] = button_on; + } +} + +// If an InventoryMove*() function is called when the inventory is not active, +// it will instead activate the inventory without attempting to change the +// selected item. This action is indicated by a return value of false. +// Otherwise, it attempts to change items and will return a value of true. + +static boolean InventoryMoveLeft() +{ + inventoryTics = 5 * 35; + if (!inventory) + { + inventory = true; + return false; + } + inv_ptr--; + if (inv_ptr < 0) + { + inv_ptr = 0; + } + else + { + curpos--; + if (curpos < 0) + { + curpos = 0; + } + } + return true; +} + +static boolean InventoryMoveRight() +{ + player_t *plr; + + plr = &players[consoleplayer]; + inventoryTics = 5 * 35; + if (!inventory) + { + inventory = true; + return false; + } + inv_ptr++; + if (inv_ptr >= plr->inventorySlotNum) + { + inv_ptr--; + if (inv_ptr < 0) + inv_ptr = 0; + } + else + { + curpos++; + if (curpos > 6) + { + curpos = 6; + } + } + return true; +} + +static void SetMouseButtons(unsigned int buttons_mask) +{ + int i; + player_t *plr; + + plr = &players[consoleplayer]; + + for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; + } + usearti = true; + } + } + + mousebuttons[i] = button_on; + } +} + +/* +=============================================================================== += += G_Responder += += get info needed to make ticcmd_ts for the players += +=============================================================================== +*/ + +boolean G_Responder(event_t * ev) +{ + player_t *plr; + + plr = &players[consoleplayer]; + if (ev->type == ev_keyup && ev->data1 == key_useartifact) + { // flag to denote that it's okay to use an artifact + if (!inventory) + { + plr->readyArtifact = plr->inventory[inv_ptr].type; + } + usearti = true; + } + + // Check for spy mode player cycle + if (gamestate == GS_LEVEL && ev->type == ev_keydown + && ev->data1 == KEY_F12 && !deathmatch) + { // Cycle the display player + do + { + displayplayer++; + if (displayplayer == MAXPLAYERS) + { + displayplayer = 0; + } + } + while (!playeringame[displayplayer] + && displayplayer != consoleplayer); + return (true); + } + + if (gamestate == GS_LEVEL) + { + if (CT_Responder(ev)) + { // Chat ate the event + return (true); + } + if (SB_Responder(ev)) + { // Status bar ate the event + return (true); + } + if (AM_Responder(ev)) + { // Automap ate the event + return (true); + } + } + + if (ev->type == ev_mouse) + { + testcontrols_mousespeed = abs(ev->data2); + } + + if (ev->type == ev_keydown && ev->data1 == key_prevweapon) + { + next_weapon = -1; + } + else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) + { + next_weapon = 1; + } + + switch (ev->type) + { + case ev_keydown: + if (ev->data1 == key_invleft) + { + if (InventoryMoveLeft()) + { + return (true); + } + break; + } + if (ev->data1 == key_invright) + { + if (InventoryMoveRight()) + { + return (true); + } + break; + } + if (ev->data1 == key_pause && !MenuActive) + { + sendpause = true; + return (true); + } + if (ev->data1 < NUMKEYS) + { + gamekeydown[ev->data1] = true; + } + return (true); // eat key down events + + case ev_keyup: + if (ev->data1 < NUMKEYS) + { + gamekeydown[ev->data1] = false; + } + return (false); // always let key up events filter down + + case ev_mouse: + SetMouseButtons(ev->data1); + mousex = ev->data2 * (mouseSensitivity + 5) / 10; + mousey = ev->data3 * (mouseSensitivity + 5) / 10; + return (true); // eat events + + case ev_joystick: + SetJoyButtons(ev->data1); + joyxmove = ev->data2; + joyymove = ev->data3; + joystrafemove = ev->data4; + joylook = ev->data5; + return (true); // eat events + + default: + break; + } + return (false); +} + +/* +=============================================================================== += += G_Ticker += +=============================================================================== +*/ + +void G_Ticker(void) +{ + int i, buf; + ticcmd_t *cmd = NULL; + +// +// do player reborns if needed +// + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].playerstate == PST_REBORN) + G_DoReborn(i); + +// +// do things to change the game state +// + while (gameaction != ga_nothing) + { + switch (gameaction) + { + case ga_loadlevel: + G_DoLoadLevel(); + break; + case ga_newgame: + G_DoNewGame(); + break; + case ga_loadgame: + G_DoLoadGame(); + break; + case ga_savegame: + G_DoSaveGame(); + break; + case ga_playdemo: + G_DoPlayDemo(); + break; + case ga_screenshot: + V_ScreenShot("HTIC%02i.%s"); + gameaction = ga_nothing; + break; + case ga_completed: + G_DoCompleted(); + break; + case ga_worlddone: + G_DoWorldDone(); + break; + case ga_victory: + F_StartFinale(); + break; + default: + break; + } + } + + +// +// get commands, check consistancy, and build new consistancy check +// + //buf = gametic%BACKUPTICS; + buf = (gametic / ticdup) % BACKUPTICS; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + cmd = &players[i].cmd; + + memcpy(cmd, &netcmds[i], sizeof(ticcmd_t)); + + if (demoplayback) + G_ReadDemoTiccmd(cmd); + if (demorecording) + G_WriteDemoTiccmd(cmd); + + if (netgame && !netdemo && !(gametic % ticdup)) + { + if (gametic > BACKUPTICS + && consistancy[i][buf] != cmd->consistancy) + { + I_Error("consistency failure (%i should be %i)", + cmd->consistancy, consistancy[i][buf]); + } + if (players[i].mo) + consistancy[i][buf] = players[i].mo->x; + else + consistancy[i][buf] = rndindex; + } + } + +// +// check for special buttons +// + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + if (players[i].cmd.buttons & BT_SPECIAL) + { + switch (players[i].cmd.buttons & BT_SPECIALMASK) + { + case BTS_PAUSE: + paused ^= 1; + if (paused) + { + S_PauseSound(); + } + else + { + S_ResumeSound(); + } + break; + + case BTS_SAVEGAME: + if (!savedescription[0]) + { + if (netgame) + { + M_StringCopy(savedescription, + DEH_String("NET GAME"), + sizeof(savedescription)); + } + else + { + M_StringCopy(savedescription, + DEH_String("SAVE GAME"), + sizeof(savedescription)); + } + } + savegameslot = + (players[i].cmd. + buttons & BTS_SAVEMASK) >> BTS_SAVESHIFT; + gameaction = ga_savegame; + break; + } + } + } + // turn inventory off after a certain amount of time + if (inventory && !(--inventoryTics)) + { + players[consoleplayer].readyArtifact = + players[consoleplayer].inventory[inv_ptr].type; + inventory = false; + cmd->arti = 0; + } +// +// do main actions +// +// +// do main actions +// + switch (gamestate) + { + case GS_LEVEL: + P_Ticker(); + SB_Ticker(); + AM_Ticker(); + CT_Ticker(); + break; + case GS_INTERMISSION: + IN_Ticker(); + break; + case GS_FINALE: + F_Ticker(); + break; + case GS_DEMOSCREEN: + D_PageTicker(); + break; + } +} + + +/* +============================================================================== + + PLAYER STRUCTURE FUNCTIONS + +also see P_SpawnPlayer in P_Things +============================================================================== +*/ + +/* +==================== += += G_InitPlayer += += Called at the start += Called by the game initialization functions +==================== +*/ + +void G_InitPlayer(int player) +{ + // clear everything else to defaults + G_PlayerReborn(player); +} + + +/* +==================== += += G_PlayerFinishLevel += += Can when a player completes a level +==================== +*/ + +void G_PlayerFinishLevel(int player) +{ + player_t *p; + int i; + +/* // BIG HACK + inv_ptr = 0; + curpos = 0; +*/ + // END HACK + p = &players[player]; + for (i = 0; i < p->inventorySlotNum; i++) + { + p->inventory[i].count = 1; + } + p->artifactCount = p->inventorySlotNum; + + if (!deathmatch) + { + for (i = 0; i < 16; i++) + { + P_PlayerUseArtifact(p, arti_fly); + } + } + memset(p->powers, 0, sizeof(p->powers)); + memset(p->keys, 0, sizeof(p->keys)); + playerkeys = 0; +// memset(p->inventory, 0, sizeof(p->inventory)); + if (p->chickenTics) + { + p->readyweapon = p->mo->special1.i; // Restore weapon + p->chickenTics = 0; + } + p->messageTics = 0; + p->lookdir = 0; + p->mo->flags &= ~MF_SHADOW; // Remove invisibility + p->extralight = 0; // Remove weapon flashes + p->fixedcolormap = 0; // Remove torch + p->damagecount = 0; // No palette changes + p->bonuscount = 0; + p->rain1 = NULL; + p->rain2 = NULL; + if (p == &players[consoleplayer]) + { + SB_state = -1; // refresh the status bar + } +} + +/* +==================== += += G_PlayerReborn += += Called after a player dies += almost everything is cleared and initialized +==================== +*/ + +void G_PlayerReborn(int player) +{ + player_t *p; + int i; + int frags[MAXPLAYERS]; + int killcount, itemcount, secretcount; + boolean secret; + + secret = false; + memcpy(frags, players[player].frags, sizeof(frags)); + killcount = players[player].killcount; + itemcount = players[player].itemcount; + secretcount = players[player].secretcount; + + p = &players[player]; + if (p->didsecret) + { + secret = true; + } + memset(p, 0, sizeof(*p)); + + memcpy(players[player].frags, frags, sizeof(players[player].frags)); + players[player].killcount = killcount; + players[player].itemcount = itemcount; + players[player].secretcount = secretcount; + + p->usedown = p->attackdown = true; // don't do anything immediately + p->playerstate = PST_LIVE; + p->health = MAXHEALTH; + p->readyweapon = p->pendingweapon = wp_goldwand; + p->weaponowned[wp_staff] = true; + p->weaponowned[wp_goldwand] = true; + p->messageTics = 0; + p->lookdir = 0; + p->ammo[am_goldwand] = 50; + for (i = 0; i < NUMAMMO; i++) + { + p->maxammo[i] = maxammo[i]; + } + if (gamemap == 9 || secret) + { + p->didsecret = true; + } + if (p == &players[consoleplayer]) + { + SB_state = -1; // refresh the status bar + inv_ptr = 0; // reset the inventory pointer + curpos = 0; + } +} + +/* +==================== += += G_CheckSpot += += Returns false if the player cannot be respawned at the given mapthing_t spot += because something is occupying it +==================== +*/ + +void P_SpawnPlayer(mapthing_t * mthing); + +boolean G_CheckSpot(int playernum, mapthing_t * mthing) +{ + fixed_t x, y; + subsector_t *ss; + unsigned an; + mobj_t *mo; + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + players[playernum].mo->flags2 &= ~MF2_PASSMOBJ; + if (!P_CheckPosition(players[playernum].mo, x, y)) + { + players[playernum].mo->flags2 |= MF2_PASSMOBJ; + return false; + } + players[playernum].mo->flags2 |= MF2_PASSMOBJ; + +// spawn a teleport fog + ss = R_PointInSubsector(x, y); + an = ((unsigned) ANG45 * (mthing->angle / 45)) >> ANGLETOFINESHIFT; + + mo = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an], + ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); + + if (players[consoleplayer].viewz != 1) + S_StartSound(mo, sfx_telept); // don't start sound on first frame + + return true; +} + +/* +==================== += += G_DeathMatchSpawnPlayer += += Spawns a player at one of the random death match spots += called at level load and each death +==================== +*/ + +void G_DeathMatchSpawnPlayer(int playernum) +{ + int i, j; + int selections; + + selections = deathmatch_p - deathmatchstarts; + if (selections < 4) + I_Error("Only %i deathmatch spots, 4 required", selections); + + for (j = 0; j < 20; j++) + { + i = P_Random() % selections; + if (G_CheckSpot(playernum, &deathmatchstarts[i])) + { + deathmatchstarts[i].type = playernum + 1; + P_SpawnPlayer(&deathmatchstarts[i]); + return; + } + } + +// no good spot, so the player will probably get stuck + P_SpawnPlayer(&playerstarts[playernum]); +} + +/* +==================== += += G_DoReborn += +==================== +*/ + +void G_DoReborn(int playernum) +{ + int i; + + // quit demo unless -demoextend + if (!demoextend && G_CheckDemoStatus()) + return; + if (!netgame) + gameaction = ga_loadlevel; // reload the level from scratch + else + { // respawn at the start + players[playernum].mo->player = NULL; // dissasociate the corpse + + // spawn at random spot if in death match + if (deathmatch) + { + G_DeathMatchSpawnPlayer(playernum); + return; + } + + if (G_CheckSpot(playernum, &playerstarts[playernum])) + { + P_SpawnPlayer(&playerstarts[playernum]); + return; + } + // try to spawn at one of the other players spots + for (i = 0; i < MAXPLAYERS; i++) + if (G_CheckSpot(playernum, &playerstarts[i])) + { + playerstarts[i].type = playernum + 1; // fake as other player + P_SpawnPlayer(&playerstarts[i]); + playerstarts[i].type = i + 1; // restore + return; + } + // he's going to be inside something. Too bad. + P_SpawnPlayer(&playerstarts[playernum]); + } +} + + +void G_ScreenShot(void) +{ + gameaction = ga_screenshot; +} + + +/* +==================== += += G_DoCompleted += +==================== +*/ + +boolean secretexit; + +void G_ExitLevel(void) +{ + secretexit = false; + gameaction = ga_completed; +} + +void G_SecretExitLevel(void) +{ + secretexit = true; + gameaction = ga_completed; +} + +void G_DoCompleted(void) +{ + int i; + static int afterSecret[5] = { 7, 5, 5, 5, 4 }; + + gameaction = ga_nothing; + + // quit demo unless -demoextend + if (!demoextend && G_CheckDemoStatus()) + { + return; + } + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + G_PlayerFinishLevel(i); + } + } + prevmap = gamemap; + if (secretexit == true) + { + gamemap = 9; + } + else if (gamemap == 9) + { // Finished secret level + gamemap = afterSecret[gameepisode - 1]; + } + else if (gamemap == 8) + { + gameaction = ga_victory; + return; + } + else + { + gamemap++; + } + gamestate = GS_INTERMISSION; + IN_Start(); +} + +//============================================================================ +// +// G_WorldDone +// +//============================================================================ + +void G_WorldDone(void) +{ + gameaction = ga_worlddone; +} + +//============================================================================ +// +// G_DoWorldDone +// +//============================================================================ + +void G_DoWorldDone(void) +{ + gamestate = GS_LEVEL; + G_DoLoadLevel(); + gameaction = ga_nothing; + viewactive = true; +} + +//--------------------------------------------------------------------------- +// +// PROC G_LoadGame +// +// Can be called by the startup code or the menu task. +// +//--------------------------------------------------------------------------- + +static char *savename = NULL; + +void G_LoadGame(char *name) +{ + savename = M_StringDuplicate(name); + gameaction = ga_loadgame; +} + +//--------------------------------------------------------------------------- +// +// PROC G_DoLoadGame +// +// Called by G_Ticker based on gameaction. +// +//--------------------------------------------------------------------------- + +#define VERSIONSIZE 16 + +void G_DoLoadGame(void) +{ + int i; + int a, b, c; + char savestr[SAVESTRINGSIZE]; + char vcheck[VERSIONSIZE], readversion[VERSIONSIZE]; + + gameaction = ga_nothing; + + SV_OpenRead(savename); + + free(savename); + savename = NULL; + + // Skip the description field + SV_Read(savestr, SAVESTRINGSIZE); + + memset(vcheck, 0, sizeof(vcheck)); + DEH_snprintf(vcheck, VERSIONSIZE, "version %i", HERETIC_VERSION); + SV_Read(readversion, VERSIONSIZE); + + if (strncmp(readversion, vcheck, VERSIONSIZE) != 0) + { // Bad version + return; + } + gameskill = SV_ReadByte(); + gameepisode = SV_ReadByte(); + gamemap = SV_ReadByte(); + for (i = 0; i < MAXPLAYERS; i++) + { + playeringame[i] = SV_ReadByte(); + } + // Load a base level + G_InitNew(gameskill, gameepisode, gamemap); + + // Create leveltime + a = SV_ReadByte(); + b = SV_ReadByte(); + c = SV_ReadByte(); + leveltime = (a << 16) + (b << 8) + c; + + // De-archive all the modifications + P_UnArchivePlayers(); + P_UnArchiveWorld(); + P_UnArchiveThinkers(); + P_UnArchiveSpecials(); + + if (SV_ReadByte() != SAVE_GAME_TERMINATOR) + { // Missing savegame termination marker + I_Error("Bad savegame"); + } + + SV_Close(); +} + + +/* +==================== += += G_InitNew += += Can be called by the startup code or the menu task += consoleplayer, displayplayer, playeringame[] should be set +==================== +*/ + +skill_t d_skill; +int d_episode; +int d_map; + +void G_DeferedInitNew(skill_t skill, int episode, int map) +{ + d_skill = skill; + d_episode = episode; + d_map = map; + gameaction = ga_newgame; +} + +void G_DoNewGame(void) +{ + G_InitNew(d_skill, d_episode, d_map); + gameaction = ga_nothing; +} + +void G_InitNew(skill_t skill, int episode, int map) +{ + int i; + int speed; + static const char *skyLumpNames[5] = { + "SKY1", "SKY2", "SKY3", "SKY1", "SKY3" + }; + + if (paused) + { + paused = false; + S_ResumeSound(); + } + if (skill < sk_baby) + skill = sk_baby; + if (skill > sk_nightmare) + skill = sk_nightmare; + if (episode < 1) + episode = 1; + // Up to 9 episodes for testing + if (episode > 9) + episode = 9; + if (map < 1) + map = 1; + if (map > 9) + map = 9; + M_ClearRandom(); + if (respawnparm) + { + respawnmonsters = true; + } + else + { + respawnmonsters = false; + } + // Set monster missile speeds + speed = skill == sk_nightmare; + for (i = 0; MonsterMissileInfo[i].type != -1; i++) + { + mobjinfo[MonsterMissileInfo[i].type].speed + = MonsterMissileInfo[i].speed[speed] << FRACBITS; + } + // Force players to be initialized upon first level load + for (i = 0; i < MAXPLAYERS; i++) + { + players[i].playerstate = PST_REBORN; + players[i].didsecret = false; + } + // Set up a bunch of globals + usergame = true; // will be set false if a demo + paused = false; + demorecording = false; + demoplayback = false; + netdemo = false; + viewactive = true; + gameepisode = episode; + gamemap = map; + gameskill = skill; + BorderNeedRefresh = true; + + // Set the sky map + if (episode > 5) + { + skytexture = R_TextureNumForName(DEH_String("SKY1")); + } + else + { + skytexture = R_TextureNumForName(DEH_String(skyLumpNames[episode - 1])); + } + +// +// give one null ticcmd_t +// +#if 0 + gametic = 0; + maketic = 1; + for (i = 0; i < MAXPLAYERS; i++) + nettics[i] = 1; // one null event for this gametic + memset(localcmds, 0, sizeof(localcmds)); + memset(netcmds, 0, sizeof(netcmds)); +#endif + G_DoLoadLevel(); +} + + +/* +=============================================================================== + + DEMO RECORDING + +=============================================================================== +*/ + +#define DEMOMARKER 0x80 +#define DEMOHEADER_RESPAWN 0x20 +#define DEMOHEADER_LONGTICS 0x10 +#define DEMOHEADER_NOMONSTERS 0x02 + +void G_ReadDemoTiccmd(ticcmd_t * cmd) +{ + if (*demo_p == DEMOMARKER) + { // end of demo data stream + G_CheckDemoStatus(); + return; + } + cmd->forwardmove = ((signed char) *demo_p++); + cmd->sidemove = ((signed char) *demo_p++); + + // If this is a longtics demo, read back in higher resolution + + if (longtics) + { + cmd->angleturn = *demo_p++; + cmd->angleturn |= (*demo_p++) << 8; + } + else + { + cmd->angleturn = ((unsigned char) *demo_p++) << 8; + } + + cmd->buttons = (unsigned char) *demo_p++; + cmd->lookfly = (unsigned char) *demo_p++; + cmd->arti = (unsigned char) *demo_p++; +} + +// Increase the size of the demo buffer to allow unlimited demos + +static void IncreaseDemoBuffer(void) +{ + int current_length; + byte *new_demobuffer; + byte *new_demop; + int new_length; + + // Find the current size + + current_length = demoend - demobuffer; + + // Generate a new buffer twice the size + new_length = current_length * 2; + + new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); + new_demop = new_demobuffer + (demo_p - demobuffer); + + // Copy over the old data + + memcpy(new_demobuffer, demobuffer, current_length); + + // Free the old buffer and point the demo pointers at the new buffer. + + Z_Free(demobuffer); + + demobuffer = new_demobuffer; + demo_p = new_demop; + demoend = demobuffer + new_length; +} + +void G_WriteDemoTiccmd(ticcmd_t * cmd) +{ + byte *demo_start; + + if (gamekeydown[key_demo_quit]) // press to end demo recording + G_CheckDemoStatus(); + + demo_start = demo_p; + + *demo_p++ = cmd->forwardmove; + *demo_p++ = cmd->sidemove; + + // If this is a longtics demo, record in higher resolution + + if (longtics) + { + *demo_p++ = (cmd->angleturn & 0xff); + *demo_p++ = (cmd->angleturn >> 8) & 0xff; + } + else + { + *demo_p++ = cmd->angleturn >> 8; + } + + *demo_p++ = cmd->buttons; + *demo_p++ = cmd->lookfly; + *demo_p++ = cmd->arti; + + // reset demo pointer back + demo_p = demo_start; + + if (demo_p > demoend - 16) + { + if (vanilla_demo_limit) + { + // no more space + G_CheckDemoStatus(); + return; + } + else + { + // Vanilla demo limit disabled: unlimited + // demo lengths! + + IncreaseDemoBuffer(); + } + } + + G_ReadDemoTiccmd(cmd); // make SURE it is exactly the same +} + + + +/* +=================== += += G_RecordDemo += +=================== +*/ + +void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, + const char *name) +{ + size_t demoname_size; + int i; + int maxsize; + + //! + // @category demo + // + // Record or playback a demo with high resolution turning. + // + + longtics = D_NonVanillaRecord(M_ParmExists("-longtics"), + "vvHeretic longtics demo"); + + // If not recording a longtics demo, record in low res + + lowres_turn = !longtics; + + //! + // @category demo + // + // Smooth out low resolution turning when recording a demo. + // + + shortticfix = M_ParmExists("-shortticfix"); + + G_InitNew(skill, episode, map); + usergame = false; + demoname_size = strlen(name) + 5; + demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); + M_snprintf(demoname, demoname_size, "%s.lmp", name); + maxsize = 0x20000; + + //! + // @arg + // @category demo + // @vanilla + // + // Specify the demo buffer size (KiB) + // + + i = M_CheckParmWithArgs("-maxdemo", 1); + if (i) + maxsize = atoi(myargv[i + 1]) * 1024; + demobuffer = Z_Malloc(maxsize, PU_STATIC, NULL); + demoend = demobuffer + maxsize; + + demo_p = demobuffer; + *demo_p++ = skill; + *demo_p++ = episode; + *demo_p++ = map; + + // Write special parameter bits onto player one byte. + // This aligns with vvHeretic demo usage: + // 0x20 = -respawn + // 0x10 = -longtics + // 0x02 = -nomonsters + + *demo_p = 1; // assume player one exists + if (D_NonVanillaRecord(respawnparm, "vvHeretic -respawn header flag")) + { + *demo_p |= DEMOHEADER_RESPAWN; + } + if (longtics) + { + *demo_p |= DEMOHEADER_LONGTICS; + } + if (D_NonVanillaRecord(nomonsters, "vvHeretic -nomonsters header flag")) + { + *demo_p |= DEMOHEADER_NOMONSTERS; + } + demo_p++; + + for (i = 1; i < MAXPLAYERS; i++) + *demo_p++ = playeringame[i]; + + demorecording = true; +} + + +/* +=================== += += G_PlayDemo += +=================== +*/ + +static const char *defdemoname; + +void G_DeferedPlayDemo(const char *name) +{ + defdemoname = name; + gameaction = ga_playdemo; +} + +void G_DoPlayDemo(void) +{ + skill_t skill; + int i, lumpnum, episode, map; + + gameaction = ga_nothing; + lumpnum = W_GetNumForName(defdemoname); + demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC); + demo_p = demobuffer; + skill = *demo_p++; + episode = *demo_p++; + map = *demo_p++; + + // vvHeretic allows extra options to be stored in the upper bits of + // the player 1 present byte. However, this is a non-vanilla extension. + if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_LONGTICS) != 0, + lumpnum, "vvHeretic longtics demo")) + { + longtics = true; + } + if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_RESPAWN) != 0, + lumpnum, "vvHeretic -respawn header flag")) + { + respawnparm = true; + } + if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_NOMONSTERS) != 0, + lumpnum, "vvHeretic -nomonsters header flag")) + { + nomonsters = true; + } + + for (i = 0; i < MAXPLAYERS; i++) + playeringame[i] = (*demo_p++) != 0; + + if (playeringame[1] || M_CheckParm("-solo-net") > 0 + || M_CheckParm("-netdemo") > 0) + { + netgame = true; + } + + precache = false; // don't spend a lot of time in loadlevel + G_InitNew(skill, episode, map); + precache = true; + usergame = false; + demoplayback = true; + + if (netgame == true) + { + netdemo = true; + } +} + + +/* +=================== += += G_TimeDemo += +=================== +*/ + +void G_TimeDemo(char *name) +{ + skill_t skill; + int episode, map, i; + + demobuffer = demo_p = W_CacheLumpName(name, PU_STATIC); + skill = *demo_p++; + episode = *demo_p++; + map = *demo_p++; + + // Read special parameter bits: see G_RecordDemo() for details. + longtics = (*demo_p & DEMOHEADER_LONGTICS) != 0; + + // don't overwrite arguments from the command line + respawnparm |= (*demo_p & DEMOHEADER_RESPAWN) != 0; + nomonsters |= (*demo_p & DEMOHEADER_NOMONSTERS) != 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + playeringame[i] = (*demo_p++) != 0; + } + + if (playeringame[1] || M_CheckParm("-solo-net") > 0 + || M_CheckParm("-netdemo") > 0) + { + netgame = true; + } + + G_InitNew(skill, episode, map); + starttime = I_GetTime(); + + usergame = false; + demoplayback = true; + timingdemo = true; + singletics = true; + + if (netgame == true) + { + netdemo = true; + } +} + + +/* +=================== += += G_CheckDemoStatus += += Called after a death or level completion to allow demos to be cleaned up += Returns true if a new demo loop action will take place +=================== +*/ + +boolean G_CheckDemoStatus(void) +{ + int endtime, realtics; + + if (timingdemo) + { + float fps; + endtime = I_GetTime(); + realtics = endtime - starttime; + fps = ((float) gametic * TICRATE) / realtics; + I_Error("timed %i gametics in %i realtics (%f fps)", + gametic, realtics, fps); + } + + if (demoplayback) + { + if (singledemo) + I_Quit(); + + W_ReleaseLumpName(defdemoname); + demoplayback = false; + netdemo = false; + netgame = false; + D_AdvanceDemo(); + return true; + } + + if (demorecording) + { + *demo_p++ = DEMOMARKER; + M_WriteFile(demoname, demobuffer, demo_p - demobuffer); + Z_Free(demobuffer); + demorecording = false; + I_Error("Demo %s recorded", demoname); + } + + return false; +} + +/**************************************************************************/ +/**************************************************************************/ + +//========================================================================== +// +// G_SaveGame +// +// Called by the menu task. is a 24 byte text string. +// +//========================================================================== + +void G_SaveGame(int slot, char *description) +{ + savegameslot = slot; + M_StringCopy(savedescription, description, sizeof(savedescription)); + sendsave = true; +} + +//========================================================================== +// +// G_DoSaveGame +// +// Called by G_Ticker based on gameaction. +// +//========================================================================== + +void G_DoSaveGame(void) +{ + int i; + char *filename; + char verString[VERSIONSIZE]; + char *description; + + filename = SV_Filename(savegameslot); + + description = savedescription; + + SV_Open(filename); + SV_Write(description, SAVESTRINGSIZE); + memset(verString, 0, sizeof(verString)); + DEH_snprintf(verString, VERSIONSIZE, "version %i", HERETIC_VERSION); + SV_Write(verString, VERSIONSIZE); + SV_WriteByte(gameskill); + SV_WriteByte(gameepisode); + SV_WriteByte(gamemap); + for (i = 0; i < MAXPLAYERS; i++) + { + SV_WriteByte(playeringame[i]); + } + SV_WriteByte(leveltime >> 16); + SV_WriteByte(leveltime >> 8); + SV_WriteByte(leveltime); + P_ArchivePlayers(); + P_ArchiveWorld(); + P_ArchiveThinkers(); + P_ArchiveSpecials(); + SV_WriteSaveGameEOF(); + SV_Close(); + + gameaction = ga_nothing; + savedescription[0] = 0; + P_SetMessage(&players[consoleplayer], DEH_String(TXT_GAMESAVED), true); + + free(filename); +} + diff --git a/games/NXDoom/src/heretic/heretic_icon.c b/games/NXDoom/src/heretic/heretic_icon.c new file mode 100644 index 00000000000..ab8b641c856 --- /dev/null +++ b/games/NXDoom/src/heretic/heretic_icon.c @@ -0,0 +1,2736 @@ +static int heretic_icon_w = 128; +static int heretic_icon_h = 128; + +static const unsigned int heretic_icon_data[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, + 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, + 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, + 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, + 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, + 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, + 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, + 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, + 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, + 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, + 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, + 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, + 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, + 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, + 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, + 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, + 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, + 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, + 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, + 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, + 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, + 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, + 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, + 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, + 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, + 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, + 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, + 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, + 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, + 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, + 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, + 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, + 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, + 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, + 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, + 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, + 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, + 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, + 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, + 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, + 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, + 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, + 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, + 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, + 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, + 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, + 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, + 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x93756aff, 0x91756aff, 0x968078ff, 0x99867fff, + 0x99867fff, 0x99867fff, 0x99867fff, 0x99867fff, 0x99867fff, 0xa2918bff, + 0xb5aaa6ff, 0xb5a9a5ff, 0xb5a9a5ff, 0xb4a8a4ff, 0xb4a8a4ff, 0xb3a7a3ff, + 0xb2a6a2ff, 0xb2a6a2ff, 0xb0a5a1ff, 0xa2928cff, 0x98857eff, 0x98847eff, + 0x98847eff, 0x98847eff, 0x97837dff, 0x95817bff, 0x937f79ff, 0x907d76ff, + 0x907e77ff, 0x9e908cff, 0xa09491ff, 0x9f938fff, 0x9d928eff, 0x9b8f8bff, + 0x998d89ff, 0x978c88ff, 0x968a86ff, 0x948884ff, 0x8f827eff, 0x7a6660ff, + 0x78645eff, 0x76625dff, 0x74605bff, 0x725e59ff, 0x705c57ff, 0x6e5b55ff, + 0x6c5953ff, 0x6a5751ff, 0x73625eff, 0x7f7370ff, 0x7d716eff, 0x7b6f6cff, + 0x796d6aff, 0x786c69ff, 0x766a67ff, 0x746865ff, 0x716563ff, 0x716562ff, + 0x5d4b47ff, 0x54403bff, 0x523d3aff, 0x55413fff, 0x574445ff, 0x59464aff, + 0x5b494fff, 0x5d4950ff, 0x5f464cff, 0x674e55ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, + 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, + 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, + 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, + 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, + 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, + 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, + 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, + 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, + 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, + 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, + 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, + 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, + 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, + 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, + 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, + 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, + 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, + 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, + 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, + 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, + 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb9b8b8ff, 0xbdbdbdff, + 0xbbbbbcff, 0xbbbbbbff, 0xbab9baff, 0xb9b9baff, 0xb8b8b9ff, 0xb8b8b8ff, + 0xb7b6b7ff, 0xb0afb0ff, 0x9f9ea0ff, 0x9e9ea0ff, 0x9e9da0ff, 0x9e9d9fff, + 0x9d9c9fff, 0x9d9c9eff, 0x9c9b9eff, 0x9c9a9eff, 0x9c9a9eff, 0xa6a5a7ff, + 0xadacafff, 0xacaaadff, 0xacaaadff, 0xaaa9acff, 0xa8a7aaff, 0xa6a5a8ff, + 0xa5a3a7ff, 0xa3a2a5ff, 0xa1a0a3ff, 0x8f8d93ff, 0x8c8a90ff, 0x8a888dff, + 0x88868cff, 0x868389ff, 0x848288ff, 0x828086ff, 0x817e85ff, 0x7e7b82ff, + 0x807e84ff, 0x8c8b8fff, 0x8b898eff, 0x89878cff, 0x87858bff, 0x858488ff, + 0x848287ff, 0x827f85ff, 0x807e83ff, 0x7e7c82ff, 0x737178ff, 0x67636cff, + 0x64616aff, 0x635f68ff, 0x605d66ff, 0x5f5b65ff, 0x5d5963ff, 0x5b5761ff, + 0x58555fff, 0x57535dff, 0x646168ff, 0x68656cff, 0x66636bff, 0x67656dff, + 0x676570ff, 0x676672ff, 0x696775ff, 0x696877ff, 0x6a6a7aff, 0x6b6b7bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x757473ff, 0x747475ff, 0x747374ff, 0x737274ff, 0x727273ff, 0x727173ff, + 0x717072ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, + 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, + 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, + 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, + 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, + 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, + 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, + 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, + 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, + 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, + 0x4a4655ff, 0x4b4653ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x747373ff, 0x747374ff, 0x737274ff, 0x727273ff, + 0x727173ff, 0x717072ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, + 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, + 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, + 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, + 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, + 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, + 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, + 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, + 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, + 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, + 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x4a4652ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x747272ff, 0x737274ff, + 0x727273ff, 0x727173ff, 0x717072ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, + 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, + 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, + 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, + 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, + 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, + 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, + 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, + 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, + 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, + 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x4a4652ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x737172ff, 0x727273ff, 0x727173ff, 0x717072ff, 0x706f72ff, 0x706f71ff, + 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, + 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, + 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, + 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, + 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, + 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, + 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, + 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, + 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, + 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, + 0x494654ff, 0x494552ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x727171ff, 0x727173ff, 0x717072ff, 0x706f72ff, + 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, + 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, + 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, + 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, + 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, + 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, + 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, + 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, + 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, + 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, + 0x494654ff, 0x494654ff, 0x484554ff, 0x494551ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x727071ff, 0x717072ff, + 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, + 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, + 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, + 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, + 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, + 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, + 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, + 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, + 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, + 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, + 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x484551ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x716f70ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, + 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, + 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, + 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, + 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, + 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, + 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, + 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, + 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, + 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, + 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, + 0x474553ff, 0x484551ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x706e70ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, + 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, + 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, + 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, + 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, + 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, + 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, + 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, + 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, + 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, + 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, + 0x484553ff, 0x474553ff, 0x474553ff, 0x474550ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x706e6fff, 0x6f6e71ff, + 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, + 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, + 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, + 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, + 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, + 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, + 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, + 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, + 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, + 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, + 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x474450ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6f6d6fff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, + 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, + 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, + 0x636068ff, 0x727361ff, 0xc3d93eff, 0xceea38ff, 0xcae938ff, 0xc6e838ff, + 0xc3e738ff, 0xbfe639ff, 0xbbe539ff, 0xb7e439ff, 0xb4e339ff, 0xb0e23aff, + 0xace13aff, 0x96bf43ff, 0x5d5b5fff, 0x595560ff, 0x585460ff, 0x5b595dff, + 0x88bb44ff, 0x93d93bff, 0x8fd83bff, 0x8bd73cff, 0x88d53cff, 0x84d43cff, + 0x80d33dff, 0x7cd23dff, 0x78d13dff, 0x74d03eff, 0x70d03eff, 0x69bd41ff, + 0x535c55ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, + 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, + 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, + 0x464452ff, 0x46444fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6e6c6eff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, + 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, + 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, + 0x646168ff, 0x636068ff, 0x625f67ff, 0xa0ac4dff, 0xd6f434ff, 0xd2f335ff, + 0xcef235ff, 0xcaf135ff, 0xc6f036ff, 0xc2ef36ff, 0xbeee36ff, 0xbaed36ff, + 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0x728453ff, 0x585460ff, + 0x58535fff, 0x6d8153ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, + 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, + 0x6fd83cff, 0x6bd73dff, 0x568d46ff, 0x4d4757ff, 0x4d4857ff, 0x4d4757ff, + 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, + 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, + 0x464552ff, 0x464452ff, 0x454451ff, 0x46444fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6e6b6eff, 0x6d6c6fff, + 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, + 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, + 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x828858ff, + 0xd1f135ff, 0xcef235ff, 0xcaf135ff, 0xc6f036ff, 0xc2ef36ff, 0xbeee36ff, + 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa3df3aff, + 0x62675bff, 0x58535fff, 0x57525fff, 0x5f6459ff, 0x90da3bff, 0x8fe13aff, + 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, + 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d43dff, 0x4b684aff, 0x423f50ff, + 0x4c4656ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, + 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, + 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x45444fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6d6b6dff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, + 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, + 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, + 0x615e66ff, 0x605d66ff, 0x70725eff, 0xc5ea37ff, 0xc6f036ff, 0xc2ef36ff, + 0xbeee36ff, 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, + 0x98cc3fff, 0x5f615cff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, + 0x5a5d59ff, 0x81c441ff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, + 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x66ce3eff, 0x46534dff, + 0x413e4eff, 0x413d4eff, 0x413e50ff, 0x4b4655ff, 0x4b4756ff, 0x4b4756ff, + 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, + 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, + 0x444451ff, 0x44444eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6c6a6dff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, + 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, + 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, + 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0xbadf3bff, + 0xc2ef36ff, 0xbeee36ff, 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, + 0xaae838ff, 0xa6e738ff, 0x8bb945ff, 0x58535fff, 0x57525fff, 0x56525eff, + 0x56515eff, 0x55505dff, 0x544f5dff, 0x78b244ff, 0x83dd3bff, 0x7fdc3bff, + 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, + 0x5fc23fff, 0x413e4eff, 0x413d4eff, 0x403d4eff, 0x403d4dff, 0x413e4fff, + 0x4a4655ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, + 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, + 0x454451ff, 0x444451ff, 0x434450ff, 0x44434eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6c696cff, 0x6b696eff, + 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, + 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, + 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, + 0x5e5b64ff, 0xb1d63eff, 0xbeee36ff, 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, + 0xaee937ff, 0xaae838ff, 0xa6e738ff, 0xa2e638ff, 0x84b047ff, 0x57525fff, + 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x72a947ff, + 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, + 0x67d63dff, 0x63d43dff, 0x59b940ff, 0x413d4eff, 0x403d4eff, 0x403d4dff, + 0x3f3d4dff, 0x3f3d4dff, 0x403e4eff, 0x494554ff, 0x494654ff, 0x494654ff, + 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, + 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x43434eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6b686cff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, + 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, + 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, + 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0xa8cc41ff, 0xbaed36ff, 0xb6ec37ff, + 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, + 0x7ea649ff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, + 0x534e5cff, 0x6ca048ff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, + 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x55af41ff, 0x403d4eff, + 0x403d4dff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, 0x3f3e4eff, + 0x484553ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, + 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, + 0x424350ff, 0x43434dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6a676bff, 0x6a686dff, 0x69676cff, 0x68666cff, + 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, + 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, + 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x9fc243ff, + 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa6e738ff, 0xa2e638ff, + 0x9fe539ff, 0x9be439ff, 0x779e4bff, 0x56515eff, 0x55505dff, 0x544f5dff, + 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x68974aff, 0x77da3cff, 0x73d93cff, + 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, + 0x51a643ff, 0x403d4dff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, + 0x3e3c4cff, 0x3e3d4cff, 0x3f3c4dff, 0x474452ff, 0x474553ff, 0x474553ff, + 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, + 0x434350ff, 0x424350ff, 0x42434fff, 0x42434dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a676bff, 0x69676cff, + 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, + 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, + 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, + 0x6e755bff, 0xaddc3bff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa6e738ff, + 0xa2e638ff, 0x9fe539ff, 0x9be439ff, 0x97e339ff, 0x8fd83bff, 0x87ce3eff, + 0x83cc3eff, 0x80ca3eff, 0x7dca3fff, 0x79c93fff, 0x76c83fff, 0x75d03eff, + 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, + 0x5cd23eff, 0x58d13eff, 0x52bf40ff, 0x41564bff, 0x3f3d4dff, 0x3e3c4dff, + 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3e3d4dff, + 0x464452ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, + 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x42424cff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x69666aff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, + 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, + 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, + 0x5d5963ff, 0x5c5863ff, 0x9bc044ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, + 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, 0x9be439ff, 0x97e339ff, 0x93e239ff, + 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, + 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, + 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x48a243ff, + 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, + 0x3d3c4bff, 0x3d3c4cff, 0x3e3d4cff, 0x454351ff, 0x454451ff, 0x454451ff, + 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, + 0x41424eff, 0x41424cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x68656aff, 0x68656bff, 0x67656bff, 0x66646aff, + 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, + 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, + 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x89a54bff, 0xaee937ff, + 0xaae838ff, 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, 0x9be439ff, 0x97e339ff, + 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, + 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, + 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, + 0x4cce3fff, 0x438846ff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, + 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3d3d4cff, + 0x444350ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, + 0x41434fff, 0x41424eff, 0x40424eff, 0x41424cff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x686469ff, 0x67656bff, + 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, + 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, + 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, + 0x5b5861ff, 0x8aad49ff, 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, 0x9be439ff, + 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x83ce3cff, 0x638747ff, 0x5d8049ff, + 0x71b940ff, 0x7bdb3bff, 0x77da3cff, 0x68b641ff, 0x547c48ff, 0x548347ff, + 0x63c63fff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, + 0x50cf3fff, 0x4cce3fff, 0x449345ff, 0x3f3e4dff, 0x3e3c4cff, 0x3e3d4cff, + 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, + 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4cff, 0x42434fff, 0x434350ff, 0x424350ff, + 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x40424bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x676469ff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, + 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, + 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, + 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x7a944fff, 0xa2e638ff, 0x9fe539ff, + 0x9be439ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, 0x586c4cff, + 0x454252ff, 0x444251ff, 0x66a144ff, 0x77da3cff, 0x73d93cff, 0x5e9d44ff, + 0x423f50ff, 0x413e4fff, 0x4b684aff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, + 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x407947ff, 0x3e3c4cff, + 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, + 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3c3c4bff, + 0x41424fff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, + 0x3f424dff, 0x40424bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x666368ff, 0x66636aff, 0x656269ff, 0x646269ff, + 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, + 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, + 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x738b51ff, + 0x9fe539ff, 0x9be439ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, + 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, + 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, + 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, + 0x3f7148ff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, + 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3c3c4aff, 0x40424eff, 0x41424eff, 0x40424eff, + 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3f414bff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x666268ff, 0x656269ff, + 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, + 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, + 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, + 0x585460ff, 0x6e8153ff, 0x9be439ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, + 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, + 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, + 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, + 0x44cc40ff, 0x40cb40ff, 0x3e6848ff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, + 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, + 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3b3b49ff, + 0x3f414dff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3f414bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x656167ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, + 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, + 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, + 0x595560ff, 0x585460ff, 0x58535fff, 0x697756ff, 0x97e339ff, 0x93e239ff, + 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, + 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, + 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, + 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x3c5e4aff, 0x3e3b4cff, + 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, + 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, + 0x3a3b48ff, 0x393b49ff, 0x3b3b49ff, 0x3f414cff, 0x3f424dff, 0x3e414dff, + 0x3e414cff, 0x3e414bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x646167ff, 0x646168ff, 0x636068ff, 0x625f67ff, + 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, + 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, + 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x636f57ff, + 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, + 0x7bdb3bff, 0x5a8247ff, 0x50694bff, 0x4f684bff, 0x5fad42ff, 0x67d63dff, + 0x63d43dff, 0x56a942ff, 0x49654aff, 0x46654aff, 0x497d46ff, 0x50cf3fff, + 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, + 0x3c564aff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, + 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393c48ff, + 0x3e404cff, 0x3e414cff, 0x3d414cff, 0x3e414aff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x646066ff, 0x636068ff, + 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, + 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, + 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, + 0x56525eff, 0x5f6659ff, 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, + 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x68b341ff, 0x4c5e4cff, 0x47544dff, + 0x5aa443ff, 0x63d43dff, 0x5fd33dff, 0x53a043ff, 0x43514cff, 0x445b4aff, + 0x4cac42ff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, + 0x38c841ff, 0x34c741ff, 0x3b5049ff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, + 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, + 0x393b48ff, 0x393a48ff, 0x393c48ff, 0x3d414cff, 0x3d414bff, 0x3d414aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x635f66ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, + 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, + 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, + 0x57525fff, 0x56525eff, 0x56515eff, 0x5a5c5aff, 0x8bdf3aff, 0x87de3aff, + 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, + 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, + 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, + 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x3b464bff, 0x3c3c4bff, + 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, + 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x393b48ff, + 0x3c414bff, 0x3d404aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x625e65ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, + 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, + 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, + 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x56535cff, + 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, + 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, + 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, + 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x2cc541ff, + 0x3c404bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, + 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, + 0x383b47ff, 0x383b47ff, 0x383a47ff, 0x3c4049ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x625e65ff, 0x615e66ff, + 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, + 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, + 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, + 0x544f5dff, 0x544e5cff, 0x81d93cff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, + 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, + 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, + 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, + 0x2cc541ff, 0x29c042ff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, + 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, + 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, + 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x393b46ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x615d64ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, + 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, + 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, + 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x7bcf3eff, 0x7bdb3bff, + 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, + 0x5fd33dff, 0x57ba41ff, 0x497448ff, 0x43524bff, 0x41514bff, 0x447348ff, + 0x47b641ff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x34c741ff, + 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x26b643ff, 0x3c3b4aff, 0x3c3b4bff, + 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, + 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, + 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, + 0x373a47ff, 0x373a45ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x605c64ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, + 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, + 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, + 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, + 0x75c63fff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, + 0x63d43dff, 0x5fd33dff, 0x54aa42ff, 0x40434dff, 0x403d4dff, 0x3f3d4dff, + 0x3f3d4dff, 0x3e3c4dff, 0x3f424dff, 0x40a543ff, 0x3cc940ff, 0x38c841ff, + 0x34c741ff, 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, 0x24af43ff, + 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, + 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, + 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x373a44ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x605b63ff, 0x5f5b65ff, + 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, + 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, + 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, + 0x524d5bff, 0x524c5bff, 0x70bd42ff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, + 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5bcb3fff, 0x424a4cff, 0x403d4dff, + 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, 0x3d494bff, + 0x38c242ff, 0x34c741ff, 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, + 0x20c242ff, 0x22a644ff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, + 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, + 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a45ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5f5a63ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, + 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, + 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, + 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x6ab443ff, 0x6fd83cff, + 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x509e44ff, + 0x403d4dff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, + 0x3e3d4cff, 0x3d3b4dff, 0x379745ff, 0x30c641ff, 0x2cc541ff, 0x28c442ff, + 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x239e45ff, 0x3b3c4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, + 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, + 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, + 0x363a46ff, 0x373a44ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5e5a62ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, + 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, + 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, + 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, + 0x65ab45ff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, + 0x58d13eff, 0x4a8645ff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, + 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x378046ff, 0x2cc541ff, + 0x28c442ff, 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, 0x219546ff, + 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, + 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, + 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, + 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x363a44ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5e5962ff, 0x5d5963ff, + 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, + 0x585460ff, 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, + 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, + 0x504b5aff, 0x504a59ff, 0x60a247ff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, + 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x477c46ff, 0x3f3d4dff, 0x3e3c4dff, + 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, + 0x357948ff, 0x28c442ff, 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, + 0x15be43ff, 0x218c46ff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, + 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, + 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, + 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x363a44ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5d5861ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, + 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, + 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, + 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x5d9949ff, 0x63d43dff, + 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x447448ff, + 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, + 0x3d3c4bff, 0x3d3c4cff, 0x347047ff, 0x24c342ff, 0x20c242ff, 0x1cc143ff, + 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x218446ff, 0x3b3b4aff, 0x3a3b4aff, + 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, + 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, + 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, + 0x353a45ff, 0x353943ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5c5761ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, + 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, + 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, + 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, + 0x59904aff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, + 0x4cce3fff, 0x416a49ff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, + 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x356749ff, 0x20c242ff, + 0x1cc143ff, 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, 0x237c47ff, + 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, + 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, + 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, + 0x353a45ff, 0x353a45ff, 0x343944ff, 0x353943ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5c5760ff, 0x5b5762ff, + 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, + 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, + 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, + 0x4e4858ff, 0x4e4858ff, 0x56884bff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, + 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x40624aff, 0x3e3c4cff, 0x3e3d4cff, + 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, + 0x355f48ff, 0x1cc143ff, 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, + 0x0cbb44ff, 0x257547ff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, + 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, + 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, + 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x343944ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5b5660ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, + 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, + 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, + 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x537f4dff, 0x58d13eff, + 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x3e594aff, + 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, + 0x3c3b4cff, 0x3c3b4aff, 0x365749ff, 0x19c043ff, 0x15be43ff, 0x11bd44ff, + 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x286d46ff, 0x393b49ff, 0x393b49ff, + 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, + 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, + 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, + 0x333944ff, 0x343a43ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5a555fff, 0x5a5561ff, 0x595560ff, 0x585460ff, + 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, + 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, + 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, + 0x50764eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, + 0x40cb40ff, 0x3e514aff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, + 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x37504aff, 0x15be43ff, + 0x11bd44ff, 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, 0x2a6548ff, + 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, + 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, + 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, + 0x343944ff, 0x333944ff, 0x333a44ff, 0x343942ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a545fff, 0x595560ff, + 0x585460ff, 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, + 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, + 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, + 0x4d4757ff, 0x4c4757ff, 0x4e6f4fff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, + 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x3c484cff, 0x3e3b4cff, 0x3d3c4bff, + 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, + 0x374849ff, 0x11bd44ff, 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, + 0x0cb846ff, 0x2c5e48ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, + 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, + 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, + 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x343942ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x59545eff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, + 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, + 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, + 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4c6650ff, 0x4cce3fff, + 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x3e3f4cff, + 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, + 0x3c3c4bff, 0x3b3c4aff, 0x3a4049ff, 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, + 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x2f5548ff, 0x393b48ff, 0x393a48ff, + 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, + 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, + 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, + 0x333943ff, 0x333942ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x58535eff, 0x58535fff, 0x57525fff, 0x56515eff, + 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, + 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, + 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, + 0x4b5e52ff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, + 0x34c341ff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, + 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x0db844ff, + 0x0cba45ff, 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x0cb547ff, 0x324f48ff, + 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, + 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, + 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, + 0x333943ff, 0x333943ff, 0x323943ff, 0x333a42ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x58525dff, 0x57525fff, + 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, + 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, + 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, + 0x4b4756ff, 0x4b4756ff, 0x4a5552ff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, + 0x38c841ff, 0x34c741ff, 0x31bb42ff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, + 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x0fb046ff, 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x0cb547ff, + 0x0cb447ff, 0x344848ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, + 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, + 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, + 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x333941ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x57515dff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, + 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, + 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, + 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4d54ff, 0x40cb40ff, + 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x2eb242ff, 0x3c3c4bff, + 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x12a846ff, 0x0cb846ff, 0x0cb746ff, + 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x374047ff, 0x383b48ff, 0x383b47ff, + 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, + 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, + 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, + 0x323942ff, 0x333841ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x56505cff, 0x56515eff, 0x55505dff, 0x544f5dff, + 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, + 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, + 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, + 0x494754ff, 0x3dc840ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x2cc541ff, + 0x2caa44ff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x15a047ff, + 0x0cb746ff, 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x0cb148ff, 0x383c48ff, + 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, + 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, + 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, + 0x333a43ff, 0x323942ff, 0x323841ff, 0x313941ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x56505cff, 0x55505dff, + 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, + 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, + 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, + 0x4a4655ff, 0x494654ff, 0x494654ff, 0x39c142ff, 0x34c741ff, 0x30c641ff, + 0x2cc541ff, 0x28c442ff, 0x2aa144ff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, + 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, + 0x393b49ff, 0x179947ff, 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x0cb248ff, + 0x0daa48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, + 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, + 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, + 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x313940ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x554f5bff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, + 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, + 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, + 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x36b843ff, + 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, 0x299845ff, 0x3c3b4bff, + 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, + 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x199047ff, 0x0cb447ff, 0x0cb348ff, + 0x0cb248ff, 0x0bb148ff, 0x11a248ff, 0x383b47ff, 0x373947ff, 0x363a46ff, + 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, + 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, + 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, + 0x303941ff, 0x313941ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x544e5bff, 0x544e5cff, 0x534e5cff, 0x524d5bff, + 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, + 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, + 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, + 0x484553ff, 0x34b044ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, 0x20c242ff, + 0x289046ff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x1d8847ff, + 0x0cb348ff, 0x0cb248ff, 0x0bb148ff, 0x0bb049ff, 0x139a49ff, 0x373947ff, + 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, + 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, + 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, + 0x303842ff, 0x303941ff, 0x303941ff, 0x313941ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x544d5aff, 0x534e5cff, + 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, + 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, + 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, + 0x484554ff, 0x484553ff, 0x474553ff, 0x32a845ff, 0x28c442ff, 0x24c342ff, + 0x20c242ff, 0x1cc143ff, 0x278847ff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, + 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, + 0x393b48ff, 0x1f8048ff, 0x0cb248ff, 0x0bb148ff, 0x0bb049ff, 0x0baf49ff, + 0x159349ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, + 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, + 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, + 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x303940ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x534d5aff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, + 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, + 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, + 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x31a046ff, + 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, 0x277f47ff, 0x3b3b4aff, + 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, + 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x217948ff, 0x0bb148ff, 0x0bb049ff, + 0x0baf49ff, 0x0bae4aff, 0x188c49ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, + 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, + 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, + 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, + 0x2f3841ff, 0x30393fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x524c59ff, 0x524c5bff, 0x514b5aff, 0x504b5aff, + 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, + 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, + 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, + 0x464552ff, 0x309747ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, 0x15be43ff, + 0x287747ff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, + 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x237248ff, + 0x0bb049ff, 0x0baf49ff, 0x0bae4aff, 0x0bad4aff, 0x1a834aff, 0x363a46ff, + 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, + 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, + 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, + 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x30393fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x524c59ff, 0x514b5aff, + 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, + 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, + 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, + 0x474553ff, 0x464552ff, 0x464452ff, 0x2f8f48ff, 0x1cc143ff, 0x19c043ff, + 0x15be43ff, 0x11bd44ff, 0x286f47ff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, + 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, + 0x383b48ff, 0x256b48ff, 0x0baf49ff, 0x0bae4aff, 0x0bad4aff, 0x0bab4bff, + 0x1d7c49ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, + 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, + 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, + 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x30393fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x514b58ff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, + 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, + 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, + 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x2f8749ff, + 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, 0x2a6748ff, 0x3a3b4aff, + 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, + 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x286448ff, 0x0bae4aff, 0x0bad4aff, + 0x0bab4bff, 0x0baa4bff, 0x1f7649ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, + 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, + 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, + 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, + 0x2f3940ff, 0x2e383fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x504b58ff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, + 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, + 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, + 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, + 0x454451ff, 0x2f804bff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, 0x0cbb44ff, + 0x2c6049ff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, + 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x2a5b48ff, + 0x0bad4aff, 0x0bab4bff, 0x0baa4bff, 0x0ba94cff, 0x216f49ff, 0x363a45ff, + 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, + 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, + 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, + 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2e393fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x504a57ff, 0x4f4959ff, + 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, + 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, + 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, + 0x454451ff, 0x454451ff, 0x444451ff, 0x2f784bff, 0x11bd44ff, 0x0dbc44ff, + 0x0cbb44ff, 0x0cba45ff, 0x305847ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, + 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, + 0x373947ff, 0x2c5547ff, 0x0bab4bff, 0x0baa4bff, 0x0ba94cff, 0x0ba84cff, + 0x246848ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, + 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, + 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, + 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2d393fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f4957ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, + 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, + 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, + 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x30704bff, + 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, 0x315148ff, 0x393b49ff, + 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, + 0x383b47ff, 0x373947ff, 0x363a46ff, 0x2f4f48ff, 0x0baa4bff, 0x0ba94cff, + 0x0ba84cff, 0x0ba74cff, 0x256248ff, 0x353a45ff, 0x343944ff, 0x343944ff, + 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, + 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, + 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, + 0x2c393fff, 0x2d393eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4e4856ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, + 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, + 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, + 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, + 0x434350ff, 0x31694cff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, 0x0cb846ff, + 0x334a48ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, + 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x304846ff, + 0x0ba94cff, 0x0ba84cff, 0x0ba74cff, 0x0ba64dff, 0x285b48ff, 0x343944ff, + 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, + 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, + 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, + 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2d383dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4e4856ff, 0x4d4857ff, + 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, + 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, + 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, + 0x434450ff, 0x434350ff, 0x424350ff, 0x34624cff, 0x0cba45ff, 0x0cb945ff, + 0x0cb846ff, 0x0cb746ff, 0x374248ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, + 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, + 0x363a46ff, 0x344146ff, 0x0ba84cff, 0x0ba74cff, 0x0ba64dff, 0x0ba54dff, + 0x2a5447ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, + 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, + 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, + 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2c383eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4d4855ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, + 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, + 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, + 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x365b4dff, + 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x0cb447ff, 0x383c48ff, 0x393a48ff, + 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, + 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x353b46ff, 0x0ba64cff, 0x0ba64dff, + 0x0ba54dff, 0x0ba44eff, 0x2c4e46ff, 0x333944ff, 0x333a44ff, 0x333943ff, + 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, + 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, + 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, + 0x2b373eff, 0x2c383dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4d4755ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, + 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, + 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, + 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, + 0x41434fff, 0x3a534dff, 0x0cb846ff, 0x0cb746ff, 0x0cb547ff, 0x0eae47ff, + 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, + 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, + 0x0ca14cff, 0x0ba54dff, 0x0ba44eff, 0x0ba24eff, 0x2e4746ff, 0x333a44ff, + 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, + 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, + 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, + 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2b383dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d4755ff, 0x4c4756ff, + 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, + 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, + 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, + 0x42434fff, 0x41434fff, 0x41424eff, 0x3b4c4dff, 0x0cb746ff, 0x0cb547ff, + 0x0cb447ff, 0x11a548ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, + 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, + 0x363a45ff, 0x353a45ff, 0x109a4cff, 0x0ba44eff, 0x0ba24eff, 0x0ba14fff, + 0x304245ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, + 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, + 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, + 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2b383dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4d4754ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, + 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, + 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, + 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x3e454eff, + 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x139f48ff, 0x383b48ff, 0x383b47ff, + 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, + 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x11934cff, 0x0ba24eff, + 0x0ba14fff, 0x0ba04fff, 0x323b43ff, 0x333943ff, 0x323943ff, 0x333a43ff, + 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, + 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, + 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, + 0x2a383eff, 0x2a383cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4c4754ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, + 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, + 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, + 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, + 0x40424eff, 0x3f424dff, 0x0eb147ff, 0x0cb348ff, 0x0cb248ff, 0x169648ff, + 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, + 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, + 0x148b4cff, 0x0ba14fff, 0x0ba04fff, 0x0d9c4fff, 0x333943ff, 0x323943ff, + 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, + 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, + 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, + 0x2a383eff, 0x2a383eff, 0x29383dff, 0x2a383cff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4c4754ff, 0x4a4655ff, + 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, + 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, + 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, + 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x10aa49ff, 0x0cb248ff, + 0x0bb148ff, 0x188f48ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, + 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, + 0x343944ff, 0x343944ff, 0x16844cff, 0x0ba04fff, 0x0b9f50ff, 0x0f954fff, + 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, + 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, + 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, + 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x29383cff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4b4653ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, + 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, + 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, + 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, + 0x13a249ff, 0x0bb148ff, 0x0bb049ff, 0x1a8848ff, 0x373947ff, 0x363a46ff, + 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, + 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x187e4cff, 0x0b9f50ff, + 0x0b9e50ff, 0x108e4eff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, + 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, + 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, + 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, + 0x28383dff, 0x29383bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4b4653ff, 0x494654ff, 0x494654ff, 0x484554ff, + 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, + 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, + 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, + 0x3e414dff, 0x3e414cff, 0x159b49ff, 0x0bb049ff, 0x0baf49ff, 0x1d8049ff, + 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, + 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, + 0x1b774bff, 0x0b9e50ff, 0x0b9d50ff, 0x12884eff, 0x323942ff, 0x323841ff, + 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, + 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, + 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, + 0x29383dff, 0x28383dff, 0x28383cff, 0x28383bff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4a4652ff, 0x494654ff, + 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, + 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, + 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, + 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x189349ff, 0x0baf49ff, + 0x0bae4aff, 0x1e7949ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, + 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, + 0x333a44ff, 0x333943ff, 0x1d714aff, 0x0b9d50ff, 0x0a9c51ff, 0x14824dff, + 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, + 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, + 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, + 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x28373aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4a4652ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, + 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, + 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, + 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, + 0x207f49ff, 0x0bae4aff, 0x0bad4aff, 0x276449ff, 0x363a46ff, 0x363a45ff, + 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, + 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x235e48ff, 0x0a9c51ff, + 0x0a9b51ff, 0x1c6e4bff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, + 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, + 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, + 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, + 0x27373bff, 0x27373aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x494552ff, 0x484553ff, 0x474553ff, 0x474553ff, + 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, + 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, + 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, + 0x3d414bff, 0x3c414bff, 0x3a454aff, 0x237048ff, 0x256749ff, 0x363b46ff, + 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, + 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, + 0x333b43ff, 0x225f48ff, 0x206549ff, 0x2e3d43ff, 0x303941ff, 0x303941ff, + 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, + 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, + 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, + 0x27383cff, 0x27373bff, 0x26373bff, 0x27373aff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x494551ff, 0x474553ff, + 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, + 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, + 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, + 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b3f49ff, + 0x373b47ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, + 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, + 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, + 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, + 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, + 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, + 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, 0x263739ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x484551ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, + 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, + 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, + 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, + 0x3b404aff, 0x3a404aff, 0x3a3f48ff, 0x363b47ff, 0x363a45ff, 0x353a45ff, + 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, + 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, + 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, + 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, + 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, + 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, + 0x25373aff, 0x263739ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x484551ff, 0x464552ff, 0x464452ff, 0x454451ff, + 0x444451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, + 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, + 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, + 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f47ff, + 0x363b45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, + 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, + 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, + 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, + 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, + 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, + 0x26373bff, 0x25373aff, 0x25373aff, 0x253639ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x474550ff, 0x464452ff, + 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, + 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, + 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, + 0x3c404bff, 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, + 0x393f48ff, 0x383f48ff, 0x383f48ff, 0x353b45ff, 0x343944ff, 0x333944ff, + 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, + 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, + 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, + 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, + 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, + 0x26373bff, 0x26373bff, 0x25373aff, 0x25373aff, 0x24363aff, 0x253638ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x474450ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, + 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, + 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, + 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, + 0x393f49ff, 0x393f48ff, 0x383f48ff, 0x383f48ff, 0x373e47ff, 0x373e47ff, + 0x353b45ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, + 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, + 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, + 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, + 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, + 0x27373bff, 0x26373bff, 0x26373bff, 0x25373aff, 0x25373aff, 0x24363aff, + 0x243639ff, 0x243638ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x46444fff, 0x454451ff, 0x444451ff, 0x434450ff, + 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, + 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, + 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b404aff, 0x3a404aff, + 0x3a3f49ff, 0x393f49ff, 0x393f48ff, 0x383f48ff, 0x383f48ff, 0x373e47ff, + 0x373e47ff, 0x363e47ff, 0x363e46ff, 0x333944ff, 0x333943ff, 0x323943ff, + 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, + 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, + 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, + 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, + 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, 0x25373aff, 0x25373aff, + 0x24363aff, 0x243639ff, 0x233639ff, 0x243637ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46404aff, 0x444451ff, + 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, + 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, + 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b404aff, + 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f48ff, 0x383f48ff, 0x383f48ff, + 0x373e47ff, 0x373e47ff, 0x363e47ff, 0x363e46ff, 0x353d46ff, 0x353d45ff, + 0x323a43ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, + 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, + 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, + 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, + 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, 0x25373aff, + 0x25373aff, 0x24363aff, 0x243639ff, 0x233639ff, 0x233638ff, 0x293333ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x553c3aea, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, + 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, + 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, + 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f48ff, 0x383f48ff, + 0x383f48ff, 0x373e47ff, 0x373e47ff, 0x363e47ff, 0x363e46ff, 0x353d46ff, + 0x353d45ff, 0x343d45ff, 0x343d45ff, 0x323a42ff, 0x323841ff, 0x303842ff, + 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, + 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, + 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, + 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, + 0x25373aff, 0x25373aff, 0x24363aff, 0x243639ff, 0x233639ff, 0x233638ff, + 0x223538ff, 0x41332be9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x713c3522, 0x4e3c3df7, 0x424350ff, 0x42434fff, + 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, + 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, + 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f48ff, + 0x383f48ff, 0x383f48ff, 0x373e47ff, 0x373e47ff, 0x363e47ff, 0x363e46ff, + 0x353d46ff, 0x353d45ff, 0x343d45ff, 0x343d45ff, 0x333d44ff, 0x333c44ff, + 0x313943ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, + 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, + 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, + 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, + 0x26373bff, 0x25373aff, 0x25373aff, 0x24363aff, 0x243639ff, 0x233639ff, + 0x233638ff, 0x223538ff, 0x38332ef6, 0x60382820, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6d3d2c4b, 0x673d2f97, 0x633d309b, 0x633d309b, 0x633d309b, 0x633d309b, + 0x633d309b, 0x633b309b, 0x633b2e9b, 0x613b2e9b, 0x613b2e9b, 0x613b2e9b, + 0x613b2e9b, 0x613b2e9b, 0x613b2e9b, 0x5f3b2e9b, 0x5f3b2c9b, 0x5f3b2c9b, + 0x5f3b2c9b, 0x5f3b2c9b, 0x5f3b2c9b, 0x5f3b2c9b, 0x5f3b2c9b, 0x5e3b2c9b, + 0x5e3b2c9b, 0x5e3a2c9b, 0x5e3a2b9b, 0x5e3a2b9b, 0x5e3a2b9b, 0x5e3a2b9b, + 0x5e3a2b9b, 0x5c3a2b9b, 0x5c3a2b9b, 0x5b372a9d, 0x5b372a9d, 0x5b372c9d, + 0x5b372c9d, 0x5b372a9d, 0x5c392b9c, 0x58382b9c, 0x58382b9c, 0x58382b9c, + 0x5a38299c, 0x5a38299c, 0x5838299c, 0x5838299c, 0x5938299b, 0x5938299b, + 0x5938279b, 0x5938279b, 0x5938279b, 0x5938279b, 0x5738279b, 0x5738279b, + 0x5738279b, 0x5738279b, 0x5738269b, 0x5738269b, 0x5736269b, 0x5736269b, + 0x5636269b, 0x5636269b, 0x5a382597, 0x633a224b, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; diff --git a/games/NXDoom/src/heretic/in_lude.c b/games/NXDoom/src/heretic/in_lude.c new file mode 100644 index 00000000000..a8ac4255dcf --- /dev/null +++ b/games/NXDoom/src/heretic/in_lude.c @@ -0,0 +1,1075 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +/* +======================== += += IN_lude.c += +======================== +*/ + +#include "doomdef.h" +#include "deh_str.h" +#include "p_local.h" +#include "s_sound.h" +#include "i_swap.h" +#include "i_system.h" +#include "i_video.h" +#include "v_video.h" +#include "am_map.h" + + +typedef enum +{ + SINGLE, + COOPERATIVE, + DEATHMATCH +} gametype_t; + +// Public functions + + +boolean intermission; + +// Private functions + +static void IN_WaitStop(void); +static void IN_Stop(void); +static void IN_LoadPics(void); +static void IN_UnloadPics(void); +static void IN_CheckForSkip(void); +static void IN_InitStats(void); +static void IN_DrawOldLevel(void); +static void IN_DrawYAH(void); +static void IN_DrawStatBack(void); +static void IN_DrawSingleStats(void); +static void IN_DrawCoopStats(void); +static void IN_DrawDMStats(void); +static void IN_DrawNumber(int val, int x, int y, int digits); +static void IN_DrawTime(int x, int y, int h, int m, int s); +static void IN_DrTextB(const char *text, int x, int y); + +static boolean skipintermission; +static int interstate = 0; +static int intertime = -1; +static int oldintertime = 0; +static gametype_t gametype; + +static int cnt; + +static int hours; +static int minutes; +static int seconds; + +static int slaughterboy; // in DM, the player with the most kills + +static int killPercent[MAXPLAYERS]; +static int bonusPercent[MAXPLAYERS]; +static int secretPercent[MAXPLAYERS]; + +static patch_t *patchINTERPIC; +static patch_t *patchBEENTHERE; +static patch_t *patchGOINGTHERE; +static patch_t *FontBNumbers[10]; +static patch_t *FontBNegative; +static patch_t *FontBSlash; +static patch_t *FontBPercent; + +static int FontBLump; +static int FontBLumpBase; +static int patchFaceOkayBase; +static int patchFaceDeadBase; + +static signed int totalFrags[MAXPLAYERS]; +static fixed_t dSlideX[MAXPLAYERS]; +static fixed_t dSlideY[MAXPLAYERS]; + +static const char *KillersText[] = { "K", "I", "L", "L", "E", "R", "S" }; + + +typedef struct +{ + int x; + int y; +} yahpt_t; + +static yahpt_t YAHspot[3][9] = { + { + {172, 78}, + {86, 90}, + {73, 66}, + {159, 95}, + {148, 126}, + {132, 54}, + {131, 74}, + {208, 138}, + {52, 101} + }, + { + {218, 57}, + {137, 81}, + {155, 124}, + {171, 68}, + {250, 86}, + {136, 98}, + {203, 90}, + {220, 140}, + {279, 106} + }, + { + {86, 99}, + {124, 103}, + {154, 79}, + {202, 83}, + {178, 59}, + {142, 58}, + {219, 66}, + {247, 57}, + {107, 80} + } +}; + +static const char *NameForMap(int map) +{ + const char *name = LevelNames[(gameepisode - 1) * 9 + map - 1]; + name = DEH_String(name); + if (strlen(name) < 7) + { + return ""; + } + return name + 7; +} + +//======================================================================== +// +// IN_Start +// +//======================================================================== + + +void IN_Start(void) +{ + I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE)); + IN_LoadPics(); + IN_InitStats(); + intermission = true; + interstate = -1; + skipintermission = false; + intertime = 0; + oldintertime = 0; + AM_Stop(); + S_StartSong(mus_intr, true); +} + +//======================================================================== +// +// IN_WaitStop +// +//======================================================================== + +void IN_WaitStop(void) +{ + if (!--cnt) + { + IN_Stop(); + G_WorldDone(); + } +} + +//======================================================================== +// +// IN_Stop +// +//======================================================================== + +void IN_Stop(void) +{ + intermission = false; + IN_UnloadPics(); + SB_state = -1; + BorderNeedRefresh = true; +} + +//======================================================================== +// +// IN_InitStats +// +// Initializes the stats for single player mode +//======================================================================== + +void IN_InitStats(void) +{ + int i; + int j; + signed int slaughterfrags; + int posnum; + int slaughtercount; + int playercount; + int count; + + if (!netgame) + { + gametype = SINGLE; + count = leveltime / 35; + hours = count / 3600; + count -= hours * 3600; + minutes = count / 60; + count -= minutes * 60; + seconds = count; + } + else if (netgame && !deathmatch) + { + gametype = COOPERATIVE; + memset(killPercent, 0, MAXPLAYERS * sizeof(int)); + memset(bonusPercent, 0, MAXPLAYERS * sizeof(int)); + memset(secretPercent, 0, MAXPLAYERS * sizeof(int)); + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (totalkills) + { + killPercent[i] = players[i].killcount * 100 / totalkills; + } + if (totalitems) + { + bonusPercent[i] = players[i].itemcount * 100 / totalitems; + } + if (totalsecret) + { + secretPercent[i] = + players[i].secretcount * 100 / totalsecret; + } + } + } + } + else + { + gametype = DEATHMATCH; + slaughterboy = 0; + slaughterfrags = -9999; + posnum = 0; + playercount = 0; + slaughtercount = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + totalFrags[i] = 0; + if (playeringame[i]) + { + playercount++; + for (j = 0; j < MAXPLAYERS; j++) + { + if (playeringame[j]) + { + totalFrags[i] += players[i].frags[j]; + } + } + dSlideX[i] = (43 * posnum * FRACUNIT) / 20; + dSlideY[i] = (36 * posnum * FRACUNIT) / 20; + posnum++; + } + if (totalFrags[i] > slaughterfrags) + { + slaughterboy = 1 << i; + slaughterfrags = totalFrags[i]; + slaughtercount = 1; + } + else if (totalFrags[i] == slaughterfrags) + { + slaughterboy |= 1 << i; + slaughtercount++; + } + } + if (playercount == slaughtercount) + { // don't do the slaughter stuff if everyone is equal + slaughterboy = 0; + } + } +} + +static void IN_LoadUnloadPics(void (*callback)(const char *lumpname, + int lumpnum, + patch_t **ptr)) +{ + int i; + + switch (gameepisode) + { + case 1: + callback(DEH_String("MAPE1"), 0, &patchINTERPIC); + break; + case 2: + callback(DEH_String("MAPE2"), 0, &patchINTERPIC); + break; + case 3: + callback(DEH_String("MAPE3"), 0, &patchINTERPIC); + break; + default: + break; + } + + callback(DEH_String("IN_X"), 0, &patchBEENTHERE); + callback(DEH_String("IN_YAH"), 0, &patchGOINGTHERE); + callback(DEH_String("FONTB13"), 0, &FontBNegative); + + callback(DEH_String("FONTB15"), 0, &FontBSlash); + callback(DEH_String("FONTB05"), 0, &FontBPercent); + + FontBLumpBase = W_GetNumForName(DEH_String("FONTB16")); + + for (i = 0; i < 10; i++) + { + callback(NULL, FontBLumpBase + i, &FontBNumbers[i]); + } +} + +//======================================================================== +// +// IN_LoadPics +// +//======================================================================== + +static void LoadLumpCallback(const char *lumpname, int lumpnum, patch_t **ptr) +{ + if (lumpname != NULL) + { + lumpnum = W_GetNumForName(lumpname); + } + + // Cache the lump + + *ptr = W_CacheLumpNum(lumpnum, PU_STATIC); +} + +void IN_LoadPics(void) +{ + FontBLump = W_GetNumForName(DEH_String("FONTB_S")) + 1; + patchFaceOkayBase = W_GetNumForName(DEH_String("FACEA0")); + patchFaceDeadBase = W_GetNumForName(DEH_String("FACEB0")); + + IN_LoadUnloadPics(LoadLumpCallback); +} + +//======================================================================== +// +// IN_UnloadPics +// +//======================================================================== + +static void UnloadLumpCallback(const char *lumpname, int lumpnum, patch_t **ptr) +{ + if (lumpname != NULL) + { + W_ReleaseLumpName(lumpname); + } + else + { + W_ReleaseLumpNum(lumpnum); + } +} + +void IN_UnloadPics(void) +{ + IN_LoadUnloadPics(UnloadLumpCallback); +} + +//======================================================================== +// +// IN_Ticker +// +//======================================================================== + +void IN_Ticker(void) +{ + if (!intermission) + { + return; + } + if (interstate == 3) + { + IN_WaitStop(); + return; + } + IN_CheckForSkip(); + intertime++; + if (oldintertime < intertime) + { + interstate++; + if (gameepisode > 3 && interstate >= 1) + { // Extended Wad levels: skip directly to the next level + interstate = 3; + } + switch (interstate) + { + case 0: + oldintertime = intertime + 300; + if (gameepisode > 3) + { + oldintertime = intertime + 1200; + } + break; + case 1: + oldintertime = intertime + 200; + break; + case 2: + oldintertime = INT_MAX; + break; + case 3: + cnt = 10; + break; + default: + break; + } + } + if (skipintermission) + { + if (interstate == 0 && intertime < 150) + { + intertime = 150; + skipintermission = false; + return; + } + else if (interstate < 2 && gameepisode < 4) + { + interstate = 2; + skipintermission = false; + S_StartSound(NULL, sfx_dorcls); + return; + } + interstate = 3; + cnt = 10; + skipintermission = false; + S_StartSound(NULL, sfx_dorcls); + } +} + +//======================================================================== +// +// IN_CheckForSkip +// +// Check to see if any player hit a key +//======================================================================== + +void IN_CheckForSkip(void) +{ + int i; + player_t *player; + + for (i = 0, player = players; i < MAXPLAYERS; i++, player++) + { + if (playeringame[i]) + { + if (player->cmd.buttons & BT_ATTACK) + { + if (!player->attackdown) + { + skipintermission = 1; + } + player->attackdown = true; + } + else + { + player->attackdown = false; + } + if (player->cmd.buttons & BT_USE) + { + if (!player->usedown) + { + skipintermission = 1; + } + player->usedown = true; + } + else + { + player->usedown = false; + } + } + } +} + +//======================================================================== +// +// IN_Drawer +// +//======================================================================== + +void IN_Drawer(void) +{ + static int oldinterstate; + + if (!intermission) + { + return; + } + if (interstate == 3) + { + return; + } + UpdateState |= I_FULLSCRN; + if (oldinterstate != 2 && interstate == 2) + { + S_StartSound(NULL, sfx_pstop); + } + oldinterstate = interstate; + switch (interstate) + { + case 0: // draw stats + IN_DrawStatBack(); + switch (gametype) + { + case SINGLE: + IN_DrawSingleStats(); + break; + case COOPERATIVE: + IN_DrawCoopStats(); + break; + case DEATHMATCH: + IN_DrawDMStats(); + break; + } + break; + case 1: // leaving old level + if (gameepisode < 4) + { + V_DrawPatch(0, 0, patchINTERPIC); + IN_DrawOldLevel(); + } + break; + case 2: // going to the next level + if (gameepisode < 4) + { + V_DrawPatch(0, 0, patchINTERPIC); + IN_DrawYAH(); + } + break; + case 3: // waiting before going to the next level + if (gameepisode < 4) + { + V_DrawPatch(0, 0, patchINTERPIC); + } + break; + default: + I_Error("IN_lude: Intermission state out of range.\n"); + break; + } +} + +//======================================================================== +// +// IN_DrawStatBack +// +//======================================================================== + +void IN_DrawStatBack(void) +{ + int x; + int y; + + byte *src; + byte *dest; + + src = W_CacheLumpName(DEH_String("FLOOR16"), PU_CACHE); + dest = I_VideoBuffer; + + for (y = 0; y < SCREENHEIGHT; y++) + { + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } +} + +//======================================================================== +// +// IN_DrawOldLevel +// +//======================================================================== + +void IN_DrawOldLevel(void) +{ + const char *level_name = NameForMap(prevmap); + int i; + int x; + + x = 160 - MN_TextBWidth(level_name) / 2; + IN_DrTextB(level_name, x, 3); + x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2; + MN_DrTextA(DEH_String("FINISHED"), x, 25); + + if (prevmap == 9) + { + for (i = 0; i < gamemap - 1; i++) + { + V_DrawPatch(YAHspot[gameepisode - 1][i].x, + YAHspot[gameepisode - 1][i].y, patchBEENTHERE); + } + if (!(intertime & 16)) + { + V_DrawPatch(YAHspot[gameepisode - 1][8].x, + YAHspot[gameepisode - 1][8].y, patchBEENTHERE); + } + } + else + { + for (i = 0; i < prevmap - 1; i++) + { + V_DrawPatch(YAHspot[gameepisode - 1][i].x, + YAHspot[gameepisode - 1][i].y, patchBEENTHERE); + } + if (players[consoleplayer].didsecret) + { + V_DrawPatch(YAHspot[gameepisode - 1][8].x, + YAHspot[gameepisode - 1][8].y, patchBEENTHERE); + } + if (!(intertime & 16)) + { + V_DrawPatch(YAHspot[gameepisode - 1][prevmap - 1].x, + YAHspot[gameepisode - 1][prevmap - 1].y, + patchBEENTHERE); + } + } +} + +//======================================================================== +// +// IN_DrawYAH +// +//======================================================================== + +void IN_DrawYAH(void) +{ + const char *level_name = NameForMap(gamemap); + int i; + int x; + + x = 160 - MN_TextAWidth(DEH_String("NOW ENTERING:")) / 2; + MN_DrTextA(DEH_String("NOW ENTERING:"), x, 10); + x = 160 - MN_TextBWidth(level_name) / 2; + IN_DrTextB(level_name, x, 20); + + if (prevmap == 9) + { + prevmap = gamemap - 1; + } + for (i = 0; i < prevmap; i++) + { + V_DrawPatch(YAHspot[gameepisode - 1][i].x, + YAHspot[gameepisode - 1][i].y, patchBEENTHERE); + } + if (players[consoleplayer].didsecret) + { + V_DrawPatch(YAHspot[gameepisode - 1][8].x, + YAHspot[gameepisode - 1][8].y, patchBEENTHERE); + } + if (!(intertime & 16) || interstate == 3) + { // draw the destination 'X' + V_DrawPatch(YAHspot[gameepisode - 1][gamemap - 1].x, + YAHspot[gameepisode - 1][gamemap - 1].y, patchGOINGTHERE); + } +} + +//======================================================================== +// +// IN_DrawSingleStats +// +//======================================================================== + +void IN_DrawSingleStats(void) +{ + const char *prev_level_name = NameForMap(prevmap); + const char *next_level_name = NameForMap(gamemap); + int x; + static int sounds; + + IN_DrTextB(DEH_String("KILLS"), 50, 65); + IN_DrTextB(DEH_String("ITEMS"), 50, 90); + IN_DrTextB(DEH_String("SECRETS"), 50, 115); + + x = 160 - MN_TextBWidth(prev_level_name) / 2; + IN_DrTextB(prev_level_name, x, 3); + x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2; + MN_DrTextA(DEH_String("FINISHED"), x, 25); + + if (intertime < 30) + { + sounds = 0; + return; + } + if (sounds < 1 && intertime >= 30) + { + S_StartSound(NULL, sfx_dorcls); + sounds++; + } + IN_DrawNumber(players[consoleplayer].killcount, 200, 65, 3); + V_DrawShadowedPatch(237, 65, FontBSlash); + IN_DrawNumber(totalkills, 248, 65, 3); + if (intertime < 60) + { + return; + } + if (sounds < 2 && intertime >= 60) + { + S_StartSound(NULL, sfx_dorcls); + sounds++; + } + IN_DrawNumber(players[consoleplayer].itemcount, 200, 90, 3); + V_DrawShadowedPatch(237, 90, FontBSlash); + IN_DrawNumber(totalitems, 248, 90, 3); + if (intertime < 90) + { + return; + } + if (sounds < 3 && intertime >= 90) + { + S_StartSound(NULL, sfx_dorcls); + sounds++; + } + IN_DrawNumber(players[consoleplayer].secretcount, 200, 115, 3); + V_DrawShadowedPatch(237, 115, FontBSlash); + IN_DrawNumber(totalsecret, 248, 115, 3); + if (intertime < 150) + { + return; + } + if (sounds < 4 && intertime >= 150) + { + S_StartSound(NULL, sfx_dorcls); + sounds++; + } + + if (gamemode != retail || gameepisode <= 3) + { + IN_DrTextB(DEH_String("TIME"), 85, 160); + IN_DrawTime(155, 160, hours, minutes, seconds); + } + else + { + x = 160 - MN_TextAWidth(DEH_String("NOW ENTERING:")) / 2; + MN_DrTextA(DEH_String("NOW ENTERING:"), x, 160); + x = 160 - MN_TextBWidth(next_level_name) / 2; + IN_DrTextB(next_level_name, x, 170); + skipintermission = false; + } +} + +//======================================================================== +// +// IN_DrawCoopStats +// +//======================================================================== + +void IN_DrawCoopStats(void) +{ + const char *level_name = NameForMap(prevmap); + int i; + int x; + int ypos; + + static int sounds; + + IN_DrTextB(DEH_String("KILLS"), 95, 35); + IN_DrTextB(DEH_String("BONUS"), 155, 35); + IN_DrTextB(DEH_String("SECRET"), 232, 35); + x = 160 - MN_TextBWidth(level_name) / 2; + IN_DrTextB(level_name, x, 3); + x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2; + MN_DrTextA(DEH_String("FINISHED"), x, 25); + + ypos = 50; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + V_DrawShadowedPatch(25, ypos, + W_CacheLumpNum(patchFaceOkayBase + i, + PU_CACHE)); + if (intertime < 40) + { + sounds = 0; + ypos += 37; + continue; + } + else if (intertime >= 40 && sounds < 1) + { + S_StartSound(NULL, sfx_dorcls); + sounds++; + } + IN_DrawNumber(killPercent[i], 85, ypos + 10, 3); + V_DrawShadowedPatch(121, ypos + 10, FontBPercent); + IN_DrawNumber(bonusPercent[i], 160, ypos + 10, 3); + V_DrawShadowedPatch(196, ypos + 10, FontBPercent); + IN_DrawNumber(secretPercent[i], 237, ypos + 10, 3); + V_DrawShadowedPatch(273, ypos + 10, FontBPercent); + ypos += 37; + } + } +} + +//======================================================================== +// +// IN_DrawDMStats +// +//======================================================================== + +void IN_DrawDMStats(void) +{ + int i; + int j; + int ypos; + int xpos; + int kpos; + + static int sounds; + + xpos = 90; + ypos = 55; + + IN_DrTextB(DEH_String("TOTAL"), 265, 30); + MN_DrTextA(DEH_String("VICTIMS"), 140, 8); + for (i = 0; i < 7; i++) + { + MN_DrTextA(DEH_String(KillersText[i]), 10, 80 + 9 * i); + } + if (intertime < 20) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + V_DrawShadowedPatch(40, + ((ypos << FRACBITS) + + dSlideY[i] * intertime) >> FRACBITS, + W_CacheLumpNum(patchFaceOkayBase + i, + PU_CACHE)); + V_DrawShadowedPatch(((xpos << FRACBITS) + + dSlideX[i] * intertime) >> FRACBITS, 18, + W_CacheLumpNum(patchFaceDeadBase + i, + PU_CACHE)); + } + } + sounds = 0; + return; + } + if (intertime >= 20 && sounds < 1) + { + S_StartSound(NULL, sfx_dorcls); + sounds++; + } + if (intertime >= 100 && slaughterboy && sounds < 2) + { + S_StartSound(NULL, sfx_wpnup); + sounds++; + } + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (intertime < 100 || i == consoleplayer) + { + V_DrawShadowedPatch(40, ypos, + W_CacheLumpNum(patchFaceOkayBase + i, + PU_CACHE)); + V_DrawShadowedPatch(xpos, 18, + W_CacheLumpNum(patchFaceDeadBase + i, + PU_CACHE)); + } + else + { + V_DrawAltTLPatch(40, ypos, + W_CacheLumpNum(patchFaceOkayBase + i, + PU_CACHE)); + V_DrawAltTLPatch(xpos, 18, + W_CacheLumpNum(patchFaceDeadBase + i, + PU_CACHE)); + } + kpos = 86; + for (j = 0; j < MAXPLAYERS; j++) + { + if (playeringame[j]) + { + IN_DrawNumber(players[i].frags[j], kpos, ypos + 10, 3); + kpos += 43; + } + } + if (slaughterboy & (1 << i)) + { + if (!(intertime & 16)) + { + IN_DrawNumber(totalFrags[i], 263, ypos + 10, 3); + } + } + else + { + IN_DrawNumber(totalFrags[i], 263, ypos + 10, 3); + } + ypos += 36; + xpos += 43; + } + } +} + +//======================================================================== +// +// IN_DrawTime +// +//======================================================================== + +void IN_DrawTime(int x, int y, int h, int m, int s) +{ + if (h) + { + IN_DrawNumber(h, x, y, 2); + IN_DrTextB(DEH_String(":"), x + 26, y); + } + x += 34; + if (m || h) + { + IN_DrawNumber(m, x, y, 2); + } + x += 34; + if (s) + { + IN_DrTextB(DEH_String(":"), x - 8, y); + IN_DrawNumber(s, x, y, 2); + } +} + +//======================================================================== +// +// IN_DrawNumber +// +//======================================================================== + +void IN_DrawNumber(int val, int x, int y, int digits) +{ + patch_t *patch; + int xpos; + int oldval; + int realdigits; + boolean neg; + + oldval = val; + xpos = x; + neg = false; + realdigits = 1; + + if (val < 0) + { //...this should reflect negative frags + val = -val; + neg = true; + if (val > 99) + { + val = 99; + } + } + if (val > 9) + { + realdigits++; + if (digits < realdigits) + { + realdigits = digits; + val = 9; + } + } + if (val > 99) + { + realdigits++; + if (digits < realdigits) + { + realdigits = digits; + val = 99; + } + } + if (val > 999) + { + realdigits++; + if (digits < realdigits) + { + realdigits = digits; + val = 999; + } + } + if (digits == 4) + { + patch = FontBNumbers[val / 1000]; + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2 - 12, y, patch); + } + if (digits > 2) + { + if (realdigits > 2) + { + patch = FontBNumbers[val / 100]; + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + } + xpos += 12; + } + val = val % 100; + if (digits > 1) + { + if (val > 9) + { + patch = FontBNumbers[val / 10]; + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + } + else if (digits == 2 || oldval > 99) + { + V_DrawShadowedPatch(xpos, y, FontBNumbers[0]); + } + xpos += 12; + } + val = val % 10; + patch = FontBNumbers[val]; + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + if (neg) + { + patch = FontBNegative; + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2 - 12 * (realdigits), + y, patch); + } +} + +//======================================================================== +// +// IN_DrTextB +// +//======================================================================== + +void IN_DrTextB(const char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 8; + } + else + { + p = W_CacheLumpNum(FontBLump + c - 33, PU_CACHE); + V_DrawShadowedPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} diff --git a/games/NXDoom/src/heretic/info.c b/games/NXDoom/src/heretic/info.c new file mode 100644 index 00000000000..d736325b761 --- /dev/null +++ b/games/NXDoom/src/heretic/info.c @@ -0,0 +1,5600 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +#include "doomdef.h" +#include "p_action.h" + +const char *sprnames[] = { + "IMPX","ACLO","PTN1","SHLD","SHD2","BAGH","SPMP","INVS","PTN2","SOAR", + "INVU","PWBK","EGGC","EGGM","FX01","SPHL","TRCH","FBMB","XPL1","ATLP", + "PPOD","AMG1","SPSH","LVAS","SLDG","SKH1","SKH2","SKH3","SKH4","CHDL", + "SRTC","SMPL","STGS","STGL","STCS","STCL","KFR1","BARL","BRPL","MOS1", + "MOS2","WTRH","HCOR","KGZ1","KGZB","KGZG","KGZY","VLCO","VFBL","VTFB", + "SFFI","TGLT","TELE","STFF","PUF3","PUF4","BEAK","WGNT","GAUN","PUF1", + "WBLS","BLSR","FX18","FX17","WMCE","MACE","FX02","WSKL","HROD","FX00", + "FX20","FX21","FX22","FX23","GWND","PUF2","WPHX","PHNX","FX04","FX08", + "FX09","WBOW","CRBW","FX03","BLOD","PLAY","FDTH","BSKL","CHKN","MUMM", + "FX15","BEAS","FRB1","SNKE","SNFX","HEAD","FX05","FX06","FX07","CLNK", + "WZRD","FX11","FX10","KNIG","SPAX","RAXE","SRCR","FX14","SOR2","SDTH", + "FX16","MNTR","FX12","FX13","AKYY","BKYY","CKYY","AMG2","AMM1","AMM2", + "AMC1","AMC2","AMS1","AMS2","AMP1","AMP2","AMB1","AMB2", + NULL +}; + +state_t states[NUMSTATES] = { + {SPR_IMPX, 0, -1, NULL, S_NULL, 0, 0}, // S_NULL + {SPR_ACLO, 4, 1050, A_FreeTargMobj, S_NULL, 0, 0}, // S_FREETARGMOBJ + {SPR_PTN1, 0, 3, NULL, S_ITEM_PTN1_2, 0, 0}, // S_ITEM_PTN1_1 + {SPR_PTN1, 1, 3, NULL, S_ITEM_PTN1_3, 0, 0}, // S_ITEM_PTN1_2 + {SPR_PTN1, 2, 3, NULL, S_ITEM_PTN1_1, 0, 0}, // S_ITEM_PTN1_3 + {SPR_SHLD, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_SHLD1 + {SPR_SHD2, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_SHD2_1 + {SPR_BAGH, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_BAGH1 + {SPR_SPMP, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_SPMP1 + {SPR_ACLO, 4, 1400, NULL, S_HIDESPECIAL2, 0, 0}, // S_HIDESPECIAL1 + {SPR_ACLO, 0, 4, A_RestoreSpecialThing1, S_HIDESPECIAL3, 0, 0}, // S_HIDESPECIAL2 + {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL4, 0, 0}, // S_HIDESPECIAL3 + {SPR_ACLO, 0, 4, NULL, S_HIDESPECIAL5, 0, 0}, // S_HIDESPECIAL4 + {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL6, 0, 0}, // S_HIDESPECIAL5 + {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL7, 0, 0}, // S_HIDESPECIAL6 + {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL8, 0, 0}, // S_HIDESPECIAL7 + {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL9, 0, 0}, // S_HIDESPECIAL8 + {SPR_ACLO, 3, 4, NULL, S_HIDESPECIAL10, 0, 0}, // S_HIDESPECIAL9 + {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL11, 0, 0}, // S_HIDESPECIAL10 + {SPR_ACLO, 3, 4, A_RestoreSpecialThing2, S_NULL, 0, 0}, // S_HIDESPECIAL11 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2, 0, 0}, // S_DORMANTARTI1 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3, 0, 0}, // S_DORMANTARTI2 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI4, 0, 0}, // S_DORMANTARTI3 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI5, 0, 0}, // S_DORMANTARTI4 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI6, 0, 0}, // S_DORMANTARTI5 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI7, 0, 0}, // S_DORMANTARTI6 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI8, 0, 0}, // S_DORMANTARTI7 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI9, 0, 0}, // S_DORMANTARTI8 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI10, 0, 0}, // S_DORMANTARTI9 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI11, 0, 0}, // S_DORMANTARTI10 + {SPR_ACLO, 0, 1400, A_HideThing, S_DORMANTARTI12, 0, 0}, // S_DORMANTARTI11 + {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI13, 0, 0}, // S_DORMANTARTI12 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI14, 0, 0}, // S_DORMANTARTI13 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI15, 0, 0}, // S_DORMANTARTI14 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI16, 0, 0}, // S_DORMANTARTI15 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI17, 0, 0}, // S_DORMANTARTI16 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI18, 0, 0}, // S_DORMANTARTI17 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI19, 0, 0}, // S_DORMANTARTI18 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI20, 0, 0}, // S_DORMANTARTI19 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI21, 0, 0}, // S_DORMANTARTI20 + {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI21 + {SPR_ACLO, 3, 3, NULL, S_DEADARTI2, 0, 0}, // S_DEADARTI1 + {SPR_ACLO, 2, 3, NULL, S_DEADARTI3, 0, 0}, // S_DEADARTI2 + {SPR_ACLO, 3, 3, NULL, S_DEADARTI4, 0, 0}, // S_DEADARTI3 + {SPR_ACLO, 2, 3, NULL, S_DEADARTI5, 0, 0}, // S_DEADARTI4 + {SPR_ACLO, 1, 3, NULL, S_DEADARTI6, 0, 0}, // S_DEADARTI5 + {SPR_ACLO, 2, 3, NULL, S_DEADARTI7, 0, 0}, // S_DEADARTI6 + {SPR_ACLO, 1, 3, NULL, S_DEADARTI8, 0, 0}, // S_DEADARTI7 + {SPR_ACLO, 0, 3, NULL, S_DEADARTI9, 0, 0}, // S_DEADARTI8 + {SPR_ACLO, 1, 3, NULL, S_DEADARTI10, 0, 0}, // S_DEADARTI9 + {SPR_ACLO, 0, 3, NULL, S_NULL, 0, 0}, // S_DEADARTI10 + {SPR_INVS, 32768, 350, NULL, S_ARTI_INVS1, 0, 0}, // S_ARTI_INVS1 + {SPR_PTN2, 0, 4, NULL, S_ARTI_PTN2_2, 0, 0}, // S_ARTI_PTN2_1 + {SPR_PTN2, 1, 4, NULL, S_ARTI_PTN2_3, 0, 0}, // S_ARTI_PTN2_2 + {SPR_PTN2, 2, 4, NULL, S_ARTI_PTN2_1, 0, 0}, // S_ARTI_PTN2_3 + {SPR_SOAR, 0, 5, NULL, S_ARTI_SOAR2, 0, 0}, // S_ARTI_SOAR1 + {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR3, 0, 0}, // S_ARTI_SOAR2 + {SPR_SOAR, 2, 5, NULL, S_ARTI_SOAR4, 0, 0}, // S_ARTI_SOAR3 + {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR1, 0, 0}, // S_ARTI_SOAR4 + {SPR_INVU, 0, 3, NULL, S_ARTI_INVU2, 0, 0}, // S_ARTI_INVU1 + {SPR_INVU, 1, 3, NULL, S_ARTI_INVU3, 0, 0}, // S_ARTI_INVU2 + {SPR_INVU, 2, 3, NULL, S_ARTI_INVU4, 0, 0}, // S_ARTI_INVU3 + {SPR_INVU, 3, 3, NULL, S_ARTI_INVU1, 0, 0}, // S_ARTI_INVU4 + {SPR_PWBK, 0, 350, NULL, S_ARTI_PWBK1, 0, 0}, // S_ARTI_PWBK1 + {SPR_EGGC, 0, 6, NULL, S_ARTI_EGGC2, 0, 0}, // S_ARTI_EGGC1 + {SPR_EGGC, 1, 6, NULL, S_ARTI_EGGC3, 0, 0}, // S_ARTI_EGGC2 + {SPR_EGGC, 2, 6, NULL, S_ARTI_EGGC4, 0, 0}, // S_ARTI_EGGC3 + {SPR_EGGC, 1, 6, NULL, S_ARTI_EGGC1, 0, 0}, // S_ARTI_EGGC4 + {SPR_EGGM, 0, 4, NULL, S_EGGFX2, 0, 0}, // S_EGGFX1 + {SPR_EGGM, 1, 4, NULL, S_EGGFX3, 0, 0}, // S_EGGFX2 + {SPR_EGGM, 2, 4, NULL, S_EGGFX4, 0, 0}, // S_EGGFX3 + {SPR_EGGM, 3, 4, NULL, S_EGGFX5, 0, 0}, // S_EGGFX4 + {SPR_EGGM, 4, 4, NULL, S_EGGFX1, 0, 0}, // S_EGGFX5 + {SPR_FX01, 32772, 3, NULL, S_EGGFXI1_2, 0, 0}, // S_EGGFXI1_1 + {SPR_FX01, 32773, 3, NULL, S_EGGFXI1_3, 0, 0}, // S_EGGFXI1_2 + {SPR_FX01, 32774, 3, NULL, S_EGGFXI1_4, 0, 0}, // S_EGGFXI1_3 + {SPR_FX01, 32775, 3, NULL, S_NULL, 0, 0}, // S_EGGFXI1_4 + {SPR_SPHL, 0, 350, NULL, S_ARTI_SPHL1, 0, 0}, // S_ARTI_SPHL1 + {SPR_TRCH, 32768, 3, NULL, S_ARTI_TRCH2, 0, 0}, // S_ARTI_TRCH1 + {SPR_TRCH, 32769, 3, NULL, S_ARTI_TRCH3, 0, 0}, // S_ARTI_TRCH2 + {SPR_TRCH, 32770, 3, NULL, S_ARTI_TRCH1, 0, 0}, // S_ARTI_TRCH3 + {SPR_FBMB, 4, 350, NULL, S_ARTI_FBMB1, 0, 0}, // S_ARTI_FBMB1 + {SPR_FBMB, 0, 10, NULL, S_FIREBOMB2, 0, 0}, // S_FIREBOMB1 + {SPR_FBMB, 1, 10, NULL, S_FIREBOMB3, 0, 0}, // S_FIREBOMB2 + {SPR_FBMB, 2, 10, NULL, S_FIREBOMB4, 0, 0}, // S_FIREBOMB3 + {SPR_FBMB, 3, 10, NULL, S_FIREBOMB5, 0, 0}, // S_FIREBOMB4 + {SPR_FBMB, 4, 6, A_Scream, S_FIREBOMB6, 0, 0}, // S_FIREBOMB5 + {SPR_XPL1, 32768, 4, A_Explode, S_FIREBOMB7, 0, 0}, // S_FIREBOMB6 + {SPR_XPL1, 32769, 4, NULL, S_FIREBOMB8, 0, 0}, // S_FIREBOMB7 + {SPR_XPL1, 32770, 4, NULL, S_FIREBOMB9, 0, 0}, // S_FIREBOMB8 + {SPR_XPL1, 32771, 4, NULL, S_FIREBOMB10, 0, 0}, // S_FIREBOMB9 + {SPR_XPL1, 32772, 4, NULL, S_FIREBOMB11, 0, 0}, // S_FIREBOMB10 + {SPR_XPL1, 32773, 4, NULL, S_NULL, 0, 0}, // S_FIREBOMB11 + {SPR_ATLP, 0, 4, NULL, S_ARTI_ATLP2, 0, 0}, // S_ARTI_ATLP1 + {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP3, 0, 0}, // S_ARTI_ATLP2 + {SPR_ATLP, 2, 4, NULL, S_ARTI_ATLP4, 0, 0}, // S_ARTI_ATLP3 + {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP1, 0, 0}, // S_ARTI_ATLP4 + {SPR_PPOD, 0, 10, NULL, S_POD_WAIT1, 0, 0}, // S_POD_WAIT1 + {SPR_PPOD, 1, 14, A_PodPain, S_POD_WAIT1, 0, 0}, // S_POD_PAIN1 + {SPR_PPOD, 32770, 5, A_RemovePod, S_POD_DIE2, 0, 0}, // S_POD_DIE1 + {SPR_PPOD, 32771, 5, A_Scream, S_POD_DIE3, 0, 0}, // S_POD_DIE2 + {SPR_PPOD, 32772, 5, A_Explode, S_POD_DIE4, 0, 0}, // S_POD_DIE3 + {SPR_PPOD, 32773, 10, NULL, S_FREETARGMOBJ, 0, 0}, // S_POD_DIE4 + {SPR_PPOD, 8, 3, NULL, S_POD_GROW2, 0, 0}, // S_POD_GROW1 + {SPR_PPOD, 9, 3, NULL, S_POD_GROW3, 0, 0}, // S_POD_GROW2 + {SPR_PPOD, 10, 3, NULL, S_POD_GROW4, 0, 0}, // S_POD_GROW3 + {SPR_PPOD, 11, 3, NULL, S_POD_GROW5, 0, 0}, // S_POD_GROW4 + {SPR_PPOD, 12, 3, NULL, S_POD_GROW6, 0, 0}, // S_POD_GROW5 + {SPR_PPOD, 13, 3, NULL, S_POD_GROW7, 0, 0}, // S_POD_GROW6 + {SPR_PPOD, 14, 3, NULL, S_POD_GROW8, 0, 0}, // S_POD_GROW7 + {SPR_PPOD, 15, 3, NULL, S_POD_WAIT1, 0, 0}, // S_POD_GROW8 + {SPR_PPOD, 6, 8, NULL, S_PODGOO2, 0, 0}, // S_PODGOO1 + {SPR_PPOD, 7, 8, NULL, S_PODGOO1, 0, 0}, // S_PODGOO2 + {SPR_PPOD, 6, 10, NULL, S_NULL, 0, 0}, // S_PODGOOX + {SPR_AMG1, 0, 35, A_MakePod, S_PODGENERATOR, 0, 0}, // S_PODGENERATOR + {SPR_SPSH, 0, 8, NULL, S_SPLASH2, 0, 0}, // S_SPLASH1 + {SPR_SPSH, 1, 8, NULL, S_SPLASH3, 0, 0}, // S_SPLASH2 + {SPR_SPSH, 2, 8, NULL, S_SPLASH4, 0, 0}, // S_SPLASH3 + {SPR_SPSH, 3, 16, NULL, S_NULL, 0, 0}, // S_SPLASH4 + {SPR_SPSH, 3, 10, NULL, S_NULL, 0, 0}, // S_SPLASHX + {SPR_SPSH, 4, 5, NULL, S_SPLASHBASE2, 0, 0}, // S_SPLASHBASE1 + {SPR_SPSH, 5, 5, NULL, S_SPLASHBASE3, 0, 0}, // S_SPLASHBASE2 + {SPR_SPSH, 6, 5, NULL, S_SPLASHBASE4, 0, 0}, // S_SPLASHBASE3 + {SPR_SPSH, 7, 5, NULL, S_SPLASHBASE5, 0, 0}, // S_SPLASHBASE4 + {SPR_SPSH, 8, 5, NULL, S_SPLASHBASE6, 0, 0}, // S_SPLASHBASE5 + {SPR_SPSH, 9, 5, NULL, S_SPLASHBASE7, 0, 0}, // S_SPLASHBASE6 + {SPR_SPSH, 10, 5, NULL, S_NULL, 0, 0}, // S_SPLASHBASE7 + {SPR_LVAS, 32768, 5, NULL, S_LAVASPLASH2, 0, 0}, // S_LAVASPLASH1 + {SPR_LVAS, 32769, 5, NULL, S_LAVASPLASH3, 0, 0}, // S_LAVASPLASH2 + {SPR_LVAS, 32770, 5, NULL, S_LAVASPLASH4, 0, 0}, // S_LAVASPLASH3 + {SPR_LVAS, 32771, 5, NULL, S_LAVASPLASH5, 0, 0}, // S_LAVASPLASH4 + {SPR_LVAS, 32772, 5, NULL, S_LAVASPLASH6, 0, 0}, // S_LAVASPLASH5 + {SPR_LVAS, 32773, 5, NULL, S_NULL, 0, 0}, // S_LAVASPLASH6 + {SPR_LVAS, 32774, 5, NULL, S_LAVASMOKE2, 0, 0}, // S_LAVASMOKE1 + {SPR_LVAS, 32775, 5, NULL, S_LAVASMOKE3, 0, 0}, // S_LAVASMOKE2 + {SPR_LVAS, 32776, 5, NULL, S_LAVASMOKE4, 0, 0}, // S_LAVASMOKE3 + {SPR_LVAS, 32777, 5, NULL, S_LAVASMOKE5, 0, 0}, // S_LAVASMOKE4 + {SPR_LVAS, 32778, 5, NULL, S_NULL, 0, 0}, // S_LAVASMOKE5 + {SPR_SLDG, 0, 8, NULL, S_SLUDGECHUNK2, 0, 0}, // S_SLUDGECHUNK1 + {SPR_SLDG, 1, 8, NULL, S_SLUDGECHUNK3, 0, 0}, // S_SLUDGECHUNK2 + {SPR_SLDG, 2, 8, NULL, S_SLUDGECHUNK4, 0, 0}, // S_SLUDGECHUNK3 + {SPR_SLDG, 3, 8, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNK4 + {SPR_SLDG, 3, 6, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNKX + {SPR_SLDG, 4, 5, NULL, S_SLUDGESPLASH2, 0, 0}, // S_SLUDGESPLASH1 + {SPR_SLDG, 5, 5, NULL, S_SLUDGESPLASH3, 0, 0}, // S_SLUDGESPLASH2 + {SPR_SLDG, 6, 5, NULL, S_SLUDGESPLASH4, 0, 0}, // S_SLUDGESPLASH3 + {SPR_SLDG, 7, 5, NULL, S_NULL, 0, 0}, // S_SLUDGESPLASH4 + {SPR_SKH1, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG70_1 + {SPR_SKH2, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG60_1 + {SPR_SKH3, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG45_1 + {SPR_SKH4, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG35_1 + {SPR_CHDL, 0, 4, NULL, S_CHANDELIER2, 0, 0}, // S_CHANDELIER1 + {SPR_CHDL, 1, 4, NULL, S_CHANDELIER3, 0, 0}, // S_CHANDELIER2 + {SPR_CHDL, 2, 4, NULL, S_CHANDELIER1, 0, 0}, // S_CHANDELIER3 + {SPR_SRTC, 0, 4, NULL, S_SERPTORCH2, 0, 0}, // S_SERPTORCH1 + {SPR_SRTC, 1, 4, NULL, S_SERPTORCH3, 0, 0}, // S_SERPTORCH2 + {SPR_SRTC, 2, 4, NULL, S_SERPTORCH1, 0, 0}, // S_SERPTORCH3 + {SPR_SMPL, 0, -1, NULL, S_NULL, 0, 0}, // S_SMALLPILLAR + {SPR_STGS, 0, -1, NULL, S_NULL, 0, 0}, // S_STALAGMITESMALL + {SPR_STGL, 0, -1, NULL, S_NULL, 0, 0}, // S_STALAGMITELARGE + {SPR_STCS, 0, -1, NULL, S_NULL, 0, 0}, // S_STALACTITESMALL + {SPR_STCL, 0, -1, NULL, S_NULL, 0, 0}, // S_STALACTITELARGE + {SPR_KFR1, 32768, 3, NULL, S_FIREBRAZIER2, 0, 0}, // S_FIREBRAZIER1 + {SPR_KFR1, 32769, 3, NULL, S_FIREBRAZIER3, 0, 0}, // S_FIREBRAZIER2 + {SPR_KFR1, 32770, 3, NULL, S_FIREBRAZIER4, 0, 0}, // S_FIREBRAZIER3 + {SPR_KFR1, 32771, 3, NULL, S_FIREBRAZIER5, 0, 0}, // S_FIREBRAZIER4 + {SPR_KFR1, 32772, 3, NULL, S_FIREBRAZIER6, 0, 0}, // S_FIREBRAZIER5 + {SPR_KFR1, 32773, 3, NULL, S_FIREBRAZIER7, 0, 0}, // S_FIREBRAZIER6 + {SPR_KFR1, 32774, 3, NULL, S_FIREBRAZIER8, 0, 0}, // S_FIREBRAZIER7 + {SPR_KFR1, 32775, 3, NULL, S_FIREBRAZIER1, 0, 0}, // S_FIREBRAZIER8 + {SPR_BARL, 0, -1, NULL, S_NULL, 0, 0}, // S_BARREL + {SPR_BRPL, 0, -1, NULL, S_NULL, 0, 0}, // S_BRPILLAR + {SPR_MOS1, 0, -1, NULL, S_NULL, 0, 0}, // S_MOSS1 + {SPR_MOS2, 0, -1, NULL, S_NULL, 0, 0}, // S_MOSS2 + {SPR_WTRH, 32768, 6, NULL, S_WALLTORCH2, 0, 0}, // S_WALLTORCH1 + {SPR_WTRH, 32769, 6, NULL, S_WALLTORCH3, 0, 0}, // S_WALLTORCH2 + {SPR_WTRH, 32770, 6, NULL, S_WALLTORCH1, 0, 0}, // S_WALLTORCH3 + {SPR_HCOR, 0, -1, NULL, S_NULL, 0, 0}, // S_HANGINGCORPSE + {SPR_KGZ1, 0, 1, NULL, S_KEYGIZMO2, 0, 0}, // S_KEYGIZMO1 + {SPR_KGZ1, 0, 1, A_InitKeyGizmo, S_KEYGIZMO3, 0, 0}, // S_KEYGIZMO2 + {SPR_KGZ1, 0, -1, NULL, S_NULL, 0, 0}, // S_KEYGIZMO3 + {SPR_KGZB, 0, 1, NULL, S_KGZ_START, 0, 0}, // S_KGZ_START + {SPR_KGZB, 32768, -1, NULL, S_NULL, 0, 0}, // S_KGZ_BLUEFLOAT1 + {SPR_KGZG, 32768, -1, NULL, S_NULL, 0, 0}, // S_KGZ_GREENFLOAT1 + {SPR_KGZY, 32768, -1, NULL, S_NULL, 0, 0}, // S_KGZ_YELLOWFLOAT1 + {SPR_VLCO, 0, 350, NULL, S_VOLCANO2, 0, 0}, // S_VOLCANO1 + {SPR_VLCO, 0, 35, A_VolcanoSet, S_VOLCANO3, 0, 0}, // S_VOLCANO2 + {SPR_VLCO, 1, 3, NULL, S_VOLCANO4, 0, 0}, // S_VOLCANO3 + {SPR_VLCO, 2, 3, NULL, S_VOLCANO5, 0, 0}, // S_VOLCANO4 + {SPR_VLCO, 3, 3, NULL, S_VOLCANO6, 0, 0}, // S_VOLCANO5 + {SPR_VLCO, 1, 3, NULL, S_VOLCANO7, 0, 0}, // S_VOLCANO6 + {SPR_VLCO, 2, 3, NULL, S_VOLCANO8, 0, 0}, // S_VOLCANO7 + {SPR_VLCO, 3, 3, NULL, S_VOLCANO9, 0, 0}, // S_VOLCANO8 + {SPR_VLCO, 4, 10, A_VolcanoBlast, S_VOLCANO2, 0, 0}, // S_VOLCANO9 + {SPR_VFBL, 0, 4, A_BeastPuff, S_VOLCANOBALL2, 0, 0}, // S_VOLCANOBALL1 + {SPR_VFBL, 1, 4, A_BeastPuff, S_VOLCANOBALL1, 0, 0}, // S_VOLCANOBALL2 + {SPR_XPL1, 0, 4, A_VolcBallImpact, S_VOLCANOBALLX2, 0, 0}, // S_VOLCANOBALLX1 + {SPR_XPL1, 1, 4, NULL, S_VOLCANOBALLX3, 0, 0}, // S_VOLCANOBALLX2 + {SPR_XPL1, 2, 4, NULL, S_VOLCANOBALLX4, 0, 0}, // S_VOLCANOBALLX3 + {SPR_XPL1, 3, 4, NULL, S_VOLCANOBALLX5, 0, 0}, // S_VOLCANOBALLX4 + {SPR_XPL1, 4, 4, NULL, S_VOLCANOBALLX6, 0, 0}, // S_VOLCANOBALLX5 + {SPR_XPL1, 5, 4, NULL, S_NULL, 0, 0}, // S_VOLCANOBALLX6 + {SPR_VTFB, 0, 4, NULL, S_VOLCANOTBALL2, 0, 0}, // S_VOLCANOTBALL1 + {SPR_VTFB, 1, 4, NULL, S_VOLCANOTBALL1, 0, 0}, // S_VOLCANOTBALL2 + {SPR_SFFI, 2, 4, NULL, S_VOLCANOTBALLX2, 0, 0}, // S_VOLCANOTBALLX1 + {SPR_SFFI, 1, 4, NULL, S_VOLCANOTBALLX3, 0, 0}, // S_VOLCANOTBALLX2 + {SPR_SFFI, 0, 4, NULL, S_VOLCANOTBALLX4, 0, 0}, // S_VOLCANOTBALLX3 + {SPR_SFFI, 1, 4, NULL, S_VOLCANOTBALLX5, 0, 0}, // S_VOLCANOTBALLX4 + {SPR_SFFI, 2, 4, NULL, S_VOLCANOTBALLX6, 0, 0}, // S_VOLCANOTBALLX5 + {SPR_SFFI, 3, 4, NULL, S_VOLCANOTBALLX7, 0, 0}, // S_VOLCANOTBALLX6 + {SPR_SFFI, 4, 4, NULL, S_NULL, 0, 0}, // S_VOLCANOTBALLX7 + {SPR_TGLT, 0, 8, A_SpawnTeleGlitter, S_TELEGLITGEN1, 0, 0}, // S_TELEGLITGEN1 + {SPR_TGLT, 5, 8, A_SpawnTeleGlitter2, S_TELEGLITGEN2, 0, 0}, // S_TELEGLITGEN2 + {SPR_TGLT, 32768, 2, NULL, S_TELEGLITTER1_2, 0, 0}, // S_TELEGLITTER1_1 + {SPR_TGLT, 32769, 2, A_AccTeleGlitter, S_TELEGLITTER1_3, 0, 0}, // S_TELEGLITTER1_2 + {SPR_TGLT, 32770, 2, NULL, S_TELEGLITTER1_4, 0, 0}, // S_TELEGLITTER1_3 + {SPR_TGLT, 32771, 2, A_AccTeleGlitter, S_TELEGLITTER1_5, 0, 0}, // S_TELEGLITTER1_4 + {SPR_TGLT, 32772, 2, NULL, S_TELEGLITTER1_1, 0, 0}, // S_TELEGLITTER1_5 + {SPR_TGLT, 32773, 2, NULL, S_TELEGLITTER2_2, 0, 0}, // S_TELEGLITTER2_1 + {SPR_TGLT, 32774, 2, A_AccTeleGlitter, S_TELEGLITTER2_3, 0, 0}, // S_TELEGLITTER2_2 + {SPR_TGLT, 32775, 2, NULL, S_TELEGLITTER2_4, 0, 0}, // S_TELEGLITTER2_3 + {SPR_TGLT, 32776, 2, A_AccTeleGlitter, S_TELEGLITTER2_5, 0, 0}, // S_TELEGLITTER2_4 + {SPR_TGLT, 32777, 2, NULL, S_TELEGLITTER2_1, 0, 0}, // S_TELEGLITTER2_5 + {SPR_TELE, 32768, 6, NULL, S_TFOG2, 0, 0}, // S_TFOG1 + {SPR_TELE, 32769, 6, NULL, S_TFOG3, 0, 0}, // S_TFOG2 + {SPR_TELE, 32770, 6, NULL, S_TFOG4, 0, 0}, // S_TFOG3 + {SPR_TELE, 32771, 6, NULL, S_TFOG5, 0, 0}, // S_TFOG4 + {SPR_TELE, 32772, 6, NULL, S_TFOG6, 0, 0}, // S_TFOG5 + {SPR_TELE, 32773, 6, NULL, S_TFOG7, 0, 0}, // S_TFOG6 + {SPR_TELE, 32774, 6, NULL, S_TFOG8, 0, 0}, // S_TFOG7 + {SPR_TELE, 32775, 6, NULL, S_TFOG9, 0, 0}, // S_TFOG8 + {SPR_TELE, 32774, 6, NULL, S_TFOG10, 0, 0}, // S_TFOG9 + {SPR_TELE, 32773, 6, NULL, S_TFOG11, 0, 0}, // S_TFOG10 + {SPR_TELE, 32772, 6, NULL, S_TFOG12, 0, 0}, // S_TFOG11 + {SPR_TELE, 32771, 6, NULL, S_TFOG13, 0, 0}, // S_TFOG12 + {SPR_TELE, 32770, 6, NULL, S_NULL, 0, 0}, // S_TFOG13 + {SPR_STFF, 0, 0, A_Light0, S_NULL, 0, 0}, // S_LIGHTDONE + {SPR_STFF, 0, 1, A_WeaponReady, S_STAFFREADY, 0, 0}, // S_STAFFREADY + {SPR_STFF, 0, 1, A_Lower, S_STAFFDOWN, 0, 0}, // S_STAFFDOWN + {SPR_STFF, 0, 1, A_Raise, S_STAFFUP, 0, 0}, // S_STAFFUP + {SPR_STFF, 3, 4, A_WeaponReady, S_STAFFREADY2_2, 0, 0}, // S_STAFFREADY2_1 + {SPR_STFF, 4, 4, A_WeaponReady, S_STAFFREADY2_3, 0, 0}, // S_STAFFREADY2_2 + {SPR_STFF, 5, 4, A_WeaponReady, S_STAFFREADY2_1, 0, 0}, // S_STAFFREADY2_3 + {SPR_STFF, 3, 1, A_Lower, S_STAFFDOWN2, 0, 0}, // S_STAFFDOWN2 + {SPR_STFF, 3, 1, A_Raise, S_STAFFUP2, 0, 0}, // S_STAFFUP2 + {SPR_STFF, 1, 6, NULL, S_STAFFATK1_2, 0, 0}, // S_STAFFATK1_1 + {SPR_STFF, 2, 8, A_StaffAttackPL1, S_STAFFATK1_3, 0, 0}, // S_STAFFATK1_2 + {SPR_STFF, 1, 8, A_ReFire, S_STAFFREADY, 0, 0}, // S_STAFFATK1_3 + {SPR_STFF, 6, 6, NULL, S_STAFFATK2_2, 0, 0}, // S_STAFFATK2_1 + {SPR_STFF, 7, 8, A_StaffAttackPL2, S_STAFFATK2_3, 0, 0}, // S_STAFFATK2_2 + {SPR_STFF, 6, 8, A_ReFire, S_STAFFREADY2_1, 0, 0}, // S_STAFFATK2_3 + {SPR_PUF3, 32768, 4, NULL, S_STAFFPUFF2, 0, 0}, // S_STAFFPUFF1 + {SPR_PUF3, 1, 4, NULL, S_STAFFPUFF3, 0, 0}, // S_STAFFPUFF2 + {SPR_PUF3, 2, 4, NULL, S_STAFFPUFF4, 0, 0}, // S_STAFFPUFF3 + {SPR_PUF3, 3, 4, NULL, S_NULL, 0, 0}, // S_STAFFPUFF4 + {SPR_PUF4, 32768, 4, NULL, S_STAFFPUFF2_2, 0, 0}, // S_STAFFPUFF2_1 + {SPR_PUF4, 32769, 4, NULL, S_STAFFPUFF2_3, 0, 0}, // S_STAFFPUFF2_2 + {SPR_PUF4, 32770, 4, NULL, S_STAFFPUFF2_4, 0, 0}, // S_STAFFPUFF2_3 + {SPR_PUF4, 32771, 4, NULL, S_STAFFPUFF2_5, 0, 0}, // S_STAFFPUFF2_4 + {SPR_PUF4, 32772, 4, NULL, S_STAFFPUFF2_6, 0, 0}, // S_STAFFPUFF2_5 + {SPR_PUF4, 32773, 4, NULL, S_NULL, 0, 0}, // S_STAFFPUFF2_6 + {SPR_BEAK, 0, 1, A_BeakReady, S_BEAKREADY, 0, 0}, // S_BEAKREADY + {SPR_BEAK, 0, 1, A_Lower, S_BEAKDOWN, 0, 0}, // S_BEAKDOWN + {SPR_BEAK, 0, 1, A_BeakRaise, S_BEAKUP, 0, 0}, // S_BEAKUP + {SPR_BEAK, 0, 18, A_BeakAttackPL1, S_BEAKREADY, 0, 0}, // S_BEAKATK1_1 + {SPR_BEAK, 0, 12, A_BeakAttackPL2, S_BEAKREADY, 0, 0}, // S_BEAKATK2_1 + {SPR_WGNT, 0, -1, NULL, S_NULL, 0, 0}, // S_WGNT + {SPR_GAUN, 0, 1, A_WeaponReady, S_GAUNTLETREADY, 0, 0}, // S_GAUNTLETREADY + {SPR_GAUN, 0, 1, A_Lower, S_GAUNTLETDOWN, 0, 0}, // S_GAUNTLETDOWN + {SPR_GAUN, 0, 1, A_Raise, S_GAUNTLETUP, 0, 0}, // S_GAUNTLETUP + {SPR_GAUN, 6, 4, A_WeaponReady, S_GAUNTLETREADY2_2, 0, 0}, // S_GAUNTLETREADY2_1 + {SPR_GAUN, 7, 4, A_WeaponReady, S_GAUNTLETREADY2_3, 0, 0}, // S_GAUNTLETREADY2_2 + {SPR_GAUN, 8, 4, A_WeaponReady, S_GAUNTLETREADY2_1, 0, 0}, // S_GAUNTLETREADY2_3 + {SPR_GAUN, 6, 1, A_Lower, S_GAUNTLETDOWN2, 0, 0}, // S_GAUNTLETDOWN2 + {SPR_GAUN, 6, 1, A_Raise, S_GAUNTLETUP2, 0, 0}, // S_GAUNTLETUP2 + {SPR_GAUN, 1, 4, NULL, S_GAUNTLETATK1_2, 0, 0}, // S_GAUNTLETATK1_1 + {SPR_GAUN, 2, 4, NULL, S_GAUNTLETATK1_3, 0, 0}, // S_GAUNTLETATK1_2 + {SPR_GAUN, 32771, 4, A_GauntletAttack, S_GAUNTLETATK1_4, 0, 0}, // S_GAUNTLETATK1_3 + {SPR_GAUN, 32772, 4, A_GauntletAttack, S_GAUNTLETATK1_5, 0, 0}, // S_GAUNTLETATK1_4 + {SPR_GAUN, 32773, 4, A_GauntletAttack, S_GAUNTLETATK1_6, 0, 0}, // S_GAUNTLETATK1_5 + {SPR_GAUN, 2, 4, A_ReFire, S_GAUNTLETATK1_7, 0, 0}, // S_GAUNTLETATK1_6 + {SPR_GAUN, 1, 4, A_Light0, S_GAUNTLETREADY, 0, 0}, // S_GAUNTLETATK1_7 + {SPR_GAUN, 9, 4, NULL, S_GAUNTLETATK2_2, 0, 0}, // S_GAUNTLETATK2_1 + {SPR_GAUN, 10, 4, NULL, S_GAUNTLETATK2_3, 0, 0}, // S_GAUNTLETATK2_2 + {SPR_GAUN, 32779, 4, A_GauntletAttack, S_GAUNTLETATK2_4, 0, 0}, // S_GAUNTLETATK2_3 + {SPR_GAUN, 32780, 4, A_GauntletAttack, S_GAUNTLETATK2_5, 0, 0}, // S_GAUNTLETATK2_4 + {SPR_GAUN, 32781, 4, A_GauntletAttack, S_GAUNTLETATK2_6, 0, 0}, // S_GAUNTLETATK2_5 + {SPR_GAUN, 10, 4, A_ReFire, S_GAUNTLETATK2_7, 0, 0}, // S_GAUNTLETATK2_6 + {SPR_GAUN, 9, 4, A_Light0, S_GAUNTLETREADY2_1, 0, 0}, // S_GAUNTLETATK2_7 + {SPR_PUF1, 32768, 4, NULL, S_GAUNTLETPUFF1_2, 0, 0}, // S_GAUNTLETPUFF1_1 + {SPR_PUF1, 32769, 4, NULL, S_GAUNTLETPUFF1_3, 0, 0}, // S_GAUNTLETPUFF1_2 + {SPR_PUF1, 32770, 4, NULL, S_GAUNTLETPUFF1_4, 0, 0}, // S_GAUNTLETPUFF1_3 + {SPR_PUF1, 32771, 4, NULL, S_NULL, 0, 0}, // S_GAUNTLETPUFF1_4 + {SPR_PUF1, 32772, 4, NULL, S_GAUNTLETPUFF2_2, 0, 0}, // S_GAUNTLETPUFF2_1 + {SPR_PUF1, 32773, 4, NULL, S_GAUNTLETPUFF2_3, 0, 0}, // S_GAUNTLETPUFF2_2 + {SPR_PUF1, 32774, 4, NULL, S_GAUNTLETPUFF2_4, 0, 0}, // S_GAUNTLETPUFF2_3 + {SPR_PUF1, 32775, 4, NULL, S_NULL, 0, 0}, // S_GAUNTLETPUFF2_4 + {SPR_WBLS, 0, -1, NULL, S_NULL, 0, 0}, // S_BLSR + {SPR_BLSR, 0, 1, A_WeaponReady, S_BLASTERREADY, 0, 0}, // S_BLASTERREADY + {SPR_BLSR, 0, 1, A_Lower, S_BLASTERDOWN, 0, 0}, // S_BLASTERDOWN + {SPR_BLSR, 0, 1, A_Raise, S_BLASTERUP, 0, 0}, // S_BLASTERUP + {SPR_BLSR, 1, 3, NULL, S_BLASTERATK1_2, 0, 0}, // S_BLASTERATK1_1 + {SPR_BLSR, 2, 3, NULL, S_BLASTERATK1_3, 0, 0}, // S_BLASTERATK1_2 + {SPR_BLSR, 3, 2, A_FireBlasterPL1, S_BLASTERATK1_4, 0, 0}, // S_BLASTERATK1_3 + {SPR_BLSR, 2, 2, NULL, S_BLASTERATK1_5, 0, 0}, // S_BLASTERATK1_4 + {SPR_BLSR, 1, 2, NULL, S_BLASTERATK1_6, 0, 0}, // S_BLASTERATK1_5 + {SPR_BLSR, 0, 0, A_ReFire, S_BLASTERREADY, 0, 0}, // S_BLASTERATK1_6 + {SPR_BLSR, 1, 0, NULL, S_BLASTERATK2_2, 0, 0}, // S_BLASTERATK2_1 + {SPR_BLSR, 2, 0, NULL, S_BLASTERATK2_3, 0, 0}, // S_BLASTERATK2_2 + {SPR_BLSR, 3, 3, A_FireBlasterPL2, S_BLASTERATK2_4, 0, 0}, // S_BLASTERATK2_3 + {SPR_BLSR, 2, 4, NULL, S_BLASTERATK2_5, 0, 0}, // S_BLASTERATK2_4 + {SPR_BLSR, 1, 4, NULL, S_BLASTERATK2_6, 0, 0}, // S_BLASTERATK2_5 + {SPR_BLSR, 0, 0, A_ReFire, S_BLASTERREADY, 0, 0}, // S_BLASTERATK2_6 + {SPR_ACLO, 4, 200, NULL, S_BLASTERFX1_1, 0, 0}, // S_BLASTERFX1_1 + {SPR_FX18, 32768, 3, A_SpawnRippers, S_BLASTERFXI1_2, 0, 0}, // S_BLASTERFXI1_1 + {SPR_FX18, 32769, 3, NULL, S_BLASTERFXI1_3, 0, 0}, // S_BLASTERFXI1_2 + {SPR_FX18, 32770, 4, NULL, S_BLASTERFXI1_4, 0, 0}, // S_BLASTERFXI1_3 + {SPR_FX18, 32771, 4, NULL, S_BLASTERFXI1_5, 0, 0}, // S_BLASTERFXI1_4 + {SPR_FX18, 32772, 4, NULL, S_BLASTERFXI1_6, 0, 0}, // S_BLASTERFXI1_5 + {SPR_FX18, 32773, 4, NULL, S_BLASTERFXI1_7, 0, 0}, // S_BLASTERFXI1_6 + {SPR_FX18, 32774, 4, NULL, S_NULL, 0, 0}, // S_BLASTERFXI1_7 + {SPR_FX18, 7, 4, NULL, S_BLASTERSMOKE2, 0, 0}, // S_BLASTERSMOKE1 + {SPR_FX18, 8, 4, NULL, S_BLASTERSMOKE3, 0, 0}, // S_BLASTERSMOKE2 + {SPR_FX18, 9, 4, NULL, S_BLASTERSMOKE4, 0, 0}, // S_BLASTERSMOKE3 + {SPR_FX18, 10, 4, NULL, S_BLASTERSMOKE5, 0, 0}, // S_BLASTERSMOKE4 + {SPR_FX18, 11, 4, NULL, S_NULL, 0, 0}, // S_BLASTERSMOKE5 + {SPR_FX18, 12, 4, NULL, S_RIPPER2, 0, 0}, // S_RIPPER1 + {SPR_FX18, 13, 5, NULL, S_RIPPER1, 0, 0}, // S_RIPPER2 + {SPR_FX18, 32782, 4, NULL, S_RIPPERX2, 0, 0}, // S_RIPPERX1 + {SPR_FX18, 32783, 4, NULL, S_RIPPERX3, 0, 0}, // S_RIPPERX2 + {SPR_FX18, 32784, 4, NULL, S_RIPPERX4, 0, 0}, // S_RIPPERX3 + {SPR_FX18, 32785, 4, NULL, S_RIPPERX5, 0, 0}, // S_RIPPERX4 + {SPR_FX18, 32786, 4, NULL, S_NULL, 0, 0}, // S_RIPPERX5 + {SPR_FX17, 32768, 4, NULL, S_BLASTERPUFF1_2, 0, 0}, // S_BLASTERPUFF1_1 + {SPR_FX17, 32769, 4, NULL, S_BLASTERPUFF1_3, 0, 0}, // S_BLASTERPUFF1_2 + {SPR_FX17, 32770, 4, NULL, S_BLASTERPUFF1_4, 0, 0}, // S_BLASTERPUFF1_3 + {SPR_FX17, 32771, 4, NULL, S_BLASTERPUFF1_5, 0, 0}, // S_BLASTERPUFF1_4 + {SPR_FX17, 32772, 4, NULL, S_NULL, 0, 0}, // S_BLASTERPUFF1_5 + {SPR_FX17, 32773, 3, NULL, S_BLASTERPUFF2_2, 0, 0}, // S_BLASTERPUFF2_1 + {SPR_FX17, 32774, 3, NULL, S_BLASTERPUFF2_3, 0, 0}, // S_BLASTERPUFF2_2 + {SPR_FX17, 32775, 4, NULL, S_BLASTERPUFF2_4, 0, 0}, // S_BLASTERPUFF2_3 + {SPR_FX17, 32776, 4, NULL, S_BLASTERPUFF2_5, 0, 0}, // S_BLASTERPUFF2_4 + {SPR_FX17, 32777, 4, NULL, S_BLASTERPUFF2_6, 0, 0}, // S_BLASTERPUFF2_5 + {SPR_FX17, 32778, 4, NULL, S_BLASTERPUFF2_7, 0, 0}, // S_BLASTERPUFF2_6 + {SPR_FX17, 32779, 4, NULL, S_NULL, 0, 0}, // S_BLASTERPUFF2_7 + {SPR_WMCE, 0, -1, NULL, S_NULL, 0, 0}, // S_WMCE + {SPR_MACE, 0, 1, A_WeaponReady, S_MACEREADY, 0, 0}, // S_MACEREADY + {SPR_MACE, 0, 1, A_Lower, S_MACEDOWN, 0, 0}, // S_MACEDOWN + {SPR_MACE, 0, 1, A_Raise, S_MACEUP, 0, 0}, // S_MACEUP + {SPR_MACE, 1, 4, NULL, S_MACEATK1_2, 0, 0}, // S_MACEATK1_1 + {SPR_MACE, 2, 3, A_FireMacePL1, S_MACEATK1_3, 0, 0}, // S_MACEATK1_2 + {SPR_MACE, 3, 3, A_FireMacePL1, S_MACEATK1_4, 0, 0}, // S_MACEATK1_3 + {SPR_MACE, 4, 3, A_FireMacePL1, S_MACEATK1_5, 0, 0}, // S_MACEATK1_4 + {SPR_MACE, 5, 3, A_FireMacePL1, S_MACEATK1_6, 0, 0}, // S_MACEATK1_5 + {SPR_MACE, 2, 4, A_ReFire, S_MACEATK1_7, 0, 0}, // S_MACEATK1_6 + {SPR_MACE, 3, 4, NULL, S_MACEATK1_8, 0, 0}, // S_MACEATK1_7 + {SPR_MACE, 4, 4, NULL, S_MACEATK1_9, 0, 0}, // S_MACEATK1_8 + {SPR_MACE, 5, 4, NULL, S_MACEATK1_10, 0, 0}, // S_MACEATK1_9 + {SPR_MACE, 1, 4, NULL, S_MACEREADY, 0, 0}, // S_MACEATK1_10 + {SPR_MACE, 1, 4, NULL, S_MACEATK2_2, 0, 0}, // S_MACEATK2_1 + {SPR_MACE, 3, 4, A_FireMacePL2, S_MACEATK2_3, 0, 0}, // S_MACEATK2_2 + {SPR_MACE, 1, 4, NULL, S_MACEATK2_4, 0, 0}, // S_MACEATK2_3 + {SPR_MACE, 0, 8, A_ReFire, S_MACEREADY, 0, 0}, // S_MACEATK2_4 + {SPR_FX02, 0, 4, A_MacePL1Check, S_MACEFX1_2, 0, 0}, // S_MACEFX1_1 + {SPR_FX02, 1, 4, A_MacePL1Check, S_MACEFX1_1, 0, 0}, // S_MACEFX1_2 + {SPR_FX02, 32773, 4, A_MaceBallImpact, S_MACEFXI1_2, 0, 0}, // S_MACEFXI1_1 + {SPR_FX02, 32774, 4, NULL, S_MACEFXI1_3, 0, 0}, // S_MACEFXI1_2 + {SPR_FX02, 32775, 4, NULL, S_MACEFXI1_4, 0, 0}, // S_MACEFXI1_3 + {SPR_FX02, 32776, 4, NULL, S_MACEFXI1_5, 0, 0}, // S_MACEFXI1_4 + {SPR_FX02, 32777, 4, NULL, S_NULL, 0, 0}, // S_MACEFXI1_5 + {SPR_FX02, 2, 4, NULL, S_MACEFX2_2, 0, 0}, // S_MACEFX2_1 + {SPR_FX02, 3, 4, NULL, S_MACEFX2_1, 0, 0}, // S_MACEFX2_2 + {SPR_FX02, 32773, 4, A_MaceBallImpact2, S_MACEFXI1_2, 0, 0}, // S_MACEFXI2_1 + {SPR_FX02, 0, 4, NULL, S_MACEFX3_2, 0, 0}, // S_MACEFX3_1 + {SPR_FX02, 1, 4, NULL, S_MACEFX3_1, 0, 0}, // S_MACEFX3_2 + {SPR_FX02, 4, 99, NULL, S_MACEFX4_1, 0, 0}, // S_MACEFX4_1 + {SPR_FX02, 32770, 4, A_DeathBallImpact, S_MACEFXI1_2, 0, 0}, // S_MACEFXI4_1 + {SPR_WSKL, 0, -1, NULL, S_NULL, 0, 0}, // S_WSKL + {SPR_HROD, 0, 1, A_WeaponReady, S_HORNRODREADY, 0, 0}, // S_HORNRODREADY + {SPR_HROD, 0, 1, A_Lower, S_HORNRODDOWN, 0, 0}, // S_HORNRODDOWN + {SPR_HROD, 0, 1, A_Raise, S_HORNRODUP, 0, 0}, // S_HORNRODUP + {SPR_HROD, 0, 4, A_FireSkullRodPL1, S_HORNRODATK1_2, 0, 0}, // S_HORNRODATK1_1 + {SPR_HROD, 1, 4, A_FireSkullRodPL1, S_HORNRODATK1_3, 0, 0}, // S_HORNRODATK1_2 + {SPR_HROD, 1, 0, A_ReFire, S_HORNRODREADY, 0, 0}, // S_HORNRODATK1_3 + {SPR_HROD, 2, 2, NULL, S_HORNRODATK2_2, 0, 0}, // S_HORNRODATK2_1 + {SPR_HROD, 3, 3, NULL, S_HORNRODATK2_3, 0, 0}, // S_HORNRODATK2_2 + {SPR_HROD, 4, 2, NULL, S_HORNRODATK2_4, 0, 0}, // S_HORNRODATK2_3 + {SPR_HROD, 5, 3, NULL, S_HORNRODATK2_5, 0, 0}, // S_HORNRODATK2_4 + {SPR_HROD, 6, 4, A_FireSkullRodPL2, S_HORNRODATK2_6, 0, 0}, // S_HORNRODATK2_5 + {SPR_HROD, 5, 2, NULL, S_HORNRODATK2_7, 0, 0}, // S_HORNRODATK2_6 + {SPR_HROD, 4, 3, NULL, S_HORNRODATK2_8, 0, 0}, // S_HORNRODATK2_7 + {SPR_HROD, 3, 2, NULL, S_HORNRODATK2_9, 0, 0}, // S_HORNRODATK2_8 + {SPR_HROD, 2, 2, A_ReFire, S_HORNRODREADY, 0, 0}, // S_HORNRODATK2_9 + {SPR_FX00, 32768, 6, NULL, S_HRODFX1_2, 0, 0}, // S_HRODFX1_1 + {SPR_FX00, 32769, 6, NULL, S_HRODFX1_1, 0, 0}, // S_HRODFX1_2 + {SPR_FX00, 32775, 5, NULL, S_HRODFXI1_2, 0, 0}, // S_HRODFXI1_1 + {SPR_FX00, 32776, 5, NULL, S_HRODFXI1_3, 0, 0}, // S_HRODFXI1_2 + {SPR_FX00, 32777, 4, NULL, S_HRODFXI1_4, 0, 0}, // S_HRODFXI1_3 + {SPR_FX00, 32778, 4, NULL, S_HRODFXI1_5, 0, 0}, // S_HRODFXI1_4 + {SPR_FX00, 32779, 3, NULL, S_HRODFXI1_6, 0, 0}, // S_HRODFXI1_5 + {SPR_FX00, 32780, 3, NULL, S_NULL, 0, 0}, // S_HRODFXI1_6 + {SPR_FX00, 32770, 3, NULL, S_HRODFX2_2, 0, 0}, // S_HRODFX2_1 + {SPR_FX00, 32771, 3, A_SkullRodPL2Seek, S_HRODFX2_3, 0, 0}, // S_HRODFX2_2 + {SPR_FX00, 32772, 3, NULL, S_HRODFX2_4, 0, 0}, // S_HRODFX2_3 + {SPR_FX00, 32773, 3, A_SkullRodPL2Seek, S_HRODFX2_1, 0, 0}, // S_HRODFX2_4 + {SPR_FX00, 32775, 5, A_AddPlayerRain, S_HRODFXI2_2, 0, 0}, // S_HRODFXI2_1 + {SPR_FX00, 32776, 5, NULL, S_HRODFXI2_3, 0, 0}, // S_HRODFXI2_2 + {SPR_FX00, 32777, 4, NULL, S_HRODFXI2_4, 0, 0}, // S_HRODFXI2_3 + {SPR_FX00, 32778, 3, NULL, S_HRODFXI2_5, 0, 0}, // S_HRODFXI2_4 + {SPR_FX00, 32779, 3, NULL, S_HRODFXI2_6, 0, 0}, // S_HRODFXI2_5 + {SPR_FX00, 32780, 3, NULL, S_HRODFXI2_7, 0, 0}, // S_HRODFXI2_6 + {SPR_FX00, 6, 1, A_HideInCeiling, S_HRODFXI2_8, 0, 0}, // S_HRODFXI2_7 + {SPR_FX00, 6, 1, A_SkullRodStorm, S_HRODFXI2_8, 0, 0}, // S_HRODFXI2_8 + {SPR_FX20, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR1_1 + {SPR_FX21, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR2_1 + {SPR_FX22, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR3_1 + {SPR_FX23, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR4_1 + {SPR_FX20, 32769, 4, A_RainImpact, S_RAINPLR1X_2, 0, 0}, // S_RAINPLR1X_1 + {SPR_FX20, 32770, 4, NULL, S_RAINPLR1X_3, 0, 0}, // S_RAINPLR1X_2 + {SPR_FX20, 32771, 4, NULL, S_RAINPLR1X_4, 0, 0}, // S_RAINPLR1X_3 + {SPR_FX20, 32772, 4, NULL, S_RAINPLR1X_5, 0, 0}, // S_RAINPLR1X_4 + {SPR_FX20, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR1X_5 + {SPR_FX21, 32769, 4, A_RainImpact, S_RAINPLR2X_2, 0, 0}, // S_RAINPLR2X_1 + {SPR_FX21, 32770, 4, NULL, S_RAINPLR2X_3, 0, 0}, // S_RAINPLR2X_2 + {SPR_FX21, 32771, 4, NULL, S_RAINPLR2X_4, 0, 0}, // S_RAINPLR2X_3 + {SPR_FX21, 32772, 4, NULL, S_RAINPLR2X_5, 0, 0}, // S_RAINPLR2X_4 + {SPR_FX21, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR2X_5 + {SPR_FX22, 32769, 4, A_RainImpact, S_RAINPLR3X_2, 0, 0}, // S_RAINPLR3X_1 + {SPR_FX22, 32770, 4, NULL, S_RAINPLR3X_3, 0, 0}, // S_RAINPLR3X_2 + {SPR_FX22, 32771, 4, NULL, S_RAINPLR3X_4, 0, 0}, // S_RAINPLR3X_3 + {SPR_FX22, 32772, 4, NULL, S_RAINPLR3X_5, 0, 0}, // S_RAINPLR3X_4 + {SPR_FX22, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR3X_5 + {SPR_FX23, 32769, 4, A_RainImpact, S_RAINPLR4X_2, 0, 0}, // S_RAINPLR4X_1 + {SPR_FX23, 32770, 4, NULL, S_RAINPLR4X_3, 0, 0}, // S_RAINPLR4X_2 + {SPR_FX23, 32771, 4, NULL, S_RAINPLR4X_4, 0, 0}, // S_RAINPLR4X_3 + {SPR_FX23, 32772, 4, NULL, S_RAINPLR4X_5, 0, 0}, // S_RAINPLR4X_4 + {SPR_FX23, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR4X_5 + {SPR_FX20, 32774, 4, NULL, S_RAINAIRXPLR1_2, 0, 0}, // S_RAINAIRXPLR1_1 + {SPR_FX21, 32774, 4, NULL, S_RAINAIRXPLR2_2, 0, 0}, // S_RAINAIRXPLR2_1 + {SPR_FX22, 32774, 4, NULL, S_RAINAIRXPLR3_2, 0, 0}, // S_RAINAIRXPLR3_1 + {SPR_FX23, 32774, 4, NULL, S_RAINAIRXPLR4_2, 0, 0}, // S_RAINAIRXPLR4_1 + {SPR_FX20, 32775, 4, NULL, S_RAINAIRXPLR1_3, 0, 0}, // S_RAINAIRXPLR1_2 + {SPR_FX21, 32775, 4, NULL, S_RAINAIRXPLR2_3, 0, 0}, // S_RAINAIRXPLR2_2 + {SPR_FX22, 32775, 4, NULL, S_RAINAIRXPLR3_3, 0, 0}, // S_RAINAIRXPLR3_2 + {SPR_FX23, 32775, 4, NULL, S_RAINAIRXPLR4_3, 0, 0}, // S_RAINAIRXPLR4_2 + {SPR_FX20, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR1_3 + {SPR_FX21, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR2_3 + {SPR_FX22, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR3_3 + {SPR_FX23, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR4_3 + {SPR_GWND, 0, 1, A_WeaponReady, S_GOLDWANDREADY, 0, 0}, // S_GOLDWANDREADY + {SPR_GWND, 0, 1, A_Lower, S_GOLDWANDDOWN, 0, 0}, // S_GOLDWANDDOWN + {SPR_GWND, 0, 1, A_Raise, S_GOLDWANDUP, 0, 0}, // S_GOLDWANDUP + {SPR_GWND, 1, 3, NULL, S_GOLDWANDATK1_2, 0, 0}, // S_GOLDWANDATK1_1 + {SPR_GWND, 2, 5, A_FireGoldWandPL1, S_GOLDWANDATK1_3, 0, 0}, // S_GOLDWANDATK1_2 + {SPR_GWND, 3, 3, NULL, S_GOLDWANDATK1_4, 0, 0}, // S_GOLDWANDATK1_3 + {SPR_GWND, 3, 0, A_ReFire, S_GOLDWANDREADY, 0, 0}, // S_GOLDWANDATK1_4 + {SPR_GWND, 1, 3, NULL, S_GOLDWANDATK2_2, 0, 0}, // S_GOLDWANDATK2_1 + {SPR_GWND, 2, 4, A_FireGoldWandPL2, S_GOLDWANDATK2_3, 0, 0}, // S_GOLDWANDATK2_2 + {SPR_GWND, 3, 3, NULL, S_GOLDWANDATK2_4, 0, 0}, // S_GOLDWANDATK2_3 + {SPR_GWND, 3, 0, A_ReFire, S_GOLDWANDREADY, 0, 0}, // S_GOLDWANDATK2_4 + {SPR_FX01, 32768, 6, NULL, S_GWANDFX1_2, 0, 0}, // S_GWANDFX1_1 + {SPR_FX01, 32769, 6, NULL, S_GWANDFX1_1, 0, 0}, // S_GWANDFX1_2 + {SPR_FX01, 32772, 3, NULL, S_GWANDFXI1_2, 0, 0}, // S_GWANDFXI1_1 + {SPR_FX01, 32773, 3, NULL, S_GWANDFXI1_3, 0, 0}, // S_GWANDFXI1_2 + {SPR_FX01, 32774, 3, NULL, S_GWANDFXI1_4, 0, 0}, // S_GWANDFXI1_3 + {SPR_FX01, 32775, 3, NULL, S_NULL, 0, 0}, // S_GWANDFXI1_4 + {SPR_FX01, 32770, 6, NULL, S_GWANDFX2_2, 0, 0}, // S_GWANDFX2_1 + {SPR_FX01, 32771, 6, NULL, S_GWANDFX2_1, 0, 0}, // S_GWANDFX2_2 + {SPR_PUF2, 32768, 3, NULL, S_GWANDPUFF1_2, 0, 0}, // S_GWANDPUFF1_1 + {SPR_PUF2, 32769, 3, NULL, S_GWANDPUFF1_3, 0, 0}, // S_GWANDPUFF1_2 + {SPR_PUF2, 32770, 3, NULL, S_GWANDPUFF1_4, 0, 0}, // S_GWANDPUFF1_3 + {SPR_PUF2, 32771, 3, NULL, S_GWANDPUFF1_5, 0, 0}, // S_GWANDPUFF1_4 + {SPR_PUF2, 32772, 3, NULL, S_NULL, 0, 0}, // S_GWANDPUFF1_5 + {SPR_WPHX, 0, -1, NULL, S_NULL, 0, 0}, // S_WPHX + {SPR_PHNX, 0, 1, A_WeaponReady, S_PHOENIXREADY, 0, 0}, // S_PHOENIXREADY + {SPR_PHNX, 0, 1, A_Lower, S_PHOENIXDOWN, 0, 0}, // S_PHOENIXDOWN + {SPR_PHNX, 0, 1, A_Raise, S_PHOENIXUP, 0, 0}, // S_PHOENIXUP + {SPR_PHNX, 1, 5, NULL, S_PHOENIXATK1_2, 0, 0}, // S_PHOENIXATK1_1 + {SPR_PHNX, 2, 7, A_FirePhoenixPL1, S_PHOENIXATK1_3, 0, 0}, // S_PHOENIXATK1_2 + {SPR_PHNX, 3, 4, NULL, S_PHOENIXATK1_4, 0, 0}, // S_PHOENIXATK1_3 + {SPR_PHNX, 1, 4, NULL, S_PHOENIXATK1_5, 0, 0}, // S_PHOENIXATK1_4 + {SPR_PHNX, 1, 0, A_ReFire, S_PHOENIXREADY, 0, 0}, // S_PHOENIXATK1_5 + {SPR_PHNX, 1, 3, A_InitPhoenixPL2, S_PHOENIXATK2_2, 0, 0}, // S_PHOENIXATK2_1 + {SPR_PHNX, 32770, 1, A_FirePhoenixPL2, S_PHOENIXATK2_3, 0, 0}, // S_PHOENIXATK2_2 + {SPR_PHNX, 1, 4, A_ReFire, S_PHOENIXATK2_4, 0, 0}, // S_PHOENIXATK2_3 + {SPR_PHNX, 1, 4, A_ShutdownPhoenixPL2, S_PHOENIXREADY, 0, 0}, // S_PHOENIXATK2_4 + {SPR_FX04, 32768, 4, A_PhoenixPuff, S_PHOENIXFX1_1, 0, 0}, // S_PHOENIXFX1_1 + {SPR_FX08, 32768, 6, A_Explode, S_PHOENIXFXI1_2, 0, 0}, // S_PHOENIXFXI1_1 + {SPR_FX08, 32769, 5, NULL, S_PHOENIXFXI1_3, 0, 0}, // S_PHOENIXFXI1_2 + {SPR_FX08, 32770, 5, NULL, S_PHOENIXFXI1_4, 0, 0}, // S_PHOENIXFXI1_3 + {SPR_FX08, 32771, 4, NULL, S_PHOENIXFXI1_5, 0, 0}, // S_PHOENIXFXI1_4 + {SPR_FX08, 32772, 4, NULL, S_PHOENIXFXI1_6, 0, 0}, // S_PHOENIXFXI1_5 + {SPR_FX08, 32773, 4, NULL, S_PHOENIXFXI1_7, 0, 0}, // S_PHOENIXFXI1_6 + {SPR_FX08, 32774, 4, NULL, S_PHOENIXFXI1_8, 0, 0}, // S_PHOENIXFXI1_7 + {SPR_FX08, 32775, 4, NULL, S_NULL, 0, 0}, // S_PHOENIXFXI1_8 + {SPR_FX08, 32776, 8, NULL, S_PHOENIXFXIX_1, 0, 0 }, // S_PHOENIXFXIX_1 + {SPR_FX08, 32777, 8, A_RemovedPhoenixFunc, S_PHOENIXFXIX_2, 0, 0 }, // S_PHOENIXFXIX_2 + {SPR_FX08, 32778, 8, NULL, S_NULL, 0, 0 }, // S_PHOENIXFXIX_3 + {SPR_FX04, 1, 4, NULL, S_PHOENIXPUFF2, 0, 0}, // S_PHOENIXPUFF1 + {SPR_FX04, 2, 4, NULL, S_PHOENIXPUFF3, 0, 0}, // S_PHOENIXPUFF2 + {SPR_FX04, 3, 4, NULL, S_PHOENIXPUFF4, 0, 0}, // S_PHOENIXPUFF3 + {SPR_FX04, 4, 4, NULL, S_PHOENIXPUFF5, 0, 0}, // S_PHOENIXPUFF4 + {SPR_FX04, 5, 4, NULL, S_NULL, 0, 0}, // S_PHOENIXPUFF5 + {SPR_FX09, 32768, 2, NULL, S_PHOENIXFX2_2, 0, 0}, // S_PHOENIXFX2_1 + {SPR_FX09, 32769, 2, NULL, S_PHOENIXFX2_3, 0, 0}, // S_PHOENIXFX2_2 + {SPR_FX09, 32768, 2, NULL, S_PHOENIXFX2_4, 0, 0}, // S_PHOENIXFX2_3 + {SPR_FX09, 32769, 2, NULL, S_PHOENIXFX2_5, 0, 0}, // S_PHOENIXFX2_4 + {SPR_FX09, 32768, 2, NULL, S_PHOENIXFX2_6, 0, 0}, // S_PHOENIXFX2_5 + {SPR_FX09, 32769, 2, A_FlameEnd, S_PHOENIXFX2_7, 0, 0}, // S_PHOENIXFX2_6 + {SPR_FX09, 32770, 2, NULL, S_PHOENIXFX2_8, 0, 0}, // S_PHOENIXFX2_7 + {SPR_FX09, 32771, 2, NULL, S_PHOENIXFX2_9, 0, 0}, // S_PHOENIXFX2_8 + {SPR_FX09, 32772, 2, NULL, S_PHOENIXFX2_10, 0, 0}, // S_PHOENIXFX2_9 + {SPR_FX09, 32773, 2, NULL, S_NULL, 0, 0}, // S_PHOENIXFX2_10 + {SPR_FX09, 32774, 3, NULL, S_PHOENIXFXI2_2, 0, 0}, // S_PHOENIXFXI2_1 + {SPR_FX09, 32775, 3, A_FloatPuff, S_PHOENIXFXI2_3, 0, 0}, // S_PHOENIXFXI2_2 + {SPR_FX09, 32776, 4, NULL, S_PHOENIXFXI2_4, 0, 0}, // S_PHOENIXFXI2_3 + {SPR_FX09, 32777, 5, NULL, S_PHOENIXFXI2_5, 0, 0}, // S_PHOENIXFXI2_4 + {SPR_FX09, 32778, 5, NULL, S_NULL, 0, 0}, // S_PHOENIXFXI2_5 + {SPR_WBOW, 0, -1, NULL, S_NULL, 0, 0}, // S_WBOW + {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW2, 0, 0}, // S_CRBOW1 + {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW3, 0, 0}, // S_CRBOW2 + {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW4, 0, 0}, // S_CRBOW3 + {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW5, 0, 0}, // S_CRBOW4 + {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW6, 0, 0}, // S_CRBOW5 + {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW7, 0, 0}, // S_CRBOW6 + {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW8, 0, 0}, // S_CRBOW7 + {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW9, 0, 0}, // S_CRBOW8 + {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW10, 0, 0}, // S_CRBOW9 + {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW11, 0, 0}, // S_CRBOW10 + {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW12, 0, 0}, // S_CRBOW11 + {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW13, 0, 0}, // S_CRBOW12 + {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW14, 0, 0}, // S_CRBOW13 + {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW15, 0, 0}, // S_CRBOW14 + {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW16, 0, 0}, // S_CRBOW15 + {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW17, 0, 0}, // S_CRBOW16 + {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW18, 0, 0}, // S_CRBOW17 + {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW1, 0, 0}, // S_CRBOW18 + {SPR_CRBW, 0, 1, A_Lower, S_CRBOWDOWN, 0, 0}, // S_CRBOWDOWN + {SPR_CRBW, 0, 1, A_Raise, S_CRBOWUP, 0, 0}, // S_CRBOWUP + {SPR_CRBW, 3, 6, A_FireCrossbowPL1, S_CRBOWATK1_2, 0, 0}, // S_CRBOWATK1_1 + {SPR_CRBW, 4, 3, NULL, S_CRBOWATK1_3, 0, 0}, // S_CRBOWATK1_2 + {SPR_CRBW, 5, 3, NULL, S_CRBOWATK1_4, 0, 0}, // S_CRBOWATK1_3 + {SPR_CRBW, 6, 3, NULL, S_CRBOWATK1_5, 0, 0}, // S_CRBOWATK1_4 + {SPR_CRBW, 7, 3, NULL, S_CRBOWATK1_6, 0, 0}, // S_CRBOWATK1_5 + {SPR_CRBW, 0, 4, NULL, S_CRBOWATK1_7, 0, 0}, // S_CRBOWATK1_6 + {SPR_CRBW, 1, 4, NULL, S_CRBOWATK1_8, 0, 0}, // S_CRBOWATK1_7 + {SPR_CRBW, 2, 5, A_ReFire, S_CRBOW1, 0, 0}, // S_CRBOWATK1_8 + {SPR_CRBW, 3, 5, A_FireCrossbowPL2, S_CRBOWATK2_2, 0, 0}, // S_CRBOWATK2_1 + {SPR_CRBW, 4, 3, NULL, S_CRBOWATK2_3, 0, 0}, // S_CRBOWATK2_2 + {SPR_CRBW, 5, 2, NULL, S_CRBOWATK2_4, 0, 0}, // S_CRBOWATK2_3 + {SPR_CRBW, 6, 3, NULL, S_CRBOWATK2_5, 0, 0}, // S_CRBOWATK2_4 + {SPR_CRBW, 7, 2, NULL, S_CRBOWATK2_6, 0, 0}, // S_CRBOWATK2_5 + {SPR_CRBW, 0, 3, NULL, S_CRBOWATK2_7, 0, 0}, // S_CRBOWATK2_6 + {SPR_CRBW, 1, 3, NULL, S_CRBOWATK2_8, 0, 0}, // S_CRBOWATK2_7 + {SPR_CRBW, 2, 4, A_ReFire, S_CRBOW1, 0, 0}, // S_CRBOWATK2_8 + {SPR_FX03, 32769, 1, NULL, S_CRBOWFX1, 0, 0}, // S_CRBOWFX1 + {SPR_FX03, 32775, 8, NULL, S_CRBOWFXI1_2, 0, 0}, // S_CRBOWFXI1_1 + {SPR_FX03, 32776, 8, NULL, S_CRBOWFXI1_3, 0, 0}, // S_CRBOWFXI1_2 + {SPR_FX03, 32777, 8, NULL, S_NULL, 0, 0}, // S_CRBOWFXI1_3 + {SPR_FX03, 32769, 1, A_BoltSpark, S_CRBOWFX2, 0, 0}, // S_CRBOWFX2 + {SPR_FX03, 32768, 1, NULL, S_CRBOWFX3, 0, 0}, // S_CRBOWFX3 + {SPR_FX03, 32770, 8, NULL, S_CRBOWFXI3_2, 0, 0}, // S_CRBOWFXI3_1 + {SPR_FX03, 32771, 8, NULL, S_CRBOWFXI3_3, 0, 0}, // S_CRBOWFXI3_2 + {SPR_FX03, 32772, 8, NULL, S_NULL, 0, 0}, // S_CRBOWFXI3_3 + {SPR_FX03, 32773, 8, NULL, S_CRBOWFX4_2, 0, 0}, // S_CRBOWFX4_1 + {SPR_FX03, 32774, 8, NULL, S_NULL, 0, 0}, // S_CRBOWFX4_2 + {SPR_BLOD, 2, 8, NULL, S_BLOOD2, 0, 0}, // S_BLOOD1 + {SPR_BLOD, 1, 8, NULL, S_BLOOD3, 0, 0}, // S_BLOOD2 + {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOOD3 + {SPR_BLOD, 2, 8, NULL, S_BLOODSPLATTER2, 0, 0}, // S_BLOODSPLATTER1 + {SPR_BLOD, 1, 8, NULL, S_BLOODSPLATTER3, 0, 0}, // S_BLOODSPLATTER2 + {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTER3 + {SPR_BLOD, 0, 6, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTERX + {SPR_PLAY, 0, -1, NULL, S_NULL, 0, 0}, // S_PLAY + {SPR_PLAY, 0, 4, NULL, S_PLAY_RUN2, 0, 0}, // S_PLAY_RUN1 + {SPR_PLAY, 1, 4, NULL, S_PLAY_RUN3, 0, 0}, // S_PLAY_RUN2 + {SPR_PLAY, 2, 4, NULL, S_PLAY_RUN4, 0, 0}, // S_PLAY_RUN3 + {SPR_PLAY, 3, 4, NULL, S_PLAY_RUN1, 0, 0}, // S_PLAY_RUN4 + {SPR_PLAY, 4, 12, NULL, S_PLAY, 0, 0}, // S_PLAY_ATK1 + {SPR_PLAY, 32773, 6, NULL, S_PLAY_ATK1, 0, 0}, // S_PLAY_ATK2 + {SPR_PLAY, 6, 4, NULL, S_PLAY_PAIN2, 0, 0}, // S_PLAY_PAIN + {SPR_PLAY, 6, 4, A_Pain, S_PLAY, 0, 0}, // S_PLAY_PAIN2 + {SPR_PLAY, 7, 6, NULL, S_PLAY_DIE2, 0, 0}, // S_PLAY_DIE1 + {SPR_PLAY, 8, 6, A_Scream, S_PLAY_DIE3, 0, 0}, // S_PLAY_DIE2 + {SPR_PLAY, 9, 6, NULL, S_PLAY_DIE4, 0, 0}, // S_PLAY_DIE3 + {SPR_PLAY, 10, 6, NULL, S_PLAY_DIE5, 0, 0}, // S_PLAY_DIE4 + {SPR_PLAY, 11, 6, A_NoBlocking, S_PLAY_DIE6, 0, 0}, // S_PLAY_DIE5 + {SPR_PLAY, 12, 6, NULL, S_PLAY_DIE7, 0, 0}, // S_PLAY_DIE6 + {SPR_PLAY, 13, 6, NULL, S_PLAY_DIE8, 0, 0}, // S_PLAY_DIE7 + {SPR_PLAY, 14, 6, NULL, S_PLAY_DIE9, 0, 0}, // S_PLAY_DIE8 + {SPR_PLAY, 15, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_PLAY_DIE9 + {SPR_PLAY, 16, 5, A_Scream, S_PLAY_XDIE2, 0, 0}, // S_PLAY_XDIE1 + {SPR_PLAY, 17, 5, A_SkullPop, S_PLAY_XDIE3, 0, 0}, // S_PLAY_XDIE2 + {SPR_PLAY, 18, 5, A_NoBlocking, S_PLAY_XDIE4, 0, 0}, // S_PLAY_XDIE3 + {SPR_PLAY, 19, 5, NULL, S_PLAY_XDIE5, 0, 0}, // S_PLAY_XDIE4 + {SPR_PLAY, 20, 5, NULL, S_PLAY_XDIE6, 0, 0}, // S_PLAY_XDIE5 + {SPR_PLAY, 21, 5, NULL, S_PLAY_XDIE7, 0, 0}, // S_PLAY_XDIE6 + {SPR_PLAY, 22, 5, NULL, S_PLAY_XDIE8, 0, 0}, // S_PLAY_XDIE7 + {SPR_PLAY, 23, 5, NULL, S_PLAY_XDIE9, 0, 0}, // S_PLAY_XDIE8 + {SPR_PLAY, 24, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_PLAY_XDIE9 + {SPR_FDTH, 32768, 5, A_FlameSnd, S_PLAY_FDTH2, 0, 0}, // S_PLAY_FDTH1 + {SPR_FDTH, 32769, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_FDTH2 + {SPR_FDTH, 32770, 5, NULL, S_PLAY_FDTH4, 0, 0}, // S_PLAY_FDTH3 + {SPR_FDTH, 32771, 4, A_Scream, S_PLAY_FDTH5, 0, 0}, // S_PLAY_FDTH4 + {SPR_FDTH, 32772, 5, NULL, S_PLAY_FDTH6, 0, 0}, // S_PLAY_FDTH5 + {SPR_FDTH, 32773, 4, NULL, S_PLAY_FDTH7, 0, 0}, // S_PLAY_FDTH6 + {SPR_FDTH, 32774, 5, A_FlameSnd, S_PLAY_FDTH8, 0, 0}, // S_PLAY_FDTH7 + {SPR_FDTH, 32775, 4, NULL, S_PLAY_FDTH9, 0, 0}, // S_PLAY_FDTH8 + {SPR_FDTH, 32776, 5, NULL, S_PLAY_FDTH10, 0, 0}, // S_PLAY_FDTH9 + {SPR_FDTH, 32777, 4, NULL, S_PLAY_FDTH11, 0, 0}, // S_PLAY_FDTH10 + {SPR_FDTH, 32778, 5, NULL, S_PLAY_FDTH12, 0, 0}, // S_PLAY_FDTH11 + {SPR_FDTH, 32779, 4, NULL, S_PLAY_FDTH13, 0, 0}, // S_PLAY_FDTH12 + {SPR_FDTH, 32780, 5, NULL, S_PLAY_FDTH14, 0, 0}, // S_PLAY_FDTH13 + {SPR_FDTH, 32781, 4, NULL, S_PLAY_FDTH15, 0, 0}, // S_PLAY_FDTH14 + {SPR_FDTH, 32782, 5, A_NoBlocking, S_PLAY_FDTH16, 0, 0}, // S_PLAY_FDTH15 + {SPR_FDTH, 32783, 4, NULL, S_PLAY_FDTH17, 0, 0}, // S_PLAY_FDTH16 + {SPR_FDTH, 32784, 5, NULL, S_PLAY_FDTH18, 0, 0}, // S_PLAY_FDTH17 + {SPR_FDTH, 32785, 4, NULL, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH18 + {SPR_ACLO, 4, 35, A_CheckBurnGone, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH19 + {SPR_ACLO, 4, 8, NULL, S_NULL, 0, 0}, // S_PLAY_FDTH20 + {SPR_BSKL, 0, 5, A_CheckSkullFloor, S_BLOODYSKULL2, 0, 0}, // S_BLOODYSKULL1 + {SPR_BSKL, 1, 5, A_CheckSkullFloor, S_BLOODYSKULL3, 0, 0}, // S_BLOODYSKULL2 + {SPR_BSKL, 2, 5, A_CheckSkullFloor, S_BLOODYSKULL4, 0, 0}, // S_BLOODYSKULL3 + {SPR_BSKL, 3, 5, A_CheckSkullFloor, S_BLOODYSKULL5, 0, 0}, // S_BLOODYSKULL4 + {SPR_BSKL, 4, 5, A_CheckSkullFloor, S_BLOODYSKULL1, 0, 0}, // S_BLOODYSKULL5 + {SPR_BSKL, 5, 16, A_CheckSkullDone, S_BLOODYSKULLX1, 0, 0}, // S_BLOODYSKULLX1 + {SPR_BSKL, 5, 1050, NULL, S_NULL, 0, 0}, // S_BLOODYSKULLX2 + {SPR_CHKN, 0, -1, NULL, S_NULL, 0, 0}, // S_CHICPLAY + {SPR_CHKN, 0, 3, NULL, S_CHICPLAY_RUN2, 0, 0}, // S_CHICPLAY_RUN1 + {SPR_CHKN, 1, 3, NULL, S_CHICPLAY_RUN3, 0, 0}, // S_CHICPLAY_RUN2 + {SPR_CHKN, 0, 3, NULL, S_CHICPLAY_RUN4, 0, 0}, // S_CHICPLAY_RUN3 + {SPR_CHKN, 1, 3, NULL, S_CHICPLAY_RUN1, 0, 0}, // S_CHICPLAY_RUN4 + {SPR_CHKN, 2, 12, NULL, S_CHICPLAY, 0, 0}, // S_CHICPLAY_ATK1 + {SPR_CHKN, 3, 4, A_Feathers, S_CHICPLAY_PAIN2, 0, 0}, // S_CHICPLAY_PAIN + {SPR_CHKN, 2, 4, A_Pain, S_CHICPLAY, 0, 0}, // S_CHICPLAY_PAIN2 + {SPR_CHKN, 0, 10, A_ChicLook, S_CHICKEN_LOOK2, 0, 0}, // S_CHICKEN_LOOK1 + {SPR_CHKN, 1, 10, A_ChicLook, S_CHICKEN_LOOK1, 0, 0}, // S_CHICKEN_LOOK2 + {SPR_CHKN, 0, 3, A_ChicChase, S_CHICKEN_WALK2, 0, 0}, // S_CHICKEN_WALK1 + {SPR_CHKN, 1, 3, A_ChicChase, S_CHICKEN_WALK1, 0, 0}, // S_CHICKEN_WALK2 + {SPR_CHKN, 3, 5, A_Feathers, S_CHICKEN_PAIN2, 0, 0}, // S_CHICKEN_PAIN1 + {SPR_CHKN, 2, 5, A_ChicPain, S_CHICKEN_WALK1, 0, 0}, // S_CHICKEN_PAIN2 + {SPR_CHKN, 0, 8, A_FaceTarget, S_CHICKEN_ATK2, 0, 0}, // S_CHICKEN_ATK1 + {SPR_CHKN, 2, 10, A_ChicAttack, S_CHICKEN_WALK1, 0, 0}, // S_CHICKEN_ATK2 + {SPR_CHKN, 4, 6, A_Scream, S_CHICKEN_DIE2, 0, 0}, // S_CHICKEN_DIE1 + {SPR_CHKN, 5, 6, A_Feathers, S_CHICKEN_DIE3, 0, 0}, // S_CHICKEN_DIE2 + {SPR_CHKN, 6, 6, NULL, S_CHICKEN_DIE4, 0, 0}, // S_CHICKEN_DIE3 + {SPR_CHKN, 7, 6, A_NoBlocking, S_CHICKEN_DIE5, 0, 0}, // S_CHICKEN_DIE4 + {SPR_CHKN, 8, 6, NULL, S_CHICKEN_DIE6, 0, 0}, // S_CHICKEN_DIE5 + {SPR_CHKN, 9, 6, NULL, S_CHICKEN_DIE7, 0, 0}, // S_CHICKEN_DIE6 + {SPR_CHKN, 10, 6, NULL, S_CHICKEN_DIE8, 0, 0}, // S_CHICKEN_DIE7 + {SPR_CHKN, 11, -1, NULL, S_NULL, 0, 0}, // S_CHICKEN_DIE8 + {SPR_CHKN, 12, 3, NULL, S_FEATHER2, 0, 0}, // S_FEATHER1 + {SPR_CHKN, 13, 3, NULL, S_FEATHER3, 0, 0}, // S_FEATHER2 + {SPR_CHKN, 14, 3, NULL, S_FEATHER4, 0, 0}, // S_FEATHER3 + {SPR_CHKN, 15, 3, NULL, S_FEATHER5, 0, 0}, // S_FEATHER4 + {SPR_CHKN, 16, 3, NULL, S_FEATHER6, 0, 0}, // S_FEATHER5 + {SPR_CHKN, 15, 3, NULL, S_FEATHER7, 0, 0}, // S_FEATHER6 + {SPR_CHKN, 14, 3, NULL, S_FEATHER8, 0, 0}, // S_FEATHER7 + {SPR_CHKN, 13, 3, NULL, S_FEATHER1, 0, 0}, // S_FEATHER8 + {SPR_CHKN, 13, 6, NULL, S_NULL, 0, 0}, // S_FEATHERX + {SPR_MUMM, 0, 10, A_Look, S_MUMMY_LOOK2, 0, 0}, // S_MUMMY_LOOK1 + {SPR_MUMM, 1, 10, A_Look, S_MUMMY_LOOK1, 0, 0}, // S_MUMMY_LOOK2 + {SPR_MUMM, 0, 4, A_Chase, S_MUMMY_WALK2, 0, 0}, // S_MUMMY_WALK1 + {SPR_MUMM, 1, 4, A_Chase, S_MUMMY_WALK3, 0, 0}, // S_MUMMY_WALK2 + {SPR_MUMM, 2, 4, A_Chase, S_MUMMY_WALK4, 0, 0}, // S_MUMMY_WALK3 + {SPR_MUMM, 3, 4, A_Chase, S_MUMMY_WALK1, 0, 0}, // S_MUMMY_WALK4 + {SPR_MUMM, 4, 6, A_FaceTarget, S_MUMMY_ATK2, 0, 0}, // S_MUMMY_ATK1 + {SPR_MUMM, 5, 6, A_MummyAttack, S_MUMMY_ATK3, 0, 0}, // S_MUMMY_ATK2 + {SPR_MUMM, 6, 6, A_FaceTarget, S_MUMMY_WALK1, 0, 0}, // S_MUMMY_ATK3 + {SPR_MUMM, 23, 5, A_FaceTarget, S_MUMMYL_ATK2, 0, 0}, // S_MUMMYL_ATK1 + {SPR_MUMM, 32792, 5, A_FaceTarget, S_MUMMYL_ATK3, 0, 0}, // S_MUMMYL_ATK2 + {SPR_MUMM, 23, 5, A_FaceTarget, S_MUMMYL_ATK4, 0, 0}, // S_MUMMYL_ATK3 + {SPR_MUMM, 32792, 5, A_FaceTarget, S_MUMMYL_ATK5, 0, 0}, // S_MUMMYL_ATK4 + {SPR_MUMM, 23, 5, A_FaceTarget, S_MUMMYL_ATK6, 0, 0}, // S_MUMMYL_ATK5 + {SPR_MUMM, 32792, 15, A_MummyAttack2, S_MUMMY_WALK1, 0, 0}, // S_MUMMYL_ATK6 + {SPR_MUMM, 7, 4, NULL, S_MUMMY_PAIN2, 0, 0}, // S_MUMMY_PAIN1 + {SPR_MUMM, 7, 4, A_Pain, S_MUMMY_WALK1, 0, 0}, // S_MUMMY_PAIN2 + {SPR_MUMM, 8, 5, NULL, S_MUMMY_DIE2, 0, 0}, // S_MUMMY_DIE1 + {SPR_MUMM, 9, 5, A_Scream, S_MUMMY_DIE3, 0, 0}, // S_MUMMY_DIE2 + {SPR_MUMM, 10, 5, A_MummySoul, S_MUMMY_DIE4, 0, 0}, // S_MUMMY_DIE3 + {SPR_MUMM, 11, 5, NULL, S_MUMMY_DIE5, 0, 0}, // S_MUMMY_DIE4 + {SPR_MUMM, 12, 5, A_NoBlocking, S_MUMMY_DIE6, 0, 0}, // S_MUMMY_DIE5 + {SPR_MUMM, 13, 5, NULL, S_MUMMY_DIE7, 0, 0}, // S_MUMMY_DIE6 + {SPR_MUMM, 14, 5, NULL, S_MUMMY_DIE8, 0, 0}, // S_MUMMY_DIE7 + {SPR_MUMM, 15, -1, NULL, S_NULL, 0, 0}, // S_MUMMY_DIE8 + {SPR_MUMM, 16, 5, NULL, S_MUMMY_SOUL2, 0, 0}, // S_MUMMY_SOUL1 + {SPR_MUMM, 17, 5, NULL, S_MUMMY_SOUL3, 0, 0}, // S_MUMMY_SOUL2 + {SPR_MUMM, 18, 5, NULL, S_MUMMY_SOUL4, 0, 0}, // S_MUMMY_SOUL3 + {SPR_MUMM, 19, 9, NULL, S_MUMMY_SOUL5, 0, 0}, // S_MUMMY_SOUL4 + {SPR_MUMM, 20, 5, NULL, S_MUMMY_SOUL6, 0, 0}, // S_MUMMY_SOUL5 + {SPR_MUMM, 21, 5, NULL, S_MUMMY_SOUL7, 0, 0}, // S_MUMMY_SOUL6 + {SPR_MUMM, 22, 5, NULL, S_NULL, 0, 0}, // S_MUMMY_SOUL7 + {SPR_FX15, 32768, 5, A_ContMobjSound, S_MUMMYFX1_2, 0, 0}, // S_MUMMYFX1_1 + {SPR_FX15, 32769, 5, A_MummyFX1Seek, S_MUMMYFX1_3, 0, 0}, // S_MUMMYFX1_2 + {SPR_FX15, 32770, 5, NULL, S_MUMMYFX1_4, 0, 0}, // S_MUMMYFX1_3 + {SPR_FX15, 32769, 5, A_MummyFX1Seek, S_MUMMYFX1_1, 0, 0}, // S_MUMMYFX1_4 + {SPR_FX15, 32771, 5, NULL, S_MUMMYFXI1_2, 0, 0}, // S_MUMMYFXI1_1 + {SPR_FX15, 32772, 5, NULL, S_MUMMYFXI1_3, 0, 0}, // S_MUMMYFXI1_2 + {SPR_FX15, 32773, 5, NULL, S_MUMMYFXI1_4, 0, 0}, // S_MUMMYFXI1_3 + {SPR_FX15, 32774, 5, NULL, S_NULL, 0, 0}, // S_MUMMYFXI1_4 + {SPR_BEAS, 0, 10, A_Look, S_BEAST_LOOK2, 0, 0}, // S_BEAST_LOOK1 + {SPR_BEAS, 1, 10, A_Look, S_BEAST_LOOK1, 0, 0}, // S_BEAST_LOOK2 + {SPR_BEAS, 0, 3, A_Chase, S_BEAST_WALK2, 0, 0}, // S_BEAST_WALK1 + {SPR_BEAS, 1, 3, A_Chase, S_BEAST_WALK3, 0, 0}, // S_BEAST_WALK2 + {SPR_BEAS, 2, 3, A_Chase, S_BEAST_WALK4, 0, 0}, // S_BEAST_WALK3 + {SPR_BEAS, 3, 3, A_Chase, S_BEAST_WALK5, 0, 0}, // S_BEAST_WALK4 + {SPR_BEAS, 4, 3, A_Chase, S_BEAST_WALK6, 0, 0}, // S_BEAST_WALK5 + {SPR_BEAS, 5, 3, A_Chase, S_BEAST_WALK1, 0, 0}, // S_BEAST_WALK6 + {SPR_BEAS, 7, 10, A_FaceTarget, S_BEAST_ATK2, 0, 0}, // S_BEAST_ATK1 + {SPR_BEAS, 8, 10, A_BeastAttack, S_BEAST_WALK1, 0, 0}, // S_BEAST_ATK2 + {SPR_BEAS, 6, 3, NULL, S_BEAST_PAIN2, 0, 0}, // S_BEAST_PAIN1 + {SPR_BEAS, 6, 3, A_Pain, S_BEAST_WALK1, 0, 0}, // S_BEAST_PAIN2 + {SPR_BEAS, 17, 6, NULL, S_BEAST_DIE2, 0, 0}, // S_BEAST_DIE1 + {SPR_BEAS, 18, 6, A_Scream, S_BEAST_DIE3, 0, 0}, // S_BEAST_DIE2 + {SPR_BEAS, 19, 6, NULL, S_BEAST_DIE4, 0, 0}, // S_BEAST_DIE3 + {SPR_BEAS, 20, 6, NULL, S_BEAST_DIE5, 0, 0}, // S_BEAST_DIE4 + {SPR_BEAS, 21, 6, NULL, S_BEAST_DIE6, 0, 0}, // S_BEAST_DIE5 + {SPR_BEAS, 22, 6, A_NoBlocking, S_BEAST_DIE7, 0, 0}, // S_BEAST_DIE6 + {SPR_BEAS, 23, 6, NULL, S_BEAST_DIE8, 0, 0}, // S_BEAST_DIE7 + {SPR_BEAS, 24, 6, NULL, S_BEAST_DIE9, 0, 0}, // S_BEAST_DIE8 + {SPR_BEAS, 25, -1, NULL, S_NULL, 0, 0}, // S_BEAST_DIE9 + {SPR_BEAS, 9, 5, NULL, S_BEAST_XDIE2, 0, 0}, // S_BEAST_XDIE1 + {SPR_BEAS, 10, 6, A_Scream, S_BEAST_XDIE3, 0, 0}, // S_BEAST_XDIE2 + {SPR_BEAS, 11, 5, NULL, S_BEAST_XDIE4, 0, 0}, // S_BEAST_XDIE3 + {SPR_BEAS, 12, 6, NULL, S_BEAST_XDIE5, 0, 0}, // S_BEAST_XDIE4 + {SPR_BEAS, 13, 5, NULL, S_BEAST_XDIE6, 0, 0}, // S_BEAST_XDIE5 + {SPR_BEAS, 14, 6, A_NoBlocking, S_BEAST_XDIE7, 0, 0}, // S_BEAST_XDIE6 + {SPR_BEAS, 15, 5, NULL, S_BEAST_XDIE8, 0, 0}, // S_BEAST_XDIE7 + {SPR_BEAS, 16, -1, NULL, S_NULL, 0, 0}, // S_BEAST_XDIE8 + {SPR_FRB1, 0, 2, A_BeastPuff, S_BEASTBALL2, 0, 0}, // S_BEASTBALL1 + {SPR_FRB1, 0, 2, A_BeastPuff, S_BEASTBALL3, 0, 0}, // S_BEASTBALL2 + {SPR_FRB1, 1, 2, A_BeastPuff, S_BEASTBALL4, 0, 0}, // S_BEASTBALL3 + {SPR_FRB1, 1, 2, A_BeastPuff, S_BEASTBALL5, 0, 0}, // S_BEASTBALL4 + {SPR_FRB1, 2, 2, A_BeastPuff, S_BEASTBALL6, 0, 0}, // S_BEASTBALL5 + {SPR_FRB1, 2, 2, A_BeastPuff, S_BEASTBALL1, 0, 0}, // S_BEASTBALL6 + {SPR_FRB1, 3, 4, NULL, S_BEASTBALLX2, 0, 0}, // S_BEASTBALLX1 + {SPR_FRB1, 4, 4, NULL, S_BEASTBALLX3, 0, 0}, // S_BEASTBALLX2 + {SPR_FRB1, 5, 4, NULL, S_BEASTBALLX4, 0, 0}, // S_BEASTBALLX3 + {SPR_FRB1, 6, 4, NULL, S_BEASTBALLX5, 0, 0}, // S_BEASTBALLX4 + {SPR_FRB1, 7, 4, NULL, S_NULL, 0, 0}, // S_BEASTBALLX5 + {SPR_FRB1, 0, 4, NULL, S_BURNBALL2, 0, 0}, // S_BURNBALL1 + {SPR_FRB1, 1, 4, NULL, S_BURNBALL3, 0, 0}, // S_BURNBALL2 + {SPR_FRB1, 2, 4, NULL, S_BURNBALL4, 0, 0}, // S_BURNBALL3 + {SPR_FRB1, 3, 4, NULL, S_BURNBALL5, 0, 0}, // S_BURNBALL4 + {SPR_FRB1, 4, 4, NULL, S_BURNBALL6, 0, 0}, // S_BURNBALL5 + {SPR_FRB1, 5, 4, NULL, S_BURNBALL7, 0, 0}, // S_BURNBALL6 + {SPR_FRB1, 6, 4, NULL, S_BURNBALL8, 0, 0}, // S_BURNBALL7 + {SPR_FRB1, 7, 4, NULL, S_NULL, 0, 0}, // S_BURNBALL8 + {SPR_FRB1, 32768, 4, NULL, S_BURNBALLFB2, 0, 0}, // S_BURNBALLFB1 + {SPR_FRB1, 32769, 4, NULL, S_BURNBALLFB3, 0, 0}, // S_BURNBALLFB2 + {SPR_FRB1, 32770, 4, NULL, S_BURNBALLFB4, 0, 0}, // S_BURNBALLFB3 + {SPR_FRB1, 32771, 4, NULL, S_BURNBALLFB5, 0, 0}, // S_BURNBALLFB4 + {SPR_FRB1, 32772, 4, NULL, S_BURNBALLFB6, 0, 0}, // S_BURNBALLFB5 + {SPR_FRB1, 32773, 4, NULL, S_BURNBALLFB7, 0, 0}, // S_BURNBALLFB6 + {SPR_FRB1, 32774, 4, NULL, S_BURNBALLFB8, 0, 0}, // S_BURNBALLFB7 + {SPR_FRB1, 32775, 4, NULL, S_NULL, 0, 0}, // S_BURNBALLFB8 + {SPR_FRB1, 3, 4, NULL, S_PUFFY2, 0, 0}, // S_PUFFY1 + {SPR_FRB1, 4, 4, NULL, S_PUFFY3, 0, 0}, // S_PUFFY2 + {SPR_FRB1, 5, 4, NULL, S_PUFFY4, 0, 0}, // S_PUFFY3 + {SPR_FRB1, 6, 4, NULL, S_PUFFY5, 0, 0}, // S_PUFFY4 + {SPR_FRB1, 7, 4, NULL, S_NULL, 0, 0}, // S_PUFFY5 + {SPR_SNKE, 0, 10, A_Look, S_SNAKE_LOOK2, 0, 0}, // S_SNAKE_LOOK1 + {SPR_SNKE, 1, 10, A_Look, S_SNAKE_LOOK1, 0, 0}, // S_SNAKE_LOOK2 + {SPR_SNKE, 0, 4, A_Chase, S_SNAKE_WALK2, 0, 0}, // S_SNAKE_WALK1 + {SPR_SNKE, 1, 4, A_Chase, S_SNAKE_WALK3, 0, 0}, // S_SNAKE_WALK2 + {SPR_SNKE, 2, 4, A_Chase, S_SNAKE_WALK4, 0, 0}, // S_SNAKE_WALK3 + {SPR_SNKE, 3, 4, A_Chase, S_SNAKE_WALK1, 0, 0}, // S_SNAKE_WALK4 + {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK2, 0, 0}, // S_SNAKE_ATK1 + {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK3, 0, 0}, // S_SNAKE_ATK2 + {SPR_SNKE, 5, 4, A_SnakeAttack, S_SNAKE_ATK4, 0, 0}, // S_SNAKE_ATK3 + {SPR_SNKE, 5, 4, A_SnakeAttack, S_SNAKE_ATK5, 0, 0}, // S_SNAKE_ATK4 + {SPR_SNKE, 5, 4, A_SnakeAttack, S_SNAKE_ATK6, 0, 0}, // S_SNAKE_ATK5 + {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK7, 0, 0}, // S_SNAKE_ATK6 + {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK8, 0, 0}, // S_SNAKE_ATK7 + {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK9, 0, 0}, // S_SNAKE_ATK8 + {SPR_SNKE, 5, 4, A_SnakeAttack2, S_SNAKE_WALK1, 0, 0}, // S_SNAKE_ATK9 + {SPR_SNKE, 4, 3, NULL, S_SNAKE_PAIN2, 0, 0}, // S_SNAKE_PAIN1 + {SPR_SNKE, 4, 3, A_Pain, S_SNAKE_WALK1, 0, 0}, // S_SNAKE_PAIN2 + {SPR_SNKE, 6, 5, NULL, S_SNAKE_DIE2, 0, 0}, // S_SNAKE_DIE1 + {SPR_SNKE, 7, 5, A_Scream, S_SNAKE_DIE3, 0, 0}, // S_SNAKE_DIE2 + {SPR_SNKE, 8, 5, NULL, S_SNAKE_DIE4, 0, 0}, // S_SNAKE_DIE3 + {SPR_SNKE, 9, 5, NULL, S_SNAKE_DIE5, 0, 0}, // S_SNAKE_DIE4 + {SPR_SNKE, 10, 5, NULL, S_SNAKE_DIE6, 0, 0}, // S_SNAKE_DIE5 + {SPR_SNKE, 11, 5, NULL, S_SNAKE_DIE7, 0, 0}, // S_SNAKE_DIE6 + {SPR_SNKE, 12, 5, A_NoBlocking, S_SNAKE_DIE8, 0, 0}, // S_SNAKE_DIE7 + {SPR_SNKE, 13, 5, NULL, S_SNAKE_DIE9, 0, 0}, // S_SNAKE_DIE8 + {SPR_SNKE, 14, 5, NULL, S_SNAKE_DIE10, 0, 0}, // S_SNAKE_DIE9 + {SPR_SNKE, 15, -1, NULL, S_NULL, 0, 0}, // S_SNAKE_DIE10 + {SPR_SNFX, 32768, 5, NULL, S_SNAKEPRO_A2, 0, 0}, // S_SNAKEPRO_A1 + {SPR_SNFX, 32769, 5, NULL, S_SNAKEPRO_A3, 0, 0}, // S_SNAKEPRO_A2 + {SPR_SNFX, 32770, 5, NULL, S_SNAKEPRO_A4, 0, 0}, // S_SNAKEPRO_A3 + {SPR_SNFX, 32771, 5, NULL, S_SNAKEPRO_A1, 0, 0}, // S_SNAKEPRO_A4 + {SPR_SNFX, 32772, 5, NULL, S_SNAKEPRO_AX2, 0, 0}, // S_SNAKEPRO_AX1 + {SPR_SNFX, 32773, 5, NULL, S_SNAKEPRO_AX3, 0, 0}, // S_SNAKEPRO_AX2 + {SPR_SNFX, 32774, 4, NULL, S_SNAKEPRO_AX4, 0, 0}, // S_SNAKEPRO_AX3 + {SPR_SNFX, 32775, 3, NULL, S_SNAKEPRO_AX5, 0, 0}, // S_SNAKEPRO_AX4 + {SPR_SNFX, 32776, 3, NULL, S_NULL, 0, 0}, // S_SNAKEPRO_AX5 + {SPR_SNFX, 32777, 6, NULL, S_SNAKEPRO_B2, 0, 0}, // S_SNAKEPRO_B1 + {SPR_SNFX, 32778, 6, NULL, S_SNAKEPRO_B1, 0, 0}, // S_SNAKEPRO_B2 + {SPR_SNFX, 32779, 5, NULL, S_SNAKEPRO_BX2, 0, 0}, // S_SNAKEPRO_BX1 + {SPR_SNFX, 32780, 5, NULL, S_SNAKEPRO_BX3, 0, 0}, // S_SNAKEPRO_BX2 + {SPR_SNFX, 32781, 4, NULL, S_SNAKEPRO_BX4, 0, 0}, // S_SNAKEPRO_BX3 + {SPR_SNFX, 32782, 3, NULL, S_NULL, 0, 0}, // S_SNAKEPRO_BX4 + {SPR_HEAD, 0, 10, A_Look, S_HEAD_LOOK, 0, 0}, // S_HEAD_LOOK + {SPR_HEAD, 0, 4, A_Chase, S_HEAD_FLOAT, 0, 0}, // S_HEAD_FLOAT + {SPR_HEAD, 0, 5, A_FaceTarget, S_HEAD_ATK2, 0, 0}, // S_HEAD_ATK1 + {SPR_HEAD, 1, 20, A_HeadAttack, S_HEAD_FLOAT, 0, 0}, // S_HEAD_ATK2 + {SPR_HEAD, 0, 4, NULL, S_HEAD_PAIN2, 0, 0}, // S_HEAD_PAIN1 + {SPR_HEAD, 0, 4, A_Pain, S_HEAD_FLOAT, 0, 0}, // S_HEAD_PAIN2 + {SPR_HEAD, 2, 7, NULL, S_HEAD_DIE2, 0, 0}, // S_HEAD_DIE1 + {SPR_HEAD, 3, 7, A_Scream, S_HEAD_DIE3, 0, 0}, // S_HEAD_DIE2 + {SPR_HEAD, 4, 7, NULL, S_HEAD_DIE4, 0, 0}, // S_HEAD_DIE3 + {SPR_HEAD, 5, 7, NULL, S_HEAD_DIE5, 0, 0}, // S_HEAD_DIE4 + {SPR_HEAD, 6, 7, A_NoBlocking, S_HEAD_DIE6, 0, 0}, // S_HEAD_DIE5 + {SPR_HEAD, 7, 7, NULL, S_HEAD_DIE7, 0, 0}, // S_HEAD_DIE6 + {SPR_HEAD, 8, -1, A_BossDeath, S_NULL, 0, 0}, // S_HEAD_DIE7 + {SPR_FX05, 0, 6, NULL, S_HEADFX1_2, 0, 0}, // S_HEADFX1_1 + {SPR_FX05, 1, 6, NULL, S_HEADFX1_3, 0, 0}, // S_HEADFX1_2 + {SPR_FX05, 2, 6, NULL, S_HEADFX1_1, 0, 0}, // S_HEADFX1_3 + {SPR_FX05, 3, 5, A_HeadIceImpact, S_HEADFXI1_2, 0, 0}, // S_HEADFXI1_1 + {SPR_FX05, 4, 5, NULL, S_HEADFXI1_3, 0, 0}, // S_HEADFXI1_2 + {SPR_FX05, 5, 5, NULL, S_HEADFXI1_4, 0, 0}, // S_HEADFXI1_3 + {SPR_FX05, 6, 5, NULL, S_NULL, 0, 0}, // S_HEADFXI1_4 + {SPR_FX05, 7, 6, NULL, S_HEADFX2_2, 0, 0}, // S_HEADFX2_1 + {SPR_FX05, 8, 6, NULL, S_HEADFX2_3, 0, 0}, // S_HEADFX2_2 + {SPR_FX05, 9, 6, NULL, S_HEADFX2_1, 0, 0}, // S_HEADFX2_3 + {SPR_FX05, 3, 5, NULL, S_HEADFXI2_2, 0, 0}, // S_HEADFXI2_1 + {SPR_FX05, 4, 5, NULL, S_HEADFXI2_3, 0, 0}, // S_HEADFXI2_2 + {SPR_FX05, 5, 5, NULL, S_HEADFXI2_4, 0, 0}, // S_HEADFXI2_3 + {SPR_FX05, 6, 5, NULL, S_NULL, 0, 0}, // S_HEADFXI2_4 + {SPR_FX06, 0, 4, A_HeadFireGrow, S_HEADFX3_2, 0, 0}, // S_HEADFX3_1 + {SPR_FX06, 1, 4, A_HeadFireGrow, S_HEADFX3_3, 0, 0}, // S_HEADFX3_2 + {SPR_FX06, 2, 4, A_HeadFireGrow, S_HEADFX3_1, 0, 0}, // S_HEADFX3_3 + {SPR_FX06, 0, 5, NULL, S_HEADFX3_5, 0, 0}, // S_HEADFX3_4 + {SPR_FX06, 1, 5, NULL, S_HEADFX3_6, 0, 0}, // S_HEADFX3_5 + {SPR_FX06, 2, 5, NULL, S_HEADFX3_4, 0, 0}, // S_HEADFX3_6 + {SPR_FX06, 3, 5, NULL, S_HEADFXI3_2, 0, 0}, // S_HEADFXI3_1 + {SPR_FX06, 4, 5, NULL, S_HEADFXI3_3, 0, 0}, // S_HEADFXI3_2 + {SPR_FX06, 5, 5, NULL, S_HEADFXI3_4, 0, 0}, // S_HEADFXI3_3 + {SPR_FX06, 6, 5, NULL, S_NULL, 0, 0}, // S_HEADFXI3_4 + {SPR_FX07, 3, 3, NULL, S_HEADFX4_2, 0, 0}, // S_HEADFX4_1 + {SPR_FX07, 4, 3, NULL, S_HEADFX4_3, 0, 0}, // S_HEADFX4_2 + {SPR_FX07, 5, 3, NULL, S_HEADFX4_4, 0, 0}, // S_HEADFX4_3 + {SPR_FX07, 6, 3, NULL, S_HEADFX4_5, 0, 0}, // S_HEADFX4_4 + {SPR_FX07, 0, 3, A_WhirlwindSeek, S_HEADFX4_6, 0, 0}, // S_HEADFX4_5 + {SPR_FX07, 1, 3, A_WhirlwindSeek, S_HEADFX4_7, 0, 0}, // S_HEADFX4_6 + {SPR_FX07, 2, 3, A_WhirlwindSeek, S_HEADFX4_5, 0, 0}, // S_HEADFX4_7 + {SPR_FX07, 6, 4, NULL, S_HEADFXI4_2, 0, 0}, // S_HEADFXI4_1 + {SPR_FX07, 5, 4, NULL, S_HEADFXI4_3, 0, 0}, // S_HEADFXI4_2 + {SPR_FX07, 4, 4, NULL, S_HEADFXI4_4, 0, 0}, // S_HEADFXI4_3 + {SPR_FX07, 3, 4, NULL, S_NULL, 0, 0}, // S_HEADFXI4_4 + {SPR_CLNK, 0, 10, A_Look, S_CLINK_LOOK2, 0, 0}, // S_CLINK_LOOK1 + {SPR_CLNK, 1, 10, A_Look, S_CLINK_LOOK1, 0, 0}, // S_CLINK_LOOK2 + {SPR_CLNK, 0, 3, A_Chase, S_CLINK_WALK2, 0, 0}, // S_CLINK_WALK1 + {SPR_CLNK, 1, 3, A_Chase, S_CLINK_WALK3, 0, 0}, // S_CLINK_WALK2 + {SPR_CLNK, 2, 3, A_Chase, S_CLINK_WALK4, 0, 0}, // S_CLINK_WALK3 + {SPR_CLNK, 3, 3, A_Chase, S_CLINK_WALK1, 0, 0}, // S_CLINK_WALK4 + {SPR_CLNK, 4, 5, A_FaceTarget, S_CLINK_ATK2, 0, 0}, // S_CLINK_ATK1 + {SPR_CLNK, 5, 4, A_FaceTarget, S_CLINK_ATK3, 0, 0}, // S_CLINK_ATK2 + {SPR_CLNK, 6, 7, A_ClinkAttack, S_CLINK_WALK1, 0, 0}, // S_CLINK_ATK3 + {SPR_CLNK, 7, 3, NULL, S_CLINK_PAIN2, 0, 0}, // S_CLINK_PAIN1 + {SPR_CLNK, 7, 3, A_Pain, S_CLINK_WALK1, 0, 0}, // S_CLINK_PAIN2 + {SPR_CLNK, 8, 6, NULL, S_CLINK_DIE2, 0, 0}, // S_CLINK_DIE1 + {SPR_CLNK, 9, 6, NULL, S_CLINK_DIE3, 0, 0}, // S_CLINK_DIE2 + {SPR_CLNK, 10, 5, A_Scream, S_CLINK_DIE4, 0, 0}, // S_CLINK_DIE3 + {SPR_CLNK, 11, 5, A_NoBlocking, S_CLINK_DIE5, 0, 0}, // S_CLINK_DIE4 + {SPR_CLNK, 12, 5, NULL, S_CLINK_DIE6, 0, 0}, // S_CLINK_DIE5 + {SPR_CLNK, 13, 5, NULL, S_CLINK_DIE7, 0, 0}, // S_CLINK_DIE6 + {SPR_CLNK, 14, -1, NULL, S_NULL, 0, 0}, // S_CLINK_DIE7 + {SPR_WZRD, 0, 10, A_Look, S_WIZARD_LOOK2, 0, 0}, // S_WIZARD_LOOK1 + {SPR_WZRD, 1, 10, A_Look, S_WIZARD_LOOK1, 0, 0}, // S_WIZARD_LOOK2 + {SPR_WZRD, 0, 3, A_Chase, S_WIZARD_WALK2, 0, 0}, // S_WIZARD_WALK1 + {SPR_WZRD, 0, 4, A_Chase, S_WIZARD_WALK3, 0, 0}, // S_WIZARD_WALK2 + {SPR_WZRD, 0, 3, A_Chase, S_WIZARD_WALK4, 0, 0}, // S_WIZARD_WALK3 + {SPR_WZRD, 0, 4, A_Chase, S_WIZARD_WALK5, 0, 0}, // S_WIZARD_WALK4 + {SPR_WZRD, 1, 3, A_Chase, S_WIZARD_WALK6, 0, 0}, // S_WIZARD_WALK5 + {SPR_WZRD, 1, 4, A_Chase, S_WIZARD_WALK7, 0, 0}, // S_WIZARD_WALK6 + {SPR_WZRD, 1, 3, A_Chase, S_WIZARD_WALK8, 0, 0}, // S_WIZARD_WALK7 + {SPR_WZRD, 1, 4, A_Chase, S_WIZARD_WALK1, 0, 0}, // S_WIZARD_WALK8 + {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK2, 0, 0}, // S_WIZARD_ATK1 + {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK3, 0, 0}, // S_WIZARD_ATK2 + {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK4, 0, 0}, // S_WIZARD_ATK3 + {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK5, 0, 0}, // S_WIZARD_ATK4 + {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK6, 0, 0}, // S_WIZARD_ATK5 + {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK7, 0, 0}, // S_WIZARD_ATK6 + {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK8, 0, 0}, // S_WIZARD_ATK7 + {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK9, 0, 0}, // S_WIZARD_ATK8 + {SPR_WZRD, 3, 12, A_WizAtk3, S_WIZARD_WALK1, 0, 0}, // S_WIZARD_ATK9 + {SPR_WZRD, 4, 3, A_GhostOff, S_WIZARD_PAIN2, 0, 0}, // S_WIZARD_PAIN1 + {SPR_WZRD, 4, 3, A_Pain, S_WIZARD_WALK1, 0, 0}, // S_WIZARD_PAIN2 + {SPR_WZRD, 5, 6, A_GhostOff, S_WIZARD_DIE2, 0, 0}, // S_WIZARD_DIE1 + {SPR_WZRD, 6, 6, A_Scream, S_WIZARD_DIE3, 0, 0}, // S_WIZARD_DIE2 + {SPR_WZRD, 7, 6, NULL, S_WIZARD_DIE4, 0, 0}, // S_WIZARD_DIE3 + {SPR_WZRD, 8, 6, NULL, S_WIZARD_DIE5, 0, 0}, // S_WIZARD_DIE4 + {SPR_WZRD, 9, 6, A_NoBlocking, S_WIZARD_DIE6, 0, 0}, // S_WIZARD_DIE5 + {SPR_WZRD, 10, 6, NULL, S_WIZARD_DIE7, 0, 0}, // S_WIZARD_DIE6 + {SPR_WZRD, 11, 6, NULL, S_WIZARD_DIE8, 0, 0}, // S_WIZARD_DIE7 + {SPR_WZRD, 12, -1, NULL, S_NULL, 0, 0}, // S_WIZARD_DIE8 + {SPR_FX11, 32768, 6, NULL, S_WIZFX1_2, 0, 0}, // S_WIZFX1_1 + {SPR_FX11, 32769, 6, NULL, S_WIZFX1_1, 0, 0}, // S_WIZFX1_2 + {SPR_FX11, 32770, 5, NULL, S_WIZFXI1_2, 0, 0}, // S_WIZFXI1_1 + {SPR_FX11, 32771, 5, NULL, S_WIZFXI1_3, 0, 0}, // S_WIZFXI1_2 + {SPR_FX11, 32772, 5, NULL, S_WIZFXI1_4, 0, 0}, // S_WIZFXI1_3 + {SPR_FX11, 32773, 5, NULL, S_WIZFXI1_5, 0, 0}, // S_WIZFXI1_4 + {SPR_FX11, 32774, 5, NULL, S_NULL, 0, 0}, // S_WIZFXI1_5 + {SPR_IMPX, 0, 10, A_Look, S_IMP_LOOK2, 0, 0}, // S_IMP_LOOK1 + {SPR_IMPX, 1, 10, A_Look, S_IMP_LOOK3, 0, 0}, // S_IMP_LOOK2 + {SPR_IMPX, 2, 10, A_Look, S_IMP_LOOK4, 0, 0}, // S_IMP_LOOK3 + {SPR_IMPX, 1, 10, A_Look, S_IMP_LOOK1, 0, 0}, // S_IMP_LOOK4 + {SPR_IMPX, 0, 3, A_Chase, S_IMP_FLY2, 0, 0}, // S_IMP_FLY1 + {SPR_IMPX, 0, 3, A_Chase, S_IMP_FLY3, 0, 0}, // S_IMP_FLY2 + {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY4, 0, 0}, // S_IMP_FLY3 + {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY5, 0, 0}, // S_IMP_FLY4 + {SPR_IMPX, 2, 3, A_Chase, S_IMP_FLY6, 0, 0}, // S_IMP_FLY5 + {SPR_IMPX, 2, 3, A_Chase, S_IMP_FLY7, 0, 0}, // S_IMP_FLY6 + {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY8, 0, 0}, // S_IMP_FLY7 + {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY1, 0, 0}, // S_IMP_FLY8 + {SPR_IMPX, 3, 6, A_FaceTarget, S_IMP_MEATK2, 0, 0}, // S_IMP_MEATK1 + {SPR_IMPX, 4, 6, A_FaceTarget, S_IMP_MEATK3, 0, 0}, // S_IMP_MEATK2 + {SPR_IMPX, 5, 6, A_ImpMeAttack, S_IMP_FLY1, 0, 0}, // S_IMP_MEATK3 + {SPR_IMPX, 0, 10, A_FaceTarget, S_IMP_MSATK1_2, 0, 0}, // S_IMP_MSATK1_1 + {SPR_IMPX, 1, 6, A_ImpMsAttack, S_IMP_MSATK1_3, 0, 0}, // S_IMP_MSATK1_2 + {SPR_IMPX, 2, 6, NULL, S_IMP_MSATK1_4, 0, 0}, // S_IMP_MSATK1_3 + {SPR_IMPX, 1, 6, NULL, S_IMP_MSATK1_5, 0, 0}, // S_IMP_MSATK1_4 + {SPR_IMPX, 0, 6, NULL, S_IMP_MSATK1_6, 0, 0}, // S_IMP_MSATK1_5 + {SPR_IMPX, 1, 6, NULL, S_IMP_MSATK1_3, 0, 0}, // S_IMP_MSATK1_6 + {SPR_IMPX, 3, 6, A_FaceTarget, S_IMP_MSATK2_2, 0, 0}, // S_IMP_MSATK2_1 + {SPR_IMPX, 4, 6, A_FaceTarget, S_IMP_MSATK2_3, 0, 0}, // S_IMP_MSATK2_2 + {SPR_IMPX, 5, 6, A_ImpMsAttack2, S_IMP_FLY1, 0, 0}, // S_IMP_MSATK2_3 + {SPR_IMPX, 6, 3, NULL, S_IMP_PAIN2, 0, 0}, // S_IMP_PAIN1 + {SPR_IMPX, 6, 3, A_Pain, S_IMP_FLY1, 0, 0}, // S_IMP_PAIN2 + {SPR_IMPX, 6, 4, A_ImpDeath, S_IMP_DIE2, 0, 0}, // S_IMP_DIE1 + {SPR_IMPX, 7, 5, NULL, S_IMP_DIE2, 0, 0}, // S_IMP_DIE2 + {SPR_IMPX, 18, 5, A_ImpXDeath1, S_IMP_XDIE2, 0, 0}, // S_IMP_XDIE1 + {SPR_IMPX, 19, 5, NULL, S_IMP_XDIE3, 0, 0}, // S_IMP_XDIE2 + {SPR_IMPX, 20, 5, NULL, S_IMP_XDIE4, 0, 0}, // S_IMP_XDIE3 + {SPR_IMPX, 21, 5, A_ImpXDeath2, S_IMP_XDIE5, 0, 0}, // S_IMP_XDIE4 + {SPR_IMPX, 22, 5, NULL, S_IMP_XDIE5, 0, 0}, // S_IMP_XDIE5 + {SPR_IMPX, 8, 7, A_ImpExplode, S_IMP_CRASH2, 0, 0}, // S_IMP_CRASH1 + {SPR_IMPX, 9, 7, A_Scream, S_IMP_CRASH3, 0, 0}, // S_IMP_CRASH2 + {SPR_IMPX, 10, 7, NULL, S_IMP_CRASH4, 0, 0}, // S_IMP_CRASH3 + {SPR_IMPX, 11, -1, NULL, S_NULL, 0, 0}, // S_IMP_CRASH4 + {SPR_IMPX, 23, 7, NULL, S_IMP_XCRASH2, 0, 0}, // S_IMP_XCRASH1 + {SPR_IMPX, 24, 7, NULL, S_IMP_XCRASH3, 0, 0}, // S_IMP_XCRASH2 + {SPR_IMPX, 25, -1, NULL, S_NULL, 0, 0}, // S_IMP_XCRASH3 + {SPR_IMPX, 12, 5, NULL, S_IMP_CHUNKA2, 0, 0}, // S_IMP_CHUNKA1 + {SPR_IMPX, 13, 700, NULL, S_IMP_CHUNKA3, 0, 0}, // S_IMP_CHUNKA2 + {SPR_IMPX, 14, 700, NULL, S_NULL, 0, 0}, // S_IMP_CHUNKA3 + {SPR_IMPX, 15, 5, NULL, S_IMP_CHUNKB2, 0, 0}, // S_IMP_CHUNKB1 + {SPR_IMPX, 16, 700, NULL, S_IMP_CHUNKB3, 0, 0}, // S_IMP_CHUNKB2 + {SPR_IMPX, 17, 700, NULL, S_NULL, 0, 0}, // S_IMP_CHUNKB3 + {SPR_FX10, 32768, 6, NULL, S_IMPFX2, 0, 0}, // S_IMPFX1 + {SPR_FX10, 32769, 6, NULL, S_IMPFX3, 0, 0}, // S_IMPFX2 + {SPR_FX10, 32770, 6, NULL, S_IMPFX1, 0, 0}, // S_IMPFX3 + {SPR_FX10, 32771, 5, NULL, S_IMPFXI2, 0, 0}, // S_IMPFXI1 + {SPR_FX10, 32772, 5, NULL, S_IMPFXI3, 0, 0}, // S_IMPFXI2 + {SPR_FX10, 32773, 5, NULL, S_IMPFXI4, 0, 0}, // S_IMPFXI3 + {SPR_FX10, 32774, 5, NULL, S_NULL, 0, 0}, // S_IMPFXI4 + {SPR_KNIG, 0, 10, A_Look, S_KNIGHT_STND2, 0, 0}, // S_KNIGHT_STND1 + {SPR_KNIG, 1, 10, A_Look, S_KNIGHT_STND1, 0, 0}, // S_KNIGHT_STND2 + {SPR_KNIG, 0, 4, A_Chase, S_KNIGHT_WALK2, 0, 0}, // S_KNIGHT_WALK1 + {SPR_KNIG, 1, 4, A_Chase, S_KNIGHT_WALK3, 0, 0}, // S_KNIGHT_WALK2 + {SPR_KNIG, 2, 4, A_Chase, S_KNIGHT_WALK4, 0, 0}, // S_KNIGHT_WALK3 + {SPR_KNIG, 3, 4, A_Chase, S_KNIGHT_WALK1, 0, 0}, // S_KNIGHT_WALK4 + {SPR_KNIG, 4, 10, A_FaceTarget, S_KNIGHT_ATK2, 0, 0}, // S_KNIGHT_ATK1 + {SPR_KNIG, 5, 8, A_FaceTarget, S_KNIGHT_ATK3, 0, 0}, // S_KNIGHT_ATK2 + {SPR_KNIG, 6, 8, A_KnightAttack, S_KNIGHT_ATK4, 0, 0}, // S_KNIGHT_ATK3 + {SPR_KNIG, 4, 10, A_FaceTarget, S_KNIGHT_ATK5, 0, 0}, // S_KNIGHT_ATK4 + {SPR_KNIG, 5, 8, A_FaceTarget, S_KNIGHT_ATK6, 0, 0}, // S_KNIGHT_ATK5 + {SPR_KNIG, 6, 8, A_KnightAttack, S_KNIGHT_WALK1, 0, 0}, // S_KNIGHT_ATK6 + {SPR_KNIG, 7, 3, NULL, S_KNIGHT_PAIN2, 0, 0}, // S_KNIGHT_PAIN1 + {SPR_KNIG, 7, 3, A_Pain, S_KNIGHT_WALK1, 0, 0}, // S_KNIGHT_PAIN2 + {SPR_KNIG, 8, 6, NULL, S_KNIGHT_DIE2, 0, 0}, // S_KNIGHT_DIE1 + {SPR_KNIG, 9, 6, A_Scream, S_KNIGHT_DIE3, 0, 0}, // S_KNIGHT_DIE2 + {SPR_KNIG, 10, 6, NULL, S_KNIGHT_DIE4, 0, 0}, // S_KNIGHT_DIE3 + {SPR_KNIG, 11, 6, A_NoBlocking, S_KNIGHT_DIE5, 0, 0}, // S_KNIGHT_DIE4 + {SPR_KNIG, 12, 6, NULL, S_KNIGHT_DIE6, 0, 0}, // S_KNIGHT_DIE5 + {SPR_KNIG, 13, 6, NULL, S_KNIGHT_DIE7, 0, 0}, // S_KNIGHT_DIE6 + {SPR_KNIG, 14, -1, NULL, S_NULL, 0, 0}, // S_KNIGHT_DIE7 + {SPR_SPAX, 32768, 3, A_ContMobjSound, S_SPINAXE2, 0, 0}, // S_SPINAXE1 + {SPR_SPAX, 32769, 3, NULL, S_SPINAXE3, 0, 0}, // S_SPINAXE2 + {SPR_SPAX, 32770, 3, NULL, S_SPINAXE1, 0, 0}, // S_SPINAXE3 + {SPR_SPAX, 32771, 6, NULL, S_SPINAXEX2, 0, 0}, // S_SPINAXEX1 + {SPR_SPAX, 32772, 6, NULL, S_SPINAXEX3, 0, 0}, // S_SPINAXEX2 + {SPR_SPAX, 32773, 6, NULL, S_NULL, 0, 0}, // S_SPINAXEX3 + {SPR_RAXE, 32768, 5, A_DripBlood, S_REDAXE2, 0, 0}, // S_REDAXE1 + {SPR_RAXE, 32769, 5, A_DripBlood, S_REDAXE1, 0, 0}, // S_REDAXE2 + {SPR_RAXE, 32770, 6, NULL, S_REDAXEX2, 0, 0}, // S_REDAXEX1 + {SPR_RAXE, 32771, 6, NULL, S_REDAXEX3, 0, 0}, // S_REDAXEX2 + {SPR_RAXE, 32772, 6, NULL, S_NULL, 0, 0}, // S_REDAXEX3 + {SPR_SRCR, 0, 10, A_Look, S_SRCR1_LOOK2, 0, 0}, // S_SRCR1_LOOK1 + {SPR_SRCR, 1, 10, A_Look, S_SRCR1_LOOK1, 0, 0}, // S_SRCR1_LOOK2 + {SPR_SRCR, 0, 5, A_Sor1Chase, S_SRCR1_WALK2, 0, 0}, // S_SRCR1_WALK1 + {SPR_SRCR, 1, 5, A_Sor1Chase, S_SRCR1_WALK3, 0, 0}, // S_SRCR1_WALK2 + {SPR_SRCR, 2, 5, A_Sor1Chase, S_SRCR1_WALK4, 0, 0}, // S_SRCR1_WALK3 + {SPR_SRCR, 3, 5, A_Sor1Chase, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_WALK4 + {SPR_SRCR, 16, 6, A_Sor1Pain, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_PAIN1 + {SPR_SRCR, 16, 7, A_FaceTarget, S_SRCR1_ATK2, 0, 0}, // S_SRCR1_ATK1 + {SPR_SRCR, 17, 6, A_FaceTarget, S_SRCR1_ATK3, 0, 0}, // S_SRCR1_ATK2 + {SPR_SRCR, 18, 10, A_Srcr1Attack, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_ATK3 + {SPR_SRCR, 18, 10, A_FaceTarget, S_SRCR1_ATK5, 0, 0}, // S_SRCR1_ATK4 + {SPR_SRCR, 16, 7, A_FaceTarget, S_SRCR1_ATK6, 0, 0}, // S_SRCR1_ATK5 + {SPR_SRCR, 17, 6, A_FaceTarget, S_SRCR1_ATK7, 0, 0}, // S_SRCR1_ATK6 + {SPR_SRCR, 18, 10, A_Srcr1Attack, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_ATK7 + {SPR_SRCR, 4, 7, NULL, S_SRCR1_DIE2, 0, 0}, // S_SRCR1_DIE1 + {SPR_SRCR, 5, 7, A_Scream, S_SRCR1_DIE3, 0, 0}, // S_SRCR1_DIE2 + {SPR_SRCR, 6, 7, NULL, S_SRCR1_DIE4, 0, 0}, // S_SRCR1_DIE3 + {SPR_SRCR, 7, 6, NULL, S_SRCR1_DIE5, 0, 0}, // S_SRCR1_DIE4 + {SPR_SRCR, 8, 6, NULL, S_SRCR1_DIE6, 0, 0}, // S_SRCR1_DIE5 + {SPR_SRCR, 9, 6, NULL, S_SRCR1_DIE7, 0, 0}, // S_SRCR1_DIE6 + {SPR_SRCR, 10, 6, NULL, S_SRCR1_DIE8, 0, 0}, // S_SRCR1_DIE7 + {SPR_SRCR, 11, 25, A_SorZap, S_SRCR1_DIE9, 0, 0}, // S_SRCR1_DIE8 + {SPR_SRCR, 12, 5, NULL, S_SRCR1_DIE10, 0, 0}, // S_SRCR1_DIE9 + {SPR_SRCR, 13, 5, NULL, S_SRCR1_DIE11, 0, 0}, // S_SRCR1_DIE10 + {SPR_SRCR, 14, 4, NULL, S_SRCR1_DIE12, 0, 0}, // S_SRCR1_DIE11 + {SPR_SRCR, 11, 20, A_SorZap, S_SRCR1_DIE13, 0, 0}, // S_SRCR1_DIE12 + {SPR_SRCR, 12, 5, NULL, S_SRCR1_DIE14, 0, 0}, // S_SRCR1_DIE13 + {SPR_SRCR, 13, 5, NULL, S_SRCR1_DIE15, 0, 0}, // S_SRCR1_DIE14 + {SPR_SRCR, 14, 4, NULL, S_SRCR1_DIE16, 0, 0}, // S_SRCR1_DIE15 + {SPR_SRCR, 11, 12, NULL, S_SRCR1_DIE17, 0, 0}, // S_SRCR1_DIE16 + {SPR_SRCR, 15, -1, A_SorcererRise, S_NULL, 0, 0}, // S_SRCR1_DIE17 + {SPR_FX14, 32768, 6, NULL, S_SRCRFX1_2, 0, 0}, // S_SRCRFX1_1 + {SPR_FX14, 32769, 6, NULL, S_SRCRFX1_3, 0, 0}, // S_SRCRFX1_2 + {SPR_FX14, 32770, 6, NULL, S_SRCRFX1_1, 0, 0}, // S_SRCRFX1_3 + {SPR_FX14, 32771, 5, NULL, S_SRCRFXI1_2, 0, 0}, // S_SRCRFXI1_1 + {SPR_FX14, 32772, 5, NULL, S_SRCRFXI1_3, 0, 0}, // S_SRCRFXI1_2 + {SPR_FX14, 32773, 5, NULL, S_SRCRFXI1_4, 0, 0}, // S_SRCRFXI1_3 + {SPR_FX14, 32774, 5, NULL, S_SRCRFXI1_5, 0, 0}, // S_SRCRFXI1_4 + {SPR_FX14, 32775, 5, NULL, S_NULL, 0, 0}, // S_SRCRFXI1_5 + {SPR_SOR2, 0, 4, NULL, S_SOR2_RISE2, 0, 0}, // S_SOR2_RISE1 + {SPR_SOR2, 1, 4, NULL, S_SOR2_RISE3, 0, 0}, // S_SOR2_RISE2 + {SPR_SOR2, 2, 4, A_SorRise, S_SOR2_RISE4, 0, 0}, // S_SOR2_RISE3 + {SPR_SOR2, 3, 4, NULL, S_SOR2_RISE5, 0, 0}, // S_SOR2_RISE4 + {SPR_SOR2, 4, 4, NULL, S_SOR2_RISE6, 0, 0}, // S_SOR2_RISE5 + {SPR_SOR2, 5, 4, NULL, S_SOR2_RISE7, 0, 0}, // S_SOR2_RISE6 + {SPR_SOR2, 6, 12, A_SorSightSnd, S_SOR2_WALK1, 0, 0}, // S_SOR2_RISE7 + {SPR_SOR2, 12, 10, A_Look, S_SOR2_LOOK2, 0, 0}, // S_SOR2_LOOK1 + {SPR_SOR2, 13, 10, A_Look, S_SOR2_LOOK1, 0, 0}, // S_SOR2_LOOK2 + {SPR_SOR2, 12, 4, A_Chase, S_SOR2_WALK2, 0, 0}, // S_SOR2_WALK1 + {SPR_SOR2, 13, 4, A_Chase, S_SOR2_WALK3, 0, 0}, // S_SOR2_WALK2 + {SPR_SOR2, 14, 4, A_Chase, S_SOR2_WALK4, 0, 0}, // S_SOR2_WALK3 + {SPR_SOR2, 15, 4, A_Chase, S_SOR2_WALK1, 0, 0}, // S_SOR2_WALK4 + {SPR_SOR2, 16, 3, NULL, S_SOR2_PAIN2, 0, 0}, // S_SOR2_PAIN1 + {SPR_SOR2, 16, 6, A_Pain, S_SOR2_WALK1, 0, 0}, // S_SOR2_PAIN2 + {SPR_SOR2, 17, 9, A_Srcr2Decide, S_SOR2_ATK2, 0, 0}, // S_SOR2_ATK1 + {SPR_SOR2, 18, 9, A_FaceTarget, S_SOR2_ATK3, 0, 0}, // S_SOR2_ATK2 + {SPR_SOR2, 19, 20, A_Srcr2Attack, S_SOR2_WALK1, 0, 0}, // S_SOR2_ATK3 + {SPR_SOR2, 11, 6, NULL, S_SOR2_TELE2, 0, 0}, // S_SOR2_TELE1 + {SPR_SOR2, 10, 6, NULL, S_SOR2_TELE3, 0, 0}, // S_SOR2_TELE2 + {SPR_SOR2, 9, 6, NULL, S_SOR2_TELE4, 0, 0}, // S_SOR2_TELE3 + {SPR_SOR2, 8, 6, NULL, S_SOR2_TELE5, 0, 0}, // S_SOR2_TELE4 + {SPR_SOR2, 7, 6, NULL, S_SOR2_TELE6, 0, 0}, // S_SOR2_TELE5 + {SPR_SOR2, 6, 6, NULL, S_SOR2_WALK1, 0, 0}, // S_SOR2_TELE6 + {SPR_SDTH, 0, 8, A_Sor2DthInit, S_SOR2_DIE2, 0, 0}, // S_SOR2_DIE1 + {SPR_SDTH, 1, 8, NULL, S_SOR2_DIE3, 0, 0}, // S_SOR2_DIE2 + {SPR_SDTH, 2, 8, A_SorDSph, S_SOR2_DIE4, 0, 0}, // S_SOR2_DIE3 + {SPR_SDTH, 3, 7, NULL, S_SOR2_DIE5, 0, 0}, // S_SOR2_DIE4 + {SPR_SDTH, 4, 7, NULL, S_SOR2_DIE6, 0, 0}, // S_SOR2_DIE5 + {SPR_SDTH, 5, 7, A_Sor2DthLoop, S_SOR2_DIE7, 0, 0}, // S_SOR2_DIE6 + {SPR_SDTH, 6, 6, A_SorDExp, S_SOR2_DIE8, 0, 0}, // S_SOR2_DIE7 + {SPR_SDTH, 7, 6, NULL, S_SOR2_DIE9, 0, 0}, // S_SOR2_DIE8 + {SPR_SDTH, 8, 18, NULL, S_SOR2_DIE10, 0, 0}, // S_SOR2_DIE9 + {SPR_SDTH, 9, 6, A_NoBlocking, S_SOR2_DIE11, 0, 0}, // S_SOR2_DIE10 + {SPR_SDTH, 10, 6, A_SorDBon, S_SOR2_DIE12, 0, 0}, // S_SOR2_DIE11 + {SPR_SDTH, 11, 6, NULL, S_SOR2_DIE13, 0, 0}, // S_SOR2_DIE12 + {SPR_SDTH, 12, 6, NULL, S_SOR2_DIE14, 0, 0}, // S_SOR2_DIE13 + {SPR_SDTH, 13, 6, NULL, S_SOR2_DIE15, 0, 0}, // S_SOR2_DIE14 + {SPR_SDTH, 14, -1, A_BossDeath, S_NULL, 0, 0}, // S_SOR2_DIE15 + {SPR_FX16, 32768, 3, A_BlueSpark, S_SOR2FX1_2, 0, 0}, // S_SOR2FX1_1 + {SPR_FX16, 32769, 3, A_BlueSpark, S_SOR2FX1_3, 0, 0}, // S_SOR2FX1_2 + {SPR_FX16, 32770, 3, A_BlueSpark, S_SOR2FX1_1, 0, 0}, // S_SOR2FX1_3 + {SPR_FX16, 32774, 5, A_Explode, S_SOR2FXI1_2, 0, 0}, // S_SOR2FXI1_1 + {SPR_FX16, 32775, 5, NULL, S_SOR2FXI1_3, 0, 0}, // S_SOR2FXI1_2 + {SPR_FX16, 32776, 5, NULL, S_SOR2FXI1_4, 0, 0}, // S_SOR2FXI1_3 + {SPR_FX16, 32777, 5, NULL, S_SOR2FXI1_5, 0, 0}, // S_SOR2FXI1_4 + {SPR_FX16, 32778, 5, NULL, S_SOR2FXI1_6, 0, 0}, // S_SOR2FXI1_5 + {SPR_FX16, 32779, 5, NULL, S_NULL, 0, 0}, // S_SOR2FXI1_6 + {SPR_FX16, 32771, 12, NULL, S_SOR2FXSPARK2, 0, 0}, // S_SOR2FXSPARK1 + {SPR_FX16, 32772, 12, NULL, S_SOR2FXSPARK3, 0, 0}, // S_SOR2FXSPARK2 + {SPR_FX16, 32773, 12, NULL, S_NULL, 0, 0}, // S_SOR2FXSPARK3 + {SPR_FX11, 32768, 35, NULL, S_SOR2FX2_2, 0, 0}, // S_SOR2FX2_1 + {SPR_FX11, 32768, 5, A_GenWizard, S_SOR2FX2_3, 0, 0}, // S_SOR2FX2_2 + {SPR_FX11, 32769, 5, NULL, S_SOR2FX2_2, 0, 0}, // S_SOR2FX2_3 + {SPR_FX11, 32770, 5, NULL, S_SOR2FXI2_2, 0, 0}, // S_SOR2FXI2_1 + {SPR_FX11, 32771, 5, NULL, S_SOR2FXI2_3, 0, 0}, // S_SOR2FXI2_2 + {SPR_FX11, 32772, 5, NULL, S_SOR2FXI2_4, 0, 0}, // S_SOR2FXI2_3 + {SPR_FX11, 32773, 5, NULL, S_SOR2FXI2_5, 0, 0}, // S_SOR2FXI2_4 + {SPR_FX11, 32774, 5, NULL, S_NULL, 0, 0}, // S_SOR2FXI2_5 + {SPR_SOR2, 6, 8, NULL, S_SOR2TELEFADE2, 0, 0}, // S_SOR2TELEFADE1 + {SPR_SOR2, 7, 6, NULL, S_SOR2TELEFADE3, 0, 0}, // S_SOR2TELEFADE2 + {SPR_SOR2, 8, 6, NULL, S_SOR2TELEFADE4, 0, 0}, // S_SOR2TELEFADE3 + {SPR_SOR2, 9, 6, NULL, S_SOR2TELEFADE5, 0, 0}, // S_SOR2TELEFADE4 + {SPR_SOR2, 10, 6, NULL, S_SOR2TELEFADE6, 0, 0}, // S_SOR2TELEFADE5 + {SPR_SOR2, 11, 6, NULL, S_NULL, 0, 0}, // S_SOR2TELEFADE6 + {SPR_MNTR, 0, 10, A_Look, S_MNTR_LOOK2, 0, 0}, // S_MNTR_LOOK1 + {SPR_MNTR, 1, 10, A_Look, S_MNTR_LOOK1, 0, 0}, // S_MNTR_LOOK2 + {SPR_MNTR, 0, 5, A_Chase, S_MNTR_WALK2, 0, 0}, // S_MNTR_WALK1 + {SPR_MNTR, 1, 5, A_Chase, S_MNTR_WALK3, 0, 0}, // S_MNTR_WALK2 + {SPR_MNTR, 2, 5, A_Chase, S_MNTR_WALK4, 0, 0}, // S_MNTR_WALK3 + {SPR_MNTR, 3, 5, A_Chase, S_MNTR_WALK1, 0, 0}, // S_MNTR_WALK4 + {SPR_MNTR, 21, 10, A_FaceTarget, S_MNTR_ATK1_2, 0, 0}, // S_MNTR_ATK1_1 + {SPR_MNTR, 22, 7, A_FaceTarget, S_MNTR_ATK1_3, 0, 0}, // S_MNTR_ATK1_2 + {SPR_MNTR, 23, 12, A_MinotaurAtk1, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK1_3 + {SPR_MNTR, 21, 10, A_MinotaurDecide, S_MNTR_ATK2_2, 0, 0}, // S_MNTR_ATK2_1 + {SPR_MNTR, 24, 4, A_FaceTarget, S_MNTR_ATK2_3, 0, 0}, // S_MNTR_ATK2_2 + {SPR_MNTR, 25, 9, A_MinotaurAtk2, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK2_3 + {SPR_MNTR, 21, 10, A_FaceTarget, S_MNTR_ATK3_2, 0, 0}, // S_MNTR_ATK3_1 + {SPR_MNTR, 22, 7, A_FaceTarget, S_MNTR_ATK3_3, 0, 0}, // S_MNTR_ATK3_2 + {SPR_MNTR, 23, 12, A_MinotaurAtk3, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK3_3 + {SPR_MNTR, 23, 12, NULL, S_MNTR_ATK3_1, 0, 0}, // S_MNTR_ATK3_4 + {SPR_MNTR, 20, 2, A_MinotaurCharge, S_MNTR_ATK4_1, 0, 0}, // S_MNTR_ATK4_1 + {SPR_MNTR, 4, 3, NULL, S_MNTR_PAIN2, 0, 0}, // S_MNTR_PAIN1 + {SPR_MNTR, 4, 6, A_Pain, S_MNTR_WALK1, 0, 0}, // S_MNTR_PAIN2 + {SPR_MNTR, 5, 6, NULL, S_MNTR_DIE2, 0, 0}, // S_MNTR_DIE1 + {SPR_MNTR, 6, 5, NULL, S_MNTR_DIE3, 0, 0}, // S_MNTR_DIE2 + {SPR_MNTR, 7, 6, A_Scream, S_MNTR_DIE4, 0, 0}, // S_MNTR_DIE3 + {SPR_MNTR, 8, 5, NULL, S_MNTR_DIE5, 0, 0}, // S_MNTR_DIE4 + {SPR_MNTR, 9, 6, NULL, S_MNTR_DIE6, 0, 0}, // S_MNTR_DIE5 + {SPR_MNTR, 10, 5, NULL, S_MNTR_DIE7, 0, 0}, // S_MNTR_DIE6 + {SPR_MNTR, 11, 6, NULL, S_MNTR_DIE8, 0, 0}, // S_MNTR_DIE7 + {SPR_MNTR, 12, 5, A_NoBlocking, S_MNTR_DIE9, 0, 0}, // S_MNTR_DIE8 + {SPR_MNTR, 13, 6, NULL, S_MNTR_DIE10, 0, 0}, // S_MNTR_DIE9 + {SPR_MNTR, 14, 5, NULL, S_MNTR_DIE11, 0, 0}, // S_MNTR_DIE10 + {SPR_MNTR, 15, 6, NULL, S_MNTR_DIE12, 0, 0}, // S_MNTR_DIE11 + {SPR_MNTR, 16, 5, NULL, S_MNTR_DIE13, 0, 0}, // S_MNTR_DIE12 + {SPR_MNTR, 17, 6, NULL, S_MNTR_DIE14, 0, 0}, // S_MNTR_DIE13 + {SPR_MNTR, 18, 5, NULL, S_MNTR_DIE15, 0, 0}, // S_MNTR_DIE14 + {SPR_MNTR, 19, -1, A_BossDeath, S_NULL, 0, 0}, // S_MNTR_DIE15 + {SPR_FX12, 32768, 6, NULL, S_MNTRFX1_2, 0, 0}, // S_MNTRFX1_1 + {SPR_FX12, 32769, 6, NULL, S_MNTRFX1_1, 0, 0}, // S_MNTRFX1_2 + {SPR_FX12, 32770, 5, NULL, S_MNTRFXI1_2, 0, 0}, // S_MNTRFXI1_1 + {SPR_FX12, 32771, 5, NULL, S_MNTRFXI1_3, 0, 0}, // S_MNTRFXI1_2 + {SPR_FX12, 32772, 5, NULL, S_MNTRFXI1_4, 0, 0}, // S_MNTRFXI1_3 + {SPR_FX12, 32773, 5, NULL, S_MNTRFXI1_5, 0, 0}, // S_MNTRFXI1_4 + {SPR_FX12, 32774, 5, NULL, S_MNTRFXI1_6, 0, 0}, // S_MNTRFXI1_5 + {SPR_FX12, 32775, 5, NULL, S_NULL, 0, 0}, // S_MNTRFXI1_6 + {SPR_FX13, 0, 2, A_MntrFloorFire, S_MNTRFX2_1, 0, 0}, // S_MNTRFX2_1 + {SPR_FX13, 32776, 4, A_Explode, S_MNTRFXI2_2, 0, 0}, // S_MNTRFXI2_1 + {SPR_FX13, 32777, 4, NULL, S_MNTRFXI2_3, 0, 0}, // S_MNTRFXI2_2 + {SPR_FX13, 32778, 4, NULL, S_MNTRFXI2_4, 0, 0}, // S_MNTRFXI2_3 + {SPR_FX13, 32779, 4, NULL, S_MNTRFXI2_5, 0, 0}, // S_MNTRFXI2_4 + {SPR_FX13, 32780, 4, NULL, S_NULL, 0, 0}, // S_MNTRFXI2_5 + {SPR_FX13, 32771, 4, NULL, S_MNTRFX3_2, 0, 0}, // S_MNTRFX3_1 + {SPR_FX13, 32770, 4, NULL, S_MNTRFX3_3, 0, 0}, // S_MNTRFX3_2 + {SPR_FX13, 32769, 5, NULL, S_MNTRFX3_4, 0, 0}, // S_MNTRFX3_3 + {SPR_FX13, 32770, 5, NULL, S_MNTRFX3_5, 0, 0}, // S_MNTRFX3_4 + {SPR_FX13, 32771, 5, NULL, S_MNTRFX3_6, 0, 0}, // S_MNTRFX3_5 + {SPR_FX13, 32772, 5, NULL, S_MNTRFX3_7, 0, 0}, // S_MNTRFX3_6 + {SPR_FX13, 32773, 4, NULL, S_MNTRFX3_8, 0, 0}, // S_MNTRFX3_7 + {SPR_FX13, 32774, 4, NULL, S_MNTRFX3_9, 0, 0}, // S_MNTRFX3_8 + {SPR_FX13, 32775, 4, NULL, S_NULL, 0, 0}, // S_MNTRFX3_9 + {SPR_AKYY, 32768, 3, NULL, S_AKYY2, 0, 0}, // S_AKYY1 + {SPR_AKYY, 32769, 3, NULL, S_AKYY3, 0, 0}, // S_AKYY2 + {SPR_AKYY, 32770, 3, NULL, S_AKYY4, 0, 0}, // S_AKYY3 + {SPR_AKYY, 32771, 3, NULL, S_AKYY5, 0, 0}, // S_AKYY4 + {SPR_AKYY, 32772, 3, NULL, S_AKYY6, 0, 0}, // S_AKYY5 + {SPR_AKYY, 32773, 3, NULL, S_AKYY7, 0, 0}, // S_AKYY6 + {SPR_AKYY, 32774, 3, NULL, S_AKYY8, 0, 0}, // S_AKYY7 + {SPR_AKYY, 32775, 3, NULL, S_AKYY9, 0, 0}, // S_AKYY8 + {SPR_AKYY, 32776, 3, NULL, S_AKYY10, 0, 0}, // S_AKYY9 + {SPR_AKYY, 32777, 3, NULL, S_AKYY1, 0, 0}, // S_AKYY10 + {SPR_BKYY, 32768, 3, NULL, S_BKYY2, 0, 0}, // S_BKYY1 + {SPR_BKYY, 32769, 3, NULL, S_BKYY3, 0, 0}, // S_BKYY2 + {SPR_BKYY, 32770, 3, NULL, S_BKYY4, 0, 0}, // S_BKYY3 + {SPR_BKYY, 32771, 3, NULL, S_BKYY5, 0, 0}, // S_BKYY4 + {SPR_BKYY, 32772, 3, NULL, S_BKYY6, 0, 0}, // S_BKYY5 + {SPR_BKYY, 32773, 3, NULL, S_BKYY7, 0, 0}, // S_BKYY6 + {SPR_BKYY, 32774, 3, NULL, S_BKYY8, 0, 0}, // S_BKYY7 + {SPR_BKYY, 32775, 3, NULL, S_BKYY9, 0, 0}, // S_BKYY8 + {SPR_BKYY, 32776, 3, NULL, S_BKYY10, 0, 0}, // S_BKYY9 + {SPR_BKYY, 32777, 3, NULL, S_BKYY1, 0, 0}, // S_BKYY10 + {SPR_CKYY, 32768, 3, NULL, S_CKYY2, 0, 0}, // S_CKYY1 + {SPR_CKYY, 32769, 3, NULL, S_CKYY3, 0, 0}, // S_CKYY2 + {SPR_CKYY, 32770, 3, NULL, S_CKYY4, 0, 0}, // S_CKYY3 + {SPR_CKYY, 32771, 3, NULL, S_CKYY5, 0, 0}, // S_CKYY4 + {SPR_CKYY, 32772, 3, NULL, S_CKYY6, 0, 0}, // S_CKYY5 + {SPR_CKYY, 32773, 3, NULL, S_CKYY7, 0, 0}, // S_CKYY6 + {SPR_CKYY, 32774, 3, NULL, S_CKYY8, 0, 0}, // S_CKYY7 + {SPR_CKYY, 32775, 3, NULL, S_CKYY9, 0, 0}, // S_CKYY8 + {SPR_CKYY, 32776, 3, NULL, S_CKYY1, 0, 0}, // S_CKYY9 + {SPR_AMG1, 0, -1, NULL, S_NULL, 0, 0}, // S_AMG1 + {SPR_AMG2, 0, 4, NULL, S_AMG2_2, 0, 0}, // S_AMG2_1 + {SPR_AMG2, 1, 4, NULL, S_AMG2_3, 0, 0}, // S_AMG2_2 + {SPR_AMG2, 2, 4, NULL, S_AMG2_1, 0, 0}, // S_AMG2_3 + {SPR_AMM1, 0, -1, NULL, S_NULL, 0, 0}, // S_AMM1 + {SPR_AMM2, 0, -1, NULL, S_NULL, 0, 0}, // S_AMM2 + {SPR_AMC1, 0, -1, NULL, S_NULL, 0, 0}, // S_AMC1 + {SPR_AMC2, 0, 5, NULL, S_AMC2_2, 0, 0}, // S_AMC2_1 + {SPR_AMC2, 1, 5, NULL, S_AMC2_3, 0, 0}, // S_AMC2_2 + {SPR_AMC2, 2, 5, NULL, S_AMC2_1, 0, 0}, // S_AMC2_3 + {SPR_AMS1, 0, 5, NULL, S_AMS1_2, 0, 0}, // S_AMS1_1 + {SPR_AMS1, 1, 5, NULL, S_AMS1_1, 0, 0}, // S_AMS1_2 + {SPR_AMS2, 0, 5, NULL, S_AMS2_2, 0, 0}, // S_AMS2_1 + {SPR_AMS2, 1, 5, NULL, S_AMS2_1, 0, 0}, // S_AMS2_2 + {SPR_AMP1, 0, 4, NULL, S_AMP1_2, 0, 0}, // S_AMP1_1 + {SPR_AMP1, 1, 4, NULL, S_AMP1_3, 0, 0}, // S_AMP1_2 + {SPR_AMP1, 2, 4, NULL, S_AMP1_1, 0, 0}, // S_AMP1_3 + {SPR_AMP2, 0, 4, NULL, S_AMP2_2, 0, 0}, // S_AMP2_1 + {SPR_AMP2, 1, 4, NULL, S_AMP2_3, 0, 0}, // S_AMP2_2 + {SPR_AMP2, 2, 4, NULL, S_AMP2_1, 0, 0}, // S_AMP2_3 + {SPR_AMB1, 0, 4, NULL, S_AMB1_2, 0, 0}, // S_AMB1_1 + {SPR_AMB1, 1, 4, NULL, S_AMB1_3, 0, 0}, // S_AMB1_2 + {SPR_AMB1, 2, 4, NULL, S_AMB1_1, 0, 0}, // S_AMB1_3 + {SPR_AMB2, 0, 4, NULL, S_AMB2_2, 0, 0}, // S_AMB2_1 + {SPR_AMB2, 1, 4, NULL, S_AMB2_3, 0, 0}, // S_AMB2_2 + {SPR_AMB2, 2, 4, NULL, S_AMB2_1, 0, 0}, // S_AMB2_3 + {SPR_AMG1, 0, 100, A_ESound, S_SND_WIND, 0, 0}, // S_SND_WIND + {SPR_AMG1, 0, 85, A_ESound, S_SND_WATERFALL, 0, 0} // S_SND_WATERFALL +}; + + +mobjinfo_t mobjinfo[NUMMOBJTYPES] = { + + { // MT_MISC0 + 81, // doomednum + S_ITEM_PTN1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ITEMSHIELD1 + 85, // doomednum + S_ITEM_SHLD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ITEMSHIELD2 + 31, // doomednum + S_ITEM_SHD2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MISC1 + 8, // doomednum + S_ITEM_BAGH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MISC2 + 35, // doomednum + S_ITEM_SPMP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIINVISIBILITY + 75, // doomednum + S_ARTI_INVS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_SHADOW | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MISC3 + 82, // doomednum + S_ARTI_PTN2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIFLY + 83, // doomednum + S_ARTI_SOAR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIINVULNERABILITY + 84, // doomednum + S_ARTI_INVU1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTITOMEOFPOWER + 86, // doomednum + S_ARTI_PWBK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIEGG + 30, // doomednum + S_ARTI_EGGC1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_EGGFX + -1, // doomednum + S_EGGFX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_EGGFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 18 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ARTISUPERHEAL + 32, // doomednum + S_ARTI_SPHL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MISC4 + 33, // doomednum + S_ARTI_TRCH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MISC5 + 34, // doomednum + S_ARTI_FBMB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_FIREBOMB + -1, // doomednum + S_FIREBOMB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_phohit, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_ARTITELEPORT + 36, // doomednum + S_ARTI_ATLP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_COUNTITEM, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_POD + 2035, // doomednum + S_POD_WAIT1, // spawnstate + 45, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_POD_PAIN1, // painstate + 255, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_POD_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_podexp, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 54 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_NOBLOOD | MF_SHOOTABLE | MF_DROPOFF, // flags + MF2_WINDTHRUST | MF2_PUSHABLE | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP // flags2 + }, + + { // MT_PODGOO + -1, // doomednum + S_PODGOO1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_PODGOOX, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_PODGENERATOR + 43, // doomednum + S_PODGENERATOR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_SPLASH + -1, // doomednum + S_SPLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SPLASHX, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_SPLASHBASE + -1, // doomednum + S_SPLASHBASE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_LAVASPLASH + -1, // doomednum + S_LAVASPLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_LAVASMOKE + -1, // doomednum + S_LAVASMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_SLUDGECHUNK + -1, // doomednum + S_SLUDGECHUNK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SLUDGECHUNKX, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_SLUDGESPLASH + -1, // doomednum + S_SLUDGESPLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_SKULLHANG70 + 17, // doomednum + S_SKULLHANG70_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 70 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_SKULLHANG60 + 24, // doomednum + S_SKULLHANG60_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 60 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_SKULLHANG45 + 25, // doomednum + S_SKULLHANG45_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 45 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_SKULLHANG35 + 26, // doomednum + S_SKULLHANG35_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 35 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_CHANDELIER + 28, // doomednum + S_CHANDELIER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 60 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_SERPTORCH + 27, // doomednum + S_SERPTORCH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 54 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_SMALLPILLAR + 29, // doomednum + S_SMALLPILLAR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 34 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_STALAGMITESMALL + 37, // doomednum + S_STALAGMITESMALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_STALAGMITELARGE + 38, // doomednum + S_STALAGMITELARGE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_STALACTITESMALL + 39, // doomednum + S_STALACTITESMALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 36 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_STALACTITELARGE + 40, // doomednum + S_STALACTITELARGE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 68 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC6 + 76, // doomednum + S_FIREBRAZIER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 44 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_BARREL + 44, // doomednum + S_BARREL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC7 + 47, // doomednum + S_BRPILLAR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 128 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC8 + 48, // doomednum + S_MOSS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 23 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC9 + 49, // doomednum + S_MOSS2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 27 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC10 + 50, // doomednum + S_WALLTORCH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC11 + 51, // doomednum + S_HANGINGCORPSE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 104 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_KEYGIZMOBLUE + 94, // doomednum + S_KEYGIZMO1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_KEYGIZMOGREEN + 95, // doomednum + S_KEYGIZMO1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_KEYGIZMOYELLOW + 96, // doomednum + S_KEYGIZMO1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_KEYGIZMOFLOAT + -1, // doomednum + S_KGZ_START, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC12 + 87, // doomednum + S_VOLCANO1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_VOLCANOBLAST + -1, // doomednum + S_VOLCANOBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_VOLCANOBALLX1, // deathstate + S_NULL, // xdeathstate + sfx_volhit, // deathsound + 2 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_VOLCANOTBLAST + -1, // doomednum + S_VOLCANOTBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_VOLCANOTBALLX1, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 2 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_TELEGLITGEN + 74, // doomednum + S_TELEGLITGEN1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_TELEGLITGEN2 + 52, // doomednum + S_TELEGLITGEN2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_TELEGLITTER + -1, // doomednum + S_TELEGLITTER1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + 0 // flags2 + }, + + { // MT_TELEGLITTER2 + -1, // doomednum + S_TELEGLITTER2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + 0 // flags2 + }, + + { // MT_TFOG + -1, // doomednum + S_TFOG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_TELEPORTMAN + 14, // doomednum + S_NULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_STAFFPUFF + -1, // doomednum + S_STAFFPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_stfhit, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_STAFFPUFF2 + -1, // doomednum + S_STAFFPUFF2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_stfpow, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_BEAKPUFF + -1, // doomednum + S_STAFFPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_chicatk, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC13 + 2005, // doomednum + S_WGNT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_GAUNTLETPUFF1 + -1, // doomednum + S_GAUNTLETPUFF1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_GAUNTLETPUFF2 + -1, // doomednum + S_GAUNTLETPUFF2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_MISC14 + 53, // doomednum + S_BLSR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_BLASTERFX1 + -1, // doomednum + S_BLASTERFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BLASTERFXI1_1, // deathstate + S_NULL, // xdeathstate + sfx_blshit, // deathsound + 184 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_BLASTERSMOKE + -1, // doomednum + S_BLASTERSMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 + }, + + { // MT_RIPPER + -1, // doomednum + S_RIPPER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_RIPPERX1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 14 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_RIP // flags2 + }, + + { // MT_BLASTERPUFF1 + -1, // doomednum + S_BLASTERPUFF1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_BLASTERPUFF2 + -1, // doomednum + S_BLASTERPUFF2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_WMACE + 2002, // doomednum + S_WMCE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_MACEFX1 + -1, // doomednum + S_MACEFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_lobsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MACEFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 20 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 + }, + + { // MT_MACEFX2 + -1, // doomednum + S_MACEFX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MACEFXI2_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 6, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 + }, + + { // MT_MACEFX3 + -1, // doomednum + S_MACEFX3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MACEFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 7 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 4, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 + }, + + { // MT_MACEFX4 + -1, // doomednum + S_MACEFX4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MACEFXI4_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 7 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 18, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_TELESTOMP // flags2 + }, + + { // MT_WSKULLROD + 2004, // doomednum + S_WSKL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_HORNRODFX1 + -1, // doomednum + S_HRODFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_hrnsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HRODFXI1_1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 22 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 + }, + + { // MT_HORNRODFX2 + -1, // doomednum + S_HRODFX2_1, // spawnstate + 4 * 35, // spawnhealth + S_NULL, // seestate + sfx_hrnsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HRODFXI2_1, // deathstate + S_NULL, // xdeathstate + sfx_ramphit, // deathsound + 22 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 10, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_RAINPLR1 + -1, // doomednum + S_RAINPLR1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_RAINPLR1X_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 12 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_RAINPLR2 + -1, // doomednum + S_RAINPLR2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_RAINPLR2X_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 12 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_RAINPLR3 + -1, // doomednum + S_RAINPLR3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_RAINPLR3X_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 12 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_RAINPLR4 + -1, // doomednum + S_RAINPLR4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_RAINPLR4X_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 12 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_GOLDWANDFX1 + -1, // doomednum + S_GWANDFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_GWANDFXI1_1, // deathstate + S_NULL, // xdeathstate + sfx_gldhit, // deathsound + 22 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_GOLDWANDFX2 + -1, // doomednum + S_GWANDFX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_GWANDFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 18 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_GOLDWANDPUFF1 + -1, // doomednum + S_GWANDPUFF1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_GOLDWANDPUFF2 + -1, // doomednum + S_GWANDFXI1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_WPHOENIXROD + 2003, // doomednum + S_WPHX, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_PHOENIXFX1 + -1, // doomednum + S_PHOENIXFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_phosht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_PHOENIXFXI1_1, // deathstate + S_NULL, // xdeathstate + sfx_phohit, // deathsound + 20 * FRACUNIT, // speed + 11 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 20, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_THRUGHOST | MF2_NOTELEPORT // flags2 + }, + + // The following thing is present in the mobjinfo table from Heretic 1.0, + // but not in Heretic 1.3 (ie. it was removed). It has been re-inserted + // here to support HHE patches. + + { // MT_PHOENIXFX_REMOVED + -1, // doomednum + S_PHOENIXFXIX_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_PHOENIXFXIX_3, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_PHOENIXPUFF + -1, // doomednum + S_PHOENIXPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 + }, + + { // MT_PHOENIXFX2 + -1, // doomednum + S_PHOENIXFX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_PHOENIXFXI2_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 6 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_MISC15 + 2001, // doomednum + S_WBOW, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_CRBOWFX1 + -1, // doomednum + S_CRBOWFX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_bowsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CRBOWFXI1_1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 30 * FRACUNIT, // speed + 11 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 10, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_CRBOWFX2 + -1, // doomednum + S_CRBOWFX2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_bowsht, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CRBOWFXI1_1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 32 * FRACUNIT, // speed + 11 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 6, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_CRBOWFX3 + -1, // doomednum + S_CRBOWFX3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CRBOWFXI3_1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 20 * FRACUNIT, // speed + 11 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 + }, + + { // MT_CRBOWFX4 + -1, // doomednum + S_CRBOWFX4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + MF2_LOGRAV // flags2 + }, + + { // MT_BLOOD + -1, // doomednum + S_BLOOD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_BLOODSPLATTER + -1, // doomednum + S_BLOODSPLATTER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BLOODSPLATTERX, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 + }, + + { // MT_PLAYER + -1, // doomednum + S_PLAY, // spawnstate + 100, // spawnhealth + S_PLAY_RUN1, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_PLAY_PAIN, // painstate + 255, // painchance + sfx_plrpai, // painsound + S_NULL, // meleestate + S_PLAY_ATK1, // missilestate + S_NULL, // crashstate + S_PLAY_DIE1, // deathstate + S_PLAY_XDIE1, // xdeathstate + sfx_plrdth, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 56 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags + MF2_WINDTHRUST | MF2_FOOTCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP // flags2 + }, + + { // MT_BLOODYSKULL + -1, // doomednum + S_BLOODYSKULL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_CHICPLAYER + -1, // doomednum + S_CHICPLAY, // spawnstate + 100, // spawnhealth + S_CHICPLAY_RUN1, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_CHICPLAY_PAIN, // painstate + 255, // painchance + sfx_chicpai, // painsound + S_NULL, // meleestate + S_CHICPLAY_ATK1, // missilestate + S_NULL, // crashstate + S_CHICKEN_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_chicdth, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 24 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_NOTDMATCH, // flags + MF2_WINDTHRUST | MF2_SLIDE | MF2_PASSMOBJ | MF2_FOOTCLIP | MF2_LOGRAV | MF2_TELESTOMP // flags2 + }, + + { // MT_CHICKEN + -1, // doomednum + S_CHICKEN_LOOK1, // spawnstate + 10, // spawnhealth + S_CHICKEN_WALK1, // seestate + sfx_chicpai, // seesound + 8, // reactiontime + sfx_chicatk, // attacksound + S_CHICKEN_PAIN1, // painstate + 200, // painchance + sfx_chicpai, // painsound + S_CHICKEN_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_CHICKEN_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_chicdth, // deathsound + 4, // speed + 9 * FRACUNIT, // radius + 22 * FRACUNIT, // height + 40, // mass + 0, // damage + sfx_chicact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF, // flags + MF2_WINDTHRUST | MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_FEATHER + -1, // doomednum + S_FEATHER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FEATHERX, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH | MF2_WINDTHRUST // flags2 + }, + + { // MT_MUMMY + 68, // doomednum + S_MUMMY_LOOK1, // spawnstate + 80, // spawnhealth + S_MUMMY_WALK1, // seestate + sfx_mumsit, // seesound + 8, // reactiontime + sfx_mumat1, // attacksound + S_MUMMY_PAIN1, // painstate + 128, // painchance + sfx_mumpai, // painsound + S_MUMMY_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_MUMMY_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_mumdth, // deathsound + 12, // speed + 22 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 75, // mass + 0, // damage + sfx_mumact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_MUMMYLEADER + 45, // doomednum + S_MUMMY_LOOK1, // spawnstate + 100, // spawnhealth + S_MUMMY_WALK1, // seestate + sfx_mumsit, // seesound + 8, // reactiontime + sfx_mumat1, // attacksound + S_MUMMY_PAIN1, // painstate + 64, // painchance + sfx_mumpai, // painsound + S_MUMMY_ATK1, // meleestate + S_MUMMYL_ATK1, // missilestate + S_NULL, // crashstate + S_MUMMY_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_mumdth, // deathsound + 12, // speed + 22 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 75, // mass + 0, // damage + sfx_mumact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_MUMMYGHOST + 69, // doomednum + S_MUMMY_LOOK1, // spawnstate + 80, // spawnhealth + S_MUMMY_WALK1, // seestate + sfx_mumsit, // seesound + 8, // reactiontime + sfx_mumat1, // attacksound + S_MUMMY_PAIN1, // painstate + 128, // painchance + sfx_mumpai, // painsound + S_MUMMY_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_MUMMY_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_mumdth, // deathsound + 12, // speed + 22 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 75, // mass + 0, // damage + sfx_mumact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_MUMMYLEADERGHOST + 46, // doomednum + S_MUMMY_LOOK1, // spawnstate + 100, // spawnhealth + S_MUMMY_WALK1, // seestate + sfx_mumsit, // seesound + 8, // reactiontime + sfx_mumat1, // attacksound + S_MUMMY_PAIN1, // painstate + 64, // painchance + sfx_mumpai, // painsound + S_MUMMY_ATK1, // meleestate + S_MUMMYL_ATK1, // missilestate + S_NULL, // crashstate + S_MUMMY_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_mumdth, // deathsound + 12, // speed + 22 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 75, // mass + 0, // damage + sfx_mumact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_MUMMYSOUL + -1, // doomednum + S_MUMMY_SOUL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MUMMYFX1 + -1, // doomednum + S_MUMMYFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MUMMYFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 9 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 14 * FRACUNIT, // height + 100, // mass + 4, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_BEAST + 70, // doomednum + S_BEAST_LOOK1, // spawnstate + 220, // spawnhealth + S_BEAST_WALK1, // seestate + sfx_bstsit, // seesound + 8, // reactiontime + sfx_bstatk, // attacksound + S_BEAST_PAIN1, // painstate + 100, // painchance + sfx_bstpai, // painsound + 0, // meleestate + S_BEAST_ATK1, // missilestate + S_NULL, // crashstate + S_BEAST_DIE1, // deathstate + S_BEAST_XDIE1, // xdeathstate + sfx_bstdth, // deathsound + 14, // speed + 32 * FRACUNIT, // radius + 74 * FRACUNIT, // height + 200, // mass + 0, // damage + sfx_bstact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_BEASTBALL + -1, // doomednum + S_BEASTBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BEASTBALLX1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 12 * FRACUNIT, // speed + 9 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 4, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 + }, + + { // MT_BURNBALL + -1, // doomednum + S_BURNBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BEASTBALLX1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 6 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_BURNBALLFB + -1, // doomednum + S_BURNBALLFB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BEASTBALLX1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 6 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_PUFFY + -1, // doomednum + S_PUFFY1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_PUFFY1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 6 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SNAKE + 92, // doomednum + S_SNAKE_LOOK1, // spawnstate + 280, // spawnhealth + S_SNAKE_WALK1, // seestate + sfx_snksit, // seesound + 8, // reactiontime + sfx_snkatk, // attacksound + S_SNAKE_PAIN1, // painstate + 48, // painchance + sfx_snkpai, // painsound + 0, // meleestate + S_SNAKE_ATK1, // missilestate + S_NULL, // crashstate + S_SNAKE_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_snkdth, // deathsound + 10, // speed + 22 * FRACUNIT, // radius + 70 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_snkact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_SNAKEPRO_A + -1, // doomednum + S_SNAKEPRO_A1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SNAKEPRO_AX1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 14 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 + }, + + { // MT_SNAKEPRO_B + -1, // doomednum + S_SNAKEPRO_B1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SNAKEPRO_BX1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 14 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_HEAD + 6, // doomednum + S_HEAD_LOOK, // spawnstate + 700, // spawnhealth + S_HEAD_FLOAT, // seestate + sfx_hedsit, // seesound + 8, // reactiontime + sfx_hedat1, // attacksound + S_HEAD_PAIN1, // painstate + 32, // painchance + sfx_hedpai, // painsound + 0, // meleestate + S_HEAD_ATK1, // missilestate + S_NULL, // crashstate + S_HEAD_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_heddth, // deathsound + 6, // speed + 40 * FRACUNIT, // radius + 72 * FRACUNIT, // height + 325, // mass + 0, // damage + sfx_hedact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags + MF2_PASSMOBJ // flags2 + }, + + { // MT_HEADFX1 + -1, // doomednum + S_HEADFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HEADFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 13 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_THRUGHOST // flags2 + }, + + { // MT_HEADFX2 + -1, // doomednum + S_HEADFX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HEADFXI2_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 8 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_HEADFX3 + -1, // doomednum + S_HEADFX3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HEADFXI3_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 14 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 5, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 + }, + + { // MT_WHIRLWIND + -1, // doomednum + S_HEADFX4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HEADFXI4_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 74 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_SHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_CLINK + 90, // doomednum + S_CLINK_LOOK1, // spawnstate + 150, // spawnhealth + S_CLINK_WALK1, // seestate + sfx_clksit, // seesound + 8, // reactiontime + sfx_clkatk, // attacksound + S_CLINK_PAIN1, // painstate + 32, // painchance + sfx_clkpai, // painsound + S_CLINK_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_CLINK_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_clkdth, // deathsound + 14, // speed + 20 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 75, // mass + 0, // damage + sfx_clkact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_WIZARD + 15, // doomednum + S_WIZARD_LOOK1, // spawnstate + 180, // spawnhealth + S_WIZARD_WALK1, // seestate + sfx_wizsit, // seesound + 8, // reactiontime + sfx_wizatk, // attacksound + S_WIZARD_PAIN1, // painstate + 64, // painchance + sfx_wizpai, // painsound + 0, // meleestate + S_WIZARD_ATK1, // missilestate + S_NULL, // crashstate + S_WIZARD_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_wizdth, // deathsound + 12, // speed + 16 * FRACUNIT, // radius + 68 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_wizact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_FLOAT | MF_NOGRAVITY, // flags + MF2_PASSMOBJ // flags2 + }, + + { // MT_WIZFX1 + -1, // doomednum + S_WIZFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_WIZFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 18 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_IMP + 66, // doomednum + S_IMP_LOOK1, // spawnstate + 40, // spawnhealth + S_IMP_FLY1, // seestate + sfx_impsit, // seesound + 8, // reactiontime + sfx_impat1, // attacksound + S_IMP_PAIN1, // painstate + 200, // painchance + sfx_imppai, // painsound + S_IMP_MEATK1, // meleestate + S_IMP_MSATK1_1, // missilestate + S_IMP_CRASH1, // crashstate + S_IMP_DIE1, // deathstate + S_IMP_XDIE1, // xdeathstate + sfx_impdth, // deathsound + 10, // speed + 16 * FRACUNIT, // radius + 36 * FRACUNIT, // height + 50, // mass + 0, // damage + sfx_impact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_FLOAT | MF_NOGRAVITY | MF_COUNTKILL, // flags + MF2_SPAWNFLOAT | MF2_PASSMOBJ // flags2 + }, + + { // MT_IMPLEADER + 5, // doomednum + S_IMP_LOOK1, // spawnstate + 80, // spawnhealth + S_IMP_FLY1, // seestate + sfx_impsit, // seesound + 8, // reactiontime + sfx_impat2, // attacksound + S_IMP_PAIN1, // painstate + 200, // painchance + sfx_imppai, // painsound + 0, // meleestate + S_IMP_MSATK2_1, // missilestate + S_IMP_CRASH1, // crashstate + S_IMP_DIE1, // deathstate + S_IMP_XDIE1, // xdeathstate + sfx_impdth, // deathsound + 10, // speed + 16 * FRACUNIT, // radius + 36 * FRACUNIT, // height + 50, // mass + 0, // damage + sfx_impact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_FLOAT | MF_NOGRAVITY | MF_COUNTKILL, // flags + MF2_SPAWNFLOAT | MF2_PASSMOBJ // flags2 + }, + + { // MT_IMPCHUNK1 + -1, // doomednum + S_IMP_CHUNKA1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_IMPCHUNK2 + -1, // doomednum + S_IMP_CHUNKB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_IMPBALL + -1, // doomednum + S_IMPFX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_IMPFXI1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 10 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 + }, + + { // MT_KNIGHT + 64, // doomednum + S_KNIGHT_STND1, // spawnstate + 200, // spawnhealth + S_KNIGHT_WALK1, // seestate + sfx_kgtsit, // seesound + 8, // reactiontime + sfx_kgtatk, // attacksound + S_KNIGHT_PAIN1, // painstate + 100, // painchance + sfx_kgtpai, // painsound + S_KNIGHT_ATK1, // meleestate + S_KNIGHT_ATK1, // missilestate + S_NULL, // crashstate + S_KNIGHT_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_kgtdth, // deathsound + 12, // speed + 24 * FRACUNIT, // radius + 78 * FRACUNIT, // height + 150, // mass + 0, // damage + sfx_kgtact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_KNIGHTGHOST + 65, // doomednum + S_KNIGHT_STND1, // spawnstate + 200, // spawnhealth + S_KNIGHT_WALK1, // seestate + sfx_kgtsit, // seesound + 8, // reactiontime + sfx_kgtatk, // attacksound + S_KNIGHT_PAIN1, // painstate + 100, // painchance + sfx_kgtpai, // painsound + S_KNIGHT_ATK1, // meleestate + S_KNIGHT_ATK1, // missilestate + S_NULL, // crashstate + S_KNIGHT_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_kgtdth, // deathsound + 12, // speed + 24 * FRACUNIT, // radius + 78 * FRACUNIT, // height + 150, // mass + 0, // damage + sfx_kgtact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 + }, + + { // MT_KNIGHTAXE + -1, // doomednum + S_SPINAXE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SPINAXEX1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 9 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_WINDTHRUST | MF2_NOTELEPORT | MF2_THRUGHOST // flags2 + }, + + { // MT_REDAXE + -1, // doomednum + S_REDAXE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_REDAXEX1, // deathstate + S_NULL, // xdeathstate + sfx_hrnhit, // deathsound + 9 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 7, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_THRUGHOST // flags2 + }, + + { // MT_SORCERER1 + 7, // doomednum + S_SRCR1_LOOK1, // spawnstate + 2000, // spawnhealth + S_SRCR1_WALK1, // seestate + sfx_sbtsit, // seesound + 8, // reactiontime + sfx_sbtatk, // attacksound + S_SRCR1_PAIN1, // painstate + 56, // painchance + sfx_sbtpai, // painsound + 0, // meleestate + S_SRCR1_ATK1, // missilestate + S_NULL, // crashstate + S_SRCR1_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_sbtdth, // deathsound + 16, // speed + 28 * FRACUNIT, // radius + 100 * FRACUNIT, // height + 800, // mass + 0, // damage + sfx_sbtact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ | MF2_BOSS // flags2 + }, + + { // MT_SRCRFX1 + -1, // doomednum + S_SRCRFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SRCRFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 20 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 10, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_SORCERER2 + -1, // doomednum + S_SOR2_LOOK1, // spawnstate + 3500, // spawnhealth + S_SOR2_WALK1, // seestate + sfx_sorsit, // seesound + 8, // reactiontime + sfx_soratk, // attacksound + S_SOR2_PAIN1, // painstate + 32, // painchance + sfx_sorpai, // painsound + 0, // meleestate + S_SOR2_ATK1, // missilestate + S_NULL, // crashstate + S_SOR2_DIE1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 14, // speed + 16 * FRACUNIT, // radius + 70 * FRACUNIT, // height + 300, // mass + 0, // damage + sfx_soract, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ | MF2_BOSS // flags2 + }, + + { // MT_SOR2FX1 + -1, // doomednum + S_SOR2FX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SOR2FXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 20 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SOR2FXSPARK + -1, // doomednum + S_SOR2FXSPARK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 + }, + + { // MT_SOR2FX2 + -1, // doomednum + S_SOR2FX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SOR2FXI2_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 6 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 10, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SOR2TELEFADE + -1, // doomednum + S_SOR2TELEFADE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_MINOTAUR + 9, // doomednum + S_MNTR_LOOK1, // spawnstate + 3000, // spawnhealth + S_MNTR_WALK1, // seestate + sfx_minsit, // seesound + 8, // reactiontime + sfx_minat1, // attacksound + S_MNTR_PAIN1, // painstate + 25, // painchance + sfx_minpai, // painsound + S_MNTR_ATK1_1, // meleestate + S_MNTR_ATK2_1, // missilestate + S_NULL, // crashstate + S_MNTR_DIE1, // deathstate + S_NULL, // xdeathstate + sfx_mindth, // deathsound + 16, // speed + 28 * FRACUNIT, // radius + 100 * FRACUNIT, // height + 800, // mass + 7, // damage + sfx_minact, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF, // flags + MF2_FOOTCLIP | MF2_PASSMOBJ | MF2_BOSS // flags2 + }, + + { // MT_MNTRFX1 + -1, // doomednum + S_MNTRFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MNTRFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 20 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 3, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_MNTRFX2 + -1, // doomednum + S_MNTRFX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MNTRFXI2_1, // deathstate + S_NULL, // xdeathstate + sfx_phohit, // deathsound + 14 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 4, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_MNTRFX3 + -1, // doomednum + S_MNTRFX3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MNTRFXI2_1, // deathstate + S_NULL, // xdeathstate + sfx_phohit, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 4, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_AKYY + 73, // doomednum + S_AKYY1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_NOTDMATCH, // flags + 0 // flags2 + }, + + { // MT_BKYY + 79, // doomednum + S_BKYY1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_NOTDMATCH, // flags + 0 // flags2 + }, + + { // MT_CKEY + 80, // doomednum + S_CKYY1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL | MF_NOTDMATCH, // flags + 0 // flags2 + }, + + { // MT_AMGWNDWIMPY + 10, // doomednum + S_AMG1, // spawnstate + AMMO_GWND_WIMPY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMGWNDHEFTY + 12, // doomednum + S_AMG2_1, // spawnstate + AMMO_GWND_HEFTY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMMACEWIMPY + 13, // doomednum + S_AMM1, // spawnstate + AMMO_MACE_WIMPY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMMACEHEFTY + 16, // doomednum + S_AMM2, // spawnstate + AMMO_MACE_HEFTY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMCBOWWIMPY + 18, // doomednum + S_AMC1, // spawnstate + AMMO_CBOW_WIMPY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMCBOWHEFTY + 19, // doomednum + S_AMC2_1, // spawnstate + AMMO_CBOW_HEFTY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMSKRDWIMPY + 20, // doomednum + S_AMS1_1, // spawnstate + AMMO_SKRD_WIMPY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMSKRDHEFTY + 21, // doomednum + S_AMS2_1, // spawnstate + AMMO_SKRD_HEFTY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMPHRDWIMPY + 22, // doomednum + S_AMP1_1, // spawnstate + AMMO_PHRD_WIMPY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMPHRDHEFTY + 23, // doomednum + S_AMP2_1, // spawnstate + AMMO_PHRD_HEFTY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMBLSRWIMPY + 54, // doomednum + S_AMB1_1, // spawnstate + AMMO_BLSR_WIMPY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AMBLSRHEFTY + 55, // doomednum + S_AMB2_1, // spawnstate + AMMO_BLSR_HEFTY, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_SOUNDWIND + 42, // doomednum + S_SND_WIND, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_SOUNDWATERFALL + 41, // doomednum + S_SND_WATERFALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + } +}; diff --git a/games/NXDoom/src/heretic/info.h b/games/NXDoom/src/heretic/info.h new file mode 100644 index 00000000000..2247b658ab5 --- /dev/null +++ b/games/NXDoom/src/heretic/info.h @@ -0,0 +1,1584 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef HERETIC_INFO_H +#define HERETIC_INFO_H + +typedef enum +{ + SPR_IMPX, + SPR_ACLO, + SPR_PTN1, + SPR_SHLD, + SPR_SHD2, + SPR_BAGH, + SPR_SPMP, + SPR_INVS, + SPR_PTN2, + SPR_SOAR, + SPR_INVU, + SPR_PWBK, + SPR_EGGC, + SPR_EGGM, + SPR_FX01, + SPR_SPHL, + SPR_TRCH, + SPR_FBMB, + SPR_XPL1, + SPR_ATLP, + SPR_PPOD, + SPR_AMG1, + SPR_SPSH, + SPR_LVAS, + SPR_SLDG, + SPR_SKH1, + SPR_SKH2, + SPR_SKH3, + SPR_SKH4, + SPR_CHDL, + SPR_SRTC, + SPR_SMPL, + SPR_STGS, + SPR_STGL, + SPR_STCS, + SPR_STCL, + SPR_KFR1, + SPR_BARL, + SPR_BRPL, + SPR_MOS1, + SPR_MOS2, + SPR_WTRH, + SPR_HCOR, + SPR_KGZ1, + SPR_KGZB, + SPR_KGZG, + SPR_KGZY, + SPR_VLCO, + SPR_VFBL, + SPR_VTFB, + SPR_SFFI, + SPR_TGLT, + SPR_TELE, + SPR_STFF, + SPR_PUF3, + SPR_PUF4, + SPR_BEAK, + SPR_WGNT, + SPR_GAUN, + SPR_PUF1, + SPR_WBLS, + SPR_BLSR, + SPR_FX18, + SPR_FX17, + SPR_WMCE, + SPR_MACE, + SPR_FX02, + SPR_WSKL, + SPR_HROD, + SPR_FX00, + SPR_FX20, + SPR_FX21, + SPR_FX22, + SPR_FX23, + SPR_GWND, + SPR_PUF2, + SPR_WPHX, + SPR_PHNX, + SPR_FX04, + SPR_FX08, + SPR_FX09, + SPR_WBOW, + SPR_CRBW, + SPR_FX03, + SPR_BLOD, + SPR_PLAY, + SPR_FDTH, + SPR_BSKL, + SPR_CHKN, + SPR_MUMM, + SPR_FX15, + SPR_BEAS, + SPR_FRB1, + SPR_SNKE, + SPR_SNFX, + SPR_HEAD, + SPR_FX05, + SPR_FX06, + SPR_FX07, + SPR_CLNK, + SPR_WZRD, + SPR_FX11, + SPR_FX10, + SPR_KNIG, + SPR_SPAX, + SPR_RAXE, + SPR_SRCR, + SPR_FX14, + SPR_SOR2, + SPR_SDTH, + SPR_FX16, + SPR_MNTR, + SPR_FX12, + SPR_FX13, + SPR_AKYY, + SPR_BKYY, + SPR_CKYY, + SPR_AMG2, + SPR_AMM1, + SPR_AMM2, + SPR_AMC1, + SPR_AMC2, + SPR_AMS1, + SPR_AMS2, + SPR_AMP1, + SPR_AMP2, + SPR_AMB1, + SPR_AMB2, + NUMSPRITES +} spritenum_t; + +typedef enum +{ + S_NULL, + S_FREETARGMOBJ, + S_ITEM_PTN1_1, + S_ITEM_PTN1_2, + S_ITEM_PTN1_3, + S_ITEM_SHLD1, + S_ITEM_SHD2_1, + S_ITEM_BAGH1, + S_ITEM_SPMP1, + S_HIDESPECIAL1, + S_HIDESPECIAL2, + S_HIDESPECIAL3, + S_HIDESPECIAL4, + S_HIDESPECIAL5, + S_HIDESPECIAL6, + S_HIDESPECIAL7, + S_HIDESPECIAL8, + S_HIDESPECIAL9, + S_HIDESPECIAL10, + S_HIDESPECIAL11, + S_DORMANTARTI1, + S_DORMANTARTI2, + S_DORMANTARTI3, + S_DORMANTARTI4, + S_DORMANTARTI5, + S_DORMANTARTI6, + S_DORMANTARTI7, + S_DORMANTARTI8, + S_DORMANTARTI9, + S_DORMANTARTI10, + S_DORMANTARTI11, + S_DORMANTARTI12, + S_DORMANTARTI13, + S_DORMANTARTI14, + S_DORMANTARTI15, + S_DORMANTARTI16, + S_DORMANTARTI17, + S_DORMANTARTI18, + S_DORMANTARTI19, + S_DORMANTARTI20, + S_DORMANTARTI21, + S_DEADARTI1, + S_DEADARTI2, + S_DEADARTI3, + S_DEADARTI4, + S_DEADARTI5, + S_DEADARTI6, + S_DEADARTI7, + S_DEADARTI8, + S_DEADARTI9, + S_DEADARTI10, + S_ARTI_INVS1, + S_ARTI_PTN2_1, + S_ARTI_PTN2_2, + S_ARTI_PTN2_3, + S_ARTI_SOAR1, + S_ARTI_SOAR2, + S_ARTI_SOAR3, + S_ARTI_SOAR4, + S_ARTI_INVU1, + S_ARTI_INVU2, + S_ARTI_INVU3, + S_ARTI_INVU4, + S_ARTI_PWBK1, + S_ARTI_EGGC1, + S_ARTI_EGGC2, + S_ARTI_EGGC3, + S_ARTI_EGGC4, + S_EGGFX1, + S_EGGFX2, + S_EGGFX3, + S_EGGFX4, + S_EGGFX5, + S_EGGFXI1_1, + S_EGGFXI1_2, + S_EGGFXI1_3, + S_EGGFXI1_4, + S_ARTI_SPHL1, + S_ARTI_TRCH1, + S_ARTI_TRCH2, + S_ARTI_TRCH3, + S_ARTI_FBMB1, + S_FIREBOMB1, + S_FIREBOMB2, + S_FIREBOMB3, + S_FIREBOMB4, + S_FIREBOMB5, + S_FIREBOMB6, + S_FIREBOMB7, + S_FIREBOMB8, + S_FIREBOMB9, + S_FIREBOMB10, + S_FIREBOMB11, + S_ARTI_ATLP1, + S_ARTI_ATLP2, + S_ARTI_ATLP3, + S_ARTI_ATLP4, + S_POD_WAIT1, + S_POD_PAIN1, + S_POD_DIE1, + S_POD_DIE2, + S_POD_DIE3, + S_POD_DIE4, + S_POD_GROW1, + S_POD_GROW2, + S_POD_GROW3, + S_POD_GROW4, + S_POD_GROW5, + S_POD_GROW6, + S_POD_GROW7, + S_POD_GROW8, + S_PODGOO1, + S_PODGOO2, + S_PODGOOX, + S_PODGENERATOR, + S_SPLASH1, + S_SPLASH2, + S_SPLASH3, + S_SPLASH4, + S_SPLASHX, + S_SPLASHBASE1, + S_SPLASHBASE2, + S_SPLASHBASE3, + S_SPLASHBASE4, + S_SPLASHBASE5, + S_SPLASHBASE6, + S_SPLASHBASE7, + S_LAVASPLASH1, + S_LAVASPLASH2, + S_LAVASPLASH3, + S_LAVASPLASH4, + S_LAVASPLASH5, + S_LAVASPLASH6, + S_LAVASMOKE1, + S_LAVASMOKE2, + S_LAVASMOKE3, + S_LAVASMOKE4, + S_LAVASMOKE5, + S_SLUDGECHUNK1, + S_SLUDGECHUNK2, + S_SLUDGECHUNK3, + S_SLUDGECHUNK4, + S_SLUDGECHUNKX, + S_SLUDGESPLASH1, + S_SLUDGESPLASH2, + S_SLUDGESPLASH3, + S_SLUDGESPLASH4, + S_SKULLHANG70_1, + S_SKULLHANG60_1, + S_SKULLHANG45_1, + S_SKULLHANG35_1, + S_CHANDELIER1, + S_CHANDELIER2, + S_CHANDELIER3, + S_SERPTORCH1, + S_SERPTORCH2, + S_SERPTORCH3, + S_SMALLPILLAR, + S_STALAGMITESMALL, + S_STALAGMITELARGE, + S_STALACTITESMALL, + S_STALACTITELARGE, + S_FIREBRAZIER1, + S_FIREBRAZIER2, + S_FIREBRAZIER3, + S_FIREBRAZIER4, + S_FIREBRAZIER5, + S_FIREBRAZIER6, + S_FIREBRAZIER7, + S_FIREBRAZIER8, + S_BARREL, + S_BRPILLAR, + S_MOSS1, + S_MOSS2, + S_WALLTORCH1, + S_WALLTORCH2, + S_WALLTORCH3, + S_HANGINGCORPSE, + S_KEYGIZMO1, + S_KEYGIZMO2, + S_KEYGIZMO3, + S_KGZ_START, + S_KGZ_BLUEFLOAT1, + S_KGZ_GREENFLOAT1, + S_KGZ_YELLOWFLOAT1, + S_VOLCANO1, + S_VOLCANO2, + S_VOLCANO3, + S_VOLCANO4, + S_VOLCANO5, + S_VOLCANO6, + S_VOLCANO7, + S_VOLCANO8, + S_VOLCANO9, + S_VOLCANOBALL1, + S_VOLCANOBALL2, + S_VOLCANOBALLX1, + S_VOLCANOBALLX2, + S_VOLCANOBALLX3, + S_VOLCANOBALLX4, + S_VOLCANOBALLX5, + S_VOLCANOBALLX6, + S_VOLCANOTBALL1, + S_VOLCANOTBALL2, + S_VOLCANOTBALLX1, + S_VOLCANOTBALLX2, + S_VOLCANOTBALLX3, + S_VOLCANOTBALLX4, + S_VOLCANOTBALLX5, + S_VOLCANOTBALLX6, + S_VOLCANOTBALLX7, + S_TELEGLITGEN1, + S_TELEGLITGEN2, + S_TELEGLITTER1_1, + S_TELEGLITTER1_2, + S_TELEGLITTER1_3, + S_TELEGLITTER1_4, + S_TELEGLITTER1_5, + S_TELEGLITTER2_1, + S_TELEGLITTER2_2, + S_TELEGLITTER2_3, + S_TELEGLITTER2_4, + S_TELEGLITTER2_5, + S_TFOG1, + S_TFOG2, + S_TFOG3, + S_TFOG4, + S_TFOG5, + S_TFOG6, + S_TFOG7, + S_TFOG8, + S_TFOG9, + S_TFOG10, + S_TFOG11, + S_TFOG12, + S_TFOG13, + S_LIGHTDONE, + S_STAFFREADY, + S_STAFFDOWN, + S_STAFFUP, + S_STAFFREADY2_1, + S_STAFFREADY2_2, + S_STAFFREADY2_3, + S_STAFFDOWN2, + S_STAFFUP2, + S_STAFFATK1_1, + S_STAFFATK1_2, + S_STAFFATK1_3, + S_STAFFATK2_1, + S_STAFFATK2_2, + S_STAFFATK2_3, + S_STAFFPUFF1, + S_STAFFPUFF2, + S_STAFFPUFF3, + S_STAFFPUFF4, + S_STAFFPUFF2_1, + S_STAFFPUFF2_2, + S_STAFFPUFF2_3, + S_STAFFPUFF2_4, + S_STAFFPUFF2_5, + S_STAFFPUFF2_6, + S_BEAKREADY, + S_BEAKDOWN, + S_BEAKUP, + S_BEAKATK1_1, + S_BEAKATK2_1, + S_WGNT, + S_GAUNTLETREADY, + S_GAUNTLETDOWN, + S_GAUNTLETUP, + S_GAUNTLETREADY2_1, + S_GAUNTLETREADY2_2, + S_GAUNTLETREADY2_3, + S_GAUNTLETDOWN2, + S_GAUNTLETUP2, + S_GAUNTLETATK1_1, + S_GAUNTLETATK1_2, + S_GAUNTLETATK1_3, + S_GAUNTLETATK1_4, + S_GAUNTLETATK1_5, + S_GAUNTLETATK1_6, + S_GAUNTLETATK1_7, + S_GAUNTLETATK2_1, + S_GAUNTLETATK2_2, + S_GAUNTLETATK2_3, + S_GAUNTLETATK2_4, + S_GAUNTLETATK2_5, + S_GAUNTLETATK2_6, + S_GAUNTLETATK2_7, + S_GAUNTLETPUFF1_1, + S_GAUNTLETPUFF1_2, + S_GAUNTLETPUFF1_3, + S_GAUNTLETPUFF1_4, + S_GAUNTLETPUFF2_1, + S_GAUNTLETPUFF2_2, + S_GAUNTLETPUFF2_3, + S_GAUNTLETPUFF2_4, + S_BLSR, + S_BLASTERREADY, + S_BLASTERDOWN, + S_BLASTERUP, + S_BLASTERATK1_1, + S_BLASTERATK1_2, + S_BLASTERATK1_3, + S_BLASTERATK1_4, + S_BLASTERATK1_5, + S_BLASTERATK1_6, + S_BLASTERATK2_1, + S_BLASTERATK2_2, + S_BLASTERATK2_3, + S_BLASTERATK2_4, + S_BLASTERATK2_5, + S_BLASTERATK2_6, + S_BLASTERFX1_1, + S_BLASTERFXI1_1, + S_BLASTERFXI1_2, + S_BLASTERFXI1_3, + S_BLASTERFXI1_4, + S_BLASTERFXI1_5, + S_BLASTERFXI1_6, + S_BLASTERFXI1_7, + S_BLASTERSMOKE1, + S_BLASTERSMOKE2, + S_BLASTERSMOKE3, + S_BLASTERSMOKE4, + S_BLASTERSMOKE5, + S_RIPPER1, + S_RIPPER2, + S_RIPPERX1, + S_RIPPERX2, + S_RIPPERX3, + S_RIPPERX4, + S_RIPPERX5, + S_BLASTERPUFF1_1, + S_BLASTERPUFF1_2, + S_BLASTERPUFF1_3, + S_BLASTERPUFF1_4, + S_BLASTERPUFF1_5, + S_BLASTERPUFF2_1, + S_BLASTERPUFF2_2, + S_BLASTERPUFF2_3, + S_BLASTERPUFF2_4, + S_BLASTERPUFF2_5, + S_BLASTERPUFF2_6, + S_BLASTERPUFF2_7, + S_WMCE, + S_MACEREADY, + S_MACEDOWN, + S_MACEUP, + S_MACEATK1_1, + S_MACEATK1_2, + S_MACEATK1_3, + S_MACEATK1_4, + S_MACEATK1_5, + S_MACEATK1_6, + S_MACEATK1_7, + S_MACEATK1_8, + S_MACEATK1_9, + S_MACEATK1_10, + S_MACEATK2_1, + S_MACEATK2_2, + S_MACEATK2_3, + S_MACEATK2_4, + S_MACEFX1_1, + S_MACEFX1_2, + S_MACEFXI1_1, + S_MACEFXI1_2, + S_MACEFXI1_3, + S_MACEFXI1_4, + S_MACEFXI1_5, + S_MACEFX2_1, + S_MACEFX2_2, + S_MACEFXI2_1, + S_MACEFX3_1, + S_MACEFX3_2, + S_MACEFX4_1, + S_MACEFXI4_1, + S_WSKL, + S_HORNRODREADY, + S_HORNRODDOWN, + S_HORNRODUP, + S_HORNRODATK1_1, + S_HORNRODATK1_2, + S_HORNRODATK1_3, + S_HORNRODATK2_1, + S_HORNRODATK2_2, + S_HORNRODATK2_3, + S_HORNRODATK2_4, + S_HORNRODATK2_5, + S_HORNRODATK2_6, + S_HORNRODATK2_7, + S_HORNRODATK2_8, + S_HORNRODATK2_9, + S_HRODFX1_1, + S_HRODFX1_2, + S_HRODFXI1_1, + S_HRODFXI1_2, + S_HRODFXI1_3, + S_HRODFXI1_4, + S_HRODFXI1_5, + S_HRODFXI1_6, + S_HRODFX2_1, + S_HRODFX2_2, + S_HRODFX2_3, + S_HRODFX2_4, + S_HRODFXI2_1, + S_HRODFXI2_2, + S_HRODFXI2_3, + S_HRODFXI2_4, + S_HRODFXI2_5, + S_HRODFXI2_6, + S_HRODFXI2_7, + S_HRODFXI2_8, + S_RAINPLR1_1, + S_RAINPLR2_1, + S_RAINPLR3_1, + S_RAINPLR4_1, + S_RAINPLR1X_1, + S_RAINPLR1X_2, + S_RAINPLR1X_3, + S_RAINPLR1X_4, + S_RAINPLR1X_5, + S_RAINPLR2X_1, + S_RAINPLR2X_2, + S_RAINPLR2X_3, + S_RAINPLR2X_4, + S_RAINPLR2X_5, + S_RAINPLR3X_1, + S_RAINPLR3X_2, + S_RAINPLR3X_3, + S_RAINPLR3X_4, + S_RAINPLR3X_5, + S_RAINPLR4X_1, + S_RAINPLR4X_2, + S_RAINPLR4X_3, + S_RAINPLR4X_4, + S_RAINPLR4X_5, + S_RAINAIRXPLR1_1, + S_RAINAIRXPLR2_1, + S_RAINAIRXPLR3_1, + S_RAINAIRXPLR4_1, + S_RAINAIRXPLR1_2, + S_RAINAIRXPLR2_2, + S_RAINAIRXPLR3_2, + S_RAINAIRXPLR4_2, + S_RAINAIRXPLR1_3, + S_RAINAIRXPLR2_3, + S_RAINAIRXPLR3_3, + S_RAINAIRXPLR4_3, + S_GOLDWANDREADY, + S_GOLDWANDDOWN, + S_GOLDWANDUP, + S_GOLDWANDATK1_1, + S_GOLDWANDATK1_2, + S_GOLDWANDATK1_3, + S_GOLDWANDATK1_4, + S_GOLDWANDATK2_1, + S_GOLDWANDATK2_2, + S_GOLDWANDATK2_3, + S_GOLDWANDATK2_4, + S_GWANDFX1_1, + S_GWANDFX1_2, + S_GWANDFXI1_1, + S_GWANDFXI1_2, + S_GWANDFXI1_3, + S_GWANDFXI1_4, + S_GWANDFX2_1, + S_GWANDFX2_2, + S_GWANDPUFF1_1, + S_GWANDPUFF1_2, + S_GWANDPUFF1_3, + S_GWANDPUFF1_4, + S_GWANDPUFF1_5, + S_WPHX, + S_PHOENIXREADY, + S_PHOENIXDOWN, + S_PHOENIXUP, + S_PHOENIXATK1_1, + S_PHOENIXATK1_2, + S_PHOENIXATK1_3, + S_PHOENIXATK1_4, + S_PHOENIXATK1_5, + S_PHOENIXATK2_1, + S_PHOENIXATK2_2, + S_PHOENIXATK2_3, + S_PHOENIXATK2_4, + S_PHOENIXFX1_1, + S_PHOENIXFXI1_1, + S_PHOENIXFXI1_2, + S_PHOENIXFXI1_3, + S_PHOENIXFXI1_4, + S_PHOENIXFXI1_5, + S_PHOENIXFXI1_6, + S_PHOENIXFXI1_7, + S_PHOENIXFXI1_8, + S_PHOENIXFXIX_1, // [ States in Heretic 1.0 that were removed + S_PHOENIXFXIX_2, + S_PHOENIXFXIX_3, // ] + S_PHOENIXPUFF1, + S_PHOENIXPUFF2, + S_PHOENIXPUFF3, + S_PHOENIXPUFF4, + S_PHOENIXPUFF5, + S_PHOENIXFX2_1, + S_PHOENIXFX2_2, + S_PHOENIXFX2_3, + S_PHOENIXFX2_4, + S_PHOENIXFX2_5, + S_PHOENIXFX2_6, + S_PHOENIXFX2_7, + S_PHOENIXFX2_8, + S_PHOENIXFX2_9, + S_PHOENIXFX2_10, + S_PHOENIXFXI2_1, + S_PHOENIXFXI2_2, + S_PHOENIXFXI2_3, + S_PHOENIXFXI2_4, + S_PHOENIXFXI2_5, + S_WBOW, + S_CRBOW1, + S_CRBOW2, + S_CRBOW3, + S_CRBOW4, + S_CRBOW5, + S_CRBOW6, + S_CRBOW7, + S_CRBOW8, + S_CRBOW9, + S_CRBOW10, + S_CRBOW11, + S_CRBOW12, + S_CRBOW13, + S_CRBOW14, + S_CRBOW15, + S_CRBOW16, + S_CRBOW17, + S_CRBOW18, + S_CRBOWDOWN, + S_CRBOWUP, + S_CRBOWATK1_1, + S_CRBOWATK1_2, + S_CRBOWATK1_3, + S_CRBOWATK1_4, + S_CRBOWATK1_5, + S_CRBOWATK1_6, + S_CRBOWATK1_7, + S_CRBOWATK1_8, + S_CRBOWATK2_1, + S_CRBOWATK2_2, + S_CRBOWATK2_3, + S_CRBOWATK2_4, + S_CRBOWATK2_5, + S_CRBOWATK2_6, + S_CRBOWATK2_7, + S_CRBOWATK2_8, + S_CRBOWFX1, + S_CRBOWFXI1_1, + S_CRBOWFXI1_2, + S_CRBOWFXI1_3, + S_CRBOWFX2, + S_CRBOWFX3, + S_CRBOWFXI3_1, + S_CRBOWFXI3_2, + S_CRBOWFXI3_3, + S_CRBOWFX4_1, + S_CRBOWFX4_2, + S_BLOOD1, + S_BLOOD2, + S_BLOOD3, + S_BLOODSPLATTER1, + S_BLOODSPLATTER2, + S_BLOODSPLATTER3, + S_BLOODSPLATTERX, + S_PLAY, + S_PLAY_RUN1, + S_PLAY_RUN2, + S_PLAY_RUN3, + S_PLAY_RUN4, + S_PLAY_ATK1, + S_PLAY_ATK2, + S_PLAY_PAIN, + S_PLAY_PAIN2, + S_PLAY_DIE1, + S_PLAY_DIE2, + S_PLAY_DIE3, + S_PLAY_DIE4, + S_PLAY_DIE5, + S_PLAY_DIE6, + S_PLAY_DIE7, + S_PLAY_DIE8, + S_PLAY_DIE9, + S_PLAY_XDIE1, + S_PLAY_XDIE2, + S_PLAY_XDIE3, + S_PLAY_XDIE4, + S_PLAY_XDIE5, + S_PLAY_XDIE6, + S_PLAY_XDIE7, + S_PLAY_XDIE8, + S_PLAY_XDIE9, + S_PLAY_FDTH1, + S_PLAY_FDTH2, + S_PLAY_FDTH3, + S_PLAY_FDTH4, + S_PLAY_FDTH5, + S_PLAY_FDTH6, + S_PLAY_FDTH7, + S_PLAY_FDTH8, + S_PLAY_FDTH9, + S_PLAY_FDTH10, + S_PLAY_FDTH11, + S_PLAY_FDTH12, + S_PLAY_FDTH13, + S_PLAY_FDTH14, + S_PLAY_FDTH15, + S_PLAY_FDTH16, + S_PLAY_FDTH17, + S_PLAY_FDTH18, + S_PLAY_FDTH19, // < These two frames were not present in the Heretic + S_PLAY_FDTH20, // < 1.0 executable (fire death animation was extended) + S_BLOODYSKULL1, + S_BLOODYSKULL2, + S_BLOODYSKULL3, + S_BLOODYSKULL4, + S_BLOODYSKULL5, + S_BLOODYSKULLX1, + S_BLOODYSKULLX2, + S_CHICPLAY, + S_CHICPLAY_RUN1, + S_CHICPLAY_RUN2, + S_CHICPLAY_RUN3, + S_CHICPLAY_RUN4, + S_CHICPLAY_ATK1, + S_CHICPLAY_PAIN, + S_CHICPLAY_PAIN2, + S_CHICKEN_LOOK1, + S_CHICKEN_LOOK2, + S_CHICKEN_WALK1, + S_CHICKEN_WALK2, + S_CHICKEN_PAIN1, + S_CHICKEN_PAIN2, + S_CHICKEN_ATK1, + S_CHICKEN_ATK2, + S_CHICKEN_DIE1, + S_CHICKEN_DIE2, + S_CHICKEN_DIE3, + S_CHICKEN_DIE4, + S_CHICKEN_DIE5, + S_CHICKEN_DIE6, + S_CHICKEN_DIE7, + S_CHICKEN_DIE8, + S_FEATHER1, + S_FEATHER2, + S_FEATHER3, + S_FEATHER4, + S_FEATHER5, + S_FEATHER6, + S_FEATHER7, + S_FEATHER8, + S_FEATHERX, + S_MUMMY_LOOK1, + S_MUMMY_LOOK2, + S_MUMMY_WALK1, + S_MUMMY_WALK2, + S_MUMMY_WALK3, + S_MUMMY_WALK4, + S_MUMMY_ATK1, + S_MUMMY_ATK2, + S_MUMMY_ATK3, + S_MUMMYL_ATK1, + S_MUMMYL_ATK2, + S_MUMMYL_ATK3, + S_MUMMYL_ATK4, + S_MUMMYL_ATK5, + S_MUMMYL_ATK6, + S_MUMMY_PAIN1, + S_MUMMY_PAIN2, + S_MUMMY_DIE1, + S_MUMMY_DIE2, + S_MUMMY_DIE3, + S_MUMMY_DIE4, + S_MUMMY_DIE5, + S_MUMMY_DIE6, + S_MUMMY_DIE7, + S_MUMMY_DIE8, + S_MUMMY_SOUL1, + S_MUMMY_SOUL2, + S_MUMMY_SOUL3, + S_MUMMY_SOUL4, + S_MUMMY_SOUL5, + S_MUMMY_SOUL6, + S_MUMMY_SOUL7, + S_MUMMYFX1_1, + S_MUMMYFX1_2, + S_MUMMYFX1_3, + S_MUMMYFX1_4, + S_MUMMYFXI1_1, + S_MUMMYFXI1_2, + S_MUMMYFXI1_3, + S_MUMMYFXI1_4, + S_BEAST_LOOK1, + S_BEAST_LOOK2, + S_BEAST_WALK1, + S_BEAST_WALK2, + S_BEAST_WALK3, + S_BEAST_WALK4, + S_BEAST_WALK5, + S_BEAST_WALK6, + S_BEAST_ATK1, + S_BEAST_ATK2, + S_BEAST_PAIN1, + S_BEAST_PAIN2, + S_BEAST_DIE1, + S_BEAST_DIE2, + S_BEAST_DIE3, + S_BEAST_DIE4, + S_BEAST_DIE5, + S_BEAST_DIE6, + S_BEAST_DIE7, + S_BEAST_DIE8, + S_BEAST_DIE9, + S_BEAST_XDIE1, + S_BEAST_XDIE2, + S_BEAST_XDIE3, + S_BEAST_XDIE4, + S_BEAST_XDIE5, + S_BEAST_XDIE6, + S_BEAST_XDIE7, + S_BEAST_XDIE8, + S_BEASTBALL1, + S_BEASTBALL2, + S_BEASTBALL3, + S_BEASTBALL4, + S_BEASTBALL5, + S_BEASTBALL6, + S_BEASTBALLX1, + S_BEASTBALLX2, + S_BEASTBALLX3, + S_BEASTBALLX4, + S_BEASTBALLX5, + S_BURNBALL1, + S_BURNBALL2, + S_BURNBALL3, + S_BURNBALL4, + S_BURNBALL5, + S_BURNBALL6, + S_BURNBALL7, + S_BURNBALL8, + S_BURNBALLFB1, + S_BURNBALLFB2, + S_BURNBALLFB3, + S_BURNBALLFB4, + S_BURNBALLFB5, + S_BURNBALLFB6, + S_BURNBALLFB7, + S_BURNBALLFB8, + S_PUFFY1, + S_PUFFY2, + S_PUFFY3, + S_PUFFY4, + S_PUFFY5, + S_SNAKE_LOOK1, + S_SNAKE_LOOK2, + S_SNAKE_WALK1, + S_SNAKE_WALK2, + S_SNAKE_WALK3, + S_SNAKE_WALK4, + S_SNAKE_ATK1, + S_SNAKE_ATK2, + S_SNAKE_ATK3, + S_SNAKE_ATK4, + S_SNAKE_ATK5, + S_SNAKE_ATK6, + S_SNAKE_ATK7, + S_SNAKE_ATK8, + S_SNAKE_ATK9, + S_SNAKE_PAIN1, + S_SNAKE_PAIN2, + S_SNAKE_DIE1, + S_SNAKE_DIE2, + S_SNAKE_DIE3, + S_SNAKE_DIE4, + S_SNAKE_DIE5, + S_SNAKE_DIE6, + S_SNAKE_DIE7, + S_SNAKE_DIE8, + S_SNAKE_DIE9, + S_SNAKE_DIE10, + S_SNAKEPRO_A1, + S_SNAKEPRO_A2, + S_SNAKEPRO_A3, + S_SNAKEPRO_A4, + S_SNAKEPRO_AX1, + S_SNAKEPRO_AX2, + S_SNAKEPRO_AX3, + S_SNAKEPRO_AX4, + S_SNAKEPRO_AX5, + S_SNAKEPRO_B1, + S_SNAKEPRO_B2, + S_SNAKEPRO_BX1, + S_SNAKEPRO_BX2, + S_SNAKEPRO_BX3, + S_SNAKEPRO_BX4, + S_HEAD_LOOK, + S_HEAD_FLOAT, + S_HEAD_ATK1, + S_HEAD_ATK2, + S_HEAD_PAIN1, + S_HEAD_PAIN2, + S_HEAD_DIE1, + S_HEAD_DIE2, + S_HEAD_DIE3, + S_HEAD_DIE4, + S_HEAD_DIE5, + S_HEAD_DIE6, + S_HEAD_DIE7, + S_HEADFX1_1, + S_HEADFX1_2, + S_HEADFX1_3, + S_HEADFXI1_1, + S_HEADFXI1_2, + S_HEADFXI1_3, + S_HEADFXI1_4, + S_HEADFX2_1, + S_HEADFX2_2, + S_HEADFX2_3, + S_HEADFXI2_1, + S_HEADFXI2_2, + S_HEADFXI2_3, + S_HEADFXI2_4, + S_HEADFX3_1, + S_HEADFX3_2, + S_HEADFX3_3, + S_HEADFX3_4, + S_HEADFX3_5, + S_HEADFX3_6, + S_HEADFXI3_1, + S_HEADFXI3_2, + S_HEADFXI3_3, + S_HEADFXI3_4, + S_HEADFX4_1, + S_HEADFX4_2, + S_HEADFX4_3, + S_HEADFX4_4, + S_HEADFX4_5, + S_HEADFX4_6, + S_HEADFX4_7, + S_HEADFXI4_1, + S_HEADFXI4_2, + S_HEADFXI4_3, + S_HEADFXI4_4, + S_CLINK_LOOK1, + S_CLINK_LOOK2, + S_CLINK_WALK1, + S_CLINK_WALK2, + S_CLINK_WALK3, + S_CLINK_WALK4, + S_CLINK_ATK1, + S_CLINK_ATK2, + S_CLINK_ATK3, + S_CLINK_PAIN1, + S_CLINK_PAIN2, + S_CLINK_DIE1, + S_CLINK_DIE2, + S_CLINK_DIE3, + S_CLINK_DIE4, + S_CLINK_DIE5, + S_CLINK_DIE6, + S_CLINK_DIE7, + S_WIZARD_LOOK1, + S_WIZARD_LOOK2, + S_WIZARD_WALK1, + S_WIZARD_WALK2, + S_WIZARD_WALK3, + S_WIZARD_WALK4, + S_WIZARD_WALK5, + S_WIZARD_WALK6, + S_WIZARD_WALK7, + S_WIZARD_WALK8, + S_WIZARD_ATK1, + S_WIZARD_ATK2, + S_WIZARD_ATK3, + S_WIZARD_ATK4, + S_WIZARD_ATK5, + S_WIZARD_ATK6, + S_WIZARD_ATK7, + S_WIZARD_ATK8, + S_WIZARD_ATK9, + S_WIZARD_PAIN1, + S_WIZARD_PAIN2, + S_WIZARD_DIE1, + S_WIZARD_DIE2, + S_WIZARD_DIE3, + S_WIZARD_DIE4, + S_WIZARD_DIE5, + S_WIZARD_DIE6, + S_WIZARD_DIE7, + S_WIZARD_DIE8, + S_WIZFX1_1, + S_WIZFX1_2, + S_WIZFXI1_1, + S_WIZFXI1_2, + S_WIZFXI1_3, + S_WIZFXI1_4, + S_WIZFXI1_5, + S_IMP_LOOK1, + S_IMP_LOOK2, + S_IMP_LOOK3, + S_IMP_LOOK4, + S_IMP_FLY1, + S_IMP_FLY2, + S_IMP_FLY3, + S_IMP_FLY4, + S_IMP_FLY5, + S_IMP_FLY6, + S_IMP_FLY7, + S_IMP_FLY8, + S_IMP_MEATK1, + S_IMP_MEATK2, + S_IMP_MEATK3, + S_IMP_MSATK1_1, + S_IMP_MSATK1_2, + S_IMP_MSATK1_3, + S_IMP_MSATK1_4, + S_IMP_MSATK1_5, + S_IMP_MSATK1_6, + S_IMP_MSATK2_1, + S_IMP_MSATK2_2, + S_IMP_MSATK2_3, + S_IMP_PAIN1, + S_IMP_PAIN2, + S_IMP_DIE1, + S_IMP_DIE2, + S_IMP_XDIE1, + S_IMP_XDIE2, + S_IMP_XDIE3, + S_IMP_XDIE4, + S_IMP_XDIE5, + S_IMP_CRASH1, + S_IMP_CRASH2, + S_IMP_CRASH3, + S_IMP_CRASH4, + S_IMP_XCRASH1, + S_IMP_XCRASH2, + S_IMP_XCRASH3, + S_IMP_CHUNKA1, + S_IMP_CHUNKA2, + S_IMP_CHUNKA3, + S_IMP_CHUNKB1, + S_IMP_CHUNKB2, + S_IMP_CHUNKB3, + S_IMPFX1, + S_IMPFX2, + S_IMPFX3, + S_IMPFXI1, + S_IMPFXI2, + S_IMPFXI3, + S_IMPFXI4, + S_KNIGHT_STND1, + S_KNIGHT_STND2, + S_KNIGHT_WALK1, + S_KNIGHT_WALK2, + S_KNIGHT_WALK3, + S_KNIGHT_WALK4, + S_KNIGHT_ATK1, + S_KNIGHT_ATK2, + S_KNIGHT_ATK3, + S_KNIGHT_ATK4, + S_KNIGHT_ATK5, + S_KNIGHT_ATK6, + S_KNIGHT_PAIN1, + S_KNIGHT_PAIN2, + S_KNIGHT_DIE1, + S_KNIGHT_DIE2, + S_KNIGHT_DIE3, + S_KNIGHT_DIE4, + S_KNIGHT_DIE5, + S_KNIGHT_DIE6, + S_KNIGHT_DIE7, + S_SPINAXE1, + S_SPINAXE2, + S_SPINAXE3, + S_SPINAXEX1, + S_SPINAXEX2, + S_SPINAXEX3, + S_REDAXE1, + S_REDAXE2, + S_REDAXEX1, + S_REDAXEX2, + S_REDAXEX3, + S_SRCR1_LOOK1, + S_SRCR1_LOOK2, + S_SRCR1_WALK1, + S_SRCR1_WALK2, + S_SRCR1_WALK3, + S_SRCR1_WALK4, + S_SRCR1_PAIN1, + S_SRCR1_ATK1, + S_SRCR1_ATK2, + S_SRCR1_ATK3, + S_SRCR1_ATK4, + S_SRCR1_ATK5, + S_SRCR1_ATK6, + S_SRCR1_ATK7, + S_SRCR1_DIE1, + S_SRCR1_DIE2, + S_SRCR1_DIE3, + S_SRCR1_DIE4, + S_SRCR1_DIE5, + S_SRCR1_DIE6, + S_SRCR1_DIE7, + S_SRCR1_DIE8, + S_SRCR1_DIE9, + S_SRCR1_DIE10, + S_SRCR1_DIE11, + S_SRCR1_DIE12, + S_SRCR1_DIE13, + S_SRCR1_DIE14, + S_SRCR1_DIE15, + S_SRCR1_DIE16, + S_SRCR1_DIE17, + S_SRCRFX1_1, + S_SRCRFX1_2, + S_SRCRFX1_3, + S_SRCRFXI1_1, + S_SRCRFXI1_2, + S_SRCRFXI1_3, + S_SRCRFXI1_4, + S_SRCRFXI1_5, + S_SOR2_RISE1, + S_SOR2_RISE2, + S_SOR2_RISE3, + S_SOR2_RISE4, + S_SOR2_RISE5, + S_SOR2_RISE6, + S_SOR2_RISE7, + S_SOR2_LOOK1, + S_SOR2_LOOK2, + S_SOR2_WALK1, + S_SOR2_WALK2, + S_SOR2_WALK3, + S_SOR2_WALK4, + S_SOR2_PAIN1, + S_SOR2_PAIN2, + S_SOR2_ATK1, + S_SOR2_ATK2, + S_SOR2_ATK3, + S_SOR2_TELE1, + S_SOR2_TELE2, + S_SOR2_TELE3, + S_SOR2_TELE4, + S_SOR2_TELE5, + S_SOR2_TELE6, + S_SOR2_DIE1, + S_SOR2_DIE2, + S_SOR2_DIE3, + S_SOR2_DIE4, + S_SOR2_DIE5, + S_SOR2_DIE6, + S_SOR2_DIE7, + S_SOR2_DIE8, + S_SOR2_DIE9, + S_SOR2_DIE10, + S_SOR2_DIE11, + S_SOR2_DIE12, + S_SOR2_DIE13, + S_SOR2_DIE14, + S_SOR2_DIE15, + S_SOR2FX1_1, + S_SOR2FX1_2, + S_SOR2FX1_3, + S_SOR2FXI1_1, + S_SOR2FXI1_2, + S_SOR2FXI1_3, + S_SOR2FXI1_4, + S_SOR2FXI1_5, + S_SOR2FXI1_6, + S_SOR2FXSPARK1, + S_SOR2FXSPARK2, + S_SOR2FXSPARK3, + S_SOR2FX2_1, + S_SOR2FX2_2, + S_SOR2FX2_3, + S_SOR2FXI2_1, + S_SOR2FXI2_2, + S_SOR2FXI2_3, + S_SOR2FXI2_4, + S_SOR2FXI2_5, + S_SOR2TELEFADE1, + S_SOR2TELEFADE2, + S_SOR2TELEFADE3, + S_SOR2TELEFADE4, + S_SOR2TELEFADE5, + S_SOR2TELEFADE6, + S_MNTR_LOOK1, + S_MNTR_LOOK2, + S_MNTR_WALK1, + S_MNTR_WALK2, + S_MNTR_WALK3, + S_MNTR_WALK4, + S_MNTR_ATK1_1, + S_MNTR_ATK1_2, + S_MNTR_ATK1_3, + S_MNTR_ATK2_1, + S_MNTR_ATK2_2, + S_MNTR_ATK2_3, + S_MNTR_ATK3_1, + S_MNTR_ATK3_2, + S_MNTR_ATK3_3, + S_MNTR_ATK3_4, + S_MNTR_ATK4_1, + S_MNTR_PAIN1, + S_MNTR_PAIN2, + S_MNTR_DIE1, + S_MNTR_DIE2, + S_MNTR_DIE3, + S_MNTR_DIE4, + S_MNTR_DIE5, + S_MNTR_DIE6, + S_MNTR_DIE7, + S_MNTR_DIE8, + S_MNTR_DIE9, + S_MNTR_DIE10, + S_MNTR_DIE11, + S_MNTR_DIE12, + S_MNTR_DIE13, + S_MNTR_DIE14, + S_MNTR_DIE15, + S_MNTRFX1_1, + S_MNTRFX1_2, + S_MNTRFXI1_1, + S_MNTRFXI1_2, + S_MNTRFXI1_3, + S_MNTRFXI1_4, + S_MNTRFXI1_5, + S_MNTRFXI1_6, + S_MNTRFX2_1, + S_MNTRFXI2_1, + S_MNTRFXI2_2, + S_MNTRFXI2_3, + S_MNTRFXI2_4, + S_MNTRFXI2_5, + S_MNTRFX3_1, + S_MNTRFX3_2, + S_MNTRFX3_3, + S_MNTRFX3_4, + S_MNTRFX3_5, + S_MNTRFX3_6, + S_MNTRFX3_7, + S_MNTRFX3_8, + S_MNTRFX3_9, + S_AKYY1, + S_AKYY2, + S_AKYY3, + S_AKYY4, + S_AKYY5, + S_AKYY6, + S_AKYY7, + S_AKYY8, + S_AKYY9, + S_AKYY10, + S_BKYY1, + S_BKYY2, + S_BKYY3, + S_BKYY4, + S_BKYY5, + S_BKYY6, + S_BKYY7, + S_BKYY8, + S_BKYY9, + S_BKYY10, + S_CKYY1, + S_CKYY2, + S_CKYY3, + S_CKYY4, + S_CKYY5, + S_CKYY6, + S_CKYY7, + S_CKYY8, + S_CKYY9, + S_AMG1, + S_AMG2_1, + S_AMG2_2, + S_AMG2_3, + S_AMM1, + S_AMM2, + S_AMC1, + S_AMC2_1, + S_AMC2_2, + S_AMC2_3, + S_AMS1_1, + S_AMS1_2, + S_AMS2_1, + S_AMS2_2, + S_AMP1_1, + S_AMP1_2, + S_AMP1_3, + S_AMP2_1, + S_AMP2_2, + S_AMP2_3, + S_AMB1_1, + S_AMB1_2, + S_AMB1_3, + S_AMB2_1, + S_AMB2_2, + S_AMB2_3, + S_SND_WIND, + S_SND_WATERFALL, + NUMSTATES +} statenum_t; + + +struct mobj_s; +struct player_s; +struct pspdef_s; + + +typedef struct +{ + spritenum_t sprite; + int frame; + int tics; + void (*action) (struct mobj_s *, struct player_s *, struct pspdef_s *); + statenum_t nextstate; + int misc1, misc2; +} state_t; + +extern state_t states[NUMSTATES]; +extern const char *sprnames[]; + + + +typedef enum +{ + MT_MISC0, + MT_ITEMSHIELD1, + MT_ITEMSHIELD2, + MT_MISC1, + MT_MISC2, + MT_ARTIINVISIBILITY, + MT_MISC3, + MT_ARTIFLY, + MT_ARTIINVULNERABILITY, + MT_ARTITOMEOFPOWER, + MT_ARTIEGG, + MT_EGGFX, + MT_ARTISUPERHEAL, + MT_MISC4, + MT_MISC5, + MT_FIREBOMB, + MT_ARTITELEPORT, + MT_POD, + MT_PODGOO, + MT_PODGENERATOR, + MT_SPLASH, + MT_SPLASHBASE, + MT_LAVASPLASH, + MT_LAVASMOKE, + MT_SLUDGECHUNK, + MT_SLUDGESPLASH, + MT_SKULLHANG70, + MT_SKULLHANG60, + MT_SKULLHANG45, + MT_SKULLHANG35, + MT_CHANDELIER, + MT_SERPTORCH, + MT_SMALLPILLAR, + MT_STALAGMITESMALL, + MT_STALAGMITELARGE, + MT_STALACTITESMALL, + MT_STALACTITELARGE, + MT_MISC6, + MT_BARREL, + MT_MISC7, + MT_MISC8, + MT_MISC9, + MT_MISC10, + MT_MISC11, + MT_KEYGIZMOBLUE, + MT_KEYGIZMOGREEN, + MT_KEYGIZMOYELLOW, + MT_KEYGIZMOFLOAT, + MT_MISC12, + MT_VOLCANOBLAST, + MT_VOLCANOTBLAST, + MT_TELEGLITGEN, + MT_TELEGLITGEN2, + MT_TELEGLITTER, + MT_TELEGLITTER2, + MT_TFOG, + MT_TELEPORTMAN, + MT_STAFFPUFF, + MT_STAFFPUFF2, + MT_BEAKPUFF, + MT_MISC13, + MT_GAUNTLETPUFF1, + MT_GAUNTLETPUFF2, + MT_MISC14, + MT_BLASTERFX1, + MT_BLASTERSMOKE, + MT_RIPPER, + MT_BLASTERPUFF1, + MT_BLASTERPUFF2, + MT_WMACE, + MT_MACEFX1, + MT_MACEFX2, + MT_MACEFX3, + MT_MACEFX4, + MT_WSKULLROD, + MT_HORNRODFX1, + MT_HORNRODFX2, + MT_RAINPLR1, + MT_RAINPLR2, + MT_RAINPLR3, + MT_RAINPLR4, + MT_GOLDWANDFX1, + MT_GOLDWANDFX2, + MT_GOLDWANDPUFF1, + MT_GOLDWANDPUFF2, + MT_WPHOENIXROD, + MT_PHOENIXFX1, + MT_PHOENIXFX_REMOVED, // In Heretic 1.0, but removed. + MT_PHOENIXPUFF, + MT_PHOENIXFX2, + MT_MISC15, + MT_CRBOWFX1, + MT_CRBOWFX2, + MT_CRBOWFX3, + MT_CRBOWFX4, + MT_BLOOD, + MT_BLOODSPLATTER, + MT_PLAYER, + MT_BLOODYSKULL, + MT_CHICPLAYER, + MT_CHICKEN, + MT_FEATHER, + MT_MUMMY, + MT_MUMMYLEADER, + MT_MUMMYGHOST, + MT_MUMMYLEADERGHOST, + MT_MUMMYSOUL, + MT_MUMMYFX1, + MT_BEAST, + MT_BEASTBALL, + MT_BURNBALL, + MT_BURNBALLFB, + MT_PUFFY, + MT_SNAKE, + MT_SNAKEPRO_A, + MT_SNAKEPRO_B, + MT_HEAD, + MT_HEADFX1, + MT_HEADFX2, + MT_HEADFX3, + MT_WHIRLWIND, + MT_CLINK, + MT_WIZARD, + MT_WIZFX1, + MT_IMP, + MT_IMPLEADER, + MT_IMPCHUNK1, + MT_IMPCHUNK2, + MT_IMPBALL, + MT_KNIGHT, + MT_KNIGHTGHOST, + MT_KNIGHTAXE, + MT_REDAXE, + MT_SORCERER1, + MT_SRCRFX1, + MT_SORCERER2, + MT_SOR2FX1, + MT_SOR2FXSPARK, + MT_SOR2FX2, + MT_SOR2TELEFADE, + MT_MINOTAUR, + MT_MNTRFX1, + MT_MNTRFX2, + MT_MNTRFX3, + MT_AKYY, + MT_BKYY, + MT_CKEY, + MT_AMGWNDWIMPY, + MT_AMGWNDHEFTY, + MT_AMMACEWIMPY, + MT_AMMACEHEFTY, + MT_AMCBOWWIMPY, + MT_AMCBOWHEFTY, + MT_AMSKRDWIMPY, + MT_AMSKRDHEFTY, + MT_AMPHRDWIMPY, + MT_AMPHRDHEFTY, + MT_AMBLSRWIMPY, + MT_AMBLSRHEFTY, + MT_SOUNDWIND, + MT_SOUNDWATERFALL, + NUMMOBJTYPES +} mobjtype_t; + +typedef struct +{ + int doomednum; + int spawnstate; + int spawnhealth; + int seestate; + int seesound; + int reactiontime; + int attacksound; + int painstate; + int painchance; + int painsound; + int meleestate; + int missilestate; + int crashstate; + int deathstate; + int xdeathstate; + int deathsound; + int speed; + int radius; + int height; + int mass; + int damage; + int activesound; + int flags; + int flags2; +} mobjinfo_t; + +extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; + +#endif /* #ifndef HERETIC_INFO_H */ + diff --git a/games/NXDoom/src/heretic/m_random.c b/games/NXDoom/src/heretic/m_random.c new file mode 100644 index 00000000000..7d535b84852 --- /dev/null +++ b/games/NXDoom/src/heretic/m_random.c @@ -0,0 +1,76 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include "m_random.h" + +/* +=============== += += M_Random += += Returns a 0-255 number += +=============== +*/ + +const unsigned int rndtable[256] = { + 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, + 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36, + 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, + 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, + 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242, + 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0, + 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, + 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113, + 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75, + 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, + 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113, + 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241, + 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, + 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, + 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226, + 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, + 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, + 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136, + 120, 163, 236, 249 +}; + +int rndindex = 0; +int prndindex = 0; + +int P_Random(void) +{ + prndindex = (prndindex + 1) & 0xff; + return rndtable[prndindex]; +} + +int M_Random(void) +{ + rndindex = (rndindex + 1) & 0xff; + return rndtable[rndindex]; +} + +void M_ClearRandom(void) +{ + rndindex = prndindex = 0; +} + +// inspired by the same routine in Eternity, thanks haleyjd +int P_SubRandom (void) +{ + int r = P_Random(); + return r - P_Random(); +} diff --git a/games/NXDoom/src/heretic/m_random.h b/games/NXDoom/src/heretic/m_random.h new file mode 100644 index 00000000000..d7ec2d18790 --- /dev/null +++ b/games/NXDoom/src/heretic/m_random.h @@ -0,0 +1,37 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef HERETIC_M_RANDOM_H +#define HERETIC_M_RANDOM_H + +// Most damage defined using HITDICE +#define HITDICE(a) ((1+(P_Random()&7))*a) + +int M_Random(void); +// returns a number from 0 to 255 +int P_Random(void); +// as M_Random, but used only by the play simulation + +void M_ClearRandom(void); +// fix randoms for demos + +extern int rndindex; + +// Defined version of P_Random() - P_Random() +int P_SubRandom (void); + +#endif // HERETIC_M_RANDOM_H + diff --git a/games/NXDoom/src/heretic/mn_menu.c b/games/NXDoom/src/heretic/mn_menu.c new file mode 100644 index 00000000000..95cb62ce5c1 --- /dev/null +++ b/games/NXDoom/src/heretic/mn_menu.c @@ -0,0 +1,1824 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// MN_menu.c + +#include +#include + +#include "deh_str.h" +#include "doomdef.h" +#include "doomkeys.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_swap.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "r_local.h" +#include "s_sound.h" +#include "v_video.h" +#include "am_map.h" + +// Macros + +#define LEFT_DIR 0 +#define RIGHT_DIR 1 +#define ITEM_HEIGHT 20 +#define SELECTOR_XOFFSET (-28) +#define SELECTOR_YOFFSET (-1) +#define SLOTTEXTLEN 16 +#define ASCII_CURSOR '[' + +// Types + +typedef enum +{ + ITT_EMPTY, + ITT_EFUNC, + ITT_LRFUNC, + ITT_SETMENU, + ITT_INERT +} ItemType_t; + +typedef enum +{ + MENU_MAIN, + MENU_EPISODE, + MENU_SKILL, + MENU_OPTIONS, + MENU_OPTIONS2, + MENU_FILES, + MENU_LOAD, + MENU_SAVE, + MENU_NONE +} MenuType_t; + +typedef struct +{ + ItemType_t type; + const char *text; + boolean(*func) (int option); + int option; + MenuType_t menu; +} MenuItem_t; + +typedef struct +{ + int x; + int y; + void (*drawFunc) (void); + int itemCount; + MenuItem_t *items; + int oldItPos; + MenuType_t prevMenu; +} Menu_t; + +// Private Functions + +static void InitFonts(void); +static void SetMenu(MenuType_t menu); +static boolean SCNetCheck(int option); +static boolean SCQuitGame(int option); +static boolean SCEpisode(int option); +static boolean SCSkill(int option); +static boolean SCMouseSensi(int option); +static boolean SCSfxVolume(int option); +static boolean SCMusicVolume(int option); +static boolean SCScreenSize(int option); +static boolean SCLoadGame(int option); +static boolean SCSaveGame(int option); +static boolean SCMessages(int option); +static boolean SCEndGame(int option); +static boolean SCInfo(int option); +static void DrawMainMenu(void); +static void DrawEpisodeMenu(void); +static void DrawSkillMenu(void); +static void DrawOptionsMenu(void); +static void DrawOptions2Menu(void); +static void DrawFileSlots(Menu_t * menu); +static void DrawFilesMenu(void); +static void MN_DrawInfo(void); +static void DrawLoadMenu(void); +static void DrawSaveMenu(void); +static void DrawSlider(Menu_t * menu, int item, int width, int slot); +void MN_LoadSlotText(void); + + +// Public Data + +boolean MenuActive; +int InfoType; +boolean messageson; + +// Private Data + +static int FontABaseLump; +static int FontBBaseLump; +static int SkullBaseLump; +static Menu_t *CurrentMenu; +static int CurrentItPos; +static int MenuEpisode; +static int MenuTime; +static boolean soundchanged; + +boolean askforquit; +static int typeofask; +static boolean FileMenuKeySteal; +static boolean slottextloaded; +static boolean joypadsave; +static char SlotText[6][SLOTTEXTLEN + 2]; +static char oldSlotText[SLOTTEXTLEN + 2]; +static int SlotStatus[6]; +static int slotptr; +static int currentSlot; +static int quicksave; +static int quickload; + +static MenuItem_t MainItems[] = { + {ITT_EFUNC, "NEW GAME", SCNetCheck, 1, MENU_EPISODE}, + {ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS}, + {ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES}, + {ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE}, + {ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE} +}; + +static Menu_t MainMenu = { + 110, 56, + DrawMainMenu, + 5, MainItems, + 0, + MENU_NONE +}; + +static MenuItem_t EpisodeItems[] = { + {ITT_EFUNC, "CITY OF THE DAMNED", SCEpisode, 1, MENU_NONE}, + {ITT_EFUNC, "HELL'S MAW", SCEpisode, 2, MENU_NONE}, + {ITT_EFUNC, "THE DOME OF D'SPARIL", SCEpisode, 3, MENU_NONE}, + {ITT_EFUNC, "THE OSSUARY", SCEpisode, 4, MENU_NONE}, + {ITT_EFUNC, "THE STAGNANT DEMESNE", SCEpisode, 5, MENU_NONE} +}; + +static Menu_t EpisodeMenu = { + 80, 50, + DrawEpisodeMenu, + 3, EpisodeItems, + 0, + MENU_MAIN +}; + +static MenuItem_t FilesItems[] = { + {ITT_EFUNC, "LOAD GAME", SCNetCheck, 2, MENU_LOAD}, + {ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE} +}; + +static Menu_t FilesMenu = { + 110, 60, + DrawFilesMenu, + 2, FilesItems, + 0, + MENU_MAIN +}; + +static MenuItem_t LoadItems[] = { + {ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE} +}; + +static Menu_t LoadMenu = { + 70, 30, + DrawLoadMenu, + 6, LoadItems, + 0, + MENU_FILES +}; + +static MenuItem_t SaveItems[] = { + {ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE} +}; + +static Menu_t SaveMenu = { + 70, 30, + DrawSaveMenu, + 6, SaveItems, + 0, + MENU_FILES +}; + +static MenuItem_t SkillItems[] = { + {ITT_EFUNC, "THOU NEEDETH A WET-NURSE", SCSkill, sk_baby, MENU_NONE}, + {ITT_EFUNC, "YELLOWBELLIES-R-US", SCSkill, sk_easy, MENU_NONE}, + {ITT_EFUNC, "BRINGEST THEM ONETH", SCSkill, sk_medium, MENU_NONE}, + {ITT_EFUNC, "THOU ART A SMITE-MEISTER", SCSkill, sk_hard, MENU_NONE}, + {ITT_EFUNC, "BLACK PLAGUE POSSESSES THEE", + SCSkill, sk_nightmare, MENU_NONE} +}; + +static Menu_t SkillMenu = { + 38, 30, + DrawSkillMenu, + 5, SkillItems, + 2, + MENU_EPISODE +}; + +static MenuItem_t OptionsItems[] = { + {ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE}, + {ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE}, + {ITT_LRFUNC, "MOUSE SENSITIVITY", SCMouseSensi, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2} +}; + +static Menu_t OptionsMenu = { + 88, 30, + DrawOptionsMenu, + 5, OptionsItems, + 0, + MENU_MAIN +}; + +static MenuItem_t Options2Items[] = { + {ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE} +}; + +static Menu_t Options2Menu = { + 90, 20, + DrawOptions2Menu, + 6, Options2Items, + 0, + MENU_OPTIONS +}; + +static Menu_t *Menus[] = { + &MainMenu, + &EpisodeMenu, + &SkillMenu, + &OptionsMenu, + &Options2Menu, + &FilesMenu, + &LoadMenu, + &SaveMenu +}; + +//--------------------------------------------------------------------------- +// +// PROC MN_Init +// +//--------------------------------------------------------------------------- + +void MN_Init(void) +{ + InitFonts(); + MenuActive = false; + messageson = true; + SkullBaseLump = W_GetNumForName(DEH_String("M_SKL00")); + + if (gamemode == retail) + { // Add episodes 4 and 5 to the menu + EpisodeMenu.itemCount = 5; + EpisodeMenu.y -= ITEM_HEIGHT; + } +} + +//--------------------------------------------------------------------------- +// +// PROC InitFonts +// +//--------------------------------------------------------------------------- + +static void InitFonts(void) +{ + FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; + FontBBaseLump = W_GetNumForName(DEH_String("FONTB_S")) + 1; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrTextA +// +// Draw text using font A. +// +//--------------------------------------------------------------------------- + +void MN_DrTextA(const char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 5; + } + else + { + p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_TextAWidth +// +// Returns the pixel width of a string using font A. +// +//--------------------------------------------------------------------------- + +int MN_TextAWidth(const char *text) +{ + char c; + int width; + patch_t *p; + + width = 0; + while ((c = *text++) != 0) + { + if (c < 33) + { + width += 5; + } + else + { + p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + width += SHORT(p->width) - 1; + } + } + return (width); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrTextB +// +// Draw text using font B. +// +//--------------------------------------------------------------------------- + +void MN_DrTextB(const char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 8; + } + else + { + p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_TextBWidth +// +// Returns the pixel width of a string using font B. +// +//--------------------------------------------------------------------------- + +int MN_TextBWidth(const char *text) +{ + char c; + int width; + patch_t *p; + + width = 0; + while ((c = *text++) != 0) + { + if (c < 33) + { + width += 5; + } + else + { + p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); + width += SHORT(p->width) - 1; + } + } + return (width); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_Ticker +// +//--------------------------------------------------------------------------- + +void MN_Ticker(void) +{ + if (MenuActive == false) + { + return; + } + MenuTime++; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_Drawer +// +//--------------------------------------------------------------------------- + +const char *QuitEndMsg[] = { + "ARE YOU SURE YOU WANT TO QUIT?", + "ARE YOU SURE YOU WANT TO END THE GAME?", + "DO YOU WANT TO QUICKSAVE THE GAME NAMED", + "DO YOU WANT TO QUICKLOAD THE GAME NAMED" +}; + +void MN_Drawer(void) +{ + int i; + int x; + int y; + MenuItem_t *item; + const char *message; + const char *selName; + + if (MenuActive == false) + { + if (askforquit) + { + message = DEH_String(QuitEndMsg[typeofask - 1]); + + MN_DrTextA(message, 160 - MN_TextAWidth(message) / 2, 80); + if (typeofask == 3) + { + MN_DrTextA(SlotText[quicksave - 1], 160 - + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + MN_DrTextA(DEH_String("?"), 160 + + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + } + if (typeofask == 4) + { + MN_DrTextA(SlotText[quickload - 1], 160 - + MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); + MN_DrTextA(DEH_String("?"), 160 + + MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); + } + UpdateState |= I_FULLSCRN; + } + return; + } + else + { + UpdateState |= I_FULLSCRN; + if (InfoType) + { + MN_DrawInfo(); + return; + } + if (screenblocks < 10) + { + BorderNeedRefresh = true; + } + if (CurrentMenu->drawFunc != NULL) + { + CurrentMenu->drawFunc(); + } + x = CurrentMenu->x; + y = CurrentMenu->y; + item = CurrentMenu->items; + for (i = 0; i < CurrentMenu->itemCount; i++) + { + if (item->type != ITT_EMPTY && item->text) + { + MN_DrTextB(DEH_String(item->text), x, y); + } + y += ITEM_HEIGHT; + item++; + } + y = CurrentMenu->y + (CurrentItPos * ITEM_HEIGHT) + SELECTOR_YOFFSET; + selName = DEH_String(MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2"); + V_DrawPatch(x + SELECTOR_XOFFSET, y, + W_CacheLumpName(selName, PU_CACHE)); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawMainMenu +// +//--------------------------------------------------------------------------- + +static void DrawMainMenu(void) +{ + int frame; + + frame = (MenuTime / 3) % 18; + V_DrawPatch(88, 0, W_CacheLumpName(DEH_String("M_HTIC"), PU_CACHE)); + V_DrawPatch(40, 10, W_CacheLumpNum(SkullBaseLump + (17 - frame), + PU_CACHE)); + V_DrawPatch(232, 10, W_CacheLumpNum(SkullBaseLump + frame, PU_CACHE)); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawEpisodeMenu +// +//--------------------------------------------------------------------------- + +static void DrawEpisodeMenu(void) +{ +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSkillMenu +// +//--------------------------------------------------------------------------- + +static void DrawSkillMenu(void) +{ +} + +//--------------------------------------------------------------------------- +// +// PROC DrawFilesMenu +// +//--------------------------------------------------------------------------- + +static void DrawFilesMenu(void) +{ +// clear out the quicksave/quickload stuff + quicksave = 0; + quickload = 0; + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawLoadMenu +// +//--------------------------------------------------------------------------- + +static void DrawLoadMenu(void) +{ + const char *title; + + title = DEH_String("LOAD GAME"); + + MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10); + if (!slottextloaded) + { + MN_LoadSlotText(); + } + DrawFileSlots(&LoadMenu); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSaveMenu +// +//--------------------------------------------------------------------------- + +static void DrawSaveMenu(void) +{ + const char *title; + + title = DEH_String("SAVE GAME"); + + MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10); + if (!slottextloaded) + { + MN_LoadSlotText(); + } + DrawFileSlots(&SaveMenu); +} + +//=========================================================================== +// +// MN_LoadSlotText +// +// Loads in the text message for each slot +//=========================================================================== + +void MN_LoadSlotText(void) +{ + FILE *fp; + int i; + char *filename; + + for (i = 0; i < 6; i++) + { + int retval; + filename = SV_Filename(i); + fp = M_fopen(filename, "rb+"); + free(filename); + + if (!fp) + { + SlotText[i][0] = 0; // empty the string + SlotStatus[i] = 0; + continue; + } + retval = fread(&SlotText[i], 1, SLOTTEXTLEN, fp); + fclose(fp); + SlotStatus[i] = retval == SLOTTEXTLEN; + } + slottextloaded = true; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawFileSlots +// +//--------------------------------------------------------------------------- + +static void DrawFileSlots(Menu_t * menu) +{ + int i; + int x; + int y; + + x = menu->x; + y = menu->y; + for (i = 0; i < 6; i++) + { + V_DrawPatch(x, y, W_CacheLumpName(DEH_String("M_FSLOT"), PU_CACHE)); + if (SlotStatus[i]) + { + MN_DrTextA(SlotText[i], x + 5, y + 5); + } + y += ITEM_HEIGHT; + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawOptionsMenu +// +//--------------------------------------------------------------------------- + +static void DrawOptionsMenu(void) +{ + if (messageson) + { + MN_DrTextB(DEH_String("ON"), 196, 50); + } + else + { + MN_DrTextB(DEH_String("OFF"), 196, 50); + } + DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawOptions2Menu +// +//--------------------------------------------------------------------------- + +static void DrawOptions2Menu(void) +{ + DrawSlider(&Options2Menu, 1, 9, screenblocks - 3); + DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume); + DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume); +} + +//--------------------------------------------------------------------------- +// +// PROC SCNetCheck +// +//--------------------------------------------------------------------------- + +static boolean SCNetCheck(int option) +{ + if (!netgame) + { // okay to go into the menu + return true; + } + switch (option) + { + case 1: + P_SetMessage(&players[consoleplayer], + "YOU CAN'T START A NEW GAME IN NETPLAY!", true); + break; + case 2: + P_SetMessage(&players[consoleplayer], + "YOU CAN'T LOAD A GAME IN NETPLAY!", true); + break; + default: + break; + } + MenuActive = false; + return false; +} + +//--------------------------------------------------------------------------- +// +// PROC SCQuitGame +// +//--------------------------------------------------------------------------- + +static boolean SCQuitGame(int option) +{ + MenuActive = false; + askforquit = true; + typeofask = 1; //quit game + if (!netgame && !demoplayback) + { + paused = true; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCEndGame +// +//--------------------------------------------------------------------------- + +static boolean SCEndGame(int option) +{ + if (demoplayback || netgame) + { + return false; + } + MenuActive = false; + askforquit = true; + typeofask = 2; //endgame + if (!netgame && !demoplayback) + { + paused = true; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCMessages +// +//--------------------------------------------------------------------------- + +static boolean SCMessages(int option) +{ + messageson ^= 1; + if (messageson) + { + P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES ON"), true); + } + else + { + P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES OFF"), true); + } + S_StartSound(NULL, sfx_chat); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCLoadGame +// +//--------------------------------------------------------------------------- + +static boolean SCLoadGame(int option) +{ + char *filename; + + if (!SlotStatus[option]) + { // slot's empty...don't try and load + return false; + } + + filename = SV_Filename(option); + G_LoadGame(filename); + free(filename); + + MN_DeactivateMenu(); + BorderNeedRefresh = true; + if (quickload == -1) + { + quickload = option + 1; + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; + } + return true; +} + +// +// Generate a default save slot name when the user saves to +// an empty slot via the joypad. +// +static void SetDefaultSaveName(int slot) +{ + // map from IWAD or PWAD? + if (W_IsIWADLump(maplumpinfo) && strcmp(savegamedir, "")) + { + M_snprintf(SlotText[slot], SLOTTEXTLEN, + "%s", maplumpinfo->name); + } + else + { + char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo)); + char *ext = strrchr(wadname, '.'); + + if (ext != NULL) + { + *ext = '\0'; + } + + M_snprintf(SlotText[slot], SLOTTEXTLEN, + "%s (%s)", maplumpinfo->name, + wadname); + free(wadname); + } + M_ForceUppercase(SlotText[slot]); + joypadsave = false; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSaveGame +// +//--------------------------------------------------------------------------- + +static boolean SCSaveGame(int option) +{ + char *ptr; + + if (!FileMenuKeySteal) + { + int x, y; + + FileMenuKeySteal = true; + // We need to activate the text input interface to type the save + // game name: + x = SaveMenu.x + 1; + y = SaveMenu.y + 1 + option * ITEM_HEIGHT; + I_StartTextInput(x, y, x + 190, y + ITEM_HEIGHT - 2); + + M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText)); + ptr = SlotText[option]; + + if (!strcmp(ptr, "") && joypadsave) + { + SetDefaultSaveName(option); + } + + while (*ptr) + { + ptr++; + } + *ptr = '['; + *(ptr + 1) = 0; + SlotStatus[option]++; + currentSlot = option; + slotptr = ptr - SlotText[option]; + return false; + } + else + { + G_SaveGame(option, SlotText[option]); + FileMenuKeySteal = false; + I_StopTextInput(); + MN_DeactivateMenu(); + } + BorderNeedRefresh = true; + if (quicksave == -1) + { + quicksave = option + 1; + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCEpisode +// +//--------------------------------------------------------------------------- + +static boolean SCEpisode(int option) +{ + if (gamemode == shareware && option > 1) + { + P_SetMessage(&players[consoleplayer], + "ONLY AVAILABLE IN THE REGISTERED VERSION", true); + } + else + { + MenuEpisode = option; + SetMenu(MENU_SKILL); + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSkill +// +//--------------------------------------------------------------------------- + +static boolean SCSkill(int option) +{ + G_DeferedInitNew(option, MenuEpisode, 1); + MN_DeactivateMenu(); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCMouseSensi +// +//--------------------------------------------------------------------------- + +static boolean SCMouseSensi(int option) +{ + if (option == RIGHT_DIR) + { + if (mouseSensitivity < 9) + { + mouseSensitivity++; + } + } + else if (mouseSensitivity) + { + mouseSensitivity--; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSfxVolume +// +//--------------------------------------------------------------------------- + +static boolean SCSfxVolume(int option) +{ + if (option == RIGHT_DIR) + { + if (snd_MaxVolume < 15) + { + snd_MaxVolume++; + } + } + else if (snd_MaxVolume) + { + snd_MaxVolume--; + } + S_SetMaxVolume(false); // don't recalc the sound curve, yet + soundchanged = true; // we'll set it when we leave the menu + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCMusicVolume +// +//--------------------------------------------------------------------------- + +static boolean SCMusicVolume(int option) +{ + if (option == RIGHT_DIR) + { + if (snd_MusicVolume < 15) + { + snd_MusicVolume++; + } + } + else if (snd_MusicVolume) + { + snd_MusicVolume--; + } + S_SetMusicVolume(); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCScreenSize +// +//--------------------------------------------------------------------------- + +static boolean SCScreenSize(int option) +{ + if (option == RIGHT_DIR) + { + if (screenblocks < 11) + { + screenblocks++; + } + } + else if (screenblocks > 3) + { + screenblocks--; + } + R_SetViewSize(screenblocks, detailLevel); + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC SCInfo +// +//--------------------------------------------------------------------------- + +static boolean SCInfo(int option) +{ + InfoType = 1; + S_StartSound(NULL, sfx_dorcls); + if (!netgame && !demoplayback) + { + paused = true; + } + return true; +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_Responder +// +//--------------------------------------------------------------------------- + +boolean MN_Responder(event_t * event) +{ + int charTyped; + int key; + int i; + MenuItem_t *item; + char *textBuffer; + int dir; + + // In testcontrols mode, none of the function keys should do anything + // - the only key is escape to quit. + + if (testcontrols) + { + if (event->type == ev_quit + || (event->type == ev_keydown + && (event->data1 == key_menu_activate + || event->data1 == key_menu_quit))) + { + I_Quit(); + return true; + } + + return false; + } + + // "close" button pressed on window? + if (event->type == ev_quit) + { + // First click on close = bring up quit confirm message. + // Second click = confirm quit. + + if (!MenuActive && askforquit && typeofask == 1) + { + G_CheckDemoStatus(); + I_Quit(); + } + else + { + SCQuitGame(0); + S_StartSound(NULL, sfx_chat); + } + return true; + } + + charTyped = 0; + key = -1; + + if (event->type == ev_joystick) + { + // Simulate key presses from joystick events to interact with the menu. + + if (MenuActive) + { + if (JOY_GET_DPAD(event->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_DPAD(event->data6); + } + else if (JOY_GET_LSTICK(event->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_LSTICK(event->data6); + } + else + { + dir = JOY_GET_RSTICK(event->data6); + } + + if (dir & JOY_DIR_UP) + { + key = key_menu_up; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_DOWN) + { + key = key_menu_down; + joywait = I_GetTime() + 5; + } + if (dir & JOY_DIR_LEFT) + { + key = key_menu_left; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_RIGHT) + { + key = key_menu_right; + joywait = I_GetTime() + 5; + } + +#define JOY_BUTTON_MAPPED(x) ((x) >= 0) +#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (event->data1 & (1 << (x))) != 0) + + if (JOY_BUTTON_PRESSED(joybfire)) + { + // Simulate pressing "Enter" when we are supplying a save slot name + if (FileMenuKeySteal) + { + key = KEY_ENTER; + } + else + { + // if selecting a save slot via joypad, set a flag + if (CurrentMenu == &SaveMenu) + { + joypadsave = true; + } + key = key_menu_forward; + } + joywait = I_GetTime() + 5; + } + if (JOY_BUTTON_PRESSED(joybuse)) + { + // If user was entering a save name, back out + if (FileMenuKeySteal) + { + key = KEY_ESCAPE; + } + else + { + key = key_menu_back; + } + joywait = I_GetTime() + 5; + } + } + else if (askforquit) + { + if (JOY_BUTTON_PRESSED(joybfire)) + { + // Simulate a 'Y' keypress + key = key_menu_confirm; + joywait = I_GetTime() + 5; + } + if (JOY_BUTTON_PRESSED(joybuse)) + { + // Simulate a 'N' keypress + key = key_menu_abort; + joywait = I_GetTime() + 5; + } + } + if (JOY_BUTTON_PRESSED(joybmenu)) + { + MN_ActivateMenu(); + joywait = I_GetTime() + 5; + return true; + } + } + + if (event->type != ev_keydown && key == -1) + { + return false; + } + + if (event->type == ev_keydown) + { + key = event->data1; + charTyped = event->data2; + } + + if (InfoType) + { + if (gamemode == shareware) + { + InfoType = (InfoType + 1) % 5; + } + else + { + InfoType = (InfoType + 1) % 4; + } + if (key == KEY_ESCAPE) + { + InfoType = 0; + } + if (!InfoType) + { + paused = false; + MN_DeactivateMenu(); + SB_state = -1; //refresh the statbar + BorderNeedRefresh = true; + } + S_StartSound(NULL, sfx_dorcls); + return (true); //make the info screen eat the keypress + } + + if ((ravpic && key == KEY_F1) || + (key != 0 && key == key_menu_screenshot)) + { + G_ScreenShot(); + return (true); + } + + if (askforquit) + { + if (key == key_menu_confirm) + { + switch (typeofask) + { + case 1: + G_CheckDemoStatus(); + I_Quit(); + return false; + + case 2: + players[consoleplayer].messageTics = 0; + //set the msg to be cleared + players[consoleplayer].message = NULL; + paused = false; + I_SetPalette(W_CacheLumpName + ("PLAYPAL", PU_CACHE)); + D_StartTitle(); // go to intro/demo mode. + break; + + case 3: + P_SetMessage(&players[consoleplayer], + "QUICKSAVING....", false); + FileMenuKeySteal = true; + SCSaveGame(quicksave - 1); + BorderNeedRefresh = true; + break; + + case 4: + P_SetMessage(&players[consoleplayer], + "QUICKLOADING....", false); + SCLoadGame(quickload - 1); + BorderNeedRefresh = true; + break; + + default: + break; + } + + askforquit = false; + typeofask = 0; + + return true; + } + else if (key == key_menu_abort || key == KEY_ESCAPE) + { + players[consoleplayer].messageTics = 1; //set the msg to be cleared + askforquit = false; + typeofask = 0; + paused = false; + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; + return true; + } + + return false; // don't let the keys filter thru + } + + if (!MenuActive && !chatmodeon) + { + if (key == key_menu_decscreen) + { + if (automapactive) + { // Don't screen size in automap + return (false); + } + SCScreenSize(LEFT_DIR); + S_StartSound(NULL, sfx_keyup); + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + return (true); + } + else if (key == key_menu_incscreen) + { + if (automapactive) + { // Don't screen size in automap + return (false); + } + SCScreenSize(RIGHT_DIR); + S_StartSound(NULL, sfx_keyup); + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + return (true); + } + else if (key == key_menu_help) // F1 + { + SCInfo(0); // start up info screens + MenuActive = true; + return (true); + } + else if (key == key_menu_save) // F2 (save game) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &SaveMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + } + return true; + } + else if (key == key_menu_load) // F3 (load game) + { + if (SCNetCheck(2)) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &LoadMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + } + return true; + } + else if (key == key_menu_volume) // F4 (volume) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &Options2Menu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + return true; + } + else if (key == key_menu_detail) // F5 (detail) + { + // F5 isn't used in Heretic. (detail level) + return true; + } + else if (key == key_menu_qsave) // F6 (quicksave) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + if (!quicksave || quicksave == -1) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &SaveMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + quicksave = -1; + P_SetMessage(&players[consoleplayer], + "CHOOSE A QUICKSAVE SLOT", true); + } + else + { + askforquit = true; + typeofask = 3; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_chat); + } + } + return true; + } + else if (key == key_menu_endgame) // F7 (end game) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + S_StartSound(NULL, sfx_chat); + SCEndGame(0); + } + return true; + } + else if (key == key_menu_messages) // F8 (toggle messages) + { + SCMessages(0); + return true; + } + else if (key == key_menu_qload) // F9 (quickload) + { + if (!quickload || quickload == -1) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &LoadMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed + quickload = -1; + P_SetMessage(&players[consoleplayer], + "CHOOSE A QUICKLOAD SLOT", true); + } + else + { + askforquit = true; + if (!netgame && !demoplayback) + { + paused = true; + } + typeofask = 4; + S_StartSound(NULL, sfx_chat); + } + return true; + } + else if (key == key_menu_quit) // F10 (quit) + { + if (gamestate == GS_LEVEL) + { + SCQuitGame(0); + S_StartSound(NULL, sfx_chat); + } + return true; + } + else if (key == key_menu_gamma) // F11 (gamma correction) + { + usegamma++; + if (usegamma > 4) + { + usegamma = 0; + } + I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE)); + return true; + } + + } + + if (!MenuActive) + { + if (key == key_menu_activate || gamestate == GS_DEMOSCREEN || demoplayback) + { + MN_ActivateMenu(); + return (true); + } + return (false); + } + if (!FileMenuKeySteal) + { + item = &CurrentMenu->items[CurrentItPos]; + + if (key == key_menu_down) // Next menu item + { + do + { + if (CurrentItPos + 1 > CurrentMenu->itemCount - 1) + { + CurrentItPos = 0; + } + else + { + CurrentItPos++; + } + } + while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); + S_StartSound(NULL, sfx_switch); + return (true); + } + else if (key == key_menu_up) // Previous menu item + { + do + { + if (CurrentItPos == 0) + { + CurrentItPos = CurrentMenu->itemCount - 1; + } + else + { + CurrentItPos--; + } + } + while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); + S_StartSound(NULL, sfx_switch); + return (true); + } + else if (key == key_menu_left) // Slider left + { + if (item->type == ITT_LRFUNC && item->func != NULL) + { + item->func(LEFT_DIR); + S_StartSound(NULL, sfx_keyup); + } + return (true); + } + else if (key == key_menu_right) // Slider right + { + if (item->type == ITT_LRFUNC && item->func != NULL) + { + item->func(RIGHT_DIR); + S_StartSound(NULL, sfx_keyup); + } + return (true); + } + else if (key == key_menu_forward) // Activate item (enter) + { + if (item->type == ITT_SETMENU) + { + SetMenu(item->menu); + } + else if (item->func != NULL) + { + CurrentMenu->oldItPos = CurrentItPos; + if (item->type == ITT_LRFUNC) + { + item->func(RIGHT_DIR); + } + else if (item->type == ITT_EFUNC) + { + if (item->func(item->option)) + { + if (item->menu != MENU_NONE) + { + SetMenu(item->menu); + } + } + } + } + S_StartSound(NULL, sfx_dorcls); + return (true); + } + else if (key == key_menu_activate) // Toggle menu + { + MN_DeactivateMenu(); + return (true); + } + else if (key == key_menu_back) // Go back to previous menu + { + S_StartSound(NULL, sfx_switch); + if (CurrentMenu->prevMenu == MENU_NONE) + { + MN_DeactivateMenu(); + } + else + { + SetMenu(CurrentMenu->prevMenu); + } + return (true); + } + else if (charTyped != 0) + { + // Jump to menu item based on first letter: + + for (i = 0; i < CurrentMenu->itemCount; i++) + { + if (CurrentMenu->items[i].text) + { + if (toupper(charTyped) + == toupper(DEH_String(CurrentMenu->items[i].text)[0])) + { + CurrentItPos = i; + return (true); + } + } + } + } + + return (false); + } + else + { + // Editing file names + // When typing a savegame name, we use the fully shifted and + // translated input value from event->data3. + charTyped = event->data3; + + textBuffer = &SlotText[currentSlot][slotptr]; + if (key == KEY_BACKSPACE) + { + if (slotptr) + { + *textBuffer = 0; + slotptr--; + textBuffer = &SlotText[currentSlot][slotptr]; + *textBuffer = ASCII_CURSOR; + } + return (true); + } + if (key == KEY_ESCAPE) + { + memset(SlotText[currentSlot], 0, SLOTTEXTLEN + 2); + M_StringCopy(SlotText[currentSlot], oldSlotText, + sizeof(SlotText[currentSlot])); + SlotStatus[currentSlot]--; + MN_DeactivateMenu(); + return (true); + } + if (key == KEY_ENTER) + { + SlotText[currentSlot][slotptr] = 0; // clear the cursor + item = &CurrentMenu->items[CurrentItPos]; + CurrentMenu->oldItPos = CurrentItPos; + if (item->type == ITT_EFUNC) + { + item->func(item->option); + if (item->menu != MENU_NONE) + { + SetMenu(item->menu); + } + } + return (true); + } + if (slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE) + { + if (isalpha(charTyped)) + { + *textBuffer++ = toupper(charTyped); + *textBuffer = ASCII_CURSOR; + slotptr++; + return (true); + } + if (isdigit(charTyped) || charTyped == ' ' + || charTyped == ',' || charTyped == '.' || charTyped == '-' + || charTyped == '!') + { + *textBuffer++ = charTyped; + *textBuffer = ASCII_CURSOR; + slotptr++; + return (true); + } + } + return (true); + } + return (false); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_ActivateMenu +// +//--------------------------------------------------------------------------- + +void MN_ActivateMenu(void) +{ + if (MenuActive) + { + return; + } + if (paused) + { + S_ResumeSound(); + } + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &MainMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, sfx_dorcls); + slottextloaded = false; //reload the slot text, when needed +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DeactivateMenu +// +//--------------------------------------------------------------------------- + +void MN_DeactivateMenu(void) +{ + if (CurrentMenu != NULL) + { + CurrentMenu->oldItPos = CurrentItPos; + } + MenuActive = false; + if (FileMenuKeySteal) + { + I_StopTextInput(); + } + if (!netgame) + { + paused = false; + } + S_StartSound(NULL, sfx_dorcls); + if (soundchanged) + { + S_SetMaxVolume(true); //recalc the sound curve + soundchanged = false; + } + players[consoleplayer].message = NULL; + players[consoleplayer].messageTics = 1; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrawInfo +// +//--------------------------------------------------------------------------- + +void MN_DrawInfo(void) +{ + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + V_DrawRawScreen(W_CacheLumpNum(W_GetNumForName("TITLE") + InfoType, + PU_CACHE)); +// V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType, +// PU_CACHE)); +} + + +//--------------------------------------------------------------------------- +// +// PROC SetMenu +// +//--------------------------------------------------------------------------- + +static void SetMenu(MenuType_t menu) +{ + CurrentMenu->oldItPos = CurrentItPos; + CurrentMenu = Menus[menu]; + CurrentItPos = CurrentMenu->oldItPos; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSlider +// +//--------------------------------------------------------------------------- + +static void DrawSlider(Menu_t * menu, int item, int width, int slot) +{ + int x; + int y; + int x2; + int count; + + x = menu->x + 24; + y = menu->y + 2 + (item * ITEM_HEIGHT); + V_DrawPatch(x - 32, y, W_CacheLumpName(DEH_String("M_SLDLT"), PU_CACHE)); + for (x2 = x, count = width; count--; x2 += 8) + { + V_DrawPatch(x2, y, W_CacheLumpName(DEH_String(count & 1 ? "M_SLDMD1" + : "M_SLDMD2"), PU_CACHE)); + } + V_DrawPatch(x2, y, W_CacheLumpName(DEH_String("M_SLDRT"), PU_CACHE)); + V_DrawPatch(x + 4 + slot * 8, y + 7, + W_CacheLumpName(DEH_String("M_SLDKB"), PU_CACHE)); +} diff --git a/games/NXDoom/src/heretic/p_action.h b/games/NXDoom/src/heretic/p_action.h new file mode 100644 index 00000000000..8bb87071ca2 --- /dev/null +++ b/games/NXDoom/src/heretic/p_action.h @@ -0,0 +1,151 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// External definitions for action pointer functions. +// + +#ifndef HERETIC_P_ACTION_H +#define HERETIC_P_ACTION_H + +void A_FreeTargMobj(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_RestoreSpecialThing1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_RestoreSpecialThing2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_HideThing(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_UnHideThing(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_RestoreArtifact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Scream(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Explode(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_PodPain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_RemovePod(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MakePod(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_InitKeyGizmo(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_VolcanoSet(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_VolcanoBlast(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BeastPuff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_VolcBallImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SpawnTeleGlitter(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SpawnTeleGlitter2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_AccTeleGlitter(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Light0(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_WeaponReady(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Lower(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Raise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_StaffAttackPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ReFire(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_StaffAttackPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BeakReady(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BeakRaise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BeakAttackPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BeakAttackPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_GauntletAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireBlasterPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireBlasterPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SpawnRippers(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireMacePL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireMacePL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MacePL1Check(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MaceBallImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MaceBallImpact2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_DeathBallImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireSkullRodPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireSkullRodPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SkullRodPL2Seek(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_AddPlayerRain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_HideInCeiling(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SkullRodStorm(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_RainImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireGoldWandPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireGoldWandPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FirePhoenixPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_InitPhoenixPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FirePhoenixPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ShutdownPhoenixPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_PhoenixPuff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_RemovedPhoenixFunc(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FlameEnd(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FloatPuff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireCrossbowPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FireCrossbowPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BoltSpark(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Pain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_NoBlocking(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_AddPlayerCorpse(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SkullPop(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FlameSnd(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_CheckBurnGone(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_CheckSkullFloor(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_CheckSkullDone(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Feathers(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ChicLook(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ChicChase(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ChicPain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_FaceTarget(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ChicAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Look(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Chase(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MummyAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MummyAttack2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MummySoul(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ContMobjSound(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MummyFX1Seek(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BeastAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SnakeAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SnakeAttack2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_HeadAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BossDeath(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_HeadIceImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_HeadFireGrow(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_WhirlwindSeek(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ClinkAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_WizAtk1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_WizAtk2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_WizAtk3(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_GhostOff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpMeAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpMsAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpMsAttack2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpDeath(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpXDeath1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpXDeath2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ImpExplode(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_KnightAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_DripBlood(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Sor1Chase(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Sor1Pain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Srcr1Attack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorZap(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorcererRise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorRise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorSightSnd(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Srcr2Decide(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Srcr2Attack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Sor2DthInit(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorDSph(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_Sor2DthLoop(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorDExp(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_SorDBon(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_BlueSpark(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_GenWizard(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MinotaurAtk1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MinotaurDecide(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MinotaurAtk2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MinotaurAtk3(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MinotaurCharge(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_MntrFloorFire(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); +void A_ESound(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); + +#endif /* #ifndef HERETIC_P_ACTION_H */ + diff --git a/games/NXDoom/src/heretic/p_ceilng.c b/games/NXDoom/src/heretic/p_ceilng.c new file mode 100644 index 00000000000..c37d3973275 --- /dev/null +++ b/games/NXDoom/src/heretic/p_ceilng.c @@ -0,0 +1,256 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include "doomdef.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +//================================================================== +//================================================================== +// +// CEILINGS +// +//================================================================== +//================================================================== + +ceiling_t *activeceilings[MAXCEILINGS]; + +//================================================================== +// +// T_MoveCeiling +// +//================================================================== +void T_MoveCeiling(thinker_t *thinker) +{ + ceiling_t *ceiling = (ceiling_t *) thinker; + result_e res; + + switch (ceiling->direction) + { + case 0: // IN STASIS + break; + case 1: // UP + res = T_MovePlane(ceiling->sector, ceiling->speed, + ceiling->topheight, false, 1, + ceiling->direction); + if (!(leveltime & 7)) + S_StartSound(&ceiling->sector->soundorg, + sfx_dormov); + if (res == pastdest) + switch (ceiling->type) + { + case raiseToHighest: + P_RemoveActiveCeiling(ceiling); + break; + case fastCrushAndRaise: + case crushAndRaise: + ceiling->direction = -1; + break; + default: + break; + } + break; + case -1: // DOWN + res = T_MovePlane(ceiling->sector, ceiling->speed, + ceiling->bottomheight, ceiling->crush, 1, + ceiling->direction); + if (!(leveltime & 7)) + S_StartSound(&ceiling->sector->soundorg, + sfx_dormov); + if (res == pastdest) + switch (ceiling->type) + { + case crushAndRaise: + ceiling->speed = CEILSPEED; + case fastCrushAndRaise: + ceiling->direction = 1; + break; + case lowerAndCrush: + case lowerToFloor: + P_RemoveActiveCeiling(ceiling); + break; + default: + break; + } + else if (res == crushed) + switch (ceiling->type) + { + case crushAndRaise: + case lowerAndCrush: + ceiling->speed = CEILSPEED / 8; + break; + default: + break; + } + break; + } +} + +//================================================================== +// +// EV_DoCeiling +// Move a ceiling up/down and all around! +// +//================================================================== +int EV_DoCeiling(line_t * line, ceiling_e type) +{ + int secnum, rtn; + sector_t *sec; + ceiling_t *ceiling; + + secnum = -1; + rtn = 0; + + // + // Reactivate in-stasis ceilings...for certain types. + // + switch (type) + { + case fastCrushAndRaise: + case crushAndRaise: + P_ActivateInStasisCeiling(line); + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + // + // new door thinker + // + rtn = 1; + ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0); + P_AddThinker(&ceiling->thinker); + sec->specialdata = ceiling; + ceiling->thinker.function = T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = false; + switch (type) + { + case fastCrushAndRaise: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT); + ceiling->direction = -1; + ceiling->speed = CEILSPEED * 2; + break; + case crushAndRaise: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + case lowerAndCrush: + case lowerToFloor: + ceiling->bottomheight = sec->floorheight; + if (type != lowerToFloor) + ceiling->bottomheight += 8 * FRACUNIT; + ceiling->direction = -1; + ceiling->speed = CEILSPEED; + break; + case raiseToHighest: + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + ceiling->speed = CEILSPEED; + break; + } + + ceiling->tag = sec->tag; + ceiling->type = type; + P_AddActiveCeiling(ceiling); + } + return rtn; +} + +//================================================================== +// +// Add an active ceiling +// +//================================================================== +void P_AddActiveCeiling(ceiling_t * c) +{ + int i; + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] == NULL) + { + activeceilings[i] = c; + return; + } +} + +//================================================================== +// +// Remove a ceiling's thinker +// +//================================================================== +void P_RemoveActiveCeiling(ceiling_t * c) +{ + int i; + + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] == c) + { + activeceilings[i]->sector->specialdata = NULL; + P_RemoveThinker(&activeceilings[i]->thinker); + activeceilings[i] = NULL; + break; + } +} + +//================================================================== +// +// Restart a ceiling that's in-stasis +// +//================================================================== +void P_ActivateInStasisCeiling(line_t * line) +{ + int i; + + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && + (activeceilings[i]->direction == 0)) + { + activeceilings[i]->direction = activeceilings[i]->olddirection; + activeceilings[i]->thinker.function = T_MoveCeiling; + } +} + +//================================================================== +// +// EV_CeilingCrushStop +// Stop a ceiling from crushing! +// +//================================================================== +int EV_CeilingCrushStop(line_t * line) +{ + int i; + int rtn; + + rtn = 0; + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && + (activeceilings[i]->direction != 0)) + { + activeceilings[i]->olddirection = activeceilings[i]->direction; + activeceilings[i]->thinker.function = NULL; + activeceilings[i]->direction = 0; // in-stasis + rtn = 1; + } + + return rtn; +} diff --git a/games/NXDoom/src/heretic/p_doors.c b/games/NXDoom/src/heretic/p_doors.c new file mode 100644 index 00000000000..3cd40373538 --- /dev/null +++ b/games/NXDoom/src/heretic/p_doors.c @@ -0,0 +1,380 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_doors.c + +#include "doomdef.h" +#include "deh_str.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +//================================================================== +//================================================================== +// +// VERTICAL DOORS +// +//================================================================== +//================================================================== + +//================================================================== +// +// T_VerticalDoor +// +//================================================================== +void T_VerticalDoor(thinker_t *thinker) +{ + vldoor_t *door = (vldoor_t *) thinker; + result_e res; + + switch (door->direction) + { + case 0: // WAITING + if (!--door->topcountdown) + switch (door->type) + { + case vld_normal: + door->direction = -1; // time to go back down + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + case vld_close30ThenOpen: + door->direction = 1; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + default: + break; + } + break; + case 2: // INITIAL WAIT + if (!--door->topcountdown) + { + switch (door->type) + { + case vld_raiseIn5Mins: + door->direction = 1; + door->type = vld_normal; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + default: + break; + } + } + break; + case -1: // DOWN + res = T_MovePlane(door->sector, door->speed, + door->sector->floorheight, false, 1, + door->direction); + if (res == pastdest) + { + switch (door->type) + { + case vld_normal: + case vld_close: + door->sector->specialdata = NULL; + P_RemoveThinker(&door->thinker); // unlink and free + S_StartSound(&door->sector->soundorg, sfx_dorcls); + break; + case vld_close30ThenOpen: + door->direction = 0; + door->topcountdown = 35 * 30; + break; + default: + break; + } + } + else if (res == crushed) + { + switch (door->type) + { + case vld_close: // DON'T GO BACK UP! + break; + default: + door->direction = 1; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + } + } + break; + case 1: // UP + res = T_MovePlane(door->sector, door->speed, + door->topheight, false, 1, door->direction); + if (res == pastdest) + { + switch (door->type) + { + case vld_normal: + door->direction = 0; // wait at top + door->topcountdown = door->topwait; + break; + case vld_close30ThenOpen: + case vld_open: + door->sector->specialdata = NULL; + P_RemoveThinker(&door->thinker); // unlink and free + S_StopSound(&door->sector->soundorg); + break; + default: + break; + } + } + break; + } +} + +//---------------------------------------------------------------------------- +// +// EV_DoDoor +// +// Move a door up/down +// +//---------------------------------------------------------------------------- + +int EV_DoDoor(line_t * line, vldoor_e type, fixed_t speed) +{ + int secnum; + int retcode; + sector_t *sec; + vldoor_t *door; + + secnum = -1; + retcode = 0; + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + { + continue; + } + // Add new door thinker + retcode = 1; + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + switch (type) + { + case vld_close: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->direction = -1; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + case vld_close30ThenOpen: + door->topheight = sec->ceilingheight; + door->direction = -1; + S_StartSound(&door->sector->soundorg, sfx_doropn); + break; + case vld_normal: + case vld_open: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + if (door->topheight != sec->ceilingheight) + { + S_StartSound(&door->sector->soundorg, + sfx_doropn); + } + break; + default: + break; + } + door->type = type; + door->speed = speed; + door->topwait = VDOORWAIT; + } + return (retcode); +} + +//================================================================== +// +// EV_VerticalDoor : open a door manually, no tag value +// +//================================================================== +void EV_VerticalDoor(line_t * line, mobj_t * thing) +{ + player_t *player; + sector_t *sec; + vldoor_t *door; + int side; + + side = 0; // only front sides can be used +// +// Check for locks +// + player = thing->player; + switch (line->special) + { + case 26: // Blue Lock + case 32: + if (!player) + { + return; + } + if (!player->keys[key_blue]) + { + P_SetMessage(player, DEH_String(TXT_NEEDBLUEKEY), false); + S_StartSound(NULL, sfx_plroof); + return; + } + break; + case 27: // Yellow Lock + case 34: + if (!player) + { + return; + } + if (!player->keys[key_yellow]) + { + P_SetMessage(player, DEH_String(TXT_NEEDYELLOWKEY), false); + S_StartSound(NULL, sfx_plroof); + return; + } + break; + case 28: // Green Lock + case 33: + if (!player) + { + return; + } + if (!player->keys[key_green]) + { + P_SetMessage(player, DEH_String(TXT_NEEDGREENKEY), false); + S_StartSound(NULL, sfx_plroof); + return; + } + break; + } + + // if the sector has an active thinker, use it + sec = sides[line->sidenum[side ^ 1]].sector; + if (sec->specialdata) + { + door = sec->specialdata; + switch (line->special) + { + case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s + case 26: + case 27: + case 28: + if (door->direction == -1) + { + door->direction = 1; // go back up + } + else + { + if (!thing->player) + { // Monsters don't close doors + return; + } + door->direction = -1; // start going down immediately + } + return; + } + } + + // for proper sound + switch (line->special) + { + case 1: // NORMAL DOOR SOUND + case 31: + S_StartSound(&sec->soundorg, sfx_doropn); + //S_StartSound(&sec->soundorg, sfx_dormov); + break; + default: // LOCKED DOOR SOUND + S_StartSound(&sec->soundorg, sfx_doropn); + //S_StartSound(&sec->soundorg, sfx_dormov); + break; + } + + // + // new door thinker + // + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + door->direction = 1; + switch (line->special) + { + case 1: + case 26: + case 27: + case 28: + door->type = vld_normal; + break; + case 31: + case 32: + case 33: + case 34: + door->type = vld_open; + line->special = 0; + break; + } + door->speed = VDOORSPEED; + door->topwait = VDOORWAIT; + + // + // find the top and bottom of the movement range + // + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; +} + +//================================================================== +// +// Spawn a door that closes after 30 seconds +// +//================================================================== +void P_SpawnDoorCloseIn30(sector_t * sec) +{ + vldoor_t *door; + + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + sec->special = 0; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + door->direction = 0; + door->type = vld_normal; + door->speed = VDOORSPEED; + door->topcountdown = 30 * 35; +} + +//================================================================== +// +// Spawn a door that opens after 5 minutes +// +//================================================================== +void P_SpawnDoorRaiseIn5Mins(sector_t * sec, int secnum) +{ + vldoor_t *door; + + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + sec->special = 0; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + door->direction = 2; + door->type = vld_raiseIn5Mins; + door->speed = VDOORSPEED; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->topwait = VDOORWAIT; + door->topcountdown = 5 * 60 * 35; +} diff --git a/games/NXDoom/src/heretic/p_enemy.c b/games/NXDoom/src/heretic/p_enemy.c new file mode 100644 index 00000000000..3ade41ae963 --- /dev/null +++ b/games/NXDoom/src/heretic/p_enemy.c @@ -0,0 +1,2711 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_enemy.c + +#include +#include "doomdef.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +// Macros + +#define MAX_BOSS_SPOTS 8 + +// Types + +typedef struct +{ + fixed_t x; + fixed_t y; + angle_t angle; +} BossSpot_t; + +// Private Data + +static int BossSpotCount; +static BossSpot_t BossSpots[MAX_BOSS_SPOTS]; + +//---------------------------------------------------------------------------- +// +// PROC P_InitMonsters +// +// Called at level load. +// +//---------------------------------------------------------------------------- + +void P_InitMonsters(void) +{ + BossSpotCount = 0; +} + +//---------------------------------------------------------------------------- +// +// PROC P_AddBossSpot +// +//---------------------------------------------------------------------------- + +void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle) +{ + if (BossSpotCount == MAX_BOSS_SPOTS) + { + I_Error("Too many boss spots."); + } + BossSpots[BossSpotCount].x = x; + BossSpots[BossSpotCount].y = y; + BossSpots[BossSpotCount].angle = angle; + BossSpotCount++; +} + +//---------------------------------------------------------------------------- +// +// PROC P_RecursiveSound +// +//---------------------------------------------------------------------------- + +mobj_t *soundtarget; + +void P_RecursiveSound(sector_t * sec, int soundblocks) +{ + int i; + line_t *check; + sector_t *other; + + // Wake up all monsters in this sector + if (sec->validcount == validcount + && sec->soundtraversed <= soundblocks + 1) + { // Already flooded + return; + } + sec->validcount = validcount; + sec->soundtraversed = soundblocks + 1; + sec->soundtarget = soundtarget; + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + if (!(check->flags & ML_TWOSIDED)) + { + continue; + } + P_LineOpening(check); + if (openrange <= 0) + { // Closed door + continue; + } + if (sides[check->sidenum[0]].sector == sec) + { + other = sides[check->sidenum[1]].sector; + } + else + { + other = sides[check->sidenum[0]].sector; + } + if (check->flags & ML_SOUNDBLOCK) + { + if (!soundblocks) + { + P_RecursiveSound(other, 1); + } + } + else + { + P_RecursiveSound(other, soundblocks); + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_NoiseAlert +// +// If a monster yells at a player, it will alert other monsters to the +// player. +// +//---------------------------------------------------------------------------- + +void P_NoiseAlert(mobj_t * target, mobj_t * emmiter) +{ + soundtarget = target; + validcount++; + P_RecursiveSound(emmiter->subsector->sector, 0); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_CheckMeleeRange +// +//---------------------------------------------------------------------------- + +boolean P_CheckMeleeRange(mobj_t * actor) +{ + mobj_t *mo; + fixed_t dist; + + if (!actor->target) + { + return (false); + } + mo = actor->target; + dist = P_AproxDistance(mo->x - actor->x, mo->y - actor->y); + if (dist >= MELEERANGE) + { + return (false); + } + if (!P_CheckSight(actor, mo)) + { + return (false); + } + if (mo->z > actor->z + actor->height) + { // Target is higher than the attacker + return (false); + } + else if (actor->z > mo->z + mo->height) + { // Attacker is higher + return (false); + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_CheckMissileRange +// +//---------------------------------------------------------------------------- + +boolean P_CheckMissileRange(mobj_t * actor) +{ + fixed_t dist; + + if (!P_CheckSight(actor, actor->target)) + { + return (false); + } + if (actor->flags & MF_JUSTHIT) + { // The target just hit the enemy, so fight back! + actor->flags &= ~MF_JUSTHIT; + return (true); + } + if (actor->reactiontime) + { // Don't attack yet + return (false); + } + dist = (P_AproxDistance(actor->x - actor->target->x, + actor->y - actor->target->y) >> FRACBITS) - 64; + if (!actor->info->meleestate) + { // No melee attack, so fire more frequently + dist -= 128; + } + if (actor->type == MT_IMP) + { // Imp's fly attack from far away + dist >>= 1; + } + if (dist > 200) + { + dist = 200; + } + if (P_Random() < dist) + { + return (false); + } + return (true); +} + +/* +================ += += P_Move += += Move in the current direction += returns false if the move is blocked +================ +*/ + +fixed_t xspeed[8] = + { FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000, 0, 47000 }; +fixed_t yspeed[8] = + { 0, 47000, FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000 }; + + +boolean P_Move(mobj_t * actor) +{ + fixed_t tryx, tryy; + line_t *ld; + boolean good; + + if (actor->movedir == DI_NODIR) + { + return (false); + } + tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; + tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; + if (!P_TryMove(actor, tryx, tryy)) + { // open any specials + if (actor->flags & MF_FLOAT && floatok) + { // must adjust height + if (actor->z < tmfloorz) + { + actor->z += FLOATSPEED; + } + else + { + actor->z -= FLOATSPEED; + } + actor->flags |= MF_INFLOAT; + return (true); + } + if (!numspechit) + { + return false; + } + actor->movedir = DI_NODIR; + good = false; + while (numspechit--) + { + ld = spechit[numspechit]; + // if the special isn't a door that can be opened, return false + if (P_UseSpecialLine(actor, ld)) + { + good = true; + } + } + return (good); + } + else + { + actor->flags &= ~MF_INFLOAT; + } + if (!(actor->flags & MF_FLOAT)) + { + if (actor->z > actor->floorz) + { + P_HitFloor(actor); + } + actor->z = actor->floorz; + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_TryWalk +// +// Attempts to move actor in its current (ob->moveangle) direction. +// If blocked by either a wall or an actor returns FALSE. +// If move is either clear of block only by a door, returns TRUE and sets. +// If a door is in the way, an OpenDoor call is made to start it opening. +// +//---------------------------------------------------------------------------- + +boolean P_TryWalk(mobj_t * actor) +{ + if (!P_Move(actor)) + { + return (false); + } + actor->movecount = P_Random() & 15; + return (true); +} + +/* +================ += += P_NewChaseDir += +================ +*/ + +dirtype_t opposite[] = + { DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, + DI_NORTH, DI_NORTHWEST, DI_NODIR +}; + +dirtype_t diags[] = + { DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST }; + +void P_NewChaseDir(mobj_t * actor) +{ + fixed_t deltax, deltay; + dirtype_t d[3]; + dirtype_t tdir, olddir, turnaround; + + if (!actor->target) + I_Error("P_NewChaseDir: called with no target"); + + olddir = actor->movedir; + turnaround = opposite[olddir]; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + if (deltax > 10 * FRACUNIT) + d[1] = DI_EAST; + else if (deltax < -10 * FRACUNIT) + d[1] = DI_WEST; + else + d[1] = DI_NODIR; + if (deltay < -10 * FRACUNIT) + d[2] = DI_SOUTH; + else if (deltay > 10 * FRACUNIT) + d[2] = DI_NORTH; + else + d[2] = DI_NODIR; + +// try direct route + if (d[1] != DI_NODIR && d[2] != DI_NODIR) + { + actor->movedir = diags[((deltay < 0) << 1) + (deltax > 0)]; + if (actor->movedir != turnaround && P_TryWalk(actor)) + return; + } + +// try other directions + if (P_Random() > 200 || abs(deltay) > abs(deltax)) + { + tdir = d[1]; + d[1] = d[2]; + d[2] = tdir; + } + + if (d[1] == turnaround) + d[1] = DI_NODIR; + if (d[2] == turnaround) + d[2] = DI_NODIR; + + if (d[1] != DI_NODIR) + { + actor->movedir = d[1]; + if (P_TryWalk(actor)) + return; /*either moved forward or attacked */ + } + + if (d[2] != DI_NODIR) + { + actor->movedir = d[2]; + if (P_TryWalk(actor)) + return; + } + +/* there is no direct path to the player, so pick another direction */ + + if (olddir != DI_NODIR) + { + actor->movedir = olddir; + if (P_TryWalk(actor)) + return; + } + + if (P_Random() & 1) /*randomly determine direction of search */ + { + for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) + { + if (tdir != turnaround) + { + actor->movedir = tdir; + if (P_TryWalk(actor)) + return; + } + } + } + else + { + // Iterate over all movedirs. + tdir = DI_SOUTHEAST; + + for (;;) + { + if (tdir != turnaround) + { + actor->movedir = tdir; + if (P_TryWalk(actor)) + return; + } + + if (tdir == DI_EAST) + { + break; + } + + --tdir; + } + } + + if (turnaround != DI_NODIR) + { + actor->movedir = turnaround; + if (P_TryWalk(actor)) + return; + } + + actor->movedir = DI_NODIR; // can't move +} + +//--------------------------------------------------------------------------- +// +// FUNC P_LookForMonsters +// +//--------------------------------------------------------------------------- + +#define MONS_LOOK_RANGE (20*64*FRACUNIT) +#define MONS_LOOK_LIMIT 64 + +boolean P_LookForMonsters(mobj_t * actor) +{ + int count; + mobj_t *mo; + thinker_t *think; + + if (!P_CheckSight(players[0].mo, actor)) + { // Player can't see monster + return (false); + } + count = 0; + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + if (!(mo->flags & MF_COUNTKILL) || (mo == actor) || (mo->health <= 0)) + { // Not a valid monster + continue; + } + if (P_AproxDistance(actor->x - mo->x, actor->y - mo->y) + > MONS_LOOK_RANGE) + { // Out of range + continue; + } + if (P_Random() < 16) + { // Skip + continue; + } + if (count++ > MONS_LOOK_LIMIT) + { // Stop searching + return (false); + } + if (!P_CheckSight(actor, mo)) + { // Out of sight + continue; + } + // Found a target monster + actor->target = mo; + return (true); + } + return (false); +} + +/* +================ += += P_LookForPlayers += += If allaround is false, only look 180 degrees in front += returns true if a player is targeted +================ +*/ + +boolean P_LookForPlayers(mobj_t * actor, boolean allaround) +{ + int c; + int stop; + player_t *player; + angle_t an; + fixed_t dist; + + if (!netgame && players[0].health <= 0) + { // Single player game and player is dead, look for monsters + return (P_LookForMonsters(actor)); + } + c = 0; + stop = (actor->lastlook - 1) & 3; + for (;; actor->lastlook = (actor->lastlook + 1) & 3) + { + if (!playeringame[actor->lastlook]) + continue; + + if (c++ == 2 || actor->lastlook == stop) + return false; // done looking + + player = &players[actor->lastlook]; + if (player->health <= 0) + continue; // dead + if (!P_CheckSight(actor, player->mo)) + continue; // out of sight + + if (!allaround) + { + an = R_PointToAngle2(actor->x, actor->y, + player->mo->x, player->mo->y) - actor->angle; + if (an > ANG90 && an < ANG270) + { + dist = P_AproxDistance(player->mo->x - actor->x, + player->mo->y - actor->y); + // if real close, react anyway + if (dist > MELEERANGE) + continue; // behind back + } + } + if (player->mo->flags & MF_SHADOW) + { // Player is invisible + if ((P_AproxDistance(player->mo->x - actor->x, + player->mo->y - actor->y) > 2 * MELEERANGE) + && P_AproxDistance(player->mo->momx, player->mo->momy) + < 5 * FRACUNIT) + { // Player is sneaking - can't detect + return (false); + } + if (P_Random() < 225) + { // Player isn't sneaking, but still didn't detect + return (false); + } + } + actor->target = player->mo; + return (true); + } + return (false); +} + +/* +=============================================================================== + + ACTION ROUTINES + +=============================================================================== +*/ + +/* +============== += += A_Look += += Stay in state until a player is sighted += +============== +*/ + +void A_Look(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *targ; + + actor->threshold = 0; // any shot will wake up + targ = actor->subsector->sector->soundtarget; + if (targ && (targ->flags & MF_SHOOTABLE)) + { + actor->target = targ; + if (actor->flags & MF_AMBUSH) + { + if (P_CheckSight(actor, actor->target)) + goto seeyou; + } + else + goto seeyou; + } + + + if (!P_LookForPlayers(actor, false)) + return; + +// go into chase state + seeyou: + if (actor->info->seesound) + { + int sound; + +/* + switch (actor->info->seesound) + { + case sfx_posit1: + case sfx_posit2: + case sfx_posit3: + sound = sfx_posit1+P_Random()%3; + break; + case sfx_bgsit1: + case sfx_bgsit2: + sound = sfx_bgsit1+P_Random()%2; + break; + default: + sound = actor->info->seesound; + break; + } +*/ + sound = actor->info->seesound; + if (actor->flags2 & MF2_BOSS) + { // Full volume + S_StartSound(NULL, sound); + } + else + { + S_StartSound(actor, sound); + } + } + P_SetMobjState(actor, actor->info->seestate); +} + + +/* +============== += += A_Chase += += Actor has a melee attack, so it tries to close as fast as possible += +============== +*/ + +void A_Chase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int delta; + + if (actor->reactiontime) + { + actor->reactiontime--; + } + + // Modify target threshold + if (actor->threshold) + { + actor->threshold--; + } + + if (gameskill == sk_nightmare) + { // Monsters move faster in nightmare mode + actor->tics -= actor->tics / 2; + if (actor->tics < 3) + { + actor->tics = 3; + } + } + +// +// turn towards movement direction if not there yet +// + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + if (delta > 0) + { + actor->angle -= ANG90 / 2; + } + else if (delta < 0) + { + actor->angle += ANG90 / 2; + } + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { // look for a new target + if (P_LookForPlayers(actor, true)) + { // got a new target + return; + } + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + +// +// don't attack twice in a row +// + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare) + P_NewChaseDir(actor); + return; + } + +// +// check for melee attack +// + if (actor->info->meleestate && P_CheckMeleeRange(actor)) + { + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); + P_SetMobjState(actor, actor->info->meleestate); + return; + } + +// +// check for missile attack +// + if (actor->info->missilestate) + { + if (gameskill < sk_nightmare && actor->movecount) + goto nomissile; + if (!P_CheckMissileRange(actor)) + goto nomissile; + P_SetMobjState(actor, actor->info->missilestate); + actor->flags |= MF_JUSTATTACKED; + return; + } + nomissile: + +// +// possibly choose another target +// + if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) + { + if (P_LookForPlayers(actor, true)) + return; // got a new target + } + +// +// chase towards player +// + if (--actor->movecount < 0 || !P_Move(actor)) + { + P_NewChaseDir(actor); + } + +// +// make active sound +// + if (actor->info->activesound && P_Random() < 3) + { + if (actor->type == MT_WIZARD && P_Random() < 128) + { + S_StartSound(actor, actor->info->seesound); + } + else if (actor->type == MT_SORCERER2) + { + S_StartSound(NULL, actor->info->activesound); + } + else + { + S_StartSound(actor, actor->info->activesound); + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FaceTarget +// +//---------------------------------------------------------------------------- + +void A_FaceTarget(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + actor->flags &= ~MF_AMBUSH; + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, + actor->target->y); + if (actor->target->flags & MF_SHADOW) + { // Target is a ghost + actor->angle += P_SubRandom() << 21; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_Pain +// +//---------------------------------------------------------------------------- + +void A_Pain(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->info->painsound) + { + S_StartSound(actor, actor->info->painsound); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_DripBlood +// +//---------------------------------------------------------------------------- + +void A_DripBlood(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1,r2; + + r1 = P_SubRandom(); + r2 = P_SubRandom(); + + mo = P_SpawnMobj(actor->x + (r2 << 11), + actor->y + (r1 << 11), actor->z, + MT_BLOOD); + mo->momx = P_SubRandom() << 10; + mo->momy = P_SubRandom() << 10; + mo->flags2 |= MF2_LOGRAV; +} + +//---------------------------------------------------------------------------- +// +// PROC A_KnightAttack +// +//---------------------------------------------------------------------------- + +void A_KnightAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(3)); + S_StartSound(actor, sfx_kgtat2); + return; + } + // Throw axe + S_StartSound(actor, actor->info->attacksound); + if (actor->type == MT_KNIGHTGHOST || P_Random() < 40) + { // Red axe + P_SpawnMissile(actor, actor->target, MT_REDAXE); + return; + } + // Green axe + P_SpawnMissile(actor, actor->target, MT_KNIGHTAXE); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpExplode +// +//---------------------------------------------------------------------------- + +void A_ImpExplode(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK1); + mo->momx = P_SubRandom() << 10; + mo->momy = P_SubRandom() << 10; + mo->momz = 9 * FRACUNIT; + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK2); + mo->momx = P_SubRandom() << 10; + mo->momy = P_SubRandom() << 10; + mo->momz = 9 * FRACUNIT; + if (actor->special1.i == 666) + { // Extreme death crash + P_SetMobjState(actor, S_IMP_XCRASH1); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_BeastPuff +// +//---------------------------------------------------------------------------- + +void A_BeastPuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_Random() > 64) + { + int r1,r2,r3; + r1 = P_SubRandom(); + r2 = P_SubRandom(); + r3 = P_SubRandom(); + P_SpawnMobj(actor->x + (r3 << 10), + actor->y + (r2 << 10), + actor->z + (r1 << 10), MT_PUFFY); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpMeAttack +// +//---------------------------------------------------------------------------- + +void A_ImpMeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, 5 + (P_Random() & 7)); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpMsAttack +// +//---------------------------------------------------------------------------- + +void A_ImpMsAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *dest; + angle_t an; + int dist; + + if (!actor->target || P_Random() > 64) + { + P_SetMobjState(actor, actor->info->seestate); + return; + } + dest = actor->target; + actor->flags |= MF_SKULLFLY; + S_StartSound(actor, actor->info->attacksound); + A_FaceTarget(actor, player, psp); + an = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(12 * FRACUNIT, finecosine[an]); + actor->momy = FixedMul(12 * FRACUNIT, finesine[an]); + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + dist = dist / (12 * FRACUNIT); + if (dist < 1) + { + dist = 1; + } + actor->momz = (dest->z + (dest->height >> 1) - actor->z) / dist; +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpMsAttack2 +// +// Fireball attack of the imp leader. +// +//---------------------------------------------------------------------------- + +void A_ImpMsAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, 5 + (P_Random() & 7)); + return; + } + P_SpawnMissile(actor, actor->target, MT_IMPBALL); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpDeath +// +//---------------------------------------------------------------------------- + +void A_ImpDeath(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SOLID; + actor->flags2 |= MF2_FOOTCLIP; + if (actor->z <= actor->floorz) + { + P_SetMobjState(actor, S_IMP_CRASH1); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpXDeath1 +// +//---------------------------------------------------------------------------- + +void A_ImpXDeath1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SOLID; + actor->flags |= MF_NOGRAVITY; + actor->flags2 |= MF2_FOOTCLIP; + actor->special1.i = 666; // Flag the crash routine +} + +//---------------------------------------------------------------------------- +// +// PROC A_ImpXDeath2 +// +//---------------------------------------------------------------------------- + +void A_ImpXDeath2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_NOGRAVITY; + if (actor->z <= actor->floorz) + { + P_SetMobjState(actor, S_IMP_CRASH1); + } +} + +//---------------------------------------------------------------------------- +// +// FUNC P_UpdateChicken +// +// Returns true if the chicken morphs. +// +//---------------------------------------------------------------------------- + +boolean P_UpdateChicken(mobj_t * actor, int tics) +{ + mobj_t *fog; + fixed_t x; + fixed_t y; + fixed_t z; + mobjtype_t moType; + mobj_t *mo; + mobj_t oldChicken; + + actor->special1.i -= tics; + if (actor->special1.i > 0) + { + return (false); + } + moType = actor->special2.i; + x = actor->x; + y = actor->y; + z = actor->z; + oldChicken = *actor; + P_SetMobjState(actor, S_FREETARGMOBJ); + mo = P_SpawnMobj(x, y, z, moType); + if (P_TestMobjLocation(mo) == false) + { // Didn't fit + P_RemoveMobj(mo); + mo = P_SpawnMobj(x, y, z, MT_CHICKEN); + mo->angle = oldChicken.angle; + mo->flags = oldChicken.flags; + mo->health = oldChicken.health; + mo->target = oldChicken.target; + mo->special1.i = 5 * 35; // Next try in 5 seconds + mo->special2.i = moType; + return (false); + } + mo->angle = oldChicken.angle; + mo->target = oldChicken.target; + fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, sfx_telept); + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ChicAttack +// +//---------------------------------------------------------------------------- + +void A_ChicAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateChicken(actor, 18)) + { + return; + } + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, 1 + (P_Random() & 1)); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_ChicLook +// +//---------------------------------------------------------------------------- + +void A_ChicLook(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateChicken(actor, 10)) + { + return; + } + A_Look(actor, player, psp); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ChicChase +// +//---------------------------------------------------------------------------- + +void A_ChicChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateChicken(actor, 3)) + { + return; + } + A_Chase(actor, player, psp); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ChicPain +// +//---------------------------------------------------------------------------- + +void A_ChicPain(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateChicken(actor, 10)) + { + return; + } + S_StartSound(actor, actor->info->painsound); +} + +//---------------------------------------------------------------------------- +// +// PROC A_Feathers +// +//---------------------------------------------------------------------------- + +void A_Feathers(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + int count; + mobj_t *mo; + + if (actor->health > 0) + { // Pain + count = P_Random() < 32 ? 2 : 1; + } + else + { // Death + count = 5 + (P_Random() & 3); + } + for (i = 0; i < count; i++) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 20 * FRACUNIT, + MT_FEATHER); + mo->target = actor; + mo->momx = P_SubRandom() << 8; + mo->momy = P_SubRandom() << 8; + mo->momz = FRACUNIT + (P_Random() << 9); + P_SetMobjState(mo, S_FEATHER1 + (P_Random() & 7)); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MummyAttack +// +//---------------------------------------------------------------------------- + +void A_MummyAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(2)); + S_StartSound(actor, sfx_mumat2); + return; + } + S_StartSound(actor, sfx_mumat1); +} + +//---------------------------------------------------------------------------- +// +// PROC A_MummyAttack2 +// +// Mummy leader missile attack. +// +//---------------------------------------------------------------------------- + +void A_MummyAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + if (!actor->target) + { + return; + } + //S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(2)); + return; + } + mo = P_SpawnMissile(actor, actor->target, MT_MUMMYFX1); + //mo = P_SpawnMissile(actor, actor->target, MT_EGGFX); + if (mo != NULL) + { + mo->special1.m = actor->target; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MummyFX1Seek +// +//---------------------------------------------------------------------------- + +void A_MummyFX1Seek(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SeekerMissile(actor, ANG1_X * 10, ANG1_X * 20); +} + +//---------------------------------------------------------------------------- +// +// PROC A_MummySoul +// +//---------------------------------------------------------------------------- + +void A_MummySoul(mobj_t * mummy, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(mummy->x, mummy->y, mummy->z + 10 * FRACUNIT, + MT_MUMMYSOUL); + mo->momz = FRACUNIT; +} + +//---------------------------------------------------------------------------- +// +// PROC A_Sor1Pain +// +//---------------------------------------------------------------------------- + +void A_Sor1Pain(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->special1.i = 20; // Number of steps to walk fast + A_Pain(actor, player, psp); +} + +//---------------------------------------------------------------------------- +// +// PROC A_Sor1Chase +// +//---------------------------------------------------------------------------- + +void A_Sor1Chase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special1.i) + { + actor->special1.i--; + actor->tics -= 3; + } + A_Chase(actor, player, psp); +} + +//---------------------------------------------------------------------------- +// +// PROC A_Srcr1Attack +// +// Sorcerer demon attack. +// +//---------------------------------------------------------------------------- + +void A_Srcr1Attack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + fixed_t momz; + angle_t angle; + + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(8)); + return; + } + if (actor->health > (actor->info->spawnhealth / 3) * 2) + { // Spit one fireball + P_SpawnMissile(actor, actor->target, MT_SRCRFX1); + } + else + { // Spit three fireballs + mo = P_SpawnMissile(actor, actor->target, MT_SRCRFX1); + if (mo) + { + momz = mo->momz; + angle = mo->angle; + P_SpawnMissileAngle(actor, MT_SRCRFX1, angle - ANG1_X * 3, momz); + P_SpawnMissileAngle(actor, MT_SRCRFX1, angle + ANG1_X * 3, momz); + } + if (actor->health < actor->info->spawnhealth / 3) + { // Maybe attack again + if (actor->special1.i) + { // Just attacked, so don't attack again + actor->special1.i = 0; + } + else + { // Set state to attack again + actor->special1.i = 1; + P_SetMobjState(actor, S_SRCR1_ATK4); + } + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_SorcererRise +// +//---------------------------------------------------------------------------- + +void A_SorcererRise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + actor->flags &= ~MF_SOLID; + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCERER2); + P_SetMobjState(mo, S_SOR2_RISE1); + mo->angle = actor->angle; + mo->target = actor->target; +} + +//---------------------------------------------------------------------------- +// +// PROC P_DSparilTeleport +// +//---------------------------------------------------------------------------- + +void P_DSparilTeleport(mobj_t *actor) +{ + int i; + fixed_t x; + fixed_t y; + fixed_t prevX; + fixed_t prevY; + fixed_t prevZ; + mobj_t *mo; + + if (!BossSpotCount) + { // No spots + return; + } + i = P_Random(); + do + { + i++; + x = BossSpots[i % BossSpotCount].x; + y = BossSpots[i % BossSpotCount].y; + } + while (P_AproxDistance(actor->x - x, actor->y - y) < 128 * FRACUNIT); + prevX = actor->x; + prevY = actor->y; + prevZ = actor->z; + if (P_TeleportMove(actor, x, y)) + { + mo = P_SpawnMobj(prevX, prevY, prevZ, MT_SOR2TELEFADE); + S_StartSound(mo, sfx_telept); + P_SetMobjState(actor, S_SOR2_TELE1); + S_StartSound(actor, sfx_telept); + actor->z = actor->floorz; + actor->angle = BossSpots[i % BossSpotCount].angle; + actor->momx = actor->momy = actor->momz = 0; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_Srcr2Decide +// +//---------------------------------------------------------------------------- + +void A_Srcr2Decide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + static int chance[] = { + 192, 120, 120, 120, 64, 64, 32, 16, 0 + }; + + if (!BossSpotCount) + { // No spots + return; + } + if (P_Random() < chance[actor->health / (actor->info->spawnhealth / 8)]) + { + P_DSparilTeleport(actor); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_Srcr2Attack +// +//---------------------------------------------------------------------------- + +void A_Srcr2Attack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int chance; + + if (!actor->target) + { + return; + } + S_StartSound(NULL, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(20)); + return; + } + chance = actor->health < actor->info->spawnhealth / 2 ? 96 : 48; + if (P_Random() < chance) + { // Wizard spawners + P_SpawnMissileAngle(actor, MT_SOR2FX2, + actor->angle - ANG45, FRACUNIT / 2); + P_SpawnMissileAngle(actor, MT_SOR2FX2, + actor->angle + ANG45, FRACUNIT / 2); + } + else + { // Blue bolt + P_SpawnMissile(actor, actor->target, MT_SOR2FX1); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_BlueSpark +// +//---------------------------------------------------------------------------- + +void A_BlueSpark(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + mobj_t *mo; + + for (i = 0; i < 2; i++) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SOR2FXSPARK); + mo->momx = P_SubRandom() << 9; + mo->momy = P_SubRandom() << 9; + mo->momz = FRACUNIT + (P_Random() << 8); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_GenWizard +// +//---------------------------------------------------------------------------- + +void A_GenWizard(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + mobj_t *fog; + + mo = P_SpawnMobj(actor->x, actor->y, + actor->z - mobjinfo[MT_WIZARD].height / 2, MT_WIZARD); + if (P_TestMobjLocation(mo) == false) + { // Didn't fit + P_RemoveMobj(mo); + return; + } + actor->momx = actor->momy = actor->momz = 0; + P_SetMobjState(actor, mobjinfo[actor->type].deathstate); + actor->flags &= ~MF_MISSILE; + fog = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TFOG); + S_StartSound(fog, sfx_telept); +} + +//---------------------------------------------------------------------------- +// +// PROC A_Sor2DthInit +// +//---------------------------------------------------------------------------- + +void A_Sor2DthInit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->special1.i = 7; // Animation loop counter + P_Massacre(); // Kill monsters early +} + +//---------------------------------------------------------------------------- +// +// PROC A_Sor2DthLoop +// +//---------------------------------------------------------------------------- + +void A_Sor2DthLoop(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (--actor->special1.i) + { // Need to loop + P_SetMobjState(actor, S_SOR2_DIE4); + } +} + +//---------------------------------------------------------------------------- +// +// D'Sparil Sound Routines +// +//---------------------------------------------------------------------------- + +void A_SorZap(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, sfx_sorzap); +} + +void A_SorRise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, sfx_sorrise); +} + +void A_SorDSph(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, sfx_sordsph); +} + +void A_SorDExp(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, sfx_sordexp); +} + +void A_SorDBon(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, sfx_sordbon); +} + +void A_SorSightSnd(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, sfx_sorsit); +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurAtk1 +// +// Melee attack. +// +//---------------------------------------------------------------------------- + +void A_MinotaurAtk1(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + player_t *player; + + if (!actor->target) + { + return; + } + S_StartSound(actor, sfx_stfpow); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(4)); + if ((player = actor->target->player) != NULL) + { // Squish the player + player->deltaviewheight = -16 * FRACUNIT; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurDecide +// +// Choose a missile attack. +// +//---------------------------------------------------------------------------- + +#define MNTR_CHARGE_SPEED (13*FRACUNIT) + +void A_MinotaurDecide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + mobj_t *target; + int dist; + + target = actor->target; + if (!target) + { + return; + } + S_StartSound(actor, sfx_minsit); + dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); + if (target->z + target->height > actor->z + && target->z + target->height < actor->z + actor->height + && dist < 8 * 64 * FRACUNIT + && dist > 1 * 64 * FRACUNIT && P_Random() < 150) + { // Charge attack + // Don't call the state function right away + P_SetMobjStateNF(actor, S_MNTR_ATK4_1); + actor->flags |= MF_SKULLFLY; + A_FaceTarget(actor, player, psp); + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(MNTR_CHARGE_SPEED, finecosine[angle]); + actor->momy = FixedMul(MNTR_CHARGE_SPEED, finesine[angle]); + actor->special1.i = 35 / 2; // Charge duration + } + else if (target->z == target->floorz + && dist < 9 * 64 * FRACUNIT && P_Random() < 220) + { // Floor fire attack + P_SetMobjState(actor, S_MNTR_ATK3_1); + actor->special2.i = 0; + } + else + { // Swing attack + A_FaceTarget(actor, player, psp); + // Don't need to call P_SetMobjState because the current state + // falls through to the swing attack + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurCharge +// +//---------------------------------------------------------------------------- + +void A_MinotaurCharge(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *puff; + + if (actor->special1.i) + { + puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF); + puff->momz = 2 * FRACUNIT; + actor->special1.i--; + } + else + { + actor->flags &= ~MF_SKULLFLY; + P_SetMobjState(actor, actor->info->seestate); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurAtk2 +// +// Swing attack. +// +//---------------------------------------------------------------------------- + +void A_MinotaurAtk2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + fixed_t momz; + + if (!actor->target) + { + return; + } + S_StartSound(actor, sfx_minat2); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(5)); + return; + } + mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX1); + if (mo) + { + S_StartSound(mo, sfx_minat2); + momz = mo->momz; + angle = mo->angle; + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 8), momz); + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 8), momz); + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 16), momz); + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 16), momz); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurAtk3 +// +// Floor fire attack. +// +//---------------------------------------------------------------------------- + +void A_MinotaurAtk3(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + mobj_t *mo; + player_t *player; + + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(5)); + if ((player = actor->target->player) != NULL) + { // Squish the player + player->deltaviewheight = -16 * FRACUNIT; + } + } + else + { + mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX2); + if (mo != NULL) + { + S_StartSound(mo, sfx_minat1); + } + } + if (P_Random() < 192 && actor->special2.i == 0) + { + P_SetMobjState(actor, S_MNTR_ATK3_4); + actor->special2.i = 1; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MntrFloorFire +// +//---------------------------------------------------------------------------- + +void A_MntrFloorFire(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1, r2; + + r1 = P_SubRandom(); + r2 = P_SubRandom(); + + actor->z = actor->floorz; + mo = P_SpawnMobj(actor->x + (r2 << 10), + actor->y + (r1 << 10), ONFLOORZ, + MT_MNTRFX3); + mo->target = actor->target; + mo->momx = 1; // Force block checking + P_CheckMissileSpawn(mo); +} + +//---------------------------------------------------------------------------- +// +// PROC A_BeastAttack +// +//---------------------------------------------------------------------------- + +void A_BeastAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(3)); + return; + } + P_SpawnMissile(actor, actor->target, MT_BEASTBALL); +} + +//---------------------------------------------------------------------------- +// +// PROC A_HeadAttack +// +//---------------------------------------------------------------------------- + +void A_HeadAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + mobj_t *fire; + mobj_t *baseFire; + mobj_t *mo; + mobj_t *target; + int randAttack; + static int atkResolve1[] = { 50, 150 }; + static int atkResolve2[] = { 150, 200 }; + int dist; + + // Ice ball (close 20% : far 60%) + // Fire column (close 40% : far 20%) + // Whirlwind (close 40% : far 20%) + // Distance threshold = 8 cells + + target = actor->target; + if (target == NULL) + { + return; + } + A_FaceTarget(actor, player, psp); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(target, actor, actor, HITDICE(6)); + return; + } + dist = P_AproxDistance(actor->x - target->x, actor->y - target->y) + > 8 * 64 * FRACUNIT; + randAttack = P_Random(); + if (randAttack < atkResolve1[dist]) + { // Ice ball + P_SpawnMissile(actor, target, MT_HEADFX1); + S_StartSound(actor, sfx_hedat2); + } + else if (randAttack < atkResolve2[dist]) + { // Fire column + baseFire = P_SpawnMissile(actor, target, MT_HEADFX3); + if (baseFire != NULL) + { + P_SetMobjState(baseFire, S_HEADFX3_4); // Don't grow + for (i = 0; i < 5; i++) + { + fire = P_SpawnMobj(baseFire->x, baseFire->y, + baseFire->z, MT_HEADFX3); + if (i == 0) + { + S_StartSound(actor, sfx_hedat1); + } + fire->target = baseFire->target; + fire->angle = baseFire->angle; + fire->momx = baseFire->momx; + fire->momy = baseFire->momy; + fire->momz = baseFire->momz; + fire->damage = 0; + fire->health = (i + 1) * 2; + P_CheckMissileSpawn(fire); + } + } + } + else + { // Whirlwind + mo = P_SpawnMissile(actor, target, MT_WHIRLWIND); + if (mo != NULL) + { + mo->z -= 32 * FRACUNIT; + mo->special1.m = target; + mo->special2.i = 50; // Timer for active sound + mo->health = 20 * TICRATE; // Duration + S_StartSound(actor, sfx_hedat3); + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_WhirlwindSeek +// +//---------------------------------------------------------------------------- + +void A_WhirlwindSeek(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->health -= 3; + if (actor->health < 0) + { + actor->momx = actor->momy = actor->momz = 0; + P_SetMobjState(actor, mobjinfo[actor->type].deathstate); + actor->flags &= ~MF_MISSILE; + return; + } + if ((actor->special2.i -= 3) < 0) + { + actor->special2.i = 58 + (P_Random() & 31); + S_StartSound(actor, sfx_hedat3); + } + if (actor->special1.m + && (((mobj_t *) (actor->special1.m))->flags & MF_SHADOW)) + { + return; + } + P_SeekerMissile(actor, ANG1_X * 10, ANG1_X * 30); +} + +//---------------------------------------------------------------------------- +// +// PROC A_HeadIceImpact +// +//---------------------------------------------------------------------------- + +void A_HeadIceImpact(mobj_t * ice, player_t *player, pspdef_t *psp) +{ + unsigned int i; + angle_t angle; + mobj_t *shard; + + for (i = 0; i < 8; i++) + { + shard = P_SpawnMobj(ice->x, ice->y, ice->z, MT_HEADFX2); + angle = i * ANG45; + shard->target = ice->target; + shard->angle = angle; + angle >>= ANGLETOFINESHIFT; + shard->momx = FixedMul(shard->info->speed, finecosine[angle]); + shard->momy = FixedMul(shard->info->speed, finesine[angle]); + shard->momz = (fixed_t)(-.6 * FRACUNIT); + P_CheckMissileSpawn(shard); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_HeadFireGrow +// +//---------------------------------------------------------------------------- + +void A_HeadFireGrow(mobj_t * fire, player_t *player, pspdef_t *psp) +{ + fire->health--; + fire->z += 9 * FRACUNIT; + if (fire->health == 0) + { + fire->damage = fire->info->damage; + P_SetMobjState(fire, S_HEADFX3_4); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_SnakeAttack +// +//---------------------------------------------------------------------------- + +void A_SnakeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + P_SetMobjState(actor, S_SNAKE_WALK1); + return; + } + S_StartSound(actor, actor->info->attacksound); + A_FaceTarget(actor, player, psp); + P_SpawnMissile(actor, actor->target, MT_SNAKEPRO_A); +} + +//---------------------------------------------------------------------------- +// +// PROC A_SnakeAttack2 +// +//---------------------------------------------------------------------------- + +void A_SnakeAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + P_SetMobjState(actor, S_SNAKE_WALK1); + return; + } + S_StartSound(actor, actor->info->attacksound); + A_FaceTarget(actor, player, psp); + P_SpawnMissile(actor, actor->target, MT_SNAKEPRO_B); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ClinkAttack +// +//---------------------------------------------------------------------------- + +void A_ClinkAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int damage; + + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + damage = ((P_Random() % 7) + 3); + P_DamageMobj(actor->target, actor, actor, damage); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_GhostOff +// +//---------------------------------------------------------------------------- + +void A_GhostOff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SHADOW; +} + +//---------------------------------------------------------------------------- +// +// PROC A_WizAtk1 +// +//---------------------------------------------------------------------------- + +void A_WizAtk1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_FaceTarget(actor, player, psp); + actor->flags &= ~MF_SHADOW; +} + +//---------------------------------------------------------------------------- +// +// PROC A_WizAtk2 +// +//---------------------------------------------------------------------------- + +void A_WizAtk2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_FaceTarget(actor, player, psp); + actor->flags |= MF_SHADOW; +} + +//---------------------------------------------------------------------------- +// +// PROC A_WizAtk3 +// +//---------------------------------------------------------------------------- + +void A_WizAtk3(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + fixed_t momz; + + actor->flags &= ~MF_SHADOW; + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(4)); + return; + } + mo = P_SpawnMissile(actor, actor->target, MT_WIZFX1); + if (mo) + { + momz = mo->momz; + angle = mo->angle; + P_SpawnMissileAngle(actor, MT_WIZFX1, angle - (ANG45 / 8), momz); + P_SpawnMissileAngle(actor, MT_WIZFX1, angle + (ANG45 / 8), momz); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_Scream +// +//---------------------------------------------------------------------------- + +void A_Scream(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + switch (actor->type) + { + case MT_CHICPLAYER: + case MT_SORCERER1: + case MT_MINOTAUR: + // Make boss death sounds full volume + S_StartSound(NULL, actor->info->deathsound); + break; + case MT_PLAYER: + // Handle the different player death screams + if (actor->special1.i < 10) + { // Wimpy death sound + S_StartSound(actor, sfx_plrwdth); + } + else if (actor->health > -50) + { // Normal death sound + S_StartSound(actor, actor->info->deathsound); + } + else if (actor->health > -100) + { // Crazy death sound + S_StartSound(actor, sfx_plrcdth); + } + else + { // Extreme death sound + S_StartSound(actor, sfx_gibdth); + } + break; + default: + S_StartSound(actor, actor->info->deathsound); + break; + } +} + +//--------------------------------------------------------------------------- +// +// PROC P_DropItem +// +//--------------------------------------------------------------------------- + +void P_DropItem(mobj_t * source, mobjtype_t type, int special, int chance) +{ + mobj_t *mo; + + if (P_Random() > chance) + { + return; + } + mo = P_SpawnMobj(source->x, source->y, + source->z + (source->height >> 1), type); + mo->momx = P_SubRandom() << 8; + mo->momy = P_SubRandom() << 8; + mo->momz = FRACUNIT * 5 + (P_Random() << 10); + mo->flags |= MF_DROPPED; + mo->health = special; +} + +//---------------------------------------------------------------------------- +// +// PROC A_NoBlocking +// +//---------------------------------------------------------------------------- + +void A_NoBlocking(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SOLID; + // Check for monsters dropping things + switch (actor->type) + { + case MT_MUMMY: + case MT_MUMMYLEADER: + case MT_MUMMYGHOST: + case MT_MUMMYLEADERGHOST: + P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84); + break; + case MT_KNIGHT: + case MT_KNIGHTGHOST: + P_DropItem(actor, MT_AMCBOWWIMPY, 5, 84); + break; + case MT_WIZARD: + P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84); + P_DropItem(actor, MT_ARTITOMEOFPOWER, 0, 4); + break; + case MT_HEAD: + P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84); + P_DropItem(actor, MT_ARTIEGG, 0, 51); + break; + case MT_BEAST: + P_DropItem(actor, MT_AMCBOWWIMPY, 10, 84); + break; + case MT_CLINK: + P_DropItem(actor, MT_AMSKRDWIMPY, 20, 84); + break; + case MT_SNAKE: + P_DropItem(actor, MT_AMPHRDWIMPY, 5, 84); + break; + case MT_MINOTAUR: + P_DropItem(actor, MT_ARTISUPERHEAL, 0, 51); + P_DropItem(actor, MT_AMPHRDWIMPY, 10, 84); + break; + default: + break; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_Explode +// +// Handles a bunch of exploding things. +// +//---------------------------------------------------------------------------- + +void A_Explode(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + int damage; + + damage = 128; + switch (actor->type) + { + case MT_FIREBOMB: // Time Bombs + actor->z += 32 * FRACUNIT; + actor->flags &= ~MF_SHADOW; + break; + case MT_MNTRFX2: // Minotaur floor fire + damage = 24; + break; + case MT_SOR2FX1: // D'Sparil missile + damage = 80 + (P_Random() & 31); + break; + default: + break; + } + P_RadiusAttack(actor, actor->target, damage); + P_HitFloor(actor); +} + +//---------------------------------------------------------------------------- +// +// PROC A_PodPain +// +//---------------------------------------------------------------------------- + +void A_PodPain(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + int i; + int count; + int chance; + mobj_t *goo; + + chance = P_Random(); + if (chance < 128) + { + return; + } + count = chance > 240 ? 2 : 1; + for (i = 0; i < count; i++) + { + goo = P_SpawnMobj(actor->x, actor->y, + actor->z + 48 * FRACUNIT, MT_PODGOO); + goo->target = actor; + goo->momx = P_SubRandom() << 9; + goo->momy = P_SubRandom() << 9; + goo->momz = FRACUNIT / 2 + (P_Random() << 9); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_RemovePod +// +//---------------------------------------------------------------------------- + +void A_RemovePod(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + if (actor->special2.m) + { + mo = (mobj_t *) actor->special2.m; + if (mo->special1.i > 0) + { + mo->special1.i--; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MakePod +// +//---------------------------------------------------------------------------- + +#define MAX_GEN_PODS 16 + +void A_MakePod(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + fixed_t x; + fixed_t y; + + if (actor->special1.i == MAX_GEN_PODS) + { // Too many generated pods + return; + } + x = actor->x; + y = actor->y; + mo = P_SpawnMobj(x, y, ONFLOORZ, MT_POD); + if (P_CheckPosition(mo, x, y) == false) + { // Didn't fit + P_RemoveMobj(mo); + return; + } + P_SetMobjState(mo, S_POD_GROW1); + P_ThrustMobj(mo, P_Random() << 24, (fixed_t) (4.5 * FRACUNIT)); + S_StartSound(mo, sfx_newpod); + actor->special1.i++; // Increment generated pod count + mo->special2.m = actor; // Link the generator to the pod + return; +} + +//---------------------------------------------------------------------------- +// +// PROC P_Massacre +// +// Kills all monsters. +// +//---------------------------------------------------------------------------- + +void P_Massacre(void) +{ + mobj_t *mo; + thinker_t *think; + + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + if ((mo->flags & MF_COUNTKILL) && (mo->health > 0)) + { + P_DamageMobj(mo, NULL, NULL, 10000); + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_BossDeath +// +// Trigger special effects if all bosses are dead. +// +//---------------------------------------------------------------------------- + +void A_BossDeath(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + thinker_t *think; + line_t dummyLine; + static mobjtype_t bossType[6] = { + MT_HEAD, + MT_MINOTAUR, + MT_SORCERER2, + MT_HEAD, + MT_MINOTAUR, + -1 + }; + + if (gamemap != 8) + { // Not a boss level + return; + } + if (actor->type != bossType[gameepisode - 1]) + { // Not considered a boss in this episode + return; + } + // Make sure all bosses are dead + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + if ((mo != actor) && (mo->type == actor->type) && (mo->health > 0)) + { // Found a living boss + return; + } + } + if (gameepisode > 1) + { // Kill any remaining monsters + P_Massacre(); + } + dummyLine.tag = 666; + EV_DoFloor(&dummyLine, lowerFloor); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ESound +// +//---------------------------------------------------------------------------- + +void A_ESound(mobj_t *mo, player_t *player, pspdef_t *psp) +{ + int sound = sfx_None; + + switch (mo->type) + { + case MT_SOUNDWATERFALL: + sound = sfx_waterfl; + break; + case MT_SOUNDWIND: + sound = sfx_wind; + break; + default: + break; + } + S_StartSound(mo, sound); +} + +//---------------------------------------------------------------------------- +// +// PROC A_SpawnTeleGlitter +// +//---------------------------------------------------------------------------- + +void A_SpawnTeleGlitter(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1, r2; + + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r2 & 31) - 16) * FRACUNIT, + actor->y + ((r1 & 31) - 16) * FRACUNIT, + actor->subsector->sector->floorheight, MT_TELEGLITTER); + mo->momz = FRACUNIT / 4; +} + +//---------------------------------------------------------------------------- +// +// PROC A_SpawnTeleGlitter2 +// +//---------------------------------------------------------------------------- + +void A_SpawnTeleGlitter2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1, r2; + + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r2 & 31) - 16) * FRACUNIT, + actor->y + ((r1 & 31) - 16) * FRACUNIT, + actor->subsector->sector->floorheight, MT_TELEGLITTER2); + mo->momz = FRACUNIT / 4; +} + +//---------------------------------------------------------------------------- +// +// PROC A_AccTeleGlitter +// +//---------------------------------------------------------------------------- + +void A_AccTeleGlitter(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (++actor->health > 35) + { + actor->momz += actor->momz / 2; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_InitKeyGizmo +// +//---------------------------------------------------------------------------- + +void A_InitKeyGizmo(mobj_t * gizmo, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + statenum_t state = S_NULL; + + switch (gizmo->type) + { + case MT_KEYGIZMOBLUE: + state = S_KGZ_BLUEFLOAT1; + break; + case MT_KEYGIZMOGREEN: + state = S_KGZ_GREENFLOAT1; + break; + case MT_KEYGIZMOYELLOW: + state = S_KGZ_YELLOWFLOAT1; + break; + default: + break; + } + mo = P_SpawnMobj(gizmo->x, gizmo->y, gizmo->z + 60 * FRACUNIT, + MT_KEYGIZMOFLOAT); + P_SetMobjState(mo, state); +} + +//---------------------------------------------------------------------------- +// +// PROC A_VolcanoSet +// +//---------------------------------------------------------------------------- + +void A_VolcanoSet(mobj_t * volcano, player_t *player, pspdef_t *psp) +{ + volcano->tics = 105 + (P_Random() & 127); +} + +//---------------------------------------------------------------------------- +// +// PROC A_VolcanoBlast +// +//---------------------------------------------------------------------------- + +void A_VolcanoBlast(mobj_t * volcano, player_t *player, pspdef_t *psp) +{ + int i; + int count; + mobj_t *blast; + angle_t angle; + + count = 1 + (P_Random() % 3); + for (i = 0; i < count; i++) + { + blast = P_SpawnMobj(volcano->x, volcano->y, volcano->z + 44 * FRACUNIT, MT_VOLCANOBLAST); // MT_VOLCANOBLAST + blast->target = volcano; + angle = P_Random() << 24; + blast->angle = angle; + angle >>= ANGLETOFINESHIFT; + blast->momx = FixedMul(1 * FRACUNIT, finecosine[angle]); + blast->momy = FixedMul(1 * FRACUNIT, finesine[angle]); + blast->momz = (fixed_t)(2.5 * FRACUNIT) + (P_Random() << 10); + S_StartSound(blast, sfx_volsht); + P_CheckMissileSpawn(blast); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_VolcBallImpact +// +//---------------------------------------------------------------------------- + +void A_VolcBallImpact(mobj_t * ball, player_t *player, pspdef_t *psp) +{ + unsigned int i; + mobj_t *tiny; + angle_t angle; + + if (ball->z <= ball->floorz) + { + ball->flags |= MF_NOGRAVITY; + ball->flags2 &= ~MF2_LOGRAV; + ball->z += 28 * FRACUNIT; + //ball->momz = 3*FRACUNIT; + } + P_RadiusAttack(ball, ball->target, 25); + for (i = 0; i < 4; i++) + { + tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_VOLCANOTBLAST); + tiny->target = ball; + angle = i * ANG90; + tiny->angle = angle; + angle >>= ANGLETOFINESHIFT; + tiny->momx = FixedMul((fixed_t)(FRACUNIT * .7), finecosine[angle]); + tiny->momy = FixedMul((fixed_t)(FRACUNIT * .7), finesine[angle]); + tiny->momz = FRACUNIT + (P_Random() << 9); + P_CheckMissileSpawn(tiny); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_SkullPop +// +//---------------------------------------------------------------------------- + +void A_SkullPop(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + mobj_t *mo; + player_t *player; + + actor->flags &= ~MF_SOLID; + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 48 * FRACUNIT, + MT_BLOODYSKULL); + //mo->target = actor; + mo->momx = P_SubRandom() << 9; + mo->momy = P_SubRandom() << 9; + mo->momz = FRACUNIT * 2 + (P_Random() << 6); + // Attach player mobj to bloody skull + player = actor->player; + actor->player = NULL; + mo->player = player; + mo->health = actor->health; + mo->angle = actor->angle; + + // fraggle: This check wasn't originally here in the Vanilla Heretic + // source, causing crashes if the player respawns before this + // function is called. + + if (player != NULL) + { + player->mo = mo; + player->lookdir = 0; + player->damagecount = 32; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_CheckSkullFloor +// +//---------------------------------------------------------------------------- + +void A_CheckSkullFloor(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->z <= actor->floorz) + { + P_SetMobjState(actor, S_BLOODYSKULLX1); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_CheckSkullDone +// +//---------------------------------------------------------------------------- + +void A_CheckSkullDone(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special2.i == 666) + { + P_SetMobjState(actor, S_BLOODYSKULLX2); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_CheckBurnGone +// +//---------------------------------------------------------------------------- + +void A_CheckBurnGone(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special2.i == 666) + { + P_SetMobjState(actor, S_PLAY_FDTH20); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FreeTargMobj +// +//---------------------------------------------------------------------------- + +void A_FreeTargMobj(mobj_t * mo, player_t *player, pspdef_t *psp) +{ + mo->momx = mo->momy = mo->momz = 0; + mo->z = mo->ceilingz + 4 * FRACUNIT; + mo->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_SOLID); + mo->flags |= MF_CORPSE | MF_DROPOFF | MF_NOGRAVITY; + mo->flags2 &= ~(MF2_PASSMOBJ | MF2_LOGRAV); + mo->player = NULL; +} + +//---------------------------------------------------------------------------- +// +// PROC A_AddPlayerCorpse +// +//---------------------------------------------------------------------------- + +#define BODYQUESIZE 32 +mobj_t *bodyque[BODYQUESIZE]; +int bodyqueslot; + +void A_AddPlayerCorpse(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (bodyqueslot >= BODYQUESIZE) + { // Too many player corpses - remove an old one + P_RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]); + } + bodyque[bodyqueslot % BODYQUESIZE] = actor; + bodyqueslot++; +} + +//---------------------------------------------------------------------------- +// +// PROC A_FlameSnd +// +//---------------------------------------------------------------------------- + +void A_FlameSnd(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(actor, sfx_hedat1); // Burn sound +} + +//---------------------------------------------------------------------------- +// +// PROC A_HideThing +// +//---------------------------------------------------------------------------- + +void A_HideThing(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + //P_UnsetThingPosition(actor); + actor->flags2 |= MF2_DONTDRAW; +} + +//---------------------------------------------------------------------------- +// +// PROC A_UnHideThing +// +//---------------------------------------------------------------------------- + +void A_UnHideThing(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + //P_SetThingPosition(actor); + actor->flags2 &= ~MF2_DONTDRAW; +} diff --git a/games/NXDoom/src/heretic/p_floor.c b/games/NXDoom/src/heretic/p_floor.c new file mode 100644 index 00000000000..d95a157aa49 --- /dev/null +++ b/games/NXDoom/src/heretic/p_floor.c @@ -0,0 +1,461 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +#include "doomdef.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +//================================================================== +//================================================================== +// +// FLOORS +// +//================================================================== +//================================================================== + + + +//================================================================== +// +// Move a plane (floor or ceiling) and check for crushing +// +//================================================================== +result_e T_MovePlane(sector_t * sector, fixed_t speed, + fixed_t dest, boolean crush, int floorOrCeiling, + int direction) +{ + boolean flag; + fixed_t lastpos; + + switch (floorOrCeiling) + { + case 0: // FLOOR + switch (direction) + { + case -1: // DOWN + if (sector->floorheight - speed < dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + //return crushed; + } + return pastdest; + } + else + { + lastpos = sector->floorheight; + sector->floorheight -= speed; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + return crushed; + } + } + break; + + case 1: // UP + if (sector->floorheight + speed > dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + //return crushed; + } + return pastdest; + } + else // COULD GET CRUSHED + { + lastpos = sector->floorheight; + sector->floorheight += speed; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + if (crush == true) + return crushed; + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + return crushed; + } + } + break; + } + break; + + case 1: // CEILING + switch (direction) + { + case -1: // DOWN + if (sector->ceilingheight - speed < dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + //return crushed; + } + return pastdest; + } + else // COULD GET CRUSHED + { + lastpos = sector->ceilingheight; + sector->ceilingheight -= speed; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + if (crush == true) + return crushed; + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + return crushed; + } + } + break; + + case 1: // UP + if (sector->ceilingheight + speed > dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + //return crushed; + } + return pastdest; + } + else + { + lastpos = sector->ceilingheight; + sector->ceilingheight += speed; + flag = P_ChangeSector(sector, crush); +#if 0 + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + return crushed; + } +#endif + } + break; + } + break; + + } + return ok; +} + +//================================================================== +// +// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) +// +//================================================================== +void T_MoveFloor(thinker_t *thinker) +{ + floormove_t *floor = (floormove_t *) thinker; + result_e res; + + res = T_MovePlane(floor->sector, floor->speed, + floor->floordestheight, floor->crush, 0, + floor->direction); + if (!(leveltime & 7)) + { + S_StartSound(&floor->sector->soundorg, sfx_dormov); + } + + if (res == pastdest) + { + floor->sector->specialdata = NULL; + if (floor->type == raiseBuildStep) + { + S_StartSound(&floor->sector->soundorg, sfx_pstop); + } + if (floor->direction == 1) + switch (floor->type) + { + case donutRaise: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + else if (floor->direction == -1) + switch (floor->type) + { + case lowerAndChange: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + P_RemoveThinker(&floor->thinker); + } + +} + +//================================================================== +// +// HANDLE FLOOR TYPES +// +//================================================================== +int EV_DoFloor(line_t * line, floor_e floortype) +{ + int secnum; + int rtn; + int i; + sector_t *sec; + floormove_t *floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // + // new floor thinker + // + rtn = 1; + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = floortype; + floor->crush = false; + switch (floortype) + { + case lowerFloor: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = P_FindHighestFloorSurrounding(sec); + break; + case lowerFloorToLowest: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = P_FindLowestFloorSurrounding(sec); + break; + case turboLower: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED * 4; + floor->floordestheight = (8 * FRACUNIT) + + P_FindHighestFloorSurrounding(sec); + break; + case raiseFloorCrush: + floor->crush = true; + case raiseFloor: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = P_FindLowestCeilingSurrounding(sec); + if (floor->floordestheight > sec->ceilingheight) + floor->floordestheight = sec->ceilingheight; + floor->floordestheight -= (8 * FRACUNIT) * + (floortype == raiseFloorCrush); + break; + case raiseFloorToNearest: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindNextHighestFloor(sec, sec->floorheight); + break; + case raiseFloor24: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 24 * FRACUNIT; + break; + case raiseFloor24AndChange: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 24 * FRACUNIT; + sec->floorpic = line->frontsector->floorpic; + sec->special = line->frontsector->special; + break; + case raiseToTexture: + { + int minsize = INT_MAX; + side_t *side; + + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + for (i = 0; i < sec->linecount; i++) + if (twoSided(secnum, i)) + { + side = getSide(secnum, i, 0); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < + minsize) + minsize = + textureheight[side->bottomtexture]; + side = getSide(secnum, i, 1); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < + minsize) + minsize = + textureheight[side->bottomtexture]; + } + floor->floordestheight = floor->sector->floorheight + + minsize; + } + break; + case lowerAndChange: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = P_FindLowestFloorSurrounding(sec); + floor->texture = sec->floorpic; + for (i = 0; i < sec->linecount; i++) + if (twoSided(secnum, i)) + { + if (getSide(secnum, i, 0)->sector - sectors == secnum) + { + sec = getSector(secnum, i, 1); + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + else + { + sec = getSector(secnum, i, 0); + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + default: + break; + } + } + return rtn; +} + +//================================================================== +// +// BUILD A STAIRCASE! +// +//================================================================== +int EV_BuildStairs(line_t * line, fixed_t stepDelta) +{ + int secnum; + int height; + int i; + int newsecnum; + int texture; + int ok; + int rtn; + sector_t *sec, *tsec; + floormove_t *floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // + // new floor thinker + // + rtn = 1; + height = sec->floorheight + stepDelta; + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = raiseBuildStep; + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = height; + + texture = sec->floorpic; + + // + // Find next sector to raise + // 1. Find 2-sided line with same sector side[0] + // 2. Other side is the next sector to raise + // + do + { + ok = 0; + for (i = 0; i < sec->linecount; i++) + { + if (!((sec->lines[i])->flags & ML_TWOSIDED)) + continue; + + tsec = (sec->lines[i])->frontsector; + newsecnum = tsec - sectors; + if (secnum != newsecnum) + continue; + tsec = (sec->lines[i])->backsector; + newsecnum = tsec - sectors; + if (tsec->floorpic != texture) + continue; + + height += stepDelta; + if (tsec->specialdata) + continue; + + sec = tsec; + secnum = newsecnum; + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = raiseBuildStep; + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = height; + ok = 1; + break; + } + } + while (ok); + } + return (rtn); +} diff --git a/games/NXDoom/src/heretic/p_inter.c b/games/NXDoom/src/heretic/p_inter.c new file mode 100644 index 00000000000..cf75a7dbf35 --- /dev/null +++ b/games/NXDoom/src/heretic/p_inter.c @@ -0,0 +1,1488 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_inter.c + +#include "doomdef.h" +#include "deh_str.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" +#include "am_map.h" + + +#define BONUSADD 6 + +int WeaponValue[] = { + 1, // staff + 3, // goldwand + 4, // crossbow + 5, // blaster + 6, // skullrod + 7, // phoenixrod + 8, // mace + 2, // gauntlets + 0 // beak +}; + +int maxammo[NUMAMMO] = { + 100, // gold wand + 50, // crossbow + 200, // blaster + 200, // skull rod + 20, // phoenix rod + 150 // mace +}; + +int GetWeaponAmmo[NUMWEAPONS] = { + 0, // staff + 25, // gold wand + 10, // crossbow + 30, // blaster + 50, // skull rod + 2, // phoenix rod + 50, // mace + 0, // gauntlets + 0 // beak +}; + +static weapontype_t GetAmmoChange[] = { + wp_goldwand, + wp_crossbow, + wp_blaster, + wp_skullrod, + wp_phoenixrod, + wp_mace +}; + +/* +static boolean GetAmmoChangePL1[NUMWEAPONS][NUMAMMO] = +{ + // staff + {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace}, + // gold wand + {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace}, + // crossbow + {-1, -1, wp_blaster, wp_skullrod, -1, -1}, + // blaster + {-1, -1, -1, -1, -1, -1}, + // skull rod + {-1, -1, -1, -1, -1, -1}, + // phoenix rod + {-1, -1, -1, -1, -1, -1}, + // mace + {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1}, + // gauntlets + {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace} +}; +*/ + +/* +static boolean GetAmmoChangePL2[NUMWEAPONS][NUMAMMO] = +{ + // staff + {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod, + wp_mace}, + // gold wand + {-1, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod, wp_mace}, + // crossbow + {-1, -1, wp_blaster, wp_skullrod, wp_phoenixrod, -1}, + // blaster + {-1, -1, -1, wp_skullrod, wp_phoenixrod, -1}, + // skull rod + {-1, -1, -1, -1, -1, -1}, + // phoenix rod + {-1, -1, -1, -1, -1, -1}, + // mace + {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1}, + // gauntlets + {-1, -1, -1, wp_skullrod, wp_phoenixrod, wp_mace} +}; +*/ + +//-------------------------------------------------------------------------- +// +// PROC P_SetMessage +// +//-------------------------------------------------------------------------- + +boolean ultimatemsg; + +void P_SetMessage(player_t * player, const char *message, boolean ultmsg) +{ + if ((ultimatemsg || !messageson) && !ultmsg) + { + return; + } + player->message = message; + player->messageTics = MESSAGETICS; + BorderTopRefresh = true; + if (ultmsg) + { + ultimatemsg = true; + } +} + +//-------------------------------------------------------------------------- +// +// FUNC P_GiveAmmo +// +// Returns true if the player accepted the ammo, false if it was +// refused (player has maxammo[ammo]). +// +//-------------------------------------------------------------------------- + +boolean P_GiveAmmo(player_t * player, ammotype_t ammo, int count) +{ + int prevAmmo; + //weapontype_t changeWeapon; + + if (ammo == am_noammo) + { + return (false); + } + if ((unsigned int) ammo >= NUMAMMO) + { + I_Error("P_GiveAmmo: bad type %i", ammo); + } + if (player->ammo[ammo] == player->maxammo[ammo]) + { + return (false); + } + if (gameskill == sk_baby || gameskill == sk_nightmare) + { // extra ammo in baby mode and nightmare mode + count += count >> 1; + } + prevAmmo = player->ammo[ammo]; + + player->ammo[ammo] += count; + if (player->ammo[ammo] > player->maxammo[ammo]) + { + player->ammo[ammo] = player->maxammo[ammo]; + } + if (prevAmmo) + { + // Don't attempt to change weapons if the player already had + // ammo of the type just given + return (true); + } + if (player->readyweapon == wp_staff + || player->readyweapon == wp_gauntlets) + { + if (player->weaponowned[GetAmmoChange[ammo]]) + { + player->pendingweapon = GetAmmoChange[ammo]; + } + } +/* + if(player->powers[pw_weaponlevel2]) + { + changeWeapon = GetAmmoChangePL2[player->readyweapon][ammo]; + } + else + { + changeWeapon = GetAmmoChangePL1[player->readyweapon][ammo]; + } + if(changeWeapon != -1) + { + if(player->weaponowned[changeWeapon]) + { + player->pendingweapon = changeWeapon; + } + } +*/ + return (true); +} + +//-------------------------------------------------------------------------- +// +// FUNC P_GiveWeapon +// +// Returns true if the weapon or its ammo was accepted. +// +//-------------------------------------------------------------------------- + +boolean P_GiveWeapon(player_t * player, weapontype_t weapon) +{ + boolean gaveAmmo; + boolean gaveWeapon; + + if (netgame && !deathmatch) + { // Cooperative net-game + if (player->weaponowned[weapon]) + { + return (false); + } + player->bonuscount += BONUSADD; + player->weaponowned[weapon] = true; + P_GiveAmmo(player, wpnlev1info[weapon].ammo, GetWeaponAmmo[weapon]); + player->pendingweapon = weapon; + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, sfx_wpnup); + } + return (false); + } + gaveAmmo = P_GiveAmmo(player, wpnlev1info[weapon].ammo, + GetWeaponAmmo[weapon]); + if (player->weaponowned[weapon]) + { + gaveWeapon = false; + } + else + { + gaveWeapon = true; + player->weaponowned[weapon] = true; + if (WeaponValue[weapon] > WeaponValue[player->readyweapon]) + { // Only switch to more powerful weapons + player->pendingweapon = weapon; + } + } + return (gaveWeapon || gaveAmmo); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveBody +// +// Returns false if the body isn't needed at all. +// +//--------------------------------------------------------------------------- + +boolean P_GiveBody(player_t * player, int num) +{ + int max; + + max = MAXHEALTH; + if (player->chickenTics) + { + max = MAXCHICKENHEALTH; + } + if (player->health >= max) + { + return (false); + } + player->health += num; + if (player->health > max) + { + player->health = max; + } + player->mo->health = player->health; + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveArmor +// +// Returns false if the armor is worse than the current armor. +// +//--------------------------------------------------------------------------- + +boolean P_GiveArmor(player_t * player, int armortype) +{ + int hits; + + hits = armortype * 100; + if (player->armorpoints >= hits) + { + return (false); + } + player->armortype = armortype; + player->armorpoints = hits; + return (true); +} + +//--------------------------------------------------------------------------- +// +// PROC P_GiveKey +// +//--------------------------------------------------------------------------- + +void P_GiveKey(player_t * player, keytype_t key) +{ + + if (player->keys[key]) + { + return; + } + if (player == &players[consoleplayer]) + { + playerkeys |= 1 << key; + KeyPoints[key].x = 0; + KeyPoints[key].y = 0; + } + player->bonuscount = BONUSADD; + player->keys[key] = true; +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GivePower +// +// Returns true if power accepted. +// +//--------------------------------------------------------------------------- + +boolean P_GivePower(player_t * player, powertype_t power) +{ + if (power == pw_invulnerability) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = INVULNTICS; + return (true); + } + if (power == pw_weaponlevel2) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = WPNLEV2TICS; + return (true); + } + if (power == pw_invisibility) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = INVISTICS; + player->mo->flags |= MF_SHADOW; + return (true); + } + if (power == pw_flight) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = FLIGHTTICS; + player->mo->flags2 |= MF2_FLY; + player->mo->flags |= MF_NOGRAVITY; + if (player->mo->z <= player->mo->floorz) + { + player->flyheight = 10; // thrust the player in the air a bit + } + return (true); + } + if (power == pw_infrared) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = INFRATICS; + return (true); + } +/* + if(power == pw_ironfeet) + { + player->powers[power] = IRONTICS; + return(true); + } + if(power == pw_strength) + { + P_GiveBody(player, 100); + player->powers[power] = 1; + return(true); + } +*/ + if (player->powers[power]) + { + return (false); // already got it + } + player->powers[power] = 1; + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveArtifact +// +// Returns true if artifact accepted. +// +//--------------------------------------------------------------------------- + +boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo) +{ + int i; + + i = 0; + while (player->inventory[i].type != arti && i < player->inventorySlotNum) + { + i++; + } + if (i == player->inventorySlotNum) + { + player->inventory[i].count = 1; + player->inventory[i].type = arti; + player->inventorySlotNum++; + } + else + { + if (player->inventory[i].count >= 16) + { // Player already has 16 of this item + return (false); + } + player->inventory[i].count++; + } + if (player->artifactCount == 0) + { + player->readyArtifact = arti; + } + player->artifactCount++; + if (mo && (mo->flags & MF_COUNTITEM)) + { + player->itemcount++; + } + return (true); +} + +//--------------------------------------------------------------------------- +// +// PROC P_SetDormantArtifact +// +// Removes the MF_SPECIAL flag, and initiates the artifact pickup +// animation. +// +//--------------------------------------------------------------------------- + +void P_SetDormantArtifact(mobj_t * arti) +{ + arti->flags &= ~MF_SPECIAL; + if (deathmatch && (arti->type != MT_ARTIINVULNERABILITY) + && (arti->type != MT_ARTIINVISIBILITY)) + { + P_SetMobjState(arti, S_DORMANTARTI1); + } + else + { // Don't respawn + P_SetMobjState(arti, S_DEADARTI1); + } + S_StartSound(arti, sfx_artiup); +} + +//--------------------------------------------------------------------------- +// +// PROC A_RestoreArtifact +// +//--------------------------------------------------------------------------- + +void A_RestoreArtifact(mobj_t * arti, player_t *player, pspdef_t *psp) +{ + arti->flags |= MF_SPECIAL; + P_SetMobjState(arti, arti->info->spawnstate); + S_StartSound(arti, sfx_respawn); +} + +//---------------------------------------------------------------------------- +// +// PROC P_HideSpecialThing +// +//---------------------------------------------------------------------------- + +void P_HideSpecialThing(mobj_t * thing) +{ + thing->flags &= ~MF_SPECIAL; + thing->flags2 |= MF2_DONTDRAW; + P_SetMobjState(thing, S_HIDESPECIAL1); +} + +//--------------------------------------------------------------------------- +// +// PROC A_RestoreSpecialThing1 +// +// Make a special thing visible again. +// +//--------------------------------------------------------------------------- + +void A_RestoreSpecialThing1(mobj_t * thing, player_t *player, pspdef_t *psp) +{ + if (thing->type == MT_WMACE) + { // Do random mace placement + P_RepositionMace(thing); + } + thing->flags2 &= ~MF2_DONTDRAW; + S_StartSound(thing, sfx_respawn); +} + +//--------------------------------------------------------------------------- +// +// PROC A_RestoreSpecialThing2 +// +//--------------------------------------------------------------------------- + +void A_RestoreSpecialThing2(mobj_t * thing, player_t *player, pspdef_t *psp) +{ + thing->flags |= MF_SPECIAL; + P_SetMobjState(thing, thing->info->spawnstate); +} + +//--------------------------------------------------------------------------- +// +// PROC P_TouchSpecialThing +// +//--------------------------------------------------------------------------- + +void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher) +{ + int i; + player_t *player; + fixed_t delta; + int sound; + boolean respawn; + + delta = special->z - toucher->z; + if (delta > toucher->height || delta < -32 * FRACUNIT) + { // Out of reach + return; + } + if (toucher->health <= 0) + { // Toucher is dead + return; + } + sound = sfx_itemup; + player = toucher->player; + respawn = true; + switch (special->sprite) + { + // Items + case SPR_PTN1: // Item_HealingPotion + if (!P_GiveBody(player, 10)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_ITEMHEALTH), false); + break; + case SPR_SHLD: // Item_Shield1 + if (!P_GiveArmor(player, 1)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_ITEMSHIELD1), false); + break; + case SPR_SHD2: // Item_Shield2 + if (!P_GiveArmor(player, 2)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_ITEMSHIELD2), false); + break; + case SPR_BAGH: // Item_BagOfHolding + if (!player->backpack) + { + for (i = 0; i < NUMAMMO; i++) + { + player->maxammo[i] *= 2; + } + player->backpack = true; + } + P_GiveAmmo(player, am_goldwand, AMMO_GWND_WIMPY); + P_GiveAmmo(player, am_blaster, AMMO_BLSR_WIMPY); + P_GiveAmmo(player, am_crossbow, AMMO_CBOW_WIMPY); + P_GiveAmmo(player, am_skullrod, AMMO_SKRD_WIMPY); + P_GiveAmmo(player, am_phoenixrod, AMMO_PHRD_WIMPY); + P_SetMessage(player, DEH_String(TXT_ITEMBAGOFHOLDING), false); + break; + case SPR_SPMP: // Item_SuperMap + if (!P_GivePower(player, pw_allmap)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_ITEMSUPERMAP), false); + break; + + // Keys + case SPR_BKYY: // Key_Blue + if (!player->keys[key_blue]) + { + P_SetMessage(player, DEH_String(TXT_GOTBLUEKEY), false); + } + P_GiveKey(player, key_blue); + sound = sfx_keyup; + if (!netgame) + { + break; + } + return; + case SPR_CKYY: // Key_Yellow + if (!player->keys[key_yellow]) + { + P_SetMessage(player, DEH_String(TXT_GOTYELLOWKEY), false); + } + sound = sfx_keyup; + P_GiveKey(player, key_yellow); + if (!netgame) + { + break; + } + return; + case SPR_AKYY: // Key_Green + if (!player->keys[key_green]) + { + P_SetMessage(player, DEH_String(TXT_GOTGREENKEY), false); + } + sound = sfx_keyup; + P_GiveKey(player, key_green); + if (!netgame) + { + break; + } + return; + + // Artifacts + case SPR_PTN2: // Arti_HealingPotion + if (P_GiveArtifact(player, arti_health, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTIHEALTH), false); + P_SetDormantArtifact(special); + } + return; + case SPR_SOAR: // Arti_Fly + if (P_GiveArtifact(player, arti_fly, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTIFLY), false); + P_SetDormantArtifact(special); + } + return; + case SPR_INVU: // Arti_Invulnerability + if (P_GiveArtifact(player, arti_invulnerability, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTIINVULNERABILITY), false); + P_SetDormantArtifact(special); + } + return; + case SPR_PWBK: // Arti_TomeOfPower + if (P_GiveArtifact(player, arti_tomeofpower, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTITOMEOFPOWER), false); + P_SetDormantArtifact(special); + } + return; + case SPR_INVS: // Arti_Invisibility + if (P_GiveArtifact(player, arti_invisibility, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTIINVISIBILITY), false); + P_SetDormantArtifact(special); + } + return; + case SPR_EGGC: // Arti_Egg + if (P_GiveArtifact(player, arti_egg, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTIEGG), false); + P_SetDormantArtifact(special); + } + return; + case SPR_SPHL: // Arti_SuperHealth + if (P_GiveArtifact(player, arti_superhealth, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTISUPERHEALTH), false); + P_SetDormantArtifact(special); + } + return; + case SPR_TRCH: // Arti_Torch + if (P_GiveArtifact(player, arti_torch, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTITORCH), false); + P_SetDormantArtifact(special); + } + return; + case SPR_FBMB: // Arti_FireBomb + if (P_GiveArtifact(player, arti_firebomb, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTIFIREBOMB), false); + P_SetDormantArtifact(special); + } + return; + case SPR_ATLP: // Arti_Teleport + if (P_GiveArtifact(player, arti_teleport, special)) + { + P_SetMessage(player, DEH_String(TXT_ARTITELEPORT), false); + P_SetDormantArtifact(special); + } + return; + + // Ammo + case SPR_AMG1: // Ammo_GoldWandWimpy + if (!P_GiveAmmo(player, am_goldwand, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOGOLDWAND1), false); + break; + case SPR_AMG2: // Ammo_GoldWandHefty + if (!P_GiveAmmo(player, am_goldwand, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOGOLDWAND2), false); + break; + case SPR_AMM1: // Ammo_MaceWimpy + if (!P_GiveAmmo(player, am_mace, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOMACE1), false); + break; + case SPR_AMM2: // Ammo_MaceHefty + if (!P_GiveAmmo(player, am_mace, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOMACE2), false); + break; + case SPR_AMC1: // Ammo_CrossbowWimpy + if (!P_GiveAmmo(player, am_crossbow, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOCROSSBOW1), false); + break; + case SPR_AMC2: // Ammo_CrossbowHefty + if (!P_GiveAmmo(player, am_crossbow, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOCROSSBOW2), false); + break; + case SPR_AMB1: // Ammo_BlasterWimpy + if (!P_GiveAmmo(player, am_blaster, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOBLASTER1), false); + break; + case SPR_AMB2: // Ammo_BlasterHefty + if (!P_GiveAmmo(player, am_blaster, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOBLASTER2), false); + break; + case SPR_AMS1: // Ammo_SkullRodWimpy + if (!P_GiveAmmo(player, am_skullrod, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOSKULLROD1), false); + break; + case SPR_AMS2: // Ammo_SkullRodHefty + if (!P_GiveAmmo(player, am_skullrod, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOSKULLROD2), false); + break; + case SPR_AMP1: // Ammo_PhoenixRodWimpy + if (!P_GiveAmmo(player, am_phoenixrod, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOPHOENIXROD1), false); + break; + case SPR_AMP2: // Ammo_PhoenixRodHefty + if (!P_GiveAmmo(player, am_phoenixrod, special->health)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_AMMOPHOENIXROD2), false); + break; + + // Weapons + case SPR_WMCE: // Weapon_Mace + if (!P_GiveWeapon(player, wp_mace)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_WPNMACE), false); + sound = sfx_wpnup; + break; + case SPR_WBOW: // Weapon_Crossbow + if (!P_GiveWeapon(player, wp_crossbow)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_WPNCROSSBOW), false); + sound = sfx_wpnup; + break; + case SPR_WBLS: // Weapon_Blaster + if (!P_GiveWeapon(player, wp_blaster)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_WPNBLASTER), false); + sound = sfx_wpnup; + break; + case SPR_WSKL: // Weapon_SkullRod + if (!P_GiveWeapon(player, wp_skullrod)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_WPNSKULLROD), false); + sound = sfx_wpnup; + break; + case SPR_WPHX: // Weapon_PhoenixRod + if (!P_GiveWeapon(player, wp_phoenixrod)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_WPNPHOENIXROD), false); + sound = sfx_wpnup; + break; + case SPR_WGNT: // Weapon_Gauntlets + if (!P_GiveWeapon(player, wp_gauntlets)) + { + return; + } + P_SetMessage(player, DEH_String(TXT_WPNGAUNTLETS), false); + sound = sfx_wpnup; + break; + default: + I_Error("P_SpecialThing: Unknown gettable thing"); + } + if (special->flags & MF_COUNTITEM) + { + player->itemcount++; + } + if (deathmatch && respawn && !(special->flags & MF_DROPPED)) + { + P_HideSpecialThing(special); + } + else + { + P_RemoveMobj(special); + } + player->bonuscount += BONUSADD; + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, sound); + SB_PaletteFlash(); + } +} + +//--------------------------------------------------------------------------- +// +// PROC P_KillMobj +// +//--------------------------------------------------------------------------- + +void P_KillMobj(mobj_t * source, mobj_t * target) +{ + target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_NOGRAVITY); + target->flags |= MF_CORPSE | MF_DROPOFF; + target->flags2 &= ~MF2_PASSMOBJ; + target->height >>= 2; + if (source && source->player) + { + if (target->flags & MF_COUNTKILL) + { // Count for intermission + source->player->killcount++; + } + if (target->player) + { // Frag stuff + if (target == source) + { // Self-frag + target->player->frags[target->player - players]--; + } + else + { + source->player->frags[target->player - players]++; + if (source->player == &players[consoleplayer]) + { + S_StartSound(NULL, sfx_gfrag); + } + if (source->player->chickenTics) + { // Make a super chicken + P_GivePower(source->player, pw_weaponlevel2); + } + } + } + } + else if (!netgame && (target->flags & MF_COUNTKILL)) + { // Count all monster deaths + players[0].killcount++; + } + if (target->player) + { + if (!source) + { // Self-frag + target->player->frags[target->player - players]--; + } + target->flags &= ~MF_SOLID; + target->flags2 &= ~MF2_FLY; + target->player->powers[pw_flight] = 0; + target->player->powers[pw_weaponlevel2] = 0; + target->player->playerstate = PST_DEAD; + P_DropWeapon(target->player); + if (target->flags2 & MF2_FIREDAMAGE) + { // Player flame death + P_SetMobjState(target, S_PLAY_FDTH1); + //S_StartSound(target, sfx_hedat1); // Burn sound + return; + } + } + if (target->health < -(target->info->spawnhealth >> 1) + && target->info->xdeathstate) + { // Extreme death + P_SetMobjState(target, target->info->xdeathstate); + } + else + { // Normal death + P_SetMobjState(target, target->info->deathstate); + } + target->tics -= P_Random() & 3; +// I_StartSound(&actor->r, actor->info->deathsound); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_MinotaurSlam +// +//--------------------------------------------------------------------------- + +void P_MinotaurSlam(mobj_t * source, mobj_t * target) +{ + angle_t angle; + fixed_t thrust; + + angle = R_PointToAngle2(source->x, source->y, target->x, target->y); + angle >>= ANGLETOFINESHIFT; + thrust = 16 * FRACUNIT + (P_Random() << 10); + target->momx += FixedMul(thrust, finecosine[angle]); + target->momy += FixedMul(thrust, finesine[angle]); + P_DamageMobj(target, NULL, NULL, HITDICE(6)); + if (target->player) + { + target->reactiontime = 14 + (P_Random() & 7); + } +} + +//--------------------------------------------------------------------------- +// +// FUNC P_TouchWhirlwind +// +//--------------------------------------------------------------------------- + +void P_TouchWhirlwind(mobj_t * target) +{ + int randVal; + + target->angle += P_SubRandom() << 20; + target->momx += P_SubRandom() << 10; + target->momy += P_SubRandom() << 10; + if (leveltime & 16 && !(target->flags2 & MF2_BOSS)) + { + randVal = P_Random(); + if (randVal > 160) + { + randVal = 160; + } + target->momz += randVal << 10; + if (target->momz > 12 * FRACUNIT) + { + target->momz = 12 * FRACUNIT; + } + } + if (!(leveltime & 7)) + { + P_DamageMobj(target, NULL, NULL, 3); + } +} + +//--------------------------------------------------------------------------- +// +// FUNC P_ChickenMorphPlayer +// +// Returns true if the player gets turned into a chicken. +// +//--------------------------------------------------------------------------- + +boolean P_ChickenMorphPlayer(player_t * player) +{ + mobj_t *pmo; + mobj_t *fog; + mobj_t *chicken; + fixed_t x; + fixed_t y; + fixed_t z; + angle_t angle; + int oldFlags2; + + if (player->chickenTics) + { + if ((player->chickenTics < CHICKENTICS - TICRATE) + && !player->powers[pw_weaponlevel2]) + { // Make a super chicken + P_GivePower(player, pw_weaponlevel2); + } + return (false); + } + if (player->powers[pw_invulnerability]) + { // Immune when invulnerable + return (false); + } + pmo = player->mo; + x = pmo->x; + y = pmo->y; + z = pmo->z; + angle = pmo->angle; + oldFlags2 = pmo->flags2; + P_SetMobjState(pmo, S_FREETARGMOBJ); + fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, sfx_telept); + chicken = P_SpawnMobj(x, y, z, MT_CHICPLAYER); + chicken->special1.i = player->readyweapon; + chicken->angle = angle; + chicken->player = player; + player->health = chicken->health = MAXCHICKENHEALTH; + player->mo = chicken; + player->armorpoints = player->armortype = 0; + player->powers[pw_invisibility] = 0; + player->powers[pw_weaponlevel2] = 0; + if (oldFlags2 & MF2_FLY) + { + chicken->flags2 |= MF2_FLY; + } + player->chickenTics = CHICKENTICS; + P_ActivateBeak(player); + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_ChickenMorph +// +//--------------------------------------------------------------------------- + +boolean P_ChickenMorph(mobj_t * actor) +{ + mobj_t *fog; + mobj_t *chicken; + mobj_t *target; + mobjtype_t moType; + fixed_t x; + fixed_t y; + fixed_t z; + angle_t angle; + int ghost; + + if (actor->player) + { + return (false); + } + moType = actor->type; + switch (moType) + { + case MT_POD: + case MT_CHICKEN: + case MT_HEAD: + case MT_MINOTAUR: + case MT_SORCERER1: + case MT_SORCERER2: + return (false); + default: + break; + } + x = actor->x; + y = actor->y; + z = actor->z; + angle = actor->angle; + ghost = actor->flags & MF_SHADOW; + target = actor->target; + P_SetMobjState(actor, S_FREETARGMOBJ); + fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, sfx_telept); + chicken = P_SpawnMobj(x, y, z, MT_CHICKEN); + chicken->special2.i = moType; + chicken->special1.i = CHICKENTICS + P_Random(); + chicken->flags |= ghost; + chicken->target = target; + chicken->angle = angle; + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_AutoUseChaosDevice +// +//--------------------------------------------------------------------------- + +boolean P_AutoUseChaosDevice(player_t * player) +{ + int i; + + for (i = 0; i < player->inventorySlotNum; i++) + { + if (player->inventory[i].type == arti_teleport) + { + P_PlayerUseArtifact(player, arti_teleport); + player->health = player->mo->health = (player->health + 1) / 2; + return (true); + } + } + return (false); +} + +//--------------------------------------------------------------------------- +// +// PROC P_AutoUseHealth +// +//--------------------------------------------------------------------------- + +void P_AutoUseHealth(player_t * player, int saveHealth) +{ + int i; + int count; + int normalCount; + int normalSlot; + int superCount; + int superSlot; + + normalCount = 0; + superCount = 0; + normalSlot = 0; + superSlot = 0; + + for (i = 0; i < player->inventorySlotNum; i++) + { + if (player->inventory[i].type == arti_health) + { + normalSlot = i; + normalCount = player->inventory[i].count; + } + else if (player->inventory[i].type == arti_superhealth) + { + superSlot = i; + superCount = player->inventory[i].count; + } + } + if ((gameskill == sk_baby) && (normalCount * 25 >= saveHealth)) + { // Use quartz flasks + count = (saveHealth + 24) / 25; + for (i = 0; i < count; i++) + { + player->health += 25; + P_PlayerRemoveArtifact(player, normalSlot); + } + } + else if (superCount * 100 >= saveHealth) + { // Use mystic urns + count = (saveHealth + 99) / 100; + for (i = 0; i < count; i++) + { + player->health += 100; + P_PlayerRemoveArtifact(player, superSlot); + } + } + else if ((gameskill == sk_baby) + && (superCount * 100 + normalCount * 25 >= saveHealth)) + { // Use mystic urns and quartz flasks + count = (saveHealth + 24) / 25; + saveHealth -= count * 25; + for (i = 0; i < count; i++) + { + player->health += 25; + P_PlayerRemoveArtifact(player, normalSlot); + } + count = (saveHealth + 99) / 100; + for (i = 0; i < count; i++) + { + player->health += 100; + P_PlayerRemoveArtifact(player, normalSlot); + } + } + player->mo->health = player->health; +} + +/* +================= += += P_DamageMobj += += Damages both enemies and players += inflictor is the thing that caused the damage += creature or missile, can be NULL (slime, etc) += source is the thing to target after taking damage += creature or NULL += Source and inflictor are the same for melee attacks += source can be null for barrel explosions and other environmental stuff +================== +*/ + +void P_DamageMobj + (mobj_t * target, mobj_t * inflictor, mobj_t * source, int damage) +{ + unsigned ang; + int saved; + player_t *player; + fixed_t thrust; + int temp; + + if (!(target->flags & MF_SHOOTABLE)) + { + // Shouldn't happen + return; + } + if (target->health <= 0) + { + return; + } + if (target->flags & MF_SKULLFLY) + { + if (target->type == MT_MINOTAUR) + { // Minotaur is invulnerable during charge attack + return; + } + target->momx = target->momy = target->momz = 0; + } + player = target->player; + if (player && gameskill == sk_baby) + { + // Take half damage in trainer mode + damage >>= 1; + } + // Special damage types + if (inflictor) + { + switch (inflictor->type) + { + case MT_EGGFX: + if (player) + { + P_ChickenMorphPlayer(player); + } + else + { + P_ChickenMorph(target); + } + return; // Always return + case MT_WHIRLWIND: + P_TouchWhirlwind(target); + return; + case MT_MINOTAUR: + if (inflictor->flags & MF_SKULLFLY) + { // Slam only when in charge mode + P_MinotaurSlam(inflictor, target); + return; + } + break; + case MT_MACEFX4: // Death ball + if ((target->flags2 & MF2_BOSS) || target->type == MT_HEAD) + { // Don't allow cheap boss kills + break; + } + else if (target->player) + { // Player specific checks + if (target->player->powers[pw_invulnerability]) + { // Can't hurt invulnerable players + break; + } + if (P_AutoUseChaosDevice(target->player)) + { // Player was saved using chaos device + return; + } + } + damage = 10000; // Something's gonna die + break; + case MT_PHOENIXFX2: // Flame thrower + if (target->player && P_Random() < 128) + { // Freeze player for a bit + target->reactiontime += 4; + } + break; + case MT_RAINPLR1: // Rain missiles + case MT_RAINPLR2: + case MT_RAINPLR3: + case MT_RAINPLR4: + if (target->flags2 & MF2_BOSS) + { // Decrease damage for bosses + damage = (P_Random() & 7) + 1; + } + break; + case MT_HORNRODFX2: + case MT_PHOENIXFX1: + if (target->type == MT_SORCERER2 && P_Random() < 96) + { // D'Sparil teleports away + P_DSparilTeleport(target); + return; + } + break; + case MT_BLASTERFX1: + case MT_RIPPER: + if (target->type == MT_HEAD) + { // Less damage to Ironlich bosses + damage = P_Random() & 1; + if (!damage) + { + return; + } + } + break; + default: + break; + } + } + // Push the target unless source is using the gauntlets + if (inflictor && (!source || !source->player + || source->player->readyweapon != wp_gauntlets) + && !(inflictor->flags2 & MF2_NODMGTHRUST)) + { + ang = R_PointToAngle2(inflictor->x, inflictor->y, + target->x, target->y); + //thrust = damage*(FRACUNIT>>3)*100/target->info->mass; + // We do this multiplication in unsigned because it might overflow + // and signed overflow is undefined behavior + // but then we must cast it back to signed for the division + // to match original behavior + // unsigned to signed cast is implementation defined behavior at worst + thrust = ((int) (damage * (FRACUNIT >> 3) * 150u)) / target->info->mass; + // make fall forwards sometimes + if ((damage < 40) && (damage > target->health) + && (target->z - inflictor->z > 64 * FRACUNIT) && (P_Random() & 1)) + { + ang += ANG180; + thrust *= 4; + } + ang >>= ANGLETOFINESHIFT; + if (source && source->player && (source == inflictor) + && source->player->powers[pw_weaponlevel2] + && source->player->readyweapon == wp_staff) + { + // Staff power level 2 + target->momx += FixedMul(10 * FRACUNIT, finecosine[ang]); + target->momy += FixedMul(10 * FRACUNIT, finesine[ang]); + if (!(target->flags & MF_NOGRAVITY)) + { + target->momz += 5 * FRACUNIT; + } + } + else + { + target->momx += FixedMul(thrust, finecosine[ang]); + target->momy += FixedMul(thrust, finesine[ang]); + } + } + + // + // player specific + // + if (player) + { + // end of game hell hack + //if(target->subsector->sector->special == 11 + // && damage >= target->health) + //{ + // damage = target->health - 1; + //} + + if (damage < 1000 && ((player->cheats & CF_GODMODE) + || player->powers[pw_invulnerability])) + { + return; + } + if (player->armortype) + { + if (player->armortype == 1) + { + saved = damage >> 1; + } + else + { + saved = (damage >> 1) + (damage >> 2); + } + if (player->armorpoints <= saved) + { + // armor is used up + saved = player->armorpoints; + player->armortype = 0; + } + player->armorpoints -= saved; + damage -= saved; + } + if (damage >= player->health + && ((gameskill == sk_baby) || deathmatch) && !player->chickenTics) + { // Try to use some inventory health + P_AutoUseHealth(player, damage - player->health + 1); + } + player->health -= damage; // mirror mobj health here for Dave + if (player->health < 0) + { + player->health = 0; + } + player->attacker = source; + player->damagecount += damage; // add damage after armor / invuln + if (player->damagecount > 100) + { + player->damagecount = 100; // teleport stomp does 10k points... + } + temp = damage < 100 ? damage : 100; + if (player == &players[consoleplayer]) + { + I_Tactile(40, 10, 40 + temp * 2); + SB_PaletteFlash(); + } + } + + // + // do the damage + // + target->health -= damage; + if (target->health <= 0) + { // Death + target->special1.i = damage; + if (target->type == MT_POD && source && source->type != MT_POD) + { // Make sure players get frags for chain-reaction kills + target->target = source; + } + if (player && inflictor && !player->chickenTics) + { // Check for flame death + if ((inflictor->flags2 & MF2_FIREDAMAGE) + || ((inflictor->type == MT_PHOENIXFX1) + && (target->health > -50) && (damage > 25))) + { + target->flags2 |= MF2_FIREDAMAGE; + } + } + P_KillMobj(source, target); + return; + } + if ((P_Random() < target->info->painchance) + && !(target->flags & MF_SKULLFLY)) + { + target->flags |= MF_JUSTHIT; // fight back! + P_SetMobjState(target, target->info->painstate); + } + target->reactiontime = 0; // we're awake now... + if (!target->threshold && source && !(source->flags2 & MF2_BOSS) + && !(target->type == MT_SORCERER2 && source->type == MT_WIZARD)) + { + // Target actor is not intent on another actor, + // so make him chase after source + target->target = source; + target->threshold = BASETHRESHOLD; + if (target->state == &states[target->info->spawnstate] + && target->info->seestate != S_NULL) + { + P_SetMobjState(target, target->info->seestate); + } + } +} diff --git a/games/NXDoom/src/heretic/p_lights.c b/games/NXDoom/src/heretic/p_lights.c new file mode 100644 index 00000000000..407041b3c05 --- /dev/null +++ b/games/NXDoom/src/heretic/p_lights.c @@ -0,0 +1,280 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +#include "doomdef.h" +#include "m_random.h" +#include "p_local.h" +#include "v_video.h" + +//================================================================== +//================================================================== +// +// BROKEN LIGHT FLASHING +// +//================================================================== +//================================================================== + +//================================================================== +// +// T_LightFlash +// +// After the map has been loaded, scan each sector for specials +// that spawn thinkers +// +//================================================================== +void T_LightFlash(thinker_t *thinker) +{ + lightflash_t *flash = (lightflash_t *) thinker; + + if (--flash->count) + return; + + if (flash->sector->lightlevel == flash->maxlight) + { + flash->sector->lightlevel = flash->minlight; + flash->count = (P_Random() & flash->mintime) + 1; + } + else + { + flash->sector->lightlevel = flash->maxlight; + flash->count = (P_Random() & flash->maxtime) + 1; + } + +} + + +//================================================================== +// +// P_SpawnLightFlash +// +// After the map has been loaded, scan each sector for specials that spawn thinkers +// +//================================================================== +void P_SpawnLightFlash(sector_t * sector) +{ + lightflash_t *flash; + + sector->special = 0; // nothing special about it during gameplay + + flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0); + P_AddThinker(&flash->thinker); + flash->thinker.function = T_LightFlash; + flash->sector = sector; + flash->maxlight = sector->lightlevel; + + flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); + flash->maxtime = 64; + flash->mintime = 7; + flash->count = (P_Random() & flash->maxtime) + 1; +} + +//================================================================== +// +// STROBE LIGHT FLASHING +// +//================================================================== + +//================================================================== +// +// T_StrobeFlash +// +// After the map has been loaded, scan each sector for specials that spawn thinkers +// +//================================================================== +void T_StrobeFlash(thinker_t *thinker) +{ + strobe_t *flash = (strobe_t *) thinker; + + if (--flash->count) + return; + + if (flash->sector->lightlevel == flash->minlight) + { + flash->sector->lightlevel = flash->maxlight; + flash->count = flash->brighttime; + } + else + { + flash->sector->lightlevel = flash->minlight; + flash->count = flash->darktime; + } + +} + +//================================================================== +// +// P_SpawnLightFlash +// +// After the map has been loaded, scan each sector for specials that spawn thinkers +// +//================================================================== +void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync) +{ + strobe_t *flash; + + flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0); + P_AddThinker(&flash->thinker); + flash->sector = sector; + flash->darktime = fastOrSlow; + flash->brighttime = STROBEBRIGHT; + flash->thinker.function = T_StrobeFlash; + flash->maxlight = sector->lightlevel; + flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); + + if (flash->minlight == flash->maxlight) + flash->minlight = 0; + sector->special = 0; // nothing special about it during gameplay + + if (!inSync) + flash->count = (P_Random() & 7) + 1; + else + flash->count = 1; +} + +//================================================================== +// +// Start strobing lights (usually from a trigger) +// +//================================================================== +void EV_StartLightStrobing(line_t * line) +{ + int secnum; + sector_t *sec; + + secnum = -1; + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + P_SpawnStrobeFlash(sec, SLOWDARK, 0); + } +} + +//================================================================== +// +// TURN LINE'S TAG LIGHTS OFF +// +//================================================================== +void EV_TurnTagLightsOff(line_t * line) +{ + int i; + int j; + int min; + sector_t *sector; + sector_t *tsec; + line_t *templine; + + sector = sectors; + for (j = 0; j < numsectors; j++, sector++) + if (sector->tag == line->tag) + { + min = sector->lightlevel; + for (i = 0; i < sector->linecount; i++) + { + templine = sector->lines[i]; + tsec = getNextSector(templine, sector); + if (!tsec) + continue; + if (tsec->lightlevel < min) + min = tsec->lightlevel; + } + sector->lightlevel = min; + } +} + +//================================================================== +// +// TURN LINE'S TAG LIGHTS ON +// +//================================================================== +void EV_LightTurnOn(line_t * line, int bright) +{ + int i; + int j; + sector_t *sector; + sector_t *temp; + line_t *templine; + + sector = sectors; + + for (i = 0; i < numsectors; i++, sector++) + if (sector->tag == line->tag) + { + // + // bright = 0 means to search for highest + // light level surrounding sector + // + if (!bright) + { + for (j = 0; j < sector->linecount; j++) + { + templine = sector->lines[j]; + temp = getNextSector(templine, sector); + if (!temp) + continue; + if (temp->lightlevel > bright) + bright = temp->lightlevel; + } + } + sector->lightlevel = bright; + } +} + +//================================================================== +// +// Spawn glowing light +// +//================================================================== +void T_Glow(thinker_t *thinker) +{ + glow_t *g = (glow_t *) thinker; + + switch (g->direction) + { + case -1: // DOWN + g->sector->lightlevel -= GLOWSPEED; + if (g->sector->lightlevel <= g->minlight) + { + g->sector->lightlevel += GLOWSPEED; + g->direction = 1; + } + break; + case 1: // UP + g->sector->lightlevel += GLOWSPEED; + if (g->sector->lightlevel >= g->maxlight) + { + g->sector->lightlevel -= GLOWSPEED; + g->direction = -1; + } + break; + } +} + +void P_SpawnGlowingLight(sector_t * sector) +{ + glow_t *g; + + g = Z_Malloc(sizeof(*g), PU_LEVSPEC, 0); + P_AddThinker(&g->thinker); + g->sector = sector; + g->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); + g->maxlight = sector->lightlevel; + g->thinker.function = T_Glow; + g->direction = -1; + + sector->special = 0; +} diff --git a/games/NXDoom/src/heretic/p_local.h b/games/NXDoom/src/heretic/p_local.h new file mode 100644 index 00000000000..6137d3d0d67 --- /dev/null +++ b/games/NXDoom/src/heretic/p_local.h @@ -0,0 +1,292 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_local.h + +#ifndef __P_LOCAL__ +#define __P_LOCAL__ + +#ifndef __R_LOCAL__ +#include "r_local.h" +#endif + +#define STARTREDPALS 1 +#define STARTBONUSPALS 9 +#define NUMREDPALS 8 +#define NUMBONUSPALS 4 + +#define FOOTCLIPSIZE 10*FRACUNIT + +#define TOCENTER -8 +#define FLOATSPEED (FRACUNIT*4) + +#define MAXHEALTH 100 +#define MAXCHICKENHEALTH 30 +#define VIEWHEIGHT (41*FRACUNIT) + +// mapblocks are used to check movement against lines and things +#define MAPBLOCKUNITS 128 +#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) +#define MAPBLOCKSHIFT (FRACBITS+7) +#define MAPBMASK (MAPBLOCKSIZE-1) +#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) + +// player radius for movement checking +#define PLAYERRADIUS 16*FRACUNIT + +// MAXRADIUS is for precalculated sector block boxes +// the spider demon is larger, but we don't have any moving sectors +// nearby +#define MAXRADIUS 32*FRACUNIT + +#define GRAVITY FRACUNIT +#define MAXMOVE (30*FRACUNIT) + +#define USERANGE (64*FRACUNIT) +#define MELEERANGE (64*FRACUNIT) +#define MISSILERANGE (32*64*FRACUNIT) + +typedef enum +{ + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS +} dirtype_t; + +#define BASETHRESHOLD 100 // follow a player exlusively for 3 seconds + +// ***** P_TICK ***** + +extern thinker_t thinkercap; // both the head and tail of the thinker list +extern int TimerGame; // tic countdown for deathmatch + +void P_InitThinkers(void); +void P_AddThinker(thinker_t * thinker); +void P_RemoveThinker(thinker_t * thinker); + +// ***** P_PSPR ***** + +#define USE_GWND_AMMO_1 1 +#define USE_GWND_AMMO_2 1 +#define USE_CBOW_AMMO_1 1 +#define USE_CBOW_AMMO_2 1 +#define USE_BLSR_AMMO_1 1 +#define USE_BLSR_AMMO_2 5 +#define USE_SKRD_AMMO_1 1 +#define USE_SKRD_AMMO_2 5 +#define USE_PHRD_AMMO_1 1 +#define USE_PHRD_AMMO_2 1 +#define USE_MACE_AMMO_1 1 +#define USE_MACE_AMMO_2 5 + +void P_OpenWeapons(void); +void P_CloseWeapons(void); +void P_AddMaceSpot(mapthing_t * mthing); +void P_RepositionMace(mobj_t * mo); +void P_SetPsprite(player_t * player, int position, statenum_t stnum); +void P_SetupPsprites(player_t * curplayer); +void P_MovePsprites(player_t * curplayer); +void P_DropWeapon(player_t * player); +void P_ActivateBeak(player_t * player); +void P_PostChickenWeapon(player_t * player, weapontype_t weapon); +void P_UpdateBeak(player_t * player, pspdef_t * psp); + +// ***** P_USER ***** + +void P_PlayerThink(player_t * player); +void P_Thrust(player_t * player, angle_t angle, fixed_t move); +void P_PlayerRemoveArtifact(player_t * player, int slot); +void P_PlayerUseArtifact(player_t * player, artitype_t arti); +boolean P_UseArtifact(player_t * player, artitype_t arti); +int P_GetPlayerNum(player_t * player); +boolean P_UndoPlayerChicken(player_t *player); + + +// ***** P_MOBJ ***** + +#define FLOOR_SOLID 0 +#define FLOOR_WATER 1 +#define FLOOR_LAVA 2 +#define FLOOR_SLUDGE 3 + +#define ONFLOORZ INT_MIN +#define ONCEILINGZ INT_MAX +#define FLOATRANDZ (INT_MAX-1) + +extern mobjtype_t PuffType; +extern mobj_t *MissileMobj; + +mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); +void P_RemoveMobj(mobj_t * th); +boolean P_SetMobjState(mobj_t * mobj, statenum_t state); +boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state); +void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move); +int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta); +boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax); +void P_MobjThinker(thinker_t *thinker); +void P_BlasterMobjThinker(thinker_t *thinker); +void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z); +void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage); +void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator); +void P_RipperBlood(mobj_t * mo); +int P_GetThingFloorType(mobj_t * thing); +int P_HitFloor(mobj_t * thing); +boolean P_CheckMissileSpawn(mobj_t * missile); +mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type); +mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, + angle_t angle, fixed_t momz); +mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type); +mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle); + +// ***** P_ENEMY ***** + +void P_NoiseAlert(mobj_t * target, mobj_t * emmiter); +void P_InitMonsters(void); +void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle); +void P_Massacre(void); +void P_DSparilTeleport(mobj_t * actor); + +// ***** P_MAPUTL ***** + +typedef struct +{ + fixed_t x, y, dx, dy; +} divline_t; + +typedef struct +{ + fixed_t frac; // along trace line + boolean isaline; + union + { + mobj_t *thing; + line_t *line; + } d; +} intercept_t; + +#define MAXINTERCEPTS 128 +extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p; +typedef boolean(*traverser_t) (intercept_t * in); + + +fixed_t P_AproxDistance(fixed_t dx, fixed_t dy); +int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line); +int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line); +void P_MakeDivline(line_t * li, divline_t * dl); +fixed_t P_InterceptVector(divline_t * v2, divline_t * v1); +int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld); + +extern fixed_t opentop, openbottom, openrange; +extern fixed_t lowfloor; +void P_LineOpening(line_t * linedef); + +boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)); +boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)); + +#define PT_ADDLINES 1 +#define PT_ADDTHINGS 2 +#define PT_EARLYOUT 4 + +extern divline_t trace; +boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, + int flags, boolean(*trav) (intercept_t *)); + +void P_UnsetThingPosition(mobj_t * thing); +void P_SetThingPosition(mobj_t * thing); + +// ***** P_MAP ***** + +extern boolean floatok; // if true, move would be ok if +extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz + +extern line_t *ceilingline; +boolean P_TestMobjLocation(mobj_t * mobj); +boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y); +mobj_t *P_CheckOnmobj(mobj_t * thing); +void P_FakeZMovement(mobj_t * mo); +boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y); +boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y); +void P_SlideMove(mobj_t * mo); + +extern fixed_t topslope, bottomslope; // slopes to top and bottom of target + +boolean P_CheckSight(mobj_t * t1, mobj_t * t2); +void P_UseLines(player_t * player); + +boolean P_ChangeSector(sector_t * sector, boolean crunch); + +extern mobj_t *linetarget; // who got hit (or NULL) +fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance); + +void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, + int damage); + +void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage); + +#define MAXSPECIALCROSS 8 +extern line_t *spechit[MAXSPECIALCROSS]; +extern int numspechit; + + +// ***** P_SETUP ***** + +extern byte *rejectmatrix; // for fast sight rejection +extern short *blockmaplump; // offsets in blockmap are from here +extern short *blockmap; +extern int bmapwidth, bmapheight; // in mapblocks +extern fixed_t bmaporgx, bmaporgy; // origin of block map +extern mobj_t **blocklinks; // for thing chains + +// ***** P_INTER ***** + +extern int maxammo[NUMAMMO]; +extern int clipammo[NUMAMMO]; + +extern boolean messageson; + + +void P_SetMessage(player_t * player, const char *message, boolean ultmsg); +void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher); +void P_DamageMobj(mobj_t * target, mobj_t * inflictor, mobj_t * source, + int damage); +boolean P_GiveAmmo(player_t * player, ammotype_t ammo, int count); +boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo); +boolean P_GiveBody(player_t * player, int num); +boolean P_GivePower(player_t * player, powertype_t power); +boolean P_ChickenMorphPlayer(player_t * player); + +// ***** AM_MAP ***** + +boolean AM_Responder(event_t * ev); +void AM_Ticker(void); +void AM_Drawer(void); + +// ***** SB_BAR ***** + +extern int SB_state; +extern int ArtifactFlash; +void SB_PaletteFlash(void); + +#include "p_spec.h" + +#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/heretic/p_map.c b/games/NXDoom/src/heretic/p_map.c new file mode 100644 index 00000000000..ba56697707b --- /dev/null +++ b/games/NXDoom/src/heretic/p_map.c @@ -0,0 +1,1696 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// P_map.c + +#include + +#include "doomdef.h" +#include "i_system.h" +#include "m_bbox.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +/* +=============================================================================== + +NOTES: + + +=============================================================================== +*/ + +/* +=============================================================================== + +mobj_t NOTES + +mobj_ts are used to tell the refresh where to draw an image, tell the world +simulation when objects are contacted, and tell the sound driver how to +position a sound. + +The refresh uses the next and prev links to follow lists of things in sectors +as they are being drawn. The sprite, frame, and angle elements determine which +patch_t is used to draw the sprite if it is visible. The sprite and frame +values are allmost allways set from state_t structures. The statescr.exe +utility generates the states.h and states.c files that contain the sprite/frame +numbers from the statescr.txt source file. The xyz origin point represents a +point at the bottom middle of the sprite (between the feet of a biped). This +is the default origin position for patch_ts grabbed with lumpy.exe. A walking +creature will have its z equal to the floor it is standing on. + +The sound code uses the x,y, and subsector fields to do stereo positioning of +any sound effited by the mobj_t. + +The play simulation uses the blocklinks, x,y,z, radius, height to determine +when mobj_ts are touching each other, touching lines in the map, or hit by +trace lines (gunshots, lines of sight, etc). The mobj_t->flags element has +various bit flags used by the simulation. + + +Every mobj_t is linked into a single sector based on it's origin coordinates. +The subsector_t is found with R_PointInSubsector(x,y), and the sector_t can be +found with subsector->sector. The sector links are only used by the rendering +code, the play simulation does not care about them at all. + +Any mobj_t that needs to be acted upon be something else in the play world +(block movement, be shot, etc) will also need to be linked into the blockmap. +If the thing has the MF_NOBLOCK flag set, it will not use the block links. It +can still interact with other things, but only as the instigator (missiles will +run into other things, but nothing can run into a missile). Each block in +the grid is 128*128 units, and knows about every line_t that it contains a +piece of, and every interactable mobj_t that has it's origin contained. + +A valid mobj_t is a mobj_t that has the proper subsector_t filled in for it's +xy coordinates and is linked into the subsector's sector or has the MF_NOSECTOR +flag set (the subsector_t needs to be valid even if MF_NOSECTOR is set), and is +linked into a blockmap block or has the MF_NOBLOCKMAP flag set. Links should +only be modified by the P_[Un]SetThingPosition () functions. Do not change +the MF_NO? flags while a thing is valid. + + +=============================================================================== +*/ + +fixed_t tmbbox[4]; +mobj_t *tmthing; +int tmflags; +fixed_t tmx, tmy; + +boolean floatok; // if true, move would be ok if + // within tmfloorz - tmceilingz + +fixed_t tmfloorz, tmceilingz, tmdropoffz; + +// keep track of the line that lowers the ceiling, so missiles don't explode +// against sky hack walls +line_t *ceilingline; + +// keep track of special lines as they are hit, but don't process them +// until the move is proven valid +#define MAXSPECIALCROSS 8 +line_t *spechit[MAXSPECIALCROSS]; +int numspechit; + +mobj_t *onmobj; //generic global onmobj...used for landing on pods/players + +/* +=============================================================================== + + TELEPORT MOVE + +=============================================================================== +*/ + +/* +================== += += PIT_StompThing += +================== +*/ + +boolean PIT_StompThing(mobj_t * thing) +{ + fixed_t blockdist; + + if (!(thing->flags & MF_SHOOTABLE)) + return true; + + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + + if (thing == tmthing) + return true; // don't clip against self + + if (!(tmthing->flags2 & MF2_TELESTOMP)) + { // Not allowed to stomp things + return (false); + } + + P_DamageMobj(thing, tmthing, tmthing, 10000); + + return true; +} + + +/* +=================== += += P_TeleportMove += +=================== +*/ + +boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + +// +// kill anything occupying the position +// + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + +// +// the base floor / ceiling is from the subsector that contains the +// point. Any contacted lines the step closer together will adjust them +// + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + +// +// stomp on any things contacted +// + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_StompThing)) + return false; + +// +// the move is ok, so link the thing into its new position +// + P_UnsetThingPosition(thing); + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + P_SetThingPosition(thing); + + return true; +} + +/* +=============================================================================== + + MOVEMENT ITERATOR FUNCTIONS + +=============================================================================== +*/ + +/* +================== += += PIT_CheckLine += += Adjusts tmfloorz and tmceilingz as lines are contacted +================== +*/ + +boolean PIT_CheckLine(line_t * ld) +{ + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] + || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] + || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + { + return (true); + } + if (P_BoxOnLineSide(tmbbox, ld) != -1) + { + return (true); + } + +// a line has been hit +/* += += The moving thing's destination position will cross the given line. += If this should not be allowed, return false. += If the line is special, keep track of it to process later if the move += is proven ok. NOTE: specials are NOT sorted by order, so two special lines += that are only 8 pixels apart could be crossed in either order. +*/ + + if (!ld->backsector) + { // One sided line + if (tmthing->flags & MF_MISSILE) + { // Missiles can trigger impact specials + if (ld->special) + { + spechit[numspechit] = ld; + numspechit++; + } + } + return false; + } + if (!(tmthing->flags & MF_MISSILE)) + { + if (ld->flags & ML_BLOCKING) + { // Explicitly blocking everything + return (false); + } + if (!tmthing->player && ld->flags & ML_BLOCKMONSTERS + && tmthing->type != MT_POD) + { // Block monsters only + return (false); + } + } + P_LineOpening(ld); // set openrange, opentop, openbottom + // adjust floor / ceiling heights + if (opentop < tmceilingz) + { + tmceilingz = opentop; + ceilingline = ld; + } + if (openbottom > tmfloorz) + { + tmfloorz = openbottom; + } + if (lowfloor < tmdropoffz) + { + tmdropoffz = lowfloor; + } + if (ld->special) + { // Contacted a special line, add it to the list + spechit[numspechit] = ld; + numspechit++; + } + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC PIT_CheckThing +// +//--------------------------------------------------------------------------- + +boolean PIT_CheckThing(mobj_t * thing) +{ + fixed_t blockdist; + boolean solid; + int damage; + + if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) + { // Can't hit thing + return (true); + } + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { // Didn't hit thing + return (true); + } + if (thing == tmthing) + { // Don't clip against self + return (true); + } + if (tmthing->flags2 & MF2_PASSMOBJ) + { // check if a mobj passed over/under another object + if ((tmthing->type == MT_IMP || tmthing->type == MT_WIZARD) + && (thing->type == MT_IMP || thing->type == MT_WIZARD)) + { // don't let imps/wizards fly over other imps/wizards + return false; + } + if (tmthing->z > thing->z + thing->height + && !(thing->flags & MF_SPECIAL)) + { + return (true); + } + else if (tmthing->z + tmthing->height < thing->z + && !(thing->flags & MF_SPECIAL)) + { // under thing + return (true); + } + } + // Check for skulls slamming into things + if (tmthing->flags & MF_SKULLFLY) + { + damage = ((P_Random() % 8) + 1) * tmthing->damage; + P_DamageMobj(thing, tmthing, tmthing, damage); + tmthing->flags &= ~MF_SKULLFLY; + tmthing->momx = tmthing->momy = tmthing->momz = 0; + P_SetMobjState(tmthing, tmthing->info->seestate); + return (false); + } + // Check for missile + if (tmthing->flags & MF_MISSILE) + { + // Check for passing through a ghost + if ((thing->flags & MF_SHADOW) && (tmthing->flags2 & MF2_THRUGHOST)) + { + return (true); + } + // Check if it went over / under + if (tmthing->z > thing->z + thing->height) + { // Over thing + return (true); + } + if (tmthing->z + tmthing->height < thing->z) + { // Under thing + return (true); + } + if (tmthing->target && tmthing->target->type == thing->type) + { // Don't hit same species as originator + if (thing == tmthing->target) + { // Don't missile self + return (true); + } + if (thing->type != MT_PLAYER) + { // Hit same species as originator, explode, no damage + return (false); + } + } + if (!(thing->flags & MF_SHOOTABLE)) + { // Didn't do any damage + return !(thing->flags & MF_SOLID); + } + if (tmthing->flags2 & MF2_RIP) + { + if (!(thing->flags & MF_NOBLOOD)) + { // Ok to spawn some blood + P_RipperBlood(tmthing); + } + S_StartSound(tmthing, sfx_ripslop); + damage = ((P_Random() & 3) + 2) * tmthing->damage; + P_DamageMobj(thing, tmthing, tmthing->target, damage); + if (thing->flags2 & MF2_PUSHABLE + && !(tmthing->flags2 & MF2_CANNOTPUSH)) + { // Push thing + thing->momx += tmthing->momx >> 2; + thing->momy += tmthing->momy >> 2; + } + numspechit = 0; + return (true); + } + // Do damage + damage = ((P_Random() % 8) + 1) * tmthing->damage; + if (damage) + { + if (!(thing->flags & MF_NOBLOOD) && P_Random() < 192) + { + P_BloodSplatter(tmthing->x, tmthing->y, tmthing->z, thing); + } + P_DamageMobj(thing, tmthing, tmthing->target, damage); + } + return (false); + } + if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH)) + { // Push thing + thing->momx += tmthing->momx >> 2; + thing->momy += tmthing->momy >> 2; + } + // Check for special thing + if (thing->flags & MF_SPECIAL) + { + solid = (thing->flags & MF_SOLID) != 0; + if (tmflags & MF_PICKUP) + { // Can be picked up by tmthing + P_TouchSpecialThing(thing, tmthing); // Can remove thing + } + return (!solid); + } + return (!(thing->flags & MF_SOLID)); +} + +//--------------------------------------------------------------------------- +// +// PIT_CheckOnmobjZ +// +//--------------------------------------------------------------------------- + +boolean PIT_CheckOnmobjZ(mobj_t * thing) +{ + fixed_t blockdist; + + if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) + { // Can't hit thing + return (true); + } + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { // Didn't hit thing + return (true); + } + if (thing == tmthing) + { // Don't clip against self + return (true); + } + if (tmthing->z > thing->z + thing->height) + { + return (true); + } + else if (tmthing->z + tmthing->height < thing->z) + { // under thing + return (true); + } + if (thing->flags & MF_SOLID) + { + onmobj = thing; + } + return (!(thing->flags & MF_SOLID)); +} + +/* +=============================================================================== + + MOVEMENT CLIPPING + +=============================================================================== +*/ + +//---------------------------------------------------------------------------- +// +// FUNC P_TestMobjLocation +// +// Returns true if the mobj is not blocked by anything at its current +// location, otherwise returns false. +// +//---------------------------------------------------------------------------- + +boolean P_TestMobjLocation(mobj_t * mobj) +{ + int flags; + + flags = mobj->flags; + mobj->flags &= ~MF_PICKUP; + if (P_CheckPosition(mobj, mobj->x, mobj->y)) + { // XY is ok, now check Z + mobj->flags = flags; + if ((mobj->z < mobj->floorz) + || (mobj->z + mobj->height > mobj->ceilingz)) + { // Bad Z + return (false); + } + return (true); + } + mobj->flags = flags; + return (false); +} + +/* +================== += += P_CheckPosition += += This is purely informative, nothing is modified (except things picked up) + +in: +a mobj_t (can be valid or invalid) +a position to be checked (doesn't need to be related to the mobj_t->x,y) + +during: +special things are touched if MF_PICKUP +early out on solid lines? + +out: +newsubsec +floorz +ceilingz +tmdropoffz the lowest point contacted (monsters won't move to a dropoff) +speciallines[] +numspeciallines + +================== +*/ + +boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + +// +// the base floor / ceiling is from the subsector that contains the +// point. Any contacted lines the step closer together will adjust them +// + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + if (tmflags & MF_NOCLIP) + return true; + +// +// check things first, possibly picking things up +// the bounding box is extended by MAXRADIUS because mobj_ts are grouped +// into mapblocks based on their origin point, and can overlap into adjacent +// blocks by up to MAXRADIUS units +// + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) + return false; +// +// check lines +// + xl = (tmbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockLinesIterator(bx, by, PIT_CheckLine)) + return false; + + return true; +} + +//============================================================================= +// +// P_CheckOnmobj(mobj_t *thing) +// +// Checks if the new Z position is legal +//============================================================================= + +mobj_t *P_CheckOnmobj(mobj_t * thing) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + fixed_t x; + fixed_t y; + mobj_t oldmo; + + x = thing->x; + y = thing->y; + tmthing = thing; + tmflags = thing->flags; + oldmo = *thing; // save the old mobj before the fake zmovement + P_FakeZMovement(tmthing); + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + +// +// the base floor / ceiling is from the subsector that contains the +// point. Any contacted lines the step closer together will adjust them +// + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + if (tmflags & MF_NOCLIP) + return NULL; + +// +// check things first, possibly picking things up +// the bounding box is extended by MAXRADIUS because mobj_ts are grouped +// into mapblocks based on their origin point, and can overlap into adjacent +// blocks by up to MAXRADIUS units +// + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_CheckOnmobjZ)) + { + *tmthing = oldmo; + return onmobj; + } + *tmthing = oldmo; + return NULL; +} + +//============================================================================= +// +// P_FakeZMovement +// +// Fake the zmovement so that we can check if a move is legal +//============================================================================= + +void P_FakeZMovement(mobj_t * mo) +{ + int dist; + int delta; +// +// adjust height +// + mo->z += mo->momz; + if (mo->flags & MF_FLOAT && mo->target) + { // float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = + P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + if (delta < 0 && dist < -(delta * 3)) + mo->z -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->z += FLOATSPEED; + } + } + if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) + && leveltime & 2) + { + mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; + } + +// +// clip movement +// + if (mo->z <= mo->floorz) + { // Hit the floor + mo->z = mo->floorz; + if (mo->momz < 0) + { + mo->momz = 0; + } + if (mo->flags & MF_SKULLFLY) + { // The skull slammed into something + mo->momz = -mo->momz; + } + if (mo->info->crashstate && (mo->flags & MF_CORPSE)) + { + return; + } + } + else if (mo->flags2 & MF2_LOGRAV) + { + if (mo->momz == 0) + mo->momz = -(GRAVITY >> 3) * 2; + else + mo->momz -= GRAVITY >> 3; + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + if (mo->momz == 0) + mo->momz = -GRAVITY * 2; + else + mo->momz -= GRAVITY; + } + + if (mo->z + mo->height > mo->ceilingz) + { // hit the ceiling + if (mo->momz > 0) + mo->momz = 0; + mo->z = mo->ceilingz - mo->height; + if (mo->flags & MF_SKULLFLY) + { // the skull slammed into something + mo->momz = -mo->momz; + } + } +} + +//========================================================================== +// +// CheckMissileImpact +// +//========================================================================== + +void CheckMissileImpact(mobj_t * mobj) +{ + int i; + + if (!numspechit || !(mobj->flags & MF_MISSILE) || !mobj->target) + { + return; + } + if (!mobj->target->player) + { + return; + } + for (i = numspechit - 1; i >= 0; i--) + { + P_ShootSpecialLine(mobj->target, spechit[i]); + } +} + +/* +=================== += += P_TryMove += += Attempt to move to a new position, crossing special lines unless MF_TELEPORT += is set += +=================== +*/ + +boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y) +{ + fixed_t oldx, oldy; + int side, oldside; + line_t *ld; + + floatok = false; + if (!P_CheckPosition(thing, x, y)) + { // Solid wall or thing + CheckMissileImpact(thing); + return false; + } + if (!(thing->flags & MF_NOCLIP)) + { + if (tmceilingz - tmfloorz < thing->height) + { // Doesn't fit + CheckMissileImpact(thing); + return false; + } + floatok = true; + if (!(thing->flags & MF_TELEPORT) + && tmceilingz - thing->z < thing->height + && !(thing->flags2 & MF2_FLY)) + { // mobj must lower itself to fit + CheckMissileImpact(thing); + return false; + } + if (thing->flags2 & MF2_FLY) + { + if (thing->z + thing->height > tmceilingz) + { + thing->momz = -8 * FRACUNIT; + return false; + } + else if (thing->z < tmfloorz + && tmfloorz - tmdropoffz > 24 * FRACUNIT) + { + thing->momz = 8 * FRACUNIT; + return false; + } + } + if (!(thing->flags & MF_TELEPORT) + // The Minotaur floor fire (MT_MNTRFX2) can step up any amount + && thing->type != MT_MNTRFX2 + && tmfloorz - thing->z > 24 * FRACUNIT) + { // Too big a step up + CheckMissileImpact(thing); + return false; + } + if ((thing->flags & MF_MISSILE) && tmfloorz > thing->z) + { + CheckMissileImpact(thing); + } + if (!(thing->flags & (MF_DROPOFF | MF_FLOAT)) + && tmfloorz - tmdropoffz > 24 * FRACUNIT) + { // Can't move over a dropoff + return false; + } + } + +// +// the move is ok, so link the thing into its new position +// + P_UnsetThingPosition(thing); + + oldx = thing->x; + oldy = thing->y; + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + P_SetThingPosition(thing); + + if (thing->flags2 & MF2_FOOTCLIP + && P_GetThingFloorType(thing) != FLOOR_SOLID) + { + thing->flags2 |= MF2_FEETARECLIPPED; + } + else if (thing->flags2 & MF2_FEETARECLIPPED) + { + thing->flags2 &= ~MF2_FEETARECLIPPED; + } + +// +// if any special lines were hit, do the effect +// + if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) + while (numspechit--) + { + // see if the line was crossed + ld = spechit[numspechit]; + side = P_PointOnLineSide(thing->x, thing->y, ld); + oldside = P_PointOnLineSide(oldx, oldy, ld); + if (side != oldside) + { + if (ld->special) + P_CrossSpecialLine(ld - lines, oldside, thing); + } + } + + return true; +} + +/* +================== += += P_ThingHeightClip += += Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, += anf possibly thing->z += += This is called for all nearby monsters whenever a sector changes height += += If the thing doesn't fit, the z will be set to the lowest value and += false will be returned +================== +*/ + +boolean P_ThingHeightClip(mobj_t * thing) +{ + boolean onfloor; + + onfloor = (thing->z == thing->floorz); + + P_CheckPosition(thing, thing->x, thing->y); + // what about stranding a monster partially off an edge? + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + + if (onfloor) + // walking monsters rise and fall with the floor + thing->z = thing->floorz; + else + { // don't adjust a floating monster unless forced to + if (thing->z + thing->height > thing->ceilingz) + thing->z = thing->ceilingz - thing->height; + } + + if (thing->ceilingz - thing->floorz < thing->height) + return false; + + return true; +} + + +/* +============================================================================== + + SLIDE MOVE + +Allows the player to slide along any angled walls + +============================================================================== +*/ + +fixed_t bestslidefrac, secondslidefrac; +line_t *bestslideline, *secondslideline; +mobj_t *slidemo; + +fixed_t tmxmove, tmymove; + +/* +================== += += P_HitSlideLine += += Adjusts the xmove / ymove so that the next move will slide along the wall +================== +*/ + +void P_HitSlideLine(line_t * ld) +{ + int side; + angle_t lineangle, moveangle, deltaangle; + fixed_t movelen, newlen; + + + if (ld->slopetype == ST_HORIZONTAL) + { + tmymove = 0; + return; + } + if (ld->slopetype == ST_VERTICAL) + { + tmxmove = 0; + return; + } + + side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); + + lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + if (side == 1) + lineangle += ANG180; + moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); + deltaangle = moveangle - lineangle; + if (deltaangle > ANG180) + deltaangle += ANG180; +// I_Error ("SlideLine: ang>ANG180"); + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance(tmxmove, tmymove); + newlen = FixedMul(movelen, finecosine[deltaangle]); + tmxmove = FixedMul(newlen, finecosine[lineangle]); + tmymove = FixedMul(newlen, finesine[lineangle]); +} + +/* +============== += += PTR_SlideTraverse += +============== +*/ + +boolean PTR_SlideTraverse(intercept_t * in) +{ + line_t *li; + + if (!in->isaline) + I_Error("PTR_SlideTraverse: not a line?"); + + li = in->d.line; + if (!(li->flags & ML_TWOSIDED)) + { + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) + return true; // don't hit the back side + goto isblocking; + } + + P_LineOpening(li); // set openrange, opentop, openbottom + if (openrange < slidemo->height) + goto isblocking; // doesn't fit + + if (opentop - slidemo->z < slidemo->height) + goto isblocking; // mobj is too high + + if (openbottom - slidemo->z > 24 * FRACUNIT) + goto isblocking; // too big a step up + + return true; // this line doesn't block movement + +// the line does block movement, see if it is closer than best so far + isblocking: + if (in->frac < bestslidefrac) + { + secondslidefrac = bestslidefrac; + secondslideline = bestslideline; + bestslidefrac = in->frac; + bestslideline = li; + } + + return false; // stop +} + + +/* +================== += += P_SlideMove += += The momx / momy move is bad, so try to slide along a wall += += Find the first line hit, move flush to it, and slide along it += += This is a kludgy mess. +================== +*/ + +void P_SlideMove(mobj_t * mo) +{ + fixed_t leadx, leady; + fixed_t trailx, traily; + fixed_t newx, newy; + int hitcount; + + slidemo = mo; + hitcount = 0; + retry: + if (++hitcount == 3) + goto stairstep; // don't loop forever + +// +// trace along the three leading corners +// + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT + 1; + + P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + +// +// move up to the wall +// + if (bestslidefrac == FRACUNIT + 1) + { // the move most have hit the middle, so stairstep + stairstep: + if (!P_TryMove(mo, mo->x, mo->y + mo->momy)) + P_TryMove(mo, mo->x + mo->momx, mo->y); + return; + } + + bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit + if (bestslidefrac > 0) + { + newx = FixedMul(mo->momx, bestslidefrac); + newy = FixedMul(mo->momy, bestslidefrac); + if (!P_TryMove(mo, mo->x + newx, mo->y + newy)) + goto stairstep; + } + +// +// now continue along the wall +// + bestslidefrac = FRACUNIT - (bestslidefrac + 0x800); // remainder + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; + if (bestslidefrac <= 0) + return; + + tmxmove = FixedMul(mo->momx, bestslidefrac); + tmymove = FixedMul(mo->momy, bestslidefrac); + + P_HitSlideLine(bestslideline); // clip the moves + + mo->momx = tmxmove; + mo->momy = tmymove; + + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove)) + { + goto retry; + } +} + + + +/* +============================================================================== + + P_LineAttack + +============================================================================== +*/ + + +mobj_t *linetarget; // who got hit (or NULL) +mobj_t *shootthing; +fixed_t shootz; // height if not aiming up or down + // ???: use slope for monsters? +int la_damage; +fixed_t attackrange; + +fixed_t aimslope; + + +/* +=============================================================================== += += PTR_AimTraverse += += Sets linetaget and aimslope when a target is aimed at +=============================================================================== +*/ + +boolean PTR_AimTraverse(intercept_t * in) +{ + line_t *li; + mobj_t *th; + fixed_t slope, thingtopslope, thingbottomslope; + fixed_t dist; + + if (in->isaline) + { + li = in->d.line; + if (!(li->flags & ML_TWOSIDED)) + return false; // stop +// +// crosses a two sided line +// a two sided line will restrict the possible target ranges + P_LineOpening(li); + + if (openbottom >= opentop) + return false; // stop + + dist = FixedMul(attackrange, in->frac); + + // Added checks if there is no backsector to prevent crashing. + // Crashes didn't happen in the DOS version of Heretic + // because reading NULL pointer produces unpredictable but + // deterministic values instead of crashing. + // See https://github.com/chocolate-doom/chocolate-doom/issues/1665 + if (li->backsector == NULL + || li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - shootz, dist); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->backsector == NULL + || li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - shootz, dist); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // shot continues + } + +// +// shoot a thing +// + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + if (!(th->flags & MF_SHOOTABLE)) + return true; // corpse or something + if (th->type == MT_POD) + { // Can't auto-aim at pods + return (true); + } + +// check angles to see if the thing can be aimed at + + dist = FixedMul(attackrange, in->frac); + thingtopslope = FixedDiv(th->z + th->height - shootz, dist); + if (thingtopslope < bottomslope) + return true; // shot over the thing + thingbottomslope = FixedDiv(th->z - shootz, dist); + if (thingbottomslope > topslope) + return true; // shot under the thing + +// +// this thing can be hit! +// + if (thingtopslope > topslope) + thingtopslope = topslope; + if (thingbottomslope < bottomslope) + thingbottomslope = bottomslope; + + aimslope = (thingtopslope + thingbottomslope) / 2; + linetarget = th; + + return false; // don't go any farther +} + + +/* +============================================================================== += += PTR_ShootTraverse += +============================================================================== +*/ + +boolean PTR_ShootTraverse(intercept_t * in) +{ + fixed_t x, y, z; + fixed_t frac; + line_t *li; + mobj_t *th; + fixed_t slope; + fixed_t dist; + fixed_t thingtopslope, thingbottomslope; + mobj_t *mo; + + if (in->isaline) + { + li = in->d.line; + if (li->special) + P_ShootSpecialLine(shootthing, li); + if (!(li->flags & ML_TWOSIDED)) + goto hitline; + +// +// crosses a two sided line +// + P_LineOpening(li); + + dist = FixedMul(attackrange, in->frac); + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - shootz, dist); + if (slope > aimslope) + goto hitline; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - shootz, dist); + if (slope < aimslope) + goto hitline; + } + + return true; // shot continues +// +// hit line +// + hitline: + // position a bit closer + frac = in->frac - FixedDiv(4 * FRACUNIT, attackrange); + x = trace.x + FixedMul(trace.dx, frac); + y = trace.y + FixedMul(trace.dy, frac); + z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); + + if (li->frontsector->ceilingpic == skyflatnum) + { + if (z > li->frontsector->ceilingheight) + return false; // don't shoot the sky! + if (li->backsector && li->backsector->ceilingpic == skyflatnum) + return false; // it's a sky hack wall + } + + P_SpawnPuff(x, y, z); + return false; // don't go any farther + } + +// +// shoot a thing +// + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + if (!(th->flags & MF_SHOOTABLE)) + return true; // corpse or something + +// +// check for physical attacks on a ghost +// + if (th->flags & MF_SHADOW && shootthing->player->readyweapon == wp_staff) + { + return (true); + } + +// check angles to see if the thing can be aimed at + dist = FixedMul(attackrange, in->frac); + thingtopslope = FixedDiv(th->z + th->height - shootz, dist); + if (thingtopslope < aimslope) + return true; // shot over the thing + thingbottomslope = FixedDiv(th->z - shootz, dist); + if (thingbottomslope > aimslope) + return true; // shot under the thing + +// +// hit thing +// + // position a bit closer + frac = in->frac - FixedDiv(10 * FRACUNIT, attackrange); + x = trace.x + FixedMul(trace.dx, frac); + y = trace.y + FixedMul(trace.dy, frac); + z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); + if (PuffType == MT_BLASTERPUFF1) + { // Make blaster big puff + mo = P_SpawnMobj(x, y, z, MT_BLASTERPUFF2); + S_StartSound(mo, sfx_blshit); + } + else + { + P_SpawnPuff(x, y, z); + } + if (la_damage) + { + if (!(in->d.thing->flags & MF_NOBLOOD) && P_Random() < 192) + { + P_BloodSplatter(x, y, z, in->d.thing); + } + P_DamageMobj(th, shootthing, shootthing, la_damage); + } + return (false); // don't go any farther +} + +/* +================= += += P_AimLineAttack += +================= +*/ + +fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance) +{ + fixed_t x2, y2; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; + shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; + topslope = 100 * FRACUNIT / 160; // can't shoot outside view angles + bottomslope = -100 * FRACUNIT / 160; + attackrange = distance; + linetarget = NULL; + + P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + PTR_AimTraverse); + + if (linetarget) + return aimslope; + return 0; +} + + + +/* +================= += += P_LineAttack += += if damage == 0, it is just a test trace that will leave linetarget set += +================= +*/ + +void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, + int damage) +{ + fixed_t x2, y2; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + la_damage = damage; + x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; + shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; + if (t1->flags2 & MF2_FEETARECLIPPED) + { + shootz -= FOOTCLIPSIZE; + } + attackrange = distance; + aimslope = slope; + + P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + PTR_ShootTraverse); +} + + + +/* +============================================================================== + + USE LINES + +============================================================================== +*/ + +mobj_t *usething; + +boolean PTR_UseTraverse(intercept_t * in) +{ + if (!in->d.line->special) + { + P_LineOpening(in->d.line); + if (openrange <= 0) + { + //S_StartSound (usething, sfx_noway); + return false; // can't use through a wall + } + return true; // not a special line, but keep checking + } + + if (P_PointOnLineSide(usething->x, usething->y, in->d.line) == 1) + return false; // don't use back sides + + P_UseSpecialLine(usething, in->d.line); + + return false; // can't use for than one special line in a row +} + + +/* +================ += += P_UseLines += += Looks for special lines in front of the player to activate +================ +*/ + +void P_UseLines(player_t * player) +{ + int angle; + fixed_t x1, y1, x2, y2; + + usething = player->mo; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; + y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; + + P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse); +} + + + +/* +============================================================================== + + RADIUS ATTACK + +============================================================================== +*/ + +mobj_t *bombsource; +mobj_t *bombspot; +int bombdamage; + +/* +================= += += PIT_RadiusAttack += += Source is the creature that casued the explosion at spot +================= +*/ + +boolean PIT_RadiusAttack(mobj_t * thing) +{ + fixed_t dx, dy, dist; + + if (!(thing->flags & MF_SHOOTABLE)) + { + return true; + } + if (thing->type == MT_MINOTAUR || thing->type == MT_SORCERER1 + || thing->type == MT_SORCERER2) + { // Episode 2 and 3 bosses take no damage from PIT_RadiusAttack + return (true); + } + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + dist = dx > dy ? dx : dy; + dist = (dist - thing->radius) >> FRACBITS; + if (dist < 0) + { + dist = 0; + } + if (dist >= bombdamage) + { // Out of range + return true; + } + if (P_CheckSight(thing, bombspot)) + { // OK to damage, target is in direct path + P_DamageMobj(thing, bombspot, bombsource, bombdamage - dist); + } + return (true); +} + +/* +================= += += P_RadiusAttack += += Source is the creature that casued the explosion at spot +================= +*/ + +void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage) +{ + int x, y, xl, xh, yl, yh; + fixed_t dist; + + dist = (damage + MAXRADIUS) << FRACBITS; + yh = (spot->y + dist - bmaporgy) >> MAPBLOCKSHIFT; + yl = (spot->y - dist - bmaporgy) >> MAPBLOCKSHIFT; + xh = (spot->x + dist - bmaporgx) >> MAPBLOCKSHIFT; + xl = (spot->x - dist - bmaporgx) >> MAPBLOCKSHIFT; + bombspot = spot; + if (spot->type == MT_POD && spot->target) + { + bombsource = spot->target; + } + else + { + bombsource = source; + } + bombdamage = damage; + for (y = yl; y <= yh; y++) + for (x = xl; x <= xh; x++) + P_BlockThingsIterator(x, y, PIT_RadiusAttack); +} + + +/* +============================================================================== + + SECTOR HEIGHT CHANGING + += After modifying a sectors floor or ceiling height, call this += routine to adjust the positions of all things that touch the += sector. += += If anything doesn't fit anymore, true will be returned. += If crunch is true, they will take damage as they are being crushed += If Crunch is false, you should set the sector height back the way it += was and call P_ChangeSector again to undo the changes +============================================================================== +*/ + +boolean crushchange; +boolean nofit; + +/* +=============== += += PIT_ChangeSector += +=============== +*/ + +boolean PIT_ChangeSector(mobj_t * thing) +{ + mobj_t *mo; + + if (P_ThingHeightClip(thing)) + return true; // keep checking + + // crunch bodies to giblets + if (thing->health <= 0) + { + //P_SetMobjState (thing, S_GIBS); + thing->height = 0; + thing->radius = 0; + return true; // keep checking + } + + // crunch dropped items + if (thing->flags & MF_DROPPED) + { + P_RemoveMobj(thing); + return true; // keep checking + } + + if (!(thing->flags & MF_SHOOTABLE)) + return true; // assume it is bloody gibs or something + + nofit = true; + if (crushchange && !(leveltime & 3)) + { + P_DamageMobj(thing, NULL, NULL, 10); + // spray blood in a random direction + mo = P_SpawnMobj(thing->x, thing->y, thing->z + thing->height / 2, + MT_BLOOD); + mo->momx = P_SubRandom() << 12; + mo->momy = P_SubRandom() << 12; + } + + return true; // keep checking (crush other things) +} + +/* +=============== += += P_ChangeSector += +=============== +*/ + +boolean P_ChangeSector(sector_t * sector, boolean crunch) +{ + int x, y; + + nofit = false; + crushchange = crunch; + +// recheck heights for all things near the moving sector + + for (x = sector->blockbox[BOXLEFT]; x <= sector->blockbox[BOXRIGHT]; x++) + for (y = sector->blockbox[BOXBOTTOM]; y <= sector->blockbox[BOXTOP]; + y++) + P_BlockThingsIterator(x, y, PIT_ChangeSector); + + + return nofit; +} diff --git a/games/NXDoom/src/heretic/p_maputl.c b/games/NXDoom/src/heretic/p_maputl.c new file mode 100644 index 00000000000..5150aaeef88 --- /dev/null +++ b/games/NXDoom/src/heretic/p_maputl.c @@ -0,0 +1,779 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_maputl.c + +#include + +#include "doomdef.h" +#include "m_bbox.h" +#include "m_misc.h" +#include "p_local.h" + + +/* +=================== += += P_AproxDistance += += Gives an estimation of distance (not exact) += +=================== +*/ + +fixed_t P_AproxDistance(fixed_t dx, fixed_t dy) +{ + dx = abs(dx); + dy = abs(dy); + if (dx < dy) + return dx + dy - (dx >> 1); + return dx + dy - (dy >> 1); +} + + +/* +================== += += P_PointOnLineSide += += Returns 0 or 1 +================== +*/ + +int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line) +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!line->dx) + { + if (x <= line->v1->x) + return line->dy > 0; + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->v1->y) + return line->dx < 0; + return line->dx > 0; + } + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = FixedMul(line->dy >> FRACBITS, dx); + right = FixedMul(dy, line->dx >> FRACBITS); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +/* +================= += += P_BoxOnLineSide += += Considers the line to be infinite += Returns side 0 or 1, -1 if box crosses the line +================= +*/ + +int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld) +{ + int p1 = 0, p2 = 0; + + switch (ld->slopetype) + { + case ST_HORIZONTAL: + p1 = tmbox[BOXTOP] > ld->v1->y; + p2 = tmbox[BOXBOTTOM] > ld->v1->y; + if (ld->dx < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + case ST_VERTICAL: + p1 = tmbox[BOXRIGHT] < ld->v1->x; + p2 = tmbox[BOXLEFT] < ld->v1->x; + if (ld->dy < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + case ST_POSITIVE: + p1 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); + break; + case ST_NEGATIVE: + p1 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); + break; + } + + if (p1 == p2) + return p1; + return -1; +} + +/* +================== += += P_PointOnDivlineSide += += Returns 0 or 1 +================== +*/ + +int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line) +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!line->dx) + { + if (x <= line->x) + return line->dy > 0; + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->y) + return line->dx < 0; + return line->dx > 0; + } + + dx = (x - line->x); + dy = (y - line->y); + +// try to quickly decide by looking at sign bits + if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000) + { + if ((line->dy ^ dx) & 0x80000000) + return 1; // (left is negative) + return 0; + } + + left = FixedMul(line->dy >> 8, dx >> 8); + right = FixedMul(dy >> 8, line->dx >> 8); + + if (right < left) + return 0; // front side + return 1; // back side +} + + + +/* +============== += += P_MakeDivline += +============== +*/ + +void P_MakeDivline(line_t * li, divline_t * dl) +{ + dl->x = li->v1->x; + dl->y = li->v1->y; + dl->dx = li->dx; + dl->dy = li->dy; +} + + +/* +=============== += += P_InterceptVector += += Returns the fractional intercept point along the first divline += += This is only called by the addthings and addlines traversers +=============== +*/ + +fixed_t P_InterceptVector(divline_t * v2, divline_t * v1) +{ +#if 1 + fixed_t frac, num, den; + + den = FixedMul(v1->dy >> 8, v2->dx) - FixedMul(v1->dx >> 8, v2->dy); + if (den == 0) + return 0; +// I_Error ("P_InterceptVector: parallel"); + num = FixedMul((v1->x - v2->x) >> 8, v1->dy) + + FixedMul((v2->y - v1->y) >> 8, v1->dx); + frac = FixedDiv(num, den); + + return frac; +#else + float frac, num, den, v1x, v1y, v1dx, v1dy, v2x, v2y, v2dx, v2dy; + + v1x = (float) v1->x / FRACUNIT; + v1y = (float) v1->y / FRACUNIT; + v1dx = (float) v1->dx / FRACUNIT; + v1dy = (float) v1->dy / FRACUNIT; + v2x = (float) v2->x / FRACUNIT; + v2y = (float) v2->y / FRACUNIT; + v2dx = (float) v2->dx / FRACUNIT; + v2dy = (float) v2->dy / FRACUNIT; + + den = v1dy * v2dx - v1dx * v2dy; + if (den == 0) + return 0; // parallel + num = (v1x - v2x) * v1dy + (v2y - v1y) * v1dx; + frac = num / den; + + return frac * FRACUNIT; +#endif +} + +/* +================== += += P_LineOpening += += Sets opentop and openbottom to the window through a two sided line += OPTIMIZE: keep this precalculated +================== +*/ + +fixed_t opentop, openbottom, openrange; +fixed_t lowfloor; + +void P_LineOpening(line_t * linedef) +{ + sector_t *front, *back; + + if (linedef->sidenum[1] == -1) + { // single sided line + openrange = 0; + return; + } + + front = linedef->frontsector; + back = linedef->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; + } + + openrange = opentop - openbottom; +} + +/* +=============================================================================== + + THING POSITION SETTING + +=============================================================================== +*/ + +/* +=================== += += P_UnsetThingPosition += += Unlinks a thing from block map and sectors += +=================== +*/ + +void P_UnsetThingPosition(mobj_t * thing) +{ + int blockx, blocky; + + if (!(thing->flags & MF_NOSECTOR)) + { // inert things don't need to be in blockmap +// unlink from subsector + if (thing->snext) + thing->snext->sprev = thing->sprev; + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + } + + if (!(thing->flags & MF_NOBLOCKMAP)) + { // inert things don't need to be in blockmap +// unlink from block map + if (thing->bnext) + thing->bnext->bprev = thing->bprev; + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + if (blockx >= 0 && blockx < bmapwidth + && blocky >= 0 && blocky < bmapheight) + blocklinks[blocky * bmapwidth + blockx] = thing->bnext; + } + } +} + + +/* +=================== += += P_SetThingPosition += += Links a thing into both a block and a subsector based on it's x y += Sets thing->subsector properly += +=================== +*/ + +void P_SetThingPosition(mobj_t * thing) +{ + subsector_t *ss; + sector_t *sec; + int blockx, blocky; + mobj_t **link; + +// +// link into subsector +// + ss = R_PointInSubsector(thing->x, thing->y); + thing->subsector = ss; + if (!(thing->flags & MF_NOSECTOR)) + { // invisible things don't go into the sector links + sec = ss->sector; + + thing->sprev = NULL; + thing->snext = sec->thinglist; + if (sec->thinglist) + sec->thinglist->sprev = thing; + sec->thinglist = thing; + } + +// +// link into blockmap +// + if (!(thing->flags & MF_NOBLOCKMAP)) + { // inert things don't need to be in blockmap + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 + && blocky < bmapheight) + { + link = &blocklinks[blocky * bmapwidth + blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) + (*link)->bprev = thing; + *link = thing; + } + else + { // thing is off the map + thing->bnext = thing->bprev = NULL; + } + } +} + + + +/* +=============================================================================== + + BLOCK MAP ITERATORS + +For each line/thing in the given mapblock, call the passed function. +If the function returns false, exit with false without checking anything else. + +=============================================================================== +*/ + +/* +================== += += P_BlockLinesIterator += += The validcount flags are used to avoid checking lines += that are marked in multiple mapblocks, so increment validcount before += the first call to P_BlockLinesIterator, then make one or more calls to it +=================== +*/ + +boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)) +{ + int offset; + short *list; + line_t *ld; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return true; + offset = y * bmapwidth + x; + + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; // line has already been checked + ld->validcount = validcount; + + if (!func(ld)) + return false; + } + + return true; // everything was checked +} + + +/* +================== += += P_BlockThingsIterator += +================== +*/ + +boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)) +{ + mobj_t *mobj; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return true; + + LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); + + for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext) + if (!func(mobj)) + return false; + + return true; +} + +/* +=============================================================================== + + INTERCEPT ROUTINES + +=============================================================================== +*/ + +intercept_t intercepts[MAXINTERCEPTS], *intercept_p; + +divline_t trace; +boolean earlyout; +int ptflags; + +/* +================== += += PIT_AddLineIntercepts += += Looks for lines in the given block that intercept the given trace += to add to the intercepts list += A line is crossed if its endpoints are on opposite sides of the trace += Returns true if earlyout and a solid line hit +================== +*/ + +boolean PIT_AddLineIntercepts(line_t * ld) +{ + int s1, s2; + fixed_t frac; + divline_t dl; + +// avoid precision problems with two routines + if (trace.dx > FRACUNIT * 16 || trace.dy > FRACUNIT * 16 + || trace.dx < -FRACUNIT * 16 || trace.dy < -FRACUNIT * 16) + { + s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); + } + else + { + s1 = P_PointOnLineSide(trace.x, trace.y, ld); + s2 = P_PointOnLineSide(trace.x + trace.dx, trace.y + trace.dy, ld); + } + if (s1 == s2) + return true; // line isn't crossed + +// +// hit the line +// + P_MakeDivline(ld, &dl); + frac = P_InterceptVector(&trace, &dl); + if (frac < 0) + return true; // behind source + +// try to early out the check + if (earlyout && frac < FRACUNIT && !ld->backsector) + return false; // stop checking + + intercept_p->frac = frac; + intercept_p->isaline = true; + intercept_p->d.line = ld; + intercept_p++; + + return true; // continue +} + + + +/* +================== += += PIT_AddThingIntercepts += +================== +*/ + +boolean PIT_AddThingIntercepts(mobj_t * thing) +{ + fixed_t x1, y1, x2, y2; + int s1, s2; + boolean tracepositive; + divline_t dl; + fixed_t frac; + + tracepositive = (trace.dx ^ trace.dy) > 0; + + // check a corner to corner crossection for hit + + if (tracepositive) + { + x1 = thing->x - thing->radius; + y1 = thing->y + thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y - thing->radius; + } + else + { + x1 = thing->x - thing->radius; + y1 = thing->y - thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y + thing->radius; + } + s1 = P_PointOnDivlineSide(x1, y1, &trace); + s2 = P_PointOnDivlineSide(x2, y2, &trace); + if (s1 == s2) + return true; // line isn't crossed + + dl.x = x1; + dl.y = y1; + dl.dx = x2 - x1; + dl.dy = y2 - y1; + frac = P_InterceptVector(&trace, &dl); + if (frac < 0) + return true; // behind source + intercept_p->frac = frac; + intercept_p->isaline = false; + intercept_p->d.thing = thing; + intercept_p++; + + return true; // keep going +} + + +/* +==================== += += P_TraverseIntercepts += += Returns true if the traverser function returns true for all lines +==================== +*/ + +boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) +{ + int count; + fixed_t dist; + intercept_t *scan, *in; + + count = intercept_p - intercepts; + in = 0; // shut up compiler warning + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts; scan < intercept_p; scan++) + if (scan->frac < dist) + { + dist = scan->frac; + in = scan; + } + + if (dist > maxfrac) + return true; // checked everything in range +#if 0 + { // don't check these yet, ther may be others inserted + in = scan = intercepts; + for (scan = intercepts; scan < intercept_p; scan++) + if (scan->frac > maxfrac) + *in++ = *scan; + intercept_p = in; + return false; + } +#endif + + if (!func(in)) + return false; // don't bother going farther + in->frac = INT_MAX; + } + + return true; // everything was traversed +} + + + +/* +================== += += P_PathTraverse += += Traces a line from x1,y1 to x2,y2, calling the traverser function for each += Returns true if the traverser function returns true for all lines +================== +*/ + +boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, + int flags, boolean(*trav) (intercept_t *)) +{ + fixed_t xt1, yt1, xt2, yt2; + fixed_t xstep, ystep; + fixed_t partial; + fixed_t xintercept, yintercept; + int mapx, mapy, mapxstep, mapystep; + int count; + + earlyout = (flags & PT_EARLYOUT) != 0; + + validcount++; + intercept_p = intercepts; + + if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) + x1 += FRACUNIT; // don't side exactly on a line + if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) + y1 += FRACUNIT; // don't side exactly on a line + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1 >> MAPBLOCKSHIFT; + yt1 = y1 >> MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2 >> MAPBLOCKSHIFT; + yt2 = y2 >> MAPBLOCKSHIFT; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256 * FRACUNIT; + } + yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); + + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256 * FRACUNIT; + } + xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); + + +// +// step through map blocks +// Count is present to prevent a round off error from skipping the break + mapx = xt1; + mapy = yt1; + + for (count = 0; count < 64; count++) + { + if (flags & PT_ADDLINES) + { + if (!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts)) + return false; // early out + } + if (flags & PT_ADDTHINGS) + { + if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts)) + return false; // early out + } + + if (mapx == xt2 && mapy == yt2) + break; + + if ((yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ((xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + + } + + +// +// go through the sorted list +// + return P_TraverseIntercepts(trav, FRACUNIT); +} diff --git a/games/NXDoom/src/heretic/p_mobj.c b/games/NXDoom/src/heretic/p_mobj.c new file mode 100644 index 00000000000..363dabe4a60 --- /dev/null +++ b/games/NXDoom/src/heretic/p_mobj.c @@ -0,0 +1,1626 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_mobj.c + +#include "doomdef.h" +#include "i_system.h" +#include "m_random.h" +#include "p_local.h" +#include "sounds.h" +#include "s_sound.h" + +void G_PlayerReborn(int player); +void P_SpawnMapThing(mapthing_t * mthing); + +mobjtype_t PuffType; +mobj_t *MissileMobj; + +static fixed_t FloatBobOffsets[64] = { + 0, 51389, 102283, 152192, + 200636, 247147, 291278, 332604, + 370727, 405280, 435929, 462380, + 484378, 501712, 514213, 521763, + 524287, 521763, 514213, 501712, + 484378, 462380, 435929, 405280, + 370727, 332604, 291278, 247147, + 200636, 152192, 102283, 51389, + -1, -51390, -102284, -152193, + -200637, -247148, -291279, -332605, + -370728, -405281, -435930, -462381, + -484380, -501713, -514215, -521764, + -524288, -521764, -514214, -501713, + -484379, -462381, -435930, -405280, + -370728, -332605, -291279, -247148, + -200637, -152193, -102284, -51389 +}; + +//---------------------------------------------------------------------------- +// +// FUNC P_SetMobjState +// +// Returns true if the mobj is still present. +// +//---------------------------------------------------------------------------- + +boolean P_SetMobjState(mobj_t * mobj, statenum_t state) +{ + state_t *st; + + if (state == S_NULL) + { // Remove mobj + mobj->state = (state_t *) S_NULL; + P_RemoveMobj(mobj); + return (false); + } + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + if (st->action) + { // Call action function + st->action(mobj, NULL, NULL); + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_SetMobjStateNF +// +// Same as P_SetMobjState, but does not call the state function. +// +//---------------------------------------------------------------------------- + +boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state) +{ + state_t *st; + + if (state == S_NULL) + { // Remove mobj + mobj->state = (state_t *) S_NULL; + P_RemoveMobj(mobj); + return (false); + } + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC P_ExplodeMissile +// +//---------------------------------------------------------------------------- + +void P_ExplodeMissile(mobj_t * mo) +{ + if (mo->type == MT_WHIRLWIND) + { + if (++mo->special2.i < 60) + { + return; + } + } + mo->momx = mo->momy = mo->momz = 0; + P_SetMobjState(mo, mobjinfo[mo->type].deathstate); + //mo->tics -= P_Random()&3; + mo->flags &= ~MF_MISSILE; + if (mo->info->deathsound) + { + S_StartSound(mo, mo->info->deathsound); + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_FloorBounceMissile +// +//---------------------------------------------------------------------------- + +void P_FloorBounceMissile(mobj_t * mo) +{ + mo->momz = -mo->momz; + P_SetMobjState(mo, mobjinfo[mo->type].deathstate); +} + +//---------------------------------------------------------------------------- +// +// PROC P_ThrustMobj +// +//---------------------------------------------------------------------------- + +void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move) +{ + angle >>= ANGLETOFINESHIFT; + mo->momx += FixedMul(move, finecosine[angle]); + mo->momy += FixedMul(move, finesine[angle]); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_FaceMobj +// +// Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs +// to turn counter clockwise. 'delta' is set to the amount 'source' +// needs to turn. +// +//---------------------------------------------------------------------------- + +int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta) +{ + angle_t diff; + angle_t angle1; + angle_t angle2; + + angle1 = source->angle; + angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y); + if (angle2 > angle1) + { + diff = angle2 - angle1; + if (diff > ANG180) + { + *delta = ANG_MAX - diff; + return (0); + } + else + { + *delta = diff; + return (1); + } + } + else + { + diff = angle1 - angle2; + if (diff > ANG180) + { + *delta = ANG_MAX - diff; + return (1); + } + else + { + *delta = diff; + return (0); + } + } +} + +//---------------------------------------------------------------------------- +// +// FUNC P_SeekerMissile +// +// The missile special1 field must be mobj_t *target. Returns true if +// target was tracked, false if not. +// +//---------------------------------------------------------------------------- + +boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax) +{ + int dir; + int dist; + angle_t delta; + angle_t angle; + mobj_t *target; + + target = (mobj_t *) actor->special1.m; + if (target == NULL) + { + return (false); + } + if (!(target->flags & MF_SHOOTABLE)) + { // Target died + actor->special1.m = NULL; + return (false); + } + dir = P_FaceMobj(actor, target, &delta); + if (delta > thresh) + { + delta >>= 1; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (dir) + { // Turn clockwise + actor->angle += delta; + } + else + { // Turn counter clockwise + actor->angle -= delta; + } + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(actor->info->speed, finecosine[angle]); + actor->momy = FixedMul(actor->info->speed, finesine[angle]); + if (actor->z + actor->height < target->z || + target->z + target->height < actor->z) + { // Need to seek vertically + dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); + dist = dist / actor->info->speed; + if (dist < 1) + { + dist = 1; + } + actor->momz = (target->z - actor->z) / dist; + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC P_XYMovement +// +//---------------------------------------------------------------------------- + +#define STOPSPEED 0x1000 +#define FRICTION_NORMAL 0xe800 +#define FRICTION_LOW 0xf900 +#define FRICTION_FLY 0xeb00 + +void P_XYMovement(mobj_t * mo) +{ + fixed_t ptryx, ptryy; + player_t *player; + fixed_t xmove, ymove; + int special; + static int windTab[3] = { 2048 * 5, 2048 * 10, 2048 * 25 }; + + if (!mo->momx && !mo->momy) + { + if (mo->flags & MF_SKULLFLY) + { // A flying mobj slammed into something + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + P_SetMobjState(mo, mo->info->seestate); + } + return; + } + special = mo->subsector->sector->special; + if (mo->flags2 & MF2_WINDTHRUST) + { + switch (special) + { + case 40: + case 41: + case 42: // Wind_East + P_ThrustMobj(mo, 0, windTab[special - 40]); + break; + case 43: + case 44: + case 45: // Wind_North + P_ThrustMobj(mo, ANG90, windTab[special - 43]); + break; + case 46: + case 47: + case 48: // Wind_South + P_ThrustMobj(mo, ANG270, windTab[special - 46]); + break; + case 49: + case 50: + case 51: // Wind_West + P_ThrustMobj(mo, ANG180, windTab[special - 49]); + break; + } + } + player = mo->player; + if (mo->momx > MAXMOVE) + { + mo->momx = MAXMOVE; + } + else if (mo->momx < -MAXMOVE) + { + mo->momx = -MAXMOVE; + } + if (mo->momy > MAXMOVE) + { + mo->momy = MAXMOVE; + } + else if (mo->momy < -MAXMOVE) + { + mo->momy = -MAXMOVE; + } + xmove = mo->momx; + ymove = mo->momy; + do + { + if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2) + { + ptryx = mo->x + xmove / 2; + ptryy = mo->y + ymove / 2; + xmove >>= 1; + ymove >>= 1; + } + else + { + ptryx = mo->x + xmove; + ptryy = mo->y + ymove; + xmove = ymove = 0; + } + if (!P_TryMove(mo, ptryx, ptryy)) + { // Blocked move + if (mo->flags2 & MF2_SLIDE) + { // Try to slide along it + P_SlideMove(mo); + } + else if (mo->flags & MF_MISSILE) + { // Explode a missile + if (ceilingline && ceilingline->backsector + && ceilingline->backsector->ceilingpic == skyflatnum) + { // Hack to prevent missiles exploding against the sky + if (mo->type == MT_BLOODYSKULL) + { + mo->momx = mo->momy = 0; + mo->momz = -FRACUNIT; + } + else + { + P_RemoveMobj(mo); + } + return; + } + P_ExplodeMissile(mo); + } + //else if(mo->info->crashstate) + //{ + // mo->momx = mo->momy = 0; + // P_SetMobjState(mo, mo->info->crashstate); + // return; + //} + else + { + mo->momx = mo->momy = 0; + } + } + } + while (xmove || ymove); + + // Friction + + if (player && player->cheats & CF_NOMOMENTUM) + { // Debug option for no sliding at all + mo->momx = mo->momy = 0; + return; + } + if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) + { // No friction for missiles + return; + } + if (mo->z > mo->floorz && !(mo->flags2 & MF2_FLY) + && !(mo->flags2 & MF2_ONMOBJ)) + { // No friction when falling + return; + } + if (mo->flags & MF_CORPSE) + { // Don't stop sliding if halfway off a step with some momentum + if (mo->momx > FRACUNIT / 4 || mo->momx < -FRACUNIT / 4 + || mo->momy > FRACUNIT / 4 || mo->momy < -FRACUNIT / 4) + { + if (mo->floorz != mo->subsector->sector->floorheight) + { + return; + } + } + } + if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED + && mo->momy > -STOPSPEED && mo->momy < STOPSPEED + && (!player || (player->cmd.forwardmove == 0 + && player->cmd.sidemove == 0))) + { // If in a walking frame, stop moving + if (player) + { + if (player->chickenTics) + { + if ((unsigned) ((player->mo->state - states) + - S_CHICPLAY_RUN1) < 4) + { + P_SetMobjState(player->mo, S_CHICPLAY); + } + } + else + { + if ((unsigned) ((player->mo->state - states) + - S_PLAY_RUN1) < 4) + { + P_SetMobjState(player->mo, S_PLAY); + } + } + } + mo->momx = 0; + mo->momy = 0; + } + else + { + if (mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) + && !(mo->flags2 & MF2_ONMOBJ)) + { + mo->momx = FixedMul(mo->momx, FRICTION_FLY); + mo->momy = FixedMul(mo->momy, FRICTION_FLY); + } + else if (special == 15) // Friction_Low + { + mo->momx = FixedMul(mo->momx, FRICTION_LOW); + mo->momy = FixedMul(mo->momy, FRICTION_LOW); + } + else + { + mo->momx = FixedMul(mo->momx, FRICTION_NORMAL); + mo->momy = FixedMul(mo->momy, FRICTION_NORMAL); + } + } +} + + +/* +=============== += += P_ZMovement += +=============== +*/ + +void P_ZMovement(mobj_t * mo) +{ + int dist; + int delta; +// +// check for smooth step up +// + if (mo->player && mo->z < mo->floorz) + { + mo->player->viewheight -= mo->floorz - mo->z; + mo->player->deltaviewheight = + (VIEWHEIGHT - mo->player->viewheight) >> 3; + } +// +// adjust height +// + mo->z += mo->momz; + if (mo->flags & MF_FLOAT && mo->target) + { // float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = + P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + if (delta < 0 && dist < -(delta * 3)) + mo->z -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->z += FLOATSPEED; + } + } + if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) + && leveltime & 2) + { + mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; + } + +// +// clip movement +// + if (mo->z <= mo->floorz) + { // Hit the floor + if (mo->flags & MF_MISSILE) + { + mo->z = mo->floorz; + if (mo->flags2 & MF2_FLOORBOUNCE) + { + P_FloorBounceMissile(mo); + return; + } + else if (mo->type == MT_MNTRFX2) + { // Minotaur floor fire can go up steps + return; + } + else + { + P_ExplodeMissile(mo); + return; + } + } + if (mo->z - mo->momz > mo->floorz) + { // Spawn splashes, etc. + P_HitFloor(mo); + } + mo->z = mo->floorz; + if (mo->momz < 0) + { + if (mo->player && mo->momz < -GRAVITY * 8 && !(mo->flags2 & MF2_FLY)) // squat down + { + mo->player->deltaviewheight = mo->momz >> 3; + S_StartSound(mo, sfx_plroof); + // haleyjd: removed externdriver crap + mo->player->centering = true; + } + mo->momz = 0; + } + if (mo->flags & MF_SKULLFLY) + { // The skull slammed into something + mo->momz = -mo->momz; + } + if (mo->info->crashstate && (mo->flags & MF_CORPSE)) + { + P_SetMobjState(mo, mo->info->crashstate); + return; + } + } + else if (mo->flags2 & MF2_LOGRAV) + { + if (mo->momz == 0) + mo->momz = -(GRAVITY >> 3) * 2; + else + mo->momz -= GRAVITY >> 3; + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + if (mo->momz == 0) + mo->momz = -GRAVITY * 2; + else + mo->momz -= GRAVITY; + } + + if (mo->z + mo->height > mo->ceilingz) + { // hit the ceiling + if (mo->momz > 0) + mo->momz = 0; + mo->z = mo->ceilingz - mo->height; + if (mo->flags & MF_SKULLFLY) + { // the skull slammed into something + mo->momz = -mo->momz; + } + if (mo->flags & MF_MISSILE) + { + if (mo->subsector->sector->ceilingpic == skyflatnum) + { + if (mo->type == MT_BLOODYSKULL) + { + mo->momx = mo->momy = 0; + mo->momz = -FRACUNIT; + } + else + { + P_RemoveMobj(mo); + } + return; + } + P_ExplodeMissile(mo); + return; + } + } +} + + +/* +================ += += P_NightmareRespawn += +================ +*/ + +void P_NightmareRespawn(mobj_t * mobj) +{ + fixed_t x, y, z; + subsector_t *ss; + mobj_t *mo; + mapthing_t *mthing; + + x = mobj->spawnpoint.x << FRACBITS; + y = mobj->spawnpoint.y << FRACBITS; + + if (!P_CheckPosition(mobj, x, y)) + return; // somthing is occupying it's position + + +// spawn a teleport fog at old spot + + mo = P_SpawnMobj(mobj->x, mobj->y, + mobj->subsector->sector->floorheight + TELEFOGHEIGHT, + MT_TFOG); + S_StartSound(mo, sfx_telept); + +// spawn a teleport fog at the new spot + ss = R_PointInSubsector(x, y); + mo = P_SpawnMobj(x, y, ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(mo, sfx_telept); + +// spawn the new monster + mthing = &mobj->spawnpoint; + +// spawn it + if (mobj->info->flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + mo = P_SpawnMobj(x, y, z, mobj->type); + mo->spawnpoint = mobj->spawnpoint; + mo->angle = ANG45 * (mthing->angle / 45); + if (mthing->options & MTF_AMBUSH) + mo->flags |= MF_AMBUSH; + + mo->reactiontime = 18; + +// remove the old monster + P_RemoveMobj(mobj); +} + +//---------------------------------------------------------------------------- +// +// PROC P_BlasterMobjThinker +// +// Thinker for the ultra-fast blaster PL2 ripper-spawning missile. +// +//---------------------------------------------------------------------------- + +void P_BlasterMobjThinker(thinker_t *thinker) +{ + mobj_t *mobj = (mobj_t *) thinker; + int i; + fixed_t xfrac; + fixed_t yfrac; + fixed_t zfrac; + fixed_t z; + boolean changexy; + + // Handle movement + if (mobj->momx || mobj->momy || (mobj->z != mobj->floorz) || mobj->momz) + { + xfrac = mobj->momx >> 3; + yfrac = mobj->momy >> 3; + zfrac = mobj->momz >> 3; + changexy = xfrac || yfrac; + for (i = 0; i < 8; i++) + { + if (changexy) + { + if (!P_TryMove(mobj, mobj->x + xfrac, mobj->y + yfrac)) + { // Blocked move + P_ExplodeMissile(mobj); + return; + } + } + mobj->z += zfrac; + if (mobj->z <= mobj->floorz) + { // Hit the floor + mobj->z = mobj->floorz; + P_HitFloor(mobj); + P_ExplodeMissile(mobj); + return; + } + if (mobj->z + mobj->height > mobj->ceilingz) + { // Hit the ceiling + mobj->z = mobj->ceilingz - mobj->height; + P_ExplodeMissile(mobj); + return; + } + if (changexy && (P_Random() < 64)) + { + z = mobj->z - 8 * FRACUNIT; + if (z < mobj->floorz) + { + z = mobj->floorz; + } + P_SpawnMobj(mobj->x, mobj->y, z, MT_BLASTERSMOKE); + } + } + } + // Advance the state + if (mobj->tics != -1) + { + mobj->tics--; + while (!mobj->tics) + { + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + { // mobj was removed + return; + } + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_MobjThinker +// +//---------------------------------------------------------------------------- + +void P_MobjThinker(thinker_t *thinker) +{ + mobj_t *mobj = (mobj_t *) thinker; + mobj_t *onmo; + + // Handle X and Y momentums + if (mobj->momx || mobj->momy || (mobj->flags & MF_SKULLFLY)) + { + P_XYMovement(mobj); + if (mobj->thinker.function == (think_t) - 1) + { // mobj was removed + return; + } + } + if (mobj->flags2 & MF2_FLOATBOB) + { // Floating item bobbing motion + mobj->z = mobj->floorz + FloatBobOffsets[(mobj->health++) & 63]; + } + else if ((mobj->z != mobj->floorz) || mobj->momz) + { // Handle Z momentum and gravity + if (mobj->flags2 & MF2_PASSMOBJ) + { + if (!(onmo = P_CheckOnmobj(mobj))) + { + P_ZMovement(mobj); + } + else + { + if (mobj->player && mobj->momz < 0) + { + mobj->flags2 |= MF2_ONMOBJ; + mobj->momz = 0; + } + if (mobj->player && (onmo->player || onmo->type == MT_POD)) + { + mobj->momx = onmo->momx; + mobj->momy = onmo->momy; + if (onmo->z < onmo->floorz) + { + mobj->z += onmo->floorz - onmo->z; + if (onmo->player) + { + onmo->player->viewheight -= + onmo->floorz - onmo->z; + onmo->player->deltaviewheight = + (VIEWHEIGHT - onmo->player->viewheight) >> 3; + } + onmo->z = onmo->floorz; + } + } + } + } + else + { + P_ZMovement(mobj); + } + if (mobj->thinker.function == (think_t) - 1) + { // mobj was removed + return; + } + } + +// +// cycle through states, calling action functions at transitions +// + if (mobj->tics != -1) + { + mobj->tics--; + // you can cycle through multiple states in a tic + while (!mobj->tics) + { + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + { // mobj was removed + return; + } + } + } + else + { // Check for monster respawn + if (!(mobj->flags & MF_COUNTKILL)) + { + return; + } + if (!respawnmonsters) + { + return; + } + mobj->movecount++; + if (mobj->movecount < 12 * 35) + { + return; + } + if (leveltime & 31) + { + return; + } + if (P_Random() > 4) + { + return; + } + P_NightmareRespawn(mobj); + } +} + +/* +=============== += += P_SpawnMobj += +=============== +*/ + +mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) +{ + mobj_t *mobj; + state_t *st; + mobjinfo_t *info; + fixed_t space; + + mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); + memset(mobj, 0, sizeof(*mobj)); + info = &mobjinfo[type]; + mobj->type = type; + mobj->info = info; + mobj->x = x; + mobj->y = y; + mobj->radius = info->radius; + mobj->height = info->height; + mobj->flags = info->flags; + mobj->flags2 = info->flags2; + mobj->damage = info->damage; + mobj->health = info->spawnhealth; + if (gameskill != sk_nightmare) + { + mobj->reactiontime = info->reactiontime; + } + mobj->lastlook = P_Random() % MAXPLAYERS; + + // Set the state, but do not use P_SetMobjState, because action + // routines can't be called yet. If the spawnstate has an action + // routine, it will not be called. + st = &states[info->spawnstate]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // Set subsector and/or block links. + P_SetThingPosition(mobj); + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + if (z == ONFLOORZ) + { + mobj->z = mobj->floorz; + } + else if (z == ONCEILINGZ) + { + mobj->z = mobj->ceilingz - mobj->info->height; + } + else if (z == FLOATRANDZ) + { + space = ((mobj->ceilingz) - (mobj->info->height)) - mobj->floorz; + if (space > 48 * FRACUNIT) + { + space -= 40 * FRACUNIT; + mobj->z = + ((space * P_Random()) >> 8) + mobj->floorz + 40 * FRACUNIT; + } + else + { + mobj->z = mobj->floorz; + } + } + else + { + mobj->z = z; + } + if (mobj->flags2 & MF2_FOOTCLIP + && P_GetThingFloorType(mobj) != FLOOR_SOLID + && mobj->floorz == mobj->subsector->sector->floorheight) + { + mobj->flags2 |= MF2_FEETARECLIPPED; + } + else + { + mobj->flags2 &= ~MF2_FEETARECLIPPED; + } + + mobj->thinker.function = P_MobjThinker; + P_AddThinker(&mobj->thinker); + return (mobj); +} + +/* +=============== += += P_RemoveMobj += +=============== +*/ + +void P_RemoveMobj(mobj_t * mobj) +{ +// unlink from sector and block lists + P_UnsetThingPosition(mobj); +// stop any playing sound + S_StopSound(mobj); +// free block + P_RemoveThinker((thinker_t *) mobj); +} + +//============================================================================= + + +/* +============ += += P_SpawnPlayer += += Called when a player is spawned on the level += Most of the player structure stays unchanged between levels +============ +*/ + +void P_SpawnPlayer(mapthing_t * mthing) +{ + player_t *p; + fixed_t x, y, z; + mobj_t *mobj; + int i; + + if (!playeringame[mthing->type - 1]) + return; // not playing + + p = &players[mthing->type - 1]; + + if (p->playerstate == PST_REBORN) + G_PlayerReborn(mthing->type - 1); + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + z = ONFLOORZ; + mobj = P_SpawnMobj(x, y, z, MT_PLAYER); + if (mthing->type > 1) // set color translations for player sprites + mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT; + + mobj->angle = ANG45 * (mthing->angle / 45); + mobj->player = p; + mobj->health = p->health; + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + p->message = NULL; + p->damagecount = 0; + p->bonuscount = 0; + p->chickenTics = 0; + p->rain1 = NULL; + p->rain2 = NULL; + p->extralight = 0; + p->fixedcolormap = 0; + p->viewheight = VIEWHEIGHT; + P_SetupPsprites(p); // setup gun psprite + if (deathmatch) + { // Give all keys in death match mode + for (i = 0; i < NUM_KEY_TYPES; i++) + { + p->keys[i] = true; + if (p == &players[consoleplayer]) + { + playerkeys = 7; + UpdateState |= I_STATBAR; + } + } + } + else if (p == &players[consoleplayer]) + { + playerkeys = 0; + UpdateState |= I_STATBAR; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_SpawnMapThing +// +// The fields of the mapthing should already be in host byte order. +// +//---------------------------------------------------------------------------- + +void P_SpawnMapThing(mapthing_t * mthing) +{ + int i; + int bit; + mobj_t *mobj; + fixed_t x, y, z; + +// count deathmatch start positions + if (mthing->type == 11) + { + if (deathmatch_p < &deathmatchstarts[10]) + { + memcpy(deathmatch_p, mthing, sizeof(*mthing)); + deathmatch_p++; + } + return; + } + +// check for players specially + if (mthing->type <= 4) + { + // save spots for respawning in network games + playerstarts[mthing->type - 1] = *mthing; + playerstartsingame[mthing->type - 1] = true; + if (!deathmatch) + { + P_SpawnPlayer(mthing); + } + return; + } + + // Ambient sound sequences + if (mthing->type >= 1200 && mthing->type < 1300) + { + P_AddAmbientSfx(mthing->type - 1200); + return; + } + + // Check for boss spots + if (mthing->type == 56) // Monster_BossSpot + { + P_AddBossSpot(mthing->x << FRACBITS, mthing->y << FRACBITS, + ANG45 * (mthing->angle / 45)); + return; + } + +// check for appropriate skill level + if (!netgame && (mthing->options & 16)) + return; + + if (gameskill == sk_baby) + bit = 1; + else if (gameskill == sk_nightmare) + bit = 4; + else + bit = 1 << (gameskill - 1); + if (!(mthing->options & bit)) + return; + +// find which type to spawn + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthing->type == mobjinfo[i].doomednum) + break; + + if (i == NUMMOBJTYPES) + I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)", mthing->type, + mthing->x, mthing->y); + +// don't spawn keys and players in deathmatch + if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) + return; + +// don't spawn any monsters if -nomonsters + if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) + return; + +// spawn it + switch (i) + { // Special stuff + case MT_WSKULLROD: + case MT_WPHOENIXROD: + case MT_AMSKRDWIMPY: + case MT_AMSKRDHEFTY: + case MT_AMPHRDWIMPY: + case MT_AMPHRDHEFTY: + case MT_AMMACEWIMPY: + case MT_AMMACEHEFTY: + case MT_ARTISUPERHEAL: + case MT_ARTITELEPORT: + case MT_ITEMSHIELD2: + if (gamemode == shareware) + { // Don't place on map in shareware version + return; + } + break; + case MT_WMACE: + if (gamemode != shareware) + { // Put in the mace spot list + P_AddMaceSpot(mthing); + return; + } + return; + default: + break; + } + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + if (mobjinfo[i].flags & MF_SPAWNCEILING) + { + z = ONCEILINGZ; + } + else if (mobjinfo[i].flags2 & MF2_SPAWNFLOAT) + { + z = FLOATRANDZ; + } + else + { + z = ONFLOORZ; + } + mobj = P_SpawnMobj(x, y, z, i); + if (mobj->flags2 & MF2_FLOATBOB) + { // Seed random starting index for bobbing motion + mobj->health = P_Random(); + } + if (mobj->tics > 0) + { + mobj->tics = 1 + (P_Random() % mobj->tics); + } + if (mobj->flags & MF_COUNTKILL) + { + totalkills++; + mobj->spawnpoint = *mthing; + } + if (mobj->flags & MF_COUNTITEM) + { + totalitems++; + } + mobj->angle = ANG45 * (mthing->angle / 45); + if (mthing->options & MTF_AMBUSH) + { + mobj->flags |= MF_AMBUSH; + } +} + +/* +=============================================================================== + + GAME SPAWN FUNCTIONS + +=============================================================================== +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_SpawnPuff +// +//--------------------------------------------------------------------------- + + +void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z) +{ + mobj_t *puff; + + z += (P_SubRandom() << 10); + puff = P_SpawnMobj(x, y, z, PuffType); + if (puff->info->attacksound) + { + S_StartSound(puff, puff->info->attacksound); + } + switch (PuffType) + { + case MT_BEAKPUFF: + case MT_STAFFPUFF: + puff->momz = FRACUNIT; + break; + case MT_GAUNTLETPUFF1: + case MT_GAUNTLETPUFF2: + puff->momz = (fixed_t)(.8 * FRACUNIT); + default: + break; + } +} + +/* +================ += += P_SpawnBlood += +================ +*/ + +/* +void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) +{ + mobj_t *th; + + z += (P_SubRandom()<<10); + th = P_SpawnMobj (x,y,z, MT_BLOOD); + th->momz = FRACUNIT*2; + th->tics -= P_Random()&3; + + if (damage <= 12 && damage >= 9) + P_SetMobjState (th,S_BLOOD2); + else if (damage < 9) + P_SetMobjState (th,S_BLOOD3); +} +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_BloodSplatter +// +//--------------------------------------------------------------------------- + +void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator) +{ + mobj_t *mo; + + mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER); + mo->target = originator; + mo->momx = P_SubRandom() << 9; + mo->momy = P_SubRandom() << 9; + mo->momz = FRACUNIT * 2; +} + +//--------------------------------------------------------------------------- +// +// PROC P_RipperBlood +// +//--------------------------------------------------------------------------- + +void P_RipperBlood(mobj_t * mo) +{ + mobj_t *th; + fixed_t x, y, z; + + x = mo->x + (P_SubRandom() << 12); + y = mo->y + (P_SubRandom() << 12); + z = mo->z + (P_SubRandom() << 12); + th = P_SpawnMobj(x, y, z, MT_BLOOD); + th->flags |= MF_NOGRAVITY; + th->momx = mo->momx >> 1; + th->momy = mo->momy >> 1; + th->tics += P_Random() & 3; +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GetThingFloorType +// +//--------------------------------------------------------------------------- + +int P_GetThingFloorType(mobj_t * thing) +{ + return (TerrainTypes[thing->subsector->sector->floorpic]); +/* + if(thing->subsector->sector->floorpic + == W_GetNumForName("FLTWAWA1")-firstflat) + { + return(FLOOR_WATER); + } + else + { + return(FLOOR_SOLID); + } +*/ +} + +//--------------------------------------------------------------------------- +// +// FUNC P_HitFloor +// +//--------------------------------------------------------------------------- + +int P_HitFloor(mobj_t * thing) +{ + mobj_t *mo; + + if (thing->floorz != thing->subsector->sector->floorheight) + { // don't splash if landing on the edge above water/lava/etc.... + return (FLOOR_SOLID); + } + switch (P_GetThingFloorType(thing)) + { + case FLOOR_WATER: + P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE); + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH); + mo->target = thing; + mo->momx = P_SubRandom() << 8; + mo->momy = P_SubRandom() << 8; + mo->momz = 2 * FRACUNIT + (P_Random() << 8); + S_StartSound(mo, sfx_gloop); + return (FLOOR_WATER); + case FLOOR_LAVA: + P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH); + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE); + mo->momz = FRACUNIT + (P_Random() << 7); + S_StartSound(mo, sfx_burn); + return (FLOOR_LAVA); + case FLOOR_SLUDGE: + P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGESPLASH); + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK); + mo->target = thing; + mo->momx = P_SubRandom() << 8; + mo->momy = P_SubRandom() << 8; + mo->momz = FRACUNIT + (P_Random() << 8); + return (FLOOR_SLUDGE); + } + return (FLOOR_SOLID); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_CheckMissileSpawn +// +// Returns true if the missile is at a valid spawn point, otherwise +// explodes it and returns false. +// +//--------------------------------------------------------------------------- + +boolean P_CheckMissileSpawn(mobj_t * missile) +{ + //missile->tics -= P_Random()&3; + + // move a little forward so an angle can be computed if it + // immediately explodes + missile->x += (missile->momx >> 1); + missile->y += (missile->momy >> 1); + missile->z += (missile->momz >> 1); + if (!P_TryMove(missile, missile->x, missile->y)) + { + P_ExplodeMissile(missile); + return (false); + } + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_SpawnMissile +// +// Returns NULL if the missile exploded immediately, otherwise returns +// a mobj_t pointer to the missile. +// +//--------------------------------------------------------------------------- + +mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type) +{ + fixed_t z; + mobj_t *th; + angle_t an; + int dist; + + switch (type) + { + case MT_MNTRFX1: // Minotaur swing attack missile + z = source->z + 40 * FRACUNIT; + break; + case MT_MNTRFX2: // Minotaur floor fire missile + z = ONFLOORZ; + break; + case MT_SRCRFX1: // Sorcerer Demon fireball + z = source->z + 48 * FRACUNIT; + break; + case MT_KNIGHTAXE: // Knight normal axe + case MT_REDAXE: // Knight red power axe + z = source->z + 36 * FRACUNIT; + break; + default: + z = source->z + 32 * FRACUNIT; + break; + } + if (source->flags2 & MF2_FEETARECLIPPED) + { + z -= FOOTCLIPSIZE; + } + th = P_SpawnMobj(source->x, source->y, z, type); + if (th->info->seesound) + { + S_StartSound(th, th->info->seesound); + } + th->target = source; // Originator + an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); + if (dest->flags & MF_SHADOW) + { // Invisible target + an += P_SubRandom() << 21; + } + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul(th->info->speed, finecosine[an]); + th->momy = FixedMul(th->info->speed, finesine[an]); + dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + if (dist < 1) + { + dist = 1; + } + th->momz = (dest->z - source->z) / dist; + return (P_CheckMissileSpawn(th) ? th : NULL); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_SpawnMissileAngle +// +// Returns NULL if the missile exploded immediately, otherwise returns +// a mobj_t pointer to the missile. +// +//--------------------------------------------------------------------------- + +mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, + angle_t angle, fixed_t momz) +{ + fixed_t z; + mobj_t *mo; + + switch (type) + { + case MT_MNTRFX1: // Minotaur swing attack missile + z = source->z + 40 * FRACUNIT; + break; + case MT_MNTRFX2: // Minotaur floor fire missile + z = ONFLOORZ; + break; + case MT_SRCRFX1: // Sorcerer Demon fireball + z = source->z + 48 * FRACUNIT; + break; + default: + z = source->z + 32 * FRACUNIT; + break; + } + if (source->flags2 & MF2_FEETARECLIPPED) + { + z -= FOOTCLIPSIZE; + } + mo = P_SpawnMobj(source->x, source->y, z, type); + if (mo->info->seesound) + { + S_StartSound(mo, mo->info->seesound); + } + mo->target = source; // Originator + mo->angle = angle; + angle >>= ANGLETOFINESHIFT; + mo->momx = FixedMul(mo->info->speed, finecosine[angle]); + mo->momy = FixedMul(mo->info->speed, finesine[angle]); + mo->momz = momz; + return (P_CheckMissileSpawn(mo) ? mo : NULL); +} + +/* +================ += += P_SpawnPlayerMissile += += Tries to aim at a nearby monster +================ +*/ + +mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type) +{ + angle_t an; + fixed_t x, y, z, slope; + + // Try to find a target + an = source->angle; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an += 1 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + } + if (!linetarget) + { + an = source->angle; + slope = ((source->player->lookdir) << FRACBITS) / 173; + } + } + x = source->x; + y = source->y; + z = source->z + 4 * 8 * FRACUNIT + + ((source->player->lookdir) << FRACBITS) / 173; + if (source->flags2 & MF2_FEETARECLIPPED) + { + z -= FOOTCLIPSIZE; + } + MissileMobj = P_SpawnMobj(x, y, z, type); + if (MissileMobj->info->seesound) + { + S_StartSound(MissileMobj, MissileMobj->info->seesound); + } + MissileMobj->target = source; + MissileMobj->angle = an; + MissileMobj->momx = FixedMul(MissileMobj->info->speed, + finecosine[an >> ANGLETOFINESHIFT]); + MissileMobj->momy = FixedMul(MissileMobj->info->speed, + finesine[an >> ANGLETOFINESHIFT]); + MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope); + if (MissileMobj->type == MT_BLASTERFX1) + { // Ultra-fast ripper spawning missile + MissileMobj->x += (MissileMobj->momx >> 3); + MissileMobj->y += (MissileMobj->momy >> 3); + MissileMobj->z += (MissileMobj->momz >> 3); + } + else + { // Normal missile + MissileMobj->x += (MissileMobj->momx >> 1); + MissileMobj->y += (MissileMobj->momy >> 1); + MissileMobj->z += (MissileMobj->momz >> 1); + } + if (!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y)) + { // Exploded immediately + P_ExplodeMissile(MissileMobj); + return (NULL); + } + return (MissileMobj); +} + +//--------------------------------------------------------------------------- +// +// PROC P_SPMAngle +// +//--------------------------------------------------------------------------- + +mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle) +{ + mobj_t *th; + angle_t an; + fixed_t x, y, z, slope; + +// +// see which target is to be aimed at +// + an = angle; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an += 1 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + } + if (!linetarget) + { + an = angle; + slope = ((source->player->lookdir) << FRACBITS) / 173; + } + } + x = source->x; + y = source->y; + z = source->z + 4 * 8 * FRACUNIT + + ((source->player->lookdir) << FRACBITS) / 173; + if (source->flags2 & MF2_FEETARECLIPPED) + { + z -= FOOTCLIPSIZE; + } + th = P_SpawnMobj(x, y, z, type); + if (th->info->seesound) + { + S_StartSound(th, th->info->seesound); + } + th->target = source; + th->angle = an; + th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); + th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); + th->momz = FixedMul(th->info->speed, slope); + return (P_CheckMissileSpawn(th) ? th : NULL); +} + +//--------------------------------------------------------------------------- +// +// PROC A_ContMobjSound +// +//--------------------------------------------------------------------------- + +void A_ContMobjSound(mobj_t * actor, player_t *player, pspdef_t *psp) +{ + switch (actor->type) + { + case MT_KNIGHTAXE: + S_StartSound(actor, sfx_kgtatk); + break; + case MT_MUMMYFX1: + S_StartSound(actor, sfx_mumhed); + break; + default: + break; + } +} diff --git a/games/NXDoom/src/heretic/p_plats.c b/games/NXDoom/src/heretic/p_plats.c new file mode 100644 index 00000000000..861a9a51a31 --- /dev/null +++ b/games/NXDoom/src/heretic/p_plats.c @@ -0,0 +1,259 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_plats.c + +#include "doomdef.h" +#include "i_system.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +plat_t *activeplats[MAXPLATS]; + +//================================================================== +// +// Move a plat up and down +// +//================================================================== +void T_PlatRaise(thinker_t *thinker) +{ + plat_t *plat = (plat_t *) thinker; + result_e res; + + switch (plat->status) + { + case up: + res = T_MovePlane(plat->sector, plat->speed, + plat->high, plat->crush, 0, 1); + if (!(leveltime & 31)) + { + S_StartSound(&plat->sector->soundorg, sfx_stnmov); + } + if (plat->type == raiseAndChange + || plat->type == raiseToNearestAndChange) + { + if (!(leveltime & 7)) + { + S_StartSound(&plat->sector->soundorg, + sfx_stnmov); + } + } + if (res == crushed && (!plat->crush)) + { + plat->count = plat->wait; + plat->status = down; + S_StartSound(&plat->sector->soundorg, sfx_pstart); + } + else if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound(&plat->sector->soundorg, sfx_pstop); + switch (plat->type) + { + case downWaitUpStay: + P_RemoveActivePlat(plat); + break; + case raiseAndChange: + P_RemoveActivePlat(plat); + break; + default: + break; + } + } + break; + case down: + res = + T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, + -1); + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound(&plat->sector->soundorg, sfx_pstop); + } + else + { + if (!(leveltime & 31)) + { + S_StartSound(&plat->sector->soundorg, + sfx_stnmov); + } + } + break; + case waiting: + if (!--plat->count) + { + if (plat->sector->floorheight == plat->low) + plat->status = up; + else + plat->status = down; + S_StartSound(&plat->sector->soundorg, sfx_pstart); + } + case in_stasis: + break; + } +} + +//================================================================== +// +// Do Platforms +// "amount" is only used for SOME platforms. +// +//================================================================== +int EV_DoPlat(line_t * line, plattype_e type, int amount) +{ + plat_t *plat; + int secnum; + int rtn; + sector_t *sec; + + secnum = -1; + rtn = 0; + + // + // Activate all plats that are in_stasis + // + switch (type) + { + case perpetualRaise: + P_ActivateInStasis(line->tag); + break; + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + // + // Find lowest & highest floors around sector + // + rtn = 1; + plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, 0); + P_AddThinker(&plat->thinker); + + plat->type = type; + plat->sector = sec; + plat->sector->specialdata = plat; + plat->thinker.function = T_PlatRaise; + plat->crush = false; + plat->tag = line->tag; + switch (type) + { + case raiseToNearestAndChange: + plat->speed = PLATSPEED / 2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = P_FindNextHighestFloor(sec, sec->floorheight); + plat->wait = 0; + plat->status = up; + sec->special = 0; // NO MORE DAMAGE, IF APPLICABLE + S_StartSound(&sec->soundorg, sfx_stnmov); + break; + case raiseAndChange: + plat->speed = PLATSPEED / 2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = sec->floorheight + amount * FRACUNIT; + plat->wait = 0; + plat->status = up; + S_StartSound(&sec->soundorg, sfx_stnmov); + break; + case downWaitUpStay: + plat->speed = PLATSPEED * 4; + plat->low = P_FindLowestFloorSurrounding(sec); + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = sec->floorheight; + plat->wait = 35 * PLATWAIT; + plat->status = down; + S_StartSound(&sec->soundorg, sfx_pstart); + break; + case perpetualRaise: + plat->speed = PLATSPEED; + plat->low = P_FindLowestFloorSurrounding(sec); + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = P_FindHighestFloorSurrounding(sec); + if (plat->high < sec->floorheight) + plat->high = sec->floorheight; + plat->wait = 35 * PLATWAIT; + plat->status = P_Random() & 1; + S_StartSound(&sec->soundorg, sfx_pstart); + break; + } + P_AddActivePlat(plat); + } + return rtn; +} + +void P_ActivateInStasis(int tag) +{ + int i; + + for (i = 0; i < MAXPLATS; i++) + if (activeplats[i] && + (activeplats[i])->tag == tag && + (activeplats[i])->status == in_stasis) + { + (activeplats[i])->status = (activeplats[i])->oldstatus; + (activeplats[i])->thinker.function = T_PlatRaise; + } +} + +void EV_StopPlat(line_t * line) +{ + int j; + + for (j = 0; j < MAXPLATS; j++) + if (activeplats[j] && ((activeplats[j])->status != in_stasis) && + ((activeplats[j])->tag == line->tag)) + { + (activeplats[j])->oldstatus = (activeplats[j])->status; + (activeplats[j])->status = in_stasis; + (activeplats[j])->thinker.function = NULL; + } +} + +void P_AddActivePlat(plat_t * plat) +{ + int i; + for (i = 0; i < MAXPLATS; i++) + if (activeplats[i] == NULL) + { + activeplats[i] = plat; + return; + } + I_Error("P_AddActivePlat: no more plats!"); +} + +void P_RemoveActivePlat(plat_t * plat) +{ + int i; + for (i = 0; i < MAXPLATS; i++) + if (plat == activeplats[i]) + { + (activeplats[i])->sector->specialdata = NULL; + P_RemoveThinker(&(activeplats[i])->thinker); + activeplats[i] = NULL; + return; + } + I_Error("P_RemoveActivePlat: can't find plat!"); +} diff --git a/games/NXDoom/src/heretic/p_pspr.c b/games/NXDoom/src/heretic/p_pspr.c new file mode 100644 index 00000000000..10e967dd6c9 --- /dev/null +++ b/games/NXDoom/src/heretic/p_pspr.c @@ -0,0 +1,1907 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_pspr.c + +#include "doomdef.h" +#include "i_system.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +// Macros + +#define LOWERSPEED FRACUNIT*6 +#define RAISESPEED FRACUNIT*6 +#define WEAPONBOTTOM 128*FRACUNIT +#define WEAPONTOP 32*FRACUNIT +#define FLAME_THROWER_TICS 10*35 +#define MAGIC_JUNK 1234 +#define MAX_MACE_SPOTS 8 + +static int MaceSpotCount; +static struct +{ + fixed_t x; + fixed_t y; +} MaceSpots[MAX_MACE_SPOTS]; + +fixed_t bulletslope; + +static int WeaponAmmoUsePL1[NUMWEAPONS] = { + 0, // staff + USE_GWND_AMMO_1, // gold wand + USE_CBOW_AMMO_1, // crossbow + USE_BLSR_AMMO_1, // blaster + USE_SKRD_AMMO_1, // skull rod + USE_PHRD_AMMO_1, // phoenix rod + USE_MACE_AMMO_1, // mace + 0, // gauntlets + 0 // beak +}; + +static int WeaponAmmoUsePL2[NUMWEAPONS] = { + 0, // staff + USE_GWND_AMMO_2, // gold wand + USE_CBOW_AMMO_2, // crossbow + USE_BLSR_AMMO_2, // blaster + USE_SKRD_AMMO_2, // skull rod + USE_PHRD_AMMO_2, // phoenix rod + USE_MACE_AMMO_2, // mace + 0, // gauntlets + 0 // beak +}; + +weaponinfo_t wpnlev1info[NUMWEAPONS] = { + { // Staff + am_noammo, // ammo + S_STAFFUP, // upstate + S_STAFFDOWN, // downstate + S_STAFFREADY, // readystate + S_STAFFATK1_1, // atkstate + S_STAFFATK1_1, // holdatkstate + S_NULL // flashstate + }, + { // Gold wand + am_goldwand, // ammo + S_GOLDWANDUP, // upstate + S_GOLDWANDDOWN, // downstate + S_GOLDWANDREADY, // readystate + S_GOLDWANDATK1_1, // atkstate + S_GOLDWANDATK1_1, // holdatkstate + S_NULL // flashstate + }, + { // Crossbow + am_crossbow, // ammo + S_CRBOWUP, // upstate + S_CRBOWDOWN, // downstate + S_CRBOW1, // readystate + S_CRBOWATK1_1, // atkstate + S_CRBOWATK1_1, // holdatkstate + S_NULL // flashstate + }, + { // Blaster + am_blaster, // ammo + S_BLASTERUP, // upstate + S_BLASTERDOWN, // downstate + S_BLASTERREADY, // readystate + S_BLASTERATK1_1, // atkstate + S_BLASTERATK1_3, // holdatkstate + S_NULL // flashstate + }, + { // Skull rod + am_skullrod, // ammo + S_HORNRODUP, // upstate + S_HORNRODDOWN, // downstate + S_HORNRODREADY, // readystae + S_HORNRODATK1_1, // atkstate + S_HORNRODATK1_1, // holdatkstate + S_NULL // flashstate + }, + { // Phoenix rod + am_phoenixrod, // ammo + S_PHOENIXUP, // upstate + S_PHOENIXDOWN, // downstate + S_PHOENIXREADY, // readystate + S_PHOENIXATK1_1, // atkstate + S_PHOENIXATK1_1, // holdatkstate + S_NULL // flashstate + }, + { // Mace + am_mace, // ammo + S_MACEUP, // upstate + S_MACEDOWN, // downstate + S_MACEREADY, // readystate + S_MACEATK1_1, // atkstate + S_MACEATK1_2, // holdatkstate + S_NULL // flashstate + }, + { // Gauntlets + am_noammo, // ammo + S_GAUNTLETUP, // upstate + S_GAUNTLETDOWN, // downstate + S_GAUNTLETREADY, // readystate + S_GAUNTLETATK1_1, // atkstate + S_GAUNTLETATK1_3, // holdatkstate + S_NULL // flashstate + }, + { // Beak + am_noammo, // ammo + S_BEAKUP, // upstate + S_BEAKDOWN, // downstate + S_BEAKREADY, // readystate + S_BEAKATK1_1, // atkstate + S_BEAKATK1_1, // holdatkstate + S_NULL // flashstate + } +}; + +weaponinfo_t wpnlev2info[NUMWEAPONS] = { + { // Staff + am_noammo, // ammo + S_STAFFUP2, // upstate + S_STAFFDOWN2, // downstate + S_STAFFREADY2_1, // readystate + S_STAFFATK2_1, // atkstate + S_STAFFATK2_1, // holdatkstate + S_NULL // flashstate + }, + { // Gold wand + am_goldwand, // ammo + S_GOLDWANDUP, // upstate + S_GOLDWANDDOWN, // downstate + S_GOLDWANDREADY, // readystate + S_GOLDWANDATK2_1, // atkstate + S_GOLDWANDATK2_1, // holdatkstate + S_NULL // flashstate + }, + { // Crossbow + am_crossbow, // ammo + S_CRBOWUP, // upstate + S_CRBOWDOWN, // downstate + S_CRBOW1, // readystate + S_CRBOWATK2_1, // atkstate + S_CRBOWATK2_1, // holdatkstate + S_NULL // flashstate + }, + { // Blaster + am_blaster, // ammo + S_BLASTERUP, // upstate + S_BLASTERDOWN, // downstate + S_BLASTERREADY, // readystate + S_BLASTERATK2_1, // atkstate + S_BLASTERATK2_3, // holdatkstate + S_NULL // flashstate + }, + { // Skull rod + am_skullrod, // ammo + S_HORNRODUP, // upstate + S_HORNRODDOWN, // downstate + S_HORNRODREADY, // readystae + S_HORNRODATK2_1, // atkstate + S_HORNRODATK2_1, // holdatkstate + S_NULL // flashstate + }, + { // Phoenix rod + am_phoenixrod, // ammo + S_PHOENIXUP, // upstate + S_PHOENIXDOWN, // downstate + S_PHOENIXREADY, // readystate + S_PHOENIXATK2_1, // atkstate + S_PHOENIXATK2_2, // holdatkstate + S_NULL // flashstate + }, + { // Mace + am_mace, // ammo + S_MACEUP, // upstate + S_MACEDOWN, // downstate + S_MACEREADY, // readystate + S_MACEATK2_1, // atkstate + S_MACEATK2_1, // holdatkstate + S_NULL // flashstate + }, + { // Gauntlets + am_noammo, // ammo + S_GAUNTLETUP2, // upstate + S_GAUNTLETDOWN2, // downstate + S_GAUNTLETREADY2_1, // readystate + S_GAUNTLETATK2_1, // atkstate + S_GAUNTLETATK2_3, // holdatkstate + S_NULL // flashstate + }, + { // Beak + am_noammo, // ammo + S_BEAKUP, // upstate + S_BEAKDOWN, // downstate + S_BEAKREADY, // readystate + S_BEAKATK2_1, // atkstate + S_BEAKATK2_1, // holdatkstate + S_NULL // flashstate + } +}; + +//--------------------------------------------------------------------------- +// +// PROC P_OpenWeapons +// +// Called at level load before things are loaded. +// +//--------------------------------------------------------------------------- + +void P_OpenWeapons(void) +{ + MaceSpotCount = 0; +} + +//--------------------------------------------------------------------------- +// +// PROC P_AddMaceSpot +// +//--------------------------------------------------------------------------- + +void P_AddMaceSpot(mapthing_t * mthing) +{ + if (MaceSpotCount == MAX_MACE_SPOTS) + { + I_Error("Too many mace spots."); + } + MaceSpots[MaceSpotCount].x = mthing->x << FRACBITS; + MaceSpots[MaceSpotCount].y = mthing->y << FRACBITS; + MaceSpotCount++; +} + +//--------------------------------------------------------------------------- +// +// PROC P_RepositionMace +// +// Chooses the next spot to place the mace. +// +//--------------------------------------------------------------------------- + +void P_RepositionMace(mobj_t * mo) +{ + int spot; + subsector_t *ss; + + P_UnsetThingPosition(mo); + spot = P_Random() % MaceSpotCount; + mo->x = MaceSpots[spot].x; + mo->y = MaceSpots[spot].y; + ss = R_PointInSubsector(mo->x, mo->y); + mo->z = mo->floorz = ss->sector->floorheight; + mo->ceilingz = ss->sector->ceilingheight; + P_SetThingPosition(mo); +} + +//--------------------------------------------------------------------------- +// +// PROC P_CloseWeapons +// +// Called at level load after things are loaded. +// +//--------------------------------------------------------------------------- + +void P_CloseWeapons(void) +{ + int spot; + + if (!MaceSpotCount) + { // No maces placed + return; + } + if (!deathmatch && P_Random() < 64) + { // Sometimes doesn't show up if not in deathmatch + return; + } + spot = P_Random() % MaceSpotCount; + P_SpawnMobj(MaceSpots[spot].x, MaceSpots[spot].y, ONFLOORZ, MT_WMACE); +} + +//--------------------------------------------------------------------------- +// +// PROC P_SetPsprite +// +//--------------------------------------------------------------------------- + +void P_SetPsprite(player_t * player, int position, statenum_t stnum) +{ + pspdef_t *psp; + state_t *state; + + psp = &player->psprites[position]; + do + { + if (!stnum) + { // Object removed itself. + psp->state = NULL; + break; + } + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; // could be 0 + if (state->misc1) + { // Set coordinates. + psp->sx = state->misc1 << FRACBITS; + psp->sy = state->misc2 << FRACBITS; + } + if (state->action) + { // Call action routine. + state->action(NULL, player, psp); + if (!psp->state) + { + break; + } + } + stnum = psp->state->nextstate; + } + while (!psp->tics); // An initial state of 0 could cycle through. +} + +/* +================= += += P_CalcSwing += +================= +*/ + +/* +fixed_t swingx, swingy; +void P_CalcSwing (player_t *player) +{ + fixed_t swing; + int angle; + +// OPTIMIZE: tablify this + + swing = player->bob; + + angle = (FINEANGLES/70*leveltime)&FINEMASK; + swingx = FixedMul ( swing, finesine[angle]); + + angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; + swingy = -FixedMul ( swingx, finesine[angle]); +} +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_ActivateBeak +// +//--------------------------------------------------------------------------- + +void P_ActivateBeak(player_t * player) +{ + player->pendingweapon = wp_nochange; + player->readyweapon = wp_beak; + player->psprites[ps_weapon].sy = WEAPONTOP; + P_SetPsprite(player, ps_weapon, S_BEAKREADY); +} + +//--------------------------------------------------------------------------- +// +// PROC P_PostChickenWeapon +// +//--------------------------------------------------------------------------- + +void P_PostChickenWeapon(player_t * player, weapontype_t weapon) +{ + if (weapon == wp_beak) + { // Should never happen + weapon = wp_staff; + } + player->pendingweapon = wp_nochange; + player->readyweapon = weapon; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + P_SetPsprite(player, ps_weapon, wpnlev1info[weapon].upstate); +} + +//--------------------------------------------------------------------------- +// +// PROC P_BringUpWeapon +// +// Starts bringing the pending weapon up from the bottom of the screen. +// +//--------------------------------------------------------------------------- + +void P_BringUpWeapon(player_t * player) +{ + statenum_t new; + + if (player->pendingweapon == wp_nochange) + { + player->pendingweapon = player->readyweapon; + } + if (player->pendingweapon == wp_gauntlets) + { + S_StartSound(player->mo, sfx_gntact); + } + if (player->powers[pw_weaponlevel2]) + { + new = wpnlev2info[player->pendingweapon].upstate; + } + else + { + new = wpnlev1info[player->pendingweapon].upstate; + } + player->pendingweapon = wp_nochange; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + P_SetPsprite(player, ps_weapon, new); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_CheckAmmo +// +// Returns true if there is enough ammo to shoot. If not, selects the +// next weapon to use. +// +//--------------------------------------------------------------------------- + +boolean P_CheckAmmo(player_t * player) +{ + ammotype_t ammo; + int *ammoUse; + int count; + + ammo = wpnlev1info[player->readyweapon].ammo; + if (player->powers[pw_weaponlevel2] && !deathmatch) + { + ammoUse = WeaponAmmoUsePL2; + } + else + { + ammoUse = WeaponAmmoUsePL1; + } + count = ammoUse[player->readyweapon]; + if (ammo == am_noammo || player->ammo[ammo] >= count) + { + return (true); + } + // out of ammo, pick a weapon to change to + do + { + if (player->weaponowned[wp_skullrod] + && player->ammo[am_skullrod] > ammoUse[wp_skullrod]) + { + player->pendingweapon = wp_skullrod; + } + else if (player->weaponowned[wp_blaster] + && player->ammo[am_blaster] > ammoUse[wp_blaster]) + { + player->pendingweapon = wp_blaster; + } + else if (player->weaponowned[wp_crossbow] + && player->ammo[am_crossbow] > ammoUse[wp_crossbow]) + { + player->pendingweapon = wp_crossbow; + } + else if (player->weaponowned[wp_mace] + && player->ammo[am_mace] > ammoUse[wp_mace]) + { + player->pendingweapon = wp_mace; + } + else if (player->ammo[am_goldwand] > ammoUse[wp_goldwand]) + { + player->pendingweapon = wp_goldwand; + } + else if (player->weaponowned[wp_gauntlets]) + { + player->pendingweapon = wp_gauntlets; + } + else if (player->weaponowned[wp_phoenixrod] + && player->ammo[am_phoenixrod] > ammoUse[wp_phoenixrod]) + { + player->pendingweapon = wp_phoenixrod; + } + else + { + player->pendingweapon = wp_staff; + } + } + while (player->pendingweapon == wp_nochange); + if (player->powers[pw_weaponlevel2]) + { + P_SetPsprite(player, ps_weapon, + wpnlev2info[player->readyweapon].downstate); + } + else + { + P_SetPsprite(player, ps_weapon, + wpnlev1info[player->readyweapon].downstate); + } + return (false); +} + +//--------------------------------------------------------------------------- +// +// PROC P_FireWeapon +// +//--------------------------------------------------------------------------- + +void P_FireWeapon(player_t * player) +{ + weaponinfo_t *wpinfo; + statenum_t attackState; + + if (!P_CheckAmmo(player)) + { + return; + } + P_SetMobjState(player->mo, S_PLAY_ATK2); + wpinfo = player->powers[pw_weaponlevel2] ? &wpnlev2info[0] + : &wpnlev1info[0]; + attackState = player->refire ? wpinfo[player->readyweapon].holdatkstate + : wpinfo[player->readyweapon].atkstate; + P_SetPsprite(player, ps_weapon, attackState); + P_NoiseAlert(player->mo, player->mo); + if (player->readyweapon == wp_gauntlets && !player->refire) + { // Play the sound for the initial gauntlet attack + S_StartSound(player->mo, sfx_gntuse); + } +} + +//--------------------------------------------------------------------------- +// +// PROC P_DropWeapon +// +// The player died, so put the weapon away. +// +//--------------------------------------------------------------------------- + +void P_DropWeapon(player_t * player) +{ + if (player->powers[pw_weaponlevel2]) + { + P_SetPsprite(player, ps_weapon, + wpnlev2info[player->readyweapon].downstate); + } + else + { + P_SetPsprite(player, ps_weapon, + wpnlev1info[player->readyweapon].downstate); + } +} + +//--------------------------------------------------------------------------- +// +// PROC A_WeaponReady +// +// The player can fire the weapon or change to another weapon at this time. +// +//--------------------------------------------------------------------------- + +void A_WeaponReady(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int angle; + + if (player->chickenTics) + { // Change to the chicken beak + P_ActivateBeak(player); + return; + } + // Change player from attack state + if (player->mo->state == &states[S_PLAY_ATK1] + || player->mo->state == &states[S_PLAY_ATK2]) + { + P_SetMobjState(player->mo, S_PLAY); + } + // Check for staff PL2 active sound + if ((player->readyweapon == wp_staff) + && (psp->state == &states[S_STAFFREADY2_1]) && P_Random() < 128) + { + S_StartSound(player->mo, sfx_stfcrk); + } + // Put the weapon away if the player has a pending weapon or has + // died. + if (player->pendingweapon != wp_nochange || !player->health) + { + if (player->powers[pw_weaponlevel2]) + { + P_SetPsprite(player, ps_weapon, + wpnlev2info[player->readyweapon].downstate); + } + else + { + P_SetPsprite(player, ps_weapon, + wpnlev1info[player->readyweapon].downstate); + } + return; + } + + // Check for fire. The phoenix rod does not auto fire. + if (player->cmd.buttons & BT_ATTACK) + { + if (!player->attackdown || (player->readyweapon != wp_phoenixrod)) + { + player->attackdown = true; + P_FireWeapon(player); + return; + } + } + else + { + player->attackdown = false; + } + + // Bob the weapon based on movement speed. + angle = (128 * leveltime) & FINEMASK; + psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]); + angle &= FINEANGLES / 2 - 1; + psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]); +} + +//--------------------------------------------------------------------------- +// +// PROC P_UpdateBeak +// +//--------------------------------------------------------------------------- + +void P_UpdateBeak(player_t * player, pspdef_t * psp) +{ + psp->sy = WEAPONTOP + (player->chickenPeck << (FRACBITS - 1)); +} + +//--------------------------------------------------------------------------- +// +// PROC A_BeakReady +// +//--------------------------------------------------------------------------- + +void A_BeakReady(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (player->cmd.buttons & BT_ATTACK) + { // Chicken beak attack + player->attackdown = true; + P_SetMobjState(player->mo, S_CHICPLAY_ATK1); + if (player->powers[pw_weaponlevel2]) + { + P_SetPsprite(player, ps_weapon, S_BEAKATK2_1); + } + else + { + P_SetPsprite(player, ps_weapon, S_BEAKATK1_1); + } + P_NoiseAlert(player->mo, player->mo); + } + else + { + if (player->mo->state == &states[S_CHICPLAY_ATK1]) + { // Take out of attack state + P_SetMobjState(player->mo, S_CHICPLAY); + } + player->attackdown = false; + } +} + +//--------------------------------------------------------------------------- +// +// PROC A_ReFire +// +// The player can re fire the weapon without lowering it entirely. +// +//--------------------------------------------------------------------------- + +void A_ReFire(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if ((player->cmd.buttons & BT_ATTACK) + && player->pendingweapon == wp_nochange && player->health) + { + player->refire++; + P_FireWeapon(player); + } + else + { + player->refire = 0; + P_CheckAmmo(player); + } +} + +//--------------------------------------------------------------------------- +// +// PROC A_Lower +// +//--------------------------------------------------------------------------- + +void A_Lower(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (player->chickenTics) + { + psp->sy = WEAPONBOTTOM; + } + else + { + psp->sy += LOWERSPEED; + } + if (psp->sy < WEAPONBOTTOM) + { // Not lowered all the way yet + return; + } + if (player->playerstate == PST_DEAD) + { // Player is dead, so don't bring up a pending weapon + psp->sy = WEAPONBOTTOM; + return; + } + if (!player->health) + { // Player is dead, so keep the weapon off screen + P_SetPsprite(player, ps_weapon, S_NULL); + return; + } + player->readyweapon = player->pendingweapon; + P_BringUpWeapon(player); +} + +//--------------------------------------------------------------------------- +// +// PROC A_BeakRaise +// +//--------------------------------------------------------------------------- + +void A_BeakRaise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + psp->sy = WEAPONTOP; + P_SetPsprite(player, ps_weapon, + wpnlev1info[player->readyweapon].readystate); +} + +//--------------------------------------------------------------------------- +// +// PROC A_Raise +// +//--------------------------------------------------------------------------- + +void A_Raise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + psp->sy -= RAISESPEED; + if (psp->sy > WEAPONTOP) + { // Not raised all the way yet + return; + } + psp->sy = WEAPONTOP; + if (player->powers[pw_weaponlevel2]) + { + P_SetPsprite(player, ps_weapon, + wpnlev2info[player->readyweapon].readystate); + } + else + { + P_SetPsprite(player, ps_weapon, + wpnlev1info[player->readyweapon].readystate); + } +} + +/* +=============== += += P_BulletSlope += += Sets a slope so a near miss is at aproximately the height of the += intended target += +=============== +*/ + +void P_BulletSlope(mobj_t * mo) +{ + angle_t an; + +// +// see which target is to be aimed at +// + an = mo->angle; + bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an += 1 << 26; + bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT); + } + if (!linetarget) + { + an += 2 << 26; + bulletslope = (mo->player->lookdir << FRACBITS) / 173; + } + } +} + +//**************************************************************************** +// +// WEAPON ATTACKS +// +//**************************************************************************** + +//---------------------------------------------------------------------------- +// +// PROC A_BeakAttackPL1 +// +//---------------------------------------------------------------------------- + +void A_BeakAttackPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + + damage = 1 + (P_Random() & 3); + angle = player->mo->angle; + slope = P_AimLineAttack(player->mo, angle, MELEERANGE); + PuffType = MT_BEAKPUFF; + P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); + if (linetarget) + { + player->mo->angle = R_PointToAngle2(player->mo->x, + player->mo->y, linetarget->x, + linetarget->y); + } + S_StartSound(player->mo, sfx_chicpk1 + (P_Random() % 3)); + player->chickenPeck = 12; + psp->tics -= P_Random() & 7; +} + +//---------------------------------------------------------------------------- +// +// PROC A_BeakAttackPL2 +// +//---------------------------------------------------------------------------- + +void A_BeakAttackPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + + damage = HITDICE(4); + angle = player->mo->angle; + slope = P_AimLineAttack(player->mo, angle, MELEERANGE); + PuffType = MT_BEAKPUFF; + P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); + if (linetarget) + { + player->mo->angle = R_PointToAngle2(player->mo->x, + player->mo->y, linetarget->x, + linetarget->y); + } + S_StartSound(player->mo, sfx_chicpk1 + (P_Random() % 3)); + player->chickenPeck = 12; + psp->tics -= P_Random() & 3; +} + +//---------------------------------------------------------------------------- +// +// PROC A_StaffAttackPL1 +// +//---------------------------------------------------------------------------- + +void A_StaffAttackPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + + damage = 5 + (P_Random() & 15); + angle = player->mo->angle; + angle += P_SubRandom() << 18; + slope = P_AimLineAttack(player->mo, angle, MELEERANGE); + PuffType = MT_STAFFPUFF; + P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); + if (linetarget) + { + //S_StartSound(player->mo, sfx_stfhit); + // turn to face target + player->mo->angle = R_PointToAngle2(player->mo->x, + player->mo->y, linetarget->x, + linetarget->y); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_StaffAttackPL2 +// +//---------------------------------------------------------------------------- + +void A_StaffAttackPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + + // P_inter.c:P_DamageMobj() handles target momentums + damage = 18 + (P_Random() & 63); + angle = player->mo->angle; + angle += P_SubRandom() << 18; + slope = P_AimLineAttack(player->mo, angle, MELEERANGE); + PuffType = MT_STAFFPUFF2; + P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); + if (linetarget) + { + //S_StartSound(player->mo, sfx_stfpow); + // turn to face target + player->mo->angle = R_PointToAngle2(player->mo->x, + player->mo->y, linetarget->x, + linetarget->y); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireBlasterPL1 +// +//---------------------------------------------------------------------------- + +void A_FireBlasterPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + int damage; + + mo = player->mo; + S_StartSound(mo, sfx_gldhit); + player->ammo[am_blaster] -= USE_BLSR_AMMO_1; + P_BulletSlope(mo); + damage = HITDICE(4); + angle = mo->angle; + if (player->refire) + { + angle += P_SubRandom() << 18; + } + PuffType = MT_BLASTERPUFF1; + P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); + S_StartSound(player->mo, sfx_blssht); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireBlasterPL2 +// +//---------------------------------------------------------------------------- + +void A_FireBlasterPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + player->ammo[am_blaster] -= + deathmatch ? USE_BLSR_AMMO_1 : USE_BLSR_AMMO_2; + mo = P_SpawnPlayerMissile(player->mo, MT_BLASTERFX1); + if (mo) + { + mo->thinker.function = P_BlasterMobjThinker; + } + S_StartSound(player->mo, sfx_blssht); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireGoldWandPL1 +// +//---------------------------------------------------------------------------- + +void A_FireGoldWandPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + int damage; + + mo = player->mo; + player->ammo[am_goldwand] -= USE_GWND_AMMO_1; + P_BulletSlope(mo); + damage = 7 + (P_Random() & 7); + angle = mo->angle; + if (player->refire) + { + angle += P_SubRandom() << 18; + } + PuffType = MT_GOLDWANDPUFF1; + P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); + S_StartSound(player->mo, sfx_gldhit); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireGoldWandPL2 +// +//---------------------------------------------------------------------------- + +void A_FireGoldWandPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + mobj_t *mo; + angle_t angle; + int damage; + fixed_t momz; + + mo = player->mo; + player->ammo[am_goldwand] -= + deathmatch ? USE_GWND_AMMO_1 : USE_GWND_AMMO_2; + PuffType = MT_GOLDWANDPUFF2; + P_BulletSlope(mo); + momz = FixedMul(mobjinfo[MT_GOLDWANDFX2].speed, bulletslope); + P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle - (ANG45 / 8), momz); + P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle + (ANG45 / 8), momz); + angle = mo->angle - (ANG45 / 8); + for (i = 0; i < 5; i++) + { + damage = 1 + (P_Random() & 7); + P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); + angle += ((ANG45 / 8) * 2) / 4; + } + S_StartSound(player->mo, sfx_gldhit); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireMacePL1B +// +//---------------------------------------------------------------------------- + +void A_FireMacePL1B(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *pmo; + mobj_t *ball; + angle_t angle; + + if (player->ammo[am_mace] < USE_MACE_AMMO_1) + { + return; + } + player->ammo[am_mace] -= USE_MACE_AMMO_1; + pmo = player->mo; + + // Vanilla bug here: + // Original code here looks like: + // (pmo->flags2 & MF2_FEETARECLIPPED != 0) + // C's operator precedence interprets this as: + // (pmo->flags2 & (MF2_FEETARECLIPPED != 0)) + // Which simplifies to: + // (pmo->flags2 & 1) + ball = P_SpawnMobj(pmo->x, pmo->y, pmo->z + 28 * FRACUNIT + - FOOTCLIPSIZE * (pmo->flags2 & 1), MT_MACEFX2); + + ball->momz = 2 * FRACUNIT + ((player->lookdir) << (FRACBITS - 5)); + angle = pmo->angle; + ball->target = pmo; + ball->angle = angle; + ball->z += (player->lookdir) << (FRACBITS - 4); + angle >>= ANGLETOFINESHIFT; + ball->momx = (pmo->momx >> 1) + + FixedMul(ball->info->speed, finecosine[angle]); + ball->momy = (pmo->momy >> 1) + + FixedMul(ball->info->speed, finesine[angle]); + S_StartSound(ball, sfx_lobsht); + P_CheckMissileSpawn(ball); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireMacePL1 +// +//---------------------------------------------------------------------------- + +void A_FireMacePL1(mobj_t *mobj, player_t * player, pspdef_t * psp) +{ + mobj_t *ball; + + if (P_Random() < 28) + { + A_FireMacePL1B(mobj, player, psp); + return; + } + if (player->ammo[am_mace] < USE_MACE_AMMO_1) + { + return; + } + player->ammo[am_mace] -= USE_MACE_AMMO_1; + psp->sx = ((P_Random() & 3) - 2) * FRACUNIT; + psp->sy = WEAPONTOP + (P_Random() & 3) * FRACUNIT; + ball = P_SPMAngle(player->mo, MT_MACEFX1, player->mo->angle + + (((P_Random() & 7) - 4) << 24)); + if (ball) + { + ball->special1.i = 16; // tics till dropoff + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MacePL1Check +// +//---------------------------------------------------------------------------- + +void A_MacePL1Check(mobj_t * ball, player_t *player, pspdef_t *psp) +{ + angle_t angle; + + if (ball->special1.i == 0) + { + return; + } + ball->special1.i -= 4; + if (ball->special1.i > 0) + { + return; + } + ball->special1.i = 0; + ball->flags2 |= MF2_LOGRAV; + angle = ball->angle >> ANGLETOFINESHIFT; + ball->momx = FixedMul(7 * FRACUNIT, finecosine[angle]); + ball->momy = FixedMul(7 * FRACUNIT, finesine[angle]); + ball->momz -= ball->momz >> 1; +} + +//---------------------------------------------------------------------------- +// +// PROC A_MaceBallImpact +// +//---------------------------------------------------------------------------- + +void A_MaceBallImpact(mobj_t * ball, player_t *player, pspdef_t *psp) +{ + if ((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID)) + { // Landed in some sort of liquid + P_RemoveMobj(ball); + return; + } + if ((ball->health != MAGIC_JUNK) && (ball->z <= ball->floorz) + && ball->momz) + { // Bounce + ball->health = MAGIC_JUNK; + ball->momz = (ball->momz * 192) >> 8; + ball->flags2 &= ~MF2_FLOORBOUNCE; + P_SetMobjState(ball, ball->info->spawnstate); + S_StartSound(ball, sfx_bounce); + } + else + { // Explode + ball->flags |= MF_NOGRAVITY; + ball->flags2 &= ~MF2_LOGRAV; + S_StartSound(ball, sfx_lobhit); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MaceBallImpact2 +// +//---------------------------------------------------------------------------- + +void A_MaceBallImpact2(mobj_t * ball, player_t *player, pspdef_t *psp) +{ + mobj_t *tiny; + angle_t angle; + + if ((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID)) + { // Landed in some sort of liquid + P_RemoveMobj(ball); + return; + } + if ((ball->z != ball->floorz) || (ball->momz < 2 * FRACUNIT)) + { // Explode + ball->momx = ball->momy = ball->momz = 0; + ball->flags |= MF_NOGRAVITY; + ball->flags2 &= ~(MF2_LOGRAV | MF2_FLOORBOUNCE); + } + else + { // Bounce + ball->momz = (ball->momz * 192) >> 8; + P_SetMobjState(ball, ball->info->spawnstate); + + tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3); + angle = ball->angle + ANG90; + tiny->target = ball->target; + tiny->angle = angle; + angle >>= ANGLETOFINESHIFT; + tiny->momx = (ball->momx >> 1) + FixedMul(ball->momz - FRACUNIT, + finecosine[angle]); + tiny->momy = (ball->momy >> 1) + FixedMul(ball->momz - FRACUNIT, + finesine[angle]); + tiny->momz = ball->momz; + P_CheckMissileSpawn(tiny); + + tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3); + angle = ball->angle - ANG90; + tiny->target = ball->target; + tiny->angle = angle; + angle >>= ANGLETOFINESHIFT; + tiny->momx = (ball->momx >> 1) + FixedMul(ball->momz - FRACUNIT, + finecosine[angle]); + tiny->momy = (ball->momy >> 1) + FixedMul(ball->momz - FRACUNIT, + finesine[angle]); + tiny->momz = ball->momz; + P_CheckMissileSpawn(tiny); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireMacePL2 +// +//---------------------------------------------------------------------------- + +void A_FireMacePL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + player->ammo[am_mace] -= deathmatch ? USE_MACE_AMMO_1 : USE_MACE_AMMO_2; + mo = P_SpawnPlayerMissile(player->mo, MT_MACEFX4); + if (mo) + { + mo->momx += player->mo->momx; + mo->momy += player->mo->momy; + mo->momz = 2 * FRACUNIT + ((player->lookdir) << (FRACBITS - 5)); + if (linetarget) + { + mo->special1.m = linetarget; + } + } + S_StartSound(player->mo, sfx_lobsht); +} + +//---------------------------------------------------------------------------- +// +// PROC A_DeathBallImpact +// +//---------------------------------------------------------------------------- + +void A_DeathBallImpact(mobj_t * ball, player_t *player, pspdef_t *psp) +{ + int i; + mobj_t *target; + angle_t angle; + boolean newAngle; + + if ((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID)) + { // Landed in some sort of liquid + P_RemoveMobj(ball); + return; + } + if ((ball->z <= ball->floorz) && ball->momz) + { // Bounce + newAngle = false; + target = (mobj_t *) ball->special1.m; + if (target) + { + if (!(target->flags & MF_SHOOTABLE)) + { // Target died + ball->special1.m = NULL; + } + else + { // Seek + angle = R_PointToAngle2(ball->x, ball->y, + target->x, target->y); + newAngle = true; + } + } + else + { // Find new target + angle = 0; + for (i = 0; i < 16; i++) + { + P_AimLineAttack(ball, angle, 10 * 64 * FRACUNIT); + if (linetarget && ball->target != linetarget) + { + ball->special1.m = linetarget; + angle = R_PointToAngle2(ball->x, ball->y, + linetarget->x, linetarget->y); + newAngle = true; + break; + } + angle += ANG45 / 2; + } + } + if (newAngle) + { + ball->angle = angle; + angle >>= ANGLETOFINESHIFT; + ball->momx = FixedMul(ball->info->speed, finecosine[angle]); + ball->momy = FixedMul(ball->info->speed, finesine[angle]); + } + P_SetMobjState(ball, ball->info->spawnstate); + S_StartSound(ball, sfx_pstop); + } + else + { // Explode + ball->flags |= MF_NOGRAVITY; + ball->flags2 &= ~MF2_LOGRAV; + S_StartSound(ball, sfx_phohit); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_SpawnRippers +// +//---------------------------------------------------------------------------- + +void A_SpawnRippers(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + unsigned int i; + angle_t angle; + mobj_t *ripper; + + for (i = 0; i < 8; i++) + { + ripper = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RIPPER); + angle = i * ANG45; + ripper->target = actor->target; + ripper->angle = angle; + angle >>= ANGLETOFINESHIFT; + ripper->momx = FixedMul(ripper->info->speed, finecosine[angle]); + ripper->momy = FixedMul(ripper->info->speed, finesine[angle]); + P_CheckMissileSpawn(ripper); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireCrossbowPL1 +// +//---------------------------------------------------------------------------- + +void A_FireCrossbowPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *pmo; + + pmo = player->mo; + player->ammo[am_crossbow] -= USE_CBOW_AMMO_1; + P_SpawnPlayerMissile(pmo, MT_CRBOWFX1); + P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle - (ANG45 / 10)); + P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle + (ANG45 / 10)); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireCrossbowPL2 +// +//---------------------------------------------------------------------------- + +void A_FireCrossbowPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *pmo; + + pmo = player->mo; + player->ammo[am_crossbow] -= + deathmatch ? USE_CBOW_AMMO_1 : USE_CBOW_AMMO_2; + P_SpawnPlayerMissile(pmo, MT_CRBOWFX2); + P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle - (ANG45 / 10)); + P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle + (ANG45 / 10)); + P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle - (ANG45 / 5)); + P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle + (ANG45 / 5)); +} + +//---------------------------------------------------------------------------- +// +// PROC A_BoltSpark +// +//---------------------------------------------------------------------------- + +void A_BoltSpark(mobj_t * bolt, player_t *player, pspdef_t *psp) +{ + mobj_t *spark; + + if (P_Random() > 50) + { + spark = P_SpawnMobj(bolt->x, bolt->y, bolt->z, MT_CRBOWFX4); + spark->x += P_SubRandom() << 10; + spark->y += P_SubRandom() << 10; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireSkullRodPL1 +// +//---------------------------------------------------------------------------- + +void A_FireSkullRodPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + if (player->ammo[am_skullrod] < USE_SKRD_AMMO_1) + { + return; + } + player->ammo[am_skullrod] -= USE_SKRD_AMMO_1; + mo = P_SpawnPlayerMissile(player->mo, MT_HORNRODFX1); + // Randomize the first frame + if (mo && P_Random() > 128) + { + P_SetMobjState(mo, S_HRODFX1_2); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireSkullRodPL2 +// +// The special2 field holds the player number that shot the rain missile. +// The special1 field is used for the seeking routines, then as a counter +// for the sound looping. +// +//---------------------------------------------------------------------------- + +void A_FireSkullRodPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->ammo[am_skullrod] -= + deathmatch ? USE_SKRD_AMMO_1 : USE_SKRD_AMMO_2; + P_SpawnPlayerMissile(player->mo, MT_HORNRODFX2); + // Use MissileMobj instead of the return value from + // P_SpawnPlayerMissile because we need to give info to the mobj + // even if it exploded immediately. + if (netgame) + { // Multi-player game + MissileMobj->special2.i = P_GetPlayerNum(player); + } + else + { // Always use red missiles in single player games + MissileMobj->special2.i = 2; + } + if (linetarget) + { + MissileMobj->special1.m = linetarget; + } + S_StartSound(MissileMobj, sfx_hrnpow); +} + +//---------------------------------------------------------------------------- +// +// PROC A_SkullRodPL2Seek +// +//---------------------------------------------------------------------------- + +void A_SkullRodPL2Seek(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SeekerMissile(actor, ANG1_X * 10, ANG1_X * 30); +} + +//---------------------------------------------------------------------------- +// +// PROC A_AddPlayerRain +// +//---------------------------------------------------------------------------- + +void A_AddPlayerRain(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + int playerNum; + player_t *player; + + playerNum = netgame ? actor->special2.i : 0; + if (!playeringame[playerNum]) + { // Player left the game + return; + } + player = &players[playerNum]; + if (player->health <= 0) + { // Player is dead + return; + } + if (player->rain1 && player->rain2) + { // Terminate an active rain + if (player->rain1->health < player->rain2->health) + { + if (player->rain1->health > 16) + { + player->rain1->health = 16; + } + player->rain1 = NULL; + } + else + { + if (player->rain2->health > 16) + { + player->rain2->health = 16; + } + player->rain2 = NULL; + } + } + // Add rain mobj to list + if (player->rain1) + { + player->rain2 = actor; + } + else + { + player->rain1 = actor; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_SkullRodStorm +// +//---------------------------------------------------------------------------- + +void A_SkullRodStorm(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + fixed_t x; + fixed_t y; + mobj_t *mo; + int playerNum; + player_t *player; + + if (actor->health-- == 0) + { + P_SetMobjState(actor, S_NULL); + playerNum = netgame ? actor->special2.i : 0; + if (!playeringame[playerNum]) + { // Player left the game + return; + } + player = &players[playerNum]; + if (player->health <= 0) + { // Player is dead + return; + } + if (player->rain1 == actor) + { + player->rain1 = NULL; + } + else if (player->rain2 == actor) + { + player->rain2 = NULL; + } + return; + } + if (P_Random() < 25) + { // Fudge rain frequency + return; + } + x = actor->x + ((P_Random() & 127) - 64) * FRACUNIT; + y = actor->y + ((P_Random() & 127) - 64) * FRACUNIT; + mo = P_SpawnMobj(x, y, ONCEILINGZ, MT_RAINPLR1 + actor->special2.i); + mo->target = actor->target; + mo->momx = 1; // Force collision detection + mo->momz = -mo->info->speed; + mo->special2.i = actor->special2.i; // Transfer player number + P_CheckMissileSpawn(mo); + if (!(actor->special1.i & 31)) + { + S_StartSound(actor, sfx_ramrain); + } + actor->special1.i++; +} + +//---------------------------------------------------------------------------- +// +// PROC A_RainImpact +// +//---------------------------------------------------------------------------- + +void A_RainImpact(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->z > actor->floorz) + { + P_SetMobjState(actor, S_RAINAIRXPLR1_1 + actor->special2.i); + } + else if (P_Random() < 40) + { + P_HitFloor(actor); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_HideInCeiling +// +//---------------------------------------------------------------------------- + +void A_HideInCeiling(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->z = actor->ceilingz + 4 * FRACUNIT; +} + +//---------------------------------------------------------------------------- +// +// PROC A_FirePhoenixPL1 +// +//---------------------------------------------------------------------------- + +void A_FirePhoenixPL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + + player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_1; + P_SpawnPlayerMissile(player->mo, MT_PHOENIXFX1); + //P_SpawnPlayerMissile(player->mo, MT_MNTRFX2); + angle = player->mo->angle + ANG180; + angle >>= ANGLETOFINESHIFT; + player->mo->momx += FixedMul(4 * FRACUNIT, finecosine[angle]); + player->mo->momy += FixedMul(4 * FRACUNIT, finesine[angle]); +} + +//---------------------------------------------------------------------------- +// +// PROC A_PhoenixPuff +// +//---------------------------------------------------------------------------- + +void A_PhoenixPuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *puff; + angle_t angle; + + P_SeekerMissile(actor, ANG1_X * 5, ANG1_X * 10); + puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF); + angle = actor->angle + ANG90; + angle >>= ANGLETOFINESHIFT; + puff->momx = FixedMul((fixed_t)(FRACUNIT * 1.3), finecosine[angle]); + puff->momy = FixedMul((fixed_t)(FRACUNIT * 1.3), finesine[angle]); + puff->momz = 0; + puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF); + angle = actor->angle - ANG90; + angle >>= ANGLETOFINESHIFT; + puff->momx = FixedMul((fixed_t)(FRACUNIT * 1.3), finecosine[angle]); + puff->momy = FixedMul((fixed_t)(FRACUNIT * 1.3), finesine[angle]); + puff->momz = 0; +} + +// +// This function was present in the Heretic 1.0 executable for the +// removed "secondary phoenix flash" object (MT_PHOENIXFX_REMOVED). +// The purpose of this object is unknown, as is this function. +// + +void A_RemovedPhoenixFunc(mobj_t *actor, player_t * player, pspdef_t * psp) +{ + I_Error("Action function invoked for removed Phoenix action!"); +} + +//---------------------------------------------------------------------------- +// +// PROC A_InitPhoenixPL2 +// +//---------------------------------------------------------------------------- + +void A_InitPhoenixPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->flamecount = FLAME_THROWER_TICS; +} + +//---------------------------------------------------------------------------- +// +// PROC A_FirePhoenixPL2 +// +// Flame thrower effect. +// +//---------------------------------------------------------------------------- + +void A_FirePhoenixPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + mobj_t *pmo; + angle_t angle; + fixed_t x, y, z; + fixed_t slope; + + if (--player->flamecount == 0) + { // Out of flame + P_SetPsprite(player, ps_weapon, S_PHOENIXATK2_4); + player->refire = 0; + return; + } + pmo = player->mo; + angle = pmo->angle; + x = pmo->x + (P_SubRandom() << 9); + y = pmo->y + (P_SubRandom() << 9); + z = pmo->z + 26 * FRACUNIT + ((player->lookdir) << FRACBITS) / 173; + if (pmo->flags2 & MF2_FEETARECLIPPED) + { + z -= FOOTCLIPSIZE; + } + slope = ((player->lookdir) << FRACBITS) / 173 + (FRACUNIT / 10); + mo = P_SpawnMobj(x, y, z, MT_PHOENIXFX2); + mo->target = pmo; + mo->angle = angle; + mo->momx = pmo->momx + FixedMul(mo->info->speed, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = pmo->momy + FixedMul(mo->info->speed, + finesine[angle >> ANGLETOFINESHIFT]); + mo->momz = FixedMul(mo->info->speed, slope); + if (!player->refire || !(leveltime % 38)) + { + S_StartSound(player->mo, sfx_phopow); + } + P_CheckMissileSpawn(mo); +} + +//---------------------------------------------------------------------------- +// +// PROC A_ShutdownPhoenixPL2 +// +//---------------------------------------------------------------------------- + +void A_ShutdownPhoenixPL2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2; +} + +//---------------------------------------------------------------------------- +// +// PROC A_FlameEnd +// +//---------------------------------------------------------------------------- + +void A_FlameEnd(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->momz += (fixed_t)(1.5 * FRACUNIT); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FloatPuff +// +//---------------------------------------------------------------------------- + +void A_FloatPuff(mobj_t * puff, player_t *player, pspdef_t *psp) +{ + puff->momz += (fixed_t)(1.8 * FRACUNIT); +} + +//--------------------------------------------------------------------------- +// +// PROC A_GauntletAttack +// +//--------------------------------------------------------------------------- + +void A_GauntletAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + int randVal; + fixed_t dist; + + psp->sx = ((P_Random() & 3) - 2) * FRACUNIT; + psp->sy = WEAPONTOP + (P_Random() & 3) * FRACUNIT; + angle = player->mo->angle; + if (player->powers[pw_weaponlevel2]) + { + damage = HITDICE(2); + dist = 4 * MELEERANGE; + angle += P_SubRandom() << 17; + PuffType = MT_GAUNTLETPUFF2; + } + else + { + damage = HITDICE(2); + dist = MELEERANGE + 1; + angle += P_SubRandom() << 18; + PuffType = MT_GAUNTLETPUFF1; + } + slope = P_AimLineAttack(player->mo, angle, dist); + P_LineAttack(player->mo, angle, dist, slope, damage); + if (!linetarget) + { + if (P_Random() > 64) + { + player->extralight = !player->extralight; + } + S_StartSound(player->mo, sfx_gntful); + return; + } + randVal = P_Random(); + if (randVal < 64) + { + player->extralight = 0; + } + else if (randVal < 160) + { + player->extralight = 1; + } + else + { + player->extralight = 2; + } + if (player->powers[pw_weaponlevel2]) + { + P_GiveBody(player, damage >> 1); + S_StartSound(player->mo, sfx_gntpow); + } + else + { + S_StartSound(player->mo, sfx_gnthit); + } + // turn to face target + angle = R_PointToAngle2(player->mo->x, player->mo->y, + linetarget->x, linetarget->y); + if (angle - player->mo->angle > ANG180) + { + if ((signed int) (angle - player->mo->angle) < -ANG90 / 20) + player->mo->angle = angle + ANG90 / 21; + else + player->mo->angle -= ANG90 / 20; + } + else + { + if (angle - player->mo->angle > ANG90 / 20) + player->mo->angle = angle - ANG90 / 21; + else + player->mo->angle += ANG90 / 20; + } + player->mo->flags |= MF_JUSTATTACKED; +} + +void A_Light0(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->extralight = 0; +} + +void A_Light1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->extralight = 1; +} + +void A_Light2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->extralight = 2; +} + +//------------------------------------------------------------------------ +// +// PROC P_SetupPsprites +// +// Called at start of level for each player +// +//------------------------------------------------------------------------ + +void P_SetupPsprites(player_t * player) +{ + int i; + + // Remove all psprites + for (i = 0; i < NUMPSPRITES; i++) + { + player->psprites[i].state = NULL; + } + // Spawn the ready weapon + player->pendingweapon = player->readyweapon; + P_BringUpWeapon(player); +} + +//------------------------------------------------------------------------ +// +// PROC P_MovePsprites +// +// Called every tic by player thinking routine +// +//------------------------------------------------------------------------ + +void P_MovePsprites(player_t * player) +{ + int i; + pspdef_t *psp; + + psp = &player->psprites[0]; + for (i = 0; i < NUMPSPRITES; i++, psp++) + { + if (psp->state != 0) // a null state means not active + { + // drop tic count and possibly change state + if (psp->tics != -1) // a -1 tic count never changes + { + psp->tics--; + if (!psp->tics) + { + P_SetPsprite(player, i, psp->state->nextstate); + } + } + } + } + player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; + player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; +} diff --git a/games/NXDoom/src/heretic/p_saveg.c b/games/NXDoom/src/heretic/p_saveg.c new file mode 100644 index 00000000000..c4a2f131df6 --- /dev/null +++ b/games/NXDoom/src/heretic/p_saveg.c @@ -0,0 +1,1925 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_tick.c + +#include + +#include "doomdef.h" +#include "i_swap.h" +#include "i_system.h" +#include "m_misc.h" +#include "p_local.h" +#include "v_video.h" + +static FILE *SaveGameFP; + +int vanilla_savegame_limit = 1; + + +//========================================================================== +// +// SV_Filename +// +// Generate the filename to use for a particular savegame slot. +// Returns a malloc()'d buffer that must be freed by the caller. +// +//========================================================================== + +char *SV_Filename(int slot) +{ + char *filename; + size_t filename_len; + + filename_len = strlen(savegamedir) + strlen(SAVEGAMENAME) + 8; + filename = malloc(filename_len); + M_snprintf(filename, filename_len, + "%s" SAVEGAMENAME "%d.hsg", savegamedir, slot); + + return filename; +} + +//========================================================================== +// +// SV_Open +// +//========================================================================== + +void SV_Open(char *fileName) +{ + SaveGameFP = M_fopen(fileName, "wb"); +} + +void SV_OpenRead(char *filename) +{ + SaveGameFP = M_fopen(filename, "rb"); + + if (SaveGameFP == NULL) + { + I_Error("Could not load savegame %s", filename); + } +} + +//========================================================================== +// +// SV_WriteSaveGameEOF +// +//========================================================================== + +void SV_WriteSaveGameEOF(void) +{ + SV_WriteByte(SAVE_GAME_TERMINATOR); + + // Enforce the same savegame size limit as in Vanilla Heretic + + if (vanilla_savegame_limit && ftell(SaveGameFP) > SAVEGAMESIZE) + { + I_Error("Savegame buffer overrun"); + } +} + +//========================================================================== +// +// SV_Close +// +//========================================================================== + +void SV_Close(void) +{ + if (SaveGameFP) + { + fclose(SaveGameFP); + SaveGameFP = NULL; + } +} + +//========================================================================== +// +// SV_Write +// +//========================================================================== + +void SV_Write(void *buffer, int size) +{ + fwrite(buffer, size, 1, SaveGameFP); +} + +void SV_WriteByte(byte val) +{ + SV_Write(&val, sizeof(byte)); +} + +void SV_WriteWord(unsigned short val) +{ + val = SHORT(val); + SV_Write(&val, sizeof(unsigned short)); +} + +void SV_WriteLong(unsigned int val) +{ + val = LONG(val); + SV_Write(&val, sizeof(int)); +} + +void SV_WritePtr(const void *ptr) +{ + long val = (long)(intptr_t) ptr; + + SV_WriteLong(val & 0xffffffff); +} + +//========================================================================== +// +// SV_Read +// +//========================================================================== + +void SV_Read(void *buffer, int size) +{ + int retval = fread(buffer, 1, size, SaveGameFP); + if (retval != size) + { + I_Error("Incomplete read in SV_Read: Expected %d, got %d bytes", + size, retval); + } +} + +byte SV_ReadByte(void) +{ + byte result; + SV_Read(&result, sizeof(byte)); + return result; +} + +uint16_t SV_ReadWord(void) +{ + uint16_t result; + SV_Read(&result, sizeof(unsigned short)); + return SHORT(result); +} + +uint32_t SV_ReadLong(void) +{ + uint32_t result; + SV_Read(&result, sizeof(int)); + return LONG(result); +} + +// +// ticcmd_t +// + +static void saveg_read_ticcmd_t(ticcmd_t *str) +{ + // char forwardmove; + str->forwardmove = SV_ReadByte(); + + // char sidemove; + str->sidemove = SV_ReadByte(); + + // short angleturn; + str->angleturn = SV_ReadWord(); + + // short consistancy; + str->consistancy = SV_ReadWord(); + + // byte chatchar; + str->chatchar = SV_ReadByte(); + + // byte buttons; + str->buttons = SV_ReadByte(); + + // byte lookfly; + str->lookfly = SV_ReadByte(); + + // byte arti; + str->arti = SV_ReadByte(); +} + +static void saveg_write_ticcmd_t(ticcmd_t *str) +{ + // char forwardmove; + SV_WriteByte(str->forwardmove); + + // char sidemove; + SV_WriteByte(str->sidemove); + + // short angleturn; + SV_WriteWord(str->angleturn); + + // short consistancy; + SV_WriteWord(str->consistancy); + + // byte chatchar; + SV_WriteByte(str->chatchar); + + // byte buttons; + SV_WriteByte(str->buttons); + + // byte lookfly; + SV_WriteByte(str->lookfly); + + // byte arti; + SV_WriteByte(str->arti); +} + +// +// inventory_t +// + +static void saveg_read_inventory_t(inventory_t *str) +{ + // int type; + str->type = SV_ReadLong(); + + // int count; + str->count = SV_ReadLong(); +} + +static void saveg_write_inventory_t(inventory_t *str) +{ + // int type; + SV_WriteLong(str->type); + + // int count; + SV_WriteLong(str->count); +} + + +// +// state_t * +// + +static void saveg_read_state_ptr(state_t **state) +{ + int statenum; + + statenum = SV_ReadLong(); + + // We have read a state number, but it is indexed according to the state + // table in Vanilla Heretic v1.3. To support v1.0 HHE patches we have + // three extra states, so map the state number to our internal state + // number. + + if (statenum >= S_PHOENIXFXIX_1) + { + statenum = (statenum - S_PHOENIXFXIX_1) + S_PHOENIXPUFF1; + } + + if (statenum == 0) + { + *state = NULL; + } + else + { + *state = &states[statenum]; + } +} + +static void saveg_write_state_ptr(state_t *state) +{ + int statenum; + + // NULL states are just written as zero. + + if (state == NULL) + { + SV_WriteLong(0); + return; + } + + statenum = state - states; + + // Our internal state table has three extra states than Vanilla, so map + // to the state numbers used by Vanilla Heretic v1.3 for savegame + // compatibility. + + if (statenum >= S_PHOENIXPUFF1) + { + statenum = (statenum - S_PHOENIXPUFF1) + S_PHOENIXFXIX_1; + } + else if (statenum >= S_PHOENIXFXIX_1) + { + // Now we're really in trouble. This state doesn't exist in Vanilla + // Heretic v1.3 (but does in v1.0). Map to a frame that might be + // vaguely sensible. + + statenum = S_PHOENIXFXI1_8; + } + + SV_WriteLong(statenum); +} + + +// +// pspdef_t +// + +static void saveg_read_pspdef_t(pspdef_t *str) +{ + // state_t *state; + saveg_read_state_ptr(&str->state); + + // int tics; + str->tics = SV_ReadLong(); + + // fixed_t sx, sy; + str->sx = SV_ReadLong(); + str->sy = SV_ReadLong(); +} + +static void saveg_write_pspdef_t(pspdef_t *str) +{ + // state_t *state; + saveg_write_state_ptr(str->state); + + // int tics; + SV_WriteLong(str->tics); + + // fixed_t sx, sy; + SV_WriteLong(str->sx); + SV_WriteLong(str->sy); +} + + +// +// player_t +// + +static void saveg_read_player_t(player_t *str) +{ + int i; + + // mobj_t *mo; + SV_ReadLong(); + str->mo = NULL; + + // playerstate_t playerstate; + str->playerstate = SV_ReadLong(); + + // ticcmd_t cmd; + saveg_read_ticcmd_t(&str->cmd); + + // fixed_t viewz; + str->viewz = SV_ReadLong(); + + // fixed_t viewheight; + str->viewheight = SV_ReadLong(); + + // fixed_t deltaviewheight; + str->deltaviewheight = SV_ReadLong(); + + // fixed_t bob; + str->bob = SV_ReadLong(); + + // int flyheight; + str->flyheight = SV_ReadLong(); + + // int lookdir; + str->lookdir = SV_ReadLong(); + + // boolean centering; + str->centering = SV_ReadLong(); + + // int health; + str->health = SV_ReadLong(); + + // int armorpoints, armortype; + str->armorpoints = SV_ReadLong(); + str->armortype = SV_ReadLong(); + + // inventory_t inventory[NUMINVENTORYSLOTS]; + for (i=0; iinventory[i]); + } + + // artitype_t readyArtifact; + str->readyArtifact = SV_ReadLong(); + + // int artifactCount; + str->artifactCount = SV_ReadLong(); + + // int inventorySlotNum; + str->inventorySlotNum = SV_ReadLong(); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i] = SV_ReadLong(); + } + + // boolean keys[NUM_KEY_TYPES]; + for (i = 0; i < NUM_KEY_TYPES; ++i) + { + str->keys[i] = SV_ReadLong(); + } + + // boolean backpack; + str->backpack = SV_ReadLong(); + + // signed int frags[MAXPLAYERS]; + for (i=0; ifrags[i] = SV_ReadLong(); + } + + // weapontype_t readyweapon; + str->readyweapon = SV_ReadLong(); + + // weapontype_t pendingweapon; + str->pendingweapon = SV_ReadLong(); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i] = SV_ReadLong(); + } + + // int ammo[NUMAMMO]; + for (i=0; iammo[i] = SV_ReadLong(); + } + + // int maxammo[NUMAMMO]; + for (i=0; imaxammo[i] = SV_ReadLong(); + } + + // int attackdown, usedown; + str->attackdown = SV_ReadLong(); + str->usedown = SV_ReadLong(); + + // int cheats; + str->cheats = SV_ReadLong(); + + // int refire; + str->refire = SV_ReadLong(); + + // int killcount, itemcount, secretcount; + str->killcount = SV_ReadLong(); + str->itemcount = SV_ReadLong(); + str->secretcount = SV_ReadLong(); + + // char *message; + SV_ReadLong(); + str->message = NULL; + + // int messageTics; + str->messageTics = SV_ReadLong(); + + // int damagecount, bonuscount; + str->damagecount = SV_ReadLong(); + str->bonuscount = SV_ReadLong(); + + // int flamecount; + str->flamecount = SV_ReadLong(); + + // mobj_t *attacker; + SV_ReadLong(); + str->attacker = NULL; + + // int extralight; + str->extralight = SV_ReadLong(); + + // int fixedcolormap; + str->fixedcolormap = SV_ReadLong(); + + // int colormap; + str->colormap = SV_ReadLong(); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // boolean didsecret; + str->didsecret = SV_ReadLong(); + + // int chickenTics; + str->chickenTics = SV_ReadLong(); + + // int chickenPeck; + str->chickenPeck = SV_ReadLong(); + + // mobj_t *rain1; + SV_ReadLong(); + str->rain1 = NULL; + + // mobj_t *rain2; + SV_ReadLong(); + str->rain2 = NULL; +} + +static void saveg_write_player_t(player_t *str) +{ + int i; + + // mobj_t *mo; + // pointer will be trashed, but it gets restored on load as + // the player number reference is stored in the mo. + SV_WritePtr(str->mo); + + // playerstate_t playerstate; + SV_WriteLong(str->playerstate); + + // ticcmd_t cmd; + saveg_write_ticcmd_t(&str->cmd); + + // fixed_t viewz; + SV_WriteLong(str->viewz); + + // fixed_t viewheight; + SV_WriteLong(str->viewheight); + + // fixed_t deltaviewheight; + SV_WriteLong(str->deltaviewheight); + + // fixed_t bob; + SV_WriteLong(str->bob); + + // int flyheight; + SV_WriteLong(str->flyheight); + + // int lookdir; + SV_WriteLong(str->lookdir); + + // boolean centering; + SV_WriteLong(str->centering); + + // int health; + SV_WriteLong(str->health); + + // int armorpoints, armortype; + SV_WriteLong(str->armorpoints); + SV_WriteLong(str->armortype); + + // inventory_t inventory[NUMINVENTORYSLOTS]; + for (i=0; iinventory[i]); + } + + // artitype_t readyArtifact; + SV_WriteLong(str->readyArtifact); + + // int artifactCount; + SV_WriteLong(str->artifactCount); + + // int inventorySlotNum; + SV_WriteLong(str->inventorySlotNum); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i]); + } + + // boolean keys[NUMKEYS]; + for (i = 0; i < NUM_KEY_TYPES; ++i) + { + SV_WriteLong(str->keys[i]); + } + + // boolean backpack; + SV_WriteLong(str->backpack); + + // signed int frags[MAXPLAYERS]; + for (i=0; ifrags[i]); + } + + // weapontype_t readyweapon; + SV_WriteLong(str->readyweapon); + + // weapontype_t pendingweapon; + SV_WriteLong(str->pendingweapon); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i]); + } + + // int ammo[NUMAMMO]; + for (i=0; iammo[i]); + } + + // int maxammo[NUMAMMO]; + for (i=0; imaxammo[i]); + } + + // int attackdown, usedown; + SV_WriteLong(str->attackdown); + SV_WriteLong(str->usedown); + + // int cheats; + SV_WriteLong(str->cheats); + + // int refire; + SV_WriteLong(str->refire); + + // int killcount, itemcount, secretcount; + SV_WriteLong(str->killcount); + SV_WriteLong(str->itemcount); + SV_WriteLong(str->secretcount); + + // char *message; + SV_WritePtr(str->message); + + // int messageTics; + SV_WriteLong(str->messageTics); + + // int damagecount, bonuscount; + SV_WriteLong(str->damagecount); + SV_WriteLong(str->bonuscount); + + // int flamecount; + SV_WriteLong(str->flamecount); + + // mobj_t *attacker; + SV_WritePtr(str->attacker); + + // int extralight; + SV_WriteLong(str->extralight); + + // int fixedcolormap; + SV_WriteLong(str->fixedcolormap); + + // int colormap; + SV_WriteLong(str->colormap); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // boolean didsecret; + SV_WriteLong(str->didsecret); + + // int chickenTics; + SV_WriteLong(str->chickenTics); + + // int chickenPeck; + SV_WriteLong(str->chickenPeck); + + // mobj_t *rain1; + SV_WritePtr(str->rain1); + + // mobj_t *rain2; + SV_WritePtr(str->rain2); +} + + +// +// mapthing_t +// + +static void saveg_read_mapthing_t(mapthing_t *str) +{ + // short x, y; + str->x = SV_ReadWord(); + str->y = SV_ReadWord(); + + // short angle; + str->angle = SV_ReadWord(); + + // short type; + str->type = SV_ReadWord(); + + // short options; + str->options = SV_ReadWord(); +} + +static void saveg_write_mapthing_t(mapthing_t *str) +{ + // short x, y; + SV_WriteWord(str->x); + SV_WriteWord(str->y); + + // short angle; + SV_WriteWord(str->angle); + + // short type; + SV_WriteWord(str->type); + + // short options; + SV_WriteWord(str->options); +} + + +// +// thinker_t +// + +static void saveg_read_thinker_t(thinker_t *str) +{ + // struct thinker_s *prev, *next; + SV_ReadLong(); + str->prev = NULL; + SV_ReadLong(); + str->next = NULL; + + // think_t function; + SV_ReadLong(); + str->function = NULL; +} + +static void saveg_write_thinker_t(thinker_t *str) +{ + // struct thinker_s *prev, *next; + SV_WritePtr(str->prev); + SV_WritePtr(str->next); + + // think_t function; + SV_WritePtr(str->function); +} + + +// +// specialval_t +// + +static void saveg_read_specialval_t(specialval_t *str) +{ + // This can also be a mobj_t ptr, but we just assume it's + // an int. This is probably a really bad assumption that's + // likely to end in tears. + + // int i; + str->i = SV_ReadLong(); +} + +static void saveg_write_specialval_t(specialval_t *str) +{ + // int i; + SV_WriteLong(str->i); +} + + +// +// mobj_t +// + +static void saveg_read_mobj_t(mobj_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // fixed_t x, y, z; + str->x = SV_ReadLong(); + str->y = SV_ReadLong(); + str->z = SV_ReadLong(); + + // struct mobj_s *snext, *sprev; + SV_ReadLong(); + str->snext = NULL; + SV_ReadLong(); + str->sprev = NULL; + + // angle_t angle; + str->angle = SV_ReadLong(); + + // spritenum_t sprite; + str->sprite = SV_ReadLong(); + + // int frame; + str->frame = SV_ReadLong(); + + // struct mobj_s *bnext, *bprev; + SV_ReadLong(); + str->bnext = NULL; + SV_ReadLong(); + str->bprev = NULL; + + // struct subsector_s *subsector; + SV_ReadLong(); + str->subsector = NULL; + + // fixed_t floorz, ceilingz; + str->floorz = SV_ReadLong(); + str->ceilingz = SV_ReadLong(); + + // fixed_t radius, height; + str->radius = SV_ReadLong(); + str->height = SV_ReadLong(); + + // fixed_t momx, momy, momz; + str->momx = SV_ReadLong(); + str->momy = SV_ReadLong(); + str->momz = SV_ReadLong(); + + // int validcount; + str->validcount = SV_ReadLong(); + + // mobjtype_t type; + str->type = SV_ReadLong(); + + // An extra thing type was added for v1.0 HHE compatibility. + // Map from the v1.3 thing type index to the internal one. + if (str->type >= MT_PHOENIXFX_REMOVED) + { + ++str->type; + } + + // mobjinfo_t *info; + SV_ReadLong(); + str->info = NULL; + + // int tics; + str->tics = SV_ReadLong(); + + // state_t *state; + saveg_read_state_ptr(&str->state); + + // int damage; + str->damage = SV_ReadLong(); + + // int flags; + str->flags = SV_ReadLong(); + + // int flags2; + str->flags2 = SV_ReadLong(); + + // specialval_t special1; + saveg_read_specialval_t(&str->special1); + + // specialval_t special2; + saveg_read_specialval_t(&str->special2); + + // Now we have a bunch of hacks to try to NULL out special values + // where special[12] contained a mobj_t pointer that isn't valid + // any more. This isn't in Vanilla but at least it stops the game + // from crashing. + + switch (str->type) + { + // Gas pods use special2.m to point to the pod generator + // that made it. + case MT_POD: + str->special2.m = NULL; + break; + + // Several thing types use special1.m to mean 'target': + case MT_MACEFX4: // A_DeathBallImpact + case MT_WHIRLWIND: // A_WhirlwindSeek + case MT_MUMMYFX1: // A_MummyFX1Seek + case MT_HORNRODFX2: // A_SkullRodPL2Seek + case MT_PHOENIXFX1: // A_PhoenixPuff + str->special1.m = NULL; + break; + + default: + break; + } + + // int health; + str->health = SV_ReadLong(); + + // int movedir; + str->movedir = SV_ReadLong(); + + // int movecount; + str->movecount = SV_ReadLong(); + + // struct mobj_s *target; + SV_ReadLong(); + str->target = NULL; + + // int reactiontime; + str->reactiontime = SV_ReadLong(); + + // int threshold; + str->threshold = SV_ReadLong(); + + // struct player_s *player; + i = SV_ReadLong(); + if (i != 0) + { + str->player = &players[i - 1]; + str->player->mo = str; + } + else + { + str->player = NULL; + } + + // int lastlook; + str->lastlook = SV_ReadLong(); + + // mapthing_t spawnpoint; + saveg_read_mapthing_t(&str->spawnpoint); +} + +static void saveg_write_mobj_t(mobj_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // fixed_t x, y, z; + SV_WriteLong(str->x); + SV_WriteLong(str->y); + SV_WriteLong(str->z); + + // struct mobj_s *snext, *sprev; + SV_WritePtr(str->snext); + SV_WritePtr(str->sprev); + + // angle_t angle; + SV_WriteLong(str->angle); + + // spritenum_t sprite; + SV_WriteLong(str->sprite); + + // int frame; + SV_WriteLong(str->frame); + + // struct mobj_s *bnext, *bprev; + SV_WritePtr(str->bnext); + SV_WritePtr(str->bprev); + + // struct subsector_s *subsector; + SV_WritePtr(str->subsector); + + // fixed_t floorz, ceilingz; + SV_WriteLong(str->floorz); + SV_WriteLong(str->ceilingz); + + // fixed_t radius, height; + SV_WriteLong(str->radius); + SV_WriteLong(str->height); + + // fixed_t momx, momy, momz; + SV_WriteLong(str->momx); + SV_WriteLong(str->momy); + SV_WriteLong(str->momz); + + // int validcount; + SV_WriteLong(str->validcount); + + // mobjtype_t type; + // Our mobjinfo table has an extra entry, for compatibility with v1.0 + // HHE patches. So translate the internal thing type index to the + // equivalent for Vanilla Heretic v1.3, for savegame compatibility. + + if (str->type > MT_PHOENIXFX_REMOVED) + { + SV_WriteLong(str->type - 1); + } + else if (str->type == MT_PHOENIXFX_REMOVED) + { + // This should never happen, but just in case, do something + // vaguely sensible ... ? + SV_WriteLong(MT_PHOENIXFX1); + } + else + { + SV_WriteLong(str->type); + } + + // mobjinfo_t *info; + SV_WritePtr(str->info); + + // int tics; + SV_WriteLong(str->tics); + + // state_t *state; + saveg_write_state_ptr(str->state); + + // int damage; + SV_WriteLong(str->damage); + + // int flags; + SV_WriteLong(str->flags); + + // int flags2; + SV_WriteLong(str->flags2); + + // specialval_t special1; + saveg_write_specialval_t(&str->special1); + + // specialval_t special2; + saveg_write_specialval_t(&str->special2); + + // int health; + SV_WriteLong(str->health); + + // int movedir; + SV_WriteLong(str->movedir); + + // int movecount; + SV_WriteLong(str->movecount); + + // struct mobj_s *target; + SV_WritePtr(str->target); + + // int reactiontime; + SV_WriteLong(str->reactiontime); + + // int threshold; + SV_WriteLong(str->threshold); + + // struct player_s *player; + if (str->player != NULL) + { + SV_WriteLong(str->player - players + 1); + } + else + { + SV_WriteLong(0); + } + + // int lastlook; + SV_WriteLong(str->lastlook); + + // mapthing_t spawnpoint; + saveg_write_mapthing_t(&str->spawnpoint); +} + + +// +// ceiling_t +// + +static void saveg_read_ceiling_t(ceiling_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // ceiling_e type; + str->type = SV_ReadLong(); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // fixed_t bottomheight, topheight; + str->bottomheight = SV_ReadLong(); + str->topheight = SV_ReadLong(); + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // boolean crush; + str->crush = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // int tag; + str->tag = SV_ReadLong(); + + // int olddirection; + str->olddirection = SV_ReadLong(); +} + +static void saveg_write_ceiling_t(ceiling_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // ceiling_e type; + SV_WriteLong(str->type); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // fixed_t bottomheight, topheight; + SV_WriteLong(str->bottomheight); + SV_WriteLong(str->topheight); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // boolean crush; + SV_WriteLong(str->crush); + + // int direction; + SV_WriteLong(str->direction); + + // int tag; + SV_WriteLong(str->tag); + + // int olddirection; + SV_WriteLong(str->olddirection); +} + + +// +// vldoor_t +// + +static void saveg_read_vldoor_t(vldoor_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // vldoor_e type; + str->type = SV_ReadLong(); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // fixed_t topheight; + str->topheight = SV_ReadLong(); + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // int topwait; + str->topwait = SV_ReadLong(); + + // int topcountdown; + str->topcountdown = SV_ReadLong(); +} + +static void saveg_write_vldoor_t(vldoor_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // vldoor_e type; + SV_WriteLong(str->type); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // fixed_t topheight; + SV_WriteLong(str->topheight); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // int direction; + SV_WriteLong(str->direction); + + // int topwait; + SV_WriteLong(str->topwait); + + // int topcountdown; + SV_WriteLong(str->topcountdown); +} + + +// +// floormove_t +// + +static void saveg_read_floormove_t(floormove_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // floor_e type; + str->type = SV_ReadLong(); + + // boolean crush; + str->crush = SV_ReadLong(); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // int direction; + str->direction = SV_ReadLong(); + + // int newspecial; + str->newspecial = SV_ReadLong(); + + // short texture; + str->texture = SV_ReadWord(); + + // fixed_t floordestheight; + str->floordestheight = SV_ReadLong(); + + // fixed_t speed; + str->speed = SV_ReadLong(); +} + +static void saveg_write_floormove_t(floormove_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // floor_e type; + SV_WriteLong(str->type); + + // boolean crush; + SV_WriteLong(str->crush); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // int direction; + SV_WriteLong(str->direction); + + // int newspecial; + SV_WriteLong(str->newspecial); + + // short texture; + SV_WriteWord(str->texture); + + // fixed_t floordestheight; + SV_WriteLong(str->floordestheight); + + // fixed_t speed; + SV_WriteLong(str->speed); +} + + +// +// plat_t +// + +static void saveg_read_plat_t(plat_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // fixed_t low; + str->low = SV_ReadLong(); + + // fixed_t high; + str->high = SV_ReadLong(); + + // int wait; + str->wait = SV_ReadLong(); + + // int count; + str->count = SV_ReadLong(); + + // plat_e status; + str->status = SV_ReadLong(); + + // plat_e oldstatus; + str->oldstatus = SV_ReadLong(); + + // boolean crush; + str->crush = SV_ReadLong(); + + // int tag; + str->tag = SV_ReadLong(); + + // plattype_e type; + str->type = SV_ReadLong(); +} + +static void saveg_write_plat_t(plat_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // fixed_t low; + SV_WriteLong(str->low); + + // fixed_t high; + SV_WriteLong(str->high); + + // int wait; + SV_WriteLong(str->wait); + + // int count; + SV_WriteLong(str->count); + + // plat_e status; + SV_WriteLong(str->status); + + // plat_e oldstatus; + SV_WriteLong(str->oldstatus); + + // boolean crush; + SV_WriteLong(str->crush); + + // int tag; + SV_WriteLong(str->tag); + + // plattype_e type; + SV_WriteLong(str->type); +} + + +// +// lightflash_t +// + +static void saveg_read_lightflash_t(lightflash_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // int count; + str->count = SV_ReadLong(); + + // int maxlight; + str->maxlight = SV_ReadLong(); + + // int minlight; + str->minlight = SV_ReadLong(); + + // int maxtime; + str->maxtime = SV_ReadLong(); + + // int mintime; + str->mintime = SV_ReadLong(); +} + +static void saveg_write_lightflash_t(lightflash_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // int count; + SV_WriteLong(str->count); + + // int maxlight; + SV_WriteLong(str->maxlight); + + // int minlight; + SV_WriteLong(str->minlight); + + // int maxtime; + SV_WriteLong(str->maxtime); + + // int mintime; + SV_WriteLong(str->mintime); +} + + +// +// strobe_t +// + +static void saveg_read_strobe_t(strobe_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // int count; + str->count = SV_ReadLong(); + + // int minlight; + str->minlight = SV_ReadLong(); + + // int maxlight; + str->maxlight = SV_ReadLong(); + + // int darktime; + str->darktime = SV_ReadLong(); + + // int brighttime; + str->brighttime = SV_ReadLong(); +} + +static void saveg_write_strobe_t(strobe_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // int count; + SV_WriteLong(str->count); + + // int minlight; + SV_WriteLong(str->minlight); + + // int maxlight; + SV_WriteLong(str->maxlight); + + // int darktime; + SV_WriteLong(str->darktime); + + // int brighttime; + SV_WriteLong(str->brighttime); +} + + +// +// glow_t +// + +static void saveg_read_glow_t(glow_t *str) +{ + int i; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // int minlight; + str->minlight = SV_ReadLong(); + + // int maxlight; + str->maxlight = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); +} + +static void saveg_write_glow_t(glow_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // int minlight; + SV_WriteLong(str->minlight); + + // int maxlight; + SV_WriteLong(str->maxlight); + + // int direction; + SV_WriteLong(str->direction); +} + + +/* +==================== += += P_ArchivePlayers += +==================== +*/ + +void P_ArchivePlayers(void) +{ + int i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + continue; + } + saveg_write_player_t(&players[i]); + } +} + +/* +==================== += += P_UnArchivePlayers += +==================== +*/ + +void P_UnArchivePlayers(void) +{ + int i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + saveg_read_player_t(&players[i]); + players[i].mo = NULL; // will be set when unarc thinker + players[i].message = NULL; + players[i].attacker = NULL; + } +} + +//============================================================================= + + +/* +==================== += += P_ArchiveWorld += +==================== +*/ + +void P_ArchiveWorld(void) +{ + int i, j; + sector_t *sec; + line_t *li; + side_t *si; + + // Sectors + for (i = 0, sec = sectors; i < numsectors; i++, sec++) + { + SV_WriteWord(sec->floorheight >> FRACBITS); + SV_WriteWord(sec->ceilingheight >> FRACBITS); + SV_WriteWord(sec->floorpic); + SV_WriteWord(sec->ceilingpic); + SV_WriteWord(sec->lightlevel); + SV_WriteWord(sec->special); // needed? + SV_WriteWord(sec->tag); // needed? + } + + // Lines + for (i = 0, li = lines; i < numlines; i++, li++) + { + SV_WriteWord(li->flags); + SV_WriteWord(li->special); + SV_WriteWord(li->tag); + for (j = 0; j < 2; j++) + { + if (li->sidenum[j] == -1) + { + continue; + } + si = &sides[li->sidenum[j]]; + SV_WriteWord(si->textureoffset >> FRACBITS); + SV_WriteWord(si->rowoffset >> FRACBITS); + SV_WriteWord(si->toptexture); + SV_WriteWord(si->bottomtexture); + SV_WriteWord(si->midtexture); + } + } +} + +/* +==================== += += P_UnArchiveWorld += +==================== +*/ + +void P_UnArchiveWorld(void) +{ + int i, j; + sector_t *sec; + line_t *li; + side_t *si; + +// +// do sectors +// + for (i = 0, sec = sectors; i < numsectors; i++, sec++) + { + sec->floorheight = SV_ReadWord() << FRACBITS; + sec->ceilingheight = SV_ReadWord() << FRACBITS; + sec->floorpic = SV_ReadWord(); + sec->ceilingpic = SV_ReadWord(); + sec->lightlevel = SV_ReadWord(); + sec->special = SV_ReadWord(); // needed? + sec->tag = SV_ReadWord(); // needed? + sec->specialdata = 0; + sec->soundtarget = 0; + } + +// +// do lines +// + for (i = 0, li = lines; i < numlines; i++, li++) + { + li->flags = SV_ReadWord(); + li->special = SV_ReadWord(); + li->tag = SV_ReadWord(); + for (j = 0; j < 2; j++) + { + if (li->sidenum[j] == -1) + continue; + si = &sides[li->sidenum[j]]; + si->textureoffset = SV_ReadWord() << FRACBITS; + si->rowoffset = SV_ReadWord() << FRACBITS; + si->toptexture = SV_ReadWord(); + si->bottomtexture = SV_ReadWord(); + si->midtexture = SV_ReadWord(); + } + } +} + +//============================================================================= + +typedef enum +{ + tc_end, + tc_mobj +} thinkerclass_t; + +/* +==================== += += P_ArchiveThinkers += +==================== +*/ + +void P_ArchiveThinkers(void) +{ + thinker_t *th; + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function == P_MobjThinker) + { + SV_WriteByte(tc_mobj); + saveg_write_mobj_t((mobj_t *) th); + } + //I_Error("P_ArchiveThinkers: Unknown thinker function"); + } + + // Add a terminating marker + SV_WriteByte(tc_end); +} + +/* +==================== += += P_UnArchiveThinkers += +==================== +*/ + +void P_UnArchiveThinkers(void) +{ + byte tclass; + thinker_t *currentthinker, *next; + mobj_t *mobj; + + // + // remove all the current thinkers + // + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + next = currentthinker->next; + if (currentthinker->function == P_MobjThinker) + P_RemoveMobj((mobj_t *) currentthinker); + else + Z_Free(currentthinker); + currentthinker = next; + } + P_InitThinkers(); + + // read in saved thinkers + while (1) + { + tclass = SV_ReadByte(); + switch (tclass) + { + case tc_end: + return; // end of list + + case tc_mobj: + mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); + saveg_read_mobj_t(mobj); + mobj->target = NULL; + P_SetThingPosition(mobj); + mobj->info = &mobjinfo[mobj->type]; + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + mobj->thinker.function = P_MobjThinker; + P_AddThinker(&mobj->thinker); + break; + + default: + I_Error("Unknown tclass %i in savegame", tclass); + } + + } + +} + +//============================================================================= + + +/* +==================== += += P_ArchiveSpecials += +==================== +*/ +enum +{ + tc_ceiling, + tc_door, + tc_floor, + tc_plat, + tc_flash, + tc_strobe, + tc_glow, + tc_endspecials +} specials_e; + +void P_ArchiveSpecials(void) +{ + /* + T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list + T_VerticalDoor, (vldoor_t: sector_t * swizzle), + T_MoveFloor, (floormove_t: sector_t * swizzle), + T_LightFlash, (lightflash_t: sector_t * swizzle), + T_StrobeFlash, (strobe_t: sector_t *), + T_Glow, (glow_t: sector_t *), + T_PlatRaise, (plat_t: sector_t *), - active list + */ + + thinker_t *th; + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function == T_MoveCeiling) + { + SV_WriteByte(tc_ceiling); + saveg_write_ceiling_t((ceiling_t *) th); + } + else if (th->function == T_VerticalDoor) + { + SV_WriteByte(tc_door); + saveg_write_vldoor_t((vldoor_t *) th); + } + else if (th->function == T_MoveFloor) + { + SV_WriteByte(tc_floor); + saveg_write_floormove_t((floormove_t *) th); + } + else if (th->function == T_PlatRaise) + { + SV_WriteByte(tc_plat); + saveg_write_plat_t((plat_t *) th); + } + else if (th->function == T_LightFlash) + { + SV_WriteByte(tc_flash); + saveg_write_lightflash_t((lightflash_t *) th); + } + else if (th->function == T_StrobeFlash) + { + SV_WriteByte(tc_strobe); + saveg_write_strobe_t((strobe_t *) th); + } + else if (th->function == T_Glow) + { + SV_WriteByte(tc_glow); + saveg_write_glow_t((glow_t *) th); + } + } + // Add a terminating marker + SV_WriteByte(tc_endspecials); +} + +/* +==================== += += P_UnArchiveSpecials += +==================== +*/ + +void P_UnArchiveSpecials(void) +{ + byte tclass; + ceiling_t *ceiling; + vldoor_t *door; + floormove_t *floor; + plat_t *plat; + lightflash_t *flash; + strobe_t *strobe; + glow_t *glow; + + + // read in saved thinkers + while (1) + { + tclass = SV_ReadByte(); + switch (tclass) + { + case tc_endspecials: + return; // end of list + + case tc_ceiling: + ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVEL, NULL); + saveg_read_ceiling_t(ceiling); + ceiling->sector->specialdata = T_MoveCeiling; // ??? + ceiling->thinker.function = T_MoveCeiling; + P_AddThinker(&ceiling->thinker); + P_AddActiveCeiling(ceiling); + break; + + case tc_door: + door = Z_Malloc(sizeof(*door), PU_LEVEL, NULL); + saveg_read_vldoor_t(door); + door->sector->specialdata = door; + door->thinker.function = T_VerticalDoor; + P_AddThinker(&door->thinker); + break; + + case tc_floor: + floor = Z_Malloc(sizeof(*floor), PU_LEVEL, NULL); + saveg_read_floormove_t(floor); + floor->sector->specialdata = T_MoveFloor; + floor->thinker.function = T_MoveFloor; + P_AddThinker(&floor->thinker); + break; + + case tc_plat: + plat = Z_Malloc(sizeof(*plat), PU_LEVEL, NULL); + saveg_read_plat_t(plat); + plat->sector->specialdata = T_PlatRaise; + // In the original Heretic code this was a conditional "fix" + // of the thinker function, but the save code (above) decides + // whether to save a T_PlatRaise based on thinker function + // anyway, so it can't be NULL. Having the conditional causes + // a bug, as our saveg_read_thinker_t sets these to NULL. + // if (plat->thinker.function) + plat->thinker.function = T_PlatRaise; + P_AddThinker(&plat->thinker); + P_AddActivePlat(plat); + break; + + case tc_flash: + flash = Z_Malloc(sizeof(*flash), PU_LEVEL, NULL); + saveg_read_lightflash_t(flash); + flash->thinker.function = T_LightFlash; + P_AddThinker(&flash->thinker); + break; + + case tc_strobe: + strobe = Z_Malloc(sizeof(*strobe), PU_LEVEL, NULL); + saveg_read_strobe_t(strobe); + strobe->thinker.function = T_StrobeFlash; + P_AddThinker(&strobe->thinker); + break; + + case tc_glow: + glow = Z_Malloc(sizeof(*glow), PU_LEVEL, NULL); + saveg_read_glow_t(glow); + glow->thinker.function = T_Glow; + P_AddThinker(&glow->thinker); + break; + + default: + I_Error("P_UnarchiveSpecials:Unknown tclass %i " + "in savegame", tclass); + } + + } + +} + + diff --git a/games/NXDoom/src/heretic/p_setup.c b/games/NXDoom/src/heretic/p_setup.c new file mode 100644 index 00000000000..645175552ec --- /dev/null +++ b/games/NXDoom/src/heretic/p_setup.c @@ -0,0 +1,709 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_main.c + +#include +#include + +#include "doomdef.h" +#include "i_swap.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_bbox.h" +#include "p_local.h" +#include "p_rejectpad.h" +#include "s_sound.h" + +void P_SpawnMapThing(mapthing_t * mthing); + +int numvertexes; +vertex_t *vertexes; + +int numsegs; +seg_t *segs; + +int numsectors; +sector_t *sectors; + +int numsubsectors; +subsector_t *subsectors; + +int numnodes; +node_t *nodes; + +int numlines; +line_t *lines; + +int numsides; +side_t *sides; + +static int totallines; + +short *blockmaplump; // offsets in blockmap are from here +short *blockmap; +int bmapwidth, bmapheight; // in mapblocks +fixed_t bmaporgx, bmaporgy; // origin of block map +mobj_t **blocklinks; // for thing chains + +byte *rejectmatrix; // for fast sight rejection + +mapthing_t deathmatchstarts[10], *deathmatch_p; +mapthing_t playerstarts[MAXPLAYERS]; +boolean playerstartsingame[MAXPLAYERS]; + +/* +================= += += P_LoadVertexes += +================= +*/ + +void P_LoadVertexes(int lump) +{ + byte *data; + int i; + mapvertex_t *ml; + vertex_t *li; + + numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t); + vertexes = Z_Malloc(numvertexes * sizeof(vertex_t), PU_LEVEL, 0); + data = W_CacheLumpNum(lump, PU_STATIC); + + ml = (mapvertex_t *) data; + li = vertexes; + for (i = 0; i < numvertexes; i++, li++, ml++) + { + li->x = SHORT(ml->x) << FRACBITS; + li->y = SHORT(ml->y) << FRACBITS; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSegs += +================= +*/ + +void P_LoadSegs(int lump) +{ + byte *data; + int i; + mapseg_t *ml; + seg_t *li; + line_t *ldef; + int linedef, side; + + numsegs = W_LumpLength(lump) / sizeof(mapseg_t); + segs = Z_Malloc(numsegs * sizeof(seg_t), PU_LEVEL, 0); + memset(segs, 0, numsegs * sizeof(seg_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + ml = (mapseg_t *) data; + li = segs; + for (i = 0; i < numsegs; i++, li++, ml++) + { + li->v1 = &vertexes[SHORT(ml->v1)]; + li->v2 = &vertexes[SHORT(ml->v2)]; + + li->angle = (SHORT(ml->angle)) << 16; + li->offset = (SHORT(ml->offset)) << 16; + linedef = SHORT(ml->linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + side = SHORT(ml->side); + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; + if (ldef->flags & ML_TWOSIDED) + li->backsector = sides[ldef->sidenum[side ^ 1]].sector; + else + li->backsector = 0; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSubsectors += +================= +*/ + +void P_LoadSubsectors(int lump) +{ + byte *data; + int i; + mapsubsector_t *ms; + subsector_t *ss; + + numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t); + subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0); + data = W_CacheLumpNum(lump, PU_STATIC); + + ms = (mapsubsector_t *) data; + memset(subsectors, 0, numsubsectors * sizeof(subsector_t)); + ss = subsectors; + for (i = 0; i < numsubsectors; i++, ss++, ms++) + { + ss->numlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSectors += +================= +*/ + +void P_LoadSectors(int lump) +{ + byte *data; + int i; + mapsector_t *ms; + sector_t *ss; + + numsectors = W_LumpLength(lump) / sizeof(mapsector_t); + sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0); + memset(sectors, 0, numsectors * sizeof(sector_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + ms = (mapsector_t *) data; + ss = sectors; + for (i = 0; i < numsectors; i++, ss++, ms++) + { + ss->floorheight = SHORT(ms->floorheight) << FRACBITS; + ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS; + ss->floorpic = R_FlatNumForName(ms->floorpic); + ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); + ss->lightlevel = SHORT(ms->lightlevel); + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + ss->thinglist = NULL; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadNodes += +================= +*/ + +void P_LoadNodes(int lump) +{ + byte *data; + int i, j, k; + mapnode_t *mn; + node_t *no; + + numnodes = W_LumpLength(lump) / sizeof(mapnode_t); + nodes = Z_Malloc(numnodes * sizeof(node_t), PU_LEVEL, 0); + data = W_CacheLumpNum(lump, PU_STATIC); + + mn = (mapnode_t *) data; + no = nodes; + for (i = 0; i < numnodes; i++, no++, mn++) + { + no->x = SHORT(mn->x) << FRACBITS; + no->y = SHORT(mn->y) << FRACBITS; + no->dx = SHORT(mn->dx) << FRACBITS; + no->dy = SHORT(mn->dy) << FRACBITS; + for (j = 0; j < 2; j++) + { + no->children[j] = SHORT(mn->children[j]); + for (k = 0; k < 4; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; + } + } + + W_ReleaseLumpNum(lump); +} + + + +/* +================= += += P_LoadThings += +================= +*/ + +void P_LoadThings(int lump) +{ + byte *data; + int i; + mapthing_t spawnthing; + mapthing_t *mt; + int numthings; + + data = W_CacheLumpNum(lump, PU_STATIC); + numthings = W_LumpLength(lump) / sizeof(mapthing_t); + + mt = (mapthing_t *) data; + for (i = 0; i < numthings; i++, mt++) + { + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + spawnthing.options = SHORT(mt->options); + P_SpawnMapThing(&spawnthing); + } + + if (!deathmatch) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !playerstartsingame[i]) + { + I_Error("P_LoadThings: Player %d start missing (vanilla crashes here)", i + 1); + } + playerstartsingame[i] = false; + } + } + + W_ReleaseLumpNum(lump); +} + + + +/* +================= += += P_LoadLineDefs += += Also counts secret lines for intermissions +================= +*/ + +void P_LoadLineDefs(int lump) +{ + byte *data; + int i; + maplinedef_t *mld; + line_t *ld; + vertex_t *v1, *v2; + + numlines = W_LumpLength(lump) / sizeof(maplinedef_t); + lines = Z_Malloc(numlines * sizeof(line_t), PU_LEVEL, 0); + memset(lines, 0, numlines * sizeof(line_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + mld = (maplinedef_t *) data; + ld = lines; + for (i = 0; i < numlines; i++, mld++, ld++) + { + ld->flags = SHORT(mld->flags); + ld->special = SHORT(mld->special); + ld->tag = SHORT(mld->tag); + v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; + v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else + { + if (FixedDiv(ld->dy, ld->dx) > 0) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + } + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + if (ld->sidenum[0] != -1) + ld->frontsector = sides[ld->sidenum[0]].sector; + else + ld->frontsector = 0; + if (ld->sidenum[1] != -1) + ld->backsector = sides[ld->sidenum[1]].sector; + else + ld->backsector = 0; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSideDefs += +================= +*/ + +void P_LoadSideDefs(int lump) +{ + byte *data; + int i; + mapsidedef_t *msd; + side_t *sd; + + numsides = W_LumpLength(lump) / sizeof(mapsidedef_t); + sides = Z_Malloc(numsides * sizeof(side_t), PU_LEVEL, 0); + memset(sides, 0, numsides * sizeof(side_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + msd = (mapsidedef_t *) data; + sd = sides; + for (i = 0; i < numsides; i++, msd++, sd++) + { + sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS; + sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS; + sd->toptexture = R_TextureNumForName(msd->toptexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->sector = §ors[SHORT(msd->sector)]; + } + + W_ReleaseLumpNum(lump); +} + + + +/* +================= += += P_LoadBlockMap += +================= +*/ + +void P_LoadBlockMap(int lump) +{ + int i, count; + int lumplen; + + lumplen = W_LumpLength(lump); + + blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); + W_ReadLump(lump, blockmaplump); + blockmap = blockmaplump + 4; + + // Swap all short integers to native byte ordering: + + count = lumplen / 2; + for (i = 0; i < count; i++) + blockmaplump[i] = SHORT(blockmaplump[i]); + + bmaporgx = blockmaplump[0] << FRACBITS; + bmaporgy = blockmaplump[1] << FRACBITS; + bmapwidth = blockmaplump[2]; + bmapheight = blockmaplump[3]; + +// clear out mobj chains + count = sizeof(*blocklinks) * bmapwidth * bmapheight; + blocklinks = Z_Malloc(count, PU_LEVEL, 0); + memset(blocklinks, 0, count); +} + + + + +/* +================= += += P_GroupLines += += Builds sector line lists and subsector sector numbers += Finds block bounding boxes for sectors +================= +*/ + +void P_GroupLines(void) +{ + line_t **linebuffer; + int i, j; + line_t *li; + sector_t *sector; + subsector_t *ss; + seg_t *seg; + fixed_t bbox[4]; + int block; + +// look up sector number for each subsector + ss = subsectors; + for (i = 0; i < numsubsectors; i++, ss++) + { + seg = &segs[ss->firstline]; + ss->sector = seg->sidedef->sector; + } + +// count number of lines in each sector + li = lines; + totallines = 0; + for (i = 0; i < numlines; i++, li++) + { + totallines++; + li->frontsector->linecount++; + if (li->backsector && li->backsector != li->frontsector) + { + li->backsector->linecount++; + totallines++; + } + } + +// build line tables for each sector + linebuffer = Z_Malloc(totallines * sizeof(line_t *), PU_LEVEL, 0); + sector = sectors; + for (i = 0; i < numsectors; i++, sector++) + { + M_ClearBox(bbox); + sector->lines = linebuffer; + li = lines; + for (j = 0; j < numlines; j++, li++) + { + if (li->frontsector == sector || li->backsector == sector) + { + *linebuffer++ = li; + M_AddToBox(bbox, li->v1->x, li->v1->y); + M_AddToBox(bbox, li->v2->x, li->v2->y); + } + } + if (linebuffer - sector->lines != sector->linecount) + I_Error("P_GroupLines: miscounted"); + + // set the degenmobj_t to the middle of the bounding box + sector->soundorg.x = (bbox[BOXRIGHT] + bbox[BOXLEFT]) / 2; + sector->soundorg.y = (bbox[BOXTOP] + bbox[BOXBOTTOM]) / 2; + + // adjust bounding box to map blocks + block = (bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + block = block >= bmapheight ? bmapheight - 1 : block; + sector->blockbox[BOXTOP] = block; + + block = (bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXBOTTOM] = block; + + block = (bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + block = block >= bmapwidth ? bmapwidth - 1 : block; + sector->blockbox[BOXRIGHT] = block; + + block = (bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXLEFT] = block; + } + +} + + +static void P_LoadReject(int lumpnum) +{ + int minlength; + int lumplen; + + // Calculate the size that the REJECT lump *should* be. + + minlength = (numsectors * numsectors + 7) / 8; + + // If the lump meets the minimum length, it can be loaded directly. + // Otherwise, we need to allocate a buffer of the correct size + // and pad it with appropriate data. + + lumplen = W_LumpLength(lumpnum); + + if (lumplen >= minlength) + { + rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + else + { + rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); + W_ReadLump(lumpnum, rejectmatrix); + + PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); + } +} + +//============================================================================= + +lumpinfo_t *maplumpinfo; + +/* +================= += += P_SetupLevel += +================= +*/ + +void P_SetupLevel(int episode, int map, int playermask, skill_t skill) +{ + int i; + int parm; + char lumpname[9]; + int lumpnum; + mobj_t *mobj; + + totalkills = totalitems = totalsecret = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + players[i].killcount = players[i].secretcount + = players[i].itemcount = 0; + } + players[consoleplayer].viewz = 1; // will be set by player think + + S_Start(); // make sure all sounds are stopped before Z_FreeTags + + Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + + P_InitThinkers(); + +// +// look for a regular (development) map first +// + lumpname[0] = 'E'; + lumpname[1] = '0' + episode; + lumpname[2] = 'M'; + lumpname[3] = '0' + map; + lumpname[4] = 0; + leveltime = 0; + + lumpnum = W_GetNumForName(lumpname); + + maplumpinfo = lumpinfo[lumpnum]; + +// note: most of this ordering is important + P_LoadBlockMap(lumpnum + ML_BLOCKMAP); + P_LoadVertexes(lumpnum + ML_VERTEXES); + P_LoadSectors(lumpnum + ML_SECTORS); + P_LoadSideDefs(lumpnum + ML_SIDEDEFS); + + P_LoadLineDefs(lumpnum + ML_LINEDEFS); + P_LoadSubsectors(lumpnum + ML_SSECTORS); + P_LoadNodes(lumpnum + ML_NODES); + P_LoadSegs(lumpnum + ML_SEGS); + + P_GroupLines(); + P_LoadReject(lumpnum + ML_REJECT); + + bodyqueslot = 0; + deathmatch_p = deathmatchstarts; + P_InitAmbientSound(); + P_InitMonsters(); + P_OpenWeapons(); + P_LoadThings(lumpnum + ML_THINGS); + P_CloseWeapons(); + +// +// if deathmatch, randomly spawn the active players +// + TimerGame = 0; + if (deathmatch) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { // must give a player spot before deathmatchspawn + mobj = P_SpawnMobj(playerstarts[i].x << 16, + playerstarts[i].y << 16, 0, MT_PLAYER); + players[i].mo = mobj; + G_DeathMatchSpawnPlayer(i); + P_RemoveMobj(mobj); + } + } + + //! + // @arg + // @category net + // @vanilla + // + // For multiplayer games: exit each level after n minutes. + // + + parm = M_CheckParmWithArgs("-timer", 1); + if (parm) + { + TimerGame = atoi(myargv[parm + 1]) * 35 * 60; + } + } + +// set up world state + P_SpawnSpecials(); + +// build subsector connect matrix +// P_ConnectSubsectors (); + +// preload graphics + if (precache) + R_PrecacheLevel(); + +//printf ("free memory: 0x%x\n", Z_FreeMemory()); + +} + + +/* +================= += += P_Init += +================= +*/ + +void P_Init(void) +{ + P_InitSwitchList(); + P_InitPicAnims(); + P_InitTerrainTypes(); + P_InitLava(); + R_InitSprites(sprnames); +} diff --git a/games/NXDoom/src/heretic/p_sight.c b/games/NXDoom/src/heretic/p_sight.c new file mode 100644 index 00000000000..3a442daefa6 --- /dev/null +++ b/games/NXDoom/src/heretic/p_sight.c @@ -0,0 +1,355 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// P_sight.c + +#include + +#include "doomdef.h" +#include "p_local.h" + +/* +============================================================================== + + P_CheckSight + +This uses specialized forms of the maputils routines for optimized performance + +============================================================================== +*/ + +fixed_t sightzstart; // eye z of looker +fixed_t topslope, bottomslope; // slopes to top and bottom of target + +int sightcounts[3]; + +/* +============== += += PTR_SightTraverse += +============== +*/ + +boolean PTR_SightTraverse(intercept_t * in) +{ + line_t *li; + fixed_t slope; + + li = in->d.line; + +// +// crosses a two sided line +// + P_LineOpening(li); + + if (openbottom >= opentop) // quick test for totally closed doors + return false; // stop + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - sightzstart, in->frac); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - sightzstart, in->frac); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // keep going +} + + + +/* +================== += += P_SightBlockLinesIterator += +=================== +*/ + +boolean P_SightBlockLinesIterator(int x, int y) +{ + int offset; + short *list; + line_t *ld; + int s1, s2; + divline_t dl; + + offset = y * bmapwidth + x; + + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; // line has already been checked + ld->validcount = validcount; + + s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); + if (s1 == s2) + continue; // line isn't crossed + P_MakeDivline(ld, &dl); + s1 = P_PointOnDivlineSide(trace.x, trace.y, &dl); + s2 = P_PointOnDivlineSide(trace.x + trace.dx, trace.y + trace.dy, + &dl); + if (s1 == s2) + continue; // line isn't crossed + + // try to early out the check + if (!ld->backsector) + return false; // stop checking + + // store the line for later intersection testing + intercept_p->d.line = ld; + intercept_p++; + + } + + return true; // everything was checked +} + +/* +==================== += += P_SightTraverseIntercepts += += Returns true if the traverser function returns true for all lines +==================== +*/ + +boolean P_SightTraverseIntercepts(void) +{ + int count; + fixed_t dist; + intercept_t *scan, *in; + divline_t dl; + + count = intercept_p - intercepts; +// +// calculate intercept distance +// + for (scan = intercepts; scan < intercept_p; scan++) + { + P_MakeDivline(scan->d.line, &dl); + scan->frac = P_InterceptVector(&trace, &dl); + } + +// +// go through in order +// + in = 0; // shut up compiler warning + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts; scan < intercept_p; scan++) + if (scan->frac < dist) + { + dist = scan->frac; + in = scan; + } + + if (!PTR_SightTraverse(in)) + return false; // don't bother going farther + in->frac = INT_MAX; + } + + return true; // everything was traversed +} + + + +/* +================== += += P_SightPathTraverse += += Traces a line from x1,y1 to x2,y2, calling the traverser function for each += Returns true if the traverser function returns true for all lines +================== +*/ + +boolean P_SightPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) +{ + fixed_t xt1, yt1, xt2, yt2; + fixed_t xstep, ystep; + fixed_t partial; + fixed_t xintercept, yintercept; + int mapx, mapy, mapxstep, mapystep; + int count; + + validcount++; + intercept_p = intercepts; + + if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) + x1 += FRACUNIT; // don't side exactly on a line + if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) + y1 += FRACUNIT; // don't side exactly on a line + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1 >> MAPBLOCKSHIFT; + yt1 = y1 >> MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2 >> MAPBLOCKSHIFT; + yt2 = y2 >> MAPBLOCKSHIFT; + +// points should never be out of bounds, but check once instead of +// each block + if (xt1 < 0 || yt1 < 0 || xt1 >= bmapwidth || yt1 >= bmapheight + || xt2 < 0 || yt2 < 0 || xt2 >= bmapwidth || yt2 >= bmapheight) + return false; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256 * FRACUNIT; + } + yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); + + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256 * FRACUNIT; + } + xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); + + +// +// step through map blocks +// Count is present to prevent a round off error from skipping the break + mapx = xt1; + mapy = yt1; + + + for (count = 0; count < 64; count++) + { + if (!P_SightBlockLinesIterator(mapx, mapy)) + { + sightcounts[1]++; + return false; // early out + } + + if (mapx == xt2 && mapy == yt2) + break; + + if ((yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ((xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + + } + + +// +// couldn't early out, so go through the sorted list +// + sightcounts[2]++; + + return P_SightTraverseIntercepts(); +} + + + +/* +===================== += += P_CheckSight += += Returns true if a straight line between t1 and t2 is unobstructed += look from eyes of t1 to any part of t2 += +===================== +*/ + +boolean P_CheckSight(mobj_t * t1, mobj_t * t2) +{ + int s1, s2; + int pnum, bytenum, bitnum; + +// +// check for trivial rejection +// + s1 = (t1->subsector->sector - sectors); + s2 = (t2->subsector->sector - sectors); + pnum = s1 * numsectors + s2; + bytenum = pnum >> 3; + bitnum = 1 << (pnum & 7); + + if (rejectmatrix[bytenum] & bitnum) + { + sightcounts[0]++; + return false; // can't possibly be connected + } + +// +// check precisely +// + sightzstart = t1->z + t1->height - (t1->height >> 2); + topslope = (t2->z + t2->height) - sightzstart; + bottomslope = (t2->z) - sightzstart; + + return P_SightPathTraverse(t1->x, t1->y, t2->x, t2->y); +} diff --git a/games/NXDoom/src/heretic/p_spec.c b/games/NXDoom/src/heretic/p_spec.c new file mode 100644 index 00000000000..cb89bac2115 --- /dev/null +++ b/games/NXDoom/src/heretic/p_spec.c @@ -0,0 +1,1306 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_Spec.c + +#include "doomdef.h" +#include "deh_str.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +// Macros + +#define MAX_AMBIENT_SFX 8 // Per level + +// Types + +typedef enum +{ + afxcmd_play, // (sound) + afxcmd_playabsvol, // (sound, volume) + afxcmd_playrelvol, // (sound, volume) + afxcmd_delay, // (ticks) + afxcmd_delayrand, // (andbits) + afxcmd_end // () +} afxcmd_t; + +// Data + +int *LevelAmbientSfx[MAX_AMBIENT_SFX]; +int *AmbSfxPtr; +int AmbSfxCount; +int AmbSfxTics; +int AmbSfxVolume; + +int AmbSndSeqInit[] = { // Startup + afxcmd_end +}; +int AmbSndSeq1[] = { // Scream + afxcmd_play, sfx_amb1, + afxcmd_end +}; +int AmbSndSeq2[] = { // Squish + afxcmd_play, sfx_amb2, + afxcmd_end +}; +int AmbSndSeq3[] = { // Drops + afxcmd_play, sfx_amb3, + afxcmd_delay, 16, + afxcmd_delayrand, 31, + afxcmd_play, sfx_amb7, + afxcmd_delay, 16, + afxcmd_delayrand, 31, + afxcmd_play, sfx_amb3, + afxcmd_delay, 16, + afxcmd_delayrand, 31, + afxcmd_play, sfx_amb7, + afxcmd_delay, 16, + afxcmd_delayrand, 31, + afxcmd_play, sfx_amb3, + afxcmd_delay, 16, + afxcmd_delayrand, 31, + afxcmd_play, sfx_amb7, + afxcmd_delay, 16, + afxcmd_delayrand, 31, + afxcmd_end +}; +int AmbSndSeq4[] = { // SlowFootSteps + afxcmd_play, sfx_amb4, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb4, -3, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb4, -3, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb4, -3, + afxcmd_delay, 15, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_end +}; +int AmbSndSeq5[] = { // Heartbeat + afxcmd_play, sfx_amb5, + afxcmd_delay, 35, + afxcmd_play, sfx_amb5, + afxcmd_delay, 35, + afxcmd_play, sfx_amb5, + afxcmd_delay, 35, + afxcmd_play, sfx_amb5, + afxcmd_end +}; +int AmbSndSeq6[] = { // Bells + afxcmd_play, sfx_amb6, + afxcmd_delay, 17, + afxcmd_playrelvol, sfx_amb6, -8, + afxcmd_delay, 17, + afxcmd_playrelvol, sfx_amb6, -8, + afxcmd_delay, 17, + afxcmd_playrelvol, sfx_amb6, -8, + afxcmd_end +}; +int AmbSndSeq7[] = { // Growl + afxcmd_play, sfx_bstsit, + afxcmd_end +}; +int AmbSndSeq8[] = { // Magic + afxcmd_play, sfx_amb8, + afxcmd_end +}; +int AmbSndSeq9[] = { // Laughter + afxcmd_play, sfx_amb9, + afxcmd_delay, 16, + afxcmd_playrelvol, sfx_amb9, -4, + afxcmd_delay, 16, + afxcmd_playrelvol, sfx_amb9, -4, + afxcmd_delay, 16, + afxcmd_playrelvol, sfx_amb10, -4, + afxcmd_delay, 16, + afxcmd_playrelvol, sfx_amb10, -4, + afxcmd_delay, 16, + afxcmd_playrelvol, sfx_amb10, -4, + afxcmd_end +}; +int AmbSndSeq10[] = { // FastFootsteps + afxcmd_play, sfx_amb4, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb4, -3, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb4, -3, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb4, -3, + afxcmd_delay, 8, + afxcmd_playrelvol, sfx_amb11, -3, + afxcmd_end +}; + +int *AmbientSfx[] = { + AmbSndSeq1, // Scream + AmbSndSeq2, // Squish + AmbSndSeq3, // Drops + AmbSndSeq4, // SlowFootsteps + AmbSndSeq5, // Heartbeat + AmbSndSeq6, // Bells + AmbSndSeq7, // Growl + AmbSndSeq8, // Magic + AmbSndSeq9, // Laughter + AmbSndSeq10 // FastFootsteps +}; + +animdef_t animdefs[] = { + // false = flat + // true = texture + {false, "FLTWAWA3", "FLTWAWA1", 8}, // Water + {false, "FLTSLUD3", "FLTSLUD1", 8}, // Sludge + {false, "FLTTELE4", "FLTTELE1", 6}, // Teleport + {false, "FLTFLWW3", "FLTFLWW1", 9}, // River - West + {false, "FLTLAVA4", "FLTLAVA1", 8}, // Lava + {false, "FLATHUH4", "FLATHUH1", 8}, // Super Lava + {true, "LAVAFL3", "LAVAFL1", 6}, // Texture: Lavaflow + {true, "WATRWAL3", "WATRWAL1", 4}, // Texture: Waterfall + {-1} +}; + +anim_t anims[MAXANIMS]; +anim_t *lastanim; + +int *TerrainTypes; +struct +{ + const char *name; + int type; +} TerrainTypeDefs[] = +{ + { "FLTWAWA1", FLOOR_WATER }, + { "FLTFLWW1", FLOOR_WATER }, + { "FLTLAVA1", FLOOR_LAVA }, + { "FLATHUH1", FLOOR_LAVA }, + { "FLTSLUD1", FLOOR_SLUDGE }, + { "END", -1 } +}; + +mobj_t LavaInflictor; + +//---------------------------------------------------------------------------- +// +// PROC P_InitLava +// +//---------------------------------------------------------------------------- + +void P_InitLava(void) +{ + memset(&LavaInflictor, 0, sizeof(mobj_t)); + LavaInflictor.type = MT_PHOENIXFX2; + LavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST; +} + +//---------------------------------------------------------------------------- +// +// PROC P_InitTerrainTypes +// +//---------------------------------------------------------------------------- + +void P_InitTerrainTypes(void) +{ + int i; + int lump; + int size; + + size = (numflats + 1) * sizeof(int); + TerrainTypes = Z_Malloc(size, PU_STATIC, 0); + memset(TerrainTypes, 0, size); + for (i = 0; TerrainTypeDefs[i].type != -1; i++) + { + lump = W_CheckNumForName(TerrainTypeDefs[i].name); + if (lump != -1) + { + TerrainTypes[lump - firstflat] = TerrainTypeDefs[i].type; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_InitPicAnims +// +//---------------------------------------------------------------------------- + +void P_InitPicAnims(void) +{ + const char *startname; + const char *endname; + int i; + + lastanim = anims; + for (i = 0; animdefs[i].istexture != -1; i++) + { + startname = DEH_String(animdefs[i].startname); + endname = DEH_String(animdefs[i].endname); + + if (animdefs[i].istexture) + { // Texture animation + if (R_CheckTextureNumForName(startname) == -1) + { // Texture doesn't exist + continue; + } + lastanim->picnum = R_TextureNumForName(endname); + lastanim->basepic = R_TextureNumForName(startname); + } + else + { // Flat animation + if (W_CheckNumForName(startname) == -1) + { // Flat doesn't exist + continue; + } + lastanim->picnum = R_FlatNumForName(endname); + lastanim->basepic = R_FlatNumForName(startname); + } + lastanim->istexture = animdefs[i].istexture; + lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; + if (lastanim->numpics < 2) + { + I_Error("P_InitPicAnims: bad cycle from %s to %s", + startname, endname); + } + lastanim->speed = animdefs[i].speed; + lastanim++; + } +} + +/* +============================================================================== + + UTILITIES + +============================================================================== +*/ + +// +// Will return a side_t* given the number of the current sector, +// the line number, and the side (0/1) that you want. +// +side_t *getSide(int currentSector, int line, int side) +{ + return &sides[(sectors[currentSector].lines[line])->sidenum[side]]; +} + +// +// Will return a sector_t* given the number of the current sector, +// the line number and the side (0/1) that you want. +// +sector_t *getSector(int currentSector, int line, int side) +{ + return sides[(sectors[currentSector].lines[line])->sidenum[side]].sector; +} + +// +// Given the sector number and the line number, will tell you whether +// the line is two-sided or not. +// +int twoSided(int sector, int line) +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} + +//================================================================== +// +// Return sector_t * of sector next to current. NULL if not two-sided line +// +//================================================================== +sector_t *getNextSector(line_t * line, sector_t * sec) +{ + if (!(line->flags & ML_TWOSIDED)) + return NULL; + + if (line->frontsector == sec) + return line->backsector; + + return line->frontsector; +} + +//================================================================== +// +// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindLowestFloorSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t floor = sec->floorheight; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->floorheight < floor) + floor = other->floorheight; + } + return floor; +} + +//================================================================== +// +// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindHighestFloorSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t floor = -500 * FRACUNIT; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->floorheight > floor) + floor = other->floorheight; + } + return floor; +} + +//================================================================== +// +// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight) +{ + int i; + int h; + fixed_t min; + line_t *check; + sector_t *other; + fixed_t height = currentheight; + + min = INT_MAX; + + for (i = 0, h = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + + if (other != NULL && other->floorheight > height) + { + if (other->floorheight < min) + { + min = other->floorheight; + } + + ++h; + } + } + + // Don't return INT_MAX if no higher floor is found. + + if (!h) + { + return height; + } + + // Compatibility note, in case of demo desyncs. + + if (h > 20) + { + fprintf(stderr, "P_FindNextHighestFloor: exceeded Vanilla limit\n"); + } + + return min; +} + +//================================================================== +// +// FIND LOWEST CEILING IN THE SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindLowestCeilingSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t height = INT_MAX; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->ceilingheight < height) + height = other->ceilingheight; + } + return height; +} + +//================================================================== +// +// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindHighestCeilingSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t height = 0; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->ceilingheight > height) + height = other->ceilingheight; + } + return height; +} + +//================================================================== +// +// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO +// +//================================================================== +int P_FindSectorFromLineTag(line_t * line, int start) +{ + int i; + + for (i = start + 1; i < numsectors; i++) + if (sectors[i].tag == line->tag) + return i; + return -1; +} + +//================================================================== +// +// Find minimum light from an adjacent sector +// +//================================================================== +int P_FindMinSurroundingLight(sector_t * sector, int max) +{ + int i; + int min; + line_t *line; + sector_t *check; + + min = max; + for (i = 0; i < sector->linecount; i++) + { + line = sector->lines[i]; + check = getNextSector(line, sector); + if (!check) + continue; + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} + +/* +============================================================================== + + EVENTS + +Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers + +============================================================================== +*/ + + + +/* +=============================================================================== += += P_CrossSpecialLine - TRIGGER += += Called every time a thing origin is about to cross += a line with a non 0 special += +=============================================================================== +*/ + +void P_CrossSpecialLine(int linenum, int side, mobj_t * thing) +{ + line_t *line; + + line = &lines[linenum]; + if (!thing->player) + { // Check if trigger allowed by non-player mobj + switch (line->special) + { + case 39: // Trigger_TELEPORT + case 97: // Retrigger_TELEPORT + case 4: // Trigger_Raise_Door + //case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER + //case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER + break; + default: + return; + break; + } + } + switch (line->special) + { + //==================================================== + // TRIGGERS + //==================================================== + case 2: // Open Door + EV_DoDoor(line, vld_open, VDOORSPEED); + line->special = 0; + break; + case 3: // Close Door + EV_DoDoor(line, vld_close, VDOORSPEED); + line->special = 0; + break; + case 4: // Raise Door + EV_DoDoor(line, vld_normal, VDOORSPEED); + line->special = 0; + break; + case 5: // Raise Floor + EV_DoFloor(line, raiseFloor); + line->special = 0; + break; + case 6: // Fast Ceiling Crush & Raise + EV_DoCeiling(line, fastCrushAndRaise); + line->special = 0; + break; + case 8: // Trigger_Build_Stairs (8 pixel steps) + EV_BuildStairs(line, 8 * FRACUNIT); + line->special = 0; + break; + case 106: // Trigger_Build_Stairs_16 (16 pixel steps) + EV_BuildStairs(line, 16 * FRACUNIT); + line->special = 0; + break; + case 10: // PlatDownWaitUp + EV_DoPlat(line, downWaitUpStay, 0); + line->special = 0; + break; + case 12: // Light Turn On - brightest near + EV_LightTurnOn(line, 0); + line->special = 0; + break; + case 13: // Light Turn On 255 + EV_LightTurnOn(line, 255); + line->special = 0; + break; + case 16: // Close Door 30 + EV_DoDoor(line, vld_close30ThenOpen, VDOORSPEED); + line->special = 0; + break; + case 17: // Start Light Strobing + EV_StartLightStrobing(line); + line->special = 0; + break; + case 19: // Lower Floor + EV_DoFloor(line, lowerFloor); + line->special = 0; + break; + case 22: // Raise floor to nearest height and change texture + EV_DoPlat(line, raiseToNearestAndChange, 0); + line->special = 0; + break; + case 25: // Ceiling Crush and Raise + EV_DoCeiling(line, crushAndRaise); + line->special = 0; + break; + case 30: // Raise floor to shortest texture height + // on either side of lines + EV_DoFloor(line, raiseToTexture); + line->special = 0; + break; + case 35: // Lights Very Dark + EV_LightTurnOn(line, 35); + line->special = 0; + break; + case 36: // Lower Floor (TURBO) + EV_DoFloor(line, turboLower); + line->special = 0; + break; + case 37: // LowerAndChange + EV_DoFloor(line, lowerAndChange); + line->special = 0; + break; + case 38: // Lower Floor To Lowest + EV_DoFloor(line, lowerFloorToLowest); + line->special = 0; + break; + case 39: // TELEPORT! + EV_Teleport(line, side, thing); + line->special = 0; + break; + case 40: // RaiseCeilingLowerFloor + EV_DoCeiling(line, raiseToHighest); + EV_DoFloor(line, lowerFloorToLowest); + line->special = 0; + break; + case 44: // Ceiling Crush + EV_DoCeiling(line, lowerAndCrush); + line->special = 0; + break; + case 52: // EXIT! + G_ExitLevel(); + line->special = 0; + break; + case 53: // Perpetual Platform Raise + EV_DoPlat(line, perpetualRaise, 0); + line->special = 0; + break; + case 54: // Platform Stop + EV_StopPlat(line); + line->special = 0; + break; + case 56: // Raise Floor Crush + EV_DoFloor(line, raiseFloorCrush); + line->special = 0; + break; + case 57: // Ceiling Crush Stop + EV_CeilingCrushStop(line); + line->special = 0; + break; + case 58: // Raise Floor 24 + EV_DoFloor(line, raiseFloor24); + line->special = 0; + break; + case 59: // Raise Floor 24 And Change + EV_DoFloor(line, raiseFloor24AndChange); + line->special = 0; + break; + case 104: // Turn lights off in sector(tag) + EV_TurnTagLightsOff(line); + line->special = 0; + break; + case 105: // Trigger_SecretExit + G_SecretExitLevel(); + line->special = 0; + break; + + //==================================================== + // RE-DOABLE TRIGGERS + //==================================================== + + case 72: // Ceiling Crush + EV_DoCeiling(line, lowerAndCrush); + break; + case 73: // Ceiling Crush and Raise + EV_DoCeiling(line, crushAndRaise); + break; + case 74: // Ceiling Crush Stop + EV_CeilingCrushStop(line); + break; + case 75: // Close Door + EV_DoDoor(line, vld_close, VDOORSPEED); + break; + case 76: // Close Door 30 + EV_DoDoor(line, vld_close30ThenOpen, VDOORSPEED); + break; + case 77: // Fast Ceiling Crush & Raise + EV_DoCeiling(line, fastCrushAndRaise); + break; + case 79: // Lights Very Dark + EV_LightTurnOn(line, 35); + break; + case 80: // Light Turn On - brightest near + EV_LightTurnOn(line, 0); + break; + case 81: // Light Turn On 255 + EV_LightTurnOn(line, 255); + break; + case 82: // Lower Floor To Lowest + EV_DoFloor(line, lowerFloorToLowest); + break; + case 83: // Lower Floor + EV_DoFloor(line, lowerFloor); + break; + case 84: // LowerAndChange + EV_DoFloor(line, lowerAndChange); + break; + case 86: // Open Door + EV_DoDoor(line, vld_open, VDOORSPEED); + break; + case 87: // Perpetual Platform Raise + EV_DoPlat(line, perpetualRaise, 0); + break; + case 88: // PlatDownWaitUp + EV_DoPlat(line, downWaitUpStay, 0); + break; + case 89: // Platform Stop + EV_StopPlat(line); + break; + case 90: // Raise Door + EV_DoDoor(line, vld_normal, VDOORSPEED); + break; + case 100: // Retrigger_Raise_Door_Turbo + EV_DoDoor(line, vld_normal, VDOORSPEED * 3); + break; + case 91: // Raise Floor + EV_DoFloor(line, raiseFloor); + break; + case 92: // Raise Floor 24 + EV_DoFloor(line, raiseFloor24); + break; + case 93: // Raise Floor 24 And Change + EV_DoFloor(line, raiseFloor24AndChange); + break; + case 94: // Raise Floor Crush + EV_DoFloor(line, raiseFloorCrush); + break; + case 95: // Raise floor to nearest height and change texture + EV_DoPlat(line, raiseToNearestAndChange, 0); + break; + case 96: // Raise floor to shortest texture height + // on either side of lines + EV_DoFloor(line, raiseToTexture); + break; + case 97: // TELEPORT! + EV_Teleport(line, side, thing); + break; + case 98: // Lower Floor (TURBO) + EV_DoFloor(line, turboLower); + break; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_ShootSpecialLine +// +// Called when a thing shoots a special line. +// +//---------------------------------------------------------------------------- + +void P_ShootSpecialLine(mobj_t * thing, line_t * line) +{ + if (!thing->player) + { // Check if trigger allowed by non-player mobj + switch (line->special) + { + case 46: // Impact_OpenDoor + break; + default: + return; + break; + } + } + switch (line->special) + { + case 24: // Impact_RaiseFloor + EV_DoFloor(line, raiseFloor); + P_ChangeSwitchTexture(line, 0); + break; + case 46: // Impact_OpenDoor + EV_DoDoor(line, vld_open, VDOORSPEED); + P_ChangeSwitchTexture(line, 1); + break; + case 47: // Impact_RaiseFloorNear&Change + EV_DoPlat(line, raiseToNearestAndChange, 0); + P_ChangeSwitchTexture(line, 0); + break; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerInSpecialSector +// +// Called every tic frame that the player origin is in a special sector. +// +//---------------------------------------------------------------------------- + +void P_PlayerInSpecialSector(player_t * player) +{ + sector_t *sector; + static int pushTab[5] = { + 2048 * 5, + 2048 * 10, + 2048 * 25, + 2048 * 30, + 2048 * 35 + }; + + sector = player->mo->subsector->sector; + if (player->mo->z != sector->floorheight) + { // Player is not touching the floor + return; + } + switch (sector->special) + { + case 7: // Damage_Sludge + if (!(leveltime & 31)) + { + P_DamageMobj(player->mo, NULL, NULL, 4); + } + break; + case 5: // Damage_LavaWimpy + if (!(leveltime & 15)) + { + P_DamageMobj(player->mo, &LavaInflictor, NULL, 5); + P_HitFloor(player->mo); + } + break; + case 16: // Damage_LavaHefty + if (!(leveltime & 15)) + { + P_DamageMobj(player->mo, &LavaInflictor, NULL, 8); + P_HitFloor(player->mo); + } + break; + case 4: // Scroll_EastLavaDamage + P_Thrust(player, 0, 2048 * 28); + if (!(leveltime & 15)) + { + P_DamageMobj(player->mo, &LavaInflictor, NULL, 5); + P_HitFloor(player->mo); + } + break; + case 9: // SecretArea + player->secretcount++; + sector->special = 0; + break; + case 11: // Exit_SuperDamage (DOOM E1M8 finale) + /* + player->cheats &= ~CF_GODMODE; + if(!(leveltime&0x1f)) + { + P_DamageMobj(player->mo, NULL, NULL, 20); + } + if(player->health <= 10) + { + G_ExitLevel(); + } + */ + break; + + case 25: + case 26: + case 27: + case 28: + case 29: // Scroll_North + P_Thrust(player, ANG90, pushTab[sector->special - 25]); + break; + case 20: + case 21: + case 22: + case 23: + case 24: // Scroll_East + P_Thrust(player, 0, pushTab[sector->special - 20]); + break; + case 30: + case 31: + case 32: + case 33: + case 34: // Scroll_South + P_Thrust(player, ANG270, pushTab[sector->special - 30]); + break; + case 35: + case 36: + case 37: + case 38: + case 39: // Scroll_West + P_Thrust(player, ANG180, pushTab[sector->special - 35]); + break; + + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + // Wind specials are handled in (P_mobj):P_XYMovement + break; + + case 15: // Friction_Low + // Only used in (P_mobj):P_XYMovement and (P_user):P_Thrust + break; + + default: + I_Error("P_PlayerInSpecialSector: " + "unknown special %i", sector->special); + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_UpdateSpecials +// +// Animate planes, scroll walls, etc. +// +//---------------------------------------------------------------------------- + +void P_UpdateSpecials(void) +{ + int i; + int pic; + anim_t *anim; + line_t *line; + + // Animate flats and textures + for (anim = anims; anim < lastanim; anim++) + { + for (i = anim->basepic; i < anim->basepic + anim->numpics; i++) + { + pic = + anim->basepic + + ((leveltime / anim->speed + i) % anim->numpics); + if (anim->istexture) + { + texturetranslation[i] = pic; + } + else + { + flattranslation[i] = pic; + } + } + } + // Update scrolling texture offsets + for (i = 0; i < numlinespecials; i++) + { + line = linespeciallist[i]; + switch (line->special) + { + case 48: // Effect_Scroll_Left + sides[line->sidenum[0]].textureoffset += FRACUNIT; + break; + case 99: // Effect_Scroll_Right + sides[line->sidenum[0]].textureoffset -= FRACUNIT; + break; + } + } + // Handle buttons + for (i = 0; i < MAXBUTTONS; i++) + { + if (buttonlist[i].btimer) + { + buttonlist[i].btimer--; + if (!buttonlist[i].btimer) + { + switch (buttonlist[i].where) + { + case top: + sides[buttonlist[i].line->sidenum[0]].toptexture = + buttonlist[i].btexture; + break; + case middle: + sides[buttonlist[i].line->sidenum[0]].midtexture = + buttonlist[i].btexture; + break; + case bottom: + sides[buttonlist[i].line->sidenum[0]].bottomtexture = + buttonlist[i].btexture; + break; + } + S_StartSound(buttonlist[i].soundorg, sfx_switch); + memset(&buttonlist[i], 0, sizeof(button_t)); + } + } + } +} + +//============================================================ +// +// Special Stuff that can't be categorized +// +//============================================================ +int EV_DoDonut(line_t * line) +{ + sector_t *s1; + sector_t *s2; + sector_t *s3; + int secnum; + int rtn; + int i; + floormove_t *floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + { + s1 = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (s1->specialdata) + continue; + + rtn = 1; + s2 = getNextSector(s1->lines[0], s1); + for (i = 0; i < s2->linecount; i++) + { + // Note: This was originally part of the following test: + // (!s2->lines[i]->flags & ML_TWOSIDED) || + // Due to the apparent mistaken formatting, this can never be + // true. + + if (s2->lines[i]->backsector == s1) + continue; + s3 = s2->lines[i]->backsector; + + // + // Spawn rising slime + // + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker(&floor->thinker); + s2->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = donutRaise; + floor->crush = false; + floor->direction = 1; + floor->sector = s2; + floor->speed = FLOORSPEED / 2; + floor->texture = s3->floorpic; + floor->newspecial = 0; + floor->floordestheight = s3->floorheight; + + // + // Spawn lowering donut-hole + // + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker(&floor->thinker); + s1->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = lowerFloor; + floor->crush = false; + floor->direction = -1; + floor->sector = s1; + floor->speed = FLOORSPEED / 2; + floor->floordestheight = s3->floorheight; + break; + } + } + return rtn; +} + +/* +============================================================================== + + SPECIAL SPAWNING + +============================================================================== +*/ +/* +================================================================================ += P_SpawnSpecials += += After the map has been loaded, scan for specials that += spawn thinkers += +=============================================================================== +*/ + +short numlinespecials; +line_t *linespeciallist[MAXLINEANIMS]; + +void P_SpawnSpecials(void) +{ + sector_t *sector; + int i; + + // + // Init special SECTORs + // + sector = sectors; + for (i = 0; i < numsectors; i++, sector++) + { + if (!sector->special) + continue; + switch (sector->special) + { + case 1: // FLICKERING LIGHTS + P_SpawnLightFlash(sector); + break; + case 2: // STROBE FAST + P_SpawnStrobeFlash(sector, FASTDARK, 0); + break; + case 3: // STROBE SLOW + P_SpawnStrobeFlash(sector, SLOWDARK, 0); + break; + case 4: // STROBE FAST/DEATH SLIME + P_SpawnStrobeFlash(sector, FASTDARK, 0); + sector->special = 4; + break; + case 8: // GLOWING LIGHT + P_SpawnGlowingLight(sector); + break; + case 9: // SECRET SECTOR + totalsecret++; + break; + case 10: // DOOR CLOSE IN 30 SECONDS + P_SpawnDoorCloseIn30(sector); + break; + case 12: // SYNC STROBE SLOW + P_SpawnStrobeFlash(sector, SLOWDARK, 1); + break; + case 13: // SYNC STROBE FAST + P_SpawnStrobeFlash(sector, FASTDARK, 1); + break; + case 14: // DOOR RAISE IN 5 MINUTES + P_SpawnDoorRaiseIn5Mins(sector, i); + break; + } + } + + + // + // Init line EFFECTs + // + numlinespecials = 0; + for (i = 0; i < numlines; i++) + switch (lines[i].special) + { + case 48: // Effect_Scroll_Left + case 99: // Effect_Scroll_Right + linespeciallist[numlinespecials] = &lines[i]; + numlinespecials++; + break; + } + + // + // Init other misc stuff + // + for (i = 0; i < MAXCEILINGS; i++) + activeceilings[i] = NULL; + for (i = 0; i < MAXPLATS; i++) + activeplats[i] = NULL; + for (i = 0; i < MAXBUTTONS; i++) + memset(&buttonlist[i], 0, sizeof(button_t)); +} + +//---------------------------------------------------------------------------- +// +// PROC P_InitAmbientSound +// +//---------------------------------------------------------------------------- + +void P_InitAmbientSound(void) +{ + AmbSfxCount = 0; + AmbSfxVolume = 0; + AmbSfxTics = 10 * TICRATE; + AmbSfxPtr = AmbSndSeqInit; +} + +//---------------------------------------------------------------------------- +// +// PROC P_AddAmbientSfx +// +// Called by (P_mobj):P_SpawnMapThing during (P_setup):P_SetupLevel. +// +//---------------------------------------------------------------------------- + +void P_AddAmbientSfx(int sequence) +{ + if (AmbSfxCount == MAX_AMBIENT_SFX) + { + I_Error("Too many ambient sound sequences"); + } + LevelAmbientSfx[AmbSfxCount++] = AmbientSfx[sequence]; +} + +//---------------------------------------------------------------------------- +// +// PROC P_AmbientSound +// +// Called every tic by (P_tick):P_Ticker. +// +//---------------------------------------------------------------------------- + +void P_AmbientSound(void) +{ + afxcmd_t cmd; + int sound; + boolean done; + + if (!AmbSfxCount) + { // No ambient sound sequences on current level + return; + } + if (--AmbSfxTics) + { + return; + } + done = false; + do + { + cmd = *AmbSfxPtr++; + switch (cmd) + { + case afxcmd_play: + AmbSfxVolume = P_Random() >> 2; + S_StartSoundAtVolume(NULL, *AmbSfxPtr++, AmbSfxVolume); + break; + case afxcmd_playabsvol: + sound = *AmbSfxPtr++; + AmbSfxVolume = *AmbSfxPtr++; + S_StartSoundAtVolume(NULL, sound, AmbSfxVolume); + break; + case afxcmd_playrelvol: + sound = *AmbSfxPtr++; + AmbSfxVolume += *AmbSfxPtr++; + if (AmbSfxVolume < 0) + { + AmbSfxVolume = 0; + } + else if (AmbSfxVolume > 127) + { + AmbSfxVolume = 127; + } + S_StartSoundAtVolume(NULL, sound, AmbSfxVolume); + break; + case afxcmd_delay: + AmbSfxTics = *AmbSfxPtr++; + done = true; + break; + case afxcmd_delayrand: + AmbSfxTics = P_Random() & (*AmbSfxPtr++); + done = true; + break; + case afxcmd_end: + AmbSfxTics = 6 * TICRATE + P_Random(); + AmbSfxPtr = LevelAmbientSfx[P_Random() % AmbSfxCount]; + done = true; + break; + default: + I_Error("P_AmbientSound: Unknown afxcmd %d", cmd); + break; + } + } + while (done == false); +} diff --git a/games/NXDoom/src/heretic/p_spec.h b/games/NXDoom/src/heretic/p_spec.h new file mode 100644 index 00000000000..7d78e4d2cf6 --- /dev/null +++ b/games/NXDoom/src/heretic/p_spec.h @@ -0,0 +1,390 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_spec.h + +/* +=============================================================================== + + P_SPEC + +=============================================================================== +*/ + +// +// Animating textures and planes +// +typedef struct +{ + boolean istexture; + int picnum; + int basepic; + int numpics; + int speed; +} anim_t; + +// +// source animation definition +// +typedef struct +{ + int istexture; // if false, it's a flat + char endname[9]; + char startname[9]; + int speed; +} animdef_t; + +#define MAXANIMS 32 + +extern anim_t anims[MAXANIMS], *lastanim; +extern int *TerrainTypes; + +// +// Animating line specials +// +#define MAXLINEANIMS 64 +extern short numlinespecials; +extern line_t *linespeciallist[MAXLINEANIMS]; + +// Define values for map objects +#define MO_TELEPORTMAN 14 + +// at game start +void P_InitPicAnims(void); +void P_InitTerrainTypes(void); +void P_InitLava(void); + +// at map load +void P_SpawnSpecials(void); +void P_InitAmbientSound(void); +void P_AddAmbientSfx(int sequence); + +// every tic +void P_UpdateSpecials(void); +void P_AmbientSound(void); + +// when needed +boolean P_UseSpecialLine(mobj_t * thing, line_t * line); +void P_ShootSpecialLine(mobj_t * thing, line_t * line); +void P_CrossSpecialLine(int linenum, int side, mobj_t * thing); + +void P_PlayerInSpecialSector(player_t * player); + +int twoSided(int sector, int line); +sector_t *getSector(int currentSector, int line, int side); +side_t *getSide(int currentSector, int line, int side); +fixed_t P_FindLowestFloorSurrounding(sector_t * sec); +fixed_t P_FindHighestFloorSurrounding(sector_t * sec); +fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight); +fixed_t P_FindLowestCeilingSurrounding(sector_t * sec); +fixed_t P_FindHighestCeilingSurrounding(sector_t * sec); +int P_FindSectorFromLineTag(line_t * line, int start); +int P_FindMinSurroundingLight(sector_t * sector, int max); +sector_t *getNextSector(line_t * line, sector_t * sec); + +// +// SPECIAL +// +int EV_DoDonut(line_t * line); + +/* +=============================================================================== + + P_LIGHTS + +=============================================================================== +*/ +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int maxlight; + int minlight; + int maxtime; + int mintime; +} lightflash_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int minlight; + int maxlight; + int darktime; + int brighttime; +} strobe_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int minlight; + int maxlight; + int direction; +} glow_t; + +#define GLOWSPEED 8 +#define STROBEBRIGHT 5 +#define FASTDARK 15 +#define SLOWDARK 35 + +void T_LightFlash(thinker_t *thinker); +void P_SpawnLightFlash(sector_t * sector); +void T_StrobeFlash(thinker_t *thinker); +void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync); +void EV_StartLightStrobing(line_t * line); +void EV_TurnTagLightsOff(line_t * line); +void EV_LightTurnOn(line_t * line, int bright); +void T_Glow(thinker_t *thinker); +void P_SpawnGlowingLight(sector_t * sector); + +/* +=============================================================================== + + P_SWITCH + +=============================================================================== +*/ +typedef struct +{ + char name1[9]; + char name2[9]; + short episode; +} switchlist_t; + +typedef enum +{ + top, + middle, + bottom +} bwhere_e; + +typedef struct +{ + line_t *line; + bwhere_e where; + int btexture; + int btimer; + void *soundorg; +} button_t; + +#define MAXSWITCHES 50 // max # of wall switches in a level +#define MAXBUTTONS 16 // 4 players, 4 buttons each at once, max. +#define BUTTONTIME 35 // 1 second + +extern button_t buttonlist[MAXBUTTONS]; + +void P_ChangeSwitchTexture(line_t * line, int useAgain); +void P_InitSwitchList(void); + +/* +=============================================================================== + + P_PLATS + +=============================================================================== +*/ +typedef enum +{ + up, + down, + waiting, + in_stasis +} plat_e; + +typedef enum +{ + perpetualRaise, + downWaitUpStay, + raiseAndChange, + raiseToNearestAndChange +} plattype_e; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + fixed_t speed; + fixed_t low; + fixed_t high; + int wait; + int count; + plat_e status; + plat_e oldstatus; + boolean crush; + int tag; + plattype_e type; +} plat_t; + +#define PLATWAIT 3 +#define PLATSPEED FRACUNIT +#define MAXPLATS 30 + +extern plat_t *activeplats[MAXPLATS]; + +void T_PlatRaise(thinker_t *thinker); +int EV_DoPlat(line_t * line, plattype_e type, int amount); +void P_AddActivePlat(plat_t * plat); +void P_RemoveActivePlat(plat_t * plat); +void EV_StopPlat(line_t * line); +void P_ActivateInStasis(int tag); + +/* +=============================================================================== + + P_DOORS + +=============================================================================== +*/ +typedef enum +{ + vld_normal, + vld_close30ThenOpen, + vld_close, + vld_open, + vld_raiseIn5Mins +} vldoor_e; + +typedef struct +{ + thinker_t thinker; + vldoor_e type; + sector_t *sector; + fixed_t topheight; + fixed_t speed; + int direction; // 1 = up, 0 = waiting at top, -1 = down + int topwait; // tics to wait at the top + // (keep in case a door going down is reset) + int topcountdown; // when it reaches 0, start going down +} vldoor_t; + +#define VDOORSPEED FRACUNIT*2 +#define VDOORWAIT 150 + +void EV_VerticalDoor(line_t * line, mobj_t * thing); +int EV_DoDoor(line_t * line, vldoor_e type, fixed_t speed); +void T_VerticalDoor(thinker_t *thinker); +void P_SpawnDoorCloseIn30(sector_t * sec); +void P_SpawnDoorRaiseIn5Mins(sector_t * sec, int secnum); + +/* +=============================================================================== + + P_CEILNG + +=============================================================================== +*/ +typedef enum +{ + lowerToFloor, + raiseToHighest, + lowerAndCrush, + crushAndRaise, + fastCrushAndRaise +} ceiling_e; + +typedef struct +{ + thinker_t thinker; + ceiling_e type; + sector_t *sector; + fixed_t bottomheight, topheight; + fixed_t speed; + boolean crush; + int direction; // 1 = up, 0 = waiting, -1 = down + int tag; // ID + int olddirection; +} ceiling_t; + +#define CEILSPEED FRACUNIT +#define CEILWAIT 150 +#define MAXCEILINGS 30 + +extern ceiling_t *activeceilings[MAXCEILINGS]; + +int EV_DoCeiling(line_t * line, ceiling_e type); +void T_MoveCeiling(thinker_t *thinker); +void P_AddActiveCeiling(ceiling_t * c); +void P_RemoveActiveCeiling(ceiling_t * c); +int EV_CeilingCrushStop(line_t * line); +void P_ActivateInStasisCeiling(line_t * line); + +/* +=============================================================================== + + P_FLOOR + +=============================================================================== +*/ +typedef enum +{ + lowerFloor, // lower floor to highest surrounding floor + lowerFloorToLowest, // lower floor to lowest surrounding floor + turboLower, // lower floor to highest surrounding floor VERY FAST + raiseFloor, // raise floor to lowest surrounding CEILING + raiseFloorToNearest, // raise floor to next highest surrounding floor + raiseToTexture, // raise floor to shortest height texture around it + lowerAndChange, // lower floor to lowest surrounding floor and change + // floorpic + raiseFloor24, + raiseFloor24AndChange, + raiseFloorCrush, + donutRaise, + raiseBuildStep // One step of a staircase +} floor_e; + +typedef struct +{ + thinker_t thinker; + floor_e type; + boolean crush; + sector_t *sector; + int direction; + int newspecial; + short texture; + fixed_t floordestheight; + fixed_t speed; +} floormove_t; + +#define FLOORSPEED FRACUNIT + +typedef enum +{ + ok, + crushed, + pastdest +} result_e; + +result_e T_MovePlane(sector_t * sector, fixed_t speed, + fixed_t dest, boolean crush, int floorOrCeiling, + int direction); + +int EV_BuildStairs(line_t * line, fixed_t stepDelta); +int EV_DoFloor(line_t * line, floor_e floortype); +void T_MoveFloor(thinker_t *thinker); + +/* +=============================================================================== + + P_TELEPT + +=============================================================================== +*/ + +boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle); +boolean EV_Teleport(line_t * line, int side, mobj_t * thing); diff --git a/games/NXDoom/src/heretic/p_switch.c b/games/NXDoom/src/heretic/p_switch.c new file mode 100644 index 00000000000..885d67326db --- /dev/null +++ b/games/NXDoom/src/heretic/p_switch.c @@ -0,0 +1,409 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include "doomdef.h" +#include "deh_str.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +//================================================================== +// +// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE +// +//================================================================== +switchlist_t alphSwitchList[] = { + {"SW1OFF", "SW1ON", 1}, + {"SW2OFF", "SW2ON", 1}, + +/* + {"SW1CTY", "SW2CTY", 1}, + {"SW1ORGRY", "SW2ORGRY", 1}, + {"SW1GRSTN", "SW2GRSTN", 1}, + {"SW1SNDP", "SW2SNDP", 1}, + {"SW1SPINE", "SW2SPINE", 1}, + {"SW1SQPEB", "SW2SQPEB", 1}, + {"SW1TRST1", "SW2TRST1", 1}, + {"SW1CSTL", "SW2CSTL", 1}, + {"SW1MOSS", "SW2MOSS", 1}, + {"SW1SNDSQ", "SW2SNDSQ", 1}, + {"SW1RED", "SW2RED", 1}, + {"SW1WOOD", "SW2WOOD", 1}, + {"SW1BROWN", "SW2BROWN", 1}, + + {"SW1TRST2", "SW2TRST2", 2}, + {"SW1MSC", "SW2MSC", 2}, + {"SW1MSC2", "SW2MSC2", 2}, + {"SW1GRDMD", "SW2GRDMD", 2}, +*/ + +#if 0 + {"SW1BRCOM", "SW2BRCOM", 1}, + {"SW1BRN1", "SW2BRN1", 1}, + {"SW1BRN2", "SW2BRN2", 1}, + {"SW1BRNGN", "SW2BRNGN", 1}, + {"SW1BROWN", "SW2BROWN", 1}, + {"SW1COMM", "SW2COMM", 1}, + {"SW1COMP", "SW2COMP", 1}, + {"SW1DIRT", "SW2DIRT", 1}, + {"SW1EXIT", "SW2EXIT", 1}, + {"SW1GRAY", "SW2GRAY", 1}, + {"SW1GRAY1", "SW2GRAY1", 1}, + {"SW1METAL", "SW2METAL", 1}, + {"SW1PIPE", "SW2PIPE", 1}, + {"SW1SLAD", "SW2SLAD", 1}, + {"SW1STARG", "SW2STARG", 1}, + {"SW1STON1", "SW2STON1", 1}, + {"SW1STON2", "SW2STON2", 1}, + {"SW1STONE", "SW2STONE", 1}, + {"SW1STRTN", "SW2STRTN", 1}, + + {"SW1BLUE", "SW2BLUE", 2}, + {"SW1CMT", "SW2CMT", 2}, + {"SW1GARG", "SW2GARG", 2}, + {"SW1GSTON", "SW2GSTON", 2}, + {"SW1HOT", "SW2HOT", 2}, + {"SW1LION", "SW2LION", 2}, + {"SW1SATYR", "SW2SATYR", 2}, + {"SW1SKIN", "SW2SKIN", 2}, + {"SW1VINE", "SW2VINE", 2}, + {"SW1WOOD", "SW2WOOD", 2}, +#endif +}; + +int switchlist[MAXSWITCHES * 2]; +int numswitches; +button_t buttonlist[MAXBUTTONS]; + +/* +=============== += += P_InitSwitchList += += Only called at game initialization += +=============== +*/ + +void P_InitSwitchList(void) +{ + int i, slindex, episode; + + // Note that this is called "episode" here but it's actually something + // quite different. As we progress from Shareware->Registered->Doom II + // we support more switch textures. + if (gamemode == shareware) + { + episode = 1; + } + else + { + episode = 2; + } + + slindex = 0; + + for (i = 0; i < arrlen(alphSwitchList); i++) + { + if (alphSwitchList[i].episode <= episode) + { + switchlist[slindex++] = + R_TextureNumForName(DEH_String(alphSwitchList[i].name1)); + switchlist[slindex++] = + R_TextureNumForName(DEH_String(alphSwitchList[i].name2)); + } + } + + numswitches = slindex / 2; + switchlist[slindex] = -1; +} + +//================================================================== +// +// Start a button counting down till it turns off. +// +//================================================================== +void P_StartButton(line_t * line, bwhere_e w, int texture, int time) +{ + int i; + + for (i = 0; i < MAXBUTTONS; i++) + if (!buttonlist[i].btimer) + { + buttonlist[i].line = line; + buttonlist[i].where = w; + buttonlist[i].btexture = texture; + buttonlist[i].btimer = time; + buttonlist[i].soundorg = &line->frontsector->soundorg; + return; + } + + I_Error("P_StartButton: no button slots left!"); +} + +//================================================================== +// +// Function that changes wall texture. +// Tell it if switch is ok to use again (1=yes, it's a button). +// +//================================================================== +void P_ChangeSwitchTexture(line_t * line, int useAgain) +{ + int texTop; + int texMid; + int texBot; + int i; + int sound; + + if (!useAgain) + line->special = 0; + + texTop = sides[line->sidenum[0]].toptexture; + texMid = sides[line->sidenum[0]].midtexture; + texBot = sides[line->sidenum[0]].bottomtexture; + + sound = sfx_switch; + //if (line->special == 11) // EXIT SWITCH? + // sound = sfx_swtchx; + + for (i = 0; i < numswitches * 2; i++) + if (switchlist[i] == texTop) + { + S_StartSound(buttonlist->soundorg, sound); + sides[line->sidenum[0]].toptexture = switchlist[i ^ 1]; + if (useAgain) + P_StartButton(line, top, switchlist[i], BUTTONTIME); + return; + } + else if (switchlist[i] == texMid) + { + S_StartSound(buttonlist->soundorg, sound); + sides[line->sidenum[0]].midtexture = switchlist[i ^ 1]; + if (useAgain) + P_StartButton(line, middle, switchlist[i], BUTTONTIME); + return; + } + else if (switchlist[i] == texBot) + { + S_StartSound(buttonlist->soundorg, sound); + sides[line->sidenum[0]].bottomtexture = switchlist[i ^ 1]; + if (useAgain) + P_StartButton(line, bottom, switchlist[i], BUTTONTIME); + return; + } +} + +/* +============================================================================== += += P_UseSpecialLine += += Called when a thing uses a special line += Only the front sides of lines are usable +=============================================================================== +*/ + +boolean P_UseSpecialLine(mobj_t * thing, line_t * line) +{ + // + // Switches that other things can activate + // + if (!thing->player) + { + if (line->flags & ML_SECRET) + return false; // never open secret doors + switch (line->special) + { + case 1: // MANUAL DOOR RAISE + case 32: // MANUAL BLUE + case 33: // MANUAL RED + case 34: // MANUAL YELLOW + break; + default: + return false; + } + } + + // + // do something + // + switch (line->special) + { + //=============================================== + // MANUALS + //=============================================== + case 1: // Vertical Door + case 26: // Blue Door/Locked + case 27: // Yellow Door /Locked + case 28: // Red Door /Locked + + case 31: // Manual door open + case 32: // Blue locked door open + case 33: // Red locked door open + case 34: // Yellow locked door open + EV_VerticalDoor(line, thing); + break; + //=============================================== + // SWITCHES + //=============================================== + case 7: // Switch_Build_Stairs (8 pixel steps) + if (EV_BuildStairs(line, 8 * FRACUNIT)) + { + P_ChangeSwitchTexture(line, 0); + } + break; + case 107: // Switch_Build_Stairs_16 (16 pixel steps) + if (EV_BuildStairs(line, 16 * FRACUNIT)) + { + P_ChangeSwitchTexture(line, 0); + } + break; + case 9: // Change Donut + if (EV_DoDonut(line)) + P_ChangeSwitchTexture(line, 0); + break; + case 11: // Exit level + G_ExitLevel(); + P_ChangeSwitchTexture(line, 0); + break; + case 14: // Raise Floor 32 and change texture + if (EV_DoPlat(line, raiseAndChange, 32)) + P_ChangeSwitchTexture(line, 0); + break; + case 15: // Raise Floor 24 and change texture + if (EV_DoPlat(line, raiseAndChange, 24)) + P_ChangeSwitchTexture(line, 0); + break; + case 18: // Raise Floor to next highest floor + if (EV_DoFloor(line, raiseFloorToNearest)) + P_ChangeSwitchTexture(line, 0); + break; + case 20: // Raise Plat next highest floor and change texture + if (EV_DoPlat(line, raiseToNearestAndChange, 0)) + P_ChangeSwitchTexture(line, 0); + break; + case 21: // PlatDownWaitUpStay + if (EV_DoPlat(line, downWaitUpStay, 0)) + P_ChangeSwitchTexture(line, 0); + break; + case 23: // Lower Floor to Lowest + if (EV_DoFloor(line, lowerFloorToLowest)) + P_ChangeSwitchTexture(line, 0); + break; + case 29: // Raise Door + if (EV_DoDoor(line, vld_normal, VDOORSPEED)) + P_ChangeSwitchTexture(line, 0); + break; + case 41: // Lower Ceiling to Floor + if (EV_DoCeiling(line, lowerToFloor)) + P_ChangeSwitchTexture(line, 0); + break; + case 71: // Turbo Lower Floor + if (EV_DoFloor(line, turboLower)) + P_ChangeSwitchTexture(line, 0); + break; + case 49: // Lower Ceiling And Crush + if (EV_DoCeiling(line, lowerAndCrush)) + P_ChangeSwitchTexture(line, 0); + break; + case 50: // Close Door + if (EV_DoDoor(line, vld_close, VDOORSPEED)) + P_ChangeSwitchTexture(line, 0); + break; + case 51: // Secret EXIT + G_SecretExitLevel(); + P_ChangeSwitchTexture(line, 0); + break; + case 55: // Raise Floor Crush + if (EV_DoFloor(line, raiseFloorCrush)) + P_ChangeSwitchTexture(line, 0); + break; + case 101: // Raise Floor + if (EV_DoFloor(line, raiseFloor)) + P_ChangeSwitchTexture(line, 0); + break; + case 102: // Lower Floor to Surrounding floor height + if (EV_DoFloor(line, lowerFloor)) + P_ChangeSwitchTexture(line, 0); + break; + case 103: // Open Door + if (EV_DoDoor(line, vld_open, VDOORSPEED)) + P_ChangeSwitchTexture(line, 0); + break; + //=============================================== + // BUTTONS + //=============================================== + case 42: // Close Door + if (EV_DoDoor(line, vld_close, VDOORSPEED)) + P_ChangeSwitchTexture(line, 1); + break; + case 43: // Lower Ceiling to Floor + if (EV_DoCeiling(line, lowerToFloor)) + P_ChangeSwitchTexture(line, 1); + break; + case 45: // Lower Floor to Surrounding floor height + if (EV_DoFloor(line, lowerFloor)) + P_ChangeSwitchTexture(line, 1); + break; + case 60: // Lower Floor to Lowest + if (EV_DoFloor(line, lowerFloorToLowest)) + P_ChangeSwitchTexture(line, 1); + break; + case 61: // Open Door + if (EV_DoDoor(line, vld_open, VDOORSPEED)) + P_ChangeSwitchTexture(line, 1); + break; + case 62: // PlatDownWaitUpStay + if (EV_DoPlat(line, downWaitUpStay, 1)) + P_ChangeSwitchTexture(line, 1); + break; + case 63: // Raise Door + if (EV_DoDoor(line, vld_normal, VDOORSPEED)) + P_ChangeSwitchTexture(line, 1); + break; + case 64: // Raise Floor to ceiling + if (EV_DoFloor(line, raiseFloor)) + P_ChangeSwitchTexture(line, 1); + break; + case 66: // Raise Floor 24 and change texture + if (EV_DoPlat(line, raiseAndChange, 24)) + P_ChangeSwitchTexture(line, 1); + break; + case 67: // Raise Floor 32 and change texture + if (EV_DoPlat(line, raiseAndChange, 32)) + P_ChangeSwitchTexture(line, 1); + break; + case 65: // Raise Floor Crush + if (EV_DoFloor(line, raiseFloorCrush)) + P_ChangeSwitchTexture(line, 1); + break; + case 68: // Raise Plat to next highest floor and change texture + if (EV_DoPlat(line, raiseToNearestAndChange, 0)) + P_ChangeSwitchTexture(line, 1); + break; + case 69: // Raise Floor to next highest floor + if (EV_DoFloor(line, raiseFloorToNearest)) + P_ChangeSwitchTexture(line, 1); + break; + case 70: // Turbo Lower Floor + if (EV_DoFloor(line, turboLower)) + P_ChangeSwitchTexture(line, 1); + break; + } + + return true; +} diff --git a/games/NXDoom/src/heretic/p_telept.c b/games/NXDoom/src/heretic/p_telept.c new file mode 100644 index 00000000000..a922f7cf871 --- /dev/null +++ b/games/NXDoom/src/heretic/p_telept.c @@ -0,0 +1,164 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_telept.c + +#include "doomdef.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" + +//---------------------------------------------------------------------------- +// +// FUNC P_Teleport +// +//---------------------------------------------------------------------------- + +boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle) +{ + fixed_t oldx; + fixed_t oldy; + fixed_t oldz; + fixed_t aboveFloor; + fixed_t fogDelta; + player_t *player; + unsigned an; + mobj_t *fog; + + oldx = thing->x; + oldy = thing->y; + oldz = thing->z; + aboveFloor = thing->z - thing->floorz; + if (!P_TeleportMove(thing, x, y)) + { + return (false); + } + if (thing->player) + { + player = thing->player; + if (player->powers[pw_flight] && aboveFloor) + { + thing->z = thing->floorz + aboveFloor; + if (thing->z + thing->height > thing->ceilingz) + { + thing->z = thing->ceilingz - thing->height; + } + player->viewz = thing->z + player->viewheight; + } + else + { + thing->z = thing->floorz; + player->viewz = thing->z + player->viewheight; + player->lookdir = 0; + } + } + else if (thing->flags & MF_MISSILE) + { + thing->z = thing->floorz + aboveFloor; + if (thing->z + thing->height > thing->ceilingz) + { + thing->z = thing->ceilingz - thing->height; + } + } + else + { + thing->z = thing->floorz; + } + // Spawn teleport fog at source and destination + fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; + fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG); + S_StartSound(fog, sfx_telept); + an = angle >> ANGLETOFINESHIFT; + fog = P_SpawnMobj(x + 20 * finecosine[an], + y + 20 * finesine[an], thing->z + fogDelta, MT_TFOG); + S_StartSound(fog, sfx_telept); + if (thing->player && !thing->player->powers[pw_weaponlevel2]) + { // Freeze player for about .5 sec + thing->reactiontime = 18; + } + thing->angle = angle; + if (thing->flags2 & MF2_FOOTCLIP + && P_GetThingFloorType(thing) != FLOOR_SOLID) + { + thing->flags2 |= MF2_FEETARECLIPPED; + } + else if (thing->flags2 & MF2_FEETARECLIPPED) + { + thing->flags2 &= ~MF2_FEETARECLIPPED; + } + if (thing->flags & MF_MISSILE) + { + angle >>= ANGLETOFINESHIFT; + thing->momx = FixedMul(thing->info->speed, finecosine[angle]); + thing->momy = FixedMul(thing->info->speed, finesine[angle]); + } + else + { + thing->momx = thing->momy = thing->momz = 0; + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC EV_Teleport +// +//---------------------------------------------------------------------------- + +boolean EV_Teleport(line_t * line, int side, mobj_t * thing) +{ + int i; + int tag; + mobj_t *m; + thinker_t *thinker; + sector_t *sector; + + if (thing->flags2 & MF2_NOTELEPORT) + { + return (false); + } + if (side == 1) + { // Don't teleport when crossing back side + return (false); + } + tag = line->tag; + for (i = 0; i < numsectors; i++) + { + if (sectors[i].tag == tag) + { + for (thinker = thinkercap.next; thinker != &thinkercap; + thinker = thinker->next) + { + if (thinker->function != P_MobjThinker) + { // Not a mobj + continue; + } + m = (mobj_t *) thinker; + if (m->type != MT_TELEPORTMAN) + { // Not a teleportman + continue; + } + sector = m->subsector->sector; + if (sector - sectors != i) + { // Wrong sector + continue; + } + return (P_Teleport(thing, m->x, m->y, m->angle)); + } + } + } + return (false); +} diff --git a/games/NXDoom/src/heretic/p_tick.c b/games/NXDoom/src/heretic/p_tick.c new file mode 100644 index 00000000000..ac1c9429966 --- /dev/null +++ b/games/NXDoom/src/heretic/p_tick.c @@ -0,0 +1,167 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_tick.c + +#include "doomdef.h" +#include "i_system.h" +#include "p_local.h" +#include "v_video.h" + +int leveltime; +int TimerGame; + +/* +=============================================================================== + + THINKERS + +All thinkers should be allocated by Z_Malloc so they can be operated on uniformly. The actual +structures will vary in size, but the first element must be thinker_t. + +=============================================================================== +*/ + +thinker_t thinkercap; // both the head and tail of the thinker list + +/* +=============== += += P_InitThinkers += +=============== +*/ + +void P_InitThinkers(void) +{ + thinkercap.prev = thinkercap.next = &thinkercap; +} + + +/* +=============== += += P_AddThinker += += Adds a new thinker at the end of the list += +=============== +*/ + +void P_AddThinker(thinker_t * thinker) +{ + thinkercap.prev->next = thinker; + thinker->next = &thinkercap; + thinker->prev = thinkercap.prev; + thinkercap.prev = thinker; +} + +/* +=============== += += P_RemoveThinker += += Deallocation is lazy -- it will not actually be freed until its += thinking turn comes up += +=============== +*/ + +void P_RemoveThinker(thinker_t * thinker) +{ + thinker->function = (think_t) - 1; +} + +/* +=============== += += P_AllocateThinker += += Allocates memory and adds a new thinker at the end of the list += +=============== +*/ + +void P_AllocateThinker(thinker_t * thinker) +{ +} + + +/* +=============== += += P_RunThinkers += +=============== +*/ + +void P_RunThinkers(void) +{ + thinker_t *currentthinker, *nextthinker; + + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + if (currentthinker->function == (think_t) - 1) + { // time to remove it + nextthinker = currentthinker->next; + currentthinker->next->prev = currentthinker->prev; + currentthinker->prev->next = currentthinker->next; + Z_Free(currentthinker); + } + else + { + if (currentthinker->function) + currentthinker->function(currentthinker); + nextthinker = currentthinker->next; + } + currentthinker = nextthinker; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_Ticker +// +//---------------------------------------------------------------------------- + +void P_Ticker(void) +{ + int i; + + if (paused) + { + return; + } + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + P_PlayerThink(&players[i]); + } + } + if (TimerGame) + { + if (!--TimerGame) + { + G_ExitLevel(); + } + } + P_RunThinkers(); + P_UpdateSpecials(); + P_AmbientSound(); + leveltime++; +} diff --git a/games/NXDoom/src/heretic/p_user.c b/games/NXDoom/src/heretic/p_user.c new file mode 100644 index 00000000000..b24029ca707 --- /dev/null +++ b/games/NXDoom/src/heretic/p_user.c @@ -0,0 +1,1017 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// P_user.c + +#include + +#include "doomdef.h" +#include "deh_str.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +void P_PlayerNextArtifact(player_t * player); + +// Macros + +#define MAXBOB 0x100000 // 16 pixels of bob + +// Data + +boolean onground; +int newtorch; // used in the torch flicker effect. +int newtorchdelta; + +boolean WeaponInShareware[] = { + true, // Staff + true, // Gold wand + true, // Crossbow + true, // Blaster + false, // Skull rod + false, // Phoenix rod + false, // Mace + true, // Gauntlets + true // Beak +}; + +/* +================== += += P_Thrust += += moves the given origin along a given angle += +================== +*/ + +void P_Thrust(player_t * player, angle_t angle, fixed_t move) +{ + angle >>= ANGLETOFINESHIFT; + if (player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz)) + { + player->mo->momx += FixedMul(move, finecosine[angle]); + player->mo->momy += FixedMul(move, finesine[angle]); + } + else if (player->mo->subsector->sector->special == 15) // Friction_Low + { + player->mo->momx += FixedMul(move >> 2, finecosine[angle]); + player->mo->momy += FixedMul(move >> 2, finesine[angle]); + } + else + { + player->mo->momx += FixedMul(move, finecosine[angle]); + player->mo->momy += FixedMul(move, finesine[angle]); + } +} + + +/* +================== += += P_CalcHeight += +=Calculate the walking / running height adjustment += +================== +*/ + +void P_CalcHeight(player_t * player) +{ + int angle; + fixed_t bob; + +// +// regular movement bobbing (needs to be calculated for gun swing even +// if not on ground) +// OPTIMIZE: tablify angle + + player->bob = FixedMul(player->mo->momx, player->mo->momx) + + FixedMul(player->mo->momy, player->mo->momy); + player->bob >>= 2; + if (player->bob > MAXBOB) + player->bob = MAXBOB; + if (player->mo->flags2 & MF2_FLY && !onground) + { + player->bob = FRACUNIT / 2; + } + + if ((player->cheats & CF_NOMOMENTUM)) + { + player->viewz = player->mo->z + VIEWHEIGHT; + if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) + player->viewz = player->mo->ceilingz - 4 * FRACUNIT; + player->viewz = player->mo->z + player->viewheight; + return; + } + + angle = (FINEANGLES / 20 * leveltime) & FINEMASK; + bob = FixedMul(player->bob / 2, finesine[angle]); + +// +// move viewheight +// + if (player->playerstate == PST_LIVE) + { + player->viewheight += player->deltaviewheight; + if (player->viewheight > VIEWHEIGHT) + { + player->viewheight = VIEWHEIGHT; + player->deltaviewheight = 0; + } + if (player->viewheight < VIEWHEIGHT / 2) + { + player->viewheight = VIEWHEIGHT / 2; + if (player->deltaviewheight <= 0) + player->deltaviewheight = 1; + } + + if (player->deltaviewheight) + { + player->deltaviewheight += FRACUNIT / 4; + if (!player->deltaviewheight) + player->deltaviewheight = 1; + } + } + + if (player->chickenTics) + { + player->viewz = player->mo->z + player->viewheight - (20 * FRACUNIT); + } + else + { + player->viewz = player->mo->z + player->viewheight + bob; + } + if (player->mo->flags2 & MF2_FEETARECLIPPED + && player->playerstate != PST_DEAD + && player->mo->z <= player->mo->floorz) + { + player->viewz -= FOOTCLIPSIZE; + } + if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) + { + player->viewz = player->mo->ceilingz - 4 * FRACUNIT; + } + if (player->viewz < player->mo->floorz + 4 * FRACUNIT) + { + player->viewz = player->mo->floorz + 4 * FRACUNIT; + } +} + +/* +================= += += P_MovePlayer += +================= +*/ + +void P_MovePlayer(player_t * player) +{ + int look; + int fly; + ticcmd_t *cmd; + + cmd = &player->cmd; + player->mo->angle += (cmd->angleturn << 16); + + onground = (player->mo->z <= player->mo->floorz + || (player->mo->flags2 & MF2_ONMOBJ)); + + if (player->chickenTics) + { // Chicken speed + if (cmd->forwardmove && (onground || player->mo->flags2 & MF2_FLY)) + P_Thrust(player, player->mo->angle, cmd->forwardmove * 2500); + if (cmd->sidemove && (onground || player->mo->flags2 & MF2_FLY)) + P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2500); + } + else + { // Normal speed + if (cmd->forwardmove && (onground || player->mo->flags2 & MF2_FLY)) + P_Thrust(player, player->mo->angle, cmd->forwardmove * 2048); + if (cmd->sidemove && (onground || player->mo->flags2 & MF2_FLY)) + P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2048); + } + + if (cmd->forwardmove || cmd->sidemove) + { + if (player->chickenTics) + { + if (player->mo->state == &states[S_CHICPLAY]) + { + P_SetMobjState(player->mo, S_CHICPLAY_RUN1); + } + } + else + { + if (player->mo->state == &states[S_PLAY]) + { + P_SetMobjState(player->mo, S_PLAY_RUN1); + } + } + } + + look = cmd->lookfly & 15; + if (look > 7) + { + look -= 16; + } + if (look) + { + if (look == TOCENTER) + { + player->centering = true; + } + else + { + player->lookdir += 5 * look; + if (player->lookdir > 90 || player->lookdir < -110) + { + player->lookdir -= 5 * look; + } + } + } + if (player->centering) + { + if (player->lookdir > 0) + { + player->lookdir -= 8; + } + else if (player->lookdir < 0) + { + player->lookdir += 8; + } + if (abs(player->lookdir) < 8) + { + player->lookdir = 0; + player->centering = false; + } + } + fly = cmd->lookfly >> 4; + if (fly > 7) + { + fly -= 16; + } + if (fly && player->powers[pw_flight]) + { + if (fly != TOCENTER) + { + player->flyheight = fly * 2; + if (!(player->mo->flags2 & MF2_FLY)) + { + player->mo->flags2 |= MF2_FLY; + player->mo->flags |= MF_NOGRAVITY; + } + } + else + { + player->mo->flags2 &= ~MF2_FLY; + player->mo->flags &= ~MF_NOGRAVITY; + } + } + else if (fly > 0) + { + P_PlayerUseArtifact(player, arti_fly); + } + if (player->mo->flags2 & MF2_FLY) + { + player->mo->momz = player->flyheight * FRACUNIT; + if (player->flyheight) + { + player->flyheight /= 2; + } + } +} + +/* +================= += += P_DeathThink += +================= +*/ + +#define ANG5 (ANG90/18) + +void P_DeathThink(player_t * player) +{ + angle_t angle, delta; + int lookDelta; + + P_MovePsprites(player); + + onground = (player->mo->z <= player->mo->floorz); + if (player->mo->type == MT_BLOODYSKULL) + { // Flying bloody skull + player->viewheight = 6 * FRACUNIT; + player->deltaviewheight = 0; + //player->damagecount = 20; + if (onground) + { + if (player->lookdir < 60) + { + lookDelta = (60 - player->lookdir) / 8; + if (lookDelta < 1 && (leveltime & 1)) + { + lookDelta = 1; + } + else if (lookDelta > 6) + { + lookDelta = 6; + } + player->lookdir += lookDelta; + } + } + } + else + { // Fall to ground + player->deltaviewheight = 0; + if (player->viewheight > 6 * FRACUNIT) + player->viewheight -= FRACUNIT; + if (player->viewheight < 6 * FRACUNIT) + player->viewheight = 6 * FRACUNIT; + if (player->lookdir > 0) + { + player->lookdir -= 6; + } + else if (player->lookdir < 0) + { + player->lookdir += 6; + } + if (abs(player->lookdir) < 6) + { + player->lookdir = 0; + } + } + P_CalcHeight(player); + + if (player->attacker && player->attacker != player->mo) + { + angle = R_PointToAngle2(player->mo->x, player->mo->y, + player->attacker->x, player->attacker->y); + delta = angle - player->mo->angle; + if (delta < ANG5 || delta > (unsigned) -ANG5) + { // Looking at killer, so fade damage flash down + player->mo->angle = angle; + if (player->damagecount) + { + player->damagecount--; + } + } + else if (delta < ANG180) + player->mo->angle += ANG5; + else + player->mo->angle -= ANG5; + } + else if (player->damagecount) + { + player->damagecount--; + } + + if (player->cmd.buttons & BT_USE) + { + if (player == &players[consoleplayer]) + { + I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE)); + inv_ptr = 0; + curpos = 0; + newtorch = 0; + newtorchdelta = 0; + } + player->playerstate = PST_REBORN; + // Let the mobj know the player has entered the reborn state. Some + // mobjs need to know when it's ok to remove themselves. + player->mo->special2.i = 666; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_ChickenPlayerThink +// +//---------------------------------------------------------------------------- + +void P_ChickenPlayerThink(player_t * player) +{ + mobj_t *pmo; + + if (player->health > 0) + { // Handle beak movement + P_UpdateBeak(player, &player->psprites[ps_weapon]); + } + if (player->chickenTics & 15) + { + return; + } + pmo = player->mo; + if (!(pmo->momx + pmo->momy) && P_Random() < 160) + { // Twitch view angle + pmo->angle += P_SubRandom() << 19; + } + if ((pmo->z <= pmo->floorz) && (P_Random() < 32)) + { // Jump and noise + pmo->momz += FRACUNIT; + P_SetMobjState(pmo, S_CHICPLAY_PAIN); + return; + } + if (P_Random() < 48) + { // Just noise + S_StartSound(pmo, sfx_chicact); + } +} + +//---------------------------------------------------------------------------- +// +// FUNC P_GetPlayerNum +// +//---------------------------------------------------------------------------- + +int P_GetPlayerNum(player_t * player) +{ + int i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (player == &players[i]) + { + return (i); + } + } + return (0); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_UndoPlayerChicken +// +//---------------------------------------------------------------------------- + +boolean P_UndoPlayerChicken(player_t * player) +{ + mobj_t *fog; + mobj_t *mo; + mobj_t *pmo; + fixed_t x; + fixed_t y; + fixed_t z; + angle_t angle; + int playerNum; + weapontype_t weapon; + int oldFlags; + int oldFlags2; + + pmo = player->mo; + x = pmo->x; + y = pmo->y; + z = pmo->z; + angle = pmo->angle; + weapon = pmo->special1.i; + oldFlags = pmo->flags; + oldFlags2 = pmo->flags2; + P_SetMobjState(pmo, S_FREETARGMOBJ); + mo = P_SpawnMobj(x, y, z, MT_PLAYER); + if (P_TestMobjLocation(mo) == false) + { // Didn't fit + P_RemoveMobj(mo); + mo = P_SpawnMobj(x, y, z, MT_CHICPLAYER); + mo->angle = angle; + mo->health = player->health; + mo->special1.i = weapon; + mo->player = player; + mo->flags = oldFlags; + mo->flags2 = oldFlags2; + player->mo = mo; + player->chickenTics = 2 * 35; + return (false); + } + playerNum = P_GetPlayerNum(player); + if (playerNum != 0) + { // Set color translation + mo->flags |= playerNum << MF_TRANSSHIFT; + } + mo->angle = angle; + mo->player = player; + mo->reactiontime = 18; + if (oldFlags2 & MF2_FLY) + { + mo->flags2 |= MF2_FLY; + mo->flags |= MF_NOGRAVITY; + } + player->chickenTics = 0; + player->powers[pw_weaponlevel2] = 0; + player->health = mo->health = MAXHEALTH; + player->mo = mo; + angle >>= ANGLETOFINESHIFT; + fog = P_SpawnMobj(x + 20 * finecosine[angle], + y + 20 * finesine[angle], z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, sfx_telept); + P_PostChickenWeapon(player, weapon); + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerThink +// +//---------------------------------------------------------------------------- + +void P_PlayerThink(player_t * player) +{ + ticcmd_t *cmd; + weapontype_t newweapon; + + // No-clip cheat + if (player->cheats & CF_NOCLIP) + { + player->mo->flags |= MF_NOCLIP; + } + else + { + player->mo->flags &= ~MF_NOCLIP; + } + cmd = &player->cmd; + if (player->mo->flags & MF_JUSTATTACKED) + { // Gauntlets attack auto forward motion + cmd->angleturn = 0; + cmd->forwardmove = 0xc800 / 512; + cmd->sidemove = 0; + player->mo->flags &= ~MF_JUSTATTACKED; + } +// messageTics is above the rest of the counters so that messages will +// go away, even in death. + player->messageTics--; // Can go negative + if (!player->messageTics) + { // Refresh the screen when a message goes away + ultimatemsg = false; // clear out any chat messages. + BorderTopRefresh = true; + } + if (player->playerstate == PST_DEAD) + { + P_DeathThink(player); + return; + } + if (player->chickenTics) + { + P_ChickenPlayerThink(player); + } + // Handle movement + if (player->mo->reactiontime) + { // Player is frozen + player->mo->reactiontime--; + } + else + { + P_MovePlayer(player); + } + P_CalcHeight(player); + if (player->mo->subsector->sector->special) + { + P_PlayerInSpecialSector(player); + } + if (cmd->arti) + { // Use an artifact + if (cmd->arti == 0xff) + { + P_PlayerNextArtifact(player); + } + else + { + P_PlayerUseArtifact(player, cmd->arti); + } + } + // Check for weapon change + if (cmd->buttons & BT_SPECIAL) + { // A special event has no other buttons + cmd->buttons = 0; + } + if (cmd->buttons & BT_CHANGE) + { + // The actual changing of the weapon is done when the weapon + // psprite can do it (A_WeaponReady), so it doesn't happen in + // the middle of an attack. + newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; + if (newweapon == wp_staff && player->weaponowned[wp_gauntlets] + && !(player->readyweapon == wp_gauntlets)) + { + newweapon = wp_gauntlets; + } + if (player->weaponowned[newweapon] + && newweapon != player->readyweapon) + { + if (WeaponInShareware[newweapon] || gamemode != shareware) + { + player->pendingweapon = newweapon; + } + } + } + // Check for use + if (cmd->buttons & BT_USE) + { + if (!player->usedown) + { + P_UseLines(player); + player->usedown = true; + } + } + else + { + player->usedown = false; + } + // Chicken counter + if (player->chickenTics) + { + if (player->chickenPeck) + { // Chicken attack counter + player->chickenPeck -= 3; + } + if (!--player->chickenTics) + { // Attempt to undo the chicken + P_UndoPlayerChicken(player); + } + } + // Cycle psprites + P_MovePsprites(player); + // Other Counters + if (player->powers[pw_invulnerability]) + { + player->powers[pw_invulnerability]--; + } + if (player->powers[pw_invisibility]) + { + if (!--player->powers[pw_invisibility]) + { + player->mo->flags &= ~MF_SHADOW; + } + } + if (player->powers[pw_infrared]) + { + player->powers[pw_infrared]--; + } + if (player->powers[pw_flight]) + { + if (!--player->powers[pw_flight]) + { + // haleyjd: removed externdriver crap + if (player->mo->z != player->mo->floorz) + { + player->centering = true; + } + + player->mo->flags2 &= ~MF2_FLY; + player->mo->flags &= ~MF_NOGRAVITY; + BorderTopRefresh = true; //make sure the sprite's cleared out + } + } + if (player->powers[pw_weaponlevel2]) + { + if (!--player->powers[pw_weaponlevel2]) + { + if ((player->readyweapon == wp_phoenixrod) + && (player->psprites[ps_weapon].state + != &states[S_PHOENIXREADY]) + && (player->psprites[ps_weapon].state + != &states[S_PHOENIXUP])) + { + P_SetPsprite(player, ps_weapon, S_PHOENIXREADY); + player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2; + player->refire = 0; + } + else if ((player->readyweapon == wp_gauntlets) + || (player->readyweapon == wp_staff)) + { + player->pendingweapon = player->readyweapon; + } + BorderTopRefresh = true; + } + } + if (player->damagecount) + { + player->damagecount--; + } + if (player->bonuscount) + { + player->bonuscount--; + } + // Colormaps + if (player->powers[pw_invulnerability]) + { + if (player->powers[pw_invulnerability] > BLINKTHRESHOLD + || (player->powers[pw_invulnerability] & 8)) + { + player->fixedcolormap = INVERSECOLORMAP; + } + else + { + player->fixedcolormap = 0; + } + } + else if (player->powers[pw_infrared]) + { + if (player->powers[pw_infrared] <= BLINKTHRESHOLD) + { + if (player->powers[pw_infrared] & 8) + { + player->fixedcolormap = 0; + } + else + { + player->fixedcolormap = 1; + } + } + else if (!(leveltime & 16) && player == &players[consoleplayer]) + { + if (newtorch) + { + if (player->fixedcolormap + newtorchdelta > 7 + || player->fixedcolormap + newtorchdelta < 1 + || newtorch == player->fixedcolormap) + { + newtorch = 0; + } + else + { + player->fixedcolormap += newtorchdelta; + } + } + else + { + newtorch = (M_Random() & 7) + 1; + newtorchdelta = (newtorch == player->fixedcolormap) ? + 0 : ((newtorch > player->fixedcolormap) ? 1 : -1); + } + } + } + else + { + player->fixedcolormap = 0; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_ArtiTele +// +//---------------------------------------------------------------------------- + +void P_ArtiTele(player_t * player) +{ + int i; + int selections; + fixed_t destX; + fixed_t destY; + angle_t destAngle; + + if (deathmatch) + { + selections = deathmatch_p - deathmatchstarts; + i = P_Random() % selections; + destX = deathmatchstarts[i].x << FRACBITS; + destY = deathmatchstarts[i].y << FRACBITS; + destAngle = ANG45 * (deathmatchstarts[i].angle / 45); + } + else + { + destX = playerstarts[0].x << FRACBITS; + destY = playerstarts[0].y << FRACBITS; + destAngle = ANG45 * (playerstarts[0].angle / 45); + } + P_Teleport(player->mo, destX, destY, destAngle); + S_StartSound(NULL, sfx_wpnup); // Full volume laugh +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerNextArtifact +// +//---------------------------------------------------------------------------- + +void P_PlayerNextArtifact(player_t * player) +{ + if (player == &players[consoleplayer]) + { + inv_ptr--; + if (inv_ptr < 6) + { + curpos--; + if (curpos < 0) + { + curpos = 0; + } + } + if (inv_ptr < 0) + { + inv_ptr = player->inventorySlotNum - 1; + if (inv_ptr < 6) + { + curpos = inv_ptr; + } + else + { + curpos = 6; + } + } + player->readyArtifact = player->inventory[inv_ptr].type; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerRemoveArtifact +// +//---------------------------------------------------------------------------- + +void P_PlayerRemoveArtifact(player_t * player, int slot) +{ + int i; + player->artifactCount--; + if (!(--player->inventory[slot].count)) + { // Used last of a type - compact the artifact list + player->readyArtifact = arti_none; + player->inventory[slot].type = arti_none; + for (i = slot + 1; i < player->inventorySlotNum; i++) + { + player->inventory[i - 1] = player->inventory[i]; + } + player->inventorySlotNum--; + if (player == &players[consoleplayer]) + { // Set position markers and get next readyArtifact + inv_ptr--; + if (inv_ptr < 6) + { + curpos--; + if (curpos < 0) + { + curpos = 0; + } + } + if (inv_ptr >= player->inventorySlotNum) + { + inv_ptr = player->inventorySlotNum - 1; + } + if (inv_ptr < 0) + { + inv_ptr = 0; + } + player->readyArtifact = player->inventory[inv_ptr].type; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerUseArtifact +// +//---------------------------------------------------------------------------- + +void P_PlayerUseArtifact(player_t * player, artitype_t arti) +{ + int i; + + for (i = 0; i < player->inventorySlotNum; i++) + { + if (player->inventory[i].type == arti) + { // Found match - try to use + if (P_UseArtifact(player, arti)) + { // Artifact was used - remove it from inventory + P_PlayerRemoveArtifact(player, i); + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, sfx_artiuse); + ArtifactFlash = 4; + } + } + else + { // Unable to use artifact, advance pointer + P_PlayerNextArtifact(player); + } + break; + } + } +} + +//---------------------------------------------------------------------------- +// +// FUNC P_UseArtifact +// +// Returns true if artifact was used. +// +//---------------------------------------------------------------------------- + +boolean P_UseArtifact(player_t * player, artitype_t arti) +{ + mobj_t *mo; + angle_t angle; + + switch (arti) + { + case arti_invulnerability: + if (!P_GivePower(player, pw_invulnerability)) + { + return (false); + } + break; + case arti_invisibility: + if (!P_GivePower(player, pw_invisibility)) + { + return (false); + } + break; + case arti_health: + if (!P_GiveBody(player, 25)) + { + return (false); + } + break; + case arti_superhealth: + if (!P_GiveBody(player, 100)) + { + return (false); + } + break; + case arti_tomeofpower: + if (player->chickenTics) + { // Attempt to undo chicken + if (P_UndoPlayerChicken(player) == false) + { // Failed + P_DamageMobj(player->mo, NULL, NULL, 10000); + } + else + { // Succeeded + player->chickenTics = 0; + S_StartSound(player->mo, sfx_wpnup); + } + } + else + { + if (!P_GivePower(player, pw_weaponlevel2)) + { + return (false); + } + if (player->readyweapon == wp_staff) + { + P_SetPsprite(player, ps_weapon, S_STAFFREADY2_1); + } + else if (player->readyweapon == wp_gauntlets) + { + P_SetPsprite(player, ps_weapon, S_GAUNTLETREADY2_1); + } + } + break; + case arti_torch: + if (!P_GivePower(player, pw_infrared)) + { + return (false); + } + break; + case arti_firebomb: + angle = player->mo->angle >> ANGLETOFINESHIFT; + + // Vanilla bug here: + // Original code here looks like: + // (player->mo->flags2 & MF2_FEETARECLIPPED != 0), + // Which under C's operator precedence is: + // (player->mo->flags2 & (MF2_FEETARECLIPPED != 0)), + // Which simplifies to: + // (player->mo->flags2 & 1), + mo = P_SpawnMobj(player->mo->x + 24 * finecosine[angle], + player->mo->y + 24 * finesine[angle], + player->mo->z - + 15 * FRACUNIT * (player->mo->flags2 & 1), + MT_FIREBOMB); + mo->target = player->mo; + break; + case arti_egg: + mo = player->mo; + P_SpawnPlayerMissile(mo, MT_EGGFX); + P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 6)); + P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 6)); + P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 3)); + P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 3)); + break; + case arti_fly: + if (!P_GivePower(player, pw_flight)) + { + return (false); + } + break; + case arti_teleport: + P_ArtiTele(player); + break; + default: + return (false); + } + return (true); +} diff --git a/games/NXDoom/src/heretic/r_bsp.c b/games/NXDoom/src/heretic/r_bsp.c new file mode 100644 index 00000000000..1e9d3be7a01 --- /dev/null +++ b/games/NXDoom/src/heretic/r_bsp.c @@ -0,0 +1,489 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// R_bsp.c + +#include "doomdef.h" +#include "i_system.h" +#include "m_bbox.h" +#include "i_system.h" +#include "r_local.h" + +seg_t *curline; +side_t *sidedef; +line_t *linedef; +sector_t *frontsector, *backsector; + +drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; + +void R_StoreWallRange(int start, int stop); + +/* +==================== += += R_ClearDrawSegs += +==================== +*/ + +void R_ClearDrawSegs(void) +{ + ds_p = drawsegs; +} + +//============================================================================= + + +/* +=============================================================================== += += ClipWallSegment += += Clips the given range of columns and includes it in the new clip list +=============================================================================== +*/ + +typedef struct +{ + int first, last; +} cliprange_t; + +// We must expand MAXSEGS to the theoretical limit of the number of solidsegs +// that can be generated in a scene by the DOOM engine. This was determined by +// Lee Killough during BOOM development to be a function of the screensize. +// The simplest thing we can do, other than fix this bug, is to let the game +// render overage and then bomb out by detecting the overflow after the +// fact. -haleyjd +//#define MAXSEGS 32 +#define MAXSEGS (SCREENWIDTH / 2 + 1) + +cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg + + +void R_ClipSolidWallSegment(int first, int last) +{ + cliprange_t *next, *start; + +// find the first range that touches the range (adjacent pixels are touching) + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) + { + if (last < start->first - 1) + { // post is entirely visible (above start), so insert a new clippost + R_StoreWallRange(first, last); + next = newend; + newend++; + while (next != start) + { + *next = *(next - 1); + next--; + } + next->first = first; + next->last = last; + return; + } + + // there is a fragment above *start + R_StoreWallRange(first, start->first - 1); + start->first = first; // adjust the clip size + } + + if (last <= start->last) + return; // bottom contained in start + + next = start; + while (last >= (next + 1)->first - 1) + { + // there is a fragment between two posts + R_StoreWallRange(next->last + 1, (next + 1)->first - 1); + next++; + if (last <= next->last) + { // bottom is contained in next + start->last = next->last; // adjust the clip size + goto crunch; + } + } + + // there is a fragment after *next + R_StoreWallRange(next->last + 1, last); + start->last = last; // adjust the clip size + + +// remove start+1 to next from the clip list, +// because start now covers their area + crunch: + if (next == start) + return; // post just extended past the bottom of one post + + while (next++ != newend) // remove a post + *++start = *next; + newend = start + 1; +} + +/* +=============================================================================== += += R_ClipPassWallSegment += += Clips the given range of columns, but does not includes it in the clip list +=============================================================================== +*/ + +void R_ClipPassWallSegment(int first, int last) +{ + cliprange_t *start; + +// find the first range that touches the range (adjacent pixels are touching) + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) + { + if (last < start->first - 1) + { // post is entirely visible (above start) + R_StoreWallRange(first, last); + return; + } + + // there is a fragment above *start + R_StoreWallRange(first, start->first - 1); + } + + if (last <= start->last) + return; // bottom contained in start + + while (last >= (start + 1)->first - 1) + { + // there is a fragment between two posts + R_StoreWallRange(start->last + 1, (start + 1)->first - 1); + start++; + if (last <= start->last) + return; + } + + // there is a fragment after *next + R_StoreWallRange(start->last + 1, last); +} + + + +/* +==================== += += R_ClearClipSegs += +==================== +*/ + +void R_ClearClipSegs(void) +{ + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs + 2; +} + + +//============================================================================= + +/* +====================== += += R_AddLine += += Clips the given segment and adds any visible pieces to the line list += +====================== +*/ + +void R_AddLine(seg_t * line) +{ + int x1, x2; + angle_t angle1, angle2, span, tspan; + + curline = line; + +// OPTIMIZE: quickly reject orthogonal back sides + + angle1 = R_PointToAngle(line->v1->x, line->v1->y); + angle2 = R_PointToAngle(line->v2->x, line->v2->y); + +// +// clip to view edges +// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW) + span = angle1 - angle2; + if (span >= ANG180) + return; // back side + + rw_angle1 = angle1; // global angle needed by segcalc + angle1 -= viewangle; + angle2 -= viewangle; + + tspan = angle1 + clipangle; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return; // totally off the left edge + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return; // totally off the left edge + angle2 = -clipangle; + } + +// +// the seg is in the view range, but not necessarily visible +// + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; + if (x1 == x2) + return; // does not cross a pixel + + backsector = line->backsector; + + if (!backsector) + goto clipsolid; // single sided line + + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + goto clipsolid; // closed door + + if (backsector->ceilingheight != frontsector->ceilingheight + || backsector->floorheight != frontsector->floorheight) + goto clippass; // window + +// reject empty lines used for triggers and special events + if (backsector->ceilingpic == frontsector->ceilingpic + && backsector->floorpic == frontsector->floorpic + && backsector->lightlevel == frontsector->lightlevel + && curline->sidedef->midtexture == 0) + return; + + clippass: + R_ClipPassWallSegment(x1, x2 - 1); + return; + + clipsolid: + R_ClipSolidWallSegment(x1, x2 - 1); +} + +//============================================================================ + + +/* +=============================================================================== += += R_CheckBBox += += Returns true if some part of the bbox might be visible += +=============================================================================== +*/ + +int checkcoord[12][4] = { + {3, 0, 2, 1}, + {3, 0, 2, 0}, + {3, 1, 2, 0}, + {0}, + {2, 0, 2, 1}, + {0, 0, 0, 0}, + {3, 1, 3, 0}, + {0}, + {2, 0, 3, 1}, + {2, 1, 3, 1}, + {2, 1, 3, 0} +}; + + +boolean R_CheckBBox(fixed_t * bspcoord) +{ + int boxx, boxy, boxpos; + fixed_t x1, y1, x2, y2; + angle_t angle1, angle2, span, tspan; + cliprange_t *start; + int sx1, sx2; + +// find the corners of the box that define the edges from current viewpoint + if (viewx <= bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx < bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy >= bspcoord[BOXTOP]) + boxy = 0; + else if (viewy > bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy << 2) + boxx; + if (boxpos == 5) + return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + +// +// check clip list for an open space +// + angle1 = R_PointToAngle(x1, y1) - viewangle; + angle2 = R_PointToAngle(x2, y2) - viewangle; + + span = angle1 - angle2; + if (span >= ANG180) + return true; // sitting on a line + tspan = angle1 + clipangle; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return false; // totally off the left edge + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return false; // totally off the left edge + angle2 = -clipangle; + } + + +// find the first clippost that touches the source post (adjacent pixels are touching) + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + sx1 = viewangletox[angle1]; + sx2 = viewangletox[angle2]; + if (sx1 == sx2) + return false; // does not cross a pixel + sx2--; + + start = solidsegs; + while (start->last < sx2) + start++; + if (sx1 >= start->first && sx2 <= start->last) + return false; // the clippost contains the new span + + return true; +} + + +/* +================ += += R_Subsector += += Draw one or more segments +================ +*/ + +void R_Subsector(int num) +{ + int count; + seg_t *line; + subsector_t *sub; + +#ifdef RANGECHECK + if (num >= numsubsectors) + I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); +#endif + + sscount++; + sub = &subsectors[num]; + frontsector = sub->sector; + count = sub->numlines; + line = &segs[sub->firstline]; + + if (frontsector->floorheight < viewz) + floorplane = R_FindPlane(frontsector->floorheight, + frontsector->floorpic, + frontsector->lightlevel, + frontsector->special); + else + floorplane = NULL; + if (frontsector->ceilingheight > viewz + || frontsector->ceilingpic == skyflatnum) + ceilingplane = R_FindPlane(frontsector->ceilingheight, + frontsector->ceilingpic, + frontsector->lightlevel, 0); + else + ceilingplane = NULL; + + R_AddSprites(frontsector); + + while (count--) + { + R_AddLine(line); + line++; + } + + // check for solidsegs overflow - extremely unsatisfactory! + if(newend > &solidsegs[32]) + I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); +} + + +/* +=============================================================================== += += RenderBSPNode += +=============================================================================== +*/ + +void R_RenderBSPNode(int bspnum) +{ + node_t *bsp; + int side; + + if (bspnum & NF_SUBSECTOR) + { + if (bspnum == -1) + R_Subsector(0); + else + R_Subsector(bspnum & (~NF_SUBSECTOR)); + return; + } + + bsp = &nodes[bspnum]; + +// +// decide which side the view point is on +// + side = R_PointOnSide(viewx, viewy, bsp); + + R_RenderBSPNode(bsp->children[side]); // recursively divide front space + + if (R_CheckBBox(bsp->bbox[side ^ 1])) // possibly divide back space + R_RenderBSPNode(bsp->children[side ^ 1]); +} diff --git a/games/NXDoom/src/heretic/r_data.c b/games/NXDoom/src/heretic/r_data.c new file mode 100644 index 00000000000..04bdecc8669 --- /dev/null +++ b/games/NXDoom/src/heretic/r_data.c @@ -0,0 +1,732 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// R_data.c + +#include "doomdef.h" +#include "deh_str.h" + +#include "i_swap.h" +#include "i_system.h" +#include "m_misc.h" +#include "r_local.h" +#include "p_local.h" + + +typedef struct +{ + int originx; // block origin (allways UL), which has allready + int originy; // accounted for the patch's internal origin + int patch; +} texpatch_t; + +// a maptexturedef_t describes a rectangular texture, which is composed of one +// or more mappatch_t structures that arrange graphic patches +typedef struct +{ + char name[8]; // for switch changing, etc + short width; + short height; + short patchcount; + texpatch_t patches[1]; // [patchcount] drawn back to front + // into the cached texture +} texture_t; + + + +int firstflat, lastflat, numflats; +int firstpatch, lastpatch, numpatches; +int firstspritelump, lastspritelump, numspritelumps; + +int numtextures; +texture_t **textures; +int *texturewidthmask; +fixed_t *textureheight; // needed for texture pegging +int *texturecompositesize; +short **texturecolumnlump; +unsigned short **texturecolumnofs; +byte **texturecomposite; + +int *flattranslation; // for global animation +int *texturetranslation; // for global animation + +fixed_t *spritewidth; // needed for pre rendering +fixed_t *spriteoffset; +fixed_t *spritetopoffset; + +lighttable_t *colormaps; + + +/* +============================================================================== + + MAPTEXTURE_T CACHING + +when a texture is first needed, it counts the number of composite columns +required in the texture and allocates space for a column directory and any +new columns. The directory will simply point inside other patches if there +is only one patch in a given column, but any columns with multiple patches +will have new column_ts generated. + +============================================================================== +*/ + +/* +=================== += += R_DrawColumnInCache += += Clip and draw a column from a patch into a cached post += +=================== +*/ + +void R_DrawColumnInCache(column_t * patch, byte * cache, int originy, + int cacheheight) +{ + int count, position; + byte *source; + + while (patch->topdelta != 0xff) + { + source = (byte *) patch + 3; + count = patch->length; + position = originy + patch->topdelta; + if (position < 0) + { + count += position; + position = 0; + } + if (position + count > cacheheight) + count = cacheheight - position; + if (count > 0) + memcpy(cache + position, source, count); + + patch = (column_t *) ((byte *) patch + patch->length + 4); + } +} + + +/* +=================== += += R_GenerateComposite += +=================== +*/ + +void R_GenerateComposite(int texnum) +{ + byte *block; + texture_t *texture; + texpatch_t *patch; + patch_t *realpatch; + int x, x1, x2; + int i; + column_t *patchcol; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + block = Z_Malloc(texturecompositesize[texnum], PU_STATIC, + &texturecomposite[texnum]); + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + +// +// composite the columns together +// + for (i = 0, patch = texture->patches; i < texture->patchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1 < 0) + x = 0; + else + x = x1; + if (x2 > texture->width) + x2 = texture->width; + + for (; x < x2; x++) + { + if (collump[x] >= 0) + continue; // column does not have multiple patches + patchcol = (column_t *) ((byte *) realpatch + + LONG(realpatch->columnofs[x - x1])); + R_DrawColumnInCache(patchcol, block + colofs[x], patch->originy, + texture->height); + } + + } + +// now that the texture has been built, it is purgable + Z_ChangeTag(block, PU_CACHE); +} + + +/* +=================== += += R_GenerateLookup += +=================== +*/ + +void R_GenerateLookup(int texnum) +{ + texture_t *texture; + byte *patchcount; // [texture->width] + texpatch_t *patch; + patch_t *realpatch; + int x, x1, x2; + int i; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + + texturecomposite[texnum] = 0; // composited not created yet + texturecompositesize[texnum] = 0; + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + +// +// count the number of columns that are covered by more than one patch +// fill in the lump / offset, so columns with only a single patch are +// all done +// + patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); + memset(patchcount, 0, texture->width); + + for (i = 0, patch = texture->patches; i < texture->patchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + if (x1 < 0) + x = 0; + else + x = x1; + if (x2 > texture->width) + x2 = texture->width; + for (; x < x2; x++) + { + patchcount[x]++; + collump[x] = patch->patch; + colofs[x] = LONG(realpatch->columnofs[x - x1]) + 3; + } + } + + for (x = 0; x < texture->width; x++) + { + if (!patchcount[x]) + { + printf("R_GenerateLookup: column without a patch (%s)\n", + texture->name); + return; + } +// I_Error ("R_GenerateLookup: column without a patch"); + if (patchcount[x] > 1) + { + collump[x] = -1; // use the cached block + colofs[x] = texturecompositesize[texnum]; + if (texturecompositesize[texnum] > 0x10000 - texture->height) + I_Error("R_GenerateLookup: texture %i is >64k", texnum); + texturecompositesize[texnum] += texture->height; + } + } + + Z_Free(patchcount); +} + + +/* +================ += += R_GetColumn += +================ +*/ + +byte *R_GetColumn(int tex, int col) +{ + int lump, ofs; + + col &= texturewidthmask[tex]; + lump = texturecolumnlump[tex][col]; + ofs = texturecolumnofs[tex][col]; + if (lump > 0) + return (byte *) W_CacheLumpNum(lump, PU_CACHE) + ofs; + if (!texturecomposite[tex]) + R_GenerateComposite(tex); + return texturecomposite[tex] + ofs; +} + + +/* +================== += += R_InitTextures += += Initializes the texture list with the textures from the world map += +================== +*/ + +void R_InitTextures(void) +{ + maptexture_t *mtexture; + texture_t *texture; + mappatch_t *mpatch; + texpatch_t *patch; + int i, j; + int *maptex, *maptex2, *maptex1; + char name[9], *names, *name_p; + int *patchlookup; + int nummappatches; + int offset, maxoff, maxoff2; + int numtextures1, numtextures2; + int *directory; + const char *texture1, *texture2, *pnames; + + texture1 = DEH_String("TEXTURE1"); + texture2 = DEH_String("TEXTURE2"); + pnames = DEH_String("PNAMES"); + +// +// load the patch names from pnames.lmp +// + names = W_CacheLumpName(pnames, PU_STATIC); + nummappatches = LONG(*((int *) names)); + name_p = names + 4; + patchlookup = Z_Malloc(nummappatches * sizeof(*patchlookup), PU_STATIC, NULL); + for (i = 0; i < nummappatches; i++) + { + M_StringCopy(name, name_p + i * 8, sizeof(name)); + patchlookup[i] = W_CheckNumForName(name); + } + W_ReleaseLumpName(pnames); + +// +// load the map texture definitions from textures.lmp +// + maptex = maptex1 = W_CacheLumpName(texture1, PU_STATIC); + numtextures1 = LONG(*maptex); + maxoff = W_LumpLength(W_GetNumForName(texture1)); + directory = maptex + 1; + + if (W_CheckNumForName(texture2) != -1) + { + maptex2 = W_CacheLumpName(texture2, PU_STATIC); + numtextures2 = LONG(*maptex2); + maxoff2 = W_LumpLength(W_GetNumForName(texture2)); + } + else + { + maptex2 = NULL; + numtextures2 = 0; + maxoff2 = 0; + } + numtextures = numtextures1 + numtextures2; + + // + // Init the startup thermometer at this point... + // + { + int start, end; + int spramount; + start = W_GetNumForName(DEH_String("S_START")); + end = W_GetNumForName(DEH_String("S_END")); + spramount = end - start + 1; + InitThermo(spramount + numtextures + 6); + } + + textures = Z_Malloc(numtextures * sizeof(texture_t *), PU_STATIC, 0); + texturecolumnlump = Z_Malloc(numtextures * sizeof(short *), PU_STATIC, 0); + texturecolumnofs = Z_Malloc(numtextures * sizeof(unsigned short *), PU_STATIC, 0); + texturecomposite = Z_Malloc(numtextures * sizeof(byte *), PU_STATIC, 0); + texturecompositesize = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); + texturewidthmask = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); + textureheight = Z_Malloc(numtextures * sizeof(fixed_t), PU_STATIC, 0); + + for (i = 0; i < numtextures; i++, directory++) + { +#ifdef __NEXT__ + if (!(i & 63)) + printf("."); +#else + IncThermo(); +#endif + if (i == numtextures1) + { // start looking in second texture file + maptex = maptex2; + maxoff = maxoff2; + directory = maptex + 1; + } + + offset = LONG(*directory); + if (offset > maxoff) + I_Error("R_InitTextures: bad texture directory"); + mtexture = (maptexture_t *) ((byte *) maptex + offset); + texture = textures[i] = Z_Malloc(sizeof(texture_t) + + + sizeof(texpatch_t) * + (SHORT(mtexture->patchcount) - 1), + PU_STATIC, 0); + texture->width = SHORT(mtexture->width); + texture->height = SHORT(mtexture->height); + texture->patchcount = SHORT(mtexture->patchcount); + memcpy(texture->name, mtexture->name, sizeof(texture->name)); + mpatch = &mtexture->patches[0]; + patch = &texture->patches[0]; + for (j = 0; j < texture->patchcount; j++, mpatch++, patch++) + { + patch->originx = SHORT(mpatch->originx); + patch->originy = SHORT(mpatch->originy); + patch->patch = patchlookup[SHORT(mpatch->patch)]; + if (patch->patch == -1) + I_Error("R_InitTextures: Missing patch in texture %s", + texture->name); + } + texturecolumnlump[i] = Z_Malloc(texture->width * sizeof(short), + PU_STATIC, 0); + texturecolumnofs[i] = Z_Malloc(texture->width * sizeof(short), + PU_STATIC, 0); + j = 1; + while (j * 2 <= texture->width) + j <<= 1; + texturewidthmask[i] = j - 1; + textureheight[i] = texture->height << FRACBITS; + } + + Z_Free(patchlookup); + + W_ReleaseLumpName(texture1); + if (maptex2) + { + W_ReleaseLumpName(texture2); + } + +// +// precalculate whatever possible +// + for (i = 0; i < numtextures; i++) + { + R_GenerateLookup(i); + CheckAbortStartup(); + } + +// +// translation table for global animation +// + texturetranslation = Z_Malloc((numtextures + 1) * sizeof(int), PU_STATIC, 0); + for (i = 0; i < numtextures; i++) + texturetranslation[i] = i; +} + + +/* +================ += += R_InitFlats += +================= +*/ + +void R_InitFlats(void) +{ + int i; + + firstflat = W_GetNumForName(DEH_String("F_START")) + 1; + lastflat = W_GetNumForName(DEH_String("F_END")) - 1; + numflats = lastflat - firstflat + 1; + +// translation table for global animation + flattranslation = Z_Malloc((numflats + 1) * sizeof(int), PU_STATIC, 0); + for (i = 0; i < numflats; i++) + flattranslation[i] = i; +} + + +/* +================ += += R_InitSpriteLumps += += Finds the width and hoffset of all sprites in the wad, so the sprite doesn't += need to be cached just for the header during rendering +================= +*/ + +void R_InitSpriteLumps(void) +{ + int i; + patch_t *patch; + + firstspritelump = W_GetNumForName(DEH_String("S_START")) + 1; + lastspritelump = W_GetNumForName(DEH_String("S_END")) - 1; + numspritelumps = lastspritelump - firstspritelump + 1; + spritewidth = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); + spriteoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); + spritetopoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); + + for (i = 0; i < numspritelumps; i++) + { +#ifdef __NEXT__ + if (!(i & 63)) + printf("."); +#else + IncThermo(); +#endif + patch = W_CacheLumpNum(firstspritelump + i, PU_CACHE); + spritewidth[i] = SHORT(patch->width) << FRACBITS; + spriteoffset[i] = SHORT(patch->leftoffset) << FRACBITS; + spritetopoffset[i] = SHORT(patch->topoffset) << FRACBITS; + } +} + + +/* +================ += += R_InitColormaps += +================= +*/ + +void R_InitColormaps(void) +{ + int lump, length; +// +// load in the light tables +// 256 byte align tables +// + lump = W_GetNumForName(DEH_String("COLORMAP")); + length = W_LumpLength(lump); + colormaps = Z_Malloc(length, PU_STATIC, 0); + W_ReadLump(lump, colormaps); +} + + +/* +================ += += R_InitData += += Locates all the lumps that will be used by all views += Must be called after W_Init +================= +*/ + +void R_InitData(void) +{ + //tprintf("\nR_InitTextures ", 0); + R_InitTextures(); + printf ("."); + //tprintf("R_InitFlats\n", 0); + R_InitFlats(); + IncThermo(); + printf ("."); + //tprintf("R_InitSpriteLumps ", 0); + R_InitSpriteLumps(); + IncThermo(); + printf ("."); + R_InitColormaps(); +} + + +//============================================================================= + +/* +================ += += R_FlatNumForName += +================ +*/ + +int R_FlatNumForName(const char *name) +{ + int i; + char namet[9]; + + i = W_CheckNumForName(name); + if (i == -1) + { + namet[8] = 0; + memcpy(namet, name, 8); + I_Error("R_FlatNumForName: %s not found", namet); + } + return i - firstflat; +} + + +/* +================ += += R_CheckTextureNumForName += +================ +*/ + +int R_CheckTextureNumForName(const char *name) +{ + int i; + + if (name[0] == '-') // no texture marker + return 0; + + for (i = 0; i < numtextures; i++) + if (!strncasecmp(textures[i]->name, name, 8)) + return i; + + return -1; +} + + +/* +================ += += R_TextureNumForName += +================ +*/ + +int R_TextureNumForName(const char *name) +{ + int i; + //char namet[9]; + + i = R_CheckTextureNumForName(name); + if (i == -1) + I_Error("R_TextureNumForName: %s not found", name); + + return i; +} + + +/* +================= += += R_PrecacheLevel += += Preloads all relevent graphics for the level +================= +*/ + +int flatmemory, texturememory, spritememory; + +void R_PrecacheLevel(void) +{ + char *flatpresent; + char *texturepresent; + char *spritepresent; + int i, j, k, lump; + texture_t *texture; + thinker_t *th; + spriteframe_t *sf; + + if (demoplayback) + return; + +// +// precache flats +// + flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); + memset(flatpresent, 0, numflats); + for (i = 0; i < numsectors; i++) + { + flatpresent[sectors[i].floorpic] = 1; + flatpresent[sectors[i].ceilingpic] = 1; + } + + flatmemory = 0; + for (i = 0; i < numflats; i++) + if (flatpresent[i]) + { + lump = firstflat + i; + flatmemory += lumpinfo[lump]->size; + W_CacheLumpNum(lump, PU_CACHE); + } + + Z_Free(flatpresent); + +// +// precache textures +// + texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); + memset(texturepresent, 0, numtextures); + + for (i = 0; i < numsides; i++) + { + texturepresent[sides[i].toptexture] = 1; + texturepresent[sides[i].midtexture] = 1; + texturepresent[sides[i].bottomtexture] = 1; + } + + texturepresent[skytexture] = 1; + + texturememory = 0; + for (i = 0; i < numtextures; i++) + { + if (!texturepresent[i]) + continue; + texture = textures[i]; + for (j = 0; j < texture->patchcount; j++) + { + lump = texture->patches[j].patch; + texturememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump, PU_CACHE); + } + } + + Z_Free(texturepresent); + +// +// precache sprites +// + spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); + memset(spritepresent, 0, numsprites); + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function == P_MobjThinker) + spritepresent[((mobj_t *) th)->sprite] = 1; + } + + spritememory = 0; + for (i = 0; i < numsprites; i++) + { + if (!spritepresent[i]) + continue; + for (j = 0; j < sprites[i].numframes; j++) + { + sf = &sprites[i].spriteframes[j]; + for (k = 0; k < 8; k++) + { + lump = firstspritelump + sf->lump[k]; + spritememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump, PU_CACHE); + } + } + } + + Z_Free(spritepresent); +} diff --git a/games/NXDoom/src/heretic/r_draw.c b/games/NXDoom/src/heretic/r_draw.c new file mode 100644 index 00000000000..4760cd59aca --- /dev/null +++ b/games/NXDoom/src/heretic/r_draw.c @@ -0,0 +1,490 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// R_draw.c + +#include "doomdef.h" +#include "deh_str.h" +#include "r_local.h" +#include "i_video.h" +#include "v_video.h" + +/* + +All drawing to the view buffer is accomplished in this file. The other refresh +files only know about ccordinates, not the architecture of the frame buffer. + +*/ + +byte *viewimage; +int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; +byte *ylookup[MAXHEIGHT]; +int columnofs[MAXWIDTH]; +byte translations[3][256]; // color tables for different players + +/* +================== += += R_DrawColumn += += Source is the top of the column to scale += +================== +*/ + +lighttable_t *dc_colormap; +int dc_x; +int dc_yl; +int dc_yh; +fixed_t dc_iscale; +fixed_t dc_texturemid; +byte *dc_source; // first pixel in a column (possibly virtual) + +int dccount; // just for profiling + +void R_DrawColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +void R_DrawColumnLow(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +// dccount++; +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +// Translucent column draw - blended with background using tinttable. + +void R_DrawTLColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + if (!dc_yl) + dc_yl = 1; + if (dc_yh == viewheight - 1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = + tinttable[((*dest) << 8) + + dc_colormap[dc_source[(frac >> FRACBITS) & 127]]]; + + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +/* +======================== += += R_DrawTranslatedColumn += +======================== +*/ + +byte *dc_translation; +byte *translationtables; + +void R_DrawTranslatedColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +void R_DrawTranslatedTLColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = tinttable[((*dest) << 8) + + + dc_colormap[dc_translation + [dc_source[frac >> FRACBITS]]]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +//-------------------------------------------------------------------------- +// +// PROC R_InitTranslationTables +// +//-------------------------------------------------------------------------- + +void R_InitTranslationTables(void) +{ + int i; + + V_LoadTintTable(); + + // Allocate translation tables + translationtables = Z_Malloc(256 * 3, PU_STATIC, 0); + + // Fill out the translation tables + for (i = 0; i < 256; i++) + { + if (i >= 225 && i <= 240) + { + translationtables[i] = 114 + (i - 225); // yellow + translationtables[i + 256] = 145 + (i - 225); // red + translationtables[i + 512] = 190 + (i - 225); // blue + } + else + { + translationtables[i] = translationtables[i + 256] + = translationtables[i + 512] = i; + } + } +} + +/* +================ += += R_DrawSpan += +================ +*/ + +int ds_y; +int ds_x1; +int ds_x2; +lighttable_t *ds_colormap; +fixed_t ds_xfrac; +fixed_t ds_yfrac; +fixed_t ds_xstep; +fixed_t ds_ystep; +byte *ds_source; // start of a 64*64 tile image + +int dscount; // just for profiling + +void R_DrawSpan(void) +{ + fixed_t xfrac, yfrac; + byte *dest; + int count, spot; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH + || (unsigned) ds_y > SCREENHEIGHT) + I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); +// dscount++; +#endif + + xfrac = ds_xfrac; + yfrac = ds_yfrac; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1; + do + { + spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); + *dest++ = ds_colormap[ds_source[spot]]; + xfrac += ds_xstep; + yfrac += ds_ystep; + } + while (count--); +} + +void R_DrawSpanLow(void) +{ + fixed_t xfrac, yfrac; + byte *dest; + int count, spot; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH + || (unsigned) ds_y > SCREENHEIGHT) + I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); +// dscount++; +#endif + + xfrac = ds_xfrac; + yfrac = ds_yfrac; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1; + do + { + spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); + *dest++ = ds_colormap[ds_source[spot]]; + xfrac += ds_xstep; + yfrac += ds_ystep; + } + while (count--); +} + + + +/* +================ += += R_InitBuffer += +================= +*/ + +void R_InitBuffer(int width, int height) +{ + int i; + + viewwindowx = (SCREENWIDTH - width) >> 1; + for (i = 0; i < width; i++) + columnofs[i] = viewwindowx + i; + if (width == SCREENWIDTH) + viewwindowy = 0; + else + viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1; + for (i = 0; i < height; i++) + ylookup[i] = I_VideoBuffer + (i + viewwindowy) * SCREENWIDTH; +} + + +/* +================== += += R_DrawViewBorder += += Draws the border around the view for different size windows +================== +*/ + +boolean BorderNeedRefresh; + +void R_DrawViewBorder(void) +{ + byte *src, *dest; + int x, y; + + if (scaledviewwidth == SCREENWIDTH) + return; + + if (gamemode == shareware) + { + src = W_CacheLumpName(DEH_String("FLOOR04"), PU_CACHE); + } + else + { + src = W_CacheLumpName(DEH_String("FLAT513"), PU_CACHE); + } + dest = I_VideoBuffer; + + for (y = 0; y < SCREENHEIGHT - SBARHEIGHT; y++) + { + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } + for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) + { + V_DrawPatch(x, viewwindowy - 4, + W_CacheLumpName(DEH_String("bordt"), PU_CACHE)); + V_DrawPatch(x, viewwindowy + viewheight, + W_CacheLumpName(DEH_String("bordb"), PU_CACHE)); + } + for (y = viewwindowy; y < viewwindowy + viewheight; y += 16) + { + V_DrawPatch(viewwindowx - 4, y, + W_CacheLumpName(DEH_String("bordl"), PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, y, + W_CacheLumpName(DEH_String("bordr"), PU_CACHE)); + } + V_DrawPatch(viewwindowx - 4, viewwindowy - 4, + W_CacheLumpName(DEH_String("bordtl"), PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, + W_CacheLumpName(DEH_String("bordtr"), PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy + viewheight, + W_CacheLumpName(DEH_String("bordbr"), PU_CACHE)); + V_DrawPatch(viewwindowx - 4, viewwindowy + viewheight, + W_CacheLumpName(DEH_String("bordbl"), PU_CACHE)); +} + +/* +================== += += R_DrawTopBorder += += Draws the top border around the view for different size windows +================== +*/ + +boolean BorderTopRefresh; + +void R_DrawTopBorder(void) +{ + byte *src, *dest; + int x, y; + + if (scaledviewwidth == SCREENWIDTH) + return; + + if (gamemode == shareware) + { + src = W_CacheLumpName(DEH_String("FLOOR04"), PU_CACHE); + } + else + { + src = W_CacheLumpName(DEH_String("FLAT513"), PU_CACHE); + } + dest = I_VideoBuffer; + + for (y = 0; y < 30; y++) + { + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } + if (viewwindowy < 25) + { + for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) + { + V_DrawPatch(x, viewwindowy - 4, + W_CacheLumpName(DEH_String("bordt"), PU_CACHE)); + } + V_DrawPatch(viewwindowx - 4, viewwindowy, + W_CacheLumpName(DEH_String("bordl"), PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy, + W_CacheLumpName(DEH_String("bordr"), PU_CACHE)); + V_DrawPatch(viewwindowx - 4, viewwindowy + 16, + W_CacheLumpName(DEH_String("bordl"), PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy + 16, + W_CacheLumpName(DEH_String("bordr"), PU_CACHE)); + + V_DrawPatch(viewwindowx - 4, viewwindowy - 4, + W_CacheLumpName(DEH_String("bordtl"), PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, + W_CacheLumpName(DEH_String("bordtr"), PU_CACHE)); + } +} diff --git a/games/NXDoom/src/heretic/r_local.h b/games/NXDoom/src/heretic/r_local.h new file mode 100644 index 00000000000..cf58ed18522 --- /dev/null +++ b/games/NXDoom/src/heretic/r_local.h @@ -0,0 +1,487 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// R_local.h + +#ifndef __R_LOCAL__ +#define __R_LOCAL__ + +#include "i_video.h" +#include "v_patch.h" + +#define ANGLETOSKYSHIFT 22 // sky map is 256*128*4 maps + +#define BASEYCENTER 100 + +#define MAXWIDTH 1120 +#define MAXHEIGHT 832 + +#define PI 3.141592657 + +#define CENTERY (SCREENHEIGHT/2) + +#define MINZ (FRACUNIT*4) + +#define FIELDOFVIEW 2048 // fineangles in the SCREENWIDTH wide window + +// +// lighting constants +// +#define LIGHTLEVELS 16 +#define LIGHTSEGSHIFT 4 +#define MAXLIGHTSCALE 48 +#define LIGHTSCALESHIFT 12 +#define MAXLIGHTZ 128 +#define LIGHTZSHIFT 20 +#define NUMCOLORMAPS 32 // number of diminishing +#define INVERSECOLORMAP 32 + +/* +============================================================================== + + INTERNAL MAP TYPES + +============================================================================== +*/ + +//================ used by play and refresh + +typedef struct +{ + fixed_t x, y; +} vertex_t; + +struct line_s; + +typedef struct +{ + fixed_t floorheight, ceilingheight; + short floorpic, ceilingpic; + short lightlevel; + short special, tag; + + int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 + mobj_t *soundtarget; // thing that made a sound (or null) + + int blockbox[4]; // mapblock bounding box for height changes + degenmobj_t soundorg; // for any sounds played by the sector + + int validcount; // if == validcount, already checked + mobj_t *thinglist; // list of mobjs in sector + void *specialdata; // thinker_t for reversable actions + int linecount; + struct line_s **lines; // [linecount] size +} sector_t; + +typedef struct +{ + fixed_t textureoffset; // add this to the calculated texture col + fixed_t rowoffset; // add this to the calculated texture top + short toptexture, bottomtexture, midtexture; + sector_t *sector; +} side_t; + +typedef enum +{ ST_HORIZONTAL, ST_VERTICAL, ST_POSITIVE, ST_NEGATIVE } slopetype_t; + +typedef struct line_s +{ + vertex_t *v1, *v2; + fixed_t dx, dy; // v2 - v1 for side checking + short flags; + short special, tag; + short sidenum[2]; // sidenum[1] will be -1 if one sided + fixed_t bbox[4]; + slopetype_t slopetype; // to aid move clipping + sector_t *frontsector, *backsector; + int validcount; // if == validcount, already checked + void *specialdata; // thinker_t for reversable actions +} line_t; + + +typedef struct subsector_s +{ + sector_t *sector; + short numlines; + short firstline; +} subsector_t; + +typedef struct +{ + vertex_t *v1, *v2; + fixed_t offset; + angle_t angle; + side_t *sidedef; + line_t *linedef; + sector_t *frontsector; + sector_t *backsector; // NULL for one sided lines +} seg_t; + +typedef struct +{ + fixed_t x, y, dx, dy; // partition line + fixed_t bbox[2][4]; // bounding box for each child + unsigned short children[2]; // if NF_SUBSECTOR its a subsector +} node_t; + + +/* +============================================================================== + + OTHER TYPES + +============================================================================== +*/ + +typedef byte lighttable_t; // this could be wider for >8 bit display + +#define MAXVISPLANES 128 +#define MAXOPENINGS SCREENWIDTH*64 + +typedef struct +{ + fixed_t height; + int picnum; + int lightlevel; + int special; + int minx, maxx; + byte pad1; // leave pads for [minx-1]/[maxx+1] + byte top[SCREENWIDTH]; + byte pad2; + byte pad3; + byte bottom[SCREENWIDTH]; + byte pad4; +} visplane_t; + +typedef struct drawseg_s +{ + seg_t *curline; + int x1, x2; + fixed_t scale1, scale2, scalestep; + int silhouette; // 0=none, 1=bottom, 2=top, 3=both + fixed_t bsilheight; // don't clip sprites above this + fixed_t tsilheight; // don't clip sprites below this +// pointers to lists for sprite clipping + short *sprtopclip; // adjusted so [x1] is first value + short *sprbottomclip; // adjusted so [x1] is first value + short *maskedtexturecol; // adjusted so [x1] is first value +} drawseg_t; + +#define SIL_NONE 0 +#define SIL_BOTTOM 1 +#define SIL_TOP 2 +#define SIL_BOTH 3 + +#define MAXDRAWSEGS 256 + +// A vissprite_t is a thing that will be drawn during a refresh +typedef struct vissprite_s +{ + struct vissprite_s *prev, *next; + int x1, x2; + fixed_t gx, gy; // for line side calculation + fixed_t gz, gzt; // global bottom / top for silhouette clipping + fixed_t startfrac; // horizontal position of x1 + fixed_t scale; + fixed_t xiscale; // negative if flipped + fixed_t texturemid; + int patch; + lighttable_t *colormap; + int mobjflags; // for color translation and shadow draw + boolean psprite; // true if psprite + fixed_t footclip; // foot clipping +} vissprite_t; + + +extern visplane_t *floorplane, *ceilingplane; + +// Sprites are patches with a special naming convention so they can be +// recognized by R_InitSprites. The sprite and frame specified by a +// thing_t is range checked at run time. +// a sprite is a patch_t that is assumed to represent a three dimensional +// object and may have multiple rotations pre drawn. Horizontal flipping +// is used to save space. Some sprites will only have one picture used +// for all views. + +typedef struct +{ + boolean rotate; // if false use 0 for any position + short lump[8]; // lump to use for view angles 0-7 + byte flip[8]; // flip (1 = flip) to use for view angles 0-7 +} spriteframe_t; + +typedef struct +{ + int numframes; + spriteframe_t *spriteframes; +} spritedef_t; + +extern spritedef_t *sprites; +extern int numsprites; + +//============================================================================= + +extern int numvertexes; +extern vertex_t *vertexes; + +extern int numsegs; +extern seg_t *segs; + +extern int numsectors; +extern sector_t *sectors; + +extern int numsubsectors; +extern subsector_t *subsectors; + +extern int numnodes; +extern node_t *nodes; + +extern int numlines; +extern line_t *lines; + +extern int numsides; +extern side_t *sides; + + + +extern fixed_t viewx, viewy, viewz; +extern angle_t viewangle; +extern player_t *viewplayer; + + +extern angle_t clipangle; + +extern int viewangletox[FINEANGLES / 2]; +extern angle_t xtoviewangle[SCREENWIDTH + 1]; + +extern fixed_t rw_distance; +extern angle_t rw_normalangle; + +// +// R_main.c +// +extern int viewwidth, viewheight, viewwindowx, viewwindowy; +extern int scaledviewwidth; +extern int centerx, centery; +extern int flyheight; +extern fixed_t centerxfrac; +extern fixed_t centeryfrac; +extern fixed_t projection; + +extern int validcount; + +extern int sscount, linecount, loopcount; +extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +extern lighttable_t *scalelightfixed[MAXLIGHTSCALE]; +extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; + +extern int extralight; +extern lighttable_t *fixedcolormap; + +extern fixed_t viewcos, viewsin; + +extern int detailshift; // 0 = high, 1 = low + +extern int detailLevel; +extern int screenblocks; + +extern void (*colfunc) (void); +extern void (*basecolfunc) (void); +extern void (*tlcolfunc) (void); +extern void (*spanfunc) (void); + +int R_PointOnSide(fixed_t x, fixed_t y, node_t * node); +int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line); +angle_t R_PointToAngle(fixed_t x, fixed_t y); +angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); +fixed_t R_PointToDist(fixed_t x, fixed_t y); +fixed_t R_ScaleFromGlobalAngle(angle_t visangle); +subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); +void R_AddPointToBox(int x, int y, fixed_t * box); +void R_ExecuteSetViewSize(void); + + +// +// R_bsp.c +// +extern seg_t *curline; +extern side_t *sidedef; +extern line_t *linedef; +extern sector_t *frontsector, *backsector; + +extern int rw_x; +extern int rw_stopx; + +extern boolean segtextured; +extern boolean markfloor; // false if the back side is the same plane +extern boolean markceiling; +extern boolean skymap; + +extern drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; + +extern lighttable_t **hscalelight, **vscalelight, **dscalelight; + +typedef void (*drawfunc_t) (int start, int stop); +void R_ClearClipSegs(void); + +void R_ClearDrawSegs(void); +void R_InitSkyMap(void); +void R_RenderBSPNode(int bspnum); + +// +// R_segs.c +// +extern int rw_angle1; // angle to line origin +extern lighttable_t **walllights; + + +void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2); + + +// +// R_plane.c +// +typedef void (*planefunction_t) (int top, int bottom); +extern planefunction_t floorfunc, ceilingfunc; + +extern int skyflatnum; + +extern short openings[MAXOPENINGS], *lastopening; + +extern short floorclip[SCREENWIDTH]; +extern short ceilingclip[SCREENWIDTH]; + +extern fixed_t yslope[SCREENHEIGHT]; +extern fixed_t distscale[SCREENWIDTH]; + +void R_InitPlanes(void); +void R_ClearPlanes(void); +void R_MapPlane(int y, int x1, int x2); +void R_MakeSpans(int x, int t1, int b1, int t2, int b2); +void R_DrawPlanes(void); + +visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel, + int special); +visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop); + + +// +// R_debug.m +// +extern int drawbsp; + +// +// R_data.c +// +extern fixed_t *textureheight; // needed for texture pegging +extern fixed_t *spritewidth; // needed for pre rendering (fracs) +extern fixed_t *spriteoffset; +extern fixed_t *spritetopoffset; +extern lighttable_t *colormaps; +extern int firstflat; +extern int numflats; + +extern int *flattranslation; // for global animation +extern int *texturetranslation; // for global animation + +extern int firstspritelump, lastspritelump, numspritelumps; + +extern int columnofs[MAXWIDTH]; + + +byte *R_GetColumn(int tex, int col); +void R_InitData(void); +void R_PrecacheLevel(void); + + +// +// R_things.c +// +#define MAXVISSPRITES 128 + +extern vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; +extern vissprite_t vsprsortedhead; + +// constant arrays used for psprite clipping and initializing clipping +extern short negonearray[SCREENWIDTH]; +extern short screenheightarray[SCREENWIDTH]; + +// vars for R_DrawMaskedColumn +extern short *mfloorclip; +extern short *mceilingclip; +extern fixed_t spryscale; +extern fixed_t sprtopscreen; +extern fixed_t sprbotscreen; + +extern fixed_t pspritescale, pspriteiscale; + + +void R_DrawMaskedColumn(column_t * column, signed int baseclip); + + +void R_SortVisSprites(void); + +void R_AddSprites(sector_t * sec); +void R_AddPSprites(void); +void R_DrawSprites(void); +void R_InitSprites(const char **namelist); +void R_ClearSprites(void); +void R_DrawMasked(void); +void R_ClipVisSprite(vissprite_t * vis, int xl, int xh); + +//============================================================================= +// +// R_draw.c +// +//============================================================================= + +extern lighttable_t *dc_colormap; +extern int dc_x; +extern int dc_yl; +extern int dc_yh; +extern fixed_t dc_iscale; +extern fixed_t dc_texturemid; +extern byte *dc_source; // first pixel in a column +extern byte *ylookup[MAXHEIGHT]; + + +void R_DrawColumn(void); +void R_DrawColumnLow(void); +void R_DrawTLColumn(void); +void R_DrawTLColumnLow(void); +void R_DrawTranslatedColumn(void); +void R_DrawTranslatedTLColumn(void); +void R_DrawTranslatedColumnLow(void); + +extern int ds_y; +extern int ds_x1; +extern int ds_x2; +extern lighttable_t *ds_colormap; +extern fixed_t ds_xfrac; +extern fixed_t ds_yfrac; +extern fixed_t ds_xstep; +extern fixed_t ds_ystep; +extern byte *ds_source; // start of a 64*64 tile image + +extern byte *translationtables; +extern byte *dc_translation; + +void R_DrawSpan(void); +void R_DrawSpanLow(void); + +void R_InitBuffer(int width, int height); +void R_InitTranslationTables(void); + +#endif // __R_LOCAL__ diff --git a/games/NXDoom/src/heretic/r_main.c b/games/NXDoom/src/heretic/r_main.c new file mode 100644 index 00000000000..1ff6a68d882 --- /dev/null +++ b/games/NXDoom/src/heretic/r_main.c @@ -0,0 +1,818 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// R_main.c + +#include +#include +#include "doomdef.h" +#include "m_bbox.h" +#include "r_local.h" +#include "tables.h" + +int viewangleoffset; + +// haleyjd: removed WATCOMC + +int validcount = 1; // increment every time a check is made + +lighttable_t *fixedcolormap; + +int centerx, centery; +fixed_t centerxfrac, centeryfrac; +fixed_t projection; + +int framecount; // just for profiling purposes + +int sscount, linecount, loopcount; + +fixed_t viewx, viewy, viewz; +angle_t viewangle; +fixed_t viewcos, viewsin; +player_t *viewplayer; + +int detailshift; // 0 = high, 1 = low + +// +// precalculated math tables +// +angle_t clipangle; + +// The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view +// angles to screen X coordinates, flattening the arc to a flat projection +// plane. There will be many angles mapped to the same X. +int viewangletox[FINEANGLES / 2]; + +// The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle +// that maps back to x ranges from clipangle to -clipangle +angle_t xtoviewangle[SCREENWIDTH + 1]; + +lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +lighttable_t *scalelightfixed[MAXLIGHTSCALE]; +lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; + +int extralight; // bumped light from gun blasts + +void (*colfunc) (void); +void (*basecolfunc) (void); +void (*tlcolfunc) (void); +void (*transcolfunc) (void); +void (*spanfunc) (void); + +/* +=================== += += R_AddPointToBox += +=================== +*/ + +void R_AddPointToBox(int x, int y, fixed_t * box) +{ + if (x < box[BOXLEFT]) + box[BOXLEFT] = x; + if (x > box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y < box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + if (y > box[BOXTOP]) + box[BOXTOP] = y; +} + + + +/* +=============================================================================== += += R_PointOnSide += += Returns side 0 (front) or 1 (back) +=============================================================================== +*/ + +int R_PointOnSide(fixed_t x, fixed_t y, node_t * node) +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!node->dx) + { + if (x <= node->x) + return node->dy > 0; + return node->dy < 0; + } + if (!node->dy) + { + if (y <= node->y) + return node->dx < 0; + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + +// try to quickly decide by looking at sign bits + if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) + { + if ((node->dy ^ dx) & 0x80000000) + return 1; // (left is negative) + return 0; + } + + left = FixedMul(node->dy >> FRACBITS, dx); + right = FixedMul(dy, node->dx >> FRACBITS); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line) +{ + fixed_t lx, ly; + fixed_t ldx, ldy; + fixed_t dx, dy; + fixed_t left, right; + + lx = line->v1->x; + ly = line->v1->y; + + ldx = line->v2->x - lx; + ldy = line->v2->y - ly; + + if (!ldx) + { + if (x <= lx) + return ldy > 0; + return ldy < 0; + } + if (!ldy) + { + if (y <= ly) + return ldx < 0; + return ldx > 0; + } + + dx = (x - lx); + dy = (y - ly); + +// try to quickly decide by looking at sign bits + if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) + { + if ((ldy ^ dx) & 0x80000000) + return 1; // (left is negative) + return 0; + } + + left = FixedMul(ldy >> FRACBITS, dx); + right = FixedMul(dy, ldx >> FRACBITS); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +/* +=============================================================================== += += R_PointToAngle += +=============================================================================== +*/ + +angle_t R_PointToAngle(fixed_t x, fixed_t y) +{ + x -= viewx; + y -= viewy; + if ((!x) && (!y)) + return 0; + if (x >= 0) + { // x >=0 + if (y >= 0) + { // y>= 0 + if (x > y) + return tantoangle[SlopeDiv(y, x)]; // octant 0 + else + return ANG90 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 1 + } + else + { // y<0 + y = -y; + if (x > y) + return -tantoangle[SlopeDiv(y, x)]; // octant 8 + else + return ANG270 + tantoangle[SlopeDiv(x, y)]; // octant 7 + } + } + else + { // x<0 + x = -x; + if (y >= 0) + { // y>= 0 + if (x > y) + return ANG180 - 1 - tantoangle[SlopeDiv(y, x)]; // octant 3 + else + return ANG90 + tantoangle[SlopeDiv(x, y)]; // octant 2 + } + else + { // y<0 + y = -y; + if (x > y) + return ANG180 + tantoangle[SlopeDiv(y, x)]; // octant 4 + else + return ANG270 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 5 + } + } + + return 0; +} + + +angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) +{ + viewx = x1; + viewy = y1; + return R_PointToAngle(x2, y2); +} + + +fixed_t R_PointToDist(fixed_t x, fixed_t y) +{ + int angle; + fixed_t dx, dy, temp; + fixed_t dist; + + dx = abs(x - viewx); + dy = abs(y - viewy); + + if (dy > dx) + { + temp = dx; + dx = dy; + dy = temp; + } + + angle = + (tantoangle[FixedDiv(dy, dx) >> DBITS] + ANG90) >> ANGLETOFINESHIFT; + + dist = FixedDiv(dx, finesine[angle]); // use as cosine + + return dist; +} + + + +/* +================= += += R_InitPointToAngle += +================= +*/ + +void R_InitPointToAngle(void) +{ +// now getting from tables.c +#if 0 + int i; + long t; + float f; +// +// slope (tangent) to angle lookup +// + for (i = 0; i <= SLOPERANGE; i++) + { + f = atan((float) i / SLOPERANGE) / (3.141592657 * 2); + t = 0xffffffff * f; + tantoangle[i] = t; + } +#endif +} + +//============================================================================= + +/* +================ += += R_ScaleFromGlobalAngle += += Returns the texture mapping scale for the current line at the given angle += rw_distance must be calculated first +================ +*/ + +fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +{ + fixed_t scale; + int anglea, angleb; + int sinea, sineb; + fixed_t num, den; + +#if 0 + { + fixed_t dist, z; + fixed_t sinv, cosv; + + sinv = finesine[(visangle - rw_normalangle) >> ANGLETOFINESHIFT]; + dist = FixedDiv(rw_distance, sinv); + cosv = finecosine[(viewangle - visangle) >> ANGLETOFINESHIFT]; + z = abs(FixedMul(dist, cosv)); + scale = FixedDiv(projection, z); + return scale; + } +#endif + + anglea = ANG90 + (visangle - viewangle); + angleb = ANG90 + (visangle - rw_normalangle); +// bothe sines are allways positive + sinea = finesine[anglea >> ANGLETOFINESHIFT]; + sineb = finesine[angleb >> ANGLETOFINESHIFT]; + num = FixedMul(projection, sineb) << detailshift; + den = FixedMul(rw_distance, sinea); + if (den > num >> 16) + { + scale = FixedDiv(num, den); + if (scale > 64 * FRACUNIT) + scale = 64 * FRACUNIT; + else if (scale < 256) + scale = 256; + } + else + scale = 64 * FRACUNIT; + + return scale; +} + + + +/* +================= += += R_InitTables += +================= +*/ + +void R_InitTables(void) +{ +// now getting from tables.c +#if 0 + int i; + float a, fv; + int t; + +// +// viewangle tangent table +// + for (i = 0; i < FINEANGLES / 2; i++) + { + a = (i - FINEANGLES / 4 + 0.5) * PI * 2 / FINEANGLES; + fv = FRACUNIT * tan(a); + t = fv; + finetangent[i] = t; + } + +// +// finesine table +// + for (i = 0; i < 5 * FINEANGLES / 4; i++) + { +// OPTIMIZE: mirror... + a = (i + 0.5) * PI * 2 / FINEANGLES; + t = FRACUNIT * sin(a); + finesine[i] = t; + } +#endif + +} + + +/* +================= += += R_InitTextureMapping += +================= +*/ + +void R_InitTextureMapping(void) +{ + int i; + int x; + int t; + fixed_t focallength; + + +// +// use tangent table to generate viewangletox +// viewangletox will give the next greatest x after the view angle +// + // calc focallength so FIELDOFVIEW angles covers SCREENWIDTH + focallength = + FixedDiv(centerxfrac, finetangent[FINEANGLES / 4 + FIELDOFVIEW / 2]); + + for (i = 0; i < FINEANGLES / 2; i++) + { + if (finetangent[i] > FRACUNIT * 2) + t = -1; + else if (finetangent[i] < -FRACUNIT * 2) + t = viewwidth + 1; + else + { + t = FixedMul(finetangent[i], focallength); + t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS; + if (t < -1) + t = -1; + else if (t > viewwidth + 1) + t = viewwidth + 1; + } + viewangletox[i] = t; + } + +// +// scan viewangletox[] to generate xtoviewangleangle[] +// +// xtoviewangle will give the smallest view angle that maps to x + for (x = 0; x <= viewwidth; x++) + { + i = 0; + while (viewangletox[i] > x) + i++; + xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90; + } + +// +// take out the fencepost cases from viewangletox +// + for (i = 0; i < FINEANGLES / 2; i++) + { + t = FixedMul(finetangent[i], focallength); + t = centerx - t; + if (viewangletox[i] == -1) + viewangletox[i] = 0; + else if (viewangletox[i] == viewwidth + 1) + viewangletox[i] = viewwidth; + } + + clipangle = xtoviewangle[0]; +} + +//============================================================================= + +/* +==================== += += R_InitLightTables += += Only inits the zlight table, because the scalelight table changes += with view size += +==================== +*/ + +#define DISTMAP 2 + +void R_InitLightTables(void) +{ + int i, j, level, startmap; + int scale; + +// +// Calculate the light levels to use for each level / distance combination +// + for (i = 0; i < LIGHTLEVELS; i++) + { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTZ; j++) + { + scale = + FixedDiv((SCREENWIDTH / 2 * FRACUNIT), + (j + 1) << LIGHTZSHIFT); + scale >>= LIGHTSCALESHIFT; + level = startmap - scale / DISTMAP; + if (level < 0) + level = 0; + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS - 1; + zlight[i][j] = colormaps + level * 256; + } + } +} + + +/* +============== += += R_SetViewSize += += Don't really change anything here, because i might be in the middle of += a refresh. The change will take effect next refresh. += +============== +*/ + +boolean setsizeneeded; +int setblocks, setdetail; + +void R_SetViewSize(int blocks, int detail) +{ + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; +} + +/* +============== += += R_ExecuteSetViewSize += +============== +*/ + +void R_ExecuteSetViewSize(void) +{ + fixed_t cosadj, dy; + int i, j, level, startmap; + + setsizeneeded = false; + + if (setblocks == 11) + { + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; + } + else + { + scaledviewwidth = setblocks * 32; + viewheight = (setblocks * 158 / 10); + } + + detailshift = setdetail; + viewwidth = scaledviewwidth >> detailshift; + + centery = viewheight / 2; + centerx = viewwidth / 2; + centerxfrac = centerx << FRACBITS; + centeryfrac = centery << FRACBITS; + projection = centerxfrac; + + if (!detailshift) + { + colfunc = basecolfunc = R_DrawColumn; + tlcolfunc = R_DrawTLColumn; + transcolfunc = R_DrawTranslatedColumn; + spanfunc = R_DrawSpan; + } + else + { + colfunc = basecolfunc = R_DrawColumnLow; + tlcolfunc = R_DrawTLColumn; + transcolfunc = R_DrawTranslatedColumn; + spanfunc = R_DrawSpanLow; + } + + R_InitBuffer(scaledviewwidth, viewheight); + + R_InitTextureMapping(); + +// +// psprite scales +// + pspritescale = FRACUNIT * viewwidth / SCREENWIDTH; + pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth; + +// +// thing clipping +// + for (i = 0; i < viewwidth; i++) + screenheightarray[i] = viewheight; + +// +// planes +// + for (i = 0; i < viewheight; i++) + { + dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; + dy = abs(dy); + yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, dy); + } + + for (i = 0; i < viewwidth; i++) + { + cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); + distscale[i] = FixedDiv(FRACUNIT, cosadj); + } + +// +// Calculate the light levels to use for each level / scale combination +// + for (i = 0; i < LIGHTLEVELS; i++) + { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTSCALE; j++) + { + level = + startmap - + j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP; + if (level < 0) + level = 0; + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS - 1; + scalelight[i][j] = colormaps + level * 256; + } + } + +// +// draw the border +// + R_DrawViewBorder(); // erase old menu stuff +} + + +/* +============== += += R_Init += +============== +*/ + +int detailLevel; +int screenblocks = 10; + +void R_Init(void) +{ + //tprintf("R_InitData ", 1); + R_InitData(); + printf ("."); + //tprintf("R_InitPointToAngle\n", 0); + R_InitPointToAngle(); + printf ("."); + //tprintf("R_InitTables ", 0); + R_InitTables(); + // viewwidth / viewheight / detailLevel are set by the defaults + printf ("."); + R_SetViewSize(screenblocks, detailLevel); + //tprintf("R_InitPlanes\n", 0); + R_InitPlanes(); + printf ("."); + //tprintf("R_InitLightTables ", 0); + R_InitLightTables(); + printf ("."); + //tprintf("R_InitSkyMap\n", 0); + R_InitSkyMap(); + printf ("."); + R_InitTranslationTables(); + framecount = 0; +} + + +/* +============== += += R_PointInSubsector += +============== +*/ + +subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) +{ + node_t *node; + int side, nodenum; + + if (!numnodes) // single subsector is a special case + return subsectors; + + nodenum = numnodes - 1; + + while (!(nodenum & NF_SUBSECTOR)) + { + node = &nodes[nodenum]; + side = R_PointOnSide(x, y, node); + nodenum = node->children[side]; + } + + return &subsectors[nodenum & ~NF_SUBSECTOR]; + +} + +//---------------------------------------------------------------------------- +// +// PROC R_SetupFrame +// +//---------------------------------------------------------------------------- + +void R_SetupFrame(player_t * player) +{ + int i; + int tableAngle; + int tempCentery; + + //drawbsp = 1; + viewplayer = player; + // haleyjd: removed WATCOMC + // haleyjd FIXME: viewangleoffset handling? + viewangle = player->mo->angle + viewangleoffset; + tableAngle = viewangle >> ANGLETOFINESHIFT; + if (player->chickenTics && player->chickenPeck) + { // Set chicken attack view position + viewx = player->mo->x + player->chickenPeck * finecosine[tableAngle]; + viewy = player->mo->y + player->chickenPeck * finesine[tableAngle]; + } + else + { // Normal view position + viewx = player->mo->x; + viewy = player->mo->y; + } + extralight = player->extralight; + viewz = player->viewz; + + tempCentery = viewheight / 2 + (player->lookdir) * screenblocks / 10; + if (centery != tempCentery) + { + centery = tempCentery; + centeryfrac = centery << FRACBITS; + for (i = 0; i < viewheight; i++) + { + yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, + abs(((i - centery) << FRACBITS) + + FRACUNIT / 2)); + } + } + viewsin = finesine[tableAngle]; + viewcos = finecosine[tableAngle]; + sscount = 0; + if (player->fixedcolormap) + { + fixedcolormap = colormaps + player->fixedcolormap + * 256 * sizeof(lighttable_t); + walllights = scalelightfixed; + for (i = 0; i < MAXLIGHTSCALE; i++) + { + scalelightfixed[i] = fixedcolormap; + } + } + else + { + fixedcolormap = 0; + } + framecount++; + validcount++; + if (BorderNeedRefresh) + { + if (setblocks < 10) + { + R_DrawViewBorder(); + } + BorderNeedRefresh = false; + BorderTopRefresh = false; + UpdateState |= I_FULLSCRN; + } + if (BorderTopRefresh) + { + if (setblocks < 10) + { + R_DrawTopBorder(); + } + BorderTopRefresh = false; + UpdateState |= I_MESSAGES; + } +} + +/* +============== += += R_RenderView += +============== +*/ + +void R_RenderPlayerView(player_t * player) +{ + R_SetupFrame(player); + R_ClearClipSegs(); + R_ClearDrawSegs(); + R_ClearPlanes(); + R_ClearSprites(); + NetUpdate(); // check for new console commands + R_RenderBSPNode(numnodes - 1); // the head node is the last node output + NetUpdate(); // check for new console commands + R_DrawPlanes(); + NetUpdate(); // check for new console commands + R_DrawMasked(); + NetUpdate(); // check for new console commands +} diff --git a/games/NXDoom/src/heretic/r_plane.c b/games/NXDoom/src/heretic/r_plane.c new file mode 100644 index 00000000000..e9ed70c760e --- /dev/null +++ b/games/NXDoom/src/heretic/r_plane.c @@ -0,0 +1,511 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// R_planes.c + +#include +#include "doomdef.h" +#include "deh_str.h" +#include "i_system.h" +#include "r_local.h" + +planefunction_t floorfunc, ceilingfunc; + +// +// sky mapping +// +int skyflatnum; +int skytexture; +int skytexturemid; +fixed_t skyiscale; + +// +// opening +// + +visplane_t visplanes[MAXVISPLANES], *lastvisplane; +visplane_t *floorplane, *ceilingplane; + +short openings[MAXOPENINGS], *lastopening; + +// +// clip values are the solid pixel bounding the range +// floorclip starts out SCREENHEIGHT +// ceilingclip starts out -1 +// +short floorclip[SCREENWIDTH]; +short ceilingclip[SCREENWIDTH]; + +// +// spanstart holds the start of a plane span +// initialized to 0 at start +// +int spanstart[SCREENHEIGHT]; +int spanstop[SCREENHEIGHT]; + +// +// texture mapping +// +lighttable_t **planezlight; +fixed_t planeheight; + +fixed_t yslope[SCREENHEIGHT]; +fixed_t distscale[SCREENWIDTH]; +fixed_t basexscale, baseyscale; + +fixed_t cachedheight[SCREENHEIGHT]; +fixed_t cacheddistance[SCREENHEIGHT]; +fixed_t cachedxstep[SCREENHEIGHT]; +fixed_t cachedystep[SCREENHEIGHT]; + + +/* +================ += += R_InitSkyMap += += Called whenever the view size changes += +================ +*/ + +void R_InitSkyMap(void) +{ + skyflatnum = R_FlatNumForName(DEH_String("F_SKY1")); + skytexturemid = 200 * FRACUNIT; + skyiscale = FRACUNIT; +} + + +/* +==================== += += R_InitPlanes += += Only at game startup +==================== +*/ + +void R_InitPlanes(void) +{ +} + + +/* +================ += += R_MapPlane += +global vars: + +planeheight +ds_source +basexscale +baseyscale +viewx +viewy + +BASIC PRIMITIVE +================ +*/ + +void R_MapPlane(int y, int x1, int x2) +{ + angle_t angle; + fixed_t distance, length; + unsigned index; + +#ifdef RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned) y > viewheight) + I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); +#endif + + if (planeheight != cachedheight[y]) + { + cachedheight[y] = planeheight; + distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); + + ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); + ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); + } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + length = FixedMul(distance, distscale[x1]); + angle = (viewangle + xtoviewangle[x1]) >> ANGLETOFINESHIFT; + ds_xfrac = viewx + FixedMul(finecosine[angle], length); + ds_yfrac = -viewy - FixedMul(finesine[angle], length); + + if (fixedcolormap) + ds_colormap = fixedcolormap; + else + { + index = distance >> LIGHTZSHIFT; + if (index >= MAXLIGHTZ) + index = MAXLIGHTZ - 1; + ds_colormap = planezlight[index]; + } + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + spanfunc(); // high or low detail +} + +//============================================================================= + +/* +==================== += += R_ClearPlanes += += At begining of frame +==================== +*/ + +void R_ClearPlanes(void) +{ + int i; + angle_t angle; + +// +// opening / clipping determination +// + for (i = 0; i < viewwidth; i++) + { + floorclip[i] = viewheight; + ceilingclip[i] = -1; + } + + lastvisplane = visplanes; + lastopening = openings; + +// +// texture calculation +// + memset(cachedheight, 0, sizeof(cachedheight)); + angle = (viewangle - ANG90) >> ANGLETOFINESHIFT; // left to right mapping + + // scale will be unit scale at SCREENWIDTH/2 distance + basexscale = FixedDiv(finecosine[angle], centerxfrac); + baseyscale = -FixedDiv(finesine[angle], centerxfrac); +} + + + +/* +=============== += += R_FindPlane += +=============== +*/ + +visplane_t *R_FindPlane(fixed_t height, int picnum, + int lightlevel, int special) +{ + visplane_t *check; + + if (picnum == skyflatnum) + { + // all skies map together + height = 0; + lightlevel = 0; + } + + for (check = visplanes; check < lastvisplane; check++) + { + if (height == check->height + && picnum == check->picnum + && lightlevel == check->lightlevel && special == check->special) + break; + } + + if (check < lastvisplane) + { + return (check); + } + + if (lastvisplane - visplanes == MAXVISPLANES) + { + I_Error("R_FindPlane: no more visplanes"); + } + + lastvisplane++; + check->height = height; + check->picnum = picnum; + check->lightlevel = lightlevel; + check->special = special; + check->minx = SCREENWIDTH; + check->maxx = -1; + memset(check->top, 0xff, sizeof(check->top)); + return (check); +} + +/* +=============== += += R_CheckPlane += +=============== +*/ + +visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop) +{ + int intrl, intrh; + int unionl, unionh; + int x; + + if (start < pl->minx) + { + intrl = pl->minx; + unionl = start; + } + else + { + unionl = pl->minx; + intrl = start; + } + + if (stop > pl->maxx) + { + intrh = pl->maxx; + unionh = stop; + } + else + { + unionh = pl->maxx; + intrh = stop; + } + + for (x = intrl; x <= intrh; x++) + if (pl->top[x] != 0xff) + break; + + if (x > intrh) + { + pl->minx = unionl; + pl->maxx = unionh; + return pl; // use the same one + } + +// make a new visplane + + lastvisplane->height = pl->height; + lastvisplane->picnum = pl->picnum; + lastvisplane->lightlevel = pl->lightlevel; + lastvisplane->special = pl->special; + pl = lastvisplane++; + pl->minx = start; + pl->maxx = stop; + memset(pl->top, 0xff, sizeof(pl->top)); + + return pl; +} + + + +//============================================================================= + +/* +================ += += R_MakeSpans += +================ +*/ + +void R_MakeSpans(int x, int t1, int b1, int t2, int b2) +{ + while (t1 < t2 && t1 <= b1) + { + R_MapPlane(t1, spanstart[t1], x - 1); + t1++; + } + while (b1 > b2 && b1 >= t1) + { + R_MapPlane(b1, spanstart[b1], x - 1); + b1--; + } + + while (t2 < t1 && t2 <= b2) + { + spanstart[t2] = x; + t2++; + } + while (b2 > b1 && b2 >= t2) + { + spanstart[b2] = x; + b2--; + } +} + + + +/* +================ += += R_DrawPlanes += += At the end of each frame +================ +*/ + +void R_DrawPlanes(void) +{ + visplane_t *pl; + int light; + int x, stop; + int lumpnum; + int angle; + byte *tempSource; + + byte *dest; + int count; + fixed_t frac, fracstep; + +#ifdef RANGECHECK + if (ds_p - drawsegs > MAXDRAWSEGS) + I_Error("R_DrawPlanes: drawsegs overflow (%td)", + ds_p - drawsegs); + if (lastvisplane - visplanes > MAXVISPLANES) + I_Error("R_DrawPlanes: visplane overflow (%td)", + lastvisplane - visplanes); + if (lastopening - openings > MAXOPENINGS) + I_Error("R_DrawPlanes: opening overflow (%td)", + lastopening - openings); +#endif + + for (pl = visplanes; pl < lastvisplane; pl++) + { + if (pl->minx > pl->maxx) + continue; + // + // sky flat + // + if (pl->picnum == skyflatnum) + { + dc_iscale = skyiscale; + dc_colormap = colormaps; // sky is allways drawn full bright + dc_texturemid = skytexturemid; + for (x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + if (dc_yl <= dc_yh) + { + angle = (viewangle + xtoviewangle[x]) >> ANGLETOSKYSHIFT; + dc_x = x; + dc_source = R_GetColumn(skytexture, angle); + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, + dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = 1; + frac = (dc_texturemid >> FRACBITS) + (dc_yl - centery); + do + { + *dest = dc_source[frac]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); + +// colfunc (); + } + } + continue; + } + + // + // regular flat + // + lumpnum = firstflat + flattranslation[pl->picnum]; + + tempSource = W_CacheLumpNum(lumpnum, PU_STATIC); + + switch (pl->special) + { + case 25: + case 26: + case 27: + case 28: + case 29: // Scroll_North + ds_source = tempSource; + break; + case 20: + case 21: + case 22: + case 23: + case 24: // Scroll_East + ds_source = tempSource + ((63 - ((leveltime >> 1) & 63)) << + (pl->special - 20) & 63); + //ds_source = tempSource+((leveltime>>1)&63); + break; + case 30: + case 31: + case 32: + case 33: + case 34: // Scroll_South + ds_source = tempSource; + break; + case 35: + case 36: + case 37: + case 38: + case 39: // Scroll_West + ds_source = tempSource; + break; + case 4: // Scroll_EastLavaDamage + ds_source = + tempSource + (((63 - ((leveltime >> 1) & 63)) << 3) & 63); + break; + default: + ds_source = tempSource; + } + planeheight = abs(pl->height - viewz); + light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; + if (light >= LIGHTLEVELS) + light = LIGHTLEVELS - 1; + if (light < 0) + light = 0; + planezlight = zlight[light]; + + pl->top[pl->maxx + 1] = 0xff; + pl->top[pl->minx - 1] = 0xff; + + stop = pl->maxx + 1; + for (x = pl->minx; x <= stop; x++) + R_MakeSpans(x, pl->top[x - 1], pl->bottom[x - 1], pl->top[x], + pl->bottom[x]); + + W_ReleaseLumpNum(lumpnum); + } +} diff --git a/games/NXDoom/src/heretic/r_segs.c b/games/NXDoom/src/heretic/r_segs.c new file mode 100644 index 00000000000..b37c94d6c6d --- /dev/null +++ b/games/NXDoom/src/heretic/r_segs.c @@ -0,0 +1,661 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +//************************************************************************** +//** +//** R_SEGS.C +//** +//** This version has the tall-sector-crossing-precision-bug fixed. +//** +//************************************************************************** + +#include + +#include "doomdef.h" +#include "r_local.h" + +// OPTIMIZE: closed two sided lines as single sided + +boolean segtextured; // true if any of the segs textures might be vis +boolean markfloor; // false if the back side is the same plane +boolean markceiling; +boolean maskedtexture; +int toptexture, bottomtexture, midtexture; + + +angle_t rw_normalangle; +int rw_angle1; // angle to line origin + +// +// wall +// +int rw_x; +int rw_stopx; +angle_t rw_centerangle; +fixed_t rw_offset; +fixed_t rw_distance; +fixed_t rw_scale; +fixed_t rw_scalestep; +fixed_t rw_midtexturemid; +fixed_t rw_toptexturemid; +fixed_t rw_bottomtexturemid; + +int worldtop, worldbottom, worldhigh, worldlow; + +fixed_t pixhigh, pixlow; +fixed_t pixhighstep, pixlowstep; +fixed_t topfrac, topstep; +fixed_t bottomfrac, bottomstep; + + +lighttable_t **walllights; + +short *maskedtexturecol; + +/* +================ += += R_RenderMaskedSegRange += +================ +*/ + +void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2) +{ + unsigned index; + column_t *col; + int lightnum; + int texnum; + +// +// calculate light table +// use different light tables for horizontal / vertical / diagonal +// OPTIMIZE: get rid of LIGHTSEGSHIFT globally + curline = ds->curline; + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = texturetranslation[curline->sidedef->midtexture]; + + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + + maskedtexturecol = ds->maskedtexturecol; + + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1) * rw_scalestep; + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + +// +// find positioning +// + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + { + dc_texturemid = frontsector->floorheight > backsector->floorheight + ? frontsector->floorheight : backsector->floorheight; + dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; + } + else + { + dc_texturemid = frontsector->ceilingheight < backsector->ceilingheight + ? frontsector->ceilingheight : backsector->ceilingheight; + dc_texturemid = dc_texturemid - viewz; + } + dc_texturemid += curline->sidedef->rowoffset; + + if (fixedcolormap) + dc_colormap = fixedcolormap; +// +// draw the columns +// + for (dc_x = x1; dc_x <= x2; dc_x++) + { + // calculate lighting + if (maskedtexturecol[dc_x] != SHRT_MAX) + { + if (!fixedcolormap) + { + index = spryscale >> LIGHTSCALESHIFT; + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + dc_colormap = walllights[index]; + } + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned) spryscale; + + // + // draw the texture + // + col = (column_t *) ((byte *) + R_GetColumn(texnum, + maskedtexturecol[dc_x]) - 3); + + R_DrawMaskedColumn(col, -1); + maskedtexturecol[dc_x] = SHRT_MAX; + } + spryscale += rw_scalestep; + } + +} + +/* +================ += += R_RenderSegLoop += += Draws zero, one, or two textures (and possibly a masked texture) for walls += Can draw or mark the starting pixel of floor and ceiling textures += += CALLED: CORE LOOPING ROUTINE +================ +*/ + +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1<> HEIGHTBITS; + if (yl < ceilingclip[rw_x] + 1) + yl = ceilingclip[rw_x] + 1; // no space above wall + if (markceiling) + { + top = ceilingclip[rw_x] + 1; + bottom = yl - 1; + if (bottom >= floorclip[rw_x]) + bottom = floorclip[rw_x] - 1; + if (top <= bottom) + { + ceilingplane->top[rw_x] = top; + ceilingplane->bottom[rw_x] = bottom; + } + } + + yh = bottomfrac >> HEIGHTBITS; + if (yh >= floorclip[rw_x]) + yh = floorclip[rw_x] - 1; + if (markfloor) + { + top = yh + 1; + bottom = floorclip[rw_x] - 1; + if (top <= ceilingclip[rw_x]) + top = ceilingclip[rw_x] + 1; + if (top <= bottom) + { + floorplane->top[rw_x] = top; + floorplane->bottom[rw_x] = bottom; + } + } + +// +// texturecolumn and lighting are independent of wall tiers +// + if (segtextured) + { + // calculate texture offset + angle = (rw_centerangle + xtoviewangle[rw_x]) >> ANGLETOFINESHIFT; + texturecolumn = + rw_offset - FixedMul(finetangent[angle], rw_distance); + texturecolumn >>= FRACBITS; + // calculate lighting + index = rw_scale >> LIGHTSCALESHIFT; + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + dc_colormap = walllights[index]; + dc_x = rw_x; + dc_iscale = 0xffffffffu / (unsigned) rw_scale; + } + +// +// draw the wall tiers +// + if (midtexture) + { // single sided line + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_source = R_GetColumn(midtexture, texturecolumn); + colfunc(); + ceilingclip[rw_x] = viewheight; + floorclip[rw_x] = -1; + } + else + { // two sided line + if (toptexture) + { // top wall + mid = pixhigh >> HEIGHTBITS; + pixhigh += pixhighstep; + if (mid >= floorclip[rw_x]) + mid = floorclip[rw_x] - 1; + if (mid >= yl) + { + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_source = R_GetColumn(toptexture, texturecolumn); + colfunc(); + ceilingclip[rw_x] = mid; + } + else + ceilingclip[rw_x] = yl - 1; + } + else + { // no top wall + if (markceiling) + ceilingclip[rw_x] = yl - 1; + } + + if (bottomtexture) + { // bottom wall + mid = (pixlow + HEIGHTUNIT - 1) >> HEIGHTBITS; + pixlow += pixlowstep; + if (mid <= ceilingclip[rw_x]) + mid = ceilingclip[rw_x] + 1; // no space above wall + if (mid <= yh) + { + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_source = R_GetColumn(bottomtexture, texturecolumn); + colfunc(); + floorclip[rw_x] = mid; + } + else + floorclip[rw_x] = yh + 1; + } + else + { // no bottom wall + if (markfloor) + floorclip[rw_x] = yh + 1; + } + + if (maskedtexture) + { // save texturecol for backdrawing of masked mid texture + maskedtexturecol[rw_x] = texturecolumn; + } + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; + } + +} + + + +/* +===================== += += R_StoreWallRange += += A wall segment will be drawn between start and stop pixels (inclusive) += +====================== +*/ + +void R_StoreWallRange(int start, int stop) +{ + fixed_t hyp; + fixed_t sineval; + angle_t distangle, offsetangle; + fixed_t vtop; + int lightnum; + + if (ds_p == &drawsegs[MAXDRAWSEGS]) + return; // don't overflow and crash + +#ifdef RANGECHECK + if (start >= viewwidth || start > stop) + I_Error("Bad R_RenderWallRange: %i to %i", start, stop); +#endif + + sidedef = curline->sidedef; + linedef = curline->linedef; + +// mark the segment as visible for auto map + linedef->flags |= ML_MAPPED; + +// +// calculate rw_distance for scale calculation +// + rw_normalangle = curline->angle + ANG90; + offsetangle = abs((int) rw_normalangle - (int) rw_angle1); + if (offsetangle > ANG90) + offsetangle = ANG90; + distangle = ANG90 - offsetangle; + hyp = R_PointToDist(curline->v1->x, curline->v1->y); + sineval = finesine[distangle >> ANGLETOFINESHIFT]; + rw_distance = FixedMul(hyp, sineval); + + + ds_p->x1 = rw_x = start; + ds_p->x2 = stop; + ds_p->curline = curline; + rw_stopx = stop + 1; + +// +// calculate scale at both ends and step +// + ds_p->scale1 = rw_scale = + R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); + if (stop > start) + { + ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); + ds_p->scalestep = rw_scalestep = + (ds_p->scale2 - rw_scale) / (stop - start); + } + else + { + // + // try to fix the stretched line bug + // +#if 0 + if (rw_distance < FRACUNIT / 2) + { + fixed_t trx, try; + fixed_t gxt, gyt; + + trx = curline->v1->x - viewx; + try = curline->v1->y - viewy; + + gxt = FixedMul(trx, viewcos); + gyt = -FixedMul(try, viewsin); + ds_p->scale1 = FixedDiv(projection, gxt - gyt); + } +#endif + ds_p->scale2 = ds_p->scale1; + } + + +// +// calculate texture boundaries and decide if floor / ceiling marks +// are needed +// + worldtop = frontsector->ceilingheight - viewz; + worldbottom = frontsector->floorheight - viewz; + + midtexture = toptexture = bottomtexture = maskedtexture = 0; + ds_p->maskedtexturecol = NULL; + + if (!backsector) + { +// +// single sided line +// + midtexture = texturetranslation[sidedef->midtexture]; + // a single sided line is terminal, so it must mark ends + markfloor = markceiling = true; + if (linedef->flags & ML_DONTPEGBOTTOM) + { + vtop = frontsector->floorheight + + textureheight[sidedef->midtexture]; + rw_midtexturemid = vtop - viewz; // bottom of texture at bottom + } + else + rw_midtexturemid = worldtop; // top of texture at top + rw_midtexturemid += sidedef->rowoffset; + ds_p->silhouette = SIL_BOTH; + ds_p->sprtopclip = screenheightarray; + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->tsilheight = INT_MIN; + } + else + { +// +// two sided line +// + ds_p->sprtopclip = ds_p->sprbottomclip = NULL; + ds_p->silhouette = 0; + if (frontsector->floorheight > backsector->floorheight) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = frontsector->floorheight; + } + else if (backsector->floorheight > viewz) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; +// ds_p->sprbottomclip = negonearray; + } + if (frontsector->ceilingheight < backsector->ceilingheight) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = frontsector->ceilingheight; + } + else if (backsector->ceilingheight < viewz) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; +// ds_p->sprtopclip = screenheightarray; + } + + if (backsector->ceilingheight <= frontsector->floorheight) + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } + if (backsector->floorheight >= frontsector->ceilingheight) + { + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT_MIN; + ds_p->silhouette |= SIL_TOP; + } + worldhigh = backsector->ceilingheight - viewz; + worldlow = backsector->floorheight - viewz; + + // hack to allow height changes in outdoor areas + if (frontsector->ceilingpic == skyflatnum + && backsector->ceilingpic == skyflatnum) + worldtop = worldhigh; + + if (worldlow != worldbottom + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel) + markfloor = true; + else + markfloor = false; // same plane on both sides + + if (worldhigh != worldtop + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel) + markceiling = true; + else + markceiling = false; // same plane on both sides + + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + markceiling = markfloor = true; // closed door + + if (worldhigh < worldtop) + { // top texture + toptexture = texturetranslation[sidedef->toptexture]; + if (linedef->flags & ML_DONTPEGTOP) + rw_toptexturemid = worldtop; // top of texture at top + else + { + vtop = backsector->ceilingheight + + textureheight[sidedef->toptexture]; + rw_toptexturemid = vtop - viewz; // bottom of texture + } + } + if (worldlow > worldbottom) + { // bottom texture + bottomtexture = texturetranslation[sidedef->bottomtexture]; + if (linedef->flags & ML_DONTPEGBOTTOM) + { // bottom of texture at bottom + rw_bottomtexturemid = worldtop; // top of texture at top + } + else // top of texture at top + rw_bottomtexturemid = worldlow; + } + rw_toptexturemid += sidedef->rowoffset; + rw_bottomtexturemid += sidedef->rowoffset; + + // + // allocate space for masked texture tables + // + if (sidedef->midtexture) + { // masked midtexture + maskedtexture = true; + ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; + } + } + +// +// calculate rw_offset (only needed for textured lines) +// + segtextured = midtexture | toptexture | bottomtexture | maskedtexture; + + if (segtextured) + { + offsetangle = rw_normalangle - rw_angle1; + if (offsetangle > ANG180) + offsetangle = -offsetangle; + if (offsetangle > ANG90) + offsetangle = ANG90; + sineval = finesine[offsetangle >> ANGLETOFINESHIFT]; + rw_offset = FixedMul(hyp, sineval); + if (rw_normalangle - rw_angle1 < ANG180) + rw_offset = -rw_offset; + rw_offset += sidedef->textureoffset + curline->offset; + rw_centerangle = ANG90 + viewangle - rw_normalangle; + + // + // calculate light table + // use different light tables for horizontal / vertical / diagonal + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + if (!fixedcolormap) + { + lightnum = + (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + } + } + + +// +// if a floor / ceiling plane is on the wrong side of the view plane +// it is definately invisible and doesn't need to be marked +// + if (frontsector->floorheight >= viewz) + markfloor = false; // above view plane + if (frontsector->ceilingheight <= viewz + && frontsector->ceilingpic != skyflatnum) + markceiling = false; // below view plane + +// +// calculate incremental stepping values for texture edges +// + worldtop >>= 4; + worldbottom >>= 4; + + topstep = -FixedMul(rw_scalestep, worldtop); + topfrac = (centeryfrac >> 4) - FixedMul(worldtop, rw_scale); + + bottomstep = -FixedMul(rw_scalestep, worldbottom); + bottomfrac = (centeryfrac >> 4) - FixedMul(worldbottom, rw_scale); + + if (backsector) + { + worldhigh >>= 4; + worldlow >>= 4; + + if (worldhigh < worldtop) + { + pixhigh = (centeryfrac >> 4) - FixedMul(worldhigh, rw_scale); + pixhighstep = -FixedMul(rw_scalestep, worldhigh); + } + if (worldlow > worldbottom) + { + pixlow = (centeryfrac >> 4) - FixedMul(worldlow, rw_scale); + pixlowstep = -FixedMul(rw_scalestep, worldlow); + } + } + +// +// render it +// + if (markceiling) + ceilingplane = R_CheckPlane(ceilingplane, rw_x, rw_stopx - 1); + if (markfloor) + floorplane = R_CheckPlane(floorplane, rw_x, rw_stopx - 1); + + R_RenderSegLoop(); + +// +// save sprite clipping info +// + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + { + memcpy(lastopening, ceilingclip + start, 2 * (rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) + && !ds_p->sprbottomclip) + { + memcpy(lastopening, floorclip + start, 2 * (rw_stopx - start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } + if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + } + if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + } + ds_p++; +} diff --git a/games/NXDoom/src/heretic/r_things.c b/games/NXDoom/src/heretic/r_things.c new file mode 100644 index 00000000000..88e35b9bc1b --- /dev/null +++ b/games/NXDoom/src/heretic/r_things.c @@ -0,0 +1,1017 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// R_things.c +#include +#include +#include "doomdef.h" +#include "deh_str.h" +#include "i_swap.h" +#include "i_system.h" +#include "r_local.h" + +typedef struct +{ + int x1, x2; + + int column; + int topclip; + int bottomclip; +} maskdraw_t; + +/* + +Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis. +This is not the same as the angle, which increases counter clockwise +(protractor). There was a lot of stuff grabbed wrong, so I changed it... + +*/ + + +fixed_t pspritescale, pspriteiscale; + +lighttable_t **spritelights; + +// constant arrays used for psprite clipping and initializing clipping +short negonearray[SCREENWIDTH]; +short screenheightarray[SCREENWIDTH]; + +/* +=============================================================================== + + INITIALIZATION FUNCTIONS + +=============================================================================== +*/ + +// variables used to look up and range check thing_t sprites patches +spritedef_t *sprites; +int numsprites; + +spriteframe_t sprtemp[26]; +int maxframe; +const char *spritename; + + + +/* +================= += += R_InstallSpriteLump += += Local function for R_InitSprites +================= +*/ + +void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, + boolean flipped) +{ + int r; + + if (frame >= 26 || rotation > 8) + I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); + + if ((int) frame > maxframe) + maxframe = frame; + + if (rotation == 0) + { +// the lump should be used for all rotations + if (sprtemp[frame].rotate == false) + I_Error("R_InitSprites: Sprite %s frame %c has multip rot=0 lump", + spritename, 'A' + frame); + if (sprtemp[frame].rotate == true) + I_Error + ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = false; + for (r = 0; r < 8; r++) + { + sprtemp[frame].lump[r] = lump - firstspritelump; + sprtemp[frame].flip[r] = (byte) flipped; + } + return; + } + +// the lump is only used for one rotation + if (sprtemp[frame].rotate == false) + I_Error + ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = true; + + rotation--; // make 0 based + if (sprtemp[frame].lump[rotation] != -1) + I_Error + ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it", + spritename, 'A' + frame, '1' + rotation); + + sprtemp[frame].lump[rotation] = lump - firstspritelump; + sprtemp[frame].flip[rotation] = (byte) flipped; +} + +/* +================= += += R_InitSpriteDefs += += Pass a null terminated list of sprite names (4 chars exactly) to be used += Builds the sprite rotation matrixes to account for horizontally flipped += sprites. Will report an error if the lumps are inconsistant +=Only called at startup += += Sprite lump names are 4 characters for the actor, a letter for the frame, += and a number for the rotation, A sprite that is flippable will have an += additional letter/number appended. The rotation character can be 0 to += signify no rotations +================= +*/ + +void R_InitSpriteDefs(const char **namelist) +{ + const char **check; + int i, l, frame, rotation; + int start, end; + +// count the number of sprite names + check = namelist; + while (*check != NULL) + check++; + numsprites = check - namelist; + + if (!numsprites) + return; + + sprites = Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); + + start = firstspritelump - 1; + end = lastspritelump + 1; + +// scan all the lump names for each of the names, noting the highest +// frame letter +// Just compare 4 characters as ints + for (i = 0; i < numsprites; i++) + { + spritename = DEH_String(namelist[i]); + memset(sprtemp, -1, sizeof(sprtemp)); + + maxframe = -1; + + // + // scan the lumps, filling in the frames for whatever is found + // + for (l = start + 1; l < end; l++) + if (!strncasecmp(lumpinfo[l]->name, spritename, 4)) + { + frame = lumpinfo[l]->name[4] - 'A'; + rotation = lumpinfo[l]->name[5] - '0'; + R_InstallSpriteLump(l, frame, rotation, false); + if (lumpinfo[l]->name[6]) + { + frame = lumpinfo[l]->name[6] - 'A'; + rotation = lumpinfo[l]->name[7] - '0'; + R_InstallSpriteLump(l, frame, rotation, true); + } + } + + // + // check the frames that were found for completeness + // + if (maxframe == -1) + { + //continue; + sprites[i].numframes = 0; + if (gamemode == shareware) + continue; + I_Error("R_InitSprites: No lumps found for sprite %s", + spritename); + } + + maxframe++; + for (frame = 0; frame < maxframe; frame++) + { + switch ((int) sprtemp[frame].rotate) + { + case -1: // no rotations were found for that frame at all + I_Error("R_InitSprites: No patches found for %s frame %c", + spritename, frame + 'A'); + case 0: // only the first rotation is needed + break; + + case 1: // must have all 8 frames + for (rotation = 0; rotation < 8; rotation++) + if (sprtemp[frame].lump[rotation] == -1) + I_Error + ("R_InitSprites: Sprite %s frame %c is missing rotations", + spritename, frame + 'A'); + } + } + + // + // allocate space for the frames present and copy sprtemp to it + // + sprites[i].numframes = maxframe; + sprites[i].spriteframes = + Z_Malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + memcpy(sprites[i].spriteframes, sprtemp, + maxframe * sizeof(spriteframe_t)); + } + +} + + +/* +=============================================================================== + + GAME FUNCTIONS + +=============================================================================== +*/ + +vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; +int newvissprite; + + +/* +=================== += += R_InitSprites += += Called at program start +=================== +*/ + +void R_InitSprites(const char **namelist) +{ + int i; + + for (i = 0; i < SCREENWIDTH; i++) + { + negonearray[i] = -1; + } + + R_InitSpriteDefs(namelist); +} + + +/* +=================== += += R_ClearSprites += += Called at frame start +=================== +*/ + +void R_ClearSprites(void) +{ + vissprite_p = vissprites; +} + + +/* +=================== += += R_NewVisSprite += +=================== +*/ + +vissprite_t overflowsprite; + +vissprite_t *R_NewVisSprite(void) +{ + if (vissprite_p == &vissprites[MAXVISSPRITES]) + return &overflowsprite; + vissprite_p++; + return vissprite_p - 1; +} + + +/* +================ += += R_DrawMaskedColumn += += Used for sprites and masked mid textures +================ +*/ + +short *mfloorclip; +short *mceilingclip; +fixed_t spryscale; +fixed_t sprtopscreen; +fixed_t sprbotscreen; + +void R_DrawMaskedColumn(column_t * column, signed int baseclip) +{ + int topscreen, bottomscreen; + fixed_t basetexturemid; + + basetexturemid = dc_texturemid; + + for (; column->topdelta != 0xff;) + { +// calculate unclipped screen coordinates for post + topscreen = sprtopscreen + spryscale * column->topdelta; + bottomscreen = topscreen + spryscale * column->length; + dc_yl = (topscreen + FRACUNIT - 1) >> FRACBITS; + dc_yh = (bottomscreen - 1) >> FRACBITS; + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yh >= baseclip && baseclip != -1) + dc_yh = baseclip; + + if (dc_yl <= dc_yh) + { + dc_source = (byte *) column + 3; + dc_texturemid = basetexturemid - (column->topdelta << FRACBITS); +// dc_source = (byte *)column + 3 - column->topdelta; + colfunc(); // either R_DrawColumn or R_DrawTLColumn + } + column = (column_t *) ((byte *) column + column->length + 4); + } + + dc_texturemid = basetexturemid; +} + + +/* +================ += += R_DrawVisSprite += += mfloorclip and mceilingclip should also be set +================ +*/ + +void R_DrawVisSprite(vissprite_t * vis, int x1, int x2) +{ + column_t *column; + int texturecolumn; + fixed_t frac; + patch_t *patch; + fixed_t baseclip; + + + patch = W_CacheLumpNum(vis->patch + firstspritelump, PU_CACHE); + + dc_colormap = vis->colormap; + +// if(!dc_colormap) +// colfunc = tlcolfunc; // NULL colormap = shadow draw + + if (vis->mobjflags & MF_SHADOW) + { + if (vis->mobjflags & MF_TRANSLATION) + { + colfunc = R_DrawTranslatedTLColumn; + dc_translation = translationtables - 256 + + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); + } + else + { // Draw using shadow column function + colfunc = tlcolfunc; + } + } + else if (vis->mobjflags & MF_TRANSLATION) + { + // Draw using translated column function + colfunc = R_DrawTranslatedColumn; + dc_translation = translationtables - 256 + + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); + } + + dc_iscale = abs(vis->xiscale) >> detailshift; + dc_texturemid = vis->texturemid; + frac = vis->startfrac; + spryscale = vis->scale; + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + +// check to see if weapon is a vissprite + if (vis->psprite) + { + dc_texturemid += FixedMul(((centery - viewheight / 2) << FRACBITS), + vis->xiscale); + sprtopscreen += (viewheight / 2 - centery) << FRACBITS; + } + + if (vis->footclip && !vis->psprite) + { + sprbotscreen = sprtopscreen + FixedMul(SHORT(patch->height) << FRACBITS, + spryscale); + baseclip = (sprbotscreen - FixedMul(vis->footclip << FRACBITS, + spryscale)) >> FRACBITS; + } + else + { + baseclip = -1; + } + + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + { + texturecolumn = frac >> FRACBITS; +#ifdef RANGECHECK + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error("R_DrawSpriteRange: bad texturecolumn"); +#endif + column = (column_t *) ((byte *) patch + + LONG(patch->columnofs[texturecolumn])); + R_DrawMaskedColumn(column, baseclip); + } + + colfunc = basecolfunc; +} + + + +/* +=================== += += R_ProjectSprite += += Generates a vissprite for a thing if it might be visible += +=================== +*/ + +void R_ProjectSprite(mobj_t * thing) +{ + fixed_t trx, try; + fixed_t gxt, gyt; + fixed_t tx, tz; + fixed_t xscale; + int x1, x2; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + unsigned rot; + boolean flip; + int index; + vissprite_t *vis; + angle_t ang; + fixed_t iscale; + + if (thing->flags2 & MF2_DONTDRAW) + { // Never make a vissprite when MF2_DONTDRAW is flagged. + return; + } + +// +// transform the origin point +// + trx = thing->x - viewx; + try = thing->y - viewy; + + gxt = FixedMul(trx, viewcos); + gyt = -FixedMul(try, viewsin); + tz = gxt - gyt; + + if (tz < MINZ) + return; // thing is behind view plane + xscale = FixedDiv(projection, tz); + + gxt = -FixedMul(trx, viewsin); + gyt = FixedMul(try, viewcos); + tx = -(gyt + gxt); + + if (abs(tx) > (tz << 2)) + return; // too far off the side + +// +// decide which patch to use for sprite reletive to player +// +#ifdef RANGECHECK + if ((unsigned) thing->sprite >= numsprites) + I_Error("R_ProjectSprite: invalid sprite number %i ", thing->sprite); +#endif + sprdef = &sprites[thing->sprite]; +#ifdef RANGECHECK + if ((thing->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", + thing->sprite, thing->frame); +#endif + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; + + if (sprframe->rotate) + { // choose a different rotation based on player view + ang = R_PointToAngle(thing->x, thing->y); + rot = (ang - thing->angle + (unsigned) (ANG45 / 2) * 9) >> 29; + lump = sprframe->lump[rot]; + flip = (boolean) sprframe->flip[rot]; + } + else + { // use single rotation for all views + lump = sprframe->lump[0]; + flip = (boolean) sprframe->flip[0]; + } + +// +// calculate edges of the shape +// + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul(tx, xscale)) >> FRACBITS; + if (x1 > viewwidth) + return; // off the right side + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul(tx, xscale)) >> FRACBITS) - 1; + if (x2 < 0) + return; // off the left side + + +// +// store information in a vissprite +// + vis = R_NewVisSprite(); + vis->mobjflags = thing->flags; + vis->psprite = false; + vis->scale = xscale << detailshift; + vis->gx = thing->x; + vis->gy = thing->y; + vis->gz = thing->z; + vis->gzt = thing->z + spritetopoffset[lump]; + + // foot clipping + if (thing->flags2 & MF2_FEETARECLIPPED + && thing->z <= thing->subsector->sector->floorheight) + { + vis->footclip = 10; + } + else + vis->footclip = 0; + vis->texturemid = vis->gzt - viewz - (vis->footclip << FRACBITS); + + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + iscale = FixedDiv(FRACUNIT, xscale); + if (flip) + { + vis->startfrac = spritewidth[lump] - 1; + vis->xiscale = -iscale; + } + else + { + vis->startfrac = 0; + vis->xiscale = iscale; + } + if (vis->x1 > x1) + vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->patch = lump; +// +// get light level +// + +// if (thing->flags & MF_SHADOW) +// vis->colormap = NULL; // shadow draw +// else ... + + if (fixedcolormap) + vis->colormap = fixedcolormap; // fixed map + else if (thing->frame & FF_FULLBRIGHT) + vis->colormap = colormaps; // full bright + else + { // diminished light + index = xscale >> (LIGHTSCALESHIFT - detailshift); + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + vis->colormap = spritelights[index]; + } +} + + + + +/* +======================== += += R_AddSprites += +======================== +*/ + +void R_AddSprites(sector_t * sec) +{ + mobj_t *thing; + int lightnum; + + if (sec->validcount == validcount) + return; // already added + + sec->validcount = validcount; + + lightnum = (sec->lightlevel >> LIGHTSEGSHIFT) + extralight; + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; + + + for (thing = sec->thinglist; thing; thing = thing->snext) + R_ProjectSprite(thing); +} + + +/* +======================== += += R_DrawPSprite += +======================== +*/ + +int PSpriteSY[NUMWEAPONS] = { + 0, // staff + 5 * FRACUNIT, // goldwand + 15 * FRACUNIT, // crossbow + 15 * FRACUNIT, // blaster + 15 * FRACUNIT, // skullrod + 15 * FRACUNIT, // phoenix rod + 15 * FRACUNIT, // mace + 15 * FRACUNIT, // gauntlets + 15 * FRACUNIT // beak +}; + +void R_DrawPSprite(pspdef_t * psp) +{ + fixed_t tx; + int x1, x2; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + boolean flip; + vissprite_t *vis, avis; + + int tempangle; + +// +// decide which patch to use +// +#ifdef RANGECHECK + if ((unsigned) psp->state->sprite >= numsprites) + I_Error("R_ProjectSprite: invalid sprite number %i ", + psp->state->sprite); +#endif + sprdef = &sprites[psp->state->sprite]; +#ifdef RANGECHECK + if ((psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", + psp->state->sprite, psp->state->frame); +#endif + sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; + + lump = sprframe->lump[0]; + flip = (boolean) sprframe->flip[0]; + +// +// calculate edges of the shape +// + tx = psp->sx - 160 * FRACUNIT; + + tx -= spriteoffset[lump]; + if (viewangleoffset) + { + tempangle = + ((centerxfrac / 1024) * (viewangleoffset >> ANGLETOFINESHIFT)); + } + else + { + tempangle = 0; + } + x1 = (centerxfrac + FixedMul(tx, pspritescale) + tempangle) >> FRACBITS; + if (x1 > viewwidth) + return; // off the right side + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul(tx, pspritescale) + + tempangle) >> FRACBITS) - 1; + if (x2 < 0) + return; // off the left side + +// +// store information in a vissprite +// + vis = &avis; + vis->mobjflags = 0; + vis->psprite = true; + vis->footclip = 0; + vis->texturemid = + (BASEYCENTER << FRACBITS) + FRACUNIT / 2 - (psp->sy - + spritetopoffset[lump]); + if (viewheight == SCREENHEIGHT) + { + vis->texturemid -= PSpriteSY[players[consoleplayer].readyweapon]; + } + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + vis->scale = pspritescale << detailshift; + if (flip) + { + vis->xiscale = -pspriteiscale; + vis->startfrac = spritewidth[lump] - 1; + } + else + { + vis->xiscale = pspriteiscale; + vis->startfrac = 0; + } + if (vis->x1 > x1) + vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->patch = lump; + + if (viewplayer->powers[pw_invisibility] > 4 * 32 || + viewplayer->powers[pw_invisibility] & 8) + { + // Invisibility + vis->colormap = spritelights[MAXLIGHTSCALE - 1]; + vis->mobjflags |= MF_SHADOW; + } + else if (fixedcolormap) + { + // Fixed color + vis->colormap = fixedcolormap; + } + else if (psp->state->frame & FF_FULLBRIGHT) + { + // Full bright + vis->colormap = colormaps; + } + else + { + // local light + vis->colormap = spritelights[MAXLIGHTSCALE - 1]; + } + R_DrawVisSprite(vis, vis->x1, vis->x2); +} + +/* +======================== += += R_DrawPlayerSprites += +======================== +*/ + +void R_DrawPlayerSprites(void) +{ + int i, lightnum; + pspdef_t *psp; + +// +// get light level +// + lightnum = + (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + + extralight; + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; +// +// clip to screen bounds +// + mfloorclip = screenheightarray; + mceilingclip = negonearray; + +// +// add all active psprites +// + for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; i++, psp++) + if (psp->state) + R_DrawPSprite(psp); + +} + + +/* +======================== += += R_SortVisSprites += +======================== +*/ + +vissprite_t vsprsortedhead; + +void R_SortVisSprites(void) +{ + int i, count; + vissprite_t *ds, *best; + static vissprite_t unsorted; + fixed_t bestscale; + + count = vissprite_p - vissprites; + + unsorted.next = unsorted.prev = &unsorted; + if (!count) + return; + + for (ds = vissprites; ds < vissprite_p; ds++) + { + ds->next = ds + 1; + ds->prev = ds - 1; + } + vissprites[0].prev = &unsorted; + unsorted.next = &vissprites[0]; + (vissprite_p - 1)->next = &unsorted; + unsorted.prev = vissprite_p - 1; + +// +// pull the vissprites out by scale +// + best = 0; // shut up the compiler warning + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i = 0; i < count; i++) + { + bestscale = INT_MAX; + for (ds = unsorted.next; ds != &unsorted; ds = ds->next) + { + if (ds->scale < bestscale) + { + bestscale = ds->scale; + best = ds; + } + } + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; + } +} + + + +/* +======================== += += R_DrawSprite += +======================== +*/ + +void R_DrawSprite(vissprite_t * spr) +{ + drawseg_t *ds; + short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH]; + int x, r1, r2; + fixed_t scale, lowscale; + int silhouette; + + for (x = spr->x1; x <= spr->x2; x++) + clipbot[x] = cliptop[x] = -2; + +// +// scan drawsegs from end to start for obscuring segs +// the first drawseg that has a greater scale is the clip seg +// + for (ds = ds_p - 1; ds >= drawsegs; ds--) + { + // + // determine if the drawseg obscures the sprite + // + if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || + (!ds->silhouette && !ds->maskedtexturecol)) + continue; // doesn't cover sprite + + r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; + r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->scale || (lowscale < spr->scale + && !R_PointOnSegSide(spr->gx, spr->gy, + ds->curline))) + { + if (ds->maskedtexturecol) // masked mid texture + R_RenderMaskedSegRange(ds, r1, r2); + continue; // seg is behind sprite + } + +// +// clip this piece of the sprite +// + silhouette = ds->silhouette; + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == 1) + { // bottom sil + for (x = r1; x <= r2; x++) + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + } + else if (silhouette == 2) + { // top sil + for (x = r1; x <= r2; x++) + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == 3) + { // both + for (x = r1; x <= r2; x++) + { + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + } + + } + +// +// all clipping has been performed, so draw the sprite +// + +// check for unclipped columns + for (x = spr->x1; x <= spr->x2; x++) + { + if (clipbot[x] == -2) + clipbot[x] = viewheight; + if (cliptop[x] == -2) + cliptop[x] = -1; + } + + mfloorclip = clipbot; + mceilingclip = cliptop; + R_DrawVisSprite(spr, spr->x1, spr->x2); +} + + +/* +======================== += += R_DrawMasked += +======================== +*/ + +void R_DrawMasked(void) +{ + vissprite_t *spr; + drawseg_t *ds; + + R_SortVisSprites(); + + if (vissprite_p > vissprites) + { + // draw all vissprites back to front + + for (spr = vsprsortedhead.next; spr != &vsprsortedhead; + spr = spr->next) + R_DrawSprite(spr); + } + +// +// render any remaining masked mid textures +// + for (ds = ds_p - 1; ds >= drawsegs; ds--) + if (ds->maskedtexturecol) + R_RenderMaskedSegRange(ds, ds->x1, ds->x2); + +// +// draw the psprites on top of everything +// +// Added for the sideviewing with an external device + if (viewangleoffset <= 1024 << ANGLETOFINESHIFT || viewangleoffset >= + -(1024 << ANGLETOFINESHIFT)) + { // don't draw on side views + R_DrawPlayerSprites(); + } + +// if (!viewangleoffset) // don't draw on side views +// R_DrawPlayerSprites (); +} diff --git a/games/NXDoom/src/heretic/s_sound.c b/games/NXDoom/src/heretic/s_sound.c new file mode 100644 index 00000000000..829278918e0 --- /dev/null +++ b/games/NXDoom/src/heretic/s_sound.c @@ -0,0 +1,607 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include + +#include "doomdef.h" +#include "i_system.h" +#include "m_random.h" +#include "sounds.h" +#include "s_sound.h" +#include "i_sound.h" +#include "r_local.h" +#include "p_local.h" + +#include "sounds.h" + +#include "w_wad.h" +#include "z_zone.h" + +/* +=============================================================================== + + MUSIC & SFX API + +=============================================================================== +*/ + +void S_ShutDown(void); +boolean S_StopSoundID(int sound_id, int priority); + +static channel_t channel[MAX_CHANNELS]; + +static void *rs; // Handle for the registered song +int mus_song = -1; +int mus_lumpnum; +void *mus_sndptr; +byte *soundCurve; + +int snd_MaxVolume = 10; +int snd_MusicVolume = 10; +int snd_Channels = 16; + +int AmbChan; + +void S_Start(void) +{ + int i; + + S_StartSong((gameepisode - 1) * 9 + gamemap - 1, true); + + //stop all sounds + for (i = 0; i < snd_Channels; i++) + { + if (channel[i].handle) + { + S_StopSound(channel[i].mo); + } + } + memset(channel, 0, 8 * sizeof(channel_t)); +} + +void S_StartSong(int song, boolean loop) +{ + int mus_len; + + if (song == mus_song) + { // don't replay an old song + return; + } + + if (rs != NULL) + { + I_StopSong(); + I_UnRegisterSong(rs); + } + + if (song < mus_e1m1 || song > NUMMUSIC) + { + return; + } + mus_lumpnum = W_GetNumForName(S_music[song].name); + mus_sndptr = W_CacheLumpNum(mus_lumpnum, PU_MUSIC); + mus_len = W_LumpLength(mus_lumpnum); + rs = I_RegisterSong(mus_sndptr, mus_len); + I_PlaySong(rs, loop); //'true' denotes endless looping. + mus_song = song; +} + +static mobj_t *GetSoundListener(void) +{ + static degenmobj_t dummy_listener; + + // If we are at the title screen, the console player doesn't have an + // object yet, so return a pointer to a static dummy listener instead. + + if (players[consoleplayer].mo != NULL) + { + return players[consoleplayer].mo; + } + else + { + dummy_listener.x = 0; + dummy_listener.y = 0; + dummy_listener.z = 0; + + return (mobj_t *) &dummy_listener; + } +} + +void S_StartSound(void *_origin, int sound_id) +{ + mobj_t *origin = _origin; + mobj_t *listener; + int dist, vol; + int i; + int priority; + int sep; + int angle; + int absx; + int absy; + + static int sndcount = 0; + int chan; + + listener = GetSoundListener(); + + if (sound_id == 0 || snd_MaxVolume == 0) + return; + if (origin == NULL) + { + origin = listener; + } + +// calculate the distance before other stuff so that we can throw out +// sounds that are beyond the hearing range. + absx = abs(origin->x - listener->x); + absy = abs(origin->y - listener->y); + dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); + dist >>= FRACBITS; +// dist = P_AproxDistance(origin->x-viewx, origin->y-viewy)>>FRACBITS; + + if (dist >= MAX_SND_DIST) + { +// dist = MAX_SND_DIST - 1; + return; //sound is beyond the hearing range... + } + if (dist < 0) + { + dist = 0; + } + priority = S_sfx[sound_id].priority; + priority *= (10 - (dist / 160)); + if (!S_StopSoundID(sound_id, priority)) + { + return; // other sounds have greater priority + } + for (i = 0; i < snd_Channels; i++) + { + if (origin->player) + { + i = snd_Channels; + break; // let the player have more than one sound. + } + if (origin == channel[i].mo) + { // only allow other mobjs one sound + S_StopSound(channel[i].mo); + break; + } + } + if (i >= snd_Channels) + { + if (sound_id >= sfx_wind) + { + if (AmbChan != -1 && S_sfx[sound_id].priority <= + S_sfx[channel[AmbChan].sound_id].priority) + { + return; //ambient channel already in use + } + else + { + AmbChan = -1; + } + } + for (i = 0; i < snd_Channels; i++) + { + if (channel[i].mo == NULL) + { + break; + } + } + if (i >= snd_Channels) + { + //look for a lower priority sound to replace. + sndcount++; + if (sndcount >= snd_Channels) + { + sndcount = 0; + } + for (chan = 0; chan < snd_Channels; chan++) + { + i = (sndcount + chan) % snd_Channels; + if (priority >= channel[i].priority) + { + chan = -1; //denote that sound should be replaced. + break; + } + } + if (chan != -1) + { + return; //no free channels. + } + else //replace the lower priority sound. + { + if (channel[i].handle) + { + if (I_SoundIsPlaying(channel[i].handle)) + { + I_StopSound(channel[i].handle); + } + if (S_sfx[channel[i].sound_id].usefulness > 0) + { + S_sfx[channel[i].sound_id].usefulness--; + } + + if (AmbChan == i) + { + AmbChan = -1; + } + } + } + } + } + if (S_sfx[sound_id].lumpnum == 0) + { + S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]); + } + + // calculate the volume based upon the distance from the sound origin. +// vol = (snd_MaxVolume*16 + dist*(-snd_MaxVolume*16)/MAX_SND_DIST)>>9; + vol = soundCurve[dist]; + + if (origin == listener) + { + sep = 128; + } + else + { + angle = R_PointToAngle2(listener->x, listener->y, + origin->x, origin->y); + angle = (angle - viewangle) >> 24; + sep = angle * 2 - 128; + if (sep < 64) + sep = -sep; + if (sep > 192) + sep = 512 - sep; + } + + channel[i].pitch = (byte) (NORM_PITCH + (M_Random() & 7) - (M_Random() & 7)); + channel[i].handle = I_StartSound(&S_sfx[sound_id], i, vol, sep, channel[i].pitch); + channel[i].mo = origin; + channel[i].sound_id = sound_id; + channel[i].priority = priority; + if (sound_id >= sfx_wind) + { + AmbChan = i; + } + if (S_sfx[sound_id].usefulness == -1) + { + S_sfx[sound_id].usefulness = 1; + } + else + { + S_sfx[sound_id].usefulness++; + } +} + +void S_StartSoundAtVolume(void *_origin, int sound_id, int volume) +{ + mobj_t *origin = _origin; + mobj_t *listener; + int i; + + listener = GetSoundListener(); + + if (sound_id == 0 || snd_MaxVolume == 0) + return; + if (origin == NULL) + { + origin = listener; + } + + if (volume == 0) + { + return; + } + volume = (volume * (snd_MaxVolume + 1) * 8) >> 7; + +// no priority checking, as ambient sounds would be the LOWEST. + for (i = 0; i < snd_Channels; i++) + { + if (channel[i].mo == NULL) + { + break; + } + } + if (i >= snd_Channels) + { + return; + } + if (S_sfx[sound_id].lumpnum == 0) + { + S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]); + } + + channel[i].pitch = (byte) (NORM_PITCH - (M_Random() & 3) + (M_Random() & 3)); + channel[i].handle = I_StartSound(&S_sfx[sound_id], i, volume, 128, channel[i].pitch); + channel[i].mo = origin; + channel[i].sound_id = sound_id; + channel[i].priority = 1; //super low priority. + if (S_sfx[sound_id].usefulness == -1) + { + S_sfx[sound_id].usefulness = 1; + } + else + { + S_sfx[sound_id].usefulness++; + } +} + +boolean S_StopSoundID(int sound_id, int priority) +{ + int i; + int lp; //least priority + int found; + + if (S_sfx[sound_id].numchannels == -1) + { + return (true); + } + lp = -1; //denote the argument sound_id + found = 0; + for (i = 0; i < snd_Channels; i++) + { + if (channel[i].sound_id == sound_id && channel[i].mo) + { + found++; //found one. Now, should we replace it?? + if (priority >= channel[i].priority) + { // if we're gonna kill one, then this'll be it + lp = i; + priority = channel[i].priority; + } + } + } + if (found < S_sfx[sound_id].numchannels) + { + return (true); + } + else if (lp == -1) + { + return (false); // don't replace any sounds + } + if (channel[lp].handle) + { + if (I_SoundIsPlaying(channel[lp].handle)) + { + I_StopSound(channel[lp].handle); + } + if (S_sfx[channel[i].sound_id].usefulness > 0) + { + S_sfx[channel[i].sound_id].usefulness--; + } + channel[lp].mo = NULL; + } + return (true); +} + +void S_StopSound(void *_origin) +{ + mobj_t *origin = _origin; + int i; + + for (i = 0; i < snd_Channels; i++) + { + if (channel[i].mo == origin) + { + I_StopSound(channel[i].handle); + if (S_sfx[channel[i].sound_id].usefulness > 0) + { + S_sfx[channel[i].sound_id].usefulness--; + } + channel[i].handle = 0; + channel[i].mo = NULL; + if (AmbChan == i) + { + AmbChan = -1; + } + } + } +} + +void S_SoundLink(mobj_t * oldactor, mobj_t * newactor) +{ + int i; + + for (i = 0; i < snd_Channels; i++) + { + if (channel[i].mo == oldactor) + channel[i].mo = newactor; + } +} + +void S_PauseSound(void) +{ + I_PauseSong(); +} + +void S_ResumeSound(void) +{ + I_ResumeSong(); +} + +void S_UpdateSounds(mobj_t * listener) +{ + int i, dist, vol; + int angle; + int sep; + int priority; + int absx; + int absy; + + I_UpdateSound(); + + listener = GetSoundListener(); + if (snd_MaxVolume == 0) + { + return; + } + + for (i = 0; i < snd_Channels; i++) + { + if (!channel[i].handle || S_sfx[channel[i].sound_id].usefulness == -1) + { + continue; + } + if (!I_SoundIsPlaying(channel[i].handle)) + { + if (S_sfx[channel[i].sound_id].usefulness > 0) + { + S_sfx[channel[i].sound_id].usefulness--; + } + channel[i].handle = 0; + channel[i].mo = NULL; + channel[i].sound_id = 0; + if (AmbChan == i) + { + AmbChan = -1; + } + } + if (channel[i].mo == NULL || channel[i].sound_id == 0 + || channel[i].mo == listener || listener == NULL) + { + continue; + } + else + { + absx = abs(channel[i].mo->x - listener->x); + absy = abs(channel[i].mo->y - listener->y); + dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); + dist >>= FRACBITS; +// dist = P_AproxDistance(channel[i].mo->x-listener->x, channel[i].mo->y-listener->y)>>FRACBITS; + + if (dist >= MAX_SND_DIST) + { + S_StopSound(channel[i].mo); + continue; + } + if (dist < 0) + dist = 0; + +// calculate the volume based upon the distance from the sound origin. +// vol = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE)+dist)*(snd_MaxVolume*8))>>7; + vol = soundCurve[dist]; + + angle = R_PointToAngle2(listener->x, listener->y, + channel[i].mo->x, channel[i].mo->y); + angle = (angle - viewangle) >> 24; + sep = angle * 2 - 128; + if (sep < 64) + sep = -sep; + if (sep > 192) + sep = 512 - sep; + // TODO: Pitch shifting. + I_UpdateSoundParams(channel[i].handle, vol, sep); + priority = S_sfx[channel[i].sound_id].priority; + priority *= (10 - (dist >> 8)); + channel[i].priority = priority; + } + } +} + +void S_Init(void) +{ + I_SetOPLDriverVer(opl_doom2_1_666); + soundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL); + if (snd_Channels > 8) + { + snd_Channels = 8; + } + I_SetMusicVolume(snd_MusicVolume * 8); + S_SetMaxVolume(true); + + I_AtExit(S_ShutDown, true); + + // Heretic defaults to pitch-shifting on + if (snd_pitchshift == -1) + { + snd_pitchshift = 1; + } + + I_PrecacheSounds(S_sfx, NUMSFX); +} + +void S_GetChannelInfo(SoundInfo_t * s) +{ + int i; + ChanInfo_t *c; + + s->channelCount = snd_Channels; + s->musicVolume = snd_MusicVolume; + s->soundVolume = snd_MaxVolume; + for (i = 0; i < snd_Channels; i++) + { + c = &s->chan[i]; + c->id = channel[i].sound_id; + c->priority = channel[i].priority; + c->name = S_sfx[c->id].name; + c->mo = channel[i].mo; + + if (c->mo != NULL) + { + c->distance = P_AproxDistance(c->mo->x - viewx, c->mo->y - viewy) + >> FRACBITS; + } + else + { + c->distance = 0; + } + } +} + +void S_SetMaxVolume(boolean fullprocess) +{ + int i; + + if (!fullprocess) + { + soundCurve[0] = + (*((byte *) W_CacheLumpName("SNDCURVE", PU_CACHE)) * + (snd_MaxVolume * 8)) >> 7; + } + else + { + for (i = 0; i < MAX_SND_DIST; i++) + { + soundCurve[i] = + (*((byte *) W_CacheLumpName("SNDCURVE", PU_CACHE) + i) * + (snd_MaxVolume * 8)) >> 7; + } + } +} + +static boolean musicPaused; +void S_SetMusicVolume(void) +{ + I_SetMusicVolume(snd_MusicVolume * 8); + if (snd_MusicVolume == 0) + { + I_PauseSong(); + musicPaused = true; + } + else if (musicPaused) + { + musicPaused = false; + I_ResumeSong(); + } +} + +void S_ShutDown(void) +{ + I_StopSong(); + I_UnRegisterSong(rs); + I_ShutdownSound(); +} + diff --git a/games/NXDoom/src/heretic/s_sound.h b/games/NXDoom/src/heretic/s_sound.h new file mode 100644 index 00000000000..796be73ee2d --- /dev/null +++ b/games/NXDoom/src/heretic/s_sound.h @@ -0,0 +1,40 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// soundst.h + +#ifndef __SOUNDSTH__ +#define __SOUNDSTH__ + +extern int snd_MaxVolume; +extern int snd_MusicVolume; +extern int snd_Channels; + + +void S_Start(void); +void S_StartSound(void *origin, int sound_id); +void S_StartSoundAtVolume(void *origin, int sound_id, int volume); +void S_StopSound(void *origin); +void S_PauseSound(void); +void S_ResumeSound(void); +void S_UpdateSounds(mobj_t * listener); +void S_StartSong(int song, boolean loop); +void S_Init(void); +void S_GetChannelInfo(SoundInfo_t * s); +void S_SetMaxVolume(boolean fullprocess); +void S_SetMusicVolume(void); + +#endif diff --git a/games/NXDoom/src/heretic/sb_bar.c b/games/NXDoom/src/heretic/sb_bar.c new file mode 100644 index 00000000000..bcc5d765a91 --- /dev/null +++ b/games/NXDoom/src/heretic/sb_bar.c @@ -0,0 +1,1283 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// SB_bar.c + +#include "doomdef.h" +#include "deh_str.h" +#include "i_video.h" +#include "i_swap.h" +#include "m_cheat.h" +#include "m_misc.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" +#include "am_map.h" + +// Types + +typedef struct Cheat_s +{ + void (*func) (player_t * player, struct Cheat_s * cheat); + cheatseq_t *seq; +} Cheat_t; + +// Private Functions + +static void DrawSoundInfo(void); +static void ShadeLine(int x, int y, int height, int shade); +static void ShadeChain(void); +static void DrINumber(signed int val, int x, int y); +static void DrBNumber(signed int val, int x, int y); +static void DrawCommonBar(void); +static void DrawMainBar(void); +static void DrawInventoryBar(void); +static void DrawFullScreenStuff(void); +static boolean HandleCheats(byte key); +static void CheatGodFunc(player_t * player, Cheat_t * cheat); +static void CheatNoClipFunc(player_t * player, Cheat_t * cheat); +static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat); +static void CheatPowerFunc(player_t * player, Cheat_t * cheat); +static void CheatHealthFunc(player_t * player, Cheat_t * cheat); +static void CheatKeysFunc(player_t * player, Cheat_t * cheat); +static void CheatSoundFunc(player_t * player, Cheat_t * cheat); +static void CheatTickerFunc(player_t * player, Cheat_t * cheat); +static void CheatArtifact1Func(player_t * player, Cheat_t * cheat); +static void CheatArtifact2Func(player_t * player, Cheat_t * cheat); +static void CheatArtifact3Func(player_t * player, Cheat_t * cheat); +static void CheatWarpFunc(player_t * player, Cheat_t * cheat); +static void CheatChickenFunc(player_t * player, Cheat_t * cheat); +static void CheatMassacreFunc(player_t * player, Cheat_t * cheat); +static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat); +static void CheatIDDQDFunc(player_t * player, Cheat_t * cheat); + +// Public Data + +boolean DebugSound; // debug flag for displaying sound info + +boolean inventory; +int curpos; +int inv_ptr; +int ArtifactFlash; + +static int DisplayTicker = 0; + +// Private Data + +static int HealthMarker; +static int ChainWiggle; +static player_t *CPlayer; +int playpalette; + +patch_t *PatchLTFACE; +patch_t *PatchRTFACE; +patch_t *PatchBARBACK; +patch_t *PatchCHAIN; +patch_t *PatchSTATBAR; +patch_t *PatchLIFEGEM; +//patch_t *PatchEMPWEAP; +//patch_t *PatchLIL4BOX; +patch_t *PatchLTFCTOP; +patch_t *PatchRTFCTOP; +//patch_t *PatchARMORBOX; +//patch_t *PatchARTIBOX; +patch_t *PatchSELECTBOX; +//patch_t *PatchKILLSPIC; +//patch_t *PatchMANAPIC; +//patch_t *PatchPOWERICN; +patch_t *PatchINVLFGEM1; +patch_t *PatchINVLFGEM2; +patch_t *PatchINVRTGEM1; +patch_t *PatchINVRTGEM2; +patch_t *PatchINumbers[10]; +patch_t *PatchNEGATIVE; +patch_t *PatchSmNumbers[10]; +patch_t *PatchBLACKSQ; +patch_t *PatchINVBAR; +patch_t *PatchARMCLEAR; +patch_t *PatchCHAINBACK; +//byte *ShadeTables; +int FontBNumBase; +int spinbooklump; +int spinflylump; + +// Toggle god mode +cheatseq_t CheatGodSeq = CHEAT("quicken", 0); + +// Toggle no clipping mode +cheatseq_t CheatNoClipSeq = CHEAT("kitty", 0); + +// Get all weapons and ammo +cheatseq_t CheatWeaponsSeq = CHEAT("rambo", 0); + +// Toggle tome of power +cheatseq_t CheatPowerSeq = CHEAT("shazam", 0); + +// Get full health +cheatseq_t CheatHealthSeq = CHEAT("ponce", 0); + +// Get all keys +cheatseq_t CheatKeysSeq = CHEAT("skel", 0); + +// Toggle sound debug info +cheatseq_t CheatSoundSeq = CHEAT("noise", 0); + +// Toggle ticker +cheatseq_t CheatTickerSeq = CHEAT("ticker", 0); + +// Get an artifact 1st stage (ask for type) +cheatseq_t CheatArtifact1Seq = CHEAT("gimme", 0); + +// Get an artifact 2nd stage (ask for count) +cheatseq_t CheatArtifact2Seq = CHEAT("gimme", 1); + +// Get an artifact final stage +cheatseq_t CheatArtifact3Seq = CHEAT("gimme", 2); + +// Warp to new level +cheatseq_t CheatWarpSeq = CHEAT("engage", 2); + +// Save a screenshot +cheatseq_t CheatChickenSeq = CHEAT("cockadoodledoo", 0); + +// Kill all monsters +cheatseq_t CheatMassacreSeq = CHEAT("massacre", 0); + +cheatseq_t CheatIDKFASeq = CHEAT("idkfa", 0); +cheatseq_t CheatIDDQDSeq = CHEAT("iddqd", 0); + +static Cheat_t Cheats[] = { + {CheatGodFunc, &CheatGodSeq}, + {CheatNoClipFunc, &CheatNoClipSeq}, + {CheatWeaponsFunc, &CheatWeaponsSeq}, + {CheatPowerFunc, &CheatPowerSeq}, + {CheatHealthFunc, &CheatHealthSeq}, + {CheatKeysFunc, &CheatKeysSeq}, + {CheatSoundFunc, &CheatSoundSeq}, + {CheatTickerFunc, &CheatTickerSeq}, + {CheatArtifact1Func, &CheatArtifact1Seq}, + {CheatArtifact2Func, &CheatArtifact2Seq}, + {CheatArtifact3Func, &CheatArtifact3Seq}, + {CheatWarpFunc, &CheatWarpSeq}, + {CheatChickenFunc, &CheatChickenSeq}, + {CheatMassacreFunc, &CheatMassacreSeq}, + {CheatIDKFAFunc, &CheatIDKFASeq}, + {CheatIDDQDFunc, &CheatIDDQDSeq}, + {NULL, NULL} +}; + +//--------------------------------------------------------------------------- +// +// PROC SB_Init +// +//--------------------------------------------------------------------------- + +void SB_Init(void) +{ + int i; + int startLump; + + PatchLTFACE = W_CacheLumpName(DEH_String("LTFACE"), PU_STATIC); + PatchRTFACE = W_CacheLumpName(DEH_String("RTFACE"), PU_STATIC); + PatchBARBACK = W_CacheLumpName(DEH_String("BARBACK"), PU_STATIC); + PatchINVBAR = W_CacheLumpName(DEH_String("INVBAR"), PU_STATIC); + PatchCHAIN = W_CacheLumpName(DEH_String("CHAIN"), PU_STATIC); + if (deathmatch) + { + PatchSTATBAR = W_CacheLumpName(DEH_String("STATBAR"), PU_STATIC); + } + else + { + PatchSTATBAR = W_CacheLumpName(DEH_String("LIFEBAR"), PU_STATIC); + } + if (!netgame) + { // single player game uses red life gem + PatchLIFEGEM = W_CacheLumpName(DEH_String("LIFEGEM2"), PU_STATIC); + } + else + { + PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName(DEH_String("LIFEGEM0")) + + consoleplayer, PU_STATIC); + } + PatchLTFCTOP = W_CacheLumpName(DEH_String("LTFCTOP"), PU_STATIC); + PatchRTFCTOP = W_CacheLumpName(DEH_String("RTFCTOP"), PU_STATIC); + PatchSELECTBOX = W_CacheLumpName(DEH_String("SELECTBOX"), PU_STATIC); + PatchINVLFGEM1 = W_CacheLumpName(DEH_String("INVGEML1"), PU_STATIC); + PatchINVLFGEM2 = W_CacheLumpName(DEH_String("INVGEML2"), PU_STATIC); + PatchINVRTGEM1 = W_CacheLumpName(DEH_String("INVGEMR1"), PU_STATIC); + PatchINVRTGEM2 = W_CacheLumpName(DEH_String("INVGEMR2"), PU_STATIC); + PatchBLACKSQ = W_CacheLumpName(DEH_String("BLACKSQ"), PU_STATIC); + PatchARMCLEAR = W_CacheLumpName(DEH_String("ARMCLEAR"), PU_STATIC); + PatchCHAINBACK = W_CacheLumpName(DEH_String("CHAINBACK"), PU_STATIC); + startLump = W_GetNumForName(DEH_String("IN0")); + for (i = 0; i < 10; i++) + { + PatchINumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); + } + PatchNEGATIVE = W_CacheLumpName(DEH_String("NEGNUM"), PU_STATIC); + FontBNumBase = W_GetNumForName(DEH_String("FONTB16")); + startLump = W_GetNumForName(DEH_String("SMALLIN0")); + for (i = 0; i < 10; i++) + { + PatchSmNumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); + } + playpalette = W_GetNumForName(DEH_String("PLAYPAL")); + spinbooklump = W_GetNumForName(DEH_String("SPINBK0")); + spinflylump = W_GetNumForName(DEH_String("SPFLY0")); +} + +//--------------------------------------------------------------------------- +// +// PROC SB_Ticker +// +//--------------------------------------------------------------------------- + +void SB_Ticker(void) +{ + int delta; + int curHealth; + + if (leveltime & 1) + { + ChainWiggle = P_Random() & 1; + } + curHealth = players[consoleplayer].mo->health; + if (curHealth < 0) + { + curHealth = 0; + } + if (curHealth < HealthMarker) + { + delta = (HealthMarker - curHealth) >> 2; + if (delta < 1) + { + delta = 1; + } + else if (delta > 8) + { + delta = 8; + } + HealthMarker -= delta; + } + else if (curHealth > HealthMarker) + { + delta = (curHealth - HealthMarker) >> 2; + if (delta < 1) + { + delta = 1; + } + else if (delta > 8) + { + delta = 8; + } + HealthMarker += delta; + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrINumber +// +// Draws a three digit number. +// +//--------------------------------------------------------------------------- + +static void DrINumber(signed int val, int x, int y) +{ + patch_t *patch; + int oldval; + + oldval = val; + if (val < 0) + { + if (val < -9) + { + V_DrawPatch(x + 1, y + 1, W_CacheLumpName(DEH_String("LAME"), PU_CACHE)); + } + else + { + val = -val; + V_DrawPatch(x + 18, y, PatchINumbers[val]); + V_DrawPatch(x + 9, y, PatchNEGATIVE); + } + return; + } + if (val > 99) + { + patch = PatchINumbers[val / 100]; + V_DrawPatch(x, y, patch); + } + val = val % 100; + if (val > 9 || oldval > 99) + { + patch = PatchINumbers[val / 10]; + V_DrawPatch(x + 9, y, patch); + } + val = val % 10; + patch = PatchINumbers[val]; + V_DrawPatch(x + 18, y, patch); +} + +//--------------------------------------------------------------------------- +// +// PROC DrBNumber +// +// Draws a three digit number using FontB +// +//--------------------------------------------------------------------------- + +static void DrBNumber(signed int val, int x, int y) +{ + patch_t *patch; + int xpos; + int oldval; + + oldval = val; + xpos = x; + if (val < 0) + { + val = 0; + } + if (val > 99) + { + patch = W_CacheLumpNum(FontBNumBase + val / 100, PU_CACHE); + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + } + val = val % 100; + xpos += 12; + if (val > 9 || oldval > 99) + { + patch = W_CacheLumpNum(FontBNumBase + val / 10, PU_CACHE); + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + } + val = val % 10; + xpos += 12; + patch = W_CacheLumpNum(FontBNumBase + val, PU_CACHE); + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); +} + +//--------------------------------------------------------------------------- +// +// PROC DrSmallNumber +// +// Draws a small two digit number. +// +//--------------------------------------------------------------------------- + +static void DrSmallNumber(int val, int x, int y) +{ + patch_t *patch; + + if (val == 1) + { + return; + } + if (val > 9) + { + patch = PatchSmNumbers[val / 10]; + V_DrawPatch(x, y, patch); + } + val = val % 10; + patch = PatchSmNumbers[val]; + V_DrawPatch(x + 4, y, patch); +} + +//--------------------------------------------------------------------------- +// +// PROC ShadeLine +// +//--------------------------------------------------------------------------- + +static void ShadeLine(int x, int y, int height, int shade) +{ + byte *dest; + byte *shades; + + shades = colormaps + 9 * 256 + shade * 2 * 256; + dest = I_VideoBuffer + y * SCREENWIDTH + x; + while (height--) + { + *(dest) = *(shades + *dest); + dest += SCREENWIDTH; + } +} + +//--------------------------------------------------------------------------- +// +// PROC ShadeChain +// +//--------------------------------------------------------------------------- + +static void ShadeChain(void) +{ + int i; + + for (i = 0; i < 16; i++) + { + ShadeLine(277 + i, 190, 10, i / 2); + ShadeLine(19 + i, 190, 10, 7 - (i / 2)); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSoundInfo +// +// Displays sound debugging information. +// +//--------------------------------------------------------------------------- + +static void DrawSoundInfo(void) +{ + int i; + SoundInfo_t s; + ChanInfo_t *c; + char text[32]; + int x; + int y; + int xPos[7] = { 1, 75, 112, 156, 200, 230, 260 }; + + if (leveltime & 16) + { + MN_DrTextA(DEH_String("*** SOUND DEBUG INFO ***"), xPos[0], 20); + } + S_GetChannelInfo(&s); + if (s.channelCount == 0) + { + return; + } + x = 0; + MN_DrTextA(DEH_String("NAME"), xPos[x++], 30); + MN_DrTextA(DEH_String("MO.T"), xPos[x++], 30); + MN_DrTextA(DEH_String("MO.X"), xPos[x++], 30); + MN_DrTextA(DEH_String("MO.Y"), xPos[x++], 30); + MN_DrTextA(DEH_String("ID"), xPos[x++], 30); + MN_DrTextA(DEH_String("PRI"), xPos[x++], 30); + MN_DrTextA(DEH_String("DIST"), xPos[x++], 30); + for (i = 0; i < s.channelCount; i++) + { + c = &s.chan[i]; + x = 0; + y = 40 + i * 10; + if (c->mo == NULL) + { // Channel is unused + MN_DrTextA(DEH_String("------"), xPos[0], y); + continue; + } + M_snprintf(text, sizeof(text), "%s", c->name); + M_ForceUppercase(text); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->mo->type); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->id); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->priority); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->distance); + MN_DrTextA(text, xPos[x++], y); + } + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; +} + +//--------------------------------------------------------------------------- +// +// PROC SB_Drawer +// +//--------------------------------------------------------------------------- + +char patcharti[][10] = { + {"ARTIBOX"}, // none + {"ARTIINVU"}, // invulnerability + {"ARTIINVS"}, // invisibility + {"ARTIPTN2"}, // health + {"ARTISPHL"}, // superhealth + {"ARTIPWBK"}, // tomeofpower + {"ARTITRCH"}, // torch + {"ARTIFBMB"}, // firebomb + {"ARTIEGGC"}, // egg + {"ARTISOAR"}, // fly + {"ARTIATLP"} // teleport +}; + +char ammopic[][10] = { + {"INAMGLD"}, + {"INAMBOW"}, + {"INAMBST"}, + {"INAMRAM"}, + {"INAMPNX"}, + {"INAMLOB"} +}; + +int SB_state = -1; +static int oldarti = 0; +static int oldartiCount = 0; +static int oldfrags = -9999; +static int oldammo = -1; +static int oldarmor = -1; +static int oldweapon = -1; +static int oldhealth = -1; +static int oldlife = -1; +static int oldkeys = -1; + +int playerkeys = 0; + + +void SB_Drawer(void) +{ + int frame; + static boolean hitCenterFrame; + + // Sound info debug stuff + if (DebugSound == true) + { + DrawSoundInfo(); + } + CPlayer = &players[consoleplayer]; + if (viewheight == SCREENHEIGHT && !automapactive) + { + DrawFullScreenStuff(); + SB_state = -1; + } + else + { + if (SB_state == -1) + { + V_DrawPatch(0, 158, PatchBARBACK); + if (players[consoleplayer].cheats & CF_GODMODE) + { + V_DrawPatch(16, 167, + W_CacheLumpName(DEH_String("GOD1"), PU_CACHE)); + V_DrawPatch(287, 167, + W_CacheLumpName(DEH_String("GOD2"), PU_CACHE)); + } + oldhealth = -1; + } + DrawCommonBar(); + if (!inventory) + { + if (SB_state != 0) + { + // Main interface + V_DrawPatch(34, 160, PatchSTATBAR); + oldarti = 0; + oldammo = -1; + oldarmor = -1; + oldweapon = -1; + oldfrags = -9999; //can't use -1, 'cuz of negative frags + oldlife = -1; + oldkeys = -1; + } + DrawMainBar(); + SB_state = 0; + } + else + { + if (SB_state != 1) + { + V_DrawPatch(34, 160, PatchINVBAR); + } + DrawInventoryBar(); + SB_state = 1; + } + } + SB_PaletteFlash(); + + // Flight icons + if (CPlayer->powers[pw_flight]) + { + if (CPlayer->powers[pw_flight] > BLINKTHRESHOLD + || !(CPlayer->powers[pw_flight] & 16)) + { + frame = (leveltime / 3) & 15; + if (CPlayer->mo->flags2 & MF2_FLY) + { + if (hitCenterFrame && (frame != 15 && frame != 0)) + { + V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + 15, + PU_CACHE)); + } + else + { + V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + frame, + PU_CACHE)); + hitCenterFrame = false; + } + } + else + { + if (!hitCenterFrame && (frame != 15 && frame != 0)) + { + V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + frame, + PU_CACHE)); + hitCenterFrame = false; + } + else + { + V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + 15, + PU_CACHE)); + hitCenterFrame = true; + } + } + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + else + { + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + } + + if (CPlayer->powers[pw_weaponlevel2] && !CPlayer->chickenTics) + { + if (CPlayer->powers[pw_weaponlevel2] > BLINKTHRESHOLD + || !(CPlayer->powers[pw_weaponlevel2] & 16)) + { + frame = (leveltime / 3) & 15; + V_DrawPatch(300, 17, + W_CacheLumpNum(spinbooklump + frame, PU_CACHE)); + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + else + { + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + } +/* + if(CPlayer->powers[pw_weaponlevel2] > BLINKTHRESHOLD + || (CPlayer->powers[pw_weaponlevel2]&8)) + { + V_DrawPatch(291, 0, W_CacheLumpName("ARTIPWBK", PU_CACHE)); + } + else + { + BorderTopRefresh = true; + } + } +*/ +} + +// sets the new palette based upon current values of player->damagecount +// and player->bonuscount +void SB_PaletteFlash(void) +{ + static int sb_palette = 0; + int palette; + byte *pal; + + CPlayer = &players[consoleplayer]; + + if (CPlayer->damagecount) + { + palette = (CPlayer->damagecount + 7) >> 3; + if (palette >= NUMREDPALS) + { + palette = NUMREDPALS - 1; + } + palette += STARTREDPALS; + } + else if (CPlayer->bonuscount) + { + palette = (CPlayer->bonuscount + 7) >> 3; + if (palette >= NUMBONUSPALS) + { + palette = NUMBONUSPALS - 1; + } + palette += STARTBONUSPALS; + } + else + { + palette = 0; + } + if (palette != sb_palette) + { + sb_palette = palette; + pal = (byte *) W_CacheLumpNum(playpalette, PU_CACHE) + palette * 768; + I_SetPalette(pal); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawCommonBar +// +//--------------------------------------------------------------------------- + +void DrawCommonBar(void) +{ + int chainY; + int healthPos; + + V_DrawPatch(0, 148, PatchLTFCTOP); + V_DrawPatch(290, 148, PatchRTFCTOP); + + if (oldhealth != HealthMarker) + { + oldhealth = HealthMarker; + healthPos = HealthMarker; + if (healthPos < 0) + { + healthPos = 0; + } + if (healthPos > 100) + { + healthPos = 100; + } + healthPos = (healthPos * 256) / 100; + chainY = + (HealthMarker == CPlayer->mo->health) ? 191 : 191 + ChainWiggle; + V_DrawPatch(0, 190, PatchCHAINBACK); + V_DrawPatch(2 + (healthPos % 17), chainY, PatchCHAIN); + V_DrawPatch(17 + healthPos, chainY, PatchLIFEGEM); + V_DrawPatch(0, 190, PatchLTFACE); + V_DrawPatch(276, 190, PatchRTFACE); + ShadeChain(); + UpdateState |= I_STATBAR; + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawMainBar +// +//--------------------------------------------------------------------------- + +void DrawMainBar(void) +{ + int i; + int temp; + + // Ready artifact + if (ArtifactFlash) + { + V_DrawPatch(180, 161, PatchBLACKSQ); + + temp = W_GetNumForName(DEH_String("useartia")) + ArtifactFlash - 1; + + V_DrawPatch(182, 161, W_CacheLumpNum(temp, PU_CACHE)); + ArtifactFlash--; + oldarti = -1; // so that the correct artifact fills in after the flash + UpdateState |= I_STATBAR; + } + else if (oldarti != CPlayer->readyArtifact + || oldartiCount != CPlayer->inventory[inv_ptr].count) + { + V_DrawPatch(180, 161, PatchBLACKSQ); + if (CPlayer->readyArtifact > 0) + { + V_DrawPatch(179, 160, + W_CacheLumpName(DEH_String(patcharti[CPlayer->readyArtifact]), + PU_CACHE)); + DrSmallNumber(CPlayer->inventory[inv_ptr].count, 201, 182); + } + oldarti = CPlayer->readyArtifact; + oldartiCount = CPlayer->inventory[inv_ptr].count; + UpdateState |= I_STATBAR; + } + + // Frags + if (deathmatch) + { + temp = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + temp += CPlayer->frags[i]; + } + if (temp != oldfrags) + { + V_DrawPatch(57, 171, PatchARMCLEAR); + DrINumber(temp, 61, 170); + oldfrags = temp; + UpdateState |= I_STATBAR; + } + } + else + { + temp = HealthMarker; + if (temp < 0) + { + temp = 0; + } + else if (temp > 100) + { + temp = 100; + } + if (oldlife != temp) + { + oldlife = temp; + V_DrawPatch(57, 171, PatchARMCLEAR); + DrINumber(temp, 61, 170); + UpdateState |= I_STATBAR; + } + } + + // Keys + if (oldkeys != playerkeys) + { + if (CPlayer->keys[key_yellow]) + { + V_DrawPatch(153, 164, W_CacheLumpName(DEH_String("ykeyicon"), PU_CACHE)); + } + if (CPlayer->keys[key_green]) + { + V_DrawPatch(153, 172, W_CacheLumpName(DEH_String("gkeyicon"), PU_CACHE)); + } + if (CPlayer->keys[key_blue]) + { + V_DrawPatch(153, 180, W_CacheLumpName(DEH_String("bkeyicon"), PU_CACHE)); + } + oldkeys = playerkeys; + UpdateState |= I_STATBAR; + } + // Ammo + temp = CPlayer->ammo[wpnlev1info[CPlayer->readyweapon].ammo]; + if (oldammo != temp || oldweapon != CPlayer->readyweapon) + { + V_DrawPatch(108, 161, PatchBLACKSQ); + if (temp && CPlayer->readyweapon > 0 && CPlayer->readyweapon < 7) + { + DrINumber(temp, 109, 162); + V_DrawPatch(111, 172, + W_CacheLumpName(DEH_String(ammopic[CPlayer->readyweapon - 1]), + PU_CACHE)); + } + oldammo = temp; + oldweapon = CPlayer->readyweapon; + UpdateState |= I_STATBAR; + } + + // Armor + if (oldarmor != CPlayer->armorpoints) + { + V_DrawPatch(224, 171, PatchARMCLEAR); + DrINumber(CPlayer->armorpoints, 228, 170); + oldarmor = CPlayer->armorpoints; + UpdateState |= I_STATBAR; + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawInventoryBar +// +//--------------------------------------------------------------------------- + +void DrawInventoryBar(void) +{ + const char *patch; + int i; + int x; + + x = inv_ptr - curpos; + UpdateState |= I_STATBAR; + V_DrawPatch(34, 160, PatchINVBAR); + for (i = 0; i < 7; i++) + { + //V_DrawPatch(50+i*31, 160, W_CacheLumpName("ARTIBOX", PU_CACHE)); + if (CPlayer->inventorySlotNum > x + i + && CPlayer->inventory[x + i].type != arti_none) + { + patch = DEH_String(patcharti[CPlayer->inventory[x + i].type]); + + V_DrawPatch(50 + i * 31, 160, W_CacheLumpName(patch, PU_CACHE)); + DrSmallNumber(CPlayer->inventory[x + i].count, 69 + i * 31, 182); + } + } + V_DrawPatch(50 + curpos * 31, 189, PatchSELECTBOX); + if (x != 0) + { + V_DrawPatch(38, 159, !(leveltime & 4) ? PatchINVLFGEM1 : + PatchINVLFGEM2); + } + if (CPlayer->inventorySlotNum - x > 7) + { + V_DrawPatch(269, 159, !(leveltime & 4) ? + PatchINVRTGEM1 : PatchINVRTGEM2); + } +} + +void DrawFullScreenStuff(void) +{ + const char *patch; + int i; + int x; + int temp; + + UpdateState |= I_FULLSCRN; + if (CPlayer->mo->health > 0) + { + DrBNumber(CPlayer->mo->health, 5, 180); + } + else + { + DrBNumber(0, 5, 180); + } + if (deathmatch) + { + temp = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + temp += CPlayer->frags[i]; + } + } + DrINumber(temp, 45, 185); + } + if (!inventory) + { + if (CPlayer->readyArtifact > 0) + { + patch = DEH_String(patcharti[CPlayer->readyArtifact]); + V_DrawAltTLPatch(286, 170, W_CacheLumpName(DEH_String("ARTIBOX"), PU_CACHE)); + V_DrawPatch(286, 170, W_CacheLumpName(patch, PU_CACHE)); + DrSmallNumber(CPlayer->inventory[inv_ptr].count, 307, 192); + } + } + else + { + x = inv_ptr - curpos; + for (i = 0; i < 7; i++) + { + V_DrawAltTLPatch(50 + i * 31, 168, + W_CacheLumpName(DEH_String("ARTIBOX"), PU_CACHE)); + if (CPlayer->inventorySlotNum > x + i + && CPlayer->inventory[x + i].type != arti_none) + { + patch = DEH_String(patcharti[CPlayer->inventory[x + i].type]); + V_DrawPatch(50 + i * 31, 168, + W_CacheLumpName(patch, PU_CACHE)); + DrSmallNumber(CPlayer->inventory[x + i].count, 69 + i * 31, + 190); + } + } + V_DrawPatch(50 + curpos * 31, 197, PatchSELECTBOX); + if (x != 0) + { + V_DrawPatch(38, 167, !(leveltime & 4) ? PatchINVLFGEM1 : + PatchINVLFGEM2); + } + if (CPlayer->inventorySlotNum - x > 7) + { + V_DrawPatch(269, 167, !(leveltime & 4) ? + PatchINVRTGEM1 : PatchINVRTGEM2); + } + } +} + +//-------------------------------------------------------------------------- +// +// FUNC SB_Responder +// +//-------------------------------------------------------------------------- + +boolean SB_Responder(event_t * event) +{ + if (event->type == ev_keydown) + { + if (HandleCheats(event->data1)) + { // Need to eat the key + return (true); + } + } + return (false); +} + +//-------------------------------------------------------------------------- +// +// FUNC HandleCheats +// +// Returns true if the caller should eat the key. +// +//-------------------------------------------------------------------------- + +static boolean HandleCheats(byte key) +{ + int i; + boolean eat; + + if (netgame || gameskill == sk_nightmare) + { // Can't cheat in a net-game, or in nightmare mode + return (false); + } + if (players[consoleplayer].health <= 0) + { // Dead players can't cheat + return (false); + } + eat = false; + for (i = 0; Cheats[i].func != NULL; i++) + { + if (cht_CheckCheat(Cheats[i].seq, key)) + { + Cheats[i].func(&players[consoleplayer], &Cheats[i]); + S_StartSound(NULL, sfx_dorcls); + } + } + return (eat); +} + +//-------------------------------------------------------------------------- +// +// CHEAT FUNCTIONS +// +//-------------------------------------------------------------------------- + +static void CheatGodFunc(player_t * player, Cheat_t * cheat) +{ + player->cheats ^= CF_GODMODE; + if (player->cheats & CF_GODMODE) + { + P_SetMessage(player, DEH_String(TXT_CHEATGODON), false); + } + else + { + P_SetMessage(player, DEH_String(TXT_CHEATGODOFF), false); + } + SB_state = -1; +} + +static void CheatNoClipFunc(player_t * player, Cheat_t * cheat) +{ + player->cheats ^= CF_NOCLIP; + if (player->cheats & CF_NOCLIP) + { + P_SetMessage(player, DEH_String(TXT_CHEATNOCLIPON), false); + } + else + { + P_SetMessage(player, DEH_String(TXT_CHEATNOCLIPOFF), false); + } +} + +static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat) +{ + int i; + + player->armorpoints = 200; + player->armortype = 2; + if (!player->backpack) + { + for (i = 0; i < NUMAMMO; i++) + { + player->maxammo[i] *= 2; + } + player->backpack = true; + } + for (i = 0; i < NUMWEAPONS - 1; i++) + { + player->weaponowned[i] = true; + } + if (gamemode == shareware) + { + player->weaponowned[wp_skullrod] = false; + player->weaponowned[wp_phoenixrod] = false; + player->weaponowned[wp_mace] = false; + } + for (i = 0; i < NUMAMMO; i++) + { + player->ammo[i] = player->maxammo[i]; + } + P_SetMessage(player, DEH_String(TXT_CHEATWEAPONS), false); +} + +static void CheatPowerFunc(player_t * player, Cheat_t * cheat) +{ + if (player->powers[pw_weaponlevel2]) + { + player->powers[pw_weaponlevel2] = 0; + P_SetMessage(player, DEH_String(TXT_CHEATPOWEROFF), false); + } + else + { + P_UseArtifact(player, arti_tomeofpower); + P_SetMessage(player, DEH_String(TXT_CHEATPOWERON), false); + } +} + +static void CheatHealthFunc(player_t * player, Cheat_t * cheat) +{ + if (player->chickenTics) + { + player->health = player->mo->health = MAXCHICKENHEALTH; + } + else + { + player->health = player->mo->health = MAXHEALTH; + } + P_SetMessage(player, DEH_String(TXT_CHEATHEALTH), false); +} + +static void CheatKeysFunc(player_t * player, Cheat_t * cheat) +{ + player->keys[key_yellow] = true; + player->keys[key_green] = true; + player->keys[key_blue] = true; + playerkeys = 7; // Key refresh flags + P_SetMessage(player, DEH_String(TXT_CHEATKEYS), false); +} + +static void CheatSoundFunc(player_t * player, Cheat_t * cheat) +{ + DebugSound = !DebugSound; + if (DebugSound) + { + P_SetMessage(player, DEH_String(TXT_CHEATSOUNDON), false); + } + else + { + P_SetMessage(player, DEH_String(TXT_CHEATSOUNDOFF), false); + } +} + +static void CheatTickerFunc(player_t * player, Cheat_t * cheat) +{ + DisplayTicker = !DisplayTicker; + if (DisplayTicker) + { + P_SetMessage(player, DEH_String(TXT_CHEATTICKERON), false); + } + else + { + P_SetMessage(player, DEH_String(TXT_CHEATTICKEROFF), false); + } + + I_DisplayFPSDots(DisplayTicker); +} + +static void CheatArtifact1Func(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS1), false); +} + +static void CheatArtifact2Func(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS2), false); +} + +static void CheatArtifact3Func(player_t * player, Cheat_t * cheat) +{ + char args[2]; + int i; + int j; + int type; + int count; + + cht_GetParam(cheat->seq, args); + type = args[0] - 'a' + 1; + count = args[1] - '0'; + if (type == 26 && count == 0) + { // All artifacts + for (i = arti_none + 1; i < NUMARTIFACTS; i++) + { + if (gamemode == shareware + && (i == arti_superhealth || i == arti_teleport)) + { + continue; + } + for (j = 0; j < 16; j++) + { + P_GiveArtifact(player, i, NULL); + } + } + P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS3), false); + } + else if (type > arti_none && type < NUMARTIFACTS + && count > 0 && count < 10) + { + if (gamemode == shareware + && (type == arti_superhealth || type == arti_teleport)) + { + P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTSFAIL), false); + return; + } + for (i = 0; i < count; i++) + { + P_GiveArtifact(player, type, NULL); + } + P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS3), false); + } + else + { // Bad input + P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTSFAIL), false); + } +} + +static void CheatWarpFunc(player_t * player, Cheat_t * cheat) +{ + char args[2]; + int episode; + int map; + + cht_GetParam(cheat->seq, args); + + episode = args[0] - '0'; + map = args[1] - '0'; + if (D_ValidEpisodeMap(heretic, gamemode, episode, map)) + { + G_DeferedInitNew(gameskill, episode, map); + P_SetMessage(player, DEH_String(TXT_CHEATWARP), false); + } +} + +static void CheatChickenFunc(player_t * player, Cheat_t * cheat) +{ + if (player->chickenTics) + { + if (P_UndoPlayerChicken(player)) + { + P_SetMessage(player, DEH_String(TXT_CHEATCHICKENOFF), false); + } + } + else if (P_ChickenMorphPlayer(player)) + { + P_SetMessage(player, DEH_String(TXT_CHEATCHICKENON), false); + } +} + +static void CheatMassacreFunc(player_t * player, Cheat_t * cheat) +{ + P_Massacre(); + P_SetMessage(player, DEH_String(TXT_CHEATMASSACRE), false); +} + +static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat) +{ + int i; + if (player->chickenTics) + { + return; + } + for (i = 1; i < 8; i++) + { + player->weaponowned[i] = false; + } + player->pendingweapon = wp_staff; + P_SetMessage(player, DEH_String(TXT_CHEATIDKFA), true); +} + +static void CheatIDDQDFunc(player_t * player, Cheat_t * cheat) +{ + P_DamageMobj(player->mo, NULL, player->mo, 10000); + P_SetMessage(player, DEH_String(TXT_CHEATIDDQD), true); +} diff --git a/games/NXDoom/src/heretic/sounds.c b/games/NXDoom/src/heretic/sounds.c new file mode 100644 index 00000000000..3e1dda157ad --- /dev/null +++ b/games/NXDoom/src/heretic/sounds.c @@ -0,0 +1,249 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// sounds.c + +#include "doomdef.h" +#include "i_sound.h" +#include "sounds.h" + +// Music info + +#define MUSIC(name) \ + { name, 0, NULL, NULL } + +musicinfo_t S_music[] = { + MUSIC("MUS_E1M1"), // 1-1 + MUSIC("MUS_E1M2"), + MUSIC("MUS_E1M3"), + MUSIC("MUS_E1M4"), + MUSIC("MUS_E1M5"), + MUSIC("MUS_E1M6"), + MUSIC("MUS_E1M7"), + MUSIC("MUS_E1M8"), + MUSIC("MUS_E1M9"), + + MUSIC("MUS_E2M1"), // 2-1 + MUSIC("MUS_E2M2"), + MUSIC("MUS_E2M3"), + MUSIC("MUS_E2M4"), + MUSIC("MUS_E1M4"), + MUSIC("MUS_E2M6"), + MUSIC("MUS_E2M7"), + MUSIC("MUS_E2M8"), + MUSIC("MUS_E2M9"), + + MUSIC("MUS_E1M1"), // 3-1 + MUSIC("MUS_E3M2"), + MUSIC("MUS_E3M3"), + MUSIC("MUS_E1M6"), + MUSIC("MUS_E1M3"), + MUSIC("MUS_E1M2"), + MUSIC("MUS_E1M5"), + MUSIC("MUS_E1M9"), + MUSIC("MUS_E2M6"), + + MUSIC("MUS_E1M6"), // 4-1 + MUSIC("MUS_E1M2"), + MUSIC("MUS_E1M3"), + MUSIC("MUS_E1M4"), + MUSIC("MUS_E1M5"), + MUSIC("MUS_E1M1"), + MUSIC("MUS_E1M7"), + MUSIC("MUS_E1M8"), + MUSIC("MUS_E1M9"), + + MUSIC("MUS_E2M1"), // 5-1 + MUSIC("MUS_E2M2"), + MUSIC("MUS_E2M3"), + MUSIC("MUS_E2M4"), + MUSIC("MUS_E1M4"), + MUSIC("MUS_E2M6"), + MUSIC("MUS_E2M7"), + MUSIC("MUS_E2M8"), + MUSIC("MUS_E2M9"), + + MUSIC("MUS_E3M2"), // 6-1 + MUSIC("MUS_E3M3"), // 6-2 + MUSIC("MUS_E1M6"), // 6-3 + + MUSIC("MUS_TITL"), + MUSIC("MUS_INTR"), + MUSIC("MUS_CPTD") +}; + +// Sound info + + /* Macro for original heretic sfxinfo_t +#define SOUND(name, priority, numchannels) \ + { name, NULL, priority, -1, NULL, 0, numchannels } +#define SOUND_LINK(name, link_id, priority, numchannels) \ + { name, &S_sfx[link_id], priority, -1, NULL, 0, numchannels } + */ + +#define SOUND(name, priority, numchannels) \ + { NULL, name, priority, NULL, -1, -1, -1, 0, numchannels, NULL } +#define SOUND_LINK(name, link_id, priority, numchannels) \ + { NULL, name, priority, &S_sfx[link_id], 0, 0, -1, 0, numchannels, NULL } + +sfxinfo_t S_sfx[] = { + SOUND("", 0, 0), + SOUND("gldhit", 32, 2), + SOUND("gntful", 32, -1), + SOUND("gnthit", 32, -1), + SOUND("gntpow", 32, -1), + SOUND("gntact", 32, -1), + SOUND("gntuse", 32, -1), + SOUND("phosht", 32, 2), + SOUND("phohit", 32, -1), + SOUND_LINK("-phopow", sfx_hedat1, 32, 1), + SOUND("lobsht", 20, 2), + SOUND("lobhit", 20, 2), + SOUND("lobpow", 20, 2), + SOUND("hrnsht", 32, 2), + SOUND("hrnhit", 32, 2), + SOUND("hrnpow", 32, 2), + SOUND("ramphit", 32, 2), + SOUND("ramrain", 10, 2), + SOUND("bowsht", 32, 2), + SOUND("stfhit", 32, 2), + SOUND("stfpow", 32, 2), + SOUND("stfcrk", 32, 2), + SOUND("impsit", 32, 2), + SOUND("impat1", 32, 2), + SOUND("impat2", 32, 2), + SOUND("impdth", 80, 2), + SOUND_LINK("-impact", sfx_impsit, 20, 2), + SOUND("imppai", 32, 2), + SOUND("mumsit", 32, 2), + SOUND("mumat1", 32, 2), + SOUND("mumat2", 32, 2), + SOUND("mumdth", 80, 2), + SOUND_LINK("-mumact", sfx_mumsit, 20, 2), + SOUND("mumpai", 32, 2), + SOUND("mumhed", 32, 2), + SOUND("bstsit", 32, 2), + SOUND("bstatk", 32, 2), + SOUND("bstdth", 80, 2), + SOUND("bstact", 20, 2), + SOUND("bstpai", 32, 2), + SOUND("clksit", 32, 2), + SOUND("clkatk", 32, 2), + SOUND("clkdth", 80, 2), + SOUND("clkact", 20, 2), + SOUND("clkpai", 32, 2), + SOUND("snksit", 32, 2), + SOUND("snkatk", 32, 2), + SOUND("snkdth", 80, 2), + SOUND("snkact", 20, 2), + SOUND("snkpai", 32, 2), + SOUND("kgtsit", 32, 2), + SOUND("kgtatk", 32, 2), + SOUND("kgtat2", 32, 2), + SOUND("kgtdth", 80, 2), + SOUND_LINK("-kgtact", sfx_kgtsit, 20, 2), + SOUND("kgtpai", 32, 2), + SOUND("wizsit", 32, 2), + SOUND("wizatk", 32, 2), + SOUND("wizdth", 80, 2), + SOUND("wizact", 20, 2), + SOUND("wizpai", 32, 2), + SOUND("minsit", 32, 2), + SOUND("minat1", 32, 2), + SOUND("minat2", 32, 2), + SOUND("minat3", 32, 2), + SOUND("mindth", 80, 2), + SOUND("minact", 20, 2), + SOUND("minpai", 32, 2), + SOUND("hedsit", 32, 2), + SOUND("hedat1", 32, 2), + SOUND("hedat2", 32, 2), + SOUND("hedat3", 32, 2), + SOUND("heddth", 80, 2), + SOUND("hedact", 20, 2), + SOUND("hedpai", 32, 2), + SOUND("sorzap", 32, 2), + SOUND("sorrise", 32, 2), + SOUND("sorsit", 200, 2), + SOUND("soratk", 32, 2), + SOUND("soract", 200, 2), + SOUND("sorpai", 200, 2), + SOUND("sordsph", 200, 2), + SOUND("sordexp", 200, 2), + SOUND("sordbon", 200, 2), + SOUND_LINK("-sbtsit", sfx_bstsit, 32, 2), + SOUND_LINK("-sbtatk", sfx_bstatk, 32, 2), + SOUND("sbtdth", 80, 2), + SOUND("sbtact", 20, 2), + SOUND("sbtpai", 32, 2), + SOUND("plroof", 32, 2), + SOUND("plrpai", 32, 2), + SOUND("plrdth", 80, 2), + SOUND("gibdth", 100, 2), + SOUND("plrwdth", 80, 2), + SOUND("plrcdth", 100, 2), + SOUND("itemup", 32, 2), + SOUND("wpnup", 32, 2), + SOUND("telept", 50, 2), + SOUND("doropn", 40, 2), + SOUND("dorcls", 40, 2), + SOUND("dormov", 40, 2), + SOUND("artiup", 32, 2), + SOUND("switch", 40, 2), + SOUND("pstart", 40, 2), + SOUND("pstop", 40, 2), + SOUND("stnmov", 40, 2), + SOUND("chicpai", 32, 2), + SOUND("chicatk", 32, 2), + SOUND("chicdth", 40, 2), + SOUND("chicact", 32, 2), + SOUND("chicpk1", 32, 2), + SOUND("chicpk2", 32, 2), + SOUND("chicpk3", 32, 2), + SOUND("keyup", 50, 2), + SOUND("ripslop", 16, 2), + SOUND("newpod", 16, -1), + SOUND("podexp", 40, -1), + SOUND("bounce", 16, 2), + SOUND_LINK("-volsht", sfx_bstatk, 16, 2), + SOUND_LINK("-volhit", sfx_lobhit, 16, 2), + SOUND("burn", 10, 2), + SOUND("splash", 10, 1), + SOUND("gloop", 10, 2), + SOUND("respawn", 10, 1), + SOUND("blssht", 32, 2), + SOUND("blshit", 32, 2), + SOUND("chat", 100, 1), + SOUND("artiuse", 32, 1), + SOUND("gfrag", 100, 1), + SOUND("waterfl", 16, 2), + + // Monophonic sounds + + SOUND("wind", 16, 1), + SOUND("amb1", 1, 1), + SOUND("amb2", 1, 1), + SOUND("amb3", 1, 1), + SOUND("amb4", 1, 1), + SOUND("amb5", 1, 1), + SOUND("amb6", 1, 1), + SOUND("amb7", 1, 1), + SOUND("amb8", 1, 1), + SOUND("amb9", 1, 1), + SOUND("amb10", 1, 1), + SOUND("amb11", 1, 0) +}; diff --git a/games/NXDoom/src/heretic/sounds.h b/games/NXDoom/src/heretic/sounds.h new file mode 100644 index 00000000000..f49b0279843 --- /dev/null +++ b/games/NXDoom/src/heretic/sounds.h @@ -0,0 +1,291 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// sounds.h + +#ifndef __SOUNDSH__ +#define __SOUNDSH__ + +#include "i_sound.h" + +#define MAX_SND_DIST 1600 +#define MAX_CHANNELS 16 + +// Music identifiers + +typedef enum +{ + mus_e1m1, + mus_e1m2, + mus_e1m3, + mus_e1m4, + mus_e1m5, + mus_e1m6, + mus_e1m7, + mus_e1m8, + mus_e1m9, + + mus_e2m1, + mus_e2m2, + mus_e2m3, + mus_e2m4, + mus_e2m5, + mus_e2m6, + mus_e2m7, + mus_e2m8, + mus_e2m9, + + mus_e3m1, + mus_e3m2, + mus_e3m3, + mus_e3m4, + mus_e3m5, + mus_e3m6, + mus_e3m7, + mus_e3m8, + mus_e3m9, + + mus_e4m1, + mus_e4m2, + mus_e4m3, + mus_e4m4, + mus_e4m5, + mus_e4m6, + mus_e4m7, + mus_e4m8, + mus_e4m9, + + mus_e5m1, + mus_e5m2, + mus_e5m3, + mus_e5m4, + mus_e5m5, + mus_e5m6, + mus_e5m7, + mus_e5m8, + mus_e5m9, + + mus_e6m1, + mus_e6m2, + mus_e6m3, + + mus_titl, + mus_intr, + mus_cptd, + NUMMUSIC +} musicenum_t; + +#if 0 +typedef struct +{ + char name[8]; +} musicinfo_t; + +typedef struct sfxinfo_s +{ + char name[8]; + struct sfxinfo_s *link; // Make alias for another sound + unsigned short priority; // Higher priority takes precendence + int usefulness; // Determines when a sound should be cached out + void *snd_ptr; + int lumpnum; + int numchannels; // total number of channels a sound type may occupy +} sfxinfo_t; + +#endif + +typedef struct +{ + mobj_t *mo; + int sound_id; + int handle; + int pitch; + int priority; +} channel_t; + +typedef struct +{ + int id; + unsigned short priority; + char *name; + mobj_t *mo; + int distance; +} ChanInfo_t; + +typedef struct +{ + int channelCount; + int musicVolume; + int soundVolume; + ChanInfo_t chan[8]; +} SoundInfo_t; + +// Sound identifiers + +typedef enum +{ + sfx_None, + sfx_gldhit, + sfx_gntful, + sfx_gnthit, + sfx_gntpow, + sfx_gntact, + sfx_gntuse, + sfx_phosht, + sfx_phohit, + sfx_phopow, + sfx_lobsht, + sfx_lobhit, + sfx_lobpow, + sfx_hrnsht, + sfx_hrnhit, + sfx_hrnpow, + sfx_ramphit, + sfx_ramrain, + sfx_bowsht, + sfx_stfhit, + sfx_stfpow, + sfx_stfcrk, + sfx_impsit, + sfx_impat1, + sfx_impat2, + sfx_impdth, + sfx_impact, + sfx_imppai, + sfx_mumsit, + sfx_mumat1, + sfx_mumat2, + sfx_mumdth, + sfx_mumact, + sfx_mumpai, + sfx_mumhed, + sfx_bstsit, + sfx_bstatk, + sfx_bstdth, + sfx_bstact, + sfx_bstpai, + sfx_clksit, + sfx_clkatk, + sfx_clkdth, + sfx_clkact, + sfx_clkpai, + sfx_snksit, + sfx_snkatk, + sfx_snkdth, + sfx_snkact, + sfx_snkpai, + sfx_kgtsit, + sfx_kgtatk, + sfx_kgtat2, + sfx_kgtdth, + sfx_kgtact, + sfx_kgtpai, + sfx_wizsit, + sfx_wizatk, + sfx_wizdth, + sfx_wizact, + sfx_wizpai, + sfx_minsit, + sfx_minat1, + sfx_minat2, + sfx_minat3, + sfx_mindth, + sfx_minact, + sfx_minpai, + sfx_hedsit, + sfx_hedat1, + sfx_hedat2, + sfx_hedat3, + sfx_heddth, + sfx_hedact, + sfx_hedpai, + sfx_sorzap, + sfx_sorrise, + sfx_sorsit, + sfx_soratk, + sfx_soract, + sfx_sorpai, + sfx_sordsph, + sfx_sordexp, + sfx_sordbon, + sfx_sbtsit, + sfx_sbtatk, + sfx_sbtdth, + sfx_sbtact, + sfx_sbtpai, + sfx_plroof, + sfx_plrpai, + sfx_plrdth, // Normal + sfx_gibdth, // Extreme + sfx_plrwdth, // Wimpy + sfx_plrcdth, // Crazy + sfx_itemup, + sfx_wpnup, + sfx_telept, + sfx_doropn, + sfx_dorcls, + sfx_dormov, + sfx_artiup, + sfx_switch, + sfx_pstart, + sfx_pstop, + sfx_stnmov, + sfx_chicpai, + sfx_chicatk, + sfx_chicdth, + sfx_chicact, + sfx_chicpk1, + sfx_chicpk2, + sfx_chicpk3, + sfx_keyup, + sfx_ripslop, + sfx_newpod, + sfx_podexp, + sfx_bounce, + sfx_volsht, + sfx_volhit, + sfx_burn, + sfx_splash, + sfx_gloop, + sfx_respawn, + sfx_blssht, + sfx_blshit, + sfx_chat, + sfx_artiuse, + sfx_gfrag, + sfx_waterfl, + + // Monophonic sounds + + sfx_wind, + sfx_amb1, + sfx_amb2, + sfx_amb3, + sfx_amb4, + sfx_amb5, + sfx_amb6, + sfx_amb7, + sfx_amb8, + sfx_amb9, + sfx_amb10, + sfx_amb11, + NUMSFX +} sfxenum_t; + +extern sfxinfo_t S_sfx[]; +extern musicinfo_t S_music[]; + +#endif diff --git a/games/NXDoom/src/hexen-res.rc.in b/games/NXDoom/src/hexen-res.rc.in new file mode 100644 index 00000000000..b2b811b6027 --- /dev/null +++ b/games/NXDoom/src/hexen-res.rc.in @@ -0,0 +1,30 @@ +1 ICON "@top_srcdir@/data/hexen.ico" + +#include + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" + +1 VERSIONINFO +PRODUCTVERSION @WINDOWS_RC_VERSION@ +FILEVERSION @WINDOWS_RC_VERSION@ +FILETYPE 1 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "@PACKAGE_VERSION@.0" + VALUE "FileDescription", "@PACKAGE_STRING@" + VALUE "InternalName", "@PACKAGE_TARNAME@" + VALUE "CompanyName", "@PACKAGE_BUGREPORT@" + VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" + VALUE "ProductName", "@PACKAGE_NAME@" + VALUE "ProductVersion", "@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + diff --git a/games/NXDoom/src/hexen/.gitignore b/games/NXDoom/src/hexen/.gitignore new file mode 100644 index 00000000000..d4e88e5a219 --- /dev/null +++ b/games/NXDoom/src/hexen/.gitignore @@ -0,0 +1,5 @@ +Makefile +Makefile.in +.deps +tags +TAGS diff --git a/games/NXDoom/src/hexen/CMakeLists.txt b/games/NXDoom/src/hexen/CMakeLists.txt new file mode 100644 index 00000000000..3eba5d07305 --- /dev/null +++ b/games/NXDoom/src/hexen/CMakeLists.txt @@ -0,0 +1,78 @@ +add_library(hexen STATIC + a_action.c + am_data.h + am_map.c am_map.h + ct_chat.c + ct_chat.h + d_net.c + f_finale.c + g_game.c + h2def.h + h2_main.c + info.c info.h + in_lude.c + m_random.c m_random.h + mn_menu.c + p_acs.c + p_action.h + p_anim.c + p_ceilng.c + p_doors.c + p_enemy.c + p_floor.c + p_inter.c + p_lights.c + p_local.h + p_map.c + p_maputl.c + p_mobj.c + po_man.c + p_plats.c + p_pspr.c + p_setup.c + p_sight.c + p_spec.c p_spec.h + p_switch.c + p_telept.c + p_things.c + p_tick.c + p_user.c + r_bsp.c + r_data.c + r_draw.c + r_local.h + r_main.c + r_plane.c + r_segs.c + r_things.c + s_sound.c s_sound.h + sb_bar.c + sc_man.c + sn_sonix.c + sounds.c sounds.h + st_start.c st_start.h + sv_save.c + textdefs.h + xddefs.h) + +target_include_directories(hexen PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") +if (DEFINED EMSCRIPTEN) + set(SDL_FLAGS "-s USE_SDL=2") + if(ENABLE_SDL2_MIXER) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") + endif() + if(ENABLE_SDL2_NET) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") + endif() +else() + set(SDL_LINK_LIBS SDL2::SDL2) + if(ENABLE_SDL2_MIXER) + list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) + endif() + if(ENABLE_SDL2_NET) + list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) + endif() +endif() +target_link_libraries(hexen ${SDL_LINK_LIBS}) +set_target_properties(hexen PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") +set_target_properties(hexen PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/hexen/Makefile.am b/games/NXDoom/src/hexen/Makefile.am new file mode 100644 index 00000000000..c974ba3c80b --- /dev/null +++ b/games/NXDoom/src/hexen/Makefile.am @@ -0,0 +1,71 @@ +AM_CFLAGS=-I$(top_srcdir)/src @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ + +EXTRA_DIST = \ + CMakeLists.txt \ + hexen_icon.c + +noinst_LIBRARIES=libhexen.a + +libhexen_a_SOURCES = \ +a_action.c \ + am_data.h \ +am_map.c am_map.h \ +ct_chat.c \ + ct_chat.h \ +d_net.c \ +f_finale.c \ +g_game.c \ + h2def.h \ +h2_main.c \ +info.c info.h \ +in_lude.c \ +m_random.c m_random.h \ +mn_menu.c \ +p_acs.c \ + p_action.h \ +p_anim.c \ +p_ceilng.c \ +p_doors.c \ +p_enemy.c \ +p_floor.c \ +p_inter.c \ +p_lights.c \ + p_local.h \ +p_map.c \ +p_maputl.c \ +p_mobj.c \ +po_man.c \ +p_plats.c \ +p_pspr.c \ +p_setup.c \ +p_sight.c \ +p_spec.c p_spec.h \ +p_switch.c \ +p_telept.c \ +p_things.c \ +p_tick.c \ +p_user.c \ +r_bsp.c \ +r_data.c \ +r_draw.c \ + r_local.h \ +r_main.c \ +r_plane.c \ +r_segs.c \ +r_things.c \ +s_sound.c s_sound.h \ +sb_bar.c \ +sc_man.c \ +sn_sonix.c \ +sounds.c sounds.h \ +st_start.c st_start.h \ +sv_save.c \ + textdefs.h \ + xddefs.h + +if HAVE_ICONS + +hexen_icon.c : $(top_builddir)/data/hexen.png + $(top_builddir)/data/convert-icon $(top_builddir)/data/hexen.png $@ + +endif diff --git a/games/NXDoom/src/hexen/a_action.c b/games/NXDoom/src/hexen/a_action.c new file mode 100644 index 00000000000..7842f556a34 --- /dev/null +++ b/games/NXDoom/src/hexen/a_action.c @@ -0,0 +1,1341 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- +int orbitTableX[256] = { + 983025, 982725, 981825, 980340, 978255, 975600, 972330, 968490, + 964065, 959070, 953475, 947325, 940590, 933300, 925440, 917025, + 908055, 898545, 888495, 877905, 866775, 855135, 842985, 830310, + 817155, 803490, 789360, 774735, 759660, 744120, 728130, 711690, + 694845, 677565, 659880, 641805, 623340, 604500, 585285, 565725, + 545820, 525600, 505050, 484200, 463065, 441645, 419955, 398010, + 375840, 353430, 330810, 307995, 285000, 261825, 238485, 215010, + 191400, 167685, 143865, 119955, 95970, 71940, 47850, 23745, + -375, -24495, -48600, -72690, -96720, -120705, -144600, -168420, + -192150, -215745, -239220, -262545, -285720, -308715, -331530, -354135, + -376530, -398700, -420630, -442320, -463725, -484860, -505695, -526230, + -546450, -566340, -585885, -605085, -623925, -642375, -660435, -678105, + -695370, -712215, -728625, -744600, -760125, -775200, -789795, -803925, + -817575, -830715, -843375, -855510, -867135, -878235, -888810, -898845, + -908340, -917295, -925695, -933540, -940815, -947520, -953670, -959235, + -964215, -968625, -972450, -975690, -978330, -980400, -981870, -982740, + -983025, -982725, -981825, -980340, -978255, -975600, -972330, -968490, + -964065, -959070, -953475, -947325, -940590, -933300, -925440, -917025, + -908055, -898545, -888495, -877905, -866775, -855135, -842985, -830310, + -817155, -803490, -789360, -774735, -759660, -744120, -728130, -711690, + -694845, -677565, -659880, -641805, -623340, -604485, -585285, -565725, + -545820, -525600, -505050, -484200, -463065, -441645, -419955, -398010, + -375840, -353430, -330810, -307995, -285000, -261825, -238485, -215010, + -191400, -167685, -143865, -119955, -95970, -71940, -47850, -23745, + 375, 24495, 48600, 72690, 96720, 120705, 144600, 168420, + 192150, 215745, 239220, 262545, 285720, 308715, 331530, 354135, + 376530, 398700, 420630, 442320, 463725, 484860, 505695, 526230, + 546450, 566340, 585885, 605085, 623925, 642375, 660435, 678105, + 695370, 712215, 728625, 744600, 760125, 775200, 789795, 803925, + 817575, 830715, 843375, 855510, 867135, 878235, 888810, 898845, + 908340, 917295, 925695, 933540, 940815, 947520, 953670, 959235, + 964215, 968625, 972450, 975690, 978330, 980400, 981870, 982740 +}; + +int orbitTableY[256] = { + 375, 24495, 48600, 72690, 96720, 120705, 144600, 168420, + 192150, 215745, 239220, 262545, 285720, 308715, 331530, 354135, + 376530, 398700, 420630, 442320, 463725, 484860, 505695, 526230, + 546450, 566340, 585885, 605085, 623925, 642375, 660435, 678105, + 695370, 712215, 728625, 744600, 760125, 775200, 789795, 803925, + 817575, 830715, 843375, 855510, 867135, 878235, 888810, 898845, + 908340, 917295, 925695, 933540, 940815, 947520, 953670, 959235, + 964215, 968625, 972450, 975690, 978330, 980400, 981870, 982740, + 983025, 982725, 981825, 980340, 978255, 975600, 972330, 968490, + 964065, 959070, 953475, 947325, 940590, 933300, 925440, 917025, + 908055, 898545, 888495, 877905, 866775, 855135, 842985, 830310, + 817155, 803490, 789360, 774735, 759660, 744120, 728130, 711690, + 694845, 677565, 659880, 641805, 623340, 604500, 585285, 565725, + 545820, 525600, 505050, 484200, 463065, 441645, 419955, 398010, + 375840, 353430, 330810, 307995, 285000, 261825, 238485, 215010, + 191400, 167685, 143865, 119955, 95970, 71940, 47850, 23745, + -375, -24495, -48600, -72690, -96720, -120705, -144600, -168420, + -192150, -215745, -239220, -262545, -285720, -308715, -331530, -354135, + -376530, -398700, -420630, -442320, -463725, -484860, -505695, -526230, + -546450, -566340, -585885, -605085, -623925, -642375, -660435, -678105, + -695370, -712215, -728625, -744600, -760125, -775200, -789795, -803925, + -817575, -830715, -843375, -855510, -867135, -878235, -888810, -898845, + -908340, -917295, -925695, -933540, -940815, -947520, -953670, -959235, + -964215, -968625, -972450, -975690, -978330, -980400, -981870, -982740, + -983025, -982725, -981825, -980340, -978255, -975600, -972330, -968490, + -964065, -959070, -953475, -947325, -940590, -933300, -925440, -917025, + -908055, -898545, -888495, -877905, -866775, -855135, -842985, -830310, + -817155, -803490, -789360, -774735, -759660, -744120, -728130, -711690, + -694845, -677565, -659880, -641805, -623340, -604485, -585285, -565725, + -545820, -525600, -505050, -484200, -463065, -441645, -419955, -398010, + -375840, -353430, -330810, -307995, -285000, -261825, -238485, -215010, + -191400, -167685, -143865, -119955, -95970, -71940, -47850, -23745 +}; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// +// Environmental Action routines +// +//-------------------------------------------------------------------------- + +//========================================================================== +// +// A_DripBlood +// +//========================================================================== + +/* +void A_DripBlood(mobj_t *actor) +{ + mobj_t *mo; + int r; + + r = P_SubRandom(); + + mo = P_SpawnMobj(actor->x+(r<<11), + actor->y+(P_SubRandom()<<11), actor->z, MT_BLOOD); + mo->momx = P_SubRandom()<<10; + mo->momy = P_SubRandom()<<10; + mo->flags2 |= MF2_LOGRAV; +} +*/ + +//============================================================================ +// +// A_PotteryExplode +// +//============================================================================ + +void A_PotteryExplode(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo = NULL; + int i; + + for (i = (P_Random() & 3) + 3; i; i--) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_POTTERYBIT1); + P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 5)); + mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4); + mo->momx = P_SubRandom() << (FRACBITS - 6); + mo->momy = P_SubRandom() << (FRACBITS - 6); + } + S_StartSound(mo, SFX_POTTERY_EXPLODE); + if (actor->args[0]) + { // Spawn an item + if (!nomonsters + || !(mobjinfo[TranslateThingType[actor->args[0]]]. + flags & MF_COUNTKILL)) + { // Only spawn monsters if not -nomonsters + P_SpawnMobj(actor->x, actor->y, actor->z, + TranslateThingType[actor->args[0]]); + } + } + P_RemoveMobj(actor); +} + +//============================================================================ +// +// A_PotteryChooseBit +// +//============================================================================ + +void A_PotteryChooseBit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SetMobjState(actor, actor->info->deathstate + (P_Random() % 5) + 1); + actor->tics = 256 + (P_Random() << 1); +} + +//============================================================================ +// +// A_PotteryCheck +// +//============================================================================ + +void A_PotteryCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + mobj_t *pmo; + + if (!netgame) + { + pmo = players[consoleplayer].mo; + if (P_CheckSight(actor, pmo) + && (abs((int)R_PointToAngle2(pmo->x, pmo->y, actor->x, actor->y) + - (int)pmo->angle) <= ANG45)) + { // Previous state (pottery bit waiting state) + P_SetMobjState(actor, actor->state - &states[0] - 1); + } + else + { + return; + } + } + else + { + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + { + continue; + } + pmo = players[i].mo; + if (P_CheckSight(actor, pmo) + && (abs((int)R_PointToAngle2(pmo->x, pmo->y, actor->x, actor->y) + - (int)pmo->angle) <= ANG45)) + { // Previous state (pottery bit waiting state) + P_SetMobjState(actor, actor->state - &states[0] - 1); + return; + } + } + } +} + +//============================================================================ +// +// A_CorpseBloodDrip +// +//============================================================================ + +void A_CorpseBloodDrip(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_Random() > 128) + { + return; + } + P_SpawnMobj(actor->x, actor->y, actor->z + actor->height / 2, + MT_CORPSEBLOODDRIP); +} + +//============================================================================ +// +// A_CorpseExplode +// +//============================================================================ + +void A_CorpseExplode(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int i; + + for (i = (P_Random() & 3) + 3; i; i--) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT); + P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3)); + mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4); + mo->momx = P_SubRandom() << (FRACBITS - 6); + mo->momy = P_SubRandom() << (FRACBITS - 6); + } + // Spawn a skull + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT); + P_SetMobjState(mo, S_CORPSEBIT_4); + if (mo) + { + mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4); + mo->momx = P_SubRandom() << (FRACBITS - 6); + mo->momy = P_SubRandom() << (FRACBITS - 6); + S_StartSound(mo, SFX_FIRED_DEATH); + } + P_RemoveMobj(actor); +} + +//============================================================================ +// +// A_LeafSpawn +// +//============================================================================ + +void A_LeafSpawn(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int i; + + for (i = (P_Random() & 3) + 1; i; i--) + { + // Official release of Hexen's source code relies on unspecified behavior + // the in order of function's argument evaluation, + // see ISO-IEC 9899-1999, [6.5.2.2.10] + mobjtype_t type = MT_LEAF1 + (P_Random() & 1); + fixed_t z = actor->z + (P_Random() << 14); + fixed_t y = actor->y + (P_SubRandom() << 14); + fixed_t x = actor->x + (P_SubRandom() << 14); + + mo = P_SpawnMobj(x, y, z, type); + if (mo) + { + P_ThrustMobj(mo, actor->angle, (P_Random() << 9) + 3 * FRACUNIT); + mo->target = actor; + mo->special1.i = 0; + } + } +} + +//============================================================================ +// +// A_LeafThrust +// +//============================================================================ + +void A_LeafThrust(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_Random() > 96) + { + return; + } + actor->momz += (P_Random() << 9) + FRACUNIT; +} + +//============================================================================ +// +// A_LeafCheck +// +//============================================================================ + +void A_LeafCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->special1.i++; + if (actor->special1.i >= 20) + { + P_SetMobjState(actor, S_NULL); + return; + } + if (P_Random() > 64) + { + if (!actor->momx && !actor->momy) + { + P_ThrustMobj(actor, actor->target->angle, + (P_Random() << 9) + FRACUNIT); + } + return; + } + P_SetMobjState(actor, S_LEAF1_8); + actor->momz = (P_Random() << 9) + FRACUNIT; + P_ThrustMobj(actor, actor->target->angle, + (P_Random() << 9) + 2 * FRACUNIT); + actor->flags |= MF_MISSILE; +} + +/* +#define ORBIT_RADIUS (15*FRACUNIT) +void GenerateOrbitTable(void) +{ + int angle; + + for (angle=0; angle<256; angle++) + { + orbitTableX[angle] = FixedMul(ORBIT_RADIUS, finecosine[angle<<5]); + orbitTableY[angle] = FixedMul(ORBIT_RADIUS, finesine[angle<<5]); + } + + printf("int orbitTableX[256]=\n{\n"); + for (angle=0; angle<256; angle+=8) + { + printf("%d, %d, %d, %d, %d, %d, %d, %d,\n", + orbitTableX[angle], + orbitTableX[angle+1], + orbitTableX[angle+2], + orbitTableX[angle+3], + orbitTableX[angle+4], + orbitTableX[angle+5], + orbitTableX[angle+6], + orbitTableX[angle+7]); + } + printf("};\n\n"); + + printf("int orbitTableY[256]=\n{\n"); + for (angle=0; angle<256; angle+=8) + { + printf("%d, %d, %d, %d, %d, %d, %d, %d,\n", + orbitTableY[angle], + orbitTableY[angle+1], + orbitTableY[angle+2], + orbitTableY[angle+3], + orbitTableY[angle+4], + orbitTableY[angle+5], + orbitTableY[angle+6], + orbitTableY[angle+7]); + } + printf("};\n"); +} +*/ + +// New bridge stuff +// Parent +// special1 true == removing from world +// +// Child +// target pointer to center mobj +// args[0] angle of ball + +void A_BridgeOrbit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->target->special1.i) + { + P_SetMobjState(actor, S_NULL); + } + actor->args[0] += 3; + actor->x = actor->target->x + orbitTableX[actor->args[0]]; + actor->y = actor->target->y + orbitTableY[actor->args[0]]; + actor->z = actor->target->z; +} + + +void A_BridgeInit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + byte startangle; + mobj_t *ball1, *ball2, *ball3; + fixed_t cx, cy, cz; + +// GenerateOrbitTable(); + + cx = actor->x; + cy = actor->y; + cz = actor->z; + startangle = P_Random(); + actor->special1.i = 0; + + // Spawn triad into world + ball1 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL); + ball1->args[0] = startangle; + ball1->target = actor; + + ball2 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL); + ball2->args[0] = (startangle + 85) & 255; + ball2->target = actor; + + ball3 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL); + ball3->args[0] = (startangle + 170) & 255; + ball3->target = actor; + + A_BridgeOrbit(ball1, NULL, NULL); + A_BridgeOrbit(ball2, NULL, NULL); + A_BridgeOrbit(ball3, NULL, NULL); +} + +void A_BridgeRemove(mobj_t * actor) +{ + actor->special1.i = true; // Removing the bridge + actor->flags &= ~MF_SOLID; + P_SetMobjState(actor, S_FREE_BRIDGE1); +} + + +//========================================================================== +// +// A_GhostOn +// +//========================================================================== + +/* +void A_GhostOn(mobj_t *actor) +{ + actor->flags |= MF_SHADOW; +} +*/ + +//========================================================================== +// +// A_GhostOff +// +//========================================================================== + +/* +void A_GhostOff(mobj_t *actor) +{ + actor->flags &= ~MF_SHADOW; +} +*/ + +//========================================================================== +// +// A_HideThing +// +//========================================================================== + +void A_HideThing(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 |= MF2_DONTDRAW; +} + +//========================================================================== +// +// A_UnHideThing +// +//========================================================================== + +void A_UnHideThing(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 &= ~MF2_DONTDRAW; +} + +//========================================================================== +// +// A_SetShootable +// +//========================================================================== + +void A_SetShootable(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 &= ~MF2_NONSHOOTABLE; + actor->flags |= MF_SHOOTABLE; +} + +//========================================================================== +// +// A_UnSetShootable +// +//========================================================================== + +void A_UnSetShootable(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 |= MF2_NONSHOOTABLE; + actor->flags &= ~MF_SHOOTABLE; +} + +//========================================================================== +// +// A_SetAltShadow +// +//========================================================================== + +void A_SetAltShadow(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SHADOW; + actor->flags |= MF_ALTSHADOW; +} + +//========================================================================== +// +// A_UnSetAltShadow +// +//========================================================================== + +/* +void A_UnSetAltShadow(mobj_t *actor) +{ + actor->flags &= ~MF_ALTSHADOW; +} +*/ + +//-------------------------------------------------------------------------- +// +// Sound Action Routines +// +//-------------------------------------------------------------------------- + +//========================================================================== +// +// A_ContMobjSound +// +//========================================================================== + +void A_ContMobjSound(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + switch (actor->type) + { + case MT_SERPENTFX: + S_StartSound(actor, SFX_SERPENTFX_CONTINUOUS); + break; + case MT_HAMMER_MISSILE: + S_StartSound(actor, SFX_FIGHTER_HAMMER_CONTINUOUS); + break; + case MT_QUAKE_FOCUS: + S_StartSound(actor, SFX_EARTHQUAKE); + break; + default: + break; + } +} + +//========================================================================== +// +// PROC A_ESound +// +//========================================================================== + +void A_ESound(mobj_t *mo, player_t *player, pspdef_t *psp) +{ + int sound; + + switch (mo->type) + { + case MT_SOUNDWIND: + sound = SFX_WIND; + break; + default: + sound = SFX_NONE; + break; + } + S_StartSound(mo, sound); +} + + + +//========================================================================== +// Summon Minotaur -- see p_enemy for variable descriptions +//========================================================================== + + +void A_Summon(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + mobj_t *master; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINOTAUR); + if (mo) + { + if (P_TestMobjLocation(mo) == false || !actor->special1.m) + { // Didn't fit - change back to artifact + P_SetMobjState(mo, S_NULL); + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SUMMONMAULATOR); + if (mo) + mo->flags2 |= MF2_DROPPED; + return; + } + + // Store leveltime into mo->args. This must be stored in little- + // endian format for Vanilla savegame compatibility. + mo->args[0] = leveltime & 0xff; + mo->args[1] = (leveltime >> 8) & 0xff; + mo->args[2] = (leveltime >> 16) & 0xff; + mo->args[3] = (leveltime >> 24) & 0xff; + master = actor->special1.m; + if (master->flags & MF_CORPSE) + { // Master dead + mo->special1.m = NULL; // No master + } + else + { + mo->special1.m = actor->special1.m; // Pointer to master (mobj_t *) + P_GivePower(master->player, pw_minotaur); + } + + // Make smoke puff + P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE); + S_StartSound(actor, SFX_MAULATOR_ACTIVE); + } +} + + + +//========================================================================== +// Fog Variables: +// +// args[0] Speed (0..10) of fog +// args[1] Angle of spread (0..128) +// args[2] Frequency of spawn (1..10) +// args[3] Lifetime countdown +// args[4] Boolean: fog moving? +// special1 Internal: Counter for spawn frequency +// special2 Internal: Index into floatbob table +// +//========================================================================== + +void A_FogSpawn(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo = NULL; + angle_t delta; + + if (actor->special1.i-- > 0) + return; + + actor->special1.i = actor->args[2]; // Reset frequency count + + switch (P_Random() % 3) + { + case 0: + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHS); + break; + case 1: + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHM); + break; + case 2: + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHL); + break; + } + + if (mo) + { + delta = actor->args[1]; + if (delta == 0) + delta = 1; + mo->angle = + actor->angle + (((P_Random() % delta) - (delta >> 1)) << 24); + mo->target = actor; + if (actor->args[0] < 1) + actor->args[0] = 1; + mo->args[0] = (P_Random() % (actor->args[0])) + 1; // Random speed + mo->args[3] = actor->args[3]; // Set lifetime + mo->args[4] = 1; // Set to moving + mo->special2.i = P_Random() & 63; + } +} + + +void A_FogMove(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int speed = actor->args[0] << FRACBITS; + angle_t angle; + int weaveindex; + + if (!(actor->args[4])) + return; + + if (actor->args[3]-- <= 0) + { + P_SetMobjStateNF(actor, actor->info->deathstate); + return; + } + + if ((actor->args[3] % 4) == 0) + { + weaveindex = actor->special2.i; + actor->z += FloatBobOffsets[weaveindex] >> 1; + actor->special2.i = (weaveindex + 1) & 63; + } + + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(speed, finecosine[angle]); + actor->momy = FixedMul(speed, finesine[angle]); +} + +//=========================================================================== +// +// A_PoisonBagInit +// +//=========================================================================== + +void A_PoisonBagInit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 28 * FRACUNIT, + MT_POISONCLOUD); + if (!mo) + { + return; + } + mo->momx = 1; // missile objects must move to impact other objects + mo->special1.i = 24 + (P_Random() & 7); + mo->special2.i = 0; + mo->target = actor->target; + mo->radius = 20 * FRACUNIT; + mo->height = 30 * FRACUNIT; + mo->flags &= ~MF_NOCLIP; +} + +//=========================================================================== +// +// A_PoisonBagCheck +// +//=========================================================================== + +void A_PoisonBagCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!--actor->special1.i) + { + P_SetMobjState(actor, S_POISONCLOUD_X1); + } + else + { + return; + } +} + +//=========================================================================== +// +// A_PoisonBagDamage +// +//=========================================================================== + +void A_PoisonBagDamage(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int bobIndex; + + A_Explode(actor, player, psp); + + bobIndex = actor->special2.i; + actor->z += FloatBobOffsets[bobIndex] >> 4; + actor->special2.i = (bobIndex + 1) & 63; +} + +//=========================================================================== +// +// A_PoisonShroom +// +//=========================================================================== + +void A_PoisonShroom(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->tics = 128 + (P_Random() << 1); +} + +//=========================================================================== +// +// A_CheckThrowBomb +// +//=========================================================================== + +void A_CheckThrowBomb(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (abs(actor->momx) < 1.5 * FRACUNIT && abs(actor->momy) < 1.5 * FRACUNIT + && actor->momz < 2 * FRACUNIT + && actor->state == &states[S_THROWINGBOMB6]) + { + P_SetMobjState(actor, S_THROWINGBOMB7); + actor->z = actor->floorz; + actor->momz = 0; + actor->flags2 &= ~MF2_FLOORBOUNCE; + actor->flags &= ~MF_MISSILE; + } + if (!--actor->health) + { + P_SetMobjState(actor, actor->info->deathstate); + } +} + +//=========================================================================== +// Quake variables +// +// args[0] Intensity on richter scale (2..9) +// args[1] Duration in tics +// args[2] Radius for damage +// args[3] Radius for tremor +// args[4] TID of map thing for focus of quake +// +//=========================================================================== + +//=========================================================================== +// +// A_LocalQuake +// +//=========================================================================== + +boolean A_LocalQuake(byte * args, mobj_t * actor) +{ + mobj_t *focus, *target; + int lastfound = 0; + int success = false; + + // Find all quake foci + do + { + target = P_FindMobjFromTID(args[4], &lastfound); + if (target) + { + focus = P_SpawnMobj(target->x, + target->y, target->z, MT_QUAKE_FOCUS); + if (focus) + { + focus->args[0] = args[0]; + focus->args[1] = args[1] >> 1; // decremented every 2 tics + focus->args[2] = args[2]; + focus->args[3] = args[3]; + focus->args[4] = args[4]; + success = true; + } + } + } + while (target != NULL); + + return (success); +} + + +//=========================================================================== +// +// A_Quake +// +//=========================================================================== +int localQuakeHappening[MAXPLAYERS]; + +void A_Quake(mobj_t *actor, player_t *player_param, pspdef_t *psp) +{ + angle_t an; + player_t *player; + mobj_t *victim; + int richters = actor->args[0]; + int playnum; + fixed_t dist; + + if (actor->args[1]-- > 0) + { + for (playnum = 0; playnum < maxplayers; playnum++) + { + player = &players[playnum]; + if (!playeringame[playnum]) + continue; + + victim = player->mo; + dist = P_AproxDistance(actor->x - victim->x, + actor->y - victim->y) >> (FRACBITS + 6); + // Tested in tile units (64 pixels) + if (dist < actor->args[3]) // In tremor radius + { + localQuakeHappening[playnum] = richters; + } + // Check if in damage radius + if ((dist < actor->args[2]) && (victim->z <= victim->floorz)) + { + if (P_Random() < 50) + { + P_DamageMobj(victim, NULL, NULL, HITDICE(1)); + } + // Thrust player around + an = victim->angle + ANG1 * P_Random(); + P_ThrustMobj(victim, an, richters << (FRACBITS - 1)); + } + } + } + else + { + for (playnum = 0; playnum < maxplayers; playnum++) + { + localQuakeHappening[playnum] = false; + } + P_SetMobjState(actor, S_NULL); + } +} + + + + +//=========================================================================== +// +// Teleport other stuff +// +//=========================================================================== + +#define TELEPORT_LIFE 1 + +void A_TeloSpawnA(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX2); + if (mo) + { + mo->special1.i = TELEPORT_LIFE; // Lifetime countdown + mo->angle = actor->angle; + mo->target = actor->target; + mo->momx = actor->momx >> 1; + mo->momy = actor->momy >> 1; + mo->momz = actor->momz >> 1; + } +} + +void A_TeloSpawnB(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX3); + if (mo) + { + mo->special1.i = TELEPORT_LIFE; // Lifetime countdown + mo->angle = actor->angle; + mo->target = actor->target; + mo->momx = actor->momx >> 1; + mo->momy = actor->momy >> 1; + mo->momz = actor->momz >> 1; + } +} + +void A_TeloSpawnC(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX4); + if (mo) + { + mo->special1.i = TELEPORT_LIFE; // Lifetime countdown + mo->angle = actor->angle; + mo->target = actor->target; + mo->momx = actor->momx >> 1; + mo->momy = actor->momy >> 1; + mo->momz = actor->momz >> 1; + } +} + +void A_TeloSpawnD(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX5); + if (mo) + { + mo->special1.i = TELEPORT_LIFE; // Lifetime countdown + mo->angle = actor->angle; + mo->target = actor->target; + mo->momx = actor->momx >> 1; + mo->momy = actor->momy >> 1; + mo->momz = actor->momz >> 1; + } +} + +void A_CheckTeleRing(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special1.i-- <= 0) + { + P_SetMobjState(actor, actor->info->deathstate); + } +} + + + + +// Dirt stuff + +void P_SpawnDirt(mobj_t * actor, fixed_t radius) +{ + fixed_t x, y, z; + int dtype = 0; + mobj_t *mo; + angle_t angle; + + angle = P_Random() << 5; // <<24 >>19 + x = actor->x + FixedMul(radius, finecosine[angle]); + y = actor->y + FixedMul(radius, finesine[angle]); +// x = actor->x + (P_SubRandom()%radius)<y + ((P_SubRandom()<z + (P_Random() << 9) + FRACUNIT; + switch (P_Random() % 6) + { + case 0: + dtype = MT_DIRT1; + break; + case 1: + dtype = MT_DIRT2; + break; + case 2: + dtype = MT_DIRT3; + break; + case 3: + dtype = MT_DIRT4; + break; + case 4: + dtype = MT_DIRT5; + break; + case 5: + dtype = MT_DIRT6; + break; + } + mo = P_SpawnMobj(x, y, z, dtype); + if (mo) + { + mo->momz = P_Random() << 10; + } +} + + + + +//=========================================================================== +// +// Thrust floor stuff +// +// Thrust Spike Variables +// special1 pointer to dirt clump mobj +// special2 speed of raise +// args[0] 0 = lowered, 1 = raised +// args[1] 0 = normal, 1 = bloody +//=========================================================================== + +void A_ThrustInitUp(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->special2.i = 5; // Raise speed + actor->args[0] = 1; // Mark as up + actor->floorclip = 0; + actor->flags = MF_SOLID; + actor->flags2 = MF2_NOTELEPORT | MF2_FLOORCLIP; + actor->special1.m = NULL; +} + +void A_ThrustInitDn(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + actor->special2.i = 5; // Raise speed + actor->args[0] = 0; // Mark as down + actor->floorclip = actor->info->height; + actor->flags = 0; + actor->flags2 = MF2_NOTELEPORT | MF2_FLOORCLIP | MF2_DONTDRAW; + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_DIRTCLUMP); + actor->special1.m = mo; +} + + +void A_ThrustRaise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (A_RaiseMobj(actor)) + { // Reached it's target height + actor->args[0] = 1; + if (actor->args[1]) + P_SetMobjStateNF(actor, S_BTHRUSTINIT2_1); + else + P_SetMobjStateNF(actor, S_THRUSTINIT2_1); + } + + // Lose the dirt clump + if ((actor->floorclip < actor->height) && actor->special1.m) + { + P_RemoveMobj(actor->special1.m); + actor->special1.m = NULL; + } + + // Spawn some dirt + if (P_Random() < 40) + P_SpawnDirt(actor, actor->radius); + actor->special2.i++; // Increase raise speed +} + +void A_ThrustLower(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (A_SinkMobj(actor)) + { + actor->args[0] = 0; + if (actor->args[1]) + P_SetMobjStateNF(actor, S_BTHRUSTINIT1_1); + else + P_SetMobjStateNF(actor, S_THRUSTINIT1_1); + } +} + +void A_ThrustBlock(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags |= MF_SOLID; +} + +void A_ThrustImpale(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + // Impale all shootables in radius + PIT_ThrustSpike(actor); +} + +//=========================================================================== +// +// A_SoAExplode - Suit of Armor Explode +// +//=========================================================================== + +void A_SoAExplode(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int i; + int r1,r2,r3; + + for (i = 0; i < 10; i++) + { + r1 = P_Random(); + r2 = P_Random(); + r3 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r3 - 128) << 12), + actor->y + ((r2 - 128) << 12), + actor->z + (r1 * actor->height / 256), + MT_ZARMORCHUNK); + P_SetMobjState(mo, mo->info->spawnstate + i); + mo->momz = ((P_Random() & 7) + 5) * FRACUNIT; + mo->momx = P_SubRandom() << (FRACBITS - 6); + mo->momy = P_SubRandom() << (FRACBITS - 6); + } + if (actor->args[0]) + { // Spawn an item + if ((gameversion != exe_hexen_1_1r2) || !nomonsters + || !(mobjinfo[TranslateThingType[actor->args[0]]]. + flags & MF_COUNTKILL)) + { // Only spawn monsters if not -nomonsters + P_SpawnMobj(actor->x, actor->y, actor->z, + TranslateThingType[actor->args[0]]); + } + } + S_StartSound(mo, SFX_SUITOFARMOR_BREAK); + P_RemoveMobj(actor); +} + +//=========================================================================== +// +// A_BellReset1 +// +//=========================================================================== + +void A_BellReset1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags |= MF_NOGRAVITY; + actor->height <<= 2; +} + +//=========================================================================== +// +// A_BellReset2 +// +//=========================================================================== + +void A_BellReset2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags |= MF_SHOOTABLE; + actor->flags &= ~MF_CORPSE; + actor->health = 5; +} + + +//=========================================================================== +// +// A_FlameCheck +// +//=========================================================================== + +void A_FlameCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->args[0]--) // Called every 8 tics + { + P_SetMobjState(actor, S_NULL); + } +} + + +//=========================================================================== +// Bat Spawner Variables +// special1 frequency counter +// special2 +// args[0] frequency of spawn (1=fastest, 10=slowest) +// args[1] spread angle (0..255) +// args[2] +// args[3] duration of bats (in octics) +// args[4] turn amount per move (in degrees) +// +// Bat Variables +// special2 lifetime counter +// args[4] turn amount per move (in degrees) +//=========================================================================== + +void A_BatSpawnInit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->special1.i = 0; // Frequency count +} + +void A_BatSpawn(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int delta; + angle_t angle; + + // Countdown until next spawn + if (actor->special1.i-- > 0) + return; + actor->special1.i = actor->args[0]; // Reset frequency count + + delta = actor->args[1]; + if (delta == 0) + delta = 1; + angle = actor->angle + (((P_Random() % delta) - (delta >> 1)) << 24); + mo = P_SpawnMissileAngle(actor, MT_BAT, angle, 0); + if (mo) + { + mo->args[0] = P_Random() & 63; // floatbob index + mo->args[4] = actor->args[4]; // turn degrees + mo->special2.i = actor->args[3] << 3; // Set lifetime + mo->target = actor; + } +} + + +void A_BatMove(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t newangle; + fixed_t speed; + + if (actor->special2.i < 0) + { + P_SetMobjState(actor, actor->info->deathstate); + } + actor->special2.i -= 2; // Called every 2 tics + + if (P_Random() < 128) + { + newangle = actor->angle + ANG1 * actor->args[4]; + } + else + { + newangle = actor->angle - ANG1 * actor->args[4]; + } + + // Adjust momentum vector to new direction + newangle >>= ANGLETOFINESHIFT; + speed = FixedMul(actor->info->speed, P_Random() << 10); + actor->momx = FixedMul(speed, finecosine[newangle]); + actor->momy = FixedMul(speed, finesine[newangle]); + + if (P_Random() < 15) + S_StartSound(actor, SFX_BAT_SCREAM); + + // Handle Z movement + actor->z = actor->target->z + 2 * FloatBobOffsets[actor->args[0]]; + actor->args[0] = (actor->args[0] + 3) & 63; +} + +//=========================================================================== +// +// A_TreeDeath +// +//=========================================================================== + +void A_TreeDeath(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!(actor->flags2 & MF2_FIREDAMAGE)) + { + actor->height <<= 2; + actor->flags |= MF_SHOOTABLE; + actor->flags &= ~(MF_CORPSE + MF_DROPOFF); + actor->health = 35; + return; + } + else + { + P_SetMobjState(actor, actor->info->meleestate); + } +} + +//=========================================================================== +// +// A_NoGravity +// +//=========================================================================== + +void A_NoGravity(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags |= MF_NOGRAVITY; +} diff --git a/games/NXDoom/src/hexen/am_data.h b/games/NXDoom/src/hexen/am_data.h new file mode 100644 index 00000000000..26589a25cf1 --- /dev/null +++ b/games/NXDoom/src/hexen/am_data.h @@ -0,0 +1,109 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef __AMDATA_H__ +#define __AMDATA_H__ + +// a line drawing of the player pointing right, starting from the middle. + +#define R ((8*PLAYERRADIUS)/7) + +mline_t player_arrow[] = { + { { -R+R/4, 0 }, { 0, 0} }, // center line. + { { -R+R/4, R/8 }, { R, 0} }, // blade + { { -R+R/4, -R/8 }, { R, 0 } }, + { { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece + { { -R+R/8, -R/4 }, { -R+R/8, R/4 } }, + { { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors + { { -R+R/8, R/4 }, { -R+R/4, R/4} }, + { { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel + { { -R-R/4, R/8 }, { -R+R/8, R/8 } }, + { { -R-R/4, -R/8}, { -R+R/8, -R/8 } } + }; + +/* +mline_t keysquare[] = { + { { 0, 0 }, { R/4, -R/2 } }, + { { R/4, -R/2 }, { R/2, -R/2 } }, + { { R/2, -R/2 }, { R/2, R/2 } }, + { { R/2, R/2 }, { R/4, R/2 } }, + { { R/4, R/2 }, { 0, 0 } }, // handle part type thing + { { 0, 0 }, { -R, 0 } }, // stem + { { -R, 0 }, { -R, -R/2 } }, // end lockpick part + { { -3*R/4, 0 }, { -3*R/4, -R/4 } } + }; +*/ + +/*mline_t player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/4 } }, // -----> + { { R, 0 }, { R-R/2, -R/4 } }, + { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> + { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> + { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } + }; +*/ +#undef R +#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) +#define NUMKEYSQUARELINES (sizeof(keysquare)/sizeof(mline_t)) + +/* +#define R ((8*PLAYERRADIUS)/7) +mline_t cheat_player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/6 } }, // -----> + { { R, 0 }, { R-R/2, -R/6 } }, + { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> + { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> + { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, + { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> + { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, + { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, + { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> + { { -R/6, -R/6 }, { 0, -R/6 } }, + { { 0, -R/6 }, { 0, R/4 } }, + { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> + { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, + { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } + }; +#undef R +#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) +*/ + + +/* +#define R (FRACUNIT) +mline_t triangle_guy[] = { + { { -.867*R, -.5*R }, { .867*R, -.5*R } }, + { { .867*R, -.5*R } , { 0, R } }, + { { 0, R }, { -.867*R, -.5*R } } + }; +#undef R +#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t)) +*/ + +#define R (FRACUNIT) +mline_t thintriangle_guy[] = { + { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, + { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, + { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } + }; +#undef R +#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) + +#endif diff --git a/games/NXDoom/src/hexen/am_map.c b/games/NXDoom/src/hexen/am_map.c new file mode 100644 index 00000000000..34985dc5d9f --- /dev/null +++ b/games/NXDoom/src/hexen/am_map.c @@ -0,0 +1,1544 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include + +#include "h2def.h" +#include "doomkeys.h" +#include "i_video.h" +#include "i_swap.h" +#include "i_timer.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "am_map.h" +#include "am_data.h" +#include "v_video.h" + +#define NUMALIAS 3 // Number of antialiased lines. + +int cheating = 0; +static int grid = 0; + +boolean automapactive = false; +static int finit_width = SCREENWIDTH; +static int finit_height = SCREENHEIGHT - SBARHEIGHT - 3; +static int f_x, f_y; // location of window on screen +static int f_w, f_h; // size of window on screen +static int lightlev; // used for funky strobing effect +static byte *fb; // pseudo-frame buffer +static int amclock; + +static mpoint_t m_paninc; // how far the window pans each tic (map coords) +static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) +static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) + +static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) +static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) + +// width/height of window on map (map coords) +static fixed_t m_w, m_h; +static fixed_t min_x, min_y; // based on level size +static fixed_t max_x, max_y; // based on level size +static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y +static fixed_t min_w, min_h; // based on player size +static fixed_t min_scale_mtof; // used to tell when to stop zooming out +static fixed_t max_scale_mtof; // used to tell when to stop zooming in + +// old stuff for recovery later +static fixed_t old_m_w, old_m_h; +static fixed_t old_m_x, old_m_y; + +// old location used by the Follower routine +static mpoint_t f_oldloc; + +// used by MTOF to scale from map-to-frame-buffer coords +static fixed_t scale_mtof = INITSCALEMTOF; +// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) +static fixed_t scale_ftom; + +static player_t *plr; // the player represented by an arrow +static vertex_t oldplr; + +//static patch_t *marknums[10]; // numbers used for marking by the automap +//static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are +//static int markpointnum = 0; // next point to be assigned + +static int followplayer = 1; // specifies whether to follow the player around + +static char cheat_kills[] = { 'k', 'i', 'l', 'l', 's' }; +static boolean ShowKills = 0; +static unsigned ShowKillsCount = 0; + +static byte antialias[NUMALIAS][8] = { + {83, 84, 85, 86, 87, 88, 89, 90}, + {96, 96, 95, 94, 93, 92, 91, 90}, + {107, 108, 109, 110, 111, 112, 89, 90} +}; + +/* +static byte *aliasmax[NUMALIAS] = { + &antialias[0][7], &antialias[1][7], &antialias[2][7] +};*/ + +static byte *maplump; // pointer to the raw data for the automap background. +static short mapystart = 0; // y-value for the start of the map bitmap...used in + //the parallax stuff. +static short mapxstart = 0; //x-value for the bitmap. + +//byte screens[][SCREENWIDTH*SCREENHEIGHT]; +//void V_MarkRect (int x, int y, int width, int height); + +// Functions + +void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, + int NumLevels, unsigned short IntensityBits); + +void AM_DrawDeathmatchStats(void); +static void DrawWorldTimer(void); + +// Calculates the slope and slope according to the x-axis of a line +// segment in map coordinates (with the upright y-axis n' all) so +// that it can be used with the brain-dead drawing stuff. + +// Ripped out for Heretic +/* +void AM_getIslope(mline_t *ml, islope_t *is) +{ + int dx, dy; + + dy = ml->a.y - ml->b.y; + dx = ml->b.x - ml->a.x; + if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); + else is->islp = FixedDiv(dx, dy); + if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); + else is->slp = FixedDiv(dy, dx); +} +*/ + +void AM_activateNewScale(void) +{ + m_x += m_w / 2; + m_y += m_h / 2; + m_w = FTOM(f_w); + m_h = FTOM(f_h); + m_x -= m_w / 2; + m_y -= m_h / 2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + +void AM_saveScaleAndLoc(void) +{ + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; +} + +void AM_restoreScaleAndLoc(void) +{ + + m_w = old_m_w; + m_h = old_m_h; + if (!followplayer) + { + m_x = old_m_x; + m_y = old_m_y; + } + else + { + m_x = plr->mo->x - m_w / 2; + m_y = plr->mo->y - m_h / 2; + } + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // Change the scaling multipliers + scale_mtof = FixedDiv(f_w << FRACBITS, m_w); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +} + +// adds a marker at the current location + +/* +void AM_addMark(void) +{ + markpoints[markpointnum].x = m_x + m_w/2; + markpoints[markpointnum].y = m_y + m_h/2; + markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; + +} +*/ +void AM_findMinMaxBoundaries(void) +{ + int i; + fixed_t a, b; + + min_x = min_y = INT_MAX; + max_x = max_y = -INT_MAX; + for (i = 0; i < numvertexes; i++) + { + if (vertexes[i].x < min_x) + min_x = vertexes[i].x; + else if (vertexes[i].x > max_x) + max_x = vertexes[i].x; + if (vertexes[i].y < min_y) + min_y = vertexes[i].y; + else if (vertexes[i].y > max_y) + max_y = vertexes[i].y; + } + max_w = max_x - min_x; + max_h = max_y - min_y; + min_w = 2 * PLAYERRADIUS; + min_h = 2 * PLAYERRADIUS; + + a = FixedDiv(f_w << FRACBITS, max_w); + b = FixedDiv(f_h << FRACBITS, max_h); + min_scale_mtof = a < b ? a : b; + + max_scale_mtof = FixedDiv(f_h << FRACBITS, 2 * PLAYERRADIUS); + +} + +void AM_changeWindowLoc(void) +{ + if (m_paninc.x || m_paninc.y) + { + followplayer = 0; + f_oldloc.x = INT_MAX; + } + + m_x += m_paninc.x; + m_y += m_paninc.y; + + if (m_x + m_w / 2 > max_x) + { + m_x = max_x - m_w / 2; + m_paninc.x = 0; + } + else if (m_x + m_w / 2 < min_x) + { + m_x = min_x - m_w / 2; + m_paninc.x = 0; + } + if (m_y + m_h / 2 > max_y) + { + m_y = max_y - m_h / 2; + m_paninc.y = 0; + } + else if (m_y + m_h / 2 < min_y) + { + m_y = min_y - m_h / 2; + m_paninc.y = 0; + } + + // The following code was commented out in the released Hexen source, + // but I believe we need to do this here to stop the background moving + // when we reach the map boundaries. (In the released source it's done + // in AM_clearFB). + mapxstart += MTOF(m_paninc.x+FRACUNIT/2); + mapystart -= MTOF(m_paninc.y+FRACUNIT/2); + if(mapxstart >= finit_width) + mapxstart -= finit_width; + if(mapxstart < 0) + mapxstart += finit_width; + if(mapystart >= finit_height) + mapystart -= finit_height; + if(mapystart < 0) + mapystart += finit_height; + // - end of code that was commented-out + + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + +void AM_initVariables(void) +{ + int pnum; + thinker_t *think; + + //static event_t st_notify = { ev_keyup, AM_MSGENTERED }; + + automapactive = true; + fb = I_VideoBuffer; + + f_oldloc.x = INT_MAX; + amclock = 0; + lightlev = 0; + + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; + + m_w = FTOM(f_w); + m_h = FTOM(f_h); + + // find player to center on initially + if (!playeringame[pnum = consoleplayer]) + for (pnum = 0; pnum < maxplayers; pnum++) + if (playeringame[pnum]) + break; + plr = &players[pnum]; + oldplr.x = plr->mo->x; + oldplr.y = plr->mo->y; + m_x = plr->mo->x - m_w / 2; + m_y = plr->mo->y - m_h / 2; + AM_changeWindowLoc(); + + // for saving & restoring + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + + // load in the location of keys, if in baby mode + +// memset(KeyPoints, 0, sizeof(vertex_t)*3); + if (gameskill == sk_baby) + { + for (think = thinkercap.next; think != &thinkercap; + think = think->next) + { + if (think->function != P_MobjThinker) + { //not a mobj + continue; + } + } + } + + // inform the status bar of the change +//c ST_Responder(&st_notify); +} + +void AM_loadPics(void) +{ + maplump = W_CacheLumpName("AUTOPAGE", PU_STATIC); +} + + +/* +void AM_clearMarks(void) +{ + int i; + for (i=0;i max_scale_mtof) + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +} + +static boolean stopped = true; + +void AM_Stop(void) +{ + //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; + +// AM_unloadPics(); + automapactive = false; +// ST_Responder(&st_notify); + stopped = true; + BorderNeedRefresh = true; +} + +void AM_Start(void) +{ + static int lastlevel = -1, lastepisode = -1; + + if (!stopped) + AM_Stop(); + stopped = false; + if (gamestate != GS_LEVEL) + { + return; // don't show automap if we aren't in a game! + } + if (lastlevel != gamemap || lastepisode != gameepisode) + { + AM_LevelInit(); + lastlevel = gamemap; + lastepisode = gameepisode; + } + AM_initVariables(); + AM_loadPics(); +} + +// set the window scale to the maximum size + +void AM_minOutWindowScale(void) +{ + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + +// set the window scale to the minimum size + +void AM_maxOutWindowScale(void) +{ + scale_mtof = max_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + +boolean AM_Responder(event_t * ev) +{ + int rc; + int key; + static int bigstate = 0; + static int joywait = 0; + + key = ev->data1; + + if (ev->type == ev_joystick && joybautomap >= 0 + && (ev->data1 & (1 << joybautomap)) != 0 && joywait < I_GetTime()) + { + joywait = I_GetTime() + 5; + + if (!automapactive) + { + AM_Start (); + SB_state = -1; + viewactive = false; + } + else + { + bigstate = 0; + viewactive = true; + AM_Stop (); + SB_state = -1; + } + + return true; + } + + + rc = false; + if (!automapactive) + { + if (ev->type == ev_keydown && key == key_map_toggle + && gamestate == GS_LEVEL) + { + AM_Start(); + SB_state = -1; + viewactive = false; + rc = true; + } + } + else if (ev->type == ev_keydown) + { + rc = true; + + if (key == key_map_east) // pan right + { + if (!followplayer) + m_paninc.x = FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_west) // pan left + { + if (!followplayer) + m_paninc.x = -FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_north) // pan up + { + if (!followplayer) + m_paninc.y = FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_south) // pan down + { + if (!followplayer) + m_paninc.y = -FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_zoomout) // zoom out + { + mtof_zoommul = M_ZOOMOUT; + ftom_zoommul = M_ZOOMIN; + } + else if (key == key_map_zoomin) // zoom in + { + mtof_zoommul = M_ZOOMIN; + ftom_zoommul = M_ZOOMOUT; + } + else if (key == key_map_toggle) + { + bigstate = 0; + viewactive = true; + AM_Stop(); + SB_state = -1; + } + else if (key == key_map_maxzoom) + { + bigstate = !bigstate; + if (bigstate) + { + AM_saveScaleAndLoc(); + AM_minOutWindowScale(); + } + else + AM_restoreScaleAndLoc(); + } + else if (key == key_map_follow) + { + followplayer = !followplayer; + f_oldloc.x = INT_MAX; + P_SetMessage(plr, + followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, + true); + } + else + { + rc = false; + } + + if (cheat_kills[ShowKillsCount] == ev->data1 && netgame && deathmatch) + { + ShowKillsCount++; + if (ShowKillsCount == 5) + { + ShowKillsCount = 0; + rc = false; + ShowKills ^= 1; + } + } + else + { + ShowKillsCount = 0; + } + } + else if (ev->type == ev_keyup) + { + rc = false; + + if (key == key_map_east) + { + if (!followplayer) + m_paninc.x = 0; + } + else if (key == key_map_west) + { + if (!followplayer) + m_paninc.x = 0; + } + else if (key == key_map_north) + { + if (!followplayer) + m_paninc.y = 0; + } + else if (key == key_map_south) + { + if (!followplayer) + m_paninc.y = 0; + } + else if (key == key_map_zoomin || key == key_map_zoomout) + { + mtof_zoommul = FRACUNIT; + ftom_zoommul = FRACUNIT; + } + } + return rc; +} + +void AM_changeWindowScale(void) +{ + + // Change the scaling multipliers + scale_mtof = FixedMul(scale_mtof, mtof_zoommul); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + + if (scale_mtof < min_scale_mtof) + AM_minOutWindowScale(); + else if (scale_mtof > max_scale_mtof) + AM_maxOutWindowScale(); + else + AM_activateNewScale(); +} + +void AM_doFollowPlayer(void) +{ + if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) + { +// m_x = FTOM(MTOF(plr->mo->x - m_w/2)); +// m_y = FTOM(MTOF(plr->mo->y - m_h/2)); +// m_x = plr->mo->x - m_w/2; +// m_y = plr->mo->y - m_h/2; + m_x = FTOM(MTOF(plr->mo->x)) - m_w / 2; + m_y = FTOM(MTOF(plr->mo->y)) - m_h / 2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // do the parallax parchment scrolling. +/* + dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point + dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y)); + + if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first + dmapx=0; //goes into the automap. + mapxstart += dmapx; + mapystart += dmapy; + + while(mapxstart >= finit_width) + mapxstart -= finit_width; + while(mapxstart < 0) + mapxstart += finit_width; + while(mapystart >= finit_height) + mapystart -= finit_height; + while(mapystart < 0) + mapystart += finit_height; +*/ + f_oldloc.x = plr->mo->x; + f_oldloc.y = plr->mo->y; + } +} + +// Ripped out for Heretic +/* +void AM_updateLightLev(void) +{ + static nexttic = 0; +//static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; + static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; + static int litelevelscnt = 0; + + // Change light level + if (amclock>nexttic) + { + lightlev = litelevels[litelevelscnt++]; + if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; + nexttic = amclock + 6 - (amclock % 6); + } +} +*/ + +void AM_Ticker(void) +{ + + if (!automapactive) + return; + + amclock++; + + if (followplayer) + AM_doFollowPlayer(); + + // Change the zoom if necessary + if (ftom_zoommul != FRACUNIT) + AM_changeWindowScale(); + + // Change x,y location + if (m_paninc.x || m_paninc.y) + AM_changeWindowLoc(); + // Update light level +// AM_updateLightLev(); + +} + +void AM_clearFB(int color) +{ + int i, j; + int dmapx; + int dmapy; + + if (followplayer) + { + dmapx = (MTOF(plr->mo->x) - MTOF(oldplr.x)); //fixed point + dmapy = (MTOF(oldplr.y) - MTOF(plr->mo->y)); + + oldplr.x = plr->mo->x; + oldplr.y = plr->mo->y; +// if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first +// dmapx=0; //goes into the automap. + mapxstart += dmapx >> 1; + mapystart += dmapy >> 1; + + while (mapxstart >= finit_width) + mapxstart -= finit_width; + while (mapxstart < 0) + mapxstart += finit_width; + while (mapystart >= finit_height) + mapystart -= finit_height; + while (mapystart < 0) + mapystart += finit_height; + } + else + { + // The released Hexen source does this here, but this causes a bug + // where the map background keeps moving when we reach the map + // boundaries. This is instead done in AM_changeWindowLoc. + /* + mapxstart += (MTOF(m_paninc.x) >> 1); + mapystart -= (MTOF(m_paninc.y) >> 1); + if (mapxstart >= finit_width) + mapxstart -= finit_width; + if (mapxstart < 0) + mapxstart += finit_width; + if (mapystart >= finit_height) + mapystart -= finit_height; + if (mapystart < 0) + mapystart += finit_height; + */ + } + + //blit the automap background to the screen. + j = mapystart * finit_width; + for (i = 0; i < SCREENHEIGHT - SBARHEIGHT; i++) + { + memcpy(I_VideoBuffer + i * finit_width, maplump + j + mapxstart, + finit_width - mapxstart); + memcpy(I_VideoBuffer + i * finit_width + finit_width - mapxstart, + maplump + j, mapxstart); + j += finit_width; + if (j >= finit_height * finit_width) + j = 0; + } + +// memcpy(I_VideoBuffer, maplump, finit_width*finit_height); +// memset(fb, color, f_w*f_h); +} + +// Based on Cohen-Sutherland clipping algorithm but with a slightly +// faster reject and precalculated slopes. If I need the speed, will +// hash algorithm to the common cases. + +boolean AM_clipMline(mline_t * ml, fline_t * fl) +{ + enum + { LEFT = 1, RIGHT = 2, BOTTOM = 4, TOP = 8 }; + int outcode1 = 0, outcode2 = 0, outside; + fpoint_t tmp = { 0, 0 }; + int dx, dy; + +#define DOOUTCODE(oc, mx, my) \ + (oc) = 0; \ + if ((my) < 0) (oc) |= TOP; \ + else if ((my) >= f_h) (oc) |= BOTTOM; \ + if ((mx) < 0) (oc) |= LEFT; \ + else if ((mx) >= f_w) (oc) |= RIGHT + + // do trivial rejects and outcodes + if (ml->a.y > m_y2) + outcode1 = TOP; + else if (ml->a.y < m_y) + outcode1 = BOTTOM; + if (ml->b.y > m_y2) + outcode2 = TOP; + else if (ml->b.y < m_y) + outcode2 = BOTTOM; + if (outcode1 & outcode2) + return false; // trivially outside + + if (ml->a.x < m_x) + outcode1 |= LEFT; + else if (ml->a.x > m_x2) + outcode1 |= RIGHT; + if (ml->b.x < m_x) + outcode2 |= LEFT; + else if (ml->b.x > m_x2) + outcode2 |= RIGHT; + if (outcode1 & outcode2) + return false; // trivially outside + + // transform to frame-buffer coordinates. + fl->a.x = CXMTOF(ml->a.x); + fl->a.y = CYMTOF(ml->a.y); + fl->b.x = CXMTOF(ml->b.x); + fl->b.y = CYMTOF(ml->b.y); + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + if (outcode1 & outcode2) + return false; + + while (outcode1 | outcode2) + { + // may be partially inside box + // find an outside point + if (outcode1) + outside = outcode1; + else + outside = outcode2; + // clip to each side + if (outside & TOP) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx * (fl->a.y)) / dy; + tmp.y = 0; + } + else if (outside & BOTTOM) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx * (fl->a.y - f_h)) / dy; + tmp.y = f_h - 1; + } + else if (outside & RIGHT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy * (f_w - 1 - fl->a.x)) / dx; + tmp.x = f_w - 1; + } + else if (outside & LEFT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy * (-fl->a.x)) / dx; + tmp.x = 0; + } + if (outside == outcode1) + { + fl->a = tmp; + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + } + else + { + fl->b = tmp; + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + } + if (outcode1 & outcode2) + return false; // trivially outside + } + + return true; +} + +#undef DOOUTCODE + +// Classic Bresenham w/ whatever optimizations I need for speed + +void AM_drawFline(fline_t * fl, int color) +{ + register int x, y, dx, dy, sx, sy, ax, ay, d; + //static fuck = 0; + + switch (color) + { + case WALLCOLORS: + DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, + &antialias[0][0], 8, 3); + break; + case FDWALLCOLORS: + DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, + &antialias[1][0], 8, 3); + break; + case CDWALLCOLORS: + DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, + &antialias[2][0], 8, 3); + break; + default: + { + // For debugging only + if (fl->a.x < 0 || fl->a.x >= f_w + || fl->a.y < 0 || fl->a.y >= f_h + || fl->b.x < 0 || fl->b.x >= f_w + || fl->b.y < 0 || fl->b.y >= f_h) + { + //fprintf(stderr, "fuck %d \r", fuck++); + return; + } + +#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO! + + dx = fl->b.x - fl->a.x; + ax = 2 * (dx < 0 ? -dx : dx); + sx = dx < 0 ? -1 : 1; + + dy = fl->b.y - fl->a.y; + ay = 2 * (dy < 0 ? -dy : dy); + sy = dy < 0 ? -1 : 1; + + x = fl->a.x; + y = fl->a.y; + + if (ax > ay) + { + d = ay - ax / 2; + while (1) + { + DOT(x, y, color); + if (x == fl->b.x) + return; + if (d >= 0) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } + else + { + d = ax - ay / 2; + while (1) + { + DOT(x, y, color); + if (y == fl->b.y) + return; + if (d >= 0) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } + } + } +} + +/* Wu antialiased line drawer. + * (X0,Y0),(X1,Y1) = line to draw + * BaseColor = color # of first color in block used for antialiasing, the + * 100% intensity version of the drawing color + * NumLevels = size of color block, with BaseColor+NumLevels-1 being the + * 0% intensity version of the drawing color + * IntensityBits = log base 2 of NumLevels; the # of bits used to describe + * the intensity of the drawing color. 2**IntensityBits==NumLevels + */ +void PUTDOT(short xx, short yy, byte * cc, byte * cm) +{ + static int oldyy; + static int oldyyshifted; + byte *oldcc = cc; + + if (xx < 32) + cc += 7 - (xx >> 2); + else if (xx > (finit_width - 32)) + cc += 7 - ((finit_width - xx) >> 2); +// if(cc==oldcc) //make sure that we don't double fade the corners. +// { + if (yy < 32) + cc += 7 - (yy >> 2); + else if (yy > (finit_height - 32)) + cc += 7 - ((finit_height - yy) >> 2); +// } + if (cc > cm && cm != NULL) + { + cc = cm; + } + else if (cc > oldcc + 6) // don't let the color escape from the fade table... + { + cc = oldcc + 6; + } + if (yy == oldyy + 1) + { + oldyy++; + oldyyshifted += 320; + } + else if (yy == oldyy - 1) + { + oldyy--; + oldyyshifted -= 320; + } + else if (yy != oldyy) + { + oldyy = yy; + oldyyshifted = yy * 320; + } + fb[oldyyshifted + xx] = *(cc); +// fb[(yy)*f_w+(xx)]=*(cc); +} + +void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, + int NumLevels, unsigned short IntensityBits) +{ + unsigned short IntensityShift, ErrorAdj, ErrorAcc; + unsigned short ErrorAccTemp, Weighting, WeightingComplementMask; + short DeltaX, DeltaY, Temp, XDir; + + /* Make sure the line runs top to bottom */ + if (Y0 > Y1) + { + Temp = Y0; + Y0 = Y1; + Y1 = Temp; + Temp = X0; + X0 = X1; + X1 = Temp; + } + /* Draw the initial pixel, which is always exactly intersected by + the line and so needs no weighting */ + PUTDOT(X0, Y0, &BaseColor[0], NULL); + + if ((DeltaX = X1 - X0) >= 0) + { + XDir = 1; + } + else + { + XDir = -1; + DeltaX = -DeltaX; /* make DeltaX positive */ + } + /* Special-case horizontal, vertical, and diagonal lines, which + require no weighting because they go right through the center of + every pixel */ + if ((DeltaY = Y1 - Y0) == 0) + { + /* Horizontal line */ + while (DeltaX-- != 0) + { + X0 += XDir; + PUTDOT(X0, Y0, &BaseColor[0], NULL); + } + return; + } + if (DeltaX == 0) + { + /* Vertical line */ + do + { + Y0++; + PUTDOT(X0, Y0, &BaseColor[0], NULL); + } + while (--DeltaY != 0); + return; + } + //diagonal line. + if (DeltaX == DeltaY) + { + do + { + X0 += XDir; + Y0++; + PUTDOT(X0, Y0, &BaseColor[0], NULL); + } + while (--DeltaY != 0); + return; + } + /* Line is not horizontal, diagonal, or vertical */ + ErrorAcc = 0; /* initialize the line error accumulator to 0 */ + /* # of bits by which to shift ErrorAcc to get intensity level */ + IntensityShift = 16 - IntensityBits; + /* Mask used to flip all bits in an intensity weighting, producing the + result (1 - intensity weighting) */ + WeightingComplementMask = NumLevels - 1; + /* Is this an X-major or Y-major line? */ + if (DeltaY > DeltaX) + { + /* Y-major line; calculate 16-bit fixed-point fractional part of a + pixel that X advances each time Y advances 1 pixel, truncating the + result so that we won't overrun the endpoint along the X axis */ + ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY; + /* Draw all pixels other than the first and last */ + while (--DeltaY) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorAdj; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the X coord */ + X0 += XDir; + } + Y0++; /* Y-major, so always advance Y */ + /* The IntensityBits most significant bits of ErrorAcc give us the + intensity weighting for this pixel, and the complement of the + weighting for the paired pixel */ + Weighting = ErrorAcc >> IntensityShift; + PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); + PUTDOT(X0 + XDir, Y0, + &BaseColor[(Weighting ^ WeightingComplementMask)], + &BaseColor[7]); + } + /* Draw the final pixel, which is always exactly intersected by the line + and so needs no weighting */ + PUTDOT(X1, Y1, &BaseColor[0], NULL); + return; + } + /* It's an X-major line; calculate 16-bit fixed-point fractional part of a + pixel that Y advances each time X advances 1 pixel, truncating the + result to avoid overrunning the endpoint along the X axis */ + ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX; + /* Draw all pixels other than the first and last */ + while (--DeltaX) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorAdj; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the Y coord */ + Y0++; + } + X0 += XDir; /* X-major, so always advance X */ + /* The IntensityBits most significant bits of ErrorAcc give us the + intensity weighting for this pixel, and the complement of the + weighting for the paired pixel */ + Weighting = ErrorAcc >> IntensityShift; + PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); + PUTDOT(X0, Y0 + 1, + &BaseColor[(Weighting ^ WeightingComplementMask)], + &BaseColor[7]); + + } + /* Draw the final pixel, which is always exactly intersected by the line + and so needs no weighting */ + PUTDOT(X1, Y1, &BaseColor[0], NULL); +} + +void AM_drawMline(mline_t * ml, int color) +{ + static fline_t fl; + + if (AM_clipMline(ml, &fl)) + AM_drawFline(&fl, color); // draws it on frame buffer using fb coords + +} + +void AM_drawGrid(int color) +{ + fixed_t x, y; + fixed_t start, end; + mline_t ml; + + // Figure out start of vertical gridlines + start = m_x; + if ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)) + start += (MAPBLOCKUNITS << FRACBITS) + - ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)); + end = m_x + m_w; + + // draw vertical gridlines + ml.a.y = m_y; + ml.b.y = m_y + m_h; + for (x = start; x < end; x += (MAPBLOCKUNITS << FRACBITS)) + { + ml.a.x = x; + ml.b.x = x; + AM_drawMline(&ml, color); + } + + // Figure out start of horizontal gridlines + start = m_y; + if ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)) + start += (MAPBLOCKUNITS << FRACBITS) + - ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)); + end = m_y + m_h; + + // draw horizontal gridlines + ml.a.x = m_x; + ml.b.x = m_x + m_w; + for (y = start; y < end; y += (MAPBLOCKUNITS << FRACBITS)) + { + ml.a.y = y; + ml.b.y = y; + AM_drawMline(&ml, color); + } +} + +void AM_drawWalls(void) +{ + int i; + static mline_t l; + + for (i = 0; i < numlines; i++) + { + l.a.x = lines[i].v1->x; + l.a.y = lines[i].v1->y; + l.b.x = lines[i].v2->x; + l.b.y = lines[i].v2->y; + if (cheating || (lines[i].flags & ML_MAPPED)) + { + if ((lines[i].flags & LINE_NEVERSEE) && !cheating) + continue; + if (!lines[i].backsector) + { + AM_drawMline(&l, WALLCOLORS + lightlev); + } + else + { + if (lines[i].flags & ML_SECRET) // secret door + { + if (cheating) + AM_drawMline(&l, 0); + else + AM_drawMline(&l, WALLCOLORS + lightlev); + } + else if (lines[i].special == 13 || lines[i].special == 83) + { // Locked door line -- all locked doors are greed + AM_drawMline(&l, GREENKEY); + } + else if (lines[i].special == 70 || lines[i].special == 71) + { // intra-level teleports are blue + AM_drawMline(&l, BLUEKEY); + } + else if (lines[i].special == 74 || lines[i].special == 75) + { // inter-level teleport/game-winning exit -- both are red + AM_drawMline(&l, BLOODRED); + } + else if (lines[i].backsector->floorheight + != lines[i].frontsector->floorheight) + { + AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change + } + else if (lines[i].backsector->ceilingheight + != lines[i].frontsector->ceilingheight) + { + AM_drawMline(&l, CDWALLCOLORS + lightlev); // ceiling level change + } + else if (cheating) + { + AM_drawMline(&l, TSWALLCOLORS + lightlev); + } + } + } + else if (plr->powers[pw_allmap]) + { + if (!(lines[i].flags & LINE_NEVERSEE)) + AM_drawMline(&l, GRAYS + 3); + } + } + +} + +void AM_rotate(fixed_t * x, fixed_t * y, angle_t a) +{ + fixed_t tmpx; + + tmpx = FixedMul(*x, finecosine[a >> ANGLETOFINESHIFT]) + - FixedMul(*y, finesine[a >> ANGLETOFINESHIFT]); + *y = FixedMul(*x, finesine[a >> ANGLETOFINESHIFT]) + + FixedMul(*y, finecosine[a >> ANGLETOFINESHIFT]); + *x = tmpx; +} + +void AM_drawLineCharacter(mline_t * lineguy, int lineguylines, fixed_t scale, + angle_t angle, int color, fixed_t x, fixed_t y) +{ + int i; + mline_t l; + + for (i = 0; i < lineguylines; i++) + { + l.a.x = lineguy[i].a.x; + l.a.y = lineguy[i].a.y; + if (scale) + { + l.a.x = FixedMul(scale, l.a.x); + l.a.y = FixedMul(scale, l.a.y); + } + if (angle) + AM_rotate(&l.a.x, &l.a.y, angle); + l.a.x += x; + l.a.y += y; + + l.b.x = lineguy[i].b.x; + l.b.y = lineguy[i].b.y; + if (scale) + { + l.b.x = FixedMul(scale, l.b.x); + l.b.y = FixedMul(scale, l.b.y); + } + if (angle) + AM_rotate(&l.b.x, &l.b.y, angle); + l.b.x += x; + l.b.y += y; + + AM_drawMline(&l, color); + } +} + +void AM_drawPlayers(void) +{ + int i; + player_t *p; + static int their_colors[] = { + AM_PLR1_COLOR, + AM_PLR2_COLOR, + AM_PLR3_COLOR, + AM_PLR4_COLOR, + AM_PLR5_COLOR, + AM_PLR6_COLOR, + AM_PLR7_COLOR, + AM_PLR8_COLOR + }; + int their_color = -1; + int color; + + if (!netgame) + { + AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, + WHITE, plr->mo->x, plr->mo->y); + return; + } + + for (i = 0; i < maxplayers; i++) + { + their_color++; + p = &players[i]; + if (deathmatch && !singledemo && p != plr) + { + continue; + } + if (!playeringame[i]) + continue; + color = their_colors[their_color]; + AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, + color, p->mo->x, p->mo->y); + } +} + +void AM_drawThings(int colors, int colorrange) +{ + int i; + mobj_t *t; + + for (i = 0; i < numsectors; i++) + { + t = sectors[i].thinglist; + while (t) + { + AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, + 16 << FRACBITS, t->angle, colors + lightlev, + t->x, t->y); + t = t->snext; + } + } +} + +/* +void AM_drawMarks(void) +{ + int i, fx, fy, w, h; + + for (i=0;iwidth); + h = SHORT(marknums[i]->height); + fx = CXMTOF(markpoints[i].x); + fy = CYMTOF(markpoints[i].y); + if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) + V_DrawPatch(fx, fy, marknums[i]); + } + } +} +*/ +/* +void AM_drawkeys(void) +{ + if(KeyPoints[0].x != 0 || KeyPoints[0].y != 0) + { + AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY, + KeyPoints[0].x, KeyPoints[0].y); + } + if(KeyPoints[1].x != 0 || KeyPoints[1].y != 0) + { + AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY, + KeyPoints[1].x, KeyPoints[1].y); + } + if(KeyPoints[2].x != 0 || KeyPoints[2].y != 0) + { + AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY, + KeyPoints[2].x, KeyPoints[2].y); + } +} +*/ + +/* +void AM_drawCrosshair(int color) +{ + fb[(f_w*(f_h+1))/2] = color; // single point for now +} +*/ + +void AM_Drawer(void) +{ + if (!automapactive) + return; + + UpdateState |= I_FULLSCRN; + AM_clearFB(BACKGROUND); + if (grid) + AM_drawGrid(GRIDCOLORS); + AM_drawWalls(); + AM_drawPlayers(); + DrawWorldTimer(); + + if (cheating == 2) + AM_drawThings(THINGCOLORS, THINGRANGE); + +// AM_drawCrosshair(XHAIRCOLORS); +// AM_drawMarks(); +// if(gameskill == sk_baby) AM_drawkeys(); + + MN_DrTextA(P_GetMapName(gamemap), 38, 144); + if (ShowKills && netgame && deathmatch) + { + AM_DrawDeathmatchStats(); + } +// I_Update(); +// V_MarkRect(f_x, f_y, f_w, f_h); + +} + +//=========================================================================== +// +// AM_DrawDeathmatchStats +// +//=========================================================================== + +// 8-player note: Proper player color names here, too + +const char *PlayerColorText[MAXPLAYERS] = { + "BLUE:", + "RED:", + "YELLOW:", + "GREEN:", + "JADE:", + "WHITE:", + "HAZEL:", + "PURPLE:" +}; + +void AM_DrawDeathmatchStats(void) +{ + int i, j, k, m; + int fragCount[MAXPLAYERS]; + int order[MAXPLAYERS]; + char textBuffer[80]; + int yPosition; + + for (i = 0; i < maxplayers; i++) + { + fragCount[i] = 0; + order[i] = -1; + } + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + { + continue; + } + else + { + for (j = 0; j < maxplayers; j++) + { + if (playeringame[j]) + { + fragCount[i] += players[i].frags[j]; + } + } + for (k = 0; k < maxplayers; k++) + { + if (order[k] == -1) + { + order[k] = i; + break; + } + else if (fragCount[i] > fragCount[order[k]]) + { + for (m = maxplayers - 1; m > k; m--) + { + order[m] = order[m - 1]; + } + order[k] = i; + break; + } + } + } + } + yPosition = 15; + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[order[i]]) + { + continue; + } + else + { + MN_DrTextA(PlayerColorText[order[i]], 8, yPosition); + M_snprintf(textBuffer, sizeof(textBuffer), + "%d", fragCount[order[i]]); + MN_DrTextA(textBuffer, 80, yPosition); + yPosition += 10; + } + } +} + +//=========================================================================== +// +// DrawWorldTimer +// +//=========================================================================== + +static void DrawWorldTimer(void) +{ + int days; + int hours; + int minutes; + int seconds; + int worldTimer; + char timeBuffer[15]; + char dayBuffer[20]; + + worldTimer = players[consoleplayer].worldTimer; + + worldTimer /= 35; + days = worldTimer / 86400; + worldTimer -= days * 86400; + hours = worldTimer / 3600; + worldTimer -= hours * 3600; + minutes = worldTimer / 60; + worldTimer -= minutes * 60; + seconds = worldTimer; + + M_snprintf(timeBuffer, sizeof(timeBuffer), + "%.2d : %.2d : %.2d", hours, minutes, seconds); + MN_DrTextA(timeBuffer, 240, 8); + + if (days) + { + if (days == 1) + { + M_snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAY", days); + } + else + { + M_snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAYS", days); + } + MN_DrTextA(dayBuffer, 240, 20); + if (days >= 5) + { + MN_DrTextA("YOU FREAK!!!", 230, 35); + } + } +} diff --git a/games/NXDoom/src/hexen/am_map.h b/games/NXDoom/src/hexen/am_map.h new file mode 100644 index 00000000000..f6081a448b0 --- /dev/null +++ b/games/NXDoom/src/hexen/am_map.h @@ -0,0 +1,128 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __AMMAP_H__ +#define __AMMAP_H__ + +// For use if I do walls with outsides/insides +#define REDS 12*8 +#define REDRANGE 1 //16 +#define BLUES (256-4*16+8) +#define BLUERANGE 1 //8 +#define GREENS (33*8) +#define GREENRANGE 1 //16 +#define GRAYS (5*8) +#define GRAYSRANGE 1 //16 +#define BROWNS (14*8) +#define BROWNRANGE 1 //16 +#define YELLOWS 10*8 +#define YELLOWRANGE 1 +#define BLACK 0 +#define WHITE 4*8 +#define PARCH 13*8-1 +#define BLOODRED 177 +#define BLUEKEY 157 +#define YELLOWKEY 137 +#define GREENKEY 198 + +// Automap colors + +#define AM_PLR1_COLOR 157 // Blue +#define AM_PLR2_COLOR 177 // Red +#define AM_PLR3_COLOR 137 // Yellow +#define AM_PLR4_COLOR 198 // Green +#define AM_PLR5_COLOR 215 // Jade +#define AM_PLR6_COLOR 32 // White +#define AM_PLR7_COLOR 106 // Hazel +#define AM_PLR8_COLOR 234 // Purple + +#define BACKGROUND PARCH +#define YOURCOLORS WHITE +#define YOURRANGE 0 +#define WALLCOLORS REDS +#define WALLRANGE REDRANGE +#define TSWALLCOLORS GRAYS +#define TSWALLRANGE GRAYSRANGE +#define FDWALLCOLORS BROWNS +#define FDWALLRANGE BROWNRANGE +#define CDWALLCOLORS YELLOWS +#define CDWALLRANGE YELLOWRANGE +#define THINGCOLORS GREENS +#define THINGRANGE GREENRANGE +#define SECRETWALLCOLORS WALLCOLORS +#define SECRETWALLRANGE WALLRANGE +#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) +#define GRIDRANGE 0 +#define XHAIRCOLORS GRAYS + +// drawing stuff + +#define AM_NUMMARKPOINTS 10 + +#define AM_MSGHEADER (('a'<<24)+('m'<<16)) +#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) +#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) + +#define INITSCALEMTOF (.2*FRACUNIT) // scale on entry +// how much the automap moves window per tic in frame-buffer coordinates +#define F_PANINC 4 // moves 140 pixels in 1 second +// how much zoom-in per tic +#define M_ZOOMIN ((int) (1.02*FRACUNIT)) // goes to 2x in 1 second +// how much zoom-out per tic +#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) // pulls out to 0.5x in 1 second + +// translates between frame-buffer and map distances +#define FTOM(x) FixedMul(((x)<<16),scale_ftom) +#define MTOF(x) (FixedMul((x),scale_mtof)>>16) +// translates between frame-buffer and map coordinates +#define CXMTOF(x) (f_x + MTOF((x)-m_x)) +#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) + +// the following is crap +#define LINE_NEVERSEE ML_DONTDRAW + +typedef struct +{ + int x, y; +} fpoint_t; + +typedef struct +{ + fpoint_t a, b; +} fline_t; + +typedef vertex_t mpoint_t; + +typedef struct +{ + mpoint_t a, b; +} mline_t; + +typedef struct +{ + fixed_t slp, islp; +} islope_t; + + +extern int cheating; +extern boolean automapactive; + + +void AM_Stop(void); + + +#endif diff --git a/games/NXDoom/src/hexen/ct_chat.c b/games/NXDoom/src/hexen/ct_chat.c new file mode 100644 index 00000000000..cba051dc09a --- /dev/null +++ b/games/NXDoom/src/hexen/ct_chat.c @@ -0,0 +1,497 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include +#include +#include "h2def.h" +#include "i_input.h" +#include "s_sound.h" +#include "doomkeys.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "v_video.h" + +#define NUMKEYS 256 + +#define QUEUESIZE 128 +#define MESSAGESIZE 128 +#define MESSAGELEN 265 + +// 8-player note: Change this stuff (CT_PLR_*, and the key mappings) +enum +{ + CT_PLR_BLUE = 1, + CT_PLR_RED, + CT_PLR_YELLOW, + CT_PLR_GREEN, + CT_PLR_PLAYER5, + CT_PLR_PLAYER6, + CT_PLR_PLAYER7, + CT_PLR_PLAYER8, + CT_PLR_ALL +}; + +#define CT_ESCAPE 6 + +// Public data + + +boolean chatmodeon; + +// Private data + +void CT_queueChatChar(char ch); +void CT_ClearChatMessage(int player); +void CT_AddChar(int player, char c); +void CT_BackSpace(int player); + +int head; +int tail; +byte ChatQueue[QUEUESIZE]; +int chat_dest[MAXPLAYERS]; +char chat_msg[MAXPLAYERS][MESSAGESIZE]; +char plr_lastmsg[MAXPLAYERS][MESSAGESIZE + 9]; +int msgptr[MAXPLAYERS]; +int msglen[MAXPLAYERS]; + +boolean cheated; + +static int FontABaseLump; + +const char *CT_FromPlrText[MAXPLAYERS] = { + "BLUE: ", + "RED: ", + "YELLOW: ", + "GREEN: ", + "JADE: ", + "WHITE: ", + "HAZEL: ", + "PURPLE: " +}; + +char *chat_macros[10]; + +boolean altdown; +boolean shiftdown; + + +//=========================================================================== +// +// CT_Init +// +// Initialize chat mode data +//=========================================================================== + +void CT_Init(void) +{ + int i; + + head = 0; //initialize the queue index + tail = 0; + chatmodeon = false; + memset(ChatQueue, 0, QUEUESIZE); + for (i = 0; i < maxplayers; i++) + { + chat_dest[i] = 0; + msgptr[i] = 0; + memset(plr_lastmsg[i], 0, MESSAGESIZE); + memset(chat_msg[i], 0, MESSAGESIZE); + } + FontABaseLump = W_GetNumForName("FONTA_S") + 1; + return; +} + +//=========================================================================== +// +// CT_Stop +// +//=========================================================================== + +void CT_Stop(void) +{ + chatmodeon = false; + I_StopTextInput(); + return; +} + +// These keys are allowed by Vanilla Heretic: + +static boolean ValidChatChar(char c) +{ + return (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') + || c == '!' || c == '?' + || c == ' ' || c == '\'' + || c == ',' || c == '.' + || c == '-' || c == '='; +} + +//=========================================================================== +// +// CT_Responder +// +//=========================================================================== + +boolean CT_Responder(event_t * ev) +{ + char *macro; + + int sendto; + + if (!netgame) + { + return false; + } + if (ev->data1 == KEY_RALT) + { + altdown = (ev->type == ev_keydown); + return false; + } + if (ev->data1 == KEY_RSHIFT) + { + shiftdown = (ev->type == ev_keydown); + return false; + } + if (gamestate != GS_LEVEL || ev->type != ev_keydown) + { + return false; + } + if (!chatmodeon) + { + sendto = 0; + if (ev->data1 == key_multi_msg) + { + sendto = CT_PLR_ALL; + } + else if (ev->data1 == key_multi_msgplayer[0]) + { + sendto = CT_PLR_BLUE; + } + else if (ev->data1 == key_multi_msgplayer[1]) + { + sendto = CT_PLR_RED; + } + else if (ev->data1 == key_multi_msgplayer[2]) + { + sendto = CT_PLR_YELLOW; + } + else if (ev->data1 == key_multi_msgplayer[3]) + { + sendto = CT_PLR_GREEN; + } + else if (ev->data1 == key_multi_msgplayer[4]) + { + sendto = CT_PLR_PLAYER5; + } + else if (ev->data1 == key_multi_msgplayer[5]) + { + sendto = CT_PLR_PLAYER6; + } + else if (ev->data1 == key_multi_msgplayer[6]) + { + sendto = CT_PLR_PLAYER7; + } + else if (ev->data1 == key_multi_msgplayer[7]) + { + sendto = CT_PLR_PLAYER8; + } + if (sendto == 0 || (sendto != CT_PLR_ALL && !playeringame[sendto - 1]) + || sendto == consoleplayer + 1) + { + return false; + } + CT_queueChatChar(sendto); + chatmodeon = true; + I_StartTextInput(25, 10, SCREENWIDTH, 18); + return true; + } + else + { + if (altdown) + { + if (ev->data1 >= '0' && ev->data1 <= '9') + { + if (ev->data1 == '0') + { // macro 0 comes after macro 9 + ev->data1 = '9' + 1; + } + macro = chat_macros[ev->data1 - '1']; + CT_queueChatChar(KEY_ENTER); //send old message + CT_queueChatChar(chat_dest[consoleplayer]); // chose the dest. + while (*macro) + { + CT_queueChatChar(toupper(*macro++)); + } + CT_queueChatChar(KEY_ENTER); //send it off... + CT_Stop(); + return true; + } + } + if (ev->data1 == KEY_ENTER) + { + CT_queueChatChar(KEY_ENTER); + usearti = false; + CT_Stop(); + return true; + } + else if (ev->data1 == KEY_ESCAPE) + { + CT_queueChatChar(CT_ESCAPE); + CT_Stop(); + return true; + } + else if (ev->data1 == KEY_BACKSPACE) + { + CT_queueChatChar(KEY_BACKSPACE); + return true; + } + else if (ValidChatChar(ev->data3)) + { + CT_queueChatChar(toupper(ev->data3)); + return true; + } + } + return false; +} + +//=========================================================================== +// +// CT_Ticker +// +//=========================================================================== + +void CT_Ticker(void) +{ + int i; + int j; + char c; + int numplayers; + + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + { + continue; + } + if ((c = players[i].cmd.chatchar) != 0) + { + if (c <= CT_PLR_ALL) + { + chat_dest[i] = c; + continue; + } + else if (c == CT_ESCAPE) + { + CT_ClearChatMessage(i); + } + else if (c == KEY_ENTER) + { + numplayers = 0; + for (j = 0; j < maxplayers; j++) + { + numplayers += playeringame[j]; + } + CT_AddChar(i, 0); // set the end of message character + if (numplayers > 2) + { + M_StringCopy(plr_lastmsg[i], CT_FromPlrText[i], + sizeof(plr_lastmsg[i])); + M_StringConcat(plr_lastmsg[i], chat_msg[i], + sizeof(plr_lastmsg[i])); + } + else + { + M_StringCopy(plr_lastmsg[i], chat_msg[i], + sizeof(plr_lastmsg[i])); + } + if (i != consoleplayer && (chat_dest[i] == consoleplayer + 1 + || chat_dest[i] == CT_PLR_ALL) + && *chat_msg[i]) + { + P_SetMessage(&players[consoleplayer], plr_lastmsg[i], + true); + S_StartSound(NULL, SFX_CHAT); + } + else if (i == consoleplayer && (*chat_msg[i])) + { + if (numplayers <= 1) + { + P_SetMessage(&players[consoleplayer], + "THERE ARE NO OTHER PLAYERS IN THE GAME!", + true); + S_StartSound(NULL, SFX_CHAT); + } + } + CT_ClearChatMessage(i); + } + else if (c == KEY_BACKSPACE) + { + CT_BackSpace(i); + } + else + { + CT_AddChar(i, c); + } + } + } + return; +} + +//=========================================================================== +// +// CT_Drawer +// +//=========================================================================== + +void CT_Drawer(void) +{ + int i; + int x; + patch_t *patch; + + if (chatmodeon) + { + x = 25; + for (i = 0; i < msgptr[consoleplayer]; i++) + { + if (chat_msg[consoleplayer][i] < 33) + { + x += 6; + } + else + { + patch = W_CacheLumpNum(FontABaseLump + + chat_msg[consoleplayer][i] - 33, + PU_CACHE); + V_DrawPatch(x, 10, patch); + x += patch->width; + } + } + V_DrawPatch(x, 10, W_CacheLumpName("FONTA59", PU_CACHE)); + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } +} + +//=========================================================================== +// +// CT_queueChatChar +// +//=========================================================================== + +void CT_queueChatChar(char ch) +{ + if (((tail + 1) & (QUEUESIZE - 1)) == head) + { // the queue is full + return; + } + ChatQueue[tail] = ch; + tail = (tail + 1) & (QUEUESIZE - 1); +} + +//=========================================================================== +// +// CT_dequeueChatChar +// +//=========================================================================== + +char CT_dequeueChatChar(void) +{ + byte temp; + + if (head == tail) + { // queue is empty + return 0; + } + temp = ChatQueue[head]; + head = (head + 1) & (QUEUESIZE - 1); + return temp; +} + +//=========================================================================== +// +// CT_AddChar +// +//=========================================================================== + +void CT_AddChar(int player, char c) +{ + patch_t *patch; + + if (msgptr[player] + 1 >= MESSAGESIZE || msglen[player] >= MESSAGELEN) + { // full. + return; + } + chat_msg[player][msgptr[player]] = c; + msgptr[player]++; + if (c < 33) + { + msglen[player] += 6; + } + else + { + patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + msglen[player] += patch->width; + } +} + +//=========================================================================== +// +// CT_BackSpace +// +// Backs up a space, when the user hits (obviously) backspace +//=========================================================================== + +void CT_BackSpace(int player) +{ + patch_t *patch; + char c; + + if (msgptr[player] == 0) + { // message is already blank + return; + } + msgptr[player]--; + c = chat_msg[player][msgptr[player]]; + if (c < 33) + { + msglen[player] -= 6; + } + else + { + patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + msglen[player] -= patch->width; + } + chat_msg[player][msgptr[player]] = 0; +} + +//=========================================================================== +// +// CT_ClearChatMessage +// +// Clears out the data for the chat message, but the player's message +// is still saved in plrmsg. +//=========================================================================== + +void CT_ClearChatMessage(int player) +{ + memset(chat_msg[player], 0, MESSAGESIZE); + msgptr[player] = 0; + msglen[player] = 0; +} diff --git a/games/NXDoom/src/hexen/ct_chat.h b/games/NXDoom/src/hexen/ct_chat.h new file mode 100644 index 00000000000..c46fdfce8bf --- /dev/null +++ b/games/NXDoom/src/hexen/ct_chat.h @@ -0,0 +1,38 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Chat mode stuff +// + +#ifndef HEXEN_CT_CHAT_H +#define HEXEN_CT_CHAT_H + +#define CT_PLR_GREEN 1 +#define CT_PLR_YELLOW 2 +#define CT_PLR_RED 3 +#define CT_PLR_BLUE 4 +#define CT_PLR_ALL 5 + +#define CT_KEY_GREEN 'g' +#define CT_KEY_YELLOW 'y' +#define CT_KEY_RED 'r' +#define CT_KEY_BLUE 'b' +#define CT_KEY_ALL 't' + +extern char *chat_macros[10]; + +#endif + diff --git a/games/NXDoom/src/hexen/d_net.c b/games/NXDoom/src/hexen/d_net.c new file mode 100644 index 00000000000..252914722cd --- /dev/null +++ b/games/NXDoom/src/hexen/d_net.c @@ -0,0 +1,283 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM Network game communication and protocol, +// all OS independend parts. +// + +#include + +#include "m_argv.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "i_videohr.h" +#include "h2def.h" +#include "m_misc.h" +#include "p_local.h" +#include "s_sound.h" +#include "w_checksum.h" + +#include "deh_main.h" + +#include "d_loop.h" + +ticcmd_t *netcmds; + + +// Called when a player leaves the game + +static void PlayerQuitGame(player_t *player) +{ + static char exitmsg[80]; + unsigned int player_num; + + player_num = player - players; + + M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg)); + exitmsg[7] += player_num; + P_SetMessage(&players[consoleplayer], exitmsg, true); + S_StartSound(NULL, SFX_CHAT); + + playeringame[player_num] = false; + + // TODO: check if it is sensible to do this: + + if (demorecording) + { + G_CheckDemoStatus (); + } +} + +static void RunTic(ticcmd_t *cmds, boolean *ingame) +{ + unsigned int i; + + // Check for player quits. + + for (i = 0; i < maxplayers; ++i) + { + if (!demoplayback && playeringame[i] && !ingame[i]) + { + PlayerQuitGame(&players[i]); + } + } + + netcmds = cmds; + + // check that there are players in the game. if not, we cannot + // run a tic. + + if (advancedemo) + H2_DoAdvanceDemo (); + + G_Ticker (); +} + +static loop_interface_t hexen_loop_interface = { + H2_ProcessEvents, + G_BuildTiccmd, + RunTic, + MN_Ticker +}; + + +// Load game settings from the specified structure and +// set global variables. + +static void LoadGameSettings(net_gamesettings_t *settings) +{ + unsigned int i; + + deathmatch = settings->deathmatch; + ticdup = settings->ticdup; + startepisode = settings->episode; + startmap = settings->map; + startskill = settings->skill; + // TODO startloadgame = settings->loadgame; + lowres_turn = settings->lowres_turn; + nomonsters = settings->nomonsters; + respawnparm = settings->respawn_monsters; + consoleplayer = settings->consoleplayer; + + if (lowres_turn) + { + printf("NOTE: Turning resolution is reduced; this is probably " + "because there is a client recording a Vanilla demo.\n"); + } + + for (i=0; inum_players; + PlayerClass[i] = settings->player_classes[i]; + + if (PlayerClass[i] >= NUMCLASSES) + { + PlayerClass[i] = PCLASS_FIGHTER; + } + } +} + +// Save the game settings from global variables to the specified +// game settings structure. + +static void SaveGameSettings(net_gamesettings_t *settings) +{ + // jhaley 20120715: Some parts of the structure are being left + // uninitialized. If -class is not used on the command line, this + // can lead to a crash in SB_Init due to player class == 0xCCCCCCCC. + memset(settings, 0, sizeof(*settings)); + + // Fill in game settings structure with appropriate parameters + // for the new game + + settings->deathmatch = deathmatch; + settings->episode = startepisode; + settings->map = startmap; + settings->skill = startskill; + // TODO settings->loadgame = startloadgame; + settings->gameversion = exe_hexen_1_1; + settings->nomonsters = nomonsters; + settings->respawn_monsters = respawnparm; + settings->timelimit = 0; + + settings->lowres_turn = M_ParmExists("-record") + && !M_ParmExists("-longtics"); +} + +static void InitConnectData(net_connect_data_t *connect_data) +{ + int i; + + // + // Connect data + // + + // Game type fields: + + connect_data->gamemode = gamemode; + connect_data->gamemission = hexen; + + // Are we recording a demo? Possibly set lowres turn mode + + connect_data->lowres_turn = M_ParmExists("-record") + && !M_ParmExists("-longtics"); + + connect_data->drone = false; + connect_data->max_players = maxplayers; + + //! + // @category net + // @arg + // + // Specify player class: 0=fighter, 1=cleric, 2=mage, 3=pig. + // + + i = M_CheckParmWithArgs("-class", 1); + + if (i > 0) + { + connect_data->player_class = atoi(myargv[i + 1]); + } + else + { + connect_data->player_class = PCLASS_FIGHTER; + } + + // Read checksums of our WAD directory and dehacked information + + W_Checksum(connect_data->wad_sha1sum); + memset(connect_data->deh_sha1sum, 0, sizeof(sha1_digest_t)); + + connect_data->is_freedoom = 0; +} + +void D_ConnectNetGame(void) +{ + net_connect_data_t connect_data; + + InitConnectData(&connect_data); + netgame = D_InitNetGame(&connect_data); + + //! + // @category net + // + // Start the game playing as though in a netgame with a single + // player. This can also be used to play back single player netgame + // demos. + // + + if (M_CheckParm("-solo-net") > 0) + { + netgame = true; + } +} + +static boolean StartupProgress(int now_ready, int total) +{ + static int ready = 0; + + while (ready < now_ready) + { + ST_NetProgress(); + ++ready; + } + + ready = now_ready; + + // Allow the user to hit escape during netgame startup to abort. + return !I_CheckAbortHR(); +} + +// +// D_CheckNetGame +// Works out player numbers among the net participants +// + +void D_CheckNetGame(void) +{ + net_gamesettings_t settings; + + D_RegisterLoopCallbacks(&hexen_loop_interface); + + if (netgame) + { + autostart = true; + } + + SaveGameSettings(&settings); + D_StartNetGame(&settings, StartupProgress); + LoadGameSettings(&settings); + + // Finish netgame progress on startup screen. + + if (netgame) + { + StartupProgress(settings.num_players, settings.num_players); + ST_NetDone(); + } +} + +//========================================================================== +// +// NET_SendFrags +// +//========================================================================== + +void NET_SendFrags(player_t * player) +{ + // Not sure what this is intended for. Unused? +} + diff --git a/games/NXDoom/src/hexen/f_finale.c b/games/NXDoom/src/hexen/f_finale.c new file mode 100644 index 00000000000..93af19e7a3b --- /dev/null +++ b/games/NXDoom/src/hexen/f_finale.c @@ -0,0 +1,387 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "i_system.h" +#include "i_video.h" +#include "p_local.h" +#include "s_sound.h" +#include +#include "v_video.h" +#include "i_swap.h" +#include "am_map.h" + + +// MACROS ------------------------------------------------------------------ + +#define TEXTSPEED 3 +#define TEXTWAIT 250 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void TextWrite(void); +static void DrawPic(void); +static void InitializeFade(boolean fadeIn); +static void DeInitializeFade(void); +static void FadePic(void); +static char *GetFinaleText(int sequence); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DECLARATIONS ------------------------------------------------ + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int FinaleStage; +static int FinaleCount; +static int FinaleEndCount; +static int FinaleLumpNum; +static int FontABaseLump; +static char *FinaleText; + +static fixed_t *Palette; +static fixed_t *PaletteDelta; +static byte *RealPalette; + +// CODE -------------------------------------------------------------------- + +//=========================================================================== +// +// F_StartFinale +// +//=========================================================================== + +void F_StartFinale(void) +{ + gameaction = ga_nothing; + gamestate = GS_FINALE; + viewactive = false; + automapactive = false; + P_ClearMessage(&players[consoleplayer]); + + FinaleStage = 0; + FinaleCount = 0; + FinaleText = GetFinaleText(0); + FinaleEndCount = 70; + FinaleLumpNum = W_GetNumForName("FINALE1"); + FontABaseLump = W_GetNumForName("FONTA_S") + 1; + InitializeFade(1); + +// S_ChangeMusic(mus_victor, true); + S_StartSongName("hall", false); // don't loop the song +} + +//=========================================================================== +// +// F_Responder +// +//=========================================================================== + +boolean F_Responder(event_t * event) +{ + return false; +} + +//=========================================================================== +// +// F_Ticker +// +//=========================================================================== + +void F_Ticker(void) +{ + FinaleCount++; + if (FinaleStage < 5 && FinaleCount >= FinaleEndCount) + { + FinaleCount = 0; + FinaleStage++; + switch (FinaleStage) + { + case 1: // Text 1 + FinaleEndCount = strlen(FinaleText) * TEXTSPEED + TEXTWAIT; + break; + case 2: // Pic 2, Text 2 + FinaleText = GetFinaleText(1); + FinaleEndCount = strlen(FinaleText) * TEXTSPEED + TEXTWAIT; + FinaleLumpNum = W_GetNumForName("FINALE2"); + S_StartSongName("orb", false); + break; + case 3: // Pic 2 -- Fade out + FinaleEndCount = 70; + DeInitializeFade(); + InitializeFade(0); + break; + case 4: // Pic 3 -- Fade in + FinaleLumpNum = W_GetNumForName("FINALE3"); + FinaleEndCount = 71; + DeInitializeFade(); + InitializeFade(1); + S_StartSongName("chess", true); + break; + case 5: // Pic 3 , Text 3 + FinaleText = GetFinaleText(2); + DeInitializeFade(); + break; + default: + break; + } + return; + } + if (FinaleStage == 0 || FinaleStage == 3 || FinaleStage == 4) + { + FadePic(); + } +} + +//=========================================================================== +// +// TextWrite +// +//=========================================================================== + +static void TextWrite(void) +{ + int count; + char *ch; + int c; + int cx, cy; + patch_t *w; + + memcpy(I_VideoBuffer, W_CacheLumpNum(FinaleLumpNum, PU_CACHE), + SCREENWIDTH * SCREENHEIGHT); + if (FinaleStage == 5) + { // Chess pic, draw the correct character graphic + if (netgame) + { + V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE)); + } + else if (PlayerClass[consoleplayer]) + { + V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc") + + PlayerClass[consoleplayer] - + 1, PU_CACHE)); + } + } + // Draw the actual text + if (FinaleStage == 5) + { + cy = 135; + } + else + { + cy = 5; + } + cx = 20; + ch = FinaleText; + count = (FinaleCount - 10) / TEXTSPEED; + if (count < 0) + { + count = 0; + } + for (; count; count--) + { + c = *ch++; + if (!c) + { + break; + } + if (c == '\n') + { + cx = 20; + cy += 9; + continue; + } + if (c < 32) + { + continue; + } + c = toupper(c); + if (c == 32) + { + cx += 5; + continue; + } + w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + if (cx + SHORT(w->width) > SCREENWIDTH) + { + break; + } + V_DrawPatch(cx, cy, w); + cx += SHORT(w->width); + } +} + +//=========================================================================== +// +// InitializeFade +// +//=========================================================================== + +static void InitializeFade(boolean fadeIn) +{ + unsigned i; + + Palette = Z_Malloc(768 * sizeof(fixed_t), PU_STATIC, 0); + PaletteDelta = Z_Malloc(768 * sizeof(fixed_t), PU_STATIC, 0); + RealPalette = Z_Malloc(768 * sizeof(byte), PU_STATIC, 0); + + if (fadeIn) + { + memset(RealPalette, 0, 768 * sizeof(byte)); + for (i = 0; i < 768; i++) + { + Palette[i] = 0; + PaletteDelta[i] = FixedDiv((*((byte *) W_CacheLumpName("playpal", + PU_CACHE) + + i)) << FRACBITS, 70 * FRACUNIT); + } + } + else + { + for (i = 0; i < 768; i++) + { + RealPalette[i] = + *((byte *) W_CacheLumpName("playpal", PU_CACHE) + i); + Palette[i] = RealPalette[i] << FRACBITS; + PaletteDelta[i] = FixedDiv(Palette[i], -70 * FRACUNIT); + } + } + I_SetPalette(RealPalette); +} + +//=========================================================================== +// +// DeInitializeFade +// +//=========================================================================== + +static void DeInitializeFade(void) +{ + Z_Free(Palette); + Z_Free(PaletteDelta); + Z_Free(RealPalette); +} + +//=========================================================================== +// +// FadePic +// +//=========================================================================== + +static void FadePic(void) +{ + unsigned i; + + for (i = 0; i < 768; i++) + { + Palette[i] += PaletteDelta[i]; + RealPalette[i] = Palette[i] >> FRACBITS; + } + I_SetPalette(RealPalette); +} + +//=========================================================================== +// +// DrawPic +// +//=========================================================================== + +static void DrawPic(void) +{ + memcpy(I_VideoBuffer, W_CacheLumpNum(FinaleLumpNum, PU_CACHE), + SCREENWIDTH * SCREENHEIGHT); + if (FinaleStage == 4 || FinaleStage == 5) + { // Chess pic, draw the correct character graphic + if (netgame) + { + V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE)); + } + else if (PlayerClass[consoleplayer]) + { + V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc") + + PlayerClass[consoleplayer] - + 1, PU_CACHE)); + } + } +} + +//=========================================================================== +// +// F_Drawer +// +//=========================================================================== + +void F_Drawer(void) +{ + switch (FinaleStage) + { + case 0: // Fade in initial finale screen + DrawPic(); + break; + case 1: + case 2: + TextWrite(); + break; + case 3: // Fade screen out + DrawPic(); + break; + case 4: // Fade in chess screen + DrawPic(); + break; + case 5: + TextWrite(); + break; + } + UpdateState |= I_FULLSCRN; +} + +//========================================================================== +// +// GetFinaleText +// +//========================================================================== + +static char *GetFinaleText(int sequence) +{ + const char *msgLumpName; + int msgSize; + int msgLump; + static const char *winMsgLumpNames[] = { + "win1msg", + "win2msg", + "win3msg" + }; + + msgLumpName = winMsgLumpNames[sequence]; + msgLump = W_GetNumForName(msgLumpName); + msgSize = W_LumpLength(msgLump); + if (msgSize >= MAX_INTRMSN_MESSAGE_SIZE) + { + I_Error("Finale message too long (%s)", msgLumpName); + } + W_ReadLump(msgLump, ClusterMessage); + ClusterMessage[msgSize] = 0; // Append terminator + return ClusterMessage; +} diff --git a/games/NXDoom/src/hexen/g_game.c b/games/NXDoom/src/hexen/g_game.c new file mode 100644 index 00000000000..ecfb3832767 --- /dev/null +++ b/games/NXDoom/src/hexen/g_game.c @@ -0,0 +1,2347 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include +#include "m_random.h" +#include "h2def.h" +#include "s_sound.h" +#include "doomkeys.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_video.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_argv.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "v_video.h" + +#define AM_STARTKEY 9 + +// External functions + + +// Functions + +void G_ReadDemoTiccmd(ticcmd_t * cmd); +void G_WriteDemoTiccmd(ticcmd_t * cmd); + +void G_DoReborn(int playernum); + +void G_DoLoadLevel(void); +void G_DoInitNew(void); +void G_DoNewGame(void); +void G_DoPlayDemo(void); +void G_DoTeleportNewMap(void); +void G_DoCompleted(void); +void G_DoVictory(void); +void G_DoWorldDone(void); +void G_DoSaveGame(void); +void G_DoSingleReborn(void); + +void H2_PageTicker(void); +void H2_AdvanceDemo(void); + +static boolean InventoryMoveLeft(); +static boolean InventoryMoveRight(); + + +gameaction_t gameaction; +gamestate_t gamestate; +skill_t gameskill; +//boolean respawnmonsters; +int gameepisode; +int gamemap; +int prevmap; + +boolean paused; +boolean sendpause; // send a pause event next tic +boolean sendsave; // send a save event next tic +boolean usergame; // ok to save / end game + +boolean timingdemo; // if true, exit with report on completion +int starttime; // for comparative timing purposes + +boolean viewactive; + +boolean deathmatch; // only if started as net death +boolean netgame; // only true if packets are broadcast +boolean playeringame[MAXPLAYERS]; +player_t players[MAXPLAYERS]; +pclass_t PlayerClass[MAXPLAYERS]; + +// Position indicator for cooperative net-play reborn +int RebornPosition; + +int consoleplayer; // player taking events and displaying +int displayplayer; // view being displayed +int levelstarttic; // gametic at level start + +char *demoname; +boolean demorecording; +boolean longtics; // specify high resolution turning in demos +boolean lowres_turn; +boolean shortticfix; // calculate lowres turning like doom +boolean demoplayback; +boolean demoextend; +boolean netdemo; +byte *demobuffer, *demo_p, *demoend; +boolean singledemo; // quit after playing a demo from cmdline + +boolean precache = true; // if true, load all graphics at start + +// TODO: Hexen uses 16-bit shorts for consistancy? +byte consistancy[MAXPLAYERS][BACKUPTICS]; + +int mouseSensitivity = 5; + +int LeaveMap; +static int LeavePosition; + +//#define MAXPLMOVE 0x32 // Old Heretic Max move + +fixed_t MaxPlayerMove[NUMCLASSES] = { 0x3C, 0x32, 0x2D, 0x31 }; +fixed_t forwardmove[NUMCLASSES][2] = { + {0x1D, 0x3C}, + {0x19, 0x32}, + {0x16, 0x2E}, + {0x18, 0x31} +}; + +fixed_t sidemove[NUMCLASSES][2] = { + {0x1B, 0x3B}, + {0x18, 0x28}, + {0x15, 0x25}, + {0x17, 0x27} +}; + +fixed_t angleturn[3] = { 640, 1280, 320 }; // + slow turn + +static int *weapon_keys[] = +{ + &key_weapon1, + &key_weapon2, + &key_weapon3, + &key_weapon4, +}; + +static int next_weapon = 0; + +#define SLOWTURNTICS 6 + +boolean gamekeydown[NUMKEYS]; +int turnheld; // for accelerative turning +int lookheld; + + +boolean mousearray[MAX_MOUSE_BUTTONS + 1]; +boolean *mousebuttons = &mousearray[1]; + // allow [-1] +int mousex, mousey; // mouse values are used once +int dclicktime, dclickstate, dclicks; +int dclicktime2, dclickstate2, dclicks2; + +#define MAX_JOY_BUTTONS 20 + +int joyxmove, joyymove; // joystick values are repeated +int joystrafemove; +int joylook; +boolean joyarray[MAX_JOY_BUTTONS + 1]; +boolean *joybuttons = &joyarray[1]; // allow [-1] + +int savegameslot; +char savedescription[32]; + +int vanilla_demo_limit = 1; + +int inventoryTics; + +// haleyjd: removed externdriver crap + +static skill_t TempSkill; +static int TempEpisode; +static int TempMap; + +boolean testcontrols = false; +int testcontrols_mousespeed; + +//============================================================================= +/* +==================== += += G_BuildTiccmd += += Builds a ticcmd from all of the available inputs or reads it from the += demo buffer. += If recording a demo, write it out +==================== +*/ + +boolean usearti = true; + +void G_BuildTiccmd(ticcmd_t *cmd, int maketic) +{ + int i; + boolean strafe, bstrafe; + int speed, tspeed, lspeed; + int forward, side; + int look, arti; + int flyheight; + int pClass; + + // haleyjd: removed externdriver crap + + pClass = players[consoleplayer].class; + memset(cmd, 0, sizeof(*cmd)); + +// cmd->consistancy = +// consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS]; + + cmd->consistancy = consistancy[consoleplayer][maketic % BACKUPTICS]; + +//printf ("cons: %i\n",cmd->consistancy); + + strafe = gamekeydown[key_strafe] + || mousebuttons[mousebstrafe] + || joybuttons[joybstrafe]; + + // Allow joybspeed hack. + + speed = key_speed >= NUMKEYS + || joybspeed >= MAX_JOY_BUTTONS + || gamekeydown[key_speed] + || joybuttons[joybspeed] + || mousebuttons[mousebspeed]; + + // haleyjd: removed externdriver crap + + forward = side = look = arti = flyheight = 0; + +// +// use two stage accelerative turning on the keyboard and joystick +// + if (joyxmove < 0 || joyxmove > 0 + || gamekeydown[key_right] || gamekeydown[key_left] + || mousebuttons[mousebturnright] || mousebuttons[mousebturnleft]) + turnheld += ticdup; + else + turnheld = 0; + if (turnheld < SLOWTURNTICS) + tspeed = 2; // slow turn + else + tspeed = speed; + + if (gamekeydown[key_lookdown] || gamekeydown[key_lookup]) + { + lookheld += ticdup; + } + else + { + lookheld = 0; + } + if (lookheld < SLOWTURNTICS) + { + lspeed = 1; // 3; + } + else + { + lspeed = 2; // 5; + } + +// +// let movement keys cancel each other out +// + if (strafe) + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + { + side += sidemove[pClass][speed]; + } + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + { + side -= sidemove[pClass][speed]; + } + if (use_analog && joyxmove) + { + joyxmove = joyxmove * joystick_move_sensitivity / 10; + joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; + joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; + side += FixedMul(sidemove[pClass][speed], joyxmove); + } + else if (joystick_move_sensitivity) + { + if (joyxmove > 0) + { + side += sidemove[pClass][speed]; + } + if (joyxmove < 0) + { + side -= sidemove[pClass][speed]; + } + } + } + else + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + cmd->angleturn -= angleturn[tspeed]; + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + cmd->angleturn += angleturn[tspeed]; + if (use_analog && joyxmove) + { + // Cubic response curve allows for finer control when stick + // deflection is small. + joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); + joyxmove = joyxmove * joystick_turn_sensitivity / 10; + cmd->angleturn -= FixedMul(angleturn[1], joyxmove); + } + else if (joystick_turn_sensitivity) + { + if (joyxmove > 0) + cmd->angleturn -= angleturn[tspeed]; + if (joyxmove < 0) + cmd->angleturn += angleturn[tspeed]; + } + } + + if (gamekeydown[key_up]) + { + forward += forwardmove[pClass][speed]; + } + if (gamekeydown[key_down]) + { + forward -= forwardmove[pClass][speed]; + } + if (use_analog && joyymove) + { + joyymove = joyymove * joystick_move_sensitivity / 10; + joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; + joyymove = (joyymove < -FRACUNIT) ? FRACUNIT : joyymove; + forward -= FixedMul(forwardmove[pClass][speed], joyymove); + } + else if (joystick_move_sensitivity) + { + if (joyymove < 0) + { + forward += forwardmove[pClass][speed]; + } + if (joyymove > 0) + { + forward -= forwardmove[pClass][speed]; + } + } + if (gamekeydown[key_straferight] || mousebuttons[mousebstraferight] + || joybuttons[joybstraferight]) + { + side += sidemove[pClass][speed]; + } + if (gamekeydown[key_strafeleft] || mousebuttons[mousebstrafeleft] + || joybuttons[joybstrafeleft]) + { + side -= sidemove[pClass][speed]; + } + + if (use_analog && joystrafemove) + { + joystrafemove = joystrafemove * joystick_move_sensitivity / 10; + joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; + joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; + side += FixedMul(sidemove[pClass][speed], joystrafemove); + } + else if (joystick_move_sensitivity) + { + if (joystrafemove < 0) + side -= sidemove[pClass][speed]; + if (joystrafemove > 0) + side += sidemove[pClass][speed]; + } + + // Look up/down/center keys + if (gamekeydown[key_lookup]) + { + look = lspeed; + } + if (gamekeydown[key_lookdown]) + { + look = -lspeed; + } + if (use_analog && joylook) + { + joylook = joylook * joystick_look_sensitivity / 10; + joylook = (joylook > FRACUNIT) ? FRACUNIT : joylook; + joylook = (joylook < -FRACUNIT) ? -FRACUNIT : joylook; + look = -FixedMul(2, joylook); + } + else if (joystick_look_sensitivity) + { + if (joylook < 0) + { + look = lspeed; + } + + if (joylook > 0) + { + look = -lspeed; + } + } + // haleyjd: removed externdriver crap + if (gamekeydown[key_lookcenter]) + { + look = TOCENTER; + } + + // haleyjd: removed externdriver crap + + // Fly up/down/drop keys + if (gamekeydown[key_flyup] || joybuttons[joybflyup]) + { + flyheight = 5; // note that the actual flyheight will be twice this + } + if (gamekeydown[key_flydown] || joybuttons[joybflydown]) + { + flyheight = -5; + } + if (gamekeydown[key_flycenter] || joybuttons[joybflycenter]) + { + flyheight = TOCENTER; + // haleyjd: removed externdriver crap + look = TOCENTER; + } + // Use artifact key + if (gamekeydown[key_useartifact] || mousebuttons[mousebuseartifact] + || joybuttons[joybuseartifact]) + { + if (gamekeydown[key_speed] && artiskip) + { + if (players[consoleplayer].inventory[inv_ptr].type != arti_none) + { // Skip an artifact + gamekeydown[key_useartifact] = false; + mousebuttons[mousebuseartifact] = false; + joybuttons[joybuseartifact] = false; + P_PlayerNextArtifact(&players[consoleplayer]); + } + } + else + { + if (inventory) + { + players[consoleplayer].readyArtifact = + players[consoleplayer].inventory[inv_ptr].type; + inventory = false; + cmd->arti = 0; + usearti = false; + } + else if (usearti) + { + cmd->arti |= + players[consoleplayer].inventory[inv_ptr]. + type & AFLAG_MASK; + usearti = false; + } + } + } + if (gamekeydown[key_jump] || mousebuttons[mousebjump] + || joybuttons[joybjump]) + { + cmd->arti |= AFLAG_JUMP; + } + if (mn_SuicideConsole) + { + cmd->arti |= AFLAG_SUICIDE; + mn_SuicideConsole = false; + } + + // Artifact hot keys + if (gamekeydown[key_arti_all] && !cmd->arti) + { + gamekeydown[key_arti_all] = false; // Use one of each artifact + cmd->arti = NUMARTIFACTS; + } + else if (gamekeydown[key_arti_health] && !cmd->arti + && (players[consoleplayer].mo->health < MAXHEALTH)) + { + gamekeydown[key_arti_health] = false; + cmd->arti = arti_health; + } + else if (gamekeydown[key_arti_poisonbag] && !cmd->arti) + { + gamekeydown[key_arti_poisonbag] = false; + cmd->arti = arti_poisonbag; + } + else if (gamekeydown[key_arti_blastradius] && !cmd->arti) + { + gamekeydown[key_arti_blastradius] = false; + cmd->arti = arti_blastradius; + } + else if (gamekeydown[key_arti_teleport] && !cmd->arti) + { + gamekeydown[key_arti_teleport] = false; + cmd->arti = arti_teleport; + } + else if (gamekeydown[key_arti_teleportother] && !cmd->arti) + { + gamekeydown[key_arti_teleportother] = false; + cmd->arti = arti_teleportother; + } + else if (gamekeydown[key_arti_egg] && !cmd->arti) + { + gamekeydown[key_arti_egg] = false; + cmd->arti = arti_egg; + } + else if (gamekeydown[key_arti_invulnerability] && !cmd->arti + && !players[consoleplayer].powers[pw_invulnerability]) + { + gamekeydown[key_arti_invulnerability] = false; + cmd->arti = arti_invulnerability; + } + +// +// buttons +// + cmd->chatchar = CT_dequeueChatChar(); + + if (gamekeydown[key_fire] || mousebuttons[mousebfire] + || joybuttons[joybfire]) + cmd->buttons |= BT_ATTACK; + + if (gamekeydown[key_use] || joybuttons[joybuse] || mousebuttons[mousebuse]) + { + cmd->buttons |= BT_USE; + dclicks = 0; // clear double clicks if hit use button + } + + // Weapon cycling. Switch to previous or next weapon. + // (Disabled when player is a pig). + if (gamestate == GS_LEVEL + && players[consoleplayer].morphTics == 0 && next_weapon != 0) + { + int start_i; + + if (players[consoleplayer].pendingweapon == WP_NOCHANGE) + { + i = players[consoleplayer].readyweapon; + } + else + { + i = players[consoleplayer].pendingweapon; + } + + // Don't loop forever. + start_i = i; + do { + i = (i + next_weapon + NUMWEAPONS) % NUMWEAPONS; + } while (i != start_i && !players[consoleplayer].weaponowned[i]); + + cmd->buttons |= BT_CHANGE; + cmd->buttons |= i << BT_WEAPONSHIFT; + } + else + { + for (i=0; ibuttons |= BT_CHANGE; + cmd->buttons |= i< 1) + { + dclickstate = mousebuttons[mousebforward]; + if (dclickstate) + dclicks++; + if (dclicks == 2) + { + cmd->buttons |= BT_USE; + dclicks = 0; + } + else + dclicktime = 0; + } + else + { + dclicktime += ticdup; + if (dclicktime > 20) + { + dclicks = 0; + dclickstate = 0; + } + } + + // + // strafe double click + // + bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; + if (bstrafe != dclickstate2 && dclicktime2 > 1) + { + dclickstate2 = bstrafe; + if (dclickstate2) + dclicks2++; + if (dclicks2 == 2) + { + cmd->buttons |= BT_USE; + dclicks2 = 0; + } + else + dclicktime2 = 0; + } + else + { + dclicktime2 += ticdup; + if (dclicktime2 > 20) + { + dclicks2 = 0; + dclickstate2 = 0; + } + } + } + + if (strafe) + { + side += mousex * 2; + } + else + { + cmd->angleturn -= mousex * 0x8; + } + + if (mousex == 0) + { + testcontrols_mousespeed = 0; + } + + forward += mousey; + mousex = mousey = 0; + + if (forward > MaxPlayerMove[pClass]) + { + forward = MaxPlayerMove[pClass]; + } + else if (forward < -MaxPlayerMove[pClass]) + { + forward = -MaxPlayerMove[pClass]; + } + if (side > MaxPlayerMove[pClass]) + { + side = MaxPlayerMove[pClass]; + } + else if (side < -MaxPlayerMove[pClass]) + { + side = -MaxPlayerMove[pClass]; + } + if (players[consoleplayer].powers[pw_speed] + && !players[consoleplayer].morphTics) + { // Adjust for a player with a speed artifact + forward = (3 * forward) >> 1; + side = (3 * side) >> 1; + } + cmd->forwardmove += forward; + cmd->sidemove += side; + if (players[consoleplayer].playerstate == PST_LIVE) + { + if (look < 0) + { + look += 16; + } + cmd->lookfly = look; + } + if (flyheight < 0) + { + flyheight += 16; + } + cmd->lookfly |= flyheight << 4; + +// +// special buttons +// + if (sendpause) + { + sendpause = false; + cmd->buttons = BT_SPECIAL | BTS_PAUSE; + } + + if (sendsave) + { + sendsave = false; + cmd->buttons = + BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT); + } + + if (lowres_turn) + { + if (shortticfix) + { + static signed short carry = 0; + signed short desired_angleturn; + + desired_angleturn = cmd->angleturn + carry; + + // round angleturn to the nearest 256 unit boundary + // for recording demos with single byte values for turn + + cmd->angleturn = (desired_angleturn + 128) & 0xff00; + + // Carry forward the error from the reduced resolution to the + // next tic, so that successive small movements can accumulate. + + carry = desired_angleturn - cmd->angleturn; + } + else + { + // truncate angleturn to the nearest 256 boundary + // for recording demos with single byte values for turn + cmd->angleturn &= 0xff00; + } + } +} + + +/* +============== += += G_DoLoadLevel += +============== +*/ + +void G_DoLoadLevel(void) +{ + int i; + + levelstarttic = gametic; // for time calculation + gamestate = GS_LEVEL; + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i] && players[i].playerstate == PST_DEAD) + players[i].playerstate = PST_REBORN; + memset(players[i].frags, 0, sizeof(players[i].frags)); + } + + SN_StopAllSequences(); + P_SetupLevel(gameepisode, gamemap, 0, gameskill); + displayplayer = consoleplayer; // view the guy you are playing + gameaction = ga_nothing; + Z_CheckHeap(); + +// +// clear cmd building stuff +// + + memset(gamekeydown, 0, sizeof(gamekeydown)); + joyxmove = joyymove = joystrafemove = joylook = 0; + mousex = mousey = 0; + sendpause = sendsave = paused = false; + memset(mousearray, 0, sizeof(mousearray)); + memset(joyarray, 0, sizeof(joyarray)); + + if (testcontrols) + { + P_SetMessage(&players[consoleplayer], "PRESS ESCAPE TO QUIT.", false); + } +} + +static void SetJoyButtons(unsigned int buttons_mask) +{ + int i; + player_t *plr; + + plr = &players[consoleplayer]; + + for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; + } + usearti = true; + } + } + + joybuttons[i] = button_on; + } +} + +// If an InventoryMove*() function is called when the inventory is not active, +// it will instead activate the inventory without attempting to change the +// selected item. This action is indicated by a return value of false. +// Otherwise, it attempts to change items and will return a value of true. + +static boolean InventoryMoveLeft() +{ + inventoryTics = 5 * 35; + if (!inventory) + { + inventory = true; + return false; + } + inv_ptr--; + if (inv_ptr < 0) + { + inv_ptr = 0; + } + else + { + curpos--; + if (curpos < 0) + { + curpos = 0; + } + } + return true; +} + +static boolean InventoryMoveRight() +{ + player_t *plr; + + plr = &players[consoleplayer]; + inventoryTics = 5 * 35; + if (!inventory) + { + inventory = true; + return false; + } + inv_ptr++; + if (inv_ptr >= plr->inventorySlotNum) + { + inv_ptr--; + if (inv_ptr < 0) + inv_ptr = 0; + } + else + { + curpos++; + if (curpos > 6) + { + curpos = 6; + } + } + return true; +} + +static void SetMouseButtons(unsigned int buttons_mask) +{ + int i; + player_t *plr; + + plr = &players[consoleplayer]; + + for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; + } + usearti = true; + } + } + + mousebuttons[i] = button_on; + } +} + +/* +=============================================================================== += += G_Responder += += get info needed to make ticcmd_ts for the players += +=============================================================================== +*/ + +boolean G_Responder(event_t * ev) +{ + player_t *plr; + + plr = &players[consoleplayer]; + if (ev->type == ev_keyup && ev->data1 == key_useartifact) + { // flag to denote that it's okay to use an artifact + if (!inventory) + { + plr->readyArtifact = plr->inventory[inv_ptr].type; + } + usearti = true; + } + + // Check for spy mode player cycle + if (gamestate == GS_LEVEL && ev->type == ev_keydown + && ev->data1 == key_spy && !deathmatch) + { // Cycle the display player + do + { + displayplayer++; + if (displayplayer == maxplayers) + { + displayplayer = 0; + } + } + while (!playeringame[displayplayer] + && displayplayer != consoleplayer); + return (true); + } + + if (CT_Responder(ev)) + { // Chat ate the event + return (true); + } + if (gamestate == GS_LEVEL) + { + if (SB_Responder(ev)) + { // Status bar ate the event + return (true); + } + if (AM_Responder(ev)) + { // Automap ate the event + return (true); + } + } + + if (ev->type == ev_mouse) + { + testcontrols_mousespeed = abs(ev->data2); + } + + if (ev->type == ev_keydown && ev->data1 == key_prevweapon) + { + next_weapon = -1; + } + else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) + { + next_weapon = 1; + } + + switch (ev->type) + { + case ev_keydown: + if (ev->data1 == key_invleft) + { + if (InventoryMoveLeft()) + { + return (true); + } + break; + } + if (ev->data1 == key_invright) + { + if (InventoryMoveRight()) + { + return (true); + } + break; + } + if (ev->data1 == key_pause && !MenuActive) + { + sendpause = true; + return (true); + } + if (ev->data1 < NUMKEYS) + { + gamekeydown[ev->data1] = true; + } + return (true); // eat key down events + + case ev_keyup: + if (ev->data1 < NUMKEYS) + { + gamekeydown[ev->data1] = false; + } + return (false); // always let key up events filter down + + case ev_mouse: + SetMouseButtons(ev->data1); + mousex = ev->data2 * (mouseSensitivity + 5) / 10; + mousey = ev->data3 * (mouseSensitivity + 5) / 10; + return (true); // eat events + + case ev_joystick: + SetJoyButtons(ev->data1); + joyxmove = ev->data2; + joyymove = ev->data3; + joystrafemove = ev->data4; + joylook = ev->data5; + return (true); // eat events + + default: + break; + } + return (false); +} + + +//========================================================================== +// +// G_Ticker +// +//========================================================================== + +void G_Ticker(void) +{ + int i, buf; + ticcmd_t *cmd = NULL; + +// +// do player reborns if needed +// + for (i = 0; i < maxplayers; i++) + if (playeringame[i] && players[i].playerstate == PST_REBORN) + G_DoReborn(i); + +// +// do things to change the game state +// + while (gameaction != ga_nothing) + { + switch (gameaction) + { + case ga_loadlevel: + G_DoLoadLevel(); + break; + case ga_initnew: + G_DoInitNew(); + break; + case ga_newgame: + G_DoNewGame(); + break; + case ga_loadgame: + Draw_LoadIcon(); + G_DoLoadGame(); + break; + case ga_savegame: + Draw_SaveIcon(); + G_DoSaveGame(); + break; + case ga_singlereborn: + G_DoSingleReborn(); + break; + case ga_playdemo: + G_DoPlayDemo(); + break; + case ga_screenshot: + V_ScreenShot("HEXEN%02i.%s"); + P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false); + gameaction = ga_nothing; + break; + case ga_leavemap: + Draw_TeleportIcon(); + G_DoTeleportNewMap(); + break; + case ga_completed: + G_DoCompleted(); + break; + case ga_worlddone: + G_DoWorldDone(); + break; + case ga_victory: + F_StartFinale(); + break; + default: + break; + } + } + + +// +// get commands, check consistancy, and build new consistancy check +// + //buf = gametic%BACKUPTICS; + buf = (gametic / ticdup) % BACKUPTICS; + + for (i = 0; i < maxplayers; i++) + if (playeringame[i]) + { + cmd = &players[i].cmd; + + memcpy(cmd, &netcmds[i], sizeof(ticcmd_t)); + + if (demoplayback) + G_ReadDemoTiccmd(cmd); + if (demorecording) + G_WriteDemoTiccmd(cmd); + + if (netgame && !netdemo && !(gametic % ticdup)) + { + if (gametic > BACKUPTICS + && consistancy[i][buf] != cmd->consistancy) + { + I_Error("consistency failure (%i should be %i)", + cmd->consistancy, consistancy[i][buf]); + } + if (players[i].mo) + consistancy[i][buf] = players[i].mo->x; + else + consistancy[i][buf] = rndindex; + } + } + +// +// check for special buttons +// + for (i = 0; i < maxplayers; i++) + if (playeringame[i]) + { + if (players[i].cmd.buttons & BT_SPECIAL) + { + switch (players[i].cmd.buttons & BT_SPECIALMASK) + { + case BTS_PAUSE: + paused ^= 1; + if (paused) + { + S_PauseSound(); + } + else + { + S_ResumeSound(); + } + break; + + case BTS_SAVEGAME: + if (!savedescription[0]) + { + if (netgame) + { + M_StringCopy(savedescription, "NET GAME", + sizeof(savedescription)); + } + else + { + M_StringCopy(savedescription, "SAVE GAME", + sizeof(savedescription)); + } + } + savegameslot = + (players[i].cmd. + buttons & BTS_SAVEMASK) >> BTS_SAVESHIFT; + gameaction = ga_savegame; + break; + } + } + } + // turn inventory off after a certain amount of time + if (inventory && !(--inventoryTics)) + { + players[consoleplayer].readyArtifact = + players[consoleplayer].inventory[inv_ptr].type; + inventory = false; + cmd->arti = 0; + } +// +// do main actions +// +// +// do main actions +// + switch (gamestate) + { + case GS_LEVEL: + P_Ticker(); + SB_Ticker(); + AM_Ticker(); + CT_Ticker(); + break; + case GS_INTERMISSION: + IN_Ticker(); + break; + case GS_FINALE: + F_Ticker(); + break; + case GS_DEMOSCREEN: + H2_PageTicker(); + break; + } +} + + +/* +============================================================================== + + PLAYER STRUCTURE FUNCTIONS + +also see P_SpawnPlayer in P_Things +============================================================================== +*/ + +//========================================================================== +// +// G_PlayerExitMap +// +// Called when the player leaves a map. +// +//========================================================================== + +void G_PlayerExitMap(int playerNumber) +{ + int i; + player_t *player; + int flightPower; + + player = &players[playerNumber]; + +// if(deathmatch) +// { +// // Strip all but one of each type of artifact +// for(i = 0; i < player->inventorySlotNum; i++) +// { +// player->inventory[i].count = 1; +// } +// player->artifactCount = player->inventorySlotNum; +// } +// else + + // Strip all current powers (retain flight) + flightPower = player->powers[pw_flight]; + memset(player->powers, 0, sizeof(player->powers)); + player->powers[pw_flight] = flightPower; + + if (deathmatch) + { + player->powers[pw_flight] = 0; + } + else + { + if (P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap)) + { // Entering new cluster + // Strip all keys + player->keys = 0; + + // Strip flight artifact + for (i = 0; i < 25; i++) + { + player->powers[pw_flight] = 0; + P_PlayerUseArtifact(player, arti_fly); + } + player->powers[pw_flight] = 0; + } + } + + if (player->morphTics) + { + player->readyweapon = player->mo->special1.i; // Restore weapon + player->morphTics = 0; + } + player->messageTics = 0; + player->lookdir = 0; + player->mo->flags &= ~MF_SHADOW; // Remove invisibility + player->extralight = 0; // Remove weapon flashes + player->fixedcolormap = 0; // Remove torch + player->damagecount = 0; // No palette changes + player->bonuscount = 0; + player->poisoncount = 0; + if (player == &players[consoleplayer]) + { + SB_state = -1; // refresh the status bar + viewangleoffset = 0; + } +} + +//========================================================================== +// +// G_PlayerReborn +// +// Called after a player dies. Almost everything is cleared and +// initialized. +// +//========================================================================== + +void G_PlayerReborn(int player) +{ + player_t *p; + int frags[MAXPLAYERS]; + int killcount, itemcount, secretcount; + unsigned int worldTimer; + + memcpy(frags, players[player].frags, sizeof(frags)); + killcount = players[player].killcount; + itemcount = players[player].itemcount; + secretcount = players[player].secretcount; + worldTimer = players[player].worldTimer; + + p = &players[player]; + memset(p, 0, sizeof(*p)); + + memcpy(players[player].frags, frags, sizeof(players[player].frags)); + players[player].killcount = killcount; + players[player].itemcount = itemcount; + players[player].secretcount = secretcount; + players[player].worldTimer = worldTimer; + players[player].class = PlayerClass[player]; + + p->usedown = p->attackdown = true; // don't do anything immediately + p->playerstate = PST_LIVE; + p->health = MAXHEALTH; + p->readyweapon = p->pendingweapon = WP_FIRST; + p->weaponowned[WP_FIRST] = true; + p->messageTics = 0; + p->lookdir = 0; + localQuakeHappening[player] = false; + if (p == &players[consoleplayer]) + { + SB_state = -1; // refresh the status bar + inv_ptr = 0; // reset the inventory pointer + curpos = 0; + viewangleoffset = 0; + } +} + +/* +==================== += += G_CheckSpot += += Returns false if the player cannot be respawned at the given mapthing_t spot += because something is occupying it +==================== +*/ + +void P_SpawnPlayer(mapthing_t * mthing); + +boolean G_CheckSpot(int playernum, mapthing_t * mthing) +{ + fixed_t x, y; + subsector_t *ss; + unsigned an; + mobj_t *mo; + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + players[playernum].mo->flags2 &= ~MF2_PASSMOBJ; + if (!P_CheckPosition(players[playernum].mo, x, y)) + { + players[playernum].mo->flags2 |= MF2_PASSMOBJ; + return false; + } + players[playernum].mo->flags2 |= MF2_PASSMOBJ; + +// spawn a teleport fog + ss = R_PointInSubsector(x, y); + an = ((unsigned) ANG45 * (mthing->angle / 45)) >> ANGLETOFINESHIFT; + + mo = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an], + ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); + if (players[consoleplayer].viewz != 1) + S_StartSound(mo, SFX_TELEPORT); // don't start sound on first frame + + return true; +} + +/* +==================== += += G_DeathMatchSpawnPlayer += += Spawns a player at one of the random death match spots += called at level load and each death +==================== +*/ + +void G_DeathMatchSpawnPlayer(int playernum) +{ + int i, j; + int selections; + + selections = deathmatch_p - deathmatchstarts; + + // This check has been moved to p_setup.c:P_LoadThings() + //if (selections < 8) + // I_Error ("Only %i deathmatch spots, 8 required", selections); + + for (j = 0; j < 20; j++) + { + i = P_Random() % selections; + if (G_CheckSpot(playernum, &deathmatchstarts[i])) + { + deathmatchstarts[i].type = playernum + 1; + P_SpawnPlayer(&deathmatchstarts[i]); + return; + } + } + +// no good spot, so the player will probably get stuck + P_SpawnPlayer(&playerstarts[0][playernum]); +} + +//========================================================================== +// +// G_DoReborn +// +//========================================================================== + +void G_DoReborn(int playernum) +{ + int i; + boolean oldWeaponowned[NUMWEAPONS]; + int oldKeys; + int oldPieces; + boolean foundSpot; + int bestWeapon; + + // quit demo unless -demoextend + if (!demoextend && G_CheckDemoStatus()) + { + return; + } + if (!netgame) + { + if (SV_RebornSlotAvailable()) + { // Use the reborn code if the slot is available + gameaction = ga_singlereborn; + } + else + { // Start a new game if there's no reborn info + gameaction = ga_newgame; + } + } + else + { // Net-game + players[playernum].mo->player = NULL; // Dissassociate the corpse + + if (deathmatch) + { // Spawn at random spot if in death match + G_DeathMatchSpawnPlayer(playernum); + return; + } + + // Cooperative net-play, retain keys and weapons + oldKeys = players[playernum].keys; + oldPieces = players[playernum].pieces; + for (i = 0; i < NUMWEAPONS; i++) + { + oldWeaponowned[i] = players[playernum].weaponowned[i]; + } + + foundSpot = false; + if (G_CheckSpot(playernum, &playerstarts[RebornPosition][playernum])) + { // Appropriate player start spot is open + P_SpawnPlayer(&playerstarts[RebornPosition][playernum]); + foundSpot = true; + } + else + { + // Try to spawn at one of the other player start spots + for (i = 0; i < maxplayers; i++) + { + if (G_CheckSpot(playernum, &playerstarts[RebornPosition][i])) + { // Found an open start spot + + // Fake as other player + playerstarts[RebornPosition][i].type = playernum + 1; + P_SpawnPlayer(&playerstarts[RebornPosition][i]); + + // Restore proper player type + playerstarts[RebornPosition][i].type = i + 1; + + foundSpot = true; + break; + } + } + } + + if (foundSpot == false) + { // Player's going to be inside something + P_SpawnPlayer(&playerstarts[RebornPosition][playernum]); + } + + // Restore keys and weapons + players[playernum].keys = oldKeys; + players[playernum].pieces = oldPieces; + for (bestWeapon = 0, i = 0; i < NUMWEAPONS; i++) + { + if (oldWeaponowned[i]) + { + bestWeapon = i; + players[playernum].weaponowned[i] = true; + } + } + players[playernum].mana[MANA_1] = 25; + players[playernum].mana[MANA_2] = 25; + if (bestWeapon) + { // Bring up the best weapon + players[playernum].pendingweapon = bestWeapon; + } + } +} + +void G_ScreenShot(void) +{ + gameaction = ga_screenshot; +} + +//========================================================================== +// +// G_StartNewInit +// +//========================================================================== + +void G_StartNewInit(void) +{ + SV_InitBaseSlot(); + SV_ClearRebornSlot(); + P_ACSInitNewGame(); + // Default the player start spot group to 0 + RebornPosition = 0; +} + +//========================================================================== +// +// G_StartNewGame +// +//========================================================================== + +void G_StartNewGame(skill_t skill) +{ + int realMap; + + G_StartNewInit(); + realMap = P_TranslateMap(1); + if (realMap == -1) + { + realMap = 1; + } + G_InitNew(TempSkill, 1, realMap); +} + +//========================================================================== +// +// G_TeleportNewMap +// +// Only called by the warp cheat code. Works just like normal map to map +// teleporting, but doesn't do any interlude stuff. +// +//========================================================================== + +void G_TeleportNewMap(int map, int position) +{ + gameaction = ga_leavemap; + LeaveMap = map; + LeavePosition = position; +} + +//========================================================================== +// +// G_DoTeleportNewMap +// +//========================================================================== + +void G_DoTeleportNewMap(void) +{ + SV_MapTeleport(LeaveMap, LeavePosition); + gamestate = GS_LEVEL; + gameaction = ga_nothing; + RebornPosition = LeavePosition; +} + +/* +boolean secretexit; +void G_ExitLevel (void) +{ + secretexit = false; + gameaction = ga_completed; +} +void G_SecretExitLevel (void) +{ + secretexit = true; + gameaction = ga_completed; +} +*/ + +//========================================================================== +// +// G_Completed +// +// Starts intermission routine, which is used only during hub exits, +// and DeathMatch games. +//========================================================================== + +void G_Completed(int map, int position) +{ + if (gamemode == shareware && map > 4) + { + P_SetMessage(&players[consoleplayer], "ACCESS DENIED -- DEMO", true); + S_StartSound(NULL, SFX_CHAT); + return; + } + + gameaction = ga_completed; + LeaveMap = map; + LeavePosition = position; +} + +void G_DoCompleted(void) +{ + int i; + + gameaction = ga_nothing; + + // quit demo unless -demoextend + if (!demoextend && G_CheckDemoStatus()) + { + return; + } + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + G_PlayerExitMap(i); + } + } + if (LeaveMap == -1 && LeavePosition == -1) + { + gameaction = ga_victory; + return; + } + else + { + gamestate = GS_INTERMISSION; + IN_Start(); + } + +/* + int i; + static int afterSecret[3] = { 7, 5, 5 }; + + gameaction = ga_nothing; + if(G_CheckDemoStatus()) + { + return; + } + for(i = 0; i < maxplayers; i++) + { + if(playeringame[i]) + { + G_PlayerFinishLevel(i); + } + } + prevmap = gamemap; + if(secretexit == true) + { + gamemap = 9; + } + else if(gamemap == 9) + { // Finished secret level + gamemap = afterSecret[gameepisode-1]; + } + else if(gamemap == 8) + { + gameaction = ga_victory; + return; + } + else + { + gamemap++; + } + gamestate = GS_INTERMISSION; + IN_Start(); +*/ +} + +//============================================================================ +// +// G_WorldDone +// +//============================================================================ + +void G_WorldDone(void) +{ + gameaction = ga_worlddone; +} + +//============================================================================ +// +// G_DoWorldDone +// +//============================================================================ + +void G_DoWorldDone(void) +{ + gamestate = GS_LEVEL; + G_DoLoadLevel(); + gameaction = ga_nothing; + viewactive = true; +} + +//========================================================================== +// +// G_DoSingleReborn +// +// Called by G_Ticker based on gameaction. Loads a game from the reborn +// save slot. +// +//========================================================================== + +void G_DoSingleReborn(void) +{ + gameaction = ga_nothing; + SV_LoadGame(SV_GetRebornSlot()); + SB_SetClassData(); +} + +//========================================================================== +// +// G_LoadGame +// +// Can be called by the startup code or the menu task. +// +//========================================================================== + +static int GameLoadSlot; + +void G_LoadGame(int slot) +{ + GameLoadSlot = slot; + gameaction = ga_loadgame; +} + +//========================================================================== +// +// G_DoLoadGame +// +// Called by G_Ticker based on gameaction. +// +//========================================================================== + +void G_DoLoadGame(void) +{ + gameaction = ga_nothing; + SV_LoadGame(GameLoadSlot); + if (!netgame) + { // Copy the base slot to the reborn slot + SV_UpdateRebornSlot(); + } + SB_SetClassData(); +} + +//========================================================================== +// +// G_SaveGame +// +// Called by the menu task. is a 24 byte text string. +// +//========================================================================== + +void G_SaveGame(int slot, char *description) +{ + savegameslot = slot; + M_StringCopy(savedescription, description, sizeof(savedescription)); + sendsave = true; +} + +//========================================================================== +// +// G_DoSaveGame +// +// Called by G_Ticker based on gameaction. +// +//========================================================================== + +void G_DoSaveGame(void) +{ + SV_SaveGame(savegameslot, savedescription); + gameaction = ga_nothing; + savedescription[0] = 0; + P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true); +} + +//========================================================================== +// +// G_DeferredNewGame +// +//========================================================================== + +void G_DeferredNewGame(skill_t skill) +{ + TempSkill = skill; + gameaction = ga_newgame; +} + +//========================================================================== +// +// G_DoNewGame +// +//========================================================================== + +void G_DoNewGame(void) +{ + G_StartNewGame(TempSkill); + gameaction = ga_nothing; +} + +/* +==================== += += G_InitNew += += Can be called by the startup code or the menu task += consoleplayer, displayplayer, playeringame[] should be set +==================== +*/ + +void G_DeferedInitNew(skill_t skill, int episode, int map) +{ + TempSkill = skill; + TempEpisode = episode; + TempMap = map; + gameaction = ga_initnew; +} + +void G_DoInitNew(void) +{ + SV_InitBaseSlot(); + G_InitNew(TempSkill, TempEpisode, TempMap); + gameaction = ga_nothing; +} + +void G_InitNew(skill_t skill, int episode, int map) +{ + int i; + + if (paused) + { + paused = false; + S_ResumeSound(); + } + if (skill < sk_baby) + { + skill = sk_baby; + } + if (skill > sk_nightmare) + { + skill = sk_nightmare; + } + if (map < 1) + { + map = 1; + } + if (map > 99) + { + map = 99; + } + M_ClearRandom(); + // Force players to be initialized upon first level load + for (i = 0; i < maxplayers; i++) + { + players[i].playerstate = PST_REBORN; + players[i].worldTimer = 0; + } + + // Set up a bunch of globals + if (!demoextend) + { + // This prevents map-loading from interrupting a demo. + // demoextend is set back to false only if starting a new game or + // loading a saved one from the menu, and only during playback. + demorecording = false; + demoplayback = false; + netdemo = false; + usergame = true; // will be set false if a demo + } + paused = false; + viewactive = true; + gameepisode = episode; + gamemap = map; + gameskill = skill; + BorderNeedRefresh = true; + + // Initialize the sky + R_InitSky(map); + + // Give one null ticcmd_t + //gametic = 0; + //maketic = 1; + //for (i=0 ; iforwardmove = ((signed char) *demo_p++); + cmd->sidemove = ((signed char) *demo_p++); + + // If this is a longtics demo, read back in higher resolution + + if (longtics) + { + cmd->angleturn = *demo_p++; + cmd->angleturn |= (*demo_p++) << 8; + } + else + { + cmd->angleturn = ((unsigned char) *demo_p++) << 8; + } + + cmd->buttons = (unsigned char) *demo_p++; + cmd->lookfly = (unsigned char) *demo_p++; + cmd->arti = (unsigned char) *demo_p++; +} + +// Increase the size of the demo buffer to allow unlimited demos + +static void IncreaseDemoBuffer(void) +{ + int current_length; + byte *new_demobuffer; + byte *new_demop; + int new_length; + + // Find the current size + + current_length = demoend - demobuffer; + + // Generate a new buffer twice the size + new_length = current_length * 2; + + new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); + new_demop = new_demobuffer + (demo_p - demobuffer); + + // Copy over the old data + + memcpy(new_demobuffer, demobuffer, current_length); + + // Free the old buffer and point the demo pointers at the new buffer. + + Z_Free(demobuffer); + + demobuffer = new_demobuffer; + demo_p = new_demop; + demoend = demobuffer + new_length; +} + +void G_WriteDemoTiccmd(ticcmd_t * cmd) +{ + byte *demo_start; + + if (gamekeydown[key_demo_quit]) // press to end demo recording + G_CheckDemoStatus(); + + demo_start = demo_p; + + *demo_p++ = cmd->forwardmove; + *demo_p++ = cmd->sidemove; + + // If this is a longtics demo, record in higher resolution + + if (longtics) + { + *demo_p++ = (cmd->angleturn & 0xff); + *demo_p++ = (cmd->angleturn >> 8) & 0xff; + } + else + { + *demo_p++ = cmd->angleturn >> 8; + } + + *demo_p++ = cmd->buttons; + *demo_p++ = cmd->lookfly; + *demo_p++ = cmd->arti; + + // reset demo pointer back + demo_p = demo_start; + + if (demo_p > demoend - 16) + { + if (vanilla_demo_limit) + { + // no more space + G_CheckDemoStatus(); + return; + } + else + { + // Vanilla demo limit disabled: unlimited + // demo lengths! + + IncreaseDemoBuffer(); + } + } + + G_ReadDemoTiccmd(cmd); // make SURE it is exactly the same +} + + + +/* +=================== += += G_RecordDemo += +=================== +*/ + +void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, + const char *name) +{ + size_t demoname_size; + int i; + int maxsize; + + //! + // @category demo + // + // Record or playback a demo with high resolution turning. + // + + longtics = D_NonVanillaRecord(M_ParmExists("-longtics"), + "vvHeretic longtics demo"); + + // If not recording a longtics demo, record in low res + + lowres_turn = !longtics; + + //! + // @category demo + // + // Smooth out low resolution turning when recording a demo. + // + + shortticfix = M_ParmExists("-shortticfix"); + + G_InitNew(skill, episode, map); + usergame = false; + demoname_size = strlen(name) + 5; + demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); + M_snprintf(demoname, demoname_size, "%s.lmp", name); + maxsize = 0x20000; + + //! + // @arg + // @category demo + // @vanilla + // + // Specify the demo buffer size (KiB) + // + + i = M_CheckParmWithArgs("-maxdemo", 1); + if (i) + maxsize = atoi(myargv[i + 1]) * 1024; + demobuffer = Z_Malloc(maxsize, PU_STATIC, NULL); + demoend = demobuffer + maxsize; + + demo_p = demobuffer; + *demo_p++ = skill; + *demo_p++ = episode; + *demo_p++ = map; + + // Write special parameter bits onto player one byte. + // This aligns with vvHeretic demo usage. Hexen demo support has no + // precedent here so consistency with another game is chosen: + // 0x20 = -respawn + // 0x10 = -longtics + // 0x02 = -nomonsters + + *demo_p = 1; // assume player one exists + if (D_NonVanillaRecord(respawnparm, "vvHeretic -respawn header flag")) + { + *demo_p |= DEMOHEADER_RESPAWN; + } + if (longtics) + { + *demo_p |= DEMOHEADER_LONGTICS; + } + if (D_NonVanillaRecord(nomonsters, "vvHeretic -nomonsters header flag")) + { + *demo_p |= DEMOHEADER_NOMONSTERS; + } + demo_p++; + *demo_p++ = PlayerClass[0]; + + for (i = 1; i < maxplayers; i++) + { + *demo_p++ = playeringame[i]; + *demo_p++ = PlayerClass[i]; + } + + demorecording = true; +} + + +/* +=================== += += G_PlayDemo += +=================== +*/ + +static const char *defdemoname; + +void G_DeferedPlayDemo(const char *name) +{ + defdemoname = name; + gameaction = ga_playdemo; +} + +void G_DoPlayDemo(void) +{ + skill_t skill; + int i, lumpnum, episode, map; + + gameaction = ga_nothing; + lumpnum = W_GetNumForName(defdemoname); + demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC); + demo_p = demobuffer; + skill = *demo_p++; + episode = *demo_p++; + map = *demo_p++; + + // When recording we store some extra options inside the upper bits + // of the player 1 present byte. However, this is a non-vanilla extension. + // Note references to vvHeretic here; these are the extensions used by + // vvHeretic, which we're just reusing for Hexen demos too. There is no + // vvHexen. + if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_LONGTICS) != 0, + lumpnum, "vvHeretic longtics demo")) + { + longtics = true; + } + if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_RESPAWN) != 0, + lumpnum, "vvHeretic -respawn header flag")) + { + respawnparm = true; + } + if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_NOMONSTERS) != 0, + lumpnum, "vvHeretic -nomonsters header flag")) + { + nomonsters = true; + } + + for (i = 0; i < maxplayers; i++) + { + playeringame[i] = (*demo_p++) != 0; + PlayerClass[i] = *demo_p++; + } + + if (playeringame[1] || M_ParmExists("-solo-net") + || M_ParmExists("-netdemo")) + { + netgame = true; + } + + // Initialize world info, etc. + G_StartNewInit(); + + precache = false; // don't spend a lot of time in loadlevel + G_InitNew(skill, episode, map); + precache = true; + usergame = false; + demoplayback = true; + + if (netgame) + { + netdemo = true; + } +} + + +/* +=================== += += G_TimeDemo += +=================== +*/ + +void G_TimeDemo(char *name) +{ + skill_t skill; + int episode, map, i; + + demobuffer = demo_p = W_CacheLumpName(name, PU_STATIC); + skill = *demo_p++; + episode = *demo_p++; + map = *demo_p++; + + // Read special parameter bits: see G_RecordDemo() for details. + longtics = (*demo_p & DEMOHEADER_LONGTICS) != 0; + + // don't overwrite arguments from the command line + respawnparm |= (*demo_p & DEMOHEADER_RESPAWN) != 0; + nomonsters |= (*demo_p & DEMOHEADER_NOMONSTERS) != 0; + + for (i = 0; i < maxplayers; i++) + { + playeringame[i] = (*demo_p++) != 0; + PlayerClass[i] = *demo_p++; + } + + if (playeringame[1] || M_ParmExists("-solo-net") + || M_ParmExists("-netdemo")) + { + netgame = true; + } + + G_InitNew(skill, episode, map); + starttime = I_GetTime(); + + usergame = false; + demoplayback = true; + timingdemo = true; + singletics = true; + + if (netgame) + { + netdemo = true; + } +} + + +/* +=================== += += G_CheckDemoStatus += += Called after a death or level completion to allow demos to be cleaned up += Returns true if a new demo loop action will take place +=================== +*/ + +boolean G_CheckDemoStatus(void) +{ + int endtime, realtics; + + if (timingdemo) + { + float fps; + endtime = I_GetTime(); + realtics = endtime - starttime; + fps = ((float) gametic * TICRATE) / realtics; + I_Error("timed %i gametics in %i realtics (%f fps)", + gametic, realtics, fps); + } + + if (demoplayback) + { + if (singledemo) + I_Quit(); + + W_ReleaseLumpName(defdemoname); + demoplayback = false; + netdemo = false; + netgame = false; + H2_AdvanceDemo(); + return true; + } + + if (demorecording) + { + *demo_p++ = DEMOMARKER; + M_WriteFile(demoname, demobuffer, demo_p - demobuffer); + Z_Free(demobuffer); + demorecording = false; + I_Error("Demo %s recorded", demoname); + } + + return false; +} diff --git a/games/NXDoom/src/hexen/h2_main.c b/games/NXDoom/src/hexen/h2_main.c new file mode 100644 index 00000000000..0a7bff85fe6 --- /dev/null +++ b/games/NXDoom/src/hexen/h2_main.c @@ -0,0 +1,1227 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +// haleyjd: removed WATCOMC +#include +#include +#include + +#include "config.h" + +#include "h2def.h" +#include "ct_chat.h" +#include "d_iwad.h" +#include "d_mode.h" +#include "m_misc.h" +#include "s_sound.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" +#include "net_client.h" +#include "p_local.h" +#include "v_video.h" +#include "w_main.h" +#include "am_map.h" + +#include "hexen_icon.c" + +// MACROS ------------------------------------------------------------------ + +#define MAXWADFILES 20 +#define CT_KEY_BLUE 'b' +#define CT_KEY_RED 'r' +#define CT_KEY_YELLOW 'y' +#define CT_KEY_GREEN 'g' +#define CT_KEY_PLAYER5 'j' // Jade +#define CT_KEY_PLAYER6 'w' // White +#define CT_KEY_PLAYER7 'h' // Hazel +#define CT_KEY_PLAYER8 'p' // Purple +#define CT_KEY_ALL 't' + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +void R_ExecuteSetViewSize(void); +void D_ConnectNetGame(void); +void D_CheckNetGame(void); +boolean F_Responder(event_t * ev); +void I_StartupKeyboard(void); +void I_StartupJoystick(void); +void I_ShutdownKeyboard(void); +void S_InitScript(void); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +void H2_AdvanceDemo(void); +void H2_PageTicker(void); + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void DrawMessage(void); +static void PageDrawer(void); +static void HandleArgs(void); +static void CheckRecordFrom(void); +static void DrawAndBlit(void); +static void CreateSavePath(void); +static void WarpCheck(void); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +GameMode_t gamemode; +GameVersion_t gameversion = exe_hexen_1_1; +static const char *gamedescription; +char *iwadfile; +static char demolumpname[9]; // Demo lump to start playing. +boolean nomonsters; // checkparm of -nomonsters +boolean respawnparm; // checkparm of -respawn +boolean randomclass; // checkparm of -randclass +boolean debugmode; // checkparm of -debug +boolean ravpic; // checkparm of -ravpic +boolean cdrom = false; // true if cd-rom mode active +boolean cmdfrag; // true if a CMD_FRAG packet should be sent out +boolean artiskip; // whether shift-enter skips an artifact +int maxzone = 0x800000; // Maximum allocated for zone heap (8meg default) +skill_t startskill; +int startepisode; +int startmap; +boolean autostart; +boolean advancedemo; +FILE *debugfile; +int UpdateState; +int maxplayers = MAXPLAYERS; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int WarpMap; +static int demosequence; +static int pagetic; +static const char *pagename; +static char *SavePathConfig; + +// CODE -------------------------------------------------------------------- + + +static const char * const chat_macro_defaults[10] = +{ + HUSTR_CHATMACRO0, + HUSTR_CHATMACRO1, + HUSTR_CHATMACRO2, + HUSTR_CHATMACRO3, + HUSTR_CHATMACRO4, + HUSTR_CHATMACRO5, + HUSTR_CHATMACRO6, + HUSTR_CHATMACRO7, + HUSTR_CHATMACRO8, + HUSTR_CHATMACRO9, +}; + + +void D_BindVariables(void) +{ + int i; + + M_ApplyPlatformDefaults(); + + I_BindInputVariables(); + I_BindVideoVariables(); + I_BindJoystickVariables(); + I_BindSoundVariables(); + + M_BindBaseControls(); + M_BindMapControls(); + M_BindMenuControls(); + M_BindWeaponControls(); + M_BindChatControls(MAXPLAYERS); + M_BindHereticControls(); + M_BindHexenControls(); + + key_multi_msgplayer[0] = CT_KEY_BLUE; + key_multi_msgplayer[1] = CT_KEY_RED; + key_multi_msgplayer[2] = CT_KEY_YELLOW; + key_multi_msgplayer[3] = CT_KEY_GREEN; + key_multi_msgplayer[4] = CT_KEY_PLAYER5; + key_multi_msgplayer[5] = CT_KEY_PLAYER6; + key_multi_msgplayer[6] = CT_KEY_PLAYER7; + key_multi_msgplayer[7] = CT_KEY_PLAYER8; + + NET_BindVariables(); + + M_BindIntVariable("graphical_startup", &graphical_startup); + M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); + M_BindIntVariable("sfx_volume", &snd_MaxVolume); + M_BindIntVariable("music_volume", &snd_MusicVolume); + M_BindIntVariable("messageson", &messageson); + M_BindIntVariable("screenblocks", &screenblocks); + M_BindIntVariable("snd_channels", &snd_Channels); + M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); + M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); + + M_BindStringVariable("savedir", &SavePathConfig); + + // Multiplayer chat macros + + for (i=0; i<10; ++i) + { + char buf[12]; + + chat_macros[i] = M_StringDuplicate(chat_macro_defaults[i]); + M_snprintf(buf, sizeof(buf), "chatmacro%i", i); + M_BindStringVariable(buf, &chat_macros[i]); + } +} + +// Set the default directory where hub savegames are saved. + +static void D_SetDefaultSavePath(void) +{ + SavePath = M_GetSaveGameDir("hexen.wad"); + + if (!strcmp(SavePath, "")) + { + // only get hexen.cfg path if one is not already found + + if (SavePathConfig == NULL || !strcmp(SavePathConfig, "")) + { + // If we are not using a savegame path (probably because we are on + // Windows and not using a config dir), behave like Vanilla Hexen + // and use hexndata/: + + SavePath = malloc(10); + M_snprintf(SavePath, 10, "hexndata%c", DIR_SEPARATOR); + } + else + { + SavePath = M_StringDuplicate(SavePathConfig); + } + } + + // only set hexen.cfg path if using default handling + + if (!M_ParmExists("-savedir") && !M_ParmExists("-cdrom")) + { + SavePathConfig = SavePath; + } +} + +// The Mac version of the Hexen IWAD is different to the "normal" DOS +// version - it doesn't include lumps used by the DOS DMX library. +// This means that we can't do GUS or OPL emulation and need to apply +// a workaround. +static void AdjustForMacIWAD(void) +{ + boolean adjust_music = false; + + switch (snd_musicdevice) + { + case SNDDEVICE_ADLIB: + case SNDDEVICE_SB: + adjust_music = W_CheckNumForName("GENMIDI") < 0; + break; + + case SNDDEVICE_GUS: + adjust_music = W_CheckNumForName("DMXGUS") < 0; + break; + + default: + break; + } + + if (adjust_music) + { + printf("** Note: You appear to be using the Mac version of the Hexen\n" + "** IWAD file. This is missing the lumps required for OPL or\n" + "** GUS emulation. Your music configuration is being adjusted\n" + "** to a different setting that won't cause the game to " + "crash.\n"); + snd_musicdevice = SNDDEVICE_GENMIDI; + } +} + +// +// D_GrabMouseCallback +// +// Called to determine whether to grab the mouse pointer +// + +static boolean D_GrabMouseCallback(void) +{ + // when menu is active or game is paused, release the mouse + + if (MenuActive || paused) + return false; + + // only grab mouse when playing levels (but not demos) + + return (gamestate == GS_LEVEL) && !advancedemo && !demoplayback; +} + +// Message displayed when quitting Hexen + +static void D_HexenQuitMessage(void) +{ + printf("\nHexen: Beyond Heretic\n"); +} + +static void D_AddFile(char *filename) +{ + printf(" adding %s\n", filename); + + W_AddFile(filename); +} + +// Find out what version of Hexen is playing. + +void D_IdentifyVersion(void) +{ + // The Hexen Shareware, ne 4 Level Demo Version, is missing the SKY1 lump + // and uses the SKY2 lump instead. Let's use this fact and the missing + // levels from MAP05 onward to identify it and set gamemode accordingly. + + if (W_CheckNumForName("SKY1") == -1 && + W_CheckNumForName("MAP05") == -1 ) + { + gamemode = shareware; + maxplayers = 4; + } + + // The v1.0 IWAD file is missing a bunch of lumps that can cause the game + // to crash, so we exit with an error if the user tries to play with it. + // But we provide an override command line flag if they really want to + // do it. + + //! + // If provided, the check for the v1.0 IWAD file is disabled, even though + // it will almost certainly cause the game to crash. + // + // @category compat + // + + if (!M_ParmExists("-v10override") + && gamemode != shareware && W_CheckNumForName("CLUS1MSG") < 0) + { + I_Error( + "You are trying to use the Hexen v1.0 IWAD. This isn't\n" + "supported by " PACKAGE_NAME ". Please upgrade to the v1.1\n" + "IWAD file. See here for more information:\n" + " https://www.doomworld.com/classicdoom/info/patches.php"); + } +} + +// Set the gamedescription string. + +void D_SetGameDescription(void) +{ +/* + NB: The 4 Level Demo Version actually prints a four-lined banner + (and indeed waits for a keypress): + + Hexen: Beyond Heretic + + 4 Level Demo Version + Press any key to continue. +*/ + + if (gamemode == shareware) + { + gamedescription = "Hexen: 4 Level Demo Version"; + } + else + { + gamedescription = "Hexen"; + } +} + +static const struct +{ + const char *description; + const char *cmdline; + GameVersion_t version; +} gameversions[] = { + {"Hexen 1.1", "1.1", exe_hexen_1_1}, + {"Hexen 1.1 (alt)", "1.1r2", exe_hexen_1_1r2}, + { NULL, NULL, 0}, +}; + +// Initialize the game version + +static void InitGameVersion(void) +{ + int p; + + //! + // @arg + // @category compat + // + // Emulate a specific version of Hexen. + // Valid values are "1.1" and "1.1r2". + // + + p = M_CheckParmWithArgs("-gameversion", 1); + + if (p) + { + int i; + for (i=0; gameversions[i].description != NULL; ++i) + { + if (!strcmp(myargv[p+1], gameversions[i].cmdline)) + { + gameversion = gameversions[i].version; + break; + } + } + + if (gameversions[i].description == NULL) + { + printf("Supported game versions:\n"); + + for (i=0; gameversions[i].description != NULL; ++i) + { + printf("\t%s (%s)\n", gameversions[i].cmdline, + gameversions[i].description); + } + + I_Error("Unknown game version '%s'", myargv[p+1]); + } + } + else + { + // Determine automatically + + gameversion = exe_hexen_1_1; + } +} + +void PrintGameVersion(void) +{ + int i; + + for (i=0; gameversions[i].description != NULL; ++i) + { + if (gameversions[i].version == gameversion) + { + printf("Emulating the behavior of the " + "'%s' executable.\n", gameversions[i].description); + break; + } + } +} + +//========================================================================== +// +// H2_Main +// +//========================================================================== +void InitMapMusicInfo(void); + +void D_DoomMain(void) +{ + GameMission_t gamemission; + int p; + + I_AtExit(D_HexenQuitMessage, false); + startepisode = 1; + autostart = false; + startskill = sk_medium; + startmap = 1; + gamemode = commercial; + + I_PrintBanner(PACKAGE_STRING); + + // Initialize subsystems + + ST_Message("V_Init: allocate screens.\n"); + V_Init(); + + // Load defaults before initing other systems + ST_Message("M_LoadDefaults: Load system defaults.\n"); + D_BindVariables(); + +#ifdef _WIN32 + + //! + // @category obscure + // @platform windows + // @vanilla + // + // Save configuration data and savegames in c:\hexndata, + // allowing play from CD. + // + + cdrom = M_ParmExists("-cdrom"); +#endif + + if (cdrom) + { + M_SetConfigDir("c:\\hexndata\\"); + } + else + { + M_SetConfigDir(NULL); + } + + M_SetConfigFilenames("hexen.cfg", PROGRAM_PREFIX "hexen.cfg"); + M_LoadDefaults(); + + D_SetDefaultSavePath(); + + I_AtExit(M_SaveDefaults, false); + + // Now that the savedir is loaded, make sure it exists + CreateSavePath(); + + ST_Message("Z_Init: Init zone memory allocation daemon.\n"); + Z_Init(); + + // haleyjd: removed WATCOMC + + ST_Message("W_Init: Init WADfiles.\n"); + + iwadfile = D_FindIWAD(IWAD_MASK_HEXEN, &gamemission); + + if (iwadfile == NULL) + { + I_Error("Game mode indeterminate. No IWAD was found. Try specifying\n" + "one with the '-iwad' command line parameter."); + } + + D_AddFile(iwadfile); + W_CheckCorrectIWAD(hexen); + D_IdentifyVersion(); + InitGameVersion(); + D_SetGameDescription(); + AdjustForMacIWAD(); + + //! + // @category mod + // + // Disable auto-loading of .wad files. + // + if (!M_ParmExists("-noautoload")) + { + char *autoload_dir; + autoload_dir = M_GetAutoloadDir("hexen.wad"); + if (autoload_dir != NULL) + { + // TODO? DEH_AutoLoadPatches(autoload_dir); + W_AutoLoadWADs(autoload_dir); + free(autoload_dir); + } + } + + HandleArgs(); + + // Generate the WAD hash table. Speed things up a bit. + W_GenerateHashTable(); + + I_PrintStartupBanner(gamedescription); + + ST_Message("MN_Init: Init menu system.\n"); + MN_Init(); + + ST_Message("CT_Init: Init chat mode data.\n"); + CT_Init(); + + InitMapMusicInfo(); // Init music fields in mapinfo + + ST_Message("S_InitScript\n"); + S_InitScript(); + + ST_Message("SN_InitSequenceScript: Registering sound sequences.\n"); + SN_InitSequenceScript(); + ST_Message("I_Init: Setting up machine state.\n"); + I_CheckIsScreensaver(); + I_InitTimer(); + I_InitJoystick(); + I_InitSound(hexen); + I_InitMusic(); + + ST_Message("NET_Init: Init networking subsystem.\n"); + NET_Init(); + D_ConnectNetGame(); + + S_Init(); + S_Start(); + + ST_Message("ST_Init: Init startup screen.\n"); + ST_Init(); + + // Show version message now, so it's visible during R_Init() + ST_Message("R_Init: Init Hexen refresh daemon"); + R_Init(); + ST_Message("\n"); + + //if (M_CheckParm("-net")) + // ST_NetProgress(); // Console player found + + ST_Message("P_Init: Init Playloop state.\n"); + P_Init(); + + // Check for command line warping. Follows P_Init() because the + // MAPINFO.TXT script must be already processed. + WarpCheck(); + + ST_Message("D_CheckNetGame: Checking network game status.\n"); + D_CheckNetGame(); + + PrintGameVersion(); + + ST_Message("SB_Init: Loading patches.\n"); + SB_Init(); + + ST_Done(); + + if (autostart) + { + ST_Message("Warp to Map %d (\"%s\":%d), Skill %d\n", + WarpMap, P_GetMapName(startmap), startmap, startskill + 1); + } + + CheckRecordFrom(); + + //! + // @arg + // @category demo + // @vanilla + // + // Record a demo named x.lmp. + // + + p = M_CheckParm("-record"); + if (p && p < myargc - 1) + { + G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p + 1]); + H2_GameLoop(); // Never returns + } + + p = M_CheckParmWithArgs("-playdemo", 1); + if (p) + { + singledemo = true; // Quit after one demo + G_DeferedPlayDemo(demolumpname); + H2_GameLoop(); // Never returns + } + + p = M_CheckParmWithArgs("-timedemo", 1); + if (p) + { + G_TimeDemo(demolumpname); + H2_GameLoop(); // Never returns + } + + //! + // @category game + // @arg + // @vanilla + // + // Load the game in savegame slot s. + // + + p = M_CheckParmWithArgs("-loadgame", 1); + if (p) + { + G_LoadGame(atoi(myargv[p + 1])); + } + + if (gameaction != ga_loadgame) + { + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; + if (autostart || netgame) + { + G_StartNewInit(); + G_InitNew(startskill, startepisode, startmap); + } + else + { + H2_StartTitle(); + } + } + H2_GameLoop(); // Never returns +} + +//========================================================================== +// +// HandleArgs +// +//========================================================================== + +static void HandleArgs(void) +{ + int p; + + //! + // @category game + // @vanilla + // + // Disable monsters. + // + + nomonsters = M_ParmExists("-nomonsters"); + + //! + // @category game + // @vanilla + // + // Monsters respawn after being killed. + // + + respawnparm = M_ParmExists("-respawn"); + + //! + // @vanilla + // @category net + // + // In deathmatch mode, change a player's class each time the + // player respawns. + // + + randomclass = M_ParmExists("-randclass"); + + //! + // @vanilla + // + // Take screenshots when F1 is pressed. + // + + ravpic = M_ParmExists("-ravpic"); + + //! + // @category obscure + // @vanilla + // + // Don't allow artifacts to be used when the run key is held down. + // + + artiskip = M_ParmExists("-artiskip"); + + debugmode = M_ParmExists("-debug"); + + //! + // @vanilla + // @category net + // + // Start a deathmatch game. + // + + deathmatch = M_ParmExists("-deathmatch"); + + // currently broken or unused: + cmdfrag = M_ParmExists("-cmdfrag"); + + // Check WAD file command line options + W_ParseCommandLine(); + + //! + // @category obscure + // @vanilla + // @arg + // + // Development option to specify path to level scripts. + // + + p = M_CheckParmWithArgs("-scripts", 1); + + if (p) + { + sc_FileScripts = true; + sc_ScriptsDir = myargv[p+1]; + } + + //! + // @category game + // @arg + // @vanilla + // + // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of + // 0 disables all monsters. + // + + p = M_CheckParmWithArgs("-skill", 1); + + if (p) + { + startskill = myargv[p+1][0] - '1'; + autostart = true; + } + + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp. + // + + p = M_CheckParmWithArgs("-playdemo", 1); + + if (!p) + { + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp, determining the framerate + // of the screen. + // + + p = M_CheckParmWithArgs("-timedemo", 1); + } + + if (p) + { + char *uc_filename; + char file[256]; + + M_StringCopy(file, myargv[p+1], sizeof(file)); + + // With Vanilla Hexen you have to specify the file without + // extension, but make that optional. + uc_filename = strdup(myargv[p + 1]); + M_ForceUppercase(uc_filename); + + if (!M_StringEndsWith(uc_filename, ".LMP")) + { + M_StringConcat(file, ".lmp", sizeof(file)); + } + + free(uc_filename); + + if (W_AddFile(file) != NULL) + { + M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, + sizeof(demolumpname)); + } + else + { + // The file failed to load, but copy the original arg as a + // demo name to make tricks like -playdemo demo1 possible. + M_StringCopy(demolumpname, myargv[p+1], sizeof(demolumpname)); + } + + ST_Message("Playing demo %s.\n", myargv[p+1]); + } + + //! + // @category demo + // + // Record or playback a demo without automatically quitting + // after either level exit or player respawn. + // + + demoextend = M_ParmExists("-demoextend"); + + if (M_ParmExists("-testcontrols")) + { + autostart = true; + testcontrols = true; + } +} + +//========================================================================== +// +// WarpCheck +// +//========================================================================== + +static void WarpCheck(void) +{ + int p; + int map; + + //! + // @category game + // @arg x + // @vanilla + // + // Start a game immediately, warping to MAPx. + // + + p = M_CheckParm("-warp"); + if (p && p < myargc - 1) + { + WarpMap = atoi(myargv[p + 1]); + map = P_TranslateMap(WarpMap); + if (map == -1) + { // Couldn't find real map number + startmap = 1; + ST_Message("-WARP: Invalid map number.\n"); + } + else + { // Found a valid startmap + startmap = map; + autostart = true; + } + } + else + { + WarpMap = 1; + startmap = P_TranslateMap(1); + if (startmap == -1) + { + startmap = 1; + } + } +} + +//========================================================================== +// +// H2_GameLoop +// +//========================================================================== + +void H2_GameLoop(void) +{ + if (M_CheckParm("-debugfile")) + { + char filename[20]; + M_snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer); + debugfile = M_fopen(filename, "w"); + } + I_SetWindowTitle(gamedescription); + I_GraphicsCheckCommandLine(); + I_SetGrabMouseCallback(D_GrabMouseCallback); + I_RegisterWindowIcon(hexen_icon_data, hexen_icon_w, hexen_icon_h); + I_InitGraphics(); + + while (1) + { + // Frame syncronous IO operations + I_StartFrame(); + + // Process one or more tics + // Will run at least one tic + TryRunTics(); + + // Move positional sounds + S_UpdateSounds(players[displayplayer].mo); + + DrawAndBlit(); + } +} + +//========================================================================== +// +// H2_ProcessEvents +// +// Send all the events of the given timestamp down the responder chain. +// +//========================================================================== + +void H2_ProcessEvents(void) +{ + event_t *ev; + + for (;;) + { + ev = D_PopEvent(); + + if (ev == NULL) + { + break; + } + + if (F_Responder(ev)) + { + continue; + } + if (MN_Responder(ev)) + { + continue; + } + G_Responder(ev); + } +} + +//========================================================================== +// +// DrawAndBlit +// +//========================================================================== + +static void DrawAndBlit(void) +{ + // Change the view size if needed + if (setsizeneeded) + { + R_ExecuteSetViewSize(); + } + + // Do buffered drawing + switch (gamestate) + { + case GS_LEVEL: + if (!gametic) + { + break; + } + if (automapactive) + { + AM_Drawer(); + } + else + { + R_RenderPlayerView(&players[displayplayer]); + } + CT_Drawer(); + UpdateState |= I_FULLVIEW; + SB_Drawer(); + break; + case GS_INTERMISSION: + IN_Drawer(); + break; + case GS_FINALE: + F_Drawer(); + break; + case GS_DEMOSCREEN: + PageDrawer(); + break; + } + + if (testcontrols) + { + V_DrawMouseSpeedBox(testcontrols_mousespeed); + } + + if (paused && !MenuActive && !askforquit) + { + if (!netgame) + { + V_DrawPatch(160, viewwindowy + 5, W_CacheLumpName("PAUSED", + PU_CACHE)); + } + else + { + V_DrawPatch(160, 70, W_CacheLumpName("PAUSED", PU_CACHE)); + } + } + + // Draw current message + DrawMessage(); + + // Draw Menu + MN_Drawer(); + + // Send out any new accumulation + NetUpdate(); + + // Flush buffered stuff to screen + I_FinishUpdate(); +} + +//========================================================================== +// +// DrawMessage +// +//========================================================================== + +static void DrawMessage(void) +{ + player_t *player; + + player = &players[consoleplayer]; + if (player->messageTics <= 0) + { // No message + return; + } + if (player->yellowMessage) + { + MN_DrTextAYellow(player->message, + 160 - MN_TextAWidth(player->message) / 2, 1); + } + else + { + MN_DrTextA(player->message, 160 - MN_TextAWidth(player->message) / 2, + 1); + } +} + +//========================================================================== +// +// H2_PageTicker +// +//========================================================================== + +void H2_PageTicker(void) +{ + if (--pagetic < 0) + { + H2_AdvanceDemo(); + } +} + +//========================================================================== +// +// PageDrawer +// +//========================================================================== + +static void PageDrawer(void) +{ + V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE)); + if (demosequence == 1) + { + V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE)); + } + UpdateState |= I_FULLSCRN; +} + +//========================================================================== +// +// H2_AdvanceDemo +// +// Called after each demo or intro demosequence finishes. +// +//========================================================================== + +void H2_AdvanceDemo(void) +{ + advancedemo = true; +} + +//========================================================================== +// +// H2_DoAdvanceDemo +// +//========================================================================== + +void H2_DoAdvanceDemo(void) +{ + players[consoleplayer].playerstate = PST_LIVE; // don't reborn + advancedemo = false; + usergame = false; // can't save/end game here + paused = false; + gameaction = ga_nothing; + demosequence = (demosequence + 1) % 7; + switch (demosequence) + { + case 0: + pagetic = 280; + gamestate = GS_DEMOSCREEN; + pagename = "TITLE"; + S_StartSongName("hexen", true); + break; + case 1: + pagetic = 210; + gamestate = GS_DEMOSCREEN; + pagename = "TITLE"; + break; + case 2: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo("demo1"); + break; + case 3: + pagetic = 200; + gamestate = GS_DEMOSCREEN; + pagename = "CREDIT"; + break; + case 4: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo("demo2"); + break; + case 5: + pagetic = 200; + gamestate = GS_DEMOSCREEN; + pagename = "CREDIT"; + break; + case 6: + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + G_DeferedPlayDemo("demo3"); + break; + } +} + +//========================================================================== +// +// H2_StartTitle +// +//========================================================================== + +void H2_StartTitle(void) +{ + gameaction = ga_nothing; + demosequence = -1; + H2_AdvanceDemo(); +} + +//========================================================================== +// +// CheckRecordFrom +// +// -recordfrom +// +//========================================================================== + +static void CheckRecordFrom(void) +{ + int p; + + //! + // @vanilla + // @category demo + // @arg + // + // Load a game from the given savegame slot and record a demo from + // it. Equivalent to -loadgame -record . + // + p = M_CheckParm("-recordfrom"); + if (!p || p > myargc - 2) + { // Bad args + return; + } + G_LoadGame(atoi(myargv[p + 1])); + G_DoLoadGame(); // Load the gameskill etc info from savegame + G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p + 2]); + + H2_GameLoop(); // Never returns +} + +// haleyjd: removed WATCOMC +/* +void CleanExit(void) +{ + union REGS regs; + + I_ShutdownKeyboard(); + regs.x.eax = 0x3; + int386(0x10, ®s, ®s); + printf("Exited from HEXEN: Beyond Heretic.\n"); + exit(1); +} +*/ + +//========================================================================== +// +// CreateSavePath +// +//========================================================================== + +static void CreateSavePath(void) +{ + M_MakeDirectory(SavePath); +} diff --git a/games/NXDoom/src/hexen/h2def.h b/games/NXDoom/src/hexen/h2def.h new file mode 100644 index 00000000000..2bfdfb513c4 --- /dev/null +++ b/games/NXDoom/src/hexen/h2def.h @@ -0,0 +1,1121 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __H2DEF__ +#define __H2DEF__ +#include +#include +#include +//#include + +#include "st_start.h" +// haleyjd: removed WATCOMC + +// ticcmd: + +#include "d_ticcmd.h" + +// events + +#include "d_event.h" + +// gamemode/mission + +#include "d_mode.h" + +// for fixed_t: + +#include "m_fixed.h" + +// angle definitions: + +#include "tables.h" + +#include "d_loop.h" +#include "net_defs.h" + +#define HEXEN_VERSION 110 +#define HEXEN_VERSION_TEXT "v1.1" + +// if rangecheck is undefined, most parameter validation debugging code +// will not be compiled +#ifndef NORANGECHECKING +#define RANGECHECK +#endif + +// Past distributions +//#ifndef VER_ID +//#define VER_ID "DVL" +//#endif +//#define HEXEN_VERSIONTEXT "ID V1.2" +//#define HEXEN_VERSIONTEXT "RETAIL STORE BETA" // 9/26/95 +//#define HEXEN_VERSIONTEXT "DVL BETA 10 05 95" // Used for GT for testing +//#define HEXEN_VERSIONTEXT "DVL BETA 10 07 95" // Just an update for Romero +//#define HEXEN_VERSIONTEXT "FINAL 1.0 (10 13 95)" // Just an update for Romero +//#ifdef RANGECHECK +//#define HEXEN_VERSIONTEXT "Version 1.1 +R "__DATE__" ("VER_ID")" +//#else +//#define HEXEN_VERSIONTEXT "Version 1.1 "__DATE__" ("VER_ID")" +//#endif +#define HEXEN_VERSIONTEXT ((gamemode == shareware) ? \ + "DEMO 10 16 95" : \ + (gameversion != exe_hexen_1_1r2) ? \ + "VERSION 1.1 MAR 12 1996 (CBI)" : \ + "VERSION 1.1 MAR 22 1996 (BCP)") + +// all exterior data is defined here +#include "xddefs.h" + +// all important printed strings +#include "textdefs.h" + +// header generated by multigen utility +#include "info.h" + +/* +=============================================================================== + + GLOBAL TYPES + +=============================================================================== +*/ + +//#define NUMARTIFCTS 28 +#define MAXPLAYERS 8 + +#define BT_ATTACK 1 +#define BT_USE 2 +#define BT_CHANGE 4 // if true, the next 3 bits hold weapon num +#define BT_WEAPONMASK (8+16+32) +#define BT_WEAPONSHIFT 3 + +#define BT_SPECIAL 128 // game events, not really buttons +#define BTS_SAVEMASK (4+8+16) +#define BTS_SAVESHIFT 2 +#define BT_SPECIALMASK 3 +#define BTS_PAUSE 1 // pause the game +#define BTS_SAVEGAME 2 // save the game at each console +// savegame slot numbers occupy the second byte of buttons + +// The top 3 bits of the artifact field in the ticcmd_t struct are used +// as additional flags +#define AFLAG_MASK 0x3F +#define AFLAG_SUICIDE 0x40 +#define AFLAG_JUMP 0x80 + +typedef enum +{ + GS_LEVEL, + GS_INTERMISSION, + GS_FINALE, + GS_DEMOSCREEN +} gamestate_t; + +typedef enum +{ + ga_nothing, + ga_loadlevel, + ga_initnew, + ga_newgame, + ga_loadgame, + ga_savegame, + ga_playdemo, + ga_completed, + ga_leavemap, + ga_singlereborn, + ga_victory, + ga_worlddone, + ga_screenshot +} gameaction_t; + +typedef enum +{ + wipe_0, + wipe_1, + wipe_2, + wipe_3, + wipe_4, + NUMWIPES, + wipe_random +} wipe_t; + +/* +=============================================================================== + + MAPOBJ DATA + +=============================================================================== +*/ + + +struct thinker_s; + + +// think_t is a function pointer to a routine to handle an actor +typedef void (*think_t)(struct thinker_s *); + +typedef struct thinker_s +{ + struct thinker_s *prev, *next; + think_t function; +} thinker_t; + +struct player_s; + +typedef union +{ + intptr_t i; + struct mobj_s *m; + struct player_s *p; +} specialval_t; + +typedef struct mobj_s +{ + thinker_t thinker; // thinker node + +// info for drawing + fixed_t x, y, z; + struct mobj_s *snext, *sprev; // links in sector (if needed) + angle_t angle; + spritenum_t sprite; // used to find patch_t and flip value + int frame; // might be ord with FF_FULLBRIGHT + +// interaction info + struct mobj_s *bnext, *bprev; // links in blocks (if needed) + struct subsector_s *subsector; + fixed_t floorz, ceilingz; // closest together of contacted secs + fixed_t floorpic; // contacted sec floorpic + fixed_t radius, height; // for movement checking + fixed_t momx, momy, momz; // momentums + int validcount; // if == validcount, already checked + mobjtype_t type; + mobjinfo_t *info; // &mobjinfo[mobj->type] + int tics; // state tic counter + state_t *state; + int damage; // For missiles + int flags; + int flags2; // Heretic flags + specialval_t special1; // Special info + specialval_t special2; // Special info + int health; + int movedir; // 0-7 + int movecount; // when 0, select a new dir + struct mobj_s *target; // thing being chased/attacked (or NULL) + // also the originator for missiles + int reactiontime; // if non 0, don't attack yet + // used by player to freeze a bit after + // teleporting + int threshold; // if > 0, the target will be chased + // no matter what (even if shot) + struct player_s *player; // only valid if type == MT_PLAYER + int lastlook; // player number last looked for + fixed_t floorclip; // value to use for floor clipping + int archiveNum; // Identity during archive + short tid; // thing identifier + byte special; // special + byte args[5]; // special arguments +} mobj_t; + +// each sector has a degenmobj_t in it's center for sound origin purposes +typedef struct +{ + thinker_t thinker; // not used for anything + fixed_t x, y, z; +} degenmobj_t; + +// +// frame flags +// +#define FF_FULLBRIGHT 0x8000 // flag in thing->frame +#define FF_FRAMEMASK 0x7fff + +// --- mobj.flags --- + +#define MF_SPECIAL 1 // call P_SpecialThing when touched +#define MF_SOLID 2 +#define MF_SHOOTABLE 4 +#define MF_NOSECTOR 8 // don't use the sector links + // (invisible but touchable) +#define MF_NOBLOCKMAP 16 // don't use the blocklinks + // (inert but displayable) +#define MF_AMBUSH 32 +#define MF_JUSTHIT 64 // try to attack right back +#define MF_JUSTATTACKED 128 // take at least one step before attacking +#define MF_SPAWNCEILING 256 // hang from ceiling instead of floor +#define MF_NOGRAVITY 512 // don't apply gravity every tic + +// movement flags +#define MF_DROPOFF 0x400 // allow jumps from high places +#define MF_PICKUP 0x800 // for players to pick up items +#define MF_NOCLIP 0x1000 // player cheat +#define MF_SLIDE 0x2000 // keep info about sliding along walls +#define MF_FLOAT 0x4000 // allow moves to any height, no gravity +#define MF_TELEPORT 0x8000 // don't cross lines or look at heights +#define MF_MISSILE 0x10000 // don't hit same species, explode on block + +#define MF_ALTSHADOW 0x20000 // alternate translucent draw +#define MF_SHADOW 0x40000 // use translucent draw (shadow demons / invis) +#define MF_NOBLOOD 0x80000 // don't bleed when shot (use puff) +#define MF_CORPSE 0x100000 // don't stop moving halfway off a step +#define MF_INFLOAT 0x200000 // floating to a height for a move, don't + // auto float to target's height + +#define MF_COUNTKILL 0x400000 // count towards intermission kill total +#define MF_ICECORPSE 0x800000 // a frozen corpse (for blasting) + +#define MF_SKULLFLY 0x1000000 // skull in flight +#define MF_NOTDMATCH 0x2000000 // don't spawn in death match (key cards) + +//#define MF_TRANSLATION 0xc000000 // if 0x4 0x8 or 0xc, use a translation +#define MF_TRANSLATION 0x1c000000 // use a translation table (>>MF_TRANSHIFT) +#define MF_TRANSSHIFT 26 // table for player colormaps + + +// --- mobj.flags2 --- + +#define MF2_LOGRAV 0x00000001 // alternate gravity setting +#define MF2_WINDTHRUST 0x00000002 // gets pushed around by the wind + // specials +#define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor +#define MF2_BLASTED 0x00000008 // missile will pass through ghosts +#define MF2_FLY 0x00000010 // fly mode is active +#define MF2_FLOORCLIP 0x00000020 // if feet are allowed to be clipped +#define MF2_SPAWNFLOAT 0x00000040 // spawn random float z +#define MF2_NOTELEPORT 0x00000080 // does not teleport +#define MF2_RIP 0x00000100 // missile rips through solid + // targets +#define MF2_PUSHABLE 0x00000200 // can be pushed by other moving + // mobjs +#define MF2_SLIDE 0x00000400 // slides against walls +#define MF2_ONMOBJ 0x00000800 // mobj is resting on top of another + // mobj +#define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, + // this flag will allow the mobj to + // pass over/under other mobjs. +#define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs +#define MF2_DROPPED 0x00004000 // dropped by a demon +#define MF2_BOSS 0x00008000 // mobj is a major boss +#define MF2_FIREDAMAGE 0x00010000 // does fire damage +#define MF2_NODMGTHRUST 0x00020000 // does not thrust target when + // damaging +#define MF2_TELESTOMP 0x00040000 // mobj can stomp another +#define MF2_FLOATBOB 0x00080000 // use float bobbing z movement +#define MF2_DONTDRAW 0x00100000 // don't generate a vissprite +#define MF2_IMPACT 0x00200000 // an MF_MISSILE mobj can activate + // SPAC_IMPACT +#define MF2_PUSHWALL 0x00400000 // mobj can push walls +#define MF2_MCROSS 0x00800000 // can activate monster cross lines +#define MF2_PCROSS 0x01000000 // can activate projectile cross lines +#define MF2_CANTLEAVEFLOORPIC 0x02000000 // stay within a certain floor type +#define MF2_NONSHOOTABLE 0x04000000 // mobj is totally non-shootable, + // but still considered solid +#define MF2_INVULNERABLE 0x08000000 // mobj is invulnerable +#define MF2_DORMANT 0x10000000 // thing is dormant +#define MF2_ICEDAMAGE 0x20000000 // does ice damage +#define MF2_SEEKERMISSILE 0x40000000 // is a seeker (for reflection) +#define MF2_REFLECTIVE 0x80000000 // reflects missiles + +//============================================================================= + +// ===== Player Class Types ===== +typedef enum +{ + PCLASS_FIGHTER, + PCLASS_CLERIC, + PCLASS_MAGE, + PCLASS_PIG, + NUMCLASSES +} pclass_t; + +typedef enum +{ + PST_LIVE, // playing + PST_DEAD, // dead on the ground + PST_REBORN // ready to restart +} playerstate_t; + +// psprites are scaled shapes directly on the view screen +// coordinates are given for a 320*200 view screen +typedef enum +{ + ps_weapon, + ps_flash, + NUMPSPRITES +} psprnum_t; + +typedef struct pspdef_s +{ + state_t *state; // a NULL state means not active + int tics; + fixed_t sx, sy; +} pspdef_t; + +/* Old Heretic key type +typedef enum +{ + key_yellow, + key_green, + key_blue, + NUM_KEY_TYPES +} keytype_t; +*/ + +typedef enum +{ + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_A, + KEY_B, + NUM_KEY_TYPES +} keytype_t; + +typedef enum +{ + ARMOR_ARMOR, + ARMOR_SHIELD, + ARMOR_HELMET, + ARMOR_AMULET, + NUMARMOR +} armortype_t; + +typedef enum +{ + WP_FIRST, + WP_SECOND, + WP_THIRD, + WP_FOURTH, + NUMWEAPONS, + WP_NOCHANGE +} weapontype_t; + +typedef enum +{ + MANA_1, + MANA_2, + NUMMANA, + MANA_BOTH, + MANA_NONE +} manatype_t; + +#define MAX_MANA 200 + +#define WPIECE1 1 +#define WPIECE2 2 +#define WPIECE3 4 + +typedef struct +{ + manatype_t mana; + int upstate; + int downstate; + int readystate; + int atkstate; + int holdatkstate; + int flashstate; +} weaponinfo_t; + +extern weaponinfo_t WeaponInfo[NUMWEAPONS][NUMCLASSES]; + +typedef enum +{ + arti_none, + arti_invulnerability, + arti_health, + arti_superhealth, + arti_healingradius, + arti_summon, + arti_torch, + arti_egg, + arti_fly, + arti_blastradius, + arti_poisonbag, + arti_teleportother, + arti_speed, + arti_boostmana, + arti_boostarmor, + arti_teleport, + // Puzzle artifacts + arti_firstpuzzitem, + arti_puzzskull = arti_firstpuzzitem, + arti_puzzgembig, + arti_puzzgemred, + arti_puzzgemgreen1, + arti_puzzgemgreen2, + arti_puzzgemblue1, + arti_puzzgemblue2, + arti_puzzbook1, + arti_puzzbook2, + arti_puzzskull2, + arti_puzzfweapon, + arti_puzzcweapon, + arti_puzzmweapon, + arti_puzzgear1, + arti_puzzgear2, + arti_puzzgear3, + arti_puzzgear4, + NUMARTIFACTS +} artitype_t; + +typedef enum +{ + pw_None, + pw_invulnerability, + pw_allmap, + pw_infrared, + pw_flight, + pw_shield, + pw_health2, + pw_speed, + pw_minotaur, + NUMPOWERS +} powertype_t; + +#define INVULNTICS (30*35) +#define INVISTICS (60*35) +#define INFRATICS (120*35) +#define IRONTICS (60*35) +#define WPNLEV2TICS (40*35) +#define FLIGHTTICS (60*35) +#define SPEEDTICS (45*35) +#define MORPHTICS (40*35) +#define MAULATORTICS (25*35) + +#define MESSAGETICS (4*35) +#define BLINKTHRESHOLD (4*35) + +#define NUMINVENTORYSLOTS NUMARTIFACTS + +typedef struct +{ + int type; + int count; +} inventory_t; + +/* +================ += += player_t += +================ +*/ + +typedef struct player_s +{ + mobj_t *mo; + playerstate_t playerstate; + ticcmd_t cmd; + + pclass_t class; // player class type + + fixed_t viewz; // focal origin above r.z + fixed_t viewheight; // base height above floor for viewz + fixed_t deltaviewheight; // squat speed + fixed_t bob; // bounded/scaled total momentum + + int flyheight; + int lookdir; + boolean centering; + int health; // only used between levels, mo->health + // is used during levels + int armorpoints[NUMARMOR]; + + inventory_t inventory[NUMINVENTORYSLOTS]; + artitype_t readyArtifact; + int artifactCount; + int inventorySlotNum; + int powers[NUMPOWERS]; + int keys; + int pieces; // Fourth Weapon pieces + signed int frags[MAXPLAYERS]; // kills of other players + weapontype_t readyweapon; + weapontype_t pendingweapon; // wp_nochange if not changing + boolean weaponowned[NUMWEAPONS]; + int mana[NUMMANA]; + int attackdown, usedown; // true if button down last tic + int cheats; // bit flags + + int refire; // refired shots are less accurate + + int killcount, itemcount, secretcount; // for intermission + char message[80]; // hint messages + int messageTics; // counter for showing messages + short ultimateMessage; + short yellowMessage; + int damagecount, bonuscount; // for screen flashing + int poisoncount; // screen flash for poison damage + mobj_t *poisoner; // NULL for non-player mobjs + mobj_t *attacker; // who did damage (NULL for floors) + int extralight; // so gun flashes light up areas + int fixedcolormap; // can be set to REDCOLORMAP, etc + int colormap; // 0-3 for which color to draw player + pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) + int morphTics; // player is a pig if > 0 + unsigned int jumpTics; // delay the next jump for a moment + unsigned int worldTimer; // total time the player's been playing +} player_t; + +#define CF_NOCLIP 1 +#define CF_GODMODE 2 +#define CF_NOMOMENTUM 4 // not really a cheat, just a debug aid + +#define SBARHEIGHT 39 // status bar height at bottom of screen + +void NET_SendFrags(player_t * player); + +/* +=============================================================================== + + GLOBAL VARIABLES + +=============================================================================== +*/ + +#define TELEFOGHEIGHT (32*FRACUNIT) + +extern GameMode_t gamemode; +extern GameVersion_t gameversion; + +extern gameaction_t gameaction; + +extern boolean paused; + +extern boolean DevMaps; // true = map development mode +extern char *DevMapsDir; // development maps directory + +extern boolean nomonsters; // checkparm of -nomonsters + +extern boolean respawnparm; // checkparm of -respawn + +extern boolean randomclass; // checkparm of -randclass + +extern boolean debugmode; // checkparm of -debug + +extern boolean usergame; // ok to save / end game + +extern boolean ravpic; // checkparm of -ravpic + +extern boolean altpal; // checkparm to use an alternate palette routine + +extern boolean cdrom; // true if cd-rom mode active ("-cdrom") + +extern boolean viewactive; + +extern boolean deathmatch; // only if started as net death + +extern boolean netgame; // only true if >1 player + +extern boolean cmdfrag; // true if a CMD_FRAG packet should be sent out every + // kill + +extern boolean playeringame[MAXPLAYERS]; +extern pclass_t PlayerClass[MAXPLAYERS]; + +extern int consoleplayer; // player taking events and displaying + +extern int displayplayer; + +extern int viewangleoffset; // ANG90 = left side, ANG270 = right + +extern player_t players[MAXPLAYERS]; + +extern boolean DebugSound; // debug flag for displaying sound info + +extern boolean demorecording; +extern boolean demoplayback; +extern boolean demoextend; // allow demos to persist through exit/respawn +extern int maxzone; // Maximum chunk allocated for zone heap + +// Truncate angleturn in ticcmds to nearest 256. +// Used when recording Vanilla demos in netgames. +extern boolean lowres_turn; + +extern int Sky1Texture; +extern int Sky2Texture; + +extern gamestate_t gamestate; +extern skill_t gameskill; +//extern boolean respawnmonsters; +extern int gameepisode; +extern int gamemap; +extern int prevmap; +extern int levelstarttic; // gametic at level start +extern int leveltime; // tics in game play for par + +extern ticcmd_t *netcmds; + +#define MAXDEATHMATCHSTARTS 16 +extern mapthing_t *deathmatch_p; +extern mapthing_t deathmatchstarts[MAXDEATHMATCHSTARTS]; + +// Position indicator for cooperative net-play reborn +extern int RebornPosition; + +#define MAX_PLAYER_STARTS 8 +extern mapthing_t playerstarts[MAX_PLAYER_STARTS][MAXPLAYERS]; +extern int maxplayers; + +extern int mouseSensitivity; + +extern boolean precache; // if true, load all graphics at level load + +extern byte *screen; // off screen work buffer, from V_video.c + +extern boolean singledemo; // quit after playing a demo from cmdline + +extern int bodyqueslot; +extern skill_t startskill; +extern int startepisode; +extern int startmap; +extern boolean autostart; +extern boolean advancedemo; + +extern boolean testcontrols; +extern int testcontrols_mousespeed; + +extern int vanilla_savegame_limit; +extern int vanilla_demo_limit; + +extern boolean usearti; + + +/* +=============================================================================== + + GLOBAL FUNCTIONS + +=============================================================================== +*/ + +#include "w_wad.h" +#include "z_zone.h" + +//---------- +//BASE LEVEL +//---------- +void H2_Main(void); +// not a globally visible function, just included for source reference +// calls all startup code +// parses command line options +// if not overrided, calls N_AdvanceDemo + +void H2_GameLoop(void); +// not a globally visible function, just included for source reference +// called by H2_Main, never exits +// manages timing and IO +// calls all ?_Responder, ?_Ticker, and ?_Drawer functions +// calls I_GetTime, I_StartFrame, and I_StartTic + +void H2_StartTitle(void); + + +extern boolean artiskip; + + +//--------- +//SYSTEM IO +//--------- +byte *I_AllocLow(int length); +// allocates from low memory under dos, just mallocs under unix + +// haleyjd: was WATCOMC, again preserved for historical interest as in Heretic +#if 0 +extern boolean useexterndriver; + +#define EBT_FIRE 1 +#define EBT_OPENDOOR 2 +#define EBT_SPEED 4 +#define EBT_STRAFE 8 +#define EBT_MAP 0x10 +#define EBT_INVENTORYLEFT 0x20 +#define EBT_INVENTORYRIGHT 0x40 +#define EBT_USEARTIFACT 0x80 +#define EBT_FLYDROP 0x100 +#define EBT_CENTERVIEW 0x200 +#define EBT_PAUSE 0x400 +#define EBT_WEAPONCYCLE 0x800 +#define EBT_JUMP 0x1000 + +typedef struct +{ + short vector; // Interrupt vector + + signed char moveForward; // forward/backward (maxes at 50) + signed char moveSideways; // strafe (maxes at 24) + short angleTurn; // turning speed (640 [slow] 1280 [fast]) + short angleHead; // head angle (+2080 [left] : 0 [center] : -2048 [right]) + signed char pitch; // look up/down (-110 : +90) + signed char flyDirection; // flyheight (+1/-1) + unsigned short buttons; // EBT_* flags +} externdata_t; +#endif + +//---- +//GAME +//---- + + +#define NUMKEYS 256 + + +void G_DeathMatchSpawnPlayer(int playernum); + +void G_InitNew(skill_t skill, int episode, int map); + +void G_DeferedInitNew(skill_t skill, int episode, int map); +// can be called by the startup code or M_Responder +// a normal game starts at map 1, but a warp test can start elsewhere + +void G_DeferredNewGame(skill_t skill); + +void G_DeferedPlayDemo(const char *demo); + +void G_LoadGame(int slot); +// can be called by the startup code or M_Responder +// calls P_SetupLevel or W_EnterWorld +void G_DoLoadGame(void); + +void G_SaveGame(int slot, char *description); +// called by M_Responder + +void H2_ProcessEvents(void); + +void H2_DoAdvanceDemo(void); + +boolean G_CheckDemoStatus(void); + +void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, + const char *name); +// only called by startup code + +void G_PlayDemo(char *name); +void G_TimeDemo(char *name); + +void G_TeleportNewMap(int map, int position); + +void G_Completed(int map, int position); +//void G_ExitLevel (void); +//void G_SecretExitLevel (void); + +void G_StartNewGame(skill_t skill); +void G_StartNewInit(void); + +void G_WorldDone(void); + +void G_BuildTiccmd(ticcmd_t *cmd, int maketic); +void G_Ticker(void); +boolean G_Responder(event_t * ev); + +void G_ScreenShot(void); + + +extern int LeaveMap; +extern boolean gamekeydown[NUMKEYS]; + + +//------- +//SV_SAVE +//------- + +#define HXS_VERSION_TEXT "HXS Ver 2.37" +#define HXS_VERSION_TEXT_LENGTH 16 +#define HXS_DESCRIPTION_LENGTH 24 + +extern char *SavePath; + +void SV_SaveGame(int slot, const char *description); +void SV_SaveMap(boolean savePlayers); +void SV_LoadGame(int slot); +void SV_MapTeleport(int map, int position); +void SV_LoadMap(void); +void SV_InitBaseSlot(void); +void SV_UpdateRebornSlot(void); +void SV_ClearRebornSlot(void); +boolean SV_RebornSlotAvailable(void); +int SV_GetRebornSlot(void); + +//----- +//PLAY +//----- + +extern lumpinfo_t *maplumpinfo; + +void P_Ticker(void); +// called by C_Ticker +// can call G_PlayerExited +// carries out all thinking of monsters and players + +void P_SetupLevel(int episode, int map, int playermask, skill_t skill); +// called by W_Ticker + +void P_Init(void); +// called by startup code + +int P_GetMapCluster(int map); +int P_TranslateMap(int map); +int P_GetMapCDTrack(int map); +int P_GetMapWarpTrans(int map); +int P_GetMapNextMap(int map); +int P_GetMapSky1Texture(int map); +int P_GetMapSky2Texture(int map); +char *P_GetMapName(int map); +fixed_t P_GetMapSky1ScrollDelta(int map); +fixed_t P_GetMapSky2ScrollDelta(int map); +boolean P_GetMapDoubleSky(int map); +boolean P_GetMapLightning(int map); +boolean P_GetMapFadeTable(int map); +char *P_GetMapSongLump(int map); +void P_PutMapSongLump(int map, char *lumpName); +int P_GetCDStartTrack(void); +int P_GetCDEnd1Track(void); +int P_GetCDEnd2Track(void); +int P_GetCDEnd3Track(void); +int P_GetCDIntermissionTrack(void); +int P_GetCDTitleTrack(void); + +//------- +//REFRESH +//------- + +extern boolean setsizeneeded; + +extern boolean BorderNeedRefresh; +extern boolean BorderTopRefresh; + +extern int UpdateState; +// define the different areas for the dirty map +#define I_NOUPDATE 0 +#define I_FULLVIEW 1 +#define I_STATBAR 2 +#define I_MESSAGES 4 +#define I_FULLSCRN 8 + +void R_RenderPlayerView(player_t * player); +// called by G_Drawer + +void R_Init(void); +// called by startup code + +void R_DrawViewBorder(void); +void R_DrawTopBorder(void); +// if the view size is not full screen, draws a border around it + +void R_SetViewSize(int blocks, int detail); +// called by M_Responder + +int R_FlatNumForName(const char *name); + +int R_TextureNumForName(const char *name); +int R_CheckTextureNumForName(const char *name); +// called by P_Ticker for switches and animations +// returns the texture number for the texture name + + +//---- +//MISC +//---- +extern int localQuakeHappening[MAXPLAYERS]; + +int M_DrawText(int x, int y, boolean direct, char *string); + +//------------------------------ +// SC_man.c +//------------------------------ + +void SC_Open(const char *name); +void SC_OpenLump(const char *name); +void SC_OpenFile(const char *name); +void SC_Close(void); +boolean SC_GetString(void); +void SC_MustGetString(void); +void SC_MustGetStringName(char *name); +boolean SC_GetNumber(void); +void SC_MustGetNumber(void); +void SC_UnGet(void); +//boolean SC_Check(void); +boolean SC_Compare(const char *text); +int SC_MatchString(const char **strings); +int SC_MustMatchString(const char **strings); +void SC_ScriptError(const char *message); + +extern char *sc_String; +extern int sc_Number; +extern int sc_Line; +extern boolean sc_End; +extern boolean sc_Crossed; +extern boolean sc_FileScripts; +extern const char *sc_ScriptsDir; + +//------------------------------ +// SN_sonix.c +//------------------------------ + +enum +{ + SEQ_PLATFORM, + SEQ_PLATFORM_HEAVY, // same script as a normal platform + SEQ_PLATFORM_METAL, + SEQ_PLATFORM_CREAK, // same script as a normal platform + SEQ_PLATFORM_SILENCE, + SEQ_PLATFORM_LAVA, + SEQ_PLATFORM_WATER, + SEQ_PLATFORM_ICE, + SEQ_PLATFORM_EARTH, + SEQ_PLATFORM_METAL2, + SEQ_DOOR_STONE, + SEQ_DOOR_HEAVY, + SEQ_DOOR_METAL, + SEQ_DOOR_CREAK, + SEQ_DOOR_SILENCE, + SEQ_DOOR_LAVA, + SEQ_DOOR_WATER, + SEQ_DOOR_ICE, + SEQ_DOOR_EARTH, + SEQ_DOOR_METAL2, + SEQ_ESOUND_WIND, + SEQ_NUMSEQ +}; + +typedef enum +{ + SEQTYPE_STONE, + SEQTYPE_HEAVY, + SEQTYPE_METAL, + SEQTYPE_CREAK, + SEQTYPE_SILENCE, + SEQTYPE_LAVA, + SEQTYPE_WATER, + SEQTYPE_ICE, + SEQTYPE_EARTH, + SEQTYPE_METAL2, + SEQTYPE_NUMSEQ +} seqtype_t; + +void SN_InitSequenceScript(void); +void SN_StartSequence(mobj_t * mobj, int sequence); +void SN_StartSequenceName(mobj_t * mobj, char *name); +void SN_StopSequence(mobj_t * mobj); +void SN_UpdateActiveSequences(void); +void SN_StopAllSequences(void); +int SN_GetSequenceOffset(int sequence, int *sequencePtr); +void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume, + int currentSoundID); + + +typedef struct seqnode_s seqnode_t; +struct seqnode_s +{ + int *sequencePtr; + int sequence; + mobj_t *mobj; + int currentSoundID; + int delayTics; + int volume; + int stopSound; + seqnode_t *prev; + seqnode_t *next; +}; + +extern int ActiveSequences; +extern seqnode_t *SequenceListHead; + +//---------------------- +// Interlude (IN_lude.c) +//---------------------- + +#define MAX_INTRMSN_MESSAGE_SIZE 1024 + +extern boolean intermission; +extern char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE]; + +void IN_Start(void); +void IN_Ticker(void); +void IN_Drawer(void); + +//---------------------- +// Chat mode (CT_chat.c) +//---------------------- + +void CT_Init(void); +void CT_Drawer(void); +boolean CT_Responder(event_t * ev); +void CT_Ticker(void); +char CT_dequeueChatChar(void); + +extern boolean chatmodeon; + +//-------------------- +// Finale (F_finale.c) +//-------------------- + +void F_Drawer(void); +void F_Ticker(void); +void F_StartFinale(void); + +//---------------------- +// STATUS BAR (SB_bar.c) +//---------------------- + +extern int inv_ptr; +extern int curpos; +extern boolean inventory; + + +void SB_Init(void); +void SB_SetClassData(void); +boolean SB_Responder(event_t * event); +void SB_Ticker(void); +void SB_Drawer(void); +void Draw_TeleportIcon(void); +void Draw_SaveIcon(void); +void Draw_LoadIcon(void); + +//----------------- +// MENU (MN_menu.c) +//----------------- + +void MN_Init(void); +void MN_ActivateMenu(void); +void MN_DeactivateMenu(void); +boolean MN_Responder(event_t * event); +void MN_Ticker(void); +void MN_Drawer(void); +void MN_DrTextA(const char *text, int x, int y); +void MN_DrTextAYellow(const char *text, int x, int y); +int MN_TextAWidth(const char *text); +void MN_DrTextB(const char *text, int x, int y); +int MN_TextBWidth(const char *text); + +extern int messageson; +extern boolean MenuActive; +extern boolean askforquit; +extern boolean mn_SuicideConsole; +extern int detailLevel; + + +#include "sounds.h" + +#include "p_action.h" + + +#endif // __H2DEF__ diff --git a/games/NXDoom/src/hexen/hexen_icon.c b/games/NXDoom/src/hexen/hexen_icon.c new file mode 100644 index 00000000000..ae1082596a0 --- /dev/null +++ b/games/NXDoom/src/hexen/hexen_icon.c @@ -0,0 +1,2736 @@ +static int hexen_icon_w = 128; +static int hexen_icon_h = 128; + +static const unsigned int hexen_icon_data[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, + 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, + 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, + 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, + 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, + 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, + 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, + 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, + 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, + 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, + 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, + 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, + 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, + 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, + 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, + 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, + 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, + 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, + 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, + 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, + 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, + 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, + 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, + 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, + 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, + 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, + 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, + 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, + 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, + 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, + 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, + 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, + 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, + 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, + 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, + 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, + 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, + 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, + 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, + 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, + 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, + 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, + 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, + 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, + 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, + 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, + 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, + 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x93756aff, 0x917469ff, 0x99796eff, 0xa07b70ff, + 0xa07b70ff, 0xa07b70ff, 0xa07b70ff, 0xa07b70ff, 0xa07b70ff, 0xa8887eff, + 0xb9a39dff, 0xb8a39cff, 0xb8a39cff, 0xb7a29bff, 0xb7a29bff, 0xb6a19aff, + 0xb5a099ff, 0xb5a099ff, 0xb49f98ff, 0xa78980ff, 0x9e7a6eff, 0x9d7a6eff, + 0x9d7a6eff, 0x9d7a6eff, 0x9b796dff, 0x99776bff, 0x977469ff, 0x957267ff, + 0x957368ff, 0xa18982ff, 0xa38e88ff, 0xa18d86ff, 0xa08c85ff, 0x9e8983ff, + 0x9c8781ff, 0x9a867fff, 0x99847dff, 0x97827bff, 0x917c74ff, 0x7e5d51ff, + 0x7c5b4fff, 0x7b594eff, 0x78574cff, 0x76554aff, 0x745348ff, 0x735246ff, + 0x715044ff, 0x6f4e42ff, 0x775c52ff, 0x816e67ff, 0x7f6c65ff, 0x7e6b63ff, + 0x7c6861ff, 0x7a6760ff, 0x79665eff, 0x76635cff, 0x74615aff, 0x736059ff, + 0x61443bff, 0x57382dff, 0x55362cff, 0x583a30ff, 0x5a3d36ff, 0x5d3f3cff, + 0x5f4141ff, 0x5f4447ff, 0x5f454bff, 0x674e55ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, + 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, + 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, + 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, + 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, + 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, + 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, + 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, + 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, + 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, + 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, + 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, + 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, + 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, + 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, + 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, + 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, + 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, + 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, + 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, + 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, + 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc69e94ff, 0xc9a49bff, + 0xc8a39aff, 0xc7a39aff, 0xc6a198ff, 0xc5a198ff, 0xc4a097ff, 0xc4a096ff, + 0xc29f95ff, 0xbd948aff, 0xb07c6eff, 0xb07b6eff, 0xaf7b6dff, 0xae7b6dff, + 0xae7a6dff, 0xad7a6cff, 0xad7a6cff, 0xac7a6cff, 0xac7a6cff, 0xb38a80ff, + 0xb7978eff, 0xb6958cff, 0xb6958cff, 0xb5948bff, 0xb29289ff, 0xb19188ff, + 0xaf8f86ff, 0xad8d85ff, 0xab8c83ff, 0x9e7164ff, 0x9a6c5fff, 0x986a5dff, + 0x97695bff, 0x946759ff, 0x926558ff, 0x906356ff, 0x8e6155ff, 0x8b5f52ff, + 0x8d6458ff, 0x96786fff, 0x94776eff, 0x91756cff, 0x90736bff, 0x8e7269ff, + 0x8c7068ff, 0x8a6e66ff, 0x896d64ff, 0x866b62ff, 0x7d5d52ff, 0x734a3dff, + 0x70483bff, 0x6e473aff, 0x6c4438ff, 0x6b4337ff, 0x684134ff, 0x664033ff, + 0x643e31ff, 0x623c2fff, 0x6b4f45ff, 0x6f564eff, 0x6d544cff, 0x6e564fff, + 0x6e5652ff, 0x6e5753ff, 0x6f5857ff, 0x6f5958ff, 0x705a5cff, 0x705b5eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x903d27ff, 0x903d28ff, 0x8f3d28ff, 0x8e3c27ff, 0x8d3c27ff, 0x8c3b27ff, + 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, + 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, + 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, + 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, + 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, + 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, + 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, + 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, + 0x572311ff, 0x572310ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8f3d27ff, 0x8f3d28ff, 0x8e3c27ff, 0x8d3c27ff, + 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, + 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, + 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, + 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, + 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, + 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, + 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, + 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, + 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e3d27ff, 0x8e3c27ff, + 0x8d3c27ff, 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, + 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, + 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, + 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, + 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, + 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, + 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, + 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, + 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, + 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8d3c26ff, 0x8d3c27ff, 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, + 0x893a25ff, 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, + 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, + 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, + 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, + 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, + 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, + 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, + 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, + 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, + 0x552210ff, 0x54220fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x8c3c26ff, 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, + 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, + 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, + 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, + 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, + 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, + 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, + 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, + 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, + 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, + 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8b3b26ff, 0x8b3b26ff, + 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, 0x863924ff, + 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, + 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, + 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, + 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, + 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, + 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, + 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, + 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, + 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8a3b25ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, + 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, + 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, + 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, + 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, + 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, + 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, + 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, + 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, + 0x52210fff, 0x51200eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x893b25ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, + 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, + 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, + 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, + 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, + 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, + 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, + 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, + 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, + 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x893a25ff, 0x893a25ff, + 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, + 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, + 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, + 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, + 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, + 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, + 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, + 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, + 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, + 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x883a24ff, 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, + 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x97361fff, + 0xe93819ff, 0xe53619ff, 0x92341fff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, + 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, + 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, + 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, + 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, + 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x852112ff, 0xd31710ff, 0xea1310ff, + 0xcc150fff, 0x752110ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, + 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, + 0x50200eff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x873924ff, 0x873924ff, 0x863924ff, 0x853824ff, + 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, + 0x7f3521ff, 0xcc371cff, 0xfe3718ff, 0xfe3617ff, 0xf23518ff, 0x91341eff, + 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, + 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, + 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, + 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, + 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xee0f0eff, 0x641e10ff, 0x572310ff, + 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, + 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x863923ff, 0x863924ff, + 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, + 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0xae361eff, 0xfe3617ff, 0xfe3517ff, + 0xfe3417ff, 0xf23318ff, 0x8f331eff, 0x78321eff, 0x77321eff, 0x77311eff, + 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, + 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, + 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, + 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, + 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0x9d1310ff, 0x501f10ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, + 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x853923ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, + 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, + 0xbd351cff, 0xfe3417ff, 0xfe3317ff, 0xfe3217ff, 0xf23217ff, 0x8d321dff, + 0xa8311bff, 0xd02f19ff, 0x9a311bff, 0x74301dff, 0x73301cff, 0x722f1cff, + 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, + 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, + 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0xf70e11ff, 0xaf1211ff, 0x40190fff, 0x4e1f0fff, 0x53210fff, + 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, + 0x4d1e0cff, 0x4d1e0cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x843823ff, 0x843823ff, 0x843723ff, 0x833723ff, + 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, + 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0xbc331bff, 0xfe3217ff, 0xfe3216ff, + 0xfd3116ff, 0xf23016ff, 0xfc2f16ff, 0xfd2e15ff, 0xfb2d15ff, 0xa02e1aff, + 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, + 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, + 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0x811411ff, 0x3f180eff, + 0x40180fff, 0x4d1e0fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, + 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4d1e0cff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x833822ff, 0x843723ff, + 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, + 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, + 0xbb321aff, 0xfd3116ff, 0xfd3016ff, 0xfd2f16ff, 0xfd2e15ff, 0xfd2d15ff, + 0xfd2c15ff, 0xfb2b15ff, 0x9f2d19ff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, + 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, + 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, + 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc41013ff, + 0x41180eff, 0x3f180eff, 0x3e180eff, 0x3f180eff, 0x4c1e0eff, 0x50200eff, + 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1d0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x833722ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, + 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7c331fff, + 0xaa321cff, 0xa4321bff, 0x78321eff, 0xba301aff, 0xfd2f16ff, 0xfd2e15ff, + 0xfd2d15ff, 0xfd2c15ff, 0xfd2b15ff, 0xfd2a15ff, 0xfa2914ff, 0x9e2c19ff, + 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, + 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, + 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, + 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, + 0x3f180eff, 0x4a1d0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4b1d0dff, 0x4c1d0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x823722ff, 0x823722ff, 0x813622ff, 0x803622ff, + 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, + 0x7a331fff, 0xb9331bff, 0xfe3216ff, 0xfd3116ff, 0x9c2b18ff, 0x76311dff, + 0xb92f19ff, 0xfd2d15ff, 0xfd2c15ff, 0xfd2b15ff, 0xfd2a15ff, 0xfc2914ff, + 0xfc2814ff, 0xf72713ff, 0x742717ff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, + 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, + 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, + 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, + 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3f180eff, 0x491c0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4b1d0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x813721ff, 0x813622ff, + 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, + 0x7b331fff, 0x7a331fff, 0x79331fff, 0xc5321aff, 0xfd3116ff, 0xfd3016ff, + 0xa02615ff, 0x5c2617ff, 0x74301dff, 0xb82e19ff, 0xfd2b15ff, 0xfd2a15ff, + 0xfc2914ff, 0xfc2814ff, 0xfc2714ff, 0xfc2614ff, 0x691d12ff, 0x602717ff, + 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, + 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, + 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, + 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3e180dff, 0x481c0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4b1c0eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x803621ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, + 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x84321dff, + 0xc12b16ff, 0xb72914ff, 0x531f13ff, 0x491d13ff, 0x5b2517ff, 0x722f1cff, + 0xb72c18ff, 0xfc2914ff, 0xfc2814ff, 0xfc2714ff, 0xfc2614ff, 0xb32112ff, + 0x441c11ff, 0x441b11ff, 0x5e2617ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, + 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, + 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x481b0dff, 0x4a1d0dff, + 0x4a1c0eff, 0x4a1c0eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x7f3621ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, + 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, + 0x77321eff, 0x77311eff, 0x712f1cff, 0x512115ff, 0x491d13ff, 0x481d13ff, + 0x481d13ff, 0x592416ff, 0x712f1bff, 0xb62b17ff, 0xfc2714ff, 0xfc2614ff, + 0xfc2513ff, 0xec2312ff, 0x621c11ff, 0x431b11ff, 0x431b10ff, 0x5c2516ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, + 0x5e2613ff, 0x932011ff, 0xf7120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xca1113ff, 0x47180eff, + 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d180eff, 0x471a0eff, 0x491c0eff, 0x4a1c0eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7f3520ff, 0x7e3521ff, + 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, + 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x6f2e1cff, + 0x502114ff, 0x481d13ff, 0x591e12ff, 0xa92313ff, 0x9c2515ff, 0x702e1aff, + 0xb52a17ff, 0xfc2513ff, 0xfc2413ff, 0xfc2313ff, 0xeb2113ff, 0x611c10ff, + 0x421a10ff, 0x421b10ff, 0x5a2415ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, + 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, + 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, + 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3e170fff, 0x461a0eff, 0x491b0fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x7e3520ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, + 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, + 0x74301dff, 0x73301cff, 0x6e2d1bff, 0x4e2014ff, 0xc22514ff, 0xfc2814ff, + 0xfc2714ff, 0xb82615ff, 0x6e2d1aff, 0xb42816ff, 0xfc2313ff, 0xfc2213ff, + 0xfb2112ff, 0xea1f11ff, 0x601b10ff, 0x411a10ff, 0x411a10ff, 0x582414ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, + 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, + 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, + 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3e1710ff, 0x461a0fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x7d3520ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, + 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, + 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x6c2d1aff, + 0xc32514ff, 0xfc2714ff, 0xfc2614ff, 0xfc2513ff, 0xb82313ff, 0x6c2c19ff, + 0xb32716ff, 0xfb2112ff, 0xfb2012ff, 0xfb1f12ff, 0xea1d11ff, 0x5e1b10ff, + 0x401a0fff, 0x401a0fff, 0x592414ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x612714ff, 0xa02013ff, 0xe41711ff, 0xf9140fff, 0xfa130fff, 0xf9120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, + 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, + 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, + 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x401710ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7d341fff, 0x7c3420ff, + 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, + 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, + 0x712f1bff, 0x702e1bff, 0x7b2b18ff, 0xe42514ff, 0xfc2513ff, 0xfc2413ff, + 0xfc2313ff, 0xb72213ff, 0x6b2c18ff, 0xb22515ff, 0xfb1f12ff, 0xfb1e12ff, + 0xfb1d12ff, 0xea1b10ff, 0x5e1910ff, 0x3f190fff, 0x3f190fff, 0x562213ff, + 0x612815ff, 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, + 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, + 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3e170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3f1611ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x7c341fff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, + 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, + 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x7a2a18ff, + 0xe42312ff, 0xfc2313ff, 0xfc2213ff, 0xfb2112ff, 0x9b2113ff, 0x682b18ff, + 0xb12414ff, 0xfb1d12ff, 0xfb1c11ff, 0xfb1b11ff, 0xea1a10ff, 0x5e190fff, + 0x3e190eff, 0x3e190fff, 0x552112ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, + 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, + 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3e170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3f1611ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x7b331eff, 0x7a331fff, 0x79331fff, 0x78321eff, + 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, + 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, + 0x6d2d1aff, 0x6c2d19ff, 0x782917ff, 0xe42112ff, 0xfb2112ff, 0xfb2012ff, + 0xb11d11ff, 0x522013ff, 0x662a17ff, 0xb02314ff, 0xfb1b11ff, 0xfb1a11ff, + 0xfa1911ff, 0xeb1810ff, 0xc71810ff, 0xc81610ff, 0xd41610ff, 0xfa1410ff, + 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, + 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3f1711ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7a331eff, 0x79331fff, + 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, + 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, + 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x772916ff, + 0xc61f12ff, 0xcb1e11ff, 0x591b10ff, 0x441a10ff, 0x5f1f11ff, 0x642916ff, + 0xb02114ff, 0xfa1911ff, 0xfa1810ff, 0xfa1710ff, 0xfa1610ff, 0xfa1510ff, + 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, + 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, + 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3f1712ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x79331eff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, + 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, + 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, + 0x6a2c18ff, 0x692b18ff, 0x642917ff, 0x471c11ff, 0x4d1a10ff, 0xe21c11ff, + 0xfb1b11ff, 0xb11d12ff, 0x642815ff, 0xba1f12ff, 0xfa1710ff, 0xfa1610ff, + 0xfa1510ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, + 0xda0f13ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, + 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3f1712ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x78321dff, 0x77321eff, 0x77311eff, 0x76311dff, + 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, + 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, + 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x622816ff, + 0x791c10ff, 0xfb1b11ff, 0xfb1a11ff, 0xfa1911ff, 0xbf1b10ff, 0xd41b11ff, + 0xfa1610ff, 0xfa1510ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, + 0xf60e12ff, 0xf50e14ff, 0xf20e15ff, 0x681510ff, 0x3e180eff, 0x3e180eff, + 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, + 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3f1712ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x77321dff, 0x77311eff, + 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, + 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, + 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x692615ff, 0xe21a11ff, 0xfa1911ff, 0xfa1810ff, + 0xfa1710ff, 0xfa1610ff, 0xfa1510ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, + 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xa91214ff, + 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3f1613ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x77311dff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, + 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, + 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x702514ff, + 0xe21910ff, 0xfa1710ff, 0xfa1610ff, 0xfa1510ff, 0xfa1410ff, 0xfa140fff, + 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, + 0xf20e18ff, 0xaf1215ff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1513ff, 0x3e1613ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x76311cff, 0x75311dff, 0x74301dff, 0x73301cff, + 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, + 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x6e2514ff, 0xe21710ff, 0xfa1510ff, 0xfa1410ff, + 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, + 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, 0x781511ff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3e1714ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x75311cff, 0x74301dff, + 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, + 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, + 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xc11b11ff, + 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, + 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, 0xae1215ff, 0x3e180eff, + 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3e1615ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x74301cff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, + 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, + 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, + 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, + 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, 0xb31116ff, + 0x41180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3f1614ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x73301bff, 0x722f1cff, 0x712f1bff, 0x712f1bff, + 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, + 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, + 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, + 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, + 0xb31116ff, 0x41180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, + 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3e1615ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x722f1bff, 0x712f1bff, + 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, + 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, + 0x612815ff, 0x612714ff, 0xbc1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, + 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, + 0xf10e19ff, 0xec0e19ff, 0x5d1611ff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, + 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3f1515ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x712f1aff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, + 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, + 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, + 0xf20e18ff, 0xf10e19ff, 0xf00e1aff, 0xef0e1cff, 0xde0f1bff, 0x5c1610ff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, + 0x3d1415ff, 0x3e1615ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x712f1aff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, + 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xbc1d12ff, 0xfa1410ff, + 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0xc01110ff, 0xec0e12ff, 0xf50e14ff, 0xf40e15ff, + 0xf30e16ff, 0xf20e18ff, 0xd90f18ff, 0xa31315ff, 0xef0e1cff, 0xee0e1dff, + 0xed0d1eff, 0xdd0e1eff, 0x5a1510ff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, + 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3e1616ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x702e1aff, 0x6f2e1aff, + 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, + 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xbc1d12ff, + 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x40180fff, 0xcb1012ff, + 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xd90f18ff, 0x54170fff, 0x3e180eff, + 0x961215ff, 0xed0d1eff, 0xec0d20ff, 0xeb0d21ff, 0xdb0e20ff, 0x591512ff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, + 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3d1516ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6f2e19ff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, + 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, + 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, + 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, + 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x8f1216ff, 0xeb0d21ff, 0xea0d22ff, + 0xe90d24ff, 0xd90e23ff, 0x5a1513ff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, + 0x3c1416ff, 0x3d1515ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6e2e19ff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, + 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, + 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, + 0x40180fff, 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, + 0x56170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, + 0x8e1217ff, 0xe90d24ff, 0xe80d25ff, 0xe70d26ff, 0xd70e26ff, 0x5a1513ff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, + 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3d1516ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6d2d19ff, 0x6c2d19ff, + 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, + 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, + 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0xa11210ff, 0x40180fff, 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, + 0xdc0f18ff, 0x56170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x8d1218ff, 0xe70d26ff, 0xe60d28ff, + 0xe50d29ff, 0xd50e27ff, 0x591415ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, + 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, + 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3d1416ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, + 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0xa11210ff, 0x40180fff, 0xa91212ff, 0xf40e15ff, 0xf30e16ff, + 0xf20e18ff, 0xdc0f18ff, 0x56170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x8c121bff, 0xe50d29ff, 0xe40d2aff, 0xe30d2cff, 0xd40e2aff, 0x5a1515ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, + 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, + 0x3c1316ff, 0x3d1417ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, + 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, + 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, 0xa91212ff, 0xf40e15ff, + 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x8b121cff, 0xe30d2cff, 0xe20d2dff, + 0xe10d2eff, 0xd20e2dff, 0x591416ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, + 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, + 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3d1418ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a2c19ff, 0x6a2c18ff, + 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, + 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, 0xa91212ff, + 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, 0x3e180eff, + 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x8a121eff, 0xe10d2eff, 0xe00d30ff, 0xdf0d31ff, 0xd00e30ff, 0x591418ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, + 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, + 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3d1318ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, + 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, + 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, + 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x8a121fff, 0xdf0d31ff, 0xde0d33ff, + 0xdd0d34ff, 0xce0e32ff, 0x591418ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, + 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, + 0x3c1218ff, 0x3c1318ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, + 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, + 0x3f180fff, 0xab1212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xd90f18ff, + 0x54170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, + 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x8e1222ff, 0xdd0d34ff, 0xdc0d35ff, 0xdb0d37ff, 0xcc0e35ff, 0x571419ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, + 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, + 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3c1319ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x682b18ff, 0x672a17ff, + 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, + 0x612815ff, 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, + 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0x9b1310ff, 0x3f180fff, 0x691511ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, + 0xd90f18ff, 0x54170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x8d1224ff, 0xdb0d37ff, 0xda0d38ff, + 0xd90d39ff, 0xcb0e38ff, 0x56141cff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, + 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, + 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3c1218ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, + 0x622815ff, 0x612815ff, 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, + 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, 0x5d1610ff, 0xf10e16ff, + 0xf20e18ff, 0xd90f18ff, 0x54170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x8c1125ff, 0xd90d39ff, 0xd80d3bff, 0xd70d3cff, 0xc90e39ff, 0x56141cff, + 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, + 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, + 0x3b1118ff, 0x3c1218ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, + 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x9b2012ff, 0xfa1410ff, + 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x40180fff, 0x7b1511ff, 0x801411ff, + 0x41180eff, 0x6e1610ff, 0x911313ff, 0x4e170fff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x8a1228ff, 0xd70d3cff, 0xd60d3dff, + 0xd50d3fff, 0xc70d3cff, 0x56141dff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, + 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, + 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3c1319ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x652a16ff, 0x642916ff, + 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, + 0xd81810ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, + 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x851411ff, + 0xf40e15ff, 0xf30e16ff, 0x941412ff, 0x3e180eff, 0x3f180eff, 0x3e180eff, + 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, + 0x8a1129ff, 0xd50d3fff, 0xd40c40ff, 0xd30c41ff, 0xc50d3fff, 0x54131dff, + 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, + 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3b121aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, + 0x5f2714ff, 0x5e2614ff, 0xe41610ff, 0xfa130fff, 0xf9120fff, 0xf9110fff, + 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, + 0x3f180fff, 0x971311ff, 0xf30e16ff, 0xf20e18ff, 0xa51214ff, 0x3f180eff, + 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x88102aff, 0xd30c41ff, 0xd20c43ff, + 0xd10c44ff, 0xc20d41ff, 0x51131dff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, + 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, + 0x3a111aff, 0x3a1219ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, + 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, 0xb61b11ff, 0xf9120fff, + 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, + 0x3f180fff, 0x5c1610ff, 0x4d170fff, 0x49180eff, 0xac1214ff, 0xb01215ff, + 0x50170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, + 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, + 0x87102dff, 0xd10c44ff, 0xd00c45ff, 0xcf0c47ff, 0x940f34ff, 0x3c1317ff, + 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, + 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3b1219ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x632815ff, 0x622815ff, + 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, + 0x652413ff, 0xd81510ff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, + 0x9b1310ff, 0x3f180fff, 0x961412ff, 0xf40e15ff, 0xea0e16ff, 0x591610ff, + 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, + 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, + 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x86102dff, 0xcf0c47ff, 0xce0c48ff, + 0x7a102cff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, + 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x3a1119ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, + 0x5d2613ff, 0x5c2513ff, 0x742211ff, 0xeb120fff, 0xf90f0eff, 0xf90e0eff, + 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, 0xc81113ff, 0xf30e16ff, + 0xf20e18ff, 0x811412ff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, + 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, + 0x5d1221ff, 0x621124ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, + 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, + 0x39101aff, 0x3a1119ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, + 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0xd4140fff, 0xf90f0eff, + 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, 0x3f180eff, + 0x761511ff, 0xe40f17ff, 0xc91016ff, 0x4b170fff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, + 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, + 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, + 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, + 0x3a111aff, 0x39101aff, 0x39101aff, 0x39111aff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x602714ff, 0x5f2714ff, + 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, + 0xd4140fff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, + 0x3f180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, + 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, + 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, + 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, + 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, + 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x39101aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, + 0x5a2412ff, 0x592411ff, 0x6b1f10ff, 0xa71310ff, 0x801510ff, 0x3f180fff, + 0x3f180fff, 0x3f180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, + 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, + 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, + 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, + 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, + 0x380f1bff, 0x39101aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, + 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x54210fff, + 0x41190eff, 0x3f180fff, 0x3f180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, + 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, + 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, + 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, + 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, + 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, + 0x38101bff, 0x380f1bff, 0x380f1bff, 0x38101bff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5d2613ff, 0x5d2613ff, + 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, + 0x572310ff, 0x562210ff, 0x52200fff, 0x40190fff, 0x3f180eff, 0x3e180eff, + 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, + 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, + 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, + 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, + 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, + 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, + 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x380f1bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, + 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x501f0fff, + 0x40190fff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, + 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, + 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, + 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, + 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, + 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, + 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, + 0x370e1cff, 0x370f1cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, + 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, + 0x53210fff, 0x52210fff, 0x4f1f0eff, 0x40190eff, 0x3e180eff, 0x3e170dff, + 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, + 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, + 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, + 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, + 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, + 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, + 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x370f1cff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5b2512ff, 0x5a2412ff, + 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, + 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x4e1f0eff, + 0x3f180eff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, + 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, + 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, + 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, + 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, + 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, + 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, + 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x360e1cff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, + 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, + 0x50200eff, 0x4f1f0dff, 0x4c1e0dff, 0x3f180dff, 0x3d170dff, 0x3d170dff, + 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, + 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, + 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, + 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, + 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, + 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, + 0x350d1dff, 0x360e1dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, + 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, + 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4a1d0dff, + 0x3f180dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, + 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, + 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, + 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, + 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, + 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, + 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, + 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x350e1dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x582411ff, 0x572311ff, + 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, + 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x491c0eff, 0x3f180eff, 0x3d170eff, 0x3d170fff, + 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, + 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, + 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, + 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, + 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, + 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, + 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, + 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x350d1dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, + 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, + 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x481c0eff, + 0x3f170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, + 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, + 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, + 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, + 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, + 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, + 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, + 0x340c1eff, 0x340d1eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, + 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, + 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, + 0x4a1d0dff, 0x4a1c0eff, 0x471b0fff, 0x3f180fff, 0x3d1610ff, 0x3e1710ff, + 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, + 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, + 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, + 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, + 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, + 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, + 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x340d1eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x562210ff, 0x552210ff, + 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, + 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, + 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x471a10ff, + 0x3f1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, + 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, + 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, + 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, + 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, + 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, + 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x340c1eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, + 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, + 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x3f1711ff, 0x3e1611ff, 0x3e1711ff, + 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, + 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, + 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, + 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, + 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, + 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, + 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, + 0x330b1fff, 0x330c1fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, + 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, + 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x461911ff, + 0x3f1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, + 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, + 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, + 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, + 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, + 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, + 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, + 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x330c1fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x53210fff, 0x52210fff, + 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, + 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, + 0x471a10ff, 0x461a10ff, 0x441812ff, 0x3e1613ff, 0x3e1612ff, 0x3e1513ff, + 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, + 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, + 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, + 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, + 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, + 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, + 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x320b1fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, + 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, + 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, + 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, 0x431811ff, + 0x3e1613ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, + 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, + 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, + 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, + 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, + 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, + 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, + 0x310a20ff, 0x320b20ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, + 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, + 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, + 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, + 0x451911ff, 0x441812ff, 0x421712ff, 0x3e1613ff, 0x3d1515ff, 0x3e1514ff, + 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, + 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, + 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, + 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, + 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, + 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, + 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x310b20ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x51200eff, 0x50200eff, + 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, + 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, + 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, + 0x451911ff, 0x451911ff, 0x441812ff, 0x441812ff, 0x431812ff, 0x421713ff, + 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, + 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, + 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, + 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, + 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, + 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, + 0x320b20ff, 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x300a21ff, 0x310a20ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, + 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, + 0x461911ff, 0x451911ff, 0x451911ff, 0x441812ff, 0x441812ff, 0x431812ff, + 0x431713ff, 0x431713ff, 0x411714ff, 0x3d1515ff, 0x3d1515ff, 0x3d1516ff, + 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, + 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, + 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, + 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, + 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, + 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x300a21ff, + 0x300921ff, 0x300a21ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, + 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x471a10ff, + 0x461a10ff, 0x461911ff, 0x451911ff, 0x451911ff, 0x441812ff, 0x441812ff, + 0x431812ff, 0x431713ff, 0x431713ff, 0x421714ff, 0x421614ff, 0x401614ff, + 0x3d1515ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, + 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, + 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, + 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, + 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, + 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x310a20ff, 0x310a21ff, + 0x300a21ff, 0x300921ff, 0x2f0922ff, 0x300a21ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0eff, 0x4d1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, + 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, + 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, 0x451911ff, 0x441812ff, + 0x441812ff, 0x431812ff, 0x431713ff, 0x431713ff, 0x421714ff, 0x421614ff, + 0x411614ff, 0x411615ff, 0x3f1515ff, 0x3d1415ff, 0x3c1416ff, 0x3c1316ff, + 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, + 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, + 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, + 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, + 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x310a20ff, + 0x310a21ff, 0x300a21ff, 0x300921ff, 0x2f0922ff, 0x2f0922ff, 0x330b20ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x5a250fea, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, + 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, + 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, 0x451911ff, + 0x441812ff, 0x441812ff, 0x431812ff, 0x431713ff, 0x431713ff, 0x421714ff, + 0x421614ff, 0x411614ff, 0x411615ff, 0x401515ff, 0x401515ff, 0x3e1516ff, + 0x3d1317ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, + 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, + 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, + 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, + 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, + 0x310a20ff, 0x310a21ff, 0x300a21ff, 0x300921ff, 0x2f0922ff, 0x2f0922ff, + 0x2e0822ff, 0x48171fe9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x782d1e22, 0x56220df7, 0x4b1d0dff, 0x4b1d0dff, + 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, + 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, + 0x451911ff, 0x441812ff, 0x441812ff, 0x431812ff, 0x431713ff, 0x431713ff, + 0x421714ff, 0x421614ff, 0x411614ff, 0x411615ff, 0x401515ff, 0x401515ff, + 0x3f1516ff, 0x3f1416ff, 0x3d1416ff, 0x3d1318ff, 0x3c1218ff, 0x3b1218ff, + 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, + 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, + 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, + 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, + 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x300a21ff, 0x300921ff, 0x2f0922ff, + 0x2f0922ff, 0x2e0822ff, 0x40131ff6, 0x68282820, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x7030114b, 0x6a2e1397, 0x682b149b, 0x662b149b, 0x662b149b, 0x662b149b, + 0x662b149b, 0x662b149b, 0x662b149b, 0x662b149b, 0x662b149b, 0x662b159b, + 0x642b159b, 0x642b159b, 0x6429159b, 0x6429159b, 0x6429159b, 0x6429159b, + 0x6429159b, 0x6429159b, 0x6429159b, 0x6329159b, 0x6329179b, 0x6329179b, + 0x6329179b, 0x6329179b, 0x6327179b, 0x6327179b, 0x6327179b, 0x6027179c, + 0x5f27179c, 0x5f27179c, 0x6027179c, 0x6027179c, 0x6027199c, 0x6127199b, + 0x5f27199b, 0x5f27199b, 0x5f26199b, 0x5f26199b, 0x5f26199b, 0x5f26199b, + 0x5f26199b, 0x5f26199b, 0x5f26199b, 0x5e261a9b, 0x5e261a9b, 0x5e241a9b, + 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, + 0x5c241c9b, 0x5c241c9b, 0x5c241c9b, 0x5c241c9b, 0x5c241c9b, 0x5c231c9b, + 0x5c231c9b, 0x5c231c9b, 0x5f231d97, 0x66291b4b, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; diff --git a/games/NXDoom/src/hexen/in_lude.c b/games/NXDoom/src/hexen/in_lude.c new file mode 100644 index 00000000000..573dce5c8d6 --- /dev/null +++ b/games/NXDoom/src/hexen/in_lude.c @@ -0,0 +1,607 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include + +#include "h2def.h" +#include "s_sound.h" +#include "i_system.h" +#include "i_video.h" +#include "m_misc.h" +#include "p_local.h" +#include "v_video.h" +#include "i_swap.h" +#include "am_map.h" + + +// MACROS ------------------------------------------------------------------ + +#define TEXTSPEED 3 +#define TEXTWAIT 140 + +// TYPES ------------------------------------------------------------------- + +typedef enum +{ + SINGLE, + COOPERATIVE, + DEATHMATCH +} gametype_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void WaitStop(void); +static void Stop(void); +static void LoadPics(void); +static void UnloadPics(void); +static void CheckForSkip(void); +static void InitStats(void); +static void DrDeathTally(void); +static void DrNumber(int val, int x, int y, int wrapThresh); +static void DrNumberBold(int val, int x, int y, int wrapThresh); +static void DrawHubText(void); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DECLARATIONS ------------------------------------------------ + +boolean intermission; +char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE]; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static boolean skipintermission; +static int interstate = 0; +static int intertime = -1; +static gametype_t gametype; +static int cnt; +static int slaughterboy; // in DM, the player with the most kills +static patch_t *patchINTERPIC; +static patch_t *FontBNumbers[10]; +static patch_t *FontBNegative; +static patch_t *FontBSlash; +static patch_t *FontBPercent; +static int FontABaseLump; +static int FontBLump; +static int FontBLumpBase; + +static signed int totalFrags[MAXPLAYERS]; + +static int HubCount; +static char *HubText; + +// CODE -------------------------------------------------------------------- + +//======================================================================== +// +// IN_Start +// +//======================================================================== + + +void IN_Start(void) +{ + int i; + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + InitStats(); + LoadPics(); + intermission = true; + interstate = 0; + skipintermission = false; + intertime = 0; + AM_Stop(); + for (i = 0; i < maxplayers; i++) + { + players[i].messageTics = 0; + players[i].message[0] = 0; + } + SN_StopAllSequences(); +} + +//======================================================================== +// +// WaitStop +// +//======================================================================== + +void WaitStop(void) +{ + if (!--cnt) + { + Stop(); +// gamestate = GS_LEVEL; +// G_DoLoadLevel(); + gameaction = ga_leavemap; +// G_WorldDone(); + } +} + +//======================================================================== +// +// Stop +// +//======================================================================== + +static void Stop(void) +{ + intermission = false; + UnloadPics(); + SB_state = -1; + BorderNeedRefresh = true; +} + +//======================================================================== +// +// InitStats +// +// Initializes the stats for single player mode +//======================================================================== + +static const char *ClusMsgLumpNames[] = { + "clus1msg", + "clus2msg", + "clus3msg", + "clus4msg", + "clus5msg" +}; + +static void InitStats(void) +{ + int i; + int j; + int oldCluster; + signed int slaughterfrags; + int slaughtercount; + int playercount; + const char *msgLumpName; + int msgSize; + int msgLump; + + if (!deathmatch) + { + gametype = SINGLE; + HubCount = 0; + oldCluster = P_GetMapCluster(gamemap); + if (oldCluster != P_GetMapCluster(LeaveMap)) + { + if (oldCluster >= 1 && oldCluster <= 5) + { + msgLumpName = ClusMsgLumpNames[oldCluster - 1]; + msgLump = W_GetNumForName(msgLumpName); + msgSize = W_LumpLength(msgLump); + if (msgSize >= MAX_INTRMSN_MESSAGE_SIZE) + { + I_Error("Cluster message too long (%s)", msgLumpName); + } + W_ReadLump(msgLump, ClusterMessage); + ClusterMessage[msgSize] = 0; // Append terminator + HubText = ClusterMessage; + HubCount = strlen(HubText) * TEXTSPEED + TEXTWAIT; + S_StartSongName("hub", true); + } + } + } + else + { + gametype = DEATHMATCH; + slaughterboy = 0; + slaughterfrags = -9999; + playercount = 0; + slaughtercount = 0; + for (i = 0; i < maxplayers; i++) + { + totalFrags[i] = 0; + if (playeringame[i]) + { + playercount++; + for (j = 0; j < maxplayers; j++) + { + if (playeringame[j]) + { + totalFrags[i] += players[i].frags[j]; + } + } + } + if (totalFrags[i] > slaughterfrags) + { + slaughterboy = 1 << i; + slaughterfrags = totalFrags[i]; + slaughtercount = 1; + } + else if (totalFrags[i] == slaughterfrags) + { + slaughterboy |= 1 << i; + slaughtercount++; + } + } + if (playercount == slaughtercount) + { // don't do the slaughter stuff if everyone is equal + slaughterboy = 0; + } + S_StartSongName("hub", true); + } +} + +//======================================================================== +// +// LoadPics +// +//======================================================================== + +static void LoadPics(void) +{ + int i; + + if (HubCount || gametype == DEATHMATCH) + { + patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC); + FontBLumpBase = W_GetNumForName("FONTB16"); + for (i = 0; i < 10; i++) + { + FontBNumbers[i] = W_CacheLumpNum(FontBLumpBase + i, PU_STATIC); + } + FontBLump = W_GetNumForName("FONTB_S") + 1; + FontBNegative = W_CacheLumpName("FONTB13", PU_STATIC); + FontABaseLump = W_GetNumForName("FONTA_S") + 1; + + FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC); + FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC); + } +} + +//======================================================================== +// +// UnloadPics +// +//======================================================================== + +static void UnloadPics(void) +{ + int i; + + if (HubCount || gametype == DEATHMATCH) + { + W_ReleaseLumpName("INTERPIC"); + + patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC); + FontBLumpBase = W_GetNumForName("FONTB16"); + for (i = 0; i < 10; i++) + { + W_ReleaseLumpNum(FontBLumpBase + i); + } + W_ReleaseLumpName("FONTB13"); + W_ReleaseLumpName("FONTB15"); + W_ReleaseLumpName("FONTB05"); + } +} + +//======================================================================== +// +// IN_Ticker +// +//======================================================================== + +void IN_Ticker(void) +{ + if (!intermission) + { + return; + } + if (interstate) + { + WaitStop(); + return; + } + skipintermission = false; + CheckForSkip(); + intertime++; + if (skipintermission || (gametype == SINGLE && !HubCount)) + { + interstate = 1; + cnt = 10; + skipintermission = false; + //S_StartSound(NULL, sfx_dorcls); + } +} + +//======================================================================== +// +// CheckForSkip +// +// Check to see if any player hit a key +//======================================================================== + +static void CheckForSkip(void) +{ + int i; + player_t *player; + static boolean triedToSkip; + + for (i = 0, player = players; i < maxplayers; i++, player++) + { + if (playeringame[i]) + { + if (player->cmd.buttons & BT_ATTACK) + { + if (!player->attackdown) + { + skipintermission = 1; + } + player->attackdown = true; + } + else + { + player->attackdown = false; + } + if (player->cmd.buttons & BT_USE) + { + if (!player->usedown) + { + skipintermission = 1; + } + player->usedown = true; + } + else + { + player->usedown = false; + } + } + } + if (deathmatch && intertime < 140) + { // wait for 4 seconds before allowing a skip + if (skipintermission == 1) + { + triedToSkip = true; + skipintermission = 0; + } + } + else + { + if (triedToSkip) + { + skipintermission = 1; + triedToSkip = false; + } + } +} + +//======================================================================== +// +// IN_Drawer +// +//======================================================================== + +void IN_Drawer(void) +{ + if (!intermission) + { + return; + } + if (interstate) + { + return; + } + UpdateState |= I_FULLSCRN; + memcpy(I_VideoBuffer, (byte *) patchINTERPIC, SCREENWIDTH * SCREENHEIGHT); + + if (gametype == SINGLE) + { + if (HubCount) + { + DrawHubText(); + } + } + else + { + DrDeathTally(); + } +} + +//======================================================================== +// +// DrDeathTally +// +//======================================================================== + +#define TALLY_EFFECT_TICKS 20 +#define TALLY_FINAL_X_DELTA (23*FRACUNIT) +#define TALLY_FINAL_Y_DELTA (13*FRACUNIT) +#define TALLY_START_XPOS (178*FRACUNIT) +#define TALLY_STOP_XPOS (90*FRACUNIT) +#define TALLY_START_YPOS (132*FRACUNIT) +#define TALLY_STOP_YPOS (83*FRACUNIT) +#define TALLY_TOP_X 85 +#define TALLY_TOP_Y 9 +#define TALLY_LEFT_X 7 +#define TALLY_LEFT_Y 71 +#define TALLY_TOTALS_X 291 + +static void DrDeathTally(void) +{ + int i, j; + fixed_t xPos, yPos; + fixed_t xDelta, yDelta; + fixed_t xStart, scale; + int x, y; + boolean bold; + static boolean showTotals; + int temp; + + V_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y, + W_CacheLumpName("tallytop", PU_CACHE)); + V_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y, + W_CacheLumpName("tallylft", PU_CACHE)); + if (intertime < TALLY_EFFECT_TICKS) + { + showTotals = false; + scale = (intertime * FRACUNIT) / TALLY_EFFECT_TICKS; + xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA); + yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA); + xStart = TALLY_START_XPOS - FixedMul(scale, + TALLY_START_XPOS - + TALLY_STOP_XPOS); + yPos = + TALLY_START_YPOS - FixedMul(scale, + TALLY_START_YPOS - TALLY_STOP_YPOS); + } + else + { + xDelta = TALLY_FINAL_X_DELTA; + yDelta = TALLY_FINAL_Y_DELTA; + xStart = TALLY_STOP_XPOS; + yPos = TALLY_STOP_YPOS; + } + if (intertime >= TALLY_EFFECT_TICKS && showTotals == false) + { + showTotals = true; + S_StartSound(NULL, SFX_PLATFORM_STOP); + } + y = yPos >> FRACBITS; + for (i = 0; i < maxplayers; i++) + { + xPos = xStart; + for (j = 0; j < maxplayers; j++, xPos += xDelta) + { + x = xPos >> FRACBITS; + bold = (i == consoleplayer || j == consoleplayer); + if (playeringame[i] && playeringame[j]) + { + if (bold) + { + DrNumberBold(players[i].frags[j], x, y, 100); + } + else + { + DrNumber(players[i].frags[j], x, y, 100); + } + } + else + { + temp = MN_TextAWidth("--") / 2; + if (bold) + { + MN_DrTextAYellow("--", x - temp, y); + } + else + { + MN_DrTextA("--", x - temp, y); + } + } + } + if (showTotals && playeringame[i] + && !((slaughterboy & (1 << i)) && !(intertime & 16))) + { + DrNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000); + } + yPos += yDelta; + y = yPos >> FRACBITS; + } +} + +//========================================================================== +// +// DrNumber +// +//========================================================================== + +static void DrNumber(int val, int x, int y, int wrapThresh) +{ + char buff[8] = "XX"; + + if (!(val < -9 && wrapThresh < 1000)) + { + M_snprintf(buff, sizeof(buff), "%d", + val >= wrapThresh ? val % wrapThresh : val); + } + MN_DrTextA(buff, x - MN_TextAWidth(buff) / 2, y); +} + +//========================================================================== +// +// DrNumberBold +// +//========================================================================== + +static void DrNumberBold(int val, int x, int y, int wrapThresh) +{ + char buff[8] = "XX"; + + if (!(val < -9 && wrapThresh < 1000)) + { + M_snprintf(buff, sizeof(buff), "%d", + val >= wrapThresh ? val % wrapThresh : val); + } + MN_DrTextAYellow(buff, x - MN_TextAWidth(buff) / 2, y); +} + +//=========================================================================== +// +// DrawHubText +// +//=========================================================================== + +static void DrawHubText(void) +{ + int count; + char *ch; + int c; + int cx, cy; + patch_t *w; + + cy = 5; + cx = 10; + ch = HubText; + count = (intertime - 10) / TEXTSPEED; + if (count < 0) + { + count = 0; + } + for (; count; count--) + { + c = *ch++; + if (!c) + { + break; + } + if (c == '\n') + { + cx = 10; + cy += 9; + continue; + } + if (c < 32) + { + continue; + } + c = toupper(c); + if (c == 32) + { + cx += 5; + continue; + } + w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + if (cx + SHORT(w->width) > SCREENWIDTH) + { + break; + } + V_DrawPatch(cx, cy, w); + cx += SHORT(w->width); + } +} diff --git a/games/NXDoom/src/hexen/info.c b/games/NXDoom/src/hexen/info.c new file mode 100644 index 00000000000..ad579b629a5 --- /dev/null +++ b/games/NXDoom/src/hexen/info.c @@ -0,0 +1,13654 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +#include "h2def.h" +#include "i_swap.h" +#include "p_local.h" + +// generated by stateco + +const char *sprnames[] = { + "MAN1","ACLO","TLGL","FBL1","XPL1","ARRW","DART","RIPP","CFCF","BLAD", + "SHRD","FFSM","FFLG","PTN1","PTN2","SOAR","INVU","SUMN","TSPK","TELO", + "TRNG","ROCK","FOGS","FOGM","FOGL","SGSA","SGSB","PORK","EGGM","FHFX", + "SPHL","STWN","GMPD","ASKU","ABGM","AGMR","AGMG","AGG2","AGMB","AGB2", + "ABK1","ABK2","ASK2","AFWP","ACWP","AMWP","AGER","AGR2","AGR3","AGR4", + "TRCH","PSBG","ATLP","THRW","SPED","BMAN","BRAC","BLST","HRAD","SPSH", + "LVAS","SLDG","STTW","RCK1","RCK2","RCK3","RCK4","CDLR","TRE1","TRDT", + "TRE2","TRE3","STM1","STM2","STM3","STM4","MSH1","MSH2","MSH3","MSH4", + "MSH5","MSH6","MSH7","MSH8","SGMP","SGM1","SGM2","SGM3","SLC1","SLC2", + "SLC3","MSS1","MSS2","SWMV","CPS1","CPS2","TMS1","TMS2","TMS3","TMS4", + "TMS5","TMS6","TMS7","CPS3","STT2","STT3","STT4","STT5","GAR1","GAR2", + "GAR3","GAR4","GAR5","GAR6","GAR7","GAR8","GAR9","BNR1","TRE4","TRE5", + "TRE6","TRE7","LOGG","ICT1","ICT2","ICT3","ICT4","ICM1","ICM2","ICM3", + "ICM4","RKBL","RKBS","RKBK","RBL1","RBL2","RBL3","VASE","POT1","POT2", + "POT3","PBIT","CPS4","CPS5","CPS6","CPB1","CPB2","CPB3","CPB4","BDRP", + "BDSH","BDPL","CNDL","LEF1","LEF3","LEF2","TWTR","WLTR","BARL","SHB1", + "SHB2","BCKT","SHRM","FBUL","FSKL","BRTR","SUIT","BBLL","CAND","IRON", + "XMAS","CDRN","CHNS","TST1","TST2","TST3","TST4","TST5","TST6","TST7", + "TST8","TST9","TST0","TELE","TSMK","FPCH","WFAX","FAXE","WFHM","FHMR", + "FSRD","FSFX","CMCE","WCSS","CSSF","WCFM","CFLM","CFFX","CHLY","SPIR", + "MWND","WMLG","MLNG","MLFX","MLF2","MSTF","MSP1","MSP2","WFR1","WFR2", + "WFR3","WCH1","WCH2","WCH3","WMS1","WMS2","WMS3","WPIG","WMCS","CONE", + "SHEX","BLOD","GIBS","PLAY","FDTH","BSKL","ICEC","CLER","MAGE","PIGY", + "CENT","CTXD","CTFX","CTDP","DEMN","DEMA","DEMB","DEMC","DEMD","DEME", + "DMFX","DEM2","DMBA","DMBB","DMBC","DMBD","DMBE","D2FX","WRTH","WRT2", + "WRBL","MNTR","FX12","FX13","MNSM","SSPT","SSDV","SSXD","SSFX","BISH", + "BPFX","DRAG","DRFX","ARM1","ARM2","ARM3","ARM4","MAN2","MAN3","KEY1", + "KEY2","KEY3","KEY4","KEY5","KEY6","KEY7","KEY8","KEY9","KEYA","KEYB", + "ETTN","ETTB","FDMN","FDMB","ICEY","ICPR","ICWS","SORC","SBMP","SBS4", + "SBMB","SBS3","SBMG","SBS1","SBS2","SBFX","RADE","WATR","KORX","ABAT", + NULL +}; + + +state_t states[NUMSTATES] = { + {SPR_MAN1, 0, -1, NULL, S_NULL, 0, 0}, // S_NULL + {SPR_ACLO, 4, 1050, A_FreeTargMobj, S_NULL, 0, 0}, // S_FREETARGMOBJ + {SPR_TLGL, 0, -1, NULL, S_NULL, 0, 0}, // S_MAPSPOT + {SPR_FBL1, 32768, 4, NULL, S_FIREBALL1_2, 0, 0}, // S_FIREBALL1_1 + {SPR_FBL1, 32769, 4, NULL, S_FIREBALL1_1, 0, 0}, // S_FIREBALL1_2 + {SPR_XPL1, 32768, 4, NULL, S_FIREBALL1_X2, 0, 0}, // S_FIREBALL1_X1 + {SPR_XPL1, 32769, 4, NULL, S_FIREBALL1_X3, 0, 0}, // S_FIREBALL1_X2 + {SPR_XPL1, 32770, 4, NULL, S_FIREBALL1_X4, 0, 0}, // S_FIREBALL1_X3 + {SPR_XPL1, 32771, 4, NULL, S_FIREBALL1_X5, 0, 0}, // S_FIREBALL1_X4 + {SPR_XPL1, 32772, 4, NULL, S_FIREBALL1_X6, 0, 0}, // S_FIREBALL1_X5 + {SPR_XPL1, 32773, 4, NULL, S_NULL, 0, 0}, // S_FIREBALL1_X6 + {SPR_ARRW, 0, -1, NULL, S_NULL, 0, 0}, // S_ARROW_1 + {SPR_ARRW, 0, 1, NULL, S_NULL, 0, 0}, // S_ARROW_X1 + {SPR_DART, 0, -1, NULL, S_NULL, 0, 0}, // S_DART_1 + {SPR_DART, 0, 1, NULL, S_NULL, 0, 0}, // S_DART_X1 + {SPR_DART, 0, -1, NULL, S_NULL, 0, 0}, // S_POISONDART_1 + {SPR_DART, 0, 1, NULL, S_NULL, 0, 0}, // S_POISONDART_X1 + {SPR_RIPP, 0, 3, NULL, S_RIPPERBALL_2, 0, 0}, // S_RIPPERBALL_1 + {SPR_RIPP, 1, 3, NULL, S_RIPPERBALL_3, 0, 0}, // S_RIPPERBALL_2 + {SPR_RIPP, 2, 3, NULL, S_RIPPERBALL_1, 0, 0}, // S_RIPPERBALL_3 + {SPR_CFCF, 32784, 4, NULL, S_RIPPERBALL_X2, 0, 0}, // S_RIPPERBALL_X1 + {SPR_CFCF, 32785, 3, NULL, S_RIPPERBALL_X3, 0, 0}, // S_RIPPERBALL_X2 + {SPR_CFCF, 32786, 4, NULL, S_RIPPERBALL_X4, 0, 0}, // S_RIPPERBALL_X3 + {SPR_CFCF, 32787, 3, NULL, S_RIPPERBALL_X5, 0, 0}, // S_RIPPERBALL_X4 + {SPR_CFCF, 32788, 4, NULL, S_RIPPERBALL_X6, 0, 0}, // S_RIPPERBALL_X5 + {SPR_CFCF, 32789, 3, NULL, S_RIPPERBALL_X7, 0, 0}, // S_RIPPERBALL_X6 + {SPR_CFCF, 32790, 4, NULL, S_RIPPERBALL_X8, 0, 0}, // S_RIPPERBALL_X7 + {SPR_CFCF, 32791, 3, NULL, S_RIPPERBALL_X9, 0, 0}, // S_RIPPERBALL_X8 + {SPR_CFCF, 32792, 4, NULL, S_RIPPERBALL_X10, 0, 0}, // S_RIPPERBALL_X9 + {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_RIPPERBALL_X10 + {SPR_BLAD, 0, -1, NULL, S_NULL, 0, 0}, // S_PRJ_BLADE1 + {SPR_BLAD, 0, 1, NULL, S_NULL, 0, 0}, // S_PRJ_BLADE_X1 + {SPR_SHRD, 32768, 3, NULL, S_ICESHARD2, 0, 0}, // S_ICESHARD1 + {SPR_SHRD, 32769, 3, NULL, S_ICESHARD3, 0, 0}, // S_ICESHARD2 + {SPR_SHRD, 32770, 3, NULL, S_ICESHARD1, 0, 0}, // S_ICESHARD3 + {SPR_FFSM, 32768, 3, NULL, S_FLAME_TSMALL2, 0, 0}, // S_FLAME_TSMALL1 + {SPR_FFSM, 32769, 3, NULL, S_FLAME_TSMALL3, 0, 0}, // S_FLAME_TSMALL2 + {SPR_FFSM, 32770, 2, A_FlameCheck, S_FLAME_TSMALL4, 0, 0}, // S_FLAME_TSMALL3 + {SPR_FFSM, 32770, 2, NULL, S_FLAME_TSMALL5, 0, 0}, // S_FLAME_TSMALL4 + {SPR_FFSM, 32771, 3, NULL, S_FLAME_TSMALL6, 0, 0}, // S_FLAME_TSMALL5 + {SPR_FFSM, 32772, 3, A_FlameCheck, S_FLAME_TSMALL1, 0, 0}, // S_FLAME_TSMALL6 + {SPR_FFLG, 32768, 4, NULL, S_FLAME_TLARGE2, 0, 0}, // S_FLAME_TLARGE1 + {SPR_FFLG, 32769, 4, A_FlameCheck, S_FLAME_TLARGE3, 0, 0}, // S_FLAME_TLARGE2 + {SPR_FFLG, 32770, 4, NULL, S_FLAME_TLARGE4, 0, 0}, // S_FLAME_TLARGE3 + {SPR_FFLG, 32771, 4, A_FlameCheck, S_FLAME_TLARGE5, 0, 0}, // S_FLAME_TLARGE4 + {SPR_FFLG, 32772, 4, NULL, S_FLAME_TLARGE6, 0, 0}, // S_FLAME_TLARGE5 + {SPR_FFLG, 32773, 4, A_FlameCheck, S_FLAME_TLARGE7, 0, 0}, // S_FLAME_TLARGE6 + {SPR_FFLG, 32774, 4, NULL, S_FLAME_TLARGE8, 0, 0}, // S_FLAME_TLARGE7 + {SPR_FFLG, 32775, 4, A_FlameCheck, S_FLAME_TLARGE9, 0, 0}, // S_FLAME_TLARGE8 + {SPR_FFLG, 32776, 4, NULL, S_FLAME_TLARGE10, 0, 0}, // S_FLAME_TLARGE9 + {SPR_FFLG, 32777, 4, A_FlameCheck, S_FLAME_TLARGE11, 0, 0}, // S_FLAME_TLARGE10 + {SPR_FFLG, 32778, 4, NULL, S_FLAME_TLARGE12, 0, 0}, // S_FLAME_TLARGE11 + {SPR_FFLG, 32779, 4, A_FlameCheck, S_FLAME_TLARGE13, 0, 0}, // S_FLAME_TLARGE12 + {SPR_FFLG, 32780, 4, NULL, S_FLAME_TLARGE14, 0, 0}, // S_FLAME_TLARGE13 + {SPR_FFLG, 32781, 4, A_FlameCheck, S_FLAME_TLARGE15, 0, 0}, // S_FLAME_TLARGE14 + {SPR_FFLG, 32782, 4, NULL, S_FLAME_TLARGE16, 0, 0}, // S_FLAME_TLARGE15 + {SPR_FFLG, 32783, 4, A_FlameCheck, S_FLAME_TLARGE5, 0, 0}, // S_FLAME_TLARGE16 + {SPR_FFSM, 0, 2, NULL, S_FLAME_SDORM2, 0, 0}, // S_FLAME_SDORM1 + {SPR_FFSM, 1, 2, A_HideThing, S_FLAME_SDORM3, 0, 0}, // S_FLAME_SDORM2 + {SPR_FFSM, 2, 200, NULL, S_FLAME_SDORM3, 0, 0}, // S_FLAME_SDORM3 + {SPR_FFSM, 32768, 3, NULL, S_FLAME_SMALL2, 0, 0}, // S_FLAME_SMALL1 + {SPR_FFSM, 32768, 3, A_UnHideThing, S_FLAME_SMALL3, 0, 0}, // S_FLAME_SMALL2 + {SPR_FFSM, 32768, 3, NULL, S_FLAME_SMALL4, 0, 0}, // S_FLAME_SMALL3 + {SPR_FFSM, 32769, 3, NULL, S_FLAME_SMALL5, 0, 0}, // S_FLAME_SMALL4 + {SPR_FFSM, 32770, 3, NULL, S_FLAME_SMALL6, 0, 0}, // S_FLAME_SMALL5 + {SPR_FFSM, 32771, 3, NULL, S_FLAME_SMALL7, 0, 0}, // S_FLAME_SMALL6 + {SPR_FFSM, 32772, 3, NULL, S_FLAME_SMALL3, 0, 0}, // S_FLAME_SMALL7 + {SPR_FFLG, 3, 2, NULL, S_FLAME_LDORM2, 0, 0}, // S_FLAME_LDORM1 + {SPR_FFLG, 2, 2, NULL, S_FLAME_LDORM3, 0, 0}, // S_FLAME_LDORM2 + {SPR_FFLG, 1, 2, NULL, S_FLAME_LDORM4, 0, 0}, // S_FLAME_LDORM3 + {SPR_FFLG, 0, 2, A_HideThing, S_FLAME_LDORM5, 0, 0}, // S_FLAME_LDORM4 + {SPR_FFLG, 0, 200, NULL, S_FLAME_LDORM5, 0, 0}, // S_FLAME_LDORM5 + {SPR_FFLG, 32768, 2, NULL, S_FLAME_LARGE2, 0, 0}, // S_FLAME_LARGE1 + {SPR_FFLG, 32768, 2, A_UnHideThing, S_FLAME_LARGE3, 0, 0}, // S_FLAME_LARGE2 + {SPR_FFLG, 32768, 4, NULL, S_FLAME_LARGE4, 0, 0}, // S_FLAME_LARGE3 + {SPR_FFLG, 32769, 4, NULL, S_FLAME_LARGE5, 0, 0}, // S_FLAME_LARGE4 + {SPR_FFLG, 32770, 4, NULL, S_FLAME_LARGE6, 0, 0}, // S_FLAME_LARGE5 + {SPR_FFLG, 32771, 4, NULL, S_FLAME_LARGE7, 0, 0}, // S_FLAME_LARGE6 + {SPR_FFLG, 32772, 4, NULL, S_FLAME_LARGE8, 0, 0}, // S_FLAME_LARGE7 + {SPR_FFLG, 32773, 4, NULL, S_FLAME_LARGE9, 0, 0}, // S_FLAME_LARGE8 + {SPR_FFLG, 32774, 4, NULL, S_FLAME_LARGE10, 0, 0}, // S_FLAME_LARGE9 + {SPR_FFLG, 32775, 4, NULL, S_FLAME_LARGE11, 0, 0}, // S_FLAME_LARGE10 + {SPR_FFLG, 32776, 4, NULL, S_FLAME_LARGE12, 0, 0}, // S_FLAME_LARGE11 + {SPR_FFLG, 32777, 4, NULL, S_FLAME_LARGE13, 0, 0}, // S_FLAME_LARGE12 + {SPR_FFLG, 32778, 4, NULL, S_FLAME_LARGE14, 0, 0}, // S_FLAME_LARGE13 + {SPR_FFLG, 32779, 4, NULL, S_FLAME_LARGE15, 0, 0}, // S_FLAME_LARGE14 + {SPR_FFLG, 32780, 4, NULL, S_FLAME_LARGE16, 0, 0}, // S_FLAME_LARGE15 + {SPR_FFLG, 32781, 4, NULL, S_FLAME_LARGE17, 0, 0}, // S_FLAME_LARGE16 + {SPR_FFLG, 32782, 4, NULL, S_FLAME_LARGE18, 0, 0}, // S_FLAME_LARGE17 + {SPR_FFLG, 32783, 4, NULL, S_FLAME_LARGE7, 0, 0}, // S_FLAME_LARGE18 + {SPR_PTN1, 0, 3, NULL, S_ITEM_PTN1_2, 0, 0}, // S_ITEM_PTN1_1 + {SPR_PTN1, 1, 3, NULL, S_ITEM_PTN1_3, 0, 0}, // S_ITEM_PTN1_2 + {SPR_PTN1, 2, 3, NULL, S_ITEM_PTN1_1, 0, 0}, // S_ITEM_PTN1_3 + {SPR_ACLO, 4, 1400, NULL, S_HIDESPECIAL2, 0, 0}, // S_HIDESPECIAL1 + {SPR_ACLO, 0, 4, A_RestoreSpecialThing1, S_HIDESPECIAL3, 0, 0}, // S_HIDESPECIAL2 + {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL4, 0, 0}, // S_HIDESPECIAL3 + {SPR_ACLO, 0, 4, NULL, S_HIDESPECIAL5, 0, 0}, // S_HIDESPECIAL4 + {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL6, 0, 0}, // S_HIDESPECIAL5 + {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL7, 0, 0}, // S_HIDESPECIAL6 + {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL8, 0, 0}, // S_HIDESPECIAL7 + {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL9, 0, 0}, // S_HIDESPECIAL8 + {SPR_ACLO, 3, 4, NULL, S_HIDESPECIAL10, 0, 0}, // S_HIDESPECIAL9 + {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL11, 0, 0}, // S_HIDESPECIAL10 + {SPR_ACLO, 3, 4, A_RestoreSpecialThing2, S_NULL, 0, 0}, // S_HIDESPECIAL11 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI1_2, 0, 0}, // S_DORMANTARTI1_1 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_3, 0, 0}, // S_DORMANTARTI1_2 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI1_4, 0, 0}, // S_DORMANTARTI1_3 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_5, 0, 0}, // S_DORMANTARTI1_4 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_6, 0, 0}, // S_DORMANTARTI1_5 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_7, 0, 0}, // S_DORMANTARTI1_6 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_8, 0, 0}, // S_DORMANTARTI1_7 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI1_9, 0, 0}, // S_DORMANTARTI1_8 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_10, 0, 0}, // S_DORMANTARTI1_9 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI1_11, 0, 0}, // S_DORMANTARTI1_10 + {SPR_ACLO, 0, 1400, A_HideThing, S_DORMANTARTI1_12, 0, 0}, // S_DORMANTARTI1_11 + {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI1_13, 0, 0}, // S_DORMANTARTI1_12 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_14, 0, 0}, // S_DORMANTARTI1_13 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI1_15, 0, 0}, // S_DORMANTARTI1_14 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_16, 0, 0}, // S_DORMANTARTI1_15 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_17, 0, 0}, // S_DORMANTARTI1_16 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_18, 0, 0}, // S_DORMANTARTI1_17 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_19, 0, 0}, // S_DORMANTARTI1_18 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI1_20, 0, 0}, // S_DORMANTARTI1_19 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_21, 0, 0}, // S_DORMANTARTI1_20 + {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI1_21 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2_2, 0, 0}, // S_DORMANTARTI2_1 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_3, 0, 0}, // S_DORMANTARTI2_2 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2_4, 0, 0}, // S_DORMANTARTI2_3 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_5, 0, 0}, // S_DORMANTARTI2_4 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_6, 0, 0}, // S_DORMANTARTI2_5 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_7, 0, 0}, // S_DORMANTARTI2_6 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_8, 0, 0}, // S_DORMANTARTI2_7 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI2_9, 0, 0}, // S_DORMANTARTI2_8 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_10, 0, 0}, // S_DORMANTARTI2_9 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI2_11, 0, 0}, // S_DORMANTARTI2_10 + {SPR_ACLO, 0, 4200, A_HideThing, S_DORMANTARTI2_12, 0, 0}, // S_DORMANTARTI2_11 + {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI2_13, 0, 0}, // S_DORMANTARTI2_12 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_14, 0, 0}, // S_DORMANTARTI2_13 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI2_15, 0, 0}, // S_DORMANTARTI2_14 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_16, 0, 0}, // S_DORMANTARTI2_15 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_17, 0, 0}, // S_DORMANTARTI2_16 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_18, 0, 0}, // S_DORMANTARTI2_17 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_19, 0, 0}, // S_DORMANTARTI2_18 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2_20, 0, 0}, // S_DORMANTARTI2_19 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_21, 0, 0}, // S_DORMANTARTI2_20 + {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI2_21 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI3_2, 0, 0}, // S_DORMANTARTI3_1 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_3, 0, 0}, // S_DORMANTARTI3_2 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI3_4, 0, 0}, // S_DORMANTARTI3_3 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_5, 0, 0}, // S_DORMANTARTI3_4 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_6, 0, 0}, // S_DORMANTARTI3_5 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_7, 0, 0}, // S_DORMANTARTI3_6 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_8, 0, 0}, // S_DORMANTARTI3_7 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI3_9, 0, 0}, // S_DORMANTARTI3_8 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_10, 0, 0}, // S_DORMANTARTI3_9 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI3_11, 0, 0}, // S_DORMANTARTI3_10 + {SPR_ACLO, 0, 21000, A_HideThing, S_DORMANTARTI3_12, 0, 0}, // S_DORMANTARTI3_11 + {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI3_13, 0, 0}, // S_DORMANTARTI3_12 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_14, 0, 0}, // S_DORMANTARTI3_13 + {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI3_15, 0, 0}, // S_DORMANTARTI3_14 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_16, 0, 0}, // S_DORMANTARTI3_15 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_17, 0, 0}, // S_DORMANTARTI3_16 + {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_18, 0, 0}, // S_DORMANTARTI3_17 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_19, 0, 0}, // S_DORMANTARTI3_18 + {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI3_20, 0, 0}, // S_DORMANTARTI3_19 + {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_21, 0, 0}, // S_DORMANTARTI3_20 + {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI3_21 + {SPR_ACLO, 3, 3, NULL, S_DEADARTI2, 0, 0}, // S_DEADARTI1 + {SPR_ACLO, 2, 3, NULL, S_DEADARTI3, 0, 0}, // S_DEADARTI2 + {SPR_ACLO, 3, 3, NULL, S_DEADARTI4, 0, 0}, // S_DEADARTI3 + {SPR_ACLO, 2, 3, NULL, S_DEADARTI5, 0, 0}, // S_DEADARTI4 + {SPR_ACLO, 1, 3, NULL, S_DEADARTI6, 0, 0}, // S_DEADARTI5 + {SPR_ACLO, 2, 3, NULL, S_DEADARTI7, 0, 0}, // S_DEADARTI6 + {SPR_ACLO, 1, 3, NULL, S_DEADARTI8, 0, 0}, // S_DEADARTI7 + {SPR_ACLO, 0, 3, NULL, S_DEADARTI9, 0, 0}, // S_DEADARTI8 + {SPR_ACLO, 1, 3, NULL, S_DEADARTI10, 0, 0}, // S_DEADARTI9 + {SPR_ACLO, 0, 3, NULL, S_NULL, 0, 0}, // S_DEADARTI10 + {SPR_PTN2, 0, 4, NULL, S_ARTI_PTN2_2, 0, 0}, // S_ARTI_PTN2_1 + {SPR_PTN2, 1, 4, NULL, S_ARTI_PTN2_3, 0, 0}, // S_ARTI_PTN2_2 + {SPR_PTN2, 2, 4, NULL, S_ARTI_PTN2_1, 0, 0}, // S_ARTI_PTN2_3 + {SPR_SOAR, 0, 5, NULL, S_ARTI_SOAR2, 0, 0}, // S_ARTI_SOAR1 + {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR3, 0, 0}, // S_ARTI_SOAR2 + {SPR_SOAR, 2, 5, NULL, S_ARTI_SOAR4, 0, 0}, // S_ARTI_SOAR3 + {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR1, 0, 0}, // S_ARTI_SOAR4 + {SPR_INVU, 0, 3, NULL, S_ARTI_INVU2, 0, 0}, // S_ARTI_INVU1 + {SPR_INVU, 1, 3, NULL, S_ARTI_INVU3, 0, 0}, // S_ARTI_INVU2 + {SPR_INVU, 2, 3, NULL, S_ARTI_INVU4, 0, 0}, // S_ARTI_INVU3 + {SPR_INVU, 3, 3, NULL, S_ARTI_INVU1, 0, 0}, // S_ARTI_INVU4 + {SPR_SUMN, 0, 350, NULL, S_ARTI_SUMMON, 0, 0}, // S_ARTI_SUMMON + {SPR_SUMN, 0, 4, NULL, S_SUMMON_FX1_1, 0, 0}, // S_SUMMON_FX1_1 + {SPR_SUMN, 0, 4, NULL, S_SUMMON_FX2_2, 0, 0}, // S_SUMMON_FX2_1 + {SPR_SUMN, 0, 4, NULL, S_SUMMON_FX2_3, 0, 0}, // S_SUMMON_FX2_2 + {SPR_SUMN, 0, 4, A_Summon, S_NULL, 0, 0}, // S_SUMMON_FX2_3 + {SPR_TSPK, 0, 3, NULL, S_THRUSTINIT2_2, 0, 0}, // S_THRUSTINIT2_1 + {SPR_TSPK, 0, 4, A_ThrustInitUp, S_THRUSTBLOCK, 0, 0}, // S_THRUSTINIT2_2 + {SPR_TSPK, 1, 3, NULL, S_BTHRUSTINIT2_2, 0, 0}, // S_BTHRUSTINIT2_1 + {SPR_TSPK, 1, 4, A_ThrustInitUp, S_BTHRUSTBLOCK, 0, 0}, // S_BTHRUSTINIT2_2 + {SPR_TSPK, 0, 3, NULL, S_THRUSTINIT1_2, 0, 0}, // S_THRUSTINIT1_1 + {SPR_TSPK, 0, 4, A_ThrustInitDn, S_THRUSTSTAY, 0, 0}, // S_THRUSTINIT1_2 + {SPR_TSPK, 1, 3, NULL, S_BTHRUSTINIT1_2, 0, 0}, // S_BTHRUSTINIT1_1 + {SPR_TSPK, 1, 4, A_ThrustInitDn, S_BTHRUSTSTAY, 0, 0}, // S_BTHRUSTINIT1_2 + {SPR_TSPK, 0, 8, A_ThrustRaise, S_THRUSTRAISE2, 0, 0}, // S_THRUSTRAISE1 + {SPR_TSPK, 0, 6, A_ThrustRaise, S_THRUSTRAISE3, 0, 0}, // S_THRUSTRAISE2 + {SPR_TSPK, 0, 4, A_ThrustRaise, S_THRUSTRAISE4, 0, 0}, // S_THRUSTRAISE3 + {SPR_TSPK, 0, 3, A_ThrustBlock, S_THRUSTIMPALE, 0, 0}, // S_THRUSTRAISE4 + {SPR_TSPK, 1, 8, A_ThrustRaise, S_BTHRUSTRAISE2, 0, 0}, // S_BTHRUSTRAISE1 + {SPR_TSPK, 1, 6, A_ThrustRaise, S_BTHRUSTRAISE3, 0, 0}, // S_BTHRUSTRAISE2 + {SPR_TSPK, 1, 4, A_ThrustRaise, S_BTHRUSTRAISE4, 0, 0}, // S_BTHRUSTRAISE3 + {SPR_TSPK, 1, 3, A_ThrustBlock, S_BTHRUSTIMPALE, 0, 0}, // S_BTHRUSTRAISE4 + {SPR_TSPK, 0, 2, A_ThrustImpale, S_THRUSTRAISE, 0, 0}, // S_THRUSTIMPALE + {SPR_TSPK, 1, 2, A_ThrustImpale, S_BTHRUSTRAISE, 0, 0}, // S_BTHRUSTIMPALE + {SPR_TSPK, 0, 2, A_ThrustRaise, S_THRUSTRAISE, 0, 0}, // S_THRUSTRAISE + {SPR_TSPK, 1, 2, A_ThrustRaise, S_BTHRUSTRAISE, 0, 0}, // S_BTHRUSTRAISE + {SPR_TSPK, 0, 10, NULL, S_THRUSTBLOCK, 0, 0}, // S_THRUSTBLOCK + {SPR_TSPK, 1, 10, NULL, S_BTHRUSTBLOCK, 0, 0}, // S_BTHRUSTBLOCK + {SPR_TSPK, 0, 2, A_ThrustLower, S_THRUSTLOWER, 0, 0}, // S_THRUSTLOWER + {SPR_TSPK, 1, 2, A_ThrustLower, S_BTHRUSTLOWER, 0, 0}, // S_BTHRUSTLOWER + {SPR_TSPK, 0, -1, NULL, S_THRUSTSTAY, 0, 0}, // S_THRUSTSTAY + {SPR_TSPK, 1, -1, NULL, S_BTHRUSTSTAY, 0, 0}, // S_BTHRUSTSTAY + {SPR_TELO, 0, 5, NULL, S_ARTI_TELOTHER2, 0, 0}, // S_ARTI_TELOTHER1 + {SPR_TELO, 1, 5, NULL, S_ARTI_TELOTHER3, 0, 0}, // S_ARTI_TELOTHER2 + {SPR_TELO, 2, 5, NULL, S_ARTI_TELOTHER4, 0, 0}, // S_ARTI_TELOTHER3 + {SPR_TELO, 3, 5, NULL, S_ARTI_TELOTHER1, 0, 0}, // S_ARTI_TELOTHER4 + {SPR_TRNG, 32772, 5, NULL, S_TELO_FX2, 0, 0}, // S_TELO_FX1 + {SPR_TRNG, 32771, 4, NULL, S_TELO_FX3, 0, 0}, // S_TELO_FX2 + {SPR_TRNG, 32770, 3, A_TeloSpawnC, S_TELO_FX4, 0, 0}, // S_TELO_FX3 + {SPR_TRNG, 32769, 3, A_TeloSpawnB, S_TELO_FX5, 0, 0}, // S_TELO_FX4 + {SPR_TRNG, 32768, 3, A_TeloSpawnA, S_TELO_FX6, 0, 0}, // S_TELO_FX5 + {SPR_TRNG, 32769, 3, A_TeloSpawnB, S_TELO_FX7, 0, 0}, // S_TELO_FX6 + {SPR_TRNG, 32770, 3, A_TeloSpawnC, S_TELO_FX8, 0, 0}, // S_TELO_FX7 + {SPR_TRNG, 32771, 3, A_TeloSpawnD, S_TELO_FX3, 0, 0}, // S_TELO_FX8 + {SPR_TRNG, 32772, 3, NULL, S_NULL, 0, 0}, // S_TELO_FX9 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX2_2, 0, 0}, // S_TELO_FX2_1 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX2_3, 0, 0}, // S_TELO_FX2_2 + {SPR_TRNG, 32771, 4, NULL, S_TELO_FX2_4, 0, 0}, // S_TELO_FX2_3 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX2_5, 0, 0}, // S_TELO_FX2_4 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX2_6, 0, 0}, // S_TELO_FX2_5 + {SPR_TRNG, 32768, 4, A_CheckTeleRing, S_TELO_FX2_1, 0, 0}, // S_TELO_FX2_6 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX3_2, 0, 0}, // S_TELO_FX3_1 + {SPR_TRNG, 32771, 4, NULL, S_TELO_FX3_3, 0, 0}, // S_TELO_FX3_2 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX3_4, 0, 0}, // S_TELO_FX3_3 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX3_5, 0, 0}, // S_TELO_FX3_4 + {SPR_TRNG, 32768, 4, NULL, S_TELO_FX3_6, 0, 0}, // S_TELO_FX3_5 + {SPR_TRNG, 32769, 4, A_CheckTeleRing, S_TELO_FX3_1, 0, 0}, // S_TELO_FX3_6 + {SPR_TRNG, 32771, 4, NULL, S_TELO_FX4_2, 0, 0}, // S_TELO_FX4_1 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX4_3, 0, 0}, // S_TELO_FX4_2 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX4_4, 0, 0}, // S_TELO_FX4_3 + {SPR_TRNG, 32768, 4, NULL, S_TELO_FX4_5, 0, 0}, // S_TELO_FX4_4 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX4_6, 0, 0}, // S_TELO_FX4_5 + {SPR_TRNG, 32770, 4, A_CheckTeleRing, S_TELO_FX4_1, 0, 0}, // S_TELO_FX4_6 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX5_2, 0, 0}, // S_TELO_FX5_1 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX5_3, 0, 0}, // S_TELO_FX5_2 + {SPR_TRNG, 32768, 4, NULL, S_TELO_FX5_4, 0, 0}, // S_TELO_FX5_3 + {SPR_TRNG, 32769, 4, NULL, S_TELO_FX5_5, 0, 0}, // S_TELO_FX5_4 + {SPR_TRNG, 32770, 4, NULL, S_TELO_FX5_6, 0, 0}, // S_TELO_FX5_5 + {SPR_TRNG, 32771, 4, A_CheckTeleRing, S_TELO_FX5_1, 0, 0}, // S_TELO_FX5_6 + {SPR_ROCK, 3, 20, NULL, S_DIRT1_1, 0, 0}, // S_DIRT1_1 + {SPR_ROCK, 3, 10, NULL, S_NULL, 0, 0}, // S_DIRT1_D + {SPR_ROCK, 4, 20, NULL, S_DIRT2_1, 0, 0}, // S_DIRT2_1 + {SPR_ROCK, 4, 10, NULL, S_NULL, 0, 0}, // S_DIRT2_D + {SPR_ROCK, 5, 20, NULL, S_DIRT3_1, 0, 0}, // S_DIRT3_1 + {SPR_ROCK, 5, 10, NULL, S_NULL, 0, 0}, // S_DIRT3_D + {SPR_ROCK, 6, 20, NULL, S_DIRT4_1, 0, 0}, // S_DIRT4_1 + {SPR_ROCK, 6, 10, NULL, S_NULL, 0, 0}, // S_DIRT4_D + {SPR_ROCK, 7, 20, NULL, S_DIRT5_1, 0, 0}, // S_DIRT5_1 + {SPR_ROCK, 7, 10, NULL, S_NULL, 0, 0}, // S_DIRT5_D + {SPR_ROCK, 8, 20, NULL, S_DIRT6_1, 0, 0}, // S_DIRT6_1 + {SPR_ROCK, 8, 10, NULL, S_NULL, 0, 0}, // S_DIRT6_D + {SPR_TSPK, 2, 20, NULL, S_DIRTCLUMP1, 0, 0}, // S_DIRTCLUMP1 + {SPR_ROCK, 0, 20, NULL, S_ROCK1_1, 0, 0}, // S_ROCK1_1 + {SPR_ROCK, 0, 10, NULL, S_NULL, 0, 0}, // S_ROCK1_D + {SPR_ROCK, 1, 20, NULL, S_ROCK2_1, 0, 0}, // S_ROCK2_1 + {SPR_ROCK, 1, 10, NULL, S_NULL, 0, 0}, // S_ROCK2_D + {SPR_ROCK, 2, 20, NULL, S_ROCK3_1, 0, 0}, // S_ROCK3_1 + {SPR_ROCK, 2, 10, NULL, S_NULL, 0, 0}, // S_ROCK3_D + {SPR_MAN1, 0, 20, A_FogSpawn, S_SPAWNFOG1, 0, 0}, // S_SPAWNFOG1 + {SPR_FOGS, 0, 7, A_FogMove, S_FOGPATCHS2, 0, 0}, // S_FOGPATCHS1 + {SPR_FOGS, 1, 7, A_FogMove, S_FOGPATCHS3, 0, 0}, // S_FOGPATCHS2 + {SPR_FOGS, 2, 7, A_FogMove, S_FOGPATCHS4, 0, 0}, // S_FOGPATCHS3 + {SPR_FOGS, 3, 7, A_FogMove, S_FOGPATCHS5, 0, 0}, // S_FOGPATCHS4 + {SPR_FOGS, 4, 7, A_FogMove, S_FOGPATCHS1, 0, 0}, // S_FOGPATCHS5 + {SPR_FOGS, 4, 5, NULL, S_NULL, 0, 0}, // S_FOGPATCHS0 + {SPR_FOGM, 0, 7, A_FogMove, S_FOGPATCHM2, 0, 0}, // S_FOGPATCHM1 + {SPR_FOGM, 1, 7, A_FogMove, S_FOGPATCHM3, 0, 0}, // S_FOGPATCHM2 + {SPR_FOGM, 2, 7, A_FogMove, S_FOGPATCHM4, 0, 0}, // S_FOGPATCHM3 + {SPR_FOGM, 3, 7, A_FogMove, S_FOGPATCHM5, 0, 0}, // S_FOGPATCHM4 + {SPR_FOGM, 4, 7, A_FogMove, S_FOGPATCHM1, 0, 0}, // S_FOGPATCHM5 + {SPR_FOGS, 0, 5, NULL, S_FOGPATCHMA, 0, 0}, // S_FOGPATCHM0 + {SPR_FOGS, 1, 5, NULL, S_FOGPATCHMB, 0, 0}, // S_FOGPATCHMA + {SPR_FOGS, 2, 5, NULL, S_FOGPATCHMC, 0, 0}, // S_FOGPATCHMB + {SPR_FOGS, 3, 5, NULL, S_FOGPATCHMD, 0, 0}, // S_FOGPATCHMC + {SPR_FOGS, 4, 5, NULL, S_FOGPATCHS0, 0, 0}, // S_FOGPATCHMD + {SPR_FOGL, 0, 7, A_FogMove, S_FOGPATCHL2, 0, 0}, // S_FOGPATCHL1 + {SPR_FOGL, 1, 7, A_FogMove, S_FOGPATCHL3, 0, 0}, // S_FOGPATCHL2 + {SPR_FOGL, 2, 7, A_FogMove, S_FOGPATCHL4, 0, 0}, // S_FOGPATCHL3 + {SPR_FOGL, 3, 7, A_FogMove, S_FOGPATCHL5, 0, 0}, // S_FOGPATCHL4 + {SPR_FOGL, 4, 7, A_FogMove, S_FOGPATCHL1, 0, 0}, // S_FOGPATCHL5 + {SPR_FOGM, 0, 4, NULL, S_FOGPATCHLA, 0, 0}, // S_FOGPATCHL0 + {SPR_FOGM, 1, 4, NULL, S_FOGPATCHLB, 0, 0}, // S_FOGPATCHLA + {SPR_FOGM, 2, 4, NULL, S_FOGPATCHLC, 0, 0}, // S_FOGPATCHLB + {SPR_FOGM, 3, 4, NULL, S_FOGPATCHLD, 0, 0}, // S_FOGPATCHLC + {SPR_FOGM, 4, 4, NULL, S_FOGPATCHM0, 0, 0}, // S_FOGPATCHLD + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE2, 0, 0}, // S_QUAKE_ACTIVE1 + {SPR_MAN1, 0, 1, A_ContMobjSound, S_QUAKE_ACTIVE3, 0, 0}, // S_QUAKE_ACTIVE2 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE4, 0, 0}, // S_QUAKE_ACTIVE3 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE5, 0, 0}, // S_QUAKE_ACTIVE4 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE6, 0, 0}, // S_QUAKE_ACTIVE5 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE7, 0, 0}, // S_QUAKE_ACTIVE6 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE8, 0, 0}, // S_QUAKE_ACTIVE7 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE9, 0, 0}, // S_QUAKE_ACTIVE8 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE0, 0, 0}, // S_QUAKE_ACTIVE9 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEA, 0, 0}, // S_QUAKE_ACTIVE0 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEB, 0, 0}, // S_QUAKE_ACTIVEA + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEC, 0, 0}, // S_QUAKE_ACTIVEB + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVED, 0, 0}, // S_QUAKE_ACTIVEC + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEE, 0, 0}, // S_QUAKE_ACTIVED + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEF, 0, 0}, // S_QUAKE_ACTIVEE + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEG, 0, 0}, // S_QUAKE_ACTIVEF + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEH, 0, 0}, // S_QUAKE_ACTIVEG + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEI, 0, 0}, // S_QUAKE_ACTIVEH + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEJ, 0, 0}, // S_QUAKE_ACTIVEI + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEK, 0, 0}, // S_QUAKE_ACTIVEJ + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEL, 0, 0}, // S_QUAKE_ACTIVEK + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEM, 0, 0}, // S_QUAKE_ACTIVEL + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEN, 0, 0}, // S_QUAKE_ACTIVEM + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEO, 0, 0}, // S_QUAKE_ACTIVEN + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEP, 0, 0}, // S_QUAKE_ACTIVEO + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEQ, 0, 0}, // S_QUAKE_ACTIVEP + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVER, 0, 0}, // S_QUAKE_ACTIVEQ + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVES, 0, 0}, // S_QUAKE_ACTIVER + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVET, 0, 0}, // S_QUAKE_ACTIVES + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEU, 0, 0}, // S_QUAKE_ACTIVET + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEV, 0, 0}, // S_QUAKE_ACTIVEU + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEW, 0, 0}, // S_QUAKE_ACTIVEV + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEX, 0, 0}, // S_QUAKE_ACTIVEW + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEY, 0, 0}, // S_QUAKE_ACTIVEX + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEZ, 0, 0}, // S_QUAKE_ACTIVEY + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT1, 0, 0}, // S_QUAKE_ACTIVEZ + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT2, 0, 0}, // S_QUAKE_ACT1 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT3, 0, 0}, // S_QUAKE_ACT2 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT4, 0, 0}, // S_QUAKE_ACT3 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT5, 0, 0}, // S_QUAKE_ACT4 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT6, 0, 0}, // S_QUAKE_ACT5 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT7, 0, 0}, // S_QUAKE_ACT6 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT8, 0, 0}, // S_QUAKE_ACT7 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT9, 0, 0}, // S_QUAKE_ACT8 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT0, 0, 0}, // S_QUAKE_ACT9 + {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE1, 0, 0}, // S_QUAKE_ACT0 + {SPR_SGSA, 0, 4, NULL, S_SGSHARD1_2, 0, 0}, // S_SGSHARD1_1 + {SPR_SGSA, 1, 4, NULL, S_SGSHARD1_3, 0, 0}, // S_SGSHARD1_2 + {SPR_SGSA, 2, 4, NULL, S_SGSHARD1_4, 0, 0}, // S_SGSHARD1_3 + {SPR_SGSA, 3, 4, NULL, S_SGSHARD1_5, 0, 0}, // S_SGSHARD1_4 + {SPR_SGSA, 4, 4, NULL, S_SGSHARD1_1, 0, 0}, // S_SGSHARD1_5 + {SPR_SGSA, 4, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD1_D + {SPR_SGSA, 5, 4, NULL, S_SGSHARD2_2, 0, 0}, // S_SGSHARD2_1 + {SPR_SGSA, 6, 4, NULL, S_SGSHARD2_3, 0, 0}, // S_SGSHARD2_2 + {SPR_SGSA, 7, 4, NULL, S_SGSHARD2_4, 0, 0}, // S_SGSHARD2_3 + {SPR_SGSA, 8, 4, NULL, S_SGSHARD2_5, 0, 0}, // S_SGSHARD2_4 + {SPR_SGSA, 9, 4, NULL, S_SGSHARD2_1, 0, 0}, // S_SGSHARD2_5 + {SPR_SGSA, 9, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD2_D + {SPR_SGSA, 10, 4, NULL, S_SGSHARD3_2, 0, 0}, // S_SGSHARD3_1 + {SPR_SGSA, 11, 4, NULL, S_SGSHARD3_3, 0, 0}, // S_SGSHARD3_2 + {SPR_SGSA, 12, 4, NULL, S_SGSHARD3_4, 0, 0}, // S_SGSHARD3_3 + {SPR_SGSA, 13, 4, NULL, S_SGSHARD3_5, 0, 0}, // S_SGSHARD3_4 + {SPR_SGSA, 14, 4, NULL, S_SGSHARD3_1, 0, 0}, // S_SGSHARD3_5 + {SPR_SGSA, 14, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD3_D + {SPR_SGSA, 15, 4, NULL, S_SGSHARD4_2, 0, 0}, // S_SGSHARD4_1 + {SPR_SGSA, 16, 4, NULL, S_SGSHARD4_3, 0, 0}, // S_SGSHARD4_2 + {SPR_SGSA, 17, 4, NULL, S_SGSHARD4_4, 0, 0}, // S_SGSHARD4_3 + {SPR_SGSA, 18, 4, NULL, S_SGSHARD4_5, 0, 0}, // S_SGSHARD4_4 + {SPR_SGSA, 19, 4, NULL, S_SGSHARD4_1, 0, 0}, // S_SGSHARD4_5 + {SPR_SGSA, 19, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD4_D + {SPR_SGSA, 20, 4, NULL, S_SGSHARD5_2, 0, 0}, // S_SGSHARD5_1 + {SPR_SGSA, 21, 4, NULL, S_SGSHARD5_3, 0, 0}, // S_SGSHARD5_2 + {SPR_SGSA, 22, 4, NULL, S_SGSHARD5_4, 0, 0}, // S_SGSHARD5_3 + {SPR_SGSA, 23, 4, NULL, S_SGSHARD5_5, 0, 0}, // S_SGSHARD5_4 + {SPR_SGSA, 24, 4, NULL, S_SGSHARD5_1, 0, 0}, // S_SGSHARD5_5 + {SPR_SGSA, 24, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD5_D + {SPR_SGSB, 0, 4, NULL, S_SGSHARD6_1, 0, 0}, // S_SGSHARD6_1 + {SPR_SGSB, 0, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD6_D + {SPR_SGSB, 1, 4, NULL, S_SGSHARD7_1, 0, 0}, // S_SGSHARD7_1 + {SPR_SGSB, 1, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD7_D + {SPR_SGSB, 2, 4, NULL, S_SGSHARD8_1, 0, 0}, // S_SGSHARD8_1 + {SPR_SGSB, 2, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD8_D + {SPR_SGSB, 3, 4, NULL, S_SGSHARD9_1, 0, 0}, // S_SGSHARD9_1 + {SPR_SGSB, 3, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD9_D + {SPR_SGSB, 4, 4, NULL, S_SGSHARD0_1, 0, 0}, // S_SGSHARD0_1 + {SPR_SGSB, 4, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD0_D + {SPR_PORK, 0, 5, NULL, S_ARTI_EGGC2, 0, 0}, // S_ARTI_EGGC1 + {SPR_PORK, 1, 5, NULL, S_ARTI_EGGC3, 0, 0}, // S_ARTI_EGGC2 + {SPR_PORK, 2, 5, NULL, S_ARTI_EGGC4, 0, 0}, // S_ARTI_EGGC3 + {SPR_PORK, 3, 5, NULL, S_ARTI_EGGC5, 0, 0}, // S_ARTI_EGGC4 + {SPR_PORK, 4, 5, NULL, S_ARTI_EGGC6, 0, 0}, // S_ARTI_EGGC5 + {SPR_PORK, 5, 5, NULL, S_ARTI_EGGC7, 0, 0}, // S_ARTI_EGGC6 + {SPR_PORK, 6, 5, NULL, S_ARTI_EGGC8, 0, 0}, // S_ARTI_EGGC7 + {SPR_PORK, 7, 5, NULL, S_ARTI_EGGC1, 0, 0}, // S_ARTI_EGGC8 + {SPR_EGGM, 0, 4, NULL, S_EGGFX2, 0, 0}, // S_EGGFX1 + {SPR_EGGM, 1, 4, NULL, S_EGGFX3, 0, 0}, // S_EGGFX2 + {SPR_EGGM, 2, 4, NULL, S_EGGFX4, 0, 0}, // S_EGGFX3 + {SPR_EGGM, 3, 4, NULL, S_EGGFX5, 0, 0}, // S_EGGFX4 + {SPR_EGGM, 4, 4, NULL, S_EGGFX1, 0, 0}, // S_EGGFX5 + {SPR_FHFX, 32776, 3, NULL, S_EGGFXI1_2, 0, 0}, // S_EGGFXI1_1 + {SPR_FHFX, 32777, 3, NULL, S_EGGFXI1_3, 0, 0}, // S_EGGFXI1_2 + {SPR_FHFX, 32778, 3, NULL, S_EGGFXI1_4, 0, 0}, // S_EGGFXI1_3 + {SPR_FHFX, 32779, 3, NULL, S_NULL, 0, 0}, // S_EGGFXI1_4 + {SPR_SPHL, 0, 350, NULL, S_ARTI_SPHL1, 0, 0}, // S_ARTI_SPHL1 + {SPR_STWN, 0, -1, NULL, S_NULL, 0, 0}, // S_ZWINGEDSTATUENOSKULL + {SPR_STWN, 1, -1, NULL, S_NULL, 0, 0}, // S_ZWINGEDSTATUENOSKULL2 + {SPR_GMPD, 0, -1, NULL, S_NULL, 0, 0}, // S_ZGEMPEDESTAL1 + {SPR_GMPD, 1, -1, NULL, S_NULL, 0, 0}, // S_ZGEMPEDESTAL2 + {SPR_ASKU, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZSKULL + {SPR_ABGM, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMBIG + {SPR_AGMR, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMRED + {SPR_AGMG, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMGREEN1 + {SPR_AGG2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMGREEN2 + {SPR_AGMB, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMBLUE1 + {SPR_AGB2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMBLUE2 + {SPR_ABK1, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZBOOK1 + {SPR_ABK2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZBOOK2 + {SPR_ASK2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZSKULL2 + {SPR_AFWP, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZFWEAPON + {SPR_ACWP, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZCWEAPON + {SPR_AMWP, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZMWEAPON + {SPR_AGER, 32768, 4, NULL, S_ARTIPUZZGEAR_2, 0, 0}, // S_ARTIPUZZGEAR_1 + {SPR_AGER, 32769, 4, NULL, S_ARTIPUZZGEAR_3, 0, 0}, // S_ARTIPUZZGEAR_2 + {SPR_AGER, 32770, 4, NULL, S_ARTIPUZZGEAR_4, 0, 0}, // S_ARTIPUZZGEAR_3 + {SPR_AGER, 32771, 4, NULL, S_ARTIPUZZGEAR_5, 0, 0}, // S_ARTIPUZZGEAR_4 + {SPR_AGER, 32772, 4, NULL, S_ARTIPUZZGEAR_6, 0, 0}, // S_ARTIPUZZGEAR_5 + {SPR_AGER, 32773, 4, NULL, S_ARTIPUZZGEAR_7, 0, 0}, // S_ARTIPUZZGEAR_6 + {SPR_AGER, 32774, 4, NULL, S_ARTIPUZZGEAR_8, 0, 0}, // S_ARTIPUZZGEAR_7 + {SPR_AGER, 32775, 4, NULL, S_ARTIPUZZGEAR_1, 0, 0}, // S_ARTIPUZZGEAR_8 + {SPR_AGR2, 32768, 4, NULL, S_ARTIPUZZGEAR2_2, 0, 0}, // S_ARTIPUZZGEAR2_1 + {SPR_AGR2, 32769, 4, NULL, S_ARTIPUZZGEAR2_3, 0, 0}, // S_ARTIPUZZGEAR2_2 + {SPR_AGR2, 32770, 4, NULL, S_ARTIPUZZGEAR2_4, 0, 0}, // S_ARTIPUZZGEAR2_3 + {SPR_AGR2, 32771, 4, NULL, S_ARTIPUZZGEAR2_5, 0, 0}, // S_ARTIPUZZGEAR2_4 + {SPR_AGR2, 32772, 4, NULL, S_ARTIPUZZGEAR2_6, 0, 0}, // S_ARTIPUZZGEAR2_5 + {SPR_AGR2, 32773, 4, NULL, S_ARTIPUZZGEAR2_7, 0, 0}, // S_ARTIPUZZGEAR2_6 + {SPR_AGR2, 32774, 4, NULL, S_ARTIPUZZGEAR2_8, 0, 0}, // S_ARTIPUZZGEAR2_7 + {SPR_AGR2, 32775, 4, NULL, S_ARTIPUZZGEAR2_1, 0, 0}, // S_ARTIPUZZGEAR2_8 + {SPR_AGR3, 32768, 4, NULL, S_ARTIPUZZGEAR3_2, 0, 0}, // S_ARTIPUZZGEAR3_1 + {SPR_AGR3, 32769, 4, NULL, S_ARTIPUZZGEAR3_3, 0, 0}, // S_ARTIPUZZGEAR3_2 + {SPR_AGR3, 32770, 4, NULL, S_ARTIPUZZGEAR3_4, 0, 0}, // S_ARTIPUZZGEAR3_3 + {SPR_AGR3, 32771, 4, NULL, S_ARTIPUZZGEAR3_5, 0, 0}, // S_ARTIPUZZGEAR3_4 + {SPR_AGR3, 32772, 4, NULL, S_ARTIPUZZGEAR3_6, 0, 0}, // S_ARTIPUZZGEAR3_5 + {SPR_AGR3, 32773, 4, NULL, S_ARTIPUZZGEAR3_7, 0, 0}, // S_ARTIPUZZGEAR3_6 + {SPR_AGR3, 32774, 4, NULL, S_ARTIPUZZGEAR3_8, 0, 0}, // S_ARTIPUZZGEAR3_7 + {SPR_AGR3, 32775, 4, NULL, S_ARTIPUZZGEAR3_1, 0, 0}, // S_ARTIPUZZGEAR3_8 + {SPR_AGR4, 32768, 4, NULL, S_ARTIPUZZGEAR4_2, 0, 0}, // S_ARTIPUZZGEAR4_1 + {SPR_AGR4, 32769, 4, NULL, S_ARTIPUZZGEAR4_3, 0, 0}, // S_ARTIPUZZGEAR4_2 + {SPR_AGR4, 32770, 4, NULL, S_ARTIPUZZGEAR4_4, 0, 0}, // S_ARTIPUZZGEAR4_3 + {SPR_AGR4, 32771, 4, NULL, S_ARTIPUZZGEAR4_5, 0, 0}, // S_ARTIPUZZGEAR4_4 + {SPR_AGR4, 32772, 4, NULL, S_ARTIPUZZGEAR4_6, 0, 0}, // S_ARTIPUZZGEAR4_5 + {SPR_AGR4, 32773, 4, NULL, S_ARTIPUZZGEAR4_7, 0, 0}, // S_ARTIPUZZGEAR4_6 + {SPR_AGR4, 32774, 4, NULL, S_ARTIPUZZGEAR4_8, 0, 0}, // S_ARTIPUZZGEAR4_7 + {SPR_AGR4, 32775, 4, NULL, S_ARTIPUZZGEAR4_1, 0, 0}, // S_ARTIPUZZGEAR4_8 + {SPR_TRCH, 32768, 3, NULL, S_ARTI_TRCH2, 0, 0}, // S_ARTI_TRCH1 + {SPR_TRCH, 32769, 3, NULL, S_ARTI_TRCH3, 0, 0}, // S_ARTI_TRCH2 + {SPR_TRCH, 32770, 3, NULL, S_ARTI_TRCH1, 0, 0}, // S_ARTI_TRCH3 + {SPR_PSBG, 0, 20, NULL, S_FIREBOMB2, 0, 0}, // S_FIREBOMB1 + {SPR_PSBG, 0, 10, NULL, S_FIREBOMB3, 0, 0}, // S_FIREBOMB2 + {SPR_PSBG, 0, 10, NULL, S_FIREBOMB4, 0, 0}, // S_FIREBOMB3 + {SPR_PSBG, 1, 4, NULL, S_FIREBOMB5, 0, 0}, // S_FIREBOMB4 + {SPR_PSBG, 2, 4, A_Scream, S_FIREBOMB6, 0, 0}, // S_FIREBOMB5 + {SPR_XPL1, 32768, 4, A_Explode, S_FIREBOMB7, 0, 0}, // S_FIREBOMB6 + {SPR_XPL1, 32769, 4, NULL, S_FIREBOMB8, 0, 0}, // S_FIREBOMB7 + {SPR_XPL1, 32770, 4, NULL, S_FIREBOMB9, 0, 0}, // S_FIREBOMB8 + {SPR_XPL1, 32771, 4, NULL, S_FIREBOMB10, 0, 0}, // S_FIREBOMB9 + {SPR_XPL1, 32772, 4, NULL, S_FIREBOMB11, 0, 0}, // S_FIREBOMB10 + {SPR_XPL1, 32773, 4, NULL, S_NULL, 0, 0}, // S_FIREBOMB11 + {SPR_ATLP, 0, 4, NULL, S_ARTI_ATLP2, 0, 0}, // S_ARTI_ATLP1 + {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP3, 0, 0}, // S_ARTI_ATLP2 + {SPR_ATLP, 2, 4, NULL, S_ARTI_ATLP4, 0, 0}, // S_ARTI_ATLP3 + {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP1, 0, 0}, // S_ARTI_ATLP4 + {SPR_PSBG, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTI_PSBG1 + {SPR_PSBG, 32768, 18, NULL, S_POISONBAG2, 0, 0}, // S_POISONBAG1 + {SPR_PSBG, 32769, 4, NULL, S_POISONBAG3, 0, 0}, // S_POISONBAG2 + {SPR_PSBG, 2, 3, NULL, S_POISONBAG4, 0, 0}, // S_POISONBAG3 + {SPR_PSBG, 2, 1, A_PoisonBagInit, S_NULL, 0, 0}, // S_POISONBAG4 + {SPR_PSBG, 3, 1, NULL, S_POISONCLOUD2, 0, 0}, // S_POISONCLOUD1 + {SPR_PSBG, 3, 1, A_Scream, S_POISONCLOUD3, 0, 0}, // S_POISONCLOUD2 + {SPR_PSBG, 3, 2, A_PoisonBagDamage, S_POISONCLOUD4, 0, 0}, // S_POISONCLOUD3 + {SPR_PSBG, 4, 2, A_PoisonBagDamage, S_POISONCLOUD5, 0, 0}, // S_POISONCLOUD4 + {SPR_PSBG, 4, 2, A_PoisonBagDamage, S_POISONCLOUD6, 0, 0}, // S_POISONCLOUD5 + {SPR_PSBG, 4, 2, A_PoisonBagDamage, S_POISONCLOUD7, 0, 0}, // S_POISONCLOUD6 + {SPR_PSBG, 5, 2, A_PoisonBagDamage, S_POISONCLOUD8, 0, 0}, // S_POISONCLOUD7 + {SPR_PSBG, 5, 2, A_PoisonBagDamage, S_POISONCLOUD9, 0, 0}, // S_POISONCLOUD8 + {SPR_PSBG, 5, 2, A_PoisonBagDamage, S_POISONCLOUD10, 0, 0}, // S_POISONCLOUD9 + {SPR_PSBG, 6, 2, A_PoisonBagDamage, S_POISONCLOUD11, 0, 0}, // S_POISONCLOUD10 + {SPR_PSBG, 6, 2, A_PoisonBagDamage, S_POISONCLOUD12, 0, 0}, // S_POISONCLOUD11 + {SPR_PSBG, 6, 2, A_PoisonBagDamage, S_POISONCLOUD13, 0, 0}, // S_POISONCLOUD12 + {SPR_PSBG, 7, 2, A_PoisonBagDamage, S_POISONCLOUD14, 0, 0}, // S_POISONCLOUD13 + {SPR_PSBG, 7, 2, A_PoisonBagDamage, S_POISONCLOUD15, 0, 0}, // S_POISONCLOUD14 + {SPR_PSBG, 7, 2, A_PoisonBagDamage, S_POISONCLOUD16, 0, 0}, // S_POISONCLOUD15 + {SPR_PSBG, 8, 2, A_PoisonBagDamage, S_POISONCLOUD17, 0, 0}, // S_POISONCLOUD16 + {SPR_PSBG, 8, 1, A_PoisonBagDamage, S_POISONCLOUD18, 0, 0}, // S_POISONCLOUD17 + {SPR_PSBG, 8, 1, A_PoisonBagCheck, S_POISONCLOUD4, 0, 0}, // S_POISONCLOUD18 + {SPR_PSBG, 7, 7, NULL, S_POISONCLOUD_X2, 0, 0}, // S_POISONCLOUD_X1 + {SPR_PSBG, 6, 7, NULL, S_POISONCLOUD_X3, 0, 0}, // S_POISONCLOUD_X2 + {SPR_PSBG, 5, 6, NULL, S_POISONCLOUD_X4, 0, 0}, // S_POISONCLOUD_X3 + {SPR_PSBG, 3, 6, NULL, S_NULL, 0, 0}, // S_POISONCLOUD_X4 + {SPR_THRW, 0, 4, A_CheckThrowBomb, S_THROWINGBOMB2, 0, 0}, // S_THROWINGBOMB1 + {SPR_THRW, 1, 3, A_CheckThrowBomb, S_THROWINGBOMB3, 0, 0}, // S_THROWINGBOMB2 + {SPR_THRW, 2, 3, A_CheckThrowBomb, S_THROWINGBOMB4, 0, 0}, // S_THROWINGBOMB3 + {SPR_THRW, 3, 3, A_CheckThrowBomb, S_THROWINGBOMB5, 0, 0}, // S_THROWINGBOMB4 + {SPR_THRW, 4, 3, A_CheckThrowBomb, S_THROWINGBOMB6, 0, 0}, // S_THROWINGBOMB5 + {SPR_THRW, 5, 3, A_CheckThrowBomb, S_THROWINGBOMB1, 0, 0}, // S_THROWINGBOMB6 + {SPR_THRW, 6, 6, A_CheckThrowBomb, S_THROWINGBOMB8, 0, 0}, // S_THROWINGBOMB7 + {SPR_THRW, 5, 4, A_CheckThrowBomb, S_THROWINGBOMB9, 0, 0}, // S_THROWINGBOMB8 + {SPR_THRW, 7, 6, A_CheckThrowBomb, S_THROWINGBOMB10, 0, 0}, // S_THROWINGBOMB9 + {SPR_THRW, 5, 4, A_CheckThrowBomb, S_THROWINGBOMB11, 0, 0}, // S_THROWINGBOMB10 + {SPR_THRW, 6, 6, A_CheckThrowBomb, S_THROWINGBOMB12, 0, 0}, // S_THROWINGBOMB11 + {SPR_THRW, 5, 3, A_CheckThrowBomb, S_THROWINGBOMB12, 0, 0}, // S_THROWINGBOMB12 + {SPR_CFCF, 32784, 4, A_NoGravity, S_THROWINGBOMB_X2, 0, 0}, // S_THROWINGBOMB_X1 + {SPR_CFCF, 32785, 3, A_Scream, S_THROWINGBOMB_X3, 0, 0}, // S_THROWINGBOMB_X2 + {SPR_CFCF, 32786, 4, A_Explode, S_THROWINGBOMB_X4, 0, 0}, // S_THROWINGBOMB_X3 + {SPR_CFCF, 32787, 3, NULL, S_THROWINGBOMB_X5, 0, 0}, // S_THROWINGBOMB_X4 + {SPR_CFCF, 32788, 4, NULL, S_THROWINGBOMB_X6, 0, 0}, // S_THROWINGBOMB_X5 + {SPR_CFCF, 32790, 3, NULL, S_THROWINGBOMB_X7, 0, 0}, // S_THROWINGBOMB_X6 + {SPR_CFCF, 32791, 4, NULL, S_THROWINGBOMB_X8, 0, 0}, // S_THROWINGBOMB_X7 + {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_THROWINGBOMB_X8 + {SPR_SPED, 32768, 3, NULL, S_ARTI_BOOTS2, 0, 0}, // S_ARTI_BOOTS1 + {SPR_SPED, 32769, 3, NULL, S_ARTI_BOOTS3, 0, 0}, // S_ARTI_BOOTS2 + {SPR_SPED, 32770, 3, NULL, S_ARTI_BOOTS4, 0, 0}, // S_ARTI_BOOTS3 + {SPR_SPED, 32771, 3, NULL, S_ARTI_BOOTS5, 0, 0}, // S_ARTI_BOOTS4 + {SPR_SPED, 32772, 3, NULL, S_ARTI_BOOTS6, 0, 0}, // S_ARTI_BOOTS5 + {SPR_SPED, 32773, 3, NULL, S_ARTI_BOOTS7, 0, 0}, // S_ARTI_BOOTS6 + {SPR_SPED, 32774, 3, NULL, S_ARTI_BOOTS8, 0, 0}, // S_ARTI_BOOTS7 + {SPR_SPED, 32775, 3, NULL, S_ARTI_BOOTS1, 0, 0}, // S_ARTI_BOOTS8 + {SPR_BMAN, 32768, -1, NULL, S_NULL, 0, 0}, // S_ARTI_MANA + {SPR_BRAC, 32768, 4, NULL, S_ARTI_ARMOR2, 0, 0}, // S_ARTI_ARMOR1 + {SPR_BRAC, 32769, 4, NULL, S_ARTI_ARMOR3, 0, 0}, // S_ARTI_ARMOR2 + {SPR_BRAC, 32770, 4, NULL, S_ARTI_ARMOR4, 0, 0}, // S_ARTI_ARMOR3 + {SPR_BRAC, 32771, 4, NULL, S_ARTI_ARMOR5, 0, 0}, // S_ARTI_ARMOR4 + {SPR_BRAC, 32772, 4, NULL, S_ARTI_ARMOR6, 0, 0}, // S_ARTI_ARMOR5 + {SPR_BRAC, 32773, 4, NULL, S_ARTI_ARMOR7, 0, 0}, // S_ARTI_ARMOR6 + {SPR_BRAC, 32774, 4, NULL, S_ARTI_ARMOR8, 0, 0}, // S_ARTI_ARMOR7 + {SPR_BRAC, 32775, 4, NULL, S_ARTI_ARMOR1, 0, 0}, // S_ARTI_ARMOR8 + {SPR_BLST, 32768, 4, NULL, S_ARTI_BLAST2, 0, 0}, // S_ARTI_BLAST1 + {SPR_BLST, 32769, 4, NULL, S_ARTI_BLAST3, 0, 0}, // S_ARTI_BLAST2 + {SPR_BLST, 32770, 4, NULL, S_ARTI_BLAST4, 0, 0}, // S_ARTI_BLAST3 + {SPR_BLST, 32771, 4, NULL, S_ARTI_BLAST5, 0, 0}, // S_ARTI_BLAST4 + {SPR_BLST, 32772, 4, NULL, S_ARTI_BLAST6, 0, 0}, // S_ARTI_BLAST5 + {SPR_BLST, 32773, 4, NULL, S_ARTI_BLAST7, 0, 0}, // S_ARTI_BLAST6 + {SPR_BLST, 32774, 4, NULL, S_ARTI_BLAST8, 0, 0}, // S_ARTI_BLAST7 + {SPR_BLST, 32775, 4, NULL, S_ARTI_BLAST1, 0, 0}, // S_ARTI_BLAST8 + {SPR_HRAD, 32768, 4, NULL, S_ARTI_HEALRAD2, 0, 0}, // S_ARTI_HEALRAD1 + {SPR_HRAD, 32769, 4, NULL, S_ARTI_HEALRAD3, 0, 0}, // S_ARTI_HEALRAD2 + {SPR_HRAD, 32770, 4, NULL, S_ARTI_HEALRAD4, 0, 0}, // S_ARTI_HEALRAD3 + {SPR_HRAD, 32771, 4, NULL, S_ARTI_HEALRAD5, 0, 0}, // S_ARTI_HEALRAD4 + {SPR_HRAD, 32772, 4, NULL, S_ARTI_HEALRAD6, 0, 0}, // S_ARTI_HEALRAD5 + {SPR_HRAD, 32773, 4, NULL, S_ARTI_HEALRAD7, 0, 0}, // S_ARTI_HEALRAD6 + {SPR_HRAD, 32774, 4, NULL, S_ARTI_HEALRAD8, 0, 0}, // S_ARTI_HEALRAD7 + {SPR_HRAD, 32775, 4, NULL, S_ARTI_HEALRAD9, 0, 0}, // S_ARTI_HEALRAD8 + {SPR_HRAD, 32776, 4, NULL, S_ARTI_HEALRAD0, 0, 0}, // S_ARTI_HEALRAD9 + {SPR_HRAD, 32777, 4, NULL, S_ARTI_HEALRADA, 0, 0}, // S_ARTI_HEALRAD0 + {SPR_HRAD, 32778, 4, NULL, S_ARTI_HEALRADB, 0, 0}, // S_ARTI_HEALRADA + {SPR_HRAD, 32779, 4, NULL, S_ARTI_HEALRADC, 0, 0}, // S_ARTI_HEALRADB + {SPR_HRAD, 32780, 4, NULL, S_ARTI_HEALRADD, 0, 0}, // S_ARTI_HEALRADC + {SPR_HRAD, 32781, 4, NULL, S_ARTI_HEALRADE, 0, 0}, // S_ARTI_HEALRADD + {SPR_HRAD, 32782, 4, NULL, S_ARTI_HEALRADF, 0, 0}, // S_ARTI_HEALRADE + {SPR_HRAD, 32783, 4, NULL, S_ARTI_HEALRAD1, 0, 0}, // S_ARTI_HEALRADF + {SPR_SPSH, 0, 8, NULL, S_SPLASH2, 0, 0}, // S_SPLASH1 + {SPR_SPSH, 1, 8, NULL, S_SPLASH3, 0, 0}, // S_SPLASH2 + {SPR_SPSH, 2, 8, NULL, S_SPLASH4, 0, 0}, // S_SPLASH3 + {SPR_SPSH, 3, 16, NULL, S_NULL, 0, 0}, // S_SPLASH4 + {SPR_SPSH, 3, 10, NULL, S_NULL, 0, 0}, // S_SPLASHX + {SPR_SPSH, 4, 5, NULL, S_SPLASHBASE2, 0, 0}, // S_SPLASHBASE1 + {SPR_SPSH, 5, 5, NULL, S_SPLASHBASE3, 0, 0}, // S_SPLASHBASE2 + {SPR_SPSH, 6, 5, NULL, S_SPLASHBASE4, 0, 0}, // S_SPLASHBASE3 + {SPR_SPSH, 7, 5, NULL, S_SPLASHBASE5, 0, 0}, // S_SPLASHBASE4 + {SPR_SPSH, 8, 5, NULL, S_SPLASHBASE6, 0, 0}, // S_SPLASHBASE5 + {SPR_SPSH, 9, 5, NULL, S_SPLASHBASE7, 0, 0}, // S_SPLASHBASE6 + {SPR_SPSH, 10, 5, NULL, S_NULL, 0, 0}, // S_SPLASHBASE7 + {SPR_LVAS, 32768, 5, NULL, S_LAVASPLASH2, 0, 0}, // S_LAVASPLASH1 + {SPR_LVAS, 32769, 5, NULL, S_LAVASPLASH3, 0, 0}, // S_LAVASPLASH2 + {SPR_LVAS, 32770, 5, NULL, S_LAVASPLASH4, 0, 0}, // S_LAVASPLASH3 + {SPR_LVAS, 32771, 5, NULL, S_LAVASPLASH5, 0, 0}, // S_LAVASPLASH4 + {SPR_LVAS, 32772, 5, NULL, S_LAVASPLASH6, 0, 0}, // S_LAVASPLASH5 + {SPR_LVAS, 32773, 5, NULL, S_NULL, 0, 0}, // S_LAVASPLASH6 + {SPR_LVAS, 32774, 5, NULL, S_LAVASMOKE2, 0, 0}, // S_LAVASMOKE1 + {SPR_LVAS, 32775, 5, NULL, S_LAVASMOKE3, 0, 0}, // S_LAVASMOKE2 + {SPR_LVAS, 32776, 5, NULL, S_LAVASMOKE4, 0, 0}, // S_LAVASMOKE3 + {SPR_LVAS, 32777, 5, NULL, S_LAVASMOKE5, 0, 0}, // S_LAVASMOKE4 + {SPR_LVAS, 32778, 5, NULL, S_NULL, 0, 0}, // S_LAVASMOKE5 + {SPR_SLDG, 0, 8, NULL, S_SLUDGECHUNK2, 0, 0}, // S_SLUDGECHUNK1 + {SPR_SLDG, 1, 8, NULL, S_SLUDGECHUNK3, 0, 0}, // S_SLUDGECHUNK2 + {SPR_SLDG, 2, 8, NULL, S_SLUDGECHUNK4, 0, 0}, // S_SLUDGECHUNK3 + {SPR_SLDG, 3, 8, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNK4 + {SPR_SLDG, 3, 6, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNKX + {SPR_SLDG, 4, 6, NULL, S_SLUDGESPLASH2, 0, 0}, // S_SLUDGESPLASH1 + {SPR_SLDG, 5, 6, NULL, S_SLUDGESPLASH3, 0, 0}, // S_SLUDGESPLASH2 + {SPR_SLDG, 6, 6, NULL, S_SLUDGESPLASH4, 0, 0}, // S_SLUDGESPLASH3 + {SPR_SLDG, 7, 6, NULL, S_NULL, 0, 0}, // S_SLUDGESPLASH4 + {SPR_STTW, 0, -1, NULL, S_NULL, 0, 0}, // S_ZWINGEDSTATUE1 + {SPR_RCK1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK1_1 + {SPR_RCK2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK2_1 + {SPR_RCK3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK3_1 + {SPR_RCK4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK4_1 + {SPR_CDLR, 0, 4, NULL, S_ZCHANDELIER2, 0, 0}, // S_ZCHANDELIER1 + {SPR_CDLR, 1, 4, NULL, S_ZCHANDELIER3, 0, 0}, // S_ZCHANDELIER2 + {SPR_CDLR, 2, 4, NULL, S_ZCHANDELIER1, 0, 0}, // S_ZCHANDELIER3 + {SPR_CDLR, 3, -1, NULL, S_NULL, 0, 0}, // S_ZCHANDELIER_U + {SPR_TRE1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDEAD1 + {SPR_TRE1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREE + {SPR_TRDT, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDESTRUCTIBLE1 + {SPR_TRDT, 1, 5, NULL, S_ZTREEDES_D2, 0, 0}, // S_ZTREEDES_D1 + {SPR_TRDT, 2, 5, A_Scream, S_ZTREEDES_D3, 0, 0}, // S_ZTREEDES_D2 + {SPR_TRDT, 3, 5, NULL, S_ZTREEDES_D4, 0, 0}, // S_ZTREEDES_D3 + {SPR_TRDT, 4, 5, NULL, S_ZTREEDES_D5, 0, 0}, // S_ZTREEDES_D4 + {SPR_TRDT, 5, 5, NULL, S_ZTREEDES_D6, 0, 0}, // S_ZTREEDES_D5 + {SPR_TRDT, 6, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDES_D6 + {SPR_TRDT, 32775, 5, NULL, S_ZTREEDES_X2, 0, 0}, // S_ZTREEDES_X1 + {SPR_TRDT, 32776, 5, NULL, S_ZTREEDES_X3, 0, 0}, // S_ZTREEDES_X2 + {SPR_TRDT, 32777, 5, NULL, S_ZTREEDES_X4, 0, 0}, // S_ZTREEDES_X3 + {SPR_TRDT, 32778, 5, NULL, S_ZTREEDES_X5, 0, 0}, // S_ZTREEDES_X4 + {SPR_TRDT, 32779, 5, NULL, S_ZTREEDES_X6, 0, 0}, // S_ZTREEDES_X5 + {SPR_TRDT, 32780, 5, A_Explode, S_ZTREEDES_X7, 0, 0}, // S_ZTREEDES_X6 + {SPR_TRDT, 32781, 5, NULL, S_ZTREEDES_X8, 0, 0}, // S_ZTREEDES_X7 + {SPR_TRDT, 14, 5, NULL, S_ZTREEDES_X9, 0, 0}, // S_ZTREEDES_X8 + {SPR_TRDT, 15, 5, NULL, S_ZTREEDES_X10, 0, 0}, // S_ZTREEDES_X9 + {SPR_TRDT, 16, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDES_X10 + {SPR_TRE2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREESWAMP182_1 + {SPR_TRE3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREESWAMP172_1 + {SPR_STM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPBURNED1 + {SPR_STM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPBARE1 + {SPR_STM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPSWAMP1_1 + {SPR_STM4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPSWAMP2_1 + {SPR_MSH1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMLARGE1_1 + {SPR_MSH2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMLARGE2_1 + {SPR_MSH3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMLARGE3_1 + {SPR_MSH4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL1_1 + {SPR_MSH5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL2_1 + {SPR_MSH6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL3_1 + {SPR_MSH7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL4_1 + {SPR_MSH8, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL5_1 + {SPR_SGMP, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEPILLAR1 + {SPR_SGM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITELARGE1 + {SPR_SGM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEMEDIUM1 + {SPR_SGM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITESMALL1 + {SPR_SLC1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITELARGE1 + {SPR_SLC2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEMEDIUM1 + {SPR_SLC3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITESMALL1 + {SPR_MSS1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZMOSSCEILING1_1 + {SPR_MSS2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZMOSSCEILING2_1 + {SPR_SWMV, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSWAMPVINE1 + {SPR_CPS1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSEKABOB1 + {SPR_CPS2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSESLEEPING1 + {SPR_TMS1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONERIP1 + {SPR_TMS2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONESHANE1 + {SPR_TMS3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONEBIGCROSS1 + {SPR_TMS4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONEBRIANR1 + {SPR_TMS5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONECROSSCIRCLE1 + {SPR_TMS6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONESMALLCROSS1 + {SPR_TMS7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONEBRIANP1 + {SPR_CPS3, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEHANGING_1 + {SPR_STT2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEGREENTALL_1 + {SPR_STT3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEBLUETALL_1 + {SPR_STT4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEGREENSHORT_1 + {SPR_STT5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEBLUESHORT_1 + {SPR_GAR1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLESTRIPETALL_1 + {SPR_GAR2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEDARKREDTALL_1 + {SPR_GAR3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEREDTALL_1 + {SPR_GAR4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLETANTALL_1 + {SPR_GAR5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLERUSTTALL_1 + {SPR_GAR6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEDARKREDSHORT_1 + {SPR_GAR7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEREDSHORT_1 + {SPR_GAR8, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLETANSHORT_1 + {SPR_GAR9, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLERUSTSHORT_1 + {SPR_BNR1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZBANNERTATTERED_1 + {SPR_TRE4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREELARGE1 + {SPR_TRE5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREELARGE2 + {SPR_TRE6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEGNARLED1 + {SPR_TRE7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEGNARLED2 + {SPR_LOGG, 0, -1, NULL, S_NULL, 0, 0}, // S_ZLOG + {SPR_ICT1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICELARGE + {SPR_ICT2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICEMEDIUM + {SPR_ICT3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICESMALL + {SPR_ICT4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICETINY + {SPR_ICM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICELARGE + {SPR_ICM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICEMEDIUM + {SPR_ICM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICESMALL + {SPR_ICM4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICETINY + {SPR_RKBL, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCKBROWN1 + {SPR_RKBS, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCKBROWN2 + {SPR_RKBK, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCKBLACK + {SPR_RBL1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZRUBBLE1 + {SPR_RBL2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZRUBBLE2 + {SPR_RBL3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZRUBBLE3 + {SPR_VASE, 0, -1, NULL, S_NULL, 0, 0}, // S_ZVASEPILLAR + {SPR_POT1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZPOTTERY1 + {SPR_POT2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZPOTTERY2 + {SPR_POT3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZPOTTERY3 + {SPR_POT1, 0, 0, A_PotteryExplode, S_NULL, 0, 0}, // S_ZPOTTERY_EXPLODE + {SPR_PBIT, 0, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_1 + {SPR_PBIT, 1, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_2 + {SPR_PBIT, 2, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_3 + {SPR_PBIT, 3, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_4 + {SPR_PBIT, 4, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_5 + {SPR_PBIT, 5, 0, A_PotteryChooseBit, S_NULL, 0, 0}, // S_POTTERYBIT_EX0 + {SPR_PBIT, 5, 140, NULL, S_POTTERYBIT_EX1_2, 0, 0}, // S_POTTERYBIT_EX1 + {SPR_PBIT, 5, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX1_2 + {SPR_PBIT, 6, 140, NULL, S_POTTERYBIT_EX2_2, 0, 0}, // S_POTTERYBIT_EX2 + {SPR_PBIT, 6, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX2_2 + {SPR_PBIT, 7, 140, NULL, S_POTTERYBIT_EX3_2, 0, 0}, // S_POTTERYBIT_EX3 + {SPR_PBIT, 7, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX3_2 + {SPR_PBIT, 8, 140, NULL, S_POTTERYBIT_EX4_2, 0, 0}, // S_POTTERYBIT_EX4 + {SPR_PBIT, 8, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX4_2 + {SPR_PBIT, 9, 140, NULL, S_POTTERYBIT_EX5_2, 0, 0}, // S_POTTERYBIT_EX5 + {SPR_PBIT, 9, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX5_2 + {SPR_CPS4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSELYNCHED1 + {SPR_CPS5, 0, 140, A_CorpseBloodDrip, S_ZCORPSELYNCHED2, 0, 0}, // S_ZCORPSELYNCHED2 + {SPR_CPS6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSESITTING + {SPR_CPS6, 0, 1, A_CorpseExplode, S_NULL, 0, 0}, // S_ZCORPSESITTING_X + {SPR_CPB1, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_1 + {SPR_CPB2, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_2 + {SPR_CPB3, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_3 + {SPR_CPB4, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_4 + {SPR_BDRP, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBLOODDRIP + {SPR_BDSH, 0, 3, NULL, S_CORPSEBLOODDRIP_X2, 0, 0}, // S_CORPSEBLOODDRIP_X1 + {SPR_BDSH, 1, 3, NULL, S_CORPSEBLOODDRIP_X3, 0, 0}, // S_CORPSEBLOODDRIP_X2 + {SPR_BDSH, 2, 2, NULL, S_CORPSEBLOODDRIP_X4, 0, 0}, // S_CORPSEBLOODDRIP_X3 + {SPR_BDSH, 3, 2, NULL, S_NULL, 0, 0}, // S_CORPSEBLOODDRIP_X4 + {SPR_BDPL, 0, -1, NULL, S_NULL, 0, 0}, // S_BLOODPOOL + {SPR_CNDL, 32768, 4, NULL, S_ZCANDLE2, 0, 0}, // S_ZCANDLE1 + {SPR_CNDL, 32769, 4, NULL, S_ZCANDLE3, 0, 0}, // S_ZCANDLE2 + {SPR_CNDL, 32770, 4, NULL, S_ZCANDLE1, 0, 0}, // S_ZCANDLE3 + {SPR_MAN1, 0, 20, A_LeafSpawn, S_ZLEAFSPAWNER, 0, 0}, // S_ZLEAFSPAWNER + {SPR_LEF1, 0, 4, NULL, S_LEAF1_2, 0, 0}, // S_LEAF1_1 + {SPR_LEF1, 1, 4, NULL, S_LEAF1_3, 0, 0}, // S_LEAF1_2 + {SPR_LEF1, 2, 4, NULL, S_LEAF1_4, 0, 0}, // S_LEAF1_3 + {SPR_LEF1, 3, 4, A_LeafThrust, S_LEAF1_5, 0, 0}, // S_LEAF1_4 + {SPR_LEF1, 4, 4, NULL, S_LEAF1_6, 0, 0}, // S_LEAF1_5 + {SPR_LEF1, 5, 4, NULL, S_LEAF1_7, 0, 0}, // S_LEAF1_6 + {SPR_LEF1, 6, 4, NULL, S_LEAF1_8, 0, 0}, // S_LEAF1_7 + {SPR_LEF1, 7, 4, A_LeafThrust, S_LEAF1_9, 0, 0}, // S_LEAF1_8 + {SPR_LEF1, 8, 4, NULL, S_LEAF1_10, 0, 0}, // S_LEAF1_9 + {SPR_LEF1, 0, 4, NULL, S_LEAF1_11, 0, 0}, // S_LEAF1_10 + {SPR_LEF1, 1, 4, NULL, S_LEAF1_12, 0, 0}, // S_LEAF1_11 + {SPR_LEF1, 2, 4, A_LeafThrust, S_LEAF1_13, 0, 0}, // S_LEAF1_12 + {SPR_LEF1, 3, 4, NULL, S_LEAF1_14, 0, 0}, // S_LEAF1_13 + {SPR_LEF1, 4, 4, NULL, S_LEAF1_15, 0, 0}, // S_LEAF1_14 + {SPR_LEF1, 5, 4, NULL, S_LEAF1_16, 0, 0}, // S_LEAF1_15 + {SPR_LEF1, 6, 4, A_LeafThrust, S_LEAF1_17, 0, 0}, // S_LEAF1_16 + {SPR_LEF1, 7, 4, NULL, S_LEAF1_18, 0, 0}, // S_LEAF1_17 + {SPR_LEF1, 8, 4, NULL, S_NULL, 0, 0}, // S_LEAF1_18 + {SPR_LEF3, 3, 10, A_LeafCheck, S_LEAF_X1, 0, 0}, // S_LEAF_X1 + {SPR_LEF2, 0, 4, NULL, S_LEAF2_2, 0, 0}, // S_LEAF2_1 + {SPR_LEF2, 1, 4, NULL, S_LEAF2_3, 0, 0}, // S_LEAF2_2 + {SPR_LEF2, 2, 4, NULL, S_LEAF2_4, 0, 0}, // S_LEAF2_3 + {SPR_LEF2, 3, 4, A_LeafThrust, S_LEAF2_5, 0, 0}, // S_LEAF2_4 + {SPR_LEF2, 4, 4, NULL, S_LEAF2_6, 0, 0}, // S_LEAF2_5 + {SPR_LEF2, 5, 4, NULL, S_LEAF2_7, 0, 0}, // S_LEAF2_6 + {SPR_LEF2, 6, 4, NULL, S_LEAF2_8, 0, 0}, // S_LEAF2_7 + {SPR_LEF2, 7, 4, A_LeafThrust, S_LEAF2_9, 0, 0}, // S_LEAF2_8 + {SPR_LEF2, 8, 4, NULL, S_LEAF2_10, 0, 0}, // S_LEAF2_9 + {SPR_LEF2, 0, 4, NULL, S_LEAF2_11, 0, 0}, // S_LEAF2_10 + {SPR_LEF2, 1, 4, NULL, S_LEAF2_12, 0, 0}, // S_LEAF2_11 + {SPR_LEF2, 2, 4, A_LeafThrust, S_LEAF2_13, 0, 0}, // S_LEAF2_12 + {SPR_LEF2, 3, 4, NULL, S_LEAF2_14, 0, 0}, // S_LEAF2_13 + {SPR_LEF2, 4, 4, NULL, S_LEAF2_15, 0, 0}, // S_LEAF2_14 + {SPR_LEF2, 5, 4, NULL, S_LEAF2_16, 0, 0}, // S_LEAF2_15 + {SPR_LEF2, 6, 4, A_LeafThrust, S_LEAF2_17, 0, 0}, // S_LEAF2_16 + {SPR_LEF2, 7, 4, NULL, S_LEAF2_18, 0, 0}, // S_LEAF2_17 + {SPR_LEF2, 8, 4, NULL, S_NULL, 0, 0}, // S_LEAF2_18 + {SPR_TWTR, 32768, 4, NULL, S_ZTWINEDTORCH_2, 0, 0}, // S_ZTWINEDTORCH_1 + {SPR_TWTR, 32769, 4, NULL, S_ZTWINEDTORCH_3, 0, 0}, // S_ZTWINEDTORCH_2 + {SPR_TWTR, 32770, 4, NULL, S_ZTWINEDTORCH_4, 0, 0}, // S_ZTWINEDTORCH_3 + {SPR_TWTR, 32771, 4, NULL, S_ZTWINEDTORCH_5, 0, 0}, // S_ZTWINEDTORCH_4 + {SPR_TWTR, 32772, 4, NULL, S_ZTWINEDTORCH_6, 0, 0}, // S_ZTWINEDTORCH_5 + {SPR_TWTR, 32773, 4, NULL, S_ZTWINEDTORCH_7, 0, 0}, // S_ZTWINEDTORCH_6 + {SPR_TWTR, 32774, 4, NULL, S_ZTWINEDTORCH_8, 0, 0}, // S_ZTWINEDTORCH_7 + {SPR_TWTR, 32775, 4, NULL, S_ZTWINEDTORCH_1, 0, 0}, // S_ZTWINEDTORCH_8 + {SPR_TWTR, 8, -1, NULL, S_NULL, 0, 0}, // S_ZTWINEDTORCH_UNLIT + {SPR_TLGL, 0, 2, NULL, S_BRIDGE2, 0, 0}, // S_BRIDGE1 + {SPR_TLGL, 0, 2, A_BridgeInit, S_BRIDGE3, 0, 0}, // S_BRIDGE2 + {SPR_TLGL, 0, -1, NULL, S_NULL, 0, 0}, // S_BRIDGE3 + {SPR_TLGL, 0, 2, NULL, S_FREE_BRIDGE2, 0, 0}, // S_FREE_BRIDGE1 + {SPR_TLGL, 0, 300, NULL, S_NULL, 0, 0}, // S_FREE_BRIDGE2 + {SPR_TLGL, 0, 2, NULL, S_BBALL2, 0, 0}, // S_BBALL1 + {SPR_TLGL, 0, 5, A_BridgeOrbit, S_BBALL2, 0, 0}, // S_BBALL2 + {SPR_WLTR, 32768, 5, NULL, S_ZWALLTORCH2, 0, 0}, // S_ZWALLTORCH1 + {SPR_WLTR, 32769, 5, NULL, S_ZWALLTORCH3, 0, 0}, // S_ZWALLTORCH2 + {SPR_WLTR, 32770, 5, NULL, S_ZWALLTORCH4, 0, 0}, // S_ZWALLTORCH3 + {SPR_WLTR, 32771, 5, NULL, S_ZWALLTORCH5, 0, 0}, // S_ZWALLTORCH4 + {SPR_WLTR, 32772, 5, NULL, S_ZWALLTORCH6, 0, 0}, // S_ZWALLTORCH5 + {SPR_WLTR, 32773, 5, NULL, S_ZWALLTORCH7, 0, 0}, // S_ZWALLTORCH6 + {SPR_WLTR, 32774, 5, NULL, S_ZWALLTORCH8, 0, 0}, // S_ZWALLTORCH7 + {SPR_WLTR, 32775, 5, NULL, S_ZWALLTORCH1, 0, 0}, // S_ZWALLTORCH8 + {SPR_WLTR, 8, -1, NULL, S_NULL, 0, 0}, // S_ZWALLTORCH_U + {SPR_BARL, 0, -1, NULL, S_NULL, 0, 0}, // S_ZBARREL1 + {SPR_SHB1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHRUB1 + {SPR_SHB1, 0, 1, A_TreeDeath, S_ZSHRUB1, 0, 0}, // S_ZSHRUB1_DIE + {SPR_SHB1, 32769, 7, NULL, S_ZSHRUB1_X2, 0, 0}, // S_ZSHRUB1_X1 + {SPR_SHB1, 32770, 6, A_Scream, S_ZSHRUB1_X3, 0, 0}, // S_ZSHRUB1_X2 + {SPR_SHB1, 32771, 5, NULL, S_NULL, 0, 0}, // S_ZSHRUB1_X3 + {SPR_SHB2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHRUB2 + {SPR_SHB2, 0, 1, A_TreeDeath, S_ZSHRUB2, 0, 0}, // S_ZSHRUB2_DIE + {SPR_SHB2, 32769, 7, NULL, S_ZSHRUB2_X2, 0, 0}, // S_ZSHRUB2_X1 + {SPR_SHB2, 32770, 6, A_Scream, S_ZSHRUB2_X3, 0, 0}, // S_ZSHRUB2_X2 + {SPR_SHB2, 32771, 5, A_Explode, S_ZSHRUB2_X4, 0, 0}, // S_ZSHRUB2_X3 + {SPR_SHB2, 32772, 5, NULL, S_NULL, 0, 0}, // S_ZSHRUB2_X4 + {SPR_BCKT, 0, -1, NULL, S_NULL, 0, 0}, // S_ZBUCKET1 + {SPR_SHRM, 0, 5, A_PoisonShroom, S_ZPOISONSHROOM_P2, 0, 0}, // S_ZPOISONSHROOM1 + {SPR_SHRM, 0, 6, NULL, S_ZPOISONSHROOM_P2, 0, 0}, // S_ZPOISONSHROOM_P1 + {SPR_SHRM, 1, 8, A_Pain, S_ZPOISONSHROOM1, 0, 0}, // S_ZPOISONSHROOM_P2 + {SPR_SHRM, 2, 5, NULL, S_ZPOISONSHROOM_X2, 0, 0}, // S_ZPOISONSHROOM_X1 + {SPR_SHRM, 3, 5, NULL, S_ZPOISONSHROOM_X3, 0, 0}, // S_ZPOISONSHROOM_X2 + {SPR_SHRM, 4, 5, A_PoisonBagInit, S_ZPOISONSHROOM_X4, 0, 0}, // S_ZPOISONSHROOM_X3 + {SPR_SHRM, 5, -1, NULL, S_NULL, 0, 0}, // S_ZPOISONSHROOM_X4 + {SPR_FBUL, 32768, 4, NULL, S_ZFIREBULL2, 0, 0}, // S_ZFIREBULL1 + {SPR_FBUL, 32769, 4, NULL, S_ZFIREBULL3, 0, 0}, // S_ZFIREBULL2 + {SPR_FBUL, 32770, 4, NULL, S_ZFIREBULL4, 0, 0}, // S_ZFIREBULL3 + {SPR_FBUL, 32771, 4, NULL, S_ZFIREBULL5, 0, 0}, // S_ZFIREBULL4 + {SPR_FBUL, 32772, 4, NULL, S_ZFIREBULL6, 0, 0}, // S_ZFIREBULL5 + {SPR_FBUL, 32773, 4, NULL, S_ZFIREBULL7, 0, 0}, // S_ZFIREBULL6 + {SPR_FBUL, 32774, 4, NULL, S_ZFIREBULL1, 0, 0}, // S_ZFIREBULL7 + {SPR_FBUL, 32777, 4, NULL, S_ZFIREBULL_DEATH2, 0, 0}, // S_ZFIREBULL_DEATH + {SPR_FBUL, 32776, 4, NULL, S_ZFIREBULL_U, 0, 0}, // S_ZFIREBULL_DEATH2 + {SPR_FBUL, 7, -1, NULL, S_NULL, 0, 0}, // S_ZFIREBULL_U + {SPR_FBUL, 32776, 4, NULL, S_ZFIREBULL_BIRTH2, 0, 0}, // S_ZFIREBULL_BIRTH + {SPR_FBUL, 32777, 4, NULL, S_ZFIREBULL1, 0, 0}, // S_ZFIREBULL_BIRTH2 + {SPR_FSKL, 32768, 4, NULL, S_ZFIRETHING2, 0, 0}, // S_ZFIRETHING1 + {SPR_FSKL, 32769, 3, NULL, S_ZFIRETHING3, 0, 0}, // S_ZFIRETHING2 + {SPR_FSKL, 32770, 4, NULL, S_ZFIRETHING4, 0, 0}, // S_ZFIRETHING3 + {SPR_FSKL, 32771, 3, NULL, S_ZFIRETHING5, 0, 0}, // S_ZFIRETHING4 + {SPR_FSKL, 32772, 4, NULL, S_ZFIRETHING6, 0, 0}, // S_ZFIRETHING5 + {SPR_FSKL, 32773, 3, NULL, S_ZFIRETHING7, 0, 0}, // S_ZFIRETHING6 + {SPR_FSKL, 32774, 4, NULL, S_ZFIRETHING8, 0, 0}, // S_ZFIRETHING7 + {SPR_FSKL, 32775, 3, NULL, S_ZFIRETHING9, 0, 0}, // S_ZFIRETHING8 + {SPR_FSKL, 32776, 4, NULL, S_ZFIRETHING1, 0, 0}, // S_ZFIRETHING9 + {SPR_BRTR, 32768, 4, NULL, S_ZBRASSTORCH2, 0, 0}, // S_ZBRASSTORCH1 + {SPR_BRTR, 32769, 4, NULL, S_ZBRASSTORCH3, 0, 0}, // S_ZBRASSTORCH2 + {SPR_BRTR, 32770, 4, NULL, S_ZBRASSTORCH4, 0, 0}, // S_ZBRASSTORCH3 + {SPR_BRTR, 32771, 4, NULL, S_ZBRASSTORCH5, 0, 0}, // S_ZBRASSTORCH4 + {SPR_BRTR, 32772, 4, NULL, S_ZBRASSTORCH6, 0, 0}, // S_ZBRASSTORCH5 + {SPR_BRTR, 32773, 4, NULL, S_ZBRASSTORCH7, 0, 0}, // S_ZBRASSTORCH6 + {SPR_BRTR, 32774, 4, NULL, S_ZBRASSTORCH8, 0, 0}, // S_ZBRASSTORCH7 + {SPR_BRTR, 32775, 4, NULL, S_ZBRASSTORCH9, 0, 0}, // S_ZBRASSTORCH8 + {SPR_BRTR, 32776, 4, NULL, S_ZBRASSTORCH10, 0, 0}, // S_ZBRASSTORCH9 + {SPR_BRTR, 32777, 4, NULL, S_ZBRASSTORCH11, 0, 0}, // S_ZBRASSTORCH10 + {SPR_BRTR, 32778, 4, NULL, S_ZBRASSTORCH12, 0, 0}, // S_ZBRASSTORCH11 + {SPR_BRTR, 32779, 4, NULL, S_ZBRASSTORCH13, 0, 0}, // S_ZBRASSTORCH12 + {SPR_BRTR, 32780, 4, NULL, S_ZBRASSTORCH1, 0, 0}, // S_ZBRASSTORCH13 + {SPR_SUIT, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSUITOFARMOR + {SPR_SUIT, 0, 1, A_SoAExplode, S_NULL, 0, 0}, // S_ZSUITOFARMOR_X1 + {SPR_SUIT, 1, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK1 + {SPR_SUIT, 2, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK2 + {SPR_SUIT, 3, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK3 + {SPR_SUIT, 4, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK4 + {SPR_SUIT, 5, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK5 + {SPR_SUIT, 6, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK6 + {SPR_SUIT, 7, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK7 + {SPR_SUIT, 8, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK8 + {SPR_SUIT, 9, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK9 + {SPR_SUIT, 10, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK10 + {SPR_BBLL, 5, -1, NULL, S_NULL, 0, 0}, // S_ZBELL + {SPR_BBLL, 0, 4, A_BellReset1, S_ZBELL_X2, 0, 0}, // S_ZBELL_X1 + {SPR_BBLL, 1, 4, NULL, S_ZBELL_X3, 0, 0}, // S_ZBELL_X2 + {SPR_BBLL, 2, 4, NULL, S_ZBELL_X4, 0, 0}, // S_ZBELL_X3 + {SPR_BBLL, 3, 5, A_Scream, S_ZBELL_X5, 0, 0}, // S_ZBELL_X4 + {SPR_BBLL, 2, 4, NULL, S_ZBELL_X6, 0, 0}, // S_ZBELL_X5 + {SPR_BBLL, 1, 4, NULL, S_ZBELL_X7, 0, 0}, // S_ZBELL_X6 + {SPR_BBLL, 0, 3, NULL, S_ZBELL_X8, 0, 0}, // S_ZBELL_X7 + {SPR_BBLL, 4, 4, NULL, S_ZBELL_X9, 0, 0}, // S_ZBELL_X8 + {SPR_BBLL, 5, 5, NULL, S_ZBELL_X10, 0, 0}, // S_ZBELL_X9 + {SPR_BBLL, 6, 6, A_Scream, S_ZBELL_X11, 0, 0}, // S_ZBELL_X10 + {SPR_BBLL, 5, 5, NULL, S_ZBELL_X12, 0, 0}, // S_ZBELL_X11 + {SPR_BBLL, 4, 4, NULL, S_ZBELL_X13, 0, 0}, // S_ZBELL_X12 + {SPR_BBLL, 0, 4, NULL, S_ZBELL_X14, 0, 0}, // S_ZBELL_X13 + {SPR_BBLL, 1, 5, NULL, S_ZBELL_X15, 0, 0}, // S_ZBELL_X14 + {SPR_BBLL, 2, 5, NULL, S_ZBELL_X16, 0, 0}, // S_ZBELL_X15 + {SPR_BBLL, 3, 6, A_Scream, S_ZBELL_X17, 0, 0}, // S_ZBELL_X16 + {SPR_BBLL, 2, 5, NULL, S_ZBELL_X18, 0, 0}, // S_ZBELL_X17 + {SPR_BBLL, 1, 5, NULL, S_ZBELL_X19, 0, 0}, // S_ZBELL_X18 + {SPR_BBLL, 0, 4, NULL, S_ZBELL_X20, 0, 0}, // S_ZBELL_X19 + {SPR_BBLL, 4, 5, NULL, S_ZBELL_X21, 0, 0}, // S_ZBELL_X20 + {SPR_BBLL, 5, 5, NULL, S_ZBELL_X22, 0, 0}, // S_ZBELL_X21 + {SPR_BBLL, 6, 7, A_Scream, S_ZBELL_X23, 0, 0}, // S_ZBELL_X22 + {SPR_BBLL, 5, 5, NULL, S_ZBELL_X24, 0, 0}, // S_ZBELL_X23 + {SPR_BBLL, 4, 5, NULL, S_ZBELL_X25, 0, 0}, // S_ZBELL_X24 + {SPR_BBLL, 0, 5, NULL, S_ZBELL_X26, 0, 0}, // S_ZBELL_X25 + {SPR_BBLL, 1, 6, NULL, S_ZBELL_X27, 0, 0}, // S_ZBELL_X26 + {SPR_BBLL, 2, 6, NULL, S_ZBELL_X28, 0, 0}, // S_ZBELL_X27 + {SPR_BBLL, 3, 7, A_Scream, S_ZBELL_X29, 0, 0}, // S_ZBELL_X28 + {SPR_BBLL, 2, 6, NULL, S_ZBELL_X30, 0, 0}, // S_ZBELL_X29 + {SPR_BBLL, 1, 6, NULL, S_ZBELL_X31, 0, 0}, // S_ZBELL_X30 + {SPR_BBLL, 0, 5, NULL, S_ZBELL_X32, 0, 0}, // S_ZBELL_X31 + {SPR_BBLL, 4, 6, NULL, S_ZBELL_X33, 0, 0}, // S_ZBELL_X32 + {SPR_BBLL, 5, 6, NULL, S_ZBELL_X34, 0, 0}, // S_ZBELL_X33 + {SPR_BBLL, 6, 7, A_Scream, S_ZBELL_X35, 0, 0}, // S_ZBELL_X34 + {SPR_BBLL, 5, 6, NULL, S_ZBELL_X36, 0, 0}, // S_ZBELL_X35 + {SPR_BBLL, 4, 6, NULL, S_ZBELL_X37, 0, 0}, // S_ZBELL_X36 + {SPR_BBLL, 0, 6, NULL, S_ZBELL_X38, 0, 0}, // S_ZBELL_X37 + {SPR_BBLL, 1, 6, NULL, S_ZBELL_X39, 0, 0}, // S_ZBELL_X38 + {SPR_BBLL, 2, 6, NULL, S_ZBELL_X40, 0, 0}, // S_ZBELL_X39 + {SPR_BBLL, 1, 7, NULL, S_ZBELL_X41, 0, 0}, // S_ZBELL_X40 + {SPR_BBLL, 0, 8, NULL, S_ZBELL_X42, 0, 0}, // S_ZBELL_X41 + {SPR_BBLL, 4, 12, NULL, S_ZBELL_X43, 0, 0}, // S_ZBELL_X42 + {SPR_BBLL, 0, 10, NULL, S_ZBELL_X44, 0, 0}, // S_ZBELL_X43 + {SPR_BBLL, 1, 12, NULL, S_ZBELL_X45, 0, 0}, // S_ZBELL_X44 + {SPR_BBLL, 0, 12, NULL, S_ZBELL_X46, 0, 0}, // S_ZBELL_X45 + {SPR_BBLL, 4, 14, NULL, S_ZBELL_X47, 0, 0}, // S_ZBELL_X46 + {SPR_BBLL, 0, 1, A_BellReset2, S_ZBELL, 0, 0}, // S_ZBELL_X47 + {SPR_CAND, 32768, 5, NULL, S_ZBLUE_CANDLE2, 0, 0}, // S_ZBLUE_CANDLE1 + {SPR_CAND, 32769, 5, NULL, S_ZBLUE_CANDLE3, 0, 0}, // S_ZBLUE_CANDLE2 + {SPR_CAND, 32770, 5, NULL, S_ZBLUE_CANDLE4, 0, 0}, // S_ZBLUE_CANDLE3 + {SPR_CAND, 32771, 5, NULL, S_ZBLUE_CANDLE5, 0, 0}, // S_ZBLUE_CANDLE4 + {SPR_CAND, 32772, 5, NULL, S_ZBLUE_CANDLE1, 0, 0}, // S_ZBLUE_CANDLE5 + {SPR_IRON, 0, -1, NULL, S_NULL, 0, 0}, // S_ZIRON_MAIDEN + {SPR_XMAS, 0, -1, NULL, S_NULL, 0, 0}, // S_ZXMAS_TREE + {SPR_XMAS, 0, 4, A_TreeDeath, S_ZXMAS_TREE, 0, 0}, // S_ZXMAS_TREE_DIE + {SPR_XMAS, 32769, 6, NULL, S_ZXMAS_TREE_X2, 0, 0}, // S_ZXMAS_TREE_X1 + {SPR_XMAS, 32770, 6, A_Scream, S_ZXMAS_TREE_X3, 0, 0}, // S_ZXMAS_TREE_X2 + {SPR_XMAS, 32771, 5, NULL, S_ZXMAS_TREE_X4, 0, 0}, // S_ZXMAS_TREE_X3 + {SPR_XMAS, 32772, 5, A_Explode, S_ZXMAS_TREE_X5, 0, 0}, // S_ZXMAS_TREE_X4 + {SPR_XMAS, 32773, 5, NULL, S_ZXMAS_TREE_X6, 0, 0}, // S_ZXMAS_TREE_X5 + {SPR_XMAS, 32774, 4, NULL, S_ZXMAS_TREE_X7, 0, 0}, // S_ZXMAS_TREE_X6 + {SPR_XMAS, 7, 5, NULL, S_ZXMAS_TREE_X8, 0, 0}, // S_ZXMAS_TREE_X7 + {SPR_XMAS, 8, 4, A_NoBlocking, S_ZXMAS_TREE_X9, 0, 0}, // S_ZXMAS_TREE_X8 + {SPR_XMAS, 9, 4, NULL, S_ZXMAS_TREE_X10, 0, 0}, // S_ZXMAS_TREE_X9 + {SPR_XMAS, 10, -1, NULL, S_NULL, 0, 0}, // S_ZXMAS_TREE_X10 + {SPR_CDRN, 32769, 4, NULL, S_ZCAULDRON2, 0, 0}, // S_ZCAULDRON1 + {SPR_CDRN, 32770, 4, NULL, S_ZCAULDRON3, 0, 0}, // S_ZCAULDRON2 + {SPR_CDRN, 32771, 4, NULL, S_ZCAULDRON4, 0, 0}, // S_ZCAULDRON3 + {SPR_CDRN, 32772, 4, NULL, S_ZCAULDRON5, 0, 0}, // S_ZCAULDRON4 + {SPR_CDRN, 32773, 4, NULL, S_ZCAULDRON6, 0, 0}, // S_ZCAULDRON5 + {SPR_CDRN, 32774, 4, NULL, S_ZCAULDRON7, 0, 0}, // S_ZCAULDRON6 + {SPR_CDRN, 32775, 4, NULL, S_ZCAULDRON1, 0, 0}, // S_ZCAULDRON7 + {SPR_CDRN, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCAULDRON_U + {SPR_CHNS, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINBIT32 + {SPR_CHNS, 1, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINBIT64 + {SPR_CHNS, 2, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_HEART + {SPR_CHNS, 3, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_HOOK1 + {SPR_CHNS, 4, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_HOOK2 + {SPR_CHNS, 5, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_SPIKE + {SPR_CHNS, 6, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_SKULL + {SPR_TST1, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT1 + {SPR_TST2, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT2 + {SPR_TST3, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT3 + {SPR_TST4, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT4 + {SPR_TST5, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT5 + {SPR_TST6, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT6 + {SPR_TST7, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT7 + {SPR_TST8, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT8 + {SPR_TST9, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT9 + {SPR_TST0, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT10 + {SPR_TELE, 32768, 6, NULL, S_TFOG2, 0, 0}, // S_TFOG1 + {SPR_TELE, 32769, 6, NULL, S_TFOG3, 0, 0}, // S_TFOG2 + {SPR_TELE, 32770, 6, NULL, S_TFOG4, 0, 0}, // S_TFOG3 + {SPR_TELE, 32771, 6, NULL, S_TFOG5, 0, 0}, // S_TFOG4 + {SPR_TELE, 32772, 6, NULL, S_TFOG6, 0, 0}, // S_TFOG5 + {SPR_TELE, 32773, 6, NULL, S_TFOG7, 0, 0}, // S_TFOG6 + {SPR_TELE, 32774, 6, NULL, S_TFOG8, 0, 0}, // S_TFOG7 + {SPR_TELE, 32775, 6, NULL, S_TFOG9, 0, 0}, // S_TFOG8 + {SPR_TELE, 32774, 6, NULL, S_TFOG10, 0, 0}, // S_TFOG9 + {SPR_TELE, 32773, 6, NULL, S_TFOG11, 0, 0}, // S_TFOG10 + {SPR_TELE, 32772, 6, NULL, S_TFOG12, 0, 0}, // S_TFOG11 + {SPR_TELE, 32771, 6, NULL, S_TFOG13, 0, 0}, // S_TFOG12 + {SPR_TELE, 32770, 6, NULL, S_NULL, 0, 0}, // S_TFOG13 + {SPR_TSMK, 0, 4, NULL, S_TELESMOKE2, 0, 0}, // S_TELESMOKE1 + {SPR_TSMK, 1, 3, NULL, S_TELESMOKE3, 0, 0}, // S_TELESMOKE2 + {SPR_TSMK, 2, 4, NULL, S_TELESMOKE4, 0, 0}, // S_TELESMOKE3 + {SPR_TSMK, 3, 3, NULL, S_TELESMOKE5, 0, 0}, // S_TELESMOKE4 + {SPR_TSMK, 4, 4, NULL, S_TELESMOKE6, 0, 0}, // S_TELESMOKE5 + {SPR_TSMK, 5, 3, NULL, S_TELESMOKE7, 0, 0}, // S_TELESMOKE6 + {SPR_TSMK, 6, 4, NULL, S_TELESMOKE8, 0, 0}, // S_TELESMOKE7 + {SPR_TSMK, 7, 3, NULL, S_TELESMOKE9, 0, 0}, // S_TELESMOKE8 + {SPR_TSMK, 8, 4, NULL, S_TELESMOKE10, 0, 0}, // S_TELESMOKE9 + {SPR_TSMK, 9, 3, NULL, S_TELESMOKE11, 0, 0}, // S_TELESMOKE10 + {SPR_TSMK, 10, 4, NULL, S_TELESMOKE12, 0, 0}, // S_TELESMOKE11 + {SPR_TSMK, 11, 3, NULL, S_TELESMOKE13, 0, 0}, // S_TELESMOKE12 + {SPR_TSMK, 12, 4, NULL, S_TELESMOKE14, 0, 0}, // S_TELESMOKE13 + {SPR_TSMK, 13, 3, NULL, S_TELESMOKE15, 0, 0}, // S_TELESMOKE14 + {SPR_TSMK, 14, 4, NULL, S_TELESMOKE16, 0, 0}, // S_TELESMOKE15 + {SPR_TSMK, 15, 3, NULL, S_TELESMOKE17, 0, 0}, // S_TELESMOKE16 + {SPR_TSMK, 16, 4, NULL, S_TELESMOKE18, 0, 0}, // S_TELESMOKE17 + {SPR_TSMK, 17, 3, NULL, S_TELESMOKE19, 0, 0}, // S_TELESMOKE18 + {SPR_TSMK, 18, 4, NULL, S_TELESMOKE20, 0, 0}, // S_TELESMOKE19 + {SPR_TSMK, 19, 3, NULL, S_TELESMOKE21, 0, 0}, // S_TELESMOKE20 + {SPR_TSMK, 20, 4, NULL, S_TELESMOKE22, 0, 0}, // S_TELESMOKE21 + {SPR_TSMK, 21, 3, NULL, S_TELESMOKE23, 0, 0}, // S_TELESMOKE22 + {SPR_TSMK, 22, 4, NULL, S_TELESMOKE24, 0, 0}, // S_TELESMOKE23 + {SPR_TSMK, 23, 3, NULL, S_TELESMOKE25, 0, 0}, // S_TELESMOKE24 + {SPR_TSMK, 24, 4, NULL, S_TELESMOKE26, 0, 0}, // S_TELESMOKE25 + {SPR_TSMK, 25, 3, NULL, S_TELESMOKE1, 0, 0}, // S_TELESMOKE26 + {SPR_FPCH, 0, 0, A_Light0, S_NULL, 0, 0}, // S_LIGHTDONE + {SPR_FPCH, 0, 1, A_WeaponReady, S_PUNCHREADY, 0, 0}, // S_PUNCHREADY + {SPR_FPCH, 0, 1, A_Lower, S_PUNCHDOWN, 0, 0}, // S_PUNCHDOWN + {SPR_FPCH, 0, 1, A_Raise, S_PUNCHUP, 0, 0}, // S_PUNCHUP + {SPR_FPCH, 1, 5, NULL, S_PUNCHATK1_2, 5, 40}, // S_PUNCHATK1_1 + {SPR_FPCH, 2, 4, NULL, S_PUNCHATK1_3, 5, 40}, // S_PUNCHATK1_2 + {SPR_FPCH, 3, 4, A_FPunchAttack, S_PUNCHATK1_4, 5, 40}, // S_PUNCHATK1_3 + {SPR_FPCH, 2, 4, NULL, S_PUNCHATK1_5, 5, 40}, // S_PUNCHATK1_4 + {SPR_FPCH, 1, 5, A_ReFire, S_PUNCHREADY, 5, 40}, // S_PUNCHATK1_5 + {SPR_FPCH, 3, 4, NULL, S_PUNCHATK2_2, 5, 40}, // S_PUNCHATK2_1 + {SPR_FPCH, 4, 4, NULL, S_PUNCHATK2_3, 5, 40}, // S_PUNCHATK2_2 + {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_4, 15, 50}, // S_PUNCHATK2_3 + {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_5, 25, 60}, // S_PUNCHATK2_4 + {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_6, 35, 70}, // S_PUNCHATK2_5 + {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_7, 45, 80}, // S_PUNCHATK2_6 + {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_8, 55, 90}, // S_PUNCHATK2_7 + {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_9, 65, 100}, // S_PUNCHATK2_8 + {SPR_FPCH, 4, 10, NULL, S_PUNCHREADY, 0, 150}, // S_PUNCHATK2_9 + {SPR_FHFX, 18, 4, NULL, S_PUNCHPUFF2, 0, 0}, // S_PUNCHPUFF1 + {SPR_FHFX, 19, 4, NULL, S_PUNCHPUFF3, 0, 0}, // S_PUNCHPUFF2 + {SPR_FHFX, 20, 4, NULL, S_PUNCHPUFF4, 0, 0}, // S_PUNCHPUFF3 + {SPR_FHFX, 21, 4, NULL, S_PUNCHPUFF5, 0, 0}, // S_PUNCHPUFF4 + {SPR_FHFX, 22, 4, NULL, S_NULL, 0, 0}, // S_PUNCHPUFF5 + {SPR_WFAX, 0, -1, NULL, S_NULL, 0, 0}, // S_AXE + {SPR_FAXE, 0, 1, A_WeaponReady, S_FAXEREADY, 0, 0}, // S_FAXEREADY + {SPR_FAXE, 0, 1, A_Lower, S_FAXEDOWN, 0, 0}, // S_FAXEDOWN + {SPR_FAXE, 0, 1, A_Raise, S_FAXEUP, 0, 0}, // S_FAXEUP + {SPR_FAXE, 1, 4, NULL, S_FAXEATK_2, 15, 32}, // S_FAXEATK_1 + {SPR_FAXE, 2, 3, NULL, S_FAXEATK_3, 15, 32}, // S_FAXEATK_2 + {SPR_FAXE, 3, 2, NULL, S_FAXEATK_4, 15, 32}, // S_FAXEATK_3 + {SPR_FAXE, 3, 1, A_FAxeAttack, S_FAXEATK_5, -5, 70}, // S_FAXEATK_4 + {SPR_FAXE, 3, 2, NULL, S_FAXEATK_6, -25, 90}, // S_FAXEATK_5 + {SPR_FAXE, 4, 1, NULL, S_FAXEATK_7, 15, 32}, // S_FAXEATK_6 + {SPR_FAXE, 4, 2, NULL, S_FAXEATK_8, 10, 54}, // S_FAXEATK_7 + {SPR_FAXE, 4, 7, NULL, S_FAXEATK_9, 10, 150}, // S_FAXEATK_8 + {SPR_FAXE, 0, 1, A_ReFire, S_FAXEATK_10, 0, 60}, // S_FAXEATK_9 + {SPR_FAXE, 0, 1, NULL, S_FAXEATK_11, 0, 52}, // S_FAXEATK_10 + {SPR_FAXE, 0, 1, NULL, S_FAXEATK_12, 0, 44}, // S_FAXEATK_11 + {SPR_FAXE, 0, 1, NULL, S_FAXEATK_13, 0, 36}, // S_FAXEATK_12 + {SPR_FAXE, 0, 1, NULL, S_FAXEREADY, 0, 0}, // S_FAXEATK_13 + {SPR_FAXE, 11, 1, A_WeaponReady, S_FAXEREADY_G1, 0, 0}, // S_FAXEREADY_G + {SPR_FAXE, 11, 1, A_WeaponReady, S_FAXEREADY_G2, 0, 0}, // S_FAXEREADY_G1 + {SPR_FAXE, 11, 1, A_WeaponReady, S_FAXEREADY_G3, 0, 0}, // S_FAXEREADY_G2 + {SPR_FAXE, 12, 1, A_WeaponReady, S_FAXEREADY_G4, 0, 0}, // S_FAXEREADY_G3 + {SPR_FAXE, 12, 1, A_WeaponReady, S_FAXEREADY_G5, 0, 0}, // S_FAXEREADY_G4 + {SPR_FAXE, 12, 1, A_WeaponReady, S_FAXEREADY_G, 0, 0}, // S_FAXEREADY_G5 + {SPR_FAXE, 11, 1, A_Lower, S_FAXEDOWN_G, 0, 0}, // S_FAXEDOWN_G + {SPR_FAXE, 11, 1, A_Raise, S_FAXEUP_G, 0, 0}, // S_FAXEUP_G + {SPR_FAXE, 13, 4, NULL, S_FAXEATK_G2, 15, 32}, // S_FAXEATK_G1 + {SPR_FAXE, 14, 3, NULL, S_FAXEATK_G3, 15, 32}, // S_FAXEATK_G2 + {SPR_FAXE, 15, 2, NULL, S_FAXEATK_G4, 15, 32}, // S_FAXEATK_G3 + {SPR_FAXE, 15, 1, A_FAxeAttack, S_FAXEATK_G5, -5, 70}, // S_FAXEATK_G4 + {SPR_FAXE, 15, 2, NULL, S_FAXEATK_G6, -25, 90}, // S_FAXEATK_G5 + {SPR_FAXE, 16, 1, NULL, S_FAXEATK_G7, 15, 32}, // S_FAXEATK_G6 + {SPR_FAXE, 16, 2, NULL, S_FAXEATK_G8, 10, 54}, // S_FAXEATK_G7 + {SPR_FAXE, 16, 7, NULL, S_FAXEATK_G9, 10, 150}, // S_FAXEATK_G8 + {SPR_FAXE, 0, 1, A_ReFire, S_FAXEATK_G10, 0, 60}, // S_FAXEATK_G9 + {SPR_FAXE, 0, 1, NULL, S_FAXEATK_G11, 0, 52}, // S_FAXEATK_G10 + {SPR_FAXE, 0, 1, NULL, S_FAXEATK_G12, 0, 44}, // S_FAXEATK_G11 + {SPR_FAXE, 0, 1, NULL, S_FAXEATK_G13, 0, 36}, // S_FAXEATK_G12 + {SPR_FAXE, 0, 1, NULL, S_FAXEREADY_G, 0, 0}, // S_FAXEATK_G13 + {SPR_FAXE, 32785, 4, NULL, S_AXEPUFF_GLOW2, 0, 0}, // S_AXEPUFF_GLOW1 + {SPR_FAXE, 32786, 4, NULL, S_AXEPUFF_GLOW3, 0, 0}, // S_AXEPUFF_GLOW2 + {SPR_FAXE, 32787, 4, NULL, S_AXEPUFF_GLOW4, 0, 0}, // S_AXEPUFF_GLOW3 + {SPR_FAXE, 32788, 4, NULL, S_AXEPUFF_GLOW5, 0, 0}, // S_AXEPUFF_GLOW4 + {SPR_FAXE, 32789, 4, NULL, S_AXEPUFF_GLOW6, 0, 0}, // S_AXEPUFF_GLOW5 + {SPR_FAXE, 32790, 4, NULL, S_AXEPUFF_GLOW7, 0, 0}, // S_AXEPUFF_GLOW6 + {SPR_FAXE, 32791, 4, NULL, S_NULL, 0, 0}, // S_AXEPUFF_GLOW7 + {SPR_FAXE, 5, 3, NULL, S_AXEBLOOD2, 0, 0}, // S_AXEBLOOD1 + {SPR_FAXE, 6, 3, NULL, S_AXEBLOOD3, 0, 0}, // S_AXEBLOOD2 + {SPR_FAXE, 7, 3, NULL, S_AXEBLOOD4, 0, 0}, // S_AXEBLOOD3 + {SPR_FAXE, 8, 3, NULL, S_AXEBLOOD5, 0, 0}, // S_AXEBLOOD4 + {SPR_FAXE, 9, 3, NULL, S_AXEBLOOD6, 0, 0}, // S_AXEBLOOD5 + {SPR_FAXE, 10, 3, NULL, S_NULL, 0, 0}, // S_AXEBLOOD6 + {SPR_WFHM, 0, -1, NULL, S_NULL, 0, 0}, // S_HAMM + {SPR_FHMR, 0, 1, A_WeaponReady, S_FHAMMERREADY, 0, 0}, // S_FHAMMERREADY + {SPR_FHMR, 0, 1, A_Lower, S_FHAMMERDOWN, 0, 0}, // S_FHAMMERDOWN + {SPR_FHMR, 0, 1, A_Raise, S_FHAMMERUP, 0, 0}, // S_FHAMMERUP + {SPR_FHMR, 1, 6, NULL, S_FHAMMERATK_2, 5, 0}, // S_FHAMMERATK_1 + {SPR_FHMR, 2, 3, A_FHammerAttack, S_FHAMMERATK_3, 5, 0}, // S_FHAMMERATK_2 + {SPR_FHMR, 3, 3, NULL, S_FHAMMERATK_4, 5, 0}, // S_FHAMMERATK_3 + {SPR_FHMR, 4, 2, NULL, S_FHAMMERATK_5, 5, 0}, // S_FHAMMERATK_4 + {SPR_FHMR, 4, 10, A_FHammerThrow, S_FHAMMERATK_6, 5, 150}, // S_FHAMMERATK_5 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_7, 0, 60}, // S_FHAMMERATK_6 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_8, 0, 55}, // S_FHAMMERATK_7 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_9, 0, 50}, // S_FHAMMERATK_8 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_10, 0, 45}, // S_FHAMMERATK_9 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_11, 0, 40}, // S_FHAMMERATK_10 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_12, 0, 35}, // S_FHAMMERATK_11 + {SPR_FHMR, 0, 1, NULL, S_FHAMMERREADY, 0, 0}, // S_FHAMMERATK_12 + {SPR_FHFX, 32768, 2, NULL, S_HAMMER_MISSILE_2, 0, 0}, // S_HAMMER_MISSILE_1 + {SPR_FHFX, 32769, 2, A_ContMobjSound, S_HAMMER_MISSILE_3, 0, 0}, // S_HAMMER_MISSILE_2 + {SPR_FHFX, 32770, 2, NULL, S_HAMMER_MISSILE_4, 0, 0}, // S_HAMMER_MISSILE_3 + {SPR_FHFX, 32771, 2, NULL, S_HAMMER_MISSILE_5, 0, 0}, // S_HAMMER_MISSILE_4 + {SPR_FHFX, 32772, 2, NULL, S_HAMMER_MISSILE_6, 0, 0}, // S_HAMMER_MISSILE_5 + {SPR_FHFX, 32773, 2, NULL, S_HAMMER_MISSILE_7, 0, 0}, // S_HAMMER_MISSILE_6 + {SPR_FHFX, 32774, 2, NULL, S_HAMMER_MISSILE_8, 0, 0}, // S_HAMMER_MISSILE_7 + {SPR_FHFX, 32775, 2, NULL, S_HAMMER_MISSILE_1, 0, 0}, // S_HAMMER_MISSILE_8 + {SPR_FHFX, 32776, 3, NULL, S_HAMMER_MISSILE_X2, 0, 0}, // S_HAMMER_MISSILE_X1 + {SPR_FHFX, 32777, 3, NULL, S_HAMMER_MISSILE_X3, 0, 0}, // S_HAMMER_MISSILE_X2 + {SPR_FHFX, 32778, 3, A_Explode, S_HAMMER_MISSILE_X4, 0, 0}, // S_HAMMER_MISSILE_X3 + {SPR_FHFX, 32779, 3, NULL, S_HAMMER_MISSILE_X5, 0, 0}, // S_HAMMER_MISSILE_X4 + {SPR_FHFX, 32780, 3, NULL, S_HAMMER_MISSILE_X6, 0, 0}, // S_HAMMER_MISSILE_X5 + {SPR_FHFX, 13, 3, NULL, S_HAMMER_MISSILE_X7, 0, 0}, // S_HAMMER_MISSILE_X6 + {SPR_FHFX, 32782, 3, NULL, S_HAMMER_MISSILE_X8, 0, 0}, // S_HAMMER_MISSILE_X7 + {SPR_FHFX, 32783, 3, NULL, S_HAMMER_MISSILE_X9, 0, 0}, // S_HAMMER_MISSILE_X8 + {SPR_FHFX, 32784, 3, NULL, S_HAMMER_MISSILE_X10, 0, 0}, // S_HAMMER_MISSILE_X9 + {SPR_FHFX, 32785, 3, NULL, S_NULL, 0, 0}, // S_HAMMER_MISSILE_X10 + {SPR_FHFX, 18, 4, NULL, S_HAMMERPUFF2, 0, 0}, // S_HAMMERPUFF1 + {SPR_FHFX, 19, 4, NULL, S_HAMMERPUFF3, 0, 0}, // S_HAMMERPUFF2 + {SPR_FHFX, 20, 4, NULL, S_HAMMERPUFF4, 0, 0}, // S_HAMMERPUFF3 + {SPR_FHFX, 21, 4, NULL, S_HAMMERPUFF5, 0, 0}, // S_HAMMERPUFF4 + {SPR_FHFX, 22, 4, NULL, S_NULL, 0, 0}, // S_HAMMERPUFF5 + {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY1, 0, 0}, // S_FSWORDREADY + {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY2, 0, 0}, // S_FSWORDREADY1 + {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY3, 0, 0}, // S_FSWORDREADY2 + {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY4, 0, 0}, // S_FSWORDREADY3 + {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY5, 0, 0}, // S_FSWORDREADY4 + {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY6, 0, 0}, // S_FSWORDREADY5 + {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY7, 0, 0}, // S_FSWORDREADY6 + {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY8, 0, 0}, // S_FSWORDREADY7 + {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY9, 0, 0}, // S_FSWORDREADY8 + {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY10, 0, 0}, // S_FSWORDREADY9 + {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY11, 0, 0}, // S_FSWORDREADY10 + {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY, 0, 0}, // S_FSWORDREADY11 + {SPR_FSRD, 32768, 1, A_Lower, S_FSWORDDOWN, 0, 0}, // S_FSWORDDOWN + {SPR_FSRD, 32768, 1, A_Raise, S_FSWORDUP, 0, 0}, // S_FSWORDUP + {SPR_FSRD, 32771, 3, NULL, S_FSWORDATK_2, 5, 36}, // S_FSWORDATK_1 + {SPR_FSRD, 32772, 3, NULL, S_FSWORDATK_3, 5, 36}, // S_FSWORDATK_2 + {SPR_FSRD, 32773, 2, NULL, S_FSWORDATK_4, 5, 36}, // S_FSWORDATK_3 + {SPR_FSRD, 32774, 3, A_FSwordAttack, S_FSWORDATK_5, 5, 36}, // S_FSWORDATK_4 + {SPR_FSRD, 32775, 2, NULL, S_FSWORDATK_6, 5, 36}, // S_FSWORDATK_5 + {SPR_FSRD, 32776, 2, NULL, S_FSWORDATK_7, 5, 36}, // S_FSWORDATK_6 + {SPR_FSRD, 32776, 10, NULL, S_FSWORDATK_8, 5, 150}, // S_FSWORDATK_7 + {SPR_FSRD, 32768, 1, NULL, S_FSWORDATK_9, 5, 60}, // S_FSWORDATK_8 + {SPR_FSRD, 32769, 1, NULL, S_FSWORDATK_10, 5, 55}, // S_FSWORDATK_9 + {SPR_FSRD, 32770, 1, NULL, S_FSWORDATK_11, 5, 50}, // S_FSWORDATK_10 + {SPR_FSRD, 32768, 1, NULL, S_FSWORDATK_12, 5, 45}, // S_FSWORDATK_11 + {SPR_FSRD, 32769, 1, NULL, S_FSWORDREADY, 5, 40}, // S_FSWORDATK_12 + {SPR_FSFX, 32768, 3, NULL, S_FSWORD_MISSILE2, 0, 0}, // S_FSWORD_MISSILE1 + {SPR_FSFX, 32769, 3, NULL, S_FSWORD_MISSILE3, 0, 0}, // S_FSWORD_MISSILE2 + {SPR_FSFX, 32770, 3, NULL, S_FSWORD_MISSILE1, 0, 0}, // S_FSWORD_MISSILE3 + {SPR_FSFX, 32771, 4, NULL, S_FSWORD_MISSILE_X2, 0, 0}, // S_FSWORD_MISSILE_X1 + {SPR_FSFX, 32772, 3, A_FSwordFlames, S_FSWORD_MISSILE_X3, 0, 0}, // S_FSWORD_MISSILE_X2 + {SPR_FSFX, 32773, 4, A_Explode, S_FSWORD_MISSILE_X4, 0, 0}, // S_FSWORD_MISSILE_X3 + {SPR_FSFX, 32774, 3, NULL, S_FSWORD_MISSILE_X5, 0, 0}, // S_FSWORD_MISSILE_X4 + {SPR_FSFX, 32775, 4, NULL, S_FSWORD_MISSILE_X6, 0, 0}, // S_FSWORD_MISSILE_X5 + {SPR_FSFX, 32776, 3, NULL, S_FSWORD_MISSILE_X7, 0, 0}, // S_FSWORD_MISSILE_X6 + {SPR_FSFX, 32777, 4, NULL, S_FSWORD_MISSILE_X8, 0, 0}, // S_FSWORD_MISSILE_X7 + {SPR_FSFX, 32778, 3, NULL, S_FSWORD_MISSILE_X9, 0, 0}, // S_FSWORD_MISSILE_X8 + {SPR_FSFX, 32779, 3, NULL, S_FSWORD_MISSILE_X10, 0, 0}, // S_FSWORD_MISSILE_X9 + {SPR_FSFX, 32780, 3, NULL, S_NULL, 0, 0}, // S_FSWORD_MISSILE_X10 + {SPR_FSFX, 32781, 3, NULL, S_FSWORD_FLAME2, 0, 0}, // S_FSWORD_FLAME1 + {SPR_FSFX, 32782, 3, NULL, S_FSWORD_FLAME3, 0, 0}, // S_FSWORD_FLAME2 + {SPR_FSFX, 32783, 3, NULL, S_FSWORD_FLAME4, 0, 0}, // S_FSWORD_FLAME3 + {SPR_FSFX, 32784, 3, NULL, S_FSWORD_FLAME5, 0, 0}, // S_FSWORD_FLAME4 + {SPR_FSFX, 32785, 3, NULL, S_FSWORD_FLAME6, 0, 0}, // S_FSWORD_FLAME5 + {SPR_FSFX, 32786, 3, NULL, S_FSWORD_FLAME7, 0, 0}, // S_FSWORD_FLAME6 + {SPR_FSFX, 32787, 3, NULL, S_FSWORD_FLAME8, 0, 0}, // S_FSWORD_FLAME7 + {SPR_FSFX, 32788, 3, NULL, S_FSWORD_FLAME9, 0, 0}, // S_FSWORD_FLAME8 + {SPR_FSFX, 32789, 3, NULL, S_FSWORD_FLAME10, 0, 0}, // S_FSWORD_FLAME9 + {SPR_FSFX, 32790, 3, NULL, S_NULL, 0, 0}, // S_FSWORD_FLAME10 + {SPR_CMCE, 0, 1, A_WeaponReady, S_CMACEREADY, 0, 0}, // S_CMACEREADY + {SPR_CMCE, 0, 1, A_Lower, S_CMACEDOWN, 0, 0}, // S_CMACEDOWN + {SPR_CMCE, 0, 1, A_Raise, S_CMACEUP, 0, 0}, // S_CMACEUP + {SPR_CMCE, 1, 2, NULL, S_CMACEATK_2, 60, 20}, // S_CMACEATK_1 + {SPR_CMCE, 1, 1, NULL, S_CMACEATK_3, 30, 33}, // S_CMACEATK_2 + {SPR_CMCE, 1, 2, NULL, S_CMACEATK_4, 8, 45}, // S_CMACEATK_3 + {SPR_CMCE, 2, 1, NULL, S_CMACEATK_5, 8, 45}, // S_CMACEATK_4 + {SPR_CMCE, 3, 1, NULL, S_CMACEATK_6, 8, 45}, // S_CMACEATK_5 + {SPR_CMCE, 4, 1, NULL, S_CMACEATK_7, 8, 45}, // S_CMACEATK_6 + {SPR_CMCE, 4, 1, A_CMaceAttack, S_CMACEATK_8, -11, 58}, // S_CMACEATK_7 + {SPR_CMCE, 5, 1, NULL, S_CMACEATK_9, 8, 45}, // S_CMACEATK_8 + {SPR_CMCE, 5, 2, NULL, S_CMACEATK_10, -8, 74}, // S_CMACEATK_9 + {SPR_CMCE, 5, 1, NULL, S_CMACEATK_11, -20, 96}, // S_CMACEATK_10 + {SPR_CMCE, 5, 8, NULL, S_CMACEATK_12, -33, 160}, // S_CMACEATK_11 + {SPR_CMCE, 0, 2, A_ReFire, S_CMACEATK_13, 8, 75}, // S_CMACEATK_12 + {SPR_CMCE, 0, 1, NULL, S_CMACEATK_14, 8, 65}, // S_CMACEATK_13 + {SPR_CMCE, 0, 2, NULL, S_CMACEATK_15, 8, 60}, // S_CMACEATK_14 + {SPR_CMCE, 0, 1, NULL, S_CMACEATK_16, 8, 55}, // S_CMACEATK_15 + {SPR_CMCE, 0, 2, NULL, S_CMACEATK_17, 8, 50}, // S_CMACEATK_16 + {SPR_CMCE, 0, 1, NULL, S_CMACEREADY, 8, 45}, // S_CMACEATK_17 + {SPR_WCSS, 0, -1, NULL, S_NULL, 0, 0}, // S_CSTAFF + {SPR_CSSF, 2, 4, NULL, S_CSTAFFREADY1, 0, 0}, // S_CSTAFFREADY + {SPR_CSSF, 1, 3, A_CStaffInitBlink, S_CSTAFFREADY2, 0, 0}, // S_CSTAFFREADY1 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY3, 0, 0}, // S_CSTAFFREADY2 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY4, 0, 0}, // S_CSTAFFREADY3 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY5, 0, 0}, // S_CSTAFFREADY4 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY6, 0, 0}, // S_CSTAFFREADY5 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY7, 0, 0}, // S_CSTAFFREADY6 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY8, 0, 0}, // S_CSTAFFREADY7 + {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY9, 0, 0}, // S_CSTAFFREADY8 + {SPR_CSSF, 0, 1, A_CStaffCheckBlink, S_CSTAFFREADY2, 0, 0}, // S_CSTAFFREADY9 + {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK2, 0, 0}, // S_CSTAFFBLINK1 + {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK3, 0, 0}, // S_CSTAFFBLINK2 + {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK4, 0, 0}, // S_CSTAFFBLINK3 + {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK5, 0, 0}, // S_CSTAFFBLINK4 + {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK6, 0, 0}, // S_CSTAFFBLINK5 + {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK7, 0, 0}, // S_CSTAFFBLINK6 + {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK8, 0, 0}, // S_CSTAFFBLINK7 + {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK9, 0, 0}, // S_CSTAFFBLINK8 + {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK10, 0, 0}, // S_CSTAFFBLINK9 + {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK11, 0, 0}, // S_CSTAFFBLINK10 + {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFREADY2, 0, 0}, // S_CSTAFFBLINK11 + {SPR_CSSF, 1, 3, NULL, S_CSTAFFDOWN2, 0, 0}, // S_CSTAFFDOWN + {SPR_CSSF, 2, 4, NULL, S_CSTAFFDOWN3, 0, 0}, // S_CSTAFFDOWN2 + {SPR_CSSF, 2, 1, A_Lower, S_CSTAFFDOWN3, 0, 0}, // S_CSTAFFDOWN3 + {SPR_CSSF, 2, 1, A_Raise, S_CSTAFFUP, 0, 0}, // S_CSTAFFUP + {SPR_CSSF, 0, 1, A_CStaffCheck, S_CSTAFFATK_2, 0, 45}, // S_CSTAFFATK_1 + {SPR_CSSF, 9, 1, A_CStaffAttack, S_CSTAFFATK_3, 0, 50}, // S_CSTAFFATK_2 + {SPR_CSSF, 9, 2, NULL, S_CSTAFFATK_4, 0, 50}, // S_CSTAFFATK_3 + {SPR_CSSF, 9, 2, NULL, S_CSTAFFATK_5, 0, 45}, // S_CSTAFFATK_4 + {SPR_CSSF, 0, 2, NULL, S_CSTAFFATK_6, 0, 40}, // S_CSTAFFATK_5 + {SPR_CSSF, 0, 2, NULL, S_CSTAFFREADY2, 0, 36}, // S_CSTAFFATK_6 + {SPR_CSSF, 10, 10, NULL, S_CSTAFFREADY2, 0, 36}, // S_CSTAFFATK2_1 + {SPR_CSSF, 32771, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE2, 0, 0}, // S_CSTAFF_MISSILE1 + {SPR_CSSF, 32771, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE3, 0, 0}, // S_CSTAFF_MISSILE2 + {SPR_CSSF, 32772, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE4, 0, 0}, // S_CSTAFF_MISSILE3 + {SPR_CSSF, 32772, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE1, 0, 0}, // S_CSTAFF_MISSILE4 + {SPR_CSSF, 32773, 4, NULL, S_CSTAFF_MISSILE_X2, 0, 0}, // S_CSTAFF_MISSILE_X1 + {SPR_CSSF, 32774, 4, NULL, S_CSTAFF_MISSILE_X3, 0, 0}, // S_CSTAFF_MISSILE_X2 + {SPR_CSSF, 32775, 3, NULL, S_CSTAFF_MISSILE_X4, 0, 0}, // S_CSTAFF_MISSILE_X3 + {SPR_CSSF, 32776, 3, NULL, S_NULL, 0, 0}, // S_CSTAFF_MISSILE_X4 + {SPR_FHFX, 18, 4, NULL, S_CSTAFFPUFF2, 0, 0}, // S_CSTAFFPUFF1 + {SPR_FHFX, 19, 4, NULL, S_CSTAFFPUFF3, 0, 0}, // S_CSTAFFPUFF2 + {SPR_FHFX, 20, 4, NULL, S_CSTAFFPUFF4, 0, 0}, // S_CSTAFFPUFF3 + {SPR_FHFX, 21, 4, NULL, S_CSTAFFPUFF5, 0, 0}, // S_CSTAFFPUFF4 + {SPR_FHFX, 22, 4, NULL, S_NULL, 0, 0}, // S_CSTAFFPUFF5 + {SPR_WCFM, 32768, 4, NULL, S_CFLAME2, 0, 0}, // S_CFLAME1 + {SPR_WCFM, 32769, 4, NULL, S_CFLAME3, 0, 0}, // S_CFLAME2 + {SPR_WCFM, 32770, 4, NULL, S_CFLAME4, 0, 0}, // S_CFLAME3 + {SPR_WCFM, 32771, 4, NULL, S_CFLAME5, 0, 0}, // S_CFLAME4 + {SPR_WCFM, 32772, 4, NULL, S_CFLAME6, 0, 0}, // S_CFLAME5 + {SPR_WCFM, 32773, 4, NULL, S_CFLAME7, 0, 0}, // S_CFLAME6 + {SPR_WCFM, 32774, 4, NULL, S_CFLAME8, 0, 0}, // S_CFLAME7 + {SPR_WCFM, 32775, 4, NULL, S_CFLAME1, 0, 0}, // S_CFLAME8 + {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY2, 0, 0}, // S_CFLAMEREADY1 + {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY3, 0, 0}, // S_CFLAMEREADY2 + {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY4, 0, 0}, // S_CFLAMEREADY3 + {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY5, 0, 0}, // S_CFLAMEREADY4 + {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY6, 0, 0}, // S_CFLAMEREADY5 + {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY7, 0, 0}, // S_CFLAMEREADY6 + {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY8, 0, 0}, // S_CFLAMEREADY7 + {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY9, 0, 0}, // S_CFLAMEREADY8 + {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY10, 0, 0}, // S_CFLAMEREADY9 + {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY11, 0, 0}, // S_CFLAMEREADY10 + {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY12, 0, 0}, // S_CFLAMEREADY11 + {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY1, 0, 0}, // S_CFLAMEREADY12 + {SPR_CFLM, 0, 1, A_Lower, S_CFLAMEDOWN, 0, 0}, // S_CFLAMEDOWN + {SPR_CFLM, 0, 1, A_Raise, S_CFLAMEUP, 0, 0}, // S_CFLAMEUP + {SPR_CFLM, 0, 2, NULL, S_CFLAMEATK_2, 0, 40}, // S_CFLAMEATK_1 + {SPR_CFLM, 3, 2, NULL, S_CFLAMEATK_3, 0, 50}, // S_CFLAMEATK_2 + {SPR_CFLM, 3, 2, NULL, S_CFLAMEATK_4, 0, 36}, // S_CFLAMEATK_3 + {SPR_CFLM, 32772, 4, NULL, S_CFLAMEATK_5, 0, 0}, // S_CFLAMEATK_4 + {SPR_CFLM, 32773, 4, A_CFlameAttack, S_CFLAMEATK_6, 0, 0}, // S_CFLAMEATK_5 + {SPR_CFLM, 32772, 4, NULL, S_CFLAMEATK_7, 0, 0}, // S_CFLAMEATK_6 + {SPR_CFLM, 6, 2, NULL, S_CFLAMEATK_8, 0, 40}, // S_CFLAMEATK_7 + {SPR_CFLM, 6, 2, NULL, S_CFLAMEREADY1, 0, 0}, // S_CFLAMEATK_8 + {SPR_CFFX, 32781, 5, NULL, S_CFLAMEFLOOR2, 0, 0}, // S_CFLAMEFLOOR1 + {SPR_CFFX, 32782, 4, NULL, S_CFLAMEFLOOR3, 0, 0}, // S_CFLAMEFLOOR2 + {SPR_CFFX, 32783, 3, NULL, S_NULL, 0, 0}, // S_CFLAMEFLOOR3 + {SPR_CFFX, 32768, 3, NULL, S_FLAMEPUFF2, 0, 0}, // S_FLAMEPUFF1 + {SPR_CFFX, 32769, 3, NULL, S_FLAMEPUFF3, 0, 0}, // S_FLAMEPUFF2 + {SPR_CFFX, 32770, 3, NULL, S_FLAMEPUFF4, 0, 0}, // S_FLAMEPUFF3 + {SPR_CFFX, 32771, 4, NULL, S_FLAMEPUFF5, 0, 0}, // S_FLAMEPUFF4 + {SPR_CFFX, 32772, 3, NULL, S_FLAMEPUFF6, 0, 0}, // S_FLAMEPUFF5 + {SPR_CFFX, 32773, 4, NULL, S_FLAMEPUFF7, 0, 0}, // S_FLAMEPUFF6 + {SPR_CFFX, 32774, 3, NULL, S_FLAMEPUFF8, 0, 0}, // S_FLAMEPUFF7 + {SPR_CFFX, 32775, 4, NULL, S_FLAMEPUFF9, 0, 0}, // S_FLAMEPUFF8 + {SPR_CFFX, 32776, 3, NULL, S_FLAMEPUFF10, 0, 0}, // S_FLAMEPUFF9 + {SPR_CFFX, 32777, 4, NULL, S_FLAMEPUFF11, 0, 0}, // S_FLAMEPUFF10 + {SPR_CFFX, 32778, 3, NULL, S_FLAMEPUFF12, 0, 0}, // S_FLAMEPUFF11 + {SPR_CFFX, 32779, 4, NULL, S_FLAMEPUFF13, 0, 0}, // S_FLAMEPUFF12 + {SPR_CFFX, 32780, 3, NULL, S_NULL, 0, 0}, // S_FLAMEPUFF13 + {SPR_CFFX, 32768, 3, NULL, S_FLAMEPUFF2_2, 0, 0}, // S_FLAMEPUFF2_1 + {SPR_CFFX, 32769, 3, NULL, S_FLAMEPUFF2_3, 0, 0}, // S_FLAMEPUFF2_2 + {SPR_CFFX, 32770, 3, NULL, S_FLAMEPUFF2_4, 0, 0}, // S_FLAMEPUFF2_3 + {SPR_CFFX, 32771, 4, NULL, S_FLAMEPUFF2_5, 0, 0}, // S_FLAMEPUFF2_4 + {SPR_CFFX, 32772, 3, NULL, S_FLAMEPUFF2_6, 0, 0}, // S_FLAMEPUFF2_5 + {SPR_CFFX, 32773, 4, NULL, S_FLAMEPUFF2_7, 0, 0}, // S_FLAMEPUFF2_6 + {SPR_CFFX, 32774, 3, NULL, S_FLAMEPUFF2_8, 0, 0}, // S_FLAMEPUFF2_7 + {SPR_CFFX, 32775, 4, NULL, S_FLAMEPUFF2_9, 0, 0}, // S_FLAMEPUFF2_8 + {SPR_CFFX, 32776, 3, NULL, S_FLAMEPUFF2_10, 0, 0}, // S_FLAMEPUFF2_9 + {SPR_CFFX, 32770, 3, NULL, S_FLAMEPUFF2_11, 0, 0}, // S_FLAMEPUFF2_10 + {SPR_CFFX, 32771, 4, NULL, S_FLAMEPUFF2_12, 0, 0}, // S_FLAMEPUFF2_11 + {SPR_CFFX, 32772, 3, NULL, S_FLAMEPUFF2_13, 0, 0}, // S_FLAMEPUFF2_12 + {SPR_CFFX, 32773, 4, NULL, S_FLAMEPUFF2_14, 0, 0}, // S_FLAMEPUFF2_13 + {SPR_CFFX, 32774, 3, NULL, S_FLAMEPUFF2_15, 0, 0}, // S_FLAMEPUFF2_14 + {SPR_CFFX, 32775, 4, NULL, S_FLAMEPUFF2_16, 0, 0}, // S_FLAMEPUFF2_15 + {SPR_CFFX, 32776, 3, NULL, S_FLAMEPUFF2_17, 0, 0}, // S_FLAMEPUFF2_16 + {SPR_CFFX, 32777, 4, NULL, S_FLAMEPUFF2_18, 0, 0}, // S_FLAMEPUFF2_17 + {SPR_CFFX, 32778, 3, NULL, S_FLAMEPUFF2_19, 0, 0}, // S_FLAMEPUFF2_18 + {SPR_CFFX, 32779, 4, NULL, S_FLAMEPUFF2_20, 0, 0}, // S_FLAMEPUFF2_19 + {SPR_CFFX, 32780, 3, NULL, S_NULL, 0, 0}, // S_FLAMEPUFF2_20 + {SPR_CFCF, 32768, 4, NULL, S_CIRCLE_FLAME2, 0, 0}, // S_CIRCLE_FLAME1 + {SPR_CFCF, 32769, 2, A_CFlameRotate, S_CIRCLE_FLAME3, 0, 0}, // S_CIRCLE_FLAME2 + {SPR_CFCF, 32770, 2, NULL, S_CIRCLE_FLAME4, 0, 0}, // S_CIRCLE_FLAME3 + {SPR_CFCF, 32771, 1, NULL, S_CIRCLE_FLAME5, 0, 0}, // S_CIRCLE_FLAME4 + {SPR_CFCF, 32772, 2, NULL, S_CIRCLE_FLAME6, 0, 0}, // S_CIRCLE_FLAME5 + {SPR_CFCF, 32773, 2, A_CFlameRotate, S_CIRCLE_FLAME7, 0, 0}, // S_CIRCLE_FLAME6 + {SPR_CFCF, 32774, 1, NULL, S_CIRCLE_FLAME8, 0, 0}, // S_CIRCLE_FLAME7 + {SPR_CFCF, 32775, 2, NULL, S_CIRCLE_FLAME9, 0, 0}, // S_CIRCLE_FLAME8 + {SPR_CFCF, 32776, 2, NULL, S_CIRCLE_FLAME10, 0, 0}, // S_CIRCLE_FLAME9 + {SPR_CFCF, 32777, 1, A_CFlameRotate, S_CIRCLE_FLAME11, 0, 0}, // S_CIRCLE_FLAME10 + {SPR_CFCF, 32778, 2, NULL, S_CIRCLE_FLAME12, 0, 0}, // S_CIRCLE_FLAME11 + {SPR_CFCF, 32779, 3, NULL, S_CIRCLE_FLAME13, 0, 0}, // S_CIRCLE_FLAME12 + {SPR_CFCF, 32780, 3, NULL, S_CIRCLE_FLAME14, 0, 0}, // S_CIRCLE_FLAME13 + {SPR_CFCF, 32781, 2, A_CFlameRotate, S_CIRCLE_FLAME15, 0, 0}, // S_CIRCLE_FLAME14 + {SPR_CFCF, 32782, 3, NULL, S_CIRCLE_FLAME16, 0, 0}, // S_CIRCLE_FLAME15 + {SPR_CFCF, 32783, 2, NULL, S_NULL, 0, 0}, // S_CIRCLE_FLAME16 + {SPR_CFCF, 32784, 3, NULL, S_CIRCLE_FLAME_X2, 0, 0}, // S_CIRCLE_FLAME_X1 + {SPR_CFCF, 32785, 3, NULL, S_CIRCLE_FLAME_X3, 0, 0}, // S_CIRCLE_FLAME_X2 + {SPR_CFCF, 32786, 3, A_Explode, S_CIRCLE_FLAME_X4, 0, 0}, // S_CIRCLE_FLAME_X3 + {SPR_CFCF, 32787, 3, NULL, S_CIRCLE_FLAME_X5, 0, 0}, // S_CIRCLE_FLAME_X4 + {SPR_CFCF, 32788, 3, NULL, S_CIRCLE_FLAME_X6, 0, 0}, // S_CIRCLE_FLAME_X5 + {SPR_CFCF, 32789, 3, NULL, S_CIRCLE_FLAME_X7, 0, 0}, // S_CIRCLE_FLAME_X6 + {SPR_CFCF, 32790, 3, NULL, S_CIRCLE_FLAME_X8, 0, 0}, // S_CIRCLE_FLAME_X7 + {SPR_CFCF, 32791, 3, NULL, S_CIRCLE_FLAME_X9, 0, 0}, // S_CIRCLE_FLAME_X8 + {SPR_CFCF, 32792, 3, NULL, S_CIRCLE_FLAME_X10, 0, 0}, // S_CIRCLE_FLAME_X9 + {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_CIRCLE_FLAME_X10 + {SPR_CFFX, 32768, 4, NULL, S_CFLAME_MISSILE2, 0, 0}, // S_CFLAME_MISSILE1 + {SPR_CFFX, 0, 1, A_CFlamePuff, S_FLAMEPUFF1, 0, 0}, // S_CFLAME_MISSILE2 + {SPR_CFFX, 32768, 1, A_CFlameMissile, S_FLAMEPUFF1, 0, 0}, // S_CFLAME_MISSILE_X + {SPR_CHLY, 0, 1, A_WeaponReady, S_CHOLYREADY, 0, 0}, // S_CHOLYREADY + {SPR_CHLY, 0, 1, A_Lower, S_CHOLYDOWN, 0, 0}, // S_CHOLYDOWN + {SPR_CHLY, 0, 1, A_Raise, S_CHOLYUP, 0, 0}, // S_CHOLYUP + {SPR_CHLY, 32768, 1, NULL, S_CHOLYATK_2, 0, 40}, // S_CHOLYATK_1 + {SPR_CHLY, 32769, 1, NULL, S_CHOLYATK_3, 0, 40}, // S_CHOLYATK_2 + {SPR_CHLY, 32770, 2, NULL, S_CHOLYATK_4, 0, 43}, // S_CHOLYATK_3 + {SPR_CHLY, 32771, 2, NULL, S_CHOLYATK_5, 0, 43}, // S_CHOLYATK_4 + {SPR_CHLY, 32772, 2, NULL, S_CHOLYATK_6, 0, 45}, // S_CHOLYATK_5 + {SPR_CHLY, 32773, 6, A_CHolyAttack, S_CHOLYATK_7, 0, 48}, // S_CHOLYATK_6 + {SPR_CHLY, 32774, 2, A_CHolyPalette, S_CHOLYATK_8, 0, 40}, // S_CHOLYATK_7 + {SPR_CHLY, 32774, 2, A_CHolyPalette, S_CHOLYATK_9, 0, 40}, // S_CHOLYATK_8 + {SPR_CHLY, 32774, 2, A_CHolyPalette, S_CHOLYREADY, 0, 36}, // S_CHOLYATK_9 + {SPR_SPIR, 0, 2, A_CHolySeek, S_HOLY_FX2, 0, 0}, // S_HOLY_FX1 + {SPR_SPIR, 0, 2, A_CHolySeek, S_HOLY_FX3, 0, 0}, // S_HOLY_FX2 + {SPR_SPIR, 1, 2, A_CHolySeek, S_HOLY_FX4, 0, 0}, // S_HOLY_FX3 + {SPR_SPIR, 1, 2, A_CHolyCheckScream, S_HOLY_FX1, 0, 0}, // S_HOLY_FX4 + {SPR_SPIR, 3, 4, NULL, S_HOLY_FX_X2, 0, 0}, // S_HOLY_FX_X1 + {SPR_SPIR, 4, 4, A_Scream, S_HOLY_FX_X3, 0, 0}, // S_HOLY_FX_X2 + {SPR_SPIR, 5, 4, NULL, S_HOLY_FX_X4, 0, 0}, // S_HOLY_FX_X3 + {SPR_SPIR, 6, 4, NULL, S_HOLY_FX_X5, 0, 0}, // S_HOLY_FX_X4 + {SPR_SPIR, 7, 4, NULL, S_HOLY_FX_X6, 0, 0}, // S_HOLY_FX_X5 + {SPR_SPIR, 8, 4, NULL, S_NULL, 0, 0}, // S_HOLY_FX_X6 + {SPR_SPIR, 2, 1, A_CHolyTail, S_HOLY_TAIL1, 0, 0}, // S_HOLY_TAIL1 + {SPR_SPIR, 3, -1, NULL, S_NULL, 0, 0}, // S_HOLY_TAIL2 + {SPR_SPIR, 10, 3, NULL, S_HOLY_PUFF2, 0, 0}, // S_HOLY_PUFF1 + {SPR_SPIR, 11, 3, NULL, S_HOLY_PUFF3, 0, 0}, // S_HOLY_PUFF2 + {SPR_SPIR, 12, 3, NULL, S_HOLY_PUFF4, 0, 0}, // S_HOLY_PUFF3 + {SPR_SPIR, 13, 3, NULL, S_HOLY_PUFF5, 0, 0}, // S_HOLY_PUFF4 + {SPR_SPIR, 14, 3, NULL, S_NULL, 0, 0}, // S_HOLY_PUFF5 + {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE2, 0, 0}, // S_HOLY_MISSILE1 + {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE3, 0, 0}, // S_HOLY_MISSILE2 + {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE4, 0, 0}, // S_HOLY_MISSILE3 + {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE_X, 0, 0}, // S_HOLY_MISSILE4 + {SPR_SPIR, 32783, 1, A_CHolyAttack2, S_NULL, 0, 0}, // S_HOLY_MISSILE_X + {SPR_SPIR, 16, 3, NULL, S_HOLY_MISSILE_P2, 0, 0}, // S_HOLY_MISSILE_P1 + {SPR_SPIR, 17, 3, NULL, S_HOLY_MISSILE_P3, 0, 0}, // S_HOLY_MISSILE_P2 + {SPR_SPIR, 18, 3, NULL, S_HOLY_MISSILE_P4, 0, 0}, // S_HOLY_MISSILE_P3 + {SPR_SPIR, 19, 3, NULL, S_HOLY_MISSILE_P5, 0, 0}, // S_HOLY_MISSILE_P4 + {SPR_SPIR, 20, 3, NULL, S_NULL, 0, 0}, // S_HOLY_MISSILE_P5 + {SPR_MWND, 0, 1, A_WeaponReady, S_MWANDREADY, 0, 0}, // S_MWANDREADY + {SPR_MWND, 0, 1, A_Lower, S_MWANDDOWN, 0, 0}, // S_MWANDDOWN + {SPR_MWND, 0, 1, A_Raise, S_MWANDUP, 0, 0}, // S_MWANDUP + {SPR_MWND, 0, 6, NULL, S_MWANDATK_2, 0, 0}, // S_MWANDATK_1 + {SPR_MWND, 32769, 6, A_MWandAttack, S_MWANDATK_3, 0, 48}, // S_MWANDATK_2 + {SPR_MWND, 0, 3, NULL, S_MWANDATK_4, 0, 40}, // S_MWANDATK_3 + {SPR_MWND, 0, 3, A_ReFire, S_MWANDREADY, 0, 36}, // S_MWANDATK_4 + {SPR_MWND, 32772, 4, NULL, S_MWANDPUFF2, 0, 0}, // S_MWANDPUFF1 + {SPR_MWND, 32773, 3, NULL, S_MWANDPUFF3, 0, 0}, // S_MWANDPUFF2 + {SPR_MWND, 32774, 4, NULL, S_MWANDPUFF4, 0, 0}, // S_MWANDPUFF3 + {SPR_MWND, 32775, 3, NULL, S_MWANDPUFF5, 0, 0}, // S_MWANDPUFF4 + {SPR_MWND, 32776, 4, NULL, S_NULL, 0, 0}, // S_MWANDPUFF5 + {SPR_MWND, 2, 4, NULL, S_MWANDSMOKE2, 0, 0}, // S_MWANDSMOKE1 + {SPR_MWND, 3, 4, NULL, S_MWANDSMOKE3, 0, 0}, // S_MWANDSMOKE2 + {SPR_MWND, 2, 4, NULL, S_MWANDSMOKE4, 0, 0}, // S_MWANDSMOKE3 + {SPR_MWND, 3, 4, NULL, S_NULL, 0, 0}, // S_MWANDSMOKE4 + {SPR_MWND, 32770, 4, NULL, S_MWAND_MISSILE2, 0, 0}, // S_MWAND_MISSILE1 + {SPR_MWND, 32771, 4, NULL, S_MWAND_MISSILE1, 0, 0}, // S_MWAND_MISSILE2 + {SPR_WMLG, 32768, 4, NULL, S_MW_LIGHTNING2, 0, 0}, // S_MW_LIGHTNING1 + {SPR_WMLG, 32769, 4, NULL, S_MW_LIGHTNING3, 0, 0}, // S_MW_LIGHTNING2 + {SPR_WMLG, 32770, 4, NULL, S_MW_LIGHTNING4, 0, 0}, // S_MW_LIGHTNING3 + {SPR_WMLG, 32771, 4, NULL, S_MW_LIGHTNING5, 0, 0}, // S_MW_LIGHTNING4 + {SPR_WMLG, 32772, 4, NULL, S_MW_LIGHTNING6, 0, 0}, // S_MW_LIGHTNING5 + {SPR_WMLG, 32773, 4, NULL, S_MW_LIGHTNING7, 0, 0}, // S_MW_LIGHTNING6 + {SPR_WMLG, 32774, 4, NULL, S_MW_LIGHTNING8, 0, 0}, // S_MW_LIGHTNING7 + {SPR_WMLG, 32775, 4, NULL, S_MW_LIGHTNING1, 0, 0}, // S_MW_LIGHTNING8 + {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY2, 0, 0}, // S_MLIGHTNINGREADY + {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY3, 0, 0}, // S_MLIGHTNINGREADY2 + {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY4, 0, 0}, // S_MLIGHTNINGREADY3 + {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY5, 0, 0}, // S_MLIGHTNINGREADY4 + {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY6, 0, 0}, // S_MLIGHTNINGREADY5 + {SPR_MLNG, 32768, 1, A_LightningReady, S_MLIGHTNINGREADY7, 0, 0}, // S_MLIGHTNINGREADY6 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY8, 0, 0}, // S_MLIGHTNINGREADY7 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY9, 0, 0}, // S_MLIGHTNINGREADY8 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY10, 0, 0}, // S_MLIGHTNINGREADY9 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY11, 0, 0}, // S_MLIGHTNINGREADY10 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY12, 0, 0}, // S_MLIGHTNINGREADY11 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY13, 0, 0}, // S_MLIGHTNINGREADY12 + {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY14, 0, 0}, // S_MLIGHTNINGREADY13 + {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY15, 0, 0}, // S_MLIGHTNINGREADY14 + {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY16, 0, 0}, // S_MLIGHTNINGREADY15 + {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY17, 0, 0}, // S_MLIGHTNINGREADY16 + {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY18, 0, 0}, // S_MLIGHTNINGREADY17 + {SPR_MLNG, 32770, 1, A_LightningReady, S_MLIGHTNINGREADY19, 0, 0}, // S_MLIGHTNINGREADY18 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY20, 0, 0}, // S_MLIGHTNINGREADY19 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY21, 0, 0}, // S_MLIGHTNINGREADY20 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY22, 0, 0}, // S_MLIGHTNINGREADY21 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY23, 0, 0}, // S_MLIGHTNINGREADY22 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY24, 0, 0}, // S_MLIGHTNINGREADY23 + {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY, 0, 0}, // S_MLIGHTNINGREADY24 + {SPR_MLNG, 32768, 1, A_Lower, S_MLIGHTNINGDOWN, 0, 0}, // S_MLIGHTNINGDOWN + {SPR_MLNG, 32768, 1, A_Raise, S_MLIGHTNINGUP, 0, 0}, // S_MLIGHTNINGUP + {SPR_MLNG, 32771, 3, NULL, S_MLIGHTNINGATK_2, 0, 0}, // S_MLIGHTNINGATK_1 + {SPR_MLNG, 32772, 3, NULL, S_MLIGHTNINGATK_3, 0, 0}, // S_MLIGHTNINGATK_2 + {SPR_MLNG, 32773, 4, A_MLightningAttack, S_MLIGHTNINGATK_4, 0, 0}, // S_MLIGHTNINGATK_3 + {SPR_MLNG, 32774, 4, NULL, S_MLIGHTNINGATK_5, 0, 0}, // S_MLIGHTNINGATK_4 + {SPR_MLNG, 32775, 3, NULL, S_MLIGHTNINGATK_6, 0, 0}, // S_MLIGHTNINGATK_5 + {SPR_MLNG, 32776, 3, NULL, S_MLIGHTNINGATK_7, 0, 0}, // S_MLIGHTNINGATK_6 + {SPR_MLNG, 32776, 6, NULL, S_MLIGHTNINGATK_8, 0, 199}, // S_MLIGHTNINGATK_7 + {SPR_MLNG, 32770, 2, NULL, S_MLIGHTNINGATK_9, 0, 55}, // S_MLIGHTNINGATK_8 + {SPR_MLNG, 32769, 2, NULL, S_MLIGHTNINGATK_10, 0, 50}, // S_MLIGHTNINGATK_9 + {SPR_MLNG, 32769, 2, NULL, S_MLIGHTNINGATK_11, 0, 45}, // S_MLIGHTNINGATK_10 + {SPR_MLNG, 32769, 2, NULL, S_MLIGHTNINGREADY, 0, 40}, // S_MLIGHTNINGATK_11 + {SPR_MLFX, 32768, 2, A_LightningZap, S_LIGHTNING_CEILING2, 0, 0}, // S_LIGHTNING_CEILING1 + {SPR_MLFX, 32769, 2, A_LightningClip, S_LIGHTNING_CEILING3, 0, 0}, // S_LIGHTNING_CEILING2 + {SPR_MLFX, 32770, 2, A_LightningClip, S_LIGHTNING_CEILING4, 0, 0}, // S_LIGHTNING_CEILING3 + {SPR_MLFX, 32771, 2, A_LightningClip, S_LIGHTNING_CEILING1, 0, 0}, // S_LIGHTNING_CEILING4 + {SPR_MLF2, 32768, 2, A_LightningRemove, S_LIGHTNING_C_X2, 0, 0}, // S_LIGHTNING_C_X1 + {SPR_MLF2, 32769, 3, NULL, S_LIGHTNING_C_X3, 0, 0}, // S_LIGHTNING_C_X2 + {SPR_MLF2, 32770, 3, NULL, S_LIGHTNING_C_X4, 0, 0}, // S_LIGHTNING_C_X3 + {SPR_MLF2, 32771, 3, NULL, S_LIGHTNING_C_X5, 0, 0}, // S_LIGHTNING_C_X4 + {SPR_MLF2, 32772, 3, NULL, S_LIGHTNING_C_X6, 0, 0}, // S_LIGHTNING_C_X5 + {SPR_MLF2, 32778, 3, NULL, S_LIGHTNING_C_X7, 0, 0}, // S_LIGHTNING_C_X6 + {SPR_MLF2, 32779, 3, NULL, S_LIGHTNING_C_X8, 0, 0}, // S_LIGHTNING_C_X7 + {SPR_MLF2, 32780, 3, NULL, S_LIGHTNING_C_X9, 0, 0}, // S_LIGHTNING_C_X8 + {SPR_ACLO, 4, 35, NULL, S_LIGHTNING_C_X10, 0, 0}, // S_LIGHTNING_C_X9 + {SPR_MLF2, 32781, 3, NULL, S_LIGHTNING_C_X11, 0, 0}, // S_LIGHTNING_C_X10 + {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_C_X12, 0, 0}, // S_LIGHTNING_C_X11 + {SPR_MLF2, 32783, 4, NULL, S_LIGHTNING_C_X13, 0, 0}, // S_LIGHTNING_C_X12 + {SPR_MLF2, 32784, 3, NULL, S_LIGHTNING_C_X14, 0, 0}, // S_LIGHTNING_C_X13 + {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_C_X15, 0, 0}, // S_LIGHTNING_C_X14 + {SPR_MLF2, 32784, 4, NULL, S_LIGHTNING_C_X16, 0, 0}, // S_LIGHTNING_C_X15 + {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_C_X17, 0, 0}, // S_LIGHTNING_C_X16 + {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_C_X18, 0, 0}, // S_LIGHTNING_C_X17 + {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_C_X19, 0, 0}, // S_LIGHTNING_C_X18 + {SPR_MLF2, 32783, 1, A_HideThing, S_FREETARGMOBJ, 0, 0}, // S_LIGHTNING_C_X19 + {SPR_MLFX, 32772, 2, A_LightningZap, S_LIGHTNING_FLOOR2, 0, 0}, // S_LIGHTNING_FLOOR1 + {SPR_MLFX, 32773, 2, A_LightningClip, S_LIGHTNING_FLOOR3, 0, 0}, // S_LIGHTNING_FLOOR2 + {SPR_MLFX, 32774, 2, A_LightningClip, S_LIGHTNING_FLOOR4, 0, 0}, // S_LIGHTNING_FLOOR3 + {SPR_MLFX, 32775, 2, A_LightningClip, S_LIGHTNING_FLOOR1, 0, 0}, // S_LIGHTNING_FLOOR4 + {SPR_MLF2, 32773, 2, A_LightningRemove, S_LIGHTNING_F_X2, 0, 0}, // S_LIGHTNING_F_X1 + {SPR_MLF2, 32774, 3, NULL, S_LIGHTNING_F_X3, 0, 0}, // S_LIGHTNING_F_X2 + {SPR_MLF2, 32775, 3, NULL, S_LIGHTNING_F_X4, 0, 0}, // S_LIGHTNING_F_X3 + {SPR_MLF2, 32776, 3, NULL, S_LIGHTNING_F_X5, 0, 0}, // S_LIGHTNING_F_X4 + {SPR_MLF2, 32777, 3, NULL, S_LIGHTNING_F_X6, 0, 0}, // S_LIGHTNING_F_X5 + {SPR_MLF2, 32778, 3, NULL, S_LIGHTNING_F_X7, 0, 0}, // S_LIGHTNING_F_X6 + {SPR_MLF2, 32779, 3, NULL, S_LIGHTNING_F_X8, 0, 0}, // S_LIGHTNING_F_X7 + {SPR_MLF2, 32780, 3, NULL, S_LIGHTNING_F_X9, 0, 0}, // S_LIGHTNING_F_X8 + {SPR_ACLO, 4, 20, NULL, S_LIGHTNING_F_X10, 0, 0}, // S_LIGHTNING_F_X9 + {SPR_MLF2, 32781, 3, NULL, S_LIGHTNING_F_X11, 0, 0}, // S_LIGHTNING_F_X10 + {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_F_X12, 0, 0}, // S_LIGHTNING_F_X11 + {SPR_MLF2, 32783, 4, NULL, S_LIGHTNING_F_X13, 0, 0}, // S_LIGHTNING_F_X12 + {SPR_MLF2, 32784, 3, NULL, S_LIGHTNING_F_X14, 0, 0}, // S_LIGHTNING_F_X13 + {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_F_X15, 0, 0}, // S_LIGHTNING_F_X14 + {SPR_MLF2, 32784, 4, A_LastZap, S_LIGHTNING_F_X16, 0, 0}, // S_LIGHTNING_F_X15 + {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_F_X17, 0, 0}, // S_LIGHTNING_F_X16 + {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_F_X18, 0, 0}, // S_LIGHTNING_F_X17 + {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_F_X19, 0, 0}, // S_LIGHTNING_F_X18 + {SPR_MLF2, 32783, 1, A_HideThing, S_FREETARGMOBJ, 0, 0}, // S_LIGHTNING_F_X19 + {SPR_MLFX, 32776, 2, A_ZapMimic, S_LIGHTNING_ZAP2, 0, 0}, // S_LIGHTNING_ZAP1 + {SPR_MLFX, 32777, 2, A_ZapMimic, S_LIGHTNING_ZAP3, 0, 0}, // S_LIGHTNING_ZAP2 + {SPR_MLFX, 32778, 2, A_ZapMimic, S_LIGHTNING_ZAP4, 0, 0}, // S_LIGHTNING_ZAP3 + {SPR_MLFX, 32779, 2, A_ZapMimic, S_LIGHTNING_ZAP5, 0, 0}, // S_LIGHTNING_ZAP4 + {SPR_MLFX, 32780, 2, A_ZapMimic, S_LIGHTNING_ZAP1, 0, 0}, // S_LIGHTNING_ZAP5 + {SPR_MLFX, 32781, 2, NULL, S_LIGHTNING_ZAP_X2, 0, 0}, // S_LIGHTNING_ZAP_X1 + {SPR_MLFX, 32782, 2, NULL, S_LIGHTNING_ZAP_X3, 0, 0}, // S_LIGHTNING_ZAP_X2 + {SPR_MLFX, 32783, 2, NULL, S_LIGHTNING_ZAP_X4, 0, 0}, // S_LIGHTNING_ZAP_X3 + {SPR_MLFX, 32784, 2, NULL, S_LIGHTNING_ZAP_X5, 0, 0}, // S_LIGHTNING_ZAP_X4 + {SPR_MLFX, 32785, 2, NULL, S_LIGHTNING_ZAP_X6, 0, 0}, // S_LIGHTNING_ZAP_X5 + {SPR_MLFX, 32786, 2, NULL, S_LIGHTNING_ZAP_X7, 0, 0}, // S_LIGHTNING_ZAP_X6 + {SPR_MLFX, 32787, 2, NULL, S_LIGHTNING_ZAP_X8, 0, 0}, // S_LIGHTNING_ZAP_X7 + {SPR_MLFX, 32788, 2, NULL, S_NULL, 0, 0}, // S_LIGHTNING_ZAP_X8 + {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY2, 0, 0}, // S_MSTAFFREADY + {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY3, 0, 0}, // S_MSTAFFREADY2 + {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY4, 0, 0}, // S_MSTAFFREADY3 + {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY5, 0, 0}, // S_MSTAFFREADY4 + {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY6, 0, 0}, // S_MSTAFFREADY5 + {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY7, 0, 0}, // S_MSTAFFREADY6 + {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY8, 0, 0}, // S_MSTAFFREADY7 + {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY9, 0, 0}, // S_MSTAFFREADY8 + {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY10, 0, 0}, // S_MSTAFFREADY9 + {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY11, 0, 0}, // S_MSTAFFREADY10 + {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY12, 0, 0}, // S_MSTAFFREADY11 + {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY13, 0, 0}, // S_MSTAFFREADY12 + {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY14, 0, 0}, // S_MSTAFFREADY13 + {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY15, 0, 0}, // S_MSTAFFREADY14 + {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY16, 0, 0}, // S_MSTAFFREADY15 + {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY17, 0, 0}, // S_MSTAFFREADY16 + {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY18, 0, 0}, // S_MSTAFFREADY17 + {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY19, 0, 0}, // S_MSTAFFREADY18 + {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY20, 0, 0}, // S_MSTAFFREADY19 + {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY21, 0, 0}, // S_MSTAFFREADY20 + {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY22, 0, 0}, // S_MSTAFFREADY21 + {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY23, 0, 0}, // S_MSTAFFREADY22 + {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY24, 0, 0}, // S_MSTAFFREADY23 + {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY25, 0, 0}, // S_MSTAFFREADY24 + {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY26, 0, 0}, // S_MSTAFFREADY25 + {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY27, 0, 0}, // S_MSTAFFREADY26 + {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY28, 0, 0}, // S_MSTAFFREADY27 + {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY29, 0, 0}, // S_MSTAFFREADY28 + {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY30, 0, 0}, // S_MSTAFFREADY29 + {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY31, 0, 0}, // S_MSTAFFREADY30 + {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY32, 0, 0}, // S_MSTAFFREADY31 + {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY33, 0, 0}, // S_MSTAFFREADY32 + {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY34, 0, 0}, // S_MSTAFFREADY33 + {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY35, 0, 0}, // S_MSTAFFREADY34 + {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY, 0, 0}, // S_MSTAFFREADY35 + {SPR_MSTF, 0, 1, A_Lower, S_MSTAFFDOWN, 0, 0}, // S_MSTAFFDOWN + {SPR_MSTF, 0, 1, A_Raise, S_MSTAFFUP, 0, 0}, // S_MSTAFFUP + {SPR_MSTF, 6, 4, NULL, S_MSTAFFATK_2, 0, 40}, // S_MSTAFFATK_1 + {SPR_MSTF, 32775, 4, A_MStaffAttack, S_MSTAFFATK_3, 0, 48}, // S_MSTAFFATK_2 + {SPR_MSTF, 32775, 2, A_MStaffPalette, S_MSTAFFATK_4, 0, 48}, // S_MSTAFFATK_3 + {SPR_MSTF, 8, 2, A_MStaffPalette, S_MSTAFFATK_5, 0, 48}, // S_MSTAFFATK_4 + {SPR_MSTF, 8, 2, A_MStaffPalette, S_MSTAFFATK_6, 0, 48}, // S_MSTAFFATK_5 + {SPR_MSTF, 8, 1, NULL, S_MSTAFFATK_7, 0, 40}, // S_MSTAFFATK_6 + {SPR_MSTF, 9, 5, NULL, S_MSTAFFREADY, 0, 36}, // S_MSTAFFATK_7 + {SPR_MSP1, 32768, 3, A_MStaffWeave, S_MSTAFF_FX1_2, 0, 0}, // S_MSTAFF_FX1_1 + {SPR_MSP1, 32769, 3, A_MStaffWeave, S_MSTAFF_FX1_3, 0, 0}, // S_MSTAFF_FX1_2 + {SPR_MSP1, 32770, 3, A_MStaffWeave, S_MSTAFF_FX1_4, 0, 0}, // S_MSTAFF_FX1_3 + {SPR_MSP1, 32771, 3, A_MStaffWeave, S_MSTAFF_FX1_5, 0, 0}, // S_MSTAFF_FX1_4 + {SPR_MSP1, 32772, 3, A_MStaffWeave, S_MSTAFF_FX1_6, 0, 0}, // S_MSTAFF_FX1_5 + {SPR_MSP1, 32773, 3, A_MStaffWeave, S_MSTAFF_FX1_1, 0, 0}, // S_MSTAFF_FX1_6 + {SPR_MSP1, 32774, 4, NULL, S_MSTAFF_FX_X2, 0, 0}, // S_MSTAFF_FX_X1 + {SPR_MSP1, 32775, 5, A_Explode, S_MSTAFF_FX_X3, 0, 0}, // S_MSTAFF_FX_X2 + {SPR_MSP1, 32776, 4, NULL, S_MSTAFF_FX_X4, 0, 0}, // S_MSTAFF_FX_X3 + {SPR_MSP1, 32777, 5, NULL, S_MSTAFF_FX_X5, 0, 0}, // S_MSTAFF_FX_X4 + {SPR_MSP1, 32778, 4, NULL, S_MSTAFF_FX_X6, 0, 0}, // S_MSTAFF_FX_X5 + {SPR_MSP1, 32779, 5, NULL, S_MSTAFF_FX_X7, 0, 0}, // S_MSTAFF_FX_X6 + {SPR_MSP1, 32780, 4, NULL, S_MSTAFF_FX_X8, 0, 0}, // S_MSTAFF_FX_X7 + {SPR_MSP1, 32781, 5, NULL, S_MSTAFF_FX_X9, 0, 0}, // S_MSTAFF_FX_X8 + {SPR_MSP1, 32782, 4, NULL, S_MSTAFF_FX_X10, 0, 0}, // S_MSTAFF_FX_X9 + {SPR_MSP1, 32783, 4, NULL, S_NULL, 0, 0}, // S_MSTAFF_FX_X10 + {SPR_MSP2, 32768, 2, A_MStaffTrack, S_MSTAFF_FX2_2, 0, 0}, // S_MSTAFF_FX2_1 + {SPR_MSP2, 32769, 2, A_MStaffTrack, S_MSTAFF_FX2_3, 0, 0}, // S_MSTAFF_FX2_2 + {SPR_MSP2, 32770, 2, A_MStaffTrack, S_MSTAFF_FX2_4, 0, 0}, // S_MSTAFF_FX2_3 + {SPR_MSP2, 32771, 2, A_MStaffTrack, S_MSTAFF_FX2_1, 0, 0}, // S_MSTAFF_FX2_4 + {SPR_MSP2, 32772, 4, NULL, S_MSTAFF_FX2_X2, 0, 0}, // S_MSTAFF_FX2_X1 + {SPR_MSP2, 32773, 5, A_Explode, S_MSTAFF_FX2_X3, 0, 0}, // S_MSTAFF_FX2_X2 + {SPR_MSP2, 32774, 5, NULL, S_MSTAFF_FX2_X4, 0, 0}, // S_MSTAFF_FX2_X3 + {SPR_MSP2, 32775, 5, NULL, S_MSTAFF_FX2_X5, 0, 0}, // S_MSTAFF_FX2_X4 + {SPR_MSP2, 32776, 4, NULL, S_NULL, 0, 0}, // S_MSTAFF_FX2_X5 + {SPR_WFR1, 32768, -1, NULL, S_NULL, 0, 0}, // S_FSWORD1 + {SPR_WFR2, 32768, -1, NULL, S_NULL, 0, 0}, // S_FSWORD2 + {SPR_WFR3, 32768, -1, NULL, S_NULL, 0, 0}, // S_FSWORD3 + {SPR_WCH1, 32768, -1, NULL, S_NULL, 0, 0}, // S_CHOLY1 + {SPR_WCH2, 32768, -1, NULL, S_NULL, 0, 0}, // S_CHOLY2 + {SPR_WCH3, 32768, -1, NULL, S_NULL, 0, 0}, // S_CHOLY3 + {SPR_WMS1, 32768, -1, NULL, S_NULL, 0, 0}, // S_MSTAFF1 + {SPR_WMS2, 32768, -1, NULL, S_NULL, 0, 0}, // S_MSTAFF2 + {SPR_WMS3, 32768, -1, NULL, S_NULL, 0, 0}, // S_MSTAFF3 + {SPR_WPIG, 0, 1, A_WeaponReady, S_SNOUTREADY, 0, 0}, // S_SNOUTREADY + {SPR_WPIG, 0, 1, A_Lower, S_SNOUTDOWN, 0, 0}, // S_SNOUTDOWN + {SPR_WPIG, 0, 1, A_Raise, S_SNOUTUP, 0, 0}, // S_SNOUTUP + {SPR_WPIG, 0, 4, A_SnoutAttack, S_SNOUTATK2, 0, 0}, // S_SNOUTATK1 + {SPR_WPIG, 1, 8, A_SnoutAttack, S_SNOUTREADY, 0, 0}, // S_SNOUTATK2 + {SPR_WMCS, 32768, 8, NULL, S_COS2, 0, 0}, // S_COS1 + {SPR_WMCS, 32769, 8, NULL, S_COS3, 0, 0}, // S_COS2 + {SPR_WMCS, 32770, 8, NULL, S_COS1, 0, 0}, // S_COS3 + {SPR_CONE, 0, 1, A_WeaponReady, S_CONEREADY, 0, 0}, // S_CONEREADY + {SPR_CONE, 0, 1, A_Lower, S_CONEDOWN, 0, 0}, // S_CONEDOWN + {SPR_CONE, 0, 1, A_Raise, S_CONEUP, 0, 0}, // S_CONEUP + {SPR_CONE, 1, 3, NULL, S_CONEATK1_2, 0, 0}, // S_CONEATK1_1 + {SPR_CONE, 2, 4, NULL, S_CONEATK1_3, 0, 0}, // S_CONEATK1_2 + {SPR_CONE, 3, 3, NULL, S_CONEATK1_4, 0, 0}, // S_CONEATK1_3 + {SPR_CONE, 4, 5, NULL, S_CONEATK1_5, 0, 0}, // S_CONEATK1_4 + {SPR_CONE, 5, 3, A_FireConePL1, S_CONEATK1_6, 0, 0}, // S_CONEATK1_5 + {SPR_CONE, 6, 3, NULL, S_CONEATK1_7, 0, 0}, // S_CONEATK1_6 + {SPR_CONE, 0, 9, NULL, S_CONEATK1_8, 0, 0}, // S_CONEATK1_7 + {SPR_CONE, 0, 10, A_ReFire, S_CONEREADY, 0, 0}, // S_CONEATK1_8 + {SPR_SHRD, 32768, 2, NULL, S_SHARDFX1_2, 0, 0}, // S_SHARDFX1_1 + {SPR_SHRD, 32768, 3, A_ShedShard, S_SHARDFX1_3, 0, 0}, // S_SHARDFX1_2 + {SPR_SHRD, 32769, 3, NULL, S_SHARDFX1_4, 0, 0}, // S_SHARDFX1_3 + {SPR_SHRD, 32770, 3, NULL, S_SHARDFX1_1, 0, 0}, // S_SHARDFX1_4 + {SPR_SHEX, 32768, 5, NULL, S_SHARDFXE1_2, 0, 0}, // S_SHARDFXE1_1 + {SPR_SHEX, 32769, 5, NULL, S_SHARDFXE1_3, 0, 0}, // S_SHARDFXE1_2 + {SPR_SHEX, 32770, 5, NULL, S_SHARDFXE1_4, 0, 0}, // S_SHARDFXE1_3 + {SPR_SHEX, 32771, 5, NULL, S_SHARDFXE1_5, 0, 0}, // S_SHARDFXE1_4 + {SPR_SHEX, 32772, 5, NULL, S_NULL, 0, 0}, // S_SHARDFXE1_5 + {SPR_BLOD, 2, 8, NULL, S_BLOOD2, 0, 0}, // S_BLOOD1 + {SPR_BLOD, 1, 8, NULL, S_BLOOD3, 0, 0}, // S_BLOOD2 + {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOOD3 + {SPR_BLOD, 2, 8, NULL, S_BLOODSPLATTER2, 0, 0}, // S_BLOODSPLATTER1 + {SPR_BLOD, 1, 8, NULL, S_BLOODSPLATTER3, 0, 0}, // S_BLOODSPLATTER2 + {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTER3 + {SPR_BLOD, 0, 6, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTERX + {SPR_GIBS, 0, -1, NULL, S_NULL, 0, 0}, // S_GIBS1 + {SPR_PLAY, 0, -1, NULL, S_NULL, 0, 0}, // S_FPLAY + {SPR_PLAY, 0, 4, NULL, S_FPLAY_RUN2, 0, 0}, // S_FPLAY_RUN1 + {SPR_PLAY, 1, 4, NULL, S_FPLAY_RUN3, 0, 0}, // S_FPLAY_RUN2 + {SPR_PLAY, 2, 4, NULL, S_FPLAY_RUN4, 0, 0}, // S_FPLAY_RUN3 + {SPR_PLAY, 3, 4, NULL, S_FPLAY_RUN1, 0, 0}, // S_FPLAY_RUN4 + {SPR_PLAY, 4, 8, NULL, S_FPLAY_ATK2, 0, 0}, // S_FPLAY_ATK1 + {SPR_PLAY, 5, 8, NULL, S_FPLAY, 0, 0}, // S_FPLAY_ATK2 + {SPR_PLAY, 6, 4, NULL, S_FPLAY_PAIN2, 0, 0}, // S_FPLAY_PAIN + {SPR_PLAY, 6, 4, A_Pain, S_FPLAY, 0, 0}, // S_FPLAY_PAIN2 + {SPR_PLAY, 7, 6, NULL, S_FPLAY_DIE2, 0, 0}, // S_FPLAY_DIE1 + {SPR_PLAY, 8, 6, A_Scream, S_FPLAY_DIE3, 0, 0}, // S_FPLAY_DIE2 + {SPR_PLAY, 9, 6, NULL, S_FPLAY_DIE4, 0, 0}, // S_FPLAY_DIE3 + {SPR_PLAY, 10, 6, NULL, S_FPLAY_DIE5, 0, 0}, // S_FPLAY_DIE4 + {SPR_PLAY, 11, 6, A_NoBlocking, S_FPLAY_DIE6, 0, 0}, // S_FPLAY_DIE5 + {SPR_PLAY, 12, 6, NULL, S_FPLAY_DIE7, 0, 0}, // S_FPLAY_DIE6 + {SPR_PLAY, 13, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_FPLAY_DIE7 + {SPR_PLAY, 14, 5, A_Scream, S_FPLAY_XDIE2, 0, 0}, // S_FPLAY_XDIE1 + {SPR_PLAY, 15, 5, A_SkullPop, S_FPLAY_XDIE3, 0, 0}, // S_FPLAY_XDIE2 + {SPR_PLAY, 17, 5, A_NoBlocking, S_FPLAY_XDIE4, 0, 0}, // S_FPLAY_XDIE3 + {SPR_PLAY, 18, 5, NULL, S_FPLAY_XDIE5, 0, 0}, // S_FPLAY_XDIE4 + {SPR_PLAY, 19, 5, NULL, S_FPLAY_XDIE6, 0, 0}, // S_FPLAY_XDIE5 + {SPR_PLAY, 20, 5, NULL, S_FPLAY_XDIE7, 0, 0}, // S_FPLAY_XDIE6 + {SPR_PLAY, 21, 5, NULL, S_FPLAY_XDIE8, 0, 0}, // S_FPLAY_XDIE7 + {SPR_PLAY, 22, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_FPLAY_XDIE8 + {SPR_PLAY, 23, 5, A_FreezeDeath, S_FPLAY_ICE2, 0, 0}, // S_FPLAY_ICE + {SPR_PLAY, 23, 1, A_FreezeDeathChunks, S_FPLAY_ICE2, 0, 0}, // S_FPLAY_ICE2 + {SPR_FDTH, 32768, 5, NULL, S_PLAY_F_FDTH2, 0, 0}, // S_PLAY_F_FDTH1 + {SPR_FDTH, 32769, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_F_FDTH2 + {SPR_FDTH, 32770, 5, NULL, S_PLAY_C_FDTH2, 0, 0}, // S_PLAY_C_FDTH1 + {SPR_FDTH, 32771, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_C_FDTH2 + {SPR_FDTH, 32772, 5, NULL, S_PLAY_M_FDTH2, 0, 0}, // S_PLAY_M_FDTH1 + {SPR_FDTH, 32773, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_M_FDTH2 + {SPR_FDTH, 32774, 5, NULL, S_PLAY_FDTH4, 0, 0}, // S_PLAY_FDTH3 + {SPR_FDTH, 32775, 4, A_Scream, S_PLAY_FDTH5, 0, 0}, // S_PLAY_FDTH4 + {SPR_FDTH, 32776, 5, NULL, S_PLAY_FDTH6, 0, 0}, // S_PLAY_FDTH5 + {SPR_FDTH, 32777, 4, NULL, S_PLAY_FDTH7, 0, 0}, // S_PLAY_FDTH6 + {SPR_FDTH, 32778, 5, NULL, S_PLAY_FDTH8, 0, 0}, // S_PLAY_FDTH7 + {SPR_FDTH, 32779, 4, NULL, S_PLAY_FDTH9, 0, 0}, // S_PLAY_FDTH8 + {SPR_FDTH, 32780, 5, NULL, S_PLAY_FDTH10, 0, 0}, // S_PLAY_FDTH9 + {SPR_FDTH, 32781, 4, NULL, S_PLAY_FDTH11, 0, 0}, // S_PLAY_FDTH10 + {SPR_FDTH, 32782, 5, NULL, S_PLAY_FDTH12, 0, 0}, // S_PLAY_FDTH11 + {SPR_FDTH, 32783, 4, NULL, S_PLAY_FDTH13, 0, 0}, // S_PLAY_FDTH12 + {SPR_FDTH, 32784, 5, NULL, S_PLAY_FDTH14, 0, 0}, // S_PLAY_FDTH13 + {SPR_FDTH, 32785, 4, NULL, S_PLAY_FDTH15, 0, 0}, // S_PLAY_FDTH14 + {SPR_FDTH, 32786, 5, A_NoBlocking, S_PLAY_FDTH16, 0, 0}, // S_PLAY_FDTH15 + {SPR_FDTH, 32787, 4, NULL, S_PLAY_FDTH17, 0, 0}, // S_PLAY_FDTH16 + {SPR_FDTH, 32788, 5, NULL, S_PLAY_FDTH18, 0, 0}, // S_PLAY_FDTH17 + {SPR_FDTH, 32789, 4, NULL, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH18 + {SPR_ACLO, 4, 35, A_CheckBurnGone, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH19 + {SPR_ACLO, 4, 8, NULL, S_NULL, 0, 0}, // S_PLAY_FDTH20 + {SPR_BSKL, 0, 5, A_CheckSkullFloor, S_BLOODYSKULL2, 0, 0}, // S_BLOODYSKULL1 + {SPR_BSKL, 1, 5, A_CheckSkullFloor, S_BLOODYSKULL3, 0, 0}, // S_BLOODYSKULL2 + {SPR_BSKL, 2, 5, A_CheckSkullFloor, S_BLOODYSKULL4, 0, 0}, // S_BLOODYSKULL3 + {SPR_BSKL, 3, 5, A_CheckSkullFloor, S_BLOODYSKULL5, 0, 0}, // S_BLOODYSKULL4 + {SPR_BSKL, 5, 5, A_CheckSkullFloor, S_BLOODYSKULL6, 0, 0}, // S_BLOODYSKULL5 + {SPR_BSKL, 6, 5, A_CheckSkullFloor, S_BLOODYSKULL7, 0, 0}, // S_BLOODYSKULL6 + {SPR_BSKL, 7, 5, A_CheckSkullFloor, S_BLOODYSKULL1, 0, 0}, // S_BLOODYSKULL7 + {SPR_BSKL, 8, 16, A_CheckSkullDone, S_BLOODYSKULLX1, 0, 0}, // S_BLOODYSKULLX1 + {SPR_BSKL, 8, 1050, NULL, S_NULL, 0, 0}, // S_BLOODYSKULLX2 + {SPR_PLAY, 0, 5, NULL, S_PLAYER_SPEED2, 0, 0}, // S_PLAYER_SPEED1 + {SPR_PLAY, 0, 3, A_SpeedFade, S_NULL, 0, 0}, // S_PLAYER_SPEED2 + {SPR_ICEC, 0, 10, NULL, S_ICECHUNK2, 0, 0}, // S_ICECHUNK1 + {SPR_ICEC, 1, 10, A_IceSetTics, S_ICECHUNK3, 0, 0}, // S_ICECHUNK2 + {SPR_ICEC, 2, 10, A_IceSetTics, S_ICECHUNK4, 0, 0}, // S_ICECHUNK3 + {SPR_ICEC, 3, 10, A_IceSetTics, S_NULL, 0, 0}, // S_ICECHUNK4 + {SPR_ICEC, 0, 10, A_IceCheckHeadDone, S_ICECHUNK_HEAD, 0, 0}, // S_ICECHUNK_HEAD + {SPR_ICEC, 0, 1050, NULL, S_NULL, 0, 0}, // S_ICECHUNK_HEAD2 + {SPR_CLER, 0, -1, NULL, S_NULL, 0, 0}, // S_CPLAY + {SPR_CLER, 0, 4, NULL, S_CPLAY_RUN2, 0, 0}, // S_CPLAY_RUN1 + {SPR_CLER, 1, 4, NULL, S_CPLAY_RUN3, 0, 0}, // S_CPLAY_RUN2 + {SPR_CLER, 2, 4, NULL, S_CPLAY_RUN4, 0, 0}, // S_CPLAY_RUN3 + {SPR_CLER, 3, 4, NULL, S_CPLAY_RUN1, 0, 0}, // S_CPLAY_RUN4 + {SPR_CLER, 4, 6, NULL, S_CPLAY_ATK2, 0, 0}, // S_CPLAY_ATK1 + {SPR_CLER, 5, 6, NULL, S_CPLAY_ATK3, 0, 0}, // S_CPLAY_ATK2 + {SPR_CLER, 6, 6, NULL, S_CPLAY, 0, 0}, // S_CPLAY_ATK3 + {SPR_CLER, 7, 4, NULL, S_CPLAY_PAIN2, 0, 0}, // S_CPLAY_PAIN + {SPR_CLER, 7, 4, A_Pain, S_CPLAY, 0, 0}, // S_CPLAY_PAIN2 + {SPR_CLER, 8, 6, NULL, S_CPLAY_DIE2, 0, 0}, // S_CPLAY_DIE1 + {SPR_CLER, 10, 6, A_Scream, S_CPLAY_DIE3, 0, 0}, // S_CPLAY_DIE2 + {SPR_CLER, 11, 6, NULL, S_CPLAY_DIE4, 0, 0}, // S_CPLAY_DIE3 + {SPR_CLER, 11, 6, NULL, S_CPLAY_DIE5, 0, 0}, // S_CPLAY_DIE4 + {SPR_CLER, 12, 6, A_NoBlocking, S_CPLAY_DIE6, 0, 0}, // S_CPLAY_DIE5 + {SPR_CLER, 13, 6, NULL, S_CPLAY_DIE7, 0, 0}, // S_CPLAY_DIE6 + {SPR_CLER, 14, 6, NULL, S_CPLAY_DIE8, 0, 0}, // S_CPLAY_DIE7 + {SPR_CLER, 15, 6, NULL, S_CPLAY_DIE9, 0, 0}, // S_CPLAY_DIE8 + {SPR_CLER, 16, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_CPLAY_DIE9 + {SPR_CLER, 17, 5, A_Scream, S_CPLAY_XDIE2, 0, 0}, // S_CPLAY_XDIE1 + {SPR_CLER, 18, 5, NULL, S_CPLAY_XDIE3, 0, 0}, // S_CPLAY_XDIE2 + {SPR_CLER, 19, 5, A_NoBlocking, S_CPLAY_XDIE4, 0, 0}, // S_CPLAY_XDIE3 + {SPR_CLER, 20, 5, NULL, S_CPLAY_XDIE5, 0, 0}, // S_CPLAY_XDIE4 + {SPR_CLER, 21, 5, NULL, S_CPLAY_XDIE6, 0, 0}, // S_CPLAY_XDIE5 + {SPR_CLER, 22, 5, NULL, S_CPLAY_XDIE7, 0, 0}, // S_CPLAY_XDIE6 + {SPR_CLER, 23, 5, NULL, S_CPLAY_XDIE8, 0, 0}, // S_CPLAY_XDIE7 + {SPR_CLER, 24, 5, NULL, S_CPLAY_XDIE9, 0, 0}, // S_CPLAY_XDIE8 + {SPR_CLER, 25, 5, NULL, S_CPLAY_XDIE10, 0, 0}, // S_CPLAY_XDIE9 + {SPR_CLER, 26, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_CPLAY_XDIE10 + {SPR_CLER, 27, 5, A_FreezeDeath, S_CPLAY_ICE2, 0, 0}, // S_CPLAY_ICE + {SPR_CLER, 27, 1, A_FreezeDeathChunks, S_CPLAY_ICE2, 0, 0}, // S_CPLAY_ICE2 + {SPR_MAGE, 0, -1, NULL, S_NULL, 0, 0}, // S_MPLAY + {SPR_MAGE, 0, 4, NULL, S_MPLAY_RUN2, 0, 0}, // S_MPLAY_RUN1 + {SPR_MAGE, 1, 4, NULL, S_MPLAY_RUN3, 0, 0}, // S_MPLAY_RUN2 + {SPR_MAGE, 2, 4, NULL, S_MPLAY_RUN4, 0, 0}, // S_MPLAY_RUN3 + {SPR_MAGE, 3, 4, NULL, S_MPLAY_RUN1, 0, 0}, // S_MPLAY_RUN4 + {SPR_MAGE, 4, 8, NULL, S_MPLAY_ATK2, 0, 0}, // S_MPLAY_ATK1 + {SPR_MAGE, 32773, 8, NULL, S_MPLAY, 0, 0}, // S_MPLAY_ATK2 + {SPR_MAGE, 6, 4, NULL, S_MPLAY_PAIN2, 0, 0}, // S_MPLAY_PAIN + {SPR_MAGE, 6, 4, A_Pain, S_MPLAY, 0, 0}, // S_MPLAY_PAIN2 + {SPR_MAGE, 7, 6, NULL, S_MPLAY_DIE2, 0, 0}, // S_MPLAY_DIE1 + {SPR_MAGE, 8, 6, A_Scream, S_MPLAY_DIE3, 0, 0}, // S_MPLAY_DIE2 + {SPR_MAGE, 9, 6, NULL, S_MPLAY_DIE4, 0, 0}, // S_MPLAY_DIE3 + {SPR_MAGE, 10, 6, NULL, S_MPLAY_DIE5, 0, 0}, // S_MPLAY_DIE4 + {SPR_MAGE, 11, 6, A_NoBlocking, S_MPLAY_DIE6, 0, 0}, // S_MPLAY_DIE5 + {SPR_MAGE, 12, 6, NULL, S_MPLAY_DIE7, 0, 0}, // S_MPLAY_DIE6 + {SPR_MAGE, 13, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_MPLAY_DIE7 + {SPR_MAGE, 14, 5, A_Scream, S_MPLAY_XDIE2, 0, 0}, // S_MPLAY_XDIE1 + {SPR_MAGE, 15, 5, NULL, S_MPLAY_XDIE3, 0, 0}, // S_MPLAY_XDIE2 + {SPR_MAGE, 17, 5, A_NoBlocking, S_MPLAY_XDIE4, 0, 0}, // S_MPLAY_XDIE3 + {SPR_MAGE, 18, 5, NULL, S_MPLAY_XDIE5, 0, 0}, // S_MPLAY_XDIE4 + {SPR_MAGE, 19, 5, NULL, S_MPLAY_XDIE6, 0, 0}, // S_MPLAY_XDIE5 + {SPR_MAGE, 20, 5, NULL, S_MPLAY_XDIE7, 0, 0}, // S_MPLAY_XDIE6 + {SPR_MAGE, 21, 5, NULL, S_MPLAY_XDIE8, 0, 0}, // S_MPLAY_XDIE7 + {SPR_MAGE, 22, 5, NULL, S_MPLAY_XDIE9, 0, 0}, // S_MPLAY_XDIE8 + {SPR_MAGE, 23, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_MPLAY_XDIE9 + {SPR_MAGE, 24, 5, A_FreezeDeath, S_MPLAY_ICE2, 0, 0}, // S_MPLAY_ICE + {SPR_MAGE, 24, 1, A_FreezeDeathChunks, S_MPLAY_ICE2, 0, 0}, // S_MPLAY_ICE2 + {SPR_PIGY, 0, -1, NULL, S_NULL, 0, 0}, // S_PIGPLAY + {SPR_PIGY, 0, 3, NULL, S_PIGPLAY_RUN2, 0, 0}, // S_PIGPLAY_RUN1 + {SPR_PIGY, 1, 3, NULL, S_PIGPLAY_RUN3, 0, 0}, // S_PIGPLAY_RUN2 + {SPR_PIGY, 2, 3, NULL, S_PIGPLAY_RUN4, 0, 0}, // S_PIGPLAY_RUN3 + {SPR_PIGY, 3, 3, NULL, S_PIGPLAY_RUN1, 0, 0}, // S_PIGPLAY_RUN4 + {SPR_PIGY, 0, 12, NULL, S_PIGPLAY, 0, 0}, // S_PIGPLAY_ATK1 + {SPR_PIGY, 3, 4, A_PigPain, S_PIGPLAY, 0, 0}, // S_PIGPLAY_PAIN + {SPR_PIGY, 1, 10, A_PigLook, S_PIG_LOOK1, 0, 0}, // S_PIG_LOOK1 + {SPR_PIGY, 0, 3, A_PigChase, S_PIG_WALK2, 0, 0}, // S_PIG_WALK1 + {SPR_PIGY, 1, 3, A_PigChase, S_PIG_WALK3, 0, 0}, // S_PIG_WALK2 + {SPR_PIGY, 2, 3, A_PigChase, S_PIG_WALK4, 0, 0}, // S_PIG_WALK3 + {SPR_PIGY, 3, 3, A_PigChase, S_PIG_WALK1, 0, 0}, // S_PIG_WALK4 + {SPR_PIGY, 3, 4, A_PigPain, S_PIG_WALK1, 0, 0}, // S_PIG_PAIN + {SPR_PIGY, 0, 5, A_FaceTarget, S_PIG_ATK2, 0, 0}, // S_PIG_ATK1 + {SPR_PIGY, 0, 10, A_PigAttack, S_PIG_WALK1, 0, 0}, // S_PIG_ATK2 + {SPR_PIGY, 4, 4, A_Scream, S_PIG_DIE2, 0, 0}, // S_PIG_DIE1 + {SPR_PIGY, 5, 3, A_NoBlocking, S_PIG_DIE3, 0, 0}, // S_PIG_DIE2 + {SPR_PIGY, 6, 4, A_QueueCorpse, S_PIG_DIE4, 0, 0}, // S_PIG_DIE3 + {SPR_PIGY, 7, 3, NULL, S_PIG_DIE5, 0, 0}, // S_PIG_DIE4 + {SPR_PIGY, 8, 4, NULL, S_PIG_DIE6, 0, 0}, // S_PIG_DIE5 + {SPR_PIGY, 9, 4, NULL, S_PIG_DIE7, 0, 0}, // S_PIG_DIE6 + {SPR_PIGY, 10, 4, NULL, S_PIG_DIE8, 0, 0}, // S_PIG_DIE7 + {SPR_PIGY, 11, -1, NULL, S_NULL, 0, 0}, // S_PIG_DIE8 + {SPR_PIGY, 12, 5, A_FreezeDeath, S_PIG_ICE2, 0, 0}, // S_PIG_ICE + {SPR_PIGY, 12, 1, A_FreezeDeathChunks, S_PIG_ICE2, 0, 0}, // S_PIG_ICE2 + {SPR_CENT, 0, 10, A_Look, S_CENTAUR_LOOK2, 0, 0}, // S_CENTAUR_LOOK1 + {SPR_CENT, 1, 10, A_Look, S_CENTAUR_LOOK1, 0, 0}, // S_CENTAUR_LOOK2 + {SPR_CENT, 0, 4, A_Chase, S_CENTAUR_WALK2, 0, 0}, // S_CENTAUR_WALK1 + {SPR_CENT, 1, 4, A_Chase, S_CENTAUR_WALK3, 0, 0}, // S_CENTAUR_WALK2 + {SPR_CENT, 2, 4, A_Chase, S_CENTAUR_WALK4, 0, 0}, // S_CENTAUR_WALK3 + {SPR_CENT, 3, 4, A_Chase, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_WALK4 + {SPR_CENT, 7, 5, A_FaceTarget, S_CENTAUR_ATK2, 0, 0}, // S_CENTAUR_ATK1 + {SPR_CENT, 8, 4, A_FaceTarget, S_CENTAUR_ATK3, 0, 0}, // S_CENTAUR_ATK2 + {SPR_CENT, 9, 7, A_CentaurAttack, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_ATK3 + {SPR_CENT, 4, 10, A_FaceTarget, S_CENTAUR_MISSILE2, 0, 0}, // S_CENTAUR_MISSILE1 + {SPR_CENT, 32773, 8, A_CentaurAttack2, S_CENTAUR_MISSILE3, 0, 0}, // S_CENTAUR_MISSILE2 + {SPR_CENT, 4, 10, A_FaceTarget, S_CENTAUR_MISSILE4, 0, 0}, // S_CENTAUR_MISSILE3 + {SPR_CENT, 32773, 8, A_CentaurAttack2, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_MISSILE4 + {SPR_CENT, 6, 6, A_Pain, S_CENTAUR_PAIN2, 0, 0}, // S_CENTAUR_PAIN1 + {SPR_CENT, 6, 6, A_SetReflective, S_CENTAUR_PAIN3, 0, 0}, // S_CENTAUR_PAIN2 + {SPR_CENT, 4, 15, A_CentaurDefend, S_CENTAUR_PAIN4, 0, 0}, // S_CENTAUR_PAIN3 + {SPR_CENT, 4, 15, A_CentaurDefend, S_CENTAUR_PAIN5, 0, 0}, // S_CENTAUR_PAIN4 + {SPR_CENT, 4, 15, A_CentaurDefend, S_CENTAUR_PAIN6, 0, 0}, // S_CENTAUR_PAIN5 + {SPR_CENT, 4, 1, A_UnSetReflective, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_PAIN6 + {SPR_CENT, 10, 4, NULL, S_CENTAUR_DEATH2, 0, 0}, // S_CENTAUR_DEATH1 + {SPR_CENT, 11, 4, A_Scream, S_CENTAUR_DEATH3, 0, 0}, // S_CENTAUR_DEATH2 + {SPR_CENT, 12, 4, NULL, S_CENTAUR_DEATH4, 0, 0}, // S_CENTAUR_DEATH3 + {SPR_CENT, 13, 4, NULL, S_CENTAUR_DEATH5, 0, 0}, // S_CENTAUR_DEATH4 + {SPR_CENT, 14, 4, A_NoBlocking, S_CENTAUR_DEATH6, 0, 0}, // S_CENTAUR_DEATH5 + {SPR_CENT, 15, 4, NULL, S_CENTAUR_DEATH7, 0, 0}, // S_CENTAUR_DEATH6 + {SPR_CENT, 16, 4, NULL, S_CENTAUR_DEATH8, 0, 0}, // S_CENTAUR_DEATH7 + {SPR_CENT, 17, 4, A_QueueCorpse, S_CENTAUR_DEATH9, 0, 0}, // S_CENTAUR_DEATH8 + {SPR_CENT, 18, 4, NULL, S_CENTAUR_DEATH0, 0, 0}, // S_CENTAUR_DEATH9 + {SPR_CENT, 19, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_DEATH0 + {SPR_CTXD, 0, 4, NULL, S_CENTAUR_DEATH_X2, 0, 0}, // S_CENTAUR_DEATH_X1 + {SPR_CTXD, 1, 4, A_NoBlocking, S_CENTAUR_DEATH_X3, 0, 0}, // S_CENTAUR_DEATH_X2 + {SPR_CTXD, 2, 4, A_CentaurDropStuff, S_CENTAUR_DEATH_X4, 0, 0}, // S_CENTAUR_DEATH_X3 + {SPR_CTXD, 3, 3, A_Scream, S_CENTAUR_DEATH_X5, 0, 0}, // S_CENTAUR_DEATH_X4 + {SPR_CTXD, 4, 4, A_QueueCorpse, S_CENTAUR_DEATH_X6, 0, 0}, // S_CENTAUR_DEATH_X5 + {SPR_CTXD, 5, 3, NULL, S_CENTAUR_DEATH_X7, 0, 0}, // S_CENTAUR_DEATH_X6 + {SPR_CTXD, 6, 4, NULL, S_CENTAUR_DEATH_X8, 0, 0}, // S_CENTAUR_DEATH_X7 + {SPR_CTXD, 7, 3, NULL, S_CENTAUR_DEATH_X9, 0, 0}, // S_CENTAUR_DEATH_X8 + {SPR_CTXD, 8, 4, NULL, S_CENTAUR_DEATH_X10, 0, 0}, // S_CENTAUR_DEATH_X9 + {SPR_CTXD, 9, 3, NULL, S_CENTAUR_DEATH_X11, 0, 0}, // S_CENTAUR_DEATH_X10 + {SPR_CTXD, 10, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_DEATH_X11 + {SPR_CENT, 20, 5, A_FreezeDeath, S_CENTAUR_ICE2, 0, 0}, // S_CENTAUR_ICE + {SPR_CENT, 20, 1, A_FreezeDeathChunks, S_CENTAUR_ICE2, 0, 0}, // S_CENTAUR_ICE2 + {SPR_CTFX, 32768, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_FX1 + {SPR_CTFX, 32769, 4, NULL, S_CENTAUR_FX_X2, 0, 0}, // S_CENTAUR_FX_X1 + {SPR_CTFX, 32770, 3, NULL, S_CENTAUR_FX_X3, 0, 0}, // S_CENTAUR_FX_X2 + {SPR_CTFX, 32771, 4, NULL, S_CENTAUR_FX_X4, 0, 0}, // S_CENTAUR_FX_X3 + {SPR_CTFX, 32772, 3, NULL, S_CENTAUR_FX_X5, 0, 0}, // S_CENTAUR_FX_X4 + {SPR_CTFX, 32773, 2, NULL, S_NULL, 0, 0}, // S_CENTAUR_FX_X5 + {SPR_CTDP, 0, 3, A_CheckFloor, S_CENTAUR_SHIELD2, 0, 0}, // S_CENTAUR_SHIELD1 + {SPR_CTDP, 1, 3, A_CheckFloor, S_CENTAUR_SHIELD3, 0, 0}, // S_CENTAUR_SHIELD2 + {SPR_CTDP, 2, 3, A_CheckFloor, S_CENTAUR_SHIELD4, 0, 0}, // S_CENTAUR_SHIELD3 + {SPR_CTDP, 3, 3, A_CheckFloor, S_CENTAUR_SHIELD5, 0, 0}, // S_CENTAUR_SHIELD4 + {SPR_CTDP, 4, 3, A_CheckFloor, S_CENTAUR_SHIELD6, 0, 0}, // S_CENTAUR_SHIELD5 + {SPR_CTDP, 5, 3, A_CheckFloor, S_CENTAUR_SHIELD3, 0, 0}, // S_CENTAUR_SHIELD6 + {SPR_CTDP, 6, 4, NULL, S_CENTAUR_SHIELD_X2, 0, 0}, // S_CENTAUR_SHIELD_X1 + {SPR_CTDP, 7, 4, A_QueueCorpse, S_CENTAUR_SHIELD_X3, 0, 0}, // S_CENTAUR_SHIELD_X2 + {SPR_CTDP, 8, 4, NULL, S_CENTAUR_SHIELD_X4, 0, 0}, // S_CENTAUR_SHIELD_X3 + {SPR_CTDP, 9, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_SHIELD_X4 + {SPR_CTDP, 10, 3, A_CheckFloor, S_CENTAUR_SWORD2, 0, 0}, // S_CENTAUR_SWORD1 + {SPR_CTDP, 11, 3, A_CheckFloor, S_CENTAUR_SWORD3, 0, 0}, // S_CENTAUR_SWORD2 + {SPR_CTDP, 12, 3, A_CheckFloor, S_CENTAUR_SWORD4, 0, 0}, // S_CENTAUR_SWORD3 + {SPR_CTDP, 13, 3, A_CheckFloor, S_CENTAUR_SWORD5, 0, 0}, // S_CENTAUR_SWORD4 + {SPR_CTDP, 14, 3, A_CheckFloor, S_CENTAUR_SWORD6, 0, 0}, // S_CENTAUR_SWORD5 + {SPR_CTDP, 15, 3, A_CheckFloor, S_CENTAUR_SWORD7, 0, 0}, // S_CENTAUR_SWORD6 + {SPR_CTDP, 16, 3, A_CheckFloor, S_CENTAUR_SWORD3, 0, 0}, // S_CENTAUR_SWORD7 + {SPR_CTDP, 17, 4, NULL, S_CENTAUR_SWORD_X2, 0, 0}, // S_CENTAUR_SWORD_X1 + {SPR_CTDP, 18, 4, A_QueueCorpse, S_CENTAUR_SWORD_X3, 0, 0}, // S_CENTAUR_SWORD_X2 + {SPR_CTDP, 19, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_SWORD_X3 + {SPR_DEMN, 0, 10, A_Look, S_DEMN_LOOK2, 0, 0}, // S_DEMN_LOOK1 + {SPR_DEMN, 0, 10, A_Look, S_DEMN_LOOK1, 0, 0}, // S_DEMN_LOOK2 + {SPR_DEMN, 0, 4, A_Chase, S_DEMN_CHASE2, 0, 0}, // S_DEMN_CHASE1 + {SPR_DEMN, 1, 4, A_Chase, S_DEMN_CHASE3, 0, 0}, // S_DEMN_CHASE2 + {SPR_DEMN, 2, 4, A_Chase, S_DEMN_CHASE4, 0, 0}, // S_DEMN_CHASE3 + {SPR_DEMN, 3, 4, A_Chase, S_DEMN_CHASE1, 0, 0}, // S_DEMN_CHASE4 + {SPR_DEMN, 4, 6, A_FaceTarget, S_DEMN_ATK1_2, 0, 0}, // S_DEMN_ATK1_1 + {SPR_DEMN, 5, 8, A_FaceTarget, S_DEMN_ATK1_3, 0, 0}, // S_DEMN_ATK1_2 + {SPR_DEMN, 6, 6, A_DemonAttack1, S_DEMN_CHASE1, 0, 0}, // S_DEMN_ATK1_3 + {SPR_DEMN, 4, 5, A_FaceTarget, S_DEMN_ATK2_2, 0, 0}, // S_DEMN_ATK2_1 + {SPR_DEMN, 5, 6, A_FaceTarget, S_DEMN_ATK2_3, 0, 0}, // S_DEMN_ATK2_2 + {SPR_DEMN, 6, 5, A_DemonAttack2, S_DEMN_CHASE1, 0, 0}, // S_DEMN_ATK2_3 + {SPR_DEMN, 4, 4, NULL, S_DEMN_PAIN2, 0, 0}, // S_DEMN_PAIN1 + {SPR_DEMN, 4, 4, A_Pain, S_DEMN_CHASE1, 0, 0}, // S_DEMN_PAIN2 + {SPR_DEMN, 7, 6, NULL, S_DEMN_DEATH2, 0, 0}, // S_DEMN_DEATH1 + {SPR_DEMN, 8, 6, NULL, S_DEMN_DEATH3, 0, 0}, // S_DEMN_DEATH2 + {SPR_DEMN, 9, 6, A_Scream, S_DEMN_DEATH4, 0, 0}, // S_DEMN_DEATH3 + {SPR_DEMN, 10, 6, A_NoBlocking, S_DEMN_DEATH5, 0, 0}, // S_DEMN_DEATH4 + {SPR_DEMN, 11, 6, A_QueueCorpse, S_DEMN_DEATH6, 0, 0}, // S_DEMN_DEATH5 + {SPR_DEMN, 12, 6, NULL, S_DEMN_DEATH7, 0, 0}, // S_DEMN_DEATH6 + {SPR_DEMN, 13, 6, NULL, S_DEMN_DEATH8, 0, 0}, // S_DEMN_DEATH7 + {SPR_DEMN, 14, 6, NULL, S_DEMN_DEATH9, 0, 0}, // S_DEMN_DEATH8 + {SPR_DEMN, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN_DEATH9 + {SPR_DEMN, 7, 6, NULL, S_DEMN_XDEATH2, 0, 0}, // S_DEMN_XDEATH1 + {SPR_DEMN, 8, 6, A_DemonDeath, S_DEMN_XDEATH3, 0, 0}, // S_DEMN_XDEATH2 + {SPR_DEMN, 9, 6, A_Scream, S_DEMN_XDEATH4, 0, 0}, // S_DEMN_XDEATH3 + {SPR_DEMN, 10, 6, A_NoBlocking, S_DEMN_XDEATH5, 0, 0}, // S_DEMN_XDEATH4 + {SPR_DEMN, 11, 6, A_QueueCorpse, S_DEMN_XDEATH6, 0, 0}, // S_DEMN_XDEATH5 + {SPR_DEMN, 12, 6, NULL, S_DEMN_XDEATH7, 0, 0}, // S_DEMN_XDEATH6 + {SPR_DEMN, 13, 6, NULL, S_DEMN_XDEATH8, 0, 0}, // S_DEMN_XDEATH7 + {SPR_DEMN, 14, 6, NULL, S_DEMN_XDEATH9, 0, 0}, // S_DEMN_XDEATH8 + {SPR_DEMN, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN_XDEATH9 + {SPR_DEMN, 16, 5, A_FreezeDeath, S_DEMON_ICE2, 0, 0}, // S_DEMON_ICE + {SPR_DEMN, 16, 1, A_FreezeDeathChunks, S_DEMON_ICE2, 0, 0}, // S_DEMON_ICE2 + {SPR_DEMA, 0, 4, NULL, S_DEMONCHUNK1_2, 0, 0}, // S_DEMONCHUNK1_1 + {SPR_DEMA, 0, 10, A_QueueCorpse, S_DEMONCHUNK1_3, 0, 0}, // S_DEMONCHUNK1_2 + {SPR_DEMA, 0, 20, NULL, S_DEMONCHUNK1_3, 0, 0}, // S_DEMONCHUNK1_3 + {SPR_DEMA, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK1_4 + {SPR_DEMB, 0, 4, NULL, S_DEMONCHUNK2_2, 0, 0}, // S_DEMONCHUNK2_1 + {SPR_DEMB, 0, 10, A_QueueCorpse, S_DEMONCHUNK2_3, 0, 0}, // S_DEMONCHUNK2_2 + {SPR_DEMB, 0, 20, NULL, S_DEMONCHUNK2_3, 0, 0}, // S_DEMONCHUNK2_3 + {SPR_DEMB, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK2_4 + {SPR_DEMC, 0, 4, NULL, S_DEMONCHUNK3_2, 0, 0}, // S_DEMONCHUNK3_1 + {SPR_DEMC, 0, 10, A_QueueCorpse, S_DEMONCHUNK3_3, 0, 0}, // S_DEMONCHUNK3_2 + {SPR_DEMC, 0, 20, NULL, S_DEMONCHUNK3_3, 0, 0}, // S_DEMONCHUNK3_3 + {SPR_DEMC, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK3_4 + {SPR_DEMD, 0, 4, NULL, S_DEMONCHUNK4_2, 0, 0}, // S_DEMONCHUNK4_1 + {SPR_DEMD, 0, 10, A_QueueCorpse, S_DEMONCHUNK4_3, 0, 0}, // S_DEMONCHUNK4_2 + {SPR_DEMD, 0, 20, NULL, S_DEMONCHUNK4_3, 0, 0}, // S_DEMONCHUNK4_3 + {SPR_DEMD, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK4_4 + {SPR_DEME, 0, 4, NULL, S_DEMONCHUNK5_2, 0, 0}, // S_DEMONCHUNK5_1 + {SPR_DEME, 0, 10, A_QueueCorpse, S_DEMONCHUNK5_3, 0, 0}, // S_DEMONCHUNK5_2 + {SPR_DEME, 0, 20, NULL, S_DEMONCHUNK5_3, 0, 0}, // S_DEMONCHUNK5_3 + {SPR_DEME, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK5_4 + {SPR_DMFX, 32768, 4, NULL, S_DEMONFX_MOVE2, 0, 0}, // S_DEMONFX_MOVE1 + {SPR_DMFX, 32769, 4, NULL, S_DEMONFX_MOVE3, 0, 0}, // S_DEMONFX_MOVE2 + {SPR_DMFX, 32770, 4, NULL, S_DEMONFX_MOVE1, 0, 0}, // S_DEMONFX_MOVE3 + {SPR_DMFX, 32771, 4, NULL, S_DEMONFX_BOOM2, 0, 0}, // S_DEMONFX_BOOM1 + {SPR_DMFX, 32772, 4, NULL, S_DEMONFX_BOOM3, 0, 0}, // S_DEMONFX_BOOM2 + {SPR_DMFX, 32773, 3, NULL, S_DEMONFX_BOOM4, 0, 0}, // S_DEMONFX_BOOM3 + {SPR_DMFX, 32774, 3, NULL, S_DEMONFX_BOOM5, 0, 0}, // S_DEMONFX_BOOM4 + {SPR_DMFX, 32775, 3, NULL, S_NULL, 0, 0}, // S_DEMONFX_BOOM5 + {SPR_DEM2, 0, 10, A_Look, S_DEMN2_LOOK2, 0, 0}, // S_DEMN2_LOOK1 + {SPR_DEM2, 0, 10, A_Look, S_DEMN2_LOOK1, 0, 0}, // S_DEMN2_LOOK2 + {SPR_DEM2, 0, 4, A_Chase, S_DEMN2_CHASE2, 0, 0}, // S_DEMN2_CHASE1 + {SPR_DEM2, 1, 4, A_Chase, S_DEMN2_CHASE3, 0, 0}, // S_DEMN2_CHASE2 + {SPR_DEM2, 2, 4, A_Chase, S_DEMN2_CHASE4, 0, 0}, // S_DEMN2_CHASE3 + {SPR_DEM2, 3, 4, A_Chase, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_CHASE4 + {SPR_DEM2, 4, 6, A_FaceTarget, S_DEMN2_ATK1_2, 0, 0}, // S_DEMN2_ATK1_1 + {SPR_DEM2, 5, 8, A_FaceTarget, S_DEMN2_ATK1_3, 0, 0}, // S_DEMN2_ATK1_2 + {SPR_DEM2, 6, 6, A_DemonAttack1, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_ATK1_3 + {SPR_DEM2, 4, 5, A_FaceTarget, S_DEMN2_ATK2_2, 0, 0}, // S_DEMN2_ATK2_1 + {SPR_DEM2, 5, 6, A_FaceTarget, S_DEMN2_ATK2_3, 0, 0}, // S_DEMN2_ATK2_2 + {SPR_DEM2, 6, 5, A_DemonAttack2, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_ATK2_3 + {SPR_DEM2, 4, 4, NULL, S_DEMN2_PAIN2, 0, 0}, // S_DEMN2_PAIN1 + {SPR_DEM2, 4, 4, A_Pain, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_PAIN2 + {SPR_DEM2, 7, 6, NULL, S_DEMN2_DEATH2, 0, 0}, // S_DEMN2_DEATH1 + {SPR_DEM2, 8, 6, NULL, S_DEMN2_DEATH3, 0, 0}, // S_DEMN2_DEATH2 + {SPR_DEM2, 9, 6, A_Scream, S_DEMN2_DEATH4, 0, 0}, // S_DEMN2_DEATH3 + {SPR_DEM2, 10, 6, A_NoBlocking, S_DEMN2_DEATH5, 0, 0}, // S_DEMN2_DEATH4 + {SPR_DEM2, 11, 6, A_QueueCorpse, S_DEMN2_DEATH6, 0, 0}, // S_DEMN2_DEATH5 + {SPR_DEM2, 12, 6, NULL, S_DEMN2_DEATH7, 0, 0}, // S_DEMN2_DEATH6 + {SPR_DEM2, 13, 6, NULL, S_DEMN2_DEATH8, 0, 0}, // S_DEMN2_DEATH7 + {SPR_DEM2, 14, 6, NULL, S_DEMN2_DEATH9, 0, 0}, // S_DEMN2_DEATH8 + {SPR_DEM2, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN2_DEATH9 + {SPR_DEM2, 7, 6, NULL, S_DEMN2_XDEATH2, 0, 0}, // S_DEMN2_XDEATH1 + {SPR_DEM2, 8, 6, A_Demon2Death, S_DEMN2_XDEATH3, 0, 0}, // S_DEMN2_XDEATH2 + {SPR_DEM2, 9, 6, A_Scream, S_DEMN2_XDEATH4, 0, 0}, // S_DEMN2_XDEATH3 + {SPR_DEM2, 10, 6, A_NoBlocking, S_DEMN2_XDEATH5, 0, 0}, // S_DEMN2_XDEATH4 + {SPR_DEM2, 11, 6, A_QueueCorpse, S_DEMN2_XDEATH6, 0, 0}, // S_DEMN2_XDEATH5 + {SPR_DEM2, 12, 6, NULL, S_DEMN2_XDEATH7, 0, 0}, // S_DEMN2_XDEATH6 + {SPR_DEM2, 13, 6, NULL, S_DEMN2_XDEATH8, 0, 0}, // S_DEMN2_XDEATH7 + {SPR_DEM2, 14, 6, NULL, S_DEMN2_XDEATH9, 0, 0}, // S_DEMN2_XDEATH8 + {SPR_DEM2, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN2_XDEATH9 + {SPR_DMBA, 0, 4, NULL, S_DEMON2CHUNK1_2, 0, 0}, // S_DEMON2CHUNK1_1 + {SPR_DMBA, 0, 10, A_QueueCorpse, S_DEMON2CHUNK1_3, 0, 0}, // S_DEMON2CHUNK1_2 + {SPR_DMBA, 0, 20, NULL, S_DEMON2CHUNK1_3, 0, 0}, // S_DEMON2CHUNK1_3 + {SPR_DMBA, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK1_4 + {SPR_DMBB, 0, 4, NULL, S_DEMON2CHUNK2_2, 0, 0}, // S_DEMON2CHUNK2_1 + {SPR_DMBB, 0, 10, A_QueueCorpse, S_DEMON2CHUNK2_3, 0, 0}, // S_DEMON2CHUNK2_2 + {SPR_DMBB, 0, 20, NULL, S_DEMON2CHUNK2_3, 0, 0}, // S_DEMON2CHUNK2_3 + {SPR_DMBB, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK2_4 + {SPR_DMBC, 0, 4, NULL, S_DEMON2CHUNK3_2, 0, 0}, // S_DEMON2CHUNK3_1 + {SPR_DMBC, 0, 10, A_QueueCorpse, S_DEMON2CHUNK3_3, 0, 0}, // S_DEMON2CHUNK3_2 + {SPR_DMBC, 0, 20, NULL, S_DEMON2CHUNK3_3, 0, 0}, // S_DEMON2CHUNK3_3 + {SPR_DMBC, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK3_4 + {SPR_DMBD, 0, 4, NULL, S_DEMON2CHUNK4_2, 0, 0}, // S_DEMON2CHUNK4_1 + {SPR_DMBD, 0, 10, A_QueueCorpse, S_DEMON2CHUNK4_3, 0, 0}, // S_DEMON2CHUNK4_2 + {SPR_DMBD, 0, 20, NULL, S_DEMON2CHUNK4_3, 0, 0}, // S_DEMON2CHUNK4_3 + {SPR_DMBD, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK4_4 + {SPR_DMBE, 0, 4, NULL, S_DEMON2CHUNK5_2, 0, 0}, // S_DEMON2CHUNK5_1 + {SPR_DMBE, 0, 10, NULL, S_DEMON2CHUNK5_3, 0, 0}, // S_DEMON2CHUNK5_2 + {SPR_DMBE, 0, 20, NULL, S_DEMON2CHUNK5_3, 0, 0}, // S_DEMON2CHUNK5_3 + {SPR_DMBE, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK5_4 + {SPR_D2FX, 32768, 4, NULL, S_DEMON2FX_MOVE2, 0, 0}, // S_DEMON2FX_MOVE1 + {SPR_D2FX, 32769, 4, NULL, S_DEMON2FX_MOVE3, 0, 0}, // S_DEMON2FX_MOVE2 + {SPR_D2FX, 32770, 4, NULL, S_DEMON2FX_MOVE4, 0, 0}, // S_DEMON2FX_MOVE3 + {SPR_D2FX, 32771, 4, NULL, S_DEMON2FX_MOVE5, 0, 0}, // S_DEMON2FX_MOVE4 + {SPR_D2FX, 32772, 4, NULL, S_DEMON2FX_MOVE6, 0, 0}, // S_DEMON2FX_MOVE5 + {SPR_D2FX, 32773, 4, NULL, S_DEMON2FX_MOVE1, 0, 0}, // S_DEMON2FX_MOVE6 + {SPR_D2FX, 32774, 4, NULL, S_DEMON2FX_BOOM2, 0, 0}, // S_DEMON2FX_BOOM1 + {SPR_D2FX, 32775, 4, NULL, S_DEMON2FX_BOOM3, 0, 0}, // S_DEMON2FX_BOOM2 + {SPR_D2FX, 32776, 4, NULL, S_DEMON2FX_BOOM4, 0, 0}, // S_DEMON2FX_BOOM3 + {SPR_D2FX, 32777, 4, NULL, S_DEMON2FX_BOOM5, 0, 0}, // S_DEMON2FX_BOOM4 + {SPR_D2FX, 32778, 3, NULL, S_DEMON2FX_BOOM6, 0, 0}, // S_DEMON2FX_BOOM5 + {SPR_D2FX, 32779, 3, NULL, S_NULL, 0, 0}, // S_DEMON2FX_BOOM6 + {SPR_WRTH, 0, 2, A_WraithRaiseInit, S_WRAITH_RAISE2, 0, 0}, // S_WRAITH_RAISE1 + {SPR_WRTH, 0, 2, A_WraithRaise, S_WRAITH_RAISE3, 0, 0}, // S_WRAITH_RAISE2 + {SPR_WRTH, 0, 2, A_FaceTarget, S_WRAITH_RAISE4, 0, 0}, // S_WRAITH_RAISE3 + {SPR_WRTH, 1, 2, A_WraithRaise, S_WRAITH_RAISE5, 0, 0}, // S_WRAITH_RAISE4 + {SPR_WRTH, 1, 2, A_WraithRaise, S_WRAITH_RAISE2, 0, 0}, // S_WRAITH_RAISE5 + {SPR_WRTH, 0, 10, NULL, S_WRAITH_INIT2, 0, 0}, // S_WRAITH_INIT1 + {SPR_WRTH, 1, 5, A_WraithInit, S_WRAITH_LOOK1, 0, 0}, // S_WRAITH_INIT2 + {SPR_WRTH, 0, 15, A_WraithLook, S_WRAITH_LOOK2, 0, 0}, // S_WRAITH_LOOK1 + {SPR_WRTH, 1, 15, A_WraithLook, S_WRAITH_LOOK1, 0, 0}, // S_WRAITH_LOOK2 + {SPR_WRTH, 0, 4, A_WraithChase, S_WRAITH_CHASE2, 0, 0}, // S_WRAITH_CHASE1 + {SPR_WRTH, 1, 4, A_WraithChase, S_WRAITH_CHASE3, 0, 0}, // S_WRAITH_CHASE2 + {SPR_WRTH, 2, 4, A_WraithChase, S_WRAITH_CHASE4, 0, 0}, // S_WRAITH_CHASE3 + {SPR_WRTH, 3, 4, A_WraithChase, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_CHASE4 + {SPR_WRTH, 4, 6, A_FaceTarget, S_WRAITH_ATK1_2, 0, 0}, // S_WRAITH_ATK1_1 + {SPR_WRTH, 5, 6, A_WraithFX3, S_WRAITH_ATK1_3, 0, 0}, // S_WRAITH_ATK1_2 + {SPR_WRTH, 6, 6, A_WraithMelee, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_ATK1_3 + {SPR_WRTH, 4, 6, A_FaceTarget, S_WRAITH_ATK2_2, 0, 0}, // S_WRAITH_ATK2_1 + {SPR_WRTH, 5, 6, NULL, S_WRAITH_ATK2_3, 0, 0}, // S_WRAITH_ATK2_2 + {SPR_WRTH, 6, 6, A_WraithMissile, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_ATK2_3 + {SPR_WRTH, 0, 2, NULL, S_WRAITH_PAIN2, 0, 0}, // S_WRAITH_PAIN1 + {SPR_WRTH, 7, 6, A_Pain, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_PAIN2 + {SPR_WRTH, 8, 4, NULL, S_WRAITH_DEATH1_2, 0, 0}, // S_WRAITH_DEATH1_1 + {SPR_WRTH, 9, 4, A_Scream, S_WRAITH_DEATH1_3, 0, 0}, // S_WRAITH_DEATH1_2 + {SPR_WRTH, 10, 4, NULL, S_WRAITH_DEATH1_4, 0, 0}, // S_WRAITH_DEATH1_3 + {SPR_WRTH, 11, 4, NULL, S_WRAITH_DEATH1_5, 0, 0}, // S_WRAITH_DEATH1_4 + {SPR_WRTH, 12, 4, A_NoBlocking, S_WRAITH_DEATH1_6, 0, 0}, // S_WRAITH_DEATH1_5 + {SPR_WRTH, 13, 4, A_QueueCorpse, S_WRAITH_DEATH1_7, 0, 0}, // S_WRAITH_DEATH1_6 + {SPR_WRTH, 14, 4, NULL, S_WRAITH_DEATH1_8, 0, 0}, // S_WRAITH_DEATH1_7 + {SPR_WRTH, 15, 5, NULL, S_WRAITH_DEATH1_9, 0, 0}, // S_WRAITH_DEATH1_8 + {SPR_WRTH, 16, 5, NULL, S_WRAITH_DEATH1_0, 0, 0}, // S_WRAITH_DEATH1_9 + {SPR_WRTH, 17, -1, NULL, S_NULL, 0, 0}, // S_WRAITH_DEATH1_0 + {SPR_WRT2, 0, 5, NULL, S_WRAITH_DEATH2_2, 0, 0}, // S_WRAITH_DEATH2_1 + {SPR_WRT2, 1, 5, A_Scream, S_WRAITH_DEATH2_3, 0, 0}, // S_WRAITH_DEATH2_2 + {SPR_WRT2, 2, 5, NULL, S_WRAITH_DEATH2_4, 0, 0}, // S_WRAITH_DEATH2_3 + {SPR_WRT2, 3, 5, NULL, S_WRAITH_DEATH2_5, 0, 0}, // S_WRAITH_DEATH2_4 + {SPR_WRT2, 4, 5, A_NoBlocking, S_WRAITH_DEATH2_6, 0, 0}, // S_WRAITH_DEATH2_5 + {SPR_WRT2, 5, 5, A_QueueCorpse, S_WRAITH_DEATH2_7, 0, 0}, // S_WRAITH_DEATH2_6 + {SPR_WRT2, 6, 5, NULL, S_WRAITH_DEATH2_8, 0, 0}, // S_WRAITH_DEATH2_7 + {SPR_WRT2, 7, -1, NULL, S_NULL, 0, 0}, // S_WRAITH_DEATH2_8 + {SPR_WRT2, 8, 5, A_FreezeDeath, S_WRAITH_ICE2, 0, 0}, // S_WRAITH_ICE + {SPR_WRT2, 8, 1, A_FreezeDeathChunks, S_WRAITH_ICE2, 0, 0}, // S_WRAITH_ICE2 + {SPR_WRBL, 32768, 3, NULL, S_WRTHFX_MOVE2, 0, 0}, // S_WRTHFX_MOVE1 + {SPR_WRBL, 32769, 3, A_WraithFX2, S_WRTHFX_MOVE3, 0, 0}, // S_WRTHFX_MOVE2 + {SPR_WRBL, 32770, 3, NULL, S_WRTHFX_MOVE1, 0, 0}, // S_WRTHFX_MOVE3 + {SPR_WRBL, 32771, 4, NULL, S_WRTHFX_BOOM2, 0, 0}, // S_WRTHFX_BOOM1 + {SPR_WRBL, 32772, 4, A_WraithFX2, S_WRTHFX_BOOM3, 0, 0}, // S_WRTHFX_BOOM2 + {SPR_WRBL, 32773, 4, NULL, S_WRTHFX_BOOM4, 0, 0}, // S_WRTHFX_BOOM3 + {SPR_WRBL, 32774, 3, A_WraithFX2, S_WRTHFX_BOOM5, 0, 0}, // S_WRTHFX_BOOM4 + {SPR_WRBL, 32775, 3, A_WraithFX2, S_WRTHFX_BOOM6, 0, 0}, // S_WRTHFX_BOOM5 + {SPR_WRBL, 32776, 3, NULL, S_NULL, 0, 0}, // S_WRTHFX_BOOM6 + {SPR_WRBL, 32777, 4, NULL, S_WRTHFX_SIZZLE2, 0, 0}, // S_WRTHFX_SIZZLE1 + {SPR_WRBL, 32778, 4, NULL, S_WRTHFX_SIZZLE3, 0, 0}, // S_WRTHFX_SIZZLE2 + {SPR_WRBL, 32779, 4, NULL, S_WRTHFX_SIZZLE4, 0, 0}, // S_WRTHFX_SIZZLE3 + {SPR_WRBL, 32780, 4, NULL, S_WRTHFX_SIZZLE5, 0, 0}, // S_WRTHFX_SIZZLE4 + {SPR_WRBL, 32781, 4, NULL, S_WRTHFX_SIZZLE6, 0, 0}, // S_WRTHFX_SIZZLE5 + {SPR_WRBL, 32782, 4, NULL, S_WRTHFX_SIZZLE7, 0, 0}, // S_WRTHFX_SIZZLE6 + {SPR_WRBL, 32783, 4, NULL, S_NULL, 0, 0}, // S_WRTHFX_SIZZLE7 + {SPR_WRBL, 32784, 4, NULL, S_WRTHFX_DROP2, 0, 0}, // S_WRTHFX_DROP1 + {SPR_WRBL, 32785, 4, NULL, S_WRTHFX_DROP3, 0, 0}, // S_WRTHFX_DROP2 + {SPR_WRBL, 32786, 4, NULL, S_WRTHFX_DROP1, 0, 0}, // S_WRTHFX_DROP3 + {SPR_WRBL, 32786, 4, NULL, S_NULL, 0, 0}, // S_WRTHFX_DEAD1 + {SPR_WRBL, 19, 4, NULL, S_WRTHFX_ADROP2, 0, 0}, // S_WRTHFX_ADROP1 + {SPR_WRBL, 20, 4, NULL, S_WRTHFX_ADROP3, 0, 0}, // S_WRTHFX_ADROP2 + {SPR_WRBL, 21, 4, NULL, S_WRTHFX_ADROP4, 0, 0}, // S_WRTHFX_ADROP3 + {SPR_WRBL, 22, 4, NULL, S_WRTHFX_ADROP1, 0, 0}, // S_WRTHFX_ADROP4 + {SPR_WRBL, 22, 10, NULL, S_NULL, 0, 0}, // S_WRTHFX_ADEAD1 + {SPR_WRBL, 23, 7, NULL, S_WRTHFX_BDROP2, 0, 0}, // S_WRTHFX_BDROP1 + {SPR_WRBL, 24, 7, NULL, S_WRTHFX_BDROP3, 0, 0}, // S_WRTHFX_BDROP2 + {SPR_WRBL, 25, 7, NULL, S_WRTHFX_BDROP1, 0, 0}, // S_WRTHFX_BDROP3 + {SPR_WRBL, 25, 35, NULL, S_NULL, 0, 0}, // S_WRTHFX_BDEAD1 + {SPR_MNTR, 0, 15, NULL, S_MNTR_SPAWN2, 0, 0}, // S_MNTR_SPAWN1 + {SPR_MNTR, 0, 15, A_MinotaurFade1, S_MNTR_SPAWN3, 0, 0}, // S_MNTR_SPAWN2 + {SPR_MNTR, 0, 3, A_MinotaurFade2, S_MNTR_LOOK1, 0, 0}, // S_MNTR_SPAWN3 + {SPR_MNTR, 0, 10, A_MinotaurLook, S_MNTR_LOOK2, 0, 0}, // S_MNTR_LOOK1 + {SPR_MNTR, 1, 10, A_MinotaurLook, S_MNTR_LOOK1, 0, 0}, // S_MNTR_LOOK2 + {SPR_MNTR, 0, 5, A_MinotaurChase, S_MNTR_WALK2, 0, 0}, // S_MNTR_WALK1 + {SPR_MNTR, 1, 5, A_MinotaurChase, S_MNTR_WALK3, 0, 0}, // S_MNTR_WALK2 + {SPR_MNTR, 2, 5, A_MinotaurChase, S_MNTR_WALK4, 0, 0}, // S_MNTR_WALK3 + {SPR_MNTR, 3, 5, A_MinotaurChase, S_MNTR_WALK1, 0, 0}, // S_MNTR_WALK4 + {SPR_MNTR, 0, 5, A_MinotaurRoam, S_MNTR_ROAM2, 0, 0}, // S_MNTR_ROAM1 + {SPR_MNTR, 1, 5, A_MinotaurRoam, S_MNTR_ROAM3, 0, 0}, // S_MNTR_ROAM2 + {SPR_MNTR, 2, 5, A_MinotaurRoam, S_MNTR_ROAM4, 0, 0}, // S_MNTR_ROAM3 + {SPR_MNTR, 3, 5, A_MinotaurRoam, S_MNTR_ROAM1, 0, 0}, // S_MNTR_ROAM4 + {SPR_MNTR, 6, 10, A_FaceTarget, S_MNTR_ATK1_2, 0, 0}, // S_MNTR_ATK1_1 + {SPR_MNTR, 7, 7, A_FaceTarget, S_MNTR_ATK1_3, 0, 0}, // S_MNTR_ATK1_2 + {SPR_MNTR, 8, 12, A_MinotaurAtk1, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK1_3 + {SPR_MNTR, 6, 10, A_MinotaurDecide, S_MNTR_ATK2_2, 0, 0}, // S_MNTR_ATK2_1 + {SPR_MNTR, 9, 4, A_FaceTarget, S_MNTR_ATK2_3, 0, 0}, // S_MNTR_ATK2_2 + {SPR_MNTR, 10, 9, A_MinotaurAtk2, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK2_3 + {SPR_MNTR, 6, 10, A_FaceTarget, S_MNTR_ATK3_2, 0, 0}, // S_MNTR_ATK3_1 + {SPR_MNTR, 7, 7, A_FaceTarget, S_MNTR_ATK3_3, 0, 0}, // S_MNTR_ATK3_2 + {SPR_MNTR, 8, 12, A_MinotaurAtk3, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK3_3 + {SPR_MNTR, 8, 12, NULL, S_MNTR_ATK3_1, 0, 0}, // S_MNTR_ATK3_4 + {SPR_MNTR, 5, 2, A_MinotaurCharge, S_MNTR_ATK4_1, 0, 0}, // S_MNTR_ATK4_1 + {SPR_MNTR, 4, 3, NULL, S_MNTR_PAIN2, 0, 0}, // S_MNTR_PAIN1 + {SPR_MNTR, 4, 6, A_Pain, S_MNTR_WALK1, 0, 0}, // S_MNTR_PAIN2 + {SPR_MNTR, 4, 6, NULL, S_MNTR_DIE2, 0, 0}, // S_MNTR_DIE1 + {SPR_MNTR, 4, 2, A_Scream, S_MNTR_DIE3, 0, 0}, // S_MNTR_DIE2 + {SPR_MNTR, 4, 5, A_SmokePuffExit, S_MNTR_DIE4, 0, 0}, // S_MNTR_DIE3 + {SPR_MNTR, 4, 5, NULL, S_MNTR_DIE5, 0, 0}, // S_MNTR_DIE4 + {SPR_MNTR, 4, 5, A_NoBlocking, S_MNTR_DIE6, 0, 0}, // S_MNTR_DIE5 + {SPR_MNTR, 4, 5, NULL, S_MNTR_DIE7, 0, 0}, // S_MNTR_DIE6 + {SPR_MNTR, 4, 5, A_MinotaurFade1, S_MNTR_DIE8, 0, 0}, // S_MNTR_DIE7 + {SPR_MNTR, 4, 5, A_MinotaurFade0, S_MNTR_DIE9, 0, 0}, // S_MNTR_DIE8 + {SPR_MNTR, 4, 10, NULL, S_NULL, 0, 0}, // S_MNTR_DIE9 + {SPR_FX12, 32768, 6, NULL, S_MNTRFX1_2, 0, 0}, // S_MNTRFX1_1 + {SPR_FX12, 32769, 6, NULL, S_MNTRFX1_1, 0, 0}, // S_MNTRFX1_2 + {SPR_FX12, 32770, 5, NULL, S_MNTRFXI1_2, 0, 0}, // S_MNTRFXI1_1 + {SPR_FX12, 32771, 5, NULL, S_MNTRFXI1_3, 0, 0}, // S_MNTRFXI1_2 + {SPR_FX12, 32772, 5, NULL, S_MNTRFXI1_4, 0, 0}, // S_MNTRFXI1_3 + {SPR_FX12, 32773, 5, NULL, S_MNTRFXI1_5, 0, 0}, // S_MNTRFXI1_4 + {SPR_FX12, 32774, 5, NULL, S_MNTRFXI1_6, 0, 0}, // S_MNTRFXI1_5 + {SPR_FX12, 32775, 5, NULL, S_NULL, 0, 0}, // S_MNTRFXI1_6 + {SPR_FX13, 0, 2, A_MntrFloorFire, S_MNTRFX2_1, 0, 0}, // S_MNTRFX2_1 + {SPR_FX13, 32776, 4, A_Explode, S_MNTRFXI2_2, 0, 0}, // S_MNTRFXI2_1 + {SPR_FX13, 32777, 4, NULL, S_MNTRFXI2_3, 0, 0}, // S_MNTRFXI2_2 + {SPR_FX13, 32778, 4, NULL, S_MNTRFXI2_4, 0, 0}, // S_MNTRFXI2_3 + {SPR_FX13, 32779, 4, NULL, S_MNTRFXI2_5, 0, 0}, // S_MNTRFXI2_4 + {SPR_FX13, 32780, 4, NULL, S_NULL, 0, 0}, // S_MNTRFXI2_5 + {SPR_FX13, 32771, 4, NULL, S_MNTRFX3_2, 0, 0}, // S_MNTRFX3_1 + {SPR_FX13, 32770, 4, NULL, S_MNTRFX3_3, 0, 0}, // S_MNTRFX3_2 + {SPR_FX13, 32769, 5, NULL, S_MNTRFX3_4, 0, 0}, // S_MNTRFX3_3 + {SPR_FX13, 32770, 5, NULL, S_MNTRFX3_5, 0, 0}, // S_MNTRFX3_4 + {SPR_FX13, 32771, 5, NULL, S_MNTRFX3_6, 0, 0}, // S_MNTRFX3_5 + {SPR_FX13, 32772, 5, NULL, S_MNTRFX3_7, 0, 0}, // S_MNTRFX3_6 + {SPR_FX13, 32773, 4, NULL, S_MNTRFX3_8, 0, 0}, // S_MNTRFX3_7 + {SPR_FX13, 32774, 4, NULL, S_MNTRFX3_9, 0, 0}, // S_MNTRFX3_8 + {SPR_FX13, 32775, 4, NULL, S_NULL, 0, 0}, // S_MNTRFX3_9 + {SPR_MNSM, 0, 3, NULL, S_MINOSMOKE2, 0, 0}, // S_MINOSMOKE1 + {SPR_MNSM, 1, 3, NULL, S_MINOSMOKE3, 0, 0}, // S_MINOSMOKE2 + {SPR_MNSM, 2, 3, NULL, S_MINOSMOKE4, 0, 0}, // S_MINOSMOKE3 + {SPR_MNSM, 3, 3, NULL, S_MINOSMOKE5, 0, 0}, // S_MINOSMOKE4 + {SPR_MNSM, 4, 3, NULL, S_MINOSMOKE6, 0, 0}, // S_MINOSMOKE5 + {SPR_MNSM, 5, 3, NULL, S_MINOSMOKE7, 0, 0}, // S_MINOSMOKE6 + {SPR_MNSM, 6, 3, NULL, S_MINOSMOKE8, 0, 0}, // S_MINOSMOKE7 + {SPR_MNSM, 7, 3, NULL, S_MINOSMOKE9, 0, 0}, // S_MINOSMOKE8 + {SPR_MNSM, 8, 3, NULL, S_MINOSMOKE0, 0, 0}, // S_MINOSMOKE9 + {SPR_MNSM, 9, 3, NULL, S_MINOSMOKEA, 0, 0}, // S_MINOSMOKE0 + {SPR_MNSM, 10, 3, NULL, S_MINOSMOKEB, 0, 0}, // S_MINOSMOKEA + {SPR_MNSM, 11, 3, NULL, S_MINOSMOKEC, 0, 0}, // S_MINOSMOKEB + {SPR_MNSM, 12, 3, NULL, S_MINOSMOKED, 0, 0}, // S_MINOSMOKEC + {SPR_MNSM, 13, 3, NULL, S_MINOSMOKEE, 0, 0}, // S_MINOSMOKED + {SPR_MNSM, 14, 3, NULL, S_MINOSMOKEF, 0, 0}, // S_MINOSMOKEE + {SPR_MNSM, 15, 3, NULL, S_MINOSMOKEG, 0, 0}, // S_MINOSMOKEF + {SPR_MNSM, 16, 3, NULL, S_NULL, 0, 0}, // S_MINOSMOKEG + {SPR_MNSM, 0, 3, NULL, S_MINOSMOKEX2, 0, 0}, // S_MINOSMOKEX1 + {SPR_MNSM, 1, 3, NULL, S_MINOSMOKEX3, 0, 0}, // S_MINOSMOKEX2 + {SPR_MNSM, 2, 3, NULL, S_MINOSMOKEX4, 0, 0}, // S_MINOSMOKEX3 + {SPR_MNSM, 3, 3, NULL, S_MINOSMOKEX5, 0, 0}, // S_MINOSMOKEX4 + {SPR_MNSM, 4, 3, NULL, S_MINOSMOKEX6, 0, 0}, // S_MINOSMOKEX5 + {SPR_MNSM, 5, 3, NULL, S_MINOSMOKEX7, 0, 0}, // S_MINOSMOKEX6 + {SPR_MNSM, 6, 3, NULL, S_MINOSMOKEX8, 0, 0}, // S_MINOSMOKEX7 + {SPR_MNSM, 7, 3, NULL, S_MINOSMOKEX9, 0, 0}, // S_MINOSMOKEX8 + {SPR_MNSM, 8, 3, NULL, S_MINOSMOKEX0, 0, 0}, // S_MINOSMOKEX9 + {SPR_MNSM, 9, 3, NULL, S_MINOSMOKEXA, 0, 0}, // S_MINOSMOKEX0 + {SPR_MNSM, 8, 3, NULL, S_MINOSMOKEXB, 0, 0}, // S_MINOSMOKEXA + {SPR_MNSM, 7, 3, NULL, S_MINOSMOKEXC, 0, 0}, // S_MINOSMOKEXB + {SPR_MNSM, 6, 3, NULL, S_MINOSMOKEXD, 0, 0}, // S_MINOSMOKEXC + {SPR_MNSM, 5, 3, NULL, S_MINOSMOKEXE, 0, 0}, // S_MINOSMOKEXD + {SPR_MNSM, 4, 3, NULL, S_MINOSMOKEXF, 0, 0}, // S_MINOSMOKEXE + {SPR_MNSM, 3, 3, NULL, S_MINOSMOKEXG, 0, 0}, // S_MINOSMOKEXF + {SPR_MNSM, 2, 3, NULL, S_MINOSMOKEXH, 0, 0}, // S_MINOSMOKEXG + {SPR_MNSM, 1, 3, NULL, S_MINOSMOKEXI, 0, 0}, // S_MINOSMOKEXH + {SPR_MNSM, 0, 3, NULL, S_NULL, 0, 0}, // S_MINOSMOKEXI + {SPR_SSPT, 7, 10, A_Look, S_SERPENT_LOOK1, 0, 0}, // S_SERPENT_LOOK1 + {SPR_SSPT, 7, 1, A_SerpentChase, S_SERPENT_SWIM2, 0, 0}, // S_SERPENT_SWIM1 + {SPR_SSPT, 7, 1, A_SerpentChase, S_SERPENT_SWIM3, 0, 0}, // S_SERPENT_SWIM2 + {SPR_SSPT, 7, 2, A_SerpentHumpDecide, S_SERPENT_SWIM1, 0, 0}, // S_SERPENT_SWIM3 + {SPR_SSPT, 7, 3, A_SerpentUnHide, S_SERPENT_HUMP2, 0, 0}, // S_SERPENT_HUMP1 + {SPR_SSPT, 4, 3, A_SerpentRaiseHump, S_SERPENT_HUMP3, 0, 0}, // S_SERPENT_HUMP2 + {SPR_SSPT, 5, 3, A_SerpentRaiseHump, S_SERPENT_HUMP4, 0, 0}, // S_SERPENT_HUMP3 + {SPR_SSPT, 6, 3, A_SerpentRaiseHump, S_SERPENT_HUMP5, 0, 0}, // S_SERPENT_HUMP4 + {SPR_SSPT, 4, 3, A_SerpentRaiseHump, S_SERPENT_HUMP6, 0, 0}, // S_SERPENT_HUMP5 + {SPR_SSPT, 5, 3, A_SerpentRaiseHump, S_SERPENT_HUMP7, 0, 0}, // S_SERPENT_HUMP6 + {SPR_SSPT, 6, 3, NULL, S_SERPENT_HUMP8, 0, 0}, // S_SERPENT_HUMP7 + {SPR_SSPT, 4, 3, NULL, S_SERPENT_HUMP9, 0, 0}, // S_SERPENT_HUMP8 + {SPR_SSPT, 5, 3, NULL, S_SERPENT_HUMP10, 0, 0}, // S_SERPENT_HUMP9 + {SPR_SSPT, 6, 3, A_SerpentLowerHump, S_SERPENT_HUMP11, 0, 0}, // S_SERPENT_HUMP10 + {SPR_SSPT, 4, 3, A_SerpentLowerHump, S_SERPENT_HUMP12, 0, 0}, // S_SERPENT_HUMP11 + {SPR_SSPT, 5, 3, A_SerpentLowerHump, S_SERPENT_HUMP13, 0, 0}, // S_SERPENT_HUMP12 + {SPR_SSPT, 6, 3, A_SerpentLowerHump, S_SERPENT_HUMP14, 0, 0}, // S_SERPENT_HUMP13 + {SPR_SSPT, 4, 3, A_SerpentLowerHump, S_SERPENT_HUMP15, 0, 0}, // S_SERPENT_HUMP14 + {SPR_SSPT, 5, 3, A_SerpentHide, S_SERPENT_SWIM1, 0, 0}, // S_SERPENT_HUMP15 + {SPR_SSPT, 0, 1, A_UnHideThing, S_SERPENT_SURFACE2, 0, 0}, // S_SERPENT_SURFACE1 + {SPR_SSPT, 0, 1, A_SerpentBirthScream, S_SERPENT_SURFACE3, 0, 0}, // S_SERPENT_SURFACE2 + {SPR_SSPT, 1, 3, A_SetShootable, S_SERPENT_SURFACE4, 0, 0}, // S_SERPENT_SURFACE3 + {SPR_SSPT, 2, 3, NULL, S_SERPENT_SURFACE5, 0, 0}, // S_SERPENT_SURFACE4 + {SPR_SSPT, 3, 4, A_SerpentCheckForAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_SURFACE5 + {SPR_SSDV, 0, 4, NULL, S_SERPENT_DIVE2, 0, 0}, // S_SERPENT_DIVE1 + {SPR_SSDV, 1, 4, NULL, S_SERPENT_DIVE3, 0, 0}, // S_SERPENT_DIVE2 + {SPR_SSDV, 2, 4, NULL, S_SERPENT_DIVE4, 0, 0}, // S_SERPENT_DIVE3 + {SPR_SSDV, 3, 4, A_UnSetShootable, S_SERPENT_DIVE5, 0, 0}, // S_SERPENT_DIVE4 + {SPR_SSDV, 4, 3, A_SerpentDiveSound, S_SERPENT_DIVE6, 0, 0}, // S_SERPENT_DIVE5 + {SPR_SSDV, 5, 3, NULL, S_SERPENT_DIVE7, 0, 0}, // S_SERPENT_DIVE6 + {SPR_SSDV, 6, 4, NULL, S_SERPENT_DIVE8, 0, 0}, // S_SERPENT_DIVE7 + {SPR_SSDV, 7, 4, NULL, S_SERPENT_DIVE9, 0, 0}, // S_SERPENT_DIVE8 + {SPR_SSDV, 8, 3, NULL, S_SERPENT_DIVE10, 0, 0}, // S_SERPENT_DIVE9 + {SPR_SSDV, 9, 3, A_SerpentHide, S_SERPENT_SWIM1, 0, 0}, // S_SERPENT_DIVE10 + {SPR_SSPT, 8, 5, A_SerpentWalk, S_SERPENT_WALK2, 0, 0}, // S_SERPENT_WALK1 + {SPR_SSPT, 9, 5, A_SerpentWalk, S_SERPENT_WALK3, 0, 0}, // S_SERPENT_WALK2 + {SPR_SSPT, 8, 5, A_SerpentWalk, S_SERPENT_WALK4, 0, 0}, // S_SERPENT_WALK3 + {SPR_SSPT, 9, 5, A_SerpentCheckForAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_WALK4 + {SPR_SSPT, 11, 5, NULL, S_SERPENT_PAIN2, 0, 0}, // S_SERPENT_PAIN1 + {SPR_SSPT, 11, 5, A_Pain, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_PAIN2 + {SPR_SSPT, 10, 6, A_FaceTarget, S_SERPENT_ATK2, 0, 0}, // S_SERPENT_ATK1 + {SPR_SSPT, 11, 5, A_SerpentChooseAttack, S_SERPENT_MELEE1, 0, 0}, // S_SERPENT_ATK2 + {SPR_SSPT, 13, 5, A_SerpentMeleeAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_MELEE1 + {SPR_SSPT, 13, 5, A_SerpentMissileAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_MISSILE1 + {SPR_SSPT, 14, 4, NULL, S_SERPENT_DIE2, 0, 0}, // S_SERPENT_DIE1 + {SPR_SSPT, 15, 4, A_Scream, S_SERPENT_DIE3, 0, 0}, // S_SERPENT_DIE2 + {SPR_SSPT, 16, 4, A_NoBlocking, S_SERPENT_DIE4, 0, 0}, // S_SERPENT_DIE3 + {SPR_SSPT, 17, 4, NULL, S_SERPENT_DIE5, 0, 0}, // S_SERPENT_DIE4 + {SPR_SSPT, 18, 4, NULL, S_SERPENT_DIE6, 0, 0}, // S_SERPENT_DIE5 + {SPR_SSPT, 19, 4, NULL, S_SERPENT_DIE7, 0, 0}, // S_SERPENT_DIE6 + {SPR_SSPT, 20, 4, NULL, S_SERPENT_DIE8, 0, 0}, // S_SERPENT_DIE7 + {SPR_SSPT, 21, 4, NULL, S_SERPENT_DIE9, 0, 0}, // S_SERPENT_DIE8 + {SPR_SSPT, 22, 4, NULL, S_SERPENT_DIE10, 0, 0}, // S_SERPENT_DIE9 + {SPR_SSPT, 23, 4, NULL, S_SERPENT_DIE11, 0, 0}, // S_SERPENT_DIE10 + {SPR_SSPT, 24, 4, NULL, S_SERPENT_DIE12, 0, 0}, // S_SERPENT_DIE11 + {SPR_SSPT, 25, 4, NULL, S_NULL, 0, 0}, // S_SERPENT_DIE12 + {SPR_SSXD, 0, 4, NULL, S_SERPENT_XDIE2, 0, 0}, // S_SERPENT_XDIE1 + {SPR_SSXD, 1, 4, A_SerpentHeadPop, S_SERPENT_XDIE3, 0, 0}, // S_SERPENT_XDIE2 + {SPR_SSXD, 2, 4, A_NoBlocking, S_SERPENT_XDIE4, 0, 0}, // S_SERPENT_XDIE3 + {SPR_SSXD, 3, 4, NULL, S_SERPENT_XDIE5, 0, 0}, // S_SERPENT_XDIE4 + {SPR_SSXD, 4, 4, NULL, S_SERPENT_XDIE6, 0, 0}, // S_SERPENT_XDIE5 + {SPR_SSXD, 5, 3, NULL, S_SERPENT_XDIE7, 0, 0}, // S_SERPENT_XDIE6 + {SPR_SSXD, 6, 3, NULL, S_SERPENT_XDIE8, 0, 0}, // S_SERPENT_XDIE7 + {SPR_SSXD, 7, 3, A_SerpentSpawnGibs, S_NULL, 0, 0}, // S_SERPENT_XDIE8 + {SPR_SSPT, 26, 5, A_FreezeDeath, S_SERPENT_ICE2, 0, 0}, // S_SERPENT_ICE + {SPR_SSPT, 26, 1, A_FreezeDeathChunks, S_SERPENT_ICE2, 0, 0}, // S_SERPENT_ICE2 + {SPR_SSFX, 32768, 3, A_ContMobjSound, S_SERPENT_FX2, 0, 0}, // S_SERPENT_FX1 + {SPR_SSFX, 32769, 3, NULL, S_SERPENT_FX3, 0, 0}, // S_SERPENT_FX2 + {SPR_SSFX, 32768, 3, NULL, S_SERPENT_FX4, 0, 0}, // S_SERPENT_FX3 + {SPR_SSFX, 32769, 3, NULL, S_SERPENT_FX1, 0, 0}, // S_SERPENT_FX4 + {SPR_SSFX, 32770, 4, NULL, S_SERPENT_FX_X2, 0, 0}, // S_SERPENT_FX_X1 + {SPR_SSFX, 32771, 4, NULL, S_SERPENT_FX_X3, 0, 0}, // S_SERPENT_FX_X2 + {SPR_SSFX, 32772, 4, NULL, S_SERPENT_FX_X4, 0, 0}, // S_SERPENT_FX_X3 + {SPR_SSFX, 32773, 4, NULL, S_SERPENT_FX_X5, 0, 0}, // S_SERPENT_FX_X4 + {SPR_SSFX, 32774, 4, NULL, S_SERPENT_FX_X6, 0, 0}, // S_SERPENT_FX_X5 + {SPR_SSFX, 32775, 4, NULL, S_NULL, 0, 0}, // S_SERPENT_FX_X6 + {SPR_SSXD, 8, 4, A_SerpentHeadCheck, S_SERPENT_HEAD2, 0, 0}, // S_SERPENT_HEAD1 + {SPR_SSXD, 9, 4, A_SerpentHeadCheck, S_SERPENT_HEAD3, 0, 0}, // S_SERPENT_HEAD2 + {SPR_SSXD, 10, 4, A_SerpentHeadCheck, S_SERPENT_HEAD4, 0, 0}, // S_SERPENT_HEAD3 + {SPR_SSXD, 11, 4, A_SerpentHeadCheck, S_SERPENT_HEAD5, 0, 0}, // S_SERPENT_HEAD4 + {SPR_SSXD, 12, 4, A_SerpentHeadCheck, S_SERPENT_HEAD6, 0, 0}, // S_SERPENT_HEAD5 + {SPR_SSXD, 13, 4, A_SerpentHeadCheck, S_SERPENT_HEAD7, 0, 0}, // S_SERPENT_HEAD6 + {SPR_SSXD, 14, 4, A_SerpentHeadCheck, S_SERPENT_HEAD8, 0, 0}, // S_SERPENT_HEAD7 + {SPR_SSXD, 15, 4, A_SerpentHeadCheck, S_SERPENT_HEAD1, 0, 0}, // S_SERPENT_HEAD8 + {SPR_SSXD, 18, -1, NULL, S_SERPENT_HEAD_X1, 0, 0}, // S_SERPENT_HEAD_X1 + {SPR_SSXD, 16, 6, NULL, S_SERPENT_GIB1_2, 0, 0}, // S_SERPENT_GIB1_1 + {SPR_SSXD, 16, 6, A_FloatGib, S_SERPENT_GIB1_3, 0, 0}, // S_SERPENT_GIB1_2 + {SPR_SSXD, 16, 8, A_FloatGib, S_SERPENT_GIB1_4, 0, 0}, // S_SERPENT_GIB1_3 + {SPR_SSXD, 16, 8, A_FloatGib, S_SERPENT_GIB1_5, 0, 0}, // S_SERPENT_GIB1_4 + {SPR_SSXD, 16, 12, A_FloatGib, S_SERPENT_GIB1_6, 0, 0}, // S_SERPENT_GIB1_5 + {SPR_SSXD, 16, 12, A_FloatGib, S_SERPENT_GIB1_7, 0, 0}, // S_SERPENT_GIB1_6 + {SPR_SSXD, 16, 232, A_DelayGib, S_SERPENT_GIB1_8, 0, 0}, // S_SERPENT_GIB1_7 + {SPR_SSXD, 16, 12, A_SinkGib, S_SERPENT_GIB1_9, 0, 0}, // S_SERPENT_GIB1_8 + {SPR_SSXD, 16, 12, A_SinkGib, S_SERPENT_GIB1_10, 0, 0}, // S_SERPENT_GIB1_9 + {SPR_SSXD, 16, 8, A_SinkGib, S_SERPENT_GIB1_11, 0, 0}, // S_SERPENT_GIB1_10 + {SPR_SSXD, 16, 8, A_SinkGib, S_SERPENT_GIB1_12, 0, 0}, // S_SERPENT_GIB1_11 + {SPR_SSXD, 16, 8, A_SinkGib, S_NULL, 0, 0}, // S_SERPENT_GIB1_12 + {SPR_SSXD, 17, 6, NULL, S_SERPENT_GIB2_2, 0, 0}, // S_SERPENT_GIB2_1 + {SPR_SSXD, 17, 6, A_FloatGib, S_SERPENT_GIB2_3, 0, 0}, // S_SERPENT_GIB2_2 + {SPR_SSXD, 17, 8, A_FloatGib, S_SERPENT_GIB2_4, 0, 0}, // S_SERPENT_GIB2_3 + {SPR_SSXD, 17, 8, A_FloatGib, S_SERPENT_GIB2_5, 0, 0}, // S_SERPENT_GIB2_4 + {SPR_SSXD, 17, 12, A_FloatGib, S_SERPENT_GIB2_6, 0, 0}, // S_SERPENT_GIB2_5 + {SPR_SSXD, 17, 12, A_FloatGib, S_SERPENT_GIB2_7, 0, 0}, // S_SERPENT_GIB2_6 + {SPR_SSXD, 17, 232, A_DelayGib, S_SERPENT_GIB2_8, 0, 0}, // S_SERPENT_GIB2_7 + {SPR_SSXD, 17, 12, A_SinkGib, S_SERPENT_GIB2_9, 0, 0}, // S_SERPENT_GIB2_8 + {SPR_SSXD, 17, 12, A_SinkGib, S_SERPENT_GIB2_10, 0, 0}, // S_SERPENT_GIB2_9 + {SPR_SSXD, 17, 8, A_SinkGib, S_SERPENT_GIB2_11, 0, 0}, // S_SERPENT_GIB2_10 + {SPR_SSXD, 17, 8, A_SinkGib, S_SERPENT_GIB2_12, 0, 0}, // S_SERPENT_GIB2_11 + {SPR_SSXD, 17, 8, A_SinkGib, S_NULL, 0, 0}, // S_SERPENT_GIB2_12 + {SPR_SSXD, 19, 6, NULL, S_SERPENT_GIB3_2, 0, 0}, // S_SERPENT_GIB3_1 + {SPR_SSXD, 19, 6, A_FloatGib, S_SERPENT_GIB3_3, 0, 0}, // S_SERPENT_GIB3_2 + {SPR_SSXD, 19, 8, A_FloatGib, S_SERPENT_GIB3_4, 0, 0}, // S_SERPENT_GIB3_3 + {SPR_SSXD, 19, 8, A_FloatGib, S_SERPENT_GIB3_5, 0, 0}, // S_SERPENT_GIB3_4 + {SPR_SSXD, 19, 12, A_FloatGib, S_SERPENT_GIB3_6, 0, 0}, // S_SERPENT_GIB3_5 + {SPR_SSXD, 19, 12, A_FloatGib, S_SERPENT_GIB3_7, 0, 0}, // S_SERPENT_GIB3_6 + {SPR_SSXD, 19, 232, A_DelayGib, S_SERPENT_GIB3_8, 0, 0}, // S_SERPENT_GIB3_7 + {SPR_SSXD, 19, 12, A_SinkGib, S_SERPENT_GIB3_9, 0, 0}, // S_SERPENT_GIB3_8 + {SPR_SSXD, 19, 12, A_SinkGib, S_SERPENT_GIB3_10, 0, 0}, // S_SERPENT_GIB3_9 + {SPR_SSXD, 19, 8, A_SinkGib, S_SERPENT_GIB3_11, 0, 0}, // S_SERPENT_GIB3_10 + {SPR_SSXD, 19, 8, A_SinkGib, S_SERPENT_GIB3_12, 0, 0}, // S_SERPENT_GIB3_11 + {SPR_SSXD, 19, 8, A_SinkGib, S_NULL, 0, 0}, // S_SERPENT_GIB3_12 + {SPR_BISH, 0, 10, A_Look, S_BISHOP_LOOK1, 0, 0}, // S_BISHOP_LOOK1 + {SPR_BISH, 0, 1, A_BishopDecide, S_BISHOP_WALK1, 0, 0}, // S_BISHOP_DECIDE + {SPR_BISH, 0, 2, A_BishopDoBlur, S_BISHOP_BLUR2, 0, 0}, // S_BISHOP_BLUR1 + {SPR_BISH, 0, 4, A_BishopSpawnBlur, S_BISHOP_BLUR2, 0, 0}, // S_BISHOP_BLUR2 + {SPR_BISH, 0, 2, A_Chase, S_BISHOP_WALK2, 0, 0}, // S_BISHOP_WALK1 + {SPR_BISH, 0, 2, A_BishopChase, S_BISHOP_WALK3, 0, 0}, // S_BISHOP_WALK2 + {SPR_BISH, 0, 2, NULL, S_BISHOP_WALK4, 0, 0}, // S_BISHOP_WALK3 + {SPR_BISH, 1, 2, A_BishopChase, S_BISHOP_WALK5, 0, 0}, // S_BISHOP_WALK4 + {SPR_BISH, 1, 2, A_Chase, S_BISHOP_WALK6, 0, 0}, // S_BISHOP_WALK5 + {SPR_BISH, 1, 2, A_BishopChase, S_BISHOP_DECIDE, 0, 0}, // S_BISHOP_WALK6 + {SPR_BISH, 0, 3, A_FaceTarget, S_BISHOP_ATK2, 0, 0}, // S_BISHOP_ATK1 + {SPR_BISH, 32771, 3, A_FaceTarget, S_BISHOP_ATK3, 0, 0}, // S_BISHOP_ATK2 + {SPR_BISH, 32772, 3, A_FaceTarget, S_BISHOP_ATK4, 0, 0}, // S_BISHOP_ATK3 + {SPR_BISH, 32773, 3, A_BishopAttack, S_BISHOP_ATK5, 0, 0}, // S_BISHOP_ATK4 + {SPR_BISH, 32773, 5, A_BishopAttack2, S_BISHOP_ATK5, 0, 0}, // S_BISHOP_ATK5 + {SPR_BISH, 2, 6, A_Pain, S_BISHOP_PAIN2, 0, 0}, // S_BISHOP_PAIN1 + {SPR_BISH, 2, 6, A_BishopPainBlur, S_BISHOP_PAIN3, 0, 0}, // S_BISHOP_PAIN2 + {SPR_BISH, 2, 6, A_BishopPainBlur, S_BISHOP_PAIN4, 0, 0}, // S_BISHOP_PAIN3 + {SPR_BISH, 2, 6, A_BishopPainBlur, S_BISHOP_PAIN5, 0, 0}, // S_BISHOP_PAIN4 + {SPR_BISH, 2, 0, NULL, S_BISHOP_WALK1, 0, 0}, // S_BISHOP_PAIN5 + {SPR_BISH, 6, 6, NULL, S_BISHOP_DEATH2, 0, 0}, // S_BISHOP_DEATH1 + {SPR_BISH, 32775, 6, A_Scream, S_BISHOP_DEATH3, 0, 0}, // S_BISHOP_DEATH2 + {SPR_BISH, 32776, 5, A_NoBlocking, S_BISHOP_DEATH4, 0, 0}, // S_BISHOP_DEATH3 + {SPR_BISH, 32777, 5, A_Explode, S_BISHOP_DEATH5, 0, 0}, // S_BISHOP_DEATH4 + {SPR_BISH, 32778, 5, NULL, S_BISHOP_DEATH6, 0, 0}, // S_BISHOP_DEATH5 + {SPR_BISH, 32779, 4, NULL, S_BISHOP_DEATH7, 0, 0}, // S_BISHOP_DEATH6 + {SPR_BISH, 32780, 4, NULL, S_BISHOP_DEATH8, 0, 0}, // S_BISHOP_DEATH7 + {SPR_BISH, 13, 4, A_BishopPuff, S_BISHOP_DEATH9, 0, 0}, // S_BISHOP_DEATH8 + {SPR_BISH, 14, 4, A_QueueCorpse, S_BISHOP_DEATH10, 0, 0}, // S_BISHOP_DEATH9 + {SPR_BISH, 15, -1, NULL, S_NULL, 0, 0}, // S_BISHOP_DEATH10 + {SPR_BISH, 23, 5, A_FreezeDeath, S_BISHOP_ICE2, 0, 0}, // S_BISHOP_ICE + {SPR_BISH, 23, 1, A_FreezeDeathChunks, S_BISHOP_ICE2, 0, 0}, // S_BISHOP_ICE2 + {SPR_BISH, 16, 5, NULL, S_BISHOP_PUFF2, 0, 0}, // S_BISHOP_PUFF1 + {SPR_BISH, 17, 5, NULL, S_BISHOP_PUFF3, 0, 0}, // S_BISHOP_PUFF2 + {SPR_BISH, 18, 5, NULL, S_BISHOP_PUFF4, 0, 0}, // S_BISHOP_PUFF3 + {SPR_BISH, 19, 5, NULL, S_BISHOP_PUFF5, 0, 0}, // S_BISHOP_PUFF4 + {SPR_BISH, 20, 6, NULL, S_BISHOP_PUFF6, 0, 0}, // S_BISHOP_PUFF5 + {SPR_BISH, 21, 6, NULL, S_BISHOP_PUFF7, 0, 0}, // S_BISHOP_PUFF6 + {SPR_BISH, 22, 5, NULL, S_NULL, 0, 0}, // S_BISHOP_PUFF7 + {SPR_BISH, 0, 16, NULL, S_BISHOPBLUR2, 0, 0}, // S_BISHOPBLUR1 + {SPR_BISH, 0, 8, A_SetAltShadow, S_NULL, 0, 0}, // S_BISHOPBLUR2 + {SPR_BISH, 2, 8, NULL, S_NULL, 0, 0}, // S_BISHOPPAINBLUR1 + {SPR_BPFX, 32768, 1, A_BishopMissileWeave, S_BISHFX1_2, 0, 0}, // S_BISHFX1_1 + {SPR_BPFX, 32769, 1, A_BishopMissileWeave, S_BISHFX1_3, 0, 0}, // S_BISHFX1_2 + {SPR_BPFX, 32768, 1, A_BishopMissileWeave, S_BISHFX1_4, 0, 0}, // S_BISHFX1_3 + {SPR_BPFX, 32769, 1, A_BishopMissileWeave, S_BISHFX1_5, 0, 0}, // S_BISHFX1_4 + {SPR_BPFX, 32769, 0, A_BishopMissileSeek, S_BISHFX1_1, 0, 0}, // S_BISHFX1_5 + {SPR_BPFX, 32770, 4, NULL, S_BISHFXI1_2, 0, 0}, // S_BISHFXI1_1 + {SPR_BPFX, 32771, 4, NULL, S_BISHFXI1_3, 0, 0}, // S_BISHFXI1_2 + {SPR_BPFX, 32772, 4, NULL, S_BISHFXI1_4, 0, 0}, // S_BISHFXI1_3 + {SPR_BPFX, 32773, 4, NULL, S_BISHFXI1_5, 0, 0}, // S_BISHFXI1_4 + {SPR_BPFX, 32774, 3, NULL, S_BISHFXI1_6, 0, 0}, // S_BISHFXI1_5 + {SPR_BPFX, 32775, 3, NULL, S_NULL, 0, 0}, // S_BISHFXI1_6 + {SPR_DRAG, 3, 10, A_Look, S_DRAGON_LOOK1, 0, 0}, // S_DRAGON_LOOK1 + {SPR_DRAG, 2, 5, NULL, S_DRAGON_INIT2, 0, 0}, // S_DRAGON_INIT + {SPR_DRAG, 1, 5, NULL, S_DRAGON_INIT3, 0, 0}, // S_DRAGON_INIT2 + {SPR_DRAG, 0, 5, A_DragonInitFlight, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_INIT3 + {SPR_DRAG, 1, 3, A_DragonFlap, S_DRAGON_WALK2, 0, 0}, // S_DRAGON_WALK1 + {SPR_DRAG, 1, 3, A_DragonFlight, S_DRAGON_WALK3, 0, 0}, // S_DRAGON_WALK2 + {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK4, 0, 0}, // S_DRAGON_WALK3 + {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK5, 0, 0}, // S_DRAGON_WALK4 + {SPR_DRAG, 3, 3, A_DragonFlight, S_DRAGON_WALK6, 0, 0}, // S_DRAGON_WALK5 + {SPR_DRAG, 3, 3, A_DragonFlight, S_DRAGON_WALK7, 0, 0}, // S_DRAGON_WALK6 + {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK8, 0, 0}, // S_DRAGON_WALK7 + {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK9, 0, 0}, // S_DRAGON_WALK8 + {SPR_DRAG, 1, 3, A_DragonFlight, S_DRAGON_WALK10, 0, 0}, // S_DRAGON_WALK9 + {SPR_DRAG, 1, 3, A_DragonFlight, S_DRAGON_WALK11, 0, 0}, // S_DRAGON_WALK10 + {SPR_DRAG, 0, 3, A_DragonFlight, S_DRAGON_WALK12, 0, 0}, // S_DRAGON_WALK11 + {SPR_DRAG, 0, 3, A_DragonFlight, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_WALK12 + {SPR_DRAG, 4, 8, A_DragonAttack, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_ATK1 + {SPR_DRAG, 5, 10, A_DragonPain, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_PAIN1 + {SPR_DRAG, 6, 5, A_Scream, S_DRAGON_DEATH2, 0, 0}, // S_DRAGON_DEATH1 + {SPR_DRAG, 7, 4, A_NoBlocking, S_DRAGON_DEATH3, 0, 0}, // S_DRAGON_DEATH2 + {SPR_DRAG, 8, 4, NULL, S_DRAGON_DEATH4, 0, 0}, // S_DRAGON_DEATH3 + {SPR_DRAG, 9, 4, A_DragonCheckCrash, S_DRAGON_DEATH4, 0, 0}, // S_DRAGON_DEATH4 + {SPR_DRAG, 10, 5, NULL, S_DRAGON_CRASH2, 0, 0}, // S_DRAGON_CRASH1 + {SPR_DRAG, 11, 5, NULL, S_DRAGON_CRASH3, 0, 0}, // S_DRAGON_CRASH2 + {SPR_DRAG, 12, -1, NULL, S_NULL, 0, 0}, // S_DRAGON_CRASH3 + {SPR_DRFX, 32768, 4, NULL, S_DRAGON_FX1_2, 0, 0}, // S_DRAGON_FX1_1 + {SPR_DRFX, 32769, 4, NULL, S_DRAGON_FX1_3, 0, 0}, // S_DRAGON_FX1_2 + {SPR_DRFX, 32770, 4, NULL, S_DRAGON_FX1_4, 0, 0}, // S_DRAGON_FX1_3 + {SPR_DRFX, 32771, 4, NULL, S_DRAGON_FX1_5, 0, 0}, // S_DRAGON_FX1_4 + {SPR_DRFX, 32772, 4, NULL, S_DRAGON_FX1_6, 0, 0}, // S_DRAGON_FX1_5 + {SPR_DRFX, 32773, 4, NULL, S_DRAGON_FX1_1, 0, 0}, // S_DRAGON_FX1_6 + {SPR_DRFX, 32774, 4, NULL, S_DRAGON_FX1_X2, 0, 0}, // S_DRAGON_FX1_X1 + {SPR_DRFX, 32775, 4, NULL, S_DRAGON_FX1_X3, 0, 0}, // S_DRAGON_FX1_X2 + {SPR_DRFX, 32776, 4, NULL, S_DRAGON_FX1_X4, 0, 0}, // S_DRAGON_FX1_X3 + {SPR_DRFX, 32777, 4, A_DragonFX2, S_DRAGON_FX1_X5, 0, 0}, // S_DRAGON_FX1_X4 + {SPR_DRFX, 32778, 3, NULL, S_DRAGON_FX1_X6, 0, 0}, // S_DRAGON_FX1_X5 + {SPR_DRFX, 32779, 3, NULL, S_NULL, 0, 0}, // S_DRAGON_FX1_X6 + {SPR_CFCF, 32784, 1, NULL, S_DRAGON_FX2_2, 0, 0}, // S_DRAGON_FX2_1 + {SPR_CFCF, 32784, 4, A_UnHideThing, S_DRAGON_FX2_3, 0, 0}, // S_DRAGON_FX2_2 + {SPR_CFCF, 32785, 3, A_Scream, S_DRAGON_FX2_4, 0, 0}, // S_DRAGON_FX2_3 + {SPR_CFCF, 32786, 4, NULL, S_DRAGON_FX2_5, 0, 0}, // S_DRAGON_FX2_4 + {SPR_CFCF, 32787, 3, A_Explode, S_DRAGON_FX2_6, 0, 0}, // S_DRAGON_FX2_5 + {SPR_CFCF, 32788, 4, NULL, S_DRAGON_FX2_7, 0, 0}, // S_DRAGON_FX2_6 + {SPR_CFCF, 32789, 3, NULL, S_DRAGON_FX2_8, 0, 0}, // S_DRAGON_FX2_7 + {SPR_CFCF, 32790, 4, NULL, S_DRAGON_FX2_9, 0, 0}, // S_DRAGON_FX2_8 + {SPR_CFCF, 32791, 3, NULL, S_DRAGON_FX2_10, 0, 0}, // S_DRAGON_FX2_9 + {SPR_CFCF, 32792, 4, NULL, S_DRAGON_FX2_11, 0, 0}, // S_DRAGON_FX2_10 + {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_DRAGON_FX2_11 + {SPR_ARM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_1 + {SPR_ARM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_2 + {SPR_ARM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_3 + {SPR_ARM4, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_4 + {SPR_MAN1, 32768, 4, NULL, S_MANA1_2, 0, 0}, // S_MANA1_1 + {SPR_MAN1, 32769, 4, NULL, S_MANA1_3, 0, 0}, // S_MANA1_2 + {SPR_MAN1, 32770, 4, NULL, S_MANA1_4, 0, 0}, // S_MANA1_3 + {SPR_MAN1, 32771, 4, NULL, S_MANA1_5, 0, 0}, // S_MANA1_4 + {SPR_MAN1, 32772, 4, NULL, S_MANA1_6, 0, 0}, // S_MANA1_5 + {SPR_MAN1, 32773, 4, NULL, S_MANA1_7, 0, 0}, // S_MANA1_6 + {SPR_MAN1, 32774, 4, NULL, S_MANA1_8, 0, 0}, // S_MANA1_7 + {SPR_MAN1, 32775, 4, NULL, S_MANA1_9, 0, 0}, // S_MANA1_8 + {SPR_MAN1, 32776, 4, NULL, S_MANA1_1, 0, 0}, // S_MANA1_9 + {SPR_MAN2, 32768, 4, NULL, S_MANA2_2, 0, 0}, // S_MANA2_1 + {SPR_MAN2, 32769, 4, NULL, S_MANA2_3, 0, 0}, // S_MANA2_2 + {SPR_MAN2, 32770, 4, NULL, S_MANA2_4, 0, 0}, // S_MANA2_3 + {SPR_MAN2, 32771, 4, NULL, S_MANA2_5, 0, 0}, // S_MANA2_4 + {SPR_MAN2, 32772, 4, NULL, S_MANA2_6, 0, 0}, // S_MANA2_5 + {SPR_MAN2, 32773, 4, NULL, S_MANA2_7, 0, 0}, // S_MANA2_6 + {SPR_MAN2, 32774, 4, NULL, S_MANA2_8, 0, 0}, // S_MANA2_7 + {SPR_MAN2, 32775, 4, NULL, S_MANA2_9, 0, 0}, // S_MANA2_8 + {SPR_MAN2, 32776, 4, NULL, S_MANA2_10, 0, 0}, // S_MANA2_9 + {SPR_MAN2, 32777, 4, NULL, S_MANA2_11, 0, 0}, // S_MANA2_10 + {SPR_MAN2, 32778, 4, NULL, S_MANA2_12, 0, 0}, // S_MANA2_11 + {SPR_MAN2, 32779, 4, NULL, S_MANA2_13, 0, 0}, // S_MANA2_12 + {SPR_MAN2, 32780, 4, NULL, S_MANA2_14, 0, 0}, // S_MANA2_13 + {SPR_MAN2, 32781, 4, NULL, S_MANA2_15, 0, 0}, // S_MANA2_14 + {SPR_MAN2, 32782, 4, NULL, S_MANA2_16, 0, 0}, // S_MANA2_15 + {SPR_MAN2, 32783, 4, NULL, S_MANA2_1, 0, 0}, // S_MANA2_16 + {SPR_MAN3, 32768, 4, NULL, S_MANA3_2, 0, 0}, // S_MANA3_1 + {SPR_MAN3, 32769, 4, NULL, S_MANA3_3, 0, 0}, // S_MANA3_2 + {SPR_MAN3, 32770, 4, NULL, S_MANA3_4, 0, 0}, // S_MANA3_3 + {SPR_MAN3, 32771, 4, NULL, S_MANA3_5, 0, 0}, // S_MANA3_4 + {SPR_MAN3, 32772, 4, NULL, S_MANA3_6, 0, 0}, // S_MANA3_5 + {SPR_MAN3, 32773, 4, NULL, S_MANA3_7, 0, 0}, // S_MANA3_6 + {SPR_MAN3, 32774, 4, NULL, S_MANA3_8, 0, 0}, // S_MANA3_7 + {SPR_MAN3, 32775, 4, NULL, S_MANA3_9, 0, 0}, // S_MANA3_8 + {SPR_MAN3, 32776, 4, NULL, S_MANA3_10, 0, 0}, // S_MANA3_9 + {SPR_MAN3, 32777, 4, NULL, S_MANA3_11, 0, 0}, // S_MANA3_10 + {SPR_MAN3, 32778, 4, NULL, S_MANA3_12, 0, 0}, // S_MANA3_11 + {SPR_MAN3, 32779, 4, NULL, S_MANA3_13, 0, 0}, // S_MANA3_12 + {SPR_MAN3, 32780, 4, NULL, S_MANA3_14, 0, 0}, // S_MANA3_13 + {SPR_MAN3, 32781, 4, NULL, S_MANA3_15, 0, 0}, // S_MANA3_14 + {SPR_MAN3, 32782, 4, NULL, S_MANA3_16, 0, 0}, // S_MANA3_15 + {SPR_MAN3, 32783, 4, NULL, S_MANA3_1, 0, 0}, // S_MANA3_16 + {SPR_KEY1, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY1 + {SPR_KEY2, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY2 + {SPR_KEY3, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY3 + {SPR_KEY4, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY4 + {SPR_KEY5, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY5 + {SPR_KEY6, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY6 + {SPR_KEY7, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY7 + {SPR_KEY8, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY8 + {SPR_KEY9, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY9 + {SPR_KEYA, 0, -1, NULL, S_NULL, 0, 0}, // S_KEYA + {SPR_KEYB, 0, -1, NULL, S_NULL, 0, 0}, // S_KEYB + {SPR_TLGL, 0, 1, NULL, S_SND_WIND2, 0, 0}, // S_SND_WIND1 + {SPR_TLGL, 0, 200, A_ESound, S_SND_WIND2, 0, 0}, // S_SND_WIND2 + {SPR_TLGL, 0, 85, A_ESound, S_SND_WATERFALL, 0, 0}, // S_SND_WATERFALL + {SPR_ETTN, 0, 10, A_Look, S_ETTIN_LOOK2, 0, 0}, // S_ETTIN_LOOK1 + {SPR_ETTN, 0, 10, A_Look, S_ETTIN_LOOK1, 0, 0}, // S_ETTIN_LOOK2 + {SPR_ETTN, 0, 5, A_Chase, S_ETTIN_CHASE2, 0, 0}, // S_ETTIN_CHASE1 + {SPR_ETTN, 1, 5, A_Chase, S_ETTIN_CHASE3, 0, 0}, // S_ETTIN_CHASE2 + {SPR_ETTN, 2, 5, A_Chase, S_ETTIN_CHASE4, 0, 0}, // S_ETTIN_CHASE3 + {SPR_ETTN, 3, 5, A_Chase, S_ETTIN_CHASE1, 0, 0}, // S_ETTIN_CHASE4 + {SPR_ETTN, 7, 7, A_Pain, S_ETTIN_CHASE1, 0, 0}, // S_ETTIN_PAIN1 + {SPR_ETTN, 4, 6, A_FaceTarget, S_ETTIN_ATK1_2, 0, 0}, // S_ETTIN_ATK1_1 + {SPR_ETTN, 5, 6, A_FaceTarget, S_ETTIN_ATK1_3, 0, 0}, // S_ETTIN_ATK1_2 + {SPR_ETTN, 6, 8, A_EttinAttack, S_ETTIN_CHASE1, 0, 0}, // S_ETTIN_ATK1_3 + {SPR_ETTN, 8, 4, NULL, S_ETTIN_DEATH1_2, 0, 0}, // S_ETTIN_DEATH1_1 + {SPR_ETTN, 9, 4, NULL, S_ETTIN_DEATH1_3, 0, 0}, // S_ETTIN_DEATH1_2 + {SPR_ETTN, 10, 4, A_Scream, S_ETTIN_DEATH1_4, 0, 0}, // S_ETTIN_DEATH1_3 + {SPR_ETTN, 11, 4, A_NoBlocking, S_ETTIN_DEATH1_5, 0, 0}, // S_ETTIN_DEATH1_4 + {SPR_ETTN, 12, 4, A_QueueCorpse, S_ETTIN_DEATH1_6, 0, 0}, // S_ETTIN_DEATH1_5 + {SPR_ETTN, 13, 4, NULL, S_ETTIN_DEATH1_7, 0, 0}, // S_ETTIN_DEATH1_6 + {SPR_ETTN, 14, 4, NULL, S_ETTIN_DEATH1_8, 0, 0}, // S_ETTIN_DEATH1_7 + {SPR_ETTN, 15, 4, NULL, S_ETTIN_DEATH1_9, 0, 0}, // S_ETTIN_DEATH1_8 + {SPR_ETTN, 16, -1, NULL, S_NULL, 0, 0}, // S_ETTIN_DEATH1_9 + {SPR_ETTB, 0, 4, NULL, S_ETTIN_DEATH2_2, 0, 0}, // S_ETTIN_DEATH2_1 + {SPR_ETTB, 1, 4, A_NoBlocking, S_ETTIN_DEATH2_3, 0, 0}, // S_ETTIN_DEATH2_2 + {SPR_ETTB, 2, 4, A_DropMace, S_ETTIN_DEATH2_4, 0, 0}, // S_ETTIN_DEATH2_3 + {SPR_ETTB, 3, 4, A_Scream, S_ETTIN_DEATH2_5, 0, 0}, // S_ETTIN_DEATH2_4 + {SPR_ETTB, 4, 4, A_QueueCorpse, S_ETTIN_DEATH2_6, 0, 0}, // S_ETTIN_DEATH2_5 + {SPR_ETTB, 5, 4, NULL, S_ETTIN_DEATH2_7, 0, 0}, // S_ETTIN_DEATH2_6 + {SPR_ETTB, 6, 4, NULL, S_ETTIN_DEATH2_8, 0, 0}, // S_ETTIN_DEATH2_7 + {SPR_ETTB, 7, 4, NULL, S_ETTIN_DEATH2_9, 0, 0}, // S_ETTIN_DEATH2_8 + {SPR_ETTB, 8, 4, NULL, S_ETTIN_DEATH2_0, 0, 0}, // S_ETTIN_DEATH2_9 + {SPR_ETTB, 9, 4, NULL, S_ETTIN_DEATH2_A, 0, 0}, // S_ETTIN_DEATH2_0 + {SPR_ETTB, 10, 4, NULL, S_ETTIN_DEATH2_B, 0, 0}, // S_ETTIN_DEATH2_A + {SPR_ETTB, 11, -1, NULL, S_NULL, 0, 0}, // S_ETTIN_DEATH2_B + {SPR_ETTN, 17, 5, A_FreezeDeath, S_ETTIN_ICE2, 0, 0}, // S_ETTIN_ICE1 + {SPR_ETTN, 17, 1, A_FreezeDeathChunks, S_ETTIN_ICE2, 0, 0}, // S_ETTIN_ICE2 + {SPR_ETTB, 12, 5, A_CheckFloor, S_ETTIN_MACE2, 0, 0}, // S_ETTIN_MACE1 + {SPR_ETTB, 13, 5, A_CheckFloor, S_ETTIN_MACE3, 0, 0}, // S_ETTIN_MACE2 + {SPR_ETTB, 14, 5, A_CheckFloor, S_ETTIN_MACE4, 0, 0}, // S_ETTIN_MACE3 + {SPR_ETTB, 15, 5, A_CheckFloor, S_ETTIN_MACE1, 0, 0}, // S_ETTIN_MACE4 + {SPR_ETTB, 16, 5, NULL, S_ETTIN_MACE6, 0, 0}, // S_ETTIN_MACE5 + {SPR_ETTB, 17, 5, A_QueueCorpse, S_ETTIN_MACE7, 0, 0}, // S_ETTIN_MACE6 + {SPR_ETTB, 18, -1, NULL, S_NULL, 0, 0}, // S_ETTIN_MACE7 + {SPR_FDMN, 32791, 5, NULL, S_FIRED_LOOK1, 0, 0}, // S_FIRED_SPAWN1 + {SPR_FDMN, 32772, 10, A_Look, S_FIRED_LOOK2, 0, 0}, // S_FIRED_LOOK1 + {SPR_FDMN, 32773, 10, A_Look, S_FIRED_LOOK3, 0, 0}, // S_FIRED_LOOK2 + {SPR_FDMN, 32774, 10, A_Look, S_FIRED_LOOK1, 0, 0}, // S_FIRED_LOOK3 + {SPR_FDMN, 32772, 8, NULL, S_FIRED_LOOK5, 0, 0}, // S_FIRED_LOOK4 + {SPR_FDMN, 32773, 6, NULL, S_FIRED_LOOK6, 0, 0}, // S_FIRED_LOOK5 + {SPR_FDMN, 32774, 5, NULL, S_FIRED_LOOK7, 0, 0}, // S_FIRED_LOOK6 + {SPR_FDMN, 32773, 8, NULL, S_FIRED_LOOK8, 0, 0}, // S_FIRED_LOOK7 + {SPR_FDMN, 32772, 6, NULL, S_FIRED_LOOK9, 0, 0}, // S_FIRED_LOOK8 + {SPR_FDMN, 32773, 7, A_FiredRocks, S_FIRED_LOOK0, 0, 0}, // S_FIRED_LOOK9 + {SPR_FDMN, 32775, 5, NULL, S_FIRED_LOOKA, 0, 0}, // S_FIRED_LOOK0 + {SPR_FDMN, 32776, 5, NULL, S_FIRED_LOOKB, 0, 0}, // S_FIRED_LOOKA + {SPR_FDMN, 32777, 5, A_UnSetInvulnerable, S_FIRED_WALK1, 0, 0}, // S_FIRED_LOOKB + {SPR_FDMN, 32768, 5, A_FiredChase, S_FIRED_WALK2, 0, 0}, // S_FIRED_WALK1 + {SPR_FDMN, 32769, 5, A_FiredChase, S_FIRED_WALK3, 0, 0}, // S_FIRED_WALK2 + {SPR_FDMN, 32770, 5, A_FiredChase, S_FIRED_WALK1, 0, 0}, // S_FIRED_WALK3 + {SPR_FDMN, 32771, 6, A_Pain, S_FIRED_WALK1, 0, 0}, // S_FIRED_PAIN1 + {SPR_FDMN, 32778, 3, A_FaceTarget, S_FIRED_ATTACK2, 0, 0}, // S_FIRED_ATTACK1 + {SPR_FDMN, 32778, 5, A_FiredAttack, S_FIRED_ATTACK3, 0, 0}, // S_FIRED_ATTACK2 + {SPR_FDMN, 32778, 5, A_FiredAttack, S_FIRED_ATTACK4, 0, 0}, // S_FIRED_ATTACK3 + {SPR_FDMN, 32778, 5, A_FiredAttack, S_FIRED_WALK1, 0, 0}, // S_FIRED_ATTACK4 + {SPR_FDMN, 32771, 4, A_FaceTarget, S_FIRED_DEATH2, 0, 0}, // S_FIRED_DEATH1 + {SPR_FDMN, 32779, 4, A_Scream, S_FIRED_DEATH3, 0, 0}, // S_FIRED_DEATH2 + {SPR_FDMN, 32779, 4, A_NoBlocking, S_FIRED_DEATH4, 0, 0}, // S_FIRED_DEATH3 + {SPR_FDMN, 32779, 200, NULL, S_NULL, 0, 0}, // S_FIRED_DEATH4 + {SPR_FDMN, 12, 5, A_FaceTarget, S_FIRED_XDEATH2, 0, 0}, // S_FIRED_XDEATH1 + {SPR_FDMN, 13, 5, A_NoBlocking, S_FIRED_XDEATH3, 0, 0}, // S_FIRED_XDEATH2 + {SPR_FDMN, 14, 5, A_FiredSplotch, S_NULL, 0, 0}, // S_FIRED_XDEATH3 + {SPR_FDMN, 17, 5, A_FreezeDeath, S_FIRED_ICE2, 0, 0}, // S_FIRED_ICE1 + {SPR_FDMN, 17, 1, A_FreezeDeathChunks, S_FIRED_ICE2, 0, 0}, // S_FIRED_ICE2 + {SPR_FDMN, 15, 3, NULL, S_FIRED_CORPSE2, 0, 0}, // S_FIRED_CORPSE1 + {SPR_FDMN, 15, 6, A_QueueCorpse, S_FIRED_CORPSE3, 0, 0}, // S_FIRED_CORPSE2 + {SPR_FDMN, 24, -1, NULL, S_NULL, 0, 0}, // S_FIRED_CORPSE3 + {SPR_FDMN, 16, 3, NULL, S_FIRED_CORPSE5, 0, 0}, // S_FIRED_CORPSE4 + {SPR_FDMN, 16, 6, A_QueueCorpse, S_FIRED_CORPSE6, 0, 0}, // S_FIRED_CORPSE5 + {SPR_FDMN, 25, -1, NULL, S_NULL, 0, 0}, // S_FIRED_CORPSE6 + {SPR_FDMN, 18, 4, NULL, S_FIRED_RDROP1, 0, 0}, // S_FIRED_RDROP1 + {SPR_FDMN, 18, 5, A_SmBounce, S_FIRED_RDEAD1_2, 0, 0}, // S_FIRED_RDEAD1_1 + {SPR_FDMN, 18, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD1_2 + {SPR_FDMN, 19, 4, NULL, S_FIRED_RDROP2, 0, 0}, // S_FIRED_RDROP2 + {SPR_FDMN, 19, 5, A_SmBounce, S_FIRED_RDEAD2_2, 0, 0}, // S_FIRED_RDEAD2_1 + {SPR_FDMN, 19, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD2_2 + {SPR_FDMN, 20, 4, NULL, S_FIRED_RDROP3, 0, 0}, // S_FIRED_RDROP3 + {SPR_FDMN, 20, 5, A_SmBounce, S_FIRED_RDEAD3_2, 0, 0}, // S_FIRED_RDEAD3_1 + {SPR_FDMN, 20, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD3_2 + {SPR_FDMN, 21, 4, NULL, S_FIRED_RDROP4, 0, 0}, // S_FIRED_RDROP4 + {SPR_FDMN, 21, 5, A_SmBounce, S_FIRED_RDEAD4_2, 0, 0}, // S_FIRED_RDEAD4_1 + {SPR_FDMN, 21, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD4_2 + {SPR_FDMN, 22, 4, NULL, S_FIRED_RDROP5, 0, 0}, // S_FIRED_RDROP5 + {SPR_FDMN, 22, 5, A_SmBounce, S_FIRED_RDEAD5_2, 0, 0}, // S_FIRED_RDEAD5_1 + {SPR_FDMN, 22, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD5_2 + {SPR_FDMB, 32768, 5, NULL, S_FIRED_FX6_1, 0, 0}, // S_FIRED_FX6_1 + {SPR_FDMB, 32769, 5, NULL, S_FIRED_FX6_3, 0, 0}, // S_FIRED_FX6_2 + {SPR_FDMB, 32770, 5, NULL, S_FIRED_FX6_4, 0, 0}, // S_FIRED_FX6_3 + {SPR_FDMB, 32771, 5, NULL, S_FIRED_FX6_5, 0, 0}, // S_FIRED_FX6_4 + {SPR_FDMB, 32772, 5, NULL, S_NULL, 0, 0}, // S_FIRED_FX6_5 + {SPR_ICEY, 0, 10, A_IceGuyLook, S_ICEGUY_LOOK, 0, 0}, // S_ICEGUY_LOOK + {SPR_ICEY, 0, -1, NULL, S_ICEGUY_LOOK, 0, 0}, // S_ICEGUY_DORMANT + {SPR_ICEY, 0, 4, A_Chase, S_ICEGUY_WALK2, 0, 0}, // S_ICEGUY_WALK1 + {SPR_ICEY, 1, 4, A_IceGuyChase, S_ICEGUY_WALK3, 0, 0}, // S_ICEGUY_WALK2 + {SPR_ICEY, 2, 4, A_Chase, S_ICEGUY_WALK4, 0, 0}, // S_ICEGUY_WALK3 + {SPR_ICEY, 3, 4, A_Chase, S_ICEGUY_WALK1, 0, 0}, // S_ICEGUY_WALK4 + {SPR_ICEY, 4, 3, A_FaceTarget, S_ICEGUY_ATK2, 0, 0}, // S_ICEGUY_ATK1 + {SPR_ICEY, 5, 3, A_FaceTarget, S_ICEGUY_ATK3, 0, 0}, // S_ICEGUY_ATK2 + {SPR_ICEY, 32774, 8, A_IceGuyAttack, S_ICEGUY_ATK4, 0, 0}, // S_ICEGUY_ATK3 + {SPR_ICEY, 5, 4, A_FaceTarget, S_ICEGUY_WALK1, 0, 0}, // S_ICEGUY_ATK4 + {SPR_ICEY, 0, 1, A_Pain, S_ICEGUY_WALK1, 0, 0}, // S_ICEGUY_PAIN1 + {SPR_ICEY, 0, 1, A_IceGuyDie, S_NULL, 0, 0}, // S_ICEGUY_DEATH + {SPR_ICPR, 32768, 3, A_IceGuyMissilePuff, S_ICEGUY_FX2, 0, 0}, // S_ICEGUY_FX1 + {SPR_ICPR, 32769, 3, A_IceGuyMissilePuff, S_ICEGUY_FX3, 0, 0}, // S_ICEGUY_FX2 + {SPR_ICPR, 32770, 3, A_IceGuyMissilePuff, S_ICEGUY_FX1, 0, 0}, // S_ICEGUY_FX3 + {SPR_ICPR, 32771, 4, NULL, S_ICEGUY_FX_X2, 0, 0}, // S_ICEGUY_FX_X1 + {SPR_ICPR, 32772, 4, A_IceGuyMissileExplode, S_ICEGUY_FX_X3, 0, 0}, // S_ICEGUY_FX_X2 + {SPR_ICPR, 32773, 4, NULL, S_ICEGUY_FX_X4, 0, 0}, // S_ICEGUY_FX_X3 + {SPR_ICPR, 32774, 4, NULL, S_ICEGUY_FX_X5, 0, 0}, // S_ICEGUY_FX_X4 + {SPR_ICPR, 32775, 3, NULL, S_NULL, 0, 0}, // S_ICEGUY_FX_X5 + {SPR_ICPR, 8, 3, NULL, S_ICEFX_PUFF2, 0, 0}, // S_ICEFX_PUFF1 + {SPR_ICPR, 9, 3, NULL, S_ICEFX_PUFF3, 0, 0}, // S_ICEFX_PUFF2 + {SPR_ICPR, 10, 3, NULL, S_ICEFX_PUFF4, 0, 0}, // S_ICEFX_PUFF3 + {SPR_ICPR, 11, 2, NULL, S_ICEFX_PUFF5, 0, 0}, // S_ICEFX_PUFF4 + {SPR_ICPR, 12, 2, NULL, S_NULL, 0, 0}, // S_ICEFX_PUFF5 + {SPR_ICPR, 32781, 3, NULL, S_ICEGUY_FX2_2, 0, 0}, // S_ICEGUY_FX2_1 + {SPR_ICPR, 32782, 3, NULL, S_ICEGUY_FX2_3, 0, 0}, // S_ICEGUY_FX2_2 + {SPR_ICPR, 32783, 3, NULL, S_ICEGUY_FX2_1, 0, 0}, // S_ICEGUY_FX2_3 + {SPR_ICPR, 32784, 50, NULL, S_NULL, 0, 0}, // S_ICEGUY_BIT1 + {SPR_ICPR, 32785, 50, NULL, S_NULL, 0, 0}, // S_ICEGUY_BIT2 + {SPR_ICWS, 0, 2, NULL, S_ICEGUY_WISP1_2, 0, 0}, // S_ICEGUY_WISP1_1 + {SPR_ICWS, 1, 2, NULL, S_ICEGUY_WISP1_3, 0, 0}, // S_ICEGUY_WISP1_2 + {SPR_ICWS, 2, 2, NULL, S_ICEGUY_WISP1_4, 0, 0}, // S_ICEGUY_WISP1_3 + {SPR_ICWS, 3, 2, NULL, S_ICEGUY_WISP1_5, 0, 0}, // S_ICEGUY_WISP1_4 + {SPR_ICWS, 4, 2, NULL, S_ICEGUY_WISP1_6, 0, 0}, // S_ICEGUY_WISP1_5 + {SPR_ICWS, 5, 2, NULL, S_ICEGUY_WISP1_7, 0, 0}, // S_ICEGUY_WISP1_6 + {SPR_ICWS, 6, 2, NULL, S_ICEGUY_WISP1_8, 0, 0}, // S_ICEGUY_WISP1_7 + {SPR_ICWS, 7, 2, NULL, S_ICEGUY_WISP1_9, 0, 0}, // S_ICEGUY_WISP1_8 + {SPR_ICWS, 8, 2, NULL, S_NULL, 0, 0}, // S_ICEGUY_WISP1_9 + {SPR_ICWS, 9, 2, NULL, S_ICEGUY_WISP2_2, 0, 0}, // S_ICEGUY_WISP2_1 + {SPR_ICWS, 10, 2, NULL, S_ICEGUY_WISP2_3, 0, 0}, // S_ICEGUY_WISP2_2 + {SPR_ICWS, 11, 2, NULL, S_ICEGUY_WISP2_4, 0, 0}, // S_ICEGUY_WISP2_3 + {SPR_ICWS, 12, 2, NULL, S_ICEGUY_WISP2_5, 0, 0}, // S_ICEGUY_WISP2_4 + {SPR_ICWS, 13, 2, NULL, S_ICEGUY_WISP2_6, 0, 0}, // S_ICEGUY_WISP2_5 + {SPR_ICWS, 14, 2, NULL, S_ICEGUY_WISP2_7, 0, 0}, // S_ICEGUY_WISP2_6 + {SPR_ICWS, 15, 2, NULL, S_ICEGUY_WISP2_8, 0, 0}, // S_ICEGUY_WISP2_7 + {SPR_ICWS, 16, 2, NULL, S_ICEGUY_WISP2_9, 0, 0}, // S_ICEGUY_WISP2_8 + {SPR_ICWS, 17, 2, NULL, S_NULL, 0, 0}, // S_ICEGUY_WISP2_9 + {SPR_PLAY, 0, 2, NULL, S_FIGHTER2, 0, 0}, // S_FIGHTER + {SPR_PLAY, 0, 3, A_ClassBossHealth, S_FIGHTERLOOK, 0, 0}, // S_FIGHTER2 + {SPR_PLAY, 0, 5, A_Look, S_FIGHTERLOOK, 0, 0}, // S_FIGHTERLOOK + {SPR_PLAY, 0, 4, A_FastChase, S_FIGHTER_RUN2, 0, 0}, // S_FIGHTER_RUN1 + {SPR_PLAY, 1, 4, A_FastChase, S_FIGHTER_RUN3, 0, 0}, // S_FIGHTER_RUN2 + {SPR_PLAY, 2, 4, A_FastChase, S_FIGHTER_RUN4, 0, 0}, // S_FIGHTER_RUN3 + {SPR_PLAY, 3, 4, A_FastChase, S_FIGHTER_RUN1, 0, 0}, // S_FIGHTER_RUN4 + {SPR_PLAY, 4, 8, A_FaceTarget, S_FIGHTER_ATK2, 0, 0}, // S_FIGHTER_ATK1 + {SPR_PLAY, 5, 8, A_FighterAttack, S_FIGHTER_RUN1, 0, 0}, // S_FIGHTER_ATK2 + {SPR_PLAY, 6, 4, NULL, S_FIGHTER_PAIN2, 0, 0}, // S_FIGHTER_PAIN + {SPR_PLAY, 6, 4, A_Pain, S_FIGHTER_RUN1, 0, 0}, // S_FIGHTER_PAIN2 + {SPR_PLAY, 7, 6, NULL, S_FIGHTER_DIE2, 0, 0}, // S_FIGHTER_DIE1 + {SPR_PLAY, 8, 6, A_Scream, S_FIGHTER_DIE3, 0, 0}, // S_FIGHTER_DIE2 + {SPR_PLAY, 9, 6, NULL, S_FIGHTER_DIE4, 0, 0}, // S_FIGHTER_DIE3 + {SPR_PLAY, 10, 6, NULL, S_FIGHTER_DIE5, 0, 0}, // S_FIGHTER_DIE4 + {SPR_PLAY, 11, 6, A_NoBlocking, S_FIGHTER_DIE6, 0, 0}, // S_FIGHTER_DIE5 + {SPR_PLAY, 12, 6, NULL, S_FIGHTER_DIE7, 0, 0}, // S_FIGHTER_DIE6 + {SPR_PLAY, 13, -1, NULL, S_NULL, 0, 0}, // S_FIGHTER_DIE7 + {SPR_PLAY, 14, 5, A_Scream, S_FIGHTER_XDIE2, 0, 0}, // S_FIGHTER_XDIE1 + {SPR_PLAY, 15, 5, A_SkullPop, S_FIGHTER_XDIE3, 0, 0}, // S_FIGHTER_XDIE2 + {SPR_PLAY, 17, 5, A_NoBlocking, S_FIGHTER_XDIE4, 0, 0}, // S_FIGHTER_XDIE3 + {SPR_PLAY, 18, 5, NULL, S_FIGHTER_XDIE5, 0, 0}, // S_FIGHTER_XDIE4 + {SPR_PLAY, 19, 5, NULL, S_FIGHTER_XDIE6, 0, 0}, // S_FIGHTER_XDIE5 + {SPR_PLAY, 20, 5, NULL, S_FIGHTER_XDIE7, 0, 0}, // S_FIGHTER_XDIE6 + {SPR_PLAY, 21, 5, NULL, S_FIGHTER_XDIE8, 0, 0}, // S_FIGHTER_XDIE7 + {SPR_PLAY, 22, -1, NULL, S_NULL, 0, 0}, // S_FIGHTER_XDIE8 + {SPR_PLAY, 23, 5, A_FreezeDeath, S_FIGHTER_ICE2, 0, 0}, // S_FIGHTER_ICE + {SPR_PLAY, 23, 1, A_FreezeDeathChunks, S_FIGHTER_ICE2, 0, 0}, // S_FIGHTER_ICE2 + {SPR_CLER, 0, 2, NULL, S_CLERIC2, 0, 0}, // S_CLERIC + {SPR_CLER, 0, 3, A_ClassBossHealth, S_CLERICLOOK, 0, 0}, // S_CLERIC2 + {SPR_CLER, 0, 5, A_Look, S_CLERICLOOK, 0, 0}, // S_CLERICLOOK + {SPR_CLER, 0, 4, A_FastChase, S_CLERIC_RUN2, 0, 0}, // S_CLERIC_RUN1 + {SPR_CLER, 1, 4, A_FastChase, S_CLERIC_RUN3, 0, 0}, // S_CLERIC_RUN2 + {SPR_CLER, 2, 4, A_FastChase, S_CLERIC_RUN4, 0, 0}, // S_CLERIC_RUN3 + {SPR_CLER, 3, 4, A_FastChase, S_CLERIC_RUN1, 0, 0}, // S_CLERIC_RUN4 + {SPR_CLER, 4, 8, A_FaceTarget, S_CLERIC_ATK2, 0, 0}, // S_CLERIC_ATK1 + {SPR_CLER, 5, 8, A_FaceTarget, S_CLERIC_ATK3, 0, 0}, // S_CLERIC_ATK2 + {SPR_CLER, 6, 10, A_ClericAttack, S_CLERIC_RUN1, 0, 0}, // S_CLERIC_ATK3 + {SPR_CLER, 7, 4, NULL, S_CLERIC_PAIN2, 0, 0}, // S_CLERIC_PAIN + {SPR_CLER, 7, 4, A_Pain, S_CLERIC_RUN1, 0, 0}, // S_CLERIC_PAIN2 + {SPR_CLER, 8, 6, NULL, S_CLERIC_DIE2, 0, 0}, // S_CLERIC_DIE1 + {SPR_CLER, 10, 6, A_Scream, S_CLERIC_DIE3, 0, 0}, // S_CLERIC_DIE2 + {SPR_CLER, 11, 6, NULL, S_CLERIC_DIE4, 0, 0}, // S_CLERIC_DIE3 + {SPR_CLER, 11, 6, NULL, S_CLERIC_DIE5, 0, 0}, // S_CLERIC_DIE4 + {SPR_CLER, 12, 6, A_NoBlocking, S_CLERIC_DIE6, 0, 0}, // S_CLERIC_DIE5 + {SPR_CLER, 13, 6, NULL, S_CLERIC_DIE7, 0, 0}, // S_CLERIC_DIE6 + {SPR_CLER, 14, 6, NULL, S_CLERIC_DIE8, 0, 0}, // S_CLERIC_DIE7 + {SPR_CLER, 15, 6, NULL, S_CLERIC_DIE9, 0, 0}, // S_CLERIC_DIE8 + {SPR_CLER, 16, -1, NULL, S_NULL, 0, 0}, // S_CLERIC_DIE9 + {SPR_CLER, 17, 5, A_Scream, S_CLERIC_XDIE2, 0, 0}, // S_CLERIC_XDIE1 + {SPR_CLER, 18, 5, NULL, S_CLERIC_XDIE3, 0, 0}, // S_CLERIC_XDIE2 + {SPR_CLER, 19, 5, A_NoBlocking, S_CLERIC_XDIE4, 0, 0}, // S_CLERIC_XDIE3 + {SPR_CLER, 20, 5, NULL, S_CLERIC_XDIE5, 0, 0}, // S_CLERIC_XDIE4 + {SPR_CLER, 21, 5, NULL, S_CLERIC_XDIE6, 0, 0}, // S_CLERIC_XDIE5 + {SPR_CLER, 22, 5, NULL, S_CLERIC_XDIE7, 0, 0}, // S_CLERIC_XDIE6 + {SPR_CLER, 23, 5, NULL, S_CLERIC_XDIE8, 0, 0}, // S_CLERIC_XDIE7 + {SPR_CLER, 24, 5, NULL, S_CLERIC_XDIE9, 0, 0}, // S_CLERIC_XDIE8 + {SPR_CLER, 25, 5, NULL, S_CLERIC_XDIE10, 0, 0}, // S_CLERIC_XDIE9 + {SPR_CLER, 26, -1, NULL, S_NULL, 0, 0}, // S_CLERIC_XDIE10 + {SPR_CLER, 27, 5, A_FreezeDeath, S_CLERIC_ICE2, 0, 0}, // S_CLERIC_ICE + {SPR_CLER, 27, 1, A_FreezeDeathChunks, S_CLERIC_ICE2, 0, 0}, // S_CLERIC_ICE2 + {SPR_MAGE, 0, 2, NULL, S_MAGE2, 0, 0}, // S_MAGE + {SPR_MAGE, 0, 3, A_ClassBossHealth, S_MAGELOOK, 0, 0}, // S_MAGE2 + {SPR_MAGE, 0, 5, A_Look, S_MAGELOOK, 0, 0}, // S_MAGELOOK + {SPR_MAGE, 0, 4, A_FastChase, S_MAGE_RUN2, 0, 0}, // S_MAGE_RUN1 + {SPR_MAGE, 1, 4, A_FastChase, S_MAGE_RUN3, 0, 0}, // S_MAGE_RUN2 + {SPR_MAGE, 2, 4, A_FastChase, S_MAGE_RUN4, 0, 0}, // S_MAGE_RUN3 + {SPR_MAGE, 3, 4, A_FastChase, S_MAGE_RUN1, 0, 0}, // S_MAGE_RUN4 + {SPR_MAGE, 4, 8, A_FaceTarget, S_MAGE_ATK2, 0, 0}, // S_MAGE_ATK1 + {SPR_MAGE, 32773, 8, A_MageAttack, S_MAGE_RUN1, 0, 0}, // S_MAGE_ATK2 + {SPR_MAGE, 6, 4, NULL, S_MAGE_PAIN2, 0, 0}, // S_MAGE_PAIN + {SPR_MAGE, 6, 4, A_Pain, S_MAGE_RUN1, 0, 0}, // S_MAGE_PAIN2 + {SPR_MAGE, 7, 6, NULL, S_MAGE_DIE2, 0, 0}, // S_MAGE_DIE1 + {SPR_MAGE, 8, 6, A_Scream, S_MAGE_DIE3, 0, 0}, // S_MAGE_DIE2 + {SPR_MAGE, 9, 6, NULL, S_MAGE_DIE4, 0, 0}, // S_MAGE_DIE3 + {SPR_MAGE, 10, 6, NULL, S_MAGE_DIE5, 0, 0}, // S_MAGE_DIE4 + {SPR_MAGE, 11, 6, A_NoBlocking, S_MAGE_DIE6, 0, 0}, // S_MAGE_DIE5 + {SPR_MAGE, 12, 6, NULL, S_MAGE_DIE7, 0, 0}, // S_MAGE_DIE6 + {SPR_MAGE, 13, -1, NULL, S_NULL, 0, 0}, // S_MAGE_DIE7 + {SPR_MAGE, 14, 5, A_Scream, S_MAGE_XDIE2, 0, 0}, // S_MAGE_XDIE1 + {SPR_MAGE, 15, 5, NULL, S_MAGE_XDIE3, 0, 0}, // S_MAGE_XDIE2 + {SPR_MAGE, 17, 5, A_NoBlocking, S_MAGE_XDIE4, 0, 0}, // S_MAGE_XDIE3 + {SPR_MAGE, 18, 5, NULL, S_MAGE_XDIE5, 0, 0}, // S_MAGE_XDIE4 + {SPR_MAGE, 19, 5, NULL, S_MAGE_XDIE6, 0, 0}, // S_MAGE_XDIE5 + {SPR_MAGE, 20, 5, NULL, S_MAGE_XDIE7, 0, 0}, // S_MAGE_XDIE6 + {SPR_MAGE, 21, 5, NULL, S_MAGE_XDIE8, 0, 0}, // S_MAGE_XDIE7 + {SPR_MAGE, 22, 5, NULL, S_MAGE_XDIE9, 0, 0}, // S_MAGE_XDIE8 + {SPR_MAGE, 23, -1, NULL, S_NULL, 0, 0}, // S_MAGE_XDIE9 + {SPR_MAGE, 24, 5, A_FreezeDeath, S_MAGE_ICE2, 0, 0}, // S_MAGE_ICE + {SPR_MAGE, 24, 1, A_FreezeDeathChunks, S_MAGE_ICE2, 0, 0}, // S_MAGE_ICE2 + {SPR_SORC, 0, 3, NULL, S_SORC_SPAWN2, 0, 0}, // S_SORC_SPAWN1 + {SPR_SORC, 0, 2, A_SorcSpinBalls, S_SORC_LOOK1, 0, 0}, // S_SORC_SPAWN2 + {SPR_SORC, 0, 10, A_Look, S_SORC_LOOK1, 0, 0}, // S_SORC_LOOK1 + {SPR_SORC, 0, 5, A_Chase, S_SORC_WALK2, 0, 0}, // S_SORC_WALK1 + {SPR_SORC, 1, 5, A_Chase, S_SORC_WALK3, 0, 0}, // S_SORC_WALK2 + {SPR_SORC, 2, 5, A_Chase, S_SORC_WALK4, 0, 0}, // S_SORC_WALK3 + {SPR_SORC, 3, 5, A_Chase, S_SORC_WALK1, 0, 0}, // S_SORC_WALK4 + {SPR_SORC, 6, 8, NULL, S_SORC_PAIN2, 0, 0}, // S_SORC_PAIN1 + {SPR_SORC, 6, 8, A_Pain, S_SORC_WALK1, 0, 0}, // S_SORC_PAIN2 + {SPR_SORC, 32773, 6, A_FaceTarget, S_SORC_ATK2_2, 0, 0}, // S_SORC_ATK2_1 + {SPR_SORC, 32773, 6, A_SpeedBalls, S_SORC_ATK2_3, 0, 0}, // S_SORC_ATK2_2 + {SPR_SORC, 32773, 6, A_FaceTarget, S_SORC_ATK2_3, 0, 0}, // S_SORC_ATK2_3 + {SPR_SORC, 32772, 6, NULL, S_SORC_ATTACK2, 0, 0}, // S_SORC_ATTACK1 + {SPR_SORC, 32772, 6, A_SpawnFizzle, S_SORC_ATTACK3, 0, 0}, // S_SORC_ATTACK2 + {SPR_SORC, 32772, 5, A_FaceTarget, S_SORC_ATTACK2, 0, 0}, // S_SORC_ATTACK3 + {SPR_SORC, 32772, 2, NULL, S_SORC_ATTACK5, 0, 0}, // S_SORC_ATTACK4 + {SPR_SORC, 32772, 2, A_SorcBossAttack, S_SORC_WALK1, 0, 0}, // S_SORC_ATTACK5 + {SPR_SORC, 32775, 5, NULL, S_SORC_DIE2, 0, 0}, // S_SORC_DIE1 + {SPR_SORC, 32776, 5, A_FaceTarget, S_SORC_DIE3, 0, 0}, // S_SORC_DIE2 + {SPR_SORC, 32777, 5, A_Scream, S_SORC_DIE4, 0, 0}, // S_SORC_DIE3 + {SPR_SORC, 32778, 5, NULL, S_SORC_DIE5, 0, 0}, // S_SORC_DIE4 + {SPR_SORC, 32779, 5, NULL, S_SORC_DIE6, 0, 0}, // S_SORC_DIE5 + {SPR_SORC, 32780, 5, NULL, S_SORC_DIE7, 0, 0}, // S_SORC_DIE6 + {SPR_SORC, 32781, 5, NULL, S_SORC_DIE8, 0, 0}, // S_SORC_DIE7 + {SPR_SORC, 32782, 5, NULL, S_SORC_DIE9, 0, 0}, // S_SORC_DIE8 + {SPR_SORC, 32783, 5, NULL, S_SORC_DIE0, 0, 0}, // S_SORC_DIE9 + {SPR_SORC, 32784, 5, NULL, S_SORC_DIEA, 0, 0}, // S_SORC_DIE0 + {SPR_SORC, 32785, 5, NULL, S_SORC_DIEB, 0, 0}, // S_SORC_DIEA + {SPR_SORC, 32786, 5, NULL, S_SORC_DIEC, 0, 0}, // S_SORC_DIEB + {SPR_SORC, 32787, 5, NULL, S_SORC_DIED, 0, 0}, // S_SORC_DIEC + {SPR_SORC, 32788, 5, A_NoBlocking, S_SORC_DIEE, 0, 0}, // S_SORC_DIED + {SPR_SORC, 32789, 5, NULL, S_SORC_DIEF, 0, 0}, // S_SORC_DIEE + {SPR_SORC, 32790, 5, NULL, S_SORC_DIEG, 0, 0}, // S_SORC_DIEF + {SPR_SORC, 32791, 5, NULL, S_SORC_DIEH, 0, 0}, // S_SORC_DIEG + {SPR_SORC, 32792, 5, NULL, S_SORC_DIEI, 0, 0}, // S_SORC_DIEH + {SPR_SORC, 32793, -1, NULL, S_NULL, 0, 0}, // S_SORC_DIEI + {SPR_SBMP, 0, 2, A_SorcBallOrbit, S_SORCBALL1_2, 0, 0}, // S_SORCBALL1_1 + {SPR_SBMP, 1, 2, A_SorcBallOrbit, S_SORCBALL1_3, 0, 0}, // S_SORCBALL1_2 + {SPR_SBMP, 2, 2, A_SorcBallOrbit, S_SORCBALL1_4, 0, 0}, // S_SORCBALL1_3 + {SPR_SBMP, 3, 2, A_SorcBallOrbit, S_SORCBALL1_5, 0, 0}, // S_SORCBALL1_4 + {SPR_SBMP, 4, 2, A_SorcBallOrbit, S_SORCBALL1_6, 0, 0}, // S_SORCBALL1_5 + {SPR_SBMP, 5, 2, A_SorcBallOrbit, S_SORCBALL1_7, 0, 0}, // S_SORCBALL1_6 + {SPR_SBMP, 6, 2, A_SorcBallOrbit, S_SORCBALL1_8, 0, 0}, // S_SORCBALL1_7 + {SPR_SBMP, 7, 2, A_SorcBallOrbit, S_SORCBALL1_9, 0, 0}, // S_SORCBALL1_8 + {SPR_SBMP, 8, 2, A_SorcBallOrbit, S_SORCBALL1_0, 0, 0}, // S_SORCBALL1_9 + {SPR_SBMP, 9, 2, A_SorcBallOrbit, S_SORCBALL1_A, 0, 0}, // S_SORCBALL1_0 + {SPR_SBMP, 10, 2, A_SorcBallOrbit, S_SORCBALL1_B, 0, 0}, // S_SORCBALL1_A + {SPR_SBMP, 11, 2, A_SorcBallOrbit, S_SORCBALL1_C, 0, 0}, // S_SORCBALL1_B + {SPR_SBMP, 12, 2, A_SorcBallOrbit, S_SORCBALL1_D, 0, 0}, // S_SORCBALL1_C + {SPR_SBMP, 13, 2, A_SorcBallOrbit, S_SORCBALL1_E, 0, 0}, // S_SORCBALL1_D + {SPR_SBMP, 14, 2, A_SorcBallOrbit, S_SORCBALL1_F, 0, 0}, // S_SORCBALL1_E + {SPR_SBMP, 15, 2, A_SorcBallOrbit, S_SORCBALL1_1, 0, 0}, // S_SORCBALL1_F + {SPR_SBMP, 0, 5, A_SorcBallPop, S_SORCBALL1_D2, 0, 0}, // S_SORCBALL1_D1 + {SPR_SBMP, 1, 2, A_BounceCheck, S_SORCBALL1_D2, 0, 0}, // S_SORCBALL1_D2 + {SPR_SBS4, 3, 5, A_Explode, S_SORCBALL1_D6, 0, 0}, // S_SORCBALL1_D5 + {SPR_SBS4, 4, 5, NULL, S_SORCBALL1_D7, 0, 0}, // S_SORCBALL1_D6 + {SPR_SBS4, 5, 6, NULL, S_SORCBALL1_D8, 0, 0}, // S_SORCBALL1_D7 + {SPR_SBS4, 6, 6, NULL, S_SORCBALL1_D9, 0, 0}, // S_SORCBALL1_D8 + {SPR_SBS4, 7, 6, NULL, S_NULL, 0, 0}, // S_SORCBALL1_D9 + {SPR_SBMB, 0, 2, A_SorcBallOrbit, S_SORCBALL2_2, 0, 0}, // S_SORCBALL2_1 + {SPR_SBMB, 1, 2, A_SorcBallOrbit, S_SORCBALL2_3, 0, 0}, // S_SORCBALL2_2 + {SPR_SBMB, 2, 2, A_SorcBallOrbit, S_SORCBALL2_4, 0, 0}, // S_SORCBALL2_3 + {SPR_SBMB, 3, 2, A_SorcBallOrbit, S_SORCBALL2_5, 0, 0}, // S_SORCBALL2_4 + {SPR_SBMB, 4, 2, A_SorcBallOrbit, S_SORCBALL2_6, 0, 0}, // S_SORCBALL2_5 + {SPR_SBMB, 5, 2, A_SorcBallOrbit, S_SORCBALL2_7, 0, 0}, // S_SORCBALL2_6 + {SPR_SBMB, 6, 2, A_SorcBallOrbit, S_SORCBALL2_8, 0, 0}, // S_SORCBALL2_7 + {SPR_SBMB, 7, 2, A_SorcBallOrbit, S_SORCBALL2_9, 0, 0}, // S_SORCBALL2_8 + {SPR_SBMB, 8, 2, A_SorcBallOrbit, S_SORCBALL2_0, 0, 0}, // S_SORCBALL2_9 + {SPR_SBMB, 9, 2, A_SorcBallOrbit, S_SORCBALL2_A, 0, 0}, // S_SORCBALL2_0 + {SPR_SBMB, 10, 2, A_SorcBallOrbit, S_SORCBALL2_B, 0, 0}, // S_SORCBALL2_A + {SPR_SBMB, 11, 2, A_SorcBallOrbit, S_SORCBALL2_C, 0, 0}, // S_SORCBALL2_B + {SPR_SBMB, 12, 2, A_SorcBallOrbit, S_SORCBALL2_D, 0, 0}, // S_SORCBALL2_C + {SPR_SBMB, 13, 2, A_SorcBallOrbit, S_SORCBALL2_E, 0, 0}, // S_SORCBALL2_D + {SPR_SBMB, 14, 2, A_SorcBallOrbit, S_SORCBALL2_F, 0, 0}, // S_SORCBALL2_E + {SPR_SBMB, 15, 2, A_SorcBallOrbit, S_SORCBALL2_1, 0, 0}, // S_SORCBALL2_F + {SPR_SBMB, 0, 5, A_SorcBallPop, S_SORCBALL2_D2, 0, 0}, // S_SORCBALL2_D1 + {SPR_SBMB, 1, 2, A_BounceCheck, S_SORCBALL2_D2, 0, 0}, // S_SORCBALL2_D2 + {SPR_SBS3, 3, 5, A_Explode, S_SORCBALL2_D6, 0, 0}, // S_SORCBALL2_D5 + {SPR_SBS3, 4, 5, NULL, S_SORCBALL2_D7, 0, 0}, // S_SORCBALL2_D6 + {SPR_SBS3, 5, 6, NULL, S_SORCBALL2_D8, 0, 0}, // S_SORCBALL2_D7 + {SPR_SBS3, 6, 6, NULL, S_SORCBALL2_D9, 0, 0}, // S_SORCBALL2_D8 + {SPR_SBS3, 7, 6, NULL, S_NULL, 0, 0}, // S_SORCBALL2_D9 + {SPR_SBMG, 0, 2, A_SorcBallOrbit, S_SORCBALL3_2, 0, 0}, // S_SORCBALL3_1 + {SPR_SBMG, 1, 2, A_SorcBallOrbit, S_SORCBALL3_3, 0, 0}, // S_SORCBALL3_2 + {SPR_SBMG, 2, 2, A_SorcBallOrbit, S_SORCBALL3_4, 0, 0}, // S_SORCBALL3_3 + {SPR_SBMG, 3, 2, A_SorcBallOrbit, S_SORCBALL3_5, 0, 0}, // S_SORCBALL3_4 + {SPR_SBMG, 4, 2, A_SorcBallOrbit, S_SORCBALL3_6, 0, 0}, // S_SORCBALL3_5 + {SPR_SBMG, 5, 2, A_SorcBallOrbit, S_SORCBALL3_7, 0, 0}, // S_SORCBALL3_6 + {SPR_SBMG, 6, 2, A_SorcBallOrbit, S_SORCBALL3_8, 0, 0}, // S_SORCBALL3_7 + {SPR_SBMG, 7, 2, A_SorcBallOrbit, S_SORCBALL3_9, 0, 0}, // S_SORCBALL3_8 + {SPR_SBMG, 8, 2, A_SorcBallOrbit, S_SORCBALL3_0, 0, 0}, // S_SORCBALL3_9 + {SPR_SBMG, 9, 2, A_SorcBallOrbit, S_SORCBALL3_A, 0, 0}, // S_SORCBALL3_0 + {SPR_SBMG, 10, 2, A_SorcBallOrbit, S_SORCBALL3_B, 0, 0}, // S_SORCBALL3_A + {SPR_SBMG, 11, 2, A_SorcBallOrbit, S_SORCBALL3_C, 0, 0}, // S_SORCBALL3_B + {SPR_SBMG, 12, 2, A_SorcBallOrbit, S_SORCBALL3_D, 0, 0}, // S_SORCBALL3_C + {SPR_SBMG, 13, 2, A_SorcBallOrbit, S_SORCBALL3_E, 0, 0}, // S_SORCBALL3_D + {SPR_SBMG, 14, 2, A_SorcBallOrbit, S_SORCBALL3_F, 0, 0}, // S_SORCBALL3_E + {SPR_SBMG, 15, 2, A_SorcBallOrbit, S_SORCBALL3_1, 0, 0}, // S_SORCBALL3_F + {SPR_SBMG, 0, 5, A_SorcBallPop, S_SORCBALL3_D2, 0, 0}, // S_SORCBALL3_D1 + {SPR_SBMG, 1, 2, A_BounceCheck, S_SORCBALL3_D2, 0, 0}, // S_SORCBALL3_D2 + {SPR_SBS3, 3, 5, A_Explode, S_SORCBALL3_D6, 0, 0}, // S_SORCBALL3_D5 + {SPR_SBS3, 4, 5, NULL, S_SORCBALL3_D7, 0, 0}, // S_SORCBALL3_D6 + {SPR_SBS3, 5, 6, NULL, S_SORCBALL3_D8, 0, 0}, // S_SORCBALL3_D7 + {SPR_SBS3, 6, 6, NULL, S_SORCBALL3_D9, 0, 0}, // S_SORCBALL3_D8 + {SPR_SBS3, 7, 6, NULL, S_NULL, 0, 0}, // S_SORCBALL3_D9 + {SPR_SBS1, 32768, 2, NULL, S_SORCFX1_2, 0, 0}, // S_SORCFX1_1 + {SPR_SBS1, 32769, 3, A_SorcFX1Seek, S_SORCFX1_3, 0, 0}, // S_SORCFX1_2 + {SPR_SBS1, 32770, 3, A_SorcFX1Seek, S_SORCFX1_4, 0, 0}, // S_SORCFX1_3 + {SPR_SBS1, 32771, 3, A_SorcFX1Seek, S_SORCFX1_1, 0, 0}, // S_SORCFX1_4 + {SPR_FHFX, 32786, 2, A_Explode, S_SORCFX1_D2, 0, 0}, // S_SORCFX1_D1 + {SPR_FHFX, 32786, 6, NULL, S_SORCFX1_D3, 0, 0}, // S_SORCFX1_D2 + {SPR_FHFX, 32786, 6, NULL, S_NULL, 0, 0}, // S_SORCFX1_D3 + {SPR_SBS2, 32768, 3, A_SorcFX2Split, S_SORCFX2_SPLIT1, 0, 0}, // S_SORCFX2_SPLIT1 + {SPR_SBS2, 32768, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT2, 0, 0}, // S_SORCFX2_ORBIT1 + {SPR_SBS2, 32769, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT3, 0, 0}, // S_SORCFX2_ORBIT2 + {SPR_SBS2, 32770, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT4, 0, 0}, // S_SORCFX2_ORBIT3 + {SPR_SBS2, 32771, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT5, 0, 0}, // S_SORCFX2_ORBIT4 + {SPR_SBS2, 32772, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT6, 0, 0}, // S_SORCFX2_ORBIT5 + {SPR_SBS2, 32773, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT7, 0, 0}, // S_SORCFX2_ORBIT6 + {SPR_SBS2, 32774, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT8, 0, 0}, // S_SORCFX2_ORBIT7 + {SPR_SBS2, 32775, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT9, 0, 0}, // S_SORCFX2_ORBIT8 + {SPR_SBS2, 32776, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT0, 0, 0}, // S_SORCFX2_ORBIT9 + {SPR_SBS2, 32777, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITA, 0, 0}, // S_SORCFX2_ORBIT0 + {SPR_SBS2, 32778, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITB, 0, 0}, // S_SORCFX2_ORBITA + {SPR_SBS2, 32779, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITC, 0, 0}, // S_SORCFX2_ORBITB + {SPR_SBS2, 32780, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITD, 0, 0}, // S_SORCFX2_ORBITC + {SPR_SBS2, 32781, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITE, 0, 0}, // S_SORCFX2_ORBITD + {SPR_SBS2, 32782, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITF, 0, 0}, // S_SORCFX2_ORBITE + {SPR_SBS2, 32783, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT1, 0, 0}, // S_SORCFX2_ORBITF + {SPR_SBS2, 0, 10, NULL, S_NULL, 0, 0}, // S_SORCFX2T1 + {SPR_SBS3, 32768, 2, NULL, S_SORCFX3_2, 0, 0}, // S_SORCFX3_1 + {SPR_SBS3, 32769, 2, NULL, S_SORCFX3_3, 0, 0}, // S_SORCFX3_2 + {SPR_SBS3, 32770, 2, NULL, S_SORCFX3_1, 0, 0}, // S_SORCFX3_3 + {SPR_SBS3, 32768, 4, NULL, S_BISHMORPHA, 0, 0}, // S_BISHMORPH1 + {SPR_BISH, 15, 4, A_SorcererBishopEntry, S_BISHMORPHB, 0, 0}, // S_BISHMORPHA + {SPR_BISH, 14, 4, NULL, S_BISHMORPHC, 0, 0}, // S_BISHMORPHB + {SPR_BISH, 13, 4, NULL, S_BISHMORPHD, 0, 0}, // S_BISHMORPHC + {SPR_BISH, 12, 3, NULL, S_BISHMORPHE, 0, 0}, // S_BISHMORPHD + {SPR_BISH, 11, 3, NULL, S_BISHMORPHF, 0, 0}, // S_BISHMORPHE + {SPR_BISH, 10, 3, NULL, S_BISHMORPHG, 0, 0}, // S_BISHMORPHF + {SPR_BISH, 9, 3, NULL, S_BISHMORPHH, 0, 0}, // S_BISHMORPHG + {SPR_BISH, 8, 3, NULL, S_BISHMORPHI, 0, 0}, // S_BISHMORPHH + {SPR_BISH, 7, 3, NULL, S_BISHMORPHJ, 0, 0}, // S_BISHMORPHI + {SPR_BISH, 6, 3, A_SpawnBishop, S_NULL, 0, 0}, // S_BISHMORPHJ + {SPR_SBS3, 3, 3, NULL, S_SORCFX3_EXP2, 0, 0}, // S_SORCFX3_EXP1 + {SPR_SBS3, 4, 3, NULL, S_SORCFX3_EXP3, 0, 0}, // S_SORCFX3_EXP2 + {SPR_SBS3, 5, 3, NULL, S_SORCFX3_EXP4, 0, 0}, // S_SORCFX3_EXP3 + {SPR_SBS3, 6, 3, NULL, S_SORCFX3_EXP5, 0, 0}, // S_SORCFX3_EXP4 + {SPR_SBS3, 7, 3, NULL, S_NULL, 0, 0}, // S_SORCFX3_EXP5 + {SPR_SBS4, 32768, 2, A_SorcFX4Check, S_SORCFX4_2, 0, 0}, // S_SORCFX4_1 + {SPR_SBS4, 32769, 2, A_SorcFX4Check, S_SORCFX4_3, 0, 0}, // S_SORCFX4_2 + {SPR_SBS4, 32770, 2, A_SorcFX4Check, S_SORCFX4_1, 0, 0}, // S_SORCFX4_3 + {SPR_SBS4, 32771, 2, NULL, S_SORCFX4_D2, 0, 0}, // S_SORCFX4_D1 + {SPR_SBS4, 32772, 2, A_Explode, S_SORCFX4_D3, 0, 0}, // S_SORCFX4_D2 + {SPR_SBS4, 32773, 2, NULL, S_SORCFX4_D4, 0, 0}, // S_SORCFX4_D3 + {SPR_SBS4, 32774, 2, NULL, S_SORCFX4_D5, 0, 0}, // S_SORCFX4_D4 + {SPR_SBS4, 32775, 2, NULL, S_NULL, 0, 0}, // S_SORCFX4_D5 + {SPR_SBFX, 32768, 4, NULL, S_SORCSPARK2, 0, 0}, // S_SORCSPARK1 + {SPR_SBFX, 32769, 4, NULL, S_SORCSPARK3, 0, 0}, // S_SORCSPARK2 + {SPR_SBFX, 32770, 4, NULL, S_SORCSPARK4, 0, 0}, // S_SORCSPARK3 + {SPR_SBFX, 32771, 4, NULL, S_SORCSPARK5, 0, 0}, // S_SORCSPARK4 + {SPR_SBFX, 32772, 4, NULL, S_SORCSPARK6, 0, 0}, // S_SORCSPARK5 + {SPR_SBFX, 32773, 4, NULL, S_SORCSPARK7, 0, 0}, // S_SORCSPARK6 + {SPR_SBFX, 32774, 4, NULL, S_NULL, 0, 0}, // S_SORCSPARK7 + {SPR_RADE, 0, 4, NULL, S_BLASTEFFECT2, 0, 0}, // S_BLASTEFFECT1 + {SPR_RADE, 1, 4, NULL, S_BLASTEFFECT3, 0, 0}, // S_BLASTEFFECT2 + {SPR_RADE, 2, 4, NULL, S_BLASTEFFECT4, 0, 0}, // S_BLASTEFFECT3 + {SPR_RADE, 3, 4, NULL, S_BLASTEFFECT5, 0, 0}, // S_BLASTEFFECT4 + {SPR_RADE, 4, 4, NULL, S_BLASTEFFECT6, 0, 0}, // S_BLASTEFFECT5 + {SPR_RADE, 5, 4, NULL, S_BLASTEFFECT7, 0, 0}, // S_BLASTEFFECT6 + {SPR_RADE, 6, 4, NULL, S_BLASTEFFECT8, 0, 0}, // S_BLASTEFFECT7 + {SPR_RADE, 7, 4, NULL, S_BLASTEFFECT9, 0, 0}, // S_BLASTEFFECT8 + {SPR_RADE, 8, 4, NULL, S_NULL, 0, 0}, // S_BLASTEFFECT9 + {SPR_WATR, 0, 5, NULL, S_WATERDRIP1, 0, 0}, // S_WATERDRIP1 + {SPR_KORX, 0, 5, A_Look, S_KORAX_LOOK1, 0, 0}, // S_KORAX_LOOK1 + {SPR_KORX, 0, 3, A_KoraxStep2, S_KORAX_CHASE2, 0, 0}, // S_KORAX_CHASE1 + {SPR_KORX, 0, 3, A_KoraxChase, S_KORAX_CHASE3, 0, 0}, // S_KORAX_CHASE2 + {SPR_KORX, 0, 3, A_KoraxChase, S_KORAX_CHASE4, 0, 0}, // S_KORAX_CHASE3 + {SPR_KORX, 0, 3, A_KoraxChase, S_KORAX_CHASE5, 0, 0}, // S_KORAX_CHASE4 + {SPR_KORX, 1, 3, A_KoraxStep, S_KORAX_CHASE6, 0, 0}, // S_KORAX_CHASE5 + {SPR_KORX, 1, 3, A_KoraxChase, S_KORAX_CHASE7, 0, 0}, // S_KORAX_CHASE6 + {SPR_KORX, 1, 3, A_KoraxChase, S_KORAX_CHASE8, 0, 0}, // S_KORAX_CHASE7 + {SPR_KORX, 1, 3, A_KoraxChase, S_KORAX_CHASE9, 0, 0}, // S_KORAX_CHASE8 + {SPR_KORX, 2, 3, A_KoraxStep2, S_KORAX_CHASE0, 0, 0}, // S_KORAX_CHASE9 + {SPR_KORX, 2, 3, A_KoraxChase, S_KORAX_CHASEA, 0, 0}, // S_KORAX_CHASE0 + {SPR_KORX, 2, 3, A_KoraxChase, S_KORAX_CHASEB, 0, 0}, // S_KORAX_CHASEA + {SPR_KORX, 2, 3, A_KoraxChase, S_KORAX_CHASEC, 0, 0}, // S_KORAX_CHASEB + {SPR_KORX, 3, 3, A_KoraxStep, S_KORAX_CHASED, 0, 0}, // S_KORAX_CHASEC + {SPR_KORX, 3, 3, A_KoraxChase, S_KORAX_CHASEE, 0, 0}, // S_KORAX_CHASED + {SPR_KORX, 3, 3, A_KoraxChase, S_KORAX_CHASEF, 0, 0}, // S_KORAX_CHASEE + {SPR_KORX, 3, 3, A_KoraxChase, S_KORAX_CHASE1, 0, 0}, // S_KORAX_CHASEF + {SPR_KORX, 7, 5, A_Pain, S_KORAX_PAIN2, 0, 0}, // S_KORAX_PAIN1 + {SPR_KORX, 7, 5, NULL, S_KORAX_CHASE2, 0, 0}, // S_KORAX_PAIN2 + {SPR_KORX, 32772, 2, A_FaceTarget, S_KORAX_ATTACK2, 0, 0}, // S_KORAX_ATTACK1 + {SPR_KORX, 32772, 5, A_KoraxDecide, S_KORAX_ATTACK2, 0, 0}, // S_KORAX_ATTACK2 + {SPR_KORX, 32772, 4, A_FaceTarget, S_KORAX_MISSILE2, 0, 0}, // S_KORAX_MISSILE1 + {SPR_KORX, 32773, 8, A_KoraxMissile, S_KORAX_MISSILE3, 0, 0}, // S_KORAX_MISSILE2 + {SPR_KORX, 32772, 8, NULL, S_KORAX_CHASE2, 0, 0}, // S_KORAX_MISSILE3 + {SPR_KORX, 32772, 5, A_FaceTarget, S_KORAX_COMMAND2, 0, 0}, // S_KORAX_COMMAND1 + {SPR_KORX, 32790, 10, A_FaceTarget, S_KORAX_COMMAND3, 0, 0}, // S_KORAX_COMMAND2 + {SPR_KORX, 32774, 15, A_KoraxCommand, S_KORAX_COMMAND4, 0, 0}, // S_KORAX_COMMAND3 + {SPR_KORX, 32790, 10, NULL, S_KORAX_COMMAND5, 0, 0}, // S_KORAX_COMMAND4 + {SPR_KORX, 32772, 5, NULL, S_KORAX_CHASE2, 0, 0}, // S_KORAX_COMMAND5 + {SPR_KORX, 8, 5, NULL, S_KORAX_DEATH2, 0, 0}, // S_KORAX_DEATH1 + {SPR_KORX, 9, 5, A_FaceTarget, S_KORAX_DEATH3, 0, 0}, // S_KORAX_DEATH2 + {SPR_KORX, 10, 5, A_Scream, S_KORAX_DEATH4, 0, 0}, // S_KORAX_DEATH3 + {SPR_KORX, 11, 5, NULL, S_KORAX_DEATH5, 0, 0}, // S_KORAX_DEATH4 + {SPR_KORX, 12, 5, NULL, S_KORAX_DEATH6, 0, 0}, // S_KORAX_DEATH5 + {SPR_KORX, 13, 5, NULL, S_KORAX_DEATH7, 0, 0}, // S_KORAX_DEATH6 + {SPR_KORX, 14, 5, NULL, S_KORAX_DEATH8, 0, 0}, // S_KORAX_DEATH7 + {SPR_KORX, 15, 5, NULL, S_KORAX_DEATH9, 0, 0}, // S_KORAX_DEATH8 + {SPR_KORX, 16, 10, NULL, S_KORAX_DEATH0, 0, 0}, // S_KORAX_DEATH9 + {SPR_KORX, 17, 5, A_KoraxBonePop, S_KORAX_DEATHA, 0, 0}, // S_KORAX_DEATH0 + {SPR_KORX, 18, 5, A_NoBlocking, S_KORAX_DEATHB, 0, 0}, // S_KORAX_DEATHA + {SPR_KORX, 19, 5, NULL, S_KORAX_DEATHC, 0, 0}, // S_KORAX_DEATHB + {SPR_KORX, 20, 5, NULL, S_KORAX_DEATHD, 0, 0}, // S_KORAX_DEATHC + {SPR_KORX, 21, -1, NULL, S_NULL, 0, 0}, // S_KORAX_DEATHD + {SPR_SPIR, 0, 5, A_KSpiritRoam, S_KSPIRIT_ROAM2, 0, 0}, // S_KSPIRIT_ROAM1 + {SPR_SPIR, 1, 5, A_KSpiritRoam, S_KSPIRIT_ROAM1, 0, 0}, // S_KSPIRIT_ROAM2 + {SPR_SPIR, 3, 5, NULL, S_KSPIRIT_DEATH2, 0, 0}, // S_KSPIRIT_DEATH1 + {SPR_SPIR, 4, 5, NULL, S_KSPIRIT_DEATH3, 0, 0}, // S_KSPIRIT_DEATH2 + {SPR_SPIR, 5, 5, NULL, S_KSPIRIT_DEATH4, 0, 0}, // S_KSPIRIT_DEATH3 + {SPR_SPIR, 6, 5, NULL, S_KSPIRIT_DEATH5, 0, 0}, // S_KSPIRIT_DEATH4 + {SPR_SPIR, 7, 5, NULL, S_KSPIRIT_DEATH6, 0, 0}, // S_KSPIRIT_DEATH5 + {SPR_SPIR, 8, 5, NULL, S_NULL, 0, 0}, // S_KSPIRIT_DEATH6 + {SPR_MLFX, 32776, 2, NULL, S_KBOLT2, 0, 0}, // S_KBOLT1 + {SPR_MLFX, 32777, 2, A_KBoltRaise, S_KBOLT3, 0, 0}, // S_KBOLT2 + {SPR_MLFX, 32776, 2, A_KBolt, S_KBOLT4, 0, 0}, // S_KBOLT3 + {SPR_MLFX, 32777, 2, A_KBolt, S_KBOLT5, 0, 0}, // S_KBOLT4 + {SPR_MLFX, 32778, 2, A_KBolt, S_KBOLT6, 0, 0}, // S_KBOLT5 + {SPR_MLFX, 32779, 2, A_KBolt, S_KBOLT7, 0, 0}, // S_KBOLT6 + {SPR_MLFX, 32780, 2, A_KBolt, S_KBOLT3, 0, 0}, // S_KBOLT7 + {SPR_MAN1, 0, 2, NULL, S_SPAWNBATS2, 0, 0}, // S_SPAWNBATS1 + {SPR_MAN1, 0, 2, A_BatSpawnInit, S_SPAWNBATS3, 0, 0}, // S_SPAWNBATS2 + {SPR_MAN1, 0, 2, A_BatSpawn, S_SPAWNBATS3, 0, 0}, // S_SPAWNBATS3 + {SPR_MAN1, 0, -1, NULL, S_NULL, 0, 0}, // S_SPAWNBATS_OFF + {SPR_ABAT, 0, 2, A_BatMove, S_BAT2, 0, 0}, // S_BAT1 + {SPR_ABAT, 1, 2, A_BatMove, S_BAT3, 0, 0}, // S_BAT2 + {SPR_ABAT, 2, 2, A_BatMove, S_BAT1, 0, 0}, // S_BAT3 + {SPR_ABAT, 0, 2, NULL, S_NULL, 0, 0} // S_BAT_DEATH +}; + + +mobjinfo_t mobjinfo[NUMMOBJTYPES] = { + + { // MT_MAPSPOT + 9001, // doomednum + S_MAPSPOT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MAPSPOTGRAVITY + 9013, // doomednum + S_MAPSPOT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + MF2_DONTDRAW // flags2 + }, + + { // MT_FIREBALL1 + -1, // doomednum + S_FIREBALL1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIREBALL1_X1, // deathstate + S_NULL, // xdeathstate + SFX_FIREBALL, // deathsound + 2 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_ARROW + -1, // doomednum + S_ARROW_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ARROW_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 6 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DART + -1, // doomednum + S_DART_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DART_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 6 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 2, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_POISONDART + -1, // doomednum + S_POISONDART_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_POISONDART_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 6 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 2, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_RIPPERBALL + -1, // doomednum + S_RIPPERBALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_RIPPERBALL_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 6 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 2, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_RIP // flags2 + }, + + { // MT_PROJECTILE_BLADE + -1, // doomednum + S_PRJ_BLADE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_PRJ_BLADE_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 6 * FRACUNIT, // speed + 6 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 3, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ICESHARD + -1, // doomednum + S_ICESHARD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SHARDFXE1_1, // deathstate + S_NULL, // xdeathstate + SFX_MAGE_SHARDS_EXPLODE, // deathsound + 25 * FRACUNIT, // speed + 13 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_ICEDAMAGE // flags2 + }, + + { // MT_FLAME_SMALL_TEMP + 10500, // doomednum + S_FLAME_TSMALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FLAME_LARGE_TEMP + 10502, // doomednum + S_FLAME_TLARGE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FLAME_SMALL + 10501, // doomednum + S_FLAME_SMALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + MF2_NOTELEPORT | MF2_DONTDRAW // flags2 + }, + + { // MT_FLAME_LARGE + 10503, // doomednum + S_FLAME_LARGE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + MF2_NOTELEPORT | MF2_DONTDRAW // flags2 + }, + + { // MT_HEALINGBOTTLE + 81, // doomednum + S_ITEM_PTN1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_HEALTHFLASK + 82, // doomednum + S_ARTI_PTN2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIFLY + 83, // doomednum + S_ARTI_SOAR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIINVULNERABILITY + 84, // doomednum + S_ARTI_INVU1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_SUMMONMAULATOR + 86, // doomednum + S_ARTI_SUMMON, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_SUMMON_FX + -1, // doomednum + S_SUMMON_FX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SUMMON_FX2_1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 20 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_DROPOFF | MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_THRUSTFLOOR_UP + 10091, // doomednum + S_THRUSTINIT2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 128 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_THRUSTFLOOR_DOWN + 10090, // doomednum + S_THRUSTINIT1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 128 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP | MF2_DONTDRAW // flags2 + }, + + { // MT_TELEPORTOTHER + 10040, // doomednum + S_ARTI_TELOTHER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_TELOTHER_FX1 + -1, // doomednum + S_TELO_FX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_TELO_FX9, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 20 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 10001, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_TELOTHER_FX2 + -1, // doomednum + S_TELO_FX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_TELO_FX9, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 16 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 10001, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_TELOTHER_FX3 + -1, // doomednum + S_TELO_FX3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_TELO_FX9, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 16 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 10001, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_TELOTHER_FX4 + -1, // doomednum + S_TELO_FX4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_TELO_FX9, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 16 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 10001, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_TELOTHER_FX5 + -1, // doomednum + S_TELO_FX5_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_TELO_FX9, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 16 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 10001, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DIRT1 + -1, // doomednum + S_DIRT1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DIRT1_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DIRT2 + -1, // doomednum + S_DIRT2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DIRT2_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DIRT3 + -1, // doomednum + S_DIRT3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DIRT3_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DIRT4 + -1, // doomednum + S_DIRT4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DIRT4_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_DIRT5 + -1, // doomednum + S_DIRT5_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DIRT5_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_DIRT6 + -1, // doomednum + S_DIRT6_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DIRT6_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_DIRTCLUMP + -1, // doomednum + S_DIRTCLUMP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ROCK1 + -1, // doomednum + S_ROCK1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ROCK1_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ROCK2 + -1, // doomednum + S_ROCK2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ROCK2_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ROCK3 + -1, // doomednum + S_ROCK3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ROCK3_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FOGSPAWNER + 10000, // doomednum + S_SPAWNFOG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + MF2_DONTDRAW | MF2_FLOATBOB // flags2 + }, + + { // MT_FOGPATCHS + 10001, // doomednum + S_FOGPATCHS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FOGPATCHS0, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_FLOAT | MF_NOGRAVITY | MF_SHADOW | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FOGPATCHM + 10002, // doomednum + S_FOGPATCHM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FOGPATCHM0, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_FLOAT | MF_NOGRAVITY | MF_SHADOW | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FOGPATCHL + 10003, // doomednum + S_FOGPATCHL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FOGPATCHL0, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_FLOAT | MF_NOGRAVITY | MF_SHADOW | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_QUAKE_FOCUS + -1, // doomednum + S_QUAKE_ACTIVE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + MF2_DONTDRAW // flags2 + }, + + { // MT_SGSHARD1 + -1, // doomednum + S_SGSHARD1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD1_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD2 + -1, // doomednum + S_SGSHARD2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD2_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD3 + -1, // doomednum + S_SGSHARD3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD3_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD4 + -1, // doomednum + S_SGSHARD4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD4_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD5 + -1, // doomednum + S_SGSHARD5_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD5_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD6 + -1, // doomednum + S_SGSHARD6_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD6_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD7 + -1, // doomednum + S_SGSHARD7_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD7_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD8 + -1, // doomednum + S_SGSHARD8_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD8_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD9 + -1, // doomednum + S_SGSHARD9_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD9_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SGSHARD0 + -1, // doomednum + S_SGSHARD0_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SGSHARD0_D, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_ARTIEGG + 30, // doomednum + S_ARTI_EGGC1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_EGGFX + -1, // doomednum + S_EGGFX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_EGGFXI1_1, // deathstate + S_NULL, // xdeathstate + 0, // deathsound + 18 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ARTISUPERHEAL + 32, // doomednum + S_ARTI_SPHL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ZWINGEDSTATUENOSKULL + 9011, // doomednum + S_ZWINGEDSTATUENOSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZGEMPEDESTAL + 9012, // doomednum + S_ZGEMPEDESTAL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 40 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZSKULL + 9002, // doomednum + S_ARTIPUZZSKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEMBIG + 9003, // doomednum + S_ARTIPUZZGEMBIG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEMRED + 9004, // doomednum + S_ARTIPUZZGEMRED, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEMGREEN1 + 9005, // doomednum + S_ARTIPUZZGEMGREEN1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEMGREEN2 + 9009, // doomednum + S_ARTIPUZZGEMGREEN2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEMBLUE1 + 9006, // doomednum + S_ARTIPUZZGEMBLUE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEMBLUE2 + 9010, // doomednum + S_ARTIPUZZGEMBLUE2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZBOOK1 + 9007, // doomednum + S_ARTIPUZZBOOK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZBOOK2 + 9008, // doomednum + S_ARTIPUZZBOOK2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZSKULL2 + 9014, // doomednum + S_ARTIPUZZSKULL2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZFWEAPON + 9015, // doomednum + S_ARTIPUZZFWEAPON, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZCWEAPON + 9016, // doomednum + S_ARTIPUZZCWEAPON, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZMWEAPON + 9017, // doomednum + S_ARTIPUZZMWEAPON, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEAR + 9018, // doomednum + S_ARTIPUZZGEAR_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEAR2 + 9019, // doomednum + S_ARTIPUZZGEAR2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEAR3 + 9020, // doomednum + S_ARTIPUZZGEAR3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTIPUZZGEAR4 + 9021, // doomednum + S_ARTIPUZZGEAR4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARTITORCH + 33, // doomednum + S_ARTI_TRCH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_FIREBOMB + -1, // doomednum + S_FIREBOMB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_FLECHETTE_EXPLODE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOGRAVITY | MF_ALTSHADOW, // flags + MF2_FIREDAMAGE // flags2 + }, + + { // MT_ARTITELEPORT + 36, // doomednum + S_ARTI_ATLP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_ARTIPOISONBAG + 8000, // doomednum + S_ARTI_PSBG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_POISONBAG + -1, // doomednum + S_POISONBAG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOGRAVITY | MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_POISONCLOUD + -1, // doomednum + S_POISONCLOUD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_POISONSHROOM_DEATH, // deathsound + 0, // speed + 1, // radius + 1, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOGRAVITY | MF_NOBLOCKMAP | MF_SHADOW | MF_NOCLIP | MF_DROPOFF, // flags + MF2_NODMGTHRUST // flags2 + }, + + { // MT_THROWINGBOMB + -1, // doomednum + S_THROWINGBOMB1, // spawnstate + 48, // spawnhealth + S_NULL, // seestate + SFX_FLECHETTE_BOUNCE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_THROWINGBOMB_X1, // deathstate + S_NULL, // xdeathstate + SFX_FLECHETTE_EXPLODE, // deathsound + 12 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_FLOORBOUNCE | MF2_FIREDAMAGE // flags2 + }, + + { // MT_SPEEDBOOTS + 8002, // doomednum + S_ARTI_BOOTS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_BOOSTMANA + 8003, // doomednum + S_ARTI_MANA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_BOOSTARMOR + 8041, // doomednum + S_ARTI_ARMOR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_BLASTRADIUS + 10110, // doomednum + S_ARTI_BLAST1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_HEALRADIUS + 10120, // doomednum + S_ARTI_HEALRAD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_SPLASH + -1, // doomednum + S_SPLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SPLASHX, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_SPLASHBASE + -1, // doomednum + S_SPLASHBASE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_LAVASPLASH + -1, // doomednum + S_LAVASPLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_LAVASMOKE + -1, // doomednum + S_LAVASMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_SLUDGECHUNK + -1, // doomednum + S_SLUDGECHUNK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SLUDGECHUNKX, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_SLUDGESPLASH + -1, // doomednum + S_SLUDGESPLASH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_MISC0 + 5, // doomednum + S_ZWINGEDSTATUE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC1 + 6, // doomednum + S_ZROCK1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC2 + 7, // doomednum + S_ZROCK2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC3 + 9, // doomednum + S_ZROCK3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC4 + 15, // doomednum + S_ZROCK4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC5 + 17, // doomednum + S_ZCHANDELIER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 60 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC6 + 8063, // doomednum + S_ZCHANDELIER_U, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 60 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC7 + 24, // doomednum + S_ZTREEDEAD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 96 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC8 + 25, // doomednum + S_ZTREE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 128 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_TREEDESTRUCTIBLE + 8062, // doomednum + S_ZTREEDESTRUCTIBLE1, // spawnstate + 70, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZTREEDES_D1, // deathstate + S_NULL, // xdeathstate + SFX_TREE_BREAK, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 180 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_MISC9 + 26, // doomednum + S_ZTREESWAMP182_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 150 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC10 + 27, // doomednum + S_ZTREESWAMP172_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 120 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC11 + 28, // doomednum + S_ZSTUMPBURNED1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC12 + 29, // doomednum + S_ZSTUMPBARE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC13 + 37, // doomednum + S_ZSTUMPSWAMP1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC14 + 38, // doomednum + S_ZSTUMPSWAMP2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC15 + 39, // doomednum + S_ZSHROOMLARGE1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC16 + 40, // doomednum + S_ZSHROOMLARGE2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC17 + 41, // doomednum + S_ZSHROOMLARGE3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC18 + 42, // doomednum + S_ZSHROOMSMALL1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC19 + 44, // doomednum + S_ZSHROOMSMALL2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC20 + 45, // doomednum + S_ZSHROOMSMALL3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC21 + 46, // doomednum + S_ZSHROOMSMALL4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC22 + 47, // doomednum + S_ZSHROOMSMALL5_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC23 + 48, // doomednum + S_ZSTALAGMITEPILLAR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 138 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC24 + 49, // doomednum + S_ZSTALAGMITELARGE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 48 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC25 + 50, // doomednum + S_ZSTALAGMITEMEDIUM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 6 * FRACUNIT, // radius + 40 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC26 + 51, // doomednum + S_ZSTALAGMITESMALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 36 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC27 + 52, // doomednum + S_ZSTALACTITELARGE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 66 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC28 + 56, // doomednum + S_ZSTALACTITEMEDIUM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 6 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC29 + 57, // doomednum + S_ZSTALACTITESMALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 40 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC30 + 58, // doomednum + S_ZMOSSCEILING1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC31 + 59, // doomednum + S_ZMOSSCEILING2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 24 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC32 + 60, // doomednum + S_ZSWAMPVINE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 52 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC33 + 61, // doomednum + S_ZCORPSEKABOB1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 92 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC34 + 62, // doomednum + S_ZCORPSESLEEPING1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC35 + 63, // doomednum + S_ZTOMBSTONERIP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 46 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC36 + 64, // doomednum + S_ZTOMBSTONESHANE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 46 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC37 + 65, // doomednum + S_ZTOMBSTONEBIGCROSS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 46 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC38 + 66, // doomednum + S_ZTOMBSTONEBRIANR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 52 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC39 + 67, // doomednum + S_ZTOMBSTONECROSSCIRCLE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 52 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC40 + 68, // doomednum + S_ZTOMBSTONESMALLCROSS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 46 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC41 + 69, // doomednum + S_ZTOMBSTONEBRIANP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 46 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC42 + 71, // doomednum + S_CORPSEHANGING_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 6 * FRACUNIT, // radius + 75 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC43 + 72, // doomednum + S_ZSTATUEGARGOYLEGREENTALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC44 + 73, // doomednum + S_ZSTATUEGARGOYLEBLUETALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC45 + 74, // doomednum + S_ZSTATUEGARGOYLEGREENSHORT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC46 + 76, // doomednum + S_ZSTATUEGARGOYLEBLUESHORT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC47 + 8044, // doomednum + S_ZSTATUEGARGOYLESTRIPETALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC48 + 8045, // doomednum + S_ZSTATUEGARGOYLEDARKREDTALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC49 + 8046, // doomednum + S_ZSTATUEGARGOYLEREDTALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC50 + 8047, // doomednum + S_ZSTATUEGARGOYLETANTALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC51 + 8048, // doomednum + S_ZSTATUEGARGOYLERUSTTALL_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 108 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC52 + 8049, // doomednum + S_ZSTATUEGARGOYLEDARKREDSHORT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC53 + 8050, // doomednum + S_ZSTATUEGARGOYLEREDSHORT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC54 + 8051, // doomednum + S_ZSTATUEGARGOYLETANSHORT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC55 + 8052, // doomednum + S_ZSTATUEGARGOYLERUSTSHORT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 14 * FRACUNIT, // radius + 62 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC56 + 77, // doomednum + S_ZBANNERTATTERED_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 120 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC57 + 78, // doomednum + S_ZTREELARGE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZTREELARGE1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 180 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC58 + 79, // doomednum + S_ZTREELARGE2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZTREELARGE2, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 180 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC59 + 80, // doomednum + S_ZTREEGNARLED1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 22 * FRACUNIT, // radius + 100 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC60 + 87, // doomednum + S_ZTREEGNARLED2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 22 * FRACUNIT, // radius + 100 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC61 + 88, // doomednum + S_ZLOG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 25 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC62 + 89, // doomednum + S_ZSTALACTITEICELARGE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 66 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC63 + 90, // doomednum + S_ZSTALACTITEICEMEDIUM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC64 + 91, // doomednum + S_ZSTALACTITEICESMALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC65 + 92, // doomednum + S_ZSTALACTITEICETINY, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC66 + 93, // doomednum + S_ZSTALAGMITEICELARGE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 66 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC67 + 94, // doomednum + S_ZSTALAGMITEICEMEDIUM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC68 + 95, // doomednum + S_ZSTALAGMITEICESMALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC69 + 96, // doomednum + S_ZSTALAGMITEICETINY, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC70 + 97, // doomednum + S_ZROCKBROWN1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 17 * FRACUNIT, // radius + 72 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC71 + 98, // doomednum + S_ZROCKBROWN2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 50 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC72 + 99, // doomednum + S_ZROCKBLACK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 40 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_MISC73 + 100, // doomednum + S_ZRUBBLE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC74 + 101, // doomednum + S_ZRUBBLE2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC75 + 102, // doomednum + S_ZRUBBLE3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_MISC76 + 103, // doomednum + S_ZVASEPILLAR, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 54 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_POTTERY1 + 104, // doomednum + S_ZPOTTERY1, // spawnstate + 15, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZPOTTERY_EXPLODE, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_DROPOFF, // flags + MF2_SLIDE | MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ // flags2 + }, + + { // MT_POTTERY2 + 105, // doomednum + S_ZPOTTERY2, // spawnstate + 15, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZPOTTERY_EXPLODE, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 25 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_DROPOFF, // flags + MF2_SLIDE | MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ // flags2 + }, + + { // MT_POTTERY3 + 106, // doomednum + S_ZPOTTERY3, // spawnstate + 15, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZPOTTERY_EXPLODE, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 25 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_DROPOFF, // flags + MF2_SLIDE | MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ // flags2 + }, + + { // MT_POTTERYBIT1 + -1, // doomednum + S_POTTERYBIT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_POTTERYBIT_EX0, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_MISC77 + 108, // doomednum + S_ZCORPSELYNCHED1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 11 * FRACUNIT, // radius + 95 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ZLYNCHED_NOHEART + 109, // doomednum + S_ZCORPSELYNCHED2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 100 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC78 + 110, // doomednum + S_ZCORPSESITTING, // spawnstate + 30, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZCORPSESITTING_X, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 35 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_CORPSEBIT + -1, // doomednum + S_CORPSEBIT_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + MF2_TELESTOMP // flags2 + }, + + { // MT_CORPSEBLOODDRIP + -1, // doomednum + S_CORPSEBLOODDRIP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CORPSEBLOODDRIP_X1, // deathstate + S_NULL, // xdeathstate + SFX_DRIP, // deathsound + 0, // speed + FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_MISSILE, // flags + MF2_LOGRAV // flags2 + }, + + { // MT_BLOODPOOL + 111, // doomednum + S_BLOODPOOL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_MISC79 + 119, // doomednum + S_ZCANDLE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC80 + 113, // doomednum + S_ZLEAFSPAWNER, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + MF2_DONTDRAW // flags2 + }, + + { // MT_LEAF1 + -1, // doomednum + S_LEAF1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_LEAF_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_LEAF2 + -1, // doomednum + S_LEAF2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_LEAF_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_ZTWINEDTORCH + 116, // doomednum + S_ZTWINEDTORCH_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZTWINEDTORCH_UNLIT + 117, // doomednum + S_ZTWINEDTORCH_UNLIT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 10 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_BRIDGE + 118, // doomednum + S_BRIDGE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 32 * FRACUNIT, // radius + 2 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_NOGRAVITY, // flags + MF2_DONTDRAW // flags2 + }, + + { // MT_BRIDGEBALL + -1, // doomednum + S_BBALL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ZWALLTORCH + 54, // doomednum + S_ZWALLTORCH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ZWALLTORCH_UNLIT + 55, // doomednum + S_ZWALLTORCH_U, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ZBARREL + 8100, // doomednum + S_ZBARREL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZSHRUB1 + 8101, // doomednum + S_ZSHRUB1, // spawnstate + 20, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_ZSHRUB1_X1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZSHRUB1_DIE, // deathstate + S_NULL, // xdeathstate + SFX_TREE_EXPLODE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 24 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_ZSHRUB2 + 8102, // doomednum + S_ZSHRUB2, // spawnstate + 10, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_ZSHRUB2_X1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZSHRUB2_DIE, // deathstate + S_NULL, // xdeathstate + SFX_TREE_EXPLODE, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 40 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_ZBUCKET + 8103, // doomednum + S_ZBUCKET1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 72 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ZPOISONSHROOM + 8104, // doomednum + S_ZPOISONSHROOM1, // spawnstate + 30, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_ZPOISONSHROOM_P1, // painstate + 255, // painchance + SFX_POISONSHROOM_PAIN, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZPOISONSHROOM_X1, // deathstate + S_NULL, // xdeathstate + SFX_POISONSHROOM_DEATH, // deathsound + 0, // speed + 6 * FRACUNIT, // radius + 20 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SHOOTABLE | MF_SOLID | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_ZFIREBULL + 8042, // doomednum + S_ZFIREBULL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 80 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZFIREBULL_UNLIT + 8043, // doomednum + S_ZFIREBULL_U, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 80 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_FIRETHING + 8060, // doomednum + S_ZFIRETHING1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_BRASSTORCH + 8061, // doomednum + S_ZBRASSTORCH1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 6 * FRACUNIT, // radius + 35 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZSUITOFARMOR + 8064, // doomednum + S_ZSUITOFARMOR, // spawnstate + 60, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZSUITOFARMOR_X1, // deathstate + S_NULL, // xdeathstate + SFX_SUITOFARMOR_BREAK, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 72 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_ZARMORCHUNK + -1, // doomednum + S_ZARMORCHUNK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + 0, // flags + 0 // flags2 + }, + + { // MT_ZBELL + 8065, // doomednum + S_ZBELL, // spawnstate + 5, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZBELL_X1, // deathstate + S_NULL, // xdeathstate + SFX_BELLRING, // deathsound + 0, // speed + 56 * FRACUNIT, // radius + 120 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZBLUE_CANDLE + 8066, // doomednum + S_ZBLUE_CANDLE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_ZIRON_MAIDEN + 8067, // doomednum + S_ZIRON_MAIDEN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 60 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZXMAS_TREE + 8068, // doomednum + S_ZXMAS_TREE, // spawnstate + 20, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_ZXMAS_TREE_X1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ZXMAS_TREE_DIE, // deathstate + S_NULL, // xdeathstate + SFX_TREE_EXPLODE, // deathsound + 0, // speed + 11 * FRACUNIT, // radius + 130 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags + 0 // flags2 + }, + + { // MT_ZCAULDRON + 8069, // doomednum + S_ZCAULDRON1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 26 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZCAULDRON_UNLIT + 8070, // doomednum + S_ZCAULDRON_U, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 12 * FRACUNIT, // radius + 26 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID, // flags + 0 // flags2 + }, + + { // MT_ZCHAINBIT32 + 8071, // doomednum + S_ZCHAINBIT32, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZCHAINBIT64 + 8072, // doomednum + S_ZCHAINBIT64, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZCHAINEND_HEART + 8073, // doomednum + S_ZCHAINEND_HEART, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZCHAINEND_HOOK1 + 8074, // doomednum + S_ZCHAINEND_HOOK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZCHAINEND_HOOK2 + 8075, // doomednum + S_ZCHAINEND_HOOK2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZCHAINEND_SPIKE + 8076, // doomednum + S_ZCHAINEND_SPIKE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_ZCHAINEND_SKULL + 8077, // doomednum + S_ZCHAINEND_SKULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 32 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT1 + 8500, // doomednum + S_TABLE_SHIT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT2 + 8501, // doomednum + S_TABLE_SHIT2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT3 + 8502, // doomednum + S_TABLE_SHIT3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT4 + 8503, // doomednum + S_TABLE_SHIT4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT5 + 8504, // doomednum + S_TABLE_SHIT5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT6 + 8505, // doomednum + S_TABLE_SHIT6, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT7 + 8506, // doomednum + S_TABLE_SHIT7, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT8 + 8507, // doomednum + S_TABLE_SHIT8, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT9 + 8508, // doomednum + S_TABLE_SHIT9, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TABLE_SHIT10 + 8509, // doomednum + S_TABLE_SHIT10, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_TFOG + -1, // doomednum + S_TFOG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MISC81 + 140, // doomednum + S_TELESMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_TELEPORTMAN + 14, // doomednum + S_NULL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_PUNCHPUFF + -1, // doomednum + S_PUNCHPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_FIGHTER_PUNCH_HITTHING, // seesound + 8, // reactiontime + SFX_FIGHTER_PUNCH_HITWALL, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_FW_AXE + 8010, // doomednum + S_AXE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_AXEPUFF + -1, // doomednum + S_HAMMERPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_FIGHTER_AXE_HITTHING, // seesound + 8, // reactiontime + SFX_FIGHTER_HAMMER_HITWALL, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_AXEPUFF_GLOW + -1, // doomednum + S_AXEPUFF_GLOW1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_FIGHTER_AXE_HITTHING, // seesound + 8, // reactiontime + SFX_FIGHTER_HAMMER_HITWALL, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_AXEBLOOD + -1, // doomednum + S_AXEBLOOD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_AXEBLOOD6, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 + }, + + { // MT_FW_HAMMER + 123, // doomednum + S_HAMM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_HAMMER_MISSILE + -1, // doomednum + S_HAMMER_MISSILE_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HAMMER_MISSILE_X1, // deathstate + S_NULL, // xdeathstate + SFX_FIGHTER_HAMMER_EXPLODE, // deathsound + 25 * FRACUNIT, // speed + 14 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 10, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FIREDAMAGE // flags2 + }, + + { // MT_HAMMERPUFF + -1, // doomednum + S_HAMMERPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_FIGHTER_HAMMER_HITTHING, // seesound + 8, // reactiontime + SFX_FIGHTER_HAMMER_HITWALL, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_FSWORD_MISSILE + -1, // doomednum + S_FSWORD_MISSILE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FSWORD_MISSILE_X1, // deathstate + S_NULL, // xdeathstate + SFX_FIGHTER_SWORD_EXPLODE, // deathsound + 30 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 8, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_FSWORD_FLAME + -1, // doomednum + S_FSWORD_FLAME1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_CW_SERPSTAFF + 10, // doomednum + S_CSTAFF, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_CSTAFF_MISSILE + -1, // doomednum + S_CSTAFF_MISSILE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CSTAFF_MISSILE_X1, // deathstate + S_NULL, // xdeathstate + SFX_CLERIC_CSTAFF_EXPLODE, // deathsound + 22 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 5, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_CSTAFFPUFF + -1, // doomednum + S_CSTAFFPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_CLERIC_CSTAFF_HITTHING, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_CW_FLAME + 8009, // doomednum + S_CFLAME1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_CFLAMEFLOOR + -1, // doomednum + S_CFLAMEFLOOR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_FLAMEPUFF + -1, // doomednum + S_FLAMEPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_CLERIC_FLAME_EXPLODE, // seesound + 8, // reactiontime + SFX_CLERIC_FLAME_EXPLODE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_FLAMEPUFF2 + -1, // doomednum + S_FLAMEPUFF2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_CLERIC_FLAME_EXPLODE, // seesound + 8, // reactiontime + SFX_CLERIC_FLAME_EXPLODE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_CIRCLEFLAME + -1, // doomednum + S_CIRCLE_FLAME1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CIRCLE_FLAME_X1, // deathstate + S_NULL, // xdeathstate + SFX_CLERIC_FLAME_CIRCLE, // deathsound + 0, // speed + 6 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 2, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_CFLAME_MISSILE + -1, // doomednum + S_CFLAME_MISSILE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CFLAME_MISSILE_X, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 200 * FRACUNIT, // speed + 14 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 8, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_DONTDRAW | MF2_FIREDAMAGE // flags2 + }, + + { // MT_HOLY_FX + -1, // doomednum + S_HOLY_FX1, // spawnstate + 105, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HOLY_FX_X1, // deathstate + S_NULL, // xdeathstate + SFX_SPIRIT_DIE, // deathsound + 12 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 3, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_SEEKERMISSILE | MF2_RIP | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_HOLY_TAIL + -1, // doomednum + S_HOLY_TAIL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_NOCLIP | MF_ALTSHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_HOLY_PUFF + -1, // doomednum + S_HOLY_PUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_HOLY_MISSILE + -1, // doomednum + S_HOLY_MISSILE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_HOLY_MISSILE_X, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 30 * FRACUNIT, // speed + 15 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_HOLY_MISSILE_PUFF + -1, // doomednum + S_HOLY_MISSILE_P1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_MWANDPUFF + -1, // doomednum + S_MWANDPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH | MF2_NODMGTHRUST // flags2 + }, + + { // MT_MWANDSMOKE + -1, // doomednum + S_MWANDSMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH | MF2_NODMGTHRUST // flags2 + }, + + { // MT_MWAND_MISSILE + -1, // doomednum + S_MWAND_MISSILE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MWANDPUFF1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 184 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 2, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_RIP | MF2_IMPACT | MF2_PCROSS | MF2_NODMGTHRUST | MF2_CANNOTPUSH // flags2 + }, + + { // MT_MW_LIGHTNING + 8040, // doomednum + S_MW_LIGHTNING1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_LIGHTNING_CEILING + -1, // doomednum + S_LIGHTNING_CEILING1, // spawnstate + 144, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_LIGHTNING_C_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 25 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 40 * FRACUNIT, // height + 100, // mass + 8, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_LIGHTNING_FLOOR + -1, // doomednum + S_LIGHTNING_FLOOR1, // spawnstate + 144, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_LIGHTNING_F_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 25 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 40 * FRACUNIT, // height + 100, // mass + 8, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_LIGHTNING_ZAP + -1, // doomednum + S_LIGHTNING_ZAP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_LIGHTNING_ZAP_X8, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 35 * FRACUNIT, // height + 100, // mass + 2, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags + 0 // flags2 + }, + + { // MT_MSTAFF_FX + -1, // doomednum + S_MSTAFF_FX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MSTAFF_FX_X1, // deathstate + S_NULL, // xdeathstate + SFX_MAGE_STAFF_EXPLODE, // deathsound + 20 * FRACUNIT, // speed + 16 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 6, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE | MF2_RIP | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_MSTAFF_FX2 + -1, // doomednum + S_MSTAFF_FX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MSTAFF_FX2_X1, // deathstate + S_NULL, // xdeathstate + SFX_MAGE_STAFF_EXPLODE, // deathsound + 17 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE | MF2_IMPACT | MF2_PCROSS | MF2_SEEKERMISSILE // flags2 + }, + + { // MT_FW_SWORD1 + 12, // doomednum + S_FSWORD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_FW_SWORD2 + 13, // doomednum + S_FSWORD2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_FW_SWORD3 + 16, // doomednum + S_FSWORD3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_CW_HOLY1 + 18, // doomednum + S_CHOLY1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_CW_HOLY2 + 19, // doomednum + S_CHOLY2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_CW_HOLY3 + 20, // doomednum + S_CHOLY3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MW_STAFF1 + 21, // doomednum + S_MSTAFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MW_STAFF2 + 22, // doomednum + S_MSTAFF2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MW_STAFF3 + 23, // doomednum + S_MSTAFF3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_SNOUTPUFF + -1, // doomednum + S_PUNCHPUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_MW_CONE + 53, // doomednum + S_COS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_SHARDFX1 + -1, // doomednum + S_SHARDFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SHARDFXE1_1, // deathstate + S_NULL, // xdeathstate + SFX_MAGE_SHARDS_EXPLODE, // deathsound + 25 * FRACUNIT, // speed + 13 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_ICEDAMAGE // flags2 + }, + + { // MT_BLOOD + -1, // doomednum + S_BLOOD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + 0 // flags2 + }, + + { // MT_BLOODSPLATTER + -1, // doomednum + S_BLOODSPLATTER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BLOODSPLATTERX, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 + }, + + { // MT_GIBS + -1, // doomednum + S_GIBS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_PLAYER_FIGHTER + -1, // doomednum + S_FPLAY, // spawnstate + 100, // spawnhealth + S_FPLAY_RUN1, // seestate + SFX_NONE, // seesound + 0, // reactiontime + SFX_NONE, // attacksound + S_FPLAY_PAIN, // painstate + 255, // painchance + SFX_PLAYER_FIGHTER_PAIN, // painsound + S_NULL, // meleestate + S_FPLAY_ATK1, // missilestate + S_NULL, // crashstate + S_FPLAY_DIE1, // deathstate + S_FPLAY_XDIE1, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags + MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL // flags2 + }, + + { // MT_BLOODYSKULL + -1, // doomednum + S_BLOODYSKULL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 4 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_CANNOTPUSH // flags2 + }, + + { // MT_PLAYER_SPEED + -1, // doomednum + S_PLAYER_SPEED1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_ALTSHADOW, // flags + 0 // flags2 + }, + + { // MT_ICECHUNK + -1, // doomednum + S_ICECHUNK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF, // flags + MF2_LOGRAV | MF2_CANNOTPUSH | MF2_FLOORCLIP // flags2 + }, + + { // MT_PLAYER_CLERIC + -1, // doomednum + S_CPLAY, // spawnstate + 100, // spawnhealth + S_CPLAY_RUN1, // seestate + SFX_NONE, // seesound + 0, // reactiontime + SFX_NONE, // attacksound + S_CPLAY_PAIN, // painstate + 255, // painchance + SFX_PLAYER_CLERIC_PAIN, // painsound + S_NULL, // meleestate + S_CPLAY_ATK1, // missilestate + S_NULL, // crashstate + S_CPLAY_DIE1, // deathstate + S_CPLAY_XDIE1, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags + MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL // flags2 + }, + + { // MT_PLAYER_MAGE + -1, // doomednum + S_MPLAY, // spawnstate + 100, // spawnhealth + S_MPLAY_RUN1, // seestate + SFX_NONE, // seesound + 0, // reactiontime + SFX_NONE, // attacksound + S_MPLAY_PAIN, // painstate + 255, // painchance + SFX_PLAYER_MAGE_PAIN, // painsound + S_NULL, // meleestate + S_MPLAY_ATK1, // missilestate + S_NULL, // crashstate + S_MPLAY_DIE1, // deathstate + S_MPLAY_XDIE1, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags + MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL // flags2 + }, + + { // MT_PIGPLAYER + -1, // doomednum + S_PIGPLAY, // spawnstate + 100, // spawnhealth + S_PIGPLAY_RUN1, // seestate + SFX_NONE, // seesound + 0, // reactiontime + SFX_NONE, // attacksound + S_PIGPLAY_PAIN, // painstate + 255, // painchance + SFX_PIG_PAIN, // painsound + S_NULL, // meleestate + S_PIGPLAY_ATK1, // missilestate + S_NULL, // crashstate + S_PIG_DIE1, // deathstate + S_NULL, // xdeathstate + SFX_PIG_DEATH, // deathsound + 0, // speed + 16 * FRACUNIT, // radius + 24 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_NOTDMATCH, // flags + MF2_WINDTHRUST | MF2_SLIDE | MF2_PASSMOBJ | MF2_FLOORCLIP | MF2_TELESTOMP | MF2_PUSHWALL // flags2 + }, + + { // MT_PIG + -1, // doomednum + S_PIG_LOOK1, // spawnstate + 25, // spawnhealth + S_PIG_WALK1, // seestate + SFX_PIG_ACTIVE1, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_PIG_PAIN, // painstate + 128, // painchance + SFX_PIG_PAIN, // painsound + S_PIG_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_PIG_DIE1, // deathstate + S_NULL, // xdeathstate + SFX_PIG_DEATH, // deathsound + 10, // speed + 12 * FRACUNIT, // radius + 22 * FRACUNIT, // height + 60, // mass + 0, // damage + SFX_PIG_ACTIVE1, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 + }, + + { // MT_CENTAUR + 107, // doomednum + S_CENTAUR_LOOK1, // spawnstate + 200, // spawnhealth + S_CENTAUR_WALK1, // seestate + SFX_CENTAUR_SIGHT, // seesound + 8, // reactiontime + SFX_CENTAUR_ATTACK, // attacksound + S_CENTAUR_PAIN1, // painstate + 135, // painchance + SFX_CENTAUR_PAIN, // painsound + S_CENTAUR_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_CENTAUR_DEATH1, // deathstate + S_CENTAUR_DEATH_X1, // xdeathstate + SFX_CENTAUR_DEATH, // deathsound + 13, // speed + 20 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 120, // mass + 0, // damage + SFX_CENTAUR_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_CENTAURLEADER + 115, // doomednum + S_CENTAUR_LOOK1, // spawnstate + 250, // spawnhealth + S_CENTAUR_WALK1, // seestate + SFX_CENTAUR_SIGHT, // seesound + 8, // reactiontime + SFX_CENTAUR_ATTACK, // attacksound + S_CENTAUR_PAIN1, // painstate + 96, // painchance + SFX_CENTAUR_PAIN, // painsound + S_CENTAUR_ATK1, // meleestate + S_CENTAUR_MISSILE1, // missilestate + S_NULL, // crashstate + S_CENTAUR_DEATH1, // deathstate + S_CENTAUR_DEATH_X1, // xdeathstate + SFX_CENTAUR_DEATH, // deathsound + 10, // speed + 20 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 120, // mass + 0, // damage + SFX_CENTAUR_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_CENTAUR_FX + -1, // doomednum + S_CENTAUR_FX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CENTAUR_FX_X1, // deathstate + S_NULL, // xdeathstate + SFX_CENTAUR_MISSILE_EXPLODE, // deathsound + 20 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 + }, + + { // MT_CENTAUR_SHIELD + -1, // doomednum + S_CENTAUR_SHIELD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CENTAUR_SHIELD_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_CENTAUR_SWORD + -1, // doomednum + S_CENTAUR_SWORD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_CENTAUR_SWORD_X1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DEMON + 31, // doomednum + S_DEMN_LOOK1, // spawnstate + 250, // spawnhealth + S_DEMN_CHASE1, // seestate + SFX_DEMON_SIGHT, // seesound + 8, // reactiontime + SFX_DEMON_ATTACK, // attacksound + S_DEMN_PAIN1, // painstate + 50, // painchance + SFX_DEMON_PAIN, // painsound + S_DEMN_ATK1_1, // meleestate + S_DEMN_ATK2_1, // missilestate + S_NULL, // crashstate + S_DEMN_DEATH1, // deathstate + S_DEMN_XDEATH1, // xdeathstate + SFX_DEMON_DEATH, // deathsound + 13, // speed + 32 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 220, // mass + 0, // damage + SFX_DEMON_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_DEMONCHUNK1 + -1, // doomednum + S_DEMONCHUNK1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMONCHUNK1_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMONCHUNK2 + -1, // doomednum + S_DEMONCHUNK2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMONCHUNK2_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMONCHUNK3 + -1, // doomednum + S_DEMONCHUNK3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMONCHUNK3_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMONCHUNK4 + -1, // doomednum + S_DEMONCHUNK4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMONCHUNK4_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMONCHUNK5 + -1, // doomednum + S_DEMONCHUNK5_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMONCHUNK5_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMONFX1 + -1, // doomednum + S_DEMONFX_MOVE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMONFX_BOOM1, // deathstate + S_NULL, // xdeathstate + SFX_DEMON_MISSILE_EXPLODE, // deathsound + 15 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 5, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FIREDAMAGE // flags2 + }, + + { // MT_DEMON2 + 8080, // doomednum + S_DEMN2_LOOK1, // spawnstate + 250, // spawnhealth + S_DEMN2_CHASE1, // seestate + SFX_DEMON_SIGHT, // seesound + 8, // reactiontime + SFX_DEMON_ATTACK, // attacksound + S_DEMN2_PAIN1, // painstate + 50, // painchance + SFX_DEMON_PAIN, // painsound + S_DEMN2_ATK1_1, // meleestate + S_DEMN2_ATK2_1, // missilestate + S_NULL, // crashstate + S_DEMN2_DEATH1, // deathstate + S_DEMN2_XDEATH1, // xdeathstate + SFX_DEMON_DEATH, // deathsound + 13, // speed + 32 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 220, // mass + 0, // damage + SFX_DEMON_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_DEMON2CHUNK1 + -1, // doomednum + S_DEMON2CHUNK1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMON2CHUNK1_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMON2CHUNK2 + -1, // doomednum + S_DEMON2CHUNK2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMON2CHUNK2_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMON2CHUNK3 + -1, // doomednum + S_DEMON2CHUNK3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMON2CHUNK3_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMON2CHUNK4 + -1, // doomednum + S_DEMON2CHUNK4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMON2CHUNK4_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMON2CHUNK5 + -1, // doomednum + S_DEMON2CHUNK5_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMON2CHUNK5_4, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_DEMON2FX1 + -1, // doomednum + S_DEMON2FX_MOVE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DEMON2FX_BOOM1, // deathstate + S_NULL, // xdeathstate + SFX_DEMON_MISSILE_EXPLODE, // deathsound + 15 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 5, // damage + SFX_NONE, // activesound + MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FIREDAMAGE // flags2 + }, + + { // MT_WRAITHB + 10011, // doomednum + S_WRAITH_LOOK1, // spawnstate + 150, // spawnhealth + S_WRAITH_RAISE1, // seestate + SFX_WRAITH_SIGHT, // seesound + 8, // reactiontime + SFX_WRAITH_ATTACK, // attacksound + S_WRAITH_PAIN1, // painstate + 25, // painchance + SFX_WRAITH_PAIN, // painsound + S_WRAITH_ATK1_1, // meleestate + S_WRAITH_ATK2_1, // missilestate + S_NULL, // crashstate + S_WRAITH_DEATH1_1, // deathstate + S_WRAITH_DEATH2_1, // xdeathstate + SFX_WRAITH_DEATH, // deathsound + 11, // speed + 20 * FRACUNIT, // radius + 68 * FRACUNIT, // height + 75, // mass + 10, // damage + SFX_WRAITH_ACTIVE, // activesound + MF_DROPOFF | MF_NOGRAVITY | MF_FLOAT | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP | MF2_DONTDRAW // flags2 + }, + + { // MT_WRAITH + 34, // doomednum + S_WRAITH_INIT1, // spawnstate + 150, // spawnhealth + S_WRAITH_CHASE1, // seestate + SFX_WRAITH_SIGHT, // seesound + 8, // reactiontime + SFX_WRAITH_ATTACK, // attacksound + S_WRAITH_PAIN1, // painstate + 25, // painchance + SFX_WRAITH_PAIN, // painsound + S_WRAITH_ATK1_1, // meleestate + S_WRAITH_ATK2_1, // missilestate + S_NULL, // crashstate + S_WRAITH_DEATH1_1, // deathstate + S_WRAITH_DEATH2_1, // xdeathstate + SFX_WRAITH_DEATH, // deathsound + 11, // speed + 20 * FRACUNIT, // radius + 55 * FRACUNIT, // height + 75, // mass + 10, // damage + SFX_WRAITH_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF | MF_NOGRAVITY | MF_FLOAT, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 + }, + + { // MT_WRAITHFX1 + -1, // doomednum + S_WRTHFX_MOVE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_WRTHFX_BOOM1, // deathstate + S_NULL, // xdeathstate + SFX_WRAITH_MISSILE_EXPLODE, // deathsound + 14 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 5, // mass + 5, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FLOORCLIP | MF2_FIREDAMAGE // flags2 + }, + + { // MT_WRAITHFX2 + -1, // doomednum + S_WRTHFX_SIZZLE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_WRAITHFX3 + -1, // doomednum + S_WRTHFX_DROP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_WRTHFX_DEAD1, // deathstate + S_NULL, // xdeathstate + SFX_DRIP, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_WRAITHFX4 + -1, // doomednum + S_WRTHFX_ADROP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_WRTHFX_ADEAD1, // deathstate + S_NULL, // xdeathstate + SFX_DRIP, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_WRAITHFX5 + -1, // doomednum + S_WRTHFX_BDROP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_WRTHFX_BDEAD1, // deathstate + S_NULL, // xdeathstate + SFX_DRIP, // deathsound + 0, // speed + 2 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 5, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_MINOTAUR + 9, // doomednum + S_MNTR_SPAWN1, // spawnstate + 2500, // spawnhealth + S_MNTR_WALK1, // seestate + SFX_MAULATOR_SIGHT, // seesound + 8, // reactiontime + SFX_MAULATOR_HAMMER_SWING, // attacksound + S_MNTR_PAIN1, // painstate + 25, // painchance + SFX_MAULATOR_PAIN, // painsound + S_MNTR_ATK1_1, // meleestate + S_MNTR_ATK2_1, // missilestate + S_NULL, // crashstate + S_MNTR_DIE1, // deathstate + S_NULL, // xdeathstate + SFX_MAULATOR_DEATH, // deathsound + 16, // speed + 28 * FRACUNIT, // radius + 100 * FRACUNIT, // height + 800, // mass + 7, // damage + SFX_MAULATOR_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 + }, + + { // MT_MNTRFX1 + -1, // doomednum + S_MNTRFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MNTRFXI1_1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 20 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 3, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_MNTRFX2 + -1, // doomednum + S_MNTRFX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MNTRFXI2_1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 14 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 12 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_MNTRFX3 + -1, // doomednum + S_MNTRFX3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_MNTRFXI2_1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_MNTRSMOKE + -1, // doomednum + S_MINOSMOKE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_MNTRSMOKEEXIT + -1, // doomednum + S_MINOSMOKEX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SERPENT + 121, // doomednum + S_SERPENT_LOOK1, // spawnstate + 90, // spawnhealth + S_SERPENT_SWIM1, // seestate + SFX_SERPENT_SIGHT, // seesound + 8, // reactiontime + SFX_SERPENT_ATTACK, // attacksound + S_SERPENT_PAIN1, // painstate + 96, // painchance + SFX_SERPENT_PAIN, // painsound + S_SERPENT_SURFACE1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SERPENT_DIE1, // deathstate + S_SERPENT_XDIE1, // xdeathstate + SFX_SERPENT_DEATH, // deathsound + 12, // speed + 32 * FRACUNIT, // radius + 70 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_COUNTKILL | MF_NOBLOOD, // flags + MF2_PASSMOBJ | MF2_DONTDRAW | MF2_CANTLEAVEFLOORPIC | MF2_NONSHOOTABLE | MF2_MCROSS // flags2 + }, + + { // MT_SERPENTLEADER + 120, // doomednum + S_SERPENT_LOOK1, // spawnstate + 90, // spawnhealth + S_SERPENT_SWIM1, // seestate + SFX_SERPENT_SIGHT, // seesound + 8, // reactiontime + SFX_SERPENT_ATTACK, // attacksound + S_SERPENT_PAIN1, // painstate + 96, // painchance + SFX_SERPENT_PAIN, // painsound + S_SERPENT_SURFACE1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SERPENT_DIE1, // deathstate + S_SERPENT_XDIE1, // xdeathstate + SFX_SERPENT_DEATH, // deathsound + 12, // speed + 32 * FRACUNIT, // radius + 70 * FRACUNIT, // height + 200, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_COUNTKILL | MF_NOBLOOD, // flags + MF2_PASSMOBJ | MF2_DONTDRAW | MF2_CANTLEAVEFLOORPIC | MF2_NONSHOOTABLE | MF2_MCROSS // flags2 + }, + + { // MT_SERPENTFX + -1, // doomednum + S_SERPENT_FX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + 0, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SERPENT_FX_X1, // deathstate + S_NULL, // xdeathstate + SFX_SERPENTFX_HIT, // deathsound + 15 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 4, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SERPENT_HEAD + -1, // doomednum + S_SERPENT_HEAD1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + MF2_LOGRAV // flags2 + }, + + { // MT_SERPENT_GIB1 + -1, // doomednum + S_SERPENT_GIB1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 3 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_SERPENT_GIB2 + -1, // doomednum + S_SERPENT_GIB2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 3 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_SERPENT_GIB3 + -1, // doomednum + S_SERPENT_GIB3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 3 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_BISHOP + 114, // doomednum + S_BISHOP_LOOK1, // spawnstate + 130, // spawnhealth + S_BISHOP_WALK1, // seestate + SFX_BISHOP_SIGHT, // seesound + 8, // reactiontime + SFX_BISHOP_ATTACK, // attacksound + S_BISHOP_PAIN1, // painstate + 110, // painchance + SFX_BISHOP_PAIN, // painsound + 0, // meleestate + S_BISHOP_ATK1, // missilestate + S_NULL, // crashstate + S_BISHOP_DEATH1, // deathstate + S_NULL, // xdeathstate + SFX_BISHOP_DEATH, // deathsound + 10, // speed + 22 * FRACUNIT, // radius + 65 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_BISHOP_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_FLOAT | MF_NOGRAVITY | MF_NOBLOOD, // flags + MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 + }, + + { // MT_BISHOP_PUFF + -1, // doomednum + S_BISHOP_PUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SHADOW | MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_BISHOPBLUR + -1, // doomednum + S_BISHOPBLUR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_BISHOPPAINBLUR + -1, // doomednum + S_BISHOPPAINBLUR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags + 0 // flags2 + }, + + { // MT_BISH_FX + -1, // doomednum + S_BISHFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BISHFXI1_1, // deathstate + S_NULL, // xdeathstate + SFX_BISHOP_MISSILE_EXPLODE, // deathsound + 10 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 100, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_SEEKERMISSILE // flags2 + }, + + { // MT_DRAGON + 254, // doomednum + S_DRAGON_LOOK1, // spawnstate + 640, // spawnhealth + S_DRAGON_INIT, // seestate + SFX_DRAGON_SIGHT, // seesound + 8, // reactiontime + SFX_DRAGON_ATTACK, // attacksound + S_DRAGON_PAIN1, // painstate + 128, // painchance + SFX_DRAGON_PAIN, // painsound + S_NULL, // meleestate + S_DRAGON_ATK1, // missilestate + S_NULL, // crashstate + S_DRAGON_DEATH1, // deathstate + S_NULL, // xdeathstate + SFX_DRAGON_DEATH, // deathsound + 10 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 65 * FRACUNIT, // height + INT_MAX, // mass + 0, // damage + SFX_DRAGON_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_FLOAT | MF_NOGRAVITY | MF_NOBLOOD, // flags + MF2_PASSMOBJ | MF2_BOSS // flags2 + }, + + { // MT_DRAGON_FX + -1, // doomednum + S_DRAGON_FX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_DRAGON_FX1_X1, // deathstate + S_NULL, // xdeathstate + SFX_DRAGON_FIREBALL_EXPLODE, // deathsound + 24 * FRACUNIT, // speed + 12 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 6, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 + }, + + { // MT_DRAGON_FX2 + -1, // doomednum + S_DRAGON_FX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_DRAGON_FIREBALL_EXPLODE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP, // flags + MF2_NOTELEPORT | MF2_FIREDAMAGE | MF2_DONTDRAW // flags2 + }, + + { // MT_ARMOR_1 + 8005, // doomednum + S_ARMOR_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARMOR_2 + 8006, // doomednum + S_ARMOR_2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARMOR_3 + 8007, // doomednum + S_ARMOR_3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_ARMOR_4 + 8008, // doomednum + S_ARMOR_4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL | MF_NOGRAVITY, // flags + 0 // flags2 + }, + + { // MT_MANA1 + 122, // doomednum + S_MANA1_1, // spawnstate + 10, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MANA2 + 124, // doomednum + S_MANA2_1, // spawnstate + 10, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_MANA3 + 8004, // doomednum + S_MANA3_1, // spawnstate + 20, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 8 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + MF2_FLOATBOB // flags2 + }, + + { // MT_KEY1 + 8030, // doomednum + S_KEY1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY2 + 8031, // doomednum + S_KEY2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY3 + 8032, // doomednum + S_KEY3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY4 + 8033, // doomednum + S_KEY4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY5 + 8034, // doomednum + S_KEY5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY6 + 8035, // doomednum + S_KEY6, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY7 + 8036, // doomednum + S_KEY7, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY8 + 8037, // doomednum + S_KEY8, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEY9 + 8038, // doomednum + S_KEY9, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEYA + 8039, // doomednum + S_KEYA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_KEYB + 8200, // doomednum + S_KEYB, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 8 * FRACUNIT, // radius + 20 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SPECIAL, // flags + 0 // flags2 + }, + + { // MT_SOUNDWIND + 1410, // doomednum + S_SND_WIND1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_SOUNDWATERFALL + 41, // doomednum + S_SND_WATERFALL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR, // flags + 0 // flags2 + }, + + { // MT_ETTIN + 10030, // doomednum + S_ETTIN_LOOK1, // spawnstate + 175, // spawnhealth + S_ETTIN_CHASE1, // seestate + SFX_ETTIN_SIGHT, // seesound + 8, // reactiontime + SFX_ETTIN_ATTACK, // attacksound + S_ETTIN_PAIN1, // painstate + 60, // painchance + SFX_ETTIN_PAIN, // painsound + S_ETTIN_ATK1_1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ETTIN_DEATH1_1, // deathstate + S_ETTIN_DEATH2_1, // xdeathstate + SFX_ETTIN_DEATH, // deathsound + 13, // speed + 25 * FRACUNIT, // radius + 68 * FRACUNIT, // height + 175, // mass + 3, // damage + SFX_ETTIN_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_ETTIN_MACE + -1, // doomednum + S_ETTIN_MACE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ETTIN_MACE5, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_FIREDEMON + 10060, // doomednum + S_FIRED_SPAWN1, // spawnstate + 80, // spawnhealth + S_FIRED_LOOK4, // seestate + SFX_FIRED_SPAWN, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_FIRED_PAIN1, // painstate + 1, // painchance + SFX_FIRED_PAIN, // painsound + S_NULL, // meleestate + S_FIRED_ATTACK1, // missilestate + S_FIRED_XDEATH1, // crashstate + S_FIRED_DEATH1, // deathstate + S_FIRED_XDEATH1, // xdeathstate + SFX_FIRED_DEATH, // deathsound + 13, // speed + 20 * FRACUNIT, // radius + 68 * FRACUNIT, // height + 75, // mass + 1, // damage + SFX_FIRED_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF | MF_NOGRAVITY | MF_FLOAT, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_INVULNERABLE | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_FIREDEMON_SPLOTCH1 + -1, // doomednum + S_FIRED_CORPSE1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_FIREDEMON_SPLOTCH2 + -1, // doomednum + S_FIRED_CORPSE4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_DROPOFF | MF_CORPSE, // flags + MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 + }, + + { // MT_FIREDEMON_FX1 + -1, // doomednum + S_FIRED_RDROP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIRED_RDEAD1_1, // deathstate + S_FIRED_RDEAD1_2, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 16, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FIREDEMON_FX2 + -1, // doomednum + S_FIRED_RDROP2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIRED_RDEAD2_1, // deathstate + S_FIRED_RDEAD2_2, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 16, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FIREDEMON_FX3 + -1, // doomednum + S_FIRED_RDROP3, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIRED_RDEAD3_1, // deathstate + S_FIRED_RDEAD3_2, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 16, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FIREDEMON_FX4 + -1, // doomednum + S_FIRED_RDROP4, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIRED_RDEAD4_1, // deathstate + S_FIRED_RDEAD4_2, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 16, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FIREDEMON_FX5 + -1, // doomednum + S_FIRED_RDROP5, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIRED_RDEAD5_1, // deathstate + S_FIRED_RDEAD5_2, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 3 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 16, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FIREDEMON_FX6 + -1, // doomednum + S_FIRED_FX6_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_FIRED_FX6_2, // deathstate + S_NULL, // xdeathstate + SFX_FIRED_MISSILE_HIT, // deathsound + 10 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 6 * FRACUNIT, // height + 15, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FLOORCLIP | MF2_FIREDAMAGE // flags2 + }, + + { // MT_ICEGUY + 8020, // doomednum + S_ICEGUY_LOOK, // spawnstate + 120, // spawnhealth + S_ICEGUY_WALK1, // seestate + SFX_ICEGUY_SIGHT, // seesound + 8, // reactiontime + SFX_ICEGUY_ATTACK, // attacksound + S_ICEGUY_PAIN1, // painstate + 144, // painchance + SFX_NONE, // painsound + 0, // meleestate + S_ICEGUY_ATK1, // missilestate + S_NULL, // crashstate + S_ICEGUY_DEATH, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 14, // speed + 22 * FRACUNIT, // radius + 75 * FRACUNIT, // height + 150, // mass + 0, // damage + SFX_ICEGUY_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags + MF2_PASSMOBJ | MF2_PUSHWALL | MF2_ICEDAMAGE | MF2_MCROSS | MF2_TELESTOMP // flags2 + }, + + { // MT_ICEGUY_FX + -1, // doomednum + S_ICEGUY_FX1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_ICEGUY_FX_X1, // deathstate + S_NULL, // xdeathstate + SFX_ICEGUY_FX_EXPLODE, // deathsound + 14 * FRACUNIT, // speed + 8 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags + MF2_NOTELEPORT | MF2_ICEDAMAGE // flags2 + }, + + { // MT_ICEFX_PUFF + -1, // doomednum + S_ICEFX_PUFF1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW | MF_DROPOFF, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ICEGUY_FX2 + -1, // doomednum + S_ICEGUY_FX2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 10 * FRACUNIT, // speed + 4 * FRACUNIT, // radius + 4 * FRACUNIT, // height + 100, // mass + 1, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_LOGRAV | MF2_ICEDAMAGE // flags2 + }, + + { // MT_ICEGUY_BIT + -1, // doomednum + S_ICEGUY_BIT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_ICEGUY_WISP1 + -1, // doomednum + S_ICEGUY_WISP1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_ICEGUY_WISP2 + -1, // doomednum + S_ICEGUY_WISP2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_FIGHTER_BOSS + 10100, // doomednum + S_FIGHTER, // spawnstate + 800, // spawnhealth + S_FIGHTER_RUN1, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_FIGHTER_PAIN, // painstate + 50, // painchance + SFX_PLAYER_FIGHTER_PAIN, // painsound + S_FIGHTER_ATK1, // meleestate + S_FIGHTER_ATK1, // missilestate + S_NULL, // crashstate + S_FIGHTER_DIE1, // deathstate + S_FIGHTER_XDIE1, // xdeathstate + SFX_PLAYER_FIGHTER_CRAZY_DEATH, // deathsound + 25, // speed + 16 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL | MF2_MCROSS // flags2 + }, + + { // MT_CLERIC_BOSS + 10101, // doomednum + S_CLERIC, // spawnstate + 800, // spawnhealth + S_CLERIC_RUN1, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_CLERIC_PAIN, // painstate + 50, // painchance + SFX_PLAYER_CLERIC_PAIN, // painsound + S_CLERIC_ATK1, // meleestate + S_CLERIC_ATK1, // missilestate + S_NULL, // crashstate + S_CLERIC_DIE1, // deathstate + S_CLERIC_XDIE1, // xdeathstate + SFX_PLAYER_CLERIC_CRAZY_DEATH, // deathsound + 25, // speed + 16 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL | MF2_MCROSS // flags2 + }, + + { // MT_MAGE_BOSS + 10102, // doomednum + S_MAGE, // spawnstate + 800, // spawnhealth + S_MAGE_RUN1, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_MAGE_PAIN, // painstate + 50, // painchance + SFX_PLAYER_MAGE_PAIN, // painsound + S_MAGE_ATK1, // meleestate + S_MAGE_ATK1, // missilestate + S_NULL, // crashstate + S_MAGE_DIE1, // deathstate + S_MAGE_XDIE1, // xdeathstate + SFX_PLAYER_MAGE_CRAZY_DEATH, // deathsound + 25, // speed + 16 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL | MF2_MCROSS // flags2 + }, + + { // MT_SORCBOSS + 10080, // doomednum + S_SORC_SPAWN1, // spawnstate + 5000, // spawnhealth + S_SORC_WALK1, // seestate + SFX_SORCERER_SIGHT, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_SORC_PAIN1, // painstate + 10, // painchance + SFX_SORCERER_PAIN, // painsound + S_NULL, // meleestate + S_SORC_ATK2_1, // missilestate + S_NULL, // crashstate + S_SORC_DIE1, // deathstate + S_NULL, // xdeathstate + SFX_SORCERER_DEATHSCREAM, // deathsound + 16, // speed + 40 * FRACUNIT, // radius + 110 * FRACUNIT, // height + 500, // mass + 9, // damage + SFX_SORCERER_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_BOSS | MF2_MCROSS // flags2 + }, + + { // MT_SORCBALL1 + -1, // doomednum + S_SORCBALL1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_SORCERER_BALLBOUNCE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_SORCBALL1_D1, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SORCBALL1_D5, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 10 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SORCBALL2 + -1, // doomednum + S_SORCBALL2_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_SORCERER_BALLBOUNCE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_SORCBALL2_D1, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SORCBALL2_D5, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 10 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SORCBALL3 + -1, // doomednum + S_SORCBALL3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_SORCERER_BALLBOUNCE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_SORCBALL3_D1, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SORCBALL3_D5, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 10 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SORCFX1 + -1, // doomednum + S_SORCFX1_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_SORCERER_BALLBOUNCE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SORCFX1_D1, // deathstate + S_SORCFX1_D1, // xdeathstate + SFX_NONE, // deathsound + 7 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE, // flags + MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 + }, + + { // MT_SORCFX2 + -1, // doomednum + S_SORCFX2_SPLIT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SORCFX2T1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 15 * FRACUNIT, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SORCFX2_T1 + -1, // doomednum + S_SORCFX2T1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_ALTSHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SORCFX3 + -1, // doomednum + S_SORCFX3_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_SORCERER_BISHOPSPAWN, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BISHMORPH1, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 15 * FRACUNIT, // speed + 22 * FRACUNIT, // radius + 65 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SORCFX3_EXPLOSION + -1, // doomednum + S_SORCFX3_EXP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_ALTSHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SORCFX4 + -1, // doomednum + S_SORCFX4_1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_SORCFX4_D1, // deathstate + S_NULL, // xdeathstate + SFX_SORCERER_BALLEXPLODE, // deathsound + 12 * FRACUNIT, // speed + 10 * FRACUNIT, // radius + 10 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_MISSILE | MF_NOGRAVITY, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_SORCSPARK1 + -1, // doomednum + S_SORCSPARK1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 5 * FRACUNIT, // radius + 5 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF, // flags + MF2_NOTELEPORT | MF2_LOGRAV // flags2 + }, + + { // MT_BLASTEFFECT + -1, // doomednum + S_BLASTEFFECT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_NOCLIP | MF_ALTSHADOW, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_WATER_DRIP + -1, // doomednum + S_WATERDRIP1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_DRIP, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 1, // mass + 0, // damage + SFX_NONE, // activesound + MF_MISSILE, // flags + MF2_LOGRAV | MF2_NOTELEPORT // flags2 + }, + + { // MT_KORAX + 10200, // doomednum + S_KORAX_LOOK1, // spawnstate + 5000, // spawnhealth + S_KORAX_CHASE2, // seestate + SFX_KORAX_SIGHT, // seesound + 8, // reactiontime + SFX_KORAX_ATTACK, // attacksound + S_KORAX_PAIN1, // painstate + 20, // painchance + SFX_KORAX_PAIN, // painsound + S_NULL, // meleestate + S_KORAX_ATTACK1, // missilestate + S_NULL, // crashstate + S_KORAX_DEATH1, // deathstate + S_NULL, // xdeathstate + SFX_KORAX_DEATH, // deathsound + 10, // speed + 65 * FRACUNIT, // radius + 115 * FRACUNIT, // height + 2000, // mass + 15, // damage + SFX_KORAX_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags + MF2_FLOORCLIP | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP | MF2_BOSS // flags2 + }, + + { // MT_KORAX_SPIRIT1 + -1, // doomednum + S_KSPIRIT_ROAM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 8 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_KORAX_SPIRIT2 + -1, // doomednum + S_KSPIRIT_ROAM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 8 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_KORAX_SPIRIT3 + -1, // doomednum + S_KSPIRIT_ROAM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 8 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_KORAX_SPIRIT4 + -1, // doomednum + S_KSPIRIT_ROAM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 8 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_KORAX_SPIRIT5 + -1, // doomednum + S_KSPIRIT_ROAM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 8 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_KORAX_SPIRIT6 + -1, // doomednum + S_KSPIRIT_ROAM1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 8 * FRACUNIT, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_DEMON_MASH + -1, // doomednum + S_DEMN_LOOK1, // spawnstate + 250, // spawnhealth + S_DEMN_CHASE1, // seestate + SFX_DEMON_SIGHT, // seesound + 8, // reactiontime + SFX_DEMON_ATTACK, // attacksound + S_DEMN_PAIN1, // painstate + 50, // painchance + SFX_DEMON_PAIN, // painsound + S_DEMN_ATK1_1, // meleestate + S_DEMN_ATK2_1, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_DEMON_DEATH, // deathsound + 13, // speed + 32 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 220, // mass + 0, // damage + SFX_DEMON_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 + }, + + { // MT_DEMON2_MASH + -1, // doomednum + S_DEMN2_LOOK1, // spawnstate + 250, // spawnhealth + S_DEMN2_CHASE1, // seestate + SFX_DEMON_SIGHT, // seesound + 8, // reactiontime + SFX_DEMON_ATTACK, // attacksound + S_DEMN2_PAIN1, // painstate + 50, // painchance + SFX_DEMON_PAIN, // painsound + S_DEMN2_ATK1_1, // meleestate + S_DEMN2_ATK2_1, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_DEMON_DEATH, // deathsound + 13, // speed + 32 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 220, // mass + 0, // damage + SFX_DEMON_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 + }, + + { // MT_ETTIN_MASH + -1, // doomednum + S_ETTIN_LOOK1, // spawnstate + 175, // spawnhealth + S_ETTIN_CHASE1, // seestate + SFX_ETTIN_SIGHT, // seesound + 8, // reactiontime + SFX_ETTIN_ATTACK, // attacksound + S_ETTIN_PAIN1, // painstate + 60, // painchance + SFX_ETTIN_PAIN, // painsound + S_ETTIN_ATK1_1, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_ETTIN_DEATH, // deathsound + 13, // speed + 25 * FRACUNIT, // radius + 68 * FRACUNIT, // height + 175, // mass + 3, // damage + SFX_ETTIN_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 + }, + + { // MT_CENTAUR_MASH + -1, // doomednum + S_CENTAUR_LOOK1, // spawnstate + 200, // spawnhealth + S_CENTAUR_WALK1, // seestate + SFX_CENTAUR_SIGHT, // seesound + 8, // reactiontime + SFX_CENTAUR_ATTACK, // attacksound + S_CENTAUR_PAIN1, // painstate + 135, // painchance + SFX_CENTAUR_PAIN, // painsound + S_CENTAUR_ATK1, // meleestate + 0, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_CENTAUR_DEATH, // deathsound + 13, // speed + 20 * FRACUNIT, // radius + 64 * FRACUNIT, // height + 120, // mass + 0, // damage + SFX_CENTAUR_ACTIVE, // activesound + MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags + MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 + }, + + { // MT_KORAX_BOLT + -1, // doomednum + S_KBOLT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 15 * FRACUNIT, // radius + 35 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags + MF2_NOTELEPORT // flags2 + }, + + { // MT_BAT_SPAWNER + 10225, // doomednum + S_SPAWNBATS1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_NULL, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 0, // speed + 20 * FRACUNIT, // radius + 16 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOSECTOR | MF_NOGRAVITY, // flags + MF2_DONTDRAW // flags2 + }, + + { // MT_BAT + -1, // doomednum + S_BAT1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + SFX_NONE, // seesound + 8, // reactiontime + SFX_NONE, // attacksound + S_NULL, // painstate + 0, // painchance + SFX_NONE, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // crashstate + S_BAT_DEATH, // deathstate + S_NULL, // xdeathstate + SFX_NONE, // deathsound + 5 * FRACUNIT, // speed + 3 * FRACUNIT, // radius + 3 * FRACUNIT, // height + 100, // mass + 0, // damage + SFX_NONE, // activesound + MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags + MF2_PASSMOBJ | MF2_NOTELEPORT // flags2 + } +}; diff --git a/games/NXDoom/src/hexen/info.h b/games/NXDoom/src/hexen/info.h new file mode 100644 index 00000000000..18872fae987 --- /dev/null +++ b/games/NXDoom/src/hexen/info.h @@ -0,0 +1,3626 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// generated by stateco + +typedef enum +{ + SPR_MAN1, + SPR_ACLO, + SPR_TLGL, + SPR_FBL1, + SPR_XPL1, + SPR_ARRW, + SPR_DART, + SPR_RIPP, + SPR_CFCF, + SPR_BLAD, + SPR_SHRD, + SPR_FFSM, + SPR_FFLG, + SPR_PTN1, + SPR_PTN2, + SPR_SOAR, + SPR_INVU, + SPR_SUMN, + SPR_TSPK, + SPR_TELO, + SPR_TRNG, + SPR_ROCK, + SPR_FOGS, + SPR_FOGM, + SPR_FOGL, + SPR_SGSA, + SPR_SGSB, + SPR_PORK, + SPR_EGGM, + SPR_FHFX, + SPR_SPHL, + SPR_STWN, + SPR_GMPD, + SPR_ASKU, + SPR_ABGM, + SPR_AGMR, + SPR_AGMG, + SPR_AGG2, + SPR_AGMB, + SPR_AGB2, + SPR_ABK1, + SPR_ABK2, + SPR_ASK2, + SPR_AFWP, + SPR_ACWP, + SPR_AMWP, + SPR_AGER, + SPR_AGR2, + SPR_AGR3, + SPR_AGR4, + SPR_TRCH, + SPR_PSBG, + SPR_ATLP, + SPR_THRW, + SPR_SPED, + SPR_BMAN, + SPR_BRAC, + SPR_BLST, + SPR_HRAD, + SPR_SPSH, + SPR_LVAS, + SPR_SLDG, + SPR_STTW, + SPR_RCK1, + SPR_RCK2, + SPR_RCK3, + SPR_RCK4, + SPR_CDLR, + SPR_TRE1, + SPR_TRDT, + SPR_TRE2, + SPR_TRE3, + SPR_STM1, + SPR_STM2, + SPR_STM3, + SPR_STM4, + SPR_MSH1, + SPR_MSH2, + SPR_MSH3, + SPR_MSH4, + SPR_MSH5, + SPR_MSH6, + SPR_MSH7, + SPR_MSH8, + SPR_SGMP, + SPR_SGM1, + SPR_SGM2, + SPR_SGM3, + SPR_SLC1, + SPR_SLC2, + SPR_SLC3, + SPR_MSS1, + SPR_MSS2, + SPR_SWMV, + SPR_CPS1, + SPR_CPS2, + SPR_TMS1, + SPR_TMS2, + SPR_TMS3, + SPR_TMS4, + SPR_TMS5, + SPR_TMS6, + SPR_TMS7, + SPR_CPS3, + SPR_STT2, + SPR_STT3, + SPR_STT4, + SPR_STT5, + SPR_GAR1, + SPR_GAR2, + SPR_GAR3, + SPR_GAR4, + SPR_GAR5, + SPR_GAR6, + SPR_GAR7, + SPR_GAR8, + SPR_GAR9, + SPR_BNR1, + SPR_TRE4, + SPR_TRE5, + SPR_TRE6, + SPR_TRE7, + SPR_LOGG, + SPR_ICT1, + SPR_ICT2, + SPR_ICT3, + SPR_ICT4, + SPR_ICM1, + SPR_ICM2, + SPR_ICM3, + SPR_ICM4, + SPR_RKBL, + SPR_RKBS, + SPR_RKBK, + SPR_RBL1, + SPR_RBL2, + SPR_RBL3, + SPR_VASE, + SPR_POT1, + SPR_POT2, + SPR_POT3, + SPR_PBIT, + SPR_CPS4, + SPR_CPS5, + SPR_CPS6, + SPR_CPB1, + SPR_CPB2, + SPR_CPB3, + SPR_CPB4, + SPR_BDRP, + SPR_BDSH, + SPR_BDPL, + SPR_CNDL, + SPR_LEF1, + SPR_LEF3, + SPR_LEF2, + SPR_TWTR, + SPR_WLTR, + SPR_BARL, + SPR_SHB1, + SPR_SHB2, + SPR_BCKT, + SPR_SHRM, + SPR_FBUL, + SPR_FSKL, + SPR_BRTR, + SPR_SUIT, + SPR_BBLL, + SPR_CAND, + SPR_IRON, + SPR_XMAS, + SPR_CDRN, + SPR_CHNS, + SPR_TST1, + SPR_TST2, + SPR_TST3, + SPR_TST4, + SPR_TST5, + SPR_TST6, + SPR_TST7, + SPR_TST8, + SPR_TST9, + SPR_TST0, + SPR_TELE, + SPR_TSMK, + SPR_FPCH, + SPR_WFAX, + SPR_FAXE, + SPR_WFHM, + SPR_FHMR, + SPR_FSRD, + SPR_FSFX, + SPR_CMCE, + SPR_WCSS, + SPR_CSSF, + SPR_WCFM, + SPR_CFLM, + SPR_CFFX, + SPR_CHLY, + SPR_SPIR, + SPR_MWND, + SPR_WMLG, + SPR_MLNG, + SPR_MLFX, + SPR_MLF2, + SPR_MSTF, + SPR_MSP1, + SPR_MSP2, + SPR_WFR1, + SPR_WFR2, + SPR_WFR3, + SPR_WCH1, + SPR_WCH2, + SPR_WCH3, + SPR_WMS1, + SPR_WMS2, + SPR_WMS3, + SPR_WPIG, + SPR_WMCS, + SPR_CONE, + SPR_SHEX, + SPR_BLOD, + SPR_GIBS, + SPR_PLAY, + SPR_FDTH, + SPR_BSKL, + SPR_ICEC, + SPR_CLER, + SPR_MAGE, + SPR_PIGY, + SPR_CENT, + SPR_CTXD, + SPR_CTFX, + SPR_CTDP, + SPR_DEMN, + SPR_DEMA, + SPR_DEMB, + SPR_DEMC, + SPR_DEMD, + SPR_DEME, + SPR_DMFX, + SPR_DEM2, + SPR_DMBA, + SPR_DMBB, + SPR_DMBC, + SPR_DMBD, + SPR_DMBE, + SPR_D2FX, + SPR_WRTH, + SPR_WRT2, + SPR_WRBL, + SPR_MNTR, + SPR_FX12, + SPR_FX13, + SPR_MNSM, + SPR_SSPT, + SPR_SSDV, + SPR_SSXD, + SPR_SSFX, + SPR_BISH, + SPR_BPFX, + SPR_DRAG, + SPR_DRFX, + SPR_ARM1, + SPR_ARM2, + SPR_ARM3, + SPR_ARM4, + SPR_MAN2, + SPR_MAN3, + SPR_KEY1, + SPR_KEY2, + SPR_KEY3, + SPR_KEY4, + SPR_KEY5, + SPR_KEY6, + SPR_KEY7, + SPR_KEY8, + SPR_KEY9, + SPR_KEYA, + SPR_KEYB, + SPR_ETTN, + SPR_ETTB, + SPR_FDMN, + SPR_FDMB, + SPR_ICEY, + SPR_ICPR, + SPR_ICWS, + SPR_SORC, + SPR_SBMP, + SPR_SBS4, + SPR_SBMB, + SPR_SBS3, + SPR_SBMG, + SPR_SBS1, + SPR_SBS2, + SPR_SBFX, + SPR_RADE, + SPR_WATR, + SPR_KORX, + SPR_ABAT, + NUMSPRITES +} spritenum_t; + +typedef enum +{ + S_NULL, + S_FREETARGMOBJ, + S_MAPSPOT, + S_FIREBALL1_1, + S_FIREBALL1_2, + S_FIREBALL1_X1, + S_FIREBALL1_X2, + S_FIREBALL1_X3, + S_FIREBALL1_X4, + S_FIREBALL1_X5, + S_FIREBALL1_X6, + S_ARROW_1, + S_ARROW_X1, + S_DART_1, + S_DART_X1, + S_POISONDART_1, + S_POISONDART_X1, + S_RIPPERBALL_1, + S_RIPPERBALL_2, + S_RIPPERBALL_3, + S_RIPPERBALL_X1, + S_RIPPERBALL_X2, + S_RIPPERBALL_X3, + S_RIPPERBALL_X4, + S_RIPPERBALL_X5, + S_RIPPERBALL_X6, + S_RIPPERBALL_X7, + S_RIPPERBALL_X8, + S_RIPPERBALL_X9, + S_RIPPERBALL_X10, + S_PRJ_BLADE1, + S_PRJ_BLADE_X1, + S_ICESHARD1, + S_ICESHARD2, + S_ICESHARD3, + S_FLAME_TSMALL1, + S_FLAME_TSMALL2, + S_FLAME_TSMALL3, + S_FLAME_TSMALL4, + S_FLAME_TSMALL5, + S_FLAME_TSMALL6, + S_FLAME_TLARGE1, + S_FLAME_TLARGE2, + S_FLAME_TLARGE3, + S_FLAME_TLARGE4, + S_FLAME_TLARGE5, + S_FLAME_TLARGE6, + S_FLAME_TLARGE7, + S_FLAME_TLARGE8, + S_FLAME_TLARGE9, + S_FLAME_TLARGE10, + S_FLAME_TLARGE11, + S_FLAME_TLARGE12, + S_FLAME_TLARGE13, + S_FLAME_TLARGE14, + S_FLAME_TLARGE15, + S_FLAME_TLARGE16, + S_FLAME_SDORM1, + S_FLAME_SDORM2, + S_FLAME_SDORM3, + S_FLAME_SMALL1, + S_FLAME_SMALL2, + S_FLAME_SMALL3, + S_FLAME_SMALL4, + S_FLAME_SMALL5, + S_FLAME_SMALL6, + S_FLAME_SMALL7, + S_FLAME_LDORM1, + S_FLAME_LDORM2, + S_FLAME_LDORM3, + S_FLAME_LDORM4, + S_FLAME_LDORM5, + S_FLAME_LARGE1, + S_FLAME_LARGE2, + S_FLAME_LARGE3, + S_FLAME_LARGE4, + S_FLAME_LARGE5, + S_FLAME_LARGE6, + S_FLAME_LARGE7, + S_FLAME_LARGE8, + S_FLAME_LARGE9, + S_FLAME_LARGE10, + S_FLAME_LARGE11, + S_FLAME_LARGE12, + S_FLAME_LARGE13, + S_FLAME_LARGE14, + S_FLAME_LARGE15, + S_FLAME_LARGE16, + S_FLAME_LARGE17, + S_FLAME_LARGE18, + S_ITEM_PTN1_1, + S_ITEM_PTN1_2, + S_ITEM_PTN1_3, + S_HIDESPECIAL1, + S_HIDESPECIAL2, + S_HIDESPECIAL3, + S_HIDESPECIAL4, + S_HIDESPECIAL5, + S_HIDESPECIAL6, + S_HIDESPECIAL7, + S_HIDESPECIAL8, + S_HIDESPECIAL9, + S_HIDESPECIAL10, + S_HIDESPECIAL11, + S_DORMANTARTI1_1, + S_DORMANTARTI1_2, + S_DORMANTARTI1_3, + S_DORMANTARTI1_4, + S_DORMANTARTI1_5, + S_DORMANTARTI1_6, + S_DORMANTARTI1_7, + S_DORMANTARTI1_8, + S_DORMANTARTI1_9, + S_DORMANTARTI1_10, + S_DORMANTARTI1_11, + S_DORMANTARTI1_12, + S_DORMANTARTI1_13, + S_DORMANTARTI1_14, + S_DORMANTARTI1_15, + S_DORMANTARTI1_16, + S_DORMANTARTI1_17, + S_DORMANTARTI1_18, + S_DORMANTARTI1_19, + S_DORMANTARTI1_20, + S_DORMANTARTI1_21, + S_DORMANTARTI2_1, + S_DORMANTARTI2_2, + S_DORMANTARTI2_3, + S_DORMANTARTI2_4, + S_DORMANTARTI2_5, + S_DORMANTARTI2_6, + S_DORMANTARTI2_7, + S_DORMANTARTI2_8, + S_DORMANTARTI2_9, + S_DORMANTARTI2_10, + S_DORMANTARTI2_11, + S_DORMANTARTI2_12, + S_DORMANTARTI2_13, + S_DORMANTARTI2_14, + S_DORMANTARTI2_15, + S_DORMANTARTI2_16, + S_DORMANTARTI2_17, + S_DORMANTARTI2_18, + S_DORMANTARTI2_19, + S_DORMANTARTI2_20, + S_DORMANTARTI2_21, + S_DORMANTARTI3_1, + S_DORMANTARTI3_2, + S_DORMANTARTI3_3, + S_DORMANTARTI3_4, + S_DORMANTARTI3_5, + S_DORMANTARTI3_6, + S_DORMANTARTI3_7, + S_DORMANTARTI3_8, + S_DORMANTARTI3_9, + S_DORMANTARTI3_10, + S_DORMANTARTI3_11, + S_DORMANTARTI3_12, + S_DORMANTARTI3_13, + S_DORMANTARTI3_14, + S_DORMANTARTI3_15, + S_DORMANTARTI3_16, + S_DORMANTARTI3_17, + S_DORMANTARTI3_18, + S_DORMANTARTI3_19, + S_DORMANTARTI3_20, + S_DORMANTARTI3_21, + S_DEADARTI1, + S_DEADARTI2, + S_DEADARTI3, + S_DEADARTI4, + S_DEADARTI5, + S_DEADARTI6, + S_DEADARTI7, + S_DEADARTI8, + S_DEADARTI9, + S_DEADARTI10, + S_ARTI_PTN2_1, + S_ARTI_PTN2_2, + S_ARTI_PTN2_3, + S_ARTI_SOAR1, + S_ARTI_SOAR2, + S_ARTI_SOAR3, + S_ARTI_SOAR4, + S_ARTI_INVU1, + S_ARTI_INVU2, + S_ARTI_INVU3, + S_ARTI_INVU4, + S_ARTI_SUMMON, + S_SUMMON_FX1_1, + S_SUMMON_FX2_1, + S_SUMMON_FX2_2, + S_SUMMON_FX2_3, + S_THRUSTINIT2_1, + S_THRUSTINIT2_2, + S_BTHRUSTINIT2_1, + S_BTHRUSTINIT2_2, + S_THRUSTINIT1_1, + S_THRUSTINIT1_2, + S_BTHRUSTINIT1_1, + S_BTHRUSTINIT1_2, + S_THRUSTRAISE1, + S_THRUSTRAISE2, + S_THRUSTRAISE3, + S_THRUSTRAISE4, + S_BTHRUSTRAISE1, + S_BTHRUSTRAISE2, + S_BTHRUSTRAISE3, + S_BTHRUSTRAISE4, + S_THRUSTIMPALE, + S_BTHRUSTIMPALE, + S_THRUSTRAISE, + S_BTHRUSTRAISE, + S_THRUSTBLOCK, + S_BTHRUSTBLOCK, + S_THRUSTLOWER, + S_BTHRUSTLOWER, + S_THRUSTSTAY, + S_BTHRUSTSTAY, + S_ARTI_TELOTHER1, + S_ARTI_TELOTHER2, + S_ARTI_TELOTHER3, + S_ARTI_TELOTHER4, + S_TELO_FX1, + S_TELO_FX2, + S_TELO_FX3, + S_TELO_FX4, + S_TELO_FX5, + S_TELO_FX6, + S_TELO_FX7, + S_TELO_FX8, + S_TELO_FX9, + S_TELO_FX2_1, + S_TELO_FX2_2, + S_TELO_FX2_3, + S_TELO_FX2_4, + S_TELO_FX2_5, + S_TELO_FX2_6, + S_TELO_FX3_1, + S_TELO_FX3_2, + S_TELO_FX3_3, + S_TELO_FX3_4, + S_TELO_FX3_5, + S_TELO_FX3_6, + S_TELO_FX4_1, + S_TELO_FX4_2, + S_TELO_FX4_3, + S_TELO_FX4_4, + S_TELO_FX4_5, + S_TELO_FX4_6, + S_TELO_FX5_1, + S_TELO_FX5_2, + S_TELO_FX5_3, + S_TELO_FX5_4, + S_TELO_FX5_5, + S_TELO_FX5_6, + S_DIRT1_1, + S_DIRT1_D, + S_DIRT2_1, + S_DIRT2_D, + S_DIRT3_1, + S_DIRT3_D, + S_DIRT4_1, + S_DIRT4_D, + S_DIRT5_1, + S_DIRT5_D, + S_DIRT6_1, + S_DIRT6_D, + S_DIRTCLUMP1, + S_ROCK1_1, + S_ROCK1_D, + S_ROCK2_1, + S_ROCK2_D, + S_ROCK3_1, + S_ROCK3_D, + S_SPAWNFOG1, + S_FOGPATCHS1, + S_FOGPATCHS2, + S_FOGPATCHS3, + S_FOGPATCHS4, + S_FOGPATCHS5, + S_FOGPATCHS0, + S_FOGPATCHM1, + S_FOGPATCHM2, + S_FOGPATCHM3, + S_FOGPATCHM4, + S_FOGPATCHM5, + S_FOGPATCHM0, + S_FOGPATCHMA, + S_FOGPATCHMB, + S_FOGPATCHMC, + S_FOGPATCHMD, + S_FOGPATCHL1, + S_FOGPATCHL2, + S_FOGPATCHL3, + S_FOGPATCHL4, + S_FOGPATCHL5, + S_FOGPATCHL0, + S_FOGPATCHLA, + S_FOGPATCHLB, + S_FOGPATCHLC, + S_FOGPATCHLD, + S_QUAKE_ACTIVE1, + S_QUAKE_ACTIVE2, + S_QUAKE_ACTIVE3, + S_QUAKE_ACTIVE4, + S_QUAKE_ACTIVE5, + S_QUAKE_ACTIVE6, + S_QUAKE_ACTIVE7, + S_QUAKE_ACTIVE8, + S_QUAKE_ACTIVE9, + S_QUAKE_ACTIVE0, + S_QUAKE_ACTIVEA, + S_QUAKE_ACTIVEB, + S_QUAKE_ACTIVEC, + S_QUAKE_ACTIVED, + S_QUAKE_ACTIVEE, + S_QUAKE_ACTIVEF, + S_QUAKE_ACTIVEG, + S_QUAKE_ACTIVEH, + S_QUAKE_ACTIVEI, + S_QUAKE_ACTIVEJ, + S_QUAKE_ACTIVEK, + S_QUAKE_ACTIVEL, + S_QUAKE_ACTIVEM, + S_QUAKE_ACTIVEN, + S_QUAKE_ACTIVEO, + S_QUAKE_ACTIVEP, + S_QUAKE_ACTIVEQ, + S_QUAKE_ACTIVER, + S_QUAKE_ACTIVES, + S_QUAKE_ACTIVET, + S_QUAKE_ACTIVEU, + S_QUAKE_ACTIVEV, + S_QUAKE_ACTIVEW, + S_QUAKE_ACTIVEX, + S_QUAKE_ACTIVEY, + S_QUAKE_ACTIVEZ, + S_QUAKE_ACT1, + S_QUAKE_ACT2, + S_QUAKE_ACT3, + S_QUAKE_ACT4, + S_QUAKE_ACT5, + S_QUAKE_ACT6, + S_QUAKE_ACT7, + S_QUAKE_ACT8, + S_QUAKE_ACT9, + S_QUAKE_ACT0, + S_SGSHARD1_1, + S_SGSHARD1_2, + S_SGSHARD1_3, + S_SGSHARD1_4, + S_SGSHARD1_5, + S_SGSHARD1_D, + S_SGSHARD2_1, + S_SGSHARD2_2, + S_SGSHARD2_3, + S_SGSHARD2_4, + S_SGSHARD2_5, + S_SGSHARD2_D, + S_SGSHARD3_1, + S_SGSHARD3_2, + S_SGSHARD3_3, + S_SGSHARD3_4, + S_SGSHARD3_5, + S_SGSHARD3_D, + S_SGSHARD4_1, + S_SGSHARD4_2, + S_SGSHARD4_3, + S_SGSHARD4_4, + S_SGSHARD4_5, + S_SGSHARD4_D, + S_SGSHARD5_1, + S_SGSHARD5_2, + S_SGSHARD5_3, + S_SGSHARD5_4, + S_SGSHARD5_5, + S_SGSHARD5_D, + S_SGSHARD6_1, + S_SGSHARD6_D, + S_SGSHARD7_1, + S_SGSHARD7_D, + S_SGSHARD8_1, + S_SGSHARD8_D, + S_SGSHARD9_1, + S_SGSHARD9_D, + S_SGSHARD0_1, + S_SGSHARD0_D, + S_ARTI_EGGC1, + S_ARTI_EGGC2, + S_ARTI_EGGC3, + S_ARTI_EGGC4, + S_ARTI_EGGC5, + S_ARTI_EGGC6, + S_ARTI_EGGC7, + S_ARTI_EGGC8, + S_EGGFX1, + S_EGGFX2, + S_EGGFX3, + S_EGGFX4, + S_EGGFX5, + S_EGGFXI1_1, + S_EGGFXI1_2, + S_EGGFXI1_3, + S_EGGFXI1_4, + S_ARTI_SPHL1, + S_ZWINGEDSTATUENOSKULL, + S_ZWINGEDSTATUENOSKULL2, + S_ZGEMPEDESTAL1, + S_ZGEMPEDESTAL2, + S_ARTIPUZZSKULL, + S_ARTIPUZZGEMBIG, + S_ARTIPUZZGEMRED, + S_ARTIPUZZGEMGREEN1, + S_ARTIPUZZGEMGREEN2, + S_ARTIPUZZGEMBLUE1, + S_ARTIPUZZGEMBLUE2, + S_ARTIPUZZBOOK1, + S_ARTIPUZZBOOK2, + S_ARTIPUZZSKULL2, + S_ARTIPUZZFWEAPON, + S_ARTIPUZZCWEAPON, + S_ARTIPUZZMWEAPON, + S_ARTIPUZZGEAR_1, + S_ARTIPUZZGEAR_2, + S_ARTIPUZZGEAR_3, + S_ARTIPUZZGEAR_4, + S_ARTIPUZZGEAR_5, + S_ARTIPUZZGEAR_6, + S_ARTIPUZZGEAR_7, + S_ARTIPUZZGEAR_8, + S_ARTIPUZZGEAR2_1, + S_ARTIPUZZGEAR2_2, + S_ARTIPUZZGEAR2_3, + S_ARTIPUZZGEAR2_4, + S_ARTIPUZZGEAR2_5, + S_ARTIPUZZGEAR2_6, + S_ARTIPUZZGEAR2_7, + S_ARTIPUZZGEAR2_8, + S_ARTIPUZZGEAR3_1, + S_ARTIPUZZGEAR3_2, + S_ARTIPUZZGEAR3_3, + S_ARTIPUZZGEAR3_4, + S_ARTIPUZZGEAR3_5, + S_ARTIPUZZGEAR3_6, + S_ARTIPUZZGEAR3_7, + S_ARTIPUZZGEAR3_8, + S_ARTIPUZZGEAR4_1, + S_ARTIPUZZGEAR4_2, + S_ARTIPUZZGEAR4_3, + S_ARTIPUZZGEAR4_4, + S_ARTIPUZZGEAR4_5, + S_ARTIPUZZGEAR4_6, + S_ARTIPUZZGEAR4_7, + S_ARTIPUZZGEAR4_8, + S_ARTI_TRCH1, + S_ARTI_TRCH2, + S_ARTI_TRCH3, + S_FIREBOMB1, + S_FIREBOMB2, + S_FIREBOMB3, + S_FIREBOMB4, + S_FIREBOMB5, + S_FIREBOMB6, + S_FIREBOMB7, + S_FIREBOMB8, + S_FIREBOMB9, + S_FIREBOMB10, + S_FIREBOMB11, + S_ARTI_ATLP1, + S_ARTI_ATLP2, + S_ARTI_ATLP3, + S_ARTI_ATLP4, + S_ARTI_PSBG1, + S_POISONBAG1, + S_POISONBAG2, + S_POISONBAG3, + S_POISONBAG4, + S_POISONCLOUD1, + S_POISONCLOUD2, + S_POISONCLOUD3, + S_POISONCLOUD4, + S_POISONCLOUD5, + S_POISONCLOUD6, + S_POISONCLOUD7, + S_POISONCLOUD8, + S_POISONCLOUD9, + S_POISONCLOUD10, + S_POISONCLOUD11, + S_POISONCLOUD12, + S_POISONCLOUD13, + S_POISONCLOUD14, + S_POISONCLOUD15, + S_POISONCLOUD16, + S_POISONCLOUD17, + S_POISONCLOUD18, + S_POISONCLOUD_X1, + S_POISONCLOUD_X2, + S_POISONCLOUD_X3, + S_POISONCLOUD_X4, + S_THROWINGBOMB1, + S_THROWINGBOMB2, + S_THROWINGBOMB3, + S_THROWINGBOMB4, + S_THROWINGBOMB5, + S_THROWINGBOMB6, + S_THROWINGBOMB7, + S_THROWINGBOMB8, + S_THROWINGBOMB9, + S_THROWINGBOMB10, + S_THROWINGBOMB11, + S_THROWINGBOMB12, + S_THROWINGBOMB_X1, + S_THROWINGBOMB_X2, + S_THROWINGBOMB_X3, + S_THROWINGBOMB_X4, + S_THROWINGBOMB_X5, + S_THROWINGBOMB_X6, + S_THROWINGBOMB_X7, + S_THROWINGBOMB_X8, + S_ARTI_BOOTS1, + S_ARTI_BOOTS2, + S_ARTI_BOOTS3, + S_ARTI_BOOTS4, + S_ARTI_BOOTS5, + S_ARTI_BOOTS6, + S_ARTI_BOOTS7, + S_ARTI_BOOTS8, + S_ARTI_MANA, + S_ARTI_ARMOR1, + S_ARTI_ARMOR2, + S_ARTI_ARMOR3, + S_ARTI_ARMOR4, + S_ARTI_ARMOR5, + S_ARTI_ARMOR6, + S_ARTI_ARMOR7, + S_ARTI_ARMOR8, + S_ARTI_BLAST1, + S_ARTI_BLAST2, + S_ARTI_BLAST3, + S_ARTI_BLAST4, + S_ARTI_BLAST5, + S_ARTI_BLAST6, + S_ARTI_BLAST7, + S_ARTI_BLAST8, + S_ARTI_HEALRAD1, + S_ARTI_HEALRAD2, + S_ARTI_HEALRAD3, + S_ARTI_HEALRAD4, + S_ARTI_HEALRAD5, + S_ARTI_HEALRAD6, + S_ARTI_HEALRAD7, + S_ARTI_HEALRAD8, + S_ARTI_HEALRAD9, + S_ARTI_HEALRAD0, + S_ARTI_HEALRADA, + S_ARTI_HEALRADB, + S_ARTI_HEALRADC, + S_ARTI_HEALRADD, + S_ARTI_HEALRADE, + S_ARTI_HEALRADF, + S_SPLASH1, + S_SPLASH2, + S_SPLASH3, + S_SPLASH4, + S_SPLASHX, + S_SPLASHBASE1, + S_SPLASHBASE2, + S_SPLASHBASE3, + S_SPLASHBASE4, + S_SPLASHBASE5, + S_SPLASHBASE6, + S_SPLASHBASE7, + S_LAVASPLASH1, + S_LAVASPLASH2, + S_LAVASPLASH3, + S_LAVASPLASH4, + S_LAVASPLASH5, + S_LAVASPLASH6, + S_LAVASMOKE1, + S_LAVASMOKE2, + S_LAVASMOKE3, + S_LAVASMOKE4, + S_LAVASMOKE5, + S_SLUDGECHUNK1, + S_SLUDGECHUNK2, + S_SLUDGECHUNK3, + S_SLUDGECHUNK4, + S_SLUDGECHUNKX, + S_SLUDGESPLASH1, + S_SLUDGESPLASH2, + S_SLUDGESPLASH3, + S_SLUDGESPLASH4, + S_ZWINGEDSTATUE1, + S_ZROCK1_1, + S_ZROCK2_1, + S_ZROCK3_1, + S_ZROCK4_1, + S_ZCHANDELIER1, + S_ZCHANDELIER2, + S_ZCHANDELIER3, + S_ZCHANDELIER_U, + S_ZTREEDEAD1, + S_ZTREE, + S_ZTREEDESTRUCTIBLE1, + S_ZTREEDES_D1, + S_ZTREEDES_D2, + S_ZTREEDES_D3, + S_ZTREEDES_D4, + S_ZTREEDES_D5, + S_ZTREEDES_D6, + S_ZTREEDES_X1, + S_ZTREEDES_X2, + S_ZTREEDES_X3, + S_ZTREEDES_X4, + S_ZTREEDES_X5, + S_ZTREEDES_X6, + S_ZTREEDES_X7, + S_ZTREEDES_X8, + S_ZTREEDES_X9, + S_ZTREEDES_X10, + S_ZTREESWAMP182_1, + S_ZTREESWAMP172_1, + S_ZSTUMPBURNED1, + S_ZSTUMPBARE1, + S_ZSTUMPSWAMP1_1, + S_ZSTUMPSWAMP2_1, + S_ZSHROOMLARGE1_1, + S_ZSHROOMLARGE2_1, + S_ZSHROOMLARGE3_1, + S_ZSHROOMSMALL1_1, + S_ZSHROOMSMALL2_1, + S_ZSHROOMSMALL3_1, + S_ZSHROOMSMALL4_1, + S_ZSHROOMSMALL5_1, + S_ZSTALAGMITEPILLAR1, + S_ZSTALAGMITELARGE1, + S_ZSTALAGMITEMEDIUM1, + S_ZSTALAGMITESMALL1, + S_ZSTALACTITELARGE1, + S_ZSTALACTITEMEDIUM1, + S_ZSTALACTITESMALL1, + S_ZMOSSCEILING1_1, + S_ZMOSSCEILING2_1, + S_ZSWAMPVINE1, + S_ZCORPSEKABOB1, + S_ZCORPSESLEEPING1, + S_ZTOMBSTONERIP1, + S_ZTOMBSTONESHANE1, + S_ZTOMBSTONEBIGCROSS1, + S_ZTOMBSTONEBRIANR1, + S_ZTOMBSTONECROSSCIRCLE1, + S_ZTOMBSTONESMALLCROSS1, + S_ZTOMBSTONEBRIANP1, + S_CORPSEHANGING_1, + S_ZSTATUEGARGOYLEGREENTALL_1, + S_ZSTATUEGARGOYLEBLUETALL_1, + S_ZSTATUEGARGOYLEGREENSHORT_1, + S_ZSTATUEGARGOYLEBLUESHORT_1, + S_ZSTATUEGARGOYLESTRIPETALL_1, + S_ZSTATUEGARGOYLEDARKREDTALL_1, + S_ZSTATUEGARGOYLEREDTALL_1, + S_ZSTATUEGARGOYLETANTALL_1, + S_ZSTATUEGARGOYLERUSTTALL_1, + S_ZSTATUEGARGOYLEDARKREDSHORT_1, + S_ZSTATUEGARGOYLEREDSHORT_1, + S_ZSTATUEGARGOYLETANSHORT_1, + S_ZSTATUEGARGOYLERUSTSHORT_1, + S_ZBANNERTATTERED_1, + S_ZTREELARGE1, + S_ZTREELARGE2, + S_ZTREEGNARLED1, + S_ZTREEGNARLED2, + S_ZLOG, + S_ZSTALACTITEICELARGE, + S_ZSTALACTITEICEMEDIUM, + S_ZSTALACTITEICESMALL, + S_ZSTALACTITEICETINY, + S_ZSTALAGMITEICELARGE, + S_ZSTALAGMITEICEMEDIUM, + S_ZSTALAGMITEICESMALL, + S_ZSTALAGMITEICETINY, + S_ZROCKBROWN1, + S_ZROCKBROWN2, + S_ZROCKBLACK, + S_ZRUBBLE1, + S_ZRUBBLE2, + S_ZRUBBLE3, + S_ZVASEPILLAR, + S_ZPOTTERY1, + S_ZPOTTERY2, + S_ZPOTTERY3, + S_ZPOTTERY_EXPLODE, + S_POTTERYBIT_1, + S_POTTERYBIT_2, + S_POTTERYBIT_3, + S_POTTERYBIT_4, + S_POTTERYBIT_5, + S_POTTERYBIT_EX0, + S_POTTERYBIT_EX1, + S_POTTERYBIT_EX1_2, + S_POTTERYBIT_EX2, + S_POTTERYBIT_EX2_2, + S_POTTERYBIT_EX3, + S_POTTERYBIT_EX3_2, + S_POTTERYBIT_EX4, + S_POTTERYBIT_EX4_2, + S_POTTERYBIT_EX5, + S_POTTERYBIT_EX5_2, + S_ZCORPSELYNCHED1, + S_ZCORPSELYNCHED2, + S_ZCORPSESITTING, + S_ZCORPSESITTING_X, + S_CORPSEBIT_1, + S_CORPSEBIT_2, + S_CORPSEBIT_3, + S_CORPSEBIT_4, + S_CORPSEBLOODDRIP, + S_CORPSEBLOODDRIP_X1, + S_CORPSEBLOODDRIP_X2, + S_CORPSEBLOODDRIP_X3, + S_CORPSEBLOODDRIP_X4, + S_BLOODPOOL, + S_ZCANDLE1, + S_ZCANDLE2, + S_ZCANDLE3, + S_ZLEAFSPAWNER, + S_LEAF1_1, + S_LEAF1_2, + S_LEAF1_3, + S_LEAF1_4, + S_LEAF1_5, + S_LEAF1_6, + S_LEAF1_7, + S_LEAF1_8, + S_LEAF1_9, + S_LEAF1_10, + S_LEAF1_11, + S_LEAF1_12, + S_LEAF1_13, + S_LEAF1_14, + S_LEAF1_15, + S_LEAF1_16, + S_LEAF1_17, + S_LEAF1_18, + S_LEAF_X1, + S_LEAF2_1, + S_LEAF2_2, + S_LEAF2_3, + S_LEAF2_4, + S_LEAF2_5, + S_LEAF2_6, + S_LEAF2_7, + S_LEAF2_8, + S_LEAF2_9, + S_LEAF2_10, + S_LEAF2_11, + S_LEAF2_12, + S_LEAF2_13, + S_LEAF2_14, + S_LEAF2_15, + S_LEAF2_16, + S_LEAF2_17, + S_LEAF2_18, + S_ZTWINEDTORCH_1, + S_ZTWINEDTORCH_2, + S_ZTWINEDTORCH_3, + S_ZTWINEDTORCH_4, + S_ZTWINEDTORCH_5, + S_ZTWINEDTORCH_6, + S_ZTWINEDTORCH_7, + S_ZTWINEDTORCH_8, + S_ZTWINEDTORCH_UNLIT, + S_BRIDGE1, + S_BRIDGE2, + S_BRIDGE3, + S_FREE_BRIDGE1, + S_FREE_BRIDGE2, + S_BBALL1, + S_BBALL2, + S_ZWALLTORCH1, + S_ZWALLTORCH2, + S_ZWALLTORCH3, + S_ZWALLTORCH4, + S_ZWALLTORCH5, + S_ZWALLTORCH6, + S_ZWALLTORCH7, + S_ZWALLTORCH8, + S_ZWALLTORCH_U, + S_ZBARREL1, + S_ZSHRUB1, + S_ZSHRUB1_DIE, + S_ZSHRUB1_X1, + S_ZSHRUB1_X2, + S_ZSHRUB1_X3, + S_ZSHRUB2, + S_ZSHRUB2_DIE, + S_ZSHRUB2_X1, + S_ZSHRUB2_X2, + S_ZSHRUB2_X3, + S_ZSHRUB2_X4, + S_ZBUCKET1, + S_ZPOISONSHROOM1, + S_ZPOISONSHROOM_P1, + S_ZPOISONSHROOM_P2, + S_ZPOISONSHROOM_X1, + S_ZPOISONSHROOM_X2, + S_ZPOISONSHROOM_X3, + S_ZPOISONSHROOM_X4, + S_ZFIREBULL1, + S_ZFIREBULL2, + S_ZFIREBULL3, + S_ZFIREBULL4, + S_ZFIREBULL5, + S_ZFIREBULL6, + S_ZFIREBULL7, + S_ZFIREBULL_DEATH, + S_ZFIREBULL_DEATH2, + S_ZFIREBULL_U, + S_ZFIREBULL_BIRTH, + S_ZFIREBULL_BIRTH2, + S_ZFIRETHING1, + S_ZFIRETHING2, + S_ZFIRETHING3, + S_ZFIRETHING4, + S_ZFIRETHING5, + S_ZFIRETHING6, + S_ZFIRETHING7, + S_ZFIRETHING8, + S_ZFIRETHING9, + S_ZBRASSTORCH1, + S_ZBRASSTORCH2, + S_ZBRASSTORCH3, + S_ZBRASSTORCH4, + S_ZBRASSTORCH5, + S_ZBRASSTORCH6, + S_ZBRASSTORCH7, + S_ZBRASSTORCH8, + S_ZBRASSTORCH9, + S_ZBRASSTORCH10, + S_ZBRASSTORCH11, + S_ZBRASSTORCH12, + S_ZBRASSTORCH13, + S_ZSUITOFARMOR, + S_ZSUITOFARMOR_X1, + S_ZARMORCHUNK1, + S_ZARMORCHUNK2, + S_ZARMORCHUNK3, + S_ZARMORCHUNK4, + S_ZARMORCHUNK5, + S_ZARMORCHUNK6, + S_ZARMORCHUNK7, + S_ZARMORCHUNK8, + S_ZARMORCHUNK9, + S_ZARMORCHUNK10, + S_ZBELL, + S_ZBELL_X1, + S_ZBELL_X2, + S_ZBELL_X3, + S_ZBELL_X4, + S_ZBELL_X5, + S_ZBELL_X6, + S_ZBELL_X7, + S_ZBELL_X8, + S_ZBELL_X9, + S_ZBELL_X10, + S_ZBELL_X11, + S_ZBELL_X12, + S_ZBELL_X13, + S_ZBELL_X14, + S_ZBELL_X15, + S_ZBELL_X16, + S_ZBELL_X17, + S_ZBELL_X18, + S_ZBELL_X19, + S_ZBELL_X20, + S_ZBELL_X21, + S_ZBELL_X22, + S_ZBELL_X23, + S_ZBELL_X24, + S_ZBELL_X25, + S_ZBELL_X26, + S_ZBELL_X27, + S_ZBELL_X28, + S_ZBELL_X29, + S_ZBELL_X30, + S_ZBELL_X31, + S_ZBELL_X32, + S_ZBELL_X33, + S_ZBELL_X34, + S_ZBELL_X35, + S_ZBELL_X36, + S_ZBELL_X37, + S_ZBELL_X38, + S_ZBELL_X39, + S_ZBELL_X40, + S_ZBELL_X41, + S_ZBELL_X42, + S_ZBELL_X43, + S_ZBELL_X44, + S_ZBELL_X45, + S_ZBELL_X46, + S_ZBELL_X47, + S_ZBLUE_CANDLE1, + S_ZBLUE_CANDLE2, + S_ZBLUE_CANDLE3, + S_ZBLUE_CANDLE4, + S_ZBLUE_CANDLE5, + S_ZIRON_MAIDEN, + S_ZXMAS_TREE, + S_ZXMAS_TREE_DIE, + S_ZXMAS_TREE_X1, + S_ZXMAS_TREE_X2, + S_ZXMAS_TREE_X3, + S_ZXMAS_TREE_X4, + S_ZXMAS_TREE_X5, + S_ZXMAS_TREE_X6, + S_ZXMAS_TREE_X7, + S_ZXMAS_TREE_X8, + S_ZXMAS_TREE_X9, + S_ZXMAS_TREE_X10, + S_ZCAULDRON1, + S_ZCAULDRON2, + S_ZCAULDRON3, + S_ZCAULDRON4, + S_ZCAULDRON5, + S_ZCAULDRON6, + S_ZCAULDRON7, + S_ZCAULDRON_U, + S_ZCHAINBIT32, + S_ZCHAINBIT64, + S_ZCHAINEND_HEART, + S_ZCHAINEND_HOOK1, + S_ZCHAINEND_HOOK2, + S_ZCHAINEND_SPIKE, + S_ZCHAINEND_SKULL, + S_TABLE_SHIT1, + S_TABLE_SHIT2, + S_TABLE_SHIT3, + S_TABLE_SHIT4, + S_TABLE_SHIT5, + S_TABLE_SHIT6, + S_TABLE_SHIT7, + S_TABLE_SHIT8, + S_TABLE_SHIT9, + S_TABLE_SHIT10, + S_TFOG1, + S_TFOG2, + S_TFOG3, + S_TFOG4, + S_TFOG5, + S_TFOG6, + S_TFOG7, + S_TFOG8, + S_TFOG9, + S_TFOG10, + S_TFOG11, + S_TFOG12, + S_TFOG13, + S_TELESMOKE1, + S_TELESMOKE2, + S_TELESMOKE3, + S_TELESMOKE4, + S_TELESMOKE5, + S_TELESMOKE6, + S_TELESMOKE7, + S_TELESMOKE8, + S_TELESMOKE9, + S_TELESMOKE10, + S_TELESMOKE11, + S_TELESMOKE12, + S_TELESMOKE13, + S_TELESMOKE14, + S_TELESMOKE15, + S_TELESMOKE16, + S_TELESMOKE17, + S_TELESMOKE18, + S_TELESMOKE19, + S_TELESMOKE20, + S_TELESMOKE21, + S_TELESMOKE22, + S_TELESMOKE23, + S_TELESMOKE24, + S_TELESMOKE25, + S_TELESMOKE26, + S_LIGHTDONE, + S_PUNCHREADY, + S_PUNCHDOWN, + S_PUNCHUP, + S_PUNCHATK1_1, + S_PUNCHATK1_2, + S_PUNCHATK1_3, + S_PUNCHATK1_4, + S_PUNCHATK1_5, + S_PUNCHATK2_1, + S_PUNCHATK2_2, + S_PUNCHATK2_3, + S_PUNCHATK2_4, + S_PUNCHATK2_5, + S_PUNCHATK2_6, + S_PUNCHATK2_7, + S_PUNCHATK2_8, + S_PUNCHATK2_9, + S_PUNCHPUFF1, + S_PUNCHPUFF2, + S_PUNCHPUFF3, + S_PUNCHPUFF4, + S_PUNCHPUFF5, + S_AXE, + S_FAXEREADY, + S_FAXEDOWN, + S_FAXEUP, + S_FAXEATK_1, + S_FAXEATK_2, + S_FAXEATK_3, + S_FAXEATK_4, + S_FAXEATK_5, + S_FAXEATK_6, + S_FAXEATK_7, + S_FAXEATK_8, + S_FAXEATK_9, + S_FAXEATK_10, + S_FAXEATK_11, + S_FAXEATK_12, + S_FAXEATK_13, + S_FAXEREADY_G, + S_FAXEREADY_G1, + S_FAXEREADY_G2, + S_FAXEREADY_G3, + S_FAXEREADY_G4, + S_FAXEREADY_G5, + S_FAXEDOWN_G, + S_FAXEUP_G, + S_FAXEATK_G1, + S_FAXEATK_G2, + S_FAXEATK_G3, + S_FAXEATK_G4, + S_FAXEATK_G5, + S_FAXEATK_G6, + S_FAXEATK_G7, + S_FAXEATK_G8, + S_FAXEATK_G9, + S_FAXEATK_G10, + S_FAXEATK_G11, + S_FAXEATK_G12, + S_FAXEATK_G13, + S_AXEPUFF_GLOW1, + S_AXEPUFF_GLOW2, + S_AXEPUFF_GLOW3, + S_AXEPUFF_GLOW4, + S_AXEPUFF_GLOW5, + S_AXEPUFF_GLOW6, + S_AXEPUFF_GLOW7, + S_AXEBLOOD1, + S_AXEBLOOD2, + S_AXEBLOOD3, + S_AXEBLOOD4, + S_AXEBLOOD5, + S_AXEBLOOD6, + S_HAMM, + S_FHAMMERREADY, + S_FHAMMERDOWN, + S_FHAMMERUP, + S_FHAMMERATK_1, + S_FHAMMERATK_2, + S_FHAMMERATK_3, + S_FHAMMERATK_4, + S_FHAMMERATK_5, + S_FHAMMERATK_6, + S_FHAMMERATK_7, + S_FHAMMERATK_8, + S_FHAMMERATK_9, + S_FHAMMERATK_10, + S_FHAMMERATK_11, + S_FHAMMERATK_12, + S_HAMMER_MISSILE_1, + S_HAMMER_MISSILE_2, + S_HAMMER_MISSILE_3, + S_HAMMER_MISSILE_4, + S_HAMMER_MISSILE_5, + S_HAMMER_MISSILE_6, + S_HAMMER_MISSILE_7, + S_HAMMER_MISSILE_8, + S_HAMMER_MISSILE_X1, + S_HAMMER_MISSILE_X2, + S_HAMMER_MISSILE_X3, + S_HAMMER_MISSILE_X4, + S_HAMMER_MISSILE_X5, + S_HAMMER_MISSILE_X6, + S_HAMMER_MISSILE_X7, + S_HAMMER_MISSILE_X8, + S_HAMMER_MISSILE_X9, + S_HAMMER_MISSILE_X10, + S_HAMMERPUFF1, + S_HAMMERPUFF2, + S_HAMMERPUFF3, + S_HAMMERPUFF4, + S_HAMMERPUFF5, + S_FSWORDREADY, + S_FSWORDREADY1, + S_FSWORDREADY2, + S_FSWORDREADY3, + S_FSWORDREADY4, + S_FSWORDREADY5, + S_FSWORDREADY6, + S_FSWORDREADY7, + S_FSWORDREADY8, + S_FSWORDREADY9, + S_FSWORDREADY10, + S_FSWORDREADY11, + S_FSWORDDOWN, + S_FSWORDUP, + S_FSWORDATK_1, + S_FSWORDATK_2, + S_FSWORDATK_3, + S_FSWORDATK_4, + S_FSWORDATK_5, + S_FSWORDATK_6, + S_FSWORDATK_7, + S_FSWORDATK_8, + S_FSWORDATK_9, + S_FSWORDATK_10, + S_FSWORDATK_11, + S_FSWORDATK_12, + S_FSWORD_MISSILE1, + S_FSWORD_MISSILE2, + S_FSWORD_MISSILE3, + S_FSWORD_MISSILE_X1, + S_FSWORD_MISSILE_X2, + S_FSWORD_MISSILE_X3, + S_FSWORD_MISSILE_X4, + S_FSWORD_MISSILE_X5, + S_FSWORD_MISSILE_X6, + S_FSWORD_MISSILE_X7, + S_FSWORD_MISSILE_X8, + S_FSWORD_MISSILE_X9, + S_FSWORD_MISSILE_X10, + S_FSWORD_FLAME1, + S_FSWORD_FLAME2, + S_FSWORD_FLAME3, + S_FSWORD_FLAME4, + S_FSWORD_FLAME5, + S_FSWORD_FLAME6, + S_FSWORD_FLAME7, + S_FSWORD_FLAME8, + S_FSWORD_FLAME9, + S_FSWORD_FLAME10, + S_CMACEREADY, + S_CMACEDOWN, + S_CMACEUP, + S_CMACEATK_1, + S_CMACEATK_2, + S_CMACEATK_3, + S_CMACEATK_4, + S_CMACEATK_5, + S_CMACEATK_6, + S_CMACEATK_7, + S_CMACEATK_8, + S_CMACEATK_9, + S_CMACEATK_10, + S_CMACEATK_11, + S_CMACEATK_12, + S_CMACEATK_13, + S_CMACEATK_14, + S_CMACEATK_15, + S_CMACEATK_16, + S_CMACEATK_17, + S_CSTAFF, + S_CSTAFFREADY, + S_CSTAFFREADY1, + S_CSTAFFREADY2, + S_CSTAFFREADY3, + S_CSTAFFREADY4, + S_CSTAFFREADY5, + S_CSTAFFREADY6, + S_CSTAFFREADY7, + S_CSTAFFREADY8, + S_CSTAFFREADY9, + S_CSTAFFBLINK1, + S_CSTAFFBLINK2, + S_CSTAFFBLINK3, + S_CSTAFFBLINK4, + S_CSTAFFBLINK5, + S_CSTAFFBLINK6, + S_CSTAFFBLINK7, + S_CSTAFFBLINK8, + S_CSTAFFBLINK9, + S_CSTAFFBLINK10, + S_CSTAFFBLINK11, + S_CSTAFFDOWN, + S_CSTAFFDOWN2, + S_CSTAFFDOWN3, + S_CSTAFFUP, + S_CSTAFFATK_1, + S_CSTAFFATK_2, + S_CSTAFFATK_3, + S_CSTAFFATK_4, + S_CSTAFFATK_5, + S_CSTAFFATK_6, + S_CSTAFFATK2_1, + S_CSTAFF_MISSILE1, + S_CSTAFF_MISSILE2, + S_CSTAFF_MISSILE3, + S_CSTAFF_MISSILE4, + S_CSTAFF_MISSILE_X1, + S_CSTAFF_MISSILE_X2, + S_CSTAFF_MISSILE_X3, + S_CSTAFF_MISSILE_X4, + S_CSTAFFPUFF1, + S_CSTAFFPUFF2, + S_CSTAFFPUFF3, + S_CSTAFFPUFF4, + S_CSTAFFPUFF5, + S_CFLAME1, + S_CFLAME2, + S_CFLAME3, + S_CFLAME4, + S_CFLAME5, + S_CFLAME6, + S_CFLAME7, + S_CFLAME8, + S_CFLAMEREADY1, + S_CFLAMEREADY2, + S_CFLAMEREADY3, + S_CFLAMEREADY4, + S_CFLAMEREADY5, + S_CFLAMEREADY6, + S_CFLAMEREADY7, + S_CFLAMEREADY8, + S_CFLAMEREADY9, + S_CFLAMEREADY10, + S_CFLAMEREADY11, + S_CFLAMEREADY12, + S_CFLAMEDOWN, + S_CFLAMEUP, + S_CFLAMEATK_1, + S_CFLAMEATK_2, + S_CFLAMEATK_3, + S_CFLAMEATK_4, + S_CFLAMEATK_5, + S_CFLAMEATK_6, + S_CFLAMEATK_7, + S_CFLAMEATK_8, + S_CFLAMEFLOOR1, + S_CFLAMEFLOOR2, + S_CFLAMEFLOOR3, + S_FLAMEPUFF1, + S_FLAMEPUFF2, + S_FLAMEPUFF3, + S_FLAMEPUFF4, + S_FLAMEPUFF5, + S_FLAMEPUFF6, + S_FLAMEPUFF7, + S_FLAMEPUFF8, + S_FLAMEPUFF9, + S_FLAMEPUFF10, + S_FLAMEPUFF11, + S_FLAMEPUFF12, + S_FLAMEPUFF13, + S_FLAMEPUFF2_1, + S_FLAMEPUFF2_2, + S_FLAMEPUFF2_3, + S_FLAMEPUFF2_4, + S_FLAMEPUFF2_5, + S_FLAMEPUFF2_6, + S_FLAMEPUFF2_7, + S_FLAMEPUFF2_8, + S_FLAMEPUFF2_9, + S_FLAMEPUFF2_10, + S_FLAMEPUFF2_11, + S_FLAMEPUFF2_12, + S_FLAMEPUFF2_13, + S_FLAMEPUFF2_14, + S_FLAMEPUFF2_15, + S_FLAMEPUFF2_16, + S_FLAMEPUFF2_17, + S_FLAMEPUFF2_18, + S_FLAMEPUFF2_19, + S_FLAMEPUFF2_20, + S_CIRCLE_FLAME1, + S_CIRCLE_FLAME2, + S_CIRCLE_FLAME3, + S_CIRCLE_FLAME4, + S_CIRCLE_FLAME5, + S_CIRCLE_FLAME6, + S_CIRCLE_FLAME7, + S_CIRCLE_FLAME8, + S_CIRCLE_FLAME9, + S_CIRCLE_FLAME10, + S_CIRCLE_FLAME11, + S_CIRCLE_FLAME12, + S_CIRCLE_FLAME13, + S_CIRCLE_FLAME14, + S_CIRCLE_FLAME15, + S_CIRCLE_FLAME16, + S_CIRCLE_FLAME_X1, + S_CIRCLE_FLAME_X2, + S_CIRCLE_FLAME_X3, + S_CIRCLE_FLAME_X4, + S_CIRCLE_FLAME_X5, + S_CIRCLE_FLAME_X6, + S_CIRCLE_FLAME_X7, + S_CIRCLE_FLAME_X8, + S_CIRCLE_FLAME_X9, + S_CIRCLE_FLAME_X10, + S_CFLAME_MISSILE1, + S_CFLAME_MISSILE2, + S_CFLAME_MISSILE_X, + S_CHOLYREADY, + S_CHOLYDOWN, + S_CHOLYUP, + S_CHOLYATK_1, + S_CHOLYATK_2, + S_CHOLYATK_3, + S_CHOLYATK_4, + S_CHOLYATK_5, + S_CHOLYATK_6, + S_CHOLYATK_7, + S_CHOLYATK_8, + S_CHOLYATK_9, + S_HOLY_FX1, + S_HOLY_FX2, + S_HOLY_FX3, + S_HOLY_FX4, + S_HOLY_FX_X1, + S_HOLY_FX_X2, + S_HOLY_FX_X3, + S_HOLY_FX_X4, + S_HOLY_FX_X5, + S_HOLY_FX_X6, + S_HOLY_TAIL1, + S_HOLY_TAIL2, + S_HOLY_PUFF1, + S_HOLY_PUFF2, + S_HOLY_PUFF3, + S_HOLY_PUFF4, + S_HOLY_PUFF5, + S_HOLY_MISSILE1, + S_HOLY_MISSILE2, + S_HOLY_MISSILE3, + S_HOLY_MISSILE4, + S_HOLY_MISSILE_X, + S_HOLY_MISSILE_P1, + S_HOLY_MISSILE_P2, + S_HOLY_MISSILE_P3, + S_HOLY_MISSILE_P4, + S_HOLY_MISSILE_P5, + S_MWANDREADY, + S_MWANDDOWN, + S_MWANDUP, + S_MWANDATK_1, + S_MWANDATK_2, + S_MWANDATK_3, + S_MWANDATK_4, + S_MWANDPUFF1, + S_MWANDPUFF2, + S_MWANDPUFF3, + S_MWANDPUFF4, + S_MWANDPUFF5, + S_MWANDSMOKE1, + S_MWANDSMOKE2, + S_MWANDSMOKE3, + S_MWANDSMOKE4, + S_MWAND_MISSILE1, + S_MWAND_MISSILE2, + S_MW_LIGHTNING1, + S_MW_LIGHTNING2, + S_MW_LIGHTNING3, + S_MW_LIGHTNING4, + S_MW_LIGHTNING5, + S_MW_LIGHTNING6, + S_MW_LIGHTNING7, + S_MW_LIGHTNING8, + S_MLIGHTNINGREADY, + S_MLIGHTNINGREADY2, + S_MLIGHTNINGREADY3, + S_MLIGHTNINGREADY4, + S_MLIGHTNINGREADY5, + S_MLIGHTNINGREADY6, + S_MLIGHTNINGREADY7, + S_MLIGHTNINGREADY8, + S_MLIGHTNINGREADY9, + S_MLIGHTNINGREADY10, + S_MLIGHTNINGREADY11, + S_MLIGHTNINGREADY12, + S_MLIGHTNINGREADY13, + S_MLIGHTNINGREADY14, + S_MLIGHTNINGREADY15, + S_MLIGHTNINGREADY16, + S_MLIGHTNINGREADY17, + S_MLIGHTNINGREADY18, + S_MLIGHTNINGREADY19, + S_MLIGHTNINGREADY20, + S_MLIGHTNINGREADY21, + S_MLIGHTNINGREADY22, + S_MLIGHTNINGREADY23, + S_MLIGHTNINGREADY24, + S_MLIGHTNINGDOWN, + S_MLIGHTNINGUP, + S_MLIGHTNINGATK_1, + S_MLIGHTNINGATK_2, + S_MLIGHTNINGATK_3, + S_MLIGHTNINGATK_4, + S_MLIGHTNINGATK_5, + S_MLIGHTNINGATK_6, + S_MLIGHTNINGATK_7, + S_MLIGHTNINGATK_8, + S_MLIGHTNINGATK_9, + S_MLIGHTNINGATK_10, + S_MLIGHTNINGATK_11, + S_LIGHTNING_CEILING1, + S_LIGHTNING_CEILING2, + S_LIGHTNING_CEILING3, + S_LIGHTNING_CEILING4, + S_LIGHTNING_C_X1, + S_LIGHTNING_C_X2, + S_LIGHTNING_C_X3, + S_LIGHTNING_C_X4, + S_LIGHTNING_C_X5, + S_LIGHTNING_C_X6, + S_LIGHTNING_C_X7, + S_LIGHTNING_C_X8, + S_LIGHTNING_C_X9, + S_LIGHTNING_C_X10, + S_LIGHTNING_C_X11, + S_LIGHTNING_C_X12, + S_LIGHTNING_C_X13, + S_LIGHTNING_C_X14, + S_LIGHTNING_C_X15, + S_LIGHTNING_C_X16, + S_LIGHTNING_C_X17, + S_LIGHTNING_C_X18, + S_LIGHTNING_C_X19, + S_LIGHTNING_FLOOR1, + S_LIGHTNING_FLOOR2, + S_LIGHTNING_FLOOR3, + S_LIGHTNING_FLOOR4, + S_LIGHTNING_F_X1, + S_LIGHTNING_F_X2, + S_LIGHTNING_F_X3, + S_LIGHTNING_F_X4, + S_LIGHTNING_F_X5, + S_LIGHTNING_F_X6, + S_LIGHTNING_F_X7, + S_LIGHTNING_F_X8, + S_LIGHTNING_F_X9, + S_LIGHTNING_F_X10, + S_LIGHTNING_F_X11, + S_LIGHTNING_F_X12, + S_LIGHTNING_F_X13, + S_LIGHTNING_F_X14, + S_LIGHTNING_F_X15, + S_LIGHTNING_F_X16, + S_LIGHTNING_F_X17, + S_LIGHTNING_F_X18, + S_LIGHTNING_F_X19, + S_LIGHTNING_ZAP1, + S_LIGHTNING_ZAP2, + S_LIGHTNING_ZAP3, + S_LIGHTNING_ZAP4, + S_LIGHTNING_ZAP5, + S_LIGHTNING_ZAP_X1, + S_LIGHTNING_ZAP_X2, + S_LIGHTNING_ZAP_X3, + S_LIGHTNING_ZAP_X4, + S_LIGHTNING_ZAP_X5, + S_LIGHTNING_ZAP_X6, + S_LIGHTNING_ZAP_X7, + S_LIGHTNING_ZAP_X8, + S_MSTAFFREADY, + S_MSTAFFREADY2, + S_MSTAFFREADY3, + S_MSTAFFREADY4, + S_MSTAFFREADY5, + S_MSTAFFREADY6, + S_MSTAFFREADY7, + S_MSTAFFREADY8, + S_MSTAFFREADY9, + S_MSTAFFREADY10, + S_MSTAFFREADY11, + S_MSTAFFREADY12, + S_MSTAFFREADY13, + S_MSTAFFREADY14, + S_MSTAFFREADY15, + S_MSTAFFREADY16, + S_MSTAFFREADY17, + S_MSTAFFREADY18, + S_MSTAFFREADY19, + S_MSTAFFREADY20, + S_MSTAFFREADY21, + S_MSTAFFREADY22, + S_MSTAFFREADY23, + S_MSTAFFREADY24, + S_MSTAFFREADY25, + S_MSTAFFREADY26, + S_MSTAFFREADY27, + S_MSTAFFREADY28, + S_MSTAFFREADY29, + S_MSTAFFREADY30, + S_MSTAFFREADY31, + S_MSTAFFREADY32, + S_MSTAFFREADY33, + S_MSTAFFREADY34, + S_MSTAFFREADY35, + S_MSTAFFDOWN, + S_MSTAFFUP, + S_MSTAFFATK_1, + S_MSTAFFATK_2, + S_MSTAFFATK_3, + S_MSTAFFATK_4, + S_MSTAFFATK_5, + S_MSTAFFATK_6, + S_MSTAFFATK_7, + S_MSTAFF_FX1_1, + S_MSTAFF_FX1_2, + S_MSTAFF_FX1_3, + S_MSTAFF_FX1_4, + S_MSTAFF_FX1_5, + S_MSTAFF_FX1_6, + S_MSTAFF_FX_X1, + S_MSTAFF_FX_X2, + S_MSTAFF_FX_X3, + S_MSTAFF_FX_X4, + S_MSTAFF_FX_X5, + S_MSTAFF_FX_X6, + S_MSTAFF_FX_X7, + S_MSTAFF_FX_X8, + S_MSTAFF_FX_X9, + S_MSTAFF_FX_X10, + S_MSTAFF_FX2_1, + S_MSTAFF_FX2_2, + S_MSTAFF_FX2_3, + S_MSTAFF_FX2_4, + S_MSTAFF_FX2_X1, + S_MSTAFF_FX2_X2, + S_MSTAFF_FX2_X3, + S_MSTAFF_FX2_X4, + S_MSTAFF_FX2_X5, + S_FSWORD1, + S_FSWORD2, + S_FSWORD3, + S_CHOLY1, + S_CHOLY2, + S_CHOLY3, + S_MSTAFF1, + S_MSTAFF2, + S_MSTAFF3, + S_SNOUTREADY, + S_SNOUTDOWN, + S_SNOUTUP, + S_SNOUTATK1, + S_SNOUTATK2, + S_COS1, + S_COS2, + S_COS3, + S_CONEREADY, + S_CONEDOWN, + S_CONEUP, + S_CONEATK1_1, + S_CONEATK1_2, + S_CONEATK1_3, + S_CONEATK1_4, + S_CONEATK1_5, + S_CONEATK1_6, + S_CONEATK1_7, + S_CONEATK1_8, + S_SHARDFX1_1, + S_SHARDFX1_2, + S_SHARDFX1_3, + S_SHARDFX1_4, + S_SHARDFXE1_1, + S_SHARDFXE1_2, + S_SHARDFXE1_3, + S_SHARDFXE1_4, + S_SHARDFXE1_5, + S_BLOOD1, + S_BLOOD2, + S_BLOOD3, + S_BLOODSPLATTER1, + S_BLOODSPLATTER2, + S_BLOODSPLATTER3, + S_BLOODSPLATTERX, + S_GIBS1, + S_FPLAY, + S_FPLAY_RUN1, + S_FPLAY_RUN2, + S_FPLAY_RUN3, + S_FPLAY_RUN4, + S_FPLAY_ATK1, + S_FPLAY_ATK2, + S_FPLAY_PAIN, + S_FPLAY_PAIN2, + S_FPLAY_DIE1, + S_FPLAY_DIE2, + S_FPLAY_DIE3, + S_FPLAY_DIE4, + S_FPLAY_DIE5, + S_FPLAY_DIE6, + S_FPLAY_DIE7, + S_FPLAY_XDIE1, + S_FPLAY_XDIE2, + S_FPLAY_XDIE3, + S_FPLAY_XDIE4, + S_FPLAY_XDIE5, + S_FPLAY_XDIE6, + S_FPLAY_XDIE7, + S_FPLAY_XDIE8, + S_FPLAY_ICE, + S_FPLAY_ICE2, + S_PLAY_F_FDTH1, + S_PLAY_F_FDTH2, + S_PLAY_C_FDTH1, + S_PLAY_C_FDTH2, + S_PLAY_M_FDTH1, + S_PLAY_M_FDTH2, + S_PLAY_FDTH3, + S_PLAY_FDTH4, + S_PLAY_FDTH5, + S_PLAY_FDTH6, + S_PLAY_FDTH7, + S_PLAY_FDTH8, + S_PLAY_FDTH9, + S_PLAY_FDTH10, + S_PLAY_FDTH11, + S_PLAY_FDTH12, + S_PLAY_FDTH13, + S_PLAY_FDTH14, + S_PLAY_FDTH15, + S_PLAY_FDTH16, + S_PLAY_FDTH17, + S_PLAY_FDTH18, + S_PLAY_FDTH19, + S_PLAY_FDTH20, + S_BLOODYSKULL1, + S_BLOODYSKULL2, + S_BLOODYSKULL3, + S_BLOODYSKULL4, + S_BLOODYSKULL5, + S_BLOODYSKULL6, + S_BLOODYSKULL7, + S_BLOODYSKULLX1, + S_BLOODYSKULLX2, + S_PLAYER_SPEED1, + S_PLAYER_SPEED2, + S_ICECHUNK1, + S_ICECHUNK2, + S_ICECHUNK3, + S_ICECHUNK4, + S_ICECHUNK_HEAD, + S_ICECHUNK_HEAD2, + S_CPLAY, + S_CPLAY_RUN1, + S_CPLAY_RUN2, + S_CPLAY_RUN3, + S_CPLAY_RUN4, + S_CPLAY_ATK1, + S_CPLAY_ATK2, + S_CPLAY_ATK3, + S_CPLAY_PAIN, + S_CPLAY_PAIN2, + S_CPLAY_DIE1, + S_CPLAY_DIE2, + S_CPLAY_DIE3, + S_CPLAY_DIE4, + S_CPLAY_DIE5, + S_CPLAY_DIE6, + S_CPLAY_DIE7, + S_CPLAY_DIE8, + S_CPLAY_DIE9, + S_CPLAY_XDIE1, + S_CPLAY_XDIE2, + S_CPLAY_XDIE3, + S_CPLAY_XDIE4, + S_CPLAY_XDIE5, + S_CPLAY_XDIE6, + S_CPLAY_XDIE7, + S_CPLAY_XDIE8, + S_CPLAY_XDIE9, + S_CPLAY_XDIE10, + S_CPLAY_ICE, + S_CPLAY_ICE2, + S_MPLAY, + S_MPLAY_RUN1, + S_MPLAY_RUN2, + S_MPLAY_RUN3, + S_MPLAY_RUN4, + S_MPLAY_ATK1, + S_MPLAY_ATK2, + S_MPLAY_PAIN, + S_MPLAY_PAIN2, + S_MPLAY_DIE1, + S_MPLAY_DIE2, + S_MPLAY_DIE3, + S_MPLAY_DIE4, + S_MPLAY_DIE5, + S_MPLAY_DIE6, + S_MPLAY_DIE7, + S_MPLAY_XDIE1, + S_MPLAY_XDIE2, + S_MPLAY_XDIE3, + S_MPLAY_XDIE4, + S_MPLAY_XDIE5, + S_MPLAY_XDIE6, + S_MPLAY_XDIE7, + S_MPLAY_XDIE8, + S_MPLAY_XDIE9, + S_MPLAY_ICE, + S_MPLAY_ICE2, + S_PIGPLAY, + S_PIGPLAY_RUN1, + S_PIGPLAY_RUN2, + S_PIGPLAY_RUN3, + S_PIGPLAY_RUN4, + S_PIGPLAY_ATK1, + S_PIGPLAY_PAIN, + S_PIG_LOOK1, + S_PIG_WALK1, + S_PIG_WALK2, + S_PIG_WALK3, + S_PIG_WALK4, + S_PIG_PAIN, + S_PIG_ATK1, + S_PIG_ATK2, + S_PIG_DIE1, + S_PIG_DIE2, + S_PIG_DIE3, + S_PIG_DIE4, + S_PIG_DIE5, + S_PIG_DIE6, + S_PIG_DIE7, + S_PIG_DIE8, + S_PIG_ICE, + S_PIG_ICE2, + S_CENTAUR_LOOK1, + S_CENTAUR_LOOK2, + S_CENTAUR_WALK1, + S_CENTAUR_WALK2, + S_CENTAUR_WALK3, + S_CENTAUR_WALK4, + S_CENTAUR_ATK1, + S_CENTAUR_ATK2, + S_CENTAUR_ATK3, + S_CENTAUR_MISSILE1, + S_CENTAUR_MISSILE2, + S_CENTAUR_MISSILE3, + S_CENTAUR_MISSILE4, + S_CENTAUR_PAIN1, + S_CENTAUR_PAIN2, + S_CENTAUR_PAIN3, + S_CENTAUR_PAIN4, + S_CENTAUR_PAIN5, + S_CENTAUR_PAIN6, + S_CENTAUR_DEATH1, + S_CENTAUR_DEATH2, + S_CENTAUR_DEATH3, + S_CENTAUR_DEATH4, + S_CENTAUR_DEATH5, + S_CENTAUR_DEATH6, + S_CENTAUR_DEATH7, + S_CENTAUR_DEATH8, + S_CENTAUR_DEATH9, + S_CENTAUR_DEATH0, + S_CENTAUR_DEATH_X1, + S_CENTAUR_DEATH_X2, + S_CENTAUR_DEATH_X3, + S_CENTAUR_DEATH_X4, + S_CENTAUR_DEATH_X5, + S_CENTAUR_DEATH_X6, + S_CENTAUR_DEATH_X7, + S_CENTAUR_DEATH_X8, + S_CENTAUR_DEATH_X9, + S_CENTAUR_DEATH_X10, + S_CENTAUR_DEATH_X11, + S_CENTAUR_ICE, + S_CENTAUR_ICE2, + S_CENTAUR_FX1, + S_CENTAUR_FX_X1, + S_CENTAUR_FX_X2, + S_CENTAUR_FX_X3, + S_CENTAUR_FX_X4, + S_CENTAUR_FX_X5, + S_CENTAUR_SHIELD1, + S_CENTAUR_SHIELD2, + S_CENTAUR_SHIELD3, + S_CENTAUR_SHIELD4, + S_CENTAUR_SHIELD5, + S_CENTAUR_SHIELD6, + S_CENTAUR_SHIELD_X1, + S_CENTAUR_SHIELD_X2, + S_CENTAUR_SHIELD_X3, + S_CENTAUR_SHIELD_X4, + S_CENTAUR_SWORD1, + S_CENTAUR_SWORD2, + S_CENTAUR_SWORD3, + S_CENTAUR_SWORD4, + S_CENTAUR_SWORD5, + S_CENTAUR_SWORD6, + S_CENTAUR_SWORD7, + S_CENTAUR_SWORD_X1, + S_CENTAUR_SWORD_X2, + S_CENTAUR_SWORD_X3, + S_DEMN_LOOK1, + S_DEMN_LOOK2, + S_DEMN_CHASE1, + S_DEMN_CHASE2, + S_DEMN_CHASE3, + S_DEMN_CHASE4, + S_DEMN_ATK1_1, + S_DEMN_ATK1_2, + S_DEMN_ATK1_3, + S_DEMN_ATK2_1, + S_DEMN_ATK2_2, + S_DEMN_ATK2_3, + S_DEMN_PAIN1, + S_DEMN_PAIN2, + S_DEMN_DEATH1, + S_DEMN_DEATH2, + S_DEMN_DEATH3, + S_DEMN_DEATH4, + S_DEMN_DEATH5, + S_DEMN_DEATH6, + S_DEMN_DEATH7, + S_DEMN_DEATH8, + S_DEMN_DEATH9, + S_DEMN_XDEATH1, + S_DEMN_XDEATH2, + S_DEMN_XDEATH3, + S_DEMN_XDEATH4, + S_DEMN_XDEATH5, + S_DEMN_XDEATH6, + S_DEMN_XDEATH7, + S_DEMN_XDEATH8, + S_DEMN_XDEATH9, + S_DEMON_ICE, + S_DEMON_ICE2, + S_DEMONCHUNK1_1, + S_DEMONCHUNK1_2, + S_DEMONCHUNK1_3, + S_DEMONCHUNK1_4, + S_DEMONCHUNK2_1, + S_DEMONCHUNK2_2, + S_DEMONCHUNK2_3, + S_DEMONCHUNK2_4, + S_DEMONCHUNK3_1, + S_DEMONCHUNK3_2, + S_DEMONCHUNK3_3, + S_DEMONCHUNK3_4, + S_DEMONCHUNK4_1, + S_DEMONCHUNK4_2, + S_DEMONCHUNK4_3, + S_DEMONCHUNK4_4, + S_DEMONCHUNK5_1, + S_DEMONCHUNK5_2, + S_DEMONCHUNK5_3, + S_DEMONCHUNK5_4, + S_DEMONFX_MOVE1, + S_DEMONFX_MOVE2, + S_DEMONFX_MOVE3, + S_DEMONFX_BOOM1, + S_DEMONFX_BOOM2, + S_DEMONFX_BOOM3, + S_DEMONFX_BOOM4, + S_DEMONFX_BOOM5, + S_DEMN2_LOOK1, + S_DEMN2_LOOK2, + S_DEMN2_CHASE1, + S_DEMN2_CHASE2, + S_DEMN2_CHASE3, + S_DEMN2_CHASE4, + S_DEMN2_ATK1_1, + S_DEMN2_ATK1_2, + S_DEMN2_ATK1_3, + S_DEMN2_ATK2_1, + S_DEMN2_ATK2_2, + S_DEMN2_ATK2_3, + S_DEMN2_PAIN1, + S_DEMN2_PAIN2, + S_DEMN2_DEATH1, + S_DEMN2_DEATH2, + S_DEMN2_DEATH3, + S_DEMN2_DEATH4, + S_DEMN2_DEATH5, + S_DEMN2_DEATH6, + S_DEMN2_DEATH7, + S_DEMN2_DEATH8, + S_DEMN2_DEATH9, + S_DEMN2_XDEATH1, + S_DEMN2_XDEATH2, + S_DEMN2_XDEATH3, + S_DEMN2_XDEATH4, + S_DEMN2_XDEATH5, + S_DEMN2_XDEATH6, + S_DEMN2_XDEATH7, + S_DEMN2_XDEATH8, + S_DEMN2_XDEATH9, + S_DEMON2CHUNK1_1, + S_DEMON2CHUNK1_2, + S_DEMON2CHUNK1_3, + S_DEMON2CHUNK1_4, + S_DEMON2CHUNK2_1, + S_DEMON2CHUNK2_2, + S_DEMON2CHUNK2_3, + S_DEMON2CHUNK2_4, + S_DEMON2CHUNK3_1, + S_DEMON2CHUNK3_2, + S_DEMON2CHUNK3_3, + S_DEMON2CHUNK3_4, + S_DEMON2CHUNK4_1, + S_DEMON2CHUNK4_2, + S_DEMON2CHUNK4_3, + S_DEMON2CHUNK4_4, + S_DEMON2CHUNK5_1, + S_DEMON2CHUNK5_2, + S_DEMON2CHUNK5_3, + S_DEMON2CHUNK5_4, + S_DEMON2FX_MOVE1, + S_DEMON2FX_MOVE2, + S_DEMON2FX_MOVE3, + S_DEMON2FX_MOVE4, + S_DEMON2FX_MOVE5, + S_DEMON2FX_MOVE6, + S_DEMON2FX_BOOM1, + S_DEMON2FX_BOOM2, + S_DEMON2FX_BOOM3, + S_DEMON2FX_BOOM4, + S_DEMON2FX_BOOM5, + S_DEMON2FX_BOOM6, + S_WRAITH_RAISE1, + S_WRAITH_RAISE2, + S_WRAITH_RAISE3, + S_WRAITH_RAISE4, + S_WRAITH_RAISE5, + S_WRAITH_INIT1, + S_WRAITH_INIT2, + S_WRAITH_LOOK1, + S_WRAITH_LOOK2, + S_WRAITH_CHASE1, + S_WRAITH_CHASE2, + S_WRAITH_CHASE3, + S_WRAITH_CHASE4, + S_WRAITH_ATK1_1, + S_WRAITH_ATK1_2, + S_WRAITH_ATK1_3, + S_WRAITH_ATK2_1, + S_WRAITH_ATK2_2, + S_WRAITH_ATK2_3, + S_WRAITH_PAIN1, + S_WRAITH_PAIN2, + S_WRAITH_DEATH1_1, + S_WRAITH_DEATH1_2, + S_WRAITH_DEATH1_3, + S_WRAITH_DEATH1_4, + S_WRAITH_DEATH1_5, + S_WRAITH_DEATH1_6, + S_WRAITH_DEATH1_7, + S_WRAITH_DEATH1_8, + S_WRAITH_DEATH1_9, + S_WRAITH_DEATH1_0, + S_WRAITH_DEATH2_1, + S_WRAITH_DEATH2_2, + S_WRAITH_DEATH2_3, + S_WRAITH_DEATH2_4, + S_WRAITH_DEATH2_5, + S_WRAITH_DEATH2_6, + S_WRAITH_DEATH2_7, + S_WRAITH_DEATH2_8, + S_WRAITH_ICE, + S_WRAITH_ICE2, + S_WRTHFX_MOVE1, + S_WRTHFX_MOVE2, + S_WRTHFX_MOVE3, + S_WRTHFX_BOOM1, + S_WRTHFX_BOOM2, + S_WRTHFX_BOOM3, + S_WRTHFX_BOOM4, + S_WRTHFX_BOOM5, + S_WRTHFX_BOOM6, + S_WRTHFX_SIZZLE1, + S_WRTHFX_SIZZLE2, + S_WRTHFX_SIZZLE3, + S_WRTHFX_SIZZLE4, + S_WRTHFX_SIZZLE5, + S_WRTHFX_SIZZLE6, + S_WRTHFX_SIZZLE7, + S_WRTHFX_DROP1, + S_WRTHFX_DROP2, + S_WRTHFX_DROP3, + S_WRTHFX_DEAD1, + S_WRTHFX_ADROP1, + S_WRTHFX_ADROP2, + S_WRTHFX_ADROP3, + S_WRTHFX_ADROP4, + S_WRTHFX_ADEAD1, + S_WRTHFX_BDROP1, + S_WRTHFX_BDROP2, + S_WRTHFX_BDROP3, + S_WRTHFX_BDEAD1, + S_MNTR_SPAWN1, + S_MNTR_SPAWN2, + S_MNTR_SPAWN3, + S_MNTR_LOOK1, + S_MNTR_LOOK2, + S_MNTR_WALK1, + S_MNTR_WALK2, + S_MNTR_WALK3, + S_MNTR_WALK4, + S_MNTR_ROAM1, + S_MNTR_ROAM2, + S_MNTR_ROAM3, + S_MNTR_ROAM4, + S_MNTR_ATK1_1, + S_MNTR_ATK1_2, + S_MNTR_ATK1_3, + S_MNTR_ATK2_1, + S_MNTR_ATK2_2, + S_MNTR_ATK2_3, + S_MNTR_ATK3_1, + S_MNTR_ATK3_2, + S_MNTR_ATK3_3, + S_MNTR_ATK3_4, + S_MNTR_ATK4_1, + S_MNTR_PAIN1, + S_MNTR_PAIN2, + S_MNTR_DIE1, + S_MNTR_DIE2, + S_MNTR_DIE3, + S_MNTR_DIE4, + S_MNTR_DIE5, + S_MNTR_DIE6, + S_MNTR_DIE7, + S_MNTR_DIE8, + S_MNTR_DIE9, + S_MNTRFX1_1, + S_MNTRFX1_2, + S_MNTRFXI1_1, + S_MNTRFXI1_2, + S_MNTRFXI1_3, + S_MNTRFXI1_4, + S_MNTRFXI1_5, + S_MNTRFXI1_6, + S_MNTRFX2_1, + S_MNTRFXI2_1, + S_MNTRFXI2_2, + S_MNTRFXI2_3, + S_MNTRFXI2_4, + S_MNTRFXI2_5, + S_MNTRFX3_1, + S_MNTRFX3_2, + S_MNTRFX3_3, + S_MNTRFX3_4, + S_MNTRFX3_5, + S_MNTRFX3_6, + S_MNTRFX3_7, + S_MNTRFX3_8, + S_MNTRFX3_9, + S_MINOSMOKE1, + S_MINOSMOKE2, + S_MINOSMOKE3, + S_MINOSMOKE4, + S_MINOSMOKE5, + S_MINOSMOKE6, + S_MINOSMOKE7, + S_MINOSMOKE8, + S_MINOSMOKE9, + S_MINOSMOKE0, + S_MINOSMOKEA, + S_MINOSMOKEB, + S_MINOSMOKEC, + S_MINOSMOKED, + S_MINOSMOKEE, + S_MINOSMOKEF, + S_MINOSMOKEG, + S_MINOSMOKEX1, + S_MINOSMOKEX2, + S_MINOSMOKEX3, + S_MINOSMOKEX4, + S_MINOSMOKEX5, + S_MINOSMOKEX6, + S_MINOSMOKEX7, + S_MINOSMOKEX8, + S_MINOSMOKEX9, + S_MINOSMOKEX0, + S_MINOSMOKEXA, + S_MINOSMOKEXB, + S_MINOSMOKEXC, + S_MINOSMOKEXD, + S_MINOSMOKEXE, + S_MINOSMOKEXF, + S_MINOSMOKEXG, + S_MINOSMOKEXH, + S_MINOSMOKEXI, + S_SERPENT_LOOK1, + S_SERPENT_SWIM1, + S_SERPENT_SWIM2, + S_SERPENT_SWIM3, + S_SERPENT_HUMP1, + S_SERPENT_HUMP2, + S_SERPENT_HUMP3, + S_SERPENT_HUMP4, + S_SERPENT_HUMP5, + S_SERPENT_HUMP6, + S_SERPENT_HUMP7, + S_SERPENT_HUMP8, + S_SERPENT_HUMP9, + S_SERPENT_HUMP10, + S_SERPENT_HUMP11, + S_SERPENT_HUMP12, + S_SERPENT_HUMP13, + S_SERPENT_HUMP14, + S_SERPENT_HUMP15, + S_SERPENT_SURFACE1, + S_SERPENT_SURFACE2, + S_SERPENT_SURFACE3, + S_SERPENT_SURFACE4, + S_SERPENT_SURFACE5, + S_SERPENT_DIVE1, + S_SERPENT_DIVE2, + S_SERPENT_DIVE3, + S_SERPENT_DIVE4, + S_SERPENT_DIVE5, + S_SERPENT_DIVE6, + S_SERPENT_DIVE7, + S_SERPENT_DIVE8, + S_SERPENT_DIVE9, + S_SERPENT_DIVE10, + S_SERPENT_WALK1, + S_SERPENT_WALK2, + S_SERPENT_WALK3, + S_SERPENT_WALK4, + S_SERPENT_PAIN1, + S_SERPENT_PAIN2, + S_SERPENT_ATK1, + S_SERPENT_ATK2, + S_SERPENT_MELEE1, + S_SERPENT_MISSILE1, + S_SERPENT_DIE1, + S_SERPENT_DIE2, + S_SERPENT_DIE3, + S_SERPENT_DIE4, + S_SERPENT_DIE5, + S_SERPENT_DIE6, + S_SERPENT_DIE7, + S_SERPENT_DIE8, + S_SERPENT_DIE9, + S_SERPENT_DIE10, + S_SERPENT_DIE11, + S_SERPENT_DIE12, + S_SERPENT_XDIE1, + S_SERPENT_XDIE2, + S_SERPENT_XDIE3, + S_SERPENT_XDIE4, + S_SERPENT_XDIE5, + S_SERPENT_XDIE6, + S_SERPENT_XDIE7, + S_SERPENT_XDIE8, + S_SERPENT_ICE, + S_SERPENT_ICE2, + S_SERPENT_FX1, + S_SERPENT_FX2, + S_SERPENT_FX3, + S_SERPENT_FX4, + S_SERPENT_FX_X1, + S_SERPENT_FX_X2, + S_SERPENT_FX_X3, + S_SERPENT_FX_X4, + S_SERPENT_FX_X5, + S_SERPENT_FX_X6, + S_SERPENT_HEAD1, + S_SERPENT_HEAD2, + S_SERPENT_HEAD3, + S_SERPENT_HEAD4, + S_SERPENT_HEAD5, + S_SERPENT_HEAD6, + S_SERPENT_HEAD7, + S_SERPENT_HEAD8, + S_SERPENT_HEAD_X1, + S_SERPENT_GIB1_1, + S_SERPENT_GIB1_2, + S_SERPENT_GIB1_3, + S_SERPENT_GIB1_4, + S_SERPENT_GIB1_5, + S_SERPENT_GIB1_6, + S_SERPENT_GIB1_7, + S_SERPENT_GIB1_8, + S_SERPENT_GIB1_9, + S_SERPENT_GIB1_10, + S_SERPENT_GIB1_11, + S_SERPENT_GIB1_12, + S_SERPENT_GIB2_1, + S_SERPENT_GIB2_2, + S_SERPENT_GIB2_3, + S_SERPENT_GIB2_4, + S_SERPENT_GIB2_5, + S_SERPENT_GIB2_6, + S_SERPENT_GIB2_7, + S_SERPENT_GIB2_8, + S_SERPENT_GIB2_9, + S_SERPENT_GIB2_10, + S_SERPENT_GIB2_11, + S_SERPENT_GIB2_12, + S_SERPENT_GIB3_1, + S_SERPENT_GIB3_2, + S_SERPENT_GIB3_3, + S_SERPENT_GIB3_4, + S_SERPENT_GIB3_5, + S_SERPENT_GIB3_6, + S_SERPENT_GIB3_7, + S_SERPENT_GIB3_8, + S_SERPENT_GIB3_9, + S_SERPENT_GIB3_10, + S_SERPENT_GIB3_11, + S_SERPENT_GIB3_12, + S_BISHOP_LOOK1, + S_BISHOP_DECIDE, + S_BISHOP_BLUR1, + S_BISHOP_BLUR2, + S_BISHOP_WALK1, + S_BISHOP_WALK2, + S_BISHOP_WALK3, + S_BISHOP_WALK4, + S_BISHOP_WALK5, + S_BISHOP_WALK6, + S_BISHOP_ATK1, + S_BISHOP_ATK2, + S_BISHOP_ATK3, + S_BISHOP_ATK4, + S_BISHOP_ATK5, + S_BISHOP_PAIN1, + S_BISHOP_PAIN2, + S_BISHOP_PAIN3, + S_BISHOP_PAIN4, + S_BISHOP_PAIN5, + S_BISHOP_DEATH1, + S_BISHOP_DEATH2, + S_BISHOP_DEATH3, + S_BISHOP_DEATH4, + S_BISHOP_DEATH5, + S_BISHOP_DEATH6, + S_BISHOP_DEATH7, + S_BISHOP_DEATH8, + S_BISHOP_DEATH9, + S_BISHOP_DEATH10, + S_BISHOP_ICE, + S_BISHOP_ICE2, + S_BISHOP_PUFF1, + S_BISHOP_PUFF2, + S_BISHOP_PUFF3, + S_BISHOP_PUFF4, + S_BISHOP_PUFF5, + S_BISHOP_PUFF6, + S_BISHOP_PUFF7, + S_BISHOPBLUR1, + S_BISHOPBLUR2, + S_BISHOPPAINBLUR1, + S_BISHFX1_1, + S_BISHFX1_2, + S_BISHFX1_3, + S_BISHFX1_4, + S_BISHFX1_5, + S_BISHFXI1_1, + S_BISHFXI1_2, + S_BISHFXI1_3, + S_BISHFXI1_4, + S_BISHFXI1_5, + S_BISHFXI1_6, + S_DRAGON_LOOK1, + S_DRAGON_INIT, + S_DRAGON_INIT2, + S_DRAGON_INIT3, + S_DRAGON_WALK1, + S_DRAGON_WALK2, + S_DRAGON_WALK3, + S_DRAGON_WALK4, + S_DRAGON_WALK5, + S_DRAGON_WALK6, + S_DRAGON_WALK7, + S_DRAGON_WALK8, + S_DRAGON_WALK9, + S_DRAGON_WALK10, + S_DRAGON_WALK11, + S_DRAGON_WALK12, + S_DRAGON_ATK1, + S_DRAGON_PAIN1, + S_DRAGON_DEATH1, + S_DRAGON_DEATH2, + S_DRAGON_DEATH3, + S_DRAGON_DEATH4, + S_DRAGON_CRASH1, + S_DRAGON_CRASH2, + S_DRAGON_CRASH3, + S_DRAGON_FX1_1, + S_DRAGON_FX1_2, + S_DRAGON_FX1_3, + S_DRAGON_FX1_4, + S_DRAGON_FX1_5, + S_DRAGON_FX1_6, + S_DRAGON_FX1_X1, + S_DRAGON_FX1_X2, + S_DRAGON_FX1_X3, + S_DRAGON_FX1_X4, + S_DRAGON_FX1_X5, + S_DRAGON_FX1_X6, + S_DRAGON_FX2_1, + S_DRAGON_FX2_2, + S_DRAGON_FX2_3, + S_DRAGON_FX2_4, + S_DRAGON_FX2_5, + S_DRAGON_FX2_6, + S_DRAGON_FX2_7, + S_DRAGON_FX2_8, + S_DRAGON_FX2_9, + S_DRAGON_FX2_10, + S_DRAGON_FX2_11, + S_ARMOR_1, + S_ARMOR_2, + S_ARMOR_3, + S_ARMOR_4, + S_MANA1_1, + S_MANA1_2, + S_MANA1_3, + S_MANA1_4, + S_MANA1_5, + S_MANA1_6, + S_MANA1_7, + S_MANA1_8, + S_MANA1_9, + S_MANA2_1, + S_MANA2_2, + S_MANA2_3, + S_MANA2_4, + S_MANA2_5, + S_MANA2_6, + S_MANA2_7, + S_MANA2_8, + S_MANA2_9, + S_MANA2_10, + S_MANA2_11, + S_MANA2_12, + S_MANA2_13, + S_MANA2_14, + S_MANA2_15, + S_MANA2_16, + S_MANA3_1, + S_MANA3_2, + S_MANA3_3, + S_MANA3_4, + S_MANA3_5, + S_MANA3_6, + S_MANA3_7, + S_MANA3_8, + S_MANA3_9, + S_MANA3_10, + S_MANA3_11, + S_MANA3_12, + S_MANA3_13, + S_MANA3_14, + S_MANA3_15, + S_MANA3_16, + S_KEY1, + S_KEY2, + S_KEY3, + S_KEY4, + S_KEY5, + S_KEY6, + S_KEY7, + S_KEY8, + S_KEY9, + S_KEYA, + S_KEYB, + S_SND_WIND1, + S_SND_WIND2, + S_SND_WATERFALL, + S_ETTIN_LOOK1, + S_ETTIN_LOOK2, + S_ETTIN_CHASE1, + S_ETTIN_CHASE2, + S_ETTIN_CHASE3, + S_ETTIN_CHASE4, + S_ETTIN_PAIN1, + S_ETTIN_ATK1_1, + S_ETTIN_ATK1_2, + S_ETTIN_ATK1_3, + S_ETTIN_DEATH1_1, + S_ETTIN_DEATH1_2, + S_ETTIN_DEATH1_3, + S_ETTIN_DEATH1_4, + S_ETTIN_DEATH1_5, + S_ETTIN_DEATH1_6, + S_ETTIN_DEATH1_7, + S_ETTIN_DEATH1_8, + S_ETTIN_DEATH1_9, + S_ETTIN_DEATH2_1, + S_ETTIN_DEATH2_2, + S_ETTIN_DEATH2_3, + S_ETTIN_DEATH2_4, + S_ETTIN_DEATH2_5, + S_ETTIN_DEATH2_6, + S_ETTIN_DEATH2_7, + S_ETTIN_DEATH2_8, + S_ETTIN_DEATH2_9, + S_ETTIN_DEATH2_0, + S_ETTIN_DEATH2_A, + S_ETTIN_DEATH2_B, + S_ETTIN_ICE1, + S_ETTIN_ICE2, + S_ETTIN_MACE1, + S_ETTIN_MACE2, + S_ETTIN_MACE3, + S_ETTIN_MACE4, + S_ETTIN_MACE5, + S_ETTIN_MACE6, + S_ETTIN_MACE7, + S_FIRED_SPAWN1, + S_FIRED_LOOK1, + S_FIRED_LOOK2, + S_FIRED_LOOK3, + S_FIRED_LOOK4, + S_FIRED_LOOK5, + S_FIRED_LOOK6, + S_FIRED_LOOK7, + S_FIRED_LOOK8, + S_FIRED_LOOK9, + S_FIRED_LOOK0, + S_FIRED_LOOKA, + S_FIRED_LOOKB, + S_FIRED_WALK1, + S_FIRED_WALK2, + S_FIRED_WALK3, + S_FIRED_PAIN1, + S_FIRED_ATTACK1, + S_FIRED_ATTACK2, + S_FIRED_ATTACK3, + S_FIRED_ATTACK4, + S_FIRED_DEATH1, + S_FIRED_DEATH2, + S_FIRED_DEATH3, + S_FIRED_DEATH4, + S_FIRED_XDEATH1, + S_FIRED_XDEATH2, + S_FIRED_XDEATH3, + S_FIRED_ICE1, + S_FIRED_ICE2, + S_FIRED_CORPSE1, + S_FIRED_CORPSE2, + S_FIRED_CORPSE3, + S_FIRED_CORPSE4, + S_FIRED_CORPSE5, + S_FIRED_CORPSE6, + S_FIRED_RDROP1, + S_FIRED_RDEAD1_1, + S_FIRED_RDEAD1_2, + S_FIRED_RDROP2, + S_FIRED_RDEAD2_1, + S_FIRED_RDEAD2_2, + S_FIRED_RDROP3, + S_FIRED_RDEAD3_1, + S_FIRED_RDEAD3_2, + S_FIRED_RDROP4, + S_FIRED_RDEAD4_1, + S_FIRED_RDEAD4_2, + S_FIRED_RDROP5, + S_FIRED_RDEAD5_1, + S_FIRED_RDEAD5_2, + S_FIRED_FX6_1, + S_FIRED_FX6_2, + S_FIRED_FX6_3, + S_FIRED_FX6_4, + S_FIRED_FX6_5, + S_ICEGUY_LOOK, + S_ICEGUY_DORMANT, + S_ICEGUY_WALK1, + S_ICEGUY_WALK2, + S_ICEGUY_WALK3, + S_ICEGUY_WALK4, + S_ICEGUY_ATK1, + S_ICEGUY_ATK2, + S_ICEGUY_ATK3, + S_ICEGUY_ATK4, + S_ICEGUY_PAIN1, + S_ICEGUY_DEATH, + S_ICEGUY_FX1, + S_ICEGUY_FX2, + S_ICEGUY_FX3, + S_ICEGUY_FX_X1, + S_ICEGUY_FX_X2, + S_ICEGUY_FX_X3, + S_ICEGUY_FX_X4, + S_ICEGUY_FX_X5, + S_ICEFX_PUFF1, + S_ICEFX_PUFF2, + S_ICEFX_PUFF3, + S_ICEFX_PUFF4, + S_ICEFX_PUFF5, + S_ICEGUY_FX2_1, + S_ICEGUY_FX2_2, + S_ICEGUY_FX2_3, + S_ICEGUY_BIT1, + S_ICEGUY_BIT2, + S_ICEGUY_WISP1_1, + S_ICEGUY_WISP1_2, + S_ICEGUY_WISP1_3, + S_ICEGUY_WISP1_4, + S_ICEGUY_WISP1_5, + S_ICEGUY_WISP1_6, + S_ICEGUY_WISP1_7, + S_ICEGUY_WISP1_8, + S_ICEGUY_WISP1_9, + S_ICEGUY_WISP2_1, + S_ICEGUY_WISP2_2, + S_ICEGUY_WISP2_3, + S_ICEGUY_WISP2_4, + S_ICEGUY_WISP2_5, + S_ICEGUY_WISP2_6, + S_ICEGUY_WISP2_7, + S_ICEGUY_WISP2_8, + S_ICEGUY_WISP2_9, + S_FIGHTER, + S_FIGHTER2, + S_FIGHTERLOOK, + S_FIGHTER_RUN1, + S_FIGHTER_RUN2, + S_FIGHTER_RUN3, + S_FIGHTER_RUN4, + S_FIGHTER_ATK1, + S_FIGHTER_ATK2, + S_FIGHTER_PAIN, + S_FIGHTER_PAIN2, + S_FIGHTER_DIE1, + S_FIGHTER_DIE2, + S_FIGHTER_DIE3, + S_FIGHTER_DIE4, + S_FIGHTER_DIE5, + S_FIGHTER_DIE6, + S_FIGHTER_DIE7, + S_FIGHTER_XDIE1, + S_FIGHTER_XDIE2, + S_FIGHTER_XDIE3, + S_FIGHTER_XDIE4, + S_FIGHTER_XDIE5, + S_FIGHTER_XDIE6, + S_FIGHTER_XDIE7, + S_FIGHTER_XDIE8, + S_FIGHTER_ICE, + S_FIGHTER_ICE2, + S_CLERIC, + S_CLERIC2, + S_CLERICLOOK, + S_CLERIC_RUN1, + S_CLERIC_RUN2, + S_CLERIC_RUN3, + S_CLERIC_RUN4, + S_CLERIC_ATK1, + S_CLERIC_ATK2, + S_CLERIC_ATK3, + S_CLERIC_PAIN, + S_CLERIC_PAIN2, + S_CLERIC_DIE1, + S_CLERIC_DIE2, + S_CLERIC_DIE3, + S_CLERIC_DIE4, + S_CLERIC_DIE5, + S_CLERIC_DIE6, + S_CLERIC_DIE7, + S_CLERIC_DIE8, + S_CLERIC_DIE9, + S_CLERIC_XDIE1, + S_CLERIC_XDIE2, + S_CLERIC_XDIE3, + S_CLERIC_XDIE4, + S_CLERIC_XDIE5, + S_CLERIC_XDIE6, + S_CLERIC_XDIE7, + S_CLERIC_XDIE8, + S_CLERIC_XDIE9, + S_CLERIC_XDIE10, + S_CLERIC_ICE, + S_CLERIC_ICE2, + S_MAGE, + S_MAGE2, + S_MAGELOOK, + S_MAGE_RUN1, + S_MAGE_RUN2, + S_MAGE_RUN3, + S_MAGE_RUN4, + S_MAGE_ATK1, + S_MAGE_ATK2, + S_MAGE_PAIN, + S_MAGE_PAIN2, + S_MAGE_DIE1, + S_MAGE_DIE2, + S_MAGE_DIE3, + S_MAGE_DIE4, + S_MAGE_DIE5, + S_MAGE_DIE6, + S_MAGE_DIE7, + S_MAGE_XDIE1, + S_MAGE_XDIE2, + S_MAGE_XDIE3, + S_MAGE_XDIE4, + S_MAGE_XDIE5, + S_MAGE_XDIE6, + S_MAGE_XDIE7, + S_MAGE_XDIE8, + S_MAGE_XDIE9, + S_MAGE_ICE, + S_MAGE_ICE2, + S_SORC_SPAWN1, + S_SORC_SPAWN2, + S_SORC_LOOK1, + S_SORC_WALK1, + S_SORC_WALK2, + S_SORC_WALK3, + S_SORC_WALK4, + S_SORC_PAIN1, + S_SORC_PAIN2, + S_SORC_ATK2_1, + S_SORC_ATK2_2, + S_SORC_ATK2_3, + S_SORC_ATTACK1, + S_SORC_ATTACK2, + S_SORC_ATTACK3, + S_SORC_ATTACK4, + S_SORC_ATTACK5, + S_SORC_DIE1, + S_SORC_DIE2, + S_SORC_DIE3, + S_SORC_DIE4, + S_SORC_DIE5, + S_SORC_DIE6, + S_SORC_DIE7, + S_SORC_DIE8, + S_SORC_DIE9, + S_SORC_DIE0, + S_SORC_DIEA, + S_SORC_DIEB, + S_SORC_DIEC, + S_SORC_DIED, + S_SORC_DIEE, + S_SORC_DIEF, + S_SORC_DIEG, + S_SORC_DIEH, + S_SORC_DIEI, + S_SORCBALL1_1, + S_SORCBALL1_2, + S_SORCBALL1_3, + S_SORCBALL1_4, + S_SORCBALL1_5, + S_SORCBALL1_6, + S_SORCBALL1_7, + S_SORCBALL1_8, + S_SORCBALL1_9, + S_SORCBALL1_0, + S_SORCBALL1_A, + S_SORCBALL1_B, + S_SORCBALL1_C, + S_SORCBALL1_D, + S_SORCBALL1_E, + S_SORCBALL1_F, + S_SORCBALL1_D1, + S_SORCBALL1_D2, + S_SORCBALL1_D5, + S_SORCBALL1_D6, + S_SORCBALL1_D7, + S_SORCBALL1_D8, + S_SORCBALL1_D9, + S_SORCBALL2_1, + S_SORCBALL2_2, + S_SORCBALL2_3, + S_SORCBALL2_4, + S_SORCBALL2_5, + S_SORCBALL2_6, + S_SORCBALL2_7, + S_SORCBALL2_8, + S_SORCBALL2_9, + S_SORCBALL2_0, + S_SORCBALL2_A, + S_SORCBALL2_B, + S_SORCBALL2_C, + S_SORCBALL2_D, + S_SORCBALL2_E, + S_SORCBALL2_F, + S_SORCBALL2_D1, + S_SORCBALL2_D2, + S_SORCBALL2_D5, + S_SORCBALL2_D6, + S_SORCBALL2_D7, + S_SORCBALL2_D8, + S_SORCBALL2_D9, + S_SORCBALL3_1, + S_SORCBALL3_2, + S_SORCBALL3_3, + S_SORCBALL3_4, + S_SORCBALL3_5, + S_SORCBALL3_6, + S_SORCBALL3_7, + S_SORCBALL3_8, + S_SORCBALL3_9, + S_SORCBALL3_0, + S_SORCBALL3_A, + S_SORCBALL3_B, + S_SORCBALL3_C, + S_SORCBALL3_D, + S_SORCBALL3_E, + S_SORCBALL3_F, + S_SORCBALL3_D1, + S_SORCBALL3_D2, + S_SORCBALL3_D5, + S_SORCBALL3_D6, + S_SORCBALL3_D7, + S_SORCBALL3_D8, + S_SORCBALL3_D9, + S_SORCFX1_1, + S_SORCFX1_2, + S_SORCFX1_3, + S_SORCFX1_4, + S_SORCFX1_D1, + S_SORCFX1_D2, + S_SORCFX1_D3, + S_SORCFX2_SPLIT1, + S_SORCFX2_ORBIT1, + S_SORCFX2_ORBIT2, + S_SORCFX2_ORBIT3, + S_SORCFX2_ORBIT4, + S_SORCFX2_ORBIT5, + S_SORCFX2_ORBIT6, + S_SORCFX2_ORBIT7, + S_SORCFX2_ORBIT8, + S_SORCFX2_ORBIT9, + S_SORCFX2_ORBIT0, + S_SORCFX2_ORBITA, + S_SORCFX2_ORBITB, + S_SORCFX2_ORBITC, + S_SORCFX2_ORBITD, + S_SORCFX2_ORBITE, + S_SORCFX2_ORBITF, + S_SORCFX2T1, + S_SORCFX3_1, + S_SORCFX3_2, + S_SORCFX3_3, + S_BISHMORPH1, + S_BISHMORPHA, + S_BISHMORPHB, + S_BISHMORPHC, + S_BISHMORPHD, + S_BISHMORPHE, + S_BISHMORPHF, + S_BISHMORPHG, + S_BISHMORPHH, + S_BISHMORPHI, + S_BISHMORPHJ, + S_SORCFX3_EXP1, + S_SORCFX3_EXP2, + S_SORCFX3_EXP3, + S_SORCFX3_EXP4, + S_SORCFX3_EXP5, + S_SORCFX4_1, + S_SORCFX4_2, + S_SORCFX4_3, + S_SORCFX4_D1, + S_SORCFX4_D2, + S_SORCFX4_D3, + S_SORCFX4_D4, + S_SORCFX4_D5, + S_SORCSPARK1, + S_SORCSPARK2, + S_SORCSPARK3, + S_SORCSPARK4, + S_SORCSPARK5, + S_SORCSPARK6, + S_SORCSPARK7, + S_BLASTEFFECT1, + S_BLASTEFFECT2, + S_BLASTEFFECT3, + S_BLASTEFFECT4, + S_BLASTEFFECT5, + S_BLASTEFFECT6, + S_BLASTEFFECT7, + S_BLASTEFFECT8, + S_BLASTEFFECT9, + S_WATERDRIP1, + S_KORAX_LOOK1, + S_KORAX_CHASE1, + S_KORAX_CHASE2, + S_KORAX_CHASE3, + S_KORAX_CHASE4, + S_KORAX_CHASE5, + S_KORAX_CHASE6, + S_KORAX_CHASE7, + S_KORAX_CHASE8, + S_KORAX_CHASE9, + S_KORAX_CHASE0, + S_KORAX_CHASEA, + S_KORAX_CHASEB, + S_KORAX_CHASEC, + S_KORAX_CHASED, + S_KORAX_CHASEE, + S_KORAX_CHASEF, + S_KORAX_PAIN1, + S_KORAX_PAIN2, + S_KORAX_ATTACK1, + S_KORAX_ATTACK2, + S_KORAX_MISSILE1, + S_KORAX_MISSILE2, + S_KORAX_MISSILE3, + S_KORAX_COMMAND1, + S_KORAX_COMMAND2, + S_KORAX_COMMAND3, + S_KORAX_COMMAND4, + S_KORAX_COMMAND5, + S_KORAX_DEATH1, + S_KORAX_DEATH2, + S_KORAX_DEATH3, + S_KORAX_DEATH4, + S_KORAX_DEATH5, + S_KORAX_DEATH6, + S_KORAX_DEATH7, + S_KORAX_DEATH8, + S_KORAX_DEATH9, + S_KORAX_DEATH0, + S_KORAX_DEATHA, + S_KORAX_DEATHB, + S_KORAX_DEATHC, + S_KORAX_DEATHD, + S_KSPIRIT_ROAM1, + S_KSPIRIT_ROAM2, + S_KSPIRIT_DEATH1, + S_KSPIRIT_DEATH2, + S_KSPIRIT_DEATH3, + S_KSPIRIT_DEATH4, + S_KSPIRIT_DEATH5, + S_KSPIRIT_DEATH6, + S_KBOLT1, + S_KBOLT2, + S_KBOLT3, + S_KBOLT4, + S_KBOLT5, + S_KBOLT6, + S_KBOLT7, + S_SPAWNBATS1, + S_SPAWNBATS2, + S_SPAWNBATS3, + S_SPAWNBATS_OFF, + S_BAT1, + S_BAT2, + S_BAT3, + S_BAT_DEATH, + NUMSTATES +} statenum_t; + + +struct mobj_s; +struct player_s; +struct pspdef_s; + + +typedef struct +{ + spritenum_t sprite; + int frame; + int tics; + void (*action) (struct mobj_s *, struct player_s *, struct pspdef_s *); + statenum_t nextstate; + int misc1, misc2; +} state_t; + +extern state_t states[NUMSTATES]; +extern const char *sprnames[]; + + + +typedef enum +{ + MT_MAPSPOT, + MT_MAPSPOTGRAVITY, + MT_FIREBALL1, + MT_ARROW, + MT_DART, + MT_POISONDART, + MT_RIPPERBALL, + MT_PROJECTILE_BLADE, + MT_ICESHARD, + MT_FLAME_SMALL_TEMP, + MT_FLAME_LARGE_TEMP, + MT_FLAME_SMALL, + MT_FLAME_LARGE, + MT_HEALINGBOTTLE, + MT_HEALTHFLASK, + MT_ARTIFLY, + MT_ARTIINVULNERABILITY, + MT_SUMMONMAULATOR, + MT_SUMMON_FX, + MT_THRUSTFLOOR_UP, + MT_THRUSTFLOOR_DOWN, + MT_TELEPORTOTHER, + MT_TELOTHER_FX1, + MT_TELOTHER_FX2, + MT_TELOTHER_FX3, + MT_TELOTHER_FX4, + MT_TELOTHER_FX5, + MT_DIRT1, + MT_DIRT2, + MT_DIRT3, + MT_DIRT4, + MT_DIRT5, + MT_DIRT6, + MT_DIRTCLUMP, + MT_ROCK1, + MT_ROCK2, + MT_ROCK3, + MT_FOGSPAWNER, + MT_FOGPATCHS, + MT_FOGPATCHM, + MT_FOGPATCHL, + MT_QUAKE_FOCUS, + MT_SGSHARD1, + MT_SGSHARD2, + MT_SGSHARD3, + MT_SGSHARD4, + MT_SGSHARD5, + MT_SGSHARD6, + MT_SGSHARD7, + MT_SGSHARD8, + MT_SGSHARD9, + MT_SGSHARD0, + MT_ARTIEGG, + MT_EGGFX, + MT_ARTISUPERHEAL, + MT_ZWINGEDSTATUENOSKULL, + MT_ZGEMPEDESTAL, + MT_ARTIPUZZSKULL, + MT_ARTIPUZZGEMBIG, + MT_ARTIPUZZGEMRED, + MT_ARTIPUZZGEMGREEN1, + MT_ARTIPUZZGEMGREEN2, + MT_ARTIPUZZGEMBLUE1, + MT_ARTIPUZZGEMBLUE2, + MT_ARTIPUZZBOOK1, + MT_ARTIPUZZBOOK2, + MT_ARTIPUZZSKULL2, + MT_ARTIPUZZFWEAPON, + MT_ARTIPUZZCWEAPON, + MT_ARTIPUZZMWEAPON, + MT_ARTIPUZZGEAR, + MT_ARTIPUZZGEAR2, + MT_ARTIPUZZGEAR3, + MT_ARTIPUZZGEAR4, + MT_ARTITORCH, + MT_FIREBOMB, + MT_ARTITELEPORT, + MT_ARTIPOISONBAG, + MT_POISONBAG, + MT_POISONCLOUD, + MT_THROWINGBOMB, + MT_SPEEDBOOTS, + MT_BOOSTMANA, + MT_BOOSTARMOR, + MT_BLASTRADIUS, + MT_HEALRADIUS, + MT_SPLASH, + MT_SPLASHBASE, + MT_LAVASPLASH, + MT_LAVASMOKE, + MT_SLUDGECHUNK, + MT_SLUDGESPLASH, + MT_MISC0, + MT_MISC1, + MT_MISC2, + MT_MISC3, + MT_MISC4, + MT_MISC5, + MT_MISC6, + MT_MISC7, + MT_MISC8, + MT_TREEDESTRUCTIBLE, + MT_MISC9, + MT_MISC10, + MT_MISC11, + MT_MISC12, + MT_MISC13, + MT_MISC14, + MT_MISC15, + MT_MISC16, + MT_MISC17, + MT_MISC18, + MT_MISC19, + MT_MISC20, + MT_MISC21, + MT_MISC22, + MT_MISC23, + MT_MISC24, + MT_MISC25, + MT_MISC26, + MT_MISC27, + MT_MISC28, + MT_MISC29, + MT_MISC30, + MT_MISC31, + MT_MISC32, + MT_MISC33, + MT_MISC34, + MT_MISC35, + MT_MISC36, + MT_MISC37, + MT_MISC38, + MT_MISC39, + MT_MISC40, + MT_MISC41, + MT_MISC42, + MT_MISC43, + MT_MISC44, + MT_MISC45, + MT_MISC46, + MT_MISC47, + MT_MISC48, + MT_MISC49, + MT_MISC50, + MT_MISC51, + MT_MISC52, + MT_MISC53, + MT_MISC54, + MT_MISC55, + MT_MISC56, + MT_MISC57, + MT_MISC58, + MT_MISC59, + MT_MISC60, + MT_MISC61, + MT_MISC62, + MT_MISC63, + MT_MISC64, + MT_MISC65, + MT_MISC66, + MT_MISC67, + MT_MISC68, + MT_MISC69, + MT_MISC70, + MT_MISC71, + MT_MISC72, + MT_MISC73, + MT_MISC74, + MT_MISC75, + MT_MISC76, + MT_POTTERY1, + MT_POTTERY2, + MT_POTTERY3, + MT_POTTERYBIT1, + MT_MISC77, + MT_ZLYNCHED_NOHEART, + MT_MISC78, + MT_CORPSEBIT, + MT_CORPSEBLOODDRIP, + MT_BLOODPOOL, + MT_MISC79, + MT_MISC80, + MT_LEAF1, + MT_LEAF2, + MT_ZTWINEDTORCH, + MT_ZTWINEDTORCH_UNLIT, + MT_BRIDGE, + MT_BRIDGEBALL, + MT_ZWALLTORCH, + MT_ZWALLTORCH_UNLIT, + MT_ZBARREL, + MT_ZSHRUB1, + MT_ZSHRUB2, + MT_ZBUCKET, + MT_ZPOISONSHROOM, + MT_ZFIREBULL, + MT_ZFIREBULL_UNLIT, + MT_FIRETHING, + MT_BRASSTORCH, + MT_ZSUITOFARMOR, + MT_ZARMORCHUNK, + MT_ZBELL, + MT_ZBLUE_CANDLE, + MT_ZIRON_MAIDEN, + MT_ZXMAS_TREE, + MT_ZCAULDRON, + MT_ZCAULDRON_UNLIT, + MT_ZCHAINBIT32, + MT_ZCHAINBIT64, + MT_ZCHAINEND_HEART, + MT_ZCHAINEND_HOOK1, + MT_ZCHAINEND_HOOK2, + MT_ZCHAINEND_SPIKE, + MT_ZCHAINEND_SKULL, + MT_TABLE_SHIT1, + MT_TABLE_SHIT2, + MT_TABLE_SHIT3, + MT_TABLE_SHIT4, + MT_TABLE_SHIT5, + MT_TABLE_SHIT6, + MT_TABLE_SHIT7, + MT_TABLE_SHIT8, + MT_TABLE_SHIT9, + MT_TABLE_SHIT10, + MT_TFOG, + MT_MISC81, + MT_TELEPORTMAN, + MT_PUNCHPUFF, + MT_FW_AXE, + MT_AXEPUFF, + MT_AXEPUFF_GLOW, + MT_AXEBLOOD, + MT_FW_HAMMER, + MT_HAMMER_MISSILE, + MT_HAMMERPUFF, + MT_FSWORD_MISSILE, + MT_FSWORD_FLAME, + MT_CW_SERPSTAFF, + MT_CSTAFF_MISSILE, + MT_CSTAFFPUFF, + MT_CW_FLAME, + MT_CFLAMEFLOOR, + MT_FLAMEPUFF, + MT_FLAMEPUFF2, + MT_CIRCLEFLAME, + MT_CFLAME_MISSILE, + MT_HOLY_FX, + MT_HOLY_TAIL, + MT_HOLY_PUFF, + MT_HOLY_MISSILE, + MT_HOLY_MISSILE_PUFF, + MT_MWANDPUFF, + MT_MWANDSMOKE, + MT_MWAND_MISSILE, + MT_MW_LIGHTNING, + MT_LIGHTNING_CEILING, + MT_LIGHTNING_FLOOR, + MT_LIGHTNING_ZAP, + MT_MSTAFF_FX, + MT_MSTAFF_FX2, + MT_FW_SWORD1, + MT_FW_SWORD2, + MT_FW_SWORD3, + MT_CW_HOLY1, + MT_CW_HOLY2, + MT_CW_HOLY3, + MT_MW_STAFF1, + MT_MW_STAFF2, + MT_MW_STAFF3, + MT_SNOUTPUFF, + MT_MW_CONE, + MT_SHARDFX1, + MT_BLOOD, + MT_BLOODSPLATTER, + MT_GIBS, + MT_PLAYER_FIGHTER, + MT_BLOODYSKULL, + MT_PLAYER_SPEED, + MT_ICECHUNK, + MT_PLAYER_CLERIC, + MT_PLAYER_MAGE, + MT_PIGPLAYER, + MT_PIG, + MT_CENTAUR, + MT_CENTAURLEADER, + MT_CENTAUR_FX, + MT_CENTAUR_SHIELD, + MT_CENTAUR_SWORD, + MT_DEMON, + MT_DEMONCHUNK1, + MT_DEMONCHUNK2, + MT_DEMONCHUNK3, + MT_DEMONCHUNK4, + MT_DEMONCHUNK5, + MT_DEMONFX1, + MT_DEMON2, + MT_DEMON2CHUNK1, + MT_DEMON2CHUNK2, + MT_DEMON2CHUNK3, + MT_DEMON2CHUNK4, + MT_DEMON2CHUNK5, + MT_DEMON2FX1, + MT_WRAITHB, + MT_WRAITH, + MT_WRAITHFX1, + MT_WRAITHFX2, + MT_WRAITHFX3, + MT_WRAITHFX4, + MT_WRAITHFX5, + MT_MINOTAUR, + MT_MNTRFX1, + MT_MNTRFX2, + MT_MNTRFX3, + MT_MNTRSMOKE, + MT_MNTRSMOKEEXIT, + MT_SERPENT, + MT_SERPENTLEADER, + MT_SERPENTFX, + MT_SERPENT_HEAD, + MT_SERPENT_GIB1, + MT_SERPENT_GIB2, + MT_SERPENT_GIB3, + MT_BISHOP, + MT_BISHOP_PUFF, + MT_BISHOPBLUR, + MT_BISHOPPAINBLUR, + MT_BISH_FX, + MT_DRAGON, + MT_DRAGON_FX, + MT_DRAGON_FX2, + MT_ARMOR_1, + MT_ARMOR_2, + MT_ARMOR_3, + MT_ARMOR_4, + MT_MANA1, + MT_MANA2, + MT_MANA3, + MT_KEY1, + MT_KEY2, + MT_KEY3, + MT_KEY4, + MT_KEY5, + MT_KEY6, + MT_KEY7, + MT_KEY8, + MT_KEY9, + MT_KEYA, + MT_KEYB, + MT_SOUNDWIND, + MT_SOUNDWATERFALL, + MT_ETTIN, + MT_ETTIN_MACE, + MT_FIREDEMON, + MT_FIREDEMON_SPLOTCH1, + MT_FIREDEMON_SPLOTCH2, + MT_FIREDEMON_FX1, + MT_FIREDEMON_FX2, + MT_FIREDEMON_FX3, + MT_FIREDEMON_FX4, + MT_FIREDEMON_FX5, + MT_FIREDEMON_FX6, + MT_ICEGUY, + MT_ICEGUY_FX, + MT_ICEFX_PUFF, + MT_ICEGUY_FX2, + MT_ICEGUY_BIT, + MT_ICEGUY_WISP1, + MT_ICEGUY_WISP2, + MT_FIGHTER_BOSS, + MT_CLERIC_BOSS, + MT_MAGE_BOSS, + MT_SORCBOSS, + MT_SORCBALL1, + MT_SORCBALL2, + MT_SORCBALL3, + MT_SORCFX1, + MT_SORCFX2, + MT_SORCFX2_T1, + MT_SORCFX3, + MT_SORCFX3_EXPLOSION, + MT_SORCFX4, + MT_SORCSPARK1, + MT_BLASTEFFECT, + MT_WATER_DRIP, + MT_KORAX, + MT_KORAX_SPIRIT1, + MT_KORAX_SPIRIT2, + MT_KORAX_SPIRIT3, + MT_KORAX_SPIRIT4, + MT_KORAX_SPIRIT5, + MT_KORAX_SPIRIT6, + MT_DEMON_MASH, + MT_DEMON2_MASH, + MT_ETTIN_MASH, + MT_CENTAUR_MASH, + MT_KORAX_BOLT, + MT_BAT_SPAWNER, + MT_BAT, + NUMMOBJTYPES +} mobjtype_t; + +typedef struct +{ + int doomednum; + int spawnstate; + int spawnhealth; + int seestate; + int seesound; + int reactiontime; + int attacksound; + int painstate; + int painchance; + int painsound; + int meleestate; + int missilestate; + int crashstate; + int deathstate; + int xdeathstate; + int deathsound; + int speed; + int radius; + int height; + int mass; + int damage; + int activesound; + int flags; + int flags2; +} mobjinfo_t; + +extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; diff --git a/games/NXDoom/src/hexen/m_random.c b/games/NXDoom/src/hexen/m_random.c new file mode 100644 index 00000000000..422b1a5d455 --- /dev/null +++ b/games/NXDoom/src/hexen/m_random.c @@ -0,0 +1,80 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "m_random.h" + +// This is the new flat distribution table + +static const unsigned char rndtable[256] = { + 201, 1, 243, 19, 18, 42, 183, 203, 101, 123, 154, 137, 34, 118, 10, 216, + 135, 246, 0, 107, 133, 229, 35, 113, 177, 211, 110, 17, 139, 84, 251, 235, + 182, 166, 161, 230, 143, 91, 24, 81, 22, 94, 7, 51, 232, 104, 122, 248, + 175, 138, 127, 171, 222, 213, 44, 16, 9, 33, 88, 102, 170, 150, 136, 114, + 62, 3, 142, 237, 6, 252, 249, 56, 74, 30, 13, 21, 180, 199, 32, 132, + 187, 234, 78, 210, 46, 131, 197, 8, 206, 244, 73, 4, 236, 178, 195, 70, + 121, 97, 167, 217, 103, 40, 247, 186, 105, 39, 95, 163, 99, 149, 253, 29, + 119, 83, 254, 26, 202, 65, 130, 155, 60, 64, 184, 106, 221, 93, 164, 196, + 112, 108, 179, 141, 54, 109, 11, 126, 75, 165, 191, 227, 87, 225, 156, 15, + 98, 162, 116, 79, 169, 140, 190, 205, 168, 194, 41, 250, 27, 20, 14, 241, + 50, 214, 72, 192, 220, 233, 67, 148, 96, 185, 176, 181, 215, 207, 172, 85, + 89, 90, 209, 128, 124, 2, 55, 173, 66, 152, 47, 129, 59, 43, 159, 240, + 239, 12, 189, 212, 144, 28, 200, 77, 219, 198, 134, 228, 45, 92, 125, 151, + 5, 53, 255, 52, 68, 245, 160, 158, 61, 86, 58, 82, 117, 37, 242, 145, + 69, 188, 115, 76, 63, 100, 49, 111, 153, 80, 38, 57, 174, 224, 71, 231, + 23, 25, 48, 218, 120, 147, 208, 36, 226, 223, 193, 238, 157, 204, 146, 31 +}; + + +int rndindex = 0; +int prndindex = 0; + +/* +=============== += += M_Random += += Returns a 0-255 number += +=============== +*/ + + +int P_Random(void) +{ + prndindex = (prndindex + 1) & 0xff; + return rndtable[prndindex]; +} + +int M_Random(void) +{ + rndindex = (rndindex + 1) & 0xff; + return rndtable[rndindex]; +} + +void M_ClearRandom(void) +{ + rndindex = prndindex = 0; +} + +// inspired by the same routine in Eternity, thanks haleyjd +int P_SubRandom (void) +{ + int r = P_Random(); + return r - P_Random(); +} diff --git a/games/NXDoom/src/hexen/m_random.h b/games/NXDoom/src/hexen/m_random.h new file mode 100644 index 00000000000..2de7630012e --- /dev/null +++ b/games/NXDoom/src/hexen/m_random.h @@ -0,0 +1,37 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef HEXEN_M_RANDOM_H +#define HEXEN_M_RANDOM_H + +// Most damage defined using HITDICE +#define HITDICE(a) ((1+(P_Random()&7))*a) + +int M_Random(void); +// returns a number from 0 to 255 +int P_Random(void); +// as M_Random, but used only by the play simulation + +void M_ClearRandom(void); +// fix randoms for demos + +extern int rndindex; + +// Defined version of P_Random() - P_Random() +int P_SubRandom (void); + +#endif // HEXEN_M_RANDOM_H + diff --git a/games/NXDoom/src/hexen/mn_menu.c b/games/NXDoom/src/hexen/mn_menu.c new file mode 100644 index 00000000000..57be51c9c6b --- /dev/null +++ b/games/NXDoom/src/hexen/mn_menu.c @@ -0,0 +1,1952 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include +#include "h2def.h" +#include "doomkeys.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_swap.h" +#include "i_video.h" +#include "m_controls.h" +#include "m_misc.h" +#include "p_local.h" +#include "r_local.h" +#include "s_sound.h" +#include "v_video.h" +#include "am_map.h" + + +// MACROS ------------------------------------------------------------------ + +#define LEFT_DIR 0 +#define RIGHT_DIR 1 +#define ITEM_HEIGHT 20 +#define SELECTOR_XOFFSET (-28) +#define SELECTOR_YOFFSET (-1) +#define SLOTTEXTLEN 16 +#define ASCII_CURSOR '[' + +// TYPES ------------------------------------------------------------------- + +typedef enum +{ + ITT_EMPTY, + ITT_EFUNC, + ITT_LRFUNC, + ITT_SETMENU, + ITT_INERT +} ItemType_t; + +typedef enum +{ + MENU_MAIN, + MENU_CLASS, + MENU_SKILL, + MENU_OPTIONS, + MENU_OPTIONS2, + MENU_FILES, + MENU_LOAD, + MENU_SAVE, + MENU_NONE +} MenuType_t; + +typedef struct +{ + ItemType_t type; + const char *text; + void (*func) (int option); + int option; + MenuType_t menu; +} MenuItem_t; + +typedef struct +{ + int x; + int y; + void (*drawFunc) (void); + int itemCount; + MenuItem_t *items; + int oldItPos; + MenuType_t prevMenu; +} Menu_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void InitFonts(void); +static void SetMenu(MenuType_t menu); +static void SCQuitGame(int option); +static void SCClass(int option); +static void SCSkill(int option); +static void SCMouseSensi(int option); +static void SCSfxVolume(int option); +static void SCMusicVolume(int option); +static void SCScreenSize(int option); +static boolean SCNetCheck(int option); +static void SCNetCheck2(int option); +static void SCLoadGame(int option); +static void SCSaveGame(int option); +static void SCMessages(int option); +static void SCEndGame(int option); +static void SCInfo(int option); +static void DrawMainMenu(void); +static void DrawClassMenu(void); +static void DrawSkillMenu(void); +static void DrawOptionsMenu(void); +static void DrawOptions2Menu(void); +static void DrawFileSlots(Menu_t * menu); +static void DrawFilesMenu(void); +static void MN_DrawInfo(void); +static void DrawLoadMenu(void); +static void DrawSaveMenu(void); +static void DrawSlider(Menu_t * menu, int item, int width, int slot); +void MN_LoadSlotText(void); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +boolean MenuActive; +int InfoType; +int messageson = true; +boolean mn_SuicideConsole; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int FontABaseLump; +static int FontAYellowBaseLump; +static int FontBBaseLump; +static int MauloBaseLump; +static Menu_t *CurrentMenu; +static int CurrentItPos; +static int MenuPClass; +static int MenuTime; +static boolean soundchanged; + +boolean askforquit; +static int typeofask; +static boolean FileMenuKeySteal; +static boolean slottextloaded; +static boolean joypadsave; +static char SlotText[6][SLOTTEXTLEN + 2]; +static char oldSlotText[SLOTTEXTLEN + 2]; +static int SlotStatus[6]; +static int slotptr; +static int currentSlot; +static int quicksave; +static int quickload; + +static MenuItem_t MainItems[] = { + {ITT_SETMENU, "NEW GAME", SCNetCheck2, 1, MENU_CLASS}, + {ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS}, + {ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES}, + {ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE}, + {ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE} +}; + +static Menu_t MainMenu = { + 110, 56, + DrawMainMenu, + 5, MainItems, + 0, + MENU_NONE +}; + +static MenuItem_t ClassItems[] = { + {ITT_EFUNC, "FIGHTER", SCClass, 0, MENU_NONE}, + {ITT_EFUNC, "CLERIC", SCClass, 1, MENU_NONE}, + {ITT_EFUNC, "MAGE", SCClass, 2, MENU_NONE} +}; + +static Menu_t ClassMenu = { + 66, 66, + DrawClassMenu, + 3, ClassItems, + 0, + MENU_MAIN +}; + +static MenuItem_t FilesItems[] = { + {ITT_SETMENU, "LOAD GAME", SCNetCheck2, 2, MENU_LOAD}, + {ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE} +}; + +static Menu_t FilesMenu = { + 110, 60, + DrawFilesMenu, + 2, FilesItems, + 0, + MENU_MAIN +}; + +static MenuItem_t LoadItems[] = { + {ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE}, + {ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE} +}; + +static Menu_t LoadMenu = { + 70, 30, + DrawLoadMenu, + 6, LoadItems, + 0, + MENU_FILES +}; + +static MenuItem_t SaveItems[] = { + {ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE}, + {ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE} +}; + +static Menu_t SaveMenu = { + 70, 30, + DrawSaveMenu, + 6, SaveItems, + 0, + MENU_FILES +}; + +static MenuItem_t SkillItems[] = { + {ITT_EFUNC, NULL, SCSkill, sk_baby, MENU_NONE}, + {ITT_EFUNC, NULL, SCSkill, sk_easy, MENU_NONE}, + {ITT_EFUNC, NULL, SCSkill, sk_medium, MENU_NONE}, + {ITT_EFUNC, NULL, SCSkill, sk_hard, MENU_NONE}, + {ITT_EFUNC, NULL, SCSkill, sk_nightmare, MENU_NONE} +}; + +static Menu_t SkillMenu = { + 120, 44, + DrawSkillMenu, + 5, SkillItems, + 2, + MENU_CLASS +}; + +static MenuItem_t OptionsItems[] = { + {ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE}, + {ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE}, + {ITT_LRFUNC, "MOUSE SENSITIVITY", SCMouseSensi, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2} +}; + +static Menu_t OptionsMenu = { + 88, 30, + DrawOptionsMenu, + 5, OptionsItems, + 0, + MENU_MAIN +}; + +static MenuItem_t Options2Items[] = { + {ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, + {ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE}, + {ITT_EMPTY, NULL, NULL, 0, MENU_NONE} +}; + +static Menu_t Options2Menu = { + 90, 20, + DrawOptions2Menu, + 6, Options2Items, + 0, + MENU_OPTIONS +}; + +static Menu_t *Menus[] = { + &MainMenu, + &ClassMenu, + &SkillMenu, + &OptionsMenu, + &Options2Menu, + &FilesMenu, + &LoadMenu, + &SaveMenu +}; + +static const char *GammaText[] = { + TXT_GAMMA_LEVEL_OFF, + TXT_GAMMA_LEVEL_1, + TXT_GAMMA_LEVEL_2, + TXT_GAMMA_LEVEL_3, + TXT_GAMMA_LEVEL_4 +}; + +// CODE -------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// PROC MN_Init +// +//--------------------------------------------------------------------------- + +void MN_Init(void) +{ + InitFonts(); + MenuActive = false; +// messageson = true; // Set by defaults in .CFG + MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00"); +} + +//--------------------------------------------------------------------------- +// +// PROC InitFonts +// +//--------------------------------------------------------------------------- + +static void InitFonts(void) +{ + FontABaseLump = W_GetNumForName("FONTA_S") + 1; + FontAYellowBaseLump = W_GetNumForName("FONTAY_S") + 1; + FontBBaseLump = W_GetNumForName("FONTB_S") + 1; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrTextA +// +// Draw text using font A. +// +//--------------------------------------------------------------------------- + +void MN_DrTextA(const char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 5; + } + else + { + p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//========================================================================== +// +// MN_DrTextAYellow +// +//========================================================================== + +void MN_DrTextAYellow(const char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 5; + } + else + { + p = W_CacheLumpNum(FontAYellowBaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_TextAWidth +// +// Returns the pixel width of a string using font A. +// +//--------------------------------------------------------------------------- + +int MN_TextAWidth(const char *text) +{ + char c; + int width; + patch_t *p; + + width = 0; + while ((c = *text++) != 0) + { + if (c < 33) + { + width += 5; + } + else + { + p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + width += SHORT(p->width) - 1; + } + } + return (width); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrTextB +// +// Draw text using font B. +// +//--------------------------------------------------------------------------- + +void MN_DrTextB(const char *text, int x, int y) +{ + char c; + patch_t *p; + + while ((c = *text++) != 0) + { + if (c < 33) + { + x += 8; + } + else + { + p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); + V_DrawPatch(x, y, p); + x += SHORT(p->width) - 1; + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_TextBWidth +// +// Returns the pixel width of a string using font B. +// +//--------------------------------------------------------------------------- + +int MN_TextBWidth(const char *text) +{ + char c; + int width; + patch_t *p; + + width = 0; + while ((c = *text++) != 0) + { + if (c < 33) + { + width += 5; + } + else + { + p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); + width += SHORT(p->width) - 1; + } + } + return (width); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_Ticker +// +//--------------------------------------------------------------------------- + +void MN_Ticker(void) +{ + if (MenuActive == false) + { + return; + } + MenuTime++; +} + +//--------------------------------------------------------------------------- +// +// PROC MN_Drawer +// +//--------------------------------------------------------------------------- + +const char *QuitEndMsg[] = { + "ARE YOU SURE YOU WANT TO QUIT?", + "ARE YOU SURE YOU WANT TO END THE GAME?", + "DO YOU WANT TO QUICKSAVE THE GAME NAMED", + "DO YOU WANT TO QUICKLOAD THE GAME NAMED", + "ARE YOU SURE YOU WANT TO SUICIDE?" +}; + +void MN_Drawer(void) +{ + int i; + int x; + int y; + MenuItem_t *item; + const char *selName; + + if (MenuActive == false) + { + if (askforquit) + { + MN_DrTextA(QuitEndMsg[typeofask - 1], 160 - + MN_TextAWidth(QuitEndMsg[typeofask - 1]) / 2, 80); + if (typeofask == 3) + { + MN_DrTextA(SlotText[quicksave - 1], 160 - + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + MN_DrTextA("?", 160 + + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + } + if (typeofask == 4) + { + MN_DrTextA(SlotText[quickload - 1], 160 - + MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); + MN_DrTextA("?", 160 + + MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); + } + UpdateState |= I_FULLSCRN; + } + return; + } + else + { + UpdateState |= I_FULLSCRN; + if (InfoType) + { + MN_DrawInfo(); + return; + } + if (screenblocks < 10) + { + BorderNeedRefresh = true; + } + if (CurrentMenu->drawFunc != NULL) + { + CurrentMenu->drawFunc(); + } + x = CurrentMenu->x; + y = CurrentMenu->y; + item = CurrentMenu->items; + for (i = 0; i < CurrentMenu->itemCount; i++) + { + if (item->type != ITT_EMPTY && item->text) + { + MN_DrTextB(item->text, x, y); + } + y += ITEM_HEIGHT; + item++; + } + y = CurrentMenu->y + (CurrentItPos * ITEM_HEIGHT) + SELECTOR_YOFFSET; + selName = MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2"; + V_DrawPatch(x + SELECTOR_XOFFSET, y, + W_CacheLumpName(selName, PU_CACHE)); + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawMainMenu +// +//--------------------------------------------------------------------------- + +static void DrawMainMenu(void) +{ + int frame; + + frame = (MenuTime / 5) % 7; + V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE)); +// Old Gold skull positions: (40, 10) and (232, 10) + V_DrawPatch(37, 80, W_CacheLumpNum(MauloBaseLump + (frame + 2) % 7, + PU_CACHE)); + V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump + frame, PU_CACHE)); +} + +//========================================================================== +// +// DrawClassMenu +// +//========================================================================== + +static void DrawClassMenu(void) +{ + pclass_t class; + static const char *boxLumpName[3] = { + "m_fbox", + "m_cbox", + "m_mbox" + }; + static const char *walkLumpName[3] = { + "m_fwalk1", + "m_cwalk1", + "m_mwalk1" + }; + + MN_DrTextB("CHOOSE CLASS:", 34, 24); + class = (pclass_t) CurrentMenu->items[CurrentItPos].option; + V_DrawPatch(174, 8, W_CacheLumpName(boxLumpName[class], PU_CACHE)); + V_DrawPatch(174 + 24, 8 + 12, + W_CacheLumpNum(W_GetNumForName(walkLumpName[class]) + + ((MenuTime >> 3) & 3), PU_CACHE)); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSkillMenu +// +//--------------------------------------------------------------------------- + +static void DrawSkillMenu(void) +{ + MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawFilesMenu +// +//--------------------------------------------------------------------------- + +static void DrawFilesMenu(void) +{ +// clear out the quicksave/quickload stuff + quicksave = 0; + quickload = 0; + P_ClearMessage(&players[consoleplayer]); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawLoadMenu +// +//--------------------------------------------------------------------------- + +static void DrawLoadMenu(void) +{ + MN_DrTextB("LOAD GAME", 160 - MN_TextBWidth("LOAD GAME") / 2, 10); + if (!slottextloaded) + { + MN_LoadSlotText(); + } + DrawFileSlots(&LoadMenu); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSaveMenu +// +//--------------------------------------------------------------------------- + +static void DrawSaveMenu(void) +{ + MN_DrTextB("SAVE GAME", 160 - MN_TextBWidth("SAVE GAME") / 2, 10); + if (!slottextloaded) + { + MN_LoadSlotText(); + } + DrawFileSlots(&SaveMenu); +} + +static boolean ReadDescriptionForSlot(int slot, char *description) +{ + FILE *fp; + boolean found; + char name[100]; + char versionText[HXS_VERSION_TEXT_LENGTH]; + + M_snprintf(name, sizeof(name), "%shex%d.hxs", SavePath, slot); + + fp = M_fopen(name, "rb"); + + if (fp == NULL) + { + return false; + } + + found = fread(description, HXS_DESCRIPTION_LENGTH, 1, fp) == 1 + && fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp) == 1; + + found = found && strcmp(versionText, HXS_VERSION_TEXT) == 0; + + fclose(fp); + + return found; +} + +//=========================================================================== +// +// MN_LoadSlotText +// +// For each slot, looks for save games and reads the description field. +// +//=========================================================================== + +void MN_LoadSlotText(void) +{ + char description[HXS_DESCRIPTION_LENGTH]; + int slot; + + for (slot = 0; slot < 6; slot++) + { + if (ReadDescriptionForSlot(slot, description)) + { + memcpy(SlotText[slot], description, SLOTTEXTLEN); + SlotStatus[slot] = 1; + } + else + { + memset(SlotText[slot], 0, SLOTTEXTLEN); + SlotStatus[slot] = 0; + } + } + slottextloaded = true; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawFileSlots +// +//--------------------------------------------------------------------------- + +static void DrawFileSlots(Menu_t * menu) +{ + int i; + int x; + int y; + + x = menu->x; + y = menu->y; + for (i = 0; i < 6; i++) + { + V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE)); + if (SlotStatus[i]) + { + MN_DrTextA(SlotText[i], x + 5, y + 5); + } + y += ITEM_HEIGHT; + } +} + +//--------------------------------------------------------------------------- +// +// PROC DrawOptionsMenu +// +//--------------------------------------------------------------------------- + +static void DrawOptionsMenu(void) +{ + if (messageson) + { + MN_DrTextB("ON", 196, 50); + } + else + { + MN_DrTextB("OFF", 196, 50); + } + DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity); +} + +//--------------------------------------------------------------------------- +// +// PROC DrawOptions2Menu +// +//--------------------------------------------------------------------------- + +static void DrawOptions2Menu(void) +{ + DrawSlider(&Options2Menu, 1, 9, screenblocks - 3); + DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume); + DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume); +} + +//--------------------------------------------------------------------------- +// +// PROC SCQuitGame +// +//--------------------------------------------------------------------------- + +static void SCQuitGame(int option) +{ + MenuActive = false; + askforquit = true; + typeofask = 1; //quit game + if (!netgame && !demoplayback) + { + paused = true; + } +} + +//--------------------------------------------------------------------------- +// +// PROC SCEndGame +// +//--------------------------------------------------------------------------- + +static void SCEndGame(int option) +{ + if (demoplayback) + { + return; + } + if (SCNetCheck(3)) + { + MenuActive = false; + askforquit = true; + typeofask = 2; //endgame + if (!netgame && !demoplayback) + { + paused = true; + } + } +} + +//--------------------------------------------------------------------------- +// +// PROC SCMessages +// +//--------------------------------------------------------------------------- + +static void SCMessages(int option) +{ + messageson ^= 1; + if (messageson) + { + P_SetMessage(&players[consoleplayer], "MESSAGES ON", true); + } + else + { + P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true); + } + S_StartSound(NULL, SFX_CHAT); +} + +//=========================================================================== +// +// SCNetCheck +// +//=========================================================================== + +static boolean SCNetCheck(int option) +{ + if (!netgame) + { + return true; + } + switch (option) + { + case 1: // new game + P_SetMessage(&players[consoleplayer], + "YOU CAN'T START A NEW GAME IN NETPLAY!", true); + break; + case 2: // load game + P_SetMessage(&players[consoleplayer], + "YOU CAN'T LOAD A GAME IN NETPLAY!", true); + break; + case 3: // end game + P_SetMessage(&players[consoleplayer], + "YOU CAN'T END A GAME IN NETPLAY!", true); + break; + } + MenuActive = false; + S_StartSound(NULL, SFX_CHAT); + return false; +} + +//=========================================================================== +// +// SCNetCheck2 +// +//=========================================================================== + +static void SCNetCheck2(int option) +{ + SCNetCheck(option); + return; +} + +//--------------------------------------------------------------------------- +// +// PROC SCLoadGame +// +//--------------------------------------------------------------------------- + +static void SCLoadGame(int option) +{ + if (demoplayback) + { + // deactivate playback, return control to player + demoextend = false; + } + if (!SlotStatus[option]) + { // Don't try to load from an empty slot + return; + } + G_LoadGame(option); + MN_DeactivateMenu(); + BorderNeedRefresh = true; + if (quickload == -1) + { + quickload = option + 1; + P_ClearMessage(&players[consoleplayer]); + } +} + +// +// Generate a default save slot name when the user saves to +// an empty slot via the joypad. +// +static void SetDefaultSaveName(int slot) +{ + // map from IWAD or PWAD? + if (W_IsIWADLump(maplumpinfo) && strcmp(SavePath, "")) + { + M_snprintf(SlotText[slot], SLOTTEXTLEN, + "%s", maplumpinfo->name); + } + else + { + char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo)); + char *ext = strrchr(wadname, '.'); + + if (ext != NULL) + { + *ext = '\0'; + } + + M_snprintf(SlotText[slot], SLOTTEXTLEN, + "%s (%s)", maplumpinfo->name, + wadname); + free(wadname); + } + M_ForceUppercase(SlotText[slot]); + joypadsave = false; +} + +//--------------------------------------------------------------------------- +// +// PROC SCSaveGame +// +//--------------------------------------------------------------------------- + +static void SCSaveGame(int option) +{ + char *ptr; + + if (!FileMenuKeySteal) + { + int x, y; + + FileMenuKeySteal = true; + // We need to activate the text input interface to type the save + // game name: + x = SaveMenu.x + 1; + y = SaveMenu.y + 1 + option * ITEM_HEIGHT; + I_StartTextInput(x, y, x + 190, y + ITEM_HEIGHT - 2); + + M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText)); + ptr = SlotText[option]; + + if (!strcmp(ptr, "") && joypadsave) + { + SetDefaultSaveName(option); + } + + while (*ptr) + { + ptr++; + } + *ptr = '['; + *(ptr + 1) = 0; + SlotStatus[option]++; + currentSlot = option; + slotptr = ptr - SlotText[option]; + return; + } + else + { + G_SaveGame(option, SlotText[option]); + FileMenuKeySteal = false; + I_StopTextInput(); + MN_DeactivateMenu(); + } + BorderNeedRefresh = true; + if (quicksave == -1) + { + quicksave = option + 1; + P_ClearMessage(&players[consoleplayer]); + } +} + +//========================================================================== +// +// SCClass +// +//========================================================================== + +static void SCClass(int option) +{ + if (netgame) + { + P_SetMessage(&players[consoleplayer], + "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", + true); + return; + } + MenuPClass = option; + switch (MenuPClass) + { + case PCLASS_FIGHTER: + SkillMenu.x = 120; + SkillItems[0].text = "SQUIRE"; + SkillItems[1].text = "KNIGHT"; + SkillItems[2].text = "WARRIOR"; + SkillItems[3].text = "BERSERKER"; + SkillItems[4].text = "TITAN"; + break; + case PCLASS_CLERIC: + SkillMenu.x = 116; + SkillItems[0].text = "ALTAR BOY"; + SkillItems[1].text = "ACOLYTE"; + SkillItems[2].text = "PRIEST"; + SkillItems[3].text = "CARDINAL"; + SkillItems[4].text = "POPE"; + break; + case PCLASS_MAGE: + SkillMenu.x = 112; + SkillItems[0].text = "APPRENTICE"; + SkillItems[1].text = "ENCHANTER"; + SkillItems[2].text = "SORCERER"; + SkillItems[3].text = "WARLOCK"; + SkillItems[4].text = "ARCHIMAGE"; + break; + } + SetMenu(MENU_SKILL); +} + +//--------------------------------------------------------------------------- +// +// PROC SCSkill +// +//--------------------------------------------------------------------------- + +static void SCSkill(int option) +{ + if (demoplayback) + { + // deactivate playback, return control to player + demoextend = false; + } + + PlayerClass[consoleplayer] = MenuPClass; + G_DeferredNewGame(option); + SB_SetClassData(); + SB_state = -1; + MN_DeactivateMenu(); +} + +//--------------------------------------------------------------------------- +// +// PROC SCMouseSensi +// +//--------------------------------------------------------------------------- + +static void SCMouseSensi(int option) +{ + if (option == RIGHT_DIR) + { + if (mouseSensitivity < 9) + { + mouseSensitivity++; + } + } + else if (mouseSensitivity) + { + mouseSensitivity--; + } +} + +//--------------------------------------------------------------------------- +// +// PROC SCSfxVolume +// +//--------------------------------------------------------------------------- + +static void SCSfxVolume(int option) +{ + if (option == RIGHT_DIR) + { + if (snd_MaxVolume < 15) + { + snd_MaxVolume++; + } + } + else if (snd_MaxVolume) + { + snd_MaxVolume--; + } + soundchanged = true; // we'll set it when we leave the menu +} + +//--------------------------------------------------------------------------- +// +// PROC SCMusicVolume +// +//--------------------------------------------------------------------------- + +static void SCMusicVolume(int option) +{ + if (option == RIGHT_DIR) + { + if (snd_MusicVolume < 15) + { + snd_MusicVolume++; + } + } + else if (snd_MusicVolume) + { + snd_MusicVolume--; + } + S_SetMusicVolume(); +} + +//--------------------------------------------------------------------------- +// +// PROC SCScreenSize +// +//--------------------------------------------------------------------------- + +static void SCScreenSize(int option) +{ + if (option == RIGHT_DIR) + { + if (screenblocks < 11) + { + screenblocks++; + } + } + else if (screenblocks > 3) + { + screenblocks--; + } + R_SetViewSize(screenblocks, detailLevel); +} + +//--------------------------------------------------------------------------- +// +// PROC SCInfo +// +//--------------------------------------------------------------------------- + +static void SCInfo(int option) +{ + InfoType = 1; + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + if (!netgame && !demoplayback) + { + paused = true; + } +} + +//--------------------------------------------------------------------------- +// +// FUNC MN_Responder +// +//--------------------------------------------------------------------------- + +boolean MN_Responder(event_t * event) +{ + int key; + int charTyped; + int i; + MenuItem_t *item; + char *textBuffer; + int dir; + + // In testcontrols mode, none of the function keys should do anything + // - the only key is escape to quit. + + if (testcontrols) + { + if (event->type == ev_quit + || (event->type == ev_keydown + && (event->data1 == key_menu_activate + || event->data1 == key_menu_quit))) + { + I_Quit(); + return true; + } + + return false; + } + + // "close" button pressed on window? + if (event->type == ev_quit) + { + // First click on close = bring up quit confirm message. + // Second click = confirm quit. + + if (!MenuActive && askforquit && typeofask == 1) + { + G_CheckDemoStatus(); + I_Quit(); + } + else + { + SCQuitGame(0); + S_StartSound(NULL, SFX_CHAT); + } + + return true; + } + + charTyped = 0; + key = -1; + + if (event->type == ev_joystick) + { + // Simulate key presses from joystick events to interact with the menu. + + if (MenuActive) + { + if (JOY_GET_DPAD(event->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_DPAD(event->data6); + } + else if (JOY_GET_LSTICK(event->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_LSTICK(event->data6); + } + else + { + dir = JOY_GET_RSTICK(event->data6); + } + + if (dir & JOY_DIR_UP) + { + key = key_menu_up; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_DOWN) + { + key = key_menu_down; + joywait = I_GetTime() + 5; + } + if (dir & JOY_DIR_LEFT) + { + key = key_menu_left; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_RIGHT) + { + key = key_menu_right; + joywait = I_GetTime() + 5; + } + +#define JOY_BUTTON_MAPPED(x) ((x) >= 0) +#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (event->data1 & (1 << (x))) != 0) + + if (JOY_BUTTON_PRESSED(joybfire)) + { + // Simulate pressing "Enter" when we are supplying a save slot name + if (FileMenuKeySteal) + { + key = KEY_ENTER; + } + else + { + // if selecting a save slot via joypad, set a flag + if (CurrentMenu == &SaveMenu) + { + joypadsave = true; + } + key = key_menu_forward; + } + joywait = I_GetTime() + 5; + } + if (JOY_BUTTON_PRESSED(joybuse)) + { + // If user was entering a save name, back out + if (FileMenuKeySteal) + { + key = KEY_ESCAPE; + } + else + { + key = key_menu_back; + } + joywait = I_GetTime() + 5; + } + } + else if (askforquit) + { + if (JOY_BUTTON_PRESSED(joybfire)) + { + // Simulate a 'Y' keypress + key = key_menu_confirm; + joywait = I_GetTime() + 5; + } + if (JOY_BUTTON_PRESSED(joybuse)) + { + // Simulate a 'N' keypress + key = key_menu_abort; + joywait = I_GetTime() + 5; + } + } + if (JOY_BUTTON_PRESSED(joybmenu)) + { + MN_ActivateMenu(); + joywait = I_GetTime() + 5; + return true; + } + } + + if (event->type != ev_keydown && key == -1) + { + return false; + } + + if (event->type == ev_keydown) + { + key = event->data1; + charTyped = event->data2; + } + + if (InfoType) + { + /* The 4-Level Demo Version also has 3 Info pages + if (gamemode == shareware) + { + InfoType = (InfoType + 1) % 5; + } + else + */ + { + InfoType = (InfoType + 1) % 4; + } + if (key == KEY_ESCAPE) + { + InfoType = 0; + } + if (!InfoType) + { + if (!netgame && !demoplayback) + { + paused = false; + } + MN_DeactivateMenu(); + SB_state = -1; //refresh the statbar + BorderNeedRefresh = true; + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + return (true); //make the info screen eat the keypress + } + + if ((ravpic && key == KEY_F1) || + (key != 0 && key == key_menu_screenshot)) + { + G_ScreenShot(); + return (true); + } + + if (askforquit) + { + if (key == key_menu_confirm) + { + switch (typeofask) + { + case 1: + G_CheckDemoStatus(); + I_Quit(); + return false; + case 2: + P_ClearMessage(&players[consoleplayer]); + askforquit = false; + typeofask = 0; + paused = false; + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + H2_StartTitle(); // go to intro/demo mode. + return false; + case 3: + P_SetMessage(&players[consoleplayer], + "QUICKSAVING....", false); + FileMenuKeySteal = true; + SCSaveGame(quicksave - 1); + BorderNeedRefresh = true; + break; + case 4: + P_SetMessage(&players[consoleplayer], + "QUICKLOADING....", false); + SCLoadGame(quickload - 1); + BorderNeedRefresh = true; + break; + case 5: + BorderNeedRefresh = true; + mn_SuicideConsole = true; + break; + default: + break; + } + + askforquit = false; + typeofask = 0; + + return true; + } + else if (key == key_menu_abort || key == KEY_ESCAPE) + { + players[consoleplayer].messageTics = 0; + askforquit = false; + typeofask = 0; + paused = false; + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; + return true; + } + + return false; // don't let the keys filter thru + } + if (!MenuActive && !chatmodeon) + { + if (key == key_menu_decscreen) + { + if (automapactive) + { // Don't screen size in automap + return (false); + } + SCScreenSize(LEFT_DIR); + S_StartSound(NULL, SFX_PICKUP_KEY); + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + return (true); + } + else if (key == key_menu_incscreen) + { + if (automapactive) + { // Don't screen size in automap + return (false); + } + SCScreenSize(RIGHT_DIR); + S_StartSound(NULL, SFX_PICKUP_KEY); + BorderNeedRefresh = true; + UpdateState |= I_FULLSCRN; + return (true); + } + else if (key == key_menu_help) // F1 (help screen) + { + SCInfo(0); // start up info screens + MenuActive = true; + return (true); + } + else if (key == key_menu_save) // F2 (save game) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &SaveMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + slottextloaded = false; //reload the slot text, when needed + } + return true; + } + else if (key == key_menu_load) // F3 (load game) + { + if (SCNetCheck(2)) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &LoadMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + slottextloaded = false; //reload the slot text, when needed + } + return true; + } + else if (key == key_menu_volume) // F4 (volume) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &Options2Menu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + slottextloaded = false; //reload the slot text, when needed + return true; + } + else if (key == key_menu_detail) // F5 (suicide) + { + MenuActive = false; + askforquit = true; + typeofask = 5; // suicide + return true; + } + else if (key == key_menu_qsave) // F6 (quicksave) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + if (!quicksave || quicksave == -1) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &SaveMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + slottextloaded = false; //reload the slot text + quicksave = -1; + P_SetMessage(&players[consoleplayer], + "CHOOSE A QUICKSAVE SLOT", true); + } + else + { + askforquit = true; + typeofask = 3; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_CHAT); + } + } + return true; + } + else if (key == key_menu_endgame) // F7 (end game) + { + if (SCNetCheck(3)) + { + if (gamestate == GS_LEVEL && !demoplayback) + { + S_StartSound(NULL, SFX_CHAT); + SCEndGame(0); + } + } + return true; + } + else if (key == key_menu_messages) // F8 (toggle messages) + { + SCMessages(0); + return true; + } + else if (key == key_menu_qload) // F9 (quickload) + { + if (SCNetCheck(2)) + { + if (!quickload || quickload == -1) + { + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &LoadMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + slottextloaded = false; // reload the slot text + quickload = -1; + P_SetMessage(&players[consoleplayer], + "CHOOSE A QUICKLOAD SLOT", true); + } + else + { + askforquit = true; + if (!netgame && !demoplayback) + { + paused = true; + } + typeofask = 4; + S_StartSound(NULL, SFX_CHAT); + } + } + return true; + } + else if (key == key_menu_quit) // F10 (quit) + { + if (gamestate == GS_LEVEL || gamestate == GS_FINALE) + { + SCQuitGame(0); + S_StartSound(NULL, SFX_CHAT); + } + return true; + } + else if (key == key_menu_gamma) // F11 (gamma correction) + { + usegamma++; + if (usegamma > 4) + { + usegamma = 0; + } + SB_PaletteFlash(true); // force change + P_SetMessage(&players[consoleplayer], GammaText[usegamma], + false); + return true; + } + else if (key == KEY_F12) // F12 (???) + { + // F12 - reload current map (devmaps mode) + + if (netgame) + { + return false; + } + if (gamekeydown[key_speed]) + { // Monsters ON + nomonsters = false; + } + if (gamekeydown[key_strafe]) + { // Monsters OFF + nomonsters = true; + } + G_DeferedInitNew(gameskill, gameepisode, gamemap); + P_SetMessage(&players[consoleplayer], TXT_CHEATWARP, false); + return true; + } + } + + if (!MenuActive) + { + if (key == key_menu_activate || gamestate == GS_DEMOSCREEN || demoplayback) + { + MN_ActivateMenu(); + return (true); + } + return (false); + } + if (!FileMenuKeySteal) + { + item = &CurrentMenu->items[CurrentItPos]; + + if (key == key_menu_down) // Next menu item + { + do + { + if (CurrentItPos + 1 > CurrentMenu->itemCount - 1) + { + CurrentItPos = 0; + } + else + { + CurrentItPos++; + } + } + while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); + S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL); + return (true); + } + else if (key == key_menu_up) // Previous menu item + { + do + { + if (CurrentItPos == 0) + { + CurrentItPos = CurrentMenu->itemCount - 1; + } + else + { + CurrentItPos--; + } + } + while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); + S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL); + return (true); + } + else if (key == key_menu_left) // Slider left + { + if (item->type == ITT_LRFUNC && item->func != NULL) + { + item->func(LEFT_DIR); + S_StartSound(NULL, SFX_PICKUP_KEY); + } + return (true); + } + else if (key == key_menu_right) // Slider right + { + if (item->type == ITT_LRFUNC && item->func != NULL) + { + item->func(RIGHT_DIR); + S_StartSound(NULL, SFX_PICKUP_KEY); + } + return (true); + } + else if (key == key_menu_forward) // Activate item (enter) + { + if (item->type == ITT_SETMENU) + { + if (item->func != NULL) + { + item->func(item->option); + } + SetMenu(item->menu); + } + else if (item->func != NULL) + { + CurrentMenu->oldItPos = CurrentItPos; + if (item->type == ITT_LRFUNC) + { + item->func(RIGHT_DIR); + } + else if (item->type == ITT_EFUNC) + { + item->func(item->option); + } + } + S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); + return (true); + } + else if (key == key_menu_activate) + { + MN_DeactivateMenu(); + return (true); + } + else if (key == key_menu_back) + { + S_StartSound(NULL, SFX_PICKUP_KEY); + + if (CurrentMenu->prevMenu == MENU_NONE) + { + MN_DeactivateMenu(); + } + else + { + SetMenu(CurrentMenu->prevMenu); + } + return (true); + } + else if (charTyped != 0) + { + for (i = 0; i < CurrentMenu->itemCount; i++) + { + if (CurrentMenu->items[i].text) + { + if (toupper(charTyped) + == toupper(CurrentMenu->items[i].text[0])) + { + CurrentItPos = i; + return (true); + } + } + } + } + return (false); + } + else + { + // Editing file names + // When typing a savegame name, we use the fully shifted and + // translated input value from event->data3. + charTyped = event->data3; + textBuffer = &SlotText[currentSlot][slotptr]; + if (key == KEY_BACKSPACE) + { + if (slotptr) + { + *textBuffer = 0; + slotptr--; + textBuffer = &SlotText[currentSlot][slotptr]; + *textBuffer = ASCII_CURSOR; + } + return (true); + } + if (key == KEY_ESCAPE) + { + M_StringCopy(SlotText[currentSlot], oldSlotText, + sizeof(SlotText[currentSlot])); + SlotStatus[currentSlot]--; + MN_DeactivateMenu(); + return (true); + } + if (key == KEY_ENTER) + { + SlotText[currentSlot][slotptr] = 0; // clear the cursor + item = &CurrentMenu->items[CurrentItPos]; + CurrentMenu->oldItPos = CurrentItPos; + if (item->type == ITT_EFUNC) + { + item->func(item->option); + if (item->menu != MENU_NONE) + { + SetMenu(item->menu); + } + } + return (true); + } + if (slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE) + { + if (isalpha(charTyped)) + { + *textBuffer++ = toupper(charTyped); + *textBuffer = ASCII_CURSOR; + slotptr++; + return (true); + } + if (isdigit(charTyped) || charTyped == ' ' + || charTyped == ',' || charTyped == '.' || charTyped == '-' + || charTyped == '!') + { + *textBuffer++ = charTyped; + *textBuffer = ASCII_CURSOR; + slotptr++; + return (true); + } + } + return (true); + } + return (false); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_ActivateMenu +// +//--------------------------------------------------------------------------- + +void MN_ActivateMenu(void) +{ + if (MenuActive) + { + return; + } + if (paused) + { + S_ResumeSound(); + } + MenuActive = true; + FileMenuKeySteal = false; + MenuTime = 0; + CurrentMenu = &MainMenu; + CurrentItPos = CurrentMenu->oldItPos; + if (!netgame && !demoplayback) + { + paused = true; + } + S_StartSound(NULL, SFX_PLATFORM_STOP); + slottextloaded = false; //reload the slot text, when needed +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DeactivateMenu +// +//--------------------------------------------------------------------------- + +void MN_DeactivateMenu(void) +{ + if (CurrentMenu != NULL) + { + CurrentMenu->oldItPos = CurrentItPos; + } + MenuActive = false; + if (FileMenuKeySteal) + { + I_StopTextInput(); + } + if (!netgame) + { + paused = false; + } + S_StartSound(NULL, SFX_PLATFORM_STOP); + P_ClearMessage(&players[consoleplayer]); +} + +//--------------------------------------------------------------------------- +// +// PROC MN_DrawInfo +// +//--------------------------------------------------------------------------- + +void MN_DrawInfo(void) +{ + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + memcpy(I_VideoBuffer, + (byte *) W_CacheLumpNum(W_GetNumForName("TITLE") + InfoType, + PU_CACHE), SCREENWIDTH * SCREENHEIGHT); +// V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType, +// PU_CACHE)); +} + + +//--------------------------------------------------------------------------- +// +// PROC SetMenu +// +//--------------------------------------------------------------------------- + +static void SetMenu(MenuType_t menu) +{ + CurrentMenu->oldItPos = CurrentItPos; + CurrentMenu = Menus[menu]; + CurrentItPos = CurrentMenu->oldItPos; +} + +//--------------------------------------------------------------------------- +// +// PROC DrawSlider +// +//--------------------------------------------------------------------------- + +static void DrawSlider(Menu_t * menu, int item, int width, int slot) +{ + int x; + int y; + int x2; + int count; + + x = menu->x + 24; + y = menu->y + 2 + (item * ITEM_HEIGHT); + V_DrawPatch(x - 32, y, W_CacheLumpName("M_SLDLT", PU_CACHE)); + for (x2 = x, count = width; count--; x2 += 8) + { + V_DrawPatch(x2, y, W_CacheLumpName(count & 1 ? "M_SLDMD1" + : "M_SLDMD2", PU_CACHE)); + } + V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE)); + V_DrawPatch(x + 4 + slot * 8, y + 7, + W_CacheLumpName("M_SLDKB", PU_CACHE)); +} diff --git a/games/NXDoom/src/hexen/p_acs.c b/games/NXDoom/src/hexen/p_acs.c new file mode 100644 index 00000000000..33d0480b6e7 --- /dev/null +++ b/games/NXDoom/src/hexen/p_acs.c @@ -0,0 +1,1996 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "m_misc.h" +#include "m_random.h" +#include "s_sound.h" +#include "i_swap.h" +#include "i_system.h" +#include "p_local.h" + +// MACROS ------------------------------------------------------------------ + +#define MAX_SCRIPT_ARGS 3 +#define SCRIPT_CONTINUE 0 +#define SCRIPT_STOP 1 +#define SCRIPT_TERMINATE 2 +#define OPEN_SCRIPTS_BASE 1000 +#define PRINT_BUFFER_SIZE 256 +#define GAME_SINGLE_PLAYER 0 +#define GAME_NET_COOPERATIVE 1 +#define GAME_NET_DEATHMATCH 2 +#define TEXTURE_TOP 0 +#define TEXTURE_MIDDLE 1 +#define TEXTURE_BOTTOM 2 + +// TYPES ------------------------------------------------------------------- + +typedef PACKED_STRUCT ( +{ + int marker; + int infoOffset; + int code; +}) acsHeader_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void StartOpenACS(int number, int infoIndex, int offset); +static void ScriptFinished(int number); +static boolean TagBusy(int tag); +static boolean AddToACSStore(int map, int number, byte * args); +static int GetACSIndex(int number); +static void Push(int value); +static int Pop(void); +static int Top(void); +static void Drop(void); + +static int CmdNOP(void); +static int CmdTerminate(void); +static int CmdSuspend(void); +static int CmdPushNumber(void); +static int CmdLSpec1(void); +static int CmdLSpec2(void); +static int CmdLSpec3(void); +static int CmdLSpec4(void); +static int CmdLSpec5(void); +static int CmdLSpec1Direct(void); +static int CmdLSpec2Direct(void); +static int CmdLSpec3Direct(void); +static int CmdLSpec4Direct(void); +static int CmdLSpec5Direct(void); +static int CmdAdd(void); +static int CmdSubtract(void); +static int CmdMultiply(void); +static int CmdDivide(void); +static int CmdModulus(void); +static int CmdEQ(void); +static int CmdNE(void); +static int CmdLT(void); +static int CmdGT(void); +static int CmdLE(void); +static int CmdGE(void); +static int CmdAssignScriptVar(void); +static int CmdAssignMapVar(void); +static int CmdAssignWorldVar(void); +static int CmdPushScriptVar(void); +static int CmdPushMapVar(void); +static int CmdPushWorldVar(void); +static int CmdAddScriptVar(void); +static int CmdAddMapVar(void); +static int CmdAddWorldVar(void); +static int CmdSubScriptVar(void); +static int CmdSubMapVar(void); +static int CmdSubWorldVar(void); +static int CmdMulScriptVar(void); +static int CmdMulMapVar(void); +static int CmdMulWorldVar(void); +static int CmdDivScriptVar(void); +static int CmdDivMapVar(void); +static int CmdDivWorldVar(void); +static int CmdModScriptVar(void); +static int CmdModMapVar(void); +static int CmdModWorldVar(void); +static int CmdIncScriptVar(void); +static int CmdIncMapVar(void); +static int CmdIncWorldVar(void); +static int CmdDecScriptVar(void); +static int CmdDecMapVar(void); +static int CmdDecWorldVar(void); +static int CmdGoto(void); +static int CmdIfGoto(void); +static int CmdDrop(void); +static int CmdDelay(void); +static int CmdDelayDirect(void); +static int CmdRandom(void); +static int CmdRandomDirect(void); +static int CmdThingCount(void); +static int CmdThingCountDirect(void); +static int CmdTagWait(void); +static int CmdTagWaitDirect(void); +static int CmdPolyWait(void); +static int CmdPolyWaitDirect(void); +static int CmdChangeFloor(void); +static int CmdChangeFloorDirect(void); +static int CmdChangeCeiling(void); +static int CmdChangeCeilingDirect(void); +static int CmdRestart(void); +static int CmdAndLogical(void); +static int CmdOrLogical(void); +static int CmdAndBitwise(void); +static int CmdOrBitwise(void); +static int CmdEorBitwise(void); +static int CmdNegateLogical(void); +static int CmdLShift(void); +static int CmdRShift(void); +static int CmdUnaryMinus(void); +static int CmdIfNotGoto(void); +static int CmdLineSide(void); +static int CmdScriptWait(void); +static int CmdScriptWaitDirect(void); +static int CmdClearLineSpecial(void); +static int CmdCaseGoto(void); +static int CmdBeginPrint(void); +static int CmdEndPrint(void); +static int CmdPrintString(void); +static int CmdPrintNumber(void); +static int CmdPrintCharacter(void); +static int CmdPlayerCount(void); +static int CmdGameType(void); +static int CmdGameSkill(void); +static int CmdTimer(void); +static int CmdSectorSound(void); +static int CmdAmbientSound(void); +static int CmdSoundSequence(void); +static int CmdSetLineTexture(void); +static int CmdSetLineBlocking(void); +static int CmdSetLineSpecial(void); +static int CmdThingSound(void); +static int CmdEndPrintBold(void); + +static void ThingCount(int type, int tid); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +int ACScriptCount; +byte *ActionCodeBase; +static int ActionCodeSize; +acsInfo_t *ACSInfo; +int MapVars[MAX_ACS_MAP_VARS]; +int WorldVars[MAX_ACS_WORLD_VARS]; +acsstore_t ACSStore[MAX_ACS_STORE + 1]; // +1 for termination marker + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static char EvalContext[64]; +static acs_t *ACScript; +static unsigned int PCodeOffset; +static byte SpecArgs[8]; +static int ACStringCount; +static char **ACStrings; +static char PrintBuffer[PRINT_BUFFER_SIZE]; +static acs_t *NewScript; + +static int (*PCodeCmds[]) (void) = +{ + CmdNOP, + CmdTerminate, + CmdSuspend, + CmdPushNumber, + CmdLSpec1, + CmdLSpec2, + CmdLSpec3, + CmdLSpec4, + CmdLSpec5, + CmdLSpec1Direct, + CmdLSpec2Direct, + CmdLSpec3Direct, + CmdLSpec4Direct, + CmdLSpec5Direct, + CmdAdd, + CmdSubtract, + CmdMultiply, + CmdDivide, + CmdModulus, + CmdEQ, + CmdNE, + CmdLT, + CmdGT, + CmdLE, + CmdGE, + CmdAssignScriptVar, + CmdAssignMapVar, + CmdAssignWorldVar, + CmdPushScriptVar, + CmdPushMapVar, + CmdPushWorldVar, + CmdAddScriptVar, + CmdAddMapVar, + CmdAddWorldVar, + CmdSubScriptVar, + CmdSubMapVar, + CmdSubWorldVar, + CmdMulScriptVar, + CmdMulMapVar, + CmdMulWorldVar, + CmdDivScriptVar, + CmdDivMapVar, + CmdDivWorldVar, + CmdModScriptVar, + CmdModMapVar, + CmdModWorldVar, + CmdIncScriptVar, + CmdIncMapVar, + CmdIncWorldVar, + CmdDecScriptVar, + CmdDecMapVar, + CmdDecWorldVar, + CmdGoto, + CmdIfGoto, + CmdDrop, + CmdDelay, + CmdDelayDirect, + CmdRandom, + CmdRandomDirect, + CmdThingCount, + CmdThingCountDirect, + CmdTagWait, + CmdTagWaitDirect, + CmdPolyWait, + CmdPolyWaitDirect, + CmdChangeFloor, + CmdChangeFloorDirect, + CmdChangeCeiling, + CmdChangeCeilingDirect, + CmdRestart, + CmdAndLogical, + CmdOrLogical, + CmdAndBitwise, + CmdOrBitwise, + CmdEorBitwise, + CmdNegateLogical, + CmdLShift, + CmdRShift, + CmdUnaryMinus, + CmdIfNotGoto, + CmdLineSide, + CmdScriptWait, + CmdScriptWaitDirect, + CmdClearLineSpecial, + CmdCaseGoto, + CmdBeginPrint, + CmdEndPrint, + CmdPrintString, + CmdPrintNumber, + CmdPrintCharacter, + CmdPlayerCount, + CmdGameType, + CmdGameSkill, + CmdTimer, + CmdSectorSound, + CmdAmbientSound, + CmdSoundSequence, + CmdSetLineTexture, + CmdSetLineBlocking, + CmdSetLineSpecial, + CmdThingSound, + CmdEndPrintBold, +}; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// ACSAssert +// +// Check that the given condition evaluates to true. If it does not, exit +// with an I_Error() printing the given message. +// +//========================================================================== + +static void ACSAssert(int condition, const char *fmt, ...) +{ + char buf[128]; + va_list args; + + if (condition) + { + return; + } + + va_start(args, fmt); + M_vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + I_Error("ACS assertion failure: in %s: %s", EvalContext, buf); +} + +//========================================================================== +// +// ReadCodeInt +// +// Read a 32-bit value from the loaded ACS lump at the location pointed to +// by PCodeOffset, advancing PCodeOffset to the next value in the process. +// +//========================================================================== + +static int ReadCodeInt(void) +{ + int result; + int *ptr; + + ACSAssert(PCodeOffset + 3 < ActionCodeSize, + "unexpectedly reached end of ACS lump"); + + ptr = (int *) (ActionCodeBase + PCodeOffset); + result = LONG(*ptr); + PCodeOffset += 4; + + return result; +} + +//========================================================================== +// +// ReadScriptVar +// +// Read a script variable index as an immediate value, validating the +// result is a valid script variable number. +// +//========================================================================== + +static int ReadScriptVar(void) +{ + int var = ReadCodeInt(); + ACSAssert(var >= 0, "negative script variable: %d < 0", var); + ACSAssert(var < MAX_ACS_SCRIPT_VARS, + "invalid script variable: %d >= %d", var, MAX_ACS_SCRIPT_VARS); + return var; +} + +//========================================================================== +// +// ReadMapVar +// +// Read a map variable index as an immediate value, validating the +// result is a valid map variable number. +// +//========================================================================== + +static int ReadMapVar(void) +{ + int var = ReadCodeInt(); + ACSAssert(var >= 0, "negative map variable: %d < 0", var); + ACSAssert(var < MAX_ACS_MAP_VARS, + "invalid map variable: %d >= %d", var, MAX_ACS_MAP_VARS); + return var; +} + +//========================================================================== +// +// ReadWorldVar +// +// Read a world variable index as an immediate value, validating the +// result is a valid world variable number. +// +//========================================================================== + +static int ReadWorldVar(void) +{ + int var = ReadCodeInt(); + ACSAssert(var >= 0, "negative world variable: %d < 0", var); + ACSAssert(var < MAX_ACS_WORLD_VARS, + "invalid world variable: %d >= %d", var, MAX_ACS_WORLD_VARS); + return var; +} + +//========================================================================== +// +// StringLookup +// +// Look up the given string in the strings table by index, validating that +// it is a valid string index. +// +//========================================================================== + +static char *StringLookup(int string_index) +{ + ACSAssert(string_index >= 0, + "negative string index: %d < 0", string_index); + ACSAssert(string_index < ACStringCount, + "invalid string index: %d >= %d", string_index, ACStringCount); + return ACStrings[string_index]; +} + +//========================================================================== +// +// ReadOffset +// +// Read a lump offset value, validating that it is an offset within the +// range of the lump. +// +//========================================================================== + +static int ReadOffset(void) +{ + int offset = ReadCodeInt(); + ACSAssert(offset >= 0, "negative lump offset %d", offset); + ACSAssert(offset < ActionCodeSize, "invalid lump offset: %d >= %d", + offset, ActionCodeSize); + return offset; +} + +//========================================================================== +// +// P_LoadACScripts +// +//========================================================================== + +void P_LoadACScripts(int lump) +{ + int i, offset; + acsHeader_t *header; + acsInfo_t *info; + + ActionCodeBase = W_CacheLumpNum(lump, PU_LEVEL); + ActionCodeSize = W_LumpLength(lump); + + M_snprintf(EvalContext, sizeof(EvalContext), + "header parsing of lump #%d", lump); + + header = (acsHeader_t *) ActionCodeBase; + PCodeOffset = LONG(header->infoOffset); + + ACScriptCount = ReadCodeInt(); + + if (ACScriptCount == 0) + { // Empty behavior lump + return; + } + + ACSInfo = Z_Malloc(ACScriptCount * sizeof(acsInfo_t), PU_LEVEL, 0); + memset(ACSInfo, 0, ACScriptCount * sizeof(acsInfo_t)); + for (i = 0, info = ACSInfo; i < ACScriptCount; i++, info++) + { + info->number = ReadCodeInt(); + info->offset = ReadOffset(); + info->argCount = ReadCodeInt(); + + if (info->argCount > MAX_SCRIPT_ARGS) + { + fprintf(stderr, "Warning: ACS script #%i has %i arguments, more " + "than the maximum of %i. Enforcing limit.\n" + "If you are seeing this message, please report " + "the name of the WAD where you saw it.\n", + i, info->argCount, MAX_SCRIPT_ARGS); + info->argCount = MAX_SCRIPT_ARGS; + } + + if (info->number >= OPEN_SCRIPTS_BASE) + { // Auto-activate + info->number -= OPEN_SCRIPTS_BASE; + StartOpenACS(info->number, i, info->offset); + info->state = ASTE_RUNNING; + } + else + { + info->state = ASTE_INACTIVE; + } + } + + ACStringCount = ReadCodeInt(); + ACSAssert(ACStringCount >= 0, "negative string count %d", ACStringCount); + ACStrings = Z_Malloc(ACStringCount * sizeof(char *), PU_LEVEL, NULL); + + for (i=0; inumber = number; + + // World objects are allotted 1 second for initialization + script->delayCount = 35; + + script->infoIndex = infoIndex; + script->ip = offset; + script->thinker.function = T_InterpretACS; + P_AddThinker(&script->thinker); +} + +//========================================================================== +// +// P_CheckACSStore +// +// Scans the ACS store and executes all scripts belonging to the current +// map. +// +//========================================================================== + +void P_CheckACSStore(void) +{ + acsstore_t *store; + + for (store = ACSStore; store->map != 0; store++) + { + if (store->map == gamemap) + { + P_StartACS(store->script, 0, store->args, NULL, NULL, 0); + if (NewScript) + { + NewScript->delayCount = 35; + } + store->map = -1; + } + } +} + +//========================================================================== +// +// P_StartACS +// +// Start an ACS script. The 'args' array should be at least MAX_SCRIPT_ARGS +// elements in length. +// +//========================================================================== + +static char ErrorMsg[128]; + +boolean P_StartACS(int number, int map, byte * args, mobj_t * activator, + line_t * line, int side) +{ + int i; + acs_t *script; + int infoIndex; + aste_t *statePtr; + + NewScript = NULL; + if (map && map != gamemap) + { // Add to the script store + return AddToACSStore(map, number, args); + } + infoIndex = GetACSIndex(number); + if (infoIndex == -1) + { // Script not found + //I_Error("P_StartACS: Unknown script number %d", number); + M_snprintf(ErrorMsg, sizeof(ErrorMsg), + "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number); + P_SetMessage(&players[consoleplayer], ErrorMsg, true); + } + statePtr = &ACSInfo[infoIndex].state; + if (*statePtr == ASTE_SUSPENDED) + { // Resume a suspended script + *statePtr = ASTE_RUNNING; + return true; + } + if (*statePtr != ASTE_INACTIVE) + { // Script is already executing + return false; + } + script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0); + memset(script, 0, sizeof(acs_t)); + script->number = number; + script->infoIndex = infoIndex; + script->activator = activator; + script->line = line; + script->side = side; + script->ip = ACSInfo[infoIndex].offset; + script->thinker.function = T_InterpretACS; + for (i = 0; i < MAX_SCRIPT_ARGS && i < ACSInfo[infoIndex].argCount; i++) + { + script->vars[i] = args[i]; + } + *statePtr = ASTE_RUNNING; + P_AddThinker(&script->thinker); + NewScript = script; + return true; +} + +//========================================================================== +// +// AddToACSStore +// +//========================================================================== + +static boolean AddToACSStore(int map, int number, byte * args) +{ + int i; + int index; + + index = -1; + for (i = 0; ACSStore[i].map != 0; i++) + { + if (ACSStore[i].script == number && ACSStore[i].map == map) + { // Don't allow duplicates + return false; + } + if (index == -1 && ACSStore[i].map == -1) + { // Remember first empty slot + index = i; + } + } + if (index == -1) + { // Append required + if (i == MAX_ACS_STORE) + { + I_Error("AddToACSStore: MAX_ACS_STORE (%d) exceeded.", + MAX_ACS_STORE); + } + index = i; + ACSStore[index + 1].map = 0; + } + ACSStore[index].map = map; + ACSStore[index].script = number; + memcpy(ACSStore[index].args, args, MAX_SCRIPT_ARGS); + return true; +} + +//========================================================================== +// +// P_StartLockedACS +// +//========================================================================== + + +boolean P_StartLockedACS(line_t * line, byte * args, mobj_t * mo, int side) +{ + int i; + int lock; + byte newArgs[5]; + char LockedBuffer[80]; + + lock = args[4]; + if (!mo->player) + { + return false; + } + if (lock) + { + if (!(mo->player->keys & (1 << (lock - 1)))) + { + M_snprintf(LockedBuffer, sizeof(LockedBuffer), + "YOU NEED THE %s\n", TextKeyMessages[lock - 1]); + P_SetMessage(mo->player, LockedBuffer, true); + S_StartSound(mo, SFX_DOOR_LOCKED); + return false; + } + } + for (i = 0; i < 4; i++) + { + newArgs[i] = args[i]; + } + newArgs[4] = 0; + return P_StartACS(newArgs[0], newArgs[1], &newArgs[2], mo, line, side); +} + +//========================================================================== +// +// P_TerminateACS +// +//========================================================================== + +boolean P_TerminateACS(int number, int map) +{ + int infoIndex; + + infoIndex = GetACSIndex(number); + if (infoIndex == -1) + { // Script not found + return false; + } + if (ACSInfo[infoIndex].state == ASTE_INACTIVE + || ACSInfo[infoIndex].state == ASTE_TERMINATING) + { // States that disallow termination + return false; + } + ACSInfo[infoIndex].state = ASTE_TERMINATING; + return true; +} + +//========================================================================== +// +// P_SuspendACS +// +//========================================================================== + +boolean P_SuspendACS(int number, int map) +{ + int infoIndex; + + infoIndex = GetACSIndex(number); + if (infoIndex == -1) + { // Script not found + return false; + } + if (ACSInfo[infoIndex].state == ASTE_INACTIVE + || ACSInfo[infoIndex].state == ASTE_SUSPENDED + || ACSInfo[infoIndex].state == ASTE_TERMINATING) + { // States that disallow suspension + return false; + } + ACSInfo[infoIndex].state = ASTE_SUSPENDED; + return true; +} + +//========================================================================== +// +// P_Init +// +//========================================================================== + +void P_ACSInitNewGame(void) +{ + memset(WorldVars, 0, sizeof(WorldVars)); + memset(ACSStore, 0, sizeof(ACSStore)); +} + +//========================================================================== +// +// T_InterpretACS +// +//========================================================================== + +void T_InterpretACS(thinker_t *thinker) +{ + acs_t *script = (acs_t *) thinker; + int cmd; + int action; + + if (ACSInfo[script->infoIndex].state == ASTE_TERMINATING) + { + ACSInfo[script->infoIndex].state = ASTE_INACTIVE; + ScriptFinished(ACScript->number); + P_RemoveThinker(&ACScript->thinker); + return; + } + if (ACSInfo[script->infoIndex].state != ASTE_RUNNING) + { + return; + } + if (script->delayCount) + { + script->delayCount--; + return; + } + ACScript = script; + PCodeOffset = ACScript->ip; + + do + { + M_snprintf(EvalContext, sizeof(EvalContext), "script %d @0x%x", + ACSInfo[script->infoIndex].number, PCodeOffset); + cmd = ReadCodeInt(); + M_snprintf(EvalContext, sizeof(EvalContext), "script %d @0x%x, cmd=%d", + ACSInfo[script->infoIndex].number, PCodeOffset, cmd); + ACSAssert(cmd >= 0, "negative ACS instruction %d", cmd); + ACSAssert(cmd < arrlen(PCodeCmds), + "invalid ACS instruction %d (maybe this WAD is designed " + "for an advanced source port and is not vanilla " + "compatible)", cmd); + action = PCodeCmds[cmd](); + } while (action == SCRIPT_CONTINUE); + + ACScript->ip = PCodeOffset; + + if (action == SCRIPT_TERMINATE) + { + ACSInfo[script->infoIndex].state = ASTE_INACTIVE; + ScriptFinished(ACScript->number); + P_RemoveThinker(&ACScript->thinker); + } +} + +//========================================================================== +// +// P_TagFinished +// +//========================================================================== + +void P_TagFinished(int tag) +{ + int i; + + if (TagBusy(tag) == true) + { + return; + } + for (i = 0; i < ACScriptCount; i++) + { + if (ACSInfo[i].state == ASTE_WAITINGFORTAG + && ACSInfo[i].waitValue == tag) + { + ACSInfo[i].state = ASTE_RUNNING; + } + } +} + +//========================================================================== +// +// P_PolyobjFinished +// +//========================================================================== + +void P_PolyobjFinished(int po) +{ + int i; + + if (PO_Busy(po) == true) + { + return; + } + for (i = 0; i < ACScriptCount; i++) + { + if (ACSInfo[i].state == ASTE_WAITINGFORPOLY + && ACSInfo[i].waitValue == po) + { + ACSInfo[i].state = ASTE_RUNNING; + } + } +} + +//========================================================================== +// +// ScriptFinished +// +//========================================================================== + +static void ScriptFinished(int number) +{ + int i; + + for (i = 0; i < ACScriptCount; i++) + { + if (ACSInfo[i].state == ASTE_WAITINGFORSCRIPT + && ACSInfo[i].waitValue == number) + { + ACSInfo[i].state = ASTE_RUNNING; + } + } +} + +//========================================================================== +// +// TagBusy +// +//========================================================================== + +static boolean TagBusy(int tag) +{ + int sectorIndex; + + sectorIndex = -1; + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) + { + if (sectors[sectorIndex].specialdata) + { + return true; + } + } + return false; +} + +//========================================================================== +// +// GetACSIndex +// +// Returns the index of a script number. Returns -1 if the script number +// is not found. +// +//========================================================================== + +static int GetACSIndex(int number) +{ + int i; + + for (i = 0; i < ACScriptCount; i++) + { + if (ACSInfo[i].number == number) + { + return i; + } + } + return -1; +} + +//========================================================================== +// +// CheckACSPresent +// +// Placing Korax in a PWAD without extra steps will result in a crash in +// Vanilla because the relevant ACS scripts are not initialized +// +//========================================================================== + +void CheckACSPresent(int number) +{ + if (GetACSIndex(number) == -1) + { + I_Error("Required ACS script %d not initialized", number); + } +} + +//========================================================================== +// +// Push +// +//========================================================================== + +static void Push(int value) +{ + ACSAssert(ACScript->stackPtr < ACS_STACK_DEPTH, + "maximum stack depth exceeded: %d >= %d", + ACScript->stackPtr, ACS_STACK_DEPTH); + ACScript->stack[ACScript->stackPtr++] = value; +} + +//========================================================================== +// +// Pop +// +//========================================================================== + +static int Pop(void) +{ + ACSAssert(ACScript->stackPtr > 0, "pop of empty stack"); + return ACScript->stack[--ACScript->stackPtr]; +} + +//========================================================================== +// +// Top +// +//========================================================================== + +static int Top(void) +{ + ACSAssert(ACScript->stackPtr > 0, "read from top of empty stack"); + return ACScript->stack[ACScript->stackPtr - 1]; +} + +//========================================================================== +// +// Drop +// +//========================================================================== + +static void Drop(void) +{ + ACSAssert(ACScript->stackPtr > 0, "drop on empty stack"); + ACScript->stackPtr--; +} + +//========================================================================== +// +// P-Code Commands +// +//========================================================================== + +static int CmdNOP(void) +{ + return SCRIPT_CONTINUE; +} + +static int CmdTerminate(void) +{ + return SCRIPT_TERMINATE; +} + +static int CmdSuspend(void) +{ + ACSInfo[ACScript->infoIndex].state = ASTE_SUSPENDED; + return SCRIPT_STOP; +} + +static int CmdPushNumber(void) +{ + Push(ReadCodeInt()); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec1(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[0] = Pop(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec2(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[1] = Pop(); + SpecArgs[0] = Pop(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec3(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[2] = Pop(); + SpecArgs[1] = Pop(); + SpecArgs[0] = Pop(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec4(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[3] = Pop(); + SpecArgs[2] = Pop(); + SpecArgs[1] = Pop(); + SpecArgs[0] = Pop(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec5(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[4] = Pop(); + SpecArgs[3] = Pop(); + SpecArgs[2] = Pop(); + SpecArgs[1] = Pop(); + SpecArgs[0] = Pop(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec1Direct(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[0] = ReadCodeInt(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec2Direct(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[0] = ReadCodeInt(); + SpecArgs[1] = ReadCodeInt(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec3Direct(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[0] = ReadCodeInt(); + SpecArgs[1] = ReadCodeInt(); + SpecArgs[2] = ReadCodeInt(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec4Direct(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[0] = ReadCodeInt(); + SpecArgs[1] = ReadCodeInt(); + SpecArgs[2] = ReadCodeInt(); + SpecArgs[3] = ReadCodeInt(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdLSpec5Direct(void) +{ + int special; + + special = ReadCodeInt(); + SpecArgs[0] = ReadCodeInt(); + SpecArgs[1] = ReadCodeInt(); + SpecArgs[2] = ReadCodeInt(); + SpecArgs[3] = ReadCodeInt(); + SpecArgs[4] = ReadCodeInt(); + P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, + ACScript->side, ACScript->activator); + return SCRIPT_CONTINUE; +} + +static int CmdAdd(void) +{ + Push(Pop() + Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdSubtract(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() - operand2); + return SCRIPT_CONTINUE; +} + +static int CmdMultiply(void) +{ + Push(Pop() * Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdDivide(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() / operand2); + return SCRIPT_CONTINUE; +} + +static int CmdModulus(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() % operand2); + return SCRIPT_CONTINUE; +} + +static int CmdEQ(void) +{ + Push(Pop() == Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdNE(void) +{ + Push(Pop() != Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdLT(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() < operand2); + return SCRIPT_CONTINUE; +} + +static int CmdGT(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() > operand2); + return SCRIPT_CONTINUE; +} + +static int CmdLE(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() <= operand2); + return SCRIPT_CONTINUE; +} + +static int CmdGE(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() >= operand2); + return SCRIPT_CONTINUE; +} + +static int CmdAssignScriptVar(void) +{ + ACScript->vars[ReadScriptVar()] = Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdAssignMapVar(void) +{ + MapVars[ReadMapVar()] = Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdAssignWorldVar(void) +{ + WorldVars[ReadWorldVar()] = Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdPushScriptVar(void) +{ + Push(ACScript->vars[ReadScriptVar()]); + return SCRIPT_CONTINUE; +} + +static int CmdPushMapVar(void) +{ + Push(MapVars[ReadMapVar()]); + return SCRIPT_CONTINUE; +} + +static int CmdPushWorldVar(void) +{ + Push(WorldVars[ReadWorldVar()]); + return SCRIPT_CONTINUE; +} + +static int CmdAddScriptVar(void) +{ + ACScript->vars[ReadScriptVar()] += Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdAddMapVar(void) +{ + MapVars[ReadMapVar()] += Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdAddWorldVar(void) +{ + WorldVars[ReadWorldVar()] += Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdSubScriptVar(void) +{ + ACScript->vars[ReadScriptVar()] -= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdSubMapVar(void) +{ + MapVars[ReadMapVar()] -= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdSubWorldVar(void) +{ + WorldVars[ReadWorldVar()] -= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdMulScriptVar(void) +{ + ACScript->vars[ReadScriptVar()] *= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdMulMapVar(void) +{ + MapVars[ReadMapVar()] *= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdMulWorldVar(void) +{ + WorldVars[ReadWorldVar()] *= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdDivScriptVar(void) +{ + ACScript->vars[ReadScriptVar()] /= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdDivMapVar(void) +{ + MapVars[ReadMapVar()] /= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdDivWorldVar(void) +{ + WorldVars[ReadWorldVar()] /= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdModScriptVar(void) +{ + ACScript->vars[ReadScriptVar()] %= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdModMapVar(void) +{ + MapVars[ReadMapVar()] %= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdModWorldVar(void) +{ + WorldVars[ReadWorldVar()] %= Pop(); + return SCRIPT_CONTINUE; +} + +static int CmdIncScriptVar(void) +{ + ++ACScript->vars[ReadScriptVar()]; + return SCRIPT_CONTINUE; +} + +static int CmdIncMapVar(void) +{ + ++MapVars[ReadMapVar()]; + return SCRIPT_CONTINUE; +} + +static int CmdIncWorldVar(void) +{ + ++WorldVars[ReadWorldVar()]; + return SCRIPT_CONTINUE; +} + +static int CmdDecScriptVar(void) +{ + --ACScript->vars[ReadScriptVar()]; + return SCRIPT_CONTINUE; +} + +static int CmdDecMapVar(void) +{ + --MapVars[ReadMapVar()]; + return SCRIPT_CONTINUE; +} + +static int CmdDecWorldVar(void) +{ + --WorldVars[ReadWorldVar()]; + return SCRIPT_CONTINUE; +} + +static int CmdGoto(void) +{ + PCodeOffset = ReadOffset(); + return SCRIPT_CONTINUE; +} + +static int CmdIfGoto(void) +{ + int offset; + + offset = ReadOffset(); + + if (Pop() != 0) + { + PCodeOffset = offset; + } + return SCRIPT_CONTINUE; +} + +static int CmdDrop(void) +{ + Drop(); + return SCRIPT_CONTINUE; +} + +static int CmdDelay(void) +{ + ACScript->delayCount = Pop(); + return SCRIPT_STOP; +} + +static int CmdDelayDirect(void) +{ + ACScript->delayCount = ReadCodeInt(); + return SCRIPT_STOP; +} + +static int CmdRandom(void) +{ + int low; + int high; + + high = Pop(); + low = Pop(); + Push(low + (P_Random() % (high - low + 1))); + return SCRIPT_CONTINUE; +} + +static int CmdRandomDirect(void) +{ + int low; + int high; + + low = ReadCodeInt(); + high = ReadCodeInt(); + Push(low + (P_Random() % (high - low + 1))); + return SCRIPT_CONTINUE; +} + +static int CmdThingCount(void) +{ + int tid; + + tid = Pop(); + ThingCount(Pop(), tid); + return SCRIPT_CONTINUE; +} + +static int CmdThingCountDirect(void) +{ + int type; + + type = ReadCodeInt(); + ThingCount(type, ReadCodeInt()); + return SCRIPT_CONTINUE; +} + +static void ThingCount(int type, int tid) +{ + int count; + int searcher; + mobj_t *mobj; + mobjtype_t moType; + thinker_t *think; + + if (!(type + tid)) + { // Nothing to count + return; + } + moType = TranslateThingType[type]; + count = 0; + searcher = -1; + if (tid) + { // Count TID things + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + if (type == 0) + { // Just count TIDs + count++; + } + else if (moType == mobj->type) + { + if (mobj->flags & MF_COUNTKILL && mobj->health <= 0) + { // Don't count dead monsters + continue; + } + count++; + } + } + } + else + { // Count only types + for (think = thinkercap.next; think != &thinkercap; + think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mobj = (mobj_t *) think; + if (mobj->type != moType) + { // Doesn't match + continue; + } + if (mobj->flags & MF_COUNTKILL && mobj->health <= 0) + { // Don't count dead monsters + continue; + } + count++; + } + } + Push(count); +} + +static int CmdTagWait(void) +{ + ACSInfo[ACScript->infoIndex].waitValue = Pop(); + ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG; + return SCRIPT_STOP; +} + +static int CmdTagWaitDirect(void) +{ + ACSInfo[ACScript->infoIndex].waitValue = ReadCodeInt(); + ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG; + return SCRIPT_STOP; +} + +static int CmdPolyWait(void) +{ + ACSInfo[ACScript->infoIndex].waitValue = Pop(); + ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY; + return SCRIPT_STOP; +} + +static int CmdPolyWaitDirect(void) +{ + ACSInfo[ACScript->infoIndex].waitValue = ReadCodeInt(); + ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY; + return SCRIPT_STOP; +} + +static int CmdChangeFloor(void) +{ + int tag; + int flat; + int sectorIndex; + + flat = R_FlatNumForName(StringLookup(Pop())); + tag = Pop(); + sectorIndex = -1; + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) + { + sectors[sectorIndex].floorpic = flat; + } + return SCRIPT_CONTINUE; +} + +static int CmdChangeFloorDirect(void) +{ + int tag; + int flat; + int sectorIndex; + + tag = ReadCodeInt(); + flat = R_FlatNumForName(StringLookup(ReadCodeInt())); + sectorIndex = -1; + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) + { + sectors[sectorIndex].floorpic = flat; + } + return SCRIPT_CONTINUE; +} + +static int CmdChangeCeiling(void) +{ + int tag; + int flat; + int sectorIndex; + + flat = R_FlatNumForName(StringLookup(Pop())); + tag = Pop(); + sectorIndex = -1; + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) + { + sectors[sectorIndex].ceilingpic = flat; + } + return SCRIPT_CONTINUE; +} + +static int CmdChangeCeilingDirect(void) +{ + int tag; + int flat; + int sectorIndex; + + tag = ReadCodeInt(); + flat = R_FlatNumForName(StringLookup(ReadCodeInt())); + sectorIndex = -1; + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) + { + sectors[sectorIndex].ceilingpic = flat; + } + return SCRIPT_CONTINUE; +} + +static int CmdRestart(void) +{ + PCodeOffset = ACSInfo[ACScript->infoIndex].offset; + return SCRIPT_CONTINUE; +} + +static int CmdAndLogical(void) +{ + Push(Pop() && Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdOrLogical(void) +{ + Push(Pop() || Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdAndBitwise(void) +{ + Push(Pop() & Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdOrBitwise(void) +{ + Push(Pop() | Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdEorBitwise(void) +{ + Push(Pop() ^ Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdNegateLogical(void) +{ + Push(!Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdLShift(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() << operand2); + return SCRIPT_CONTINUE; +} + +static int CmdRShift(void) +{ + int operand2; + + operand2 = Pop(); + Push(Pop() >> operand2); + return SCRIPT_CONTINUE; +} + +static int CmdUnaryMinus(void) +{ + Push(-Pop()); + return SCRIPT_CONTINUE; +} + +static int CmdIfNotGoto(void) +{ + int offset; + + offset = ReadOffset(); + + if (Pop() == 0) + { + PCodeOffset = offset; + } + return SCRIPT_CONTINUE; +} + +static int CmdLineSide(void) +{ + Push(ACScript->side); + return SCRIPT_CONTINUE; +} + +static int CmdScriptWait(void) +{ + ACSInfo[ACScript->infoIndex].waitValue = Pop(); + ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT; + return SCRIPT_STOP; +} + +static int CmdScriptWaitDirect(void) +{ + ACSInfo[ACScript->infoIndex].waitValue = ReadCodeInt(); + ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT; + return SCRIPT_STOP; +} + +static int CmdClearLineSpecial(void) +{ + if (ACScript->line) + { + ACScript->line->special = 0; + } + return SCRIPT_CONTINUE; +} + +static int CmdCaseGoto(void) +{ + int value; + int offset; + + value = ReadCodeInt(); + offset = ReadOffset(); + + if (Top() == value) + { + PCodeOffset = offset; + Drop(); + } + + return SCRIPT_CONTINUE; +} + +static int CmdBeginPrint(void) +{ + *PrintBuffer = 0; + return SCRIPT_CONTINUE; +} + +static int CmdEndPrint(void) +{ + player_t *player; + + if (ACScript->activator && ACScript->activator->player) + { + player = ACScript->activator->player; + } + else + { + player = &players[consoleplayer]; + } + P_SetMessage(player, PrintBuffer, true); + return SCRIPT_CONTINUE; +} + +static int CmdEndPrintBold(void) +{ + int i; + + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + P_SetYellowMessage(&players[i], PrintBuffer, true); + } + } + return SCRIPT_CONTINUE; +} + +static int CmdPrintString(void) +{ + M_StringConcat(PrintBuffer, StringLookup(Pop()), sizeof(PrintBuffer)); + return SCRIPT_CONTINUE; +} + +static int CmdPrintNumber(void) +{ + char tempStr[16]; + + M_snprintf(tempStr, sizeof(tempStr), "%d", Pop()); + M_StringConcat(PrintBuffer, tempStr, sizeof(PrintBuffer)); + return SCRIPT_CONTINUE; +} + +static int CmdPrintCharacter(void) +{ + char tempStr[2]; + + tempStr[0] = Pop(); + tempStr[1] = '\0'; + M_StringConcat(PrintBuffer, tempStr, sizeof(PrintBuffer)); + + return SCRIPT_CONTINUE; +} + +static int CmdPlayerCount(void) +{ + int i; + int count; + + count = 0; + for (i = 0; i < maxplayers; i++) + { + count += playeringame[i]; + } + Push(count); + return SCRIPT_CONTINUE; +} + +static int CmdGameType(void) +{ + int gametype; + + if (netgame == false) + { + gametype = GAME_SINGLE_PLAYER; + } + else if (deathmatch) + { + gametype = GAME_NET_DEATHMATCH; + } + else + { + gametype = GAME_NET_COOPERATIVE; + } + Push(gametype); + return SCRIPT_CONTINUE; +} + +static int CmdGameSkill(void) +{ + Push(gameskill); + return SCRIPT_CONTINUE; +} + +static int CmdTimer(void) +{ + Push(leveltime); + return SCRIPT_CONTINUE; +} + +static int CmdSectorSound(void) +{ + int volume; + mobj_t *mobj; + + mobj = NULL; + if (ACScript->line) + { + mobj = (mobj_t *) & ACScript->line->frontsector->soundorg; + } + volume = Pop(); + S_StartSoundAtVolume(mobj, S_GetSoundID(StringLookup(Pop())), volume); + return SCRIPT_CONTINUE; +} + +static int CmdThingSound(void) +{ + int tid; + int sound; + int volume; + mobj_t *mobj; + int searcher; + + volume = Pop(); + sound = S_GetSoundID(StringLookup(Pop())); + tid = Pop(); + searcher = -1; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + S_StartSoundAtVolume(mobj, sound, volume); + } + return SCRIPT_CONTINUE; +} + +static int CmdAmbientSound(void) +{ + int volume; + + volume = Pop(); + S_StartSoundAtVolume(NULL, S_GetSoundID(StringLookup(Pop())), volume); + return SCRIPT_CONTINUE; +} + +static int CmdSoundSequence(void) +{ + mobj_t *mobj; + + mobj = NULL; + if (ACScript->line) + { + mobj = (mobj_t *) & ACScript->line->frontsector->soundorg; + } + SN_StartSequenceName(mobj, StringLookup(Pop())); + return SCRIPT_CONTINUE; +} + +static int CmdSetLineTexture(void) +{ + line_t *line; + int lineTag; + int side; + int position; + int texture; + int searcher; + + texture = R_TextureNumForName(StringLookup(Pop())); + position = Pop(); + side = Pop(); + lineTag = Pop(); + searcher = -1; + while ((line = P_FindLine(lineTag, &searcher)) != NULL) + { + if (position == TEXTURE_MIDDLE) + { + sides[line->sidenum[side]].midtexture = texture; + } + else if (position == TEXTURE_BOTTOM) + { + sides[line->sidenum[side]].bottomtexture = texture; + } + else + { // TEXTURE_TOP + sides[line->sidenum[side]].toptexture = texture; + } + } + return SCRIPT_CONTINUE; +} + +static int CmdSetLineBlocking(void) +{ + line_t *line; + int lineTag; + boolean blocking; + int searcher; + + blocking = Pop()? ML_BLOCKING : 0; + lineTag = Pop(); + searcher = -1; + while ((line = P_FindLine(lineTag, &searcher)) != NULL) + { + line->flags = (line->flags & ~ML_BLOCKING) | blocking; + } + return SCRIPT_CONTINUE; +} + +static int CmdSetLineSpecial(void) +{ + line_t *line; + int lineTag; + int special, arg1, arg2, arg3, arg4, arg5; + int searcher; + + arg5 = Pop(); + arg4 = Pop(); + arg3 = Pop(); + arg2 = Pop(); + arg1 = Pop(); + special = Pop(); + lineTag = Pop(); + searcher = -1; + while ((line = P_FindLine(lineTag, &searcher)) != NULL) + { + line->special = special; + line->arg1 = arg1; + line->arg2 = arg2; + line->arg3 = arg3; + line->arg4 = arg4; + line->arg5 = arg5; + } + return SCRIPT_CONTINUE; +} diff --git a/games/NXDoom/src/hexen/p_action.h b/games/NXDoom/src/hexen/p_action.h new file mode 100644 index 00000000000..8336fbe582a --- /dev/null +++ b/games/NXDoom/src/hexen/p_action.h @@ -0,0 +1,240 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// External definitions for action pointer functions. +// + +#ifndef HEXEN_P_ACTION_H +#define HEXEN_P_ACTION_H + + +void A_FreeTargMobj(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FlameCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_HideThing(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_RestoreSpecialThing1(mobj_t *thing, player_t *player, pspdef_t *psp); +void A_RestoreSpecialThing2(mobj_t *thing, player_t *player, pspdef_t *psp); +void A_RestoreArtifact(mobj_t *arti, player_t *player, pspdef_t *psp); +void A_Summon(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ThrustInitUp(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ThrustInitDn(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ThrustRaise(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ThrustBlock(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ThrustImpale(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ThrustLower(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_TeloSpawnC(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_TeloSpawnB(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_TeloSpawnA(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_TeloSpawnD(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CheckTeleRing(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FogSpawn(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FogMove(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Quake(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ContMobjSound(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Scream(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PoisonBagInit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PoisonBagDamage(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PoisonBagCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CheckThrowBomb(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_NoGravity(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PotteryExplode(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PotteryChooseBit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PotteryCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CorpseBloodDrip(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CorpseExplode(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LeafSpawn(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LeafThrust(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LeafCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BridgeInit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BridgeOrbit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_TreeDeath(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PoisonShroom(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Pain(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SoAExplode(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BellReset1(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BellReset2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Light0(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WeaponReady(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Lower(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Raise(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FPunchAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ReFire(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FAxeAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FHammerAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FHammerThrow(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FSwordAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FSwordFlames(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CMaceAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CStaffInitBlink(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CStaffCheckBlink(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CStaffCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CStaffMissileSlither(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CFlameAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CFlameRotate(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CFlamePuff(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CFlameMissile(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolyAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolyPalette(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolySeek(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolyCheckScream(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolyTail(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolySpawnPuff(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolyAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MWandAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LightningReady(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MLightningAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LightningZap(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LightningClip(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LightningRemove(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_LastZap(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ZapMimic(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MStaffPalette(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MStaffWeave(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MStaffTrack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SnoutAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FireConePL1(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ShedShard(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_AddPlayerCorpse(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SkullPop(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FreezeDeath(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CheckBurnGone(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CheckSkullFloor(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CheckSkullDone(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SpeedFade(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceSetTics(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceCheckHeadDone(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PigPain(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PigLook(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PigChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FaceTarget(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_PigAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_QueueCorpse(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Look(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Chase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CentaurAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CentaurAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SetReflective(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CentaurDefend(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_UnSetReflective(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CentaurDropStuff(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CheckFloor(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DemonAttack1(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DemonAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DemonDeath(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_Demon2Death(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithRaiseInit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithRaise(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithInit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithLook(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithFX3(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithMelee(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithMissile(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_WraithFX2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurFade1(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurFade2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurRoam(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurAtk1(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurDecide(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurAtk2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurAtk3(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurCharge(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SmokePuffExit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurFade0(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MntrFloorFire(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentHumpDecide(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentUnHide(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentRaiseHump(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentLowerHump(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentHide(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentBirthScream(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SetShootable(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentCheckForAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_UnSetShootable(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentDiveSound(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentWalk(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentChooseAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentMeleeAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentMissileAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentHeadPop(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentSpawnGibs(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SerpentHeadCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FloatGib(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DelayGib(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SinkGib(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopDecide(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopDoBlur(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopSpawnBlur(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopPainBlur(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopPuff(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SetAltShadow(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopMissileWeave(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BishopMissileSeek(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonInitFlight(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonFlap(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonFlight(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonPain(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonCheckCrash(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DragonFX2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ESound(mobj_t *mo, player_t *player, pspdef_t *psp); +void A_EttinAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DropMace(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FiredRocks(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_UnSetInvulnerable(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FiredChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FiredAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FiredSplotch(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SmBounce(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceGuyLook(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceGuyChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceGuyAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceGuyDie(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceGuyMissilePuff(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_IceGuyMissileExplode(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ClassBossHealth(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FastChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FighterAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_ClericAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MageAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcBallPop(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcFX2Split(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcFX2Orbit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcererBishopEntry(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SpawnBishop(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcFX4Check(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxStep2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxChase(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxStep(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxDecide(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxMissile(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxCommand(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KoraxBonePop(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KSpiritRoam(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KBoltRaise(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_KBolt(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BatSpawnInit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BatSpawn(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BatMove(mobj_t *actor, player_t *player, pspdef_t *psp); + + +#endif // HEXEN_P_ACTION_H diff --git a/games/NXDoom/src/hexen/p_anim.c b/games/NXDoom/src/hexen/p_anim.c new file mode 100644 index 00000000000..12f90a5edd0 --- /dev/null +++ b/games/NXDoom/src/hexen/p_anim.c @@ -0,0 +1,477 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +#define ANIM_SCRIPT_NAME "ANIMDEFS" +#define MAX_ANIM_DEFS 20 +#define MAX_FRAME_DEFS 96 +#define ANIM_FLAT 0 +#define ANIM_TEXTURE 1 +#define SCI_FLAT "flat" +#define SCI_TEXTURE "texture" +#define SCI_PIC "pic" +#define SCI_TICS "tics" +#define SCI_RAND "rand" + +#define LIGHTNING_SPECIAL 198 +#define LIGHTNING_SPECIAL2 199 +#define SKYCHANGE_SPECIAL 200 + +// TYPES ------------------------------------------------------------------- + +typedef struct +{ + int index; + int tics; +} frameDef_t; + +typedef struct +{ + int type; + int index; + int tics; + int currentFrameDef; + int startFrameDef; + int endFrameDef; +} animDef_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void P_LightningFlash(void); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +fixed_t Sky1ScrollDelta; +fixed_t Sky2ScrollDelta; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static animDef_t AnimDefs[MAX_ANIM_DEFS]; +static frameDef_t FrameDefs[MAX_FRAME_DEFS]; +static int AnimDefCount; +static boolean LevelHasLightning; +static int NextLightningFlash; +static int LightningFlash; +static int *LightningLightLevels; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// P_AnimateSurfaces +// +//========================================================================== + +void P_AnimateSurfaces(void) +{ + int i; + animDef_t *ad; + line_t *line; + + // Animate flats and textures + for (i = 0; i < AnimDefCount; i++) + { + ad = &AnimDefs[i]; + ad->tics--; + if (ad->tics == 0) + { + if (ad->currentFrameDef == ad->endFrameDef) + { + ad->currentFrameDef = ad->startFrameDef; + } + else + { + ad->currentFrameDef++; + } + ad->tics = FrameDefs[ad->currentFrameDef].tics; + if (ad->tics > 255) + { // Random tics + ad->tics = (ad->tics >> 16) + + P_Random() % ((ad->tics & 0xff00) >> 8); + } + if (ad->type == ANIM_FLAT) + { + flattranslation[ad->index] = + FrameDefs[ad->currentFrameDef].index; + } + else + { // Texture + texturetranslation[ad->index] = + FrameDefs[ad->currentFrameDef].index; + } + } + } + + // Update scrolling textures + for (i = 0; i < numlinespecials; i++) + { + line = linespeciallist[i]; + switch (line->special) + { + case 100: // Scroll_Texture_Left + sides[line->sidenum[0]].textureoffset += line->arg1 << 10; + break; + case 101: // Scroll_Texture_Right + sides[line->sidenum[0]].textureoffset -= line->arg1 << 10; + break; + case 102: // Scroll_Texture_Up + sides[line->sidenum[0]].rowoffset += line->arg1 << 10; + break; + case 103: // Scroll_Texture_Down + sides[line->sidenum[0]].rowoffset -= line->arg1 << 10; + break; + } + } + + // Update sky column offsets + Sky1ColumnOffset += Sky1ScrollDelta; + Sky2ColumnOffset += Sky2ScrollDelta; + + if (LevelHasLightning) + { + if (!NextLightningFlash || LightningFlash) + { + P_LightningFlash(); + } + else + { + NextLightningFlash--; + } + } +} + +//========================================================================== +// +// P_LightningFlash +// +//========================================================================== + +static void P_LightningFlash(void) +{ + int i; + sector_t *tempSec; + int *tempLight; + boolean foundSec; + int flashLight; + + if (LightningFlash) + { + LightningFlash--; + if (LightningFlash) + { + tempLight = LightningLightLevels; + tempSec = sectors; + for (i = 0; i < numsectors; i++, tempSec++) + { + if (tempSec->ceilingpic == skyflatnum + || tempSec->special == LIGHTNING_SPECIAL + || tempSec->special == LIGHTNING_SPECIAL2) + { + if (*tempLight < tempSec->lightlevel - 4) + { + tempSec->lightlevel -= 4; + } + tempLight++; + } + } + } + else + { // remove the alternate lightning flash special + tempLight = LightningLightLevels; + tempSec = sectors; + for (i = 0; i < numsectors; i++, tempSec++) + { + if (tempSec->ceilingpic == skyflatnum + || tempSec->special == LIGHTNING_SPECIAL + || tempSec->special == LIGHTNING_SPECIAL2) + { + tempSec->lightlevel = *tempLight; + tempLight++; + } + } + Sky1Texture = P_GetMapSky1Texture(gamemap); + } + return; + } + LightningFlash = (P_Random() & 7) + 8; + flashLight = 200 + (P_Random() & 31); + tempSec = sectors; + tempLight = LightningLightLevels; + foundSec = false; + for (i = 0; i < numsectors; i++, tempSec++) + { + if (tempSec->ceilingpic == skyflatnum + || tempSec->special == LIGHTNING_SPECIAL + || tempSec->special == LIGHTNING_SPECIAL2) + { + *tempLight = tempSec->lightlevel; + if (tempSec->special == LIGHTNING_SPECIAL) + { + tempSec->lightlevel += 64; + if (tempSec->lightlevel > flashLight) + { + tempSec->lightlevel = flashLight; + } + } + else if (tempSec->special == LIGHTNING_SPECIAL2) + { + tempSec->lightlevel += 32; + if (tempSec->lightlevel > flashLight) + { + tempSec->lightlevel = flashLight; + } + } + else + { + tempSec->lightlevel = flashLight; + } + if (tempSec->lightlevel < *tempLight) + { + tempSec->lightlevel = *tempLight; + } + tempLight++; + foundSec = true; + } + } + if (foundSec) + { + Sky1Texture = P_GetMapSky2Texture(gamemap); // set alternate sky + S_StartSound(NULL, SFX_THUNDER_CRASH); + } + // Calculate the next lighting flash + if (!NextLightningFlash) + { + if (P_Random() < 50) + { // Immediate Quick flash + NextLightningFlash = (P_Random() & 15) + 16; + } + else + { + if (P_Random() < 128 && !(leveltime & 32)) + { + NextLightningFlash = ((P_Random() & 7) + 2) * 35; + } + else + { + NextLightningFlash = ((P_Random() & 15) + 5) * 35; + } + } + } +} + +//========================================================================== +// +// P_ForceLightning +// +//========================================================================== + +void P_ForceLightning(void) +{ + NextLightningFlash = 0; +} + +//========================================================================== +// +// P_InitLightning +// +//========================================================================== + +void P_InitLightning(void) +{ + int i; + int secCount; + + if (!P_GetMapLightning(gamemap)) + { + LevelHasLightning = false; + LightningFlash = 0; + return; + } + LightningFlash = 0; + secCount = 0; + for (i = 0; i < numsectors; i++) + { + if (sectors[i].ceilingpic == skyflatnum + || sectors[i].special == LIGHTNING_SPECIAL + || sectors[i].special == LIGHTNING_SPECIAL2) + { + secCount++; + } + } + if (secCount) + { + LevelHasLightning = true; + } + else + { + LevelHasLightning = false; + return; + } + LightningLightLevels = (int *) Z_Malloc(secCount * sizeof(int), PU_LEVEL, + NULL); + NextLightningFlash = ((P_Random() & 15) + 5) * 35; // don't flash at level start +} + +//========================================================================== +// +// P_InitFTAnims +// +// Initialize flat and texture animation lists. +// +//========================================================================== + +void P_InitFTAnims(void) +{ + int base; + int mod; + int fd; + animDef_t *ad; + boolean ignore; + boolean done; + + fd = 0; + ad = AnimDefs; + AnimDefCount = 0; + SC_Open(ANIM_SCRIPT_NAME); + while (SC_GetString()) + { + if (AnimDefCount == MAX_ANIM_DEFS) + { + I_Error("P_InitFTAnims: too many AnimDefs."); + } + if (SC_Compare(SCI_FLAT)) + { + ad->type = ANIM_FLAT; + } + else if (SC_Compare(SCI_TEXTURE)) + { + ad->type = ANIM_TEXTURE; + } + else + { + SC_ScriptError(NULL); + } + SC_MustGetString(); // Name + ignore = false; + if (ad->type == ANIM_FLAT) + { + if (W_CheckNumForName(sc_String) == -1) + { + ignore = true; + } + else + { + ad->index = R_FlatNumForName(sc_String); + } + } + else + { // Texture + if (R_CheckTextureNumForName(sc_String) == -1) + { + ignore = true; + } + else + { + ad->index = R_TextureNumForName(sc_String); + } + } + ad->startFrameDef = fd; + done = false; + while (done == false) + { + if (SC_GetString()) + { + if (SC_Compare(SCI_PIC)) + { + if (fd == MAX_FRAME_DEFS) + { + I_Error("P_InitFTAnims: too many FrameDefs."); + } + SC_MustGetNumber(); + if (ignore == false) + { + FrameDefs[fd].index = ad->index + sc_Number - 1; + } + SC_MustGetString(); + if (SC_Compare(SCI_TICS)) + { + SC_MustGetNumber(); + if (ignore == false) + { + FrameDefs[fd].tics = sc_Number; + fd++; + } + } + else if (SC_Compare(SCI_RAND)) + { + SC_MustGetNumber(); + base = sc_Number; + SC_MustGetNumber(); + if (ignore == false) + { + mod = sc_Number - base + 1; + FrameDefs[fd].tics = (base << 16) + (mod << 8); + fd++; + } + } + else + { + SC_ScriptError(NULL); + } + } + else + { + SC_UnGet(); + done = true; + } + } + else + { + done = true; + } + } + if ((ignore == false) && (fd - ad->startFrameDef < 2)) + { + I_Error("P_InitFTAnims: AnimDef has framecount < 2."); + } + if (ignore == false) + { + ad->endFrameDef = fd - 1; + ad->currentFrameDef = ad->endFrameDef; + ad->tics = 1; // Force 1st game tic to animate + AnimDefCount++; + ad++; + } + } + SC_Close(); +} diff --git a/games/NXDoom/src/hexen/p_ceilng.c b/games/NXDoom/src/hexen/p_ceilng.c new file mode 100644 index 00000000000..dfe0ba66f3f --- /dev/null +++ b/games/NXDoom/src/hexen/p_ceilng.c @@ -0,0 +1,303 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "p_local.h" + +//================================================================== +//================================================================== +// +// CEILINGS +// +//================================================================== +//================================================================== + +ceiling_t *activeceilings[MAXCEILINGS]; + +//================================================================== +// +// T_MoveCeiling +// +//================================================================== +void T_MoveCeiling(thinker_t *thinker) +{ + ceiling_t *ceiling = (ceiling_t *) thinker; + result_e res; + + switch (ceiling->direction) + { +// case 0: // IN STASIS +// break; + case 1: // UP + res = T_MovePlane(ceiling->sector, ceiling->speed, + ceiling->topheight, false, 1, + ceiling->direction); + if (res == RES_PASTDEST) + { + SN_StopSequence((mobj_t *) & ceiling->sector->soundorg); + switch (ceiling->type) + { + case CLEV_CRUSHANDRAISE: + ceiling->direction = -1; + ceiling->speed = ceiling->speed * 2; + break; + default: + P_RemoveActiveCeiling(ceiling); + break; + } + } + break; + case -1: // DOWN + res = T_MovePlane(ceiling->sector, ceiling->speed, + ceiling->bottomheight, ceiling->crush, 1, + ceiling->direction); + if (res == RES_PASTDEST) + { + SN_StopSequence((mobj_t *) & ceiling->sector->soundorg); + switch (ceiling->type) + { + case CLEV_CRUSHANDRAISE: + case CLEV_CRUSHRAISEANDSTAY: + ceiling->direction = 1; + ceiling->speed = ceiling->speed / 2; + break; + default: + P_RemoveActiveCeiling(ceiling); + break; + } + } + else if (res == RES_CRUSHED) + { + switch (ceiling->type) + { + case CLEV_CRUSHANDRAISE: + case CLEV_LOWERANDCRUSH: + case CLEV_CRUSHRAISEANDSTAY: + //ceiling->speed = ceiling->speed/4; + break; + default: + break; + } + } + break; + } +} + +//================================================================== +// +// EV_DoCeiling +// Move a ceiling up/down and all around! +// +//================================================================== +int EV_DoCeiling(line_t * line, byte * arg, ceiling_e type) +{ + int secnum, rtn; + sector_t *sec; + ceiling_t *ceiling; + + secnum = -1; + rtn = 0; + +/* Old Ceiling stasis code + // + // Reactivate in-stasis ceilings...for certain types. + // + switch(type) + { + case CLEV_CRUSHANDRAISE: + P_ActivateInStasisCeiling(line); + default: + break; + } +*/ + while ((secnum = P_FindSectorFromTag(arg[0], secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + // + // new door thinker + // + rtn = 1; + ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0); + P_AddThinker(&ceiling->thinker); + sec->specialdata = ceiling; + ceiling->thinker.function = T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = 0; + ceiling->speed = arg[1] * (FRACUNIT / 8); + switch (type) + { + case CLEV_CRUSHRAISEANDSTAY: + ceiling->crush = arg[2]; // arg[2] = crushing value + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT); + ceiling->direction = -1; + break; + case CLEV_CRUSHANDRAISE: + ceiling->topheight = sec->ceilingheight; + case CLEV_LOWERANDCRUSH: + ceiling->crush = arg[2]; // arg[2] = crushing value + case CLEV_LOWERTOFLOOR: + ceiling->bottomheight = sec->floorheight; + if (type != CLEV_LOWERTOFLOOR) + { + ceiling->bottomheight += 8 * FRACUNIT; + } + ceiling->direction = -1; + break; + case CLEV_RAISETOHIGHEST: + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + break; + case CLEV_LOWERBYVALUE: + ceiling->bottomheight = + sec->ceilingheight - arg[2] * FRACUNIT; + ceiling->direction = -1; + break; + case CLEV_RAISEBYVALUE: + ceiling->topheight = sec->ceilingheight + arg[2] * FRACUNIT; + ceiling->direction = 1; + break; + case CLEV_MOVETOVALUETIMES8: + { + int destHeight = arg[2] * FRACUNIT * 8; + + if (arg[3]) + { + destHeight = -destHeight; + } + if (sec->ceilingheight <= destHeight) + { + ceiling->direction = 1; + ceiling->topheight = destHeight; + if (sec->ceilingheight == destHeight) + { + rtn = 0; + } + } + else if (sec->ceilingheight > destHeight) + { + ceiling->direction = -1; + ceiling->bottomheight = destHeight; + } + break; + } + default: + rtn = 0; + break; + } + ceiling->tag = sec->tag; + ceiling->type = type; + P_AddActiveCeiling(ceiling); + if (rtn) + { + SN_StartSequence((mobj_t *) & ceiling->sector->soundorg, + SEQ_PLATFORM + ceiling->sector->seqType); + } + } + return rtn; +} + +//================================================================== +// +// Add an active ceiling +// +//================================================================== +void P_AddActiveCeiling(ceiling_t * c) +{ + int i; + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] == NULL) + { + activeceilings[i] = c; + return; + } +} + +//================================================================== +// +// Remove a ceiling's thinker +// +//================================================================== +void P_RemoveActiveCeiling(ceiling_t * c) +{ + int i; + + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] == c) + { + activeceilings[i]->sector->specialdata = NULL; + P_RemoveThinker(&activeceilings[i]->thinker); + P_TagFinished(activeceilings[i]->sector->tag); + activeceilings[i] = NULL; + break; + } +} + +#if 0 +//================================================================== +// +// Restart a ceiling that's in-stasis +// +//================================================================== +void P_ActivateInStasisCeiling(line_t * line) +{ + int i; + + for (i = 0; i < MAXCEILINGS; i++) + if (activeceilings[i] && (activeceilings[i]->tag == line->arg1) && + (activeceilings[i]->direction == 0)) + { + activeceilings[i]->direction = activeceilings[i]->olddirection; + activeceilings[i]->thinker.function = T_MoveCeiling; + SN_StartSequence((mobj_t *) & activeceilings[i]->sector->soundorg, + SEQ_PLATFORM + + activeceilings[i]->sector->seqType); + } +} +#endif + +//================================================================== +// +// EV_CeilingCrushStop +// Stop a ceiling from crushing! +// +//================================================================== + +int EV_CeilingCrushStop(line_t * line, byte * args) +{ + int i; + int rtn; + + rtn = 0; + for (i = 0; i < MAXCEILINGS; i++) + { + if (activeceilings[i] && activeceilings[i]->tag == args[0]) + { + rtn = 1; + SN_StopSequence((mobj_t *) & activeceilings[i]->sector->soundorg); + activeceilings[i]->sector->specialdata = NULL; + P_RemoveThinker(&activeceilings[i]->thinker); + P_TagFinished(activeceilings[i]->sector->tag); + activeceilings[i] = NULL; + break; + } + } + return rtn; +} diff --git a/games/NXDoom/src/hexen/p_doors.c b/games/NXDoom/src/hexen/p_doors.c new file mode 100644 index 00000000000..eb526f2d541 --- /dev/null +++ b/games/NXDoom/src/hexen/p_doors.c @@ -0,0 +1,319 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "p_local.h" + +//================================================================== +//================================================================== +// +// VERTICAL DOORS +// +//================================================================== +//================================================================== + +//================================================================== +// +// T_VerticalDoor +// +//================================================================== +void T_VerticalDoor(thinker_t *thinker) +{ + vldoor_t *door = (vldoor_t *) thinker; + result_e res; + + switch (door->direction) + { + case 0: // WAITING + if (!--door->topcountdown) + switch (door->type) + { + case DREV_NORMAL: + door->direction = -1; // time to go back down + SN_StartSequence((mobj_t *) & door->sector->soundorg, + SEQ_DOOR_STONE + + door->sector->seqType); + break; + case DREV_CLOSE30THENOPEN: + door->direction = 1; + break; + default: + break; + } + break; + case 2: // INITIAL WAIT + if (!--door->topcountdown) + { + switch (door->type) + { + case DREV_RAISEIN5MINS: + door->direction = 1; + door->type = DREV_NORMAL; + break; + default: + break; + } + } + break; + case -1: // DOWN + res = T_MovePlane(door->sector, door->speed, + door->sector->floorheight, false, 1, + door->direction); + if (res == RES_PASTDEST) + { + SN_StopSequence((mobj_t *) & door->sector->soundorg); + switch (door->type) + { + case DREV_NORMAL: + case DREV_CLOSE: + door->sector->specialdata = NULL; + P_TagFinished(door->sector->tag); + P_RemoveThinker(&door->thinker); // unlink and free + break; + case DREV_CLOSE30THENOPEN: + door->direction = 0; + door->topcountdown = 35 * 30; + break; + default: + break; + } + } + else if (res == RES_CRUSHED) + { + switch (door->type) + { + case DREV_CLOSE: // DON'T GO BACK UP! + break; + default: + door->direction = 1; + break; + } + } + break; + case 1: // UP + res = T_MovePlane(door->sector, door->speed, + door->topheight, false, 1, door->direction); + if (res == RES_PASTDEST) + { + SN_StopSequence((mobj_t *) & door->sector->soundorg); + switch (door->type) + { + case DREV_NORMAL: + door->direction = 0; // wait at top + door->topcountdown = door->topwait; + break; + case DREV_CLOSE30THENOPEN: + case DREV_OPEN: + door->sector->specialdata = NULL; + P_TagFinished(door->sector->tag); + P_RemoveThinker(&door->thinker); // unlink and free + break; + default: + break; + } + } + break; + } +} + +//---------------------------------------------------------------------------- +// +// EV_DoDoor +// +// Move a door up/down +// +//---------------------------------------------------------------------------- + +int EV_DoDoor(line_t * line, byte * args, vldoor_e type) +{ + int secnum; + int retcode; + sector_t *sec; + vldoor_t *door; + fixed_t speed; + + speed = args[1] * FRACUNIT / 8; + secnum = -1; + retcode = 0; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + { + continue; + } + // Add new door thinker + retcode = 1; + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + switch (type) + { + case DREV_CLOSE: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->direction = -1; + break; + case DREV_CLOSE30THENOPEN: + door->topheight = sec->ceilingheight; + door->direction = -1; + break; + case DREV_NORMAL: + case DREV_OPEN: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + break; + default: + break; + } + door->type = type; + door->speed = speed; + door->topwait = args[2]; // line->arg3 + SN_StartSequence((mobj_t *) & door->sector->soundorg, + SEQ_DOOR_STONE + door->sector->seqType); + } + return (retcode); +} + +//================================================================== +// +// EV_VerticalDoor : open a door manually, no tag value +// +//================================================================== +boolean EV_VerticalDoor(line_t * line, mobj_t * thing) +{ + sector_t *sec; + vldoor_t *door; + int side; + + side = 0; // only front sides can be used + + // if the sector has an active thinker, use it + sec = sides[line->sidenum[side ^ 1]].sector; + if (sec->specialdata) + { + return false; +/* + door = sec->specialdata; + switch(line->special) + { // only for raise doors + case 12: + if(door->direction == -1) + { + door->direction = 1; // go back up + } + else + { + if(!thing->player) + { // Monsters don't close doors + return; + } + door->direction = -1; // start going down immediately + } + return; + } +*/ + } + // + // new door thinker + // + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + door->direction = 1; + switch (line->special) + { + case 11: + door->type = DREV_OPEN; + line->special = 0; + break; + case 12: + case 13: + door->type = DREV_NORMAL; + break; + default: + door->type = DREV_NORMAL; + break; + } + door->speed = line->arg2 * (FRACUNIT / 8); + door->topwait = line->arg3; + + // + // find the top and bottom of the movement range + // + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + SN_StartSequence((mobj_t *) & door->sector->soundorg, + SEQ_DOOR_STONE + door->sector->seqType); + return true; +} + +//================================================================== +// +// Spawn a door that closes after 30 seconds +// +//================================================================== + +/* +void P_SpawnDoorCloseIn30(sector_t *sec) +{ + vldoor_t *door; + + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + sec->special = 0; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + door->direction = 0; + door->type = DREV_NORMAL; + door->speed = VDOORSPEED; + door->topcountdown = 30*35; +} +*/ + +//================================================================== +// +// Spawn a door that opens after 5 minutes +// +//================================================================== + +/* +void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum) +{ + vldoor_t *door; + + door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker(&door->thinker); + sec->specialdata = door; + sec->special = 0; + door->thinker.function = T_VerticalDoor; + door->sector = sec; + door->direction = 2; + door->type = DREV_RAISEIN5MINS; + door->speed = VDOORSPEED; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->topwait = VDOORWAIT; + door->topcountdown = 5*60*35; +} +*/ diff --git a/games/NXDoom/src/hexen/p_enemy.c b/games/NXDoom/src/hexen/p_enemy.c new file mode 100644 index 00000000000..fa8d094237e --- /dev/null +++ b/games/NXDoom/src/hexen/p_enemy.c @@ -0,0 +1,5428 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "i_swap.h" +#include "p_local.h" +#include "s_sound.h" + +// Macros +// Types +// Private Data +// External Data + + +//---------------------------------------------------------------------------- +// +// PROC P_RecursiveSound +// +//---------------------------------------------------------------------------- + +mobj_t *soundtarget; + +void P_RecursiveSound(sector_t * sec, int soundblocks) +{ + int i; + line_t *check; + sector_t *other; + + // Wake up all monsters in this sector + if (sec->validcount == validcount + && sec->soundtraversed <= soundblocks + 1) + { // Already flooded + return; + } + sec->validcount = validcount; + sec->soundtraversed = soundblocks + 1; + sec->soundtarget = soundtarget; + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + if (!(check->flags & ML_TWOSIDED)) + { + continue; + } + P_LineOpening(check); + if (openrange <= 0) + { // Closed door + continue; + } + if (sides[check->sidenum[0]].sector == sec) + { + other = sides[check->sidenum[1]].sector; + } + else + { + other = sides[check->sidenum[0]].sector; + } + if (check->flags & ML_SOUNDBLOCK) + { + if (!soundblocks) + { + P_RecursiveSound(other, 1); + } + } + else + { + P_RecursiveSound(other, soundblocks); + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_NoiseAlert +// +// If a monster yells at a player, it will alert other monsters to the +// player. +// +//---------------------------------------------------------------------------- + +void P_NoiseAlert(mobj_t * target, mobj_t * emmiter) +{ + soundtarget = target; + validcount++; + P_RecursiveSound(emmiter->subsector->sector, 0); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_CheckMeleeRange +// +//---------------------------------------------------------------------------- + +boolean P_CheckMeleeRange(mobj_t * actor) +{ + mobj_t *mo; + fixed_t dist; + + if (!actor->target) + { + return (false); + } + mo = actor->target; + dist = P_AproxDistance(mo->x - actor->x, mo->y - actor->y); + if (dist >= MELEERANGE) + { + return (false); + } + if (!P_CheckSight(actor, mo)) + { + return (false); + } + if (mo->z > actor->z + actor->height) + { // Target is higher than the attacker + return (false); + } + else if (actor->z > mo->z + mo->height) + { // Attacker is higher + return (false); + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_CheckMeleeRange2 +// +//---------------------------------------------------------------------------- + +boolean P_CheckMeleeRange2(mobj_t * actor) +{ + mobj_t *mo; + fixed_t dist; + + if (!actor->target) + { + return (false); + } + mo = actor->target; + dist = P_AproxDistance(mo->x - actor->x, mo->y - actor->y); + if (dist >= MELEERANGE * 2 || dist < MELEERANGE) + { + return (false); + } + if (!P_CheckSight(actor, mo)) + { + return (false); + } + if (mo->z > actor->z + actor->height) + { // Target is higher than the attacker + return (false); + } + else if (actor->z > mo->z + mo->height) + { // Attacker is higher + return (false); + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_CheckMissileRange +// +//---------------------------------------------------------------------------- + +boolean P_CheckMissileRange(mobj_t * actor) +{ + fixed_t dist; + + if (!P_CheckSight(actor, actor->target)) + { + return (false); + } + if (actor->flags & MF_JUSTHIT) + { // The target just hit the enemy, so fight back! + actor->flags &= ~MF_JUSTHIT; + return (true); + } + if (actor->reactiontime) + { // Don't attack yet + return (false); + } + dist = (P_AproxDistance(actor->x - actor->target->x, + actor->y - actor->target->y) >> FRACBITS) - 64; + if (!actor->info->meleestate) + { // No melee attack, so fire more frequently + dist -= 128; + } + if (dist > 200) + { + dist = 200; + } + if (P_Random() < dist) + { + return (false); + } + return (true); +} + +/* +================ += += P_Move += += Move in the current direction += returns false if the move is blocked +================ +*/ + +fixed_t xspeed[8] = + { FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000, 0, 47000 }; +fixed_t yspeed[8] = + { 0, 47000, FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000 }; + + +boolean P_Move(mobj_t * actor) +{ + fixed_t tryx, tryy; + line_t *ld; + boolean good; + + if (actor->flags2 & MF2_BLASTED) + return (true); + if (actor->movedir == DI_NODIR) + { + return (false); + } + tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; + tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; + if (!P_TryMove(actor, tryx, tryy)) + { // open any specials + if (actor->flags & MF_FLOAT && floatok) + { // must adjust height + if (actor->z < tmfloorz) + { + actor->z += FLOATSPEED; + } + else + { + actor->z -= FLOATSPEED; + } + actor->flags |= MF_INFLOAT; + return (true); + } + if (!numspechit) + { + return false; + } + actor->movedir = DI_NODIR; + good = false; + while (numspechit--) + { + ld = spechit[numspechit]; + // if the special isn't a door that can be opened, return false + if (P_ActivateLine(ld, actor, 0, SPAC_USE)) + { + good = true; + } +/* Old version before use/cross/impact specials were combined + if(P_UseSpecialLine(actor, ld)) + { + good = true; + } +*/ + } + return (good); + } + else + { + actor->flags &= ~MF_INFLOAT; + } + if (!(actor->flags & MF_FLOAT)) + { + if (actor->z > actor->floorz) + { + P_HitFloor(actor); + } + actor->z = actor->floorz; + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_TryWalk +// +// Attempts to move actor in its current (ob->moveangle) direction. +// If blocked by either a wall or an actor returns FALSE. +// If move is either clear of block only by a door, returns TRUE and sets. +// If a door is in the way, an OpenDoor call is made to start it opening. +// +//---------------------------------------------------------------------------- + +boolean P_TryWalk(mobj_t * actor) +{ + if (!P_Move(actor)) + { + return (false); + } + actor->movecount = P_Random() & 15; + return (true); +} + +/* +================ += += P_NewChaseDir += +================ +*/ + +dirtype_t opposite[] = + { DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, + DI_NORTH, DI_NORTHWEST, DI_NODIR +}; + +dirtype_t diags[] = + { DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST }; + +void P_NewChaseDir(mobj_t * actor) +{ + fixed_t deltax, deltay; + dirtype_t d[3]; + dirtype_t tdir, olddir, turnaround; + + if (!actor->target) + I_Error("P_NewChaseDir: called with no target"); + + olddir = actor->movedir; + turnaround = opposite[olddir]; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + if (deltax > 10 * FRACUNIT) + d[1] = DI_EAST; + else if (deltax < -10 * FRACUNIT) + d[1] = DI_WEST; + else + d[1] = DI_NODIR; + if (deltay < -10 * FRACUNIT) + d[2] = DI_SOUTH; + else if (deltay > 10 * FRACUNIT) + d[2] = DI_NORTH; + else + d[2] = DI_NODIR; + +// try direct route + if (d[1] != DI_NODIR && d[2] != DI_NODIR) + { + actor->movedir = diags[((deltay < 0) << 1) + (deltax > 0)]; + if (actor->movedir != turnaround && P_TryWalk(actor)) + return; + } + +// try other directions + if (P_Random() > 200 || abs(deltay) > abs(deltax)) + { + tdir = d[1]; + d[1] = d[2]; + d[2] = tdir; + } + + if (d[1] == turnaround) + d[1] = DI_NODIR; + if (d[2] == turnaround) + d[2] = DI_NODIR; + + if (d[1] != DI_NODIR) + { + actor->movedir = d[1]; + if (P_TryWalk(actor)) + return; /*either moved forward or attacked */ + } + + if (d[2] != DI_NODIR) + { + actor->movedir = d[2]; + if (P_TryWalk(actor)) + return; + } + +/* there is no direct path to the player, so pick another direction */ + + if (olddir != DI_NODIR) + { + actor->movedir = olddir; + if (P_TryWalk(actor)) + return; + } + + if (P_Random() & 1) /*randomly determine direction of search */ + { + for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) + { + if (tdir != turnaround) + { + actor->movedir = tdir; + if (P_TryWalk(actor)) + return; + } + } + } + else + { + tdir = DI_SOUTHEAST; + + for (;;) + { + if (tdir != turnaround) + { + actor->movedir = tdir; + if (P_TryWalk(actor)) + return; + } + + if (tdir == DI_EAST) + { + break; + } + + --tdir; + } + } + + if (turnaround != DI_NODIR) + { + actor->movedir = turnaround; + if (P_TryWalk(actor)) + return; + } + + actor->movedir = DI_NODIR; // can't move +} + +//--------------------------------------------------------------------------- +// +// FUNC P_LookForMonsters +// +//--------------------------------------------------------------------------- + +#define MONS_LOOK_RANGE (16*64*FRACUNIT) +#define MONS_LOOK_LIMIT 64 + +boolean P_LookForMonsters(mobj_t * actor) +{ + int count; + mobj_t *mo; + thinker_t *think; + + if (!P_CheckSight(players[0].mo, actor)) + { // Player can't see monster + return (false); + } + count = 0; + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + if (!(mo->flags & MF_COUNTKILL) || (mo == actor) || (mo->health <= 0)) + { // Not a valid monster + continue; + } + if (P_AproxDistance(actor->x - mo->x, actor->y - mo->y) + > MONS_LOOK_RANGE) + { // Out of range + continue; + } + if (P_Random() < 16) + { // Skip + continue; + } + if (count++ > MONS_LOOK_LIMIT) + { // Stop searching + return (false); + } + if (!P_CheckSight(actor, mo)) + { // Out of sight + continue; + } + if (actor->type == MT_MINOTAUR) + { + if ((mo->type == MT_MINOTAUR) && + (mo->target != actor->special1.p->mo)) + { + continue; + } + } + // Found a target monster + actor->target = mo; + return (true); + } + return (false); +} + +/* +================ += += P_LookForPlayers += += If allaround is false, only look 180 degrees in front += returns true if a player is targeted +================ +*/ + +boolean P_LookForPlayers(mobj_t * actor, boolean allaround) +{ + int c; + int stop; + player_t *player; + angle_t an; + fixed_t dist; + int consecutive_missing = 0; // for breaking infinite loop + + if (!netgame && players[0].health <= 0) + { // Single player game and player is dead, look for monsters + return (P_LookForMonsters(actor)); + } + c = 0; + + // The 3 below is probably a mistake (it should be MAXPLAYERS - 1, or 7) + // and in vanilla this can potentially cause an infinite loop in + // multiplayer. Unfortunately we can't correct the mistake - doing so will + // cause desyncs. Upon spawning, each enemy's lastlook is initialized to a + // random value between 0 and 7 (i.e MAXPLAYERS - 1). There's a chance + // that the first call of this function for that enemy will return early + // courtesy of the actor->lastlook == stop condition. In a single-player + // game this occurs when (actor->lastlook - 1) & 3 equals 0, or when + // lastlook equals 1 or 5. + + // If you use MAXPLAYERS - 1, it has the side effect of altering which + // enemies are affected by an early actor->lastlook == stop return. Now it + // happens when (actor->lastlook - 1) & 7 equals 0, or when lastlook equals + // 1, *not* 1 and 5 as above. + + stop = (actor->lastlook - 1) & 3; + for (;; actor->lastlook = (actor->lastlook + 1) & 3) + { + if (!playeringame[actor->lastlook]) + { + // Break the vanilla infinite loop here. It can occur if there are + // > 4 players and players 0 - 3 all quit the game. Error out + // instead. + if (consecutive_missing == 4) + { + I_Error("P_LookForPlayers: No player 1 - 4.\n"); + } + consecutive_missing++; + continue; + } + + consecutive_missing = 0; + + if (c++ == 2 || actor->lastlook == stop) + return false; // done looking + + player = &players[actor->lastlook]; + if (player->health <= 0) + continue; // dead + if (!P_CheckSight(actor, player->mo)) + continue; // out of sight + + if (!allaround) + { + an = R_PointToAngle2(actor->x, actor->y, + player->mo->x, player->mo->y) - actor->angle; + if (an > ANG90 && an < ANG270) + { + dist = P_AproxDistance(player->mo->x - actor->x, + player->mo->y - actor->y); + // if real close, react anyway + if (dist > MELEERANGE) + continue; // behind back + } + } + if (player->mo->flags & MF_SHADOW) + { // Player is invisible + if ((P_AproxDistance(player->mo->x - actor->x, + player->mo->y - actor->y) > 2 * MELEERANGE) + && P_AproxDistance(player->mo->momx, player->mo->momy) + < 5 * FRACUNIT) + { // Player is sneaking - can't detect + return (false); + } + if (P_Random() < 225) + { // Player isn't sneaking, but still didn't detect + return (false); + } + } + if (actor->type == MT_MINOTAUR) + { + if (actor->special1.p == player) + { + continue; // Don't target master + } + } + + actor->target = player->mo; + return (true); + } + return (false); +} + +/* +=============================================================================== + + ACTION ROUTINES + +=============================================================================== +*/ + +/* +============== += += A_Look += += Stay in state until a player is sighted += +============== +*/ + +void A_Look(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *targ; + + actor->threshold = 0; // any shot will wake up + targ = actor->subsector->sector->soundtarget; + if (targ && (targ->flags & MF_SHOOTABLE)) + { + actor->target = targ; + if (actor->flags & MF_AMBUSH) + { + if (P_CheckSight(actor, actor->target)) + goto seeyou; + } + else + goto seeyou; + } + + + if (!P_LookForPlayers(actor, false)) + return; + +// go into chase state + seeyou: + if (actor->info->seesound) + { + int sound; + + sound = actor->info->seesound; + if (actor->flags2 & MF2_BOSS) + { // Full volume + S_StartSound(NULL, sound); + } + else + { + S_StartSound(actor, sound); + } + } + P_SetMobjState(actor, actor->info->seestate); +} + + +/* +============== += += A_Chase += += Actor has a melee attack, so it tries to close as fast as possible += +============== +*/ + +void A_Chase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int delta; + + if (actor->reactiontime) + { + actor->reactiontime--; + } + + // Modify target threshold + if (actor->threshold) + { + actor->threshold--; + } + + if (gameskill == sk_nightmare) + { // Monsters move faster in nightmare mode + actor->tics -= actor->tics / 2; + if (actor->tics < 3) + { + actor->tics = 3; + } + } + +// +// turn towards movement direction if not there yet +// + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + if (delta > 0) + { + actor->angle -= ANG90 / 2; + } + else if (delta < 0) + { + actor->angle += ANG90 / 2; + } + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { // look for a new target + if (P_LookForPlayers(actor, true)) + { // got a new target + return; + } + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + +// +// don't attack twice in a row +// + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare) + P_NewChaseDir(actor); + return; + } + +// +// check for melee attack +// + if (actor->info->meleestate && P_CheckMeleeRange(actor)) + { + if (actor->info->attacksound) + { + S_StartSound(actor, actor->info->attacksound); + } + P_SetMobjState(actor, actor->info->meleestate); + return; + } + +// +// check for missile attack +// + if (actor->info->missilestate) + { + if (gameskill < sk_nightmare && actor->movecount) + goto nomissile; + if (!P_CheckMissileRange(actor)) + goto nomissile; + P_SetMobjState(actor, actor->info->missilestate); + actor->flags |= MF_JUSTATTACKED; + return; + } + nomissile: + +// +// possibly choose another target +// + if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) + { + if (P_LookForPlayers(actor, true)) + return; // got a new target + } + +// +// chase towards player +// + if (--actor->movecount < 0 || !P_Move(actor)) + { + P_NewChaseDir(actor); + } + +// +// make active sound +// + if (actor->info->activesound && P_Random() < 3) + { + if (actor->type == MT_BISHOP && P_Random() < 128) + { + S_StartSound(actor, actor->info->seesound); + } + else if (actor->type == MT_PIG) + { + S_StartSound(actor, SFX_PIG_ACTIVE1 + (P_Random() & 1)); + } + else if (actor->flags2 & MF2_BOSS) + { + S_StartSound(NULL, actor->info->activesound); + } + else + { + S_StartSound(actor, actor->info->activesound); + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FaceTarget +// +//---------------------------------------------------------------------------- + +void A_FaceTarget(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + actor->flags &= ~MF_AMBUSH; + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, + actor->target->y); + if (actor->target->flags & MF_SHADOW) + { // Target is a ghost + actor->angle += P_SubRandom() << 21; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_Pain +// +//---------------------------------------------------------------------------- + +void A_Pain(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->info->painsound) + { + S_StartSound(actor, actor->info->painsound); + } +} + +//============================================================================ +// +// A_SetInvulnerable +// +//============================================================================ + +void A_SetInvulnerable(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 |= MF2_INVULNERABLE; +} + +//============================================================================ +// +// A_UnSetInvulnerable +// +//============================================================================ + +void A_UnSetInvulnerable(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 &= ~MF2_INVULNERABLE; +} + +//============================================================================ +// +// A_SetReflective +// +//============================================================================ + +void A_SetReflective(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 |= MF2_REFLECTIVE; + + if ((actor->type == MT_CENTAUR) || (actor->type == MT_CENTAURLEADER)) + { + A_SetInvulnerable(actor, player, psp); + } +} + +//============================================================================ +// +// A_UnSetReflective +// +//============================================================================ + +void A_UnSetReflective(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 &= ~MF2_REFLECTIVE; + + if ((actor->type == MT_CENTAUR) || (actor->type == MT_CENTAURLEADER)) + { + A_UnSetInvulnerable(actor, player, psp); + } +} + + +//---------------------------------------------------------------------------- +// +// FUNC P_UpdateMorphedMonster +// +// Returns true if the pig morphs. +// +//---------------------------------------------------------------------------- + +boolean P_UpdateMorphedMonster(mobj_t * actor, int tics) +{ + mobj_t *fog; + fixed_t x; + fixed_t y; + fixed_t z; + mobjtype_t moType; + mobj_t *mo; + mobj_t oldMonster; + + actor->special1.i -= tics; + if (actor->special1.i > 0) + { + return (false); + } + moType = actor->special2.i; + switch (moType) + { + case MT_WRAITHB: // These must remain morphed + case MT_SERPENT: + case MT_SERPENTLEADER: + case MT_MINOTAUR: + return (false); + default: + break; + } + x = actor->x; + y = actor->y; + z = actor->z; + oldMonster = *actor; // Save pig vars + + P_RemoveMobjFromTIDList(actor); + P_SetMobjState(actor, S_FREETARGMOBJ); + mo = P_SpawnMobj(x, y, z, moType); + + if (P_TestMobjLocation(mo) == false) + { // Didn't fit + P_RemoveMobj(mo); + mo = P_SpawnMobj(x, y, z, oldMonster.type); + mo->angle = oldMonster.angle; + mo->flags = oldMonster.flags; + mo->health = oldMonster.health; + mo->target = oldMonster.target; + mo->special = oldMonster.special; + mo->special1.i = 5 * 35; // Next try in 5 seconds + mo->special2.i = moType; + mo->tid = oldMonster.tid; + memcpy(mo->args, oldMonster.args, 5); + P_InsertMobjIntoTIDList(mo, oldMonster.tid); + return (false); + } + mo->angle = oldMonster.angle; + mo->target = oldMonster.target; + mo->tid = oldMonster.tid; + mo->special = oldMonster.special; + memcpy(mo->args, oldMonster.args, 5); + P_InsertMobjIntoTIDList(mo, oldMonster.tid); + fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, SFX_TELEPORT); + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC A_PigLook +// +//---------------------------------------------------------------------------- + +void A_PigLook(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateMorphedMonster(actor, 10)) + { + return; + } + A_Look(actor, player, psp); +} + +//---------------------------------------------------------------------------- +// +// PROC A_PigChase +// +//---------------------------------------------------------------------------- + +void A_PigChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateMorphedMonster(actor, 3)) + { + return; + } + A_Chase(actor, player, psp); +} + +//============================================================================ +// +// A_PigAttack +// +//============================================================================ + +void A_PigAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_UpdateMorphedMonster(actor, 18)) + { + return; + } + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, 2 + (P_Random() & 1)); + S_StartSound(actor, SFX_PIG_ATTACK); + } +} + +//============================================================================ +// +// A_PigPain +// +//============================================================================ + +void A_PigPain(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_Pain(actor, player, psp); + if (actor->z <= actor->floorz) + { + actor->momz = 3.5 * FRACUNIT; + } +} + + + +void FaceMovementDirection(mobj_t * actor) +{ + switch (actor->movedir) + { + case DI_EAST: + actor->angle = 0u << 24; + break; + case DI_NORTHEAST: + actor->angle = 32u << 24; + break; + case DI_NORTH: + actor->angle = 64u << 24; + break; + case DI_NORTHWEST: + actor->angle = 96u << 24; + break; + case DI_WEST: + actor->angle = 128u << 24; + break; + case DI_SOUTHWEST: + actor->angle = 160u << 24; + break; + case DI_SOUTH: + actor->angle = 192u << 24; + break; + case DI_SOUTHEAST: + actor->angle = 224u << 24; + break; + } +} + + +//---------------------------------------------------------------------------- +// +// Minotaur variables +// +// special1 pointer to player that spawned it (mobj_t) +// special2 internal to minotaur AI +// args[0] args[0]-args[3] together make up minotaur start time +// args[1] | +// args[2] | +// args[3] V +// args[4] charge duration countdown +//---------------------------------------------------------------------------- + +void A_MinotaurFade0(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_ALTSHADOW; + actor->flags |= MF_SHADOW; +} + +void A_MinotaurFade1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + // Second level of transparency + actor->flags &= ~MF_SHADOW; + actor->flags |= MF_ALTSHADOW; +} + +void A_MinotaurFade2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + // Make fully visible + actor->flags &= ~MF_SHADOW; + actor->flags &= ~MF_ALTSHADOW; +} + + +//---------------------------------------------------------------------------- +// +// A_MinotaurRoam - +// +// +//---------------------------------------------------------------------------- + + +// Check the age of the minotaur and stomp it after MAULATORTICS of time +// have passed. Returns false if killed. +static boolean CheckMinotaurAge(mobj_t *mo) +{ + unsigned int starttime; + + // The start time is stored in the mobj_t structure, but it is stored + // in little endian format. For Vanilla savegame compatibility we must + // swap it to the native endianness. + memcpy(&starttime, mo->args, sizeof(unsigned int)); + + if (leveltime - LONG(starttime) >= MAULATORTICS) + { + P_DamageMobj(mo, NULL, NULL, 10000); + return false; + } + + return true; +} + +void A_MinotaurRoam(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SHADOW; // In case pain caused him to + actor->flags &= ~MF_ALTSHADOW; // skip his fade in. + + if (!CheckMinotaurAge(actor)) + { + return; + } + + if (P_Random() < 30) + A_MinotaurLook(actor, player, psp); // adjust to closest target + + if (P_Random() < 6) + { + //Choose new direction + actor->movedir = P_Random() % 8; + FaceMovementDirection(actor); + } + if (!P_Move(actor)) + { + // Turn + if (P_Random() & 1) + actor->movedir = (actor->movedir + 1) % 8; + else + actor->movedir = (actor->movedir + 7) % 8; + FaceMovementDirection(actor); + } +} + + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurLook +// +// Look for enemy of player +//---------------------------------------------------------------------------- +#define MINOTAUR_LOOK_DIST (16*54*FRACUNIT) + +void A_MinotaurLook(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + mobj_t *mo = NULL; + player_t *player; + thinker_t *think; + fixed_t dist; + int i; + mobj_t *master = actor->special1.m; + + actor->target = NULL; + if (deathmatch) // Quick search for players + { + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + continue; + player = &players[i]; + mo = player->mo; + if (mo == master) + continue; + if (mo->health <= 0) + continue; + dist = P_AproxDistance(actor->x - mo->x, actor->y - mo->y); + if (dist > MINOTAUR_LOOK_DIST) + continue; + actor->target = mo; + break; + } + } + + if (!actor->target) // Near player monster search + { + if (master && (master->health > 0) && (master->player)) + mo = P_RoughMonsterSearch(master, 20); + else + mo = P_RoughMonsterSearch(actor, 20); + actor->target = mo; + } + + if (!actor->target) // Normal monster search + { + for (think = thinkercap.next; think != &thinkercap; + think = think->next) + { + if (think->function != P_MobjThinker) + continue; + mo = (mobj_t *) think; + if (!(mo->flags & MF_COUNTKILL)) + continue; + if (mo->health <= 0) + continue; + if (!(mo->flags & MF_SHOOTABLE)) + continue; + dist = P_AproxDistance(actor->x - mo->x, actor->y - mo->y); + if (dist > MINOTAUR_LOOK_DIST) + continue; + if ((mo == master) || (mo == actor)) + continue; + if ((mo->type == MT_MINOTAUR) && + (mo->special1.m == actor->special1.m)) + continue; + actor->target = mo; + break; // Found mobj to attack + } + } + + if (actor->target) + { + P_SetMobjStateNF(actor, S_MNTR_WALK1); + } + else + { + P_SetMobjStateNF(actor, S_MNTR_ROAM1); + } +} + + + + +void A_MinotaurChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SHADOW; // In case pain caused him to + actor->flags &= ~MF_ALTSHADOW; // skip his fade in. + + if (!CheckMinotaurAge(actor)) + { + return; + } + + if (P_Random() < 30) + A_MinotaurLook(actor, player, psp); // adjust to closest target + + if (!actor->target || (actor->target->health <= 0) || + !(actor->target->flags & MF_SHOOTABLE)) + { // look for a new target + P_SetMobjState(actor, S_MNTR_LOOK1); + return; + } + + FaceMovementDirection(actor); + actor->reactiontime = 0; + + // Melee attack + if (actor->info->meleestate && P_CheckMeleeRange(actor)) + { + if (actor->info->attacksound) + { + S_StartSound(actor, actor->info->attacksound); + } + P_SetMobjState(actor, actor->info->meleestate); + return; + } + + // Missile attack + if (actor->info->missilestate && P_CheckMissileRange(actor)) + { + P_SetMobjState(actor, actor->info->missilestate); + return; + } + + // chase towards target + if (!P_Move(actor)) + { + P_NewChaseDir(actor); + } + + // Active sound + if (actor->info->activesound && P_Random() < 6) + { + S_StartSound(actor, actor->info->activesound); + } + +} + + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurAtk1 +// +// Melee attack. +// +//---------------------------------------------------------------------------- + +void A_MinotaurAtk1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + return; + + S_StartSound(actor, SFX_MAULATOR_HAMMER_SWING); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(4)); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurDecide +// +// Choose a missile attack. +// +//---------------------------------------------------------------------------- + +#define MNTR_CHARGE_SPEED (23*FRACUNIT) + +void A_MinotaurDecide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + mobj_t *target = actor->target; + int dist; + + if (!target) + return; + dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); + + if (target->z + target->height > actor->z + && target->z + target->height < actor->z + actor->height + && dist < 16 * 64 * FRACUNIT + && dist > 1 * 64 * FRACUNIT && P_Random() < 230) + { // Charge attack + // Don't call the state function right away + P_SetMobjStateNF(actor, S_MNTR_ATK4_1); + actor->flags |= MF_SKULLFLY; + A_FaceTarget(actor, player, psp); + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(MNTR_CHARGE_SPEED, finecosine[angle]); + actor->momy = FixedMul(MNTR_CHARGE_SPEED, finesine[angle]); + actor->args[4] = 35 / 2; // Charge duration + } + else if (target->z == target->floorz + && dist < 9 * 64 * FRACUNIT && P_Random() < 100) + { // Floor fire attack + P_SetMobjState(actor, S_MNTR_ATK3_1); + actor->special2.i = 0; + } + else + { // Swing attack + A_FaceTarget(actor, player, psp); + // Don't need to call P_SetMobjState because the current state + // falls through to the swing attack + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurCharge +// +//---------------------------------------------------------------------------- + +void A_MinotaurCharge(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *puff; + + if (!actor->target) + return; + + if (actor->args[4] > 0) + { + puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PUNCHPUFF); + puff->momz = 2 * FRACUNIT; + actor->args[4]--; + } + else + { + actor->flags &= ~MF_SKULLFLY; + P_SetMobjState(actor, actor->info->seestate); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurAtk2 +// +// Swing attack. +// +//---------------------------------------------------------------------------- + +void A_MinotaurAtk2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + fixed_t momz; + + if (!actor->target) + return; + + S_StartSound(actor, SFX_MAULATOR_HAMMER_SWING); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(3)); + return; + } + mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX1); + if (mo) + { + //S_StartSound(mo, sfx_minat2); + momz = mo->momz; + angle = mo->angle; + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 8), momz); + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 8), momz); + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 16), momz); + P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 16), momz); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MinotaurAtk3 +// +// Floor fire attack. +// +//---------------------------------------------------------------------------- + +void A_MinotaurAtk3(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + mobj_t *mo; + player_t *player; + + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(3)); + if ((player = actor->target->player) != NULL) + { // Squish the player + player->deltaviewheight = -16 * FRACUNIT; + } + } + else + { + mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX2); + if (mo != NULL) + { + S_StartSound(mo, SFX_MAULATOR_HAMMER_HIT); + } + } + if (P_Random() < 192 && actor->special2.i == 0) + { + P_SetMobjState(actor, S_MNTR_ATK3_4); + actor->special2.i = 1; + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_MntrFloorFire +// +//---------------------------------------------------------------------------- + +void A_MntrFloorFire(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1, r2; + + r1 = P_SubRandom(); + r2 = P_SubRandom(); + + actor->z = actor->floorz; + mo = P_SpawnMobj(actor->x + (r2 << 10), + actor->y + (r1 << 10), ONFLOORZ, + MT_MNTRFX3); + mo->target = actor->target; + mo->momx = 1; // Force block checking + P_CheckMissileSpawn(mo); +} + + +//---------------------------------------------------------------------------- +// +// PROC A_Scream +// +//---------------------------------------------------------------------------- + +void A_Scream(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int sound; + + S_StopSound(actor); + if (actor->player) + { + if (actor->player->morphTics) + { + S_StartSound(actor, actor->info->deathsound); + } + else + { + // Handle the different player death screams + if (actor->momz <= -39 * FRACUNIT) + { // Falling splat + sound = SFX_PLAYER_FALLING_SPLAT; + } + else if (actor->health > -50) + { // Normal death sound + switch (actor->player->class) + { + case PCLASS_FIGHTER: + sound = SFX_PLAYER_FIGHTER_NORMAL_DEATH; + break; + case PCLASS_CLERIC: + sound = SFX_PLAYER_CLERIC_NORMAL_DEATH; + break; + case PCLASS_MAGE: + sound = SFX_PLAYER_MAGE_NORMAL_DEATH; + break; + default: + sound = SFX_NONE; + break; + } + } + else if (actor->health > -100) + { // Crazy death sound + switch (actor->player->class) + { + case PCLASS_FIGHTER: + sound = SFX_PLAYER_FIGHTER_CRAZY_DEATH; + break; + case PCLASS_CLERIC: + sound = SFX_PLAYER_CLERIC_CRAZY_DEATH; + break; + case PCLASS_MAGE: + sound = SFX_PLAYER_MAGE_CRAZY_DEATH; + break; + default: + sound = SFX_NONE; + break; + } + } + else + { // Extreme death sound + switch (actor->player->class) + { + case PCLASS_FIGHTER: + sound = SFX_PLAYER_FIGHTER_EXTREME1_DEATH; + break; + case PCLASS_CLERIC: + sound = SFX_PLAYER_CLERIC_EXTREME1_DEATH; + break; + case PCLASS_MAGE: + sound = SFX_PLAYER_MAGE_EXTREME1_DEATH; + break; + default: + sound = SFX_NONE; + break; + } + sound += P_Random() % 3; // Three different extreme deaths + } + S_StartSound(actor, sound); + } + } + else + { + S_StartSound(actor, actor->info->deathsound); + } +} + +//--------------------------------------------------------------------------- +// +// PROC P_DropItem +// +//--------------------------------------------------------------------------- + +/* +void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance) +{ + mobj_t *mo; + + if(P_Random() > chance) + { + return; + } + mo = P_SpawnMobj(source->x, source->y, + source->z+(source->height>>1), type); + mo->momx = P_SubRandom()<<8; + mo->momy = P_SubRandom()<<8; + mo->momz = FRACUNIT*5+(P_Random()<<10); + mo->flags2 |= MF2_DROPPED; + mo->health = special; +} +*/ + +//---------------------------------------------------------------------------- +// +// PROC A_NoBlocking +// +//---------------------------------------------------------------------------- + +void A_NoBlocking(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags &= ~MF_SOLID; + + // Check for monsters dropping things +/* switch(actor->type) + { + // Add the monster dropped items here + case MT_MUMMYLEADERGHOST: + P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84); + break; + default: + break; + } +*/ +} + +//---------------------------------------------------------------------------- +// +// PROC A_Explode +// +// Handles a bunch of exploding things. +// +//---------------------------------------------------------------------------- + +void A_Explode(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int damage; + int distance; + boolean damageSelf; + + damage = 128; + distance = 128; + damageSelf = true; + switch (actor->type) + { + case MT_FIREBOMB: // Time Bombs + actor->z += 32 * FRACUNIT; + actor->flags &= ~MF_SHADOW; + break; + case MT_MNTRFX2: // Minotaur floor fire + damage = 24; + break; + case MT_BISHOP: // Bishop radius death + damage = 25 + (P_Random() & 15); + break; + case MT_HAMMER_MISSILE: // Fighter Hammer + damage = 128; + damageSelf = false; + break; + case MT_FSWORD_MISSILE: // Fighter Runesword + damage = 64; + damageSelf = false; + break; + case MT_CIRCLEFLAME: // Cleric Flame secondary flames + damage = 20; + damageSelf = false; + break; + case MT_SORCBALL1: // Sorcerer balls + case MT_SORCBALL2: + case MT_SORCBALL3: + distance = 255; + damage = 255; + actor->args[0] = 1; // don't play bounce + break; + case MT_SORCFX1: // Sorcerer spell 1 + damage = 30; + break; + case MT_SORCFX4: // Sorcerer spell 4 + damage = 20; + break; + case MT_TREEDESTRUCTIBLE: + damage = 10; + break; + case MT_DRAGON_FX2: + damage = 80; + damageSelf = false; + break; + case MT_MSTAFF_FX: + damage = 64; + distance = 192; + damageSelf = false; + break; + case MT_MSTAFF_FX2: + damage = 80; + distance = 192; + damageSelf = false; + break; + case MT_POISONCLOUD: + damage = 4; + distance = 40; + break; + case MT_ZXMAS_TREE: + case MT_ZSHRUB2: + damage = 30; + distance = 64; + break; + default: + break; + } + P_RadiusAttack(actor, actor->target, damage, distance, damageSelf); + if (actor->z <= actor->floorz + (distance << FRACBITS) + && actor->type != MT_POISONCLOUD) + { + P_HitFloor(actor); + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_Massacre +// +// Kills all monsters. +// +//---------------------------------------------------------------------------- + +int P_Massacre(void) +{ + int count; + mobj_t *mo; + thinker_t *think; + + count = 0; + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + if ((mo->flags & MF_COUNTKILL) && (mo->health > 0)) + { + mo->flags2 &= ~(MF2_NONSHOOTABLE + MF2_INVULNERABLE); + mo->flags |= MF_SHOOTABLE; + P_DamageMobj(mo, NULL, NULL, 10000); + count++; + } + } + return count; +} + + + +//---------------------------------------------------------------------------- +// +// PROC A_SkullPop +// +//---------------------------------------------------------------------------- + +void A_SkullPop(mobj_t *actor, player_t *player_, pspdef_t *psp) +{ + mobj_t *mo; + player_t *player; + + if (!actor->player) + { + return; + } + actor->flags &= ~MF_SOLID; + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 48 * FRACUNIT, + MT_BLOODYSKULL); + //mo->target = actor; + mo->momx = P_SubRandom() << 9; + mo->momy = P_SubRandom() << 9; + mo->momz = FRACUNIT * 2 + (P_Random() << 6); + // Attach player mobj to bloody skull + player = actor->player; + actor->player = NULL; + actor->special1.i = player->class; + mo->player = player; + mo->health = actor->health; + mo->angle = actor->angle; + player->mo = mo; + player->lookdir = 0; + player->damagecount = 32; +} + +//---------------------------------------------------------------------------- +// +// PROC A_CheckSkullFloor +// +//---------------------------------------------------------------------------- + +void A_CheckSkullFloor(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->z <= actor->floorz) + { + P_SetMobjState(actor, S_BLOODYSKULLX1); + S_StartSound(actor, SFX_DRIP); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_CheckSkullDone +// +//---------------------------------------------------------------------------- + +void A_CheckSkullDone(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special2.i == 666) + { + P_SetMobjState(actor, S_BLOODYSKULLX2); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_CheckBurnGone +// +//---------------------------------------------------------------------------- + +void A_CheckBurnGone(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special2.i == 666) + { + P_SetMobjState(actor, S_PLAY_FDTH20); + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_FreeTargMobj +// +//---------------------------------------------------------------------------- + +void A_FreeTargMobj(mobj_t *mo, player_t *player, pspdef_t *psp) +{ + mo->momx = mo->momy = mo->momz = 0; + mo->z = mo->ceilingz + 4 * FRACUNIT; + mo->flags &= + ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_SOLID | MF_COUNTKILL); + mo->flags |= MF_CORPSE | MF_DROPOFF | MF_NOGRAVITY; + mo->flags2 &= ~(MF2_PASSMOBJ | MF2_LOGRAV); + mo->flags2 |= MF2_DONTDRAW; + mo->player = NULL; + mo->health = -1000; // Don't resurrect +} + + +//---------------------------------------------------------------------------- +// +// CorpseQueue Routines +// +//---------------------------------------------------------------------------- + +// Corpse queue for monsters - this should be saved out +#define CORPSEQUEUESIZE 64 +mobj_t *corpseQueue[CORPSEQUEUESIZE]; +int corpseQueueSlot; + +// throw another corpse on the queue +void A_QueueCorpse(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *corpse; + + if (corpseQueueSlot >= CORPSEQUEUESIZE) + { // Too many corpses - remove an old one + corpse = corpseQueue[corpseQueueSlot % CORPSEQUEUESIZE]; + if (corpse) + P_RemoveMobj(corpse); + } + corpseQueue[corpseQueueSlot % CORPSEQUEUESIZE] = actor; + corpseQueueSlot++; +} + +// Remove a mobj from the queue (for resurrection) +void A_DeQueueCorpse(mobj_t *actor) +{ + int slot; + + for (slot = 0; slot < CORPSEQUEUESIZE; slot++) + { + if (corpseQueue[slot] == actor) + { + corpseQueue[slot] = NULL; + break; + } + } +} + +void P_InitCreatureCorpseQueue(boolean corpseScan) +{ + thinker_t *think; + mobj_t *mo; + + // Initialize queue + corpseQueueSlot = 0; + memset(corpseQueue, 0, sizeof(mobj_t *) * CORPSEQUEUESIZE); + + if (!corpseScan) + return; + + // Search mobj list for corpses and place them in this queue + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + continue; + mo = (mobj_t *) think; + if (!(mo->flags & MF_CORPSE)) + continue; // Must be a corpse + if (mo->flags & MF_ICECORPSE) + continue; // Not ice corpses + // Only corpses that call A_QueueCorpse from death routine + switch (mo->type) + { + case MT_CENTAUR: + case MT_CENTAURLEADER: + case MT_DEMON: + case MT_DEMON2: + case MT_WRAITH: + case MT_WRAITHB: + case MT_BISHOP: + case MT_ETTIN: + case MT_PIG: + case MT_CENTAUR_SHIELD: + case MT_CENTAUR_SWORD: + case MT_DEMONCHUNK1: + case MT_DEMONCHUNK2: + case MT_DEMONCHUNK3: + case MT_DEMONCHUNK4: + case MT_DEMONCHUNK5: + case MT_DEMON2CHUNK1: + case MT_DEMON2CHUNK2: + case MT_DEMON2CHUNK3: + case MT_DEMON2CHUNK4: + case MT_DEMON2CHUNK5: + case MT_FIREDEMON_SPLOTCH1: + case MT_FIREDEMON_SPLOTCH2: + A_QueueCorpse(mo, NULL, NULL); // Add corpse to queue + break; + default: + break; + } + } +} + + +//---------------------------------------------------------------------------- +// +// PROC A_AddPlayerCorpse +// +//---------------------------------------------------------------------------- + +#define BODYQUESIZE 32 +mobj_t *bodyque[BODYQUESIZE]; +int bodyqueslot; + +void A_AddPlayerCorpse(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (bodyqueslot >= BODYQUESIZE) + { // Too many player corpses - remove an old one + P_RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]); + } + bodyque[bodyqueslot % BODYQUESIZE] = actor; + bodyqueslot++; +} + +//============================================================================ +// +// A_SerpentUnHide +// +//============================================================================ + +void A_SerpentUnHide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 &= ~MF2_DONTDRAW; + actor->floorclip = 24 * FRACUNIT; +} + +//============================================================================ +// +// A_SerpentHide +// +//============================================================================ + +void A_SerpentHide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 |= MF2_DONTDRAW; + actor->floorclip = 0; +} + +//============================================================================ +// +// A_SerpentChase +// +//============================================================================ + +void A_SerpentChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int delta; + int oldX, oldY, oldFloor; + + if (actor->reactiontime) + { + actor->reactiontime--; + } + + // Modify target threshold + if (actor->threshold) + { + actor->threshold--; + } + + if (gameskill == sk_nightmare) + { // Monsters move faster in nightmare mode + actor->tics -= actor->tics / 2; + if (actor->tics < 3) + { + actor->tics = 3; + } + } + +// +// turn towards movement direction if not there yet +// + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + if (delta > 0) + { + actor->angle -= ANG90 / 2; + } + else if (delta < 0) + { + actor->angle += ANG90 / 2; + } + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { // look for a new target + if (P_LookForPlayers(actor, true)) + { // got a new target + return; + } + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + +// +// don't attack twice in a row +// + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare) + P_NewChaseDir(actor); + return; + } + +// +// check for melee attack +// + if (actor->info->meleestate && P_CheckMeleeRange(actor)) + { + if (actor->info->attacksound) + { + S_StartSound(actor, actor->info->attacksound); + } + P_SetMobjState(actor, actor->info->meleestate); + return; + } + +// +// possibly choose another target +// + if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) + { + if (P_LookForPlayers(actor, true)) + return; // got a new target + } + +// +// chase towards player +// + oldX = actor->x; + oldY = actor->y; + oldFloor = actor->subsector->sector->floorpic; + if (--actor->movecount < 0 || !P_Move(actor)) + { + P_NewChaseDir(actor); + } + if (actor->subsector->sector->floorpic != oldFloor) + { + P_TryMove(actor, oldX, oldY); + P_NewChaseDir(actor); + } + +// +// make active sound +// + if (actor->info->activesound && P_Random() < 3) + { + S_StartSound(actor, actor->info->activesound); + } +} + +//============================================================================ +// +// A_SerpentRaiseHump +// +// Raises the hump above the surface by raising the floorclip level +//============================================================================ + +void A_SerpentRaiseHump(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->floorclip -= 4 * FRACUNIT; +} + +//============================================================================ +// +// A_SerpentLowerHump +// +//============================================================================ + +void A_SerpentLowerHump(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->floorclip += 4 * FRACUNIT; +} + +//============================================================================ +// +// A_SerpentHumpDecide +// +// Decided whether to hump up, or if the mobj is a serpent leader, +// to missile attack +//============================================================================ + +void A_SerpentHumpDecide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->type == MT_SERPENTLEADER) + { + if (P_Random() > 30) + { + return; + } + else if (P_Random() < 40) + { // Missile attack + P_SetMobjState(actor, S_SERPENT_SURFACE1); + return; + } + } + else if (P_Random() > 3) + { + return; + } + if (!P_CheckMeleeRange(actor)) + { // The hump shouldn't occur when within melee range + if (actor->type == MT_SERPENTLEADER && P_Random() < 128) + { + P_SetMobjState(actor, S_SERPENT_SURFACE1); + } + else + { + P_SetMobjState(actor, S_SERPENT_HUMP1); + S_StartSound(actor, SFX_SERPENT_ACTIVE); + } + } +} + +//============================================================================ +// +// A_SerpentBirthScream +// +//============================================================================ + +void A_SerpentBirthScream(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(actor, SFX_SERPENT_BIRTH); +} + +//============================================================================ +// +// A_SerpentDiveSound +// +//============================================================================ + +void A_SerpentDiveSound(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(actor, SFX_SERPENT_ACTIVE); +} + +//============================================================================ +// +// A_SerpentWalk +// +// Similar to A_Chase, only has a hardcoded entering of meleestate +//============================================================================ + +void A_SerpentWalk(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int delta; + + if (actor->reactiontime) + { + actor->reactiontime--; + } + + // Modify target threshold + if (actor->threshold) + { + actor->threshold--; + } + + if (gameskill == sk_nightmare) + { // Monsters move faster in nightmare mode + actor->tics -= actor->tics / 2; + if (actor->tics < 3) + { + actor->tics = 3; + } + } + +// +// turn towards movement direction if not there yet +// + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + if (delta > 0) + { + actor->angle -= ANG90 / 2; + } + else if (delta < 0) + { + actor->angle += ANG90 / 2; + } + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { // look for a new target + if (P_LookForPlayers(actor, true)) + { // got a new target + return; + } + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + +// +// don't attack twice in a row +// + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare) + P_NewChaseDir(actor); + return; + } + +// +// check for melee attack +// + if (actor->info->meleestate && P_CheckMeleeRange(actor)) + { + if (actor->info->attacksound) + { + S_StartSound(actor, actor->info->attacksound); + } + P_SetMobjState(actor, S_SERPENT_ATK1); + return; + } +// +// possibly choose another target +// + if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) + { + if (P_LookForPlayers(actor, true)) + return; // got a new target + } + +// +// chase towards player +// + if (--actor->movecount < 0 || !P_Move(actor)) + { + P_NewChaseDir(actor); + } +} + +//============================================================================ +// +// A_SerpentCheckForAttack +// +//============================================================================ + +void A_SerpentCheckForAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + if (actor->type == MT_SERPENTLEADER) + { + if (!P_CheckMeleeRange(actor)) + { + P_SetMobjState(actor, S_SERPENT_ATK1); + return; + } + } + if (P_CheckMeleeRange2(actor)) + { + P_SetMobjState(actor, S_SERPENT_WALK1); + } + else if (P_CheckMeleeRange(actor)) + { + if (P_Random() < 32) + { + P_SetMobjState(actor, S_SERPENT_WALK1); + } + else + { + P_SetMobjState(actor, S_SERPENT_ATK1); + } + } +} + +//============================================================================ +// +// A_SerpentChooseAttack +// +//============================================================================ + +void A_SerpentChooseAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target || P_CheckMeleeRange(actor)) + { + return; + } + if (actor->type == MT_SERPENTLEADER) + { + P_SetMobjState(actor, S_SERPENT_MISSILE1); + } +} + +//============================================================================ +// +// A_SerpentMeleeAttack +// +//============================================================================ + +void A_SerpentMeleeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(5)); + S_StartSound(actor, SFX_SERPENT_MELEEHIT); + } + if (P_Random() < 96) + { + A_SerpentCheckForAttack(actor, player, psp); + } +} + +//============================================================================ +// +// A_SerpentMissileAttack +// +//============================================================================ + +void A_SerpentMissileAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + + P_SpawnMissile(actor, actor->target, MT_SERPENTFX); +} + +//============================================================================ +// +// A_SerpentHeadPop +// +//============================================================================ + +void A_SerpentHeadPop(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_SERPENT_HEAD); +} + +//============================================================================ +// +// A_SerpentSpawnGibs +// +//============================================================================ + +void A_SerpentSpawnGibs(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1, r2; + + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12), + actor->y + ((r1 - 128) << 12), + actor->floorz + FRACUNIT, MT_SERPENT_GIB1); + if (mo) + { + mo->momx = (P_Random() - 128) << 6; + mo->momy = (P_Random() - 128) << 6; + mo->floorclip = 6 * FRACUNIT; + } + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12), + actor->y + ((r1 - 128) << 12), + actor->floorz + FRACUNIT, MT_SERPENT_GIB2); + if (mo) + { + mo->momx = (P_Random() - 128) << 6; + mo->momy = (P_Random() - 128) << 6; + mo->floorclip = 6 * FRACUNIT; + } + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12), + actor->y + ((r1 - 128) << 12), + actor->floorz + FRACUNIT, MT_SERPENT_GIB3); + if (mo) + { + mo->momx = (P_Random() - 128) << 6; + mo->momy = (P_Random() - 128) << 6; + mo->floorclip = 6 * FRACUNIT; + } +} + +//============================================================================ +// +// A_FloatGib +// +//============================================================================ + +void A_FloatGib(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->floorclip -= FRACUNIT; +} + +//============================================================================ +// +// A_SinkGib +// +//============================================================================ + +void A_SinkGib(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->floorclip += FRACUNIT; +} + +//============================================================================ +// +// A_DelayGib +// +//============================================================================ + +void A_DelayGib(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->tics -= P_Random() >> 2; +} + +//============================================================================ +// +// A_SerpentHeadCheck +// +//============================================================================ + +void A_SerpentHeadCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->z <= actor->floorz) + { + if (P_GetThingFloorType(actor) >= FLOOR_LIQUID) + { + P_HitFloor(actor); + P_SetMobjState(actor, S_NULL); + } + else + { + P_SetMobjState(actor, S_SERPENT_HEAD_X1); + } + } +} + +//============================================================================ +// +// A_CentaurAttack +// +//============================================================================ + +void A_CentaurAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, P_Random() % 7 + 3); + } +} + +//============================================================================ +// +// A_CentaurAttack2 +// +//============================================================================ + +void A_CentaurAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + P_SpawnMissile(actor, actor->target, MT_CENTAUR_FX); + S_StartSound(actor, SFX_CENTAURLEADER_ATTACK); +} + +//============================================================================ +// +// A_CentaurDropStuff +// +// Spawn shield/sword sprites when the centaur pulps //============================================================================ + +void A_CentaurDropStuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_CENTAUR_SHIELD); + if (mo) + { + angle = actor->angle + ANG90; + mo->momz = FRACUNIT * 8 + (P_Random() << 10); + mo->momx = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_CENTAUR_SWORD); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = FRACUNIT * 8 + (P_Random() << 10); + mo->momx = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } +} + +//============================================================================ +// +// A_CentaurDefend +// +//============================================================================ + +void A_CentaurDefend(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_FaceTarget(actor, player, psp); + if (P_CheckMeleeRange(actor) && P_Random() < 32) + { + A_UnSetInvulnerable(actor, player, psp); + P_SetMobjState(actor, actor->info->meleestate); + } +} + +//============================================================================ +// +// A_BishopAttack +// +//============================================================================ + +void A_BishopAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + { + return; + } + S_StartSound(actor, actor->info->attacksound); + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(4)); + return; + } + actor->special1.i = (P_Random() & 3) + 5; +} + +//============================================================================ +// +// A_BishopAttack2 +// +// Spawns one of a string of bishop missiles +//============================================================================ + +void A_BishopAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + if (!actor->target || !actor->special1.i) + { + actor->special1.i = 0; + P_SetMobjState(actor, S_BISHOP_WALK1); + return; + } + mo = P_SpawnMissile(actor, actor->target, MT_BISH_FX); + if (mo) + { + mo->special1.m = actor->target; + mo->special2.i = 16; // High word == x/y, Low word == z + } + actor->special1.i--; +} + +//============================================================================ +// +// A_BishopMissileWeave +// +//============================================================================ + +void A_BishopMissileWeave(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t newX, newY; + int weaveXY, weaveZ; + int angle; + + weaveXY = actor->special2.i >> 16; + weaveZ = actor->special2.i & 0xFFFF; + angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + newX = actor->x - FixedMul(finecosine[angle], + FloatBobOffsets[weaveXY] << 1); + newY = actor->y - FixedMul(finesine[angle], + FloatBobOffsets[weaveXY] << 1); + weaveXY = (weaveXY + 2) & 63; + newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 1); + newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 1); + P_TryMove(actor, newX, newY); + actor->z -= FloatBobOffsets[weaveZ]; + weaveZ = (weaveZ + 2) & 63; + actor->z += FloatBobOffsets[weaveZ]; + actor->special2.i = weaveZ + (weaveXY << 16); +} + +//============================================================================ +// +// A_BishopMissileSeek +// +//============================================================================ + +void A_BishopMissileSeek(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SeekerMissile(actor, ANG1 * 2, ANG1 * 3); +} + +//============================================================================ +// +// A_BishopDecide +// +//============================================================================ + +void A_BishopDecide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_Random() < 220) + { + return; + } + else + { + P_SetMobjState(actor, S_BISHOP_BLUR1); + } +} + +//============================================================================ +// +// A_BishopDoBlur +// +//============================================================================ + +void A_BishopDoBlur(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->special1.i = (P_Random() & 3) + 3; // Random number of blurs + if (P_Random() < 120) + { + P_ThrustMobj(actor, actor->angle + ANG90, 11 * FRACUNIT); + } + else if (P_Random() > 125) + { + P_ThrustMobj(actor, actor->angle - ANG90, 11 * FRACUNIT); + } + else + { // Thrust forward + P_ThrustMobj(actor, actor->angle, 11 * FRACUNIT); + } + S_StartSound(actor, SFX_BISHOP_BLUR); +} + +//============================================================================ +// +// A_BishopSpawnBlur +// +//============================================================================ + +void A_BishopSpawnBlur(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + if (!--actor->special1.i) + { + actor->momx = 0; + actor->momy = 0; + if (P_Random() > 96) + { + P_SetMobjState(actor, S_BISHOP_WALK1); + } + else + { + P_SetMobjState(actor, S_BISHOP_ATK1); + } + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BISHOPBLUR); + if (mo) + { + mo->angle = actor->angle; + } +} + +//============================================================================ +// +// A_BishopChase +// +//============================================================================ + +void A_BishopChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->z -= FloatBobOffsets[actor->special2.i] >> 1; + actor->special2.i = (actor->special2.i + 4) & 63; + actor->z += FloatBobOffsets[actor->special2.i] >> 1; +} + +//============================================================================ +// +// A_BishopPuff +// +//============================================================================ + +void A_BishopPuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 40 * FRACUNIT, + MT_BISHOP_PUFF); + if (mo) + { + mo->momz = FRACUNIT / 2; + } +} + +//============================================================================ +// +// A_BishopPainBlur +// +//============================================================================ + +void A_BishopPainBlur(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int r1,r2,r3; + + if (P_Random() < 64) + { + P_SetMobjState(actor, S_BISHOP_BLUR1); + return; + } + + r1 = P_SubRandom(); + r2 = P_SubRandom(); + r3 = P_SubRandom(); + + mo = P_SpawnMobj(actor->x + (r3 << 12), actor->y + + (r2 << 12), + actor->z + (r1 << 11), + MT_BISHOPPAINBLUR); + if (mo) + { + mo->angle = actor->angle; + } +} + +//============================================================================ +// +// DragonSeek +// +//============================================================================ + +static void DragonSeek(mobj_t * actor, angle_t thresh, angle_t turnMax) +{ + int dir; + int dist; + angle_t delta; + angle_t angle; + mobj_t *target; + int search; + int i; + int bestArg; + angle_t bestAngle; + angle_t angleToSpot, angleToTarget; + mobj_t *mo; + + target = actor->special1.m; + if (target == NULL) + { + return; + } + dir = P_FaceMobj(actor, target, &delta); + if (delta > thresh) + { + delta >>= 1; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (dir) + { // Turn clockwise + actor->angle += delta; + } + else + { // Turn counter clockwise + actor->angle -= delta; + } + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(actor->info->speed, finecosine[angle]); + actor->momy = FixedMul(actor->info->speed, finesine[angle]); + if (actor->z + actor->height < target->z + || target->z + target->height < actor->z) + { + dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); + dist = dist / actor->info->speed; + if (dist < 1) + { + dist = 1; + } + actor->momz = (target->z - actor->z) / dist; + } + else + { + dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); + dist = dist / actor->info->speed; + } + if (target->flags & MF_SHOOTABLE && P_Random() < 64) + { // attack the destination mobj if it's attackable + mobj_t *oldTarget; + + if (abs((int) actor->angle - (int) R_PointToAngle2(actor->x, actor->y, + target->x, + target->y)) < ANG45 / 2) + { + oldTarget = actor->target; + actor->target = target; + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(10)); + S_StartSound(actor, SFX_DRAGON_ATTACK); + } + else if (P_Random() < 128 && P_CheckMissileRange(actor)) + { + P_SpawnMissile(actor, target, MT_DRAGON_FX); + S_StartSound(actor, SFX_DRAGON_ATTACK); + } + actor->target = oldTarget; + } + } + if (dist < 4) + { // Hit the target thing + if (actor->target && P_Random() < 200) + { + bestArg = -1; + bestAngle = ANG_MAX; + angleToTarget = R_PointToAngle2(actor->x, actor->y, + actor->target->x, + actor->target->y); + for (i = 0; i < 5; i++) + { + if (!target->args[i]) + { + continue; + } + search = -1; + mo = P_FindMobjFromTID(target->args[i], &search); + angleToSpot = R_PointToAngle2(actor->x, actor->y, + mo->x, mo->y); + if (abs((int) angleToSpot - (int) angleToTarget) < bestAngle) + { + bestAngle = abs((int) angleToSpot - (int) angleToTarget); + bestArg = i; + } + } + if (bestArg != -1) + { + search = -1; + actor->special1.m = + P_FindMobjFromTID(target->args[bestArg], &search); + } + } + else + { + do + { + i = (P_Random() >> 2) % 5; + } + while (!target->args[i]); + search = -1; + actor->special1.m = + P_FindMobjFromTID(target->args[i], &search); + } + } +} + +//============================================================================ +// +// A_DragonInitFlight +// +//============================================================================ + +void A_DragonInitFlight(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int search; + + search = -1; + do + { // find the first tid identical to the dragon's tid + actor->special1.m = P_FindMobjFromTID(actor->tid, &search); + if (search == -1) + { + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + } + while (actor->special1.m == actor); + P_RemoveMobjFromTIDList(actor); +} + +//============================================================================ +// +// A_DragonFlight +// +//============================================================================ + +void A_DragonFlight(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + + DragonSeek(actor, 4 * ANG1, 8 * ANG1); + if (actor->target) + { + if (!(actor->target->flags & MF_SHOOTABLE)) + { // target died + actor->target = NULL; + return; + } + angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, + actor->target->y); + if (abs((int) actor->angle - (int) angle) < ANG45 / 2 + && P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(8)); + S_StartSound(actor, SFX_DRAGON_ATTACK); + } + else if (abs((int) actor->angle - (int) angle) <= ANG1 * 20) + { + P_SetMobjState(actor, actor->info->missilestate); + S_StartSound(actor, SFX_DRAGON_ATTACK); + } + } + else + { + P_LookForPlayers(actor, true); + } +} + +//============================================================================ +// +// A_DragonFlap +// +//============================================================================ + +void A_DragonFlap(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_DragonFlight(actor, player, psp); + if (P_Random() < 240) + { + S_StartSound(actor, SFX_DRAGON_WINGFLAP); + } + else + { + S_StartSound(actor, actor->info->activesound); + } +} + +//============================================================================ +// +// A_DragonAttack +// +//============================================================================ + +void A_DragonAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMissile(actor, actor->target, MT_DRAGON_FX); +} + +//============================================================================ +// +// A_DragonFX2 +// +//============================================================================ + +void A_DragonFX2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int i; + int r1,r2,r3; + int delay; + + delay = 16 + (P_Random() >> 3); + for (i = 1 + (P_Random() & 3); i; i--) + { + r1 = P_Random(); + r2 = P_Random(); + r3 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r3 - 128) << 14), + actor->y + ((r2 - 128) << 14), + actor->z + ((r1 - 128) << 12), + MT_DRAGON_FX2); + if (mo) + { + mo->tics = delay + (P_Random() & 3) * i * 2; + mo->target = actor->target; + } + } +} + +//============================================================================ +// +// A_DragonPain +// +//============================================================================ + +void A_DragonPain(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_Pain(actor, player, psp); + if (!actor->special1.i) + { // no destination spot yet + P_SetMobjState(actor, S_DRAGON_INIT); + } +} + +//============================================================================ +// +// A_DragonCheckCrash +// +//============================================================================ + +void A_DragonCheckCrash(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->z <= actor->floorz) + { + P_SetMobjState(actor, S_DRAGON_CRASH1); + } +} + +//============================================================================ +// Demon AI +//============================================================================ + +// +// A_DemonAttack1 (melee) +// +void A_DemonAttack1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(2)); + } +} + + +// +// A_DemonAttack2 (missile) +// +void A_DemonAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int fireBall; + + if (actor->type == MT_DEMON) + { + fireBall = MT_DEMONFX1; + } + else + { + fireBall = MT_DEMON2FX1; + } + mo = P_SpawnMissile(actor, actor->target, fireBall); + if (mo) + { + mo->z += 30 * FRACUNIT; + S_StartSound(actor, SFX_DEMON_MISSILE_FIRE); + } +} + +// +// A_DemonDeath +// + +void A_DemonDeath(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMONCHUNK1); + if (mo) + { + angle = actor->angle + ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMONCHUNK2); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMONCHUNK3); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMONCHUNK4); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMONCHUNK5); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } +} + +//=========================================================================== +// +// A_Demon2Death +// +//=========================================================================== + +void A_Demon2Death(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMON2CHUNK1); + if (mo) + { + angle = actor->angle + ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMON2CHUNK2); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMON2CHUNK3); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMON2CHUNK4); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, + MT_DEMON2CHUNK5); + if (mo) + { + angle = actor->angle - ANG90; + mo->momz = 8 * FRACUNIT; + mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + } +} + + + +// +// A_SinkMobj +// Sink a mobj incrementally into the floor +// + +boolean A_SinkMobj(mobj_t * actor) +{ + if (actor->floorclip < actor->info->height) + { + switch (actor->type) + { + case MT_THRUSTFLOOR_DOWN: + case MT_THRUSTFLOOR_UP: + actor->floorclip += 6 * FRACUNIT; + break; + default: + actor->floorclip += FRACUNIT; + break; + } + return false; + } + return true; +} + +// +// A_RaiseMobj +// Raise a mobj incrementally from the floor to +// + +boolean A_RaiseMobj(mobj_t * actor) +{ + int done = true; + + // Raise a mobj from the ground + if (actor->floorclip > 0) + { + switch (actor->type) + { + case MT_WRAITHB: + actor->floorclip -= 2 * FRACUNIT; + break; + case MT_THRUSTFLOOR_DOWN: + case MT_THRUSTFLOOR_UP: + actor->floorclip -= actor->special2.i * FRACUNIT; + break; + default: + actor->floorclip -= 2 * FRACUNIT; + break; + } + if (actor->floorclip <= 0) + { + actor->floorclip = 0; + done = true; + } + else + { + done = false; + } + } + return done; // Reached target height +} + + +//============================================================================ +// Wraith Variables +// +// special1 Internal index into floatbob +// special2 +//============================================================================ + +// +// A_WraithInit +// + +void A_WraithInit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->z += 48 << FRACBITS; + actor->special1.i = 0; // index into floatbob +} + +void A_WraithRaiseInit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags2 &= ~MF2_DONTDRAW; + actor->flags2 &= ~MF2_NONSHOOTABLE; + actor->flags |= MF_SHOOTABLE | MF_SOLID; + actor->floorclip = actor->info->height; +} + +void A_WraithRaise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (A_RaiseMobj(actor)) + { + // Reached it's target height + P_SetMobjState(actor, S_WRAITH_CHASE1); + } + + P_SpawnDirt(actor, actor->radius); +} + + +void A_WraithMelee(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int amount; + + // Steal health from target and give to player + if (P_CheckMeleeRange(actor) && (P_Random() < 220)) + { + amount = HITDICE(2); + P_DamageMobj(actor->target, actor, actor, amount); + actor->health += amount; + } +} + +void A_WraithMissile(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMissile(actor, actor->target, MT_WRAITHFX1); + if (mo) + { + S_StartSound(actor, SFX_WRAITH_MISSILE_FIRE); + } +} + + +// +// A_WraithFX2 - spawns sparkle tail of missile +// + +void A_WraithFX2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t angle; + int i; + + for (i = 0; i < 2; i++) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX2); + if (mo) + { + if (P_Random() < 128) + { + angle = actor->angle + (P_Random() << 22); + } + else + { + angle = actor->angle - (P_Random() << 22); + } + mo->momz = 0; + mo->momx = FixedMul((P_Random() << 7) + FRACUNIT, + finecosine[angle >> ANGLETOFINESHIFT]); + mo->momy = FixedMul((P_Random() << 7) + FRACUNIT, + finesine[angle >> ANGLETOFINESHIFT]); + mo->target = actor; + mo->floorclip = 10 * FRACUNIT; + } + } +} + + +// Spawn an FX3 around the actor during attacks +void A_WraithFX3(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int numdropped = P_Random() % 15; + int i; + + for (i = 0; i < numdropped; i++) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX3); + if (mo) + { + mo->x += (P_Random() - 128) << 11; + mo->y += (P_Random() - 128) << 11; + mo->z += (P_Random() << 10); + mo->target = actor; + } + } +} + +// Spawn an FX4 during movement +void A_WraithFX4(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int chance = P_Random(); + int spawn4, spawn5; + + if (chance < 10) + { + spawn4 = true; + spawn5 = false; + } + else if (chance < 20) + { + spawn4 = false; + spawn5 = true; + } + else if (chance < 25) + { + spawn4 = true; + spawn5 = true; + } + else + { + spawn4 = false; + spawn5 = false; + } + + if (spawn4) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX4); + if (mo) + { + mo->x += (P_Random() - 128) << 12; + mo->y += (P_Random() - 128) << 12; + mo->z += (P_Random() << 10); + mo->target = actor; + } + } + if (spawn5) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX5); + if (mo) + { + mo->x += (P_Random() - 128) << 11; + mo->y += (P_Random() - 128) << 11; + mo->z += (P_Random() << 10); + mo->target = actor; + } + } +} + + +void A_WraithLook(mobj_t *actor, player_t *player, pspdef_t *psp) +{ +// A_WraithFX4(actor); // too expensive + A_Look(actor, player, psp); +} + + +void A_WraithChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int weaveindex = actor->special1.i; + actor->z += FloatBobOffsets[weaveindex]; + actor->special1.i = (weaveindex + 2) & 63; +// if (actor->floorclip > 0) +// { +// P_SetMobjState(actor, S_WRAITH_RAISE2); +// return; +// } + A_Chase(actor, player, psp); + A_WraithFX4(actor, player, psp); +} + + + +//============================================================================ +// Ettin AI +//============================================================================ + +void A_EttinAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_CheckMeleeRange(actor)) + { + P_DamageMobj(actor->target, actor, actor, HITDICE(2)); + } +} + + +void A_DropMace(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, + actor->z + (actor->height >> 1), MT_ETTIN_MACE); + if (mo) + { + mo->momx = (P_Random() - 128) << 11; + mo->momy = (P_Random() - 128) << 11; + mo->momz = FRACUNIT * 10 + (P_Random() << 10); + mo->target = actor; + } +} + + +//============================================================================ +// Fire Demon AI +// +// special1 index into floatbob +// special2 whether strafing or not +//============================================================================ + +void A_FiredSpawnRock(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int x, y, z; + int rtype = 0; + + switch (P_Random() % 5) + { + case 0: + rtype = MT_FIREDEMON_FX1; + break; + case 1: + rtype = MT_FIREDEMON_FX2; + break; + case 2: + rtype = MT_FIREDEMON_FX3; + break; + case 3: + rtype = MT_FIREDEMON_FX4; + break; + case 4: + rtype = MT_FIREDEMON_FX5; + break; + } + + x = actor->x + ((P_Random() - 128) << 12); + y = actor->y + ((P_Random() - 128) << 12); + z = actor->z + ((P_Random()) << 11); + mo = P_SpawnMobj(x, y, z, rtype); + if (mo) + { + mo->target = actor; + mo->momx = (P_Random() - 128) << 10; + mo->momy = (P_Random() - 128) << 10; + mo->momz = (P_Random() << 10); + mo->special1.i = 2; // Number bounces + } + + // Initialize fire demon + actor->special2.i = 0; + actor->flags &= ~MF_JUSTATTACKED; +} + +void A_FiredRocks(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_FiredSpawnRock(actor, player, psp); + A_FiredSpawnRock(actor, player, psp); + A_FiredSpawnRock(actor, player, psp); + A_FiredSpawnRock(actor, player, psp); + A_FiredSpawnRock(actor, player, psp); +} + +void A_FiredAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + mo = P_SpawnMissile(actor, actor->target, MT_FIREDEMON_FX6); + if (mo) + S_StartSound(actor, SFX_FIRED_ATTACK); +} + +void A_SmBounce(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + // give some more momentum (x,y,&z) + actor->z = actor->floorz + FRACUNIT; + actor->momz = (2 * FRACUNIT) + (P_Random() << 10); + actor->momx = P_Random() % 3 << FRACBITS; + actor->momy = P_Random() % 3 << FRACBITS; +} + + +#define FIREDEMON_ATTACK_RANGE 64*8*FRACUNIT + +void A_FiredChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int weaveindex = actor->special1.i; + mobj_t *target = actor->target; + angle_t ang; + fixed_t dist; + + if (actor->reactiontime) + actor->reactiontime--; + if (actor->threshold) + actor->threshold--; + + // Float up and down + actor->z += FloatBobOffsets[weaveindex]; + actor->special1.i = (weaveindex + 2) & 63; + + // Insure it stays above certain height + if (actor->z < actor->floorz + (64 * FRACUNIT)) + { + actor->z += 2 * FRACUNIT; + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { // Invalid target + P_LookForPlayers(actor, true); + return; + } + + // Strafe + if (actor->special2.i > 0) + { + actor->special2.i--; + } + else + { + actor->special2.i = 0; + actor->momx = actor->momy = 0; + dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); + if (dist < FIREDEMON_ATTACK_RANGE) + { + if (P_Random() < 30) + { + ang = + R_PointToAngle2(actor->x, actor->y, target->x, target->y); + if (P_Random() < 128) + ang += ANG90; + else + ang -= ANG90; + ang >>= ANGLETOFINESHIFT; + actor->momx = FixedMul(8 * FRACUNIT, finecosine[ang]); + actor->momy = FixedMul(8 * FRACUNIT, finesine[ang]); + actor->special2.i = 3; // strafe time + } + } + } + + FaceMovementDirection(actor); + + // Normal movement + if (!actor->special2.i) + { + if (--actor->movecount < 0 || !P_Move(actor)) + { + P_NewChaseDir(actor); + } + } + + // Do missile attack + if (!(actor->flags & MF_JUSTATTACKED)) + { + if (P_CheckMissileRange(actor) && (P_Random() < 20)) + { + P_SetMobjState(actor, actor->info->missilestate); + actor->flags |= MF_JUSTATTACKED; + return; + } + } + else + { + actor->flags &= ~MF_JUSTATTACKED; + } + + // make active sound + if (actor->info->activesound && P_Random() < 3) + { + S_StartSound(actor, actor->info->activesound); + } +} + +void A_FiredSplotch(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FIREDEMON_SPLOTCH1); + if (mo) + { + mo->momx = (P_Random() - 128) << 11; + mo->momy = (P_Random() - 128) << 11; + mo->momz = FRACUNIT * 3 + (P_Random() << 10); + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FIREDEMON_SPLOTCH2); + if (mo) + { + mo->momx = (P_Random() - 128) << 11; + mo->momy = (P_Random() - 128) << 11; + mo->momz = FRACUNIT * 3 + (P_Random() << 10); + } +} + + +//============================================================================ +// +// A_IceGuyLook +// +//============================================================================ + +void A_IceGuyLook(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t dist; + fixed_t an; + + A_Look(actor, player, psp); + if (P_Random() < 64) + { + dist = ((P_Random() - 128) * actor->radius) >> 7; + an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + + P_SpawnMobj(actor->x + FixedMul(dist, finecosine[an]), + actor->y + FixedMul(dist, finesine[an]), + actor->z + 60 * FRACUNIT, + MT_ICEGUY_WISP1 + (P_Random() & 1)); + } +} + +//============================================================================ +// +// A_IceGuyChase +// +//============================================================================ + +void A_IceGuyChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t dist; + fixed_t an; + mobj_t *mo; + + A_Chase(actor, player, psp); + if (P_Random() < 128) + { + dist = ((P_Random() - 128) * actor->radius) >> 7; + an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + + mo = P_SpawnMobj(actor->x + FixedMul(dist, finecosine[an]), + actor->y + FixedMul(dist, finesine[an]), + actor->z + 60 * FRACUNIT, + MT_ICEGUY_WISP1 + (P_Random() & 1)); + if (mo) + { + mo->momx = actor->momx; + mo->momy = actor->momy; + mo->momz = actor->momz; + mo->target = actor; + } + } +} + +//============================================================================ +// +// A_IceGuyAttack +// +//============================================================================ + +void A_IceGuyAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t an; + + if (!actor->target) + { + return; + } + an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + P_SpawnMissileXYZ(actor->x + FixedMul(actor->radius >> 1, + finecosine[an]), + actor->y + FixedMul(actor->radius >> 1, finesine[an]), + actor->z + 40 * FRACUNIT, actor, actor->target, + MT_ICEGUY_FX); + an = (actor->angle - ANG90) >> ANGLETOFINESHIFT; + P_SpawnMissileXYZ(actor->x + FixedMul(actor->radius >> 1, + finecosine[an]), + actor->y + FixedMul(actor->radius >> 1, finesine[an]), + actor->z + 40 * FRACUNIT, actor, actor->target, + MT_ICEGUY_FX); + S_StartSound(actor, actor->info->attacksound); +} + +//============================================================================ +// +// A_IceGuyMissilePuff +// +//============================================================================ + +void A_IceGuyMissilePuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMobj(actor->x, actor->y, actor->z + 2 * FRACUNIT, MT_ICEFX_PUFF); +} + +//============================================================================ +// +// A_IceGuyDie +// +//============================================================================ + +void A_IceGuyDie(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->momx = 0; + actor->momy = 0; + actor->momz = 0; + actor->height <<= 2; + A_FreezeDeathChunks(actor, player, psp); +} + +//============================================================================ +// +// A_IceGuyMissileExplode +// +//============================================================================ + +void A_IceGuyMissileExplode(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + unsigned int i; + + for (i = 0; i < 8; i++) + { + mo = P_SpawnMissileAngle(actor, MT_ICEGUY_FX2, i * ANG45, + -0.3 * FRACUNIT); + if (mo) + { + mo->target = actor->target; + } + } +} + + + + + + + + + +//============================================================================ +// +// Sorcerer stuff +// +// Sorcerer Variables +// special1 Angle of ball 1 (all others relative to that) +// special2 which ball to stop at in stop mode (MT_???) +// args[0] Denfense time +// args[1] Number of full rotations since stopping mode +// args[2] Target orbit speed for acceleration/deceleration +// args[3] Movement mode (see SORC_ macros) +// args[4] Current ball orbit speed +// Sorcerer Ball Variables +// special1 Previous angle of ball (for woosh) +// special2 Countdown of rapid fire (FX4) +// args[0] If set, don't play the bounce sound when bouncing +//============================================================================ + +#define SORCBALL_INITIAL_SPEED 7 +#define SORCBALL_TERMINAL_SPEED 25 +#define SORCBALL_SPEED_ROTATIONS 5 +#define SORC_DEFENSE_TIME 255 +#define SORC_DEFENSE_HEIGHT 45 +#define BOUNCE_TIME_UNIT (35/2) +#define SORCFX4_RAPIDFIRE_TIME (6*3) // 3 seconds +#define SORCFX4_SPREAD_ANGLE 20 + +#define SORC_DECELERATE 0 +#define SORC_ACCELERATE 1 +#define SORC_STOPPING 2 +#define SORC_FIRESPELL 3 +#define SORC_STOPPED 4 +#define SORC_NORMAL 5 +#define SORC_FIRING_SPELL 6 + +#define BALL1_ANGLEOFFSET 0 +#define BALL2_ANGLEOFFSET (ANG_MAX/3) +#define BALL3_ANGLEOFFSET ((ANG_MAX/3)*2) + + +// Spawn spinning balls above head - actor is sorcerer +void A_SorcSpinBalls(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + fixed_t z; + + A_SlowBalls(actor, player, psp); + actor->args[0] = 0; // Currently no defense + actor->args[3] = SORC_NORMAL; + actor->args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed + actor->special1.i = ANG1; + z = actor->z - actor->floorclip + actor->info->height; + + mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCBALL1); + if (mo) + { + mo->target = actor; + mo->special2.i = SORCFX4_RAPIDFIRE_TIME; + } + mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCBALL2); + if (mo) + mo->target = actor; + mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCBALL3); + if (mo) + mo->target = actor; +} + + +// +// A_SorcBallOrbit() ========================================== +// + +void A_SorcBallOrbit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int x, y; + angle_t angle, baseangle; + int mode = actor->target->args[3]; + mobj_t *parent = (mobj_t *) actor->target; + int dist = parent->radius - (actor->radius << 1); + angle_t prevangle = actor->special1.i; + + if (actor->target->health <= 0) + P_SetMobjState(actor, actor->info->painstate); + + baseangle = (angle_t) parent->special1.i; + switch (actor->type) + { + case MT_SORCBALL1: + angle = baseangle + BALL1_ANGLEOFFSET; + break; + case MT_SORCBALL2: + angle = baseangle + BALL2_ANGLEOFFSET; + break; + case MT_SORCBALL3: + angle = baseangle + BALL3_ANGLEOFFSET; + break; + default: + I_Error("corrupted sorcerer"); + return; + } + actor->angle = angle; + angle >>= ANGLETOFINESHIFT; + + switch (mode) + { + case SORC_NORMAL: // Balls rotating normally + A_SorcUpdateBallAngle(actor, player, psp); + break; + case SORC_DECELERATE: // Balls decelerating + A_DecelBalls(actor, player, psp); + A_SorcUpdateBallAngle(actor, player, psp); + break; + case SORC_ACCELERATE: // Balls accelerating + A_AccelBalls(actor, player, psp); + A_SorcUpdateBallAngle(actor, player, psp); + break; + case SORC_STOPPING: // Balls stopping + if ((parent->special2.i == actor->type) && + (parent->args[1] > SORCBALL_SPEED_ROTATIONS) && + (abs((int) angle - (int) (parent->angle >> ANGLETOFINESHIFT)) < + (30 << 5))) + { + // Can stop now + actor->target->args[3] = SORC_FIRESPELL; + actor->target->args[4] = 0; + // Set angle so ball angle == sorcerer angle + switch (actor->type) + { + case MT_SORCBALL1: + parent->special1.i = (int) (parent->angle - + BALL1_ANGLEOFFSET); + break; + case MT_SORCBALL2: + parent->special1.i = (int) (parent->angle - + BALL2_ANGLEOFFSET); + break; + case MT_SORCBALL3: + parent->special1.i = (int) (parent->angle - + BALL3_ANGLEOFFSET); + break; + default: + break; + } + } + else + { + A_SorcUpdateBallAngle(actor, player, psp); + } + break; + case SORC_FIRESPELL: // Casting spell + if (parent->special2.i == actor->type) + { + // Put sorcerer into special throw spell anim + if (parent->health > 0) + P_SetMobjStateNF(parent, S_SORC_ATTACK1); + + if (actor->type == MT_SORCBALL1 && P_Random() < 200) + { + S_StartSound(NULL, SFX_SORCERER_SPELLCAST); + actor->special2.i = SORCFX4_RAPIDFIRE_TIME; + actor->args[4] = 128; + parent->args[3] = SORC_FIRING_SPELL; + } + else + { + A_CastSorcererSpell(actor, player, psp); + parent->args[3] = SORC_STOPPED; + } + } + break; + case SORC_FIRING_SPELL: + if (parent->special2.i == actor->type) + { + if (actor->special2.i-- <= 0) + { + // Done rapid firing + parent->args[3] = SORC_STOPPED; + // Back to orbit balls + if (parent->health > 0) + P_SetMobjStateNF(parent, S_SORC_ATTACK4); + } + else + { + // Do rapid fire spell + A_SorcOffense2(actor, player, psp); + } + } + break; + case SORC_STOPPED: // Balls stopped + default: + break; + } + + if ((angle < prevangle) && (parent->args[4] == SORCBALL_TERMINAL_SPEED)) + { + parent->args[1]++; // Bump rotation counter + // Completed full rotation - make woosh sound + S_StartSound(actor, SFX_SORCERER_BALLWOOSH); + } + actor->special1.i = angle; // Set previous angle + x = parent->x + FixedMul(dist, finecosine[angle]); + y = parent->y + FixedMul(dist, finesine[angle]); + actor->x = x; + actor->y = y; + actor->z = parent->z - parent->floorclip + parent->info->height; +} + + +// +// Set balls to speed mode - actor is sorcerer +// +void A_SpeedBalls(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->args[3] = SORC_ACCELERATE; // speed mode + actor->args[2] = SORCBALL_TERMINAL_SPEED; // target speed +} + + +// +// Set balls to slow mode - actor is sorcerer +// +void A_SlowBalls(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->args[3] = SORC_DECELERATE; // slow mode + actor->args[2] = SORCBALL_INITIAL_SPEED; // target speed +} + + +// +// Instant stop when rotation gets to ball in special2 +// actor is sorcerer +// +void A_StopBalls(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int chance = P_Random(); + actor->args[3] = SORC_STOPPING; // stopping mode + actor->args[1] = 0; // Reset rotation counter + + if ((actor->args[0] <= 0) && (chance < 200)) + { + actor->special2.i = MT_SORCBALL2; // Blue + } + else if ((actor->health < (actor->info->spawnhealth >> 1)) && + (chance < 200)) + { + actor->special2.i = MT_SORCBALL3; // Green + } + else + { + actor->special2.i = MT_SORCBALL1; // Yellow + } + + +} + + +// +// Increase ball orbit speed - actor is ball +// +void A_AccelBalls(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *sorc = actor->target; + + if (sorc->args[4] < sorc->args[2]) + { + sorc->args[4]++; + } + else + { + sorc->args[3] = SORC_NORMAL; + if (sorc->args[4] >= SORCBALL_TERMINAL_SPEED) + { + // Reached terminal velocity - stop balls + A_StopBalls(sorc, player, psp); + } + } +} + + +// Decrease ball orbit speed - actor is ball +void A_DecelBalls(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *sorc = actor->target; + + if (sorc->args[4] > sorc->args[2]) + { + sorc->args[4]--; + } + else + { + sorc->args[3] = SORC_NORMAL; + } +} + + +// Update angle if first ball - actor is ball +void A_SorcUpdateBallAngle(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->type == MT_SORCBALL1) + { + actor->target->special1.i += ANG1 * actor->target->args[4]; + } +} + + +// actor is ball +void A_CastSorcererSpell(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int spell = actor->type; + angle_t ang1, ang2; + fixed_t z; + mobj_t *parent = actor->target; + + S_StartSound(NULL, SFX_SORCERER_SPELLCAST); + + // Put sorcerer into throw spell animation + if (parent->health > 0) + P_SetMobjStateNF(parent, S_SORC_ATTACK4); + + switch (spell) + { + case MT_SORCBALL1: // Offensive + A_SorcOffense1(actor, player, psp); + break; + case MT_SORCBALL2: // Defensive + z = parent->z - parent->floorclip + + SORC_DEFENSE_HEIGHT * FRACUNIT; + mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCFX2); + parent->flags2 |= MF2_REFLECTIVE | MF2_INVULNERABLE; + parent->args[0] = SORC_DEFENSE_TIME; + if (mo) + mo->target = parent; + break; + case MT_SORCBALL3: // Reinforcements + ang1 = actor->angle - ANG45; + ang2 = actor->angle + ANG45; + if (actor->health < (actor->info->spawnhealth / 3)) + { // Spawn 2 at a time + mo = P_SpawnMissileAngle(parent, MT_SORCFX3, ang1, + 4 * FRACUNIT); + if (mo) + mo->target = parent; + mo = P_SpawnMissileAngle(parent, MT_SORCFX3, ang2, + 4 * FRACUNIT); + if (mo) + mo->target = parent; + } + else + { + if (P_Random() < 128) + ang1 = ang2; + mo = P_SpawnMissileAngle(parent, MT_SORCFX3, ang1, + 4 * FRACUNIT); + if (mo) + mo->target = parent; + } + break; + default: + break; + } +} + +/* +void A_SpawnReinforcements(mobj_t *actor) +{ + mobj_t *parent = actor->target; + mobj_t *mo; + angle_t ang; + + ang = ANG1 * P_Random(); + mo = P_SpawnMissileAngle(actor, MT_SORCFX3, ang, 5*FRACUNIT); + if (mo) mo->target = parent; +} +*/ + +// actor is ball +void A_SorcOffense1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + angle_t ang1, ang2; + mobj_t *parent = (mobj_t *) actor->target; + + ang1 = actor->angle + ANG1 * 70; + ang2 = actor->angle - ANG1 * 70; + mo = P_SpawnMissileAngle(parent, MT_SORCFX1, ang1, 0); + if (mo) + { + mo->target = parent; + mo->special1.m = parent->target; + mo->args[4] = BOUNCE_TIME_UNIT; + mo->args[3] = 15; // Bounce time in seconds + } + mo = P_SpawnMissileAngle(parent, MT_SORCFX1, ang2, 0); + if (mo) + { + mo->target = parent; + mo->special1.m = parent->target; + mo->args[4] = BOUNCE_TIME_UNIT; + mo->args[3] = 15; // Bounce time in seconds + } +} + + +// Actor is ball +void A_SorcOffense2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t ang1; + mobj_t *mo; + int delta, index; + mobj_t *parent = actor->target; + mobj_t *dest = parent->target; + int dist; + + index = actor->args[4] << 5; + actor->args[4] += 15; + delta = (finesine[index]) * SORCFX4_SPREAD_ANGLE; + delta = (delta >> FRACBITS) * ANG1; + ang1 = actor->angle + delta; + mo = P_SpawnMissileAngle(parent, MT_SORCFX4, ang1, 0); + if (mo) + { + mo->special2.i = 35 * 5 / 2; // 5 seconds + dist = P_AproxDistance(dest->x - mo->x, dest->y - mo->y); + dist = dist / mo->info->speed; + if (dist < 1) + dist = 1; + mo->momz = (dest->z - mo->z) / dist; + } +} + + +// Resume ball spinning +void A_SorcBossAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->args[3] = SORC_ACCELERATE; + actor->args[2] = SORCBALL_INITIAL_SPEED; +} + + +// spell cast magic fizzle +void A_SpawnFizzle(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t x, y, z; + fixed_t dist = 5 * FRACUNIT; + angle_t angle = actor->angle >> ANGLETOFINESHIFT; + fixed_t speed = actor->info->speed; + angle_t rangle; + mobj_t *mo; + int ix; + + x = actor->x + FixedMul(dist, finecosine[angle]); + y = actor->y + FixedMul(dist, finesine[angle]); + z = actor->z - actor->floorclip + (actor->height >> 1); + for (ix = 0; ix < 5; ix++) + { + mo = P_SpawnMobj(x, y, z, MT_SORCSPARK1); + if (mo) + { + rangle = angle + ((P_Random() % 5) << 1); + mo->momx = FixedMul(P_Random() % speed, finecosine[rangle]); + mo->momy = FixedMul(P_Random() % speed, finesine[rangle]); + mo->momz = FRACUNIT * 2; + } + } +} + + +//============================================================================ +// Yellow spell - offense +//============================================================================ + +void A_SorcFX1Seek(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_BounceCheck(actor, player, psp); + P_SeekerMissile(actor, ANG1 * 2, ANG1 * 6); +} + + +//============================================================================ +// Blue spell - defense +//============================================================================ +// +// FX2 Variables +// special1 current angle +// special2 +// args[0] 0 = CW, 1 = CCW +// args[1] +//============================================================================ + +// Split ball in two +void A_SorcFX2Split(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCFX2); + if (mo) + { + mo->target = actor->target; + mo->args[0] = 0; // CW + mo->special1.i = actor->angle; // Set angle + P_SetMobjStateNF(mo, S_SORCFX2_ORBIT1); + } + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCFX2); + if (mo) + { + mo->target = actor->target; + mo->args[0] = 1; // CCW + mo->special1.i = actor->angle; // Set angle + P_SetMobjStateNF(mo, S_SORCFX2_ORBIT1); + } + P_SetMobjStateNF(actor, S_NULL); +} + + +// Orbit FX2 about sorcerer +void A_SorcFX2Orbit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + fixed_t x, y, z; + mobj_t *parent = actor->target; + fixed_t dist = parent->info->radius; + + if ((parent->health <= 0) || // Sorcerer is dead + (!parent->args[0])) // Time expired + { + P_SetMobjStateNF(actor, actor->info->deathstate); + parent->args[0] = 0; + parent->flags2 &= ~MF2_REFLECTIVE; + parent->flags2 &= ~MF2_INVULNERABLE; + } + + if (actor->args[0] && (parent->args[0]-- <= 0)) // Time expired + { + P_SetMobjStateNF(actor, actor->info->deathstate); + parent->args[0] = 0; + parent->flags2 &= ~MF2_REFLECTIVE; + } + + // Move to new position based on angle + if (actor->args[0]) // Counter clock-wise + { + actor->special1.i += ANG1 * 10; + angle = ((angle_t) actor->special1.i) >> ANGLETOFINESHIFT; + x = parent->x + FixedMul(dist, finecosine[angle]); + y = parent->y + FixedMul(dist, finesine[angle]); + z = parent->z - parent->floorclip + SORC_DEFENSE_HEIGHT * FRACUNIT; + z += FixedMul(15 * FRACUNIT, finecosine[angle]); + // Spawn trailer + P_SpawnMobj(x, y, z, MT_SORCFX2_T1); + } + else // Clock wise + { + actor->special1.i -= ANG1 * 10; + angle = ((angle_t) actor->special1.i) >> ANGLETOFINESHIFT; + x = parent->x + FixedMul(dist, finecosine[angle]); + y = parent->y + FixedMul(dist, finesine[angle]); + z = parent->z - parent->floorclip + SORC_DEFENSE_HEIGHT * FRACUNIT; + z += FixedMul(20 * FRACUNIT, finesine[angle]); + // Spawn trailer + P_SpawnMobj(x, y, z, MT_SORCFX2_T1); + } + + actor->x = x; + actor->y = y; + actor->z = z; +} + + + +//============================================================================ +// Green spell - spawn bishops +//============================================================================ + +void A_SpawnBishop(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BISHOP); + if (mo) + { + if (!P_TestMobjLocation(mo)) + { + P_SetMobjState(mo, S_NULL); + } + } + P_SetMobjState(actor, S_NULL); +} + +/* +void A_SmokePuffEntry(mobj_t *actor) +{ + P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE); +} +*/ + +void A_SmokePuffExit(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKEEXIT); +} + +void A_SorcererBishopEntry(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCFX3_EXPLOSION); + S_StartSound(actor, actor->info->seesound); +} + + +//============================================================================ +// FX4 - rapid fire balls +//============================================================================ + +void A_SorcFX4Check(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special2.i-- <= 0) + { + P_SetMobjStateNF(actor, actor->info->deathstate); + } +} + +//============================================================================ +// Ball death - spawn stuff +//============================================================================ + +void A_SorcBallPop(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, SFX_SORCERER_BALLPOP); + actor->flags &= ~MF_NOGRAVITY; + actor->flags2 |= MF2_LOGRAV; + actor->momx = ((P_Random() % 10) - 5) << FRACBITS; + actor->momy = ((P_Random() % 10) - 5) << FRACBITS; + actor->momz = (2 + (P_Random() % 3)) << FRACBITS; + actor->special2.i = 4 * FRACUNIT; // Initial bounce factor + actor->args[4] = BOUNCE_TIME_UNIT; // Bounce time unit + actor->args[3] = 5; // Bounce time in seconds +} + + + +void A_BounceCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->args[4]-- <= 0) + { + if (actor->args[3]-- <= 0) + { + P_SetMobjState(actor, actor->info->deathstate); + switch (actor->type) + { + case MT_SORCBALL1: + case MT_SORCBALL2: + case MT_SORCBALL3: + S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE); + break; + case MT_SORCFX1: + S_StartSound(NULL, SFX_SORCERER_HEADSCREAM); + break; + default: + break; + } + } + else + { + actor->args[4] = BOUNCE_TIME_UNIT; + } + } +} + + + + +//============================================================================ +// Class Bosses +//============================================================================ +#define CLASS_BOSS_STRAFE_RANGE 64*10*FRACUNIT + +void A_FastChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int delta; + fixed_t dist; + angle_t ang; + mobj_t *target; + + if (actor->reactiontime) + { + actor->reactiontime--; + } + + // Modify target threshold + if (actor->threshold) + { + actor->threshold--; + } + + if (gameskill == sk_nightmare) + { // Monsters move faster in nightmare mode + actor->tics -= actor->tics / 2; + if (actor->tics < 3) + { + actor->tics = 3; + } + } + +// +// turn towards movement direction if not there yet +// + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + if (delta > 0) + { + actor->angle -= ANG90 / 2; + } + else if (delta < 0) + { + actor->angle += ANG90 / 2; + } + } + + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { // look for a new target + if (P_LookForPlayers(actor, true)) + { // got a new target + return; + } + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + +// +// don't attack twice in a row +// + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare) + P_NewChaseDir(actor); + return; + } + + // Strafe + if (actor->special2.i > 0) + { + actor->special2.i--; + } + else + { + target = actor->target; + actor->special2.i = 0; + actor->momx = actor->momy = 0; + dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); + if (dist < CLASS_BOSS_STRAFE_RANGE) + { + if (P_Random() < 100) + { + ang = R_PointToAngle2(actor->x, actor->y, + target->x, target->y); + if (P_Random() < 128) + ang += ANG90; + else + ang -= ANG90; + ang >>= ANGLETOFINESHIFT; + actor->momx = FixedMul(13 * FRACUNIT, finecosine[ang]); + actor->momy = FixedMul(13 * FRACUNIT, finesine[ang]); + actor->special2.i = 3; // strafe time + } + } + } + +// +// check for missile attack +// + if (actor->info->missilestate) + { + if (gameskill < sk_nightmare && actor->movecount) + goto nomissile; + if (!P_CheckMissileRange(actor)) + goto nomissile; + P_SetMobjState(actor, actor->info->missilestate); + actor->flags |= MF_JUSTATTACKED; + return; + } + nomissile: + +// +// possibly choose another target +// + if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) + { + if (P_LookForPlayers(actor, true)) + return; // got a new target + } + +// +// chase towards player +// + if (!actor->special2.i) + { + if (--actor->movecount < 0 || !P_Move(actor)) + { + P_NewChaseDir(actor); + } + } +} + + +void A_FighterAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + return; + A_FSwordAttack2(actor, player, psp); +} + + +void A_ClericAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + return; + A_CHolyAttack3(actor, player, psp); +} + + + +void A_MageAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!actor->target) + return; + A_MStaffAttack2(actor, player, psp); +} + +void A_ClassBossHealth(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (netgame && !deathmatch) // co-op only + { + if (!actor->special1.i) + { + actor->health *= 5; + actor->special1.i = true; // has been initialized + } + } +} + + +//=========================================================================== +// +// A_CheckFloor - Checks if an object hit the floor +// +//=========================================================================== + +void A_CheckFloor(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->z <= actor->floorz) + { + actor->z = actor->floorz; + actor->flags2 &= ~MF2_LOGRAV; + P_SetMobjState(actor, actor->info->deathstate); + } +} + +//============================================================================ +// +// A_FreezeDeath +// +//============================================================================ + +void A_FreezeDeath(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int r = P_Random(); + actor->tics = 75 + r + P_Random(); + actor->flags |= MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD; + actor->flags2 |= MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ | MF2_SLIDE; + actor->height <<= 2; + S_StartSound(actor, SFX_FREEZE_DEATH); + + if (actor->player) + { + actor->player->damagecount = 0; + actor->player->poisoncount = 0; + actor->player->bonuscount = 0; + if (actor->player == &players[consoleplayer]) + { + SB_PaletteFlash(false); + } + } + else if (actor->flags & MF_COUNTKILL && actor->special) + { + // Initiate monster death actions. + P_ExecuteLineSpecial(actor->special, actor->args, NULL, 0, actor); + } +} + +//============================================================================ +// +// A_IceSetTics +// +//============================================================================ + +void A_IceSetTics(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int floor; + + actor->tics = 70 + (P_Random() & 63); + floor = P_GetThingFloorType(actor); + if (floor == FLOOR_LAVA) + { + actor->tics >>= 2; + } + else if (floor == FLOOR_ICE) + { + actor->tics <<= 1; + } +} + +//============================================================================ +// +// A_IceCheckHeadDone +// +//============================================================================ + +void A_IceCheckHeadDone(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->special2.i == 666) + { + P_SetMobjState(actor, S_ICECHUNK_HEAD2); + } +} + +//============================================================================ +// +// A_FreezeDeathChunks +// +//============================================================================ + +void A_FreezeDeathChunks(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + int r1,r2,r3; + mobj_t *mo; + + if (actor->momx || actor->momy || actor->momz) + { + actor->tics = 105; + return; + } + S_StartSound(actor, SFX_FREEZE_SHATTER); + + for (i = 12 + (P_Random() & 15); i >= 0; i--) + { + r1 = P_Random(); + r2 = P_Random(); + r3 = P_Random(); + mo = P_SpawnMobj(actor->x + + (((r3 - 128) * actor->radius) >> 7), + actor->y + + (((r2 - 128) * actor->radius) >> 7), + actor->z + (r1 * actor->height / 255), + MT_ICECHUNK); + P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3)); + mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2; + mo->momx = P_SubRandom() << (FRACBITS - 7); + mo->momy = P_SubRandom() << (FRACBITS - 7); + A_IceSetTics(mo, NULL, NULL); // set a random tic wait + } + for (i = 12 + (P_Random() & 15); i >= 0; i--) + { + r1 = P_Random(); + r2 = P_Random(); + r3 = P_Random(); + mo = P_SpawnMobj(actor->x + + (((r3 - 128) * actor->radius) >> 7), + actor->y + + (((r2 - 128) * actor->radius) >> 7), + actor->z + (r1 * actor->height / 255), + MT_ICECHUNK); + P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3)); + mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2; + mo->momx = P_SubRandom() << (FRACBITS - 7); + mo->momy = P_SubRandom() << (FRACBITS - 7); + A_IceSetTics(mo, NULL, NULL); // set a random tic wait + } + if (actor->player) + { // attach the player's view to a chunk of ice + mo = P_SpawnMobj(actor->x, actor->y, actor->z + VIEWHEIGHT, + MT_ICECHUNK); + P_SetMobjState(mo, S_ICECHUNK_HEAD); + mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2; + mo->momx = P_SubRandom() << (FRACBITS - 7); + mo->momy = P_SubRandom() << (FRACBITS - 7); + mo->flags2 |= MF2_ICEDAMAGE; // used to force blue palette + mo->flags2 &= ~MF2_FLOORCLIP; + mo->player = actor->player; + actor->player = NULL; + mo->health = actor->health; + mo->angle = actor->angle; + mo->player->mo = mo; + mo->player->lookdir = 0; + } + P_RemoveMobjFromTIDList(actor); + P_SetMobjState(actor, S_FREETARGMOBJ); + actor->flags2 |= MF2_DONTDRAW; +} + +//=========================================================================== +// Korax Variables +// special1 last teleport destination +// special2 set if "below half" script not yet run +// +// Korax Scripts (reserved) +// 249 Tell scripts that we are below half health +// 250-254 Control scripts +// 255 Death script +// +// Korax TIDs (reserved) +// 245 Reserved for Korax himself +// 248 Initial teleport destination +// 249 Teleport destination +// 250-254 For use in respective control scripts +// 255 For use in death script (spawn spots) +//=========================================================================== +#define KORAX_SPIRIT_LIFETIME (5*(35/5)) // 5 seconds +#define KORAX_COMMAND_HEIGHT (120*FRACUNIT) +#define KORAX_COMMAND_OFFSET (27*FRACUNIT) + +void KoraxFire1(mobj_t * actor, int type); +void KoraxFire2(mobj_t * actor, int type); +void KoraxFire3(mobj_t * actor, int type); +void KoraxFire4(mobj_t * actor, int type); +void KoraxFire5(mobj_t * actor, int type); +void KoraxFire6(mobj_t * actor, int type); +void KSpiritInit(mobj_t * spirit, mobj_t * korax); + +#define KORAX_TID (245) +#define KORAX_FIRST_TELEPORT_TID (248) +#define KORAX_TELEPORT_TID (249) + +void A_KoraxChase(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *spot; + int lastfound; + byte args[3] = {0, 0, 0}; + + if ((!actor->special2.i) && + (actor->health <= (actor->info->spawnhealth / 2))) + { + lastfound = 0; + spot = P_FindMobjFromTID(KORAX_FIRST_TELEPORT_TID, &lastfound); + if (spot) + { + P_Teleport(actor, spot->x, spot->y, spot->angle, true); + } + + CheckACSPresent(249); + P_StartACS(249, 0, args, actor, NULL, 0); + actor->special2.i = 1; // Don't run again + + return; + } + + if (!actor->target) + return; + if (P_Random() < 30) + { + P_SetMobjState(actor, actor->info->missilestate); + } + else if (P_Random() < 30) + { + S_StartSound(NULL, SFX_KORAX_ACTIVE); + } + + // Teleport away + if (actor->health < (actor->info->spawnhealth >> 1)) + { + if (P_Random() < 10) + { + lastfound = actor->special1.i; + spot = P_FindMobjFromTID(KORAX_TELEPORT_TID, &lastfound); + actor->special1.i = lastfound; + if (spot) + { + P_Teleport(actor, spot->x, spot->y, spot->angle, true); + } + } + } +} + +void A_KoraxStep(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_Chase(actor, player, psp); +} + +void A_KoraxStep2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + S_StartSound(NULL, SFX_KORAX_STEP); + A_Chase(actor, player, psp); +} + +void A_KoraxBonePop(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + byte args[5]; + + args[0] = args[1] = args[2] = args[3] = args[4] = 0; + + // Spawn 6 spirits equalangularly + mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT1, ANG60 * 0, + 5 * FRACUNIT); + if (mo) + KSpiritInit(mo, actor); + mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT2, ANG60 * 1, + 5 * FRACUNIT); + if (mo) + KSpiritInit(mo, actor); + mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT3, ANG60 * 2, + 5 * FRACUNIT); + if (mo) + KSpiritInit(mo, actor); + mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT4, ANG60 * 3, + 5 * FRACUNIT); + if (mo) + KSpiritInit(mo, actor); + mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT5, ANG60 * 4, + 5 * FRACUNIT); + if (mo) + KSpiritInit(mo, actor); + mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT6, ANG60 * 5, + 5 * FRACUNIT); + if (mo) + KSpiritInit(mo, actor); + + CheckACSPresent(255); + P_StartACS(255, 0, args, actor, NULL, 0); // Death script +} + +void KSpiritInit(mobj_t * spirit, mobj_t * korax) +{ + int i; + mobj_t *tail, *next; + + spirit->health = KORAX_SPIRIT_LIFETIME; + + spirit->special1.m = korax; // Swarm around korax + spirit->special2.i = 32 + (P_Random() & 7); // Float bob index + spirit->args[0] = 10; // initial turn value + spirit->args[1] = 0; // initial look angle + + // Spawn a tail for spirit + tail = P_SpawnMobj(spirit->x, spirit->y, spirit->z, MT_HOLY_TAIL); + tail->special2.m = spirit; // parent + for (i = 1; i < 3; i++) + { + next = P_SpawnMobj(spirit->x, spirit->y, spirit->z, MT_HOLY_TAIL); + P_SetMobjState(next, next->info->spawnstate + 1); + tail->special1.m = next; + tail = next; + } + tail->special1.m = NULL; // last tail bit +} + +void A_KoraxDecide(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (P_Random() < 220) + { + P_SetMobjState(actor, S_KORAX_MISSILE1); + } + else + { + P_SetMobjState(actor, S_KORAX_COMMAND1); + } +} + +void A_KoraxMissile(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int type = P_Random() % 6; + int sound = 0; + + S_StartSound(actor, SFX_KORAX_ATTACK); + + switch (type) + { + case 0: + type = MT_WRAITHFX1; + sound = SFX_WRAITH_MISSILE_FIRE; + break; + case 1: + type = MT_DEMONFX1; + sound = SFX_DEMON_MISSILE_FIRE; + break; + case 2: + type = MT_DEMON2FX1; + sound = SFX_DEMON_MISSILE_FIRE; + break; + case 3: + type = MT_FIREDEMON_FX6; + sound = SFX_FIRED_ATTACK; + break; + case 4: + type = MT_CENTAUR_FX; + sound = SFX_CENTAURLEADER_ATTACK; + break; + case 5: + type = MT_SERPENTFX; + sound = SFX_CENTAURLEADER_ATTACK; + break; + } + + // Fire all 6 missiles at once + S_StartSound(NULL, sound); + KoraxFire1(actor, type); + KoraxFire2(actor, type); + KoraxFire3(actor, type); + KoraxFire4(actor, type); + KoraxFire5(actor, type); + KoraxFire6(actor, type); +} + + +// Call action code scripts (250-254) +void A_KoraxCommand(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + byte args[5]; + fixed_t x, y, z; + angle_t ang; + int numcommands; + + S_StartSound(actor, SFX_KORAX_COMMAND); + + // Shoot stream of lightning to ceiling + ang = (actor->angle - ANG90) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_COMMAND_OFFSET, finecosine[ang]); + y = actor->y + FixedMul(KORAX_COMMAND_OFFSET, finesine[ang]); + z = actor->z + KORAX_COMMAND_HEIGHT; + P_SpawnMobj(x, y, z, MT_KORAX_BOLT); + + args[0] = args[1] = args[2] = args[3] = args[4] = 0; + + if (actor->health <= (actor->info->spawnhealth >> 1)) + { + numcommands = 5; + } + else + { + numcommands = 4; + } + + switch (P_Random() % numcommands) + { + case 0: + CheckACSPresent(250); + P_StartACS(250, 0, args, actor, NULL, 0); + break; + case 1: + CheckACSPresent(251); + P_StartACS(251, 0, args, actor, NULL, 0); + break; + case 2: + CheckACSPresent(252); + P_StartACS(252, 0, args, actor, NULL, 0); + break; + case 3: + CheckACSPresent(253); + P_StartACS(253, 0, args, actor, NULL, 0); + break; + case 4: + CheckACSPresent(254); + P_StartACS(254, 0, args, actor, NULL, 0); + break; + } +} + + +#define KORAX_DELTAANGLE (85*ANG1) +#define KORAX_ARM_EXTENSION_SHORT (40*FRACUNIT) +#define KORAX_ARM_EXTENSION_LONG (55*FRACUNIT) + +#define KORAX_ARM1_HEIGHT (108*FRACUNIT) +#define KORAX_ARM2_HEIGHT (82*FRACUNIT) +#define KORAX_ARM3_HEIGHT (54*FRACUNIT) +#define KORAX_ARM4_HEIGHT (104*FRACUNIT) +#define KORAX_ARM5_HEIGHT (86*FRACUNIT) +#define KORAX_ARM6_HEIGHT (53*FRACUNIT) + + +// Arm projectiles +// arm positions numbered: +// 1 top left +// 2 middle left +// 3 lower left +// 4 top right +// 5 middle right +// 6 lower right + + +// Arm 1 projectile +void KoraxFire1(mobj_t * actor, int type) +{ + angle_t ang; + fixed_t x, y, z; + + ang = (actor->angle - KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_ARM_EXTENSION_SHORT, finecosine[ang]); + y = actor->y + FixedMul(KORAX_ARM_EXTENSION_SHORT, finesine[ang]); + z = actor->z - actor->floorclip + KORAX_ARM1_HEIGHT; + P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); +} + + +// Arm 2 projectile +void KoraxFire2(mobj_t * actor, int type) +{ + angle_t ang; + fixed_t x, y, z; + + ang = (actor->angle - KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); + y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); + z = actor->z - actor->floorclip + KORAX_ARM2_HEIGHT; + P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); +} + +// Arm 3 projectile +void KoraxFire3(mobj_t * actor, int type) +{ + angle_t ang; + fixed_t x, y, z; + + ang = (actor->angle - KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); + y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); + z = actor->z - actor->floorclip + KORAX_ARM3_HEIGHT; + P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); +} + +// Arm 4 projectile +void KoraxFire4(mobj_t * actor, int type) +{ + angle_t ang; + fixed_t x, y, z; + + ang = (actor->angle + KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_ARM_EXTENSION_SHORT, finecosine[ang]); + y = actor->y + FixedMul(KORAX_ARM_EXTENSION_SHORT, finesine[ang]); + z = actor->z - actor->floorclip + KORAX_ARM4_HEIGHT; + P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); +} + +// Arm 5 projectile +void KoraxFire5(mobj_t * actor, int type) +{ + angle_t ang; + fixed_t x, y, z; + + ang = (actor->angle + KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); + y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); + z = actor->z - actor->floorclip + KORAX_ARM5_HEIGHT; + P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); +} + +// Arm 6 projectile +void KoraxFire6(mobj_t * actor, int type) +{ + angle_t ang; + fixed_t x, y, z; + + ang = (actor->angle + KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; + x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); + y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); + z = actor->z - actor->floorclip + KORAX_ARM6_HEIGHT; + P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); +} + + +void A_KSpiritWeave(mobj_t *actor) +{ + fixed_t newX, newY; + int weaveXY, weaveZ; + int angle; + + weaveXY = actor->special2.i >> 16; + weaveZ = actor->special2.i & 0xFFFF; + angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + newX = actor->x - FixedMul(finecosine[angle], + FloatBobOffsets[weaveXY] << 2); + newY = actor->y - FixedMul(finesine[angle], + FloatBobOffsets[weaveXY] << 2); + weaveXY = (weaveXY + (P_Random() % 5)) & 63; + newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 2); + newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 2); + P_TryMove(actor, newX, newY); + actor->z -= FloatBobOffsets[weaveZ] << 1; + weaveZ = (weaveZ + (P_Random() % 5)) & 63; + actor->z += FloatBobOffsets[weaveZ] << 1; + actor->special2.i = weaveZ + (weaveXY << 16); +} + +void A_KSpiritSeeker(mobj_t * actor, angle_t thresh, angle_t turnMax) +{ + int dir; + int dist; + angle_t delta; + angle_t angle; + mobj_t *target; + fixed_t newZ; + fixed_t deltaZ; + + target = actor->special1.m; + if (target == NULL) + { + return; + } + dir = P_FaceMobj(actor, target, &delta); + if (delta > thresh) + { + delta >>= 1; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (dir) + { // Turn clockwise + actor->angle += delta; + } + else + { // Turn counter clockwise + actor->angle -= delta; + } + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(actor->info->speed, finecosine[angle]); + actor->momy = FixedMul(actor->info->speed, finesine[angle]); + + if (!(leveltime & 15) + || actor->z > target->z + (target->info->height) + || actor->z + actor->height < target->z) + { + newZ = target->z + ((P_Random() * target->info->height) >> 8); + deltaZ = newZ - actor->z; + if (abs(deltaZ) > 15 * FRACUNIT) + { + if (deltaZ > 0) + { + deltaZ = 15 * FRACUNIT; + } + else + { + deltaZ = -15 * FRACUNIT; + } + } + dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); + dist = dist / actor->info->speed; + if (dist < 1) + { + dist = 1; + } + actor->momz = deltaZ / dist; + } + return; +} + + +void A_KSpiritRoam(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (actor->health-- <= 0) + { + S_StartSound(actor, SFX_SPIRIT_DIE); + P_SetMobjState(actor, S_KSPIRIT_DEATH1); + } + else + { + if (actor->special1.m) + { + A_KSpiritSeeker(actor, actor->args[0] * ANG1, + actor->args[0] * ANG1 * 2); + } + A_KSpiritWeave(actor); + if (P_Random() < 50) + { + S_StartSound(NULL, SFX_SPIRIT_ACTIVE); + } + } +} + +void A_KBolt(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + // Countdown lifetime + if (actor->special1.i-- <= 0) + { + P_SetMobjState(actor, S_NULL); + } +} + + +#define KORAX_BOLT_HEIGHT 48*FRACUNIT +#define KORAX_BOLT_LIFETIME 3 + +void A_KBoltRaise(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + fixed_t z; + + // Spawn a child upward + z = actor->z + KORAX_BOLT_HEIGHT; + + if ((z + KORAX_BOLT_HEIGHT) < actor->ceilingz) + { + mo = P_SpawnMobj(actor->x, actor->y, z, MT_KORAX_BOLT); + if (mo) + { + mo->special1.i = KORAX_BOLT_LIFETIME; + } + } + else + { + // Maybe cap it off here + } +} diff --git a/games/NXDoom/src/hexen/p_floor.c b/games/NXDoom/src/hexen/p_floor.c new file mode 100644 index 00000000000..370cb173fec --- /dev/null +++ b/games/NXDoom/src/hexen/p_floor.c @@ -0,0 +1,946 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "p_local.h" + + +//================================================================== +//================================================================== +// +// FLOORS +// +//================================================================== +//================================================================== + +//================================================================== +// +// Move a plane (floor or ceiling) and check for crushing +// +//================================================================== +result_e T_MovePlane(sector_t * sector, fixed_t speed, + fixed_t dest, int crush, int floorOrCeiling, + int direction) +{ + boolean flag; + fixed_t lastpos; + + switch (floorOrCeiling) + { + case 0: // FLOOR + switch (direction) + { + case -1: // DOWN + if (sector->floorheight - speed < dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + //return RES_CRUSHED; + } + return RES_PASTDEST; + } + else + { + lastpos = sector->floorheight; + sector->floorheight -= speed; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + return RES_CRUSHED; + } + } + break; + + case 1: // UP + if (sector->floorheight + speed > dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + //return RES_CRUSHED; + } + return RES_PASTDEST; + } + else // COULD GET CRUSHED + { + lastpos = sector->floorheight; + sector->floorheight += speed; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + //if (crush == true) + //{ + // return RES_CRUSHED; + //} + sector->floorheight = lastpos; + P_ChangeSector(sector, crush); + return RES_CRUSHED; + } + } + break; + } + break; + + case 1: // CEILING + switch (direction) + { + case -1: // DOWN + if (sector->ceilingheight - speed < dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + //return RES_CRUSHED; + } + return RES_PASTDEST; + } + else // COULD GET CRUSHED + { + lastpos = sector->ceilingheight; + sector->ceilingheight -= speed; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + //if (crush == true) + //{ + // return RES_CRUSHED; + //} + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + return RES_CRUSHED; + } + } + break; + + case 1: // UP + if (sector->ceilingheight + speed > dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector, crush); + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + //return RES_CRUSHED; + } + return RES_PASTDEST; + } + else + { + lastpos = sector->ceilingheight; + sector->ceilingheight += speed; + flag = P_ChangeSector(sector, crush); +#if 0 + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector, crush); + return RES_CRUSHED; + } +#endif + } + break; + } + break; + + } + return RES_OK; +} + +//================================================================== +// +// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) +// +//================================================================== +void T_MoveFloor(thinker_t *thinker) +{ + floormove_t *floor = (floormove_t *) thinker; + result_e res; + + if (floor->resetDelayCount) + { + floor->resetDelayCount--; + if (!floor->resetDelayCount) + { + floor->floordestheight = floor->resetHeight; + floor->direction = -floor->direction; + floor->resetDelay = 0; + floor->delayCount = 0; + floor->delayTotal = 0; + } + } + if (floor->delayCount) + { + floor->delayCount--; + if (!floor->delayCount && floor->textureChange) + { + floor->sector->floorpic += floor->textureChange; + } + return; + } + + res = T_MovePlane(floor->sector, floor->speed, + floor->floordestheight, floor->crush, 0, + floor->direction); + + if (floor->type == FLEV_RAISEBUILDSTEP) + { + if ((floor->direction == 1 && floor->sector->floorheight >= + floor->stairsDelayHeight) || (floor->direction == -1 && + floor->sector->floorheight <= + floor->stairsDelayHeight)) + { + floor->delayCount = floor->delayTotal; + floor->stairsDelayHeight += floor->stairsDelayHeightDelta; + } + } + if (res == RES_PASTDEST) + { + SN_StopSequence((mobj_t *) & floor->sector->soundorg); + if (floor->delayTotal) + { + floor->delayTotal = 0; + } + if (floor->resetDelay) + { +// floor->resetDelayCount = floor->resetDelay; +// floor->resetDelay = 0; + return; + } + floor->sector->specialdata = NULL; + /* + if (floor->direction == 1) + switch(floor->type) + { + case donutRaise: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + else if (floor->direction == -1) + switch(floor->type) + { + case lowerAndChange: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + */ + if (floor->textureChange) + { + floor->sector->floorpic -= floor->textureChange; + } + P_TagFinished(floor->sector->tag); + P_RemoveThinker(&floor->thinker); + } +} + +//================================================================== +// +// HANDLE FLOOR TYPES +// +//================================================================== +int EV_DoFloor(line_t * line, byte * args, floor_e floortype) +{ + int secnum; + int rtn; + sector_t *sec; + floormove_t *floor = NULL; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // + // new floor thinker + // + rtn = 1; + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + memset(floor, 0, sizeof(*floor)); + P_AddThinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = floortype; + floor->crush = 0; + floor->speed = args[1] * (FRACUNIT / 8); + if (floortype == FLEV_LOWERTIMES8INSTANT || + floortype == FLEV_RAISETIMES8INSTANT) + { + floor->speed = 2000 << FRACBITS; + } + switch (floortype) + { + case FLEV_LOWERFLOOR: + floor->direction = -1; + floor->sector = sec; + floor->floordestheight = P_FindHighestFloorSurrounding(sec); + break; + case FLEV_LOWERFLOORTOLOWEST: + floor->direction = -1; + floor->sector = sec; + floor->floordestheight = P_FindLowestFloorSurrounding(sec); + break; + case FLEV_LOWERFLOORBYVALUE: + floor->direction = -1; + floor->sector = sec; + floor->floordestheight = floor->sector->floorheight - + args[2] * FRACUNIT; + break; + case FLEV_LOWERTIMES8INSTANT: + case FLEV_LOWERBYVALUETIMES8: + floor->direction = -1; + floor->sector = sec; + floor->floordestheight = floor->sector->floorheight - + args[2] * FRACUNIT * 8; + break; + case FLEV_RAISEFLOORCRUSH: + floor->crush = args[2]; // arg[2] = crushing value + floor->direction = 1; + floor->sector = sec; + floor->floordestheight = sec->ceilingheight - 8 * FRACUNIT; + break; + case FLEV_RAISEFLOOR: + floor->direction = 1; + floor->sector = sec; + floor->floordestheight = P_FindLowestCeilingSurrounding(sec); + if (floor->floordestheight > sec->ceilingheight) + floor->floordestheight = sec->ceilingheight; + break; + case FLEV_RAISEFLOORTONEAREST: + floor->direction = 1; + floor->sector = sec; + floor->floordestheight = + P_FindNextHighestFloor(sec, sec->floorheight); + break; + case FLEV_RAISEFLOORBYVALUE: + floor->direction = 1; + floor->sector = sec; + floor->floordestheight = floor->sector->floorheight + + args[2] * FRACUNIT; + break; + case FLEV_RAISETIMES8INSTANT: + case FLEV_RAISEBYVALUETIMES8: + floor->direction = 1; + floor->sector = sec; + floor->floordestheight = floor->sector->floorheight + + args[2] * FRACUNIT * 8; + break; + case FLEV_MOVETOVALUETIMES8: + floor->sector = sec; + floor->floordestheight = args[2] * FRACUNIT * 8; + if (args[3]) + { + floor->floordestheight = -floor->floordestheight; + } + if (floor->floordestheight > floor->sector->floorheight) + { + floor->direction = 1; + } + else if (floor->floordestheight < floor->sector->floorheight) + { + floor->direction = -1; + } + else + { // already at lowest position + rtn = 0; + } + break; + default: + rtn = 0; + break; + } + } + if (rtn) + { + SN_StartSequence((mobj_t *) & floor->sector->soundorg, + SEQ_PLATFORM + floor->sector->seqType); + } + return rtn; +} + +//============================================================================ +// +// EV_DoFloorAndCeiling +// +//============================================================================ + +int EV_DoFloorAndCeiling(line_t * line, byte * args, boolean raise) +{ + boolean floor, ceiling; + int secnum; + sector_t *sec; + + if (raise) + { + floor = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE); + secnum = -1; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + sec->specialdata = NULL; + } + ceiling = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE); + } + else + { + floor = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE); + secnum = -1; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + sec->specialdata = NULL; + } + ceiling = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE); + } + return (floor | ceiling); +} + +// ===== Build Stairs Private Data ===== + +#define STAIR_SECTOR_TYPE 26 +#define STAIR_QUEUE_SIZE 32 + +struct +{ + sector_t *sector; + int type; + int height; +} StairQueue[STAIR_QUEUE_SIZE]; + +static int QueueHead; +static int QueueTail; + +static int StepDelta; +static int Direction; +static int Speed; +static int Texture; +static int StartDelay; +static int StartDelayDelta; +static int TextureChange; +static int StartHeight; + +//========================================================================== +// +// QueueStairSector +// +//========================================================================== + +static void QueueStairSector(sector_t * sec, int type, int height) +{ + if ((QueueTail + 1) % STAIR_QUEUE_SIZE == QueueHead) + { + I_Error("BuildStairs: Too many branches located.\n"); + } + StairQueue[QueueTail].sector = sec; + StairQueue[QueueTail].type = type; + StairQueue[QueueTail].height = height; + + QueueTail = (QueueTail + 1) % STAIR_QUEUE_SIZE; +} + +//========================================================================== +// +// DequeueStairSector +// +//========================================================================== + +static sector_t *DequeueStairSector(int *type, int *height) +{ + sector_t *sec; + + if (QueueHead == QueueTail) + { // queue is empty + return NULL; + } + *type = StairQueue[QueueHead].type; + *height = StairQueue[QueueHead].height; + sec = StairQueue[QueueHead].sector; + QueueHead = (QueueHead + 1) % STAIR_QUEUE_SIZE; + + return sec; +} + +//========================================================================== +// +// ProcessStairSector +// +//========================================================================== + +static void ProcessStairSector(sector_t * sec, int type, int height, + stairs_e stairsType, int delay, int resetDelay) +{ + int i; + sector_t *tsec; + floormove_t *floor; + + // + // new floor thinker + // + height += StepDelta; + floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); + memset(floor, 0, sizeof(*floor)); + P_AddThinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = FLEV_RAISEBUILDSTEP; + floor->direction = Direction; + floor->sector = sec; + floor->floordestheight = height; + switch (stairsType) + { + case STAIRS_NORMAL: + floor->speed = Speed; + if (delay) + { + floor->delayTotal = delay; + floor->stairsDelayHeight = sec->floorheight + StepDelta; + floor->stairsDelayHeightDelta = StepDelta; + } + floor->resetDelay = resetDelay; + floor->resetDelayCount = resetDelay; + floor->resetHeight = sec->floorheight; + break; + case STAIRS_SYNC: + floor->speed = FixedMul(Speed, FixedDiv(height - StartHeight, + StepDelta)); + floor->resetDelay = delay; //arg4 + floor->resetDelayCount = delay; + floor->resetHeight = sec->floorheight; + break; +/* + case STAIRS_PHASED: + floor->floordestheight = sec->floorheight+StepDelta; + floor->speed = Speed; + floor->delayCount = StartDelay; + StartDelay += StartDelayDelta; + floor->textureChange = TextureChange; + floor->resetDelayCount = StartDelay; + break; +*/ + default: + break; + } + SN_StartSequence((mobj_t *) & sec->soundorg, SEQ_PLATFORM + sec->seqType); + // + // Find next sector to raise + // Find nearby sector with sector special equal to type + // + for (i = 0; i < sec->linecount; i++) + { + if (!((sec->lines[i])->flags & ML_TWOSIDED)) + { + continue; + } + tsec = (sec->lines[i])->frontsector; + if (tsec->special == type + STAIR_SECTOR_TYPE && !tsec->specialdata + && tsec->floorpic == Texture && tsec->validcount != validcount) + { + QueueStairSector(tsec, type ^ 1, height); + tsec->validcount = validcount; + //tsec->special = 0; + } + tsec = (sec->lines[i])->backsector; + if (tsec->special == type + STAIR_SECTOR_TYPE && !tsec->specialdata + && tsec->floorpic == Texture && tsec->validcount != validcount) + { + QueueStairSector(tsec, type ^ 1, height); + tsec->validcount = validcount; + //tsec->special = 0; + } + } +} + +//================================================================== +// +// BUILD A STAIRCASE! +// +// Direction is either positive or negative, denoting build stairs +// up or down. +//================================================================== + +int EV_BuildStairs(line_t * line, byte * args, int direction, + stairs_e stairsType) +{ + int secnum; + int height; + int delay; + int resetDelay; + sector_t *sec; + sector_t *qSec; + int type; + + // Set global stairs variables + TextureChange = 0; + Direction = direction; + StepDelta = Direction * (args[2] * FRACUNIT); + Speed = args[1] * (FRACUNIT / 8); + resetDelay = args[4]; + delay = args[3]; + if (stairsType == STAIRS_PHASED) + { + StartDelayDelta = args[3]; + StartDelay = StartDelayDelta; + resetDelay = StartDelayDelta; + delay = 0; + TextureChange = args[4]; + } + + secnum = -1; + + validcount++; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + + Texture = sec->floorpic; + StartHeight = sec->floorheight; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + QueueStairSector(sec, 0, sec->floorheight); + sec->special = 0; + } + while ((qSec = DequeueStairSector(&type, &height)) != NULL) + { + ProcessStairSector(qSec, type, height, stairsType, delay, resetDelay); + } + return (1); +} + +//========================================================================= +// +// T_BuildPillar +// +//========================================================================= + +void T_BuildPillar(thinker_t *thinker) +{ + pillar_t *pillar = (pillar_t *) thinker; + result_e res1; + result_e res2; + + // First, raise the floor + res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floordest, pillar->crush, 0, pillar->direction); // floorOrCeiling, direction + // Then, lower the ceiling + res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed, + pillar->ceilingdest, pillar->crush, 1, + -pillar->direction); + if (res1 == RES_PASTDEST && res2 == RES_PASTDEST) + { + pillar->sector->specialdata = NULL; + SN_StopSequence((mobj_t *) & pillar->sector->soundorg); + P_TagFinished(pillar->sector->tag); + P_RemoveThinker(&pillar->thinker); + } +} + +//========================================================================= +// +// EV_BuildPillar +// +//========================================================================= + +int EV_BuildPillar(line_t * line, byte * args, boolean crush) +{ + int secnum; + sector_t *sec; + pillar_t *pillar; + int newHeight; + int rtn; + + rtn = 0; + secnum = -1; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; // already moving + if (sec->floorheight == sec->ceilingheight) + { // pillar is already closed + continue; + } + rtn = 1; + if (!args[2]) + { + newHeight = sec->floorheight + + ((sec->ceilingheight - sec->floorheight) / 2); + } + else + { + newHeight = sec->floorheight + (args[2] << FRACBITS); + } + + pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0); + sec->specialdata = pillar; + P_AddThinker(&pillar->thinker); + pillar->thinker.function = T_BuildPillar; + pillar->sector = sec; + if (!args[2]) + { + pillar->ceilingSpeed = pillar->floorSpeed = + args[1] * (FRACUNIT / 8); + } + else if (newHeight - sec->floorheight > + sec->ceilingheight - newHeight) + { + pillar->floorSpeed = args[1] * (FRACUNIT / 8); + pillar->ceilingSpeed = FixedMul(sec->ceilingheight - newHeight, + FixedDiv(pillar->floorSpeed, + newHeight - + sec->floorheight)); + } + else + { + pillar->ceilingSpeed = args[1] * (FRACUNIT / 8); + pillar->floorSpeed = FixedMul(newHeight - sec->floorheight, + FixedDiv(pillar->ceilingSpeed, + sec->ceilingheight - + newHeight)); + } + pillar->floordest = newHeight; + pillar->ceilingdest = newHeight; + pillar->direction = 1; + pillar->crush = crush * args[3]; + SN_StartSequence((mobj_t *) & pillar->sector->soundorg, + SEQ_PLATFORM + pillar->sector->seqType); + } + return rtn; +} + +//========================================================================= +// +// EV_OpenPillar +// +//========================================================================= + +int EV_OpenPillar(line_t * line, byte * args) +{ + int secnum; + sector_t *sec; + pillar_t *pillar; + int rtn; + + rtn = 0; + secnum = -1; + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; // already moving + if (sec->floorheight != sec->ceilingheight) + { // pillar isn't closed + continue; + } + rtn = 1; + pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0); + sec->specialdata = pillar; + P_AddThinker(&pillar->thinker); + pillar->thinker.function = T_BuildPillar; + pillar->sector = sec; + if (!args[2]) + { + pillar->floordest = P_FindLowestFloorSurrounding(sec); + } + else + { + pillar->floordest = sec->floorheight - (args[2] << FRACBITS); + } + if (!args[3]) + { + pillar->ceilingdest = P_FindHighestCeilingSurrounding(sec); + } + else + { + pillar->ceilingdest = sec->ceilingheight + (args[3] << FRACBITS); + } + if (sec->floorheight - pillar->floordest >= pillar->ceilingdest - + sec->ceilingheight) + { + pillar->floorSpeed = args[1] * (FRACUNIT / 8); + pillar->ceilingSpeed = FixedMul(sec->ceilingheight - + pillar->ceilingdest, + FixedDiv(pillar->floorSpeed, + pillar->floordest - + sec->floorheight)); + } + else + { + pillar->ceilingSpeed = args[1] * (FRACUNIT / 8); + pillar->floorSpeed = + FixedMul(pillar->floordest - sec->floorheight, + FixedDiv(pillar->ceilingSpeed, + sec->ceilingheight - pillar->ceilingdest)); + } + pillar->direction = -1; // open the pillar + SN_StartSequence((mobj_t *) & pillar->sector->soundorg, + SEQ_PLATFORM + pillar->sector->seqType); + } + return rtn; +} + +//========================================================================= +// +// EV_FloorCrushStop +// +//========================================================================= + +int EV_FloorCrushStop(line_t * line, byte * args) +{ + thinker_t *think; + floormove_t *floor; + boolean rtn; + + rtn = 0; + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != T_MoveFloor) + { + continue; + } + floor = (floormove_t *) think; + if (floor->type != FLEV_RAISEFLOORCRUSH) + { + continue; + } + // Completely remove the crushing floor + SN_StopSequence((mobj_t *) & floor->sector->soundorg); + floor->sector->specialdata = NULL; + P_TagFinished(floor->sector->tag); + P_RemoveThinker(&floor->thinker); + rtn = 1; + } + return rtn; +} + +//========================================================================== +// +// T_FloorWaggle +// +//========================================================================== + +#define WGLSTATE_EXPAND 1 +#define WGLSTATE_STABLE 2 +#define WGLSTATE_REDUCE 3 + +void T_FloorWaggle(thinker_t *thinker) +{ + floorWaggle_t *waggle = (floorWaggle_t *) thinker; + switch (waggle->state) + { + case WGLSTATE_EXPAND: + if ((waggle->scale += waggle->scaleDelta) >= waggle->targetScale) + { + waggle->scale = waggle->targetScale; + waggle->state = WGLSTATE_STABLE; + } + break; + case WGLSTATE_REDUCE: + if ((waggle->scale -= waggle->scaleDelta) <= 0) + { // Remove + waggle->sector->floorheight = waggle->originalHeight; + P_ChangeSector(waggle->sector, true); + waggle->sector->specialdata = NULL; + P_TagFinished(waggle->sector->tag); + P_RemoveThinker(&waggle->thinker); + return; + } + break; + case WGLSTATE_STABLE: + if (waggle->ticker != -1) + { + if (!--waggle->ticker) + { + waggle->state = WGLSTATE_REDUCE; + } + } + break; + } + waggle->accumulator += waggle->accDelta; + waggle->sector->floorheight = waggle->originalHeight + + FixedMul(FloatBobOffsets[(waggle->accumulator >> FRACBITS) & 63], + waggle->scale); + P_ChangeSector(waggle->sector, true); +} + +//========================================================================== +// +// EV_StartFloorWaggle +// +//========================================================================== + +boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset, + int timer) +{ + int sectorIndex; + sector_t *sector; + floorWaggle_t *waggle; + boolean retCode; + + retCode = false; + sectorIndex = -1; + while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) + { + sector = §ors[sectorIndex]; + if (sector->specialdata) + { // Already busy with another thinker + continue; + } + retCode = true; + waggle = Z_Malloc(sizeof(*waggle), PU_LEVSPEC, 0); + sector->specialdata = waggle; + waggle->thinker.function = T_FloorWaggle; + waggle->sector = sector; + waggle->originalHeight = sector->floorheight; + waggle->accumulator = offset * FRACUNIT; + waggle->accDelta = speed << 10; + waggle->scale = 0; + waggle->targetScale = height << 10; + waggle->scaleDelta = waggle->targetScale + / (35 + ((3 * 35) * height) / 255); + waggle->ticker = timer ? timer * 35 : -1; + waggle->state = WGLSTATE_EXPAND; + P_AddThinker(&waggle->thinker); + } + return retCode; +} diff --git a/games/NXDoom/src/hexen/p_inter.c b/games/NXDoom/src/hexen/p_inter.c new file mode 100644 index 00000000000..fab06674c2a --- /dev/null +++ b/games/NXDoom/src/hexen/p_inter.c @@ -0,0 +1,2231 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "m_misc.h" +#include "m_random.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" + +#define BONUSADD 6 + +int ArmorIncrement[NUMCLASSES][NUMARMOR] = { + {25 * FRACUNIT, 20 * FRACUNIT, 15 * FRACUNIT, 5 * FRACUNIT}, + {10 * FRACUNIT, 25 * FRACUNIT, 5 * FRACUNIT, 20 * FRACUNIT}, + {5 * FRACUNIT, 15 * FRACUNIT, 10 * FRACUNIT, 25 * FRACUNIT}, + {0, 0, 0, 0} +}; + +int AutoArmorSave[NUMCLASSES] = + { 15 * FRACUNIT, 10 * FRACUNIT, 5 * FRACUNIT, 0 }; + +const char *TextKeyMessages[] = { + TXT_KEY_STEEL, + TXT_KEY_CAVE, + TXT_KEY_AXE, + TXT_KEY_FIRE, + TXT_KEY_EMERALD, + TXT_KEY_DUNGEON, + TXT_KEY_SILVER, + TXT_KEY_RUSTED, + TXT_KEY_HORN, + TXT_KEY_SWAMP, + TXT_KEY_CASTLE +}; + +static void SetDormantArtifact(mobj_t * arti); +static void TryPickupArtifact(player_t * player, artitype_t artifactType, + mobj_t * artifact); +static void TryPickupWeapon(player_t * player, pclass_t weaponClass, + weapontype_t weaponType, mobj_t * weapon, + const char *message); +static void TryPickupWeaponPiece(player_t * player, pclass_t matchClass, + int pieceValue, mobj_t * pieceMobj); + +//-------------------------------------------------------------------------- +// +// PROC P_SetMessage +// +//-------------------------------------------------------------------------- + +void P_SetMessage(player_t * player, const char *message, boolean ultmsg) +{ + if ((player->ultimateMessage || !messageson) && !ultmsg) + { + return; + } + + M_StringCopy(player->message, message, sizeof(player->message)); +// strupr(player->message); + player->messageTics = MESSAGETICS; + player->yellowMessage = false; + if (ultmsg) + { + player->ultimateMessage = true; + } + if (player == &players[consoleplayer]) + { + BorderTopRefresh = true; + } +} + +//========================================================================== +// +// P_SetYellowMessage +// +//========================================================================== + +void P_SetYellowMessage(player_t * player, const char *message, boolean ultmsg) +{ + if ((player->ultimateMessage || !messageson) && !ultmsg) + { + return; + } + M_StringCopy(player->message, message, sizeof(player->message)); + player->messageTics = 5 * MESSAGETICS; // Bold messages last longer + player->yellowMessage = true; + if (ultmsg) + { + player->ultimateMessage = true; + } + if (player == &players[consoleplayer]) + { + BorderTopRefresh = true; + } +} + +//========================================================================== +// +// P_ClearMessage +// +//========================================================================== + +void P_ClearMessage(player_t * player) +{ + player->messageTics = 0; + if (player == &players[consoleplayer]) + { + BorderTopRefresh = true; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_HideSpecialThing +// +//---------------------------------------------------------------------------- + +void P_HideSpecialThing(mobj_t * thing) +{ + thing->flags &= ~MF_SPECIAL; + thing->flags2 |= MF2_DONTDRAW; + P_SetMobjState(thing, S_HIDESPECIAL1); +} + +//-------------------------------------------------------------------------- +// +// FUNC P_GiveMana +// +// Returns true if the player accepted the mana, false if it was +// refused (player has MAX_MANA). +// +//-------------------------------------------------------------------------- + +boolean P_GiveMana(player_t * player, manatype_t mana, int count) +{ + int prevMana; + //weapontype_t changeWeapon; + + if (mana == MANA_NONE || mana == MANA_BOTH) + { + return (false); + } + if ((unsigned int) mana > NUMMANA) + { + I_Error("P_GiveMana: bad type %i", mana); + } + if (player->mana[mana] == MAX_MANA) + { + return (false); + } + if (gameskill == sk_baby || gameskill == sk_nightmare) + { // extra mana in baby mode and nightmare mode + count += count >> 1; + } + prevMana = player->mana[mana]; + + player->mana[mana] += count; + if (player->mana[mana] > MAX_MANA) + { + player->mana[mana] = MAX_MANA; + } + if (player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND + && mana == MANA_1 && prevMana <= 0) + { + P_SetPsprite(player, ps_weapon, S_FAXEREADY_G); + } + return (true); +} + +//========================================================================== +// +// TryPickupWeapon +// +//========================================================================== + +static void TryPickupWeapon(player_t * player, pclass_t weaponClass, + weapontype_t weaponType, mobj_t * weapon, + const char *message) +{ + boolean remove; + boolean gaveMana; + boolean gaveWeapon; + + remove = true; + if (player->class != weaponClass) + { // Wrong class, but try to pick up for mana + if (netgame && !deathmatch) + { // Can't pick up weapons for other classes in coop netplay + return; + } + if (weaponType == WP_SECOND) + { + if (!P_GiveMana(player, MANA_1, 25)) + { + return; + } + } + else + { + if (!P_GiveMana(player, MANA_2, 25)) + { + return; + } + } + } + else if (netgame && !deathmatch) + { // Cooperative net-game + if (player->weaponowned[weaponType]) + { + return; + } + player->weaponowned[weaponType] = true; + if (weaponType == WP_SECOND) + { + P_GiveMana(player, MANA_1, 25); + } + else + { + P_GiveMana(player, MANA_2, 25); + } + player->pendingweapon = weaponType; + remove = false; + } + else + { // Deathmatch or single player game + if (weaponType == WP_SECOND) + { + gaveMana = P_GiveMana(player, MANA_1, 25); + } + else + { + gaveMana = P_GiveMana(player, MANA_2, 25); + } + if (player->weaponowned[weaponType]) + { + gaveWeapon = false; + } + else + { + gaveWeapon = true; + player->weaponowned[weaponType] = true; + if (weaponType > player->readyweapon) + { // Only switch to more powerful weapons + player->pendingweapon = weaponType; + } + } + if (!(gaveWeapon || gaveMana)) + { // Player didn't need the weapon or any mana + return; + } + } + + P_SetMessage(player, message, false); + if (weapon->special) + { + P_ExecuteLineSpecial(weapon->special, weapon->args, + NULL, 0, player->mo); + weapon->special = 0; + } + + if (remove) + { + if (deathmatch && !(weapon->flags2 & MF2_DROPPED)) + { + P_HideSpecialThing(weapon); + } + else + { + P_RemoveMobj(weapon); + } + } + + player->bonuscount += BONUSADD; + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, SFX_PICKUP_WEAPON); + SB_PaletteFlash(false); + } +} + +//-------------------------------------------------------------------------- +// +// FUNC P_GiveWeapon +// +// Returns true if the weapon or its mana was accepted. +// +//-------------------------------------------------------------------------- + +/* +boolean P_GiveWeapon(player_t *player, pclass_t class, weapontype_t weapon) +{ + boolean gaveMana; + boolean gaveWeapon; + + if(player->class != class) + { // player cannot use this weapon, take it anyway, and get mana + if(netgame && !deathmatch) + { // Can't pick up weapons for other classes in coop netplay + return false; + } + if(weapon == WP_SECOND) + { + return P_GiveMana(player, MANA_1, 25); + } + else + { + return P_GiveMana(player, MANA_2, 25); + } + } + if(netgame && !deathmatch) + { // Cooperative net-game + if(player->weaponowned[weapon]) + { + return(false); + } + player->bonuscount += BONUSADD; + player->weaponowned[weapon] = true; + if(weapon == WP_SECOND) + { + P_GiveMana(player, MANA_1, 25); + } + else + { + P_GiveMana(player, MANA_2, 25); + } + player->pendingweapon = weapon; + if(player == &players[consoleplayer]) + { + S_StartSound(NULL, SFX_PICKUP_WEAPON); + } + return(false); + } + if(weapon == WP_SECOND) + { + gaveMana = P_GiveMana(player, MANA_1, 25); + } + else + { + gaveMana = P_GiveMana(player, MANA_2, 25); + } + if(player->weaponowned[weapon]) + { + gaveWeapon = false; + } + else + { + gaveWeapon = true; + player->weaponowned[weapon] = true; + if(weapon > player->readyweapon) + { // Only switch to more powerful weapons + player->pendingweapon = weapon; + } + } + return(gaveWeapon || gaveMana); +} +*/ + +//=========================================================================== +// +// P_GiveWeaponPiece +// +//=========================================================================== + +/* +boolean P_GiveWeaponPiece(player_t *player, pclass_t class, int piece) +{ + P_GiveMana(player, MANA_1, 20); + P_GiveMana(player, MANA_2, 20); + if(player->class != class) + { + return true; + } + else if(player->pieces&piece) + { // player already has that weapon piece + return true; + } + player->pieces |= piece; + if(player->pieces == 7) + { // player has built the fourth weapon! + P_GiveWeapon(player, class, WP_FOURTH); + S_StartSound(player->mo, SFX_WEAPON_BUILD); + } + return true; +} +*/ + +//========================================================================== +// +// TryPickupWeaponPiece +// +//========================================================================== + +static void TryPickupWeaponPiece(player_t * player, pclass_t matchClass, + int pieceValue, mobj_t * pieceMobj) +{ + boolean remove; + boolean checkAssembled; + boolean gaveWeapon; + int gaveMana; + static const char *fourthWeaponText[] = { + TXT_WEAPON_F4, + TXT_WEAPON_C4, + TXT_WEAPON_M4 + }; + static const char *weaponPieceText[] = { + TXT_QUIETUS_PIECE, + TXT_WRAITHVERGE_PIECE, + TXT_BLOODSCOURGE_PIECE + }; + static int pieceValueTrans[] = { + 0, // 0: never + WPIECE1 | WPIECE2 | WPIECE3, // WPIECE1 (1) + WPIECE2 | WPIECE3, // WPIECE2 (2) + 0, // 3: never + WPIECE3 // WPIECE3 (4) + }; + + remove = true; + checkAssembled = true; + gaveWeapon = false; + if (player->class != matchClass) + { // Wrong class, but try to pick up for mana + if (netgame && !deathmatch) + { // Can't pick up wrong-class weapons in coop netplay + return; + } + checkAssembled = false; + gaveMana = P_GiveMana(player, MANA_1, 20) + + P_GiveMana(player, MANA_2, 20); + if (!gaveMana) + { // Didn't need the mana, so don't pick it up + return; + } + } + else if (netgame && !deathmatch) + { // Cooperative net-game + if (player->pieces & pieceValue) + { // Already has the piece + return; + } + pieceValue = pieceValueTrans[pieceValue]; + P_GiveMana(player, MANA_1, 20); + P_GiveMana(player, MANA_2, 20); + remove = false; + } + else + { // Deathmatch or single player game + gaveMana = P_GiveMana(player, MANA_1, 20) + + P_GiveMana(player, MANA_2, 20); + if (player->pieces & pieceValue) + { // Already has the piece, check if mana needed + if (!gaveMana) + { // Didn't need the mana, so don't pick it up + return; + } + checkAssembled = false; + } + } + + // Pick up the weapon piece + if (pieceMobj->special) + { + P_ExecuteLineSpecial(pieceMobj->special, pieceMobj->args, + NULL, 0, player->mo); + pieceMobj->special = 0; + } + if (remove) + { + if (deathmatch && !(pieceMobj->flags2 & MF2_DROPPED)) + { + P_HideSpecialThing(pieceMobj); + } + else + { + P_RemoveMobj(pieceMobj); + } + } + player->bonuscount += BONUSADD; + if (player == &players[consoleplayer]) + { + SB_PaletteFlash(false); + } + + // Check if fourth weapon assembled + if (checkAssembled) + { + player->pieces |= pieceValue; + if (player->pieces == (WPIECE1 | WPIECE2 | WPIECE3)) + { + gaveWeapon = true; + player->weaponowned[WP_FOURTH] = true; + player->pendingweapon = WP_FOURTH; + } + } + + if (gaveWeapon) + { + P_SetMessage(player, fourthWeaponText[matchClass], false); + // Play the build-sound full volume for all players + S_StartSound(NULL, SFX_WEAPON_BUILD); + } + else + { + P_SetMessage(player, weaponPieceText[matchClass], false); + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, SFX_PICKUP_WEAPON); + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveBody +// +// Returns false if the body isn't needed at all. +// +//--------------------------------------------------------------------------- + +boolean P_GiveBody(player_t * player, int num) +{ + int max; + + max = MAXHEALTH; + if (player->morphTics) + { + max = MAXMORPHHEALTH; + } + if (player->health >= max) + { + return (false); + } + player->health += num; + if (player->health > max) + { + player->health = max; + } + player->mo->health = player->health; + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveArmor +// +// Returns false if the armor is worse than the current armor. +// +//--------------------------------------------------------------------------- + +boolean P_GiveArmor(player_t * player, armortype_t armortype, int amount) +{ + int hits; + int totalArmor; + + if (amount == -1) + { + hits = ArmorIncrement[player->class][armortype]; + if (player->armorpoints[armortype] >= hits) + { + return false; + } + else + { + player->armorpoints[armortype] = hits; + } + } + else + { + hits = amount * 5 * FRACUNIT; + totalArmor = player->armorpoints[ARMOR_ARMOR] + + player->armorpoints[ARMOR_SHIELD] + + player->armorpoints[ARMOR_HELMET] + + player->armorpoints[ARMOR_AMULET] + + AutoArmorSave[player->class]; + if (totalArmor < ArmorMax[player->class] * 5 * FRACUNIT) + { + player->armorpoints[armortype] += hits; + } + else + { + return false; + } + } + return true; +} + +//--------------------------------------------------------------------------- +// +// PROC P_GiveKey +// +//--------------------------------------------------------------------------- + +int P_GiveKey(player_t * player, keytype_t key) +{ + if (player->keys & (1 << key)) + { + return false; + } + player->bonuscount += BONUSADD; + player->keys |= 1 << key; + return true; +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GivePower +// +// Returns true if power accepted. +// +//--------------------------------------------------------------------------- + +boolean P_GivePower(player_t * player, powertype_t power) +{ + if (power == pw_invulnerability) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = INVULNTICS; + player->mo->flags2 |= MF2_INVULNERABLE; + if (player->class == PCLASS_MAGE) + { + player->mo->flags2 |= MF2_REFLECTIVE; + } + return (true); + } + if (power == pw_flight) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = FLIGHTTICS; + player->mo->flags2 |= MF2_FLY; + player->mo->flags |= MF_NOGRAVITY; + if (player->mo->z <= player->mo->floorz) + { + player->flyheight = 10; // thrust the player in the air a bit + } + return (true); + } + if (power == pw_infrared) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = INFRATICS; + return (true); + } + if (power == pw_speed) + { + if (player->powers[power] > BLINKTHRESHOLD) + { // Already have it + return (false); + } + player->powers[power] = SPEEDTICS; + return (true); + } + if (power == pw_minotaur) + { + // Doesn't matter if already have power, renew ticker + player->powers[power] = MAULATORTICS; + return (true); + } +/* + if(power == pw_ironfeet) + { + player->powers[power] = IRONTICS; + return(true); + } + if(power == pw_strength) + { + P_GiveBody(player, 100); + player->powers[power] = 1; + return(true); + } +*/ + if (player->powers[power]) + { + return (false); // already got it + } + player->powers[power] = 1; + return (true); +} + +//========================================================================== +// +// TryPickupArtifact +// +//========================================================================== + +static void TryPickupArtifact(player_t * player, artitype_t artifactType, + mobj_t * artifact) +{ + static const char *artifactMessages[NUMARTIFACTS] = { + NULL, + TXT_ARTIINVULNERABILITY, + TXT_ARTIHEALTH, + TXT_ARTISUPERHEALTH, + TXT_ARTIHEALINGRADIUS, + TXT_ARTISUMMON, + TXT_ARTITORCH, + TXT_ARTIEGG, + TXT_ARTIFLY, + TXT_ARTIBLASTRADIUS, + TXT_ARTIPOISONBAG, + TXT_ARTITELEPORTOTHER, + TXT_ARTISPEED, + TXT_ARTIBOOSTMANA, + TXT_ARTIBOOSTARMOR, + TXT_ARTITELEPORT, + TXT_ARTIPUZZSKULL, + TXT_ARTIPUZZGEMBIG, + TXT_ARTIPUZZGEMRED, + TXT_ARTIPUZZGEMGREEN1, + TXT_ARTIPUZZGEMGREEN2, + TXT_ARTIPUZZGEMBLUE1, + TXT_ARTIPUZZGEMBLUE2, + TXT_ARTIPUZZBOOK1, + TXT_ARTIPUZZBOOK2, + TXT_ARTIPUZZSKULL2, + TXT_ARTIPUZZFWEAPON, + TXT_ARTIPUZZCWEAPON, + TXT_ARTIPUZZMWEAPON, + TXT_ARTIPUZZGEAR, // All gear pickups use the same text + TXT_ARTIPUZZGEAR, + TXT_ARTIPUZZGEAR, + TXT_ARTIPUZZGEAR + }; + + if (gamemode == shareware) + { + artifactMessages[arti_blastradius] = TXT_ARTITELEPORT; + artifactMessages[arti_teleport] = TXT_ARTIBLASTRADIUS; + } + + if (P_GiveArtifact(player, artifactType, artifact)) + { + if (artifact->special) + { + P_ExecuteLineSpecial(artifact->special, artifact->args, + NULL, 0, NULL); + artifact->special = 0; + } + player->bonuscount += BONUSADD; + if (artifactType < arti_firstpuzzitem) + { + SetDormantArtifact(artifact); + S_StartSound(artifact, SFX_PICKUP_ARTIFACT); + P_SetMessage(player, artifactMessages[artifactType], false); + } + else + { // Puzzle item + S_StartSound(NULL, SFX_PICKUP_ITEM); + P_SetMessage(player, artifactMessages[artifactType], true); + if (!netgame || deathmatch) + { // Remove puzzle items if not cooperative netplay + P_RemoveMobj(artifact); + } + } + } +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GiveArtifact +// +// Returns true if artifact accepted. +// +//--------------------------------------------------------------------------- + +boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo) +{ + int i; + int j; + boolean slidePointer; + + slidePointer = false; + i = 0; + while (player->inventory[i].type != arti && i < player->inventorySlotNum) + { + i++; + } + if (i == player->inventorySlotNum) + { + if (arti < arti_firstpuzzitem) + { + i = 0; + while (player->inventory[i].type < arti_firstpuzzitem + && i < player->inventorySlotNum) + { + i++; + } + if (i != player->inventorySlotNum) + { + for (j = player->inventorySlotNum; j > i; j--) + { + player->inventory[j].count = + player->inventory[j - 1].count; + player->inventory[j].type = player->inventory[j - 1].type; + slidePointer = true; + } + } + } + player->inventory[i].count = 1; + player->inventory[i].type = arti; + player->inventorySlotNum++; + } + else + { + if (arti >= arti_firstpuzzitem && netgame && !deathmatch) + { // Can't carry more than 1 puzzle item in coop netplay + return false; + } + if (player->inventory[i].count >= 25) + { // Player already has 25 of this item + return false; + } + player->inventory[i].count++; + } + if (!player->artifactCount) + { + player->readyArtifact = arti; + } + else if (player == &players[consoleplayer] && slidePointer + && i <= inv_ptr) + { + inv_ptr++; + curpos++; + if (curpos > 6) + { + curpos = 6; + } + } + player->artifactCount++; + return (true); +} + +//========================================================================== +// +// SetDormantArtifact +// +// Removes the MF_SPECIAL flag and initiates the artifact pickup +// animation. +// +//========================================================================== + +static void SetDormantArtifact(mobj_t * arti) +{ + arti->flags &= ~MF_SPECIAL; + if (deathmatch && !(arti->flags2 & MF2_DROPPED)) + { + if (arti->type == MT_ARTIINVULNERABILITY) + { + P_SetMobjState(arti, S_DORMANTARTI3_1); + } + else if (arti->type == MT_SUMMONMAULATOR || arti->type == MT_ARTIFLY) + { + P_SetMobjState(arti, S_DORMANTARTI2_1); + } + else + { + P_SetMobjState(arti, S_DORMANTARTI1_1); + } + } + else + { // Don't respawn + P_SetMobjState(arti, S_DEADARTI1); + } +} + +//--------------------------------------------------------------------------- +// +// PROC A_RestoreArtifact +// +//--------------------------------------------------------------------------- + +void A_RestoreArtifact(mobj_t *arti, player_t *player, pspdef_t *psp) +{ + arti->flags |= MF_SPECIAL; + P_SetMobjState(arti, arti->info->spawnstate); + S_StartSound(arti, SFX_RESPAWN); +} + +//--------------------------------------------------------------------------- +// +// PROC A_RestoreSpecialThing1 +// +// Make a special thing visible again. +// +//--------------------------------------------------------------------------- + +void A_RestoreSpecialThing1(mobj_t * thing, player_t *player, pspdef_t *psp) +{ + thing->flags2 &= ~MF2_DONTDRAW; + S_StartSound(thing, SFX_RESPAWN); +} + +//--------------------------------------------------------------------------- +// +// PROC A_RestoreSpecialThing2 +// +//--------------------------------------------------------------------------- + +void A_RestoreSpecialThing2(mobj_t * thing, player_t *player, pspdef_t *psp) +{ + thing->flags |= MF_SPECIAL; + P_SetMobjState(thing, thing->info->spawnstate); +} + +//--------------------------------------------------------------------------- +// +// PROC P_TouchSpecialThing +// +//--------------------------------------------------------------------------- + +void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher) +{ + player_t *player; + fixed_t delta; + int sound; + boolean respawn; + + delta = special->z - toucher->z; + if (delta > toucher->height || delta < -32 * FRACUNIT) + { // Out of reach + return; + } + if (toucher->health <= 0) + { // Toucher is dead + return; + } + sound = SFX_PICKUP_ITEM; + player = toucher->player; + respawn = true; + switch (special->sprite) + { + // Items + case SPR_PTN1: // Item_HealingPotion + if (!P_GiveBody(player, 10)) + { + return; + } + P_SetMessage(player, TXT_ITEMHEALTH, false); + break; + case SPR_ARM1: + if (!P_GiveArmor(player, ARMOR_ARMOR, -1)) + { + return; + } + P_SetMessage(player, TXT_ARMOR1, false); + break; + case SPR_ARM2: + if (!P_GiveArmor(player, ARMOR_SHIELD, -1)) + { + return; + } + P_SetMessage(player, TXT_ARMOR2, false); + break; + case SPR_ARM3: + if (!P_GiveArmor(player, ARMOR_HELMET, -1)) + { + return; + } + P_SetMessage(player, TXT_ARMOR3, false); + break; + case SPR_ARM4: + if (!P_GiveArmor(player, ARMOR_AMULET, -1)) + { + return; + } + P_SetMessage(player, TXT_ARMOR4, false); + break; + + // Keys + case SPR_KEY1: + case SPR_KEY2: + case SPR_KEY3: + case SPR_KEY4: + case SPR_KEY5: + case SPR_KEY6: + case SPR_KEY7: + case SPR_KEY8: + case SPR_KEY9: + case SPR_KEYA: + case SPR_KEYB: + if (!P_GiveKey(player, special->sprite - SPR_KEY1)) + { + return; + } + P_SetMessage(player, TextKeyMessages[special->sprite - SPR_KEY1], + true); + sound = SFX_PICKUP_KEY; + + // Check and process the special now in case the key doesn't + // get removed for coop netplay + if (special->special) + { + P_ExecuteLineSpecial(special->special, special->args, + NULL, 0, toucher); + special->special = 0; + } + + if (!netgame) + { // Only remove keys in single player game + break; + } + player->bonuscount += BONUSADD; + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, sound); + SB_PaletteFlash(false); + } + return; + + // Artifacts + case SPR_PTN2: + TryPickupArtifact(player, arti_health, special); + return; + case SPR_SOAR: + TryPickupArtifact(player, arti_fly, special); + return; + case SPR_INVU: + TryPickupArtifact(player, arti_invulnerability, special); + return; + case SPR_SUMN: + TryPickupArtifact(player, arti_summon, special); + return; + case SPR_PORK: + TryPickupArtifact(player, arti_egg, special); + return; + case SPR_SPHL: + TryPickupArtifact(player, arti_superhealth, special); + return; + case SPR_HRAD: + TryPickupArtifact(player, arti_healingradius, special); + return; + case SPR_TRCH: + TryPickupArtifact(player, arti_torch, special); + return; + case SPR_ATLP: + TryPickupArtifact(player, arti_teleport, special); + return; + case SPR_TELO: + TryPickupArtifact(player, arti_teleportother, special); + return; + case SPR_PSBG: + TryPickupArtifact(player, arti_poisonbag, special); + return; + case SPR_SPED: + TryPickupArtifact(player, arti_speed, special); + return; + case SPR_BMAN: + TryPickupArtifact(player, arti_boostmana, special); + return; + case SPR_BRAC: + TryPickupArtifact(player, arti_boostarmor, special); + return; + case SPR_BLST: + TryPickupArtifact(player, arti_blastradius, special); + return; + + // Puzzle artifacts + case SPR_ASKU: + TryPickupArtifact(player, arti_puzzskull, special); + return; + case SPR_ABGM: + TryPickupArtifact(player, arti_puzzgembig, special); + return; + case SPR_AGMR: + TryPickupArtifact(player, arti_puzzgemred, special); + return; + case SPR_AGMG: + TryPickupArtifact(player, arti_puzzgemgreen1, special); + return; + case SPR_AGG2: + TryPickupArtifact(player, arti_puzzgemgreen2, special); + return; + case SPR_AGMB: + TryPickupArtifact(player, arti_puzzgemblue1, special); + return; + case SPR_AGB2: + TryPickupArtifact(player, arti_puzzgemblue2, special); + return; + case SPR_ABK1: + TryPickupArtifact(player, arti_puzzbook1, special); + return; + case SPR_ABK2: + TryPickupArtifact(player, arti_puzzbook2, special); + return; + case SPR_ASK2: + TryPickupArtifact(player, arti_puzzskull2, special); + return; + case SPR_AFWP: + TryPickupArtifact(player, arti_puzzfweapon, special); + return; + case SPR_ACWP: + TryPickupArtifact(player, arti_puzzcweapon, special); + return; + case SPR_AMWP: + TryPickupArtifact(player, arti_puzzmweapon, special); + return; + case SPR_AGER: + TryPickupArtifact(player, arti_puzzgear1, special); + return; + case SPR_AGR2: + TryPickupArtifact(player, arti_puzzgear2, special); + return; + case SPR_AGR3: + TryPickupArtifact(player, arti_puzzgear3, special); + return; + case SPR_AGR4: + TryPickupArtifact(player, arti_puzzgear4, special); + return; + + // Mana + case SPR_MAN1: + if (!P_GiveMana(player, MANA_1, 15)) + { + return; + } + P_SetMessage(player, TXT_MANA_1, false); + break; + case SPR_MAN2: + if (!P_GiveMana(player, MANA_2, 15)) + { + return; + } + P_SetMessage(player, TXT_MANA_2, false); + break; + case SPR_MAN3: // Double Mana Dodecahedron + if (!P_GiveMana(player, MANA_1, 20)) + { + if (!P_GiveMana(player, MANA_2, 20)) + { + return; + } + } + else + { + P_GiveMana(player, MANA_2, 20); + } + P_SetMessage(player, TXT_MANA_BOTH, false); + break; + + // 2nd and 3rd Mage Weapons + case SPR_WMCS: // Frost Shards + TryPickupWeapon(player, PCLASS_MAGE, WP_SECOND, + special, TXT_WEAPON_M2); + return; + case SPR_WMLG: // Arc of Death + TryPickupWeapon(player, PCLASS_MAGE, WP_THIRD, + special, TXT_WEAPON_M3); + return; + + // 2nd and 3rd Fighter Weapons + case SPR_WFAX: // Timon's Axe + TryPickupWeapon(player, PCLASS_FIGHTER, WP_SECOND, + special, TXT_WEAPON_F2); + return; + case SPR_WFHM: // Hammer of Retribution + TryPickupWeapon(player, PCLASS_FIGHTER, WP_THIRD, + special, TXT_WEAPON_F3); + return; + + // 2nd and 3rd Cleric Weapons + case SPR_WCSS: // Serpent Staff + TryPickupWeapon(player, PCLASS_CLERIC, WP_SECOND, + special, TXT_WEAPON_C2); + return; + case SPR_WCFM: // Firestorm + TryPickupWeapon(player, PCLASS_CLERIC, WP_THIRD, + special, TXT_WEAPON_C3); + return; + + // Fourth Weapon Pieces + case SPR_WFR1: + TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE1, special); + return; + case SPR_WFR2: + TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE2, special); + return; + case SPR_WFR3: + TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE3, special); + return; + case SPR_WCH1: + TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE1, special); + return; + case SPR_WCH2: + TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE2, special); + return; + case SPR_WCH3: + TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE3, special); + return; + case SPR_WMS1: + TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE1, special); + return; + case SPR_WMS2: + TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE2, special); + return; + case SPR_WMS3: + TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE3, special); + return; + + default: + I_Error("P_SpecialThing: Unknown gettable thing"); + } + if (special->special) + { + P_ExecuteLineSpecial(special->special, special->args, NULL, + 0, toucher); + special->special = 0; + } + if (deathmatch && respawn && !(special->flags2 & MF2_DROPPED)) + { + P_HideSpecialThing(special); + } + else + { + P_RemoveMobj(special); + } + player->bonuscount += BONUSADD; + if (player == &players[consoleplayer]) + { + S_StartSound(NULL, sound); + SB_PaletteFlash(false); + } +} + +// Search thinker list for minotaur +mobj_t *ActiveMinotaur(player_t * master) +{ + mobj_t *mo; + player_t *plr; + thinker_t *think; + unsigned int *starttime; + + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + continue; + mo = (mobj_t *) think; + if (mo->type != MT_MINOTAUR) + continue; + if (mo->health <= 0) + continue; + if (!(mo->flags & MF_COUNTKILL)) + continue; // for morphed minotaurs + if (mo->flags & MF_CORPSE) + continue; + starttime = (unsigned int *) mo->args; + if ((leveltime - *starttime) >= MAULATORTICS) + continue; + plr = mo->special1.m->player; + if (plr == master) + return (mo); + } + return (NULL); +} + + +//--------------------------------------------------------------------------- +// +// PROC P_KillMobj +// +//--------------------------------------------------------------------------- + +void P_KillMobj(mobj_t * source, mobj_t * target) +{ + byte dummyArgs[3] = {0, 0, 0}; + mobj_t *master; + + target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_NOGRAVITY); + target->flags |= MF_CORPSE | MF_DROPOFF; + target->flags2 &= ~MF2_PASSMOBJ; + target->height >>= 2; + if ((target->flags & MF_COUNTKILL || target->type == MT_ZBELL) + && target->special) + { // Initiate monster death actions + if (target->type == MT_SORCBOSS) + { + P_StartACS(target->special, 0, dummyArgs, target, NULL, 0); + } + else + { + P_ExecuteLineSpecial(target->special, target->args, + NULL, 0, target); + } + } + if (source && source->player) + { // Check for frag changes + if (target->player) + { + if (target == source) + { // Self-frag + target->player->frags[target->player - players]--; + if (cmdfrag && netgame + && source->player == &players[consoleplayer]) + { // Send out a frag count packet + NET_SendFrags(source->player); + } + } + else + { + source->player->frags[target->player - players]++; + if (cmdfrag && netgame + && source->player == &players[consoleplayer]) + { // Send out a frag count packet + NET_SendFrags(source->player); + } + } + } + } + if (target->player) + { // Player death + if (!source) + { // Self-frag + target->player->frags[target->player - players]--; + if (cmdfrag && netgame + && target->player == &players[consoleplayer]) + { // Send out a frag count packet + NET_SendFrags(target->player); + } + } + target->flags &= ~MF_SOLID; + target->flags2 &= ~MF2_FLY; + target->player->powers[pw_flight] = 0; + target->player->playerstate = PST_DEAD; + P_DropWeapon(target->player); + if (target->flags2 & MF2_FIREDAMAGE) + { // Player flame death + switch (target->player->class) + { + case PCLASS_FIGHTER: + S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH); + P_SetMobjState(target, S_PLAY_F_FDTH1); + return; + case PCLASS_CLERIC: + S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH); + P_SetMobjState(target, S_PLAY_C_FDTH1); + return; + case PCLASS_MAGE: + S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH); + P_SetMobjState(target, S_PLAY_M_FDTH1); + return; + default: + break; + } + } + if (target->flags2 & MF2_ICEDAMAGE) + { // Player ice death + target->flags &= ~(7 << MF_TRANSSHIFT); //no translation + target->flags |= MF_ICECORPSE; + switch (target->player->class) + { + case PCLASS_FIGHTER: + P_SetMobjState(target, S_FPLAY_ICE); + return; + case PCLASS_CLERIC: + P_SetMobjState(target, S_CPLAY_ICE); + return; + case PCLASS_MAGE: + P_SetMobjState(target, S_MPLAY_ICE); + return; + case PCLASS_PIG: + P_SetMobjState(target, S_PIG_ICE); + return; + default: + break; + } + } + } + if (target->flags2 & MF2_FIREDAMAGE) + { + if (target->type == MT_FIGHTER_BOSS + || target->type == MT_CLERIC_BOSS || target->type == MT_MAGE_BOSS) + { + switch (target->type) + { + case MT_FIGHTER_BOSS: + S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH); + P_SetMobjState(target, S_PLAY_F_FDTH1); + return; + case MT_CLERIC_BOSS: + S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH); + P_SetMobjState(target, S_PLAY_C_FDTH1); + return; + case MT_MAGE_BOSS: + S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH); + P_SetMobjState(target, S_PLAY_M_FDTH1); + return; + default: + break; + } + } + else if (target->type == MT_TREEDESTRUCTIBLE) + { + P_SetMobjState(target, S_ZTREEDES_X1); + target->height = 24 * FRACUNIT; + S_StartSound(target, SFX_TREE_EXPLODE); + return; + } + } + if (target->flags2 & MF2_ICEDAMAGE) + { + target->flags |= MF_ICECORPSE; + switch (target->type) + { + case MT_BISHOP: + P_SetMobjState(target, S_BISHOP_ICE); + return; + case MT_CENTAUR: + case MT_CENTAURLEADER: + P_SetMobjState(target, S_CENTAUR_ICE); + return; + case MT_DEMON: + case MT_DEMON2: + P_SetMobjState(target, S_DEMON_ICE); + return; + case MT_SERPENT: + case MT_SERPENTLEADER: + P_SetMobjState(target, S_SERPENT_ICE); + return; + case MT_WRAITH: + case MT_WRAITHB: + P_SetMobjState(target, S_WRAITH_ICE); + return; + case MT_ETTIN: + P_SetMobjState(target, S_ETTIN_ICE1); + return; + case MT_FIREDEMON: + P_SetMobjState(target, S_FIRED_ICE1); + return; + case MT_FIGHTER_BOSS: + P_SetMobjState(target, S_FIGHTER_ICE); + return; + case MT_CLERIC_BOSS: + P_SetMobjState(target, S_CLERIC_ICE); + return; + case MT_MAGE_BOSS: + P_SetMobjState(target, S_MAGE_ICE); + return; + case MT_PIG: + P_SetMobjState(target, S_PIG_ICE); + return; + default: + target->flags &= ~MF_ICECORPSE; + break; + } + } + + if (target->type == MT_MINOTAUR) + { + master = target->special1.m; + if (master->health > 0) + { + if (!ActiveMinotaur(master->player)) + { + master->player->powers[pw_minotaur] = 0; + } + } + } + else if (target->type == MT_TREEDESTRUCTIBLE) + { + target->height = 24 * FRACUNIT; + } + if (target->health < -(target->info->spawnhealth >> 1) + && target->info->xdeathstate) + { // Extreme death + P_SetMobjState(target, target->info->xdeathstate); + } + else + { // Normal death + if ((target->type == MT_FIREDEMON) && + (target->z <= target->floorz + 2 * FRACUNIT) && + (target->info->xdeathstate)) + { + // This is to fix the imps' staying in fall state + P_SetMobjState(target, target->info->xdeathstate); + } + else + { + P_SetMobjState(target, target->info->deathstate); + } + } + target->tics -= P_Random() & 3; +// I_StartSound(&actor->r, actor->info->deathsound); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_MinotaurSlam +// +//--------------------------------------------------------------------------- + +void P_MinotaurSlam(mobj_t * source, mobj_t * target) +{ + angle_t angle; + fixed_t thrust; + + angle = R_PointToAngle2(source->x, source->y, target->x, target->y); + angle >>= ANGLETOFINESHIFT; + thrust = 16 * FRACUNIT + (P_Random() << 10); + target->momx += FixedMul(thrust, finecosine[angle]); + target->momy += FixedMul(thrust, finesine[angle]); + P_DamageMobj(target, NULL, source, HITDICE(4)); + if (target->player) + { + target->reactiontime = 14 + (P_Random() & 7); + } + source->args[0] = 0; // Stop charging +} + + +//--------------------------------------------------------------------------- +// +// FUNC P_MorphPlayer +// +// Returns true if the player gets turned into a pig +// +//--------------------------------------------------------------------------- + +boolean P_MorphPlayer(player_t * player) +{ + mobj_t *pmo; + mobj_t *fog; + mobj_t *beastMo; + fixed_t x; + fixed_t y; + fixed_t z; + angle_t angle; + int oldFlags2; + + if (player->powers[pw_invulnerability]) + { // Immune when invulnerable + return (false); + } + if (player->morphTics) + { // Player is already a beast + return false; + } + pmo = player->mo; + x = pmo->x; + y = pmo->y; + z = pmo->z; + angle = pmo->angle; + oldFlags2 = pmo->flags2; + P_SetMobjState(pmo, S_FREETARGMOBJ); + fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, SFX_TELEPORT); + beastMo = P_SpawnMobj(x, y, z, MT_PIGPLAYER); + beastMo->special1.i = player->readyweapon; + beastMo->angle = angle; + beastMo->player = player; + player->health = beastMo->health = MAXMORPHHEALTH; + player->mo = beastMo; + memset(&player->armorpoints[0], 0, NUMARMOR * sizeof(int)); + player->class = PCLASS_PIG; + if (oldFlags2 & MF2_FLY) + { + beastMo->flags2 |= MF2_FLY; + } + player->morphTics = MORPHTICS; + P_ActivateMorphWeapon(player); + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_MorphMonster +// +//--------------------------------------------------------------------------- + +boolean P_MorphMonster(mobj_t * actor) +{ + mobj_t *master, *monster, *fog; + mobjtype_t moType; + fixed_t x; + fixed_t y; + fixed_t z; + mobj_t oldMonster; + + if (actor->player) + return (false); + if (!(actor->flags & MF_COUNTKILL)) + return false; + if (actor->flags2 & MF2_BOSS) + return false; + moType = actor->type; + switch (moType) + { + case MT_PIG: + return (false); + case MT_FIGHTER_BOSS: + case MT_CLERIC_BOSS: + case MT_MAGE_BOSS: + return (false); + default: + break; + } + + oldMonster = *actor; + x = oldMonster.x; + y = oldMonster.y; + z = oldMonster.z; + P_RemoveMobjFromTIDList(actor); + P_SetMobjState(actor, S_FREETARGMOBJ); + fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, SFX_TELEPORT); + monster = P_SpawnMobj(x, y, z, MT_PIG); + monster->special2.i = moType; + monster->special1.i = MORPHTICS + P_Random(); + monster->flags |= (oldMonster.flags & MF_SHADOW); + monster->target = oldMonster.target; + monster->angle = oldMonster.angle; + monster->tid = oldMonster.tid; + monster->special = oldMonster.special; + P_InsertMobjIntoTIDList(monster, oldMonster.tid); + memcpy(monster->args, oldMonster.args, 5); + + // check for turning off minotaur power for active icon + if (moType == MT_MINOTAUR) + { + master = oldMonster.special1.m; + if (master->health > 0) + { + if (!ActiveMinotaur(master->player)) + { + master->player->powers[pw_minotaur] = 0; + } + } + } + return (true); +} + +//--------------------------------------------------------------------------- +// +// PROC P_AutoUseHealth +// +//--------------------------------------------------------------------------- + +void P_AutoUseHealth(player_t * player, int saveHealth) +{ + int i; + int count; + int normalCount; + int normalSlot = 0; + int superCount; + int superSlot = 0; + + normalCount = superCount = 0; + for (i = 0; i < player->inventorySlotNum; i++) + { + if (player->inventory[i].type == arti_health) + { + normalSlot = i; + normalCount = player->inventory[i].count; + } + else if (player->inventory[i].type == arti_superhealth) + { + superSlot = i; + superCount = player->inventory[i].count; + } + } + if ((gameskill == sk_baby) && (normalCount * 25 >= saveHealth)) + { // Use quartz flasks + count = (saveHealth + 24) / 25; + for (i = 0; i < count; i++) + { + player->health += 25; + P_PlayerRemoveArtifact(player, normalSlot); + } + } + else if (superCount * 100 >= saveHealth) + { // Use mystic urns + count = (saveHealth + 99) / 100; + for (i = 0; i < count; i++) + { + player->health += 100; + P_PlayerRemoveArtifact(player, superSlot); + } + } + else if ((gameskill == sk_baby) + && (superCount * 100 + normalCount * 25 >= saveHealth)) + { // Use mystic urns and quartz flasks + count = (saveHealth + 24) / 25; + saveHealth -= count * 25; + for (i = 0; i < count; i++) + { + player->health += 25; + P_PlayerRemoveArtifact(player, normalSlot); + } + count = (saveHealth + 99) / 100; + for (i = 0; i < count; i++) + { + player->health += 100; + P_PlayerRemoveArtifact(player, normalSlot); + } + } + player->mo->health = player->health; +} + +/* +================= += += P_DamageMobj += += Damages both enemies and players += inflictor is the thing that caused the damage += creature or missile, can be NULL (slime, etc) += source is the thing to target after taking damage += creature or NULL += Source and inflictor are the same for melee attacks += source can be null for barrel explosions and other environmental stuff +================== +*/ + +void P_DamageMobj + (mobj_t * target, mobj_t * inflictor, mobj_t * source, int damage) +{ + unsigned ang; + int saved; + fixed_t savedPercent; + player_t *player; + mobj_t *master; + fixed_t thrust; + int temp; + int i; + + if (!(target->flags & MF_SHOOTABLE)) + { + // Shouldn't happen + return; + } + if (target->health <= 0) + { + if (inflictor && inflictor->flags2 & MF2_ICEDAMAGE) + { + return; + } + else if (target->flags & MF_ICECORPSE) // frozen + { + target->tics = 1; + target->momx = target->momy = 0; + } + return; + } + if ((target->flags2 & MF2_INVULNERABLE) && damage < 10000) + { // mobj is invulnerable + if (target->player) + return; // for player, no exceptions + if (inflictor) + { + switch (inflictor->type) + { + // These inflictors aren't foiled by invulnerability + case MT_HOLY_FX: + case MT_POISONCLOUD: + case MT_FIREBOMB: + break; + default: + return; + } + } + else + { + return; + } + } + if (target->player) + { + if (damage < 1000 && ((target->player->cheats & CF_GODMODE) + || target->player->powers[pw_invulnerability])) + { + return; + } + } + if (target->flags & MF_SKULLFLY) + { + target->momx = target->momy = target->momz = 0; + } + if (target->flags2 & MF2_DORMANT) + { + // Invulnerable, and won't wake up + return; + } + player = target->player; + if (player && gameskill == sk_baby) + { + // Take half damage in trainer mode + damage >>= 1; + } + // Special damage types + if (inflictor) + { + switch (inflictor->type) + { + case MT_EGGFX: + if (player) + { + P_MorphPlayer(player); + } + else + { + P_MorphMonster(target); + } + return; // Always return + case MT_TELOTHER_FX1: + case MT_TELOTHER_FX2: + case MT_TELOTHER_FX3: + case MT_TELOTHER_FX4: + case MT_TELOTHER_FX5: + if ((target->flags & MF_COUNTKILL) && + (target->type != MT_SERPENT) && + (target->type != MT_SERPENTLEADER) && + (!(target->flags2 & MF2_BOSS))) + { + P_TeleportOther(target); + } + return; + case MT_MINOTAUR: + if (inflictor->flags & MF_SKULLFLY) + { // Slam only when in charge mode + P_MinotaurSlam(inflictor, target); + return; + } + break; + case MT_BISH_FX: + // Bishops are just too nasty + damage >>= 1; + break; + case MT_SHARDFX1: + switch (inflictor->special2.i) + { + case 3: + damage <<= 3; + break; + case 2: + damage <<= 2; + break; + case 1: + damage <<= 1; + break; + default: + break; + } + break; + case MT_CSTAFF_MISSILE: + // Cleric Serpent Staff does poison damage + if (target->player) + { + P_PoisonPlayer(target->player, source, 20); + damage >>= 1; + } + break; + case MT_ICEGUY_FX2: + damage >>= 1; + break; + case MT_POISONDART: + if (target->player) + { + P_PoisonPlayer(target->player, source, 20); + damage >>= 1; + } + break; + case MT_POISONCLOUD: + if (target->player) + { + if (target->player->poisoncount < 4) + { + P_PoisonDamage(target->player, source, 15 + (P_Random() & 15), false); // Don't play painsound + P_PoisonPlayer(target->player, source, 50); + S_StartSound(target, SFX_PLAYER_POISONCOUGH); + } + return; + } + else if (!(target->flags & MF_COUNTKILL)) + { // only damage monsters/players with the poison cloud + return; + } + break; + case MT_FSWORD_MISSILE: + if (target->player) + { + damage -= damage >> 2; + } + break; + default: + break; + } + } + // Push the target unless source is using the gauntlets + if (inflictor && (!source || !source->player) + && !(inflictor->flags2 & MF2_NODMGTHRUST)) + { + ang = R_PointToAngle2(inflictor->x, inflictor->y, + target->x, target->y); + //thrust = damage*(FRACUNIT>>3)*100/target->info->mass; + thrust = damage * (FRACUNIT >> 3) * 150 / target->info->mass; + // make fall forwards sometimes + if ((damage < 40) && (damage > target->health) + && (target->z - inflictor->z > 64 * FRACUNIT) && (P_Random() & 1)) + { + ang += ANG180; + thrust *= 4; + } + ang >>= ANGLETOFINESHIFT; + target->momx += FixedMul(thrust, finecosine[ang]); + target->momy += FixedMul(thrust, finesine[ang]); + } + + // + // player specific + // + if (player) + { + savedPercent = AutoArmorSave[player->class] + + player->armorpoints[ARMOR_ARMOR] + + player->armorpoints[ARMOR_SHIELD] + + player->armorpoints[ARMOR_HELMET] + + player->armorpoints[ARMOR_AMULET]; + if (savedPercent) + { // armor absorbed some damage + if (savedPercent > 100 * FRACUNIT) + { + savedPercent = 100 * FRACUNIT; + } + for (i = 0; i < NUMARMOR; i++) + { + if (player->armorpoints[i]) + { + player->armorpoints[i] -= + FixedDiv(FixedMul(damage << FRACBITS, + ArmorIncrement[player->class][i]), + 300 * FRACUNIT); + if (player->armorpoints[i] < 2 * FRACUNIT) + { + player->armorpoints[i] = 0; + } + } + } + saved = FixedDiv(FixedMul(damage << FRACBITS, savedPercent), + 100 * FRACUNIT); + if (saved > savedPercent * 2) + { + saved = savedPercent * 2; + } + damage -= saved >> FRACBITS; + } + if (damage >= player->health + && ((gameskill == sk_baby) || deathmatch) && !player->morphTics) + { // Try to use some inventory health + P_AutoUseHealth(player, damage - player->health + 1); + } + player->health -= damage; // mirror mobj health here for Dave + if (player->health < 0) + { + player->health = 0; + } + player->attacker = source; + player->damagecount += damage; // add damage after armor / invuln + if (player->damagecount > 100) + { + player->damagecount = 100; // teleport stomp does 10k points... + } + temp = damage < 100 ? damage : 100; + if (player == &players[consoleplayer]) + { + I_Tactile(40, 10, 40 + temp * 2); + SB_PaletteFlash(false); + } + } + + // + // do the damage + // + target->health -= damage; + if (target->health <= 0) + { // Death + if (inflictor) + { // check for special fire damage or ice damage deaths + if (inflictor->flags2 & MF2_FIREDAMAGE) + { + if (player && !player->morphTics) + { // Check for flame death + if (target->health > -50 && damage > 25) + { + target->flags2 |= MF2_FIREDAMAGE; + } + } + else + { + target->flags2 |= MF2_FIREDAMAGE; + } + } + else if (inflictor->flags2 & MF2_ICEDAMAGE) + { + target->flags2 |= MF2_ICEDAMAGE; + } + } + if (source && (source->type == MT_MINOTAUR)) + { // Minotaur's kills go to his master + master = source->special1.m; + // Make sure still alive and not a pointer to fighter head + if (master->player && (master->player->mo == master)) + { + source = master; + } + } + if (source && (source->player) && + (source->player->readyweapon == WP_FOURTH)) + { + // Always extreme death from fourth weapon + target->health = -5000; + } + P_KillMobj(source, target); + return; + } + if ((P_Random() < target->info->painchance) + && !(target->flags & MF_SKULLFLY)) + { + if (inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR + && inflictor->type <= MT_LIGHTNING_ZAP)) + { + if (P_Random() < 96) + { + target->flags |= MF_JUSTHIT; // fight back! + P_SetMobjState(target, target->info->painstate); + } + else + { // "electrocute" the target + target->frame |= FF_FULLBRIGHT; + if (target->flags & MF_COUNTKILL && P_Random() < 128 + && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT)) + { + if ((target->type == MT_CENTAUR) || + (target->type == MT_CENTAURLEADER) || + (target->type == MT_ETTIN)) + { + S_StartSound(target, SFX_PUPPYBEAT); + } + } + } + } + else + { + target->flags |= MF_JUSTHIT; // fight back! + P_SetMobjState(target, target->info->painstate); + if (inflictor && inflictor->type == MT_POISONCLOUD) + { + if (target->flags & MF_COUNTKILL && P_Random() < 128 + && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT)) + { + if ((target->type == MT_CENTAUR) || + (target->type == MT_CENTAURLEADER) || + (target->type == MT_ETTIN)) + { + S_StartSound(target, SFX_PUPPYBEAT); + } + } + } + } + } + target->reactiontime = 0; // we're awake now... + if (!target->threshold && source && !(source->flags2 & MF2_BOSS) + && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR)) + { + // Target actor is not intent on another actor, + // so make him chase after source + if ((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER) + || (target->type == MT_CENTAURLEADER + && source->type == MT_CENTAUR)) + { + return; + } + target->target = source; + target->threshold = BASETHRESHOLD; + if (target->state == &states[target->info->spawnstate] + && target->info->seestate != S_NULL) + { + P_SetMobjState(target, target->info->seestate); + } + } +} + +//========================================================================== +// +// P_FallingDamage +// +//========================================================================== + +void P_FallingDamage(player_t * player) +{ + int damage; + int mom; + int dist; + + mom = abs(player->mo->momz); + dist = FixedMul(mom, 16 * FRACUNIT / 23); + + if (mom >= 63 * FRACUNIT) + { // automatic death + P_DamageMobj(player->mo, NULL, NULL, 10000); + return; + } + damage = ((FixedMul(dist, dist) / 10) >> FRACBITS) - 24; + if (player->mo->momz > -39 * FRACUNIT && damage > player->mo->health + && player->mo->health != 1) + { // No-death threshold + damage = player->mo->health - 1; + } + S_StartSound(player->mo, SFX_PLAYER_LAND); + P_DamageMobj(player->mo, NULL, NULL, damage); +} + +//========================================================================== +// +// P_PoisonPlayer - Sets up all data concerning poisoning +// +//========================================================================== + +void P_PoisonPlayer(player_t * player, mobj_t * poisoner, int poison) +{ + if ((player->cheats & CF_GODMODE) || player->powers[pw_invulnerability]) + { + return; + } + player->poisoncount += poison; + player->poisoner = poisoner; + if (player->poisoncount > 100) + { + player->poisoncount = 100; + } +} + +//========================================================================== +// +// P_PoisonDamage - Similar to P_DamageMobj +// +//========================================================================== + +void P_PoisonDamage(player_t * player, mobj_t * source, int damage, + boolean playPainSound) +{ + mobj_t *target; + mobj_t *inflictor; + + target = player->mo; + inflictor = source; + if (target->health <= 0) + { + return; + } + if (target->flags2 & MF2_INVULNERABLE && damage < 10000) + { // mobj is invulnerable + return; + } + if (gameskill == sk_baby) + { + // Take half damage in trainer mode + damage >>= 1; + } + if (damage < 1000 && ((player->cheats & CF_GODMODE) + || player->powers[pw_invulnerability])) + { + return; + } + if (damage >= player->health + && ((gameskill == sk_baby) || deathmatch) && !player->morphTics) + { // Try to use some inventory health + P_AutoUseHealth(player, damage - player->health + 1); + } + player->health -= damage; // mirror mobj health here for Dave + if (player->health < 0) + { + player->health = 0; + } + player->attacker = source; + + // + // do the damage + // + target->health -= damage; + if (target->health <= 0) + { // Death + target->special1.i = damage; + if (inflictor && !player->morphTics) + { // Check for flame death + if ((inflictor->flags2 & MF2_FIREDAMAGE) + && (target->health > -50) && (damage > 25)) + { + target->flags2 |= MF2_FIREDAMAGE; + } + if (inflictor->flags2 & MF2_ICEDAMAGE) + { + target->flags2 |= MF2_ICEDAMAGE; + } + } + P_KillMobj(source, target); + return; + } + if (!(leveltime & 63) && playPainSound) + { + P_SetMobjState(target, target->info->painstate); + } +/* + if((P_Random() < target->info->painchance) + && !(target->flags&MF_SKULLFLY)) + { + target->flags |= MF_JUSTHIT; // fight back! + P_SetMobjState(target, target->info->painstate); + } +*/ +} diff --git a/games/NXDoom/src/hexen/p_lights.c b/games/NXDoom/src/hexen/p_lights.c new file mode 100644 index 00000000000..aae27212f6e --- /dev/null +++ b/games/NXDoom/src/hexen/p_lights.c @@ -0,0 +1,369 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "m_random.h" +#include "p_local.h" + +//============================================================================ +// +// T_Light +// +//============================================================================ + +void T_Light(thinker_t *thinker) +{ + light_t *light = (light_t *) thinker; + if (light->count) + { + light->count--; + return; + } + switch (light->type) + { + case LITE_FADE: + light->sector->lightlevel = + ((light->sector->lightlevel << FRACBITS) + + light->value2) >> FRACBITS; + if (light->tics2 == 1) + { + if (light->sector->lightlevel >= light->value1) + { + light->sector->lightlevel = light->value1; + P_RemoveThinker(&light->thinker); + } + } + else if (light->sector->lightlevel <= light->value1) + { + light->sector->lightlevel = light->value1; + P_RemoveThinker(&light->thinker); + } + break; + case LITE_GLOW: + light->sector->lightlevel = + ((light->sector->lightlevel << FRACBITS) + + light->tics1) >> FRACBITS; + if (light->tics2 == 1) + { + if (light->sector->lightlevel >= light->value1) + { + light->sector->lightlevel = light->value1; + light->tics1 = -light->tics1; + light->tics2 = -1; // reverse direction + } + } + else if (light->sector->lightlevel <= light->value2) + { + light->sector->lightlevel = light->value2; + light->tics1 = -light->tics1; + light->tics2 = 1; // reverse direction + } + break; + case LITE_FLICKER: + if (light->sector->lightlevel == light->value1) + { + light->sector->lightlevel = light->value2; + light->count = (P_Random() & 7) + 1; + } + else + { + light->sector->lightlevel = light->value1; + light->count = (P_Random() & 31) + 1; + } + break; + case LITE_STROBE: + if (light->sector->lightlevel == light->value1) + { + light->sector->lightlevel = light->value2; + light->count = light->tics2; + } + else + { + light->sector->lightlevel = light->value1; + light->count = light->tics1; + } + break; + default: + break; + } +} + +//============================================================================ +// +// EV_SpawnLight +// +//============================================================================ + +boolean EV_SpawnLight(line_t * line, byte * arg, lighttype_t type) +{ + light_t *light; + sector_t *sec; + int secNum; + int arg1, arg2, arg3, arg4; + boolean think; + boolean rtn; + + /* + Original code; redundant considering that a byte value is always + in the range 0-255: + + arg1 = arg[1] > 255 ? 255 : arg[1]; + arg1 = arg1 < 0 ? 0 : arg1; + arg2 = arg[2] > 255 ? 255 : arg[2]; + arg2 = arg2 < 0 ? 0 : arg2; + arg3 = arg[3] > 255 ? 255 : arg[3]; + arg3 = arg3 < 0 ? 0 : arg3; + arg4 = arg[4] > 255 ? 255 : arg[4]; + arg4 = arg4 < 0 ? 0 : arg4; + */ + + arg1 = arg[1]; + arg2 = arg[2]; + arg3 = arg[3]; + arg4 = arg[4]; + + secNum = -1; + rtn = false; + while ((secNum = P_FindSectorFromTag(arg[0], secNum)) >= 0) + { + think = false; + sec = §ors[secNum]; + + light = (light_t *) Z_Malloc(sizeof(light_t), PU_LEVSPEC, 0); + light->type = type; + light->sector = sec; + light->count = 0; + rtn = true; + switch (type) + { + case LITE_RAISEBYVALUE: + sec->lightlevel += arg1; + if (sec->lightlevel > 255) + { + sec->lightlevel = 255; + } + break; + case LITE_LOWERBYVALUE: + sec->lightlevel -= arg1; + if (sec->lightlevel < 0) + { + sec->lightlevel = 0; + } + break; + case LITE_CHANGETOVALUE: + sec->lightlevel = arg1; + if (sec->lightlevel < 0) + { + sec->lightlevel = 0; + } + else if (sec->lightlevel > 255) + { + sec->lightlevel = 255; + } + break; + case LITE_FADE: + think = true; + light->value1 = arg1; // destination lightlevel + light->value2 = FixedDiv((arg1 - sec->lightlevel) << FRACBITS, arg2 << FRACBITS); // delta lightlevel + if (sec->lightlevel <= arg1) + { + light->tics2 = 1; // get brighter + } + else + { + light->tics2 = -1; + } + break; + case LITE_GLOW: + think = true; + light->value1 = arg1; // upper lightlevel + light->value2 = arg2; // lower lightlevel + light->tics1 = FixedDiv((arg1 - sec->lightlevel) << FRACBITS, arg3 << FRACBITS); // lightlevel delta + if (sec->lightlevel <= arg1) + { + light->tics2 = 1; // get brighter + } + else + { + light->tics2 = -1; + } + break; + case LITE_FLICKER: + think = true; + light->value1 = arg1; // upper lightlevel + light->value2 = arg2; // lower lightlevel + sec->lightlevel = light->value1; + light->count = (P_Random() & 64) + 1; + break; + case LITE_STROBE: + think = true; + light->value1 = arg1; // upper lightlevel + light->value2 = arg2; // lower lightlevel + light->tics1 = arg3; // upper tics + light->tics2 = arg4; // lower tics + light->count = arg3; + sec->lightlevel = light->value1; + break; + default: + rtn = false; + break; + } + if (think) + { + P_AddThinker(&light->thinker); + light->thinker.function = T_Light; + } + else + { + Z_Free(light); + } + } + return rtn; +} + +//============================================================================ +// +// T_Phase +// +//============================================================================ + +int PhaseTable[64] = { + 128, 112, 96, 80, 64, 48, 32, 32, + 16, 16, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 16, 16, 16, + 32, 32, 48, 64, 80, 96, 112, 128 +}; + +void T_Phase(thinker_t *thinker) +{ + phase_t *phase = (phase_t *) thinker; + phase->index = (phase->index + 1) & 63; + phase->sector->lightlevel = phase->base + PhaseTable[phase->index]; +} + +//========================================================================== +// +// P_SpawnPhasedLight +// +//========================================================================== + +void P_SpawnPhasedLight(sector_t * sector, int base, int index) +{ + phase_t *phase; + + phase = Z_Malloc(sizeof(*phase), PU_LEVSPEC, 0); + P_AddThinker(&phase->thinker); + phase->sector = sector; + if (index == -1) + { // sector->lightlevel as the index + phase->index = sector->lightlevel & 63; + } + else + { + phase->index = index & 63; + } + phase->base = base & 255; + sector->lightlevel = phase->base + PhaseTable[phase->index]; + phase->thinker.function = T_Phase; + + sector->special = 0; +} + +//========================================================================== +// +// P_SpawnLightSequence +// +//========================================================================== + +void P_SpawnLightSequence(sector_t * sector, int indexStep) +{ + sector_t *sec; + sector_t *nextSec; + sector_t *tempSec; + int seqSpecial; + int i; + int count; + fixed_t index; + fixed_t indexDelta; + int base; + + seqSpecial = LIGHT_SEQUENCE; // look for Light_Sequence, first + sec = sector; + count = 1; + do + { + nextSec = NULL; + sec->special = LIGHT_SEQUENCE_START; // make sure that the search doesn't back up. + for (i = 0; i < sec->linecount; i++) + { + tempSec = getNextSector(sec->lines[i], sec); + if (!tempSec) + { + continue; + } + if (tempSec->special == seqSpecial) + { + if (seqSpecial == LIGHT_SEQUENCE) + { + seqSpecial = LIGHT_SEQUENCE_ALT; + } + else + { + seqSpecial = LIGHT_SEQUENCE; + } + nextSec = tempSec; + count++; + } + } + sec = nextSec; + } + while (sec); + + sec = sector; + count *= indexStep; + index = 0; + indexDelta = FixedDiv(64 * FRACUNIT, count * FRACUNIT); + base = sector->lightlevel; + do + { + nextSec = NULL; + if (sec->lightlevel) + { + base = sec->lightlevel; + } + P_SpawnPhasedLight(sec, base, index >> FRACBITS); + index += indexDelta; + for (i = 0; i < sec->linecount; i++) + { + tempSec = getNextSector(sec->lines[i], sec); + if (!tempSec) + { + continue; + } + if (tempSec->special == LIGHT_SEQUENCE_START) + { + nextSec = tempSec; + } + } + sec = nextSec; + } + while (sec); +} diff --git a/games/NXDoom/src/hexen/p_local.h b/games/NXDoom/src/hexen/p_local.h new file mode 100644 index 00000000000..9bd92dd9637 --- /dev/null +++ b/games/NXDoom/src/hexen/p_local.h @@ -0,0 +1,429 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __P_LOCAL__ +#define __P_LOCAL__ + +#ifndef __R_LOCAL__ +#include "r_local.h" +#endif + +#define STARTREDPALS 1 +#define STARTBONUSPALS 9 +#define STARTPOISONPALS 13 +#define STARTICEPAL 21 +#define STARTHOLYPAL 22 +#define STARTSCOURGEPAL 25 +#define NUMREDPALS 8 +#define NUMBONUSPALS 4 +#define NUMPOISONPALS 8 + +#define TOCENTER -8 +#define FLOATSPEED (FRACUNIT*4) + +#define MAXHEALTH 100 +#define MAXMORPHHEALTH 30 +#define VIEWHEIGHT (48*FRACUNIT) + +// mapblocks are used to check movement against lines and things +#define MAPBLOCKUNITS 128 +#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) +#define MAPBLOCKSHIFT (FRACBITS+7) +#define MAPBMASK (MAPBLOCKSIZE-1) +#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) + +// player radius for movement checking +#define PLAYERRADIUS 16*FRACUNIT + +// MAXRADIUS is for precalculated sector block boxes +// the spider demon is larger, but we don't have any moving sectors +// nearby +#define MAXRADIUS 32*FRACUNIT + +#define GRAVITY FRACUNIT +#define MAXMOVE (30*FRACUNIT) + +#define USERANGE (64*FRACUNIT) +#define MELEERANGE (64*FRACUNIT) +#define MISSILERANGE (32*64*FRACUNIT) + +typedef enum +{ + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS +} dirtype_t; + +#define BASETHRESHOLD 100 // follow a player exlusively for 3 seconds + +// ***** P_TICK ***** + +extern thinker_t thinkercap; // both the head and tail of the thinker list +extern int TimerGame; // tic countdown for deathmatch + +void P_InitThinkers(void); +void P_AddThinker(thinker_t * thinker); +void P_RemoveThinker(thinker_t * thinker); + +// ***** P_PSPR ***** + +#define USE_MANA1 1 +#define USE_MANA2 1 + +void P_SetPsprite(player_t * player, int position, statenum_t stnum); +void P_SetPspriteNF(player_t * player, int position, statenum_t stnum); +void P_SetupPsprites(player_t * curplayer); +void P_MovePsprites(player_t * curplayer); +void P_DropWeapon(player_t * player); +void P_ActivateMorphWeapon(player_t * player); +void P_PostMorphWeapon(player_t * player, weapontype_t weapon); + +// ***** P_USER ***** + + +extern int ArmorMax[NUMCLASSES]; +extern int PStateNormal[NUMCLASSES]; +extern int PStateRun[NUMCLASSES]; +extern int PStateAttack[NUMCLASSES]; +extern int PStateAttackEnd[NUMCLASSES]; + +void P_PlayerThink(player_t * player); +void P_Thrust(player_t * player, angle_t angle, fixed_t move); +void P_PlayerNextArtifact(player_t *player); +void P_PlayerRemoveArtifact(player_t * player, int slot); +void P_PlayerUseArtifact(player_t * player, artitype_t arti); +boolean P_UseArtifact(player_t * player, artitype_t arti); +int P_GetPlayerNum(player_t * player); +void P_TeleportOther(mobj_t * victim); +void ResetBlasted(mobj_t * mo); +boolean P_UndoPlayerMorph(player_t *player); + + +// ***** P_MOBJ ***** + +// Any floor type >= FLOOR_LIQUID will floorclip sprites +enum +{ + FLOOR_SOLID, + FLOOR_ICE, + FLOOR_LIQUID, + FLOOR_WATER, + FLOOR_LAVA, + FLOOR_SLUDGE +}; + +#define ONFLOORZ INT_MIN +#define ONCEILINGZ INT_MAX +#define FLOATRANDZ (INT_MAX-1) +#define FROMCEILINGZ128 (INT_MAX-2) + +extern mobjtype_t PuffType; +extern mobj_t *MissileMobj; + +extern fixed_t FloatBobOffsets[64]; + + +mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); +void P_RemoveMobj(mobj_t * th); +boolean P_SetMobjState(mobj_t * mobj, statenum_t state); +boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state); +void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move); +int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta); +boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax); +void P_MobjThinker(thinker_t *thinker); +void P_DegenMobjThinker(thinker_t *thinker); +void P_BlasterMobjThinker(thinker_t *thinker); +void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z); +void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage); +void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator); +void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator); +void P_RipperBlood(mobj_t * mo); +int P_GetThingFloorType(mobj_t * thing); +int P_HitFloor(mobj_t * thing); +boolean P_CheckMissileSpawn(mobj_t * missile); +mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type); +mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z, + mobj_t * source, mobj_t * dest, mobjtype_t type); +mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, + angle_t angle, fixed_t momz); +mobj_t *P_SpawnMissileAngleSpeed(mobj_t * source, mobjtype_t type, + angle_t angle, fixed_t momz, fixed_t speed); +mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type); +mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle); +mobj_t *P_SPMAngleXYZ(mobj_t * source, fixed_t x, fixed_t y, + fixed_t z, mobjtype_t type, angle_t angle); +void P_CreateTIDList(void); +void P_RemoveMobjFromTIDList(mobj_t * mobj); +void P_InsertMobjIntoTIDList(mobj_t * mobj, int tid); +mobj_t *P_FindMobjFromTID(int tid, int *searchPosition); +void P_ExplodeMissile(mobj_t *mo); +mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z, + mobj_t * source, mobj_t * dest, mobjtype_t type); + +// ***** P_ENEMY ***** + +void P_NoiseAlert(mobj_t * target, mobj_t * emmiter); +int P_Massacre(void); +boolean A_RaiseMobj(mobj_t * actor); +boolean A_SinkMobj(mobj_t * actor); +void A_NoBlocking(mobj_t *actor, player_t *player, pspdef_t *psp); +boolean P_LookForMonsters(mobj_t * actor); +void P_InitCreatureCorpseQueue(boolean corpseScan); +void A_DeQueueCorpse(mobj_t * actor); +void A_Explode(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CHolyAttack3(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FSwordAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MStaffAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_FreezeDeathChunks(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcBallOrbit(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcSpinBalls(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SpeedBalls(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SlowBalls(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_StopBalls(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_AccelBalls(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_DecelBalls(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcBossAttack(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SpawnFizzle(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_CastSorcererSpell(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcUpdateBallAngle(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_BounceCheck(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcFX1Seek(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcOffense1(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_SorcOffense2(mobj_t *actor, player_t *player, pspdef_t *psp); +void A_MinotaurLook(mobj_t *actor, player_t *player, pspdef_t *psp); + + +// ***** P_MAPUTL ***** + +typedef struct +{ + fixed_t x, y, dx, dy; +} divline_t; + +typedef struct +{ + fixed_t frac; // along trace line + boolean isaline; + union + { + mobj_t *thing; + line_t *line; + } d; +} intercept_t; + +#define MAXINTERCEPTS 128 +extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p; +typedef boolean(*traverser_t) (intercept_t * in); + + +fixed_t P_AproxDistance(fixed_t dx, fixed_t dy); +int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line); +int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line); +void P_MakeDivline(line_t * li, divline_t * dl); +fixed_t P_InterceptVector(divline_t * v2, divline_t * v1); +int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld); + +extern fixed_t opentop, openbottom, openrange; +extern fixed_t lowfloor; +void P_LineOpening(line_t * linedef); + +boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)); +boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)); + +#define PT_ADDLINES 1 +#define PT_ADDTHINGS 2 +#define PT_EARLYOUT 4 + +extern divline_t trace; +boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, + int flags, boolean(*trav) (intercept_t *)); + +void P_UnsetThingPosition(mobj_t * thing); +void P_SetThingPosition(mobj_t * thing); +mobj_t *P_RoughMonsterSearch(mobj_t * mo, int distance); + +// ***** P_MAP ***** + + +#define MAXSPECIALCROSS 8 + + +extern boolean floatok; // if true, move would be ok if +extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz +extern int tmfloorpic; +extern mobj_t *BlockingMobj; + +extern line_t *ceilingline; +extern line_t *spechit[MAXSPECIALCROSS]; +extern int numspechit; + +extern fixed_t topslope, bottomslope; // slopes to top and bottom of target + + +boolean P_TestMobjLocation(mobj_t * mobj); +boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y); +mobj_t *P_CheckOnmobj(mobj_t * thing); +void P_FakeZMovement(mobj_t * mo); +boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y); +boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y); +void P_SlideMove(mobj_t * mo); +void P_BounceWall(mobj_t * mo); +boolean P_CheckSight(mobj_t * t1, mobj_t * t2); +void P_UseLines(player_t * player); +boolean P_UsePuzzleItem(player_t * player, int itemType); +void PIT_ThrustSpike(mobj_t * actor); +void P_InitSlideLine(void); + +boolean P_ChangeSector(sector_t * sector, int crunch); + +extern mobj_t *PuffSpawned; // true if a puff was spawned +extern mobj_t *linetarget; // who got hit (or NULL) +fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance); + +void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, + int damage); + +void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage, int distance, + boolean damageSource); + +// ***** P_SETUP ***** + +extern byte *rejectmatrix; // for fast sight rejection +extern short *blockmaplump; // offsets in blockmap are from here +extern short *blockmap; +extern int bmapwidth, bmapheight; // in mapblocks +extern fixed_t bmaporgx, bmaporgy; // origin of block map +extern mobj_t **blocklinks; // for thing chains + +// ***** P_INTER ***** + +extern int clipmana[NUMMANA]; +extern int ArmorIncrement[NUMCLASSES][NUMARMOR]; +extern int AutoArmorSave[NUMCLASSES]; +extern const char *TextKeyMessages[]; + + +void P_SetMessage(player_t * player, const char *message, boolean ultmsg); +void P_SetYellowMessage(player_t * player, const char *message, boolean ultmsg); +void P_ClearMessage(player_t * player); +void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher); +void P_DamageMobj(mobj_t * target, mobj_t * inflictor, mobj_t * source, + int damage); +void P_FallingDamage(player_t * player); +void P_PoisonPlayer(player_t * player, mobj_t * poisoner, int poison); +void P_PoisonDamage(player_t * player, mobj_t * source, int damage, + boolean playPainSound); +boolean P_GiveMana(player_t * player, manatype_t mana, int count); +boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo); +boolean P_GiveArmor(player_t * player, armortype_t armortype, int amount); +boolean P_GiveBody(player_t * player, int num); +boolean P_GivePower(player_t * player, powertype_t power); +boolean P_MorphPlayer(player_t * player); + +// ***** AM_MAP ***** + +boolean AM_Responder(event_t * ev); +void AM_Ticker(void); +void AM_Drawer(void); + +// ***** A_ACTION ***** +boolean A_LocalQuake(byte * args, mobj_t * victim); +void P_SpawnDirt(mobj_t * actor, fixed_t radius); +void A_BridgeRemove(mobj_t * actor); +void A_UnHideThing(mobj_t *actor, player_t *player, pspdef_t *psp); + + +// ***** SB_BAR ***** + +extern int SB_state; +extern int ArtifactFlash; +void SB_PaletteFlash(boolean forceChange); + +// ===== PO_MAN ===== + +typedef enum +{ + PODOOR_NONE, + PODOOR_SLIDE, + PODOOR_SWING, +} podoortype_t; + +typedef struct +{ + thinker_t thinker; + int polyobj; + int speed; + unsigned int dist; + int angle; + fixed_t xSpeed; // for sliding walls + fixed_t ySpeed; +} polyevent_t; + +typedef struct +{ + thinker_t thinker; + int polyobj; + int speed; + int dist; + int totalDist; + int direction; + fixed_t xSpeed, ySpeed; + int tics; + int waitTics; + podoortype_t type; + boolean close; +} polydoor_t; + +enum +{ + PO_ANCHOR_TYPE = 3000, + PO_SPAWN_TYPE, + PO_SPAWNCRUSH_TYPE +}; + +#define PO_LINE_START 1 // polyobj line start special +#define PO_LINE_EXPLICIT 5 + +extern polyobj_t *polyobjs; // list of all poly-objects on the level +extern int po_NumPolyobjs; +extern polyblock_t **PolyBlockMap; + + +void T_PolyDoor(thinker_t *thinker); +void T_RotatePoly(thinker_t *thinker); +boolean EV_RotatePoly(line_t * line, byte * args, int direction, boolean + overRide); +void T_MovePoly(thinker_t *thinker); +boolean EV_MovePoly(line_t * line, byte * args, boolean timesEight, boolean + overRide); +boolean EV_OpenPolyDoor(line_t * line, byte * args, podoortype_t type); + +boolean PO_MovePolyobj(int num, int x, int y); +boolean PO_RotatePolyobj(int num, angle_t angle); +void PO_Init(int lump); +boolean PO_Busy(int polyobj); + +#include "p_spec.h" + +#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/hexen/p_map.c b/games/NXDoom/src/hexen/p_map.c new file mode 100644 index 00000000000..6a3886015e7 --- /dev/null +++ b/games/NXDoom/src/hexen/p_map.c @@ -0,0 +1,2338 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "m_bbox.h" +#include "p_local.h" +#include "s_sound.h" + +static void CheckForPushSpecial(line_t * line, int side, mobj_t * mobj); + +/* +=============================================================================== + +NOTES: + + +=============================================================================== +*/ + +/* +=============================================================================== + +mobj_t NOTES + +mobj_ts are used to tell the refresh where to draw an image, tell the world simulation when objects are contacted, and tell the sound driver how to position a sound. + +The refresh uses the next and prev links to follow lists of things in sectors as they are being drawn. The sprite, frame, and angle elements determine which patch_t is used to draw the sprite if it is visible. The sprite and frame values are allmost allways set from state_t structures. The statescr.exe utility generates the states.h and states.c files that contain the sprite/frame numbers from the statescr.txt source file. The xyz origin point represents a point at the bottom middle of the sprite (between the feet of a biped). This is the default origin position for patch_ts grabbed with lumpy.exe. A walking creature will have its z equal to the floor it is standing on. + +The sound code uses the x,y, and subsector fields to do stereo positioning of any sound effited by the mobj_t. + +The play simulation uses the blocklinks, x,y,z, radius, height to determine when mobj_ts are touching each other, touching lines in the map, or hit by trace lines (gunshots, lines of sight, etc). The mobj_t->flags element has various bit flags used by the simulation. + + +Every mobj_t is linked into a single sector based on it's origin coordinates. +The subsector_t is found with R_PointInSubsector(x,y), and the sector_t can be found with subsector->sector. The sector links are only used by the rendering code, the play simulation does not care about them at all. + +Any mobj_t that needs to be acted upon be something else in the play world (block movement, be shot, etc) will also need to be linked into the blockmap. If the thing has the MF_NOBLOCK flag set, it will not use the block links. It can still interact with other things, but only as the instigator (missiles will run into other things, but nothing can run into a missile). Each block in the grid is 128*128 units, and knows about every line_t that it contains a piece of, and every interactable mobj_t that has it's origin contained. + +A valid mobj_t is a mobj_t that has the proper subsector_t filled in for it's xy coordinates and is linked into the subsector's sector or has the MF_NOSECTOR flag set (the subsector_t needs to be valid even if MF_NOSECTOR is set), and is linked into a blockmap block or has the MF_NOBLOCKMAP flag set. Links should only be modified by the P_[Un]SetThingPosition () functions. Do not change the MF_NO? flags while a thing is valid. + + +=============================================================================== +*/ + +fixed_t tmbbox[4]; +mobj_t *tmthing; +mobj_t *tsthing; +int tmflags; +fixed_t tmx, tmy; + +boolean floatok; // if true, move would be ok if + // within tmfloorz - tmceilingz + +fixed_t tmfloorz, tmceilingz, tmdropoffz; +int tmfloorpic; + +// keep track of the line that lowers the ceiling, so missiles don't explode +// against sky hack walls +line_t *ceilingline; + +// keep track of special lines as they are hit, but don't process them +// until the move is proven valid + +line_t *spechit[MAXSPECIALCROSS]; +int numspechit; + +mobj_t *onmobj; // generic global onmobj...used for landing on pods/players +mobj_t *BlockingMobj; + +/* +=============================================================================== + + TELEPORT MOVE + +=============================================================================== +*/ + +/* +================== += += PIT_StompThing += +================== +*/ + +boolean PIT_StompThing(mobj_t * thing) +{ + fixed_t blockdist; + + if (!(thing->flags & MF_SHOOTABLE)) + return true; + + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + + if (thing == tmthing) + return true; // don't clip against self + + if (!(tmthing->flags2 & MF2_TELESTOMP)) + { // Not allowed to stomp things + return (false); + } + + P_DamageMobj(thing, tmthing, tmthing, 10000); + + return true; +} + + +/* +=================== += += P_TeleportMove += +=================== +*/ + +boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + +// +// kill anything occupying the position +// + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + +// +// the base floor / ceiling is from the subsector that contains the +// point. Any contacted lines the step closer together will adjust them +// + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + tmfloorpic = newsubsec->sector->floorpic; + + validcount++; + numspechit = 0; + +// +// stomp on any things contacted +// + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_StompThing)) + return false; + +// +// the move is ok, so link the thing into its new position +// + P_UnsetThingPosition(thing); + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + P_SetThingPosition(thing); + + return true; +} + + +boolean PIT_ThrustStompThing(mobj_t * thing) +{ + fixed_t blockdist; + + if (!(thing->flags & MF_SHOOTABLE)) + return true; + + blockdist = thing->radius + tsthing->radius; + if (abs(thing->x - tsthing->x) >= blockdist || + abs(thing->y - tsthing->y) >= blockdist || + (thing->z > tsthing->z + tsthing->height)) + return true; // didn't hit it + + if (thing == tsthing) + return true; // don't clip against self + + P_DamageMobj(thing, tsthing, tsthing, 10001); + tsthing->args[1] = 1; // Mark thrust thing as bloody + + return true; +} + + + +void PIT_ThrustSpike(mobj_t * actor) +{ + int xl, xh, yl, yh, bx, by; + int x0, x2, y0, y2; + + tsthing = actor; + + x0 = actor->x - actor->info->radius; + x2 = actor->x + actor->info->radius; + y0 = actor->y - actor->info->radius; + y2 = actor->y + actor->info->radius; + + xl = (x0 - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (x2 - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (y0 - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (y2 - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + // stomp on any things contacted + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx, by, PIT_ThrustStompThing); +} + + + +/* +=============================================================================== + + MOVEMENT ITERATOR FUNCTIONS + +=============================================================================== +*/ + +/* +================== += += PIT_CheckLine += += Adjusts tmfloorz and tmceilingz as lines are contacted +================== +*/ + +boolean PIT_CheckLine(line_t * ld) +{ + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] + || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] + || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + { + return (true); + } + if (P_BoxOnLineSide(tmbbox, ld) != -1) + { + return (true); + } + +// a line has been hit +/* += += The moving thing's destination position will cross the given line. += If this should not be allowed, return false. += If the line is special, keep track of it to process later if the move += is proven ok. NOTE: specials are NOT sorted by order, so two special lines += that are only 8 pixels apart could be crossed in either order. +*/ + + if (!ld->backsector) + { // One sided line + if (tmthing->flags2 & MF2_BLASTED) + { + P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); + } + CheckForPushSpecial(ld, 0, tmthing); + return (false); + } + if (!(tmthing->flags & MF_MISSILE)) + { + if (ld->flags & ML_BLOCKING) + { // Explicitly blocking everything + if (tmthing->flags2 & MF2_BLASTED) + { + P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); + } + CheckForPushSpecial(ld, 0, tmthing); + return (false); + } + if (!tmthing->player && ld->flags & ML_BLOCKMONSTERS) + { // Block monsters only + if (tmthing->flags2 & MF2_BLASTED) + { + P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); + } + return (false); + } + } + P_LineOpening(ld); // set openrange, opentop, openbottom + // adjust floor / ceiling heights + if (opentop < tmceilingz) + { + tmceilingz = opentop; + ceilingline = ld; + } + if (openbottom > tmfloorz) + { + tmfloorz = openbottom; + } + if (lowfloor < tmdropoffz) + { + tmdropoffz = lowfloor; + } + if (ld->special) + { // Contacted a special line, add it to the list + spechit[numspechit] = ld; + numspechit++; + } + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC PIT_CheckThing +// +//--------------------------------------------------------------------------- + +boolean PIT_CheckThing(mobj_t * thing) +{ + fixed_t blockdist; + boolean solid; + int damage; + + if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) + { // Can't hit thing + return (true); + } + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { // Didn't hit thing + return (true); + } + if (thing == tmthing) + { // Don't clip against self + return (true); + } + BlockingMobj = thing; + if (tmthing->flags2 & MF2_PASSMOBJ) + { // check if a mobj passed over/under another object + if (tmthing->type == MT_BISHOP && thing->type == MT_BISHOP) + { // don't let bishops fly over other bishops + return false; + } + if (tmthing->z >= thing->z + thing->height + && !(thing->flags & MF_SPECIAL)) + { + return (true); + } + else if (tmthing->z + tmthing->height < thing->z + && !(thing->flags & MF_SPECIAL)) + { // under thing + return (true); + } + } + // Check for skulls slamming into things + if (tmthing->flags & MF_SKULLFLY) + { + if (tmthing->type == MT_MINOTAUR) + { + // Slamming minotaurs shouldn't move non-creatures + if (!(thing->flags & MF_COUNTKILL)) + { + return (false); + } + } + else if (tmthing->type == MT_HOLY_FX) + { + if (thing->flags & MF_SHOOTABLE && thing != tmthing->target) + { + if (netgame && !deathmatch && thing->player) + { // don't attack other co-op players + return true; + } + if (thing->flags2 & MF2_REFLECTIVE + && (thing->player || thing->flags2 & MF2_BOSS)) + { + tmthing->special1.m = tmthing->target; + tmthing->target = thing; + return true; + } + if (thing->flags & MF_COUNTKILL || thing->player) + { + tmthing->special1.m = thing; + } + if (P_Random() < 96) + { + damage = 12; + if (thing->player || thing->flags2 & MF2_BOSS) + { + damage = 3; + // ghost burns out faster when attacking players/bosses + tmthing->health -= 6; + } + P_DamageMobj(thing, tmthing, tmthing->target, damage); + if (P_Random() < 128) + { + P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, + MT_HOLY_PUFF); + S_StartSound(tmthing, SFX_SPIRIT_ATTACK); + if (thing->flags & MF_COUNTKILL && P_Random() < 128 + && !S_GetSoundPlayingInfo(thing, SFX_PUPPYBEAT)) + { + if ((thing->type == MT_CENTAUR) || + (thing->type == MT_CENTAURLEADER) || + (thing->type == MT_ETTIN)) + { + S_StartSound(thing, SFX_PUPPYBEAT); + } + } + } + } + if (thing->health <= 0) + { + tmthing->special1.i = 0; + } + } + return true; + } + damage = ((P_Random() % 8) + 1) * tmthing->damage; + P_DamageMobj(thing, tmthing, tmthing, damage); + tmthing->flags &= ~MF_SKULLFLY; + tmthing->momx = tmthing->momy = tmthing->momz = 0; + P_SetMobjState(tmthing, tmthing->info->seestate); + return (false); + } + // Check for blasted thing running into another + if (tmthing->flags2 & MF2_BLASTED && thing->flags & MF_SHOOTABLE) + { + if (!(thing->flags2 & MF2_BOSS) && (thing->flags & MF_COUNTKILL)) + { + thing->momx += tmthing->momx; + thing->momy += tmthing->momy; + if ((thing->momx + thing->momy) > 3 * FRACUNIT) + { + damage = (tmthing->info->mass / 100) + 1; + P_DamageMobj(thing, tmthing, tmthing, damage); + damage = (thing->info->mass / 100) + 1; + P_DamageMobj(tmthing, thing, thing, damage >> 2); + } + return (false); + } + } + // Check for missile + if (tmthing->flags & MF_MISSILE) + { + // Check for a non-shootable mobj + if (thing->flags2 & MF2_NONSHOOTABLE) + { + return true; + } + // Check if it went over / under + if (tmthing->z > thing->z + thing->height) + { // Over thing + return (true); + } + if (tmthing->z + tmthing->height < thing->z) + { // Under thing + return (true); + } + if (tmthing->flags2 & MF2_FLOORBOUNCE) + { + if (tmthing->target == thing || !(thing->flags & MF_SOLID)) + { + return true; + } + else + { + return false; + } + } + if (tmthing->type == MT_LIGHTNING_FLOOR + || tmthing->type == MT_LIGHTNING_CEILING) + { + if (thing->flags & MF_SHOOTABLE && thing != tmthing->target) + { + if (thing->info->mass != INT_MAX) + { + thing->momx += tmthing->momx >> 4; + thing->momy += tmthing->momy >> 4; + } + if ((!thing->player && !(thing->flags2 & MF2_BOSS)) + || !(leveltime & 1)) + { + if (thing->type == MT_CENTAUR + || thing->type == MT_CENTAURLEADER) + { // Lightning does more damage to centaurs + P_DamageMobj(thing, tmthing, tmthing->target, 9); + } + else + { + P_DamageMobj(thing, tmthing, tmthing->target, 3); + } + if (!(S_GetSoundPlayingInfo(tmthing, + SFX_MAGE_LIGHTNING_ZAP))) + { + S_StartSound(tmthing, SFX_MAGE_LIGHTNING_ZAP); + } + if (thing->flags & MF_COUNTKILL && P_Random() < 64 + && !S_GetSoundPlayingInfo(thing, SFX_PUPPYBEAT)) + { + if ((thing->type == MT_CENTAUR) || + (thing->type == MT_CENTAURLEADER) || + (thing->type == MT_ETTIN)) + { + S_StartSound(thing, SFX_PUPPYBEAT); + } + } + } + tmthing->health--; + if (tmthing->health <= 0 || thing->health <= 0) + { + return false; + } + if (tmthing->type == MT_LIGHTNING_FLOOR) + { + if (tmthing->special2.m + && !tmthing->special2.m->special1.m) + { + tmthing->special2.m->special1.m = thing; + } + } + else if (!tmthing->special1.m) + { + tmthing->special1.m = thing; + } + } + return true; // lightning zaps through all sprites + } + else if (tmthing->type == MT_LIGHTNING_ZAP) + { + mobj_t *lmo; + + if (thing->flags & MF_SHOOTABLE && thing != tmthing->target) + { + lmo = tmthing->special2.m; + if (lmo) + { + if (lmo->type == MT_LIGHTNING_FLOOR) + { + if (lmo->special2.m + && !lmo->special2.m->special1.m) + { + lmo->special2.m->special1.m = thing; + } + } + else if (!lmo->special1.m) + { + lmo->special1.m = thing; + } + if (!(leveltime & 3)) + { + lmo->health--; + } + } + } + } + else if (tmthing->type == MT_MSTAFF_FX2 && thing != tmthing->target) + { + if (!thing->player && !(thing->flags2 & MF2_BOSS)) + { + switch (thing->type) + { + case MT_FIGHTER_BOSS: // these not flagged boss + case MT_CLERIC_BOSS: // so they can be blasted + case MT_MAGE_BOSS: + break; + default: + P_DamageMobj(thing, tmthing, tmthing->target, 10); + return true; + break; + } + } + } + if (tmthing->target && tmthing->target->type == thing->type) + { // Don't hit same species as originator + if (thing == tmthing->target) + { // Don't missile self + return (true); + } + if (!thing->player) + { // Hit same species as originator, explode, no damage + return (false); + } + } + if (!(thing->flags & MF_SHOOTABLE)) + { // Didn't do any damage + return !(thing->flags & MF_SOLID); + } + if (tmthing->flags2 & MF2_RIP) + { + if (!(thing->flags & MF_NOBLOOD) && + !(thing->flags2 & MF2_REFLECTIVE) && + !(thing->flags2 & MF2_INVULNERABLE)) + { // Ok to spawn some blood + P_RipperBlood(tmthing); + } + //S_StartSound(tmthing, sfx_ripslop); + damage = ((P_Random() & 3) + 2) * tmthing->damage; + P_DamageMobj(thing, tmthing, tmthing->target, damage); + if (thing->flags2 & MF2_PUSHABLE + && !(tmthing->flags2 & MF2_CANNOTPUSH)) + { // Push thing + thing->momx += tmthing->momx >> 2; + thing->momy += tmthing->momy >> 2; + } + numspechit = 0; + return (true); + } + // Do damage + damage = ((P_Random() % 8) + 1) * tmthing->damage; + if (damage) + { + if (!(thing->flags & MF_NOBLOOD) && + !(thing->flags2 & MF2_REFLECTIVE) && + !(thing->flags2 & MF2_INVULNERABLE) && + !(tmthing->type == MT_TELOTHER_FX1) && + !(tmthing->type == MT_TELOTHER_FX2) && + !(tmthing->type == MT_TELOTHER_FX3) && + !(tmthing->type == MT_TELOTHER_FX4) && + !(tmthing->type == MT_TELOTHER_FX5) && (P_Random() < 192)) + { + P_BloodSplatter(tmthing->x, tmthing->y, tmthing->z, thing); + } + P_DamageMobj(thing, tmthing, tmthing->target, damage); + } + return (false); + } + if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH)) + { // Push thing + thing->momx += tmthing->momx >> 2; + thing->momy += tmthing->momy >> 2; + } + // Check for special thing + if (thing->flags & MF_SPECIAL) + { + solid = (thing->flags & MF_SOLID) != 0; + if (tmflags & MF_PICKUP) + { // Can be picked up by tmthing + P_TouchSpecialThing(thing, tmthing); // Can remove thing + } + return (!solid); + } + return (!(thing->flags & MF_SOLID)); +} + +//--------------------------------------------------------------------------- +// +// PIT_CheckOnmobjZ +// +//--------------------------------------------------------------------------- + +boolean PIT_CheckOnmobjZ(mobj_t * thing) +{ + fixed_t blockdist; + + if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) + { // Can't hit thing + return (true); + } + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { // Didn't hit thing + return (true); + } + if (thing == tmthing) + { // Don't clip against self + return (true); + } + if (tmthing->z > thing->z + thing->height) + { + return (true); + } + else if (tmthing->z + tmthing->height < thing->z) + { // under thing + return (true); + } + if (thing->flags & MF_SOLID) + { + onmobj = thing; + } + return (!(thing->flags & MF_SOLID)); +} + +/* +=============================================================================== + + MOVEMENT CLIPPING + +=============================================================================== +*/ + +//---------------------------------------------------------------------------- +// +// FUNC P_TestMobjLocation +// +// Returns true if the mobj is not blocked by anything at its current +// location, otherwise returns false. +// +//---------------------------------------------------------------------------- + +boolean P_TestMobjLocation(mobj_t * mobj) +{ + int flags; + + flags = mobj->flags; + mobj->flags &= ~MF_PICKUP; + if (P_CheckPosition(mobj, mobj->x, mobj->y)) + { // XY is ok, now check Z + mobj->flags = flags; + if ((mobj->z < mobj->floorz) + || (mobj->z + mobj->height > mobj->ceilingz)) + { // Bad Z + return (false); + } + return (true); + } + mobj->flags = flags; + return (false); +} + +/* +================== += += P_CheckPosition += += This is purely informative, nothing is modified (except things picked up) + +in: +a mobj_t (can be valid or invalid) +a position to be checked (doesn't need to be related to the mobj_t->x,y) + +during: +special things are touched if MF_PICKUP +early out on solid lines? + +out: +newsubsec +floorz +ceilingz +tmdropoffz = the lowest point contacted (monsters won't move to a dropoff) +speciallines[] +numspeciallines +mobj_t *BlockingMobj = pointer to thing that blocked position (NULL if not +blocked, or blocked by a line). + +================== +*/ + +boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + +// +// the base floor / ceiling is from the subsector that contains the +// point. Any contacted lines the step closer together will adjust them +// + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + tmfloorpic = newsubsec->sector->floorpic; + + validcount++; + numspechit = 0; + + if (tmflags & MF_NOCLIP && !(tmflags & MF_SKULLFLY)) + { + return true; + } + +// +// check things first, possibly picking things up +// the bounding box is extended by MAXRADIUS because mobj_ts are grouped +// into mapblocks based on their origin point, and can overlap into adjacent +// blocks by up to MAXRADIUS units +// + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + BlockingMobj = NULL; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) + return false; +// +// check lines +// + if (tmflags & MF_NOCLIP) + { + return true; + } + + BlockingMobj = NULL; + xl = (tmbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockLinesIterator(bx, by, PIT_CheckLine)) + return false; + return true; +} + +//============================================================================= +// +// P_CheckOnmobj(mobj_t *thing) +// +// Checks if the new Z position is legal +//============================================================================= + +mobj_t *P_CheckOnmobj(mobj_t * thing) +{ + int xl, xh, yl, yh, bx, by; + subsector_t *newsubsec; + fixed_t x; + fixed_t y; + mobj_t oldmo; + + x = thing->x; + y = thing->y; + tmthing = thing; + tmflags = thing->flags; + oldmo = *thing; // save the old mobj before the fake zmovement + P_FakeZMovement(tmthing); + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector(x, y); + ceilingline = NULL; + +// +// the base floor / ceiling is from the subsector that contains the +// point. Any contacted lines the step closer together will adjust them +// + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + tmfloorpic = newsubsec->sector->floorpic; + + validcount++; + numspechit = 0; + + if (tmflags & MF_NOCLIP) + return NULL; + +// +// check things first, possibly picking things up +// the bounding box is extended by MAXRADIUS because mobj_ts are grouped +// into mapblocks based on their origin point, and can overlap into adjacent +// blocks by up to MAXRADIUS units +// + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + if (!P_BlockThingsIterator(bx, by, PIT_CheckOnmobjZ)) + { + *tmthing = oldmo; + return onmobj; + } + *tmthing = oldmo; + return NULL; +} + +//============================================================================= +// +// P_FakeZMovement +// +// Fake the zmovement so that we can check if a move is legal +//============================================================================= + +void P_FakeZMovement(mobj_t * mo) +{ + int dist; + int delta; +// +// adjust height +// + mo->z += mo->momz; + if (mo->flags & MF_FLOAT && mo->target) + { // float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = + P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + if (delta < 0 && dist < -(delta * 3)) + mo->z -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->z += FLOATSPEED; + } + } + if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) + && leveltime & 2) + { + mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; + } + +// +// clip movement +// + if (mo->z <= mo->floorz) + { // Hit the floor + mo->z = mo->floorz; + if (mo->momz < 0) + { + mo->momz = 0; + } + if (mo->flags & MF_SKULLFLY) + { // The skull slammed into something + mo->momz = -mo->momz; + } + if (mo->info->crashstate && (mo->flags & MF_CORPSE)) + { + return; + } + } + else if (mo->flags2 & MF2_LOGRAV) + { + if (mo->momz == 0) + mo->momz = -(GRAVITY >> 3) * 2; + else + mo->momz -= GRAVITY >> 3; + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + if (mo->momz == 0) + mo->momz = -GRAVITY * 2; + else + mo->momz -= GRAVITY; + } + + if (mo->z + mo->height > mo->ceilingz) + { // hit the ceiling + if (mo->momz > 0) + mo->momz = 0; + mo->z = mo->ceilingz - mo->height; + if (mo->flags & MF_SKULLFLY) + { // the skull slammed into something + mo->momz = -mo->momz; + } + } +} + +//=========================================================================== +// +// CheckForPushSpecial +// +//=========================================================================== + +static void CheckForPushSpecial(line_t * line, int side, mobj_t * mobj) +{ + if (line->special) + { + if (mobj->flags2 & MF2_PUSHWALL) + { + P_ActivateLine(line, mobj, side, SPAC_PUSH); + } + else if (mobj->flags2 & MF2_IMPACT) + { + P_ActivateLine(line, mobj, side, SPAC_IMPACT); + } + } +} + +/* +=================== += += P_TryMove += += Attempt to move to a new position, crossing special lines unless MF_TELEPORT += is set += +=================== +*/ + +boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y) +{ + fixed_t oldx, oldy; + int side, oldside; + line_t *ld; + + floatok = false; + if (!P_CheckPosition(thing, x, y)) + { // Solid wall or thing + if (!BlockingMobj || BlockingMobj->player || !thing->player) + { + goto pushline; + } + else if (BlockingMobj->z + BlockingMobj->height - thing->z + > 24 * FRACUNIT + || (BlockingMobj->subsector->sector->ceilingheight + - (BlockingMobj->z + BlockingMobj->height) < + thing->height) + || (tmceilingz - (BlockingMobj->z + BlockingMobj->height) < + thing->height)) + { + goto pushline; + } + } + if (!(thing->flags & MF_NOCLIP)) + { + if (tmceilingz - tmfloorz < thing->height) + { // Doesn't fit + goto pushline; + } + floatok = true; + if (!(thing->flags & MF_TELEPORT) + && tmceilingz - thing->z < thing->height + && thing->type != MT_LIGHTNING_CEILING + && !(thing->flags2 & MF2_FLY)) + { // mobj must lower itself to fit + goto pushline; + } + if (thing->flags2 & MF2_FLY) + { + if (thing->z + thing->height > tmceilingz) + { + thing->momz = -8 * FRACUNIT; + goto pushline; + } + else if (thing->z < tmfloorz + && tmfloorz - tmdropoffz > 24 * FRACUNIT) + { + thing->momz = 8 * FRACUNIT; + goto pushline; + } + } + if (!(thing->flags & MF_TELEPORT) + // The Minotaur floor fire (MT_MNTRFX2) can step up any amount + && thing->type != MT_MNTRFX2 && thing->type != MT_LIGHTNING_FLOOR + && tmfloorz - thing->z > 24 * FRACUNIT) + { + goto pushline; + } + if (!(thing->flags & (MF_DROPOFF | MF_FLOAT)) && + (tmfloorz - tmdropoffz > 24 * FRACUNIT) && + !(thing->flags2 & MF2_BLASTED)) + { // Can't move over a dropoff unless it's been blasted + return (false); + } + if (thing->flags2 & MF2_CANTLEAVEFLOORPIC + && (tmfloorpic != thing->subsector->sector->floorpic + || tmfloorz - thing->z != 0)) + { // must stay within a sector of a certain floor type + return false; + } + } + +// +// the move is ok, so link the thing into its new position +// + P_UnsetThingPosition(thing); + + oldx = thing->x; + oldy = thing->y; + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->floorpic = tmfloorpic; + thing->x = x; + thing->y = y; + + P_SetThingPosition(thing); + + if (thing->flags2 & MF2_FLOORCLIP) + { + if (thing->z == thing->subsector->sector->floorheight + && P_GetThingFloorType(thing) >= FLOOR_LIQUID) + { + thing->floorclip = 10 * FRACUNIT; + } + else + { + thing->floorclip = 0; + } + } + +// +// if any special lines were hit, do the effect +// + if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) + { + while (numspechit > 0) + { + numspechit--; + // see if the line was crossed + ld = spechit[numspechit]; + side = P_PointOnLineSide(thing->x, thing->y, ld); + oldside = P_PointOnLineSide(oldx, oldy, ld); + if (side != oldside) + { + if (ld->special) + { + if (thing->player) + { + P_ActivateLine(ld, thing, oldside, SPAC_CROSS); + } + else if (thing->flags2 & MF2_MCROSS) + { + P_ActivateLine(ld, thing, oldside, SPAC_MCROSS); + } + else if (thing->flags2 & MF2_PCROSS) + { + P_ActivateLine(ld, thing, oldside, SPAC_PCROSS); + } + } + } + } + } + return true; + + pushline: + if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) + { + int numSpecHitTemp; + + if (tmthing->flags2 & MF2_BLASTED) + { + P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); + } + numSpecHitTemp = numspechit; + while (numSpecHitTemp > 0) + { + numSpecHitTemp--; + // see if the line was crossed + ld = spechit[numSpecHitTemp]; + side = P_PointOnLineSide(thing->x, thing->y, ld); + CheckForPushSpecial(ld, side, thing); + } + } + return false; +} + +/* +================== += += P_ThingHeightClip += += Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, += anf possibly thing->z += += This is called for all nearby monsters whenever a sector changes height += += If the thing doesn't fit, the z will be set to the lowest value and += false will be returned +================== +*/ + +boolean P_ThingHeightClip(mobj_t * thing) +{ + boolean onfloor; + + onfloor = (thing->z == thing->floorz); + + P_CheckPosition(thing, thing->x, thing->y); + // what about stranding a monster partially off an edge? + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->floorpic = tmfloorpic; + + if (onfloor) + { // walking monsters rise and fall with the floor + if ((thing->z - thing->floorz < 9 * FRACUNIT) + || (thing->flags & MF_NOGRAVITY)) + { + thing->z = thing->floorz; + } + } + else + { // don't adjust a floating monster unless forced to + if (thing->z + thing->height > thing->ceilingz) + thing->z = thing->ceilingz - thing->height; + } + + if (thing->ceilingz - thing->floorz < thing->height) + return false; + + return true; +} + + +/* +============================================================================== + + SLIDE MOVE + +Allows the player to slide along any angled walls + +============================================================================== +*/ + +fixed_t bestslidefrac, secondslidefrac; +line_t *bestslideline, *secondslideline; +mobj_t *slidemo; + +fixed_t tmxmove, tmymove; + +/* +================== += += P_HitSlideLine += += Adjusts the xmove / ymove so that the next move will slide along the wall +================== +*/ + +void P_HitSlideLine(line_t * ld) +{ + int side; + angle_t lineangle, moveangle, deltaangle; + fixed_t movelen, newlen; + + + if (ld->slopetype == ST_HORIZONTAL) + { + tmymove = 0; + return; + } + if (ld->slopetype == ST_VERTICAL) + { + tmxmove = 0; + return; + } + + side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); + + lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + if (side == 1) + lineangle += ANG180; + moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); + deltaangle = moveangle - lineangle; + if (deltaangle > ANG180) + deltaangle += ANG180; +// I_Error ("SlideLine: ang>ANG180"); + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance(tmxmove, tmymove); + newlen = FixedMul(movelen, finecosine[deltaangle]); + tmxmove = FixedMul(newlen, finecosine[lineangle]); + tmymove = FixedMul(newlen, finesine[lineangle]); +} + +/* +============== += += PTR_SlideTraverse += +============== +*/ + +boolean PTR_SlideTraverse(intercept_t * in) +{ + line_t *li; + + if (!in->isaline) + I_Error("PTR_SlideTraverse: not a line?"); + + li = in->d.line; + if (!(li->flags & ML_TWOSIDED)) + { + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) + return true; // don't hit the back side + goto isblocking; + } + + P_LineOpening(li); // set openrange, opentop, openbottom + if (openrange < slidemo->height) + goto isblocking; // doesn't fit + + if (opentop - slidemo->z < slidemo->height) + goto isblocking; // mobj is too high + + if (openbottom - slidemo->z > 24 * FRACUNIT) + goto isblocking; // too big a step up + + return true; // this line doesn't block movement + +// the line does block movement, see if it is closer than best so far + isblocking: + if (in->frac < bestslidefrac) + { + secondslidefrac = bestslidefrac; + secondslideline = bestslideline; + bestslidefrac = in->frac; + bestslideline = li; + } + + return false; // stop +} + + +/* +================== += += P_SlideMove += += The momx / momy move is bad, so try to slide along a wall += += Find the first line hit, move flush to it, and slide along it += += This is a kludgy mess. +================== +*/ + +void P_SlideMove(mobj_t * mo) +{ + fixed_t leadx, leady; + fixed_t trailx, traily; + fixed_t newx, newy; + int hitcount; + + slidemo = mo; + hitcount = 0; + retry: + if (++hitcount == 3) + goto stairstep; // don't loop forever + +// +// trace along the three leading corners +// + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT + 1; + + P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + +// +// move up to the wall +// + if (bestslidefrac == FRACUNIT + 1) + { // the move must have hit the middle, so stairstep + stairstep: + if (!P_TryMove(mo, mo->x, mo->y + mo->momy)) + { + P_TryMove(mo, mo->x + mo->momx, mo->y); + } + return; + } + + bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit + if (bestslidefrac > 0) + { + newx = FixedMul(mo->momx, bestslidefrac); + newy = FixedMul(mo->momy, bestslidefrac); + if (!P_TryMove(mo, mo->x + newx, mo->y + newy)) + goto stairstep; + } + +// +// now continue along the wall +// + bestslidefrac = FRACUNIT - (bestslidefrac + 0x800); // remainder + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; + if (bestslidefrac <= 0) + return; + + tmxmove = FixedMul(mo->momx, bestslidefrac); + tmymove = FixedMul(mo->momy, bestslidefrac); + + P_HitSlideLine(bestslideline); // clip the moves + + mo->momx = tmxmove; + mo->momy = tmymove; + + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove)) + { + goto retry; + } +} + +//============================================================================ +// +// P_InitSlideLine +// +//============================================================================ + +void P_InitSlideLine(void) +{ + // use relevant parts from first bestslideline in demo1 (hexen.wad) + static vertex_t initvertex1 = {-77594624, 37748736}; + static line_t initslideline = {&initvertex1, NULL, 0, 6291456, 0, 0, 0, 0, + 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0 }, 0, NULL, NULL, 0, NULL}; + + if (bestslideline == NULL) + { + bestslideline = &initslideline; + } +} + +//============================================================================ +// +// PTR_BounceTraverse +// +//============================================================================ + +boolean PTR_BounceTraverse(intercept_t * in) +{ + line_t *li; + + if (!in->isaline) + I_Error("PTR_BounceTraverse: not a line?"); + + li = in->d.line; + if (!(li->flags & ML_TWOSIDED)) + { + if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) + return true; // don't hit the back side + goto bounceblocking; + } + + P_LineOpening(li); // set openrange, opentop, openbottom + if (openrange < slidemo->height) + goto bounceblocking; // doesn't fit + + if (opentop - slidemo->z < slidemo->height) + goto bounceblocking; // mobj is too high + return true; // this line doesn't block movement + +// the line does block movement, see if it is closer than best so far + bounceblocking: + if (in->frac < bestslidefrac) + { + secondslidefrac = bestslidefrac; + secondslideline = bestslideline; + bestslidefrac = in->frac; + bestslideline = li; + } + return false; // stop +} + +//============================================================================ +// +// P_BounceWall +// +//============================================================================ + +void P_BounceWall(mobj_t * mo) +{ + fixed_t leadx, leady; + int side; + angle_t lineangle, moveangle, deltaangle; + fixed_t movelen; + + slidemo = mo; + +// +// trace along the three leading corners +// + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + } + else + { + leadx = mo->x - mo->radius; + } + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + } + else + { + leady = mo->y - mo->radius; + } + bestslidefrac = FRACUNIT + 1; + P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_BounceTraverse); + + // P_BounceWall call on a tall sector after fresh game start + // without the player sliding along any walls before. + // For more details check: + // https://github.com/chocolate-doom/chocolate-doom/issues/1732 + // https://github.com/chocolate-doom/chocolate-doom/issues/1160 + if (bestslideline == NULL) + { + I_Error("P_BounceWall: No bestslideline was set. Try bumping walls."); + } + + side = P_PointOnLineSide(mo->x, mo->y, bestslideline); + lineangle = R_PointToAngle2(0, 0, bestslideline->dx, bestslideline->dy); + if (side == 1) + lineangle += ANG180; + moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); + deltaangle = (2 * lineangle) - moveangle; +// if (deltaangle > ANG180) +// deltaangle += ANG180; +// I_Error ("SlideLine: ang>ANG180"); + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance(mo->momx, mo->momy); + movelen = FixedMul(movelen, 0.75 * FRACUNIT); // friction + if (movelen < FRACUNIT) + movelen = 2 * FRACUNIT; + mo->momx = FixedMul(movelen, finecosine[deltaangle]); + mo->momy = FixedMul(movelen, finesine[deltaangle]); +} + + +/* +============================================================================== + + P_LineAttack + +============================================================================== +*/ + + +mobj_t *PuffSpawned; +mobj_t *linetarget; // who got hit (or NULL) +mobj_t *shootthing; +fixed_t shootz; // height if not aiming up or down + // ???: use slope for monsters? +int la_damage; +fixed_t attackrange; + +fixed_t aimslope; + + +/* +=============================================================================== += += PTR_AimTraverse += += Sets linetaget and aimslope when a target is aimed at +=============================================================================== +*/ + +boolean PTR_AimTraverse(intercept_t * in) +{ + line_t *li; + mobj_t *th; + fixed_t slope, thingtopslope, thingbottomslope; + fixed_t dist; + + if (in->isaline) + { + li = in->d.line; + if (!(li->flags & ML_TWOSIDED)) + return false; // stop +// +// crosses a two sided line +// a two sided line will restrict the possible target ranges + P_LineOpening(li); + + if (openbottom >= opentop) + return false; // stop + + dist = FixedMul(attackrange, in->frac); + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - shootz, dist); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - shootz, dist); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // shot continues + } + +// +// shoot a thing +// + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + if (!(th->flags & MF_SHOOTABLE)) + { // corpse or something + return true; + } + if (th->player && netgame && !deathmatch) + { // don't aim at fellow co-op players + return true; + } + +// check angles to see if the thing can be aimed at + + dist = FixedMul(attackrange, in->frac); + thingtopslope = FixedDiv(th->z + th->height - shootz, dist); + if (thingtopslope < bottomslope) + return true; // shot over the thing + thingbottomslope = FixedDiv(th->z - shootz, dist); + if (thingbottomslope > topslope) + return true; // shot under the thing + +// +// this thing can be hit! +// + if (thingtopslope > topslope) + thingtopslope = topslope; + if (thingbottomslope < bottomslope) + thingbottomslope = bottomslope; + + aimslope = (thingtopslope + thingbottomslope) / 2; + linetarget = th; + + return false; // don't go any farther +} + + +/* +============================================================================== += += PTR_ShootTraverse += +============================================================================== +*/ + +boolean PTR_ShootTraverse(intercept_t * in) +{ + fixed_t x, y, z; + fixed_t frac; + line_t *li; + mobj_t *th; + fixed_t slope; + fixed_t dist; + fixed_t thingtopslope, thingbottomslope; + + if (in->isaline) + { + li = in->d.line; + if (li->special) + { + P_ActivateLine(li, shootthing, 0, SPAC_IMPACT); +// P_ShootSpecialLine (shootthing, li); + } + if (!(li->flags & ML_TWOSIDED)) + goto hitline; + +// +// crosses a two sided line +// + P_LineOpening(li); + + dist = FixedMul(attackrange, in->frac); + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - shootz, dist); + if (slope > aimslope) + goto hitline; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - shootz, dist); + if (slope < aimslope) + goto hitline; + } + + return true; // shot continues +// +// hit line +// + hitline: + // position a bit closer + frac = in->frac - FixedDiv(4 * FRACUNIT, attackrange); + x = trace.x + FixedMul(trace.dx, frac); + y = trace.y + FixedMul(trace.dy, frac); + z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); + + if (li->frontsector->ceilingpic == skyflatnum) + { + if (z > li->frontsector->ceilingheight) + return false; // don't shoot the sky! + if (li->backsector && li->backsector->ceilingpic == skyflatnum) + return false; // it's a sky hack wall + } + + P_SpawnPuff(x, y, z); + return false; // don't go any farther + } + +// +// shoot a thing +// + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + if (!(th->flags & MF_SHOOTABLE)) + return true; // corpse or something + +// +// check for physical attacks on a ghost +// +/* FIX: Impliment Heretic 2 weapons here + if(th->flags&MF_SHADOW && shootthing->player->readyweapon == wp_staff) + { + return(true); + } +*/ + +// check angles to see if the thing can be aimed at + dist = FixedMul(attackrange, in->frac); + thingtopslope = FixedDiv(th->z + th->height - shootz, dist); + if (thingtopslope < aimslope) + return true; // shot over the thing + thingbottomslope = FixedDiv(th->z - shootz, dist); + if (thingbottomslope > aimslope) + return true; // shot under the thing + +// +// hit thing +// + // position a bit closer + frac = in->frac - FixedDiv(10 * FRACUNIT, attackrange); + x = trace.x + FixedMul(trace.dx, frac); + y = trace.y + FixedMul(trace.dy, frac); + z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); + P_SpawnPuff(x, y, z); + if (la_damage) + { + if (!(in->d.thing->flags & MF_NOBLOOD) && + !(in->d.thing->flags2 & MF2_INVULNERABLE)) + { + if (PuffType == MT_AXEPUFF || PuffType == MT_AXEPUFF_GLOW) + { + P_BloodSplatter2(x, y, z, in->d.thing); + } + if (P_Random() < 192) + { + P_BloodSplatter(x, y, z, in->d.thing); + } + } + if (PuffType == MT_FLAMEPUFF2) + { // Cleric FlameStrike does fire damage + P_DamageMobj(th, &LavaInflictor, shootthing, la_damage); + } + else + { + P_DamageMobj(th, shootthing, shootthing, la_damage); + } + } + return (false); // don't go any farther +} + +/* +================= += += P_AimLineAttack += +================= +*/ + +fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance) +{ + fixed_t x2, y2; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; + shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; + topslope = 100 * FRACUNIT / 160; // can't shoot outside view angles + bottomslope = -100 * FRACUNIT / 160; + attackrange = distance; + linetarget = NULL; + + P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + PTR_AimTraverse); + + if (linetarget) + return aimslope; + return 0; +} + + + +/* +================= += += P_LineAttack += += if damage == 0, it is just a test trace that will leave linetarget set += +================= +*/ + +void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, + int damage) +{ + fixed_t x2, y2; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + la_damage = damage; + x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; + shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; + shootz -= t1->floorclip; + attackrange = distance; + aimslope = slope; + + if (P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + PTR_ShootTraverse)) + { + switch (PuffType) + { + case MT_PUNCHPUFF: + S_StartSound(t1, SFX_FIGHTER_PUNCH_MISS); + break; + case MT_HAMMERPUFF: + case MT_AXEPUFF: + case MT_AXEPUFF_GLOW: + S_StartSound(t1, SFX_FIGHTER_HAMMER_MISS); + break; + case MT_FLAMEPUFF: + P_SpawnPuff(x2, y2, shootz + FixedMul(slope, distance)); + break; + default: + break; + } + } +} + +/* +============================================================================== + + USE LINES + +============================================================================== +*/ + +mobj_t *usething; + +boolean PTR_UseTraverse(intercept_t * in) +{ + int sound; + fixed_t pheight; + + if (!in->d.line->special) + { + P_LineOpening(in->d.line); + if (openrange <= 0) + { + if (usething->player) + { + switch (usething->player->class) + { + case PCLASS_FIGHTER: + sound = SFX_PLAYER_FIGHTER_FAILED_USE; + break; + case PCLASS_CLERIC: + sound = SFX_PLAYER_CLERIC_FAILED_USE; + break; + case PCLASS_MAGE: + sound = SFX_PLAYER_MAGE_FAILED_USE; + break; + case PCLASS_PIG: + sound = SFX_PIG_ACTIVE1; + break; + default: + sound = SFX_NONE; + break; + } + S_StartSound(usething, sound); + } + return false; // can't use through a wall + } + if (usething->player) + { + pheight = usething->z + (usething->height / 2); + if ((opentop < pheight) || (openbottom > pheight)) + { + switch (usething->player->class) + { + case PCLASS_FIGHTER: + sound = SFX_PLAYER_FIGHTER_FAILED_USE; + break; + case PCLASS_CLERIC: + sound = SFX_PLAYER_CLERIC_FAILED_USE; + break; + case PCLASS_MAGE: + sound = SFX_PLAYER_MAGE_FAILED_USE; + break; + case PCLASS_PIG: + sound = SFX_PIG_ACTIVE1; + break; + default: + sound = SFX_NONE; + break; + } + S_StartSound(usething, sound); + } + } + return true; // not a special line, but keep checking + } + + if (P_PointOnLineSide(usething->x, usething->y, in->d.line) == 1) + return false; // don't use back sides + +// P_UseSpecialLine (usething, in->d.line); + P_ActivateLine(in->d.line, usething, 0, SPAC_USE); + + return false; // can't use for than one special line in a row +} + + +/* +================ += += P_UseLines += += Looks for special lines in front of the player to activate +================ +*/ + +void P_UseLines(player_t * player) +{ + int angle; + fixed_t x1, y1, x2, y2; + + usething = player->mo; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; + y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; + + P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse); +} + +//========================================================================== +// +// PTR_PuzzleItemTraverse +// +//========================================================================== + +#define USE_PUZZLE_ITEM_SPECIAL 129 + +static mobj_t *PuzzleItemUser; +static int PuzzleItemType; +static boolean PuzzleActivated; + +boolean PTR_PuzzleItemTraverse(intercept_t * in) +{ + mobj_t *mobj; + byte args[3]; + int sound; + + if (in->isaline) + { // Check line + if (in->d.line->special != USE_PUZZLE_ITEM_SPECIAL) + { + P_LineOpening(in->d.line); + if (openrange <= 0) + { + sound = SFX_NONE; + if (PuzzleItemUser->player) + { + switch (PuzzleItemUser->player->class) + { + case PCLASS_FIGHTER: + sound = SFX_PUZZLE_FAIL_FIGHTER; + break; + case PCLASS_CLERIC: + sound = SFX_PUZZLE_FAIL_CLERIC; + break; + case PCLASS_MAGE: + sound = SFX_PUZZLE_FAIL_MAGE; + break; + default: + sound = SFX_NONE; + break; + } + } + S_StartSound(PuzzleItemUser, sound); + return false; // can't use through a wall + } + return true; // Continue searching + } + if (P_PointOnLineSide(PuzzleItemUser->x, PuzzleItemUser->y, + in->d.line) == 1) + { // Don't use back sides + return false; + } + if (PuzzleItemType != in->d.line->arg1) + { // Item type doesn't match + return false; + } + + // Construct an args[] array that would contain the values from + // the line that would be passed by Vanilla Hexen. + args[0] = in->d.line->arg3; + args[1] = in->d.line->arg4; + args[2] = in->d.line->arg5; + + P_StartACS(in->d.line->arg2, 0, args, PuzzleItemUser, in->d.line, 0); + in->d.line->special = 0; + PuzzleActivated = true; + return false; // Stop searching + } + // Check thing + mobj = in->d.thing; + if (mobj->special != USE_PUZZLE_ITEM_SPECIAL) + { // Wrong special + return true; + } + if (PuzzleItemType != mobj->args[0]) + { // Item type doesn't match + return true; + } + + P_StartACS(mobj->args[1], 0, &mobj->args[2], PuzzleItemUser, NULL, 0); + mobj->special = 0; + PuzzleActivated = true; + return false; // Stop searching +} + +//========================================================================== +// +// P_UsePuzzleItem +// +// Returns true if the puzzle item was used on a line or a thing. +// +//========================================================================== + +boolean P_UsePuzzleItem(player_t * player, int itemType) +{ + int angle; + fixed_t x1, y1, x2, y2; + + PuzzleItemType = itemType; + PuzzleItemUser = player->mo; + PuzzleActivated = false; + angle = player->mo->angle >> ANGLETOFINESHIFT; + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; + y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; + P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + PTR_PuzzleItemTraverse); + return PuzzleActivated; +} + +/* +============================================================================== + + RADIUS ATTACK + +============================================================================== +*/ + +mobj_t *bombsource; +mobj_t *bombspot; +int bombdamage; +int bombdistance; +boolean DamageSource; + +/* +================= += += PIT_RadiusAttack += += Source is the creature that casued the explosion at spot +================= +*/ + +boolean PIT_RadiusAttack(mobj_t * thing) +{ + fixed_t dx, dy, dist; + int damage; + + if (!(thing->flags & MF_SHOOTABLE)) + { + return true; + } +// if(thing->flags2&MF2_BOSS) +// { // Bosses take no damage from PIT_RadiusAttack +// return(true); +// } + if (!DamageSource && thing == bombsource) + { // don't damage the source of the explosion + return true; + } + if (abs((thing->z - bombspot->z) >> FRACBITS) > 2 * bombdistance) + { // too high/low + return true; + } + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + dist = dx > dy ? dx : dy; + dist = (dist - thing->radius) >> FRACBITS; + if (dist < 0) + { + dist = 0; + } + if (dist >= bombdistance) + { // Out of range + return true; + } + if (P_CheckSight(thing, bombspot)) + { // OK to damage, target is in direct path + damage = (bombdamage * (bombdistance - dist) / bombdistance) + 1; + if (thing->player) + { + damage >>= 2; + } + P_DamageMobj(thing, bombspot, bombsource, damage); + } + return (true); +} + +/* +================= += += P_RadiusAttack += += Source is the creature that caused the explosion at spot +================= +*/ + +void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage, int distance, + boolean damageSource) +{ + int x, y, xl, xh, yl, yh; + fixed_t dist; + + dist = (distance + MAXRADIUS) << FRACBITS; + yh = (spot->y + dist - bmaporgy) >> MAPBLOCKSHIFT; + yl = (spot->y - dist - bmaporgy) >> MAPBLOCKSHIFT; + xh = (spot->x + dist - bmaporgx) >> MAPBLOCKSHIFT; + xl = (spot->x - dist - bmaporgx) >> MAPBLOCKSHIFT; + bombspot = spot; + bombsource = source; + bombdamage = damage; + bombdistance = distance; + DamageSource = damageSource; + for (y = yl; y <= yh; y++) + { + for (x = xl; x <= xh; x++) + { + P_BlockThingsIterator(x, y, PIT_RadiusAttack); + } + } +} + +/* +============================================================================== + + SECTOR HEIGHT CHANGING + += After modifying a sectors floor or ceiling height, call this += routine to adjust the positions of all things that touch the += sector. += += If anything doesn't fit anymore, true will be returned. += If crunch is true, they will take damage as they are being crushed += If Crunch is false, you should set the sector height back the way it += was and call P_ChangeSector again to undo the changes +============================================================================== +*/ + +int crushchange; +boolean nofit; + +/* +=============== += += PIT_ChangeSector += +=============== +*/ + +boolean PIT_ChangeSector(mobj_t * thing) +{ + mobj_t *mo; + + if (P_ThingHeightClip(thing)) + return true; // keep checking + + // crunch bodies to giblets + if ((thing->flags & MF_CORPSE) && (thing->health <= 0)) + { + if (thing->flags & MF_NOBLOOD) + { + P_RemoveMobj(thing); + } + else + { + if (thing->state != &states[S_GIBS1]) + { + P_SetMobjState(thing, S_GIBS1); + thing->height = 0; + thing->radius = 0; + S_StartSound(thing, SFX_PLAYER_FALLING_SPLAT); + } + } + return true; // keep checking + } + + // crunch dropped items + if (thing->flags2 & MF2_DROPPED) + { + P_RemoveMobj(thing); + return true; // keep checking + } + + if (!(thing->flags & MF_SHOOTABLE)) + return true; // assume it is bloody gibs or something + + nofit = true; + if (crushchange && !(leveltime & 3)) + { + P_DamageMobj(thing, NULL, NULL, crushchange); + // spray blood in a random direction + if ((!(thing->flags & MF_NOBLOOD)) && + (!(thing->flags2 & MF2_INVULNERABLE))) + { + mo = P_SpawnMobj(thing->x, thing->y, thing->z + thing->height / 2, + MT_BLOOD); + mo->momx = P_SubRandom() << 12; + mo->momy = P_SubRandom() << 12; + } + } + + return true; // keep checking (crush other things) +} + +/* +=============== += += P_ChangeSector += +=============== +*/ + +boolean P_ChangeSector(sector_t * sector, int crunch) +{ + int x, y; + + nofit = false; + crushchange = crunch; + +// recheck heights for all things near the moving sector + + for (x = sector->blockbox[BOXLEFT]; x <= sector->blockbox[BOXRIGHT]; x++) + for (y = sector->blockbox[BOXBOTTOM]; y <= sector->blockbox[BOXTOP]; + y++) + P_BlockThingsIterator(x, y, PIT_ChangeSector); + + + return nofit; +} diff --git a/games/NXDoom/src/hexen/p_maputl.c b/games/NXDoom/src/hexen/p_maputl.c new file mode 100644 index 00000000000..1ed0aa968e3 --- /dev/null +++ b/games/NXDoom/src/hexen/p_maputl.c @@ -0,0 +1,1072 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "m_bbox.h" +#include "m_misc.h" +#include "p_local.h" + +static mobj_t *RoughBlockCheck(mobj_t * mo, int index); + +/* +=================== += += P_AproxDistance += += Gives an estimation of distance (not exact) += +=================== +*/ + +fixed_t P_AproxDistance(fixed_t dx, fixed_t dy) +{ + dx = abs(dx); + dy = abs(dy); + if (dx < dy) + return dx + dy - (dx >> 1); + return dx + dy - (dy >> 1); +} + + +/* +================== += += P_PointOnLineSide += += Returns 0 or 1 +================== +*/ + +int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line) +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!line->dx) + { + if (x <= line->v1->x) + return line->dy > 0; + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->v1->y) + return line->dx < 0; + return line->dx > 0; + } + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = FixedMul(line->dy >> FRACBITS, dx); + right = FixedMul(dy, line->dx >> FRACBITS); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +/* +================= += += P_BoxOnLineSide += += Considers the line to be infinite += Returns side 0 or 1, -1 if box crosses the line +================= +*/ + +int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld) +{ + int p1 = 0, p2 = 0; + + switch (ld->slopetype) + { + case ST_HORIZONTAL: + p1 = tmbox[BOXTOP] > ld->v1->y; + p2 = tmbox[BOXBOTTOM] > ld->v1->y; + if (ld->dx < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + case ST_VERTICAL: + p1 = tmbox[BOXRIGHT] < ld->v1->x; + p2 = tmbox[BOXLEFT] < ld->v1->x; + if (ld->dy < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + case ST_POSITIVE: + p1 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); + break; + case ST_NEGATIVE: + p1 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); + break; + } + + if (p1 == p2) + return p1; + return -1; +} + +/* +================== += += P_PointOnDivlineSide += += Returns 0 or 1 +================== +*/ + +int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line) +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!line->dx) + { + if (x <= line->x) + return line->dy > 0; + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->y) + return line->dx < 0; + return line->dx > 0; + } + + dx = (x - line->x); + dy = (y - line->y); + +// try to quickly decide by looking at sign bits + if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000) + { + if ((line->dy ^ dx) & 0x80000000) + return 1; // (left is negative) + return 0; + } + + left = FixedMul(line->dy >> 8, dx >> 8); + right = FixedMul(dy >> 8, line->dx >> 8); + + if (right < left) + return 0; // front side + return 1; // back side +} + + + +/* +============== += += P_MakeDivline += +============== +*/ + +void P_MakeDivline(line_t * li, divline_t * dl) +{ + dl->x = li->v1->x; + dl->y = li->v1->y; + dl->dx = li->dx; + dl->dy = li->dy; +} + + +/* +=============== += += P_InterceptVector += += Returns the fractional intercept point along the first divline += += This is only called by the addthings and addlines traversers +=============== +*/ + +fixed_t P_InterceptVector(divline_t * v2, divline_t * v1) +{ +#if 1 + fixed_t frac, num, den; + + den = FixedMul(v1->dy >> 8, v2->dx) - FixedMul(v1->dx >> 8, v2->dy); + if (den == 0) + return 0; +// I_Error ("P_InterceptVector: parallel"); + num = FixedMul((v1->x - v2->x) >> 8, v1->dy) + + FixedMul((v2->y - v1->y) >> 8, v1->dx); + frac = FixedDiv(num, den); + + return frac; +#else + float frac, num, den, v1x, v1y, v1dx, v1dy, v2x, v2y, v2dx, v2dy; + + v1x = (float) v1->x / FRACUNIT; + v1y = (float) v1->y / FRACUNIT; + v1dx = (float) v1->dx / FRACUNIT; + v1dy = (float) v1->dy / FRACUNIT; + v2x = (float) v2->x / FRACUNIT; + v2y = (float) v2->y / FRACUNIT; + v2dx = (float) v2->dx / FRACUNIT; + v2dy = (float) v2->dy / FRACUNIT; + + den = v1dy * v2dx - v1dx * v2dy; + if (den == 0) + return 0; // parallel + num = (v1x - v2x) * v1dy + (v2y - v1y) * v1dx; + frac = num / den; + + return frac * FRACUNIT; +#endif +} + +/* +================== += += P_LineOpening += += Sets opentop and openbottom to the window through a two sided line += OPTIMIZE: keep this precalculated +================== +*/ + +fixed_t opentop, openbottom, openrange; +fixed_t lowfloor; + +void P_LineOpening(line_t * linedef) +{ + sector_t *front, *back; + + if (linedef->sidenum[1] == -1) + { // single sided line + openrange = 0; + return; + } + + front = linedef->frontsector; + back = linedef->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + tmfloorpic = front->floorpic; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; + tmfloorpic = back->floorpic; + } + + openrange = opentop - openbottom; +} + +/* +=============================================================================== + + THING POSITION SETTING + +=============================================================================== +*/ + +/* +=================== += += P_UnsetThingPosition += += Unlinks a thing from block map and sectors += +=================== +*/ + +void P_UnsetThingPosition(mobj_t * thing) +{ + int blockx, blocky; + + if (!(thing->flags & MF_NOSECTOR)) + { // inert things don't need to be in blockmap +// unlink from subsector + if (thing->snext) + thing->snext->sprev = thing->sprev; + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + } + + if (!(thing->flags & MF_NOBLOCKMAP)) + { // inert things don't need to be in blockmap +// unlink from block map + if (thing->bnext) + thing->bnext->bprev = thing->bprev; + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + if (blockx >= 0 && blockx < bmapwidth + && blocky >= 0 && blocky < bmapheight) + blocklinks[blocky * bmapwidth + blockx] = thing->bnext; + } + } +} + + +/* +=================== += += P_SetThingPosition += += Links a thing into both a block and a subsector based on it's x y += Sets thing->subsector properly += +=================== +*/ + +void P_SetThingPosition(mobj_t * thing) +{ + subsector_t *ss; + sector_t *sec; + int blockx, blocky; + mobj_t **link; + +// +// link into subsector +// + ss = R_PointInSubsector(thing->x, thing->y); + thing->subsector = ss; + if (!(thing->flags & MF_NOSECTOR)) + { // invisible things don't go into the sector links + sec = ss->sector; + + thing->sprev = NULL; + thing->snext = sec->thinglist; + if (sec->thinglist) + sec->thinglist->sprev = thing; + sec->thinglist = thing; + } + +// +// link into blockmap +// + if (!(thing->flags & MF_NOBLOCKMAP)) + { // inert things don't need to be in blockmap + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 + && blocky < bmapheight) + { + link = &blocklinks[blocky * bmapwidth + blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) + (*link)->bprev = thing; + *link = thing; + } + else + { // thing is off the map + thing->bnext = thing->bprev = NULL; + } + } +} + + + +/* +=============================================================================== + + BLOCK MAP ITERATORS + +For each line/thing in the given mapblock, call the passed function. +If the function returns false, exit with false without checking anything else. + +=============================================================================== +*/ + +/* +================== += += P_BlockLinesIterator += += The validcount flags are used to avoid checking lines += that are marked in multiple mapblocks, so increment validcount before += the first call to P_BlockLinesIterator, then make one or more calls to it +=================== +*/ + +boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)) +{ + int offset; + short *list; + line_t *ld; + + int i; + polyblock_t *polyLink; + seg_t **tempSeg; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return true; + offset = y * bmapwidth + x; + + polyLink = PolyBlockMap[offset]; + while (polyLink) + { + if (polyLink->polyobj) + { + if (polyLink->polyobj->validcount != validcount) + { + polyLink->polyobj->validcount = validcount; + tempSeg = polyLink->polyobj->segs; + for (i = 0; i < polyLink->polyobj->numsegs; i++, tempSeg++) + { + if ((*tempSeg)->linedef->validcount == validcount) + { + continue; + } + (*tempSeg)->linedef->validcount = validcount; + if (!func((*tempSeg)->linedef)) + { + return false; + } + } + } + } + polyLink = polyLink->next; + } + + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; // line has already been checked + ld->validcount = validcount; + + if (!func(ld)) + return false; + } + + return true; // everything was checked +} + + +/* +================== += += P_BlockThingsIterator += +================== +*/ + +boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)) +{ + mobj_t *mobj; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return true; + + LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); + + for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext) + if (!func(mobj)) + return false; + + return true; +} + +/* +=============================================================================== + + INTERCEPT ROUTINES + +=============================================================================== +*/ + +intercept_t intercepts[MAXINTERCEPTS], *intercept_p; + +divline_t trace; +boolean earlyout; +int ptflags; + +/* +================== += += PIT_AddLineIntercepts += += Looks for lines in the given block that intercept the given trace += to add to the intercepts list += A line is crossed if its endpoints are on opposite sides of the trace += Returns true if earlyout and a solid line hit +================== +*/ + +boolean PIT_AddLineIntercepts(line_t * ld) +{ + int s1, s2; + fixed_t frac; + divline_t dl; + +// avoid precision problems with two routines + if (trace.dx > FRACUNIT * 16 || trace.dy > FRACUNIT * 16 + || trace.dx < -FRACUNIT * 16 || trace.dy < -FRACUNIT * 16) + { + s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); + } + else + { + s1 = P_PointOnLineSide(trace.x, trace.y, ld); + s2 = P_PointOnLineSide(trace.x + trace.dx, trace.y + trace.dy, ld); + } + if (s1 == s2) + return true; // line isn't crossed + +// +// hit the line +// + P_MakeDivline(ld, &dl); + frac = P_InterceptVector(&trace, &dl); + if (frac < 0) + return true; // behind source + +// try to early out the check + if (earlyout && frac < FRACUNIT && !ld->backsector) + return false; // stop checking + + intercept_p->frac = frac; + intercept_p->isaline = true; + intercept_p->d.line = ld; + intercept_p++; + + return true; // continue +} + + + +/* +================== += += PIT_AddThingIntercepts += +================== +*/ + +boolean PIT_AddThingIntercepts(mobj_t * thing) +{ + fixed_t x1, y1, x2, y2; + int s1, s2; + boolean tracepositive; + divline_t dl; + fixed_t frac; + + tracepositive = (trace.dx ^ trace.dy) > 0; + + // check a corner to corner crossection for hit + + if (tracepositive) + { + x1 = thing->x - thing->radius; + y1 = thing->y + thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y - thing->radius; + } + else + { + x1 = thing->x - thing->radius; + y1 = thing->y - thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y + thing->radius; + } + s1 = P_PointOnDivlineSide(x1, y1, &trace); + s2 = P_PointOnDivlineSide(x2, y2, &trace); + if (s1 == s2) + return true; // line isn't crossed + + dl.x = x1; + dl.y = y1; + dl.dx = x2 - x1; + dl.dy = y2 - y1; + frac = P_InterceptVector(&trace, &dl); + if (frac < 0) + return true; // behind source + intercept_p->frac = frac; + intercept_p->isaline = false; + intercept_p->d.thing = thing; + intercept_p++; + + return true; // keep going +} + + +/* +==================== += += P_TraverseIntercepts += += Returns true if the traverser function returns true for all lines +==================== +*/ + +boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) +{ + int count; + fixed_t dist; + intercept_t *scan, *in; + + count = intercept_p - intercepts; + in = 0; // shut up compiler warning + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts; scan < intercept_p; scan++) + if (scan->frac < dist) + { + dist = scan->frac; + in = scan; + } + + if (dist > maxfrac) + return true; // checked everything in range +#if 0 + { // don't check these yet, ther may be others inserted + in = scan = intercepts; + for (scan = intercepts; scan < intercept_p; scan++) + if (scan->frac > maxfrac) + *in++ = *scan; + intercept_p = in; + return false; + } +#endif + + if (!func(in)) + return false; // don't bother going farther + in->frac = INT_MAX; + } + + return true; // everything was traversed +} + + + +/* +================== += += P_PathTraverse += += Traces a line from x1,y1 to x2,y2, calling the traverser function for each += Returns true if the traverser function returns true for all lines +================== +*/ + +boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, + int flags, boolean(*trav) (intercept_t *)) +{ + fixed_t xt1, yt1, xt2, yt2; + fixed_t xstep, ystep; + fixed_t partial; + fixed_t xintercept, yintercept; + int mapx, mapy, mapxstep, mapystep; + int count; + + earlyout = (flags & PT_EARLYOUT) != 0; + + validcount++; + intercept_p = intercepts; + + if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) + x1 += FRACUNIT; // don't side exactly on a line + if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) + y1 += FRACUNIT; // don't side exactly on a line + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1 >> MAPBLOCKSHIFT; + yt1 = y1 >> MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2 >> MAPBLOCKSHIFT; + yt2 = y2 >> MAPBLOCKSHIFT; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256 * FRACUNIT; + } + yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); + + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256 * FRACUNIT; + } + xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); + + +// +// step through map blocks +// Count is present to prevent a round off error from skipping the break + mapx = xt1; + mapy = yt1; + + for (count = 0; count < 64; count++) + { + if (flags & PT_ADDLINES) + { + if (!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts)) + return false; // early out + } + if (flags & PT_ADDTHINGS) + { + if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts)) + return false; // early out + } + + if (mapx == xt2 && mapy == yt2) + break; + + if ((yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ((xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + + } + + +// +// go through the sorted list +// + return P_TraverseIntercepts(trav, FRACUNIT); +} + +//=========================================================================== +// +// P_RoughMonsterSearch +// +// Searches though the surrounding mapblocks for monsters/players +// distance is in MAPBLOCKUNITS +//=========================================================================== + +mobj_t *P_RoughMonsterSearch(mobj_t * mo, int distance) +{ + int blockX; + int blockY; + int startX, startY; + int blockIndex; + int firstStop; + int secondStop; + int thirdStop; + int finalStop; + int count; + mobj_t *target; + + startX = (mo->x - bmaporgx) >> MAPBLOCKSHIFT; + startY = (mo->y - bmaporgy) >> MAPBLOCKSHIFT; + + if (startX >= 0 && startX < bmapwidth && startY >= 0 + && startY < bmapheight) + { + target = RoughBlockCheck(mo, startY * bmapwidth + startX); + if (target != NULL) + { // found a target right away + return target; + } + } + for (count = 1; count <= distance; count++) + { + blockX = startX - count; + blockY = startY - count; + + if (blockY < 0) + { + blockY = 0; + } + else if (blockY >= bmapheight) + { + blockY = bmapheight - 1; + } + if (blockX < 0) + { + blockX = 0; + } + else if (blockX >= bmapwidth) + { + blockX = bmapwidth - 1; + } + blockIndex = blockY * bmapwidth + blockX; + firstStop = startX + count; + if (firstStop < 0) + { + continue; + } + if (firstStop >= bmapwidth) + { + firstStop = bmapwidth - 1; + } + secondStop = startY + count; + if (secondStop < 0) + { + continue; + } + if (secondStop >= bmapheight) + { + secondStop = bmapheight - 1; + } + thirdStop = secondStop * bmapwidth + blockX; + secondStop = secondStop * bmapwidth + firstStop; + firstStop += blockY * bmapwidth; + finalStop = blockIndex; + + // Trace the first block section (along the top) + for (; blockIndex <= firstStop; blockIndex++) + { + target = RoughBlockCheck(mo, blockIndex); + if (target != NULL) + { + return target; + } + } + // Trace the second block section (right edge) + for (blockIndex--; blockIndex <= secondStop; blockIndex += bmapwidth) + { + target = RoughBlockCheck(mo, blockIndex); + if (target != NULL) + { + return target; + } + } + // Trace the third block section (bottom edge) + for (blockIndex -= bmapwidth; blockIndex >= thirdStop; blockIndex--) + { + target = RoughBlockCheck(mo, blockIndex); + if (target != NULL) + { + return target; + } + } + // Trace the final block section (left edge) + for (blockIndex++; blockIndex > finalStop; blockIndex -= bmapwidth) + { + target = RoughBlockCheck(mo, blockIndex); + if (target != NULL) + { + return target; + } + } + } + return NULL; +} + +//=========================================================================== +// +// RoughBlockCheck +// +//=========================================================================== + +static mobj_t *RoughBlockCheck(mobj_t * mo, int index) +{ + mobj_t *link; + mobj_t *master; + angle_t angle; + + link = blocklinks[index]; + while (link) + { + if (mo->player) // Minotaur looking around player + { + if ((link->flags & MF_COUNTKILL) || + (link->player && (link != mo))) + { + if (!(link->flags & MF_SHOOTABLE)) + { + link = link->bnext; + continue; + } + if (link->flags2 & MF2_DORMANT) + { + link = link->bnext; + continue; + } + if ((link->type == MT_MINOTAUR) && + (link->special1.m == mo)) + { + link = link->bnext; + continue; + } + if (netgame && !deathmatch && link->player) + { + link = link->bnext; + continue; + } + if (P_CheckSight(mo, link)) + { + return link; + } + } + link = link->bnext; + } + else if (mo->type == MT_MINOTAUR) // looking around minotaur + { + master = mo->special1.m; + if ((link->flags & MF_COUNTKILL) || + (link->player && (link != master))) + { + if (!(link->flags & MF_SHOOTABLE)) + { + link = link->bnext; + continue; + } + if (link->flags2 & MF2_DORMANT) + { + link = link->bnext; + continue; + } + if ((link->type == MT_MINOTAUR) && + (link->special1.m == mo->special1.m)) + { + link = link->bnext; + continue; + } + if (netgame && !deathmatch && link->player) + { + link = link->bnext; + continue; + } + if (P_CheckSight(mo, link)) + { + return link; + } + } + link = link->bnext; + } + else if (mo->type == MT_MSTAFF_FX2) // bloodscourge + { + if ((link->flags & MF_COUNTKILL || + (link->player && link != mo->target)) + && !(link->flags2 & MF2_DORMANT)) + { + if (!(link->flags & MF_SHOOTABLE)) + { + link = link->bnext; + continue; + } + if (netgame && !deathmatch && link->player) + { + link = link->bnext; + continue; + } + else if (P_CheckSight(mo, link)) + { + master = mo->target; + angle = R_PointToAngle2(master->x, master->y, + link->x, link->y) - master->angle; + angle >>= 24; + if (angle > 226 || angle < 30) + { + return link; + } + } + } + link = link->bnext; + } + else // spirits + { + if ((link->flags & MF_COUNTKILL || + (link->player && link != mo->target)) + && !(link->flags2 & MF2_DORMANT)) + { + if (!(link->flags & MF_SHOOTABLE)) + { + link = link->bnext; + continue; + } + if (netgame && !deathmatch && link->player) + { + link = link->bnext; + continue; + } + if (link == mo->target) + { + link = link->bnext; + continue; + } + else if (P_CheckSight(mo, link)) + { + return link; + } + } + link = link->bnext; + } + } + return NULL; +} diff --git a/games/NXDoom/src/hexen/p_mobj.c b/games/NXDoom/src/hexen/p_mobj.c new file mode 100644 index 00000000000..0c302ed14fe --- /dev/null +++ b/games/NXDoom/src/hexen/p_mobj.c @@ -0,0 +1,2469 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" +#include "sounds.h" + +// MACROS ------------------------------------------------------------------ + +#define MAX_TID_COUNT 200 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +void G_PlayerReborn(int player); +void P_MarkAsLeaving(mobj_t * corpse); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +void P_SpawnMapThing(mapthing_t * mthing); + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void PlayerLandedOnThing(mobj_t * mo, mobj_t * onmobj); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +mobjtype_t PuffType; +mobj_t *MissileMobj; + +fixed_t FloatBobOffsets[64] = { + 0, 51389, 102283, 152192, + 200636, 247147, 291278, 332604, + 370727, 405280, 435929, 462380, + 484378, 501712, 514213, 521763, + 524287, 521763, 514213, 501712, + 484378, 462380, 435929, 405280, + 370727, 332604, 291278, 247147, + 200636, 152192, 102283, 51389, + -1, -51390, -102284, -152193, + -200637, -247148, -291279, -332605, + -370728, -405281, -435930, -462381, + -484380, -501713, -514215, -521764, + -524288, -521764, -514214, -501713, + -484379, -462381, -435930, -405280, + -370728, -332605, -291279, -247148, + -200637, -152193, -102284, -51389 +}; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int TIDList[MAX_TID_COUNT + 1]; // +1 for termination marker +static mobj_t *TIDMobj[MAX_TID_COUNT]; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// P_SetMobjState +// +// Returns true if the mobj is still present. +// +//========================================================================== + +boolean P_SetMobjState(mobj_t * mobj, statenum_t state) +{ + state_t *st; + + if (state == S_NULL) + { // Remove mobj + mobj->state = (state_t *) S_NULL; + P_RemoveMobj(mobj); + return (false); + } + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + if (st->action) + { // Call action function + st->action(mobj, NULL, NULL); + } + return (true); +} + +//========================================================================== +// +// P_SetMobjStateNF +// +// Same as P_SetMobjState, but does not call the state function. +// +//========================================================================== + +boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state) +{ + state_t *st; + + if (state == S_NULL) + { // Remove mobj + mobj->state = (state_t *) S_NULL; + P_RemoveMobj(mobj); + return (false); + } + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC P_ExplodeMissile +// +//---------------------------------------------------------------------------- + +void P_ExplodeMissile(mobj_t * mo) +{ + mo->momx = mo->momy = mo->momz = 0; + P_SetMobjState(mo, mobjinfo[mo->type].deathstate); + //mo->tics -= P_Random()&3; + mo->flags &= ~MF_MISSILE; + + switch (mo->type) + { + case MT_SORCBALL1: + case MT_SORCBALL2: + case MT_SORCBALL3: + S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE); + break; + case MT_SORCFX1: + S_StartSound(NULL, SFX_SORCERER_HEADSCREAM); + break; + default: + if (mo->info->deathsound) + { + S_StartSound(mo, mo->info->deathsound); + } + break; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_FloorBounceMissile +// +//---------------------------------------------------------------------------- + +void P_FloorBounceMissile(mobj_t * mo) +{ + if (P_HitFloor(mo) >= FLOOR_LIQUID) + { + switch (mo->type) + { + case MT_SORCFX1: + case MT_SORCBALL1: + case MT_SORCBALL2: + case MT_SORCBALL3: + break; + default: + P_RemoveMobj(mo); + return; + } + } + switch (mo->type) + { + case MT_SORCFX1: + mo->momz = -mo->momz; // no energy absorbed + break; + case MT_SGSHARD1: + case MT_SGSHARD2: + case MT_SGSHARD3: + case MT_SGSHARD4: + case MT_SGSHARD5: + case MT_SGSHARD6: + case MT_SGSHARD7: + case MT_SGSHARD8: + case MT_SGSHARD9: + case MT_SGSHARD0: + mo->momz = FixedMul(mo->momz, -0.3 * FRACUNIT); + if (abs(mo->momz) < (FRACUNIT / 2)) + { + P_SetMobjState(mo, S_NULL); + return; + } + break; + default: + mo->momz = FixedMul(mo->momz, -0.7 * FRACUNIT); + break; + } + mo->momx = 2 * mo->momx / 3; + mo->momy = 2 * mo->momy / 3; + if (mo->info->seesound) + { + switch (mo->type) + { + case MT_SORCBALL1: + case MT_SORCBALL2: + case MT_SORCBALL3: + if (!mo->args[0]) + S_StartSound(mo, mo->info->seesound); + break; + default: + S_StartSound(mo, mo->info->seesound); + break; + } + S_StartSound(mo, mo->info->seesound); + } +// P_SetMobjState(mo, mobjinfo[mo->type].deathstate); +} + +//---------------------------------------------------------------------------- +// +// PROC P_ThrustMobj +// +//---------------------------------------------------------------------------- + +void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move) +{ + angle >>= ANGLETOFINESHIFT; + mo->momx += FixedMul(move, finecosine[angle]); + mo->momy += FixedMul(move, finesine[angle]); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_FaceMobj +// +// Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs +// to turn counter clockwise. 'delta' is set to the amount 'source' +// needs to turn. +// +//---------------------------------------------------------------------------- + +int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta) +{ + angle_t diff; + angle_t angle1; + angle_t angle2; + + angle1 = source->angle; + angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y); + if (angle2 > angle1) + { + diff = angle2 - angle1; + if (diff > ANG180) + { + *delta = ANG_MAX - diff; + return (0); + } + else + { + *delta = diff; + return (1); + } + } + else + { + diff = angle1 - angle2; + if (diff > ANG180) + { + *delta = ANG_MAX - diff; + return (1); + } + else + { + *delta = diff; + return (0); + } + } +} + +//---------------------------------------------------------------------------- +// +// +// The missile special1 field must be mobj_t *target. Returns true if +// target was tracked, false if not. +// +//---------------------------------------------------------------------------- + +boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax) +{ + int dir; + int dist; + angle_t delta; + angle_t angle; + mobj_t *target; + + target = actor->special1.m; + if (target == NULL) + { + return (false); + } + if (!(target->flags & MF_SHOOTABLE)) + { // Target died + actor->special1.m = NULL; + return (false); + } + dir = P_FaceMobj(actor, target, &delta); + if (delta > thresh) + { + delta >>= 1; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (dir) + { // Turn clockwise + actor->angle += delta; + } + else + { // Turn counter clockwise + actor->angle -= delta; + } + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(actor->info->speed, finecosine[angle]); + actor->momy = FixedMul(actor->info->speed, finesine[angle]); + if (actor->z + actor->height < target->z + || target->z + target->height < actor->z) + { // Need to seek vertically + dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); + dist = dist / actor->info->speed; + if (dist < 1) + { + dist = 1; + } + actor->momz = (target->z + (target->height >> 1) + - (actor->z + (actor->height >> 1))) / dist; + } + return (true); +} + +//---------------------------------------------------------------------------- +// +// PROC P_XYMovement +// +//---------------------------------------------------------------------------- + +#define STOPSPEED 0x1000 +#define FRICTION_NORMAL 0xe800 +#define FRICTION_LOW 0xf900 +#define FRICTION_FLY 0xeb00 + +void P_XYMovement(mobj_t * mo) +{ + fixed_t ptryx, ptryy; + player_t *player; + fixed_t xmove, ymove; + int special; + angle_t angle; + static int windTab[3] = { 2048 * 5, 2048 * 10, 2048 * 25 }; + + if (!mo->momx && !mo->momy) + { + if (mo->flags & MF_SKULLFLY) + { // A flying mobj slammed into something + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + P_SetMobjState(mo, mo->info->seestate); + } + return; + } + special = mo->subsector->sector->special; + if (mo->flags2 & MF2_WINDTHRUST) + { + switch (special) + { + case 40: + case 41: + case 42: // Wind_East + P_ThrustMobj(mo, 0, windTab[special - 40]); + break; + case 43: + case 44: + case 45: // Wind_North + P_ThrustMobj(mo, ANG90, windTab[special - 43]); + break; + case 46: + case 47: + case 48: // Wind_South + P_ThrustMobj(mo, ANG270, windTab[special - 46]); + break; + case 49: + case 50: + case 51: // Wind_West + P_ThrustMobj(mo, ANG180, windTab[special - 49]); + break; + } + } + player = mo->player; + if (mo->momx > MAXMOVE) + { + mo->momx = MAXMOVE; + } + else if (mo->momx < -MAXMOVE) + { + mo->momx = -MAXMOVE; + } + if (mo->momy > MAXMOVE) + { + mo->momy = MAXMOVE; + } + else if (mo->momy < -MAXMOVE) + { + mo->momy = -MAXMOVE; + } + xmove = mo->momx; + ymove = mo->momy; + do + { + if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2) + { + ptryx = mo->x + xmove / 2; + ptryy = mo->y + ymove / 2; + xmove >>= 1; + ymove >>= 1; + } + else + { + ptryx = mo->x + xmove; + ptryy = mo->y + ymove; + xmove = ymove = 0; + } + if (!P_TryMove(mo, ptryx, ptryy)) + { // Blocked move + if (mo->flags2 & MF2_SLIDE) + { // Try to slide along it + if (BlockingMobj == NULL) + { // Slide against wall + P_SlideMove(mo); + } + else + { // Slide against mobj + //if(P_TryMove(mo, mo->x, mo->y+mo->momy)) + if (P_TryMove(mo, mo->x, ptryy)) + { + mo->momx = 0; + } + //else if(P_TryMove(mo, mo->x+mo->momx, mo->y)) + else if (P_TryMove(mo, ptryx, mo->y)) + { + mo->momy = 0; + } + else + { + mo->momx = mo->momy = 0; + } + } + } + else if (mo->flags & MF_MISSILE) + { + if (mo->flags2 & MF2_FLOORBOUNCE) + { + if (BlockingMobj) + { + if ((BlockingMobj->flags2 & MF2_REFLECTIVE) || + ((!BlockingMobj->player) && + (!(BlockingMobj->flags & MF_COUNTKILL)))) + { + fixed_t speed; + + angle = R_PointToAngle2(BlockingMobj->x, + BlockingMobj->y, mo->x, + mo->y) + + ANG1 * ((P_Random() % 16) - 8); + speed = P_AproxDistance(mo->momx, mo->momy); + speed = FixedMul(speed, 0.75 * FRACUNIT); + mo->angle = angle; + angle >>= ANGLETOFINESHIFT; + mo->momx = FixedMul(speed, finecosine[angle]); + mo->momy = FixedMul(speed, finesine[angle]); + if (mo->info->seesound) + { + S_StartSound(mo, mo->info->seesound); + } + return; + } + else + { // Struck a player/creature + P_ExplodeMissile(mo); + } + } + else + { // Struck a wall + P_BounceWall(mo); + switch (mo->type) + { + case MT_SORCBALL1: + case MT_SORCBALL2: + case MT_SORCBALL3: + case MT_SORCFX1: + break; + default: + if (mo->info->seesound) + { + S_StartSound(mo, mo->info->seesound); + } + break; + } + return; + } + } + if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE)) + { + angle = R_PointToAngle2(BlockingMobj->x, + BlockingMobj->y, mo->x, mo->y); + + // Change angle for delflection/reflection + switch (BlockingMobj->type) + { + case MT_CENTAUR: + case MT_CENTAURLEADER: + if (abs((int) angle - (int) BlockingMobj->angle) >> 24 > 45) + goto explode; + if (mo->type == MT_HOLY_FX) + goto explode; + // Drop through to sorcerer full reflection + case MT_SORCBOSS: + // Deflection + if (P_Random() < 128) + angle += ANG45; + else + angle -= ANG45; + break; + default: + // Reflection + angle += ANG1 * ((P_Random() % 16) - 8); + break; + } + + // Reflect the missile along angle + mo->angle = angle; + angle >>= ANGLETOFINESHIFT; + mo->momx = + FixedMul(mo->info->speed >> 1, finecosine[angle]); + mo->momy = + FixedMul(mo->info->speed >> 1, finesine[angle]); +// mo->momz = -mo->momz; + if (mo->flags2 & MF2_SEEKERMISSILE) + { + mo->special1.m = mo->target; + } + mo->target = BlockingMobj; + return; + } + explode: + // Explode a missile + if (ceilingline && ceilingline->backsector + && ceilingline->backsector->ceilingpic == skyflatnum) + { // Hack to prevent missiles exploding against the sky + if (mo->type == MT_BLOODYSKULL) + { + mo->momx = mo->momy = 0; + mo->momz = -FRACUNIT; + } + else if (mo->type == MT_HOLY_FX) + { + P_ExplodeMissile(mo); + } + else + { + P_RemoveMobj(mo); + } + return; + } + P_ExplodeMissile(mo); + } + //else if(mo->info->crashstate) + //{ + // mo->momx = mo->momy = 0; + // P_SetMobjState(mo, mo->info->crashstate); + // return; + //} + else + { + mo->momx = mo->momy = 0; + } + } + } + while (xmove || ymove); + + // Friction + + if (player && player->cheats & CF_NOMOMENTUM) + { // Debug option for no sliding at all + mo->momx = mo->momy = 0; + return; + } + if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) + { // No friction for missiles + return; + } + if (mo->z > mo->floorz && !(mo->flags2 & MF2_FLY) + && !(mo->flags2 & MF2_ONMOBJ)) + { // No friction when falling + if (mo->type != MT_BLASTEFFECT) + return; + } + if (mo->flags & MF_CORPSE) + { // Don't stop sliding if halfway off a step with some momentum + if (mo->momx > FRACUNIT / 4 || mo->momx < -FRACUNIT / 4 + || mo->momy > FRACUNIT / 4 || mo->momy < -FRACUNIT / 4) + { + if (mo->floorz != mo->subsector->sector->floorheight) + { + return; + } + } + } + if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED + && mo->momy > -STOPSPEED && mo->momy < STOPSPEED + && (!player || (player->cmd.forwardmove == 0 + && player->cmd.sidemove == 0))) + { // If in a walking frame, stop moving + if (player) + { + if ((unsigned) ((player->mo->state - states) + - PStateRun[player->class]) < 4) + { + P_SetMobjState(player->mo, PStateNormal[player->class]); + } + } + mo->momx = 0; + mo->momy = 0; + } + else + { + if (mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) + && !(mo->flags2 & MF2_ONMOBJ)) + { + mo->momx = FixedMul(mo->momx, FRICTION_FLY); + mo->momy = FixedMul(mo->momy, FRICTION_FLY); + } + else if (P_GetThingFloorType(mo) == FLOOR_ICE) + { + mo->momx = FixedMul(mo->momx, FRICTION_LOW); + mo->momy = FixedMul(mo->momy, FRICTION_LOW); + } + else + { + mo->momx = FixedMul(mo->momx, FRICTION_NORMAL); + mo->momy = FixedMul(mo->momy, FRICTION_NORMAL); + } + } +} + + +// Move this to p_inter *** +void P_MonsterFallingDamage(mobj_t * mo) +{ + int damage; + int mom; + + mom = abs(mo->momz); + if (mom > 35 * FRACUNIT) + { // automatic death + damage = 10000; + } + else + { + damage = ((mom - (23 * FRACUNIT)) * 6) >> FRACBITS; + } + damage = 10000; // always kill 'em + P_DamageMobj(mo, NULL, NULL, damage); +} + + + +/* +=============== += += P_ZMovement += +=============== +*/ + +void P_ZMovement(mobj_t * mo) +{ + int dist; + int delta; +// +// check for smooth step up +// + if (mo->player && mo->z < mo->floorz) + { + mo->player->viewheight -= mo->floorz - mo->z; + mo->player->deltaviewheight = + (VIEWHEIGHT - mo->player->viewheight) >> 3; + } +// +// adjust height +// + mo->z += mo->momz; + if (mo->flags & MF_FLOAT && mo->target) + { // float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = + P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + if (delta < 0 && dist < -(delta * 3)) + mo->z -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->z += FLOATSPEED; + } + } + if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) + && leveltime & 2) + { + mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; + } + +// +// clip movement +// + if (mo->z <= mo->floorz) + { // Hit the floor + if (mo->flags & MF_MISSILE) + { + mo->z = mo->floorz; + if (mo->flags2 & MF2_FLOORBOUNCE) + { + P_FloorBounceMissile(mo); + return; + } + else if (mo->type == MT_HOLY_FX) + { // The spirit struck the ground + mo->momz = 0; + P_HitFloor(mo); + return; + } + else if (mo->type == MT_MNTRFX2 || mo->type == MT_LIGHTNING_FLOOR) + { // Minotaur floor fire can go up steps + return; + } + else + { + P_HitFloor(mo); + P_ExplodeMissile(mo); + return; + } + } + if (mo->flags & MF_COUNTKILL) // Blasted mobj falling + { + if (mo->momz < -(23 * FRACUNIT)) + { + P_MonsterFallingDamage(mo); + } + } + if (mo->z - mo->momz > mo->floorz) + { // Spawn splashes, etc. + P_HitFloor(mo); + } + mo->z = mo->floorz; + if (mo->momz < 0) + { + if (mo->flags2 & MF2_ICEDAMAGE && mo->momz < -GRAVITY * 8) + { + mo->tics = 1; + mo->momx = 0; + mo->momy = 0; + mo->momz = 0; + return; + } + if (mo->player) + { + mo->player->jumpTics = 7; // delay any jumping for a short time + if (mo->momz < -GRAVITY * 8 && !(mo->flags2 & MF2_FLY)) + { // squat down + mo->player->deltaviewheight = mo->momz >> 3; + if (mo->momz < -23 * FRACUNIT) + { + P_FallingDamage(mo->player); + P_NoiseAlert(mo, mo); + } + else if (mo->momz < -GRAVITY * 12 + && !mo->player->morphTics) + { + S_StartSound(mo, SFX_PLAYER_LAND); + switch (mo->player->class) + { + case PCLASS_FIGHTER: + S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT); + break; + case PCLASS_CLERIC: + S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT); + break; + case PCLASS_MAGE: + S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT); + break; + default: + break; + } + } + else if ((P_GetThingFloorType(mo) < FLOOR_LIQUID) && + (!mo->player->morphTics)) + { + S_StartSound(mo, SFX_PLAYER_LAND); + } + // haleyjd: removed externdriver crap + mo->player->centering = true; + } + } + else if (mo->type >= MT_POTTERY1 && mo->type <= MT_POTTERY3) + { + P_DamageMobj(mo, NULL, NULL, 25); + } + else if (mo->flags & MF_COUNTKILL) + { + if (mo->momz < -23 * FRACUNIT) + { + // Doesn't get here + } + } + mo->momz = 0; + } + if (mo->flags & MF_SKULLFLY) + { // The skull slammed into something + mo->momz = -mo->momz; + } + if (mo->info->crashstate && + (mo->flags & MF_CORPSE) && !(mo->flags2 & MF2_ICEDAMAGE)) + { + P_SetMobjState(mo, mo->info->crashstate); + return; + } + } + else if (mo->flags2 & MF2_LOGRAV) + { + if (mo->momz == 0) + mo->momz = -(GRAVITY >> 3) * 2; + else + mo->momz -= GRAVITY >> 3; + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + if (mo->momz == 0) + mo->momz = -GRAVITY * 2; + else + mo->momz -= GRAVITY; + } + + if (mo->z + mo->height > mo->ceilingz) + { // hit the ceiling + if (mo->momz > 0) + mo->momz = 0; + mo->z = mo->ceilingz - mo->height; + if (mo->flags2 & MF2_FLOORBOUNCE) + { + // Maybe reverse momentum here for ceiling bounce + // Currently won't happen + + if (mo->info->seesound) + { + S_StartSound(mo, mo->info->seesound); + } + return; + } + if (mo->flags & MF_SKULLFLY) + { // the skull slammed into something + mo->momz = -mo->momz; + } + if (mo->flags & MF_MISSILE) + { + if (mo->type == MT_LIGHTNING_CEILING) + { + return; + } + if (mo->subsector->sector->ceilingpic == skyflatnum) + { + if (mo->type == MT_BLOODYSKULL) + { + mo->momx = mo->momy = 0; + mo->momz = -FRACUNIT; + } + else if (mo->type == MT_HOLY_FX) + { + P_ExplodeMissile(mo); + } + else + { + P_RemoveMobj(mo); + } + return; + } + P_ExplodeMissile(mo); + return; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_BlasterMobjThinker +// +// +//---------------------------------------------------------------------------- + +void P_BlasterMobjThinker(thinker_t *thinker) +{ + mobj_t *mobj = (mobj_t *) thinker; + int i; + fixed_t xfrac; + fixed_t yfrac; + fixed_t zfrac; + fixed_t z; + boolean changexy; + mobj_t *mo; + + // Handle movement + if (mobj->momx || mobj->momy || (mobj->z != mobj->floorz) || mobj->momz) + { + xfrac = mobj->momx >> 3; + yfrac = mobj->momy >> 3; + zfrac = mobj->momz >> 3; + changexy = xfrac || yfrac; + for (i = 0; i < 8; i++) + { + if (changexy) + { + if (!P_TryMove(mobj, mobj->x + xfrac, mobj->y + yfrac)) + { // Blocked move + P_ExplodeMissile(mobj); + return; + } + } + mobj->z += zfrac; + if (mobj->z <= mobj->floorz) + { // Hit the floor + mobj->z = mobj->floorz; + P_HitFloor(mobj); + P_ExplodeMissile(mobj); + return; + } + if (mobj->z + mobj->height > mobj->ceilingz) + { // Hit the ceiling + mobj->z = mobj->ceilingz - mobj->height; + P_ExplodeMissile(mobj); + return; + } + if (changexy) + { + if (mobj->type == MT_MWAND_MISSILE && (P_Random() < 128)) + { + z = mobj->z - 8 * FRACUNIT; + if (z < mobj->floorz) + { + z = mobj->floorz; + } + P_SpawnMobj(mobj->x, mobj->y, z, MT_MWANDSMOKE); + } + else if (!--mobj->special1.i) + { + mobj->special1.i = 4; + z = mobj->z - 12 * FRACUNIT; + if (z < mobj->floorz) + { + z = mobj->floorz; + } + mo = P_SpawnMobj(mobj->x, mobj->y, z, MT_CFLAMEFLOOR); + if (mo) + { + mo->angle = mobj->angle; + } + } + } + } + } + // Advance the state + if (mobj->tics != -1) + { + mobj->tics--; + while (!mobj->tics) + { + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + { // mobj was removed + return; + } + } + } +} + +//=========================================================================== +// +// PlayerLandedOnThing +// +//=========================================================================== + +static void PlayerLandedOnThing(mobj_t * mo, mobj_t * onmobj) +{ + mo->player->deltaviewheight = mo->momz >> 3; + if (mo->momz < -23 * FRACUNIT) + { + P_FallingDamage(mo->player); + P_NoiseAlert(mo, mo); + } + else if (mo->momz < -GRAVITY * 12 && !mo->player->morphTics) + { + S_StartSound(mo, SFX_PLAYER_LAND); + switch (mo->player->class) + { + case PCLASS_FIGHTER: + S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT); + break; + case PCLASS_CLERIC: + S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT); + break; + case PCLASS_MAGE: + S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT); + break; + default: + break; + } + } + else if (!mo->player->morphTics) + { + S_StartSound(mo, SFX_PLAYER_LAND); + } + // haleyjd: removed externdriver crap + mo->player->centering = true; +} + +//---------------------------------------------------------------------------- +// +// PROC P_MobjThinker +// +//---------------------------------------------------------------------------- + +void P_MobjThinker(thinker_t *thinker) +{ + mobj_t *mobj = (mobj_t *) thinker; + mobj_t *onmo; +/* + // Reset to not blasted when momentums are gone + if((mobj->flags2&MF2_BLASTED) && (!(mobj->momx)) && (!(mobj->momy))) + ResetBlasted(mobj); +*/ + // Handle X and Y momentums + BlockingMobj = NULL; + if (mobj->momx || mobj->momy || (mobj->flags & MF_SKULLFLY)) + { + P_XYMovement(mobj); + if (mobj->thinker.function == (think_t) - 1) + { // mobj was removed + return; + } + } + else if (mobj->flags2 & MF2_BLASTED) + { // Reset to not blasted when momentums are gone + ResetBlasted(mobj); + } + if (mobj->flags2 & MF2_FLOATBOB) + { // Floating item bobbing motion (special1 is height) + mobj->z = mobj->floorz + + mobj->special1.i + FloatBobOffsets[(mobj->health++) & 63]; + } + else if ((mobj->z != mobj->floorz) || mobj->momz || BlockingMobj) + { // Handle Z momentum and gravity + if (mobj->flags2 & MF2_PASSMOBJ) + { + if (!(onmo = P_CheckOnmobj(mobj))) + { + P_ZMovement(mobj); + if (mobj->player && mobj->flags & MF2_ONMOBJ) + { + mobj->flags2 &= ~MF2_ONMOBJ; + } + } + else + { + if (mobj->player) + { + if (mobj->momz < -GRAVITY * 8 + && !(mobj->flags2 & MF2_FLY)) + { + PlayerLandedOnThing(mobj, onmo); + } + if (onmo->z + onmo->height - mobj->z <= 24 * FRACUNIT) + { + mobj->player->viewheight -= onmo->z + onmo->height + - mobj->z; + mobj->player->deltaviewheight = + (VIEWHEIGHT - mobj->player->viewheight) >> 3; + mobj->z = onmo->z + onmo->height; + mobj->flags2 |= MF2_ONMOBJ; + mobj->momz = 0; + } + else + { // hit the bottom of the blocking mobj + mobj->momz = 0; + } + } +/* Landing on another player, and mimicking his movements + if(mobj->player && onmo->player) + { + mobj->momx = onmo->momx; + mobj->momy = onmo->momy; + if(onmo->z < onmo->floorz) + { + mobj->z += onmo->floorz-onmo->z; + if(onmo->player) + { + onmo->player->viewheight -= onmo->floorz-onmo->z; + onmo->player->deltaviewheight = (VIEWHEIGHT- + onmo->player->viewheight)>>3; + } + onmo->z = onmo->floorz; + } + } +*/ + } + } + else + { + P_ZMovement(mobj); + } + if (mobj->thinker.function == (think_t) - 1) + { // mobj was removed + return; + } + } + + // Cycle through states, calling action functions at transitions + if (mobj->tics != -1) + { + mobj->tics--; + // you can cycle through multiple states in a tic + while (!mobj->tics) + { + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + { // mobj was removed + return; + } + } + } +} + +//========================================================================== +// +// P_SpawnMobj +// +//========================================================================== + +mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) +{ + mobj_t *mobj; + state_t *st; + mobjinfo_t *info; + fixed_t space; + + mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); + memset(mobj, 0, sizeof(*mobj)); + info = &mobjinfo[type]; + mobj->type = type; + mobj->info = info; + mobj->x = x; + mobj->y = y; + mobj->radius = info->radius; + mobj->height = info->height; + mobj->flags = info->flags; + mobj->flags2 = info->flags2; + mobj->damage = info->damage; + mobj->health = info->spawnhealth; + if (gameskill != sk_nightmare) + { + mobj->reactiontime = info->reactiontime; + } + mobj->lastlook = P_Random() % maxplayers; + + // Set the state, but do not use P_SetMobjState, because action + // routines can't be called yet. If the spawnstate has an action + // routine, it will not be called. + st = &states[info->spawnstate]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // Set subsector and/or block links. + P_SetThingPosition(mobj); + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + if (z == ONFLOORZ) + { + mobj->z = mobj->floorz; + } + else if (z == ONCEILINGZ) + { + mobj->z = mobj->ceilingz - mobj->info->height; + } + else if (z == FLOATRANDZ) + { + space = ((mobj->ceilingz) - (mobj->info->height)) - mobj->floorz; + if (space > 48 * FRACUNIT) + { + space -= 40 * FRACUNIT; + mobj->z = + ((space * P_Random()) >> 8) + mobj->floorz + 40 * FRACUNIT; + } + else + { + mobj->z = mobj->floorz; + } + } + else if (mobj->flags2 & MF2_FLOATBOB) + { + mobj->z = mobj->floorz + z; // artifact z passed in as height + } + else + { + mobj->z = z; + } + if (mobj->flags2 & MF2_FLOORCLIP + && P_GetThingFloorType(mobj) >= FLOOR_LIQUID + && mobj->z == mobj->subsector->sector->floorheight) + { + mobj->floorclip = 10 * FRACUNIT; + } + else + { + mobj->floorclip = 0; + } + + mobj->thinker.function = P_MobjThinker; + P_AddThinker(&mobj->thinker); + return (mobj); +} + +//========================================================================== +// +// P_RemoveMobj +// +//========================================================================== + +void P_RemoveMobj(mobj_t * mobj) +{ + // Remove from creature queue + if (mobj->flags & MF_COUNTKILL && mobj->flags & MF_CORPSE) + { + A_DeQueueCorpse(mobj); + } + + if (mobj->tid) + { // Remove from TID list + P_RemoveMobjFromTIDList(mobj); + } + + // Unlink from sector and block lists + P_UnsetThingPosition(mobj); + + // Stop any playing sound + S_StopSound(mobj); + + // Free block + P_RemoveThinker((thinker_t *) mobj); +} + +//========================================================================== +// +// P_SpawnPlayer +// +// Called when a player is spawned on the level. Most of the player +// structure stays unchanged between levels. +// +//========================================================================== + +void P_SpawnPlayer(mapthing_t * mthing) +{ + player_t *p; + fixed_t x, y, z; + mobj_t *mobj; + + if (mthing->type - 1 >= maxplayers || !playeringame[mthing->type - 1]) + { // Not playing + return; + } + + p = &players[mthing->type - 1]; + if (p->playerstate == PST_REBORN) + { + G_PlayerReborn(mthing->type - 1); + } + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = ONFLOORZ; + if (randomclass && deathmatch) + { + p->class = P_Random() % 3; + if (p->class == PlayerClass[mthing->type - 1]) + { + p->class = (p->class + 1) % 3; + } + PlayerClass[mthing->type - 1] = p->class; + SB_SetClassData(); + } + else + { + p->class = PlayerClass[mthing->type - 1]; + } + switch (p->class) + { + case PCLASS_FIGHTER: + mobj = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER); + break; + case PCLASS_CLERIC: + mobj = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC); + break; + case PCLASS_MAGE: + mobj = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE); + break; + default: + I_Error("P_SpawnPlayer: Unknown class type"); + return; + } + + // Set translation table data + if (p->class == PCLASS_FIGHTER + && (mthing->type == 1 || mthing->type == 3)) + { + // The first type should be blue, and the third should be the + // Fighter's original gold color + if (mthing->type == 1) + { + mobj->flags |= 2 << MF_TRANSSHIFT; + } + } + else if (mthing->type > 1) + { // Set color translation bits for player sprites + mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT; + } + + mobj->angle = ANG45 * (mthing->angle / 45); + mobj->player = p; + mobj->health = p->health; + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + P_ClearMessage(p); + p->damagecount = 0; + p->bonuscount = 0; + p->poisoncount = 0; + p->morphTics = 0; + p->extralight = 0; + p->fixedcolormap = 0; + p->viewheight = VIEWHEIGHT; + P_SetupPsprites(p); + if (deathmatch) + { // Give all keys in death match mode + p->keys = 2047; + } +} + +//========================================================================== +// +// P_SpawnMapThing +// +// The fields of the mapthing should already be in host byte order. +// +//========================================================================== + +void P_SpawnMapThing(mapthing_t * mthing) +{ + int i; + unsigned int spawnMask; + mobj_t *mobj; + fixed_t x, y, z; + static unsigned int classFlags[] = { + MTF_FIGHTER, + MTF_CLERIC, + MTF_MAGE + }; + + // Count deathmatch start positions + if (mthing->type == 11) + { + if (deathmatch_p < &deathmatchstarts[MAXDEATHMATCHSTARTS]) + { + memcpy(deathmatch_p, mthing, sizeof(*mthing)); + deathmatch_p++; + } + return; + } + if (mthing->type == PO_ANCHOR_TYPE) + { // Polyobj Anchor Pt. + return; + } + else if (mthing->type == PO_SPAWN_TYPE + || mthing->type == PO_SPAWNCRUSH_TYPE) + { // Polyobj Anchor Pt. + po_NumPolyobjs++; + return; + } + + // Check for player starts 1 to 4 + if (mthing->type <= 4) + { + playerstarts[mthing->arg1][mthing->type - 1] = *mthing; + if (!deathmatch && !mthing->arg1) + { + P_SpawnPlayer(mthing); + } + return; + } + // Check for player starts 5 to 8 + if (mthing->type >= 9100 && mthing->type <= 9103) + { + mapthing_t *player_start; + int player; + + player = 4 + mthing->type - 9100; + + player_start = &playerstarts[mthing->arg1][player]; + memcpy(player_start, mthing, sizeof(mapthing_t)); + player_start->type = player + 1; + + if (!deathmatch && !player_start->arg1) + { + P_SpawnPlayer(player_start); + } + return; + } + + if (mthing->type >= 1400 && mthing->type < 1410) + { + R_PointInSubsector(mthing->x << FRACBITS, + mthing->y << FRACBITS)->sector->seqType = + mthing->type - 1400; + return; + } + + // Check current game type with spawn flags + if (netgame == false) + { + spawnMask = MTF_GSINGLE; + } + else if (deathmatch) + { + spawnMask = MTF_GDEATHMATCH; + } + else + { + spawnMask = MTF_GCOOP; + } + if (!(mthing->options & spawnMask)) + { + return; + } + + // Check current skill with spawn flags + if (gameskill == sk_baby || gameskill == sk_easy) + { + spawnMask = MTF_EASY; + } + else if (gameskill == sk_hard || gameskill == sk_nightmare) + { + spawnMask = MTF_HARD; + } + else + { + spawnMask = MTF_NORMAL; + } + if (!(mthing->options & spawnMask)) + { + return; + } + + // Check current character classes with spawn flags + if (netgame == false) + { // Single player + if ((mthing->options & classFlags[PlayerClass[0]]) == 0) + { // Not for current class + return; + } + } + else if (deathmatch == false) + { // Cooperative + spawnMask = 0; + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + spawnMask |= classFlags[PlayerClass[i]]; + } + } + if ((mthing->options & spawnMask) == 0) + { + return; + } + } + + // Find which type to spawn + for (i = 0; i < NUMMOBJTYPES; i++) + { + if (mthing->type == mobjinfo[i].doomednum) + { + break; + } + } + + if (i == NUMMOBJTYPES) + { // Can't find thing type + I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)", + mthing->type, mthing->x, mthing->y); + } + + // Don't spawn keys and players in deathmatch + if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) + { + return; + } + + // Don't spawn monsters if -nomonsters + if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) + { + return; + } + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + if (mobjinfo[i].flags & MF_SPAWNCEILING) + { + z = ONCEILINGZ; + } + else if (mobjinfo[i].flags2 & MF2_SPAWNFLOAT) + { + z = FLOATRANDZ; + } + else if (mobjinfo[i].flags2 & MF2_FLOATBOB) + { + z = mthing->height << FRACBITS; + } + else + { + z = ONFLOORZ; + } + switch (i) + { // Special stuff + case MT_ZLYNCHED_NOHEART: + P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODPOOL); + break; + default: + break; + } + mobj = P_SpawnMobj(x, y, z, i); + if (z == ONFLOORZ) + { + mobj->z += mthing->height << FRACBITS; + } + else if (z == ONCEILINGZ) + { + mobj->z -= mthing->height << FRACBITS; + } + mobj->tid = mthing->tid; + mobj->special = mthing->special; + mobj->args[0] = mthing->arg1; + mobj->args[1] = mthing->arg2; + mobj->args[2] = mthing->arg3; + mobj->args[3] = mthing->arg4; + mobj->args[4] = mthing->arg5; + if (mobj->flags2 & MF2_FLOATBOB) + { // Seed random starting index for bobbing motion + mobj->health = P_Random(); + mobj->special1.i = mthing->height << FRACBITS; + } + if (mobj->tics > 0) + { + mobj->tics = 1 + (P_Random() % mobj->tics); + } +// if(mobj->flags&MF_COUNTITEM) +// { +// totalitems++; +// } + if (mobj->flags & MF_COUNTKILL) + { + // Quantize angle to 45 degree increments + mobj->angle = ANG45 * (mthing->angle / 45); + } + else + { + // Scale angle correctly (source is 0..359) + mobj->angle = ((mthing->angle << 8) / 360) << 24; + } + if (mthing->options & MTF_AMBUSH) + { + mobj->flags |= MF_AMBUSH; + } + if (mthing->options & MTF_DORMANT) + { + mobj->flags2 |= MF2_DORMANT; + if (mobj->type == MT_ICEGUY) + { + P_SetMobjState(mobj, S_ICEGUY_DORMANT); + } + mobj->tics = -1; + } +} + +//========================================================================== +// +// P_CreateTIDList +// +//========================================================================== + +void P_CreateTIDList(void) +{ + int i; + mobj_t *mobj; + thinker_t *t; + + i = 0; + for (t = thinkercap.next; t != &thinkercap; t = t->next) + { // Search all current thinkers + if (t->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mobj = (mobj_t *) t; + if (mobj->tid != 0) + { // Add to list + if (i == MAX_TID_COUNT) + { + I_Error("P_CreateTIDList: MAX_TID_COUNT (%d) exceeded.", + MAX_TID_COUNT); + } + TIDList[i] = mobj->tid; + TIDMobj[i++] = mobj; + } + } + // Add termination marker + TIDList[i] = 0; +} + +//========================================================================== +// +// P_InsertMobjIntoTIDList +// +//========================================================================== + +void P_InsertMobjIntoTIDList(mobj_t * mobj, int tid) +{ + int i; + int index; + + index = -1; + for (i = 0; TIDList[i] != 0; i++) + { + if (TIDList[i] == -1) + { // Found empty slot + index = i; + break; + } + } + if (index == -1) + { // Append required + if (i == MAX_TID_COUNT) + { + I_Error("P_InsertMobjIntoTIDList: MAX_TID_COUNT (%d)" + "exceeded.", MAX_TID_COUNT); + } + index = i; + TIDList[index + 1] = 0; + } + mobj->tid = tid; + TIDList[index] = tid; + TIDMobj[index] = mobj; +} + +//========================================================================== +// +// P_RemoveMobjFromTIDList +// +//========================================================================== + +void P_RemoveMobjFromTIDList(mobj_t * mobj) +{ + int i; + + for (i = 0; TIDList[i] != 0; i++) + { + if (TIDMobj[i] == mobj) + { + TIDList[i] = -1; + TIDMobj[i] = NULL; + mobj->tid = 0; + return; + } + } + mobj->tid = 0; +} + +//========================================================================== +// +// P_FindMobjFromTID +// +//========================================================================== + +mobj_t *P_FindMobjFromTID(int tid, int *searchPosition) +{ + int i; + + for (i = *searchPosition + 1; TIDList[i] != 0; i++) + { + if (TIDList[i] == tid) + { + *searchPosition = i; + return TIDMobj[i]; + } + } + *searchPosition = -1; + return NULL; +} + +/* +=============================================================================== + + GAME SPAWN FUNCTIONS + +=============================================================================== +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_SpawnPuff +// +//--------------------------------------------------------------------------- + + +void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z) +{ + mobj_t *puff; + + z += (P_SubRandom() << 10); + puff = P_SpawnMobj(x, y, z, PuffType); + if (linetarget && puff->info->seesound) + { // Hit thing sound + S_StartSound(puff, puff->info->seesound); + } + else if (puff->info->attacksound) + { + S_StartSound(puff, puff->info->attacksound); + } + switch (PuffType) + { + case MT_PUNCHPUFF: + puff->momz = FRACUNIT; + break; + case MT_HAMMERPUFF: + puff->momz = .8 * FRACUNIT; + break; + default: + break; + } + PuffSpawned = puff; +} + +/* +================ += += P_SpawnBlood += +================ +*/ + +/* +void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) +{ + mobj_t *th; + + z += (P_SubRandom()<<10); + th = P_SpawnMobj (x,y,z, MT_BLOOD); + th->momz = FRACUNIT*2; + th->tics -= P_Random()&3; + + if (damage <= 12 && damage >= 9) + P_SetMobjState (th,S_BLOOD2); + else if (damage < 9) + P_SetMobjState (th,S_BLOOD3); +} +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_BloodSplatter +// +//--------------------------------------------------------------------------- + +void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator) +{ + mobj_t *mo; + + mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER); + mo->target = originator; + mo->momx = P_SubRandom() << 10; + mo->momy = P_SubRandom() << 10; + mo->momz = 3 * FRACUNIT; +} + +//=========================================================================== +// +// P_BloodSplatter2 +// +//=========================================================================== + +void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator) +{ + mobj_t *mo; + int r1, r2; + + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(x + ((r2 - 128) << 11), + y + ((r1 - 128) << 11), z, MT_AXEBLOOD); + mo->target = originator; +} + +//--------------------------------------------------------------------------- +// +// PROC P_RipperBlood +// +//--------------------------------------------------------------------------- + +void P_RipperBlood(mobj_t * mo) +{ + mobj_t *th; + fixed_t x, y, z; + + x = mo->x + (P_SubRandom() << 12); + y = mo->y + (P_SubRandom() << 12); + z = mo->z + (P_SubRandom() << 12); + th = P_SpawnMobj(x, y, z, MT_BLOOD); +// th->flags |= MF_NOGRAVITY; + th->momx = mo->momx >> 1; + th->momy = mo->momy >> 1; + th->tics += P_Random() & 3; +} + +//--------------------------------------------------------------------------- +// +// FUNC P_GetThingFloorType +// +//--------------------------------------------------------------------------- + +int P_GetThingFloorType(mobj_t * thing) +{ + if (thing->floorpic) + { + return (TerrainTypes[thing->floorpic]); + } + else + { + return (TerrainTypes[thing->subsector->sector->floorpic]); + } +/* + if(thing->subsector->sector->floorpic + == W_GetNumForName("FLTWAWA1")-firstflat) + { + return(FLOOR_WATER); + } + else + { + return(FLOOR_SOLID); + } +*/ +} + +//--------------------------------------------------------------------------- +// +// FUNC P_HitFloor +// +//--------------------------------------------------------------------------- +#define SMALLSPLASHCLIP 12<floorz != thing->subsector->sector->floorheight) + { // don't splash if landing on the edge above water/lava/etc.... + return (FLOOR_SOLID); + } + + // Things that don't splash go here + switch (thing->type) + { + case MT_LEAF1: + case MT_LEAF2: +// case MT_BLOOD: // I set these to low mass -- pm +// case MT_BLOODSPLATTER: + case MT_SPLASH: + case MT_SLUDGECHUNK: + return (FLOOR_SOLID); + default: + break; + } + + // Small splash for small masses + if (thing->info->mass < 10) + smallsplash = true; + + switch (P_GetThingFloorType(thing)) + { + case FLOOR_WATER: + if (smallsplash) + { + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE); + if (mo) + mo->floorclip += SMALLSPLASHCLIP; + S_StartSound(mo, SFX_AMBIENT10); // small drip + } + else + { + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH); + mo->target = thing; + mo->momx = P_SubRandom() << 8; + mo->momy = P_SubRandom() << 8; + mo->momz = 2 * FRACUNIT + (P_Random() << 8); + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE); + if (thing->player) + P_NoiseAlert(thing, thing); + S_StartSound(mo, SFX_WATER_SPLASH); + } + return (FLOOR_WATER); + case FLOOR_LAVA: + if (smallsplash) + { + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH); + if (mo) + mo->floorclip += SMALLSPLASHCLIP; + } + else + { + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE); + mo->momz = FRACUNIT + (P_Random() << 7); + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH); + if (thing->player) + P_NoiseAlert(thing, thing); + } + S_StartSound(mo, SFX_LAVA_SIZZLE); + if (thing->player && leveltime & 31) + { + P_DamageMobj(thing, &LavaInflictor, NULL, 5); + } + return (FLOOR_LAVA); + case FLOOR_SLUDGE: + if (smallsplash) + { + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, + MT_SLUDGESPLASH); + if (mo) + mo->floorclip += SMALLSPLASHCLIP; + } + else + { + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, + MT_SLUDGECHUNK); + mo->target = thing; + mo->momx = P_SubRandom() << 8; + mo->momy = P_SubRandom() << 8; + mo->momz = FRACUNIT + (P_Random() << 8); + mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, + MT_SLUDGESPLASH); + if (thing->player) + P_NoiseAlert(thing, thing); + } + S_StartSound(mo, SFX_SLUDGE_GLOOP); + return (FLOOR_SLUDGE); + } + return (FLOOR_SOLID); +} + + +//--------------------------------------------------------------------------- +// +// FUNC P_CheckMissileSpawn +// +// Returns true if the missile is at a valid spawn point, otherwise +// explodes it and returns false. +// +//--------------------------------------------------------------------------- + +boolean P_CheckMissileSpawn(mobj_t * missile) +{ + //missile->tics -= P_Random()&3; + + // move a little forward so an angle can be computed if it + // immediately explodes + missile->x += (missile->momx >> 1); + missile->y += (missile->momy >> 1); + missile->z += (missile->momz >> 1); + if (!P_TryMove(missile, missile->x, missile->y)) + { + P_ExplodeMissile(missile); + return (false); + } + return (true); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_SpawnMissile +// +// Returns NULL if the missile exploded immediately, otherwise returns +// a mobj_t pointer to the missile. +// +//--------------------------------------------------------------------------- + +mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type) +{ + fixed_t z; + mobj_t *th; + angle_t an; + int dist; + + switch (type) + { + case MT_MNTRFX1: // Minotaur swing attack missile + z = source->z + 40 * FRACUNIT; + break; + case MT_MNTRFX2: // Minotaur floor fire missile + z = ONFLOORZ + source->floorclip; + break; + case MT_CENTAUR_FX: + z = source->z + 45 * FRACUNIT; + break; + case MT_ICEGUY_FX: + z = source->z + 40 * FRACUNIT; + break; + case MT_HOLY_MISSILE: + z = source->z + 40 * FRACUNIT; + break; + default: + z = source->z + 32 * FRACUNIT; + break; + } + z -= source->floorclip; + th = P_SpawnMobj(source->x, source->y, z, type); + if (th->info->seesound) + { + S_StartSound(th, th->info->seesound); + } + th->target = source; // Originator + an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); + if (dest->flags & MF_SHADOW) + { // Invisible target + an += P_SubRandom() << 21; + } + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul(th->info->speed, finecosine[an]); + th->momy = FixedMul(th->info->speed, finesine[an]); + dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + if (dist < 1) + { + dist = 1; + } + th->momz = (dest->z - source->z) / dist; + return (P_CheckMissileSpawn(th) ? th : NULL); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_SpawnMissileXYZ +// +// Returns NULL if the missile exploded immediately, otherwise returns +// a mobj_t pointer to the missile. +// +//--------------------------------------------------------------------------- + +mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z, + mobj_t * source, mobj_t * dest, mobjtype_t type) +{ + mobj_t *th; + angle_t an; + int dist; + + z -= source->floorclip; + th = P_SpawnMobj(x, y, z, type); + if (th->info->seesound) + { + S_StartSound(th, th->info->seesound); + } + th->target = source; // Originator + an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); + if (dest->flags & MF_SHADOW) + { // Invisible target + an += P_SubRandom() << 21; + } + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul(th->info->speed, finecosine[an]); + th->momy = FixedMul(th->info->speed, finesine[an]); + dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + if (dist < 1) + { + dist = 1; + } + th->momz = (dest->z - source->z) / dist; + return (P_CheckMissileSpawn(th) ? th : NULL); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_SpawnMissileAngle +// +// Returns NULL if the missile exploded immediately, otherwise returns +// a mobj_t pointer to the missile. +// +//--------------------------------------------------------------------------- + +mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, + angle_t angle, fixed_t momz) +{ + fixed_t z; + mobj_t *mo; + + switch (type) + { + case MT_MNTRFX1: // Minotaur swing attack missile + z = source->z + 40 * FRACUNIT; + break; + case MT_MNTRFX2: // Minotaur floor fire missile + z = ONFLOORZ + source->floorclip; + break; + case MT_ICEGUY_FX2: // Secondary Projectiles of the Ice Guy + z = source->z + 3 * FRACUNIT; + break; + case MT_MSTAFF_FX2: + z = source->z + 40 * FRACUNIT; + break; + default: + z = source->z + 32 * FRACUNIT; + break; + } + z -= source->floorclip; + mo = P_SpawnMobj(source->x, source->y, z, type); + if (mo->info->seesound) + { + S_StartSound(mo, mo->info->seesound); + } + mo->target = source; // Originator + mo->angle = angle; + angle >>= ANGLETOFINESHIFT; + mo->momx = FixedMul(mo->info->speed, finecosine[angle]); + mo->momy = FixedMul(mo->info->speed, finesine[angle]); + mo->momz = momz; + return (P_CheckMissileSpawn(mo) ? mo : NULL); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_SpawnMissileAngleSpeed +// +// Returns NULL if the missile exploded immediately, otherwise returns +// a mobj_t pointer to the missile. +// +//--------------------------------------------------------------------------- + +mobj_t *P_SpawnMissileAngleSpeed(mobj_t * source, mobjtype_t type, + angle_t angle, fixed_t momz, fixed_t speed) +{ + fixed_t z; + mobj_t *mo; + + z = source->z; + z -= source->floorclip; + mo = P_SpawnMobj(source->x, source->y, z, type); + if (mo->info->seesound) + { + //S_StartSound(mo, mo->info->seesound); + } + mo->target = source; // Originator + mo->angle = angle; + angle >>= ANGLETOFINESHIFT; + mo->momx = FixedMul(speed, finecosine[angle]); + mo->momy = FixedMul(speed, finesine[angle]); + mo->momz = momz; + return (P_CheckMissileSpawn(mo) ? mo : NULL); +} + + + +/* +================ += += P_SpawnPlayerMissile += += Tries to aim at a nearby monster +================ +*/ + +mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type) +{ + angle_t an; + fixed_t x, y, z, slope; + + // Try to find a target + an = source->angle; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an += 1 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + } + if (!linetarget) + { + an = source->angle; + slope = ((source->player->lookdir) << FRACBITS) / 173; + } + } + x = source->x; + y = source->y; + if (type == MT_LIGHTNING_FLOOR) + { + z = ONFLOORZ; + slope = 0; + } + else if (type == MT_LIGHTNING_CEILING) + { + z = ONCEILINGZ; + slope = 0; + } + else + { + z = source->z + 4 * 8 * FRACUNIT + + ((source->player->lookdir) << FRACBITS) / 173; + z -= source->floorclip; + } + MissileMobj = P_SpawnMobj(x, y, z, type); + if (MissileMobj->info->seesound) + { + //S_StartSound(MissileMobj, MissileMobj->info->seesound); + } + MissileMobj->target = source; + MissileMobj->angle = an; + MissileMobj->momx = FixedMul(MissileMobj->info->speed, + finecosine[an >> ANGLETOFINESHIFT]); + MissileMobj->momy = FixedMul(MissileMobj->info->speed, + finesine[an >> ANGLETOFINESHIFT]); + MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope); + if (MissileMobj->type == MT_MWAND_MISSILE + || MissileMobj->type == MT_CFLAME_MISSILE) + { // Ultra-fast ripper spawning missile + MissileMobj->x += (MissileMobj->momx >> 3); + MissileMobj->y += (MissileMobj->momy >> 3); + MissileMobj->z += (MissileMobj->momz >> 3); + } + else + { // Normal missile + MissileMobj->x += (MissileMobj->momx >> 1); + MissileMobj->y += (MissileMobj->momy >> 1); + MissileMobj->z += (MissileMobj->momz >> 1); + } + if (!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y)) + { // Exploded immediately + P_ExplodeMissile(MissileMobj); + return (NULL); + } + return (MissileMobj); +} + + +//---------------------------------------------------------------------------- +// +// P_SpawnPlayerMinotaur - +// +// Special missile that has larger blocking than player +//---------------------------------------------------------------------------- + +/* +mobj_t *P_SpawnPlayerMinotaur(mobj_t *source, mobjtype_t type) +{ + angle_t an; + fixed_t x, y, z; + fixed_t dist=0 *FRACUNIT; + + an = source->angle; + x = source->x + FixedMul(dist, finecosine[an>>ANGLETOFINESHIFT]); + y = source->y + FixedMul(dist, finesine[an>>ANGLETOFINESHIFT]); + z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<floorclip; + MissileMobj = P_SpawnMobj(x, y, z, type); + if(MissileMobj->info->seesound) + { + //S_StartSound(MissileMobj, MissileMobj->info->seesound); + } + MissileMobj->target = source; + MissileMobj->angle = an; + MissileMobj->momx = FixedMul(MissileMobj->info->speed, + finecosine[an>>ANGLETOFINESHIFT]); + MissileMobj->momy = FixedMul(MissileMobj->info->speed, + finesine[an>>ANGLETOFINESHIFT]); + MissileMobj->momz = 0; + +// MissileMobj->x += (MissileMobj->momx>>3); +// MissileMobj->y += (MissileMobj->momy>>3); +// MissileMobj->z += (MissileMobj->momz>>3); + + if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y)) + { // Wouln't fit + + return(NULL); + } + return(MissileMobj); +} +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_SPMAngle +// +//--------------------------------------------------------------------------- + +mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle) +{ + mobj_t *th; + angle_t an; + fixed_t x, y, z, slope; + +// +// see which target is to be aimed at +// + an = angle; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an += 1 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + } + if (!linetarget) + { + an = angle; + slope = ((source->player->lookdir) << FRACBITS) / 173; + } + } + x = source->x; + y = source->y; + z = source->z + 4 * 8 * FRACUNIT + + ((source->player->lookdir) << FRACBITS) / 173; + z -= source->floorclip; + th = P_SpawnMobj(x, y, z, type); +// if(th->info->seesound) +// { +// S_StartSound(th, th->info->seesound); +// } + th->target = source; + th->angle = an; + th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); + th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); + th->momz = FixedMul(th->info->speed, slope); + return (P_CheckMissileSpawn(th) ? th : NULL); +} + +//=========================================================================== +// +// P_SPMAngleXYZ +// +//=========================================================================== + +mobj_t *P_SPMAngleXYZ(mobj_t * source, fixed_t x, fixed_t y, + fixed_t z, mobjtype_t type, angle_t angle) +{ + mobj_t *th; + angle_t an; + fixed_t slope; + +// +// see which target is to be aimed at +// + an = angle; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an += 1 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + } + if (!linetarget) + { + an = angle; + slope = ((source->player->lookdir) << FRACBITS) / 173; + } + } + z += 4 * 8 * FRACUNIT + ((source->player->lookdir) << FRACBITS) / 173; + z -= source->floorclip; + th = P_SpawnMobj(x, y, z, type); +// if(th->info->seesound) +// { +// S_StartSound(th, th->info->seesound); +// } + th->target = source; + th->angle = an; + th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); + th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); + th->momz = FixedMul(th->info->speed, slope); + return (P_CheckMissileSpawn(th) ? th : NULL); +} + +mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z, + mobj_t * source, mobj_t * dest, mobjtype_t type) +{ + mobj_t *th; + angle_t an; + int dist; + + z -= source->floorclip; + th = P_SpawnMobj(x, y, z, type); + if (th->info->seesound) + { + S_StartSound(th, th->info->seesound); + } + th->target = source; // Originator + an = R_PointToAngle2(x, y, dest->x, dest->y); + if (dest->flags & MF_SHADOW) + { // Invisible target + an += P_SubRandom() << 21; + } + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul(th->info->speed, finecosine[an]); + th->momy = FixedMul(th->info->speed, finesine[an]); + dist = P_AproxDistance(dest->x - x, dest->y - y); + dist = dist / th->info->speed; + if (dist < 1) + { + dist = 1; + } + th->momz = (dest->z - z + (30 * FRACUNIT)) / dist; + return (P_CheckMissileSpawn(th) ? th : NULL); +} diff --git a/games/NXDoom/src/hexen/p_plats.c b/games/NXDoom/src/hexen/p_plats.c new file mode 100644 index 00000000000..8c91b357553 --- /dev/null +++ b/games/NXDoom/src/hexen/p_plats.c @@ -0,0 +1,277 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "p_local.h" + +plat_t *activeplats[MAXPLATS]; + +//================================================================== +// +// Move a plat up and down +// +//================================================================== +void T_PlatRaise(thinker_t *thinker) +{ + plat_t *plat = (plat_t *) thinker; + result_e res; + + switch (plat->status) + { + case PLAT_UP: + res = T_MovePlane(plat->sector, plat->speed, + plat->high, plat->crush, 0, 1); + if (res == RES_CRUSHED && (!plat->crush)) + { + plat->count = plat->wait; + plat->status = PLAT_DOWN; + SN_StartSequence((mobj_t *) & plat->sector->soundorg, + SEQ_PLATFORM + plat->sector->seqType); + } + else if (res == RES_PASTDEST) + { + plat->count = plat->wait; + plat->status = PLAT_WAITING; + SN_StopSequence((mobj_t *) & plat->sector->soundorg); + switch (plat->type) + { + case PLAT_DOWNWAITUPSTAY: + case PLAT_DOWNBYVALUEWAITUPSTAY: + P_RemoveActivePlat(plat); + break; + default: + break; + } + } + break; + case PLAT_DOWN: + res = + T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, + -1); + if (res == RES_PASTDEST) + { + plat->count = plat->wait; + plat->status = PLAT_WAITING; + switch (plat->type) + { + case PLAT_UPWAITDOWNSTAY: + case PLAT_UPBYVALUEWAITDOWNSTAY: + P_RemoveActivePlat(plat); + break; + default: + break; + } + SN_StopSequence((mobj_t *) & plat->sector->soundorg); + } + break; + case PLAT_WAITING: + if (!--plat->count) + { + if (plat->sector->floorheight == plat->low) + plat->status = PLAT_UP; + else + plat->status = PLAT_DOWN; + SN_StartSequence((mobj_t *) & plat->sector->soundorg, + SEQ_PLATFORM + plat->sector->seqType); + } +// case PLAT_IN_STASIS: +// break; + } +} + +//================================================================== +// +// Do Platforms +// "amount" is only used for SOME platforms. +// +//================================================================== +int EV_DoPlat(line_t * line, byte * args, plattype_e type, int amount) +{ + plat_t *plat; + int secnum; + int rtn; + sector_t *sec; + + secnum = -1; + rtn = 0; + +/* + // + // Activate all plats that are in_stasis + // + switch(type) + { + case PLAT_PERPETUALRAISE: + P_ActivateInStasis(args[0]); + break; + default: + break; + } +*/ + + while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + // + // Find lowest & highest floors around sector + // + rtn = 1; + plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, 0); + P_AddThinker(&plat->thinker); + + plat->type = type; + plat->sector = sec; + plat->sector->specialdata = plat; + plat->thinker.function = T_PlatRaise; + plat->crush = false; + plat->tag = args[0]; + plat->speed = args[1] * (FRACUNIT / 8); + switch (type) + { + case PLAT_DOWNWAITUPSTAY: + plat->low = P_FindLowestFloorSurrounding(sec) + 8 * FRACUNIT; + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = sec->floorheight; + plat->wait = args[2]; + plat->status = PLAT_DOWN; + break; + case PLAT_DOWNBYVALUEWAITUPSTAY: + plat->low = sec->floorheight - args[3] * 8 * FRACUNIT; + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = sec->floorheight; + plat->wait = args[2]; + plat->status = PLAT_DOWN; + break; + case PLAT_UPWAITDOWNSTAY: + plat->high = P_FindHighestFloorSurrounding(sec); + if (plat->high < sec->floorheight) + plat->high = sec->floorheight; + plat->low = sec->floorheight; + plat->wait = args[2]; + plat->status = PLAT_UP; + break; + case PLAT_UPBYVALUEWAITDOWNSTAY: + plat->high = sec->floorheight + args[3] * 8 * FRACUNIT; + if (plat->high < sec->floorheight) + plat->high = sec->floorheight; + plat->low = sec->floorheight; + plat->wait = args[2]; + plat->status = PLAT_UP; + break; + case PLAT_PERPETUALRAISE: + plat->low = P_FindLowestFloorSurrounding(sec) + 8 * FRACUNIT; + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = P_FindHighestFloorSurrounding(sec); + if (plat->high < sec->floorheight) + plat->high = sec->floorheight; + plat->wait = args[2]; + plat->status = P_Random() & 1; + break; + } + P_AddActivePlat(plat); + SN_StartSequence((mobj_t *) & sec->soundorg, + SEQ_PLATFORM + sec->seqType); + } + return rtn; +} + +#if 0 +void P_ActivateInStasis(int tag) +{ + int i; + + for (i = 0; i < MAXPLATS; i++) + if (activeplats[i] && + (activeplats[i])->tag == tag && + (activeplats[i])->status == PLAT_IN_STASIS) + { + (activeplats[i])->status = (activeplats[i])->oldstatus; + (activeplats[i])->thinker.function = T_PlatRaise; + } +} +#endif + +void EV_StopPlat(line_t * line, byte * args) +{ + int i; + + for (i = 0; i < MAXPLATS; i++) + { + activeplats[i]->tag = args[0]; + + if (activeplats[i]->tag != 0) + { + activeplats[i]->sector->specialdata = NULL; + P_TagFinished(activeplats[i]->sector->tag); + P_RemoveThinker(&activeplats[i]->thinker); + activeplats[i] = NULL; + + return; + } + } + +/* + int j; + + for (j = 0;j < MAXPLATS;j++) + { + if (activeplats[j] && ((activeplats[j])->status != PLAT_IN_STASIS) && + ((activeplats[j])->tag == args[0])) + { + (activeplats[j])->oldstatus = (activeplats[j])->status; + (activeplats[j])->status = PLAT_IN_STASIS; + (activeplats[j])->thinker.function = NULL; + SN_StopSequence((mobj_t *)&(activeplats[j])->sector->soundorg); + } + } +*/ +} + +void P_AddActivePlat(plat_t * plat) +{ + int i; + for (i = 0; i < MAXPLATS; i++) + if (activeplats[i] == NULL) + { + activeplats[i] = plat; + return; + } + I_Error("P_AddActivePlat: no more plats!"); +} + +void P_RemoveActivePlat(plat_t * plat) +{ + int i; + for (i = 0; i < MAXPLATS; i++) + if (plat == activeplats[i]) + { + (activeplats[i])->sector->specialdata = NULL; + P_TagFinished(plat->sector->tag); + P_RemoveThinker(&(activeplats[i])->thinker); + activeplats[i] = NULL; + return; + } + I_Error("P_RemoveActivePlat: can't find plat!"); +} diff --git a/games/NXDoom/src/hexen/p_pspr.c b/games/NXDoom/src/hexen/p_pspr.c new file mode 100644 index 00000000000..230841344b7 --- /dev/null +++ b/games/NXDoom/src/hexen/p_pspr.c @@ -0,0 +1,2476 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +#define LOWERSPEED FRACUNIT*6 +#define RAISESPEED FRACUNIT*6 +#define WEAPONBOTTOM 128*FRACUNIT +#define WEAPONTOP 32*FRACUNIT + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +fixed_t bulletslope; + +weaponinfo_t WeaponInfo[NUMWEAPONS][NUMCLASSES] = { + { // First Weapons + { // Fighter First Weapon - Punch + MANA_NONE, // mana + S_PUNCHUP, // upstate + S_PUNCHDOWN, // downstate + S_PUNCHREADY, // readystate + S_PUNCHATK1_1, // atkstate + S_PUNCHATK1_1, // holdatkstate + S_NULL // flashstate + }, + { // Cleric First Weapon - Mace + MANA_NONE, // mana + S_CMACEUP, // upstate + S_CMACEDOWN, // downstate + S_CMACEREADY, // readystate + S_CMACEATK_1, // atkstate + S_CMACEATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Mage First Weapon - Wand + MANA_NONE, + S_MWANDUP, + S_MWANDDOWN, + S_MWANDREADY, + S_MWANDATK_1, + S_MWANDATK_1, + S_NULL}, + { // Pig - Snout + MANA_NONE, // mana + S_SNOUTUP, // upstate + S_SNOUTDOWN, // downstate + S_SNOUTREADY, // readystate + S_SNOUTATK1, // atkstate + S_SNOUTATK1, // holdatkstate + S_NULL // flashstate + } + }, + { // Second Weapons + { // Fighter - Axe + MANA_NONE, // mana + S_FAXEUP, // upstate + S_FAXEDOWN, // downstate + S_FAXEREADY, // readystate + S_FAXEATK_1, // atkstate + S_FAXEATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Cleric - Serpent Staff + MANA_1, // mana + S_CSTAFFUP, // upstate + S_CSTAFFDOWN, // downstate + S_CSTAFFREADY, // readystate + S_CSTAFFATK_1, // atkstate + S_CSTAFFATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Mage - Cone of shards + MANA_1, // mana + S_CONEUP, // upstate + S_CONEDOWN, // downstate + S_CONEREADY, // readystate + S_CONEATK1_1, // atkstate + S_CONEATK1_3, // holdatkstate + S_NULL // flashstate + }, + { // Pig - Snout + MANA_NONE, // mana + S_SNOUTUP, // upstate + S_SNOUTDOWN, // downstate + S_SNOUTREADY, // readystate + S_SNOUTATK1, // atkstate + S_SNOUTATK1, // holdatkstate + S_NULL // flashstate + } + }, + { // Third Weapons + { // Fighter - Hammer + MANA_NONE, // mana + S_FHAMMERUP, // upstate + S_FHAMMERDOWN, // downstate + S_FHAMMERREADY, // readystate + S_FHAMMERATK_1, // atkstate + S_FHAMMERATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Cleric - Flame Strike + MANA_2, // mana + S_CFLAMEUP, // upstate + S_CFLAMEDOWN, // downstate + S_CFLAMEREADY1, // readystate + S_CFLAMEATK_1, // atkstate + S_CFLAMEATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Mage - Lightning + MANA_2, // mana + S_MLIGHTNINGUP, // upstate + S_MLIGHTNINGDOWN, // downstate + S_MLIGHTNINGREADY, // readystate + S_MLIGHTNINGATK_1, // atkstate + S_MLIGHTNINGATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Pig - Snout + MANA_NONE, // mana + S_SNOUTUP, // upstate + S_SNOUTDOWN, // downstate + S_SNOUTREADY, // readystate + S_SNOUTATK1, // atkstate + S_SNOUTATK1, // holdatkstate + S_NULL // flashstate + } + }, + { // Fourth Weapons + { // Fighter - Rune Sword + MANA_BOTH, // mana + S_FSWORDUP, // upstate + S_FSWORDDOWN, // downstate + S_FSWORDREADY, // readystate + S_FSWORDATK_1, // atkstate + S_FSWORDATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Cleric - Holy Symbol + MANA_BOTH, // mana + S_CHOLYUP, // upstate + S_CHOLYDOWN, // downstate + S_CHOLYREADY, // readystate + S_CHOLYATK_1, // atkstate + S_CHOLYATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Mage - Staff + MANA_BOTH, // mana + S_MSTAFFUP, // upstate + S_MSTAFFDOWN, // downstate + S_MSTAFFREADY, // readystate + S_MSTAFFATK_1, // atkstate + S_MSTAFFATK_1, // holdatkstate + S_NULL // flashstate + }, + { // Pig - Snout + MANA_NONE, // mana + S_SNOUTUP, // upstate + S_SNOUTDOWN, // downstate + S_SNOUTREADY, // readystate + S_SNOUTATK1, // atkstate + S_SNOUTATK1, // holdatkstate + S_NULL // flashstate + } + } +}; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int WeaponManaUse[NUMCLASSES][NUMWEAPONS] = { + {0, 2, 3, 14}, + {0, 1, 4, 18}, + {0, 3, 5, 15}, + {0, 0, 0, 0} +}; + +// CODE -------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// PROC P_SetPsprite +// +//--------------------------------------------------------------------------- + +void P_SetPsprite(player_t * player, int position, statenum_t stnum) +{ + pspdef_t *psp; + state_t *state; + + psp = &player->psprites[position]; + do + { + if (!stnum) + { // Object removed itself. + psp->state = NULL; + break; + } + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; // could be 0 + if (state->misc1) + { // Set coordinates. + psp->sx = state->misc1 << FRACBITS; + } + if (state->misc2) + { + psp->sy = state->misc2 << FRACBITS; + } + if (state->action) + { // Call action routine. + state->action(NULL, player, psp); + if (!psp->state) + { + break; + } + } + stnum = psp->state->nextstate; + } + while (!psp->tics); // An initial state of 0 could cycle through. +} + +//--------------------------------------------------------------------------- +// +// PROC P_SetPspriteNF +// +// Identical to P_SetPsprite, without calling the action function +//--------------------------------------------------------------------------- + +void P_SetPspriteNF(player_t * player, int position, statenum_t stnum) +{ + pspdef_t *psp; + state_t *state; + + psp = &player->psprites[position]; + do + { + if (!stnum) + { // Object removed itself. + psp->state = NULL; + break; + } + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; // could be 0 + if (state->misc1) + { // Set coordinates. + psp->sx = state->misc1 << FRACBITS; + } + if (state->misc2) + { + psp->sy = state->misc2 << FRACBITS; + } + stnum = psp->state->nextstate; + } + while (!psp->tics); // An initial state of 0 could cycle through. +} + +/* +================= += += P_CalcSwing += +================= +*/ + +/* +fixed_t swingx, swingy; +void P_CalcSwing (player_t *player) +{ + fixed_t swing; + int angle; + +// OPTIMIZE: tablify this + + swing = player->bob; + + angle = (FINEANGLES/70*leveltime)&FINEMASK; + swingx = FixedMul ( swing, finesine[angle]); + + angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; + swingy = -FixedMul ( swingx, finesine[angle]); +} +*/ + +//--------------------------------------------------------------------------- +// +// PROC P_ActivateMorphWeapon +// +//--------------------------------------------------------------------------- + +void P_ActivateMorphWeapon(player_t * player) +{ + player->pendingweapon = WP_NOCHANGE; + player->psprites[ps_weapon].sy = WEAPONTOP; + player->readyweapon = WP_FIRST; // Snout is the first weapon + P_SetPsprite(player, ps_weapon, S_SNOUTREADY); +} + + +//--------------------------------------------------------------------------- +// +// PROC P_PostMorphWeapon +// +//--------------------------------------------------------------------------- + +void P_PostMorphWeapon(player_t * player, weapontype_t weapon) +{ + player->pendingweapon = WP_NOCHANGE; + player->readyweapon = weapon; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + P_SetPsprite(player, ps_weapon, + WeaponInfo[weapon][player->class].upstate); +} + +//--------------------------------------------------------------------------- +// +// PROC P_BringUpWeapon +// +// Starts bringing the pending weapon up from the bottom of the screen. +// +//--------------------------------------------------------------------------- + +void P_BringUpWeapon(player_t * player) +{ + statenum_t new; + + if (player->pendingweapon == WP_NOCHANGE) + { + player->pendingweapon = player->readyweapon; + } + if (player->class == PCLASS_FIGHTER && player->pendingweapon == WP_SECOND + && player->mana[MANA_1]) + { + new = S_FAXEUP_G; + } + else + { + new = WeaponInfo[player->pendingweapon][player->class].upstate; + } + player->pendingweapon = WP_NOCHANGE; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + P_SetPsprite(player, ps_weapon, new); +} + +//--------------------------------------------------------------------------- +// +// FUNC P_CheckMana +// +// Returns true if there is enough mana to shoot. If not, selects the +// next weapon to use. +// +//--------------------------------------------------------------------------- + +boolean P_CheckMana(player_t * player) +{ + manatype_t mana; + int count; + + mana = WeaponInfo[player->readyweapon][player->class].mana; + count = WeaponManaUse[player->class][player->readyweapon]; + if (mana == MANA_BOTH) + { + if (player->mana[MANA_1] >= count && player->mana[MANA_2] >= count) + { + return true; + } + } + else if (mana == MANA_NONE || player->mana[mana] >= count) + { + return (true); + } + // out of mana, pick a weapon to change to + do + { + if (player->weaponowned[WP_THIRD] + && player->mana[MANA_2] >= WeaponManaUse[player->class][WP_THIRD]) + { + player->pendingweapon = WP_THIRD; + } + else if (player->weaponowned[WP_SECOND] + && player->mana[MANA_1] >= + WeaponManaUse[player->class][WP_SECOND]) + { + player->pendingweapon = WP_SECOND; + } + else if (player->weaponowned[WP_FOURTH] + && player->mana[MANA_1] >= + WeaponManaUse[player->class][WP_FOURTH] + && player->mana[MANA_2] >= + WeaponManaUse[player->class][WP_FOURTH]) + { + player->pendingweapon = WP_FOURTH; + } + else + { + player->pendingweapon = WP_FIRST; + } + } + while (player->pendingweapon == WP_NOCHANGE); + P_SetPsprite(player, ps_weapon, + WeaponInfo[player->readyweapon][player->class].downstate); + return (false); +} + +//--------------------------------------------------------------------------- +// +// PROC P_FireWeapon +// +//--------------------------------------------------------------------------- + +void P_FireWeapon(player_t * player) +{ + statenum_t attackState; + + if (!P_CheckMana(player)) + { + return; + } + P_SetMobjState(player->mo, PStateAttack[player->class]); // S_PLAY_ATK1); + if (player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND + && player->mana[MANA_1] > 0) + { // Glowing axe + attackState = S_FAXEATK_G1; + } + else + { + attackState = player->refire ? + WeaponInfo[player->readyweapon][player->class].holdatkstate + : WeaponInfo[player->readyweapon][player->class].atkstate; + } + P_SetPsprite(player, ps_weapon, attackState); + P_NoiseAlert(player->mo, player->mo); +} + +//--------------------------------------------------------------------------- +// +// PROC P_DropWeapon +// +// The player died, so put the weapon away. +// +//--------------------------------------------------------------------------- + +void P_DropWeapon(player_t * player) +{ + P_SetPsprite(player, ps_weapon, + WeaponInfo[player->readyweapon][player->class].downstate); +} + +//--------------------------------------------------------------------------- +// +// PROC A_WeaponReady +// +// The player can fire the weapon or change to another weapon at this time. +// +//--------------------------------------------------------------------------- + +void A_WeaponReady(mobj_t *obj, player_t *player, pspdef_t *psp) +{ + int angle; + + // Change player from attack state + if (player->mo->state >= &states[PStateAttack[player->class]] + && player->mo->state <= &states[PStateAttackEnd[player->class]]) + { + P_SetMobjState(player->mo, PStateNormal[player->class]); + } + // Put the weapon away if the player has a pending weapon or has + // died. + if (player->pendingweapon != WP_NOCHANGE || !player->health) + { + P_SetPsprite(player, ps_weapon, + WeaponInfo[player->readyweapon][player->class]. + downstate); + return; + } + + // Check for fire. + if (player->cmd.buttons & BT_ATTACK) + { + player->attackdown = true; + P_FireWeapon(player); + return; + } + else + { + player->attackdown = false; + } + + if (!player->morphTics) + { + // Bob the weapon based on movement speed. + angle = (128 * leveltime) & FINEMASK; + psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]); + angle &= FINEANGLES / 2 - 1; + psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]); + } +} + +//--------------------------------------------------------------------------- +// +// PROC A_ReFire +// +// The player can re fire the weapon without lowering it entirely. +// +//--------------------------------------------------------------------------- + +void A_ReFire(mobj_t *mobj, player_t *player, pspdef_t *psp) +{ + if ((player->cmd.buttons & BT_ATTACK) + && player->pendingweapon == WP_NOCHANGE && player->health) + { + player->refire++; + P_FireWeapon(player); + } + else + { + player->refire = 0; + P_CheckMana(player); + } +} + +//--------------------------------------------------------------------------- +// +// PROC A_Lower +// +//--------------------------------------------------------------------------- + +void A_Lower(mobj_t *mobj, player_t *player, pspdef_t *psp) +{ + if (player->morphTics) + { + psp->sy = WEAPONBOTTOM; + } + else + { + psp->sy += LOWERSPEED; + } + if (psp->sy < WEAPONBOTTOM) + { // Not lowered all the way yet + return; + } + if (player->playerstate == PST_DEAD) + { // Player is dead, so don't bring up a pending weapon + psp->sy = WEAPONBOTTOM; + return; + } + if (!player->health) + { // Player is dead, so keep the weapon off screen + P_SetPsprite(player, ps_weapon, S_NULL); + return; + } + player->readyweapon = player->pendingweapon; + P_BringUpWeapon(player); +} + +//--------------------------------------------------------------------------- +// +// PROC A_Raise +// +//--------------------------------------------------------------------------- + +void A_Raise(mobj_t *mobj, player_t *player, pspdef_t *psp) +{ + psp->sy -= RAISESPEED; + if (psp->sy > WEAPONTOP) + { // Not raised all the way yet + return; + } + psp->sy = WEAPONTOP; + if (player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND + && player->mana[MANA_1]) + { + P_SetPsprite(player, ps_weapon, S_FAXEREADY_G); + } + else + { + P_SetPsprite(player, ps_weapon, + WeaponInfo[player->readyweapon][player->class]. + readystate); + } +} + +/* +=============== += += P_BulletSlope += += Sets a slope so a near miss is at aproximately the height of the += intended target += +=============== +*/ + +/* +void P_BulletSlope (mobj_t *mo) +{ + angle_t an; + +// +// see which target is to be aimed at +// + an = mo->angle; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + if (!linetarget) + { + an += 1<<26; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + if (!linetarget) + { + an -= 2<<26; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + } + if (!linetarget) + { + an += 1<<26; + bulletslope = (mo->player->lookdir<x, pmo->y, linetarget->x, linetarget->y); + difference = (int) angle - (int) pmo->angle; + if (abs(difference) > MAX_ANGADJUST) + { + pmo->angle += difference > 0 ? MAX_ANGADJUST : -MAX_ANGADJUST; + } + else + { + pmo->angle = angle; + } +} + +//============================================================================ +// +// A_SnoutAttack +// +//============================================================================ + +void A_SnoutAttack(mobj_t *mobj, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + + damage = 3 + (P_Random() & 3); + angle = player->mo->angle; + slope = P_AimLineAttack(player->mo, angle, MELEERANGE); + PuffType = MT_SNOUTPUFF; + PuffSpawned = NULL; + P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); + S_StartSound(player->mo, SFX_PIG_ACTIVE1 + (P_Random() & 1)); + if (linetarget) + { + AdjustPlayerAngle(player->mo); +// player->mo->angle = R_PointToAngle2(player->mo->x, +// player->mo->y, linetarget->x, linetarget->y); + if (PuffSpawned) + { // Bit something + S_StartSound(player->mo, SFX_PIG_ATTACK); + } + } +} + +//============================================================================ +// +// A_FHammerAttack +// +//============================================================================ + +#define HAMMER_RANGE (MELEERANGE+MELEERANGE/2) + +void A_FHammerAttack(mobj_t *mobj, player_t *player, pspdef_t *psp) +{ + angle_t angle; + mobj_t *pmo = player->mo; + int damage; + fixed_t power; + int slope; + int i; + + damage = 60 + (P_Random() & 63); + power = 10 * FRACUNIT; + PuffType = MT_HAMMERPUFF; + for (i = 0; i < 16; i++) + { + angle = pmo->angle + i * (ANG45 / 32); + slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE); + if (linetarget) + { + P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage); + AdjustPlayerAngle(pmo); + if (linetarget->flags & MF_COUNTKILL || linetarget->player) + { + P_ThrustMobj(linetarget, angle, power); + } + pmo->special1.i = false; // Don't throw a hammer + goto hammerdone; + } + angle = pmo->angle - i * (ANG45 / 32); + slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE); + if (linetarget) + { + P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage); + AdjustPlayerAngle(pmo); + if (linetarget->flags & MF_COUNTKILL || linetarget->player) + { + P_ThrustMobj(linetarget, angle, power); + } + pmo->special1.i = false; // Don't throw a hammer + goto hammerdone; + } + } + // didn't find any targets in meleerange, so set to throw out a hammer + PuffSpawned = NULL; + angle = pmo->angle; + slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE); + P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage); + if (PuffSpawned) + { + pmo->special1.i = false; + } + else + { + pmo->special1.i = true; + } + hammerdone: + if (player->mana[MANA_2] < + WeaponManaUse[player->class][player->readyweapon]) + { // Don't spawn a hammer if the player doesn't have enough mana + pmo->special1.i = false; + } + return; +} + +//============================================================================ +// +// A_FHammerThrow +// +//============================================================================ + +void A_FHammerThrow(mobj_t *mobj, player_t * player, pspdef_t * psp) +{ + mobj_t *mo; + + if (!player->mo->special1.i) + { + return; + } + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; + mo = P_SpawnPlayerMissile(player->mo, MT_HAMMER_MISSILE); + if (mo) + { + mo->special1.i = 0; + } +} + +//============================================================================ +// +// A_FSwordAttack +// +//============================================================================ + +void A_FSwordAttack(mobj_t *mobj, player_t *player, pspdef_t *psp) +{ + mobj_t *pmo; + + player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; + pmo = player->mo; + P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z - 10 * FRACUNIT, + MT_FSWORD_MISSILE, pmo->angle + ANG45 / 4); + P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z - 5 * FRACUNIT, + MT_FSWORD_MISSILE, pmo->angle + ANG45 / 8); + P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z, MT_FSWORD_MISSILE, pmo->angle); + P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z + 5 * FRACUNIT, + MT_FSWORD_MISSILE, pmo->angle - ANG45 / 8); + P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z + 10 * FRACUNIT, + MT_FSWORD_MISSILE, pmo->angle - ANG45 / 4); + S_StartSound(pmo, SFX_FIGHTER_SWORD_FIRE); +} + +//============================================================================ +// +// A_FSwordAttack2 +// +//============================================================================ + +void A_FSwordAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle = actor->angle; + + P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle + ANG45 / 4, 0); + P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle + ANG45 / 8, 0); + P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle, 0); + P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle - ANG45 / 8, 0); + P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle - ANG45 / 4, 0); + S_StartSound(actor, SFX_FIGHTER_SWORD_FIRE); +} + +//============================================================================ +// +// A_FSwordFlames +// +//============================================================================ + +void A_FSwordFlames(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + int r1,r2,r3; + + for (i = 1 + (P_Random() & 3); i; i--) + { + r1 = P_Random(); + r2 = P_Random(); + r3 = P_Random(); + P_SpawnMobj(actor->x + ((r3 - 128) << 12), actor->y + + ((r2 - 128) << 12), + actor->z + ((r1 - 128) << 11), MT_FSWORD_FLAME); + } +} + +//============================================================================ +// +// A_MWandAttack +// +//============================================================================ + +void A_MWandAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnPlayerMissile(player->mo, MT_MWAND_MISSILE); + if (mo) + { + mo->thinker.function = P_BlasterMobjThinker; + } + S_StartSound(player->mo, SFX_MAGE_WAND_FIRE); +} + +// ===== Mage Lightning Weapon ===== + +//============================================================================ +// +// A_LightningReady +// +//============================================================================ + +void A_LightningReady(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_WeaponReady(actor, player, psp); + if (P_Random() < 160) + { + S_StartSound(player->mo, SFX_MAGE_LIGHTNING_READY); + } +} + +//============================================================================ +// +// A_LightningClip +// +//============================================================================ + +#define ZAGSPEED FRACUNIT + +void A_LightningClip(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *cMo; + mobj_t *target = NULL; + int zigZag; + + if (actor->type == MT_LIGHTNING_FLOOR) + { + actor->z = actor->floorz; + target = actor->special2.m->special1.m; + } + else if (actor->type == MT_LIGHTNING_CEILING) + { + actor->z = actor->ceilingz - actor->height; + target = actor->special1.m; + } + if (actor->type == MT_LIGHTNING_FLOOR) + { // floor lightning zig-zags, and forces the ceiling lightning to mimic + cMo = actor->special2.m; + zigZag = P_Random(); + if ((zigZag > 128 && actor->special1.i < 2) || actor->special1.i < -2) + { + P_ThrustMobj(actor, actor->angle + ANG90, ZAGSPEED); + if (cMo) + { + P_ThrustMobj(cMo, actor->angle + ANG90, ZAGSPEED); + } + actor->special1.i++; + } + else + { + P_ThrustMobj(actor, actor->angle - ANG90, ZAGSPEED); + if (cMo) + { + P_ThrustMobj(cMo, cMo->angle - ANG90, ZAGSPEED); + } + actor->special1.i--; + } + } + if (target) + { + if (target->health <= 0) + { + P_ExplodeMissile(actor); + } + else + { + actor->angle = R_PointToAngle2(actor->x, actor->y, target->x, + target->y); + actor->momx = 0; + actor->momy = 0; + P_ThrustMobj(actor, actor->angle, actor->info->speed >> 1); + } + } +} + +//============================================================================ +// +// A_LightningZap +// +//============================================================================ + +void A_LightningZap(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + fixed_t deltaZ; + int r1,r2; + + A_LightningClip(actor, player, psp); + + actor->health -= 8; + if (actor->health <= 0) + { + P_SetMobjState(actor, actor->info->deathstate); + return; + } + if (actor->type == MT_LIGHTNING_FLOOR) + { + deltaZ = 10 * FRACUNIT; + } + else + { + deltaZ = -10 * FRACUNIT; + } + r1 = P_Random(); + r2 = P_Random(); + mo = P_SpawnMobj(actor->x + ((r2 - 128) * actor->radius / 256), + actor->y + ((r1 - 128) * actor->radius / 256), + actor->z + deltaZ, MT_LIGHTNING_ZAP); + if (mo) + { + mo->special2.m = actor; + mo->momx = actor->momx; + mo->momy = actor->momy; + mo->target = actor->target; + if (actor->type == MT_LIGHTNING_FLOOR) + { + mo->momz = 20 * FRACUNIT; + } + else + { + mo->momz = -20 * FRACUNIT; + } + } +/* + mo = P_SpawnMobj(actor->x+((P_Random()-128)*actor->radius/256), + actor->y+((P_Random()-128)*actor->radius/256), + actor->z+deltaZ, MT_LIGHTNING_ZAP); + if(mo) + { + mo->special2.m = actor; + mo->momx = actor->momx; + mo->momy = actor->momy; + mo->target = actor->target; + if(actor->type == MT_LIGHTNING_FLOOR) + { + mo->momz = 16*FRACUNIT; + } + else + { + mo->momz = -16*FRACUNIT; + } + } +*/ + if (actor->type == MT_LIGHTNING_FLOOR && P_Random() < 160) + { + S_StartSound(actor, SFX_MAGE_LIGHTNING_CONTINUOUS); + } +} + +//============================================================================ +// +// A_MLightningAttack2 +// +//============================================================================ + +void A_MLightningAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *fmo, *cmo; + + fmo = P_SpawnPlayerMissile(actor, MT_LIGHTNING_FLOOR); + cmo = P_SpawnPlayerMissile(actor, MT_LIGHTNING_CEILING); + if (fmo) + { + fmo->special1.m = NULL; + fmo->special2.m = cmo; + A_LightningZap(fmo, player, psp); + } + if (cmo) + { + cmo->special1.m = NULL; // mobj that it will track + cmo->special2.m = fmo; + A_LightningZap(cmo, player, psp); + } + S_StartSound(actor, SFX_MAGE_LIGHTNING_FIRE); +} + +//============================================================================ +// +// A_MLightningAttack +// +//============================================================================ + +void A_MLightningAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_MLightningAttack2(player->mo, player, psp); + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; +} + +//============================================================================ +// +// A_ZapMimic +// +//============================================================================ + +void A_ZapMimic(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = actor->special2.m; + if (mo) + { + if (mo->state >= &states[mo->info->deathstate] + || mo->state == &states[S_FREETARGMOBJ]) + { + P_ExplodeMissile(actor); + } + else + { + actor->momx = mo->momx; + actor->momy = mo->momy; + } + } +} + +//============================================================================ +// +// A_LastZap +// +//============================================================================ + +void A_LastZap(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_LIGHTNING_ZAP); + if (mo) + { + P_SetMobjState(mo, S_LIGHTNING_ZAP_X1); + mo->momz = 40 * FRACUNIT; + } +} + +//============================================================================ +// +// A_LightningRemove +// +//============================================================================ + +void A_LightningRemove(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = actor->special2.m; + if (mo) + { + mo->special2.m = NULL; + P_ExplodeMissile(mo); + } +} + + +//============================================================================ +// +// MStaffSpawn +// +//============================================================================ +void MStaffSpawn(mobj_t * pmo, angle_t angle) +{ + mobj_t *mo; + + mo = P_SPMAngle(pmo, MT_MSTAFF_FX2, angle); + if (mo) + { + mo->target = pmo; + mo->special1.m = P_RoughMonsterSearch(mo, 10); + } +} + +//============================================================================ +// +// A_MStaffAttack +// +//============================================================================ + +void A_MStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + mobj_t *pmo; + + player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; + pmo = player->mo; + angle = pmo->angle; + + MStaffSpawn(pmo, angle); + MStaffSpawn(pmo, angle - ANG1 * 5); + MStaffSpawn(pmo, angle + ANG1 * 5); + S_StartSound(player->mo, SFX_MAGE_STAFF_FIRE); + if (player == &players[consoleplayer]) + { + player->damagecount = 0; + player->bonuscount = 0; + I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), + PU_CACHE) + + STARTSCOURGEPAL * 768); + } +} + +//============================================================================ +// +// A_MStaffPalette +// +//============================================================================ + +void A_MStaffPalette(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int pal; + + if (player == &players[consoleplayer]) + { + pal = STARTSCOURGEPAL + psp->state - (&states[S_MSTAFFATK_2]); + if (pal == STARTSCOURGEPAL + 3) + { // reset back to original playpal + pal = 0; + } + I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), + PU_CACHE) + pal * 768); + } +} + +//============================================================================ +// +// A_MStaffWeave +// +//============================================================================ + +void A_MStaffWeave(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t newX, newY; + int weaveXY, weaveZ; + int angle; + + weaveXY = actor->special2.i >> 16; + weaveZ = actor->special2.i & 0xFFFF; + angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + newX = actor->x - FixedMul(finecosine[angle], + FloatBobOffsets[weaveXY] << 2); + newY = actor->y - FixedMul(finesine[angle], + FloatBobOffsets[weaveXY] << 2); + weaveXY = (weaveXY + 6) & 63; + newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 2); + newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 2); + P_TryMove(actor, newX, newY); + actor->z -= FloatBobOffsets[weaveZ] << 1; + weaveZ = (weaveZ + 3) & 63; + actor->z += FloatBobOffsets[weaveZ] << 1; + if (actor->z <= actor->floorz) + { + actor->z = actor->floorz + FRACUNIT; + } + actor->special2.i = weaveZ + (weaveXY << 16); +} + + +//============================================================================ +// +// A_MStaffTrack +// +//============================================================================ + +void A_MStaffTrack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if ((actor->special1.m == NULL) && (P_Random() < 50)) + { + actor->special1.m = P_RoughMonsterSearch(actor, 10); + } + P_SeekerMissile(actor, ANG1 * 2, ANG1 * 10); +} + + +//============================================================================ +// +// MStaffSpawn2 - for use by mage class boss +// +//============================================================================ + +void MStaffSpawn2(mobj_t * actor, angle_t angle) +{ + mobj_t *mo; + + mo = P_SpawnMissileAngle(actor, MT_MSTAFF_FX2, angle, 0); + if (mo) + { + mo->target = actor; + mo->special1.m = P_RoughMonsterSearch(mo, 10); + } +} + +//============================================================================ +// +// A_MStaffAttack2 - for use by mage class boss +// +//============================================================================ + +void A_MStaffAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + angle = actor->angle; + MStaffSpawn2(actor, angle); + MStaffSpawn2(actor, angle - ANG1 * 5); + MStaffSpawn2(actor, angle + ANG1 * 5); + S_StartSound(actor, SFX_MAGE_STAFF_FIRE); +} + +//============================================================================ +// +// A_FPunchAttack +// +//============================================================================ + +void A_FPunchAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + mobj_t *pmo = player->mo; + fixed_t power; + int i; + + damage = 40 + (P_Random() & 15); + power = 2 * FRACUNIT; + PuffType = MT_PUNCHPUFF; + for (i = 0; i < 16; i++) + { + angle = pmo->angle + i * (ANG45 / 16); + slope = P_AimLineAttack(pmo, angle, 2 * MELEERANGE); + if (linetarget) + { + player->mo->special1.i++; + if (pmo->special1.i == 3) + { + damage <<= 1; + power = 6 * FRACUNIT; + PuffType = MT_HAMMERPUFF; + } + P_LineAttack(pmo, angle, 2 * MELEERANGE, slope, damage); + if (linetarget->flags & MF_COUNTKILL || linetarget->player) + { + P_ThrustMobj(linetarget, angle, power); + } + AdjustPlayerAngle(pmo); + goto punchdone; + } + angle = pmo->angle - i * (ANG45 / 16); + slope = P_AimLineAttack(pmo, angle, 2 * MELEERANGE); + if (linetarget) + { + pmo->special1.i++; + if (pmo->special1.i == 3) + { + damage <<= 1; + power = 6 * FRACUNIT; + PuffType = MT_HAMMERPUFF; + } + P_LineAttack(pmo, angle, 2 * MELEERANGE, slope, damage); + if (linetarget->flags & MF_COUNTKILL || linetarget->player) + { + P_ThrustMobj(linetarget, angle, power); + } + AdjustPlayerAngle(pmo); + goto punchdone; + } + } + // didn't find any creatures, so try to strike any walls + pmo->special1.i = 0; + + angle = pmo->angle; + slope = P_AimLineAttack(pmo, angle, MELEERANGE); + P_LineAttack(pmo, angle, MELEERANGE, slope, damage); + + punchdone: + if (pmo->special1.i == 3) + { + pmo->special1.i = 0; + P_SetPsprite(player, ps_weapon, S_PUNCHATK2_1); + S_StartSound(pmo, SFX_FIGHTER_GRUNT); + } + return; +} + +//============================================================================ +// +// A_FAxeAttack +// +//============================================================================ + +#define AXERANGE 2.25*MELEERANGE + +void A_FAxeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + mobj_t *pmo = player->mo; + fixed_t power; + int damage; + int slope; + int i; + int useMana; + int r; + + r = P_Random(); + damage = 40 + (r & 15) + (P_Random() & 7); + power = 0; + if (player->mana[MANA_1] > 0) + { + damage <<= 1; + power = 6 * FRACUNIT; + PuffType = MT_AXEPUFF_GLOW; + useMana = 1; + } + else + { + PuffType = MT_AXEPUFF; + useMana = 0; + } + for (i = 0; i < 16; i++) + { + angle = pmo->angle + i * (ANG45 / 16); + slope = P_AimLineAttack(pmo, angle, AXERANGE); + if (linetarget) + { + P_LineAttack(pmo, angle, AXERANGE, slope, damage); + if (linetarget->flags & MF_COUNTKILL || linetarget->player) + { + P_ThrustMobj(linetarget, angle, power); + } + AdjustPlayerAngle(pmo); + useMana++; + goto axedone; + } + angle = pmo->angle - i * (ANG45 / 16); + slope = P_AimLineAttack(pmo, angle, AXERANGE); + if (linetarget) + { + P_LineAttack(pmo, angle, AXERANGE, slope, damage); + if (linetarget->flags & MF_COUNTKILL) + { + P_ThrustMobj(linetarget, angle, power); + } + AdjustPlayerAngle(pmo); + useMana++; + goto axedone; + } + } + // didn't find any creatures, so try to strike any walls + pmo->special1.m = NULL; + + angle = pmo->angle; + slope = P_AimLineAttack(pmo, angle, MELEERANGE); + P_LineAttack(pmo, angle, MELEERANGE, slope, damage); + + axedone: + if (useMana == 2) + { + player->mana[MANA_1] -= + WeaponManaUse[player->class][player->readyweapon]; + if (player->mana[MANA_1] <= 0) + { + P_SetPsprite(player, ps_weapon, S_FAXEATK_5); + } + } + return; +} + +//=========================================================================== +// +// A_CMaceAttack +// +//=========================================================================== + +void A_CMaceAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; + int i; + + damage = 25 + (P_Random() & 15); + PuffType = MT_HAMMERPUFF; + for (i = 0; i < 16; i++) + { + angle = player->mo->angle + i * (ANG45 / 16); + slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE); + if (linetarget) + { + P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage); + AdjustPlayerAngle(player->mo); +// player->mo->angle = R_PointToAngle2(player->mo->x, +// player->mo->y, linetarget->x, linetarget->y); + goto macedone; + } + angle = player->mo->angle - i * (ANG45 / 16); + slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE); + if (linetarget) + { + P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage); + AdjustPlayerAngle(player->mo); +// player->mo->angle = R_PointToAngle2(player->mo->x, +// player->mo->y, linetarget->x, linetarget->y); + goto macedone; + } + } + // didn't find any creatures, so try to strike any walls + player->mo->special1.m = NULL; + + angle = player->mo->angle; + slope = P_AimLineAttack(player->mo, angle, MELEERANGE); + P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); + macedone: + return; +} + +//============================================================================ +// +// A_CStaffCheck +// +//============================================================================ + +void A_CStaffCheck(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *pmo; + int damage; + int newLife; + angle_t angle; + int slope; + int i; + + pmo = player->mo; + damage = 20 + (P_Random() & 15); + PuffType = MT_CSTAFFPUFF; + for (i = 0; i < 3; i++) + { + angle = pmo->angle + i * (ANG45 / 16); + slope = P_AimLineAttack(pmo, angle, 1.5 * MELEERANGE); + if (linetarget) + { + P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage); + pmo->angle = R_PointToAngle2(pmo->x, pmo->y, + linetarget->x, linetarget->y); + if ((linetarget->player || linetarget->flags & MF_COUNTKILL) + && (!(linetarget->flags2 & (MF2_DORMANT + MF2_INVULNERABLE)))) + { + newLife = player->health + (damage >> 3); + newLife = newLife > 100 ? 100 : newLife; + pmo->health = player->health = newLife; + P_SetPsprite(player, ps_weapon, S_CSTAFFATK2_1); + } + player->mana[MANA_1] -= + WeaponManaUse[player->class][player->readyweapon]; + break; + } + angle = pmo->angle - i * (ANG45 / 16); + slope = P_AimLineAttack(player->mo, angle, 1.5 * MELEERANGE); + if (linetarget) + { + P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage); + pmo->angle = R_PointToAngle2(pmo->x, pmo->y, + linetarget->x, linetarget->y); + if (linetarget->player || linetarget->flags & MF_COUNTKILL) + { + newLife = player->health + (damage >> 4); + newLife = newLife > 100 ? 100 : newLife; + pmo->health = player->health = newLife; + P_SetPsprite(player, ps_weapon, S_CSTAFFATK2_1); + } + player->mana[MANA_1] -= + WeaponManaUse[player->class][player->readyweapon]; + break; + } + } +} + +//============================================================================ +// +// A_CStaffAttack +// +//============================================================================ + +void A_CStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + mobj_t *pmo; + + player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; + pmo = player->mo; + mo = P_SPMAngle(pmo, MT_CSTAFF_MISSILE, pmo->angle - (ANG45 / 15)); + if (mo) + { + mo->special2.i = 32; + } + mo = P_SPMAngle(pmo, MT_CSTAFF_MISSILE, pmo->angle + (ANG45 / 15)); + if (mo) + { + mo->special2.i = 0; + } + S_StartSound(player->mo, SFX_CLERIC_CSTAFF_FIRE); +} + +//============================================================================ +// +// A_CStaffMissileSlither +// +//============================================================================ + +void A_CStaffMissileSlither(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + fixed_t newX, newY; + int weaveXY; + int angle; + + weaveXY = actor->special2.i; + angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + newX = actor->x - FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); + newY = actor->y - FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); + weaveXY = (weaveXY + 3) & 63; + newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); + newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); + P_TryMove(actor, newX, newY); + actor->special2.i = weaveXY; +} + +//============================================================================ +// +// A_CStaffInitBlink +// +//============================================================================ + +void A_CStaffInitBlink(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->mo->special1.i = (P_Random() >> 1) + 20; +} + +//============================================================================ +// +// A_CStaffCheckBlink +// +//============================================================================ + +void A_CStaffCheckBlink(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + if (!--player->mo->special1.i) + { + P_SetPsprite(player, ps_weapon, S_CSTAFFBLINK1); + player->mo->special1.i = (P_Random() + 50) >> 2; + } +} + +//============================================================================ +// +// A_CFlameAttack +// +//============================================================================ + +#define FLAMESPEED (0.45*FRACUNIT) +#define CFLAMERANGE (12*64*FRACUNIT) + +void A_CFlameAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + + mo = P_SpawnPlayerMissile(player->mo, MT_CFLAME_MISSILE); + if (mo) + { + mo->thinker.function = P_BlasterMobjThinker; + mo->special1.i = 2; + } + + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; + S_StartSound(player->mo, SFX_CLERIC_FLAME_FIRE); +} + +//============================================================================ +// +// A_CFlamePuff +// +//============================================================================ + +void A_CFlamePuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_UnHideThing(actor, player, psp); + actor->momx = 0; + actor->momy = 0; + actor->momz = 0; + S_StartSound(actor, SFX_CLERIC_FLAME_EXPLODE); +} + +//============================================================================ +// +// A_CFlameMissile +// +//============================================================================ + +void A_CFlameMissile(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int i; + int an; + fixed_t dist; + mobj_t *mo; + + A_UnHideThing(actor, player, psp); + S_StartSound(actor, SFX_CLERIC_FLAME_EXPLODE); + if (BlockingMobj && BlockingMobj->flags & MF_SHOOTABLE) + { // Hit something, so spawn the flame circle around the thing + dist = BlockingMobj->radius + 18 * FRACUNIT; + for (i = 0; i < 4; i++) + { + an = (i * ANG45) >> ANGLETOFINESHIFT; + mo = P_SpawnMobj(BlockingMobj->x + FixedMul(dist, finecosine[an]), + BlockingMobj->y + FixedMul(dist, finesine[an]), + BlockingMobj->z + 5 * FRACUNIT, MT_CIRCLEFLAME); + if (mo) + { + mo->angle = an << ANGLETOFINESHIFT; + mo->target = actor->target; + mo->momx = mo->special1.i = + FixedMul(FLAMESPEED, finecosine[an]); + mo->momy = mo->special2.i = FixedMul(FLAMESPEED, finesine[an]); + mo->tics -= P_Random() & 3; + } + mo = P_SpawnMobj(BlockingMobj->x - FixedMul(dist, finecosine[an]), + BlockingMobj->y - FixedMul(dist, finesine[an]), + BlockingMobj->z + 5 * FRACUNIT, MT_CIRCLEFLAME); + if (mo) + { + mo->angle = ANG180 + (an << ANGLETOFINESHIFT); + mo->target = actor->target; + mo->momx = mo->special1.i = FixedMul(-FLAMESPEED, + finecosine[an]); + mo->momy = mo->special2.i = FixedMul(-FLAMESPEED, finesine[an]); + mo->tics -= P_Random() & 3; + } + } + P_SetMobjState(actor, S_FLAMEPUFF2_1); + } +} + +/* +void A_CFlameAttack(player_t *player, pspdef_t *psp) +{ + mobj_t *pmo; + angle_t angle; + int damage; + int i; + int an, an90; + fixed_t dist; + mobj_t *mo; + + pmo = player->mo; + P_BulletSlope(pmo); + damage = 25+HITDICE(3); + angle = pmo->angle; + if(player->refire) + { + angle += P_SubRandom()<<17; + } + P_AimLineAttack(pmo, angle, CFLAMERANGE); // Correctly set linetarget + if(!linetarget) + { + angle += ANG1*2; + P_AimLineAttack(pmo, angle, CFLAMERANGE); + if(!linetarget) + { + angle -= ANG1*4; + P_AimLineAttack(pmo, angle, CFLAMERANGE); + if(!linetarget) + { + angle += ANG1*2; + } + } + } + if(linetarget) + { + PuffType = MT_FLAMEPUFF2; + } + else + { + PuffType = MT_FLAMEPUFF; + } + P_LineAttack(pmo, angle, CFLAMERANGE, bulletslope, damage); + if(linetarget) + { // Hit something, so spawn the flame circle around the thing + dist = linetarget->radius+18*FRACUNIT; + for(i = 0; i < 4; i++) + { + an = (i*ANG45)>>ANGLETOFINESHIFT; + an90 = (i*ANG45+ANG90)>>ANGLETOFINESHIFT; + mo = P_SpawnMobj(linetarget->x+FixedMul(dist, finecosine[an]), + linetarget->y+FixedMul(dist, finesine[an]), + linetarget->z+5*FRACUNIT, MT_CIRCLEFLAME); + if(mo) + { + mo->angle = an<target = pmo; + mo->momx = mo->special1.i = FixedMul(FLAMESPEED, finecosine[an]); + mo->momy = mo->special2.i = FixedMul(FLAMESPEED, finesine[an]); + mo->tics -= P_Random()&3; + } + mo = P_SpawnMobj(linetarget->x-FixedMul(dist, finecosine[an]), + linetarget->y-FixedMul(dist, finesine[an]), + linetarget->z+5*FRACUNIT, MT_CIRCLEFLAME); + if(mo) + { + mo->angle = ANG180+(an<target = pmo; + mo->momx = mo->special1.i = FixedMul(-FLAMESPEED, + finecosine[an]); + mo->momy = mo->special2.i = FixedMul(-FLAMESPEED, finesine[an]); + mo->tics -= P_Random()&3; + } + } + } +// Create a line of flames from the player to the flame puff + CFlameCreateFlames(player->mo); + + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; + S_StartSound(player->mo, SFX_CLERIC_FLAME_FIRE); +} +*/ + +//============================================================================ +// +// A_CFlameRotate +// +//============================================================================ + +#define FLAMEROTSPEED 2*FRACUNIT + +void A_CFlameRotate(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int an; + + an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + actor->momx = actor->special1.i + FixedMul(FLAMEROTSPEED, finecosine[an]); + actor->momy = actor->special2.i + FixedMul(FLAMEROTSPEED, finesine[an]); + actor->angle += ANG90 / 15; +} + + +//============================================================================ +// +// A_CHolyAttack3 +// +// Spawns the spirits +//============================================================================ + +void A_CHolyAttack3(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMissile(actor, actor->target, MT_HOLY_MISSILE); + S_StartSound(actor, SFX_CHOLY_FIRE); +} + + +//============================================================================ +// +// A_CHolyAttack2 +// +// Spawns the spirits +//============================================================================ + +void A_CHolyAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int j; + int i; + int r; + mobj_t *mo; + mobj_t *tail, *next; + + for (j = 0; j < 4; j++) + { + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_HOLY_FX); + if (!mo) + { + continue; + } + switch (j) + { // float bob index + case 0: + mo->special2.i = P_Random() & 7; // upper-left + break; + case 1: + mo->special2.i = 32 + (P_Random() & 7); // upper-right + break; + case 2: + mo->special2.i = (32 + (P_Random() & 7)) << 16; // lower-left + break; + case 3: + r = P_Random(); + mo->special2.i = + ((32 + (r & 7)) << 16) + 32 + (P_Random() & 7); + break; + } + mo->z = actor->z; + mo->angle = actor->angle + (ANG45 + ANG45 / 2) - ANG45 * j; + P_ThrustMobj(mo, mo->angle, mo->info->speed); + mo->target = actor->target; + mo->args[0] = 10; // initial turn value + mo->args[1] = 0; // initial look angle + if (deathmatch) + { // Ghosts last slightly less longer in DeathMatch + mo->health = 85; + } + if (linetarget) + { + mo->special1.m = linetarget; + mo->flags |= MF_NOCLIP | MF_SKULLFLY; + mo->flags &= ~MF_MISSILE; + } + tail = P_SpawnMobj(mo->x, mo->y, mo->z, MT_HOLY_TAIL); + tail->special2.m = mo; // parent + for (i = 1; i < 3; i++) + { + next = P_SpawnMobj(mo->x, mo->y, mo->z, MT_HOLY_TAIL); + P_SetMobjState(next, next->info->spawnstate + 1); + tail->special1.m = next; + tail = next; + } + tail->special1.m = NULL; // last tail bit + } +} + +//============================================================================ +// +// A_CHolyAttack +// +//============================================================================ + +void A_CHolyAttack(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; + player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; + P_SpawnPlayerMissile(player->mo, MT_HOLY_MISSILE); + if (player == &players[consoleplayer]) + { + player->damagecount = 0; + player->bonuscount = 0; + I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), + PU_CACHE) + STARTHOLYPAL * 768); + } + S_StartSound(player->mo, SFX_CHOLY_FIRE); +} + +//============================================================================ +// +// A_CHolyPalette +// +//============================================================================ + +void A_CHolyPalette(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + int pal; + + if (player == &players[consoleplayer]) + { + pal = STARTHOLYPAL + psp->state - (&states[S_CHOLYATK_6]); + if (pal == STARTHOLYPAL + 3) + { // reset back to original playpal + pal = 0; + } + I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), + PU_CACHE) + pal * 768); + } +} + +//============================================================================ +// +// CHolyFindTarget +// +//============================================================================ + +static void CHolyFindTarget(mobj_t * actor) +{ + mobj_t *target; + + target = P_RoughMonsterSearch(actor, 6); + if (target != NULL) + { + actor->special1.m = target; + actor->flags |= MF_NOCLIP | MF_SKULLFLY; + actor->flags &= ~MF_MISSILE; + } +} + +//============================================================================ +// +// CHolySeekerMissile +// +// Similar to P_SeekerMissile, but seeks to a random Z on the target +//============================================================================ + +static void CHolySeekerMissile(mobj_t * actor, angle_t thresh, + angle_t turnMax) +{ + int dir; + int dist; + angle_t delta; + angle_t angle; + mobj_t *target; + fixed_t newZ; + fixed_t deltaZ; + + target = actor->special1.m; + if (target == NULL) + { + return; + } + if (!(target->flags & MF_SHOOTABLE) + || (!(target->flags & MF_COUNTKILL) && !target->player)) + { // Target died/target isn't a player or creature + actor->special1.m = NULL; + actor->flags &= ~(MF_NOCLIP | MF_SKULLFLY); + actor->flags |= MF_MISSILE; + CHolyFindTarget(actor); + return; + } + dir = P_FaceMobj(actor, target, &delta); + if (delta > thresh) + { + delta >>= 1; + if (delta > turnMax) + { + delta = turnMax; + } + } + if (dir) + { // Turn clockwise + actor->angle += delta; + } + else + { // Turn counter clockwise + actor->angle -= delta; + } + angle = actor->angle >> ANGLETOFINESHIFT; + actor->momx = FixedMul(actor->info->speed, finecosine[angle]); + actor->momy = FixedMul(actor->info->speed, finesine[angle]); + if (!(leveltime & 15) + || actor->z > target->z + (target->height) + || actor->z + actor->height < target->z) + { + newZ = target->z + ((P_Random() * target->height) >> 8); + deltaZ = newZ - actor->z; + if (abs(deltaZ) > 15 * FRACUNIT) + { + if (deltaZ > 0) + { + deltaZ = 15 * FRACUNIT; + } + else + { + deltaZ = -15 * FRACUNIT; + } + } + dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); + dist = dist / actor->info->speed; + if (dist < 1) + { + dist = 1; + } + actor->momz = deltaZ / dist; + } + return; +} + +//============================================================================ +// +// A_CHolyWeave +// +//============================================================================ + +static void CHolyWeave(mobj_t * actor) +{ + fixed_t newX, newY; + int weaveXY, weaveZ; + int angle; + + weaveXY = actor->special2.i >> 16; + weaveZ = actor->special2.i & 0xFFFF; + angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + newX = actor->x - FixedMul(finecosine[angle], + FloatBobOffsets[weaveXY] << 2); + newY = actor->y - FixedMul(finesine[angle], + FloatBobOffsets[weaveXY] << 2); + weaveXY = (weaveXY + (P_Random() % 5)) & 63; + newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 2); + newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 2); + P_TryMove(actor, newX, newY); + actor->z -= FloatBobOffsets[weaveZ] << 1; + weaveZ = (weaveZ + (P_Random() % 5)) & 63; + actor->z += FloatBobOffsets[weaveZ] << 1; + actor->special2.i = weaveZ + (weaveXY << 16); +} + +//============================================================================ +// +// A_CHolySeek +// +//============================================================================ + +void A_CHolySeek(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->health--; + if (actor->health <= 0) + { + actor->momx >>= 2; + actor->momy >>= 2; + actor->momz = 0; + P_SetMobjState(actor, actor->info->deathstate); + actor->tics -= P_Random() & 3; + return; + } + if (actor->special1.m) + { + CHolySeekerMissile(actor, actor->args[0] * ANG1, + actor->args[0] * ANG1 * 2); + if (!((leveltime + 7) & 15)) + { + actor->args[0] = 5 + (P_Random() / 20); + } + } + CHolyWeave(actor); +} + +//============================================================================ +// +// CHolyTailFollow +// +//============================================================================ + +static void CHolyTailFollow(mobj_t * actor, fixed_t dist) +{ + mobj_t *child; + int an; + fixed_t oldDistance, newDistance; + + child = actor->special1.m; + if (child) + { + an = R_PointToAngle2(actor->x, actor->y, child->x, + child->y) >> ANGLETOFINESHIFT; + oldDistance = + P_AproxDistance(child->x - actor->x, child->y - actor->y); + if (P_TryMove + (child, actor->x + FixedMul(dist, finecosine[an]), + actor->y + FixedMul(dist, finesine[an]))) + { + newDistance = P_AproxDistance(child->x - actor->x, + child->y - actor->y) - FRACUNIT; + if (oldDistance < FRACUNIT) + { + if (child->z < actor->z) + { + child->z = actor->z - dist; + } + else + { + child->z = actor->z + dist; + } + } + else + { + child->z = actor->z + FixedMul(FixedDiv(newDistance, + oldDistance), + child->z - actor->z); + } + } + CHolyTailFollow(child, dist - FRACUNIT); + } +} + +//============================================================================ +// +// CHolyTailRemove +// +//============================================================================ + +static void CHolyTailRemove(mobj_t * actor) +{ + mobj_t *child; + + child = actor->special1.m; + if (child) + { + CHolyTailRemove(child); + } + P_RemoveMobj(actor); +} + +//============================================================================ +// +// A_CHolyTail +// +//============================================================================ + +void A_CHolyTail(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *parent; + + parent = actor->special2.m; + + if (parent) + { + if (parent->state >= &states[parent->info->deathstate]) + { // Ghost removed, so remove all tail parts + CHolyTailRemove(actor); + return; + } + else if (P_TryMove(actor, parent->x - FixedMul(14 * FRACUNIT, + finecosine[parent-> + angle >> + ANGLETOFINESHIFT]), + parent->y - FixedMul(14 * FRACUNIT, + finesine[parent-> + angle >> + ANGLETOFINESHIFT]))) + { + actor->z = parent->z - 5 * FRACUNIT; + } + CHolyTailFollow(actor, 10 * FRACUNIT); + } +} + +//============================================================================ +// +// A_CHolyCheckScream +// +//============================================================================ + +void A_CHolyCheckScream(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + A_CHolySeek(actor, player, psp); + if (P_Random() < 20) + { + S_StartSound(actor, SFX_SPIRIT_ACTIVE); + } + if (!actor->special1.m) + { + CHolyFindTarget(actor); + } +} + +//============================================================================ +// +// A_CHolySpawnPuff +// +//============================================================================ + +void A_CHolySpawnPuff(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + P_SpawnMobj(actor->x, actor->y, actor->z, MT_HOLY_MISSILE_PUFF); +} + +//---------------------------------------------------------------------------- +// +// PROC A_FireConePL1 +// +//---------------------------------------------------------------------------- + +#define SHARDSPAWN_LEFT 1 +#define SHARDSPAWN_RIGHT 2 +#define SHARDSPAWN_UP 4 +#define SHARDSPAWN_DOWN 8 + +void A_FireConePL1(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int i; + mobj_t *pmo, *mo; + int conedone = false; + + pmo = player->mo; + player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; + S_StartSound(pmo, SFX_MAGE_SHARDS_FIRE); + + damage = 90 + (P_Random() & 15); + for (i = 0; i < 16; i++) + { + angle = pmo->angle + i * (ANG45 / 16); + P_AimLineAttack(pmo, angle, MELEERANGE); + if (linetarget) + { + pmo->flags2 |= MF2_ICEDAMAGE; + P_DamageMobj(linetarget, pmo, pmo, damage); + pmo->flags2 &= ~MF2_ICEDAMAGE; + conedone = true; + break; + } + } + + // didn't find any creatures, so fire projectiles + if (!conedone) + { + mo = P_SpawnPlayerMissile(pmo, MT_SHARDFX1); + if (mo) + { + mo->special1.i = SHARDSPAWN_LEFT | SHARDSPAWN_DOWN | SHARDSPAWN_UP + | SHARDSPAWN_RIGHT; + mo->special2.i = 3; // Set sperm count (levels of reproductivity) + mo->target = pmo; + mo->args[0] = 3; // Mark Initial shard as super damage + } + } +} + +void A_ShedShard(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + mobj_t *mo; + int spawndir = actor->special1.i; + int spermcount = actor->special2.i; + + if (spermcount <= 0) + return; // No sperm left + actor->special2.i = 0; + spermcount--; + + // every so many calls, spawn a new missile in it's set directions + if (spawndir & SHARDSPAWN_LEFT) + { + mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, + actor->angle + (ANG45 / 9), 0, + (20 + 2 * spermcount) << FRACBITS); + if (mo) + { + mo->special1.i = SHARDSPAWN_LEFT; + mo->special2.i = spermcount; + mo->momz = actor->momz; + mo->target = actor->target; + mo->args[0] = (spermcount == 3) ? 2 : 0; + } + } + if (spawndir & SHARDSPAWN_RIGHT) + { + mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, + actor->angle - (ANG45 / 9), 0, + (20 + 2 * spermcount) << FRACBITS); + if (mo) + { + mo->special1.i = SHARDSPAWN_RIGHT; + mo->special2.i = spermcount; + mo->momz = actor->momz; + mo->target = actor->target; + mo->args[0] = (spermcount == 3) ? 2 : 0; + } + } + if (spawndir & SHARDSPAWN_UP) + { + mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, actor->angle, + 0, (15 + 2 * spermcount) << FRACBITS); + if (mo) + { + mo->momz = actor->momz; + mo->z += 8 * FRACUNIT; + if (spermcount & 1) // Every other reproduction + mo->special1.i = + SHARDSPAWN_UP | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; + else + mo->special1.i = SHARDSPAWN_UP; + mo->special2.i = spermcount; + mo->target = actor->target; + mo->args[0] = (spermcount == 3) ? 2 : 0; + } + } + if (spawndir & SHARDSPAWN_DOWN) + { + mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, actor->angle, + 0, (15 + 2 * spermcount) << FRACBITS); + if (mo) + { + mo->momz = actor->momz; + mo->z -= 4 * FRACUNIT; + if (spermcount & 1) // Every other reproduction + mo->special1.i = + SHARDSPAWN_DOWN | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; + else + mo->special1.i = SHARDSPAWN_DOWN; + mo->special2.i = spermcount; + mo->target = actor->target; + mo->args[0] = (spermcount == 3) ? 2 : 0; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC A_HideInCeiling +// +//---------------------------------------------------------------------------- + +/* +void A_HideInCeiling(mobj_t *actor) +{ + actor->z = actor->ceilingz+4*FRACUNIT; +} +*/ + +//---------------------------------------------------------------------------- +// +// PROC A_FloatPuff +// +//---------------------------------------------------------------------------- + +/* +void A_FloatPuff(mobj_t *puff) +{ + puff->momz += 1.8*FRACUNIT; +} +*/ + +void A_Light0(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + player->extralight = 0; +} + +/* +void A_Light1(player_t *player, pspdef_t *psp) +{ + player->extralight = 1; +} +*/ + +/* +void A_Light2(player_t *player, pspdef_t *psp) +{ + player->extralight = 2; +} +*/ + +//------------------------------------------------------------------------ +// +// PROC P_SetupPsprites +// +// Called at start of level for each player +// +//------------------------------------------------------------------------ + +void P_SetupPsprites(player_t * player) +{ + int i; + + // Remove all psprites + for (i = 0; i < NUMPSPRITES; i++) + { + player->psprites[i].state = NULL; + } + // Spawn the ready weapon + player->pendingweapon = player->readyweapon; + P_BringUpWeapon(player); +} + +//------------------------------------------------------------------------ +// +// PROC P_MovePsprites +// +// Called every tic by player thinking routine +// +//------------------------------------------------------------------------ + +void P_MovePsprites(player_t * player) +{ + int i; + pspdef_t *psp; + + psp = &player->psprites[0]; + for (i = 0; i < NUMPSPRITES; i++, psp++) + { + if (psp->state != 0) // a null state means not active + { + // drop tic count and possibly change state + if (psp->tics != -1) // a -1 tic count never changes + { + psp->tics--; + if (!psp->tics) + { + P_SetPsprite(player, i, psp->state->nextstate); + } + } + } + } + player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; + player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; +} diff --git a/games/NXDoom/src/hexen/p_setup.c b/games/NXDoom/src/hexen/p_setup.c new file mode 100644 index 00000000000..d71907727ae --- /dev/null +++ b/games/NXDoom/src/hexen/p_setup.c @@ -0,0 +1,1273 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include +#include +#include "h2def.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_bbox.h" +#include "m_misc.h" +#include "i_swap.h" +#include "s_sound.h" +#include "p_local.h" +#include "p_rejectpad.h" + +// MACROS ------------------------------------------------------------------ + +#define MAPINFO_SCRIPT_NAME "MAPINFO" +#define MCMD_SKY1 1 +#define MCMD_SKY2 2 +#define MCMD_LIGHTNING 3 +#define MCMD_FADETABLE 4 +#define MCMD_DOUBLESKY 5 +#define MCMD_CLUSTER 6 +#define MCMD_WARPTRANS 7 +#define MCMD_NEXT 8 +#define MCMD_CDTRACK 9 +#define MCMD_CD_STARTTRACK 10 +#define MCMD_CD_END1TRACK 11 +#define MCMD_CD_END2TRACK 12 +#define MCMD_CD_END3TRACK 13 +#define MCMD_CD_INTERTRACK 14 +#define MCMD_CD_TITLETRACK 15 + +#define UNKNOWN_MAP_NAME "DEVELOPMENT MAP" +#define DEFAULT_SKY_NAME "SKY1" +#define DEFAULT_SONG_LUMP "DEFSONG" +#define DEFAULT_FADE_TABLE "COLORMAP" + +// TYPES ------------------------------------------------------------------- + +typedef struct mapInfo_s mapInfo_t; +struct mapInfo_s +{ + short cluster; + short warpTrans; + short nextMap; + short cdTrack; + char name[32]; + short sky1Texture; + short sky2Texture; + fixed_t sky1ScrollDelta; + fixed_t sky2ScrollDelta; + boolean doubleSky; + boolean lightning; + int fadetable; + char songLump[10]; +}; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +void P_SpawnMapThing(mapthing_t * mthing); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static int QualifyMap(int map); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +int MapCount; +mapthing_t deathmatchstarts[MAXDEATHMATCHSTARTS], *deathmatch_p; +mapthing_t playerstarts[MAX_PLAYER_STARTS][MAXPLAYERS]; +int numvertexes; +vertex_t *vertexes; +int numsegs; +seg_t *segs; +int numsectors; +sector_t *sectors; +int numsubsectors; +subsector_t *subsectors; +int numnodes; +node_t *nodes; +int numlines; +line_t *lines; +int numsides; +side_t *sides; +static int totallines; +short *blockmaplump; // offsets in blockmap are from here +short *blockmap; +int bmapwidth, bmapheight; // in mapblocks +fixed_t bmaporgx, bmaporgy; // origin of block map +mobj_t **blocklinks; // for thing chains +byte *rejectmatrix; // for fast sight rejection + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static mapInfo_t MapInfo[99]; +static const char *MapCmdNames[] = { + "SKY1", + "SKY2", + "DOUBLESKY", + "LIGHTNING", + "FADETABLE", + "CLUSTER", + "WARPTRANS", + "NEXT", + "CDTRACK", + "CD_START_TRACK", + "CD_END1_TRACK", + "CD_END2_TRACK", + "CD_END3_TRACK", + "CD_INTERMISSION_TRACK", + "CD_TITLE_TRACK", + NULL +}; +static int MapCmdIDs[] = { + MCMD_SKY1, + MCMD_SKY2, + MCMD_DOUBLESKY, + MCMD_LIGHTNING, + MCMD_FADETABLE, + MCMD_CLUSTER, + MCMD_WARPTRANS, + MCMD_NEXT, + MCMD_CDTRACK, + MCMD_CD_STARTTRACK, + MCMD_CD_END1TRACK, + MCMD_CD_END2TRACK, + MCMD_CD_END3TRACK, + MCMD_CD_INTERTRACK, + MCMD_CD_TITLETRACK +}; + +static int cd_NonLevelTracks[6]; // Non-level specific song cd track numbers + +// CODE -------------------------------------------------------------------- + +/* +================= += += P_LoadVertexes += +================= +*/ + +void P_LoadVertexes(int lump) +{ + byte *data; + int i; + mapvertex_t *ml; + vertex_t *li; + + numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t); + vertexes = Z_Malloc(numvertexes * sizeof(vertex_t), PU_LEVEL, 0); + data = W_CacheLumpNum(lump, PU_STATIC); + + ml = (mapvertex_t *) data; + li = vertexes; + for (i = 0; i < numvertexes; i++, li++, ml++) + { + li->x = SHORT(ml->x) << FRACBITS; + li->y = SHORT(ml->y) << FRACBITS; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSegs += +================= +*/ + +void P_LoadSegs(int lump) +{ + byte *data; + int i; + mapseg_t *ml; + seg_t *li; + line_t *ldef; + int linedef, side; + + numsegs = W_LumpLength(lump) / sizeof(mapseg_t); + segs = Z_Malloc(numsegs * sizeof(seg_t), PU_LEVEL, 0); + memset(segs, 0, numsegs * sizeof(seg_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + ml = (mapseg_t *) data; + li = segs; + for (i = 0; i < numsegs; i++, li++, ml++) + { + li->v1 = &vertexes[SHORT(ml->v1)]; + li->v2 = &vertexes[SHORT(ml->v2)]; + + li->angle = (SHORT(ml->angle)) << 16; + li->offset = (SHORT(ml->offset)) << 16; + linedef = SHORT(ml->linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + side = SHORT(ml->side); + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; + if (ldef->flags & ML_TWOSIDED) + li->backsector = sides[ldef->sidenum[side ^ 1]].sector; + else + li->backsector = 0; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSubsectors += +================= +*/ + +void P_LoadSubsectors(int lump) +{ + byte *data; + int i; + mapsubsector_t *ms; + subsector_t *ss; + + numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t); + subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0); + data = W_CacheLumpNum(lump, PU_STATIC); + + ms = (mapsubsector_t *) data; + memset(subsectors, 0, numsubsectors * sizeof(subsector_t)); + ss = subsectors; + for (i = 0; i < numsubsectors; i++, ss++, ms++) + { + ss->numlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSectors += +================= +*/ + +void P_LoadSectors(int lump) +{ + byte *data; + int i; + mapsector_t *ms; + sector_t *ss; + + numsectors = W_LumpLength(lump) / sizeof(mapsector_t); + sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0); + memset(sectors, 0, numsectors * sizeof(sector_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + ms = (mapsector_t *) data; + ss = sectors; + + for (i = 0; i < numsectors; i++, ss++, ms++) + { + ss->floorheight = SHORT(ms->floorheight) << FRACBITS; + ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS; + ss->floorpic = R_FlatNumForName(ms->floorpic); + ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); + ss->lightlevel = SHORT(ms->lightlevel); + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + ss->thinglist = NULL; + ss->seqType = SEQTYPE_STONE; // default seqType + } + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadNodes += +================= +*/ + +void P_LoadNodes(int lump) +{ + byte *data; + int i, j, k; + mapnode_t *mn; + node_t *no; + + numnodes = W_LumpLength(lump) / sizeof(mapnode_t); + nodes = Z_Malloc(numnodes * sizeof(node_t), PU_LEVEL, 0); + data = W_CacheLumpNum(lump, PU_STATIC); + + mn = (mapnode_t *) data; + no = nodes; + for (i = 0; i < numnodes; i++, no++, mn++) + { + no->x = SHORT(mn->x) << FRACBITS; + no->y = SHORT(mn->y) << FRACBITS; + no->dx = SHORT(mn->dx) << FRACBITS; + no->dy = SHORT(mn->dy) << FRACBITS; + for (j = 0; j < 2; j++) + { + no->children[j] = SHORT(mn->children[j]); + for (k = 0; k < 4; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; + } + } + W_ReleaseLumpNum(lump); +} + +//========================================================================== +// +// P_LoadThings +// +//========================================================================== + +void P_LoadThings(int lump) +{ + byte *data; + int i; + mapthing_t spawnthing; + mapthing_t *mt; + int numthings; + int playerCount; + int deathSpotsCount; + + data = W_CacheLumpNum(lump, PU_STATIC); + numthings = W_LumpLength(lump) / sizeof(mapthing_t); + + mt = (mapthing_t *) data; + for (i = 0; i < numthings; i++, mt++) + { + spawnthing.tid = SHORT(mt->tid); + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.height = SHORT(mt->height); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + spawnthing.options = SHORT(mt->options); + + spawnthing.special = mt->special; + spawnthing.arg1 = mt->arg1; + spawnthing.arg2 = mt->arg2; + spawnthing.arg3 = mt->arg3; + spawnthing.arg4 = mt->arg4; + spawnthing.arg5 = mt->arg5; + + P_SpawnMapThing(&spawnthing); + } + P_CreateTIDList(); + P_InitCreatureCorpseQueue(false); // false = do NOT scan for corpses + W_ReleaseLumpNum(lump); + + if (!deathmatch) + { // Don't need to check deathmatch spots + return; + } + playerCount = 0; + for (i = 0; i < maxplayers; i++) + { + playerCount += playeringame[i]; + } + deathSpotsCount = deathmatch_p - deathmatchstarts; + if (deathSpotsCount < playerCount) + { + I_Error("P_LoadThings: Player count (%d) exceeds deathmatch " + "spots (%d)", playerCount, deathSpotsCount); + } +} + +/* +================= += += P_LoadLineDefs += +================= +*/ + +void P_LoadLineDefs(int lump) +{ + byte *data; + int i; + maplinedef_t *mld; + line_t *ld; + vertex_t *v1, *v2; + + numlines = W_LumpLength(lump) / sizeof(maplinedef_t); + lines = Z_Malloc(numlines * sizeof(line_t), PU_LEVEL, 0); + memset(lines, 0, numlines * sizeof(line_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + mld = (maplinedef_t *) data; + ld = lines; + for (i = 0; i < numlines; i++, mld++, ld++) + { + ld->flags = SHORT(mld->flags); + + // Old line special info ... + //ld->special = SHORT(mld->special); + //ld->tag = SHORT(mld->tag); + + // New line special info ... + ld->special = mld->special; + ld->arg1 = mld->arg1; + ld->arg2 = mld->arg2; + ld->arg3 = mld->arg3; + ld->arg4 = mld->arg4; + ld->arg5 = mld->arg5; + + v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; + v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else + { + if (FixedDiv(ld->dy, ld->dx) > 0) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + } + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + if (ld->sidenum[0] != -1) + ld->frontsector = sides[ld->sidenum[0]].sector; + else + ld->frontsector = 0; + if (ld->sidenum[1] != -1) + ld->backsector = sides[ld->sidenum[1]].sector; + else + ld->backsector = 0; + } + + W_ReleaseLumpNum(lump); +} + + +/* +================= += += P_LoadSideDefs += +================= +*/ + +void P_LoadSideDefs(int lump) +{ + byte *data; + int i; + mapsidedef_t *msd; + side_t *sd; + + numsides = W_LumpLength(lump) / sizeof(mapsidedef_t); + sides = Z_Malloc(numsides * sizeof(side_t), PU_LEVEL, 0); + memset(sides, 0, numsides * sizeof(side_t)); + data = W_CacheLumpNum(lump, PU_STATIC); + + msd = (mapsidedef_t *) data; + sd = sides; + + for (i = 0; i < numsides; i++, msd++, sd++) + { + sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS; + sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS; + sd->toptexture = R_TextureNumForName(msd->toptexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->sector = §ors[SHORT(msd->sector)]; + } + W_ReleaseLumpNum(lump); +} + +/* +================= += += P_LoadBlockMap += +================= +*/ + +void P_LoadBlockMap(int lump) +{ + int i, count; + int lumplen; + + lumplen = W_LumpLength(lump); + + blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); + W_ReadLump(lump, blockmaplump); + blockmap = blockmaplump + 4; + + // Swap all short integers to native byte ordering: + + count = lumplen / 2; + + for (i = 0; i < count; i++) + blockmaplump[i] = SHORT(blockmaplump[i]); + + bmaporgx = blockmaplump[0] << FRACBITS; + bmaporgy = blockmaplump[1] << FRACBITS; + bmapwidth = blockmaplump[2]; + bmapheight = blockmaplump[3]; + + // clear out mobj chains + + count = sizeof(*blocklinks) * bmapwidth * bmapheight; + blocklinks = Z_Malloc(count, PU_LEVEL, 0); + memset(blocklinks, 0, count); +} + + + + +/* +================= += += P_GroupLines += += Builds sector line lists and subsector sector numbers += Finds block bounding boxes for sectors +================= +*/ + +void P_DegenMobjThinker(thinker_t *thinker) +{ + (void) thinker; + I_Error("This function should never get called."); +} + +void P_GroupLines(void) +{ + line_t **linebuffer; + int i, j; + line_t *li; + sector_t *sector; + subsector_t *ss; + seg_t *seg; + fixed_t bbox[4]; + int block; + +// look up sector number for each subsector + ss = subsectors; + for (i = 0; i < numsubsectors; i++, ss++) + { + seg = &segs[ss->firstline]; + ss->sector = seg->sidedef->sector; + } + +// count number of lines in each sector + li = lines; + totallines = 0; + for (i = 0; i < numlines; i++, li++) + { + totallines++; + li->frontsector->linecount++; + if (li->backsector && li->backsector != li->frontsector) + { + li->backsector->linecount++; + totallines++; + } + } + +// build line tables for each sector + linebuffer = Z_Malloc(totallines * sizeof(line_t *), PU_LEVEL, 0); + sector = sectors; + for (i = 0; i < numsectors; i++, sector++) + { + M_ClearBox(bbox); + sector->lines = linebuffer; + li = lines; + for (j = 0; j < numlines; j++, li++) + { + if (li->frontsector == sector || li->backsector == sector) + { + *linebuffer++ = li; + M_AddToBox(bbox, li->v1->x, li->v1->y); + M_AddToBox(bbox, li->v2->x, li->v2->y); + } + } + if (linebuffer - sector->lines != sector->linecount) + I_Error("P_GroupLines: miscounted"); + + // set the degenmobj_t to the middle of the bounding box + sector->soundorg.x = (bbox[BOXRIGHT] + bbox[BOXLEFT]) / 2; + sector->soundorg.y = (bbox[BOXTOP] + bbox[BOXBOTTOM]) / 2; + sector->soundorg.thinker.function = (think_t) P_DegenMobjThinker; + + // adjust bounding box to map blocks + block = (bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + block = block >= bmapheight ? bmapheight - 1 : block; + sector->blockbox[BOXTOP] = block; + + block = (bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXBOTTOM] = block; + + block = (bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + block = block >= bmapwidth ? bmapwidth - 1 : block; + sector->blockbox[BOXRIGHT] = block; + + block = (bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXLEFT] = block; + } + +} + + +static void P_LoadReject(int lumpnum) +{ + int minlength; + int lumplen; + + // Calculate the size that the REJECT lump *should* be. + + minlength = (numsectors * numsectors + 7) / 8; + + // If the lump meets the minimum length, it can be loaded directly. + // Otherwise, we need to allocate a buffer of the correct size + // and pad it with appropriate data. + + lumplen = W_LumpLength(lumpnum); + + if (lumplen >= minlength) + { + rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + else + { + rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); + W_ReadLump(lumpnum, rejectmatrix); + + PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); + } +} + +//============================================================================= + +lumpinfo_t *maplumpinfo; + +/* +================= += += P_SetupLevel += +================= +*/ + +void P_SetupLevel(int episode, int map, int playermask, skill_t skill) +{ + int i; + int parm; + char lumpname[9]; + int lumpnum; + mobj_t *mobj; + + for (i = 0; i < maxplayers; i++) + { + players[i].killcount = players[i].secretcount + = players[i].itemcount = 0; + } + players[consoleplayer].viewz = 1; // will be set by player think + + // Waiting-for-level-load song; not played if playing music from CD + // (the seek time will be so long it will just make loading take + // longer) + if (!cdmusic) + { + S_StartSongName("chess", true); + } + + Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + + P_InitThinkers(); + leveltime = 0; + + M_snprintf(lumpname, sizeof(lumpname), "MAP%02d", map); + lumpnum = W_GetNumForName(lumpname); + + maplumpinfo = lumpinfo[lumpnum]; + + // + // Begin processing map lumps + // Note: most of this ordering is important + // + P_LoadBlockMap(lumpnum + ML_BLOCKMAP); + P_LoadVertexes(lumpnum + ML_VERTEXES); + P_LoadSectors(lumpnum + ML_SECTORS); + P_LoadSideDefs(lumpnum + ML_SIDEDEFS); + P_LoadLineDefs(lumpnum + ML_LINEDEFS); + P_LoadSubsectors(lumpnum + ML_SSECTORS); + P_LoadNodes(lumpnum + ML_NODES); + P_LoadSegs(lumpnum + ML_SEGS); + P_GroupLines(); + P_LoadReject(lumpnum + ML_REJECT); + bodyqueslot = 0; + po_NumPolyobjs = 0; + deathmatch_p = deathmatchstarts; + P_LoadThings(lumpnum + ML_THINGS); + PO_Init(lumpnum + ML_THINGS); // Initialize the polyobjs + P_LoadACScripts(lumpnum + ML_BEHAVIOR); // ACS object code + // + // End of map lump processing + // + + // If deathmatch, randomly spawn the active players + TimerGame = 0; + if (deathmatch) + { + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { // must give a player spot before deathmatchspawn + mobj = P_SpawnMobj(playerstarts[0][i].x << 16, + playerstarts[0][i].y << 16, 0, + MT_PLAYER_FIGHTER); + players[i].mo = mobj; + G_DeathMatchSpawnPlayer(i); + P_RemoveMobj(mobj); + } + } + + //! + // @arg + // @category net + // @vanilla + // + // For multiplayer games: exit each level after n minutes. + // + + parm = M_CheckParmWithArgs("-timer", 1); + if (parm) + { + TimerGame = atoi(myargv[parm + 1]) * 35 * 60; + } + } + +// set up world state + P_SpawnSpecials(); + +// build subsector connect matrix +// P_ConnectSubsectors (); + +// Load colormap and set the fullbright flag + i = P_GetMapFadeTable(gamemap); + W_ReadLump(i, colormaps); + if (i == W_GetNumForName("COLORMAP")) + { + LevelUseFullBright = true; + } + else + { // Probably fog ... don't use fullbright sprites + LevelUseFullBright = false; + } + +// preload graphics + if (precache) + R_PrecacheLevel(); + + // Check if the level is a lightning level + P_InitLightning(); + + S_StopAllSound(); + SN_StopAllSequences(); + S_StartSong(gamemap, true); + +//printf ("free memory: 0x%x\n", Z_FreeMemory()); + +} + +//========================================================================== +// +// InitMapInfo +// +//========================================================================== + +static void InitMapInfo(void) +{ + int map; + int mapMax; + int mcmdValue; + mapInfo_t *info; + char songMulch[10]; + const char *default_sky_name = DEFAULT_SKY_NAME; + + mapMax = 1; + + if (gamemode == shareware) + { + default_sky_name = "SKY2"; + } + + // Put defaults into MapInfo[0] + info = MapInfo; + info->cluster = 0; + info->warpTrans = 0; + info->nextMap = 1; // Always go to map 1 if not specified + info->cdTrack = 1; + info->sky1Texture = R_TextureNumForName(default_sky_name); + info->sky2Texture = info->sky1Texture; + info->sky1ScrollDelta = 0; + info->sky2ScrollDelta = 0; + info->doubleSky = false; + info->lightning = false; + info->fadetable = W_GetNumForName(DEFAULT_FADE_TABLE); + M_StringCopy(info->name, UNKNOWN_MAP_NAME, sizeof(info->name)); + +// M_StringCopy(info->songLump, DEFAULT_SONG_LUMP, sizeof(info->songLump)); + SC_Open(MAPINFO_SCRIPT_NAME); + while (SC_GetString()) + { + if (SC_Compare("MAP") == false) + { + SC_ScriptError(NULL); + } + SC_MustGetNumber(); + if (sc_Number < 1 || sc_Number > 99) + { // + SC_ScriptError(NULL); + } + map = sc_Number; + + info = &MapInfo[map]; + + // Save song lump name + M_StringCopy(songMulch, info->songLump, sizeof(songMulch)); + + // Copy defaults to current map definition + memcpy(info, &MapInfo[0], sizeof(*info)); + + // Restore song lump name + M_StringCopy(info->songLump, songMulch, sizeof(info->songLump)); + + // The warp translation defaults to the map number + info->warpTrans = map; + + // Map name must follow the number + SC_MustGetString(); + M_StringCopy(info->name, sc_String, sizeof(info->name)); + + // Process optional tokens + while (SC_GetString()) + { + if (SC_Compare("MAP")) + { // Start next map definition + SC_UnGet(); + break; + } + mcmdValue = MapCmdIDs[SC_MustMatchString(MapCmdNames)]; + switch (mcmdValue) + { + case MCMD_CLUSTER: + SC_MustGetNumber(); + info->cluster = sc_Number; + break; + case MCMD_WARPTRANS: + SC_MustGetNumber(); + info->warpTrans = sc_Number; + break; + case MCMD_NEXT: + SC_MustGetNumber(); + info->nextMap = sc_Number; + break; + case MCMD_CDTRACK: + SC_MustGetNumber(); + info->cdTrack = sc_Number; + break; + case MCMD_SKY1: + SC_MustGetString(); + info->sky1Texture = R_TextureNumForName(sc_String); + SC_MustGetNumber(); + info->sky1ScrollDelta = sc_Number << 8; + break; + case MCMD_SKY2: + SC_MustGetString(); + info->sky2Texture = R_TextureNumForName(sc_String); + SC_MustGetNumber(); + info->sky2ScrollDelta = sc_Number << 8; + break; + case MCMD_DOUBLESKY: + info->doubleSky = true; + break; + case MCMD_LIGHTNING: + info->lightning = true; + break; + case MCMD_FADETABLE: + SC_MustGetString(); + info->fadetable = W_GetNumForName(sc_String); + break; + case MCMD_CD_STARTTRACK: + case MCMD_CD_END1TRACK: + case MCMD_CD_END2TRACK: + case MCMD_CD_END3TRACK: + case MCMD_CD_INTERTRACK: + case MCMD_CD_TITLETRACK: + SC_MustGetNumber(); + cd_NonLevelTracks[mcmdValue - MCMD_CD_STARTTRACK] = + sc_Number; + break; + } + } + mapMax = map > mapMax ? map : mapMax; + } + SC_Close(); + MapCount = mapMax; +} + +//========================================================================== +// +// P_GetMapCluster +// +//========================================================================== + +int P_GetMapCluster(int map) +{ + return MapInfo[QualifyMap(map)].cluster; +} + +//========================================================================== +// +// P_GetMapCDTrack +// +//========================================================================== + +int P_GetMapCDTrack(int map) +{ + return MapInfo[QualifyMap(map)].cdTrack; +} + +//========================================================================== +// +// P_GetMapWarpTrans +// +//========================================================================== + +int P_GetMapWarpTrans(int map) +{ + return MapInfo[QualifyMap(map)].warpTrans; +} + +//========================================================================== +// +// P_GetMapNextMap +// +//========================================================================== + +int P_GetMapNextMap(int map) +{ + return MapInfo[QualifyMap(map)].nextMap; +} + +//========================================================================== +// +// P_TranslateMap +// +// Returns the actual map number given a warp map number. +// +//========================================================================== + +int P_TranslateMap(int map) +{ + int i; + + for (i = 1; i < 99; i++) // Make this a macro + { + if (MapInfo[i].warpTrans == map) + { + return i; + } + } + // Not found + return -1; +} + +//========================================================================== +// +// P_GetMapSky1Texture +// +//========================================================================== + +int P_GetMapSky1Texture(int map) +{ + return MapInfo[QualifyMap(map)].sky1Texture; +} + +//========================================================================== +// +// P_GetMapSky2Texture +// +//========================================================================== + +int P_GetMapSky2Texture(int map) +{ + return MapInfo[QualifyMap(map)].sky2Texture; +} + +//========================================================================== +// +// P_GetMapName +// +//========================================================================== + +char *P_GetMapName(int map) +{ + return MapInfo[QualifyMap(map)].name; +} + +//========================================================================== +// +// P_GetMapSky1ScrollDelta +// +//========================================================================== + +fixed_t P_GetMapSky1ScrollDelta(int map) +{ + return MapInfo[QualifyMap(map)].sky1ScrollDelta; +} + +//========================================================================== +// +// P_GetMapSky2ScrollDelta +// +//========================================================================== + +fixed_t P_GetMapSky2ScrollDelta(int map) +{ + return MapInfo[QualifyMap(map)].sky2ScrollDelta; +} + +//========================================================================== +// +// P_GetMapDoubleSky +// +//========================================================================== + +boolean P_GetMapDoubleSky(int map) +{ + return MapInfo[QualifyMap(map)].doubleSky; +} + +//========================================================================== +// +// P_GetMapLightning +// +//========================================================================== + +boolean P_GetMapLightning(int map) +{ + return MapInfo[QualifyMap(map)].lightning; +} + +//========================================================================== +// +// P_GetMapFadeTable +// +//========================================================================== + +boolean P_GetMapFadeTable(int map) +{ + return MapInfo[QualifyMap(map)].fadetable; +} + +//========================================================================== +// +// P_GetMapSongLump +// +//========================================================================== + +char *P_GetMapSongLump(int map) +{ + if (!strcasecmp(MapInfo[QualifyMap(map)].songLump, DEFAULT_SONG_LUMP)) + { + return NULL; + } + else + { + return MapInfo[QualifyMap(map)].songLump; + } +} + +//========================================================================== +// +// P_PutMapSongLump +// +//========================================================================== + +void P_PutMapSongLump(int map, char *lumpName) +{ + if (map < 1 || map > MapCount) + { + return; + } + M_StringCopy(MapInfo[map].songLump, lumpName, + sizeof(MapInfo[map].songLump)); +} + +//========================================================================== +// +// P_GetCDStartTrack +// +//========================================================================== + +int P_GetCDStartTrack(void) +{ + return cd_NonLevelTracks[MCMD_CD_STARTTRACK - MCMD_CD_STARTTRACK]; +} + +//========================================================================== +// +// P_GetCDEnd1Track +// +//========================================================================== + +int P_GetCDEnd1Track(void) +{ + return cd_NonLevelTracks[MCMD_CD_END1TRACK - MCMD_CD_STARTTRACK]; +} + +//========================================================================== +// +// P_GetCDEnd2Track +// +//========================================================================== + +int P_GetCDEnd2Track(void) +{ + return cd_NonLevelTracks[MCMD_CD_END2TRACK - MCMD_CD_STARTTRACK]; +} + +//========================================================================== +// +// P_GetCDEnd3Track +// +//========================================================================== + +int P_GetCDEnd3Track(void) +{ + return cd_NonLevelTracks[MCMD_CD_END3TRACK - MCMD_CD_STARTTRACK]; +} + +//========================================================================== +// +// P_GetCDIntermissionTrack +// +//========================================================================== + +int P_GetCDIntermissionTrack(void) +{ + return cd_NonLevelTracks[MCMD_CD_INTERTRACK - MCMD_CD_STARTTRACK]; +} + +//========================================================================== +// +// P_GetCDTitleTrack +// +//========================================================================== + +int P_GetCDTitleTrack(void) +{ + return cd_NonLevelTracks[MCMD_CD_TITLETRACK - MCMD_CD_STARTTRACK]; +} + +//========================================================================== +// +// QualifyMap +// +//========================================================================== + +static int QualifyMap(int map) +{ + return (map < 1 || map > MapCount) ? 0 : map; +} + +//========================================================================== +// +// P_Init +// +//========================================================================== + +void P_Init(void) +{ + InitMapInfo(); + P_InitSwitchList(); + P_InitFTAnims(); // Init flat and texture animations + P_InitTerrainTypes(); + P_InitLava(); + R_InitSprites(sprnames); +} + + +// Special early initializer needed to start sound before R_Init() +void InitMapMusicInfo(void) +{ + int i; + + for (i = 0; i < 99; i++) + { + M_StringCopy(MapInfo[i].songLump, DEFAULT_SONG_LUMP, + sizeof(MapInfo[i].songLump)); + } + MapCount = 98; +} + +/* +void My_Debug(void) +{ + int i; + + printf("My debug stuff ----------------------\n"); + printf("gamemap=%d\n",gamemap); + for (i=0; i<10; i++) + { + printf("i=%d songlump=%s\n",i,MapInfo[i].songLump); + } +} +*/ diff --git a/games/NXDoom/src/hexen/p_sight.c b/games/NXDoom/src/hexen/p_sight.c new file mode 100644 index 00000000000..b5efd07f604 --- /dev/null +++ b/games/NXDoom/src/hexen/p_sight.c @@ -0,0 +1,398 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "p_local.h" + +/* +============================================================================== + + P_CheckSight + +This uses specialized forms of the maputils routines for optimized performance + +============================================================================== +*/ + +fixed_t sightzstart; // eye z of looker +fixed_t topslope, bottomslope; // slopes to top and bottom of target + +int sightcounts[3]; + +/* +============== += += PTR_SightTraverse += +============== +*/ + +boolean PTR_SightTraverse(intercept_t * in) +{ + line_t *li; + fixed_t slope; + + li = in->d.line; + +// +// crosses a two sided line +// + P_LineOpening(li); + + if (openbottom >= opentop) // quick test for totally closed doors + return false; // stop + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - sightzstart, in->frac); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - sightzstart, in->frac); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // keep going +} + + + +/* +================== += += P_SightBlockLinesIterator += +=================== +*/ + +boolean P_SightBlockLinesIterator(int x, int y) +{ + int offset; + short *list; + line_t *ld; + int s1, s2; + divline_t dl; + + polyblock_t *polyLink; + seg_t **segList; + int i; + + offset = y * bmapwidth + x; + + polyLink = PolyBlockMap[offset]; + while (polyLink) + { + if (polyLink->polyobj) + { // only check non-empty links + if (polyLink->polyobj->validcount != validcount) + { + segList = polyLink->polyobj->segs; + for (i = 0; i < polyLink->polyobj->numsegs; i++, segList++) + { + ld = (*segList)->linedef; + if (ld->validcount == validcount) + { + continue; + } + ld->validcount = validcount; + s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); + if (s1 == s2) + continue; // line isn't crossed + P_MakeDivline(ld, &dl); + s1 = P_PointOnDivlineSide(trace.x, trace.y, &dl); + s2 = P_PointOnDivlineSide(trace.x + trace.dx, + trace.y + trace.dy, &dl); + if (s1 == s2) + continue; // line isn't crossed + + // try to early out the check + if (!ld->backsector) + return false; // stop checking + + // store the line for later intersection testing + intercept_p->d.line = ld; + intercept_p++; + } + polyLink->polyobj->validcount = validcount; + } + } + polyLink = polyLink->next; + } + + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; // line has already been checked + ld->validcount = validcount; + + s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); + if (s1 == s2) + continue; // line isn't crossed + P_MakeDivline(ld, &dl); + s1 = P_PointOnDivlineSide(trace.x, trace.y, &dl); + s2 = P_PointOnDivlineSide(trace.x + trace.dx, trace.y + trace.dy, + &dl); + if (s1 == s2) + continue; // line isn't crossed + + // try to early out the check + if (!ld->backsector) + return false; // stop checking + + // store the line for later intersection testing + intercept_p->d.line = ld; + intercept_p++; + + } + + return true; // everything was checked +} + +/* +==================== += += P_SightTraverseIntercepts += += Returns true if the traverser function returns true for all lines +==================== +*/ + +boolean P_SightTraverseIntercepts(void) +{ + int count; + fixed_t dist; + intercept_t *scan, *in; + divline_t dl; + + count = intercept_p - intercepts; +// +// calculate intercept distance +// + for (scan = intercepts; scan < intercept_p; scan++) + { + P_MakeDivline(scan->d.line, &dl); + scan->frac = P_InterceptVector(&trace, &dl); + } + +// +// go through in order +// + in = 0; // shut up compiler warning + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts; scan < intercept_p; scan++) + if (scan->frac < dist) + { + dist = scan->frac; + in = scan; + } + + if (!PTR_SightTraverse(in)) + return false; // don't bother going farther + in->frac = INT_MAX; + } + + return true; // everything was traversed +} + + + +/* +================== += += P_SightPathTraverse += += Traces a line from x1,y1 to x2,y2, calling the traverser function for each += Returns true if the traverser function returns true for all lines +================== +*/ + +boolean P_SightPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) +{ + fixed_t xt1, yt1, xt2, yt2; + fixed_t xstep, ystep; + fixed_t partial; + fixed_t xintercept, yintercept; + int mapx, mapy, mapxstep, mapystep; + int count; + + validcount++; + intercept_p = intercepts; + + if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) + x1 += FRACUNIT; // don't side exactly on a line + if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) + y1 += FRACUNIT; // don't side exactly on a line + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1 >> MAPBLOCKSHIFT; + yt1 = y1 >> MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2 >> MAPBLOCKSHIFT; + yt2 = y2 >> MAPBLOCKSHIFT; + +// points should never be out of bounds, but check once instead of +// each block + if (xt1 < 0 || yt1 < 0 || xt1 >= bmapwidth || yt1 >= bmapheight + || xt2 < 0 || yt2 < 0 || xt2 >= bmapwidth || yt2 >= bmapheight) + return false; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); + ystep = FixedDiv(y2 - y1, abs(x2 - x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256 * FRACUNIT; + } + yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); + + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); + xstep = FixedDiv(x2 - x1, abs(y2 - y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256 * FRACUNIT; + } + xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); + + +// +// step through map blocks +// Count is present to prevent a round off error from skipping the break + mapx = xt1; + mapy = yt1; + + + for (count = 0; count < 64; count++) + { + if (!P_SightBlockLinesIterator(mapx, mapy)) + { + sightcounts[1]++; + return false; // early out + } + + if (mapx == xt2 && mapy == yt2) + break; + + if ((yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ((xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + + } + + +// +// couldn't early out, so go through the sorted list +// + sightcounts[2]++; + + return P_SightTraverseIntercepts(); +} + + + +/* +===================== += += P_CheckSight += += Returns true if a straight line between t1 and t2 is unobstructed += look from eyes of t1 to any part of t2 += +===================== +*/ + +boolean P_CheckSight(mobj_t * t1, mobj_t * t2) +{ + int s1, s2; + int pnum, bytenum, bitnum; + +// +// check for trivial rejection +// + s1 = (t1->subsector->sector - sectors); + s2 = (t2->subsector->sector - sectors); + pnum = s1 * numsectors + s2; + bytenum = pnum >> 3; + bitnum = 1 << (pnum & 7); + + if (rejectmatrix[bytenum] & bitnum) + { + sightcounts[0]++; + return false; // can't possibly be connected + } + +// +// check precisely +// + sightzstart = t1->z + t1->height - (t1->height >> 2); + topslope = (t2->z + t2->height) - sightzstart; + bottomslope = (t2->z) - sightzstart; + + return P_SightPathTraverse(t1->x, t1->y, t2->x, t2->y); +} diff --git a/games/NXDoom/src/hexen/p_spec.c b/games/NXDoom/src/hexen/p_spec.c new file mode 100644 index 00000000000..400bf70df32 --- /dev/null +++ b/games/NXDoom/src/hexen/p_spec.c @@ -0,0 +1,1202 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "i_system.h" +#include "m_misc.h" +#include "p_local.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +#define MAX_TAGGED_LINES 64 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static boolean CheckedLockedDoor(mobj_t * mo, byte lock); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +int *TerrainTypes; +struct +{ + const char *name; + int type; +} TerrainTypeDefs[] = +{ + { + "X_005", FLOOR_WATER}, + { + "X_001", FLOOR_LAVA}, + { + "X_009", FLOOR_SLUDGE}, + { + "F_033", FLOOR_ICE}, + { + "END", -1} +}; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static struct +{ + line_t *line; + int lineTag; +} TaggedLines[MAX_TAGGED_LINES]; +static int TaggedLineCount; + +mobj_t LavaInflictor; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// P_InitLava +// +//========================================================================== + +void P_InitLava(void) +{ + memset(&LavaInflictor, 0, sizeof(mobj_t)); + LavaInflictor.type = MT_CIRCLEFLAME; + LavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST; +} + +//========================================================================== +// +// P_InitTerrainTypes +// +//========================================================================== + +void P_InitTerrainTypes(void) +{ + int i; + int lump; + int size; + + size = (numflats + 1) * sizeof(int); + TerrainTypes = Z_Malloc(size, PU_STATIC, 0); + memset(TerrainTypes, 0, size); + for (i = 0; TerrainTypeDefs[i].type != -1; i++) + { + lump = W_CheckNumForName(TerrainTypeDefs[i].name); + if (lump != -1) + { + TerrainTypes[lump - firstflat] = TerrainTypeDefs[i].type; + } + } +} + +//========================================================================== +// +// getSide +// +// Will return a side_t* given the number of the current sector, the +// line number, and the side (0/1) that you want. +// +//========================================================================== + +/* +side_t *getSide(int currentSector, int line, int side) +{ + return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; +} +*/ + +//========================================================================== +// +// getSector +// +// Will return a sector_t* given the number of the current sector, the +// line number, and the side (0/1) that you want. +// +//========================================================================== + +/* +sector_t *getSector(int currentSector, int line, int side) +{ + return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; +} +*/ + +//========================================================================== +// +// twoSided +// +// Given the sector number and the line number, will tell you whether +// the line is two-sided or not. +// +//========================================================================== + +/* +int twoSided(int sector, int line) +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} +*/ + +//================================================================== +// +// Return sector_t * of sector next to current. NULL if not two-sided line +// +//================================================================== +sector_t *getNextSector(line_t * line, sector_t * sec) +{ + if (!(line->flags & ML_TWOSIDED)) + return NULL; + + if (line->frontsector == sec) + return line->backsector; + + return line->frontsector; +} + +//================================================================== +// +// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindLowestFloorSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t floor = sec->floorheight; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->floorheight < floor) + floor = other->floorheight; + } + return floor; +} + +//================================================================== +// +// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindHighestFloorSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t floor = -500 * FRACUNIT; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->floorheight > floor) + floor = other->floorheight; + } + return floor; +} + +//================================================================== +// +// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight) +{ + int i; + int h; + int min; + line_t *check; + sector_t *other; + fixed_t height = currentheight; + fixed_t heightlist[20]; // 20 adjoining sectors max! + + heightlist[0] = 0; + + for (i = 0, h = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->floorheight > height) + heightlist[h++] = other->floorheight; + } + + // + // Find lowest height in list + // + min = heightlist[0]; + for (i = 1; i < h; i++) + if (heightlist[i] < min) + min = heightlist[i]; + + return min; +} + +//================================================================== +// +// FIND LOWEST CEILING IN THE SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindLowestCeilingSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t height = INT_MAX; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->ceilingheight < height) + height = other->ceilingheight; + } + return height; +} + +//================================================================== +// +// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS +// +//================================================================== +fixed_t P_FindHighestCeilingSurrounding(sector_t * sec) +{ + int i; + line_t *check; + sector_t *other; + fixed_t height = 0; + + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check, sec); + if (!other) + continue; + if (other->ceilingheight > height) + height = other->ceilingheight; + } + return height; +} + +//================================================================== +// +// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO +// +//================================================================== + +/* +int P_FindSectorFromLineTag(line_t *line,int start) +{ + int i; + + for (i=start+1;iarg1) + return i; + return -1; +} +*/ + +//========================================================================= +// +// P_FindSectorFromTag +// +//========================================================================= + +int P_FindSectorFromTag(int tag, int start) +{ + int i; + + for (i = start + 1; i < numsectors; i++) + { + if (sectors[i].tag == tag) + { + return i; + } + } + return -1; +} + +//================================================================== +// +// Find minimum light from an adjacent sector +// +//================================================================== + +/* +int P_FindMinSurroundingLight(sector_t *sector,int max) +{ + int i; + int min; + line_t *line; + sector_t *check; + + min = max; + for (i=0 ; i < sector->linecount ; i++) + { + line = sector->lines[i]; + check = getNextSector(line,sector); + if (!check) + continue; + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} +*/ + +//========================================================================= +// +// EV_SectorSoundChange +// +//========================================================================= + +boolean EV_SectorSoundChange(byte * args) +{ + int secNum; + boolean rtn; + + if (!args[0]) + { + return false; + } + secNum = -1; + rtn = false; + while ((secNum = P_FindSectorFromTag(args[0], secNum)) >= 0) + { + sectors[secNum].seqType = args[1]; + rtn = true; + } + return rtn; +} + +//============================================================================ +// +// CheckedLockedDoor +// +//============================================================================ + +static boolean CheckedLockedDoor(mobj_t * mo, byte lock) +{ + char LockedBuffer[80]; + + if (!mo->player) + { + return false; + } + if (!lock) + { + return true; + } + if (!(mo->player->keys & (1 << (lock - 1)))) + { + M_snprintf(LockedBuffer, sizeof(LockedBuffer), + "YOU NEED THE %s\n", TextKeyMessages[lock - 1]); + P_SetMessage(mo->player, LockedBuffer, true); + S_StartSound(mo, SFX_DOOR_LOCKED); + return false; + } + return true; +} + + +//========================================================================== +// +// EV_LineSearchForPuzzleItem +// +//========================================================================== + +boolean EV_LineSearchForPuzzleItem(line_t * line, byte * args, mobj_t * mo) +{ + player_t *player; + int i; + int type; + artitype_t arti; + + if (!mo) + return false; + player = mo->player; + if (!player) + return false; + + // Search player's inventory for puzzle items + for (i = 0; i < player->artifactCount; i++) + { + arti = player->inventory[i].type; + type = arti - arti_firstpuzzitem; + if (type < 0) + continue; + if (type == line->arg1) + { + // A puzzle item was found for the line + if (P_UseArtifact(player, arti)) + { + // A puzzle item was found for the line + P_PlayerRemoveArtifact(player, i); + if (player == &players[consoleplayer]) + { + if (arti < arti_firstpuzzitem) + { + S_StartSound(NULL, SFX_ARTIFACT_USE); + } + else + { + S_StartSound(NULL, SFX_PUZZLE_SUCCESS); + } + ArtifactFlash = 4; + } + return true; + } + } + } + return false; +} + + + +/* +============================================================================== + + EVENTS + +Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers + +============================================================================== +*/ +//============================================================================ +// +// P_ExecuteLineSpecial +// +// Invoked when crossing a linedef. The args[] array should be at least +// 5 elements in length. +// +//============================================================================ + +boolean P_ExecuteLineSpecial(int special, byte * args, line_t * line, + int side, mobj_t * mo) +{ + boolean buttonSuccess; + + buttonSuccess = false; + switch (special) + { + case 1: // Poly Start Line + break; + case 2: // Poly Rotate Left + buttonSuccess = EV_RotatePoly(line, args, 1, false); + break; + case 3: // Poly Rotate Right + buttonSuccess = EV_RotatePoly(line, args, -1, false); + break; + case 4: // Poly Move + buttonSuccess = EV_MovePoly(line, args, false, false); + break; + case 5: // Poly Explicit Line: Only used in initialization + break; + case 6: // Poly Move Times 8 + buttonSuccess = EV_MovePoly(line, args, true, false); + break; + case 7: // Poly Door Swing + buttonSuccess = EV_OpenPolyDoor(line, args, PODOOR_SWING); + break; + case 8: // Poly Door Slide + buttonSuccess = EV_OpenPolyDoor(line, args, PODOOR_SLIDE); + break; + case 10: // Door Close + buttonSuccess = EV_DoDoor(line, args, DREV_CLOSE); + break; + case 11: // Door Open + if (!args[0]) + { + buttonSuccess = EV_VerticalDoor(line, mo); + } + else + { + buttonSuccess = EV_DoDoor(line, args, DREV_OPEN); + } + break; + case 12: // Door Raise + if (!args[0]) + { + buttonSuccess = EV_VerticalDoor(line, mo); + } + else + { + buttonSuccess = EV_DoDoor(line, args, DREV_NORMAL); + } + break; + case 13: // Door Locked_Raise + if (CheckedLockedDoor(mo, args[3])) + { + if (!args[0]) + { + buttonSuccess = EV_VerticalDoor(line, mo); + } + else + { + buttonSuccess = EV_DoDoor(line, args, DREV_NORMAL); + } + } + break; + case 20: // Floor Lower by Value + buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE); + break; + case 21: // Floor Lower to Lowest + buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERFLOORTOLOWEST); + break; + case 22: // Floor Lower to Nearest + buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERFLOOR); + break; + case 23: // Floor Raise by Value + buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE); + break; + case 24: // Floor Raise to Highest + buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOOR); + break; + case 25: // Floor Raise to Nearest + buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOORTONEAREST); + break; + case 26: // Stairs Build Down Normal + buttonSuccess = EV_BuildStairs(line, args, -1, STAIRS_NORMAL); + break; + case 27: // Build Stairs Up Normal + buttonSuccess = EV_BuildStairs(line, args, 1, STAIRS_NORMAL); + break; + case 28: // Floor Raise and Crush + buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOORCRUSH); + break; + case 29: // Build Pillar (no crushing) + buttonSuccess = EV_BuildPillar(line, args, false); + break; + case 30: // Open Pillar + buttonSuccess = EV_OpenPillar(line, args); + break; + case 31: // Stairs Build Down Sync + buttonSuccess = EV_BuildStairs(line, args, -1, STAIRS_SYNC); + break; + case 32: // Build Stairs Up Sync + buttonSuccess = EV_BuildStairs(line, args, 1, STAIRS_SYNC); + break; + case 35: // Raise Floor by Value Times 8 + buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEBYVALUETIMES8); + break; + case 36: // Lower Floor by Value Times 8 + buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERBYVALUETIMES8); + break; + case 40: // Ceiling Lower by Value + buttonSuccess = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE); + break; + case 41: // Ceiling Raise by Value + buttonSuccess = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE); + break; + case 42: // Ceiling Crush and Raise + buttonSuccess = EV_DoCeiling(line, args, CLEV_CRUSHANDRAISE); + break; + case 43: // Ceiling Lower and Crush + buttonSuccess = EV_DoCeiling(line, args, CLEV_LOWERANDCRUSH); + break; + case 44: // Ceiling Crush Stop + buttonSuccess = EV_CeilingCrushStop(line, args); + break; + case 45: // Ceiling Crush Raise and Stay + buttonSuccess = EV_DoCeiling(line, args, CLEV_CRUSHRAISEANDSTAY); + break; + case 46: // Floor Crush Stop + buttonSuccess = EV_FloorCrushStop(line, args); + break; + case 60: // Plat Perpetual Raise + buttonSuccess = EV_DoPlat(line, args, PLAT_PERPETUALRAISE, 0); + break; + case 61: // Plat Stop + EV_StopPlat(line, args); + break; + case 62: // Plat Down-Wait-Up-Stay + buttonSuccess = EV_DoPlat(line, args, PLAT_DOWNWAITUPSTAY, 0); + break; + case 63: // Plat Down-by-Value*8-Wait-Up-Stay + buttonSuccess = EV_DoPlat(line, args, PLAT_DOWNBYVALUEWAITUPSTAY, + 0); + break; + case 64: // Plat Up-Wait-Down-Stay + buttonSuccess = EV_DoPlat(line, args, PLAT_UPWAITDOWNSTAY, 0); + break; + case 65: // Plat Up-by-Value*8-Wait-Down-Stay + buttonSuccess = EV_DoPlat(line, args, PLAT_UPBYVALUEWAITDOWNSTAY, + 0); + break; + case 66: // Floor Lower Instant * 8 + buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERTIMES8INSTANT); + break; + case 67: // Floor Raise Instant * 8 + buttonSuccess = EV_DoFloor(line, args, FLEV_RAISETIMES8INSTANT); + break; + case 68: // Floor Move to Value * 8 + buttonSuccess = EV_DoFloor(line, args, FLEV_MOVETOVALUETIMES8); + break; + case 69: // Ceiling Move to Value * 8 + buttonSuccess = EV_DoCeiling(line, args, CLEV_MOVETOVALUETIMES8); + break; + case 70: // Teleport + if (side == 0) + { // Only teleport when crossing the front side of a line + buttonSuccess = EV_Teleport(args[0], mo, true); + } + break; + case 71: // Teleport, no fog + if (side == 0) + { // Only teleport when crossing the front side of a line + buttonSuccess = EV_Teleport(args[0], mo, false); + } + break; + case 72: // Thrust Mobj + if (!side) // Only thrust on side 0 + { + P_ThrustMobj(mo, args[0] * (ANG90 / 64), + args[1] << FRACBITS); + buttonSuccess = 1; + } + break; + case 73: // Damage Mobj + if (args[0]) + { + P_DamageMobj(mo, NULL, NULL, args[0]); + } + else + { // If arg1 is zero, then guarantee a kill + P_DamageMobj(mo, NULL, NULL, 10000); + } + buttonSuccess = 1; + break; + case 74: // Teleport_NewMap + if (side == 0) + { // Only teleport when crossing the front side of a line + if (!(mo && mo->player && mo->player->playerstate == PST_DEAD)) // Players must be alive to teleport + { + G_Completed(args[0], args[1]); + buttonSuccess = true; + } + } + break; + case 75: // Teleport_EndGame + if (side == 0) + { // Only teleport when crossing the front side of a line + if (!(mo && mo->player && mo->player->playerstate == PST_DEAD)) // Players must be alive to teleport + { + buttonSuccess = true; + if (deathmatch) + { // Winning in deathmatch just goes back to map 1 + G_Completed(1, 0); + } + else + { // Passing -1, -1 to G_Completed() starts the Finale + G_Completed(-1, -1); + } + } + } + break; + case 80: // ACS_Execute + buttonSuccess = + P_StartACS(args[0], args[1], &args[2], mo, line, side); + break; + case 81: // ACS_Suspend + buttonSuccess = P_SuspendACS(args[0], args[1]); + break; + case 82: // ACS_Terminate + buttonSuccess = P_TerminateACS(args[0], args[1]); + break; + case 83: // ACS_LockedExecute + buttonSuccess = P_StartLockedACS(line, args, mo, side); + break; + case 90: // Poly Rotate Left Override + buttonSuccess = EV_RotatePoly(line, args, 1, true); + break; + case 91: // Poly Rotate Right Override + buttonSuccess = EV_RotatePoly(line, args, -1, true); + break; + case 92: // Poly Move Override + buttonSuccess = EV_MovePoly(line, args, false, true); + break; + case 93: // Poly Move Times 8 Override + buttonSuccess = EV_MovePoly(line, args, true, true); + break; + case 94: // Build Pillar Crush + buttonSuccess = EV_BuildPillar(line, args, true); + break; + case 95: // Lower Floor and Ceiling + buttonSuccess = EV_DoFloorAndCeiling(line, args, false); + break; + case 96: // Raise Floor and Ceiling + buttonSuccess = EV_DoFloorAndCeiling(line, args, true); + break; + case 109: // Force Lightning + buttonSuccess = true; + P_ForceLightning(); + break; + case 110: // Light Raise by Value + buttonSuccess = EV_SpawnLight(line, args, LITE_RAISEBYVALUE); + break; + case 111: // Light Lower by Value + buttonSuccess = EV_SpawnLight(line, args, LITE_LOWERBYVALUE); + break; + case 112: // Light Change to Value + buttonSuccess = EV_SpawnLight(line, args, LITE_CHANGETOVALUE); + break; + case 113: // Light Fade + buttonSuccess = EV_SpawnLight(line, args, LITE_FADE); + break; + case 114: // Light Glow + buttonSuccess = EV_SpawnLight(line, args, LITE_GLOW); + break; + case 115: // Light Flicker + buttonSuccess = EV_SpawnLight(line, args, LITE_FLICKER); + break; + case 116: // Light Strobe + buttonSuccess = EV_SpawnLight(line, args, LITE_STROBE); + break; + case 120: // Quake Tremor + buttonSuccess = A_LocalQuake(args, mo); + break; + case 129: // UsePuzzleItem + buttonSuccess = EV_LineSearchForPuzzleItem(line, args, mo); + break; + case 130: // Thing_Activate + buttonSuccess = EV_ThingActivate(args[0]); + break; + case 131: // Thing_Deactivate + buttonSuccess = EV_ThingDeactivate(args[0]); + break; + case 132: // Thing_Remove + buttonSuccess = EV_ThingRemove(args[0]); + break; + case 133: // Thing_Destroy + buttonSuccess = EV_ThingDestroy(args[0]); + break; + case 134: // Thing_Projectile + buttonSuccess = EV_ThingProjectile(args, 0); + break; + case 135: // Thing_Spawn + buttonSuccess = EV_ThingSpawn(args, 1); + break; + case 136: // Thing_ProjectileGravity + buttonSuccess = EV_ThingProjectile(args, 1); + break; + case 137: // Thing_SpawnNoFog + buttonSuccess = EV_ThingSpawn(args, 0); + break; + case 138: // Floor_Waggle + buttonSuccess = EV_StartFloorWaggle(args[0], args[1], + args[2], args[3], args[4]); + break; + case 140: // Sector_SoundChange + buttonSuccess = EV_SectorSoundChange(args); + break; + + // Line specials only processed during level initialization + // 100: Scroll_Texture_Left + // 101: Scroll_Texture_Right + // 102: Scroll_Texture_Up + // 103: Scroll_Texture_Down + // 121: Line_SetIdentification + + // Inert Line specials + default: + break; + } + return buttonSuccess; +} + +//============================================================================ +// +// P_ActivateLine +// +//============================================================================ + +boolean P_ActivateLine(line_t * line, mobj_t * mo, int side, + int activationType) +{ + byte args[5]; + int lineActivation; + boolean repeat; + boolean buttonSuccess; + + lineActivation = GET_SPAC(line->flags); + if (lineActivation != activationType) + { + return false; + } + if (!mo->player && !(mo->flags & MF_MISSILE)) + { + if (lineActivation != SPAC_MCROSS) + { // currently, monsters can only activate the MCROSS activation type + return false; + } + if (line->flags & ML_SECRET) + return false; // never open secret doors + } + repeat = (line->flags & ML_REPEAT_SPECIAL) != 0; + + // Construct args[] array to contain the arguments from the line, as we + // cannot rely on struct field ordering and layout. + args[0] = line->arg1; + args[1] = line->arg2; + args[2] = line->arg3; + args[3] = line->arg4; + args[4] = line->arg5; + buttonSuccess = P_ExecuteLineSpecial(line->special, args, line, side, mo); + if (!repeat && buttonSuccess) + { // clear the special on non-retriggerable lines + line->special = 0; + } + if ((lineActivation == SPAC_USE || lineActivation == SPAC_IMPACT) + && buttonSuccess) + { + P_ChangeSwitchTexture(line, repeat); + } + return true; +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerInSpecialSector +// +// Called every tic frame that the player origin is in a special sector. +// +//---------------------------------------------------------------------------- + +void P_PlayerInSpecialSector(player_t * player) +{ + sector_t *sector; + static int pushTab[3] = { + 2048 * 5, + 2048 * 10, + 2048 * 25 + }; + + sector = player->mo->subsector->sector; + if (player->mo->z != sector->floorheight) + { // Player is not touching the floor + return; + } + switch (sector->special) + { + case 9: // SecretArea + player->secretcount++; + sector->special = 0; + break; + + case 201: + case 202: + case 203: // Scroll_North_xxx + P_Thrust(player, ANG90, pushTab[sector->special - 201]); + break; + case 204: + case 205: + case 206: // Scroll_East_xxx + P_Thrust(player, 0, pushTab[sector->special - 204]); + break; + case 207: + case 208: + case 209: // Scroll_South_xxx + P_Thrust(player, ANG270, pushTab[sector->special - 207]); + break; + case 210: + case 211: + case 212: // Scroll_West_xxx + P_Thrust(player, ANG180, pushTab[sector->special - 210]); + break; + case 213: + case 214: + case 215: // Scroll_NorthWest_xxx + P_Thrust(player, ANG90 + ANG45, pushTab[sector->special - 213]); + break; + case 216: + case 217: + case 218: // Scroll_NorthEast_xxx + P_Thrust(player, ANG45, pushTab[sector->special - 216]); + break; + case 219: + case 220: + case 221: // Scroll_SouthEast_xxx + P_Thrust(player, ANG270 + ANG45, pushTab[sector->special - 219]); + break; + case 222: + case 223: + case 224: // Scroll_SouthWest_xxx + P_Thrust(player, ANG180 + ANG45, pushTab[sector->special - 222]); + break; + + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + // Wind specials are handled in (P_mobj):P_XYMovement + break; + + case 26: // Stairs_Special1 + case 27: // Stairs_Special2 + // Used in (P_floor):ProcessStairSector + break; + + case 198: // Lightning Special + case 199: // Lightning Flash special + case 200: // Sky2 + // Used in (R_plane):R_Drawplanes + break; + default: + I_Error("P_PlayerInSpecialSector: " + "unknown special %i", sector->special); + } +} + +//============================================================================ +// +// P_PlayerOnSpecialFlat +// +//============================================================================ + +void P_PlayerOnSpecialFlat(player_t * player, int floorType) +{ + if (player->mo->z != player->mo->floorz) + { // Player is not touching the floor + return; + } + switch (floorType) + { + case FLOOR_LAVA: + if (!(leveltime & 31)) + { + P_DamageMobj(player->mo, &LavaInflictor, NULL, 10); + S_StartSound(player->mo, SFX_LAVA_SIZZLE); + } + break; + default: + break; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_UpdateSpecials +// +//---------------------------------------------------------------------------- + +void P_UpdateSpecials(void) +{ + int i; + + // Handle buttons + for (i = 0; i < MAXBUTTONS; i++) + { + if (buttonlist[i].btimer) + { + buttonlist[i].btimer--; + if (!buttonlist[i].btimer) + { + switch (buttonlist[i].where) + { + case SWTCH_TOP: + sides[buttonlist[i].line->sidenum[0]].toptexture = + buttonlist[i].btexture; + break; + case SWTCH_MIDDLE: + sides[buttonlist[i].line->sidenum[0]].midtexture = + buttonlist[i].btexture; + break; + case SWTCH_BOTTOM: + sides[buttonlist[i].line->sidenum[0]].bottomtexture = + buttonlist[i].btexture; + break; + } + //S_StartSound((mobj_t *)&buttonlist[i].soundorg, sfx_switch); + memset(&buttonlist[i], 0, sizeof(button_t)); + } + } + } +} + +/* +============================================================================== + + SPECIAL SPAWNING + +============================================================================== +*/ +/* +================================================================================ += P_SpawnSpecials += += After the map has been loaded, scan for specials that += spawn thinkers += +=============================================================================== +*/ + +short numlinespecials; +line_t *linespeciallist[MAXLINEANIMS]; + +void P_SpawnSpecials(void) +{ + sector_t *sector; + int i; + + // + // Init special SECTORs + // + sector = sectors; + for (i = 0; i < numsectors; i++, sector++) + { + if (!sector->special) + continue; + switch (sector->special) + { + case 1: // Phased light + // Hardcoded base, use sector->lightlevel as the index + P_SpawnPhasedLight(sector, 80, -1); + break; + case 2: // Phased light sequence start + P_SpawnLightSequence(sector, 1); + break; + // Specials 3 & 4 are used by the phased light sequences + + /* + case 1: // FLICKERING LIGHTS + P_SpawnLightFlash (sector); + break; + case 2: // STROBE FAST + P_SpawnStrobeFlash(sector,FASTDARK,0); + break; + case 3: // STROBE SLOW + P_SpawnStrobeFlash(sector,SLOWDARK,0); + break; + case 4: // STROBE FAST/DEATH SLIME + P_SpawnStrobeFlash(sector,FASTDARK,0); + sector->special = 4; + break; + case 8: // GLOWING LIGHT + P_SpawnGlowingLight(sector); + break; + case 9: // SECRET SECTOR + totalsecret++; + break; + case 10: // DOOR CLOSE IN 30 SECONDS + P_SpawnDoorCloseIn30 (sector); + break; + case 12: // SYNC STROBE SLOW + P_SpawnStrobeFlash (sector, SLOWDARK, 1); + break; + case 13: // SYNC STROBE FAST + P_SpawnStrobeFlash (sector, FASTDARK, 1); + break; + case 14: // DOOR RAISE IN 5 MINUTES + P_SpawnDoorRaiseIn5Mins (sector, i); + break; + */ + } + } + + + // + // Init line EFFECTs + // + numlinespecials = 0; + TaggedLineCount = 0; + for (i = 0; i < numlines; i++) + { + switch (lines[i].special) + { + case 100: // Scroll_Texture_Left + case 101: // Scroll_Texture_Right + case 102: // Scroll_Texture_Up + case 103: // Scroll_Texture_Down + linespeciallist[numlinespecials] = &lines[i]; + numlinespecials++; + break; + case 121: // Line_SetIdentification + if (lines[i].arg1) + { + if (TaggedLineCount == MAX_TAGGED_LINES) + { + I_Error("P_SpawnSpecials: MAX_TAGGED_LINES " + "(%d) exceeded.", MAX_TAGGED_LINES); + } + TaggedLines[TaggedLineCount].line = &lines[i]; + TaggedLines[TaggedLineCount++].lineTag = lines[i].arg1; + } + lines[i].special = 0; + break; + } + } + + // + // Init other misc stuff + // + for (i = 0; i < MAXCEILINGS; i++) + activeceilings[i] = NULL; + for (i = 0; i < MAXPLATS; i++) + activeplats[i] = NULL; + for (i = 0; i < MAXBUTTONS; i++) + memset(&buttonlist[i], 0, sizeof(button_t)); + + // Initialize flat and texture animations + P_InitFTAnims(); +} + +//========================================================================== +// +// P_FindLine +// +//========================================================================== + +line_t *P_FindLine(int lineTag, int *searchPosition) +{ + int i; + + for (i = *searchPosition + 1; i < TaggedLineCount; i++) + { + if (TaggedLines[i].lineTag == lineTag) + { + *searchPosition = i; + return TaggedLines[i].line; + } + } + *searchPosition = -1; + return NULL; +} diff --git a/games/NXDoom/src/hexen/p_spec.h b/games/NXDoom/src/hexen/p_spec.h new file mode 100644 index 00000000000..3814484baa1 --- /dev/null +++ b/games/NXDoom/src/hexen/p_spec.h @@ -0,0 +1,586 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef P_SPEC_H +#define P_SPEC_H + + +extern int *TerrainTypes; + +// +// scrolling line specials +// + +#define MAXLINEANIMS 64 +extern short numlinespecials; +extern line_t *linespeciallist[MAXLINEANIMS]; + +extern mobj_t LavaInflictor; + + +// Define values for map objects +#define MO_TELEPORTMAN 14 + +// at game start +void P_InitTerrainTypes(void); +void P_InitLava(void); + +// at map load +void P_SpawnSpecials(void); + +// every tic +void P_UpdateSpecials(void); + +// when needed +boolean P_ExecuteLineSpecial(int special, byte * args, line_t * line, + int side, mobj_t * mo); +boolean P_ActivateLine(line_t * ld, mobj_t * mo, int side, + int activationType); +//boolean P_UseSpecialLine ( mobj_t *thing, line_t *line); +//void P_ShootSpecialLine ( mobj_t *thing, line_t *line); +//void P_CrossSpecialLine (int linenum, int side, mobj_t *thing); + +void P_PlayerInSpecialSector(player_t * player); +void P_PlayerOnSpecialFlat(player_t * player, int floorType); + +//int twoSided(int sector,int line); +//sector_t *getSector(int currentSector,int line,int side); +//side_t *getSide(int currentSector,int line, int side); +fixed_t P_FindLowestFloorSurrounding(sector_t * sec); +fixed_t P_FindHighestFloorSurrounding(sector_t * sec); +fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight); +fixed_t P_FindLowestCeilingSurrounding(sector_t * sec); +fixed_t P_FindHighestCeilingSurrounding(sector_t * sec); +//int P_FindSectorFromLineTag(line_t *line,int start); +int P_FindSectorFromTag(int tag, int start); +//int P_FindMinSurroundingLight(sector_t *sector,int max); +sector_t *getNextSector(line_t * line, sector_t * sec); +line_t *P_FindLine(int lineTag, int *searchPosition); + +// +// SPECIAL +// +//int EV_DoDonut(line_t *line); + +//------------------------------- +// P_anim.c +//------------------------------- + + +extern fixed_t Sky1ScrollDelta; +extern fixed_t Sky2ScrollDelta; + + +void P_AnimateSurfaces(void); +void P_InitFTAnims(void); +void P_InitLightning(void); +void P_ForceLightning(void); + +/* +=============================================================================== + + P_LIGHTS + +=============================================================================== +*/ + +typedef enum +{ + LITE_RAISEBYVALUE, + LITE_LOWERBYVALUE, + LITE_CHANGETOVALUE, + LITE_FADE, + LITE_GLOW, + LITE_FLICKER, + LITE_STROBE +} lighttype_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + lighttype_t type; + int value1; + int value2; + int tics1; + int tics2; + int count; +} light_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int index; + int base; +} phase_t; + +#define LIGHT_SEQUENCE_START 2 +#define LIGHT_SEQUENCE 3 +#define LIGHT_SEQUENCE_ALT 4 + +void T_Phase(thinker_t *thinker); +void T_Light(thinker_t *thinker); +void P_SpawnPhasedLight(sector_t * sector, int base, int index); +void P_SpawnLightSequence(sector_t * sector, int indexStep); +boolean EV_SpawnLight(line_t * line, byte * arg, lighttype_t type); + +#if 0 +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int maxlight; + int minlight; + int maxtime; + int mintime; +} lightflash_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int minlight; + int maxlight; + int darktime; + int brighttime; +} strobe_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int minlight; + int maxlight; + int direction; +} glow_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int index; + int base; +} phase_t; + +#define GLOWSPEED 8 +#define STROBEBRIGHT 5 +#define FASTDARK 15 +#define SLOWDARK 35 + +#define LIGHT_SEQUENCE_START 2 +#define LIGHT_SEQUENCE 3 +#define LIGHT_SEQUENCE_ALT 4 + +void T_LightFlash(lightflash_t * flash); +void P_SpawnLightFlash(sector_t * sector); +void T_StrobeFlash(strobe_t * flash); +void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync); +void EV_StartLightStrobing(line_t * line); +void EV_TurnTagLightsOff(line_t * line); +void EV_LightTurnOn(line_t * line, int bright); +void T_Glow(glow_t * g); +void P_SpawnGlowingLight(sector_t * sector); +void T_Phase(phase_t * phase); +void P_SpawnPhasedLight(sector_t * sector, int base, int index); +void P_SpawnLightSequence(sector_t * sector, int indexStep); +#endif + +/* +=============================================================================== + + P_SWITCH + +=============================================================================== +*/ +typedef struct +{ + char name1[9]; + char name2[9]; + int soundID; +} switchlist_t; + +typedef enum +{ + SWTCH_TOP, + SWTCH_MIDDLE, + SWTCH_BOTTOM +} bwhere_e; + +typedef struct +{ + line_t *line; + bwhere_e where; + int btexture; + int btimer; + mobj_t *soundorg; +} button_t; + +#define MAXSWITCHES 50 // max # of wall switches in a level +#define MAXBUTTONS 16 // 4 players, 4 buttons each at once, max. +#define BUTTONTIME 35 // 1 second + +extern button_t buttonlist[MAXBUTTONS]; + +void P_ChangeSwitchTexture(line_t * line, int useAgain); +void P_InitSwitchList(void); + +/* +=============================================================================== + + P_PLATS + +=============================================================================== +*/ + +typedef enum +{ + PLAT_UP, + PLAT_DOWN, + PLAT_WAITING, +// PLAT_IN_STASIS +} plat_e; + +typedef enum +{ + PLAT_PERPETUALRAISE, + PLAT_DOWNWAITUPSTAY, + PLAT_DOWNBYVALUEWAITUPSTAY, + PLAT_UPWAITDOWNSTAY, + PLAT_UPBYVALUEWAITDOWNSTAY, + //PLAT_RAISEANDCHANGE, + //PLAT_RAISETONEARESTANDCHANGE +} plattype_e; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + fixed_t speed; + fixed_t low; + fixed_t high; + int wait; + int count; + plat_e status; + plat_e oldstatus; + int crush; + int tag; + plattype_e type; +} plat_t; + +#define PLATWAIT 3 +#define PLATSPEED FRACUNIT +#define MAXPLATS 30 + +extern plat_t *activeplats[MAXPLATS]; + +void T_PlatRaise(thinker_t *thinker); +int EV_DoPlat(line_t * line, byte * args, plattype_e type, int amount); +void P_AddActivePlat(plat_t * plat); +void P_RemoveActivePlat(plat_t * plat); +void EV_StopPlat(line_t * line, byte * args); + +/* +=============================================================================== + + P_DOORS + +=============================================================================== +*/ +typedef enum +{ + DREV_NORMAL, + DREV_CLOSE30THENOPEN, + DREV_CLOSE, + DREV_OPEN, + DREV_RAISEIN5MINS, +} vldoor_e; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + vldoor_e type; + fixed_t topheight; + fixed_t speed; + int direction; // 1 = up, 0 = waiting at top, -1 = down + int topwait; // tics to wait at the top (keep in case a door going down is reset) + int topcountdown; // when it reaches 0, start going down +} vldoor_t; + +#define VDOORSPEED FRACUNIT*2 +#define VDOORWAIT 150 + +boolean EV_VerticalDoor(line_t * line, mobj_t * thing); +int EV_DoDoor(line_t * line, byte * args, vldoor_e type); +void T_VerticalDoor(thinker_t *thinker); +//void P_SpawnDoorCloseIn30(sector_t *sec); +//void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum); + +/* +=============================================================================== + + P_CEILNG + +=============================================================================== +*/ +typedef enum +{ + CLEV_LOWERTOFLOOR, + CLEV_RAISETOHIGHEST, + CLEV_LOWERANDCRUSH, + CLEV_CRUSHANDRAISE, + CLEV_LOWERBYVALUE, + CLEV_RAISEBYVALUE, + CLEV_CRUSHRAISEANDSTAY, + CLEV_MOVETOVALUETIMES8 +} ceiling_e; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + ceiling_e type; + fixed_t bottomheight, topheight; + fixed_t speed; + int crush; + int direction; // 1 = up, 0 = waiting, -1 = down + int tag; // ID + int olddirection; +} ceiling_t; + +#define CEILSPEED FRACUNIT +#define CEILWAIT 150 +#define MAXCEILINGS 30 + +extern ceiling_t *activeceilings[MAXCEILINGS]; + +int EV_DoCeiling(line_t * line, byte * args, ceiling_e type); +void T_MoveCeiling(thinker_t *thinker); +void P_AddActiveCeiling(ceiling_t * c); +void P_RemoveActiveCeiling(ceiling_t * c); +int EV_CeilingCrushStop(line_t * line, byte * args); + +/* +=============================================================================== + + P_FLOOR + +=============================================================================== +*/ +typedef enum +{ + FLEV_LOWERFLOOR, // lower floor to highest surrounding floor + FLEV_LOWERFLOORTOLOWEST, // lower floor to lowest surrounding floor + FLEV_LOWERFLOORBYVALUE, + FLEV_RAISEFLOOR, // raise floor to lowest surrounding CEILING + FLEV_RAISEFLOORTONEAREST, // raise floor to next highest surrounding floor + FLEV_RAISEFLOORBYVALUE, + FLEV_RAISEFLOORCRUSH, + FLEV_RAISEBUILDSTEP, // One step of a staircase + FLEV_RAISEBYVALUETIMES8, + FLEV_LOWERBYVALUETIMES8, + FLEV_LOWERTIMES8INSTANT, + FLEV_RAISETIMES8INSTANT, + FLEV_MOVETOVALUETIMES8 +} floor_e; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + floor_e type; + int crush; + int direction; + int newspecial; + short texture; + fixed_t floordestheight; + fixed_t speed; + int delayCount; + int delayTotal; + fixed_t stairsDelayHeight; + fixed_t stairsDelayHeightDelta; + fixed_t resetHeight; + short resetDelay; + short resetDelayCount; + byte textureChange; +} floormove_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int ceilingSpeed; + int floorSpeed; + int floordest; + int ceilingdest; + int direction; + int crush; +} pillar_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + fixed_t originalHeight; + fixed_t accumulator; + fixed_t accDelta; + fixed_t targetScale; + fixed_t scale; + fixed_t scaleDelta; + int ticker; + int state; +} floorWaggle_t; + +#define FLOORSPEED FRACUNIT + +typedef enum +{ + RES_OK, + RES_CRUSHED, + RES_PASTDEST +} result_e; + +typedef enum +{ + STAIRS_NORMAL, + STAIRS_SYNC, + STAIRS_PHASED +} stairs_e; + +result_e T_MovePlane(sector_t * sector, fixed_t speed, + fixed_t dest, int crush, int floorOrCeiling, + int direction); + +int EV_BuildStairs(line_t * line, byte * args, int direction, stairs_e type); +int EV_DoFloor(line_t * line, byte * args, floor_e floortype); +void T_MoveFloor(thinker_t *thinker); +void T_BuildPillar(thinker_t *thinker); +void T_FloorWaggle(thinker_t *thinker); +int EV_BuildPillar(line_t * line, byte * args, boolean crush); +int EV_OpenPillar(line_t * line, byte * args); +int EV_DoFloorAndCeiling(line_t * line, byte * args, boolean raise); +int EV_FloorCrushStop(line_t * line, byte * args); +boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset, + int timer); + +//-------------------------------------------------------------------------- +// +// p_telept +// +//-------------------------------------------------------------------------- + +boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle, + boolean useFog); +boolean EV_Teleport(int tid, mobj_t * thing, boolean fog); + +//-------------------------------------------------------------------------- +// +// p_acs +// +//-------------------------------------------------------------------------- + +#define MAX_ACS_SCRIPT_VARS 10 +#define MAX_ACS_MAP_VARS 32 +#define MAX_ACS_WORLD_VARS 64 +#define ACS_STACK_DEPTH 32 +#define MAX_ACS_STORE 20 + +typedef enum +{ + ASTE_INACTIVE, + ASTE_RUNNING, + ASTE_SUSPENDED, + ASTE_WAITINGFORTAG, + ASTE_WAITINGFORPOLY, + ASTE_WAITINGFORSCRIPT, + ASTE_TERMINATING +} aste_t; + +typedef struct acs_s acs_t; +typedef struct acsInfo_s acsInfo_t; + +struct acsInfo_s +{ + int number; + int offset; + int argCount; + aste_t state; + int waitValue; +}; + +struct acs_s +{ + thinker_t thinker; + mobj_t *activator; + line_t *line; + int side; + int number; + int infoIndex; + int delayCount; + int stack[ACS_STACK_DEPTH]; + int stackPtr; + int vars[MAX_ACS_SCRIPT_VARS]; + int ip; +}; + +typedef struct +{ + int map; // Target map + int script; // Script number on target map + byte args[4]; // Padded to 4 for alignment +} acsstore_t; + +void P_LoadACScripts(int lump); +boolean P_StartACS(int number, int map, byte * args, mobj_t * activator, + line_t * line, int side); +boolean P_StartLockedACS(line_t * line, byte * args, mobj_t * mo, int side); +boolean P_TerminateACS(int number, int map); +boolean P_SuspendACS(int number, int map); +void T_InterpretACS(thinker_t *thinker); +void P_TagFinished(int tag); +void P_PolyobjFinished(int po); +void P_ACSInitNewGame(void); +void P_CheckACSStore(void); +void CheckACSPresent(int number); + +extern int ACScriptCount; +extern byte *ActionCodeBase; +extern acsInfo_t *ACSInfo; +extern int MapVars[MAX_ACS_MAP_VARS]; +extern int WorldVars[MAX_ACS_WORLD_VARS]; +extern acsstore_t ACSStore[MAX_ACS_STORE + 1]; // +1 for termination marker + +//-------------------------------------------------------------------------- +// +// p_things +// +//-------------------------------------------------------------------------- + +extern mobjtype_t TranslateThingType[]; + +boolean EV_ThingProjectile(byte * args, boolean gravity); +boolean EV_ThingSpawn(byte * args, boolean fog); +boolean EV_ThingActivate(int tid); +boolean EV_ThingDeactivate(int tid); +boolean EV_ThingRemove(int tid); +boolean EV_ThingDestroy(int tid); + + +#endif // P_SPEC_H diff --git a/games/NXDoom/src/hexen/p_switch.c b/games/NXDoom/src/hexen/p_switch.c new file mode 100644 index 00000000000..a90269a799f --- /dev/null +++ b/games/NXDoom/src/hexen/p_switch.c @@ -0,0 +1,172 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" + +//================================================================== +// +// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE +// +//================================================================== +switchlist_t alphSwitchListDemo[] = { + {"SW_1_UP", "SW_1_DN", SFX_SWITCH1}, + {"SW_2_UP", "SW_2_DN", SFX_SWITCH1}, + {"SW52_OFF", "SW52_ON", SFX_SWITCH2}, + {"\0", "\0", 0} +}; + +switchlist_t alphSwitchListFull[] = { + {"SW_1_UP", "SW_1_DN", SFX_SWITCH1}, + {"SW_2_UP", "SW_2_DN", SFX_SWITCH1}, + {"VALVE1", "VALVE2", SFX_VALVE_TURN}, + {"SW51_OFF", "SW51_ON", SFX_SWITCH2}, + {"SW52_OFF", "SW52_ON", SFX_SWITCH2}, + {"SW53_UP", "SW53_DN", SFX_ROPE_PULL}, + {"PUZZLE5", "PUZZLE9", SFX_SWITCH1}, + {"PUZZLE6", "PUZZLE10", SFX_SWITCH1}, + {"PUZZLE7", "PUZZLE11", SFX_SWITCH1}, + {"PUZZLE8", "PUZZLE12", SFX_SWITCH1}, + {"\0", "\0", 0} +}; + +switchlist_t *alphSwitchList = NULL; + +int switchlist[MAXSWITCHES * 2]; +int numswitches; +button_t buttonlist[MAXBUTTONS]; + +/* +=============== += += P_InitSwitchList += += Only called at game initialization += +=============== +*/ + +void P_InitSwitchList(void) +{ + int i; + int index; + + if (!alphSwitchList) + { + if (gamemode == shareware) + { + alphSwitchList = alphSwitchListDemo; + } + else + { + alphSwitchList = alphSwitchListFull; + } + } + + for (index = 0, i = 0; i < MAXSWITCHES; i++) + { + if (!alphSwitchList[i].soundID) + { + numswitches = index / 2; + switchlist[index] = -1; + break; + } + switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1); + switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2); + } +} + +//================================================================== +// +// Start a button counting down till it turns off. +// +//================================================================== +void P_StartButton(line_t * line, bwhere_e w, int texture, int time) +{ + int i; + + for (i = 0; i < MAXBUTTONS; i++) + { + if (!buttonlist[i].btimer) + { + buttonlist[i].line = line; + buttonlist[i].where = w; + buttonlist[i].btexture = texture; + buttonlist[i].btimer = time; + buttonlist[i].soundorg = (mobj_t *) & line->frontsector->soundorg; + return; + } + } + I_Error("P_StartButton: no button slots left!"); +} + +//================================================================== +// +// Function that changes wall texture. +// Tell it if switch is ok to use again (1=yes, it's a button). +// +//================================================================== +void P_ChangeSwitchTexture(line_t * line, int useAgain) +{ + int texTop; + int texMid; + int texBot; + int i; + + texTop = sides[line->sidenum[0]].toptexture; + texMid = sides[line->sidenum[0]].midtexture; + texBot = sides[line->sidenum[0]].bottomtexture; + + for (i = 0; i < numswitches * 2; i++) + { + if (switchlist[i] == texTop) + { + S_StartSound((mobj_t *) & line->frontsector->soundorg, + alphSwitchList[i / 2].soundID); + sides[line->sidenum[0]].toptexture = switchlist[i ^ 1]; + if (useAgain) + { + P_StartButton(line, SWTCH_TOP, switchlist[i], BUTTONTIME); + } + return; + } + else if (switchlist[i] == texMid) + { + S_StartSound((mobj_t *) & line->frontsector->soundorg, + alphSwitchList[i / 2].soundID); + sides[line->sidenum[0]].midtexture = switchlist[i ^ 1]; + if (useAgain) + { + P_StartButton(line, SWTCH_MIDDLE, switchlist[i], BUTTONTIME); + } + return; + } + else if (switchlist[i] == texBot) + { + S_StartSound((mobj_t *) & line->frontsector->soundorg, + alphSwitchList[i / 2].soundID); + sides[line->sidenum[0]].bottomtexture = switchlist[i ^ 1]; + if (useAgain) + { + P_StartButton(line, SWTCH_BOTTOM, switchlist[i], BUTTONTIME); + } + return; + } + } +} diff --git a/games/NXDoom/src/hexen/p_telept.c b/games/NXDoom/src/hexen/p_telept.c new file mode 100644 index 00000000000..ba5416b27d0 --- /dev/null +++ b/games/NXDoom/src/hexen/p_telept.c @@ -0,0 +1,190 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// P_Teleport +// +//========================================================================== + +boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle, + boolean useFog) +{ + fixed_t oldx; + fixed_t oldy; + fixed_t oldz; + fixed_t aboveFloor; + fixed_t fogDelta; + player_t *player; + unsigned an; + mobj_t *fog; + + oldx = thing->x; + oldy = thing->y; + oldz = thing->z; + aboveFloor = thing->z - thing->floorz; + if (!P_TeleportMove(thing, x, y)) + { + return false; + } + if (thing->player) + { + player = thing->player; + if (player->powers[pw_flight] && aboveFloor) + { + thing->z = thing->floorz + aboveFloor; + if (thing->z + thing->height > thing->ceilingz) + { + thing->z = thing->ceilingz - thing->height; + } + player->viewz = thing->z + player->viewheight; + } + else + { + thing->z = thing->floorz; + player->viewz = thing->z + player->viewheight; + if (useFog) + { + player->lookdir = 0; + } + } + } + else if (thing->flags & MF_MISSILE) + { + thing->z = thing->floorz + aboveFloor; + if (thing->z + thing->height > thing->ceilingz) + { + thing->z = thing->ceilingz - thing->height; + } + } + else + { + thing->z = thing->floorz; + } + // Spawn teleport fog at source and destination + if (useFog) + { + fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; + fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG); + S_StartSound(fog, SFX_TELEPORT); + an = angle >> ANGLETOFINESHIFT; + fog = P_SpawnMobj(x + 20 * finecosine[an], + y + 20 * finesine[an], thing->z + fogDelta, + MT_TFOG); + S_StartSound(fog, SFX_TELEPORT); + if (thing->player && !thing->player->powers[pw_speed]) + { // Freeze player for about .5 sec + thing->reactiontime = 18; + } + thing->angle = angle; + } + if (thing->flags2 & MF2_FLOORCLIP) + { + if (thing->z == thing->subsector->sector->floorheight + && P_GetThingFloorType(thing) > FLOOR_SOLID) + { + thing->floorclip = 10 * FRACUNIT; + } + else + { + thing->floorclip = 0; + } + } + if (thing->flags & MF_MISSILE) + { + angle >>= ANGLETOFINESHIFT; + thing->momx = FixedMul(thing->info->speed, finecosine[angle]); + thing->momy = FixedMul(thing->info->speed, finesine[angle]); + } + else if (useFog) // no fog doesn't alter the player's momentums + { + thing->momx = thing->momy = thing->momz = 0; + } + return true; +} + +//========================================================================== +// +// EV_Teleport +// +//========================================================================== + +boolean EV_Teleport(int tid, mobj_t * thing, boolean fog) +{ + int i; + int count; + mobj_t *mo; + int searcher; + + if (!thing) + { // Teleport function called with an invalid mobj + return false; + } + if (thing->flags2 & MF2_NOTELEPORT) + { + return false; + } + count = 0; + searcher = -1; + while (P_FindMobjFromTID(tid, &searcher) != NULL) + { + count++; + } + if (count == 0) + { + return false; + } + count = 1 + (P_Random() % count); + searcher = -1; + mo = NULL; + + for (i = 0; i < count; i++) + { + mo = P_FindMobjFromTID(tid, &searcher); + } + if (mo == NULL) + { + I_Error("Can't find teleport mapspot\n"); + } + return P_Teleport(thing, mo->x, mo->y, mo->angle, fog); +} diff --git a/games/NXDoom/src/hexen/p_things.c b/games/NXDoom/src/hexen/p_things.c new file mode 100644 index 00000000000..12ec8547e00 --- /dev/null +++ b/games/NXDoom/src/hexen/p_things.c @@ -0,0 +1,537 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "p_local.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static boolean ActivateThing(mobj_t * mobj); +static boolean DeactivateThing(mobj_t * mobj); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +mobjtype_t TranslateThingType[] = { + MT_MAPSPOT, // T_NONE + MT_CENTAUR, // T_CENTAUR + MT_CENTAURLEADER, // T_CENTAURLEADER + MT_DEMON, // T_DEMON + MT_ETTIN, // T_ETTIN + MT_FIREDEMON, // T_FIREGARGOYLE + MT_SERPENT, // T_WATERLURKER + MT_SERPENTLEADER, // T_WATERLURKERLEADER + MT_WRAITH, // T_WRAITH + MT_WRAITHB, // T_WRAITHBURIED + MT_FIREBALL1, // T_FIREBALL1 + MT_MANA1, // T_MANA1 + MT_MANA2, // T_MANA2 + MT_SPEEDBOOTS, // T_ITEMBOOTS + MT_ARTIEGG, // T_ITEMEGG + MT_ARTIFLY, // T_ITEMFLIGHT + MT_SUMMONMAULATOR, // T_ITEMSUMMON + MT_TELEPORTOTHER, // T_ITEMTPORTOTHER + MT_ARTITELEPORT, // T_ITEMTELEPORT + MT_BISHOP, // T_BISHOP + MT_ICEGUY, // T_ICEGOLEM + MT_BRIDGE, // T_BRIDGE + MT_BOOSTARMOR, // T_DRAGONSKINBRACERS + MT_HEALINGBOTTLE, // T_ITEMHEALTHPOTION + MT_HEALTHFLASK, // T_ITEMHEALTHFLASK + MT_ARTISUPERHEAL, // T_ITEMHEALTHFULL + MT_BOOSTMANA, // T_ITEMBOOSTMANA + MT_FW_AXE, // T_FIGHTERAXE + MT_FW_HAMMER, // T_FIGHTERHAMMER + MT_FW_SWORD1, // T_FIGHTERSWORD1 + MT_FW_SWORD2, // T_FIGHTERSWORD2 + MT_FW_SWORD3, // T_FIGHTERSWORD3 + MT_CW_SERPSTAFF, // T_CLERICSTAFF + MT_CW_HOLY1, // T_CLERICHOLY1 + MT_CW_HOLY2, // T_CLERICHOLY2 + MT_CW_HOLY3, // T_CLERICHOLY3 + MT_MW_CONE, // T_MAGESHARDS + MT_MW_STAFF1, // T_MAGESTAFF1 + MT_MW_STAFF2, // T_MAGESTAFF2 + MT_MW_STAFF3, // T_MAGESTAFF3 + MT_EGGFX, // T_MORPHBLAST + MT_ROCK1, // T_ROCK1 + MT_ROCK2, // T_ROCK2 + MT_ROCK3, // T_ROCK3 + MT_DIRT1, // T_DIRT1 + MT_DIRT2, // T_DIRT2 + MT_DIRT3, // T_DIRT3 + MT_DIRT4, // T_DIRT4 + MT_DIRT5, // T_DIRT5 + MT_DIRT6, // T_DIRT6 + MT_ARROW, // T_ARROW + MT_DART, // T_DART + MT_POISONDART, // T_POISONDART + MT_RIPPERBALL, // T_RIPPERBALL + MT_SGSHARD1, // T_STAINEDGLASS1 + MT_SGSHARD2, // T_STAINEDGLASS2 + MT_SGSHARD3, // T_STAINEDGLASS3 + MT_SGSHARD4, // T_STAINEDGLASS4 + MT_SGSHARD5, // T_STAINEDGLASS5 + MT_SGSHARD6, // T_STAINEDGLASS6 + MT_SGSHARD7, // T_STAINEDGLASS7 + MT_SGSHARD8, // T_STAINEDGLASS8 + MT_SGSHARD9, // T_STAINEDGLASS9 + MT_SGSHARD0, // T_STAINEDGLASS0 + MT_PROJECTILE_BLADE, // T_BLADE + MT_ICESHARD, // T_ICESHARD + MT_FLAME_SMALL, // T_FLAME_SMALL + MT_FLAME_LARGE, // T_FLAME_LARGE + MT_ARMOR_1, // T_MESHARMOR + MT_ARMOR_2, // T_FALCONSHIELD + MT_ARMOR_3, // T_PLATINUMHELM + MT_ARMOR_4, // T_AMULETOFWARDING + MT_ARTIPOISONBAG, // T_ITEMFLECHETTE + MT_ARTITORCH, // T_ITEMTORCH + MT_BLASTRADIUS, // T_ITEMREPULSION + MT_MANA3, // T_MANA3 + MT_ARTIPUZZSKULL, // T_PUZZSKULL + MT_ARTIPUZZGEMBIG, // T_PUZZGEMBIG + MT_ARTIPUZZGEMRED, // T_PUZZGEMRED + MT_ARTIPUZZGEMGREEN1, // T_PUZZGEMGREEN1 + MT_ARTIPUZZGEMGREEN2, // T_PUZZGEMGREEN2 + MT_ARTIPUZZGEMBLUE1, // T_PUZZGEMBLUE1 + MT_ARTIPUZZGEMBLUE2, // T_PUZZGEMBLUE2 + MT_ARTIPUZZBOOK1, // T_PUZZBOOK1 + MT_ARTIPUZZBOOK2, // T_PUZZBOOK2 + MT_KEY1, // T_METALKEY + MT_KEY2, // T_SMALLMETALKEY + MT_KEY3, // T_AXEKEY + MT_KEY4, // T_FIREKEY + MT_KEY5, // T_GREENKEY + MT_KEY6, // T_MACEKEY + MT_KEY7, // T_SILVERKEY + MT_KEY8, // T_RUSTYKEY + MT_KEY9, // T_HORNKEY + MT_KEYA, // T_SERPENTKEY + MT_WATER_DRIP, // T_WATERDRIP + MT_FLAME_SMALL_TEMP, // T_TEMPSMALLFLAME + MT_FLAME_SMALL, // T_PERMSMALLFLAME + MT_FLAME_LARGE_TEMP, // T_TEMPLARGEFLAME + MT_FLAME_LARGE, // T_PERMLARGEFLAME + MT_DEMON_MASH, // T_DEMON_MASH + MT_DEMON2_MASH, // T_DEMON2_MASH + MT_ETTIN_MASH, // T_ETTIN_MASH + MT_CENTAUR_MASH, // T_CENTAUR_MASH + MT_THRUSTFLOOR_UP, // T_THRUSTSPIKEUP + MT_THRUSTFLOOR_DOWN, // T_THRUSTSPIKEDOWN + MT_WRAITHFX4, // T_FLESH_DRIP1 + MT_WRAITHFX5, // T_FLESH_DRIP2 + MT_WRAITHFX2 // T_SPARK_DRIP +}; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// EV_ThingProjectile +// +//========================================================================== + +boolean EV_ThingProjectile(byte * args, boolean gravity) +{ + int tid; + angle_t angle; + int fineAngle; + fixed_t speed; + fixed_t vspeed; + mobjtype_t moType; + mobj_t *mobj; + mobj_t *newMobj; + int searcher; + boolean success; + + success = false; + searcher = -1; + tid = args[0]; + moType = TranslateThingType[args[1]]; + if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL)) + { // Don't spawn monsters if -nomonsters + return false; + } + angle = (int) args[2] << 24; + fineAngle = angle >> ANGLETOFINESHIFT; + speed = (int) args[3] << 13; + vspeed = (int) args[4] << 13; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + newMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, moType); + if (newMobj->info->seesound) + { + S_StartSound(newMobj, newMobj->info->seesound); + } + newMobj->target = mobj; // Originator + newMobj->angle = angle; + newMobj->momx = FixedMul(speed, finecosine[fineAngle]); + newMobj->momy = FixedMul(speed, finesine[fineAngle]); + newMobj->momz = vspeed; + newMobj->flags2 |= MF2_DROPPED; // Don't respawn + if (gravity == true) + { + newMobj->flags &= ~MF_NOGRAVITY; + newMobj->flags2 |= MF2_LOGRAV; + } + if (P_CheckMissileSpawn(newMobj) == true) + { + success = true; + } + } + return success; +} + +//========================================================================== +// +// EV_ThingSpawn +// +//========================================================================== + +boolean EV_ThingSpawn(byte * args, boolean fog) +{ + int tid; + angle_t angle; + mobj_t *mobj; + mobj_t *newMobj; + mobj_t *fogMobj; + mobjtype_t moType; + int searcher; + boolean success; + fixed_t z; + + success = false; + searcher = -1; + tid = args[0]; + moType = TranslateThingType[args[1]]; + if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL)) + { // Don't spawn monsters if -nomonsters + return false; + } + angle = (int) args[2] << 24; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + if (mobjinfo[moType].flags2 & MF2_FLOATBOB) + { + z = mobj->z - mobj->floorz; + } + else + { + z = mobj->z; + } + newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType); + if (P_TestMobjLocation(newMobj) == false) + { // Didn't fit + P_RemoveMobj(newMobj); + } + else + { + newMobj->angle = angle; + if (fog == true) + { + fogMobj = P_SpawnMobj(mobj->x, mobj->y, + mobj->z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fogMobj, SFX_TELEPORT); + } + newMobj->flags2 |= MF2_DROPPED; // Don't respawn + if (newMobj->flags2 & MF2_FLOATBOB) + { + newMobj->special1.i = newMobj->z - newMobj->floorz; + } + success = true; + } + } + return success; +} + +//========================================================================== +// +// EV_ThingActivate +// +//========================================================================== + +boolean EV_ThingActivate(int tid) +{ + mobj_t *mobj; + int searcher; + boolean success; + + success = false; + searcher = -1; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + if (ActivateThing(mobj) == true) + { + success = true; + } + } + return success; +} + +//========================================================================== +// +// EV_ThingDeactivate +// +//========================================================================== + +boolean EV_ThingDeactivate(int tid) +{ + mobj_t *mobj; + int searcher; + boolean success; + + success = false; + searcher = -1; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + if (DeactivateThing(mobj) == true) + { + success = true; + } + } + return success; +} + +//========================================================================== +// +// EV_ThingRemove +// +//========================================================================== + +boolean EV_ThingRemove(int tid) +{ + mobj_t *mobj; + int searcher; + boolean success; + + success = false; + searcher = -1; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + if (mobj->type == MT_BRIDGE) + { + A_BridgeRemove(mobj); + return true; + } + P_RemoveMobj(mobj); + success = true; + } + return success; +} + +//========================================================================== +// +// EV_ThingDestroy +// +//========================================================================== + +boolean EV_ThingDestroy(int tid) +{ + mobj_t *mobj; + int searcher; + boolean success; + + success = false; + searcher = -1; + while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) + { + if (mobj->flags & MF_SHOOTABLE) + { + P_DamageMobj(mobj, NULL, NULL, 10000); + success = true; + } + } + return success; +} + +//========================================================================== +// +// EV_ThingMove +// +// arg[0] = tid +// arg[1] = speed +// arg[2] = angle (255 = use mobj angle) +// arg[3] = distance (pixels>>2) +// +//========================================================================== + +/* +boolean EV_ThingMove(byte *args) +{ + return false; +} +*/ + +//========================================================================== +// +// ActivateThing +// +//========================================================================== + +static boolean ActivateThing(mobj_t * mobj) +{ + if (mobj->flags & MF_COUNTKILL) + { // Monster + if (mobj->flags2 & MF2_DORMANT) + { + mobj->flags2 &= ~MF2_DORMANT; + mobj->tics = 1; + return true; + } + return false; + } + switch (mobj->type) + { + case MT_ZTWINEDTORCH: + case MT_ZTWINEDTORCH_UNLIT: + P_SetMobjState(mobj, S_ZTWINEDTORCH_1); + S_StartSound(mobj, SFX_IGNITE); + break; + case MT_ZWALLTORCH: + case MT_ZWALLTORCH_UNLIT: + P_SetMobjState(mobj, S_ZWALLTORCH1); + S_StartSound(mobj, SFX_IGNITE); + break; + case MT_ZGEMPEDESTAL: + P_SetMobjState(mobj, S_ZGEMPEDESTAL2); + break; + case MT_ZWINGEDSTATUENOSKULL: + P_SetMobjState(mobj, S_ZWINGEDSTATUENOSKULL2); + break; + case MT_THRUSTFLOOR_UP: + case MT_THRUSTFLOOR_DOWN: + if (mobj->args[0] == 0) + { + S_StartSound(mobj, SFX_THRUSTSPIKE_LOWER); + mobj->flags2 &= ~MF2_DONTDRAW; + if (mobj->args[1]) + P_SetMobjState(mobj, S_BTHRUSTRAISE1); + else + P_SetMobjState(mobj, S_THRUSTRAISE1); + } + break; + case MT_ZFIREBULL: + case MT_ZFIREBULL_UNLIT: + P_SetMobjState(mobj, S_ZFIREBULL_BIRTH); + S_StartSound(mobj, SFX_IGNITE); + break; + case MT_ZBELL: + if (mobj->health > 0) + { + P_DamageMobj(mobj, NULL, NULL, 10); // 'ring' the bell + } + break; + case MT_ZCAULDRON: + case MT_ZCAULDRON_UNLIT: + P_SetMobjState(mobj, S_ZCAULDRON1); + S_StartSound(mobj, SFX_IGNITE); + break; + case MT_FLAME_SMALL: + S_StartSound(mobj, SFX_IGNITE); + P_SetMobjState(mobj, S_FLAME_SMALL1); + break; + case MT_FLAME_LARGE: + S_StartSound(mobj, SFX_IGNITE); + P_SetMobjState(mobj, S_FLAME_LARGE1); + break; + case MT_BAT_SPAWNER: + P_SetMobjState(mobj, S_SPAWNBATS1); + break; + default: + return false; + break; + } + return true; +} + +//========================================================================== +// +// DeactivateThing +// +//========================================================================== + +static boolean DeactivateThing(mobj_t * mobj) +{ + if (mobj->flags & MF_COUNTKILL) + { // Monster + if (!(mobj->flags2 & MF2_DORMANT)) + { + mobj->flags2 |= MF2_DORMANT; + mobj->tics = -1; + return true; + } + return false; + } + switch (mobj->type) + { + case MT_ZTWINEDTORCH: + case MT_ZTWINEDTORCH_UNLIT: + P_SetMobjState(mobj, S_ZTWINEDTORCH_UNLIT); + break; + case MT_ZWALLTORCH: + case MT_ZWALLTORCH_UNLIT: + P_SetMobjState(mobj, S_ZWALLTORCH_U); + break; + case MT_THRUSTFLOOR_UP: + case MT_THRUSTFLOOR_DOWN: + if (mobj->args[0] == 1) + { + S_StartSound(mobj, SFX_THRUSTSPIKE_RAISE); + if (mobj->args[1]) + P_SetMobjState(mobj, S_BTHRUSTLOWER); + else + P_SetMobjState(mobj, S_THRUSTLOWER); + } + break; + case MT_ZFIREBULL: + case MT_ZFIREBULL_UNLIT: + P_SetMobjState(mobj, S_ZFIREBULL_DEATH); + break; + case MT_ZCAULDRON: + case MT_ZCAULDRON_UNLIT: + P_SetMobjState(mobj, S_ZCAULDRON_U); + break; + case MT_FLAME_SMALL: + P_SetMobjState(mobj, S_FLAME_SDORM1); + break; + case MT_FLAME_LARGE: + P_SetMobjState(mobj, S_FLAME_LDORM1); + break; + case MT_BAT_SPAWNER: + P_SetMobjState(mobj, S_SPAWNBATS_OFF); + break; + default: + return false; + break; + } + return true; +} diff --git a/games/NXDoom/src/hexen/p_tick.c b/games/NXDoom/src/hexen/p_tick.c new file mode 100644 index 00000000000..3d3dd389c77 --- /dev/null +++ b/games/NXDoom/src/hexen/p_tick.c @@ -0,0 +1,151 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "p_local.h" + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void RunThinkers(void); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +int leveltime; +int TimerGame; +thinker_t thinkercap; // The head and tail of the thinker list + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// P_Ticker +// +//========================================================================== + +void P_Ticker(void) +{ + int i; + + if (paused) + { + return; + } + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + P_PlayerThink(&players[i]); + } + } + if (TimerGame) + { + if (!--TimerGame) + { + G_Completed(P_TranslateMap(P_GetMapNextMap(gamemap)), 0); + } + } + RunThinkers(); + P_UpdateSpecials(); + P_AnimateSurfaces(); + leveltime++; +} + +//========================================================================== +// +// RunThinkers +// +//========================================================================== + +static void RunThinkers(void) +{ + thinker_t *currentthinker, *nextthinker; + + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + if (currentthinker->function == (think_t) - 1) + { // Time to remove it + nextthinker = currentthinker->next; + currentthinker->next->prev = currentthinker->prev; + currentthinker->prev->next = currentthinker->next; + Z_Free(currentthinker); + } + else + { + if (currentthinker->function) + currentthinker->function(currentthinker); + nextthinker = currentthinker->next; + } + + currentthinker = nextthinker; + } +} + +//========================================================================== +// +// P_InitThinkers +// +//========================================================================== + +void P_InitThinkers(void) +{ + thinkercap.prev = thinkercap.next = &thinkercap; +} + +//========================================================================== +// +// P_AddThinker +// +// Adds a new thinker at the end of the list. +// +//========================================================================== + +void P_AddThinker(thinker_t * thinker) +{ + thinkercap.prev->next = thinker; + thinker->next = &thinkercap; + thinker->prev = thinkercap.prev; + thinkercap.prev = thinker; +} + +//========================================================================== +// +// P_RemoveThinker +// +// Deallocation is lazy -- it will not actually be freed until its +// thinking turn comes up. +// +//========================================================================== + +void P_RemoveThinker(thinker_t * thinker) +{ + thinker->function = (think_t) - 1; +} diff --git a/games/NXDoom/src/hexen/p_user.c b/games/NXDoom/src/hexen/p_user.c new file mode 100644 index 00000000000..52986bd2306 --- /dev/null +++ b/games/NXDoom/src/hexen/p_user.c @@ -0,0 +1,1643 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "m_random.h" +#include "i_system.h" +#include "p_local.h" +#include "s_sound.h" + + +// Macros + +#define MAXBOB 0x100000 // 16 pixels of bob + +// Data + +boolean onground; +int newtorch; // used in the torch flicker effect. +int newtorchdelta; + +int PStateNormal[NUMCLASSES] = { + S_FPLAY, + S_CPLAY, + S_MPLAY, + S_PIGPLAY +}; + +int PStateRun[NUMCLASSES] = { + S_FPLAY_RUN1, + S_CPLAY_RUN1, + S_MPLAY_RUN1, + S_PIGPLAY_RUN1 +}; + +int PStateAttack[NUMCLASSES] = { + S_FPLAY_ATK1, + S_CPLAY_ATK1, + S_MPLAY_ATK1, + S_PIGPLAY_ATK1 +}; + +int PStateAttackEnd[NUMCLASSES] = { + S_FPLAY_ATK2, + S_CPLAY_ATK3, + S_MPLAY_ATK2, + S_PIGPLAY_ATK1 +}; + +int ArmorMax[NUMCLASSES] = { 20, 18, 16, 1 }; + +/* +================== += += P_Thrust += += moves the given origin along a given angle += +================== +*/ + +void P_Thrust(player_t * player, angle_t angle, fixed_t move) +{ + angle >>= ANGLETOFINESHIFT; + if (player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz)) + { + player->mo->momx += FixedMul(move, finecosine[angle]); + player->mo->momy += FixedMul(move, finesine[angle]); + } + else if (P_GetThingFloorType(player->mo) == FLOOR_ICE) // Friction_Low + { + player->mo->momx += FixedMul(move >> 1, finecosine[angle]); + player->mo->momy += FixedMul(move >> 1, finesine[angle]); + } + else + { + player->mo->momx += FixedMul(move, finecosine[angle]); + player->mo->momy += FixedMul(move, finesine[angle]); + } +} + + +/* +================== += += P_CalcHeight += +=Calculate the walking / running height adjustment += +================== +*/ + +void P_CalcHeight(player_t * player) +{ + int angle; + fixed_t bob; + +// +// regular movement bobbing (needs to be calculated for gun swing even +// if not on ground) +// OPTIMIZE: tablify angle + + player->bob = FixedMul(player->mo->momx, player->mo->momx) + + FixedMul(player->mo->momy, player->mo->momy); + player->bob >>= 2; + if (player->bob > MAXBOB) + player->bob = MAXBOB; + if (player->mo->flags2 & MF2_FLY && !onground) + { + player->bob = FRACUNIT / 2; + } + + if ((player->cheats & CF_NOMOMENTUM)) + { + player->viewz = player->mo->z + VIEWHEIGHT; + if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) + player->viewz = player->mo->ceilingz - 4 * FRACUNIT; + player->viewz = player->mo->z + player->viewheight; + return; + } + + angle = (FINEANGLES / 20 * leveltime) & FINEMASK; + bob = FixedMul(player->bob / 2, finesine[angle]); + +// +// move viewheight +// + if (player->playerstate == PST_LIVE) + { + player->viewheight += player->deltaviewheight; + if (player->viewheight > VIEWHEIGHT) + { + player->viewheight = VIEWHEIGHT; + player->deltaviewheight = 0; + } + if (player->viewheight < VIEWHEIGHT / 2) + { + player->viewheight = VIEWHEIGHT / 2; + if (player->deltaviewheight <= 0) + player->deltaviewheight = 1; + } + + if (player->deltaviewheight) + { + player->deltaviewheight += FRACUNIT / 4; + if (!player->deltaviewheight) + player->deltaviewheight = 1; + } + } + + if (player->morphTics) + { + player->viewz = player->mo->z + player->viewheight - (20 * FRACUNIT); + } + else + { + player->viewz = player->mo->z + player->viewheight + bob; + } + if (player->mo->floorclip && player->playerstate != PST_DEAD + && player->mo->z <= player->mo->floorz) + { + player->viewz -= player->mo->floorclip; + } + if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) + { + player->viewz = player->mo->ceilingz - 4 * FRACUNIT; + } + if (player->viewz < player->mo->floorz + 4 * FRACUNIT) + { + player->viewz = player->mo->floorz + 4 * FRACUNIT; + } +} + +/* +================= += += P_MovePlayer += +================= +*/ + +void P_MovePlayer(player_t * player) +{ + int look; + int fly; + ticcmd_t *cmd; + + cmd = &player->cmd; + player->mo->angle += (cmd->angleturn << 16); + + onground = (player->mo->z <= player->mo->floorz + || (player->mo->flags2 & MF2_ONMOBJ)); + + if (cmd->forwardmove) + { + if (onground || player->mo->flags2 & MF2_FLY) + { + P_Thrust(player, player->mo->angle, cmd->forwardmove * 2048); + } + else + { + P_Thrust(player, player->mo->angle, FRACUNIT >> 8); + } + } + if (cmd->sidemove) + { + if (onground || player->mo->flags2 & MF2_FLY) + { + P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2048); + } + else + { + P_Thrust(player, player->mo->angle, FRACUNIT >> 8); + } + } + if (cmd->forwardmove || cmd->sidemove) + { + if (player->mo->state == &states[PStateNormal[player->class]]) + { + P_SetMobjState(player->mo, PStateRun[player->class]); + } + } + + look = cmd->lookfly & 15; + if (look > 7) + { + look -= 16; + } + if (look) + { + if (look == TOCENTER) + { + player->centering = true; + } + else + { + player->lookdir += 5 * look; + if (player->lookdir > 90 || player->lookdir < -110) + { + player->lookdir -= 5 * look; + } + } + } + if (player->centering) + { + if (player->lookdir > 0) + { + player->lookdir -= 8; + } + else if (player->lookdir < 0) + { + player->lookdir += 8; + } + if (abs(player->lookdir) < 8) + { + player->lookdir = 0; + player->centering = false; + } + } + fly = cmd->lookfly >> 4; + if (fly > 7) + { + fly -= 16; + } + if (fly && player->powers[pw_flight]) + { + if (fly != TOCENTER) + { + player->flyheight = fly * 2; + if (!(player->mo->flags2 & MF2_FLY)) + { + player->mo->flags2 |= MF2_FLY; + player->mo->flags |= MF_NOGRAVITY; + if (player->mo->momz <= -39 * FRACUNIT) + { // stop falling scream + S_StopSound(player->mo); + } + } + } + else + { + player->mo->flags2 &= ~MF2_FLY; + player->mo->flags &= ~MF_NOGRAVITY; + } + } + else if (fly > 0) + { + P_PlayerUseArtifact(player, arti_fly); + } + if (player->mo->flags2 & MF2_FLY) + { + player->mo->momz = player->flyheight * FRACUNIT; + if (player->flyheight) + { + player->flyheight /= 2; + } + } +} + +//========================================================================== +// +// P_DeathThink +// +//========================================================================== + +void P_DeathThink(player_t * player) +{ + int dir; + angle_t delta; + int lookDelta; + + P_MovePsprites(player); + + onground = (player->mo->z <= player->mo->floorz); + if (player->mo->type == MT_BLOODYSKULL || player->mo->type == MT_ICECHUNK) + { // Flying bloody skull or flying ice chunk + player->viewheight = 6 * FRACUNIT; + player->deltaviewheight = 0; + //player->damagecount = 20; + if (onground) + { + if (player->lookdir < 60) + { + lookDelta = (60 - player->lookdir) / 8; + if (lookDelta < 1 && (leveltime & 1)) + { + lookDelta = 1; + } + else if (lookDelta > 6) + { + lookDelta = 6; + } + player->lookdir += lookDelta; + } + } + } + else if (!(player->mo->flags2 & MF2_ICEDAMAGE)) + { // Fall to ground (if not frozen) + player->deltaviewheight = 0; + if (player->viewheight > 6 * FRACUNIT) + { + player->viewheight -= FRACUNIT; + } + if (player->viewheight < 6 * FRACUNIT) + { + player->viewheight = 6 * FRACUNIT; + } + if (player->lookdir > 0) + { + player->lookdir -= 6; + } + else if (player->lookdir < 0) + { + player->lookdir += 6; + } + if (abs(player->lookdir) < 6) + { + player->lookdir = 0; + } + } + P_CalcHeight(player); + + if (player->attacker && player->attacker != player->mo) + { // Watch killer + dir = P_FaceMobj(player->mo, player->attacker, &delta); + if (delta < ANG1 * 10) + { // Looking at killer, so fade damage and poison counters + if (player->damagecount) + { + player->damagecount--; + } + if (player->poisoncount) + { + player->poisoncount--; + } + } + delta = delta / 8; + if (delta > ANG1 * 5) + { + delta = ANG1 * 5; + } + if (dir) + { // Turn clockwise + player->mo->angle += delta; + } + else + { // Turn counter clockwise + player->mo->angle -= delta; + } + } + else if (player->damagecount || player->poisoncount) + { + if (player->damagecount) + { + player->damagecount--; + } + else + { + player->poisoncount--; + } + } + + if (player->cmd.buttons & BT_USE) + { + if (player == &players[consoleplayer]) + { + I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE)); + inv_ptr = 0; + curpos = 0; + newtorch = 0; + newtorchdelta = 0; + } + player->playerstate = PST_REBORN; + player->mo->special1.i = player->class; + if (player->mo->special1.i > 2) + { + player->mo->special1.i = 0; + } + // Let the mobj know the player has entered the reborn state. Some + // mobjs need to know when it's ok to remove themselves. + player->mo->special2.i = 666; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_MorphPlayerThink +// +//---------------------------------------------------------------------------- + +void P_MorphPlayerThink(player_t * player) +{ + mobj_t *pmo; + + if (player->morphTics & 15) + { + return; + } + pmo = player->mo; + if (!(pmo->momx + pmo->momy) && P_Random() < 64) + { // Snout sniff + P_SetPspriteNF(player, ps_weapon, S_SNOUTATK2); + S_StartSound(pmo, SFX_PIG_ACTIVE1); // snort + return; + } + if (P_Random() < 48) + { + if (P_Random() < 128) + { + S_StartSound(pmo, SFX_PIG_ACTIVE1); + } + else + { + S_StartSound(pmo, SFX_PIG_ACTIVE2); + } + } +} + +//---------------------------------------------------------------------------- +// +// FUNC P_GetPlayerNum +// +//---------------------------------------------------------------------------- + +int P_GetPlayerNum(player_t * player) +{ + int i; + + for (i = 0; i < maxplayers; i++) + { + if (player == &players[i]) + { + return (i); + } + } + return (0); +} + +//---------------------------------------------------------------------------- +// +// FUNC P_UndoPlayerMorph +// +//---------------------------------------------------------------------------- + +boolean P_UndoPlayerMorph(player_t * player) +{ + mobj_t *fog; + mobj_t *mo; + mobj_t *pmo; + fixed_t x; + fixed_t y; + fixed_t z; + angle_t angle; + int playerNum; + weapontype_t weapon; + int oldFlags; + int oldFlags2; + int oldBeast; + + pmo = player->mo; + x = pmo->x; + y = pmo->y; + z = pmo->z; + angle = pmo->angle; + weapon = pmo->special1.i; + oldFlags = pmo->flags; + oldFlags2 = pmo->flags2; + oldBeast = pmo->type; + P_SetMobjState(pmo, S_FREETARGMOBJ); + playerNum = P_GetPlayerNum(player); + switch (PlayerClass[playerNum]) + { + case PCLASS_FIGHTER: + mo = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER); + break; + case PCLASS_CLERIC: + mo = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC); + break; + case PCLASS_MAGE: + mo = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE); + break; + default: + I_Error("P_UndoPlayerMorph: Unknown player class %d\n", + player->class); + return false; + } + if (P_TestMobjLocation(mo) == false) + { // Didn't fit + P_RemoveMobj(mo); + mo = P_SpawnMobj(x, y, z, oldBeast); + mo->angle = angle; + mo->health = player->health; + mo->special1.i = weapon; + mo->player = player; + mo->flags = oldFlags; + mo->flags2 = oldFlags2; + player->mo = mo; + player->morphTics = 2 * 35; + return (false); + } + if (player->class == PCLASS_FIGHTER) + { + // The first type should be blue, and the third should be the + // Fighter's original gold color + if (playerNum == 0) + { + mo->flags |= 2 << MF_TRANSSHIFT; + } + else if (playerNum != 2) + { + mo->flags |= playerNum << MF_TRANSSHIFT; + } + } + else if (playerNum) + { // Set color translation bits for player sprites + mo->flags |= playerNum << MF_TRANSSHIFT; + } + mo->angle = angle; + mo->player = player; + mo->reactiontime = 18; + if (oldFlags2 & MF2_FLY) + { + mo->flags2 |= MF2_FLY; + mo->flags |= MF_NOGRAVITY; + } + player->morphTics = 0; + player->health = mo->health = MAXHEALTH; + player->mo = mo; + player->class = PlayerClass[playerNum]; + angle >>= ANGLETOFINESHIFT; + fog = P_SpawnMobj(x + 20 * finecosine[angle], + y + 20 * finesine[angle], z + TELEFOGHEIGHT, MT_TFOG); + S_StartSound(fog, SFX_TELEPORT); + P_PostMorphWeapon(player, weapon); + return (true); +} + + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerThink +// +//---------------------------------------------------------------------------- + +void P_PlayerThink(player_t * player) +{ + ticcmd_t *cmd; + weapontype_t newweapon; + int floorType; + mobj_t *pmo; + + // No-clip cheat + if (player->cheats & CF_NOCLIP) + { + player->mo->flags |= MF_NOCLIP; + } + else + { + player->mo->flags &= ~MF_NOCLIP; + } + cmd = &player->cmd; + if (player->mo->flags & MF_JUSTATTACKED) + { // Gauntlets attack auto forward motion + cmd->angleturn = 0; + cmd->forwardmove = 0xc800 / 512; + cmd->sidemove = 0; + player->mo->flags &= ~MF_JUSTATTACKED; + } +// messageTics is above the rest of the counters so that messages will +// go away, even in death. + player->messageTics--; // Can go negative + if (!player->messageTics || player->messageTics == -1) + { // Refresh the screen when a message goes away + player->ultimateMessage = false; // clear out any chat messages. + player->yellowMessage = false; + if (player == &players[consoleplayer]) + { + BorderTopRefresh = true; + } + } + player->worldTimer++; + if (player->playerstate == PST_DEAD) + { + P_DeathThink(player); + return; + } + if (player->jumpTics) + { + player->jumpTics--; + } + if (player->morphTics) + { + P_MorphPlayerThink(player); + } + // Handle movement + if (player->mo->reactiontime) + { // Player is frozen + player->mo->reactiontime--; + } + else + { + P_MovePlayer(player); + pmo = player->mo; + if (player->powers[pw_speed] && !(leveltime & 1) + && P_AproxDistance(pmo->momx, pmo->momy) > 12 * FRACUNIT) + { + mobj_t *speedMo; + int playerNum; + + speedMo = P_SpawnMobj(pmo->x, pmo->y, pmo->z, MT_PLAYER_SPEED); + if (speedMo) + { + speedMo->angle = pmo->angle; + playerNum = P_GetPlayerNum(player); + if (player->class == PCLASS_FIGHTER) + { + // The first type should be blue, and the + // third should be the Fighter's original gold color + if (playerNum == 0) + { + speedMo->flags |= 2 << MF_TRANSSHIFT; + } + else if (playerNum != 2) + { + speedMo->flags |= playerNum << MF_TRANSSHIFT; + } + } + else if (playerNum) + { // Set color translation bits for player sprites + speedMo->flags |= playerNum << MF_TRANSSHIFT; + } + speedMo->target = pmo; + speedMo->special1.i = player->class; + if (speedMo->special1.i > 2) + { + speedMo->special1.i = 0; + } + speedMo->sprite = pmo->sprite; + speedMo->floorclip = pmo->floorclip; + if (player == &players[consoleplayer]) + { + speedMo->flags2 |= MF2_DONTDRAW; + } + } + } + } + P_CalcHeight(player); + if (player->mo->subsector->sector->special) + { + P_PlayerInSpecialSector(player); + } + if ((floorType = P_GetThingFloorType(player->mo)) != FLOOR_SOLID) + { + P_PlayerOnSpecialFlat(player, floorType); + } + switch (player->class) + { + case PCLASS_FIGHTER: + if (player->mo->momz <= -35 * FRACUNIT + && player->mo->momz >= -40 * FRACUNIT && !player->morphTics + && !S_GetSoundPlayingInfo(player->mo, + SFX_PLAYER_FIGHTER_FALLING_SCREAM)) + { + S_StartSound(player->mo, SFX_PLAYER_FIGHTER_FALLING_SCREAM); + } + break; + case PCLASS_CLERIC: + if (player->mo->momz <= -35 * FRACUNIT + && player->mo->momz >= -40 * FRACUNIT && !player->morphTics + && !S_GetSoundPlayingInfo(player->mo, + SFX_PLAYER_CLERIC_FALLING_SCREAM)) + { + S_StartSound(player->mo, SFX_PLAYER_CLERIC_FALLING_SCREAM); + } + break; + case PCLASS_MAGE: + if (player->mo->momz <= -35 * FRACUNIT + && player->mo->momz >= -40 * FRACUNIT && !player->morphTics + && !S_GetSoundPlayingInfo(player->mo, + SFX_PLAYER_MAGE_FALLING_SCREAM)) + { + S_StartSound(player->mo, SFX_PLAYER_MAGE_FALLING_SCREAM); + } + break; + default: + break; + } + if (cmd->arti) + { // Use an artifact + if ((cmd->arti & AFLAG_JUMP) && onground && !player->jumpTics) + { + if (player->morphTics) + { + player->mo->momz = 6 * FRACUNIT; + } + else + { + player->mo->momz = 9 * FRACUNIT; + } + player->mo->flags2 &= ~MF2_ONMOBJ; + player->jumpTics = 18; + } + else if (cmd->arti & AFLAG_SUICIDE) + { + P_DamageMobj(player->mo, NULL, NULL, 10000); + } + if (cmd->arti == NUMARTIFACTS) + { // use one of each artifact (except puzzle artifacts) + int i; + + for (i = 1; i < arti_firstpuzzitem; i++) + { + P_PlayerUseArtifact(player, i); + } + } + else + { + P_PlayerUseArtifact(player, cmd->arti & AFLAG_MASK); + } + } + // Check for weapon change + if (cmd->buttons & BT_SPECIAL) + { // A special event has no other buttons + cmd->buttons = 0; + } + if (cmd->buttons & BT_CHANGE && !player->morphTics) + { + // The actual changing of the weapon is done when the weapon + // psprite can do it (A_WeaponReady), so it doesn't happen in + // the middle of an attack. + newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; + if (player->weaponowned[newweapon] + && newweapon != player->readyweapon) + { + player->pendingweapon = newweapon; + } + } + // Check for use + if (cmd->buttons & BT_USE) + { + if (!player->usedown) + { + P_UseLines(player); + player->usedown = true; + } + } + else + { + player->usedown = false; + } + // Morph counter + if (player->morphTics) + { + if (!--player->morphTics) + { // Attempt to undo the pig + P_UndoPlayerMorph(player); + } + } + // Cycle psprites + P_MovePsprites(player); + // Other Counters + if (player->powers[pw_invulnerability]) + { + if (player->class == PCLASS_CLERIC) + { + if (!(leveltime & 7) && player->mo->flags & MF_SHADOW + && !(player->mo->flags2 & MF2_DONTDRAW)) + { + player->mo->flags &= ~MF_SHADOW; + if (!(player->mo->flags & MF_ALTSHADOW)) + { + player->mo->flags2 |= MF2_DONTDRAW | MF2_NONSHOOTABLE; + } + } + if (!(leveltime & 31)) + { + if (player->mo->flags2 & MF2_DONTDRAW) + { + if (!(player->mo->flags & MF_SHADOW)) + { + player->mo->flags |= MF_SHADOW | MF_ALTSHADOW; + } + else + { + player->mo->flags2 &= + ~(MF2_DONTDRAW | MF2_NONSHOOTABLE); + } + } + else + { + player->mo->flags |= MF_SHADOW; + player->mo->flags &= ~MF_ALTSHADOW; + } + } + } + if (!(--player->powers[pw_invulnerability])) + { + player->mo->flags2 &= ~(MF2_INVULNERABLE | MF2_REFLECTIVE); + if (player->class == PCLASS_CLERIC) + { + player->mo->flags2 &= ~(MF2_DONTDRAW | MF2_NONSHOOTABLE); + player->mo->flags &= ~(MF_SHADOW | MF_ALTSHADOW); + } + } + } + if (player->powers[pw_minotaur]) + { + player->powers[pw_minotaur]--; + } + if (player->powers[pw_infrared]) + { + player->powers[pw_infrared]--; + } + if (player->powers[pw_flight] && netgame) + { + if (!--player->powers[pw_flight]) + { + if (player->mo->z != player->mo->floorz) + { + // haleyjd: removed externdriver crap + player->centering = true; + } + player->mo->flags2 &= ~MF2_FLY; + player->mo->flags &= ~MF_NOGRAVITY; + BorderTopRefresh = true; //make sure the sprite's cleared out + } + } + if (player->powers[pw_speed]) + { + player->powers[pw_speed]--; + } + if (player->damagecount) + { + player->damagecount--; + } + if (player->bonuscount) + { + player->bonuscount--; + } + if (player->poisoncount && !(leveltime & 15)) + { + player->poisoncount -= 5; + if (player->poisoncount < 0) + { + player->poisoncount = 0; + } + P_PoisonDamage(player, player->poisoner, 1, true); + } + // Colormaps +// if(player->powers[pw_invulnerability]) +// { +// if(player->powers[pw_invulnerability] > BLINKTHRESHOLD +// || (player->powers[pw_invulnerability]&8)) +// { +// player->fixedcolormap = INVERSECOLORMAP; +// } +// else +// { +// player->fixedcolormap = 0; +// } +// } +// else + if (player->powers[pw_infrared]) + { + if (player->powers[pw_infrared] <= BLINKTHRESHOLD) + { + if (player->powers[pw_infrared] & 8) + { + player->fixedcolormap = 0; + } + else + { + player->fixedcolormap = 1; + } + } + else if (!(leveltime & 16) && player == &players[consoleplayer]) + { + if (newtorch) + { + if (player->fixedcolormap + newtorchdelta > 7 + || player->fixedcolormap + newtorchdelta < 1 + || newtorch == player->fixedcolormap) + { + newtorch = 0; + } + else + { + player->fixedcolormap += newtorchdelta; + } + } + else + { + newtorch = (M_Random() & 7) + 1; + newtorchdelta = (newtorch == player->fixedcolormap) ? + 0 : ((newtorch > player->fixedcolormap) ? 1 : -1); + } + } + } + else + { + player->fixedcolormap = 0; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_ArtiTele +// +//---------------------------------------------------------------------------- + +void P_ArtiTele(player_t * player) +{ + int i; + int selections; + fixed_t destX; + fixed_t destY; + angle_t destAngle; + + if (deathmatch) + { + selections = deathmatch_p - deathmatchstarts; + i = P_Random() % selections; + destX = deathmatchstarts[i].x << FRACBITS; + destY = deathmatchstarts[i].y << FRACBITS; + destAngle = ANG45 * (deathmatchstarts[i].angle / 45); + } + else + { + destX = playerstarts[0][0].x << FRACBITS; + destY = playerstarts[0][0].y << FRACBITS; + destAngle = ANG45 * (playerstarts[0][0].angle / 45); + } + P_Teleport(player->mo, destX, destY, destAngle, true); + if (player->morphTics) + { // Teleporting away will undo any morph effects (pig) + P_UndoPlayerMorph(player); + } + //S_StartSound(NULL, sfx_wpnup); // Full volume laugh +} + + +//---------------------------------------------------------------------------- +// +// PROC P_ArtiTeleportOther +// +//---------------------------------------------------------------------------- + +void P_ArtiTeleportOther(player_t * player) +{ + mobj_t *mo; + + mo = P_SpawnPlayerMissile(player->mo, MT_TELOTHER_FX1); + if (mo) + { + mo->target = player->mo; + } +} + + +void P_TeleportToPlayerStarts(mobj_t * victim) +{ + int i, selections = 0; + fixed_t destX, destY; + angle_t destAngle; + + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + continue; + selections++; + } + i = P_Random() % selections; + destX = playerstarts[0][i].x << FRACBITS; + destY = playerstarts[0][i].y << FRACBITS; + destAngle = ANG45 * (playerstarts[0][i].angle / 45); + P_Teleport(victim, destX, destY, destAngle, true); + //S_StartSound(NULL, sfx_wpnup); // Full volume laugh +} + +void P_TeleportToDeathmatchStarts(mobj_t * victim) +{ + int i, selections; + fixed_t destX, destY; + angle_t destAngle; + + selections = deathmatch_p - deathmatchstarts; + if (selections) + { + i = P_Random() % selections; + destX = deathmatchstarts[i].x << FRACBITS; + destY = deathmatchstarts[i].y << FRACBITS; + destAngle = ANG45 * (deathmatchstarts[i].angle / 45); + P_Teleport(victim, destX, destY, destAngle, true); + //S_StartSound(NULL, sfx_wpnup); // Full volume laugh + } + else + { + P_TeleportToPlayerStarts(victim); + } +} + + + +//---------------------------------------------------------------------------- +// +// PROC P_TeleportOther +// +//---------------------------------------------------------------------------- +void P_TeleportOther(mobj_t * victim) +{ + if (victim->player) + { + if (deathmatch) + P_TeleportToDeathmatchStarts(victim); + else + P_TeleportToPlayerStarts(victim); + } + else + { + // If death action, run it upon teleport + if (victim->flags & MF_COUNTKILL && victim->special) + { + P_RemoveMobjFromTIDList(victim); + P_ExecuteLineSpecial(victim->special, victim->args, + NULL, 0, victim); + victim->special = 0; + } + + // Send all monsters to deathmatch spots + P_TeleportToDeathmatchStarts(victim); + } +} + + + +#define BLAST_RADIUS_DIST 255*FRACUNIT +#define BLAST_SPEED 20*FRACUNIT +#define BLAST_FULLSTRENGTH 255 + +void ResetBlasted(mobj_t * mo) +{ + mo->flags2 &= ~MF2_BLASTED; + if (!(mo->flags & MF_ICECORPSE)) + { + mo->flags2 &= ~MF2_SLIDE; + } +} + +void P_BlastMobj(mobj_t * source, mobj_t * victim, fixed_t strength) +{ + angle_t angle, ang; + mobj_t *mo; + fixed_t x, y, z; + + angle = R_PointToAngle2(source->x, source->y, victim->x, victim->y); + angle >>= ANGLETOFINESHIFT; + if (strength < BLAST_FULLSTRENGTH) + { + victim->momx = FixedMul(strength, finecosine[angle]); + victim->momy = FixedMul(strength, finesine[angle]); + if (victim->player) + { + // Players handled automatically + } + else + { + victim->flags2 |= MF2_SLIDE; + victim->flags2 |= MF2_BLASTED; + } + } + else // full strength blast from artifact + { + if (victim->flags & MF_MISSILE) + { + switch (victim->type) + { + case MT_SORCBALL1: // don't blast sorcerer balls + case MT_SORCBALL2: + case MT_SORCBALL3: + return; + break; + case MT_MSTAFF_FX2: // Reflect to originator + victim->special1.m = victim->target; + victim->target = source; + break; + default: + break; + } + } + if (victim->type == MT_HOLY_FX) + { + if (victim->special1.m == source) + { + victim->special1.m = victim->target; + victim->target = source; + } + } + victim->momx = FixedMul(BLAST_SPEED, finecosine[angle]); + victim->momy = FixedMul(BLAST_SPEED, finesine[angle]); + + // Spawn blast puff + ang = R_PointToAngle2(victim->x, victim->y, source->x, source->y); + ang >>= ANGLETOFINESHIFT; + x = victim->x + FixedMul(victim->radius + FRACUNIT, finecosine[ang]); + y = victim->y + FixedMul(victim->radius + FRACUNIT, finesine[ang]); + z = victim->z - victim->floorclip + (victim->height >> 1); + mo = P_SpawnMobj(x, y, z, MT_BLASTEFFECT); + if (mo) + { + mo->momx = victim->momx; + mo->momy = victim->momy; + } + + if (victim->flags & MF_MISSILE) + { + victim->momz = 8 * FRACUNIT; + mo->momz = victim->momz; + } + else + { + victim->momz = (1000 / victim->info->mass) << FRACBITS; + } + if (victim->player) + { + // Players handled automatically + } + else + { + victim->flags2 |= MF2_SLIDE; + victim->flags2 |= MF2_BLASTED; + } + } +} + + +// Blast all mobj things away +void P_BlastRadius(player_t * player) +{ + mobj_t *mo; + mobj_t *pmo = player->mo; + thinker_t *think; + fixed_t dist; + + S_StartSound(pmo, SFX_ARTIFACT_BLAST); + P_NoiseAlert(player->mo, player->mo); + + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + if ((mo == pmo) || (mo->flags2 & MF2_BOSS)) + { // Not a valid monster + continue; + } + if ((mo->type == MT_POISONCLOUD) || // poison cloud + (mo->type == MT_HOLY_FX) || // holy fx + (mo->flags & MF_ICECORPSE)) // frozen corpse + { + // Let these special cases go + } + else if ((mo->flags & MF_COUNTKILL) && (mo->health <= 0)) + { + continue; + } + else if (!(mo->flags & MF_COUNTKILL) && + !(mo->player) && !(mo->flags & MF_MISSILE)) + { // Must be monster, player, or missile + continue; + } + if (mo->flags2 & MF2_DORMANT) + { + continue; // no dormant creatures + } + if ((mo->type == MT_WRAITHB) && (mo->flags2 & MF2_DONTDRAW)) + { + continue; // no underground wraiths + } + if ((mo->type == MT_SPLASHBASE) || (mo->type == MT_SPLASH)) + { + continue; + } + if (mo->type == MT_SERPENT || mo->type == MT_SERPENTLEADER) + { + continue; + } + dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y); + if (dist > BLAST_RADIUS_DIST) + { // Out of range + continue; + } + P_BlastMobj(pmo, mo, BLAST_FULLSTRENGTH); + } +} + + +#define HEAL_RADIUS_DIST 255*FRACUNIT + +// Do class specific effect for everyone in radius +boolean P_HealRadius(player_t * player) +{ + mobj_t *mo; + mobj_t *pmo = player->mo; + thinker_t *think; + fixed_t dist; + int effective = false; + int amount; + + for (think = thinkercap.next; think != &thinkercap; think = think->next) + { + if (think->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + mo = (mobj_t *) think; + + if (!mo->player) + continue; + if (mo->health <= 0) + continue; + dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y); + if (dist > HEAL_RADIUS_DIST) + { // Out of range + continue; + } + + switch (player->class) + { + case PCLASS_FIGHTER: // Radius armor boost + if ((P_GiveArmor(mo->player, ARMOR_ARMOR, 1)) || + (P_GiveArmor(mo->player, ARMOR_SHIELD, 1)) || + (P_GiveArmor(mo->player, ARMOR_HELMET, 1)) || + (P_GiveArmor(mo->player, ARMOR_AMULET, 1))) + { + effective = true; + S_StartSound(mo, SFX_MYSTICINCANT); + } + break; + case PCLASS_CLERIC: // Radius heal + amount = 50 + (P_Random() % 50); + if (P_GiveBody(mo->player, amount)) + { + effective = true; + S_StartSound(mo, SFX_MYSTICINCANT); + } + break; + case PCLASS_MAGE: // Radius mana boost + amount = 50 + (P_Random() % 50); + if ((P_GiveMana(mo->player, MANA_1, amount)) || + (P_GiveMana(mo->player, MANA_2, amount))) + { + effective = true; + S_StartSound(mo, SFX_MYSTICINCANT); + } + break; + case PCLASS_PIG: + default: + break; + } + } + return (effective); +} + + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerNextArtifact +// +//---------------------------------------------------------------------------- + +void P_PlayerNextArtifact(player_t * player) +{ + if (player == &players[consoleplayer]) + { + inv_ptr--; + if (inv_ptr < 6) + { + curpos--; + if (curpos < 0) + { + curpos = 0; + } + } + if (inv_ptr < 0) + { + inv_ptr = player->inventorySlotNum - 1; + if (inv_ptr < 6) + { + curpos = inv_ptr; + } + else + { + curpos = 6; + } + } + player->readyArtifact = player->inventory[inv_ptr].type; + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerRemoveArtifact +// +//---------------------------------------------------------------------------- + +void P_PlayerRemoveArtifact(player_t * player, int slot) +{ + int i; + + player->artifactCount--; + if (!(--player->inventory[slot].count)) + { // Used last of a type - compact the artifact list + player->readyArtifact = arti_none; + player->inventory[slot].type = arti_none; + for (i = slot + 1; i < player->inventorySlotNum; i++) + { + player->inventory[i - 1] = player->inventory[i]; + } + player->inventorySlotNum--; + if (player == &players[consoleplayer]) + { // Set position markers and get next readyArtifact + inv_ptr--; + if (inv_ptr < 6) + { + curpos--; + if (curpos < 0) + { + curpos = 0; + } + } + if (inv_ptr >= player->inventorySlotNum) + { + inv_ptr = player->inventorySlotNum - 1; + } + if (inv_ptr < 0) + { + inv_ptr = 0; + } + player->readyArtifact = player->inventory[inv_ptr].type; + } + } +} + +//---------------------------------------------------------------------------- +// +// PROC P_PlayerUseArtifact +// +//---------------------------------------------------------------------------- + +void P_PlayerUseArtifact(player_t * player, artitype_t arti) +{ + int i; + + for (i = 0; i < player->inventorySlotNum; i++) + { + if (player->inventory[i].type == arti) + { // Found match - try to use + if (P_UseArtifact(player, arti)) + { // Artifact was used - remove it from inventory + P_PlayerRemoveArtifact(player, i); + if (player == &players[consoleplayer]) + { + if (arti < arti_firstpuzzitem) + { + S_StartSound(NULL, SFX_ARTIFACT_USE); + } + else + { + S_StartSound(NULL, SFX_PUZZLE_SUCCESS); + } + ArtifactFlash = 4; + } + } + else if (arti < arti_firstpuzzitem) + { // Unable to use artifact, advance pointer + P_PlayerNextArtifact(player); + } + break; + } + } +} + +//========================================================================== +// +// P_UseArtifact +// +// Returns true if the artifact was used. +// +//========================================================================== + +boolean P_UseArtifact(player_t * player, artitype_t arti) +{ + mobj_t *mo; + angle_t angle; + int i; + int count; + + switch (arti) + { + case arti_invulnerability: + if (!P_GivePower(player, pw_invulnerability)) + { + return (false); + } + break; + case arti_health: + if (!P_GiveBody(player, 25)) + { + return (false); + } + break; + case arti_superhealth: + if (!P_GiveBody(player, 100)) + { + return (false); + } + break; + case arti_healingradius: + if (!P_HealRadius(player)) + { + return (false); + } + break; + case arti_torch: + if (!P_GivePower(player, pw_infrared)) + { + return (false); + } + break; + case arti_egg: + mo = player->mo; + P_SpawnPlayerMissile(mo, MT_EGGFX); + P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 6)); + P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 6)); + P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 3)); + P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 3)); + break; + case arti_fly: + if (!P_GivePower(player, pw_flight)) + { + return (false); + } + if (player->mo->momz <= -35 * FRACUNIT) + { // stop falling scream + S_StopSound(player->mo); + } + break; + case arti_summon: + mo = P_SpawnPlayerMissile(player->mo, MT_SUMMON_FX); + if (mo) + { + mo->target = player->mo; + mo->special1.m = (player->mo); + mo->momz = 5 * FRACUNIT; + } + break; + case arti_teleport: + P_ArtiTele(player); + break; + case arti_teleportother: + P_ArtiTeleportOther(player); + break; + case arti_poisonbag: + angle = player->mo->angle >> ANGLETOFINESHIFT; + if (player->class == PCLASS_CLERIC) + { + mo = P_SpawnMobj(player->mo->x + 16 * finecosine[angle], + player->mo->y + 24 * finesine[angle], + player->mo->z - player->mo->floorclip + + 8 * FRACUNIT, MT_POISONBAG); + if (mo) + { + mo->target = player->mo; + } + } + else if (player->class == PCLASS_MAGE) + { + mo = P_SpawnMobj(player->mo->x + 16 * finecosine[angle], + player->mo->y + 24 * finesine[angle], + player->mo->z - player->mo->floorclip + + 8 * FRACUNIT, MT_FIREBOMB); + if (mo) + { + mo->target = player->mo; + } + } + else // PCLASS_FIGHTER, obviously (also pig, not so obviously) + { + mo = P_SpawnMobj(player->mo->x, player->mo->y, + player->mo->z - player->mo->floorclip + + 35 * FRACUNIT, MT_THROWINGBOMB); + if (mo) + { + mo->angle = + player->mo->angle + (((P_Random() & 7) - 4) << 24); + mo->momz = + 4 * FRACUNIT + ((player->lookdir) << (FRACBITS - 4)); + mo->z += player->lookdir << (FRACBITS - 4); + P_ThrustMobj(mo, mo->angle, mo->info->speed); + mo->momx += player->mo->momx >> 1; + mo->momy += player->mo->momy >> 1; + mo->target = player->mo; + mo->tics -= P_Random() & 3; + P_CheckMissileSpawn(mo); + } + } + break; + case arti_speed: + if (!P_GivePower(player, pw_speed)) + { + return (false); + } + break; + case arti_boostmana: + if (!P_GiveMana(player, MANA_1, MAX_MANA)) + { + if (!P_GiveMana(player, MANA_2, MAX_MANA)) + { + return false; + } + + } + else + { + P_GiveMana(player, MANA_2, MAX_MANA); + } + break; + case arti_boostarmor: + count = 0; + + for (i = 0; i < NUMARMOR; i++) + { + count += P_GiveArmor(player, i, 1); // 1 point per armor type + } + if (!count) + { + return false; + } + break; + case arti_blastradius: + P_BlastRadius(player); + break; + + case arti_puzzskull: + case arti_puzzgembig: + case arti_puzzgemred: + case arti_puzzgemgreen1: + case arti_puzzgemgreen2: + case arti_puzzgemblue1: + case arti_puzzgemblue2: + case arti_puzzbook1: + case arti_puzzbook2: + case arti_puzzskull2: + case arti_puzzfweapon: + case arti_puzzcweapon: + case arti_puzzmweapon: + case arti_puzzgear1: + case arti_puzzgear2: + case arti_puzzgear3: + case arti_puzzgear4: + if (P_UsePuzzleItem(player, arti - arti_firstpuzzitem)) + { + return true; + } + else + { + P_SetYellowMessage(player, TXT_USEPUZZLEFAILED, false); + return false; + } + break; + default: + return false; + } + return true; +} + +//============================================================================ +// +// A_SpeedFade +// +//============================================================================ + +void A_SpeedFade(mobj_t *actor, player_t *player, pspdef_t *psp) +{ + actor->flags |= MF_SHADOW; + actor->flags &= ~MF_ALTSHADOW; + actor->sprite = actor->target->sprite; +} diff --git a/games/NXDoom/src/hexen/po_man.c b/games/NXDoom/src/hexen/po_man.c new file mode 100644 index 00000000000..89364ad536d --- /dev/null +++ b/games/NXDoom/src/hexen/po_man.c @@ -0,0 +1,1505 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "i_system.h" +#include "m_bbox.h" +#include "i_swap.h" +#include "p_local.h" +#include "r_local.h" + +// MACROS ------------------------------------------------------------------ + +#define PO_MAXPOLYSEGS 64 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static polyobj_t *GetPolyobj(int polyNum); +static int GetPolyobjMirror(int poly); +static void ThrustMobj(mobj_t * mobj, seg_t * seg, polyobj_t * po); +static void UpdateSegBBox(seg_t * seg); +static void RotatePt(int an, fixed_t * x, fixed_t * y, fixed_t startSpotX, + fixed_t startSpotY); +static void UnLinkPolyobj(polyobj_t * po); +static void LinkPolyobj(polyobj_t * po); +static boolean CheckMobjBlocking(seg_t * seg, polyobj_t * po); +static void InitBlockMap(void); +static void IterFindPolySegs(int x, int y, seg_t ** segList); +static void SpawnPolyobj(int index, int tag, boolean crush); +static void TranslateToStartSpot(int tag, int originX, int originY); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +polyblock_t **PolyBlockMap; +polyobj_t *polyobjs; // list of all poly-objects on the level +int po_NumPolyobjs; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int PolySegCount; +static fixed_t PolyStartX; +static fixed_t PolyStartY; + +// CODE -------------------------------------------------------------------- + +// ===== Polyobj Event Code ===== + +//========================================================================== +// +// T_RotatePoly +// +//========================================================================== + +void T_RotatePoly(thinker_t *thinker) +{ + polyevent_t *pe = (polyevent_t *) thinker; + int absSpeed; + polyobj_t *poly; + + if (PO_RotatePolyobj(pe->polyobj, pe->speed)) + { + absSpeed = abs(pe->speed); + + if (pe->dist == -1) + { // perpetual polyobj + return; + } + pe->dist -= absSpeed; + if (pe->dist <= 0) + { + poly = GetPolyobj(pe->polyobj); + if (poly->specialdata == pe) + { + poly->specialdata = NULL; + } + SN_StopSequence((mobj_t *) & poly->startSpot); + P_PolyobjFinished(poly->tag); + P_RemoveThinker(&pe->thinker); + } + if (pe->dist < absSpeed) + { + pe->speed = pe->dist * (pe->speed < 0 ? -1 : 1); + } + } +} + +//========================================================================== +// +// EV_RotatePoly +// +//========================================================================== + +boolean EV_RotatePoly(line_t * line, byte * args, int direction, boolean + overRide) +{ + int mirror; + int polyNum; + polyevent_t *pe; + polyobj_t *poly; + + polyNum = args[0]; + poly = GetPolyobj(polyNum); + if (poly != NULL) + { + if (poly->specialdata && !overRide) + { // poly is already moving + return false; + } + } + else + { + I_Error("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); + } + pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); + P_AddThinker(&pe->thinker); + pe->thinker.function = T_RotatePoly; + pe->polyobj = polyNum; + if (args[2]) + { + if (args[2] == 255) + { + pe->dist = -1; + } + else + { + pe->dist = args[2] * (ANG90 / 64); // Angle + } + } + else + { + pe->dist = ANG_MAX - 1; + } + pe->speed = (args[1] * direction * (ANG90 / 64)) >> 3; + poly->specialdata = pe; + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + + while ((mirror = GetPolyobjMirror(polyNum)) != 0) + { + poly = GetPolyobj(mirror); + if (poly && poly->specialdata && !overRide) + { // mirroring poly is already in motion + break; + } + pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); + P_AddThinker(&pe->thinker); + pe->thinker.function = T_RotatePoly; + poly->specialdata = pe; + pe->polyobj = mirror; + if (args[2]) + { + if (args[2] == 255) + { + pe->dist = -1; + } + else + { + pe->dist = args[2] * (ANG90 / 64); // Angle + } + } + else + { + pe->dist = ANG_MAX - 1; + } + poly = GetPolyobj(polyNum); + if (poly != NULL) + { + poly->specialdata = pe; + } + else + { + I_Error("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); + } + direction = -direction; + pe->speed = (args[1] * direction * (ANG90 / 64)) >> 3; + polyNum = mirror; + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + return true; +} + +//========================================================================== +// +// T_MovePoly +// +//========================================================================== + +void T_MovePoly(thinker_t *thinker) +{ + polyevent_t *pe = (polyevent_t *) thinker; + int absSpeed; + polyobj_t *poly; + + if (PO_MovePolyobj(pe->polyobj, pe->xSpeed, pe->ySpeed)) + { + absSpeed = abs(pe->speed); + pe->dist -= absSpeed; + if (pe->dist <= 0) + { + poly = GetPolyobj(pe->polyobj); + if (poly->specialdata == pe) + { + poly->specialdata = NULL; + } + SN_StopSequence((mobj_t *) & poly->startSpot); + P_PolyobjFinished(poly->tag); + P_RemoveThinker(&pe->thinker); + } + if (pe->dist < absSpeed) + { + pe->speed = pe->dist * (pe->speed < 0 ? -1 : 1); + pe->xSpeed = FixedMul(pe->speed, finecosine[pe->angle]); + pe->ySpeed = FixedMul(pe->speed, finesine[pe->angle]); + } + } +} + +//========================================================================== +// +// EV_MovePoly +// +//========================================================================== + +boolean EV_MovePoly(line_t * line, byte * args, boolean timesEight, boolean + overRide) +{ + int mirror; + int polyNum; + polyevent_t *pe; + polyobj_t *poly; + angle_t an; + + polyNum = args[0]; + poly = GetPolyobj(polyNum); + if (poly != NULL) + { + if (poly->specialdata && !overRide) + { // poly is already moving + return false; + } + } + else + { + I_Error("EV_MovePoly: Invalid polyobj num: %d\n", polyNum); + } + pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); + P_AddThinker(&pe->thinker); + pe->thinker.function = T_MovePoly; + pe->polyobj = polyNum; + if (timesEight) + { + pe->dist = args[3] * 8 * FRACUNIT; + } + else + { + pe->dist = args[3] * FRACUNIT; // Distance + } + pe->speed = args[1] * (FRACUNIT / 8); + poly->specialdata = pe; + + an = args[2] * (ANG90 / 64); + + pe->angle = an >> ANGLETOFINESHIFT; + pe->xSpeed = FixedMul(pe->speed, finecosine[pe->angle]); + pe->ySpeed = FixedMul(pe->speed, finesine[pe->angle]); + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + + while ((mirror = GetPolyobjMirror(polyNum)) != 0) + { + poly = GetPolyobj(mirror); + if (poly && poly->specialdata && !overRide) + { // mirroring poly is already in motion + break; + } + pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); + P_AddThinker(&pe->thinker); + pe->thinker.function = T_MovePoly; + pe->polyobj = mirror; + poly->specialdata = pe; + if (timesEight) + { + pe->dist = args[3] * 8 * FRACUNIT; + } + else + { + pe->dist = args[3] * FRACUNIT; // Distance + } + pe->speed = args[1] * (FRACUNIT / 8); + an = an + ANG180; // reverse the angle + pe->angle = an >> ANGLETOFINESHIFT; + pe->xSpeed = FixedMul(pe->speed, finecosine[pe->angle]); + pe->ySpeed = FixedMul(pe->speed, finesine[pe->angle]); + polyNum = mirror; + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + return true; +} + +//========================================================================== +// +// T_PolyDoor +// +//========================================================================== + +void T_PolyDoor(thinker_t *thinker) +{ + polydoor_t *pd = (polydoor_t *) thinker; + int absSpeed; + polyobj_t *poly; + + if (pd->tics) + { + if (!--pd->tics) + { + poly = GetPolyobj(pd->polyobj); + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + return; + } + switch (pd->type) + { + case PODOOR_SLIDE: + if (PO_MovePolyobj(pd->polyobj, pd->xSpeed, pd->ySpeed)) + { + absSpeed = abs(pd->speed); + pd->dist -= absSpeed; + if (pd->dist <= 0) + { + poly = GetPolyobj(pd->polyobj); + SN_StopSequence((mobj_t *) & poly->startSpot); + if (!pd->close) + { + pd->dist = pd->totalDist; + pd->close = true; + pd->tics = pd->waitTics; + pd->direction = (ANG_MAX >> ANGLETOFINESHIFT) - + pd->direction; + pd->xSpeed = -pd->xSpeed; + pd->ySpeed = -pd->ySpeed; + } + else + { + if (poly->specialdata == pd) + { + poly->specialdata = NULL; + } + P_PolyobjFinished(poly->tag); + P_RemoveThinker(&pd->thinker); + } + } + } + else + { + poly = GetPolyobj(pd->polyobj); + if (poly->crush || !pd->close) + { // continue moving if the poly is a crusher, or is opening + return; + } + else + { // open back up + pd->dist = pd->totalDist - pd->dist; + pd->direction = (ANG_MAX >> ANGLETOFINESHIFT) - + pd->direction; + pd->xSpeed = -pd->xSpeed; + pd->ySpeed = -pd->ySpeed; + pd->close = false; + SN_StartSequence((mobj_t *) & poly->startSpot, + SEQ_DOOR_STONE + poly->seqType); + } + } + break; + case PODOOR_SWING: + if (PO_RotatePolyobj(pd->polyobj, pd->speed)) + { + absSpeed = abs(pd->speed); + if (pd->dist == -1) + { // perpetual polyobj + return; + } + pd->dist -= absSpeed; + if (pd->dist <= 0) + { + poly = GetPolyobj(pd->polyobj); + SN_StopSequence((mobj_t *) & poly->startSpot); + if (!pd->close) + { + pd->dist = pd->totalDist; + pd->close = true; + pd->tics = pd->waitTics; + pd->speed = -pd->speed; + } + else + { + if (poly->specialdata == pd) + { + poly->specialdata = NULL; + } + P_PolyobjFinished(poly->tag); + P_RemoveThinker(&pd->thinker); + } + } + } + else + { + poly = GetPolyobj(pd->polyobj); + if (poly->crush || !pd->close) + { // continue moving if the poly is a crusher, or is opening + return; + } + else + { // open back up and rewait + pd->dist = pd->totalDist - pd->dist; + pd->speed = -pd->speed; + pd->close = false; + SN_StartSequence((mobj_t *) & poly->startSpot, + SEQ_DOOR_STONE + poly->seqType); + } + } + break; + default: + break; + } +} + +//========================================================================== +// +// EV_OpenPolyDoor +// +//========================================================================== + +boolean EV_OpenPolyDoor(line_t * line, byte * args, podoortype_t type) +{ + int mirror; + int polyNum; + polydoor_t *pd; + polyobj_t *poly; + angle_t an = 0; + + polyNum = args[0]; + poly = GetPolyobj(polyNum); + if (poly != NULL) + { + if (poly->specialdata) + { // poly is already moving + return false; + } + } + else + { + I_Error("EV_OpenPolyDoor: Invalid polyobj num: %d\n", polyNum); + } + pd = Z_Malloc(sizeof(polydoor_t), PU_LEVSPEC, 0); + memset(pd, 0, sizeof(polydoor_t)); + P_AddThinker(&pd->thinker); + pd->thinker.function = T_PolyDoor; + pd->type = type; + pd->polyobj = polyNum; + if (type == PODOOR_SLIDE) + { + pd->waitTics = args[4]; + pd->speed = args[1] * (FRACUNIT / 8); + pd->totalDist = args[3] * FRACUNIT; // Distance + pd->dist = pd->totalDist; + an = args[2] * (ANG90 / 64); + pd->direction = an >> ANGLETOFINESHIFT; + pd->xSpeed = FixedMul(pd->speed, finecosine[pd->direction]); + pd->ySpeed = FixedMul(pd->speed, finesine[pd->direction]); + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + else if (type == PODOOR_SWING) + { + pd->waitTics = args[3]; + pd->direction = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR + pd->speed = (args[1] * pd->direction * (ANG90 / 64)) >> 3; + pd->totalDist = args[2] * (ANG90 / 64); + pd->dist = pd->totalDist; + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + + poly->specialdata = pd; + + while ((mirror = GetPolyobjMirror(polyNum)) != 0) + { + poly = GetPolyobj(mirror); + if (poly && poly->specialdata) + { // mirroring poly is already in motion + break; + } + pd = Z_Malloc(sizeof(polydoor_t), PU_LEVSPEC, 0); + memset(pd, 0, sizeof(polydoor_t)); + P_AddThinker(&pd->thinker); + pd->thinker.function = T_PolyDoor; + pd->polyobj = mirror; + pd->type = type; + poly->specialdata = pd; + if (type == PODOOR_SLIDE) + { + pd->waitTics = args[4]; + pd->speed = args[1] * (FRACUNIT / 8); + pd->totalDist = args[3] * FRACUNIT; // Distance + pd->dist = pd->totalDist; + an = an + ANG180; // reverse the angle + pd->direction = an >> ANGLETOFINESHIFT; + pd->xSpeed = FixedMul(pd->speed, finecosine[pd->direction]); + pd->ySpeed = FixedMul(pd->speed, finesine[pd->direction]); + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + else if (type == PODOOR_SWING) + { + pd->waitTics = args[3]; + pd->direction = -1; // ADD: same as above + pd->speed = (args[1] * pd->direction * (ANG90 / 64)) >> 3; + pd->totalDist = args[2] * (ANG90 / 64); + pd->dist = pd->totalDist; + SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + + poly->seqType); + } + polyNum = mirror; + } + return true; +} + +// ===== Higher Level Poly Interface code ===== + +//========================================================================== +// +// GetPolyobj +// +//========================================================================== + +static polyobj_t *GetPolyobj(int polyNum) +{ + int i; + + for (i = 0; i < po_NumPolyobjs; i++) + { + if (polyobjs[i].tag == polyNum) + { + return &polyobjs[i]; + } + } + return NULL; +} + +//========================================================================== +// +// GetPolyobjMirror +// +//========================================================================== + +static int GetPolyobjMirror(int poly) +{ + int i; + + for (i = 0; i < po_NumPolyobjs; i++) + { + if (polyobjs[i].tag == poly) + { + return ((*polyobjs[i].segs)->linedef->arg2); + } + } + return 0; +} + +//========================================================================== +// +// ThrustMobj +// +//========================================================================== + +static void ThrustMobj(mobj_t * mobj, seg_t * seg, polyobj_t * po) +{ + int thrustAngle; + int thrustX; + int thrustY; + polyevent_t *pe; + + int force; + + if (!(mobj->flags & MF_SHOOTABLE) && !mobj->player) + { + return; + } + thrustAngle = (seg->angle - ANG90) >> ANGLETOFINESHIFT; + + pe = po->specialdata; + if (pe) + { + if (pe->thinker.function == T_RotatePoly) + { + force = pe->speed >> 8; + } + else + { + force = pe->speed >> 3; + } + if (force < FRACUNIT) + { + force = FRACUNIT; + } + else if (force > 4 * FRACUNIT) + { + force = 4 * FRACUNIT; + } + } + else + { + force = FRACUNIT; + } + + thrustX = FixedMul(force, finecosine[thrustAngle]); + thrustY = FixedMul(force, finesine[thrustAngle]); + mobj->momx += thrustX; + mobj->momy += thrustY; + if (po->crush) + { + if (!P_CheckPosition(mobj, mobj->x + thrustX, mobj->y + thrustY)) + { + P_DamageMobj(mobj, NULL, NULL, 3); + } + } +} + +//========================================================================== +// +// UpdateSegBBox +// +//========================================================================== + +static void UpdateSegBBox(seg_t * seg) +{ + line_t *line; + + line = seg->linedef; + + if (seg->v1->x < seg->v2->x) + { + line->bbox[BOXLEFT] = seg->v1->x; + line->bbox[BOXRIGHT] = seg->v2->x; + } + else + { + line->bbox[BOXLEFT] = seg->v2->x; + line->bbox[BOXRIGHT] = seg->v1->x; + } + if (seg->v1->y < seg->v2->y) + { + line->bbox[BOXBOTTOM] = seg->v1->y; + line->bbox[BOXTOP] = seg->v2->y; + } + else + { + line->bbox[BOXBOTTOM] = seg->v2->y; + line->bbox[BOXTOP] = seg->v1->y; + } + + // Update the line's slopetype + line->dx = line->v2->x - line->v1->x; + line->dy = line->v2->y - line->v1->y; + if (!line->dx) + { + line->slopetype = ST_VERTICAL; + } + else if (!line->dy) + { + line->slopetype = ST_HORIZONTAL; + } + else + { + if (FixedDiv(line->dy, line->dx) > 0) + { + line->slopetype = ST_POSITIVE; + } + else + { + line->slopetype = ST_NEGATIVE; + } + } +} + +//========================================================================== +// +// PO_MovePolyobj +// +//========================================================================== + +boolean PO_MovePolyobj(int num, int x, int y) +{ + int count; + seg_t **segList; + seg_t **veryTempSeg; + polyobj_t *po; + vertex_t *prevPts; + boolean blocked; + + if (!(po = GetPolyobj(num))) + { + I_Error("PO_MovePolyobj: Invalid polyobj number: %d\n", num); + } + + UnLinkPolyobj(po); + + segList = po->segs; + prevPts = po->prevPts; + blocked = false; + + validcount++; + for (count = po->numsegs; count; count--, segList++, prevPts++) + { + if ((*segList)->linedef->validcount != validcount) + { + (*segList)->linedef->bbox[BOXTOP] += y; + (*segList)->linedef->bbox[BOXBOTTOM] += y; + (*segList)->linedef->bbox[BOXLEFT] += x; + (*segList)->linedef->bbox[BOXRIGHT] += x; + (*segList)->linedef->validcount = validcount; + } + for (veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++) + { + if ((*veryTempSeg)->v1 == (*segList)->v1) + { + break; + } + } + if (veryTempSeg == segList) + { + (*segList)->v1->x += x; + (*segList)->v1->y += y; + } + (*prevPts).x += x; // previous points are unique for each seg + (*prevPts).y += y; + } + segList = po->segs; + for (count = po->numsegs; count; count--, segList++) + { + if (CheckMobjBlocking(*segList, po)) + { + blocked = true; + } + } + if (blocked) + { + count = po->numsegs; + segList = po->segs; + prevPts = po->prevPts; + validcount++; + while (count--) + { + if ((*segList)->linedef->validcount != validcount) + { + (*segList)->linedef->bbox[BOXTOP] -= y; + (*segList)->linedef->bbox[BOXBOTTOM] -= y; + (*segList)->linedef->bbox[BOXLEFT] -= x; + (*segList)->linedef->bbox[BOXRIGHT] -= x; + (*segList)->linedef->validcount = validcount; + } + for (veryTempSeg = po->segs; veryTempSeg != segList; + veryTempSeg++) + { + if ((*veryTempSeg)->v1 == (*segList)->v1) + { + break; + } + } + if (veryTempSeg == segList) + { + (*segList)->v1->x -= x; + (*segList)->v1->y -= y; + } + (*prevPts).x -= x; + (*prevPts).y -= y; + segList++; + prevPts++; + } + LinkPolyobj(po); + return false; + } + po->startSpot.x += x; + po->startSpot.y += y; + LinkPolyobj(po); + return true; +} + +//========================================================================== +// +// RotatePt +// +//========================================================================== + +static void RotatePt(int an, fixed_t * x, fixed_t * y, fixed_t startSpotX, + fixed_t startSpotY) +{ + fixed_t trx, try; + fixed_t gxt, gyt; + + trx = *x; + try = *y; + + gxt = FixedMul(trx, finecosine[an]); + gyt = FixedMul(try, finesine[an]); + *x = (gxt - gyt) + startSpotX; + + gxt = FixedMul(trx, finesine[an]); + gyt = FixedMul(try, finecosine[an]); + *y = (gyt + gxt) + startSpotY; +} + +//========================================================================== +// +// PO_RotatePolyobj +// +//========================================================================== + +boolean PO_RotatePolyobj(int num, angle_t angle) +{ + int count; + seg_t **segList; + vertex_t *originalPts; + vertex_t *prevPts; + int an; + polyobj_t *po; + boolean blocked; + + if (!(po = GetPolyobj(num))) + { + I_Error("PO_RotatePolyobj: Invalid polyobj number: %d\n", num); + } + an = (po->angle + angle) >> ANGLETOFINESHIFT; + + UnLinkPolyobj(po); + + segList = po->segs; + originalPts = po->originalPts; + prevPts = po->prevPts; + + for (count = po->numsegs; count; count--, segList++, originalPts++, + prevPts++) + { + prevPts->x = (*segList)->v1->x; + prevPts->y = (*segList)->v1->y; + (*segList)->v1->x = originalPts->x; + (*segList)->v1->y = originalPts->y; + RotatePt(an, &(*segList)->v1->x, &(*segList)->v1->y, po->startSpot.x, + po->startSpot.y); + } + segList = po->segs; + blocked = false; + validcount++; + for (count = po->numsegs; count; count--, segList++) + { + if (CheckMobjBlocking(*segList, po)) + { + blocked = true; + } + if ((*segList)->linedef->validcount != validcount) + { + UpdateSegBBox(*segList); + (*segList)->linedef->validcount = validcount; + } + (*segList)->angle += angle; + } + if (blocked) + { + segList = po->segs; + prevPts = po->prevPts; + for (count = po->numsegs; count; count--, segList++, prevPts++) + { + (*segList)->v1->x = prevPts->x; + (*segList)->v1->y = prevPts->y; + } + segList = po->segs; + validcount++; + for (count = po->numsegs; count; count--, segList++, prevPts++) + { + if ((*segList)->linedef->validcount != validcount) + { + UpdateSegBBox(*segList); + (*segList)->linedef->validcount = validcount; + } + (*segList)->angle -= angle; + } + LinkPolyobj(po); + return false; + } + po->angle += angle; + LinkPolyobj(po); + return true; +} + +//========================================================================== +// +// UnLinkPolyobj +// +//========================================================================== + +static void UnLinkPolyobj(polyobj_t * po) +{ + polyblock_t *link; + int i, j; + int index; + + // remove the polyobj from each blockmap section + for (j = po->bbox[BOXBOTTOM]; j <= po->bbox[BOXTOP]; j++) + { + index = j * bmapwidth; + for (i = po->bbox[BOXLEFT]; i <= po->bbox[BOXRIGHT]; i++) + { + if (i >= 0 && i < bmapwidth && j >= 0 && j < bmapheight) + { + link = PolyBlockMap[index + i]; + while (link != NULL && link->polyobj != po) + { + link = link->next; + } + if (link == NULL) + { // polyobj not located in the link cell + continue; + } + link->polyobj = NULL; + } + } + } +} + +//========================================================================== +// +// LinkPolyobj +// +//========================================================================== + +static void LinkPolyobj(polyobj_t * po) +{ + int leftX, rightX; + int topY, bottomY; + seg_t **tempSeg; + polyblock_t **link; + polyblock_t *tempLink; + int i, j; + + // calculate the polyobj bbox + tempSeg = po->segs; + rightX = leftX = (*tempSeg)->v1->x; + topY = bottomY = (*tempSeg)->v1->y; + + for (i = 0; i < po->numsegs; i++, tempSeg++) + { + if ((*tempSeg)->v1->x > rightX) + { + rightX = (*tempSeg)->v1->x; + } + if ((*tempSeg)->v1->x < leftX) + { + leftX = (*tempSeg)->v1->x; + } + if ((*tempSeg)->v1->y > topY) + { + topY = (*tempSeg)->v1->y; + } + if ((*tempSeg)->v1->y < bottomY) + { + bottomY = (*tempSeg)->v1->y; + } + } + po->bbox[BOXRIGHT] = (rightX - bmaporgx) >> MAPBLOCKSHIFT; + po->bbox[BOXLEFT] = (leftX - bmaporgx) >> MAPBLOCKSHIFT; + po->bbox[BOXTOP] = (topY - bmaporgy) >> MAPBLOCKSHIFT; + po->bbox[BOXBOTTOM] = (bottomY - bmaporgy) >> MAPBLOCKSHIFT; + // add the polyobj to each blockmap section + for (j = po->bbox[BOXBOTTOM] * bmapwidth; + j <= po->bbox[BOXTOP] * bmapwidth; j += bmapwidth) + { + for (i = po->bbox[BOXLEFT]; i <= po->bbox[BOXRIGHT]; i++) + { + if (i >= 0 && i < bmapwidth && j >= 0 + && j < bmapheight * bmapwidth) + { + link = &PolyBlockMap[j + i]; + if (!(*link)) + { // Create a new link at the current block cell + *link = Z_Malloc(sizeof(polyblock_t), PU_LEVEL, 0); + (*link)->next = NULL; + (*link)->prev = NULL; + (*link)->polyobj = po; + continue; + } + else + { + tempLink = *link; + while (tempLink->next != NULL + && tempLink->polyobj != NULL) + { + tempLink = tempLink->next; + } + } + if (tempLink->polyobj == NULL) + { + tempLink->polyobj = po; + continue; + } + else + { + tempLink->next = Z_Malloc(sizeof(polyblock_t), + PU_LEVEL, 0); + tempLink->next->next = NULL; + tempLink->next->prev = tempLink; + tempLink->next->polyobj = po; + } + } + // else, don't link the polyobj, since it's off the map + } + } +} + +//========================================================================== +// +// CheckMobjBlocking +// +//========================================================================== + +static boolean CheckMobjBlocking(seg_t * seg, polyobj_t * po) +{ + mobj_t *mobj; + int i, j; + int left, right, top, bottom; + int tmbbox[4]; + line_t *ld; + boolean blocked; + + ld = seg->linedef; + + top = (ld->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + bottom = (ld->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + left = (ld->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + right = (ld->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + + blocked = false; + + bottom = bottom < 0 ? 0 : bottom; + bottom = bottom >= bmapheight ? bmapheight - 1 : bottom; + top = top < 0 ? 0 : top; + top = top >= bmapheight ? bmapheight - 1 : top; + left = left < 0 ? 0 : left; + left = left >= bmapwidth ? bmapwidth - 1 : left; + right = right < 0 ? 0 : right; + right = right >= bmapwidth ? bmapwidth - 1 : right; + + for (j = bottom * bmapwidth; j <= top * bmapwidth; j += bmapwidth) + { + for (i = left; i <= right; i++) + { + for (mobj = blocklinks[j + i]; mobj; mobj = mobj->bnext) + { + if (mobj->flags & MF_SOLID || mobj->player) + { + tmbbox[BOXTOP] = mobj->y + mobj->radius; + tmbbox[BOXBOTTOM] = mobj->y - mobj->radius; + tmbbox[BOXLEFT] = mobj->x - mobj->radius; + tmbbox[BOXRIGHT] = mobj->x + mobj->radius; + + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] + || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] + || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + { + continue; + } + if (P_BoxOnLineSide(tmbbox, ld) != -1) + { + continue; + } + ThrustMobj(mobj, seg, po); + blocked = true; + } + } + } + } + return blocked; +} + +//========================================================================== +// +// InitBlockMap +// +//========================================================================== + +static void InitBlockMap(void) +{ + int i; + int j; + seg_t **segList; + int leftX, rightX; + int topY, bottomY; + + PolyBlockMap = Z_Malloc(bmapwidth * bmapheight * sizeof(polyblock_t *), + PU_LEVEL, 0); + memset(PolyBlockMap, 0, bmapwidth * bmapheight * sizeof(polyblock_t *)); + + for (i = 0; i < po_NumPolyobjs; i++) + { + LinkPolyobj(&polyobjs[i]); + + // calculate a rough area + // right now, working like shit...gotta fix this... + segList = polyobjs[i].segs; + leftX = rightX = (*segList)->v1->x; + topY = bottomY = (*segList)->v1->y; + for (j = 0; j < polyobjs[i].numsegs; j++, segList++) + { + if ((*segList)->v1->x < leftX) + { + leftX = (*segList)->v1->x; + } + if ((*segList)->v1->x > rightX) + { + rightX = (*segList)->v1->x; + } + if ((*segList)->v1->y < bottomY) + { + bottomY = (*segList)->v1->y; + } + if ((*segList)->v1->y > topY) + { + topY = (*segList)->v1->y; + } + } +// area = ((rightX >> FRACBITS) - (leftX >> FRACBITS)) * +// ((topY >> FRACBITS) - (bottomY >> FRACBITS)); + +// fprintf(stdaux, "Area of Polyobj[%d]: %d\n", polyobjs[i].tag, area); +// fprintf(stdaux, "\t[%d]\n[%d]\t\t[%d]\n\t[%d]\n", topY>>FRACBITS, +// leftX>>FRACBITS, +// rightX>>FRACBITS, bottomY>>FRACBITS); + } +} + +//========================================================================== +// +// IterFindPolySegs +// +// Passing NULL for segList will cause IterFindPolySegs to +// count the number of segs in the polyobj +//========================================================================== + +static void IterFindPolySegs(int x, int y, seg_t ** segList) +{ + int i; + + if (x == PolyStartX && y == PolyStartY) + { + return; + } + for (i = 0; i < numsegs; i++) + { + if (segs[i].v1->x == x && segs[i].v1->y == y) + { + if (!segList) + { + PolySegCount++; + } + else + { + *segList++ = &segs[i]; + } + IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, segList); + return; + } + } + I_Error("IterFindPolySegs: Non-closed Polyobj located.\n"); +} + + +//========================================================================== +// +// SpawnPolyobj +// +//========================================================================== + +static void SpawnPolyobj(int index, int tag, boolean crush) +{ + int i; + int j; + int psIndex; + int psIndexOld; + seg_t *polySegList[PO_MAXPOLYSEGS]; + + for (i = 0; i < numsegs; i++) + { + if (segs[i].linedef->special == PO_LINE_START && + segs[i].linedef->arg1 == tag) + { + if (polyobjs[index].segs) + { + I_Error("SpawnPolyobj: Polyobj %d already spawned.\n", tag); + } + segs[i].linedef->special = 0; + segs[i].linedef->arg1 = 0; + PolySegCount = 1; + PolyStartX = segs[i].v1->x; + PolyStartY = segs[i].v1->y; + IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, NULL); + + polyobjs[index].numsegs = PolySegCount; + polyobjs[index].segs = Z_Malloc(PolySegCount * sizeof(seg_t *), + PU_LEVEL, 0); + *(polyobjs[index].segs) = &segs[i]; // insert the first seg + IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, + polyobjs[index].segs + 1); + polyobjs[index].crush = crush; + polyobjs[index].tag = tag; + polyobjs[index].seqType = segs[i].linedef->arg3; + if (polyobjs[index].seqType < 0 + || polyobjs[index].seqType >= SEQTYPE_NUMSEQ) + { + polyobjs[index].seqType = 0; + } + break; + } + } + if (!polyobjs[index].segs) + { // didn't find a polyobj through PO_LINE_START + psIndex = 0; + polyobjs[index].numsegs = 0; + for (j = 1; j < PO_MAXPOLYSEGS; j++) + { + psIndexOld = psIndex; + for (i = 0; i < numsegs; i++) + { + if (segs[i].linedef->special == PO_LINE_EXPLICIT && + segs[i].linedef->arg1 == tag) + { + if (!segs[i].linedef->arg2) + { + I_Error + ("SpawnPolyobj: Explicit line missing order number (probably %d) in poly %d.\n", + j + 1, tag); + } + if (segs[i].linedef->arg2 == j) + { + polySegList[psIndex] = &segs[i]; + polyobjs[index].numsegs++; + psIndex++; + if (psIndex > PO_MAXPOLYSEGS) + { + I_Error + ("SpawnPolyobj: psIndex > PO_MAXPOLYSEGS\n"); + } + } + } + } + // Clear out any specials for these segs...we cannot clear them out + // in the above loop, since we aren't guaranteed one seg per + // linedef. + for (i = 0; i < numsegs; i++) + { + if (segs[i].linedef->special == PO_LINE_EXPLICIT && + segs[i].linedef->arg1 == tag + && segs[i].linedef->arg2 == j) + { + segs[i].linedef->special = 0; + segs[i].linedef->arg1 = 0; + } + } + if (psIndex == psIndexOld) + { // Check if an explicit line order has been skipped + // A line has been skipped if there are any more explicit + // lines with the current tag value + for (i = 0; i < numsegs; i++) + { + if (segs[i].linedef->special == PO_LINE_EXPLICIT && + segs[i].linedef->arg1 == tag) + { + I_Error + ("SpawnPolyobj: Missing explicit line %d for poly %d\n", + j, tag); + } + } + } + } + if (polyobjs[index].numsegs) + { + PolySegCount = polyobjs[index].numsegs; // PolySegCount used globally + polyobjs[index].crush = crush; + polyobjs[index].tag = tag; + polyobjs[index].segs = Z_Malloc(polyobjs[index].numsegs + * sizeof(seg_t *), PU_LEVEL, 0); + for (i = 0; i < polyobjs[index].numsegs; i++) + { + polyobjs[index].segs[i] = polySegList[i]; + } + polyobjs[index].seqType = (*polyobjs[index].segs)->linedef->arg4; + } + // Next, change the polyobjs first line to point to a mirror + // if it exists + (*polyobjs[index].segs)->linedef->arg2 = + (*polyobjs[index].segs)->linedef->arg3; + } +} + +//========================================================================== +// +// TranslateToStartSpot +// +//========================================================================== + +static void TranslateToStartSpot(int tag, int originX, int originY) +{ + seg_t **tempSeg; + seg_t **veryTempSeg; + vertex_t *tempPt; + subsector_t *sub; + polyobj_t *po; + int deltaX; + int deltaY; + vertex_t avg; // used to find a polyobj's center, and hence subsector + int i; + + po = NULL; + for (i = 0; i < po_NumPolyobjs; i++) + { + if (polyobjs[i].tag == tag) + { + po = &polyobjs[i]; + break; + } + } + if (!po) + { // didn't match the tag with a polyobj tag + I_Error("TranslateToStartSpot: Unable to match polyobj tag: %d\n", + tag); + } + if (po->segs == NULL) + { + I_Error + ("TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", + tag); + } + po->originalPts = Z_Malloc(po->numsegs * sizeof(vertex_t), PU_LEVEL, 0); + po->prevPts = Z_Malloc(po->numsegs * sizeof(vertex_t), PU_LEVEL, 0); + deltaX = originX - po->startSpot.x; + deltaY = originY - po->startSpot.y; + + tempSeg = po->segs; + tempPt = po->originalPts; + avg.x = 0; + avg.y = 0; + + validcount++; + for (i = 0; i < po->numsegs; i++, tempSeg++, tempPt++) + { + if ((*tempSeg)->linedef->validcount != validcount) + { + (*tempSeg)->linedef->bbox[BOXTOP] -= deltaY; + (*tempSeg)->linedef->bbox[BOXBOTTOM] -= deltaY; + (*tempSeg)->linedef->bbox[BOXLEFT] -= deltaX; + (*tempSeg)->linedef->bbox[BOXRIGHT] -= deltaX; + (*tempSeg)->linedef->validcount = validcount; + } + for (veryTempSeg = po->segs; veryTempSeg != tempSeg; veryTempSeg++) + { + if ((*veryTempSeg)->v1 == (*tempSeg)->v1) + { + break; + } + } + if (veryTempSeg == tempSeg) + { // the point hasn't been translated, yet + (*tempSeg)->v1->x -= deltaX; + (*tempSeg)->v1->y -= deltaY; + } + avg.x += (*tempSeg)->v1->x >> FRACBITS; + avg.y += (*tempSeg)->v1->y >> FRACBITS; + // the original Pts are based off the startSpot Pt, and are + // unique to each seg, not each linedef + tempPt->x = (*tempSeg)->v1->x - po->startSpot.x; + tempPt->y = (*tempSeg)->v1->y - po->startSpot.y; + } + avg.x /= po->numsegs; + avg.y /= po->numsegs; + sub = R_PointInSubsector(avg.x << FRACBITS, avg.y << FRACBITS); + if (sub->poly != NULL) + { + I_Error + ("PO_TranslateToStartSpot: Multiple polyobjs in a single subsector.\n"); + } + sub->poly = po; +} + +//========================================================================== +// +// PO_Init +// +//========================================================================== + +void PO_Init(int lump) +{ + byte *data; + int i; + mapthing_t spawnthing; + mapthing_t *mt; + int numthings; + int polyIndex; + + polyobjs = Z_Malloc(po_NumPolyobjs * sizeof(polyobj_t), PU_LEVEL, 0); + memset(polyobjs, 0, po_NumPolyobjs * sizeof(polyobj_t)); + + data = W_CacheLumpNum(lump, PU_STATIC); + numthings = W_LumpLength(lump) / sizeof(mapthing_t); + mt = (mapthing_t *) data; + polyIndex = 0; // index polyobj number + // Find the startSpot points, and spawn each polyobj + for (i = 0; i < numthings; i++, mt++) + { + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + + // 3001 = no crush, 3002 = crushing + if (spawnthing.type == PO_SPAWN_TYPE + || spawnthing.type == PO_SPAWNCRUSH_TYPE) + { // Polyobj StartSpot Pt. + polyobjs[polyIndex].startSpot.x = spawnthing.x << FRACBITS; + polyobjs[polyIndex].startSpot.y = spawnthing.y << FRACBITS; + polyobjs[polyIndex].startSpot.thinker.function = (think_t) P_DegenMobjThinker; + SpawnPolyobj(polyIndex, spawnthing.angle, + (spawnthing.type == PO_SPAWNCRUSH_TYPE)); + polyIndex++; + } + } + mt = (mapthing_t *) data; + for (i = 0; i < numthings; i++, mt++) + { + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + if (spawnthing.type == PO_ANCHOR_TYPE) + { // Polyobj Anchor Pt. + TranslateToStartSpot(spawnthing.angle, + spawnthing.x << FRACBITS, + spawnthing.y << FRACBITS); + } + } + W_ReleaseLumpNum(lump); + // check for a startspot without an anchor point + for (i = 0; i < po_NumPolyobjs; i++) + { + if (!polyobjs[i].originalPts) + { + I_Error + ("PO_Init: StartSpot located without an Anchor point: %d\n", + polyobjs[i].tag); + } + } + InitBlockMap(); +} + +//========================================================================== +// +// PO_Busy +// +//========================================================================== + +boolean PO_Busy(int polyobj) +{ + polyobj_t *poly; + + poly = GetPolyobj(polyobj); + if (!poly->specialdata) + { + return false; + } + else + { + return true; + } +} diff --git a/games/NXDoom/src/hexen/r_bsp.c b/games/NXDoom/src/hexen/r_bsp.c new file mode 100644 index 00000000000..cae9cbfd466 --- /dev/null +++ b/games/NXDoom/src/hexen/r_bsp.c @@ -0,0 +1,508 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "m_bbox.h" +#include "r_local.h" + +seg_t *curline; +side_t *sidedef; +line_t *linedef; +sector_t *frontsector, *backsector; + +drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; + +void R_StoreWallRange(int start, int stop); + +/* +==================== += += R_ClearDrawSegs += +==================== +*/ + +void R_ClearDrawSegs(void) +{ + ds_p = drawsegs; +} + +//============================================================================= + + +/* +=============================================================================== += += ClipWallSegment += += Clips the given range of columns and includes it in the new clip list +=============================================================================== +*/ + +typedef struct +{ + int first, last; +} cliprange_t; + +// We must expand MAXSEGS to the theoretical limit of the number of solidsegs +// that can be generated in a scene by the DOOM engine. This was determined by +// Lee Killough during BOOM development to be a function of the screensize. +// The simplest thing we can do, other than fix this bug, is to let the game +// render overage and then bomb out by detecting the overflow after the +// fact. -haleyjd +//#define MAXSEGS 32 +#define MAXSEGS (SCREENWIDTH / 2 + 1) + +cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg + + +void R_ClipSolidWallSegment(int first, int last) +{ + cliprange_t *next, *start; + +// find the first range that touches the range (adjacent pixels are touching) + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) + { + if (last < start->first - 1) + { // post is entirely visible (above start), so insert a new clippost + R_StoreWallRange(first, last); + next = newend; + newend++; + while (next != start) + { + *next = *(next - 1); + next--; + } + next->first = first; + next->last = last; + return; + } + + // there is a fragment above *start + R_StoreWallRange(first, start->first - 1); + start->first = first; // adjust the clip size + } + + if (last <= start->last) + return; // bottom contained in start + + next = start; + while (last >= (next + 1)->first - 1) + { + // there is a fragment between two posts + R_StoreWallRange(next->last + 1, (next + 1)->first - 1); + next++; + if (last <= next->last) + { // bottom is contained in next + start->last = next->last; // adjust the clip size + goto crunch; + } + } + + // there is a fragment after *next + R_StoreWallRange(next->last + 1, last); + start->last = last; // adjust the clip size + + +// remove start+1 to next from the clip list, +// because start now covers their area + crunch: + if (next == start) + return; // post just extended past the bottom of one post + + while (next++ != newend) // remove a post + *++start = *next; + newend = start + 1; +} + +/* +=============================================================================== += += R_ClipPassWallSegment += += Clips the given range of columns, but does not includes it in the clip list +=============================================================================== +*/ + +void R_ClipPassWallSegment(int first, int last) +{ + cliprange_t *start; + +// find the first range that touches the range (adjacent pixels are touching) + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) + { + if (last < start->first - 1) + { // post is entirely visible (above start) + R_StoreWallRange(first, last); + return; + } + + // there is a fragment above *start + R_StoreWallRange(first, start->first - 1); + } + + if (last <= start->last) + return; // bottom contained in start + + while (last >= (start + 1)->first - 1) + { + // there is a fragment between two posts + R_StoreWallRange(start->last + 1, (start + 1)->first - 1); + start++; + if (last <= start->last) + return; + } + + // there is a fragment after *next + R_StoreWallRange(start->last + 1, last); +} + + + +/* +==================== += += R_ClearClipSegs += +==================== +*/ + +void R_ClearClipSegs(void) +{ + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs + 2; +} + + +//============================================================================= + +/* +====================== += += R_AddLine += += Clips the given segment and adds any visible pieces to the line list += +====================== +*/ + +void R_AddLine(seg_t * line) +{ + int x1, x2; + angle_t angle1, angle2, span, tspan; + + curline = line; + +// OPTIMIZE: quickly reject orthogonal back sides + + angle1 = R_PointToAngle(line->v1->x, line->v1->y); + angle2 = R_PointToAngle(line->v2->x, line->v2->y); + +// +// clip to view edges +// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW) + span = angle1 - angle2; + if (span >= ANG180) + return; // back side + + rw_angle1 = angle1; // global angle needed by segcalc + angle1 -= viewangle; + angle2 -= viewangle; + + tspan = angle1 + clipangle; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return; // totally off the left edge + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return; // totally off the left edge + angle2 = -clipangle; + } + +// +// the seg is in the view range, but not necessarily visible +// + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; + if (x1 == x2) + return; // does not cross a pixel + + backsector = line->backsector; + + if (!backsector) + goto clipsolid; // single sided line + + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + goto clipsolid; // closed door + + if (backsector->ceilingheight != frontsector->ceilingheight + || backsector->floorheight != frontsector->floorheight) + goto clippass; // window + +// reject empty lines used for triggers and special events + if (backsector->ceilingpic == frontsector->ceilingpic + && backsector->floorpic == frontsector->floorpic + && backsector->lightlevel == frontsector->lightlevel + && backsector->special == frontsector->special + && curline->sidedef->midtexture == 0) + return; + + clippass: + R_ClipPassWallSegment(x1, x2 - 1); + return; + + clipsolid: + R_ClipSolidWallSegment(x1, x2 - 1); +} + +//============================================================================ + + +/* +=============================================================================== += += R_CheckBBox += += Returns true if some part of the bbox might be visible += +=============================================================================== +*/ + +int checkcoord[12][4] = { + {3, 0, 2, 1}, + {3, 0, 2, 0}, + {3, 1, 2, 0}, + {0}, + {2, 0, 2, 1}, + {0, 0, 0, 0}, + {3, 1, 3, 0}, + {0}, + {2, 0, 3, 1}, + {2, 1, 3, 1}, + {2, 1, 3, 0} +}; + + +boolean R_CheckBBox(fixed_t * bspcoord) +{ + int boxx, boxy, boxpos; + fixed_t x1, y1, x2, y2; + angle_t angle1, angle2, span, tspan; + cliprange_t *start; + int sx1, sx2; + +// find the corners of the box that define the edges from current viewpoint + if (viewx <= bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx < bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy >= bspcoord[BOXTOP]) + boxy = 0; + else if (viewy > bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy << 2) + boxx; + if (boxpos == 5) + return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + +// +// check clip list for an open space +// + angle1 = R_PointToAngle(x1, y1) - viewangle; + angle2 = R_PointToAngle(x2, y2) - viewangle; + + span = angle1 - angle2; + if (span >= ANG180) + return true; // sitting on a line + tspan = angle1 + clipangle; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return false; // totally off the left edge + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) + { + tspan -= 2 * clipangle; + if (tspan >= span) + return false; // totally off the left edge + angle2 = -clipangle; + } + + +// find the first clippost that touches the source post (adjacent pixels are touching) + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + sx1 = viewangletox[angle1]; + sx2 = viewangletox[angle2]; + if (sx1 == sx2) + return false; // does not cross a pixel + sx2--; + + start = solidsegs; + while (start->last < sx2) + start++; + if (sx1 >= start->first && sx2 <= start->last) + return false; // the clippost contains the new span + + return true; +} + + +/* +================ += += R_Subsector += += Draw one or more segments +================ +*/ + +void R_Subsector(int num) +{ + int count; + seg_t *line; + subsector_t *sub; + int polyCount; + seg_t **polySeg; + +#ifdef RANGECHECK + if (num >= numsubsectors) + I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); +#endif + + sscount++; + sub = &subsectors[num]; + frontsector = sub->sector; + count = sub->numlines; + line = &segs[sub->firstline]; + + if (frontsector->floorheight < viewz) + { + floorplane = R_FindPlane(frontsector->floorheight, + frontsector->floorpic, + frontsector->lightlevel, + frontsector->special); + } + else + { + floorplane = NULL; + } + + if (frontsector->ceilingheight > viewz + || frontsector->ceilingpic == skyflatnum) + { + ceilingplane = R_FindPlane(frontsector->ceilingheight, + frontsector->ceilingpic, + frontsector->lightlevel, 0); + } + else + { + ceilingplane = NULL; + } + + R_AddSprites(frontsector); + if (sub->poly) + { // Render the polyobj in the subsector first + polyCount = sub->poly->numsegs; + polySeg = sub->poly->segs; + while (polyCount--) + { + R_AddLine(*polySeg++); + } + } + while (count--) + { + R_AddLine(line); + line++; + } + + // check for solidsegs overflow - extremely unsatisfactory! + if(newend > &solidsegs[32]) + I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); +} + + +/* +=============================================================================== += += RenderBSPNode += +=============================================================================== +*/ + +void R_RenderBSPNode(int bspnum) +{ + node_t *bsp; + int side; + + if (bspnum & NF_SUBSECTOR) + { + if (bspnum == -1) + R_Subsector(0); + else + R_Subsector(bspnum & (~NF_SUBSECTOR)); + return; + } + + bsp = &nodes[bspnum]; + +// +// decide which side the view point is on +// + side = R_PointOnSide(viewx, viewy, bsp); + + R_RenderBSPNode(bsp->children[side]); // recursively divide front space + + if (R_CheckBBox(bsp->bbox[side ^ 1])) // possibly divide back space + R_RenderBSPNode(bsp->children[side ^ 1]); +} diff --git a/games/NXDoom/src/hexen/r_data.c b/games/NXDoom/src/hexen/r_data.c new file mode 100644 index 00000000000..1c4ef7c36a5 --- /dev/null +++ b/games/NXDoom/src/hexen/r_data.c @@ -0,0 +1,689 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "i_swap.h" +#include "m_misc.h" +#include "r_local.h" +#include "p_local.h" + +typedef struct +{ + int originx; // block origin (allways UL), which has allready + int originy; // accounted for the patch's internal origin + int patch; +} texpatch_t; + +// a maptexturedef_t describes a rectangular texture, which is composed of one +// or more mappatch_t structures that arrange graphic patches +typedef struct +{ + char name[8]; // for switch changing, etc + short width; + short height; + short patchcount; + texpatch_t patches[1]; // [patchcount] drawn back to front + // into the cached texture +} texture_t; + + + +int firstflat, lastflat, numflats; +int firstpatch, lastpatch, numpatches; +int firstspritelump, lastspritelump, numspritelumps; + +int numtextures; +texture_t **textures; +int *texturewidthmask; +fixed_t *textureheight; // needed for texture pegging +int *texturecompositesize; +short **texturecolumnlump; +unsigned short **texturecolumnofs; +byte **texturecomposite; + +int *flattranslation; // for global animation +int *texturetranslation; // for global animation + +fixed_t *spritewidth; // needed for pre rendering +fixed_t *spriteoffset; +fixed_t *spritetopoffset; + +lighttable_t *colormaps; + + +/* +============================================================================== + + MAPTEXTURE_T CACHING + +when a texture is first needed, it counts the number of composite columns +required in the texture and allocates space for a column directory and any +new columns. The directory will simply point inside other patches if there +is only one patch in a given column, but any columns with multiple patches +will have new column_ts generated. + +============================================================================== +*/ + +/* +=================== += += R_DrawColumnInCache += += Clip and draw a column from a patch into a cached post += +=================== +*/ + +void R_DrawColumnInCache(column_t * patch, byte * cache, int originy, + int cacheheight) +{ + int count, position; + byte *source; + + while (patch->topdelta != 0xff) + { + source = (byte *) patch + 3; + count = patch->length; + position = originy + patch->topdelta; + if (position < 0) + { + count += position; + position = 0; + } + if (position + count > cacheheight) + count = cacheheight - position; + if (count > 0) + memcpy(cache + position, source, count); + + patch = (column_t *) ((byte *) patch + patch->length + 4); + } +} + + +/* +=================== += += R_GenerateComposite += +=================== +*/ + +void R_GenerateComposite(int texnum) +{ + byte *block; + texture_t *texture; + texpatch_t *patch; + patch_t *realpatch; + int x, x1, x2; + int i; + column_t *patchcol; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + block = Z_Malloc(texturecompositesize[texnum], PU_STATIC, + &texturecomposite[texnum]); + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + +// +// composite the columns together +// + for (i = 0, patch = texture->patches; i < texture->patchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1 < 0) + x = 0; + else + x = x1; + if (x2 > texture->width) + x2 = texture->width; + + for (; x < x2; x++) + { + if (collump[x] >= 0) + continue; // column does not have multiple patches + patchcol = (column_t *) ((byte *) realpatch + + LONG(realpatch->columnofs[x - x1])); + R_DrawColumnInCache(patchcol, block + colofs[x], patch->originy, + texture->height); + } + + } + +// now that the texture has been built, it is purgable + Z_ChangeTag(block, PU_CACHE); +} + + +/* +=================== += += R_GenerateLookup += +=================== +*/ + +void R_GenerateLookup(int texnum) +{ + texture_t *texture; + byte *patchcount; // [texture->width] + texpatch_t *patch; + patch_t *realpatch; + int x, x1, x2; + int i; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + + texturecomposite[texnum] = 0; // composited not created yet + texturecompositesize[texnum] = 0; + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + +// +// count the number of columns that are covered by more than one patch +// fill in the lump / offset, so columns with only a single patch are +// all done +// + patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); + memset(patchcount, 0, texture->width); + for (i = 0, patch = texture->patches; i < texture->patchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + if (x1 < 0) + x = 0; + else + x = x1; + if (x2 > texture->width) + x2 = texture->width; + for (; x < x2; x++) + { + patchcount[x]++; + collump[x] = patch->patch; + colofs[x] = LONG(realpatch->columnofs[x - x1]) + 3; + } + } + + for (x = 0; x < texture->width; x++) + { + if (!patchcount[x]) + { + ST_Message("R_GenerateLookup: column without a patch (%s)\n", + texture->name); + return; + } +// I_Error ("R_GenerateLookup: column without a patch"); + if (patchcount[x] > 1) + { + collump[x] = -1; // use the cached block + colofs[x] = texturecompositesize[texnum]; + if (texturecompositesize[texnum] > 0x10000 - texture->height) + I_Error("R_GenerateLookup: texture %i is >64k", texnum); + texturecompositesize[texnum] += texture->height; + } + } + + Z_Free(patchcount); +} + + +/* +================ += += R_GetColumn += +================ +*/ + +byte *R_GetColumn(int tex, int col) +{ + int lump, ofs; + + col &= texturewidthmask[tex]; + lump = texturecolumnlump[tex][col]; + ofs = texturecolumnofs[tex][col]; + if (lump > 0) + return (byte *) W_CacheLumpNum(lump, PU_CACHE) + ofs; + if (!texturecomposite[tex]) + R_GenerateComposite(tex); + return texturecomposite[tex] + ofs; +} + + +/* +================== += += R_InitTextures += += Initializes the texture list with the textures from the world map += +================== +*/ + +void R_InitTextures(void) +{ + maptexture_t *mtexture; + texture_t *texture; + mappatch_t *mpatch; + texpatch_t *patch; + int i, j; + int *maptex, *maptex2, *maptex1; + char name[9], *names, *name_p; + int *patchlookup; + int nummappatches; + int offset, maxoff, maxoff2; + int numtextures1, numtextures2; + int *directory; + +// +// load the patch names from pnames.lmp +// + names = W_CacheLumpName("PNAMES", PU_STATIC); + nummappatches = LONG(*((int *) names)); + name_p = names + 4; + patchlookup = Z_Malloc(nummappatches * sizeof(*patchlookup), PU_STATIC, NULL); + for (i = 0; i < nummappatches; i++) + { + M_StringCopy(name, name_p + i * 8, sizeof(name)); + patchlookup[i] = W_CheckNumForName(name); + } + W_ReleaseLumpName("PNAMES"); + +// +// load the map texture definitions from textures.lmp +// + maptex = maptex1 = W_CacheLumpName("TEXTURE1", PU_STATIC); + numtextures1 = LONG(*maptex); + maxoff = W_LumpLength(W_GetNumForName("TEXTURE1")); + directory = maptex + 1; + + if (W_CheckNumForName("TEXTURE2") != -1) + { + maptex2 = W_CacheLumpName("TEXTURE2", PU_STATIC); + numtextures2 = LONG(*maptex2); + maxoff2 = W_LumpLength(W_GetNumForName("TEXTURE2")); + } + else + { + maptex2 = NULL; + numtextures2 = 0; + maxoff2 = 0; + } + numtextures = numtextures1 + numtextures2; + + textures = Z_Malloc(numtextures * sizeof(texture_t *), PU_STATIC, 0); + texturecolumnlump = Z_Malloc(numtextures * sizeof(short *), PU_STATIC, 0); + texturecolumnofs = Z_Malloc(numtextures * sizeof(short *), PU_STATIC, 0); + texturecomposite = Z_Malloc(numtextures * sizeof(byte *), PU_STATIC, 0); + texturecompositesize = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); + texturewidthmask = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); + textureheight = Z_Malloc(numtextures * sizeof(fixed_t), PU_STATIC, 0); + + for (i = 0; i < numtextures; i++, directory++) + { + if (i == numtextures1) + { // start looking in second texture file + maptex = maptex2; + maxoff = maxoff2; + directory = maptex + 1; + } + + offset = LONG(*directory); + if (offset > maxoff) + I_Error("R_InitTextures: bad texture directory"); + mtexture = (maptexture_t *) ((byte *) maptex + offset); + texture = textures[i] = Z_Malloc(sizeof(texture_t) + + + sizeof(texpatch_t) * + (SHORT(mtexture->patchcount) - 1), + PU_STATIC, 0); + texture->width = SHORT(mtexture->width); + texture->height = SHORT(mtexture->height); + texture->patchcount = SHORT(mtexture->patchcount); + memcpy(texture->name, mtexture->name, sizeof(texture->name)); + mpatch = &mtexture->patches[0]; + patch = &texture->patches[0]; + for (j = 0; j < texture->patchcount; j++, mpatch++, patch++) + { + patch->originx = SHORT(mpatch->originx); + patch->originy = SHORT(mpatch->originy); + patch->patch = patchlookup[SHORT(mpatch->patch)]; + if (patch->patch == -1) + I_Error("R_InitTextures: Missing patch in texture %s", + texture->name); + } + texturecolumnlump[i] = Z_Malloc(texture->width * sizeof(short), PU_STATIC, 0); + texturecolumnofs[i] = Z_Malloc(texture->width * sizeof(short), PU_STATIC, 0); + j = 1; + while (j * 2 <= texture->width) + j <<= 1; + texturewidthmask[i] = j - 1; + textureheight[i] = texture->height << FRACBITS; + } + + Z_Free(patchlookup); + + W_ReleaseLumpName("TEXTURE1"); + if (maptex2) + W_ReleaseLumpName("TEXTURE2"); + +// +// precalculate whatever possible +// + for (i = 0; i < numtextures; i++) + { + R_GenerateLookup(i); + if (!(i & 31)) + ST_Progress(); + } + +// +// translation table for global animation +// + texturetranslation = Z_Malloc((numtextures + 1) * sizeof(int), PU_STATIC, 0); + for (i = 0; i < numtextures; i++) + texturetranslation[i] = i; +} + + +/* +================ += += R_InitFlats += +================= +*/ + +void R_InitFlats(void) +{ + int i; + + firstflat = W_GetNumForName("F_START") + 1; + lastflat = W_GetNumForName("F_END") - 1; + numflats = lastflat - firstflat + 1; + +// translation table for global animation + flattranslation = Z_Malloc((numflats + 1) * sizeof(int), PU_STATIC, 0); + for (i = 0; i < numflats; i++) + flattranslation[i] = i; +} + + +/* +================ += += R_InitSpriteLumps += += Finds the width and hoffset of all sprites in the wad, so the sprite doesn't += need to be cached just for the header during rendering +================= +*/ + +void R_InitSpriteLumps(void) +{ + int i; + patch_t *patch; + + firstspritelump = W_GetNumForName("S_START") + 1; + lastspritelump = W_GetNumForName("S_END") - 1; + numspritelumps = lastspritelump - firstspritelump + 1; + spritewidth = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); + spriteoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); + spritetopoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); + + for (i = 0; i < numspritelumps; i++) + { + if (!(i & 127)) + ST_Progress(); + patch = W_CacheLumpNum(firstspritelump + i, PU_CACHE); + spritewidth[i] = SHORT(patch->width) << FRACBITS; + spriteoffset[i] = SHORT(patch->leftoffset) << FRACBITS; + spritetopoffset[i] = SHORT(patch->topoffset) << FRACBITS; + } +} + + +/* +================ += += R_InitColormaps += +================= +*/ + +void R_InitColormaps(void) +{ + int lump, length; +// +// load in the light tables +// 256 byte align tables +// + lump = W_GetNumForName("COLORMAP"); + length = W_LumpLength(lump); + colormaps = Z_Malloc(length, PU_STATIC, 0); + W_ReadLump(lump, colormaps); +} + + +/* +================ += += R_InitData += += Locates all the lumps that will be used by all views += Must be called after W_Init +================= +*/ + +void R_InitData(void) +{ + R_InitTextures(); + R_InitFlats(); + R_InitSpriteLumps(); + R_InitColormaps(); +} + +//============================================================================= + +/* +================ += += R_FlatNumForName += +================ +*/ + +int R_FlatNumForName(const char *name) +{ + int i; + char namet[9]; + + i = W_CheckNumForName(name); + if (i == -1) + { + namet[8] = 0; + memcpy(namet, name, 8); + I_Error("R_FlatNumForName: %s not found", namet); + } + return i - firstflat; +} + + +/* +================ += += R_CheckTextureNumForName += +================ +*/ + +int R_CheckTextureNumForName(const char *name) +{ + int i; + + if (name[0] == '-') // no texture marker + return 0; + + for (i = 0; i < numtextures; i++) + if (!strncasecmp(textures[i]->name, name, 8)) + return i; + + return -1; +} + + +/* +================ += += R_TextureNumForName += +================ +*/ + +int R_TextureNumForName(const char *name) +{ + int i; + //char namet[9]; + + i = R_CheckTextureNumForName(name); + if (i == -1) + I_Error("R_TextureNumForName: %s not found", name); + + return i; +} + + +/* +================= += += R_PrecacheLevel += += Preloads all relevent graphics for the level +================= +*/ + +int flatmemory, texturememory, spritememory; + +void R_PrecacheLevel(void) +{ + char *flatpresent; + char *texturepresent; + char *spritepresent; + int i, j, k, lump; + texture_t *texture; + thinker_t *th; + spriteframe_t *sf; + + if (demoplayback) + return; + +// +// precache flats +// + flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); + memset(flatpresent, 0, numflats); + for (i = 0; i < numsectors; i++) + { + flatpresent[sectors[i].floorpic] = 1; + flatpresent[sectors[i].ceilingpic] = 1; + } + + flatmemory = 0; + for (i = 0; i < numflats; i++) + if (flatpresent[i]) + { + lump = firstflat + i; + flatmemory += lumpinfo[lump]->size; + W_CacheLumpNum(lump, PU_CACHE); + } + + Z_Free(flatpresent); + +// +// precache textures +// + texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); + memset(texturepresent, 0, numtextures); + + for (i = 0; i < numsides; i++) + { + texturepresent[sides[i].toptexture] = 1; + texturepresent[sides[i].midtexture] = 1; + texturepresent[sides[i].bottomtexture] = 1; + } + + texturepresent[Sky1Texture] = 1; + texturepresent[Sky2Texture] = 1; + + texturememory = 0; + for (i = 0; i < numtextures; i++) + { + if (!texturepresent[i]) + continue; + texture = textures[i]; + for (j = 0; j < texture->patchcount; j++) + { + lump = texture->patches[j].patch; + texturememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump, PU_CACHE); + } + } + + Z_Free(texturepresent); + +// +// precache sprites +// + spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); + memset(spritepresent, 0, numsprites); + + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function == P_MobjThinker) + spritepresent[((mobj_t *) th)->sprite] = 1; + } + + spritememory = 0; + for (i = 0; i < numsprites; i++) + { + if (!spritepresent[i]) + continue; + for (j = 0; j < sprites[i].numframes; j++) + { + sf = &sprites[i].spriteframes[j]; + for (k = 0; k < 8; k++) + { + lump = firstspritelump + sf->lump[k]; + spritememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump, PU_CACHE); + } + } + } + + Z_Free(spritepresent); +} diff --git a/games/NXDoom/src/hexen/r_draw.c b/games/NXDoom/src/hexen/r_draw.c new file mode 100644 index 00000000000..13a0421b498 --- /dev/null +++ b/games/NXDoom/src/hexen/r_draw.c @@ -0,0 +1,558 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "i_video.h" +#include "r_local.h" +#include "v_video.h" + +/* + +All drawing to the view buffer is accomplished in this file. The other refresh +files only know about ccordinates, not the architecture of the frame buffer. + +*/ + +byte *viewimage; +int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; +byte *ylookup[MAXHEIGHT]; +int columnofs[MAXWIDTH]; +//byte translations[3][256]; // color tables for different players + +/* +================== += += R_DrawColumn += += Source is the top of the column to scale += +================== +*/ + +lighttable_t *dc_colormap; +int dc_x; +int dc_yl; +int dc_yh; +fixed_t dc_iscale; +fixed_t dc_texturemid; +byte *dc_source; // first pixel in a column (possibly virtual) + +int dccount; // just for profiling + +void R_DrawColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +void R_DrawColumnLow(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +// dccount++; +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +void R_DrawTLColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + if (!dc_yl) + dc_yl = 1; + if (dc_yh == viewheight - 1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = tinttable[*dest + + (dc_colormap[dc_source[(frac >> FRACBITS) & 127]] << + 8)]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +//============================================================================ +// +// R_DrawAltTLColumn +// +//============================================================================ + +void R_DrawAltTLColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + if (!dc_yl) + dc_yl = 1; + if (dc_yh == viewheight - 1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawAltTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = tinttable[((*dest) << 8) + + dc_colormap[dc_source[(frac >> FRACBITS) & 127]]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +/* +======================== += += R_DrawTranslatedColumn += +======================== +*/ + +byte *dc_translation; +byte *translationtables; + +void R_DrawTranslatedColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +//============================================================================ +// +// R_DrawTranslatedTLColumn +// +//============================================================================ + +void R_DrawTranslatedTLColumn(void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do + { + *dest = tinttable[((*dest) << 8) + + + dc_colormap[dc_translation + [dc_source[frac >> FRACBITS]]]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +//============================================================================ +// +// R_DrawTranslatedAltTLColumn +// +//============================================================================ + +/* +void R_DrawTranslatedAltTLColumn (void) +{ + int count; + byte *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + do + { + *dest = tinttable[*dest + +(dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8)]; + dest += SCREENWIDTH; + frac += fracstep; + } while (count--); +} +*/ + +//-------------------------------------------------------------------------- +// +// PROC R_InitTranslationTables +// +//-------------------------------------------------------------------------- + +void R_InitTranslationTables(void) +{ + int i; + byte *transLump; + int lumpnum; + + V_LoadTintTable(); + + // Allocate translation tables + translationtables = Z_Malloc(256 * 3 * (maxplayers - 1), PU_STATIC, 0); + + for (i = 0; i < 3 * (maxplayers - 1); i++) + { + lumpnum = W_GetNumForName("trantbl0") + i; + transLump = W_CacheLumpNum(lumpnum, PU_STATIC); + memcpy(translationtables + i * 256, transLump, 256); + W_ReleaseLumpNum(lumpnum); + } +} + +/* +================ += += R_DrawSpan += +================ +*/ + +int ds_y; +int ds_x1; +int ds_x2; +lighttable_t *ds_colormap; +fixed_t ds_xfrac; +fixed_t ds_yfrac; +fixed_t ds_xstep; +fixed_t ds_ystep; +byte *ds_source; // start of a 64*64 tile image + +int dscount; // just for profiling + +void R_DrawSpan(void) +{ + fixed_t xfrac, yfrac; + byte *dest; + int count, spot; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH + || (unsigned) ds_y > SCREENHEIGHT) + I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); +// dscount++; +#endif + + xfrac = ds_xfrac; + yfrac = ds_yfrac; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1; + do + { + spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); + *dest++ = ds_colormap[ds_source[spot]]; + xfrac += ds_xstep; + yfrac += ds_ystep; + } + while (count--); +} + +void R_DrawSpanLow(void) +{ + fixed_t xfrac, yfrac; + byte *dest; + int count, spot; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH + || (unsigned) ds_y > SCREENHEIGHT) + I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); +// dscount++; +#endif + + xfrac = ds_xfrac; + yfrac = ds_yfrac; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1; + do + { + spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); + *dest++ = ds_colormap[ds_source[spot]]; + xfrac += ds_xstep; + yfrac += ds_ystep; + } + while (count--); +} + + + +/* +================ += += R_InitBuffer += +================= +*/ + +void R_InitBuffer(int width, int height) +{ + int i; + + viewwindowx = (SCREENWIDTH - width) >> 1; + for (i = 0; i < width; i++) + columnofs[i] = viewwindowx + i; + if (width == SCREENWIDTH) + viewwindowy = 0; + else + viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1; + for (i = 0; i < height; i++) + ylookup[i] = I_VideoBuffer + (i + viewwindowy) * SCREENWIDTH; +} + + +/* +================== += += R_DrawViewBorder += += Draws the border around the view for different size windows +================== +*/ + +boolean BorderNeedRefresh; + +void R_DrawViewBorder(void) +{ + byte *src, *dest; + int x, y; + + if (scaledviewwidth == SCREENWIDTH) + return; + + src = W_CacheLumpName("F_022", PU_CACHE); + dest = I_VideoBuffer; + + for (y = 0; y < SCREENHEIGHT - SBARHEIGHT; y++) + { + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } + for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) + { + V_DrawPatch(x, viewwindowy - 4, W_CacheLumpName("bordt", PU_CACHE)); + V_DrawPatch(x, viewwindowy + viewheight, W_CacheLumpName("bordb", + PU_CACHE)); + } + for (y = viewwindowy; y < viewwindowy + viewheight; y += 16) + { + V_DrawPatch(viewwindowx - 4, y, W_CacheLumpName("bordl", PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, y, W_CacheLumpName("bordr", + PU_CACHE)); + } + V_DrawPatch(viewwindowx - 4, viewwindowy - 4, W_CacheLumpName("bordtl", + PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, + W_CacheLumpName("bordtr", PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy + viewheight, + W_CacheLumpName("bordbr", PU_CACHE)); + V_DrawPatch(viewwindowx - 4, viewwindowy + viewheight, + W_CacheLumpName("bordbl", PU_CACHE)); +} + +/* +================== += += R_DrawTopBorder += += Draws the top border around the view for different size windows +================== +*/ + +boolean BorderTopRefresh; + +void R_DrawTopBorder(void) +{ + byte *src, *dest; + int x, y; + + if (scaledviewwidth == SCREENWIDTH) + return; + +/* if(gamemode == shareware) + { + src = W_CacheLumpName ("FLOOR04", PU_CACHE); + } + else + { + src = W_CacheLumpName ("FLAT513", PU_CACHE); + } +*/ + src = W_CacheLumpName("F_022", PU_CACHE); + dest = I_VideoBuffer; + + for (y = 0; y < 34; y++) + { + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } + if (viewwindowy < 35) + { + for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) + { + V_DrawPatch(x, viewwindowy - 4, + W_CacheLumpName("bordt", PU_CACHE)); + } + V_DrawPatch(viewwindowx - 4, viewwindowy, W_CacheLumpName("bordl", + PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy, + W_CacheLumpName("bordr", PU_CACHE)); + V_DrawPatch(viewwindowx - 4, viewwindowy + 16, + W_CacheLumpName("bordl", PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy + 16, + W_CacheLumpName("bordr", PU_CACHE)); + + V_DrawPatch(viewwindowx - 4, viewwindowy - 4, + W_CacheLumpName("bordtl", PU_CACHE)); + V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, + W_CacheLumpName("bordtr", PU_CACHE)); + } +} diff --git a/games/NXDoom/src/hexen/r_local.h b/games/NXDoom/src/hexen/r_local.h new file mode 100644 index 00000000000..e9cb26ce03d --- /dev/null +++ b/games/NXDoom/src/hexen/r_local.h @@ -0,0 +1,554 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __R_LOCAL__ +#define __R_LOCAL__ + +#include "i_video.h" + +#define ANGLETOSKYSHIFT 22 // sky map is 256*128*4 maps + +#define BASEYCENTER 100 + +#define MAXWIDTH 1120 +#define MAXHEIGHT 832 + +#define PI 3.141592657 + +#define CENTERY (SCREENHEIGHT/2) + +#define MINZ (FRACUNIT*4) + +#define FIELDOFVIEW 2048 // fineangles in the SCREENWIDTH wide window + +// +// lighting constants +// +#define LIGHTLEVELS 16 +#define LIGHTSEGSHIFT 4 +#define MAXLIGHTSCALE 48 +#define LIGHTSCALESHIFT 12 +#define MAXLIGHTZ 128 +#define LIGHTZSHIFT 20 +#define NUMCOLORMAPS 32 // number of diminishing +#define INVERSECOLORMAP 32 + +/* +============================================================================== + + INTERNAL MAP TYPES + +============================================================================== +*/ + +//================ used by play and refresh + +typedef struct +{ + fixed_t x, y; +} vertex_t; + +struct line_s; + +typedef struct +{ + fixed_t floorheight, ceilingheight; + short floorpic, ceilingpic; + short lightlevel; + short special, tag; + + int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 + mobj_t *soundtarget; // thing that made a sound (or null) + seqtype_t seqType; // stone, metal, heavy, etc... + + int blockbox[4]; // mapblock bounding box for height changes + degenmobj_t soundorg; // for any sounds played by the sector + int validcount; // if == validcount, already checked + mobj_t *thinglist; // list of mobjs in sector + void *specialdata; // thinker_t for reversable actions + int linecount; + struct line_s **lines; // [linecount] size +} sector_t; + +typedef struct +{ + fixed_t textureoffset; // add this to the calculated texture col + fixed_t rowoffset; // add this to the calculated texture top + short toptexture, bottomtexture, midtexture; + sector_t *sector; +} side_t; + +typedef enum +{ + ST_HORIZONTAL, + ST_VERTICAL, + ST_POSITIVE, + ST_NEGATIVE +} slopetype_t; + +/* +typedef struct line_s +{ + vertex_t *v1, *v2; + fixed_t dx,dy; // v2 - v1 for side checking + short flags; + short special, tag; + short sidenum[2]; // sidenum[1] will be -1 if one sided + fixed_t bbox[4]; + slopetype_t slopetype; // to aid move clipping + sector_t *frontsector, *backsector; + int validcount; // if == validcount, already checked + void *specialdata; // thinker_t for reversable actions +} line_t; +*/ + +typedef struct line_s +{ + vertex_t *v1; + vertex_t *v2; + fixed_t dx; + fixed_t dy; + short flags; + byte special; + byte arg1; + byte arg2; + byte arg3; + byte arg4; + byte arg5; + short sidenum[2]; + fixed_t bbox[4]; + slopetype_t slopetype; + sector_t *frontsector; + sector_t *backsector; + int validcount; + void *specialdata; +} line_t; + +typedef struct +{ + vertex_t *v1, *v2; + fixed_t offset; + angle_t angle; + side_t *sidedef; + line_t *linedef; + sector_t *frontsector; + sector_t *backsector; // NULL for one sided lines +} seg_t; + +// ===== Polyobj data ===== +typedef struct +{ + int numsegs; + seg_t **segs; + degenmobj_t startSpot; + vertex_t *originalPts; // used as the base for the rotations + vertex_t *prevPts; // use to restore the old point values + angle_t angle; + int tag; // reference tag assigned in HereticEd + int bbox[4]; + int validcount; + boolean crush; // should the polyobj attempt to crush mobjs? + int seqType; + fixed_t size; // polyobj size (area of POLY_AREAUNIT == size of FRACUNIT) + void *specialdata; // pointer a thinker, if the poly is moving +} polyobj_t; + +typedef struct polyblock_s +{ + polyobj_t *polyobj; + struct polyblock_s *prev; + struct polyblock_s *next; +} polyblock_t; + +typedef struct subsector_s +{ + sector_t *sector; + short numlines; + short firstline; + polyobj_t *poly; +} subsector_t; + +typedef struct +{ + fixed_t x, y, dx, dy; // partition line + fixed_t bbox[2][4]; // bounding box for each child + unsigned short children[2]; // if NF_SUBSECTOR its a subsector +} node_t; + + +/* +============================================================================== + + OTHER TYPES + +============================================================================== +*/ + +typedef byte lighttable_t; // this could be wider for >8 bit display + +#define MAXVISPLANES 160 +#define MAXOPENINGS SCREENWIDTH*64 + +typedef struct +{ + fixed_t height; + int picnum; + int lightlevel; + int special; + int minx, maxx; + byte pad1; // leave pads for [minx-1]/[maxx+1] + byte top[SCREENWIDTH]; + byte pad2; + byte pad3; + byte bottom[SCREENWIDTH]; + byte pad4; +} visplane_t; + +typedef struct drawseg_s +{ + seg_t *curline; + int x1, x2; + fixed_t scale1, scale2, scalestep; + int silhouette; // 0=none, 1=bottom, 2=top, 3=both + fixed_t bsilheight; // don't clip sprites above this + fixed_t tsilheight; // don't clip sprites below this +// pointers to lists for sprite clipping + short *sprtopclip; // adjusted so [x1] is first value + short *sprbottomclip; // adjusted so [x1] is first value + short *maskedtexturecol; // adjusted so [x1] is first value +} drawseg_t; + +#define SIL_NONE 0 +#define SIL_BOTTOM 1 +#define SIL_TOP 2 +#define SIL_BOTH 3 + +#define MAXDRAWSEGS 256 + +// A vissprite_t is a thing that will be drawn during a refresh +typedef struct vissprite_s +{ + struct vissprite_s *prev, *next; + int x1, x2; + fixed_t gx, gy; // for line side calculation + fixed_t gz, gzt; // global bottom / top for silhouette clipping + fixed_t startfrac; // horizontal position of x1 + fixed_t scale; + fixed_t xiscale; // negative if flipped + fixed_t texturemid; + int patch; + lighttable_t *colormap; + int mobjflags; // for color translation and shadow draw + boolean psprite; // true if psprite + int class; // player class (used in translation) + fixed_t floorclip; +} vissprite_t; + + +extern visplane_t *floorplane, *ceilingplane; + +// Sprites are patches with a special naming convention so they can be +// recognized by R_InitSprites. The sprite and frame specified by a +// thing_t is range checked at run time. +// a sprite is a patch_t that is assumed to represent a three dimensional +// object and may have multiple rotations pre drawn. Horizontal flipping +// is used to save space. Some sprites will only have one picture used +// for all views. + +typedef struct +{ + boolean rotate; // if false use 0 for any position + short lump[8]; // lump to use for view angles 0-7 + byte flip[8]; // flip (1 = flip) to use for view angles 0-7 +} spriteframe_t; + +typedef struct +{ + int numframes; + spriteframe_t *spriteframes; +} spritedef_t; + +extern spritedef_t *sprites; +extern int numsprites; + +//============================================================================= + +extern int numvertexes; +extern vertex_t *vertexes; + +extern int numsegs; +extern seg_t *segs; + +extern int numsectors; +extern sector_t *sectors; + +extern int numsubsectors; +extern subsector_t *subsectors; + +extern int numnodes; +extern node_t *nodes; + +extern int numlines; +extern line_t *lines; + +extern int numsides; +extern side_t *sides; + + + +extern fixed_t viewx, viewy, viewz; +extern angle_t viewangle; +extern player_t *viewplayer; + + +extern angle_t clipangle; + +extern int viewangletox[FINEANGLES / 2]; +extern angle_t xtoviewangle[SCREENWIDTH + 1]; + +extern fixed_t rw_distance; +extern angle_t rw_normalangle; + +// +// R_main.c +// +extern int screenblocks; +extern int viewwidth, viewheight, viewwindowx, viewwindowy; +extern int scaledviewwidth; +extern int centerx, centery; +extern int flyheight; +extern fixed_t centerxfrac; +extern fixed_t centeryfrac; +extern fixed_t projection; + +extern int validcount; + +extern int sscount, linecount, loopcount; +extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +extern lighttable_t *scalelightfixed[MAXLIGHTSCALE]; +extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; + +extern int extralight; +extern lighttable_t *fixedcolormap; + +extern fixed_t viewcos, viewsin; + +extern int detailshift; // 0 = high, 1 = low + +extern void (*colfunc) (void); +extern void (*basecolfunc) (void); +extern void (*tlcolfunc) (void); +extern void (*spanfunc) (void); + +int R_PointOnSide(fixed_t x, fixed_t y, node_t * node); +int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line); +angle_t R_PointToAngle(fixed_t x, fixed_t y); +angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); +fixed_t R_PointToDist(fixed_t x, fixed_t y); +fixed_t R_ScaleFromGlobalAngle(angle_t visangle); +subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); +//void R_AddPointToBox (int x, int y, fixed_t *box); + + +// +// R_bsp.c +// +extern seg_t *curline; +extern side_t *sidedef; +extern line_t *linedef; +extern sector_t *frontsector, *backsector; + +extern int rw_x; +extern int rw_stopx; + +extern boolean segtextured; +extern boolean markfloor; // false if the back side is the same plane +extern boolean markceiling; +extern boolean skymap; + +extern drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; + +extern lighttable_t **hscalelight, **vscalelight, **dscalelight; + +typedef void (*drawfunc_t) (int start, int stop); +void R_ClearClipSegs(void); + +void R_ClearDrawSegs(void); +void R_InitSkyMap(void); +void R_RenderBSPNode(int bspnum); + +// +// R_segs.c +// +extern int rw_angle1; // angle to line origin +extern int TransTextureStart; +extern int TransTextureEnd; +extern lighttable_t **walllights; + + +void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2); + +// +// R_plane.c +// +typedef void (*planefunction_t) (int top, int bottom); +extern planefunction_t floorfunc, ceilingfunc; + +extern fixed_t Sky1ColumnOffset; +extern fixed_t Sky2ColumnOffset; +extern int skyflatnum; +extern boolean DoubleSky; + +extern short openings[MAXOPENINGS], *lastopening; + +extern short floorclip[SCREENWIDTH]; +extern short ceilingclip[SCREENWIDTH]; + +extern fixed_t yslope[SCREENHEIGHT]; +extern fixed_t distscale[SCREENWIDTH]; + +void R_InitPlanes(void); +void R_ClearPlanes(void); +void R_MapPlane(int y, int x1, int x2); +void R_MakeSpans(int x, int t1, int b1, int t2, int b2); +void R_DrawPlanes(void); + +visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel, + int special); +visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop); + +void R_InitSky(int map); + + +// +// R_debug.m +// +extern int drawbsp; + +void RD_OpenMapWindow(void); +void RD_ClearMapWindow(void); +void RD_DisplayLine(int x1, int y1, int x2, int y2, float gray); +void RD_DrawNodeLine(node_t * node); +void RD_DrawLineCheck(seg_t * line); +void RD_DrawLine(seg_t * line); +void RD_DrawBBox(fixed_t * bbox); + + +// +// R_data.c +// +extern fixed_t *textureheight; // needed for texture pegging +extern fixed_t *spritewidth; // needed for pre rendering (fracs) +extern fixed_t *spriteoffset; +extern fixed_t *spritetopoffset; +extern lighttable_t *colormaps; +extern int firstflat; +extern int numflats; + +extern int *flattranslation; // for global animation +extern int *texturetranslation; // for global animation + +extern int firstspritelump, lastspritelump, numspritelumps; +extern boolean LevelUseFullBright; + +byte *R_GetColumn(int tex, int col); +void R_InitData(void); +void R_PrecacheLevel(void); + + +// +// R_things.c +// +#define MAXVISSPRITES 192 + +extern vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; +extern vissprite_t vsprsortedhead; + +// constant arrays used for psprite clipping and initializing clipping +extern short negonearray[SCREENWIDTH]; +extern short screenheightarray[SCREENWIDTH]; + +// vars for R_DrawMaskedColumn +extern short *mfloorclip; +extern short *mceilingclip; +extern fixed_t spryscale; +extern fixed_t sprtopscreen; +extern fixed_t sprbotscreen; + +extern fixed_t pspritescale, pspriteiscale; + + +void R_DrawMaskedColumn(column_t * column, signed int baseclip); + + +void R_SortVisSprites(void); + +void R_AddSprites(sector_t * sec); +void R_AddPSprites(void); +void R_DrawSprites(void); +void R_InitSprites(const char **namelist); +void R_ClearSprites(void); +void R_DrawMasked(void); +void R_ClipVisSprite(vissprite_t * vis, int xl, int xh); + +//============================================================================= +// +// R_draw.c +// +//============================================================================= + +extern lighttable_t *dc_colormap; +extern int dc_x; +extern int dc_yl; +extern int dc_yh; +extern fixed_t dc_iscale; +extern fixed_t dc_texturemid; +extern byte *dc_source; // first pixel in a column +extern byte *ylookup[MAXHEIGHT]; +extern int columnofs[MAXWIDTH]; + + +void R_DrawColumn(void); +void R_DrawColumnLow(void); +void R_DrawTLColumn(void); +void R_DrawTLColumnLow(void); +void R_DrawTranslatedColumn(void); +void R_DrawTranslatedTLColumn(void); +void R_DrawTranslatedColumnLow(void); +void R_DrawAltTLColumn(void); +//void R_DrawTranslatedAltTLColumn(void); + +extern int ds_y; +extern int ds_x1; +extern int ds_x2; +extern lighttable_t *ds_colormap; +extern fixed_t ds_xfrac; +extern fixed_t ds_yfrac; +extern fixed_t ds_xstep; +extern fixed_t ds_ystep; +extern byte *ds_source; // start of a 64*64 tile image + +extern byte *translationtables; +extern byte *dc_translation; + +void R_DrawSpan(void); +void R_DrawSpanLow(void); + +void R_InitBuffer(int width, int height); +void R_InitTranslationTables(void); + +#endif // __R_LOCAL__ diff --git a/games/NXDoom/src/hexen/r_main.c b/games/NXDoom/src/hexen/r_main.c new file mode 100644 index 00000000000..3bbb4fce2f5 --- /dev/null +++ b/games/NXDoom/src/hexen/r_main.c @@ -0,0 +1,830 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include +#include "m_random.h" +#include "h2def.h" +#include "m_bbox.h" +#include "r_local.h" + +int viewangleoffset; + +// haleyjd: removed WATCOMC + +int validcount = 1; // increment every time a check is made + +lighttable_t *fixedcolormap; + +int centerx, centery; +fixed_t centerxfrac, centeryfrac; +fixed_t projection; + +int framecount; // just for profiling purposes + +int sscount, linecount, loopcount; + +fixed_t viewx, viewy, viewz; +angle_t viewangle; +fixed_t viewcos, viewsin; +player_t *viewplayer; + +int detailshift; // 0 = high, 1 = low + +// +// precalculated math tables +// +angle_t clipangle; + +// The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view +// angles to screen X coordinates, flattening the arc to a flat projection +// plane. There will be many angles mapped to the same X. +int viewangletox[FINEANGLES / 2]; + +// The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle +// that maps back to x ranges from clipangle to -clipangle +angle_t xtoviewangle[SCREENWIDTH + 1]; + +lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +lighttable_t *scalelightfixed[MAXLIGHTSCALE]; +lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; + +int extralight; // bumped light from gun blasts + +void (*colfunc) (void); +void (*basecolfunc) (void); +void (*tlcolfunc) (void); +void (*transcolfunc) (void); +void (*spanfunc) (void); + +/* +=================== += += R_AddPointToBox += +=================== +*/ + +/* +void R_AddPointToBox (int x, int y, fixed_t *box) +{ + if (x< box[BOXLEFT]) + box[BOXLEFT] = x; + if (x> box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y< box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + if (y> box[BOXTOP]) + box[BOXTOP] = y; +} +*/ + + +/* +=============================================================================== += += R_PointOnSide += += Returns side 0 (front) or 1 (back) +=============================================================================== +*/ + +int R_PointOnSide(fixed_t x, fixed_t y, node_t * node) +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!node->dx) + { + if (x <= node->x) + return node->dy > 0; + return node->dy < 0; + } + if (!node->dy) + { + if (y <= node->y) + return node->dx < 0; + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + +// try to quickly decide by looking at sign bits + if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) + { + if ((node->dy ^ dx) & 0x80000000) + return 1; // (left is negative) + return 0; + } + + left = FixedMul(node->dy >> FRACBITS, dx); + right = FixedMul(dy, node->dx >> FRACBITS); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line) +{ + fixed_t lx, ly; + fixed_t ldx, ldy; + fixed_t dx, dy; + fixed_t left, right; + + lx = line->v1->x; + ly = line->v1->y; + + ldx = line->v2->x - lx; + ldy = line->v2->y - ly; + + if (!ldx) + { + if (x <= lx) + return ldy > 0; + return ldy < 0; + } + if (!ldy) + { + if (y <= ly) + return ldx < 0; + return ldx > 0; + } + + dx = (x - lx); + dy = (y - ly); + +// try to quickly decide by looking at sign bits + if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) + { + if ((ldy ^ dx) & 0x80000000) + return 1; // (left is negative) + return 0; + } + + left = FixedMul(ldy >> FRACBITS, dx); + right = FixedMul(dy, ldx >> FRACBITS); + + if (right < left) + return 0; // front side + return 1; // back side +} + + +/* +=============================================================================== += += R_PointToAngle += +=============================================================================== +*/ + +#define DBITS (FRACBITS-SLOPEBITS) + +angle_t R_PointToAngle(fixed_t x, fixed_t y) +{ + x -= viewx; + y -= viewy; + if ((!x) && (!y)) + return 0; + if (x >= 0) + { // x >=0 + if (y >= 0) + { // y>= 0 + if (x > y) + return tantoangle[SlopeDiv(y, x)]; // octant 0 + else + return ANG90 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 1 + } + else + { // y<0 + y = -y; + if (x > y) + return -tantoangle[SlopeDiv(y, x)]; // octant 8 + else + return ANG270 + tantoangle[SlopeDiv(x, y)]; // octant 7 + } + } + else + { // x<0 + x = -x; + if (y >= 0) + { // y>= 0 + if (x > y) + return ANG180 - 1 - tantoangle[SlopeDiv(y, x)]; // octant 3 + else + return ANG90 + tantoangle[SlopeDiv(x, y)]; // octant 2 + } + else + { // y<0 + y = -y; + if (x > y) + return ANG180 + tantoangle[SlopeDiv(y, x)]; // octant 4 + else + return ANG270 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 5 + } + } + + return 0; +} + + +angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) +{ + viewx = x1; + viewy = y1; + return R_PointToAngle(x2, y2); +} + + +fixed_t R_PointToDist(fixed_t x, fixed_t y) +{ + int angle; + fixed_t dx, dy, temp; + fixed_t dist; + + dx = abs(x - viewx); + dy = abs(y - viewy); + + if (dy > dx) + { + temp = dx; + dx = dy; + dy = temp; + } + + angle = + (tantoangle[FixedDiv(dy, dx) >> DBITS] + ANG90) >> ANGLETOFINESHIFT; + + dist = FixedDiv(dx, finesine[angle]); // use as cosine + + return dist; +} + + + +/* +================= += += R_InitPointToAngle += +================= +*/ + +void R_InitPointToAngle(void) +{ +// now getting from tables.c +#if 0 + int i; + long t; + float f; +// +// slope (tangent) to angle lookup +// + for (i = 0; i <= SLOPERANGE; i++) + { + f = atan((float) i / SLOPERANGE) / (3.141592657 * 2); + t = 0xffffffff * f; + tantoangle[i] = t; + } +#endif +} + +//============================================================================= + +/* +================ += += R_ScaleFromGlobalAngle += += Returns the texture mapping scale for the current line at the given angle += rw_distance must be calculated first +================ +*/ + +fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +{ + fixed_t scale; + int anglea, angleb; + int sinea, sineb; + fixed_t num, den; + +#if 0 + { + fixed_t dist, z; + fixed_t sinv, cosv; + + sinv = finesine[(visangle - rw_normalangle) >> ANGLETOFINESHIFT]; + dist = FixedDiv(rw_distance, sinv); + cosv = finecosine[(viewangle - visangle) >> ANGLETOFINESHIFT]; + z = abs(FixedMul(dist, cosv)); + scale = FixedDiv(projection, z); + return scale; + } +#endif + + anglea = ANG90 + (visangle - viewangle); + angleb = ANG90 + (visangle - rw_normalangle); +// bothe sines are allways positive + sinea = finesine[anglea >> ANGLETOFINESHIFT]; + sineb = finesine[angleb >> ANGLETOFINESHIFT]; + num = FixedMul(projection, sineb) << detailshift; + den = FixedMul(rw_distance, sinea); + if (den > num >> 16) + { + scale = FixedDiv(num, den); + if (scale > 64 * FRACUNIT) + scale = 64 * FRACUNIT; + else if (scale < 256) + scale = 256; + } + else + scale = 64 * FRACUNIT; + + return scale; +} + + + +/* +================= += += R_InitTables += +================= +*/ + +void R_InitTables(void) +{ +// now getting from tables.c +#if 0 + int i; + float a, fv; + int t; + +// +// viewangle tangent table +// + for (i = 0; i < FINEANGLES / 2; i++) + { + a = (i - FINEANGLES / 4 + 0.5) * PI * 2 / FINEANGLES; + fv = FRACUNIT * tan(a); + t = fv; + finetangent[i] = t; + } + +// +// finesine table +// + for (i = 0; i < 5 * FINEANGLES / 4; i++) + { +// OPTIMIZE: mirror... + a = (i + 0.5) * PI * 2 / FINEANGLES; + t = FRACUNIT * sin(a); + finesine[i] = t; + } +#endif + +} + + +/* +================= += += R_InitTextureMapping += +================= +*/ + +void R_InitTextureMapping(void) +{ + int i; + int x; + int t; + fixed_t focallength; + + +// +// use tangent table to generate viewangletox +// viewangletox will give the next greatest x after the view angle +// + // calc focallength so FIELDOFVIEW angles covers SCREENWIDTH + focallength = + FixedDiv(centerxfrac, finetangent[FINEANGLES / 4 + FIELDOFVIEW / 2]); + + for (i = 0; i < FINEANGLES / 2; i++) + { + if (finetangent[i] > FRACUNIT * 2) + t = -1; + else if (finetangent[i] < -FRACUNIT * 2) + t = viewwidth + 1; + else + { + t = FixedMul(finetangent[i], focallength); + t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS; + if (t < -1) + t = -1; + else if (t > viewwidth + 1) + t = viewwidth + 1; + } + viewangletox[i] = t; + } + +// +// scan viewangletox[] to generate xtoviewangleangle[] +// +// xtoviewangle will give the smallest view angle that maps to x + for (x = 0; x <= viewwidth; x++) + { + i = 0; + while (viewangletox[i] > x) + i++; + xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90; + } + +// +// take out the fencepost cases from viewangletox +// + for (i = 0; i < FINEANGLES / 2; i++) + { + t = FixedMul(finetangent[i], focallength); + t = centerx - t; + if (viewangletox[i] == -1) + viewangletox[i] = 0; + else if (viewangletox[i] == viewwidth + 1) + viewangletox[i] = viewwidth; + } + + clipangle = xtoviewangle[0]; +} + +//============================================================================= + +/* +==================== += += R_InitLightTables += += Only inits the zlight table, because the scalelight table changes += with view size += +==================== +*/ + +#define DISTMAP 2 + +void R_InitLightTables(void) +{ + int i, j, level, startmap; + int scale; + +// +// Calculate the light levels to use for each level / distance combination +// + for (i = 0; i < LIGHTLEVELS; i++) + { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTZ; j++) + { + scale = + FixedDiv((SCREENWIDTH / 2 * FRACUNIT), + (j + 1) << LIGHTZSHIFT); + scale >>= LIGHTSCALESHIFT; + level = startmap - scale / DISTMAP; + if (level < 0) + level = 0; + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS - 1; + zlight[i][j] = colormaps + level * 256; + } + } +} + + +/* +============== += += R_SetViewSize += += Don't really change anything here, because i might be in the middle of += a refresh. The change will take effect next refresh. += +============== +*/ + +boolean setsizeneeded; +int setblocks, setdetail; + +void R_SetViewSize(int blocks, int detail) +{ + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; +} + +/* +============== += += R_ExecuteSetViewSize += +============== +*/ + +void R_ExecuteSetViewSize(void) +{ + fixed_t cosadj, dy; + int i, j, level, startmap; + + setsizeneeded = false; + + if (setblocks == 11) + { + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; + } + else + { + scaledviewwidth = setblocks * 32; + viewheight = (setblocks * 161 / 10); + } + + detailshift = setdetail; + viewwidth = scaledviewwidth >> detailshift; + + centery = viewheight / 2; + centerx = viewwidth / 2; + centerxfrac = centerx << FRACBITS; + centeryfrac = centery << FRACBITS; + projection = centerxfrac; + + if (!detailshift) + { + colfunc = basecolfunc = R_DrawColumn; + tlcolfunc = R_DrawTLColumn; + transcolfunc = R_DrawTranslatedColumn; + spanfunc = R_DrawSpan; + } + else + { + colfunc = basecolfunc = R_DrawColumnLow; + tlcolfunc = R_DrawTLColumn; + transcolfunc = R_DrawTranslatedColumn; + spanfunc = R_DrawSpanLow; + } + + R_InitBuffer(scaledviewwidth, viewheight); + + R_InitTextureMapping(); + +// +// psprite scales +// + pspritescale = FRACUNIT * viewwidth / SCREENWIDTH; + pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth; + +// +// thing clipping +// + for (i = 0; i < viewwidth; i++) + screenheightarray[i] = viewheight; + +// +// planes +// + for (i = 0; i < viewheight; i++) + { + dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; + dy = abs(dy); + yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, dy); + } + + for (i = 0; i < viewwidth; i++) + { + cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); + distscale[i] = FixedDiv(FRACUNIT, cosadj); + } + +// +// Calculate the light levels to use for each level / scale combination +// + for (i = 0; i < LIGHTLEVELS; i++) + { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTSCALE; j++) + { + level = + startmap - + j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP; + if (level < 0) + level = 0; + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS - 1; + scalelight[i][j] = colormaps + level * 256; + } + } + +// +// draw the border +// + R_DrawViewBorder(); // erase old menu stuff +} + + +/* +============== += += R_Init += +============== +*/ + +int detailLevel; +int screenblocks = 10; + +void R_Init(void) +{ + R_InitData(); + R_InitPointToAngle(); + R_InitTables(); + // viewwidth / viewheight / detailLevel are set by the defaults + R_SetViewSize(screenblocks, detailLevel); + R_InitPlanes(); + R_InitLightTables(); + R_InitSkyMap(); + R_InitTranslationTables(); + framecount = 0; +} + +/* +============== += += R_PointInSubsector += +============== +*/ + +subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) +{ + node_t *node; + int side, nodenum; + + if (!numnodes) // single subsector is a special case + return subsectors; + + nodenum = numnodes - 1; + + while (!(nodenum & NF_SUBSECTOR)) + { + node = &nodes[nodenum]; + side = R_PointOnSide(x, y, node); + nodenum = node->children[side]; + } + + return &subsectors[nodenum & ~NF_SUBSECTOR]; + +} + +//---------------------------------------------------------------------------- +// +// PROC R_SetupFrame +// +//---------------------------------------------------------------------------- + +void R_SetupFrame(player_t * player) +{ + int i; + int tableAngle; + int tempCentery; + int intensity; + + //drawbsp = 1; + viewplayer = player; + // haleyjd: removed WATCOMC + // haleyjd FIXME: viewangleoffset handling? + viewangle = player->mo->angle + viewangleoffset; + tableAngle = viewangle >> ANGLETOFINESHIFT; + viewx = player->mo->x; + viewy = player->mo->y; + + if (localQuakeHappening[displayplayer] && !paused) + { + intensity = localQuakeHappening[displayplayer]; + viewx += ((M_Random() % (intensity << 2)) + - (intensity << 1)) << FRACBITS; + viewy += ((M_Random() % (intensity << 2)) + - (intensity << 1)) << FRACBITS; + } + + extralight = player->extralight; + viewz = player->viewz; + + tempCentery = viewheight / 2 + (player->lookdir) * screenblocks / 10; + if (centery != tempCentery) + { + centery = tempCentery; + centeryfrac = centery << FRACBITS; + for (i = 0; i < viewheight; i++) + { + yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, + abs(((i - centery) << FRACBITS) + + FRACUNIT / 2)); + } + } + viewsin = finesine[tableAngle]; + viewcos = finecosine[tableAngle]; + sscount = 0; + if (player->fixedcolormap) + { + fixedcolormap = colormaps + player->fixedcolormap + * 256 * sizeof(lighttable_t); + walllights = scalelightfixed; + for (i = 0; i < MAXLIGHTSCALE; i++) + { + scalelightfixed[i] = fixedcolormap; + } + } + else + { + fixedcolormap = 0; + } + framecount++; + validcount++; + if (BorderNeedRefresh) + { + if (setblocks < 10) + { + R_DrawViewBorder(); + } + BorderNeedRefresh = false; + BorderTopRefresh = false; + UpdateState |= I_FULLSCRN; + } + if (BorderTopRefresh) + { + if (setblocks < 10) + { + R_DrawTopBorder(); + } + BorderTopRefresh = false; + UpdateState |= I_MESSAGES; + } + +#if 0 + { + static int frame; + memset(screen, frame, SCREENWIDTH * SCREENHEIGHT); + frame++; + } +#endif +} + +/* +============== += += R_RenderView += +============== +*/ + +void R_RenderPlayerView(player_t * player) +{ + R_SetupFrame(player); + R_ClearClipSegs(); + R_ClearDrawSegs(); + R_ClearPlanes(); + R_ClearSprites(); + NetUpdate(); // check for new console commands + + // Make displayed player invisible locally + if (localQuakeHappening[displayplayer] && gamestate == GS_LEVEL) + { + players[displayplayer].mo->flags2 |= MF2_DONTDRAW; + R_RenderBSPNode(numnodes - 1); // head node is the last node output + players[displayplayer].mo->flags2 &= ~MF2_DONTDRAW; + } + else + { + R_RenderBSPNode(numnodes - 1); // head node is the last node output + } + + NetUpdate(); // check for new console commands + R_DrawPlanes(); + NetUpdate(); // check for new console commands + R_DrawMasked(); + NetUpdate(); // check for new console commands +} diff --git a/games/NXDoom/src/hexen/r_plane.c b/games/NXDoom/src/hexen/r_plane.c new file mode 100644 index 00000000000..8acbcc43cb0 --- /dev/null +++ b/games/NXDoom/src/hexen/r_plane.c @@ -0,0 +1,579 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "i_system.h" +#include "r_local.h" +#include "p_spec.h" + + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +int Sky1Texture; +int Sky2Texture; +fixed_t Sky1ColumnOffset; +fixed_t Sky2ColumnOffset; +int skyflatnum; +int skytexturemid; +fixed_t skyiscale; +boolean DoubleSky; +planefunction_t floorfunc, ceilingfunc; + +// Opening +visplane_t visplanes[MAXVISPLANES], *lastvisplane; +visplane_t *floorplane, *ceilingplane; +short openings[MAXOPENINGS], *lastopening; + +// Clip values are the solid pixel bounding the range. +// floorclip start out SCREENHEIGHT +// ceilingclip starts out -1 +short floorclip[SCREENWIDTH]; +short ceilingclip[SCREENWIDTH]; + +// spanstart holds the start of a plane span, initialized to 0 +int spanstart[SCREENHEIGHT]; +int spanstop[SCREENHEIGHT]; + +// Texture mapping +lighttable_t **planezlight; +fixed_t planeheight; +fixed_t yslope[SCREENHEIGHT]; +fixed_t distscale[SCREENWIDTH]; +fixed_t basexscale, baseyscale; +fixed_t cachedheight[SCREENHEIGHT]; +fixed_t cacheddistance[SCREENHEIGHT]; +fixed_t cachedxstep[SCREENHEIGHT]; +fixed_t cachedystep[SCREENHEIGHT]; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// R_InitSky +// +// Called at level load. +// +//========================================================================== + +void R_InitSky(int map) +{ + Sky1Texture = P_GetMapSky1Texture(map); + Sky2Texture = P_GetMapSky2Texture(map); + Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map); + Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map); + Sky1ColumnOffset = 0; + Sky2ColumnOffset = 0; + DoubleSky = P_GetMapDoubleSky(map); +} + +//========================================================================== +// +// R_InitSkyMap +// +// Called whenever the view size changes. +// +//========================================================================== + +void R_InitSkyMap(void) +{ + skyflatnum = R_FlatNumForName("F_SKY"); + skytexturemid = 200 * FRACUNIT; + skyiscale = FRACUNIT; +} + +//========================================================================== +// +// R_InitPlanes +// +// Called at game startup. +// +//========================================================================== + +void R_InitPlanes(void) +{ +} + +//========================================================================== +// +// R_MapPlane +// +// Globals used: planeheight, ds_source, basexscale, baseyscale, +// viewx, viewy. +// +//========================================================================== + +void R_MapPlane(int y, int x1, int x2) +{ + angle_t angle; + fixed_t distance, length; + unsigned index; + +#ifdef RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned) y > viewheight) + { + I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); + } +#endif + + if (planeheight != cachedheight[y]) + { + cachedheight[y] = planeheight; + distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); + ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); + ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); + } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + length = FixedMul(distance, distscale[x1]); + angle = (viewangle + xtoviewangle[x1]) >> ANGLETOFINESHIFT; + ds_xfrac = viewx + FixedMul(finecosine[angle], length); + ds_yfrac = -viewy - FixedMul(finesine[angle], length); + + if (fixedcolormap) + { + ds_colormap = fixedcolormap; + } + else + { + index = distance >> LIGHTZSHIFT; + if (index >= MAXLIGHTZ) + { + index = MAXLIGHTZ - 1; + } + ds_colormap = planezlight[index]; + } + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + spanfunc(); // High or low detail +} + +//========================================================================== +// +// R_ClearPlanes +// +// Called at the beginning of each frame. +// +//========================================================================== + +void R_ClearPlanes(void) +{ + int i; + angle_t angle; + + // Opening / clipping determination + for (i = 0; i < viewwidth; i++) + { + floorclip[i] = viewheight; + ceilingclip[i] = -1; + } + + lastvisplane = visplanes; + lastopening = openings; + + // Texture calculation + memset(cachedheight, 0, sizeof(cachedheight)); + angle = (viewangle - ANG90) >> ANGLETOFINESHIFT; // left to right mapping + // Scale will be unit scale at SCREENWIDTH/2 distance + basexscale = FixedDiv(finecosine[angle], centerxfrac); + baseyscale = -FixedDiv(finesine[angle], centerxfrac); +} + +//========================================================================== +// +// R_FindPlane +// +//========================================================================== + +visplane_t *R_FindPlane(fixed_t height, int picnum, + int lightlevel, int special) +{ + visplane_t *check; + + if (special < 150) + { // Don't let low specials affect search + special = 0; + } + + if (picnum == skyflatnum) + { // All skies map together + height = 0; + lightlevel = 0; + } + + for (check = visplanes; check < lastvisplane; check++) + { + if (height == check->height + && picnum == check->picnum + && lightlevel == check->lightlevel && special == check->special) + break; + } + + if (check < lastvisplane) + { + return (check); + } + + if (lastvisplane - visplanes == MAXVISPLANES) + { + I_Error("R_FindPlane: no more visplanes"); + } + + lastvisplane++; + check->height = height; + check->picnum = picnum; + check->lightlevel = lightlevel; + check->special = special; + check->minx = SCREENWIDTH; + check->maxx = -1; + memset(check->top, 0xff, sizeof(check->top)); + return (check); +} + +//========================================================================== +// +// R_CheckPlane +// +//========================================================================== + +visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop) +{ + int intrl, intrh; + int unionl, unionh; + int x; + + if (start < pl->minx) + { + intrl = pl->minx; + unionl = start; + } + else + { + unionl = pl->minx; + intrl = start; + } + if (stop > pl->maxx) + { + intrh = pl->maxx; + unionh = stop; + } + else + { + unionh = pl->maxx; + intrh = stop; + } + + for (x = intrl; x <= intrh; x++) + { + if (pl->top[x] != 0xff) + { + break; + } + } + + if (x > intrh) + { + pl->minx = unionl; + pl->maxx = unionh; + return pl; // use the same visplane + } + + // Make a new visplane + lastvisplane->height = pl->height; + lastvisplane->picnum = pl->picnum; + lastvisplane->lightlevel = pl->lightlevel; + lastvisplane->special = pl->special; + pl = lastvisplane++; + pl->minx = start; + pl->maxx = stop; + memset(pl->top, 0xff, sizeof(pl->top)); + + return pl; +} + +//========================================================================== +// +// R_MakeSpans +// +//========================================================================== + +void R_MakeSpans(int x, int t1, int b1, int t2, int b2) +{ + while (t1 < t2 && t1 <= b1) + { + R_MapPlane(t1, spanstart[t1], x - 1); + t1++; + } + while (b1 > b2 && b1 >= t1) + { + R_MapPlane(b1, spanstart[b1], x - 1); + b1--; + } + while (t2 < t1 && t2 <= b2) + { + spanstart[t2] = x; + t2++; + } + while (b2 > b1 && b2 >= t2) + { + spanstart[b2] = x; + b2--; + } +} + +//========================================================================== +// +// R_DrawPlanes +// +//========================================================================== + +#define SKYTEXTUREMIDSHIFTED 200 + +void R_DrawPlanes(void) +{ + visplane_t *pl; + int light; + int x, stop; + int angle; + byte *tempSource; + byte *source; + byte *source2; + byte *dest; + int count; + int offset; + int skyTexture; + int offset2; + int skyTexture2; + int scrollOffset; + +#ifdef RANGECHECK + if (ds_p - drawsegs > MAXDRAWSEGS) + { + I_Error("R_DrawPlanes: drawsegs overflow (%td)", + ds_p - drawsegs); + } + if (lastvisplane - visplanes > MAXVISPLANES) + { + I_Error("R_DrawPlanes: visplane overflow (%td)", + lastvisplane - visplanes); + } + if (lastopening - openings > MAXOPENINGS) + { + I_Error("R_DrawPlanes: opening overflow (%td)", + lastopening - openings); + } +#endif + + for (pl = visplanes; pl < lastvisplane; pl++) + { + if (pl->minx > pl->maxx) + { + continue; + } + if (pl->picnum == skyflatnum) + { // Sky flat + if (DoubleSky) + { // Render 2 layers, sky 1 in front + offset = Sky1ColumnOffset >> 16; + skyTexture = texturetranslation[Sky1Texture]; + offset2 = Sky2ColumnOffset >> 16; + skyTexture2 = texturetranslation[Sky2Texture]; + for (x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + if (dc_yl <= dc_yh) + { + count = dc_yh - dc_yl; + if (count < 0) + { + return; + } + angle = (viewangle + xtoviewangle[x]) + >> ANGLETOSKYSHIFT; + source = R_GetColumn(skyTexture, angle + offset) + + SKYTEXTUREMIDSHIFTED + (dc_yl - centery); + source2 = R_GetColumn(skyTexture2, angle + offset2) + + SKYTEXTUREMIDSHIFTED + (dc_yl - centery); + dest = ylookup[dc_yl] + columnofs[x]; + do + { + if (*source) + { + *dest = *source++; + source2++; + } + else + { + *dest = *source2++; + source++; + } + dest += SCREENWIDTH; + } + while (count--); + } + } + continue; // Next visplane + } + else + { // Render single layer + if (pl->special == 200) + { // Use sky 2 + offset = Sky2ColumnOffset >> 16; + skyTexture = texturetranslation[Sky2Texture]; + } + else + { // Use sky 1 + offset = Sky1ColumnOffset >> 16; + skyTexture = texturetranslation[Sky1Texture]; + } + for (x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + if (dc_yl <= dc_yh) + { + count = dc_yh - dc_yl; + if (count < 0) + { + return; + } + angle = (viewangle + xtoviewangle[x]) + >> ANGLETOSKYSHIFT; + source = R_GetColumn(skyTexture, angle + offset) + + SKYTEXTUREMIDSHIFTED + (dc_yl - centery); + dest = ylookup[dc_yl] + columnofs[x]; + do + { + *dest = *source++; + dest += SCREENWIDTH; + } + while (count--); + } + } + continue; // Next visplane + } + } + // Regular flat + tempSource = W_CacheLumpNum(firstflat + + flattranslation[pl->picnum], PU_STATIC); + scrollOffset = leveltime >> 1 & 63; + switch (pl->special) + { // Handle scrolling flats + case 201: + case 202: + case 203: // Scroll_North_xxx + ds_source = tempSource + ((scrollOffset + << (pl->special - 201) & 63) << 6); + break; + case 204: + case 205: + case 206: // Scroll_East_xxx + ds_source = tempSource + ((63 - scrollOffset) + << (pl->special - 204) & 63); + break; + case 207: + case 208: + case 209: // Scroll_South_xxx + ds_source = tempSource + (((63 - scrollOffset) + << (pl->special - 207) & 63) << 6); + break; + case 210: + case 211: + case 212: // Scroll_West_xxx + ds_source = tempSource + (scrollOffset + << (pl->special - 210) & 63); + break; + case 213: + case 214: + case 215: // Scroll_NorthWest_xxx + ds_source = tempSource + (scrollOffset + << (pl->special - 213) & 63) + + ((scrollOffset << (pl->special - 213) & 63) << 6); + break; + case 216: + case 217: + case 218: // Scroll_NorthEast_xxx + ds_source = tempSource + ((63 - scrollOffset) + << (pl->special - 216) & 63) + + ((scrollOffset << (pl->special - 216) & 63) << 6); + break; + case 219: + case 220: + case 221: // Scroll_SouthEast_xxx + ds_source = tempSource + ((63 - scrollOffset) + << (pl->special - 219) & 63) + + (((63 - scrollOffset) << (pl->special - 219) & 63) << 6); + break; + case 222: + case 223: + case 224: // Scroll_SouthWest_xxx + ds_source = tempSource + (scrollOffset + << (pl->special - 222) & 63) + + (((63 - scrollOffset) << (pl->special - 222) & 63) << 6); + break; + default: + ds_source = tempSource; + break; + } + planeheight = abs(pl->height - viewz); + light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; + if (light >= LIGHTLEVELS) + { + light = LIGHTLEVELS - 1; + } + if (light < 0) + { + light = 0; + } + planezlight = zlight[light]; + + pl->top[pl->maxx + 1] = 0xff; + pl->top[pl->minx - 1] = 0xff; + + stop = pl->maxx + 1; + for (x = pl->minx; x <= stop; x++) + { + R_MakeSpans(x, pl->top[x - 1], pl->bottom[x - 1], + pl->top[x], pl->bottom[x]); + } + W_ReleaseLumpNum(firstflat + flattranslation[pl->picnum]); + } +} diff --git a/games/NXDoom/src/hexen/r_segs.c b/games/NXDoom/src/hexen/r_segs.c new file mode 100644 index 00000000000..003cf2eb0ec --- /dev/null +++ b/games/NXDoom/src/hexen/r_segs.c @@ -0,0 +1,654 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "i_system.h" +#include "r_local.h" + +// OPTIMIZE: closed two sided lines as single sided + +boolean segtextured; // true if any of the segs textures might be vis +boolean markfloor; // false if the back side is the same plane +boolean markceiling; +boolean maskedtexture; +int toptexture, bottomtexture, midtexture; + + +angle_t rw_normalangle; +int rw_angle1; // angle to line origin + +// +// wall +// +int rw_x; +int rw_stopx; +angle_t rw_centerangle; +fixed_t rw_offset; +fixed_t rw_distance; +fixed_t rw_scale; +fixed_t rw_scalestep; +fixed_t rw_midtexturemid; +fixed_t rw_toptexturemid; +fixed_t rw_bottomtexturemid; + +int worldtop, worldbottom, worldhigh, worldlow; + +fixed_t pixhigh, pixlow; +fixed_t pixhighstep, pixlowstep; +fixed_t topfrac, topstep; +fixed_t bottomfrac, bottomstep; + + +lighttable_t **walllights; + +short *maskedtexturecol; + +/* +================ += += R_RenderMaskedSegRange += +================ +*/ + +void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2) +{ + unsigned index; + column_t *col; + int lightnum; + int texnum; + +// +// calculate light table +// use different light tables for horizontal / vertical / diagonal +// OPTIMIZE: get rid of LIGHTSEGSHIFT globally + curline = ds->curline; + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = texturetranslation[curline->sidedef->midtexture]; + + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; + //if (curline->v1->y == curline->v2->y) + // lightnum--; + //else if (curline->v1->x == curline->v2->x) + // lightnum++; + //if (lightnum < 0) + // walllights = scalelight[0]; + if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + + maskedtexturecol = ds->maskedtexturecol; + + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1) * rw_scalestep; + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + +// +// find positioning +// + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + { + dc_texturemid = frontsector->floorheight > backsector->floorheight + ? frontsector->floorheight : backsector->floorheight; + dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; + } + else + { + dc_texturemid = frontsector->ceilingheight < backsector->ceilingheight + ? frontsector->ceilingheight : backsector->ceilingheight; + dc_texturemid = dc_texturemid - viewz; + } + dc_texturemid += curline->sidedef->rowoffset; + + if (fixedcolormap) + dc_colormap = fixedcolormap; +// +// draw the columns +// + for (dc_x = x1; dc_x <= x2; dc_x++) + { + // calculate lighting + if (maskedtexturecol[dc_x] != SHRT_MAX) + { + if (!fixedcolormap) + { + index = spryscale >> LIGHTSCALESHIFT; + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + dc_colormap = walllights[index]; + } + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned) spryscale; + + // + // draw the texture + // + col = (column_t *) ((byte *) + R_GetColumn(texnum, + maskedtexturecol[dc_x]) - 3); + + R_DrawMaskedColumn(col, -1); + maskedtexturecol[dc_x] = SHRT_MAX; + } + spryscale += rw_scalestep; + } + +} + +/* +================ += += R_RenderSegLoop += += Draws zero, one, or two textures (and possibly a masked texture) for walls += Can draw or mark the starting pixel of floor and ceiling textures += += CALLED: CORE LOOPING ROUTINE +================ +*/ + +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1<> HEIGHTBITS; + if (yl < ceilingclip[rw_x] + 1) + yl = ceilingclip[rw_x] + 1; // no space above wall + if (markceiling) + { + top = ceilingclip[rw_x] + 1; + bottom = yl - 1; + if (bottom >= floorclip[rw_x]) + bottom = floorclip[rw_x] - 1; + if (top <= bottom) + { + ceilingplane->top[rw_x] = top; + ceilingplane->bottom[rw_x] = bottom; + } + } + + yh = bottomfrac >> HEIGHTBITS; + if (yh >= floorclip[rw_x]) + yh = floorclip[rw_x] - 1; + if (markfloor) + { + top = yh + 1; + bottom = floorclip[rw_x] - 1; + if (top <= ceilingclip[rw_x]) + top = ceilingclip[rw_x] + 1; + if (top <= bottom) + { + floorplane->top[rw_x] = top; + floorplane->bottom[rw_x] = bottom; + } + } + +// +// texturecolumn and lighting are independent of wall tiers +// + if (segtextured) + { + // calculate texture offset + angle = (rw_centerangle + xtoviewangle[rw_x]) >> ANGLETOFINESHIFT; + texturecolumn = + rw_offset - FixedMul(finetangent[angle], rw_distance); + texturecolumn >>= FRACBITS; + // calculate lighting + index = rw_scale >> LIGHTSCALESHIFT; + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + dc_colormap = walllights[index]; + dc_x = rw_x; + dc_iscale = 0xffffffffu / (unsigned) rw_scale; + } + +// +// draw the wall tiers +// + if (midtexture) + { // single sided line + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_source = R_GetColumn(midtexture, texturecolumn); + colfunc(); + ceilingclip[rw_x] = viewheight; + floorclip[rw_x] = -1; + } + else + { // two sided line + if (toptexture) + { // top wall + mid = pixhigh >> HEIGHTBITS; + pixhigh += pixhighstep; + if (mid >= floorclip[rw_x]) + mid = floorclip[rw_x] - 1; + if (mid >= yl) + { + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_source = R_GetColumn(toptexture, texturecolumn); + colfunc(); + ceilingclip[rw_x] = mid; + } + else + ceilingclip[rw_x] = yl - 1; + } + else + { // no top wall + if (markceiling) + ceilingclip[rw_x] = yl - 1; + } + + if (bottomtexture) + { // bottom wall + mid = (pixlow + HEIGHTUNIT - 1) >> HEIGHTBITS; + pixlow += pixlowstep; + if (mid <= ceilingclip[rw_x]) + mid = ceilingclip[rw_x] + 1; // no space above wall + if (mid <= yh) + { + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_source = R_GetColumn(bottomtexture, texturecolumn); + colfunc(); + floorclip[rw_x] = mid; + } + else + floorclip[rw_x] = yh + 1; + } + else + { // no bottom wall + if (markfloor) + floorclip[rw_x] = yh + 1; + } + + if (maskedtexture) + { // save texturecol for backdrawing of masked mid texture + maskedtexturecol[rw_x] = texturecolumn; + } + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; + } + +} + + + +/* +===================== += += R_StoreWallRange += += A wall segment will be drawn between start and stop pixels (inclusive) += +====================== +*/ + +void R_StoreWallRange(int start, int stop) +{ + fixed_t hyp; + fixed_t sineval; + angle_t distangle, offsetangle; + fixed_t vtop; + int lightnum; + + if (ds_p == &drawsegs[MAXDRAWSEGS]) + return; // don't overflow and crash + +#ifdef RANGECHECK + if (start >= viewwidth || start > stop) + I_Error("Bad R_RenderWallRange: %i to %i", start, stop); +#endif + + sidedef = curline->sidedef; + linedef = curline->linedef; + +// mark the segment as visible for auto map + linedef->flags |= ML_MAPPED; + +// +// calculate rw_distance for scale calculation +// + rw_normalangle = curline->angle + ANG90; + offsetangle = abs((int) rw_normalangle - (int) rw_angle1); + if (offsetangle > ANG90) + offsetangle = ANG90; + distangle = ANG90 - offsetangle; + hyp = R_PointToDist(curline->v1->x, curline->v1->y); + sineval = finesine[distangle >> ANGLETOFINESHIFT]; + rw_distance = FixedMul(hyp, sineval); + + + ds_p->x1 = rw_x = start; + ds_p->x2 = stop; + ds_p->curline = curline; + rw_stopx = stop + 1; + +// +// calculate scale at both ends and step +// + ds_p->scale1 = rw_scale = + R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); + if (stop > start) + { + ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); + ds_p->scalestep = rw_scalestep = + (ds_p->scale2 - rw_scale) / (stop - start); + } + else + { + // + // try to fix the stretched line bug + // +#if 0 + if (rw_distance < FRACUNIT / 2) + { + fixed_t trx, try; + fixed_t gxt, gyt; + + trx = curline->v1->x - viewx; + try = curline->v1->y - viewy; + + gxt = FixedMul(trx, viewcos); + gyt = -FixedMul(try, viewsin); + ds_p->scale1 = FixedDiv(projection, gxt - gyt); + } +#endif + ds_p->scale2 = ds_p->scale1; + } + + +// +// calculate texture boundaries and decide if floor / ceiling marks +// are needed +// + worldtop = frontsector->ceilingheight - viewz; + worldbottom = frontsector->floorheight - viewz; + + midtexture = toptexture = bottomtexture = maskedtexture = 0; + ds_p->maskedtexturecol = NULL; + + if (!backsector) + { +// +// single sided line +// + midtexture = texturetranslation[sidedef->midtexture]; + // a single sided line is terminal, so it must mark ends + markfloor = markceiling = true; + if (linedef->flags & ML_DONTPEGBOTTOM) + { + vtop = frontsector->floorheight + + textureheight[sidedef->midtexture]; + rw_midtexturemid = vtop - viewz; // bottom of texture at bottom + } + else + rw_midtexturemid = worldtop; // top of texture at top + rw_midtexturemid += sidedef->rowoffset; + ds_p->silhouette = SIL_BOTH; + ds_p->sprtopclip = screenheightarray; + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->tsilheight = INT_MIN; + } + else + { +// +// two sided line +// + ds_p->sprtopclip = ds_p->sprbottomclip = NULL; + ds_p->silhouette = 0; + if (frontsector->floorheight > backsector->floorheight) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = frontsector->floorheight; + } + else if (backsector->floorheight > viewz) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; +// ds_p->sprbottomclip = negonearray; + } + if (frontsector->ceilingheight < backsector->ceilingheight) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = frontsector->ceilingheight; + } + else if (backsector->ceilingheight < viewz) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; +// ds_p->sprtopclip = screenheightarray; + } + + if (backsector->ceilingheight <= frontsector->floorheight) + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } + if (backsector->floorheight >= frontsector->ceilingheight) + { + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT_MIN; + ds_p->silhouette |= SIL_TOP; + } + worldhigh = backsector->ceilingheight - viewz; + worldlow = backsector->floorheight - viewz; + + // hack to allow height changes in outdoor areas + if (frontsector->ceilingpic == skyflatnum + && backsector->ceilingpic == skyflatnum) + worldtop = worldhigh; + + if (worldlow != worldbottom + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel + || backsector->special != frontsector->special) + markfloor = true; + else + markfloor = false; // same plane on both sides + + if (worldhigh != worldtop + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel) + markceiling = true; + else + markceiling = false; // same plane on both sides + + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + markceiling = markfloor = true; // closed door + + if (worldhigh < worldtop) + { // top texture + toptexture = texturetranslation[sidedef->toptexture]; + if (linedef->flags & ML_DONTPEGTOP) + rw_toptexturemid = worldtop; // top of texture at top + else + { + vtop = backsector->ceilingheight + + textureheight[sidedef->toptexture]; + rw_toptexturemid = vtop - viewz; // bottom of texture + } + } + if (worldlow > worldbottom) + { // bottom texture + bottomtexture = texturetranslation[sidedef->bottomtexture]; + if (linedef->flags & ML_DONTPEGBOTTOM) + { // bottom of texture at bottom + rw_bottomtexturemid = worldtop; // top of texture at top + } + else // top of texture at top + rw_bottomtexturemid = worldlow; + } + rw_toptexturemid += sidedef->rowoffset; + rw_bottomtexturemid += sidedef->rowoffset; + + // + // allocate space for masked texture tables + // + if (sidedef->midtexture) + { // masked midtexture + maskedtexture = true; + ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; + } + } + +// +// calculate rw_offset (only needed for textured lines) +// + segtextured = midtexture | toptexture | bottomtexture | maskedtexture; + + if (segtextured) + { + offsetangle = rw_normalangle - rw_angle1; + if (offsetangle > ANG180) + offsetangle = -offsetangle; + if (offsetangle > ANG90) + offsetangle = ANG90; + sineval = finesine[offsetangle >> ANGLETOFINESHIFT]; + rw_offset = FixedMul(hyp, sineval); + if (rw_normalangle - rw_angle1 < ANG180) + rw_offset = -rw_offset; + rw_offset += sidedef->textureoffset + curline->offset; + rw_centerangle = ANG90 + viewangle - rw_normalangle; + + // + // calculate light table + // use different light tables for horizontal / vertical / diagonal + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + if (!fixedcolormap) + { + lightnum = + (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; + //if (curline->v1->y == curline->v2->y) + // lightnum--; + //else if (curline->v1->x == curline->v2->x) + // lightnum++; + //if (lightnum < 0) + // walllights = scalelight[0]; + if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + } + } + + +// +// if a floor / ceiling plane is on the wrong side of the view plane +// it is definately invisible and doesn't need to be marked +// + if (frontsector->floorheight >= viewz) + markfloor = false; // above view plane + if (frontsector->ceilingheight <= viewz + && frontsector->ceilingpic != skyflatnum) + markceiling = false; // below view plane + +// +// calculate incremental stepping values for texture edges +// + worldtop >>= 4; + worldbottom >>= 4; + + topstep = -FixedMul(rw_scalestep, worldtop); + topfrac = (centeryfrac >> 4) - FixedMul(worldtop, rw_scale); + + bottomstep = -FixedMul(rw_scalestep, worldbottom); + bottomfrac = (centeryfrac >> 4) - FixedMul(worldbottom, rw_scale); + + if (backsector) + { + worldhigh >>= 4; + worldlow >>= 4; + + if (worldhigh < worldtop) + { + pixhigh = (centeryfrac >> 4) - FixedMul(worldhigh, rw_scale); + pixhighstep = -FixedMul(rw_scalestep, worldhigh); + } + if (worldlow > worldbottom) + { + pixlow = (centeryfrac >> 4) - FixedMul(worldlow, rw_scale); + pixlowstep = -FixedMul(rw_scalestep, worldlow); + } + } + +// +// render it +// + if (markceiling) + ceilingplane = R_CheckPlane(ceilingplane, rw_x, rw_stopx - 1); + if (markfloor) + floorplane = R_CheckPlane(floorplane, rw_x, rw_stopx - 1); + + R_RenderSegLoop(); + +// +// save sprite clipping info +// + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + { + memcpy(lastopening, ceilingclip + start, 2 * (rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) + && !ds_p->sprbottomclip) + { + memcpy(lastopening, floorclip + start, 2 * (rw_stopx - start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } + if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + } + if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + } + ds_p++; +} diff --git a/games/NXDoom/src/hexen/r_things.c b/games/NXDoom/src/hexen/r_things.c new file mode 100644 index 00000000000..e9cfeccdb09 --- /dev/null +++ b/games/NXDoom/src/hexen/r_things.c @@ -0,0 +1,1044 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include +#include +#include "h2def.h" +#include "i_system.h" +#include "i_swap.h" +#include "r_local.h" + +//void R_DrawTranslatedAltTLColumn(void); + +typedef struct +{ + int x1, x2; + + int column; + int topclip; + int bottomclip; +} maskdraw_t; + +/* + +Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis. +This is not the same as the angle, which increases counter clockwise +(protractor). There was a lot of stuff grabbed wrong, so I changed it... + +*/ + + +fixed_t pspritescale, pspriteiscale; + +lighttable_t **spritelights; + +// constant arrays used for psprite clipping and initializing clipping +short negonearray[SCREENWIDTH]; +short screenheightarray[SCREENWIDTH]; + +boolean LevelUseFullBright; +/* +=============================================================================== + + INITIALIZATION FUNCTIONS + +=============================================================================== +*/ + +// variables used to look up and range check thing_t sprites patches +spritedef_t *sprites; +int numsprites; + +spriteframe_t sprtemp[30]; +int maxframe; +static const char *spritename; + + + +/* +================= += += R_InstallSpriteLump += += Local function for R_InitSprites +================= +*/ + +void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, + boolean flipped) +{ + int r; + + if (frame >= 30 || rotation > 8) + I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); + + if ((int) frame > maxframe) + maxframe = frame; + + if (rotation == 0) + { +// the lump should be used for all rotations + if (sprtemp[frame].rotate == false) + I_Error("R_InitSprites: Sprite %s frame %c has multip rot=0 lump", + spritename, 'A' + frame); + if (sprtemp[frame].rotate == true) + I_Error + ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = false; + for (r = 0; r < 8; r++) + { + sprtemp[frame].lump[r] = lump - firstspritelump; + sprtemp[frame].flip[r] = (byte) flipped; + } + return; + } + +// the lump is only used for one rotation + if (sprtemp[frame].rotate == false) + I_Error + ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = true; + + rotation--; // make 0 based + if (sprtemp[frame].lump[rotation] != -1) + I_Error + ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it", + spritename, 'A' + frame, '1' + rotation); + + sprtemp[frame].lump[rotation] = lump - firstspritelump; + sprtemp[frame].flip[rotation] = (byte) flipped; +} + +/* +================= += += R_InitSpriteDefs += += Pass a null terminated list of sprite names (4 chars exactly) to be used += Builds the sprite rotation matrixes to account for horizontally flipped += sprites. Will report an error if the lumps are inconsistant +=Only called at startup += += Sprite lump names are 4 characters for the actor, a letter for the frame, += and a number for the rotation, A sprite that is flippable will have an += additional letter/number appended. The rotation character can be 0 to += signify no rotations +================= +*/ + +void R_InitSpriteDefs(const char **namelist) +{ + const char **check; + int i, l, frame, rotation; + int start, end; + +// count the number of sprite names + check = namelist; + while (*check != NULL) + check++; + numsprites = check - namelist; + + if (!numsprites) + return; + + sprites = Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); + + start = firstspritelump - 1; + end = lastspritelump + 1; + +// scan all the lump names for each of the names, noting the highest +// frame letter +// Just compare 4 characters as ints + for (i = 0; i < numsprites; i++) + { + spritename = namelist[i]; + memset(sprtemp, -1, sizeof(sprtemp)); + + maxframe = -1; + + // + // scan the lumps, filling in the frames for whatever is found + // + for (l = start + 1; l < end; l++) + if (!strncmp(lumpinfo[l]->name, namelist[i], 4)) + { + frame = lumpinfo[l]->name[4] - 'A'; + rotation = lumpinfo[l]->name[5] - '0'; + R_InstallSpriteLump(l, frame, rotation, false); + if (lumpinfo[l]->name[6]) + { + frame = lumpinfo[l]->name[6] - 'A'; + rotation = lumpinfo[l]->name[7] - '0'; + R_InstallSpriteLump(l, frame, rotation, true); + } + } + + // + // check the frames that were found for completeness + // + if (maxframe == -1) + { + //continue; + sprites[i].numframes = 0; + if (gamemode == shareware) + continue; + I_Error("R_InitSprites: No lumps found for sprite %s", + namelist[i]); + } + + maxframe++; + for (frame = 0; frame < maxframe; frame++) + { + switch ((int) sprtemp[frame].rotate) + { + case -1: // no rotations were found for that frame at all + I_Error("R_InitSprites: No patches found for %s frame %c", + namelist[i], frame + 'A'); + case 0: // only the first rotation is needed + break; + + case 1: // must have all 8 frames + for (rotation = 0; rotation < 8; rotation++) + if (sprtemp[frame].lump[rotation] == -1) + I_Error + ("R_InitSprites: Sprite %s frame %c is missing rotations", + namelist[i], frame + 'A'); + } + } + + // + // allocate space for the frames present and copy sprtemp to it + // + sprites[i].numframes = maxframe; + sprites[i].spriteframes = + Z_Malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + memcpy(sprites[i].spriteframes, sprtemp, + maxframe * sizeof(spriteframe_t)); + } + +} + + +/* +=============================================================================== + + GAME FUNCTIONS + +=============================================================================== +*/ + +vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; +int newvissprite; + + +/* +=================== += += R_InitSprites += += Called at program start +=================== +*/ + +void R_InitSprites(const char **namelist) +{ + int i; + + for (i = 0; i < SCREENWIDTH; i++) + { + negonearray[i] = -1; + } + + R_InitSpriteDefs(namelist); +} + + +/* +=================== += += R_ClearSprites += += Called at frame start +=================== +*/ + +void R_ClearSprites(void) +{ + vissprite_p = vissprites; +} + + +/* +=================== += += R_NewVisSprite += +=================== +*/ + +vissprite_t overflowsprite; + +vissprite_t *R_NewVisSprite(void) +{ + if (vissprite_p == &vissprites[MAXVISSPRITES]) + return &overflowsprite; + vissprite_p++; + return vissprite_p - 1; +} + + +/* +================ += += R_DrawMaskedColumn += += Used for sprites and masked mid textures +================ +*/ + +short *mfloorclip; +short *mceilingclip; +fixed_t spryscale; +fixed_t sprtopscreen; +fixed_t sprbotscreen; + +void R_DrawMaskedColumn(column_t * column, signed int baseclip) +{ + int topscreen, bottomscreen; + fixed_t basetexturemid; + + basetexturemid = dc_texturemid; + + for (; column->topdelta != 0xff;) + { +// calculate unclipped screen coordinates for post + topscreen = sprtopscreen + spryscale * column->topdelta; + bottomscreen = topscreen + spryscale * column->length; + dc_yl = (topscreen + FRACUNIT - 1) >> FRACBITS; + dc_yh = (bottomscreen - 1) >> FRACBITS; + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yh >= baseclip && baseclip != -1) + dc_yh = baseclip; + + if (dc_yl <= dc_yh) + { + dc_source = (byte *) column + 3; + dc_texturemid = basetexturemid - (column->topdelta << FRACBITS); +// dc_source = (byte *)column + 3 - column->topdelta; + colfunc(); // either R_DrawColumn or R_DrawTLColumn + } + column = (column_t *) ((byte *) column + column->length + 4); + } + + dc_texturemid = basetexturemid; +} + + +/* +================ += += R_DrawVisSprite += += mfloorclip and mceilingclip should also be set +================ +*/ + +void R_DrawVisSprite(vissprite_t * vis, int x1, int x2) +{ + column_t *column; + int texturecolumn; + fixed_t frac; + patch_t *patch; + fixed_t baseclip; + + + patch = W_CacheLumpNum(vis->patch + firstspritelump, PU_CACHE); + + dc_colormap = vis->colormap; + +// if(!dc_colormap) +// colfunc = tlcolfunc; // NULL colormap = shadow draw + + if (vis->mobjflags & (MF_SHADOW | MF_ALTSHADOW)) + { + if (vis->mobjflags & MF_TRANSLATION) + { + colfunc = R_DrawTranslatedTLColumn; + dc_translation = translationtables - 256 + + vis->class * ((maxplayers - 1) * 256) + + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); + } + else if (vis->mobjflags & MF_SHADOW) + { // Draw using shadow column function + colfunc = tlcolfunc; + } + else + { + colfunc = R_DrawAltTLColumn; + } + } + else if (vis->mobjflags & MF_TRANSLATION) + { + // Draw using translated column function + colfunc = R_DrawTranslatedColumn; + dc_translation = translationtables - 256 + + vis->class * ((maxplayers - 1) * 256) + + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); + } + + dc_iscale = abs(vis->xiscale) >> detailshift; + dc_texturemid = vis->texturemid; + frac = vis->startfrac; + spryscale = vis->scale; + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + + // check to see if vissprite is a weapon + if (vis->psprite) + { + dc_texturemid += FixedMul(((centery - viewheight / 2) << FRACBITS), + vis->xiscale); + sprtopscreen += (viewheight / 2 - centery) << FRACBITS; + } + + if (vis->floorclip && !vis->psprite) + { + sprbotscreen = sprtopscreen + FixedMul(SHORT(patch->height) << FRACBITS, + spryscale); + baseclip = (sprbotscreen - FixedMul(vis->floorclip, + spryscale)) >> FRACBITS; + } + else + { + baseclip = -1; + } + + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + { + texturecolumn = frac >> FRACBITS; +#ifdef RANGECHECK + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error("R_DrawSpriteRange: bad texturecolumn"); +#endif + column = (column_t *) ((byte *) patch + + LONG(patch->columnofs[texturecolumn])); + R_DrawMaskedColumn(column, baseclip); + } + + colfunc = basecolfunc; +} + + + +/* +=================== += += R_ProjectSprite += += Generates a vissprite for a thing if it might be visible += +=================== +*/ + +void R_ProjectSprite(mobj_t * thing) +{ + fixed_t trx, try; + fixed_t gxt, gyt; + fixed_t tx, tz; + fixed_t xscale; + int x1, x2; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + unsigned rot; + boolean flip; + int index; + vissprite_t *vis; + angle_t ang; + fixed_t iscale; + + if (thing->flags2 & MF2_DONTDRAW) + { // Never make a vissprite when MF2_DONTDRAW is flagged. + return; + } + +// +// transform the origin point +// + trx = thing->x - viewx; + try = thing->y - viewy; + + gxt = FixedMul(trx, viewcos); + gyt = -FixedMul(try, viewsin); + tz = gxt - gyt; + + if (tz < MINZ) + return; // thing is behind view plane + xscale = FixedDiv(projection, tz); + + gxt = -FixedMul(trx, viewsin); + gyt = FixedMul(try, viewcos); + tx = -(gyt + gxt); + + if (abs(tx) > (tz << 2)) + return; // too far off the side + +// +// decide which patch to use for sprite reletive to player +// +#ifdef RANGECHECK + if ((unsigned) thing->sprite >= numsprites) + I_Error("R_ProjectSprite: invalid sprite number %i ", thing->sprite); +#endif + sprdef = &sprites[thing->sprite]; +#ifdef RANGECHECK + if ((thing->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", + thing->sprite, thing->frame); +#endif + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; + + if (sprframe->rotate) + { // choose a different rotation based on player view + ang = R_PointToAngle(thing->x, thing->y); + rot = (ang - thing->angle + (unsigned) (ANG45 / 2) * 9) >> 29; + lump = sprframe->lump[rot]; + flip = (boolean) sprframe->flip[rot]; + } + else + { // use single rotation for all views + lump = sprframe->lump[0]; + flip = (boolean) sprframe->flip[0]; + } + +// +// calculate edges of the shape +// + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul(tx, xscale)) >> FRACBITS; + if (x1 > viewwidth) + return; // off the right side + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul(tx, xscale)) >> FRACBITS) - 1; + if (x2 < 0) + return; // off the left side + + +// +// store information in a vissprite +// + vis = R_NewVisSprite(); + vis->mobjflags = thing->flags; + vis->psprite = false; + vis->scale = xscale << detailshift; + vis->gx = thing->x; + vis->gy = thing->y; + vis->gz = thing->z; + vis->gzt = thing->z + spritetopoffset[lump]; + if (thing->flags & MF_TRANSLATION) + { + if (thing->player) + { + vis->class = thing->player->class; + } + else + { + vis->class = thing->special1.i; + } + if (vis->class > 2) + { + vis->class = 0; + } + } + // foot clipping + vis->floorclip = thing->floorclip; + vis->texturemid = vis->gzt - viewz - vis->floorclip; + + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + iscale = FixedDiv(FRACUNIT, xscale); + if (flip) + { + vis->startfrac = spritewidth[lump] - 1; + vis->xiscale = -iscale; + } + else + { + vis->startfrac = 0; + vis->xiscale = iscale; + } + if (vis->x1 > x1) + vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->patch = lump; +// +// get light level +// + +// if (thing->flags & MF_SHADOW) +// vis->colormap = NULL; // shadow draw +// else ... + + if (fixedcolormap) + vis->colormap = fixedcolormap; // fixed map + else if (LevelUseFullBright && thing->frame & FF_FULLBRIGHT) + vis->colormap = colormaps; // full bright + else + { // diminished light + index = xscale >> (LIGHTSCALESHIFT - detailshift); + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + vis->colormap = spritelights[index]; + } +} + + + + +/* +======================== += += R_AddSprites += +======================== +*/ + +void R_AddSprites(sector_t * sec) +{ + mobj_t *thing; + int lightnum; + + if (sec->validcount == validcount) + return; // already added + + sec->validcount = validcount; + + lightnum = (sec->lightlevel >> LIGHTSEGSHIFT) + extralight; + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; + + + for (thing = sec->thinglist; thing; thing = thing->snext) + R_ProjectSprite(thing); +} + + +/* +======================== += += R_DrawPSprite += +======================== +*/ + +// Y-adjustment values for full screen (4 weapons) +int PSpriteSY[NUMCLASSES][NUMWEAPONS] = { + {0, -12 * FRACUNIT, -10 * FRACUNIT, 10 * FRACUNIT}, // Fighter + {-8 * FRACUNIT, 10 * FRACUNIT, 10 * FRACUNIT, 0}, // Cleric + {9 * FRACUNIT, 20 * FRACUNIT, 20 * FRACUNIT, 20 * FRACUNIT}, // Mage + {10 * FRACUNIT, 10 * FRACUNIT, 10 * FRACUNIT, 10 * FRACUNIT} // Pig +}; + +void R_DrawPSprite(pspdef_t * psp) +{ + fixed_t tx; + int x1, x2; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + boolean flip; + vissprite_t *vis, avis; + + int tempangle; + +// +// decide which patch to use +// +#ifdef RANGECHECK + if ((unsigned) psp->state->sprite >= numsprites) + I_Error("R_ProjectSprite: invalid sprite number %i ", + psp->state->sprite); +#endif + sprdef = &sprites[psp->state->sprite]; +#ifdef RANGECHECK + if ((psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", + psp->state->sprite, psp->state->frame); +#endif + sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; + + lump = sprframe->lump[0]; + flip = (boolean) sprframe->flip[0]; + +// +// calculate edges of the shape +// + tx = psp->sx - 160 * FRACUNIT; + + tx -= spriteoffset[lump]; + if (viewangleoffset) + { + tempangle = + ((centerxfrac / 1024) * (viewangleoffset >> ANGLETOFINESHIFT)); + } + else + { + tempangle = 0; + } + x1 = (centerxfrac + FixedMul(tx, pspritescale) + tempangle) >> FRACBITS; + if (x1 > viewwidth) + return; // off the right side + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul(tx, pspritescale) + + tempangle) >> FRACBITS) - 1; + if (x2 < 0) + return; // off the left side + +// +// store information in a vissprite +// + vis = &avis; + vis->mobjflags = 0; + vis->class = 0; + vis->psprite = true; + vis->floorclip = 0; + vis->texturemid = (BASEYCENTER << FRACBITS) + FRACUNIT / 2 + - (psp->sy - spritetopoffset[lump]); + if (viewheight == SCREENHEIGHT) + { + vis->texturemid -= PSpriteSY[viewplayer->class] + [players[consoleplayer].readyweapon]; + } + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + vis->scale = pspritescale << detailshift; + if (flip) + { + vis->xiscale = -pspriteiscale; + vis->startfrac = spritewidth[lump] - 1; + } + else + { + vis->xiscale = pspriteiscale; + vis->startfrac = 0; + } + if (vis->x1 > x1) + vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->patch = lump; + + if (viewplayer->powers[pw_invulnerability] && viewplayer->class + == PCLASS_CLERIC) + { + vis->colormap = spritelights[MAXLIGHTSCALE - 1]; + if (viewplayer->powers[pw_invulnerability] > 4 * 32) + { + if (viewplayer->mo->flags2 & MF2_DONTDRAW) + { // don't draw the psprite + vis->mobjflags |= MF_SHADOW; + } + else if (viewplayer->mo->flags & MF_SHADOW) + { + vis->mobjflags |= MF_ALTSHADOW; + } + } + else if (viewplayer->powers[pw_invulnerability] & 8) + { + vis->mobjflags |= MF_SHADOW; + } + } + else if (fixedcolormap) + { + // Fixed color + vis->colormap = fixedcolormap; + } + else if (psp->state->frame & FF_FULLBRIGHT) + { + // Full bright + vis->colormap = colormaps; + } + else + { + // local light + vis->colormap = spritelights[MAXLIGHTSCALE - 1]; + } + R_DrawVisSprite(vis, vis->x1, vis->x2); +} + +/* +======================== += += R_DrawPlayerSprites += +======================== +*/ + +void R_DrawPlayerSprites(void) +{ + int i, lightnum; + pspdef_t *psp; + +// +// get light level +// + lightnum = + (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + + extralight; + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; +// +// clip to screen bounds +// + mfloorclip = screenheightarray; + mceilingclip = negonearray; + +// +// add all active psprites +// + for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; i++, psp++) + if (psp->state) + R_DrawPSprite(psp); + +} + + +/* +======================== += += R_SortVisSprites += +======================== +*/ + +vissprite_t vsprsortedhead; + +void R_SortVisSprites(void) +{ + int i, count; + vissprite_t *ds, *best; + static vissprite_t unsorted; + fixed_t bestscale; + + count = vissprite_p - vissprites; + + unsorted.next = unsorted.prev = &unsorted; + if (!count) + return; + + for (ds = vissprites; ds < vissprite_p; ds++) + { + ds->next = ds + 1; + ds->prev = ds - 1; + } + vissprites[0].prev = &unsorted; + unsorted.next = &vissprites[0]; + (vissprite_p - 1)->next = &unsorted; + unsorted.prev = vissprite_p - 1; + +// +// pull the vissprites out by scale +// + best = 0; // shut up the compiler warning + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i = 0; i < count; i++) + { + bestscale = INT_MAX; + for (ds = unsorted.next; ds != &unsorted; ds = ds->next) + { + if (ds->scale < bestscale) + { + bestscale = ds->scale; + best = ds; + } + } + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; + } +} + + + +/* +======================== += += R_DrawSprite += +======================== +*/ + +void R_DrawSprite(vissprite_t * spr) +{ + drawseg_t *ds; + short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH]; + int x, r1, r2; + fixed_t scale, lowscale; + int silhouette; + + for (x = spr->x1; x <= spr->x2; x++) + clipbot[x] = cliptop[x] = -2; + +// +// scan drawsegs from end to start for obscuring segs +// the first drawseg that has a greater scale is the clip seg +// + for (ds = ds_p - 1; ds >= drawsegs; ds--) + { + // + // determine if the drawseg obscures the sprite + // + if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || + (!ds->silhouette && !ds->maskedtexturecol)) + continue; // doesn't cover sprite + + r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; + r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->scale || (lowscale < spr->scale + && !R_PointOnSegSide(spr->gx, spr->gy, + ds->curline))) + { + if (ds->maskedtexturecol) // masked mid texture + R_RenderMaskedSegRange(ds, r1, r2); + continue; // seg is behind sprite + } + +// +// clip this piece of the sprite +// + silhouette = ds->silhouette; + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == 1) + { // bottom sil + for (x = r1; x <= r2; x++) + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + } + else if (silhouette == 2) + { // top sil + for (x = r1; x <= r2; x++) + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == 3) + { // both + for (x = r1; x <= r2; x++) + { + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + } + + } + +// +// all clipping has been performed, so draw the sprite +// + +// check for unclipped columns + for (x = spr->x1; x <= spr->x2; x++) + { + if (clipbot[x] == -2) + clipbot[x] = viewheight; + if (cliptop[x] == -2) + cliptop[x] = -1; + } + + mfloorclip = clipbot; + mceilingclip = cliptop; + R_DrawVisSprite(spr, spr->x1, spr->x2); +} + + +/* +======================== += += R_DrawMasked += +======================== +*/ + +void R_DrawMasked(void) +{ + vissprite_t *spr; + drawseg_t *ds; + + R_SortVisSprites(); + + if (vissprite_p > vissprites) + { + // draw all vissprites back to front + + for (spr = vsprsortedhead.next; spr != &vsprsortedhead; + spr = spr->next) + R_DrawSprite(spr); + } + +// +// render any remaining masked mid textures +// + for (ds = ds_p - 1; ds >= drawsegs; ds--) + if (ds->maskedtexturecol) + R_RenderMaskedSegRange(ds, ds->x1, ds->x2); + +// +// draw the psprites on top of everything +// +// Added for the sideviewing with an external device + if (viewangleoffset <= 1024 << ANGLETOFINESHIFT || viewangleoffset >= + -(1024 << ANGLETOFINESHIFT)) + { // don't draw on side views + R_DrawPlayerSprites(); + } + +// if (!viewangleoffset) // don't draw on side views +// R_DrawPlayerSprites (); +} diff --git a/games/NXDoom/src/hexen/s_sound.c b/games/NXDoom/src/hexen/s_sound.c new file mode 100644 index 00000000000..33e62167189 --- /dev/null +++ b/games/NXDoom/src/hexen/s_sound.c @@ -0,0 +1,1014 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include "h2def.h" +#include "m_random.h" +#include "i_cdmus.h" +#include "i_sound.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_argv.h" +#include "m_misc.h" +#include "r_local.h" +#include "p_local.h" // for P_AproxDistance +#include "sounds.h" +#include "s_sound.h" + +#define PRIORITY_MAX_ADJUST 10 +#define DIST_ADJUST (MAX_SND_DIST/PRIORITY_MAX_ADJUST) + +#define DEFAULT_ARCHIVEPATH "o:\\sound\\archive\\" + +void S_ShutDown(void); + +// If true, CD music playback is enabled (snd_musicdevice == SNDDEVICE_CD +// and CD initialization succeeded). +boolean cdmusic; + +// Track number of a track to play explicitly chosen by the +// player using cheats. A value of zero means no track chosen: +static int cd_custom_track = 0; + +// Currently playing track: +static int cd_current_track = 0; + +// Time (MS) at which the currently-playing CD track will finish playing +// and should be looped. Zero if we are not currently playing a track: +static int cd_track_end_time = 0; + +/* +=============================================================================== + + MUSIC & SFX API + +=============================================================================== +*/ + +//static channel_t channel[MAX_CHANNELS]; + +//static int rs; //the current registered song. +//int mus_song = -1; +//int mus_lumpnum; +//void *mus_sndptr; +//byte *soundCurve; + + +static channel_t Channel[MAX_CHANNELS]; +static void *RegisteredSong; //the current registered song. +static boolean MusicPaused; +static int Mus_Song = -1; +static byte *Mus_SndPtr; +static byte *SoundCurve; + +int snd_MaxVolume = 10; // maximum volume for sound +int snd_MusicVolume = 10; // maximum volume for music +int snd_Channels = 16; + +// int AmbChan; + +//========================================================================== +// +// S_Start +// +//========================================================================== + +void S_Start(void) +{ + S_StopAllSound(); + S_StartSong(gamemap, true); +} + +//========================================================================== +// +// Returns true if we are playing a looping CD track and it is time to +// restart it. +// +//========================================================================== + +static boolean ShouldRestartCDTrack(void) +{ + return cd_track_end_time != 0 && I_GetTimeMS() > cd_track_end_time; +} + +//========================================================================== +// +// Start playing a CD track. Returns true for success. +// +//========================================================================== + +static boolean StartCDTrack(int track, boolean loop) +{ + // Already playing? If so, don't bother. + + if (track == cd_current_track && !ShouldRestartCDTrack()) + { + return true; + } + + if (I_CDMusPlay(track)) + { + return false; + } + + cd_current_track = track; + + if (loop) + { + cd_track_end_time = I_GetTimeMS() + 1000 * I_CDMusTrackLength(track); + } + else + { + cd_track_end_time = 0; + } + + return true; +} + +//========================================================================== +// +// S_StartSong +// +//========================================================================== + +void S_StartSong(int song, boolean loop) +{ + char *songLump; + int lumpnum; + int length; + int track; + + // If we're in CD music mode, play a CD track, instead: + if (cdmusic) + { + // Default to the player-chosen track + if (cd_custom_track != 0) + { + track = cd_custom_track; + } + else + { + track = P_GetMapCDTrack(gamemap); + } + + StartCDTrack(track, loop); + } + else + { + if (song == Mus_Song) + { // don't replay an old song + return; + } + if (RegisteredSong) + { + I_StopSong(); + I_UnRegisterSong(RegisteredSong); + RegisteredSong = 0; + } + songLump = P_GetMapSongLump(song); + if (!songLump) + { + return; + } + + lumpnum = W_GetNumForName(songLump); + Mus_SndPtr = W_CacheLumpNum(lumpnum, PU_STATIC); + length = W_LumpLength(lumpnum); + + RegisteredSong = I_RegisterSong(Mus_SndPtr, length); + I_PlaySong(RegisteredSong, loop); + Mus_Song = song; + + W_ReleaseLumpNum(lumpnum); + } +} + +//========================================================================== +// +// Play a custom-chosen music track selected by the player. +// +// Returns true for success. +// +//========================================================================== + +boolean S_StartCustomCDTrack(int tracknum) +{ + boolean result; + + result = StartCDTrack(tracknum, true); + + if (result) + { + cd_custom_track = tracknum; + } + + return result; +} + +//========================================================================== +// +// Get the currently-playing CD track; returns -1 if not playing. +// +//========================================================================== + +int S_GetCurrentCDTrack(void) +{ + if (!cdmusic || cd_current_track == 0) + { + return -1; + } + + return cd_current_track; +} + +//========================================================================== +// +// S_StartSongName +// +//========================================================================== + +void S_StartSongName(const char *songLump, boolean loop) +{ + int lumpnum; + int cdTrack; + int length; + + if (!songLump) + { + return; + } + if (cdmusic) + { + cdTrack = 0; + + if (!strcmp(songLump, "hexen")) + { + cdTrack = P_GetCDTitleTrack(); + } + else if (!strcmp(songLump, "hub")) + { + cdTrack = P_GetCDIntermissionTrack(); + } + else if (!strcmp(songLump, "hall")) + { + cdTrack = P_GetCDEnd1Track(); + } + else if (!strcmp(songLump, "orb")) + { + cdTrack = P_GetCDEnd2Track(); + } + else if (!strcmp(songLump, "chess") && cd_custom_track == 0) + { + cdTrack = P_GetCDEnd3Track(); + } +/* Uncomment this, if Kevin writes a specific song for startup + else if(!strcmp(songLump, "start")) + { + cdTrack = P_GetCDStartTrack(); + } +*/ + if (cdTrack != 0) + { + cd_custom_track = 0; + StartCDTrack(cdTrack, loop); + } + } + else + { + if (RegisteredSong) + { + I_StopSong(); + I_UnRegisterSong(RegisteredSong); + RegisteredSong = NULL; + } + + lumpnum = W_GetNumForName(songLump); + Mus_SndPtr = W_CacheLumpNum(lumpnum, PU_MUSIC); + length = W_LumpLength(lumpnum); + + RegisteredSong = I_RegisterSong(Mus_SndPtr, length); + I_PlaySong(RegisteredSong, loop); + W_ReleaseLumpNum(lumpnum); + Mus_Song = -1; + } +} + +//========================================================================== +// +// S_GetSoundID +// +//========================================================================== + +int S_GetSoundID(char *name) +{ + int i; + + for (i = 0; i < NUMSFX; i++) + { + if (!strcmp(S_sfx[i].tagname, name)) + { + return i; + } + } + return 0; +} + +//========================================================================== +// +// S_StartSound +// +//========================================================================== + +void S_StartSound(mobj_t * origin, int sound_id) +{ + S_StartSoundAtVolume(origin, sound_id, 127); +} + +static mobj_t *GetSoundListener(void) +{ + static degenmobj_t dummy_listener; + + // If we are at the title screen, the console player doesn't have an + // object yet, so return a pointer to a static dummy listener instead. + + if (players[displayplayer].mo != NULL) + { + return players[displayplayer].mo; + } + else + { + dummy_listener.x = 0; + dummy_listener.y = 0; + dummy_listener.z = 0; + + return (mobj_t *) &dummy_listener; + } +} + +//========================================================================== +// +// S_StartSoundAtVolume +// +//========================================================================== + +void S_StartSoundAtVolume(mobj_t * origin, int sound_id, int volume) +{ + mobj_t *listener; + int dist, vol; + int i; + int priority; + int sep; + int angle; + int absx; + int absy; + + static int sndcount = 0; + int chan; + + if (sound_id == 0 || snd_MaxVolume == 0) + return; + + listener = GetSoundListener(); + + if (origin == NULL) + { + origin = listener; + } + if (volume == 0) + { + return; + } + + // calculate the distance before other stuff so that we can throw out + // sounds that are beyond the hearing range. + absx = abs(origin->x - listener->x); + absy = abs(origin->y - listener->y); + dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); + dist >>= FRACBITS; + if (dist >= MAX_SND_DIST) + { + return; // sound is beyond the hearing range... + } + if (dist < 0) + { + dist = 0; + } + priority = S_sfx[sound_id].priority; + priority *= (PRIORITY_MAX_ADJUST - (dist / DIST_ADJUST)); + #if 0 + // TODO + if (!S_StopSoundID(sound_id, priority)) + { + return; // other sounds have greater priority + } + #endif + for (i = 0; i < snd_Channels; i++) + { + // The origin pointer may point to an object of type degenmobj_t + // (i.e. sector_t.soundorg and polyobj_t.startSpot) which does not have + // a player element. Thus the origin->player pointer may point to + // random memory which most likely evaluates to true. + if (origin->thinker.function == P_DegenMobjThinker || origin->player) + { + i = snd_Channels; + break; // let the player have more than one sound. + } + if (origin == Channel[i].mo) + { // only allow other mobjs one sound + S_StopSound(Channel[i].mo); + break; + } + } + if (i >= snd_Channels) + { + for (i = 0; i < snd_Channels; i++) + { + if (Channel[i].mo == NULL) + { + break; + } + } + if (i >= snd_Channels) + { + // look for a lower priority sound to replace. + sndcount++; + if (sndcount >= snd_Channels) + { + sndcount = 0; + } + for (chan = 0; chan < snd_Channels; chan++) + { + i = (sndcount + chan) % snd_Channels; + if (priority >= Channel[i].priority) + { + chan = -1; //denote that sound should be replaced. + break; + } + } + if (chan != -1) + { + return; //no free channels. + } + else //replace the lower priority sound. + { + if (Channel[i].handle) + { + if (I_SoundIsPlaying(Channel[i].handle)) + { + I_StopSound(Channel[i].handle); + } + if (S_sfx[Channel[i].sound_id].usefulness > 0) + { + S_sfx[Channel[i].sound_id].usefulness--; + } + } + } + } + } + + Channel[i].mo = origin; + + vol = (SoundCurve[dist] * (snd_MaxVolume * 8) * volume) >> 14; + if (origin == listener) + { + sep = 128; +// vol = (volume*(snd_MaxVolume+1)*8)>>7; + } + else + { + angle = R_PointToAngle2(listener->x, + listener->y, + Channel[i].mo->x, Channel[i].mo->y); + angle = (angle - viewangle) >> 24; + sep = angle * 2 - 128; + if (sep < 64) + sep = -sep; + if (sep > 192) + sep = 512 - sep; +// vol = SoundCurve[dist]; + } + + // if the sfxinfo_t is marked as 'can be pitch shifted' + if (S_sfx[sound_id].pitch) + { + Channel[i].pitch = (byte) (NORM_PITCH + (M_Random() & 7) - (M_Random() & 7)); + } + else + { + Channel[i].pitch = NORM_PITCH; + } + + if (S_sfx[sound_id].lumpnum == 0) + { + S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]); + } + + Channel[i].handle = I_StartSound(&S_sfx[sound_id], + i, + vol, + sep, + Channel[i].pitch); + Channel[i].sound_id = sound_id; + Channel[i].priority = priority; + Channel[i].volume = volume; + if (S_sfx[sound_id].usefulness < 0) + { + S_sfx[sound_id].usefulness = 1; + } + else + { + S_sfx[sound_id].usefulness++; + } +} + +//========================================================================== +// +// S_StopSoundID +// +//========================================================================== + +boolean S_StopSoundID(int sound_id, int priority) +{ + int i; + int lp; //least priority + int found; + + if (S_sfx[sound_id].numchannels == -1) + { + return (true); + } + lp = -1; //denote the argument sound_id + found = 0; + for (i = 0; i < snd_Channels; i++) + { + if (Channel[i].sound_id == sound_id && Channel[i].mo) + { + found++; //found one. Now, should we replace it?? + if (priority >= Channel[i].priority) + { // if we're gonna kill one, then this'll be it + lp = i; + priority = Channel[i].priority; + } + } + } + if (found < S_sfx[sound_id].numchannels) + { + return (true); + } + else if (lp == -1) + { + return (false); // don't replace any sounds + } + if (Channel[lp].handle) + { + if (I_SoundIsPlaying(Channel[lp].handle)) + { + I_StopSound(Channel[lp].handle); + } + if (S_sfx[Channel[lp].sound_id].usefulness > 0) + { + S_sfx[Channel[lp].sound_id].usefulness--; + } + Channel[lp].mo = NULL; + } + return (true); +} + +//========================================================================== +// +// S_StopSound +// +//========================================================================== + +void S_StopSound(mobj_t * origin) +{ + int i; + + for (i = 0; i < snd_Channels; i++) + { + if (Channel[i].mo == origin) + { + I_StopSound(Channel[i].handle); + if (S_sfx[Channel[i].sound_id].usefulness > 0) + { + S_sfx[Channel[i].sound_id].usefulness--; + } + Channel[i].handle = 0; + Channel[i].mo = NULL; + } + } +} + +//========================================================================== +// +// S_StopAllSound +// +//========================================================================== + +void S_StopAllSound(void) +{ + int i; + + //stop all sounds + for (i = 0; i < snd_Channels; i++) + { + if (Channel[i].handle) + { + S_StopSound(Channel[i].mo); + } + } + memset(Channel, 0, 8 * sizeof(channel_t)); +} + +//========================================================================== +// +// S_SoundLink +// +//========================================================================== + +void S_SoundLink(mobj_t * oldactor, mobj_t * newactor) +{ + int i; + + for (i = 0; i < snd_Channels; i++) + { + if (Channel[i].mo == oldactor) + Channel[i].mo = newactor; + } +} + +//========================================================================== +// +// S_PauseSound +// +//========================================================================== + +void S_PauseSound(void) +{ + if (cdmusic) + { + I_CDMusStop(); + } + else + { + I_PauseSong(); + } +} + +//========================================================================== +// +// S_ResumeSound +// +//========================================================================== + +void S_ResumeSound(void) +{ + if (cdmusic) + { + I_CDMusResume(); + } + else + { + I_ResumeSong(); + } +} + +//========================================================================== +// +// S_UpdateSounds +// +//========================================================================== + +void S_UpdateSounds(mobj_t * listener) +{ + int i, dist, vol; + int angle; + int sep; + int priority; + int absx; + int absy; + + I_UpdateSound(); + + // If we are looping a CD track, we need to check if it has + // finished playing and needs to restart. + if (cdmusic && ShouldRestartCDTrack()) + { + StartCDTrack(cd_current_track, true); + } + + if (snd_MaxVolume == 0) + { + return; + } + + // Update any Sequences + SN_UpdateActiveSequences(); + + for (i = 0; i < snd_Channels; i++) + { + if (!Channel[i].handle || S_sfx[Channel[i].sound_id].usefulness == -1) + { + continue; + } + if (!I_SoundIsPlaying(Channel[i].handle)) + { + if (S_sfx[Channel[i].sound_id].usefulness > 0) + { + S_sfx[Channel[i].sound_id].usefulness--; + } + Channel[i].handle = 0; + Channel[i].mo = NULL; + Channel[i].sound_id = 0; + } + if (Channel[i].mo == NULL || Channel[i].sound_id == 0 + || Channel[i].mo == listener || listener == NULL) + { + continue; + } + else + { + absx = abs(Channel[i].mo->x - listener->x); + absy = abs(Channel[i].mo->y - listener->y); + dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); + dist >>= FRACBITS; + + if (dist >= MAX_SND_DIST) + { + S_StopSound(Channel[i].mo); + continue; + } + if (dist < 0) + { + dist = 0; + } + //vol = SoundCurve[dist]; + vol = + (SoundCurve[dist] * (snd_MaxVolume * 8) * + Channel[i].volume) >> 14; + if (Channel[i].mo == listener) + { + sep = 128; + } + else + { + angle = R_PointToAngle2(listener->x, listener->y, + Channel[i].mo->x, Channel[i].mo->y); + angle = (angle - viewangle) >> 24; + sep = angle * 2 - 128; + if (sep < 64) + sep = -sep; + if (sep > 192) + sep = 512 - sep; + } + I_UpdateSoundParams(i, vol, sep); + priority = S_sfx[Channel[i].sound_id].priority; + priority *= PRIORITY_MAX_ADJUST - (dist / DIST_ADJUST); + Channel[i].priority = priority; + } + } +} + +//========================================================================== +// +// S_Init +// +//========================================================================== + +void S_Init(void) +{ + I_SetOPLDriverVer(opl_doom2_1_666); + SoundCurve = W_CacheLumpName("SNDCURVE", PU_STATIC); +// SoundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL); + + if (snd_Channels > 8) + { + snd_Channels = 8; + } + I_SetMusicVolume(snd_MusicVolume * 8); + + I_AtExit(S_ShutDown, true); + + // Hexen defaults to pitch-shifting on + if (snd_pitchshift == -1) + { + snd_pitchshift = 1; + } + + I_PrecacheSounds(S_sfx, NUMSFX); + + // Attempt to setup CD music + if (snd_musicdevice == SNDDEVICE_CD) + { + ST_Message(" Attempting to initialize CD Music: "); + if (!cdrom) + { + cdmusic = (I_CDMusInit() != -1); + } + else + { + // The user is trying to use the cdrom for both game and music + cdmusic = false; + } + + if (cdmusic) + { + ST_Message("initialized.\n"); + } + else + { + ST_Message("failed.\n"); + } + + I_CDMusPrintStartup(); + } +} + +//========================================================================== +// +// S_GetChannelInfo +// +//========================================================================== + +void S_GetChannelInfo(SoundInfo_t * s) +{ + int i; + ChanInfo_t *c; + + s->channelCount = snd_Channels; + s->musicVolume = snd_MusicVolume; + s->soundVolume = snd_MaxVolume; + for (i = 0; i < snd_Channels; i++) + { + c = &s->chan[i]; + c->id = Channel[i].sound_id; + c->priority = Channel[i].priority; + c->name = S_sfx[c->id].name; + c->mo = Channel[i].mo; + + if (c->mo != NULL) + { + c->distance = P_AproxDistance(c->mo->x - viewx, c->mo->y - viewy) + >> FRACBITS; + } + else + { + c->distance = 0; + } + } +} + +//========================================================================== +// +// S_GetSoundPlayingInfo +// +//========================================================================== + +boolean S_GetSoundPlayingInfo(mobj_t * mobj, int sound_id) +{ + int i; + + for (i = 0; i < snd_Channels; i++) + { + if (Channel[i].sound_id == sound_id && Channel[i].mo == mobj) + { + if (I_SoundIsPlaying(Channel[i].handle)) + { + return true; + } + } + } + return false; +} + +//========================================================================== +// +// S_SetMusicVolume +// +//========================================================================== + +void S_SetMusicVolume(void) +{ + if (cdmusic) + { + I_CDMusSetVolume(snd_MusicVolume * 16); // 0-255 + } + else + { + I_SetMusicVolume(snd_MusicVolume * 8); + } + if (snd_MusicVolume == 0) + { + if (!cdmusic) + { + I_PauseSong(); + } + MusicPaused = true; + } + else if (MusicPaused) + { + if (!cdmusic) + { + I_ResumeSong(); + } + MusicPaused = false; + } +} + +//========================================================================== +// +// S_ShutDown +// +//========================================================================== + +void S_ShutDown(void) +{ + I_StopSong(); + I_UnRegisterSong(RegisteredSong); + I_ShutdownSound(); + if (cdmusic) + { + I_CDMusStop(); + } +} + +//========================================================================== +// +// S_InitScript +// +//========================================================================== + +void S_InitScript(void) +{ + int i; + + SC_OpenLump("sndinfo"); + + while (SC_GetString()) + { + if (*sc_String == '$') + { + if (!strcasecmp(sc_String, "$ARCHIVEPATH")) + { + SC_MustGetString(); + } + else if (!strcasecmp(sc_String, "$MAP")) + { + SC_MustGetNumber(); + SC_MustGetString(); + if (sc_Number) + { + P_PutMapSongLump(sc_Number, sc_String); + } + } + continue; + } + else + { + for (i = 0; i < NUMSFX; i++) + { + if (!strcmp(S_sfx[i].tagname, sc_String)) + { + SC_MustGetString(); + if (*sc_String != '?') + { + M_StringCopy(S_sfx[i].name, sc_String, + sizeof(S_sfx[i].name)); + } + else + { + M_StringCopy(S_sfx[i].name, "default", + sizeof(S_sfx[i].name)); + } + break; + } + } + if (i == NUMSFX) + { + SC_MustGetString(); + } + } + } + SC_Close(); + + for (i = 0; i < NUMSFX; i++) + { + if (!strcmp(S_sfx[i].name, "")) + { + M_StringCopy(S_sfx[i].name, "default", sizeof(S_sfx[i].name)); + } + } +} + diff --git a/games/NXDoom/src/hexen/s_sound.h b/games/NXDoom/src/hexen/s_sound.h new file mode 100644 index 00000000000..f8284be7787 --- /dev/null +++ b/games/NXDoom/src/hexen/s_sound.h @@ -0,0 +1,94 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __S_SOUND__ +#define __S_SOUND__ + +/* +typedef struct +{ + char name[8]; + int p1; +} musicinfo_t; +*/ + +/* +typedef struct sfxinfo_s +{ + char tagName[32]; + char lumpname[12]; // Only need 9 bytes, but padded out to be dword aligned + //struct sfxinfo_s *link; // Make alias for another sound + int priority; // Higher priority takes precendence + int usefulness; // Determines when a sound should be cached out + void *snd_ptr; + int lumpnum; + int numchannels; // total number of channels a sound type may occupy + boolean changePitch; +} sfxinfo_t; +*/ + +typedef struct +{ + mobj_t *mo; + int sound_id; + int handle; + int volume; + int pitch; + int priority; +} channel_t; + +typedef struct +{ + int id; + unsigned short priority; + char *name; + mobj_t *mo; + int distance; +} ChanInfo_t; + +typedef struct +{ + int channelCount; + int musicVolume; + int soundVolume; + ChanInfo_t chan[8]; +} SoundInfo_t; + +extern int snd_MaxVolume; +extern int snd_MusicVolume; +extern int snd_Channels; +extern boolean cdmusic; + +void S_Start(void); +void S_StartSound(mobj_t * origin, int sound_id); +int S_GetSoundID(char *name); +void S_StartSoundAtVolume(mobj_t * origin, int sound_id, int volume); +void S_StopSound(mobj_t * origin); +void S_StopAllSound(void); +void S_PauseSound(void); +void S_ResumeSound(void); +void S_UpdateSounds(mobj_t * listener); +void S_StartSong(int song, boolean loop); +void S_StartSongName(const char *songLump, boolean loop); +void S_Init(void); +void S_GetChannelInfo(SoundInfo_t * s); +void S_SetMusicVolume(void); +boolean S_GetSoundPlayingInfo(mobj_t * mobj, int sound_id); +boolean S_StartCustomCDTrack(int tracknum); +int S_GetCurrentCDTrack(void); + +#endif diff --git a/games/NXDoom/src/hexen/sb_bar.c b/games/NXDoom/src/hexen/sb_bar.c new file mode 100644 index 00000000000..fa94d59a3a1 --- /dev/null +++ b/games/NXDoom/src/hexen/sb_bar.c @@ -0,0 +1,2000 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "i_cdmus.h" +#include "i_video.h" +#include "m_bbox.h" +#include "m_cheat.h" +#include "m_misc.h" +#include "p_local.h" +#include "s_sound.h" +#include "v_video.h" +#include "i_swap.h" +#include "am_map.h" + + +// TYPES ------------------------------------------------------------------- + +typedef struct Cheat_s +{ + void (*func) (player_t * player, struct Cheat_s * cheat); + cheatseq_t *seq; +} Cheat_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void DrawSoundInfo(void); +static void DrINumber(signed int val, int x, int y); +static void DrRedINumber(signed int val, int x, int y); +static void DrBNumber(signed int val, int x, int y); +static void DrawCommonBar(void); +static void DrawMainBar(void); +static void DrawInventoryBar(void); +static void DrawKeyBar(void); +static void DrawWeaponPieces(void); +static void DrawFullScreenStuff(void); +static void DrawAnimatedIcons(void); +static boolean HandleCheats(byte key); +static boolean CheatAddKey(Cheat_t * cheat, byte key, boolean * eat); +static void CheatGodFunc(player_t * player, Cheat_t * cheat); +static void CheatNoClipFunc(player_t * player, Cheat_t * cheat); +static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat); +static void CheatHealthFunc(player_t * player, Cheat_t * cheat); +static void CheatKeysFunc(player_t * player, Cheat_t * cheat); +static void CheatSoundFunc(player_t * player, Cheat_t * cheat); +static void CheatTickerFunc(player_t * player, Cheat_t * cheat); +static void CheatArtifactAllFunc(player_t * player, Cheat_t * cheat); +static void CheatPuzzleFunc(player_t * player, Cheat_t * cheat); +static void CheatWarpFunc(player_t * player, Cheat_t * cheat); +static void CheatPigFunc(player_t * player, Cheat_t * cheat); +static void CheatMassacreFunc(player_t * player, Cheat_t * cheat); +static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat); +static void CheatQuickenFunc1(player_t * player, Cheat_t * cheat); +static void CheatQuickenFunc2(player_t * player, Cheat_t * cheat); +static void CheatQuickenFunc3(player_t * player, Cheat_t * cheat); +static void CheatClassFunc1(player_t * player, Cheat_t * cheat); +static void CheatClassFunc2(player_t * player, Cheat_t * cheat); +static void CheatInitFunc(player_t * player, Cheat_t * cheat); +static void CheatVersionFunc(player_t * player, Cheat_t * cheat); +static void CheatDebugFunc(player_t * player, Cheat_t * cheat); +static void CheatScriptFunc1(player_t * player, Cheat_t * cheat); +static void CheatScriptFunc2(player_t * player, Cheat_t * cheat); +static void CheatScriptFunc3(player_t * player, Cheat_t * cheat); +static void CheatRevealFunc(player_t * player, Cheat_t * cheat); +static void CheatTrackFunc1(player_t * player, Cheat_t * cheat); +static void CheatTrackFunc2(player_t * player, Cheat_t * cheat); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DECLARATIONS ------------------------------------------------ + +boolean DebugSound; // Debug flag for displaying sound info +boolean inventory; +int curpos; +int inv_ptr; +int ArtifactFlash; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int DisplayTicker = 0; +static int HealthMarker; +//static int ChainWiggle; +static player_t *CPlayer; +static int SpinFlylump; +static int SpinMinotaurLump; +static int SpinSpeedLump; +static int SpinDefenseLump; + +static int FontBNumBase; +static int PlayPalette; + +static patch_t *PatchH2BAR; +static patch_t *PatchH2TOP; +static patch_t *PatchLFEDGE; +static patch_t *PatchRTEDGE; +static patch_t *PatchARMCLEAR; +static patch_t *PatchARTICLEAR; +static patch_t *PatchMANACLEAR; +static patch_t *PatchKILLS; +static patch_t *PatchMANAVIAL1; +static patch_t *PatchMANAVIAL2; +static patch_t *PatchMANAVIALDIM1; +static patch_t *PatchMANAVIALDIM2; +static patch_t *PatchMANADIM1; +static patch_t *PatchMANADIM2; +static patch_t *PatchMANABRIGHT1; +static patch_t *PatchMANABRIGHT2; +static patch_t *PatchCHAIN; +static patch_t *PatchSTATBAR; +static patch_t *PatchKEYBAR; +static patch_t *PatchLIFEGEM; +static patch_t *PatchSELECTBOX; +static patch_t *PatchINumbers[10]; +static patch_t *PatchNEGATIVE; +static patch_t *PatchSmNumbers[10]; +static patch_t *PatchINVBAR; +static patch_t *PatchWEAPONSLOT; +static patch_t *PatchWEAPONFULL; +static patch_t *PatchPIECE1; +static patch_t *PatchPIECE2; +static patch_t *PatchPIECE3; +static patch_t *PatchINVLFGEM1; +static patch_t *PatchINVLFGEM2; +static patch_t *PatchINVRTGEM1; +static patch_t *PatchINVRTGEM2; + +// Toggle god mode +cheatseq_t CheatGodSeq = CHEAT("satan", 0); + +// Toggle no clipping mode +cheatseq_t CheatNoClipSeq = CHEAT("casper", 0); + +// Get all weapons and mana +cheatseq_t CheatWeaponsSeq = CHEAT("nra", 0); + +// Get full health +cheatseq_t CheatHealthSeq = CHEAT("clubmed", 0); + +// Get all keys +cheatseq_t CheatKeysSeq = CHEAT("locksmith", 0); + +// Toggle sound debug info +cheatseq_t CheatSoundSeq = CHEAT("noise", 0); + +// Toggle ticker +cheatseq_t CheatTickerSeq = CHEAT("ticker", 0); + +// Get all artifacts +cheatseq_t CheatArtifactAllSeq = CHEAT("indiana", 0); + +// Get all puzzle pieces +cheatseq_t CheatPuzzleSeq = CHEAT("sherlock", 0); + +// Warp to new level +cheatseq_t CheatWarpSeq = CHEAT("visit", 2); + +// Become a pig +cheatseq_t CheatPigSeq = CHEAT("deliverance", 0); + +// Kill all monsters +cheatseq_t CheatMassacreSeq = CHEAT("butcher", 0); + +cheatseq_t CheatIDKFASeq = CHEAT("conan", 0); + +cheatseq_t CheatQuickenSeq1 = CHEAT("martek", 0); + +cheatseq_t CheatQuickenSeq2 = CHEAT("martekmartek", 0); + +cheatseq_t CheatQuickenSeq3 = CHEAT("martekmartekmartek", 0); + +// New class +cheatseq_t CheatClass1Seq = CHEAT("shadowcaster", 0); + +cheatseq_t CheatClass2Seq = CHEAT("shadowcaster", 1); + +cheatseq_t CheatInitSeq = CHEAT("init", 0); + +cheatseq_t CheatVersionSeq = CHEAT("mrjones", 0); + +cheatseq_t CheatDebugSeq = CHEAT("where", 0); + +cheatseq_t CheatScriptSeq1 = CHEAT("puke", 0); + +cheatseq_t CheatScriptSeq2 = CHEAT("puke", 1); + +cheatseq_t CheatScriptSeq3 = CHEAT("puke", 2); + +cheatseq_t CheatRevealSeq = CHEAT("mapsco", 0); + +cheatseq_t CheatTrackSeq1 = CHEAT("`", 0); + +cheatseq_t CheatTrackSeq2 = CHEAT("`", 2); + +static Cheat_t Cheats[] = { + {CheatTrackFunc1, &CheatTrackSeq1}, + {CheatTrackFunc2, &CheatTrackSeq2}, + {CheatGodFunc, &CheatGodSeq}, + {CheatNoClipFunc, &CheatNoClipSeq}, + {CheatWeaponsFunc, &CheatWeaponsSeq}, + {CheatHealthFunc, &CheatHealthSeq}, + {CheatKeysFunc, &CheatKeysSeq}, + {CheatSoundFunc, &CheatSoundSeq}, + {CheatTickerFunc, &CheatTickerSeq}, + {CheatArtifactAllFunc, &CheatArtifactAllSeq}, + {CheatPuzzleFunc, &CheatPuzzleSeq}, + {CheatWarpFunc, &CheatWarpSeq}, + {CheatPigFunc, &CheatPigSeq}, + {CheatMassacreFunc, &CheatMassacreSeq}, + {CheatIDKFAFunc, &CheatIDKFASeq}, + {CheatQuickenFunc1, &CheatQuickenSeq1}, + {CheatQuickenFunc2, &CheatQuickenSeq2}, + {CheatQuickenFunc3, &CheatQuickenSeq3}, + {CheatClassFunc1, &CheatClass1Seq}, + {CheatClassFunc2, &CheatClass2Seq}, + {CheatInitFunc, &CheatInitSeq}, + {CheatVersionFunc, &CheatVersionSeq}, + {CheatDebugFunc, &CheatDebugSeq}, + {CheatScriptFunc1, &CheatScriptSeq1}, + {CheatScriptFunc2, &CheatScriptSeq2}, + {CheatScriptFunc3, &CheatScriptSeq3}, + {CheatRevealFunc, &CheatRevealSeq}, +}; + +#define SET_CHEAT(cheat, seq) \ + { memcpy(cheat.sequence, seq, sizeof(seq)); \ + cheat.sequence_len = sizeof(seq) - 1; } + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// SB_Init +// +//========================================================================== + +void SB_Init(void) +{ + int i; + int startLump; + + PatchH2BAR = W_CacheLumpName("H2BAR", PU_STATIC); + PatchH2TOP = W_CacheLumpName("H2TOP", PU_STATIC); + PatchINVBAR = W_CacheLumpName("INVBAR", PU_STATIC); + PatchLFEDGE = W_CacheLumpName("LFEDGE", PU_STATIC); + PatchRTEDGE = W_CacheLumpName("RTEDGE", PU_STATIC); + PatchSTATBAR = W_CacheLumpName("STATBAR", PU_STATIC); + PatchKEYBAR = W_CacheLumpName("KEYBAR", PU_STATIC); + PatchSELECTBOX = W_CacheLumpName("SELECTBOX", PU_STATIC); + PatchARTICLEAR = W_CacheLumpName("ARTICLS", PU_STATIC); + PatchARMCLEAR = W_CacheLumpName("ARMCLS", PU_STATIC); + PatchMANACLEAR = W_CacheLumpName("MANACLS", PU_STATIC); + PatchMANAVIAL1 = W_CacheLumpName("MANAVL1", PU_STATIC); + PatchMANAVIAL2 = W_CacheLumpName("MANAVL2", PU_STATIC); + PatchMANAVIALDIM1 = W_CacheLumpName("MANAVL1D", PU_STATIC); + PatchMANAVIALDIM2 = W_CacheLumpName("MANAVL2D", PU_STATIC); + PatchMANADIM1 = W_CacheLumpName("MANADIM1", PU_STATIC); + PatchMANADIM2 = W_CacheLumpName("MANADIM2", PU_STATIC); + PatchMANABRIGHT1 = W_CacheLumpName("MANABRT1", PU_STATIC); + PatchMANABRIGHT2 = W_CacheLumpName("MANABRT2", PU_STATIC); + PatchINVLFGEM1 = W_CacheLumpName("invgeml1", PU_STATIC); + PatchINVLFGEM2 = W_CacheLumpName("invgeml2", PU_STATIC); + PatchINVRTGEM1 = W_CacheLumpName("invgemr1", PU_STATIC); + PatchINVRTGEM2 = W_CacheLumpName("invgemr2", PU_STATIC); + +// PatchCHAINBACK = W_CacheLumpName("CHAINBACK", PU_STATIC); + startLump = W_GetNumForName("IN0"); + for (i = 0; i < 10; i++) + { + PatchINumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); + } + PatchNEGATIVE = W_CacheLumpName("NEGNUM", PU_STATIC); + FontBNumBase = W_GetNumForName("FONTB16"); + startLump = W_GetNumForName("SMALLIN0"); + for (i = 0; i < 10; i++) + { + PatchSmNumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); + } + PlayPalette = W_GetNumForName("PLAYPAL"); + SpinFlylump = W_GetNumForName("SPFLY0"); + SpinMinotaurLump = W_GetNumForName("SPMINO0"); + SpinSpeedLump = W_GetNumForName("SPBOOT0"); + SpinDefenseLump = W_GetNumForName("SPSHLD0"); + + if (deathmatch) + { + PatchKILLS = W_CacheLumpName("KILLS", PU_STATIC); + } + SB_SetClassData(); + + if (gamemode == shareware) + { + SET_CHEAT(CheatGodSeq, "bgokey"); + SET_CHEAT(CheatNoClipSeq, "rjohnson"); + SET_CHEAT(CheatWeaponsSeq, "crhinehart"); + SET_CHEAT(CheatHealthSeq,"sgurno"); + SET_CHEAT(CheatKeysSeq, "mraymondjudy"); + SET_CHEAT(CheatSoundSeq, "kschilder"); + SET_CHEAT(CheatTickerSeq, "rrettenmund"); + SET_CHEAT(CheatArtifactAllSeq, "braffel"); + SET_CHEAT(CheatPuzzleSeq, "tmoore"); + SET_CHEAT(CheatWarpSeq, "bpelletier"); + SET_CHEAT(CheatPigSeq, "ebiessman"); + SET_CHEAT(CheatMassacreSeq, "cstika"); + SET_CHEAT(CheatIDKFASeq, "rambo"); + SET_CHEAT(CheatQuickenSeq1, "quicken"); + SET_CHEAT(CheatQuickenSeq2, "quickenquicken"); + SET_CHEAT(CheatQuickenSeq3, "quickenquickenquicken"); + SET_CHEAT(CheatClass1Seq, "plipo"); + SET_CHEAT(CheatClass2Seq, "plipo"); + SET_CHEAT(CheatVersionSeq, "pmacarther"); + SET_CHEAT(CheatDebugSeq, "jsumwalt"); + SET_CHEAT(CheatScriptSeq1, "mwagabaza"); + SET_CHEAT(CheatScriptSeq2, "mwagabaza"); + SET_CHEAT(CheatScriptSeq3, "mwagabaza"); + SET_CHEAT(CheatRevealSeq, "reveal"); + } +} + +//========================================================================== +// +// SB_SetClassData +// +//========================================================================== + +void SB_SetClassData(void) +{ + int class; + + class = PlayerClass[consoleplayer]; // original player class (not pig) + PatchWEAPONSLOT = W_CacheLumpNum(W_GetNumForName("wpslot0") + + class, PU_STATIC); + PatchWEAPONFULL = W_CacheLumpNum(W_GetNumForName("wpfull0") + + class, PU_STATIC); + PatchPIECE1 = W_CacheLumpNum(W_GetNumForName("wpiecef1") + + class, PU_STATIC); + PatchPIECE2 = W_CacheLumpNum(W_GetNumForName("wpiecef2") + + class, PU_STATIC); + PatchPIECE3 = W_CacheLumpNum(W_GetNumForName("wpiecef3") + + class, PU_STATIC); + PatchCHAIN = W_CacheLumpNum(W_GetNumForName("chain") + class, PU_STATIC); + if (!netgame) + { // single player game uses red life gem (the second gem) + PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("lifegem") + + maxplayers * class + 1, PU_STATIC); + } + else + { + PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("lifegem") + + maxplayers * class + consoleplayer, + PU_STATIC); + } + SB_state = -1; + UpdateState |= I_FULLSCRN; +} + +//========================================================================== +// +// SB_Ticker +// +//========================================================================== + +void SB_Ticker(void) +{ + int delta; + int curHealth; + + curHealth = players[consoleplayer].mo->health; + if (curHealth < 0) + { + curHealth = 0; + } + if (curHealth < HealthMarker) + { + delta = (HealthMarker - curHealth) >> 2; + if (delta < 1) + { + delta = 1; + } + else if (delta > 6) + { + delta = 6; + } + HealthMarker -= delta; + } + else if (curHealth > HealthMarker) + { + delta = (curHealth - HealthMarker) >> 2; + if (delta < 1) + { + delta = 1; + } + else if (delta > 6) + { + delta = 6; + } + HealthMarker += delta; + } +} + +//========================================================================== +// +// DrINumber +// +// Draws a three digit number. +// +//========================================================================== + +static void DrINumber(signed int val, int x, int y) +{ + patch_t *patch; + int oldval; + + oldval = val; + if (val < 0) + { + val = -val; + if (val > 99) + { + val = 99; + } + if (val > 9) + { + patch = PatchINumbers[val / 10]; + V_DrawPatch(x + 8, y, patch); + V_DrawPatch(x, y, PatchNEGATIVE); + } + else + { + V_DrawPatch(x + 8, y, PatchNEGATIVE); + } + val = val % 10; + patch = PatchINumbers[val]; + V_DrawPatch(x + 16, y, patch); + return; + } + if (val > 99) + { + patch = PatchINumbers[val / 100]; + V_DrawPatch(x, y, patch); + } + val = val % 100; + if (val > 9 || oldval > 99) + { + patch = PatchINumbers[val / 10]; + V_DrawPatch(x + 8, y, patch); + } + val = val % 10; + patch = PatchINumbers[val]; + V_DrawPatch(x + 16, y, patch); +} + +//========================================================================== +// +// DrRedINumber +// +// Draws a three digit number using the red font +// +//========================================================================== + +static void DrRedINumber(signed int val, int x, int y) +{ + patch_t *patch; + int oldval; + + oldval = val; + if (val < 0) + { + val = 0; + } + if (val > 99) + { + patch = + W_CacheLumpNum(W_GetNumForName("inred0") + val / 100, PU_CACHE); + V_DrawPatch(x, y, patch); + } + val = val % 100; + if (val > 9 || oldval > 99) + { + patch = + W_CacheLumpNum(W_GetNumForName("inred0") + val / 10, PU_CACHE); + V_DrawPatch(x + 8, y, patch); + } + val = val % 10; + patch = W_CacheLumpNum(W_GetNumForName("inred0") + val, PU_CACHE); + V_DrawPatch(x + 16, y, patch); +} + +//========================================================================== +// +// DrBNumber +// +// Draws a three digit number using FontB +// +//========================================================================== + +static void DrBNumber(signed int val, int x, int y) +{ + patch_t *patch; + int xpos; + int oldval; + + oldval = val; + xpos = x; + if (val < 0) + { + val = 0; + } + if (val > 99) + { + patch = W_CacheLumpNum(FontBNumBase + val / 100, PU_CACHE); + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + } + val = val % 100; + xpos += 12; + if (val > 9 || oldval > 99) + { + patch = W_CacheLumpNum(FontBNumBase + val / 10, PU_CACHE); + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); + } + val = val % 10; + xpos += 12; + patch = W_CacheLumpNum(FontBNumBase + val, PU_CACHE); + V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); +} + +//========================================================================== +// +// DrSmallNumber +// +// Draws a small two digit number. +// +//========================================================================== + +static void DrSmallNumber(int val, int x, int y) +{ + patch_t *patch; + + if (val <= 0) + { + return; + } + if (val > 999) + { + val %= 1000; + } + if (val > 99) + { + patch = PatchSmNumbers[val / 100]; + V_DrawPatch(x, y, patch); + patch = PatchSmNumbers[(val % 100) / 10]; + V_DrawPatch(x + 4, y, patch); + } + else if (val > 9) + { + patch = PatchSmNumbers[val / 10]; + V_DrawPatch(x + 4, y, patch); + } + val %= 10; + patch = PatchSmNumbers[val]; + V_DrawPatch(x + 8, y, patch); +} + +/* +//========================================================================== +// +// ShadeLine +// +//========================================================================== + +static void ShadeLine(int x, int y, int height, int shade) +{ + byte *dest; + byte *shades; + + shades = colormaps+9*256+shade*2*256; + dest = I_VideoBuffer+y*SCREENWIDTH+x; + while(height--) + { + *(dest) = *(shades+*dest); + dest += SCREENWIDTH; + } +} + +//========================================================================== +// +// ShadeChain +// +//========================================================================== + +static void ShadeChain(void) +{ + int i; + + for(i = 0; i < 16; i++) + { + ShadeLine(277+i, 190, 10, i/2); + ShadeLine(19+i, 190, 10, 7-(i/2)); + } +} +*/ + +//========================================================================== +// +// DrawSoundInfo +// +// Displays sound debugging information. +// +//========================================================================== + +static void DrawSoundInfo(void) +{ + int i; + SoundInfo_t s; + ChanInfo_t *c; + char text[32]; + int x; + int y; + int xPos[7] = { 1, 75, 112, 156, 200, 230, 260 }; + + if (leveltime & 16) + { + MN_DrTextA("*** SOUND DEBUG INFO ***", xPos[0], 20); + } + S_GetChannelInfo(&s); + if (s.channelCount == 0) + { + return; + } + x = 0; + MN_DrTextA("NAME", xPos[x++], 30); + MN_DrTextA("MO.T", xPos[x++], 30); + MN_DrTextA("MO.X", xPos[x++], 30); + MN_DrTextA("MO.Y", xPos[x++], 30); + MN_DrTextA("ID", xPos[x++], 30); + MN_DrTextA("PRI", xPos[x++], 30); + MN_DrTextA("DIST", xPos[x++], 30); + for (i = 0; i < s.channelCount; i++) + { + c = &s.chan[i]; + x = 0; + y = 40 + i * 10; + if (c->mo == NULL) + { // Channel is unused + MN_DrTextA("------", xPos[0], y); + continue; + } + M_snprintf(text, sizeof(text), "%s", c->name); + M_ForceUppercase(text); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->mo->type); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", (int) c->id); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->priority); + MN_DrTextA(text, xPos[x++], y); + M_snprintf(text, sizeof(text), "%d", c->distance); + MN_DrTextA(text, xPos[x++], y); + } + UpdateState |= I_FULLSCRN; + BorderNeedRefresh = true; +} + +//========================================================================== +// +// SB_Drawer +// +//========================================================================== + +char patcharti[][10] = { + {"ARTIBOX"}, // none + {"ARTIINVU"}, // invulnerability + {"ARTIPTN2"}, // health + {"ARTISPHL"}, // superhealth + {"ARTIHRAD"}, // healing radius + {"ARTISUMN"}, // summon maulator + {"ARTITRCH"}, // torch + {"ARTIPORK"}, // egg + {"ARTISOAR"}, // fly + {"ARTIBLST"}, // blast radius + {"ARTIPSBG"}, // poison bag + {"ARTITELO"}, // teleport other + {"ARTISPED"}, // speed + {"ARTIBMAN"}, // boost mana + {"ARTIBRAC"}, // boost armor + {"ARTIATLP"}, // teleport + {"ARTISKLL"}, // arti_puzzskull + {"ARTIBGEM"}, // arti_puzzgembig + {"ARTIGEMR"}, // arti_puzzgemred + {"ARTIGEMG"}, // arti_puzzgemgreen1 + {"ARTIGMG2"}, // arti_puzzgemgreen2 + {"ARTIGEMB"}, // arti_puzzgemblue1 + {"ARTIGMB2"}, // arti_puzzgemblue2 + {"ARTIBOK1"}, // arti_puzzbook1 + {"ARTIBOK2"}, // arti_puzzbook2 + {"ARTISKL2"}, // arti_puzzskull2 + {"ARTIFWEP"}, // arti_puzzfweapon + {"ARTICWEP"}, // arti_puzzcweapon + {"ARTIMWEP"}, // arti_puzzmweapon + {"ARTIGEAR"}, // arti_puzzgear1 + {"ARTIGER2"}, // arti_puzzgear2 + {"ARTIGER3"}, // arti_puzzgear3 + {"ARTIGER4"}, // arti_puzzgear4 +}; + +int SB_state = -1; +static int oldarti = 0; +static int oldartiCount = 0; +static int oldfrags = -9999; +static int oldmana1 = -1; +static int oldmana2 = -1; +static int oldarmor = -1; +static int oldhealth = -1; +static int oldlife = -1; +static int oldpieces = -1; +static int oldweapon = -1; +static int oldkeys = -1; + + +void SB_Drawer(void) +{ + // Sound info debug stuff + if (DebugSound == true) + { + DrawSoundInfo(); + } + CPlayer = &players[consoleplayer]; + if (viewheight == SCREENHEIGHT && !automapactive) + { + DrawFullScreenStuff(); + SB_state = -1; + } + else + { + if (SB_state == -1) + { + V_DrawPatch(0, 134, PatchH2BAR); + oldhealth = -1; + } + DrawCommonBar(); + if (!inventory) + { + if (SB_state != 0) + { + // Main interface + if (!automapactive) + { + V_DrawPatch(38, 162, PatchSTATBAR); + } + else + { + V_DrawPatch(38, 162, PatchKEYBAR); + } + oldarti = 0; + oldmana1 = -1; + oldmana2 = -1; + oldarmor = -1; + oldpieces = -1; + oldfrags = -9999; //can't use -1, 'cuz of negative frags + oldlife = -1; + oldweapon = -1; + oldkeys = -1; + } + if (!automapactive) + { + DrawMainBar(); + } + else + { + DrawKeyBar(); + } + SB_state = 0; + } + else + { + DrawInventoryBar(); + SB_state = 1; + } + } + SB_PaletteFlash(false); + DrawAnimatedIcons(); +} + +//========================================================================== +// +// DrawAnimatedIcons +// +//========================================================================== + +static void DrawAnimatedIcons(void) +{ + int frame; + static boolean hitCenterFrame; + + // Wings of wrath + if (CPlayer->powers[pw_flight]) + { + if (CPlayer->powers[pw_flight] > BLINKTHRESHOLD + || !(CPlayer->powers[pw_flight] & 16)) + { + frame = (leveltime / 3) & 15; + if (CPlayer->mo->flags2 & MF2_FLY) + { + if (hitCenterFrame && (frame != 15 && frame != 0)) + { + V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + 15, + PU_CACHE)); + } + else + { + V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + frame, + PU_CACHE)); + hitCenterFrame = false; + } + } + else + { + if (!hitCenterFrame && (frame != 15 && frame != 0)) + { + V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + frame, + PU_CACHE)); + hitCenterFrame = false; + } + else + { + V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + 15, + PU_CACHE)); + hitCenterFrame = true; + } + } + } + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + + // Speed Boots + if (CPlayer->powers[pw_speed]) + { + if (CPlayer->powers[pw_speed] > BLINKTHRESHOLD + || !(CPlayer->powers[pw_speed] & 16)) + { + frame = (leveltime / 3) & 15; + V_DrawPatch(60, 19, W_CacheLumpNum(SpinSpeedLump + frame, + PU_CACHE)); + } + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + + // Defensive power + if (CPlayer->powers[pw_invulnerability]) + { + if (CPlayer->powers[pw_invulnerability] > BLINKTHRESHOLD + || !(CPlayer->powers[pw_invulnerability] & 16)) + { + frame = (leveltime / 3) & 15; + V_DrawPatch(260, 19, W_CacheLumpNum(SpinDefenseLump + frame, + PU_CACHE)); + } + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } + + // Minotaur Active + if (CPlayer->powers[pw_minotaur]) + { + if (CPlayer->powers[pw_minotaur] > BLINKTHRESHOLD + || !(CPlayer->powers[pw_minotaur] & 16)) + { + frame = (leveltime / 3) & 15; + V_DrawPatch(300, 19, W_CacheLumpNum(SpinMinotaurLump + frame, + PU_CACHE)); + } + BorderTopRefresh = true; + UpdateState |= I_MESSAGES; + } +} + +//========================================================================== +// +// SB_PaletteFlash +// +// Sets the new palette based upon the current values of +// consoleplayer->damagecount and consoleplayer->bonuscount. +// +//========================================================================== + +void SB_PaletteFlash(boolean forceChange) +{ + static int sb_palette = 0; + int palette; + byte *pal; + + if (forceChange) + { + sb_palette = -1; + } + if (gamestate == GS_LEVEL) + { + CPlayer = &players[consoleplayer]; + if (CPlayer->poisoncount) + { + palette = 0; + palette = (CPlayer->poisoncount + 7) >> 3; + if (palette >= NUMPOISONPALS) + { + palette = NUMPOISONPALS - 1; + } + palette += STARTPOISONPALS; + } + else if (CPlayer->damagecount) + { + palette = (CPlayer->damagecount + 7) >> 3; + if (palette >= NUMREDPALS) + { + palette = NUMREDPALS - 1; + } + palette += STARTREDPALS; + } + else if (CPlayer->bonuscount) + { + palette = (CPlayer->bonuscount + 7) >> 3; + if (palette >= NUMBONUSPALS) + { + palette = NUMBONUSPALS - 1; + } + palette += STARTBONUSPALS; + } + else if (CPlayer->mo->flags2 & MF2_ICEDAMAGE) + { // Frozen player + palette = STARTICEPAL; + } + else + { + palette = 0; + } + } + else + { + palette = 0; + } + if (palette != sb_palette) + { + sb_palette = palette; + pal = (byte *) W_CacheLumpNum(PlayPalette, PU_CACHE) + palette * 768; + I_SetPalette(pal); + } +} + +//========================================================================== +// +// DrawCommonBar +// +//========================================================================== + +void DrawCommonBar(void) +{ + int healthPos; + + V_DrawPatch(0, 134, PatchH2TOP); + + if (oldhealth != HealthMarker) + { + oldhealth = HealthMarker; + healthPos = HealthMarker; + if (healthPos < 0) + { + healthPos = 0; + } + if (healthPos > 100) + { + healthPos = 100; + } + V_DrawPatch(28 + (((healthPos * 196) / 100) % 9), 193, PatchCHAIN); + V_DrawPatch(7 + ((healthPos * 11) / 5), 193, PatchLIFEGEM); + V_DrawPatch(0, 193, PatchLFEDGE); + V_DrawPatch(277, 193, PatchRTEDGE); +// ShadeChain(); + UpdateState |= I_STATBAR; + } +} + +//========================================================================== +// +// DrawMainBar +// +//========================================================================== + +void DrawMainBar(void) +{ + int i; + int temp; + patch_t *manaPatch1, *manaPatch2; + patch_t *manaVialPatch1, *manaVialPatch2; + + manaPatch1 = NULL; + manaPatch2 = NULL; + manaVialPatch1 = NULL; + manaVialPatch2 = NULL; + + // Ready artifact + if (ArtifactFlash) + { + V_DrawPatch(144, 160, PatchARTICLEAR); + V_DrawPatch(148, 164, W_CacheLumpNum(W_GetNumForName("useartia") + + ArtifactFlash - 1, PU_CACHE)); + ArtifactFlash--; + oldarti = -1; // so that the correct artifact fills in after the flash + UpdateState |= I_STATBAR; + } + else if (oldarti != CPlayer->readyArtifact + || oldartiCount != CPlayer->inventory[inv_ptr].count) + { + V_DrawPatch(144, 160, PatchARTICLEAR); + if (CPlayer->readyArtifact > 0) + { + V_DrawPatch(143, 163, + W_CacheLumpName(patcharti[CPlayer->readyArtifact], + PU_CACHE)); + if (CPlayer->inventory[inv_ptr].count > 1) + { + DrSmallNumber(CPlayer->inventory[inv_ptr].count, 162, 184); + } + } + oldarti = CPlayer->readyArtifact; + oldartiCount = CPlayer->inventory[inv_ptr].count; + UpdateState |= I_STATBAR; + } + + // Frags + if (deathmatch) + { + temp = 0; + for (i = 0; i < maxplayers; i++) + { + temp += CPlayer->frags[i]; + } + if (temp != oldfrags) + { + V_DrawPatch(38, 162, PatchKILLS); + DrINumber(temp, 40, 176); + oldfrags = temp; + UpdateState |= I_STATBAR; + } + } + else + { + temp = HealthMarker; + if (temp < 0) + { + temp = 0; + } + else if (temp > 100) + { + temp = 100; + } + if (oldlife != temp) + { + oldlife = temp; + V_DrawPatch(41, 178, PatchARMCLEAR); + if (temp >= 25) + { + DrINumber(temp, 40, 176); + } + else + { + DrRedINumber(temp, 40, 176); + } + UpdateState |= I_STATBAR; + } + } + // Mana + temp = CPlayer->mana[0]; + if (oldmana1 != temp) + { + V_DrawPatch(77, 178, PatchMANACLEAR); + DrSmallNumber(temp, 79, 181); + manaVialPatch1 = (patch_t *) 1; // force a vial update + if (temp == 0) + { // Draw Dim Mana icon + manaPatch1 = PatchMANADIM1; + } + else if (oldmana1 == 0) + { + manaPatch1 = PatchMANABRIGHT1; + } + oldmana1 = temp; + UpdateState |= I_STATBAR; + } + temp = CPlayer->mana[1]; + if (oldmana2 != temp) + { + V_DrawPatch(109, 178, PatchMANACLEAR); + DrSmallNumber(temp, 111, 181); + manaVialPatch1 = (patch_t *) 1; // force a vial update + if (temp == 0) + { // Draw Dim Mana icon + manaPatch2 = PatchMANADIM2; + } + else if (oldmana2 == 0) + { + manaPatch2 = PatchMANABRIGHT2; + } + oldmana2 = temp; + UpdateState |= I_STATBAR; + } + if (oldweapon != CPlayer->readyweapon || manaPatch1 || manaPatch2 + || manaVialPatch1) + { // Update mana graphics based upon mana count/weapon type + if (CPlayer->readyweapon == WP_FIRST) + { + manaPatch1 = PatchMANADIM1; + manaPatch2 = PatchMANADIM2; + manaVialPatch1 = PatchMANAVIALDIM1; + manaVialPatch2 = PatchMANAVIALDIM2; + } + else if (CPlayer->readyweapon == WP_SECOND) + { + if (!manaPatch1) + { + manaPatch1 = PatchMANABRIGHT1; + } + manaVialPatch1 = PatchMANAVIAL1; + manaPatch2 = PatchMANADIM2; + manaVialPatch2 = PatchMANAVIALDIM2; + } + else if (CPlayer->readyweapon == WP_THIRD) + { + manaPatch1 = PatchMANADIM1; + manaVialPatch1 = PatchMANAVIALDIM1; + if (!manaPatch2) + { + manaPatch2 = PatchMANABRIGHT2; + } + manaVialPatch2 = PatchMANAVIAL2; + } + else + { + manaVialPatch1 = PatchMANAVIAL1; + manaVialPatch2 = PatchMANAVIAL2; + if (!manaPatch1) + { + manaPatch1 = PatchMANABRIGHT1; + } + if (!manaPatch2) + { + manaPatch2 = PatchMANABRIGHT2; + } + } + V_DrawPatch(77, 164, manaPatch1); + V_DrawPatch(110, 164, manaPatch2); + V_DrawPatch(94, 164, manaVialPatch1); + for (i = 165; i < 187 - (22 * CPlayer->mana[0]) / MAX_MANA; i++) + { + I_VideoBuffer[i * SCREENWIDTH + 95] = 0; + I_VideoBuffer[i * SCREENWIDTH + 96] = 0; + I_VideoBuffer[i * SCREENWIDTH + 97] = 0; + } + V_DrawPatch(102, 164, manaVialPatch2); + for (i = 165; i < 187 - (22 * CPlayer->mana[1]) / MAX_MANA; i++) + { + I_VideoBuffer[i * SCREENWIDTH + 103] = 0; + I_VideoBuffer[i * SCREENWIDTH + 104] = 0; + I_VideoBuffer[i * SCREENWIDTH + 105] = 0; + } + oldweapon = CPlayer->readyweapon; + UpdateState |= I_STATBAR; + } + // Armor + temp = AutoArmorSave[CPlayer->class] + + CPlayer->armorpoints[ARMOR_ARMOR] + + CPlayer->armorpoints[ARMOR_SHIELD] + + CPlayer->armorpoints[ARMOR_HELMET] + + CPlayer->armorpoints[ARMOR_AMULET]; + if (oldarmor != temp) + { + oldarmor = temp; + V_DrawPatch(255, 178, PatchARMCLEAR); + DrINumber(FixedDiv(temp, 5 * FRACUNIT) >> FRACBITS, 250, 176); + UpdateState |= I_STATBAR; + } + // Weapon Pieces + if (oldpieces != CPlayer->pieces) + { + DrawWeaponPieces(); + oldpieces = CPlayer->pieces; + UpdateState |= I_STATBAR; + } +} + +//========================================================================== +// +// DrawInventoryBar +// +//========================================================================== + +void DrawInventoryBar(void) +{ + int i; + int x; + + x = inv_ptr - curpos; + UpdateState |= I_STATBAR; + V_DrawPatch(38, 162, PatchINVBAR); + for (i = 0; i < 7; i++) + { + //V_DrawPatch(50+i*31, 160, W_CacheLumpName("ARTIBOX", PU_CACHE)); + if (CPlayer->inventorySlotNum > x + i + && CPlayer->inventory[x + i].type != arti_none) + { + V_DrawPatch(50 + i * 31, 163, + W_CacheLumpName(patcharti + [CPlayer->inventory[x + i].type], + PU_CACHE)); + if (CPlayer->inventory[x + i].count > 1) + { + DrSmallNumber(CPlayer->inventory[x + i].count, 68 + i * 31, + 185); + } + } + } + V_DrawPatch(50 + curpos * 31, 163, PatchSELECTBOX); + if (x != 0) + { + V_DrawPatch(42, 163, !(leveltime & 4) ? PatchINVLFGEM1 : + PatchINVLFGEM2); + } + if (CPlayer->inventorySlotNum - x > 7) + { + V_DrawPatch(269, 163, !(leveltime & 4) ? PatchINVRTGEM1 : + PatchINVRTGEM2); + } +} + +//========================================================================== +// +// DrawKeyBar +// +//========================================================================== + +void DrawKeyBar(void) +{ + int i; + int xPosition; + int temp; + + if (oldkeys != CPlayer->keys) + { + xPosition = 46; + for (i = 0; i < NUM_KEY_TYPES && xPosition <= 126; i++) + { + if (CPlayer->keys & (1 << i)) + { + V_DrawPatch(xPosition, 164, + W_CacheLumpNum(W_GetNumForName("keyslot1") + i, + PU_CACHE)); + xPosition += 20; + } + } + oldkeys = CPlayer->keys; + UpdateState |= I_STATBAR; + } + temp = AutoArmorSave[CPlayer->class] + + CPlayer->armorpoints[ARMOR_ARMOR] + + CPlayer->armorpoints[ARMOR_SHIELD] + + CPlayer->armorpoints[ARMOR_HELMET] + + CPlayer->armorpoints[ARMOR_AMULET]; + if (oldarmor != temp) + { + for (i = 0; i < NUMARMOR; i++) + { + if (!CPlayer->armorpoints[i]) + { + continue; + } + if (CPlayer->armorpoints[i] <= + (ArmorIncrement[CPlayer->class][i] >> 2)) + { + V_DrawTLPatch(150 + 31 * i, 164, + W_CacheLumpNum(W_GetNumForName("armslot1") + + i, PU_CACHE)); + } + else if (CPlayer->armorpoints[i] <= + (ArmorIncrement[CPlayer->class][i] >> 1)) + { + V_DrawAltTLPatch(150 + 31 * i, 164, + W_CacheLumpNum(W_GetNumForName("armslot1") + + i, PU_CACHE)); + } + else + { + V_DrawPatch(150 + 31 * i, 164, + W_CacheLumpNum(W_GetNumForName("armslot1") + i, + PU_CACHE)); + } + } + oldarmor = temp; + UpdateState |= I_STATBAR; + } +} + +//========================================================================== +// +// DrawWeaponPieces +// +//========================================================================== + +static int PieceX[NUMCLASSES][3] = { + {190, 225, 234}, + {190, 212, 225}, + {190, 205, 224}, + {0, 0, 0} // Pig is never used +}; + +static void DrawWeaponPieces(void) +{ + if (CPlayer->pieces == 7) + { + V_DrawPatch(190, 162, PatchWEAPONFULL); + return; + } + V_DrawPatch(190, 162, PatchWEAPONSLOT); + if (CPlayer->pieces & WPIECE1) + { + V_DrawPatch(PieceX[PlayerClass[consoleplayer]][0], 162, PatchPIECE1); + } + if (CPlayer->pieces & WPIECE2) + { + V_DrawPatch(PieceX[PlayerClass[consoleplayer]][1], 162, PatchPIECE2); + } + if (CPlayer->pieces & WPIECE3) + { + V_DrawPatch(PieceX[PlayerClass[consoleplayer]][2], 162, PatchPIECE3); + } +} + +//========================================================================== +// +// DrawFullScreenStuff +// +//========================================================================== + +void DrawFullScreenStuff(void) +{ + int i; + int x; + int temp; + + UpdateState |= I_FULLSCRN; + if (CPlayer->mo->health > 0) + { + DrBNumber(CPlayer->mo->health, 5, 180); + } + else + { + DrBNumber(0, 5, 180); + } + if (deathmatch) + { + temp = 0; + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + temp += CPlayer->frags[i]; + } + } + DrINumber(temp, 45, 185); + } + if (!inventory) + { + if (CPlayer->readyArtifact > 0) + { + V_DrawTLPatch(286, 170, W_CacheLumpName("ARTIBOX", PU_CACHE)); + V_DrawPatch(284, 169, + W_CacheLumpName(patcharti[CPlayer->readyArtifact], + PU_CACHE)); + if (CPlayer->inventory[inv_ptr].count > 1) + { + DrSmallNumber(CPlayer->inventory[inv_ptr].count, 302, 192); + } + } + } + else + { + x = inv_ptr - curpos; + for (i = 0; i < 7; i++) + { + V_DrawTLPatch(50 + i * 31, 168, W_CacheLumpName("ARTIBOX", + PU_CACHE)); + if (CPlayer->inventorySlotNum > x + i + && CPlayer->inventory[x + i].type != arti_none) + { + V_DrawPatch(49 + i * 31, 167, + W_CacheLumpName(patcharti + [CPlayer->inventory[x + i].type], + PU_CACHE)); + if (CPlayer->inventory[x + i].count > 1) + { + DrSmallNumber(CPlayer->inventory[x + i].count, + 66 + i * 31, 188); + } + } + } + V_DrawPatch(50 + curpos * 31, 167, PatchSELECTBOX); + if (x != 0) + { + V_DrawPatch(40, 167, !(leveltime & 4) ? PatchINVLFGEM1 : + PatchINVLFGEM2); + } + if (CPlayer->inventorySlotNum - x > 7) + { + V_DrawPatch(268, 167, !(leveltime & 4) ? + PatchINVRTGEM1 : PatchINVRTGEM2); + } + } +} + + +//========================================================================== +// +// Draw_TeleportIcon +// +//========================================================================== +void Draw_TeleportIcon(void) +{ + patch_t *patch; + patch = W_CacheLumpNum(W_GetNumForName("teleicon"), PU_CACHE); + V_DrawPatch(100, 68, patch); + UpdateState |= I_FULLSCRN; + I_FinishUpdate(); + UpdateState |= I_FULLSCRN; +} + +//========================================================================== +// +// Draw_SaveIcon +// +//========================================================================== +void Draw_SaveIcon(void) +{ + patch_t *patch; + patch = W_CacheLumpNum(W_GetNumForName("saveicon"), PU_CACHE); + V_DrawPatch(100, 68, patch); + UpdateState |= I_FULLSCRN; + I_FinishUpdate(); + UpdateState |= I_FULLSCRN; +} + +//========================================================================== +// +// Draw_LoadIcon +// +//========================================================================== +void Draw_LoadIcon(void) +{ + patch_t *patch; + patch = W_CacheLumpNum(W_GetNumForName("loadicon"), PU_CACHE); + V_DrawPatch(100, 68, patch); + UpdateState |= I_FULLSCRN; + I_FinishUpdate(); + UpdateState |= I_FULLSCRN; +} + + + +//========================================================================== +// +// SB_Responder +// +//========================================================================== + +boolean SB_Responder(event_t * event) +{ + if (event->type == ev_keydown) + { + if (HandleCheats(event->data1)) + { // Need to eat the key + return (true); + } + } + return (false); +} + +//========================================================================== +// +// HandleCheats +// +// Returns true if the caller should eat the key. +// +//========================================================================== + +static boolean HandleCheats(byte key) +{ + int i; + boolean eat; + + if (gameskill == sk_nightmare) + { // Can't cheat in nightmare mode + return (false); + } + else if (netgame) + { // change CD track is the only cheat available in deathmatch + eat = false; + if (cdmusic) + { + if (CheatAddKey(&Cheats[0], key, &eat)) + { + Cheats[0].func(&players[consoleplayer], &Cheats[0]); + S_StartSound(NULL, SFX_PLATFORM_STOP); + } + if (CheatAddKey(&Cheats[1], key, &eat)) + { + Cheats[1].func(&players[consoleplayer], &Cheats[1]); + S_StartSound(NULL, SFX_PLATFORM_STOP); + } + } + return eat; + } + if (players[consoleplayer].health <= 0) + { // Dead players can't cheat + return (false); + } + eat = false; + for (i = 0; ipos) + { + cheat->pos = cheat->sequence; + cheat->currentArg = 0; + } + if (*cheat->pos == 0) + { + *eat = true; + cheat->args[cheat->currentArg++] = key; + cheat->pos++; + } + else if (CheatLookup[key] == *cheat->pos) + { + cheat->pos++; + } + else + { + cheat->pos = cheat->sequence; + cheat->currentArg = 0; + } + if (*cheat->pos == 0xff) + { + cheat->pos = cheat->sequence; + cheat->currentArg = 0; + return (true); + } + return (false); + */ + + *eat = cht_CheckCheat(cheat->seq, key); + + return *eat; +} + +//========================================================================== +// +// CHEAT FUNCTIONS +// +//========================================================================== + +static void CheatGodFunc(player_t * player, Cheat_t * cheat) +{ + player->cheats ^= CF_GODMODE; + if (player->cheats & CF_GODMODE) + { + P_SetMessage(player, TXT_CHEATGODON, true); + } + else + { + P_SetMessage(player, TXT_CHEATGODOFF, true); + } + SB_state = -1; +} + +static void CheatNoClipFunc(player_t * player, Cheat_t * cheat) +{ + player->cheats ^= CF_NOCLIP; + if (player->cheats & CF_NOCLIP) + { + P_SetMessage(player, TXT_CHEATNOCLIPON, true); + } + else + { + P_SetMessage(player, TXT_CHEATNOCLIPOFF, true); + } +} + +static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat) +{ + int i; + + for (i = 0; i < NUMARMOR; i++) + { + player->armorpoints[i] = ArmorIncrement[player->class][i]; + } + for (i = 0; i < NUMWEAPONS; i++) + { + player->weaponowned[i] = true; + } + for (i = 0; i < NUMMANA; i++) + { + player->mana[i] = MAX_MANA; + } + P_SetMessage(player, TXT_CHEATWEAPONS, true); +} + +static void CheatHealthFunc(player_t * player, Cheat_t * cheat) +{ + if (player->morphTics) + { + player->health = player->mo->health = MAXMORPHHEALTH; + } + else + { + player->health = player->mo->health = MAXHEALTH; + } + P_SetMessage(player, TXT_CHEATHEALTH, true); +} + +static void CheatKeysFunc(player_t * player, Cheat_t * cheat) +{ + player->keys = 2047; + P_SetMessage(player, TXT_CHEATKEYS, true); +} + +static void CheatSoundFunc(player_t * player, Cheat_t * cheat) +{ + DebugSound = !DebugSound; + if (DebugSound) + { + P_SetMessage(player, TXT_CHEATSOUNDON, true); + } + else + { + P_SetMessage(player, TXT_CHEATSOUNDOFF, true); + } +} + +static void CheatTickerFunc(player_t * player, Cheat_t * cheat) +{ + DisplayTicker = !DisplayTicker; + if (DisplayTicker) + { + P_SetMessage(player, TXT_CHEATTICKERON, true); + } + else + { + P_SetMessage(player, TXT_CHEATTICKEROFF, true); + } + + I_DisplayFPSDots(DisplayTicker); +} + +static void CheatArtifactAllFunc(player_t * player, Cheat_t * cheat) +{ + int i; + int j; + + for (i = arti_none + 1; i < arti_firstpuzzitem; i++) + { + for (j = 0; j < 25; j++) + { + P_GiveArtifact(player, i, NULL); + } + } + P_SetMessage(player, TXT_CHEATARTIFACTS3, true); +} + +static void CheatPuzzleFunc(player_t * player, Cheat_t * cheat) +{ + int i; + + for (i = arti_firstpuzzitem; i < NUMARTIFACTS; i++) + { + P_GiveArtifact(player, i, NULL); + } + P_SetMessage(player, TXT_CHEATARTIFACTS3, true); +} + +static void CheatInitFunc(player_t * player, Cheat_t * cheat) +{ + G_DeferedInitNew(gameskill, gameepisode, gamemap); + P_SetMessage(player, TXT_CHEATWARP, true); +} + +static void CheatWarpFunc(player_t * player, Cheat_t * cheat) +{ + int tens; + int ones; + int map; + char mapName[9]; + char args[2]; + + cht_GetParam(cheat->seq, args); + + tens = args[0] - '0'; + ones = args[1] - '0'; + if (tens < 0 || tens > 9 || ones < 0 || ones > 9) + { // Bad map + P_SetMessage(player, TXT_CHEATBADINPUT, true); + return; + } + map = P_TranslateMap((args[0] - '0') * 10 + args[1] - '0'); + if (map == -1) + { // Not found + P_SetMessage(player, TXT_CHEATNOMAP, true); + return; + } + if (map == gamemap) + { // Don't try to teleport to current map + P_SetMessage(player, TXT_CHEATBADINPUT, true); + return; + } + M_snprintf(mapName, sizeof(mapName), "MAP%02d", map); + if (W_CheckNumForName(mapName) == -1) + { // Can't find + P_SetMessage(player, TXT_CHEATNOMAP, true); + return; + } + P_SetMessage(player, TXT_CHEATWARP, true); + G_TeleportNewMap(map, 0); +} + +static void CheatPigFunc(player_t * player, Cheat_t * cheat) +{ + if (player->morphTics) + { + P_UndoPlayerMorph(player); + } + else + { + P_MorphPlayer(player); + } + P_SetMessage(player, "SQUEAL!!", true); +} + +static void CheatMassacreFunc(player_t * player, Cheat_t * cheat) +{ + int count; + char buffer[80]; + + count = P_Massacre(); + M_snprintf(buffer, sizeof(buffer), "%d MONSTERS KILLED\n", count); + P_SetMessage(player, buffer, true); +} + +static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat) +{ + int i; + if (player->morphTics) + { + return; + } + for (i = 1; i < NUMWEAPONS; i++) + { + player->weaponowned[i] = false; + } + + // In the original code, NUMWEAPONS was 8. So the writes to weaponowned + // overflowed the array. We must set the following fields to zero as + // well: + + player->mana[0] = 0; + player->mana[1] = 0; + player->attackdown = 0; + player->usedown = 0; + + player->pendingweapon = WP_FIRST; + P_SetMessage(player, TXT_CHEATIDKFA, true); +} + +static void CheatQuickenFunc1(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, "TRYING TO CHEAT? THAT'S ONE....", true); +} + +static void CheatQuickenFunc2(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, "THAT'S TWO....", true); +} + +static void CheatQuickenFunc3(player_t * player, Cheat_t * cheat) +{ + P_DamageMobj(player->mo, NULL, player->mo, 10000); + P_SetMessage(player, "THAT'S THREE! TIME TO DIE.", true); +} + +static void CheatClassFunc1(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, "ENTER NEW PLAYER CLASS (0 - 2)", true); +} + +static void CheatClassFunc2(player_t * player, Cheat_t * cheat) +{ + int i; + int class; + char args[2]; + + cht_GetParam(cheat->seq, args); + + if (player->morphTics) + { // don't change class if the player is morphed + return; + } + class = args[0] - '0'; + if (class > 2 || class < 0) + { + P_SetMessage(player, "INVALID PLAYER CLASS", true); + return; + } + player->class = class; + for (i = 0; i < NUMARMOR; i++) + { + player->armorpoints[i] = 0; + } + PlayerClass[consoleplayer] = class; + P_PostMorphWeapon(player, WP_FIRST); + SB_SetClassData(); + SB_state = -1; + UpdateState |= I_FULLSCRN; +} + +static void CheatVersionFunc(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, HEXEN_VERSIONTEXT, true); +} + +static void CheatDebugFunc(player_t * player, Cheat_t * cheat) +{ + char textBuffer[50]; + M_snprintf(textBuffer, sizeof(textBuffer), + "MAP %d (%d) X:%5d Y:%5d Z:%5d", + P_GetMapWarpTrans(gamemap), + gamemap, + player->mo->x >> FRACBITS, + player->mo->y >> FRACBITS, player->mo->z >> FRACBITS); + P_SetMessage(player, textBuffer, true); +} + +static void CheatScriptFunc1(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, "RUN WHICH SCRIPT(01-99)?", true); +} + +static void CheatScriptFunc2(player_t * player, Cheat_t * cheat) +{ + P_SetMessage(player, "RUN WHICH SCRIPT(01-99)?", true); +} + +static void CheatScriptFunc3(player_t * player, Cheat_t * cheat) +{ + int script; + byte script_args[3]; + int tens, ones; + char textBuffer[40]; + char args[2]; + + cht_GetParam(cheat->seq, args); + + tens = args[0] - '0'; + ones = args[1] - '0'; + script = tens * 10 + ones; + if (script < 1) + return; + if (script > 99) + return; + script_args[0] = script_args[1] = script_args[2] = 0; + + if (P_StartACS(script, 0, script_args, player->mo, NULL, 0)) + { + M_snprintf(textBuffer, sizeof(textBuffer), + "RUNNING SCRIPT %.2d", script); + P_SetMessage(player, textBuffer, true); + } +} + + +static void CheatRevealFunc(player_t * player, Cheat_t * cheat) +{ + cheating = (cheating + 1) % 3; +} + +//=========================================================================== +// +// CheatTrackFunc1 +// +//=========================================================================== + +static void CheatTrackFunc1(player_t * player, Cheat_t * cheat) +{ + char buffer[80]; + + if (!cdmusic) + { + return; + } + + if (I_CDMusInit() == -1) + { + P_SetMessage(player, "ERROR INITIALIZING CD", true); + } + + M_snprintf(buffer, sizeof(buffer), "ENTER DESIRED CD TRACK (%.2d - %.2d):\n", + I_CDMusFirstTrack(), I_CDMusLastTrack()); + P_SetMessage(player, buffer, true); +} + +//=========================================================================== +// +// CheatTrackFunc2 +// +//=========================================================================== + +static void CheatTrackFunc2(player_t * player, Cheat_t * cheat) +{ + char buffer[80]; + int track; + char args[2]; + + cht_GetParam(cheat->seq, args); + + if (!cdmusic) + { + return; + } + + track = (args[0] - '0') * 10 + (args[1] - '0'); + if (track < I_CDMusFirstTrack() || track > I_CDMusLastTrack()) + { + P_SetMessage(player, "INVALID TRACK NUMBER\n", true); + return; + } + + if (track == S_GetCurrentCDTrack()) + { + return; + } + + if (!S_StartCustomCDTrack(track)) + { + M_snprintf(buffer, sizeof(buffer), + "ERROR WHILE TRYING TO PLAY CD TRACK: %.2d\n", track); + P_SetMessage(player, buffer, true); + } + else + { + // No error encountered while attempting to play the track + M_snprintf(buffer, sizeof(buffer), "PLAYING TRACK: %.2d\n", track); + P_SetMessage(player, buffer, true); + } +} diff --git a/games/NXDoom/src/hexen/sc_man.c b/games/NXDoom/src/hexen/sc_man.c new file mode 100644 index 00000000000..489bc72e0ec --- /dev/null +++ b/games/NXDoom/src/hexen/sc_man.c @@ -0,0 +1,465 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include +#include +#include "h2def.h" +#include "i_system.h" +#include "m_misc.h" + +// MACROS ------------------------------------------------------------------ + +#define MAX_STRING_SIZE 64 +#define ASCII_COMMENT (';') +#define ASCII_QUOTE (34) +#define LUMP_SCRIPT 1 +#define FILE_ZONE_SCRIPT 2 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void CheckOpen(void); +static void OpenScript(const char *name, int type); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +char *sc_String; +int sc_Number; +int sc_Line; +boolean sc_End; +boolean sc_Crossed; +boolean sc_FileScripts = false; +const char *sc_ScriptsDir = ""; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static char ScriptName[16]; +static char *ScriptBuffer; +static char *ScriptPtr; +static char *ScriptEndPtr; +static char StringBuffer[MAX_STRING_SIZE]; +static int ScriptLumpNum; +static boolean ScriptOpen = false; +static int ScriptSize; +static boolean AlreadyGot = false; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// SC_Open +// +//========================================================================== + +void SC_Open(const char *name) +{ + char fileName[128]; + + if (sc_FileScripts == true) + { + M_snprintf(fileName, sizeof(fileName), "%s%s.txt", sc_ScriptsDir, name); + SC_OpenFile(fileName); + } + else + { + SC_OpenLump(name); + } +} + +//========================================================================== +// +// SC_OpenLump +// +// Loads a script (from the WAD files) and prepares it for parsing. +// +//========================================================================== + +void SC_OpenLump(const char *name) +{ + OpenScript(name, LUMP_SCRIPT); +} + +//========================================================================== +// +// SC_OpenFile +// +// Loads a script (from a file) and prepares it for parsing. Uses the +// zone memory allocator for memory allocation and de-allocation. +// +//========================================================================== + +void SC_OpenFile(const char *name) +{ + OpenScript(name, FILE_ZONE_SCRIPT); +} + +//========================================================================== +// +// OpenScript +// +//========================================================================== + +static void OpenScript(const char *name, int type) +{ + SC_Close(); + if (type == LUMP_SCRIPT) + { // Lump script + ScriptLumpNum = W_GetNumForName(name); + ScriptBuffer = (char *) W_CacheLumpNum(ScriptLumpNum, PU_STATIC); + ScriptSize = W_LumpLength(ScriptLumpNum); + M_StringCopy(ScriptName, name, sizeof(ScriptName)); + } + else if (type == FILE_ZONE_SCRIPT) + { // File script - zone + ScriptLumpNum = -1; + ScriptSize = M_ReadFile(name, (byte **) & ScriptBuffer); + M_ExtractFileBase(name, ScriptName); + } + ScriptPtr = ScriptBuffer; + ScriptEndPtr = ScriptPtr + ScriptSize; + sc_Line = 1; + sc_End = false; + ScriptOpen = true; + sc_String = StringBuffer; + AlreadyGot = false; +} + +//========================================================================== +// +// SC_Close +// +//========================================================================== + +void SC_Close(void) +{ + if (ScriptOpen) + { + if (ScriptLumpNum >= 0) + { + W_ReleaseLumpNum(ScriptLumpNum); + } + else + { + Z_Free(ScriptBuffer); + } + ScriptOpen = false; + } +} + +//========================================================================== +// +// SC_GetString +// +//========================================================================== + +boolean SC_GetString(void) +{ + char *text; + boolean foundToken; + + CheckOpen(); + if (AlreadyGot) + { + AlreadyGot = false; + return true; + } + foundToken = false; + sc_Crossed = false; + if (ScriptPtr >= ScriptEndPtr) + { + sc_End = true; + return false; + } + while (foundToken == false) + { + while (ScriptPtr < ScriptEndPtr && *ScriptPtr <= 32) + { + if (*ScriptPtr++ == '\n') + { + sc_Line++; + sc_Crossed = true; + } + } + if (ScriptPtr >= ScriptEndPtr) + { + sc_End = true; + return false; + } + if (*ScriptPtr != ASCII_COMMENT) + { // Found a token + foundToken = true; + } + else + { // Skip comment + while (*ScriptPtr++ != '\n') + { + if (ScriptPtr >= ScriptEndPtr) + { + sc_End = true; + return false; + } + } + sc_Line++; + sc_Crossed = true; + } + } + text = sc_String; + if (*ScriptPtr == ASCII_QUOTE) + { // Quoted string + ScriptPtr++; + while (*ScriptPtr != ASCII_QUOTE) + { + *text++ = *ScriptPtr++; + if (ScriptPtr == ScriptEndPtr + || text == &sc_String[MAX_STRING_SIZE - 1]) + { + break; + } + } + ScriptPtr++; + } + else + { // Normal string + while ((*ScriptPtr > 32) && (*ScriptPtr != ASCII_COMMENT)) + { + *text++ = *ScriptPtr++; + if (ScriptPtr == ScriptEndPtr + || text == &sc_String[MAX_STRING_SIZE - 1]) + { + break; + } + } + } + *text = 0; + return true; +} + +//========================================================================== +// +// SC_MustGetString +// +//========================================================================== + +void SC_MustGetString(void) +{ + if (SC_GetString() == false) + { + SC_ScriptError("Missing string."); + } +} + +//========================================================================== +// +// SC_MustGetStringName +// +//========================================================================== + +void SC_MustGetStringName(char *name) +{ + SC_MustGetString(); + if (SC_Compare(name) == false) + { + SC_ScriptError(NULL); + } +} + +//========================================================================== +// +// SC_GetNumber +// +//========================================================================== + +boolean SC_GetNumber(void) +{ + char *stopper; + + CheckOpen(); + if (SC_GetString()) + { + sc_Number = strtol(sc_String, &stopper, 0); + if (*stopper != 0) + { + I_Error("SC_GetNumber: Bad numeric constant \"%s\".\n" + "Script %s, Line %d", sc_String, ScriptName, sc_Line); + } + return true; + } + else + { + return false; + } +} + +//========================================================================== +// +// SC_MustGetNumber +// +//========================================================================== + +void SC_MustGetNumber(void) +{ + if (SC_GetNumber() == false) + { + SC_ScriptError("Missing integer."); + } +} + +//========================================================================== +// +// SC_UnGet +// +// Assumes there is a valid string in sc_String. +// +//========================================================================== + +void SC_UnGet(void) +{ + AlreadyGot = true; +} + +//========================================================================== +// +// SC_Check +// +// Returns true if another token is on the current line. +// +//========================================================================== + +/* +boolean SC_Check(void) +{ + char *text; + + CheckOpen(); + text = ScriptPtr; + if(text >= ScriptEndPtr) + { + return false; + } + while(*text <= 32) + { + if(*text == '\n') + { + return false; + } + text++; + if(text == ScriptEndPtr) + { + return false; + } + } + if(*text == ASCII_COMMENT) + { + return false; + } + return true; +} +*/ + +//========================================================================== +// +// SC_MatchString +// +// Returns the index of the first match to sc_String from the passed +// array of strings, or -1 if not found. +// +//========================================================================== + +int SC_MatchString(const char **strings) +{ + int i; + + for (i = 0; *strings != NULL; i++) + { + if (SC_Compare(*strings++)) + { + return i; + } + } + return -1; +} + +//========================================================================== +// +// SC_MustMatchString +// +//========================================================================== + +int SC_MustMatchString(const char **strings) +{ + int i; + + i = SC_MatchString(strings); + if (i == -1) + { + SC_ScriptError(NULL); + } + return i; +} + +//========================================================================== +// +// SC_Compare +// +//========================================================================== + +boolean SC_Compare(const char *text) +{ + if (strcasecmp(text, sc_String) == 0) + { + return true; + } + return false; +} + +//========================================================================== +// +// SC_ScriptError +// +//========================================================================== + +void SC_ScriptError(const char *message) +{ + if (message == NULL) + { + message = "Bad syntax."; + } + I_Error("Script error, \"%s\" line %d: %s", ScriptName, sc_Line, message); +} + +//========================================================================== +// +// CheckOpen +// +//========================================================================== + +static void CheckOpen(void) +{ + if (ScriptOpen == false) + { + I_Error("SC_ call before SC_Open()."); + } +} diff --git a/games/NXDoom/src/hexen/sn_sonix.c b/games/NXDoom/src/hexen/sn_sonix.c new file mode 100644 index 00000000000..81c506babc7 --- /dev/null +++ b/games/NXDoom/src/hexen/sn_sonix.c @@ -0,0 +1,535 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include +#include "m_random.h" +#include "h2def.h" +#include "i_system.h" +#include "i_sound.h" +#include "s_sound.h" + +// MACROS ------------------------------------------------------------------ + +#define SS_MAX_SCRIPTS 64 +#define SS_TEMPBUFFER_SIZE 1024 +#define SS_SEQUENCE_NAME_LENGTH 32 + +#define SS_SCRIPT_NAME "SNDSEQ" +#define SS_STRING_PLAY "play" +#define SS_STRING_PLAYUNTILDONE "playuntildone" +#define SS_STRING_PLAYTIME "playtime" +#define SS_STRING_PLAYREPEAT "playrepeat" +#define SS_STRING_DELAY "delay" +#define SS_STRING_DELAYRAND "delayrand" +#define SS_STRING_VOLUME "volume" +#define SS_STRING_END "end" +#define SS_STRING_STOPSOUND "stopsound" + +// TYPES ------------------------------------------------------------------- + +typedef enum +{ + SS_CMD_NONE, + SS_CMD_PLAY, + SS_CMD_WAITUNTILDONE, // used by PLAYUNTILDONE + SS_CMD_PLAYTIME, + SS_CMD_PLAYREPEAT, + SS_CMD_DELAY, + SS_CMD_DELAYRAND, + SS_CMD_VOLUME, + SS_CMD_STOPSOUND, + SS_CMD_END +} sscmds_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void VerifySequencePtr(int *base, int *ptr); +static int GetSoundOffset(char *name); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static struct +{ + char name[SS_SEQUENCE_NAME_LENGTH]; + int scriptNum; + int stopSound; +} SequenceTranslate[SEQ_NUMSEQ] = +{ + { + "Platform", 0, 0}, + { + "Platform", 0, 0}, // a 'heavy' platform is just a platform + { + "PlatformMetal", 0, 0}, + { + "Platform", 0, 0}, // same with a 'creak' platform + { + "Silence", 0, 0}, + { + "Lava", 0, 0}, + { + "Water", 0, 0}, + { + "Ice", 0, 0}, + { + "Earth", 0, 0}, + { + "PlatformMetal2", 0, 0}, + { + "DoorNormal", 0, 0}, + { + "DoorHeavy", 0, 0}, + { + "DoorMetal", 0, 0}, + { + "DoorCreak", 0, 0}, + { + "Silence", 0, 0}, + { + "Lava", 0, 0}, + { + "Water", 0, 0}, + { + "Ice", 0, 0}, + { + "Earth", 0, 0}, + { + "DoorMetal2", 0, 0}, + { + "Wind", 0, 0} +}; + +static int *SequenceData[SS_MAX_SCRIPTS]; + +int ActiveSequences; +seqnode_t *SequenceListHead; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// VerifySequencePtr +// +// Verifies the integrity of the temporary ptr, and ensures that the ptr +// isn't exceeding the size of the temporary buffer +//========================================================================== + +static void VerifySequencePtr(int *base, int *ptr) +{ + if (ptr - base > SS_TEMPBUFFER_SIZE) + { + I_Error("VerifySequencePtr: tempPtr >= %d\n", SS_TEMPBUFFER_SIZE); + } +} + +//========================================================================== +// +// GetSoundOffset +// +//========================================================================== + +static int GetSoundOffset(char *name) +{ + int i; + + for (i = 0; i < NUMSFX; i++) + { + if (!strcasecmp(name, S_sfx[i].tagname)) + { + return i; + } + } + SC_ScriptError("GetSoundOffset: Unknown sound name\n"); + return 0; +} + +//========================================================================== +// +// SN_InitSequenceScript +// +//========================================================================== + +void SN_InitSequenceScript(void) +{ + int i, j; + int inSequence; + int *tempDataStart = NULL; + int *tempDataPtr = NULL; + + inSequence = -1; + ActiveSequences = 0; + for (i = 0; i < SS_MAX_SCRIPTS; i++) + { + SequenceData[i] = NULL; + } + SC_Open(SS_SCRIPT_NAME); + while (SC_GetString()) + { + if (*sc_String == ':') + { + if (inSequence != -1) + { + SC_ScriptError("SN_InitSequenceScript: Nested Script Error"); + } + tempDataStart = (int *) Z_Malloc(SS_TEMPBUFFER_SIZE, + PU_STATIC, NULL); + memset(tempDataStart, 0, SS_TEMPBUFFER_SIZE); + tempDataPtr = tempDataStart; + for (i = 0; i < SS_MAX_SCRIPTS; i++) + { + if (SequenceData[i] == NULL) + { + break; + } + } + if (i == SS_MAX_SCRIPTS) + { + I_Error("Number of SS Scripts >= SS_MAX_SCRIPTS"); + } + for (j = 0; j < SEQ_NUMSEQ; j++) + { + if (!strcasecmp(SequenceTranslate[j].name, sc_String + 1)) + { + SequenceTranslate[j].scriptNum = i; + inSequence = j; + break; + } + } + continue; // parse the next command + } + if (inSequence == -1) + { + continue; + } + if (SC_Compare(SS_STRING_PLAYUNTILDONE)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + SC_MustGetString(); + *tempDataPtr++ = SS_CMD_PLAY; + *tempDataPtr++ = GetSoundOffset(sc_String); + *tempDataPtr++ = SS_CMD_WAITUNTILDONE; + } + else if (SC_Compare(SS_STRING_PLAY)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + SC_MustGetString(); + *tempDataPtr++ = SS_CMD_PLAY; + *tempDataPtr++ = GetSoundOffset(sc_String); + } + else if (SC_Compare(SS_STRING_PLAYTIME)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + SC_MustGetString(); + *tempDataPtr++ = SS_CMD_PLAY; + *tempDataPtr++ = GetSoundOffset(sc_String); + SC_MustGetNumber(); + *tempDataPtr++ = SS_CMD_DELAY; + *tempDataPtr++ = sc_Number; + } + else if (SC_Compare(SS_STRING_PLAYREPEAT)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + SC_MustGetString(); + *tempDataPtr++ = SS_CMD_PLAYREPEAT; + *tempDataPtr++ = GetSoundOffset(sc_String); + } + else if (SC_Compare(SS_STRING_DELAY)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + *tempDataPtr++ = SS_CMD_DELAY; + SC_MustGetNumber(); + *tempDataPtr++ = sc_Number; + } + else if (SC_Compare(SS_STRING_DELAYRAND)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + *tempDataPtr++ = SS_CMD_DELAYRAND; + SC_MustGetNumber(); + *tempDataPtr++ = sc_Number; + SC_MustGetNumber(); + *tempDataPtr++ = sc_Number; + } + else if (SC_Compare(SS_STRING_VOLUME)) + { + VerifySequencePtr(tempDataStart, tempDataPtr); + *tempDataPtr++ = SS_CMD_VOLUME; + SC_MustGetNumber(); + *tempDataPtr++ = sc_Number; + } + else if (SC_Compare(SS_STRING_END)) + { + int dataSize; + + *tempDataPtr++ = SS_CMD_END; + dataSize = (tempDataPtr - tempDataStart) * sizeof(int); + SequenceData[i] = (int *) Z_Malloc(dataSize, PU_STATIC, NULL); + memcpy(SequenceData[i], tempDataStart, dataSize); + Z_Free(tempDataStart); + inSequence = -1; + } + else if (SC_Compare(SS_STRING_STOPSOUND)) + { + SC_MustGetString(); + SequenceTranslate[inSequence].stopSound = + GetSoundOffset(sc_String); + *tempDataPtr++ = SS_CMD_STOPSOUND; + } + else + { + SC_ScriptError("SN_InitSequenceScript: Unknown commmand.\n"); + } + } +} + +//========================================================================== +// +// SN_StartSequence +// +//========================================================================== + +void SN_StartSequence(mobj_t * mobj, int sequence) +{ + seqnode_t *node; + + SN_StopSequence(mobj); // Stop any previous sequence + node = (seqnode_t *) Z_Malloc(sizeof(seqnode_t), PU_STATIC, NULL); + node->sequencePtr = SequenceData[SequenceTranslate[sequence].scriptNum]; + node->sequence = sequence; + node->mobj = mobj; + node->delayTics = 0; + node->stopSound = SequenceTranslate[sequence].stopSound; + node->volume = 127; // Start at max volume + + if (!SequenceListHead) + { + SequenceListHead = node; + node->next = node->prev = NULL; + } + else + { + SequenceListHead->prev = node; + node->next = SequenceListHead; + node->prev = NULL; + SequenceListHead = node; + } + ActiveSequences++; + return; +} + +//========================================================================== +// +// SN_StartSequenceName +// +//========================================================================== + +void SN_StartSequenceName(mobj_t * mobj, char *name) +{ + int i; + + for (i = 0; i < SEQ_NUMSEQ; i++) + { + if (!strcmp(name, SequenceTranslate[i].name)) + { + SN_StartSequence(mobj, i); + return; + } + } +} + +//========================================================================== +// +// SN_StopSequence +// +//========================================================================== + +void SN_StopSequence(mobj_t * mobj) +{ + seqnode_t *node; + + for (node = SequenceListHead; node; node = node->next) + { + if (node->mobj == mobj) + { + S_StopSound(mobj); + if (node->stopSound) + { + S_StartSoundAtVolume(mobj, node->stopSound, node->volume); + } + if (SequenceListHead == node) + { + SequenceListHead = node->next; + } + if (node->prev) + { + node->prev->next = node->next; + } + if (node->next) + { + node->next->prev = node->prev; + } + Z_Free(node); + ActiveSequences--; + } + } +} + +//========================================================================== +// +// SN_UpdateActiveSequences +// +//========================================================================== + +void SN_UpdateActiveSequences(void) +{ + seqnode_t *node; + boolean sndPlaying; + + if (!ActiveSequences || paused) + { // No sequences currently playing/game is paused + return; + } + for (node = SequenceListHead; node; node = node->next) + { + if (node->delayTics) + { + node->delayTics--; + continue; + } + sndPlaying = S_GetSoundPlayingInfo(node->mobj, node->currentSoundID); + switch (*node->sequencePtr) + { + case SS_CMD_PLAY: + if (!sndPlaying) + { + node->currentSoundID = *(node->sequencePtr + 1); + S_StartSoundAtVolume(node->mobj, node->currentSoundID, + node->volume); + } + node->sequencePtr += 2; + break; + case SS_CMD_WAITUNTILDONE: + if (!sndPlaying) + { + node->sequencePtr++; + node->currentSoundID = 0; + } + break; + case SS_CMD_PLAYREPEAT: + if (!sndPlaying) + { + node->currentSoundID = *(node->sequencePtr + 1); + S_StartSoundAtVolume(node->mobj, node->currentSoundID, + node->volume); + } + break; + case SS_CMD_DELAY: + node->delayTics = *(node->sequencePtr + 1); + node->sequencePtr += 2; + node->currentSoundID = 0; + break; + case SS_CMD_DELAYRAND: + node->delayTics = *(node->sequencePtr + 1) + + M_Random() % (*(node->sequencePtr + 2) - + *(node->sequencePtr + 1)); + node->sequencePtr += 2; + node->currentSoundID = 0; + break; + case SS_CMD_VOLUME: + node->volume = (127 * (*(node->sequencePtr + 1))) / 100; + node->sequencePtr += 2; + break; + case SS_CMD_STOPSOUND: + // Wait until something else stops the sequence + break; + case SS_CMD_END: + SN_StopSequence(node->mobj); + break; + default: + break; + } + } +} + +//========================================================================== +// +// SN_StopAllSequences +// +//========================================================================== + +void SN_StopAllSequences(void) +{ + seqnode_t *node; + + for (node = SequenceListHead; node; node = node->next) + { + node->stopSound = 0; // don't play any stop sounds + SN_StopSequence(node->mobj); + } +} + +//========================================================================== +// +// SN_GetSequenceOffset +// +//========================================================================== + +int SN_GetSequenceOffset(int sequence, int *sequencePtr) +{ + return (sequencePtr - + SequenceData[SequenceTranslate[sequence].scriptNum]); +} + +//========================================================================== +// +// SN_ChangeNodeData +// +// nodeNum zero is the first node +//========================================================================== + +void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume, + int currentSoundID) +{ + int i; + seqnode_t *node; + + i = 0; + node = SequenceListHead; + while (node && i < nodeNum) + { + node = node->next; + i++; + } + if (!node) + { // reach the end of the list before finding the nodeNum-th node + return; + } + node->delayTics = delayTics; + node->volume = volume; + node->sequencePtr += seqOffset; + node->currentSoundID = currentSoundID; +} diff --git a/games/NXDoom/src/hexen/sounds.c b/games/NXDoom/src/hexen/sounds.c new file mode 100644 index 00000000000..fe322baa4c9 --- /dev/null +++ b/games/NXDoom/src/hexen/sounds.c @@ -0,0 +1,313 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#include "h2def.h" +#include "sounds.h" + +// Music info + +/* +musicinfo_t S_music[] = +{ + { "MUS_E1M1", 0 }, // 1-1 + { "MUS_E1M2", 0 }, + { "MUS_E1M3", 0 }, + { "MUS_E1M4", 0 }, + { "MUS_E1M5", 0 }, + { "MUS_E1M6", 0 }, + { "MUS_E1M7", 0 }, + { "MUS_E1M8", 0 }, + { "MUS_E1M9", 0 }, + { "MUS_E2M1", 0 }, // 2-1 + { "MUS_E2M2", 0 }, + { "MUS_E2M3", 0 }, + { "MUS_E2M4", 0 }, + { "MUS_E1M4", 0 }, + { "MUS_E2M6", 0 }, + { "MUS_E2M7", 0 }, + { "MUS_E2M8", 0 }, + { "MUS_E2M9", 0 }, + { "MUS_E1M1", 0 }, // 3-1 + { "MUS_E3M2", 0 }, + { "MUS_E3M3", 0 }, + { "MUS_E1M6", 0 }, + { "MUS_E1M3", 0 }, + { "MUS_E1M2", 0 }, + { "MUS_E1M5", 0 }, + { "MUS_E1M9", 0 }, + { "MUS_E2M6", 0 }, + { "MUS_E1M6", 0 }, // 4-1 + { "MUS_TITL", 0 }, + { "MUS_INTR", 0 }, + { "MUS_CPTD", 0 } +}; +*/ + +// Sound info + +#define SOUND(name, priority, numchannels, pitchshift) \ + { name, "", priority, NULL, pitchshift, 0, -1, 0, numchannels, NULL } + +sfxinfo_t S_sfx[] = { + // tagname, lumpname, priority, usefulness, snd_ptr, lumpnum, numchannels, + // pitchshift + SOUND("", 0, 0, 0), + SOUND("PlayerFighterNormalDeath", 256, 2, 1), + SOUND("PlayerFighterCrazyDeath", 256, 2, 1), + SOUND("PlayerFighterExtreme1Death", 256, 2, 1), + SOUND("PlayerFighterExtreme2Death", 256, 2, 1), + SOUND("PlayerFighterExtreme3Death", 256, 2, 1), + SOUND("PlayerFighterBurnDeath", 256, 2, 1), + SOUND("PlayerClericNormalDeath", 256, 2, 1), + SOUND("PlayerClericCrazyDeath", 256, 2, 1), + SOUND("PlayerClericExtreme1Death", 256, 2, 1), + SOUND("PlayerClericExtreme2Death", 256, 2, 1), + SOUND("PlayerClericExtreme3Death", 256, 2, 1), + SOUND("PlayerClericBurnDeath", 256, 2, 1), + SOUND("PlayerMageNormalDeath", 256, 2, 0), + SOUND("PlayerMageCrazyDeath", 256, 2, 0), + SOUND("PlayerMageExtreme1Death", 256, 2, 0), + SOUND("PlayerMageExtreme2Death", 256, 2, 0), + SOUND("PlayerMageExtreme3Death", 256, 2, 0), + SOUND("PlayerMageBurnDeath", 256, 2, 0), + SOUND("PlayerFighterPain", 256, 2, 1), + SOUND("PlayerClericPain", 256, 2, 1), + SOUND("PlayerMagePain", 256, 2, 0), + SOUND("PlayerFighterGrunt", 256, 2, 1), + SOUND("PlayerClericGrunt", 256, 2, 1), + SOUND("PlayerMageGrunt", 256, 2, 0), + SOUND("PlayerLand", 32, 2, 1), + SOUND("PlayerPoisonCough", 256, 2, 1), + SOUND("PlayerFighterFallingScream", 256, 2, 1), + SOUND("PlayerClericFallingScream", 256, 2, 1), + SOUND("PlayerMageFallingScream", 256, 2, 0), + SOUND("PlayerFallingSplat", 256, 2, 1), + SOUND("PlayerFighterFailedUse", 256, 1, 1), + SOUND("PlayerClericFailedUse", 256, 1, 1), + SOUND("PlayerMageFailedUse", 256, 1, 0), + SOUND("PlatformStart", 36, 2, 1), + SOUND("PlatformStartMetal", 36, 2, 1), + SOUND("PlatformStop", 40, 2, 1), + SOUND("StoneMove", 32, 2, 1), + SOUND("MetalMove", 32, 2, 1), + SOUND("DoorOpen", 36, 2, 1), + SOUND("DoorLocked", 36, 2, 1), + SOUND("DoorOpenMetal", 36, 2, 1), + SOUND("DoorCloseMetal", 36, 2, 1), + SOUND("DoorCloseLight", 36, 2, 1), + SOUND("DoorCloseHeavy", 36, 2, 1), + SOUND("DoorCreak", 36, 2, 1), + SOUND("PickupWeapon", 36, 2, 0), + SOUND("PickupArtifact", 36, 2, 1), + SOUND("PickupKey", 36, 2, 1), + SOUND("PickupItem", 36, 2, 1), + SOUND("PickupPiece", 36, 2, 0), + SOUND("WeaponBuild", 36, 2, 0), + SOUND("UseArtifact", 36, 2, 1), + SOUND("BlastRadius", 36, 2, 1), + SOUND("Teleport", 256, 2, 1), + SOUND("ThunderCrash", 30, 2, 1), + SOUND("FighterPunchMiss", 80, 2, 1), + SOUND("FighterPunchHitThing", 80, 2, 1), + SOUND("FighterPunchHitWall", 80, 2, 1), + SOUND("FighterGrunt", 80, 2, 1), + SOUND("FighterAxeHitThing", 80, 2, 1), + SOUND("FighterHammerMiss", 80, 2, 1), + SOUND("FighterHammerHitThing", 80, 2, 1), + SOUND("FighterHammerHitWall", 80, 2, 1), + SOUND("FighterHammerContinuous", 32, 2, 1), + SOUND("FighterHammerExplode", 80, 2, 1), + SOUND("FighterSwordFire", 80, 2, 1), + SOUND("FighterSwordExplode", 80, 2, 1), + SOUND("ClericCStaffFire", 80, 2, 1), + SOUND("ClericCStaffExplode", 40, 2, 1), + SOUND("ClericCStaffHitThing", 80, 2, 1), + SOUND("ClericFlameFire", 80, 2, 1), + SOUND("ClericFlameExplode", 80, 2, 1), + SOUND("ClericFlameCircle", 80, 2, 1), + SOUND("MageWandFire", 80, 2, 1), + SOUND("MageLightningFire", 80, 2, 1), + SOUND("MageLightningZap", 32, 2, 1), + SOUND("MageLightningContinuous", 32, 2, 1), + SOUND("MageLightningReady", 30, 2, 1), + SOUND("MageShardsFire", 80, 2, 1), + SOUND("MageShardsExplode", 36, 2, 1), + SOUND("MageStaffFire", 80, 2, 1), + SOUND("MageStaffExplode", 40, 2, 1), + SOUND("Switch1", 32, 2, 1), + SOUND("Switch2", 32, 2, 1), + SOUND("SerpentSight", 32, 2, 1), + SOUND("SerpentActive", 32, 2, 1), + SOUND("SerpentPain", 32, 2, 1), + SOUND("SerpentAttack", 32, 2, 1), + SOUND("SerpentMeleeHit", 32, 2, 1), + SOUND("SerpentDeath", 40, 2, 1), + SOUND("SerpentBirth", 32, 2, 1), + SOUND("SerpentFXContinuous", 32, 2, 1), + SOUND("SerpentFXHit", 32, 2, 1), + SOUND("PotteryExplode", 32, 2, 1), + SOUND("Drip", 32, 2, 1), + SOUND("CentaurSight", 32, 2, 1), + SOUND("CentaurActive", 32, 2, 1), + SOUND("CentaurPain", 32, 2, 1), + SOUND("CentaurAttack", 32, 2, 1), + SOUND("CentaurDeath", 40, 2, 1), + SOUND("CentaurLeaderAttack", 32, 2, 1), + SOUND("CentaurMissileExplode", 32, 2, 1), + SOUND("Wind", 1, 2, 1), + SOUND("BishopSight", 32, 2, 1), + SOUND("BishopActive", 32, 2, 1), + SOUND("BishopPain", 32, 2, 1), + SOUND("BishopAttack", 32, 2, 1), + SOUND("BishopDeath", 40, 2, 1), + SOUND("BishopMissileExplode", 32, 2, 1), + SOUND("BishopBlur", 32, 2, 1), + SOUND("DemonSight", 32, 2, 1), + SOUND("DemonActive", 32, 2, 1), + SOUND("DemonPain", 32, 2, 1), + SOUND("DemonAttack", 32, 2, 1), + SOUND("DemonMissileFire", 32, 2, 1), + SOUND("DemonMissileExplode", 32, 2, 1), + SOUND("DemonDeath", 40, 2, 1), + SOUND("WraithSight", 32, 2, 1), + SOUND("WraithActive", 32, 2, 1), + SOUND("WraithPain", 32, 2, 1), + SOUND("WraithAttack", 32, 2, 1), + SOUND("WraithMissileFire", 32, 2, 1), + SOUND("WraithMissileExplode", 32, 2, 1), + SOUND("WraithDeath", 40, 2, 1), + SOUND("PigActive1", 32, 2, 1), + SOUND("PigActive2", 32, 2, 1), + SOUND("PigPain", 32, 2, 1), + SOUND("PigAttack", 32, 2, 1), + SOUND("PigDeath", 40, 2, 1), + SOUND("MaulatorSight", 32, 2, 1), + SOUND("MaulatorActive", 32, 2, 1), + SOUND("MaulatorPain", 32, 2, 1), + SOUND("MaulatorHamSwing", 32, 2, 1), + SOUND("MaulatorHamHit", 32, 2, 1), + SOUND("MaulatorMissileHit", 32, 2, 1), + SOUND("MaulatorDeath", 40, 2, 1), + SOUND("FreezeDeath", 40, 2, 1), + SOUND("FreezeShatter", 40, 2, 1), + SOUND("EttinSight", 32, 2, 1), + SOUND("EttinActive", 32, 2, 1), + SOUND("EttinPain", 32, 2, 1), + SOUND("EttinAttack", 32, 2, 1), + SOUND("EttinDeath", 40, 2, 1), + SOUND("FireDemonSpawn", 32, 2, 1), + SOUND("FireDemonActive", 32, 2, 1), + SOUND("FireDemonPain", 32, 2, 1), + SOUND("FireDemonAttack", 32, 2, 1), + SOUND("FireDemonMissileHit", 32, 2, 1), + SOUND("FireDemonDeath", 40, 2, 1), + SOUND("IceGuySight", 32, 2, 1), + SOUND("IceGuyActive", 32, 2, 1), + SOUND("IceGuyAttack", 32, 2, 1), + SOUND("IceGuyMissileExplode", 32, 2, 1), + SOUND("SorcererSight", 256, 2, 1), + SOUND("SorcererActive", 256, 2, 1), + SOUND("SorcererPain", 256, 2, 1), + SOUND("SorcererSpellCast", 256, 2, 1), + SOUND("SorcererBallWoosh", 256, 4, 1), + SOUND("SorcererDeathScream", 256, 2, 1), + SOUND("SorcererBishopSpawn", 80, 2, 1), + SOUND("SorcererBallPop", 80, 2, 1), + SOUND("SorcererBallBounce", 80, 3, 1), + SOUND("SorcererBallExplode", 80, 3, 1), + SOUND("SorcererBigBallExplode", 80, 3, 1), + SOUND("SorcererHeadScream", 256, 2, 1), + SOUND("DragonSight", 64, 2, 1), + SOUND("DragonActive", 64, 2, 1), + SOUND("DragonWingflap", 64, 2, 1), + SOUND("DragonAttack", 64, 2, 1), + SOUND("DragonPain", 64, 2, 1), + SOUND("DragonDeath", 64, 2, 1), + SOUND("DragonFireballExplode", 32, 2, 1), + SOUND("KoraxSight", 256, 2, 1), + SOUND("KoraxActive", 256, 2, 1), + SOUND("KoraxPain", 256, 2, 1), + SOUND("KoraxAttack", 256, 2, 1), + SOUND("KoraxCommand", 256, 2, 1), + SOUND("KoraxDeath", 256, 2, 1), + SOUND("KoraxStep", 128, 2, 1), + SOUND("ThrustSpikeRaise", 32, 2, 1), + SOUND("ThrustSpikeLower", 32, 2, 1), + SOUND("GlassShatter", 32, 2, 1), + SOUND("FlechetteBounce", 32, 2, 1), + SOUND("FlechetteExplode", 32, 2, 1), + SOUND("LavaMove", 36, 2, 1), + SOUND("WaterMove", 36, 2, 1), + SOUND("IceStartMove", 36, 2, 1), + SOUND("EarthStartMove", 36, 2, 1), + SOUND("WaterSplash", 32, 2, 1), + SOUND("LavaSizzle", 32, 2, 1), + SOUND("SludgeGloop", 32, 2, 1), + SOUND("HolySymbolFire", 64, 2, 1), + SOUND("SpiritActive", 32, 2, 1), + SOUND("SpiritAttack", 32, 2, 1), + SOUND("SpiritDie", 32, 2, 1), + SOUND("ValveTurn", 36, 2, 1), + SOUND("RopePull", 36, 2, 1), + SOUND("FlyBuzz", 20, 2, 1), + SOUND("Ignite", 32, 2, 1), + SOUND("PuzzleSuccess", 256, 2, 1), + SOUND("PuzzleFailFighter", 256, 2, 1), + SOUND("PuzzleFailCleric", 256, 2, 1), + SOUND("PuzzleFailMage", 256, 2, 1), + SOUND("Earthquake", 32, 2, 1), + SOUND("BellRing", 32, 2, 0), + SOUND("TreeBreak", 32, 2, 1), + SOUND("TreeExplode", 32, 2, 1), + SOUND("SuitofArmorBreak", 32, 2, 1), + SOUND("PoisonShroomPain", 20, 2, 1), + SOUND("PoisonShroomDeath", 32, 2, 1), + SOUND("Ambient1", 1, 1, 1), + SOUND("Ambient2", 1, 1, 1), + SOUND("Ambient3", 1, 1, 1), + SOUND("Ambient4", 1, 1, 1), + SOUND("Ambient5", 1, 1, 1), + SOUND("Ambient6", 1, 1, 1), + SOUND("Ambient7", 1, 1, 1), + SOUND("Ambient8", 1, 1, 1), + SOUND("Ambient9", 1, 1, 1), + SOUND("Ambient10", 1, 1, 1), + SOUND("Ambient11", 1, 1, 1), + SOUND("Ambient12", 1, 1, 1), + SOUND("Ambient13", 1, 1, 1), + SOUND("Ambient14", 1, 1, 1), + SOUND("Ambient15", 1, 1, 1), + SOUND("StartupTick", 32, 2, 1), + SOUND("SwitchOtherLevel", 32, 2, 1), + SOUND("Respawn", 32, 2, 1), + SOUND("KoraxVoiceGreetings", 512, 2, 1), + SOUND("KoraxVoiceReady", 512, 2, 1), + SOUND("KoraxVoiceBlood", 512, 2, 1), + SOUND("KoraxVoiceGame", 512, 2, 1), + SOUND("KoraxVoiceBoard", 512, 2, 1), + SOUND("KoraxVoiceWorship", 512, 2, 1), + SOUND("KoraxVoiceMaybe", 512, 2, 1), + SOUND("KoraxVoiceStrong", 512, 2, 1), + SOUND("KoraxVoiceFace", 512, 2, 1), + SOUND("BatScream", 32, 2, 1), + SOUND("Chat", 512, 2, 1), + SOUND("MenuMove", 32, 2, 1), + SOUND("ClockTick", 32, 2, 1), + SOUND("Fireball", 32, 2, 1), + SOUND("PuppyBeat", 30, 2, 1), + SOUND("MysticIncant", 32, 4, 1), +}; diff --git a/games/NXDoom/src/hexen/sounds.h b/games/NXDoom/src/hexen/sounds.h new file mode 100644 index 00000000000..1fe2345f233 --- /dev/null +++ b/games/NXDoom/src/hexen/sounds.h @@ -0,0 +1,321 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __SOUNDSH__ +#define __SOUNDSH__ + +#include "i_sound.h" + +#define MAX_SND_DIST 2025 +#define MAX_CHANNELS 16 + +// Music identifiers + +typedef enum +{ + mus_e1m1, + mus_e1m2, + mus_e1m3, + mus_e1m4, + mus_e1m5, + mus_e1m6, + mus_e1m7, + mus_e1m8, + mus_e1m9, + mus_e2m1, + mus_e2m2, + mus_e2m3, + mus_e2m4, + mus_e2m5, + mus_e2m6, + mus_e2m7, + mus_e2m8, + mus_e2m9, + mus_e3m1, + mus_e3m2, + mus_e3m3, + mus_e3m4, + mus_e3m5, + mus_e3m6, + mus_e3m7, + mus_e3m8, + mus_e3m9, + mus_e4m1, + mus_titl, + mus_intr, + mus_cptd, + NUMMUSIC +} musicenum_t; + +// Sound identifiers + +typedef enum +{ + SFX_NONE, + SFX_PLAYER_FIGHTER_NORMAL_DEATH, // class specific death screams + SFX_PLAYER_FIGHTER_CRAZY_DEATH, + SFX_PLAYER_FIGHTER_EXTREME1_DEATH, + SFX_PLAYER_FIGHTER_EXTREME2_DEATH, + SFX_PLAYER_FIGHTER_EXTREME3_DEATH, + SFX_PLAYER_FIGHTER_BURN_DEATH, + SFX_PLAYER_CLERIC_NORMAL_DEATH, + SFX_PLAYER_CLERIC_CRAZY_DEATH, + SFX_PLAYER_CLERIC_EXTREME1_DEATH, + SFX_PLAYER_CLERIC_EXTREME2_DEATH, + SFX_PLAYER_CLERIC_EXTREME3_DEATH, + SFX_PLAYER_CLERIC_BURN_DEATH, + SFX_PLAYER_MAGE_NORMAL_DEATH, + SFX_PLAYER_MAGE_CRAZY_DEATH, + SFX_PLAYER_MAGE_EXTREME1_DEATH, + SFX_PLAYER_MAGE_EXTREME2_DEATH, + SFX_PLAYER_MAGE_EXTREME3_DEATH, + SFX_PLAYER_MAGE_BURN_DEATH, + SFX_PLAYER_FIGHTER_PAIN, + SFX_PLAYER_CLERIC_PAIN, + SFX_PLAYER_MAGE_PAIN, + SFX_PLAYER_FIGHTER_GRUNT, + SFX_PLAYER_CLERIC_GRUNT, + SFX_PLAYER_MAGE_GRUNT, + SFX_PLAYER_LAND, + SFX_PLAYER_POISONCOUGH, + SFX_PLAYER_FIGHTER_FALLING_SCREAM, // class specific falling screams + SFX_PLAYER_CLERIC_FALLING_SCREAM, + SFX_PLAYER_MAGE_FALLING_SCREAM, + SFX_PLAYER_FALLING_SPLAT, + SFX_PLAYER_FIGHTER_FAILED_USE, + SFX_PLAYER_CLERIC_FAILED_USE, + SFX_PLAYER_MAGE_FAILED_USE, + SFX_PLATFORM_START, + SFX_PLATFORM_STARTMETAL, + SFX_PLATFORM_STOP, + SFX_STONE_MOVE, + SFX_METAL_MOVE, + SFX_DOOR_OPEN, + SFX_DOOR_LOCKED, + SFX_DOOR_METAL_OPEN, + SFX_DOOR_METAL_CLOSE, + SFX_DOOR_LIGHT_CLOSE, + SFX_DOOR_HEAVY_CLOSE, + SFX_DOOR_CREAK, + SFX_PICKUP_WEAPON, + SFX_PICKUP_ARTIFACT, + SFX_PICKUP_KEY, + SFX_PICKUP_ITEM, + SFX_PICKUP_PIECE, + SFX_WEAPON_BUILD, + SFX_ARTIFACT_USE, + SFX_ARTIFACT_BLAST, + SFX_TELEPORT, + SFX_THUNDER_CRASH, + SFX_FIGHTER_PUNCH_MISS, + SFX_FIGHTER_PUNCH_HITTHING, + SFX_FIGHTER_PUNCH_HITWALL, + SFX_FIGHTER_GRUNT, + SFX_FIGHTER_AXE_HITTHING, + SFX_FIGHTER_HAMMER_MISS, + SFX_FIGHTER_HAMMER_HITTHING, + SFX_FIGHTER_HAMMER_HITWALL, + SFX_FIGHTER_HAMMER_CONTINUOUS, + SFX_FIGHTER_HAMMER_EXPLODE, + SFX_FIGHTER_SWORD_FIRE, + SFX_FIGHTER_SWORD_EXPLODE, + SFX_CLERIC_CSTAFF_FIRE, + SFX_CLERIC_CSTAFF_EXPLODE, + SFX_CLERIC_CSTAFF_HITTHING, + SFX_CLERIC_FLAME_FIRE, + SFX_CLERIC_FLAME_EXPLODE, + SFX_CLERIC_FLAME_CIRCLE, + SFX_MAGE_WAND_FIRE, + SFX_MAGE_LIGHTNING_FIRE, + SFX_MAGE_LIGHTNING_ZAP, + SFX_MAGE_LIGHTNING_CONTINUOUS, + SFX_MAGE_LIGHTNING_READY, + SFX_MAGE_SHARDS_FIRE, + SFX_MAGE_SHARDS_EXPLODE, + SFX_MAGE_STAFF_FIRE, + SFX_MAGE_STAFF_EXPLODE, + SFX_SWITCH1, + SFX_SWITCH2, + SFX_SERPENT_SIGHT, + SFX_SERPENT_ACTIVE, + SFX_SERPENT_PAIN, + SFX_SERPENT_ATTACK, + SFX_SERPENT_MELEEHIT, + SFX_SERPENT_DEATH, + SFX_SERPENT_BIRTH, + SFX_SERPENTFX_CONTINUOUS, + SFX_SERPENTFX_HIT, + SFX_POTTERY_EXPLODE, + SFX_DRIP, + SFX_CENTAUR_SIGHT, + SFX_CENTAUR_ACTIVE, + SFX_CENTAUR_PAIN, + SFX_CENTAUR_ATTACK, + SFX_CENTAUR_DEATH, + SFX_CENTAURLEADER_ATTACK, + SFX_CENTAUR_MISSILE_EXPLODE, + SFX_WIND, + SFX_BISHOP_SIGHT, + SFX_BISHOP_ACTIVE, + SFX_BISHOP_PAIN, + SFX_BISHOP_ATTACK, + SFX_BISHOP_DEATH, + SFX_BISHOP_MISSILE_EXPLODE, + SFX_BISHOP_BLUR, + SFX_DEMON_SIGHT, + SFX_DEMON_ACTIVE, + SFX_DEMON_PAIN, + SFX_DEMON_ATTACK, + SFX_DEMON_MISSILE_FIRE, + SFX_DEMON_MISSILE_EXPLODE, + SFX_DEMON_DEATH, + SFX_WRAITH_SIGHT, + SFX_WRAITH_ACTIVE, + SFX_WRAITH_PAIN, + SFX_WRAITH_ATTACK, + SFX_WRAITH_MISSILE_FIRE, + SFX_WRAITH_MISSILE_EXPLODE, + SFX_WRAITH_DEATH, + SFX_PIG_ACTIVE1, + SFX_PIG_ACTIVE2, + SFX_PIG_PAIN, + SFX_PIG_ATTACK, + SFX_PIG_DEATH, + SFX_MAULATOR_SIGHT, + SFX_MAULATOR_ACTIVE, + SFX_MAULATOR_PAIN, + SFX_MAULATOR_HAMMER_SWING, + SFX_MAULATOR_HAMMER_HIT, + SFX_MAULATOR_MISSILE_HIT, + SFX_MAULATOR_DEATH, + SFX_FREEZE_DEATH, + SFX_FREEZE_SHATTER, + SFX_ETTIN_SIGHT, + SFX_ETTIN_ACTIVE, + SFX_ETTIN_PAIN, + SFX_ETTIN_ATTACK, + SFX_ETTIN_DEATH, + SFX_FIRED_SPAWN, + SFX_FIRED_ACTIVE, + SFX_FIRED_PAIN, + SFX_FIRED_ATTACK, + SFX_FIRED_MISSILE_HIT, + SFX_FIRED_DEATH, + SFX_ICEGUY_SIGHT, + SFX_ICEGUY_ACTIVE, + SFX_ICEGUY_ATTACK, + SFX_ICEGUY_FX_EXPLODE, + SFX_SORCERER_SIGHT, + SFX_SORCERER_ACTIVE, + SFX_SORCERER_PAIN, + SFX_SORCERER_SPELLCAST, + SFX_SORCERER_BALLWOOSH, + SFX_SORCERER_DEATHSCREAM, + SFX_SORCERER_BISHOPSPAWN, + SFX_SORCERER_BALLPOP, + SFX_SORCERER_BALLBOUNCE, + SFX_SORCERER_BALLEXPLODE, + SFX_SORCERER_BIGBALLEXPLODE, + SFX_SORCERER_HEADSCREAM, + SFX_DRAGON_SIGHT, + SFX_DRAGON_ACTIVE, + SFX_DRAGON_WINGFLAP, + SFX_DRAGON_ATTACK, + SFX_DRAGON_PAIN, + SFX_DRAGON_DEATH, + SFX_DRAGON_FIREBALL_EXPLODE, + SFX_KORAX_SIGHT, + SFX_KORAX_ACTIVE, + SFX_KORAX_PAIN, + SFX_KORAX_ATTACK, + SFX_KORAX_COMMAND, + SFX_KORAX_DEATH, + SFX_KORAX_STEP, + SFX_THRUSTSPIKE_RAISE, + SFX_THRUSTSPIKE_LOWER, + SFX_STAINEDGLASS_SHATTER, + SFX_FLECHETTE_BOUNCE, + SFX_FLECHETTE_EXPLODE, + SFX_LAVA_MOVE, + SFX_WATER_MOVE, + SFX_ICE_STARTMOVE, + SFX_EARTH_STARTMOVE, + SFX_WATER_SPLASH, + SFX_LAVA_SIZZLE, + SFX_SLUDGE_GLOOP, + SFX_CHOLY_FIRE, + SFX_SPIRIT_ACTIVE, + SFX_SPIRIT_ATTACK, + SFX_SPIRIT_DIE, + SFX_VALVE_TURN, + SFX_ROPE_PULL, + SFX_FLY_BUZZ, + SFX_IGNITE, + SFX_PUZZLE_SUCCESS, + SFX_PUZZLE_FAIL_FIGHTER, + SFX_PUZZLE_FAIL_CLERIC, + SFX_PUZZLE_FAIL_MAGE, + SFX_EARTHQUAKE, + SFX_BELLRING, + SFX_TREE_BREAK, + SFX_TREE_EXPLODE, + SFX_SUITOFARMOR_BREAK, + SFX_POISONSHROOM_PAIN, + SFX_POISONSHROOM_DEATH, + SFX_AMBIENT1, + SFX_AMBIENT2, + SFX_AMBIENT3, + SFX_AMBIENT4, + SFX_AMBIENT5, + SFX_AMBIENT6, + SFX_AMBIENT7, + SFX_AMBIENT8, + SFX_AMBIENT9, + SFX_AMBIENT10, + SFX_AMBIENT11, + SFX_AMBIENT12, + SFX_AMBIENT13, + SFX_AMBIENT14, + SFX_AMBIENT15, + SFX_STARTUP_TICK, + SFX_SWITCH_OTHERLEVEL, + SFX_RESPAWN, + SFX_KORAX_VOICE_1, + SFX_KORAX_VOICE_2, + SFX_KORAX_VOICE_3, + SFX_KORAX_VOICE_4, + SFX_KORAX_VOICE_5, + SFX_KORAX_VOICE_6, + SFX_KORAX_VOICE_7, + SFX_KORAX_VOICE_8, + SFX_KORAX_VOICE_9, + SFX_BAT_SCREAM, + SFX_CHAT, + SFX_MENU_MOVE, + SFX_CLOCK_TICK, + SFX_FIREBALL, + SFX_PUPPYBEAT, + SFX_MYSTICINCANT, + NUMSFX +} sfxenum_t; + + +extern sfxinfo_t S_sfx[]; +extern musicinfo_t S_music[]; + + +#endif diff --git a/games/NXDoom/src/hexen/st_start.c b/games/NXDoom/src/hexen/st_start.c new file mode 100644 index 00000000000..aa104358db1 --- /dev/null +++ b/games/NXDoom/src/hexen/st_start.c @@ -0,0 +1,310 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + + +// HEADER FILES ------------------------------------------------------------ + +#include + +#include "config.h" + +#include "h2def.h" +#include "i_system.h" +#include "i_video.h" +#include "i_videohr.h" +#include "s_sound.h" +#include "st_start.h" + + +// MACROS ------------------------------------------------------------------ +#define ST_MAX_NOTCHES 32 +#define ST_NOTCH_WIDTH 16 +#define ST_NOTCH_HEIGHT 23 +#define ST_PROGRESS_X 64 // Start of notches x screen pos. +#define ST_PROGRESS_Y 441 // Start of notches y screen pos. + +#define ST_NETPROGRESS_X 288 +#define ST_NETPROGRESS_Y 32 +#define ST_NETNOTCH_WIDTH 8 +#define ST_NETNOTCH_HEIGHT 16 +#define ST_MAX_NETNOTCHES 8 + +byte *ST_LoadScreen(void); +void ST_UpdateNotches(int notchPosition); +void ST_UpdateNetNotches(int notchPosition); + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ +static const byte *bitmap = NULL; +int graphical_startup = 1; +static boolean using_graphical_startup; + +static const byte notchTable[] = { + // plane 0 + 0x00, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xC0, + 0x0F, 0x90, 0x1B, 0x68, 0x3D, 0xBC, 0x3F, 0xFC, 0x20, 0x08, 0x20, 0x08, + 0x2F, 0xD8, 0x37, 0xD8, 0x37, 0xF8, 0x1F, 0xF8, 0x1C, 0x50, + + // plane 1 + 0x00, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xA0, + 0x30, 0x6C, 0x24, 0x94, 0x42, 0x4A, 0x60, 0x0E, 0x60, 0x06, 0x7F, 0xF6, + 0x7F, 0xF6, 0x7F, 0xF6, 0x5E, 0xF6, 0x38, 0x16, 0x23, 0xAC, + + // plane 2 + 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xE0, + 0x30, 0x6C, 0x24, 0x94, 0x52, 0x6A, 0x7F, 0xFE, 0x60, 0x0E, 0x60, 0x0E, + 0x6F, 0xD6, 0x77, 0xD6, 0x56, 0xF6, 0x38, 0x36, 0x23, 0xAC, + + // plane 3 + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x02, 0x40, + 0x0F, 0x90, 0x1B, 0x68, 0x3D, 0xB4, 0x1F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8, + 0x10, 0x28, 0x08, 0x28, 0x29, 0x08, 0x07, 0xE8, 0x1C, 0x50 +}; + + +// Red Network Progress notches +static const byte netnotchTable[] = { + // plane 0 + 0x80, 0x50, 0xD0, 0xf0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xD0, 0xF0, 0xC0, + 0x70, 0x50, 0x80, 0x60, + + // plane 1 + 0x60, 0xE0, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0xA0, + 0xA0, 0xE0, 0x60, 0x00, + + // plane 2 + 0x80, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, + 0x10, 0x10, 0x80, 0x60, + + // plane 3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +// CODE -------------------------------------------------------------------- + + + +//-------------------------------------------------------------------------- +// +// Startup Screen Functions +// +//-------------------------------------------------------------------------- + + +//========================================================================== +// +// ST_Init - Do the startup screen +// +//========================================================================== + +void ST_Init(void) +{ + byte *pal; + byte *buffer; + + using_graphical_startup = false; + + if (graphical_startup && !debugmode && !testcontrols) + { + I_SetWindowTitleHR("Hexen startup - " PACKAGE_STRING); + + // Set 640x480x16 mode + if (I_SetVideoModeHR()) + { + using_graphical_startup = true; + I_InitWindowIcon(); + + S_StartSongName("orb", true); + + I_ClearScreenHR(); + I_InitPaletteHR(); + I_BlackPaletteHR(); + + // Load graphic + buffer = ST_LoadScreen(); + pal = buffer; + bitmap = buffer + 16 * 3; + + I_SlamHR(bitmap); + I_FadeToPaletteHR(pal); + Z_Free(buffer); + } + } +} + +void ST_Done(void) +{ + if (using_graphical_startup) + { + I_ClearScreenHR(); + I_UnsetVideoModeHR(); + } +} + + +//========================================================================== +// +// ST_UpdateNotches +// +//========================================================================== + +void ST_UpdateNotches(int notchPosition) +{ + int x = ST_PROGRESS_X + notchPosition * ST_NOTCH_WIDTH; + int y = ST_PROGRESS_Y; + I_SlamBlockHR(x, y, ST_NOTCH_WIDTH, ST_NOTCH_HEIGHT, notchTable); +} + + +//========================================================================== +// +// ST_UpdateNetNotches - indicates network progress +// +//========================================================================== + +void ST_UpdateNetNotches(int notchPosition) +{ + int x = ST_NETPROGRESS_X + notchPosition * ST_NETNOTCH_WIDTH; + int y = ST_NETPROGRESS_Y; + I_SlamBlockHR(x, y, ST_NETNOTCH_WIDTH, ST_NETNOTCH_HEIGHT, netnotchTable); +} + + +//========================================================================== +// +// ST_Progress - increments progress indicator +// +//========================================================================== + +void ST_Progress(void) +{ + // Check for ESC press -- during startup all events eaten here + if (I_CheckAbortHR()) + { + I_Quit(); + } + + if (using_graphical_startup) + { + static int notchPosition = 0; + + if (notchPosition < ST_MAX_NOTCHES) + { + ST_UpdateNotches(notchPosition); + S_StartSound(NULL, SFX_STARTUP_TICK); + //I_Sleep(1000); + notchPosition++; + } + } + + printf("."); +} + + +//========================================================================== +// +// ST_NetProgress - indicates network progress +// +//========================================================================== + +void ST_NetProgress(void) +{ + printf("*"); + + if (using_graphical_startup) + { + static int netnotchPosition = 0; + + if (netnotchPosition < ST_MAX_NETNOTCHES) + { + ST_UpdateNetNotches(netnotchPosition); + S_StartSound(NULL, SFX_DRIP); + netnotchPosition++; + } + } +} + + +//========================================================================== +// +// ST_NetDone - net progress complete +// +//========================================================================== +void ST_NetDone(void) +{ + if (using_graphical_startup) + { + S_StartSound(NULL, SFX_PICKUP_WEAPON); + } +} + + +//========================================================================== +// +// ST_Message - gives debug message +// +//========================================================================== + +void ST_Message(const char *message, ...) +{ + va_list argptr; + + va_start(argptr, message); + vprintf(message, argptr); + va_end(argptr); +} + +//========================================================================== +// +// ST_RealMessage - gives user message +// +//========================================================================== + +void ST_RealMessage(const char *message, ...) +{ + va_list argptr; + + va_start(argptr, message); + vprintf(message, argptr); + va_end(argptr); +} + + + +//========================================================================== +// +// ST_LoadScreen - loads startup graphic +// +//========================================================================== + + +byte *ST_LoadScreen(void) +{ + int length, lump; + byte *buffer; + + lump = W_GetNumForName("STARTUP"); + length = W_LumpLength(lump); + buffer = (byte *) Z_Malloc(length, PU_STATIC, NULL); + W_ReadLump(lump, buffer); + return (buffer); +} + diff --git a/games/NXDoom/src/hexen/st_start.h b/games/NXDoom/src/hexen/st_start.h new file mode 100644 index 00000000000..d38d28303a5 --- /dev/null +++ b/games/NXDoom/src/hexen/st_start.h @@ -0,0 +1,41 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef STSTART_H +#define STSTART_H + +#include "doomtype.h" + +// HEADER FILES ------------------------------------------------------------ + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- +extern void ST_Init(void); +extern void ST_Done(void); +extern void ST_Message(const char *message, ...) PRINTF_ATTR(1, 2); +extern void ST_RealMessage(const char *message, ...) PRINTF_ATTR(1, 2); +extern void ST_Progress(void); +extern void ST_NetProgress(void); +extern void ST_NetDone(void); + +// PUBLIC DATA DECLARATIONS ------------------------------------------------ + +extern int graphical_startup; + +#endif diff --git a/games/NXDoom/src/hexen/sv_save.c b/games/NXDoom/src/hexen/sv_save.c new file mode 100644 index 00000000000..007e63340f9 --- /dev/null +++ b/games/NXDoom/src/hexen/sv_save.c @@ -0,0 +1,3508 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// HEADER FILES ------------------------------------------------------------ + +#include "h2def.h" +#include "i_system.h" +#include "m_misc.h" +#include "i_swap.h" +#include "p_local.h" + +// MACROS ------------------------------------------------------------------ + +#define MAX_TARGET_PLAYERS 512 +#define MOBJ_NULL -1 +#define MOBJ_XX_PLAYER -2 +#define MAX_MAPS 99 +#define BASE_SLOT 6 +#define REBORN_SLOT 7 +#define REBORN_DESCRIPTION "TEMP GAME" +#define MAX_THINKER_SIZE 256 + +// TYPES ------------------------------------------------------------------- + +typedef enum +{ + ASEG_GAME_HEADER = 101, + ASEG_MAP_HEADER, + ASEG_WORLD, + ASEG_POLYOBJS, + ASEG_MOBJS, + ASEG_THINKERS, + ASEG_SCRIPTS, + ASEG_PLAYERS, + ASEG_SOUNDS, + ASEG_MISC, + ASEG_END +} gameArchiveSegment_t; + +typedef enum +{ + TC_NULL, + TC_MOVE_CEILING, + TC_VERTICAL_DOOR, + TC_MOVE_FLOOR, + TC_PLAT_RAISE, + TC_INTERPRET_ACS, + TC_FLOOR_WAGGLE, + TC_LIGHT, + TC_PHASE, + TC_BUILD_PILLAR, + TC_ROTATE_POLY, + TC_MOVE_POLY, + TC_POLY_DOOR +} thinkClass_t; + +typedef struct +{ + thinkClass_t tClass; + think_t thinkerFunc; + void (*writeFunc)(thinker_t *thinker); + void (*readFunc)(thinker_t *thinker); + void (*restoreFunc)(thinker_t *thinker); + size_t size; +} thinkInfo_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; +} ssthinker_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +void P_SpawnPlayer(mapthing_t * mthing); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void ArchiveWorld(void); +static void UnarchiveWorld(void); +static void ArchivePolyobjs(void); +static void UnarchivePolyobjs(void); +static void ArchiveMobjs(void); +static void UnarchiveMobjs(void); +static void ArchiveThinkers(void); +static void UnarchiveThinkers(void); +static void ArchiveScripts(void); +static void UnarchiveScripts(void); +static void ArchivePlayers(void); +static void UnarchivePlayers(void); +static void ArchiveSounds(void); +static void UnarchiveSounds(void); +static void ArchiveMisc(void); +static void UnarchiveMisc(void); +static void SetMobjArchiveNums(void); +static void RemoveAllThinkers(void); +static int GetMobjNum(mobj_t * mobj); +static void SetMobjPtr(mobj_t **ptr, unsigned int archiveNum); +static void RestoreSSThinker(thinker_t *sst); +static void RestorePlatRaise(thinker_t *thinker); +static void RestoreMoveCeiling(thinker_t *thinker); +static void AssertSegment(gameArchiveSegment_t segType); +static void ClearSaveSlot(int slot); +static void CopySaveSlot(int sourceSlot, int destSlot); +static void CopyFile(char *sourceName, char *destName); +static boolean ExistingFile(char *name); +static void SV_OpenRead(char *fileName); +static void SV_OpenWrite(char *fileName); +static void SV_Close(void); +static void SV_Read(void *buffer, int size); +static byte SV_ReadByte(void); +static uint16_t SV_ReadWord(void); +static uint32_t SV_ReadLong(void); +static void *SV_ReadPtr(void); +static void SV_Write(const void *buffer, int size); +static void SV_WriteByte(byte val); +static void SV_WriteWord(unsigned short val); +static void SV_WriteLong(unsigned int val); +static void SV_WritePtr(void *ptr); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +#define DEFAULT_SAVEPATH "hexndata/" + +char *SavePath = DEFAULT_SAVEPATH; + +int vanilla_savegame_limit = 1; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static int MobjCount; +static mobj_t **MobjList; +static mobj_t ***TargetPlayerAddrs; +static int TargetPlayerCount; +static boolean SavingPlayers; +static FILE *SavingFP; + +// CODE -------------------------------------------------------------------- + +// Autogenerated functions for reading/writing structs: + +// +// acsstore_t +// + +static void StreamIn_acsstore_t(acsstore_t *str) +{ + int i; + + // int map; + str->map = SV_ReadLong(); + + // int script; + str->script = SV_ReadLong(); + + // byte args[4]; + for (i=0; i<4; ++i) + { + str->args[i] = SV_ReadByte(); + } +} + +static void StreamOut_acsstore_t(acsstore_t *str) +{ + int i; + + // int map; + SV_WriteLong(str->map); + + // int script; + SV_WriteLong(str->script); + + // byte args[4]; + for (i=0; i<4; ++i) + { + SV_WriteByte(str->args[i]); + } +} + + +// +// ticcmd_t +// (this is based on the Vanilla definition of the struct) +// + +static void StreamIn_ticcmd_t(ticcmd_t *str) +{ + // char forwardmove; + str->forwardmove = SV_ReadByte(); + + // char sidemove; + str->sidemove = SV_ReadByte(); + + // short angleturn; + str->angleturn = SV_ReadWord(); + + // short consistancy; + str->consistancy = SV_ReadWord(); + + // byte chatchar; + str->chatchar = SV_ReadByte(); + + // byte buttons; + str->buttons = SV_ReadByte(); + + // byte lookfly; + str->lookfly = SV_ReadByte(); + + // byte arti; + str->arti = SV_ReadByte(); +} + +static void StreamOut_ticcmd_t(ticcmd_t *str) +{ + // char forwardmove; + SV_WriteByte(str->forwardmove); + + // char sidemove; + SV_WriteByte(str->sidemove); + + // short angleturn; + SV_WriteWord(str->angleturn); + + // short consistancy; + SV_WriteWord(str->consistancy); + + // byte chatchar; + SV_WriteByte(str->chatchar); + + // byte buttons; + SV_WriteByte(str->buttons); + + // byte lookfly; + SV_WriteByte(str->lookfly); + + // byte arti; + SV_WriteByte(str->arti); +} + + + +// +// inventory_t +// + +static void StreamIn_inventory_t(inventory_t *str) +{ + // int type; + str->type = SV_ReadLong(); + + // int count; + str->count = SV_ReadLong(); +} + +static void StreamOut_inventory_t(inventory_t *str) +{ + // int type; + SV_WriteLong(str->type); + + // int count; + SV_WriteLong(str->count); +} + + +// +// pspdef_t +// + +static void StreamIn_pspdef_t(pspdef_t *str) +{ + int state_num; + + // state_t *state; + + // This is a pointer; it is stored as an index into the states table. + + state_num = SV_ReadLong(); + + if (state_num != 0) + { + str->state = states + state_num; + } + else + { + str->state = NULL; + } + + // int tics; + str->tics = SV_ReadLong(); + + // fixed_t sx, sy; + str->sx = SV_ReadLong(); + str->sy = SV_ReadLong(); +} + +static void StreamOut_pspdef_t(pspdef_t *str) +{ + // state_t *state; + // This is a pointer; store the index in the states table, + // rather than the pointer itself. + if (str->state != NULL) + { + SV_WriteLong(str->state - states); + } + else + { + SV_WriteLong(0); + } + + // int tics; + SV_WriteLong(str->tics); + + // fixed_t sx, sy; + SV_WriteLong(str->sx); + SV_WriteLong(str->sy); +} + + +// +// player_t +// + +static void StreamIn_player_t(player_t *str) +{ + int i; + + // mobj_t *mo; + // Pointer value is reset on load. + str->mo = SV_ReadPtr(); + str->mo = NULL; + + // playerstate_t playerstate; + str->playerstate = SV_ReadLong(); + + // ticcmd_t cmd; + StreamIn_ticcmd_t(&str->cmd); + + // pclass_t class; + str->class = SV_ReadLong(); + + // fixed_t viewz; + str->viewz = SV_ReadLong(); + + // fixed_t viewheight; + str->viewheight = SV_ReadLong(); + + // fixed_t deltaviewheight; + str->deltaviewheight = SV_ReadLong(); + + // fixed_t bob; + str->bob = SV_ReadLong(); + + // int flyheight; + str->flyheight = SV_ReadLong(); + + // int lookdir; + str->lookdir = SV_ReadLong(); + + // boolean centering; + str->centering = SV_ReadLong(); + + // int health; + str->health = SV_ReadLong(); + + // int armorpoints[NUMARMOR]; + for (i=0; iarmorpoints[i] = SV_ReadLong(); + } + + // inventory_t inventory[NUMINVENTORYSLOTS]; + for (i=0; iinventory[i]); + } + + // artitype_t readyArtifact; + str->readyArtifact = SV_ReadLong(); + + // int artifactCount; + str->artifactCount = SV_ReadLong(); + + // int inventorySlotNum; + str->inventorySlotNum = SV_ReadLong(); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i] = SV_ReadLong(); + } + + // int keys; + str->keys = SV_ReadLong(); + + // int pieces; + str->pieces = SV_ReadLong(); + + // signed int frags[MAXPLAYERS]; + for (i=0; ifrags[i] = SV_ReadLong(); + } + + // weapontype_t readyweapon; + str->readyweapon = SV_ReadLong(); + + // weapontype_t pendingweapon; + str->pendingweapon = SV_ReadLong(); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i] = SV_ReadLong(); + } + + // int mana[NUMMANA]; + for (i=0; imana[i] = SV_ReadLong(); + } + + // int attackdown, usedown; + str->attackdown = SV_ReadLong(); + str->usedown = SV_ReadLong(); + + // int cheats; + str->cheats = SV_ReadLong(); + + // int refire; + str->refire = SV_ReadLong(); + + // int killcount, itemcount, secretcount; + str->killcount = SV_ReadLong(); + str->itemcount = SV_ReadLong(); + str->secretcount = SV_ReadLong(); + + // char message[80]; + for (i=0; i<80; ++i) + { + str->message[i] = SV_ReadByte(); + } + + // int messageTics; + str->messageTics = SV_ReadLong(); + + // short ultimateMessage; + str->ultimateMessage = SV_ReadWord(); + + // short yellowMessage; + str->yellowMessage = SV_ReadWord(); + + // int damagecount, bonuscount; + str->damagecount = SV_ReadLong(); + str->bonuscount = SV_ReadLong(); + + // int poisoncount; + str->poisoncount = SV_ReadLong(); + + // mobj_t *poisoner; + // Pointer value is reset. + str->poisoner = SV_ReadPtr(); + str->poisoner = NULL; + + // mobj_t *attacker; + // Pointer value is reset. + str->attacker = SV_ReadPtr(); + str->attacker = NULL; + + // int extralight; + str->extralight = SV_ReadLong(); + + // int fixedcolormap; + str->fixedcolormap = SV_ReadLong(); + + // int colormap; + str->colormap = SV_ReadLong(); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // int morphTics; + str->morphTics = SV_ReadLong(); + + // unsigned int jumpTics; + str->jumpTics = SV_ReadLong(); + + // unsigned int worldTimer; + str->worldTimer = SV_ReadLong(); +} + +static void StreamOut_player_t(player_t *str) +{ + int i; + + // mobj_t *mo; + SV_WritePtr(str->mo); + + // playerstate_t playerstate; + SV_WriteLong(str->playerstate); + + // ticcmd_t cmd; + StreamOut_ticcmd_t(&str->cmd); + + // pclass_t class; + SV_WriteLong(str->class); + + // fixed_t viewz; + SV_WriteLong(str->viewz); + + // fixed_t viewheight; + SV_WriteLong(str->viewheight); + + // fixed_t deltaviewheight; + SV_WriteLong(str->deltaviewheight); + + // fixed_t bob; + SV_WriteLong(str->bob); + + // int flyheight; + SV_WriteLong(str->flyheight); + + // int lookdir; + SV_WriteLong(str->lookdir); + + // boolean centering; + SV_WriteLong(str->centering); + + // int health; + SV_WriteLong(str->health); + + // int armorpoints[NUMARMOR]; + for (i=0; iarmorpoints[i]); + } + + // inventory_t inventory[NUMINVENTORYSLOTS]; + for (i=0; iinventory[i]); + } + + // artitype_t readyArtifact; + SV_WriteLong(str->readyArtifact); + + // int artifactCount; + SV_WriteLong(str->artifactCount); + + // int inventorySlotNum; + SV_WriteLong(str->inventorySlotNum); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i]); + } + + // int keys; + SV_WriteLong(str->keys); + + // int pieces; + SV_WriteLong(str->pieces); + + // signed int frags[MAXPLAYERS]; + for (i=0; ifrags[i]); + } + + // weapontype_t readyweapon; + SV_WriteLong(str->readyweapon); + + // weapontype_t pendingweapon; + SV_WriteLong(str->pendingweapon); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i]); + } + + // int mana[NUMMANA]; + for (i=0; imana[i]); + } + + // int attackdown, usedown; + SV_WriteLong(str->attackdown); + SV_WriteLong(str->usedown); + + // int cheats; + SV_WriteLong(str->cheats); + + // int refire; + SV_WriteLong(str->refire); + + // int killcount, itemcount, secretcount; + SV_WriteLong(str->killcount); + SV_WriteLong(str->itemcount); + SV_WriteLong(str->secretcount); + + // char message[80]; + for (i=0; i<80; ++i) + { + SV_WriteByte(str->message[i]); + } + + // int messageTics; + SV_WriteLong(str->messageTics); + + // short ultimateMessage; + SV_WriteWord(str->ultimateMessage); + + // short yellowMessage; + SV_WriteWord(str->yellowMessage); + + // int damagecount, bonuscount; + SV_WriteLong(str->damagecount); + SV_WriteLong(str->bonuscount); + + // int poisoncount; + SV_WriteLong(str->poisoncount); + + // mobj_t *poisoner; + SV_WritePtr(str->poisoner); + + // mobj_t *attacker; + SV_WritePtr(str->attacker); + + // int extralight; + SV_WriteLong(str->extralight); + + // int fixedcolormap; + SV_WriteLong(str->fixedcolormap); + + // int colormap; + SV_WriteLong(str->colormap); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // int morphTics; + SV_WriteLong(str->morphTics); + + // unsigned int jumpTics; + SV_WriteLong(str->jumpTics); + + // unsigned int worldTimer; + SV_WriteLong(str->worldTimer); +} + + +// +// thinker_t +// + +static void StreamIn_thinker_t(thinker_t *str) +{ + // struct thinker_s *prev, *next; + // Pointers are discarded: + str->prev = SV_ReadPtr(); + str->prev = NULL; + str->next = SV_ReadPtr(); + str->next = NULL; + + // think_t function; + // Function pointer is discarded: + str->function = SV_ReadPtr(); + str->function = NULL; +} + +static void StreamOut_thinker_t(thinker_t *str) +{ + // struct thinker_s *prev, *next; + SV_WritePtr(str->prev); + SV_WritePtr(str->next); + + // think_t function; + SV_WritePtr(&str->function); +} + + +// +// mobj_t +// + +static void StreamInMobjSpecials(mobj_t *mobj) +{ + unsigned int special1, special2; + + special1 = SV_ReadLong(); + special2 = SV_ReadLong(); + + mobj->special1.i = special1; + mobj->special2.i = special2; + + switch (mobj->type) + { + // Just special1 + case MT_BISH_FX: + case MT_HOLY_FX: + case MT_DRAGON: + case MT_THRUSTFLOOR_UP: + case MT_THRUSTFLOOR_DOWN: + case MT_MINOTAUR: + case MT_SORCFX1: + SetMobjPtr(&mobj->special1.m, special1); + break; + + // Just special2 + case MT_LIGHTNING_FLOOR: + case MT_LIGHTNING_ZAP: + SetMobjPtr(&mobj->special2.m, special2); + break; + + // Both special1 and special2 + case MT_HOLY_TAIL: + case MT_LIGHTNING_CEILING: + SetMobjPtr(&mobj->special1.m, special1); + SetMobjPtr(&mobj->special2.m, special2); + break; + + default: + break; + } +} + +static void StreamIn_mobj_t(mobj_t *str) +{ + unsigned int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // fixed_t x, y, z; + str->x = SV_ReadLong(); + str->y = SV_ReadLong(); + str->z = SV_ReadLong(); + + // struct mobj_s *snext, *sprev; + // Pointer values are discarded: + str->snext = SV_ReadPtr(); + str->snext = NULL; + str->sprev = SV_ReadPtr(); + str->sprev = NULL; + + // angle_t angle; + str->angle = SV_ReadLong(); + + // spritenum_t sprite; + str->sprite = SV_ReadLong(); + + // int frame; + str->frame = SV_ReadLong(); + + // struct mobj_s *bnext, *bprev; + // Values are read but discarded; this will be restored when the thing's + // position is set. + str->bnext = SV_ReadPtr(); + str->bnext = NULL; + str->bprev = SV_ReadPtr(); + str->bprev = NULL; + + // struct subsector_s *subsector; + // Read but discard: pointer will be restored when thing position is set. + str->subsector = SV_ReadPtr(); + str->subsector = NULL; + + // fixed_t floorz, ceilingz; + str->floorz = SV_ReadLong(); + str->ceilingz = SV_ReadLong(); + + // fixed_t floorpic; + str->floorpic = SV_ReadLong(); + + // fixed_t radius, height; + str->radius = SV_ReadLong(); + str->height = SV_ReadLong(); + + // fixed_t momx, momy, momz; + str->momx = SV_ReadLong(); + str->momy = SV_ReadLong(); + str->momz = SV_ReadLong(); + + // int validcount; + str->validcount = SV_ReadLong(); + + // mobjtype_t type; + str->type = SV_ReadLong(); + + // mobjinfo_t *info; + // Pointer value is read but discarded. + str->info = SV_ReadPtr(); + str->info = NULL; + + // int tics; + str->tics = SV_ReadLong(); + + // state_t *state; + // Restore as index into states table. + i = SV_ReadLong(); + str->state = &states[i]; + + // int damage; + str->damage = SV_ReadLong(); + + // int flags; + str->flags = SV_ReadLong(); + + // int flags2; + str->flags2 = SV_ReadLong(); + + // specialval_t special1; + // specialval_t special2; + // Read in special values: there are special cases to deal with with + // mobj pointers. + StreamInMobjSpecials(str); + + // int health; + str->health = SV_ReadLong(); + + // int movedir; + str->movedir = SV_ReadLong(); + + // int movecount; + str->movecount = SV_ReadLong(); + + // struct mobj_s *target; + i = SV_ReadLong(); + SetMobjPtr(&str->target, i); + + // int reactiontime; + str->reactiontime = SV_ReadLong(); + + // int threshold; + str->threshold = SV_ReadLong(); + + // struct player_s *player; + // Saved as player number. + i = SV_ReadLong(); + if (i == 0) + { + str->player = NULL; + } + else + { + str->player = &players[i - 1]; + str->player->mo = str; + } + + // int lastlook; + str->lastlook = SV_ReadLong(); + + // fixed_t floorclip; + str->floorclip = SV_ReadLong(); + + // int archiveNum; + str->archiveNum = SV_ReadLong(); + + // short tid; + str->tid = SV_ReadWord(); + + // byte special; + str->special = SV_ReadByte(); + + // byte args[5]; + for (i=0; i<5; ++i) + { + str->args[i] = SV_ReadByte(); + } +} + +static void StreamOutMobjSpecials(mobj_t *mobj) +{ + unsigned int special1, special2; + boolean corpse; + + corpse = (mobj->flags & MF_CORPSE) != 0; + special1 = mobj->special1.i; + special2 = mobj->special2.i; + + switch (mobj->type) + { + // Just special1 + case MT_BISH_FX: + case MT_HOLY_FX: + case MT_DRAGON: + case MT_THRUSTFLOOR_UP: + case MT_THRUSTFLOOR_DOWN: + case MT_MINOTAUR: + case MT_SORCFX1: + case MT_MSTAFF_FX2: + if (corpse) + { + special1 = MOBJ_NULL; + } + else + { + special1 = GetMobjNum(mobj->special1.m); + } + break; + + // Just special2 + case MT_LIGHTNING_FLOOR: + case MT_LIGHTNING_ZAP: + if (corpse) + { + special2 = MOBJ_NULL; + } + else + { + special2 = GetMobjNum(mobj->special2.m); + } + break; + + // Both special1 and special2 + case MT_HOLY_TAIL: + case MT_LIGHTNING_CEILING: + if (corpse) + { + special1 = MOBJ_NULL; + special2 = MOBJ_NULL; + } + else + { + special1 = GetMobjNum(mobj->special1.m); + special2 = GetMobjNum(mobj->special2.m); + } + break; + + // Miscellaneous + case MT_KORAX: + special1 = 0; // Searching index + break; + + default: + break; + } + + // Write special values to savegame file. + + SV_WriteLong(special1); + SV_WriteLong(special2); +} + +static void StreamOut_mobj_t(mobj_t *str) +{ + int i; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // fixed_t x, y, z; + SV_WriteLong(str->x); + SV_WriteLong(str->y); + SV_WriteLong(str->z); + + // struct mobj_s *snext, *sprev; + SV_WritePtr(str->snext); + SV_WritePtr(str->sprev); + + // angle_t angle; + SV_WriteLong(str->angle); + + // spritenum_t sprite; + SV_WriteLong(str->sprite); + + // int frame; + SV_WriteLong(str->frame); + + // struct mobj_s *bnext, *bprev; + SV_WritePtr(str->bnext); + SV_WritePtr(str->bprev); + + // struct subsector_s *subsector; + SV_WritePtr(str->subsector); + + // fixed_t floorz, ceilingz; + SV_WriteLong(str->floorz); + SV_WriteLong(str->ceilingz); + + // fixed_t floorpic; + SV_WriteLong(str->floorpic); + + // fixed_t radius, height; + SV_WriteLong(str->radius); + SV_WriteLong(str->height); + + // fixed_t momx, momy, momz; + SV_WriteLong(str->momx); + SV_WriteLong(str->momy); + SV_WriteLong(str->momz); + + // int validcount; + SV_WriteLong(str->validcount); + + // mobjtype_t type; + SV_WriteLong(str->type); + + // mobjinfo_t *info; + SV_WritePtr(str->info); + + // int tics; + SV_WriteLong(str->tics); + + // state_t *state; + // Save as index into the states table. + SV_WriteLong(str->state - states); + + // int damage; + SV_WriteLong(str->damage); + + // int flags; + SV_WriteLong(str->flags); + + // int flags2; + SV_WriteLong(str->flags2); + + // specialval_t special1; + // specialval_t special2; + // There are lots of special cases for the special values: + StreamOutMobjSpecials(str); + + // int health; + SV_WriteLong(str->health); + + // int movedir; + SV_WriteLong(str->movedir); + + // int movecount; + SV_WriteLong(str->movecount); + + // struct mobj_s *target; + if ((str->flags & MF_CORPSE) != 0) + { + SV_WriteLong(MOBJ_NULL); + } + else + { + SV_WriteLong(GetMobjNum(str->target)); + } + + // int reactiontime; + SV_WriteLong(str->reactiontime); + + // int threshold; + SV_WriteLong(str->threshold); + + // struct player_s *player; + // Stored as index into players[] array, if there is a player pointer. + if (str->player != NULL) + { + SV_WriteLong(str->player - players + 1); + } + else + { + SV_WriteLong(0); + } + + // int lastlook; + SV_WriteLong(str->lastlook); + + // fixed_t floorclip; + SV_WriteLong(str->floorclip); + + // int archiveNum; + SV_WriteLong(str->archiveNum); + + // short tid; + SV_WriteWord(str->tid); + + // byte special; + SV_WriteByte(str->special); + + // byte args[5]; + for (i=0; i<5; ++i) + { + SV_WriteByte(str->args[i]); + } +} + + +// +// floormove_t +// + +static void StreamIn_floormove_t(thinker_t *thinker) +{ + floormove_t *str = (floormove_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = sectors + i; + + // floor_e type; + str->type = SV_ReadLong(); + + // int crush; + str->crush = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // int newspecial; + str->newspecial = SV_ReadLong(); + + // short texture; + str->texture = SV_ReadWord(); + + // fixed_t floordestheight; + str->floordestheight = SV_ReadLong(); + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // int delayCount; + str->delayCount = SV_ReadLong(); + + // int delayTotal; + str->delayTotal = SV_ReadLong(); + + // fixed_t stairsDelayHeight; + str->stairsDelayHeight = SV_ReadLong(); + + // fixed_t stairsDelayHeightDelta; + str->stairsDelayHeightDelta = SV_ReadLong(); + + // fixed_t resetHeight; + str->resetHeight = SV_ReadLong(); + + // short resetDelay; + str->resetDelay = SV_ReadWord(); + + // short resetDelayCount; + str->resetDelayCount = SV_ReadWord(); + + // byte textureChange; + str->textureChange = SV_ReadByte(); +} + +static void StreamOut_floormove_t(thinker_t *thinker) +{ + floormove_t *str = (floormove_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // floor_e type; + SV_WriteLong(str->type); + + // int crush; + SV_WriteLong(str->crush); + + // int direction; + SV_WriteLong(str->direction); + + // int newspecial; + SV_WriteLong(str->newspecial); + + // short texture; + SV_WriteWord(str->texture); + + // fixed_t floordestheight; + SV_WriteLong(str->floordestheight); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // int delayCount; + SV_WriteLong(str->delayCount); + + // int delayTotal; + SV_WriteLong(str->delayTotal); + + // fixed_t stairsDelayHeight; + SV_WriteLong(str->stairsDelayHeight); + + // fixed_t stairsDelayHeightDelta; + SV_WriteLong(str->stairsDelayHeightDelta); + + // fixed_t resetHeight; + SV_WriteLong(str->resetHeight); + + // short resetDelay; + SV_WriteWord(str->resetDelay); + + // short resetDelayCount; + SV_WriteWord(str->resetDelayCount); + + // byte textureChange; + SV_WriteByte(str->textureChange); +} + + +// +// plat_t +// + +static void StreamIn_plat_t(thinker_t *thinker) +{ + plat_t *str = (plat_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = sectors + i; + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // fixed_t low; + str->low = SV_ReadLong(); + + // fixed_t high; + str->high = SV_ReadLong(); + + // int wait; + str->wait = SV_ReadLong(); + + // int count; + str->count = SV_ReadLong(); + + // plat_e status; + str->status = SV_ReadLong(); + + // plat_e oldstatus; + str->oldstatus = SV_ReadLong(); + + // int crush; + str->crush = SV_ReadLong(); + + // int tag; + str->tag = SV_ReadLong(); + + // plattype_e type; + str->type = SV_ReadLong(); +} + +static void StreamOut_plat_t(thinker_t *thinker) +{ + plat_t *str = (plat_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // fixed_t low; + SV_WriteLong(str->low); + + // fixed_t high; + SV_WriteLong(str->high); + + // int wait; + SV_WriteLong(str->wait); + + // int count; + SV_WriteLong(str->count); + + // plat_e status; + SV_WriteLong(str->status); + + // plat_e oldstatus; + SV_WriteLong(str->oldstatus); + + // int crush; + SV_WriteLong(str->crush); + + // int tag; + SV_WriteLong(str->tag); + + // plattype_e type; + SV_WriteLong(str->type); +} + + +// +// ceiling_t +// + +static void StreamIn_ceiling_t(thinker_t *thinker) +{ + ceiling_t *str = (ceiling_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = sectors + i; + + // ceiling_e type; + str->type = SV_ReadLong(); + + // fixed_t bottomheight, topheight; + str->bottomheight = SV_ReadLong(); + str->topheight = SV_ReadLong(); + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // int crush; + str->crush = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // int tag; + str->tag = SV_ReadLong(); + + // int olddirection; + str->olddirection = SV_ReadLong(); +} + +static void StreamOut_ceiling_t(thinker_t *thinker) +{ + ceiling_t *str = (ceiling_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // ceiling_e type; + SV_WriteLong(str->type); + + // fixed_t bottomheight, topheight; + SV_WriteLong(str->bottomheight); + SV_WriteLong(str->topheight); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // int crush; + SV_WriteLong(str->crush); + + // int direction; + SV_WriteLong(str->direction); + + // int tag; + SV_WriteLong(str->tag); + + // int olddirection; + SV_WriteLong(str->olddirection); +} + + +// +// light_t +// + +static void StreamIn_light_t(thinker_t *thinker) +{ + light_t *str = (light_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = sectors + i; + + // lighttype_t type; + str->type = SV_ReadLong(); + + // int value1; + str->value1 = SV_ReadLong(); + + // int value2; + str->value2 = SV_ReadLong(); + + // int tics1; + str->tics1 = SV_ReadLong(); + + // int tics2; + str->tics2 = SV_ReadLong(); + + // int count; + str->count = SV_ReadLong(); +} + +static void StreamOut_light_t(thinker_t *thinker) +{ + light_t *str = (light_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // lighttype_t type; + SV_WriteLong(str->type); + + // int value1; + SV_WriteLong(str->value1); + + // int value2; + SV_WriteLong(str->value2); + + // int tics1; + SV_WriteLong(str->tics1); + + // int tics2; + SV_WriteLong(str->tics2); + + // int count; + SV_WriteLong(str->count); +} + + +// +// vldoor_t +// + +static void StreamIn_vldoor_t(thinker_t *thinker) +{ + vldoor_t *str = (vldoor_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // vldoor_e type; + str->type = SV_ReadLong(); + + // fixed_t topheight; + str->topheight = SV_ReadLong(); + + // fixed_t speed; + str->speed = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // int topwait; + str->topwait = SV_ReadLong(); + + // int topcountdown; + str->topcountdown = SV_ReadLong(); +} + +static void StreamOut_vldoor_t(thinker_t *thinker) +{ + vldoor_t *str = (vldoor_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // vldoor_e type; + SV_WriteLong(str->type); + + // fixed_t topheight; + SV_WriteLong(str->topheight); + + // fixed_t speed; + SV_WriteLong(str->speed); + + // int direction; + SV_WriteLong(str->direction); + + // int topwait; + SV_WriteLong(str->topwait); + + // int topcountdown; + SV_WriteLong(str->topcountdown); +} + + +// +// phase_t +// + +static void StreamIn_phase_t(thinker_t *thinker) +{ + phase_t *str = (phase_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // int index; + str->index = SV_ReadLong(); + + // int base; + str->base = SV_ReadLong(); +} + +static void StreamOut_phase_t(thinker_t *thinker) +{ + phase_t *str = (phase_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // int index; + SV_WriteLong(str->index); + + // int base; + SV_WriteLong(str->base); +} + + +// +// acs_t +// + +static void StreamIn_acs_t(thinker_t *thinker) +{ + acs_t *str = (acs_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // mobj_t *activator; + i = SV_ReadLong(); + SetMobjPtr(&str->activator, i); + + // line_t *line; + i = SV_ReadLong(); + if (i != -1) + { + str->line = &lines[i]; + } + else + { + str->line = NULL; + } + + // int side; + str->side = SV_ReadLong(); + + // int number; + str->number = SV_ReadLong(); + + // int infoIndex; + str->infoIndex = SV_ReadLong(); + + // int delayCount; + str->delayCount = SV_ReadLong(); + + // int stack[ACS_STACK_DEPTH]; + for (i=0; istack[i] = SV_ReadLong(); + } + + // int stackPtr; + str->stackPtr = SV_ReadLong(); + + // int vars[MAX_ACS_SCRIPT_VARS]; + for (i=0; ivars[i] = SV_ReadLong(); + } + + // int *ip; + str->ip = SV_ReadLong(); +} + +static void StreamOut_acs_t(thinker_t *thinker) +{ + acs_t *str = (acs_t *) thinker; + + int i; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // mobj_t *activator; + SV_WriteLong(GetMobjNum(str->activator)); + + // line_t *line; + if (str->line != NULL) + { + SV_WriteLong(str->line - lines); + } + else + { + SV_WriteLong(-1); + } + + // int side; + SV_WriteLong(str->side); + + // int number; + SV_WriteLong(str->number); + + // int infoIndex; + SV_WriteLong(str->infoIndex); + + // int delayCount; + SV_WriteLong(str->delayCount); + + // int stack[ACS_STACK_DEPTH]; + for (i=0; istack[i]); + } + + // int stackPtr; + SV_WriteLong(str->stackPtr); + + // int vars[MAX_ACS_SCRIPT_VARS]; + for (i=0; ivars[i]); + } + + // int *ip; + SV_WriteLong(str->ip); +} + + +// +// polyevent_t +// + +static void StreamIn_polyevent_t(thinker_t *thinker) +{ + polyevent_t *str = (polyevent_t *) thinker; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // int polyobj; + str->polyobj = SV_ReadLong(); + + // int speed; + str->speed = SV_ReadLong(); + + // unsigned int dist; + str->dist = SV_ReadLong(); + + // int angle; + str->angle = SV_ReadLong(); + + // fixed_t xSpeed; + str->xSpeed = SV_ReadLong(); + + // fixed_t ySpeed; + str->ySpeed = SV_ReadLong(); +} + +static void StreamOut_polyevent_t(thinker_t *thinker) +{ + polyevent_t *str = (polyevent_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // int polyobj; + SV_WriteLong(str->polyobj); + + // int speed; + SV_WriteLong(str->speed); + + // unsigned int dist; + SV_WriteLong(str->dist); + + // int angle; + SV_WriteLong(str->angle); + + // fixed_t xSpeed; + SV_WriteLong(str->xSpeed); + + // fixed_t ySpeed; + SV_WriteLong(str->ySpeed); +} + + +// +// pillar_t +// + +static void StreamIn_pillar_t(thinker_t *thinker) +{ + pillar_t *str = (pillar_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // int ceilingSpeed; + str->ceilingSpeed = SV_ReadLong(); + + // int floorSpeed; + str->floorSpeed = SV_ReadLong(); + + // int floordest; + str->floordest = SV_ReadLong(); + + // int ceilingdest; + str->ceilingdest = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // int crush; + str->crush = SV_ReadLong(); +} + +static void StreamOut_pillar_t(thinker_t *thinker) +{ + pillar_t *str = (pillar_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // int ceilingSpeed; + SV_WriteLong(str->ceilingSpeed); + + // int floorSpeed; + SV_WriteLong(str->floorSpeed); + + // int floordest; + SV_WriteLong(str->floordest); + + // int ceilingdest; + SV_WriteLong(str->ceilingdest); + + // int direction; + SV_WriteLong(str->direction); + + // int crush; + SV_WriteLong(str->crush); +} + + +// +// polydoor_t +// + +static void StreamIn_polydoor_t(thinker_t *thinker) +{ + polydoor_t *str = (polydoor_t *) thinker; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // int polyobj; + str->polyobj = SV_ReadLong(); + + // int speed; + str->speed = SV_ReadLong(); + + // int dist; + str->dist = SV_ReadLong(); + + // int totalDist; + str->totalDist = SV_ReadLong(); + + // int direction; + str->direction = SV_ReadLong(); + + // fixed_t xSpeed, ySpeed; + str->xSpeed = SV_ReadLong(); + str->ySpeed = SV_ReadLong(); + + // int tics; + str->tics = SV_ReadLong(); + + // int waitTics; + str->waitTics = SV_ReadLong(); + + // podoortype_t type; + str->type = SV_ReadLong(); + + // boolean close; + str->close = SV_ReadLong(); +} + +static void StreamOut_polydoor_t(thinker_t *thinker) +{ + polydoor_t *str = (polydoor_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // int polyobj; + SV_WriteLong(str->polyobj); + + // int speed; + SV_WriteLong(str->speed); + + // int dist; + SV_WriteLong(str->dist); + + // int totalDist; + SV_WriteLong(str->totalDist); + + // int direction; + SV_WriteLong(str->direction); + + // fixed_t xSpeed, ySpeed; + SV_WriteLong(str->xSpeed); + SV_WriteLong(str->ySpeed); + + // int tics; + SV_WriteLong(str->tics); + + // int waitTics; + SV_WriteLong(str->waitTics); + + // podoortype_t type; + SV_WriteLong(str->type); + + // boolean close; + SV_WriteLong(str->close); +} + + +// +// floorWaggle_t +// + +static void StreamIn_floorWaggle_t(thinker_t *thinker) +{ + floorWaggle_t *str = (floorWaggle_t *) thinker; + + int i; + + // thinker_t thinker; + StreamIn_thinker_t(&str->thinker); + + // sector_t *sector; + i = SV_ReadLong(); + str->sector = §ors[i]; + + // fixed_t originalHeight; + str->originalHeight = SV_ReadLong(); + + // fixed_t accumulator; + str->accumulator = SV_ReadLong(); + + // fixed_t accDelta; + str->accDelta = SV_ReadLong(); + + // fixed_t targetScale; + str->targetScale = SV_ReadLong(); + + // fixed_t scale; + str->scale = SV_ReadLong(); + + // fixed_t scaleDelta; + str->scaleDelta = SV_ReadLong(); + + // int ticker; + str->ticker = SV_ReadLong(); + + // int state; + str->state = SV_ReadLong(); +} + +static void StreamOut_floorWaggle_t(thinker_t *thinker) +{ + floorWaggle_t *str = (floorWaggle_t *) thinker; + + // thinker_t thinker; + StreamOut_thinker_t(&str->thinker); + + // sector_t *sector; + SV_WriteLong(str->sector - sectors); + + // fixed_t originalHeight; + SV_WriteLong(str->originalHeight); + + // fixed_t accumulator; + SV_WriteLong(str->accumulator); + + // fixed_t accDelta; + SV_WriteLong(str->accDelta); + + // fixed_t targetScale; + SV_WriteLong(str->targetScale); + + // fixed_t scale; + SV_WriteLong(str->scale); + + // fixed_t scaleDelta; + SV_WriteLong(str->scaleDelta); + + // int ticker; + SV_WriteLong(str->ticker); + + // int state; + SV_WriteLong(str->state); +} + + +//========================================================================== +// +// SV_SaveGame +// +//========================================================================== + +void SV_SaveGame(int slot, const char *description) +{ + char fileName[100]; + char versionText[HXS_VERSION_TEXT_LENGTH]; + unsigned int i; + + // Open the output file + M_snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath); + SV_OpenWrite(fileName); + + // Write game save description + SV_Write(description, HXS_DESCRIPTION_LENGTH); + + // Write version info + memset(versionText, 0, HXS_VERSION_TEXT_LENGTH); + M_StringCopy(versionText, HXS_VERSION_TEXT, HXS_VERSION_TEXT_LENGTH); + SV_Write(versionText, HXS_VERSION_TEXT_LENGTH); + + // Place a header marker + SV_WriteLong(ASEG_GAME_HEADER); + + // Write current map and difficulty + SV_WriteByte(gamemap); + SV_WriteByte(gameskill); + + // Write global script info + for (i = 0; i < MAX_ACS_WORLD_VARS; ++i) + { + SV_WriteLong(WorldVars[i]); + } + + for (i = 0; i < MAX_ACS_STORE + 1; ++i) + { + StreamOut_acsstore_t(&ACSStore[i]); + } + + ArchivePlayers(); + + // Place a termination marker + SV_WriteLong(ASEG_END); + + // Close the output file + SV_Close(); + + // Save out the current map + SV_SaveMap(true); // true = save player info + + // Clear all save files at destination slot + ClearSaveSlot(slot); + + // Copy base slot to destination slot + CopySaveSlot(BASE_SLOT, slot); +} + +//========================================================================== +// +// SV_SaveMap +// +//========================================================================== + +void SV_SaveMap(boolean savePlayers) +{ + char fileName[100]; + + SavingPlayers = savePlayers; + + // Open the output file + M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap); + SV_OpenWrite(fileName); + + // Place a header marker + SV_WriteLong(ASEG_MAP_HEADER); + + // Write the level timer + SV_WriteLong(leveltime); + + // Set the mobj archive numbers + SetMobjArchiveNums(); + + ArchiveWorld(); + ArchivePolyobjs(); + ArchiveMobjs(); + ArchiveThinkers(); + ArchiveScripts(); + ArchiveSounds(); + ArchiveMisc(); + + // Place a termination marker + SV_WriteLong(ASEG_END); + + // Close the output file + SV_Close(); +} + +//========================================================================== +// +// SV_LoadGame +// +//========================================================================== + +void SV_LoadGame(int slot) +{ + int i; + char fileName[100]; + char version_text[HXS_VERSION_TEXT_LENGTH]; + player_t playerBackup[MAXPLAYERS]; + mobj_t *mobj; + + // Copy all needed save files to the base slot + if (slot != BASE_SLOT) + { + ClearSaveSlot(BASE_SLOT); + CopySaveSlot(slot, BASE_SLOT); + } + + // Create the name + M_snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath); + + // Load the file + SV_OpenRead(fileName); + + // Set the save pointer and skip the description field + fseek(SavingFP, HXS_DESCRIPTION_LENGTH, SEEK_CUR); + + // Check the version text + + for (i = 0; i < sizeof(version_text); ++i) + { + version_text[i] = SV_ReadByte(); + } + if (strncmp(version_text, HXS_VERSION_TEXT, HXS_VERSION_TEXT_LENGTH) != 0) + { // Bad version + return; + } + + AssertSegment(ASEG_GAME_HEADER); + + gameepisode = 1; + gamemap = SV_ReadByte(); + gameskill = SV_ReadByte(); + + // Read global script info + + for (i = 0; i < MAX_ACS_WORLD_VARS; ++i) + { + WorldVars[i] = SV_ReadLong(); + } + + for (i = 0; i < MAX_ACS_STORE + 1; ++i) + { + StreamIn_acsstore_t(&ACSStore[i]); + } + + // Read the player structures + UnarchivePlayers(); + + AssertSegment(ASEG_END); + + // Save player structs + for (i = 0; i < maxplayers; i++) + { + playerBackup[i] = players[i]; + } + + SV_Close(); + + // Load the current map + SV_LoadMap(); + + // Don't need the player mobj relocation info for load game + Z_Free(TargetPlayerAddrs); + + // Restore player structs + inv_ptr = 0; + curpos = 0; + for (i = 0; i < maxplayers; i++) + { + mobj = players[i].mo; + players[i] = playerBackup[i]; + players[i].mo = mobj; + if (i == consoleplayer) + { + players[i].readyArtifact = players[i].inventory[inv_ptr].type; + } + } + + // Set Bestslideline after loading + P_InitSlideLine(); +} + +//========================================================================== +// +// SV_UpdateRebornSlot +// +// Copies the base slot to the reborn slot. +// +//========================================================================== + +void SV_UpdateRebornSlot(void) +{ + ClearSaveSlot(REBORN_SLOT); + CopySaveSlot(BASE_SLOT, REBORN_SLOT); +} + +//========================================================================== +// +// SV_ClearRebornSlot +// +//========================================================================== + +void SV_ClearRebornSlot(void) +{ + ClearSaveSlot(REBORN_SLOT); +} + +//========================================================================== +// +// SV_MapTeleport +// +//========================================================================== + +void SV_MapTeleport(int map, int position) +{ + int i; + int j; + char fileName[100]; + player_t playerBackup[MAXPLAYERS]; + mobj_t *targetPlayerMobj; + mobj_t *mobj; + int inventoryPtr; + int currentInvPos; + boolean rClass; + boolean playerWasReborn; + boolean oldWeaponowned[NUMWEAPONS]; + int oldKeys = 0; + int oldPieces = 0; + int bestWeapon; + + if (!deathmatch) + { + if (P_GetMapCluster(gamemap) == P_GetMapCluster(map)) + { // Same cluster - save map without saving player mobjs + SV_SaveMap(false); + } + else + { // Entering new cluster - clear base slot + ClearSaveSlot(BASE_SLOT); + } + } + + // Store player structs for later + rClass = randomclass; + randomclass = false; + for (i = 0; i < maxplayers; i++) + { + playerBackup[i] = players[i]; + } + + // Save some globals that get trashed during the load + inventoryPtr = inv_ptr; + currentInvPos = curpos; + + // Only SV_LoadMap() uses TargetPlayerAddrs, so it's NULLed here + // for the following check (player mobj redirection) + TargetPlayerAddrs = NULL; + + gamemap = map; + M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap); + if (!deathmatch && ExistingFile(fileName)) + { // Unarchive map + SV_LoadMap(); + } + else + { // New map + G_InitNew(gameskill, gameepisode, gamemap); + + // Destroy all freshly spawned players + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + P_RemoveMobj(players[i].mo); + } + } + } + + // Restore player structs + targetPlayerMobj = NULL; + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + { + continue; + } + players[i] = playerBackup[i]; + P_ClearMessage(&players[i]); + players[i].attacker = NULL; + players[i].poisoner = NULL; + + if (netgame) + { + if (players[i].playerstate == PST_DEAD) + { // In a network game, force all players to be alive + players[i].playerstate = PST_REBORN; + } + if (!deathmatch) + { // Cooperative net-play, retain keys and weapons + oldKeys = players[i].keys; + oldPieces = players[i].pieces; + for (j = 0; j < NUMWEAPONS; j++) + { + oldWeaponowned[j] = players[i].weaponowned[j]; + } + } + } + playerWasReborn = (players[i].playerstate == PST_REBORN); + if (deathmatch) + { + memset(players[i].frags, 0, sizeof(players[i].frags)); + mobj = P_SpawnMobj(playerstarts[0][i].x << 16, + playerstarts[0][i].y << 16, 0, + MT_PLAYER_FIGHTER); + players[i].mo = mobj; + G_DeathMatchSpawnPlayer(i); + P_RemoveMobj(mobj); + } + else + { + P_SpawnPlayer(&playerstarts[position][i]); + } + + if (playerWasReborn && netgame && !deathmatch) + { // Restore keys and weapons when reborn in co-op + players[i].keys = oldKeys; + players[i].pieces = oldPieces; + for (bestWeapon = 0, j = 0; j < NUMWEAPONS; j++) + { + if (oldWeaponowned[j]) + { + bestWeapon = j; + players[i].weaponowned[j] = true; + } + } + players[i].mana[MANA_1] = 25; + players[i].mana[MANA_2] = 25; + if (bestWeapon) + { // Bring up the best weapon + players[i].pendingweapon = bestWeapon; + } + } + + if (targetPlayerMobj == NULL) + { // The poor sap + targetPlayerMobj = players[i].mo; + } + } + randomclass = rClass; + + // Redirect anything targeting a player mobj + if (TargetPlayerAddrs) + { + for (i = 0; i < TargetPlayerCount; i++) + { + *TargetPlayerAddrs[i] = targetPlayerMobj; + } + Z_Free(TargetPlayerAddrs); + } + + // Destroy all things touching players + for (i = 0; i < maxplayers; i++) + { + if (playeringame[i]) + { + P_TeleportMove(players[i].mo, players[i].mo->x, players[i].mo->y); + } + } + + // Restore trashed globals + inv_ptr = inventoryPtr; + curpos = currentInvPos; + + // Launch waiting scripts + if (!deathmatch) + { + P_CheckACSStore(); + } + + // For single play, save immediately into the reborn slot + if (!netgame) + { + SV_SaveGame(REBORN_SLOT, REBORN_DESCRIPTION); + } +} + +//========================================================================== +// +// SV_GetRebornSlot +// +//========================================================================== + +int SV_GetRebornSlot(void) +{ + return (REBORN_SLOT); +} + +//========================================================================== +// +// SV_RebornSlotAvailable +// +// Returns true if the reborn slot is available. +// +//========================================================================== + +boolean SV_RebornSlotAvailable(void) +{ + char fileName[100]; + + M_snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, REBORN_SLOT); + return ExistingFile(fileName); +} + +//========================================================================== +// +// SV_LoadMap +// +//========================================================================== + +void SV_LoadMap(void) +{ + char fileName[100]; + + // Load a base level + G_InitNew(gameskill, gameepisode, gamemap); + + // Remove all thinkers + RemoveAllThinkers(); + + // Create the name + M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap); + + // Load the file + SV_OpenRead(fileName); + + AssertSegment(ASEG_MAP_HEADER); + + // Read the level timer + leveltime = SV_ReadLong(); + + UnarchiveWorld(); + UnarchivePolyobjs(); + UnarchiveMobjs(); + UnarchiveThinkers(); + UnarchiveScripts(); + UnarchiveSounds(); + UnarchiveMisc(); + + AssertSegment(ASEG_END); + + // Free mobj list and save buffer + Z_Free(MobjList); + SV_Close(); +} + +//========================================================================== +// +// SV_InitBaseSlot +// +//========================================================================== + +void SV_InitBaseSlot(void) +{ + ClearSaveSlot(BASE_SLOT); +} + +//========================================================================== +// +// ArchivePlayers +// +//========================================================================== + +static void ArchivePlayers(void) +{ + int i; + + SV_WriteLong(ASEG_PLAYERS); + for (i = 0; i < maxplayers; i++) + { + SV_WriteByte(playeringame[i]); + } + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + { + continue; + } + SV_WriteByte(PlayerClass[i]); + StreamOut_player_t(&players[i]); + } +} + +//========================================================================== +// +// UnarchivePlayers +// +//========================================================================== + +static void UnarchivePlayers(void) +{ + int i; + + AssertSegment(ASEG_PLAYERS); + for (i = 0; i < maxplayers; i++) + { + playeringame[i] = SV_ReadByte(); + } + for (i = 0; i < maxplayers; i++) + { + if (!playeringame[i]) + { + continue; + } + PlayerClass[i] = SV_ReadByte(); + StreamIn_player_t(&players[i]); + P_ClearMessage(&players[i]); + } +} + +//========================================================================== +// +// ArchiveWorld +// +//========================================================================== + +static void ArchiveWorld(void) +{ + int i; + int j; + sector_t *sec; + line_t *li; + side_t *si; + + SV_WriteLong(ASEG_WORLD); + for (i = 0, sec = sectors; i < numsectors; i++, sec++) + { + SV_WriteWord(sec->floorheight >> FRACBITS); + SV_WriteWord(sec->ceilingheight >> FRACBITS); + SV_WriteWord(sec->floorpic); + SV_WriteWord(sec->ceilingpic); + SV_WriteWord(sec->lightlevel); + SV_WriteWord(sec->special); + SV_WriteWord(sec->tag); + SV_WriteWord(sec->seqType); + } + for (i = 0, li = lines; i < numlines; i++, li++) + { + SV_WriteWord(li->flags); + SV_WriteByte(li->special); + SV_WriteByte(li->arg1); + SV_WriteByte(li->arg2); + SV_WriteByte(li->arg3); + SV_WriteByte(li->arg4); + SV_WriteByte(li->arg5); + for (j = 0; j < 2; j++) + { + if (li->sidenum[j] == -1) + { + continue; + } + si = &sides[li->sidenum[j]]; + SV_WriteWord(si->textureoffset >> FRACBITS); + SV_WriteWord(si->rowoffset >> FRACBITS); + SV_WriteWord(si->toptexture); + SV_WriteWord(si->bottomtexture); + SV_WriteWord(si->midtexture); + } + } +} + +//========================================================================== +// +// UnarchiveWorld +// +//========================================================================== + +static void UnarchiveWorld(void) +{ + int i; + int j; + sector_t *sec; + line_t *li; + side_t *si; + + AssertSegment(ASEG_WORLD); + for (i = 0, sec = sectors; i < numsectors; i++, sec++) + { + sec->floorheight = SV_ReadWord() << FRACBITS; + sec->ceilingheight = SV_ReadWord() << FRACBITS; + sec->floorpic = SV_ReadWord(); + sec->ceilingpic = SV_ReadWord(); + sec->lightlevel = SV_ReadWord(); + sec->special = SV_ReadWord(); + sec->tag = SV_ReadWord(); + sec->seqType = SV_ReadWord(); + sec->specialdata = 0; + sec->soundtarget = 0; + } + for (i = 0, li = lines; i < numlines; i++, li++) + { + li->flags = SV_ReadWord(); + li->special = SV_ReadByte(); + li->arg1 = SV_ReadByte(); + li->arg2 = SV_ReadByte(); + li->arg3 = SV_ReadByte(); + li->arg4 = SV_ReadByte(); + li->arg5 = SV_ReadByte(); + for (j = 0; j < 2; j++) + { + if (li->sidenum[j] == -1) + { + continue; + } + si = &sides[li->sidenum[j]]; + si->textureoffset = SV_ReadWord() << FRACBITS; + si->rowoffset = SV_ReadWord() << FRACBITS; + si->toptexture = SV_ReadWord(); + si->bottomtexture = SV_ReadWord(); + si->midtexture = SV_ReadWord(); + } + } +} + +//========================================================================== +// +// SetMobjArchiveNums +// +// Sets the archive numbers in all mobj structs. Also sets the MobjCount +// global. Ignores player mobjs if SavingPlayers is false. +// +//========================================================================== + +static void SetMobjArchiveNums(void) +{ + mobj_t *mobj; + thinker_t *thinker; + + MobjCount = 0; + for (thinker = thinkercap.next; thinker != &thinkercap; + thinker = thinker->next) + { + if (thinker->function == P_MobjThinker) + { + mobj = (mobj_t *) thinker; + if (mobj->player && !SavingPlayers) + { // Skipping player mobjs + continue; + } + mobj->archiveNum = MobjCount++; + } + } +} + +//========================================================================== +// +// ArchiveMobjs +// +//========================================================================== + +static void ArchiveMobjs(void) +{ + int count; + thinker_t *thinker; + + SV_WriteLong(ASEG_MOBJS); + SV_WriteLong(MobjCount); + count = 0; + for (thinker = thinkercap.next; thinker != &thinkercap; + thinker = thinker->next) + { + if (thinker->function != P_MobjThinker) + { // Not a mobj thinker + continue; + } + if (((mobj_t *) thinker)->player && !SavingPlayers) + { // Skipping player mobjs + continue; + } + count++; + StreamOut_mobj_t((mobj_t *) thinker); + } + if (count != MobjCount) + { + I_Error("ArchiveMobjs: bad mobj count"); + } +} + +//========================================================================== +// +// UnarchiveMobjs +// +//========================================================================== + +static void UnarchiveMobjs(void) +{ + int i; + mobj_t *mobj; + + AssertSegment(ASEG_MOBJS); + TargetPlayerAddrs = Z_Malloc(MAX_TARGET_PLAYERS * sizeof(mobj_t **), + PU_STATIC, NULL); + TargetPlayerCount = 0; + MobjCount = SV_ReadLong(); + MobjList = Z_Malloc(MobjCount * sizeof(mobj_t *), PU_STATIC, NULL); + for (i = 0; i < MobjCount; i++) + { + MobjList[i] = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL); + } + for (i = 0; i < MobjCount; i++) + { + mobj = MobjList[i]; + StreamIn_mobj_t(mobj); + + // Restore broken pointers. + mobj->info = &mobjinfo[mobj->type]; + P_SetThingPosition(mobj); + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + + mobj->thinker.function = P_MobjThinker; + P_AddThinker(&mobj->thinker); + } + P_CreateTIDList(); + P_InitCreatureCorpseQueue(true); // true = scan for corpses +} + +//========================================================================== +// +// GetMobjNum +// +//========================================================================== + +static int GetMobjNum(mobj_t * mobj) +{ + if (mobj == NULL) + { + return MOBJ_NULL; + } + if (mobj->player && !SavingPlayers) + { + return MOBJ_XX_PLAYER; + } + return mobj->archiveNum; +} + +//========================================================================== +// +// SetMobjPtr +// +//========================================================================== + +static void SetMobjPtr(mobj_t **ptr, unsigned int archiveNum) +{ + if (archiveNum == MOBJ_NULL) + { + *ptr = NULL; + } + else if (archiveNum == MOBJ_XX_PLAYER) + { + if (TargetPlayerCount == MAX_TARGET_PLAYERS) + { + I_Error("RestoreMobj: exceeded MAX_TARGET_PLAYERS"); + } + TargetPlayerAddrs[TargetPlayerCount++] = ptr; + *ptr = NULL; + } + else + { + *ptr = MobjList[archiveNum]; + } +} + +//========================================================================== +// +// Thinker types list. +// +// This is used by ArchiveThinkers and UnarchiveThinkers, below. +// +// Original comment: +// "This list has been prioritized using frequency estimates" +// +//========================================================================== + +static thinkInfo_t ThinkerInfo[] = { + { + TC_MOVE_FLOOR, + T_MoveFloor, + StreamOut_floormove_t, + StreamIn_floormove_t, + RestoreSSThinker, + sizeof(floormove_t) + }, + { + TC_PLAT_RAISE, + T_PlatRaise, + StreamOut_plat_t, + StreamIn_plat_t, + RestorePlatRaise, + sizeof(plat_t) + }, + { + TC_MOVE_CEILING, + T_MoveCeiling, + StreamOut_ceiling_t, + StreamIn_ceiling_t, + RestoreMoveCeiling, + sizeof(ceiling_t) + }, + { + TC_LIGHT, + T_Light, + StreamOut_light_t, + StreamIn_light_t, + NULL, + sizeof(light_t) + }, + { + TC_VERTICAL_DOOR, + T_VerticalDoor, + StreamOut_vldoor_t, + StreamIn_vldoor_t, + RestoreSSThinker, + sizeof(vldoor_t) + }, + { + TC_PHASE, + T_Phase, + StreamOut_phase_t, + StreamIn_phase_t, + NULL, + sizeof(phase_t) + }, + { + TC_INTERPRET_ACS, + T_InterpretACS, + StreamOut_acs_t, + StreamIn_acs_t, + NULL, + sizeof(acs_t) + }, + { + TC_ROTATE_POLY, + T_RotatePoly, + StreamOut_polyevent_t, + StreamIn_polyevent_t, + NULL, + sizeof(polyevent_t) + }, + { + TC_BUILD_PILLAR, + T_BuildPillar, + StreamOut_pillar_t, + StreamIn_pillar_t, + RestoreSSThinker, + sizeof(pillar_t) + }, + { + TC_MOVE_POLY, + T_MovePoly, + StreamOut_polyevent_t, + StreamIn_polyevent_t, + NULL, + sizeof(polyevent_t) + }, + { + TC_POLY_DOOR, + T_PolyDoor, + StreamOut_polydoor_t, + StreamIn_polydoor_t, + NULL, + sizeof(polydoor_t) + }, + { + TC_FLOOR_WAGGLE, + T_FloorWaggle, + StreamOut_floorWaggle_t, + StreamIn_floorWaggle_t, + RestoreSSThinker, + sizeof(floorWaggle_t) + }, + { TC_NULL, NULL, NULL, NULL, NULL, 0}, +}; + +//========================================================================== +// +// ArchiveThinkers +// +//========================================================================== + +static void ArchiveThinkers(void) +{ + thinker_t *thinker; + thinkInfo_t *info; + + SV_WriteLong(ASEG_THINKERS); + for (thinker = thinkercap.next; thinker != &thinkercap; + thinker = thinker->next) + { + for (info = ThinkerInfo; info->tClass != TC_NULL; info++) + { + if (thinker->function == info->thinkerFunc) + { + SV_WriteByte(info->tClass); + info->writeFunc(thinker); + break; + } + } + } + // Add a termination marker + SV_WriteByte(TC_NULL); +} + +//========================================================================== +// +// UnarchiveThinkers +// +//========================================================================== + +static void UnarchiveThinkers(void) +{ + int tClass; + thinker_t *thinker; + thinkInfo_t *info; + + AssertSegment(ASEG_THINKERS); + while ((tClass = SV_ReadByte()) != TC_NULL) + { + for (info = ThinkerInfo; info->tClass != TC_NULL; info++) + { + if (tClass == info->tClass) + { + thinker = Z_Malloc(info->size, PU_LEVEL, NULL); + info->readFunc(thinker); + thinker->function = info->thinkerFunc; + if (info->restoreFunc) + { + info->restoreFunc(thinker); + } + P_AddThinker(thinker); + break; + } + } + if (info->tClass == TC_NULL) + { + I_Error("UnarchiveThinkers: Unknown tClass %d in " + "savegame", tClass); + } + } +} + +//========================================================================== +// +// RestoreSSThinker +// +//========================================================================== + +static void RestoreSSThinker(thinker_t *thinker) +{ + ssthinker_t *sst = (ssthinker_t *) thinker; + sst->sector->specialdata = sst->thinker.function; +} + +//========================================================================== +// +// RestorePlatRaise +// +//========================================================================== + +static void RestorePlatRaise(thinker_t *thinker) +{ + plat_t *plat = (plat_t *) thinker; + plat->sector->specialdata = T_PlatRaise; + P_AddActivePlat(plat); +} + +//========================================================================== +// +// RestoreMoveCeiling +// +//========================================================================== + +static void RestoreMoveCeiling(thinker_t *thinker) +{ + ceiling_t *ceiling = (ceiling_t *) thinker; + ceiling->sector->specialdata = T_MoveCeiling; + P_AddActiveCeiling(ceiling); +} + +//========================================================================== +// +// ArchiveScripts +// +//========================================================================== + +static void ArchiveScripts(void) +{ + int i; + + SV_WriteLong(ASEG_SCRIPTS); + for (i = 0; i < ACScriptCount; i++) + { + SV_WriteWord(ACSInfo[i].state); + SV_WriteWord(ACSInfo[i].waitValue); + } + + for (i = 0; i< MAX_ACS_MAP_VARS; ++i) + { + SV_WriteLong(MapVars[i]); + } +} + +//========================================================================== +// +// UnarchiveScripts +// +//========================================================================== + +static void UnarchiveScripts(void) +{ + int i; + + AssertSegment(ASEG_SCRIPTS); + for (i = 0; i < ACScriptCount; i++) + { + ACSInfo[i].state = SV_ReadWord(); + ACSInfo[i].waitValue = SV_ReadWord(); + } + + for (i = 0; i < MAX_ACS_MAP_VARS; ++i) + { + MapVars[i] = SV_ReadLong(); + } +} + +//========================================================================== +// +// ArchiveMisc +// +//========================================================================== + +static void ArchiveMisc(void) +{ + int ix; + + SV_WriteLong(ASEG_MISC); + for (ix = 0; ix < maxplayers; ix++) + { + SV_WriteLong(localQuakeHappening[ix]); + } +} + +//========================================================================== +// +// UnarchiveMisc +// +//========================================================================== + +static void UnarchiveMisc(void) +{ + int ix; + + AssertSegment(ASEG_MISC); + for (ix = 0; ix < maxplayers; ix++) + { + localQuakeHappening[ix] = SV_ReadLong(); + } +} + +//========================================================================== +// +// RemoveAllThinkers +// +//========================================================================== + +static void RemoveAllThinkers(void) +{ + thinker_t *thinker; + thinker_t *nextThinker; + + thinker = thinkercap.next; + while (thinker != &thinkercap) + { + nextThinker = thinker->next; + if (thinker->function == P_MobjThinker) + { + P_RemoveMobj((mobj_t *) thinker); + } + else + { + Z_Free(thinker); + } + thinker = nextThinker; + } + P_InitThinkers(); +} + +//========================================================================== +// +// ArchiveSounds +// +//========================================================================== + +static void ArchiveSounds(void) +{ + seqnode_t *node; + sector_t *sec; + int difference; + int i; + + SV_WriteLong(ASEG_SOUNDS); + + // Save the sound sequences + SV_WriteLong(ActiveSequences); + for (node = SequenceListHead; node; node = node->next) + { + SV_WriteLong(node->sequence); + SV_WriteLong(node->delayTics); + SV_WriteLong(node->volume); + SV_WriteLong(SN_GetSequenceOffset(node->sequence, + node->sequencePtr)); + SV_WriteLong(node->currentSoundID); + for (i = 0; i < po_NumPolyobjs; i++) + { + if (node->mobj == (mobj_t *) & polyobjs[i].startSpot) + { + break; + } + } + if (i == po_NumPolyobjs) + { // Sound is attached to a sector, not a polyobj + sec = R_PointInSubsector(node->mobj->x, node->mobj->y)->sector; + difference = (int) ((byte *) sec + - (byte *) & sectors[0]) / sizeof(sector_t); + SV_WriteLong(0); // 0 -- sector sound origin + } + else + { + SV_WriteLong(1); // 1 -- polyobj sound origin + difference = i; + } + SV_WriteLong(difference); + } +} + +//========================================================================== +// +// UnarchiveSounds +// +//========================================================================== + +static void UnarchiveSounds(void) +{ + int i; + int numSequences; + int sequence; + int delayTics; + int volume; + int seqOffset; + int soundID; + int polySnd; + int secNum; + mobj_t *sndMobj; + + AssertSegment(ASEG_SOUNDS); + + // Reload and restart all sound sequences + numSequences = SV_ReadLong(); + i = 0; + while (i < numSequences) + { + sequence = SV_ReadLong(); + delayTics = SV_ReadLong(); + volume = SV_ReadLong(); + seqOffset = SV_ReadLong(); + + soundID = SV_ReadLong(); + polySnd = SV_ReadLong(); + secNum = SV_ReadLong(); + if (!polySnd) + { + sndMobj = (mobj_t *) & sectors[secNum].soundorg; + } + else + { + sndMobj = (mobj_t *) & polyobjs[secNum].startSpot; + } + SN_StartSequence(sndMobj, sequence); + SN_ChangeNodeData(i, seqOffset, delayTics, volume, soundID); + i++; + } +} + +//========================================================================== +// +// ArchivePolyobjs +// +//========================================================================== + +static void ArchivePolyobjs(void) +{ + int i; + + SV_WriteLong(ASEG_POLYOBJS); + SV_WriteLong(po_NumPolyobjs); + for (i = 0; i < po_NumPolyobjs; i++) + { + SV_WriteLong(polyobjs[i].tag); + SV_WriteLong(polyobjs[i].angle); + SV_WriteLong(polyobjs[i].startSpot.x); + SV_WriteLong(polyobjs[i].startSpot.y); + } +} + +//========================================================================== +// +// UnarchivePolyobjs +// +//========================================================================== + +static void UnarchivePolyobjs(void) +{ + int i; + fixed_t deltaX; + fixed_t deltaY; + + AssertSegment(ASEG_POLYOBJS); + if (SV_ReadLong() != po_NumPolyobjs) + { + I_Error("UnarchivePolyobjs: Bad polyobj count"); + } + for (i = 0; i < po_NumPolyobjs; i++) + { + if (SV_ReadLong() != polyobjs[i].tag) + { + I_Error("UnarchivePolyobjs: Invalid polyobj tag"); + } + PO_RotatePolyobj(polyobjs[i].tag, (angle_t) SV_ReadLong()); + deltaX = SV_ReadLong() - polyobjs[i].startSpot.x; + deltaY = SV_ReadLong() - polyobjs[i].startSpot.y; + PO_MovePolyobj(polyobjs[i].tag, deltaX, deltaY); + } +} + +//========================================================================== +// +// AssertSegment +// +//========================================================================== + +static void AssertSegment(gameArchiveSegment_t segType) +{ + if (SV_ReadLong() != segType) + { + I_Error("Corrupt save game: Segment [%d] failed alignment check", + segType); + } +} + +//========================================================================== +// +// ClearSaveSlot +// +// Deletes all save game files associated with a slot number. +// +//========================================================================== + +static void ClearSaveSlot(int slot) +{ + int i; + char fileName[100]; + + for (i = 0; i < MAX_MAPS; i++) + { + M_snprintf(fileName, sizeof(fileName), + "%shex%d%02d.hxs", SavePath, slot, i); + M_remove(fileName); + } + M_snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, slot); + M_remove(fileName); +} + +//========================================================================== +// +// CopySaveSlot +// +// Copies all the save game files from one slot to another. +// +//========================================================================== + +static void CopySaveSlot(int sourceSlot, int destSlot) +{ + int i; + char sourceName[100]; + char destName[100]; + + for (i = 0; i < MAX_MAPS; i++) + { + M_snprintf(sourceName, sizeof(sourceName), + "%shex%d%02d.hxs", SavePath, sourceSlot, i); + if (ExistingFile(sourceName)) + { + M_snprintf(destName, sizeof(destName), + "%shex%d%02d.hxs", SavePath, destSlot, i); + CopyFile(sourceName, destName); + } + } + M_snprintf(sourceName, sizeof(sourceName), + "%shex%d.hxs", SavePath, sourceSlot); + if (ExistingFile(sourceName)) + { + M_snprintf(destName, sizeof(destName), + "%shex%d.hxs", SavePath, destSlot); + CopyFile(sourceName, destName); + } + else + { + I_Error("Could not load savegame %s", sourceName); + } +} + +//========================================================================== +// +// CopyFile +// +// This function was rewritten to copy files with minimal strain on zone +// allocation and allow for big maps that technically work in vanilla to +// save without error. +//========================================================================== + +static void CopyFile(char *source_name, char *dest_name) +{ + const int BUFFER_CHUNK_SIZE = 0x10000; + + byte *buffer; + int file_length, file_remaining; + FILE *read_handle, *write_handle; + int buf_count, read_count, write_count; + + read_handle = M_fopen(source_name, "rb"); + if (read_handle == NULL) + { + I_Error ("Couldn't read file %s", source_name); + } + file_length = file_remaining = M_FileLength(read_handle); + + // Vanilla savegame emulation. + // + // CopyFile() typically calls M_ReadFile() which stores the entire file + // in memory: Chocolate Hexen should force an allocation error here + // whenever it's appropriate. + + if (vanilla_savegame_limit) + { + buffer = Z_Malloc(file_length, PU_STATIC, NULL); + Z_Free(buffer); + } + + write_handle = M_fopen(dest_name, "wb"); + if (write_handle == NULL) + { + I_Error ("Couldn't read file %s", dest_name); + } + + buffer = Z_Malloc (BUFFER_CHUNK_SIZE, PU_STATIC, NULL); + + do + { + buf_count = BUFFER_CHUNK_SIZE; + if( file_remaining < BUFFER_CHUNK_SIZE) + { + buf_count = file_remaining; + } + + read_count = fread(buffer, 1, buf_count, read_handle); + if (read_count < buf_count) + { + I_Error ("Couldn't read file %s", source_name); + } + + write_count = fwrite(buffer, 1, buf_count, write_handle); + if (write_count < buf_count) + { + I_Error ("Couldn't write to file %s", dest_name); + } + + file_remaining -= buf_count; + } while (file_remaining > 0); + + Z_Free(buffer); + fclose(read_handle); + fclose(write_handle); +} + +//========================================================================== +// +// ExistingFile +// +//========================================================================== + +static boolean ExistingFile(char *name) +{ + FILE *fp; + + if ((fp = M_fopen(name, "rb")) != NULL) + { + fclose(fp); + return true; + } + else + { + return false; + } +} + +//========================================================================== +// +// SV_Open +// +//========================================================================== + +static void SV_OpenRead(char *fileName) +{ + SavingFP = M_fopen(fileName, "rb"); + + // Should never happen, only if hex6.hxs cannot ever be created. + if (SavingFP == NULL) + { + I_Error("Could not load savegame %s", fileName); + } +} + +static void SV_OpenWrite(char *fileName) +{ + SavingFP = M_fopen(fileName, "wb"); +} + +//========================================================================== +// +// SV_Close +// +//========================================================================== + +static void SV_Close(void) +{ + if (SavingFP) + { + fclose(SavingFP); + SavingFP = NULL; + } +} + +//========================================================================== +// +// SV_Read +// +//========================================================================== + +static void SV_Read(void *buffer, int size) +{ + int retval = fread(buffer, 1, size, SavingFP); + if (retval != size) + { + I_Error("Incomplete read in SV_Read: Expected %d, got %d bytes", + size, retval); + } +} + +static byte SV_ReadByte(void) +{ + byte result; + SV_Read(&result, sizeof(byte)); + return result; +} + +static uint16_t SV_ReadWord(void) +{ + uint16_t result; + SV_Read(&result, sizeof(unsigned short)); + return SHORT(result); +} + +static uint32_t SV_ReadLong(void) +{ + uint32_t result; + SV_Read(&result, sizeof(int)); + return LONG(result); +} + +static void *SV_ReadPtr(void) +{ + return (void *) (intptr_t) SV_ReadLong(); +} + +//========================================================================== +// +// SV_Write +// +//========================================================================== + +static void SV_Write(const void *buffer, int size) +{ + fwrite(buffer, size, 1, SavingFP); +} + +static void SV_WriteByte(byte val) +{ + fwrite(&val, sizeof(byte), 1, SavingFP); +} + +static void SV_WriteWord(unsigned short val) +{ + val = SHORT(val); + fwrite(&val, sizeof(unsigned short), 1, SavingFP); +} + +static void SV_WriteLong(unsigned int val) +{ + val = LONG(val); + fwrite(&val, sizeof(int), 1, SavingFP); +} + +static void SV_WritePtr(void *val) +{ + long ptr; + + // Write a pointer value. In Vanilla Hexen pointers are 32-bit but + // nowadays they might be larger. Whatever value we write here isn't + // going to be much use when we reload the game. + + ptr = (long)(intptr_t) val; + SV_WriteLong((unsigned int) (ptr & 0xffffffff)); +} diff --git a/games/NXDoom/src/hexen/textdefs.h b/games/NXDoom/src/hexen/textdefs.h new file mode 100644 index 00000000000..febeb178d54 --- /dev/null +++ b/games/NXDoom/src/hexen/textdefs.h @@ -0,0 +1,172 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +// MN_menu.c --------------------------------------------------------------- + +#define PRESSKEY "press a key." +#define PRESSYN "press y or n." +#define TXT_PAUSED "PAUSED" +#define QUITMSG "are you sure you want to\nquit this great game?" +#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY +#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY +#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY +#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY +#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN +#define QLPROMPT "do you want to quickload the game named"\ + "\n\n'%s'?\n\n"PRESSYN +#define NEWGAME "you can't start a new game\n"\ + "while in a network game.\n\n"PRESSKEY +#define MSGOFF "Messages OFF" +#define MSGON "Messages ON" +#define NETEND "you can't end a netgame!\n\n"PRESSKEY +#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN +#define DOSY "(press y to quit to dos.)" +#define TXT_GAMMA_LEVEL_OFF "GAMMA CORRECTION OFF" +#define TXT_GAMMA_LEVEL_1 "GAMMA CORRECTION LEVEL 1" +#define TXT_GAMMA_LEVEL_2 "GAMMA CORRECTION LEVEL 2" +#define TXT_GAMMA_LEVEL_3 "GAMMA CORRECTION LEVEL 3" +#define TXT_GAMMA_LEVEL_4 "GAMMA CORRECTION LEVEL 4" +#define EMPTYSTRING "empty slot" + +// P_inter.c --------------------------------------------------------------- + +// Mana + +#define TXT_MANA_1 "BLUE MANA" +#define TXT_MANA_2 "GREEN MANA" +#define TXT_MANA_BOTH "COMBINED MANA" + +// Keys + +#define TXT_KEY_STEEL "STEEL KEY" +#define TXT_KEY_CAVE "CAVE KEY" +#define TXT_KEY_AXE "AXE KEY" +#define TXT_KEY_FIRE "FIRE KEY" +#define TXT_KEY_EMERALD "EMERALD KEY" +#define TXT_KEY_DUNGEON "DUNGEON KEY" +#define TXT_KEY_SILVER "SILVER KEY" +#define TXT_KEY_RUSTED "RUSTED KEY" +#define TXT_KEY_HORN "HORN KEY" +#define TXT_KEY_SWAMP "SWAMP KEY" +#define TXT_KEY_CASTLE "CASTLE KEY" + +// Artifacts + +#define TXT_ARTIINVULNERABILITY "ICON OF THE DEFENDER" +#define TXT_ARTIHEALTH "QUARTZ FLASK" +#define TXT_ARTISUPERHEALTH "MYSTIC URN" +#define TXT_ARTISUMMON "DARK SERVANT" +#define TXT_ARTITORCH "TORCH" +#define TXT_ARTIEGG "PORKALATOR" +#define TXT_ARTIFLY "WINGS OF WRATH" +#define TXT_ARTITELEPORT "CHAOS DEVICE" +#define TXT_ARTIPOISONBAG "FLECHETTE" +#define TXT_ARTITELEPORTOTHER "BANISHMENT DEVICE" +#define TXT_ARTISPEED "BOOTS OF SPEED" +#define TXT_ARTIBOOSTMANA "KRATER OF MIGHT" +#define TXT_ARTIBOOSTARMOR "DRAGONSKIN BRACERS" +#define TXT_ARTIBLASTRADIUS "DISC OF REPULSION" +#define TXT_ARTIHEALINGRADIUS "MYSTIC AMBIT INCANT" + +// Puzzle artifacts + +#define TXT_ARTIPUZZSKULL "YORICK'S SKULL" +#define TXT_ARTIPUZZGEMBIG "HEART OF D'SPARIL" +#define TXT_ARTIPUZZGEMRED "RUBY PLANET" +#define TXT_ARTIPUZZGEMGREEN1 "EMERALD PLANET" +#define TXT_ARTIPUZZGEMGREEN2 "EMERALD PLANET" +#define TXT_ARTIPUZZGEMBLUE1 "SAPPHIRE PLANET" +#define TXT_ARTIPUZZGEMBLUE2 "SAPPHIRE PLANET" +#define TXT_ARTIPUZZBOOK1 "DAEMON CODEX" +#define TXT_ARTIPUZZBOOK2 "LIBER OSCURA" +#define TXT_ARTIPUZZSKULL2 "FLAME MASK" +#define TXT_ARTIPUZZFWEAPON "GLAIVE SEAL" +#define TXT_ARTIPUZZCWEAPON "HOLY RELIC" +#define TXT_ARTIPUZZMWEAPON "SIGIL OF THE MAGUS" +#define TXT_ARTIPUZZGEAR "CLOCK GEAR" +#define TXT_USEPUZZLEFAILED "YOU CANNOT USE THIS HERE" + +// Items + +#define TXT_ITEMHEALTH "CRYSTAL VIAL" +#define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING" +#define TXT_ITEMSHIELD1 "SILVER SHIELD" +#define TXT_ITEMSHIELD2 "ENCHANTED SHIELD" +#define TXT_ITEMSUPERMAP "MAP SCROLL" +#define TXT_ARMOR1 "MESH ARMOR" +#define TXT_ARMOR2 "FALCON SHIELD" +#define TXT_ARMOR3 "PLATINUM HELMET" +#define TXT_ARMOR4 "AMULET OF WARDING" + +// Weapons + +#define TXT_WEAPON_F2 "TIMON'S AXE" +#define TXT_WEAPON_F3 "HAMMER OF RETRIBUTION" +#define TXT_WEAPON_F4 "QUIETUS ASSEMBLED" +#define TXT_WEAPON_C2 "SERPENT STAFF" +#define TXT_WEAPON_C3 "FIRESTORM" +#define TXT_WEAPON_C4 "WRAITHVERGE ASSEMBLED" +#define TXT_WEAPON_M2 "FROST SHARDS" +#define TXT_WEAPON_M3 "ARC OF DEATH" +#define TXT_WEAPON_M4 "BLOODSCOURGE ASSEMBLED" +#define TXT_QUIETUS_PIECE "SEGMENT OF QUIETUS" +#define TXT_WRAITHVERGE_PIECE "SEGMENT OF WRAITHVERGE" +#define TXT_BLOODSCOURGE_PIECE "SEGMENT OF BLOODSCOURGE" + +// SB_bar.c ---------------------------------------------------------------- + +#define TXT_CHEATGODON "GOD MODE ON" +#define TXT_CHEATGODOFF "GOD MODE OFF" +#define TXT_CHEATNOCLIPON "NO CLIPPING ON" +#define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF" +#define TXT_CHEATWEAPONS "ALL WEAPONS" +#define TXT_CHEATHEALTH "FULL HEALTH" +#define TXT_CHEATKEYS "ALL KEYS" +#define TXT_CHEATSOUNDON "SOUND DEBUG ON" +#define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF" +#define TXT_CHEATTICKERON "TICKER ON" +#define TXT_CHEATTICKEROFF "TICKER OFF" +#define TXT_CHEATARTIFACTS3 "ALL ARTIFACTS" +#define TXT_CHEATARTIFACTSFAIL "BAD INPUT" +#define TXT_CHEATWARP "LEVEL WARP" +#define TXT_CHEATSCREENSHOT "SCREENSHOT" +#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!" +#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS" +#define TXT_CHEATBADINPUT "BAD INPUT" +#define TXT_CHEATNOMAP "CAN'T FIND MAP" + +// G_game.c ---------------------------------------------------------------- + +#define TXT_GAMESAVED "GAME SAVED" + +// M_misc.c ---------------------------------------------------------------- + +#define HUSTR_CHATMACRO1 "I'm ready to kick butt!" +#define HUSTR_CHATMACRO2 "I'm OK." +#define HUSTR_CHATMACRO3 "I'm not looking too good!" +#define HUSTR_CHATMACRO4 "Help!" +#define HUSTR_CHATMACRO5 "You suck!" +#define HUSTR_CHATMACRO6 "Next time, scumbag..." +#define HUSTR_CHATMACRO7 "Come here!" +#define HUSTR_CHATMACRO8 "I'll take care of it." +#define HUSTR_CHATMACRO9 "Yes" +#define HUSTR_CHATMACRO0 "No" + +// AM_map.c ---------------------------------------------------------------- + +#define AMSTR_FOLLOWON "FOLLOW MODE ON" +#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF" diff --git a/games/NXDoom/src/hexen/xddefs.h b/games/NXDoom/src/hexen/xddefs.h new file mode 100644 index 00000000000..544f4ce2806 --- /dev/null +++ b/games/NXDoom/src/hexen/xddefs.h @@ -0,0 +1,189 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + + +#ifndef __XDDEFS__ +#define __XDDEFS__ + +#include "doomtype.h" +#include "v_patch.h" + +//-------------------------------------------------------------------------- +// +// Map level types +// +//-------------------------------------------------------------------------- + +// lump order in a map wad +enum +{ + ML_LABEL, + ML_THINGS, + ML_LINEDEFS, + ML_SIDEDEFS, + ML_VERTEXES, + ML_SEGS, + ML_SSECTORS, + ML_NODES, + ML_SECTORS, + ML_REJECT, + ML_BLOCKMAP, + ML_BEHAVIOR +}; + +typedef PACKED_STRUCT ( +{ + short x; + short y; +}) mapvertex_t; + +typedef PACKED_STRUCT ( +{ + short textureoffset; + short rowoffset; + char toptexture[8]; + char bottomtexture[8]; + char midtexture[8]; + short sector; // on viewer's side +}) mapsidedef_t; + +typedef PACKED_STRUCT ( +{ + short v1; + short v2; + short flags; + byte special; + byte arg1; + byte arg2; + byte arg3; + byte arg4; + byte arg5; + short sidenum[2]; // sidenum[1] will be -1 if one sided +}) maplinedef_t; + +#define ML_BLOCKING 0x0001 +#define ML_BLOCKMONSTERS 0x0002 +#define ML_TWOSIDED 0x0004 +#define ML_DONTPEGTOP 0x0008 +#define ML_DONTPEGBOTTOM 0x0010 +#define ML_SECRET 0x0020 // don't map as two sided: IT'S A SECRET! +#define ML_SOUNDBLOCK 0x0040 // don't let sound cross two of these +#define ML_DONTDRAW 0x0080 // don't draw on the automap +#define ML_MAPPED 0x0100 // set if already drawn in automap +#define ML_REPEAT_SPECIAL 0x0200 // special is repeatable +#define ML_SPAC_SHIFT 10 +#define ML_SPAC_MASK 0x1c00 +#define GET_SPAC(flags) ((flags&ML_SPAC_MASK)>>ML_SPAC_SHIFT) + +// Special activation types +#define SPAC_CROSS 0 // when player crosses line +#define SPAC_USE 1 // when player uses line +#define SPAC_MCROSS 2 // when monster crosses line +#define SPAC_IMPACT 3 // when projectile hits line +#define SPAC_PUSH 4 // when player/monster pushes line +#define SPAC_PCROSS 5 // when projectile crosses line + +typedef PACKED_STRUCT ( +{ + short floorheight; + short ceilingheight; + char floorpic[8]; + char ceilingpic[8]; + short lightlevel; + short special; + short tag; +}) mapsector_t; + +typedef PACKED_STRUCT ( +{ + short numsegs; + short firstseg; // segs are stored sequentially +}) mapsubsector_t; + +typedef PACKED_STRUCT ( +{ + short v1; + short v2; + short angle; + short linedef; + short side; + short offset; +}) mapseg_t; + +#define NF_SUBSECTOR 0x8000 +typedef PACKED_STRUCT ( +{ + short x, y, dx, dy; // partition line + short bbox[2][4]; // bounding box for each child + unsigned short children[2]; // if NF_SUBSECTOR its a subsector +}) mapnode_t; + +typedef PACKED_STRUCT ( +{ + short tid; + short x; + short y; + short height; + short angle; + short type; + short options; + byte special; + byte arg1; + byte arg2; + byte arg3; + byte arg4; + byte arg5; +}) mapthing_t; + +#define MTF_EASY 1 +#define MTF_NORMAL 2 +#define MTF_HARD 4 +#define MTF_AMBUSH 8 +#define MTF_DORMANT 16 +#define MTF_FIGHTER 32 +#define MTF_CLERIC 64 +#define MTF_MAGE 128 +#define MTF_GSINGLE 256 +#define MTF_GCOOP 512 +#define MTF_GDEATHMATCH 1024 + +//-------------------------------------------------------------------------- +// +// Texture definition +// +//-------------------------------------------------------------------------- + +typedef PACKED_STRUCT ( +{ + short originx; + short originy; + short patch; + short stepdir; + short colormap; +}) mappatch_t; + +typedef PACKED_STRUCT ( +{ + char name[8]; + boolean masked; + short width; + short height; + int obsolete; + short patchcount; + mappatch_t patches[1]; +}) maptexture_t; + +#endif // __XDDEFS__ diff --git a/games/NXDoom/src/i_cdmus.c b/games/NXDoom/src/i_cdmus.c new file mode 100644 index 00000000000..caad87af8d4 --- /dev/null +++ b/games/NXDoom/src/i_cdmus.c @@ -0,0 +1,79 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// +// 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. +// +// +// Hexen CD interface. +// + +#include + +#include "SDL.h" + +#include "doomtype.h" + +#include "i_cdmus.h" + +int cd_Error; + +int I_CDMusInit(void) +{ + fprintf(stderr, + "I_CDMusInit: CD music playback is no longer supported! " + "Please use digital music packs instead:\n" + "https://www.chocolate-doom.org/wiki/index.php/Digital_music_packs\n"); + return -1; +} + +// We cannot print status messages inline during startup, they must +// be deferred until after I_CDMusInit has returned. + +void I_CDMusPrintStartup(void) +{ +} + +int I_CDMusPlay(int track) +{ + return 0; +} + +int I_CDMusStop(void) +{ + return 0; +} + +int I_CDMusResume(void) +{ + return 0; +} + +int I_CDMusSetVolume(int volume) +{ + return 0; +} + +int I_CDMusFirstTrack(void) +{ + return 0; +} + +int I_CDMusLastTrack(void) +{ + return 0; +} + +int I_CDMusTrackLength(int track_num) +{ + return 0; +} + diff --git a/games/NXDoom/src/i_cdmus.h b/games/NXDoom/src/i_cdmus.h new file mode 100644 index 00000000000..31db2a659ae --- /dev/null +++ b/games/NXDoom/src/i_cdmus.h @@ -0,0 +1,41 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// +// 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. +// + +// i_cdmus.h + +#ifndef __ICDMUS__ +#define __ICDMUS__ + +#define CDERR_NOTINSTALLED 10 // MSCDEX not installed +#define CDERR_NOAUDIOSUPPORT 11 // CD-ROM Doesn't support audio +#define CDERR_NOAUDIOTRACKS 12 // Current CD has no audio tracks +#define CDERR_BADDRIVE 20 // Bad drive number +#define CDERR_BADTRACK 21 // Bad track number +#define CDERR_IOCTLBUFFMEM 22 // Not enough low memory for IOCTL +#define CDERR_DEVREQBASE 100 // DevReq errors + +extern int cd_Error; + +int I_CDMusInit(void); +void I_CDMusPrintStartup(void); +int I_CDMusPlay(int track); +int I_CDMusStop(void); +int I_CDMusResume(void); +int I_CDMusSetVolume(int volume); +int I_CDMusFirstTrack(void); +int I_CDMusLastTrack(void); +int I_CDMusTrackLength(int track); + +#endif diff --git a/games/NXDoom/src/i_endoom.c b/games/NXDoom/src/i_endoom.c new file mode 100644 index 00000000000..9beacc90199 --- /dev/null +++ b/games/NXDoom/src/i_endoom.c @@ -0,0 +1,79 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Exit text-mode ENDOOM screen. +// + +#include +#include + +#include "config.h" +#include "doomtype.h" +#include "i_video.h" + +#include "txt_main.h" + +#define ENDOOM_W 80 +#define ENDOOM_H 25 + +// +// Displays the text mode ending screen after the game quits +// + +void I_Endoom(byte *endoom_data) +{ + unsigned char *screendata; + int y; + int indent; + + // Set up text mode screen + + TXT_Init(); + + TXT_SetWindowTitle(PACKAGE_STRING); + // SDL2-TODO I_InitWindowTitle(); + // SDL2-TODO I_InitWindowIcon(); + + // Write the data to the screen memory + + screendata = TXT_GetScreenData(); + + indent = (ENDOOM_W - TXT_SCREEN_W) / 2; + + for (y=0; y 0) + { + break; + } + + TXT_Sleep(0); + } + + // Shut down text mode screen + + TXT_Shutdown(); +} + diff --git a/games/NXDoom/src/i_endoom.h b/games/NXDoom/src/i_endoom.h new file mode 100644 index 00000000000..8c8ff457fae --- /dev/null +++ b/games/NXDoom/src/i_endoom.h @@ -0,0 +1,29 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Exit text-mode ENDOOM screen. +// + + +#ifndef __I_ENDOOM__ +#define __I_ENDOOM__ + +// Display the Endoom screen on shutdown. Pass a pointer to the +// ENDOOM lump. + +void I_Endoom(byte *data); + +#endif + diff --git a/games/NXDoom/src/i_flmusic.c b/games/NXDoom/src/i_flmusic.c new file mode 100644 index 00000000000..a0978a0f189 --- /dev/null +++ b/games/NXDoom/src/i_flmusic.c @@ -0,0 +1,332 @@ +// +// Copyright(C) 2022 Roman Fomin +// Copyright(C) 2023 Michael Day +// +// 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. +// +// DESCRIPTION: +// FluidSynth backend + +#include "config.h" + +#ifdef HAVE_FLUIDSYNTH + +#include "fluidsynth.h" + +#if (FLUIDSYNTH_VERSION_MAJOR < 2 || \ + (FLUIDSYNTH_VERSION_MAJOR == 2 && FLUIDSYNTH_VERSION_MINOR < 2)) + +typedef int fluid_int_t; +typedef long fluid_long_long_t; + +#else + +typedef fluid_long_long_t fluid_int_t; + +#endif + +#include "SDL_mixer.h" + +#include "doomtype.h" +#include "i_system.h" +#include "i_sound.h" +#include "m_misc.h" +#include "memio.h" +#include "mus2mid.h" + +#include + +char *fsynth_sf_path = ""; +int fsynth_chorus_active = 1; +float fsynth_chorus_depth = 5.0f; +float fsynth_chorus_level = 0.35f; +int fsynth_chorus_nr = 3; +float fsynth_chorus_speed = 0.3f; +char *fsynth_midibankselect = "gs"; +int fsynth_polyphony = 256; +int fsynth_reverb_active = 1; +float fsynth_reverb_damp = 0.4f; +float fsynth_reverb_level = 0.15f; +float fsynth_reverb_roomsize = 0.6f; +float fsynth_reverb_width = 4.0f; +float fsynth_gain = 1.0f; + +static fluid_synth_t *synth = NULL; +static fluid_settings_t *settings = NULL; +static fluid_player_t *player = NULL; + +static void FL_Mix_Callback(void *udata, Uint8 *stream, int len) +{ + int result; + + result = fluid_synth_write_s16(synth, len / 4, stream, 0, 2, stream, 1, 2); + + if (result != FLUID_OK) + { + fprintf(stderr, + "FL_Mix_Callback: Error generating FluidSynth audio.\n"); + } +} + +static boolean I_FL_InitMusic(void) +{ + int sf_id; + + if (strlen(fsynth_sf_path) == 0) + { + fprintf(stderr, + "I_FL_InitMusic: No FluidSynth soundfont file specified.\n"); + return false; + } + + settings = new_fluid_settings(); + + fluid_settings_setnum(settings, "synth.sample-rate", snd_samplerate); + fluid_settings_setstr(settings, "synth.midi-bank-select", + fsynth_midibankselect); + fluid_settings_setint(settings, "synth.polyphony", fsynth_polyphony); + + fluid_settings_setint(settings, "synth.chorus.active", + fsynth_chorus_active); + fluid_settings_setint(settings, "synth.reverb.active", + fsynth_reverb_active); + + if (fsynth_reverb_active) + { + fluid_settings_setnum(settings, "synth.reverb.room-size", + fsynth_reverb_roomsize); + fluid_settings_setnum(settings, "synth.reverb.damp", + fsynth_reverb_damp); + fluid_settings_setnum(settings, "synth.reverb.width", + fsynth_reverb_width); + fluid_settings_setnum(settings, "synth.reverb.level", + fsynth_reverb_level); + } + + if (fsynth_chorus_active) + { + fluid_settings_setnum(settings, "synth.chorus.level", + fsynth_chorus_level); + fluid_settings_setnum(settings, "synth.chorus.depth", + fsynth_chorus_depth); + fluid_settings_setint(settings, "synth.chorus.nr", fsynth_chorus_nr); + fluid_settings_setnum(settings, "synth.chorus.speed", + fsynth_chorus_speed); + } + + if (fsynth_gain < 0.0f) + { + fsynth_gain = 0.0f; + } + if (fsynth_gain > 10.0f) + { + fsynth_gain = 10.0f; + } + + synth = new_fluid_synth(settings); + + if (synth == NULL) + { + fprintf(stderr, + "I_FL_InitMusic: FluidSynth failed to initialize synth.\n"); + return false; + } + + sf_id = fluid_synth_sfload(synth, fsynth_sf_path, true); + if (sf_id == FLUID_FAILED) + { + delete_fluid_synth(synth); + synth = NULL; + delete_fluid_settings(settings); + settings = NULL; + fprintf(stderr, + "I_FL_InitMusic: Error loading FluidSynth soundfont: '%s'.\n", + fsynth_sf_path); + return false; + } + + printf("I_FL_InitMusic: Using '%s'.\n", fsynth_sf_path); + + return true; +} + +static void I_FL_SetMusicVolume(int volume) +{ + if (synth == NULL) + { + return; + } + // FluidSynth's default is 0.2. Make 1.0 the maximum. + // 0 -- 0.2 -- 10.0 + fluid_synth_set_gain(synth, ((float) volume / 127) * fsynth_gain); +} + +static void I_FL_PauseSong(void) +{ + if (player) + { + Mix_HookMusic(NULL, NULL); + } +} + +static void I_FL_ResumeSong(void) +{ + if (player) + { + Mix_HookMusic(FL_Mix_Callback, NULL); + } +} + +static void I_FL_PlaySong(void *handle, boolean looping) +{ + if (player) + { + fluid_player_set_loop(player, looping ? -1 : 1); + fluid_player_play(player); + } +} + +static void I_FL_StopSong(void) +{ + if (player) + { + fluid_player_stop(player); + } +} + +// Determine whether memory block is a .mid file + +static boolean IsMid(const byte *mem, int len) +{ + return len > 4 && !memcmp(mem, "MThd", 4); +} + +static void *I_FL_RegisterSong(void *data, int len) +{ + int result = FLUID_FAILED; + + player = new_fluid_player(synth); + + if (player == NULL) + { + fprintf(stderr, + "I_FL_RegisterSong: FluidSynth failed to initialize player.\n"); + return NULL; + } + + if (IsMid(data, len)) + { + result = fluid_player_add_mem(player, data, len); + + if (result == FLUID_FAILED) + { + fprintf(stderr, + "I_FL_RegisterSong: FluidSynth failed to load MIDI.\n"); + return NULL; + } + } + else + { + // Assume a MUS file and try to convert + MEMFILE *instream; + MEMFILE *outstream; + void *outbuf; + size_t outbuf_len; + + instream = mem_fopen_read(data, len); + outstream = mem_fopen_write(); + + if (mus2mid(instream, outstream) == 0) + { + mem_get_buf(outstream, &outbuf, &outbuf_len); + result = fluid_player_add_mem(player, outbuf, outbuf_len); + } + + mem_fclose(instream); + mem_fclose(outstream); + + if (result == FLUID_FAILED) + { + fprintf(stderr, + "I_FL_RegisterSong: FluidSynth failed to load MUS.\n"); + return NULL; + } + } + + Mix_HookMusic(FL_Mix_Callback, NULL); + return player; +} + +static void I_FL_UnRegisterSong(void *handle) +{ + if (player) + { + fluid_synth_program_reset(synth); + fluid_synth_system_reset(synth); + + Mix_HookMusic(NULL, NULL); + + delete_fluid_player(player); + player = NULL; + } +} + +static void I_FL_ShutdownMusic(void) +{ + I_FL_StopSong(); + I_FL_UnRegisterSong(NULL); + + if (synth) + { + delete_fluid_synth(synth); + synth = NULL; + } + + if (settings) + { + delete_fluid_settings(settings); + settings = NULL; + } +} + +static boolean I_FL_MusicIsPlaying(void) +{ + if (player == NULL) + { + return false; + } + + return (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING); +} + +static const snddevice_t music_fl_devices[] = +{ + SNDDEVICE_FSYNTH, +}; + +const music_module_t music_fl_module = +{ + music_fl_devices, + arrlen(music_fl_devices), + I_FL_InitMusic, + I_FL_ShutdownMusic, + I_FL_SetMusicVolume, + I_FL_PauseSong, + I_FL_ResumeSong, + I_FL_RegisterSong, + I_FL_UnRegisterSong, + I_FL_PlaySong, + I_FL_StopSong, + I_FL_MusicIsPlaying, + NULL // Poll +}; + +#endif diff --git a/games/NXDoom/src/i_glob.c b/games/NXDoom/src/i_glob.c new file mode 100644 index 00000000000..79c3e898366 --- /dev/null +++ b/games/NXDoom/src/i_glob.c @@ -0,0 +1,373 @@ +// +// Copyright(C) 2018 Simon Howard +// +// 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. +// +// +// File globbing API. This allows the contents of the filesystem +// to be interrogated. +// + +#include +#include +#include + +#include "i_glob.h" +#include "m_misc.h" +#include "config.h" + +#if defined(_WIN32) +#include +#ifndef S_ISDIR +#define S_ISDIR(m) (((m)& S_IFMT) == S_IFDIR) +#endif +#elif defined(HAVE_DIRENT_H) +#include +#include +#elif defined(__WATCOMC__) +// Watcom has the same API in a different header. +#include +#else +#define NO_DIRENT_IMPLEMENTATION +#endif + +#ifndef NO_DIRENT_IMPLEMENTATION + +// Only the fields d_name and (as an XSI extension) d_ino are specified +// in POSIX.1. Other than Linux, the d_type field is available mainly +// only on BSD systems. The remaining fields are available on many, but +// not all systems. +static boolean IsDirectory(char *dir, struct dirent *de) +{ +#if defined(_DIRENT_HAVE_D_TYPE) + if (de->d_type != DT_UNKNOWN && de->d_type != DT_LNK) + { + return de->d_type == DT_DIR; + } + else +#endif + { + char *filename; + struct stat sb; + int result; + + filename = M_StringJoin(dir, DIR_SEPARATOR_S, de->d_name, NULL); + result = M_stat(filename, &sb); + free(filename); + + if (result != 0) + { + return false; + } + + return S_ISDIR(sb.st_mode); + } +} + +struct glob_s +{ + char **globs; + int num_globs; + int flags; + DIR *dir; + char *directory; + char *last_filename; + // These fields are only used when the GLOB_FLAG_SORTED flag is set: + char **filenames; + int filenames_len; + int next_index; +}; + +static void FreeStringList(char **globs, int num_globs) +{ + int i; + for (i = 0; i < num_globs; ++i) + { + free(globs[i]); + } + free(globs); +} + +glob_t *I_StartMultiGlob(const char *directory, int flags, + const char *glob, ...) +{ + char **globs; + int num_globs; + glob_t *result; + va_list args; + + globs = malloc(sizeof(char *)); + if (globs == NULL) + { + return NULL; + } + globs[0] = M_StringDuplicate(glob); + num_globs = 1; + + va_start(args, glob); + for (;;) + { + const char *arg = va_arg(args, const char *); + char **new_globs; + + if (arg == NULL) + { + break; + } + + new_globs = realloc(globs, sizeof(char *) * (num_globs + 1)); + if (new_globs == NULL) + { + FreeStringList(globs, num_globs); + } + globs = new_globs; + globs[num_globs] = M_StringDuplicate(arg); + ++num_globs; + } + va_end(args); + + result = malloc(sizeof(glob_t)); + if (result == NULL) + { + FreeStringList(globs, num_globs); + return NULL; + } + + result->dir = opendir(directory); + if (result->dir == NULL) + { + FreeStringList(globs, num_globs); + free(result); + return NULL; + } + + result->directory = M_StringDuplicate(directory); + result->globs = globs; + result->num_globs = num_globs; + result->flags = flags; + result->last_filename = NULL; + result->filenames = NULL; + result->filenames_len = 0; + result->next_index = -1; + return result; +} + +glob_t *I_StartGlob(const char *directory, const char *glob, int flags) +{ + return I_StartMultiGlob(directory, flags, glob, NULL); +} + +void I_EndGlob(glob_t *glob) +{ + if (glob == NULL) + { + return; + } + + FreeStringList(glob->globs, glob->num_globs); + FreeStringList(glob->filenames, glob->filenames_len); + + free(glob->directory); + free(glob->last_filename); + (void) closedir(glob->dir); + free(glob); +} + +static boolean MatchesGlob(const char *name, const char *glob, int flags) +{ + int n, g; + + while (*glob != '\0') + { + n = *name; + g = *glob; + + if ((flags & GLOB_FLAG_NOCASE) != 0) + { + n = tolower(n); + g = tolower(g); + } + + if (g == '*') + { + // To handle *-matching we skip past the * and recurse + // to check each subsequent character in turn. If none + // match then the whole match is a failure. + while (*name != '\0') + { + if (MatchesGlob(name, glob + 1, flags)) + { + return true; + } + ++name; + } + return glob[1] == '\0'; + } + else if (g != '?' && n != g) + { + // For normal characters the name must match the glob, + // but for ? we don't care what the character is. + return false; + } + + ++name; + ++glob; + } + + // Match successful when glob and name end at the same time. + return *name == '\0'; +} + +static boolean MatchesAnyGlob(const char *name, glob_t *glob) +{ + int i; + + for (i = 0; i < glob->num_globs; ++i) + { + if (MatchesGlob(name, glob->globs[i], glob->flags)) + { + return true; + } + } + return false; +} + +static char *NextGlob(glob_t *glob) +{ + struct dirent *de; + + do + { + de = readdir(glob->dir); + if (de == NULL) + { + return NULL; + } + } while (IsDirectory(glob->directory, de) + || !MatchesAnyGlob(de->d_name, glob)); + + // Return the fully-qualified path, not just the bare filename. + return M_StringJoin(glob->directory, DIR_SEPARATOR_S, de->d_name, NULL); +} + +static void ReadAllFilenames(glob_t *glob) +{ + char *name; + + glob->filenames = NULL; + glob->filenames_len = 0; + glob->next_index = 0; + + for (;;) + { + name = NextGlob(glob); + if (name == NULL) + { + break; + } + glob->filenames = realloc(glob->filenames, + (glob->filenames_len + 1) * sizeof(char *)); + glob->filenames[glob->filenames_len] = name; + ++glob->filenames_len; + } +} + +static void SortFilenames(char **filenames, int len, int flags) +{ + char *pivot, *tmp; + int i, left_len, cmp; + + if (len <= 1) + { + return; + } + pivot = filenames[len - 1]; + left_len = 0; + for (i = 0; i < len-1; ++i) + { + if ((flags & GLOB_FLAG_NOCASE) != 0) + { + cmp = strcasecmp(filenames[i], pivot); + } + else + { + cmp = strcmp(filenames[i], pivot); + } + + if (cmp < 0) + { + tmp = filenames[i]; + filenames[i] = filenames[left_len]; + filenames[left_len] = tmp; + ++left_len; + } + } + filenames[len - 1] = filenames[left_len]; + filenames[left_len] = pivot; + + SortFilenames(filenames, left_len, flags); + SortFilenames(&filenames[left_len + 1], len - left_len - 1, flags); +} + +const char *I_NextGlob(glob_t *glob) +{ + const char *result; + + if (glob == NULL) + { + return NULL; + } + + // In unsorted mode we just return the filenames as we read + // them back from the system API. + if ((glob->flags & GLOB_FLAG_SORTED) == 0) + { + free(glob->last_filename); + glob->last_filename = NextGlob(glob); + return glob->last_filename; + } + + // In sorted mode we read the whole list of filenames into memory, + // sort them and return them one at a time. + if (glob->next_index < 0) + { + ReadAllFilenames(glob); + SortFilenames(glob->filenames, glob->filenames_len, glob->flags); + } + if (glob->next_index >= glob->filenames_len) + { + return NULL; + } + result = glob->filenames[glob->next_index]; + ++glob->next_index; + return result; +} + +#else /* #ifdef NO_DIRENT_IMPLEMENTATION */ + +#warning No native implementation of file globbing. + +glob_t *I_StartGlob(const char *directory, const char *glob, int flags) +{ + return NULL; +} + +void I_EndGlob(glob_t *glob) +{ +} + +const char *I_NextGlob(glob_t *glob) +{ + return ""; +} + +#endif /* #ifdef NO_DIRENT_IMPLEMENTATION */ + diff --git a/games/NXDoom/src/i_glob.h b/games/NXDoom/src/i_glob.h new file mode 100644 index 00000000000..f976db01c4f --- /dev/null +++ b/games/NXDoom/src/i_glob.h @@ -0,0 +1,44 @@ +// +// Copyright(C) 2018 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System specific file globbing interface. +// + + +#ifndef __I_GLOB__ +#define __I_GLOB__ + +#define GLOB_FLAG_NOCASE 0x01 +#define GLOB_FLAG_SORTED 0x02 + +typedef struct glob_s glob_t; + +// Start reading a list of file paths from the given directory which match +// the given glob pattern. I_EndGlob() must be called on completion. +glob_t *I_StartGlob(const char *directory, const char *glob, int flags); + +// Same as I_StartGlob but multiple glob patterns can be provided. The list +// of patterns must be terminated with NULL. +glob_t *I_StartMultiGlob(const char *directory, int flags, + const char *glob, ...); + +// Finish reading file list. +void I_EndGlob(glob_t *glob); + +// Read the name of the next globbed filename. NULL is returned if there +// are no more found. +const char *I_NextGlob(glob_t *glob); + +#endif + diff --git a/games/NXDoom/src/i_input.c b/games/NXDoom/src/i_input.c new file mode 100644 index 00000000000..091aa6b88eb --- /dev/null +++ b/games/NXDoom/src/i_input.c @@ -0,0 +1,473 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// SDL implementation of system-specific input interface. +// + +#include + +#include "SDL.h" +#include "SDL_keycode.h" + +#include "doomkeys.h" +#include "doomtype.h" +#include "d_event.h" +#include "i_input.h" +#include "m_argv.h" +#include "m_config.h" + +static const int scancode_translate_table[] = SCANCODE_TO_KEYS_ARRAY; + +// Lookup table for mapping ASCII characters to their equivalent when +// shift is pressed on a US layout keyboard. This is the original table +// as found in the Doom sources, comments and all. +static const char shiftxform[] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, ' ', '!', '"', '#', '$', '%', '&', + '"', // shift-' + '(', ')', '*', '+', + '<', // shift-, + '_', // shift-- + '>', // shift-. + '?', // shift-/ + ')', // shift-0 + '!', // shift-1 + '@', // shift-2 + '#', // shift-3 + '$', // shift-4 + '%', // shift-5 + '^', // shift-6 + '&', // shift-7 + '*', // shift-8 + '(', // shift-9 + ':', + ':', // shift-; + '<', + '+', // shift-= + '>', '?', '@', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '[', // shift-[ + '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK + ']', // shift-] + '"', '_', + '\'', // shift-` + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '{', '|', '}', '~', 127 +}; + +// If true, I_StartTextInput() has been called, and we are populating +// the data3 field of ev_keydown events. +static boolean text_input_enabled = true; + +// Bit mask of mouse button state. +static unsigned int mouse_button_state = 0; + +// Disallow mouse and joystick movement to cause forward/backward +// motion. Specified with the '-novert' command line parameter. +// This is an int to allow saving to config file +int novert = 0; + +// If true, keyboard mapping is ignored, like in Vanilla Doom. +// The sensible thing to do is to disable this if you have a non-US +// keyboard. + +int vanilla_keyboard_mapping = true; + +// Mouse acceleration +// +// This emulates some of the behavior of DOS mouse drivers by increasing +// the speed when the mouse is moved fast. +// +// The mouse input values are input directly to the game, but when +// the values exceed the value of mouse_threshold, they are multiplied +// by mouse_acceleration to increase the speed. +float mouse_acceleration = 2.0; +int mouse_threshold = 10; + +// Translates the SDL key to a value of the type found in doomkeys.h +static int TranslateKey(SDL_Keysym *sym) +{ + int scancode = sym->scancode; + + switch (scancode) + { + case SDL_SCANCODE_LCTRL: + case SDL_SCANCODE_RCTRL: + return KEY_RCTRL; + + case SDL_SCANCODE_LSHIFT: + case SDL_SCANCODE_RSHIFT: + return KEY_RSHIFT; + + case SDL_SCANCODE_LALT: + return KEY_LALT; + + case SDL_SCANCODE_RALT: + return KEY_RALT; + + default: + if (scancode >= 0 && scancode < arrlen(scancode_translate_table)) + { + return scancode_translate_table[scancode]; + } + else + { + return 0; + } + } +} + +// Get the localized version of the key press. This takes into account the +// keyboard layout, but does not apply any changes due to modifiers, (eg. +// shift-, alt-, etc.) +static int GetLocalizedKey(SDL_Keysym *sym) +{ + // When using Vanilla mapping, we just base everything off the scancode + // and always pretend the user is using a US layout keyboard. + if (vanilla_keyboard_mapping) + { + return TranslateKey(sym); + } + else + { + int result = sym->sym; + + if (result < 0 || result >= 128) + { + result = 0; + } + + return result; + } +} + +// Get the equivalent ASCII (Unicode?) character for a keypress. +static int GetTypedChar(SDL_Keysym *sym) +{ + // We only return typed characters when entering text, after + // I_StartTextInput() has been called. Otherwise we return nothing. + if (!text_input_enabled) + { + return 0; + } + + // If we're strictly emulating Vanilla, we should always act like + // we're using a US layout keyboard (in ev_keydown, data1=data2). + // Otherwise we should use the native key mapping. + if (vanilla_keyboard_mapping) + { + int result = TranslateKey(sym); + + // If shift is held down, apply the original uppercase + // translation table used under DOS. + if ((SDL_GetModState() & KMOD_SHIFT) != 0 + && result >= 0 && result < arrlen(shiftxform)) + { + result = shiftxform[result]; + } + + return result; + } + else + { + SDL_Event next_event; + + // Special cases, where we always return a fixed value. + switch (sym->sym) + { + case SDLK_BACKSPACE: return KEY_BACKSPACE; + case SDLK_RETURN: return KEY_ENTER; + default: + break; + } + + // The following is a gross hack, but I don't see an easier way + // of doing this within the SDL2 API (in SDL1 it was easier). + // We want to get the fully transformed input character associated + // with this keypress - correct keyboard layout, appropriately + // transformed by any modifier keys, etc. So peek ahead in the SDL + // event queue and see if the key press is immediately followed by + // an SDL_TEXTINPUT event. If it is, it's reasonable to assume the + // key press and the text input are connected. Technically the SDL + // API does not guarantee anything of the sort, but in practice this + // is what happens and I've verified it through manual inspect of + // the SDL source code. + // + // In an ideal world we'd split out ev_keydown into a separate + // ev_textinput event, as SDL2 has done. But this doesn't work + // (I experimented with the idea), because lots of Doom's code is + // based around different responders "eating" events to stop them + // being passed on to another responder. If code is listening for + // a text input, it cannot block the corresponding keydown events + // which can affect other responders. + // + // So we're stuck with this as a rather fragile alternative. + + if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT, + SDL_FIRSTEVENT, SDL_LASTEVENT) == 1 + && next_event.type == SDL_TEXTINPUT) + { + // If an SDL_TEXTINPUT event is found, we always assume it + // matches the key press. The input text must be a single + // ASCII character - if it isn't, it's possible the input + // char is a Unicode value instead; better to send a null + // character than the unshifted key. + if (strlen(next_event.text.text) == 1 + && (next_event.text.text[0] & 0x80) == 0) + { + return next_event.text.text[0]; + } + } + + // Failed to find anything :/ + return 0; + } +} + +void I_HandleKeyboardEvent(SDL_Event *sdlevent) +{ + // XXX: passing pointers to event for access after this function + // has terminated is undefined behaviour + event_t event; + + switch (sdlevent->type) + { + case SDL_KEYDOWN: + event.type = ev_keydown; + event.data1 = TranslateKey(&sdlevent->key.keysym); + event.data2 = GetLocalizedKey(&sdlevent->key.keysym); + event.data3 = GetTypedChar(&sdlevent->key.keysym); + + if (event.data1 != 0) + { + D_PostEvent(&event); + } + break; + + case SDL_KEYUP: + event.type = ev_keyup; + event.data1 = TranslateKey(&sdlevent->key.keysym); + + // data2/data3 are initialized to zero for ev_keyup. + // For ev_keydown it's the shifted Unicode character + // that was typed, but if something wants to detect + // key releases it should do so based on data1 + // (key ID), not the printable char. + + event.data2 = 0; + event.data3 = 0; + + if (event.data1 != 0) + { + D_PostEvent(&event); + } + break; + + default: + break; + } +} + +void I_StartTextInput(int x1, int y1, int x2, int y2) +{ + text_input_enabled = true; + + if (!vanilla_keyboard_mapping) + { + // SDL2-TODO: SDL_SetTextInputRect(...); + SDL_StartTextInput(); + } +} + +void I_StopTextInput(void) +{ + text_input_enabled = false; + + if (!vanilla_keyboard_mapping) + { + SDL_StopTextInput(); + } +} + +static void UpdateMouseButtonState(unsigned int button, boolean on) +{ + static event_t event; + + if (button < SDL_BUTTON_LEFT || button > MAX_MOUSE_BUTTONS) + { + return; + } + + // Note: button "0" is left, button "1" is right, + // button "2" is middle for Doom. This is different + // to how SDL sees things. + // In the end: Left=0, Right=1, Middle=2, + // WheelUp=3 WheelDown=4, XButton1=5, XButton2=6 + + switch (button) + { + case SDL_BUTTON_LEFT: + button = 0; + break; + + case SDL_BUTTON_RIGHT: + button = 1; + break; + + case SDL_BUTTON_MIDDLE: + button = 2; + break; + + default: + // SDL buttons are indexed from 1. + // And the wheel is mapped to button 3/4 + // So we have to increment 2 and decrement 1 => inc 1. + button++; + break; + } + + // Turn bit representing this button on or off. + + if (on) + { + mouse_button_state |= (1 << button); + } + else + { + mouse_button_state &= ~(1 << button); + } + + // Post an event with the new button state. + + event.type = ev_mouse; + event.data1 = mouse_button_state; + event.data2 = event.data3 = 0; + D_PostEvent(&event); +} + +static void MapMouseWheelToButtons(SDL_MouseWheelEvent *wheel) +{ + // SDL2 distinguishes button events from mouse wheel events. + // We want to treat the mouse wheel as two buttons, as per + // SDL1 + static event_t up, down; + int button; + + if (wheel->y <= 0) + { // scroll down + button = 4; + } + else + { // scroll up + button = 3; + } + + // post a button down event + mouse_button_state |= (1 << button); + down.type = ev_mouse; + down.data1 = mouse_button_state; + down.data2 = down.data3 = 0; + D_PostEvent(&down); + + // post a button up event + mouse_button_state &= ~(1 << button); + up.type = ev_mouse; + up.data1 = mouse_button_state; + up.data2 = up.data3 = 0; + D_PostEvent(&up); +} + +void I_HandleMouseEvent(SDL_Event *sdlevent) +{ + switch (sdlevent->type) + { + case SDL_MOUSEBUTTONDOWN: + UpdateMouseButtonState(sdlevent->button.button, true); + break; + + case SDL_MOUSEBUTTONUP: + UpdateMouseButtonState(sdlevent->button.button, false); + break; + + case SDL_MOUSEWHEEL: + MapMouseWheelToButtons(&(sdlevent->wheel)); + break; + + default: + break; + } +} + +static int AccelerateMouse(int val) +{ + if (val < 0) + return -AccelerateMouse(-val); + + if (val > mouse_threshold) + { + return (int)((val - mouse_threshold) * mouse_acceleration + mouse_threshold); + } + else + { + return val; + } +} + +// +// Read the change in mouse state to generate mouse motion events +// +// This is to combine all mouse movement for a tic into one mouse +// motion event. +void I_ReadMouse(void) +{ + int x, y; + event_t ev; + + SDL_GetRelativeMouseState(&x, &y); + + if (x != 0 || y != 0) + { + ev.type = ev_mouse; + ev.data1 = mouse_button_state; + ev.data2 = AccelerateMouse(x); + + if (!novert) + { + ev.data3 = -AccelerateMouse(y); + } + else + { + ev.data3 = 0; + } + + // XXX: undefined behaviour since event is scoped to + // this function + D_PostEvent(&ev); + } +} + +// Bind all variables controlling input options. +void I_BindInputVariables(void) +{ + M_BindFloatVariable("mouse_acceleration", &mouse_acceleration); + M_BindIntVariable("mouse_threshold", &mouse_threshold); + M_BindIntVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); + M_BindIntVariable("novert", &novert); +} diff --git a/games/NXDoom/src/i_input.h b/games/NXDoom/src/i_input.h new file mode 100644 index 00000000000..0dda76d073f --- /dev/null +++ b/games/NXDoom/src/i_input.h @@ -0,0 +1,49 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System-specific keyboard/mouse input. +// + + +#ifndef __I_INPUT__ +#define __I_INPUT__ + +#include "doomtype.h" + +#include "SDL.h" + + +#define MAX_MOUSE_BUTTONS 8 + +extern float mouse_acceleration; +extern int mouse_threshold; + +void I_BindInputVariables(void); +void I_ReadMouse(void); + +// I_StartTextInput begins text input, activating the on-screen keyboard +// (if one is used). The caller indicates that any entered text will be +// displayed in the rectangle given by the provided set of coordinates. +void I_StartTextInput(int x1, int y1, int x2, int y2); + +// I_StopTextInput finishes text input, deactivating the on-screen keyboard +// (if one is used). +void I_StopTextInput(void); + +void I_HandleKeyboardEvent(SDL_Event *sdlevent); +void I_HandleMouseEvent(SDL_Event *sdlevent); + + +#endif diff --git a/games/NXDoom/src/i_joystick.c b/games/NXDoom/src/i_joystick.c new file mode 100644 index 00000000000..9e28a100831 --- /dev/null +++ b/games/NXDoom/src/i_joystick.c @@ -0,0 +1,826 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// SDL Joystick code. +// + + +#include "SDL.h" +#include "SDL_joystick.h" +#include "SDL_gamecontroller.h" + +#include +#include +#include + +#include "doomtype.h" +#include "d_event.h" +#include "i_joystick.h" +#include "i_system.h" + +#include "m_config.h" +#include "m_fixed.h" +#include "m_misc.h" + +static SDL_GameController *gamepad = NULL; +static SDL_Joystick *joystick = NULL; + +// Configuration variables: + +// Standard default.cfg Joystick enable/disable + +static int usejoystick = 0; + +// Use SDL_gamecontroller interface for the selected device +static int use_gamepad = 0; + +// SDL_GameControllerType of gamepad +static int gamepad_type = 0; + +// SDL GUID and index of the joystick to use. +static char *joystick_guid = ""; +static int joystick_index = -1; + +// Which joystick axis to use for horizontal movement, and whether to +// invert the direction: + +static int joystick_x_axis = 0; +static int joystick_x_invert = 0; + +// Which joystick axis to use for vertical movement, and whether to +// invert the direction: + +static int joystick_y_axis = 1; +static int joystick_y_invert = 0; + +// Which joystick axis to use for strafing? + +static int joystick_strafe_axis = -1; +static int joystick_strafe_invert = 0; + +// Which joystick axis to use for looking? + +static int joystick_look_axis = -1; +static int joystick_look_invert = 0; + +// Configurable dead zone for each axis, specified as a percentage of the axis +// max value. +static int joystick_x_dead_zone = 33; +static int joystick_y_dead_zone = 33; +static int joystick_strafe_dead_zone = 33; +static int joystick_look_dead_zone = 33; + +int use_analog = 0; + +int joystick_turn_sensitivity = 10; +int joystick_move_sensitivity = 10; +int joystick_look_sensitivity = 10; + +// Virtual to physical button joystick button mapping. By default this +// is a straight mapping. +static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +}; + +void I_ShutdownGamepad(void) +{ + if (gamepad != NULL) + { + SDL_GameControllerClose(gamepad); + gamepad = NULL; + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + } +} + +static int FindFirstGamepad(void) +{ + int i; + int gamepadindex = -1; + + for (i = 0; i < SDL_NumJoysticks(); ++i) + { + if (SDL_IsGameController(i)) + { + gamepadindex = i; + break; + } + } + + return gamepadindex; +} + +static int FindSpecificGamepad(SDL_JoystickGUID guid) +{ + SDL_JoystickGUID dev_guid; + int i; + int gamepadindex = -1; + + for (i = 0; i < SDL_NumJoysticks(); ++i) + { + dev_guid = SDL_JoystickGetDeviceGUID(i); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + gamepadindex = i; + break; + } + } + + return gamepadindex; +} + +static int DeviceIndexGamepad(void) +{ + SDL_JoystickGUID guid, dev_guid; + int index = -1; + + if (strcmp(joystick_guid, "")) + { + guid = SDL_JoystickGetGUIDFromString(joystick_guid); + + // First, look for the gamepad at the previously-used index. + if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) + { + dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + return joystick_index; + } + } + + // Maybe the index has moved? + index = FindSpecificGamepad(guid); + } + + // If the previous gamepad isn't present, see if a different one is + // available. + if (index < 0) + { + index = FindFirstGamepad(); + } + + return index; +} + +void I_InitGamepad(void) +{ + SDL_JoystickGUID guid; + int index; + + if (!use_gamepad) + { + return; + } + + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) + { + return; + } + + index = DeviceIndexGamepad(); + + if (index < 0) + { + printf("I_InitGamepad: No gamepad found.\n"); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + return; + } + + gamepad = SDL_GameControllerOpen(index); + + if (gamepad == NULL) + { + printf("I_InitGamepad: Failed to open gamepad: %s\n", SDL_GetError()); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + return; + } + + joystick_index = index; + gamepad_type = SDL_GameControllerTypeForIndex(index); + + if (strcmp(joystick_guid, "")) + { + joystick_guid = malloc(GUID_STRING_BUF_SIZE); + } + + guid = SDL_JoystickGetDeviceGUID(joystick_index); + SDL_JoystickGetGUIDString(guid, joystick_guid, GUID_STRING_BUF_SIZE); + + // GameController events do not fire if Joystick events are disabled. + SDL_JoystickEventState(SDL_ENABLE); + SDL_GameControllerEventState(SDL_ENABLE); + + printf("I_InitGamepad: %s\n", SDL_GameControllerName(gamepad)); + I_AtExit(I_ShutdownGamepad, true); +} + +static int GetTriggerStateGamepad(SDL_GameControllerAxis trigger) +{ + return (SDL_GameControllerGetAxis(gamepad, trigger) > TRIGGER_THRESHOLD); +} + +// Get the state of the given virtual button. + +static int ReadButtonStateGamepad(int vbutton) +{ + int physbutton, state; + + // Map from virtual button to physical (SDL) button. + if (vbutton < NUM_VIRTUAL_BUTTONS) + { + physbutton = joystick_physical_buttons[vbutton]; + } + else + { + physbutton = vbutton; + } + + switch (physbutton) + { + case GAMEPAD_BUTTON_TRIGGERLEFT: + state = GetTriggerStateGamepad(SDL_CONTROLLER_AXIS_TRIGGERLEFT); + break; + + case GAMEPAD_BUTTON_TRIGGERRIGHT: + state = GetTriggerStateGamepad(SDL_CONTROLLER_AXIS_TRIGGERRIGHT); + break; + + default: + state = SDL_GameControllerGetButton(gamepad, physbutton); + break; + } + + return state; +} + +// Get a bitmask of all currently-pressed buttons + +static int GetButtonsStateGamepad(void) +{ + int i; + int result = 0; + + for (i = 0; i < MAX_VIRTUAL_BUTTONS; ++i) + { + if (ReadButtonStateGamepad(i)) + { + result |= 1u << i; + } + } + + return result; +} + +// Read the state of an axis, inverting if necessary. + +static int GetAxisStateGamepad(const int *axis_values, int axis, int invert, + int dead_zone) +{ + int result; + + // Axis -1 means disabled. + + if (axis < 0) + { + return 0; + } + + // Dead zone is expressed as percentage of axis max value + dead_zone = 32768 * dead_zone / 100; + + result = axis_values[axis]; + + if (result < dead_zone && result > -dead_zone) + { + return 0; + } + + if (invert) + { + result = -result; + } + + result *= FRACUNIT / 32768; // Want FXP number between -1 and 1 + + return result; +} + +#define DIRECTION_DEADZONE (50 * 32768 / 100) + +static int GetDirectionalInputGamepad(const int *axis_values) +{ + int value; + int dpad = JOY_DIR_NONE; + int leftstick = JOY_DIR_NONE; + int rightstick = JOY_DIR_NONE; + + // Dpad. + if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_UP)) + { + dpad |= JOY_DIR_UP; + } + + if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) + { + dpad |= JOY_DIR_DOWN; + } + + if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) + { + dpad |= JOY_DIR_LEFT; + } + + if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) + { + dpad |= JOY_DIR_RIGHT; + } + + // Left stick. + value = axis_values[SDL_CONTROLLER_AXIS_LEFTY]; + + if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) + { + if (value > 0) + { + leftstick |= JOY_DIR_DOWN; + } + else + { + leftstick |= JOY_DIR_UP; + } + } + + value = axis_values[SDL_CONTROLLER_AXIS_LEFTX]; + + if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) + { + if (value > 0) + { + leftstick |= JOY_DIR_RIGHT; + } + else + { + leftstick |= JOY_DIR_LEFT; + } + } + + // Right stick. + value = axis_values[SDL_CONTROLLER_AXIS_RIGHTX]; + + if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) + { + if (value > 0) + { + rightstick |= JOY_DIR_RIGHT; + } + else + { + rightstick |= JOY_DIR_LEFT; + } + } + + value = axis_values[SDL_CONTROLLER_AXIS_RIGHTY]; + + if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) + { + if (value > 0) + { + rightstick |= JOY_DIR_DOWN; + } + else + { + rightstick |= JOY_DIR_UP; + } + } + + return ((dpad << DPAD_SHIFT) | (leftstick << LSTICK_SHIFT) | + (rightstick << RSTICK_SHIFT)); +} + +void I_UpdateGamepad(void) +{ + if (gamepad != NULL) + { + event_t ev; + int axis_values[SDL_CONTROLLER_AXIS_MAX]; + + axis_values[SDL_CONTROLLER_AXIS_LEFTX] = + SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_LEFTX); + + axis_values[SDL_CONTROLLER_AXIS_LEFTY] = + SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_LEFTY); + + axis_values[SDL_CONTROLLER_AXIS_RIGHTX] = + SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTX); + + axis_values[SDL_CONTROLLER_AXIS_RIGHTY] = + SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTY); + + ev.type = ev_joystick; + ev.data1 = GetButtonsStateGamepad(); + ev.data2 = GetAxisStateGamepad(axis_values, joystick_x_axis, + joystick_x_invert, joystick_x_dead_zone); + ev.data3 = GetAxisStateGamepad(axis_values, joystick_y_axis, + joystick_y_invert, joystick_y_dead_zone); + ev.data4 = GetAxisStateGamepad(axis_values, joystick_strafe_axis, + joystick_strafe_invert, + joystick_strafe_dead_zone); + ev.data5 = GetAxisStateGamepad(axis_values, joystick_look_axis, + joystick_look_invert, + joystick_look_dead_zone); + ev.data6 = GetDirectionalInputGamepad(axis_values); + + D_PostEvent(&ev); + } +} + +void I_ShutdownJoystick(void) +{ + if (joystick != NULL) + { + SDL_JoystickClose(joystick); + joystick = NULL; + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } +} + +static boolean IsValidAxis(int axis) +{ + int num_axes; + + if (axis < 0) + { + return true; + } + + if (IS_BUTTON_AXIS(axis)) + { + return true; + } + + if (IS_HAT_AXIS(axis)) + { + return HAT_AXIS_HAT(axis) < SDL_JoystickNumHats(joystick); + } + + num_axes = SDL_JoystickNumAxes(joystick); + + return axis < num_axes; +} + +static int DeviceIndex(void) +{ + SDL_JoystickGUID guid, dev_guid; + int i; + + guid = SDL_JoystickGetGUIDFromString(joystick_guid); + + // GUID identifies a class of device rather than a specific device. + // Check if joystick_index has the expected GUID, as this can act + // as a tie-breaker in case there are multiple identical devices. + if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) + { + dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + return joystick_index; + } + } + + // Check all devices to look for one with the expected GUID. + for (i = 0; i < SDL_NumJoysticks(); ++i) + { + dev_guid = SDL_JoystickGetDeviceGUID(i); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + printf("I_InitJoystick: Joystick moved to index %d.\n", i); + return i; + } + } + + // No joystick found with the expected GUID. + return -1; +} + +void I_InitJoystick(void) +{ + int index; + + if (!usejoystick || !strcmp(joystick_guid, "")) + { + return; + } + + if (use_gamepad) + { + I_InitGamepad(); + return; + } + + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) + { + return; + } + + index = DeviceIndex(); + + if (index < 0) + { + printf("I_InitJoystick: Couldn't find joystick with GUID \"%s\": " + "device not found or not connected?\n", + joystick_guid); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + return; + } + + // Open the joystick + + joystick = SDL_JoystickOpen(index); + + if (joystick == NULL) + { + printf("I_InitJoystick: Failed to open joystick #%i: %s\n", index, + SDL_GetError()); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + return; + } + + if (!IsValidAxis(joystick_x_axis) + || !IsValidAxis(joystick_y_axis) + || !IsValidAxis(joystick_strafe_axis) + || !IsValidAxis(joystick_look_axis)) + { + printf("I_InitJoystick: Invalid joystick axis for configured joystick " + "(run joystick setup again)\n"); + + SDL_JoystickClose(joystick); + joystick = NULL; + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } + + SDL_JoystickEventState(SDL_ENABLE); + + // Initialized okay! + + printf("I_InitJoystick: %s\n", SDL_JoystickName(joystick)); + + I_AtExit(I_ShutdownJoystick, true); +} + +static boolean IsAxisButton(int physbutton) +{ + if (IS_BUTTON_AXIS(joystick_x_axis)) + { + if (physbutton == BUTTON_AXIS_NEG(joystick_x_axis) + || physbutton == BUTTON_AXIS_POS(joystick_x_axis)) + { + return true; + } + } + if (IS_BUTTON_AXIS(joystick_y_axis)) + { + if (physbutton == BUTTON_AXIS_NEG(joystick_y_axis) + || physbutton == BUTTON_AXIS_POS(joystick_y_axis)) + { + return true; + } + } + if (IS_BUTTON_AXIS(joystick_strafe_axis)) + { + if (physbutton == BUTTON_AXIS_NEG(joystick_strafe_axis) + || physbutton == BUTTON_AXIS_POS(joystick_strafe_axis)) + { + return true; + } + } + if (IS_BUTTON_AXIS(joystick_look_axis)) + { + if (physbutton == BUTTON_AXIS_NEG(joystick_look_axis) + || physbutton == BUTTON_AXIS_POS(joystick_look_axis)) + { + return true; + } + } + + return false; +} + +// Get the state of the given virtual button. + +static int ReadButtonState(int vbutton) +{ + int physbutton; + + // Map from virtual button to physical (SDL) button. + if (vbutton < NUM_VIRTUAL_BUTTONS) + { + physbutton = joystick_physical_buttons[vbutton]; + } + else + { + physbutton = vbutton; + } + + // Never read axis buttons as buttons. + if (IsAxisButton(physbutton)) + { + return 0; + } + + return SDL_JoystickGetButton(joystick, physbutton); +} + +// Get a bitmask of all currently-pressed buttons + +static int GetButtonsState(void) +{ + int i; + int result = 0; + + for (i = 0; i < MAX_VIRTUAL_BUTTONS; ++i) + { + if (ReadButtonState(i)) + { + result |= 1 << i; + } + } + + return result; +} + +// Read the state of an axis, inverting if necessary. + +static int GetAxisState(int axis, int invert, int dead_zone) +{ + int result; + + // Axis -1 means disabled. + + if (axis < 0) + { + return 0; + } + + // Is this a button axis, or a hat axis? + // If so, we need to handle it specially. + + result = 0; + + if (IS_BUTTON_AXIS(axis)) + { + if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_NEG(axis))) + { + result -= 32767; + } + if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_POS(axis))) + { + result += 32767; + } + } + else if (IS_HAT_AXIS(axis)) + { + int direction = HAT_AXIS_DIRECTION(axis); + int hatval = SDL_JoystickGetHat(joystick, HAT_AXIS_HAT(axis)); + + if (direction == HAT_AXIS_HORIZONTAL) + { + if ((hatval & SDL_HAT_LEFT) != 0) + { + result -= 32767; + } + else if ((hatval & SDL_HAT_RIGHT) != 0) + { + result += 32767; + } + } + else if (direction == HAT_AXIS_VERTICAL) + { + if ((hatval & SDL_HAT_UP) != 0) + { + result -= 32767; + } + else if ((hatval & SDL_HAT_DOWN) != 0) + { + result += 32767; + } + } + } + else + { + result = SDL_JoystickGetAxis(joystick, axis); + + // Dead zone is expressed as percentage of axis max value + dead_zone = 32768 * dead_zone / 100; + + if (result < dead_zone && result > -dead_zone) + { + result = 0; + } + } + + if (invert) + { + result = -result; + } + + result *= FRACUNIT / 32768; // Want FXP number between -1 and 1 + + return result; +} + +static int GetDirectionalInput(int x, int y) +{ + int retval = JOY_DIR_NONE; + + if (x > 0) + { + retval |= JOY_DIR_RIGHT; + } + else if (x < 0) + { + retval |= JOY_DIR_LEFT; + } + + if (y > 0) + { + retval |= JOY_DIR_DOWN; + } + else if (y < 0) + { + retval |= JOY_DIR_UP; + } + + return (retval << DPAD_SHIFT); +} + +void I_UpdateJoystick(void) +{ + if (use_gamepad) + { + I_UpdateGamepad(); + return; + } + + if (joystick != NULL) + { + event_t ev; + + ev.type = ev_joystick; + ev.data1 = GetButtonsState(); + ev.data2 = GetAxisState(joystick_x_axis, joystick_x_invert, + joystick_x_dead_zone); + ev.data3 = GetAxisState(joystick_y_axis, joystick_y_invert, + joystick_y_dead_zone); + ev.data4 = GetAxisState(joystick_strafe_axis, joystick_strafe_invert, + joystick_strafe_dead_zone); + ev.data5 = GetAxisState(joystick_look_axis, joystick_look_invert, + joystick_look_dead_zone); + ev.data6 = GetDirectionalInput(ev.data2, ev.data3); + D_PostEvent(&ev); + } +} + +void I_BindJoystickVariables(void) +{ + int i; + + M_BindIntVariable("use_joystick", &usejoystick); + M_BindIntVariable("use_gamepad", &use_gamepad); + M_BindIntVariable("gamepad_type", &gamepad_type); + M_BindStringVariable("joystick_guid", &joystick_guid); + M_BindIntVariable("joystick_index", &joystick_index); + M_BindIntVariable("joystick_x_axis", &joystick_x_axis); + M_BindIntVariable("joystick_y_axis", &joystick_y_axis); + M_BindIntVariable("joystick_strafe_axis", &joystick_strafe_axis); + M_BindIntVariable("joystick_x_invert", &joystick_x_invert); + M_BindIntVariable("joystick_y_invert", &joystick_y_invert); + M_BindIntVariable("joystick_strafe_invert",&joystick_strafe_invert); + M_BindIntVariable("joystick_look_axis", &joystick_look_axis); + M_BindIntVariable("joystick_look_invert", &joystick_look_invert); + M_BindIntVariable("joystick_x_dead_zone", &joystick_x_dead_zone); + M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone); + M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone); + M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone); + M_BindIntVariable("use_analog", &use_analog); + M_BindIntVariable("joystick_turn_sensitivity", &joystick_turn_sensitivity); + M_BindIntVariable("joystick_move_sensitivity", &joystick_move_sensitivity); + M_BindIntVariable("joystick_look_sensitivity", &joystick_look_sensitivity); + + for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) + { + char name[32]; + M_snprintf(name, sizeof(name), "joystick_physical_button%i", i); + M_BindIntVariable(name, &joystick_physical_buttons[i]); + } +} + diff --git a/games/NXDoom/src/i_joystick.h b/games/NXDoom/src/i_joystick.h new file mode 100644 index 00000000000..15c8daa300e --- /dev/null +++ b/games/NXDoom/src/i_joystick.h @@ -0,0 +1,115 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System-specific joystick interface. +// + + +#ifndef __I_JOYSTICK__ +#define __I_JOYSTICK__ + +#include "SDL_gamecontroller.h" + +// Number of "virtual" joystick buttons defined in configuration files. +// This needs to be at least as large as the number of different key +// bindings supported by the higher-level game code (joyb* variables). +#define NUM_VIRTUAL_BUTTONS 17 + +// Max allowed number of virtual mappings. Chosen to be less than joybspeed +// autorun value. +#define MAX_VIRTUAL_BUTTONS 20 + +// If this bit is set in a configuration file axis value, the axis is +// not actually a joystick axis, but instead is a "button axis". This +// means that instead of reading an SDL joystick axis, we read the +// state of two buttons to get the axis value. This is needed for eg. +// the PS3 SIXAXIS controller, where the D-pad buttons register as +// buttons, not as two axes. +#define BUTTON_AXIS 0x10000 + +// Query whether a given axis value describes a button axis. +#define IS_BUTTON_AXIS(axis) ((axis) >= 0 && ((axis) & BUTTON_AXIS) != 0) + +// Get the individual buttons from a button axis value. +#define BUTTON_AXIS_NEG(axis) ((axis) & 0xff) +#define BUTTON_AXIS_POS(axis) (((axis) >> 8) & 0xff) + +// Create a button axis value from two button values. +#define CREATE_BUTTON_AXIS(neg, pos) (BUTTON_AXIS | (neg) | ((pos) << 8)) + +// If this bit is set in an axis value, the axis is not actually a +// joystick axis, but is a "hat" axis. This means that we read (one of) +// the hats on the joystick. +#define HAT_AXIS 0x20000 + +#define IS_HAT_AXIS(axis) ((axis) >= 0 && ((axis) & HAT_AXIS) != 0) + +// Get the hat number from a hat axis value. +#define HAT_AXIS_HAT(axis) ((axis) & 0xff) +// Which axis of the hat? (horizonal or vertical) +#define HAT_AXIS_DIRECTION(axis) (((axis) >> 8) & 0xff) + +#define CREATE_HAT_AXIS(hat, direction) \ + (HAT_AXIS | (hat) | ((direction) << 8)) + +#define HAT_AXIS_HORIZONTAL 1 +#define HAT_AXIS_VERTICAL 2 + +// When a trigger reads greater than this, consider it to be pressed. 30 comes +// from XINPUT_GAMEPAD_TRIGGER_THRESHOLD in xinput.h, and is scaled here for +// the SDL_GameController trigger max value. +#define TRIGGER_THRESHOLD (30 * 32767 / 255) + +// To be used with SDL_JoystickGetGUIDString; see SDL_joystick.h +#define GUID_STRING_BUF_SIZE 33 + +// Helper macros for bitpacked directional data from gamepad inputs. +#define DPAD_SHIFT 0 +#define LSTICK_SHIFT 4 +#define RSTICK_SHIFT 8 +#define JOY_GET_DPAD(x) (((x) >> DPAD_SHIFT) & 0xf) +#define JOY_GET_LSTICK(x) (((x) >> LSTICK_SHIFT) & 0xf) +#define JOY_GET_RSTICK(x) (((x) >> RSTICK_SHIFT) & 0xf) + +// 4-way direction data for gamepad directional inputs. +enum +{ + JOY_DIR_NONE = 0x0, + JOY_DIR_UP = 0x1, + JOY_DIR_DOWN = 0x2, + JOY_DIR_LEFT = 0x4, + JOY_DIR_RIGHT = 0x8 +}; + +// Extend the SDL_GameControllerButton enum to include the triggers. +enum +{ + GAMEPAD_BUTTON_TRIGGERLEFT = SDL_CONTROLLER_BUTTON_MAX, + GAMEPAD_BUTTON_TRIGGERRIGHT, + GAMEPAD_BUTTON_MAX +}; + +extern int use_analog; +extern int joystick_turn_sensitivity; +extern int joystick_move_sensitivity; +extern int joystick_look_sensitivity; + +void I_InitJoystick(void); +void I_ShutdownJoystick(void); +void I_UpdateJoystick(void); + +void I_BindJoystickVariables(void); + +#endif /* #ifndef __I_JOYSTICK__ */ + diff --git a/games/NXDoom/src/i_main.c b/games/NXDoom/src/i_main.c new file mode 100644 index 00000000000..851f0e9d26f --- /dev/null +++ b/games/NXDoom/src/i_main.c @@ -0,0 +1,79 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Main program, simply calls D_DoomMain high level loop. +// + +#include "config.h" + +#include +#include +#include + +#include "SDL.h" + +#include "doomtype.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_misc.h" + + +// +// D_DoomMain() +// Not a globally visible function, just included for source reference, +// calls all startup code, parses command line options. +// + +void D_DoomMain (void); + +int main(int argc, char **argv) +{ + // save arguments + + myargc = argc; + myargv = malloc(argc * sizeof(char *)); + assert(myargv != NULL); + + for (int i = 0; i < argc; i++) + { + myargv[i] = M_StringDuplicate(argv[i]); + } + + //! + // Print the program version and exit. + // + if (M_ParmExists("-version") || M_ParmExists("--version")) { + puts(PACKAGE_STRING); + exit(0); + } + +#if defined(_WIN32) + // compose a proper command line from loose file paths passed as arguments + // to allow for loading WADs and DEHACKED patches by drag-and-drop + M_AddLooseFiles(); +#endif + + M_FindResponseFile(); + M_SetExeDir(); + + SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); + + // start doom + + D_DoomMain (); + + return 0; +} + diff --git a/games/NXDoom/src/i_musicpack.c b/games/NXDoom/src/i_musicpack.c new file mode 100644 index 00000000000..10a2d16481f --- /dev/null +++ b/games/NXDoom/src/i_musicpack.c @@ -0,0 +1,1496 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System interface for music. +// + + +#include +#include +#include +#include + +#include "SDL.h" + +#include "i_glob.h" + +#include "config.h" +#include "doomtype.h" +#include "memio.h" +#include "mus2mid.h" + +#include "deh_str.h" +#include "gusconf.h" +#include "i_sound.h" +#include "i_system.h" +#include "i_swap.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" +#include "sha1.h" +#include "w_wad.h" +#include "z_zone.h" + + +char *music_pack_path = ""; + + +#ifndef DISABLE_SDL2MIXER + +#include "SDL_mixer.h" + +#define MID_HEADER_MAGIC "MThd" +#define MUS_HEADER_MAGIC "MUS\x1a" + +// Starting with 2.6.0, SDL_mixer supports OGG and FLAC looping natively. +// TODO: Once SDL_mixer 2.6.0+ is a requirement, delete the old looping code. +#if !defined(USE_SDL_MIXER_LOOPING) +#if defined(SDL_MIXER_VERSION_ATLEAST) +#if SDL_MIXER_VERSION_ATLEAST(2, 6, 0) +#define USE_SDL_MIXER_LOOPING 1 +#else +#define USE_SDL_MIXER_LOOPING 0 +#endif // SDL_MIXER_VERSION_ATLEAST(2, 6, 0) +#else +#define USE_SDL_MIXER_LOOPING 0 +#endif // defined(SDL_MIXER_VERSION_ATLEAST) +#endif // !defined(USE_SDL_MIXER_LOOPING) + +#if !USE_SDL_MIXER_LOOPING +#define FLAC_HEADER "fLaC" +#define OGG_HEADER "OggS" + +// Looping Vorbis metadata tag names. These have been defined by ZDoom +// for specifying the start and end positions for looping music tracks +// in .ogg and .flac files. +// More information is here: http://zdoom.org/wiki/Audio_loop +#define LOOP_START_TAG "LOOP_START" +#define LOOP_END_TAG "LOOP_END" + +// FLAC metadata headers that we care about. +#define FLAC_STREAMINFO 0 +#define FLAC_VORBIS_COMMENT 4 + +// Ogg metadata headers that we care about. +#define OGG_ID_HEADER 1 +#define OGG_COMMENT_HEADER 3 +#endif // !USE_SDL_MIXER_LOOPING + +// Structure for music substitution. +// We store a mapping based on SHA1 checksum -> filename of substitute music +// file to play, so that substitution occurs based on content rather than +// lump name. This has some inherent advantages: +// * Music for Plutonia (reused from Doom 1) works automatically. +// * If a PWAD replaces music, the replacement music is used rather than +// the substitute music for the IWAD. +// * If a PWAD reuses music from an IWAD (even from a different game), we get +// the high quality version of the music automatically (neat!) + +typedef struct +{ + const char *hash_prefix; + const char *filename; +} subst_music_t; + +#if !USE_SDL_MIXER_LOOPING +// Structure containing parsed metadata read from a digital music track: +typedef struct +{ + boolean valid; + unsigned int samplerate_hz; + int start_time, end_time; +} file_metadata_t; +#endif // !USE_SDL_MIXER_LOOPING + +static subst_music_t *subst_music = NULL; +static unsigned int subst_music_len = 0; + +static boolean music_initialized = false; + +// If this is true, this module initialized SDL sound and has the +// responsibility to shut it down + +static boolean sdl_was_initialized = false; + +#if !USE_SDL_MIXER_LOOPING +// If true, we are playing a substitute digital track rather than in-WAD +// MIDI/MUS track, and file_metadata contains loop metadata. +static file_metadata_t file_metadata; + +// Position (in samples) that we have reached in the current track. +// This is updated by the TrackPositionCallback function. +static unsigned int current_track_pos; +#endif // !USE_SDL_MIXER_LOOPING + +// Currently playing music track. +static Mix_Music *current_track_music = NULL; + +// If true, the currently playing track is being played on loop. +static boolean current_track_loop; + +// Table of known hashes and filenames to look up for them. This allows +// users to drop in a set of files without having to also provide a +// configuration file. +static const subst_music_t known_filenames[] = { + // Doom 1 music files. + {"b2e05b4e8dff8d76f8f4", "d_inter.{ext}"}, + {"0c0acce45130bab935d2", "d_intro.{ext}"}, + {"fca4086939a68ae4ed84", "d_victor.{ext}"}, + {"5971e5e20554f47ca065", "d_intro.{ext}"}, + {"99767e32769229897f77", "d_e1m1.{ext}"}, + {"b5e7dfb4efe9e688bf2a", "d_e1m2.{ext}"}, + {"fda8fa73e4d30a6b961c", "d_e1m3.{ext}"}, + {"3805f9bf3f1702f7e7f5", "d_e1m4.{ext}"}, + {"f546ed823b234fe39165", "d_e1m5.{ext}"}, + {"4450811b5a6748cfd83e", "d_e1m6.{ext}"}, + {"73edb50d96b0ac03be34", "d_e1m7.{ext}"}, + {"47d711a6fd32f5047879", "d_e1m8.{ext}"}, + {"62c631c2fdaa5ecd9a8d", "d_e1m9.{ext}"}, + {"7702a6449585428e7185", "d_e2m1.{ext}"}, + {"1cb1810989cbfae2b29b", "d_e2m2.{ext}"}, + {"7d740f3c881a22945e47", "d_e2m4.{ext}"}, + {"ae9c3dc2f9aeea002327", "d_e2m6.{ext}"}, + {"b26aad3caa420e9a2c76", "d_e2m7.{ext}"}, + {"90f06251a2a90bfaefd4", "d_e2m8.{ext}"}, + {"b2fb439f23c08c8e2577", "d_e3m1.{ext}"}, + {"b6c07bb249526b864208", "d_e3m2.{ext}"}, + {"ce3587ee503ffe707b2d", "d_e3m3.{ext}"}, + {"d746ea2aa16b3237422c", "d_e3m8.{ext}"}, + {"3da3b1335560a92912e6", "d_bunny.{ext}"}, + + // Duplicates that don't have identical hashes: + {"4a5badc4f10a7d4ed021", "d_inter.{ext}"}, // E2M3 + {"36b14bf165b3fdd3958e", "d_e1m7.{ext}"}, // E3M5 + {"e77c3d42f2ea87f04607", "d_e1m6.{ext}"}, // E3M6 + {"3d85ec9c10b5ea465568", "d_e2m7.{ext}"}, // E3M7 + {"4d42e2ce1c1ff192500e", "d_e1m9.{ext}"}, // E3M9 + + // These tracks are reused in Alien Vendetta, but are MIDs: + {"a05e45f67e1b64733fe3", "d_e2m1.{ext}"}, // MAP02 + {"8024ae1616ddd97ce330", "d_e1m4.{ext}"}, // MAP03 + {"3af8d79ddba49edaf9eb", "d_victor.{ext}"}, // MAP05 + {"a55352c96c025b6bd08a", "d_inter.{ext}"}, // MAP07 + {"76d1fc25ab7b1b4a58d6", "d_e1m8.{ext}"}, // MAP11 + {"497777f0863eca7cea87", "d_e1m2.{ext}"}, // MAP12 + {"0228fd87f8762f112fb6", "d_e2m2.{ext}"}, // MAP13 + {"db94e8e1d7c02092eab5", "d_e1m6.{ext}"}, // MAP14 + {"5a8d7a307eebc952795c", "d_e2m7.{ext}"}, // MAP16 + {"1a36b692bf26d94a72cc", "d_e1m7.{ext}"}, // MAP23 + {"37c6cefa351b06995152", "d_e1m5.{ext}"}, // MAP27 + {"36b97b87fe98348d44b6", "d_e2m6.{ext}"}, // MAP28 + + // Doom II music files. + {"79080e9681a2d7bec3fb", "d_runnin.{ext}"}, // MAP01,15 + {"868b3aae73c7b12e92c0", "d_stalks.{ext}"}, // MAP02,11,17 + {"19237754d2eb85f41d84", "d_countd.{ext}"}, // MAP03,21 + {"00abff3b61b25a6855d2", "d_betwee.{ext}"}, // MAP04 + {"954636c7ee09edf5d98f", "d_doom.{ext}"}, // MAP05,13 + {"8d32b2b7aa3b806474c1", "d_the_da.{ext}"}, // MAP06,12,24 + {"41efc3c84bb321af2b6b", "d_shawn.{ext}"}, // MAP07,19,29 + // Assuming single D_DDTBLU: http://doomwiki.org/wiki/Doom_II_music#Trivia + {"51c0872fec9f43259318", "d_ddtblu.{ext}"}, // MAP08 + {"acb7ad85494d18235df8", "d_ddtblu.{ext}"}, // MAP14,22 + {"4b7ceccbf47e78e2fa0b", "d_in_cit.{ext}"}, // MAP09 + {"1d1f4a9edba174584e11", "d_dead.{ext}"}, // MAP10,16 + {"1736c81aac77f9bffd3d", "d_romero.{ext}"}, // MAP18,27 + {"a55d400570ad255a576b", "d_messag.{ext}"}, // MAP20,26 + {"29d30c3fbd712016f2e5", "d_ampie.{ext}"}, // MAP23 + {"bcfe9786afdcfb704afa", "d_adrian.{ext}"}, // MAP25 + {"e05c10389e71836834ae", "d_tense.{ext}"}, // MAP28 + {"b779022b1d0f0010b8f0", "d_openin.{ext}"}, // MAP30 + {"a9a5f7b0ab3be0f4fc24", "d_evil.{ext}"}, // MAP31 + {"4503d155aafec0296689", "d_ultima.{ext}"}, // MAP32 + {"56f2363f01df38908c77", "d_dm2ttl.{ext}"}, + {"71e58baf9e9dea4dd24a", "d_dm2int.{ext}"}, + {"e632318629869811f7dc", "d_read_m.{ext}"}, + + // Duplicate filenames: the above filenames are the "canonical" files + // for the given SHA1 hashes, but we can also look for these filenames + // corresponding to the duplicated music tracks too. + {"868b3aae73c7b12e92c0", "d_stlks2.{ext}"}, + {"868b3aae73c7b12e92c0", "d_stlks3.{ext}"}, + {"8d32b2b7aa3b806474c1", "d_theda2.{ext}"}, + {"8d32b2b7aa3b806474c1", "d_theda3.{ext}"}, + {"954636c7ee09edf5d98f", "d_doom2.{ext}"}, + {"acb7ad85494d18235df8", "d_ddtbl2.{ext}"}, + {"acb7ad85494d18235df8", "d_ddtbl3.{ext}"}, + {"79080e9681a2d7bec3fb", "d_runni2.{ext}"}, + {"1d1f4a9edba174584e11", "d_dead2.{ext}"}, + {"41efc3c84bb321af2b6b", "d_shawn2.{ext}"}, + {"41efc3c84bb321af2b6b", "d_shawn3.{ext}"}, + {"19237754d2eb85f41d84", "d_count2.{ext}"}, + {"a55d400570ad255a576b", "d_messg2.{ext}"}, + {"1736c81aac77f9bffd3d", "d_romer2.{ext}"}, + + // These tracks are reused in Alien Vendetta, but are MIDs: + {"9433604c098b7b1119a4", "d_in_cit.{ext}"}, // MAP26 + + // Heretic tracks. + {"12818ca0d3c957e7d57e", "mus_titl.{ext}"}, + {"5cb988538ce1b1857349", "mus_intr.{ext}"}, + {"6f126abe35a78b61b930", "mus_cptd.{ext}"}, + {"62557250f0427c067dc9", "mus_e1m1.{ext}"}, + {"1e8d5fd814490b9ae166", "mus_e1m2.{ext}"}, + {"f0f31e8834e85035d434", "mus_e1m3.{ext}"}, + {"054d6997405cc5a32b46", "mus_e1m4.{ext}"}, + {"31950ab062cc1e5ca49d", "mus_e1m5.{ext}"}, + {"7389024fbab0dff47211", "mus_e1m6.{ext}"}, + {"f2aa312dddd0a294a095", "mus_e1m7.{ext}"}, + {"cd6856731d1ae1f3aa4e", "mus_e1m8.{ext}"}, + {"d7fe793f266733d92e61", "mus_e1m9.{ext}"}, + {"933545b48fad8c66f042", "mus_e2m1.{ext}"}, + {"bf88ecd4ae1621222592", "mus_e2m2.{ext}"}, + {"4f619f87a828c2ca4801", "mus_e2m3.{ext}"}, + {"13033a83c49424b2f2ab", "mus_e2m4.{ext}"}, + {"b3851f9351ae411d9de3", "mus_e2m6.{ext}"}, + {"82539791159fbbc02a23", "mus_e2m7.{ext}"}, + {"fd9e53a49cfa62c463a0", "mus_e2m8.{ext}"}, + {"29503959324d2ca67958", "mus_e2m9.{ext}"}, + {"3aa632257c5be375b97b", "mus_e3m2.{ext}"}, + {"69ba0dce7913d53b67a8", "mus_e3m3.{ext}"}, + + // These Heretic tracks are reused in Alien Vendetta, but are MIDs: + {"51344131e8d260753ce7", "mus_e2m3.{ext}"}, // MAP15 + {"78b570b2397570440aff", "mus_e1m1.{ext}"}, // MAP19 + {"ee21ba9fad4de3dfaef0", "mus_e1m4.{ext}"}, // MAP29 + {"d2bb643a60696ccbca03", "mus_e1m9.{ext}"}, // MAP32 + + // Hexen tracks: + {"fbf55fc1ee26bd01266b", "winnowr.{ext}"}, + {"71776e2da2b7ba607d81", "jachr.{ext}"}, + {"c5c8630608b8132b33cd", "simonr.{ext}"}, + {"43683b3f55a031de88d4", "wutzitr.{ext}"}, + {"a6062883f29436ef73db", "falconr.{ext}"}, + {"512cb6cc9b558d5f0fef", "levelr.{ext}"}, + {"d31226ae75fce6a24208", "chartr.{ext}"}, + {"bf1f1e561bbdba4e699f", "swampr.{ext}"}, + {"b303193f756ca0e2de0f", "deepr.{ext}"}, + {"f0635f0386d883b00186", "fubasr.{ext}"}, + {"18f2a01f83df6e3abedc", "grover.{ext}"}, + {"b2527eb0522f08b2cf5f", "fortr.{ext}"}, + {"343addba8ba53a20a160", "foojar.{ext}"}, + {"c13109045b06b5a63386", "sixater.{ext}"}, + {"693525aaf69eac5429ab", "wobabyr.{ext}"}, + {"8f884223811c2bb8311d", "cryptr.{ext}"}, + {"de540e6826e62b32c01c", "fantar.{ext}"}, + {"efdff548df918934f71f", "blechr.{ext}"}, + {"de91f150f6a127e72e35", "voidr.{ext}"}, + {"e0497fe27289fe18515b", "chap_1r.{ext}"}, + {"f2ef1abdc3f672a3519a", "chap_2r.{ext}"}, + {"78cd9882f61cc441bef4", "chap_3r.{ext}"}, + {"97b2b575d9d096c1f89f", "chap_4r.{ext}"}, + {"ad0197a0f6c52ac30915", "chippyr.{ext}"}, + {"30506c62e9f0989ffe09", "percr.{ext}"}, + {"3542803beaa43bf1de1a", "secretr.{ext}"}, + {"81067721f40c611d09fb", "bonesr.{ext}"}, + {"4822af2e1a2eb7faf660", "octor.{ext}"}, + {"26bb3cec902ed8008fc2", "rithmr.{ext}"}, + {"94ab641c7aa93caac77a", "stalkr.{ext}"}, + {"d0a3f337c54b0703b4d3", "borkr.{ext}"}, + {"79e7781ec7eb9b9434b5", "crucibr.{ext}"}, + {"c2786e5581a7f8801969", "hexen.{ext}"}, + {"97fae9a084c0efda5151", "hub.{ext}"}, + {"c5da52d5c2ec4803ef8f", "hall.{ext}"}, + {"1e71bc0e2feafb06214e", "orb.{ext}"}, + {"bc9dcfa6632e847e03af", "chess.{ext}"}, + + // Hexen CD tracks: alternate filenames for a ripped copy of + // the CD soundtrack. + {"71776e2da2b7ba607d81", "hexen02.{ext}"}, // level 2 (jachr) + {"efdff548df918934f71f", "hexen03.{ext}"}, // level 26 (blechr) + {"c2786e5581a7f8801969", "hexen04.{ext}"}, // (hexen) + {"1e71bc0e2feafb06214e", "hexen05.{ext}"}, // (orb) + {"f0635f0386d883b00186", "hexen06.{ext}"}, // level 10 (fubasr) + {"bc9dcfa6632e847e03af", "hexen07.{ext}"}, // (chess) + {"8f884223811c2bb8311d", "hexen08.{ext}"}, // level 24 (cryptr) + {"a6062883f29436ef73db", "hexen09.{ext}"}, // level 5 (falconr) + {"4822af2e1a2eb7faf660", "hexen10.{ext}"}, // level 36 (octor) + {"26bb3cec902ed8008fc2", "hexen11.{ext}"}, // level 37 (rithmr) + {"c13109045b06b5a63386", "hexen12.{ext}"}, // level 22 (sixater) + {"fbf55fc1ee26bd01266b", "hexen13.{ext}"}, // level 1 (winnowr) + {"bf1f1e561bbdba4e699f", "hexen14.{ext}"}, // level 8 (swampr) + {"43683b3f55a031de88d4", "hexen15.{ext}"}, // level 4 (wutzitr) + {"81067721f40c611d09fb", "hexen16.{ext}"}, // level 35 (bonesr) + {"e0497fe27289fe18515b", "hexen17.{ext}"}, // level 28 (chap_1r) + {"97b2b575d9d096c1f89f", "hexen18.{ext}"}, // level 31 (chap_4r) + {"de540e6826e62b32c01c", "hexen19.{ext}"}, // level 25 (fantar) + {"343addba8ba53a20a160", "hexen20.{ext}"}, // level 21 (foojar) + {"512cb6cc9b558d5f0fef", "hexen21.{ext}"}, // level 6 (levelr) + {"c5c8630608b8132b33cd", "hexen22.{ext}"}, // level 3 (simonr) + + // Strife: + {"8ac2b2b47707f0fdf8f6", "d_logo.{ext}"}, // Title + {"62e1c58054a1f1bc39b2", "d_action.{ext}"}, // 1,15,28 + {"12fa000f3fa1edac5c4f", "d_tavern.{ext}"}, // 2 + {"695e56ab3251792d20e5", "d_danger.{ext}"}, // 3,11 + {"96fe30e8712217b60dd7", "d_fast.{ext}"}, // 4 + {"61345598a3de04aad508", "d_darker.{ext}"}, // 6,14 + {"52353e9a435b7b1cb268", "d_strike.{ext}"}, // 7,19 + {"061164504907bffc9c22", "d_slide.{ext}"}, // 8,18,22 + {"3dbb4b703ce69aafcdd5", "d_tribal.{ext}"}, // 9 + {"393773688eba050c3548", "d_march.{ext}"}, // 10 + {"3cba3c627de065a667dd", "d_mood.{ext}"}, // 12 + {"b1f65a333e5c70255784", "d_castle.{ext}"}, // 13 + {"e1455a83a04c9ac4a09f", "d_fight.{ext}"}, // 16,31 + {"17f822b7374b1f069b89", "d_spense.{ext}"}, // 17 + {"e66c5a1a7d05f021f4ae", "d_dark.{ext}"}, // 20 + {"1c92bd0625026af30dad", "d_tech.{ext}"}, // 21,27 + {"7ae280713d078de7933a", "d_drone.{ext}"}, // 23,30 + {"4a664afd0d7eae79c97a", "d_panthr.{ext}"}, // 24 + {"4a7d62beeac5601ccf21", "d_sad.{ext}"}, // 25 + {"e60e109779400f2855d7", "d_instry.{ext}"}, // 26,29 + {"b7d36878faeb291d6df5", "d_happy.{ext}"}, // Better ending + {"ff4a342c8c5ec51b06c3", "d_end.{ext}"}, // Worse ending + // This conflicts with Doom's d_intro: + //{"ec8fa484c4e85adbf700", "d_intro.{ext}"}, // 5 +}; + +#if !USE_SDL_MIXER_LOOPING +// Given a time string (for LOOP_START/LOOP_END), parse it and return +// the time (in # samples since start of track) it represents. +static unsigned int ParseVorbisTime(unsigned int samplerate_hz, char *value) +{ + char *num_start, *p; + unsigned int result = 0; + char c; + + if (strchr(value, ':') == NULL) + { + return atoi(value); + } + + result = 0; + num_start = value; + + for (p = value; *p != '\0'; ++p) + { + if (*p == '.' || *p == ':') + { + c = *p; *p = '\0'; + result = result * 60 + atoi(num_start); + num_start = p + 1; + *p = c; + } + + if (*p == '.') + { + return result * samplerate_hz + + (unsigned int) (atof(p) * samplerate_hz); + } + } + + return (result * 60 + atoi(num_start)) * samplerate_hz; +} + +// Given a vorbis comment string (eg. "LOOP_START=12345"), set fields +// in the metadata structure as appropriate. +static void ParseVorbisComment(file_metadata_t *metadata, char *comment) +{ + char *eq, *key, *value; + + eq = strchr(comment, '='); + + if (eq == NULL) + { + return; + } + + key = comment; + *eq = '\0'; + value = eq + 1; + + if (!strcmp(key, LOOP_START_TAG)) + { + metadata->start_time = ParseVorbisTime(metadata->samplerate_hz, value); + } + else if (!strcmp(key, LOOP_END_TAG)) + { + metadata->end_time = ParseVorbisTime(metadata->samplerate_hz, value); + } +} + +// Parse a vorbis comments structure, reading from the given file. +static void ParseVorbisComments(file_metadata_t *metadata, FILE *fs) +{ + uint32_t buf; + unsigned int num_comments, i, comment_len; + char *comment; + + // We must have read the sample rate already from an earlier header. + if (metadata->samplerate_hz == 0) + { + return; + } + + // Skip the starting part we don't care about. + if (fread(&buf, 4, 1, fs) < 1) + { + return; + } + if (fseek(fs, LONG(buf), SEEK_CUR) != 0) + { + return; + } + + // Read count field for number of comments. + if (fread(&buf, 4, 1, fs) < 1) + { + return; + } + num_comments = LONG(buf); + + // Read each individual comment. + for (i = 0; i < num_comments; ++i) + { + // Read length of comment. + if (fread(&buf, 4, 1, fs) < 1) + { + return; + } + + comment_len = LONG(buf); + + // Read actual comment data into string buffer. + comment = calloc(1, comment_len + 1); + if (comment == NULL + || fread(comment, 1, comment_len, fs) < comment_len) + { + free(comment); + break; + } + + // Parse comment string. + ParseVorbisComment(metadata, comment); + free(comment); + } +} + +static void ParseFlacStreaminfo(file_metadata_t *metadata, FILE *fs) +{ + byte buf[34]; + + // Read block data. + if (fread(buf, sizeof(buf), 1, fs) < 1) + { + return; + } + + // We only care about sample rate and song length. + metadata->samplerate_hz = (buf[10] << 12) | (buf[11] << 4) + | (buf[12] >> 4); + // Song length is actually a 36 bit field, but 32 bits should be + // enough for everybody. + //metadata->song_length = (buf[14] << 24) | (buf[15] << 16) + // | (buf[16] << 8) | buf[17]; +} + +static void ParseFlacFile(file_metadata_t *metadata, FILE *fs) +{ + byte header[4]; + unsigned int block_type; + size_t block_len; + boolean last_block; + + for (;;) + { + long pos = -1; + + // Read METADATA_BLOCK_HEADER: + if (fread(header, 4, 1, fs) < 1) + { + return; + } + + block_type = header[0] & ~0x80; + last_block = (header[0] & 0x80) != 0; + block_len = (header[1] << 16) | (header[2] << 8) | header[3]; + + pos = ftell(fs); + if (pos < 0) + { + return; + } + + if (block_type == FLAC_STREAMINFO) + { + ParseFlacStreaminfo(metadata, fs); + } + else if (block_type == FLAC_VORBIS_COMMENT) + { + ParseVorbisComments(metadata, fs); + } + + if (last_block) + { + break; + } + + // Seek to start of next block. + if (fseek(fs, pos + block_len, SEEK_SET) != 0) + { + return; + } + } +} + +static void ParseOggIdHeader(file_metadata_t *metadata, FILE *fs) +{ + byte buf[21]; + + if (fread(buf, sizeof(buf), 1, fs) < 1) + { + return; + } + + metadata->samplerate_hz = (buf[8] << 24) | (buf[7] << 16) + | (buf[6] << 8) | buf[5]; +} + +static void ParseOggFile(file_metadata_t *metadata, FILE *fs) +{ + byte buf[7]; + unsigned int offset; + + // Scan through the start of the file looking for headers. They + // begin '[byte]vorbis' where the byte value indicates header type. + memset(buf, 0, sizeof(buf)); + + for (offset = 0; offset < 100 * 1024; ++offset) + { + // buf[] is used as a sliding window. Each iteration, we + // move the buffer one byte to the left and read an extra + // byte onto the end. + memmove(buf, buf + 1, sizeof(buf) - 1); + + if (fread(&buf[6], 1, 1, fs) < 1) + { + return; + } + + if (!memcmp(buf + 1, "vorbis", 6)) + { + switch (buf[0]) + { + case OGG_ID_HEADER: + ParseOggIdHeader(metadata, fs); + break; + case OGG_COMMENT_HEADER: + ParseVorbisComments(metadata, fs); + break; + default: + break; + } + } + } +} + +static void ReadLoopPoints(const char *filename, file_metadata_t *metadata) +{ + FILE *fs; + char header[4]; + + metadata->valid = false; + metadata->samplerate_hz = 0; + metadata->start_time = 0; + metadata->end_time = -1; + + fs = M_fopen(filename, "rb"); + + if (fs == NULL) + { + return; + } + + // Check for a recognized file format; use the first four bytes + // of the file. + + if (fread(header, 4, 1, fs) < 1) + { + fclose(fs); + return; + } + + if (memcmp(header, FLAC_HEADER, 4) == 0) + { + ParseFlacFile(metadata, fs); + } + else if (memcmp(header, OGG_HEADER, 4) == 0) + { + ParseOggFile(metadata, fs); + } + + fclose(fs); + + // Only valid if at the very least we read the sample rate. + metadata->valid = metadata->samplerate_hz > 0; + + // If start and end time are both zero, ignore the loop tags. + // This is consistent with other source ports. + if (metadata->start_time == 0 && metadata->end_time == 0) + { + metadata->valid = false; + } +} +#endif // !USE_SDL_MIXER_LOOPING + +// Given a MUS lump, look up a substitute MUS file to play instead +// (or NULL to just use normal MIDI playback). + +static const char *GetSubstituteMusicFile(void *data, size_t data_len) +{ + sha1_context_t context; + sha1_digest_t hash; + const char *filename; + char hash_str[sizeof(sha1_digest_t) * 2 + 1]; + unsigned int i; + + // Don't bother doing a hash if we're never going to find anything. + if (subst_music_len == 0) + { + return NULL; + } + + SHA1_Init(&context); + SHA1_Update(&context, data, data_len); + SHA1_Final(hash, &context); + + // Build a string representation of the hash. + for (i = 0; i < sizeof(sha1_digest_t); ++i) + { + M_snprintf(hash_str + i * 2, sizeof(hash_str) - i * 2, + "%02x", hash[i]); + } + + // Look for a hash that matches. + // The substitute mapping list can (intentionally) contain multiple + // filename mappings for the same hash. This allows us to try + // different files and fall back if our first choice isn't found. + + filename = NULL; + + for (i = 0; i < subst_music_len; ++i) + { + if (M_StringStartsWith(hash_str, subst_music[i].hash_prefix)) + { + filename = subst_music[i].filename; + + // If the file exists, then use this file in preference to + // any fallbacks. But we always return a filename if it's + // in the list, even if it's just so we can print an error + // message to the user saying it doesn't exist. + if (M_FileExists(filename)) + { + break; + } + } + } + + return filename; +} + +static char *GetFullPath(const char *musicdir, const char *path) +{ + char *result; + char *systemized_path; + + // Starting with directory separator means we have an absolute path, + // so just return it. + if (path[0] == DIR_SEPARATOR) + { + return M_StringDuplicate(path); + } + +#ifdef _WIN32 + // d:\path\... + if (isalpha(path[0]) && path[1] == ':' && path[2] == DIR_SEPARATOR) + { + return M_StringDuplicate(path); + } +#endif + + // Paths in the substitute filenames can contain Unix-style / + // path separators, but we should convert this to the separator + // for the native platform. + systemized_path = M_StringReplace(path, "/", DIR_SEPARATOR_S); + + // Copy config filename and cut off the filename to just get the + // parent dir. + result = M_StringJoin(musicdir, systemized_path, NULL); + free(systemized_path); + + return result; +} + +// If filename ends with .{ext}, check if a .ogg, .flac or .mp3 exists with +// that name, returning it if found. If none exist, NULL is returned. If the +// filename doesn't end with .{ext} then it just acts as a wrapper around +// GetFullPath(). +static char *ExpandFileExtension(const char *musicdir, const char *filename) +{ + static const char *extns[] = {".flac", ".ogg", ".mp3"}; + char *replaced, *result; + int i; + + if (!M_StringEndsWith(filename, ".{ext}")) + { + return GetFullPath(musicdir, filename); + } + + for (i = 0; i < arrlen(extns); ++i) + { + replaced = M_StringReplace(filename, ".{ext}", extns[i]); + result = GetFullPath(musicdir, replaced); + free(replaced); + if (M_FileExists(result)) + { + return result; + } + free(result); + } + + return NULL; +} + +// Add a substitute music file to the lookup list. +static void AddSubstituteMusic(const char *musicdir, const char *hash_prefix, + const char *filename) +{ + subst_music_t *s; + char *path; + + path = ExpandFileExtension(musicdir, filename); + if (path == NULL) + { + return; + } + + ++subst_music_len; + subst_music = + I_Realloc(subst_music, sizeof(subst_music_t) * subst_music_len); + s = &subst_music[subst_music_len - 1]; + s->hash_prefix = hash_prefix; + s->filename = path; +} + +static const char *ReadHashPrefix(char *line) +{ + char *result; + char *p; + int i, len; + + for (p = line; *p != '\0' && !isspace(*p) && *p != '='; ++p) + { + if (!isxdigit(*p)) + { + return NULL; + } + } + + len = p - line; + if (len == 0 || len > sizeof(sha1_digest_t) * 2) + { + return NULL; + } + + result = malloc(len + 1); + if (result == NULL) + { + return NULL; + } + + for (i = 0; i < len; ++i) + { + result[i] = tolower(line[i]); + } + result[len] = '\0'; + + return result; +} + +// Parse a line from substitute music configuration file; returns error +// message or NULL for no error. + +static const char *ParseSubstituteLine(char *musicdir, char *line) +{ + const char *hash_prefix; + char *filename; + char *p; + + // Strip out comments if present. + p = strchr(line, '#'); + if (p != NULL) + { + while (p > line && isspace(*(p - 1))) + { + --p; + } + *p = '\0'; + } + + // Skip leading spaces. + for (p = line; *p != '\0' && isspace(*p); ++p); + + // Empty line? This includes comment lines now that comments have + // been stripped. + if (*p == '\0') + { + return NULL; + } + + hash_prefix = ReadHashPrefix(p); + if (hash_prefix == NULL) + { + return "Invalid hash prefix"; + } + + p += strlen(hash_prefix); + + // Skip spaces. + for (; *p != '\0' && isspace(*p); ++p); + + if (*p != '=') + { + return "Expected '='"; + } + + ++p; + + // Skip spaces. + for (; *p != '\0' && isspace(*p); ++p); + + filename = p; + + // We're now at the filename. Cut off trailing space characters. + while (strlen(p) > 0 && isspace(p[strlen(p) - 1])) + { + p[strlen(p) - 1] = '\0'; + } + + if (strlen(p) == 0) + { + return "No filename specified for music substitution"; + } + + // Expand full path and add to our database of substitutes. + AddSubstituteMusic(musicdir, hash_prefix, filename); + + return NULL; +} + +// Read a substitute music configuration file. + +static boolean ReadSubstituteConfig(char *musicdir, const char *filename) +{ + char *buffer; + char *line; + int linenum = 1; + + // This unnecessarily opens the file twice... + if (!M_FileExists(filename)) + { + return false; + } + + M_ReadFile(filename, (byte **) &buffer); + + line = buffer; + + while (line != NULL) + { + const char *error; + char *next; + + // find end of line + char *eol = strchr(line, '\n'); + if (eol != NULL) + { + // change the newline into NUL + *eol = '\0'; + next = eol + 1; + } + else + { + // end of buffer + next = NULL; + } + + error = ParseSubstituteLine(musicdir, line); + + if (error != NULL) + { + fprintf(stderr, "%s:%i: Error: %s\n", filename, linenum, error); + } + + ++linenum; + line = next; + } + + Z_Free(buffer); + + return true; +} + +// Find substitute configs and try to load them. + +static void LoadSubstituteConfigs(void) +{ + glob_t *glob; + char *musicdir; + const char *path; + unsigned int old_music_len; + unsigned int i; + + // We can configure the path to music packs using the music_pack_path + // configuration variable. Otherwise we use the current directory, or + // $configdir/music to look for .cfg files. + if (strcmp(music_pack_path, "") != 0) + { + musicdir = M_StringJoin(music_pack_path, DIR_SEPARATOR_S, NULL); + } + else if (!strcmp(configdir, exedir)) + { + musicdir = M_StringDuplicate(""); + } + else + { + musicdir = M_StringJoin(configdir, "music", DIR_SEPARATOR_S, NULL); + } + + // Load all music packs, by searching for .cfg files. + glob = I_StartGlob(musicdir, "*.cfg", GLOB_FLAG_SORTED|GLOB_FLAG_NOCASE); + for (;;) + { + path = I_NextGlob(glob); + if (path == NULL) + { + break; + } + ReadSubstituteConfig(musicdir, path); + } + I_EndGlob(glob); + + if (subst_music_len > 0) + { + printf("Loaded %u music substitutions from config files.\n", + subst_music_len); + } + + old_music_len = subst_music_len; + + // Add entries from known filenames list. We add this after those from the + // configuration files, so that the entries here can be overridden. + for (i = 0; i < arrlen(known_filenames); ++i) + { + AddSubstituteMusic(musicdir, known_filenames[i].hash_prefix, + known_filenames[i].filename); + } + + if (subst_music_len > old_music_len) + { + printf("Configured %u music substitutions based on filename.\n", + subst_music_len - old_music_len); + } + + free(musicdir); +} + +// Returns true if the given lump number is a music lump that should +// be included in substitute configs. +// Identifying music lumps by name is not feasible; some games (eg. +// Heretic, Hexen) don't have a common naming pattern for music lumps. + +static boolean IsMusicLump(int lumpnum) +{ + byte *data; + boolean result; + + if (W_LumpLength(lumpnum) < 4) + { + return false; + } + + data = W_CacheLumpNum(lumpnum, PU_STATIC); + + result = memcmp(data, MUS_HEADER_MAGIC, 4) == 0 + || memcmp(data, MID_HEADER_MAGIC, 4) == 0; + + W_ReleaseLumpNum(lumpnum); + + return result; +} + +// Dump an example config file containing checksums for all MIDI music +// found in the WAD directory. + +static void DumpSubstituteConfig(const char *filename) +{ + sha1_context_t context; + sha1_digest_t digest; + char name[9]; + byte *data; + FILE *fs; + unsigned int lumpnum; + size_t h; + + fs = M_fopen(filename, "w"); + + if (fs == NULL) + { + I_Error("Failed to open %s for writing", filename); + return; + } + + fprintf(fs, "# Example %s substitute MIDI file.\n\n", PACKAGE_NAME); + fprintf(fs, "# SHA1 hash = filename\n"); + + for (lumpnum = 0; lumpnum < numlumps; ++lumpnum) + { + strncpy(name, lumpinfo[lumpnum]->name, 8); + name[8] = '\0'; + + if (!IsMusicLump(lumpnum)) + { + continue; + } + + // Calculate hash. + data = W_CacheLumpNum(lumpnum, PU_STATIC); + SHA1_Init(&context); + SHA1_Update(&context, data, W_LumpLength(lumpnum)); + SHA1_Final(digest, &context); + W_ReleaseLumpNum(lumpnum); + + // Print line. + for (h = 0; h < sizeof(sha1_digest_t); ++h) + { + fprintf(fs, "%02x", digest[h]); + } + + fprintf(fs, " = %s.ogg\n", name); + } + + fprintf(fs, "\n"); + fclose(fs); + + printf("Substitute MIDI config file written to %s.\n", filename); + I_Quit(); +} + +// Shutdown music + +static void I_MP_ShutdownMusic(void) +{ + if (music_initialized) + { + Mix_HaltMusic(); + music_initialized = false; + + if (sdl_was_initialized) + { + Mix_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + sdl_was_initialized = false; + } + } +} + +static boolean SDLIsInitialized(void) +{ + int freq, channels; + Uint16 format; + + return Mix_QuerySpec(&freq, &format, &channels) != 0; +} + +#if !USE_SDL_MIXER_LOOPING +// Callback function that is invoked to track current track position. +void TrackPositionCallback(int chan, void *stream, int len, void *udata) +{ + // Position is doubled up twice: for 16-bit samples and for stereo. + current_track_pos += len / 4; +} +#endif // !USE_SDL_MIXER_LOOPING + +// Initialize music subsystem +static boolean I_MP_InitMusic(void) +{ + int i; + + //! + // @category obscure + // @arg + // + // Read all MIDI files from loaded WAD files, dump an example + // substitution music config file to the specified file, and quit. + // + i = M_CheckParmWithArgs("-dumpsubstconfig", 1); + + if (i > 0) + { + DumpSubstituteConfig(myargv[i + 1]); + } + + // If we're in GENMIDI mode, try to load sound packs. + LoadSubstituteConfigs(); + + // We can't initialize if we don't have any substitute files to work with. + // If so, don't bother with SDL initialization etc. + if (subst_music_len == 0) + { + return false; + } + + // If SDL_mixer is not initialized, we have to initialize it + // and have the responsibility to shut it down later on. + if (SDLIsInitialized()) + { + music_initialized = true; + } + else if (SDL_Init(SDL_INIT_AUDIO) < 0) + { + fprintf(stderr, "Unable to set up sound.\n"); + } + else if (Mix_OpenAudioDevice(snd_samplerate, AUDIO_S16SYS, 2, 1024, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) + { + fprintf(stderr, "Error initializing SDL_mixer: %s\n", + Mix_GetError()); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } + else + { + SDL_PauseAudio(0); + + sdl_was_initialized = true; + music_initialized = true; + } + + // Initialize SDL_Mixer for digital music playback + Mix_Init(MIX_INIT_FLAC | MIX_INIT_OGG | MIX_INIT_MP3); + +#if !USE_SDL_MIXER_LOOPING + // Register an effect function to track the music position. + Mix_RegisterEffect(MIX_CHANNEL_POST, TrackPositionCallback, NULL, NULL); +#endif // !USE_SDL_MIXER_LOOPING + + return music_initialized; +} + +// Set music volume (0 - 127) + +static void I_MP_SetMusicVolume(int volume) +{ + Mix_VolumeMusic((volume * MIX_MAX_VOLUME) / 127); +} + +// Start playing a mid + +static void I_MP_PlaySong(void *handle, boolean looping) +{ + int loops; + + if (!music_initialized) + { + return; + } + + if (handle == NULL) + { + return; + } + + current_track_music = (Mix_Music *) handle; + current_track_loop = looping; + + if (looping) + { + loops = -1; + } + else + { + loops = 1; + } + +#if !USE_SDL_MIXER_LOOPING + // Don't loop when playing substitute music, as we do it + // ourselves instead. + if (file_metadata.valid) + { + loops = 1; + SDL_LockAudio(); + current_track_pos = 0; // start of track + SDL_UnlockAudio(); + } +#endif // !USE_SDL_MIXER_LOOPING + + if (Mix_PlayMusic(current_track_music, loops) == -1) + { + fprintf(stderr, "I_MP_PlaySong: Error starting track: %s\n", + Mix_GetError()); + } +} + +static void I_MP_PauseSong(void) +{ + if (!music_initialized) + { + return; + } + + Mix_PauseMusic(); +} + +static void I_MP_ResumeSong(void) +{ + if (!music_initialized) + { + return; + } + + Mix_ResumeMusic(); +} + +static void I_MP_StopSong(void) +{ + if (!music_initialized) + { + return; + } + + Mix_HaltMusic(); + current_track_music = NULL; +} + +static void I_MP_UnRegisterSong(void *handle) +{ + Mix_Music *music = (Mix_Music *) handle; + + if (!music_initialized) + { + return; + } + + if (handle == NULL) + { + return; + } + + Mix_FreeMusic(music); +} + +static void *I_MP_RegisterSong(void *data, int len) +{ + const char *filename; + Mix_Music *music; + + if (!music_initialized) + { + return NULL; + } + + // See if we're substituting this MUS for a high-quality replacement. + filename = GetSubstituteMusicFile(data, len); + if (filename == NULL) + { + return NULL; + } + + music = Mix_LoadMUS(filename); + if (music == NULL) + { + // Fall through and play MIDI normally, but print an error + // message. + fprintf(stderr, "Failed to load substitute music file: %s: %s\n", + filename, Mix_GetError()); + return NULL; + } + +#if !USE_SDL_MIXER_LOOPING + // Read loop point metadata from the file so that we know where + // to loop the music. + ReadLoopPoints(filename, &file_metadata); +#endif // !USE_SDL_MIXER_LOOPING + return music; +} + +// Is the song playing? +static boolean I_MP_MusicIsPlaying(void) +{ + if (!music_initialized) + { + return false; + } + + return Mix_PlayingMusic(); +} + +#if !USE_SDL_MIXER_LOOPING +// Get position in substitute music track, in seconds since start of track. +static double GetMusicPosition(void) +{ + unsigned int music_pos; + int freq; + + Mix_QuerySpec(&freq, NULL, NULL); + + SDL_LockAudio(); + music_pos = current_track_pos; + SDL_UnlockAudio(); + + return (double) music_pos / freq; +} + +static void RestartCurrentTrack(void) +{ + double start = (double) file_metadata.start_time + / file_metadata.samplerate_hz; + + // If the track finished we need to restart it. + if (current_track_music != NULL) + { + Mix_PlayMusic(current_track_music, 1); + } + + Mix_SetMusicPosition(start); + SDL_LockAudio(); + current_track_pos = file_metadata.start_time; + SDL_UnlockAudio(); +} +#endif // !USE_SDL_MIXER_LOOPING + +// Poll music position; if we have passed the loop point end position +// then we need to go back. +static void I_MP_PollMusic(void) +{ +#if !USE_SDL_MIXER_LOOPING + // When playing substitute tracks, loop tags only apply if we're playing + // a looping track. Tracks like the title screen music have the loop + // tags ignored. + if (current_track_loop && file_metadata.valid) + { + double end = (double) file_metadata.end_time + / file_metadata.samplerate_hz; + + // If we have reached the loop end point then we have to take action. + if (file_metadata.end_time >= 0 && GetMusicPosition() >= end) + { + RestartCurrentTrack(); + } + + // Have we reached the actual end of track (not loop end)? + if (!Mix_PlayingMusic()) + { + RestartCurrentTrack(); + } + } +#endif // !USE_SDL_MIXER_LOOPING +} + +const music_module_t music_pack_module = +{ + NULL, + 0, + I_MP_InitMusic, + I_MP_ShutdownMusic, + I_MP_SetMusicVolume, + I_MP_PauseSong, + I_MP_ResumeSong, + I_MP_RegisterSong, + I_MP_UnRegisterSong, + I_MP_PlaySong, + I_MP_StopSong, + I_MP_MusicIsPlaying, + I_MP_PollMusic, +}; + + +#else // DISABLE_SDL2MIXER + + +static boolean I_NULL_InitMusic(void) +{ + return false; +} + + +static void I_NULL_ShutdownMusic(void) +{ +} + + +static void I_NULL_SetMusicVolume(int volume) +{ +} + + +static void I_NULL_PauseSong(void) +{ +} + + +static void I_NULL_ResumeSong(void) +{ +} + + +static void *I_NULL_RegisterSong(void *data, int len) +{ + return NULL; +} + + +static void I_NULL_UnRegisterSong(void *handle) +{ +} + + +static void I_NULL_PlaySong(void *handle, boolean looping) +{ +} + + +static void I_NULL_StopSong(void) +{ +} + + +static boolean I_NULL_MusicIsPlaying(void) +{ + return false; +} + + +static void I_NULL_PollMusic(void) +{ +} + +const music_module_t music_pack_module = +{ + NULL, + 0, + I_NULL_InitMusic, + I_NULL_ShutdownMusic, + I_NULL_SetMusicVolume, + I_NULL_PauseSong, + I_NULL_ResumeSong, + I_NULL_RegisterSong, + I_NULL_UnRegisterSong, + I_NULL_PlaySong, + I_NULL_StopSong, + I_NULL_MusicIsPlaying, + I_NULL_PollMusic, +}; + + +#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/src/i_oplmusic.c b/games/NXDoom/src/i_oplmusic.c new file mode 100644 index 00000000000..54e7dac3c35 --- /dev/null +++ b/games/NXDoom/src/i_oplmusic.c @@ -0,0 +1,1898 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System interface for music. +// + + +#include +#include +#include + +#include "memio.h" +#include "mus2mid.h" + +#include "deh_main.h" +#include "i_sound.h" +#include "i_swap.h" +#include "m_misc.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "opl.h" +#include "midifile.h" + +// #define OPL_MIDI_DEBUG + +#define MAXMIDLENGTH (96 * 1024) +#define GENMIDI_NUM_INSTRS 128 +#define GENMIDI_NUM_PERCUSSION 47 + +#define GENMIDI_HEADER "#OPL_II#" +#define GENMIDI_FLAG_FIXED 0x0001 /* fixed pitch */ +#define GENMIDI_FLAG_2VOICE 0x0004 /* double voice (OPL3) */ + +#define PERCUSSION_LOG_LEN 16 + +typedef PACKED_STRUCT ( +{ + byte tremolo; + byte attack; + byte sustain; + byte waveform; + byte scale; + byte level; +}) genmidi_op_t; + +typedef PACKED_STRUCT ( +{ + genmidi_op_t modulator; + byte feedback; + genmidi_op_t carrier; + byte unused; + short base_note_offset; +}) genmidi_voice_t; + +typedef PACKED_STRUCT ( +{ + unsigned short flags; + byte fine_tuning; + byte fixed_note; + + genmidi_voice_t voices[2]; +}) genmidi_instr_t; + +// Data associated with a channel of a track that is currently playing. + +typedef struct +{ + // The instrument currently used for this track. + + genmidi_instr_t *instrument; + + // Volume level + + int volume; + int volume_base; + + // Pan + + int pan; + + // Pitch bend value: + + int bend; + +} opl_channel_data_t; + +// Data associated with a track that is currently playing. + +typedef struct +{ + // Track iterator used to read new events. + + midi_track_iter_t *iter; +} opl_track_data_t; + +typedef struct opl_voice_s opl_voice_t; + +struct opl_voice_s +{ + // Index of this voice: + int index; + + // The operators used by this voice: + int op1, op2; + + // Array used by voice: + int array; + + // Currently-loaded instrument data + genmidi_instr_t *current_instr; + + // The voice number in the instrument to use. + // This is normally set to zero; if this is a double voice + // instrument, it may be one. + unsigned int current_instr_voice; + + // The channel currently using this voice. + opl_channel_data_t *channel; + + // The midi key that this voice is playing. + unsigned int key; + + // The note being played. This is normally the same as + // the key, but if the instrument is a fixed pitch + // instrument, it is different. + unsigned int note; + + // The frequency value being used. + unsigned int freq; + + // The volume of the note being played on this channel. + unsigned int note_volume; + + // The current volume (register value) that has been set for this channel. + unsigned int car_volume; + unsigned int mod_volume; + + // Pan. + unsigned int reg_pan; + + // Priority. + unsigned int priority; +}; + +// Operators used by the different voices. + +static const int voice_operators[2][OPL_NUM_VOICES] = { + { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12 }, + { 0x03, 0x04, 0x05, 0x0b, 0x0c, 0x0d, 0x13, 0x14, 0x15 } +}; + +// Frequency values to use for each note. + +static const unsigned short frequency_curve[] = { + + 0x133, 0x133, 0x134, 0x134, 0x135, 0x136, 0x136, 0x137, // -1 + 0x137, 0x138, 0x138, 0x139, 0x139, 0x13a, 0x13b, 0x13b, + 0x13c, 0x13c, 0x13d, 0x13d, 0x13e, 0x13f, 0x13f, 0x140, + 0x140, 0x141, 0x142, 0x142, 0x143, 0x143, 0x144, 0x144, + + 0x145, 0x146, 0x146, 0x147, 0x147, 0x148, 0x149, 0x149, // -2 + 0x14a, 0x14a, 0x14b, 0x14c, 0x14c, 0x14d, 0x14d, 0x14e, + 0x14f, 0x14f, 0x150, 0x150, 0x151, 0x152, 0x152, 0x153, + 0x153, 0x154, 0x155, 0x155, 0x156, 0x157, 0x157, 0x158, + + // These are used for the first seven MIDI note values: + + 0x158, 0x159, 0x15a, 0x15a, 0x15b, 0x15b, 0x15c, 0x15d, // 0 + 0x15d, 0x15e, 0x15f, 0x15f, 0x160, 0x161, 0x161, 0x162, + 0x162, 0x163, 0x164, 0x164, 0x165, 0x166, 0x166, 0x167, + 0x168, 0x168, 0x169, 0x16a, 0x16a, 0x16b, 0x16c, 0x16c, + + 0x16d, 0x16e, 0x16e, 0x16f, 0x170, 0x170, 0x171, 0x172, // 1 + 0x172, 0x173, 0x174, 0x174, 0x175, 0x176, 0x176, 0x177, + 0x178, 0x178, 0x179, 0x17a, 0x17a, 0x17b, 0x17c, 0x17c, + 0x17d, 0x17e, 0x17e, 0x17f, 0x180, 0x181, 0x181, 0x182, + + 0x183, 0x183, 0x184, 0x185, 0x185, 0x186, 0x187, 0x188, // 2 + 0x188, 0x189, 0x18a, 0x18a, 0x18b, 0x18c, 0x18d, 0x18d, + 0x18e, 0x18f, 0x18f, 0x190, 0x191, 0x192, 0x192, 0x193, + 0x194, 0x194, 0x195, 0x196, 0x197, 0x197, 0x198, 0x199, + + 0x19a, 0x19a, 0x19b, 0x19c, 0x19d, 0x19d, 0x19e, 0x19f, // 3 + 0x1a0, 0x1a0, 0x1a1, 0x1a2, 0x1a3, 0x1a3, 0x1a4, 0x1a5, + 0x1a6, 0x1a6, 0x1a7, 0x1a8, 0x1a9, 0x1a9, 0x1aa, 0x1ab, + 0x1ac, 0x1ad, 0x1ad, 0x1ae, 0x1af, 0x1b0, 0x1b0, 0x1b1, + + 0x1b2, 0x1b3, 0x1b4, 0x1b4, 0x1b5, 0x1b6, 0x1b7, 0x1b8, // 4 + 0x1b8, 0x1b9, 0x1ba, 0x1bb, 0x1bc, 0x1bc, 0x1bd, 0x1be, + 0x1bf, 0x1c0, 0x1c0, 0x1c1, 0x1c2, 0x1c3, 0x1c4, 0x1c4, + 0x1c5, 0x1c6, 0x1c7, 0x1c8, 0x1c9, 0x1c9, 0x1ca, 0x1cb, + + 0x1cc, 0x1cd, 0x1ce, 0x1ce, 0x1cf, 0x1d0, 0x1d1, 0x1d2, // 5 + 0x1d3, 0x1d3, 0x1d4, 0x1d5, 0x1d6, 0x1d7, 0x1d8, 0x1d8, + 0x1d9, 0x1da, 0x1db, 0x1dc, 0x1dd, 0x1de, 0x1de, 0x1df, + 0x1e0, 0x1e1, 0x1e2, 0x1e3, 0x1e4, 0x1e5, 0x1e5, 0x1e6, + + 0x1e7, 0x1e8, 0x1e9, 0x1ea, 0x1eb, 0x1ec, 0x1ed, 0x1ed, // 6 + 0x1ee, 0x1ef, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5, + 0x1f6, 0x1f6, 0x1f7, 0x1f8, 0x1f9, 0x1fa, 0x1fb, 0x1fc, + 0x1fd, 0x1fe, 0x1ff, 0x200, 0x201, 0x201, 0x202, 0x203, + + // First note of looped range used for all octaves: + + 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, // 7 + 0x20c, 0x20d, 0x20e, 0x20f, 0x210, 0x210, 0x211, 0x212, + 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a, + 0x21b, 0x21c, 0x21d, 0x21e, 0x21f, 0x220, 0x221, 0x222, + + 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22a, // 8 + 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, 0x230, 0x231, 0x232, + 0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, + 0x23b, 0x23c, 0x23d, 0x23e, 0x23f, 0x240, 0x241, 0x242, + + 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b, // 9 + 0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253, + 0x254, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x25b, 0x25c, + 0x25d, 0x25e, 0x25f, 0x260, 0x262, 0x263, 0x264, 0x265, + + 0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, // 10 + 0x26f, 0x270, 0x271, 0x272, 0x273, 0x275, 0x276, 0x277, + 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280, + 0x281, 0x282, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, + + 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x292, 0x293, // 11 + 0x294, 0x295, 0x296, 0x298, 0x299, 0x29a, 0x29b, 0x29c, + 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6, + 0x2a7, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ae, 0x2af, 0x2b0, + + 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba, // 12 + 0x2bb, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c2, 0x2c3, 0x2c4, + 0x2c5, 0x2c7, 0x2c8, 0x2c9, 0x2cb, 0x2cc, 0x2cd, 0x2ce, + 0x2d0, 0x2d1, 0x2d2, 0x2d4, 0x2d5, 0x2d6, 0x2d8, 0x2d9, + + 0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, // 13 + 0x2e5, 0x2e6, 0x2e8, 0x2e9, 0x2ea, 0x2ec, 0x2ed, 0x2ee, + 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9, + 0x2fb, 0x2fc, 0x2fd, 0x2ff, 0x300, 0x302, 0x303, 0x304, + + 0x306, 0x307, 0x309, 0x30a, 0x30b, 0x30d, 0x30e, 0x310, // 14 + 0x311, 0x312, 0x314, 0x315, 0x317, 0x318, 0x31a, 0x31b, + 0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327, + 0x328, 0x329, 0x32b, 0x32c, 0x32e, 0x32f, 0x331, 0x332, + + 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e, // 15 + 0x340, 0x341, 0x343, 0x344, 0x346, 0x347, 0x349, 0x34a, + 0x34c, 0x34d, 0x34f, 0x350, 0x352, 0x353, 0x355, 0x357, + 0x358, 0x35a, 0x35b, 0x35d, 0x35e, 0x360, 0x361, 0x363, + + 0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, // 16 + 0x371, 0x373, 0x374, 0x376, 0x378, 0x379, 0x37b, 0x37c, + 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389, + 0x38b, 0x38d, 0x38e, 0x390, 0x392, 0x393, 0x395, 0x397, + + 0x398, 0x39a, 0x39c, 0x39d, 0x39f, 0x3a1, 0x3a2, 0x3a4, // 17 + 0x3a6, 0x3a7, 0x3a9, 0x3ab, 0x3ac, 0x3ae, 0x3b0, 0x3b1, + 0x3b3, 0x3b5, 0x3b7, 0x3b8, 0x3ba, 0x3bc, 0x3bd, 0x3bf, + 0x3c1, 0x3c3, 0x3c4, 0x3c6, 0x3c8, 0x3ca, 0x3cb, 0x3cd, + + // The last note has an incomplete range, and loops round back to + // the start. Note that the last value is actually a buffer overrun + // and does not fit with the other values. + + 0x3cf, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3da, 0x3db, // 18 + 0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e4, 0x3e6, 0x3e8, 0x3ea, + 0x3ec, 0x3ed, 0x3ef, 0x3f1, 0x3f3, 0x3f5, 0x3f6, 0x3f8, + 0x3fa, 0x3fc, 0x3fe, 0x36c, +}; + +// Mapping from MIDI volume level to OPL level value. + +static const unsigned int volume_mapping_table[] = { + 0, 1, 3, 5, 6, 8, 10, 11, + 13, 14, 16, 17, 19, 20, 22, 23, + 25, 26, 27, 29, 30, 32, 33, 34, + 36, 37, 39, 41, 43, 45, 47, 49, + 50, 52, 54, 55, 57, 59, 60, 61, + 63, 64, 66, 67, 68, 69, 71, 72, + 73, 74, 75, 76, 77, 79, 80, 81, + 82, 83, 84, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 92, 93, 94, 95, + 96, 96, 97, 98, 99, 99, 100, 101, + 101, 102, 103, 103, 104, 105, 105, 106, + 107, 107, 108, 109, 109, 110, 110, 111, + 112, 112, 113, 113, 114, 114, 115, 115, + 116, 117, 117, 118, 118, 119, 119, 120, + 120, 121, 121, 122, 122, 123, 123, 123, + 124, 124, 125, 125, 126, 126, 127, 127 +}; + +static opl_driver_ver_t opl_drv_ver = opl_doom_1_9; +static boolean music_initialized = false; + +//static boolean musicpaused = false; +static int start_music_volume; +static int current_music_volume; + +// GENMIDI lump instrument data: + +static genmidi_instr_t *main_instrs; +static genmidi_instr_t *percussion_instrs; +static char (*main_instr_names)[32]; +static char (*percussion_names)[32]; + +// Voices: + +static opl_voice_t voices[OPL_NUM_VOICES * 2]; +static opl_voice_t *voice_free_list[OPL_NUM_VOICES * 2]; +static opl_voice_t *voice_alloced_list[OPL_NUM_VOICES * 2]; +static int voice_free_num; +static int voice_alloced_num; +static int opl_opl3mode; +static int num_opl_voices; + +// Data for each channel. + +static opl_channel_data_t channels[MIDI_CHANNELS_PER_TRACK]; + +// Track data for playing tracks: + +static opl_track_data_t *tracks; +static unsigned int num_tracks = 0; +static unsigned int running_tracks = 0; +static boolean song_looping; + +// Tempo control variables + +static unsigned int ticks_per_beat; +static unsigned int us_per_beat; + +// Mini-log of recently played percussion instruments: + +static uint8_t last_perc[PERCUSSION_LOG_LEN]; +static unsigned int last_perc_count; + +// Configuration file variable, containing the port number for the +// adlib chip. + +char *snd_dmxoption = ""; +int opl_io_port = 0x388; + +// If true, OPL sound channels are reversed to their correct arrangement +// (as intended by the MIDI standard) rather than the backwards one +// used by DMX due to a bug. + +static boolean opl_stereo_correct = false; + +// Load instrument table from GENMIDI lump: + +static boolean LoadInstrumentTable(void) +{ + byte *lump; + + lump = W_CacheLumpName(DEH_String("genmidi"), PU_STATIC); + + // DMX does not check header + + main_instrs = (genmidi_instr_t *) (lump + strlen(GENMIDI_HEADER)); + percussion_instrs = main_instrs + GENMIDI_NUM_INSTRS; + main_instr_names = + (char (*)[32]) (percussion_instrs + GENMIDI_NUM_PERCUSSION); + percussion_names = main_instr_names + GENMIDI_NUM_INSTRS; + + return true; +} + +// Get the next available voice from the freelist. + +static opl_voice_t *GetFreeVoice(void) +{ + opl_voice_t *result; + int i; + + // None available? + + if (voice_free_num == 0) + { + return NULL; + } + + // Remove from free list + + result = voice_free_list[0]; + + voice_free_num--; + + for (i = 0; i < voice_free_num; i++) + { + voice_free_list[i] = voice_free_list[i + 1]; + } + + // Add to allocated list + + voice_alloced_list[voice_alloced_num++] = result; + + return result; +} + +// Release a voice back to the freelist. + +static void VoiceKeyOff(opl_voice_t *voice); + +static void ReleaseVoice(int index) +{ + opl_voice_t *voice; + boolean double_voice; + int i; + + // Doom 2 1.666 OPL crash emulation. + if (index >= voice_alloced_num) + { + + voice_alloced_num = 0; + voice_free_num = 0; + return; + } + + voice = voice_alloced_list[index]; + + VoiceKeyOff(voice); + + voice->channel = NULL; + voice->note = 0; + + double_voice = voice->current_instr_voice != 0; + + // Remove from alloced list. + + voice_alloced_num--; + + for (i = index; i < voice_alloced_num; i++) + { + voice_alloced_list[i] = voice_alloced_list[i + 1]; + } + + // Search to the end of the freelist (This is how Doom behaves!) + + voice_free_list[voice_free_num++] = voice; + + if (double_voice && opl_drv_ver < opl_doom_1_9) + { + ReleaseVoice(index); + } +} + +// Load data to the specified operator + +static void LoadOperatorData(int operator, genmidi_op_t *data, + boolean max_level, unsigned int *volume) +{ + int level; + + // The scale and level fields must be combined for the level register. + // For the carrier wave we always set the maximum level. + + level = data->scale; + + if (max_level) + { + level |= 0x3f; + } + else + { + level |= data->level; + } + + *volume = level; + + OPL_WriteRegister(OPL_REGS_LEVEL + operator, level); + OPL_WriteRegister(OPL_REGS_TREMOLO + operator, data->tremolo); + OPL_WriteRegister(OPL_REGS_ATTACK + operator, data->attack); + OPL_WriteRegister(OPL_REGS_SUSTAIN + operator, data->sustain); + OPL_WriteRegister(OPL_REGS_WAVEFORM + operator, data->waveform); +} + +// Set the instrument for a particular voice. + +static void SetVoiceInstrument(opl_voice_t *voice, + genmidi_instr_t *instr, + unsigned int instr_voice) +{ + genmidi_voice_t *data; + unsigned int modulating; + + // Instrument already set for this channel? + + if (voice->current_instr == instr + && voice->current_instr_voice == instr_voice) + { + return; + } + + voice->current_instr = instr; + voice->current_instr_voice = instr_voice; + + data = &instr->voices[instr_voice]; + + // Are we usind modulated feedback mode? + + modulating = (data->feedback & 0x01) == 0; + + // Doom loads the second operator first, then the first. + // The carrier is set to minimum volume until the voice volume + // is set in SetVoiceVolume (below). If we are not using + // modulating mode, we must set both to minimum volume. + + LoadOperatorData(voice->op2 | voice->array, &data->carrier, true, + &voice->car_volume); + LoadOperatorData(voice->op1 | voice->array, &data->modulator, !modulating, + &voice->mod_volume); + + // Set feedback register that control the connection between the + // two operators. Turn on bits in the upper nybble; I think this + // is for OPL3, where it turns on channel A/B. + + OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array, + data->feedback | voice->reg_pan); + + // Calculate voice priority. + + voice->priority = 0x0f - (data->carrier.attack >> 4) + + 0x0f - (data->carrier.sustain & 0x0f); +} + +static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume) +{ + genmidi_voice_t *opl_voice; + unsigned int midi_volume; + unsigned int full_volume; + unsigned int car_volume; + unsigned int mod_volume; + + voice->note_volume = volume; + + opl_voice = &voice->current_instr->voices[voice->current_instr_voice]; + + // Multiply note volume and channel volume to get the actual volume. + + midi_volume = 2 * (volume_mapping_table[voice->channel->volume] + 1); + + full_volume = (volume_mapping_table[voice->note_volume] * midi_volume) + >> 9; + + // The volume value to use in the register: + car_volume = 0x3f - full_volume; + + // Update the volume register(s) if necessary. + + if (car_volume != (voice->car_volume & 0x3f)) + { + voice->car_volume = car_volume | (voice->car_volume & 0xc0); + + OPL_WriteRegister((OPL_REGS_LEVEL + voice->op2) | voice->array, + voice->car_volume); + + // If we are using non-modulated feedback mode, we must set the + // volume for both voices. + + if ((opl_voice->feedback & 0x01) != 0 + && opl_voice->modulator.level != 0x3f) + { + mod_volume = opl_voice->modulator.level; + if (mod_volume < car_volume) + { + mod_volume = car_volume; + } + + mod_volume |= voice->mod_volume & 0xc0; + + if(mod_volume != voice->mod_volume) + { + voice->mod_volume = mod_volume; + OPL_WriteRegister((OPL_REGS_LEVEL + voice->op1) | voice->array, + mod_volume | + (opl_voice->modulator.scale & 0xc0)); + } + } + } +} + +static void SetVoicePan(opl_voice_t *voice, unsigned int pan) +{ + genmidi_voice_t *opl_voice; + + voice->reg_pan = pan; + opl_voice = &voice->current_instr->voices[voice->current_instr_voice];; + + OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array, + opl_voice->feedback | pan); +} + +// Initialize the voice table and freelist + +static void InitVoices(void) +{ + int i; + + // Start with an empty free list. + + voice_free_num = num_opl_voices; + voice_alloced_num = 0; + + // Initialize each voice. + + for (i = 0; i < num_opl_voices; ++i) + { + voices[i].index = i % OPL_NUM_VOICES; + voices[i].op1 = voice_operators[0][i % OPL_NUM_VOICES]; + voices[i].op2 = voice_operators[1][i % OPL_NUM_VOICES]; + voices[i].array = (i / OPL_NUM_VOICES) << 8; + voices[i].current_instr = NULL; + + // Add this voice to the freelist. + + voice_free_list[i] = &voices[i]; + } +} + +static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume, + boolean clip_start); + +// Set music volume (0 - 127) + +static void I_OPL_SetMusicVolume(int volume) +{ + unsigned int i; + + if (current_music_volume == volume) + { + return; + } + + // Internal state variable. + + current_music_volume = volume; + + // Update the volume of all voices. + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + if (i == 15) + { + SetChannelVolume(&channels[i], volume, false); + } + else + { + SetChannelVolume(&channels[i], channels[i].volume_base, false); + } + } +} + +static void VoiceKeyOff(opl_voice_t *voice) +{ + OPL_WriteRegister((OPL_REGS_FREQ_2 + voice->index) | voice->array, + voice->freq >> 8); +} + +static opl_channel_data_t *TrackChannelForEvent(opl_track_data_t *track, + midi_event_t *event) +{ + unsigned int channel_num = event->data.channel.channel; + + // MIDI uses track #9 for percussion, but for MUS it's track #15 + // instead. Because DMX works on MUS data internally, we need to + // swap back to the MUS version of the channel number. + if (channel_num == 9) + { + channel_num = 15; + } + else if (channel_num == 15) + { + channel_num = 9; + } + + return &channels[channel_num]; +} + +// Get the frequency that we should be using for a voice. + +static void KeyOffEvent(opl_track_data_t *track, midi_event_t *event) +{ + opl_channel_data_t *channel; + int i; + unsigned int key; + +/* + printf("note off: channel %i, %i, %i\n", + event->data.channel.channel, + event->data.channel.param1, + event->data.channel.param2); +*/ + + channel = TrackChannelForEvent(track, event); + key = event->data.channel.param1; + + // Turn off voices being used to play this key. + // If it is a double voice instrument there will be two. + + for (i = 0; i < voice_alloced_num; i++) + { + if (voice_alloced_list[i]->channel == channel + && voice_alloced_list[i]->key == key) + { + // Finished with this voice now. + + ReleaseVoice(i); + + i--; + } + } +} + +// When all voices are in use, we must discard an existing voice to +// play a new note. Find and free an existing voice. The channel +// passed to the function is the channel for the new note to be +// played. + +static void ReplaceExistingVoice(void) +{ + int i; + int result; + + // Check the allocated voices, if we find an instrument that is + // of a lower priority to the new instrument, discard it. + // If a voice is being used to play the second voice of an instrument, + // use that, as second voices are non-essential. + // Lower numbered MIDI channels implicitly have a higher priority + // than higher-numbered channels, eg. MIDI channel 1 is never + // discarded for MIDI channel 2. + + result = 0; + + for (i = 0; i < voice_alloced_num; i++) + { + if (voice_alloced_list[i]->current_instr_voice != 0 + || voice_alloced_list[i]->channel + >= voice_alloced_list[result]->channel) + { + result = i; + } + } + + ReleaseVoice(result); +} + +// Alternate versions of ReplaceExistingVoice() used when emulating old +// versions of the DMX library used in Doom 1.666, Heretic and Hexen. + +static void ReplaceExistingVoiceDoom1(void) +{ + int i; + int result; + + result = 0; + + for (i = 0; i < voice_alloced_num; i++) + { + if (voice_alloced_list[i]->channel + > voice_alloced_list[result]->channel) + { + result = i; + } + } + + ReleaseVoice(result); +} + +static void ReplaceExistingVoiceDoom2(opl_channel_data_t *channel) +{ + int i; + int result; + int priority; + + result = 0; + + priority = 0x8000; + + for (i = 0; i < voice_alloced_num - 3; i++) + { + if (voice_alloced_list[i]->priority < priority + && voice_alloced_list[i]->channel >= channel) + { + priority = voice_alloced_list[i]->priority; + result = i; + } + } + + ReleaseVoice(result); +} + + +static unsigned int FrequencyForVoice(opl_voice_t *voice) +{ + genmidi_voice_t *gm_voice; + signed int freq_index; + unsigned int octave; + unsigned int sub_index; + signed int note; + + note = voice->note; + + // Apply note offset. + // Don't apply offset if the instrument is a fixed note instrument. + + gm_voice = &voice->current_instr->voices[voice->current_instr_voice]; + + if ((SHORT(voice->current_instr->flags) & GENMIDI_FLAG_FIXED) == 0) + { + note += (signed short) SHORT(gm_voice->base_note_offset); + } + + // Avoid possible overflow due to base note offset: + + while (note < 0) + { + note += 12; + } + + while (note > 95) + { + note -= 12; + } + + freq_index = 64 + 32 * note + voice->channel->bend; + + // If this is the second voice of a double voice instrument, the + // frequency index can be adjusted by the fine tuning field. + + if (voice->current_instr_voice != 0) + { + freq_index += (voice->current_instr->fine_tuning / 2) - 64; + } + + if (freq_index < 0) + { + freq_index = 0; + } + + // The first 7 notes use the start of the table, while + // consecutive notes loop around the latter part. + + if (freq_index < 284) + { + return frequency_curve[freq_index]; + } + + sub_index = (freq_index - 284) % (12 * 32); + octave = (freq_index - 284) / (12 * 32); + + // Once the seventh octave is reached, things break down. + // We can only go up to octave 7 as a maximum anyway (the OPL + // register only has three bits for octave number), but for the + // notes in octave 7, the first five bits have octave=7, the + // following notes have octave=6. This 7/6 pattern repeats in + // following octaves (which are technically impossible to + // represent anyway). + + if (octave >= 7) + { + octave = 7; + } + + // Calculate the resulting register value to use for the frequency. + + return frequency_curve[sub_index + 284] | (octave << 10); +} + +// Update the frequency that a voice is programmed to use. + +static void UpdateVoiceFrequency(opl_voice_t *voice) +{ + unsigned int freq; + + // Calculate the frequency to use for this voice and update it + // if neccessary. + + freq = FrequencyForVoice(voice); + + if (voice->freq != freq) + { + OPL_WriteRegister((OPL_REGS_FREQ_1 + voice->index) | voice->array, + freq & 0xff); + OPL_WriteRegister((OPL_REGS_FREQ_2 + voice->index) | voice->array, + (freq >> 8) | 0x20); + + voice->freq = freq; + } +} + +// Program a single voice for an instrument. For a double voice +// instrument (GENMIDI_FLAG_2VOICE), this is called twice for each +// key on event. + +static void VoiceKeyOn(opl_channel_data_t *channel, + genmidi_instr_t *instrument, + unsigned int instrument_voice, + unsigned int note, + unsigned int key, + unsigned int volume) +{ + opl_voice_t *voice; + + if (!opl_opl3mode && opl_drv_ver == opl_doom1_1_666) + { + instrument_voice = 0; + } + + // Find a voice to use for this new note. + + voice = GetFreeVoice(); + + if (voice == NULL) + { + return; + } + + voice->channel = channel; + voice->key = key; + + // Work out the note to use. This is normally the same as + // the key, unless it is a fixed pitch instrument. + + if ((SHORT(instrument->flags) & GENMIDI_FLAG_FIXED) != 0) + { + voice->note = instrument->fixed_note; + } + else + { + voice->note = note; + } + + voice->reg_pan = channel->pan; + + // Program the voice with the instrument data: + + SetVoiceInstrument(voice, instrument, instrument_voice); + + // Set the volume level. + + SetVoiceVolume(voice, volume); + + // Write the frequency value to turn the note on. + + voice->freq = 0; + UpdateVoiceFrequency(voice); +} + +static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event) +{ + genmidi_instr_t *instrument; + opl_channel_data_t *channel; + unsigned int note, key, volume, voicenum; + boolean double_voice; + +/* + printf("note on: channel %i, %i, %i\n", + event->data.channel.channel, + event->data.channel.param1, + event->data.channel.param2); +*/ + + note = event->data.channel.param1; + key = event->data.channel.param1; + volume = event->data.channel.param2; + + // A volume of zero means key off. Some MIDI tracks, eg. the ones + // in AV.wad, use a second key on with a volume of zero to mean + // key off. + if (volume <= 0) + { + KeyOffEvent(track, event); + return; + } + + // The channel. + channel = TrackChannelForEvent(track, event); + + // Percussion channel is treated differently. + if (event->data.channel.channel == 9) + { + if (key < 35 || key > 81) + { + return; + } + + instrument = &percussion_instrs[key - 35]; + + last_perc[last_perc_count] = key; + last_perc_count = (last_perc_count + 1) % PERCUSSION_LOG_LEN; + note = 60; + } + else + { + instrument = channel->instrument; + } + + double_voice = (SHORT(instrument->flags) & GENMIDI_FLAG_2VOICE) != 0; + + switch (opl_drv_ver) + { + case opl_doom1_1_666: + voicenum = double_voice + 1; + if (!opl_opl3mode) + { + voicenum = 1; + } + while (voice_alloced_num > num_opl_voices - voicenum) + { + ReplaceExistingVoiceDoom1(); + } + + // Find and program a voice for this instrument. If this + // is a double voice instrument, we must do this twice. + + if (double_voice) + { + VoiceKeyOn(channel, instrument, 1, note, key, volume); + } + + VoiceKeyOn(channel, instrument, 0, note, key, volume); + break; + case opl_doom2_1_666: + if (voice_alloced_num == num_opl_voices) + { + ReplaceExistingVoiceDoom2(channel); + } + if (voice_alloced_num == num_opl_voices - 1 && double_voice) + { + ReplaceExistingVoiceDoom2(channel); + } + + // Find and program a voice for this instrument. If this + // is a double voice instrument, we must do this twice. + + if (double_voice) + { + VoiceKeyOn(channel, instrument, 1, note, key, volume); + } + + VoiceKeyOn(channel, instrument, 0, note, key, volume); + break; + default: + case opl_doom_1_9: + if (voice_free_num == 0) + { + ReplaceExistingVoice(); + } + + // Find and program a voice for this instrument. If this + // is a double voice instrument, we must do this twice. + + VoiceKeyOn(channel, instrument, 0, note, key, volume); + + if (double_voice) + { + VoiceKeyOn(channel, instrument, 1, note, key, volume); + } + break; + } +} + +static void ProgramChangeEvent(opl_track_data_t *track, midi_event_t *event) +{ + opl_channel_data_t *channel; + int instrument; + + // Set the instrument used on this channel. + + channel = TrackChannelForEvent(track, event); + instrument = event->data.channel.param1; + channel->instrument = &main_instrs[instrument]; + + // TODO: Look through existing voices that are turned on on this + // channel, and change the instrument. +} + +static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume, + boolean clip_start) +{ + unsigned int i; + + channel->volume_base = volume; + + if (volume > current_music_volume) + { + volume = current_music_volume; + } + + if (clip_start && volume > start_music_volume) + { + volume = start_music_volume; + } + + channel->volume = volume; + + // Update all voices that this channel is using. + + for (i = 0; i < num_opl_voices; ++i) + { + if (voices[i].channel == channel) + { + SetVoiceVolume(&voices[i], voices[i].note_volume); + } + } +} + +static void SetChannelPan(opl_channel_data_t *channel, unsigned int pan) +{ + unsigned int reg_pan; + unsigned int i; + + // The DMX library has the stereo channels backwards, maybe because + // Paul Radek had a Soundblaster card with the channels reversed, or + // perhaps it was just a bug in the OPL3 support that was never + // finished. By default we preserve this bug, but we also provide a + // secret DMXOPTION to fix it. + if (opl_stereo_correct) + { + pan = 144 - pan; + } + + if (opl_opl3mode) + { + if (pan >= 96) + { + reg_pan = 0x10; + } + else if (pan <= 48) + { + reg_pan = 0x20; + } + else + { + reg_pan = 0x30; + } + if (channel->pan != reg_pan) + { + channel->pan = reg_pan; + for (i = 0; i < num_opl_voices; i++) + { + if (voices[i].channel == channel) + { + SetVoicePan(&voices[i], reg_pan); + } + } + } + } +} + +// Handler for the MIDI_CONTROLLER_ALL_NOTES_OFF channel event. +static void AllNotesOff(opl_channel_data_t *channel, unsigned int param) +{ + int i; + + for (i = 0; i < voice_alloced_num; i++) + { + if (voice_alloced_list[i]->channel == channel) + { + // Finished with this voice now. + + ReleaseVoice(i); + + i--; + } + } +} + +static void ControllerEvent(opl_track_data_t *track, midi_event_t *event) +{ + opl_channel_data_t *channel; + unsigned int controller; + unsigned int param; + +/* + printf("change controller: channel %i, %i, %i\n", + event->data.channel.channel, + event->data.channel.param1, + event->data.channel.param2); +*/ + + channel = TrackChannelForEvent(track, event); + controller = event->data.channel.param1; + param = event->data.channel.param2; + + switch (controller) + { + case MIDI_CONTROLLER_VOLUME_MSB: + SetChannelVolume(channel, param, true); + break; + + case MIDI_CONTROLLER_PAN: + SetChannelPan(channel, param); + break; + + case MIDI_CONTROLLER_ALL_NOTES_OFF: + AllNotesOff(channel, param); + break; + + default: +#ifdef OPL_MIDI_DEBUG + fprintf(stderr, "Unknown MIDI controller type: %u\n", controller); +#endif + break; + } +} + +// Process a pitch bend event. + +static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event) +{ + opl_channel_data_t *channel; + int i; + opl_voice_t *voice_updated_list[OPL_NUM_VOICES * 2]; + unsigned int voice_updated_num = 0; + opl_voice_t *voice_not_updated_list[OPL_NUM_VOICES * 2]; + unsigned int voice_not_updated_num = 0; + + // Update the channel bend value. Only the MSB of the pitch bend + // value is considered: this is what Doom does. + + channel = TrackChannelForEvent(track, event); + channel->bend = event->data.channel.param2 - 64; + + // Update all voices for this channel. + + for (i = 0; i < voice_alloced_num; ++i) + { + if (voice_alloced_list[i]->channel == channel) + { + UpdateVoiceFrequency(voice_alloced_list[i]); + voice_updated_list[voice_updated_num++] = voice_alloced_list[i]; + } + else + { + voice_not_updated_list[voice_not_updated_num++] = + voice_alloced_list[i]; + } + } + + for (i = 0; i < voice_not_updated_num; i++) + { + voice_alloced_list[i] = voice_not_updated_list[i]; + } + + for (i = 0; i < voice_updated_num; i++) + { + voice_alloced_list[i + voice_not_updated_num] = voice_updated_list[i]; + } +} + +static void MetaSetTempo(unsigned int tempo) +{ + OPL_AdjustCallbacks((float) us_per_beat / tempo); + us_per_beat = tempo; +} + +// Process a meta event. + +static void MetaEvent(opl_track_data_t *track, midi_event_t *event) +{ + byte *data = event->data.meta.data; + unsigned int data_len = event->data.meta.length; + + switch (event->data.meta.type) + { + // Things we can just ignore. + + case MIDI_META_SEQUENCE_NUMBER: + case MIDI_META_TEXT: + case MIDI_META_COPYRIGHT: + case MIDI_META_TRACK_NAME: + case MIDI_META_INSTR_NAME: + case MIDI_META_LYRICS: + case MIDI_META_MARKER: + case MIDI_META_CUE_POINT: + case MIDI_META_SEQUENCER_SPECIFIC: + break; + + case MIDI_META_SET_TEMPO: + if (data_len == 3) + { + MetaSetTempo((data[0] << 16) | (data[1] << 8) | data[2]); + } + break; + + // End of track - actually handled when we run out of events + // in the track, see below. + + case MIDI_META_END_OF_TRACK: + break; + + default: +#ifdef OPL_MIDI_DEBUG + fprintf(stderr, "Unknown MIDI meta event type: %u\n", + event->data.meta.type); +#endif + break; + } +} + +// Process a MIDI event from a track. + +static void ProcessEvent(opl_track_data_t *track, midi_event_t *event) +{ + switch (event->event_type) + { + case MIDI_EVENT_NOTE_OFF: + KeyOffEvent(track, event); + break; + + case MIDI_EVENT_NOTE_ON: + KeyOnEvent(track, event); + break; + + case MIDI_EVENT_CONTROLLER: + ControllerEvent(track, event); + break; + + case MIDI_EVENT_PROGRAM_CHANGE: + ProgramChangeEvent(track, event); + break; + + case MIDI_EVENT_PITCH_BEND: + PitchBendEvent(track, event); + break; + + case MIDI_EVENT_META: + MetaEvent(track, event); + break; + + // SysEx events can be ignored. + + case MIDI_EVENT_SYSEX: + case MIDI_EVENT_SYSEX_SPLIT: + break; + + default: +#ifdef OPL_MIDI_DEBUG + fprintf(stderr, "Unknown MIDI event type %i\n", event->event_type); +#endif + break; + } +} + +static void ScheduleTrack(opl_track_data_t *track); +static void InitChannel(opl_channel_data_t *channel); + +// Restart a song from the beginning. + +static void RestartSong(void *unused) +{ + unsigned int i; + + running_tracks = num_tracks; + + start_music_volume = current_music_volume; + + for (i = 0; i < num_tracks; ++i) + { + MIDI_RestartIterator(tracks[i].iter); + ScheduleTrack(&tracks[i]); + } + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + InitChannel(&channels[i]); + } +} + +// Callback function invoked when another event needs to be read from +// a track. + +static void TrackTimerCallback(void *arg) +{ + opl_track_data_t *track = arg; + midi_event_t *event; + + // Get the next event and process it. + + if (!MIDI_GetNextEvent(track->iter, &event)) + { + return; + } + + ProcessEvent(track, event); + + // End of track? + + if (event->event_type == MIDI_EVENT_META + && event->data.meta.type == MIDI_META_END_OF_TRACK) + { + --running_tracks; + + // When all tracks have finished, restart the song. + // Don't restart the song immediately, but wait for 5ms + // before triggering a restart. Otherwise it is possible + // to construct an empty MIDI file that causes the game + // to lock up in an infinite loop. (5ms should be short + // enough not to be noticeable by the listener). + + if (running_tracks <= 0 && song_looping) + { + OPL_SetCallback(5000, RestartSong, NULL); + } + + return; + } + + // Reschedule the callback for the next event in the track. + + ScheduleTrack(track); +} + +static void ScheduleTrack(opl_track_data_t *track) +{ + unsigned int nticks; + uint64_t us; + + // Get the number of microseconds until the next event. + + nticks = MIDI_GetDeltaTime(track->iter); + us = ((uint64_t) nticks * us_per_beat) / ticks_per_beat; + + // Set a timer to be invoked when the next event is + // ready to play. + + OPL_SetCallback(us, TrackTimerCallback, track); +} + +// Initialize a channel. + +static void InitChannel(opl_channel_data_t *channel) +{ + // TODO: Work out sensible defaults? + + channel->instrument = &main_instrs[0]; + channel->volume = current_music_volume; + channel->volume_base = 100; + if (channel->volume > channel->volume_base) + { + channel->volume = channel->volume_base; + } + channel->pan = 0x30; + channel->bend = 0; +} + +// Start a MIDI track playing: + +static void StartTrack(midi_file_t *file, unsigned int track_num) +{ + opl_track_data_t *track; + + track = &tracks[track_num]; + track->iter = MIDI_IterateTrack(file, track_num); + + // Schedule the first event. + + ScheduleTrack(track); +} + +// Start playing a mid + +static void I_OPL_PlaySong(void *handle, boolean looping) +{ + midi_file_t *file; + unsigned int i; + + if (!music_initialized || handle == NULL) + { + return; + } + + file = handle; + + // Allocate track data. + + tracks = malloc(MIDI_NumTracks(file) * sizeof(opl_track_data_t)); + + num_tracks = MIDI_NumTracks(file); + running_tracks = num_tracks; + song_looping = looping; + + ticks_per_beat = MIDI_GetFileTimeDivision(file); + + // Default is 120 bpm. + // TODO: this is wrong + + us_per_beat = 500 * 1000; + + start_music_volume = current_music_volume; + + for (i = 0; i < num_tracks; ++i) + { + StartTrack(file, i); + } + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + InitChannel(&channels[i]); + } + + // If the music was previously paused, it needs to be unpaused; playing + // a new song implies that we turn off pause. This matches vanilla + // behavior of the DMX library, and some of the higher-level code in + // s_sound.c relies on this. + OPL_SetPaused(0); +} + +static void I_OPL_PauseSong(void) +{ + unsigned int i; + + if (!music_initialized) + { + return; + } + + // Pause OPL callbacks. + + OPL_SetPaused(1); + + // Turn off all main instrument voices (not percussion). + // This is what Vanilla does. + + for (i = 0; i < num_opl_voices; ++i) + { + if (voices[i].channel != NULL + && voices[i].current_instr < percussion_instrs) + { + VoiceKeyOff(&voices[i]); + } + } +} + +static void I_OPL_ResumeSong(void) +{ + if (!music_initialized) + { + return; + } + + OPL_SetPaused(0); +} + +static void I_OPL_StopSong(void) +{ + unsigned int i; + + if (!music_initialized) + { + return; + } + + OPL_Lock(); + + // Stop all playback. + + OPL_ClearCallbacks(); + + // Free all voices. + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + AllNotesOff(&channels[i], 0); + } + + // Free all track data. + + for (i = 0; i < num_tracks; ++i) + { + MIDI_FreeIterator(tracks[i].iter); + } + + free(tracks); + + tracks = NULL; + num_tracks = 0; + + OPL_Unlock(); +} + +static void I_OPL_UnRegisterSong(void *handle) +{ + if (!music_initialized) + { + return; + } + + if (handle != NULL) + { + MIDI_FreeFile(handle); + } +} + +// Determine whether memory block is a .mid file + +static boolean IsMid(byte *mem, int len) +{ + return len > 4 && !memcmp(mem, "MThd", 4); +} + +static boolean ConvertMus(byte *musdata, int len, char *filename) +{ + MEMFILE *instream; + MEMFILE *outstream; + void *outbuf; + size_t outbuf_len; + int result; + + instream = mem_fopen_read(musdata, len); + outstream = mem_fopen_write(); + + result = mus2mid(instream, outstream); + + if (result == 0) + { + mem_get_buf(outstream, &outbuf, &outbuf_len); + + M_WriteFile(filename, outbuf, outbuf_len); + } + + mem_fclose(instream); + mem_fclose(outstream); + + return result; +} + +static void *I_OPL_RegisterSong(void *data, int len) +{ + midi_file_t *result; + char *filename; + + if (!music_initialized) + { + return NULL; + } + + // MUS files begin with "MUS" + // Reject anything which doesnt have this signature + + filename = M_TempFile("doom.mid"); + + if (IsMid(data, len) && len < MAXMIDLENGTH) + { + M_WriteFile(filename, data, len); + } + else + { + // Assume a MUS file and try to convert + + ConvertMus(data, len, filename); + } + + result = MIDI_LoadFile(filename); + + if (result == NULL) + { + fprintf(stderr, "I_OPL_RegisterSong: Failed to load MID.\n"); + } + + // remove file now + + M_remove(filename); + free(filename); + + return result; +} + +// Is the song playing? + +static boolean I_OPL_MusicIsPlaying(void) +{ + if (!music_initialized) + { + return false; + } + + return num_tracks > 0; +} + +// Shutdown music + +static void I_OPL_ShutdownMusic(void) +{ + if (music_initialized) + { + // Stop currently-playing track, if there is one: + + I_OPL_StopSong(); + + OPL_Shutdown(); + + // Release GENMIDI lump + + W_ReleaseLumpName(DEH_String("genmidi")); + + music_initialized = false; + } +} + +// Initialize music subsystem + +static boolean I_OPL_InitMusic(void) +{ + const char *dmxoption; + opl_init_result_t chip_type; + + OPL_SetSampleRate(snd_samplerate); + + chip_type = OPL_Init(opl_io_port); + if (chip_type == OPL_INIT_NONE) + { + printf("Dude. The Adlib isn't responding.\n"); + return false; + } + + // The DMXOPTION variable must be set to enable OPL3 support. + // As an extension, we also allow it to be set from the config file. + dmxoption = getenv("DMXOPTION"); + if (dmxoption == NULL) + { + dmxoption = snd_dmxoption != NULL ? snd_dmxoption : ""; + } + + if (chip_type == OPL_INIT_OPL3 && strstr(dmxoption, "-opl3") != NULL) + { + opl_opl3mode = 1; + num_opl_voices = OPL_NUM_VOICES * 2; + } + else + { + opl_opl3mode = 0; + num_opl_voices = OPL_NUM_VOICES; + } + + // Secret, undocumented DMXOPTION that reverses the stereo channels + // into their correct orientation. + opl_stereo_correct = strstr(dmxoption, "-reverse") != NULL; + + // Initialize all registers. + + OPL_InitRegisters(opl_opl3mode); + + // Load instruments from GENMIDI lump: + + if (!LoadInstrumentTable()) + { + OPL_Shutdown(); + return false; + } + + InitVoices(); + + tracks = NULL; + num_tracks = 0; + music_initialized = true; + + return true; +} + +const static snddevice_t music_opl_devices[] = +{ + SNDDEVICE_ADLIB, + SNDDEVICE_SB, +}; + +const music_module_t music_opl_module = +{ + music_opl_devices, + arrlen(music_opl_devices), + I_OPL_InitMusic, + I_OPL_ShutdownMusic, + I_OPL_SetMusicVolume, + I_OPL_PauseSong, + I_OPL_ResumeSong, + I_OPL_RegisterSong, + I_OPL_UnRegisterSong, + I_OPL_PlaySong, + I_OPL_StopSong, + I_OPL_MusicIsPlaying, + NULL, // Poll +}; + +void I_SetOPLDriverVer(opl_driver_ver_t ver) +{ + opl_drv_ver = ver; +} + +//---------------------------------------------------------------------- +// +// Development / debug message generation, to help developing GENMIDI +// lumps. +// +//---------------------------------------------------------------------- + +static int NumActiveChannels(void) +{ + int i; + + for (i = MIDI_CHANNELS_PER_TRACK - 1; i >= 0; --i) + { + if (channels[i].instrument != &main_instrs[0]) + { + return i + 1; + } + } + + return 0; +} + +static int ChannelInUse(opl_channel_data_t *channel) +{ + int i; + + for (i = 0; i < voice_alloced_num; i++) + { + if (voice_alloced_list[i]->channel == channel) + { + return 1; + } + } + + return 0; +} + +void I_OPL_DevMessages(char *result, size_t result_len) +{ + char tmp[80]; + int instr_num; + int lines; + int i; + + if (num_tracks == 0) + { + M_snprintf(result, result_len, "No OPL track!"); + return; + } + + M_snprintf(result, result_len, "Tracks:\n"); + lines = 1; + + for (i = 0; i < NumActiveChannels(); ++i) + { + if (channels[i].instrument == NULL) + { + continue; + } + + instr_num = channels[i].instrument - main_instrs; + + M_snprintf(tmp, sizeof(tmp), + "chan %i: %c i#%i (%s)\n", + i, + ChannelInUse(&channels[i]) ? '\'' : ' ', + instr_num + 1, + main_instr_names[instr_num]); + M_StringConcat(result, tmp, result_len); + + ++lines; + } + + M_snprintf(tmp, sizeof(tmp), "\nLast percussion:\n"); + M_StringConcat(result, tmp, result_len); + lines += 2; + + i = (last_perc_count + PERCUSSION_LOG_LEN - 1) % PERCUSSION_LOG_LEN; + + do { + if (last_perc[i] == 0) + { + break; + } + + M_snprintf(tmp, sizeof(tmp), + "%cp#%i (%s)\n", + i == 0 ? '\'' : ' ', + last_perc[i], + percussion_names[last_perc[i] - 35]); + M_StringConcat(result, tmp, result_len); + ++lines; + + i = (i + PERCUSSION_LOG_LEN - 1) % PERCUSSION_LOG_LEN; + } while (lines < 25 && i != last_perc_count); +} + diff --git a/games/NXDoom/src/i_pcsound.c b/games/NXDoom/src/i_pcsound.c new file mode 100644 index 00000000000..c3ec62803b6 --- /dev/null +++ b/games/NXDoom/src/i_pcsound.c @@ -0,0 +1,338 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System interface for PC speaker sound. +// + +#include "SDL.h" +#include + +#include "doomtype.h" + +#include "deh_str.h" +#include "i_sound.h" +#include "m_misc.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "pcsound.h" + +#define TIMER_FREQ 1193181 /* hz */ + +static boolean pcs_initialized = false; + +static SDL_mutex *sound_lock; +static GameMission_t gamemission; + +static uint8_t *current_sound_lump = NULL; +static uint8_t *current_sound_pos = NULL; +static unsigned int current_sound_remaining = 0; +static int current_sound_handle = 0; +static int current_sound_lump_num = -1; + +static const uint16_t divisors[] = { + 0, + 6818, 6628, 6449, 6279, 6087, 5906, 5736, 5575, + 5423, 5279, 5120, 4971, 4830, 4697, 4554, 4435, + 4307, 4186, 4058, 3950, 3836, 3728, 3615, 3519, + 3418, 3323, 3224, 3131, 3043, 2960, 2875, 2794, + 2711, 2633, 2560, 2485, 2415, 2348, 2281, 2213, + 2153, 2089, 2032, 1975, 1918, 1864, 1810, 1757, + 1709, 1659, 1612, 1565, 1521, 1478, 1435, 1395, + 1355, 1316, 1280, 1242, 1207, 1173, 1140, 1107, + 1075, 1045, 1015, 986, 959, 931, 905, 879, + 854, 829, 806, 783, 760, 739, 718, 697, + 677, 658, 640, 621, 604, 586, 570, 553, + 538, 522, 507, 493, 479, 465, 452, 439, + 427, 415, 403, 391, 380, 369, 359, 348, + 339, 329, 319, 310, 302, 293, 285, 276, + 269, 261, 253, 246, 239, 232, 226, 219, + 213, 207, 201, 195, 190, 184, 179, +}; + +static void PCSCallbackFunc(int *duration, int *freq) +{ + unsigned int tone; + + *duration = 1000 / 140; + + if (SDL_LockMutex(sound_lock) < 0) + { + *freq = 0; + return; + } + + if (current_sound_lump != NULL && current_sound_remaining > 0) + { + // Read the next tone + + tone = *current_sound_pos; + + // Use the tone -> frequency lookup table. See pcspkr10.zip + // for a full discussion of this. + // Check we don't overflow the frequency table. + + if (tone < arrlen(divisors) && divisors[tone] != 0) + { + *freq = (int) (TIMER_FREQ / divisors[tone]); + } + else + { + *freq = 0; + } + + ++current_sound_pos; + --current_sound_remaining; + } + else + { + *freq = 0; + } + + SDL_UnlockMutex(sound_lock); +} + +static boolean CachePCSLump(sfxinfo_t *sfxinfo) +{ + int lumplen; + int headerlen; + + // Free the current sound lump back to the cache + + if (current_sound_lump != NULL) + { + W_ReleaseLumpNum(current_sound_lump_num); + current_sound_lump = NULL; + } + + // Load from WAD + + current_sound_lump = W_CacheLumpNum(sfxinfo->lumpnum, PU_STATIC); + lumplen = W_LumpLength(sfxinfo->lumpnum); + + // Read header + + if (current_sound_lump[0] != 0x00 || current_sound_lump[1] != 0x00) + { + return false; + } + + headerlen = (current_sound_lump[3] << 8) | current_sound_lump[2]; + + if (headerlen > lumplen - 4) + { + return false; + } + + // Header checks out ok + + current_sound_remaining = headerlen; + current_sound_pos = current_sound_lump + 4; + current_sound_lump_num = sfxinfo->lumpnum; + + return true; +} + +// These Doom PC speaker sounds are not played - this can be seen in the +// Heretic source code, where there are remnants of this left over +// from Doom. + +static boolean IsDisabledSound(sfxinfo_t *sfxinfo) +{ + int i; + const char *disabled_sounds[] = { + "posact", + "bgact", + "dmact", + "dmpain", + "popain", + "sawidl", + "rifle", + }; + + for (i=0; iname, disabled_sounds[i])) + { + return true; + } + } + + return false; +} + +static int I_PCS_StartSound(sfxinfo_t *sfxinfo, + int channel, + int vol, + int sep, + int pitch) +{ + int result; + + if (!pcs_initialized) + { + return -1; + } + + if (IsDisabledSound(sfxinfo)) + { + return -1; + } + + if (SDL_LockMutex(sound_lock) < 0) + { + return -1; + } + + result = CachePCSLump(sfxinfo); + + if (result) + { + current_sound_handle = channel; + } + + SDL_UnlockMutex(sound_lock); + + if (result) + { + return channel; + } + else + { + return -1; + } +} + +static void I_PCS_StopSound(int handle) +{ + if (!pcs_initialized) + { + return; + } + + if (SDL_LockMutex(sound_lock) < 0) + { + return; + } + + // If this is the channel currently playing, immediately end it. + + if (current_sound_handle == handle) + { + current_sound_remaining = 0; + } + + SDL_UnlockMutex(sound_lock); +} + +// +// Retrieve the raw data lump index +// for a given SFX name. +// + +static int I_PCS_GetSfxLumpNum(sfxinfo_t* sfx) +{ + char namebuf[9]; + + if (gamemission == doom || gamemission == strife) + { + M_snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String(sfx->name)); + + if (gamemission == strife && W_CheckNumForName(namebuf) == -1) + { + // Missing sounds replaced with DPRIFLE. + M_snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String("rifle")); + } + } + else + { + M_StringCopy(namebuf, DEH_String(sfx->name), sizeof(namebuf)); + } + + return W_GetNumForName(namebuf); +} + + +static boolean I_PCS_SoundIsPlaying(int handle) +{ + if (!pcs_initialized) + { + return false; + } + + if (handle != current_sound_handle) + { + return false; + } + + return current_sound_lump != NULL && current_sound_remaining > 0; +} + +static boolean I_PCS_InitSound(GameMission_t mission) +{ + gamemission = mission; + + // Use the sample rate from the configuration file + + PCSound_SetSampleRate(snd_samplerate); + + // Initialize the PC speaker subsystem. + + pcs_initialized = PCSound_Init(PCSCallbackFunc); + + if (pcs_initialized) + { + sound_lock = SDL_CreateMutex(); + } + + return pcs_initialized; +} + +static void I_PCS_ShutdownSound(void) +{ + if (pcs_initialized) + { + PCSound_Shutdown(); + } +} + +static void I_PCS_UpdateSound(void) +{ + // no-op. +} + +void I_PCS_UpdateSoundParams(int channel, int vol, int sep) +{ + // no-op. +} + +static const snddevice_t sound_pcsound_devices[] = +{ + SNDDEVICE_PCSPEAKER, +}; + +const sound_module_t sound_pcsound_module = +{ + sound_pcsound_devices, + arrlen(sound_pcsound_devices), + I_PCS_InitSound, + I_PCS_ShutdownSound, + I_PCS_GetSfxLumpNum, + I_PCS_UpdateSound, + I_PCS_UpdateSoundParams, + I_PCS_StartSound, + I_PCS_StopSound, + I_PCS_SoundIsPlaying, +}; + diff --git a/games/NXDoom/src/i_sdlmusic.c b/games/NXDoom/src/i_sdlmusic.c new file mode 100644 index 00000000000..70502d0b203 --- /dev/null +++ b/games/NXDoom/src/i_sdlmusic.c @@ -0,0 +1,473 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System interface for music. +// + + +#include +#include +#include +#include + +#include "SDL.h" + +#include "config.h" +#include "doomtype.h" +#include "memio.h" +#include "mus2mid.h" + +#include "deh_str.h" +#include "gusconf.h" +#include "i_sound.h" +#include "i_system.h" +#include "i_swap.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" +#include "sha1.h" +#include "w_wad.h" +#include "z_zone.h" + + +char *timidity_cfg_path = ""; + +static char *temp_timidity_cfg = NULL; + +// If the temp_timidity_cfg config variable is set, generate a "wrapper" +// config file for Timidity to point to the actual config file. This +// is needed to inject a "dir" command so that the patches are read +// relative to the actual config file. + +static boolean WriteWrapperTimidityConfig(char *write_path) +{ + char *path; + FILE *fstream; + + if (!strcmp(timidity_cfg_path, "")) + { + return false; + } + + fstream = M_fopen(write_path, "w"); + + if (fstream == NULL) + { + return false; + } + + path = M_DirName(timidity_cfg_path); + fprintf(fstream, "dir %s\n", path); + free(path); + + fprintf(fstream, "source %s\n", timidity_cfg_path); + fclose(fstream); + + return true; +} + + +// putenv requires a non-const string whose lifetime is the whole program +// so can't use a string directly, have to do this silliness +static char sdl_mixer_disable_fluidsynth[] = "SDL_MIXER_DISABLE_FLUIDSYNTH=1"; + + +void I_InitTimidityConfig(void) +{ + char *env_string; + boolean success; + + temp_timidity_cfg = M_TempFile("timidity.cfg"); + + if (snd_musicdevice == SNDDEVICE_GUS) + { + success = GUS_WriteConfig(temp_timidity_cfg); + } + else + { + success = WriteWrapperTimidityConfig(temp_timidity_cfg); + } + + // Set the TIMIDITY_CFG environment variable to point to the temporary + // config file. + if (success) + { + env_string = M_StringJoin("TIMIDITY_CFG=", temp_timidity_cfg, NULL); + putenv(env_string); + // env_string deliberately not freed; see putenv manpage + + // If we're explicitly configured to use Timidity (either through + // timidity_cfg_path or GUS mode), then disable Fluidsynth, because + // SDL_mixer considers Fluidsynth a higher priority than Timidity and + // therefore can end up circumventing Timidity entirely. + putenv(sdl_mixer_disable_fluidsynth); + } + else + { + free(temp_timidity_cfg); + temp_timidity_cfg = NULL; + } +} + + +#ifndef DISABLE_SDL2MIXER + +#include "SDL_mixer.h" + + +#define MAXMIDLENGTH (96 * 1024) + +static boolean music_initialized = false; + +// If this is true, this module initialized SDL sound and has the +// responsibility to shut it down + +static boolean sdl_was_initialized = false; + +static boolean musicpaused = false; +static int current_music_volume; + + +// Remove the temporary config file generated by I_InitTimidityConfig(). + +static void RemoveTimidityConfig(void) +{ + if (temp_timidity_cfg != NULL) + { + M_remove(temp_timidity_cfg); + free(temp_timidity_cfg); + } +} + +// Shutdown music + +static void I_SDL_ShutdownMusic(void) +{ + if (music_initialized) + { + Mix_HaltMusic(); + music_initialized = false; + + if (sdl_was_initialized) + { + Mix_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + sdl_was_initialized = false; + } + } +} + +static boolean SDLIsInitialized(void) +{ + int freq, channels; + Uint16 format; + + return Mix_QuerySpec(&freq, &format, &channels) != 0; +} + +#ifdef _WIN32 +// putenv requires a non-const string whose lifetime is the whole program +static char sdl_mixer_disable_nativemidi[] = "SDL_MIXER_DISABLE_NATIVEMIDI=1"; +#endif + +// Initialize music subsystem +static boolean I_SDL_InitMusic(void) +{ + // If SDL_mixer is not initialized, we have to initialize it + // and have the responsibility to shut it down later on. + + if (SDLIsInitialized()) + { + music_initialized = true; + } + else + { + if (SDL_Init(SDL_INIT_AUDIO) < 0) + { + fprintf(stderr, "Unable to set up sound.\n"); + } + else if (Mix_OpenAudioDevice(snd_samplerate, AUDIO_S16SYS, 2, 1024, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) + { + fprintf(stderr, "Error initializing SDL_mixer: %s\n", + Mix_GetError()); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } + else + { + SDL_PauseAudio(0); + + sdl_was_initialized = true; + music_initialized = true; + } + } + + #ifdef _WIN32 + // Never let SDL Mixer use native midi on Windows. Avoids SDL Mixer bug + // where music volume affects global application volume. + putenv(sdl_mixer_disable_nativemidi); + #endif + + // Initialize SDL_Mixer for MIDI music playback + Mix_Init(MIX_INIT_MID); + + // Once initialization is complete, the temporary Timidity config + // file can be removed. + + RemoveTimidityConfig(); + + // If snd_musiccmd is set, we need to call Mix_SetMusicCMD to + // configure an external music playback program. + + if (strlen(snd_musiccmd) > 0) + { + Mix_SetMusicCMD(snd_musiccmd); + } + + return music_initialized; +} + +// +// SDL_mixer's native MIDI music playing does not pause properly. +// As a workaround, set the volume to 0 when paused. +// + +static void UpdateMusicVolume(void) +{ + int vol; + + if (musicpaused) + { + vol = 0; + } + else + { + vol = (current_music_volume * MIX_MAX_VOLUME) / 127; + } + + Mix_VolumeMusic(vol); +} + +// Set music volume (0 - 127) + +static void I_SDL_SetMusicVolume(int volume) +{ + // Internal state variable. + current_music_volume = volume; + + UpdateMusicVolume(); +} + +// Start playing a mid + +static void I_SDL_PlaySong(void *handle, boolean looping) +{ + int loops; + + if (!music_initialized) + { + return; + } + + if (handle == NULL) + { + return; + } + + if (looping) + { + loops = -1; + } + else + { + loops = 1; + } + + Mix_PlayMusic((Mix_Music *) handle, loops); +} + +static void I_SDL_PauseSong(void) +{ + if (!music_initialized) + { + return; + } + + musicpaused = true; + + UpdateMusicVolume(); +} + +static void I_SDL_ResumeSong(void) +{ + if (!music_initialized) + { + return; + } + + musicpaused = false; + + UpdateMusicVolume(); +} + +static void I_SDL_StopSong(void) +{ + if (!music_initialized) + { + return; + } + + Mix_HaltMusic(); +} + +static void I_SDL_UnRegisterSong(void *handle) +{ + Mix_Music *music = (Mix_Music *) handle; + + if (!music_initialized) + { + return; + } + + if (handle != NULL) + { + Mix_FreeMusic(music); + } +} + +// Determine whether memory block is a .mid file + +static boolean IsMid(byte *mem, int len) +{ + return len > 4 && !memcmp(mem, "MThd", 4); +} + +static boolean ConvertMus(byte *musdata, int len, const char *filename) +{ + MEMFILE *instream; + MEMFILE *outstream; + void *outbuf; + size_t outbuf_len; + int result; + + instream = mem_fopen_read(musdata, len); + outstream = mem_fopen_write(); + + result = mus2mid(instream, outstream); + + if (result == 0) + { + mem_get_buf(outstream, &outbuf, &outbuf_len); + + M_WriteFile(filename, outbuf, outbuf_len); + } + + mem_fclose(instream); + mem_fclose(outstream); + + return result; +} + +static void *I_SDL_RegisterSong(void *data, int len) +{ + char *filename; + Mix_Music *music; + + if (!music_initialized) + { + return NULL; + } + + // MUS files begin with "MUS" + // Reject anything which doesnt have this signature + + filename = M_TempFile("doom.mid"); + + if (IsMid(data, len) && len < MAXMIDLENGTH) + { + M_WriteFile(filename, data, len); + } + else + { + // Assume a MUS file and try to convert + + ConvertMus(data, len, filename); + } + + // Load the MIDI. In an ideal world we'd be using Mix_LoadMUS_RW() + // by now, but Mix_SetMusicCMD() only works with Mix_LoadMUS(), so + // we have to generate a temporary file. + + music = Mix_LoadMUS(filename); + if (music == NULL) + { + // Failed to load + fprintf(stderr, "Error loading midi: %s\n", Mix_GetError()); + } + + // Remove the temporary MIDI file; however, when using an external + // MIDI program we can't delete the file. Otherwise, the program + // won't find the file to play. This means we leave a mess on + // disk :( + + if (strlen(snd_musiccmd) == 0) + { + M_remove(filename); + } + + free(filename); + + return music; +} + +// Is the song playing? +static boolean I_SDL_MusicIsPlaying(void) +{ + if (!music_initialized) + { + return false; + } + + return Mix_PlayingMusic(); +} + +static const snddevice_t music_sdl_devices[] = +{ + SNDDEVICE_PAS, + SNDDEVICE_GUS, + SNDDEVICE_WAVEBLASTER, + SNDDEVICE_SOUNDCANVAS, + SNDDEVICE_GENMIDI, + SNDDEVICE_AWE32, +}; + +const music_module_t music_sdl_module = +{ + music_sdl_devices, + arrlen(music_sdl_devices), + I_SDL_InitMusic, + I_SDL_ShutdownMusic, + I_SDL_SetMusicVolume, + I_SDL_PauseSong, + I_SDL_ResumeSong, + I_SDL_RegisterSong, + I_SDL_UnRegisterSong, + I_SDL_PlaySong, + I_SDL_StopSong, + I_SDL_MusicIsPlaying, + NULL, // Poll +}; + + +#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/src/i_sdlsound.c b/games/NXDoom/src/i_sdlsound.c new file mode 100644 index 00000000000..18a51a09d86 --- /dev/null +++ b/games/NXDoom/src/i_sdlsound.c @@ -0,0 +1,1146 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// Copyright(C) 2008 David Flater +// +// 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. +// +// DESCRIPTION: +// System interface for sound. +// + +#include "config.h" + +#include +#include +#include +#include +#include "SDL.h" + +#ifdef HAVE_LIBSAMPLERATE +#include +#endif + +#include "deh_str.h" +#include "i_sound.h" +#include "i_system.h" +#include "i_swap.h" +#include "m_argv.h" +#include "m_misc.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "doomtype.h" + + +int use_libsamplerate = 0; + +// Scale factor used when converting libsamplerate floating point numbers +// to integers. Too high means the sounds can clip; too low means they +// will be too quiet. This is an amount that should avoid clipping most +// of the time: with all the Doom IWAD sound effects, at least. If a PWAD +// is used, clipping might occur. + +float libsamplerate_scale = 0.65f; + + +#ifndef DISABLE_SDL2MIXER + +#include "SDL_mixer.h" + + +#define LOW_PASS_FILTER +//#define DEBUG_DUMP_WAVS +#define NUM_CHANNELS 16 + +typedef struct allocated_sound_s allocated_sound_t; + +struct allocated_sound_s +{ + sfxinfo_t *sfxinfo; + Mix_Chunk chunk; + int use_count; + int pitch; + allocated_sound_t *prev, *next; +}; + +static boolean sound_initialized = false; + +static allocated_sound_t *channels_playing[NUM_CHANNELS]; + +static int mixer_freq; +static Uint16 mixer_format; +static int mixer_channels; +static boolean use_sfx_prefix; +static boolean (*ExpandSoundData)(sfxinfo_t *sfxinfo, + byte *data, + int samplerate, + int length) = NULL; + +// Doubly-linked list of allocated sounds. +// When a sound is played, it is moved to the head, so that the oldest +// sounds not used recently are at the tail. + +static allocated_sound_t *allocated_sounds_head = NULL; +static allocated_sound_t *allocated_sounds_tail = NULL; +static int allocated_sounds_size = 0; + + +// Hook a sound into the linked list at the head. + +static void AllocatedSoundLink(allocated_sound_t *snd) +{ + snd->prev = NULL; + + snd->next = allocated_sounds_head; + allocated_sounds_head = snd; + + if (allocated_sounds_tail == NULL) + { + allocated_sounds_tail = snd; + } + else + { + snd->next->prev = snd; + } +} + +// Unlink a sound from the linked list. + +static void AllocatedSoundUnlink(allocated_sound_t *snd) +{ + if (snd->prev == NULL) + { + allocated_sounds_head = snd->next; + } + else + { + snd->prev->next = snd->next; + } + + if (snd->next == NULL) + { + allocated_sounds_tail = snd->prev; + } + else + { + snd->next->prev = snd->prev; + } +} + +static void FreeAllocatedSound(allocated_sound_t *snd) +{ + // Unlink from linked list. + + AllocatedSoundUnlink(snd); + + // Keep track of the amount of allocated sound data: + + allocated_sounds_size -= snd->chunk.alen; + + free(snd); +} + +// Search from the tail backwards along the allocated sounds list, find +// and free a sound that is not in use, to free up memory. Return true +// for success. + +static boolean FindAndFreeSound(void) +{ + allocated_sound_t *snd; + + snd = allocated_sounds_tail; + + while (snd != NULL) + { + if (snd->use_count == 0) + { + FreeAllocatedSound(snd); + return true; + } + + snd = snd->prev; + } + + // No available sounds to free... + + return false; +} + +// Enforce SFX cache size limit. We are just about to allocate "len" +// bytes on the heap for a new sound effect, so free up some space +// so that we keep allocated_sounds_size < snd_cachesize + +static void ReserveCacheSpace(size_t len) +{ + if (snd_cachesize <= 0) + { + return; + } + + // Keep freeing sound effects that aren't currently being played, + // until there is enough space for the new sound. + + while (allocated_sounds_size + len > snd_cachesize) + { + // Free a sound. If there is nothing more to free, stop. + + if (!FindAndFreeSound()) + { + break; + } + } +} + +// Allocate a block for a new sound effect. + +static allocated_sound_t *AllocateSound(sfxinfo_t *sfxinfo, size_t len) +{ + allocated_sound_t *snd; + + // Keep allocated sounds within the cache size. + + ReserveCacheSpace(len); + + // Allocate the sound structure and data. The data will immediately + // follow the structure, which acts as a header. + + do + { + snd = malloc(sizeof(allocated_sound_t) + len); + + // Out of memory? Try to free an old sound, then loop round + // and try again. + + if (snd == NULL && !FindAndFreeSound()) + { + return NULL; + } + + } while (snd == NULL); + + // Skip past the chunk structure for the audio buffer + + snd->chunk.abuf = (byte *) (snd + 1); + snd->chunk.alen = len; + snd->chunk.allocated = 1; + snd->chunk.volume = MIX_MAX_VOLUME; + snd->pitch = NORM_PITCH; + + snd->sfxinfo = sfxinfo; + snd->use_count = 0; + + // Keep track of how much memory all these cached sounds are using... + + allocated_sounds_size += len; + + AllocatedSoundLink(snd); + + return snd; +} + +// Lock a sound, to indicate that it may not be freed. + +static void LockAllocatedSound(allocated_sound_t *snd) +{ + // Increase use count, to stop the sound being freed. + + ++snd->use_count; + + //printf("++ %s: Use count=%i\n", snd->sfxinfo->name, snd->use_count); + + // When we use a sound, re-link it into the list at the head, so + // that the oldest sounds fall to the end of the list for freeing. + + AllocatedSoundUnlink(snd); + AllocatedSoundLink(snd); +} + +// Unlock a sound to indicate that it may now be freed. + +static void UnlockAllocatedSound(allocated_sound_t *snd) +{ + if (snd->use_count <= 0) + { + I_Error("Sound effect released more times than it was locked..."); + } + + --snd->use_count; + + //printf("-- %s: Use count=%i\n", snd->sfxinfo->name, snd->use_count); +} + +// Search through the list of allocated sounds and return the one that matches +// the supplied sfxinfo entry and pitch level. + +static allocated_sound_t * GetAllocatedSoundBySfxInfoAndPitch(sfxinfo_t *sfxinfo, int pitch) +{ + allocated_sound_t * p = allocated_sounds_head; + + while (p != NULL) + { + if (p->sfxinfo == sfxinfo && p->pitch == pitch) + { + return p; + } + p = p->next; + } + + return NULL; +} + +// Allocate a new sound chunk and pitch-shift an existing sound up-or-down +// into it. + +static allocated_sound_t * PitchShift(allocated_sound_t *insnd, int pitch) +{ + allocated_sound_t * outsnd; + Sint16 *inp, *outp; + Sint16 *srcbuf, *dstbuf; + Uint32 srclen, dstlen; + + srcbuf = (Sint16 *)insnd->chunk.abuf; + srclen = insnd->chunk.alen; + + // determine ratio pitch:NORM_PITCH and apply to srclen, then invert. + // This is an approximation of vanilla behaviour based on measurements + dstlen = (int)((1 + (1 - (float)pitch / NORM_PITCH)) * srclen); + + // ensure that the new buffer is an even length + if ((dstlen % 2) == 0) + { + dstlen++; + } + + outsnd = AllocateSound(insnd->sfxinfo, dstlen); + + if (!outsnd) + { + return NULL; + } + + outsnd->pitch = pitch; + dstbuf = (Sint16 *)outsnd->chunk.abuf; + + // loop over output buffer. find corresponding input cell, copy over + for (outp = dstbuf; outp < dstbuf + dstlen/2; ++outp) + { + inp = srcbuf + (int)((float)(outp - dstbuf) / dstlen * srclen); + *outp = *inp; + } + + return outsnd; +} + +// When a sound stops, check if it is still playing. If it is not, +// we can mark the sound data as CACHE to be freed back for other +// means. + +static void ReleaseSoundOnChannel(int channel) +{ + allocated_sound_t *snd = channels_playing[channel]; + + Mix_HaltChannel(channel); + + if (snd == NULL) + { + return; + } + + channels_playing[channel] = NULL; + + UnlockAllocatedSound(snd); + + // if the sound is a pitch-shift and it's not in use, immediately + // free it + if (snd->pitch != NORM_PITCH && snd->use_count <= 0) + { + FreeAllocatedSound(snd); + } +} + +#ifdef HAVE_LIBSAMPLERATE + +// Returns the conversion mode for libsamplerate to use. + +static int SRC_ConversionMode(void) +{ + switch (use_libsamplerate) + { + // 0 = disabled + + default: + case 0: + return -1; + + // Ascending numbers give higher quality + + case 1: + return SRC_LINEAR; + case 2: + return SRC_ZERO_ORDER_HOLD; + case 3: + return SRC_SINC_FASTEST; + case 4: + return SRC_SINC_MEDIUM_QUALITY; + case 5: + return SRC_SINC_BEST_QUALITY; + } +} + +// libsamplerate-based generic sound expansion function for any sample rate +// unsigned 8 bits --> signed 16 bits +// mono --> stereo +// samplerate --> mixer_freq +// Returns number of clipped samples. +// DWF 2008-02-10 with cleanups by Simon Howard. + +static boolean ExpandSoundData_SRC(sfxinfo_t *sfxinfo, + byte *data, + int samplerate, + int length) +{ + SRC_DATA src_data; + float *data_in; + uint32_t i, abuf_index=0, clipped=0; +// uint32_t alen; + int retn; + int16_t *expanded; + allocated_sound_t *snd; + Mix_Chunk *chunk; + + src_data.input_frames = length; + data_in = malloc(length * sizeof(float)); + src_data.data_in = data_in; + src_data.src_ratio = (double)mixer_freq / samplerate; + + // We include some extra space here in case of rounding-up. + src_data.output_frames = src_data.src_ratio * length + (mixer_freq / 4); + src_data.data_out = malloc(src_data.output_frames * sizeof(float)); + + assert(src_data.data_in != NULL && src_data.data_out != NULL); + + // Convert input data to floats + + for (i=0; ichunk; + expanded = (int16_t *) chunk->abuf; + + // Convert the result back into 16-bit integers. + + for (i=0; i INT16_MAX) + { + cvtval_i = INT16_MAX; + ++clipped; + } + + // Left and right channels + + expanded[abuf_index++] = cvtval_i; + expanded[abuf_index++] = cvtval_i; + } + + free(data_in); + free(src_data.data_out); + + if (clipped > 0) + { + fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", + sfxinfo->name, clipped, + 400.0 * clipped / chunk->alen); + } + + return true; +} + +#endif + +static boolean ConvertibleRatio(int freq1, int freq2) +{ + int ratio; + + if (freq1 > freq2) + { + return ConvertibleRatio(freq2, freq1); + } + else if ((freq2 % freq1) != 0) + { + // Not in a direct ratio + + return false; + } + else + { + // Check the ratio is a power of 2 + + ratio = freq2 / freq1; + + while ((ratio & 1) == 0) + { + ratio = ratio >> 1; + } + + return ratio == 1; + } +} + +#ifdef DEBUG_DUMP_WAVS + +// Debug code to dump resampled sound effects to WAV files for analysis. + +static void WriteWAV(char *filename, byte *data, + uint32_t length, int samplerate) +{ + FILE *wav; + unsigned int i; + unsigned short s; + + wav = M_fopen(filename, "wb"); + + // Header + + fwrite("RIFF", 1, 4, wav); + i = LONG(36 + samplerate); + fwrite(&i, 4, 1, wav); + fwrite("WAVE", 1, 4, wav); + + // Subchunk 1 + + fwrite("fmt ", 1, 4, wav); + i = LONG(16); + fwrite(&i, 4, 1, wav); // Length + s = SHORT(1); + fwrite(&s, 2, 1, wav); // Format (PCM) + s = SHORT(2); + fwrite(&s, 2, 1, wav); // Channels (2=stereo) + i = LONG(samplerate); + fwrite(&i, 4, 1, wav); // Sample rate + i = LONG(samplerate * 2 * 2); + fwrite(&i, 4, 1, wav); // Byte rate (samplerate * stereo * 16 bit) + s = SHORT(2 * 2); + fwrite(&s, 2, 1, wav); // Block align (stereo * 16 bit) + s = SHORT(16); + fwrite(&s, 2, 1, wav); // Bits per sample (16 bit) + + // Data subchunk + + fwrite("data", 1, 4, wav); + i = LONG(length); + fwrite(&i, 4, 1, wav); // Data length + fwrite(data, 1, length, wav); // Data + + fclose(wav); +} + +#endif + +// Generic sound expansion function for any sample rate. +// Returns number of clipped samples (always 0). + +static boolean ExpandSoundData_SDL(sfxinfo_t *sfxinfo, + byte *data, + int samplerate, + int length) +{ + SDL_AudioCVT convertor; + allocated_sound_t *snd; + Mix_Chunk *chunk; + uint32_t expanded_length; + + // Calculate the length of the expanded version of the sample. + + expanded_length = (uint32_t) ((((uint64_t) length) * mixer_freq) / samplerate); + + // Double up twice: 8 -> 16 bit and mono -> stereo + + expanded_length *= 4; + + // Allocate a chunk in which to expand the sound + + snd = AllocateSound(sfxinfo, expanded_length); + + if (snd == NULL) + { + return false; + } + + chunk = &snd->chunk; + + // If we can, use the standard / optimized SDL conversion routines. + + if (samplerate <= mixer_freq + && ConvertibleRatio(samplerate, mixer_freq) + && SDL_BuildAudioCVT(&convertor, + AUDIO_U8, 1, samplerate, + mixer_format, mixer_channels, mixer_freq)) + { + convertor.len = length; + convertor.buf = malloc(convertor.len * convertor.len_mult); + assert(convertor.buf != NULL); + memcpy(convertor.buf, data, length); + + SDL_ConvertAudio(&convertor); + + memcpy(chunk->abuf, convertor.buf, chunk->alen); + free(convertor.buf); + } + else + { + Sint16 *expanded = (Sint16 *) chunk->abuf; + int expanded_length; + int expand_ratio; + int i; + + // Generic expansion if conversion does not work: + // + // SDL's audio conversion only works for rate conversions that are + // powers of 2; if the two formats are not in a direct power of 2 + // ratio, do this naive conversion instead. + + // number of samples in the converted sound + + expanded_length = ((uint64_t) length * mixer_freq) / samplerate; + expand_ratio = (length << 8) / expanded_length; + + for (i=0; i> 8; + + sample = data[src] | (data[src] << 8); + sample -= 32768; + + // expand 8->16 bits, mono->stereo + + expanded[i * 2] = expanded[i * 2 + 1] = sample; + } + +#ifdef LOW_PASS_FILTER + // Perform a low-pass filter on the upscaled sound to filter + // out high-frequency noise from the conversion process. + + { + float rc, dt, alpha; + + // Low-pass filter for cutoff frequency f: + // + // For sampling rate r, dt = 1 / r + // rc = 1 / 2*pi*f + // alpha = dt / (rc + dt) + + // Filter to the half sample rate of the original sound effect + // (maximum frequency, by nyquist) + + dt = 1.0f / mixer_freq; + rc = 1.0f / (3.14f * samplerate); + alpha = dt / (rc + dt); + + // Both channels are processed in parallel, hence [i-2]: + + for (i=2; ilumpnum; + data = W_CacheLumpNum(lumpnum, PU_STATIC); + lumplen = W_LumpLength(lumpnum); + + // Check the header, and ensure this is a valid sound + + if (lumplen < 8 + || data[0] != 0x03 || data[1] != 0x00) + { + // Invalid sound + + return false; + } + + // 16 bit sample rate field, 32 bit length field + + samplerate = (data[3] << 8) | data[2]; + length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; + + // If the header specifies that the length of the sound is greater than + // the length of the lump itself, this is an invalid sound lump + + // We also discard sound lumps that are less than 49 samples long, + // as this is how DMX behaves - although the actual cut-off length + // seems to vary slightly depending on the sample rate. This needs + // further investigation to better understand the correct + // behavior. + + if (length > lumplen - 8 || length <= 48) + { + return false; + } + + // The DMX sound library seems to skip the first 16 and last 16 + // bytes of the lump - reason unknown. + + data += 16; + length -= 32; + + // Sample rate conversion + + if (!ExpandSoundData(sfxinfo, data + 8, samplerate, length)) + { + return false; + } + +#ifdef DEBUG_DUMP_WAVS + { + char filename[16]; + allocated_sound_t * snd; + + M_snprintf(filename, sizeof(filename), "%s.wav", + DEH_String(sfxinfo->name)); + snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, NORM_PITCH); + WriteWAV(filename, snd->chunk.abuf, snd->chunk.alen,mixer_freq); + } +#endif + + // don't need the original lump any more + + W_ReleaseLumpNum(lumpnum); + + return true; +} + +static void GetSfxLumpName(sfxinfo_t *sfx, char *buf, size_t buf_len) +{ + // Linked sfx lumps? Get the lump number for the sound linked to. + + if (sfx->link != NULL) + { + sfx = sfx->link; + } + + // Doom adds a DS* prefix to sound lumps; Heretic and Hexen don't + // do this. + + if (use_sfx_prefix) + { + M_snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name)); + } + else + { + M_StringCopy(buf, DEH_String(sfx->name), buf_len); + } +} + +// Preload all the sound effects - stops nasty ingame freezes + +static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds) +{ + char namebuf[9]; + int i; + + printf("I_SDL_PrecacheSounds: Precaching all sound effects.."); + + for (i=0; i= NUM_CHANNELS) + { + return; + } + + left = ((254 - sep) * vol) / 127; + right = ((sep) * vol) / 127; + + if (left < 0) left = 0; + else if ( left > 255) left = 255; + if (right < 0) right = 0; + else if (right > 255) right = 255; + + Mix_SetPanning(handle, left, right); +} + +// +// Starting a sound means adding it +// to the current list of active sounds +// in the internal channels. +// As the SFX info struct contains +// e.g. a pointer to the raw data, +// it is ignored. +// As our sound handling does not handle +// priority, it is ignored. +// Pitching (that is, increased speed of playback) +// is set, but currently not used by mixing. +// + +static int I_SDL_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch) +{ + allocated_sound_t *snd; + + if (!sound_initialized || channel < 0 || channel >= NUM_CHANNELS) + { + return -1; + } + + // Release a sound effect if there is already one playing + // on this channel + + ReleaseSoundOnChannel(channel); + + // Get the sound data + + if (!LockSound(sfxinfo)) + { + return -1; + } + + snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, pitch); + + if (snd == NULL) + { + allocated_sound_t *newsnd; + // fetch the base sound effect, un-pitch-shifted + snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, NORM_PITCH); + + if (snd == NULL) + { + return -1; + } + + if (snd_pitchshift) + { + newsnd = PitchShift(snd, pitch); + + if (newsnd) + { + LockAllocatedSound(newsnd); + UnlockAllocatedSound(snd); + snd = newsnd; + } + } + } + else + { + LockAllocatedSound(snd); + } + + // play sound + + Mix_PlayChannel(channel, &snd->chunk, 0); + + channels_playing[channel] = snd; + + // set separation, etc. + + I_SDL_UpdateSoundParams(channel, vol, sep); + + return channel; +} + +static void I_SDL_StopSound(int handle) +{ + if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS) + { + return; + } + + // Sound data is no longer needed; release the + // sound data being used for this channel + + ReleaseSoundOnChannel(handle); +} + + +static boolean I_SDL_SoundIsPlaying(int handle) +{ + if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS) + { + return false; + } + + return Mix_Playing(handle); +} + +// +// Periodically called to update the sound system +// + +static void I_SDL_UpdateSound(void) +{ + int i; + + // Check all channels to see if a sound has finished + + for (i=0; i limit) + { + return (1 << n); + } + } + + // Should never happen? + + return 1024; +} + +static boolean I_SDL_InitSound(GameMission_t mission) +{ + int i; + + use_sfx_prefix = (mission == doom || mission == strife); + + // No sounds yet + for (i=0; i +#include + +#include "config.h" +#include "doomtype.h" + +#include "gusconf.h" +#include "i_sound.h" +#include "i_video.h" +#include "m_argv.h" +#include "m_config.h" + +#ifndef DISABLE_SDL2MIXER + +#include "SDL_mixer.h" + +#endif // DISABLE_SDL2MIXER + + +// Sound sample rate to use for digital output (Hz) + +int snd_samplerate = 44100; + +// Maximum number of bytes to dedicate to allocated sound effects. +// (Default: 64MB) + +int snd_cachesize = 64 * 1024 * 1024; + +// Config variable that controls the sound buffer size. +// We default to 28ms (1000 / 35fps = 1 buffer per tic). + +int snd_maxslicetime_ms = 28; + +// External command to invoke to play back music. + +char *snd_musiccmd = ""; + +// Whether to vary the pitch of sound effects +// Each game will set the default differently + +int snd_pitchshift = -1; + +int snd_musicdevice = SNDDEVICE_SB; +int snd_sfxdevice = SNDDEVICE_SB; + +// Low-level sound and music modules we are using +static const sound_module_t *sound_module; +static const music_module_t *music_module; + +// If true, the music pack module was successfully initialized. +static boolean music_packs_active = false; + +// This is either equal to music_module or &music_pack_module, +// depending on whether the current track is substituted. +static const music_module_t *active_music_module; + + +// DOS-specific options: These are unused but should be maintained +// so that the config file can be shared between chocolate +// doom and doom.exe + +static int snd_sbport = 0; +static int snd_sbirq = 0; +static int snd_sbdma = 0; +static int snd_mport = 0; + +// Compiled-in sound modules: + +static const sound_module_t *sound_modules[] = +{ +#ifndef DISABLE_SDL2MIXER + &sound_sdl_module, +#endif // DISABLE_SDL2MIXER + &sound_pcsound_module, + NULL, +}; + +// Compiled-in music modules: + +static const music_module_t *music_modules[] = +{ +#ifdef _WIN32 + &music_win_module, +#endif +#ifdef HAVE_FLUIDSYNTH + &music_fl_module, +#endif // HAVE_FLUIDSYNTH +#ifndef DISABLE_SDL2MIXER + &music_sdl_module, +#endif // DISABLE_SDL2MIXER + &music_opl_module, + NULL, +}; + +// Check if a sound device is in the given list of devices + +static boolean SndDeviceInList(snddevice_t device, const snddevice_t *list, + int len) +{ + int i; + + for (i=0; isound_devices, + sound_modules[i]->num_sound_devices)) + { + // Initialize the module + + if (sound_modules[i]->Init(mission)) + { + sound_module = sound_modules[i]; + return; + } + } + } +} + +// Initialize music according to snd_musicdevice. + +static void InitMusicModule(void) +{ + int i; + + music_module = NULL; + + for (i=0; music_modules[i] != NULL; ++i) + { + // Is the music device in the list of devices supported + // by this module? + + if (SndDeviceInList(snd_musicdevice, + music_modules[i]->sound_devices, + music_modules[i]->num_sound_devices)) + { + #ifdef _WIN32 + // Skip the native Windows MIDI module if using Timidity. + + if (strcmp(timidity_cfg_path, "") && + music_modules[i] == &music_win_module) + { + continue; + } + #endif + + // Initialize the module + + if (music_modules[i]->Init()) + { + music_module = music_modules[i]; + return; + } + } + } +} + +// +// Initializes sound stuff, including volume +// Sets channels, SFX and music volume, +// allocates channel buffer, sets S_sfx lookup. +// + +void I_InitSound(GameMission_t mission) +{ + boolean nosound, nosfx, nomusic, nomusicpacks; + + //! + // @vanilla + // + // Disable all sound output. + // + + nosound = M_CheckParm("-nosound") > 0; + + //! + // @vanilla + // + // Disable sound effects. + // + + nosfx = M_CheckParm("-nosfx") > 0; + + //! + // @vanilla + // + // Disable music. + // + + nomusic = M_CheckParm("-nomusic") > 0; + + //! + // + // Disable substitution music packs. + // + + nomusicpacks = M_ParmExists("-nomusicpacks"); + + // Auto configure the music pack directory. + M_SetMusicPackDir(); + + // Initialize the sound and music subsystems. + + if (!nosound && !screensaver_mode) + { + // This is kind of a hack. If native MIDI is enabled, set up + // the TIMIDITY_CFG environment variable here before SDL_mixer + // is opened. + + if (!nomusic + && (snd_musicdevice == SNDDEVICE_GENMIDI + || snd_musicdevice == SNDDEVICE_GUS)) + { + I_InitTimidityConfig(); + } + + if (!nosfx) + { + InitSfxModule(mission); + } + + if (!nomusic) + { + InitMusicModule(); + active_music_module = music_module; + } + + // We may also have substitute MIDIs we can load. + if (!nomusicpacks && music_module != NULL) + { + music_packs_active = music_pack_module.Init(); + } + } +} + +void I_ShutdownSound(void) +{ + if (sound_module != NULL) + { + sound_module->Shutdown(); + } + + if (music_packs_active) + { + music_pack_module.Shutdown(); + } + + if (music_module != NULL) + { + music_module->Shutdown(); + } +} + +int I_GetSfxLumpNum(sfxinfo_t *sfxinfo) +{ + if (sound_module != NULL) + { + return sound_module->GetSfxLumpNum(sfxinfo); + } + else + { + return 0; + } +} + +void I_UpdateSound(void) +{ + if (sound_module != NULL) + { + sound_module->Update(); + } + + if (active_music_module != NULL && active_music_module->Poll != NULL) + { + active_music_module->Poll(); + } +} + +static void CheckVolumeSeparation(int *vol, int *sep) +{ + if (*sep < 0) + { + *sep = 0; + } + else if (*sep > 254) + { + *sep = 254; + } + + if (*vol < 0) + { + *vol = 0; + } + else if (*vol > 127) + { + *vol = 127; + } +} + +void I_UpdateSoundParams(int channel, int vol, int sep) +{ + if (sound_module != NULL) + { + CheckVolumeSeparation(&vol, &sep); + sound_module->UpdateSoundParams(channel, vol, sep); + } +} + +int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch) +{ + if (sound_module != NULL) + { + CheckVolumeSeparation(&vol, &sep); + return sound_module->StartSound(sfxinfo, channel, vol, sep, pitch); + } + else + { + return 0; + } +} + +void I_StopSound(int channel) +{ + if (sound_module != NULL) + { + sound_module->StopSound(channel); + } +} + +boolean I_SoundIsPlaying(int channel) +{ + if (sound_module != NULL) + { + return sound_module->SoundIsPlaying(channel); + } + else + { + return false; + } +} + +void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds) +{ + if (sound_module != NULL && sound_module->CacheSounds != NULL) + { + sound_module->CacheSounds(sounds, num_sounds); + } +} + +void I_InitMusic(void) +{ +} + +void I_ShutdownMusic(void) +{ + +} + +void I_SetMusicVolume(int volume) +{ + if (music_module != NULL) + { + music_module->SetMusicVolume(volume); + + if (music_packs_active && music_module != &music_pack_module) + { + music_pack_module.SetMusicVolume(volume); + } + } +} + +void I_PauseSong(void) +{ + if (active_music_module != NULL) + { + active_music_module->PauseMusic(); + } +} + +void I_ResumeSong(void) +{ + if (active_music_module != NULL) + { + active_music_module->ResumeMusic(); + } +} + +void *I_RegisterSong(void *data, int len) +{ + // If the music pack module is active, check to see if there is a + // valid substitution for this track. If there is, we set the + // active_music_module pointer to the music pack module for the + // duration of this particular track. + if (music_packs_active) + { + void *handle; + + handle = music_pack_module.RegisterSong(data, len); + if (handle != NULL) + { + active_music_module = &music_pack_module; + return handle; + } + } + + // No substitution for this track, so use the main module. + active_music_module = music_module; + if (active_music_module != NULL) + { + return active_music_module->RegisterSong(data, len); + } + else + { + return NULL; + } +} + +void I_UnRegisterSong(void *handle) +{ + if (active_music_module != NULL) + { + active_music_module->UnRegisterSong(handle); + } +} + +void I_PlaySong(void *handle, boolean looping) +{ + if (active_music_module != NULL) + { + active_music_module->PlaySong(handle, looping); + } +} + +void I_StopSong(void) +{ + if (active_music_module != NULL) + { + active_music_module->StopSong(); + } +} + +boolean I_MusicIsPlaying(void) +{ + if (active_music_module != NULL) + { + return active_music_module->MusicIsPlaying(); + } + else + { + return false; + } +} + +void I_BindSoundVariables(void) +{ + M_BindIntVariable("snd_musicdevice", &snd_musicdevice); + M_BindIntVariable("snd_sfxdevice", &snd_sfxdevice); + M_BindIntVariable("snd_sbport", &snd_sbport); + M_BindIntVariable("snd_sbirq", &snd_sbirq); + M_BindIntVariable("snd_sbdma", &snd_sbdma); + M_BindIntVariable("snd_mport", &snd_mport); + M_BindIntVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms); + M_BindStringVariable("snd_musiccmd", &snd_musiccmd); + M_BindStringVariable("snd_dmxoption", &snd_dmxoption); + M_BindIntVariable("snd_samplerate", &snd_samplerate); + M_BindIntVariable("snd_cachesize", &snd_cachesize); + M_BindIntVariable("opl_io_port", &opl_io_port); + M_BindIntVariable("snd_pitchshift", &snd_pitchshift); + + M_BindStringVariable("music_pack_path", &music_pack_path); + M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path); + M_BindStringVariable("gus_patch_path", &gus_patch_path); + M_BindIntVariable("gus_ram_kb", &gus_ram_kb); +#ifdef _WIN32 + M_BindStringVariable("winmm_midi_device", &winmm_midi_device); + M_BindIntVariable("winmm_complevel", &winmm_complevel); + M_BindIntVariable("winmm_reset_type", &winmm_reset_type); + M_BindIntVariable("winmm_reset_delay", &winmm_reset_delay); +#endif + +#ifdef HAVE_FLUIDSYNTH + M_BindIntVariable("fsynth_chorus_active", &fsynth_chorus_active); + M_BindFloatVariable("fsynth_chorus_depth", &fsynth_chorus_depth); + M_BindFloatVariable("fsynth_chorus_level", &fsynth_chorus_level); + M_BindIntVariable("fsynth_chorus_nr", &fsynth_chorus_nr); + M_BindFloatVariable("fsynth_chorus_speed", &fsynth_chorus_speed); + M_BindStringVariable("fsynth_midibankselect", &fsynth_midibankselect); + M_BindIntVariable("fsynth_polyphony", &fsynth_polyphony); + M_BindIntVariable("fsynth_reverb_active", &fsynth_reverb_active); + M_BindFloatVariable("fsynth_reverb_damp", &fsynth_reverb_damp); + M_BindFloatVariable("fsynth_reverb_level", &fsynth_reverb_level); + M_BindFloatVariable("fsynth_reverb_roomsize", &fsynth_reverb_roomsize); + M_BindFloatVariable("fsynth_reverb_width", &fsynth_reverb_width); + M_BindFloatVariable("fsynth_gain", &fsynth_gain); + M_BindStringVariable("fsynth_sf_path", &fsynth_sf_path); +#endif // HAVE_FLUIDSYNTH + + M_BindIntVariable("use_libsamplerate", &use_libsamplerate); + M_BindFloatVariable("libsamplerate_scale", &libsamplerate_scale); +} + diff --git a/games/NXDoom/src/i_sound.h b/games/NXDoom/src/i_sound.h new file mode 100644 index 00000000000..376e1bb9c81 --- /dev/null +++ b/games/NXDoom/src/i_sound.h @@ -0,0 +1,300 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The not so system specific sound interface. +// + + +#ifndef __I_SOUND__ +#define __I_SOUND__ + +#include "doomtype.h" +#include "d_mode.h" + +// so that the individual game logic and sound driver code agree +#define NORM_PITCH 127 + +// +// SoundFX struct. +// +typedef struct sfxinfo_struct sfxinfo_t; + +struct sfxinfo_struct +{ + // tag name, used for hexen. + const char *tagname; + + // lump name. If we are running with use_sfx_prefix=true, a + // 'DS' (or 'DP' for PC speaker sounds) is prepended to this. + + char name[9]; + + // Sfx priority + int priority; + + // referenced sound if a link + sfxinfo_t *link; + + // pitch if a link (Doom), whether to pitch-shift (Hexen) + int pitch; + + // volume if a link + int volume; + + // this is checked every second to see if sound + // can be thrown out (if 0, then decrement, if -1, + // then throw out, if > 0, then it is in use) + int usefulness; + + // lump number of sfx + int lumpnum; + + // Maximum number of channels that the sound can be played on + // (Heretic) + int numchannels; + + // data used by the low level code + void *driver_data; +}; + +// +// MusicInfo struct. +// +typedef struct +{ + // up to 6-character name + const char *name; + + // lump number of music + int lumpnum; + + // music data + void *data; + + // music handle once registered + void *handle; + +} musicinfo_t; + +typedef enum +{ + SNDDEVICE_NONE = 0, + SNDDEVICE_PCSPEAKER = 1, + SNDDEVICE_ADLIB = 2, + SNDDEVICE_SB = 3, + SNDDEVICE_PAS = 4, + SNDDEVICE_GUS = 5, + SNDDEVICE_WAVEBLASTER = 6, + SNDDEVICE_SOUNDCANVAS = 7, + SNDDEVICE_GENMIDI = 8, + SNDDEVICE_AWE32 = 9, + SNDDEVICE_CD = 10, + SNDDEVICE_FSYNTH = 11, +} snddevice_t; + +// Interface for sound modules + +typedef struct +{ + // List of sound devices that this sound module is used for. + + const snddevice_t *sound_devices; + int num_sound_devices; + + // Initialise sound module + // Returns true if successfully initialised + + boolean (*Init)(GameMission_t mission); + + // Shutdown sound module + + void (*Shutdown)(void); + + // Returns the lump index of the given sound. + + int (*GetSfxLumpNum)(sfxinfo_t *sfxinfo); + + // Called periodically to update the subsystem. + + void (*Update)(void); + + // Update the sound settings on the given channel. + + void (*UpdateSoundParams)(int channel, int vol, int sep); + + // Start a sound on a given channel. Returns the channel id + // or -1 on failure. + + int (*StartSound)(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch); + + // Stop the sound playing on the given channel. + + void (*StopSound)(int channel); + + // Query if a sound is playing on the given channel + + boolean (*SoundIsPlaying)(int channel); + + // Called on startup to precache sound effects (if necessary) + + void (*CacheSounds)(sfxinfo_t *sounds, int num_sounds); + +} sound_module_t; + +void I_InitSound(GameMission_t mission); +void I_ShutdownSound(void); +int I_GetSfxLumpNum(sfxinfo_t *sfxinfo); +void I_UpdateSound(void); +void I_UpdateSoundParams(int channel, int vol, int sep); +int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch); +void I_StopSound(int channel); +boolean I_SoundIsPlaying(int channel); +void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds); + +// Interface for music modules + +typedef struct +{ + // List of sound devices that this music module is used for. + + const snddevice_t *sound_devices; + int num_sound_devices; + + // Initialise the music subsystem + + boolean (*Init)(void); + + // Shutdown the music subsystem + + void (*Shutdown)(void); + + // Set music volume - range 0-127 + + void (*SetMusicVolume)(int volume); + + // Pause music + + void (*PauseMusic)(void); + + // Un-pause music + + void (*ResumeMusic)(void); + + // Register a song handle from data + // Returns a handle that can be used to play the song + + void *(*RegisterSong)(void *data, int len); + + // Un-register (free) song data + + void (*UnRegisterSong)(void *handle); + + // Play the song + + void (*PlaySong)(void *handle, boolean looping); + + // Stop playing the current song. + + void (*StopSong)(void); + + // Query if music is playing. + + boolean (*MusicIsPlaying)(void); + + // Invoked periodically to poll. + + void (*Poll)(void); +} music_module_t; + +void I_InitMusic(void); +void I_ShutdownMusic(void); +void I_SetMusicVolume(int volume); +void I_PauseSong(void); +void I_ResumeSong(void); +void *I_RegisterSong(void *data, int len); +void I_UnRegisterSong(void *handle); +void I_PlaySong(void *handle, boolean looping); +void I_StopSong(void); +boolean I_MusicIsPlaying(void); + +extern int snd_sfxdevice; +extern int snd_musicdevice; +extern int snd_samplerate; +extern int snd_cachesize; +extern int snd_maxslicetime_ms; +extern char *snd_musiccmd; +extern int snd_pitchshift; +extern char *snd_dmxoption; +extern int use_libsamplerate; +extern float libsamplerate_scale; + +void I_BindSoundVariables(void); + +// DMX version to emulate for OPL emulation: +typedef enum { + opl_doom1_1_666, // Doom 1 v1.666 + opl_doom2_1_666, // Doom 2 v1.666, Hexen, Heretic + opl_doom_1_9 // Doom v1.9, Strife +} opl_driver_ver_t; + +void I_SetOPLDriverVer(opl_driver_ver_t ver); +void I_OPL_DevMessages(char *, size_t); + +// Sound modules + +void I_InitTimidityConfig(void); +extern const sound_module_t sound_sdl_module; +extern const sound_module_t sound_pcsound_module; +extern const music_module_t music_sdl_module; +extern const music_module_t music_opl_module; +extern const music_module_t music_pack_module; +extern const music_module_t music_win_module; +extern const music_module_t music_fl_module; + +// For OPL module: + +extern int opl_io_port; + +// For native music module: + +extern char *music_pack_path; +extern char *timidity_cfg_path; +#ifdef _WIN32 +extern char *winmm_midi_device; +extern int winmm_complevel; +extern int winmm_reset_type; +extern int winmm_reset_delay; +#endif + +// For FluidSynth module: + +#ifdef HAVE_FLUIDSYNTH +extern char *fsynth_sf_path; +extern int fsynth_chorus_active; +extern float fsynth_chorus_depth; +extern float fsynth_chorus_level; +extern int fsynth_chorus_nr; +extern float fsynth_chorus_speed; +extern char *fsynth_midibankselect; +extern int fsynth_polyphony; +extern int fsynth_reverb_active; +extern float fsynth_reverb_damp; +extern float fsynth_reverb_level; +extern float fsynth_reverb_roomsize; +extern float fsynth_reverb_width; +extern float fsynth_gain; +#endif // HAVE_FLUIDSYNTH + +#endif diff --git a/games/NXDoom/src/i_swap.h b/games/NXDoom/src/i_swap.h new file mode 100644 index 00000000000..3dee8e3f685 --- /dev/null +++ b/games/NXDoom/src/i_swap.h @@ -0,0 +1,43 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Endianess handling, swapping 16bit and 32bit. +// + + +#ifndef __I_SWAP__ +#define __I_SWAP__ + +#include "SDL_endian.h" + +// Endianess handling. +// WAD files are stored little endian. + +// Just use SDL's endianness swapping functions. + +// These are deliberately cast to signed values; this is the behaviour +// of the macros in the original source and some code relies on it. + +#define SHORT(x) ((signed short) SDL_SwapLE16(x)) +#define LONG(x) ((signed int) SDL_SwapLE32(x)) + +// Defines for checking the endianness of the system. + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define SYS_BIG_ENDIAN +#endif + +#endif + diff --git a/games/NXDoom/src/i_system.c b/games/NXDoom/src/i_system.c new file mode 100644 index 00000000000..dba359035ce --- /dev/null +++ b/games/NXDoom/src/i_system.c @@ -0,0 +1,470 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// + + + +#include +#include +#include + +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#endif + +#include "SDL.h" + +#include "config.h" + +#include "deh_str.h" +#include "doomtype.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" +#include "i_joystick.h" +#include "i_sound.h" +#include "i_timer.h" +#include "i_video.h" + +#include "i_system.h" + +#include "w_wad.h" +#include "z_zone.h" + +#define DEFAULT_RAM 16 /* MiB */ +#define MIN_RAM 4 /* MiB */ + + +typedef struct atexit_listentry_s atexit_listentry_t; + +struct atexit_listentry_s +{ + atexit_func_t func; + boolean run_on_error; + atexit_listentry_t *next; +}; + +static atexit_listentry_t *exit_funcs = NULL; + +void I_AtExit(atexit_func_t func, boolean run_on_error) +{ + atexit_listentry_t *entry; + + entry = malloc(sizeof(*entry)); + + entry->func = func; + entry->run_on_error = run_on_error; + entry->next = exit_funcs; + exit_funcs = entry; +} + +// Tactile feedback function, probably used for the Logitech Cyberman + +void I_Tactile(int on, int off, int total) +{ +} + +// Zone memory auto-allocation function that allocates the zone size +// by trying progressively smaller zone sizes until one is found that +// works. + +static byte *AutoAllocMemory(int *size, int default_ram, int min_ram) +{ + byte *zonemem; + + // Allocate the zone memory. This loop tries progressively smaller + // zone sizes until a size is found that can be allocated. + // If we used the -mb command line parameter, only the parameter + // provided is accepted. + + zonemem = NULL; + + while (zonemem == NULL) + { + // We need a reasonable minimum amount of RAM to start. + + if (default_ram < min_ram) + { + I_Error("Unable to allocate %i MiB of RAM for zone", default_ram); + } + + // Try to allocate the zone memory. + + *size = default_ram * 1024 * 1024; + + zonemem = malloc(*size); + + // Failed to allocate? Reduce zone size until we reach a size + // that is acceptable. + + if (zonemem == NULL) + { + default_ram -= 1; + } + } + + return zonemem; +} + +byte *I_ZoneBase (int *size) +{ + byte *zonemem; + int min_ram, default_ram; + int p; + + //! + // @category obscure + // @arg + // + // Specify the heap size, in MiB. + // + + p = M_CheckParmWithArgs("-mb", 1); + + if (p > 0) + { + default_ram = atoi(myargv[p+1]); + min_ram = default_ram; + } + else + { + // Because of the 8-byte pointer size in a 64-bit build, the default + // heap size (16 MiB) is insufficient compared to a 32-bit build. For + // example, the Alien Vendetta avm62402.lmp demo completes successfully + // on a 32-bit build, but terminates with an out of memory error on a + // 64-bit build. Therefore, to maintain consistency with a 32-bit + // build, the heap size should be increased. + + if (sizeof(void *) == 8) + { + default_ram = DEFAULT_RAM * 2; + } + else + { + default_ram = DEFAULT_RAM; + } + min_ram = MIN_RAM; + } + + zonemem = AutoAllocMemory(size, default_ram, min_ram); + + printf("zone memory: %p, %x allocated for zone\n", + zonemem, *size); + + return zonemem; +} + +void I_PrintBanner(const char *msg) +{ + int i; + int spaces = 35 - (strlen(msg) / 2); + + for (i=0; ifunc(); + entry = entry->next; + } + + SDL_Quit(); + + exit(0); +} + + + +// +// I_Error +// + +static boolean already_quitting = false; + +void I_Error (const char *error, ...) +{ + char msgbuf[512]; + va_list argptr; + atexit_listentry_t *entry; + boolean exit_gui_popup; + + if (already_quitting) + { + fprintf(stderr, "Warning: recursive call to I_Error detected.\n"); + exit(-1); + } + else + { + already_quitting = true; + } + + // Message first. + va_start(argptr, error); + //fprintf(stderr, "\nError: "); + vfprintf(stderr, error, argptr); + fprintf(stderr, "\n\n"); + va_end(argptr); + fflush(stderr); + + // Write a copy of the message into buffer. + va_start(argptr, error); + memset(msgbuf, 0, sizeof(msgbuf)); + M_vsnprintf(msgbuf, sizeof(msgbuf), error, argptr); + va_end(argptr); + + // Shutdown. Here might be other errors. + + entry = exit_funcs; + + while (entry != NULL) + { + if (entry->run_on_error) + { + entry->func(); + } + + entry = entry->next; + } + + //! + // @category obscure + // + // If specified, don't show a GUI window for error messages when the + // game exits with an error. + // + exit_gui_popup = !M_ParmExists("-nogui"); + + // Pop up a GUI dialog box to show the error message, if the + // game was not run from the console (and the user will + // therefore be unable to otherwise see the message). + if (exit_gui_popup && !I_ConsoleStdout()) + { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + PACKAGE_STRING, msgbuf, NULL); + } + + // abort(); + + SDL_Quit(); + + exit(-1); +} + +// +// I_Realloc +// + +void *I_Realloc(void *ptr, size_t size) +{ + void *new_ptr; + + new_ptr = realloc(ptr, size); + + if (size != 0 && new_ptr == NULL) + { + I_Error ("I_Realloc: failed on reallocation of %zu bytes", size); + } + + return new_ptr; +} + +// +// Read Access Violation emulation. +// +// From PrBoom+, by entryway. +// + +// C:\>debug +// -d 0:0 +// +// DOS 6.22: +// 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) +// DOS 7.1: +// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) +// Win98: +// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) +// DOSBox under XP: +// 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + +#define DOS_MEM_DUMP_SIZE 10 + +static const unsigned char mem_dump_dos622[DOS_MEM_DUMP_SIZE] = { + 0x57, 0x92, 0x19, 0x00, 0xF4, 0x06, 0x70, 0x00, 0x16, 0x00}; +static const unsigned char mem_dump_win98[DOS_MEM_DUMP_SIZE] = { + 0x9E, 0x0F, 0xC9, 0x00, 0x65, 0x04, 0x70, 0x00, 0x16, 0x00}; +static const unsigned char mem_dump_dosbox[DOS_MEM_DUMP_SIZE] = { + 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00}; +static unsigned char mem_dump_custom[DOS_MEM_DUMP_SIZE]; + +static const unsigned char *dos_mem_dump = mem_dump_dos622; + +boolean I_GetMemoryValue(unsigned int offset, void *value, int size) +{ + static boolean firsttime = true; + + if (firsttime) + { + int p, i, val; + + firsttime = false; + i = 0; + + //! + // @category compat + // @arg + // + // Specify DOS version to emulate for NULL pointer dereference + // emulation. Supported versions are: dos622, dos71, dosbox. + // The default is to emulate DOS 7.1 (Windows 98). + // + + p = M_CheckParmWithArgs("-setmem", 1); + + if (p > 0) + { + if (!strcasecmp(myargv[p + 1], "dos622")) + { + dos_mem_dump = mem_dump_dos622; + } + if (!strcasecmp(myargv[p + 1], "dos71")) + { + dos_mem_dump = mem_dump_win98; + } + else if (!strcasecmp(myargv[p + 1], "dosbox")) + { + dos_mem_dump = mem_dump_dosbox; + } + else + { + for (i = 0; i < DOS_MEM_DUMP_SIZE; ++i) + { + ++p; + + if (p >= myargc || myargv[p][0] == '-') + { + break; + } + + M_StrToInt(myargv[p], &val); + mem_dump_custom[i++] = (unsigned char) val; + } + + dos_mem_dump = mem_dump_custom; + } + } + } + + switch (size) + { + case 1: + *((unsigned char *) value) = dos_mem_dump[offset]; + return true; + case 2: + *((unsigned short *) value) = dos_mem_dump[offset] + | (dos_mem_dump[offset + 1] << 8); + return true; + case 4: + *((unsigned int *) value) = dos_mem_dump[offset] + | (dos_mem_dump[offset + 1] << 8) + | (dos_mem_dump[offset + 2] << 16) + | (dos_mem_dump[offset + 3] << 24); + return true; + } + + return false; +} + diff --git a/games/NXDoom/src/i_system.h b/games/NXDoom/src/i_system.h new file mode 100644 index 00000000000..78376f3cc7b --- /dev/null +++ b/games/NXDoom/src/i_system.h @@ -0,0 +1,86 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System specific interface stuff. +// + + +#ifndef __I_SYSTEM__ +#define __I_SYSTEM__ + +#include "d_ticcmd.h" +#include "d_event.h" + + +typedef void (*atexit_func_t)(void); + +// Called by DoomMain. +void I_Init (void); + +// Called by startup code +// to get the ammount of memory to malloc +// for the zone management. +byte* I_ZoneBase (int *size); + +boolean I_ConsoleStdout(void); + + +// Asynchronous interrupt functions should maintain private queues +// that are read by the synchronous functions +// to be converted into events. + +// Either returns a null ticcmd, +// or calls a loadable driver to build it. +// This ticcmd will then be modified by the gameloop +// for normal input. +ticcmd_t* I_BaseTiccmd (void); + + +// Called by M_Responder when quit is selected. +// Clean exit, displays sell blurb. +void I_Quit (void) NORETURN; + +void I_Error (const char *error, ...) NORETURN PRINTF_ATTR(1, 2); + +void I_Tactile (int on, int off, int total); + +void *I_Realloc(void *ptr, size_t size); + +boolean I_GetMemoryValue(unsigned int offset, void *value, int size); + +// Schedule a function to be called when the program exits. +// If run_if_error is true, the function is called if the exit +// is due to an error (I_Error) + +void I_AtExit(atexit_func_t func, boolean run_if_error); + +// Add all system-specific config file variable bindings. + +void I_BindVariables(void); + +// Print startup banner copyright message. + +void I_PrintStartupBanner(const char *gamedescription); + +// Print a centered text banner displaying the given string. + +void I_PrintBanner(const char *text); + +// Print a dividing line for startup banners. + +void I_PrintDivider(void); + +#endif + diff --git a/games/NXDoom/src/i_timer.c b/games/NXDoom/src/i_timer.c new file mode 100644 index 00000000000..4ec6fb047ef --- /dev/null +++ b/games/NXDoom/src/i_timer.c @@ -0,0 +1,82 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Timer functions. +// + +#include "SDL.h" + +#include "i_timer.h" +#include "doomtype.h" + +// +// I_GetTime +// returns time in 1/35th second tics +// + +static Uint32 basetime = 0; + +int I_GetTime (void) +{ + Uint32 ticks; + + ticks = SDL_GetTicks(); + + if (basetime == 0) + basetime = ticks; + + ticks -= basetime; + + return (ticks * TICRATE) / 1000; +} + +// +// Same as I_GetTime, but returns time in milliseconds +// + +int I_GetTimeMS(void) +{ + Uint32 ticks; + + ticks = SDL_GetTicks(); + + if (basetime == 0) + basetime = ticks; + + return ticks - basetime; +} + +// Sleep for a specified number of ms + +void I_Sleep(int ms) +{ + SDL_Delay(ms); +} + +void I_WaitVBL(int count) +{ + I_Sleep((count * 1000) / 70); +} + + +void I_InitTimer(void) +{ + // initialize timer + + SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1"); + + SDL_Init(SDL_INIT_TIMER); +} + diff --git a/games/NXDoom/src/i_timer.h b/games/NXDoom/src/i_timer.h new file mode 100644 index 00000000000..9b3dbb8d105 --- /dev/null +++ b/games/NXDoom/src/i_timer.h @@ -0,0 +1,42 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System-specific timer interface +// + + +#ifndef __I_TIMER__ +#define __I_TIMER__ + +#define TICRATE 35 + +// Called by D_DoomLoop, +// returns current time in tics. +int I_GetTime (void); + +// returns current time in ms +int I_GetTimeMS (void); + +// Pause for a specified number of ms +void I_Sleep(int ms); + +// Initialize timer +void I_InitTimer(void); + +// Wait for vertical retrace or pause a bit. +void I_WaitVBL(int count); + +#endif + diff --git a/games/NXDoom/src/i_video.c b/games/NXDoom/src/i_video.c new file mode 100644 index 00000000000..6ff3b80e1d0 --- /dev/null +++ b/games/NXDoom/src/i_video.c @@ -0,0 +1,1537 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM graphics stuff for SDL. +// + + +#include +#include + +#include "SDL.h" +#include "SDL_opengl.h" + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + +#include "config.h" +#include "d_loop.h" +#include "deh_str.h" +#include "doomtype.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" +#include "tables.h" +#include "v_diskicon.h" +#include "v_video.h" +#include "w_wad.h" +#include "z_zone.h" + +// These are (1) the window (or the full screen) that our game is rendered to +// and (2) the renderer that scales the texture (see below) into this window. + +static SDL_Window *screen; +static SDL_Renderer *renderer; + +// Window title + +static const char *window_title = ""; + +// These are (1) the 320x200x8 paletted buffer that we draw to (i.e. the one +// that holds I_VideoBuffer), (2) the 320x200x32 RGBA intermediate buffer that +// we blit the former buffer to, (3) the intermediate 320x200 texture that we +// load the RGBA buffer to and that we render into another texture (4) which +// is upscaled by an integer factor UPSCALE using "nearest" scaling and which +// in turn is finally rendered to screen using "linear" scaling. + +static SDL_Surface *screenbuffer = NULL; +static SDL_Surface *argbbuffer = NULL; +static SDL_Texture *texture = NULL; +static SDL_Texture *texture_upscaled = NULL; + +static SDL_Rect blit_rect = { + 0, + 0, + SCREENWIDTH, + SCREENHEIGHT +}; + +// palette + +static SDL_Color palette[256]; +static boolean palette_to_set; + +// display has been set up? + +static boolean initialized = false; + +// disable mouse? + +static boolean nomouse = false; +int usemouse = 1; + +// Save screenshots in PNG format. + +int png_screenshots = 0; + +// SDL video driver name + +char *video_driver = ""; + +// Window position: + +char *window_position = "center"; + +// SDL display number on which to run. + +int video_display = 0; + +// Screen width and height, from configuration file. + +int window_width = 800; +int window_height = 600; + +// Fullscreen mode, 0x0 for SDL_WINDOW_FULLSCREEN_DESKTOP. + +int fullscreen_width = 0, fullscreen_height = 0; + +// Maximum number of pixels to use for intermediate scale buffer. + +static int max_scaling_buffer_pixels = 16000000; + +// Run in full screen mode? (int type for config code) + +int fullscreen = true; + +// Aspect ratio correction mode + +int aspect_ratio_correct = true; +static int actualheight; + +// Smooth pixel scaling +int smooth_pixel_scaling = true; + +// Force integer scales for resolution-independent rendering + +int integer_scaling = false; + +// VGA Porch palette change emulation + +int vga_porch_flash = false; + +// Force software rendering, for systems which lack effective hardware +// acceleration + +int force_software_renderer = false; + +// Time to wait for the screen to settle on startup before starting the +// game (ms) + +static int startup_delay = 1000; + +// Grab the mouse? (int type for config code). nograbmouse_override allows +// this to be temporarily disabled via the command line. + +static int grabmouse = true; +static boolean nograbmouse_override = false; + +// The screen buffer; this is modified to draw things to the screen + +pixel_t *I_VideoBuffer = NULL; + +// If true, game is running as a screensaver + +boolean screensaver_mode = false; + +// Flag indicating whether the screen is currently visible: +// when the screen isnt visible, don't render the screen + +boolean screenvisible = true; + +// If true, we display dots at the bottom of the screen to +// indicate FPS. + +static boolean display_fps_dots; + +// If this is true, the screen is rendered but not blitted to the +// video buffer. + +static boolean noblit; + +// Callback function to invoke to determine whether to grab the +// mouse pointer. + +static grabmouse_callback_t grabmouse_callback = NULL; + +// Does the window currently have focus? + +static boolean window_focused = true; + +// Window resize state. + +static boolean need_resize = false; +static unsigned int last_resize_time; +#define RESIZE_DELAY 500 + +// Gamma correction level to use + +int usegamma = 0; + +// Joystick/gamepad hysteresis +unsigned int joywait = 0; + +// Icon RGB data and dimensions +static const unsigned int *icon_data; +static int icon_w; +static int icon_h; + +static boolean MouseShouldBeGrabbed() +{ + // never grab the mouse when in screensaver mode + + if (screensaver_mode) + return false; + + // if the window doesn't have focus, never grab it + + if (!window_focused) + return false; + + // always grab the mouse when full screen (dont want to + // see the mouse pointer) + + if (fullscreen) + return true; + + // Don't grab the mouse if mouse input is disabled + + if (!usemouse || nomouse) + return false; + + // if we specify not to grab the mouse, never grab + + if (nograbmouse_override || !grabmouse) + return false; + + // Invoke the grabmouse callback function to determine whether + // the mouse should be grabbed + + if (grabmouse_callback != NULL) + { + return grabmouse_callback(); + } + else + { + return true; + } +} + +void I_SetGrabMouseCallback(grabmouse_callback_t func) +{ + grabmouse_callback = func; +} + +// Set the variable controlling FPS dots. + +void I_DisplayFPSDots(boolean dots_on) +{ + display_fps_dots = dots_on; +} + +static void SetShowCursor(boolean show) +{ + if (!screensaver_mode) + { + // When the cursor is hidden, grab the input. + // Relative mode implicitly hides the cursor. + SDL_SetRelativeMouseMode(!show); + SDL_GetRelativeMouseState(NULL, NULL); + } +} + +void I_ShutdownGraphics(void) +{ + if (initialized) + { + SetShowCursor(true); + + SDL_FreeSurface(argbbuffer); + SDL_FreeSurface(screenbuffer); + SDL_DestroyTexture(texture_upscaled); + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(screen); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + + initialized = false; + } +} + + + +// +// I_StartFrame +// +void I_StartFrame (void) +{ + // er? + +} + +// Adjust window_width / window_height variables to be an an aspect +// ratio consistent with the aspect_ratio_correct variable. +static void AdjustWindowSize(void) +{ + if (aspect_ratio_correct || integer_scaling) + { + if (window_width * actualheight <= window_height * SCREENWIDTH) + { + // We round up window_height if the ratio is not exact; this leaves + // the result stable. + window_height = (window_width * actualheight + SCREENWIDTH - 1) / SCREENWIDTH; + } + else + { + window_width = window_height * SCREENWIDTH / actualheight; + } + } +} + +static void HandleWindowEvent(SDL_WindowEvent *event) +{ + int i; + + switch (event->event) + { +#if 0 // SDL2-TODO + case SDL_ACTIVEEVENT: + // need to update our focus state + UpdateFocus(); + break; +#endif + case SDL_WINDOWEVENT_EXPOSED: + palette_to_set = true; + break; + + case SDL_WINDOWEVENT_RESIZED: + need_resize = true; + last_resize_time = SDL_GetTicks(); + break; + + // Don't render the screen when the window is minimized: + + case SDL_WINDOWEVENT_MINIMIZED: + screenvisible = false; + break; + + case SDL_WINDOWEVENT_MAXIMIZED: + case SDL_WINDOWEVENT_RESTORED: + screenvisible = true; + break; + + // Update the value of window_focused when we get a focus event + // + // We try to make ourselves be well-behaved: the grab on the mouse + // is removed if we lose focus (such as a popup window appearing), + // and we dont move the mouse around if we aren't focused either. + + case SDL_WINDOWEVENT_FOCUS_GAINED: + window_focused = true; + break; + + case SDL_WINDOWEVENT_FOCUS_LOST: + window_focused = false; + break; + + // We want to save the user's preferred monitor to use for running the + // game, so that next time we're run we start on the same display. So + // every time the window is moved, find which display we're now on and + // update the video_display config variable. + + case SDL_WINDOWEVENT_MOVED: + i = SDL_GetWindowDisplayIndex(screen); + if (i >= 0) + { + video_display = i; + } + break; + + default: + break; + } +} + +static boolean ToggleFullScreenKeyShortcut(SDL_Keysym *sym) +{ + Uint16 flags = (KMOD_LALT | KMOD_RALT); +#if defined(__MACOSX__) + flags |= (KMOD_LGUI | KMOD_RGUI); +#endif + return (sym->scancode == SDL_SCANCODE_RETURN || + sym->scancode == SDL_SCANCODE_KP_ENTER) && (sym->mod & flags) != 0; +} + +static void I_ToggleFullScreen(void) +{ + unsigned int flags = 0; + + // TODO: Consider implementing fullscreen toggle for SDL_WINDOW_FULLSCREEN + // (mode-changing) setup. This is hard because we have to shut down and + // restart again. + if (fullscreen_width != 0 || fullscreen_height != 0) + { + return; + } + + fullscreen = !fullscreen; + + if (fullscreen) + { + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } + + SDL_SetWindowFullscreen(screen, flags); + + if (!fullscreen) + { + AdjustWindowSize(); + SDL_SetWindowSize(screen, window_width, window_height); + } +} + +void I_GetEvent(void) +{ + SDL_Event sdlevent; + + SDL_PumpEvents(); + + while (SDL_PollEvent(&sdlevent)) + { + switch (sdlevent.type) + { + case SDL_KEYDOWN: + if (ToggleFullScreenKeyShortcut(&sdlevent.key.keysym)) + { + I_ToggleFullScreen(); + break; + } + // deliberate fall-though + + case SDL_KEYUP: + I_HandleKeyboardEvent(&sdlevent); + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: + if (usemouse && !nomouse && window_focused) + { + I_HandleMouseEvent(&sdlevent); + } + break; + + case SDL_QUIT: + if (screensaver_mode) + { + I_Quit(); + } + else + { + event_t event; + event.type = ev_quit; + D_PostEvent(&event); + } + break; + + case SDL_WINDOWEVENT: + if (sdlevent.window.windowID == SDL_GetWindowID(screen)) + { + HandleWindowEvent(&sdlevent.window); + } + break; + + default: + break; + } + } +} + +// +// I_StartTic +// +void I_StartTic (void) +{ + if (!initialized) + { + return; + } + + I_GetEvent(); + + if (usemouse && !nomouse && window_focused) + { + I_ReadMouse(); + } + + if (joywait < I_GetTime()) + { + I_UpdateJoystick(); + } +} + + +// +// I_UpdateNoBlit +// +void I_UpdateNoBlit (void) +{ + // what is this? +} + +static void UpdateGrab(void) +{ + static boolean currently_grabbed = false; + boolean grab; + + grab = MouseShouldBeGrabbed(); + + if (screensaver_mode) + { + // Hide the cursor in screensaver mode + + SetShowCursor(false); + } + else if (grab && !currently_grabbed) + { + SetShowCursor(false); + } + else if (!grab && currently_grabbed) + { + int screen_w, screen_h; + + SetShowCursor(true); + + // When releasing the mouse from grab, warp the mouse cursor to + // the bottom-right of the screen. This is a minimally distracting + // place for it to appear - we may only have released the grab + // because we're at an end of level intermission screen, for + // example. + + SDL_GetWindowSize(screen, &screen_w, &screen_h); + SDL_WarpMouseInWindow(screen, screen_w - 16, screen_h - 16); + SDL_GetRelativeMouseState(NULL, NULL); + } + + currently_grabbed = grab; +} + +static void LimitTextureSize(int *w_upscale, int *h_upscale) +{ + SDL_RendererInfo rinfo; + int orig_w, orig_h; + + orig_w = *w_upscale; + orig_h = *h_upscale; + + // Query renderer and limit to maximum texture dimensions of hardware: + if (SDL_GetRendererInfo(renderer, &rinfo) != 0) + { + I_Error("CreateUpscaledTexture: SDL_GetRendererInfo() call failed: %s", + SDL_GetError()); + } + + while (*w_upscale * SCREENWIDTH > rinfo.max_texture_width) + { + --*w_upscale; + } + while (*h_upscale * SCREENHEIGHT > rinfo.max_texture_height) + { + --*h_upscale; + } + + if ((*w_upscale < 1 && rinfo.max_texture_width > 0) || + (*h_upscale < 1 && rinfo.max_texture_height > 0)) + { + I_Error("CreateUpscaledTexture: Can't create a texture big enough for " + "the whole screen! Maximum texture size %dx%d", + rinfo.max_texture_width, rinfo.max_texture_height); + } + + // We limit the amount of texture memory used for the intermediate buffer, + // since beyond a certain point there are diminishing returns. Also, + // depending on the hardware there may be performance problems with very + // huge textures, so the user can use this to reduce the maximum texture + // size if desired. + + if (max_scaling_buffer_pixels < SCREENWIDTH * SCREENHEIGHT) + { + I_Error("CreateUpscaledTexture: max_scaling_buffer_pixels too small " + "to create a texture buffer: %d < %d", + max_scaling_buffer_pixels, SCREENWIDTH * SCREENHEIGHT); + } + + while (*w_upscale * *h_upscale * SCREENWIDTH * SCREENHEIGHT + > max_scaling_buffer_pixels) + { + if (*w_upscale > *h_upscale) + { + --*w_upscale; + } + else + { + --*h_upscale; + } + } + + if (*w_upscale != orig_w || *h_upscale != orig_h) + { + printf("CreateUpscaledTexture: Limited texture size to %dx%d " + "(max %d pixels, max texture size %dx%d)\n", + *w_upscale * SCREENWIDTH, *h_upscale * SCREENHEIGHT, + max_scaling_buffer_pixels, + rinfo.max_texture_width, rinfo.max_texture_height); + } +} + +static void CreateUpscaledTexture(boolean force) +{ + int w, h; + int h_upscale, w_upscale; + static int h_upscale_old, w_upscale_old; + + SDL_Texture *new_texture, *old_texture; + + // Get the size of the renderer output. The units this gives us will be + // real world pixels, which are not necessarily equivalent to the screen's + // window size (because of highdpi). + if (SDL_GetRendererOutputSize(renderer, &w, &h) != 0) + { + I_Error("Failed to get renderer output size: %s", SDL_GetError()); + } + + // When the screen or window dimensions do not match the aspect ratio + // of the texture, the rendered area is scaled down to fit. Calculate + // the actual dimensions of the rendered area. + + if (w * actualheight < h * SCREENWIDTH) + { + // Tall window. + + h = w * actualheight / SCREENWIDTH; + } + else + { + // Wide window. + + w = h * SCREENWIDTH / actualheight; + } + + // Pick texture size the next integer multiple of the screen dimensions. + // If one screen dimension matches an integer multiple of the original + // resolution, there is no need to overscale in this direction. + + w_upscale = (w + SCREENWIDTH - 1) / SCREENWIDTH; + h_upscale = (h + SCREENHEIGHT - 1) / SCREENHEIGHT; + + // Minimum texture dimensions of 320x200. + + if (w_upscale < 1) + { + w_upscale = 1; + } + if (h_upscale < 1) + { + h_upscale = 1; + } + + LimitTextureSize(&w_upscale, &h_upscale); + + // Create a new texture only if the upscale factors have actually changed. + + if (h_upscale == h_upscale_old && w_upscale == w_upscale_old && !force) + { + return; + } + + h_upscale_old = h_upscale; + w_upscale_old = w_upscale; + + // Set the scaling quality for rendering the upscaled texture to "linear", + // which looks much softer and smoother than "nearest" but does a better + // job at downscaling from the upscaled texture to screen. + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + + new_texture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, + w_upscale*SCREENWIDTH, + h_upscale*SCREENHEIGHT); + + old_texture = texture_upscaled; + texture_upscaled = new_texture; + + if (old_texture != NULL) + { + SDL_DestroyTexture(old_texture); + } +} + +// +// I_FinishUpdate +// +void I_FinishUpdate (void) +{ + static int lasttic; + int tics; + int i; + + if (!initialized) + return; + + if (noblit) + return; + + if (need_resize) + { + if (SDL_GetTicks() > last_resize_time + RESIZE_DELAY) + { + int flags; + // When the window is resized (we're not in fullscreen mode), + // save the new window size. + flags = SDL_GetWindowFlags(screen); + if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) + { + SDL_GetWindowSize(screen, &window_width, &window_height); + + // Adjust the window by resizing again so that the window + // is the right aspect ratio. + AdjustWindowSize(); + SDL_SetWindowSize(screen, window_width, window_height); + } + CreateUpscaledTexture(false); + need_resize = false; + palette_to_set = true; + } + else + { + return; + } + } + + UpdateGrab(); + +#if 0 // SDL2-TODO + // Don't update the screen if the window isn't visible. + // Not doing this breaks under Windows when we alt-tab away + // while fullscreen. + + if (!(SDL_GetAppState() & SDL_APPACTIVE)) + return; +#endif + + // draws little dots on the bottom of the screen + + if (display_fps_dots) + { + i = I_GetTime(); + tics = i - lasttic; + lasttic = i; + if (tics > 20) tics = 20; + + for (i=0 ; iformat->palette, palette, 0, 256); + palette_to_set = false; + + if (vga_porch_flash) + { + // "flash" the pillars/letterboxes with palette changes, emulating + // VGA "porch" behaviour (GitHub issue #832) + SDL_SetRenderDrawColor(renderer, palette[0].r, palette[0].g, + palette[0].b, SDL_ALPHA_OPAQUE); + } + } + + // Blit from the paletted 8-bit screen buffer to the intermediate + // 32-bit RGBA buffer and update the intermediate texture with the + // contents of the RGBA buffer. + + SDL_LockTexture(texture, &blit_rect, &argbbuffer->pixels, + &argbbuffer->pitch); + SDL_LowerBlit(screenbuffer, &blit_rect, argbbuffer, &blit_rect); + SDL_UnlockTexture(texture); + + // Make sure the pillarboxes are kept clear each frame. + + SDL_RenderClear(renderer); + + if (smooth_pixel_scaling && !force_software_renderer) + { + // Render this intermediate texture into the upscaled texture + // using "nearest" integer scaling. + SDL_SetRenderTarget(renderer, texture_upscaled); + SDL_RenderCopy(renderer, texture, NULL, NULL); + + // Finally, render this upscaled texture to screen using linear scaling. + + SDL_SetRenderTarget(renderer, NULL); + SDL_RenderCopy(renderer, texture_upscaled, NULL, NULL); + } + else + { + SDL_SetRenderTarget(renderer, NULL); + SDL_RenderCopy(renderer, texture, NULL, NULL); + } + + + // Draw! + + SDL_RenderPresent(renderer); + + // Restore background and undo the disk indicator, if it was drawn. + V_RestoreDiskBackground(); +} + + +// +// I_ReadScreen +// +void I_ReadScreen (pixel_t* scr) +{ + memcpy(scr, I_VideoBuffer, SCREENWIDTH*SCREENHEIGHT*sizeof(*scr)); +} + + +// +// I_SetPalette +// +void I_SetPalette (byte *doompalette) +{ + int i; + + for (i=0; i<256; ++i) + { + // Zero out the bottom two bits of each channel - the PC VGA + // controller only supports 6 bits of accuracy. + + palette[i].a = 0xFFU; + palette[i].r = gammatable[usegamma][*doompalette++] & ~3; + palette[i].g = gammatable[usegamma][*doompalette++] & ~3; + palette[i].b = gammatable[usegamma][*doompalette++] & ~3; + } + + palette_to_set = true; +} + +// Given an RGB value, find the closest matching palette index. + +int I_GetPaletteIndex(int r, int g, int b) +{ + int best, best_diff, diff; + int i; + + best = 0; best_diff = INT_MAX; + + for (i = 0; i < 256; ++i) + { + diff = (r - palette[i].r) * (r - palette[i].r) + + (g - palette[i].g) * (g - palette[i].g) + + (b - palette[i].b) * (b - palette[i].b); + + if (diff < best_diff) + { + best = i; + best_diff = diff; + } + + if (diff == 0) + { + break; + } + } + + return best; +} + +// +// Set the window title +// + +void I_SetWindowTitle(const char *title) +{ + window_title = title; +} + +// +// Call the SDL function to set the window title, based on +// the title set with I_SetWindowTitle. +// + +void I_InitWindowTitle(void) +{ + char *buf; + + buf = M_StringJoin(window_title, " - ", PACKAGE_STRING, NULL); + SDL_SetWindowTitle(screen, buf); + free(buf); +} + +void I_RegisterWindowIcon(const unsigned int *icon, int width, int height) +{ + icon_data = icon; + icon_w = width; + icon_h = height; +} + +// Set the application icon + +void I_InitWindowIcon(void) +{ + SDL_Surface *surface; + + surface = SDL_CreateRGBSurfaceFrom((void *) icon_data, icon_w, icon_h, + 32, icon_w * 4, + 0xffu << 24, 0xffu << 16, + 0xffu << 8, 0xffu << 0); + + SDL_SetWindowIcon(screen, surface); + SDL_FreeSurface(surface); +} + +// Set video size to a particular scale factor (1x, 2x, 3x, etc.) + +static void SetScaleFactor(int factor) +{ + int height; + + // Pick 320x200 or 320x240, depending on aspect ratio correct + if (aspect_ratio_correct) + { + height = SCREENHEIGHT_4_3; + } + else + { + height = SCREENHEIGHT; + } + + window_width = factor * SCREENWIDTH; + window_height = factor * height; + fullscreen = false; +} + +void I_GraphicsCheckCommandLine(void) +{ + int i; + + //! + // @category video + // @vanilla + // + // Disable blitting the screen. + // + + noblit = M_CheckParm ("-noblit"); + + //! + // @category video + // + // Don't grab the mouse when running in windowed mode. + // + + nograbmouse_override = M_ParmExists("-nograbmouse"); + + // default to fullscreen mode, allow override with command line + // nofullscreen because we love prboom + + //! + // @category video + // + // Run in a window. + // + + if (M_CheckParm("-window") || M_CheckParm("-nofullscreen")) + { + fullscreen = false; + } + + //! + // @category video + // + // Run in fullscreen mode. + // + + if (M_CheckParm("-fullscreen")) + { + fullscreen = true; + } + + //! + // @category video + // + // Disable the mouse. + // + + nomouse = M_CheckParm("-nomouse") > 0; + + //! + // @category video + // @arg + // + // Specify the screen width, in pixels. Implies -window. + // + + i = M_CheckParmWithArgs("-width", 1); + + if (i > 0) + { + window_width = atoi(myargv[i + 1]); + fullscreen = false; + } + + //! + // @category video + // @arg + // + // Specify the screen height, in pixels. Implies -window. + // + + i = M_CheckParmWithArgs("-height", 1); + + if (i > 0) + { + window_height = atoi(myargv[i + 1]); + fullscreen = false; + } + + //! + // @category video + // @arg + // + // Specify the dimensions of the window. Implies -window. + // + + i = M_CheckParmWithArgs("-geometry", 1); + + if (i > 0) + { + int w, h, s; + + s = sscanf(myargv[i + 1], "%ix%i", &w, &h); + if (s == 2) + { + window_width = w; + window_height = h; + fullscreen = false; + } + } + + //! + // @category video + // @arg + // + // Specify the display number on which to show the screen. + // + + i = M_CheckParmWithArgs("-display", 1); + + if (i > 0) + { + int display = atoi(myargv[i + 1]); + if (display >= 0) + { + video_display = display; + } + } + + //! + // @category video + // + // Don't scale up the screen. Implies -window. + // + + if (M_CheckParm("-1")) + { + SetScaleFactor(1); + } + + //! + // @category video + // + // Double up the screen to 2x its normal size. Implies -window. + // + + if (M_CheckParm("-2")) + { + SetScaleFactor(2); + } + + //! + // @category video + // + // Double up the screen to 3x its normal size. Implies -window. + // + + if (M_CheckParm("-3")) + { + SetScaleFactor(3); + } +} + +// Check if we have been invoked as a screensaver by xscreensaver. + +void I_CheckIsScreensaver(void) +{ + char *env; + + env = getenv("XSCREENSAVER_WINDOW"); + + if (env != NULL) + { + screensaver_mode = true; + } +} + +static void SetSDLVideoDriver(void) +{ + // Allow a default value for the SDL video driver to be specified + // in the configuration file. + + if (strcmp(video_driver, "") != 0) + { + char *env_string; + + env_string = M_StringJoin("SDL_VIDEODRIVER=", video_driver, NULL); + putenv(env_string); + free(env_string); + } +} + +// Check the display bounds of the display referred to by 'video_display' and +// set x and y to a location that places the window in the center of that +// display. +static void CenterWindow(int *x, int *y, int w, int h) +{ + SDL_Rect bounds; + + if (SDL_GetDisplayBounds(video_display, &bounds) < 0) + { + fprintf(stderr, "CenterWindow: Failed to read display bounds " + "for display #%d!\n", video_display); + return; + } + + *x = bounds.x + SDL_max((bounds.w - w) / 2, 0); + *y = bounds.y + SDL_max((bounds.h - h) / 2, 0); +} + +void I_GetWindowPosition(int *x, int *y, int w, int h) +{ + // Check that video_display corresponds to a display that really exists, + // and if it doesn't, reset it. + if (video_display < 0 || video_display >= SDL_GetNumVideoDisplays()) + { + fprintf(stderr, + "I_GetWindowPosition: We were configured to run on display #%d, " + "but it no longer exists (max %d). Moving to display 0.\n", + video_display, SDL_GetNumVideoDisplays() - 1); + video_display = 0; + } + + // in fullscreen mode, the window "position" still matters, because + // we use it to control which display we run fullscreen on. + + if (fullscreen) + { + CenterWindow(x, y, w, h); + return; + } + + // in windowed mode, the desired window position can be specified + // in the configuration file. + + if (window_position == NULL || !strcmp(window_position, "")) + { + *x = *y = SDL_WINDOWPOS_UNDEFINED; + } + else if (!strcmp(window_position, "center")) + { + // Note: SDL has a SDL_WINDOWPOS_CENTER, but this is useless for our + // purposes, since we also want to control which display we appear on. + // So we have to do this ourselves. + CenterWindow(x, y, w, h); + } + else if (sscanf(window_position, "%i,%i", x, y) != 2) + { + // invalid format: revert to default + fprintf(stderr, "I_GetWindowPosition: invalid window_position setting\n"); + *x = *y = SDL_WINDOWPOS_UNDEFINED; + } +} + +static void SetVideoMode(void) +{ + int w, h; + int x, y; + int window_flags = 0, renderer_flags = 0; + SDL_DisplayMode mode; + + w = window_width; + h = window_height; + + // In windowed mode, the window can be resized while the game is + // running. + window_flags = SDL_WINDOW_RESIZABLE; + + // Set the highdpi flag - this makes a big difference on Macs with + // retina displays, especially when using small window sizes. + window_flags |= SDL_WINDOW_ALLOW_HIGHDPI; + + if (fullscreen) + { + if (fullscreen_width == 0 && fullscreen_height == 0) + { + // This window_flags means "Never change the screen resolution! + // Instead, draw to the entire screen by scaling the texture + // appropriately". + window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } + else + { + w = fullscreen_width; + h = fullscreen_height; + window_flags |= SDL_WINDOW_FULLSCREEN; + } + } + + // Running without window decorations is potentially useful if you're + // playing in three window mode and want to line up three game windows + // next to each other on a single desktop. + // Deliberately not documented because I'm not sure how useful this is yet. + if (M_ParmExists("-borderless")) + { + window_flags |= SDL_WINDOW_BORDERLESS; + } + + I_GetWindowPosition(&x, &y, w, h); + + // Create window and renderer contexts. We set the window title + // later anyway and leave the window position "undefined". If + // "window_flags" contains the fullscreen flag (see above), then + // w and h are ignored. + + if (screen == NULL) + { + screen = SDL_CreateWindow(NULL, x, y, w, h, window_flags); + + if (screen == NULL) + { + I_Error("Error creating window for video startup: %s", + SDL_GetError()); + } + + SDL_SetWindowMinimumSize(screen, SCREENWIDTH, actualheight); + + I_InitWindowTitle(); + I_InitWindowIcon(); + } + + // The SDL_RENDERER_TARGETTEXTURE flag is required to render the + // intermediate texture into the upscaled texture. + renderer_flags = SDL_RENDERER_TARGETTEXTURE; + + if (SDL_GetCurrentDisplayMode(video_display, &mode) != 0) + { + I_Error("Could not get display mode for video display #%d: %s", + video_display, SDL_GetError()); + } + + // Turn on vsync if we aren't in a -timedemo + if (!singletics && mode.refresh_rate > 0) + { + renderer_flags |= SDL_RENDERER_PRESENTVSYNC; + } + + if (force_software_renderer) + { + renderer_flags |= SDL_RENDERER_SOFTWARE; + renderer_flags &= ~SDL_RENDERER_PRESENTVSYNC; + } + + if (renderer != NULL) + { + SDL_DestroyRenderer(renderer); + // all associated textures get destroyed + texture = NULL; + texture_upscaled = NULL; + } + + renderer = SDL_CreateRenderer(screen, -1, renderer_flags); + + // If we could not find a matching render driver, + // try again without hardware acceleration. + + if (renderer == NULL && !force_software_renderer) + { + renderer_flags |= SDL_RENDERER_SOFTWARE; + renderer_flags &= ~SDL_RENDERER_PRESENTVSYNC; + + renderer = SDL_CreateRenderer(screen, -1, renderer_flags); + + // If this helped, save the setting for later. + if (renderer != NULL) + { + force_software_renderer = 1; + } + } + + if (renderer == NULL) + { + I_Error("Error creating renderer for screen window: %s", + SDL_GetError()); + } + + // Important: Set the "logical size" of the rendering context. At the same + // time this also defines the aspect ratio that is preserved while scaling + // and stretching the texture into the window. + + if (aspect_ratio_correct || integer_scaling) + { + SDL_RenderSetLogicalSize(renderer, + SCREENWIDTH, + actualheight); + } + + // Force integer scales for resolution-independent rendering. + + SDL_RenderSetIntegerScale(renderer, integer_scaling); + + // Blank out the full screen area in case there is any junk in + // the borders that won't otherwise be overwritten. + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + + // Create the 8-bit paletted and the 32-bit RGBA screenbuffer surfaces. + + if (screenbuffer != NULL) + { + SDL_FreeSurface(screenbuffer); + screenbuffer = NULL; + } + + if (screenbuffer == NULL) + { + screenbuffer = SDL_CreateRGBSurface(0, + SCREENWIDTH, SCREENHEIGHT, 8, + 0, 0, 0, 0); + SDL_FillRect(screenbuffer, NULL, 0); + } + + // Format of argbbuffer must match the screen pixel format because we + // import the surface data into the texture. + + if (argbbuffer != NULL) + { + SDL_FreeSurface(argbbuffer); + argbbuffer = NULL; + } + + if (argbbuffer == NULL) + { + // pixels and pitch will be filled with the texture's values + // in I_FinishUpdate() + argbbuffer = SDL_CreateRGBSurfaceWithFormatFrom( + NULL, w, h, 0, 0, SDL_PIXELFORMAT_ARGB8888); + } + + if (texture != NULL) + { + SDL_DestroyTexture(texture); + } + + // Set the scaling quality for rendering the intermediate texture into + // the upscaled texture to "nearest", which is gritty and pixelated and + // resembles software scaling pretty well. + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + + // Create the intermediate texture that the RGBA surface gets loaded into. + // The SDL_TEXTUREACCESS_STREAMING flag means that this texture's content + // is going to change frequently. + + texture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + SCREENWIDTH, SCREENHEIGHT); + + // Workaround for SDL 2.0.14+ alt-tab bug (taken from Doom Retro via Prboom-plus and Woof) +#if defined(_WIN32) + { + SDL_version ver; + SDL_GetVersion(&ver); + if (ver.major == 2 && ver.minor == 0 && (ver.patch == 14 || ver.patch == 16)) + { + SDL_SetHintWithPriority(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1", SDL_HINT_OVERRIDE); + } + } +#endif + + // Initially create the upscaled texture for rendering to screen + + CreateUpscaledTexture(true); +} + +void I_InitGraphics(void) +{ + SDL_Event dummy; + byte *doompal; + char *env; + + // Pass through the XSCREENSAVER_WINDOW environment variable to + // SDL_WINDOWID, to embed the SDL window into the Xscreensaver + // window. + + env = getenv("XSCREENSAVER_WINDOW"); + + if (env != NULL) + { + char winenv[30]; + unsigned int winid; + + sscanf(env, "0x%x", &winid); + M_snprintf(winenv, sizeof(winenv), "SDL_WINDOWID=%u", winid); + + putenv(winenv); + } + + SetSDLVideoDriver(); + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + I_Error("Failed to initialize video: %s", SDL_GetError()); + } + + // When in screensaver mode, run full screen and auto detect + // screen dimensions (don't change video mode) + if (screensaver_mode) + { + fullscreen = true; + } + + if (aspect_ratio_correct == 1) + { + actualheight = SCREENHEIGHT_4_3; + } + else + { + actualheight = SCREENHEIGHT; + } + + // Create the game window; this may switch graphic modes depending + // on configuration. + AdjustWindowSize(); + SetVideoMode(); + + // Start with a clear black screen + // (screen will be flipped after we set the palette) + + SDL_FillRect(screenbuffer, NULL, 0); + + // Set the palette + + doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE); + I_SetPalette(doompal); + SDL_SetPaletteColors(screenbuffer->format->palette, palette, 0, 256); + + // SDL2-TODO UpdateFocus(); + UpdateGrab(); + + // On some systems, it takes a second or so for the screen to settle + // after changing modes. We include the option to add a delay when + // setting the screen mode, so that the game doesn't start immediately + // with the player unable to see anything. + + if (fullscreen && !screensaver_mode) + { + SDL_Delay(startup_delay); + } + + // The actual 320x200 canvas that we draw to. This is the pixel buffer of + // the 8-bit paletted screen buffer that gets blit on an intermediate + // 32-bit RGBA screen buffer that gets loaded into a texture that gets + // finally rendered into our window or full screen in I_FinishUpdate(). + + I_VideoBuffer = screenbuffer->pixels; + V_RestoreBuffer(); + + // Clear the screen to black. + + memset(I_VideoBuffer, 0, SCREENWIDTH * SCREENHEIGHT * sizeof(*I_VideoBuffer)); + + // clear out any events waiting at the start and center the mouse + + while (SDL_PollEvent(&dummy)); + + initialized = true; + + // Call I_ShutdownGraphics on quit + + I_AtExit(I_ShutdownGraphics, true); +} + +// Bind all variables controlling video options into the configuration +// file system. +void I_BindVideoVariables(void) +{ + M_BindIntVariable("use_mouse", &usemouse); + M_BindIntVariable("fullscreen", &fullscreen); + M_BindIntVariable("video_display", &video_display); + M_BindIntVariable("aspect_ratio_correct", &aspect_ratio_correct); + M_BindIntVariable("integer_scaling", &integer_scaling); + M_BindIntVariable("smooth_pixel_scaling", &smooth_pixel_scaling); + M_BindIntVariable("vga_porch_flash", &vga_porch_flash); + M_BindIntVariable("startup_delay", &startup_delay); + M_BindIntVariable("fullscreen_width", &fullscreen_width); + M_BindIntVariable("fullscreen_height", &fullscreen_height); + M_BindIntVariable("force_software_renderer", &force_software_renderer); + M_BindIntVariable("max_scaling_buffer_pixels", &max_scaling_buffer_pixels); + M_BindIntVariable("window_width", &window_width); + M_BindIntVariable("window_height", &window_height); + M_BindIntVariable("grabmouse", &grabmouse); + M_BindStringVariable("video_driver", &video_driver); + M_BindStringVariable("window_position", &window_position); + M_BindIntVariable("usegamma", &usegamma); + M_BindIntVariable("png_screenshots", &png_screenshots); +} \ No newline at end of file diff --git a/games/NXDoom/src/i_video.h b/games/NXDoom/src/i_video.h new file mode 100644 index 00000000000..d98b8f5076e --- /dev/null +++ b/games/NXDoom/src/i_video.h @@ -0,0 +1,110 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System specific interface stuff. +// + + +#ifndef __I_VIDEO__ +#define __I_VIDEO__ + +#include "doomtype.h" + +// Screen width and height. + +#define SCREENWIDTH 320 +#define SCREENHEIGHT 200 + +// Screen height used when aspect_ratio_correct=true. + +#define SCREENHEIGHT_4_3 240 + +typedef boolean (*grabmouse_callback_t)(void); + +// Called by D_DoomMain, +// determines the hardware configuration +// and sets up the video mode +void I_InitGraphics (void); + +void I_GraphicsCheckCommandLine(void); + +void I_ShutdownGraphics(void); + +// Takes full 8 bit values. +void I_SetPalette (byte* palette); +int I_GetPaletteIndex(int r, int g, int b); + +void I_UpdateNoBlit (void); +void I_FinishUpdate (void); + +void I_ReadScreen (pixel_t* scr); + +void I_BeginRead (void); + +void I_SetWindowTitle(const char *title); + +void I_CheckIsScreensaver(void); +void I_SetGrabMouseCallback(grabmouse_callback_t func); + +void I_DisplayFPSDots(boolean dots_on); +void I_BindVideoVariables(void); + +void I_InitWindowTitle(void); +void I_RegisterWindowIcon(const unsigned int *icon, int width, int height); +void I_InitWindowIcon(void); + +// Called before processing any tics in a frame (just after displaying a frame). +// Time consuming syncronous operations are performed here (joystick reading). + +void I_StartFrame (void); + +// Called before processing each tic in a frame. +// Quick syncronous operations are performed here. + +void I_StartTic (void); + +// Enable the loading disk image displayed when reading from disk. + +void I_EnableLoadingDisk(int xoffs, int yoffs); + +extern char *video_driver; +extern boolean screenvisible; + +extern int vanilla_keyboard_mapping; +extern boolean screensaver_mode; +extern int usegamma; +extern pixel_t *I_VideoBuffer; + +extern int screen_width; +extern int screen_height; +extern int fullscreen; +extern int aspect_ratio_correct; +extern int integer_scaling; +extern int smooth_pixel_scaling; +extern int vga_porch_flash; +extern int force_software_renderer; + +extern int png_screenshots; + +extern char *window_position; +void I_GetWindowPosition(int *x, int *y, int w, int h); + +// Joystic/gamepad hysteresis +extern unsigned int joywait; + +extern int usemouse; + + +#endif \ No newline at end of file diff --git a/games/NXDoom/src/i_videohr.c b/games/NXDoom/src/i_videohr.c new file mode 100644 index 00000000000..08e23033677 --- /dev/null +++ b/games/NXDoom/src/i_videohr.c @@ -0,0 +1,257 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// SDL emulation of VGA 640x480x4 planar video mode, +// for Hexen startup loading screen. +// + +#include "SDL.h" +#include "string.h" + +#include "doomtype.h" +#include "i_timer.h" +#include "i_video.h" + +// Palette fade-in takes two seconds + +#define FADE_TIME 2000 + +#define HR_SCREENWIDTH 640 +#define HR_SCREENHEIGHT 480 + +static SDL_Window *hr_screen = NULL; +static SDL_Surface *hr_surface = NULL; +static const char *window_title = ""; + +boolean I_SetVideoModeHR(void) +{ + int x, y; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + return false; + } + + I_GetWindowPosition(&x, &y, HR_SCREENWIDTH, HR_SCREENHEIGHT); + + // Create screen surface at the native desktop pixel depth (bpp=0), + // as we cannot trust true 8-bit to reliably work nowadays. + hr_screen = SDL_CreateWindow(window_title, x, y, + HR_SCREENWIDTH, HR_SCREENHEIGHT, + 0); + + if (hr_screen == NULL) + { + SDL_QuitSubSystem(SDL_INIT_VIDEO); + return false; + } + + // We do all actual drawing into an intermediate surface. + hr_surface = SDL_CreateRGBSurface(0, HR_SCREENWIDTH, HR_SCREENHEIGHT, + 8, 0, 0, 0, 0); + + return true; +} + +void I_SetWindowTitleHR(const char *title) +{ + window_title = title; +} + +void I_UnsetVideoModeHR(void) +{ + if (hr_screen != NULL) + { + SDL_QuitSubSystem(SDL_INIT_VIDEO); + hr_screen = NULL; + SDL_FreeSurface(hr_surface); + hr_surface = NULL; + } +} + +void I_ClearScreenHR(void) +{ + SDL_Rect area = { 0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT }; + + SDL_FillRect(hr_surface, &area, 0); +} + +void I_SlamBlockHR(int x, int y, int w, int h, const byte *src) +{ + SDL_Rect blit_rect; + const byte *srcptrs[4]; + byte srcbits[4]; + byte *dest; + int x1, y1; + int i; + int bit; + + // Set up source pointers to read from source buffer - each 4-bit + // pixel has its bits split into four sub-buffers + + for (i=0; i<4; ++i) + { + srcptrs[i] = src + (i * w * h / 8); + } + + if (SDL_LockSurface(hr_surface) < 0) + { + return; + } + + // Draw each pixel + + bit = 0; + + for (y1=y; y1pixels) + y1 * hr_surface->pitch + x; + + for (x1=x; x1> (7 - (bit % 8))) & 0x1; + } + + // Reassemble the pixel value + + *dest = (srcbits[0] << 0) + | (srcbits[1] << 1) + | (srcbits[2] << 2) + | (srcbits[3] << 3); + + // Next pixel! + + ++dest; + ++bit; + } + } + + SDL_UnlockSurface(hr_surface); + + // Update the region we drew. + blit_rect.x = x; + blit_rect.y = y; + blit_rect.w = w; + blit_rect.h = h; + SDL_BlitSurface(hr_surface, &blit_rect, + SDL_GetWindowSurface(hr_screen), &blit_rect); + SDL_UpdateWindowSurfaceRects(hr_screen, &blit_rect, 1); +} + +void I_SlamHR(const byte *buffer) +{ + I_SlamBlockHR(0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT, buffer); +} + +void I_InitPaletteHR(void) +{ + // ... +} + +void I_SetPaletteHR(const byte *palette) +{ + SDL_Rect screen_rect = {0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT}; + SDL_Color sdlpal[16]; + int i; + + for (i=0; i<16; ++i) + { + sdlpal[i].r = palette[i * 3 + 0] * 4; + sdlpal[i].g = palette[i * 3 + 1] * 4; + sdlpal[i].b = palette[i * 3 + 2] * 4; + } + + // After setting colors, update the screen. + SDL_SetPaletteColors(hr_surface->format->palette, sdlpal, 0, 16); + SDL_BlitSurface(hr_surface, &screen_rect, + SDL_GetWindowSurface(hr_screen), &screen_rect); + SDL_UpdateWindowSurfaceRects(hr_screen, &screen_rect, 1); +} + +void I_FadeToPaletteHR(const byte *palette) +{ + byte tmppal[16 * 3]; + int starttime; + int elapsed; + int i; + + starttime = I_GetTimeMS(); + + for (;;) + { + elapsed = I_GetTimeMS() - starttime; + + if (elapsed >= FADE_TIME) + { + break; + } + + // Generate the fake palette + + for (i=0; i<16 * 3; ++i) + { + tmppal[i] = (palette[i] * elapsed) / FADE_TIME; + } + + I_SetPaletteHR(tmppal); + SDL_UpdateWindowSurface(hr_screen); + + // Sleep a bit + + I_Sleep(10); + } + + // Set the final palette + + I_SetPaletteHR(palette); +} + +void I_BlackPaletteHR(void) +{ + byte blackpal[16 * 3]; + + memset(blackpal, 0, sizeof(blackpal)); + + I_SetPaletteHR(blackpal); +} + +// Check if the user has hit the escape key to abort startup. +boolean I_CheckAbortHR(void) +{ + SDL_Event ev; + boolean result = false; + + // Not initialized? + if (hr_surface == NULL) + { + return false; + } + + while (SDL_PollEvent(&ev)) + { + if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE) + { + result = true; + } + } + + return result; +} + diff --git a/games/NXDoom/src/i_videohr.h b/games/NXDoom/src/i_videohr.h new file mode 100644 index 00000000000..d0a0dca501c --- /dev/null +++ b/games/NXDoom/src/i_videohr.h @@ -0,0 +1,35 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// SDL emulation of VGA 640x480x4 planar video mode, +// for Hexen startup loading screen. +// + +#ifndef I_VIDEOHR_H +#define I_VIDEOHR_H + +boolean I_SetVideoModeHR(void); +void I_UnsetVideoModeHR(void); +void I_SetWindowTitleHR(const char *title); +void I_ClearScreenHR(void); +void I_SlamBlockHR(int x, int y, int w, int h, const byte *src); +void I_SlamHR(const byte *buffer); +void I_InitPaletteHR(void); +void I_SetPaletteHR(const byte *palette); +void I_FadeToPaletteHR(const byte *palette); +void I_BlackPaletteHR(void); +boolean I_CheckAbortHR(void); + +#endif /* #ifndef I_VIDEOHR_H */ + diff --git a/games/NXDoom/src/i_winmusic.c b/games/NXDoom/src/i_winmusic.c new file mode 100644 index 00000000000..6871fe22451 --- /dev/null +++ b/games/NXDoom/src/i_winmusic.c @@ -0,0 +1,1920 @@ +// +// Copyright(C) 2021-2022 Roman Fomin +// Copyright(C) 2022 ceski +// +// 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. +// +// DESCRIPTION: +// Windows native MIDI + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include + +#include "doomtype.h" +#include "i_sound.h" +#include "i_system.h" +#include "m_misc.h" +#include "memio.h" +#include "mus2mid.h" +#include "midifile.h" +#include "midifallback.h" + +enum +{ + COMP_VANILLA, + COMP_STANDARD, + COMP_FULL, +}; + +enum +{ + RESET_TYPE_NONE, + RESET_TYPE_GM, + RESET_TYPE_GS, + RESET_TYPE_XG, +}; + +char *winmm_midi_device = NULL; +int winmm_complevel = COMP_VANILLA; +int winmm_reset_type = RESET_TYPE_GM; +int winmm_reset_delay = 0; + +static const byte gm_system_on[] = { + 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 +}; + +static const byte gs_reset[] = { + 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7 +}; + +static const byte xg_system_on[] = { + 0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00, 0xF7 +}; + +static const byte ff_loopStart[] = {'l', 'o', 'o', 'p', 'S', 't', 'a', 'r', 't'}; +static const byte ff_loopEnd[] = {'l', 'o', 'o', 'p', 'E', 'n', 'd'}; + +static boolean use_fallback; + +#define DEFAULT_VOLUME 100 +static byte channel_volume[MIDI_CHANNELS_PER_TRACK]; +static float volume_factor = 0.0f; +static boolean update_volume = false; + +typedef enum +{ + STATE_STARTUP, + STATE_SHUTDOWN, + STATE_EXIT, + STATE_STOPPING, + STATE_STOPPED, + STATE_PLAYING, + STATE_PAUSED +} win_midi_state_t; + +static win_midi_state_t win_midi_state; + +static DWORD timediv; +static DWORD tempo; + +static UINT MidiDevice; +static HMIDISTRM hMidiStream; +static MIDIHDR MidiStreamHdr; +static HANDLE hBufferReturnEvent; +static HANDLE hStoppedEvent; +static HANDLE hPlayerThread; +static CRITICAL_SECTION CriticalSection; + +#define EMIDI_DEVICE (1U << EMIDI_DEVICE_GENERAL_MIDI) + +// This is a reduced Windows MIDIEVENT structure for MEVT_F_SHORT +// type of events. + +typedef struct +{ + DWORD dwDeltaTime; + DWORD dwStreamID; // always 0 + DWORD dwEvent; +} native_event_t; + +typedef struct +{ + midi_track_iter_t *iter; + unsigned int elapsed_time; + unsigned int saved_elapsed_time; + boolean end_of_track; + boolean saved_end_of_track; + unsigned int emidi_device_flags; + boolean emidi_designated; + boolean emidi_program; + boolean emidi_volume; + int emidi_loop_count; +} win_midi_track_t; + +typedef struct +{ + win_midi_track_t *tracks; + unsigned int elapsed_time; + unsigned int saved_elapsed_time; + unsigned int num_tracks; + boolean registered; + boolean looping; + boolean ff_loop; + boolean ff_restart; + boolean rpg_loop; +} win_midi_song_t; + +static win_midi_song_t song; + +#define BUFFER_INITIAL_SIZE 8192 + +#define PLAYER_THREAD_WAIT_TIME 3000 + +typedef struct +{ + byte *data; + unsigned int size; + unsigned int position; + boolean prepared; +} buffer_t; + +static buffer_t buffer; + +// Maximum of 4 events in the buffer for faster volume updates. + +#define STREAM_MAX_EVENTS 4 + +#define MAKE_EVT(a, b, c, d) \ + ((DWORD)(a) | ((DWORD)(b) << 8) | ((DWORD)(c) << 16) | ((DWORD)(d) << 24)) + +#define PADDED_SIZE(x) (((x) + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1)) + +// Check for midiStream errors. + +static void MidiError(const char *prefix, DWORD dwError) +{ + wchar_t werror[MAXERRORLENGTH]; + MMRESULT mmr; + + mmr = midiOutGetErrorTextW(dwError, (LPWSTR) werror, MAXERRORLENGTH); + if (mmr == MMSYSERR_NOERROR) + { + char *error = M_ConvertWideToUtf8(werror); + fprintf(stderr, "%s: %s.\n", prefix, error); + free(error); + } + else + { + fprintf(stderr, "%s: Unknown midiStream error.\n", prefix); + } +} + +// midiStream callback. + +static void CALLBACK MidiStreamProc(HMIDIOUT hMidi, UINT uMsg, + DWORD_PTR dwInstance, DWORD_PTR dwParam1, + DWORD_PTR dwParam2) +{ + if (uMsg == MOM_DONE) + { + SetEvent(hBufferReturnEvent); + } +} + +// Unprepare MIDI header. The calling thread must have exclusive access to the +// shared resources in this function. + +static void UnprepareHeader(void) +{ + // Avoid ASan detection. Commentary by Microsoft: "It looks like + // midiOutPrepareHeader() allocates with HeapAlloc(), and then + // midiOutUnprepareHeader() deallocates with GlobalFree(GlobalHandle + // (...)). By design, this kind of allocator mismatch is an issue that ASan + // is designed to catch. It is theoretically possible for us to support + // this kind of code, but it’s not very high priority since it is undefined + // behavior, though it happens to work right now outside of ASan." + // https://developercommunity.visualstudio.com/t/1597288 + +#ifndef __SANITIZE_ADDRESS__ + MIDIHDR *hdr = &MidiStreamHdr; + MMRESULT mmr; + + mmr = midiOutUnprepareHeader((HMIDIOUT)hMidiStream, hdr, sizeof(MIDIHDR)); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiOutUnprepareHeader", mmr); + } +#endif +} + +// Allocate buffer. The calling thread must have exclusive access to the shared +// resources in this function. + +static void AllocateBuffer(const unsigned int size) +{ + buffer.size = PADDED_SIZE(size); + buffer.data = I_Realloc(buffer.data, buffer.size); +} + +// Pads the buffer with zeros so that an integral number of DWORDs are stored. +// Required for long messages (SysEx). Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static void WriteBufferPad(void) +{ + unsigned int padding = PADDED_SIZE(buffer.position); + memset(buffer.data + buffer.position, 0, padding - buffer.position); + buffer.position = padding; +} + +// Writes message data to buffer. Call this function from the MIDI thread only, +// with exclusive access to shared resources. + +static void WriteBuffer(const byte *ptr, unsigned int size) +{ + if (buffer.prepared) + { + UnprepareHeader(); + buffer.prepared = false; + } + + if (buffer.position + size >= buffer.size) + { + AllocateBuffer(size + buffer.size * 2); + } + + memcpy(buffer.data + buffer.position, ptr, size); + buffer.position += size; +} + +// Streams out the current buffer. Call this function from the MIDI thread only, +// with exclusive access to shared resources. + +static void StreamOut(void) +{ + MIDIHDR *hdr = &MidiStreamHdr; + MMRESULT mmr; + + memset(hdr, 0, sizeof(*hdr)); + hdr->lpData = (LPSTR)buffer.data; + hdr->dwBytesRecorded = buffer.position; + hdr->dwBufferLength = buffer.size; + + // Reset buffer position even if midiStreamOut fails. + buffer.position = 0; + + mmr = midiOutPrepareHeader((HMIDIOUT)hMidiStream, hdr, sizeof(MIDIHDR)); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiOutPrepareHeader", mmr); + return; + } + + buffer.prepared = true; + + mmr = midiStreamOut(hMidiStream, hdr, sizeof(MIDIHDR)); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamOut", mmr); + } +} + +// Writes a short MIDI message. Call this function from the MIDI thread only, +// with exclusive access to shared resources. + +static void SendShortMsg(unsigned int delta_time, byte status, byte channel, + byte param1, byte param2) +{ + native_event_t native_event; + native_event.dwDeltaTime = delta_time; + native_event.dwStreamID = 0; + native_event.dwEvent = MAKE_EVT(status | channel, param1, param2, MEVT_SHORTMSG); + WriteBuffer((byte *)&native_event, sizeof(native_event_t)); +} + +// Writes a short MIDI message (from an event). Call this function from the MIDI +// thread only, with exclusive access to shared resources. + +static void SendChannelMsg(unsigned int delta_time, const midi_event_t *event, + boolean use_param2) +{ + SendShortMsg(delta_time, event->event_type, event->data.channel.channel, + event->data.channel.param1, + use_param2 ? event->data.channel.param2 : 0); +} + +// Writes a long MIDI message (SysEx). Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static void SendLongMsg(unsigned int delta_time, const byte *ptr, + unsigned int length) +{ + native_event_t native_event; + native_event.dwDeltaTime = delta_time; + native_event.dwStreamID = 0; + native_event.dwEvent = MAKE_EVT(length, 0, 0, MEVT_LONGMSG); + WriteBuffer((byte *)&native_event, sizeof(native_event_t)); + WriteBuffer(ptr, length); + WriteBufferPad(); +} + +// Writes an RPN message set to NULL (0x7F). Prevents accidental data entry. +// Call this function from the MIDI thread only, with exclusive access to shared +// resources. + +static void SendNullRPN(unsigned int delta_time, const midi_event_t *event) +{ + const byte channel = event->data.channel.channel; + SendShortMsg(delta_time, MIDI_EVENT_CONTROLLER, channel, + MIDI_CONTROLLER_RPN_LSB, MIDI_RPN_NULL); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, channel, + MIDI_CONTROLLER_RPN_MSB, MIDI_RPN_NULL); +} + +// Writes a NOP message (ticks). Call this function from the MIDI thread only, +// with exclusive access to shared resources. + +static void SendNOPMsg(unsigned int delta_time) +{ + native_event_t native_event; + native_event.dwDeltaTime = delta_time; + native_event.dwStreamID = 0; + native_event.dwEvent = MAKE_EVT(0, 0, 0, MEVT_NOP); + WriteBuffer((byte *)&native_event, sizeof(native_event_t)); +} + +// Writes a NOP message (milliseconds). Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static void SendDelayMsg(unsigned int time_ms) +{ + // Convert ms to ticks (see "Standard MIDI Files 1.0" page 14). + const unsigned int ticks = (float) time_ms * 1000 * timediv / tempo + 0.5f; + SendNOPMsg(ticks); +} + +// Writes a tempo MIDI meta message. Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static void UpdateTempo(unsigned int delta_time, const midi_event_t *event) +{ + native_event_t native_event; + + tempo = MAKE_EVT(event->data.meta.data[2], event->data.meta.data[1], + event->data.meta.data[0], 0); + + native_event.dwDeltaTime = delta_time; + native_event.dwStreamID = 0; + native_event.dwEvent = MAKE_EVT(tempo, 0, 0, MEVT_TEMPO); + WriteBuffer((byte *)&native_event, sizeof(native_event_t)); +} + +// Writes a MIDI volume message. The value is scaled by the volume slider. Call +// this function from the MIDI thread only, with exclusive access to shared +// resources. + +static void SendManualVolumeMsg(unsigned int delta_time, byte channel, + byte volume) +{ + unsigned int scaled_volume; + + scaled_volume = volume * volume_factor + 0.5f; + + if (scaled_volume > 127) + { + scaled_volume = 127; + } + + SendShortMsg(delta_time, MIDI_EVENT_CONTROLLER, channel, + MIDI_CONTROLLER_VOLUME_MSB, scaled_volume); + + channel_volume[channel] = volume; +} + +// Writes a MIDI volume message (from an event). The value is scaled by the +// volume slider. Call this function from the MIDI thread only, with exclusive +// access to shared resources. + +static void SendVolumeMsg(unsigned int delta_time, const midi_event_t *event) +{ + SendManualVolumeMsg(delta_time, event->data.channel.channel, + event->data.channel.param2); +} + +// Sets each channel to its saved volume level, scaled by the volume slider. +// Call this function from the MIDI thread only, with exclusive access to shared +// resources. + +static void UpdateVolume(void) +{ + int i; + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + SendManualVolumeMsg(0, i, channel_volume[i]); + } +} + +// Sets each channel to the default volume level, scaled by the volume slider. +// Call this function from the MIDI thread only, with exclusive access to shared +// resources. + +static void ResetVolume(void) +{ + int i; + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + SendManualVolumeMsg(0, i, DEFAULT_VOLUME); + } +} + +// Writes "notes off" and "sound off" messages for each channel. Some devices +// may support only one or the other. Held notes (sustained, etc.) are released +// to prevent hanging notes. Call this function from the MIDI thread only, with +// exclusive access to shared resources. + +static void SendNotesSoundOff(void) +{ + int i; + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_NOTES_OFF, 0); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_SOUND_OFF, 0); + } +} + +// Resets commonly used controllers. This is only for a reset type of "none" for +// devices that don't support SysEx resets. Call this function from the MIDI +// thread only, with exclusive access to shared resources. + +static void ResetControllers(void) +{ + int i; + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + // Reset commonly used controllers. + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RESET_ALL_CTRLS, 0); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_PAN, 64); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_BANK_SELECT_MSB, 0); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_BANK_SELECT_LSB, 0); + SendShortMsg(0, MIDI_EVENT_PROGRAM_CHANGE, i, 0, 0); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_REVERB, 40); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_CHORUS, 0); + } +} + +// Resets the pitch bend sensitivity for each channel. This must be sent during +// a reset due to an MS GS Wavetable Synth bug. Call this function from the MIDI +// thread only, with exclusive access to shared resources. + +static void ResetPitchBendSensitivity(void) +{ + int i; + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + // Set RPN MSB/LSB to pitch bend sensitivity. + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_LSB, 0); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_MSB, 0); + + // Reset pitch bend sensitivity to +/- 2 semitones and 0 cents. + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_DATA_ENTRY_MSB, 2); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_DATA_ENTRY_LSB, 0); + + // Set RPN MSB/LSB to null value after data entry. + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_LSB, 127); + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_MSB, 127); + } +} + +// Resets the MIDI device. Call this function before each song starts and once +// at shut down. Call this function from the MIDI thread only, with exclusive +// access to shared resources. + +static void ResetDevice(void) +{ + MIDI_ResetFallback(); + use_fallback = false; + + switch (winmm_reset_type) + { + case RESET_TYPE_NONE: + ResetControllers(); + break; + + case RESET_TYPE_GS: + SendLongMsg(0, gs_reset, sizeof(gs_reset)); + use_fallback = (winmm_complevel != COMP_VANILLA); + break; + + case RESET_TYPE_XG: + SendLongMsg(0, xg_system_on, sizeof(xg_system_on)); + break; + + default: + SendLongMsg(0, gm_system_on, sizeof(gm_system_on)); + break; + } + + // MS GS Wavetable Synth doesn't reset pitch bend sensitivity. + ResetPitchBendSensitivity(); + + // Reset volume (initial playback or on shutdown if no SysEx reset). + // Scale by slider on initial playback, max on shutdown. + if (win_midi_state == STATE_STARTUP) + { + ResetVolume(); + } + else if (winmm_reset_type == RESET_TYPE_NONE) + { + volume_factor = 1.0f; + ResetVolume(); + } + + // Send delay after reset. This is for hardware devices only (e.g. SC-55). + if (winmm_reset_delay > 0) + { + SendDelayMsg(winmm_reset_delay); + } +} + +// Normally, volume is controlled by channel volume messages. Roland defined a +// special SysEx message called "part level" that is equivalent to this. MS GS +// Wavetable Synth ignores these messages, but other MIDI devices support them. +// Returns true if there is a match. Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static boolean IsPartLevel(const byte *msg, unsigned int length) +{ + if (length == 10 && + msg[0] == 0x41 && // Roland + msg[2] == 0x42 && // GS + msg[3] == 0x12 && // DT1 + msg[4] == 0x40 && // Address MSB + msg[5] >= 0x10 && // Address + msg[5] <= 0x1F && // Address + msg[6] == 0x19 && // Address LSB + msg[9] == 0xF7) // SysEx EOX + { + const byte checksum = + 128 - ((int) msg[4] + msg[5] + msg[6] + msg[7]) % 128; + + if (msg[8] == checksum) + { + // GS Part Level (aka Channel Volume) + // 41 42 12 40 19 F7 + return true; + } + } + + return false; +} + +// Checks if the current SysEx message matches any known SysEx reset message. +// Returns true if there is a match. Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static boolean IsSysExReset(const byte *msg, unsigned int length) +{ + if (length < 5) + { + return false; + } + + switch (msg[0]) + { + case 0x41: // Roland + switch (msg[2]) + { + case 0x42: // GS + switch (msg[3]) + { + case 0x12: // DT1 + if (length == 10 && + msg[4] == 0x00 && // Address MSB + msg[5] == 0x00 && // Address + msg[6] == 0x7F && // Address LSB + ((msg[7] == 0x00 && // Data (MODE-1) + msg[8] == 0x01) || // Checksum (MODE-1) + (msg[7] == 0x01 && // Data (MODE-2) + msg[8] == 0x00))) // Checksum (MODE-2) + { + // SC-88 System Mode Set + // 41 42 12 00 00 7F 00 01 F7 (MODE-1) + // 41 42 12 00 00 7F 01 00 F7 (MODE-2) + return true; + } + else if (length == 10 && + msg[4] == 0x40 && // Address MSB + msg[5] == 0x00 && // Address + msg[6] == 0x7F && // Address LSB + msg[7] == 0x00 && // Data (GS Reset) + msg[8] == 0x41) // Checksum + { + // GS Reset + // 41 42 12 40 00 7F 00 41 F7 + return true; + } + break; + } + break; + } + break; + + case 0x43: // Yamaha + switch (msg[2]) + { + case 0x2B: // TG300 + if (length == 9 && + msg[3] == 0x00 && // Start Address b20 - b14 + msg[4] == 0x00 && // Start Address b13 - b7 + msg[5] == 0x7F && // Start Address b6 - b0 + msg[6] == 0x00 && // Data + msg[7] == 0x01) // Checksum + { + // TG300 All Parameter Reset + // 43 2B 00 00 7F 00 01 F7 + return true; + } + break; + + case 0x4C: // XG + if (length == 8 && + msg[3] == 0x00 && // Address High + msg[4] == 0x00 && // Address Mid + (msg[5] == 0x7E || // Address Low (System On) + msg[5] == 0x7F) && // Address Low (All Parameter Reset) + msg[6] == 0x00) // Data + { + // XG System On, XG All Parameter Reset + // 43 4C 00 00 7E 00 F7 + // 43 4C 00 00 7F 00 F7 + return true; + } + break; + } + break; + + case 0x7E: // Universal Non-Real Time + switch (msg[2]) + { + case 0x09: // General Midi + if (length == 5 && + (msg[3] == 0x01 || // GM System On + msg[3] == 0x02 || // GM System Off + msg[3] == 0x03)) // GM2 System On + { + // GM System On/Off, GM2 System On + // 7E 09 01 F7 + // 7E 09 02 F7 + // 7E 09 03 F7 + return true; + } + break; + } + break; + } + return false; +} + +// Writes a MIDI SysEx message. Call this function from the MIDI thread only, +// with exclusive access to shared resources. + +static void SendSysExMsg(unsigned int delta_time, const midi_event_t *event) +{ + native_event_t native_event; + const byte event_type = MIDI_EVENT_SYSEX; + const byte *data = event->data.sysex.data; + const unsigned int length = event->data.sysex.length; + + if (IsPartLevel(data, length)) + { + byte channel; + + // Convert "block number" to a channel number. + if (data[5] == 0x10) // Channel 10 + { + channel = 9; + } + else if (data[5] < 0x1A) // Channels 1-9 + { + channel = (data[5] & 0x0F) - 1; + } + else // Channels 11-16 + { + channel = data[5] & 0x0F; + } + + // Replace SysEx part level message with channel volume message. + SendManualVolumeMsg(delta_time, channel, data[7]); + return; + } + + // Send the SysEx message. + native_event.dwDeltaTime = delta_time; + native_event.dwStreamID = 0; + native_event.dwEvent = MAKE_EVT(length + sizeof(byte), 0, 0, MEVT_LONGMSG); + WriteBuffer((byte *)&native_event, sizeof(native_event_t)); + WriteBuffer(&event_type, sizeof(byte)); + WriteBuffer(data, length); + WriteBufferPad(); + + if (IsSysExReset(data, length)) + { + // SysEx reset also resets volume. Take the default channel volumes + // and scale them by the user's volume slider. + ResetVolume(); + + // Disable instrument fallback and give priority to MIDI file. Fallback + // assumes GS (SC-55 level) and the MIDI file could be GM, GM2, XG, or + // GS (SC-88 or higher). Preserve the composer's intent. + if (use_fallback) + { + MIDI_ResetFallback(); + use_fallback = false; + } + } +} + +// Writes a MIDI program change message. If applicable, emulates capital tone +// fallback to fix invalid instruments. Call this function from the MIDI thread +// only, with exclusive access to shared resources. + +static void SendProgramMsg(unsigned int delta_time, byte channel, byte program, + const midi_fallback_t *fallback) +{ + switch ((int)fallback->type) + { + case FALLBACK_BANK_MSB: + SendShortMsg(delta_time, MIDI_EVENT_CONTROLLER, channel, + MIDI_CONTROLLER_BANK_SELECT_MSB, fallback->value); + SendShortMsg(0, MIDI_EVENT_PROGRAM_CHANGE, channel, program, 0); + break; + + case FALLBACK_DRUMS: + SendShortMsg(delta_time, MIDI_EVENT_PROGRAM_CHANGE, channel, + fallback->value, 0); + break; + + default: + SendShortMsg(delta_time, MIDI_EVENT_PROGRAM_CHANGE, channel, + program, 0); + break; + } +} + +// Sets a Final Fantasy or RPG Maker loop point. Call this function from the +// MIDI thread only, with exclusive access to shared resources. + +static void SetLoopPoint(void) +{ + unsigned int i; + + for (i = 0; i < song.num_tracks; ++i) + { + MIDI_SetLoopPoint(song.tracks[i].iter); + song.tracks[i].saved_end_of_track = song.tracks[i].end_of_track; + song.tracks[i].saved_elapsed_time = song.tracks[i].elapsed_time; + } + song.saved_elapsed_time = song.elapsed_time; +} + +// Checks if the MIDI meta message contains a Final Fantasy loop marker. Call +// this function from the MIDI thread only, with exclusive access to shared +// resources. + +static void CheckFFLoop(const midi_event_t *event) +{ + if (event->data.meta.length == sizeof(ff_loopStart) && + !memcmp(event->data.meta.data, ff_loopStart, sizeof(ff_loopStart))) + { + SetLoopPoint(); + song.ff_loop = true; + } + else if (song.ff_loop && event->data.meta.length == sizeof(ff_loopEnd) && + !memcmp(event->data.meta.data, ff_loopEnd, sizeof(ff_loopEnd))) + { + song.ff_restart = true; + } +} + +// Writes an EMIDI message. Call this function from the MIDI thread only, with +// exclusive access to shared resources. + +static void SendEMIDI(unsigned int delta_time, const midi_event_t *event, + win_midi_track_t *track, const midi_fallback_t *fallback) +{ + unsigned int i; + unsigned int flag; + int count; + + switch (event->data.channel.param1) + { + case EMIDI_CONTROLLER_TRACK_DESIGNATION: + if (track->elapsed_time < timediv) + { + flag = event->data.channel.param2; + + if (flag == EMIDI_DEVICE_ALL) + { + track->emidi_device_flags = UINT_MAX; + track->emidi_designated = true; + } + else if (flag <= EMIDI_DEVICE_ULTRASOUND) + { + track->emidi_device_flags |= 1U << flag; + track->emidi_designated = true; + } + } + SendNOPMsg(delta_time); + break; + + case EMIDI_CONTROLLER_TRACK_EXCLUSION: + if (song.rpg_loop) + { + SetLoopPoint(); + } + else if (track->elapsed_time < timediv) + { + flag = event->data.channel.param2; + + if (!track->emidi_designated) + { + track->emidi_device_flags = UINT_MAX; + track->emidi_designated = true; + } + + if (flag <= EMIDI_DEVICE_ULTRASOUND) + { + track->emidi_device_flags &= ~(1U << flag); + } + } + SendNOPMsg(delta_time); + break; + + case EMIDI_CONTROLLER_PROGRAM_CHANGE: + if (track->emidi_program || track->elapsed_time < timediv) + { + track->emidi_program = true; + SendProgramMsg(delta_time, event->data.channel.channel, + event->data.channel.param2, fallback); + } + else + { + SendNOPMsg(delta_time); + } + break; + + case EMIDI_CONTROLLER_VOLUME: + if (track->emidi_volume || track->elapsed_time < timediv) + { + track->emidi_volume = true; + SendVolumeMsg(delta_time, event); + } + else + { + SendNOPMsg(delta_time); + } + break; + + case EMIDI_CONTROLLER_LOOP_BEGIN: + count = event->data.channel.param2; + count = (count == 0) ? (-1) : count; + track->emidi_loop_count = count; + MIDI_SetLoopPoint(track->iter); + SendNOPMsg(delta_time); + break; + + case EMIDI_CONTROLLER_LOOP_END: + if (event->data.channel.param2 == EMIDI_LOOP_FLAG) + { + if (track->emidi_loop_count != 0) + { + MIDI_RestartAtLoopPoint(track->iter); + } + + if (track->emidi_loop_count > 0) + { + track->emidi_loop_count--; + } + } + SendNOPMsg(delta_time); + break; + + case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: + count = event->data.channel.param2; + count = (count == 0) ? (-1) : count; + for (i = 0; i < song.num_tracks; ++i) + { + song.tracks[i].emidi_loop_count = count; + MIDI_SetLoopPoint(song.tracks[i].iter); + song.tracks[i].saved_end_of_track = song.tracks[i].end_of_track; + song.tracks[i].saved_elapsed_time = song.tracks[i].elapsed_time; + } + song.saved_elapsed_time = song.elapsed_time; + SendNOPMsg(delta_time); + break; + + case EMIDI_CONTROLLER_GLOBAL_LOOP_END: + if (event->data.channel.param2 == EMIDI_LOOP_FLAG) + { + for (i = 0; i < song.num_tracks; ++i) + { + if (song.tracks[i].emidi_loop_count != 0) + { + MIDI_RestartAtLoopPoint(song.tracks[i].iter); + song.tracks[i].end_of_track = + song.tracks[i].saved_end_of_track; + song.tracks[i].elapsed_time = + song.tracks[i].saved_elapsed_time; + song.elapsed_time = song.saved_elapsed_time; + } + + if (song.tracks[i].emidi_loop_count > 0) + { + song.tracks[i].emidi_loop_count--; + } + } + } + SendNOPMsg(delta_time); + break; + } +} + +// Writes a MIDI meta message. Call this function from the MIDI thread only, +// with exclusive access to shared resources. + +static void SendMetaMsg(unsigned int delta_time, const midi_event_t *event, + win_midi_track_t *track) +{ + switch (event->data.meta.type) + { + case MIDI_META_END_OF_TRACK: + track->end_of_track = true; + SendNOPMsg(delta_time); + break; + + case MIDI_META_SET_TEMPO: + UpdateTempo(delta_time, event); + break; + + case MIDI_META_MARKER: + if (winmm_complevel != COMP_VANILLA) + { + CheckFFLoop(event); + } + SendNOPMsg(delta_time); + break; + + default: + SendNOPMsg(delta_time); + break; + } +} + +// AddToBuffer function for vanilla (DMX MPU-401) compatibility level. Do not +// call this function directly. See the AddToBuffer function pointer. + +static boolean AddToBuffer_Vanilla(unsigned int delta_time, + const midi_event_t *event, + win_midi_track_t *track) +{ + switch ((int) event->event_type) + { + case MIDI_EVENT_SYSEX: + SendNOPMsg(delta_time); + return false; + + case MIDI_EVENT_META: + SendMetaMsg(delta_time, event, track); + break; + + case MIDI_EVENT_CONTROLLER: + switch (event->data.channel.param1) + { + case MIDI_CONTROLLER_BANK_SELECT_MSB: + case MIDI_CONTROLLER_BANK_SELECT_LSB: + // DMX has broken bank select support and runs in GM mode. + SendChannelMsg(delta_time, event, false); + break; + + case MIDI_CONTROLLER_MODULATION: + case MIDI_CONTROLLER_PAN: + case MIDI_CONTROLLER_EXPRESSION: + case MIDI_CONTROLLER_HOLD1_PEDAL: + case MIDI_CONTROLLER_SOFT_PEDAL: + case MIDI_CONTROLLER_REVERB: + case MIDI_CONTROLLER_CHORUS: + case MIDI_CONTROLLER_ALL_SOUND_OFF: + case MIDI_CONTROLLER_ALL_NOTES_OFF: + SendChannelMsg(delta_time, event, true); + break; + + case MIDI_CONTROLLER_VOLUME_MSB: + SendVolumeMsg(delta_time, event); + break; + + case MIDI_CONTROLLER_RESET_ALL_CTRLS: + // MS GS Wavetable Synth resets volume if param2 isn't zero. + SendChannelMsg(delta_time, event, false); + break; + + default: + SendNOPMsg(delta_time); + break; + } + break; + + case MIDI_EVENT_NOTE_OFF: + case MIDI_EVENT_NOTE_ON: + case MIDI_EVENT_PITCH_BEND: + SendChannelMsg(delta_time, event, true); + break; + + case MIDI_EVENT_PROGRAM_CHANGE: + SendChannelMsg(delta_time, event, false); + break; + + default: + SendNOPMsg(delta_time); + break; + } + + return true; +} + +// AddToBuffer function for standard and full MIDI compatibility levels. Do not +// call this function directly. See the AddToBuffer function pointer. + +static boolean AddToBuffer_Standard(unsigned int delta_time, + const midi_event_t *event, + win_midi_track_t *track) +{ + midi_fallback_t fallback = {FALLBACK_NONE, 0}; + + if (use_fallback) + { + MIDI_CheckFallback(event, &fallback, winmm_complevel == COMP_FULL); + } + + switch ((int) event->event_type) + { + case MIDI_EVENT_SYSEX: + if (winmm_complevel == COMP_FULL) + { + SendSysExMsg(delta_time, event); + } + else + { + SendNOPMsg(delta_time); + } + return false; + + case MIDI_EVENT_META: + SendMetaMsg(delta_time, event, track); + return true; + } + + if (track->emidi_designated && (EMIDI_DEVICE & ~track->emidi_device_flags)) + { + // Send NOP if this device has been excluded from this track. + SendNOPMsg(delta_time); + return true; + } + + switch ((int) event->event_type) + { + case MIDI_EVENT_CONTROLLER: + switch (event->data.channel.param1) + { + case MIDI_CONTROLLER_BANK_SELECT_MSB: + case MIDI_CONTROLLER_MODULATION: + case MIDI_CONTROLLER_DATA_ENTRY_MSB: + case MIDI_CONTROLLER_PAN: + case MIDI_CONTROLLER_EXPRESSION: + case MIDI_CONTROLLER_DATA_ENTRY_LSB: + case MIDI_CONTROLLER_HOLD1_PEDAL: + case MIDI_CONTROLLER_SOFT_PEDAL: + case MIDI_CONTROLLER_REVERB: + case MIDI_CONTROLLER_CHORUS: + case MIDI_CONTROLLER_ALL_SOUND_OFF: + case MIDI_CONTROLLER_ALL_NOTES_OFF: + case MIDI_CONTROLLER_POLY_MODE_OFF: + case MIDI_CONTROLLER_POLY_MODE_ON: + SendChannelMsg(delta_time, event, true); + break; + + case MIDI_CONTROLLER_VOLUME_MSB: + if (track->emidi_volume) + { + SendNOPMsg(delta_time); + } + else + { + SendVolumeMsg(delta_time, event); + } + break; + + case MIDI_CONTROLLER_VOLUME_LSB: + SendNOPMsg(delta_time); + break; + + case MIDI_CONTROLLER_BANK_SELECT_LSB: + SendChannelMsg(delta_time, event, + fallback.type != FALLBACK_BANK_LSB); + break; + + case MIDI_CONTROLLER_NRPN_LSB: + case MIDI_CONTROLLER_NRPN_MSB: + if (winmm_complevel == COMP_FULL) + { + SendChannelMsg(delta_time, event, true); + } + else + { + // MS GS Wavetable Synth nulls RPN for any NRPN. + SendNullRPN(delta_time, event); + } + break; + + case MIDI_CONTROLLER_RPN_LSB: + switch (event->data.channel.param2) + { + case MIDI_RPN_PITCH_BEND_SENS_LSB: + case MIDI_RPN_FINE_TUNING_LSB: + case MIDI_RPN_COARSE_TUNING_LSB: + case MIDI_RPN_NULL: + SendChannelMsg(delta_time, event, true); + break; + + default: + if (winmm_complevel == COMP_FULL) + { + SendChannelMsg(delta_time, event, true); + } + else + { + // MS GS Wavetable Synth ignores other RPNs. + SendNullRPN(delta_time, event); + } + break; + } + break; + + case MIDI_CONTROLLER_RPN_MSB: + switch (event->data.channel.param2) + { + case MIDI_RPN_MSB: + case MIDI_RPN_NULL: + SendChannelMsg(delta_time, event, true); + break; + + default: + if (winmm_complevel == COMP_FULL) + { + SendChannelMsg(delta_time, event, true); + } + else + { + // MS GS Wavetable Synth ignores other RPNs. + SendNullRPN(delta_time, event); + } + break; + } + break; + + case EMIDI_CONTROLLER_TRACK_DESIGNATION: + case EMIDI_CONTROLLER_TRACK_EXCLUSION: + case EMIDI_CONTROLLER_PROGRAM_CHANGE: + case EMIDI_CONTROLLER_VOLUME: + case EMIDI_CONTROLLER_LOOP_BEGIN: + case EMIDI_CONTROLLER_LOOP_END: + case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: + case EMIDI_CONTROLLER_GLOBAL_LOOP_END: + SendEMIDI(delta_time, event, track, &fallback); + break; + + case MIDI_CONTROLLER_RESET_ALL_CTRLS: + // MS GS Wavetable Synth resets volume if param2 isn't zero. + SendChannelMsg(delta_time, event, false); + break; + + default: + if (winmm_complevel == COMP_FULL) + { + SendChannelMsg(delta_time, event, true); + } + else + { + SendNOPMsg(delta_time); + } + break; + } + break; + + case MIDI_EVENT_NOTE_OFF: + case MIDI_EVENT_NOTE_ON: + case MIDI_EVENT_PITCH_BEND: + SendChannelMsg(delta_time, event, true); + break; + + case MIDI_EVENT_PROGRAM_CHANGE: + if (track->emidi_program) + { + SendNOPMsg(delta_time); + } + else + { + SendProgramMsg(delta_time, event->data.channel.channel, + event->data.channel.param1, &fallback); + } + break; + + case MIDI_EVENT_AFTERTOUCH: + if (winmm_complevel == COMP_FULL) + { + SendChannelMsg(delta_time, event, true); + } + else + { + SendNOPMsg(delta_time); + } + break; + + case MIDI_EVENT_CHAN_AFTERTOUCH: + if (winmm_complevel == COMP_FULL) + { + SendChannelMsg(delta_time, event, false); + } + else + { + SendNOPMsg(delta_time); + } + break; + + default: + SendNOPMsg(delta_time); + break; + } + + return true; +} + +// Function pointer determined by the desired MIDI compatibility level. Set +// during initialization by the main thread, then called from the MIDI thread +// only. The calling thread must have exclusive access to the shared resources +// in this function. + +static boolean (*AddToBuffer)(unsigned int delta_time, + const midi_event_t *event, + win_midi_track_t *track) = AddToBuffer_Vanilla; + +// Restarts a song that uses a Final Fantasy or RPG Maker loop point. Call this +// function from the MIDI thread only, with exclusive access to shared +// resources. + +static void RestartLoop(void) +{ + unsigned int i; + + for (i = 0; i < song.num_tracks; ++i) + { + MIDI_RestartAtLoopPoint(song.tracks[i].iter); + song.tracks[i].end_of_track = song.tracks[i].saved_end_of_track; + song.tracks[i].elapsed_time = song.tracks[i].saved_elapsed_time; + } + song.elapsed_time = song.saved_elapsed_time; +} + +// Restarts a song that uses standard looping. Call this function from the MIDI +// thread only, with exclusive access to shared resources. + +static void RestartTracks(void) +{ + unsigned int i; + + for (i = 0; i < song.num_tracks; ++i) + { + MIDI_RestartIterator(song.tracks[i].iter); + song.tracks[i].elapsed_time = 0; + song.tracks[i].end_of_track = false; + song.tracks[i].emidi_device_flags = 0; + song.tracks[i].emidi_designated = false; + song.tracks[i].emidi_program = false; + song.tracks[i].emidi_volume = false; + song.tracks[i].emidi_loop_count = 0; + } + song.elapsed_time = 0; +} + +// The controllers "EMIDI track exclusion" and "RPG Maker loop point" share the +// same number (CC#111) and are not compatible with each other. As a workaround, +// allow an RPG Maker loop point only if no other EMIDI events are present. Call +// this function from the MIDI thread only, before the song starts, with +// exclusive access to shared resources. + +static boolean IsRPGLoop(void) +{ + unsigned int i; + unsigned int num_rpg_events = 0; + unsigned int num_emidi_events = 0; + midi_event_t *event = NULL; + + for (i = 0; i < song.num_tracks; ++i) + { + while (MIDI_GetNextEvent(song.tracks[i].iter, &event)) + { + if (event->event_type == MIDI_EVENT_CONTROLLER) + { + switch (event->data.channel.param1) + { + case EMIDI_CONTROLLER_TRACK_EXCLUSION: + num_rpg_events++; + break; + + case EMIDI_CONTROLLER_TRACK_DESIGNATION: + case EMIDI_CONTROLLER_PROGRAM_CHANGE: + case EMIDI_CONTROLLER_VOLUME: + case EMIDI_CONTROLLER_LOOP_BEGIN: + case EMIDI_CONTROLLER_LOOP_END: + case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: + case EMIDI_CONTROLLER_GLOBAL_LOOP_END: + num_emidi_events++; + break; + } + } + } + + MIDI_RestartIterator(song.tracks[i].iter); + } + + return (num_rpg_events == 1 && num_emidi_events == 0); +} + +// Fills the output buffer with events from the current song and then streams it +// out. Call this function from the MIDI thread only, with exclusive access to +// shared resources. + +static void FillBuffer(void) +{ + unsigned int i; + int num_events; + + for (num_events = 0; num_events < STREAM_MAX_EVENTS; ) + { + midi_event_t *event = NULL; + win_midi_track_t *track = NULL; + unsigned int min_time = UINT_MAX; + unsigned int delta_time; + + // Find next event across all tracks. + for (i = 0; i < song.num_tracks; ++i) + { + if (!song.tracks[i].end_of_track) + { + unsigned int time = song.tracks[i].elapsed_time + + MIDI_GetDeltaTime(song.tracks[i].iter); + if (time < min_time) + { + min_time = time; + track = &song.tracks[i]; + } + } + } + + // No more events. Restart or stop song. + if (track == NULL) + { + if (song.elapsed_time) + { + if (song.ff_restart || song.rpg_loop) + { + song.ff_restart = false; + RestartLoop(); + continue; + } + else if (song.looping) + { + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) + { + SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RESET_ALL_CTRLS, 0); + } + RestartTracks(); + continue; + } + } + break; + } + + track->elapsed_time = min_time; + delta_time = min_time - song.elapsed_time; + song.elapsed_time = min_time; + + if (!MIDI_GetNextEvent(track->iter, &event)) + { + track->end_of_track = true; + continue; + } + + // Restart FF loop after sending all events that share same timediv. + if (song.ff_restart && MIDI_GetDeltaTime(track->iter) > 0) + { + song.ff_restart = false; + RestartLoop(); + continue; + } + + if (!AddToBuffer(delta_time, event, track)) + { + StreamOut(); + return; + } + + num_events++; + } + + if (num_events) + { + StreamOut(); + } +} + +// The Windows API documentation states: "Applications should not call any +// multimedia functions from inside the callback function, as doing so can +// cause a deadlock." We use a thread to avoid possible deadlocks. + +static DWORD WINAPI PlayerProc(void) +{ + boolean keep_going = true; + + while (keep_going) + { + if (WaitForSingleObject(hBufferReturnEvent, INFINITE) != WAIT_OBJECT_0) + { + continue; + } + + // The MIDI thread must have exclusive access to shared resources until + // the end of the current loop iteration or when the thread exits. + EnterCriticalSection(&CriticalSection); + + switch (win_midi_state) + { + case STATE_STARTUP: + ResetDevice(); + StreamOut(); + song.rpg_loop = IsRPGLoop(); + win_midi_state = STATE_PLAYING; + break; + + case STATE_SHUTDOWN: + // Send notes/sound off prior to reset to prevent volume spikes. + SendNotesSoundOff(); + ResetDevice(); + StreamOut(); + win_midi_state = STATE_EXIT; + break; + + case STATE_EXIT: + keep_going = false; + break; + + case STATE_PLAYING: + if (update_volume) + { + UpdateVolume(); + StreamOut(); + update_volume = false; + break; + } + FillBuffer(); + break; + + case STATE_STOPPING: + // Send notes/sound off to prevent hanging notes. + SendNotesSoundOff(); + StreamOut(); + win_midi_state = STATE_STOPPED; + break; + + case STATE_STOPPED: + SetEvent(hStoppedEvent); + break; + + case STATE_PAUSED: + break; + } + + LeaveCriticalSection(&CriticalSection); + } + + return 0; +} + +// Restarts the MIDI stream. Call this function from the main thread only, with +// exclusive access to shared resources. + +static void StreamStart(void) +{ + MMRESULT mmr; + + SetEvent(hBufferReturnEvent); + + mmr = midiStreamRestart(hMidiStream); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamRestart", mmr); + } +} + +// Turns off notes but does not release all held ones (use SendNotesSoundOff() +// to prevent hanging notes). The output buffer is returned to the callback +// function and flagged as MHDR_DONE. Call this function from the main thread +// only, with exclusive access to shared resources. + +static void StreamStop(void) +{ + MMRESULT mmr; + + mmr = midiStreamStop(hMidiStream); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamStop", mmr); + } + + ResetEvent(hBufferReturnEvent); + ResetEvent(hStoppedEvent); +} + +static boolean I_WIN_InitMusic(void) +{ + const int all_devices = midiOutGetNumDevs(); + int i; + MMRESULT mmr; + + if (winmm_midi_device == NULL) + { + winmm_midi_device = M_StringDuplicate(""); + } + + for (i = 0; i < all_devices; i++) + { + MIDIOUTCAPS caps; + + if (midiOutGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR && + !strncasecmp(winmm_midi_device, caps.szPname, MAXPNAMELEN)) + { + MidiDevice = i; + break; + } + } + + if (i == all_devices) + { + free(winmm_midi_device); + winmm_midi_device = M_StringDuplicate("Microsoft MIDI Mapper"); + MidiDevice = MIDI_MAPPER; + } + + mmr = midiStreamOpen(&hMidiStream, &MidiDevice, (DWORD)1, + (DWORD_PTR)MidiStreamProc, (DWORD_PTR)NULL, + CALLBACK_FUNCTION); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamOpen", mmr); + hMidiStream = NULL; + return false; + } + + AllocateBuffer(BUFFER_INITIAL_SIZE); + + hBufferReturnEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + hStoppedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + hPlayerThread = + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayerProc, 0, 0, 0); + SetThreadPriority(hPlayerThread, THREAD_PRIORITY_TIME_CRITICAL); + InitializeCriticalSectionAndSpinCount(&CriticalSection, 1024); + + AddToBuffer = (winmm_complevel == COMP_VANILLA) ? AddToBuffer_Vanilla + : AddToBuffer_Standard; + MIDI_InitFallback(); + + return true; +} + +static void I_WIN_SetMusicVolume(int volume) +{ + static int last_volume = -1; + + if (last_volume == volume) + { + // Ignore holding key down in volume menu. + return; + } + last_volume = volume; + + EnterCriticalSection(&CriticalSection); + volume_factor = sqrtf((float)volume / 120); + update_volume = song.registered; + LeaveCriticalSection(&CriticalSection); +} + +static void I_WIN_StopSong(void) +{ + if (!hMidiStream) + { + return; + } + + EnterCriticalSection(&CriticalSection); + StreamStop(); + win_midi_state = STATE_STOPPING; + StreamStart(); + LeaveCriticalSection(&CriticalSection); + + WaitForSingleObject(hStoppedEvent, PLAYER_THREAD_WAIT_TIME); + StreamStop(); +} + +static void I_WIN_PlaySong(void *handle, boolean looping) +{ + if (!hMidiStream) + { + return; + } + + EnterCriticalSection(&CriticalSection); + song.looping = looping; + win_midi_state = STATE_STARTUP; + StreamStart(); + LeaveCriticalSection(&CriticalSection); +} + +static void I_WIN_PauseSong(void) +{ + if (!hMidiStream) + { + return; + } + + I_WIN_StopSong(); + + EnterCriticalSection(&CriticalSection); + win_midi_state = STATE_PAUSED; + LeaveCriticalSection(&CriticalSection); +} + +static void I_WIN_ResumeSong(void) +{ + if (!hMidiStream) + { + return; + } + + EnterCriticalSection(&CriticalSection); + if (win_midi_state == STATE_PAUSED) + { + win_midi_state = STATE_PLAYING; + StreamStart(); + } + LeaveCriticalSection(&CriticalSection); +} + +// Determine whether memory block is a .mid file + +static boolean IsMid(byte *mem, int len) +{ + return len > 4 && !memcmp(mem, "MThd", 4); +} + +static boolean ConvertMus(byte *musdata, int len, const char *filename) +{ + MEMFILE *instream; + MEMFILE *outstream; + void *outbuf; + size_t outbuf_len; + int result; + + instream = mem_fopen_read(musdata, len); + outstream = mem_fopen_write(); + + result = mus2mid(instream, outstream); + + if (result == 0) + { + mem_get_buf(outstream, &outbuf, &outbuf_len); + + M_WriteFile(filename, outbuf, outbuf_len); + } + + mem_fclose(instream); + mem_fclose(outstream); + + return result; +} + +static void *I_WIN_RegisterSong(void *data, int len) +{ + unsigned int i; + char *filename; + midi_file_t *file; + + MIDIPROPTIMEDIV prop_timediv; + MIDIPROPTEMPO prop_tempo; + MMRESULT mmr; + + if (!hMidiStream) + { + return NULL; + } + + // MUS files begin with "MUS" + // Reject anything which doesnt have this signature + + filename = M_TempFile("doom.mid"); + + if (IsMid(data, len)) + { + M_WriteFile(filename, data, len); + } + else + { + // Assume a MUS file and try to convert + + ConvertMus(data, len, filename); + } + + file = MIDI_LoadFile(filename); + + M_remove(filename); + free(filename); + + if (file == NULL) + { + fprintf(stderr, "I_WIN_RegisterSong: Failed to load MID.\n"); + return NULL; + } + + prop_timediv.cbStruct = sizeof(MIDIPROPTIMEDIV); + prop_timediv.dwTimeDiv = MIDI_GetFileTimeDivision(file); + mmr = midiStreamProperty(hMidiStream, (LPBYTE)&prop_timediv, + MIDIPROP_SET | MIDIPROP_TIMEDIV); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamProperty", mmr); + return NULL; + } + timediv = prop_timediv.dwTimeDiv; + + // Set initial tempo. + prop_tempo.cbStruct = sizeof(MIDIPROPTIMEDIV); + prop_tempo.dwTempo = 500000; // 120 BPM + mmr = midiStreamProperty(hMidiStream, (LPBYTE)&prop_tempo, + MIDIPROP_SET | MIDIPROP_TEMPO); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamProperty", mmr); + return NULL; + } + tempo = prop_tempo.dwTempo; + + song.num_tracks = MIDI_NumTracks(file); + song.tracks = calloc(song.num_tracks, sizeof(win_midi_track_t)); + for (i = 0; i < song.num_tracks; ++i) + { + song.tracks[i].iter = MIDI_IterateTrack(file, i); + } + song.registered = true; + + return file; +} + +static void I_WIN_UnRegisterSong(void *handle) +{ + if (!hMidiStream) + { + return; + } + + if (song.tracks) + { + unsigned int i; + for (i = 0; i < song.num_tracks; ++i) + { + MIDI_FreeIterator(song.tracks[i].iter); + song.tracks[i].iter = NULL; + } + free(song.tracks); + song.tracks = NULL; + } + if (handle) + { + MIDI_FreeFile(handle); + } + song.elapsed_time = 0; + song.saved_elapsed_time = 0; + song.num_tracks = 0; + song.registered = false; + song.looping = false; + song.ff_loop = false; + song.ff_restart = false; + song.rpg_loop = false; +} + +static void I_WIN_ShutdownMusic(void) +{ + MMRESULT mmr; + + if (!hMidiStream) + { + return; + } + + EnterCriticalSection(&CriticalSection); + StreamStop(); + I_WIN_UnRegisterSong(NULL); + win_midi_state = STATE_SHUTDOWN; + StreamStart(); + LeaveCriticalSection(&CriticalSection); + + if (WaitForSingleObject(hPlayerThread, PLAYER_THREAD_WAIT_TIME) == + WAIT_OBJECT_0) + { + CloseHandle(hPlayerThread); + hPlayerThread = NULL; + } + StreamStop(); + + if (buffer.prepared) + { + UnprepareHeader(); + buffer.prepared = false; + } + + mmr = midiStreamClose(hMidiStream); + if (mmr != MMSYSERR_NOERROR) + { + MidiError("midiStreamClose", mmr); + } + hMidiStream = NULL; + + free(buffer.data); + buffer.data = NULL; + buffer.size = 0; + buffer.position = 0; + + CloseHandle(hBufferReturnEvent); + CloseHandle(hStoppedEvent); + DeleteCriticalSection(&CriticalSection); +} + +static boolean I_WIN_MusicIsPlaying(void) +{ + return (song.num_tracks > 0); +} + +static const snddevice_t music_win_devices[] = +{ + SNDDEVICE_PAS, + SNDDEVICE_WAVEBLASTER, + SNDDEVICE_SOUNDCANVAS, + SNDDEVICE_GENMIDI, + SNDDEVICE_AWE32, +}; + +const music_module_t music_win_module = +{ + music_win_devices, + arrlen(music_win_devices), + I_WIN_InitMusic, + I_WIN_ShutdownMusic, + I_WIN_SetMusicVolume, + I_WIN_PauseSong, + I_WIN_ResumeSong, + I_WIN_RegisterSong, + I_WIN_UnRegisterSong, + I_WIN_PlaySong, + I_WIN_StopSong, + I_WIN_MusicIsPlaying, + NULL, // Poll +}; + +#endif diff --git a/games/NXDoom/src/m_argv.c b/games/NXDoom/src/m_argv.c new file mode 100644 index 00000000000..724a42b6726 --- /dev/null +++ b/games/NXDoom/src/m_argv.c @@ -0,0 +1,556 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// + + +#include +#include +#include +#include + +#include "SDL_stdinc.h" + +#include "doomtype.h" +#include "d_iwad.h" +#include "i_system.h" +#include "m_misc.h" +#include "m_argv.h" // haleyjd 20110212: warning fix + +int myargc; +char** myargv; + + + + +// +// M_CheckParm +// Checks for the given parameter +// in the program's command line arguments. +// Returns the argument number (1 to argc-1) +// or 0 if not present +// + +int M_CheckParmWithArgs(const char *check, int num_args) +{ + int i; + + // Check if myargv[i] has been set to NULL in LoadResponseFile(), + // which may call I_Error(), which in turn calls M_ParmExists("-nogui"). + + for (i = 1; i < myargc - num_args && myargv[i]; i++) + { + if (!strcasecmp(check, myargv[i])) + return i; + } + + return 0; +} + +// +// M_ParmExists +// +// Returns true if the given parameter exists in the program's command +// line arguments, false if not. +// + +boolean M_ParmExists(const char *check) +{ + return M_CheckParm(check) != 0; +} + +int M_CheckParm(const char *check) +{ + return M_CheckParmWithArgs(check, 0); +} + +#define MAXARGVS 100 + +static void LoadResponseFile(int argv_index, const char *filename) +{ + FILE *handle; + int size; + char *infile; + char *file; + char **newargv; + int newargc; + int i, k; + + // Read the response file into memory + handle = M_fopen(filename, "rb"); + + if (handle == NULL) + { + printf ("\nNo such response file!"); + exit(1); + } + + printf("Found response file %s!\n", filename); + + size = M_FileLength(handle); + + // Read in the entire file + // Allocate one byte extra - this is in case there is an argument + // at the end of the response file, in which case a '\0' will be + // needed. + + file = malloc(size + 1); + + i = 0; + + while (i < size) + { + k = fread(file + i, 1, size - i, handle); + + if (k < 0) + { + I_Error("Failed to read full contents of '%s'", filename); + } + + i += k; + } + + fclose(handle); + + // Create new arguments list array + + newargv = malloc(sizeof(char *) * MAXARGVS); + newargc = 0; + memset(newargv, 0, sizeof(char *) * MAXARGVS); + + // Copy all the arguments in the list up to the response file + + if (argv_index >= MAXARGVS) + { + I_Error("Too many arguments up to the response file!"); + } + + for (i=0; i= size) + { + break; + } + + // If the next argument is enclosed in quote marks, treat + // the contents as a single argument. This allows long filenames + // to be specified. + + if (infile[k] == '\"') + { + char *argstart; + // Skip the first character(") + ++k; + + argstart = &infile[k]; + + // Read all characters between quotes + + while (k < size && infile[k] != '\"' && infile[k] != '\n') + { + ++k; + } + + if (k >= size || infile[k] == '\n') + { + I_Error("Quotes unclosed in response file '%s'", + filename); + } + + // Cut off the string at the closing quote + + infile[k] = '\0'; + ++k; + + if (newargc >= MAXARGVS) + { + I_Error("Too many arguments in the response file!"); + } + + newargv[newargc++] = M_StringDuplicate(argstart); + } + else + { + char *argstart; + // Read in the next argument until a space is reached + + argstart = &infile[k]; + + while(k < size && !isspace(infile[k])) + { + ++k; + } + + // Cut off the end of the argument at the first space + + infile[k] = '\0'; + ++k; + + if (newargc >= MAXARGVS) + { + I_Error("Too many arguments in the response file!"); + } + + newargv[newargc++] = M_StringDuplicate(argstart); + } + } + + // Add arguments following the response file argument + + if (newargc + myargc - (argv_index + 1) >= MAXARGVS) + { + I_Error("Too many arguments following the response file!"); + } + + for (i=argv_index + 1; i + // + // Load extra command-line arguments from the given response + // file. Arguments read from the file are inserted into the + // command line, replacing this argument. A response file can + // also be loaded using the abbreviated syntax '@file.rsp'. + // + i = M_CheckParmWithArgs("-response", 1); + if (i <= 0) + { + break; + } + // Replace the -response argument so that the next time through + // the loop we'll ignore it. Since some parameters stop reading when + // an argument beginning with a '-' is encountered, we keep something + // that starts with a '-'. + free(myargv[i]); + myargv[i] = M_StringDuplicate("-_"); + LoadResponseFile(i + 1, myargv[i + 1]); + } +} + +#if defined(_WIN32) +enum +{ + FILETYPE_UNKNOWN = 0x0, + FILETYPE_IWAD = 0x2, + FILETYPE_PWAD = 0x4, + FILETYPE_DEH = 0x8, + FILETYPE_DEMO = 0x10, +}; + +static boolean FileIsDemoLump(const char *filename) +{ + FILE *handle; + int count, ver; + byte buf[12], *p = buf; + + handle = M_fopen(filename, "rb"); + + if (handle == NULL) + { + return false; + } + + count = fread(buf, 1, sizeof(buf), handle); + fclose(handle); + + if (count != sizeof(buf)) + { + return false; + } + + ver = *p++; + + if (ver >= 0 && ver <= 4) // v1.0/v1.1/v1.2 + { + p--; + } + else + { + switch (ver) + { + case 104: // v1.4 + case 105: // v1.5 + case 106: // v1.6/v1.666 + case 107: // v1.7/v1.7a + case 108: // v1.8 + case 109: // v1.9 + case 111: // v1.91 hack + break; + default: + return false; + break; + } + } + + if (*p++ > 5) // skill + { + return false; + } + if (*p++ > 9) // episode + { + return false; + } + if (*p++ > 99) // map + { + return false; + } + + return true; +} + +static int GuessFileType(const char *name) +{ + int ret = FILETYPE_UNKNOWN; + const char *base; + char *lower; + static boolean iwad_found = false, demo_found = false; + + base = M_BaseName(name); + lower = M_StringDuplicate(base); + M_ForceLowercase(lower); + + // only ever add one argument to the -iwad parameter + + if (iwad_found == false && D_IsIWADName(lower)) + { + ret = FILETYPE_IWAD; + iwad_found = true; + } + else if (M_StringEndsWith(lower, ".wad")) + { + ret = FILETYPE_PWAD; + } + else if (M_StringEndsWith(lower, ".lmp")) + { + // only ever add one argument to the -playdemo parameter + + if (demo_found == false && FileIsDemoLump(name)) + { + ret = FILETYPE_DEMO; + demo_found = true; + } + else + { + ret = FILETYPE_PWAD; + } + } + else if (M_StringEndsWith(lower, ".deh") || +// M_StringEndsWith(lower, ".bex") || + M_StringEndsWith(lower, ".hhe") || + M_StringEndsWith(lower, ".seh")) + { + ret = FILETYPE_DEH; + } + + free(lower); + + return ret; +} + +typedef struct +{ + char *str; + int type, stable; +} argument_t; + +static int CompareByFileType(const void *a, const void *b) +{ + const argument_t *arg_a = (const argument_t *) a; + const argument_t *arg_b = (const argument_t *) b; + + const int ret = arg_a->type - arg_b->type; + + return ret ? ret : (arg_a->stable - arg_b->stable); +} + +void M_AddLooseFiles(void) +{ + int i, types = 0; + char **newargv; + argument_t *arguments; + + if (myargc < 2) + { + return; + } + + // allocate space for up to four additional regular parameters + // (-iwad, -merge, -deh, -playdemo) + + arguments = malloc((myargc + 4) * sizeof(*arguments)); + memset(arguments, 0, (myargc + 4) * sizeof(*arguments)); + + // check the command line and make sure it does not already + // contain any regular parameters or response files + // but only fully-qualified LFS or UNC file paths + + for (i = 1; i < myargc; i++) + { + char *arg = myargv[i]; + int type; + + if (strlen(arg) < 3 || + arg[0] == '-' || + arg[0] == '@' || + ((!isalpha(arg[0]) || arg[1] != ':' || arg[2] != '\\') && + (arg[0] != '\\' || arg[1] != '\\'))) + { + free(arguments); + return; + } + + type = GuessFileType(arg); + arguments[i].str = arg; + arguments[i].type = type; + arguments[i].stable = i; + types |= type; + } + + // add space for one additional regular parameter + // for each discovered file type in the new argument list + // and sort parameters right before their corresponding file paths + + if (types & FILETYPE_IWAD) + { + arguments[myargc].str = M_StringDuplicate("-iwad"); + arguments[myargc].type = FILETYPE_IWAD - 1; + myargc++; + } + if (types & FILETYPE_PWAD) + { + arguments[myargc].str = M_StringDuplicate("-merge"); + arguments[myargc].type = FILETYPE_PWAD - 1; + myargc++; + } + if (types & FILETYPE_DEH) + { + arguments[myargc].str = M_StringDuplicate("-deh"); + arguments[myargc].type = FILETYPE_DEH - 1; + myargc++; + } + if (types & FILETYPE_DEMO) + { + arguments[myargc].str = M_StringDuplicate("-playdemo"); + arguments[myargc].type = FILETYPE_DEMO - 1; + myargc++; + } + + newargv = malloc(myargc * sizeof(*newargv)); + + // sort the argument list by file type, except for the zeroth argument + // which is the executable invocation itself + + SDL_qsort(arguments + 1, myargc - 1, sizeof(*arguments), CompareByFileType); + + newargv[0] = myargv[0]; + + for (i = 1; i < myargc; i++) + { + newargv[i] = arguments[i].str; + } + + free(arguments); + + free(myargv); + myargv = newargv; +} +#endif + +// Return the name of the executable used to start the program: + +const char *M_GetExecutableName(void) +{ + return M_BaseName(myargv[0]); +} + +char *exedir = NULL; + +void M_SetExeDir(void) +{ + char *dirname; + + dirname = M_DirName(myargv[0]); + exedir = M_StringJoin(dirname, DIR_SEPARATOR_S, NULL); + free(dirname); +} diff --git a/games/NXDoom/src/m_argv.h b/games/NXDoom/src/m_argv.h new file mode 100644 index 00000000000..b42f11cd479 --- /dev/null +++ b/games/NXDoom/src/m_argv.h @@ -0,0 +1,53 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Nil. +// + + +#ifndef __M_ARGV__ +#define __M_ARGV__ + +#include "doomtype.h" + +// +// MISC +// +extern int myargc; +extern char** myargv; + +extern char *exedir; +void M_SetExeDir(void); + +// Returns the position of the given parameter +// in the arg list (0 if not found). +int M_CheckParm (const char* check); + +// Same as M_CheckParm, but checks that num_args arguments are available +// following the specified argument. +int M_CheckParmWithArgs(const char *check, int num_args); + +void M_FindResponseFile(void); +void M_AddLooseFiles(void); + +// Parameter has been specified? + +boolean M_ParmExists(const char *check); + +// Get name of executable used to run this program: + +const char *M_GetExecutableName(void); + +#endif diff --git a/games/NXDoom/src/m_bbox.c b/games/NXDoom/src/m_bbox.c new file mode 100644 index 00000000000..fb3f270d1b4 --- /dev/null +++ b/games/NXDoom/src/m_bbox.c @@ -0,0 +1,54 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Main loop menu stuff. +// Random number LUT. +// Default Config File. +// PCX Screenshots. +// + + + +#include "m_bbox.h" + + + + +void M_ClearBox (fixed_t *box) +{ + box[BOXTOP] = box[BOXRIGHT] = INT_MIN; + box[BOXBOTTOM] = box[BOXLEFT] = INT_MAX; +} + +void +M_AddToBox +( fixed_t* box, + fixed_t x, + fixed_t y ) +{ + if (xbox[BOXRIGHT]) + box[BOXRIGHT] = x; + if (ybox[BOXTOP]) + box[BOXTOP] = y; +} + + + + + diff --git a/games/NXDoom/src/m_bbox.h b/games/NXDoom/src/m_bbox.h new file mode 100644 index 00000000000..5a7af57c458 --- /dev/null +++ b/games/NXDoom/src/m_bbox.h @@ -0,0 +1,47 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Nil. +// + + +#ifndef __M_BBOX__ +#define __M_BBOX__ + +#include + +#include "m_fixed.h" + + +// Bounding box coordinate storage. +enum +{ + BOXTOP, + BOXBOTTOM, + BOXLEFT, + BOXRIGHT +}; // bbox coordinates + +// Bounding box functions. +void M_ClearBox (fixed_t* box); + +void +M_AddToBox +( fixed_t* box, + fixed_t x, + fixed_t y ); + + +#endif diff --git a/games/NXDoom/src/m_cheat.c b/games/NXDoom/src/m_cheat.c new file mode 100644 index 00000000000..1565f9ef5e3 --- /dev/null +++ b/games/NXDoom/src/m_cheat.c @@ -0,0 +1,89 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Cheat sequence checking. +// + + + +#include + +#include "doomtype.h" +#include "m_cheat.h" + +// +// CHEAT SEQUENCE PACKAGE +// + +// +// Called in st_stuff module, which handles the input. +// Returns a 1 if the cheat was successful, 0 if failed. +// +int +cht_CheckCheat +( cheatseq_t* cht, + char key ) +{ + // if we make a short sequence on a cheat with parameters, this + // will not work in vanilla doom. behave the same. + + if (cht->parameter_chars > 0 && strlen(cht->sequence) < cht->sequence_len) + return false; + + if (cht->chars_read < strlen(cht->sequence)) + { + // still reading characters from the cheat code + // and verifying. reset back to the beginning + // if a key is wrong + + if (key == cht->sequence[cht->chars_read]) + ++cht->chars_read; + else + cht->chars_read = 0; + + cht->param_chars_read = 0; + } + else if (cht->param_chars_read < cht->parameter_chars) + { + // we have passed the end of the cheat sequence and are + // entering parameters now + + cht->parameter_buf[cht->param_chars_read] = key; + + ++cht->param_chars_read; + } + + if (cht->chars_read >= strlen(cht->sequence) + && cht->param_chars_read >= cht->parameter_chars) + { + cht->chars_read = cht->param_chars_read = 0; + + return true; + } + + // cheat not matched yet + + return false; +} + +void +cht_GetParam +( cheatseq_t* cht, + char* buffer ) +{ + memcpy(buffer, cht->parameter_buf, cht->parameter_chars); +} + + diff --git a/games/NXDoom/src/m_cheat.h b/games/NXDoom/src/m_cheat.h new file mode 100644 index 00000000000..6775e709e41 --- /dev/null +++ b/games/NXDoom/src/m_cheat.h @@ -0,0 +1,62 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Cheat code checking. +// + + +#ifndef __M_CHEAT__ +#define __M_CHEAT__ + +// +// CHEAT SEQUENCE PACKAGE +// + +// declaring a cheat + +#define CHEAT(value, parameters) \ + { value, sizeof(value) - 1, parameters, 0, 0, "" } + +#define MAX_CHEAT_LEN 25 +#define MAX_CHEAT_PARAMS 5 + +typedef struct +{ + // settings for this cheat + + char sequence[MAX_CHEAT_LEN]; + size_t sequence_len; + int parameter_chars; + + // state used during the game + + size_t chars_read; + int param_chars_read; + char parameter_buf[MAX_CHEAT_PARAMS]; +} cheatseq_t; + +int +cht_CheckCheat +( cheatseq_t* cht, + char key ); + + +void +cht_GetParam +( cheatseq_t* cht, + char* buffer ); + + +#endif diff --git a/games/NXDoom/src/m_config.c b/games/NXDoom/src/m_config.c new file mode 100644 index 00000000000..e1a0260a226 --- /dev/null +++ b/games/NXDoom/src/m_config.c @@ -0,0 +1,2811 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Configuration file interface. +// + + +#include +#include +#include +#include +#include +#include +#include + +#include "SDL_filesystem.h" + +#include "config.h" + +#include "doomtype.h" +#include "doomkeys.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" + +#include "z_zone.h" + +// +// DEFAULTS +// + +// Location where all configuration data is stored - +// default.cfg, savegames, etc. + +const char *configdir; + +static char *autoload_path = ""; + +// Default filenames for configuration files. + +static const char *default_main_config; +static const char *default_extra_config; + +typedef enum +{ + DEFAULT_INT, + DEFAULT_INT_HEX, + DEFAULT_STRING, + DEFAULT_FLOAT, + DEFAULT_KEY, +} default_type_t; + +typedef struct +{ + // Name of the variable + const char *name; + + // Pointer to the location in memory of the variable + union { + int *i; + char **s; + float *f; + } location; + + // Type of the variable + default_type_t type; + + // If this is a key value, the original integer scancode we read from + // the config file before translating it to the internal key value. + // If zero, we didn't read this value from a config file. + int untranslated; + + // The value we translated the scancode into when we read the + // config file on startup. If the variable value is different from + // this, it has been changed and needs to be converted; otherwise, + // use the 'untranslated' value. + int original_translated; + + // If true, this config variable has been bound to a variable + // and is being used. + boolean bound; +} default_t; + +typedef struct +{ + default_t *defaults; + int numdefaults; + const char *filename; +} default_collection_t; + +#define CONFIG_VARIABLE_GENERIC(name, type) \ + { #name, {NULL}, type, 0, 0, false } + +#define CONFIG_VARIABLE_KEY(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_KEY) +#define CONFIG_VARIABLE_INT(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_INT) +#define CONFIG_VARIABLE_INT_HEX(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_INT_HEX) +#define CONFIG_VARIABLE_FLOAT(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_FLOAT) +#define CONFIG_VARIABLE_STRING(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_STRING) + +//! @begin_config_file default + +static default_t doom_defaults_list[] = +{ + //! + // Mouse sensitivity. This value is used to multiply input mouse + // movement to control the effect of moving the mouse. + // + // The "normal" maximum value available for this through the + // in-game options menu is 9. A value of 31 or greater will cause + // the game to crash when entering the options menu. + // + + CONFIG_VARIABLE_INT(mouse_sensitivity), + + //! + // Volume of sound effects, range 0-15. + // + + CONFIG_VARIABLE_INT(sfx_volume), + + //! + // Volume of in-game music, range 0-15. + // + + CONFIG_VARIABLE_INT(music_volume), + + //! + // @game strife + // + // If non-zero, dialogue text is displayed over characters' pictures + // when engaging actors who have voices. + // + + CONFIG_VARIABLE_INT(show_talk), + + //! + // @game strife + // + // Volume of voice sound effects, range 0-15. + // + + CONFIG_VARIABLE_INT(voice_volume), + + //! + // @game doom + // + // If non-zero, messages are displayed on the heads-up display + // in the game ("picked up a clip", etc). If zero, these messages + // are not displayed. + // + + CONFIG_VARIABLE_INT(show_messages), + + //! + // Keyboard key to turn right. + // + + CONFIG_VARIABLE_KEY(key_right), + + //! + // Keyboard key to turn left. + // + + CONFIG_VARIABLE_KEY(key_left), + + //! + // Keyboard key to move forward. + // + + CONFIG_VARIABLE_KEY(key_up), + + //! + // Keyboard key to move backward. + // + + CONFIG_VARIABLE_KEY(key_down), + + //! + // Keyboard key to strafe left. + // + + CONFIG_VARIABLE_KEY(key_strafeleft), + + //! + // Keyboard key to strafe right. + // + + CONFIG_VARIABLE_KEY(key_straferight), + + //! + // @game strife + // + // Keyboard key to use health. + // + + CONFIG_VARIABLE_KEY(key_useHealth), + + //! + // @game hexen + // + // Keyboard key to jump. + // + + CONFIG_VARIABLE_KEY(key_jump), + + //! + // @game heretic hexen + // + // Keyboard key to fly upward. + // + + CONFIG_VARIABLE_KEY(key_flyup), + + //! + // @game heretic hexen + // + // Keyboard key to fly downwards. + // + + CONFIG_VARIABLE_KEY(key_flydown), + + //! + // @game heretic hexen + // + // Keyboard key to center flying. + // + + CONFIG_VARIABLE_KEY(key_flycenter), + + //! + // @game heretic hexen + // + // Keyboard key to look up. + // + + CONFIG_VARIABLE_KEY(key_lookup), + + //! + // @game heretic hexen + // + // Keyboard key to look down. + // + + CONFIG_VARIABLE_KEY(key_lookdown), + + //! + // @game heretic hexen + // + // Keyboard key to center the view. + // + + CONFIG_VARIABLE_KEY(key_lookcenter), + + //! + // @game strife + // + // Keyboard key to query inventory. + // + + CONFIG_VARIABLE_KEY(key_invquery), + + //! + // @game strife + // + // Keyboard key to display mission objective. + // + + CONFIG_VARIABLE_KEY(key_mission), + + //! + // @game strife + // + // Keyboard key to display inventory popup. + // + + CONFIG_VARIABLE_KEY(key_invPop), + + //! + // @game strife + // + // Keyboard key to display keys popup. + // + + CONFIG_VARIABLE_KEY(key_invKey), + + //! + // @game strife + // + // Keyboard key to jump to start of inventory. + // + + CONFIG_VARIABLE_KEY(key_invHome), + + //! + // @game strife + // + // Keyboard key to jump to end of inventory. + // + + CONFIG_VARIABLE_KEY(key_invEnd), + + //! + // @game heretic hexen + // + // Keyboard key to scroll left in the inventory. + // + + CONFIG_VARIABLE_KEY(key_invleft), + + //! + // @game heretic hexen + // + // Keyboard key to scroll right in the inventory. + // + + CONFIG_VARIABLE_KEY(key_invright), + + //! + // @game strife + // + // Keyboard key to scroll left in the inventory. + // + + CONFIG_VARIABLE_KEY(key_invLeft), + + //! + // @game strife + // + // Keyboard key to scroll right in the inventory. + // + + CONFIG_VARIABLE_KEY(key_invRight), + + //! + // @game heretic hexen + // + // Keyboard key to use the current item in the inventory. + // + + CONFIG_VARIABLE_KEY(key_useartifact), + + //! + // @game strife + // + // Keyboard key to use inventory item. + // + + CONFIG_VARIABLE_KEY(key_invUse), + + //! + // @game strife + // + // Keyboard key to drop an inventory item. + // + + CONFIG_VARIABLE_KEY(key_invDrop), + + //! + // @game strife + // + // Keyboard key to look up. + // + + CONFIG_VARIABLE_KEY(key_lookUp), + + //! + // @game strife + // + // Keyboard key to look down. + // + + CONFIG_VARIABLE_KEY(key_lookDown), + + //! + // Keyboard key to fire the currently selected weapon. + // + + CONFIG_VARIABLE_KEY(key_fire), + + //! + // Keyboard key to "use" an object, eg. a door or switch. + // + + CONFIG_VARIABLE_KEY(key_use), + + //! + // Keyboard key to turn on strafing. When held down, pressing the + // key to turn left or right causes the player to strafe left or + // right instead. + // + + CONFIG_VARIABLE_KEY(key_strafe), + + //! + // Keyboard key to make the player run. + // + + CONFIG_VARIABLE_KEY(key_speed), + + //! + // If non-zero, mouse input is enabled. If zero, mouse input is + // disabled. + // + + CONFIG_VARIABLE_INT(use_mouse), + + //! + // Mouse button to fire the currently selected weapon. + // + + CONFIG_VARIABLE_INT(mouseb_fire), + + //! + // Mouse button to turn on strafing. When held down, the player + // will strafe left and right instead of turning left and right. + // + + CONFIG_VARIABLE_INT(mouseb_strafe), + + //! + // Mouse button to move forward. + // + + CONFIG_VARIABLE_INT(mouseb_forward), + + //! + // Mouse button to turn on running. When held down, the player + // will run while moving. + // + + CONFIG_VARIABLE_INT(mouseb_speed), + + //! + // @game hexen strife + // + // Mouse button to jump. + // + + CONFIG_VARIABLE_INT(mouseb_jump), + + //! + // If non-zero, joystick input is enabled. + // + + CONFIG_VARIABLE_INT(use_joystick), + + //! + // Joystick virtual button that fires the current weapon. + // + + CONFIG_VARIABLE_INT(joyb_fire), + + //! + // Joystick virtual button that makes the player strafe while + // held down. + // + + CONFIG_VARIABLE_INT(joyb_strafe), + + //! + // Joystick virtual button to "use" an object, eg. a door or switch. + // + + CONFIG_VARIABLE_INT(joyb_use), + + //! + // Joystick virtual button that makes the player run while held + // down. + // + // If this has a value of 20 or greater, the player will always run, + // even if use_joystick is 0. + // + + CONFIG_VARIABLE_INT(joyb_speed), + + //! + // @game hexen strife + // + // Joystick virtual button that makes the player jump. + // + + CONFIG_VARIABLE_INT(joyb_jump), + + //! + // @game doom heretic hexen + // + // Screen size, range 3-11. + // + // A value of 11 gives a full-screen view with the status bar not + // displayed. A value of 10 gives a full-screen view with the + // status bar displayed. + // + + CONFIG_VARIABLE_INT(screenblocks), + + //! + // @game strife + // + // Screen size, range 3-11. + // + // A value of 11 gives a full-screen view with the status bar not + // displayed. A value of 10 gives a full-screen view with the + // status bar displayed. + // + + CONFIG_VARIABLE_INT(screensize), + + //! + // @game doom + // + // Screen detail. Zero gives normal "high detail" mode, while + // a non-zero value gives "low detail" mode. + // + + CONFIG_VARIABLE_INT(detaillevel), + + //! + // Number of sounds that will be played simultaneously. + // + + CONFIG_VARIABLE_INT(snd_channels), + + //! + // Music output device. A non-zero value gives MIDI sound output, + // while a value of zero disables music. + // + + CONFIG_VARIABLE_INT(snd_musicdevice), + + //! + // Sound effects device. A value of zero disables in-game sound + // effects, a value of 1 enables PC speaker sound effects, while + // a value in the range 2-9 enables the "normal" digital sound + // effects. + // + + CONFIG_VARIABLE_INT(snd_sfxdevice), + + //! + // SoundBlaster I/O port. Unused. + // + + CONFIG_VARIABLE_INT(snd_sbport), + + //! + // SoundBlaster IRQ. Unused. + // + + CONFIG_VARIABLE_INT(snd_sbirq), + + //! + // SoundBlaster DMA channel. Unused. + // + + CONFIG_VARIABLE_INT(snd_sbdma), + + //! + // Output port to use for OPL MIDI playback. Unused. + // + + CONFIG_VARIABLE_INT(snd_mport), + + //! + // Gamma correction level. A value of zero disables gamma + // correction, while a value in the range 1-4 gives increasing + // levels of gamma correction. + // + + CONFIG_VARIABLE_INT(usegamma), + + //! + // @game hexen + // + // Directory in which to store savegames. + // + + CONFIG_VARIABLE_STRING(savedir), + + //! + // @game hexen + // + // Controls whether messages are displayed in the heads-up display. + // If this has a non-zero value, messages are displayed. + // + + CONFIG_VARIABLE_INT(messageson), + + //! + // @game strife + // + // Name of background flat used by view border. + // + + CONFIG_VARIABLE_STRING(back_flat), + + //! + // @game strife + // + // Multiplayer nickname (?). + // + + CONFIG_VARIABLE_STRING(nickname), + + //! + // Multiplayer chat macro: message to send when alt+0 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro0), + + //! + // Multiplayer chat macro: message to send when alt+1 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro1), + + //! + // Multiplayer chat macro: message to send when alt+2 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro2), + + //! + // Multiplayer chat macro: message to send when alt+3 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro3), + + //! + // Multiplayer chat macro: message to send when alt+4 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro4), + + //! + // Multiplayer chat macro: message to send when alt+5 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro5), + + //! + // Multiplayer chat macro: message to send when alt+6 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro6), + + //! + // Multiplayer chat macro: message to send when alt+7 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro7), + + //! + // Multiplayer chat macro: message to send when alt+8 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro8), + + //! + // Multiplayer chat macro: message to send when alt+9 is pressed. + // + + CONFIG_VARIABLE_STRING(chatmacro9), + + //! + // @game strife + // + // Serial port number to use for SERSETUP.EXE (unused). + // + + CONFIG_VARIABLE_INT(comport), +}; + +static default_collection_t doom_defaults = +{ + doom_defaults_list, + arrlen(doom_defaults_list), + NULL, +}; + +//! @begin_config_file extended + +static default_t extra_defaults_list[] = +{ + //! + // Name of the SDL video driver to use. If this is an empty string, + // the default video driver is used. + // + + CONFIG_VARIABLE_STRING(video_driver), + + //! + // Position of the window on the screen when running in windowed + // mode. Accepted values are: "" (empty string) - don't care, + // "center" - place window at center of screen, "x,y" - place + // window at the specified coordinates. + // + + CONFIG_VARIABLE_STRING(window_position), + + //! + // If non-zero, the game will run in full screen mode. If zero, + // the game will run in a window. + // + + CONFIG_VARIABLE_INT(fullscreen), + + //! + // Index of the display on which the game should run. This has no + // effect if running in windowed mode (fullscreen=0) and + // window_position is not set to "center". + // + + CONFIG_VARIABLE_INT(video_display), + + //! + // If non-zero, the screen will be stretched vertically to display + // correctly on a square pixel video mode. + // + + CONFIG_VARIABLE_INT(aspect_ratio_correct), + + //! + // If non-zero, the screen will have smooth scaling. + // + + CONFIG_VARIABLE_INT(smooth_pixel_scaling), + + //! + // If non-zero, forces integer scales for resolution-independent rendering. + // + + CONFIG_VARIABLE_INT(integer_scaling), + + // If non-zero, any pillar/letter boxes drawn around the game area + // will "flash" when the game palette changes, simulating the VGA + // "porch" + + CONFIG_VARIABLE_INT(vga_porch_flash), + + //! + // Window width when running in windowed mode. + // + + CONFIG_VARIABLE_INT(window_width), + + //! + // Window height when running in windowed mode. + // + + CONFIG_VARIABLE_INT(window_height), + + //! + // Width for screen mode when running fullscreen. + // If this and fullscreen_height are both set to zero, we run + // fullscreen as a desktop window that covers the entire screen, + // rather than ever switching screen modes. It should usually + // be unnecessary to set this value. + // + + CONFIG_VARIABLE_INT(fullscreen_width), + + //! + // Height for screen mode when running fullscreen. + // See documentation for fullscreen_width. + // + + CONFIG_VARIABLE_INT(fullscreen_height), + + //! + // If non-zero, force the use of a software renderer. For use on + // systems lacking hardware acceleration. + // + + CONFIG_VARIABLE_INT(force_software_renderer), + + //! + // Maximum number of pixels to use for intermediate scaling buffer. + // More pixels mean that the screen can be rendered more precisely, + // but there are diminishing returns on quality. The default limits to + // 16,000,000 pixels, which is enough to cover 4K monitor standards. + + CONFIG_VARIABLE_INT(max_scaling_buffer_pixels), + + //! + // Number of milliseconds to wait on startup after the video mode + // has been set, before the game will start. This allows the + // screen to settle on some monitors that do not display an image + // for a brief interval after changing video modes. + // + + CONFIG_VARIABLE_INT(startup_delay), + + //! + // @game heretic hexen strife + // + // If non-zero, display the graphical startup screen. + // + + CONFIG_VARIABLE_INT(graphical_startup), + + //! + // @game doom heretic strife + // + // If non-zero, the ENDOOM text screen is displayed when exiting the + // game. If zero, the ENDOOM screen is not displayed. + // + + CONFIG_VARIABLE_INT(show_endoom), + + //! + // @game doom strife + // + // If non-zero, a disk activity indicator is displayed when data is read + // from disk. If zero, the disk activity indicator is not displayed. + // + + CONFIG_VARIABLE_INT(show_diskicon), + + //! + // If non-zero, save screenshots in PNG format. If zero, screenshots are + // saved in PCX format, as Vanilla Doom does. + // + + CONFIG_VARIABLE_INT(png_screenshots), + + //! + // Sound output sample rate, in Hz. Typical values to use are + // 11025, 22050, 44100 and 48000. + // + + CONFIG_VARIABLE_INT(snd_samplerate), + + //! + // Maximum number of bytes to allocate for caching converted sound + // effects in memory. If set to zero, there is no limit applied. + // + + CONFIG_VARIABLE_INT(snd_cachesize), + + //! + // Maximum size of the output sound buffer size in milliseconds. + // Sound output is generated periodically in slices. Higher values + // might be more efficient but will introduce latency to the + // sound output. The default is 28ms (one slice per tic with the + // 35fps timer). + // + + CONFIG_VARIABLE_INT(snd_maxslicetime_ms), + + //! + // If non-zero, sound effects will have their pitch varied up or + // down by a random amount during play. If zero, sound effects + // play back at their default pitch. + // + + CONFIG_VARIABLE_INT(snd_pitchshift), + + //! + // External command to invoke to perform MIDI playback. If set to + // the empty string, SDL_mixer's internal MIDI playback is used. + // This only has any effect when snd_musicdevice is set to General + // MIDI output. + // + + CONFIG_VARIABLE_STRING(snd_musiccmd), + + //! + // Value to set for the DMXOPTION environment variable. If this contains + // "-opl3", output for an OPL3 chip is generated when in OPL MIDI + // playback mode. + // + + CONFIG_VARIABLE_STRING(snd_dmxoption), + + //! + // The I/O port to use to access the OPL chip. Only relevant when + // using native OPL music playback. + // + + CONFIG_VARIABLE_INT_HEX(opl_io_port), + + //! + // Controls whether libsamplerate support is used for performing + // sample rate conversions of sound effects. Support for this + // must be compiled into the program. + // + // If zero, libsamplerate support is disabled. If non-zero, + // libsamplerate is enabled. Increasing values roughly correspond + // to higher quality conversion; the higher the quality, the + // slower the conversion process. Linear conversion = 1; + // Zero order hold = 2; Fast Sinc filter = 3; Medium quality + // Sinc filter = 4; High quality Sinc filter = 5. + // + + CONFIG_VARIABLE_INT(use_libsamplerate), + + //! + // Scaling factor used by libsamplerate. This is used when converting + // sounds internally back into integer form; normally it should not + // be necessary to change it from the default value. The only time + // it might be needed is if a PWAD file is loaded that contains very + // loud sounds, in which case the conversion may cause sound clipping + // and the scale factor should be reduced. The lower the value, the + // quieter the sound effects become, so it should be set as high as is + // possible without clipping occurring. + + CONFIG_VARIABLE_FLOAT(libsamplerate_scale), + + //! + // Full path to a directory in which WAD files and dehacked patches + // can be placed to be automatically loaded on startup. A subdirectory + // of this directory matching the IWAD name is checked to find the + // files to load. + + CONFIG_VARIABLE_STRING(autoload_path), + + //! + // Full path to a directory containing configuration files for + // substitute music packs. These packs contain high quality renderings + // of game music to be played instead of using the system's built-in + // MIDI playback. + // + + CONFIG_VARIABLE_STRING(music_pack_path), + +#ifdef HAVE_FLUIDSYNTH + //! + // If 1, activate the FluidSynth chorus effects module. If 0, no chorus + // will be added to the output signal. + // + + CONFIG_VARIABLE_INT(fsynth_chorus_active), + + //! + // Specifies the modulation depth of the FluidSynth chorus. Default is + // 5.0, range is 0.0 to 256.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_chorus_depth), + + //! + // Specifies the output amplitude of the FluidSynth chorus signal. Default + // is 0.35, range is 0.0 to 10.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_chorus_level), + + //! + // Sets the voice count of the FluidSynth chorus signal. Default is 3, + // range is 0 to 99. + // + + CONFIG_VARIABLE_INT(fsynth_chorus_nr), + + //! + // Sets the FluidSynth chorus modulation speed in Hz. Default is 0.3, + // range is 0.1 to 5.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_chorus_speed), + + //! + // This setting defines how FluidSynth interprets Bank Select messages. The + // default is "gs". Other possible values are "gm", "xg" and "mma". + // + + CONFIG_VARIABLE_STRING(fsynth_midibankselect), + + //! + // Sets the number of FluidSynth voices that can be played in parallel. + // Default is 256, range is 1 - 65535. + // + + CONFIG_VARIABLE_INT(fsynth_polyphony), + + //! + // If 1, activate the FluidSynth reverb effects module. If 0, no reverb + // will be added to the output signal. + // + + CONFIG_VARIABLE_INT(fsynth_reverb_active), + + //! + // Sets the amount of FluidSynth reverb damping. Default is 0.4, range is + // 0.0 to 1.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_reverb_damp), + + //! + // Sets the FluidSynth reverb amplitude. Default is 0.15, range is 0.0 - + // 1.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_reverb_level), + + //! + // Sets the room size(i.e. amount of wet) FluidSynth reverb. Default is + // 0.6, range is 0.0 - 1.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_reverb_roomsize), + + //! + // Sets the stereo spread of the FluidSynth reverb signal. Default is + // 0.4, range is 0.0 - 100.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_reverb_width), + + //! + // Fine tune the FluidSynth output level. Default is 1.0, + // range is 0.0 - 10.0. + // + + CONFIG_VARIABLE_FLOAT(fsynth_gain), + + //! + // Full path to a soundfont file to use with FluidSynth MIDI playback. + // + + CONFIG_VARIABLE_STRING(fsynth_sf_path), +#endif // HAVE_FLUIDSYNTH + + //! + // Full path to a Timidity configuration file to use for MIDI + // playback. The file will be evaluated from the directory where + // it is evaluated, so there is no need to add "dir" commands + // into it. + // + + CONFIG_VARIABLE_STRING(timidity_cfg_path), + + //! + // Path to GUS patch files to use when operating in GUS emulation + // mode. + // + + CONFIG_VARIABLE_STRING(gus_patch_path), + + //! + // Number of kilobytes of RAM to use in GUS emulation mode. Valid + // values are 256, 512, 768 or 1024. + // + + CONFIG_VARIABLE_INT(gus_ram_kb), + +#ifdef _WIN32 + //! + // MIDI device for native Windows MIDI. + // + + CONFIG_VARIABLE_STRING(winmm_midi_device), + + //! + // Compatibility level for native Windows MIDI, default 0. Valid values are + // 0 (Vanilla), 1 (Standard), 2 (Full). + // + + CONFIG_VARIABLE_INT(winmm_complevel), + + //! + // Reset device type for native Windows MIDI, default 1. Valid values are + // 0 (None), 1 (GM Mode), 2 (GS Mode), 3 (XG Mode). + // + + CONFIG_VARIABLE_INT(winmm_reset_type), + + //! + // Reset device delay for native Windows MIDI, default 0, median value 100 ms. + // + + CONFIG_VARIABLE_INT(winmm_reset_delay), +#endif + + //! + // @game doom strife + // + // If non-zero, the Vanilla savegame limit is enforced; if the + // savegame exceeds 180224 bytes in size, the game will exit with + // an error. If this has a value of zero, there is no limit to + // the size of savegames. + // + + CONFIG_VARIABLE_INT(vanilla_savegame_limit), + + //! + // @game doom strife + // + // If non-zero, the Vanilla demo size limit is enforced; the game + // exits with an error when a demo exceeds the demo size limit + // (128KiB by default). If this has a value of zero, there is no + // limit to the size of demos. + // + + CONFIG_VARIABLE_INT(vanilla_demo_limit), + + //! + // If non-zero, the game behaves like Vanilla Doom, always assuming + // an American keyboard mapping. If this has a value of zero, the + // native keyboard mapping of the keyboard is used. + // + + CONFIG_VARIABLE_INT(vanilla_keyboard_mapping), + + //! + // Name to use in network games for identification. This is only + // used on the "waiting" screen while waiting for the game to start. + // + + CONFIG_VARIABLE_STRING(player_name), + + //! + // If this is non-zero, the mouse will be "grabbed" when running + // in windowed mode so that it can be used as an input device. + // When running full screen, this has no effect. + // + + CONFIG_VARIABLE_INT(grabmouse), + + //! + // If non-zero, all vertical mouse movement is ignored. This + // emulates the behavior of the "novert" tool available under DOS + // that performs the same function. + // + + CONFIG_VARIABLE_INT(novert), + + //! + // Mouse acceleration factor. When the speed of mouse movement + // exceeds the threshold value (mouse_threshold), the speed is + // multiplied by this value. + // + + CONFIG_VARIABLE_FLOAT(mouse_acceleration), + + //! + // Mouse acceleration threshold. When the speed of mouse movement + // exceeds this threshold value, the speed is multiplied by an + // acceleration factor (mouse_acceleration). + // + + CONFIG_VARIABLE_INT(mouse_threshold), + + //! + // Mouse button to strafe left. + // + + CONFIG_VARIABLE_INT(mouseb_strafeleft), + + //! + // Mouse button to strafe right. + // + + CONFIG_VARIABLE_INT(mouseb_straferight), + + //! + // Mouse button to turn left. + // + + CONFIG_VARIABLE_INT(mouseb_turnleft), + + //! + // Mouse button to turn right. + // + + CONFIG_VARIABLE_INT(mouseb_turnright), + + //! + // Mouse button to "use" an object, eg. a door or switch. + // + + CONFIG_VARIABLE_INT(mouseb_use), + + //! + // Mouse button to move backwards. + // + + CONFIG_VARIABLE_INT(mouseb_backward), + + //! + // Mouse button to cycle to the previous weapon. + // + + CONFIG_VARIABLE_INT(mouseb_prevweapon), + + //! + // Mouse button to cycle to the next weapon. + // + + CONFIG_VARIABLE_INT(mouseb_nextweapon), + + //! + // @game heretic + // + // Mouse button to move to the left in the inventory. + // + + CONFIG_VARIABLE_INT(mouseb_invleft), + + //! + // @game heretic + // + // Mouse button to move to the right in the inventory. + // + + CONFIG_VARIABLE_INT(mouseb_invright), + + //! + // @game heretic hexen + // + // Mouse button to use artifact. + // + + CONFIG_VARIABLE_INT(mouseb_useartifact), + + //! + // If non-zero, double-clicking a mouse button acts like pressing + // the "use" key to use an object in-game, eg. a door or switch. + // + + CONFIG_VARIABLE_INT(dclick_use), + + //! + // SDL GUID string indicating the joystick to use. An empty string + // indicates that no joystick is configured. + // + + CONFIG_VARIABLE_STRING(joystick_guid), + + //! + // Index of SDL joystick to use; this is only used in the case where + // multiple identical joystick devices are connected which have the + // same GUID, to distinguish between devices. + // + + CONFIG_VARIABLE_INT(joystick_index), + + //! + // If non-zero, use analog movement when playing with a gamepad. + // + + CONFIG_VARIABLE_INT(use_analog), + + //! + // Joystick axis to use to for horizontal (X) movement. + // + + CONFIG_VARIABLE_INT(joystick_x_axis), + + //! + // If non-zero, movement on the horizontal joystick axis is inverted. + // + + CONFIG_VARIABLE_INT(joystick_x_invert), + + //! + // Joystick turn analog sensitivity, specified as a value between 0 and 20. + // + + CONFIG_VARIABLE_INT(joystick_turn_sensitivity), + + //! + // Joystick axis to use to for vertical (Y) movement. + // + + CONFIG_VARIABLE_INT(joystick_y_axis), + + //! + // If non-zero, movement on the vertical joystick axis is inverted. + // + + CONFIG_VARIABLE_INT(joystick_y_invert), + + //! + // Joystick axis to use to for strafing movement. + // + + CONFIG_VARIABLE_INT(joystick_strafe_axis), + + //! + // If non-zero, movement on the joystick axis used for strafing + // is inverted. + // + + CONFIG_VARIABLE_INT(joystick_strafe_invert), + + //! + // Joystick move and strafe analog sensitivity, specified as a value + // between 0 and 20. + // + + CONFIG_VARIABLE_INT(joystick_move_sensitivity), + //! + // Joystick axis to use to for looking up and down. + // + + CONFIG_VARIABLE_INT(joystick_look_axis), + + //! + // If non-zero, movement on the joystick axis used for looking + // is inverted. + // + + CONFIG_VARIABLE_INT(joystick_look_invert), + + //! + // Joystick look analog sensitivity, specified as a value between 0 and 20. + // + + CONFIG_VARIABLE_INT(joystick_look_sensitivity), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #0. + // + + CONFIG_VARIABLE_INT(joystick_physical_button0), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #1. + // + + CONFIG_VARIABLE_INT(joystick_physical_button1), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #2. + // + + CONFIG_VARIABLE_INT(joystick_physical_button2), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #3. + // + + CONFIG_VARIABLE_INT(joystick_physical_button3), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #4. + // + + CONFIG_VARIABLE_INT(joystick_physical_button4), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #5. + // + + CONFIG_VARIABLE_INT(joystick_physical_button5), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #6. + // + + CONFIG_VARIABLE_INT(joystick_physical_button6), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #7. + // + + CONFIG_VARIABLE_INT(joystick_physical_button7), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #8. + // + + CONFIG_VARIABLE_INT(joystick_physical_button8), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #9. + // + + CONFIG_VARIABLE_INT(joystick_physical_button9), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #10. + // + + CONFIG_VARIABLE_INT(joystick_physical_button10), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #11. + // + + CONFIG_VARIABLE_INT(joystick_physical_button11), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #12. + // + + CONFIG_VARIABLE_INT(joystick_physical_button12), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #13. + // + + CONFIG_VARIABLE_INT(joystick_physical_button13), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #14. + // + + CONFIG_VARIABLE_INT(joystick_physical_button14), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #15. + // + + CONFIG_VARIABLE_INT(joystick_physical_button15), + + //! + // The physical joystick button that corresponds to joystick + // virtual button #16. + // + + CONFIG_VARIABLE_INT(joystick_physical_button16), + + //! + // If non-zero, use the SDL_GameController interface instead of the + // SDL_Joystick interface. + // + + CONFIG_VARIABLE_INT(use_gamepad), + + //! + // Stores the SDL_GameControllerType of the last configured gamepad. + // + + CONFIG_VARIABLE_INT(gamepad_type), + + //! + // Joystick x axis dead zone, specified as a percentage of the axis max + // value. + // + + CONFIG_VARIABLE_INT(joystick_x_dead_zone), + + //! + // Joystick y axis dead zone, specified as a percentage of the axis max + // value. + // + + CONFIG_VARIABLE_INT(joystick_y_dead_zone), + + //! + // Joystick strafe axis dead zone, specified as a percentage of the axis + // max value. + // + + CONFIG_VARIABLE_INT(joystick_strafe_dead_zone), + + //! + // Joystick look axis dead zone, specified as a percentage of the axis max + // value. + // + + CONFIG_VARIABLE_INT(joystick_look_dead_zone), + + //! + // Joystick virtual button to make the player strafe left. + // + + CONFIG_VARIABLE_INT(joyb_strafeleft), + + //! + // Joystick virtual button to make the player strafe right. + // + + CONFIG_VARIABLE_INT(joyb_straferight), + + //! + // Joystick virtual button to activate the menu. + // + + CONFIG_VARIABLE_INT(joyb_menu_activate), + + //! + // Joystick virtual button to toggle the automap. + // + + CONFIG_VARIABLE_INT(joyb_toggle_automap), + + //! + // Joystick virtual button that cycles to the previous weapon. + // + + CONFIG_VARIABLE_INT(joyb_prevweapon), + + //! + // Joystick virtual button that cycles to the next weapon. + // + + CONFIG_VARIABLE_INT(joyb_nextweapon), + + //! + // @game heretic hexen + // Joystick virtual button to activate artifact. + // + + CONFIG_VARIABLE_INT(joyb_useartifact), + + //! + // @game heretic hexen + // Joystick virtual button to move left in the inventory. + // + + CONFIG_VARIABLE_INT(joyb_invleft), + + //! + // @game heretic hexen + // Joystick virtual button to move right in the inventory. + // + + CONFIG_VARIABLE_INT(joyb_invright), + + //! + // @game heretic hexen + // Joystick virtual button to fly up. + // + + CONFIG_VARIABLE_INT(joyb_flyup), + + //! + // @game heretic hexen + // Joystick virtual button to fly down. + // + + CONFIG_VARIABLE_INT(joyb_flydown), + + //! + // @game heretic hexen + // Joystick virtual button to center flying. + // + + CONFIG_VARIABLE_INT(joyb_flycenter), + + //! + // Key to pause or unpause the game. + // + + CONFIG_VARIABLE_KEY(key_pause), + + //! + // Key that activates the menu when pressed. + // + + CONFIG_VARIABLE_KEY(key_menu_activate), + + //! + // Key that moves the cursor up on the menu. + // + + CONFIG_VARIABLE_KEY(key_menu_up), + + //! + // Key that moves the cursor down on the menu. + // + + CONFIG_VARIABLE_KEY(key_menu_down), + + //! + // Key that moves the currently selected slider on the menu left. + // + + CONFIG_VARIABLE_KEY(key_menu_left), + + //! + // Key that moves the currently selected slider on the menu right. + // + + CONFIG_VARIABLE_KEY(key_menu_right), + + //! + // Key to go back to the previous menu. + // + + CONFIG_VARIABLE_KEY(key_menu_back), + + //! + // Key to activate the currently selected menu item. + // + + CONFIG_VARIABLE_KEY(key_menu_forward), + + //! + // Key to answer 'yes' to a question in the menu. + // + + CONFIG_VARIABLE_KEY(key_menu_confirm), + + //! + // Key to answer 'no' to a question in the menu. + // + + CONFIG_VARIABLE_KEY(key_menu_abort), + + //! + // Keyboard shortcut to bring up the help screen. + // + + CONFIG_VARIABLE_KEY(key_menu_help), + + //! + // Keyboard shortcut to bring up the save game menu. + // + + CONFIG_VARIABLE_KEY(key_menu_save), + + //! + // Keyboard shortcut to bring up the load game menu. + // + + CONFIG_VARIABLE_KEY(key_menu_load), + + //! + // Keyboard shortcut to bring up the sound volume menu. + // + + CONFIG_VARIABLE_KEY(key_menu_volume), + + //! + // Keyboard shortcut to toggle the detail level. + // + + CONFIG_VARIABLE_KEY(key_menu_detail), + + //! + // Keyboard shortcut to quicksave the current game. + // + + CONFIG_VARIABLE_KEY(key_menu_qsave), + + //! + // Keyboard shortcut to end the game. + // + + CONFIG_VARIABLE_KEY(key_menu_endgame), + + //! + // Keyboard shortcut to toggle heads-up messages. + // + + CONFIG_VARIABLE_KEY(key_menu_messages), + + //! + // Keyboard shortcut to load the last quicksave. + // + + CONFIG_VARIABLE_KEY(key_menu_qload), + + //! + // Keyboard shortcut to quit the game. + // + + CONFIG_VARIABLE_KEY(key_menu_quit), + + //! + // Keyboard shortcut to toggle the gamma correction level. + // + + CONFIG_VARIABLE_KEY(key_menu_gamma), + + //! + // Keyboard shortcut to switch view in multiplayer. + // + + CONFIG_VARIABLE_KEY(key_spy), + + //! + // Keyboard shortcut to increase the screen size. + // + + CONFIG_VARIABLE_KEY(key_menu_incscreen), + + //! + // Keyboard shortcut to decrease the screen size. + // + + CONFIG_VARIABLE_KEY(key_menu_decscreen), + + //! + // Keyboard shortcut to save a screenshot. + // + + CONFIG_VARIABLE_KEY(key_menu_screenshot), + + //! + // Key to toggle the map view. + // + + CONFIG_VARIABLE_KEY(key_map_toggle), + + //! + // Key to pan north when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_north), + + //! + // Key to pan south when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_south), + + //! + // Key to pan east when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_east), + + //! + // Key to pan west when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_west), + + //! + // Key to zoom in when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_zoomin), + + //! + // Key to zoom out when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_zoomout), + + //! + // Key to zoom out the maximum amount when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_maxzoom), + + //! + // Key to toggle follow mode when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_follow), + + //! + // Key to toggle the grid display when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_grid), + + //! + // Key to set a mark when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_mark), + + //! + // Key to clear all marks when in the map view. + // + + CONFIG_VARIABLE_KEY(key_map_clearmark), + + //! + // Key to select weapon 1. + // + + CONFIG_VARIABLE_KEY(key_weapon1), + + //! + // Key to select weapon 2. + // + + CONFIG_VARIABLE_KEY(key_weapon2), + + //! + // Key to select weapon 3. + // + + CONFIG_VARIABLE_KEY(key_weapon3), + + //! + // Key to select weapon 4. + // + + CONFIG_VARIABLE_KEY(key_weapon4), + + //! + // Key to select weapon 5. + // + + CONFIG_VARIABLE_KEY(key_weapon5), + + //! + // Key to select weapon 6. + // + + CONFIG_VARIABLE_KEY(key_weapon6), + + //! + // Key to select weapon 7. + // + + CONFIG_VARIABLE_KEY(key_weapon7), + + //! + // Key to select weapon 8. + // + + CONFIG_VARIABLE_KEY(key_weapon8), + + //! + // Key to cycle to the previous weapon. + // + + CONFIG_VARIABLE_KEY(key_prevweapon), + + //! + // Key to cycle to the next weapon. + // + + CONFIG_VARIABLE_KEY(key_nextweapon), + + //! + // @game heretic + // + // Key to use "quartz flask" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_quartz), + + //! + // @game heretic + // + // Key to use "mystic urn" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_urn), + + //! + // @game heretic + // + // Key to use "timebomb of the ancients" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_bomb), + + //! + // @game heretic + // + // Key to use "tome of power" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_tome), + + //! + // @game heretic + // + // Key to use "ring of invincibility" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_ring), + + //! + // @game heretic + // + // Key to use "chaos device" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_chaosdevice), + + //! + // @game heretic + // + // Key to use "shadowsphere" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_shadowsphere), + + //! + // @game heretic + // + // Key to use "wings of wrath" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_wings), + + //! + // @game heretic + // + // Key to use "torch" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_torch), + + //! + // @game heretic + // + // Key to use "morph ovum" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_morph), + + //! + // @game hexen + // + // Key to use one of each artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_all), + + //! + // @game hexen + // + // Key to use "quartz flask" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_health), + + //! + // @game hexen + // + // Key to use "flechette" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_poisonbag), + + //! + // @game hexen + // + // Key to use "disc of repulsion" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_blastradius), + + //! + // @game hexen + // + // Key to use "chaos device" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_teleport), + + //! + // @game hexen + // + // Key to use "banishment device" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_teleportother), + + //! + // @game hexen + // + // Key to use "porkalator" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_egg), + + //! + // @game hexen + // + // Key to use "icon of the defender" artifact. + // + + CONFIG_VARIABLE_KEY(key_arti_invulnerability), + + //! + // Key to re-display last message. + // + + CONFIG_VARIABLE_KEY(key_message_refresh), + + //! + // Key to quit the game when recording a demo. + // + + CONFIG_VARIABLE_KEY(key_demo_quit), + + //! + // Key to send a message during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msg), + + //! + // Key to send a message to player 1 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer1), + + //! + // Key to send a message to player 2 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer2), + + //! + // Key to send a message to player 3 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer3), + + //! + // Key to send a message to player 4 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer4), + + //! + // @game hexen strife + // + // Key to send a message to player 5 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer5), + + //! + // @game hexen strife + // + // Key to send a message to player 6 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer6), + + //! + // @game hexen strife + // + // Key to send a message to player 7 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer7), + + //! + // @game hexen strife + // + // Key to send a message to player 8 during multiplayer games. + // + + CONFIG_VARIABLE_KEY(key_multi_msgplayer8), +}; + +static default_collection_t extra_defaults = +{ + extra_defaults_list, + arrlen(extra_defaults_list), + NULL, +}; + +// Search a collection for a variable + +static default_t *SearchCollection(default_collection_t *collection, const char *name) +{ + int i; + + for (i=0; inumdefaults; ++i) + { + if (!strcmp(name, collection->defaults[i].name)) + { + return &collection->defaults[i]; + } + } + + return NULL; +} + +// Mapping from DOS keyboard scan code to internal key code (as defined +// in doomkey.h). I think I (fraggle) reused this from somewhere else +// but I can't find where. Anyway, notes: +// * KEY_PAUSE is wrong - it's in the KEY_NUMLOCK spot. This shouldn't +// matter in terms of Vanilla compatibility because neither of +// those were valid for key bindings. +// * There is no proper scan code for PrintScreen (on DOS machines it +// sends an interrupt). So I added a fake scan code of 126 for it. +// The presence of this is important so we can bind PrintScreen as +// a screenshot key. +static const int scantokey[128] = +{ + 0 , 27, '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', KEY_BACKSPACE, 9, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', 13, KEY_RCTRL, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', KEY_RSHIFT,'\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,KEYP_MULTIPLY, + KEY_RALT, ' ', KEY_CAPSLOCK,KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, + KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, /*KEY_NUMLOCK?*/KEY_PAUSE,KEY_SCRLCK,KEY_HOME, + KEY_UPARROW,KEY_PGUP,KEY_MINUS,KEY_LEFTARROW,KEYP_5,KEY_RIGHTARROW,KEYP_PLUS,KEY_END, + KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0, 0, 0, KEY_F11, + KEY_F12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, KEY_PRTSCR, 0 +}; + + +static void SaveDefaultCollection(default_collection_t *collection) +{ + default_t *defaults; + int i, v; + FILE *f; + + f = M_fopen(collection->filename, "w"); + if (!f) + return; // can't write the file, but don't complain + + defaults = collection->defaults; + + for (i=0 ; inumdefaults ; i++) + { + int chars_written; + + // Ignore unbound variables + + if (!defaults[i].bound) + { + continue; + } + + // Print the name and line up all values at 30 characters + + chars_written = fprintf(f, "%s ", defaults[i].name); + + for (; chars_written < 30; ++chars_written) + fprintf(f, " "); + + // Print the value + + switch (defaults[i].type) + { + case DEFAULT_KEY: + + // use the untranslated version if we can, to reduce + // the possibility of screwing up the user's config + // file + + v = *defaults[i].location.i; + + if (v == KEY_RSHIFT) + { + // Special case: for shift, force scan code for + // right shift, as this is what Vanilla uses. + // This overrides the change check below, to fix + // configuration files made by old versions that + // mistakenly used the scan code for left shift. + + v = 54; + } + else if (defaults[i].untranslated + && v == defaults[i].original_translated) + { + // Has not been changed since the last time we + // read the config file. + + v = defaults[i].untranslated; + } + else + { + // search for a reverse mapping back to a scancode + // in the scantokey table + + int s; + + for (s=0; s<128; ++s) + { + if (scantokey[s] == v) + { + v = s; + break; + } + } + } + + fprintf(f, "%i", v); + break; + + case DEFAULT_INT: + fprintf(f, "%i", *defaults[i].location.i); + break; + + case DEFAULT_INT_HEX: + fprintf(f, "0x%x", *defaults[i].location.i); + break; + + case DEFAULT_FLOAT: + fprintf(f, "%f", *defaults[i].location.f); + break; + + case DEFAULT_STRING: + fprintf(f,"\"%s\"", *defaults[i].location.s); + break; + } + + fprintf(f, "\n"); + } + + fclose (f); +} + +// Parses integer values in the configuration file + +static int ParseIntParameter(const char *strparm) +{ + int parm; + + if (strparm[0] == '0' && strparm[1] == 'x') + sscanf(strparm+2, "%x", (unsigned int *) &parm); + else + sscanf(strparm, "%i", &parm); + + return parm; +} + +static void SetVariable(default_t *def, const char *value) +{ + int intparm; + + // parameter found + + switch (def->type) + { + case DEFAULT_STRING: + *def->location.s = M_StringDuplicate(value); + break; + + case DEFAULT_INT: + case DEFAULT_INT_HEX: + *def->location.i = ParseIntParameter(value); + break; + + case DEFAULT_KEY: + + // translate scancodes read from config + // file (save the old value in untranslated) + + intparm = ParseIntParameter(value); + def->untranslated = intparm; + if (intparm >= 0 && intparm < 128) + { + intparm = scantokey[intparm]; + } + else + { + intparm = 0; + } + + def->original_translated = intparm; + *def->location.i = intparm; + break; + + case DEFAULT_FLOAT: + { + // Different locales use different decimal separators. + // However, the choice of the current locale isn't always + // under our own control. If the atof() function fails to + // parse the string representing the floating point number + // using the current locale's decimal separator, it will + // return 0, resulting in silent sound effects. To + // mitigate this, we replace the first non-digit, + // non-minus character in the string with the current + // locale's decimal separator before passing it to atof(). + struct lconv *lc = localeconv(); + char dec, *str; + int i = 0; + + dec = lc->decimal_point[0]; + str = M_StringDuplicate(value); + + // Skip sign indicators. + if (str[i] == '-' || str[i] == '+') + { + i++; + } + + for ( ; str[i] != '\0'; i++) + { + if (!isdigit(str[i])) + { + str[i] = dec; + break; + } + } + + *def->location.f = (float) atof(str); + free(str); + } + break; + } +} + +static void LoadDefaultCollection(default_collection_t *collection) +{ + FILE *f; + default_t *def; + char defname[80]; + char strparm[100]; + + // read the file in, overriding any set defaults + f = M_fopen(collection->filename, "r"); + + if (f == NULL) + { + // File not opened, but don't complain. + // It's probably just the first time they ran the game. + + return; + } + + while (!feof(f)) + { + if (fscanf(f, "%79s %99[^\n]\n", defname, strparm) != 2) + { + // This line doesn't match + + continue; + } + + // Find the setting in the list + + def = SearchCollection(collection, defname); + + if (def == NULL || !def->bound) + { + // Unknown variable? Unbound variables are also treated + // as unknown. + + continue; + } + + // Strip off trailing non-printable characters (\r characters + // from DOS text files) + + while (strlen(strparm) > 0 && !isprint(strparm[strlen(strparm)-1])) + { + strparm[strlen(strparm)-1] = '\0'; + } + + // Surrounded by quotes? If so, remove them. + if (strlen(strparm) >= 2 + && strparm[0] == '"' && strparm[strlen(strparm) - 1] == '"') + { + strparm[strlen(strparm) - 1] = '\0'; + memmove(strparm, strparm + 1, sizeof(strparm) - 1); + } + + SetVariable(def, strparm); + } + + fclose (f); +} + +// Set the default filenames to use for configuration files. + +void M_SetConfigFilenames(const char *main_config, const char *extra_config) +{ + default_main_config = main_config; + default_extra_config = extra_config; +} + +// +// M_SaveDefaults +// + +void M_SaveDefaults (void) +{ + SaveDefaultCollection(&doom_defaults); + SaveDefaultCollection(&extra_defaults); +} + +// +// Save defaults to alternate filenames +// + +void M_SaveDefaultsAlternate(const char *main, const char *extra) +{ + const char *orig_main; + const char *orig_extra; + + // Temporarily change the filenames + + orig_main = doom_defaults.filename; + orig_extra = extra_defaults.filename; + + doom_defaults.filename = main; + extra_defaults.filename = extra; + + M_SaveDefaults(); + + // Restore normal filenames + + doom_defaults.filename = orig_main; + extra_defaults.filename = orig_extra; +} + +// +// M_LoadDefaults +// + +void M_LoadDefaults (void) +{ + int i; + + // This variable is a special snowflake for no good reason. + M_BindStringVariable("autoload_path", &autoload_path); + + // check for a custom default file + + //! + // @arg + // @vanilla + // + // Load main configuration from the specified file, instead of the + // default. + // + + i = M_CheckParmWithArgs("-config", 1); + + if (i) + { + doom_defaults.filename = myargv[i+1]; + printf (" default file: %s\n",doom_defaults.filename); + } + else + { + doom_defaults.filename + = M_StringJoin(configdir, default_main_config, NULL); + } + + printf("saving config in %s\n", doom_defaults.filename); + + //! + // @arg + // + // Load additional configuration from the specified file, instead of + // the default. + // + + i = M_CheckParmWithArgs("-extraconfig", 1); + + if (i) + { + extra_defaults.filename = myargv[i+1]; + printf(" extra configuration file: %s\n", + extra_defaults.filename); + } + else + { + extra_defaults.filename + = M_StringJoin(configdir, default_extra_config, NULL); + } + + LoadDefaultCollection(&doom_defaults); + LoadDefaultCollection(&extra_defaults); +} + +// Get a configuration file variable by its name + +static default_t *GetDefaultForName(const char *name) +{ + default_t *result; + + // Try the main list and the extras + + result = SearchCollection(&doom_defaults, name); + + if (result == NULL) + { + result = SearchCollection(&extra_defaults, name); + } + + // Not found? Internal error. + + if (result == NULL) + { + I_Error("Unknown configuration variable: '%s'", name); + } + + return result; +} + +// +// Bind a variable to a given configuration file variable, by name. +// + +void M_BindIntVariable(const char *name, int *location) +{ + default_t *variable; + + variable = GetDefaultForName(name); + assert(variable->type == DEFAULT_INT + || variable->type == DEFAULT_INT_HEX + || variable->type == DEFAULT_KEY); + + variable->location.i = location; + variable->bound = true; +} + +void M_BindFloatVariable(const char *name, float *location) +{ + default_t *variable; + + variable = GetDefaultForName(name); + assert(variable->type == DEFAULT_FLOAT); + + variable->location.f = location; + variable->bound = true; +} + +void M_BindStringVariable(const char *name, char **location) +{ + default_t *variable; + + variable = GetDefaultForName(name); + assert(variable->type == DEFAULT_STRING); + + variable->location.s = location; + variable->bound = true; +} + +// Set the value of a particular variable; an API function for other +// parts of the program to assign values to config variables by name. + +boolean M_SetVariable(const char *name, const char *value) +{ + default_t *variable; + + variable = GetDefaultForName(name); + + if (variable == NULL || !variable->bound) + { + return false; + } + + SetVariable(variable, value); + + return true; +} + +// Get the value of a variable. + +int M_GetIntVariable(const char *name) +{ + default_t *variable; + + variable = GetDefaultForName(name); + + if (variable == NULL || !variable->bound + || (variable->type != DEFAULT_INT && variable->type != DEFAULT_INT_HEX)) + { + return 0; + } + + return *variable->location.i; +} + +const char *M_GetStringVariable(const char *name) +{ + default_t *variable; + + variable = GetDefaultForName(name); + + if (variable == NULL || !variable->bound + || variable->type != DEFAULT_STRING) + { + return NULL; + } + + return *variable->location.s; +} + +float M_GetFloatVariable(const char *name) +{ + default_t *variable; + + variable = GetDefaultForName(name); + + if (variable == NULL || !variable->bound + || variable->type != DEFAULT_FLOAT) + { + return 0; + } + + return *variable->location.f; +} + +// Get the path to the default configuration dir to use, if NULL +// is passed to M_SetConfigDir. + +static char *GetDefaultConfigDir(void) +{ +#if !defined(_WIN32) || defined(_WIN32_WCE) + + // Configuration settings are stored in an OS-appropriate path + // determined by SDL. On typical Unix systems, this might be + // ~/.local/share/chocolate-doom. On Windows, we behave like + // Vanilla Doom and save in the current directory. + + char *result; + char *copy; + + result = SDL_GetPrefPath("", PACKAGE_TARNAME); + if (result != NULL) + { + copy = M_StringDuplicate(result); + SDL_free(result); + return copy; + } +#endif /* #ifndef _WIN32 */ + return M_StringDuplicate(exedir); +} + +// +// SetConfigDir: +// +// Sets the location of the configuration directory, where configuration +// files are stored - default.cfg, chocolate-doom.cfg, savegames, etc. +// + +void M_SetConfigDir(const char *dir) +{ + // Use the directory that was passed, or find the default. + + if (dir != NULL) + { + configdir = dir; + } + else + { + configdir = GetDefaultConfigDir(); + } + + if (strcmp(configdir, exedir) != 0) + { + printf("Using %s for configuration and saves\n", configdir); + } + + // Make the directory if it doesn't already exist: + + M_MakeDirectory(configdir); +} + +#define MUSIC_PACK_README \ +"Extract music packs into this directory in .flac or .ogg format;\n" \ +"they will be automatically loaded based on filename to replace the\n" \ +"in-game music with high quality versions.\n\n" \ +"For more information check here:\n\n" \ +" \n\n" + +// Set the value of music_pack_path if it is currently empty, and create +// the directory if necessary. +void M_SetMusicPackDir(void) +{ + const char *current_path; + char *prefdir, *music_pack_path, *readme_path; + + current_path = M_GetStringVariable("music_pack_path"); + + if (current_path != NULL && strlen(current_path) > 0) + { + return; + } + + prefdir = SDL_GetPrefPath("", PACKAGE_TARNAME); + if (prefdir == NULL) + { + printf("M_SetMusicPackDir: SDL_GetPrefPath failed, music pack directory not set\n"); + return; + } + music_pack_path = M_StringJoin(prefdir, "music-packs", NULL); + + M_MakeDirectory(prefdir); + M_MakeDirectory(music_pack_path); + M_SetVariable("music_pack_path", music_pack_path); + + // We write a README file with some basic instructions on how to use + // the directory. + readme_path = M_StringJoin(music_pack_path, DIR_SEPARATOR_S, + "README.txt", NULL); + M_WriteFile(readme_path, MUSIC_PACK_README, strlen(MUSIC_PACK_README)); + + free(readme_path); + free(music_pack_path); + SDL_free(prefdir); +} + +// +// Calculate the path to the directory to use to store save games. +// Creates the directory as necessary. +// + +char *M_GetSaveGameDir(const char *iwadname) +{ + char *savegamedir; + char *topdir; + int p; + + //! + // @arg + // + // Specify a path from which to load and save games. If the + // directory does not exist then it will automatically be created. + // + + p = M_CheckParmWithArgs("-savedir", 1); + if (p) + { + savegamedir = myargv[p + 1]; + if (!M_FileExists(savegamedir)) + { + M_MakeDirectory(savegamedir); + } + + // add separator at end just in case + savegamedir = M_StringJoin(savegamedir, DIR_SEPARATOR_S, NULL); + + printf("Save directory changed to %s.\n", savegamedir); + } +#ifdef _WIN32 + // In -cdrom mode, we write savegames to a specific directory + // in addition to configs. + + else if (M_ParmExists("-cdrom")) + { + savegamedir = M_StringDuplicate(configdir); + } +#endif + // If not "doing" a configuration directory (Windows), don't "do" + // a savegame directory, either. + else if (!strcmp(configdir, exedir)) + { + savegamedir = M_StringDuplicate(""); + } + else + { + // ~/.local/share/chocolate-doom/savegames + + topdir = M_StringJoin(configdir, "savegames", NULL); + M_MakeDirectory(topdir); + + // eg. ~/.local/share/chocolate-doom/savegames/doom2.wad/ + + savegamedir = M_StringJoin(topdir, DIR_SEPARATOR_S, iwadname, + DIR_SEPARATOR_S, NULL); + + M_MakeDirectory(savegamedir); + + free(topdir); + } + + return savegamedir; +} + +// +// Calculate the path to the directory for autoloaded WADs/DEHs. +// Creates the directory as necessary. +// +char *M_GetAutoloadDir(const char *iwadname) +{ + char *result; + + if (autoload_path == NULL || strlen(autoload_path) == 0) + { + char *prefdir; + prefdir = SDL_GetPrefPath("", PACKAGE_TARNAME); + if (prefdir == NULL) + { + printf("M_GetAutoloadDir: SDL_GetPrefPath failed\n"); + return NULL; + } + autoload_path = M_StringJoin(prefdir, "autoload", NULL); + SDL_free(prefdir); + } + + M_MakeDirectory(autoload_path); + + result = M_StringJoin(autoload_path, DIR_SEPARATOR_S, iwadname, NULL); + M_MakeDirectory(result); + + // TODO: Add README file + + return result; +} \ No newline at end of file diff --git a/games/NXDoom/src/m_config.h b/games/NXDoom/src/m_config.h new file mode 100644 index 00000000000..5939b6bef8f --- /dev/null +++ b/games/NXDoom/src/m_config.h @@ -0,0 +1,43 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Configuration file interface. +// + + +#ifndef __M_CONFIG__ +#define __M_CONFIG__ + +#include "doomtype.h" + +void M_LoadDefaults(void); +void M_SaveDefaults(void); +void M_SaveDefaultsAlternate(const char *main, const char *extra); +void M_SetConfigDir(const char *dir); +void M_SetMusicPackDir(void); +void M_BindIntVariable(const char *name, int *variable); +void M_BindFloatVariable(const char *name, float *variable); +void M_BindStringVariable(const char *name, char **variable); +boolean M_SetVariable(const char *name, const char *value); +int M_GetIntVariable(const char *name); +const char *M_GetStringVariable(const char *name); +float M_GetFloatVariable(const char *name); +void M_SetConfigFilenames(const char *main_config, const char *extra_config); +char *M_GetSaveGameDir(const char *iwadname); +char *M_GetAutoloadDir(const char *iwadname); + +extern const char *configdir; + +#endif diff --git a/games/NXDoom/src/m_controls.c b/games/NXDoom/src/m_controls.c new file mode 100644 index 00000000000..1a5f520e144 --- /dev/null +++ b/games/NXDoom/src/m_controls.c @@ -0,0 +1,457 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include + +#include "doomtype.h" +#include "doomkeys.h" + +#include "m_config.h" +#include "m_misc.h" + +// +// Keyboard controls +// + +int key_right = KEY_RIGHTARROW; +int key_left = KEY_LEFTARROW; + +int key_up = KEY_UPARROW; +int key_down = KEY_DOWNARROW; +int key_strafeleft = ','; +int key_straferight = '.'; +int key_fire = KEY_RCTRL; +int key_use = ' '; +int key_strafe = KEY_RALT; +int key_speed = KEY_RSHIFT; + +// +// Heretic keyboard controls +// + +int key_flyup = KEY_PGUP; +int key_flydown = KEY_INS; +int key_flycenter = KEY_HOME; + +int key_lookup = KEY_PGDN; +int key_lookdown = KEY_DEL; +int key_lookcenter = KEY_END; + +int key_invleft = '['; +int key_invright = ']'; +int key_useartifact = KEY_ENTER; + +int key_arti_quartz = 0; +int key_arti_urn = 0; +int key_arti_bomb = 0; +int key_arti_tome = 127; +int key_arti_ring = 0; +int key_arti_chaosdevice = 0; +int key_arti_shadowsphere = 0; +int key_arti_wings = 0; +int key_arti_torch = 0; +int key_arti_morph = 0; + +// +// Hexen key controls +// + +int key_jump = '/'; + +int key_arti_all = KEY_BACKSPACE; +int key_arti_health = '\\'; +int key_arti_poisonbag = '0'; +int key_arti_blastradius = '9'; +int key_arti_teleport = '8'; +int key_arti_teleportother = '7'; +int key_arti_egg = '6'; +int key_arti_invulnerability = '5'; + +// +// Strife key controls +// +// haleyjd 09/01/10 +// + +// Note: Strife also uses key_invleft, key_invright, key_jump, key_lookup, and +// key_lookdown, but with different default values. + +int key_usehealth = 'h'; +int key_invquery = 'q'; +int key_mission = 'w'; +int key_invpop = 'z'; +int key_invkey = 'k'; +int key_invhome = KEY_HOME; +int key_invend = KEY_END; +int key_invuse = KEY_ENTER; +int key_invdrop = KEY_BACKSPACE; + + +// +// Mouse controls +// + +int mousebfire = 0; +int mousebstrafe = 1; +int mousebforward = 2; +int mousebspeed = 3; + +int mousebjump = -1; + +int mousebstrafeleft = -1; +int mousebstraferight = -1; +int mousebturnleft = -1; +int mousebturnright = -1; +int mousebbackward = -1; +int mousebuse = -1; + +int mousebprevweapon = -1; +int mousebnextweapon = -1; +int mousebinvleft = -1; +int mousebinvright = -1; +int mousebuseartifact = -1; + +int key_message_refresh = KEY_ENTER; +int key_pause = KEY_PAUSE; +int key_demo_quit = 'q'; +int key_spy = KEY_F12; + +// Multiplayer chat keys: + +int key_multi_msg = 't'; +int key_multi_msgplayer[8]; + +// Weapon selection keys: + +int key_weapon1 = '1'; +int key_weapon2 = '2'; +int key_weapon3 = '3'; +int key_weapon4 = '4'; +int key_weapon5 = '5'; +int key_weapon6 = '6'; +int key_weapon7 = '7'; +int key_weapon8 = '8'; +int key_prevweapon = 0; +int key_nextweapon = 0; + +// Map control keys: + +int key_map_north = KEY_UPARROW; +int key_map_south = KEY_DOWNARROW; +int key_map_east = KEY_RIGHTARROW; +int key_map_west = KEY_LEFTARROW; +int key_map_zoomin = '='; +int key_map_zoomout = '-'; +int key_map_toggle = KEY_TAB; +int key_map_maxzoom = '0'; +int key_map_follow = 'f'; +int key_map_grid = 'g'; +int key_map_mark = 'm'; +int key_map_clearmark = 'c'; + +// menu keys: + +int key_menu_activate = KEY_ESCAPE; +int key_menu_up = KEY_UPARROW; +int key_menu_down = KEY_DOWNARROW; +int key_menu_left = KEY_LEFTARROW; +int key_menu_right = KEY_RIGHTARROW; +int key_menu_back = KEY_BACKSPACE; +int key_menu_forward = KEY_ENTER; +int key_menu_confirm = 'y'; +int key_menu_abort = 'n'; + +int key_menu_help = KEY_F1; +int key_menu_save = KEY_F2; +int key_menu_load = KEY_F3; +int key_menu_volume = KEY_F4; +int key_menu_detail = KEY_F5; +int key_menu_qsave = KEY_F6; +int key_menu_endgame = KEY_F7; +int key_menu_messages = KEY_F8; +int key_menu_qload = KEY_F9; +int key_menu_quit = KEY_F10; +int key_menu_gamma = KEY_F11; + +int key_menu_incscreen = KEY_EQUALS; +int key_menu_decscreen = KEY_MINUS; +int key_menu_screenshot = 0; + +// +// Joystick controls +// + +int joybfire = 0; +int joybstrafe = 1; +int joybuse = 3; +int joybspeed = 2; + +int joybstrafeleft = -1; +int joybstraferight = -1; + +int joybjump = -1; + +int joybprevweapon = -1; +int joybnextweapon = -1; + +int joybmenu = -1; +int joybautomap = -1; + +int joybuseartifact = -1; +int joybinvleft = -1; +int joybinvright = -1; + +int joybflyup = -1; +int joybflydown = -1; +int joybflycenter = -1; + +// Control whether if a mouse button is double clicked, it acts like +// "use" has been pressed + +int dclick_use = 1; + +// +// Bind all of the common controls used by Doom and all other games. +// + +void M_BindBaseControls(void) +{ + M_BindIntVariable("key_right", &key_right); + M_BindIntVariable("key_left", &key_left); + M_BindIntVariable("key_up", &key_up); + M_BindIntVariable("key_down", &key_down); + M_BindIntVariable("key_strafeleft", &key_strafeleft); + M_BindIntVariable("key_straferight", &key_straferight); + M_BindIntVariable("key_fire", &key_fire); + M_BindIntVariable("key_use", &key_use); + M_BindIntVariable("key_strafe", &key_strafe); + M_BindIntVariable("key_speed", &key_speed); + + M_BindIntVariable("mouseb_fire", &mousebfire); + M_BindIntVariable("mouseb_strafe", &mousebstrafe); + M_BindIntVariable("mouseb_forward", &mousebforward); + M_BindIntVariable("mouseb_speed", &mousebspeed); + + M_BindIntVariable("joyb_fire", &joybfire); + M_BindIntVariable("joyb_strafe", &joybstrafe); + M_BindIntVariable("joyb_use", &joybuse); + M_BindIntVariable("joyb_speed", &joybspeed); + + M_BindIntVariable("joyb_menu_activate", &joybmenu); + M_BindIntVariable("joyb_toggle_automap", &joybautomap); + + // Extra controls that are not in the Vanilla versions: + + M_BindIntVariable("joyb_strafeleft", &joybstrafeleft); + M_BindIntVariable("joyb_straferight", &joybstraferight); + M_BindIntVariable("mouseb_strafeleft", &mousebstrafeleft); + M_BindIntVariable("mouseb_straferight", &mousebstraferight); + M_BindIntVariable("mouseb_turnleft", &mousebturnleft); + M_BindIntVariable("mouseb_turnright", &mousebturnright); + M_BindIntVariable("mouseb_use", &mousebuse); + M_BindIntVariable("mouseb_backward", &mousebbackward); + M_BindIntVariable("dclick_use", &dclick_use); + M_BindIntVariable("key_pause", &key_pause); + M_BindIntVariable("key_message_refresh", &key_message_refresh); +} + +void M_BindHereticControls(void) +{ + M_BindIntVariable("key_flyup", &key_flyup); + M_BindIntVariable("key_flydown", &key_flydown); + M_BindIntVariable("key_flycenter", &key_flycenter); + + M_BindIntVariable("key_lookup", &key_lookup); + M_BindIntVariable("key_lookdown", &key_lookdown); + M_BindIntVariable("key_lookcenter", &key_lookcenter); + + M_BindIntVariable("key_invleft", &key_invleft); + M_BindIntVariable("key_invright", &key_invright); + M_BindIntVariable("key_useartifact", &key_useartifact); + + M_BindIntVariable("mouseb_invleft", &mousebinvleft); + M_BindIntVariable("mouseb_invright", &mousebinvright); + M_BindIntVariable("mouseb_useartifact", &mousebuseartifact); + + M_BindIntVariable("joyb_invleft", &joybinvleft); + M_BindIntVariable("joyb_invright", &joybinvright); + M_BindIntVariable("joyb_useartifact", &joybuseartifact); + + M_BindIntVariable("joyb_flyup", &joybflyup); + M_BindIntVariable("joyb_flydown", &joybflydown); + M_BindIntVariable("joyb_flycenter", &joybflycenter); + + M_BindIntVariable("key_arti_quartz", &key_arti_quartz); + M_BindIntVariable("key_arti_urn", &key_arti_urn); + M_BindIntVariable("key_arti_bomb", &key_arti_bomb); + M_BindIntVariable("key_arti_tome", &key_arti_tome); + M_BindIntVariable("key_arti_ring", &key_arti_ring); + M_BindIntVariable("key_arti_chaosdevice", &key_arti_chaosdevice); + M_BindIntVariable("key_arti_shadowsphere", &key_arti_shadowsphere); + M_BindIntVariable("key_arti_wings", &key_arti_wings); + M_BindIntVariable("key_arti_torch", &key_arti_torch); + M_BindIntVariable("key_arti_morph", &key_arti_morph); +} + +void M_BindHexenControls(void) +{ + M_BindIntVariable("key_jump", &key_jump); + M_BindIntVariable("mouseb_jump", &mousebjump); + M_BindIntVariable("joyb_jump", &joybjump); + + M_BindIntVariable("key_arti_all", &key_arti_all); + M_BindIntVariable("key_arti_health", &key_arti_health); + M_BindIntVariable("key_arti_poisonbag", &key_arti_poisonbag); + M_BindIntVariable("key_arti_blastradius", &key_arti_blastradius); + M_BindIntVariable("key_arti_teleport", &key_arti_teleport); + M_BindIntVariable("key_arti_teleportother", &key_arti_teleportother); + M_BindIntVariable("key_arti_egg", &key_arti_egg); + M_BindIntVariable("key_arti_invulnerability", &key_arti_invulnerability); +} + +void M_BindStrifeControls(void) +{ + // These are shared with all games, but have different defaults: + key_message_refresh = '/'; + + // These keys are shared with Heretic/Hexen but have different defaults: + key_jump = 'a'; + key_lookup = KEY_PGUP; + key_lookdown = KEY_PGDN; + key_invleft = KEY_INS; + key_invright = KEY_DEL; + + M_BindIntVariable("key_jump", &key_jump); + M_BindIntVariable("key_lookUp", &key_lookup); + M_BindIntVariable("key_lookDown", &key_lookdown); + M_BindIntVariable("key_invLeft", &key_invleft); + M_BindIntVariable("key_invRight", &key_invright); + + // Custom Strife-only Keys: + M_BindIntVariable("key_useHealth", &key_usehealth); + M_BindIntVariable("key_invquery", &key_invquery); + M_BindIntVariable("key_mission", &key_mission); + M_BindIntVariable("key_invPop", &key_invpop); + M_BindIntVariable("key_invKey", &key_invkey); + M_BindIntVariable("key_invHome", &key_invhome); + M_BindIntVariable("key_invEnd", &key_invend); + M_BindIntVariable("key_invUse", &key_invuse); + M_BindIntVariable("key_invDrop", &key_invdrop); + + // Strife also supports jump on mouse and joystick, and in the exact same + // manner as Hexen! + M_BindIntVariable("mouseb_jump", &mousebjump); + M_BindIntVariable("joyb_jump", &joybjump); + + // Subset of inventory actions common to Heretic/Hexen and Strife. + M_BindIntVariable("joyb_invleft", &joybinvleft); + M_BindIntVariable("joyb_invright", &joybinvright); + // This is technically "invuse" in Strife, but let's reuse the value. + M_BindIntVariable("joyb_useartifact", &joybuseartifact); +} + +void M_BindWeaponControls(void) +{ + M_BindIntVariable("key_weapon1", &key_weapon1); + M_BindIntVariable("key_weapon2", &key_weapon2); + M_BindIntVariable("key_weapon3", &key_weapon3); + M_BindIntVariable("key_weapon4", &key_weapon4); + M_BindIntVariable("key_weapon5", &key_weapon5); + M_BindIntVariable("key_weapon6", &key_weapon6); + M_BindIntVariable("key_weapon7", &key_weapon7); + M_BindIntVariable("key_weapon8", &key_weapon8); + + M_BindIntVariable("key_prevweapon", &key_prevweapon); + M_BindIntVariable("key_nextweapon", &key_nextweapon); + + M_BindIntVariable("joyb_prevweapon", &joybprevweapon); + M_BindIntVariable("joyb_nextweapon", &joybnextweapon); + + M_BindIntVariable("mouseb_prevweapon", &mousebprevweapon); + M_BindIntVariable("mouseb_nextweapon", &mousebnextweapon); +} + +void M_BindMapControls(void) +{ + M_BindIntVariable("key_map_north", &key_map_north); + M_BindIntVariable("key_map_south", &key_map_south); + M_BindIntVariable("key_map_east", &key_map_east); + M_BindIntVariable("key_map_west", &key_map_west); + M_BindIntVariable("key_map_zoomin", &key_map_zoomin); + M_BindIntVariable("key_map_zoomout", &key_map_zoomout); + M_BindIntVariable("key_map_toggle", &key_map_toggle); + M_BindIntVariable("key_map_maxzoom", &key_map_maxzoom); + M_BindIntVariable("key_map_follow", &key_map_follow); + M_BindIntVariable("key_map_grid", &key_map_grid); + M_BindIntVariable("key_map_mark", &key_map_mark); + M_BindIntVariable("key_map_clearmark", &key_map_clearmark); +} + +void M_BindMenuControls(void) +{ + M_BindIntVariable("key_menu_activate", &key_menu_activate); + M_BindIntVariable("key_menu_up", &key_menu_up); + M_BindIntVariable("key_menu_down", &key_menu_down); + M_BindIntVariable("key_menu_left", &key_menu_left); + M_BindIntVariable("key_menu_right", &key_menu_right); + M_BindIntVariable("key_menu_back", &key_menu_back); + M_BindIntVariable("key_menu_forward", &key_menu_forward); + M_BindIntVariable("key_menu_confirm", &key_menu_confirm); + M_BindIntVariable("key_menu_abort", &key_menu_abort); + + M_BindIntVariable("key_menu_help", &key_menu_help); + M_BindIntVariable("key_menu_save", &key_menu_save); + M_BindIntVariable("key_menu_load", &key_menu_load); + M_BindIntVariable("key_menu_volume", &key_menu_volume); + M_BindIntVariable("key_menu_detail", &key_menu_detail); + M_BindIntVariable("key_menu_qsave", &key_menu_qsave); + M_BindIntVariable("key_menu_endgame", &key_menu_endgame); + M_BindIntVariable("key_menu_messages", &key_menu_messages); + M_BindIntVariable("key_menu_qload", &key_menu_qload); + M_BindIntVariable("key_menu_quit", &key_menu_quit); + M_BindIntVariable("key_menu_gamma", &key_menu_gamma); + + M_BindIntVariable("key_menu_incscreen", &key_menu_incscreen); + M_BindIntVariable("key_menu_decscreen", &key_menu_decscreen); + M_BindIntVariable("key_menu_screenshot",&key_menu_screenshot); + M_BindIntVariable("key_demo_quit", &key_demo_quit); + M_BindIntVariable("key_spy", &key_spy); +} + +void M_BindChatControls(unsigned int num_players) +{ + char name[32]; // haleyjd: 20 not large enough - Thank you, come again! + unsigned int i; // haleyjd: signedness conflict + + M_BindIntVariable("key_multi_msg", &key_multi_msg); + + for (i=0; i> FRACBITS; +} + + + +// +// FixedDiv, C version. +// + +fixed_t FixedDiv(fixed_t a, fixed_t b) +{ + if ((abs(a) >> 14) >= abs(b)) + { + return (a^b) < 0 ? INT_MIN : INT_MAX; + } + else + { + int64_t result; + + result = ((int64_t) a << FRACBITS) / b; + + return (fixed_t) result; + } +} + diff --git a/games/NXDoom/src/m_fixed.h b/games/NXDoom/src/m_fixed.h new file mode 100644 index 00000000000..733b2901ce8 --- /dev/null +++ b/games/NXDoom/src/m_fixed.h @@ -0,0 +1,39 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Fixed point arithemtics, implementation. +// + + +#ifndef __M_FIXED__ +#define __M_FIXED__ + + + + +// +// Fixed point, 32bit as 16.16. +// +#define FRACBITS 16 +#define FRACUNIT (1< +#include +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#else +#include +#endif + +#include "doomtype.h" + +#include "i_system.h" +#include "m_misc.h" +#include "z_zone.h" + +#ifdef _WIN32 +static wchar_t *ConvertMultiByteToWide(const char *str, UINT code_page) +{ + wchar_t *wstr = NULL; + int wlen = 0; + + wlen = MultiByteToWideChar(code_page, 0, str, -1, NULL, 0); + + if (!wlen) + { + errno = EINVAL; + printf("ConvertMultiByteToWide: Failed to convert path to wide encoding.\n"); + return NULL; + } + + wstr = malloc(sizeof(wchar_t) * wlen); + + if (!wstr) + { + I_Error("ConvertMultiByteToWide: Failed to allocate new string."); + return NULL; + } + + if (MultiByteToWideChar(code_page, 0, str, -1, wstr, wlen) == 0) + { + errno = EINVAL; + printf("ConvertMultiByteToWide: Failed to convert path to wide encoding.\n"); + free(wstr); + return NULL; + } + + return wstr; +} + +static char *ConvertWideToMultiByte(const wchar_t *wstr, UINT code_page) +{ + char *str = NULL; + int len = 0; + + len = WideCharToMultiByte(code_page, 0, wstr, -1, NULL, 0, NULL, NULL); + + if (!len) + { + errno = EINVAL; + printf("ConvertWideToMultiByte: Failed to convert path to multibyte encoding.\n"); + return NULL; + } + + str = malloc(sizeof(char) * len); + + if (!str) + { + I_Error("ConvertWideToMultiByte: Failed to allocate new string."); + return NULL; + } + + if (WideCharToMultiByte(code_page, 0, wstr, -1, str, len, NULL, NULL) == 0) + { + errno = EINVAL; + printf("ConvertWideToMultiByte: Failed to convert path to multibyte encoding.\n"); + free(str); + return NULL; + } + + return str; +} + +// Convert wide string to a UTF8 string. The result is newly allocated and must +// be freed by the caller after use. + +char *M_ConvertWideToUtf8(const wchar_t *wstr) +{ + return ConvertWideToMultiByte(wstr, CP_UTF8); +} + +// Convert UTF8 string to a wide string. The result is newly allocated and must +// be freed by the caller after use. + +wchar_t *M_ConvertUtf8ToWide(const char *str) +{ + return ConvertMultiByteToWide(str, CP_UTF8); +} +#endif + +FILE *M_fopen(const char *filename, const char *mode) +{ +#ifdef _WIN32 + FILE *file; + wchar_t *wname = NULL; + wchar_t *wmode = NULL; + + wname = M_ConvertUtf8ToWide(filename); + + if (!wname) + { + return NULL; + } + + wmode = M_ConvertUtf8ToWide(mode); + + if (!wmode) + { + free(wname); + return NULL; + } + + file = _wfopen(wname, wmode); + + free(wname); + free(wmode); + + return file; +#else + return fopen(filename, mode); +#endif +} + +int M_remove(const char *path) +{ +#ifdef _WIN32 + wchar_t *wpath = NULL; + int ret; + + wpath = M_ConvertUtf8ToWide(path); + + if (!wpath) + { + return 0; + } + + ret = _wremove(wpath); + + free(wpath); + + return ret; +#else + return remove(path); +#endif +} + +int M_rename(const char *oldname, const char *newname) +{ +#ifdef _WIN32 + wchar_t *wold = NULL; + wchar_t *wnew = NULL; + int ret; + + wold = M_ConvertUtf8ToWide(oldname); + + if (!wold) + { + return 0; + } + + wnew = M_ConvertUtf8ToWide(newname); + + if (!wnew) + { + free(wold); + return 0; + } + + ret = _wrename(wold, wnew); + + free(wold); + free(wnew); + + return ret; +#else + return rename(oldname, newname); +#endif +} + +int M_stat(const char *path, struct stat *buf) +{ +#ifdef _WIN32 + wchar_t *wpath = NULL; + struct _stat wbuf; + int ret; + + wpath = M_ConvertUtf8ToWide(path); + + if (!wpath) + { + return -1; + } + + ret = _wstat(wpath, &wbuf); + + // The _wstat() function expects a struct _stat* parameter that is + // incompatible with struct stat*. We copy only the required compatible + // field. + buf->st_mode = wbuf.st_mode; + + free(wpath); + + return ret; +#else + return stat(path, buf); +#endif +} + +#ifdef _WIN32 +typedef struct { + char *var; + const char *name; +} env_var_t; + +static env_var_t *env_vars; +static int num_vars; +#endif + +char *M_getenv(const char *name) +{ +#ifdef _WIN32 + int i; + wchar_t *wenv = NULL, *wname = NULL; + char *env = NULL; + + for (i = 0; i < num_vars; ++i) + { + if (!strcasecmp(name, env_vars[i].name)) + { + return env_vars[i].var; + } + } + + wname = M_ConvertUtf8ToWide(name); + + if (!wname) + { + return NULL; + } + + wenv = _wgetenv(wname); + + free(wname); + + if (wenv) + { + env = M_ConvertWideToUtf8(wenv); + } + else + { + env = NULL; + } + + env_vars = I_Realloc(env_vars, (num_vars + 1) * sizeof(*env_vars)); + env_vars[num_vars].var = env; + env_vars[num_vars].name = M_StringDuplicate(name); + ++num_vars; + + return env; +#else + return getenv(name); +#endif +} + +// +// Create a directory +// + +void M_MakeDirectory(const char *path) +{ +#ifdef _WIN32 + wchar_t *wdir; + + wdir = M_ConvertUtf8ToWide(path); + + if (!wdir) + { + return; + } + + _wmkdir(wdir); + + free(wdir); +#else + mkdir(path, 0755); +#endif +} + +// Check if a file exists + +boolean M_FileExists(const char *filename) +{ + FILE *fstream; + + fstream = M_fopen(filename, "r"); + + if (fstream != NULL) + { + fclose(fstream); + return true; + } + else + { + // If we can't open because the file is a directory, the + // "file" exists at least! + + return errno == EISDIR; + } +} + +// Check if a file exists by probing for common case variation of its filename. +// Returns a newly allocated string that the caller is responsible for freeing. + +char *M_FileCaseExists(const char *path) +{ + char *path_dup, *filename, *ext; + + path_dup = M_StringDuplicate(path); + + // 0: actual path + if (M_FileExists(path_dup)) + { + return path_dup; + } + + filename = strrchr(path_dup, DIR_SEPARATOR); + if (filename != NULL) + { + filename++; + } + else + { + filename = path_dup; + } + + // 1: lowercase filename, e.g. doom2.wad + M_ForceLowercase(filename); + + if (M_FileExists(path_dup)) + { + return path_dup; + } + + // 2: uppercase filename, e.g. DOOM2.WAD + M_ForceUppercase(filename); + + if (M_FileExists(path_dup)) + { + return path_dup; + } + + // 3. uppercase basename with lowercase extension, e.g. DOOM2.wad + ext = strrchr(path_dup, '.'); + if (ext != NULL && ext > filename) + { + M_ForceLowercase(ext + 1); + + if (M_FileExists(path_dup)) + { + return path_dup; + } + } + + // 4. lowercase filename with uppercase first letter, e.g. Doom2.wad + if (strlen(filename) > 1) + { + M_ForceLowercase(filename + 1); + + if (M_FileExists(path_dup)) + { + return path_dup; + } + } + + // 5. no luck + free(path_dup); + return NULL; +} + +// +// Determine the length of an open file. +// + +long M_FileLength(FILE *handle) +{ + long savedpos; + long length; + + // save the current position in the file + savedpos = ftell(handle); + + // jump to the end and find the length + fseek(handle, 0, SEEK_END); + length = ftell(handle); + + // go back to the old location + fseek(handle, savedpos, SEEK_SET); + + return length; +} + +// +// M_WriteFile +// + +boolean M_WriteFile(const char *name, const void *source, int length) +{ + FILE *handle; + int count; + + handle = M_fopen(name, "wb"); + + if (handle == NULL) + return false; + + count = fwrite(source, 1, length, handle); + fclose(handle); + + if (count < length) + return false; + + return true; +} + + +// +// M_ReadFile +// + +int M_ReadFile(const char *name, byte **buffer) +{ + FILE *handle; + int count, length; + byte *buf; + + handle = M_fopen(name, "rb"); + if (handle == NULL) + I_Error ("Couldn't read file %s", name); + + // find the size of the file by seeking to the end and + // reading the current position + + length = M_FileLength(handle); + + buf = Z_Malloc (length + 1, PU_STATIC, NULL); + count = fread(buf, 1, length, handle); + fclose (handle); + + if (count < length) + I_Error ("Couldn't read file %s", name); + + buf[length] = '\0'; + *buffer = buf; + return length; +} + +// Returns the path to a temporary file of the given name, stored +// inside the system temporary directory. +// +// The returned value must be freed with Z_Free after use. + +char *M_TempFile(const char *s) +{ + const char *tempdir; + +#ifdef _WIN32 + + // Check the TEMP environment variable to find the location. + + tempdir = M_getenv("TEMP"); + + if (tempdir == NULL) + { + tempdir = "."; + } +#else + // Check the $TMPDIR environment variable to find the location. + + tempdir = getenv("TMPDIR"); + + if (tempdir == NULL) + { + tempdir = "/tmp"; + } +#endif + + return M_StringJoin(tempdir, DIR_SEPARATOR_S, s, NULL); +} + +boolean M_StrToInt(const char *str, int *result) +{ + return sscanf(str, " 0x%x", (unsigned int *) result) == 1 + || sscanf(str, " 0X%x", (unsigned int *) result) == 1 + || sscanf(str, " 0%o", (unsigned int *) result) == 1 + || sscanf(str, " %d", result) == 1; +} + +// Returns the directory portion of the given path, without the trailing +// slash separator character. If no directory is described in the path, +// the string "." is returned. In either case, the result is newly allocated +// and must be freed by the caller after use. +char *M_DirName(const char *path) +{ + char *result; + const char *pf, *pb; + + pf = strrchr(path, '/'); +#ifdef _WIN32 + pb = strrchr(path, '\\'); +#else + pb = NULL; +#endif + if (pf == NULL && pb == NULL) + { + return M_StringDuplicate("."); + } + else + { + const char *p = (pb > pf) ? pb : pf; + result = M_StringDuplicate(path); + result[p - path] = '\0'; + return result; + } +} + +// Returns the base filename described by the given path (without the +// directory name). The result points inside path and nothing new is +// allocated. +const char *M_BaseName(const char *path) +{ + const char *pf, *pb; + + pf = strrchr(path, '/'); +#ifdef _WIN32 + pb = strrchr(path, '\\'); +#else + pb = NULL; +#endif + if (pf == NULL && pb == NULL) + { + return path; + } + else + { + const char *p = (pb > pf) ? pb : pf; + return p + 1; + } +} + +void M_ExtractFileBase(const char *path, char *dest) +{ + const char *src; + const char *filename; + int length; + + src = path + strlen(path) - 1; + + // back up until a \ or the start + while (src != path && *(src - 1) != DIR_SEPARATOR) + { + src--; + } + + filename = src; + + // Copy up to eight characters + // Note: Vanilla Doom exits with an error if a filename is specified + // with a base of more than eight characters. To remove the 8.3 + // filename limit, instead we simply truncate the name. + + length = 0; + memset(dest, 0, 8); + + while (*src != '\0' && *src != '.') + { + if (length >= 8) + { + printf("Warning: Truncated '%s' lump name to '%.8s'.\n", + filename, dest); + break; + } + + dest[length++] = toupper((int)*src++); + } +} + +//--------------------------------------------------------------------------- +// +// PROC M_ForceUppercase +// +// Change string to uppercase. +// +//--------------------------------------------------------------------------- + +void M_ForceUppercase(char *text) +{ + char *p; + + for (p = text; *p != '\0'; ++p) + { + *p = toupper(*p); + } +} + +//--------------------------------------------------------------------------- +// +// PROC M_ForceLowercase +// +// Change string to lowercase. +// +//--------------------------------------------------------------------------- + +void M_ForceLowercase(char *text) +{ + char *p; + + for (p = text; *p != '\0'; ++p) + { + *p = tolower(*p); + } +} + +// +// M_StrCaseStr +// +// Case-insensitive version of strstr() +// + +const char *M_StrCaseStr(const char *haystack, const char *needle) +{ + unsigned int haystack_len; + unsigned int needle_len; + unsigned int len; + unsigned int i; + + haystack_len = strlen(haystack); + needle_len = strlen(needle); + + if (haystack_len < needle_len) + { + return NULL; + } + + len = haystack_len - needle_len; + + for (i = 0; i <= len; ++i) + { + if (!strncasecmp(haystack + i, needle, needle_len)) + { + return haystack + i; + } + } + + return NULL; +} + +// +// Safe version of strdup() that checks the string was successfully +// allocated. +// + +char *M_StringDuplicate(const char *orig) +{ + char *result; + + result = strdup(orig); + + if (result == NULL) + { + I_Error("Failed to duplicate string (length %zu)\n", + strlen(orig)); + } + + return result; +} + +// +// String replace function. +// + +char *M_StringReplace(const char *haystack, const char *needle, + const char *replacement) +{ + char *result, *dst; + const char *p; + size_t needle_len = strlen(needle); + size_t result_len, dst_len; + + // Iterate through occurrences of 'needle' and calculate the size of + // the new string. + result_len = strlen(haystack) + 1; + p = haystack; + + for (;;) + { + p = strstr(p, needle); + if (p == NULL) + { + break; + } + + p += needle_len; + result_len += strlen(replacement) - needle_len; + } + + // Construct new string. + + result = malloc(result_len); + if (result == NULL) + { + I_Error("M_StringReplace: Failed to allocate new string"); + return NULL; + } + + dst = result; dst_len = result_len; + p = haystack; + + while (*p != '\0') + { + if (!strncmp(p, needle, needle_len)) + { + M_StringCopy(dst, replacement, dst_len); + p += needle_len; + dst += strlen(replacement); + dst_len -= strlen(replacement); + } + else + { + *dst = *p; + ++dst; --dst_len; + ++p; + } + } + + *dst = '\0'; + + return result; +} + +// Safe string copy function that works like OpenBSD's strlcpy(). +// Returns true if the string was not truncated. + +boolean M_StringCopy(char *dest, const char *src, size_t dest_size) +{ + size_t len; + + if (dest_size >= 1) + { + dest[dest_size - 1] = '\0'; + strncpy(dest, src, dest_size - 1); + } + else + { + return false; + } + + len = strlen(dest); + return src[len] == '\0'; +} + +// Safe string concat function that works like OpenBSD's strlcat(). +// Returns true if string not truncated. + +boolean M_StringConcat(char *dest, const char *src, size_t dest_size) +{ + size_t offset; + + offset = strlen(dest); + if (offset > dest_size) + { + offset = dest_size; + } + + return M_StringCopy(dest + offset, src, dest_size - offset); +} + +// Returns true if 's' begins with the specified prefix. + +boolean M_StringStartsWith(const char *s, const char *prefix) +{ + return strlen(s) >= strlen(prefix) + && strncmp(s, prefix, strlen(prefix)) == 0; +} + +// Returns true if 's' ends with the specified suffix. + +boolean M_StringEndsWith(const char *s, const char *suffix) +{ + return strlen(s) >= strlen(suffix) + && strcmp(s + strlen(s) - strlen(suffix), suffix) == 0; +} + +// Return a newly-malloced string with all the strings given as arguments +// concatenated together. + +char *M_StringJoin(const char *s, ...) +{ + char *result; + const char *v; + va_list args; + size_t result_len; + + result_len = strlen(s) + 1; + + va_start(args, s); + for (;;) + { + v = va_arg(args, const char *); + if (v == NULL) + { + break; + } + + result_len += strlen(v); + } + va_end(args); + + result = malloc(result_len); + + if (result == NULL) + { + I_Error("M_StringJoin: Failed to allocate new string."); + return NULL; + } + + M_StringCopy(result, s, result_len); + + va_start(args, s); + for (;;) + { + v = va_arg(args, const char *); + if (v == NULL) + { + break; + } + + M_StringConcat(result, v, result_len); + } + va_end(args); + + return result; +} + +// On Windows, vsnprintf() is _vsnprintf(). +#ifdef _WIN32 +#if _MSC_VER < 1400 /* not needed for Visual Studio 2008 */ +#define vsnprintf _vsnprintf +#endif +#endif + +// Safe, portable vsnprintf(). +int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args) +{ + int result; + + if (buf_len < 1) + { + return 0; + } + + // Windows (and other OSes?) has a vsnprintf() that doesn't always + // append a trailing \0. So we must do it, and write into a buffer + // that is one byte shorter; otherwise this function is unsafe. + result = vsnprintf(buf, buf_len, s, args); + + // If truncated, change the final char in the buffer to a \0. + // A negative result indicates a truncated buffer on Windows. + if (result < 0 || result >= buf_len) + { + buf[buf_len - 1] = '\0'; + result = buf_len - 1; + } + + return result; +} + +// Safe, portable snprintf(). +int M_snprintf(char *buf, size_t buf_len, const char *s, ...) +{ + va_list args; + int result; + va_start(args, s); + result = M_vsnprintf(buf, buf_len, s, args); + va_end(args); + return result; +} + +// +// M_NormalizeSlashes +// +// Remove trailing slashes, translate backslashes to slashes +// The string to normalize is passed and returned in str +// +// killough 11/98: rewritten +// +// [STRIFE] - haleyjd 20110210: Borrowed from Eternity and adapted to respect +// the DIR_SEPARATOR define used by Choco Doom. This routine originated in +// BOOM. +// +void M_NormalizeSlashes(char *str) +{ + char *p; + + // Convert all slashes/backslashes to DIR_SEPARATOR + for (p = str; *p; p++) + { + if ((*p == '/' || *p == '\\') && *p != DIR_SEPARATOR) + { + *p = DIR_SEPARATOR; + } + } + + // Remove trailing slashes + while (p > str && *--p == DIR_SEPARATOR) + { + *p = 0; + } + + // Collapse multiple slashes + for (p = str; (*str++ = *p); ) + { + if (*p++ == DIR_SEPARATOR) + { + while (*p == DIR_SEPARATOR) + { + p++; + } + } + } +} diff --git a/games/NXDoom/src/m_misc.h b/games/NXDoom/src/m_misc.h new file mode 100644 index 00000000000..6dc18ccfa36 --- /dev/null +++ b/games/NXDoom/src/m_misc.h @@ -0,0 +1,107 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Miscellaneous. +// + + +#ifndef __M_MISC__ +#define __M_MISC__ + +#include +#include +#include + +#include "doomtype.h" + +#ifdef _WIN32 +wchar_t *M_ConvertUtf8ToWide(const char *str); +char *M_ConvertWideToUtf8(const wchar_t *wstr); +#endif + +FILE *M_fopen(const char *filename, const char *mode); +int M_remove(const char *path); +int M_rename(const char *oldname, const char *newname); +int M_stat(const char *path, struct stat *buf); +char *M_getenv(const char *name); +boolean M_WriteFile(const char *name, const void *source, int length); +int M_ReadFile(const char *name, byte **buffer); +void M_MakeDirectory(const char *dir); +char *M_TempFile(const char *s); +boolean M_FileExists(const char *file); +char *M_FileCaseExists(const char *file); +long M_FileLength(FILE *handle); +boolean M_StrToInt(const char *str, int *result); +char *M_DirName(const char *path); +const char *M_BaseName(const char *path); +void M_ExtractFileBase(const char *path, char *dest); +void M_ForceUppercase(char *text); +void M_ForceLowercase(char *text); +const char *M_StrCaseStr(const char *haystack, const char *needle); +char *M_StringDuplicate(const char *orig); +boolean M_StringCopy(char *dest, const char *src, size_t dest_size); +boolean M_StringConcat(char *dest, const char *src, size_t dest_size); +char *M_StringReplace(const char *haystack, const char *needle, + const char *replacement); +char *M_StringJoin(const char *s, ...); +boolean M_StringStartsWith(const char *s, const char *prefix); +boolean M_StringEndsWith(const char *s, const char *suffix); +int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args); +int M_snprintf(char *buf, size_t buf_len, const char *s, ...) PRINTF_ATTR(3, 4); +void M_NormalizeSlashes(char *str); + + +// debugging code to check there are no loops in a linked list +// disabled unless explicitly requested +#ifdef DEBUG_LINKED_LISTS + + +#define LINKED_LIST_CHECK_NO_CYCLE(list_type, list, next_member) \ + do \ + { \ + if (list != NULL) { \ + list_type *slow, *fast; \ + slow = list; \ + fast = list->next_member; \ + while (fast) { \ + if (!fast->next_member) { \ + break; \ + } \ + fast = fast->next_member->next_member; \ + slow = slow->next_member; \ + if (slow == fast) { \ + fprintf(stderr, "loop in linked list " # list " in %s:%d", __FILE__, __LINE__); \ + __builtin_trap(); \ + } \ + } \ + } \ + } while (0) \ + + + +#else // DEBUG_LINKED_LISTS + + +#define LINKED_LIST_CHECK_NO_CYCLE(list_type, list, next_member) \ + do \ + { \ + } while (0) \ + + +#endif // DEBUG_LINKED_LISTS + + +#endif + diff --git a/games/NXDoom/src/manifest.xml b/games/NXDoom/src/manifest.xml new file mode 100644 index 00000000000..05a19e7ad92 --- /dev/null +++ b/games/NXDoom/src/manifest.xml @@ -0,0 +1,12 @@ + + + + + + + true + + + + diff --git a/games/NXDoom/src/memio.c b/games/NXDoom/src/memio.c new file mode 100644 index 00000000000..299a66bf73d --- /dev/null +++ b/games/NXDoom/src/memio.c @@ -0,0 +1,197 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Emulates the IO functions in C stdio.h reading and writing to +// memory. +// + +#include +#include +#include + +#include "memio.h" + +#include "z_zone.h" + +typedef enum { + MODE_READ, + MODE_WRITE, +} memfile_mode_t; + +struct _MEMFILE { + unsigned char *buf; + size_t buflen; + size_t alloced; + unsigned int position; + memfile_mode_t mode; +}; + +// Open a memory area for reading + +MEMFILE *mem_fopen_read(void *buf, size_t buflen) +{ + MEMFILE *file; + + file = Z_Malloc(sizeof(MEMFILE), PU_STATIC, 0); + + file->buf = (unsigned char *) buf; + file->buflen = buflen; + file->position = 0; + file->mode = MODE_READ; + + return file; +} + +// Read bytes + +size_t mem_fread(void *buf, size_t size, size_t nmemb, MEMFILE *stream) +{ + size_t items; + + if (stream->mode != MODE_READ) + { + printf("not a read stream\n"); + return -1; + } + + // Trying to read more bytes than we have left? + + items = nmemb; + + if (items * size > stream->buflen - stream->position) + { + items = (stream->buflen - stream->position) / size; + } + + // Copy bytes to buffer + + memcpy(buf, stream->buf + stream->position, items * size); + + // Update position + + stream->position += items * size; + + return items; +} + +// Open a memory area for writing + +MEMFILE *mem_fopen_write(void) +{ + MEMFILE *file; + + file = Z_Malloc(sizeof(MEMFILE), PU_STATIC, 0); + + file->alloced = 1024; + file->buf = Z_Malloc(file->alloced, PU_STATIC, 0); + file->buflen = 0; + file->position = 0; + file->mode = MODE_WRITE; + + return file; +} + +// Write bytes to stream + +size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, MEMFILE *stream) +{ + size_t bytes; + + if (stream->mode != MODE_WRITE) + { + return -1; + } + + // More bytes than can fit in the buffer? + // If so, reallocate bigger. + + bytes = size * nmemb; + + while (bytes > stream->alloced - stream->position) + { + unsigned char *newbuf; + + newbuf = Z_Malloc(stream->alloced * 2, PU_STATIC, 0); + memcpy(newbuf, stream->buf, stream->alloced); + Z_Free(stream->buf); + stream->buf = newbuf; + stream->alloced *= 2; + } + + // Copy into buffer + + memcpy(stream->buf + stream->position, ptr, bytes); + stream->position += bytes; + + if (stream->position > stream->buflen) + stream->buflen = stream->position; + + return nmemb; +} + +void mem_get_buf(MEMFILE *stream, void **buf, size_t *buflen) +{ + *buf = stream->buf; + *buflen = stream->buflen; +} + +void mem_fclose(MEMFILE *stream) +{ + if (stream->mode == MODE_WRITE) + { + Z_Free(stream->buf); + } + + Z_Free(stream); +} + +long mem_ftell(MEMFILE *stream) +{ + return stream->position; +} + +int mem_fseek(MEMFILE *stream, signed long position, mem_rel_t whence) +{ + unsigned int newpos; + + switch (whence) + { + case MEM_SEEK_SET: + newpos = (int) position; + break; + + case MEM_SEEK_CUR: + newpos = (int) (stream->position + position); + break; + + case MEM_SEEK_END: + newpos = (int) (stream->buflen + position); + break; + default: + return -1; + } + + if (newpos < stream->buflen) + { + stream->position = newpos; + return 0; + } + else + { + printf("Error seeking to %u\n", newpos); + return -1; + } +} + + diff --git a/games/NXDoom/src/memio.h b/games/NXDoom/src/memio.h new file mode 100644 index 00000000000..03706a3171a --- /dev/null +++ b/games/NXDoom/src/memio.h @@ -0,0 +1,38 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef MEMIO_H +#define MEMIO_H + +typedef struct _MEMFILE MEMFILE; + +typedef enum +{ + MEM_SEEK_SET, + MEM_SEEK_CUR, + MEM_SEEK_END, +} mem_rel_t; + +MEMFILE *mem_fopen_read(void *buf, size_t buflen); +size_t mem_fread(void *buf, size_t size, size_t nmemb, MEMFILE *stream); +MEMFILE *mem_fopen_write(void); +size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, MEMFILE *stream); +void mem_get_buf(MEMFILE *stream, void **buf, size_t *buflen); +void mem_fclose(MEMFILE *stream); +long mem_ftell(MEMFILE *stream); +int mem_fseek(MEMFILE *stream, signed long offset, mem_rel_t whence); + +#endif /* #ifndef MEMIO_H */ + diff --git a/games/NXDoom/src/midifallback.c b/games/NXDoom/src/midifallback.c new file mode 100644 index 00000000000..615d6880f23 --- /dev/null +++ b/games/NXDoom/src/midifallback.c @@ -0,0 +1,370 @@ +// +// Copyright(C) 2022 ceski +// +// 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. +// +// DESCRIPTION: +// MIDI instrument fallback support +// + +#ifdef _WIN32 + +#include "doomtype.h" +#include "midifile.h" +#include "midifallback.h" + +static const byte drums_table[128] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x18, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F +}; + +static byte variation[128][128]; +static byte bank_msb[MIDI_CHANNELS_PER_TRACK]; +static byte drum_map[MIDI_CHANNELS_PER_TRACK]; +static boolean selected[MIDI_CHANNELS_PER_TRACK]; + +static void UpdateDrumMap(const byte *msg, unsigned int length) +{ + byte idx; + byte checksum; + + // GS allows drums on any channel using SysEx messages. + // The message format is F0 followed by: + // + // 41 10 42 12 40 15 F7 + // + // is [11-19, 10, 1A-1F] for channels 1-16. Note the position of 10. + // is 00-02 for off (normal part), drum map 1, or drum map 2. + // is checksum. + + if (length == 10 && + msg[0] == 0x41 && // Roland + msg[1] == 0x10 && // Device ID + msg[2] == 0x42 && // GS + msg[3] == 0x12 && // DT1 + msg[4] == 0x40 && // Address MSB + msg[6] == 0x15 && // Address LSB + msg[9] == 0xF7) // SysEx EOX + { + checksum = 128 - ((int)msg[4] + msg[5] + msg[6] + msg[7]) % 128; + + if (msg[8] != checksum) + { + return; + } + + if (msg[5] == 0x10) // Channel 10 + { + idx = 9; + } + else if (msg[5] < 0x1A) // Channels 1-9 + { + idx = (msg[5] & 0x0F) - 1; + } + else // Channels 11-16 + { + idx = msg[5] & 0x0F; + } + + drum_map[idx] = msg[7]; + } +} + +static boolean GetProgramFallback(byte idx, byte program, + midi_fallback_t *fallback) +{ + if (drum_map[idx] == 0) // Normal channel + { + if (bank_msb[idx] == 0 || variation[bank_msb[idx]][program]) + { + // Found a capital or variation for this bank select MSB. + selected[idx] = true; + return false; + } + + fallback->type = FALLBACK_BANK_MSB; + + if (!selected[idx] || bank_msb[idx] > 63) + { + // Fall to capital when no instrument has (successfully) + // selected this variation or if the variation is above 63. + fallback->value = 0; + return true; + } + + // A previous instrument used this variation but it's not + // valid for the current instrument. Fall to the next valid + // "sub-capital" (next variation that is a multiple of 8). + fallback->value = (bank_msb[idx] / 8) * 8; + while (fallback->value > 0) + { + if (variation[fallback->value][program]) + { + break; + } + fallback->value -= 8; + } + return true; + } + else // Drums channel + { + if (program != drums_table[program]) + { + // Use drum set from drums fallback table. + // Drums 0-63 and 127: same as original SC-55 (1.00 - 1.21). + // Drums 64-126: standard drum set (0). + fallback->type = FALLBACK_DRUMS; + fallback->value = drums_table[program]; + selected[idx] = true; + return true; + } + } + + return false; +} + +void MIDI_CheckFallback(const midi_event_t *event, midi_fallback_t *fallback, + boolean allow_sysex) +{ + byte idx; + byte program; + + switch ((int)event->event_type) + { + case MIDI_EVENT_SYSEX: + if (allow_sysex) + { + UpdateDrumMap(event->data.sysex.data, event->data.sysex.length); + } + break; + + case MIDI_EVENT_CONTROLLER: + idx = event->data.channel.channel; + switch (event->data.channel.param1) + { + case MIDI_CONTROLLER_BANK_SELECT_MSB: + bank_msb[idx] = event->data.channel.param2; + selected[idx] = false; + break; + + case MIDI_CONTROLLER_BANK_SELECT_LSB: + selected[idx] = false; + if (event->data.channel.param2 > 0) + { + // Bank select LSB > 0 not supported. This also + // preserves user's current SC-XX map. + fallback->type = FALLBACK_BANK_LSB; + fallback->value = 0; + return; + } + break; + + case EMIDI_CONTROLLER_PROGRAM_CHANGE: + program = event->data.channel.param2; + if (GetProgramFallback(idx, program, fallback)) + { + return; + } + break; + } + break; + + case MIDI_EVENT_PROGRAM_CHANGE: + idx = event->data.channel.channel; + program = event->data.channel.param1; + if (GetProgramFallback(idx, program, fallback)) + { + return; + } + break; + } + + fallback->type = FALLBACK_NONE; + fallback->value = 0; +} + +void MIDI_ResetFallback(void) +{ + int i; + + for (i = 0; i < MIDI_CHANNELS_PER_TRACK; i++) + { + bank_msb[i] = 0; + drum_map[i] = 0; + selected[i] = false; + } + + // Channel 10 (index 9) is set to drum map 1 by default. + drum_map[9] = 1; +} + +void MIDI_InitFallback(void) +{ + byte program; + + MIDI_ResetFallback(); + + // Capital + for (program = 0; program < 128; program++) + { + variation[0][program] = 1; + } + + // Variation #1 + variation[1][38] = 1; + variation[1][57] = 1; + variation[1][60] = 1; + variation[1][80] = 1; + variation[1][81] = 1; + variation[1][98] = 1; + variation[1][102] = 1; + variation[1][104] = 1; + variation[1][120] = 1; + variation[1][121] = 1; + variation[1][122] = 1; + variation[1][123] = 1; + variation[1][124] = 1; + variation[1][125] = 1; + variation[1][126] = 1; + variation[1][127] = 1; + + // Variation #2 + variation[2][102] = 1; + variation[2][120] = 1; + variation[2][122] = 1; + variation[2][123] = 1; + variation[2][124] = 1; + variation[2][125] = 1; + variation[2][126] = 1; + variation[2][127] = 1; + + // Variation #3 + variation[3][122] = 1; + variation[3][123] = 1; + variation[3][124] = 1; + variation[3][125] = 1; + variation[3][126] = 1; + variation[3][127] = 1; + + // Variation #4 + variation[4][122] = 1; + variation[4][124] = 1; + variation[4][125] = 1; + variation[4][126] = 1; + + // Variation #5 + variation[5][122] = 1; + variation[5][124] = 1; + variation[5][125] = 1; + variation[5][126] = 1; + + // Variation #6 + variation[6][125] = 1; + + // Variation #7 + variation[7][125] = 1; + + // Variation #8 + variation[8][0] = 1; + variation[8][1] = 1; + variation[8][2] = 1; + variation[8][3] = 1; + variation[8][4] = 1; + variation[8][5] = 1; + variation[8][6] = 1; + variation[8][11] = 1; + variation[8][12] = 1; + variation[8][14] = 1; + variation[8][16] = 1; + variation[8][17] = 1; + variation[8][19] = 1; + variation[8][21] = 1; + variation[8][24] = 1; + variation[8][25] = 1; + variation[8][26] = 1; + variation[8][27] = 1; + variation[8][28] = 1; + variation[8][30] = 1; + variation[8][31] = 1; + variation[8][38] = 1; + variation[8][39] = 1; + variation[8][40] = 1; + variation[8][48] = 1; + variation[8][50] = 1; + variation[8][61] = 1; + variation[8][62] = 1; + variation[8][63] = 1; + variation[8][80] = 1; + variation[8][81] = 1; + variation[8][107] = 1; + variation[8][115] = 1; + variation[8][116] = 1; + variation[8][117] = 1; + variation[8][118] = 1; + variation[8][125] = 1; + + // Variation #9 + variation[9][14] = 1; + variation[9][118] = 1; + variation[9][125] = 1; + + // Variation #16 + variation[16][0] = 1; + variation[16][4] = 1; + variation[16][5] = 1; + variation[16][6] = 1; + variation[16][16] = 1; + variation[16][19] = 1; + variation[16][24] = 1; + variation[16][25] = 1; + variation[16][28] = 1; + variation[16][39] = 1; + variation[16][62] = 1; + variation[16][63] = 1; + + // Variation #24 + variation[24][4] = 1; + variation[24][6] = 1; + + // Variation #32 + variation[32][16] = 1; + variation[32][17] = 1; + variation[32][24] = 1; + variation[32][52] = 1; + + // CM-64 Map (PCM) + for (program = 0; program < 64; program++) + { + variation[126][program] = 1; + } + + // CM-64 Map (LA) + for (program = 0; program < 128; program++) + { + variation[127][program] = 1; + } +} + +#endif diff --git a/games/NXDoom/src/midifallback.h b/games/NXDoom/src/midifallback.h new file mode 100644 index 00000000000..6093b2e6ffa --- /dev/null +++ b/games/NXDoom/src/midifallback.h @@ -0,0 +1,47 @@ +// +// Copyright(C) 2022 ceski +// +// 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. +// +// DESCRIPTION: +// MIDI instrument fallback support +// + +#ifdef _WIN32 + +#ifndef MIDIFALLBACK_H +#define MIDIFALLBACK_H + +#include "doomtype.h" +#include "midifile.h" + +typedef enum midi_fallback_type_t +{ + FALLBACK_NONE, + FALLBACK_BANK_MSB, + FALLBACK_BANK_LSB, + FALLBACK_DRUMS, +} midi_fallback_type_t; + +typedef struct midi_fallback_t +{ + midi_fallback_type_t type; + byte value; +} midi_fallback_t; + +void MIDI_CheckFallback(const midi_event_t *event, midi_fallback_t *fallback, + boolean allow_sysex); +void MIDI_ResetFallback(void); +void MIDI_InitFallback(void); + +#endif // MIDIFALLBACK_H + +#endif // _WIN32 diff --git a/games/NXDoom/src/midifile.c b/games/NXDoom/src/midifile.c new file mode 100644 index 00000000000..258154eeab9 --- /dev/null +++ b/games/NXDoom/src/midifile.c @@ -0,0 +1,838 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Reading of MIDI files. +// + +#include +#include +#include +#include + +#include "doomtype.h" +#include "i_swap.h" +#include "i_system.h" +#include "m_misc.h" +#include "midifile.h" + +#define HEADER_CHUNK_ID "MThd" +#define TRACK_CHUNK_ID "MTrk" +#define MAX_BUFFER_SIZE 0x10000 + +// haleyjd 09/09/10: packing required +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif + +typedef PACKED_STRUCT ( +{ + byte chunk_id[4]; + unsigned int chunk_size; +}) chunk_header_t; + +typedef PACKED_STRUCT ( +{ + chunk_header_t chunk_header; + unsigned short format_type; + unsigned short num_tracks; + unsigned short time_division; +}) midi_header_t; + +// haleyjd 09/09/10: packing off. +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +typedef struct +{ + // Length in bytes: + + unsigned int data_len; + + // Events in this track: + + midi_event_t *events; + int num_events; +} midi_track_t; + +struct midi_track_iter_s +{ + midi_track_t *track; + unsigned int position; + unsigned int loop_point; +}; + +struct midi_file_s +{ + midi_header_t header; + + // All tracks in this file: + midi_track_t *tracks; + unsigned int num_tracks; + + // Data buffer used to store data read for SysEx or meta events: + byte *buffer; + unsigned int buffer_size; +}; + +// Check the header of a chunk: + +static boolean CheckChunkHeader(chunk_header_t *chunk, + const char *expected_id) +{ + boolean result; + + result = (memcmp((char *) chunk->chunk_id, expected_id, 4) == 0); + + if (!result) + { + fprintf(stderr, "CheckChunkHeader: Expected '%s' chunk header, " + "got '%c%c%c%c'\n", + expected_id, + chunk->chunk_id[0], chunk->chunk_id[1], + chunk->chunk_id[2], chunk->chunk_id[3]); + } + + return result; +} + +// Read a single byte. Returns false on error. + +static boolean ReadByte(byte *result, FILE *stream) +{ + int c; + + c = fgetc(stream); + + if (c == EOF) + { + fprintf(stderr, "ReadByte: Unexpected end of file\n"); + return false; + } + else + { + *result = (byte) c; + + return true; + } +} + +// Read a variable-length value. + +static boolean ReadVariableLength(unsigned int *result, FILE *stream) +{ + int i; + byte b = 0; + + *result = 0; + + for (i=0; i<4; ++i) + { + if (!ReadByte(&b, stream)) + { + fprintf(stderr, "ReadVariableLength: Error while reading " + "variable-length value\n"); + return false; + } + + // Insert the bottom seven bits from this byte. + + *result <<= 7; + *result |= b & 0x7f; + + // If the top bit is not set, this is the end. + + if ((b & 0x80) == 0) + { + return true; + } + } + + fprintf(stderr, "ReadVariableLength: Variable-length value too " + "long: maximum of four bytes\n"); + return false; +} + +// Read a byte sequence into the data buffer. + +static void *ReadByteSequence(unsigned int num_bytes, FILE *stream) +{ + unsigned int i; + byte *result; + + // Allocate a buffer. Allocate one extra byte, as malloc(0) is + // non-portable. + + result = malloc(num_bytes + 1); + + if (result == NULL) + { + fprintf(stderr, "ReadByteSequence: Failed to allocate buffer\n"); + return NULL; + } + + // Read the data: + + for (i=0; ievent_type = event_type & 0xf0; + event->data.channel.channel = event_type & 0x0f; + + // Read parameters: + + if (!ReadByte(&b, stream)) + { + fprintf(stderr, "ReadChannelEvent: Error while reading channel " + "event parameters\n"); + return false; + } + + event->data.channel.param1 = b; + + // Second parameter: + + if (two_param) + { + if (!ReadByte(&b, stream)) + { + fprintf(stderr, "ReadChannelEvent: Error while reading channel " + "event parameters\n"); + return false; + } + + event->data.channel.param2 = b; + } + + return true; +} + +// Read sysex event: + +static boolean ReadSysExEvent(midi_event_t *event, int event_type, + FILE *stream) +{ + event->event_type = event_type; + + if (!ReadVariableLength(&event->data.sysex.length, stream)) + { + fprintf(stderr, "ReadSysExEvent: Failed to read length of " + "SysEx block\n"); + return false; + } + + // Read the byte sequence: + + event->data.sysex.data = ReadByteSequence(event->data.sysex.length, stream); + + if (event->data.sysex.data == NULL) + { + fprintf(stderr, "ReadSysExEvent: Failed while reading SysEx event\n"); + return false; + } + + return true; +} + +// Read meta event: + +static boolean ReadMetaEvent(midi_event_t *event, FILE *stream) +{ + byte b = 0; + + event->event_type = MIDI_EVENT_META; + + // Read meta event type: + + if (!ReadByte(&b, stream)) + { + fprintf(stderr, "ReadMetaEvent: Failed to read meta event type\n"); + return false; + } + + event->data.meta.type = b; + + // Read length of meta event data: + + if (!ReadVariableLength(&event->data.meta.length, stream)) + { + fprintf(stderr, "ReadSysExEvent: Failed to read length of " + "SysEx block\n"); + return false; + } + + // Read the byte sequence: + + event->data.meta.data = ReadByteSequence(event->data.meta.length, stream); + + if (event->data.meta.data == NULL) + { + fprintf(stderr, "ReadSysExEvent: Failed while reading SysEx event\n"); + return false; + } + + return true; +} + +static boolean ReadEvent(midi_event_t *event, unsigned int *last_event_type, + FILE *stream) +{ + byte event_type = 0; + + if (!ReadVariableLength(&event->delta_time, stream)) + { + fprintf(stderr, "ReadEvent: Failed to read event timestamp\n"); + return false; + } + + if (!ReadByte(&event_type, stream)) + { + fprintf(stderr, "ReadEvent: Failed to read event type\n"); + return false; + } + + // All event types have their top bit set. Therefore, if + // the top bit is not set, it is because we are using the "same + // as previous event type" shortcut to save a byte. Skip back + // a byte so that we read this byte again. + + if ((event_type & 0x80) == 0) + { + event_type = *last_event_type; + + if (fseek(stream, -1, SEEK_CUR) < 0) + { + fprintf(stderr, "ReadEvent: Unable to seek in stream\n"); + return false; + } + } + else + { + *last_event_type = event_type; + } + + // Check event type: + + switch (event_type & 0xf0) + { + // Two parameter channel events: + + case MIDI_EVENT_NOTE_OFF: + case MIDI_EVENT_NOTE_ON: + case MIDI_EVENT_AFTERTOUCH: + case MIDI_EVENT_CONTROLLER: + case MIDI_EVENT_PITCH_BEND: + return ReadChannelEvent(event, event_type, true, stream); + + // Single parameter channel events: + + case MIDI_EVENT_PROGRAM_CHANGE: + case MIDI_EVENT_CHAN_AFTERTOUCH: + return ReadChannelEvent(event, event_type, false, stream); + + default: + break; + } + + // Specific value? + + switch (event_type) + { + case MIDI_EVENT_SYSEX: + case MIDI_EVENT_SYSEX_SPLIT: + return ReadSysExEvent(event, event_type, stream); + + case MIDI_EVENT_META: + return ReadMetaEvent(event, stream); + + default: + break; + } + + fprintf(stderr, "ReadEvent: Unknown MIDI event type: 0x%x\n", event_type); + return false; +} + +// Free an event: + +static void FreeEvent(midi_event_t *event) +{ + // Some event types have dynamically allocated buffers assigned + // to them that must be freed. + + switch (event->event_type) + { + case MIDI_EVENT_SYSEX: + case MIDI_EVENT_SYSEX_SPLIT: + free(event->data.sysex.data); + break; + + case MIDI_EVENT_META: + free(event->data.meta.data); + break; + + default: + // Nothing to do. + break; + } +} + +// Read and check the track chunk header + +static boolean ReadTrackHeader(midi_track_t *track, FILE *stream) +{ + size_t records_read; + chunk_header_t chunk_header; + + records_read = fread(&chunk_header, sizeof(chunk_header_t), 1, stream); + + if (records_read < 1) + { + return false; + } + + if (!CheckChunkHeader(&chunk_header, TRACK_CHUNK_ID)) + { + return false; + } + + track->data_len = SDL_SwapBE32(chunk_header.chunk_size); + + return true; +} + +static boolean ReadTrack(midi_track_t *track, FILE *stream) +{ + midi_event_t *new_events; + midi_event_t *event; + unsigned int last_event_type; + + track->num_events = 0; + track->events = NULL; + + // Read the header: + + if (!ReadTrackHeader(track, stream)) + { + return false; + } + + // Then the events: + + last_event_type = 0; + + for (;;) + { + // Resize the track slightly larger to hold another event: + + new_events = I_Realloc(track->events, + sizeof(midi_event_t) * (track->num_events + 1)); + track->events = new_events; + + // Read the next event: + + event = &track->events[track->num_events]; + if (!ReadEvent(event, &last_event_type, stream)) + { + return false; + } + + ++track->num_events; + + // End of track? + + if (event->event_type == MIDI_EVENT_META + && event->data.meta.type == MIDI_META_END_OF_TRACK) + { + break; + } + } + + return true; +} + +// Free a track: + +static void FreeTrack(midi_track_t *track) +{ + unsigned int i; + + for (i=0; inum_events; ++i) + { + FreeEvent(&track->events[i]); + } + + free(track->events); +} + +static boolean ReadAllTracks(midi_file_t *file, FILE *stream) +{ + unsigned int i; + + // Allocate list of tracks and read each track: + + file->tracks = malloc(sizeof(midi_track_t) * file->num_tracks); + + if (file->tracks == NULL) + { + return false; + } + + memset(file->tracks, 0, sizeof(midi_track_t) * file->num_tracks); + + // Read each track: + + for (i=0; inum_tracks; ++i) + { + if (!ReadTrack(&file->tracks[i], stream)) + { + return false; + } + } + + return true; +} + +// Read and check the header chunk. + +static boolean ReadFileHeader(midi_file_t *file, FILE *stream) +{ + size_t records_read; + unsigned int format_type; + + records_read = fread(&file->header, sizeof(midi_header_t), 1, stream); + + if (records_read < 1) + { + return false; + } + + if (!CheckChunkHeader(&file->header.chunk_header, HEADER_CHUNK_ID) + || SDL_SwapBE32(file->header.chunk_header.chunk_size) != 6) + { + fprintf(stderr, "ReadFileHeader: Invalid MIDI chunk header! " + "chunk_size=%i\n", + SDL_SwapBE32(file->header.chunk_header.chunk_size)); + return false; + } + + format_type = SDL_SwapBE16(file->header.format_type); + file->num_tracks = SDL_SwapBE16(file->header.num_tracks); + + if ((format_type != 0 && format_type != 1) + || file->num_tracks < 1) + { + fprintf(stderr, "ReadFileHeader: Only type 0/1 " + "MIDI files supported!\n"); + return false; + } + + return true; +} + +void MIDI_FreeFile(midi_file_t *file) +{ + int i; + + if (file->tracks != NULL) + { + for (i=0; inum_tracks; ++i) + { + FreeTrack(&file->tracks[i]); + } + + free(file->tracks); + } + + free(file); +} + +midi_file_t *MIDI_LoadFile(char *filename) +{ + midi_file_t *file; + FILE *stream; + + file = malloc(sizeof(midi_file_t)); + + if (file == NULL) + { + return NULL; + } + + file->tracks = NULL; + file->num_tracks = 0; + file->buffer = NULL; + file->buffer_size = 0; + + // Open file + + stream = M_fopen(filename, "rb"); + + if (stream == NULL) + { + fprintf(stderr, "MIDI_LoadFile: Failed to open '%s'\n", filename); + MIDI_FreeFile(file); + return NULL; + } + + // Read MIDI file header + + if (!ReadFileHeader(file, stream)) + { + fclose(stream); + MIDI_FreeFile(file); + return NULL; + } + + // Read all tracks: + + if (!ReadAllTracks(file, stream)) + { + fclose(stream); + MIDI_FreeFile(file); + return NULL; + } + + fclose(stream); + + return file; +} + +// Get the number of tracks in a MIDI file. + +unsigned int MIDI_NumTracks(midi_file_t *file) +{ + return file->num_tracks; +} + +// Start iterating over the events in a track. + +midi_track_iter_t *MIDI_IterateTrack(midi_file_t *file, unsigned int track) +{ + midi_track_iter_t *iter; + + assert(track < file->num_tracks); + + iter = malloc(sizeof(*iter)); + iter->track = &file->tracks[track]; + iter->position = 0; + iter->loop_point = 0; + + return iter; +} + +void MIDI_FreeIterator(midi_track_iter_t *iter) +{ + free(iter); +} + +// Get the time until the next MIDI event in a track. + +unsigned int MIDI_GetDeltaTime(midi_track_iter_t *iter) +{ + if (iter->position < iter->track->num_events) + { + midi_event_t *next_event; + + next_event = &iter->track->events[iter->position]; + + return next_event->delta_time; + } + else + { + return 0; + } +} + +// Get a pointer to the next MIDI event. + +int MIDI_GetNextEvent(midi_track_iter_t *iter, midi_event_t **event) +{ + if (iter->position < iter->track->num_events) + { + *event = &iter->track->events[iter->position]; + ++iter->position; + + return 1; + } + else + { + return 0; + } +} + +unsigned int MIDI_GetFileTimeDivision(midi_file_t *file) +{ + short result = SDL_SwapBE16(file->header.time_division); + + // Negative time division indicates SMPTE time and must be handled + // differently. + if (result < 0) + { + return (signed int)(-(result/256)) + * (signed int)(result & 0xFF); + } + else + { + return result; + } +} + +void MIDI_RestartIterator(midi_track_iter_t *iter) +{ + iter->position = 0; + iter->loop_point = 0; +} + +void MIDI_SetLoopPoint(midi_track_iter_t *iter) +{ + iter->loop_point = iter->position; +} + +void MIDI_RestartAtLoopPoint(midi_track_iter_t *iter) +{ + iter->position = iter->loop_point; +} + +#ifdef TEST + +static char *MIDI_EventTypeToString(midi_event_type_t event_type) +{ + switch (event_type) + { + case MIDI_EVENT_NOTE_OFF: + return "MIDI_EVENT_NOTE_OFF"; + case MIDI_EVENT_NOTE_ON: + return "MIDI_EVENT_NOTE_ON"; + case MIDI_EVENT_AFTERTOUCH: + return "MIDI_EVENT_AFTERTOUCH"; + case MIDI_EVENT_CONTROLLER: + return "MIDI_EVENT_CONTROLLER"; + case MIDI_EVENT_PROGRAM_CHANGE: + return "MIDI_EVENT_PROGRAM_CHANGE"; + case MIDI_EVENT_CHAN_AFTERTOUCH: + return "MIDI_EVENT_CHAN_AFTERTOUCH"; + case MIDI_EVENT_PITCH_BEND: + return "MIDI_EVENT_PITCH_BEND"; + case MIDI_EVENT_SYSEX: + return "MIDI_EVENT_SYSEX"; + case MIDI_EVENT_SYSEX_SPLIT: + return "MIDI_EVENT_SYSEX_SPLIT"; + case MIDI_EVENT_META: + return "MIDI_EVENT_META"; + + default: + return "(unknown)"; + } +} + +void PrintTrack(midi_track_t *track) +{ + midi_event_t *event; + unsigned int i; + + for (i=0; inum_events; ++i) + { + event = &track->events[i]; + + if (event->delta_time > 0) + { + printf("Delay: %u ticks\n", event->delta_time); + } + + printf("Event type: %s (%i)\n", + MIDI_EventTypeToString(event->event_type), + event->event_type); + + switch(event->event_type) + { + case MIDI_EVENT_NOTE_OFF: + case MIDI_EVENT_NOTE_ON: + case MIDI_EVENT_AFTERTOUCH: + case MIDI_EVENT_CONTROLLER: + case MIDI_EVENT_PROGRAM_CHANGE: + case MIDI_EVENT_CHAN_AFTERTOUCH: + case MIDI_EVENT_PITCH_BEND: + printf("\tChannel: %u\n", event->data.channel.channel); + printf("\tParameter 1: %u\n", event->data.channel.param1); + printf("\tParameter 2: %u\n", event->data.channel.param2); + break; + + case MIDI_EVENT_SYSEX: + case MIDI_EVENT_SYSEX_SPLIT: + printf("\tLength: %u\n", event->data.sysex.length); + break; + + case MIDI_EVENT_META: + printf("\tMeta type: %u\n", event->data.meta.type); + printf("\tLength: %u\n", event->data.meta.length); + break; + } + } +} + +int main(int argc, char *argv[]) +{ + midi_file_t *file; + unsigned int i; + + if (argc < 2) + { + printf("Usage: %s \n", argv[0]); + exit(1); + } + + file = MIDI_LoadFile(argv[1]); + + if (file == NULL) + { + fprintf(stderr, "Failed to open %s\n", argv[1]); + exit(1); + } + + for (i=0; inum_tracks; ++i) + { + printf("\n== Track %u ==\n\n", i); + + PrintTrack(&file->tracks[i]); + } + + return 0; +} + +#endif + diff --git a/games/NXDoom/src/midifile.h b/games/NXDoom/src/midifile.h new file mode 100644 index 00000000000..035d6f8aa75 --- /dev/null +++ b/games/NXDoom/src/midifile.h @@ -0,0 +1,232 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// MIDI file parsing. +// + +#ifndef MIDIFILE_H +#define MIDIFILE_H + +typedef struct midi_file_s midi_file_t; +typedef struct midi_track_iter_s midi_track_iter_t; + +#define MIDI_CHANNELS_PER_TRACK 16 + +#define MIDI_RPN_MSB 0x00 +#define MIDI_RPN_PITCH_BEND_SENS_LSB 0x00 +#define MIDI_RPN_FINE_TUNING_LSB 0x01 +#define MIDI_RPN_COARSE_TUNING_LSB 0x02 +#define MIDI_RPN_NULL 0x7F + +typedef enum +{ + MIDI_EVENT_NOTE_OFF = 0x80, + MIDI_EVENT_NOTE_ON = 0x90, + MIDI_EVENT_AFTERTOUCH = 0xA0, + MIDI_EVENT_CONTROLLER = 0xB0, + MIDI_EVENT_PROGRAM_CHANGE = 0xC0, + MIDI_EVENT_CHAN_AFTERTOUCH = 0xD0, + MIDI_EVENT_PITCH_BEND = 0xE0, + + MIDI_EVENT_SYSEX = 0xF0, + MIDI_EVENT_SYSEX_SPLIT = 0xF7, + MIDI_EVENT_META = 0xFF, +} midi_event_type_t; + +typedef enum +{ + MIDI_CONTROLLER_BANK_SELECT_MSB = 0x00, + MIDI_CONTROLLER_MODULATION = 0x01, + MIDI_CONTROLLER_BREATH_CONTROL = 0x02, + MIDI_CONTROLLER_FOOT_CONTROL = 0x04, + MIDI_CONTROLLER_PORTAMENTO = 0x05, + MIDI_CONTROLLER_DATA_ENTRY_MSB = 0x06, + MIDI_CONTROLLER_VOLUME_MSB = 0x07, + MIDI_CONTROLLER_PAN = 0x0A, + MIDI_CONTROLLER_EXPRESSION = 0x0B, + + MIDI_CONTROLLER_BANK_SELECT_LSB = 0x20, + MIDI_CONTROLLER_DATA_ENTRY_LSB = 0x26, + MIDI_CONTROLLER_VOLUME_LSB = 0X27, + + MIDI_CONTROLLER_HOLD1_PEDAL = 0x40, + MIDI_CONTROLLER_SOFT_PEDAL = 0x43, + + MIDI_CONTROLLER_REVERB = 0x5B, + MIDI_CONTROLLER_CHORUS = 0x5D, + + MIDI_CONTROLLER_NRPN_LSB = 0x62, + MIDI_CONTROLLER_NRPN_MSB = 0x63, + MIDI_CONTROLLER_RPN_LSB = 0x64, + MIDI_CONTROLLER_RPN_MSB = 0x65, + + MIDI_CONTROLLER_ALL_SOUND_OFF = 0x78, + MIDI_CONTROLLER_RESET_ALL_CTRLS = 0x79, + MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B, + + MIDI_CONTROLLER_POLY_MODE_OFF = 0x7E, + MIDI_CONTROLLER_POLY_MODE_ON = 0x7F, +} midi_controller_t; + +typedef enum +{ + MIDI_META_SEQUENCE_NUMBER = 0x00, + + MIDI_META_TEXT = 0x01, + MIDI_META_COPYRIGHT = 0x02, + MIDI_META_TRACK_NAME = 0x03, + MIDI_META_INSTR_NAME = 0x04, + MIDI_META_LYRICS = 0x05, + MIDI_META_MARKER = 0x06, + MIDI_META_CUE_POINT = 0x07, + + MIDI_META_CHANNEL_PREFIX = 0x20, + MIDI_META_END_OF_TRACK = 0x2F, + + MIDI_META_SET_TEMPO = 0x51, + MIDI_META_SMPTE_OFFSET = 0x54, + MIDI_META_TIME_SIGNATURE = 0x58, + MIDI_META_KEY_SIGNATURE = 0x59, + MIDI_META_SEQUENCER_SPECIFIC = 0x7F, +} midi_meta_event_type_t; + +#define EMIDI_LOOP_FLAG 0x7F + +typedef enum +{ + EMIDI_DEVICE_GENERAL_MIDI = 0x00, + EMIDI_DEVICE_SOUND_CANVAS = 0x01, + EMIDI_DEVICE_AWE32 = 0x02, + EMIDI_DEVICE_WAVE_BLASTER = 0x03, + EMIDI_DEVICE_SOUND_BLASTER = 0x04, + EMIDI_DEVICE_PRO_AUDIO = 0x05, + EMIDI_DEVICE_SOUND_MAN_16 = 0x06, + EMIDI_DEVICE_ADLIB = 0x07, + EMIDI_DEVICE_SOUNDSCAPE = 0x08, + EMIDI_DEVICE_ULTRASOUND = 0x09, + EMIDI_DEVICE_ALL = 0x7F, +} emidi_device_t; + +typedef enum +{ + EMIDI_CONTROLLER_TRACK_DESIGNATION = 0x6E, + EMIDI_CONTROLLER_TRACK_EXCLUSION = 0x6F, + EMIDI_CONTROLLER_PROGRAM_CHANGE = 0x70, + EMIDI_CONTROLLER_VOLUME = 0x71, + EMIDI_CONTROLLER_LOOP_BEGIN = 0x74, + EMIDI_CONTROLLER_LOOP_END = 0x75, + EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN = 0x76, + EMIDI_CONTROLLER_GLOBAL_LOOP_END = 0x77, +} emidi_controller_t; + +typedef struct +{ + // Meta event type: + + unsigned int type; + + // Length: + + unsigned int length; + + // Meta event data: + + byte *data; +} midi_meta_event_data_t; + +typedef struct +{ + // Length: + + unsigned int length; + + // Event data: + + byte *data; +} midi_sysex_event_data_t; + +typedef struct +{ + // The channel number to which this applies: + + unsigned int channel; + + // Extra parameters: + + unsigned int param1; + unsigned int param2; +} midi_channel_event_data_t; + +typedef struct +{ + // Time between the previous event and this event. + unsigned int delta_time; + + // Type of event: + midi_event_type_t event_type; + + union + { + midi_channel_event_data_t channel; + midi_meta_event_data_t meta; + midi_sysex_event_data_t sysex; + } data; +} midi_event_t; + +// Load a MIDI file. + +midi_file_t *MIDI_LoadFile(char *filename); + +// Free a MIDI file. + +void MIDI_FreeFile(midi_file_t *file); + +// Get the time division value from the MIDI header. + +unsigned int MIDI_GetFileTimeDivision(midi_file_t *file); + +// Get the number of tracks in a MIDI file. + +unsigned int MIDI_NumTracks(midi_file_t *file); + +// Start iterating over the events in a track. + +midi_track_iter_t *MIDI_IterateTrack(midi_file_t *file, unsigned int track_num); + +// Free an iterator. + +void MIDI_FreeIterator(midi_track_iter_t *iter); + +// Get the time until the next MIDI event in a track. + +unsigned int MIDI_GetDeltaTime(midi_track_iter_t *iter); + +// Get a pointer to the next MIDI event. + +int MIDI_GetNextEvent(midi_track_iter_t *iter, midi_event_t **event); + +// Reset an iterator to the beginning of a track. + +void MIDI_RestartIterator(midi_track_iter_t *iter); + +// Set loop point to current position. + +void MIDI_SetLoopPoint(midi_track_iter_t *iter); + +// Set position to saved loop point. + +void MIDI_RestartAtLoopPoint(midi_track_iter_t *iter); + +#endif /* #ifndef MIDIFILE_H */ + diff --git a/games/NXDoom/src/mus2mid.c b/games/NXDoom/src/mus2mid.c new file mode 100644 index 00000000000..f81f939f22f --- /dev/null +++ b/games/NXDoom/src/mus2mid.c @@ -0,0 +1,736 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// Copyright(C) 2006 Ben Ryves 2006 +// +// 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. +// +// mus2mid.c - Ben Ryves 2006 - http://benryves.com - benryves@benryves.com +// Use to convert a MUS file into a single track, type 0 MIDI file. + +#include +#include + +#include "doomtype.h" +#include "i_swap.h" + +#include "memio.h" +#include "mus2mid.h" + +#define NUM_CHANNELS 16 + +#define MIDI_PERCUSSION_CHAN 9 +#define MUS_PERCUSSION_CHAN 15 + +// MUS event codes +typedef enum +{ + mus_releasekey = 0x00, + mus_presskey = 0x10, + mus_pitchwheel = 0x20, + mus_systemevent = 0x30, + mus_changecontroller = 0x40, + mus_scoreend = 0x60 +} musevent; + +// MIDI event codes +typedef enum +{ + midi_releasekey = 0x80, + midi_presskey = 0x90, + midi_aftertouchkey = 0xA0, + midi_changecontroller = 0xB0, + midi_changepatch = 0xC0, + midi_aftertouchchannel = 0xD0, + midi_pitchwheel = 0xE0 +} midievent; + +// Structure to hold MUS file header +typedef PACKED_STRUCT ( +{ + byte id[4]; + unsigned short scorelength; + unsigned short scorestart; + unsigned short primarychannels; + unsigned short secondarychannels; + unsigned short instrumentcount; +}) musheader; + +// Standard MIDI type 0 header + track header +static const byte midiheader[] = +{ + 'M', 'T', 'h', 'd', // Main header + 0x00, 0x00, 0x00, 0x06, // Header size + 0x00, 0x00, // MIDI type (0) + 0x00, 0x01, // Number of tracks + 0x00, 0x46, // Resolution + 'M', 'T', 'r', 'k', // Start of track + 0x00, 0x00, 0x00, 0x00 // Placeholder for track length +}; + +// Cached channel velocities +static byte channelvelocities[] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127 +}; + +// Timestamps between sequences of MUS events + +static unsigned int queuedtime = 0; + +// Counter for the length of the track + +static unsigned int tracksize; + +static const byte controller_map[] = +{ + 0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D, + 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79 +}; + +static int channel_map[NUM_CHANNELS]; + +// Write timestamp to a MIDI file. + +static boolean WriteTime(unsigned int time, MEMFILE *midioutput) +{ + unsigned int buffer = time & 0x7F; + byte writeval; + + while ((time >>= 7) != 0) + { + buffer <<= 8; + buffer |= ((time & 0x7F) | 0x80); + } + + for (;;) + { + writeval = (byte)(buffer & 0xFF); + + if (mem_fwrite(&writeval, 1, 1, midioutput) != 1) + { + return true; + } + + ++tracksize; + + if ((buffer & 0x80) != 0) + { + buffer >>= 8; + } + else + { + queuedtime = 0; + return false; + } + } +} + + +// Write the end of track marker +static boolean WriteEndTrack(MEMFILE *midioutput) +{ + byte endtrack[] = {0xFF, 0x2F, 0x00}; + + if (WriteTime(queuedtime, midioutput)) + { + return true; + } + + if (mem_fwrite(endtrack, 1, 3, midioutput) != 3) + { + return true; + } + + tracksize += 3; + return false; +} + +// Write a key press event +static boolean WritePressKey(byte channel, byte key, + byte velocity, MEMFILE *midioutput) +{ + byte working = midi_presskey | channel; + + if (WriteTime(queuedtime, midioutput)) + { + return true; + } + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = key & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = velocity & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + tracksize += 3; + + return false; +} + +// Write a key release event +static boolean WriteReleaseKey(byte channel, byte key, + MEMFILE *midioutput) +{ + byte working = midi_releasekey | channel; + + if (WriteTime(queuedtime, midioutput)) + { + return true; + } + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = key & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = 0; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + tracksize += 3; + + return false; +} + +// Write a pitch wheel/bend event +static boolean WritePitchWheel(byte channel, short wheel, + MEMFILE *midioutput) +{ + byte working = midi_pitchwheel | channel; + + if (WriteTime(queuedtime, midioutput)) + { + return true; + } + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = wheel & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = (wheel >> 7) & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + tracksize += 3; + return false; +} + +// Write a patch change event +static boolean WriteChangePatch(byte channel, byte patch, + MEMFILE *midioutput) +{ + byte working = midi_changepatch | channel; + + if (WriteTime(queuedtime, midioutput)) + { + return true; + } + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = patch & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + tracksize += 2; + + return false; +} + +// Write a valued controller change event + +static boolean WriteChangeController_Valued(byte channel, + byte control, + byte value, + MEMFILE *midioutput) +{ + byte working = midi_changecontroller | channel; + + if (WriteTime(queuedtime, midioutput)) + { + return true; + } + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + working = control & 0x7F; + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + // Quirk in vanilla DOOM? MUS controller values should be + // 7-bit, not 8-bit. + + working = value;// & 0x7F; + + // Fix on said quirk to stop MIDI players from complaining that + // the value is out of range: + + if (working & 0x80) + { + working = 0x7F; + } + + if (mem_fwrite(&working, 1, 1, midioutput) != 1) + { + return true; + } + + tracksize += 3; + + return false; +} + +// Write a valueless controller change event +static boolean WriteChangeController_Valueless(byte channel, + byte control, + MEMFILE *midioutput) +{ + return WriteChangeController_Valued(channel, control, 0, + midioutput); +} + +// Allocate a free MIDI channel. + +static int AllocateMIDIChannel(void) +{ + int result; + int max; + int i; + + // Find the current highest-allocated channel. + + max = -1; + + for (i=0; i max) + { + max = channel_map[i]; + } + } + + // max is now equal to the highest-allocated MIDI channel. We can + // now allocate the next available channel. This also works if + // no channels are currently allocated (max=-1) + + result = max + 1; + + // Don't allocate the MIDI percussion channel! + + if (result == MIDI_PERCUSSION_CHAN) + { + ++result; + } + + return result; +} + +// Given a MUS channel number, get the MIDI channel number to use +// in the outputted file. + +static int GetMIDIChannel(int mus_channel, MEMFILE *midioutput) +{ + // Find the MIDI channel to use for this MUS channel. + // MUS channel 15 is the percusssion channel. + + if (mus_channel == MUS_PERCUSSION_CHAN) + { + return MIDI_PERCUSSION_CHAN; + } + else + { + // If a MIDI channel hasn't been allocated for this MUS channel + // yet, allocate the next free MIDI channel. + + if (channel_map[mus_channel] == -1) + { + channel_map[mus_channel] = AllocateMIDIChannel(); + + // First time using the channel, send an "all notes off" + // event. This fixes "The D_DDTBLU disease" described here: + // https://www.doomworld.com/vb/source-ports/66802-the + WriteChangeController_Valueless(channel_map[mus_channel], 0x7b, + midioutput); + } + + return channel_map[mus_channel]; + } +} + +static boolean ReadMusHeader(MEMFILE *file, musheader *header) +{ + boolean result; + + result = mem_fread(&header->id, sizeof(byte), 4, file) == 4 + && mem_fread(&header->scorelength, sizeof(short), 1, file) == 1 + && mem_fread(&header->scorestart, sizeof(short), 1, file) == 1 + && mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1 + && mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1 + && mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1; + + if (result) + { + header->scorelength = SHORT(header->scorelength); + header->scorestart = SHORT(header->scorestart); + header->primarychannels = SHORT(header->primarychannels); + header->secondarychannels = SHORT(header->secondarychannels); + header->instrumentcount = SHORT(header->instrumentcount); + } + + return result; +} + + +// Read a MUS file from a stream (musinput) and output a MIDI file to +// a stream (midioutput). +// +// Returns 0 on success or 1 on failure. + +boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput) +{ + // Header for the MUS file + musheader musfileheader; + + // Descriptor for the current MUS event + byte eventdescriptor; + int channel; // Channel number + musevent event; + + + // Bunch of vars read from MUS lump + byte key; + byte controllernumber; + byte controllervalue; + + // Buffer used for MIDI track size record + byte tracksizebuffer[4]; + + // Flag for when the score end marker is hit. + int hitscoreend = 0; + + // Temp working byte + byte working; + // Used in building up time delays + unsigned int timedelay; + + // Initialise channel map to mark all channels as unused. + + for (channel=0; channel 14) + { + return true; + } + + if (WriteChangeController_Valueless(channel, + controller_map[controllernumber], + midioutput)) + { + return true; + } + + break; + + case mus_changecontroller: + if (mem_fread(&controllernumber, 1, 1, musinput) != 1) + { + return true; + } + + if (mem_fread(&controllervalue, 1, 1, musinput) != 1) + { + return true; + } + + if (controllernumber == 0) + { + if (WriteChangePatch(channel, controllervalue, + midioutput)) + { + return true; + } + } + else + { + if (controllernumber < 1 || controllernumber > 9) + { + return true; + } + + if (WriteChangeController_Valued(channel, + controller_map[controllernumber], + controllervalue, + midioutput)) + { + return true; + } + } + + break; + + case mus_scoreend: + hitscoreend = 1; + break; + + default: + return true; + break; + } + + if (eventdescriptor & 0x80) + { + break; + } + } + // Now we need to read the time code: + if (!hitscoreend) + { + timedelay = 0; + for (;;) + { + if (mem_fread(&working, 1, 1, musinput) != 1) + { + return true; + } + + timedelay = timedelay * 128 + (working & 0x7F); + if ((working & 0x80) == 0) + { + break; + } + } + queuedtime += timedelay; + } + } + + // End of track + if (WriteEndTrack(midioutput)) + { + return true; + } + + // Write the track size into the stream + if (mem_fseek(midioutput, 18, MEM_SEEK_SET)) + { + return true; + } + + tracksizebuffer[0] = (tracksize >> 24) & 0xff; + tracksizebuffer[1] = (tracksize >> 16) & 0xff; + tracksizebuffer[2] = (tracksize >> 8) & 0xff; + tracksizebuffer[3] = tracksize & 0xff; + + if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4) + { + return true; + } + + return false; +} + +#ifdef STANDALONE + +#include "m_misc.h" +#include "z_zone.h" + +int main(int argc, char *argv[]) +{ + MEMFILE *src, *dst; + byte *infile; + long infile_len; + void *outfile; + size_t outfile_len; + + if (argc != 3) + { + printf("Usage: %s \n", argv[0]); + exit(-1); + } + + Z_Init(); + + infile_len = M_ReadFile(argv[1], &infile); + + src = mem_fopen_read(infile, infile_len); + dst = mem_fopen_write(); + + if (mus2mid(src, dst)) + { + fprintf(stderr, "mus2mid() failed\n"); + exit(-1); + } + + // Write result to output file: + + mem_get_buf(dst, &outfile, &outfile_len); + + M_WriteFile(argv[2], outfile, outfile_len); + + return 0; +} + +#endif + diff --git a/games/NXDoom/src/mus2mid.h b/games/NXDoom/src/mus2mid.h new file mode 100644 index 00000000000..324025a2c53 --- /dev/null +++ b/games/NXDoom/src/mus2mid.h @@ -0,0 +1,29 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// Copyright(C) 2006 Ben Ryves 2006 +// +// 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. +// +// +// mus2mid.h - Ben Ryves 2006 - http://benryves.com - benryves@benryves.com +// Use to convert a MUS file into a single track, type 0 MIDI file. + +#ifndef MUS2MID_H +#define MUS2MID_H + +#include "doomtype.h" +#include "memio.h" + +boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput); + +#endif /* #ifndef MUS2MID_H */ + diff --git a/games/NXDoom/src/net_client.c b/games/NXDoom/src/net_client.c new file mode 100644 index 00000000000..19b720fa6a4 --- /dev/null +++ b/games/NXDoom/src/net_client.c @@ -0,0 +1,1229 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Network client code +// + +#include +#include +#include +#include + +#include "config.h" +#include "doomtype.h" +#include "deh_main.h" +#include "deh_str.h" +#include "d_loop.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_argv.h" +#include "m_fixed.h" +#include "m_config.h" +#include "m_misc.h" +#include "net_client.h" +#include "net_common.h" +#include "net_defs.h" +#include "net_gui.h" +#include "net_io.h" +#include "net_packet.h" +#include "net_query.h" +#include "net_server.h" +#include "net_structrw.h" +#include "net_petname.h" +#include "w_checksum.h" +#include "w_wad.h" + + +typedef enum +{ + // waiting for the game to launch + + CLIENT_STATE_WAITING_LAUNCH, + + // waiting for the game to start + + CLIENT_STATE_WAITING_START, + + // in game + + CLIENT_STATE_IN_GAME, + +} net_clientstate_t; + +// Type of structure used in the receive window + +typedef struct +{ + // Whether this tic has been received yet + + boolean active; + + // Last time we sent a resend request for this tic + + unsigned int resend_time; + + // Tic data from server + + net_full_ticcmd_t cmd; + +} net_server_recv_t; + +// Type of structure used in the send window + +typedef struct +{ + // Whether this slot is active yet + + boolean active; + + // The tic number + + unsigned int seq; + + // Time the command was generated + + unsigned int time; + + // Ticcmd diff + + net_ticdiff_t cmd; +} net_server_send_t; + + +static net_connection_t client_connection; +static net_clientstate_t client_state; +static net_addr_t *server_addr; +static net_context_t *client_context; + +// game settings, as received from the server when the game started + +static net_gamesettings_t settings; + +// Why did the server reject us? +char *net_client_reject_reason = NULL; + +// true if the client code is in use + +boolean net_client_connected; + +// true if we have received waiting data from the server, +// and the wait data that was received. + +boolean net_client_received_wait_data; +net_waitdata_t net_client_wait_data; + +// Waiting at the initial wait screen for the game to be launched? + +boolean net_waiting_for_launch = false; + +// Name that we send to the server + +char *net_player_name = NULL; + +// Connected but not participating in the game (observer) + +boolean drone = false; + +// The last ticcmd constructed + +static ticcmd_t last_ticcmd; + +// Buffer of ticcmd diffs being sent to the server + +static net_server_send_t send_queue[BACKUPTICS]; + +// Receive window + +static ticcmd_t recvwindow_cmd_base[NET_MAXPLAYERS]; +static int recvwindow_start; +static net_server_recv_t recvwindow[BACKUPTICS]; + +// Whether we need to send an acknowledgement and +// when gamedata was last received. + +static boolean need_to_acknowledge; +static unsigned int gamedata_recv_time; + +// The latency (time between when we sent our command and we got all +// the other players' commands from the server) for the last tic we +// received. We include this latency in tics we send to the server so +// that they can adjust to us. +static int last_latency; + +// Hash checksums of our wad directory and dehacked data. + +sha1_digest_t net_local_wad_sha1sum; +sha1_digest_t net_local_deh_sha1sum; + +// Are we playing with the freedoom IWAD? + +unsigned int net_local_is_freedoom; + +#define NET_CL_ExpandTicNum(b) NET_ExpandTicNum(recvwindow_start, (b)) + +// Called when we become disconnected from the server + +static void NET_CL_Disconnected(void) +{ + D_ReceiveTic(NULL, NULL); +} + +// Called when a packet is received from the server containing game +// data. This updates the clock synchronization variable (offsetms) +// using a PID filter that keeps client clocks in sync. +static void UpdateClockSync(unsigned int seq, + unsigned int remote_latency) +{ + static int last_error, cumul_error; + int latency, error; + + if (seq == send_queue[seq % BACKUPTICS].seq) + { + latency = I_GetTimeMS() - send_queue[seq % BACKUPTICS].time; + } + else if (seq > send_queue[seq % BACKUPTICS].seq) + { + // We have received the ticcmd from the server before we have + // even sent ours + + latency = 0; + } + else + { + return; + } + + // PID filter. These are manually trained parameters. +#define KP 0.1 +#define KI 0.01 +#define KD 0.02 + + // How does our latency compare to the worst other player? + error = latency - remote_latency; + cumul_error += error; + + offsetms = KP * (FRACUNIT * error) + - KI * (FRACUNIT * cumul_error) + + (KD * FRACUNIT) * (last_error - error); + + last_error = error; + last_latency = latency; + + NET_Log("client: latency %d, remote %d -> offset=%dms, cumul_error=%d", + latency, remote_latency, offsetms / FRACUNIT, cumul_error); +} + +// Expand a net_full_ticcmd_t, applying the diffs in cmd->cmds as +// patches against recvwindow_cmd_base. Place the results into +// the d_net.c structures (netcmds/nettics) and save the new ticcmd +// back into recvwindow_cmd_base. + +static void NET_CL_ExpandFullTiccmd(net_full_ticcmd_t *cmd, unsigned int seq, + ticcmd_t *ticcmds) +{ + int i; + + // Expand tic diffs for all players + + for (i=0; iplayeringame[i]) + { + net_ticdiff_t *diff; + + diff = &cmd->cmds[i]; + + // Use the ticcmd diff to patch the previous ticcmd to + // the new ticcmd + + NET_TiccmdPatch(&recvwindow_cmd_base[i], diff, &ticcmds[i]); + + // Store a copy for next time + + recvwindow_cmd_base[i] = ticcmds[i]; + } + } +} + +// Advance the receive window + +static void NET_CL_AdvanceWindow(void) +{ + ticcmd_t ticcmds[NET_MAXPLAYERS]; + + while (recvwindow[0].active) + { + // Expand tic diff data into d_net.c structures + + NET_CL_ExpandFullTiccmd(&recvwindow[0].cmd, recvwindow_start, + ticcmds); + D_ReceiveTic(ticcmds, recvwindow[0].cmd.playeringame); + + // Advance the window + + memmove(recvwindow, recvwindow + 1, + sizeof(net_server_recv_t) * (BACKUPTICS - 1)); + memset(&recvwindow[BACKUPTICS-1], 0, sizeof(net_server_recv_t)); + + ++recvwindow_start; + + NET_Log("client: advanced receive window to %d", recvwindow_start); + } +} + +// Shut down the client code, etc. Invoked after a disconnect. + +static void NET_CL_Shutdown(void) +{ + if (net_client_connected) + { + net_client_connected = false; + + NET_ReleaseAddress(server_addr); + + // Shut down network module, etc. To do. + } +} + +void NET_CL_LaunchGame(void) +{ + NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_LAUNCH); +} + +void NET_CL_StartGame(net_gamesettings_t *settings) +{ + net_packet_t *packet; + + // Start from a ticcmd of all zeros + + memset(&last_ticcmd, 0, sizeof(ticcmd_t)); + + // Send packet + + packet = NET_Conn_NewReliable(&client_connection, + NET_PACKET_TYPE_GAMESTART); + + NET_WriteSettings(packet, settings); +} + +static void NET_CL_SendGameDataACK(void) +{ + net_packet_t *packet; + + packet = NET_NewPacket(10); + + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_ACK); + NET_WriteInt8(packet, recvwindow_start & 0xff); + + NET_Conn_SendPacket(&client_connection, packet); + + NET_FreePacket(packet); + + need_to_acknowledge = false; +} + +static void NET_CL_SendTics(int start, int end) +{ + net_packet_t *packet; + int i; + + if (!net_client_connected) + { + // Disconnected from server + + return; + } + + if (start < 0) + start = 0; + + // Build a new packet to send to the server + + packet = NET_NewPacket(512); + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); + + // Write the start tic and number of tics. Send only the low byte + // of start - it can be inferred by the server. + + NET_WriteInt8(packet, recvwindow_start & 0xff); + NET_WriteInt8(packet, start & 0xff); + NET_WriteInt8(packet, end - start + 1); + + // Add the tics. + + for (i=start; i<=end; ++i) + { + net_server_send_t *sendobj; + + sendobj = &send_queue[i % BACKUPTICS]; + + NET_WriteInt16(packet, last_latency); + + NET_WriteTiccmdDiff(packet, &sendobj->cmd, settings.lowres_turn); + } + + // Send the packet + + NET_Conn_SendPacket(&client_connection, packet); + + // All done! + + NET_FreePacket(packet); + + // Acknowledgement has been sent as part of the packet + + need_to_acknowledge = false; +} + +// Add a new ticcmd to the send queue + +void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic) +{ + net_ticdiff_t diff; + net_server_send_t *sendobj; + int starttic, endtic; + + // Calculate the difference to the last ticcmd + + NET_TiccmdDiff(&last_ticcmd, ticcmd, &diff); + + // Store in the send queue + + sendobj = &send_queue[maketic % BACKUPTICS]; + sendobj->active = true; + sendobj->seq = maketic; + sendobj->time = I_GetTimeMS(); + sendobj->cmd = diff; + + last_ticcmd = *ticcmd; + + // Send to server. + + starttic = maketic - settings.extratics; + endtic = maketic; + + if (starttic < 0) + starttic = 0; + + NET_Log("client: generated tic %d, sending %d-%d", + maketic, starttic, endtic); + NET_CL_SendTics(starttic, endtic); +} + +// Parse a SYN packet received back from the server indicating a successful +// connection attempt. +static void NET_CL_ParseSYN(net_packet_t *packet) +{ + net_protocol_t protocol; + char *server_version; + + NET_Log("client: processing SYN response"); + + server_version = NET_ReadSafeString(packet); + if (server_version == NULL) + { + NET_Log("client: error: failed to read server version"); + return; + } + + protocol = NET_ReadProtocol(packet); + if (protocol == NET_PROTOCOL_UNKNOWN) + { + NET_Log("client: error: can't find a common protocol"); + return; + } + + // We are now successfully connected. + NET_Log("client: connected to server"); + client_connection.state = NET_CONN_STATE_CONNECTED; + client_connection.protocol = protocol; + + // Even though we have negotiated a compatible protocol, the game may still + // desync. Chocolate Doom's philosophy makes this unlikely, but if we're + // playing with a forked version, or even against a different version that + // fixes a compatibility issue, we may still have problems. + if (strcmp(server_version, PACKAGE_STRING) != 0) + { + fprintf(stderr, "NET_CL_ParseSYN: This is '%s', but the server is " + "'%s'. It is possible that this mismatch may cause the game " + "to desync.\n", PACKAGE_STRING, server_version); + } +} + +static void SetRejectReason(const char *s) +{ + free(net_client_reject_reason); + if (s != NULL) + { + net_client_reject_reason = strdup(s); + } + else + { + net_client_reject_reason = NULL; + } +} + +static void NET_CL_ParseReject(net_packet_t *packet) +{ + char *msg; + + msg = NET_ReadSafeString(packet); + if (msg == NULL) + { + return; + } + + if (client_connection.state == NET_CONN_STATE_CONNECTING) + { + client_connection.state = NET_CONN_STATE_DISCONNECTED; + client_connection.disconnect_reason = NET_DISCONNECT_REMOTE; + SetRejectReason(msg); + } +} + +// data received while we are waiting for the game to start + +static void NET_CL_ParseWaitingData(net_packet_t *packet) +{ + net_waitdata_t wait_data; + + if (!NET_ReadWaitData(packet, &wait_data)) + { + // Invalid packet? + return; + } + + if (wait_data.num_players > wait_data.max_players + || wait_data.ready_players > wait_data.num_players + || wait_data.max_players > NET_MAXPLAYERS) + { + // insane data + + return; + } + + if ((wait_data.consoleplayer >= 0 && drone) + || (wait_data.consoleplayer < 0 && !drone) + || (wait_data.consoleplayer >= wait_data.num_players)) + { + // Invalid player number + + return; + } + + memcpy(&net_client_wait_data, &wait_data, sizeof(net_waitdata_t)); + net_client_received_wait_data = true; +} + +static void NET_CL_ParseLaunch(net_packet_t *packet) +{ + unsigned int num_players; + + NET_Log("client: processing launch packet"); + + if (client_state != CLIENT_STATE_WAITING_LAUNCH) + { + NET_Log("client: error: not in waiting launch state, client_state=%d", + client_state); + return; + } + + // The launch packet contains the number of players that will be + // in the game when it starts, so that we can do the startup + // progress indicator (the wait data is unreliable). + + if (!NET_ReadInt8(packet, &num_players)) + { + NET_Log("client: error: failed to read number of players"); + return; + } + + net_client_wait_data.num_players = num_players; + client_state = CLIENT_STATE_WAITING_START; + NET_Log("client: now waiting for game start"); +} + +static void NET_CL_ParseGameStart(net_packet_t *packet) +{ + NET_Log("client: processing game start packet"); + + if (!NET_ReadSettings(packet, &settings)) + { + NET_Log("client: error: failed to read settings"); + return; + } + + if (client_state != CLIENT_STATE_WAITING_START) + { + NET_Log("client: error: not in waiting start state, client_state=%d", + client_state); + return; + } + + if (settings.num_players > NET_MAXPLAYERS + || settings.consoleplayer >= (signed int) settings.num_players) + { + // insane values + NET_Log("client: error: bad settings, num_players=%d, consoleplayer=%d", + settings.num_players, settings.consoleplayer); + return; + } + + if ((drone && settings.consoleplayer >= 0) + || (!drone && settings.consoleplayer < 0)) + { + // Invalid player number: must be positive for real players, + // negative for drones + NET_Log("client: error: mismatch: drone=%d, consoleplayer=%d", + drone, settings.consoleplayer); + return; + } + + NET_Log("client: beginning game state"); + client_state = CLIENT_STATE_IN_GAME; + + // Clear the receive window + + memset(recvwindow, 0, sizeof(recvwindow)); + recvwindow_start = 0; + memset(&recvwindow_cmd_base, 0, sizeof(recvwindow_cmd_base)); + + // Clear the send queue + + memset(&send_queue, 0x00, sizeof(send_queue)); +} + +static void NET_CL_SendResendRequest(int start, int end) +{ + net_packet_t *packet; + unsigned int nowtime; + int i; + + //printf("CL: Send resend %i-%i\n", start, end); + + packet = NET_NewPacket(64); + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); + NET_WriteInt32(packet, start); + NET_WriteInt8(packet, end - start + 1); + NET_Conn_SendPacket(&client_connection, packet); + NET_FreePacket(packet); + + nowtime = I_GetTimeMS(); + + // Save the time we sent the resend request + + for (i=start; i<=end; ++i) + { + int index; + + index = i - recvwindow_start; + + if (index < 0 || index >= BACKUPTICS) + continue; + + recvwindow[index].resend_time = nowtime; + } +} + +// Check for expired resend requests + +static void NET_CL_CheckResends(void) +{ + int i; + int resend_start, resend_end; + unsigned int nowtime; + boolean maybe_deadlocked; + + nowtime = I_GetTimeMS(); + maybe_deadlocked = nowtime - gamedata_recv_time > 1000; + + resend_start = -1; + resend_end = -1; + + for (i=0; iactive + && recvobj->resend_time != 0 + && nowtime > recvobj->resend_time + 300; + + // if no game data has been received in a long time, we may be in + // a deadlock scenario where tics from the server have been lost, so + // we've stopped generating any more, so the server isn't sending us + // any, so we don't get any to trigger a resend request. So force the + // first few tics in the receive window to be requested. + if (i == 0 && !recvobj->active && recvobj->resend_time == 0 + && maybe_deadlocked) + { + need_resend = true; + } + + if (need_resend) + { + // Start a new run of resend tics? + + if (resend_start < 0) + { + resend_start = i; + } + + resend_end = i; + } + else if (resend_start >= 0) + { + // End of a run of resend tics + NET_Log("client: resend request timed out for %d-%d (%d)", + recvwindow_start + resend_start, + recvwindow_start + resend_end, + recvwindow[resend_start].resend_time); + NET_CL_SendResendRequest(recvwindow_start + resend_start, + recvwindow_start + resend_end); + resend_start = -1; + } + } + + if (resend_start >= 0) + { + NET_Log("client: resend request timed out for %d-%d (%d)", + recvwindow_start + resend_start, + recvwindow_start + resend_end, + recvwindow[resend_start].resend_time); + NET_CL_SendResendRequest(recvwindow_start + resend_start, + recvwindow_start + resend_end); + } + + // We have received some data from the server and not acknowledged + // it yet. Normally this gets acknowledged when we send our game + // data, but if the client is a drone we need to do this. + + if (need_to_acknowledge && nowtime - gamedata_recv_time > 200) + { + NET_Log("client: no game data received since %d: triggering ack", + gamedata_recv_time); + NET_CL_SendGameDataACK(); + } +} + + +// Parsing of NET_PACKET_TYPE_GAMEDATA packets +// (packets containing the actual ticcmd data) + +static void NET_CL_ParseGameData(net_packet_t *packet) +{ + net_server_recv_t *recvobj; + unsigned int seq, num_tics; + unsigned int nowtime; + int resend_start, resend_end; + size_t i; + int index; + + NET_Log("client: processing game data packet"); + + // Read header + if (!NET_ReadInt8(packet, &seq) + || !NET_ReadInt8(packet, &num_tics)) + { + NET_Log("client: error: failed to read header"); + return; + } + + nowtime = I_GetTimeMS(); + + // Whatever happens, we now need to send an acknowledgement of our + // current receive point. + + if (!need_to_acknowledge) + { + need_to_acknowledge = true; + gamedata_recv_time = nowtime; + } + + // Expand byte value into the full tic number + seq = NET_CL_ExpandTicNum(seq); + NET_Log("client: got game data, seq=%d, num_tics=%d", seq, num_tics); + + for (i=0; i= BACKUPTICS) + { + // Out of range of the recv window + + continue; + } + + // Store in the receive window + + recvobj = &recvwindow[index]; + + recvobj->active = true; + recvobj->cmd = cmd; + NET_Log("client: stored tic %d in receive window", seq + i); + + // If a packet is lost or arrives out of order, we might get + // the tic in the next packet instead (because of extratic). + // If that's the case then the latency for receiving that tic + // now will be bogus. So we only use the last tic in the packet + // to trigger a clock sync update. + if (i == num_tics - 1) + { + UpdateClockSync(seq + i, cmd.latency); + } + } + + // Has this been received out of sequence, ie. have we not received + // all tics before the first tic in this packet? If so, send a + // resend request. + + //printf("CL: %p: %i\n", client, seq); + + resend_end = seq - recvwindow_start; + + if (resend_end <= 0) + return; + + if (resend_end >= BACKUPTICS) + resend_end = BACKUPTICS - 1; + + index = resend_end - 1; + resend_start = resend_end; + + while (index >= 0) + { + recvobj = &recvwindow[index]; + + if (recvobj->active) + { + // ended our run of unreceived tics + + break; + } + + if (recvobj->resend_time != 0) + { + // Already sent a resend request for this tic + + break; + } + + resend_start = index; + --index; + } + + // Possibly send a resend request + if (resend_start < resend_end) + { + NET_Log("client: request resend for %d-%d before %d", + recvwindow_start + resend_start, + recvwindow_start + resend_end - 1, seq); + NET_CL_SendResendRequest(recvwindow_start + resend_start, + recvwindow_start + resend_end - 1); + } +} + +// Parse a resend request from the server due to a dropped packet + +static void NET_CL_ParseResendRequest(net_packet_t *packet) +{ + static unsigned int start; + static unsigned int end; + static unsigned int num_tics; + + NET_Log("client: processing resend request"); + + if (drone) + { + // Drones don't send gamedata. + NET_Log("client: error: resend request but we're a drone?"); + return; + } + + if (!NET_ReadInt32(packet, &start) + || !NET_ReadInt8(packet, &num_tics)) + { + NET_Log("client: error: couldn't read start and num_tics"); + return; + } + + end = start + num_tics - 1; + + //printf("requested resend %i-%i .. ", start, end); + NET_Log("client: resend request: start=%d, num_tics=%d", start, num_tics); + + // Check we have the tics being requested. If not, reduce the + // window of tics to only what we have. + + while (start <= end + && (!send_queue[start % BACKUPTICS].active + || send_queue[start % BACKUPTICS].seq != start)) + { + ++start; + } + + while (start <= end + && (!send_queue[end % BACKUPTICS].active + || send_queue[end % BACKUPTICS].seq != end)) + { + --end; + } + + // Resend those tics + if (start <= end) + { + NET_Log("client: resending %d-%d", start, end); + NET_CL_SendTics(start, end); + } + else + { + NET_Log("client: don't have the tics to resend"); + } +} + +// Console message that the server wants the client to print + +static void NET_CL_ParseConsoleMessage(net_packet_t *packet) +{ + char *msg; + + msg = NET_ReadSafeString(packet); + + if (msg == NULL) + { + return; + } + + printf("Message from server:\n%s\n", msg); +} + +// parse a received packet + +static void NET_CL_ParsePacket(net_packet_t *packet) +{ + unsigned int packet_type; + + if (!NET_ReadInt16(packet, &packet_type)) + { + return; + } + + NET_Log("client: packet from server, type %d", + packet_type & ~NET_RELIABLE_PACKET); + NET_LogPacket(packet); + + if (NET_Conn_Packet(&client_connection, packet, &packet_type)) + { + // Packet eaten by the common connection code + } + else + { + switch (packet_type) + { + case NET_PACKET_TYPE_SYN: + NET_CL_ParseSYN(packet); + break; + + case NET_PACKET_TYPE_REJECTED: + NET_CL_ParseReject(packet); + break; + + case NET_PACKET_TYPE_WAITING_DATA: + NET_CL_ParseWaitingData(packet); + break; + + case NET_PACKET_TYPE_LAUNCH: + NET_CL_ParseLaunch(packet); + break; + + case NET_PACKET_TYPE_GAMESTART: + NET_CL_ParseGameStart(packet); + break; + + case NET_PACKET_TYPE_GAMEDATA: + NET_CL_ParseGameData(packet); + break; + + case NET_PACKET_TYPE_GAMEDATA_RESEND: + NET_CL_ParseResendRequest(packet); + break; + + case NET_PACKET_TYPE_CONSOLE_MESSAGE: + NET_CL_ParseConsoleMessage(packet); + break; + + default: + break; + } + } +} + +// "Run" the client code: check for new packets, send packets as +// needed + +void NET_CL_Run(void) +{ + net_addr_t *addr; + net_packet_t *packet; + + if (!net_client_connected) + { + return; + } + + while (NET_RecvPacket(client_context, &addr, &packet)) + { + // only accept packets from the server + + if (addr == server_addr) + { + NET_CL_ParsePacket(packet); + } + + NET_FreePacket(packet); + NET_ReleaseAddress(addr); + } + + // Run the common connection code to send any packets as needed + + NET_Conn_Run(&client_connection); + + if (client_connection.state == NET_CONN_STATE_DISCONNECTED + || client_connection.state == NET_CONN_STATE_DISCONNECTED_SLEEP) + { + NET_CL_Disconnected(); + + NET_CL_Shutdown(); + } + + net_waiting_for_launch = + client_connection.state == NET_CONN_STATE_CONNECTED + && client_state == CLIENT_STATE_WAITING_LAUNCH; + + if (client_state == CLIENT_STATE_IN_GAME) + { + // Possibly advance the receive window + + NET_CL_AdvanceWindow(); + + // Check if our resend requests have timed out + + NET_CL_CheckResends(); + } +} + +static void NET_CL_SendSYN(net_connect_data_t *data) +{ + net_packet_t *packet; + + NET_Log("client: sending SYN"); + + packet = NET_NewPacket(10); + NET_WriteInt16(packet, NET_PACKET_TYPE_SYN); + NET_WriteInt32(packet, NET_MAGIC_NUMBER); + NET_WriteString(packet, PACKAGE_STRING); + NET_WriteProtocolList(packet); + NET_WriteConnectData(packet, data); + NET_WriteString(packet, net_player_name); + NET_Conn_SendPacket(&client_connection, packet); + NET_FreePacket(packet); +} + +// Connect to a server +boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data) +{ + int start_time; + int last_send_time; + boolean sent_hole_punch; + + server_addr = addr; + NET_ReferenceAddress(addr); + + memcpy(net_local_wad_sha1sum, data->wad_sha1sum, sizeof(sha1_digest_t)); + memcpy(net_local_deh_sha1sum, data->deh_sha1sum, sizeof(sha1_digest_t)); + net_local_is_freedoom = data->is_freedoom; + + // create a new network I/O context and add just the necessary module + client_context = NET_NewContext(); + + // initialize module for client mode + if (!addr->module->InitClient()) + { + SetRejectReason("Failed to initialize client module"); + return false; + } + + NET_AddModule(client_context, addr->module); + + net_client_connected = true; + net_client_received_wait_data = false; + sent_hole_punch = false; + + NET_Conn_InitClient(&client_connection, addr, NET_PROTOCOL_UNKNOWN); + + // try to connect + start_time = I_GetTimeMS(); + last_send_time = -1; + SetRejectReason("Unknown reason"); + + while (client_connection.state == NET_CONN_STATE_CONNECTING) + { + int nowtime = I_GetTimeMS(); + + // Send a SYN packet every second. + if (nowtime - last_send_time > 1000 || last_send_time < 0) + { + NET_CL_SendSYN(data); + last_send_time = nowtime; + } + + // time out after 5 seconds + if (nowtime - start_time > 5000) + { + SetRejectReason("No response from server"); + break; + } + + if (!sent_hole_punch && nowtime - start_time > 2000) + { + NET_Log("client: no response to SYN, requesting hole punch"); + NET_RequestHolePunch(client_context, addr); + sent_hole_punch = true; + } + + // run client code + NET_CL_Run(); + + // run the server, just in case we are doing a loopback connect + NET_SV_Run(); + + // Don't hog the CPU + I_Sleep(1); + } + + if (client_connection.state == NET_CONN_STATE_CONNECTED) + { + // connected ok! + NET_Log("client: connected successfully"); + SetRejectReason(NULL); + client_state = CLIENT_STATE_WAITING_LAUNCH; + drone = data->drone; + + return true; + } + else + { + // failed to connect + NET_Log("client: failed to connect"); + NET_CL_Shutdown(); + + return false; + } +} + +// read game settings received from server + +boolean NET_CL_GetSettings(net_gamesettings_t *_settings) +{ + if (client_state != CLIENT_STATE_IN_GAME) + { + return false; + } + + memcpy(_settings, &settings, sizeof(net_gamesettings_t)); + + return true; +} + +// disconnect from the server + +void NET_CL_Disconnect(void) +{ + int start_time; + + if (!net_client_connected) + { + return; + } + + NET_Log("client: beginning disconnect"); + NET_Conn_Disconnect(&client_connection); + + start_time = I_GetTimeMS(); + + while (client_connection.state != NET_CONN_STATE_DISCONNECTED + && client_connection.state != NET_CONN_STATE_DISCONNECTED_SLEEP) + { + if (I_GetTimeMS() - start_time > 5000) + { + // time out after 5 seconds + + NET_Log("client: no acknowledgement of disconnect received"); + client_state = CLIENT_STATE_WAITING_START; + + fprintf(stderr, "NET_CL_Disconnect: Timeout while disconnecting " + "from server\n"); + break; + } + + NET_CL_Run(); + NET_SV_Run(); + + I_Sleep(1); + } + + // Finished sending disconnect packets, etc. + NET_Log("client: disconnect complete"); + NET_CL_Shutdown(); +} + +void NET_CL_Init(void) +{ + // Try to set from the USER and USERNAME environment variables + // Otherwise, fallback to "Player" + + if (net_player_name == NULL) + { + net_player_name = NET_GetRandomPetName(); + } +} + +void NET_Init(void) +{ + NET_OpenLog(); + NET_CL_Init(); +} + +void NET_BindVariables(void) +{ + M_BindStringVariable("player_name", &net_player_name); +} diff --git a/games/NXDoom/src/net_client.h b/games/NXDoom/src/net_client.h new file mode 100644 index 00000000000..37ba01984e4 --- /dev/null +++ b/games/NXDoom/src/net_client.h @@ -0,0 +1,53 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Network client code +// + +#ifndef NET_CLIENT_H +#define NET_CLIENT_H + +#include "doomtype.h" +#include "d_ticcmd.h" +#include "sha1.h" +#include "net_defs.h" + +boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data); +void NET_CL_Disconnect(void); +void NET_CL_Run(void); +void NET_CL_Init(void); +void NET_CL_LaunchGame(void); +void NET_CL_StartGame(net_gamesettings_t *settings); +void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic); +boolean NET_CL_GetSettings(net_gamesettings_t *_settings); +void NET_Init(void); + +void NET_BindVariables(void); + +extern boolean net_client_connected; +extern boolean net_client_received_wait_data; +extern net_waitdata_t net_client_wait_data; +extern char *net_client_reject_reason; +extern boolean net_waiting_for_launch; +extern char *net_player_name; + +extern sha1_digest_t net_server_wad_sha1sum; +extern sha1_digest_t net_server_deh_sha1sum; +extern unsigned int net_server_is_freedoom; +extern sha1_digest_t net_local_wad_sha1sum; +extern sha1_digest_t net_local_deh_sha1sum; +extern unsigned int net_local_is_freedoom; + +extern boolean drone; + +#endif /* #ifndef NET_CLIENT_H */ diff --git a/games/NXDoom/src/net_common.c b/games/NXDoom/src/net_common.c new file mode 100644 index 00000000000..99b32c25608 --- /dev/null +++ b/games/NXDoom/src/net_common.c @@ -0,0 +1,527 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Common code shared between the client and server +// + +#include +#include +#include +#include + +#include "doomtype.h" +#include "d_mode.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_argv.h" +#include "m_misc.h" + +#include "net_common.h" +#include "net_io.h" +#include "net_packet.h" +#include "net_structrw.h" + +// connections time out after 30 seconds + +#define CONNECTION_TIMEOUT_LEN 30 + +// maximum time between sending packets + +#define KEEPALIVE_PERIOD 1 + +// reliable packet that is guaranteed to reach its destination + +struct net_reliable_packet_s +{ + net_packet_t *packet; + int last_send_time; + int seq; + net_reliable_packet_t *next; +}; + +static FILE *net_debug = NULL; + +static void NET_Conn_Init(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol) +{ + conn->last_send_time = -1; + conn->num_retries = 0; + conn->addr = addr; + conn->protocol = protocol; + conn->reliable_packets = NULL; + conn->reliable_send_seq = 0; + conn->reliable_recv_seq = 0; + conn->keepalive_recv_time = I_GetTimeMS(); +} + +// Initialize as a client connection + +void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol) +{ + NET_Conn_Init(conn, addr, protocol); + conn->state = NET_CONN_STATE_CONNECTING; +} + +// Initialize as a server connection + +void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol) +{ + NET_Conn_Init(conn, addr, protocol); + conn->state = NET_CONN_STATE_CONNECTED; +} + +// Send a packet to a connection +// All packets should be sent through this interface, as it maintains the +// keepalive_send_time counter. + +void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet) +{ + conn->keepalive_send_time = I_GetTimeMS(); + NET_SendPacket(conn->addr, packet); +} + +static void NET_Conn_ParseDisconnect(net_connection_t *conn, net_packet_t *packet) +{ + net_packet_t *reply; + + // Other end wants to disconnect + // Send a DISCONNECT_ACK reply. + + reply = NET_NewPacket(10); + NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK); + NET_Conn_SendPacket(conn, reply); + NET_FreePacket(reply); + + conn->last_send_time = I_GetTimeMS(); + + conn->state = NET_CONN_STATE_DISCONNECTED_SLEEP; + conn->disconnect_reason = NET_DISCONNECT_REMOTE; +} + +// Parse a DISCONNECT_ACK packet + +static void NET_Conn_ParseDisconnectACK(net_connection_t *conn, + net_packet_t *packet) +{ + + if (conn->state == NET_CONN_STATE_DISCONNECTING) + { + // We have received an acknowledgement to our disconnect + // request. We have been disconnected successfully. + + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_LOCAL; + conn->last_send_time = -1; + } +} + +static void NET_Conn_ParseReliableACK(net_connection_t *conn, net_packet_t *packet) +{ + unsigned int seq; + + if (!NET_ReadInt8(packet, &seq)) + { + return; + } + + if (conn->reliable_packets == NULL) + { + return; + } + + // Is this an acknowledgement for the first packet in the list? + + if (seq == (unsigned int)((conn->reliable_packets->seq + 1) & 0xff)) + { + net_reliable_packet_t *rp; + + // Discard it, then. + // Unlink from the list. + + rp = conn->reliable_packets; + conn->reliable_packets = rp->next; + + NET_FreePacket(rp->packet); + free(rp); + } +} + +// Process the header of a reliable packet +// +// Returns true if the packet should be discarded (incorrect sequence) + +static boolean NET_Conn_ReliablePacket(net_connection_t *conn, + net_packet_t *packet) +{ + unsigned int seq; + net_packet_t *reply; + boolean result; + + // Read the sequence number + + if (!NET_ReadInt8(packet, &seq)) + { + return true; + } + + if (seq != (unsigned int)(conn->reliable_recv_seq & 0xff)) + { + // This is not the next expected packet in the sequence! + // + // Discard the packet. If we were smart, we would use a proper + // sliding window protocol to do this, but I'm lazy. + + result = true; + } + else + { + // Now we can receive the next packet in the sequence. + + conn->reliable_recv_seq = (conn->reliable_recv_seq + 1) & 0xff; + + result = false; + } + + // Send an acknowledgement + + // Note: this is braindead. It would be much more sensible to + // include this in the next packet, rather than the overhead of + // sending a complete packet just for one byte of information. + + reply = NET_NewPacket(10); + + NET_WriteInt16(reply, NET_PACKET_TYPE_RELIABLE_ACK); + NET_WriteInt8(reply, conn->reliable_recv_seq & 0xff); + + NET_Conn_SendPacket(conn, reply); + + NET_FreePacket(reply); + + return result; +} + +// Process a packet received by the server +// +// Returns true if eaten by common code + +boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet, + unsigned int *packet_type) +{ + conn->keepalive_recv_time = I_GetTimeMS(); + + // Is this a reliable packet? + + if (*packet_type & NET_RELIABLE_PACKET) + { + if (NET_Conn_ReliablePacket(conn, packet)) + { + // Invalid packet: eat it. + + return true; + } + + // Remove the reliable bit + + *packet_type &= ~NET_RELIABLE_PACKET; + } + + switch (*packet_type) + { + case NET_PACKET_TYPE_DISCONNECT: + NET_Conn_ParseDisconnect(conn, packet); + break; + case NET_PACKET_TYPE_DISCONNECT_ACK: + NET_Conn_ParseDisconnectACK(conn, packet); + break; + case NET_PACKET_TYPE_KEEPALIVE: + // No special action needed. + break; + case NET_PACKET_TYPE_RELIABLE_ACK: + NET_Conn_ParseReliableACK(conn, packet); + break; + default: + // Not a common packet + + return false; + } + + // We found a packet that we found interesting, and ate it. + + return true; +} + +void NET_Conn_Disconnect(net_connection_t *conn) +{ + if (conn->state != NET_CONN_STATE_DISCONNECTED + && conn->state != NET_CONN_STATE_DISCONNECTING + && conn->state != NET_CONN_STATE_DISCONNECTED_SLEEP) + { + conn->state = NET_CONN_STATE_DISCONNECTING; + conn->disconnect_reason = NET_DISCONNECT_LOCAL; + conn->last_send_time = -1; + conn->num_retries = 0; + } +} + +void NET_Conn_Run(net_connection_t *conn) +{ + net_packet_t *packet; + unsigned int nowtime; + + nowtime = I_GetTimeMS(); + + if (conn->state == NET_CONN_STATE_CONNECTED) + { + // Check the keepalive counters + + if (nowtime - conn->keepalive_recv_time > CONNECTION_TIMEOUT_LEN * 1000) + { + // Haven't received any packets from the other end in a long + // time. Assume disconnected. + + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_TIMEOUT; + } + + if (nowtime - conn->keepalive_send_time > KEEPALIVE_PERIOD * 1000) + { + // We have not sent anything in a long time. + // Send a keepalive. + + packet = NET_NewPacket(10); + NET_WriteInt16(packet, NET_PACKET_TYPE_KEEPALIVE); + NET_Conn_SendPacket(conn, packet); + NET_FreePacket(packet); + } + + // Check the reliable packet list. Has the first packet in the + // list timed out? + // + // NB. This is braindead, we have a fixed time of one second. + + if (conn->reliable_packets != NULL + && (conn->reliable_packets->last_send_time < 0 + || nowtime - conn->reliable_packets->last_send_time > 1000)) + { + // Packet timed out, time to resend + + NET_Conn_SendPacket(conn, conn->reliable_packets->packet); + conn->reliable_packets->last_send_time = nowtime; + } + } + else if (conn->state == NET_CONN_STATE_DISCONNECTING) + { + // Waiting for a reply to our DISCONNECT request. + + if (conn->last_send_time < 0 + || nowtime - conn->last_send_time > 1000) + { + // it has been a second since the last disconnect packet + // was sent, and still no reply. + + if (conn->num_retries < MAX_RETRIES) + { + // send another disconnect + + packet = NET_NewPacket(10); + NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT); + NET_Conn_SendPacket(conn, packet); + NET_FreePacket(packet); + conn->last_send_time = nowtime; + + ++conn->num_retries; + } + else + { + // No more retries allowed. + // Force disconnect. + + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_LOCAL; + } + } + } + else if (conn->state == NET_CONN_STATE_DISCONNECTED_SLEEP) + { + // We are disconnected, waiting in case we need to send + // a DISCONNECT_ACK to the server again. + + if (nowtime - conn->last_send_time > 5000) + { + // Idle for 5 seconds, switch state + + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_REMOTE; + } + } +} + +net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type) +{ + net_packet_t *packet; + net_reliable_packet_t *rp; + net_reliable_packet_t **listend; + + // Generate a packet with the right header + + packet = NET_NewPacket(100); + + NET_WriteInt16(packet, packet_type | NET_RELIABLE_PACKET); + + // write the low byte of the send sequence number + + NET_WriteInt8(packet, conn->reliable_send_seq & 0xff); + + // Add to the list of reliable packets + + rp = malloc(sizeof(net_reliable_packet_t)); + rp->packet = packet; + rp->next = NULL; + rp->seq = conn->reliable_send_seq; + rp->last_send_time = -1; + + for (listend = &conn->reliable_packets; + *listend != NULL; + listend = &((*listend)->next)); + + *listend = rp; + + // Count along the sequence + + conn->reliable_send_seq = (conn->reliable_send_seq + 1) & 0xff; + + // Finished + + return packet; +} + +// Used to expand the least significant byte of a tic number into +// the full tic number, from the current tic number + +unsigned int NET_ExpandTicNum(unsigned int relative, unsigned int b) +{ + unsigned int l, h; + unsigned int result; + + h = relative & ~0xff; + l = relative & 0xff; + + result = h | b; + + if (l < 0x40 && b > 0xb0) + result -= 0x100; + if (l > 0xb0 && b < 0x40) + result += 0x100; + + return result; +} + +// Check that game settings are valid + +boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission, + net_gamesettings_t *settings) +{ + if (settings->ticdup <= 0) + return false; + + if (settings->extratics < 0) + return false; + + if (settings->deathmatch < 0 || settings->deathmatch > 2) + return false; + + if (settings->skill < sk_noitems || settings->skill > sk_nightmare) + return false; + + if (!D_ValidGameVersion(mission, settings->gameversion)) + return false; + + if (!D_ValidEpisodeMap(mission, mode, settings->episode, settings->map)) + return false; + + return true; +} + +static void CloseLog(void) +{ + if (net_debug != NULL) + { + fclose(net_debug); + net_debug = NULL; + } +} + +void NET_OpenLog(void) +{ + int p; + + p = M_CheckParmWithArgs("-netlog", 1); + if (p > 0) + { + net_debug = M_fopen(myargv[p + 1], "w"); + if (net_debug == NULL) + { + I_Error("Failed to open %s to write debug log.", myargv[p + 1]); + } + I_AtExit(CloseLog, true); + } +} + +void NET_Log(const char *fmt, ...) +{ + va_list args; + + if (net_debug == NULL) + { + return; + } + + fprintf(net_debug, "%8d: ", I_GetTimeMS()); + va_start(args, fmt); + vfprintf(net_debug, fmt, args); + va_end(args); + fprintf(net_debug, "\n"); +} + +void NET_LogPacket(net_packet_t *packet) +{ + int i, bytes; + + if (net_debug == NULL) + { + return; + } + + bytes = packet->len - packet->pos; + if (bytes == 0) + { + return; + } + fprintf(net_debug, "\t%02x", packet->data[packet->pos]); + for (i = 1; i < bytes; ++i) + { + if ((i % 16) == 0) + { + fprintf(net_debug, "\n\t"); + } + else + { + fprintf(net_debug, " "); + } + fprintf(net_debug, "%02x", packet->data[packet->pos + i]); + } + fprintf(net_debug, "\n"); +} + diff --git a/games/NXDoom/src/net_common.h b/games/NXDoom/src/net_common.h new file mode 100644 index 00000000000..15a7684aef8 --- /dev/null +++ b/games/NXDoom/src/net_common.h @@ -0,0 +1,106 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Common code shared between the client and server +// + +#ifndef NET_COMMON_H +#define NET_COMMON_H + +#include "d_mode.h" +#include "net_defs.h" +#include "net_packet.h" + +typedef enum +{ + // Client has sent a SYN, is waiting for a SYN in response. + NET_CONN_STATE_CONNECTING, + + // Successfully connected. + NET_CONN_STATE_CONNECTED, + + // Sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply + NET_CONN_STATE_DISCONNECTING, + + // Client successfully disconnected + NET_CONN_STATE_DISCONNECTED, + + // We are disconnected, but in a sleep state, waiting for several + // seconds. This is in case the DISCONNECT_ACK we sent failed + // to arrive, and we need to send another one. We keep this as + // a valid connection for a few seconds until we are sure that + // the other end has successfully disconnected as well. + NET_CONN_STATE_DISCONNECTED_SLEEP, + +} net_connstate_t; + +// Reason a connection was terminated + +typedef enum +{ + // As the result of a local disconnect request + + NET_DISCONNECT_LOCAL, + + // As the result of a remote disconnect request + + NET_DISCONNECT_REMOTE, + + // Timeout (no data received in a long time) + + NET_DISCONNECT_TIMEOUT, + +} net_disconnect_reason_t; + +#define MAX_RETRIES 5 + +typedef struct net_reliable_packet_s net_reliable_packet_t; + +typedef struct +{ + net_connstate_t state; + net_disconnect_reason_t disconnect_reason; + net_addr_t *addr; + net_protocol_t protocol; + int last_send_time; + int num_retries; + int keepalive_send_time; + int keepalive_recv_time; + net_reliable_packet_t *reliable_packets; + int reliable_send_seq; + int reliable_recv_seq; +} net_connection_t; + + +void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet); +void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol); +void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol); +boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet, + unsigned int *packet_type); +void NET_Conn_Disconnect(net_connection_t *conn); +void NET_Conn_Run(net_connection_t *conn); +net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type); + +// Other miscellaneous common functions +unsigned int NET_ExpandTicNum(unsigned int relative, unsigned int b); +boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission, + net_gamesettings_t *settings); + +void NET_OpenLog(void); +void NET_Log(const char *fmt, ...); +void NET_LogPacket(net_packet_t *packet); + +#endif /* #ifndef NET_COMMON_H */ + diff --git a/games/NXDoom/src/net_dedicated.c b/games/NXDoom/src/net_dedicated.c new file mode 100644 index 00000000000..dcb9f8fae2a --- /dev/null +++ b/games/NXDoom/src/net_dedicated.c @@ -0,0 +1,80 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dedicated server code. +// + +#include +#include + +#include "doomtype.h" + +#include "i_system.h" +#include "i_timer.h" + +#include "m_argv.h" + +#include "net_common.h" +#include "net_sdl.h" +#include "net_server.h" + +// +// People can become confused about how dedicated servers work. Game +// options are specified to the controlling player who is the first to +// join a game. Bomb out with an error message if game options are +// specified to a dedicated server. +// + +static const char *not_dedicated_options[] = +{ + "-deh", "-iwad", "-cdrom", "-gameversion", "-nomonsters", "-respawn", + "-fast", "-altdeath", "-deathmatch", "-turbo", "-merge", "-af", "-as", + "-aa", "-file", "-wart", "-skill", "-episode", "-timer", "-avg", "-warp", + "-loadgame", "-longtics", "-extratics", "-dup", "-shorttics", NULL, +}; + +static void CheckForClientOptions(void) +{ + int i; + + for (i=0; not_dedicated_options[i] != NULL; ++i) + { + if (M_CheckParm(not_dedicated_options[i]) > 0) + { + I_Error("The command line parameter '%s' was specified to a " + "dedicated server.\nGame parameters should be specified " + "to the first player to join a server, \nnot to the " + "server itself. ", + not_dedicated_options[i]); + } + } +} + +void NET_DedicatedServer(void) +{ + CheckForClientOptions(); + + NET_OpenLog(); + NET_SV_Init(); + NET_SV_AddModule(&net_sdl_module); + NET_SV_RegisterWithMaster(); + + while (true) + { + NET_SV_Run(); + // TODO: Block on socket instead of polling. + I_Sleep(1); + } +} + diff --git a/games/NXDoom/src/net_dedicated.h b/games/NXDoom/src/net_dedicated.h new file mode 100644 index 00000000000..3d7387b5782 --- /dev/null +++ b/games/NXDoom/src/net_dedicated.h @@ -0,0 +1,25 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Dedicated server code. +// + +#ifndef NET_DEDICATED_H +#define NET_DEDICATED_H + +void NET_DedicatedServer(void); + +#endif /* #ifndef NET_DEDICATED_H */ + + diff --git a/games/NXDoom/src/net_defs.h b/games/NXDoom/src/net_defs.h new file mode 100644 index 00000000000..ab852c08eec --- /dev/null +++ b/games/NXDoom/src/net_defs.h @@ -0,0 +1,276 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Definitions for use in networking code. +// + +#ifndef NET_DEFS_H +#define NET_DEFS_H + +#include + +#include "doomtype.h" +#include "d_ticcmd.h" +#include "sha1.h" + +// Absolute maximum number of "nodes" in the game. This is different to +// NET_MAXPLAYERS, as there may be observers that are not participating +// (eg. left/right monitors) + +#define MAXNETNODES 16 + +// The maximum number of players, multiplayer/networking. +// This is the maximum supported by the networking code; individual games +// have their own values for MAXPLAYERS that can be smaller. + +#define NET_MAXPLAYERS 8 + +// Maximum length of a player's name. + +#define MAXPLAYERNAME 30 + +// Networking and tick handling related. + +#define BACKUPTICS 128 + +typedef struct _net_module_s net_module_t; +typedef struct _net_packet_s net_packet_t; +typedef struct _net_addr_s net_addr_t; +typedef struct _net_context_s net_context_t; + +struct _net_packet_s +{ + byte *data; + size_t len; + size_t alloced; + unsigned int pos; +}; + +struct _net_module_s +{ + // Initialize this module for use as a client + + boolean (*InitClient)(void); + + // Initialize this module for use as a server + + boolean (*InitServer)(void); + + // Send a packet + + void (*SendPacket)(net_addr_t *addr, net_packet_t *packet); + + // Check for new packets to receive + // + // Returns true if packet received + + boolean (*RecvPacket)(net_addr_t **addr, net_packet_t **packet); + + // Converts an address to a string + + void (*AddrToString)(net_addr_t *addr, char *buffer, int buffer_len); + + // Free back an address when no longer in use + + void (*FreeAddress)(net_addr_t *addr); + + // Try to resolve a name to an address + + net_addr_t *(*ResolveAddress)(const char *addr); +}; + +// net_addr_t + +struct _net_addr_s +{ + net_module_t *module; + int refcount; + void *handle; +}; + +// Magic number sent when connecting to check this is a valid client +#define NET_MAGIC_NUMBER 1454104972U + +// Old magic number used by Chocolate Doom versions before v3.0: +#define NET_OLD_MAGIC_NUMBER 3436803284U + +// header field value indicating that the packet is a reliable packet + +#define NET_RELIABLE_PACKET (1 << 15) + +// Supported protocols. If you're developing a fork of Chocolate +// Doom, you can add your own entry to this list while maintaining +// compatibility with Chocolate Doom servers. Higher-numbered enum values +// will be preferred when negotiating a protocol for the client and server +// to use, so the order matters. +// NOTE: The values in this enum do not have any special value outside of +// the program they're compiled in. What matters is the string representation. +typedef enum +{ + // Protocol introduced with Chocolate Doom v3.0. Each compatibility- + // breaking change to the network protocol will produce a new protocol + // number in this enum. + NET_PROTOCOL_CHOCOLATE_DOOM_0, + + // Add your own protocol here; be sure to add a name for it to the list + // in net_common.c too. + + NET_NUM_PROTOCOLS, + NET_PROTOCOL_UNKNOWN, +} net_protocol_t; + +// packet types + +typedef enum +{ + NET_PACKET_TYPE_SYN, + NET_PACKET_TYPE_ACK, // deprecated + NET_PACKET_TYPE_REJECTED, + NET_PACKET_TYPE_KEEPALIVE, + NET_PACKET_TYPE_WAITING_DATA, + NET_PACKET_TYPE_GAMESTART, + NET_PACKET_TYPE_GAMEDATA, + NET_PACKET_TYPE_GAMEDATA_ACK, + NET_PACKET_TYPE_DISCONNECT, + NET_PACKET_TYPE_DISCONNECT_ACK, + NET_PACKET_TYPE_RELIABLE_ACK, + NET_PACKET_TYPE_GAMEDATA_RESEND, + NET_PACKET_TYPE_CONSOLE_MESSAGE, + NET_PACKET_TYPE_QUERY, + NET_PACKET_TYPE_QUERY_RESPONSE, + NET_PACKET_TYPE_LAUNCH, + NET_PACKET_TYPE_NAT_HOLE_PUNCH, +} net_packet_type_t; + +typedef enum +{ + NET_MASTER_PACKET_TYPE_ADD, + NET_MASTER_PACKET_TYPE_ADD_RESPONSE, + NET_MASTER_PACKET_TYPE_QUERY, + NET_MASTER_PACKET_TYPE_QUERY_RESPONSE, + NET_MASTER_PACKET_TYPE_GET_METADATA, + NET_MASTER_PACKET_TYPE_GET_METADATA_RESPONSE, + NET_MASTER_PACKET_TYPE_SIGN_START, + NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, + NET_MASTER_PACKET_TYPE_SIGN_END, + NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, + NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH, + NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL, +} net_master_packet_type_t; + +// Settings specified when the client connects to the server. + +typedef struct +{ + int gamemode; + int gamemission; + int lowres_turn; + int drone; + int max_players; + int is_freedoom; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; + int player_class; +} net_connect_data_t; + +// Game settings sent by client to server when initiating game start, +// and received from the server by clients when the game starts. + +typedef struct +{ + int ticdup; + int extratics; + int deathmatch; + int episode; + int nomonsters; + int fast_monsters; + int respawn_monsters; + int map; + int skill; + int gameversion; + int lowres_turn; + int new_sync; + int timelimit; + int loadgame; + int random; // [Strife only] + + // These fields are only used by the server when sending a game + // start message: + + int num_players; + int consoleplayer; + + // Hexen player classes: + + int player_classes[NET_MAXPLAYERS]; + +} net_gamesettings_t; + +#define NET_TICDIFF_FORWARD (1 << 0) +#define NET_TICDIFF_SIDE (1 << 1) +#define NET_TICDIFF_TURN (1 << 2) +#define NET_TICDIFF_BUTTONS (1 << 3) +#define NET_TICDIFF_CONSISTANCY (1 << 4) +#define NET_TICDIFF_CHATCHAR (1 << 5) +#define NET_TICDIFF_RAVEN (1 << 6) +#define NET_TICDIFF_STRIFE (1 << 7) + +typedef struct +{ + unsigned int diff; + ticcmd_t cmd; +} net_ticdiff_t; + +// Complete set of ticcmds from all players + +typedef struct +{ + signed int latency; + unsigned int seq; + boolean playeringame[NET_MAXPLAYERS]; + net_ticdiff_t cmds[NET_MAXPLAYERS]; +} net_full_ticcmd_t; + +// Data sent in response to server queries + +typedef struct +{ + const char *version; + int server_state; + int num_players; + int max_players; + int gamemode; + int gamemission; + const char *description; + net_protocol_t protocol; +} net_querydata_t; + +// Data sent by the server while waiting for the game to start. + +typedef struct +{ + int num_players; + int num_drones; + int ready_players; + int max_players; + int is_controller; + int consoleplayer; + char player_names[NET_MAXPLAYERS][MAXPLAYERNAME]; + char player_addrs[NET_MAXPLAYERS][MAXPLAYERNAME]; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; + int is_freedoom; +} net_waitdata_t; + +#endif /* #ifndef NET_DEFS_H */ diff --git a/games/NXDoom/src/net_gui.c b/games/NXDoom/src/net_gui.c new file mode 100644 index 00000000000..0a73fa43cd9 --- /dev/null +++ b/games/NXDoom/src/net_gui.c @@ -0,0 +1,434 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Graphical stuff related to the networking code: +// +// * The client waiting screen when we are waiting for the server to +// start the game. +// + +#include +#include +#include +#include + +#include "config.h" +#include "doomkeys.h" + +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "m_argv.h" +#include "m_misc.h" + +#include "net_client.h" +#include "net_gui.h" +#include "net_query.h" +#include "net_server.h" + +#include "textscreen.h" + +static txt_window_t *window; +static int old_max_players; +static txt_label_t *player_labels[NET_MAXPLAYERS]; +static txt_label_t *ip_labels[NET_MAXPLAYERS]; +static txt_label_t *drone_label; +static txt_label_t *master_msg_label; +static boolean had_warning; + +// Number of players we expect to be in the game. When the number is +// reached, we auto-start the game (if we're the controller). If +// zero, do not autostart. +static int expected_nodes; + +static void EscapePressed(TXT_UNCAST_ARG(widget), void *unused) +{ + TXT_Shutdown(); + I_Quit(); +} + +static void StartGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + NET_CL_LaunchGame(); +} + +static void OpenWaitDialog(void) +{ + txt_window_action_t *cancel; + + TXT_SetDesktopTitle(PACKAGE_STRING); + + window = TXT_NewWindow("Waiting for game start..."); + + TXT_AddWidget(window, TXT_NewLabel("\nPlease wait...\n\n")); + + cancel = TXT_NewWindowAction(KEY_ESCAPE, "Cancel"); + TXT_SignalConnect(cancel, "pressed", EscapePressed, NULL); + + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, cancel); + TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_BOTTOM, + TXT_SCREEN_W / 2, TXT_SCREEN_H - 9); + + old_max_players = 0; +} + +static void BuildWindow(void) +{ + char buf[50]; + txt_table_t *table; + int i; + + TXT_ClearTable(window); + table = TXT_NewTable(3); + TXT_AddWidget(window, table); + + // Add spacers + + TXT_AddWidget(table, NULL); + TXT_AddWidget(table, TXT_NewStrut(25, 1)); + TXT_AddWidget(table, TXT_NewStrut(17, 1)); + + // Player labels + + for (i = 0; i < net_client_wait_data.max_players; ++i) + { + M_snprintf(buf, sizeof(buf), " %i. ", i + 1); + TXT_AddWidget(table, TXT_NewLabel(buf)); + player_labels[i] = TXT_NewLabel(""); + ip_labels[i] = TXT_NewLabel(""); + TXT_AddWidget(table, player_labels[i]); + TXT_AddWidget(table, ip_labels[i]); + } + + drone_label = TXT_NewLabel(""); + + TXT_AddWidget(window, drone_label); +} + +static void UpdateGUI(void) +{ + txt_window_action_t *startgame; + char buf[50]; + unsigned int i; + + // If the value of max_players changes, we must rebuild the + // contents of the window. This includes when the first + // waiting data packet is received. + + if (net_client_received_wait_data) + { + if (net_client_wait_data.max_players != old_max_players) + { + BuildWindow(); + } + } + else + { + return; + } + + for (i = 0; i < net_client_wait_data.max_players; ++i) + { + txt_color_t color = TXT_COLOR_BRIGHT_WHITE; + + if ((signed) i == net_client_wait_data.consoleplayer) + { + color = TXT_COLOR_YELLOW; + } + + TXT_SetFGColor(player_labels[i], color); + TXT_SetFGColor(ip_labels[i], color); + + if (i < net_client_wait_data.num_players) + { + TXT_SetLabel(player_labels[i], + net_client_wait_data.player_names[i]); + TXT_SetLabel(ip_labels[i], + net_client_wait_data.player_addrs[i]); + } + else + { + TXT_SetLabel(player_labels[i], ""); + TXT_SetLabel(ip_labels[i], ""); + } + } + + if (net_client_wait_data.num_drones > 0) + { + M_snprintf(buf, sizeof(buf), " (+%i observer clients)", + net_client_wait_data.num_drones); + TXT_SetLabel(drone_label, buf); + } + else + { + TXT_SetLabel(drone_label, ""); + } + + if (net_client_wait_data.is_controller) + { + startgame = TXT_NewWindowAction(' ', "Start game"); + TXT_SignalConnect(startgame, "pressed", StartGame, NULL); + } + else + { + startgame = NULL; + } + + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, startgame); +} + +static void BuildMasterStatusWindow(void) +{ + txt_window_t *master_window; + + master_window = TXT_NewWindow(NULL); + master_msg_label = TXT_NewLabel(""); + TXT_AddWidget(master_window, master_msg_label); + + // This window is here purely for information, so it should be + // in the background. + + TXT_LowerWindow(master_window); + TXT_SetWindowPosition(master_window, TXT_HORIZ_CENTER, TXT_VERT_CENTER, + TXT_SCREEN_W / 2, TXT_SCREEN_H - 4); + TXT_SetWindowAction(master_window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(master_window, TXT_HORIZ_CENTER, NULL); + TXT_SetWindowAction(master_window, TXT_HORIZ_RIGHT, NULL); +} + +static void CheckMasterStatus(void) +{ + boolean added; + + if (!NET_Query_CheckAddedToMaster(&added)) + { + return; + } + + if (master_msg_label == NULL) + { + BuildMasterStatusWindow(); + } + + if (added) + { + TXT_SetLabel(master_msg_label, + "Your server is now registered with the global master server.\n" + "Other players can find your server online."); + } + else + { + TXT_SetLabel(master_msg_label, + "Failed to register with the master server. Your server is not\n" + "publicly accessible. You may need to reconfigure your Internet\n" + "router to add a port forward for UDP port 2342. Look up\n" + "information on port forwarding online."); + } +} + +static void PrintSHA1Digest(const char *s, const byte *digest) +{ + unsigned int i; + + printf("%s: ", s); + + for (i=0; i + // @category net + // + // Autostart the netgame when n nodes (clients) have joined the server. + // + + i = M_CheckParmWithArgs("-nodes", 1); + if (i > 0) + { + expected_nodes = atoi(myargv[i + 1]); + } +} + +static void CheckAutoLaunch(void) +{ + int nodes; + + if (net_client_received_wait_data + && net_client_wait_data.is_controller + && expected_nodes > 0) + { + nodes = net_client_wait_data.num_players + + net_client_wait_data.num_drones; + + if (nodes >= expected_nodes) + { + StartGame(NULL, NULL); + expected_nodes = 0; + } + } +} + +void NET_WaitForLaunch(void) +{ + if (!TXT_Init()) + { + fprintf(stderr, "Failed to initialize GUI\n"); + exit(-1); + } + + TXT_SetColor(TXT_COLOR_BLUE, 0x04, 0x14, 0x40); // Romero's "funky blue" color + + I_InitWindowIcon(); + + ParseCommandLineArgs(); + OpenWaitDialog(); + had_warning = false; + + while (net_waiting_for_launch) + { + UpdateGUI(); + CheckAutoLaunch(); + CheckSHA1Sums(); + CheckMasterStatus(); + + TXT_DispatchEvents(); + TXT_DrawDesktop(); + + NET_CL_Run(); + NET_SV_Run(); + + if (!net_client_connected) + { + I_Error("Lost connection to server"); + } + + TXT_Sleep(100); + } + + TXT_Shutdown(); +} diff --git a/games/NXDoom/src/net_gui.h b/games/NXDoom/src/net_gui.h new file mode 100644 index 00000000000..4f4198b6087 --- /dev/null +++ b/games/NXDoom/src/net_gui.h @@ -0,0 +1,29 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Graphical stuff related to the networking code: +// +// * The client waiting screen when we are waiting for the server to +// start the game. +// + + +#ifndef NET_GUI_H +#define NET_GUI_H + +#include "doomtype.h" + +extern void NET_WaitForLaunch(void); + +#endif /* #ifndef NET_GUI_H */ + diff --git a/games/NXDoom/src/net_io.c b/games/NXDoom/src/net_io.c new file mode 100644 index 00000000000..02519afe21d --- /dev/null +++ b/games/NXDoom/src/net_io.c @@ -0,0 +1,147 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Network packet I/O. Base layer for sending/receiving packets, +// through the network module system +// + +#include + +#include "i_system.h" +#include "net_defs.h" +#include "net_io.h" +#include "z_zone.h" + +#define MAX_MODULES 16 + +struct _net_context_s +{ + net_module_t *modules[MAX_MODULES]; + int num_modules; +}; + +net_addr_t net_broadcast_addr; + +net_context_t *NET_NewContext(void) +{ + net_context_t *context; + + context = Z_Malloc(sizeof(net_context_t), PU_STATIC, 0); + context->num_modules = 0; + + return context; +} + +void NET_AddModule(net_context_t *context, net_module_t *module) +{ + if (context->num_modules >= MAX_MODULES) + { + I_Error("NET_AddModule: No more modules for context"); + } + + context->modules[context->num_modules] = module; + ++context->num_modules; +} + +net_addr_t *NET_ResolveAddress(net_context_t *context, const char *addr) +{ + int i; + net_addr_t *result; + + for (i=0; inum_modules; ++i) + { + result = context->modules[i]->ResolveAddress(addr); + + if (result != NULL) + { + NET_ReferenceAddress(result); + return result; + } + } + + return NULL; +} + +void NET_SendPacket(net_addr_t *addr, net_packet_t *packet) +{ + addr->module->SendPacket(addr, packet); +} + +void NET_SendBroadcast(net_context_t *context, net_packet_t *packet) +{ + int i; + + for (i=0; inum_modules; ++i) + { + context->modules[i]->SendPacket(&net_broadcast_addr, packet); + } +} + +boolean NET_RecvPacket(net_context_t *context, + net_addr_t **addr, + net_packet_t **packet) +{ + int i; + + // check all modules for new packets + + for (i=0; inum_modules; ++i) + { + if (context->modules[i]->RecvPacket(addr, packet)) + { + NET_ReferenceAddress(*addr); + return true; + } + } + + return false; +} + +// Note: this prints into a static buffer, calling again overwrites +// the first result + +char *NET_AddrToString(net_addr_t *addr) +{ + static char buf[128]; + + addr->module->AddrToString(addr, buf, sizeof(buf) - 1); + + return buf; +} + +void NET_ReferenceAddress(net_addr_t *addr) +{ + if (addr == NULL) + { + return; + } + ++addr->refcount; + //printf("%s: +refcount=%d\n", NET_AddrToString(addr), addr->refcount); +} + +void NET_ReleaseAddress(net_addr_t *addr) +{ + if (addr == NULL) + { + return; + } + + --addr->refcount; + //printf("%s: -refcount=%d\n", NET_AddrToString(addr), addr->refcount); + if (addr->refcount <= 0) + { + addr->module->FreeAddress(addr); + } +} + diff --git a/games/NXDoom/src/net_io.h b/games/NXDoom/src/net_io.h new file mode 100644 index 00000000000..d61a1eb3d9f --- /dev/null +++ b/games/NXDoom/src/net_io.h @@ -0,0 +1,61 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Network packet manipulation (net_packet_t) +// + +#ifndef NET_IO_H +#define NET_IO_H + +#include "net_defs.h" + +extern net_addr_t net_broadcast_addr; + +// Create a new network context. +net_context_t *NET_NewContext(void); + +// Add a network module to a context. +void NET_AddModule(net_context_t *context, net_module_t *module); + +// Send a packet to the given address. +void NET_SendPacket(net_addr_t *addr, net_packet_t *packet); + +// Send a broadcast using all modules in the given context. +void NET_SendBroadcast(net_context_t *context, net_packet_t *packet); + +// Check all modules in the given context and receive a packet, returning true +// if a packet was received. The result is stored in *packet and the source is +// stored in *addr, with an implicit reference added. The packet must be freed +// by the caller and the reference releasd. +boolean NET_RecvPacket(net_context_t *context, net_addr_t **addr, + net_packet_t **packet); + +// Return a string representation of the given address. The result points to a +// static buffer and will become invalid with the next call. +char *NET_AddrToString(net_addr_t *addr); + +// Add a reference to the given address. +void NET_ReferenceAddress(net_addr_t *addr); + +// Release a reference to the given address. When there are no more references, +// the address will be freed. +void NET_ReleaseAddress(net_addr_t *addr); + +// Resolve a string representation of an address. If successful, a net_addr_t +// pointer is received with an implicit reference that must be freed by the +// caller when it is no longer needed. +net_addr_t *NET_ResolveAddress(net_context_t *context, const char *address); + +#endif /* #ifndef NET_IO_H */ + diff --git a/games/NXDoom/src/net_loop.c b/games/NXDoom/src/net_loop.c new file mode 100644 index 00000000000..65140fa3bc9 --- /dev/null +++ b/games/NXDoom/src/net_loop.c @@ -0,0 +1,231 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Loopback network module for server compiled into the client +// + +#include +#include + +#include "doomtype.h" +#include "i_system.h" +#include "m_misc.h" +#include "net_defs.h" +#include "net_loop.h" +#include "net_packet.h" + +#define MAX_QUEUE_SIZE 16 + +typedef struct +{ + net_packet_t *packets[MAX_QUEUE_SIZE]; + int head, tail; +} packet_queue_t; + +static packet_queue_t client_queue; +static packet_queue_t server_queue; +static net_addr_t client_addr; +static net_addr_t server_addr; + +static void QueueInit(packet_queue_t *queue) +{ + queue->head = queue->tail = 0; +} + +static void QueuePush(packet_queue_t *queue, net_packet_t *packet) +{ + int new_tail; + + new_tail = (queue->tail + 1) % MAX_QUEUE_SIZE; + + if (new_tail == queue->head) + { + // queue is full + + return; + } + + queue->packets[queue->tail] = packet; + queue->tail = new_tail; +} + +static net_packet_t *QueuePop(packet_queue_t *queue) +{ + net_packet_t *packet; + + if (queue->tail == queue->head) + { + // queue empty + + return NULL; + } + + packet = queue->packets[queue->head]; + queue->head = (queue->head + 1) % MAX_QUEUE_SIZE; + + return packet; +} + +//----------------------------------------------------------------------------- +// +// Client end code +// +//----------------------------------------------------------------------------- + +static boolean NET_CL_InitClient(void) +{ + QueueInit(&client_queue); + + return true; +} + +static boolean NET_CL_InitServer(void) +{ + I_Error("NET_CL_InitServer: attempted to initialize client pipe end as a server!"); + return false; +} + +static void NET_CL_SendPacket(net_addr_t *addr, net_packet_t *packet) +{ + QueuePush(&server_queue, NET_PacketDup(packet)); +} + +static boolean NET_CL_RecvPacket(net_addr_t **addr, net_packet_t **packet) +{ + net_packet_t *popped; + + popped = QueuePop(&client_queue); + + if (popped != NULL) + { + *packet = popped; + *addr = &client_addr; + client_addr.module = &net_loop_client_module; + + return true; + } + + return false; +} + +static void NET_CL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +{ + M_snprintf(buffer, buffer_len, "local server"); +} + +static void NET_CL_FreeAddress(net_addr_t *addr) +{ +} + +static net_addr_t *NET_CL_ResolveAddress(const char *address) +{ + if (address == NULL) + { + client_addr.module = &net_loop_client_module; + + return &client_addr; + } + else + { + return NULL; + } +} + +net_module_t net_loop_client_module = +{ + NET_CL_InitClient, + NET_CL_InitServer, + NET_CL_SendPacket, + NET_CL_RecvPacket, + NET_CL_AddrToString, + NET_CL_FreeAddress, + NET_CL_ResolveAddress, +}; + +//----------------------------------------------------------------------------- +// +// Server end code +// +//----------------------------------------------------------------------------- + +static boolean NET_SV_InitClient(void) +{ + I_Error("NET_SV_InitClient: attempted to initialize server pipe end as a client!"); + return false; +} + +static boolean NET_SV_InitServer(void) +{ + QueueInit(&server_queue); + + return true; +} + +static void NET_SV_SendPacket(net_addr_t *addr, net_packet_t *packet) +{ + QueuePush(&client_queue, NET_PacketDup(packet)); +} + +static boolean NET_SV_RecvPacket(net_addr_t **addr, net_packet_t **packet) +{ + net_packet_t *popped; + + popped = QueuePop(&server_queue); + + if (popped != NULL) + { + *packet = popped; + *addr = &server_addr; + server_addr.module = &net_loop_server_module; + + return true; + } + + return false; +} + +static void NET_SV_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +{ + M_snprintf(buffer, buffer_len, "local client"); +} + +static void NET_SV_FreeAddress(net_addr_t *addr) +{ +} + +static net_addr_t *NET_SV_ResolveAddress(const char *address) +{ + if (address == NULL) + { + server_addr.module = &net_loop_server_module; + return &server_addr; + } + else + { + return NULL; + } +} + +net_module_t net_loop_server_module = +{ + NET_SV_InitClient, + NET_SV_InitServer, + NET_SV_SendPacket, + NET_SV_RecvPacket, + NET_SV_AddrToString, + NET_SV_FreeAddress, + NET_SV_ResolveAddress, +}; + + diff --git a/games/NXDoom/src/net_loop.h b/games/NXDoom/src/net_loop.h new file mode 100644 index 00000000000..5a2e58ee1c9 --- /dev/null +++ b/games/NXDoom/src/net_loop.h @@ -0,0 +1,27 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Loopback network module for server compiled into the client +// + +#ifndef NET_LOOP_H +#define NET_LOOP_H + +#include "net_defs.h" + +extern net_module_t net_loop_client_module; +extern net_module_t net_loop_server_module; + +#endif /* #ifndef NET_LOOP_H */ + diff --git a/games/NXDoom/src/net_packet.c b/games/NXDoom/src/net_packet.c new file mode 100644 index 00000000000..23bfda675e5 --- /dev/null +++ b/games/NXDoom/src/net_packet.c @@ -0,0 +1,328 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Network packet manipulation (net_packet_t) +// + +#include +#include +#include "m_misc.h" +#include "net_packet.h" +#include "z_zone.h" + +static int total_packet_memory = 0; + +net_packet_t *NET_NewPacket(int initial_size) +{ + net_packet_t *packet; + + packet = (net_packet_t *) Z_Malloc(sizeof(net_packet_t), PU_STATIC, 0); + + if (initial_size == 0) + initial_size = 256; + + packet->alloced = initial_size; + packet->data = Z_Malloc(initial_size, PU_STATIC, 0); + packet->len = 0; + packet->pos = 0; + + total_packet_memory += sizeof(net_packet_t) + initial_size; + + //printf("total packet memory: %i bytes\n", total_packet_memory); + //printf("%p: allocated\n", packet); + + return packet; +} + +// duplicates an existing packet + +net_packet_t *NET_PacketDup(net_packet_t *packet) +{ + net_packet_t *newpacket; + + newpacket = NET_NewPacket(packet->len); + memcpy(newpacket->data, packet->data, packet->len); + newpacket->len = packet->len; + + return newpacket; +} + +void NET_FreePacket(net_packet_t *packet) +{ + //printf("%p: destroyed\n", packet); + + total_packet_memory -= sizeof(net_packet_t) + packet->alloced; + Z_Free(packet->data); + Z_Free(packet); +} + +// Read a byte from the packet, returning true if read +// successfully + +boolean NET_ReadInt8(net_packet_t *packet, unsigned int *data) +{ + if (packet->pos + 1 > packet->len) + return false; + + *data = packet->data[packet->pos]; + + packet->pos += 1; + + return true; +} + +// Read a 16-bit integer from the packet, returning true if read +// successfully + +boolean NET_ReadInt16(net_packet_t *packet, unsigned int *data) +{ + byte *p; + + if (packet->pos + 2 > packet->len) + return false; + + p = packet->data + packet->pos; + + *data = (p[0] << 8) | p[1]; + packet->pos += 2; + + return true; +} + +// Read a 32-bit integer from the packet, returning true if read +// successfully + +boolean NET_ReadInt32(net_packet_t *packet, unsigned int *data) +{ + byte *p; + + if (packet->pos + 4 > packet->len) + return false; + + p = packet->data + packet->pos; + + *data = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + packet->pos += 4; + + return true; +} + +// Signed read functions + +boolean NET_ReadSInt8(net_packet_t *packet, signed int *data) +{ + if (NET_ReadInt8(packet,(unsigned int *) data)) + { + if (*data & (1 << 7)) + { + *data &= ~(1 << 7); + *data -= (1 << 7); + } + return true; + } + else + { + return false; + } +} + +boolean NET_ReadSInt16(net_packet_t *packet, signed int *data) +{ + if (NET_ReadInt16(packet, (unsigned int *) data)) + { + if (*data & (1 << 15)) + { + *data &= ~(1 << 15); + *data -= (1 << 15); + } + return true; + } + else + { + return false; + } +} + +boolean NET_ReadSInt32(net_packet_t *packet, signed int *data) +{ + if (NET_ReadInt32(packet, (unsigned int *) data)) + { + if (*data & (1U << 31)) + { + *data &= ~(1U << 31); + *data -= (1U << 31); + } + return true; + } + else + { + return false; + } +} + +// Read a string from the packet. Returns NULL if a terminating +// NUL character was not found before the end of the packet. + +char *NET_ReadString(net_packet_t *packet) +{ + char *start; + + start = (char *) packet->data + packet->pos; + + // Search forward for a NUL character + + while (packet->pos < packet->len && packet->data[packet->pos] != '\0') + { + ++packet->pos; + } + + if (packet->pos >= packet->len) + { + // Reached the end of the packet + + return NULL; + } + + // packet->data[packet->pos] == '\0': We have reached a terminating + // NULL. Skip past this NULL and continue reading immediately + // after it. + + ++packet->pos; + + return start; +} + +// Read a string from the packet, but (potentially) modify it to strip +// out any unprintable characters which could be malicious control codes. +// Note that this may modify the original packet contents. +char *NET_ReadSafeString(net_packet_t *packet) +{ + char *r, *w, *result; + + result = NET_ReadString(packet); + if (result == NULL) + { + return NULL; + } + + // w is always <= r, so we never produce a longer string than the original. + w = result; + for (r = result; *r != '\0'; ++r) + { + // TODO: This is a very naive way of producing a safe string; only + // ASCII characters are allowed. Probably this should really support + // UTF-8 characters as well. + if (isprint(*r) || *r == '\n') + { + *w = *r; + ++w; + } + } + *w = '\0'; + + return result; +} + +// Dynamically increases the size of a packet + +static void NET_IncreasePacket(net_packet_t *packet) +{ + byte *newdata; + + total_packet_memory -= packet->alloced; + + packet->alloced *= 2; + + newdata = Z_Malloc(packet->alloced, PU_STATIC, 0); + + memcpy(newdata, packet->data, packet->len); + + Z_Free(packet->data); + packet->data = newdata; + + total_packet_memory += packet->alloced; +} + +// Write a single byte to the packet + +void NET_WriteInt8(net_packet_t *packet, unsigned int i) +{ + if (packet->len + 1 > packet->alloced) + NET_IncreasePacket(packet); + + packet->data[packet->len] = i; + packet->len += 1; +} + +// Write a 16-bit integer to the packet + +void NET_WriteInt16(net_packet_t *packet, unsigned int i) +{ + byte *p; + + if (packet->len + 2 > packet->alloced) + NET_IncreasePacket(packet); + + p = packet->data + packet->len; + + p[0] = (i >> 8) & 0xff; + p[1] = i & 0xff; + + packet->len += 2; +} + + +// Write a single byte to the packet + +void NET_WriteInt32(net_packet_t *packet, unsigned int i) +{ + byte *p; + + if (packet->len + 4 > packet->alloced) + NET_IncreasePacket(packet); + + p = packet->data + packet->len; + + p[0] = (i >> 24) & 0xff; + p[1] = (i >> 16) & 0xff; + p[2] = (i >> 8) & 0xff; + p[3] = i & 0xff; + + packet->len += 4; +} + +void NET_WriteString(net_packet_t *packet, const char *string) +{ + byte *p; + size_t string_size; + + string_size = strlen(string) + 1; + + // Increase the packet size until large enough to hold the string + + while (packet->len + string_size > packet->alloced) + { + NET_IncreasePacket(packet); + } + + p = packet->data + packet->len; + + M_StringCopy((char *) p, string, string_size); + + packet->len += string_size; +} + + + + diff --git a/games/NXDoom/src/net_packet.h b/games/NXDoom/src/net_packet.h new file mode 100644 index 00000000000..6beb44b2aac --- /dev/null +++ b/games/NXDoom/src/net_packet.h @@ -0,0 +1,45 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Definitions for use in networking code. +// + +#ifndef NET_PACKET_H +#define NET_PACKET_H + +#include "net_defs.h" + +net_packet_t *NET_NewPacket(int initial_size); +net_packet_t *NET_PacketDup(net_packet_t *packet); +void NET_FreePacket(net_packet_t *packet); + +boolean NET_ReadInt8(net_packet_t *packet, unsigned int *data); +boolean NET_ReadInt16(net_packet_t *packet, unsigned int *data); +boolean NET_ReadInt32(net_packet_t *packet, unsigned int *data); + +boolean NET_ReadSInt8(net_packet_t *packet, signed int *data); +boolean NET_ReadSInt16(net_packet_t *packet, signed int *data); +boolean NET_ReadSInt32(net_packet_t *packet, signed int *data); + +char *NET_ReadString(net_packet_t *packet); +char *NET_ReadSafeString(net_packet_t *packet); + +void NET_WriteInt8(net_packet_t *packet, unsigned int i); +void NET_WriteInt16(net_packet_t *packet, unsigned int i); +void NET_WriteInt32(net_packet_t *packet, unsigned int i); + +void NET_WriteString(net_packet_t *packet, const char *string); + +#endif /* #ifndef NET_PACKET_H */ + diff --git a/games/NXDoom/src/net_petname.c b/games/NXDoom/src/net_petname.c new file mode 100644 index 00000000000..db6600db6a2 --- /dev/null +++ b/games/NXDoom/src/net_petname.c @@ -0,0 +1,118 @@ +// +// Copyright(C) 2019 Jonathan Dowland +// +// 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. +// +// DESCRIPTION: +// Generate a randomized, private, memorable name for a Player +// + +#include +#include +#include "doomtype.h" +#include "m_misc.h" + +static const char * const adjectives [] = { + "Grumpy", + "Ecstatic", + "Surly", + "Prepared", + "Crafty", + "Alert", + "Sluggish", + "Testy", + "Reluctant", + "Languid", + "Passive", + "Pacifist", + "Aggressive", + "Hostile", + "Bubbly", + "Giggly", + "Laughing", + "Crying", + "Frowning", + "Torpid", + "Lethargic", + "Manic", + "Patient", + "Protective", + "Philosophical", + "Enquiring", + "Debating", + "Furious", + "Laid-Back", + "Easy-Going", + "Cromulent", + "Excitable", + "Tired", + "Exhausted", + "Ruminating", + "Redundant", + "Sporty", + "Ginger", + "Scary", + "Posh", + "Baby", +}; + +static const char * const nouns[] = { + "Frad", + // Doom + "Cacodemon", + "Arch-Vile", + "Cyberdemon", + "Imp", + "Demon", + "Mancubus", + "Arachnotron", + "Baron", + "Knight", + "Revenant", + // Hexen + "Ettin", + "Maulotaur", + "Centaur", + "Afrit", + "Serpent", + // Heretic + "Disciple", + "Gargoyle", + "Golem", + "Lich", + // Strife + "Sentinel", + "Acolyte", + "Templar", + "Reaver", + "Spectre", +}; + +/* + * ideally we would export this and the caller would invoke it during + * their setup routine. But, the two callers only invoke getRandomPetName + * once, so the initialization might as well occur then. + */ +static void InitPetName() +{ + srand((unsigned int)time(NULL)); +} + +char *NET_GetRandomPetName() +{ + const char *a, *n; + + InitPetName(); + a = adjectives[rand() % arrlen(adjectives)]; + n = nouns[rand() % arrlen(nouns)]; + + return M_StringJoin(a, " ", n, NULL); +} diff --git a/games/NXDoom/src/net_petname.h b/games/NXDoom/src/net_petname.h new file mode 100644 index 00000000000..29225074402 --- /dev/null +++ b/games/NXDoom/src/net_petname.h @@ -0,0 +1,18 @@ +// +// Copyright(C) 2019 Jonathan Dowland +// +// 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. +// +// DESCRIPTION: +// Generate a randomized, private, memorable name for a Player +// + +char *NET_GetRandomPetName(); diff --git a/games/NXDoom/src/net_query.c b/games/NXDoom/src/net_query.c new file mode 100644 index 00000000000..d9c8b2d96f1 --- /dev/null +++ b/games/NXDoom/src/net_query.c @@ -0,0 +1,1006 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Querying servers to find their current status. +// + +#include +#include +#include +#include + +#include "i_system.h" +#include "i_timer.h" +#include "m_misc.h" + +#include "net_common.h" +#include "net_defs.h" +#include "net_io.h" +#include "net_packet.h" +#include "net_query.h" +#include "net_structrw.h" +#include "net_sdl.h" + +// DNS address of the Internet master server. + +#define MASTER_SERVER_ADDRESS "master.chocolate-doom.org:2342" + +// Time to wait for a response before declaring a timeout. + +#define QUERY_TIMEOUT_SECS 2 + +// Time to wait for secure demo signatures before declaring a timeout. + +#define SIGNATURE_TIMEOUT_SECS 5 + +// Number of query attempts to make before giving up on a server. + +#define QUERY_MAX_ATTEMPTS 3 + +typedef enum +{ + QUERY_TARGET_SERVER, // Normal server target. + QUERY_TARGET_MASTER, // The master server. + QUERY_TARGET_BROADCAST // Send a broadcast query +} query_target_type_t; + +typedef enum +{ + QUERY_TARGET_QUEUED, // Query not yet sent + QUERY_TARGET_QUERIED, // Query sent, waiting response + QUERY_TARGET_RESPONDED, // Response received + QUERY_TARGET_NO_RESPONSE +} query_target_state_t; + +typedef struct +{ + query_target_type_t type; + query_target_state_t state; + net_addr_t *addr; + net_querydata_t data; + unsigned int ping_time; + unsigned int query_time; + unsigned int query_attempts; + boolean printed; +} query_target_t; + +static boolean registered_with_master = false; +static boolean got_master_response = false; + +static net_context_t *query_context; +static query_target_t *targets; +static int num_targets; + +static boolean query_loop_running = false; +static boolean printed_header = false; +static int last_query_time = 0; + +static char *securedemo_start_message = NULL; + +// Resolve the master server address. + +net_addr_t *NET_Query_ResolveMaster(net_context_t *context) +{ + net_addr_t *addr; + + addr = NET_ResolveAddress(context, MASTER_SERVER_ADDRESS); + + if (addr == NULL) + { + fprintf(stderr, "Warning: Failed to resolve address " + "for master server: %s\n", MASTER_SERVER_ADDRESS); + } + + return addr; +} + +// Send a registration packet to the master server to register +// ourselves with the global list. + +void NET_Query_AddToMaster(net_addr_t *master_addr) +{ + net_packet_t *packet; + + packet = NET_NewPacket(10); + NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_ADD); + NET_SendPacket(master_addr, packet); + NET_FreePacket(packet); +} + +// Process a packet received from the master server. + +void NET_Query_AddResponse(net_packet_t *packet) +{ + unsigned int result; + + if (!NET_ReadInt16(packet, &result)) + { + return; + } + + if (result != 0) + { + // Only show the message once. + + if (!registered_with_master) + { + printf("Registered with master server at %s\n", + MASTER_SERVER_ADDRESS); + registered_with_master = true; + } + } + else + { + // Always show rejections. + + printf("Failed to register with master server at %s\n", + MASTER_SERVER_ADDRESS); + } + + got_master_response = true; +} + +boolean NET_Query_CheckAddedToMaster(boolean *result) +{ + // Got response from master yet? + + if (!got_master_response) + { + return false; + } + + *result = registered_with_master; + return true; +} + +// Send a query to the master server. + +static void NET_Query_SendMasterQuery(net_addr_t *addr) +{ + net_packet_t *packet; + + packet = NET_NewPacket(4); + NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_QUERY); + NET_SendPacket(addr, packet); + NET_FreePacket(packet); + + // We also send a NAT_HOLE_PUNCH_ALL packet so that servers behind + // NAT gateways will open themselves up to us. + packet = NET_NewPacket(4); + NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL); + NET_SendPacket(addr, packet); + NET_FreePacket(packet); +} + +// Send a hole punch request to the master server for the server at the +// given address. +void NET_RequestHolePunch(net_context_t *context, net_addr_t *addr) +{ + net_addr_t *master_addr; + net_packet_t *packet; + + master_addr = NET_Query_ResolveMaster(context); + if (master_addr == NULL) + { + return; + } + + packet = NET_NewPacket(32); + NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH); + NET_WriteString(packet, NET_AddrToString(addr)); + NET_SendPacket(master_addr, packet); + + NET_FreePacket(packet); + NET_ReleaseAddress(master_addr); +} + +// Given the specified address, find the target associated. If no +// target is found, and 'create' is true, a new target is created. + +static query_target_t *GetTargetForAddr(net_addr_t *addr, boolean create) +{ + query_target_t *target; + int i; + + for (i=0; itype = QUERY_TARGET_SERVER; + target->state = QUERY_TARGET_QUEUED; + target->printed = false; + target->query_attempts = 0; + target->addr = addr; + NET_ReferenceAddress(addr); + ++num_targets; + + return target; +} + +static void FreeTargets(void) +{ + int i; + + for (i = 0; i < num_targets; ++i) + { + NET_ReleaseAddress(targets[i].addr); + } + free(targets); + targets = NULL; + num_targets = 0; +} + +// Transmit a query packet + +static void NET_Query_SendQuery(net_addr_t *addr) +{ + net_packet_t *request; + + request = NET_NewPacket(10); + NET_WriteInt16(request, NET_PACKET_TYPE_QUERY); + + if (addr == NULL) + { + NET_SendBroadcast(query_context, request); + } + else + { + NET_SendPacket(addr, request); + } + + NET_FreePacket(request); +} + +static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet, + net_query_callback_t callback, + void *user_data) +{ + unsigned int packet_type; + net_querydata_t querydata; + query_target_t *target; + + // Read the header + + if (!NET_ReadInt16(packet, &packet_type) + || packet_type != NET_PACKET_TYPE_QUERY_RESPONSE) + { + return; + } + + // Read query data + + if (!NET_ReadQueryData(packet, &querydata)) + { + return; + } + + // Find the target that responded. + + target = GetTargetForAddr(addr, false); + + // If the target is not found, it may be because we are doing + // a LAN broadcast search, in which case we need to create a + // target for the new responder. + + if (target == NULL) + { + query_target_t *broadcast_target; + + broadcast_target = GetTargetForAddr(NULL, false); + + // Not in broadcast mode, unexpected response that came out + // of nowhere. Ignore. + + if (broadcast_target == NULL + || broadcast_target->state != QUERY_TARGET_QUERIED) + { + return; + } + + // Create new target. + + target = GetTargetForAddr(addr, true); + broadcast_target = GetTargetForAddr(NULL, false); + target->state = QUERY_TARGET_QUERIED; + target->query_time = broadcast_target->query_time; + } + + if (target->state != QUERY_TARGET_RESPONDED) + { + target->state = QUERY_TARGET_RESPONDED; + memcpy(&target->data, &querydata, sizeof(net_querydata_t)); + + // Calculate RTT. + + target->ping_time = I_GetTimeMS() - target->query_time; + + // Invoke callback to signal that we have a new address. + + callback(addr, &target->data, target->ping_time, user_data); + } +} + +// Parse a response packet from the master server. + +static void NET_Query_ParseMasterResponse(net_addr_t *master_addr, + net_packet_t *packet) +{ + unsigned int packet_type; + query_target_t *target; + char *addr_str; + net_addr_t *addr; + + // Read the header. We are only interested in query responses. + + if (!NET_ReadInt16(packet, &packet_type) + || packet_type != NET_MASTER_PACKET_TYPE_QUERY_RESPONSE) + { + return; + } + + // Read a list of strings containing the addresses of servers + // that the master knows about. + + for (;;) + { + addr_str = NET_ReadString(packet); + + if (addr_str == NULL) + { + break; + } + + // Resolve address and add to targets list if it is not already + // there. + + addr = NET_ResolveAddress(query_context, addr_str); + if (addr != NULL) + { + GetTargetForAddr(addr, true); + NET_ReleaseAddress(addr); + } + } + + // Mark the master as having responded. + + target = GetTargetForAddr(master_addr, true); + target->state = QUERY_TARGET_RESPONDED; +} + +static void NET_Query_ParsePacket(net_addr_t *addr, net_packet_t *packet, + net_query_callback_t callback, + void *user_data) +{ + query_target_t *target; + + // This might be the master server responding. + + target = GetTargetForAddr(addr, false); + + if (target != NULL && target->type == QUERY_TARGET_MASTER) + { + NET_Query_ParseMasterResponse(addr, packet); + } + else + { + NET_Query_ParseResponse(addr, packet, callback, user_data); + } +} + +static void NET_Query_GetResponse(net_query_callback_t callback, + void *user_data) +{ + net_addr_t *addr; + net_packet_t *packet; + + if (NET_RecvPacket(query_context, &addr, &packet)) + { + NET_Query_ParsePacket(addr, packet, callback, user_data); + NET_ReleaseAddress(addr); + NET_FreePacket(packet); + } +} + +// Find a target we have not yet queried and send a query. + +static void SendOneQuery(void) +{ + unsigned int now; + unsigned int i; + + now = I_GetTimeMS(); + + // Rate limit - only send one query every 50ms. + + if (now - last_query_time < 50) + { + return; + } + + for (i = 0; i < num_targets; ++i) + { + // Not queried yet? + // Or last query timed out without a response? + + if (targets[i].state == QUERY_TARGET_QUEUED + || (targets[i].state == QUERY_TARGET_QUERIED + && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000)) + { + break; + } + } + + if (i >= num_targets) + { + return; + } + + // Found a target to query. Send a query; how to do this depends on + // the target type. + + switch (targets[i].type) + { + case QUERY_TARGET_SERVER: + NET_Query_SendQuery(targets[i].addr); + break; + + case QUERY_TARGET_BROADCAST: + NET_Query_SendQuery(NULL); + break; + + case QUERY_TARGET_MASTER: + NET_Query_SendMasterQuery(targets[i].addr); + break; + } + + //printf("Queried %s\n", NET_AddrToString(targets[i].addr)); + targets[i].state = QUERY_TARGET_QUERIED; + targets[i].query_time = now; + ++targets[i].query_attempts; + + last_query_time = now; +} + +// Time out servers that have been queried and not responded. + +static void CheckTargetTimeouts(void) +{ + unsigned int i; + unsigned int now; + + now = I_GetTimeMS(); + + for (i = 0; i < num_targets; ++i) + { + /* + printf("target %i: state %i, queries %i, query time %i\n", + i, targets[i].state, targets[i].query_attempts, + now - targets[i].query_time); + */ + + // We declare a target to be "no response" when we've sent + // multiple query packets to it (QUERY_MAX_ATTEMPTS) and + // received no response to any of them. + + if (targets[i].state == QUERY_TARGET_QUERIED + && targets[i].query_attempts >= QUERY_MAX_ATTEMPTS + && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000) + { + targets[i].state = QUERY_TARGET_NO_RESPONSE; + + if (targets[i].type == QUERY_TARGET_MASTER) + { + fprintf(stderr, "NET_MasterQuery: no response " + "from master server.\n"); + } + } + } +} + +// If all targets have responded or timed out, returns true. + +static boolean AllTargetsDone(void) +{ + unsigned int i; + + for (i = 0; i < num_targets; ++i) + { + if (targets[i].state != QUERY_TARGET_RESPONDED + && targets[i].state != QUERY_TARGET_NO_RESPONSE) + { + return false; + } + } + + return true; +} + +// Polling function, invoked periodically to send queries and +// interpret new responses received from remote servers. +// Returns zero when the query sequence has completed and all targets +// have returned responses or timed out. + +int NET_Query_Poll(net_query_callback_t callback, void *user_data) +{ + CheckTargetTimeouts(); + + // Send a query. This will only send a single query at once. + + SendOneQuery(); + + // Check for a response + + NET_Query_GetResponse(callback, user_data); + + return !AllTargetsDone(); +} + +// Stop the query loop + +static void NET_Query_ExitLoop(void) +{ + query_loop_running = false; +} + +// Loop waiting for responses. +// The specified callback is invoked when a new server responds. + +static void NET_Query_QueryLoop(net_query_callback_t callback, void *user_data) +{ + query_loop_running = true; + + while (query_loop_running && NET_Query_Poll(callback, user_data)) + { + // Don't thrash the CPU + + I_Sleep(1); + } +} + +void NET_Query_Init(void) +{ + if (query_context == NULL) + { + query_context = NET_NewContext(); + NET_AddModule(query_context, &net_sdl_module); + net_sdl_module.InitClient(); + } + + free(targets); + targets = NULL; + num_targets = 0; + + printed_header = false; +} + +// Callback that exits the query loop when the first server is found. + +static void NET_Query_ExitCallback(net_addr_t *addr, net_querydata_t *data, + unsigned int ping_time, void *user_data) +{ + NET_Query_ExitLoop(); +} + +// Search the targets list and find a target that has responded. +// If none have responded, returns NULL. + +static query_target_t *FindFirstResponder(void) +{ + unsigned int i; + + for (i = 0; i < num_targets; ++i) + { + if (targets[i].type == QUERY_TARGET_SERVER + && targets[i].state == QUERY_TARGET_RESPONDED) + { + return &targets[i]; + } + } + + return NULL; +} + +// Return a count of the number of responses. + +static int GetNumResponses(void) +{ + unsigned int i; + int result; + + result = 0; + + for (i = 0; i < num_targets; ++i) + { + if (targets[i].type == QUERY_TARGET_SERVER + && targets[i].state == QUERY_TARGET_RESPONDED) + { + ++result; + } + } + + return result; +} + +int NET_StartLANQuery(void) +{ + query_target_t *target; + + NET_Query_Init(); + + // Add a broadcast target to the list. + + target = GetTargetForAddr(NULL, true); + target->type = QUERY_TARGET_BROADCAST; + + return 1; +} + +int NET_StartMasterQuery(void) +{ + net_addr_t *master; + query_target_t *target; + + NET_Query_Init(); + + // Resolve master address and add to targets list. + + master = NET_Query_ResolveMaster(query_context); + + if (master == NULL) + { + return 0; + } + + target = GetTargetForAddr(master, true); + target->type = QUERY_TARGET_MASTER; + NET_ReleaseAddress(master); + + return 1; +} + +// ----------------------------------------------------------------------- + +static void formatted_printf(int wide, const char *s, ...) PRINTF_ATTR(2, 3); +static void formatted_printf(int wide, const char *s, ...) +{ + va_list args; + int i; + + va_start(args, s); + i = vprintf(s, args); + va_end(args); + + while (i < wide) + { + putchar(' '); + ++i; + } +} + +static const char *GameDescription(GameMode_t mode, GameMission_t mission) +{ + switch (mission) + { + case doom: + if (mode == shareware) + return "swdoom"; + else if (mode == registered) + return "regdoom"; + else if (mode == retail) + return "ultdoom"; + else + return "doom"; + case doom2: + return "doom2"; + case pack_tnt: + return "tnt"; + case pack_plut: + return "plutonia"; + case pack_chex: + return "chex"; + case pack_hacx: + return "hacx"; + case heretic: + return "heretic"; + case hexen: + return "hexen"; + case strife: + return "strife"; + default: + return "?"; + } +} + +static void PrintHeader(void) +{ + int i; + + putchar('\n'); + formatted_printf(5, "Ping"); + formatted_printf(18, "Address"); + formatted_printf(8, "Players"); + puts("Description"); + + for (i=0; i<70; ++i) + putchar('='); + putchar('\n'); +} + +// Callback function that just prints information in a table. + +static void NET_QueryPrintCallback(net_addr_t *addr, + net_querydata_t *data, + unsigned int ping_time, + void *user_data) +{ + // If this is the first server, print the header. + + if (!printed_header) + { + PrintHeader(); + printed_header = true; + } + + formatted_printf(5, "%4i", ping_time); + formatted_printf(22, "%s", NET_AddrToString(addr)); + formatted_printf(4, "%i/%i ", data->num_players, + data->max_players); + + if (data->gamemode != indetermined) + { + printf("(%s) ", GameDescription(data->gamemode, + data->gamemission)); + } + + if (data->server_state) + { + printf("(game running) "); + } + + printf("%s\n", data->description); +} + +void NET_LANQuery(void) +{ + if (NET_StartLANQuery()) + { + printf("\nSearching for servers on local LAN ...\n"); + + NET_Query_QueryLoop(NET_QueryPrintCallback, NULL); + + printf("\n%i server(s) found.\n", GetNumResponses()); + FreeTargets(); + } +} + +void NET_MasterQuery(void) +{ + if (NET_StartMasterQuery()) + { + printf("\nSearching for servers on Internet ...\n"); + + NET_Query_QueryLoop(NET_QueryPrintCallback, NULL); + + printf("\n%i server(s) found.\n", GetNumResponses()); + FreeTargets(); + } +} + +void NET_QueryAddress(const char *addr_str) +{ + net_addr_t *addr; + query_target_t *target; + + NET_Query_Init(); + + addr = NET_ResolveAddress(query_context, addr_str); + + if (addr == NULL) + { + I_Error("NET_QueryAddress: Host '%s' not found!", addr_str); + } + + // Add the address to the list of targets. + + target = GetTargetForAddr(addr, true); + + printf("\nQuerying '%s'...\n", addr_str); + + // Run query loop. + + NET_Query_QueryLoop(NET_Query_ExitCallback, NULL); + + // Check if the target responded. + + if (target->state == QUERY_TARGET_RESPONDED) + { + NET_QueryPrintCallback(addr, &target->data, target->ping_time, NULL); + NET_ReleaseAddress(addr); + FreeTargets(); + } + else + { + I_Error("No response from '%s'", addr_str); + } +} + +net_addr_t *NET_FindLANServer(void) +{ + query_target_t *target; + query_target_t *responder; + net_addr_t *result; + + NET_Query_Init(); + + // Add a broadcast target to the list. + + target = GetTargetForAddr(NULL, true); + target->type = QUERY_TARGET_BROADCAST; + + // Run the query loop, and stop at the first target found. + + NET_Query_QueryLoop(NET_Query_ExitCallback, NULL); + + responder = FindFirstResponder(); + + if (responder != NULL) + { + result = responder->addr; + NET_ReferenceAddress(result); + } + else + { + result = NULL; + } + + FreeTargets(); + return result; +} + +// Block until a packet of the given type is received from the given +// address. + +static net_packet_t *BlockForPacket(net_addr_t *addr, unsigned int packet_type, + unsigned int timeout_ms) +{ + net_packet_t *packet; + net_addr_t *packet_src; + unsigned int read_packet_type; + unsigned int start_time; + + start_time = I_GetTimeMS(); + + while (I_GetTimeMS() < start_time + timeout_ms) + { + if (!NET_RecvPacket(query_context, &packet_src, &packet)) + { + I_Sleep(20); + continue; + } + + // Caller doesn't need additional reference. + NET_ReleaseAddress(packet_src); + + if (packet_src == addr + && NET_ReadInt16(packet, &read_packet_type) + && packet_type == read_packet_type) + { + return packet; + } + + NET_FreePacket(packet); + } + + // Timeout - no response. + + return NULL; +} + +// Query master server for secure demo start seed value. + +boolean NET_StartSecureDemo(prng_seed_t seed) +{ + net_packet_t *request, *response; + net_addr_t *master_addr; + char *signature; + boolean result; + + NET_Query_Init(); + master_addr = NET_Query_ResolveMaster(query_context); + + // Send request packet to master server. + + request = NET_NewPacket(10); + NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_START); + NET_SendPacket(master_addr, request); + NET_FreePacket(request); + + // Block for response and read contents. + // The signed start message will be saved for later. + + response = BlockForPacket(master_addr, + NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, + SIGNATURE_TIMEOUT_SECS * 1000); + + result = false; + + if (response != NULL) + { + if (NET_ReadPRNGSeed(response, seed)) + { + signature = NET_ReadString(response); + + if (signature != NULL) + { + securedemo_start_message = M_StringDuplicate(signature); + result = true; + } + } + + NET_FreePacket(response); + } + + return result; +} + +// Query master server for secure demo end signature. + +char *NET_EndSecureDemo(sha1_digest_t demo_hash) +{ + net_packet_t *request, *response; + net_addr_t *master_addr; + char *signature; + + master_addr = NET_Query_ResolveMaster(query_context); + + // Construct end request and send to master server. + + request = NET_NewPacket(10); + NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_END); + NET_WriteSHA1Sum(request, demo_hash); + NET_WriteString(request, securedemo_start_message); + NET_SendPacket(master_addr, request); + NET_FreePacket(request); + + // Block for response. The response packet simply contains a string + // with the ASCII signature. + + response = BlockForPacket(master_addr, + NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, + SIGNATURE_TIMEOUT_SECS * 1000); + + if (response == NULL) + { + return NULL; + } + + signature = NET_ReadString(response); + + NET_FreePacket(response); + + return signature; +} + diff --git a/games/NXDoom/src/net_query.h b/games/NXDoom/src/net_query.h new file mode 100644 index 00000000000..e0c9e9bef2d --- /dev/null +++ b/games/NXDoom/src/net_query.h @@ -0,0 +1,45 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Querying servers to find their current status. +// + +#ifndef NET_QUERY_H +#define NET_QUERY_H + +#include "net_defs.h" + +typedef void (*net_query_callback_t)(net_addr_t *addr, + net_querydata_t *querydata, + unsigned int ping_time, + void *user_data); + +extern int NET_StartLANQuery(void); +extern int NET_StartMasterQuery(void); + +extern void NET_LANQuery(void); +extern void NET_MasterQuery(void); +extern void NET_QueryAddress(const char *addr); +extern net_addr_t *NET_FindLANServer(void); + +extern int NET_Query_Poll(net_query_callback_t callback, void *user_data); + +extern net_addr_t *NET_Query_ResolveMaster(net_context_t *context); +extern void NET_Query_AddToMaster(net_addr_t *master_addr); +extern boolean NET_Query_CheckAddedToMaster(boolean *result); +extern void NET_Query_AddResponse(net_packet_t *packet); +extern void NET_RequestHolePunch(net_context_t *context, net_addr_t *addr); + +#endif /* #ifndef NET_QUERY_H */ + diff --git a/games/NXDoom/src/net_sdl.c b/games/NXDoom/src/net_sdl.c new file mode 100644 index 00000000000..2965f42340b --- /dev/null +++ b/games/NXDoom/src/net_sdl.c @@ -0,0 +1,441 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Networking module which uses SDL_net +// + +#include +#include +#include + +#include "doomtype.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_misc.h" +#include "net_defs.h" +#include "net_io.h" +#include "net_packet.h" +#include "net_sdl.h" +#include "z_zone.h" + +// +// NETWORKING +// + + +#ifndef DISABLE_SDL2NET + + +#include + +#define DEFAULT_PORT 2342 + +static boolean initted = false; +static int port = DEFAULT_PORT; +static UDPsocket udpsocket; +static UDPpacket *recvpacket; + +typedef struct +{ + net_addr_t net_addr; + IPaddress sdl_addr; +} addrpair_t; + +static addrpair_t **addr_table; +static int addr_table_size = -1; + +// Initializes the address table + +static void NET_SDL_InitAddrTable(void) +{ + addr_table_size = 16; + + addr_table = Z_Malloc(sizeof(addrpair_t *) * addr_table_size, + PU_STATIC, 0); + memset(addr_table, 0, sizeof(addrpair_t *) * addr_table_size); +} + +static boolean AddressesEqual(IPaddress *a, IPaddress *b) +{ + return a->host == b->host + && a->port == b->port; +} + +// Finds an address by searching the table. If the address is not found, +// it is added to the table. + +static net_addr_t *NET_SDL_FindAddress(IPaddress *addr) +{ + addrpair_t *new_entry; + int empty_entry = -1; + int i; + + if (addr_table_size < 0) + { + NET_SDL_InitAddrTable(); + } + + for (i=0; isdl_addr)) + { + return &addr_table[i]->net_addr; + } + + if (empty_entry < 0 && addr_table[i] == NULL) + empty_entry = i; + } + + // Was not found in list. We need to add it. + + // Is there any space in the table? If not, increase the table size + + if (empty_entry < 0) + { + addrpair_t **new_addr_table; + int new_addr_table_size; + + // after reallocing, we will add this in as the first entry + // in the new block of memory + + empty_entry = addr_table_size; + + // allocate a new array twice the size, init to 0 and copy + // the existing table in. replace the old table. + + new_addr_table_size = addr_table_size * 2; + new_addr_table = Z_Malloc(sizeof(addrpair_t *) * new_addr_table_size, + PU_STATIC, 0); + memset(new_addr_table, 0, sizeof(addrpair_t *) * new_addr_table_size); + memcpy(new_addr_table, addr_table, + sizeof(addrpair_t *) * addr_table_size); + Z_Free(addr_table); + addr_table = new_addr_table; + addr_table_size = new_addr_table_size; + } + + // Add a new entry + + new_entry = Z_Malloc(sizeof(addrpair_t), PU_STATIC, 0); + + new_entry->sdl_addr = *addr; + new_entry->net_addr.refcount = 0; + new_entry->net_addr.handle = &new_entry->sdl_addr; + new_entry->net_addr.module = &net_sdl_module; + + addr_table[empty_entry] = new_entry; + + return &new_entry->net_addr; +} + +static void NET_SDL_FreeAddress(net_addr_t *addr) +{ + int i; + + for (i=0; inet_addr) + { + Z_Free(addr_table[i]); + addr_table[i] = NULL; + return; + } + } + + I_Error("NET_SDL_FreeAddress: Attempted to remove an unused address!"); +} + +static boolean NET_SDL_InitClient(void) +{ + int p; + + if (initted) + return true; + + //! + // @category net + // @arg + // + // Use the specified UDP port for communications, instead of + // the default (2342). + // + + p = M_CheckParmWithArgs("-port", 1); + if (p > 0) + port = atoi(myargv[p+1]); + + SDLNet_Init(); + + udpsocket = SDLNet_UDP_Open(0); + + if (udpsocket == NULL) + { + I_Error("NET_SDL_InitClient: Unable to open a socket!"); + } + + recvpacket = SDLNet_AllocPacket(1500); + +#ifdef DROP_PACKETS + srand(time(NULL)); +#endif + + initted = true; + + return true; +} + +static boolean NET_SDL_InitServer(void) +{ + int p; + + if (initted) + return true; + + p = M_CheckParmWithArgs("-port", 1); + if (p > 0) + port = atoi(myargv[p+1]); + + SDLNet_Init(); + + udpsocket = SDLNet_UDP_Open(port); + + if (udpsocket == NULL) + { + I_Error("NET_SDL_InitServer: Unable to bind to port %i", port); + } + + recvpacket = SDLNet_AllocPacket(1500); +#ifdef DROP_PACKETS + srand(time(NULL)); +#endif + + initted = true; + + return true; +} + +static void NET_SDL_SendPacket(net_addr_t *addr, net_packet_t *packet) +{ + UDPpacket sdl_packet; + IPaddress ip; + + if (addr == &net_broadcast_addr) + { + SDLNet_ResolveHost(&ip, NULL, port); + ip.host = INADDR_BROADCAST; + } + else + { + ip = *((IPaddress *) addr->handle); + } + +#if 0 + { + static int this_second_sent = 0; + static int lasttime; + + this_second_sent += packet->len + 64; + + if (I_GetTime() - lasttime > TICRATE) + { + printf("%i bytes sent in the last second\n", this_second_sent); + lasttime = I_GetTime(); + this_second_sent = 0; + } + } +#endif + +#ifdef DROP_PACKETS + if ((rand() % 4) == 0) + return; +#endif + + sdl_packet.channel = 0; + sdl_packet.data = packet->data; + sdl_packet.len = packet->len; + sdl_packet.address = ip; + + if (!SDLNet_UDP_Send(udpsocket, -1, &sdl_packet)) + { + I_Error("NET_SDL_SendPacket: Error transmitting packet: %s", + SDLNet_GetError()); + } +} + +static boolean NET_SDL_RecvPacket(net_addr_t **addr, net_packet_t **packet) +{ + int result; + + result = SDLNet_UDP_Recv(udpsocket, recvpacket); + + if (result < 0) + { + I_Error("NET_SDL_RecvPacket: Error receiving packet: %s", + SDLNet_GetError()); + } + + // no packets received + + if (result == 0) + return false; + + // Put the data into a new packet structure + + *packet = NET_NewPacket(recvpacket->len); + memcpy((*packet)->data, recvpacket->data, recvpacket->len); + (*packet)->len = recvpacket->len; + + // Address + + *addr = NET_SDL_FindAddress(&recvpacket->address); + + return true; +} + +void NET_SDL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +{ + IPaddress *ip; + uint32_t host; + uint16_t port; + + ip = (IPaddress *) addr->handle; + host = SDLNet_Read32(&ip->host); + port = SDLNet_Read16(&ip->port); + + M_snprintf(buffer, buffer_len, "%i.%i.%i.%i", + (host >> 24) & 0xff, (host >> 16) & 0xff, + (host >> 8) & 0xff, host & 0xff); + + // If we are using the default port we just need to show the IP address, + // but otherwise we need to include the port. This is important because + // we use the string representation in the setup tool to provided an + // address to connect to. + if (port != DEFAULT_PORT) + { + char portbuf[10]; + M_snprintf(portbuf, sizeof(portbuf), ":%i", port); + M_StringConcat(buffer, portbuf, buffer_len); + } +} + +net_addr_t *NET_SDL_ResolveAddress(const char *address) +{ + IPaddress ip; + char *addr_hostname; + int addr_port; + int result; + char *colon; + + colon = strchr(address, ':'); + + addr_hostname = M_StringDuplicate(address); + if (colon != NULL) + { + addr_hostname[colon - address] = '\0'; + addr_port = atoi(colon + 1); + } + else + { + addr_port = port; + } + + result = SDLNet_ResolveHost(&ip, addr_hostname, addr_port); + + free(addr_hostname); + + if (result) + { + // unable to resolve + + return NULL; + } + else + { + return NET_SDL_FindAddress(&ip); + } +} + +// Complete module + +net_module_t net_sdl_module = +{ + NET_SDL_InitClient, + NET_SDL_InitServer, + NET_SDL_SendPacket, + NET_SDL_RecvPacket, + NET_SDL_AddrToString, + NET_SDL_FreeAddress, + NET_SDL_ResolveAddress, +}; + + +#else // DISABLE_SDL2NET + +// no-op implementation + + +static boolean NET_NULL_InitClient(void) +{ + return false; +} + + +static boolean NET_NULL_InitServer(void) +{ + return false; +} + + +static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet) +{ +} + + +static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet) +{ + return false; +} + + +static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +{ + +} + + +static void NET_NULL_FreeAddress(net_addr_t *addr) +{ +} + + +net_addr_t *NET_NULL_ResolveAddress(const char *address) +{ + return NULL; +} + + +net_module_t net_sdl_module = +{ + NET_NULL_InitClient, + NET_NULL_InitServer, + NET_NULL_SendPacket, + NET_NULL_RecvPacket, + NET_NULL_AddrToString, + NET_NULL_FreeAddress, + NET_NULL_ResolveAddress, +}; + + +#endif // DISABLE_SDL2NET diff --git a/games/NXDoom/src/net_sdl.h b/games/NXDoom/src/net_sdl.h new file mode 100644 index 00000000000..c249de1c490 --- /dev/null +++ b/games/NXDoom/src/net_sdl.h @@ -0,0 +1,26 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Networking module which uses SDL_net +// + +#ifndef NET_SDL_H +#define NET_SDL_H + +#include "net_defs.h" + +extern net_module_t net_sdl_module; + +#endif /* #ifndef NET_SDL_H */ + diff --git a/games/NXDoom/src/net_server.c b/games/NXDoom/src/net_server.c new file mode 100644 index 00000000000..9374b64ec71 --- /dev/null +++ b/games/NXDoom/src/net_server.c @@ -0,0 +1,2097 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Network server code +// + +#include +#include +#include +#include + +#include "config.h" + +#include "doomtype.h" +#include "d_mode.h" +#include "i_system.h" +#include "i_timer.h" +#include "m_argv.h" +#include "m_misc.h" + +#include "net_client.h" +#include "net_common.h" +#include "net_defs.h" +#include "net_io.h" +#include "net_loop.h" +#include "net_packet.h" +#include "net_query.h" +#include "net_server.h" +#include "net_sdl.h" +#include "net_structrw.h" + +// How often to refresh our registration with the master server. +#define MASTER_REFRESH_PERIOD 30 /* twice per minute */ + +// How often to re-resolve the address of the master server? +#define MASTER_RESOLVE_PERIOD 8 * 60 * 60 /* 8 hours */ + +typedef enum +{ + // waiting for the game to be "launched" (key player to press the start + // button) + + SERVER_WAITING_LAUNCH, + + // game has been launched, we are waiting for all players to be ready + // so the game can start. + + SERVER_WAITING_START, + + // in a game + + SERVER_IN_GAME, +} net_server_state_t; + +typedef struct +{ + boolean active; + int player_number; + net_addr_t *addr; + net_connection_t connection; + int last_send_time; + char *name; + + // If true, the client has sent the NET_PACKET_TYPE_GAMESTART + // message indicating that it is ready for the game to start. + + boolean ready; + + // Time that this client connected to the server. + // This is used to determine the controller (oldest client). + + unsigned int connect_time; + + // Last time new gamedata was received from this client + + int last_gamedata_time; + + // recording a demo without -longtics + + boolean recording_lowres; + + // send queue: items to send to the client + // this is a circular buffer + + int sendseq; + net_full_ticcmd_t sendqueue[BACKUPTICS]; + + // Latest acknowledged by the client + + unsigned int acknowledged; + + // Value of max_players specified by the client on connect. + + int max_players; + + // Observer: receives data but does not participate in the game. + + boolean drone; + + // SHA1 hash sums of the client's WAD directory and dehacked data + + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; + + // Is this client is playing with the Freedoom IWAD? + + unsigned int is_freedoom; + + // Player class (for Hexen) + + int player_class; + +} net_client_t; + +// structure used for the recv window + +typedef struct +{ + // Whether this tic has been received yet + + boolean active; + + // Latency value received from the client + + signed int latency; + + // Last time we sent a resend request for this tic + + unsigned int resend_time; + + // Tic data itself + + net_ticdiff_t diff; +} net_client_recv_t; + +static net_server_state_t server_state; +static boolean server_initialized = false; +static net_client_t clients[MAXNETNODES]; +static net_client_t *sv_players[NET_MAXPLAYERS]; +static net_context_t *server_context; +static unsigned int sv_gamemode; +static unsigned int sv_gamemission; +static net_gamesettings_t sv_settings; + +// For registration with master server: + +static net_addr_t *master_server = NULL; +static unsigned int master_refresh_time; +static unsigned int master_resolve_time; + +// receive window + +static unsigned int recvwindow_start; +static net_client_recv_t recvwindow[BACKUPTICS][NET_MAXPLAYERS]; + +#define NET_SV_ExpandTicNum(b) NET_ExpandTicNum(recvwindow_start, (b)) + +static void NET_SV_DisconnectClient(net_client_t *client) +{ + if (client->active) + { + NET_Conn_Disconnect(&client->connection); + } +} + +static boolean ClientConnected(net_client_t *client) +{ + // Check that the client is properly connected: ie. not in the + // process of connecting or disconnecting + + return client->active + && client->connection.state == NET_CONN_STATE_CONNECTED; +} + +// Send a message to be displayed on a client's console + +static void NET_SV_SendConsoleMessage(net_client_t *client, const char *s, ...) PRINTF_ATTR(2, 3); +static void NET_SV_SendConsoleMessage(net_client_t *client, const char *s, ...) +{ + char buf[1024]; + va_list args; + net_packet_t *packet; + + va_start(args, s); + M_vsnprintf(buf, sizeof(buf), s, args); + va_end(args); + + packet = NET_Conn_NewReliable(&client->connection, + NET_PACKET_TYPE_CONSOLE_MESSAGE); + + NET_WriteString(packet, buf); +} + +// Send a message to all clients + +static void NET_SV_BroadcastMessage(const char *s, ...) PRINTF_ATTR(1, 2); +static void NET_SV_BroadcastMessage(const char *s, ...) +{ + char buf[1024]; + va_list args; + int i; + + va_start(args, s); + M_vsnprintf(buf, sizeof(buf), s, args); + va_end(args); + + for (i=0; iplayer_number = pl; + ++pl; + } + else + { + clients[i].player_number = -1; + } + } + } + + for (; plconnect_time) + { + best = &clients[i]; + } + } + + return best; +} + +typedef enum +{ + RANGE_LOCALHOST, // Same process or 127.x + RANGE_PRIVATE, // RFC 1918 + RANGE_PUBLIC, // The public Internet +} ip_range_t; + +static ip_range_t ClientAddressRange(const char *addr) +{ + if (!strcmp(addr, "local client") + || M_StringStartsWith(addr, "127.")) + { + return RANGE_LOCALHOST; + } + if (M_StringStartsWith(addr, "10.") + || M_StringStartsWith(addr, "192.168.")) + { + return RANGE_PRIVATE; + } + return RANGE_PUBLIC; +} + +static void NET_SV_SendWaitingData(net_client_t *client) +{ + net_waitdata_t wait_data; + net_packet_t *packet; + net_client_t *controller; + ip_range_t client_range, player_range; + const char *addr; + int i; + + NET_SV_AssignPlayers(); + + controller = NET_SV_Controller(); + + wait_data.num_players = NET_SV_NumPlayers(); + wait_data.num_drones = NET_SV_NumDrones(); + wait_data.ready_players = NET_SV_NumReadyPlayers(); + wait_data.max_players = NET_SV_MaxPlayers(); + wait_data.is_controller = (client == controller); + wait_data.consoleplayer = client->player_number; + + // Send the WAD and dehacked checksums of the controlling client. + // If no controller found (?), send the details that the client + // is expecting anyway. + + if (controller == NULL) + { + controller = client; + } + + memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, + sizeof(sha1_digest_t)); + memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, + sizeof(sha1_digest_t)); + wait_data.is_freedoom = controller->is_freedoom; + + // We only send IP addresses to locally-connected clients (including + // the 127.* loopback range): + addr = NET_AddrToString(client->connection.addr); + client_range = ClientAddressRange(addr); + + // set name and address of each player: + + for (i = 0; i < wait_data.num_players; ++i) + { + M_StringCopy(wait_data.player_names[i], + sv_players[i]->name, + MAXPLAYERNAME); + + // For privacy, only local clients or those on a LAN get to see + // addresses. Public clients only get to see their own address, + // though we do reveal localhost addresses since they're harmless, + // and we do reveal when a client is connected via LAN. + addr = NET_AddrToString(sv_players[i]->addr); + player_range = ClientAddressRange(addr); + if (client_range == RANGE_LOCALHOST || client_range == RANGE_PRIVATE + || i == wait_data.consoleplayer || player_range == RANGE_LOCALHOST) + { + M_StringCopy(wait_data.player_addrs[i], addr, MAXPLAYERNAME); + } + else if (player_range == RANGE_PRIVATE) + { + M_snprintf(wait_data.player_addrs[i], MAXPLAYERNAME, + "[LAN player]"); + } + else + { + M_snprintf(wait_data.player_addrs[i], MAXPLAYERNAME, + "[address hidden]"); + } + } + + // Construct packet: + + packet = NET_NewPacket(10); + NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); + NET_WriteWaitData(packet, &wait_data); + + // Send packet to client and free + + NET_Conn_SendPacket(&client->connection, packet); + NET_FreePacket(packet); +} + +// Find the latest tic which has been acknowledged as received by +// all clients. + +static unsigned int NET_SV_LatestAcknowledged(void) +{ + unsigned int lowtic = UINT_MAX; + int i; + + for (i=0; iactive = true; + client->connect_time = I_GetTimeMS(); + NET_Conn_InitServer(&client->connection, addr, protocol); + client->addr = addr; + NET_ReferenceAddress(addr); + client->last_send_time = -1; + + // init the ticcmd send queue + + client->sendseq = 0; + client->acknowledged = 0; + client->drone = false; + client->ready = false; + + client->last_gamedata_time = 0; + + memset(client->sendqueue, 0xff, sizeof(client->sendqueue)); + + NET_Log("server: initialized new client from %s", NET_AddrToString(addr)); +} + +// parse a SYN from a client(initiating a connection) + +static void NET_SV_ParseSYN(net_packet_t *packet, net_client_t *client, + net_addr_t *addr) +{ + unsigned int magic; + net_connect_data_t data; + net_packet_t *reply; + net_protocol_t protocol; + char *player_name; + char *client_version; + int num_players; + int i; + + NET_Log("server: processing SYN packet"); + + // Read the magic number and check it is the expected one. + if (!NET_ReadInt32(packet, &magic)) + { + NET_Log("server: error: no magic number for SYN"); + return; + } + + switch (magic) + { + case NET_MAGIC_NUMBER: + break; + + case NET_OLD_MAGIC_NUMBER: + NET_Log("server: error: client using old magic number: %d", magic); + NET_SV_SendReject(addr, + "You are using an old client version that is not supported by " + "this server. This server is running " PACKAGE_STRING "."); + return; + + default: + NET_Log("server: error: wrong magic number: %d", magic); + return; + } + + // Read the client version string. We actually now only use this when + // sending a reject message, as we only reject if we can't negotiate a + // common protocol (below). + client_version = NET_ReadString(packet); + if (client_version == NULL) + { + NET_Log("server: error: no version from client"); + return; + } + + // Read the client's list of accepted protocols. Net play between forks + // of Chocolate Doom is accepted provided that they can negotiate a + // common accepted protocol. + protocol = NET_ReadProtocolList(packet); + if (protocol == NET_PROTOCOL_UNKNOWN) + { + char reject_msg[256]; + + M_snprintf(reject_msg, sizeof(reject_msg), + "Version mismatch: server version is: " PACKAGE_STRING "; " + "client is: %s. No common compatible protocol could be " + "negotiated.", client_version); + NET_SV_SendReject(addr, reject_msg); + NET_Log("server: error: no common protocol"); + return; + } + + // Read connect data, and check that the game mode/mission are valid + // and the max_players value is in a sensible range. + if (!NET_ReadConnectData(packet, &data)) + { + NET_Log("server: error: failed to read connect data"); + return; + } + + if (!D_ValidGameMode(data.gamemission, data.gamemode) + || data.max_players > NET_MAXPLAYERS) + { + NET_Log("server: error: invalid connect data, max_players=%d, " + "gamemission=%d, gamemode=%d", + data.max_players, data.gamemission, data.gamemode); + return; + } + + // Read the player's name + player_name = NET_ReadString(packet); + if (player_name == NULL) + { + NET_Log("server: error: failed to read player name"); + return; + } + + // At this point we have received a valid SYN. + + // Not accepting new connections? + if (server_state != SERVER_WAITING_LAUNCH) + { + NET_Log("server: error: not in waiting launch state, server_state=%d", + server_state); + NET_SV_SendReject(addr, + "Server is not currently accepting connections"); + return; + } + + // Before accepting a new client, check that there is a slot free. + NET_SV_AssignPlayers(); + num_players = NET_SV_NumPlayers(); + + if ((!data.drone && num_players >= NET_SV_MaxPlayers()) + || NET_SV_NumClients() >= MAXNETNODES) + { + NET_Log("server: no more players, num_players=%d, max=%d", + num_players, NET_SV_MaxPlayers()); + NET_SV_SendReject(addr, "Server is full!"); + return; + } + + // TODO: Add server option to allow rejecting clients which set + // lowres_turn. This is potentially desirable as the presence of such + // clients affects turning resolution. + + // Adopt the game mode and mission of the first connecting client: + if (num_players == 0 && !data.drone) + { + sv_gamemode = data.gamemode; + sv_gamemission = data.gamemission; + NET_Log("server: new game, mode=%d, mission=%d", + sv_gamemode, sv_gamemission); + } + + // Check the connecting client is playing the same game as all + // the other clients + if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission) + { + char msg[128]; + NET_Log("server: wrong mode/mission, %d != %d || %d != %d", + data.gamemode, sv_gamemode, data.gamemission, sv_gamemission); + M_snprintf(msg, sizeof(msg), + "Game mismatch: server is %s (%s), client is %s (%s)", + D_GameMissionString(sv_gamemission), + D_GameModeString(sv_gamemode), + D_GameMissionString(data.gamemission), + D_GameModeString(data.gamemode)); + + NET_SV_SendReject(addr, msg); + return; + } + + // Allocate a client slot if there isn't one already + if (client == NULL) + { + // find a slot, or return if none found + + for (i=0; iconnection.state == NET_CONN_STATE_DISCONNECTED) + { + client->active = false; + } + } + + // Client already connected? + if (client->active) + { + NET_Log("server: client is already initialized (duplicate SYN?)"); + return; + } + + // Activate, initialize connection + NET_SV_InitNewClient(client, addr, protocol); + + // Save the SHA1 checksums and other details. + memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t)); + memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t)); + client->is_freedoom = data.is_freedoom; + client->max_players = data.max_players; + client->name = M_StringDuplicate(player_name); + client->recording_lowres = data.lowres_turn; + client->drone = data.drone; + client->player_class = data.player_class; + + // Send a reply back to the client, indicating a successful connection + // and specifying the protocol that will be used for communications. + reply = NET_Conn_NewReliable(&client->connection, NET_PACKET_TYPE_SYN); + NET_WriteString(reply, PACKAGE_STRING); + NET_WriteProtocol(reply, protocol); +} + +// Parse a launch packet. This is sent by the key player when the "start" +// button is pressed, and causes the startup process to continue. + +static void NET_SV_ParseLaunch(net_packet_t *packet, net_client_t *client) +{ + net_packet_t *launchpacket; + int num_players; + unsigned int i; + + NET_Log("server: processing launch packet"); + + // Only the controller can launch the game. + + if (client != NET_SV_Controller()) + { + NET_Log("server: error: this client isn't the controller, %d != %d", + client, NET_SV_Controller()); + return; + } + + // Can only launch when we are in the waiting state. + + if (server_state != SERVER_WAITING_LAUNCH) + { + NET_Log("server: error: not in waiting launch state, state=%d", + server_state); + return; + } + + // Forward launch on to all clients. + NET_Log("server: sending launch to all clients"); + NET_SV_AssignPlayers(); + num_players = NET_SV_NumPlayers(); + + for (i=0; irecording_lowres) + { + sv_settings.lowres_turn = true; + } + } + + sv_settings.num_players = NET_SV_NumPlayers(); + + // Copy player classes: + + for (i = 0; i < NET_MAXPLAYERS; ++i) + { + if (sv_players[i] != NULL) + { + sv_settings.player_classes[i] = sv_players[i]->player_class; + } + else + { + sv_settings.player_classes[i] = 0; + } + } + + nowtime = I_GetTimeMS(); + + // Send start packets to each connected node + + for (i = 0; i < MAXNETNODES; ++i) + { + if (!ClientConnected(&clients[i])) + continue; + + clients[i].last_gamedata_time = nowtime; + + startpacket = NET_Conn_NewReliable(&clients[i].connection, + NET_PACKET_TYPE_GAMESTART); + + sv_settings.consoleplayer = clients[i].player_number; + + NET_WriteSettings(startpacket, &sv_settings); + } + + // Change server state + NET_Log("server: beginning game state"); + server_state = SERVER_IN_GAME; + + memset(recvwindow, 0, sizeof(recvwindow)); + recvwindow_start = 0; +} + +// Returns true when all nodes have indicated readiness to start the game. + +static boolean AllNodesReady(void) +{ + unsigned int i; + + for (i = 0; i < MAXNETNODES; ++i) + { + if (ClientConnected(&clients[i]) && !clients[i].ready) + { + return false; + } + } + + return true; +} + +// Check if the game should start, and if so, start it. + +static void CheckStartGame(void) +{ + if (!AllNodesReady()) + { + NET_Log("server: not all clients ready to start yet"); + return; + } + + NET_Log("server: all clients ready, starting game"); + StartGame(); +} + +// Send waiting data with current status to all nodes that are ready to +// start the game. + +static void SendAllWaitingData(void) +{ + unsigned int i; + + for (i = 0; i < MAXNETNODES; ++i) + { + if (ClientConnected(&clients[i]) && clients[i].ready) + { + NET_SV_SendWaitingData(&clients[i]); + } + } +} + +// Parse a game start packet + +static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) +{ + net_gamesettings_t settings; + + NET_Log("server: processing game start packet"); + + // Can only start a game if we are in the waiting start state. + + if (server_state != SERVER_WAITING_START) + { + NET_Log("server: error: not in waiting start state, server_state=%d", + server_state); + return; + } + + if (client == NET_SV_Controller()) + { + if (!NET_ReadSettings(packet, &settings)) + { + // Malformed packet + NET_Log("server: error: no settings from controller"); + return; + } + + // Check the game settings are valid + + if (!NET_ValidGameSettings(sv_gamemode, sv_gamemission, &settings)) + { + NET_Log("server: error: invalid game settings"); + return; + } + + sv_settings = settings; + } + + client->ready = true; + + CheckStartGame(); + + // Update all ready clients with the current state (number of players + // ready, etc.). This is used by games that show startup progress + // (eg. Hexen's spinal loading) + + SendAllWaitingData(); +} + +// Send a resend request to a client + +static void NET_SV_SendResendRequest(net_client_t *client, int start, int end) +{ + net_packet_t *packet; + net_client_recv_t *recvobj; + int i; + unsigned int nowtime; + int index; + + NET_Log("server: send resend to %s for tics %d-%d", + NET_AddrToString(client->addr), start, end); + + packet = NET_NewPacket(20); + + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); + NET_WriteInt32(packet, start); + NET_WriteInt8(packet, end - start + 1); + + NET_Conn_SendPacket(&client->connection, packet); + NET_FreePacket(packet); + + // Store the time we send the resend request + + nowtime = I_GetTimeMS(); + + for (i=start; i<=end; ++i) + { + index = i - recvwindow_start; + + if (index >= BACKUPTICS) + { + // Outside the range + + continue; + } + + recvobj = &recvwindow[index][client->player_number]; + + recvobj->resend_time = nowtime; + } +} + +// Check for expired resend requests + +static void NET_SV_CheckResends(net_client_t *client) +{ + int i; + int player; + int resend_start, resend_end; + unsigned int nowtime; + + nowtime = I_GetTimeMS(); + + player = client->player_number; + resend_start = -1; + resend_end = -1; + + for (i=0; iactive + && recvobj->resend_time != 0 + && nowtime > recvobj->resend_time + 300; + + if (need_resend) + { + // Start a new run of resend tics? + if (resend_start < 0) + { + resend_start = i; + } + resend_end = i; + } + else if (resend_start >= 0) + { + // End of a run of resend tics + NET_Log("server: resend request to %s timed out for %d-%d (%d)", + NET_AddrToString(client->addr), + recvwindow_start + resend_start, + recvwindow_start + resend_end, + &recvwindow[resend_start][player].resend_time); + NET_SV_SendResendRequest(client, + recvwindow_start + resend_start, + recvwindow_start + resend_end); + + resend_start = -1; + } + } + + if (resend_start >= 0) + { + NET_Log("server: resend request to %s timed out for %d-%d (%d)", + NET_AddrToString(client->addr), + recvwindow_start + resend_start, + recvwindow_start + resend_end, + &recvwindow[resend_start][player].resend_time); + NET_SV_SendResendRequest(client, + recvwindow_start + resend_start, + recvwindow_start + resend_end); + } +} + +// Process game data from a client + +static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) +{ + net_client_recv_t *recvobj; + unsigned int seq; + unsigned int ackseq; + unsigned int num_tics; + unsigned int nowtime; + size_t i; + int player; + int resend_start, resend_end; + int index; + + if (server_state != SERVER_IN_GAME) + { + NET_Log("server: error: not in game state: server_state=%d", + server_state); + return; + } + + if (client->drone) + { + // Drones do not contribute any game data. + NET_Log("server: error: game data from a drone?"); + return; + } + + player = client->player_number; + + // Read header + if (!NET_ReadInt8(packet, &ackseq) + || !NET_ReadInt8(packet, &seq) + || !NET_ReadInt8(packet, &num_tics)) + { + NET_Log("server: error: failed to read header"); + return; + } + + NET_Log("server: got game data, seq=%d, num_tics=%d, ackseq=%d", + seq, num_tics, ackseq); + + // Get the current time + nowtime = I_GetTimeMS(); + + // Expand 8-bit values to the full sequence number + ackseq = NET_SV_ExpandTicNum(ackseq); + seq = NET_SV_ExpandTicNum(seq); + + // Sanity checks + + for (i=0; i= BACKUPTICS) + { + // Not in range of the recv window + + continue; + } + + recvobj = &recvwindow[index][player]; + recvobj->active = true; + recvobj->diff = diff; + recvobj->latency = latency; + + client->last_gamedata_time = nowtime; + NET_Log("server: stored tic %d for player %d", seq + i, player); + } + + // Higher acknowledgement point? + + if (ackseq > client->acknowledged) + { + NET_Log("server: acknowledged up to %d", ackseq); + client->acknowledged = ackseq; + } + + // Has this been received out of sequence, ie. have we not received + // all tics before the first tic in this packet? If so, send a + // resend request. + + //printf("SV: %p: %i\n", client, seq); + + resend_end = seq - recvwindow_start; + + if (resend_end <= 0) + return; + + if (resend_end >= BACKUPTICS) + resend_end = BACKUPTICS - 1; + + index = resend_end - 1; + resend_start = resend_end; + + while (index >= 0) + { + recvobj = &recvwindow[index][player]; + + if (recvobj->active) + { + // ended our run of unreceived tics + + break; + } + + if (recvobj->resend_time != 0) + { + // Already sent a resend request for this tic + + break; + } + + resend_start = index; + --index; + } + + // Possibly send a resend request + if (resend_start < resend_end) + { + NET_Log("server: request resend for %d-%d before %d", + recvwindow_start + resend_start, + recvwindow_start + resend_end - 1, seq); + NET_SV_SendResendRequest(client, + recvwindow_start + resend_start, + recvwindow_start + resend_end - 1); + } +} + +static void NET_SV_ParseGameDataACK(net_packet_t *packet, net_client_t *client) +{ + unsigned int ackseq; + + NET_Log("server: processing game data ack packet"); + + if (server_state != SERVER_IN_GAME) + { + NET_Log("server: error: not in game state, server_state=%d", + server_state); + return; + } + + // Read header + + if (!NET_ReadInt8(packet, &ackseq)) + { + NET_Log("server: error: missing acknowledgement field"); + return; + } + + // Expand 8-bit values to the full sequence number + + ackseq = NET_SV_ExpandTicNum(ackseq); + + // Higher acknowledgement point than we already have? + + if (ackseq > client->acknowledged) + { + NET_Log("server: acknowledged up to %d", ackseq); + client->acknowledged = ackseq; + } +} + +static void NET_SV_SendTics(net_client_t *client, + unsigned int start, unsigned int end) +{ + net_packet_t *packet; + unsigned int i; + + packet = NET_NewPacket(500); + + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); + + // Send the start tic and number of tics + + NET_WriteInt8(packet, start & 0xff); + NET_WriteInt8(packet, end-start + 1); + + // Write the tics + + for (i=start; i<=end; ++i) + { + net_full_ticcmd_t *cmd; + + cmd = &client->sendqueue[i % BACKUPTICS]; + + if (i != cmd->seq) + { + I_Error("Wanted to send %i, but %i is in its place", i, cmd->seq); + } + + // Add command + + NET_WriteFullTiccmd(packet, cmd, sv_settings.lowres_turn); + } + + // Send packet + + NET_Conn_SendPacket(&client->connection, packet); + + NET_FreePacket(packet); +} + +// Parse a retransmission request from a client + +static void NET_SV_ParseResendRequest(net_packet_t *packet, net_client_t *client) +{ + unsigned int start, last; + unsigned int num_tics; + unsigned int i; + + NET_Log("server: processing resend request"); + + // Read the starting tic and number of tics + + if (!NET_ReadInt32(packet, &start) + || !NET_ReadInt8(packet, &num_tics)) + { + NET_Log("server: error: missing fields for resend"); + return; + } + + //printf("SV: %p: resend %i-%i\n", client, start, start+num_tics-1); + + // Check we have all the requested tics + + last = start + num_tics - 1; + + for (i=start; i<=last; ++i) + { + net_full_ticcmd_t *cmd; + + cmd = &client->sendqueue[i % BACKUPTICS]; + + if (i != cmd->seq) + { + // We do not have the requested tic (any more) + // This is pretty fatal. We could disconnect the client, + // but then again this could be a spoofed packet. Just + // ignore it. + NET_Log("server: error: don't have tic %d any more, " + "can't resend", i); + return; + } + } + + // Resend those tics + NET_Log("server: resending tics %d-%d", start, last); + NET_SV_SendTics(client, start, last); +} + +// Send a response back to the client + +void NET_SV_SendQueryResponse(net_addr_t *addr) +{ + net_packet_t *reply; + net_querydata_t querydata; + int p; + + // Version + + querydata.version = PACKAGE_STRING; + + // Server state + + querydata.server_state = server_state; + + // Number of players/maximum players + + querydata.num_players = NET_SV_NumPlayers(); + querydata.max_players = NET_SV_MaxPlayers(); + + // Game mode/mission + + querydata.gamemode = sv_gamemode; + querydata.gamemission = sv_gamemission; + + //! + // @category net + // @arg + // + // When starting a network server, specify a name for the server. + // + + p = M_CheckParmWithArgs("-servername", 1); + + if (p > 0) + { + querydata.description = myargv[p + 1]; + } + else + { + querydata.description = "Unnamed server"; + } + + // Send it and we're done. + NET_Log("server: sending query response to %s", NET_AddrToString(addr)); + reply = NET_NewPacket(64); + NET_WriteInt16(reply, NET_PACKET_TYPE_QUERY_RESPONSE); + NET_WriteQueryData(reply, &querydata); + NET_SendPacket(addr, reply); + NET_FreePacket(reply); +} + +static void NET_SV_ParseHolePunch(net_packet_t *packet) +{ + const char *addr_string; + net_packet_t *sendpacket; + net_addr_t *addr; + + addr_string = NET_ReadString(packet); + if (addr_string == NULL) + { + NET_Log("server: error: hole punch request but no address provided"); + return; + } + + addr = NET_ResolveAddress(server_context, addr_string); + if (addr == NULL) + { + NET_Log("server: error: failed to resolve address: %s", addr_string); + return; + } + + sendpacket = NET_NewPacket(16); + NET_WriteInt16(sendpacket, NET_PACKET_TYPE_NAT_HOLE_PUNCH); + NET_SendPacket(addr, sendpacket); + NET_FreePacket(sendpacket); + NET_ReleaseAddress(addr); + NET_Log("server: sent hole punch to %s", addr_string); +} + +static void NET_SV_MasterPacket(net_packet_t *packet) +{ + unsigned int packet_type; + + // Read the packet type + + if (!NET_ReadInt16(packet, &packet_type)) + { + NET_Log("server: error: no packet type in master server message"); + return; + } + + NET_Log("server: packet from master server; type %d", packet_type); + NET_LogPacket(packet); + + switch (packet_type) + { + case NET_MASTER_PACKET_TYPE_ADD_RESPONSE: + NET_Query_AddResponse(packet); + break; + + case NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH: + NET_SV_ParseHolePunch(packet); + break; + } +} + +// Process a packet received by the server + +static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) +{ + net_client_t *client; + unsigned int packet_type; + + // Response from master server? + + if (addr != NULL && addr == master_server) + { + NET_SV_MasterPacket(packet); + return; + } + + // Find which client this packet came from + + client = NET_SV_FindClient(addr); + + // Read the packet type + + if (!NET_ReadInt16(packet, &packet_type)) + { + // no packet type + + return; + } + + NET_Log("server: packet from %s; type %d", NET_AddrToString(addr), + packet_type & ~NET_RELIABLE_PACKET); + NET_LogPacket(packet); + + if (packet_type == NET_PACKET_TYPE_SYN) + { + NET_SV_ParseSYN(packet, client, addr); + } + else if (packet_type == NET_PACKET_TYPE_QUERY) + { + NET_SV_SendQueryResponse(addr); + } + else if (client == NULL) + { + // Must come from a valid client; ignore otherwise + } + else if (NET_Conn_Packet(&client->connection, packet, &packet_type)) + { + // Packet was eaten by the common connection code + } + else + { + //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type); + + switch (packet_type) + { + case NET_PACKET_TYPE_GAMESTART: + NET_SV_ParseGameStart(packet, client); + break; + case NET_PACKET_TYPE_LAUNCH: + NET_SV_ParseLaunch(packet, client); + break; + case NET_PACKET_TYPE_GAMEDATA: + NET_SV_ParseGameData(packet, client); + break; + case NET_PACKET_TYPE_GAMEDATA_ACK: + NET_SV_ParseGameDataACK(packet, client); + break; + case NET_PACKET_TYPE_GAMEDATA_RESEND: + NET_SV_ParseResendRequest(packet, client); + break; + default: + // unknown packet type + + break; + } + } +} + + +static void NET_SV_PumpSendQueue(net_client_t *client) +{ + net_full_ticcmd_t cmd; + int recv_index; + int num_players; + int i; + int starttic, endtic; + + // If a client has not sent any acknowledgments for a while, + // wait until they catch up. + + if (client->sendseq - NET_SV_LatestAcknowledged() > 40) + { + return; + } + + // Work out the index into the receive window + + recv_index = client->sendseq - recvwindow_start; + + if (recv_index < 0 || recv_index >= BACKUPTICS) + { + return; + } + + // Check if we can generate a new entry for the send queue + // using the data in recvwindow. + + num_players = 0; + + for (i=0; isendseq > recvwindow_start + 10) + { + return; + } + + // We have all data we need to generate a command for this tic. + + cmd.seq = client->sendseq; + + // Add ticcmds from all players + + cmd.latency = 0; + + for (i=0; idiff; + + if (recvobj->latency > cmd.latency) + cmd.latency = recvobj->latency; + } + + //printf("SV: %i: latency %i\n", client->player_number, cmd.latency); + + // Add into the queue + + client->sendqueue[client->sendseq % BACKUPTICS] = cmd; + + // Transmit the new tic to the client + + starttic = client->sendseq - sv_settings.extratics; + endtic = client->sendseq; + + if (starttic < 0) + starttic = 0; + + NET_Log("server: send tics %d-%d to %s", starttic, endtic, + NET_AddrToString(client->addr)); + NET_SV_SendTics(client, starttic, endtic); + + ++client->sendseq; +} + +// Prevent against deadlock: resend requests are usually only +// triggered if we miss a packet and receive the next one. +// If we miss a whole load of packets, we can end up in a +// deadlock situation where the client will not send any more. +// If we don't receive any game data in a while, trigger a resend +// request for the next tic we're expecting. + +void NET_SV_CheckDeadlock(net_client_t *client) +{ + int nowtime; + int i; + + // Don't expect game data from clients. + + if (client->drone) + { + return; + } + + nowtime = I_GetTimeMS(); + + // If we haven't received anything for a long time, it may be a deadlock. + + if (nowtime - client->last_gamedata_time > 1000) + { + NET_Log("server: no gamedata from %s since %d - deadlock?", + NET_AddrToString(client->addr), + client->last_gamedata_time); + + // Search the receive window for the first tic we are expecting + // from this player. + + for (i=0; iplayer_number].active) + { + NET_Log("server: deadlock: sending resend request for %d-%d", + recvwindow_start + i, recvwindow_start + i + 5); + + // Found a tic we haven't received. Send a resend request. + + NET_SV_SendResendRequest(client, + recvwindow_start + i, + recvwindow_start + i + 5); + + client->last_gamedata_time = nowtime; + break; + } + } + + // If we sent a resend request to break the deadlock, also trigger a + // resend of any tics we have sitting in the send queue, in case the + // client is blocked waiting on tics from us that have been lost. + // This fixes deadlock with some older clients which do not send + // resends to break deadlock. + if (i < BACKUPTICS && client->sendseq > client->acknowledged) + { + NET_Log("server: also resending tics %d-%d to break deadlock", + client->acknowledged, client->sendseq - 1); + NET_SV_SendTics(client, client->acknowledged, client->sendseq - 1); + } + } +} + +// Called when all players have disconnected. Return to listening for +// players to start a new game, and disconnect any drones still connected. + +static void NET_SV_GameEnded(void) +{ + int i; + + server_state = SERVER_WAITING_LAUNCH; + sv_gamemode = indetermined; + + for (i=0; iconnection); + + if (client->connection.state == NET_CONN_STATE_DISCONNECTED + && client->connection.disconnect_reason == NET_DISCONNECT_TIMEOUT) + { + NET_Log("server: client at %s timed out", + NET_AddrToString(client->addr)); + NET_SV_BroadcastMessage("Client '%s' timed out and disconnected", + client->name); + } + + // Is this client disconnected? + + if (client->connection.state == NET_CONN_STATE_DISCONNECTED) + { + client->active = false; + + // If we were about to start a game, any player disconnecting + // should cause an abort. + + if (server_state == SERVER_WAITING_START && !client->drone) + { + NET_SV_BroadcastMessage("Game startup aborted because " + "player '%s' disconnected.", + client->name); + NET_SV_GameEnded(); + } + + free(client->name); + NET_ReleaseAddress(client->addr); + + // Are there any clients left connected? If not, return the + // server to the waiting-for-players state. + // + // Disconnect any drones still connected. + + if (NET_SV_NumPlayers() <= 0) + { + NET_Log("server: no player clients left, game ended"); + NET_SV_GameEnded(); + } + } + + if (!ClientConnected(client)) + { + // client has not yet finished connecting + + return; + } + + if (server_state == SERVER_WAITING_LAUNCH) + { + // Waiting for the game to start + + // Send information once every second + + if (client->last_send_time < 0 + || I_GetTimeMS() - client->last_send_time > 1000) + { + NET_SV_SendWaitingData(client); + client->last_send_time = I_GetTimeMS(); + } + } + + if (server_state == SERVER_IN_GAME) + { + NET_SV_PumpSendQueue(client); + NET_SV_CheckDeadlock(client); + } +} + +// Add a network module to the server context + +void NET_SV_AddModule(net_module_t *module) +{ + module->InitServer(); + NET_AddModule(server_context, module); +} + +// Initialize server and wait for connections + +void NET_SV_Init(void) +{ + int i; + + // initialize send/receive context + + server_context = NET_NewContext(); + + // no clients yet + + for (i=0; i MASTER_RESOLVE_PERIOD * 1000) + { + net_addr_t *new_addr; + + new_addr = NET_Query_ResolveMaster(server_context); + NET_ReleaseAddress(master_server); + master_server = new_addr; + + master_resolve_time = now; + } + + // Possibly refresh our registration with the master server. + + if (now - master_refresh_time > MASTER_REFRESH_PERIOD * 1000) + { + NET_Query_AddToMaster(master_server); + master_refresh_time = now; + } +} + +void NET_SV_RegisterWithMaster(void) +{ + //! + // @category net + // + // When running a server, don't register with the global master server. + // Implies -server. + // + + if (!M_CheckParm("-privateserver")) + { + master_server = NET_Query_ResolveMaster(server_context); + } + else + { + master_server = NULL; + } + + // Send request. + + if (master_server != NULL) + { + NET_Query_AddToMaster(master_server); + master_refresh_time = I_GetTimeMS(); + master_resolve_time = master_refresh_time; + } +} + +// Run server code to check for new packets/send packets as the server +// requires + +void NET_SV_Run(void) +{ + net_addr_t *addr; + net_packet_t *packet; + int i; + + if (!server_initialized) + { + return; + } + + while (NET_RecvPacket(server_context, &addr, &packet)) + { + NET_SV_Packet(packet, addr); + NET_FreePacket(packet); + NET_ReleaseAddress(addr); + } + + if (master_server != NULL) + { + UpdateMasterServer(); + } + + // "Run" any clients that may have things to do, independent of responses + // to received packets + + for (i=0; i 5000) + { + running = false; + fprintf(stderr, "SV: Timed out waiting for clients to disconnect.\n"); + } + + // Run the client code in case this is a loopback client. + + NET_CL_Run(); + NET_SV_Run(); + + // Don't hog the CPU + + I_Sleep(1); + } +} diff --git a/games/NXDoom/src/net_server.h b/games/NXDoom/src/net_server.h new file mode 100644 index 00000000000..b9de7456ef8 --- /dev/null +++ b/games/NXDoom/src/net_server.h @@ -0,0 +1,42 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Network server code +// + +#ifndef NET_SERVER_H +#define NET_SERVER_H + +// initialize server and wait for connections + +void NET_SV_Init(void); + +// run server: check for new packets received etc. + +void NET_SV_Run(void); + +// Shut down the server +// Blocks until all clients disconnect, or until a 5 second timeout + +void NET_SV_Shutdown(void); + +// Add a network module to the context used by the server + +void NET_SV_AddModule(net_module_t *module); + +// Register server with master server. + +void NET_SV_RegisterWithMaster(void); + +#endif /* #ifndef NET_SERVER_H */ + diff --git a/games/NXDoom/src/net_structrw.c b/games/NXDoom/src/net_structrw.c new file mode 100644 index 00000000000..2dbd2740a13 --- /dev/null +++ b/games/NXDoom/src/net_structrw.c @@ -0,0 +1,676 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// Reading and writing various structures into packets +// + +#include +#include +#include + +#include "doomtype.h" +#include "i_system.h" +#include "m_misc.h" +#include "net_packet.h" +#include "net_structrw.h" + +// String names for the enum values in net_protocol_t, which are what is +// sent over the wire. Every enum value must have an entry in this list. +static struct +{ + net_protocol_t protocol; + const char *name; +} protocol_names[] = { + {NET_PROTOCOL_CHOCOLATE_DOOM_0, "CHOCOLATE_DOOM_0"}, +}; + +void NET_WriteConnectData(net_packet_t *packet, net_connect_data_t *data) +{ + NET_WriteInt8(packet, data->gamemode); + NET_WriteInt8(packet, data->gamemission); + NET_WriteInt8(packet, data->lowres_turn); + NET_WriteInt8(packet, data->drone); + NET_WriteInt8(packet, data->max_players); + NET_WriteInt8(packet, data->is_freedoom); + NET_WriteSHA1Sum(packet, data->wad_sha1sum); + NET_WriteSHA1Sum(packet, data->deh_sha1sum); + NET_WriteInt8(packet, data->player_class); +} + +boolean NET_ReadConnectData(net_packet_t *packet, net_connect_data_t *data) +{ + return NET_ReadInt8(packet, (unsigned int *) &data->gamemode) + && NET_ReadInt8(packet, (unsigned int *) &data->gamemission) + && NET_ReadInt8(packet, (unsigned int *) &data->lowres_turn) + && NET_ReadInt8(packet, (unsigned int *) &data->drone) + && NET_ReadInt8(packet, (unsigned int *) &data->max_players) + && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom) + && NET_ReadSHA1Sum(packet, data->wad_sha1sum) + && NET_ReadSHA1Sum(packet, data->deh_sha1sum) + && NET_ReadInt8(packet, (unsigned int *) &data->player_class); +} + +void NET_WriteSettings(net_packet_t *packet, net_gamesettings_t *settings) +{ + int i; + + NET_WriteInt8(packet, settings->ticdup); + NET_WriteInt8(packet, settings->extratics); + NET_WriteInt8(packet, settings->deathmatch); + NET_WriteInt8(packet, settings->nomonsters); + NET_WriteInt8(packet, settings->fast_monsters); + NET_WriteInt8(packet, settings->respawn_monsters); + NET_WriteInt8(packet, settings->episode); + NET_WriteInt8(packet, settings->map); + NET_WriteInt8(packet, settings->skill); + NET_WriteInt8(packet, settings->gameversion); + NET_WriteInt8(packet, settings->lowres_turn); + NET_WriteInt8(packet, settings->new_sync); + NET_WriteInt32(packet, settings->timelimit); + NET_WriteInt8(packet, settings->loadgame); + NET_WriteInt8(packet, settings->random); + NET_WriteInt8(packet, settings->num_players); + NET_WriteInt8(packet, settings->consoleplayer); + + for (i = 0; i < settings->num_players; ++i) + { + NET_WriteInt8(packet, settings->player_classes[i]); + } +} + +boolean NET_ReadSettings(net_packet_t *packet, net_gamesettings_t *settings) +{ + boolean success; + int i; + + success = NET_ReadInt8(packet, (unsigned int *) &settings->ticdup) + && NET_ReadInt8(packet, (unsigned int *) &settings->extratics) + && NET_ReadInt8(packet, (unsigned int *) &settings->deathmatch) + && NET_ReadInt8(packet, (unsigned int *) &settings->nomonsters) + && NET_ReadInt8(packet, (unsigned int *) &settings->fast_monsters) + && NET_ReadInt8(packet, (unsigned int *) &settings->respawn_monsters) + && NET_ReadInt8(packet, (unsigned int *) &settings->episode) + && NET_ReadInt8(packet, (unsigned int *) &settings->map) + && NET_ReadSInt8(packet, &settings->skill) + && NET_ReadInt8(packet, (unsigned int *) &settings->gameversion) + && NET_ReadInt8(packet, (unsigned int *) &settings->lowres_turn) + && NET_ReadInt8(packet, (unsigned int *) &settings->new_sync) + && NET_ReadInt32(packet, (unsigned int *) &settings->timelimit) + && NET_ReadSInt8(packet, (signed int *) &settings->loadgame) + && NET_ReadInt8(packet, (unsigned int *) &settings->random) + && NET_ReadInt8(packet, (unsigned int *) &settings->num_players) + && NET_ReadSInt8(packet, (signed int *) &settings->consoleplayer); + + if (!success) + { + return false; + } + + for (i = 0; i < settings->num_players && i < NET_MAXPLAYERS; ++i) + { + if (!NET_ReadInt8(packet, + (unsigned int *) &settings->player_classes[i])) + { + return false; + } + } + + return true; +} + +boolean NET_ReadQueryData(net_packet_t *packet, net_querydata_t *query) +{ + boolean success; + + query->version = NET_ReadSafeString(packet); + + success = query->version != NULL + && NET_ReadInt8(packet, (unsigned int *) &query->server_state) + && NET_ReadInt8(packet, (unsigned int *) &query->num_players) + && NET_ReadInt8(packet, (unsigned int *) &query->max_players) + && NET_ReadInt8(packet, (unsigned int *) &query->gamemode) + && NET_ReadInt8(packet, (unsigned int *) &query->gamemission); + + if (!success) + { + return false; + } + + query->description = NET_ReadSafeString(packet); + + // We read the list of protocols supported by the server. However, + // old versions of Chocolate Doom do not support this field; it is + // okay if it cannot be successfully read. + query->protocol = NET_ReadProtocolList(packet); + + return query->description != NULL; +} + +void NET_WriteQueryData(net_packet_t *packet, net_querydata_t *query) +{ + NET_WriteString(packet, query->version); + NET_WriteInt8(packet, query->server_state); + NET_WriteInt8(packet, query->num_players); + NET_WriteInt8(packet, query->max_players); + NET_WriteInt8(packet, query->gamemode); + NET_WriteInt8(packet, query->gamemission); + NET_WriteString(packet, query->description); + + // Write a list of all supported protocols. Note that the query->protocol + // field is ignored here; it is only used when receiving. + NET_WriteProtocolList(packet); +} + +void NET_WriteTiccmdDiff(net_packet_t *packet, net_ticdiff_t *diff, + boolean lowres_turn) +{ + // Header + + NET_WriteInt8(packet, diff->diff); + + // Write the fields which are enabled: + + if (diff->diff & NET_TICDIFF_FORWARD) + NET_WriteInt8(packet, diff->cmd.forwardmove); + if (diff->diff & NET_TICDIFF_SIDE) + NET_WriteInt8(packet, diff->cmd.sidemove); + if (diff->diff & NET_TICDIFF_TURN) + { + if (lowres_turn) + { + NET_WriteInt8(packet, diff->cmd.angleturn / 256); + } + else + { + NET_WriteInt16(packet, diff->cmd.angleturn); + } + } + if (diff->diff & NET_TICDIFF_BUTTONS) + NET_WriteInt8(packet, diff->cmd.buttons); + if (diff->diff & NET_TICDIFF_CONSISTANCY) + NET_WriteInt8(packet, diff->cmd.consistancy); + if (diff->diff & NET_TICDIFF_CHATCHAR) + NET_WriteInt8(packet, diff->cmd.chatchar); + if (diff->diff & NET_TICDIFF_RAVEN) + { + NET_WriteInt8(packet, diff->cmd.lookfly); + NET_WriteInt8(packet, diff->cmd.arti); + } + if (diff->diff & NET_TICDIFF_STRIFE) + { + NET_WriteInt8(packet, diff->cmd.buttons2); + NET_WriteInt16(packet, diff->cmd.inventory); + } +} + +boolean NET_ReadTiccmdDiff(net_packet_t *packet, net_ticdiff_t *diff, + boolean lowres_turn) +{ + unsigned int val; + signed int sval; + + // Read header + + if (!NET_ReadInt8(packet, &diff->diff)) + return false; + + // Read fields + + if (diff->diff & NET_TICDIFF_FORWARD) + { + if (!NET_ReadSInt8(packet, &sval)) + return false; + diff->cmd.forwardmove = sval; + } + + if (diff->diff & NET_TICDIFF_SIDE) + { + if (!NET_ReadSInt8(packet, &sval)) + return false; + diff->cmd.sidemove = sval; + } + + if (diff->diff & NET_TICDIFF_TURN) + { + if (lowres_turn) + { + if (!NET_ReadSInt8(packet, &sval)) + return false; + diff->cmd.angleturn = sval * 256; + } + else + { + if (!NET_ReadSInt16(packet, &sval)) + return false; + diff->cmd.angleturn = sval; + } + } + + if (diff->diff & NET_TICDIFF_BUTTONS) + { + if (!NET_ReadInt8(packet, &val)) + return false; + diff->cmd.buttons = val; + } + + if (diff->diff & NET_TICDIFF_CONSISTANCY) + { + if (!NET_ReadInt8(packet, &val)) + return false; + diff->cmd.consistancy = val; + } + + if (diff->diff & NET_TICDIFF_CHATCHAR) + { + if (!NET_ReadInt8(packet, &val)) + return false; + diff->cmd.chatchar = val; + } + + if (diff->diff & NET_TICDIFF_RAVEN) + { + if (!NET_ReadInt8(packet, &val)) + return false; + diff->cmd.lookfly = val; + + if (!NET_ReadInt8(packet, &val)) + return false; + diff->cmd.arti = val; + } + + if (diff->diff & NET_TICDIFF_STRIFE) + { + if (!NET_ReadInt8(packet, &val)) + return false; + diff->cmd.buttons2 = val; + + if (!NET_ReadInt16(packet, &val)) + return false; + diff->cmd.inventory = val; + } + + return true; +} + +void NET_TiccmdDiff(ticcmd_t *tic1, ticcmd_t *tic2, net_ticdiff_t *diff) +{ + diff->diff = 0; + diff->cmd = *tic2; + + if (tic1->forwardmove != tic2->forwardmove) + diff->diff |= NET_TICDIFF_FORWARD; + if (tic1->sidemove != tic2->sidemove) + diff->diff |= NET_TICDIFF_SIDE; + if (tic1->angleturn != tic2->angleturn) + diff->diff |= NET_TICDIFF_TURN; + if (tic1->buttons != tic2->buttons) + diff->diff |= NET_TICDIFF_BUTTONS; + if (tic1->consistancy != tic2->consistancy) + diff->diff |= NET_TICDIFF_CONSISTANCY; + if (tic2->chatchar != 0) + diff->diff |= NET_TICDIFF_CHATCHAR; + + // Heretic/Hexen-specific + + if (tic1->lookfly != tic2->lookfly || tic2->arti != 0) + diff->diff |= NET_TICDIFF_RAVEN; + + // Strife-specific + + if (tic1->buttons2 != tic2->buttons2 || tic2->inventory != 0) + diff->diff |= NET_TICDIFF_STRIFE; +} + +void NET_TiccmdPatch(ticcmd_t *src, net_ticdiff_t *diff, ticcmd_t *dest) +{ + memmove(dest, src, sizeof(ticcmd_t)); + + // Apply the diff + + if (diff->diff & NET_TICDIFF_FORWARD) + dest->forwardmove = diff->cmd.forwardmove; + if (diff->diff & NET_TICDIFF_SIDE) + dest->sidemove = diff->cmd.sidemove; + if (diff->diff & NET_TICDIFF_TURN) + dest->angleturn = diff->cmd.angleturn; + if (diff->diff & NET_TICDIFF_BUTTONS) + dest->buttons = diff->cmd.buttons; + if (diff->diff & NET_TICDIFF_CONSISTANCY) + dest->consistancy = diff->cmd.consistancy; + + if (diff->diff & NET_TICDIFF_CHATCHAR) + dest->chatchar = diff->cmd.chatchar; + else + dest->chatchar = 0; + + // Heretic/Hexen specific: + + if (diff->diff & NET_TICDIFF_RAVEN) + { + dest->lookfly = diff->cmd.lookfly; + dest->arti = diff->cmd.arti; + } + else + { + dest->arti = 0; + } + + // Strife-specific: + + if (diff->diff & NET_TICDIFF_STRIFE) + { + dest->buttons2 = diff->cmd.buttons2; + dest->inventory = diff->cmd.inventory; + } + else + { + dest->inventory = 0; + } +} + +// +// net_full_ticcmd_t +// + +boolean NET_ReadFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn) +{ + unsigned int bitfield; + int i; + + // Latency + + if (!NET_ReadSInt16(packet, &cmd->latency)) + { + return false; + } + + // Regenerate playeringame from the "header" bitfield + + if (!NET_ReadInt8(packet, &bitfield)) + { + return false; + } + + for (i=0; iplayeringame[i] = (bitfield & (1 << i)) != 0; + } + + // Read cmds + + for (i=0; iplayeringame[i]) + { + if (!NET_ReadTiccmdDiff(packet, &cmd->cmds[i], lowres_turn)) + { + return false; + } + } + } + + return true; +} + +void NET_WriteFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn) +{ + unsigned int bitfield; + int i; + + // Write the latency + + NET_WriteInt16(packet, cmd->latency); + + // Write "header" byte indicating which players are active + // in this ticcmd + + bitfield = 0; + + for (i=0; iplayeringame[i]) + { + bitfield |= 1 << i; + } + } + + NET_WriteInt8(packet, bitfield); + + // Write player ticcmds + + for (i=0; iplayeringame[i]) + { + NET_WriteTiccmdDiff(packet, &cmd->cmds[i], lowres_turn); + } + } +} + +void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data) +{ + int i; + + NET_WriteInt8(packet, data->num_players); + NET_WriteInt8(packet, data->num_drones); + NET_WriteInt8(packet, data->ready_players); + NET_WriteInt8(packet, data->max_players); + NET_WriteInt8(packet, data->is_controller); + NET_WriteInt8(packet, data->consoleplayer); + + for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i) + { + NET_WriteString(packet, data->player_names[i]); + NET_WriteString(packet, data->player_addrs[i]); + } + + NET_WriteSHA1Sum(packet, data->wad_sha1sum); + NET_WriteSHA1Sum(packet, data->deh_sha1sum); + NET_WriteInt8(packet, data->is_freedoom); +} + +boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data) +{ + int i; + char *s; + + if (!NET_ReadInt8(packet, (unsigned int *) &data->num_players) + || !NET_ReadInt8(packet, (unsigned int *) &data->num_drones) + || !NET_ReadInt8(packet, (unsigned int *) &data->ready_players) + || !NET_ReadInt8(packet, (unsigned int *) &data->max_players) + || !NET_ReadInt8(packet, (unsigned int *) &data->is_controller) + || !NET_ReadSInt8(packet, &data->consoleplayer)) + { + return false; + } + + for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i) + { + s = NET_ReadString(packet); + + if (s == NULL || strlen(s) >= MAXPLAYERNAME) + { + return false; + } + + M_StringCopy(data->player_names[i], s, MAXPLAYERNAME); + + s = NET_ReadString(packet); + + if (s == NULL || strlen(s) >= MAXPLAYERNAME) + { + return false; + } + + M_StringCopy(data->player_addrs[i], s, MAXPLAYERNAME); + } + + return NET_ReadSHA1Sum(packet, data->wad_sha1sum) + && NET_ReadSHA1Sum(packet, data->deh_sha1sum) + && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom); +} + +static boolean NET_ReadBlob(net_packet_t *packet, uint8_t *buf, size_t len) +{ + unsigned int b; + int i; + + for (i=0; i +#include + +#include "m_argv.h" +#include "p_rejectpad.h" + + +// Pad the REJECT lump with extra data when the lump is too small, +// to simulate a REJECT buffer overflow in Vanilla Doom. + +void PadRejectArray(byte *array, unsigned int len, int totallines) +{ + unsigned int i; + unsigned int byte_num; + byte *dest; + unsigned int padvalue; + + // Values to pad the REJECT array with: + + unsigned int rejectpad[4] = + { + 0, // Size + 0, // Part of z_zone block header + 50, // PU_LEVEL + 0x1d4a11 // DOOM_CONST_ZONEID + }; + + rejectpad[0] = ((totallines * 4 + 3) & ~3) + 24; + + // Copy values from rejectpad into the destination array. + + dest = array; + + for (i=0; i> (byte_num * 8)) & 0xff; + ++dest; + } + + // We only have a limited pad size. Print a warning if the + // REJECT lump is too small. + + if (len > sizeof(rejectpad)) + { + fprintf(stderr, "PadRejectArray: REJECT lump too short to pad! (%u > %i)\n", + len, (int) sizeof(rejectpad)); + + // Pad remaining space with 0 (or 0xff, if specified on command line). + + if (M_CheckParm("-reject_pad_with_ff")) + { + padvalue = 0xff; + } + else + { + padvalue = 0x00; + } + + memset(array + sizeof(rejectpad), padvalue, len - sizeof(rejectpad)); + } +} diff --git a/games/NXDoom/src/p_rejectpad.h b/games/NXDoom/src/p_rejectpad.h new file mode 100644 index 00000000000..78ab8407069 --- /dev/null +++ b/games/NXDoom/src/p_rejectpad.h @@ -0,0 +1,28 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Padding of Reject Lump +// + + +#ifndef __P_REJECTPAD__ +#define __P_REJECTPAD__ + +#include "doomtype.h" + +// Padding of Reject Lump +void PadRejectArray(byte *array, unsigned int len, int totallines); + +#endif diff --git a/games/NXDoom/src/setup-res.rc.in b/games/NXDoom/src/setup-res.rc.in new file mode 100644 index 00000000000..2be914f96b6 --- /dev/null +++ b/games/NXDoom/src/setup-res.rc.in @@ -0,0 +1,28 @@ +1 ICON "@top_srcdir@/data/setup.ico" + +1 24 MOVEABLE PURE "@top_builddir@/src/setup/setup-manifest.xml" + +1 VERSIONINFO +PRODUCTVERSION @WINDOWS_RC_VERSION@ +FILEVERSION @WINDOWS_RC_VERSION@ +FILETYPE 1 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "@PACKAGE_VERSION@.0" + VALUE "FileDescription", "@PACKAGE_STRING@ Setup" + VALUE "InternalName", "@PACKAGE_TARNAME@" + VALUE "CompanyName", "@PACKAGE_BUGREPORT@" + VALUE "LegalCopyright", "GNU General Public License" + VALUE "ProductName", "@PACKAGE_NAME@ Setup" + VALUE "ProductVersion", "@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + diff --git a/games/NXDoom/src/setup/.gitignore b/games/NXDoom/src/setup/.gitignore new file mode 100644 index 00000000000..f41d11c73e7 --- /dev/null +++ b/games/NXDoom/src/setup/.gitignore @@ -0,0 +1,7 @@ +Makefile.in +Makefile +.deps +setup-manifest.xml +*.rc +tags +TAGS diff --git a/games/NXDoom/src/setup/CMakeLists.txt b/games/NXDoom/src/setup/CMakeLists.txt new file mode 100644 index 00000000000..c25af659944 --- /dev/null +++ b/games/NXDoom/src/setup/CMakeLists.txt @@ -0,0 +1,32 @@ +add_library(setup STATIC + compatibility.c compatibility.h + display.c display.h + joystick.c joystick.h + keyboard.c keyboard.h + mainmenu.c + mode.c mode.h + mouse.c mouse.h + multiplayer.c multiplayer.h + sound.c sound.h + execute.c execute.h + txt_joyaxis.c txt_joyaxis.h + txt_joybinput.c txt_joybinput.h + txt_keyinput.c txt_keyinput.h + txt_mouseinput.c txt_mouseinput.h) + +target_include_directories(setup PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") + +if (DEFINED EMSCRIPTEN) + set(SDL_FLAGS "-s USE_SDL=2") + if(ENABLE_SDL2_MIXER) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") + endif() +else() + set(SDL_LINK_LIBS, "SDL2::SDL2") + if(ENABLE_SDL2_MIXER) + list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) + endif() +endif() +target_link_libraries(setup textscreen ${SDL_LINK_LIBS}) +set_target_properties(setup PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") +set_target_properties(setup PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/setup/Makefile.am b/games/NXDoom/src/setup/Makefile.am new file mode 100644 index 00000000000..493b0b47240 --- /dev/null +++ b/games/NXDoom/src/setup/Makefile.am @@ -0,0 +1,42 @@ + +AM_CFLAGS = @SDL_CFLAGS@ \ + @SDLMIXER_CFLAGS@ \ + -I$(top_srcdir)/textscreen -I$(top_srcdir)/src + +noinst_LIBRARIES = libsetup.a + +libsetup_a_SOURCES = \ + compatibility.c compatibility.h \ + display.c display.h \ + joystick.c joystick.h \ + keyboard.c keyboard.h \ + mainmenu.c \ + mode.c mode.h \ + mouse.c mouse.h \ + multiplayer.c multiplayer.h \ + sound.c sound.h \ + execute.c execute.h \ + txt_joyaxis.c txt_joyaxis.h \ + txt_joybinput.c txt_joybinput.h \ + txt_keyinput.c txt_keyinput.h \ + txt_mouseinput.c txt_mouseinput.h + +EXTRA_DIST= \ + CMakeLists.txt \ + setup_icon.c + +appdir = $(prefix)/share/applications +app_DATA = @PACKAGE_RDNS@.Setup.desktop + +CLEANFILES = $(app_DATA) + +@PACKAGE_RDNS@.Setup.desktop : Setup.desktop + cp Setup.desktop $@ + +if HAVE_ICONS + +setup_icon.c : $(top_builddir)/data/setup.png + $(top_builddir)/data/convert-icon $(top_builddir)/data/setup.png $@ + +endif + diff --git a/games/NXDoom/src/setup/Setup.desktop.in b/games/NXDoom/src/setup/Setup.desktop.in new file mode 100644 index 00000000000..2a5e71fa1e2 --- /dev/null +++ b/games/NXDoom/src/setup/Setup.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=@PACKAGE_SHORTNAME@ Setup +Exec=@PROGRAM_PREFIX@setup +Icon=@PROGRAM_PREFIX@setup +Type=Application +Comment=Setup tool for @PACKAGE_SHORTNAME@ +Categories=Settings; +Keywords=first;person;shooter;doom;heretic;hexen;strife;vanilla; diff --git a/games/NXDoom/src/setup/compatibility.c b/games/NXDoom/src/setup/compatibility.c new file mode 100644 index 00000000000..b96228f6115 --- /dev/null +++ b/games/NXDoom/src/setup/compatibility.c @@ -0,0 +1,51 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// Sound control menu + +#include + +#include "m_config.h" +#include "textscreen.h" +#include "mode.h" + +#include "compatibility.h" + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-compat" + +int vanilla_savegame_limit = 1; +int vanilla_demo_limit = 1; + +void CompatibilitySettings(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + + window = TXT_NewWindow("Compatibility"); + + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + TXT_AddWidgets(window, + TXT_NewCheckBox("Vanilla savegame limit", + &vanilla_savegame_limit), + TXT_NewCheckBox("Vanilla demo limit", + &vanilla_demo_limit), + NULL); +} + +void BindCompatibilityVariables(void) +{ + M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); + M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); +} + diff --git a/games/NXDoom/src/setup/compatibility.h b/games/NXDoom/src/setup/compatibility.h new file mode 100644 index 00000000000..39a5fc8f7f6 --- /dev/null +++ b/games/NXDoom/src/setup/compatibility.h @@ -0,0 +1,24 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_COMPATIBILITY_H +#define SETUP_COMPATIBILITY_H + +void CompatibilitySettings(void *widget, void *user_data); +void BindCompatibilityVariables(void); + +extern int vanilla_savegame_limit; +extern int vanilla_demo_limit; + +#endif /* #ifndef SETUP_COMPATIBILITY_H */ diff --git a/games/NXDoom/src/setup/display.c b/games/NXDoom/src/setup/display.c new file mode 100644 index 00000000000..0f89a09310f --- /dev/null +++ b/games/NXDoom/src/setup/display.c @@ -0,0 +1,289 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include "textscreen.h" +#include "m_config.h" +#include "m_misc.h" +#include "mode.h" + +#include "display.h" +#include "config.h" + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-display" + + +typedef struct +{ + int w, h; +} window_size_t; + +// List of aspect ratio-uncorrected window sizes: +static window_size_t window_sizes_unscaled[] = +{ + { 320, 200 }, + { 640, 400 }, + { 960, 600 }, + { 1280, 800 }, + { 1600, 1000 }, + { 0, 0}, +}; + +// List of aspect ratio-corrected window sizes: +static window_size_t window_sizes_scaled[] = +{ + { 320, 240 }, + { 512, 400 }, + { 640, 480 }, + { 800, 600 }, + { 960, 720 }, + { 1024, 800 }, + { 1280, 960 }, + { 1600, 1200 }, + { 1920, 1440 }, + { 0, 0}, +}; + +static char *video_driver = ""; +static char *window_position = ""; +static int video_display = 0; +static int aspect_ratio_correct = 1; +static int integer_scaling = 0; +static int smooth_pixel_scaling = 1; +static int vga_porch_flash = 0; +static int force_software_renderer = 0; +static int fullscreen = 1; +static int fullscreen_width = 0, fullscreen_height = 0; +static int window_width = 800, window_height = 600; +static int startup_delay = 1000; +static int max_scaling_buffer_pixels = 16000000; +static int usegamma = 0; + +int graphical_startup = 1; +int show_endoom = 1; +int show_diskicon = 1; +int png_screenshots = 0; + +static int system_video_env_set; + +// Set the SDL_VIDEODRIVER environment variable + +void SetDisplayDriver(void) +{ + static int first_time = 1; + + if (first_time) + { + system_video_env_set = getenv("SDL_VIDEODRIVER") != NULL; + + first_time = 0; + } + + // Don't override the command line environment, if it has been set. + + if (system_video_env_set) + { + return; + } + + // Use the value from the configuration file, if it has been set. + + if (strcmp(video_driver, "") != 0) + { + char *env_string; + + env_string = M_StringJoin("SDL_VIDEODRIVER=", video_driver, NULL); + putenv(env_string); + free(env_string); + } +} + +static void WindowSizeSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(size)) +{ + TXT_CAST_ARG(window_size_t, size); + + window_width = size->w; + window_height = size->h; +} + +static txt_radiobutton_t *SizeSelectButton(window_size_t *size) +{ + char buf[15]; + txt_radiobutton_t *result; + + M_snprintf(buf, sizeof(buf), "%ix%i", size->w, size->h); + result = TXT_NewRadioButton(buf, &window_width, size->w); + TXT_SignalConnect(result, "selected", WindowSizeSelected, size); + + return result; +} + +static void GenerateSizesTable(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(sizes_table)) +{ + TXT_CAST_ARG(txt_table_t, sizes_table); + window_size_t *sizes; + boolean have_size; + int i; + + // Pick which window sizes list to use + if (aspect_ratio_correct == 1) + { + sizes = window_sizes_scaled; + } + else + { + sizes = window_sizes_unscaled; + } + + // Build the table + TXT_ClearTable(sizes_table); + TXT_SetColumnWidths(sizes_table, 14, 14, 14); + + TXT_AddWidget(sizes_table, TXT_NewSeparator("Window size")); + + have_size = false; + + for (i = 0; sizes[i].w != 0; ++i) + { + TXT_AddWidget(sizes_table, SizeSelectButton(&sizes[i])); + have_size = have_size || window_width == sizes[i].w; + } + + // Windows can be any arbitrary size. We key off the width of the + // window in pixels. If the current size is not in the list of + // standard (integer multiply) sizes, create a special button to + // mean "the current window size". + if (!have_size) + { + static window_size_t current_size; + current_size.w = window_width; + current_size.h = window_height; + TXT_AddWidget(sizes_table, SizeSelectButton(¤t_size)); + } +} + +static void AdvancedDisplayConfig(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(sizes_table)) +{ + TXT_CAST_ARG(txt_table_t, sizes_table); + txt_window_t *window; + txt_checkbox_t *ar_checkbox; + + window = TXT_NewWindow("Advanced display options"); + + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + TXT_SetColumnWidths(window, 40); + + TXT_AddWidgets(window, + ar_checkbox = TXT_NewCheckBox("Force correct aspect ratio", + &aspect_ratio_correct), + TXT_If(gamemission == heretic || gamemission == hexen + || gamemission == strife, + TXT_NewCheckBox("Graphical startup", &graphical_startup)), + TXT_If(gamemission == doom || gamemission == heretic + || gamemission == strife, + TXT_NewCheckBox("Show ENDOOM screen on exit", + &show_endoom)), +#ifdef HAVE_LIBPNG + TXT_NewCheckBox("Save screenshots in PNG format", + &png_screenshots), +#endif + TXT_NewCheckBox("Smooth pixel scaling", &smooth_pixel_scaling), + NULL); + + TXT_SignalConnect(ar_checkbox, "changed", GenerateSizesTable, sizes_table); +} + +void ConfigDisplay(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + txt_table_t *sizes_table; + txt_window_action_t *advanced_button; + + // Open the window + window = TXT_NewWindow("Display Configuration"); + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + // Build window: + TXT_AddWidgets(window, + TXT_NewCheckBox("Full screen", &fullscreen), + TXT_NewConditional(&fullscreen, 0, + sizes_table = TXT_NewTable(3)), + NULL); + + TXT_SetColumnWidths(window, 42); + + // The window is set at a fixed vertical position. This keeps + // the top of the window stationary when switching between + // fullscreen and windowed mode (which causes the window's + // height to change). + TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, + TXT_SCREEN_W / 2, 6); + + GenerateSizesTable(NULL, sizes_table); + + // Button to open "advanced" window. + // Need to pass a pointer to the window sizes table, as some of the options + // in there trigger a rebuild of it. + advanced_button = TXT_NewWindowAction('a', "Advanced"); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, advanced_button); + TXT_SignalConnect(advanced_button, "pressed", + AdvancedDisplayConfig, sizes_table); +} + +void BindDisplayVariables(void) +{ + M_BindIntVariable("video_display", &video_display); + M_BindIntVariable("aspect_ratio_correct", &aspect_ratio_correct); + M_BindIntVariable("integer_scaling", &integer_scaling); + M_BindIntVariable("smooth_pixel_scaling", &smooth_pixel_scaling); + M_BindIntVariable("fullscreen", &fullscreen); + M_BindIntVariable("fullscreen_width", &fullscreen_width); + M_BindIntVariable("fullscreen_height", &fullscreen_height); + M_BindIntVariable("window_width", &window_width); + M_BindIntVariable("window_height", &window_height); + M_BindIntVariable("startup_delay", &startup_delay); + M_BindStringVariable("video_driver", &video_driver); + M_BindStringVariable("window_position", &window_position); + M_BindIntVariable("usegamma", &usegamma); + M_BindIntVariable("png_screenshots", &png_screenshots); + M_BindIntVariable("vga_porch_flash", &vga_porch_flash); + M_BindIntVariable("force_software_renderer", &force_software_renderer); + M_BindIntVariable("max_scaling_buffer_pixels", &max_scaling_buffer_pixels); + + if (gamemission == doom || gamemission == heretic + || gamemission == strife) + { + M_BindIntVariable("show_endoom", &show_endoom); + } + + if (gamemission == doom || gamemission == strife) + { + M_BindIntVariable("show_diskicon", &show_diskicon); + } + + if (gamemission == heretic || gamemission == hexen || gamemission == strife) + { + M_BindIntVariable("graphical_startup", &graphical_startup); + } +} \ No newline at end of file diff --git a/games/NXDoom/src/setup/display.h b/games/NXDoom/src/setup/display.h new file mode 100644 index 00000000000..0c20c51a2db --- /dev/null +++ b/games/NXDoom/src/setup/display.h @@ -0,0 +1,26 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_DISPLAY_H +#define SETUP_DISPLAY_H + +void ConfigDisplay(void *widget, void *user_data); +void SetDisplayDriver(void); +void BindDisplayVariables(void); + +extern int show_endoom; +extern int graphical_startup; +extern int png_screenshots; + +#endif /* #ifndef SETUP_DISPLAY_H */ diff --git a/games/NXDoom/src/setup/execute.c b/games/NXDoom/src/setup/execute.c new file mode 100644 index 00000000000..2dc0ba85d90 --- /dev/null +++ b/games/NXDoom/src/setup/execute.c @@ -0,0 +1,429 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// Code for invoking Doom + +#include +#include +#include +#include +#include + +#include + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#else + +#include +#include + +#endif + +#include "textscreen.h" + +#include "config.h" +#include "execute.h" +#include "mode.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" + +struct execute_context_s +{ + char *response_file; + FILE *stream; +}; + +// Returns the path to a temporary file of the given name, stored +// inside the system temporary directory. + +static char *TempFile(const char *s) +{ + const char *tempdir; + +#ifdef _WIN32 + // Check the TEMP environment variable to find the location. + + tempdir = M_getenv("TEMP"); + + if (tempdir == NULL) + { + tempdir = "."; + } +#else + // Check the $TMPDIR environment variable to find the location. + + tempdir = getenv("TMPDIR"); + + if (tempdir == NULL) + { + tempdir = "/tmp"; + } +#endif + + return M_StringJoin(tempdir, DIR_SEPARATOR_S, s, NULL); +} + +static int ArgumentNeedsEscape(const char *arg) +{ + const char *p; + + for (p = arg; *p != '\0'; ++p) + { + if (isspace(*p)) + { + return 1; + } + } + + return 0; +} + +// Arguments passed to the setup tool should be passed through to the +// game when launching a game. Calling this adds all arguments from +// myargv to the output context. + +void PassThroughArguments(execute_context_t *context) +{ + int i; + + for (i = 1; i < myargc; ++i) + { + if (ArgumentNeedsEscape(myargv[i])) + { + AddCmdLineParameter(context, "\"%s\"", myargv[i]); + } + else + { + AddCmdLineParameter(context, "%s", myargv[i]); + } + } +} + +execute_context_t *NewExecuteContext(void) +{ + execute_context_t *result; + + result = malloc(sizeof(execute_context_t)); + + result->response_file = TempFile("chocolat.rsp"); + result->stream = M_fopen(result->response_file, "w"); + + if (result->stream == NULL) + { + fprintf(stderr, "Error opening response file\n"); + exit(-1); + } + + return result; +} + +void AddCmdLineParameter(execute_context_t *context, const char *s, ...) +{ + va_list args; + + va_start(args, s); + + vfprintf(context->stream, s, args); + fprintf(context->stream, "\n"); + + va_end(args); +} + +#if defined(_WIN32) + +boolean OpenFolder(const char *path) +{ + // "If the function succeeds, it returns a value greater than 32." + return (int)ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; +} + +// Wait for the specified process to exit. Returns the exit code. +static unsigned int WaitForProcessExit(HANDLE subprocess) +{ + DWORD exit_code; + + for (;;) + { + WaitForSingleObject(subprocess, INFINITE); + + if (!GetExitCodeProcess(subprocess, &exit_code)) + { + return -1; + } + + if (exit_code != STILL_ACTIVE) + { + return exit_code; + } + } +} + +static void ConcatWCString(wchar_t *buf, const char *value) +{ + MultiByteToWideChar(CP_OEMCP, 0, + value, strlen(value) + 1, + buf + wcslen(buf), strlen(value) + 1); +} + +// Build the command line string, a wide character string of the form: +// +// "program" "arg" + +static wchar_t *BuildCommandLine(const char *program, const char *arg) +{ + wchar_t exe_path[MAX_PATH]; + wchar_t *result; + wchar_t *sep; + + // Get the path to this .exe file. + + GetModuleFileNameW(NULL, exe_path, MAX_PATH); + + // Allocate buffer to contain result string. + + result = calloc(wcslen(exe_path) + strlen(program) + strlen(arg) + 6, + sizeof(wchar_t)); + + wcscpy(result, L"\""); + + // Copy the path part of the filename (including ending \) + // into the result buffer: + + sep = wcsrchr(exe_path, DIR_SEPARATOR); + + if (sep != NULL) + { + wcsncpy(result + 1, exe_path, sep - exe_path + 1); + result[sep - exe_path + 2] = '\0'; + } + + // Concatenate the name of the program: + + ConcatWCString(result, program); + + // End of program name, start of argument: + + wcscat(result, L"\" \""); + + ConcatWCString(result, arg); + + wcscat(result, L"\""); + + return result; +} + +static int ExecuteCommand(const char *program, const char *arg) +{ + STARTUPINFOW startup_info; + PROCESS_INFORMATION proc_info; + wchar_t *command; + int result = 0; + + command = BuildCommandLine(program, arg); + + // Invoke the program: + + memset(&proc_info, 0, sizeof(proc_info)); + memset(&startup_info, 0, sizeof(startup_info)); + startup_info.cb = sizeof(startup_info); + + if (!CreateProcessW(NULL, command, + NULL, NULL, FALSE, 0, NULL, NULL, + &startup_info, &proc_info)) + { + result = -1; + } + else + { + // Wait for the process to finish, and save the exit code. + + result = WaitForProcessExit(proc_info.hProcess); + + CloseHandle(proc_info.hProcess); + CloseHandle(proc_info.hThread); + } + + free(command); + + return result; +} + +#else + +boolean OpenFolder(const char *path) +{ + char *cmd; + int result; + +#if defined(__MACOSX__) + cmd = M_StringJoin("open \"", path, "\"", NULL); +#else + cmd = M_StringJoin("xdg-open \"", path, "\"", NULL); +#endif + result = system(cmd); + free(cmd); + + return result == 0; +} + +// Given the specified program name, get the full path to the program, +// assuming that it is in the same directory as this program is. + +static char *GetFullExePath(const char *program) +{ + char *result; + char *sep; + size_t result_len; + unsigned int path_len; + + sep = strrchr(myargv[0], DIR_SEPARATOR); + + if (sep == NULL) + { + result = M_StringDuplicate(program); + } + else + { + path_len = sep - myargv[0] + 1; + result_len = strlen(program) + path_len + 1; + result = malloc(result_len); + + M_StringCopy(result, myargv[0], result_len); + result[path_len] = '\0'; + + M_StringConcat(result, program, result_len); + } + + return result; +} + +static int ExecuteCommand(const char *program, const char *arg) +{ + pid_t childpid; + int result; + const char *argv[3]; + + childpid = fork(); + + if (childpid == 0) + { + // This is the child. Execute the command. + + argv[0] = GetFullExePath(program); + argv[1] = arg; + argv[2] = NULL; + + execvp(argv[0], (char **) argv); + + exit(0x80); + } + else + { + // This is the parent. Wait for the child to finish, and return + // the status code. + + waitpid(childpid, &result, 0); + + if (WIFEXITED(result) && WEXITSTATUS(result) != 0x80) + { + return WEXITSTATUS(result); + } + else + { + return -1; + } + } +} + +#endif + +int ExecuteDoom(execute_context_t *context) +{ + char *response_file_arg; + int result; + + fclose(context->stream); + + // Build the command line + + response_file_arg = M_StringJoin("@", context->response_file, NULL); + + // Run Doom + + result = ExecuteCommand(GetExecutableName(), response_file_arg); + + free(response_file_arg); + + // Destroy context + M_remove(context->response_file); + free(context->response_file); + free(context); + + return result; +} + +static void TestCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) +{ + execute_context_t *exec; + char *main_cfg; + char *extra_cfg; + txt_window_t *testwindow; + + testwindow = TXT_MessageBox("Starting Doom", + "Starting Doom to test the\n" + "settings. Please wait."); + TXT_DrawDesktop(); + + // Save temporary configuration files with the current configuration + + main_cfg = TempFile("tmp.cfg"); + extra_cfg = TempFile("extratmp.cfg"); + + M_SaveDefaultsAlternate(main_cfg, extra_cfg); + + // Run with the -testcontrols parameter + + exec = NewExecuteContext(); + AddCmdLineParameter(exec, "-testcontrols"); + AddCmdLineParameter(exec, "-config \"%s\"", main_cfg); + AddCmdLineParameter(exec, "-extraconfig \"%s\"", extra_cfg); + ExecuteDoom(exec); + + TXT_CloseWindow(testwindow); + + // Delete the temporary config files + + M_remove(main_cfg); + M_remove(extra_cfg); + free(main_cfg); + free(extra_cfg); +} + +txt_window_action_t *TestConfigAction(void) +{ + txt_window_action_t *test_action; + + test_action = TXT_NewWindowAction('t', "Test"); + TXT_SignalConnect(test_action, "pressed", TestCallback, NULL); + + return test_action; +} + diff --git a/games/NXDoom/src/setup/execute.h b/games/NXDoom/src/setup/execute.h new file mode 100644 index 00000000000..21530f14d60 --- /dev/null +++ b/games/NXDoom/src/setup/execute.h @@ -0,0 +1,40 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef TESTCONFIG_H +#define TESTCONFIG_H + +#include "doomtype.h" +#include "textscreen.h" + +typedef struct execute_context_s execute_context_t; + +#define IWAD_DOOM2 (1 << 0) /* doom2.wad */ +#define IWAD_PLUTONIA (1 << 1) /* plutonia.wad */ +#define IWAD_TNT (1 << 2) /* tnt.wad */ +#define IWAD_DOOM (1 << 3) /* doom.wad */ +#define IWAD_DOOM1 (1 << 4) /* doom1.wad */ +#define IWAD_CHEX (1 << 5) /* chex.wad */ + +execute_context_t *NewExecuteContext(void); +void AddCmdLineParameter(execute_context_t *context, const char *s, ...) PRINTF_ATTR(2, 3); +void PassThroughArguments(execute_context_t *context); +int ExecuteDoom(execute_context_t *context); +int FindInstalledIWADs(void); +boolean OpenFolder(const char *path); + +txt_window_action_t *TestConfigAction(void); + +#endif /* #ifndef TESTCONFIG_H */ + diff --git a/games/NXDoom/src/setup/joystick.c b/games/NXDoom/src/setup/joystick.c new file mode 100644 index 00000000000..3a2b5a9089d --- /dev/null +++ b/games/NXDoom/src/setup/joystick.c @@ -0,0 +1,1365 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include +#include + +#include "doomtype.h" +#include "i_joystick.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" +#include "textscreen.h" + +#include "execute.h" +#include "joystick.h" +#include "mode.h" +#include "txt_joyaxis.h" +#include "txt_joybinput.h" + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-gamepad" + +typedef struct +{ + const char *name; // Config file name + int value; +} joystick_config_t; + +typedef struct +{ + const char *name; + int axes, buttons, hats; + const joystick_config_t *configs; +} known_joystick_t; + +// SDL joystick successfully initialized? + +static int joystick_initted = 0; + +// Joystick enable/disable + +static int usejoystick = 0; + +// GUID and index of joystick to use. + +char *joystick_guid = ""; +int joystick_index = -1; + +// Calibration button. This is the button the user pressed at the +// start of the calibration sequence. They *must* press this button +// for each subsequent sequence. + +static int calibrate_button = -1; + +// Which joystick axis to use for horizontal movement, and whether to +// invert the direction: + +static int joystick_x_axis = 0; +static int joystick_x_invert = 0; + +// Which joystick axis to use for vertical movement, and whether to +// invert the direction: + +static int joystick_y_axis = 1; +static int joystick_y_invert = 0; + +// Strafe axis. + +static int joystick_strafe_axis = -1; +static int joystick_strafe_invert = 0; + +// Look axis. + +static int joystick_look_axis = -1; +static int joystick_look_invert = 0; + +// Configurable dead zone for each axis, specified as a percentage of the axis +// max value. +static int joystick_x_dead_zone = 33; +static int joystick_y_dead_zone = 33; +static int joystick_strafe_dead_zone = 33; +static int joystick_look_dead_zone = 33; + +int use_analog = 0; + +int joystick_turn_sensitivity = 10; +int joystick_move_sensitivity = 10; +int joystick_look_sensitivity = 10; + +// Virtual to physical mapping. +int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +}; + +static txt_button_t *joystick_button; +static txt_joystick_axis_t *x_axis_widget; +static txt_joystick_axis_t *y_axis_widget; + +// +// Calibration +// + +static txt_window_t *calibration_window; +static SDL_Joystick **all_joysticks = NULL; +static int all_joysticks_len = 0; + +// Known controllers. +// There are lots of game controllers on the market. Try to configure +// them in a consistent way: +// +// * Use the D-pad rather than an analog stick. left/right turns the +// player, up/down moves forward/backward - ie. a "traditional" +// layout like Vanilla Doom rather than something more elaborate. +// * No strafe axis. +// * Fire and run keys together, on the main right-side buttons, +// ideally arranged so both can be controlled/covered simultaneously +// with the thumb. +// * Jump/use keys in the same cluster if possible. +// * Strafe left/right configured to map to shoulder buttons if they +// are present. No "strafe on" key unless shoulder buttons not present. +// * If a second set of shoulder buttons are also present, these map +// to prev weapon/next weapon. +// * Menu button mapped to start button. +// +// With the common right-side button arrangement that looks like this, +// which is similar to the Vanilla default configuration when using +// a Gravis Gamepad: +// +// B A = Fire +// A D B = Jump +// C C = Speed +// D = Use + +// Always loaded before others, to get a known starting configuration. +static const joystick_config_t empty_defaults[] = +{ + {"joystick_x_axis", -1}, + {"joystick_x_invert", 0}, + {"joystick_y_axis", -1}, + {"joystick_y_invert", 0}, + {"joystick_strafe_axis", -1}, + {"joystick_strafe_invert", 0}, + {"joystick_look_axis", -1}, + {"joystick_look_invert", 0}, + {"joyb_fire", -1}, + {"joyb_use", -1}, + {"joyb_strafe", -1}, + {"joyb_speed", -1}, + {"joyb_strafeleft", -1}, + {"joyb_straferight", -1}, + {"joyb_prevweapon", -1}, + {"joyb_nextweapon", -1}, + {"joyb_jump", -1}, + {"joyb_menu_activate", -1}, + {"joyb_toggle_automap", -1}, + {"joyb_useartifact", -1}, + {"joyb_invleft", -1}, + {"joyb_invright", -1}, + {"joyb_flyup", -1}, + {"joyb_flydown", -1}, + {"joyb_flycenter", -1}, + {"joystick_physical_button0", 0}, + {"joystick_physical_button1", 1}, + {"joystick_physical_button2", 2}, + {"joystick_physical_button3", 3}, + {"joystick_physical_button4", 4}, + {"joystick_physical_button5", 5}, + {"joystick_physical_button6", 6}, + {"joystick_physical_button7", 7}, + {"joystick_physical_button8", 8}, + {"joystick_physical_button9", 9}, + {"joystick_physical_button10", 10}, + {"joystick_physical_button11", 11}, + {"joystick_physical_button12", 12}, + {"joystick_physical_button13", 13}, + {"joystick_physical_button14", 14}, + {"joystick_physical_button15", 15}, + {"joystick_physical_button16", 16}, + {NULL, 0}, +}; + +static const joystick_config_t ps3_controller[] = +{ + {"joystick_x_axis", CREATE_BUTTON_AXIS(7, 5)}, + {"joystick_y_axis", CREATE_BUTTON_AXIS(4, 6)}, + {"joyb_fire", 15}, // Square + {"joyb_speed", 14}, // X + {"joyb_use", 13}, // Circle + {"joyb_jump", 12}, // Triangle + {"joyb_strafeleft", 8}, // Bottom shoulder buttons + {"joyb_straferight", 9}, + {"joyb_prevweapon", 10}, // Top shoulder buttons + {"joyb_nextweapon", 11}, + {"joyb_menu_activate", 3}, // Start + {NULL, 0}, +}; + +// Playstation 4 Dual Shock 4 (DS4) +static const joystick_config_t ps4_ds4_controller[] = +{ + {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, + {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, + {"joyb_fire", 0}, // Square + {"joyb_speed", 1}, // X + {"joyb_use", 2}, // Circle + {"joyb_jump", 3}, // Triangle + {"joyb_strafeleft", 6}, // Bottom shoulder buttons + {"joyb_straferight", 7}, + {"joyb_prevweapon", 4}, // Top shoulder buttons + {"joyb_nextweapon", 5}, + {"joyb_menu_activate", 12}, // Playstation logo button +}; + +static const joystick_config_t airflo_controller[] = +{ + {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, + {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, + {"joyb_fire", 2}, // "3" + {"joyb_speed", 0}, // "1" + {"joyb_jump", 3}, // "4" + {"joyb_use", 1}, // "2" + {"joyb_strafeleft", 6}, // Bottom shoulder buttons + {"joyb_straferight", 7}, + {"joyb_prevweapon", 4}, // Top shoulder buttons + {"joyb_nextweapon", 5}, + {"joyb_menu_activate", 9}, // "10", where "Start" usually is. + {NULL, 0}, +}; + +// Wii controller is weird, so we have to take some liberties. +// Also it's not a HID device, so it won't appear the same everywhere. +// Assume there is no nunchuk or classic controller attached. + +// When using WJoy on OS X. +static const joystick_config_t wii_controller_wjoy[] = +{ + {"joystick_x_axis", CREATE_BUTTON_AXIS(2, 3)}, + {"joystick_y_axis", CREATE_BUTTON_AXIS(1, 0)}, + {"joyb_fire", 9}, // Button 1 + {"joyb_speed", 10}, // Button 2 + {"joyb_use", 5}, // Button B (trigger) + {"joyb_prevweapon", 7}, // - + {"joyb_nextweapon", 6}, // + + {"joyb_menu_activate", 9}, // Button A + {NULL, 0}, +}; + +// Xbox 360 controller. Thanks to Brad Harding for the details. +static const joystick_config_t xbox360_controller[] = +{ + {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, + {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, + {"joystick_strafe_axis", 2}, // Trigger buttons form an axis(???) + {"joyb_fire", 2}, // X + {"joyb_speed", 0}, // A + {"joyb_jump", 3}, // Y + {"joyb_use", 1}, // B + {"joyb_prevweapon", 4}, // LB + {"joyb_nextweapon", 5}, // RB + {"joyb_menu_activate", 9}, // Start + {NULL, 0}, +}; + +// Xbox 360 controller under Linux. +static const joystick_config_t xbox360_controller_linux[] = +{ + {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, + {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, + // Ideally we'd like the trigger buttons to be strafe left/right + // But Linux presents each trigger button as its own axis, which + // we can't really work with. So we have to settle for a + // suboptimal setup. + {"joyb_fire", 2}, // X + {"joyb_speed", 0}, // A + {"joyb_jump", 3}, // Y + {"joyb_use", 1}, // B + {"joyb_strafeleft", 4}, // LB + {"joyb_straferight", 5}, // RB + {"joyb_menu_activate", 7}, // Start + {"joyb_prevweapon", 6}, // Back + {NULL, 0}, +}; + +// Logitech Dual Action (F310, F710). Thanks to Brad Harding for details. +static const joystick_config_t logitech_f310_controller[] = +{ + {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, + {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, + {"joyb_fire", 0}, // X + {"joyb_speed", 1}, // A + {"joyb_jump", 3}, // Y + {"joyb_use", 2}, // B + {"joyb_strafeleft", 6}, // LT + {"joyb_straferight", 7}, // RT + {"joyb_prevweapon", 4}, // LB + {"joyb_nextweapon", 5}, // RB + {"joyb_menu_activate", 11}, // Start + {NULL, 0}, +}; + +// Multilaser JS030 gamepad, similar to a PS2 controller. +static const joystick_config_t multilaser_js030_controller[] = +{ + {"joystick_x_axis", 0}, // Left stick / D-pad + {"joystick_y_axis", 1}, + {"joyb_fire", 3}, // Square + {"joyb_speed", 2}, // X + {"joyb_use", 1}, // Circle + {"joyb_jump", 0}, // Triangle + {"joyb_strafeleft", 6}, // Bottom shoulder buttons + {"joyb_straferight", 7}, + {"joyb_prevweapon", 4}, // Top shoulder buttons + {"joyb_nextweapon", 5}, + {"joyb_menu_activate", 9}, // Start + {NULL, 0}, +}; + +// Buffalo Classic USB Gamepad (thanks Fabian Greffrath). +static const joystick_config_t buffalo_classic_controller[] = +{ + {"joystick_x_axis", 0}, + {"joystick_y_axis", 1}, + {"joyb_use", 0}, // A + {"joyb_speed", 1}, // B + {"joyb_jump", 2}, // X + {"joyb_fire", 3}, // Y + {"joyb_strafeleft", 4}, // Left shoulder + {"joyb_straferight", 5}, // Right shoulder + {"joyb_prevweapon", 6}, // Select + {"joyb_menu_activate", 7}, // Start + {NULL, 0}, +}; + +// Config for if the user is actually using an old PC joystick or gamepad, +// probably via a USB-Gameport adapter. +static const joystick_config_t pc_gameport_controller[] = +{ + {"joystick_x_axis", 0}, + {"joystick_y_axis", 1}, + // Button configuration is the default as used for Vanilla Doom, + // Heretic and Hexen. When playing with a Gravis Gamepad, this + // layout should also be vaguely similar to the standard layout + // described above. + {"joyb_fire", 0}, + {"joyb_strafe", 1}, + {"joyb_use", 3}, + {"joyb_speed", 2}, + {NULL, 0}, +}; + +// http://www.8bitdo.com/nes30pro/ and http://www.8bitdo.com/fc30pro/ +static const joystick_config_t nes30_pro_controller[] = +{ + {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, + {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, + {"joyb_fire", 4}, // Y + {"joyb_speed", 1}, // B + {"joyb_jump", 3}, // X + {"joyb_use", 0}, // A + {"joyb_strafeleft", 6}, // L1 + {"joyb_straferight", 7}, // R1 + {"joyb_prevweapon", 8}, // L2 + {"joyb_nextweapon", 9}, // R2 + {"joyb_menu_activate", 11}, // Start + {"joyb_toggle_automap", 10}, // Select + {NULL, 0}, +}; + +// http://www.8bitdo.com/sfc30/ or http://www.8bitdo.com/snes30/ +// and http://www.nes30.com/ and http://www.fc30.com/ +static const joystick_config_t sfc30_controller[] = +{ + {"joystick_x_axis", 0}, + {"joystick_y_axis", 1}, + {"joyb_fire", 4}, // Y + {"joyb_speed", 1}, // B + {"joyb_jump", 3}, // X + {"joyb_use", 0}, // A + {"joyb_strafeleft", 6}, // L + {"joyb_straferight", 7}, // R + {"joyb_menu_activate", 11}, // Start + {"joyb_toggle_automap", 10}, // Select + {NULL, 0}, +}; + +static const known_joystick_t known_joysticks[] = +{ + { + "PLAYSTATION(R)3 Controller", + 4, 19, 0, + ps3_controller, + }, + + { + "AIRFLO ", + 4, 13, 1, + airflo_controller, + }, + + { + "Wiimote (*", // WJoy includes the Wiimote MAC address. + 6, 26, 0, + wii_controller_wjoy, + }, + + { + "Controller (XBOX 360 For Windows)", + 5, 10, 1, + xbox360_controller, + }, + + { + "Controller (XBOX One For Windows)", + 5, 10, 1, + xbox360_controller, + }, + + // Xbox 360 controller as it appears on Linux. + { + "Microsoft X-Box 360 pad", + 6, 11, 1, + xbox360_controller_linux, + }, + + // Xbox One controller as it appears on Linux. + { + "Microsoft X-Box One pad", + 6, 11, 1, + xbox360_controller_linux, + }, + + { + "Logitech Dual Action", + 4, 12, 1, + logitech_f310_controller, + }, + + { + "USB Vibration Joystick", + 4, 12, 1, + multilaser_js030_controller, + }, + + { + "USB,2-axis 8-button gamepad ", + 2, 8, 0, + buffalo_classic_controller, + }, + + // PS4 controller just appears as the generic-sounding "Wireless + // Controller". Hopefully the number of buttons/axes/hats should be + // enough to distinguish it from other gamepads. + { + "Wireless Controller", + 6, 14, 1, + ps4_ds4_controller, + }, + + // This is the configuration for the USB-Gameport adapter listed on + // this page as the "Mayflash USB to Gameport Adapter" (though the + // device is labeled as "Super Joy Box 7"): + // https://sites.google.com/site/joystickrehab/itemcatal + // TODO: Add extra configurations here for other USB-Gameport adapters, + // which should just be the same configuration. + { + "WiseGroup.,Ltd Gameport to USB Controller", + 4, 8, 1, + pc_gameport_controller, + }, + + // How the Super Joy Box 7 appears on Mac OS X. + { + "Gameport to USB Controller", + 2, 8, 1, + pc_gameport_controller, + }, + + // 8Bitdo NES30 Pro, http://www.8bitdo.com/nes30pro/ + { + "8Bitdo NES30 Pro", + 4, 16, 1, + nes30_pro_controller, + }, + + // the above, NES variant, via USB on Linux/Raspbian (odd values) + { + "8Bitdo NES30 Pro*", + 6, 15, 1, + nes30_pro_controller, + }, + + // the above, NES variant, connected over bluetooth + { + "8Bitdo NES30 Pro", + 6, 16, 1, + nes30_pro_controller, + }, + + // 8bitdo NES30 Pro, in joystick mode (R1+Power), swaps the D-Pad + // and analog stick inputs. Only applicable over Bluetooth. On USB, + // this mode registers the device as an Xbox 360 pad. + { + "8Bitdo NES30 Pro Joystick", + 6, 16, 1, + nes30_pro_controller, + }, + + // variant of the above, via USB on Mac + // Note: untested, but theorized to exist based on us comparing + // a NES30 Pro tested on Linux with a FC30 Pro tested with Mac & Linux + { + "8Bitdo NES30 Pro", + 4, 15, 1, + nes30_pro_controller, + }, + + + // 8Bitdo FC30 Pro, http://8bitdo.cn/fc30pro/ + // connected over bluetooth + { + "8Bitdo FC30 Pro", + 4, 16, 1, + nes30_pro_controller, + }, + + // variant of the above, via USB on Linux/Raspbian + { + "8Bitdo FC30 Pro*", + 6, 15, 1, + nes30_pro_controller, + }, + + // variant of the above, Linux/bluetooth + { + "8Bitdo FC30 Pro", + 6, 16, 1, + nes30_pro_controller, + }, + + // variant of the above, via USB on Mac + { + "8Bitdo FC30 Pro", + 4, 15, 1, + nes30_pro_controller, + }, + + // 8Bitdo SFC30 SNES replica controller + // in default mode and in controller mode (Start+R) + // the latter suffixes "Joystick" to the name + // http://www.8bitdo.com/sfc30/ + { + "8Bitdo SFC30 GamePad*", + 4, 16, 1, + sfc30_controller, + }, + + // As above, but as detected on RHEL Linux (odd extra axes) + { + "8Bitdo SFC30 GamePad*", + 6, 16, 1, + sfc30_controller, + }, + + // SNES30 colour variation of the above + // http://www.8bitdo.com/snes30/ + { + "8Bitdo SNES30 GamePad*", + 4, 16, 1, + sfc30_controller, + }, + + // 8Bitdo SFC30 SNES replica controller in USB controller mode + // tested with firmware V2.68 (Beta); latest stable V2.65 doesn't work on + // OS X in USB controller mode + // Names seen so far: + // 'SFC30 Joystick' (OS X) + // 'SFC30 SFC30 Joystick' (Fedora 24; RHEL7) + // XXX: there is probably a SNES30 variant of this too + { + "SFC30 *", + 4, 12, 1, + sfc30_controller, + }, + + // NES30 (not pro), tested in default and "hold R whilst turning on" + // mode, with whatever firmware it came with out of the box. Latter + // mode puts " Joystick" suffix on the name string + { + "8Bitdo NES30 GamePad*", + 4, 16, 1, + sfc30_controller, // identical to SFC30 + }, + // FC30 variant of the above + { + "8Bitdo FC30 GamePad*", + 4, 16, 1, + sfc30_controller, // identical to SFC30 + }, + + // NES30 in USB mode + { + "NES30*", + 4, 12, 1, + sfc30_controller, // identical to SFC30 + }, + // FC30 variant of the above + { + "FC30*", + 4, 12, 1, + sfc30_controller, // identical to SFC30 + }, +}; + +// Use SDL_GameController interface +int use_gamepad = 0; + +// SDL_GameControllerType of gamepad +int gamepad_type = 0; + +// Based on Unity Doom mapping +static const joystick_config_t modern_gamepad[] = +{ + {"joystick_x_axis", SDL_CONTROLLER_AXIS_RIGHTX}, + {"joystick_y_axis", SDL_CONTROLLER_AXIS_LEFTY}, + {"joystick_strafe_axis", SDL_CONTROLLER_AXIS_LEFTX}, + {"joystick_look_axis", SDL_CONTROLLER_AXIS_RIGHTY}, + {"joyb_fire", GAMEPAD_BUTTON_TRIGGERRIGHT}, + {"joyb_speed", GAMEPAD_BUTTON_TRIGGERLEFT}, + {"joyb_use", SDL_CONTROLLER_BUTTON_B}, + {"joyb_jump", SDL_CONTROLLER_BUTTON_A}, + {"joyb_prevweapon", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, + {"joyb_nextweapon", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, + {"joyb_menu_activate", SDL_CONTROLLER_BUTTON_START}, + {"joyb_toggle_automap", SDL_CONTROLLER_BUTTON_Y}, + {"joyb_useartifact", SDL_CONTROLLER_BUTTON_X}, + {"joyb_invleft", SDL_CONTROLLER_BUTTON_DPAD_LEFT}, + {"joyb_invright", SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, + {"joyb_flyup", SDL_CONTROLLER_BUTTON_DPAD_UP}, + {"joyb_flydown", SDL_CONTROLLER_BUTTON_DPAD_DOWN}, + {"joyb_flycenter", SDL_CONTROLLER_BUTTON_LEFTSTICK}, + {NULL, 0}, +}; + +// Based on the SNES Doom mapping +static const joystick_config_t classic_gamepad[] = +{ + {"joystick_x_axis", SDL_CONTROLLER_AXIS_LEFTX}, + {"joystick_y_axis", SDL_CONTROLLER_AXIS_LEFTY}, + {"joyb_fire", SDL_CONTROLLER_BUTTON_X}, // SNES Y + {"joyb_speed", SDL_CONTROLLER_BUTTON_A}, // SNES B + {"joyb_use", SDL_CONTROLLER_BUTTON_B}, // SNES A + {"joyb_strafeleft", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, // SNES L + {"joyb_straferight", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, // SNES R + {"joyb_nextweapon", SDL_CONTROLLER_BUTTON_Y}, // SNES X + {"joyb_menu_activate", SDL_CONTROLLER_BUTTON_START}, // SNES Start + {"joyb_toggle_automap", SDL_CONTROLLER_BUTTON_BACK}, // SNES Select + {NULL, 0}, +}; + +// SNES Doom mapping with extra shoulder buttons +static const joystick_config_t classic_gamepad_plus[] = +{ + {"joystick_x_axis", SDL_CONTROLLER_AXIS_LEFTX}, + {"joystick_y_axis", SDL_CONTROLLER_AXIS_LEFTY}, + {"joyb_fire", SDL_CONTROLLER_BUTTON_X}, // SNES Y + {"joyb_speed", SDL_CONTROLLER_BUTTON_A}, // SNES B + {"joyb_use", SDL_CONTROLLER_BUTTON_B}, // SNES A + {"joyb_strafeleft", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, // L1 + {"joyb_straferight", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, // R1 + {"joyb_prevweapon", GAMEPAD_BUTTON_TRIGGERLEFT}, // L2 + {"joyb_nextweapon", GAMEPAD_BUTTON_TRIGGERRIGHT}, // R2 + {"joyb_menu_activate", SDL_CONTROLLER_BUTTON_START}, // SNES Start + {"joyb_toggle_automap", SDL_CONTROLLER_BUTTON_BACK}, // SNES Select + {NULL, 0}, +}; + +static const known_joystick_t *GetJoystickType(int index) +{ + SDL_Joystick *joystick; + const char *name; + int axes, buttons, hats; + int i; + + joystick = all_joysticks[index]; + name = SDL_JoystickName(joystick); + axes = SDL_JoystickNumAxes(joystick); + buttons = SDL_JoystickNumButtons(joystick); + hats = SDL_JoystickNumHats(joystick); + + for (i = 0; i < arrlen(known_joysticks); ++i) + { + // Check for a name match. If the name ends in '*', this means + // ignore the rest. + if (M_StringEndsWith(known_joysticks[i].name, "*")) + { + if (strncmp(known_joysticks[i].name, name, + strlen(known_joysticks[i].name) - 1) != 0) + { + continue; + } + } + else + { + if (strcmp(known_joysticks[i].name, name) != 0) + { + continue; + } + } + + if (known_joysticks[i].axes == axes + && known_joysticks[i].buttons == buttons + && known_joysticks[i].hats == hats) + { + return &known_joysticks[i]; + } + } + + printf("Unknown joystick '%s' with %i axes, %i buttons, %i hats\n", + name, axes, buttons, hats); + printf("Please consider sending in details about your gamepad!\n"); + + return NULL; +} + +// Query if the joystick at the given index is a known joystick type. +static boolean IsKnownJoystick(int index) +{ + return GetJoystickType(index) != NULL; +} + +// Load a configuration set. +static void LoadConfigurationSet(const joystick_config_t *configs) +{ + const joystick_config_t *config; + char buf[10]; + int button; + int i; + + button = 0; + + for (i = 0; configs[i].name != NULL; ++i) + { + config = &configs[i]; + + // Don't overwrite autorun if it is set. + if (!strcmp(config->name, "joyb_speed") && + joybspeed >= MAX_VIRTUAL_BUTTONS) + { + continue; + } + + // For buttons, set the virtual button mapping as well. + if (M_StringStartsWith(config->name, "joyb_") && config->value >= 0) + { + joystick_physical_buttons[button] = config->value; + M_snprintf(buf, sizeof(buf), "%i", button); + M_SetVariable(config->name, buf); + ++button; + } + else + { + M_snprintf(buf, sizeof(buf), "%i", config->value); + M_SetVariable(config->name, buf); + } + } +} + +// Load configuration for joystick_index based on known types. +static void LoadKnownConfiguration(void) +{ + const known_joystick_t *jstype; + + jstype = GetJoystickType(joystick_index); + if (jstype == NULL) + { + return; + } + + LoadConfigurationSet(empty_defaults); + LoadConfigurationSet(jstype->configs); +} + +static void InitJoystick(void) +{ + if (!joystick_initted) + { + joystick_initted = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0; + } +} + +static void UnInitJoystick(void) +{ + if (joystick_initted) + { + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + joystick_initted = 0; + } +} + +// We identify joysticks using GUID where possible, but joystick_index +// is used to distinguish between different devices. As the index can +// change, UpdateJoystickIndex() checks to see if it is still valid and +// updates it as appropriate. +static void UpdateJoystickIndex(void) +{ + SDL_JoystickGUID guid, dev_guid; + int i; + + guid = SDL_JoystickGetGUIDFromString(joystick_guid); + + // Is joystick_index already correct? + if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) + { + dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + return; + } + } + + // If index is not correct, look for the first device with the + // expected GUID. It may have moved to a different index. + for (i = 0; i < SDL_NumJoysticks(); ++i) + { + dev_guid = SDL_JoystickGetDeviceGUID(i); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + joystick_index = i; + return; + } + } + + // Not found; it's possible the device is disconnected. Do not + // reset joystick_guid or joystick_index in case they are + // reconnected later. +} + +// Set the label showing the name of the currently selected joystick +static void SetJoystickButtonLabel(void) +{ + SDL_JoystickGUID guid, dev_guid; + const char *name; + + if (!usejoystick || !strcmp(joystick_guid, "")) + { + name = "None set"; + } + else + { + name = "Not found (device disconnected?)"; + + // Use the device name if the GUID and index match. + if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) + { + guid = SDL_JoystickGetGUIDFromString(joystick_guid); + dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); + if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) + { + name = SDL_JoystickNameForIndex(joystick_index); + } + } + } + + TXT_SetButtonLabel(joystick_button, (char *) name); +} + +// Try to open all joysticks visible to SDL. + +static int OpenAllJoysticks(void) +{ + int i; + int result; + + InitJoystick(); + + // SDL_JoystickOpen() all joysticks. + + all_joysticks_len = SDL_NumJoysticks(); + all_joysticks = calloc(all_joysticks_len, sizeof(SDL_Joystick *)); + + result = 0; + + for (i = 0; i < all_joysticks_len; ++i) + { + all_joysticks[i] = SDL_JoystickOpen(i); + + // If any joystick is successfully opened, return true. + + if (all_joysticks[i] != NULL) + { + result = 1; + } + } + + // Success? Turn on joystick events. + + if (result) + { + SDL_JoystickEventState(SDL_ENABLE); + } + else + { + free(all_joysticks); + all_joysticks = NULL; + } + + return result; +} + +// Close all the joysticks opened with OpenAllJoysticks() + +static void CloseAllJoysticks(void) +{ + int i; + + for (i = 0; i < all_joysticks_len; ++i) + { + if (all_joysticks[i] != NULL) + { + SDL_JoystickClose(all_joysticks[i]); + } + } + + SDL_JoystickEventState(SDL_DISABLE); + + free(all_joysticks); + all_joysticks = NULL; + + UnInitJoystick(); +} + +static void CalibrateXAxis(void) +{ + TXT_ConfigureJoystickAxis(x_axis_widget, calibrate_button, NULL); +} + +// Given the SDL_JoystickID instance ID from a button event, set the +// joystick_guid and joystick_index config variables. +static boolean SetJoystickGUID(SDL_JoystickID joy_id) +{ + SDL_JoystickGUID guid; + int i; + + for (i = 0; i < all_joysticks_len; ++i) + { + if (SDL_JoystickInstanceID(all_joysticks[i]) == joy_id) + { + guid = SDL_JoystickGetGUID(all_joysticks[i]); + joystick_guid = malloc(GUID_STRING_BUF_SIZE); + SDL_JoystickGetGUIDString(guid, joystick_guid, + GUID_STRING_BUF_SIZE); + joystick_index = i; + + return true; + } + } + + return false; +} + +static void GetGamepadDefaultConfig(void) +{ + boolean have_four_shoulder, have_dual_sticks; + char *mapping; + SDL_JoystickGUID guid; + + guid = SDL_JoystickGetGUID(all_joysticks[joystick_index]); + mapping = SDL_GameControllerMappingForGUID(guid); + have_four_shoulder = + strstr(mapping, "leftshoulder") && strstr(mapping, "rightshoulder") && + strstr(mapping, "lefttrigger") && strstr(mapping, "righttrigger"); + have_dual_sticks = strstr(mapping, "leftx") && strstr(mapping, "rightx"); + SDL_free(mapping); + + LoadConfigurationSet(empty_defaults); + + if (have_four_shoulder && have_dual_sticks) + { + LoadConfigurationSet(modern_gamepad); + } + else if (have_four_shoulder) + { + LoadConfigurationSet(classic_gamepad_plus); + } + else + { + LoadConfigurationSet(classic_gamepad); + } +} + +static int CalibrationEventCallback(SDL_Event *event, void *user_data) +{ + if (event->type != SDL_JOYBUTTONDOWN) + { + return 0; + } + + if (!SetJoystickGUID(event->jbutton.which)) + { + return 0; + } + + if (SDL_IsGameController(joystick_index)) + { + usejoystick = 1; + use_gamepad = 1; + gamepad_type = SDL_GameControllerTypeForIndex(joystick_index); + LoadConfigurationSet(empty_defaults); + GetGamepadDefaultConfig(); + TXT_CloseWindow(calibration_window); + return 1; + } + + // At this point, we have a button press. + // In the first "center" stage, we're just trying to work out which + // joystick is being configured and which button the user is pressing. + usejoystick = 1; + use_gamepad = 0; + gamepad_type = SDL_CONTROLLER_TYPE_UNKNOWN; + calibrate_button = event->jbutton.button; + + // If the joystick is a known one, auto-load default + // config for it. Otherwise, proceed with calibration. + if (IsKnownJoystick(joystick_index)) + { + LoadKnownConfiguration(); + TXT_CloseWindow(calibration_window); + } + else + { + TXT_CloseWindow(calibration_window); + + // Calibrate joystick axes: Y axis first, then X axis once + // completed. + TXT_ConfigureJoystickAxis(y_axis_widget, calibrate_button, + CalibrateXAxis); + } + + return 1; +} + +static void NoJoystick(void) +{ + TXT_MessageBox(NULL, "No gamepads or joysticks could be found.\n\n" + "Try configuring your controller from within\n" + "your OS first. Maybe you need to install\n" + "some drivers or otherwise configure it."); + + usejoystick = 0; + use_gamepad = 0; + joystick_index = -1; + SetJoystickButtonLabel(); +} + +static void RefreshJoystickWindow(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(unused)) +{ + ConfigJoystick(NULL, NULL); +} + +static void CalibrateWindowClosed(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(joystick_window)) +{ + TXT_CAST_ARG(txt_window_t, joystick_window); + TXT_SDL_SetEventCallback(NULL, NULL); + SetJoystickButtonLabel(); + CloseAllJoysticks(); + + // Refresh Joystick window to update button and axis widgets. + TXT_SignalConnect(joystick_window, "closed", RefreshJoystickWindow, NULL); + TXT_CloseWindow(joystick_window); +} + +static void CalibrateJoystick(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(joystick_window)) +{ + TXT_CAST_ARG(txt_window_t, joystick_window); + + // Try to open all available joysticks. If none are opened successfully, + // bomb out with an error. + + if (!OpenAllJoysticks()) + { + NoJoystick(); + return; + } + + calibration_window = TXT_NewWindow("Gamepad/Joystick calibration"); + + TXT_AddWidgets(calibration_window, + TXT_NewStrut(0, 1), + TXT_NewLabel("Center the D-pad or joystick,\n" + "and press a button."), + TXT_NewStrut(0, 1), + NULL); + + TXT_SetWindowAction(calibration_window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(calibration_window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(calibration_window)); + TXT_SetWindowAction(calibration_window, TXT_HORIZ_RIGHT, NULL); + + TXT_SDL_SetEventCallback(CalibrationEventCallback, NULL); + + TXT_SignalConnect(calibration_window, "closed", CalibrateWindowClosed, + joystick_window); + + // Start calibration +} + +// +// GUI +// + +static void AddJoystickControl(TXT_UNCAST_ARG(table), const char *label, int *var) +{ + TXT_CAST_ARG(txt_table_t, table); + txt_joystick_input_t *joy_input; + + joy_input = TXT_NewJoystickInput(var); + + TXT_AddWidgets(table, + TXT_NewLabel(label), + joy_input, + TXT_TABLE_EMPTY, + NULL); +} + +static void SwapLRSticks(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + // Single pad/stick controllers don't get a joystick_strafe_axis value + if (joystick_strafe_axis >= 0) + { + if (joystick_x_axis == SDL_CONTROLLER_AXIS_LEFTX) + { + joystick_x_axis = SDL_CONTROLLER_AXIS_RIGHTX; + joystick_y_axis = SDL_CONTROLLER_AXIS_LEFTY; + joystick_strafe_axis = SDL_CONTROLLER_AXIS_LEFTX; + joystick_look_axis = SDL_CONTROLLER_AXIS_RIGHTY; + } + else + { + joystick_x_axis = SDL_CONTROLLER_AXIS_LEFTX; + joystick_y_axis = SDL_CONTROLLER_AXIS_RIGHTY; + joystick_strafe_axis = SDL_CONTROLLER_AXIS_RIGHTX; + joystick_look_axis = SDL_CONTROLLER_AXIS_LEFTY; + } + } +} + +static void AdjustAnalog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + txt_window_t *window; + + window = TXT_NewWindow("Analog Settings"); + TXT_SetTableColumns(window, 2); + TXT_SetColumnWidths(window, 10, 6); + TXT_AddWidgets(window, + TXT_NewCheckBox("Use analog controls", &use_analog), + TXT_NewSeparator("Sensitivity"), + TXT_NewLabel("Movement"), + TXT_NewSpinControl(&joystick_move_sensitivity, 0, 20), + TXT_NewLabel("Turn"), + TXT_NewSpinControl(&joystick_turn_sensitivity, 0, 20), + NULL); + if (gamemission == heretic || gamemission == hexen || gamemission == strife) + { + TXT_AddWidgets(window, + TXT_NewLabel("Look"), + TXT_NewSpinControl(&joystick_look_sensitivity, 0, 20), NULL); + } + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowEscapeAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + TXT_SetWidgetAlign(window, TXT_HORIZ_CENTER); +} + +static void MoreControls(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + txt_window_t *window; + + window = TXT_NewWindow("Additional Gamepad/Joystick buttons"); + TXT_SetTableColumns(window, 6); + TXT_SetColumnWidths(window, 20, 10, 1, 20, 10, 0); + + AddJoystickControl(window, "Use inventory item", &joybuseartifact); + AddJoystickControl(window, "Inventory left", &joybinvleft); + AddJoystickControl(window, "Inventory right", &joybinvright); + if (gamemission == heretic || gamemission == hexen) + { + AddJoystickControl(window, "Fly up", &joybflyup); + AddJoystickControl(window, "Fly down", &joybflydown); + AddJoystickControl(window, "Fly center", &joybflycenter); + } + + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowEscapeAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + TXT_SetWidgetAlign(window, TXT_HORIZ_CENTER); +} + +void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + + window = TXT_NewWindow("Gamepad/Joystick configuration"); + TXT_SetTableColumns(window, 6); + TXT_SetColumnWidths(window, 18, 10, 1, 18, 10, 0); + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + TXT_AddWidgets(window, + TXT_NewLabel("Controller"), + joystick_button = TXT_NewButton("zzzz"), + TXT_TABLE_EOL, + + TXT_NewSeparator("Axes"), + TXT_NewLabel("Forward/backward"), + y_axis_widget = TXT_NewJoystickAxis(&joystick_y_axis, + &joystick_y_invert, + &joystick_y_dead_zone, + JOYSTICK_AXIS_VERTICAL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_EMPTY, + TXT_TABLE_EMPTY, + + TXT_NewLabel("Turn left/right"), + x_axis_widget = + TXT_NewJoystickAxis(&joystick_x_axis, + &joystick_x_invert, + &joystick_x_dead_zone, + JOYSTICK_AXIS_HORIZONTAL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_EMPTY, + TXT_TABLE_EMPTY, + + TXT_NewLabel("Strafe left/right"), + TXT_NewJoystickAxis(&joystick_strafe_axis, + &joystick_strafe_invert, + &joystick_strafe_dead_zone, + JOYSTICK_AXIS_HORIZONTAL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_EMPTY, + TXT_TABLE_EMPTY, + NULL); + + if (gamemission == heretic || gamemission == hexen || gamemission == strife) + { + TXT_AddWidgets(window, + TXT_NewLabel("Look up/down"), + TXT_NewJoystickAxis(&joystick_look_axis, + &joystick_look_invert, + &joystick_look_dead_zone, + JOYSTICK_AXIS_VERTICAL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_EMPTY, + TXT_TABLE_EMPTY, + NULL); + } + + TXT_AddWidget(window, + TXT_NewConditional(&use_gamepad, 1, + TXT_NewButton2("Swap L and R sticks", SwapLRSticks, NULL))); + TXT_AddWidget(window, TXT_TABLE_EOL); + + TXT_AddWidget(window, + TXT_NewButton2("Analog settings", AdjustAnalog, NULL)); + TXT_AddWidget(window, TXT_TABLE_EOL); + + TXT_AddWidget(window, TXT_NewSeparator("Buttons")); + + AddJoystickControl(window, "Fire/Attack", &joybfire); + AddJoystickControl(window, "Strafe Left", &joybstrafeleft); + + AddJoystickControl(window, "Use", &joybuse); + AddJoystickControl(window, "Strafe Right", &joybstraferight); + + AddJoystickControl(window, "Previous weapon", &joybprevweapon); + AddJoystickControl(window, "Strafe", &joybstrafe); + + AddJoystickControl(window, "Next weapon", &joybnextweapon); + + // High values of joybspeed are used to activate the "always run mode" + // trick in Vanilla Doom. If this has been enabled, not only is the + // joybspeed value meaningless, but the control itself is useless. + + if (joybspeed < MAX_VIRTUAL_BUTTONS) + { + AddJoystickControl(window, "Run", &joybspeed); + } + + if (gamemission == hexen || gamemission == strife) + { + AddJoystickControl(window, "Jump", &joybjump); + } + + AddJoystickControl(window, "Activate menu", &joybmenu); + + AddJoystickControl(window, "Toggle Automap", &joybautomap); + + if (gamemission == heretic || gamemission == hexen || gamemission == strife) + { + TXT_AddWidget(window, + TXT_NewButton2("More controls...", MoreControls, NULL)); + TXT_AddWidget(window, TXT_TABLE_EOL); + } + + TXT_SignalConnect(joystick_button, "pressed", CalibrateJoystick, window); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); + + InitJoystick(); + UpdateJoystickIndex(); + SetJoystickButtonLabel(); + UnInitJoystick(); +} + +void BindJoystickVariables(void) +{ + int i; + + M_BindIntVariable("use_joystick", &usejoystick); + M_BindIntVariable("use_gamepad", &use_gamepad); + M_BindIntVariable("gamepad_type", &gamepad_type); + M_BindStringVariable("joystick_guid", &joystick_guid); + M_BindIntVariable("joystick_index", &joystick_index); + M_BindIntVariable("joystick_x_axis", &joystick_x_axis); + M_BindIntVariable("joystick_y_axis", &joystick_y_axis); + M_BindIntVariable("joystick_strafe_axis", &joystick_strafe_axis); + M_BindIntVariable("joystick_x_invert", &joystick_x_invert); + M_BindIntVariable("joystick_y_invert", &joystick_y_invert); + M_BindIntVariable("joystick_strafe_invert", &joystick_strafe_invert); + M_BindIntVariable("joystick_look_axis", &joystick_look_axis); + M_BindIntVariable("joystick_look_invert", &joystick_look_invert); + M_BindIntVariable("joystick_x_dead_zone", &joystick_x_dead_zone); + M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone); + M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone); + M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone); + M_BindIntVariable("use_analog", &use_analog); + M_BindIntVariable("joystick_turn_sensitivity", &joystick_turn_sensitivity); + M_BindIntVariable("joystick_move_sensitivity", &joystick_move_sensitivity); + M_BindIntVariable("joystick_look_sensitivity", &joystick_look_sensitivity); + + for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) + { + char name[32]; + M_snprintf(name, sizeof(name), "joystick_physical_button%i", i); + M_BindIntVariable(name, &joystick_physical_buttons[i]); + } +} + diff --git a/games/NXDoom/src/setup/joystick.h b/games/NXDoom/src/setup/joystick.h new file mode 100644 index 00000000000..dd17b7d92f0 --- /dev/null +++ b/games/NXDoom/src/setup/joystick.h @@ -0,0 +1,32 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_JOYSTICK_H +#define SETUP_JOYSTICK_H + + +#include "i_joystick.h" + + +extern int joystick_index; +extern int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS]; +extern int use_gamepad; +extern int gamepad_type; + + +void ConfigJoystick(void *widget, void *user_data); +void BindJoystickVariables(void); + +#endif /* #ifndef SETUP_JOYSTICK_H */ + diff --git a/games/NXDoom/src/setup/keyboard.c b/games/NXDoom/src/setup/keyboard.c new file mode 100644 index 00000000000..02de4f88b3d --- /dev/null +++ b/games/NXDoom/src/setup/keyboard.c @@ -0,0 +1,448 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include "textscreen.h" +#include "doomtype.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" + +#include "execute.h" +#include "txt_keyinput.h" + +#include "mode.h" +#include "joystick.h" +#include "keyboard.h" + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-keyboard" + +int vanilla_keyboard_mapping = 1; + +static int always_run = 0; + +// Keys within these groups cannot have the same value. + +static int *controls[] = { &key_left, &key_right, &key_up, &key_down, + &key_strafeleft, &key_straferight, &key_fire, + &key_use, &key_strafe, &key_speed, &key_jump, + &key_flyup, &key_flydown, &key_flycenter, + &key_lookup, &key_lookdown, &key_lookcenter, + &key_invleft, &key_invright, &key_invquery, + &key_invuse, &key_invpop, &key_mission, &key_invkey, + &key_invhome, &key_invend, &key_invdrop, + &key_useartifact, &key_pause, &key_usehealth, + &key_weapon1, &key_weapon2, &key_weapon3, + &key_weapon4, &key_weapon5, &key_weapon6, + &key_weapon7, &key_weapon8, + &key_arti_quartz, &key_arti_urn, &key_arti_bomb, + &key_arti_tome, &key_arti_ring, &key_arti_chaosdevice, + &key_arti_shadowsphere, &key_arti_wings, + &key_arti_torch, &key_arti_morph, + &key_arti_all, &key_arti_health, &key_arti_poisonbag, + &key_arti_blastradius, &key_arti_teleport, + &key_arti_teleportother, &key_arti_egg, + &key_arti_invulnerability, + &key_prevweapon, &key_nextweapon, NULL }; + +static int *menu_nav[] = { &key_menu_activate, &key_menu_up, &key_menu_down, + &key_menu_left, &key_menu_right, &key_menu_back, + &key_menu_forward, NULL }; + +static int *shortcuts[] = { &key_menu_help, &key_menu_save, &key_menu_load, + &key_menu_volume, &key_menu_detail, &key_menu_qsave, + &key_menu_endgame, &key_menu_messages, &key_spy, + &key_menu_qload, &key_menu_quit, &key_menu_gamma, + &key_menu_incscreen, &key_menu_decscreen, + &key_menu_screenshot, + &key_message_refresh, &key_multi_msg, + &key_multi_msgplayer[0], &key_multi_msgplayer[1], + &key_multi_msgplayer[2], &key_multi_msgplayer[3], NULL }; + +static int *map_keys[] = { &key_map_north, &key_map_south, &key_map_east, + &key_map_west, &key_map_zoomin, &key_map_zoomout, + &key_map_toggle, &key_map_maxzoom, &key_map_follow, + &key_map_grid, &key_map_mark, &key_map_clearmark, + NULL }; + +static void UpdateJoybSpeed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(var)) +{ + if (always_run) + { + /* + if you want to pick one for chocolate doom to use, + pick 29, since that is the most universal one that + also works with heretic, hexen and strife =P + + NB. This choice also works with original, ultimate and final exes. + */ + + joybspeed = 29; + } + else + { + joybspeed = 2; + } +} + +static int VarInGroup(int *variable, int **group) +{ + unsigned int i; + + for (i=0; group[i] != NULL; ++i) + { + if (group[i] == variable) + { + return 1; + } + } + + return 0; +} + +static void CheckKeyGroup(int *variable, int **group) +{ + unsigned int i; + + // Don't check unless the variable is in this group. + + if (!VarInGroup(variable, group)) + { + return; + } + + // If another variable has the same value as the new value, reset it. + + for (i=0; group[i] != NULL; ++i) + { + if (*variable == *group[i] && group[i] != variable) + { + // A different key has the same value. Clear the existing + // value. This ensures that no two keys can have the same + // value. + + *group[i] = 0; + } + } +} + +// Callback invoked when a key control is set + +static void KeySetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) +{ + TXT_CAST_ARG(int, variable); + + CheckKeyGroup(variable, controls); + CheckKeyGroup(variable, menu_nav); + CheckKeyGroup(variable, shortcuts); + CheckKeyGroup(variable, map_keys); +} + +// Add a label and keyboard input to the specified table. + +static void AddKeyControl(TXT_UNCAST_ARG(table), const char *name, int *var) +{ + TXT_CAST_ARG(txt_table_t, table); + txt_key_input_t *key_input; + + TXT_AddWidget(table, TXT_NewLabel(name)); + key_input = TXT_NewKeyInput(var); + TXT_AddWidget(table, key_input); + + TXT_SignalConnect(key_input, "set", KeySetCallback, var); +} + +static void AddSectionLabel(TXT_UNCAST_ARG(table), const char *title, + boolean add_space) +{ + TXT_CAST_ARG(txt_table_t, table); + char buf[64]; + + if (add_space) + { + TXT_AddWidgets(table, + TXT_NewStrut(0, 1), + TXT_TABLE_EOL, + NULL); + } + + M_snprintf(buf, sizeof(buf), " - %s - ", title); + + TXT_AddWidgets(table, + TXT_NewLabel(buf), + TXT_TABLE_EOL, + NULL); +} +static void ConfigExtraKeys(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + txt_window_t *window; + txt_scrollpane_t *scrollpane; + txt_table_t *table; + boolean extra_keys = gamemission == heretic + || gamemission == hexen + || gamemission == strife; + + window = TXT_NewWindow("Extra keyboard controls"); + + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + table = TXT_NewTable(2); + + TXT_SetColumnWidths(table, 21, 9); + + if (extra_keys) + { + // When we have extra controls, a scrollable pane must be used. + + scrollpane = TXT_NewScrollPane(0, 13, table); + TXT_AddWidget(window, scrollpane); + + AddSectionLabel(table, "View", false); + + AddKeyControl(table, "Look up", &key_lookup); + AddKeyControl(table, "Look down", &key_lookdown); + AddKeyControl(table, "Center view", &key_lookcenter); + + if (gamemission == heretic || gamemission == hexen) + { + AddSectionLabel(table, "Flying", true); + + AddKeyControl(table, "Fly up", &key_flyup); + AddKeyControl(table, "Fly down", &key_flydown); + AddKeyControl(table, "Fly center", &key_flycenter); + } + + AddSectionLabel(table, "Inventory", true); + + AddKeyControl(table, "Inventory left", &key_invleft); + AddKeyControl(table, "Inventory right", &key_invright); + + if (gamemission == strife) + { + AddKeyControl(table, "Home", &key_invhome); + AddKeyControl(table, "End", &key_invend); + AddKeyControl(table, "Query", &key_invquery); + AddKeyControl(table, "Drop", &key_invdrop); + AddKeyControl(table, "Show weapons", &key_invpop); + AddKeyControl(table, "Show mission", &key_mission); + AddKeyControl(table, "Show keys", &key_invkey); + AddKeyControl(table, "Use", &key_invuse); + AddKeyControl(table, "Use health", &key_usehealth); + } + else + { + AddKeyControl(table, "Use artifact", &key_useartifact); + } + + if (gamemission == heretic) + { + AddSectionLabel(table, "Artifacts", true); + + AddKeyControl(table, "Quartz Flask", &key_arti_quartz); + AddKeyControl(table, "Mystic Urn", &key_arti_urn); + AddKeyControl(table, "Timebomb", &key_arti_bomb); + AddKeyControl(table, "Tome of Power", &key_arti_tome); + AddKeyControl(table, "Ring of Invincibility ", &key_arti_ring); + AddKeyControl(table, "Chaos Device", &key_arti_chaosdevice); + AddKeyControl(table, "Shadowsphere", &key_arti_shadowsphere); + AddKeyControl(table, "Wings of Wrath", &key_arti_wings); + AddKeyControl(table, "Torch", &key_arti_torch); + AddKeyControl(table, "Morph Ovum", &key_arti_morph); + } + + if (gamemission == hexen) + { + AddSectionLabel(table, "Artifacts", true); + + AddKeyControl(table, "One of each", &key_arti_all); + AddKeyControl(table, "Quartz Flask", &key_arti_health); + AddKeyControl(table, "Flechette", &key_arti_poisonbag); + AddKeyControl(table, "Disc of Repulsion", &key_arti_blastradius); + AddKeyControl(table, "Chaos Device", &key_arti_teleport); + AddKeyControl(table, "Banishment Device", &key_arti_teleportother); + AddKeyControl(table, "Porkalator", &key_arti_egg); + AddKeyControl(table, "Icon of the Defender", + &key_arti_invulnerability); + } + } + else + { + TXT_AddWidget(window, table); + } + + AddSectionLabel(table, "Weapons", extra_keys); + + AddKeyControl(table, "Weapon 1", &key_weapon1); + AddKeyControl(table, "Weapon 2", &key_weapon2); + AddKeyControl(table, "Weapon 3", &key_weapon3); + AddKeyControl(table, "Weapon 4", &key_weapon4); + AddKeyControl(table, "Weapon 5", &key_weapon5); + AddKeyControl(table, "Weapon 6", &key_weapon6); + AddKeyControl(table, "Weapon 7", &key_weapon7); + AddKeyControl(table, "Weapon 8", &key_weapon8); + AddKeyControl(table, "Previous weapon", &key_prevweapon); + AddKeyControl(table, "Next weapon", &key_nextweapon); +} + +static void OtherKeysDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + txt_window_t *window; + txt_table_t *table; + txt_scrollpane_t *scrollpane; + + window = TXT_NewWindow("Other keys"); + + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + table = TXT_NewTable(2); + + TXT_SetColumnWidths(table, 25, 9); + + AddSectionLabel(table, "Menu navigation", false); + + AddKeyControl(table, "Activate menu", &key_menu_activate); + AddKeyControl(table, "Move cursor up", &key_menu_up); + AddKeyControl(table, "Move cursor down", &key_menu_down); + AddKeyControl(table, "Move slider left", &key_menu_left); + AddKeyControl(table, "Move slider right", &key_menu_right); + AddKeyControl(table, "Go to previous menu", &key_menu_back); + AddKeyControl(table, "Activate menu item", &key_menu_forward); + AddKeyControl(table, "Confirm action", &key_menu_confirm); + AddKeyControl(table, "Cancel action", &key_menu_abort); + + AddSectionLabel(table, "Shortcut keys", true); + + AddKeyControl(table, "Pause game", &key_pause); + AddKeyControl(table, "Help screen", &key_menu_help); + AddKeyControl(table, "Save game", &key_menu_save); + AddKeyControl(table, "Load game", &key_menu_load); + AddKeyControl(table, "Sound volume", &key_menu_volume); + AddKeyControl(table, "Toggle detail", &key_menu_detail); + AddKeyControl(table, "Quick save", &key_menu_qsave); + AddKeyControl(table, "End game", &key_menu_endgame); + AddKeyControl(table, "Toggle messages", &key_menu_messages); + AddKeyControl(table, "Quick load", &key_menu_qload); + AddKeyControl(table, "Quit game", &key_menu_quit); + AddKeyControl(table, "Toggle gamma", &key_menu_gamma); + AddKeyControl(table, "Multiplayer spy", &key_spy); + + AddKeyControl(table, "Increase screen size", &key_menu_incscreen); + AddKeyControl(table, "Decrease screen size", &key_menu_decscreen); + AddKeyControl(table, "Save a screenshot", &key_menu_screenshot); + + AddKeyControl(table, "Display last message", &key_message_refresh); + AddKeyControl(table, "Finish recording demo", &key_demo_quit); + + AddSectionLabel(table, "Map", true); + AddKeyControl(table, "Toggle map", &key_map_toggle); + AddKeyControl(table, "Zoom in", &key_map_zoomin); + AddKeyControl(table, "Zoom out", &key_map_zoomout); + AddKeyControl(table, "Maximum zoom out", &key_map_maxzoom); + AddKeyControl(table, "Follow mode", &key_map_follow); + AddKeyControl(table, "Pan north", &key_map_north); + AddKeyControl(table, "Pan south", &key_map_south); + AddKeyControl(table, "Pan east", &key_map_east); + AddKeyControl(table, "Pan west", &key_map_west); + AddKeyControl(table, "Toggle grid", &key_map_grid); + AddKeyControl(table, "Mark location", &key_map_mark); + AddKeyControl(table, "Clear all marks", &key_map_clearmark); + + AddSectionLabel(table, "Multiplayer", true); + + AddKeyControl(table, "Send message", &key_multi_msg); + AddKeyControl(table, "- to player 1", &key_multi_msgplayer[0]); + AddKeyControl(table, "- to player 2", &key_multi_msgplayer[1]); + AddKeyControl(table, "- to player 3", &key_multi_msgplayer[2]); + AddKeyControl(table, "- to player 4", &key_multi_msgplayer[3]); + + if (gamemission == hexen || gamemission == strife) + { + AddKeyControl(table, "- to player 5", &key_multi_msgplayer[4]); + AddKeyControl(table, "- to player 6", &key_multi_msgplayer[5]); + AddKeyControl(table, "- to player 7", &key_multi_msgplayer[6]); + AddKeyControl(table, "- to player 8", &key_multi_msgplayer[7]); + } + + scrollpane = TXT_NewScrollPane(0, 13, table); + + TXT_AddWidget(window, scrollpane); +} + +void ConfigKeyboard(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + txt_checkbox_t *run_control; + + always_run = joybspeed >= 20; + + window = TXT_NewWindow("Keyboard configuration"); + + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + // The window is on a 5-column grid layout that looks like: + // Label | Control | | Label | Control + // There is a small gap between the two conceptual "columns" of + // controls, just for spacing. + TXT_SetTableColumns(window, 5); + TXT_SetColumnWidths(window, 15, 8, 2, 15, 8); + + TXT_AddWidget(window, TXT_NewSeparator("Movement")); + AddKeyControl(window, "Move Forward", &key_up); + TXT_AddWidget(window, TXT_TABLE_EMPTY); + AddKeyControl(window, "Strafe Left", &key_strafeleft); + + AddKeyControl(window, "Move Backward", &key_down); + TXT_AddWidget(window, TXT_TABLE_EMPTY); + AddKeyControl(window, "Strafe Right", &key_straferight); + + AddKeyControl(window, "Turn Left", &key_left); + TXT_AddWidget(window, TXT_TABLE_EMPTY); + AddKeyControl(window, "Run", &key_speed); + + AddKeyControl(window, "Turn Right", &key_right); + TXT_AddWidget(window, TXT_TABLE_EMPTY); + AddKeyControl(window, "Strafe On", &key_strafe); + + if (gamemission == hexen || gamemission == strife) + { + AddKeyControl(window, "Jump", &key_jump); + } + + TXT_AddWidget(window, TXT_NewSeparator("Action")); + AddKeyControl(window, "Fire/Attack", &key_fire); + TXT_AddWidget(window, TXT_TABLE_EMPTY); + AddKeyControl(window, "Use", &key_use); + + TXT_AddWidgets(window, + TXT_NewButton2("More controls...", ConfigExtraKeys, NULL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_TABLE_EMPTY, + TXT_NewButton2("Other keys...", OtherKeysDialog, NULL), + TXT_TABLE_OVERFLOW_RIGHT, + + TXT_NewSeparator("Misc."), + run_control = TXT_NewCheckBox("Always run", &always_run), + TXT_TABLE_EOL, + TXT_NewInvertedCheckBox("Use native keyboard mapping", + &vanilla_keyboard_mapping), + TXT_TABLE_EOL, + NULL); + + TXT_SignalConnect(run_control, "changed", UpdateJoybSpeed, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); +} + +void BindKeyboardVariables(void) +{ + M_BindIntVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); +} diff --git a/games/NXDoom/src/setup/keyboard.h b/games/NXDoom/src/setup/keyboard.h new file mode 100644 index 00000000000..81b8b91a26c --- /dev/null +++ b/games/NXDoom/src/setup/keyboard.h @@ -0,0 +1,23 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_KEYBOARD_H +#define SETUP_KEYBOARD_H + +void ConfigKeyboard(void *widget, void *user_data); +void BindKeyboardVariables(void); + +extern int vanilla_keyboard_mapping; + +#endif /* #ifndef SETUP_KEYBOARD_H */ diff --git a/games/NXDoom/src/setup/mainmenu.c b/games/NXDoom/src/setup/mainmenu.c new file mode 100644 index 00000000000..94b765f3796 --- /dev/null +++ b/games/NXDoom/src/setup/mainmenu.c @@ -0,0 +1,346 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include +#include + +#include "config.h" +#include "textscreen.h" + +#include "execute.h" + +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" +#include "z_zone.h" + +#include "setup_icon.c" +#include "mode.h" + +#include "compatibility.h" +#include "display.h" +#include "joystick.h" +#include "keyboard.h" +#include "mouse.h" +#include "multiplayer.h" +#include "sound.h" + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup" + +static const int cheat_sequence[] = +{ + KEY_UPARROW, KEY_UPARROW, KEY_DOWNARROW, KEY_DOWNARROW, + KEY_LEFTARROW, KEY_RIGHTARROW, KEY_LEFTARROW, KEY_RIGHTARROW, + 'b', 'a', KEY_ENTER, 0 +}; + +static unsigned int cheat_sequence_index = 0; + +// I think these are good "sensible" defaults: + +static void SensibleDefaults(void) +{ + key_up = 'w'; + key_down = 's'; + key_strafeleft = 'a'; + key_straferight = 'd'; + key_jump = '/'; + key_lookup = KEY_PGUP; + key_lookdown = KEY_PGDN; + key_lookcenter = KEY_HOME; + key_flyup = KEY_INS; + key_flydown = KEY_DEL; + key_flycenter = KEY_END; + key_prevweapon = ','; + key_nextweapon = '.'; + key_invleft = '['; + key_invright = ']'; + key_message_refresh = '\''; + key_mission = 'i'; // Strife keys + key_invpop = 'o'; + key_invkey = 'p'; + key_multi_msgplayer[0] = 'g'; + key_multi_msgplayer[1] = 'h'; + key_multi_msgplayer[2] = 'j'; + key_multi_msgplayer[3] = 'k'; + key_multi_msgplayer[4] = 'v'; + key_multi_msgplayer[5] = 'b'; + key_multi_msgplayer[6] = 'n'; + key_multi_msgplayer[7] = 'm'; + mousebprevweapon = 4; // Scroll wheel = weapon cycle + mousebnextweapon = 3; + snd_musicdevice = 3; + joybspeed = 29; // Always run + vanilla_savegame_limit = 0; + vanilla_keyboard_mapping = 0; + vanilla_demo_limit = 0; + graphical_startup = 0; + show_endoom = 0; + dclick_use = 0; + novert = 1; + snd_dmxoption = "-opl3 -reverse"; + png_screenshots = 1; +} + +static int MainMenuKeyPress(txt_window_t *window, int key, void *user_data) +{ + if (key == cheat_sequence[cheat_sequence_index]) + { + ++cheat_sequence_index; + + if (cheat_sequence[cheat_sequence_index] == 0) + { + SensibleDefaults(); + cheat_sequence_index = 0; + + window = TXT_MessageBox(NULL, " \x01 "); + + return 1; + } + } + else + { + cheat_sequence_index = 0; + } + + return 0; +} + +static void DoQuit(void *widget, void *dosave) +{ + if (dosave != NULL) + { + M_SaveDefaults(); + } + + TXT_Shutdown(); + + exit(0); +} + +static void QuitConfirm(void *unused1, void *unused2) +{ + txt_window_t *window; + txt_label_t *label; + txt_button_t *yes_button; + txt_button_t *no_button; + + window = TXT_NewWindow(NULL); + + TXT_AddWidgets(window, + label = TXT_NewLabel("Exiting setup.\nSave settings?"), + TXT_NewStrut(24, 0), + yes_button = TXT_NewButton2(" Yes ", DoQuit, DoQuit), + no_button = TXT_NewButton2(" No ", DoQuit, NULL), + NULL); + + TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); + TXT_SetWidgetAlign(yes_button, TXT_HORIZ_CENTER); + TXT_SetWidgetAlign(no_button, TXT_HORIZ_CENTER); + + // Only an "abort" button in the middle. + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); +} + +static void LaunchDoom(void *unused1, void *unused2) +{ + execute_context_t *exec; + + // Save configuration first + + M_SaveDefaults(); + + // Shut down textscreen GUI + + TXT_Shutdown(); + + // Launch Doom + + exec = NewExecuteContext(); + PassThroughArguments(exec); + ExecuteDoom(exec); + + exit(0); +} + +static txt_button_t *GetLaunchButton(void) +{ + const char *label; + + switch (gamemission) + { + case doom: + label = "Save parameters and launch DOOM"; + break; + case heretic: + label = "Save parameters and launch Heretic"; + break; + case hexen: + label = "Save parameters and launch Hexen"; + break; + case strife: + label = "Save parameters and launch STRIFE!"; + break; + default: + label = "Save parameters and launch game"; + break; + } + + return TXT_NewButton2(label, LaunchDoom, NULL); +} + +void MainMenu(void) +{ + txt_window_t *window; + txt_window_action_t *quit_action; + txt_window_action_t *warp_action; + + window = TXT_NewWindow("Main Menu"); + + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + TXT_AddWidgets(window, + TXT_NewButton2("Configure Display", + (TxtWidgetSignalFunc) ConfigDisplay, NULL), + TXT_NewButton2("Configure Sound", + (TxtWidgetSignalFunc) ConfigSound, NULL), + TXT_NewButton2("Configure Keyboard", + (TxtWidgetSignalFunc) ConfigKeyboard, NULL), + TXT_NewButton2("Configure Mouse", + (TxtWidgetSignalFunc) ConfigMouse, NULL), + TXT_NewButton2("Configure Gamepad/Joystick", + (TxtWidgetSignalFunc) ConfigJoystick, NULL), + TXT_NewButton2("Compatibility", + (TxtWidgetSignalFunc) CompatibilitySettings, NULL), + GetLaunchButton(), + TXT_NewStrut(0, 1), + TXT_NewButton2("Start a Network Game", + (TxtWidgetSignalFunc) StartMultiGame, NULL), + TXT_NewButton2("Join a Network Game", + (TxtWidgetSignalFunc) JoinMultiGame, NULL), + TXT_NewButton2("Multiplayer Configuration", + (TxtWidgetSignalFunc) MultiplayerConfig, NULL), + NULL); + + quit_action = TXT_NewWindowAction(KEY_ESCAPE, "Quit"); + warp_action = TXT_NewWindowAction(KEY_F2, "Warp"); + TXT_SignalConnect(quit_action, "pressed", QuitConfirm, NULL); + TXT_SignalConnect(warp_action, "pressed", + (TxtWidgetSignalFunc) WarpMenu, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, quit_action); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, warp_action); + + TXT_SetKeyListener(window, MainMenuKeyPress, NULL); +} + +// +// Initialize all configuration variables, load config file, etc +// + +static void InitConfig(void) +{ + M_SetConfigDir(NULL); + InitBindings(); + + SetChatMacroDefaults(); + SetPlayerNameDefault(); + + M_LoadDefaults(); + + // Create and configure the music pack directory if it does not + // already exist. + M_SetMusicPackDir(); +} + +// +// Application icon +// + +static void SetIcon(void) +{ + SDL_Surface *surface; + + surface = SDL_CreateRGBSurfaceFrom((void *) setup_icon_data, setup_icon_w, + setup_icon_h, 32, setup_icon_w * 4, + 0xffu << 24, 0xffu << 16, + 0xffu << 8, 0xffu << 0); + + SDL_SetWindowIcon(TXT_SDLWindow, surface); + SDL_FreeSurface(surface); +} + +static void SetWindowTitle(void) +{ + char *title; + + title = M_StringReplace(PACKAGE_NAME " Setup ver " PACKAGE_VERSION, + "Doom", + GetGameTitle()); + + + TXT_SetDesktopTitle(title); + + free(title); +} + +// Initialize the textscreen library. + +static void InitTextscreen(void) +{ + SetDisplayDriver(); + + if (!TXT_Init()) + { + fprintf(stderr, "Failed to initialize GUI\n"); + exit(-1); + } + + // Set Romero's "funky blue" color: + // + TXT_SetColor(TXT_COLOR_BLUE, 0x04, 0x14, 0x40); + + SetIcon(); + SetWindowTitle(); +} + + +// +// Initialize and run the textscreen GUI. +// + +static void RunGUI(void) +{ + InitTextscreen(); + + TXT_GUIMainLoop(); +} + +static void MissionSet(void) +{ + SetWindowTitle(); + InitConfig(); + MainMenu(); +} + +void D_DoomMain(void) +{ + SetupMission(MissionSet); + + RunGUI(); +} diff --git a/games/NXDoom/src/setup/mode.c b/games/NXDoom/src/setup/mode.c new file mode 100644 index 00000000000..0f604094315 --- /dev/null +++ b/games/NXDoom/src/setup/mode.c @@ -0,0 +1,384 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include + +#include "doomtype.h" + +#include "config.h" +#include "textscreen.h" + +#include "doomtype.h" +#include "d_mode.h" +#include "d_iwad.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" + +#include "compatibility.h" +#include "display.h" +#include "joystick.h" +#include "keyboard.h" +#include "mouse.h" +#include "multiplayer.h" +#include "sound.h" + +#include "mode.h" + +GameMission_t gamemission; +static const iwad_t **iwads; + +typedef struct +{ + const char *label; + GameMission_t mission; + int mask; + const char *name; + const char *config_file; + const char *extra_config_file; + const char *executable; +} mission_config_t; + +// Default mission to fall back on, if no IWADs are found at all: + +#define DEFAULT_MISSION (&mission_configs[0]) + +static mission_config_t mission_configs[] = +{ + { + "Doom", + doom, + IWAD_MASK_DOOM, + "doom", + "default.cfg", + PROGRAM_PREFIX "doom.cfg", + PROGRAM_PREFIX "doom" + }, + { + "Heretic", + heretic, + IWAD_MASK_HERETIC, + "heretic", + "heretic.cfg", + PROGRAM_PREFIX "heretic.cfg", + PROGRAM_PREFIX "heretic" + }, + { + "Hexen", + hexen, + IWAD_MASK_HEXEN, + "hexen", + "hexen.cfg", + PROGRAM_PREFIX "hexen.cfg", + PROGRAM_PREFIX "hexen" + }, + { + "Strife", + strife, + IWAD_MASK_STRIFE, + "strife", + "strife.cfg", + PROGRAM_PREFIX "strife.cfg", + PROGRAM_PREFIX "strife" + } +}; + +static GameSelectCallback game_selected_callback; + +// Miscellaneous variables that aren't used in setup. + +static int showMessages = 1; +static int screenblocks = 9; +static int detailLevel = 0; +static char *savedir = NULL; +static char *executable = NULL; +static const char *game_title = "Doom"; +static char *back_flat = "F_PAVE01"; +static int comport = 0; +static char *nickname = NULL; + +static void BindMiscVariables(void) +{ + if (gamemission == doom) + { + M_BindIntVariable("detaillevel", &detailLevel); + M_BindIntVariable("show_messages", &showMessages); + } + + if (gamemission == hexen) + { + M_BindStringVariable("savedir", &savedir); + M_BindIntVariable("messageson", &showMessages); + + // Hexen has a variable to control the savegame directory + // that is used. + + savedir = M_GetSaveGameDir("hexen.wad"); + + // On Windows, hexndata\ is the default. + + if (!strcmp(savedir, "")) + { + free(savedir); + savedir = "hexndata" DIR_SEPARATOR_S; + } + } + + if (gamemission == strife) + { + // Strife has a different default value than the other games + screenblocks = 10; + + M_BindStringVariable("back_flat", &back_flat); + M_BindStringVariable("nickname", &nickname); + + M_BindIntVariable("screensize", &screenblocks); + M_BindIntVariable("comport", &comport); + } + else + { + M_BindIntVariable("screenblocks", &screenblocks); + } + +} + +// +// Initialise all configuration file bindings. +// + +void InitBindings(void) +{ + M_ApplyPlatformDefaults(); + + // Keyboard, mouse, joystick controls + + M_BindBaseControls(); + M_BindWeaponControls(); + M_BindMapControls(); + M_BindMenuControls(); + + if (gamemission == heretic || gamemission == hexen) + { + M_BindHereticControls(); + } + + if (gamemission == hexen) + { + M_BindHexenControls(); + } + + if (gamemission == strife) + { + M_BindStrifeControls(); + } + + // All other variables + + BindCompatibilityVariables(); + BindDisplayVariables(); + BindJoystickVariables(); + BindKeyboardVariables(); + BindMouseVariables(); + BindSoundVariables(); + BindMiscVariables(); + BindMultiplayerVariables(); +} + +// Set the name of the executable program to run the game: + +static void SetExecutable(mission_config_t *config) +{ + char *extension; + + free(executable); + +#ifdef _WIN32 + extension = ".exe"; +#else + extension = ""; +#endif + + executable = M_StringJoin(config->executable, extension, NULL); +} + +static void SetMission(mission_config_t *config) +{ + iwads = D_FindAllIWADs(config->mask); + gamemission = config->mission; + SetExecutable(config); + game_title = config->label; + M_SetConfigFilenames(config->config_file, config->extra_config_file); +} + +static mission_config_t *GetMissionForName(const char *name) +{ + int i; + + for (i=0; iname) != NULL) + { + SetMission(config); + callback(); + return true; + } + } + + return false; +} + +static void GameSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(config)) +{ + TXT_CAST_ARG(mission_config_t, config); + + SetMission(config); + game_selected_callback(); +} + +static void OpenGameSelectDialog(GameSelectCallback callback) +{ + mission_config_t *mission = NULL; + txt_window_t *window; + const iwad_t **iwads; + int num_games; + int i; + + window = TXT_NewWindow("Select game"); + + TXT_AddWidget(window, TXT_NewLabel("Select a game to configure:\n")); + num_games = 0; + + // Add a button for each game. + + for (i=0; i + // + // Specify the game to configure the settings for. Valid + // values are 'doom', 'heretic', 'hexen' and 'strife'. + // + + p = M_CheckParm("-game"); + + if (p > 0) + { + mission_name = myargv[p + 1]; + + config = GetMissionForName(mission_name); + + if (config == NULL) + { + I_Error("Invalid parameter - '%s'", mission_name); + } + + SetMission(config); + callback(); + } + else if (!CheckExecutableName(callback)) + { + OpenGameSelectDialog(callback); + } +} + +const char *GetExecutableName(void) +{ + return executable; +} + +const char *GetGameTitle(void) +{ + return game_title; +} + +const iwad_t **GetIwads(void) +{ + return iwads; +} + diff --git a/games/NXDoom/src/setup/mode.h b/games/NXDoom/src/setup/mode.h new file mode 100644 index 00000000000..2687a4889aa --- /dev/null +++ b/games/NXDoom/src/setup/mode.h @@ -0,0 +1,31 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_MODE_H +#define SETUP_MODE_H + +#include "d_mode.h" +#include "d_iwad.h" + +typedef void (*GameSelectCallback)(void); +extern GameMission_t gamemission; + +void SetupMission(GameSelectCallback callback); +void InitBindings(void); +const char *GetExecutableName(void); +const char *GetGameTitle(void); +const iwad_t **GetIwads(void); + +#endif /* #ifndef SETUP_MODE_H */ + diff --git a/games/NXDoom/src/setup/mouse.c b/games/NXDoom/src/setup/mouse.c new file mode 100644 index 00000000000..95a83320928 --- /dev/null +++ b/games/NXDoom/src/setup/mouse.c @@ -0,0 +1,176 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include + +#include "textscreen.h" +#include "doomtype.h" +#include "m_config.h" +#include "m_controls.h" + +#include "execute.h" +#include "txt_mouseinput.h" + +#include "mode.h" +#include "mouse.h" + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-mouse" + +static int usemouse = 1; + +static int mouseSensitivity = 5; +static float mouse_acceleration = 2.0; +static int mouse_threshold = 10; +static int grabmouse = 1; + +int novert = 0; + +static int *all_mouse_buttons[] = { + &mousebfire, + &mousebstrafe, + &mousebforward, + &mousebstrafeleft, + &mousebstraferight, + &mousebbackward, + &mousebuse, + &mousebjump, + &mousebprevweapon, + &mousebnextweapon, + &mousebspeed, + &mousebinvleft, + &mousebinvright, + &mousebuseartifact, + &mousebturnleft, + &mousebturnright, +}; + +static void MouseSetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) +{ + TXT_CAST_ARG(int, variable); + unsigned int i; + + // Check if the same mouse button is used for a different action + // If so, set the other action(s) to -1 (unset) + + for (i=0; i +#include +#include + +#include "doomtype.h" + +#include "textscreen.h" + +#include "d_iwad.h" +#include "m_config.h" +#include "m_misc.h" +#include "doom/d_englsh.h" +#include "m_controls.h" + +#include "multiplayer.h" +#include "mode.h" +#include "execute.h" + +#include "net_io.h" +#include "net_query.h" + +#include "net_petname.h" + +#define MULTI_START_HELP_URL "https://www.chocolate-doom.org/setup-multi-start" +#define MULTI_JOIN_HELP_URL "https://www.chocolate-doom.org/setup-multi-join" +#define MULTI_CONFIG_HELP_URL "https://www.chocolate-doom.org/setup-multi-config" +#define LEVEL_WARP_HELP_URL "https://www.chocolate-doom.org/setup-level-warp" + +#define NUM_WADS 10 +#define NUM_EXTRA_PARAMS 10 + +typedef enum +{ + WARP_ExMy, + WARP_MAPxy, +} warptype_t; + +// Fallback IWADs to use if no IWADs are detected. + +static const iwad_t fallback_iwads[] = { + { "doom.wad", doom, registered, "Doom" }, + { "heretic.wad", heretic, retail, "Heretic" }, + { "hexen.wad", hexen, commercial, "Hexen" }, + { "strife1.wad", strife, commercial, "Strife" }, +}; + +// Array of IWADs found to be installed + +static const iwad_t **found_iwads; +static const char **iwad_labels; + +// Index of the currently selected IWAD + +static int found_iwad_selected = -1; + +// Filename to pass to '-iwad'. + +static const char *iwadfile; + +static const char *wad_extensions[] = { "wad", "lmp", "deh", NULL }; + +static const char *doom_skills[] = +{ + "I'm too young to die.", "Hey, not too rough.", "Hurt me plenty.", + "Ultra-Violence.", "NIGHTMARE!", +}; + +static const char *chex_skills[] = +{ + "Easy does it", "Not so sticky", "Gobs of goo", "Extreme ooze", + "SUPER SLIMEY!" +}; + +static const char *heretic_skills[] = +{ + "Thou needeth a wet-nurse", "Yellowbellies-R-us", "Bringest them oneth", + "Thou art a smite-meister", "Black plague possesses thee" +}; + +static const char *hexen_fighter_skills[] = +{ + "Squire", "Knight", "Warrior", "Berserker", "Titan" +}; + +static const char *hexen_cleric_skills[] = +{ + "Altar boy", "Acolyte", "Priest", "Cardinal", "Pope" +}; + +static const char *hexen_mage_skills[] = +{ + "Apprentice", "Enchanter", "Sorceror", "Warlock", "Archimage" +}; + +static const char *strife_skills[] = +{ + "Training", "Rookie", "Veteran", "Elite", "Bloodbath" +}; + +static const char *character_classes[] = { "Fighter", "Cleric", "Mage" }; + +static const char *gamemodes[] = { "Co-operative", "Deathmatch", "Deathmatch 2.0" }; + +static const char *strife_gamemodes[] = +{ + "Normal deathmatch", + "Items respawn", // (altdeath) +}; + +static char *net_player_name; +static char *chat_macros[10]; + +static char *wads[NUM_WADS]; +static char *extra_params[NUM_EXTRA_PARAMS]; +static int character_class = 0; +static int skill = 2; +static int nomonsters = 0; +static int deathmatch = 0; +static int strife_altdeath = 0; +static int fast = 0; +static int respawn = 0; +static int udpport = 2342; +static int timer = 0; +static int privateserver = 0; + +static txt_dropdown_list_t *skillbutton; +static txt_button_t *warpbutton; +static warptype_t warptype = WARP_MAPxy; +static int warpepisode = 1; +static int warpmap = 1; + +// Address to connect to when joining a game + +static char *connect_address = NULL; + +static txt_window_t *query_window; +static int query_servers_found; + +// Find an IWAD from its description + +static const iwad_t *GetCurrentIWAD(void) +{ + return found_iwads[found_iwad_selected]; +} + +// Is the currently selected IWAD the Chex Quest chex.wad? + +static boolean IsChexQuest(const iwad_t *iwad) +{ + return !strcmp(iwad->name, "chex.wad"); +} + +static void AddWADs(execute_context_t *exec) +{ + int have_wads = 0; + int i; + + for (i=0; i 0) + { + if (!have_wads) + { + AddCmdLineParameter(exec, "-merge"); + have_wads = 1; + } + + AddCmdLineParameter(exec, "\"%s\"", wads[i]); + } + } +} + +static void AddExtraParameters(execute_context_t *exec) +{ + int i; + + for (i=0; i 0) + { + AddCmdLineParameter(exec, "%s", extra_params[i]); + } + } +} + +static void AddIWADParameter(execute_context_t *exec) +{ + if (iwadfile != NULL) + { + AddCmdLineParameter(exec, "-iwad %s", iwadfile); + } +} + +// Callback function invoked to launch the game. +// This is used when starting a server and also when starting a +// single player game via the "warp" menu. + +static void StartGame(int multiplayer) +{ + execute_context_t *exec; + + exec = NewExecuteContext(); + + // Extra parameters come first, before all others; this way, + // they can override any of the options set in the dialog. + + AddExtraParameters(exec); + + AddIWADParameter(exec); + AddCmdLineParameter(exec, "-skill %i", skill + 1); + + if (gamemission == hexen) + { + AddCmdLineParameter(exec, "-class %i", character_class); + } + + if (nomonsters) + { + AddCmdLineParameter(exec, "-nomonsters"); + } + + if (fast) + { + AddCmdLineParameter(exec, "-fast"); + } + + if (respawn) + { + AddCmdLineParameter(exec, "-respawn"); + } + + if (warptype == WARP_ExMy) + { + // TODO: select IWAD based on warp type + AddCmdLineParameter(exec, "-warp %i %i", warpepisode, warpmap); + } + else if (warptype == WARP_MAPxy) + { + AddCmdLineParameter(exec, "-warp %i", warpmap); + } + + // Multiplayer-specific options: + + if (multiplayer) + { + AddCmdLineParameter(exec, "-server"); + AddCmdLineParameter(exec, "-port %i", udpport); + + if (deathmatch == 1) + { + AddCmdLineParameter(exec, "-deathmatch"); + } + else if (deathmatch == 2 || strife_altdeath != 0) + { + AddCmdLineParameter(exec, "-altdeath"); + } + + if (timer > 0) + { + AddCmdLineParameter(exec, "-timer %i", timer); + } + + if (privateserver) + { + AddCmdLineParameter(exec, "-privateserver"); + } + } + + AddWADs(exec); + + TXT_Shutdown(); + + M_SaveDefaults(); + PassThroughArguments(exec); + + ExecuteDoom(exec); + + exit(0); +} + +static void StartServerGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + StartGame(1); +} + +static void StartSinglePlayerGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + StartGame(0); +} + +static void UpdateWarpButton(void) +{ + char buf[10]; + + if (warptype == WARP_ExMy) + { + M_snprintf(buf, sizeof(buf), "E%iM%i", warpepisode, warpmap); + } + else if (warptype == WARP_MAPxy) + { + M_snprintf(buf, sizeof(buf), "MAP%02i", warpmap); + } + + TXT_SetButtonLabel(warpbutton, buf); +} + +static void UpdateSkillButton(void) +{ + const iwad_t *iwad = GetCurrentIWAD(); + + if (IsChexQuest(iwad)) + { + skillbutton->values = chex_skills; + } + else switch(gamemission) + { + default: + case doom: + skillbutton->values = doom_skills; + break; + + case heretic: + skillbutton->values = heretic_skills; + break; + + case hexen: + if (character_class == 0) + { + skillbutton->values = hexen_fighter_skills; + } + else if (character_class == 1) + { + skillbutton->values = hexen_cleric_skills; + } + else + { + skillbutton->values = hexen_mage_skills; + } + break; + + case strife: + skillbutton->values = strife_skills; + break; + } +} + +static void SetExMyWarp(TXT_UNCAST_ARG(widget), void *val) +{ + int l; + + l = (intptr_t) val; + + warpepisode = l / 10; + warpmap = l % 10; + + UpdateWarpButton(); +} + +static void SetMAPxyWarp(TXT_UNCAST_ARG(widget), void *val) +{ + int l; + + l = (intptr_t) val; + + warpmap = l; + + UpdateWarpButton(); +} + +static void CloseLevelSelectDialog(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(window)) +{ + TXT_CAST_ARG(txt_window_t, window); + + TXT_CloseWindow(window); +} + +static void LevelSelectDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) +{ + txt_window_t *window; + txt_button_t *button; + const iwad_t *iwad; + char buf[10]; + int episodes; + int x, y; + int l; + int i; + + window = TXT_NewWindow("Select level"); + iwad = GetCurrentIWAD(); + + if (warptype == WARP_ExMy) + { + episodes = D_GetNumEpisodes(iwad->mission, iwad->mode); + TXT_SetTableColumns(window, episodes); + + // ExMy levels + + for (y=1; y<10; ++y) + { + for (x=1; x<=episodes; ++x) + { + if (IsChexQuest(iwad) && (x > 1 || y > 5)) + { + continue; + } + + if (!D_ValidEpisodeMap(iwad->mission, iwad->mode, x, y)) + { + TXT_AddWidget(window, NULL); + continue; + } + + M_snprintf(buf, sizeof(buf), + " E%dM%d ", x, y); + button = TXT_NewButton(buf); + TXT_SignalConnect(button, "pressed", + SetExMyWarp, (void *) (intptr_t) (x * 10 + y)); + TXT_SignalConnect(button, "pressed", + CloseLevelSelectDialog, window); + TXT_AddWidget(window, button); + + if (warpepisode == x && warpmap == y) + { + TXT_SelectWidget(window, button); + } + } + } + } + else + { + TXT_SetTableColumns(window, 6); + + for (i=0; i<60; ++i) + { + x = i % 6; + y = i / 6; + + l = x * 10 + y + 1; + + if (!D_ValidEpisodeMap(iwad->mission, iwad->mode, 1, l)) + { + TXT_AddWidget(window, NULL); + continue; + } + + M_snprintf(buf, sizeof(buf), " MAP%02d ", l); + button = TXT_NewButton(buf); + TXT_SignalConnect(button, "pressed", + SetMAPxyWarp, (void *) (intptr_t) l); + TXT_SignalConnect(button, "pressed", + CloseLevelSelectDialog, window); + TXT_AddWidget(window, button); + + if (warpmap == l) + { + TXT_SelectWidget(window, button); + } + } + } +} + +static void IWADSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + const iwad_t *iwad; + + // Find the iwad_t selected + + iwad = GetCurrentIWAD(); + + // Update iwadfile + + iwadfile = iwad->name; +} + +// Called when the IWAD button is changed, to update warptype. + +static void UpdateWarpType(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + warptype_t new_warptype; + const iwad_t *iwad; + + // Get the selected IWAD + + iwad = GetCurrentIWAD(); + + // Find the new warp type + + if (D_IsEpisodeMap(iwad->mission)) + { + new_warptype = WARP_ExMy; + } + else + { + new_warptype = WARP_MAPxy; + } + + // Reset to E1M1 / MAP01 when the warp type is changed. + + if (new_warptype != warptype) + { + warpepisode = 1; + warpmap = 1; + } + + warptype = new_warptype; + + UpdateWarpButton(); + UpdateSkillButton(); +} + +// Get an IWAD list with a default fallback IWAD that is appropriate +// for the game we are configuring (matches gamemission global variable). + +static const iwad_t **GetFallbackIwadList(void) +{ + static const iwad_t *fallback_iwad_list[2]; + unsigned int i; + + // Default to use if we don't find something better. + + fallback_iwad_list[0] = &fallback_iwads[0]; + fallback_iwad_list[1] = NULL; + + for (i = 0; i < arrlen(fallback_iwads); ++i) + { + if (gamemission == fallback_iwads[i].mission) + { + fallback_iwad_list[0] = &fallback_iwads[i]; + break; + } + } + + return fallback_iwad_list; +} + +static txt_widget_t *IWADSelector(void) +{ + txt_dropdown_list_t *dropdown; + txt_widget_t *result; + int num_iwads; + unsigned int i; + + // Find out what WADs are installed + + found_iwads = GetIwads(); + + // Build a list of the descriptions for all installed IWADs + + num_iwads = 0; + + for (i=0; found_iwads[i] != NULL; ++i) + { + ++num_iwads; + } + + iwad_labels = malloc(sizeof(*iwad_labels) * num_iwads); + + for (i=0; i < num_iwads; ++i) + { + iwad_labels[i] = found_iwads[i]->description; + } + + // If no IWADs are found, provide Doom 2 as an option, but + // we're probably screwed. + + if (num_iwads == 0) + { + found_iwads = GetFallbackIwadList(); + num_iwads = 1; + } + + // Build a dropdown list of IWADs + + if (num_iwads < 2) + { + // We have only one IWAD. Show as a label. + + result = (txt_widget_t *) TXT_NewLabel(found_iwads[0]->description); + } + else + { + // Dropdown list allowing IWAD to be selected. + + dropdown = TXT_NewDropdownList(&found_iwad_selected, + iwad_labels, num_iwads); + + TXT_SignalConnect(dropdown, "changed", IWADSelected, NULL); + + result = (txt_widget_t *) dropdown; + } + + // The first time the dialog is opened, found_iwad_selected=-1, + // so select the first IWAD in the list. Don't lose the setting + // if we close and reopen the dialog. + + if (found_iwad_selected < 0 || found_iwad_selected >= num_iwads) + { + found_iwad_selected = 0; + } + + IWADSelected(NULL, NULL); + + return result; +} + +// Create the window action button to start the game. This invokes +// a different callback depending on whether to start a multiplayer +// or single player game. + +static txt_window_action_t *StartGameAction(int multiplayer) +{ + txt_window_action_t *action; + TxtWidgetSignalFunc callback; + + action = TXT_NewWindowAction(KEY_F10, "Start"); + + if (multiplayer) + { + callback = StartServerGame; + } + else + { + callback = StartSinglePlayerGame; + } + + TXT_SignalConnect(action, "pressed", callback, NULL); + + return action; +} + +static void OpenWadsWindow(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) +{ + txt_window_t *window; + int i; + + window = TXT_NewWindow("Add WADs"); + + for (i=0; iserver_state != 0) + { + TXT_MessageBox("Cannot connect to server", + "Gameplay is already in progress\n" + "on this server."); + return; + } + + // Set address to connect to: + + free(connect_address); + connect_address = M_StringDuplicate(button->label); + + // Auto-choose IWAD if there is already a player connected. + + if (querydata->num_players > 0) + { + for (i = 0; found_iwads[i] != NULL; ++i) + { + if (found_iwads[i]->mode == querydata->gamemode + && found_iwads[i]->mission == querydata->gamemission) + { + found_iwad_selected = i; + iwadfile = found_iwads[i]->name; + break; + } + } + + if (found_iwads[i] == NULL) + { + TXT_MessageBox(NULL, + "The game on this server seems to be:\n" + "\n" + " %s\n" + "\n" + "but the IWAD file %s is not found!\n" + "Without the required IWAD file, it may not be\n" + "possible to join this game.", + D_SuggestGameName(querydata->gamemission, + querydata->gamemode), + D_SuggestIWADName(querydata->gamemission, + querydata->gamemode)); + } + } + + // Finished with search. + + TXT_CloseWindow(query_window); +} + +static void QueryResponseCallback(net_addr_t *addr, + net_querydata_t *querydata, + unsigned int ping_time, + TXT_UNCAST_ARG(results_table)) +{ + TXT_CAST_ARG(txt_table_t, results_table); + char ping_time_str[16]; + char description[47]; + + // When we connect we'll have to negotiate a common protocol that we + // can agree upon between the client and server. If we can't then we + // won't be able to connect, so it's pointless to include it in the + // results list. If protocol==NET_PROTOCOL_UNKNOWN then this may be + // an old, pre-3.0 Chocolate Doom server that doesn't support the new + // protocol negotiation mechanism, or it may be an incompatible fork. + if (querydata->protocol == NET_PROTOCOL_UNKNOWN) + { + return; + } + + M_snprintf(ping_time_str, sizeof(ping_time_str), "%ims", ping_time); + + // Build description from server name field. Because there is limited + // space, we only include the player count if there are already players + // connected to the server. + if (querydata->num_players > 0) + { + M_snprintf(description, sizeof(description), "(%d/%d) ", + querydata->num_players, querydata->max_players); + } + else + { + M_StringCopy(description, "", sizeof(description)); + } + + M_StringConcat(description, querydata->description, sizeof(description)); + + TXT_AddWidgets(results_table, + TXT_NewLabel(ping_time_str), + TXT_NewButton2(NET_AddrToString(addr), + SelectQueryAddress, querydata), + TXT_NewLabel(description), + NULL); + + ++query_servers_found; +} + +static void QueryPeriodicCallback(TXT_UNCAST_ARG(results_table)) +{ + TXT_CAST_ARG(txt_table_t, results_table); + + if (!NET_Query_Poll(QueryResponseCallback, results_table)) + { + TXT_SetPeriodicCallback(NULL, NULL, 0); + + if (query_servers_found == 0) + { + TXT_AddWidgets(results_table, + TXT_TABLE_EMPTY, + TXT_NewLabel("No compatible servers found."), + NULL + ); + } + } +} + +static void QueryWindowClosed(TXT_UNCAST_ARG(window), void *unused) +{ + TXT_SetPeriodicCallback(NULL, NULL, 0); +} + +static void ServerQueryWindow(const char *title) +{ + txt_table_t *results_table; + + query_servers_found = 0; + + query_window = TXT_NewWindow(title); + + TXT_AddWidget(query_window, + TXT_NewScrollPane(70, 10, + results_table = TXT_NewTable(3))); + + TXT_SetColumnWidths(results_table, 7, 22, 40); + TXT_SetPeriodicCallback(QueryPeriodicCallback, results_table, 1); + + TXT_SignalConnect(query_window, "closed", QueryWindowClosed, NULL); +} + +static void FindInternetServer(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(user_data)) +{ + NET_StartMasterQuery(); + ServerQueryWindow("Find Internet server"); +} + +static void FindLANServer(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(user_data)) +{ + NET_StartLANQuery(); + ServerQueryWindow("Find LAN server"); +} + +void JoinMultiGame(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + txt_inputbox_t *address_box; + + window = TXT_NewWindow("Join multiplayer game"); + TXT_SetTableColumns(window, 2); + TXT_SetColumnWidths(window, 12, 12); + + TXT_SetWindowHelpURL(window, MULTI_JOIN_HELP_URL); + + TXT_AddWidgets(window, + TXT_NewLabel("Game"), + IWADSelector(), + NULL); + + if (gamemission == hexen) + { + TXT_AddWidgets(window, + TXT_NewLabel("Character class "), + TXT_NewDropdownList(&character_class, + character_classes, 3), + NULL); + } + + TXT_AddWidgets(window, + TXT_NewSeparator("Server"), + TXT_NewLabel("Connect to address: "), + address_box = TXT_NewInputBox(&connect_address, 30), + + TXT_NewButton2("Find server on Internet...", + FindInternetServer, NULL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_NewButton2("Find server on local network...", + FindLANServer, NULL), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_NewStrut(0, 1), + TXT_TABLE_OVERFLOW_RIGHT, + TXT_NewButton2("Add extra parameters...", + OpenExtraParamsWindow, NULL), + NULL); + + TXT_SelectWidget(window, address_box); + + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, WadWindowAction()); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, JoinGameAction()); +} + +void SetChatMacroDefaults(void) +{ + int i; + const char *const defaults[] = + { + HUSTR_CHATMACRO0, + HUSTR_CHATMACRO1, + HUSTR_CHATMACRO2, + HUSTR_CHATMACRO3, + HUSTR_CHATMACRO4, + HUSTR_CHATMACRO5, + HUSTR_CHATMACRO6, + HUSTR_CHATMACRO7, + HUSTR_CHATMACRO8, + HUSTR_CHATMACRO9, + }; + + // If the chat macros have not been set, initialize with defaults. + + for (i=0; i<10; ++i) + { + if (chat_macros[i] == NULL) + { + chat_macros[i] = M_StringDuplicate(defaults[i]); + } + } +} + +void SetPlayerNameDefault(void) +{ + if (net_player_name == NULL) + { + net_player_name = NET_GetRandomPetName(); + } +} + +void MultiplayerConfig(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + txt_label_t *label; + txt_table_t *table; + char buf[10]; + int i; + + window = TXT_NewWindow("Multiplayer Configuration"); + TXT_SetWindowHelpURL(window, MULTI_CONFIG_HELP_URL); + + TXT_AddWidgets(window, + TXT_NewStrut(0, 1), + TXT_NewHorizBox(TXT_NewLabel("Player name: "), + TXT_NewInputBox(&net_player_name, 25), + NULL), + TXT_NewStrut(0, 1), + TXT_NewSeparator("Chat macros"), + NULL); + + table = TXT_NewTable(2); + + for (i=0; i<10; ++i) + { + M_snprintf(buf, sizeof(buf), "#%i ", i + 1); + + label = TXT_NewLabel(buf); + TXT_SetFGColor(label, TXT_COLOR_BRIGHT_CYAN); + + TXT_AddWidgets(table, + label, + TXT_NewInputBox(&chat_macros[(i + 1) % 10], 40), + NULL); + } + + TXT_AddWidget(window, table); +} + +void BindMultiplayerVariables(void) +{ + char buf[15]; + int i; + + M_BindStringVariable("player_name", &net_player_name); + + for (i=0; i<10; ++i) + { + M_snprintf(buf, sizeof(buf), "chatmacro%i", i); + M_BindStringVariable(buf, &chat_macros[i]); + } + + switch (gamemission) + { + case doom: + M_BindChatControls(4); + key_multi_msgplayer[0] = 'g'; + key_multi_msgplayer[1] = 'i'; + key_multi_msgplayer[2] = 'b'; + key_multi_msgplayer[3] = 'r'; + break; + + case heretic: + M_BindChatControls(4); + key_multi_msgplayer[0] = 'g'; + key_multi_msgplayer[1] = 'y'; + key_multi_msgplayer[2] = 'r'; + key_multi_msgplayer[3] = 'b'; + break; + + case hexen: + M_BindChatControls(8); + key_multi_msgplayer[0] = 'b'; + key_multi_msgplayer[1] = 'r'; + key_multi_msgplayer[2] = 'y'; + key_multi_msgplayer[3] = 'g'; + key_multi_msgplayer[4] = 'j'; + key_multi_msgplayer[5] = 'w'; + key_multi_msgplayer[6] = 'h'; + key_multi_msgplayer[7] = 'p'; + break; + + default: + break; + } +} + diff --git a/games/NXDoom/src/setup/multiplayer.h b/games/NXDoom/src/setup/multiplayer.h new file mode 100644 index 00000000000..911afbd0c1e --- /dev/null +++ b/games/NXDoom/src/setup/multiplayer.h @@ -0,0 +1,29 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_MULTIPLAYER_H +#define SETUP_MULTIPLAYER_H + +void StartMultiGame(void *widget, void *user_data); +void WarpMenu(void *widget, void *user_data); +void JoinMultiGame(void *widget, void *user_data); +void MultiplayerConfig(void *widget, void *user_data); + +void SetChatMacroDefaults(void); +void SetPlayerNameDefault(void); + +void BindMultiplayerVariables(void); + +#endif /* #ifndef SETUP_MULTIPLAYER_H */ + diff --git a/games/NXDoom/src/setup/setup-manifest.xml.in b/games/NXDoom/src/setup/setup-manifest.xml.in new file mode 100644 index 00000000000..111ad0f888b --- /dev/null +++ b/games/NXDoom/src/setup/setup-manifest.xml.in @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + diff --git a/games/NXDoom/src/setup/setup_icon.c b/games/NXDoom/src/setup/setup_icon.c new file mode 100644 index 00000000000..748cc93e961 --- /dev/null +++ b/games/NXDoom/src/setup/setup_icon.c @@ -0,0 +1,2736 @@ +static int setup_icon_w = 128; +static int setup_icon_h = 128; + +static const unsigned int setup_icon_data[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, + 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, + 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, + 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, + 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, + 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, + 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, + 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, + 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, + 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, + 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, + 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, + 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, + 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, + 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, + 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, + 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, + 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, + 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, + 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, + 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, + 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, + 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, + 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, + 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, + 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, + 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, + 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, + 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, + 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, + 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, + 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, + 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, + 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, + 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, + 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, + 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, + 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, + 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, + 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, + 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, + 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, + 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, + 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, + 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, + 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, + 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, + 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x93756aff, 0x90756aff, 0x8b7974ff, 0x877b7bff, + 0x877b7bff, 0x877b7bff, 0x877b7bff, 0x877b7bff, 0x877b7bff, 0x928888ff, + 0xaba3a3ff, 0xaaa3a3ff, 0xaaa3a3ff, 0xa9a2a2ff, 0xa8a2a2ff, 0xa7a1a0ff, + 0xa6a09fff, 0xa6a09fff, 0xa59e9eff, 0x938989ff, 0x867a7aff, 0x867a79ff, + 0x867a79ff, 0x867979ff, 0x857878ff, 0x837676ff, 0x817474ff, 0x7f7272ff, + 0x807373ff, 0x928989ff, 0x968e8eff, 0x958d8dff, 0x938b8cff, 0x918989ff, + 0x8e8787ff, 0x8d8585ff, 0x8c8484ff, 0x898282ff, 0x837b7bff, 0x695c5cff, + 0x675a5aff, 0x655959ff, 0x635657ff, 0x615455ff, 0x5f5253ff, 0x5e5152ff, + 0x5c4e4fff, 0x5a4c4dff, 0x665a5bff, 0x756d6dff, 0x736b6bff, 0x72696aff, + 0x706767ff, 0x6e6666ff, 0x6d6464ff, 0x6b6262ff, 0x685f60ff, 0x685f5fff, + 0x504344ff, 0x443637ff, 0x423336ff, 0x45373bff, 0x473a41ff, 0x4a3c47ff, + 0x4c3f4bff, 0x54424dff, 0x5e454cff, 0x674e55ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, + 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, + 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, + 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, + 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, + 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, + 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, + 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, + 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, + 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, + 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, + 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, + 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, + 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, + 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, + 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, + 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, + 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, + 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, + 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, + 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, + 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e9faeff, 0x94a5b3ff, + 0x93a3b2ff, 0x93a3b2ff, 0x92a2b1ff, 0x92a1b1ff, 0x91a0b0ff, 0x90a0afff, + 0x8f9faeff, 0x8394a5ff, 0x647b92ff, 0x647a92ff, 0x647a92ff, 0x647a91ff, + 0x647a91ff, 0x647990ff, 0x637890ff, 0x637890ff, 0x637890ff, 0x78899cff, + 0x8795a5ff, 0x8694a4ff, 0x8694a4ff, 0x8593a3ff, 0x8490a1ff, 0x828ea0ff, + 0x808d9dff, 0x7f8b9cff, 0x7c899aff, 0x5c6e86ff, 0x566882ff, 0x546680ff, + 0x53657eff, 0x51627cff, 0x4f617aff, 0x4d5e78ff, 0x4c5d77ff, 0x495b75ff, + 0x4f5f77ff, 0x697486ff, 0x687384ff, 0x677183ff, 0x656f81ff, 0x636e80ff, + 0x626c7eff, 0x606a7cff, 0x5e697aff, 0x5c6678ff, 0x4b576dff, 0x35435fff, + 0x33415cff, 0x32405bff, 0x2f3d58ff, 0x2e3b57ff, 0x2c3955ff, 0x2a3854ff, + 0x283552ff, 0x273450ff, 0x3f485eff, 0x485063ff, 0x464f61ff, 0x475065ff, + 0x485067ff, 0x475169ff, 0x49526cff, 0x4a536eff, 0x4b5471ff, 0x4c5573ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x1b3f5eff, 0x1a3e60ff, 0x1a3e5fff, 0x193d5fff, 0x193c5eff, 0x193c5eff, + 0x183b5dff, 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, + 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, + 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, + 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, + 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, + 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, + 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, + 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, + 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, + 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x1b3e5eff, 0x1a3e5fff, 0x193d5fff, 0x193c5eff, + 0x193c5eff, 0x183b5dff, 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, + 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, + 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, + 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, + 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, + 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, + 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, + 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, + 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, + 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, + 0x041541ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b3e5dff, 0x193d5fff, + 0x193c5eff, 0x193c5eff, 0x183b5dff, 0x183a5dff, 0x183a5cff, 0x17395cff, + 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, + 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, + 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, + 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, + 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, + 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, + 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, + 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, + 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, + 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x1b3d5dff, 0x193c5eff, 0x193c5eff, 0x183b5dff, 0x183a5dff, 0x183a5cff, + 0x17395cff, 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, + 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, + 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, + 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, + 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, + 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, + 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, + 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, + 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, + 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x1b3c5cff, 0x193c5eff, 0x183b5dff, 0x183a5dff, + 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, + 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, + 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, + 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, + 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, + 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, + 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, + 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, + 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, + 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b3c5cff, 0x183b5dff, + 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, 0x16375aff, + 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, + 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, + 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, + 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, + 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, + 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, + 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, + 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, + 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x1a3b5bff, 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, + 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, + 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, + 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, + 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, + 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, + 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, + 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, + 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, + 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x1a3a5bff, 0x183a5cff, 0x17395cff, 0x17385bff, + 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, + 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, + 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, + 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, + 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, + 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, + 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, + 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, + 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, + 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1a3a5aff, 0x17395cff, + 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, + 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, + 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, + 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, + 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, + 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, + 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, + 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, + 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, + 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x19395aff, 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, + 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, + 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, + 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, + 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, + 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, + 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, + 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, + 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, + 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x193859ff, 0x17385bff, 0x16375aff, 0x16375aff, + 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, + 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, + 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, + 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, + 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, + 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, + 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, + 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, + 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x193859ff, 0x16375aff, + 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, + 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, + 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, + 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, + 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, + 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, + 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, + 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, + 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x183758ff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, + 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, + 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, + 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, + 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x36496aff, + 0xadb5c3ff, 0xbec4cfff, 0xbec4cfff, 0xbec4cfff, 0xbec4cfff, 0xbec4ceff, + 0xbec4ceff, 0xacb3c1ff, 0x324364ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, + 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, + 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x183758ff, 0x163659ff, 0x153559ff, 0x153558ff, + 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, + 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, + 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, + 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, + 0x0d244cff, 0xc9ced7ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xc7cad0ff, 0x081b41ff, + 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, + 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, + 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x183657ff, 0x153559ff, + 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, + 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, + 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, + 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, + 0x0d254dff, 0x0d244cff, 0x0c244cff, 0xf4f5f7ff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xf4f5f6ff, 0x06122cff, 0x071a40ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, + 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, + 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x173557ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, + 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, + 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, + 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, + 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x20355aff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfdfdfdff, 0x19243bff, 0x05112cff, 0x06193fff, + 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, + 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x173556ff, 0x153458ff, 0x143357ff, 0x143357ff, + 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, + 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, + 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, + 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, + 0x3f5070ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0x374054ff, + 0x041029ff, 0x04102bff, 0x06173eff, 0x061944ff, 0x061843ff, 0x061743ff, + 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x173456ff, 0x143357ff, + 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, + 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, + 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, + 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, + 0x0c234bff, 0x0c224bff, 0x5c6c86ff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, + 0xfafafaff, 0x565e6eff, 0x041029ff, 0x040f29ff, 0x04102bff, 0x06163dff, + 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x163355ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, + 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, + 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, + 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, + 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x7b879dff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, + 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0x737a87ff, 0x040f29ff, 0x040f29ff, + 0x040e28ff, 0x040e2aff, 0x05153dff, 0x051642ff, 0x051641ff, 0x041541ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x163355ff, 0x143256ff, 0x133156ff, 0x133156ff, + 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, + 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, + 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, + 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x132850ff, + 0xaeb5c2ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xa5a9b2ff, + 0x0d1731ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x030e2aff, 0x05143cff, + 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x163254ff, 0x133156ff, + 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, + 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, + 0x0f2950ff, 0x253b5fff, 0x243b5fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, + 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x20355aff, + 0x909aadff, 0xeff0f3ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, + 0xf5f5f5ff, 0xf4f4f4ff, 0xe3e4e6ff, 0x868a96ff, 0x18223aff, 0x030d28ff, + 0x030d27ff, 0x020d29ff, 0x04123bff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x17254dff, 0x18264eff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x153154ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, + 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, + 0x0f2a50ff, 0x0f2950ff, 0x576883ff, 0xfafbfcff, 0xfdfdfeff, 0xb7becaff, + 0x50627fff, 0x0e264eff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0f254dff, + 0x78859bff, 0xf4f5f6ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, + 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, + 0xe4e5e6ff, 0x6c7180ff, 0x05102aff, 0x020c26ff, 0x030d28ff, 0x04133bff, + 0x051541ff, 0x414d6cff, 0x9da2b0ff, 0xdededfff, 0xd9d9daff, 0x444e69ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x153154ff, 0x133055ff, 0x122f55ff, 0x122f54ff, + 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, + 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x183056ff, 0xe3e6eaff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xdbdee4ff, 0x76839aff, 0x1a3056ff, + 0x22365bff, 0xc5cad4ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, + 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, + 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xb1b4baff, 0x172038ff, + 0x0f1831ff, 0x636979ff, 0xc1c3c9ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, + 0xddddddff, 0xc1c3c6ff, 0x0c193fff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x153053ff, 0x122f55ff, + 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, + 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x8693a7ff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xf4f5f7ff, 0xe9ebefff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, + 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, + 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xd1d2d4ff, 0xd9dadbff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, + 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0x6e7382ff, 0x031138ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x142f53ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, + 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, + 0x284062ff, 0xf5f6f7ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, + 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, + 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, + 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, + 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, + 0xceced0ff, 0x1e2541ff, 0x041239ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x142f52ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, + 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, + 0x0f284fff, 0x0e284fff, 0xabb4c1ff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfdfdfdff, 0xfcfcfcff, 0xd4d6daff, 0x8a8f9aff, 0x606877ff, 0x4a5264ff, + 0x4a5264ff, 0x5e6575ff, 0x868a96ff, 0xcaccd0ff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, + 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, + 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0x8b8e98ff, 0x050d2dff, 0x051239ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x142e52ff, 0x112d53ff, + 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, + 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x465977ff, 0xfefefeff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfdfdfdff, 0xb6bac1ff, 0x353e53ff, 0x041029ff, 0x041029ff, + 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x030d28ff, + 0x30384dff, 0xaaadb4ff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, + 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, + 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd1d1d1ff, + 0x343a53ff, 0x050e2eff, 0x05123aff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x132d51ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, + 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0xc0c6d0ff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xf1f2f3ff, 0x545d6dff, 0x05102aff, 0x041029ff, + 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, + 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0x4c5365ff, 0xdbdcddff, + 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, + 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, + 0xd2d2d2ff, 0xd0d0d0ff, 0x999ca4ff, 0x050f2eff, 0x050f2eff, 0x05123aff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x132d51ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, + 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, + 0x0e264eff, 0xc4cad3ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xe7e8ebff, 0x323c50ff, 0x05102aff, + 0x041029ff, 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x040e28ff, + 0x030e28ff, 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0x020c26ff, + 0x020c26ff, 0x2b3348ff, 0xcfd0d2ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, + 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, + 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0x9b9ea6ff, 0x050f2eff, + 0x050f30ff, 0x050f30ff, 0x05123aff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x132c50ff, 0x102c52ff, + 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, + 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x324666ff, 0xd9dce0ff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf7f7f8ff, 0x3f485bff, + 0x05102aff, 0x041029ff, 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, + 0x040e28ff, 0x030e28ff, 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, + 0x020c26ff, 0x020c26ff, 0x020c26ff, 0x020c27ff, 0x373e53ff, 0xdbdbdcff, + 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, + 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xafb0b5ff, + 0x242d47ff, 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x05123aff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x122c50ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, + 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, + 0x172d51ff, 0xaaafb8ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, + 0x787e8cff, 0x05102aff, 0x041029ff, 0x041029ff, 0x040f29ff, 0x040f29ff, + 0x09132cff, 0x5e6575ff, 0xabaeb6ff, 0xcbcdd1ff, 0xcaccd0ff, 0xa8abb2ff, + 0x595f70ff, 0x07112aff, 0x020c26ff, 0x020c26ff, 0x020c27ff, 0x020c27ff, + 0x020c27ff, 0x696e7eff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, + 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, + 0x888b96ff, 0x0f1836ff, 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, + 0x060f31ff, 0x061032ff, 0x05123bff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x122b4fff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, + 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, + 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0b2047ff, 0x6d7685ff, 0xf8f9f9ff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfdfdfdff, 0xe0e1e4ff, 0x0d1731ff, 0x041029ff, 0x041029ff, 0x040f29ff, + 0x040f29ff, 0x262f45ff, 0xcacbd0ff, 0xefefefff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xbec0c5ff, 0x222a41ff, 0x020c27ff, + 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x0b142fff, 0xc2c3c7ff, 0xdadadaff, + 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, + 0xc9c9caff, 0x585e70ff, 0x050f2eff, 0x050f30ff, 0x050f30ff, 0x050f30ff, + 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x05123bff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x122a4fff, 0x0f2a50ff, + 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, + 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, + 0x0a1f47ff, 0x384359ff, 0xdddfe2ff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0x747a88ff, 0x041029ff, 0x041029ff, + 0x040f29ff, 0x040f29ff, 0x1e273eff, 0xd8d9dcff, 0xefefefff, 0xeeeeeeff, + 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, + 0xcbcccfff, 0x19223aff, 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, + 0x656a7aff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, + 0xd0d0d0ff, 0xb4b5b9ff, 0x2d354eff, 0x050f2eff, 0x050f30ff, 0x050f30ff, + 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, + 0x061034ff, 0x061034ff, 0x05123bff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x112a4eff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, + 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, + 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a1e46ff, 0x888f9bff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0x273247ff, + 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0xa5a9b1ff, 0xefefefff, + 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0x9699a2ff, 0x020c29ff, 0x040d29ff, + 0x040d29ff, 0x040d2aff, 0x212943ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, + 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0x6a6f7fff, 0x050f2eff, 0x050f30ff, + 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, + 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x05123cff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x11294eff, 0x0f284fff, 0x0e284fff, 0x0e274eff, + 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, + 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, + 0xafb6c2ff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, + 0xdbdde0ff, 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x1f273eff, + 0xeeeeeeff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, + 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xddddddff, + 0x1c243cff, 0x040d29ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, 0xbebec2ff, + 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0x898c97ff, + 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, + 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, + 0x061035ff, 0x061136ff, 0x05123cff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11284dff, 0x0e284fff, + 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, + 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, + 0x0a1f48ff, 0x0a1f48ff, 0xc3c8d2ff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, + 0xfafafaff, 0xf8f8f8ff, 0xc0c3c8ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, + 0x040e28ff, 0x596070ff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, + 0xdededeff, 0xddddddff, 0x525769ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, + 0x050d2cff, 0xa5a7aeff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, + 0xccccccff, 0x989ba3ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x060f31ff, + 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, + 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x07133bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x10284dff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, + 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, + 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0xcdd1d9ff, 0xfdfdfdff, + 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xabafb7ff, 0x040f29ff, + 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x6d7281ff, 0xecececff, 0xebebebff, + 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, + 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0x646979ff, 0x040d2bff, + 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x9496a0ff, 0xd0d0d0ff, 0xcfcfcfff, + 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xa1a3aaff, 0x050f30ff, 0x050f31ff, + 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, + 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, + 0x061137ff, 0x081237ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x10274cff, 0x0e264eff, 0x0d264dff, 0x0d254dff, + 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, + 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, + 0xc2c7d1ff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, + 0xbbbec4ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x030d28ff, 0x5d6373ff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, + 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, + 0x53596cff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x9fa1a9ff, + 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0x989ba2ff, + 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, + 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, + 0x061136ff, 0x061137ff, 0x061137ff, 0x081237ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10264cff, 0x0d264dff, + 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, + 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, + 0x091d47ff, 0x091d46ff, 0xb0b6c3ff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, + 0xf5f5f5ff, 0xf4f4f4ff, 0xd2d3d6ff, 0x040e28ff, 0x030e28ff, 0x030d28ff, + 0x030d27ff, 0x262f45ff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, + 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, + 0xdadadaff, 0xd8d8d8ff, 0x222a45ff, 0x050d2cff, 0x050d2cff, 0x050d2dff, + 0x050d2dff, 0xb4b5b9ff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0x8b8e98ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, + 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, + 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x081237ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0f264bff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, + 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, + 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x8992a6ff, 0xf8f8f8ff, + 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf0f0f0ff, 0x1b253cff, + 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0xaeb0b7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, + 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0x9fa1aaff, 0x050d2cff, 0x050d2cff, + 0x050d2dff, 0x050d2dff, 0x1b233fff, 0xccccccff, 0xccccccff, 0xcacacaff, + 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0x6e7281ff, 0x061031ff, 0x061032ff, + 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, + 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, + 0x061138ff, 0x081238ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0f254bff, 0x0d244cff, 0x0c244cff, 0x0c234bff, + 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, + 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x223359ff, + 0xc5c9d2ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, + 0xefefefff, 0x636979ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0x020c26ff, + 0x283046ff, 0xd8d9daff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, + 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xcacbccff, 0x252c46ff, + 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x575d6fff, 0xccccccff, + 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0x9a9ca3ff, + 0x1a2342ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, + 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, + 0x061137ff, 0x061138ff, 0x061138ff, 0x081238ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0f244bff, 0x0c244cff, + 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, + 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, + 0x4c5979ff, 0xe5e6eaff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, + 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xc4c5caff, 0x05102aff, 0x020c26ff, + 0x020c26ff, 0x020c26ff, 0x020c26ff, 0x373e53ff, 0xcecfd1ff, 0xe0e0e0ff, + 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xc3c4c7ff, + 0x353b53ff, 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x07112fff, + 0xabacb2ff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, + 0xc2c2c2ff, 0xc1c1c1ff, 0xafb0b3ff, 0x39415bff, 0x061034ff, 0x061034ff, + 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, + 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x081238ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0e244bff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, + 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, + 0x0b1f48ff, 0x848da2ff, 0xf6f6f7ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, + 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, + 0x5b6171ff, 0x020c26ff, 0x020c26ff, 0x020c26ff, 0x020c27ff, 0x020c27ff, + 0x121b34ff, 0x737886ff, 0xbbbcc0ff, 0xd8d8d9ff, 0xd7d7d8ff, 0xb7b8bdff, + 0x707483ff, 0x131a37ff, 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, + 0x050f2eff, 0x51576aff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbbbbbbff, + 0x636879ff, 0x081236ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, + 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, + 0x061239ff, 0x081339ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0e234aff, 0x0c224bff, 0x0b224aff, 0x0b214aff, + 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, + 0x091d46ff, 0x1e3057ff, 0xbcc1ccff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, + 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xd9dadbff, 0x252d43ff, 0x020c26ff, 0x020c27ff, + 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, 0x060f2cff, + 0x060f2dff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x050d2dff, + 0x050e2dff, 0x050f2eff, 0x242d47ff, 0xbebfc1ff, 0xc9c9c9ff, 0xc7c7c7ff, + 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, + 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, 0x8b8d97ff, 0x151f40ff, 0x061136ff, + 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, + 0x061138ff, 0x061239ff, 0x061239ff, 0x081339ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e224aff, 0x0b224aff, + 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, + 0x091d47ff, 0x091d46ff, 0x081c46ff, 0xb2b8c5ff, 0xf8f8f8ff, 0xf7f7f7ff, + 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, + 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xc2c4c8ff, + 0x182139ff, 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, + 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, + 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x19223dff, 0xadaeb3ff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, + 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, + 0x80838eff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, + 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x081339ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0d2249ff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, + 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0xc3c7d0ff, + 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, + 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xe3e3e3ff, 0xc9cacdff, 0x2f374cff, 0x020c29ff, 0x040d29ff, + 0x040d29ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, + 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x2e364eff, 0xb6b7baff, + 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, + 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, + 0xb6b6b6ff, 0xb5b5b5ff, 0x8b8e96ff, 0x061137ff, 0x061137ff, 0x061137ff, + 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, + 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0d2149ff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, + 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, + 0x071b45ff, 0x525f7cff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, + 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, + 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdadadbff, + 0x878a95ff, 0x19213aff, 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, + 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x151e3aff, 0x6f7482ff, + 0xc4c4c5ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, + 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, + 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb3b3b3ff, 0x3b435dff, 0x061137ff, + 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, + 0x06123aff, 0x06123aff, 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0d2148ff, 0x0a2049ff, + 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, + 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0xb5bac5ff, 0xf2f2f2ff, + 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, + 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xd3d3d4ff, 0x999ca5ff, 0x595f71ff, + 0x383e55ff, 0x232a44ff, 0x232a45ff, 0x373d55ff, 0x585d6fff, 0x93969fff, + 0xc6c6c7ff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, + 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, + 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb3b3b3ff, 0x848791ff, + 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, + 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x08133aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0c2048ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, + 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, + 0x2d3c60ff, 0xececedff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, + 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, + 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, + 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, + 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, + 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb3b3b3ff, + 0xafafb0ff, 0x242d4cff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, + 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0c1f47ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, + 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, + 0x061944ff, 0x061843ff, 0x061743ff, 0x8d95a7ff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe2e2e2ff, + 0xdbdbdcff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, + 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, + 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, + 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xb8b9baff, + 0xbbbbbbff, 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, + 0xb3b3b3ff, 0xb1b1b1ff, 0x696d7dff, 0x061137ff, 0x061138ff, 0x061138ff, + 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x06123aff, 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c1f47ff, 0x091e47ff, + 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, + 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x15254eff, + 0xdadcdfff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xd8d9daff, + 0x898d98ff, 0x293147ff, 0x242c43ff, 0xbabcc1ff, 0xddddddff, 0xdbdbdbff, + 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, + 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, + 0xa3a4aaff, 0x252d4bff, 0x202947ff, 0x666a7cff, 0xacadb0ff, 0xb6b6b6ff, + 0xb5b5b5ff, 0xb3b3b3ff, 0xb1b1b1ff, 0xa4a5a8ff, 0x141e41ff, 0x061138ff, + 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x08143bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0b1e46ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, + 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, + 0x051642ff, 0x051641ff, 0x5f6a84ff, 0xe9e9e9ff, 0xe7e7e7ff, 0xc1c3c7ff, + 0x616776ff, 0x0e1731ff, 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x0f1732ff, + 0x828591ff, 0xd9d9d9ff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, + 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, + 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, + 0xbebebeff, 0x707483ff, 0x0f183bff, 0x061034ff, 0x061035ff, 0x061035ff, + 0x0f183bff, 0x4f556bff, 0x97999fff, 0xb1b1b1ff, 0xb0b0b0ff, 0x484e65ff, + 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x07133bff, 0x07143bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0b1d46ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, + 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, + 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x323d59ff, + 0x353c51ff, 0x030d27ff, 0x020c27ff, 0x020c27ff, 0x020c27ff, 0x020c29ff, + 0x040d29ff, 0x040d29ff, 0x040d2aff, 0x2b334bff, 0x9497a1ff, 0xd3d3d3ff, + 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, + 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, + 0xbfbfc0ff, 0x838691ff, 0x272f4dff, 0x061034ff, 0x061034ff, 0x061035ff, + 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x071238ff, 0x2c3452ff, + 0x28314fff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, + 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x07133bff, 0x06133cff, 0x07143bff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0b1d45ff, 0x081c46ff, + 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, + 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x031034ff, 0x020c27ff, 0x020c27ff, 0x020c27ff, + 0x020c29ff, 0x040d29ff, 0x040d29ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, + 0x050d2cff, 0x1d2440ff, 0x9c9ea7ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, + 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, + 0xc2c2c2ff, 0x90929bff, 0x1a2342ff, 0x061034ff, 0x061034ff, 0x061034ff, + 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, + 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, + 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x07143cff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0a1c45ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, + 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x031034ff, + 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, 0x040d2aff, 0x040d2bff, + 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x676b7bff, 0xcfcfcfff, + 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0x5e6375ff, 0x061034ff, 0x061034ff, + 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, + 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, + 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, + 0x06133cff, 0x07143cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0a1b45ff, 0x071b45ff, 0x071a45ff, 0x071944ff, + 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, + 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x031035ff, 0x040d29ff, 0x040d29ff, 0x040d2aff, + 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x050d2dff, + 0x4c5266ff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, + 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0x464c64ff, + 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, + 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, + 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, + 0x06133cff, 0x06133cff, 0x06133dff, 0x07143cff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x091b44ff, 0x071a45ff, + 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, + 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x031135ff, + 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, + 0x050d2dff, 0x050e2dff, 0x333b53ff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, + 0xbebebeff, 0x2f3652ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, + 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, + 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, + 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x07143cff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x091a44ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, + 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x031136ff, 0x040d2cff, 0x050d2cff, 0x050d2cff, + 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x19223eff, 0xcacacaff, + 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, + 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0x172041ff, 0x061035ff, 0x061035ff, + 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, + 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, + 0x06133cff, 0x08133cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x091a43ff, 0x061944ff, 0x061843ff, 0x061743ff, + 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041137ff, + 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x050f2eff, + 0x061031ff, 0xc3c3c5ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, + 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xb5b6b7ff, 0x071136ff, + 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, + 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, + 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, + 0x06133dff, 0x06133cff, 0x06123dff, 0x08143dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x081a43ff, 0x061843ff, + 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041137ff, 0x050d2dff, 0x050e2dff, 0x050f2eff, + 0x050f2eff, 0x050f30ff, 0x050f30ff, 0xa4a6acff, 0xc6c6c6ff, 0xc4c4c4ff, + 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, + 0x999ba2ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, + 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, + 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, + 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x08143dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x081942ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041137ff, + 0x050f2eff, 0x050f2eff, 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x363d57ff, + 0x9ea0a7ff, 0xa9aaafff, 0xa8a9aeff, 0xa7a8adff, 0xa6a7acff, 0xa4a5aaff, + 0xa3a4a9ff, 0x95979fff, 0x323955ff, 0x061035ff, 0x061136ff, 0x061136ff, + 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, + 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, + 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, + 0x06133eff, 0x08143dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x081842ff, 0x051742ff, 0x051642ff, 0x051641ff, + 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041138ff, 0x050f30ff, 0x050f30ff, 0x050f30ff, + 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, + 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, + 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, + 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, + 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, + 0x06133dff, 0x06133eff, 0x06133eff, 0x08143eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x071841ff, 0x051642ff, + 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041138ff, + 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, + 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, + 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, + 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, + 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, + 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x07143eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x071741ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041139ff, 0x060f31ff, 0x061031ff, 0x061032ff, + 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, + 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, + 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, + 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, + 0x05133fff, 0x07143eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x071740ff, 0x041541ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x04113aff, + 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, + 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, + 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, + 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, + 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, + 0x06133eff, 0x05133fff, 0x05133fff, 0x07143eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x061640ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x05123aff, 0x061034ff, 0x061034ff, 0x061034ff, + 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, + 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, + 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, + 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, + 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x07143eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05123aff, + 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, + 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, + 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, + 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, + 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, + 0x05133fff, 0x07143eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x05123bff, 0x061035ff, 0x061035ff, 0x061136ff, + 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, + 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, + 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, + 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, + 0x05133eff, 0x05133fff, 0x05133fff, 0x07153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06123bff, + 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, + 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, + 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, + 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, + 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x06153eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x06123cff, 0x061137ff, 0x061137ff, 0x061137ff, + 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, + 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, + 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, + 0x04143fff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06123cff, + 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, + 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, + 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, + 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, + 0x051440ff, 0x04143fff, 0x04143fff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x06123cff, 0x061138ff, 0x061138ff, 0x061239ff, + 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, + 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, + 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, + 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, + 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06123dff, + 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, + 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, + 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, + 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x06123dff, 0x06123aff, 0x06123aff, 0x06123aff, + 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, + 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, + 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, + 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05133dff, + 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, + 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, + 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, + 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, + 0x04143fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x05133eff, 0x06123aff, 0x06123aff, 0x06123bff, + 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, + 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, + 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, + 0x04143fff, 0x04143fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05133eff, + 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, + 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, + 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, + 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e163bff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x05133eff, 0x06133cff, 0x06133cff, 0x06133cff, + 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, + 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, + 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x0f163aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x2e1f2fea, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05133dff, + 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, + 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, + 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x2e1f30e9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5a2d2d22, 0x231c32f7, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x05133eff, 0x06133dff, 0x06133cff, 0x06123dff, + 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, + 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, + 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, + 0x041440ff, 0x041440ff, 0x231b33f6, 0x58303020, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x552c254b, 0x4c292a97, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4627299d, + 0x4625299d, 0x46272a9d, 0x4627299d, 0x4627299d, 0x4627299d, 0x4627299d, + 0x4627299c, 0x4627299c, 0x4827299c, 0x4827299c, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, + 0x4827299b, 0x4827299b, 0x4c292a97, 0x552c254b, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; diff --git a/games/NXDoom/src/setup/sound.c b/games/NXDoom/src/setup/sound.c new file mode 100644 index 00000000000..982ce00bccc --- /dev/null +++ b/games/NXDoom/src/setup/sound.c @@ -0,0 +1,410 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +// Sound control menu + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +#include +#include + +#include "textscreen.h" +#include "m_config.h" +#include "m_misc.h" + +#include "execute.h" +#include "mode.h" +#include "sound.h" + +#ifndef DISABLE_SDL2MIXER + +#include "SDL_mixer.h" + +#endif // DISABLE_SDL2MIXER + + +#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-sound" + +typedef enum +{ + OPLMODE_OPL2, + OPLMODE_OPL3, + NUM_OPLMODES, +} oplmode_t; + +static const char *opltype_strings[] = +{ + "OPL2", + "OPL3" +}; + +static const char *cfg_extension[] = { "cfg", NULL }; + +#ifdef HAVE_FLUIDSYNTH +static const char *sf_extension[] = { "sf2", "sf3", NULL }; +#endif + +// Config file variables: + +int snd_sfxdevice = SNDDEVICE_SB; +int snd_musicdevice = SNDDEVICE_SB; +int snd_samplerate = 44100; +int opl_io_port = 0x388; +int snd_cachesize = 64 * 1024 * 1024; +int snd_maxslicetime_ms = 28; +char *snd_musiccmd = ""; +int snd_pitchshift = 0; +char *snd_dmxoption = ""; + +static int numChannels = 8; +static int sfxVolume = 8; +static int musicVolume = 8; +static int voiceVolume = 15; +static int show_talk = 0; +int use_libsamplerate = 0; +float libsamplerate_scale = 0.65; + +char *music_pack_path = NULL; +char *timidity_cfg_path = NULL; +static char *gus_patch_path = NULL; +static int gus_ram_kb = 1024; +#ifdef _WIN32 +#define MAX_MIDI_DEVICES 20 +static char *midi_names[MAX_MIDI_DEVICES]; +static int midi_index; +char *winmm_midi_device = NULL; +int winmm_complevel = 0; +int winmm_reset_type = 1; +int winmm_reset_delay = 0; +#endif + +#ifdef HAVE_FLUIDSYNTH +char *fsynth_sf_path = NULL; +int fsynth_chorus_active = 1; +float fsynth_chorus_depth = 5.0f; +float fsynth_chorus_level = 0.35f; +int fsynth_chorus_nr = 3; +float fsynth_chorus_speed = 0.3f; +char *fsynth_midibankselect = "gs"; +int fsynth_polyphony = 256; +int fsynth_reverb_active = 1; +float fsynth_reverb_damp = 0.4f; +float fsynth_reverb_level = 0.15f; +float fsynth_reverb_roomsize = 0.6f; +float fsynth_reverb_width = 4.0f; +float fsynth_gain = 1.0f; +#endif // HAVE_FLUIDSYNTH + +// DOS specific variables: these are unused but should be maintained +// so that the config file can be shared between chocolate +// doom and doom.exe + +static int snd_sbport = 0; +static int snd_sbirq = 0; +static int snd_sbdma = 0; +static int snd_mport = 0; + +static int snd_oplmode; + +static void UpdateSndDevices(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) +{ + switch (snd_oplmode) + { + default: + case OPLMODE_OPL2: + snd_dmxoption = ""; + break; + + case OPLMODE_OPL3: + snd_dmxoption = "-opl3"; + break; + } +} + +static txt_dropdown_list_t *OPLTypeSelector(void) +{ + txt_dropdown_list_t *result; + + if (snd_dmxoption != NULL && strstr(snd_dmxoption, "-opl3") != NULL) + { + snd_oplmode = OPLMODE_OPL3; + } + else + { + snd_oplmode = OPLMODE_OPL2; + } + + result = TXT_NewDropdownList(&snd_oplmode, opltype_strings, 2); + + TXT_SignalConnect(result, "changed", UpdateSndDevices, NULL); + + return result; +} + +static void OpenMusicPackDir(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + if (!OpenFolder(music_pack_path)) + { + TXT_MessageBox("Error", "Failed to open music pack directory."); + } +} + +#ifdef _WIN32 +static void UpdateMidiDevice(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) +{ + free(winmm_midi_device); + winmm_midi_device = M_StringDuplicate(midi_names[midi_index]); +} + +static txt_dropdown_list_t *MidiDeviceSelector(void) +{ + txt_dropdown_list_t *result; + int num_devices = 1; + int all_devices = midiOutGetNumDevs(); + int i; + + midi_index = 0; + free(midi_names[0]); + midi_names[0] = M_StringDuplicate("Microsoft MIDI Mapper"); + + if (all_devices > MAX_MIDI_DEVICES - num_devices) + { + all_devices = MAX_MIDI_DEVICES - num_devices; + } + + for (i = 0; i < all_devices; i++) + { + MIDIOUTCAPS caps; + + if (midiOutGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) + { + free(midi_names[num_devices]); + midi_names[num_devices] = M_StringDuplicate(caps.szPname); + + if (!strncasecmp(winmm_midi_device, midi_names[num_devices], + MAXPNAMELEN)) + { + // Set the dropdown list index to the saved device. + midi_index = num_devices; + } + + num_devices++; + } + } + + free(winmm_midi_device); + winmm_midi_device = M_StringDuplicate(midi_names[midi_index]); + + result = TXT_NewDropdownList(&midi_index, (const char **) midi_names, + num_devices); + TXT_SignalConnect(result, "changed", UpdateMidiDevice, NULL); + + return result; +} +#endif + +void ConfigSound(TXT_UNCAST_ARG(widget), void *user_data) +{ + txt_window_t *window; + txt_window_action_t *music_action; + + // Build the window + + window = TXT_NewWindow("Sound configuration"); + TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); + + TXT_SetColumnWidths(window, 40); + TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, + TXT_SCREEN_W / 2, 3); + + music_action = TXT_NewWindowAction('m', "Music Packs"); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, music_action); + TXT_SignalConnect(music_action, "pressed", OpenMusicPackDir, NULL); + + TXT_AddWidgets(window, + TXT_NewSeparator("Sound effects"), + TXT_NewRadioButton("Disabled", &snd_sfxdevice, SNDDEVICE_NONE), + TXT_If(gamemission == doom || gamemission == strife, + TXT_NewRadioButton("PC speaker effects", &snd_sfxdevice, + SNDDEVICE_PCSPEAKER)), + TXT_NewRadioButton("Digital sound effects", + &snd_sfxdevice, + SNDDEVICE_SB), + TXT_If(gamemission == doom || gamemission == heretic + || gamemission == hexen, + TXT_NewConditional(&snd_sfxdevice, SNDDEVICE_SB, + TXT_NewHorizBox( + TXT_NewStrut(4, 0), + TXT_NewCheckBox("Pitch-shifted sounds", &snd_pitchshift), + NULL))), + TXT_If(gamemission == strife, + TXT_NewConditional(&snd_sfxdevice, SNDDEVICE_SB, + TXT_NewHorizBox( + TXT_NewStrut(4, 0), + TXT_NewCheckBox("Show text with voices", &show_talk), + NULL))), + + TXT_NewSeparator("Music"), + TXT_NewRadioButton("Disabled", &snd_musicdevice, SNDDEVICE_NONE), + + TXT_NewRadioButton("OPL (Adlib/Soundblaster)", &snd_musicdevice, + SNDDEVICE_SB), + TXT_NewConditional(&snd_musicdevice, SNDDEVICE_SB, + TXT_NewHorizBox( + TXT_NewStrut(4, 0), + TXT_NewLabel("Chip type: "), + OPLTypeSelector(), + NULL)), + + TXT_NewRadioButton("GUS (emulated)", &snd_musicdevice, SNDDEVICE_GUS), + TXT_NewConditional(&snd_musicdevice, SNDDEVICE_GUS, + TXT_MakeTable(2, + TXT_NewStrut(4, 0), + TXT_NewLabel("Path to patch files: "), + TXT_NewStrut(4, 0), + TXT_NewFileSelector(&gus_patch_path, 34, + "Select directory containing GUS patches", + TXT_DIRECTORY), + NULL)), + + TXT_NewRadioButton("Native MIDI", &snd_musicdevice, SNDDEVICE_GENMIDI), +#ifdef _WIN32 + TXT_NewConditional(&snd_musicdevice, SNDDEVICE_GENMIDI, + TXT_NewHorizBox( + TXT_NewStrut(4, 0), + TXT_NewLabel("Device: "), + MidiDeviceSelector(), + NULL)), +#endif + TXT_NewConditional(&snd_musicdevice, SNDDEVICE_GENMIDI, + TXT_MakeTable(2, + TXT_NewStrut(4, 0), + TXT_NewLabel("Timidity configuration file: "), + TXT_NewStrut(4, 0), + TXT_NewFileSelector(&timidity_cfg_path, 34, + "Select Timidity config file", + cfg_extension), + NULL)), +#ifdef HAVE_FLUIDSYNTH + TXT_NewRadioButton("FluidSynth", &snd_musicdevice, SNDDEVICE_FSYNTH), + TXT_NewConditional(&snd_musicdevice, SNDDEVICE_FSYNTH, + TXT_MakeTable(2, + TXT_NewStrut(4, 0), + TXT_NewLabel("Soundfont file: "), + TXT_NewStrut(4, 0), + TXT_NewFileSelector(&fsynth_sf_path, 34, + "Select FluidSynth soundfont file", + sf_extension), + NULL)), +#endif + NULL); +} + +void BindSoundVariables(void) +{ + M_BindIntVariable("snd_sfxdevice", &snd_sfxdevice); + M_BindIntVariable("snd_musicdevice", &snd_musicdevice); + M_BindIntVariable("snd_channels", &numChannels); + M_BindIntVariable("snd_samplerate", &snd_samplerate); + M_BindIntVariable("sfx_volume", &sfxVolume); + M_BindIntVariable("music_volume", &musicVolume); + + M_BindIntVariable("use_libsamplerate", &use_libsamplerate); + M_BindFloatVariable("libsamplerate_scale", &libsamplerate_scale); + + M_BindIntVariable("gus_ram_kb", &gus_ram_kb); + M_BindStringVariable("gus_patch_path", &gus_patch_path); + M_BindStringVariable("music_pack_path", &music_pack_path); + M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path); +#ifdef _WIN32 + M_BindStringVariable("winmm_midi_device", &winmm_midi_device); + M_BindIntVariable("winmm_complevel", &winmm_complevel); + M_BindIntVariable("winmm_reset_type", &winmm_reset_type); + M_BindIntVariable("winmm_reset_delay", &winmm_reset_delay); +#endif + +#ifdef HAVE_FLUIDSYNTH + M_BindIntVariable("fsynth_chorus_active", &fsynth_chorus_active); + M_BindFloatVariable("fsynth_chorus_depth", &fsynth_chorus_depth); + M_BindFloatVariable("fsynth_chorus_level", &fsynth_chorus_level); + M_BindIntVariable("fsynth_chorus_nr", &fsynth_chorus_nr); + M_BindFloatVariable("fsynth_chorus_speed", &fsynth_chorus_speed); + M_BindStringVariable("fsynth_midibankselect", &fsynth_midibankselect); + M_BindIntVariable("fsynth_polyphony", &fsynth_polyphony); + M_BindIntVariable("fsynth_reverb_active", &fsynth_reverb_active); + M_BindFloatVariable("fsynth_reverb_damp", &fsynth_reverb_damp); + M_BindFloatVariable("fsynth_reverb_level", &fsynth_reverb_level); + M_BindFloatVariable("fsynth_reverb_roomsize", &fsynth_reverb_roomsize); + M_BindFloatVariable("fsynth_reverb_width", &fsynth_reverb_width); + M_BindFloatVariable("fsynth_gain", &fsynth_gain); + M_BindStringVariable("fsynth_sf_path", &fsynth_sf_path); +#endif // HAVE_FLUIDSYNTH + + M_BindIntVariable("snd_sbport", &snd_sbport); + M_BindIntVariable("snd_sbirq", &snd_sbirq); + M_BindIntVariable("snd_sbdma", &snd_sbdma); + M_BindIntVariable("snd_mport", &snd_mport); + M_BindIntVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms); + M_BindStringVariable("snd_musiccmd", &snd_musiccmd); + M_BindStringVariable("snd_dmxoption", &snd_dmxoption); + + M_BindIntVariable("snd_cachesize", &snd_cachesize); + M_BindIntVariable("opl_io_port", &opl_io_port); + + M_BindIntVariable("snd_pitchshift", &snd_pitchshift); + + if (gamemission == strife) + { + M_BindIntVariable("voice_volume", &voiceVolume); + M_BindIntVariable("show_talk", &show_talk); + } + + music_pack_path = M_StringDuplicate(""); + timidity_cfg_path = M_StringDuplicate(""); + gus_patch_path = M_StringDuplicate(""); + +#ifdef _WIN32 + winmm_midi_device = M_StringDuplicate(""); +#endif + +#ifdef HAVE_FLUIDSYNTH + fsynth_sf_path = M_StringDuplicate(""); +#endif + + // All versions of Heretic and Hexen did pitch-shifting. + // Most versions of Doom did not and Strife never did. + snd_pitchshift = gamemission == heretic || gamemission == hexen; + + // Default sound volumes - different games use different values. + + switch (gamemission) + { + case doom: + default: + sfxVolume = 8; musicVolume = 8; + break; + case heretic: + case hexen: + sfxVolume = 10; musicVolume = 10; + break; + case strife: + sfxVolume = 8; musicVolume = 13; + break; + } +} + diff --git a/games/NXDoom/src/setup/sound.h b/games/NXDoom/src/setup/sound.h new file mode 100644 index 00000000000..a21570135b8 --- /dev/null +++ b/games/NXDoom/src/setup/sound.h @@ -0,0 +1,24 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef SETUP_SOUND_H +#define SETUP_SOUND_H + +#include "i_sound.h" + +void ConfigSound(void *widget, void *user_data); +void BindSoundVariables(void); + + +#endif /* #ifndef SETUP_SOUND_H */ diff --git a/games/NXDoom/src/setup/txt_joyaxis.c b/games/NXDoom/src/setup/txt_joyaxis.c new file mode 100644 index 00000000000..620c0bfa41e --- /dev/null +++ b/games/NXDoom/src/setup/txt_joyaxis.c @@ -0,0 +1,654 @@ +// +// Copyright(C) 2014 Simon Howard +// +// 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. +// + +#include +#include +#include + +#include "SDL.h" + +#include "joystick.h" +#include "i_joystick.h" +#include "i_system.h" +#include "m_controls.h" +#include "m_misc.h" + +#include "textscreen.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_joyaxis.h" +#include "txt_utf8.h" + +#define JOYSTICK_AXIS_WIDTH 20 + +static const char *CalibrationLabel(txt_joystick_axis_t *joystick_axis) +{ + switch (joystick_axis->config_stage) + { + case CONFIG_CENTER: + return "Center the D-pad or joystick,\n" + "and press a button."; + + case CONFIG_STAGE1: + if (joystick_axis->dir == JOYSTICK_AXIS_VERTICAL) + { + return "Push the D-pad or joystick up,\n" + "and press the button."; + } + else + { + return "Push the D-pad or joystick to the\n" + "left, and press the button."; + } + + case CONFIG_STAGE2: + if (joystick_axis->dir == JOYSTICK_AXIS_VERTICAL) + { + return "Push the D-pad or joystick down,\n" + "and press the button."; + } + else + { + return "Push the D-pad or joystick to the\n" + "right, and press the button."; + } + } + + return NULL; +} + +static void SetCalibrationLabel(txt_joystick_axis_t *joystick_axis) +{ + TXT_SetLabel(joystick_axis->config_label, CalibrationLabel(joystick_axis)); +} + +// Search all axes on joystick being configured; find a button that is +// pressed (other than the calibrate button). Returns the button number. + +static int FindPressedAxisButton(txt_joystick_axis_t *joystick_axis) +{ + int i; + + for (i = 0; i < SDL_JoystickNumButtons(joystick_axis->joystick); ++i) + { + if (i == joystick_axis->config_button) + { + continue; + } + + if (SDL_JoystickGetButton(joystick_axis->joystick, i)) + { + return i; + } + } + + return -1; +} + +// Look for a hat that isn't centered. Returns the encoded hat axis. + +static int FindUncenteredHat(SDL_Joystick *joystick, int *axis_invert) +{ + int i, hatval; + + for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) + { + hatval = SDL_JoystickGetHat(joystick, i); + + switch (hatval) + { + case SDL_HAT_LEFT: + case SDL_HAT_RIGHT: + *axis_invert = hatval != SDL_HAT_LEFT; + return CREATE_HAT_AXIS(i, HAT_AXIS_HORIZONTAL); + + case SDL_HAT_UP: + case SDL_HAT_DOWN: + *axis_invert = hatval != SDL_HAT_UP; + return CREATE_HAT_AXIS(i, HAT_AXIS_VERTICAL); + + // If the hat is centered, or is not pointing in a + // definite direction, then ignore it. We don't accept + // the hat being pointed to the upper-left for example, + // because it's ambiguous. + case SDL_HAT_CENTERED: + default: + break; + } + } + + // None found. + return -1; +} + +static boolean CalibrateAxis(txt_joystick_axis_t *joystick_axis) +{ + int best_axis; + int best_value; + int best_invert; + Sint16 axis_value; + int i; + + // Check all axes to find which axis has the largest value. We test + // for one axis at a time, so eg. when we prompt to push the joystick + // left, whichever axis has the largest value is the left axis. + + best_axis = 0; + best_value = 0; + best_invert = 0; + + for (i = 0; i < SDL_JoystickNumAxes(joystick_axis->joystick); ++i) + { + axis_value = SDL_JoystickGetAxis(joystick_axis->joystick, i); + + if (joystick_axis->bad_axis[i]) + { + continue; + } + + if (abs(axis_value) > best_value) + { + best_value = abs(axis_value); + best_invert = axis_value > 0; + best_axis = i; + } + } + + // Did we find one axis that had a significant value? + + if (best_value > 32768 / 4) + { + // Save the best values we have found + + *joystick_axis->axis = best_axis; + *joystick_axis->invert = best_invert; + return true; + } + + // Otherwise, maybe this is a "button axis", like the PS3 SIXAXIS + // controller that exposes the D-pad as four individual buttons. + // Search for a button. + + i = FindPressedAxisButton(joystick_axis); + + if (i >= 0) + { + *joystick_axis->axis = CREATE_BUTTON_AXIS(i, 0); + *joystick_axis->invert = 0; + return true; + } + + // Maybe it's a D-pad that is presented as a hat. This sounds weird + // but gamepads like this really do exist; an example is the + // Nyko AIRFLO Ex. + + i = FindUncenteredHat(joystick_axis->joystick, joystick_axis->invert); + + if (i >= 0) + { + *joystick_axis->axis = i; + return true; + } + + // User pressed the button without pushing the joystick anywhere. + return false; +} + +static boolean SetButtonAxisPositive(txt_joystick_axis_t *joystick_axis) +{ + int button; + + button = FindPressedAxisButton(joystick_axis); + + if (button >= 0) + { + *joystick_axis->axis |= CREATE_BUTTON_AXIS(0, button); + return true; + } + + return false; +} + +static void IdentifyBadAxes(txt_joystick_axis_t *joystick_axis) +{ + int i, val; + + free(joystick_axis->bad_axis); + + joystick_axis->bad_axis + = calloc(SDL_JoystickNumAxes(joystick_axis->joystick), + sizeof(boolean)); + + // Look for uncentered axes. + + for (i = 0; i < SDL_JoystickNumAxes(joystick_axis->joystick); ++i) + { + val = SDL_JoystickGetAxis(joystick_axis->joystick, i); + + joystick_axis->bad_axis[i] = abs(val) > (32768 / 5); + + if (joystick_axis->bad_axis[i]) + { + printf("Ignoring uncentered joystick axis #%i: %i\n", i, val); + } + } +} + +static int NextCalibrateStage(txt_joystick_axis_t *joystick_axis) +{ + switch (joystick_axis->config_stage) + { + case CONFIG_CENTER: + return CONFIG_STAGE1; + + // After pushing to the left, there are two possibilities: + // either it is a button axis, in which case we need to find + // the other button, or we can just move on to the next axis. + case CONFIG_STAGE1: + if (IS_BUTTON_AXIS(*joystick_axis->axis)) + { + return CONFIG_STAGE2; + } + else + { + return CONFIG_CENTER; + } + + case CONFIG_STAGE2: + return CONFIG_CENTER; + } + + return -1; +} + +static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_axis)) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + boolean advance; + + if (event->type != SDL_JOYBUTTONDOWN) + { + return 0; + } + + // At this point, we have a button press. + // In the first "center" stage, we're just trying to work out which + // joystick is being configured and which button the user is pressing. + if (joystick_axis->config_stage == CONFIG_CENTER) + { + joystick_axis->config_button = event->jbutton.button; + IdentifyBadAxes(joystick_axis); + + // Advance to next stage. + joystick_axis->config_stage = CONFIG_STAGE1; + SetCalibrationLabel(joystick_axis); + + return 1; + } + + // In subsequent stages, the user is asked to push in a specific + // direction and press the button. They must push the same button + // as they did before; this is necessary to support button axes. + if (event->jbutton.which == SDL_JoystickInstanceID(joystick_axis->joystick) + && event->jbutton.button == joystick_axis->config_button) + { + switch (joystick_axis->config_stage) + { + default: + case CONFIG_STAGE1: + advance = CalibrateAxis(joystick_axis); + break; + + case CONFIG_STAGE2: + advance = SetButtonAxisPositive(joystick_axis); + break; + } + + // Advance to the next calibration stage? + + if (advance) + { + joystick_axis->config_stage = NextCalibrateStage(joystick_axis); + SetCalibrationLabel(joystick_axis); + + // Finished? + if (joystick_axis->config_stage == CONFIG_CENTER) + { + TXT_CloseWindow(joystick_axis->config_window); + + if (joystick_axis->callback != NULL) + { + joystick_axis->callback(); + } + } + + return 1; + } + } + + return 0; +} + +static void CalibrateWindowClosed(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(joystick_axis)) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + + free(joystick_axis->bad_axis); + joystick_axis->bad_axis = NULL; + + SDL_JoystickClose(joystick_axis->joystick); + SDL_JoystickEventState(SDL_DISABLE); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + TXT_SDL_SetEventCallback(NULL, NULL); +} + +void TXT_ConfigureJoystickAxis(txt_joystick_axis_t *joystick_axis, + int using_button, + txt_joystick_axis_callback_t callback) +{ + // Open the joystick first. + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) + { + return; + } + + joystick_axis->joystick = SDL_JoystickOpen(joystick_index); + if (joystick_axis->joystick == NULL) + { + TXT_MessageBox(NULL, "Please configure a controller first!"); + return; + } + + SDL_JoystickEventState(SDL_ENABLE); + + // Build the prompt window. + + joystick_axis->config_window + = TXT_NewWindow("Gamepad/Joystick calibration"); + TXT_AddWidgets(joystick_axis->config_window, + TXT_NewStrut(0, 1), + joystick_axis->config_label = TXT_NewLabel(""), + TXT_NewStrut(0, 1), + NULL); + + TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(joystick_axis->config_window)); + TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_RIGHT, NULL); + TXT_SetWidgetAlign(joystick_axis->config_window, TXT_HORIZ_CENTER); + + if (using_button >= 0) + { + joystick_axis->config_stage = CONFIG_STAGE1; + joystick_axis->config_button = using_button; + IdentifyBadAxes(joystick_axis); + } + else + { + joystick_axis->config_stage = CONFIG_CENTER; + } + + SetCalibrationLabel(joystick_axis); + + // Close the joystick and shut down joystick subsystem when the window + // is closed. + TXT_SignalConnect(joystick_axis->config_window, "closed", + CalibrateWindowClosed, joystick_axis); + + TXT_SDL_SetEventCallback(EventCallback, joystick_axis); + + // When successfully calibrated, invoke this callback: + joystick_axis->callback = callback; +} + +void TXT_ConfigureGamepadAxis(txt_joystick_axis_t *joystick_axis, + int using_button, + txt_joystick_axis_callback_t callback) +{ + // Build the prompt window. + + joystick_axis->config_window = TXT_NewWindow("Configure axis"); + TXT_SetTableColumns(joystick_axis->config_window, 2); + TXT_SetColumnWidths(joystick_axis->config_window, 10, 5); + TXT_AddWidgets(joystick_axis->config_window, + TXT_NewCheckBox("Invert", joystick_axis->invert), + TXT_TABLE_EMPTY, + TXT_NewLabel("Dead zone"), + TXT_NewSpinControl(joystick_axis->dead_zone, 10, 90), + NULL); + + TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction( + joystick_axis->config_window, TXT_HORIZ_CENTER, + TXT_NewWindowEscapeAction(joystick_axis->config_window)); + TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_RIGHT, NULL); + TXT_SetWidgetAlign(joystick_axis->config_window, TXT_HORIZ_CENTER); +} + +static void TXT_JoystickAxisSizeCalc(TXT_UNCAST_ARG(joystick_axis)) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + + // All joystickinputs are the same size. + + joystick_axis->widget.w = JOYSTICK_AXIS_WIDTH; + joystick_axis->widget.h = 1; +} + +static void TXT_JoystickAxisDrawer(TXT_UNCAST_ARG(joystick_axis)) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + char buf[JOYSTICK_AXIS_WIDTH + 1]; + int i; + + if (*joystick_axis->axis < 0) + { + M_StringCopy(buf, "(none)", sizeof(buf)); + } + else if (IS_BUTTON_AXIS(*joystick_axis->axis)) + { + int neg, pos; + + neg = BUTTON_AXIS_NEG(*joystick_axis->axis); + pos = BUTTON_AXIS_POS(*joystick_axis->axis); + M_snprintf(buf, sizeof(buf), "BUTTONS #%i+#%i", neg, pos); + } + else if (IS_HAT_AXIS(*joystick_axis->axis)) + { + int hat, dir; + + hat = HAT_AXIS_HAT(*joystick_axis->axis); + dir = HAT_AXIS_DIRECTION(*joystick_axis->axis); + + M_snprintf(buf, sizeof(buf), "HAT #%i (%s)", hat, + dir == HAT_AXIS_HORIZONTAL ? "horizontal" : "vertical"); + } + else + { + M_snprintf(buf, sizeof(buf), "AXIS #%i", *joystick_axis->axis); + } + + TXT_SetWidgetBG(joystick_axis); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i = TXT_UTF8_Strlen(buf); i < joystick_axis->widget.w; ++i) + { + TXT_DrawString(" "); + } +} + +static void GetAxisDescription(int axis, char *buf, size_t buf_len) +{ + switch (axis) + { + case SDL_CONTROLLER_AXIS_INVALID: + M_StringCopy(buf, "(none)", sizeof(buf)); + break; + + case SDL_CONTROLLER_AXIS_LEFTX: + M_StringCopy(buf, "Left X", sizeof(buf)); + break; + + case SDL_CONTROLLER_AXIS_LEFTY: + M_StringCopy(buf, "Left Y", sizeof(buf)); + break; + + case SDL_CONTROLLER_AXIS_RIGHTX: + M_StringCopy(buf, "Right X", sizeof(buf)); + break; + + case SDL_CONTROLLER_AXIS_RIGHTY: + M_StringCopy(buf, "Right Y", sizeof(buf)); + break; + + default: + M_StringCopy(buf, "(unknown)", sizeof(buf)); + break; + } +} + +static void TXT_GamepadAxisDrawer(TXT_UNCAST_ARG(joystick_axis)) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + char buf[JOYSTICK_AXIS_WIDTH + 1]; + int i; + + GetAxisDescription(*joystick_axis->axis, buf, sizeof(buf)); + + TXT_SetWidgetBG(joystick_axis); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i = TXT_UTF8_Strlen(buf); i < joystick_axis->widget.w; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_JoystickAxisDestructor(TXT_UNCAST_ARG(joystick_axis)) +{ +} + +static int TXT_JoystickAxisKeyPress(TXT_UNCAST_ARG(joystick_axis), int key) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + + if (key == KEY_ENTER) + { + TXT_ConfigureJoystickAxis(joystick_axis, -1, NULL); + return 1; + } + + if (key == KEY_BACKSPACE || key == KEY_DEL) + { + *joystick_axis->axis = -1; + } + + return 0; +} + +static int TXT_GamepadAxisKeyPress(TXT_UNCAST_ARG(joystick_axis), int key) +{ + TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); + + if (key == KEY_ENTER) + { + TXT_ConfigureGamepadAxis(joystick_axis, -1, NULL); + return 1; + } + + if (key == KEY_BACKSPACE || key == KEY_DEL) + { + *joystick_axis->axis = -1; + } + + return 0; +} + +static void TXT_JoystickAxisMousePress(TXT_UNCAST_ARG(widget), + int x, int y, int b) +{ + TXT_CAST_ARG(txt_joystick_axis_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_JoystickAxisKeyPress(widget, KEY_ENTER); + } +} + +static void TXT_GamepadAxisMousePress(TXT_UNCAST_ARG(widget), int x, int y, + int b) +{ + TXT_CAST_ARG(txt_joystick_axis_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_GamepadAxisKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_joystick_axis_class = +{ + TXT_AlwaysSelectable, + TXT_JoystickAxisSizeCalc, + TXT_JoystickAxisDrawer, + TXT_JoystickAxisKeyPress, + TXT_JoystickAxisDestructor, + TXT_JoystickAxisMousePress, + NULL, +}; + +txt_widget_class_t txt_gamepad_axis_class = +{ + TXT_AlwaysSelectable, + TXT_JoystickAxisSizeCalc, + TXT_GamepadAxisDrawer, + TXT_GamepadAxisKeyPress, + TXT_JoystickAxisDestructor, + TXT_GamepadAxisMousePress, + NULL, +}; + +txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert, int *dead_zone, + txt_joystick_axis_direction_t dir) +{ + txt_joystick_axis_t *joystick_axis; + + joystick_axis = malloc(sizeof(txt_joystick_axis_t)); + + if (use_gamepad) + { + TXT_InitWidget(joystick_axis, &txt_gamepad_axis_class); + } + else + { + TXT_InitWidget(joystick_axis, &txt_joystick_axis_class); + } + joystick_axis->axis = axis; + joystick_axis->invert = invert; + joystick_axis->dead_zone = dead_zone; + joystick_axis->dir = dir; + joystick_axis->bad_axis = NULL; + + return joystick_axis; +} + diff --git a/games/NXDoom/src/setup/txt_joyaxis.h b/games/NXDoom/src/setup/txt_joyaxis.h new file mode 100644 index 00000000000..f0527c5b106 --- /dev/null +++ b/games/NXDoom/src/setup/txt_joyaxis.h @@ -0,0 +1,90 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef TXT_JOY_AXIS_H +#define TXT_JOY_AXIS_H + +typedef struct txt_joystick_axis_s txt_joystick_axis_t; + +typedef enum +{ + JOYSTICK_AXIS_HORIZONTAL, + JOYSTICK_AXIS_VERTICAL, +} txt_joystick_axis_direction_t; + +typedef enum +{ + CONFIG_CENTER, // "Center the joystick and press a button..." + CONFIG_STAGE1, // "Top or left and press a button..." + CONFIG_STAGE2, // [Optional] "Bottom or right and press a button..." +} txt_joystick_axis_stage_t; + +// Callback invoked when calibration is completed. +typedef void (*txt_joystick_axis_callback_t)(void); + +#include "txt_widget.h" +#include "txt_window.h" + +#include "SDL.h" + +// +// A joystick axis. +// + +struct txt_joystick_axis_s +{ + txt_widget_t widget; + int *axis, *invert, *dead_zone; + txt_joystick_axis_direction_t dir; + + // Only used when configuring: + + // Configuration prompt window and label. + txt_window_t *config_window; + txt_label_t *config_label; + + // SDL joystick handle for reading joystick state. + SDL_Joystick *joystick; + + // "Bad" joystick axes. Sometimes an axis can be stuck or "bad". An + // example I found is that if you unplug the nunchuck extension from + // a Wii remote, the axes from the nunchuck can be stuck at one of + // the maximum values. These have to be ignored, so when we ask the + // user to center the joystick, we look for bad axes that are not + // close to zero. + boolean *bad_axis; + + // Stage we have reached in configuring joystick axis. + txt_joystick_axis_stage_t config_stage; + + // Button to press to advance to next stage. + int config_button; + + // Callback invoked when the axis is calibrated. + txt_joystick_axis_callback_t callback; +}; + +txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert, int *dead_zone, + txt_joystick_axis_direction_t dir); + +// Configure a joystick axis widget. +// axis: The axis widget to configure. +// using_button: If non-negative, use this joystick button as the button +// to expect from the user. Otherwise, ask. +void TXT_ConfigureJoystickAxis(txt_joystick_axis_t *axis, int using_button, + txt_joystick_axis_callback_t callback); + +#endif /* #ifndef TXT_JOY_AXIS_H */ + + diff --git a/games/NXDoom/src/setup/txt_joybinput.c b/games/NXDoom/src/setup/txt_joybinput.c new file mode 100644 index 00000000000..a4362e34019 --- /dev/null +++ b/games/NXDoom/src/setup/txt_joybinput.c @@ -0,0 +1,780 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include +#include + +#include "SDL_joystick.h" +#include "SDL_gamecontroller.h" + +#include "doomkeys.h" +#include "joystick.h" +#include "i_joystick.h" +#include "i_system.h" +#include "m_controls.h" +#include "m_misc.h" + +#include "txt_joybinput.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_label.h" +#include "txt_sdl.h" +#include "txt_utf8.h" +#include "txt_window.h" + +#define JOYSTICK_INPUT_WIDTH 10 + + +// Joystick button variables. +// The ordering of this array is important. We will always try to map +// each variable to the virtual button with the same array index. For +// example: joybfire should always be 0, and then we change +// joystick_physical_buttons[0] to point to the physical joystick +// button that the user wants to use for firing. We do this so that +// the menus work (the game code is hard coded to interpret +// button #0 = select menu item, button #1 = go back to previous menu). +static int *all_joystick_buttons[NUM_VIRTUAL_BUTTONS] = +{ + &joybfire, + &joybuse, + &joybstrafe, + &joybspeed, + &joybstrafeleft, + &joybstraferight, + &joybprevweapon, + &joybnextweapon, + &joybjump, + &joybmenu, + &joybautomap, + &joybuseartifact, + &joybinvleft, + &joybinvright, + &joybflyup, + &joybflydown, + &joybflycenter, +}; + +// For indirection so that we're not dependent on item ordering in the +// SDL_GameControllerButton enum. +static const int gamepad_buttons[GAMEPAD_BUTTON_MAX] = +{ + SDL_CONTROLLER_BUTTON_A, + SDL_CONTROLLER_BUTTON_B, + SDL_CONTROLLER_BUTTON_X, + SDL_CONTROLLER_BUTTON_Y, + SDL_CONTROLLER_BUTTON_BACK, + SDL_CONTROLLER_BUTTON_GUIDE, + SDL_CONTROLLER_BUTTON_START, + SDL_CONTROLLER_BUTTON_LEFTSTICK, + SDL_CONTROLLER_BUTTON_RIGHTSTICK, + SDL_CONTROLLER_BUTTON_LEFTSHOULDER, + SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, + SDL_CONTROLLER_BUTTON_DPAD_UP, + SDL_CONTROLLER_BUTTON_DPAD_DOWN, + SDL_CONTROLLER_BUTTON_DPAD_LEFT, + SDL_CONTROLLER_BUTTON_DPAD_RIGHT, + SDL_CONTROLLER_BUTTON_MISC1, + SDL_CONTROLLER_BUTTON_PADDLE1, + SDL_CONTROLLER_BUTTON_PADDLE2, + SDL_CONTROLLER_BUTTON_PADDLE3, + SDL_CONTROLLER_BUTTON_PADDLE4, + SDL_CONTROLLER_BUTTON_TOUCHPAD, + GAMEPAD_BUTTON_TRIGGERLEFT, + GAMEPAD_BUTTON_TRIGGERRIGHT, +}; + +// Items in the following button lists are ordered according to gamepad_buttons +// above. +static const char *xbox360_buttons[GAMEPAD_BUTTON_MAX] = +{ + "A", + "B", + "X", + "Y", + "BACK", + "GUIDE", + "START", + "LSB", + "RSB", + "LB", + "RB", + "DPAD U", + "DPAD D", + "DPAD L", + "DPAD R", + "", + "", + "", + "", + "", + "", + "LT", + "RT", +}; + +static const char *xboxone_buttons[GAMEPAD_BUTTON_MAX] = +{ + "A", + "B", + "X", + "Y", + "VIEW", + "XBOX", + "MENU", + "LSB", + "RSB", + "LB", + "RB", + "DPAD U", + "DPAD D", + "DPAD L", + "DPAD R", + "PROFILE", + "P1", + "P2", + "P3", + "P4", + "", + "LT", + "RT", +}; + +static const char *ps3_buttons[GAMEPAD_BUTTON_MAX] = +{ + "X", + "CIRCLE", + "SQUARE", + "TRIANGLE", + "SELECT", + "PS", + "START", + "L3", + "R3", + "L1", + "R1", + "DPAD U", + "DPAD D", + "DPAD L", + "DPAD R", + "", + "", + "", + "", + "", + "", + "L2", + "R2", +}; + +static const char *ps4_buttons[GAMEPAD_BUTTON_MAX] = +{ + "X", + "CIRCLE", + "SQUARE", + "TRIANGLE", + "SHARE", + "PS", + "OPTIONS", + "L3", + "R3", + "L1", + "R1", + "DPAD U", + "DPAD D", + "DPAD L", + "DPAD R", + "", + "", + "", + "", + "", + "TOUCH", + "L2", + "R2", +}; + +static const char *ps5_buttons[GAMEPAD_BUTTON_MAX] = +{ + "X", + "CIRCLE", + "SQUARE", + "TRIANGLE", + "SHARE", + "PS", + "OPTIONS", + "L3", + "R3", + "L1", + "R1", + "DPAD U", + "DPAD D", + "DPAD L", + "DPAD R", + "MUTE", + "", + "", + "", + "", + "TOUCH", + "L2", + "R2", +}; + +static const char *switchpro_buttons[GAMEPAD_BUTTON_MAX] = +{ + "B", + "A", + "Y", + "X", + "MINUS", + "HOME", + "PLUS", + "LSB", + "RSB", + "L", + "R", + "DPAD U", + "DPAD D", + "DPAD L", + "DPAD R", + "CAPTURE", + "", + "", + "", + "", + "", + "ZL", + "ZR", +}; + +static int PhysicalForVirtualButton(int vbutton) +{ + if (vbutton < NUM_VIRTUAL_BUTTONS) + { + return joystick_physical_buttons[vbutton]; + } + else + { + return vbutton; + } +} + +// Get the virtual button number for the given variable, ie. the +// variable's index in all_joystick_buttons[NUM_VIRTUAL_BUTTONS]. +static int VirtualButtonForVariable(int *variable) +{ + int i; + + for (i = 0; i < arrlen(all_joystick_buttons); ++i) + { + if (variable == all_joystick_buttons[i]) + { + return i; + } + } + + I_Error("Couldn't find virtual button"); + return -1; +} + +// Rearrange joystick button configuration to be in "canonical" form: +// each joyb* variable should have a value equal to its index in +// all_joystick_buttons[NUM_VIRTUAL_BUTTONS] above. +static void CanonicalizeButtons(void) +{ + int new_mapping[NUM_VIRTUAL_BUTTONS]; + int vbutton; + int i; + + for (i = 0; i < arrlen(all_joystick_buttons); ++i) + { + vbutton = *all_joystick_buttons[i]; + + // Don't remap the speed key if it's bound to "always run". + // Also preserve "unbound" variables. + if ((all_joystick_buttons[i] == &joybspeed && + vbutton >= MAX_VIRTUAL_BUTTONS) || + vbutton < 0) + { + new_mapping[i] = i; + } + else + { + new_mapping[i] = PhysicalForVirtualButton(vbutton); + *all_joystick_buttons[i] = i; + } + } + + for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) + { + joystick_physical_buttons[i] = new_mapping[i]; + } +} + +// Check all existing buttons and clear any using the specified physical +// button. +static void ClearVariablesUsingButton(int physbutton) +{ + int vbutton; + int i; + + for (i = 0; i < arrlen(all_joystick_buttons); ++i) + { + vbutton = *all_joystick_buttons[i]; + + if (vbutton >= 0 && physbutton == PhysicalForVirtualButton(vbutton)) + { + *all_joystick_buttons[i] = -1; + } + } +} + +// Called in response to SDL events when the prompt window is open: + +static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + // Got the joystick button press? + + if (event->type == SDL_JOYBUTTONDOWN) + { + int vbutton, physbutton; + + // Before changing anything, remap button configuration into + // canonical form, to avoid conflicts. + CanonicalizeButtons(); + + vbutton = VirtualButtonForVariable(joystick_input->variable); + physbutton = event->jbutton.button; + + if (joystick_input->check_conflicts) + { + ClearVariablesUsingButton(physbutton); + } + + // Set mapping. + *joystick_input->variable = vbutton; + joystick_physical_buttons[vbutton] = physbutton; + + TXT_CloseWindow(joystick_input->prompt_window); + return 1; + } + + return 0; +} + +static int EventCallbackGamepad(SDL_Event *event, + TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + // Got the joystick button press? + + if (event->type == SDL_CONTROLLERBUTTONDOWN || + event->type == SDL_CONTROLLERAXISMOTION) + { + int vbutton, physbutton, axis; + + // Before changing anything, remap button configuration into + // canonical form, to avoid conflicts. + CanonicalizeButtons(); + + vbutton = VirtualButtonForVariable(joystick_input->variable); + axis = event->caxis.axis; + + if (event->type == SDL_CONTROLLERAXISMOTION && + (axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT || + axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) && + event->caxis.value > TRIGGER_THRESHOLD) + { + if (axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) + { + physbutton = GAMEPAD_BUTTON_TRIGGERLEFT; + } + else + { + physbutton = GAMEPAD_BUTTON_TRIGGERRIGHT; + } + } + else if (event->type == SDL_CONTROLLERBUTTONDOWN) + { + physbutton = event->cbutton.button; + } + else + { + return 0; + } + + if (joystick_input->check_conflicts) + { + ClearVariablesUsingButton(physbutton); + } + + // Set mapping. + *joystick_input->variable = vbutton; + joystick_physical_buttons[vbutton] = physbutton; + + TXT_CloseWindow(joystick_input->prompt_window); + return 1; + } + + return 0; +} + +// When the prompt window is closed, disable the event callback function; +// we are no longer interested in receiving notification of events. + +static void PromptWindowClosed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(joystick)) +{ + TXT_CAST_ARG(SDL_Joystick, joystick); + + SDL_JoystickClose(joystick); + TXT_SDL_SetEventCallback(NULL, NULL); + SDL_JoystickEventState(SDL_DISABLE); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); +} + +static void PromptWindowClosedGamepad(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(joystick)) +{ + TXT_CAST_ARG(SDL_GameController, joystick); + + SDL_GameControllerClose(joystick); + TXT_SDL_SetEventCallback(NULL, NULL); + SDL_JoystickEventState(SDL_DISABLE); + SDL_GameControllerEventState(SDL_DISABLE); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); +} + +static void OpenErrorWindow(void) +{ + TXT_MessageBox(NULL, "Please configure a controller first!"); +} + +static void OpenPromptWindow(txt_joystick_input_t *joystick_input) +{ + txt_window_t *window; + SDL_Joystick *joystick; + + // Silently update when the shift button is held down. + + joystick_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) + { + return; + } + + // Check the current joystick is valid + + joystick = SDL_JoystickOpen(joystick_index); + + if (joystick == NULL) + { + OpenErrorWindow(); + return; + } + + // Open the prompt window + + window = TXT_MessageBox(NULL, "Press the new button on the controller..."); + + TXT_SDL_SetEventCallback(EventCallback, joystick_input); + TXT_SignalConnect(window, "closed", PromptWindowClosed, joystick); + joystick_input->prompt_window = window; + + SDL_JoystickEventState(SDL_ENABLE); +} + +static void OpenPromptWindowGamepad(txt_joystick_input_t *joystick_input) +{ + txt_window_t *window; + SDL_GameController *gamepad; + + // Silently update when the shift button is held down. + + joystick_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) + { + return; + } + + // Check the current joystick is valid + + gamepad = SDL_GameControllerOpen(joystick_index); + + if (gamepad == NULL) + { + OpenErrorWindow(); + return; + } + + // Open the prompt window + + window = TXT_MessageBox(NULL, "Press the new button on the controller..."); + + TXT_SDL_SetEventCallback(EventCallbackGamepad, joystick_input); + TXT_SignalConnect(window, "closed", PromptWindowClosedGamepad, gamepad); + joystick_input->prompt_window = window; + + // GameController events do not fire if Joystick events are disabled. + SDL_JoystickEventState(SDL_ENABLE); + SDL_GameControllerEventState(SDL_ENABLE); +} + +static void TXT_JoystickInputSizeCalc(TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + // All joystickinputs are the same size. + + joystick_input->widget.w = JOYSTICK_INPUT_WIDTH; + joystick_input->widget.h = 1; +} + +static void GetJoystickButtonDescription(int vbutton, char *buf, + size_t buf_len) +{ + M_snprintf(buf, buf_len, "BUTTON #%i", + PhysicalForVirtualButton(vbutton) + 1); +} + +static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + char buf[20]; + int i; + + if (*joystick_input->variable < 0) + { + M_StringCopy(buf, "(none)", sizeof(buf)); + } + else + { + GetJoystickButtonDescription(*joystick_input->variable, + buf, sizeof(buf)); + } + + TXT_SetWidgetBG(joystick_input); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i = TXT_UTF8_Strlen(buf); i < JOYSTICK_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static int GetGamepadButtonIndex(int button) +{ + int i; + + for (i = 0; i < arrlen(gamepad_buttons); ++i) + { + if (button == gamepad_buttons[i]) + { + return i; + } + } + + return -1; +} + +static void GetGamepadButtonDescription(int vbutton, char *buf, size_t buf_len) +{ + int index; + + index = GetGamepadButtonIndex(PhysicalForVirtualButton(vbutton)); + + if (index < 0) + { + M_StringCopy(buf, "(unknown)", buf_len); + return; + } + + switch (gamepad_type) + { + case SDL_CONTROLLER_TYPE_XBOX360: + M_snprintf(buf, buf_len, "%s", xbox360_buttons[index]); + break; + + case SDL_CONTROLLER_TYPE_XBOXONE: + M_snprintf(buf, buf_len, "%s", xboxone_buttons[index]); + break; + + case SDL_CONTROLLER_TYPE_PS3: + M_snprintf(buf, buf_len, "%s", ps3_buttons[index]); + break; + + case SDL_CONTROLLER_TYPE_PS4: + M_snprintf(buf, buf_len, "%s", ps4_buttons[index]); + break; + + case SDL_CONTROLLER_TYPE_PS5: + M_snprintf(buf, buf_len, "%s", ps5_buttons[index]); + break; + + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + M_snprintf(buf, buf_len, "%s", switchpro_buttons[index]); + break; + + default: + M_snprintf(buf, buf_len, "BUTTON #%i", + PhysicalForVirtualButton(vbutton) + 1); + break; + } +} + +static void TXT_GamepadInputDrawer(TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + char buf[20]; // Need to fit "BUTTON #XX" + int i; + + if (*joystick_input->variable < 0) + { + M_StringCopy(buf, "(none)", sizeof(buf)); + } + else + { + GetGamepadButtonDescription(*joystick_input->variable, buf, + sizeof(buf)); + } + + TXT_SetWidgetBG(joystick_input); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i = TXT_UTF8_Strlen(buf); i < JOYSTICK_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_JoystickInputDestructor(TXT_UNCAST_ARG(joystick_input)) +{ +} + +static int TXT_JoystickInputKeyPress(TXT_UNCAST_ARG(joystick_input), int key) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + if (key == KEY_ENTER) + { + // Open a window to prompt for the new joystick press + OpenPromptWindow(joystick_input); + + return 1; + } + + if (key == KEY_BACKSPACE || key == KEY_DEL) + { + *joystick_input->variable = -1; + } + + return 0; +} + +static int TXT_GamepadInputKeyPress(TXT_UNCAST_ARG(joystick_input), int key) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + if (key == KEY_ENTER) + { + // Open a window to prompt for the new joystick press + OpenPromptWindowGamepad(joystick_input); + + return 1; + } + + if (key == KEY_BACKSPACE || key == KEY_DEL) + { + *joystick_input->variable = -1; + } + + return 0; +} + +static void TXT_JoystickInputMousePress(TXT_UNCAST_ARG(widget), + int x, int y, int b) +{ + TXT_CAST_ARG(txt_joystick_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_JoystickInputKeyPress(widget, KEY_ENTER); + } +} + +static void TXT_GamepadInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, + int b) +{ + TXT_CAST_ARG(txt_joystick_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_GamepadInputKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_joystick_input_class = +{ + TXT_AlwaysSelectable, + TXT_JoystickInputSizeCalc, + TXT_JoystickInputDrawer, + TXT_JoystickInputKeyPress, + TXT_JoystickInputDestructor, + TXT_JoystickInputMousePress, + NULL, +}; + +txt_widget_class_t txt_gamepad_input_class = +{ + TXT_AlwaysSelectable, + TXT_JoystickInputSizeCalc, + TXT_GamepadInputDrawer, + TXT_GamepadInputKeyPress, + TXT_JoystickInputDestructor, + TXT_GamepadInputMousePress, + NULL, +}; + +txt_joystick_input_t *TXT_NewJoystickInput(int *variable) +{ + txt_joystick_input_t *joystick_input; + + joystick_input = malloc(sizeof(txt_joystick_input_t)); + + if (use_gamepad) + { + TXT_InitWidget(joystick_input, &txt_gamepad_input_class); + } + else + { + TXT_InitWidget(joystick_input, &txt_joystick_input_class); + } + joystick_input->variable = variable; + + return joystick_input; +} + diff --git a/games/NXDoom/src/setup/txt_joybinput.h b/games/NXDoom/src/setup/txt_joybinput.h new file mode 100644 index 00000000000..26a9f24c320 --- /dev/null +++ b/games/NXDoom/src/setup/txt_joybinput.h @@ -0,0 +1,40 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef TXT_JOYB_INPUT_H +#define TXT_JOYB_INPUT_H + +typedef struct txt_joystick_input_s txt_joystick_input_t; + +#include "txt_widget.h" +#include "txt_window.h" + +// +// A joystick input is like an input box. When selected, a box pops up +// allowing a joystick button to be pressed to select it. +// + +struct txt_joystick_input_s +{ + txt_widget_t widget; + int *variable; + txt_window_t *prompt_window; + int check_conflicts; +}; + +txt_joystick_input_t *TXT_NewJoystickInput(int *variable); + +#endif /* #ifndef TXT_JOYB_INPUT_H */ + + diff --git a/games/NXDoom/src/setup/txt_keyinput.c b/games/NXDoom/src/setup/txt_keyinput.c new file mode 100644 index 00000000000..6c3b35917d0 --- /dev/null +++ b/games/NXDoom/src/setup/txt_keyinput.c @@ -0,0 +1,185 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include + +#include "doomkeys.h" +#include "m_misc.h" + +#include "txt_keyinput.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_label.h" +#include "txt_utf8.h" +#include "txt_window.h" + +#define KEY_INPUT_WIDTH 8 + +static int KeyPressCallback(txt_window_t *window, int key, + TXT_UNCAST_ARG(key_input)) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + + if (key != KEY_ESCAPE) + { + // Got the key press. Save to the variable and close the window. + + *key_input->variable = key; + + if (key_input->check_conflicts) + { + TXT_EmitSignal(key_input, "set"); + } + + TXT_CloseWindow(window); + + // Return to normal input mode now that we have the key. + TXT_SetInputMode(TXT_INPUT_NORMAL); + + return 1; + } + else + { + return 0; + } +} + +static void ReleaseGrab(TXT_UNCAST_ARG(window), TXT_UNCAST_ARG(unused)) +{ + // SDL2-TODO: Needed? + // SDL_WM_GrabInput(SDL_GRAB_OFF); +} + +static void OpenPromptWindow(txt_key_input_t *key_input) +{ + txt_window_t *window; + + // Silently update when the shift button is held down. + + key_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + + window = TXT_MessageBox(NULL, "Press the new key..."); + + TXT_SetKeyListener(window, KeyPressCallback, key_input); + + // Switch to raw input mode while we're grabbing the key. + TXT_SetInputMode(TXT_INPUT_RAW); + + // Grab input while reading the key. On Windows Mobile + // handheld devices, the hardware keypresses are only + // detected when input is grabbed. + + // SDL2-TODO: Needed? + //SDL_WM_GrabInput(SDL_GRAB_ON); + TXT_SignalConnect(window, "closed", ReleaseGrab, NULL); +} + +static void TXT_KeyInputSizeCalc(TXT_UNCAST_ARG(key_input)) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + + // All keyinputs are the same size. + + key_input->widget.w = KEY_INPUT_WIDTH; + key_input->widget.h = 1; +} + + +static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input)) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + char buf[20]; + int i; + + if (*key_input->variable == 0) + { + M_StringCopy(buf, "(none)", sizeof(buf)); + } + else + { + TXT_GetKeyDescription(*key_input->variable, buf, sizeof(buf)); + } + + TXT_SetWidgetBG(key_input); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i = TXT_UTF8_Strlen(buf); i < KEY_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_KeyInputDestructor(TXT_UNCAST_ARG(key_input)) +{ +} + +static int TXT_KeyInputKeyPress(TXT_UNCAST_ARG(key_input), int key) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + + if (key == KEY_ENTER) + { + // Open a window to prompt for the new key press + + OpenPromptWindow(key_input); + + return 1; + } + + if (key == KEY_BACKSPACE || key == KEY_DEL) + { + *key_input->variable = 0; + } + + return 0; +} + +static void TXT_KeyInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) +{ + TXT_CAST_ARG(txt_key_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_KeyInputKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_key_input_class = +{ + TXT_AlwaysSelectable, + TXT_KeyInputSizeCalc, + TXT_KeyInputDrawer, + TXT_KeyInputKeyPress, + TXT_KeyInputDestructor, + TXT_KeyInputMousePress, + NULL, +}; + +txt_key_input_t *TXT_NewKeyInput(int *variable) +{ + txt_key_input_t *key_input; + + key_input = malloc(sizeof(txt_key_input_t)); + + TXT_InitWidget(key_input, &txt_key_input_class); + key_input->variable = variable; + + return key_input; +} + diff --git a/games/NXDoom/src/setup/txt_keyinput.h b/games/NXDoom/src/setup/txt_keyinput.h new file mode 100644 index 00000000000..334d6c1cf15 --- /dev/null +++ b/games/NXDoom/src/setup/txt_keyinput.h @@ -0,0 +1,38 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef TXT_KEY_INPUT_H +#define TXT_KEY_INPUT_H + +typedef struct txt_key_input_s txt_key_input_t; + +#include "txt_widget.h" + +// +// A key input is like an input box. When selected, a box pops up +// allowing a key to be selected. +// + +struct txt_key_input_s +{ + txt_widget_t widget; + int *variable; + int check_conflicts; +}; + +txt_key_input_t *TXT_NewKeyInput(int *variable); + +#endif /* #ifndef TXT_KEY_INPUT_H */ + + diff --git a/games/NXDoom/src/setup/txt_mouseinput.c b/games/NXDoom/src/setup/txt_mouseinput.c new file mode 100644 index 00000000000..99196a581ee --- /dev/null +++ b/games/NXDoom/src/setup/txt_mouseinput.c @@ -0,0 +1,184 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include +#include + +#include "doomkeys.h" +#include "m_misc.h" + +#include "txt_mouseinput.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_label.h" +#include "txt_utf8.h" +#include "txt_window.h" + +// eg. "BUTTON #10" +#define MOUSE_INPUT_WIDTH 10 + +static int MousePressCallback(txt_window_t *window, + int x, int y, int b, + TXT_UNCAST_ARG(mouse_input)) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + + // Got the mouse press. Save to the variable and close the window. + + *mouse_input->variable = b - TXT_MOUSE_BASE; + + if (mouse_input->check_conflicts) + { + TXT_EmitSignal(mouse_input, "set"); + } + + TXT_CloseWindow(window); + + return 1; +} + +static void OpenPromptWindow(txt_mouse_input_t *mouse_input) +{ + txt_window_t *window; + + // Silently update when the shift key is held down. + mouse_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); + + window = TXT_MessageBox(NULL, "Press the new mouse button..."); + + TXT_SetMouseListener(window, MousePressCallback, mouse_input); +} + +static void TXT_MouseInputSizeCalc(TXT_UNCAST_ARG(mouse_input)) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + + // All mouseinputs are the same size. + + mouse_input->widget.w = MOUSE_INPUT_WIDTH; + mouse_input->widget.h = 1; +} + +static void GetMouseButtonDescription(int button, char *buf, size_t buf_len) +{ + switch (button) + { + case 0: + M_StringCopy(buf, "LEFT", buf_len); + break; + case 1: + M_StringCopy(buf, "RIGHT", buf_len); + break; + case 2: + M_StringCopy(buf, "MID", buf_len); + break; + case 3: + M_StringCopy(buf, "WHEEL UP", buf_len); + break; + case 4: + M_StringCopy(buf, "WHEEL DOWN", buf_len); + break; + default: + M_snprintf(buf, buf_len, "BUTTON #%i", button - 1); + break; + } +} + +static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input)) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + char buf[20]; + int i; + + if (*mouse_input->variable < 0) + { + M_StringCopy(buf, "(none)", sizeof(buf)); + } + else + { + GetMouseButtonDescription(*mouse_input->variable, buf, sizeof(buf)); + } + + TXT_SetWidgetBG(mouse_input); + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i = TXT_UTF8_Strlen(buf); i < MOUSE_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_MouseInputDestructor(TXT_UNCAST_ARG(mouse_input)) +{ +} + +static int TXT_MouseInputKeyPress(TXT_UNCAST_ARG(mouse_input), int key) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + + if (key == KEY_ENTER) + { + // Open a window to prompt for the new mouse press + + OpenPromptWindow(mouse_input); + + return 1; + } + + if (key == KEY_BACKSPACE || key == KEY_DEL) + { + *mouse_input->variable = -1; + } + + return 0; +} + +static void TXT_MouseInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) +{ + TXT_CAST_ARG(txt_mouse_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_MouseInputKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_mouse_input_class = +{ + TXT_AlwaysSelectable, + TXT_MouseInputSizeCalc, + TXT_MouseInputDrawer, + TXT_MouseInputKeyPress, + TXT_MouseInputDestructor, + TXT_MouseInputMousePress, + NULL, +}; + +txt_mouse_input_t *TXT_NewMouseInput(int *variable) +{ + txt_mouse_input_t *mouse_input; + + mouse_input = malloc(sizeof(txt_mouse_input_t)); + + TXT_InitWidget(mouse_input, &txt_mouse_input_class); + mouse_input->variable = variable; + + return mouse_input; +} + diff --git a/games/NXDoom/src/setup/txt_mouseinput.h b/games/NXDoom/src/setup/txt_mouseinput.h new file mode 100644 index 00000000000..2b05c371823 --- /dev/null +++ b/games/NXDoom/src/setup/txt_mouseinput.h @@ -0,0 +1,38 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#ifndef TXT_MOUSE_INPUT_H +#define TXT_MOUSE_INPUT_H + +typedef struct txt_mouse_input_s txt_mouse_input_t; + +#include "txt_widget.h" + +// +// A mouse input is like an input box. When selected, a box pops up +// allowing a mouse to be selected. +// + +struct txt_mouse_input_s +{ + txt_widget_t widget; + int *variable; + int check_conflicts; +}; + +txt_mouse_input_t *TXT_NewMouseInput(int *variable); + +#endif /* #ifndef TXT_MOUSE_INPUT_H */ + + diff --git a/games/NXDoom/src/sha1.c b/games/NXDoom/src/sha1.c new file mode 100644 index 00000000000..8504134a985 --- /dev/null +++ b/games/NXDoom/src/sha1.c @@ -0,0 +1,321 @@ +/* sha1.c - SHA1 hash function + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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. + */ + + +/* Test vectors: + * + * "abc" + * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D + * + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 + */ + +#include +#include +#include +#include + +#include "i_swap.h" +#include "sha1.h" + +void SHA1_Init(sha1_context_t *hd) +{ + hd->h0 = 0x67452301; + hd->h1 = 0xefcdab89; + hd->h2 = 0x98badcfe; + hd->h3 = 0x10325476; + hd->h4 = 0xc3d2e1f0; + hd->nblocks = 0; + hd->count = 0; +} + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void Transform(sha1_context_t *hd, byte *data) +{ + uint32_t a,b,c,d,e,tm; + uint32_t x[16]; + + /* get values from the chaining vars */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + +#ifdef SYS_BIG_ENDIAN + memcpy(x, data, 64); +#else + { + int i; + byte *p2; + for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + + +#define K1 0x5A827999L +#define K2 0x6ED9EBA1L +#define K3 0x8F1BBCDCL +#define K4 0xCA62C1D6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) + +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ + ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ + , (x[i&0x0f] = rol(tm,1)) ) + +#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + + f( b, c, d ) \ + + k \ + + m; \ + b = rol( b, 30 ); \ + } while(0) + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + /* update chainig vars */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +void SHA1_Update(sha1_context_t *hd, byte *inbuf, size_t inlen) +{ + if (hd->count == 64) + { + /* flush the buffer */ + Transform(hd, hd->buf); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) + { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + SHA1_Update(hd, NULL, 0); + if (!inlen) + return; + } + + while (inlen >= 64) + { + Transform(hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* The routine final terminates the computation and + * returns the digest. + * The handle is prepared for a new cycle, but adding bytes to the + * handle will the destroy the returned buffer. + * Returns: 20 bytes representing the digest. + */ + +void SHA1_Final(sha1_digest_t digest, sha1_context_t *hd) +{ + uint32_t t, msb, lsb; + byte *p; + + SHA1_Update(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if (hd->count < 56) + { + /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 56) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { + /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 64) + hd->buf[hd->count++] = 0; + SHA1_Update(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb ; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb ; + Transform(hd, hd->buf); + + p = hd->buf; +#ifdef SYS_BIG_ENDIAN +#define X(a) do { *(uint32_t*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X + + memcpy(digest, hd->buf, sizeof(sha1_digest_t)); +} + +void SHA1_UpdateInt32(sha1_context_t *context, unsigned int val) +{ + byte buf[4]; + + buf[0] = (val >> 24) & 0xff; + buf[1] = (val >> 16) & 0xff; + buf[2] = (val >> 8) & 0xff; + buf[3] = val & 0xff; + + SHA1_Update(context, buf, 4); +} + +void SHA1_UpdateString(sha1_context_t *context, char *str) +{ + SHA1_Update(context, (byte *) str, strlen(str) + 1); +} + diff --git a/games/NXDoom/src/sha1.h b/games/NXDoom/src/sha1.h new file mode 100644 index 00000000000..249571be335 --- /dev/null +++ b/games/NXDoom/src/sha1.h @@ -0,0 +1,40 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// SHA-1 digest. +// + +#ifndef __SHA1_H__ +#define __SHA1_H__ + +#include "doomtype.h" + +typedef struct sha1_context_s sha1_context_t; +typedef byte sha1_digest_t[20]; + +struct sha1_context_s { + uint32_t h0,h1,h2,h3,h4; + uint32_t nblocks; + byte buf[64]; + int count; +}; + +void SHA1_Init(sha1_context_t *context); +void SHA1_Update(sha1_context_t *context, byte *buf, size_t len); +void SHA1_Final(sha1_digest_t digest, sha1_context_t *context); +void SHA1_UpdateInt32(sha1_context_t *context, unsigned int val); +void SHA1_UpdateString(sha1_context_t *context, char *str); + +#endif /* #ifndef __SHA1_H__ */ + diff --git a/games/NXDoom/src/strife-res.rc.in b/games/NXDoom/src/strife-res.rc.in new file mode 100644 index 00000000000..ab9a2580de7 --- /dev/null +++ b/games/NXDoom/src/strife-res.rc.in @@ -0,0 +1,30 @@ +1 ICON "@top_srcdir@/data/strife.ico" + +#include + +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" + +1 VERSIONINFO +PRODUCTVERSION @WINDOWS_RC_VERSION@ +FILEVERSION @WINDOWS_RC_VERSION@ +FILETYPE 1 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "FileVersion", "@PACKAGE_VERSION@.0" + VALUE "FileDescription", "@PACKAGE_STRING@" + VALUE "InternalName", "@PACKAGE_TARNAME@" + VALUE "CompanyName", "@PACKAGE_BUGREPORT@" + VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" + VALUE "ProductName", "@PACKAGE_NAME@" + VALUE "ProductVersion", "@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} + diff --git a/games/NXDoom/src/strife/.gitignore b/games/NXDoom/src/strife/.gitignore new file mode 100644 index 00000000000..d4e88e5a219 --- /dev/null +++ b/games/NXDoom/src/strife/.gitignore @@ -0,0 +1,5 @@ +Makefile +Makefile.in +.deps +tags +TAGS diff --git a/games/NXDoom/src/strife/CMakeLists.txt b/games/NXDoom/src/strife/CMakeLists.txt new file mode 100644 index 00000000000..20d336cdb67 --- /dev/null +++ b/games/NXDoom/src/strife/CMakeLists.txt @@ -0,0 +1,92 @@ +set(STRIFE_SOURCES + am_map.c am_map.h + deh_ammo.c + deh_cheat.c + deh_strife.c + deh_frame.c + deh_misc.c deh_misc.h + deh_ptr.c + deh_sound.c + deh_thing.c + deh_weapon.c + d_englsh.h + d_items.c d_items.h + d_main.c d_main.h + d_net.c + doomdata.h + doomdef.c doomdef.h + doomstat.c doomstat.h + d_player.h + dstrings.c dstrings.h + d_textur.h + d_think.h + f_finale.c f_finale.h + f_wipe.c f_wipe.h + g_game.c g_game.h + hu_lib.c hu_lib.h + hu_stuff.c hu_stuff.h + info.c info.h + m_menu.c m_menu.h + m_random.c m_random.h + m_saves.c m_saves.h + p_ceilng.c + p_dialog.c p_dialog.h + p_doors.c + p_enemy.c + p_floor.c + p_inter.c p_inter.h + p_lights.c + p_local.h + p_map.c + p_maputl.c + p_mobj.c p_mobj.h + p_plats.c + p_pspr.c p_pspr.h + p_saveg.c p_saveg.h + p_setup.c p_setup.h + p_sight.c + p_spec.c p_spec.h + p_switch.c + p_telept.c + p_tick.c p_tick.h + p_user.c + r_bsp.c r_bsp.h + r_data.c r_data.h + r_defs.h + r_draw.c r_draw.h + r_local.h + r_main.c r_main.h + r_plane.c r_plane.h + r_segs.c r_segs.h + r_sky.c r_sky.h + r_state.h + r_things.c r_things.h + s_sound.c s_sound.h + sounds.c sounds.h + st_lib.c st_lib.h + st_stuff.c st_stuff.h + wi_stuff.c wi_stuff.h) + +add_library(strife STATIC ${STRIFE_SOURCES}) + +target_include_directories(strife PRIVATE "../" "../../win32/" "${CMAKE_CURRENT_BINARY_DIR}/../../") +if (DEFINED EMSCRIPTEN) + set(SDL_FLAGS "-s USE_SDL=2") + if(ENABLE_SDL2_MIXER) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") + endif() + if(ENABLE_SDL2_NET) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") + endif() +else() + set(SDL_LINK_LIBS, "SDL2::SDL2") + if(ENABLE_SDL2_MIXER) + list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) + endif() + if(ENABLE_SDL2_NET) + list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) + endif() +endif() +target_link_libraries(strife textscreen ${SDL_LINK_LIBS}) +set_target_properties(strife PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") +set_target_properties(strife PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/strife/Makefile.am b/games/NXDoom/src/strife/Makefile.am new file mode 100644 index 00000000000..36d7b0c58fa --- /dev/null +++ b/games/NXDoom/src/strife/Makefile.am @@ -0,0 +1,85 @@ +AM_CFLAGS=-I$(top_srcdir)/src \ + -I$(top_srcdir)/textscreen \ + @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ + +EXTRA_DIST = \ + CMakeLists.txt \ + strife_icon.c + +noinst_LIBRARIES=libstrife.a + +libstrife_a_SOURCES = \ +am_map.c am_map.h \ +deh_ammo.c \ +deh_cheat.c \ +deh_strife.c \ +deh_frame.c \ +deh_misc.c deh_misc.h \ +deh_ptr.c \ +deh_sound.c \ +deh_thing.c \ +deh_weapon.c \ + d_englsh.h \ +d_items.c d_items.h \ +d_main.c d_main.h \ +d_net.c \ + doomdata.h \ +doomdef.c doomdef.h \ +doomstat.c doomstat.h \ + d_player.h \ +dstrings.c dstrings.h \ + d_textur.h \ + d_think.h \ +f_finale.c f_finale.h \ +f_wipe.c f_wipe.h \ +g_game.c g_game.h \ +hu_lib.c hu_lib.h \ +hu_stuff.c hu_stuff.h \ +info.c info.h \ +m_menu.c m_menu.h \ +m_random.c m_random.h \ +m_saves.c m_saves.h \ +p_ceilng.c \ +p_dialog.c p_dialog.h \ +p_doors.c \ +p_enemy.c \ +p_floor.c \ +p_inter.c p_inter.h \ +p_lights.c \ + p_local.h \ +p_map.c \ +p_maputl.c \ +p_mobj.c p_mobj.h \ +p_plats.c \ +p_pspr.c p_pspr.h \ +p_saveg.c p_saveg.h \ +p_setup.c p_setup.h \ +p_sight.c \ +p_spec.c p_spec.h \ +p_switch.c \ +p_telept.c \ +p_tick.c p_tick.h \ +p_user.c \ +r_bsp.c r_bsp.h \ +r_data.c r_data.h \ + r_defs.h \ +r_draw.c r_draw.h \ + r_local.h \ +r_main.c r_main.h \ +r_plane.c r_plane.h \ +r_segs.c r_segs.h \ +r_sky.c r_sky.h \ + r_state.h \ +r_things.c r_things.h \ +s_sound.c s_sound.h \ +sounds.c sounds.h \ +st_lib.c st_lib.h \ +st_stuff.c st_stuff.h \ +wi_stuff.c wi_stuff.h + +if HAVE_ICONS + +strife_icon.c : $(top_builddir)/data/strife.png + $(top_builddir)/data/convert-icon $(top_builddir)/data/strife.png $@ + +endif diff --git a/games/NXDoom/src/strife/am_map.c b/games/NXDoom/src/strife/am_map.c new file mode 100644 index 00000000000..e36fb56d5cb --- /dev/null +++ b/games/NXDoom/src/strife/am_map.c @@ -0,0 +1,1415 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: the automap code +// + + +#include + +#include "deh_main.h" + +#include "z_zone.h" +#include "doomkeys.h" +#include "doomdef.h" +#include "m_misc.h" +#include "st_stuff.h" +#include "p_local.h" +#include "w_wad.h" + +#include "m_cheat.h" +#include "m_controls.h" +#include "i_system.h" +#include "i_timer.h" + +// Needs access to LFB. +#include "v_video.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "dstrings.h" + +#include "am_map.h" + + +// Automap colors +#define BACKGROUND 240 // haleyjd [STRIFE] +#define WALLCOLORS 5 // villsa [STRIFE] +#define WALLRANGE 16 +#define TSWALLCOLORS 16 +#define FDWALLCOLORS 122 // villsa [STRIFE] +#define CDWALLCOLORS 116 +#define CTWALLCOLORS 19 // villsa [STRIFE] +#define SPWALLCOLORS 243 // villsa [STRIFE] +#define THINGCOLORS 233 // villsa [STRIFE] +#define MISSILECOLORS 227 // villsa [STRIFE] +#define SHOOTABLECOLORS 235 // villsa [STRIFE] + +// drawing stuff + +#define AM_NUMMARKPOINTS 10 + +// scale on entry +#define INITSCALEMTOF (.2*FRACUNIT) +// how much the automap moves window per tic in frame-buffer coordinates +// moves 140 pixels in 1 second +#define F_PANINC 4 +// how much zoom-in per tic +// goes to 2x in 1 second +#define M_ZOOMIN ((int) (1.02*FRACUNIT)) +// how much zoom-out per tic +// pulls out to 0.5x in 1 second +#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) + +// translates between frame-buffer and map distances +#define FTOM(x) FixedMul(((x)<<16),scale_ftom) +#define MTOF(x) (FixedMul((x),scale_mtof)>>16) +// translates between frame-buffer and map coordinates +#define CXMTOF(x) (f_x + MTOF((x)-m_x)) +#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) + +// the following is crap +#define LINE_NEVERSEE ML_DONTDRAW + +typedef struct +{ + int x, y; +} fpoint_t; + +typedef struct +{ + fpoint_t a, b; +} fline_t; + +typedef struct +{ + fixed_t x,y; +} mpoint_t; + +typedef struct +{ + mpoint_t a, b; +} mline_t; + +typedef struct +{ + fixed_t slp, islp; +} islope_t; + + + +// +// The vector graphics for the automap. +// A line drawing of the player pointing right, +// starting from the middle. +// +#define R ((8*PLAYERRADIUS)/7) +mline_t player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/4 } }, // -----> + { { R, 0 }, { R-R/2, -R/4 } }, + { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> + { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> + { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } +}; +#undef R + +#define R ((8*PLAYERRADIUS)/7) +mline_t cheat_player_arrow[] = { + { { -R+R/8, 0 }, { R, 0 } }, // ----- + { { R, 0 }, { R-R/2, R/6 } }, // -----> + { { R, 0 }, { R-R/2, -R/6 } }, + { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> + { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, + { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> + { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, + { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> + { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, + { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, + { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> + { { -R/6, -R/6 }, { 0, -R/6 } }, + { { 0, -R/6 }, { 0, R/4 } }, + { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> + { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, + { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } +}; +#undef R + +#define R (FRACUNIT) +mline_t triangle_guy[] = { + { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } }, + { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } }, + { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } } +}; +#undef R + +#define R (FRACUNIT) +mline_t thintriangle_guy[] = { + { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, + { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, + { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } +}; +#undef R + + + + +static int cheating = 0; +//static int grid = 0; [STRIFE]: no such variable + +boolean automapactive = false; +static int finit_width = SCREENWIDTH; +static int finit_height = SCREENHEIGHT - 32; + +// location of window on screen +static int f_x; +static int f_y; + +// size of window on screen +static int f_w; +static int f_h; + +static int lightlev; // used for funky strobing effect +static byte* fb; // pseudo-frame buffer +static int amclock; + +static mpoint_t m_paninc; // how far the window pans each tic (map coords) +static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) +static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) + +static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) +static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) + +// +// width/height of window on map (map coords) +// +static fixed_t m_w; +static fixed_t m_h; + +// based on level size +static fixed_t min_x; +static fixed_t min_y; +static fixed_t max_x; +static fixed_t max_y; + +static fixed_t max_w; // max_x-min_x, +static fixed_t max_h; // max_y-min_y + +// based on player size +static fixed_t min_w; +static fixed_t min_h; + + +static fixed_t min_scale_mtof; // used to tell when to stop zooming out +static fixed_t max_scale_mtof; // used to tell when to stop zooming in + +// old stuff for recovery later +static fixed_t old_m_w, old_m_h; +static fixed_t old_m_x, old_m_y; + +// old location used by the Follower routine +static mpoint_t f_oldloc; + +// used by MTOF to scale from map-to-frame-buffer coords +static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; +// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) +static fixed_t scale_ftom; + +static player_t *plr; // the player represented by an arrow + +static patch_t *marknums[10]; // numbers used for marking by the automap +static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are +static int markpointnum = 0; // next point to be assigned +static int mapmarknum = 0; // villsa [STRIFE] unused but this was meant to be used for objective based markers +static int followplayer = 1; // specifies whether to follow the player around + +cheatseq_t cheat_amap = CHEAT("topo", 0); // villsa [STRIFE] + +static boolean stopped = true; + + +// Calculates the slope and slope according to the x-axis of a line +// segment in map coordinates (with the upright y-axis n' all) so +// that it can be used with the brain-dead drawing stuff. + +void +AM_getIslope +( mline_t* ml, + islope_t* is ) +{ + int dx, dy; + + dy = ml->a.y - ml->b.y; + dx = ml->b.x - ml->a.x; + if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); + else is->islp = FixedDiv(dx, dy); + if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); + else is->slp = FixedDiv(dy, dx); + +} + +// +// +// +void AM_activateNewScale(void) +{ + m_x += m_w/2; + m_y += m_h/2; + m_w = FTOM(f_w); + m_h = FTOM(f_h); + m_x -= m_w/2; + m_y -= m_h/2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + +// +// +// +void AM_saveScaleAndLoc(void) +{ + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; +} + +// +// +// +void AM_restoreScaleAndLoc(void) +{ + + m_w = old_m_w; + m_h = old_m_h; + if (!followplayer) + { + m_x = old_m_x; + m_y = old_m_y; + } else { + m_x = plr->mo->x - m_w/2; + m_y = plr->mo->y - m_h/2; + } + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + + // Change the scaling multipliers + scale_mtof = FixedDiv(f_w<mo->x; // 20160306 [STRIFE]: use player position + markpoints[markpointnum].y = plr->mo->y; + //markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; + ++markpointnum; // haleyjd 20141101: [STRIFE] does not wrap around +} + +// +// Determines bounding box of all vertices, +// sets global variables controlling zoom range. +// +void AM_findMinMaxBoundaries(void) +{ + int i; + fixed_t a; + fixed_t b; + + min_x = min_y = INT_MAX; + max_x = max_y = -INT_MAX; + + for (i=0;i max_x) + max_x = vertexes[i].x; + + if (vertexes[i].y < min_y) + min_y = vertexes[i].y; + else if (vertexes[i].y > max_y) + max_y = vertexes[i].y; + } + + max_w = max_x - min_x; + max_h = max_y - min_y; + + min_w = 2*PLAYERRADIUS; // const? never changed? + min_h = 2*PLAYERRADIUS; + + a = FixedDiv(f_w< max_x) + m_x = max_x - m_w/2; + else if (m_x + m_w/2 < min_x) + m_x = min_x - m_w/2; + + if (m_y + m_h/2 > max_y) + m_y = max_y - m_h/2; + else if (m_y + m_h/2 < min_y) + m_y = min_y - m_h/2; + + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; +} + + +// +// +// +void AM_initVariables(void) +{ + int pnum; + static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 }; + + automapactive = true; + fb = I_VideoBuffer; + + f_oldloc.x = INT_MAX; + amclock = 0; + lightlev = 0; + + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; + + m_w = FTOM(f_w); + m_h = FTOM(f_h); + + // find player to center on initially + if (playeringame[consoleplayer]) + { + plr = &players[consoleplayer]; + } + else + { + plr = &players[0]; + + for (pnum=0;pnummo->x - m_w/2; + m_y = plr->mo->y - m_h/2; + AM_changeWindowLoc(); + + // for saving & restoring + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + + // inform the status bar of the change + ST_Responder(&st_notify); + +} + +// +// AM_loadPics +// +// haleyjd 08/27/10: [STRIFE] Changed marknums to PLMNUM%d +// +void AM_loadPics(void) +{ + int i; + char namebuf[9]; + + for (i=0;i<10;i++) + { + DEH_snprintf(namebuf, 9, "PLMNUM%d", i); + marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); + } + +} + +void AM_unloadPics(void) +{ + int i; + char namebuf[9]; + + for (i=0;i<10;i++) + { + DEH_snprintf(namebuf, 9, "PLMNUM%d", i); + W_ReleaseLumpName(namebuf); + } +} + +void AM_clearMarks(void) +{ + int i; + + for (i=0;i max_scale_mtof) + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +} + + + + +// +// +// +void AM_Stop (void) +{ + static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 }; + + AM_unloadPics(); + automapactive = false; + ST_Responder(&st_notify); + stopped = true; +} + +// +// +// +void AM_Start (void) +{ + static int lastlevel = -1; + //static int lastepisode = -1; + + if (!stopped) AM_Stop(); + stopped = false; + if (lastlevel != gamemap /*|| lastepisode != gameepisode*/) + { + AM_LevelInit(); + lastlevel = gamemap; + //lastepisode = gameepisode; + } + AM_initVariables(); + AM_loadPics(); +} + +// +// set the window scale to the maximum size +// +void AM_minOutWindowScale(void) +{ + scale_mtof = min_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + +// +// set the window scale to the minimum size +// +void AM_maxOutWindowScale(void) +{ + scale_mtof = max_scale_mtof; + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + AM_activateNewScale(); +} + + +// +// Handle events (user inputs) in automap mode +// +boolean +AM_Responder +( event_t* ev ) +{ + + int rc; + static int bigstate=0; + static int joywait = 0; + static char buffer[20]; + int key; + + rc = false; + + if (ev->type == ev_joystick && joybautomap >= 0 + && (ev->data1 & (1 << joybautomap)) != 0 && joywait < I_GetTime()) + { + joywait = I_GetTime() + 5; + + if (!automapactive) + { + AM_Start (); + viewactive = false; + } + else + { + bigstate = 0; + viewactive = true; + AM_Stop (); + } + + return true; + } + + + if (!automapactive) + { + if (ev->type == ev_keydown && ev->data1 == key_map_toggle) + { + AM_Start (); + viewactive = false; + rc = true; + } + } + else if (ev->type == ev_keydown) + { + rc = true; + key = ev->data1; + + if (key == key_map_east) // pan right + { + if (!followplayer) m_paninc.x = FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_west) // pan left + { + if (!followplayer) m_paninc.x = -FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_north) // pan up + { + if (!followplayer) m_paninc.y = FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_south) // pan down + { + if (!followplayer) m_paninc.y = -FTOM(F_PANINC); + else rc = false; + } + else if (key == key_map_zoomout) // zoom out + { + mtof_zoommul = M_ZOOMOUT; + ftom_zoommul = M_ZOOMIN; + } + else if (key == key_map_zoomin) // zoom in + { + mtof_zoommul = M_ZOOMIN; + ftom_zoommul = M_ZOOMOUT; + } + else if (key == key_map_toggle) + { + bigstate = 0; + viewactive = true; + AM_Stop (); + } + else if (key == key_map_maxzoom) + { + bigstate = !bigstate; + if (bigstate) + { + AM_saveScaleAndLoc(); + AM_minOutWindowScale(); + } + else AM_restoreScaleAndLoc(); + } + else if (key == key_map_follow) + { + followplayer = !followplayer; + f_oldloc.x = INT_MAX; + if (followplayer) + plr->message = DEH_String(AMSTR_FOLLOWON); + else + plr->message = DEH_String(AMSTR_FOLLOWOFF); + } + // haleyjd 20141101: [STRIFE] grid is not supported + /* + else if (key == key_map_grid) + { + grid = !grid; + if (grid) + plr->message = DEH_String(AMSTR_GRIDON); + else + plr->message = DEH_String(AMSTR_GRIDOFF); + } + */ + else if (key == key_map_mark) + { + // haleyjd 20141101: [STRIFE] if full, mark 9 is replaced + if(markpointnum == AM_NUMMARKPOINTS) + --markpointnum; + M_snprintf(buffer, sizeof(buffer), + "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum + 1); // [STRIFE] + plr->message = buffer; + AM_addMark(); + } + else if (key == key_map_clearmark) + { + // haleyjd 20141101: [STRIFE] clears last mark only + if(markpointnum > 0) + { + markpoints[markpointnum - 1].x = -1; + --markpointnum; + plr->message = DEH_String(AMSTR_MARKSCLEARED); + } + } + else + { + rc = false; + } + + if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data2)) + { + rc = false; + cheating = (cheating+1) % 3; + } + } + else if (ev->type == ev_keyup) + { + rc = false; + key = ev->data1; + + if (key == key_map_east) + { + if (!followplayer) m_paninc.x = 0; + } + else if (key == key_map_west) + { + if (!followplayer) m_paninc.x = 0; + } + else if (key == key_map_north) + { + if (!followplayer) m_paninc.y = 0; + } + else if (key == key_map_south) + { + if (!followplayer) m_paninc.y = 0; + } + else if (key == key_map_zoomout || key == key_map_zoomin) + { + mtof_zoommul = FRACUNIT; + ftom_zoommul = FRACUNIT; + } + } + + return rc; + +} + + +// +// Zooming +// +void AM_changeWindowScale(void) +{ + + // Change the scaling multipliers + scale_mtof = FixedMul(scale_mtof, mtof_zoommul); + scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + + if (scale_mtof < min_scale_mtof) + AM_minOutWindowScale(); + else if (scale_mtof > max_scale_mtof) + AM_maxOutWindowScale(); + else + AM_activateNewScale(); +} + + +// +// +// +void AM_doFollowPlayer(void) +{ + + if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) + { + m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; + m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + f_oldloc.x = plr->mo->x; + f_oldloc.y = plr->mo->y; + + // m_x = FTOM(MTOF(plr->mo->x - m_w/2)); + // m_y = FTOM(MTOF(plr->mo->y - m_h/2)); + // m_x = plr->mo->x - m_w/2; + // m_y = plr->mo->y - m_h/2; + + } + +} + +// +// +// +void AM_updateLightLev(void) +{ + static int nexttic = 0; + //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; + static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; + static int litelevelscnt = 0; + + // Change light level + if (amclock>nexttic) + { + lightlev = litelevels[litelevelscnt++]; + if (litelevelscnt == arrlen(litelevels)) litelevelscnt = 0; + nexttic = amclock + 6 - (amclock % 6); + } + +} + + +// +// Updates on Game Tick +// +void AM_Ticker (void) +{ + + if (!automapactive) + return; + + amclock++; + + if (followplayer) + AM_doFollowPlayer(); + + // Change the zoom if necessary + if (ftom_zoommul != FRACUNIT) + AM_changeWindowScale(); + + // Change x,y location + if (m_paninc.x || m_paninc.y) + AM_changeWindowLoc(); + + // Update light level + // AM_updateLightLev(); + +} + + +// +// Clear automap frame buffer. +// +void AM_clearFB(int color) +{ + memset(fb, color, f_w*f_h); +} + + +// +// Automap clipping of lines. +// +// Based on Cohen-Sutherland clipping algorithm but with a slightly +// faster reject and precalculated slopes. If the speed is needed, +// use a hash algorithm to handle the common cases. +// +boolean +AM_clipMline +( mline_t* ml, + fline_t* fl ) +{ + enum + { + LEFT =1, + RIGHT =2, + BOTTOM =4, + TOP =8 + }; + + register int outcode1 = 0; + register int outcode2 = 0; + register int outside; + + fpoint_t tmp; + int dx; + int dy; + + +#define DOOUTCODE(oc, mx, my) \ + (oc) = 0; \ + if ((my) < 0) (oc) |= TOP; \ + else if ((my) >= f_h) (oc) |= BOTTOM; \ + if ((mx) < 0) (oc) |= LEFT; \ + else if ((mx) >= f_w) (oc) |= RIGHT; + + + // do trivial rejects and outcodes + if (ml->a.y > m_y2) + outcode1 = TOP; + else if (ml->a.y < m_y) + outcode1 = BOTTOM; + + if (ml->b.y > m_y2) + outcode2 = TOP; + else if (ml->b.y < m_y) + outcode2 = BOTTOM; + + if (outcode1 & outcode2) + return false; // trivially outside + + if (ml->a.x < m_x) + outcode1 |= LEFT; + else if (ml->a.x > m_x2) + outcode1 |= RIGHT; + + if (ml->b.x < m_x) + outcode2 |= LEFT; + else if (ml->b.x > m_x2) + outcode2 |= RIGHT; + + if (outcode1 & outcode2) + return false; // trivially outside + + // transform to frame-buffer coordinates. + fl->a.x = CXMTOF(ml->a.x); + fl->a.y = CYMTOF(ml->a.y); + fl->b.x = CXMTOF(ml->b.x); + fl->b.y = CYMTOF(ml->b.y); + + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + + if (outcode1 & outcode2) + return false; + + while (outcode1 | outcode2) + { + // may be partially inside box + // find an outside point + if (outcode1) + outside = outcode1; + else + outside = outcode2; + + // clip to each side + if (outside & TOP) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx*(fl->a.y))/dy; + tmp.y = 0; + } + else if (outside & BOTTOM) + { + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy; + tmp.y = f_h-1; + } + else if (outside & RIGHT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx; + tmp.x = f_w-1; + } + else if (outside & LEFT) + { + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy*(-fl->a.x))/dx; + tmp.x = 0; + } + else + { + tmp.x = 0; + tmp.y = 0; + } + + if (outside == outcode1) + { + fl->a = tmp; + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + } + else + { + fl->b = tmp; + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + } + + if (outcode1 & outcode2) + return false; // trivially outside + } + + return true; +} +#undef DOOUTCODE + + +// +// Classic Bresenham w/ whatever optimizations needed for speed +// +void +AM_drawFline +( fline_t* fl, + int color ) +{ + register int x; + register int y; + register int dx; + register int dy; + register int sx; + register int sy; + register int ax; + register int ay; + register int d; + + static int fuck = 0; + + // For debugging only + if ( fl->a.x < 0 || fl->a.x >= f_w + || fl->a.y < 0 || fl->a.y >= f_h + || fl->b.x < 0 || fl->b.x >= f_w + || fl->b.y < 0 || fl->b.y >= f_h) + { + DEH_fprintf(stderr, "fuck %d \r", fuck++); + return; + } + +#define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) + + dx = fl->b.x - fl->a.x; + ax = 2 * (dx<0 ? -dx : dx); + sx = dx<0 ? -1 : 1; + + dy = fl->b.y - fl->a.y; + ay = 2 * (dy<0 ? -dy : dy); + sy = dy<0 ? -1 : 1; + + x = fl->a.x; + y = fl->a.y; + + if (ax > ay) + { + d = ay - ax/2; + while (1) + { + PUTDOT(x,y,color); + if (x == fl->b.x) return; + if (d>=0) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } + else + { + d = ax - ay/2; + while (1) + { + PUTDOT(x, y, color); + if (y == fl->b.y) return; + if (d >= 0) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } +} + + +// +// Clip lines, draw visible part sof lines. +// +void +AM_drawMline +( mline_t* ml, + int color ) +{ + static fline_t fl; + + if (AM_clipMline(ml, &fl)) + AM_drawFline(&fl, color); // draws it on frame buffer using fb coords +} + + + +// +// Draws flat (floor/ceiling tile) aligned grid lines. +// +/*void AM_drawGrid(int color) +{ + fixed_t x, y; + fixed_t start, end; + mline_t ml; + + // Figure out start of vertical gridlines + start = m_x; + if ((start-bmaporgx)%(MAPBLOCKUNITS<v1->x; + l.a.y = line->v1->y; + l.b.x = line->v2->x; + l.b.y = line->v2->y; + + if(cheating || (line->flags & ML_MAPPED)) + { + if((line->flags & LINE_NEVERSEE) && !cheating) + continue; + + // villsa [STRIFE] + if(line->special == 145 || line->special == 186) + { + AM_drawMline(&l, SPWALLCOLORS); + } + // villsa [STRIFE] lightlev is unused here + else if(!line->backsector) + { + AM_drawMline(&l, WALLCOLORS); + } + else + { + if(line->special == 39) + { // teleporters + AM_drawMline(&l, WALLCOLORS+WALLRANGE/2); + } + else if (line->flags & ML_SECRET) // secret door + { + // villsa [STRIFE] just draw the wall as is! + AM_drawMline(&l, WALLCOLORS); + } + else if(line->backsector->floorheight != line->frontsector->floorheight) + { + AM_drawMline(&l, FDWALLCOLORS); // floor level change + } + else if(line->backsector->ceilingheight != line->frontsector->ceilingheight) + { + AM_drawMline(&l, CDWALLCOLORS); // ceiling level change + } + else if (cheating) + { + AM_drawMline(&l, TSWALLCOLORS); + } + } + } + // villsa [STRIFE] show all of the map on map 15 + else if(plr->powers[pw_allmap] || gamemap == 15) + { + if(!(line->flags & LINE_NEVERSEE)) + AM_drawMline(&l, CTWALLCOLORS); + } + } +} + + +// +// Rotation in 2D. +// Used to rotate player arrow line character. +// +void +AM_rotate +( fixed_t* x, + fixed_t* y, + angle_t a ) +{ + fixed_t tmpx; + + tmpx = + FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT]) + - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]); + + *y = + FixedMul(*x,finesine[a>>ANGLETOFINESHIFT]) + + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]); + + *x = tmpx; +} + +void +AM_drawLineCharacter +( mline_t* lineguy, + int lineguylines, + fixed_t scale, + angle_t angle, + int color, + fixed_t x, + fixed_t y ) +{ + int i; + mline_t l; + + for (i=0;imo->angle, + 224, plr->mo->x, plr->mo->y); + return; + } + + for(i = 0; i < MAXPLAYERS; i++) + { + their_color++; + p = &players[i]; + + // villsa [STRIFE] check for gameskill?? + if((gameskill && deathmatch && !singledemo) && p != plr) + continue; + + if(!playeringame[i]) + continue; + + // villsa [STRIFE] change to 27 + if(p->powers[pw_invisibility]) + color = 27; // *close* to black + else + color = their_colors[their_color]; + + AM_drawLineCharacter + (player_arrow, arrlen(player_arrow), 0, p->mo->angle, + color, p->mo->x, p->mo->y); + } + +} + +// +// AM_drawThings +// +// villsa [STRIFE] no arguments +// +void AM_drawThings(void) +{ + int i; + mobj_t* t; + int colors; + fixed_t radius; + + // villsa [STRIFE] almost re-written + // specific things can have different radius, color and appearence + for(i = 0; i < numsectors; i++) + { + t = sectors[i].thinglist; + while(t) + { + radius = t->radius; + + if(t->flags & (MF_MISSILE|MF_SPECIAL)) + { + colors = MISSILECOLORS; + } + else if(t->flags & MF_COUNTKILL) + { + colors = SHOOTABLECOLORS; + } + else + { + colors = THINGCOLORS; + radius = (16<angle, colors, t->x, t->y); + + t = t->snext; + } + } +} + +// +// AM_drawMarks +// +void AM_drawMarks(void) +{ + int i, fx, fy, w, h; + + for(i = 0; i < AM_NUMMARKPOINTS; i++) + { + if(markpoints[i].x != -1) + { + // w = SHORT(marknums[i]->width); + // h = SHORT(marknums[i]->height); + w = 5; // because something's wrong with the wad, i guess + h = 6; // because something's wrong with the wad, i guess + fx = CXMTOF(markpoints[i].x); + fy = CYMTOF(markpoints[i].y); + if(fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) + { + // villsa [STRIFE] + if(i >= mapmarknum) + V_DrawPatch(fx, fy, marknums[i]); + } + } + } + +} + +// villsa [STRIFE] unused +/*void AM_drawCrosshair(int color) +{ + fb[(f_w*(f_h+1))/2] = color; // single point for now +}*/ + +void AM_Drawer (void) +{ + if (!automapactive) return; + + AM_clearFB(BACKGROUND); + + // villsa [STRIFE] not used + /*if(grid) + AM_drawGrid(GRIDCOLORS);*/ + + AM_drawWalls(); + AM_drawPlayers(); + + // villsa [STRIFE] draw things when map powerup is enabled + if(cheating == 2 || plr->powers[pw_allmap] > 1) + AM_drawThings(); + + // villsa [STRIFE] not used + //AM_drawCrosshair(XHAIRCOLORS); + + AM_drawMarks(); + V_MarkRect(f_x, f_y, f_w, f_h); + +} diff --git a/games/NXDoom/src/strife/am_map.h b/games/NXDoom/src/strife/am_map.h new file mode 100644 index 00000000000..572d2389bc2 --- /dev/null +++ b/games/NXDoom/src/strife/am_map.h @@ -0,0 +1,49 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// AutoMap module. +// + +#ifndef __AMMAP_H__ +#define __AMMAP_H__ + +#include "d_event.h" +#include "m_cheat.h" + +// Used by ST StatusBar stuff. +#define AM_MSGHEADER (('a'<<24)+('m'<<16)) +#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) +#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) + + +// Called by main loop. +boolean AM_Responder (event_t* ev); + +// Called by main loop. +void AM_Ticker (void); + +// Called by main loop, +// called instead of view drawer if automap active. +void AM_Drawer (void); + +// Called to force the automap to quit +// if the level is completed while it is up. +void AM_Stop (void); + + +extern cheatseq_t cheat_amap; + + +#endif diff --git a/games/NXDoom/src/strife/d_englsh.h b/games/NXDoom/src/strife/d_englsh.h new file mode 100644 index 00000000000..57312a89f17 --- /dev/null +++ b/games/NXDoom/src/strife/d_englsh.h @@ -0,0 +1,593 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Printed strings for translation. +// English language support (default). +// + +#ifndef __D_ENGLSH__ +#define __D_ENGLSH__ + +// +// Printed strings for translation +// + +// +// D_Main.C +// +#define D_DEVSTR "Development mode ON.\n" +#define D_CDROM "CD-ROM Version: Accessing strife.cd\n" + +// +// M_Menu.C +// +#define PRESSKEY "press a key." +#define PRESSYN "press y or n." +#define QUITMSG "are you sure you want to\nquit this great game?" +// [STRIFE] modified: +#define LOADNET "you can't load while in a net game!\n\n"PRESSKEY +#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY +// [STRIFE] modified: +#define QSAVESPOT "you haven't picked a\nquicksave slot yet!\n\n"PRESSKEY +// [STRIFE] modified: +#define SAVEDEAD "you're not playing a game\n\n"PRESSKEY +#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN +// [STRIFE] modified: +#define QLPROMPT "do you want to quickload\n\n'%s'?\n\n"PRESSYN + +#define NEWGAME \ +"you can't start a new game\n"\ +"while in a network game.\n\n"PRESSKEY + +#define NIGHTMARE \ +"are you sure? this skill level\n"\ +"isn't even remotely fair.\n\n"PRESSYN + +#define SWSTRING \ +"this is the shareware version of doom.\n\n"\ +"you need to order the entire trilogy.\n\n"PRESSKEY + +#define MSGOFF "Messages OFF" +#define MSGON "Messages ON" +#define NETEND "you can't end a netgame!\n\n"PRESSKEY +#define ENDGAME "are you sure you want\nto end the game?\n\n"PRESSYN + +// haleyjd 09/11/10: [STRIFE] No "to dos." on this +#define DOSY "(press y to quit)" + +#define DETAILHI "High detail" +#define DETAILLO "Low detail" +#define GAMMALVL0 "Gamma correction OFF" +#define GAMMALVL1 "Gamma correction level 1" +#define GAMMALVL2 "Gamma correction level 2" +#define GAMMALVL3 "Gamma correction level 3" +#define GAMMALVL4 "Gamma correction level 4" +#define EMPTYSTRING "empty slot" + +// +// P_inter.C +// +#define GOTARMOR "Picked up the armor." +#define GOTMEGA "Picked up the MegaArmor!" +#define GOTHTHBONUS "Picked up a health bonus." +#define GOTARMBONUS "Picked up an armor bonus." +#define GOTSTIM "Picked up a stimpack." +#define GOTMEDINEED "Picked up a medikit that you REALLY need!" +#define GOTMEDIKIT "Picked up a medikit." +#define GOTSUPER "Supercharge!" + +#define GOTBLUECARD "Picked up a blue keycard." +#define GOTYELWCARD "Picked up a yellow keycard." +#define GOTREDCARD "Picked up a red keycard." +#define GOTBLUESKUL "Picked up a blue skull key." +#define GOTYELWSKUL "Picked up a yellow skull key." +#define GOTREDSKULL "Picked up a red skull key." + +#define GOTINVUL "Invulnerability!" +#define GOTBERSERK "Berserk!" +#define GOTINVIS "Partial Invisibility" +#define GOTSUIT "Radiation Shielding Suit" +#define GOTMAP "Computer Area Map" +#define GOTVISOR "Light Amplification Visor" +#define GOTMSPHERE "MegaSphere!" + +#define GOTCLIP "Picked up a clip." +#define GOTCLIPBOX "Picked up a box of bullets." +#define GOTROCKET "Picked up a rocket." +#define GOTROCKBOX "Picked up a box of rockets." +#define GOTCELL "Picked up an energy cell." +#define GOTCELLBOX "Picked up an energy cell pack." +#define GOTSHELLS "Picked up 4 shotgun shells." +#define GOTSHELLBOX "Picked up a box of shotgun shells." +#define GOTBACKPACK "Picked up a backpack full of ammo!" + +#define GOTBFG9000 "You got the BFG9000! Oh, yes." +#define GOTCHAINGUN "You got the chaingun!" +#define GOTCHAINSAW "A chainsaw! Find some meat!" +#define GOTLAUNCHER "You got the rocket launcher!" +#define GOTPLASMA "You got the plasma gun!" +#define GOTSHOTGUN "You got the shotgun!" +#define GOTSHOTGUN2 "You got the super shotgun!" + +// +// P_Doors.C +// +#define PD_BLUEO "You need a blue key to activate this object" +#define PD_REDO "You need a red key to activate this object" +#define PD_YELLOWO "You need a yellow key to activate this object" +#define PD_BLUEK "You need a blue key to open this door" +#define PD_REDK "You need a red key to open this door" +#define PD_YELLOWK "You need a yellow key to open this door" + +// +// G_game.C +// +#define GGSAVED "game saved." + +// +// HU_stuff.C +// +#define HUSTR_MSGU "[Message unsent]" + +// haleyjd 08/31/10: [STRIFE] Strife map names + +#define HUSTR_1 "AREA 1: sanctuary" +#define HUSTR_2 "AREA 2: town" +#define HUSTR_3 "AREA 3: front base" +#define HUSTR_4 "AREA 4: power station" +#define HUSTR_5 "AREA 5: prison" +#define HUSTR_6 "AREA 6: sewers" +#define HUSTR_7 "AREA 7: castle" +#define HUSTR_8 "AREA 8: Audience Chamber" +#define HUSTR_9 "AREA 9: Castle: Programmer's Keep" + +#define HUSTR_10 "AREA 10: New Front Base" +#define HUSTR_11 "AREA 11: Borderlands" +#define HUSTR_12 "AREA 12: the temple of the oracle" +#define HUSTR_13 "AREA 13: Catacombs" +#define HUSTR_14 "AREA 14: mines" +#define HUSTR_15 "AREA 15: Fortress: Administration" +#define HUSTR_16 "AREA 16: Fortress: Bishop's Tower" +#define HUSTR_17 "AREA 17: Fortress: The Bailey" +#define HUSTR_18 "AREA 18: Fortress: Stores" +#define HUSTR_19 "AREA 19: Fortress: Security Complex" + +#define HUSTR_20 "AREA 20: Factory: Receiving" +#define HUSTR_21 "AREA 21: Factory: Manufacturing" +#define HUSTR_22 "AREA 22: Factory: Forge" +#define HUSTR_23 "AREA 23: Order Commons" +#define HUSTR_24 "AREA 24: Factory: Conversion Chapel" +#define HUSTR_25 "AREA 25: Catacombs: Ruined Temple" +#define HUSTR_26 "AREA 26: proving grounds" +#define HUSTR_27 "AREA 27: The Lab" +#define HUSTR_28 "AREA 28: Alien Ship" +#define HUSTR_29 "AREA 29: Entity's Lair" + +#define HUSTR_30 "AREA 30: Abandoned Front Base" +#define HUSTR_31 "AREA 31: Training Facility" + +#define HUSTR_32 "AREA 1: Sanctuary" +#define HUSTR_33 "AREA 2: Town" +#define HUSTR_34 "AREA 3: Movement Base" + +// haleyjd 20110219: [STRIFE] replaced all with Strife chat macros: +#define HUSTR_CHATMACRO1 "Fucker!" +#define HUSTR_CHATMACRO2 "--SPLAT-- Instant wall art." +#define HUSTR_CHATMACRO3 "That had to hurt!" +#define HUSTR_CHATMACRO4 "Smackings!" +#define HUSTR_CHATMACRO5 "Gib-O-Matic baby." +#define HUSTR_CHATMACRO6 "Burn! Yah! Yah!" +#define HUSTR_CHATMACRO7 "Buh-Bye!" +#define HUSTR_CHATMACRO8 "Sizzle chest!" +#define HUSTR_CHATMACRO9 "That sucked!" +#define HUSTR_CHATMACRO0 "Mommy?" + +#define HUSTR_TALKTOSELF1 "You mumble to yourself" +#define HUSTR_TALKTOSELF2 "Who's there?" +#define HUSTR_TALKTOSELF3 "You scare yourself" +#define HUSTR_TALKTOSELF4 "You start to rave" +#define HUSTR_TALKTOSELF5 "You've lost it..." + +#define HUSTR_MESSAGESENT "[Message Sent]" + +// The following should NOT be changed unless it seems +// just AWFULLY necessary + +// [STRIFE]: Not used, as strings are local to hu_stuff.c +//#define HUSTR_PLRGREEN "Green: " +//#define HUSTR_PLRINDIGO "Indigo: " +//#define HUSTR_PLRBROWN "Brown: " +//#define HUSTR_PLRRED "Red: " + +#define HUSTR_KEYGREEN 'g' +#define HUSTR_KEYINDIGO 'i' +#define HUSTR_KEYBROWN 'b' +#define HUSTR_KEYRED 'r' + +// +// AM_map.C +// + +#define AMSTR_FOLLOWON "Follow Mode ON" +#define AMSTR_FOLLOWOFF "Follow Mode OFF" + +#define AMSTR_GRIDON "Grid ON" +#define AMSTR_GRIDOFF "Grid OFF" + +#define AMSTR_MARKEDSPOT "Marked Spot" +#define AMSTR_MARKSCLEARED "Last Mark Cleared" // [STRIFE] + +// +// ST_stuff.C +// + +#define STSTR_MUS "Music Change" +#define STSTR_NOMUS "IMPOSSIBLE SELECTION" +#define STSTR_DQDON "You're Invincible!" // [STRIFE] +#define STSTR_DQDOFF "You're a looney!" // [STRIFE] + +#define STSTR_KFAADDED "Very Happy Ammo Added" +#define STSTR_FAADDED "Ammo Added" // [STRIFE] + +#define STSTR_NCON "No Clipping Mode ON" +#define STSTR_NCOFF "No Clipping Mode OFF" + +#define STSTR_BEHOLD "Bzrk, Inviso, Mask, Health, Pack, Stats" // [STRIFE] +#define STSTR_BEHOLDX "Power-up Toggled" + +#define STSTR_CHOPPERS "... doesn't suck - GM" +#define STSTR_CLEV "Changing Level..." + +// +// F_Finale.C +// +#define E1TEXT \ +"Once you beat the big badasses and\n"\ +"clean out the moon base you're supposed\n"\ +"to win, aren't you? Aren't you? Where's\n"\ +"your fat reward and ticket home? What\n"\ +"the hell is this? It's not supposed to\n"\ +"end this way!\n"\ +"\n" \ +"It stinks like rotten meat, but looks\n"\ +"like the lost Deimos base. Looks like\n"\ +"you're stuck on The Shores of Hell.\n"\ +"The only way out is through.\n"\ +"\n"\ +"To continue the DOOM experience, play\n"\ +"The Shores of Hell and its amazing\n"\ +"sequel, Inferno!\n" + + +#define E2TEXT \ +"You've done it! The hideous cyber-\n"\ +"demon lord that ruled the lost Deimos\n"\ +"moon base has been slain and you\n"\ +"are triumphant! But ... where are\n"\ +"you? You clamber to the edge of the\n"\ +"moon and look down to see the awful\n"\ +"truth.\n" \ +"\n"\ +"Deimos floats above Hell itself!\n"\ +"You've never heard of anyone escaping\n"\ +"from Hell, but you'll make the bastards\n"\ +"sorry they ever heard of you! Quickly,\n"\ +"you rappel down to the surface of\n"\ +"Hell.\n"\ +"\n" \ +"Now, it's on to the final chapter of\n"\ +"DOOM! -- Inferno." + + +#define E3TEXT \ +"The loathsome spiderdemon that\n"\ +"masterminded the invasion of the moon\n"\ +"bases and caused so much death has had\n"\ +"its ass kicked for all time.\n"\ +"\n"\ +"A hidden doorway opens and you enter.\n"\ +"You've proven too tough for Hell to\n"\ +"contain, and now Hell at last plays\n"\ +"fair -- for you emerge from the door\n"\ +"to see the green fields of Earth!\n"\ +"Home at last.\n" \ +"\n"\ +"You wonder what's been happening on\n"\ +"Earth while you were battling evil\n"\ +"unleashed. It's good that no Hell-\n"\ +"spawn could have come through that\n"\ +"door with you ..." + + +#define E4TEXT \ +"the spider mastermind must have sent forth\n"\ +"its legions of hellspawn before your\n"\ +"final confrontation with that terrible\n"\ +"beast from hell. but you stepped forward\n"\ +"and brought forth eternal damnation and\n"\ +"suffering upon the horde as a true hero\n"\ +"would in the face of something so evil.\n"\ +"\n"\ +"besides, someone was gonna pay for what\n"\ +"happened to daisy, your pet rabbit.\n"\ +"\n"\ +"but now, you see spread before you more\n"\ +"potential pain and gibbitude as a nation\n"\ +"of demons run amok among our cities.\n"\ +"\n"\ +"next stop, hell on earth!" + + +// after level 6, put this: + +#define C1TEXT \ +"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ +"STARPORT. BUT SOMETHING IS WRONG. THE\n" \ +"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ +"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ +"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ +"\n"\ +"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ +"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ +"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ +"OF THE STARBASE AND FIND THE CONTROLLING\n" \ +"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ +"HOSTAGE." + +// After level 11, put this: + +#define C2TEXT \ +"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ +"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\ +"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\ +"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\ +"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\ +"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\ +"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\ +"THAT YOU HAVE SAVED YOUR SPECIES.\n"\ +"\n"\ +"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\ +"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\ +"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\ +"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\ +"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\ +"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\ +"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\ +"UP AND RETURN TO THE FRAY." + + +// After level 20, put this: + +#define C3TEXT \ +"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\ +"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\ +"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\ +"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\ +"TEETH AND PLUNGE THROUGH IT.\n"\ +"\n"\ +"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\ +"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\ +"GOT TO GO THROUGH HELL TO GET TO IT?" + + +// After level 29, put this: + +#define C4TEXT \ +"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\ +"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\ +"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\ +"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\ +"UP AND DIES, ITS THRASHING LIMBS\n"\ +"DEVASTATING UNTOLD MILES OF HELL'S\n"\ +"SURFACE.\n"\ +"\n"\ +"YOU'VE DONE IT. THE INVASION IS OVER.\n"\ +"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\ +"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\ +"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\ +"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\ +"HOME. REBUILDING EARTH OUGHT TO BE A\n"\ +"LOT MORE FUN THAN RUINING IT WAS.\n" + + + +// Before level 31, put this: + +#define C5TEXT \ +"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\ +"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\ +"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\ +"WHO THE INMATES OF THIS CORNER OF HELL\n"\ +"WILL BE." + + +// Before level 32, put this: + +#define C6TEXT \ +"CONGRATULATIONS, YOU'VE FOUND THE\n"\ +"SUPER SECRET LEVEL! YOU'D BETTER\n"\ +"BLAZE THROUGH THIS ONE!\n" + + +// after map 06 + +#define P1TEXT \ +"You gloat over the steaming carcass of the\n"\ +"Guardian. With its death, you've wrested\n"\ +"the Accelerator from the stinking claws\n"\ +"of Hell. You relax and glance around the\n"\ +"room. Damn! There was supposed to be at\n"\ +"least one working prototype, but you can't\n"\ +"see it. The demons must have taken it.\n"\ +"\n"\ +"You must find the prototype, or all your\n"\ +"struggles will have been wasted. Keep\n"\ +"moving, keep fighting, keep killing.\n"\ +"Oh yes, keep living, too." + + +// after map 11 + +#define P2TEXT \ +"Even the deadly Arch-Vile labyrinth could\n"\ +"not stop you, and you've gotten to the\n"\ +"prototype Accelerator which is soon\n"\ +"efficiently and permanently deactivated.\n"\ +"\n"\ +"You're good at that kind of thing." + + +// after map 20 + +#define P3TEXT \ +"You've bashed and battered your way into\n"\ +"the heart of the devil-hive. Time for a\n"\ +"Search-and-Destroy mission, aimed at the\n"\ +"Gatekeeper, whose foul offspring is\n"\ +"cascading to Earth. Yeah, he's bad. But\n"\ +"you know who's worse!\n"\ +"\n"\ +"Grinning evilly, you check your gear, and\n"\ +"get ready to give the bastard a little Hell\n"\ +"of your own making!" + +// after map 30 + +#define P4TEXT \ +"The Gatekeeper's evil face is splattered\n"\ +"all over the place. As its tattered corpse\n"\ +"collapses, an inverted Gate forms and\n"\ +"sucks down the shards of the last\n"\ +"prototype Accelerator, not to mention the\n"\ +"few remaining demons. You're done. Hell\n"\ +"has gone back to pounding bad dead folks \n"\ +"instead of good live ones. Remember to\n"\ +"tell your grandkids to put a rocket\n"\ +"launcher in your coffin. If you go to Hell\n"\ +"when you die, you'll need it for some\n"\ +"final cleaning-up ..." + +// before map 31 + +#define P5TEXT \ +"You've found the second-hardest level we\n"\ +"got. Hope you have a saved game a level or\n"\ +"two previous. If not, be prepared to die\n"\ +"aplenty. For master marines only." + +// before map 32 + +#define P6TEXT \ +"Betcha wondered just what WAS the hardest\n"\ +"level we had ready for ya? Now you know.\n"\ +"No one gets out alive." + + +#define T1TEXT \ +"You've fought your way out of the infested\n"\ +"experimental labs. It seems that UAC has\n"\ +"once again gulped it down. With their\n"\ +"high turnover, it must be hard for poor\n"\ +"old UAC to buy corporate health insurance\n"\ +"nowadays..\n"\ +"\n"\ +"Ahead lies the military complex, now\n"\ +"swarming with diseased horrors hot to get\n"\ +"their teeth into you. With luck, the\n"\ +"complex still has some warlike ordnance\n"\ +"laying around." + + +#define T2TEXT \ +"You hear the grinding of heavy machinery\n"\ +"ahead. You sure hope they're not stamping\n"\ +"out new hellspawn, but you're ready to\n"\ +"ream out a whole herd if you have to.\n"\ +"They might be planning a blood feast, but\n"\ +"you feel about as mean as two thousand\n"\ +"maniacs packed into one mad killer.\n"\ +"\n"\ +"You don't plan to go down easy." + + +#define T3TEXT \ +"The vista opening ahead looks real damn\n"\ +"familiar. Smells familiar, too -- like\n"\ +"fried excrement. You didn't like this\n"\ +"place before, and you sure as hell ain't\n"\ +"planning to like it now. The more you\n"\ +"brood on it, the madder you get.\n"\ +"Hefting your gun, an evil grin trickles\n"\ +"onto your face. Time to take some names." + +#define T4TEXT \ +"Suddenly, all is silent, from one horizon\n"\ +"to the other. The agonizing echo of Hell\n"\ +"fades away, the nightmare sky turns to\n"\ +"blue, the heaps of monster corpses start \n"\ +"to evaporate along with the evil stench \n"\ +"that filled the air. Jeeze, maybe you've\n"\ +"done it. Have you really won?\n"\ +"\n"\ +"Something rumbles in the distance.\n"\ +"A blue light begins to glow inside the\n"\ +"ruined skull of the demon-spitter." + + +#define T5TEXT \ +"What now? Looks totally different. Kind\n"\ +"of like King Tut's condo. Well,\n"\ +"whatever's here can't be any worse\n"\ +"than usual. Can it? Or maybe it's best\n"\ +"to let sleeping gods lie.." + + +#define T6TEXT \ +"Time for a vacation. You've burst the\n"\ +"bowels of hell and by golly you're ready\n"\ +"for a break. You mutter to yourself,\n"\ +"Maybe someone else can kick Hell's ass\n"\ +"next time around. Ahead lies a quiet town,\n"\ +"with peaceful flowing water, quaint\n"\ +"buildings, and presumably no Hellspawn.\n"\ +"\n"\ +"As you step off the transport, you hear\n"\ +"the stomp of a cyberdemon's iron shoe." + + + +// +// Character cast strings F_FINALE.C +// +#define CC_ZOMBIE "ZOMBIEMAN" +#define CC_SHOTGUN "SHOTGUN GUY" +#define CC_HEAVY "HEAVY WEAPON DUDE" +#define CC_IMP "IMP" +#define CC_DEMON "DEMON" +#define CC_LOST "LOST SOUL" +#define CC_CACO "CACODEMON" +#define CC_HELL "HELL KNIGHT" +#define CC_BARON "BARON OF HELL" +#define CC_ARACH "ARACHNOTRON" +#define CC_PAIN "PAIN ELEMENTAL" +#define CC_REVEN "REVENANT" +#define CC_MANCU "MANCUBUS" +#define CC_ARCH "ARCH-VILE" +#define CC_SPIDER "THE SPIDER MASTERMIND" +#define CC_CYBER "THE CYBERDEMON" +#define CC_HERO "OUR HERO" + + +#endif diff --git a/games/NXDoom/src/strife/d_items.c b/games/NXDoom/src/strife/d_items.c new file mode 100644 index 00000000000..a57ed61ea84 --- /dev/null +++ b/games/NXDoom/src/strife/d_items.c @@ -0,0 +1,159 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// + + +// We are referring to sprite numbers. +#include "info.h" + +#include "d_items.h" + + +// +// PSPRITE ACTIONS for waepons. +// This struct controls the weapon animations. +// +// Each entry is: +// ammo/amunition type +// upstate +// downstate +// readystate +// atkstate, i.e. attack/fire/hit frame +// flashstate, muzzle flash +// + +// villsa [STRIFE] +weaponinfo_t weaponinfo[NUMWEAPONS] = +{ + { + // fist + am_noammo, + S_PNCH_03, + S_PNCH_02, + S_PNCH_01, + S_PNCH_04, + S_NULL, + 1 + }, + { + // electric bow + am_elecbolts, + S_XBOW_02, + S_XBOW_01, + S_XBOW_00, + S_XBOW_03, + S_NULL, + 1 + }, + { + // rifle + am_bullets, + S_RIFG_02, + S_RIFG_01, + S_RIFG_00, + S_RIFF_00, + S_NULL, + 1 + }, + { + // missile launcher + am_missiles, + S_MMIS_02, + S_MMIS_01, + S_MMIS_00, + S_MMIS_03, + S_NULL, + 0 + }, + { + // grenade launcher + am_hegrenades, + S_GREN_02, + S_GREN_01, + S_GREN_00, + S_GREN_03, + S_GREF_00, + 0 + }, + { + // flame thrower + am_cell, + S_FLMT_03, + S_FLMT_02, + S_FLMT_00, + S_FLMF_00, + S_NULL, + 1 + }, + { + // mauler + am_cell, + S_BLST_05, + S_BLST_04, + S_BLST_00, + S_BLSF_00, + S_NULL, + 0 + }, + { + // sigil + am_noammo, + S_SIGH_06, + S_SIGH_05, + S_SIGH_00, + S_SIGH_07, + S_SIGF_00, + 0 + }, + { + // poison bow + am_poisonbolts, + S_XBOW_15, + S_XBOW_14, + S_XBOW_13, + S_XBOW_16, + S_NULL, + 1 + }, + { + // wp grenade launcher + am_wpgrenades, + S_GREN_10, + S_GREN_09, + S_GREN_08, + S_GREN_11, + S_GREF_03, + 0 + }, + { + // torpedo + am_cell, + S_BLST_18, + S_BLST_17, + S_BLST_13, + S_BLST_19, + S_NULL, + 0 + }, +}; + + + + + + + + diff --git a/games/NXDoom/src/strife/d_items.h b/games/NXDoom/src/strife/d_items.h new file mode 100644 index 00000000000..eb4d725f29c --- /dev/null +++ b/games/NXDoom/src/strife/d_items.h @@ -0,0 +1,42 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Items: key cards, artifacts, weapon, ammunition. +// + + +#ifndef __D_ITEMS__ +#define __D_ITEMS__ + +#include "doomdef.h" + + + +// Weapon info: sprite frames, ammunition use. +typedef struct +{ + ammotype_t ammo; + int upstate; + int downstate; + int readystate; + int atkstate; + int flashstate; + boolean availabledemo; // villsa [STRIFE] + +} weaponinfo_t; + +extern weaponinfo_t weaponinfo[NUMWEAPONS]; + +#endif diff --git a/games/NXDoom/src/strife/d_main.c b/games/NXDoom/src/strife/d_main.c new file mode 100644 index 00000000000..56372b53803 --- /dev/null +++ b/games/NXDoom/src/strife/d_main.c @@ -0,0 +1,2191 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM main program (D_DoomMain) and game loop (D_DoomLoop), +// plus functions to determine game mode (shareware, registered), +// parse command line parameters, configure game parameters (turbo), +// and call the startup functions. +// + + +#include +#include +#include +#include + +#include "config.h" +#include "deh_main.h" +#include "doomdef.h" +#include "doomstat.h" + +#include "dstrings.h" +#include "sounds.h" + +#include "txt_main.h" +#include "txt_io.h" + +#include "d_iwad.h" + +#include "z_zone.h" +#include "w_main.h" +#include "w_wad.h" +#include "s_sound.h" +#include "v_diskicon.h" +#include "v_video.h" + +#include "f_finale.h" +#include "f_wipe.h" + +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_menu.h" +#include "m_saves.h" // haleyjd [STRIFE] +#include "p_saveg.h" +#include "p_dialog.h" // haleyjd [STRIFE] + +#include "i_endoom.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "i_swap.h" + +#include "g_game.h" + +#include "hu_stuff.h" +#include "wi_stuff.h" +#include "st_stuff.h" +#include "am_map.h" +#include "net_client.h" +#include "net_dedicated.h" +#include "net_query.h" + +#include "p_setup.h" +#include "r_local.h" + +#include "d_main.h" + +#include "strife_icon.c" + +// +// D-DoomLoop() +// Not a globally visible function, +// just included for source reference, +// called by D_DoomMain, never exits. +// Manages timing and IO, +// calls all ?_Responder, ?_Ticker, and ?_Drawer, +// calls I_GetTime, I_StartFrame, and I_StartTic +// +void D_DoomLoop (void); + +static boolean D_AddFile(char *filename); + +// Location where savegames are stored + +char * savegamedir; + +// location of IWAD and WAD files + +char * iwadfile; + + +boolean devparm; // started game with -devparm +boolean nomonsters; // checkparm of -nomonsters +boolean respawnparm; // checkparm of -respawn +boolean fastparm; // checkparm of -fast +boolean flipparm; // [STRIFE] haleyjd 20110629: checkparm of -flip +boolean randomparm; // [STRIFE] haleyjd 20130915: checkparm of -random + +boolean showintro = true; // [STRIFE] checkparm of -nograph, disables intro + + +skill_t startskill; +int startepisode; +int startmap; +boolean autostart; +int startloadgame; + +boolean advancedemo; + +// villsa [STRIFE] workparm variable (similar to devparm?) +boolean workparm = false; + +// villsa [STRIFE] stonecold cheat variable +boolean stonecold = false; + +// haleyjd 09/11/10: [STRIFE] Game type variables +boolean isregistered; +boolean isdemoversion; + +// Store demo, do not accept any inputs +// haleyjd [STRIFE] Unused. +//boolean storedemo; + + +int show_endoom = 1; +int show_diskicon = 1; +int graphical_startup = 1; +static boolean using_text_startup; + +// If true, startup has completed and the main game loop has started. + +static boolean main_loop_started = false; + +// fraggle 06/03/11 [STRIFE]: Unused config variable, preserved +// for compatibility: + +static int comport = 0; + +// fraggle 06/03/11 [STRIFE]: Multiplayer nickname? +char *nickname = NULL; + +void D_ConnectNetGame(void); +void D_CheckNetGame(void); + + +// +// D_ProcessEvents +// Send all the events of the given timestamp down the responder chain +// +void D_ProcessEvents (void) +{ + event_t* ev; + + // haleyjd 08/22/2010: [STRIFE] there is no such thing as a "store demo" + // version of Strife + + // IF STORE DEMO, DO NOT ACCEPT INPUT + //if (storedemo) + // return; + + while ((ev = D_PopEvent()) != NULL) + { + if (M_Responder (ev)) + continue; // menu ate the event + G_Responder (ev); + } +} + + + + +// +// D_Display +// draw current display, possibly wiping it from the previous +// +// wipegamestate can be set to -1 to force a wipe on the next draw +// +// haleyjd 08/23/10: [STRIFE]: +// * Changes to eliminate intermission and change timing of screenwipe +// * 20100901: Added ST_DrawExternal and popupactivestate static variable +// * 20110206: Start wipegamestate at GS_UNKNOWN (STRIFE-TODO: rename?) +// +gamestate_t wipegamestate = GS_UNKNOWN; + +void D_Display (void) +{ + static boolean viewactivestate = false; + static boolean menuactivestate = false; + static boolean inhelpscreensstate = false; + static boolean popupactivestate = false; // [STRIFE] + static boolean fullscreen = false; + static gamestate_t oldgamestate = -1; + static int borderdrawcount; + int nowtime; + int tics; + int wipestart; + int y; + boolean done; + boolean wipe; + boolean redrawsbar; + + if (nodrawers) + return; // for comparative timing / profiling + + redrawsbar = false; + + // change the view size if needed + if (setsizeneeded) + { + R_ExecuteSetViewSize (); + oldgamestate = -1; // force background redraw + borderdrawcount = 3; + } + + // save the current screen if about to wipe + if (gamestate != wipegamestate) + { + wipe = true; + wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + } + else + wipe = false; + + if (gamestate == GS_LEVEL && gametic) + HU_Erase(); + + // do buffered drawing + switch (gamestate) + { + case GS_LEVEL: + if (!gametic) + break; + if (automapactive) + AM_Drawer (); + if (wipe || (viewheight != 200 && fullscreen) ) + redrawsbar = true; + // haleyjd 08/29/10: [STRIFE] Always redraw sbar if menu is/was active + if (menuactivestate || (inhelpscreensstate && !inhelpscreens)) + redrawsbar = true; // just put away the help screen + ST_Drawer (viewheight == 200, redrawsbar ); + fullscreen = viewheight == 200; + break; + + // haleyjd 08/23/2010: [STRIFE] No intermission + /* + case GS_INTERMISSION: + WI_Drawer (); + break; + */ + + case GS_FINALE: + F_Drawer (); + break; + + case GS_DEMOSCREEN: + D_PageDrawer (); + break; + + default: + break; + } + + // draw buffered stuff to screen + I_UpdateNoBlit (); + + // draw the view directly + if (gamestate == GS_LEVEL && !automapactive && gametic) + R_RenderPlayerView (&players[displayplayer]); + + // clean up border stuff + if (gamestate != oldgamestate && gamestate != GS_LEVEL) + I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); + + // see if the border needs to be initially drawn + if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) + { + viewactivestate = false; // view was not active + R_FillBackScreen (); // draw the pattern into the back screen + } + + // see if the border needs to be updated to the screen + if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320) + { + if (menuactive || menuactivestate || !viewactivestate) + { + borderdrawcount = 3; + popupactivestate = false; + } + if (borderdrawcount) + { + R_DrawViewBorder (); // erase old menu stuff + borderdrawcount--; + } + + } + + if (testcontrols) + { + // Box showing current mouse speed + + V_DrawMouseSpeedBox(testcontrols_mousespeed); + } + + menuactivestate = menuactive; + viewactivestate = viewactive; + inhelpscreensstate = inhelpscreens; + oldgamestate = wipegamestate = gamestate; + + // haleyjd 20120208: [STRIFE] Rogue moved this down to below border drawing + if (gamestate == GS_LEVEL && gametic) + { + HU_Drawer (); + if(ST_DrawExternal()) + popupactivestate = true; + else if(popupactivestate) + { + popupactivestate = false; + menuactivestate = 1; + } + } + + // draw pause pic + if (paused) + { + if (automapactive) + y = 4; + else + y = viewwindowy+4; + V_DrawPatchDirect(viewwindowx + (scaledviewwidth - 68) / 2, y, + W_CacheLumpName (DEH_String("M_PAUSE"), PU_CACHE)); + } + + + // menus go directly to the screen + M_Drawer (); // menu is drawn even on top of everything + NetUpdate (); // send out any new accumulation + + + // normal update + if (!wipe) + { + I_FinishUpdate (); // page flip or blit buffer + return; + } + + // wipe update + wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + + wipestart = I_GetTime () - 1; + + do + { + do + { + nowtime = I_GetTime (); + tics = nowtime - wipestart; + I_Sleep(1); + } while (tics < 3); // haleyjd 08/23/2010: [STRIFE] Changed from == 0 to < 3 + + // haleyjd 08/26/10: [STRIFE] Changed to use ColorXForm wipe. + wipestart = nowtime; + done = wipe_ScreenWipe(wipe_ColorXForm + , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); + I_UpdateNoBlit (); + M_Drawer (); // menu is drawn even on top of wipes + I_FinishUpdate (); // page flip or blit buffer + } while (!done); +} + +// +// Add configuration file variable bindings. +// + + +static const char * const chat_macro_defaults[10] = +{ + HUSTR_CHATMACRO0, + HUSTR_CHATMACRO1, + HUSTR_CHATMACRO2, + HUSTR_CHATMACRO3, + HUSTR_CHATMACRO4, + HUSTR_CHATMACRO5, + HUSTR_CHATMACRO6, + HUSTR_CHATMACRO7, + HUSTR_CHATMACRO8, + HUSTR_CHATMACRO9 +}; + + +void D_BindVariables(void) +{ + int i; + + M_ApplyPlatformDefaults(); + + I_BindInputVariables(); + I_BindVideoVariables(); + I_BindJoystickVariables(); + I_BindSoundVariables(); + + M_BindBaseControls(); + M_BindWeaponControls(); + M_BindMapControls(); + M_BindMenuControls(); + M_BindStrifeControls(); // haleyjd 09/01/10: [STRIFE] + M_BindChatControls(MAXPLAYERS); + + // haleyjd 20130915: Strife chat keys + key_multi_msgplayer[0] = '1'; + key_multi_msgplayer[1] = '2'; + key_multi_msgplayer[2] = '3'; + key_multi_msgplayer[3] = '4'; + key_multi_msgplayer[4] = '5'; + key_multi_msgplayer[5] = '6'; + key_multi_msgplayer[6] = '7'; + key_multi_msgplayer[7] = '8'; + + NET_BindVariables(); + + // haleyjd 08/29/10: [STRIFE] + // * Added voice volume + // * Added back flat + // * Removed show_messages + // * Added show_talk + // fraggle 03/06/10: [STRIFE] + // * Removed detailLevel + // * screenblocks -> screensize + // * Added nickname, comport + + M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); + M_BindIntVariable("sfx_volume", &sfxVolume); + M_BindIntVariable("music_volume", &musicVolume); + M_BindIntVariable("voice_volume", &voiceVolume); + M_BindIntVariable("show_talk", &dialogshowtext); + M_BindIntVariable("screensize", &screenblocks); + M_BindIntVariable("snd_channels", &snd_channels); + M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); + M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); + M_BindIntVariable("show_endoom", &show_endoom); + M_BindIntVariable("show_diskicon", &show_diskicon); + M_BindIntVariable("graphical_startup", &graphical_startup); + + M_BindStringVariable("back_flat", &back_flat); + M_BindStringVariable("nickname", &nickname); + + M_BindIntVariable("comport", &comport); + + // Multiplayer chat macros + + for (i=0; i<10; ++i) + { + char buf[12]; + + chat_macros[i] = M_StringDuplicate(chat_macro_defaults[i]); + M_snprintf(buf, sizeof(buf), "chatmacro%i", i); + M_BindStringVariable(buf, &chat_macros[i]); + } +} + +// +// D_GrabMouseCallback +// +// Called to determine whether to grab the mouse pointer +// + +boolean D_GrabMouseCallback(void) +{ + // Drone players don't need mouse focus + + if (drone) + return false; + + // when menu is active or game is paused, release the mouse. + + if (menuactive || paused) + return false; + + // only grab mouse when playing levels (but not demos) + + return (gamestate == GS_LEVEL) && !demoplayback; +} + +// During startup, never grab the mouse. + +static boolean D_StartupGrabCallback(void) +{ + return false; +} + +// +// D_DoomLoop +// +// haleyjd 08/23/10: [STRIFE] Verified unmodified. +// +void D_DoomLoop (void) +{ + if (demorecording) + G_BeginRecording (); + + main_loop_started = true; + + TryRunTics(); + + if (!showintro) + { + I_RegisterWindowIcon(strife_icon_data, strife_icon_w, strife_icon_h); + I_InitGraphics(); + } + + if (show_diskicon) + { + V_EnableLoadingDisk("STDISK", SCREENWIDTH - LOADING_DISK_W, 3); + } + I_SetGrabMouseCallback(D_GrabMouseCallback); + + V_RestoreBuffer(); + R_ExecuteSetViewSize(); + + D_StartGameLoop(); + + if (testcontrols) + { + wipegamestate = gamestate; + } + + while (1) + { + // frame syncronous IO operations + I_StartFrame (); + + // process one or more tics + TryRunTics (); // will run at least one tic + + S_UpdateSounds (players[consoleplayer].mo);// move positional sounds + + // Update display, next frame, with current state. + if (screenvisible) + D_Display (); + } +} + + + +// +// DEMO LOOP +// +int demosequence; +int pagetic; +const char *pagename; + + +// +// D_PageTicker +// Handles timing for warped projection +// +// haleyjd 08/22/2010: [STRIFE] verified unmodified +// +void D_PageTicker (void) +{ + if (--pagetic < 0) + D_AdvanceDemo (); +} + + + +// +// D_PageDrawer +// +// haleyjd 08/22/2010: [STRIFE] verified unmodified +// +void D_PageDrawer (void) +{ + V_DrawPatch (0, 0, W_CacheLumpName(pagename, PU_CACHE)); +} + + +// +// D_AdvanceDemo +// Called after each demo or intro demosequence finishes +// +// haleyjd 08/22/2010: [STRIFE] verified unmodified +// +void D_AdvanceDemo (void) +{ + advancedemo = true; +} + + +// +// This cycles through the demo sequences. +// FIXME - version dependend demo numbers? +// +// [STRIFE] Modified for the opening slideshow and the exit screen +// +void D_DoAdvanceDemo (void) +{ + players[consoleplayer].playerstate = PST_LIVE; // not reborn + advancedemo = false; + usergame = false; // no save / end game here + paused = false; + gameaction = ga_nothing; + + // villsa 09/12/10: [STRIFE] converted pagetics to ticrate + switch (demosequence) + { + case -5: // exit the game + I_Quit(); + return; + case -4: // show exit screen + menuactive = false; + pagetic = 3*TICRATE; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("PANEL7"); + S_StartMusic(mus_fast); + if(isdemoversion) + demosequence = -3; // show Velocity logo + else + demosequence = -5; // exit + return; + case -3: // show Velocity logo for demo version + pagetic = 6*TICRATE; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("vellogo"); + demosequence = -5; // exit + return; + case -2: // title screen + pagetic = 6*TICRATE; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("TITLEPIC"); + S_StartMusic(mus_logo); + demosequence = -1; // start intro cinematic + return; + case -1: // start of intro cinematic + pagetic = 10; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("PANEL0"); + S_StartSound(NULL, sfx_rb2act); + wipegamestate = -1; + break; + case 0: // Rogue logo + pagetic = 4*TICRATE; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("RGELOGO"); + wipegamestate = -1; + break; + case 1: + pagetic = 7*TICRATE; // The comet struck our planet without + gamestate = GS_DEMOSCREEN; // warning.We lost our paradise in a + pagename = DEH_String("PANEL1"); // single, violent stroke. + I_StartVoice(DEH_String("pro1")); + S_StartMusic(mus_intro); + break; + case 2: + pagetic = 9*TICRATE; // The impact released a virus which + gamestate = GS_DEMOSCREEN; // swept through the land and killed + pagename = DEH_String("PANEL2"); // millions. They turned out to be + I_StartVoice(DEH_String("pro2")); // the lucky ones... + break; + case 3: + pagetic = 12*TICRATE; // For those that did not die became + gamestate = GS_DEMOSCREEN; // mutations of humanity. Some became + pagename = DEH_String("PANEL3"); // fanatics who heard the voice of a + I_StartVoice(DEH_String("pro3")); // malignant God in their heads, and + break; // called themselves the Order. + case 4: + pagetic = 11*TICRATE; // Those of us who were deaf to this + pagename = DEH_String("PANEL4"); // voice suffer horribly and are + gamestate = GS_DEMOSCREEN; // forced to serve these ruthless + I_StartVoice(DEH_String("pro4")); // psychotics, who wield weapons more + break; // powerful than anything we can muster. + case 5: + pagetic = 10*TICRATE; // They destroy our women and children, + gamestate = GS_DEMOSCREEN; // so that we must hide them underground, + pagename = DEH_String("PANEL5"); // and live like animals in constant + I_StartVoice(DEH_String("pro5")); // fear for our lives. + break; + case 6: // But there are whispers of discontent. + pagetic = 16*TICRATE; // If we organize, can we defeat our + gamestate = GS_DEMOSCREEN; // masters? Weapons are being stolen, + pagename = DEH_String("PANEL6"); // soldiers are being trained. A + I_StartVoice(DEH_String("pro6")); // Movement is born! Born of lifelong + break; // STRIFE! + case 7: // titlepic again - unused... + pagetic = 9*TICRATE; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("TITLEPIC"); + wipegamestate = -1; + break; + case 8: // demo + ClearTmp(); + pagetic = 9*TICRATE; + G_DeferedPlayDemo(DEH_String("demo1")); + break; + case 9: // velocity logo? - unused... + pagetic = 6*TICRATE; + gamestate = GS_DEMOSCREEN; + pagename = DEH_String("vellogo"); + wipegamestate = -1; + break; + case 10: // credits + gamestate = GS_DEMOSCREEN; + pagetic = 12*TICRATE; + pagename = DEH_String("CREDIT"); + wipegamestate = -1; + break; + default: + break; + } + + ++demosequence; + + if(demosequence > 11) + demosequence = -2; + if(demosequence == 7 || demosequence == 9) + ++demosequence; +} + + + +// +// D_StartTitle +// +// [STRIFE] +// haleyjd 09/11/10: Small modifications for new demo sequence. +// +void D_StartTitle (void) +{ + gamestate = GS_DEMOSCREEN; + gameaction = ga_nothing; + demosequence = -2; + D_AdvanceDemo (); +} + +// +// D_QuitGame +// +// [STRIFE] New function +// haleyjd 09/11/10: Sets up the quit game snippet powered by the +// demo sequence. +// +void D_QuitGame(void) +{ + gameaction = ga_nothing; + demosequence = -4; + D_AdvanceDemo(); +} + +// Strings for dehacked replacements of the startup banner +// +// These are from the original source: some of them are perhaps +// not used in any dehacked patches + +static const char *banners[] = +{ + // strife1.wad: + + " " + "STRIFE: Quest for the Sigil v1.2" + " " +}; + +// +// Get game name: if the startup banner has been replaced, use that. +// Otherwise, use the name given +// + +static char *GetGameName(char *gamename) +{ + size_t i; + const char *deh_sub; + + for (i=0; i 1996 || date.day > 15 && date.month > 4) + I_Error("Data error! Corrupted WAD File!"); + serial_year = serialnum / 10000; + serial_month = serialnum / 100 - 100 * serial_year; + if(date.year < serial_year || + date.day < serialnum - 100 * serial_month - 10000 * serial_year && + date.month < serial_month) + I_Error("Bad wadfile"); +} +#endif + +// Set the gamedescription string + +void D_SetGameDescription(void) +{ + gamedescription = GetGameName("Strife: Quest for the Sigil"); +} + +// print title for every printed line +static char title[128] = ""; + +static void InitTitleString(void) +{ + switch (gameversion) + { + case exe_strife_1_2: + DEH_snprintf(title, sizeof(title), " " + "STRIFE: Quest for the Sigil v1.2" + " " + ); + break; + case exe_strife_1_31: + default: + DEH_snprintf(title, sizeof(title), " " + "STRIFE: Quest for the Sigil v1.31" + " " + ); + break; + } +} + +static boolean D_AddFile(char *filename) +{ + wad_file_t *handle; + + printf(" adding %s\n", filename); + handle = W_AddFile(filename); + + return handle != NULL; +} + +// Copyright message banners +// Some dehacked mods replace these. These are only displayed if they are +// replaced by dehacked. +// haleyjd 08/22/2010: [STRIFE] altered to match strings from binary +static const char *copyright_banners[] = +{ + "===========================================================================\n" + "ATTENTION: This version of STRIFE has extra files added to it.\n" + " You will not receive technical support for modified games.\n" + "===========================================================================\n", + + "===========================================================================\n" + " This version is NOT SHAREWARE, do not distribute!\n" + " Please report software piracy to the SPA: 1-800-388-PIR8\n" + "===========================================================================\n", + + "===========================================================================\n" + " Shareware!\n" + "===========================================================================\n" +}; + +// Prints a message only if it has been modified by dehacked. + +void PrintDehackedBanners(void) +{ + size_t i; + + for (i=0; i + // @category compat + // + // Emulate a specific version of Strife. Valid values are "1.2" and "1.31". + // + + p = M_CheckParmWithArgs("-gameversion", 1); + + if (p) + { + int i; + for (i=0; gameversions[i].description != NULL; ++i) + { + if (!strcmp(myargv[p+1], gameversions[i].cmdline)) + { + gameversion = gameversions[i].version; + break; + } + } + + if (gameversions[i].description == NULL) + { + printf("Supported game versions:\n"); + + for (i=0; gameversions[i].description != NULL; ++i) + { + printf("\t%s (%s)\n", gameversions[i].cmdline, + gameversions[i].description); + } + + I_Error("Unknown game version '%s'", myargv[p+1]); + } + } + else + { + gameversion = exe_strife_1_31; + } +} + +void PrintGameVersion(void) +{ + int i; + + for (i=0; gameversions[i].description != NULL; ++i) + { + if (gameversions[i].version == gameversion) + { + printf("Emulating the behavior of the " + "'%s' executable.\n", gameversions[i].description); + break; + } + } +} + +// Function called at exit to display the ENDOOM screen + +static void D_Endoom(void) +{ + byte *endoom; + + // Don't show ENDOOM if we have it disabled, or we're running + // in screensaver or control test mode. Only show it once the + // game has actually started. + + + if (!show_endoom || !main_loop_started || screensaver_mode || testcontrols) + { + return; + } + + // haleyjd 08/27/10: [STRIFE] ENDOOM -> ENDSTRF + endoom = W_CacheLumpName(DEH_String("ENDSTRF"), PU_STATIC); + + I_Endoom(endoom); +} + +// +// D_GetCursorColumn +// +static int D_GetCursorColumn(void) +{ + int x, y; + TXT_GetXY(&x, &y); + return x; +} + +// +// D_GetCursorRow +// +static int D_GetCursorRow(void) +{ + int x, y; + TXT_GetXY(&x, &y); + return y; +} + +// +// D_SetCursorPosition +// +static void D_SetCursorPosition(int column, int row) +{ + TXT_GotoXY(column, row); +} + +// +// D_SetChar +// +static void D_SetChar(char c) +{ + int x, y; + // Backup position + TXT_GetXY(&x, &y); + TXT_PutChar(c); + // Restore position + TXT_GotoXY(x, y); +} + +// +// D_DrawText +// +static void D_DrawText(const char *string, int bc, int fc) +{ + int column; + int row; + int i; + + if (!using_text_startup) + { + return; + } + + // Set text color + TXT_BGColor(bc, 0); + TXT_FGColor(fc); + + // Get column position + column = D_GetCursorColumn(); + + // Get row position + row = D_GetCursorRow(); + + for (i = 0; i < strlen(string); i++) + { + // Set character + D_SetChar(string[i]); + + // Check cursor position + if (++column >= 80) + column = 0; + + // Set postition + D_SetCursorPosition(column, row); + } +} + +//============================================================================= +// +// haleyjd: Chocolate Strife Specifics +// +// None of the code in here is from the original executable, but is needed for +// other reasons. + +// +// D_PatchClipCallback +// +// haleyjd 08/28/10: Clip patches to the framebuffer without errors. +// Returns false if V_DrawPatch should return without drawing. +// +boolean D_PatchClipCallback(patch_t *patch, int x, int y) +{ + // note that offsets were already accounted for in V_DrawPatch + return (x >= 0 && y >= 0 + && x + SHORT(patch->width) <= SCREENWIDTH + && y + SHORT(patch->height) <= SCREENHEIGHT); +} + +// +// D_InitChocoStrife +// +// haleyjd 08/28/10: Take care of some Strife-specific initialization +// that is necessitated by Chocolate Doom issues, such as setting global +// callbacks. +// +static void D_InitChocoStrife(void) +{ + // set the V_DrawPatch clipping callback + V_SetPatchClipCallback(D_PatchClipCallback); +} + + +// +// STRIFE Graphical Intro Sequence +// + +#define MAXINTROPROGRESS 69 + +static int introprogress; // track the progress of the intro + +static byte *rawgfx_startup0; // raw linear gfx for intro +static byte *rawgfx_startp[4]; +static byte *rawgfx_startlz[2]; +static byte *rawgfx_startbot; + +// +// D_IntroBackground +// +// [STRIFE] New function +// haleyjd 20110206: Strife only drew this once, but for supporting double- +// buffered or page-flipped surfaces it is best to redraw the entire screen +// every frame. +// +static void D_IntroBackground(void) +{ + if(!showintro) + return; + + // Fill the background entirely (wasn't needed in vanilla) + V_DrawFilledBox(0, 0, SCREENWIDTH, SCREENHEIGHT, 0); + + // Strife cleared the screen somewhere in the low-level code between the + // intro and the titlescreen, so this is to take care of that and get + // proper fade-in behavior on the titlescreen + if(introprogress >= MAXINTROPROGRESS) + { + I_FinishUpdate(); + return; + } + + // Draw a 95-pixel rect from STARTUP0 starting at y=57 to (0,41) on the + // screen (this was a memcpy directly to 0xA3340 in low DOS memory) + V_DrawBlock(0, 41, 320, 95, rawgfx_startup0 + (320*57)); +} + +// +// D_InitIntroSequence +// +// [STRIFE] New function +// haleyjd 20110206: Initialize the graphical introduction sequence +// + +static void D_InitIntroSequence(void) +{ + byte *textScreen; + char string[80]; + + if (devparm || !graphical_startup || testcontrols) + { + using_text_startup = false; + showintro = false; + return; + } + + if(showintro) + { + // In vanilla Strife, Mode 13h was initialized directly in D_DoomMain. + // We have to be a little more courteous of the low-level code here. + I_SetGrabMouseCallback(D_StartupGrabCallback); + I_RegisterWindowIcon(strife_icon_data, strife_icon_h, strife_icon_w); + I_InitGraphics(); + V_RestoreBuffer(); // make the V_ routines work + + // Load all graphics + rawgfx_startup0 = W_CacheLumpName("STARTUP0", PU_STATIC); + rawgfx_startp[0] = W_CacheLumpName("STRTPA1", PU_STATIC); + rawgfx_startp[1] = W_CacheLumpName("STRTPB1", PU_STATIC); + rawgfx_startp[2] = W_CacheLumpName("STRTPC1", PU_STATIC); + rawgfx_startp[3] = W_CacheLumpName("STRTPD1", PU_STATIC); + rawgfx_startlz[0] = W_CacheLumpName("STRTLZ1", PU_STATIC); + rawgfx_startlz[1] = W_CacheLumpName("STRTLZ2", PU_STATIC); + rawgfx_startbot = W_CacheLumpName("STRTBOT", PU_STATIC); + + // Draw the background + D_IntroBackground(); + + using_text_startup = false; + } + else + { + if (!TXT_Init()) + { + using_text_startup = false; + return; + } + + I_InitWindowTitle(); + I_InitWindowIcon(); + + // Clear screen + textScreen = TXT_GetScreenData(); + memset(textScreen, 0, 4000); + + using_text_startup = true; + + // Print title + + D_SetCursorPosition(0, 0); + D_DrawText(title, TXT_COLOR_GREEN, TXT_COLOR_BLACK); + + DEH_snprintf(string, sizeof(string), "Rogue Entertainment"); + D_SetCursorPosition(40 - strlen(string) / 2, 5); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + DEH_snprintf(string, sizeof(string), "and"); + D_SetCursorPosition(40 - strlen(string) / 2, 7); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + DEH_snprintf(string, sizeof(string), "Velocity Games"); + D_SetCursorPosition(40 - strlen(string) / 2, 9); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + DEH_snprintf(string, sizeof(string), "present"); + D_SetCursorPosition(40 - strlen(string) / 2, 11); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + DEH_snprintf(string, sizeof(string), "S T R I F E"); + D_SetCursorPosition(40 - strlen(string) / 2, 14); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + DEH_snprintf(string, sizeof(string), "Loading..."); + D_SetCursorPosition(40 - strlen(string) / 2, 17); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + DEH_snprintf(string, sizeof(string), + "[ ]"); + D_SetCursorPosition(14, 18); + D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); + + TXT_UpdateScreen(); + } +} + +// +// D_DrawIntroSequence +// +// [STRIFE] New function +// haleyjd 20110206: Refresh the intro sequence +// +static void D_DrawIntroSequence(void) +{ + int laserpos; + int robotpos; + int i; + + if (showintro) + { + D_IntroBackground(); // haleyjd: refresh the background + + // Laser position + laserpos = (200 * introprogress / MAXINTROPROGRESS) + 60; + + // BUG: (?) Due to this clip, the laser never even comes close to + // touching the peasant; confirmed with vanilla. This MAY have been + // intentional, for effect, however, since no death frames are shown + // either... kind of a black-out death. + if (laserpos > 200) + laserpos = 200; + + // Draw the laser + // Blitted 16 bytes for 16 rows starting at 705280 + laserpos + // (705280 - 0xA0000) / 320 == 156 + V_DrawBlock(laserpos, 156, 16, 16, rawgfx_startlz[laserpos % 2]); + + // Robot position + robotpos = laserpos % 5 - 2; + + // Draw the robot + // Blitted 48 bytes for 48 rows starting at 699534 + (320*robotpos) + // 699534 - 0xA0000 == 44174, which % 320 == 14, / 320 == 138 + V_DrawBlock(14, 138 + robotpos, 48, 48, rawgfx_startbot); + + // Draw the peasant + // Blitted 32 bytes for 64 rows starting at 699142 + // 699142 - 0xA0000 == 43782, which % 320 == 262, / 320 == 136 + V_DrawBlock(262, 136, 32, 64, rawgfx_startp[laserpos % 4]); + + I_FinishUpdate(); + } + else if (using_text_startup) + { + // Laser position + laserpos = 50 * introprogress / MAXINTROPROGRESS; + + if (laserpos > 50) + { + laserpos = 50; + } + + for (i = 0; i < laserpos; i++) + { + D_SetCursorPosition(15 + i, 18); + D_DrawText("#", TXT_COLOR_GREEN, TXT_COLOR_BLUE); + } + + I_Sleep(10); + + TXT_UpdateScreen(); + } +} + +// +// D_IntroTick +// +// Advance the intro sequence +// +void D_IntroTick(void) +{ + static boolean didsound = false; // haleyjd 20120209 + + if(devparm) + return; + + ++introprogress; + if(introprogress >= MAXINTROPROGRESS) + { + D_IntroBackground(); // haleyjd: clear the bg anyway + + // haleyjd 20120209: This isn't 100% true to vanilla because vanilla + // would play this sound a half-dozen times. BUT, in vanilla, for + // whatever reason, under DMX, playing the same sound multiple times + // doesn't add up violently like it does under SDL_mixer. This means + // that without this one-time limitation, the sound is far too loud. + if(!didsound) + { + S_StartSound(NULL, sfx_psdtha); + didsound = true; + } + } + else + D_DrawIntroSequence(); +} + +// +// End Chocolate Strife Specifics +// +//============================================================================= + +static void G_CheckDemoStatusAtExit (void) +{ + G_CheckDemoStatus(); +} + +// +// D_DoomMain +// +void D_DoomMain (void) +{ + int p; + char file[256]; + char demolumpname[9]; + + I_AtExit(D_Endoom, false); + + // haleyjd 20110206 [STRIFE]: -nograph parameter + + //! + // @vanilla + // + // Disable graphical introduction sequence + // + + if (M_ParmExists("-nograph")) + showintro = false; + + // Undocumented: + // Invoked by setup to test the controls. + + if (M_ParmExists("-testcontrols")) + { + testcontrols = true; + showintro = false; + } + + // haleyjd 20110206: Moved up -devparm for max visibility + + //! + // @vanilla + // + // Developer mode. Implies -nograph. + // + + devparm = M_CheckParm ("-devparm"); + + // print banner + + I_PrintBanner(PACKAGE_STRING); + + //DEH_printf("Z_Init: Init zone memory allocation daemon. \n"); [STRIFE] removed + Z_Init (); + + //! + // @category net + // + // Start a dedicated server, routing packets but not participating + // in the game itself. + // + + if (M_CheckParm("-dedicated") > 0) + { + printf("Dedicated server mode.\n"); + NET_DedicatedServer(); + + // Never returns + } + + //! + // @category net + // + // Query the Internet master server for a global list of active + // servers. + // + + if (M_CheckParm("-search")) + { + NET_MasterQuery(); + exit(0); + } + + //! + // @arg
+ // @category net + // + // Query the status of the server running on the given IP + // address. + // + + p = M_CheckParmWithArgs("-query", 1); + + if (p) + { + NET_QueryAddress(myargv[p+1]); + exit(0); + } + + //! + // @category net + // + // Search the local LAN for running servers. + // + + if (M_CheckParm("-localsearch")) + { + NET_LANQuery(); + exit(0); + } + + //! + // @category game + // @vanilla + // + // Disable monsters. + // + + nomonsters = M_CheckParm ("-nomonsters"); + + //! + // @category obscure + // @vanilla + // + // Set Rogue playtesting mode + // (god mode; no cliping mode toggled by backspace). + // + + workparm = M_CheckParm ("-work"); + + //! + // @category obscure + // @vanilla + // + // Flip player gun sprites (broken). + // + + flipparm = M_CheckParm ("-flip"); + + //! + // @category game + // @vanilla + // + // Respawn monsters after they are killed. + // + + respawnparm = M_CheckParm ("-respawn"); + + //! + // @category game + // @vanilla + // + // Items respawn at random locations + // + + randomparm = M_CheckParm ("-random"); + + //! + // @category game + // @vanilla + // + // Monsters move faster. + // + + fastparm = M_CheckParm ("-fast"); + + I_DisplayFPSDots(devparm); + + // haleyjd 20110206 [STRIFE]: -devparm implies -nograph + if(devparm) + showintro = false; + + // Note: Vanilla Strife does not understand the -deathmatch command + // line parameter. deathmatch=1 is the default behavior when + // playing a netgame. + + //! + // @category net + // @vanilla + // + // Start a deathmatch game. Weapons do not stay in place and + // all items respawn after 30 seconds. + // + + if (M_CheckParm ("-altdeath")) + deathmatch = 2; + + if (devparm) + DEH_printf(D_DEVSTR); + + // find which dir to use for config files + +#ifdef _WIN32 + + //! + // @category obscure + // @platform windows + // @vanilla + // + // Save configuration data and savegames in c:\strife.cd, + // allowing play from CD. + // + + if (M_CheckParm("-cdrom") > 0) + { + printf(D_CDROM); + + // haleyjd 08/22/2010: [STRIFE] Use strife.cd folder for -cdrom + M_SetConfigDir("c:\\strife.cd\\"); + } + else +#endif + { + // Auto-detect the configuration dir. + + M_SetConfigDir(NULL); + } + + //! + // @category game + // @arg + // @vanilla + // + // Turbo mode. The player's speed is multiplied by x%. If unspecified, + // x defaults to 200. Values are rounded up to 10 and down to 400. + // + + if ( (p=M_CheckParm ("-turbo")) ) + { + int scale = 200; + + if (p 400) + scale = 400; + DEH_printf("turbo scale: %i%%\n", scale); + forwardmove[0] = forwardmove[0]*scale/100; + forwardmove[1] = forwardmove[1]*scale/100; + sidemove[0] = sidemove[0]*scale/100; + sidemove[1] = sidemove[1]*scale/100; + } + + // init subsystems + // DEH_printf("V_Init: allocate screens.\n"); [STRIFE] removed + V_Init (); + + // Load configuration files before initialising other subsystems. + // haleyjd 08/22/2010: [STRIFE] - use strife.cfg + // DEH_printf("M_LoadDefaults: Load system defaults.\n"); [STRIFE] removed + M_SetConfigFilenames("strife.cfg", PROGRAM_PREFIX "strife.cfg"); + D_BindVariables(); + M_LoadDefaults(); + + // Save configuration at exit. + I_AtExit(M_SaveDefaults, false); + + // Find the main IWAD file and load it. + iwadfile = D_FindIWAD(IWAD_MASK_STRIFE, &gamemission); + + // None found? + if (iwadfile == NULL) + { + I_Error("Game mode indeterminate. No IWAD file was found. Try\n" + "specifying one with the '-iwad' command line parameter.\n"); + } + + modifiedgame = false; + + if(devparm) // [STRIFE] Devparm only + DEH_printf("W_Init: Init WADfiles.\n"); + D_AddFile(iwadfile); + W_CheckCorrectIWAD(strife); + D_IdentifyVersion(); + + //! + // @category mod + // + // Disable auto-loading of .wad files. + // + if (!M_ParmExists("-noautoload")) + { + char *autoload_dir; + autoload_dir = M_GetAutoloadDir("strife1.wad"); + if (autoload_dir != NULL) + { + DEH_AutoLoadPatches(autoload_dir); + W_AutoLoadWADs(autoload_dir); + free(autoload_dir); + } + } + + // Load dehacked patches specified on the command line. + DEH_ParseCommandLine(); + + // Load PWAD files. + modifiedgame = W_ParseCommandLine(); + + // [STRIFE] serial number output + if(devparm) + { + char msgbuf[80]; + char *serial = W_CacheLumpName("SERIAL", PU_CACHE); + int serialnum = atoi(serial); + + DEH_snprintf(msgbuf, sizeof(msgbuf), "Wad Serial Number: %d:", serialnum); + printf("%s\n", msgbuf); + } + + // add any files specified on the command line with -file wadfile + // to the wad list + // + + // Debug: +// W_PrintDirectory(); + + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp. + // + + p = M_CheckParmWithArgs ("-playdemo", 1); + + if (!p) + { + //! + // @arg + // @category demo + // @vanilla + // + // Play back the demo named demo.lmp, determining the framerate + // of the screen. + // + p = M_CheckParmWithArgs("-timedemo", 1); + + } + + if (p) + { + char *uc_filename = strdup(myargv[p + 1]); + M_ForceUppercase(uc_filename); + + // With Vanilla you have to specify the file without extension, + // but make that optional. + if (M_StringEndsWith(uc_filename, ".LMP")) + { + M_StringCopy(file, myargv[p + 1], sizeof(file)); + } + else + { + DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p+1]); + } + + free(uc_filename); + + if (D_AddFile (file)) + { + M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, + sizeof(demolumpname)); + } + else + { + // If file failed to load, still continue trying to play + // the demo in the same way as Vanilla Doom. This makes + // tricks like "-playdemo demo1" possible. + + M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); + } + + printf("Playing demo %s.\n", file); + } + + I_AtExit(G_CheckDemoStatusAtExit, true); + + // Generate the WAD hash table. Speed things up a bit. + + W_GenerateHashTable(); + + InitGameVersion(); + InitTitleString(); + D_SetGameDescription(); + I_SetWindowTitle(gamedescription); + savegamedir = M_GetSaveGameDir("strife1.wad"); + + // fraggle 20130405: I_InitTimer is needed here for the netgame + // startup. Start low-level sound init here too. + I_InitTimer(); + I_InitSound(strife); + I_InitMusic(); + + if(devparm) // [STRIFE] + printf ("NET_Init: Init network subsystem.\n"); + NET_Init(); + D_ConnectNetGame(); + + // haleyjd 20110210: Create Strife hub save folders + M_CreateSaveDirs(savegamedir); + + I_GraphicsCheckCommandLine(); + + // haleyjd 20110206 [STRIFE] Startup the introduction sequence + D_InitIntroSequence(); + + // haleyjd 20110924: moved S_Init up to here + if(devparm) // [STRIFE] + DEH_printf("S_Init: Setting up sound.\n"); + S_Init (sfxVolume * 8, musicVolume * 8, voiceVolume * 8); // [STRIFE]: voice + D_IntroTick(); // [STRIFE] + + // Check for -file in shareware + if (modifiedgame) + { + // These are the lumps that will be checked in IWAD, + // if any one is not present, execution will be aborted. + // haleyjd 08/22/2010: [STRIFE] Check for Strife lumps. + char name[3][8]= + { + "map23", "map30", "ROB3E1" + }; + int i; + + // haleyjd 08/22/2010: [STRIFE] Changed string to match binary + // STRIFE-FIXME: Needs to test isdemoversion variable + if ( gamemode == shareware) + I_Error(DEH_String("\nYou cannot -file with the demo " + "version. You must buy the real game!")); + + // Check for fake IWAD with right name, + // but w/o all the lumps of the registered version. + // STRIFE-FIXME: Needs to test isregistered variable + if (gamemode == registered) + for (i = 0; i < 3; i++) + if (W_CheckNumForName(name[i])<0) + I_Error(DEH_String("\nThis is not the registered version.")); + } + + D_IntroTick(); // [STRIFE] + + // get skill / episode / map from parms + startskill = sk_easy; // [STRIFE]: inits to sk_easy + startepisode = 1; + startmap = 1; + autostart = false; + + //! + // @category game + // @arg + // @vanilla + // + // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of + // 0 disables all monsters. + // + + p = M_CheckParmWithArgs("-skill", 1); + + if (p) + { + startskill = myargv[p+1][0]-'1'; + autostart = true; + } + + // [STRIFE] no such thing in Strife + // + // // @category game + // // @arg + // // @vanilla + // // + // // Start playing episode n (1-4). + // // + + // p = M_CheckParmWithArgs("-episode", 1); + + // if (p) + // { + // startepisode = myargv[p+1][0]-'0'; + // startmap = 1; + // autostart = true; + // } + + timelimit = 0; + + //! + // @arg + // @category net + // @vanilla + // + // For multiplayer games: exit each level after n minutes. + // + + p = M_CheckParmWithArgs("-timer", 1); + + if (p) + { + timelimit = atoi(myargv[p+1]); + printf("timer: %i\n", timelimit); + } + + //! + // @category net + // @vanilla + // + // Austin Virtual Gaming: end levels after 20 minutes. + // + + p = M_CheckParm ("-avg"); + + if (p) + { + timelimit = 20; + } + + //! + // @category game + // @arg x + // @vanilla + // + // Start a game immediately, warping to level x. + // + + p = M_CheckParmWithArgs("-warp", 1); + + if (p) + { + if (gamemode == commercial) + startmap = atoi (myargv[p+1]); + else + { + startepisode = myargv[p+1][0]-'0'; + + if (p + 2 < myargc) + { + startmap = myargv[p+2][0]-'0'; + } + else + { + startmap = 1; + } + } + autostart = true; + } + + if (testcontrols) + { + startepisode = 1; + startmap = 3; + autostart = true; + } + + // Check for load game parameter + // We do this here and save the slot number, so that the network code + // can override it or send the load slot to other players. + + //! + // @category game + // @arg + // @vanilla + // + // Load the game in slot s. + // + + p = M_CheckParmWithArgs("-loadgame", 1); + + if (p) + { + startloadgame = atoi(myargv[p+1]); + } + else + { + // Not loading a game + startloadgame = -1; + } + + if (W_CheckNumForName("SS_START") >= 0 + || W_CheckNumForName("FF_END") >= 0) + { + I_PrintDivider(); + printf(" WARNING: The loaded WAD file contains modified sprites or\n" + " floor textures. You may want to use the '-merge' command\n" + " line option instead of '-file'.\n"); + } + + I_PrintStartupBanner(gamedescription); + PrintDehackedBanners(); + + // haleyjd 08/28/10: Init Choco Strife stuff. + D_InitChocoStrife(); + + // haleyjd 08/22/2010: [STRIFE] Modified string to match binary + if(devparm) // [STRIFE] + DEH_printf("R_Init: Loading Graphics - "); + R_Init (); + D_IntroTick(); // [STRIFE] + + if(devparm) // [STRIFE] + DEH_printf("\nP_Init: Init Playloop state.\n"); + P_Init (); + D_IntroTick(); // [STRIFE] + + if(devparm) // [STRIFE] + DEH_printf("I_Init: Setting up machine state.\n"); + I_CheckIsScreensaver(); + I_InitJoystick(); + D_IntroTick(); // [STRIFE] + + D_IntroTick(); // [STRIFE] + + if(devparm) // [STRIFE] + DEH_printf("M_Init: Init Menu.\n"); + M_Init (); + D_IntroTick(); // [STRIFE] + + // haleyjd 20110924: Moved S_Init up. + D_IntroTick(); + + // haleyjd 20110220: This stuff was done in I_StartupSound in vanilla, but + // we'll do it here instead so we don't have to modify the low-level shared + // code with Strife-specific stuff. + + //! + // @vanilla + // + // Disable voice dialog and show dialog as text instead, + // even if voices.wad can be found. + // + + if(disable_voices || M_CheckParm("-novoice")) + { + dialogshowtext = disable_voices = 1; + } + + if(devparm) + DEH_printf(" Play voices = %d\n", disable_voices == 0); + + if(devparm) // [STRIFE] + DEH_printf("D_CheckNetGame: Checking network game status.\n"); + D_CheckNetGame (); + + PrintGameVersion(); + + if(devparm) + DEH_printf("HU_Init: Setting up heads up display.\n"); + HU_Init (); + D_IntroTick(); // [STRIFE] + + if(devparm) + DEH_printf("ST_Init: Init status bar.\n"); + ST_Init (); + D_IntroTick(); // [STRIFE] + + // haleyjd [STRIFE] -statcopy used to be here... + D_IntroTick(); // [STRIFE] + + // If Doom II without a MAP01 lump, this is a store demo. + // Moved this here so that MAP01 isn't constantly looked up + // in the main loop. + // haleyjd 08/23/2010: [STRIFE] There is no storedemo version of Strife + /* + if (gamemode == commercial && W_CheckNumForName("map01") < 0) + storedemo = true; + */ + + //! + // @arg + // @category demo + // @vanilla + // + // Record a demo named x.lmp. + // + + p = M_CheckParmWithArgs("-record", 1); + + if (p) + { + G_RecordDemo (myargv[p+1]); + autostart = true; + } + D_IntroTick(); // [STRIFE] + + p = M_CheckParmWithArgs("-playdemo", 1); + if (p) + { + singledemo = true; // quit after one demo + G_DeferedPlayDemo (demolumpname); + D_DoomLoop (); // never returns + } + D_IntroTick(); // [STRIFE] + + p = M_CheckParmWithArgs("-timedemo", 1); + if (p) + { + G_TimeDemo (demolumpname); + D_DoomLoop (); // never returns + } + D_IntroTick(); // [STRIFE] + + if (startloadgame >= 0) + { + // [STRIFE]: different, for hubs + M_LoadSelect(startloadgame); + } + D_IntroTick(); // [STRIFE] + + + if (gameaction != ga_loadgame ) + { + if (autostart || netgame) + G_InitNew (startskill, startmap); + else + D_StartTitle (); // start up intro loop + } + + if (using_text_startup) + { + TXT_Shutdown(); + } + + D_DoomLoop (); // never returns +} diff --git a/games/NXDoom/src/strife/d_main.h b/games/NXDoom/src/strife/d_main.h new file mode 100644 index 00000000000..22f55488d66 --- /dev/null +++ b/games/NXDoom/src/strife/d_main.h @@ -0,0 +1,64 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// System specific interface stuff. +// + + +#ifndef __D_MAIN__ +#define __D_MAIN__ + +#include "doomdef.h" + +#include "v_patch.h" + + +// Read events from all input devices + +void D_ProcessEvents (void); + + +// +// BASE LEVEL +// +void D_PageTicker (void); +void D_PageDrawer (void); +void D_AdvanceDemo (void); +void D_DoAdvanceDemo (void); +void D_StartTitle (void); +void D_QuitGame (void); // [STRIFE] + +void D_IntroTick(void); // [STRIFE] + +boolean D_PatchClipCallback(patch_t *patch, int x, int y); // [STRIFE] + + +// +// GLOBAL VARIABLES +// + +extern gameaction_t gameaction; +extern boolean isregistered; // villsa [STRIFE] +extern boolean isdemoversion; // haleyjd [STRIFE] +extern boolean stonecold; // villsa [STRIFE] +extern boolean workparm; // villsa [STRIFE] +extern boolean advancedemo; + +// haleyjd 20130915 [STRIFE]: need nickname +extern char *nickname; + + +#endif + diff --git a/games/NXDoom/src/strife/d_net.c b/games/NXDoom/src/strife/d_net.c new file mode 100644 index 00000000000..26d807830f0 --- /dev/null +++ b/games/NXDoom/src/strife/d_net.c @@ -0,0 +1,290 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM Network game communication and protocol, +// all OS independend parts. +// + +#include + +#include "d_main.h" +#include "m_argv.h" +#include "m_menu.h" +#include "m_misc.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "g_game.h" +#include "doomdef.h" +#include "doomstat.h" +#include "w_checksum.h" + +#include "deh_main.h" + +#include "d_loop.h" + +ticcmd_t *netcmds; + +// Called when a player leaves the game + +static void PlayerQuitGame(player_t *player) +{ + static char exitmsg[80]; + unsigned int player_num; + + player_num = player - players; + + // Do this the same way as Vanilla Doom does, to allow dehacked + // replacements of this message + + M_StringCopy(exitmsg, DEH_String("Player 1 left the game"), + sizeof(exitmsg)); + + exitmsg[7] += player_num; + + playeringame[player_num] = false; + players[consoleplayer].message = exitmsg; + + // TODO: check if it is sensible to do this: + + if (demorecording) + { + G_CheckDemoStatus (); + } +} + +static void RunTic(ticcmd_t *cmds, boolean *ingame) +{ + unsigned int i; + + // Check for player quits. + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (!demoplayback && playeringame[i] && !ingame[i]) + { + PlayerQuitGame(&players[i]); + } + } + + netcmds = cmds; + + // check that there are players in the game. if not, we cannot + // run a tic. + + if (advancedemo) + D_DoAdvanceDemo (); + + M_Ticker(); + G_Ticker(); +} + +static void NullMenuTicker() +{ + // no-op. +} + +static loop_interface_t strife_loop_interface = { + D_ProcessEvents, + G_BuildTiccmd, + RunTic, + NullMenuTicker +}; + + +// Load game settings from the specified structure and +// set global variables. + +static void LoadGameSettings(net_gamesettings_t *settings) +{ + unsigned int i; + + deathmatch = settings->deathmatch; + ticdup = settings->ticdup; + startepisode = settings->episode; + startmap = settings->map; + startskill = settings->skill; + startloadgame = settings->loadgame; + lowres_turn = settings->lowres_turn; + nomonsters = settings->nomonsters; + fastparm = settings->fast_monsters; + respawnparm = settings->respawn_monsters; + timelimit = settings->timelimit; + consoleplayer = settings->consoleplayer; + randomparm = settings->random; + + if (lowres_turn) + { + printf("NOTE: Turning resolution is reduced; this is probably " + "because there is a client recording a Vanilla demo.\n"); + } + + for (i = 0; i < MAXPLAYERS; ++i) + { + playeringame[i] = i < settings->num_players; + } +} + +// Save the game settings from global variables to the specified +// game settings structure. + +static void SaveGameSettings(net_gamesettings_t *settings) +{ + // Fill in game settings structure with appropriate parameters + // for the new game + + settings->deathmatch = deathmatch; + settings->episode = startepisode; + settings->map = startmap; + settings->skill = startskill; + settings->loadgame = startloadgame; + settings->gameversion = gameversion; + settings->nomonsters = nomonsters; + settings->fast_monsters = fastparm; + settings->respawn_monsters = respawnparm; + settings->timelimit = timelimit; + settings->random = randomparm; + + settings->lowres_turn = M_ParmExists("-record") + && !M_ParmExists("-longtics"); +} + +static void InitConnectData(net_connect_data_t *connect_data) +{ + connect_data->drone = false; + connect_data->max_players = MAXPLAYERS; + + //! + // @category net + // + // Run as the left screen in three screen mode. + // + + if (M_CheckParm("-left") > 0) + { + viewangleoffset = ANG90; + connect_data->drone = true; + } + + //! + // @category net + // + // Run as the right screen in three screen mode. + // + + if (M_CheckParm("-right") > 0) + { + viewangleoffset = ANG270; + connect_data->drone = true; + } + + // + // Connect data + // + + // Game type fields: + + connect_data->gamemode = gamemode; + connect_data->gamemission = gamemission; + + // Are we recording a demo? Possibly set lowres turn mode + + connect_data->lowres_turn = M_CheckParm("-record") > 0 + && M_CheckParm("-longtics") == 0; + + // Read checksums of our WAD directory and dehacked information + + W_Checksum(connect_data->wad_sha1sum); + DEH_Checksum(connect_data->deh_sha1sum); + + connect_data->is_freedoom = 0; +} + +void D_ConnectNetGame(void) +{ + net_connect_data_t connect_data; + + InitConnectData(&connect_data); + netgame = D_InitNetGame(&connect_data); + + //! + // @category net + // + // Start the game playing as though in a netgame with a single + // player. This can also be used to play back single player netgame + // demos. + // + + if (M_CheckParm("-solo-net") > 0) + { + netgame = true; + } +} + +// +// D_CheckNetGame +// Works out player numbers among the net participants +// +void D_CheckNetGame(void) +{ + net_gamesettings_t settings; + + D_RegisterLoopCallbacks(&strife_loop_interface); + + if (netgame) + { + autostart = true; + } + + SaveGameSettings(&settings); + D_StartNetGame(&settings, NULL); + LoadGameSettings(&settings); + + // Strife games are always deathmatch, though -altdeath is + // supported for respawning items. + + if (netgame && deathmatch == 0) + { + deathmatch = 1; + } + + DEH_printf("startmap: %i, skill: %i, enemies: %i, random: %i\n", + startmap, startskill, !nomonsters, randomparm); + + + DEH_printf("player %i of %i (%i nodes)\n", + consoleplayer+1, settings.num_players, settings.num_players); + + // Show players here; the server might have specified a time limit + + if (timelimit > 0 && deathmatch) + { + // Gross hack to work like Vanilla: + + if (timelimit == 20 && M_CheckParm("-avg")) + { + DEH_printf("Austin Virtual Gaming: Levels will end " + "after 20 minutes\n"); + } + else + { + DEH_printf("Levels will end after %d minute", timelimit); + if (timelimit > 1) + printf("s"); + printf(".\n"); + } + } +} + diff --git a/games/NXDoom/src/strife/d_player.h b/games/NXDoom/src/strife/d_player.h new file mode 100644 index 00000000000..1f5b4ec00ed --- /dev/null +++ b/games/NXDoom/src/strife/d_player.h @@ -0,0 +1,249 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __D_PLAYER__ +#define __D_PLAYER__ + + +// The player data structure depends on a number +// of other structs: items (internal inventory), +// animation states (closely tied to the sprites +// used to represent them, unfortunately). +#include "d_items.h" +#include "p_pspr.h" + +// In addition, the player is just a special +// case of the generic moving object/actor. +#include "p_mobj.h" + +// Finally, for odd reasons, the player input +// is buffered within the player data struct, +// as commands per game tick. +#include "d_ticcmd.h" + +#include "net_defs.h" + + + + +// +// Player states. +// +typedef enum +{ + // Playing or camping. + PST_LIVE, + // Dead on the ground, view follows killer. + PST_DEAD, + // Ready to restart/respawn??? + PST_REBORN + +} playerstate_t; + + +// +// Player internal flags, for cheats and debug. +// +typedef enum +{ + // No clipping, walk through barriers. + CF_NOCLIP = 1, + // No damage, no health loss. + CF_GODMODE = 2, + // Not really a cheat, just a debug aid. + CF_NOMOMENTUM = 4, + // villsa [STRIFE] new cheat + // set when on fire and disable inventory + CF_ONFIRE = 8, + // villsa [STRIFE] new cheat + // auto-use medkits + CF_AUTOHEALTH = 16 + +} cheat_t; + +// haleyjd 08/30/10: [STRIFE] +// Player Inventory Item Structure +typedef struct inventory_s +{ + int sprite; // a sprite number + int type; // a thing type + int amount; // amount being carried +} inventory_t; + +#define NUMINVENTORY 32 + +// +// Extended player object info: player_t +// +// haleyjd 08/30/10: [STRIFE] +// * Transformed to match binary structure layout. +// +typedef struct player_s +{ + mobj_t* mo; + playerstate_t playerstate; + ticcmd_t cmd; + + // Determine POV, + // including viewpoint bobbing during movement. + // Focal origin above r.z + fixed_t viewz; + // Base height above floor for viewz. + fixed_t viewheight; + // Bob/squat speed. + fixed_t deltaviewheight; + // bounded/scaled total momentum. + fixed_t bob; + + // This is only used between levels, + // mo->health is used during levels. + int health; + short armorpoints; // [STRIFE] Changed to short + // Armor type is 0-2. + short armortype; // [STRIFE] Changed to short + + // Power ups. invinc and invis are tic counters. + int powers[NUMPOWERS]; + + // [STRIFE] Additions: + int sigiltype; // Type of Sigil carried + int nukagecount; // Nukage exposure counter + int questflags; // Quest bit flags + int pitch; // Up/down look angle + boolean centerview; // True if view should be centered + inventory_t inventory[NUMINVENTORY]; // Player inventory items + boolean st_update; // If true, update status bar + short numinventory; // Num. active inventory items + short inventorycursor; // Selected inventory item + short accuracy; // Accuracy stat + short stamina; // Stamina stat + + boolean cards[NUMCARDS]; + boolean backpack; + + // True if button down last tic. + int attackdown; + int usedown; + int inventorydown; // [STRIFE] Use inventory item + + // Frags, kills of other players. + int frags[MAXPLAYERS]; + weapontype_t readyweapon; + + // Is wp_nochange if not changing. + weapontype_t pendingweapon; + + boolean weaponowned[NUMWEAPONS]; + int ammo[NUMAMMO]; + int maxammo[NUMAMMO]; + + // Bit flags, for cheats and debug. + // See cheat_t, above. + int cheats; + + // Refired shots are less accurate. + int refire; + + // For intermission stats. + short killcount; // [STRIFE] Changed to short + //int itemcount; // [STRIFE] Eliminated these. + //int secretcount; + + // Hint messages. + const char *message; + + // For screen flashing (red or bright). + int damagecount; + int bonuscount; + + // Who did damage (NULL for floors/ceilings). + mobj_t* attacker; + + // So gun flashes light up areas. + int extralight; + + // Current PLAYPAL, ??? + // can be set to REDCOLORMAP for pain, etc. + int fixedcolormap; + + // Player skin colorshift, + // 0-3 for which color to draw player. + //int colormap; [STRIFE] no such? or did it become the below? + + // [STRIFE] For use of teleport beacons + short allegiance; + + // Overlay view sprites (gun, etc). + pspdef_t psprites[NUMPSPRITES]; + + // [STRIFE] Inefficient means of tracking automap state on all maps + boolean mapstate[40]; + + // True if secret level has been done. + //boolean didsecret; [STRIFE] Removed this. + +} player_t; + + +// +// INTERMISSION +// Structure passed e.g. to WI_Start(wb) +// +typedef struct +{ + boolean in; // whether the player is in game + + // Player stats, kills, collected items etc. + int skills; + int sitems; + int ssecret; + int stime; + int frags[4]; + int score; // current score on entry, modified on return + +} wbplayerstruct_t; + +typedef struct +{ + int epsd; // episode # (0-2) + + // if true, splash the secret level + boolean didsecret; + + // previous and next levels, origin 0 + int last; + int next; + + int maxkills; + int maxitems; + int maxsecret; + int maxfrags; + + // the par time + int partime; + + // index of this player in game + int pnum; + + wbplayerstruct_t plyr[MAXPLAYERS]; + +} wbstartstruct_t; + + +#endif diff --git a/games/NXDoom/src/strife/d_textur.h b/games/NXDoom/src/strife/d_textur.h new file mode 100644 index 00000000000..1afe040eb04 --- /dev/null +++ b/games/NXDoom/src/strife/d_textur.h @@ -0,0 +1,43 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Typedefs related to to textures etc., +// isolated here to make it easier separating modules. +// + + +#ifndef __D_TEXTUR__ +#define __D_TEXTUR__ + +#include "doomtype.h" + + + + +// +// Flats? +// +// a pic is an unmasked block of pixels +typedef struct +{ + byte width; + byte height; + byte data; +} pic_t; + + + + +#endif diff --git a/games/NXDoom/src/strife/d_think.h b/games/NXDoom/src/strife/d_think.h new file mode 100644 index 00000000000..0966ad96023 --- /dev/null +++ b/games/NXDoom/src/strife/d_think.h @@ -0,0 +1,68 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// MapObj data. Map Objects or mobjs are actors, entities, +// thinker, take-your-pick... anything that moves, acts, or +// suffers state changes of more or less violent nature. +// + + +#ifndef __D_THINK__ +#define __D_THINK__ + + + + + +// +// Experimental stuff. +// To compile this as "ANSI C with classes" +// we will need to handle the various +// action functions cleanly. +// +typedef void (*actionf_v)(); +typedef void (*actionf_p1)( void* ); +typedef void (*actionf_p2)( void*, void* ); + +typedef union +{ + actionf_v acv; + actionf_p1 acp1; + actionf_p2 acp2; + +} actionf_t; + + + + + +// Historically, "think_t" is yet another +// function pointer to a routine to handle +// an actor. +typedef actionf_t think_t; + + +// Doubly linked list of actors. +typedef struct thinker_s +{ + struct thinker_s* prev; + struct thinker_s* next; + think_t function; + +} thinker_t; + + + +#endif diff --git a/games/NXDoom/src/strife/deh_ammo.c b/games/NXDoom/src/strife/deh_ammo.c new file mode 100644 index 00000000000..dd8bee54678 --- /dev/null +++ b/games/NXDoom/src/strife/deh_ammo.c @@ -0,0 +1,103 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Ammo" sections in dehacked files +// + +#include +#include +#include + +#include "doomdef.h" +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "p_local.h" + +static void *DEH_AmmoStart(deh_context_t *context, char *line) +{ + int ammo_number = 0; + + if (sscanf(line, "Ammo %i", &ammo_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (ammo_number < 0 || ammo_number >= NUMAMMO) + { + DEH_Warning(context, "Invalid ammo number: %i", ammo_number); + return NULL; + } + + return &maxammo[ammo_number]; +} + +static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + int ivalue; + int ammo_number; + + if (tag == NULL) + return; + + ammo_number = ((int *) tag) - maxammo; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + // maxammo + + if (!strcasecmp(variable_name, "Per ammo")) + clipammo[ammo_number] = ivalue; + else if (!strcasecmp(variable_name, "Max ammo")) + maxammo[ammo_number] = ivalue; + else + { + DEH_Warning(context, "Field named '%s' not found", variable_name); + } +} + +static void DEH_AmmoSHA1Hash(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "am_map.h" +#include "st_stuff.h" + +typedef struct +{ + const char *name; + cheatseq_t *seq; +} deh_cheat_t; + +static deh_cheat_t allcheats[] = +{ + // haleyjd 20110224: filled in all cheats + {"Change music", &cheat_mus }, + {"Level Warp", &cheat_clev }, + {"Stealth Boots", &cheat_stealth }, + {"Sigil piece", &cheat_lego }, + {"FPS", &cheat_mypos }, + {"TeleportMapSpot", &cheat_scoot }, + {"Gold&StatTokens", &cheat_midas }, + {"God mode", &cheat_god }, + {"Keys", &cheat_keys }, + {"Weapons & Ammo", &cheat_ammo }, + {"Massacre", &cheat_nuke }, + {"No Clipping", &cheat_noclip }, + {"Berserk", &cheat_powerup[0] }, + {"Invisibility", &cheat_powerup[1] }, + {"Enviro Suit", &cheat_powerup[2] }, + {"Health", &cheat_powerup[3] }, + {"Backpack", &cheat_powerup[4] }, + // STRIFE-FIXME/TODO: Does SeHackEd not support PUMPUP{S,T,nil}, or "DOTS" ? +}; + +static deh_cheat_t *FindCheatByName(char *name) +{ + size_t i; + + for (i=0; i= cheat->seq->sequence_len) + { + DEH_Warning(context, "Cheat sequence longer than supported by " + "Vanilla dehacked"); + break; + } + + if (deh_apply_cheats) + { + cheat->seq->sequence[i] = unsvalue[i]; + } + ++i; + + // Absolute limit - don't exceed + + if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars) + { + DEH_Error(context, "Cheat sequence too long!"); + return; + } + } + + if (deh_apply_cheats) + { + cheat->seq->sequence[i] = '\0'; + } +} + +deh_section_t deh_section_cheat = +{ + "Cheat", + NULL, + DEH_CheatStart, + DEH_CheatParseLine, + NULL, + NULL, +}; + diff --git a/games/NXDoom/src/strife/deh_frame.c b/games/NXDoom/src/strife/deh_frame.c new file mode 100644 index 00000000000..c36f3e34ced --- /dev/null +++ b/games/NXDoom/src/strife/deh_frame.c @@ -0,0 +1,159 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Frame" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" +#include "d_items.h" +#include "info.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "deh_mapping.h" + +DEH_BEGIN_MAPPING(state_mapping, state_t) + DEH_MAPPING("Sprite number", sprite) + DEH_MAPPING("Sprite subnumber", frame) + DEH_MAPPING("Duration", tics) + DEH_MAPPING("Next frame", nextstate) + DEH_UNSUPPORTED_MAPPING("Action pointer") +DEH_END_MAPPING + +static void *DEH_FrameStart(deh_context_t *context, char *line) +{ + int frame_number = 0; + state_t *state; + + if (sscanf(line, "Frame %i", &frame_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (frame_number < 0 || frame_number >= NUMSTATES) + { + DEH_Warning(context, "Invalid frame number: %i", frame_number); + return NULL; + } + + if (frame_number >= DEH_VANILLA_NUMSTATES) + { + DEH_Warning(context, "Attempt to modify frame %i: this will cause " + "problems in Vanilla dehacked.", frame_number); + } + + state = &states[frame_number]; + + return state; +} + +// Simulate a frame overflow: Doom has 967 frames in the states[] array, but +// DOS dehacked internally only allocates memory for 966. As a result, +// attempts to set frame 966 (the last frame) will overflow the dehacked +// array and overwrite the weaponinfo[] array instead. +// +// This is noticable in Batman Doom where it is impossible to switch weapons +// away from the fist once selected. + +static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value) +{ + if (!strcasecmp(varname, "Duration")) + { + weaponinfo[0].ammo = value; + } + else if (!strcasecmp(varname, "Codep frame")) + { + weaponinfo[0].upstate = value; + } + else if (!strcasecmp(varname, "Next frame")) + { + weaponinfo[0].downstate = value; + } + else if (!strcasecmp(varname, "Unknown 1")) + { + weaponinfo[0].readystate = value; + } + else if (!strcasecmp(varname, "Unknown 2")) + { + weaponinfo[0].atkstate = value; + } + else + { + DEH_Error(context, "Unable to simulate frame overflow: field '%s'", + varname); + } +} + +static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) +{ + state_t *state; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + state = (state_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + // all values are integers + + ivalue = atoi(value); + + if (state == &states[NUMSTATES - 1]) + { + DEH_FrameOverflow(context, variable_name, ivalue); + } + else + { + // set the appropriate field + + DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); + } +} + +static void DEH_FrameSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" +#include "deh_misc.h" + +// Dehacked: "Initial Health" +// This is the initial health a player has when starting anew. +// See G_PlayerReborn in g_game.c + +int deh_initial_health = DEH_DEFAULT_INITIAL_HEALTH; + +// Dehacked: "Initial bullets" +// This is the number of bullets the player has when starting anew. +// See G_PlayerReborn in g_game.c + +int deh_initial_bullets = DEH_DEFAULT_INITIAL_BULLETS; + +// Dehacked: "Max Health" +// This is the maximum health that can be reached using medikits +// alone. See P_TouchSpecialThing in p_inter.c + +int deh_max_health = DEH_DEFAULT_MAX_HEALTH; + +// Dehacked: "Max Armor" +// This is the maximum armor which can be reached by picking up +// armor helmets. See P_TouchSpecialThing in p_inter.c + +int deh_max_armor = DEH_DEFAULT_MAX_ARMOR; + +// Dehacked: "Green Armor Class" +// This is the armor class that is given when picking up the green +// armor or an armor helmet. See P_TouchSpecialThing in p_inter.c +// +// DOS dehacked only modifies the behavior of the green armor shirt, +// the armor class set by armor helmets is not affected. + +int deh_green_armor_class = DEH_DEFAULT_GREEN_ARMOR_CLASS; + +// Dehacked: "Blue Armor Class" +// This is the armor class that is given when picking up the blue +// armor or a megasphere. See P_TouchSpecialThing in p_inter.c +// +// DOS dehacked only modifies the MegaArmor behavior and not +// the MegaSphere, which always gives armor type 2. + +int deh_blue_armor_class = DEH_DEFAULT_BLUE_ARMOR_CLASS; + +// Dehacked: "Max soulsphere" +// The maximum health which can be reached by picking up the +// soulsphere. See P_TouchSpecialThing in p_inter.c + +int deh_max_soulsphere = DEH_DEFAULT_MAX_SOULSPHERE; + +// Dehacked: "Soulsphere health" +// The amount of health bonus that picking up a soulsphere +// gives. See P_TouchSpecialThing in p_inter.c + +int deh_soulsphere_health = DEH_DEFAULT_SOULSPHERE_HEALTH; + +// Dehacked: "Megasphere health" +// This is what the health is set to after picking up a +// megasphere. See P_TouchSpecialThing in p_inter.c + +int deh_megasphere_health = DEH_DEFAULT_MEGASPHERE_HEALTH; + +// Dehacked: "God mode health" +// This is what the health value is set to when cheating using +// the IDDQD god mode cheat. See ST_Responder in st_stuff.c + +int deh_god_mode_health = DEH_DEFAULT_GOD_MODE_HEALTH; + +// Dehacked: "IDFA Armor" +// This is what the armor is set to when using the IDFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idfa_armor = DEH_DEFAULT_IDFA_ARMOR; + +// Dehacked: "IDFA Armor Class" +// This is what the armor class is set to when using the IDFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idfa_armor_class = DEH_DEFAULT_IDFA_ARMOR_CLASS; + +// Dehacked: "IDKFA Armor" +// This is what the armor is set to when using the IDKFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idkfa_armor = DEH_DEFAULT_IDKFA_ARMOR; + +// Dehacked: "IDKFA Armor Class" +// This is what the armor class is set to when using the IDKFA cheat. +// See ST_Responder in st_stuff.c + +int deh_idkfa_armor_class = DEH_DEFAULT_IDKFA_ARMOR_CLASS; + +// Dehacked: "BFG Cells/Shot" +// This is the number of CELLs firing the BFG uses up. +// See P_CheckAmmo and A_FireBFG in p_pspr.c + +int deh_bfg_cells_per_shot = DEH_DEFAULT_BFG_CELLS_PER_SHOT; + +// Dehacked: "Monsters infight" +// This controls whether monsters can harm other monsters of the same +// species. For example, whether an imp fireball will damage other +// imps. The value of this in dehacked patches is weird - '202' means +// off, while '221' means on. +// +// See PIT_CheckThing in p_map.c + +int deh_species_infighting = DEH_DEFAULT_SPECIES_INFIGHTING; + +static struct +{ + const char *deh_name; + int *value; +} misc_settings[] = { + {"Initial Health", &deh_initial_health}, + {"Initial Bullets", &deh_initial_bullets}, + {"Max Health", &deh_max_health}, + {"Max Armor", &deh_max_armor}, + {"LeatherArmorClass", &deh_green_armor_class}, + {"Metal Armor Class", &deh_blue_armor_class}, + {"Max Soulsphere", &deh_max_soulsphere}, + {"Soulsphere Health", &deh_soulsphere_health}, + {"Megasphere Health", &deh_megasphere_health}, + {"God Mode Health", &deh_god_mode_health}, + {"IDFA Armor", &deh_idfa_armor}, + {"IDFA Armor Class", &deh_idfa_armor_class}, + {"IDKFA Armor", &deh_idkfa_armor}, + {"IDKFA Armor Class", &deh_idkfa_armor_class}, + {"Mauler Cells/Shot", &deh_bfg_cells_per_shot}, +}; + +static void *DEH_MiscStart(deh_context_t *context, char *line) +{ + return NULL; +} + +static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + int ivalue; + size_t i; + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + if (!strcasecmp(variable_name, "Monsters Infight")) + { + // See notes above. + + if (ivalue == 202) + { + deh_species_infighting = 0; + } + else if (ivalue == 221) + { + deh_species_infighting = 1; + } + else + { + DEH_Warning(context, + "Invalid value for 'Monsters Infight': %i", ivalue); + } + + return; + } + + for (i=0; i +#include +#include + +#include "doomtype.h" +#include "info.h" + +#include "deh_defs.h" +#include "deh_io.h" +#include "deh_main.h" + +static actionf_t codeptrs[NUMSTATES]; + +static int CodePointerIndex(actionf_t *ptr) +{ + int i; + + for (i=0; i= NUMSTATES) + { + DEH_Warning(context, "Invalid frame number: %i", frame_number); + return NULL; + } + + return &states[frame_number]; +} + +static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag) +{ + state_t *state; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + state = (state_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + DEH_Warning(context, "Failed to parse assignment"); + return; + } + +// printf("Set %s to %s for state\n", variable_name, value); + + // all values are integers + + ivalue = atoi(value); + + // set the appropriate field + + if (!strcasecmp(variable_name, "Codep frame")) + { + if (ivalue < 0 || ivalue >= NUMSTATES) + { + DEH_Warning(context, "Invalid state '%i'", ivalue); + } + else + { + state->action = codeptrs[ivalue]; + } + } + else + { + DEH_Warning(context, "Unknown variable name '%s'", variable_name); + } +} + +static void DEH_PointerSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" +#include "sounds.h" + +DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t) + DEH_UNSUPPORTED_MAPPING("Offset") + DEH_UNSUPPORTED_MAPPING("Zero/One") + DEH_MAPPING("Value", priority) + DEH_MAPPING("Zero 1", link) + DEH_MAPPING("Zero 2", pitch) + DEH_MAPPING("Zero 3", volume) + DEH_UNSUPPORTED_MAPPING("Zero 4") + DEH_MAPPING("Neg. One 1", usefulness) + DEH_MAPPING("Neg. One 2", lumpnum) +DEH_END_MAPPING + +static void *DEH_SoundStart(deh_context_t *context, char *line) +{ + int sound_number = 0; + + if (sscanf(line, "Sound %i", &sound_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (sound_number < 0 || sound_number >= NUMSFX) + { + DEH_Warning(context, "Invalid sound number: %i", sound_number); + return NULL; + } + + if (sound_number >= DEH_VANILLA_NUMSFX) + { + DEH_Warning(context, "Attempt to modify SFX %i. This will cause " + "problems in Vanilla dehacked.", sound_number); + } + + return &S_sfx[sound_number]; +} + +static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag) +{ + sfxinfo_t *sfx; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + sfx = (sfxinfo_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + // all values are integers + + ivalue = atoi(value); + + // Set the field value + + DEH_SetMapping(context, &sound_mapping, sfx, variable_name, ivalue); +} + +deh_section_t deh_section_sound = +{ + "Sound", + NULL, + DEH_SoundStart, + DEH_SoundParseLine, + NULL, + NULL, +}; + diff --git a/games/NXDoom/src/strife/deh_strife.c b/games/NXDoom/src/strife/deh_strife.c new file mode 100644 index 00000000000..76cb496c16f --- /dev/null +++ b/games/NXDoom/src/strife/deh_strife.c @@ -0,0 +1,47 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Top-level dehacked definitions for Strife dehacked (sehacked) +// + +#include +#include "deh_defs.h" +#include "deh_main.h" + +const char *deh_signatures[] = +{ + "Patch File for SeHackEd v0.4", + "Patch File for SeHackEd v0.3", + NULL +}; + + +// +// List of section types: +// + +deh_section_t *deh_section_types[] = +{ + &deh_section_ammo, + &deh_section_cheat, + &deh_section_frame, + &deh_section_misc, + &deh_section_pointer, + &deh_section_sound, + &deh_section_text, + &deh_section_thing, + &deh_section_weapon, + NULL +}; + diff --git a/games/NXDoom/src/strife/deh_thing.c b/games/NXDoom/src/strife/deh_thing.c new file mode 100644 index 00000000000..72b92642ede --- /dev/null +++ b/games/NXDoom/src/strife/deh_thing.c @@ -0,0 +1,132 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// Parses "Thing" sections in dehacked files +// + +#include +#include + +#include "doomtype.h" + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" + +#include "info.h" + +DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t) + DEH_MAPPING("ID #", doomednum) + DEH_MAPPING("Initial frame", spawnstate) + DEH_MAPPING("Hit points", spawnhealth) + DEH_MAPPING("First moving frame", seestate) + DEH_MAPPING("Alert sound", seesound) + DEH_MAPPING("Reaction time", reactiontime) + DEH_MAPPING("Attack sound", attacksound) + DEH_MAPPING("Injury frame", painstate) + DEH_MAPPING("Pain chance", painchance) + DEH_MAPPING("Pain sound", painsound) + DEH_MAPPING("Close attack frame", meleestate) + DEH_MAPPING("Far attack frame", missilestate) + DEH_MAPPING("Crash frame", crashstate) + DEH_MAPPING("Death frame", deathstate) + DEH_MAPPING("Exploding frame", xdeathstate) + DEH_MAPPING("Death sound", deathsound) + DEH_MAPPING("Speed", speed) + DEH_MAPPING("Width", radius) + DEH_MAPPING("Height", height) + DEH_MAPPING("Mass", mass) + DEH_MAPPING("Missile damage", damage) + DEH_MAPPING("Action sound", activesound) + DEH_MAPPING("Bits", flags) + DEH_UNSUPPORTED_MAPPING("Name pointer") +DEH_END_MAPPING + +static void *DEH_ThingStart(deh_context_t *context, char *line) +{ + int thing_number = 0; + mobjinfo_t *mobj; + + if (sscanf(line, "Thing %i", &thing_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + // dehacked files are indexed from 1 + --thing_number; + + if (thing_number < 0 || thing_number >= NUMMOBJTYPES) + { + DEH_Warning(context, "Invalid thing number: %i", thing_number); + return NULL; + } + + mobj = &mobjinfo[thing_number]; + + return mobj; +} + +static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) +{ + mobjinfo_t *mobj; + char *variable_name, *value; + int ivalue; + + if (tag == NULL) + return; + + mobj = (mobjinfo_t *) tag; + + // Parse the assignment + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + +// printf("Set %s to %s for mobj\n", variable_name, value); + + // all values are integers + + ivalue = atoi(value); + + // Set the field value + + DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); +} + +static void DEH_ThingSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include +#include + +#include "doomtype.h" + +#include "d_items.h" + +#include "deh_defs.h" +#include "deh_main.h" +#include "deh_mapping.h" + +DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t) + DEH_MAPPING("Ammo type", ammo) + DEH_MAPPING("Deselect frame", upstate) + DEH_MAPPING("Select frame", downstate) + DEH_MAPPING("Bobbing frame", readystate) + DEH_MAPPING("Shooting frame", atkstate) + DEH_MAPPING("Firing frame", flashstate) + DEH_UNSUPPORTED_MAPPING("? Unknown") +DEH_END_MAPPING + +static void *DEH_WeaponStart(deh_context_t *context, char *line) +{ + int weapon_number = 0; + + if (sscanf(line, "Weapon %i", &weapon_number) != 1) + { + DEH_Warning(context, "Parse error on section start"); + return NULL; + } + + if (weapon_number < 0 || weapon_number >= NUMWEAPONS) + { + DEH_Warning(context, "Invalid weapon number: %i", weapon_number); + return NULL; + } + + return &weaponinfo[weapon_number]; +} + +static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) +{ + char *variable_name, *value; + weaponinfo_t *weapon; + int ivalue; + + if (tag == NULL) + return; + + weapon = (weaponinfo_t *) tag; + + if (!DEH_ParseAssignment(line, &variable_name, &value)) + { + // Failed to parse + + DEH_Warning(context, "Failed to parse assignment"); + return; + } + + ivalue = atoi(value); + + DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); +} + +static void DEH_WeaponSHA1Sum(sha1_context_t *context) +{ + int i; + + for (i=0; i +#include + +#include "doomtype.h" +#include "i_timer.h" +#include "d_mode.h" + +// +// Global parameters/defines. +// +// DOOM version +// +// haleyjd 09/28/10: Replaced with Strife version +#define STRIFE_VERSION 101 + +// Version code for cph's longtics hack ("v1.91") +#define DOOM_191_VERSION 111 + + +// Maximum players for Strife: +#define MAXPLAYERS 8 + +// If rangecheck is undefined, +// most parameter validation debugging code will not be compiled +#define RANGECHECK + +// The current state of the game: whether we are +// playing, gazing at the intermission screen, +// the game final animation, or a demo. +typedef enum +{ + GS_LEVEL, + GS_UNKNOWN, + GS_FINALE, + GS_DEMOSCREEN, +} gamestate_t; + +typedef enum +{ + ga_nothing, + ga_loadlevel, + ga_newgame, + ga_loadgame, + ga_savegame, + ga_playdemo, + ga_completed, + ga_victory, + ga_worlddone, + ga_screenshot +} gameaction_t; + +// +// Difficulty/skill settings/filters. +// + +// Skill flags. +#define MTF_EASY 1 +#define MTF_NORMAL 2 +#define MTF_HARD 4 +// villsa [STRIFE] standing monsters +#define MTF_STAND 8 +// villsa [STRIFE] don't spawn in single player +#define MTF_NOTSINGLE 16 +// Deaf monsters/do not react to sound. +#define MTF_AMBUSH 32 +// villsa [STRIFE] friendly to players +#define MTF_FRIEND 64 +// villsa [STRIFE] TODO - identify +#define MTF_UNKNOWN1 128 +// villsa [STRIFE] thing is translucent - STRIFE-TODO: But how much? +#define MTF_TRANSLUCENT 256 +// villsa [STRIFE] thing is more - or less? - translucent - STRIFE-TODO +#define MTF_MVIS 512 +// villsa [STRIFE] TODO - identify +#define MTF_UNKNOWN2 1024 + + + +// +// Key cards. +// +// villsa [STRIFE] +typedef enum +{ + key_BaseKey, // 0 + key_GovsKey, // 1 + key_Passcard, // 2 + key_IDCard, // 3 + key_PrisonKey, // 4 + key_SeveredHand, // 5 + key_Power1Key, // 6 + key_Power2Key, // 7 + key_Power3Key, // 8 + key_GoldKey, // 9 + key_IDBadge, // 10 + key_SilverKey, // 11 + key_OracleKey, // 12 + key_MilitaryID, // 13 + key_OrderKey, // 14 + key_WarehouseKey, // 15 + key_BrassKey, // 16 + key_RedCrystalKey, // 17 + key_BlueCrystalKey, // 18 + key_ChapelKey, // 19 + key_CatacombKey, // 20 + key_SecurityKey, // 21 + key_CoreKey, // 22 + key_MaulerKey, // 23 + key_FactoryKey, // 24 + key_MineKey, // 25 + key_NewKey5, // 26 + + NUMCARDS // 27 +} card_t; + + + +// The defined weapons, +// including a marker indicating +// user has not changed weapon. +// villsa [STRIFE] +typedef enum +{ + wp_fist, + wp_elecbow, + wp_rifle, + wp_missile, + wp_hegrenade, + wp_flame, + wp_mauler, + wp_sigil, + wp_poisonbow, + wp_wpgrenade, + wp_torpedo, + + NUMWEAPONS, + + // No pending weapon change. + wp_nochange + +} weapontype_t; + + +// Ammunition types defined. +typedef enum +{ + am_bullets, + am_elecbolts, + am_poisonbolts, + am_cell, + am_missiles, + am_hegrenades, + am_wpgrenades, + + NUMAMMO, + + am_noammo // unlimited ammo + +} ammotype_t; + + +// Power up artifacts. +// villsa [STRIFE] +typedef enum +{ + pw_strength, + pw_invisibility, + pw_ironfeet, + pw_allmap, + pw_communicator, + pw_targeter, + NUMPOWERS + +} powertype_t; + +// villsa [STRIFE] +// quest numbers +typedef enum +{ // Hex Watcom Name player_t offset + tk_quest1, // 0x00000001 questflags & 1 0x4D + tk_quest2, // 0x00000002 questflags & 2 + tk_quest3, // 0x00000004 questflags & 4 + tk_quest4, // 0x00000008 questflags & 8 + tk_quest5, // 0x00000010 questflags & 10h + tk_quest6, // 0x00000020 questflags & 20h + tk_quest7, // 0x00000040 questflags & 40h + tk_quest8, // 0x00000080 questflags & 80h + tk_quest9, // 0x00000100 BYTE1(questflags) & 1 0x4E + tk_quest10, // 0x00000200 BYTE1(questflags) & 2 + tk_quest11, // 0x00000400 BYTE1(questflags) & 4 + tk_quest12, // 0x00000800 BYTE1(questflags) & 8 + tk_quest13, // 0x00001000 BYTE1(questflags) & 10h + tk_quest14, // 0x00002000 BYTE1(questflags) & 20h + tk_quest15, // 0x00004000 BYTE1(questflags) & 40h + tk_quest16, // 0x00008000 BYTE1(questflags) & 80h + tk_quest17, // 0x00010000 BYTE2(questflags) & 1 0x4F + tk_quest18, // 0x00020000 BYTE2(questflags) & 2 + tk_quest19, // 0x00040000 BYTE2(questflags) & 4 + tk_quest20, // 0x00080000 BYTE2(questflags) & 8 + tk_quest21, // 0x00100000 BYTE2(questflags) & 10h + tk_quest22, // 0x00200000 BYTE2(questflags) & 20h + tk_quest23, // 0x00400000 BYTE2(questflags) & 40h + tk_quest24, // 0x00800000 BYTE2(questflags) & 80h + tk_quest25, // 0x01000000 BYTE3(questflags) & 1 0x50 + tk_quest26, // 0x02000000 BYTE3(questflags) & 2 + tk_quest27, // 0x04000000 BYTE3(questflags) & 4 + tk_quest28, // 0x08000000 BYTE3(questflags) & 8 + tk_quest29, // 0x10000000 BYTE3(questflags) & 10h + tk_quest30, // 0x20000000 BYTE3(questflags) & 20h + tk_quest31, // 0x40000000 BYTE3(questflags) & 40h + tk_quest32, // most likely unused + tk_numquests +} questtype_t; + +// haleyjd 09/12/10: [STRIFE] +// flag values for each quest. +enum +{ // Name Flag from bitnum Purpose, if known + QF_QUEST1 = (1 << tk_quest1), // Obtained Beldin's ring + QF_QUEST2 = (1 << tk_quest2), // Stole the Chalice + QF_QUEST3 = (1 << tk_quest3), // Permission to visit Irale (visited Macil) + QF_QUEST4 = (1 << tk_quest4), // Accepted Gov. Mourel's "messy" chore + QF_QUEST5 = (1 << tk_quest5), // Accepted Gov. Mourel's "bloody" chore + QF_QUEST6 = (1 << tk_quest6), // Destroyed the Power Coupling + QF_QUEST7 = (1 << tk_quest7), // Killed Blue Acolytes ("Scanning Team") + QF_QUEST8 = (1 << tk_quest8), // Unused; formerly, picked up Broken Coupling + QF_QUEST9 = (1 << tk_quest9), // Obtained Derwin's ear + QF_QUEST10 = (1 << tk_quest10), // Obtained Prison Pass + QF_QUEST11 = (1 << tk_quest11), // Obtained Prison Key + QF_QUEST12 = (1 << tk_quest12), // Obtained Judge Wolenick's hand + QF_QUEST13 = (1 << tk_quest13), // Freed the Prisoners + QF_QUEST14 = (1 << tk_quest14), // Destroyed the Power Crystal + QF_QUEST15 = (1 << tk_quest15), // Obtained Guard Uniform + QF_QUEST16 = (1 << tk_quest16), // Destroyed the Gate Mechanism + QF_QUEST17 = (1 << tk_quest17), // Heard Macil's story about the Sigil (MAP10) + QF_QUEST18 = (1 << tk_quest18), // Obtained Oracle Pass + QF_QUEST19 = (1 << tk_quest19), + QF_QUEST20 = (1 << tk_quest20), + QF_QUEST21 = (1 << tk_quest21), // Killed Bishop + QF_QUEST22 = (1 << tk_quest22), // Killed Oracle with QUEST21 set + QF_QUEST23 = (1 << tk_quest23), // Killed Oracle (always given) + QF_QUEST24 = (1 << tk_quest24), // Killed Macil + QF_QUEST25 = (1 << tk_quest25), // Destroyed the Converter + QF_QUEST26 = (1 << tk_quest26), // Killed Loremaster + QF_QUEST27 = (1 << tk_quest27), // Destroyed the Computer (checked for good ending) + QF_QUEST28 = (1 << tk_quest28), // Obtained Catacomb Key (checked by line type 228) + QF_QUEST29 = (1 << tk_quest29), // Destroyed the Mines Transmitter + QF_QUEST30 = (1 << tk_quest30), + QF_QUEST31 = (1 << tk_quest31), + QF_QUEST32 = (1U << tk_quest32), // Unused; BUG: Broken Coupling accidentally sets it. + + QF_ALLQUESTS = (QF_QUEST31 + (QF_QUEST31 - 1)) // does not include bit 32! +}; + +// +// Power up durations, +// how many seconds till expiration, +// assuming TICRATE is 35 ticks/second. +// +typedef enum +{ + INVISTICS = (55*TICRATE), // villsa [STRIFE] changed from 60 to 55 + IRONTICS = (80*TICRATE), // villsa [STRIFE] changed from 60 to 80 + PMUPTICS = (80*TICRATE), // villsa [STRIFE] + TARGTICS = (160*TICRATE),// villsa [STRIFE] + +} powerduration_t; + +#endif // __DOOMDEF__ diff --git a/games/NXDoom/src/strife/doomstat.c b/games/NXDoom/src/strife/doomstat.c new file mode 100644 index 00000000000..7f3116b5c99 --- /dev/null +++ b/games/NXDoom/src/strife/doomstat.c @@ -0,0 +1,35 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Put all global tate variables here. +// + +#include + +#include "doomstat.h" + + +// Game Mode - identify IWAD as shareware, retail etc. +GameMode_t gamemode = indetermined; +GameMission_t gamemission = doom; +GameVersion_t gameversion = exe_strife_1_31; +const char *gamedescription; + +// Set if homebrew PWAD stuff has been added. +boolean modifiedgame; + + + + diff --git a/games/NXDoom/src/strife/doomstat.h b/games/NXDoom/src/strife/doomstat.h new file mode 100644 index 00000000000..4be2435b134 --- /dev/null +++ b/games/NXDoom/src/strife/doomstat.h @@ -0,0 +1,281 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// All the global variables that store the internal state. +// Theoretically speaking, the internal state of the engine +// should be found by looking at the variables collected +// here, and every relevant module will have to include +// this header file. +// In practice, things are a bit messy. +// + + +#ifndef __D_STATE__ +#define __D_STATE__ + +// We need globally shared data structures, +// for defining the global state variables. +#include "doomdata.h" +#include "d_loop.h" + +// We need the playr data structure as well. +#include "d_player.h" + +// Game mode/mission +#include "d_mode.h" + +#include "net_defs.h" + + + +// ------------------------ +// Command line parameters. +// +extern boolean nomonsters; // checkparm of -nomonsters +extern boolean respawnparm; // checkparm of -respawn +extern boolean fastparm; // checkparm of -fast +extern boolean randomparm; // [STRIFE] checkparm of -random +extern boolean flipparm; // [STRIFE] checkparm of -flip + +extern boolean devparm; // DEBUG: launched with -devparm + + +// ----------------------------------------------------- +// Game Mode - identify IWAD as shareware, retail etc. +// +extern GameMode_t gamemode; +extern GameMission_t gamemission; +extern GameVersion_t gameversion; +extern const char *gamedescription; + +// Set if homebrew PWAD stuff has been added. +extern boolean modifiedgame; + + +// ------------------------------------------- +// Selected skill type, map etc. +// + +// Defaults for menu, methinks. +extern skill_t startskill; +extern int startepisode; +extern int startmap; + +// Savegame slot to load on startup. This is the value provided to +// the -loadgame option. If this has not been provided, this is -1. + +extern int startloadgame; + +extern boolean autostart; + +// Selected by user. +extern skill_t gameskill; +extern int gameepisode; +extern int gamemap; + +// If non-zero, exit the level after this number of minutes +extern int timelimit; + +// Nightmare mode flag, single player. +extern boolean respawnmonsters; + +// Netgame? Only true if >1 player. +extern boolean netgame; + +// 0=Co-op; 1=Deathmatch; 2=Altdeath +extern int deathmatch; + +// ------------------------- +// Internal parameters for sound rendering. +// These have been taken from the DOS version, +// but are not (yet) supported with Linux +// (e.g. no sound volume adjustment with menu. + +// From m_menu.c: +// Sound FX volume has default, 0 - 15 +// Music volume has default, 0 - 15 +// These are multiplied by 8. +extern int sfxVolume; +extern int musicVolume; +extern int voiceVolume; // haleyjd 08/29/10: [STRIFE] + +// Current music/sfx card - index useless +// w/o a reference LUT in a sound module. +// Ideally, this would use indices found +// in: /usr/include/linux/soundcard.h +extern int snd_MusicDevice; +extern int snd_SfxDevice; +// Config file? Same disclaimer as above. +extern int snd_DesiredMusicDevice; +extern int snd_DesiredSfxDevice; + + +// ------------------------- +// Status flags for refresh. +// + +// Depending on view size - no status bar? +// Note that there is no way to disable the +// status bar explicitely. +extern boolean statusbaractive; + +extern boolean automapactive; // In AutoMap mode? +extern boolean menuactive; // Menu overlayed? +extern boolean menupause; // haleyjd 08/29/10: [STRIFE] +extern int menupausetime; // haleyjd 09/04/10: [STRIFE] +extern boolean menuindialog; // haleyjd: ditto +extern boolean paused; // Game Pause? + + +extern boolean viewactive; + +extern boolean nodrawers; + +extern boolean testcontrols; +extern int testcontrols_mousespeed; + + + + +// This one is related to the 3-screen display mode. +// ANG90 = left side, ANG270 = right +extern int viewangleoffset; + +// Player taking events, and displaying. +extern int consoleplayer; +extern int displayplayer; + + +// ------------------------------------- +// Scores, rating. +// Statistics on a given map, for intermission. +// +extern int totalkills; +//extern int totalitems; [STRIFE] unused +extern int totalsecret; + +// Timer, for scores. +extern int levelstarttic; // gametic at level start +extern int leveltime; // tics in game play for par + + + +// -------------------------------------- +// DEMO playback/recording related stuff. +// No demo, there is a human player in charge? +// Disable save/end game? +extern boolean usergame; + +//? +extern boolean demoplayback; +extern boolean demorecording; +extern int mouse_fire_countdown; // villsa [STRIFE] +extern int joystick_fire_countdown; + +extern fixed_t forwardmove[2]; +extern fixed_t sidemove[2]; + +// Round angleturn in ticcmds to the nearest 256. This is used when +// recording Vanilla demos in netgames. + +extern boolean lowres_turn; + +// Quit after playing a demo from cmdline. +extern boolean singledemo; + + + + +//? +extern gamestate_t gamestate; + + + + + + +//----------------------------- +// Internal parameters, fixed. +// These are set by the engine, and not changed +// according to user inputs. Partly load from +// WAD, partly set at startup time. + + +// Bookkeeping on players - state. +extern player_t players[MAXPLAYERS]; + +// Alive? Disconnected? +extern boolean playeringame[MAXPLAYERS]; + + +// Player spawn spots for deathmatch. +#define MAX_DM_STARTS 10 +extern mapthing_t deathmatchstarts[MAX_DM_STARTS]; +extern mapthing_t* deathmatch_p; + +// Player spawn spots. +extern mapthing_t playerstarts[MAXPLAYERS]; + +// haleyjd 08/24/10: [STRIFE] rift spots +#define MAXRIFTSPOTS 16 +extern mapthing_t riftSpots[MAXRIFTSPOTS]; + +// Intermission stats. +// Parameters for world map / intermission. +extern wbstartstruct_t wminfo; + + + + + + +//----------------------------------------- +// Internal parameters, used for engine. +// + +// File handling stuff. +extern char * savegamedir; + +// if true, load all graphics at level load +extern boolean precache; + + +// wipegamestate can be set to -1 +// to force a wipe on the next draw +extern gamestate_t wipegamestate; + +extern int mouseSensitivity; + +//extern int bodyqueslot; [STRIFE] unused + + + +// Needed to store the number of the dummy sky flat. +// Used for rendering, +// as well as tracking projectiles etc. +extern int skyflatnum; + + + +// Netgame stuff (buffers and pointers, i.e. indices). + + +extern int rndindex; + +extern ticcmd_t *netcmds; + + + +#endif diff --git a/games/NXDoom/src/strife/dstrings.c b/games/NXDoom/src/strife/dstrings.c new file mode 100644 index 00000000000..86433ab280f --- /dev/null +++ b/games/NXDoom/src/strife/dstrings.c @@ -0,0 +1,73 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Globally defined strings. +// + + + +#include "dstrings.h" + +const char *doom1_endmsg[] = +{ + "are you sure you want to\nquit this great game?", + "please don't leave, there's more\ndemons to toast!", + "let's beat it -- this is turning\ninto a bloodbath!", + "i wouldn't leave if i were you.\ndos is much worse.", + "you're trying to say you like dos\nbetter than me, right?", + "don't leave yet -- there's a\ndemon around that corner!", + "ya know, next time you come in here\ni'm gonna toast ya.", + "go ahead and leave. see if i care.", +}; + +const char *doom2_endmsg[] = +{ + // QuitDOOM II messages + "are you sure you want to\nquit this great game?", + "you want to quit?\nthen, thou hast lost an eighth!", + "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!", + "get outta here and go back\nto your boring programs.", + "if i were your boss, i'd \n deathmatch ya in a minute!", + "look, bud. you leave now\nand you forfeit your body count!", + "just leave. when you come\nback, i'll be waiting with a bat.", + "you're lucky i don't smack\nyou for thinking about leaving.", +}; + +#if 0 + +// UNUSED messages included in the source release + +char* endmsg[] = +{ + // DOOM1 + QUITMSG, + // FinalDOOM? + "fuck you, pussy!\nget the fuck out!", + "you quit and i'll jizz\nin your cystholes!", + "if you leave, i'll make\nthe lord drink my jizz.", + "hey, ron! can we say\n'fuck' in the game?", + "i'd leave: this is just\nmore monsters and levels.\nwhat a load.", + "suck it down, asshole!\nyou're a fucking wimp!", + "don't quit now! we're \nstill spending your money!", + + // Internal debug. Different style, too. + "THIS IS NO MESSAGE!\nPage intentionally left blank." +}; + +#endif + + + + diff --git a/games/NXDoom/src/strife/dstrings.h b/games/NXDoom/src/strife/dstrings.h new file mode 100644 index 00000000000..81115792a29 --- /dev/null +++ b/games/NXDoom/src/strife/dstrings.h @@ -0,0 +1,41 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: +// DOOM strings, by language. +// + + +#ifndef __DSTRINGS__ +#define __DSTRINGS__ + + +// All important printed strings. + +#include "d_englsh.h" + +// Misc. other strings. +#define SAVEGAMENAME "doomsav" + + +// QuitDOOM messages +// 8 per each game type +#define NUM_QUITMESSAGES 8 + +extern const char *doom1_endmsg[]; +extern const char *doom2_endmsg[]; + + +#endif diff --git a/games/NXDoom/src/strife/f_finale.c b/games/NXDoom/src/strife/f_finale.c new file mode 100644 index 00000000000..a6d139938ab --- /dev/null +++ b/games/NXDoom/src/strife/f_finale.c @@ -0,0 +1,1047 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// Copyright(C) 2010 James Haley, Samuel Villarreal +// +// 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. +// +// DESCRIPTION: +// Game completion, final screen animation. +// +// [STRIFE] Module marked finished 2010-09-13 22:56 +// + + +#include +#include + +// Functions. +#include "deh_main.h" +#include "i_system.h" +#include "i_swap.h" +#include "z_zone.h" +#include "v_video.h" +#include "w_wad.h" +#include "s_sound.h" + +// Data. +#include "d_main.h" +#include "dstrings.h" +#include "sounds.h" + +#include "doomstat.h" +#include "r_state.h" + +#include "p_dialog.h" // [STRIFE] + +typedef enum +{ + F_STAGE_TEXT, + F_STAGE_ARTSCREEN, + F_STAGE_CAST, +} finalestage_t; + +// ? +//#include "doomstat.h" +//#include "r_local.h" +//#include "f_finale.h" + +// Stage of animation: +finalestage_t finalestage; + +unsigned int finalecount; + +// haleyjd 09/12/10: [STRIFE] Slideshow variables +const char *slideshow_panel; +unsigned int slideshow_tics; +int slideshow_state; + +// haleyjd 09/13/10: [STRIFE] All this is unused. +/* +#define TEXTSPEED 3 +#define TEXTWAIT 250 + +typedef struct +{ + GameMission_t mission; + int episode, level; + char *background; + char *text; +} textscreen_t; + +static textscreen_t textscreens[] = +{ + { doom, 1, 8, "FLOOR4_8", E1TEXT}, + { doom, 2, 8, "SFLR6_1", E2TEXT}, + { doom, 3, 8, "MFLR8_4", E3TEXT}, + { doom, 4, 8, "MFLR8_3", E4TEXT}, + + { doom2, 1, 6, "SLIME16", C1TEXT}, + { doom2, 1, 11, "RROCK14", C2TEXT}, + { doom2, 1, 20, "RROCK07", C3TEXT}, + { doom2, 1, 30, "RROCK17", C4TEXT}, + { doom2, 1, 15, "RROCK13", C5TEXT}, + { doom2, 1, 31, "RROCK19", C6TEXT}, + + { pack_tnt, 1, 6, "SLIME16", T1TEXT}, + { pack_tnt, 1, 11, "RROCK14", T2TEXT}, + { pack_tnt, 1, 20, "RROCK07", T3TEXT}, + { pack_tnt, 1, 30, "RROCK17", T4TEXT}, + { pack_tnt, 1, 15, "RROCK13", T5TEXT}, + { pack_tnt, 1, 31, "RROCK19", T6TEXT}, + + { pack_plut, 1, 6, "SLIME16", P1TEXT}, + { pack_plut, 1, 11, "RROCK14", P2TEXT}, + { pack_plut, 1, 20, "RROCK07", P3TEXT}, + { pack_plut, 1, 30, "RROCK17", P4TEXT}, + { pack_plut, 1, 15, "RROCK13", P5TEXT}, + { pack_plut, 1, 31, "RROCK19", P6TEXT}, +}; + +char* finaletext; +char* finaleflat; +*/ + +void F_StartCast (void); +void F_CastTicker (void); +boolean F_CastResponder (event_t *ev); +void F_CastDrawer (void); + +// [STRIFE] - Slideshow states enumeration +enum +{ + // Exit states + SLIDE_EXITHACK = -99, // Hacky exit - start a new dialog + SLIDE_HACKHACK = -9, // Bizarre unused state + SLIDE_EXIT = -1, // Exit to next finale state + SLIDE_CHOCO = -2, // haleyjd: This state is Choco-specific... see below. + + // Unknown + SLIDE_UNKNOWN = 0, // Dunno what it's for, possibly unused + + // MAP03 - Macil's Programmer exposition + SLIDE_PROGRAMMER1 = 1, + SLIDE_PROGRAMMER2, + SLIDE_PROGRAMMER3, + SLIDE_PROGRAMMER4, // Next state = -99 + + // MAP10 - Macil's Sigil exposition + SLIDE_SIGIL1 = 5, + SLIDE_SIGIL2, + SLIDE_SIGIL3, + SLIDE_SIGIL4, // Next state = -99 + + // MAP29 - Endings + // Good Ending + SLIDE_GOODEND1 = 10, + SLIDE_GOODEND2, + SLIDE_GOODEND3, + SLIDE_GOODEND4, // Next state = -1 + + // Bad Ending + SLIDE_BADEND1 = 14, + SLIDE_BADEND2, + SLIDE_BADEND3, // Next state = -1 + + // Blah Ending + SLIDE_BLAHEND1 = 17, + SLIDE_BLAHEND2, + SLIDE_BLAHEND3, // Next state = -1 + + // Demo Ending - haleyjd 20130301: v1.31 only + SLIDE_DEMOEND1 = 25, + SLIDE_DEMOEND2 // Next state = -1 +}; + +// +// F_StartFinale +// +// [STRIFE] +// haleyjd 09/13/10: Modified to drive slideshow sequences. +// +void F_StartFinale (void) +{ +#if 0 + // haleyjd 20111006: see below... + patch_t *panel; +#endif + + gameaction = ga_nothing; + gamestate = GS_FINALE; + viewactive = false; + automapactive = false; + wipegamestate = -1; // [STRIFE] + + // [STRIFE] Setup the slide show + slideshow_panel = DEH_String("PANEL0"); + + // haleyjd 20111006: These two lines of code *are* in vanilla Strife; + // however, there, they were completely inconsequential due to the dirty + // rects system. No intervening V_MarkRect call means PANEL0 was never + // drawn to the framebuffer. In Chocolate Strife, however, with no such + // system in place, this only manages to fuck up the fade-out that is + // supposed to happen at the beginning of all finales. So, don't do it! +#if 0 + panel = (patch_t *)W_CacheLumpName(slideshow_panel, PU_CACHE); + V_DrawPatch(0, 0, panel); +#endif + + switch(gamemap) + { + case 3: // Macil's exposition on the Programmer + slideshow_state = SLIDE_PROGRAMMER1; + break; + case 9: // Super hack for death of Programmer + slideshow_state = SLIDE_EXITHACK; + break; + case 10: // Macil's exposition on the Sigil + slideshow_state = SLIDE_SIGIL1; + break; + case 29: // Endings + if(!netgame) + { + if(players[0].health <= 0) // Bad ending + slideshow_state = SLIDE_BADEND1; // - Humanity goes extinct + else + { + if((players[0].questflags & QF_QUEST25) && // Converter destroyed + (players[0].questflags & QF_QUEST27)) // Computer destroyed (wtf?!) + { + // Good ending - You get the hot babe. + slideshow_state = SLIDE_GOODEND1; + } + else + { + // Blah ending - You win the battle, but fail at life. + slideshow_state = SLIDE_BLAHEND1; + } + } + } + break; + case 34: // For the demo version ending + slideshow_state = SLIDE_EXIT; + + // haleyjd 20130301: Somebody noticed the demo levels were missing the + // ending they used to have in the demo version EXE, I guess. But the + // weird thing is, this will only trigger if you run with strife0.wad, + // and no released version thereof actually works with the 1.31 EXE + // due to differing dialog formats... was there to be an updated demo + // that never got released?! + if(gameversion == exe_strife_1_31 && isdemoversion) + slideshow_state = SLIDE_DEMOEND1; + break; + } + + S_ChangeMusic(mus_dark, 1); + slideshow_tics = 7; + finalestage = F_STAGE_TEXT; + finalecount = 0; +} + +// +// F_Responder +// +// [STRIFE] Verified unmodified +// +boolean F_Responder (event_t *event) +{ + if (finalestage == F_STAGE_CAST) + return F_CastResponder (event); + + return false; +} + +// +// F_WaitTicker +// +// [STRIFE] New function +// haleyjd 09/13/10: This is called from G_Ticker if gamestate is 1, but we +// have no idea for what it's supposed to be. It is unused. +// +void F_WaitTicker(void) +{ + if(++finalecount >= 250) + { + gamestate = GS_FINALE; + finalestage = 0; + finalecount = 0; + } +} + +// +// F_DoSlideShow +// +// [STRIFE] New function +// haleyjd 09/13/10: Handles slideshow states. Begging to be tabulated! +// +static void F_DoSlideShow(void) +{ + patch_t *patch; + + switch(slideshow_state) + { + case SLIDE_UNKNOWN: // state #0, seems to be unused + slideshow_tics = 700; + slideshow_state = SLIDE_EXIT; + // falls through into state 1, so above is pointless? ... + + case SLIDE_PROGRAMMER1: // state #1 + slideshow_panel = DEH_String("SS2F1"); + I_StartVoice(DEH_String("MAC10")); + slideshow_state = SLIDE_PROGRAMMER2; + slideshow_tics = 315; + break; + case SLIDE_PROGRAMMER2: // state #2 + slideshow_panel = DEH_String("SS2F2"); + I_StartVoice(DEH_String("MAC11")); + slideshow_state = SLIDE_PROGRAMMER3; + slideshow_tics = 350; + break; + case SLIDE_PROGRAMMER3: // state #3 + slideshow_panel = DEH_String("SS2F3"); + I_StartVoice(DEH_String("MAC12")); + slideshow_state = SLIDE_PROGRAMMER4; + slideshow_tics = 420; + break; + case SLIDE_PROGRAMMER4: // state #4 + slideshow_panel = DEH_String("SS2F4"); + I_StartVoice(DEH_String("MAC13")); + slideshow_state = SLIDE_EXITHACK; // End of slides + slideshow_tics = 595; + break; + + case SLIDE_SIGIL1: // state #5 + slideshow_panel = DEH_String("SS3F1"); + I_StartVoice(DEH_String("MAC16")); + slideshow_state = SLIDE_SIGIL2; + slideshow_tics = 350; + break; + case SLIDE_SIGIL2: // state #6 + slideshow_panel = DEH_String("SS3F2"); + I_StartVoice(DEH_String("MAC17")); + slideshow_state = SLIDE_SIGIL3; + slideshow_tics = 420; + break; + case SLIDE_SIGIL3: // state #7 + slideshow_panel = DEH_String("SS3F3"); + I_StartVoice(DEH_String("MAC18")); + slideshow_tics = 420; + slideshow_state = SLIDE_SIGIL4; + break; + case SLIDE_SIGIL4: // state #8 + slideshow_panel = DEH_String("SS3F4"); + I_StartVoice(DEH_String("MAC19")); + slideshow_tics = 385; + slideshow_state = SLIDE_EXITHACK; // End of slides + break; + + case SLIDE_GOODEND1: // state #10 + slideshow_panel = DEH_String("SS4F1"); + S_StartMusic(mus_happy); + I_StartVoice(DEH_String("RIE01")); + slideshow_state = SLIDE_GOODEND2; + slideshow_tics = 455; + break; + case SLIDE_GOODEND2: // state #11 + slideshow_panel = DEH_String("SS4F2"); + I_StartVoice(DEH_String("BBX01")); + slideshow_state = SLIDE_GOODEND3; + slideshow_tics = 385; + break; + case SLIDE_GOODEND3: // state #12 + slideshow_panel = DEH_String("SS4F3"); + I_StartVoice(DEH_String("BBX02")); + slideshow_state = SLIDE_GOODEND4; + slideshow_tics = 490; + break; + case SLIDE_GOODEND4: // state #13 + slideshow_panel = DEH_String("SS4F4"); + slideshow_state = SLIDE_EXIT; // Go to end credits + slideshow_tics = 980; + break; + + case SLIDE_BADEND1: // state #14 + S_StartMusic(mus_sad); + slideshow_panel = DEH_String("SS5F1"); + I_StartVoice(DEH_String("SS501b")); + slideshow_state = SLIDE_BADEND2; + slideshow_tics = 385; + break; + case SLIDE_BADEND2: // state #15 + slideshow_panel = DEH_String("SS5F2"); + I_StartVoice(DEH_String("SS502b")); + slideshow_state = SLIDE_BADEND3; + slideshow_tics = 350; + break; + case SLIDE_BADEND3: // state #16 + slideshow_panel = DEH_String("SS5F3"); + I_StartVoice(DEH_String("SS503b")); + slideshow_state = SLIDE_EXIT; // Go to end credits + slideshow_tics = 385; + break; + + case SLIDE_BLAHEND1: // state #17 + S_StartMusic(mus_end); + slideshow_panel = DEH_String("SS6F1"); + I_StartVoice(DEH_String("SS601A")); + slideshow_state = SLIDE_BLAHEND2; + slideshow_tics = 280; + break; + case SLIDE_BLAHEND2: // state #18 + S_StartMusic(mus_end); + slideshow_panel = DEH_String("SS6F2"); + I_StartVoice(DEH_String("SS602A")); + slideshow_state = SLIDE_BLAHEND3; + slideshow_tics = 280; + break; + case SLIDE_BLAHEND3: // state #19 + S_StartMusic(mus_end); + slideshow_panel = DEH_String("SS6F3"); + I_StartVoice(DEH_String("SS603A")); + slideshow_state = SLIDE_EXIT; // Go to credits + slideshow_tics = 315; + break; + + case SLIDE_DEMOEND1: // state #25 - only exists in 1.31 + slideshow_panel = DEH_String("PANEL7"); + slideshow_tics = 175; + slideshow_state = SLIDE_DEMOEND2; + break; + case SLIDE_DEMOEND2: // state #26 - ditto + slideshow_panel = DEH_String("VELLOGO"); + slideshow_tics = 175; + slideshow_state = SLIDE_EXIT; // Go to end credits + break; + + case SLIDE_EXITHACK: // state -99: super hack state + gamestate = GS_LEVEL; + P_DialogStartP1(); + break; + case SLIDE_HACKHACK: // state -9: unknown bizarre unused state + S_StartSound(NULL, sfx_rifle); + slideshow_tics = 3150; + break; + case SLIDE_EXIT: // state -1: proceed to next finale stage + finalecount = 0; + finalestage = F_STAGE_ARTSCREEN; + wipegamestate = -1; + S_StartMusic(mus_fast); + // haleyjd 20130301: The ONLY glitch fixed in 1.31 of Strife + // *would* be something this insignificant, of course! + if(gameversion != exe_strife_1_31) + slideshow_state = SLIDE_CHOCO; // haleyjd: see below... + break; + case SLIDE_CHOCO: + // haleyjd 09/14/10: This wouldn't be necessary except that Choco + // doesn't support the V_MarkRect dirty rectangles system. This + // just so happens to have hidden the fact that the ending + // does a screenfade every ~19 seconds due to remaining stuck in + // SLIDE_EXIT state above, UNLESS the menus were active - the + // V_MarkRect calls in the menu system cause it to be visible. + // This means that in order to get the same behavior as the vanilla + // EXE, I need different code. So, come to this state and only set + // wipegamestate if menuactive is true. + finalecount = 0; + finalestage = F_STAGE_ARTSCREEN; + if(menuactive) + wipegamestate = -1; + S_StartMusic(mus_fast); + slideshow_state = SLIDE_CHOCO; // remain here. + break; + default: + break; + } + + finalecount = 0; + if(gameversion != exe_strife_1_31) // See above. This was removed in 1.31. + { + patch = (patch_t *)W_CacheLumpName(DEH_String("PANEL0"), PU_CACHE); + V_DrawPatch(0, 0, patch); + } +} + +// +// F_Ticker +// +// [STRIFE] Modifications for new finales +// haleyjd 09/13/10: Calls F_DoSlideShow +// +void F_Ticker (void) +{ + size_t i; + + // check for skipping + if (finalecount > 50) // [STRIFE] No commercial check + { + // go on to the next level + for (i=0 ; i slideshow_tics) // [STRIFE] Advance slideshow + F_DoSlideShow(); + + // [STRIFE]: Rest is unused + /* + if ( gamemode == commercial) + return; + + if (finalestage == F_STAGE_TEXT + && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT) + { + finalecount = 0; + finalestage = F_STAGE_ARTSCREEN; + wipegamestate = -1; // force a wipe + if (gameepisode == 3) + S_StartMusic (mus_logo); + } + */ +} + +// haleyjd 09/13/10: Not present in Strife: Cast drawing functions + +#include "hu_stuff.h" + +/* +// +// F_TextWrite +// +void F_TextWrite (void) +{ + byte* src; + byte* dest; + + int x,y,w; + signed int count; + char* ch; + int c; + int cx; + int cy; + + // erase the entire screen to a tiled background + src = W_CacheLumpName ( finaleflat , PU_CACHE); + dest = I_VideoBuffer; + + for (y=0 ; y HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + if (cx+w > SCREENWIDTH) + break; + V_DrawPatch(cx, cy, hu_font[c]); + cx+=w; + } + +} +*/ + +// +// Final DOOM 2 animation +// Casting by id Software. +// in order of appearance +// +typedef struct +{ + int isindemo; // [STRIFE] Changed from name, which is in mobjinfo + mobjtype_t type; +} castinfo_t; + +// haleyjd: [STRIFE] A new cast order was defined, however it is unused in any +// of the released versions of Strife, even including the demo version :( +castinfo_t castorder[] = { + { 1, MT_PLAYER }, + { 1, MT_BEGGAR1 }, + { 1, MT_PEASANT2_A }, + { 1, MT_REBEL1 }, + { 1, MT_GUARD1 }, + { 1, MT_CRUSADER }, + { 1, MT_RLEADER2 }, + { 0, MT_SENTINEL }, + { 0, MT_STALKER }, + { 0, MT_PROGRAMMER }, + { 0, MT_REAVER }, + { 0, MT_PGUARD }, + { 0, MT_INQUISITOR }, + { 0, MT_PRIEST }, + { 0, MT_SPECTRE_A }, + { 0, MT_BISHOP }, + { 0, MT_ENTITY }, + { 1, NUMMOBJTYPES } +}; + +int castnum; +int casttics; +state_t* caststate; +boolean castdeath; +int castframes; +int castonmelee; +boolean castattacking; + +// +// F_StartCast +// +// haleyjd 09/13/10: [STRIFE] Heavily modified, yet unused. +// Evidence suggests this was meant to be started from a menu item. +// See m_menu.c for more info. +// +void F_StartCast (void) +{ + usergame = false; + gameaction = ga_nothing; + viewactive = false; + automapactive = false; + castnum = 0; + gamestate = GS_FINALE; + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + casttics = caststate->tics; + if(casttics > 50) + casttics = 50; + wipegamestate = -1; // force a screen wipe + castdeath = false; + finalestage = F_STAGE_CAST; + castframes = 0; + castonmelee = 0; + castattacking = false; +} + + +// +// F_CastTicker +// +// [STRIFE] Heavily modified, but unused. +// haleyjd 09/13/10: Yeah, I bothered translating this even though it isn't +// going to be seen, in part because I hope some Strife port or another will +// pick it up and finish it, adding it as the optional menu item it was +// meant to be, or just adding it as part of the ending sequence. +// +void F_CastTicker (void) +{ + int st; + + if (--casttics > 0) + return; // not time to change state yet + + if (caststate->tics == -1 || caststate->nextstate == S_NULL) + { + // switch from deathstate to next monster + castnum++; + castdeath = false; + if (isdemoversion) + { + // [STRIFE] Demo version had a shorter cast + if(!castorder[castnum].isindemo) + castnum = 0; + } + // [STRIFE] Break on type == NUMMOBJTYPES rather than name == NULL + if (castorder[castnum].type == NUMMOBJTYPES) + castnum = 0; + if (mobjinfo[castorder[castnum].type].seesound) + S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound); + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + castframes = 0; + } + else + { + int sfx = 0; + + // just advance to next state in animation + if (caststate == &states[S_PLAY_05]) // villsa [STRIFE] - updated + goto stopattack; // Oh, gross hack! + st = caststate->nextstate; + caststate = &states[st]; + castframes++; + + if (st != mobjinfo[castorder[castnum].type].meleestate && + st != mobjinfo[castorder[castnum].type].missilestate) + { + if (st == S_PLAY_05) + sfx = sfx_rifle; + else + sfx = 0; + } + else + sfx = mobjinfo[castorder[castnum].type].attacksound; + + if (sfx) + S_StartSound (NULL, sfx); + } + + if (!castdeath && castframes == 12) + { + // go into attack frame + castattacking = true; + if (castonmelee) + caststate=&states[mobjinfo[castorder[castnum].type].meleestate]; + else + caststate=&states[mobjinfo[castorder[castnum].type].missilestate]; + castonmelee ^= 1; + if (caststate == &states[S_NULL]) + { + if (castonmelee) + caststate = &states[mobjinfo[castorder[castnum].type].meleestate]; + else + caststate = &states[mobjinfo[castorder[castnum].type].missilestate]; + } + } + + if (castattacking) + { + if (castframes == 24 + || caststate == &states[mobjinfo[castorder[castnum].type].seestate] ) + { +stopattack: + castattacking = false; + castframes = 0; + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + } + } + + casttics = caststate->tics; + if (casttics > 50) // [STRIFE] Cap tics + casttics = 50; + else if (casttics == -1) + casttics = 15; +} + + +// +// F_CastResponder +// +// [STRIFE] This still exists in Strife but is never used. +// It was used at some point in development, however, as they made +// numerous modifications to the cast call system. +// +boolean F_CastResponder (event_t* ev) +{ + if (ev->type != ev_keydown) + return false; + + if (castdeath) + return true; // already in dying frames + + // go into death frame + castdeath = true; + caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; + casttics = caststate->tics; + if(casttics > 50) // [STRIFE] Upper bound on casttics + casttics = 50; + castframes = 0; + castattacking = false; + if (mobjinfo[castorder[castnum].type].deathsound) + S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound); + + return true; +} + +// +// F_CastPrint +// +// [STRIFE] Verified unmodified, and unused. +// +void F_CastPrint (char* text) +{ + char* ch; + int c; + int cx; + int w; + int width; + + // find width + ch = text; + width = 0; + + while (ch) + { + c = *ch++; + if (!c) + break; + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c> HU_FONTSIZE) + { + width += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + width += w; + } + + // draw it + cx = 160-width/2; + ch = text; + while (ch) + { + c = *ch++; + if (!c) + break; + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c> HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + V_DrawPatch(cx, 180, hu_font[c]); + cx+=w; + } + +} + +// haleyjd 09/13/10: [STRIFE] Unfortunately they removed whatever was +// partway finished of this function from the binary, as there is no +// trace of it. This means we cannot know for sure what the cast call +// would have looked like. :( +/* +// +// F_CastDrawer +// +void F_CastDrawer (void) +{ + spritedef_t* sprdef; + spriteframe_t* sprframe; + int lump; + boolean flip; + patch_t* patch; + + // erase the entire screen to a background + V_DrawPatch (0, 0, W_CacheLumpName (DEH_String("BOSSBACK"), PU_CACHE)); + + F_CastPrint (DEH_String(castorder[castnum].name)); + + // draw the current frame in the middle of the screen + sprdef = &sprites[caststate->sprite]; + sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK]; + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + + patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE); + if (flip) + V_DrawPatchFlipped(160, 170, patch); + else + V_DrawPatch(160, 170, patch); +} +*/ + +#ifdef STRIFE_DEMO_CODE +// +// F_DrawPatchCol +// +// [STRIFE] Verified unmodified, but not present in 1.2 +// It WAS present in the demo version, however... +// +void +F_DrawPatchCol +( int x, + patch_t* patch, + int col ) +{ + column_t* column; + byte* source; + byte* dest; + byte* desttop; + int count; + + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); + desttop = I_VideoBuffer + x; + + // step through the posts in a column + while (column->topdelta != 0xff ) + { + source = (byte *)column + 3; + dest = desttop + column->topdelta*SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = *source++; + dest += SCREENWIDTH; + } + column = (column_t *)( (byte *)column + column->length + 4 ); + } +} +#endif + +// +// F_DrawMap34End +// +// [STRIFE] Modified from F_BunnyScroll +// * In 1.2 and up this just causes a weird black screen. +// * In the demo version, it was an actual scroll between two screens. +// I have implemented both code segments, though only the black screen +// one will currently be used, as full demo version support isn't looking +// likely right now. +// +void F_DrawMap34End (void) +{ + signed int scrolled; + int x; +// patch_t* p1; +// patch_t* p2; + +// p1 = W_CacheLumpName (DEH_String("credit"), PU_LEVEL); +// p2 = W_CacheLumpName (DEH_String("vellogo"), PU_LEVEL); + + V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); + + + scrolled = (320 - ((signed int) finalecount-430)/2); + if (scrolled > 320) + scrolled = 320; + if (scrolled < 0) + scrolled = 0; + +#ifdef STRIFE_DEMO_CODE + for ( x=0 ; x + +#include "z_zone.h" +#include "i_video.h" +#include "v_video.h" +#include "m_random.h" + +#include "doomtype.h" + +#include "r_defs.h" // haleyjd [STRIFE] +#include "r_draw.h" + +#include "f_wipe.h" + +// +// SCREEN WIPE PACKAGE +// + +// when zero, stop the wipe +static boolean go = 0; + +static byte* wipe_scr_start; +static byte* wipe_scr_end; +static byte* wipe_scr; + + +void +wipe_shittyColMajorXform +( short* array, + int width, + int height ) +{ + int x; + int y; + short* dest; + + dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0); + + for(y=0;y 0; i--) + { + if(*cur_screen != *end_screen) + { + changed = true; + *cur_screen = xlatab[(*cur_screen << 8) + *end_screen]; + } + ++cur_screen; + ++end_screen; + } + + return !changed; +} + +// haleyjd 08/26/10: [STRIFE] Verified unmodified. +int +wipe_exitColorXForm +( int width, + int height, + int ticks ) +{ + return 0; +} + + +static int* y; + +int +wipe_initMelt +( int width, + int height, + int ticks ) +{ + int i, r; + + // copy start screen to main screen + memcpy(wipe_scr, wipe_scr_start, width*height); + + // makes this wipe faster (in theory) + // to have stuff in column-major format + wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height); + wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height); + + // setup initial column positions + // (y<0 => not ready to scroll yet) + y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0); + y[0] = -(M_Random()%16); + for (i=1;i 0) y[i] = 0; + else if (y[i] == -16) y[i] = -15; + } + + return 0; +} + +int +wipe_doMelt +( int width, + int height, + int ticks ) +{ + int i; + int j; + int dy; + int idx; + + short* s; + short* d; + boolean done = true; + + width/=2; + + while (ticks--) + { + for (i=0;i= height) dy = height - y[i]; + s = &((short *)wipe_scr_end)[i*height+y[i]]; + d = &((short *)wipe_scr)[y[i]*width+i]; + idx = 0; + for (j=dy;j;j--) + { + d[idx] = *(s++); + idx += width; + } + y[i] += dy; + s = &((short *)wipe_scr_start)[i*height]; + d = &((short *)wipe_scr)[y[i]*width+i]; + idx = 0; + for (j=height-y[i];j;j--) + { + d[idx] = *(s++); + idx += width; + } + done = false; + } + } + } + + return done; + +} + +int +wipe_exitMelt +( int width, + int height, + int ticks ) +{ + Z_Free(y); + Z_Free(wipe_scr_start); + Z_Free(wipe_scr_end); + return 0; +} + +// haleyjd 08/26/10: [STRIFE] Verified unmodified. +int +wipe_StartScreen +( int x, + int y, + int width, + int height ) +{ + wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); + I_ReadScreen(wipe_scr_start); + return 0; +} + +// haleyjd 08/26/10: [STRIFE] Verified unmodified. +int +wipe_EndScreen +( int x, + int y, + int width, + int height ) +{ + wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); + I_ReadScreen(wipe_scr_end); + V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr. + return 0; +} + +// haleyjd 08/26/10: [STRIFE] Verified unmodified. +int +wipe_ScreenWipe +( int wipeno, + int x, + int y, + int width, + int height, + int ticks ) +{ + int rc; + static int (*wipes[])(int, int, int) = + { + wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm, + wipe_initMelt, wipe_doMelt, wipe_exitMelt + }; + + // initial stuff + if (!go) + { + go = 1; + // haleyjd 20110629 [STRIFE]: We *must* use a temp buffer here. + wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG + //wipe_scr = I_VideoBuffer; + (*wipes[wipeno*3])(width, height, ticks); + } + + // do a piece of wipe-in + V_MarkRect(0, 0, width, height); + rc = (*wipes[wipeno*3+1])(width, height, ticks); + + // haleyjd 20110629 [STRIFE]: Copy temp buffer to the real screen. + V_DrawBlock(x, y, width, height, wipe_scr); + + // final stuff + if (rc) + { + go = 0; + (*wipes[wipeno*3+2])(width, height, ticks); + } + + return !go; +} + diff --git a/games/NXDoom/src/strife/f_wipe.h b/games/NXDoom/src/strife/f_wipe.h new file mode 100644 index 00000000000..6ffd05872a6 --- /dev/null +++ b/games/NXDoom/src/strife/f_wipe.h @@ -0,0 +1,63 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Mission start screen wipe/melt, special effects. +// + + +#ifndef __F_WIPE_H__ +#define __F_WIPE_H__ + +// +// SCREEN WIPE PACKAGE +// + +enum +{ + // [STRIFE]: ColorXForm reimplemented as a proper crossfade + wipe_ColorXForm, + + // weird screen melt + wipe_Melt, + + wipe_NUMWIPES +}; + +int +wipe_StartScreen +( int x, + int y, + int width, + int height ); + + +int +wipe_EndScreen +( int x, + int y, + int width, + int height ); + + +int +wipe_ScreenWipe +( int wipeno, + int x, + int y, + int width, + int height, + int ticks ); + +#endif diff --git a/games/NXDoom/src/strife/g_game.c b/games/NXDoom/src/strife/g_game.c new file mode 100644 index 00000000000..50faee1c845 --- /dev/null +++ b/games/NXDoom/src/strife/g_game.c @@ -0,0 +1,2534 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// + +#include +#include +#include + +#include "doomdef.h" +#include "doomkeys.h" +#include "doomstat.h" + +#include "deh_main.h" +#include "deh_misc.h" +#include "z_zone.h" +#include "f_finale.h" +#include "m_argv.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_menu.h" +#include "m_misc.h" +#include "m_saves.h" // STRIFE +#include "m_random.h" +#include "i_input.h" +#include "i_joystick.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "p_setup.h" +#include "p_saveg.h" +#include "p_tick.h" +#include "d_main.h" +#include "wi_stuff.h" +#include "hu_stuff.h" +#include "st_stuff.h" +#include "am_map.h" + +// Needs access to LFB. +#include "v_video.h" + +#include "w_wad.h" + +#include "p_local.h" + +#include "s_sound.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +// SKY handling - still the wrong place. +#include "r_data.h" +#include "r_sky.h" + +#include "p_dialog.h" // villsa [STRIFE] + +#include "g_game.h" + + +#define SAVEGAMESIZE 0x2c000 + +void G_ReadDemoTiccmd (ticcmd_t* cmd); +void G_WriteDemoTiccmd (ticcmd_t* cmd); +void G_PlayerReborn (int player); + +void G_DoReborn (int playernum); + +void G_DoLoadLevel (void); +void G_DoNewGame (void); +void G_DoPlayDemo (void); +void G_DoCompleted (void); +void G_DoVictory (void); +void G_DoWorldDone (void); +void G_DoSaveGame (char *path); + +// Gamestate the last time G_Ticker was called. + +gamestate_t oldgamestate; + +gameaction_t gameaction; +gamestate_t gamestate; +skill_t gameskill = 2; // [STRIFE] Default value set to 2. +boolean respawnmonsters; +//int gameepisode; +int gamemap; + +// haleyjd 08/24/10: [STRIFE] New variables +int destmap; // current destination map when exiting +int riftdest; // destination spot for player +angle_t riftangle; // player angle saved during exit + +// If non-zero, exit the level after this number of minutes. + +int timelimit; + +boolean paused; +boolean sendpause; // send a pause event next tic +boolean sendsave; // send a save event next tic +boolean usergame; // ok to save / end game + +boolean timingdemo; // if true, exit with report on completion +boolean nodrawers; // for comparative timing purposes +int starttime; // for comparative timing purposes + +boolean viewactive; + +int deathmatch; // only if started as net death +boolean netgame; // only true if packets are broadcast +boolean playeringame[MAXPLAYERS]; +player_t players[MAXPLAYERS]; + +boolean turbodetected[MAXPLAYERS]; + +int consoleplayer; // player taking events and displaying +int displayplayer; // view being displayed +int levelstarttic; // gametic at level start +int totalkills, /*totalitems,*/ totalsecret; // for intermission + +char *demoname; +boolean demorecording; +boolean longtics; // cph's doom 1.91 longtics hack +boolean lowres_turn; // low resolution turning for longtics +boolean demoplayback; +boolean netdemo; +byte* demobuffer; +byte* demo_p; +byte* demoend; +boolean singledemo; // quit after playing a demo from cmdline + +boolean precache = true; // if true, load all graphics at start + +boolean testcontrols = false; // Invoked by setup to test controls + +wbstartstruct_t wminfo; // parms for world map / intermission + +byte consistancy[MAXPLAYERS][BACKUPTICS]; + +#define MAXPLMOVE (forwardmove[1]) + +#define TURBOTHRESHOLD 0x32 + +fixed_t forwardmove[2] = {0x19, 0x32}; +fixed_t sidemove[2] = {0x18, 0x28}; +fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn + +int mouse_fire_countdown = 0; // villsa [STRIFE] +int joystick_fire_countdown = 0; + +static int *weapon_keys[] = { + &key_weapon1, + &key_weapon2, + &key_weapon3, + &key_weapon4, + &key_weapon5, + &key_weapon6, + &key_weapon7, + &key_weapon8 +}; + +// Set to -1 or +1 to switch to the previous or next weapon. + +static int next_weapon = 0; + +// Used for prev/next weapon keys. +// STRIFE-TODO: Check this table makes sense. + +static const struct +{ + weapontype_t weapon; + weapontype_t weapon_num; +} weapon_order_table[] = { + { wp_fist, wp_fist }, + { wp_poisonbow, wp_elecbow }, + { wp_elecbow, wp_elecbow }, + { wp_rifle, wp_rifle }, + { wp_missile, wp_missile }, + { wp_wpgrenade, wp_hegrenade }, + { wp_hegrenade, wp_hegrenade }, + { wp_flame, wp_flame }, + { wp_torpedo, wp_mauler }, + { wp_mauler, wp_mauler }, + { wp_sigil, wp_sigil }, +}; + +#define SLOWTURNTICS 6 + +#define NUMKEYS 256 +#define MAX_JOY_BUTTONS 20 + +static boolean gamekeydown[NUMKEYS]; +static int turnheld; // for accelerative turning + +static boolean mousearray[MAX_MOUSE_BUTTONS + 1]; +static boolean *mousebuttons = &mousearray[1]; // allow [-1] + +// mouse values are used once +int mousex; +int mousey; + +static int dclicktime; +static boolean dclickstate; +static int dclicks; +static int dclicktime2; +static boolean dclickstate2; +static int dclicks2; + +// joystick values are repeated +static int joyxmove; +static int joyymove; +static int joystrafemove; +static int joylook; +static boolean joyarray[MAX_JOY_BUTTONS + 1]; +static boolean *joybuttons = &joyarray[1]; // allow [-1] + +static int savegameslot = 6; // [STRIFE] initialized to 6 +static char savedescription[32]; + +int testcontrols_mousespeed; + +#define BODYQUESIZE 32 + +mobj_t* bodyque[BODYQUESIZE]; +//int bodyqueslot; [STRIFE] unused + +int vanilla_savegame_limit = 1; +int vanilla_demo_limit = 1; + + +int G_CmdChecksum (ticcmd_t* cmd) +{ + size_t i; + int sum = 0; + + for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++) + sum += ((int *)cmd)[i]; + + return sum; +} + +static boolean WeaponSelectable(weapontype_t weapon) +{ + player_t *player; + + player = &players[consoleplayer]; + + // Can't select a weapon if we don't own it. + + if (!player->weaponowned[weapon]) + { + return false; + } + + // Can't use registered-only weapons in demo mode: + + if (isdemoversion && !weaponinfo[weapon].availabledemo) + { + return false; + } + + // Special rules for switching to alternate versions of weapons. + // These must match the weapon-switching rules in P_PlayerThink() + + // haleyjd 20141024: same fix here as in P_PlayerThink for torpedo. + + if (weapon == wp_torpedo + && player->ammo[weaponinfo[wp_torpedo].ammo] < 30) + { + return false; + } + + if (player->ammo[weaponinfo[weapon].ammo] == 0) + { + return false; + } + + return true; +} + +static int G_NextWeapon(int direction) +{ + weapontype_t weapon; + int start_i, i; + + // Find index in the table. + + if (players[consoleplayer].pendingweapon == wp_nochange) + { + weapon = players[consoleplayer].readyweapon; + } + else + { + weapon = players[consoleplayer].pendingweapon; + } + + for (i=0; i= arrlen(weapon_order_table)) { + I_Error("Internal error: weapon %d not present in weapon_order_table", weapon); + } + + // Switch weapon. + start_i = i; + do + { + i += direction; + i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); + } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon)); + + return weapon_order_table[i].weapon_num; +} + +// +// G_BuildTiccmd +// Builds a ticcmd from all of the available inputs +// or reads it from the demo buffer. +// If recording a demo, write it out +// +void G_BuildTiccmd (ticcmd_t* cmd, int maketic) +{ + int i; + boolean strafe; + boolean bstrafe; + int speed; + int tspeed; + int forward; + int side; + + memset(cmd, 0, sizeof(ticcmd_t)); + + cmd->consistancy = + consistancy[consoleplayer][maketic%BACKUPTICS]; + + // villsa [STRIFE] look up key + if(gamekeydown[key_lookup] || (joylook < 0 && joystick_look_sensitivity)) + cmd->buttons2 |= BT2_LOOKUP; + + // villsa [STRIFE] look down key + if(gamekeydown[key_lookdown] || (joylook > 0 && joystick_look_sensitivity)) + cmd->buttons2 |= BT2_LOOKDOWN; + + // villsa [STRIFE] inventory use key + if(gamekeydown[key_invuse] || joybuttons[joybuseartifact]) + { + player_t* player = &players[consoleplayer]; + if(player->numinventory > 0) + { + cmd->buttons2 |= BT2_INVUSE; + cmd->inventory = player->inventory[player->inventorycursor].sprite; + } + } + + // villsa [STRIFE] inventory drop key + if(gamekeydown[key_invdrop]) + { + player_t* player = &players[consoleplayer]; + if(player->numinventory > 0) + { + cmd->buttons2 |= BT2_INVDROP; + cmd->inventory = player->inventory[player->inventorycursor].sprite; + } + } + + // villsa [STRIFE] use medkit + if(gamekeydown[key_usehealth]) + cmd->buttons2 |= BT2_HEALTH; + + + + strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] + || joybuttons[joybstrafe]; + + // fraggle: support the old "joyb_speed = 31" hack which + // allowed an autorun effect + + speed = key_speed >= NUMKEYS + || joybspeed >= MAX_JOY_BUTTONS + || gamekeydown[key_speed] + || joybuttons[joybspeed] + || mousebuttons[mousebspeed]; + + forward = side = 0; + + // villsa [STRIFE] running causes centerview to occur + if(speed) + cmd->buttons2 |= BT2_CENTERVIEW; + + // villsa [STRIFE] disable running if low on health + if (players[consoleplayer].health <= 15) + speed = 0; + + // use two stage accelerative turning + // on the keyboard and joystick + if (joyxmove < 0 + || joyxmove > 0 + || gamekeydown[key_right] + || gamekeydown[key_left] + || mousebuttons[mousebturnright] + || mousebuttons[mousebturnleft]) + turnheld += ticdup; + else + turnheld = 0; + + if (turnheld < SLOWTURNTICS) + tspeed = 2; // slow turn + else + tspeed = speed; + + // let movement keys cancel each other out + if (strafe) + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + { + // fprintf(stderr, "strafe right\n"); + side += sidemove[speed]; + } + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + { + // fprintf(stderr, "strafe left\n"); + side -= sidemove[speed]; + } + if (use_analog && joyxmove) + { + joyxmove = joyxmove * joystick_move_sensitivity / 10; + joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; + joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; + side += FixedMul(sidemove[speed], joyxmove); + } + else if (joystick_move_sensitivity) + { + if (joyxmove > 0) + side += sidemove[speed]; + if (joyxmove < 0) + side -= sidemove[speed]; + } + + } + else + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + cmd->angleturn -= angleturn[tspeed]; + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + cmd->angleturn += angleturn[tspeed]; + if (use_analog && joyxmove) + { + // Cubic response curve allows for finer control when stick + // deflection is small. + joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); + joyxmove = joyxmove * joystick_turn_sensitivity / 10; + cmd->angleturn -= FixedMul(angleturn[1], joyxmove); + } + else if (joystick_turn_sensitivity) + { + if (joyxmove > 0) + cmd->angleturn -= angleturn[tspeed]; + if (joyxmove < 0) + cmd->angleturn += angleturn[tspeed]; + } + } + + if (gamekeydown[key_up]) + { + // fprintf(stderr, "up\n"); + forward += forwardmove[speed]; + } + if (gamekeydown[key_down]) + { + // fprintf(stderr, "down\n"); + forward -= forwardmove[speed]; + } + + if (use_analog && joyymove) + { + joyymove = joyymove * joystick_move_sensitivity / 10; + joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; + joyymove = (joyymove < -FRACUNIT) ? FRACUNIT : joyymove; + forward -= FixedMul(forwardmove[speed], joyymove); + } + else if (joystick_move_sensitivity) + { + if (joyymove < 0) + forward += forwardmove[speed]; + if (joyymove > 0) + forward -= forwardmove[speed]; + } + + if (gamekeydown[key_strafeleft] + || joybuttons[joybstrafeleft] + || mousebuttons[mousebstrafeleft]) + { + side -= sidemove[speed]; + } + + if (gamekeydown[key_straferight] + || joybuttons[joybstraferight] + || mousebuttons[mousebstraferight]) + { + side += sidemove[speed]; + } + + if (use_analog && joystrafemove) + { + joystrafemove = joystrafemove * joystick_move_sensitivity / 10; + joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; + joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; + side += FixedMul(sidemove[speed], joystrafemove); + } + else if (joystick_move_sensitivity) + { + if (joystrafemove < 0) + side -= sidemove[speed]; + if (joystrafemove > 0) + side += sidemove[speed]; + } + // buttons + cmd->chatchar = HU_dequeueChatChar(); + + // villsa [STRIFE] - add mouse button support for jump + if (gamekeydown[key_jump] || mousebuttons[mousebjump] + || joybuttons[joybjump]) + cmd->buttons2 |= BT2_JUMP; + + // villsa [STRIFE]: Moved mousebuttons[mousebfire] to below + if (gamekeydown[key_fire]) + cmd->buttons |= BT_ATTACK; + + // villsa [STRIFE] + if(mousebuttons[mousebfire]) + { + if(mouse_fire_countdown <= 0) + cmd->buttons |= BT_ATTACK; + else + --mouse_fire_countdown; + } + if(joybuttons[joybfire]) + { + if(joystick_fire_countdown <= 0) + cmd->buttons |= BT_ATTACK; + else + --joystick_fire_countdown; + } + + if (gamekeydown[key_use] + || joybuttons[joybuse] + || mousebuttons[mousebuse]) + { + cmd->buttons |= BT_USE; + // clear double clicks if hit use button + dclicks = 0; + } + + // If the previous or next weapon button is pressed, the + // next_weapon variable is set to change weapons when + // we generate a ticcmd. Choose a new weapon. + + if (gamestate == GS_LEVEL && next_weapon != 0) + { + i = G_NextWeapon(next_weapon); + cmd->buttons |= BT_CHANGE; + cmd->buttons |= i << BT_WEAPONSHIFT; + } + else + { + // Check weapon keys. + + for (i=0; ibuttons |= BT_CHANGE; + cmd->buttons |= i< 1 ) + { + dclickstate = mousebuttons[mousebforward]; + if (dclickstate) + dclicks++; + if (dclicks == 2) + { + cmd->buttons |= BT_USE; + dclicks = 0; + } + else + dclicktime = 0; + } + else + { + dclicktime += ticdup; + if (dclicktime > 20) + { + dclicks = 0; + dclickstate = 0; + } + } + + // strafe double click + bstrafe = + mousebuttons[mousebstrafe] + || joybuttons[joybstrafe]; + if (bstrafe != dclickstate2 && dclicktime2 > 1 ) + { + dclickstate2 = bstrafe; + if (dclickstate2) + dclicks2++; + if (dclicks2 == 2) + { + cmd->buttons |= BT_USE; + dclicks2 = 0; + } + else + dclicktime2 = 0; + } + else + { + dclicktime2 += ticdup; + if (dclicktime2 > 20) + { + dclicks2 = 0; + dclickstate2 = 0; + } + } + } + + forward += mousey; + + if (strafe) + side += mousex*2; + else + cmd->angleturn -= mousex*0x8; + + if (mousex == 0) + { + // No movement in the previous frame + + testcontrols_mousespeed = 0; + } + + mousex = mousey = 0; + + if (forward > MAXPLMOVE) + forward = MAXPLMOVE; + else if (forward < -MAXPLMOVE) + forward = -MAXPLMOVE; + if (side > MAXPLMOVE) + side = MAXPLMOVE; + else if (side < -MAXPLMOVE) + side = -MAXPLMOVE; + + cmd->forwardmove += forward; + cmd->sidemove += side; + + // special buttons + if (sendpause) + { + sendpause = false; + cmd->buttons = BT_SPECIAL | BTS_PAUSE; + } + + if (sendsave) + { + sendsave = false; + cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<angleturn + carry; + + // round angleturn to the nearest 256 unit boundary + // for recording demos with single byte values for turn + + cmd->angleturn = (desired_angleturn + 128) & 0xff00; + + // Carry forward the error from the reduced resolution to the + // next tic, so that successive small movements can accumulate. + + carry = desired_angleturn - cmd->angleturn; + } +} + + +// +// G_DoLoadLevel +// +void G_DoLoadLevel (void) +{ + int i; + + // haleyjd 10/03/10: [STRIFE] This is not done here. + //skyflatnum = R_FlatNumForName(DEH_String(SKYFLATNAME)); + + levelstarttic = gametic; // for time calculation + + if (wipegamestate == GS_LEVEL) + wipegamestate = -1; // force a wipe + + gamestate = GS_LEVEL; + + for (i=0 ; iinventorycursor > 0) + player->inventorycursor--; + } + else if (i == joybinvright) + { + if (player->inventorycursor < player->numinventory - 1) + player->inventorycursor++; + } + } + + joybuttons[i] = button_on; + } +} + +static void SetMouseButtons(unsigned int buttons_mask) +{ + int i; + + for (i=0; itype == ev_keydown + && ev->data1 == key_spy && (singledemo || !gameskill) ) // [STRIFE]: o_O + { + // spy mode + do + { + displayplayer++; + if (displayplayer == MAXPLAYERS) + displayplayer = 0; + } while (!playeringame[displayplayer] && displayplayer != consoleplayer); + return true; + } + + // any other key pops up menu if in demos + if (gameaction == ga_nothing && !singledemo && + (demoplayback || gamestate == GS_DEMOSCREEN) + ) + { + if (ev->type == ev_keydown || + (ev->type == ev_mouse && ev->data1) || + (ev->type == ev_joystick && ev->data1) ) + { + if(devparm && ev->data1 == 'g') + D_PageTicker(); // [STRIFE]: wat? o_O + else + M_StartControlPanel (); + return true; + } + return false; + } + + if (gamestate == GS_LEVEL) + { +#if 0 + if (devparm && ev->type == ev_keydown && ev->data1 == ';') + { + G_DeathMatchSpawnPlayer (0); + return true; + } +#endif + if (HU_Responder (ev)) + return true; // chat ate the event + if (ST_Responder (ev)) + return true; // status window ate it + if (AM_Responder (ev)) + return true; // automap ate it + } + + if (gamestate == GS_FINALE) + { + if (F_Responder (ev)) + return true; // finale ate the event + } + + if (testcontrols && ev->type == ev_mouse) + { + // If we are invoked by setup to test the controls, save the + // mouse speed so that we can display it on-screen. + // Perform a low pass filter on this so that the thermometer + // appears to move smoothly. + + testcontrols_mousespeed = abs(ev->data2); + } + + // If the next/previous weapon keys are pressed, set the next_weapon + // variable to change weapons when the next ticcmd is generated. + + if (ev->type == ev_keydown && ev->data1 == key_prevweapon) + { + next_weapon = -1; + } + else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) + { + next_weapon = 1; + } + + switch (ev->type) + { + case ev_keydown: + if (ev->data1 == key_pause) + { + sendpause = true; + } + else if (ev->data1 data1] = true; + } + + return true; // eat key down events + + case ev_keyup: + if (ev->data1 data1] = false; + return false; // always let key up events filter down + + case ev_mouse: + SetMouseButtons(ev->data1); + mousex = ev->data2*(mouseSensitivity+5)/10; + mousey = ev->data3*(mouseSensitivity+5)/10; + return true; // eat events + + case ev_joystick: + SetJoyButtons(ev->data1); + joyxmove = ev->data2; + joyymove = ev->data3; + joystrafemove = ev->data4; + joylook = ev->data5; + return true; // eat events + + default: + break; + } + + return false; +} + +// +// G_Ticker +// Make ticcmd_ts for the players. +// +void G_Ticker (void) +{ + int i; + int buf; + ticcmd_t* cmd; + + // do player reborns if needed + for (i=0 ; iforwardmove > TURBOTHRESHOLD) + { + turbodetected[i] = true; + } + + if ((gametic & 31) == 0 + && ((gametic >> 5) % MAXPLAYERS) == i + && turbodetected[i]) + { + static char turbomessage[80]; + M_snprintf(turbomessage, sizeof(turbomessage), + "%s is turbo!", player_names[i]); + players[consoleplayer].message = turbomessage; + turbodetected[i] = false; + } + + if (netgame && !netdemo && !(gametic%ticdup) ) + { + if (gametic > BACKUPTICS + && consistancy[i][buf] != cmd->consistancy) + { + I_Error ("consistency failure (%i should be %i)", + cmd->consistancy, consistancy[i][buf]); + } + if (players[i].mo) + consistancy[i][buf] = players[i].mo->x; + else + consistancy[i][buf] = rndindex; + } + } + } + + // check for special buttons + for (i=0 ; i>BTS_SAVESHIFT; + gameaction = ga_savegame; + break; + } + } + } + } + + // Have we just finished displaying an intermission screen? + // haleyjd 08/23/10: [STRIFE] No intermission. + /* + if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION) + { + WI_End(); + } + */ + + oldgamestate = gamestate; + + // do main actions + switch (gamestate) + { + case GS_LEVEL: + P_Ticker (); + ST_Ticker (); + AM_Ticker (); + HU_Ticker (); + break; + + // haleyjd 08/23/10: [STRIFE] No intermission. + /* + case GS_INTERMISSION: + WI_Ticker (); + break; + */ + case GS_UNKNOWN: // STRIFE-TODO: What is this? is it ever used?? + F_WaitTicker(); + break; + + case GS_FINALE: + F_Ticker (); + break; + + case GS_DEMOSCREEN: + D_PageTicker (); + break; + } +} + + +// +// PLAYER STRUCTURE FUNCTIONS +// also see P_SpawnPlayer in P_Things +// + +// +// G_InitPlayer +// Called at the start. +// Called by the game initialization functions. +// +// [STRIFE] No such function. +/* +void G_InitPlayer (int player) +{ + player_t* p; + + // set up the saved info + p = &players[player]; + + // clear everything else to defaults + G_PlayerReborn (player); + +} +*/ + + +// +// G_PlayerFinishLevel +// Can when a player completes a level. +// +// [STRIFE] No such function. The equivalent to this logic was moved into +// G_DoCompleted. +/* +void G_PlayerFinishLevel (int player) +{ + player_t* p; + + p = &players[player]; + + memset (p->powers, 0, sizeof (p->powers)); + memset (p->cards, 0, sizeof (p->cards)); + p->mo->flags &= ~MF_SHADOW; // cancel invisibility + p->extralight = 0; // cancel gun flashes + p->fixedcolormap = 0; // cancel ir gogles + p->damagecount = 0; // no palette changes + p->bonuscount = 0; +} +*/ + +// +// G_PlayerReborn +// Called after a player dies +// almost everything is cleared and initialized +// +// [STRIFE] Small changes for allegiance, inventory, health auto-use, and +// mission objective. +// +void G_PlayerReborn (int player) +{ + player_t* p; + int i; + int frags[MAXPLAYERS]; + int killcount; + int allegiance; + + killcount = players[player].killcount; + allegiance = players[player].allegiance; // [STRIFE] + + memcpy(frags,players[player].frags,sizeof(frags)); + + p = &players[player]; + memset (p, 0, sizeof(*p)); + + memcpy(p->frags, frags, sizeof(p->frags)); + + p->usedown = true; // don't do anything immediately + p->attackdown = true; + p->inventorydown = true; // villsa [STRIFE] + p->playerstate = PST_LIVE; + p->health = deh_initial_health; // Use dehacked value + p->readyweapon = wp_fist; // villsa [STRIFE] default to fists + p->pendingweapon = wp_fist; // villsa [STRIFE] default to fists + p->weaponowned[wp_fist] = true; // villsa [STRIFE] default to fists + p->cheats |= CF_AUTOHEALTH; // villsa [STRIFE] + p->killcount = killcount; + p->allegiance = allegiance; // villsa [STRIFE] + p->centerview = true; // villsa [STRIFE] + + for(i = 0; i < NUMAMMO; i++) + p->maxammo[i] = maxammo[i]; + + // [STRIFE] clear inventory + for(i = 0; i < 32; i++) + p->inventory[i].type = NUMMOBJTYPES; + + // villsa [STRIFE]: Default objective + M_StringCopy(mission_objective, DEH_String("Find help"), + OBJECTIVE_LEN); +} + +// +// G_CheckSpot +// Returns false if the player cannot be respawned +// at the given mapthing_t spot +// because something is occupying it +// +// [STRIFE] Changed to eliminate body queue and an odd error message was added. +// +void P_SpawnPlayer (mapthing_t* mthing); + +boolean +G_CheckSpot +( int playernum, + mapthing_t* mthing ) +{ + fixed_t x; + fixed_t y; + subsector_t* ss; + unsigned an; + mobj_t* mo; + int i; + + if (!players[playernum].mo) + { + // [STRIFE] weird error message added here: + if(leveltime > 0) + players[playernum].message = DEH_String("you didn't have a body!"); + + // first spawn of level, before corpses + for (i=0 ; ix == mthing->x << FRACBITS + && players[i].mo->y == mthing->y << FRACBITS) + return false; + return true; + } + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + if (!P_CheckPosition (players[playernum].mo, x, y) ) + return false; + + // flush an old corpse if needed + // [STRIFE] player corpses remove themselves after a short time, so + // evidently this wasn't needed. + /* + if (bodyqueslot >= BODYQUESIZE) + P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); + bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; + bodyqueslot++; + */ + + // spawn a teleport fog + ss = R_PointInSubsector (x,y); + an = ( ANG45 * (((unsigned int) mthing->angle)/45) ) >> ANGLETOFINESHIFT; + + mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] + , ss->sector->floorheight + , MT_TFOG); + + if (players[consoleplayer].viewz != 1) + S_StartSound (mo, sfx_telept); // don't start sound on first frame + + return true; +} + + +// +// G_DeathMatchSpawnPlayer +// Spawns a player at one of the random death match spots +// called at level load and each death +// +// [STRIFE]: Modified exit message to match binary. +// +void G_DeathMatchSpawnPlayer (int playernum) +{ + int i,j; + int selections; + + selections = deathmatch_p - deathmatchstarts; + if (selections < 4) + I_Error ("Only %i deathmatch spots, at least 4 required!", selections); + + for (j=0 ; j<20 ; j++) + { + i = P_Random() % selections; + if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) + { + deathmatchstarts[i].type = playernum+1; + P_SpawnPlayer (&deathmatchstarts[i]); + return; + } + } + + // no good spot, so the player will probably get stuck + P_SpawnPlayer (&playerstarts[playernum]); +} + +// +// G_LoadPath +// +// haleyjd 20101003: [STRIFE] New function +// Sets loadpath based on the map and "savepathtemp" +// +void G_LoadPath(int map) +{ + char mapbuf[33]; + + memset(mapbuf, 0, sizeof(mapbuf)); + M_snprintf(mapbuf, sizeof(mapbuf), "%d", map); + + // haleyjd: free if already set, and use M_SafeFilePath + if(loadpath) + Z_Free(loadpath); + loadpath = M_SafeFilePath(savepathtemp, mapbuf); +} + +// +// G_DoReborn +// +void G_DoReborn (int playernum) +{ + int i; + + if (!netgame) + { + // reload the level from scratch + // [STRIFE] Reborn level load + G_LoadPath(gamemap); + gameaction = ga_loadgame; + } + else + { + // respawn at the start + + // first dissasociate the corpse + // [STRIFE] Checks for NULL first + if(players[playernum].mo) + players[playernum].mo->player = NULL; + + // spawn at random spot if in death match + if (deathmatch) + { + G_DeathMatchSpawnPlayer (playernum); + return; + } + + if (G_CheckSpot (playernum, &playerstarts[playernum]) ) + { + P_SpawnPlayer (&playerstarts[playernum]); + return; + } + + // try to spawn at one of the other players spots + for (i=0 ; i Abandoned Front Base + map = 30; + if(map == 7) // Castle -> New Front Base + map = 10; + } + + // no rifting in deathmatch games + if(deathmatch) + spot = 0; + + riftangle = angle; + riftdest = spot; + destmap = map; +} + +// +// G_Exit2 +// +// haleyjd 20101003: [STRIFE] New function. +// No xrefs to this, doesn't seem to be used. Could have gotten inlined +// somewhere but I haven't seen it. +// +void G_Exit2(int dest, angle_t angle) +{ + riftdest = dest; + gameaction = ga_completed; + riftangle = angle; + destmap = gamemap; +} + +// +// G_ExitLevel +// +// haleyjd 20100824: [STRIFE]: +// * Default to next map in numeric order; init destmap and riftdest. +// +void G_ExitLevel (int dest) +{ + if(dest == 0) + dest = gamemap + 1; + destmap = dest; + riftdest = 0; + gameaction = ga_completed; +} + +/* +// haleyjd 20100823: [STRIFE] No secret exits in Strife. +// Here's for the german edition. +void G_SecretExitLevel (void) +{ + // IF NO WOLF3D LEVELS, NO SECRET EXIT! + if ( (gamemode == commercial) + && (W_CheckNumForName("map31")<0)) + secretexit = false; + else + secretexit = true; + gameaction = ga_completed; +} +*/ + +// +// G_StartFinale +// +// haleyjd 20100921: [STRIFE] New function. +// This replaced G_SecretExitLevel in Strife. I don't know that it's actually +// used anywhere in the game, but it *is* usable in mods via linetype 124, +// W1 Start Finale. +// +void G_StartFinale(void) +{ + gameaction = ga_victory; +} + +// +// G_DoCompleted +// +// haleyjd 20100823: [STRIFE]: +// * Removed G_PlayerFinishLevel and just sets some powerup states. +// * Removed Chex, as not relevant to Strife. +// * Removed DOOM level transfer logic +// * Removed intermission code. +// * Added setting gameaction to ga_worlddone. +// +void G_DoCompleted (void) +{ + int i; + + // deal with powerup states + for(i = 0; i < MAXPLAYERS; i++) + { + if(playeringame[i]) + { + // [STRIFE] restore pw_allmap power from mapstate cache + if(destmap < 40) + players[i].powers[pw_allmap] = players[i].mapstate[destmap]; + + // Shadowarmor doesn't persist between maps in netgames + if(netgame) + players[i].powers[pw_invisibility] = 0; + } + } + + stonecold = false; // villsa [STRIFE] + + if (automapactive) + AM_Stop (); + + // [STRIFE] HUB SAVE + if(!deathmatch) + G_DoSaveGame(savepathtemp); + + gameaction = ga_worlddone; +} + + +// haleyjd 20100824: [STRIFE] No secret exits. +/* +// +// G_WorldDone +// +void G_WorldDone (void) +{ + gameaction = ga_worlddone; + + if (secretexit) + players[consoleplayer].didsecret = true; + + if ( gamemode == commercial ) + { + switch (gamemap) + { + case 15: + case 31: + if (!secretexit) + break; + case 6: + case 11: + case 20: + case 30: + F_StartFinale (); + break; + } + } +} +*/ + +// +// G_RiftPlayer +// +// haleyjd 20100824: [STRIFE] New function +// Teleports the player to the appropriate rift spot. +// +void G_RiftPlayer(void) +{ + if(riftdest) + { + P_TeleportMove(players[0].mo, + riftSpots[riftdest - 1].x << FRACBITS, + riftSpots[riftdest - 1].y << FRACBITS); + players[0].mo->angle = riftangle; + players[0].mo->health = players[0].health; + } +} + +// +// G_RiftCheat +// +// haleyjd 20100824: [STRIFE] New function +// Called from the cheat code to jump to a rift spot. +// +boolean G_RiftCheat(int riftSpotNum) +{ + return P_TeleportMove(players[0].mo, + riftSpots[riftSpotNum - 1].x << FRACBITS, + riftSpots[riftSpotNum - 1].y << FRACBITS); +} + +// +// G_DoWorldDone +// +// haleyjd 20100824: [STRIFE] Added destmap -> gamemap set. +// +void G_DoWorldDone (void) +{ + int temp_leveltime = leveltime; + boolean temp_shadow = false; + boolean temp_mvis = false; + + gamestate = GS_LEVEL; + gamemap = destmap; + + // [STRIFE] HUB LOAD + G_LoadPath(destmap); + if (!deathmatch) + { + // Remember Shadowarmor across hub loads + if(players[0].mo->flags & MF_SHADOW) + temp_shadow = true; + if(players[0].mo->flags & MF_MVIS) + temp_mvis = true; + } + G_DoLoadGame(false); + + // [STRIFE] leveltime carries over between maps + leveltime = temp_leveltime; + + if(!deathmatch) + { + // [STRIFE]: transfer saved powerups + players[0].mo->flags &= ~(MF_SHADOW|MF_MVIS); + if(temp_shadow) + players[0].mo->flags |= MF_SHADOW; + if(temp_mvis) + players[0].mo->flags |= MF_MVIS; + + // [STRIFE] HUB SAVE + G_RiftPlayer(); + G_DoSaveGame(savepathtemp); + M_SaveMisObj(savepathtemp); + } + + gameaction = ga_nothing; + viewactive = true; +} + +// +// G_DoWorldDone2 +// +// haleyjd 20101003: [STRIFE] New function. No xrefs; unused. +// +void G_DoWorldDone2(void) +{ + gamestate = GS_LEVEL; + gameaction = ga_nothing; + viewactive = true; +} + +// +// G_ReadCurrent +// +// haleyjd 20101003: [STRIFE] New function. +// Reads the "CURRENT" file from the given path and then sets it to +// gamemap. +// +void G_ReadCurrent(const char *path) +{ + char *temppath = NULL; + byte *buffer = NULL; + + temppath = M_SafeFilePath(path, "\\current"); + + if(M_ReadFile(temppath, &buffer) <= 0) + gameaction = ga_newgame; + else + { + // haleyjd 20110211: do endian-correct read + gamemap = (((int)buffer[0]) | + ((int)buffer[1] << 8) | + ((int)buffer[2] << 16) | + ((int)buffer[3] << 24)); + gameaction = ga_loadgame; + Z_Free(buffer); + } + + Z_Free(temppath); + + G_LoadPath(gamemap); +} + +// +// G_InitFromSavegame +// Can be called by the startup code or the menu task. +// + +char savename[256]; + +// [STRIFE]: No such function. +/* +void G_LoadGame (char* name) +{ + M_StringCopy(savename, name, sizeof(savename)); + gameaction = ga_loadgame; +} +*/ + +// haleyjd 20100928: [STRIFE] VERSIONSIZE == 8 +#define VERSIONSIZE 8 + +void G_DoLoadGame (boolean userload) +{ + int savedleveltime; + + gameaction = ga_nothing; + + save_stream = M_fopen(loadpath, "rb"); + + // [STRIFE] If the file does not exist, G_DoLoadLevel is called. + if (save_stream == NULL) + { + G_DoLoadLevel(); + return; + } + + savegame_error = false; + + if (!P_ReadSaveGameHeader()) + { + fclose(save_stream); + return; + } + + // haleyjd: A comment would be good here, fraggle... + // Evidently this is a Choco-ism, necessitated by reading the savegame + // header *before* calling G_DoLoadLevel. + savedleveltime = leveltime; + + // load a base level + + // STRIFE-TODO: ???? + if(userload) + G_InitNew(gameskill, gamemap); + else + G_DoLoadLevel(); + + leveltime = savedleveltime; + + // dearchive all the modifications + // [STRIFE] some portions of player_t are not overwritten when loading + // between hub levels + P_UnArchivePlayers (userload); + P_UnArchiveWorld (); + P_UnArchiveThinkers (); + P_UnArchiveSpecials (); + + if (!P_ReadSaveGameEOF()) + I_Error ("Bad savegame"); + + fclose(save_stream); + + if (setsizeneeded) + R_ExecuteSetViewSize (); + + // draw the pattern into the back screen + R_FillBackScreen (); +} + +// +// G_WriteSaveName +// +// haleyjd 20101003: [STRIFE] New function +// +// Writes the character name to the NAME file. +// +boolean G_WriteSaveName(int slot, const char *charname) +{ + //char savedir[16]; + char *tmpname; + boolean retval; + + savegameslot = slot; + + // haleyjd: removed special -cdrom treatment, as I believe it is taken + // care of automatically via using Choco's savegamedir setting. + + // haleyjd: free previous path, if any, and allocate new one using + // M_SafeFilePath routine, which isn't limited to 128 characters. + if(savepathtemp) + Z_Free(savepathtemp); + savepathtemp = M_SafeFilePath(savegamedir, "strfsav6.ssg"); + + // haleyjd: as above. + if(savepath) + Z_Free(savepath); + savepath = M_SafeFilePath(savegamedir, M_MakeStrifeSaveDir(savegameslot, "")); + + // haleyjd: memset full character_name for safety + memset(character_name, 0, CHARACTER_NAME_LEN); + M_StringCopy(character_name, charname, sizeof(character_name)); + + // haleyjd: use M_SafeFilePath + tmpname = M_SafeFilePath(savepathtemp, "name"); + + // Write the "name" file under the directory + retval = M_WriteFile(tmpname, character_name, 32); + + Z_Free(tmpname); + + return retval; +} + +// +// G_SaveGame +// Called by the menu task. +// Description is a 24 byte text string +// +// [STRIFE] No such function, at least in v1.2 +// STRIFE-TODO: Does this make a comeback in v1.31? +/* +void +G_SaveGame +( int slot, + char* description ) +{ + savegameslot = slot; + M_StringCopy(savedescription, description, sizeof(savedescription)); + sendsave = true; +} +*/ + +void G_DoSaveGame (char *path) +{ + char *current_path; + char *savegame_file; + char *temp_savegame_file; + byte gamemapbytes[4]; + char gamemapstr[33]; + + temp_savegame_file = P_TempSaveGameFile(); + + // [STRIFE] custom save file path logic + memset(gamemapstr, 0, sizeof(gamemapstr)); + M_snprintf(gamemapstr, sizeof(gamemapstr), "%d", gamemap); + savegame_file = M_SafeFilePath(path, gamemapstr); + + // [STRIFE] write the "current" file, which tells which hub map + // the save slot is currently on. + current_path = M_SafeFilePath(path, "current"); + // haleyjd: endian-agnostic IO + gamemapbytes[0] = (byte)( gamemap & 0xff); + gamemapbytes[1] = (byte)((gamemap >> 8) & 0xff); + gamemapbytes[2] = (byte)((gamemap >> 16) & 0xff); + gamemapbytes[3] = (byte)((gamemap >> 24) & 0xff); + M_WriteFile(current_path, gamemapbytes, 4); + Z_Free(current_path); + + // Open the savegame file for writing. We write to a temporary file + // and then rename it at the end if it was successfully written. + // This prevents an existing savegame from being overwritten by + // a corrupted one, or if a savegame buffer overrun occurs. + + save_stream = M_fopen(temp_savegame_file, "wb"); + + if (save_stream == NULL) + { + return; + } + + savegame_error = false; + + P_WriteSaveGameHeader(savedescription); + + P_ArchivePlayers (); + P_ArchiveWorld (); + P_ArchiveThinkers (); + P_ArchiveSpecials (); + + P_WriteSaveGameEOF(); + + // Enforce the same savegame size limit as in Vanilla Doom, + // except if the vanilla_savegame_limit setting is turned off. + // [STRIFE]: Verified subject to same limit. + + if (vanilla_savegame_limit && ftell(save_stream) > SAVEGAMESIZE) + { + I_Error ("Savegame buffer overrun"); + } + + // Finish up, close the savegame file. + + fclose(save_stream); + + // Now rename the temporary savegame file to the actual savegame + // file, overwriting the old savegame if there was one there. + + M_remove(savegame_file); + M_rename(temp_savegame_file, savegame_file); + + // haleyjd: free the savegame_file path + Z_Free(savegame_file); + + gameaction = ga_nothing; + //M_StringCopy(savedescription, "", sizeof(savedescription)); + + // [STRIFE]: custom message logic + if(!strcmp(path, savepath)) + { + M_snprintf(savename, sizeof(savename), "%s saved.", character_name); + players[consoleplayer].message = savename; + } + + // draw the pattern into the back screen + R_FillBackScreen (); +} + + +// +skill_t d_skill; +//int d_episode; [STRIFE] No such thing as episodes in Strife +int d_map; + +// +// G_DeferedInitNew +// +// Can be called by the startup code or the menu task, +// consoleplayer, displayplayer, playeringame[] should be set. +// +// haleyjd 20100922: [STRIFE] Removed episode parameter +// +void G_DeferedInitNew(skill_t skill, int map) +{ + d_skill = skill; + d_map = map; + gameaction = ga_newgame; +} + +// +// G_DoNewGame +// +// [STRIFE] Code added to turn off the stonecold effect. +// Someone also removed the nomonsters reset... +// +void G_DoNewGame (void) +{ + demoplayback = false; + netdemo = false; + netgame = false; + deathmatch = false; + playeringame[1] = playeringame[2] = playeringame[3] = 0; + respawnparm = false; + fastparm = false; + stonecold = false; // villsa [STRIFE] + //nomonsters = false; [STRIFE] not set here!?! + consoleplayer = 0; + G_InitNew (d_skill, d_map); + gameaction = ga_nothing; +} + +// +// G_InitNew +// +// haleyjd 20100824: [STRIFE]: +// * Added riftdest initialization +// * Removed episode parameter +// +void +G_InitNew +( skill_t skill, + int map ) +{ + const char *skytexturename; + int i; + + if (paused) + { + paused = false; + S_ResumeSound (); + } + + if (skill > sk_nightmare) + skill = sk_nightmare; + + // [STRIFE] Removed episode nonsense and gamemap clipping + + M_ClearRandom (); + + if (skill == sk_nightmare || respawnparm ) + respawnmonsters = true; + else + respawnmonsters = false; + + // [STRIFE] Strife skill level mobjinfo/states tweaking + // BUG: None of this code runs properly when loading save games, so + // basically it's impossible to play any skill level properly unless + // you never quit and reload from the command line. + if(!skill && gameskill) + { + // Setting to Baby skill... make things easier. + + // Acolytes walk, attack, and feel pain slower + for(i = S_AGRD_13; i <= S_AGRD_23; i++) + states[i].tics *= 2; + + // Reavers attack slower + for(i = S_ROB1_10; i <= S_ROB1_15; i++) + states[i].tics *= 2; + + // Turrets attack slower + for(i = S_TURT_02; i <= S_TURT_03; i++) + states[i].tics *= 2; + + // Crusaders attack and feel pain slower + for(i = S_ROB2_09; i <= S_ROB2_19; i++) + states[i].tics *= 2; + + // Stalkers think, walk, and attack slower + for(i = S_SPID_03; i <= S_SPID_10; i++) + states[i].tics *= 2; + + // The Bishop's homing missiles are faster (what?? BUG?) + mobjinfo[MT_SEEKMISSILE].speed *= 2; + } + if(skill && !gameskill) + { + // Setting a higher skill when previously on baby... make things normal + + // Acolytes + for(i = S_AGRD_13; i <= S_AGRD_23; i++) + states[i].tics >>= 1; + + // Reavers + for(i = S_ROB1_10; i <= S_ROB1_15; i++) + states[i].tics >>= 1; + + // Turrets + for(i = S_TURT_02; i <= S_TURT_03; i++) + states[i].tics >>= 1; + + // Crusaders + for(i = S_ROB2_09; i <= S_ROB2_19; i++) + states[i].tics >>= 1; + + // Stalkers + for(i = S_SPID_03; i <= S_SPID_10; i++) + states[i].tics >>= 1; + + // The Bishop's homing missiles - again, seemingly backward. + mobjinfo[MT_SEEKMISSILE].speed >>= 1; + } + if(fastparm || (skill == sk_nightmare && skill != gameskill)) + { + // BLOODBATH! Make some things super-aggressive. + + // Acolytes walk, attack, and feel pain twice as fast + // (This makes just getting out of the first room almost impossible) + for(i = S_AGRD_13; i <= S_AGRD_23; i++) + states[i].tics >>= 1; + + // Bishop's homing missiles again get SLOWER and not faster o_O + mobjinfo[MT_SEEKMISSILE].speed >>= 1; + } + else if(skill != sk_nightmare && gameskill == sk_nightmare) + { + // Setting back to an ordinary skill after being on Bloodbath? + // Put stuff back to normal. + + // Acolytes + for(i = S_AGRD_13; i <= S_AGRD_23; i++) + states[i].tics *= 2; + + // Bishop's homing missiles + mobjinfo[MT_SEEKMISSILE].speed *= 2; + } + + // force players to be initialized upon first level load + for (i=0 ; i= 9 && gamemap < 32) + skytexturename = "skymnt01"; + else + skytexturename = "skymnt02"; + + skytexturename = DEH_String(skytexturename); + + skytexture = R_TextureNumForName(skytexturename); + + // [STRIFE] HUBS + G_LoadPath(gamemap); + G_DoLoadLevel(); +} + + +// +// DEMO RECORDING +// +#define DEMOMARKER 0x80 + +// +// G_ReadDemoTiccmd +// +// [STRIFE] Modified for Strife ticcmd_t +// +void G_ReadDemoTiccmd (ticcmd_t* cmd) +{ + if (*demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus (); + return; + } + cmd->forwardmove = ((signed char)*demo_p++); + cmd->sidemove = ((signed char)*demo_p++); + cmd->angleturn = ((unsigned char) *demo_p++)<<8; + cmd->buttons = (unsigned char)*demo_p++; + cmd->buttons2 = (unsigned char)*demo_p++; // [STRIFE] + cmd->inventory = (int)*demo_p++; // [STRIFE] +} + +// Increase the size of the demo buffer to allow unlimited demos + +static void IncreaseDemoBuffer(void) +{ + int current_length; + byte *new_demobuffer; + byte *new_demop; + int new_length; + + // Find the current size + + current_length = demoend - demobuffer; + + // Generate a new buffer twice the size + new_length = current_length * 2; + + new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); + new_demop = new_demobuffer + (demo_p - demobuffer); + + // Copy over the old data + + memcpy(new_demobuffer, demobuffer, current_length); + + // Free the old buffer and point the demo pointers at the new buffer. + + Z_Free(demobuffer); + + demobuffer = new_demobuffer; + demo_p = new_demop; + demoend = demobuffer + new_length; +} + +// +// G_WriteDemoTiccmd +// +// [STRIFE] Modified for Strife ticcmd_t. +// +void G_WriteDemoTiccmd (ticcmd_t* cmd) +{ + byte *demo_start; + + if (gamekeydown[key_demo_quit]) // press q to end demo recording + G_CheckDemoStatus (); + + demo_start = demo_p; + + *demo_p++ = cmd->forwardmove; + *demo_p++ = cmd->sidemove; + *demo_p++ = cmd->angleturn >> 8; + *demo_p++ = cmd->buttons; + *demo_p++ = cmd->buttons2; // [STRIFE] + *demo_p++ = (byte)(cmd->inventory & 0xff); // [STRIFE] + + // reset demo pointer back + demo_p = demo_start; + + if (demo_p > demoend - 16) + { + if (vanilla_demo_limit) + { + // no more space + G_CheckDemoStatus (); + return; + } + else + { + // Vanilla demo limit disabled: unlimited + // demo lengths! + + IncreaseDemoBuffer(); + } + } + + G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same +} + + + +// +// G_RecordDemo +// +// [STRIFE] Verified unmodified +// +void G_RecordDemo (const char* name) +{ + size_t demoname_size; + int i; + int maxsize; + + usergame = false; + demoname_size = strlen(name) + 5; + demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); + M_snprintf(demoname, demoname_size, "%s.lmp", name); + maxsize = 0x20000; + + //! + // @arg + // @category demo + // @vanilla + // + // Specify the demo buffer size (KiB) + // + + i = M_CheckParmWithArgs("-maxdemo", 1); + if (i) + maxsize = atoi(myargv[i+1])*1024; + demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL); + demoend = demobuffer + maxsize; + + demorecording = true; +} + + +void G_BeginRecording (void) +{ + int i; + + // + // @category demo + // + // Record a high resolution "Doom 1.91" demo. + // + + // STRIFE-TODO: if somebody makes a "Strife Plus", we could add this. + /* + longtics = M_CheckParm("-longtics") != 0; + */ + longtics = false; + + // If not recording a longtics demo, record in low res + lowres_turn = !longtics; + + demo_p = demobuffer; + + // Save the right version code for this demo + *demo_p++ = STRIFE_VERSION; + + *demo_p++ = gameskill; + //*demo_p++ = gameepisode; [STRIFE] Doesn't have episodes. + *demo_p++ = gamemap; + *demo_p++ = deathmatch; + *demo_p++ = respawnparm; + *demo_p++ = fastparm; + *demo_p++ = nomonsters; + *demo_p++ = consoleplayer; + + for (i=0 ; i + +#include "doomdef.h" +#include "doomkeys.h" + +#include "v_video.h" +#include "i_swap.h" + +#include "d_main.h" +#include "hu_lib.h" +#include "r_local.h" +#include "r_draw.h" +#include "hu_stuff.h" // [STRIFE] + +#include "doomstat.h" + +// boolean : whether the screen is always erased +#define noterased viewwindowx + + +// +// HUlib_drawYellowText +// +// haleyjd 20100918: [STRIFE] New function. +// +void HUlib_drawYellowText(int x, int y, const char *text) +{ + int start_x = x; + const char *rover = text; + char c; + + while((c = *rover++)) + { + if(c == '\n') + { + x = start_x; + y += 12; + continue; + } + + // haleyjd 20110213: found MORE code ignored/misinterpreted by Hex-Rays: + // Underscores are replaced by spaces. + if(c == '_') + c = ' '; + else if (c == ' ' && x == start_x) // skip spaces at the start of a line + continue; + + c = toupper(c) - HU_FONTSTART; + + if(c >= 0 && c < HU_FONTSIZE) + { + patch_t *patch = yfont[(int) c]; + int width = SHORT(patch->width); + + if(x + width <= (SCREENWIDTH - 20)) + { + // haleyjd: STRIFE-TODO: bit different than the exe... for now + if(!D_PatchClipCallback(patch, x + SHORT(patch->leftoffset), + y + SHORT(patch->topoffset))) + return; + V_DrawPatchDirect(x, y, patch); + x = x + width; + } + else + { + x = start_x; + --rover; + y += 12; + } + } + else + { + x += 4; + } + } +} + +// +// HUlib_init +// +// [STRIFE] Verified unmodified. +// +void HUlib_init(void) +{ +} + +// +// HUlib_clearTextLine +// +// [STRIFE] Verified unmodified. +// +void HUlib_clearTextLine(hu_textline_t* t) +{ + t->len = 0; + t->l[0] = 0; + t->needsupdate = true; +} + +// +// HUlib_initTextLine +// +// [STRIFE] Verified unmodified +// +void +HUlib_initTextLine +( hu_textline_t* t, + int x, + int y, + patch_t** f, + int sc ) +{ + t->x = x; + t->y = y; + t->f = f; + t->sc = sc; + HUlib_clearTextLine(t); +} + +// +// HUlib_addCharToTextLine +// +// [STRIFE] Verified unmodified. +// +boolean +HUlib_addCharToTextLine +( hu_textline_t* t, + char ch ) +{ + if (t->len == HU_MAXLINELENGTH) + return false; + else + { + t->l[t->len++] = ch; + t->l[t->len] = 0; + t->needsupdate = 4; + return true; + } +} + +// +// HUlib_delCharFromTextLine +// +// [STRIFE] Verified unmodified. +// +boolean HUlib_delCharFromTextLine(hu_textline_t* t) +{ + if (!t->len) return false; + else + { + t->l[--t->len] = 0; + t->needsupdate = 4; + return true; + } +} + +// +// HUlib_drawTextLine +// +// haleyjd 09/18/10: [STRIFE] Modified to not draw underscores in text. +// +void +HUlib_drawTextLine +( hu_textline_t* l, + boolean drawcursor ) +{ + int i; + int w; + int x; + unsigned char c; + + // draw the new stuff + x = l->x; + + for(i = 0; i < l->len; i++) + { + c = toupper(l->l[i]); + if (c != ' ' && c >= l->sc && c < '_') // [STRIFE]: Underscores excluded + { + w = SHORT(l->f[c - l->sc]->width); + if (x+w > SCREENWIDTH) + break; + V_DrawPatchDirect(x, l->y, l->f[c - l->sc]); + x += w; + } + else + { + x += 4; + if (x >= SCREENWIDTH) + break; + } + } + + // draw the cursor if requested + if (drawcursor + && x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH) + { + V_DrawPatchDirect(x, l->y, l->f['_' - l->sc]); + } +} + +// +// HUlib_eraseTextLine +// +// sorta called by HU_Erase and just better darn get things straight +// +// [STRIFE] Verified unmodified. +// +void HUlib_eraseTextLine(hu_textline_t* l) +{ + int lh; + int y; + int yoffset; + + // Only erases when NOT in automap and the screen is reduced, + // and the text must either need updating or refreshing + // (because of a recent change back from the automap) + + if (!automapactive && + viewwindowx && l->needsupdate) + { + lh = SHORT(l->f[0]->height) + 1; + for (y=l->y,yoffset=y*SCREENWIDTH ; yy+lh ; y++,yoffset+=SCREENWIDTH) + { + if (y < viewwindowy || y >= viewwindowy + viewheight) + R_VideoErase(yoffset, SCREENWIDTH); // erase entire line + else + { + R_VideoErase(yoffset, viewwindowx); // erase left border + R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); + // erase right border + } + } + } + + if (l->needsupdate) l->needsupdate--; +} + +// +// HUlib_initSText +// +// [STRIFE] Verified unmodified. +// +void +HUlib_initSText +( hu_stext_t* s, + int x, + int y, + int h, + patch_t** font, + int startchar, + boolean* on ) +{ + int i; + + s->h = h; + s->on = on; + s->laston = true; + s->cl = 0; + for (i=0;il[i], + x, y - i*(SHORT(font[0]->height)+1), + font, startchar); + } +} + +// +// HUlib_addLineToSText +// +// [STRIFE] Verified unmodified. +// +void HUlib_addLineToSText(hu_stext_t* s) +{ + int i; + + // add a clear line + if (++s->cl == s->h) + s->cl = 0; + HUlib_clearTextLine(&s->l[s->cl]); + + // everything needs updating + for (i=0 ; ih ; i++) + s->l[i].needsupdate = 4; +} + +// +// HUlib_addMessageToSText +// +// [STRIFE] Verified unmodified. +// +void +HUlib_addMessageToSText +( hu_stext_t* s, + const char *prefix, + const char *msg ) +{ + HUlib_addLineToSText(s); + if (prefix) + while (*prefix) + HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++)); + + while (*msg) + HUlib_addCharToTextLine(&s->l[s->cl], *(msg++)); +} + +// +// HUlib_drawSText +// +// [STRIFE] Verified unmodified. +// +void HUlib_drawSText(hu_stext_t* s) +{ + int i, idx; + hu_textline_t *l; + + if (!*s->on) + return; // if not on, don't draw + + // draw everything + for (i=0 ; ih ; i++) + { + idx = s->cl - i; + if (idx < 0) + idx += s->h; // handle queue of lines + + l = &s->l[idx]; + + // need a decision made here on whether to skip the draw + HUlib_drawTextLine(l, false); // no cursor, please + } +} + +// +// HUlib_eraseSText +// +// [STRIFE] Verified unmodified. +// +void HUlib_eraseSText(hu_stext_t* s) +{ + int i; + + for (i=0 ; ih ; i++) + { + if (s->laston && !*s->on) + s->l[i].needsupdate = 4; + HUlib_eraseTextLine(&s->l[i]); + } + s->laston = *s->on; +} + +// +// HUlib_initIText +// +// [STRIFE] Verified unmodified. +// +void +HUlib_initIText +( hu_itext_t* it, + int x, + int y, + patch_t** font, + int startchar, + boolean* on ) +{ + it->lm = 0; // default left margin is start of text + it->on = on; + it->laston = true; + HUlib_initTextLine(&it->l, x, y, font, startchar); +} + + +// The following deletion routines adhere to the left margin restriction +// [STRIFE] Verified unmodified. +void HUlib_delCharFromIText(hu_itext_t* it) +{ + if (it->l.len != it->lm) + HUlib_delCharFromTextLine(&it->l); +} + +// [STRIFE] Verified unmodified. +void HUlib_eraseLineFromIText(hu_itext_t* it) +{ + while (it->lm != it->l.len) + HUlib_delCharFromTextLine(&it->l); +} + +// Resets left margin as well +// [STRIFE] Verified unmodified. +void HUlib_resetIText(hu_itext_t* it) +{ + it->lm = 0; + HUlib_clearTextLine(&it->l); +} + +// +// HUlib_addPrefixToIText +// +// [STRIFE] Verified unmodified. +// +void +HUlib_addPrefixToIText +( hu_itext_t* it, + char* str ) +{ + while (*str) + HUlib_addCharToTextLine(&it->l, *(str++)); + it->lm = it->l.len; +} + +// wrapper function for handling general keyed input. +// returns true if it ate the key +// [STRIFE] Verified unmodified. +boolean +HUlib_keyInIText +( hu_itext_t* it, + unsigned char ch ) +{ + ch = toupper(ch); + + if (ch >= ' ' && ch <= '_') + HUlib_addCharToTextLine(&it->l, (char) ch); + else if (ch == KEY_BACKSPACE) + HUlib_delCharFromIText(it); + else if (ch != KEY_ENTER) + return false; // did not eat key + + return true; // ate the key +} + +// +// HUlib_drawIText +// +// [STRIFE] Verified unmodified. +// +void HUlib_drawIText(hu_itext_t* it) +{ + hu_textline_t *l = &it->l; + + if (!*it->on) + return; + HUlib_drawTextLine(l, true); // draw the line w/ cursor +} + +// +// HUlib_eraseIText +// +// [STRIFE] Verified unmodified. +// +void HUlib_eraseIText(hu_itext_t* it) +{ + if (it->laston && !*it->on) + it->l.needsupdate = 4; + HUlib_eraseTextLine(&it->l); + it->laston = *it->on; +} + diff --git a/games/NXDoom/src/strife/hu_lib.h b/games/NXDoom/src/strife/hu_lib.h new file mode 100644 index 00000000000..5639860d1f5 --- /dev/null +++ b/games/NXDoom/src/strife/hu_lib.h @@ -0,0 +1,185 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// + +#ifndef __HULIB__ +#define __HULIB__ + +// We are referring to patches. +#include "r_defs.h" + +// font stuff +#define HU_CHARERASE KEY_BACKSPACE + +#define HU_MAXLINES 4 +#define HU_MAXLINELENGTH 80 + +// +// Typedefs of widgets +// + +// Text Line widget +// (parent of Scrolling Text and Input Text widgets) +typedef struct +{ + // left-justified position of scrolling text window + int x; + int y; + + patch_t** f; // font + int sc; // start character + char l[HU_MAXLINELENGTH+1]; // line of text + int len; // current line length + + // whether this line needs to be udpated + int needsupdate; + +} hu_textline_t; + + + +// Scrolling Text window widget +// (child of Text Line widget) +typedef struct +{ + hu_textline_t l[HU_MAXLINES]; // text lines to draw + int h; // height in lines + int cl; // current line number + + // pointer to boolean stating whether to update window + boolean* on; + boolean laston; // last value of *->on. + +} hu_stext_t; + + + +// Input Text Line widget +// (child of Text Line widget) +typedef struct +{ + hu_textline_t l; // text line to input on + + // left margin past which I am not to delete characters + int lm; + + // pointer to boolean stating whether to update window + boolean* on; + boolean laston; // last value of *->on; + +} hu_itext_t; + + +// +// Widget creation, access, and update routines +// + +// initializes heads-up widget library +void HUlib_init(void); + +// +// textline code +// + +// clear a line of text +void HUlib_clearTextLine(hu_textline_t *t); + +void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc); + +// returns success +boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); + +// returns success +boolean HUlib_delCharFromTextLine(hu_textline_t *t); + +// draws tline +void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor); + +// erases text line +void HUlib_eraseTextLine(hu_textline_t *l); + +// villsa [STRIFE] +void HUlib_drawYellowText(int x, int y, const char *text); + + +// +// Scrolling Text window widget routines +// + +// ? +void +HUlib_initSText +( hu_stext_t* s, + int x, + int y, + int h, + patch_t** font, + int startchar, + boolean* on ); + +// add a new line +void HUlib_addLineToSText(hu_stext_t* s); + +// ? +void +HUlib_addMessageToSText +( hu_stext_t* s, + const char *prefix, + const char *msg ); + +// draws stext +void HUlib_drawSText(hu_stext_t* s); + +// erases all stext lines +void HUlib_eraseSText(hu_stext_t* s); + +// Input Text Line widget routines +void +HUlib_initIText +( hu_itext_t* it, + int x, + int y, + patch_t** font, + int startchar, + boolean* on ); + +// enforces left margin +void HUlib_delCharFromIText(hu_itext_t* it); + +// enforces left margin +void HUlib_eraseLineFromIText(hu_itext_t* it); + +// resets line and left margin +void HUlib_resetIText(hu_itext_t* it); + +// left of left-margin +void +HUlib_addPrefixToIText +( hu_itext_t* it, + char* str ); + +// whether eaten +boolean +HUlib_keyInIText +( hu_itext_t* it, + unsigned char ch ); + +void HUlib_drawIText(hu_itext_t* it); + +// erases all itext lines +void HUlib_eraseIText(hu_itext_t* it); + +#endif diff --git a/games/NXDoom/src/strife/hu_stuff.c b/games/NXDoom/src/strife/hu_stuff.c new file mode 100644 index 00000000000..34f8ff457d8 --- /dev/null +++ b/games/NXDoom/src/strife/hu_stuff.c @@ -0,0 +1,687 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Heads-up displays +// + + +#include + +#include "doomdef.h" +#include "doomkeys.h" + +#include "z_zone.h" + +#include "deh_main.h" +#include "i_input.h" +#include "i_swap.h" +#include "i_video.h" + +#include "d_main.h" +#include "hu_stuff.h" +#include "hu_lib.h" +#include "m_controls.h" +#include "m_misc.h" +#include "w_wad.h" + +#include "s_sound.h" + +#include "doomstat.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +// +// Locally used constants, shortcuts. +// +#define HU_TITLE (mapnames[gamemap-1]) +#define HU_TITLEHEIGHT 1 +#define HU_TITLEX 0 + +// haleyjd 09/01/10: [STRIFE] 167 -> 160 to move up level name +#define HU_TITLEY (160 - SHORT(hu_font[0]->height)) + +#define HU_INPUTTOGGLE 't' +#define HU_INPUTX HU_MSGX +#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1)) +#define HU_INPUTWIDTH 64 +#define HU_INPUTHEIGHT 1 + +char *chat_macros[10]; + +// villsa [STRIFE] +char player_names[8][16] = +{ + "1: ", + "2: ", + "3: ", + "4: ", + "5: ", + "6: ", + "7: ", + "8: " +}; + +char chat_char; // remove later. +static player_t* plr; +patch_t* hu_font[HU_FONTSIZE]; +patch_t* yfont[HU_FONTSIZE]; // haleyjd 09/18/10: [STRIFE] +static hu_textline_t w_title; +boolean chat_on; +static hu_itext_t w_chat; +static boolean always_off = false; +static char chat_dest[MAXPLAYERS]; +static hu_itext_t w_inputbuffer[MAXPLAYERS]; + +static boolean message_on; +boolean message_dontfuckwithme; +static boolean message_nottobefuckedwith; + +static hu_stext_t w_message; +static int message_counter; + + +static boolean headsupactive = false; + +// haleyjd 20130915 [STRIFE]: true if setting nickname +static boolean hu_setting_name = false; + +// +// Builtin map names. +// The actual names can be found in DStrings.h. +// + +// haleyjd 08/31/10: [STRIFE] Changed for Strife level names. +// List of names for levels. + +const char *mapnames[] = +{ + // Strife map names + + // First "episode" - Quest to destroy the Order's Castle + HUSTR_1, + HUSTR_2, + HUSTR_3, + HUSTR_4, + HUSTR_5, + HUSTR_6, + HUSTR_7, + HUSTR_8, + HUSTR_9, + + // Second "episode" - Kill the Bishop and Make a Choice + HUSTR_10, + HUSTR_11, + HUSTR_12, + HUSTR_13, + HUSTR_14, + HUSTR_15, + HUSTR_16, + HUSTR_17, + HUSTR_18, + HUSTR_19, + + // Third "episode" - Shut down Factory, kill Loremaster and Entity + HUSTR_20, + HUSTR_21, + HUSTR_22, + HUSTR_23, + HUSTR_24, + HUSTR_25, + HUSTR_26, + HUSTR_27, + HUSTR_28, + HUSTR_29, + + // "Secret" levels - Abandoned Base and Training Facility + HUSTR_30, + HUSTR_31, + + // Demo version maps + HUSTR_32, + HUSTR_33, + HUSTR_34 +}; + +// +// HU_Init +// +// haleyjd 09/18/10: [STRIFE] +// * Modified to load yfont along with hu_font. +// +void HU_Init(void) +{ + int i; + int j; + char buffer[9]; + + // load the heads-up font + j = HU_FONTSTART; + for (i=0;i This is definitely not the best that Rogue had to offer. Markov. +// +// Fastcall Registers: edx ebx +// Temp Registers: esi edi +static void HU_addMessage(const char *prefix, const char *message) +{ + char c; // eax + int width = 0; // edx + const char *rover1; // ebx (in first loop) + const char *rover2; // ecx (in second loop) + char *bufptr; // ebx (in second loop) + char buffer[HU_MAXLINELENGTH+2]; // esp+52h + + // Loop 1: Total up width of prefix. + rover1 = prefix; + if(rover1) + { + while((c = *rover1)) + { + c = toupper(c) - HU_FONTSTART; + ++rover1; + + if(c < 0 || c >= HU_FONTSIZE) + width += 4; + else + width += SHORT(hu_font[(int) c]->width); + } + } + + // Loop 2: Copy as much of message into buffer as will fit on screen + bufptr = buffer; + rover2 = message; + while((c = *rover2)) + { + if((c == ' ' || c == '-') && width > 285) + break; + + *bufptr = c; + ++bufptr; // BUG: No check for overflow. + ++rover2; + c = toupper(c); + + if(c == ' ' || c < '!' || c >= '_') + width += 4; + else + { + c -= HU_FONTSTART; + width += SHORT(hu_font[(int) c]->width); + } + } + + // Too big to fit? + // BUG: doesn't consider by how much it's over. + if(width > 320) + { + // backup a char... hell if I know why. + --bufptr; + --rover2; + } + + // rover2 is not at the end? + if((c = *rover2)) + { + // if not ON a space... + if(c != ' ') + { + // back up both pointers til one is found. + // BUG: no check against LHS of buffer. Hurr! + while(*bufptr != ' ') + { + --bufptr; + --rover2; + } + } + } + + *bufptr = '\0'; + + // Add two message lines. + HUlib_addMessageToSText(&w_message, prefix, buffer); + HUlib_addMessageToSText(&w_message, NULL, rover2); +} + +// +// HU_Ticker +// +// haleyjd 09/18/10: [STRIFE] Changes to split up message into two lines, +// and support for player names (STRIFE-TODO: unfinished!) +// +void HU_Ticker(void) +{ + int i, rc; + char c; + //char *prefix; STRIFE-TODO + + // tick down message counter if message is up + if (message_counter && !--message_counter) + { + message_on = false; + message_nottobefuckedwith = false; + } + + // haleyjd 20110219: [STRIFE] this condition was removed + //if (showMessages || message_dontfuckwithme) + //{ + // display message if necessary + if ((plr->message && !message_nottobefuckedwith) + || (plr->message && message_dontfuckwithme)) + { + //HUlib_addMessageToSText(&w_message, 0, plr->message); + HU_addMessage(NULL, plr->message); // haleyjd [STRIFE] + plr->message = 0; + message_on = true; + message_counter = HU_MSGTIMEOUT; + message_nottobefuckedwith = message_dontfuckwithme; + message_dontfuckwithme = 0; + } + //} // else message_on = false; + + // check for incoming chat characters + if (netgame) + { + for (i=0 ; idata1 == KEY_RSHIFT) + { + return false; + } + else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT) + { + altdown = ev->type == ev_keydown; + return false; + } + + if (ev->type != ev_keydown) + return false; + + if (!chat_on) + { + if (ev->data1 == key_message_refresh) + { + message_on = true; + message_counter = HU_MSGTIMEOUT; + eatkey = true; + } + else if (netgame && ev->data2 == key_multi_msg) + { + StartChatInput(); + eatkey = true; + HUlib_resetIText(&w_chat); + HU_queueChatChar(HU_BROADCAST); + } + // [STRIFE]: You cannot go straight to chatting with a particular + // player from here... you must press 't' first. See below. + } + else + { + c = ev->data3; + // send a macro + if (altdown) + { + c = c - '0'; + if (c > 9) + return false; + // fprintf(stderr, "got here\n"); + macromessage = chat_macros[c]; + + // kill last message with a '\n' + HU_queueChatChar(KEY_ENTER); // DEBUG!!! + + // send the macro message + while (*macromessage) + HU_queueChatChar(*macromessage++); + HU_queueChatChar(KEY_ENTER); + + // leave chat mode and notify that it was sent + StopChatInput(); + M_StringCopy(lastmessage, chat_macros[c], sizeof(lastmessage)); + plr->message = lastmessage; + eatkey = true; + } + else + { + if(w_chat.l.len) // [STRIFE]: past first char of chat? + { + eatkey = HUlib_keyInIText(&w_chat, c); + if (eatkey) + HU_queueChatChar(c); + } + else + { + // [STRIFE]: check for player-specific message; + // slightly different than vanilla, to allow keys to be customized + for(i = 0; i < MAXPLAYERS; i++) + { + if (ev->data1 == key_multi_msgplayer[i]) + break; + } + if(i < MAXPLAYERS) + { + // talking to self? + if(i == consoleplayer) + { + num_nobrainers++; + if (num_nobrainers < 3) + plr->message = DEH_String(HUSTR_TALKTOSELF1); + else if (num_nobrainers < 6) + plr->message = DEH_String(HUSTR_TALKTOSELF2); + else if (num_nobrainers < 9) + plr->message = DEH_String(HUSTR_TALKTOSELF3); + else if (num_nobrainers < 32) + plr->message = DEH_String(HUSTR_TALKTOSELF4); + else + plr->message = DEH_String(HUSTR_TALKTOSELF5); + } + else + { + eatkey = true; + HU_queueChatChar(i+1); + DEH_snprintf(lastmessage, sizeof(lastmessage), + "Talking to: %c", '1' + i); + plr->message = lastmessage; + } + } + else if(c == '$') // [STRIFE]: name changing + { + eatkey = true; + HU_queueChatChar(HU_CHANGENAME); + M_StringCopy(lastmessage, DEH_String("Changing Name:"), + sizeof(lastmessage)); + plr->message = lastmessage; + hu_setting_name = true; + } + else + { + eatkey = HUlib_keyInIText(&w_chat, c); + if (eatkey) + HU_queueChatChar(c); + } + } + + if (c == KEY_ENTER) + { + StopChatInput(); + if (w_chat.l.len) + { + // [STRIFE]: name setting + if(hu_setting_name) + { + DEH_snprintf(lastmessage, sizeof(lastmessage), + "%s now %.13s", player_names[consoleplayer], + w_chat.l.l); + // haleyjd 20141024: missing name set for local client + DEH_snprintf(player_names[consoleplayer], + sizeof(player_names[consoleplayer]), + "%.13s: ", w_chat.l.l); + hu_setting_name = false; + } + else + { + M_StringCopy(lastmessage, w_chat.l.l, + sizeof(lastmessage)); + } + plr->message = lastmessage; + } + } + else if (c == KEY_ESCAPE) + { + StopChatInput(); + } + } + } + + return eatkey; +} diff --git a/games/NXDoom/src/strife/hu_stuff.h b/games/NXDoom/src/strife/hu_stuff.h new file mode 100644 index 00000000000..2140d830ec2 --- /dev/null +++ b/games/NXDoom/src/strife/hu_stuff.h @@ -0,0 +1,75 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Head up display +// + +#ifndef __HU_STUFF_H__ +#define __HU_STUFF_H__ + +#include "d_event.h" +#include "v_patch.h" + +// +// Globally visible constants. +// +#define HU_FONTSTART '!' // the first font characters +#define HU_FONTEND '_' // the last font characters + +// Calculate # of glyphs in font. +#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) + +#define HU_BROADCAST 9 // haleyjd [STRIFE] Changed 5 -> 9 +#define HU_CHANGENAME 10 // haleyjd [STRIFE] Special command + +#define HU_MSGX 0 +#define HU_MSGY (SHORT(hu_font[0]->height) + 1) // [STRIFE]: DOOM bug fix +#define HU_MSGWIDTH 64 // in characters +#define HU_MSGHEIGHT 2 // in lines + +#define HU_MSGTIMEOUT (8*TICRATE) // haleyjd [STRIFE] Doubled message timeout + + +// +// HEADS UP TEXT +// + +void HU_Init(void); +void HU_Start(void); + +boolean HU_Responder(event_t* ev); + +void HU_Ticker(void); +void HU_Drawer(void); +char HU_dequeueChatChar(void); +void HU_Erase(void); + +extern char *chat_macros[10]; +extern char player_names[8][16]; // villsa [STRIFE] + +// haleyjd [STRIFE] externalized: +extern const char *mapnames[]; + +// [STRIFE] +extern patch_t* yfont[HU_FONTSIZE]; // haleyjd 09/18/10: [STRIFE] +extern patch_t *hu_font[HU_FONTSIZE]; + +extern boolean message_dontfuckwithme; + +extern boolean chat_on; +extern boolean sendsave; + + +#endif + diff --git a/games/NXDoom/src/strife/info.c b/games/NXDoom/src/strife/info.c new file mode 100644 index 00000000000..7976299b861 --- /dev/null +++ b/games/NXDoom/src/strife/info.c @@ -0,0 +1,11041 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Thing frame/state LUT, +// generated by multigen utilitiy. +// This one is the original DOOM version, preserved. +// + +#include +#include + +// Data. +#include "sounds.h" +#include "m_fixed.h" + +#include "info.h" + +#include "p_mobj.h" + +// villsa [STRIFE] +const char *sprnames[NUMSPRITES+1] = +{ + "PLAY", "PNCH", "WAVE", "RBPY", "TRGT", "XBOW", "MMIS", "RIFG", + "RIFF", "FLMT", "FLMF", "BLST", "BLSF", "GREN", "GREF", "SIGH", + "SIGF", "POW1", "POW2", "POW3", "ZAP1", "SPRY", "BLOD", "PUFY", + "SHT1", "SHT2", "GRIN", "GRAP", "UBAM", "BNG2", "BNG4", "BNG3", + "FLBE", "XPRK", "OCLW", "CCLW", "TEND", "MICR", "MISS", "AROW", + "ARWP", "TORP", "THIT", "TWAV", "MISL", "TFOG", "IFOG", "SHRD", + "RGIB", "MRYS", "MRNO", "MRST", "MRLK", "MRBD", "MRPN", "MRGT", + "BURN", "DISR", "PEAS", "GIBS", "AGRD", "ARMR", "SACR", "TNK1", + "TNK2", "TNK3", "TNK4", "TNK5", "TNK6", "NEAL", "BEGR", "HMN1", + "LEDR", "LEAD", "ROB1", "PGRD", "ROB2", "MLDR", "ORCL", "PRST", + "PDED", "ALN1", "AL1P", "NODE", "MTHD", "MNAM", "MNAL", "MDTH", + "NEST", "PODD", "ZAP6", "ZOT3", "ZAP7", "ZOT1", "ZAP5", "ZOT2", + "SEWR", "SPID", "ROB3", "RBB3", "PRGR", "BASE", "FRBL", "KLAX", + "TURT", "BALL", "PSTN", "SECR", "TARG", "RING", "EARS", "COMM", + "BOOM", "RATT", "HOGN", "DEAD", "SBAN", "BOTR", "HATR", "TOPR", + "COUP", "BUBB", "BUBF", "BUBC", "ASPR", "SPDL", "TOKN", "OTOK", + "HELT", "GUNT", "FULL", "MEAT", "JUNK", "FFOT", "DIE1", "BEAC", + "ARM1", "ARM2", "BARW", "BART", "LAMP", "LANT", "BARL", "BOWL", + "BRAZ", "TRCH", "LTRH", "LMPC", "LOGS", "TRHO", "WATR", "MUGG", + "FUSL", "CRD1", "CRD2", "TPAS", "KY1G", "KY2S", "KY3B", "HAND", + "CRYS", "PRIS", "PWR1", "PWR2", "PWR3", "ORAC", "GYID", "FUBR", + "WARE", "RCRY", "BCRY", "CHAP", "TUNL", "BLTK", "SECK", "MINE", + "REBL", "PROC", "ANKH", "GOID", "STMP", "MDKT", "COIN", "CRED", + "SACK", "CHST", "SHD1", "MASK", "UNIF", "OFIC", "PMAP", "PMUP", + "BLIT", "BBOX", "MSSL", "ROKT", "BRY1", "CPAC", "PQRL", "XQRL", + "GRN1", "GRN2", "BKPK", "RELC", "RIFL", "FLAM", "BFLM", "MMSL", + "TRPD", "GRND", "CBOW", "SIGL", "LITE", "CNDL", "CLBR", "LITS", + "LITB", "LITG", "ROK1", "ROK2", "ROK3", "ROK4", "LOGG", "RUB1", + "RUB2", "RUB3", "RUB4", "RUB5", "RUB6", "RUB7", "RUB8", "CHAN", + "STAT", "DSTA", "CRAB", "CAGE", "TREE", "TRE1", "BUSH", "SHRB", + "STAK", "BAR1", "VASE", "STOL", "POT1", "TUB1", "ANVL", "TLMP", + "TRAY", "APOW", "AFED", "DRIP", "CDRP", "SPLH", "WTFT", "HERT", + "TELP", "MONI", "STEL", "STLA", "STLE", "HUGE", "STLG", NULL +}; + + +// Doesn't work with g++, needs actionf_p1 +// villsa [STRIFE] +void A_Look(); +void A_RandomWalk(); +void A_FriendLook(); +void A_Listen(); +void A_Chase(); +void A_FaceTarget(); +void A_PeasantPunch(); +void A_ReaverAttack(); +void A_BulletAttack(); +void A_CheckTargetVisible(); +void A_SentinelAttack(); +void A_StalkerThink(); +void A_StalkerSetLook(); +void A_StalkerDrop(); +void A_StalkerScratch(); +void A_FloatWeave(); +void A_RobotMelee(); +void A_TemplarMauler(); +void A_CrusaderAttack(); +void A_CrusaderLeft(); +void A_CrusaderRight(); +void A_CheckTargetVisible2(); +void A_InqFlyCheck(); +void A_InqGrenade(); +void A_InqTakeOff(); +void A_InqFly(); +void A_FireSigilWeapon(); +void A_ProgrammerAttack(); +void A_Sigil_A_Action(); +void A_SpectreEAttack(); +void A_SpectreCAttack(); +void A_AlertSpectreC(); +void A_Sigil_E_Action(); +void A_SigilTrail(); +void A_SpectreDAttack(); +void A_FireSigilEOffshoot(); +void A_ShadowOff(); +void A_ModifyVisibility(); +void A_ShadowOn(); +void A_SetTLOptions(); +void A_BossMeleeAtk(); +void A_BishopAttack(); +void A_FireHookShot(); +void A_FireChainShot(); +void A_MissileSmoke(); +void A_SpawnSparkPuff(); +void A_Tracer(); +void A_ProgrammerMelee(); +void A_Scream(); +void A_XScream(); +void A_Pain(); +void A_PeasantCrash(); +void A_Fall(); +void A_HideZombie(); +void A_MerchantPain(); +void A_ProgrammerDie(); +void A_InqTossArm(); +void A_SpawnSpectreB(); +void A_SpawnSpectreD(); +void A_SpawnSpectreE(); +void A_SpawnEntity(); +void A_EntityDeath(); +void A_SpawnZombie(); +void A_ZombieInSpecialSector(); +void A_CrystalExplode(); +void A_QuestMsg(); +void A_ExtraLightOff(); +void A_CrystalRadiusAtk(); +void A_DeathExplode5(); +void A_DeathExplode1(); +void A_DeathExplode2(); +void A_DeathExplode3(); +void A_RaiseAlarm(); +void A_MissileTick(); +void A_SpawnGrenadeFire(); +void A_NodeChunk(); +void A_HeadChunk(); +void A_BurnSpread(); +void A_AcolyteSpecial(); +void A_BossDeath(); +void A_InqChase(); +void A_StalkerChase(); +void A_PlayerScream(); +void A_TeleportBeacon(); +void A_BodyParts(); +void A_ClaxonBlare(); +void A_ActiveSound(); +void A_ClearSoundTarget(); +void A_DropBurnFlesh(); +void A_FlameDeath(); +void A_ClearForceField(); +void A_WeaponReady(); +void A_ReFire(); +void A_CheckReload(); +void A_Lower(); +void A_Raise(); +void A_GunFlash(); +void A_Punch(); +void A_FireFlameThrower(); +void A_FireMissile(); +void A_FireMauler2(); +void A_FireGrenade(); +void A_FireElectricBolt(); +void A_FirePoisonBolt(); +void A_FireRifle(); +void A_FireMauler1(); +void A_SigilSound(); +void A_FireSigil(); +void A_GunFlashThinker(); +void A_Light0(); +void A_Light1(); +void A_Light2(); +void A_SigilShock(); +void A_TorpedoExplode(); +void A_MaulerSound(); + +// villsa [STRIFE] +state_t states[NUMSTATES] = +{ + +/*S_NULL*/ { SPR_PLAY, 0, -1, { NULL }, S_NULL }, //00 +/*S_PNCH_00*/ { SPR_PNCH, 0, 0, { A_Light0 }, S_NULL }, //01 +/*S_WAVE_00*/ { SPR_WAVE, 32768, 3, { NULL }, S_WAVE_01 }, //02 +/*S_WAVE_01*/ { SPR_WAVE, 32769, 3, { NULL }, S_WAVE_02 }, //03 +/*S_WAVE_02*/ { SPR_WAVE, 32770, 3, { NULL }, S_WAVE_03 }, //04 +/*S_WAVE_03*/ { SPR_WAVE, 32771, 3, { NULL }, S_WAVE_00 }, //05 +/*S_RBPY_00*/ { SPR_RBPY, 32768, 3, { NULL }, S_RBPY_01 }, //06 +/*S_RBPY_01*/ { SPR_RBPY, 32769, 3, { NULL }, S_RBPY_02 }, //07 +/*S_RBPY_02*/ { SPR_RBPY, 32770, 3, { NULL }, S_RBPY_03 }, //08 +/*S_RBPY_03*/ { SPR_RBPY, 32771, 3, { NULL }, S_RBPY_00 }, //09 +/*S_TRGT_00*/ { SPR_TRGT, 0, -1, { NULL }, S_NULL }, //10 +/*S_TRGT_01*/ { SPR_TRGT, 1, -1, { NULL }, S_NULL }, //11 +/*S_TRGT_02*/ { SPR_TRGT, 2, -1, { NULL }, S_NULL }, //12 +/*S_PNCH_01*/ { SPR_PNCH, 0, 1, { A_WeaponReady }, S_PNCH_01 }, //13 +/*S_PNCH_02*/ { SPR_PNCH, 0, 1, { A_Lower }, S_PNCH_02 }, //14 +/*S_PNCH_03*/ { SPR_PNCH, 0, 1, { A_Raise }, S_PNCH_03 }, //15 +/*S_PNCH_04*/ { SPR_PNCH, 1, 4, { NULL }, S_PNCH_05 }, //16 +/*S_PNCH_05*/ { SPR_PNCH, 2, 4, { A_Punch }, S_PNCH_06 }, //17 +/*S_PNCH_06*/ { SPR_PNCH, 3, 5, { NULL }, S_PNCH_07 }, //18 +/*S_PNCH_07*/ { SPR_PNCH, 2, 4, { NULL }, S_PNCH_08 }, //19 +/*S_PNCH_08*/ { SPR_PNCH, 1, 5, { A_ReFire }, S_PNCH_01 }, //20 +/*S_XBOW_00*/ { SPR_XBOW, 0, 1, { A_WeaponReady }, S_XBOW_00 }, //21 +/*S_XBOW_01*/ { SPR_XBOW, 0, 1, { A_Lower }, S_XBOW_01 }, //22 +/*S_XBOW_02*/ { SPR_XBOW, 0, 1, { A_Raise }, S_XBOW_02 }, //23 +/*S_XBOW_03*/ { SPR_XBOW, 0, 3, { A_GunFlashThinker }, S_XBOW_04 }, //24 +/*S_XBOW_04*/ { SPR_XBOW, 1, 6, { A_FireElectricBolt }, S_XBOW_05 }, //25 +/*S_XBOW_05*/ { SPR_XBOW, 2, 4, { NULL }, S_XBOW_06 }, //26 +/*S_XBOW_06*/ { SPR_XBOW, 3, 6, { NULL }, S_XBOW_07 }, //27 +/*S_XBOW_07*/ { SPR_XBOW, 4, 3, { NULL }, S_XBOW_08 }, //28 +/*S_XBOW_08*/ { SPR_XBOW, 5, 5, { NULL }, S_XBOW_09 }, //29 +/*S_XBOW_09*/ { SPR_XBOW, 6, 5, { A_CheckReload }, S_XBOW_00 }, //30 +/*S_XBOW_10*/ { SPR_XBOW, 10, 5, { NULL }, S_XBOW_11 }, //31 +/*S_XBOW_11*/ { SPR_XBOW, 11, 5, { NULL }, S_XBOW_12 }, //32 +/*S_XBOW_12*/ { SPR_XBOW, 12, 5, { NULL }, S_XBOW_10 }, //33 +/*S_XBOW_13*/ { SPR_XBOW, 7, 1, { A_WeaponReady }, S_XBOW_13 }, //34 +/*S_XBOW_14*/ { SPR_XBOW, 7, 1, { A_Lower }, S_XBOW_14 }, //35 +/*S_XBOW_15*/ { SPR_XBOW, 7, 1, { A_Raise }, S_XBOW_15 }, //36 +/*S_XBOW_16*/ { SPR_XBOW, 7, 3, { NULL }, S_XBOW_17 }, //37 +/*S_XBOW_17*/ { SPR_XBOW, 1, 6, { A_FirePoisonBolt }, S_XBOW_18 }, //38 +/*S_XBOW_18*/ { SPR_XBOW, 2, 4, { NULL }, S_XBOW_19 }, //39 +/*S_XBOW_19*/ { SPR_XBOW, 3, 6, { NULL }, S_XBOW_20 }, //40 +/*S_XBOW_20*/ { SPR_XBOW, 4, 3, { NULL }, S_XBOW_21 }, //41 +/*S_XBOW_21*/ { SPR_XBOW, 8, 5, { NULL }, S_XBOW_22 }, //42 +/*S_XBOW_22*/ { SPR_XBOW, 9, 5, { A_CheckReload }, S_XBOW_13 }, //43 +/*S_MMIS_00*/ { SPR_MMIS, 0, 1, { A_WeaponReady }, S_MMIS_00 }, //44 +/*S_MMIS_01*/ { SPR_MMIS, 0, 1, { A_Lower }, S_MMIS_01 }, //45 +/*S_MMIS_02*/ { SPR_MMIS, 0, 1, { A_Raise }, S_MMIS_02 }, //46 +/*S_MMIS_03*/ { SPR_MMIS, 0, 4, { A_FireMissile }, S_MMIS_04 }, //47 +/*S_MMIS_04*/ { SPR_MMIS, 1, 4, { A_Light1 }, S_MMIS_05 }, //48 +/*S_MMIS_05*/ { SPR_MMIS, 32770, 5, { NULL }, S_MMIS_06 }, //49 +/*S_MMIS_06*/ { SPR_MMIS, 32771, 2, { A_Light2 }, S_MMIS_07 }, //50 +/*S_MMIS_07*/ { SPR_MMIS, 32772, 2, { NULL }, S_MMIS_08 }, //51 +/*S_MMIS_08*/ { SPR_MMIS, 32773, 2, { A_Light0 }, S_MMIS_09 }, //52 +/*S_MMIS_09*/ { SPR_MMIS, 5, 0, { A_ReFire }, S_MMIS_00 }, //53 +/*S_RIFG_00*/ { SPR_RIFG, 0, 1, { A_WeaponReady }, S_RIFG_00 }, //54 +/*S_RIFG_01*/ { SPR_RIFG, 1, 1, { A_Lower }, S_RIFG_01 }, //55 +/*S_RIFG_02*/ { SPR_RIFG, 0, 1, { A_Raise }, S_RIFG_02 }, //56 +/*S_RIFF_00*/ { SPR_RIFF, 0, 3, { A_FireRifle }, S_RIFF_01 }, //57 +/*S_RIFF_01*/ { SPR_RIFF, 1, 3, { A_FireRifle }, S_RIFG_03 }, //58 +/*S_RIFG_03*/ { SPR_RIFG, 3, 3, { A_FireRifle }, S_RIFG_04 }, //59 +/*S_RIFG_04*/ { SPR_RIFG, 2, 0, { A_ReFire }, S_RIFG_05 }, //60 +/*S_RIFG_05*/ { SPR_RIFG, 1, 2, { NULL }, S_RIFG_00 }, //61 +/*S_FLMT_00*/ { SPR_FLMT, 0, 3, { A_WeaponReady }, S_FLMT_01 }, //62 +/*S_FLMT_01*/ { SPR_FLMT, 1, 3, { A_WeaponReady }, S_FLMT_00 }, //63 +/*S_FLMT_02*/ { SPR_FLMT, 0, 1, { A_Lower }, S_FLMT_02 }, //64 +/*S_FLMT_03*/ { SPR_FLMT, 0, 1, { A_Raise }, S_FLMT_03 }, //65 +/*S_FLMF_00*/ { SPR_FLMF, 0, 2, { A_FireFlameThrower }, S_FLMF_01 }, //66 +/*S_FLMF_01*/ { SPR_FLMF, 1, 3, { A_ReFire }, S_FLMT_00 }, //67 +/*S_BLST_00*/ { SPR_BLST, 5, 6, { A_WeaponReady }, S_BLST_01 }, //68 +/*S_BLST_01*/ { SPR_BLST, 6, 6, { A_WeaponReady }, S_BLST_02 }, //69 +/*S_BLST_02*/ { SPR_BLST, 7, 6, { A_WeaponReady }, S_BLST_03 }, //70 +/*S_BLST_03*/ { SPR_BLST, 0, 6, { A_WeaponReady }, S_BLST_00 }, //71 +/*S_BLST_04*/ { SPR_BLST, 0, 1, { A_Lower }, S_BLST_04 }, //72 +/*S_BLST_05*/ { SPR_BLST, 0, 1, { A_Raise }, S_BLST_05 }, //73 +/*S_BLSF_00*/ { SPR_BLSF, 32768, 5, { A_FireMauler1 }, S_BLST_06 }, //74 +/*S_BLST_06*/ { SPR_BLST, 32769, 3, { A_Light1 }, S_BLST_07 }, //75 +/*S_BLST_07*/ { SPR_BLST, 2, 2, { A_Light2 }, S_BLST_08 }, //76 +/*S_BLST_08*/ { SPR_BLST, 3, 2, { NULL }, S_BLST_09 }, //77 +/*S_BLST_09*/ { SPR_BLST, 4, 2, { NULL }, S_BLST_10 }, //78 +/*S_BLST_10*/ { SPR_BLST, 0, 7, { A_Light0 }, S_BLST_11 }, //79 +/*S_BLST_11*/ { SPR_BLST, 7, 7, { NULL }, S_BLST_12 }, //80 +/*S_BLST_12*/ { SPR_BLST, 6, 7, { A_CheckReload }, S_BLST_00 }, //81 +/*S_BLST_13*/ { SPR_BLST, 8, 7, { A_WeaponReady }, S_BLST_14 }, //82 +/*S_BLST_14*/ { SPR_BLST, 9, 7, { A_WeaponReady }, S_BLST_15 }, //83 +/*S_BLST_15*/ { SPR_BLST, 10, 7, { A_WeaponReady }, S_BLST_16 }, //84 +/*S_BLST_16*/ { SPR_BLST, 11, 7, { A_WeaponReady }, S_BLST_13 }, //85 +/*S_BLST_17*/ { SPR_BLST, 8, 1, { A_Lower }, S_BLST_17 }, //86 +/*S_BLST_18*/ { SPR_BLST, 8, 1, { A_Raise }, S_BLST_18 }, //87 +/*S_BLST_19*/ { SPR_BLST, 8, 20, { A_MaulerSound }, S_BLST_20 }, //88 +/*S_BLST_20*/ { SPR_BLST, 9, 10, { A_Light1 }, S_BLSF_01 }, //89 +/*S_BLSF_01*/ { SPR_BLSF, 32768, 10, { A_FireMauler2 }, S_BLST_21 }, //90 +/*S_BLST_21*/ { SPR_BLST, 32769, 3, { A_Light2 }, S_BLST_22 }, //91 +/*S_BLST_22*/ { SPR_BLST, 2, 2, { NULL }, S_BLST_23 }, //92 +/*S_BLST_23*/ { SPR_BLST, 3, 2, { A_Light0 }, S_BLST_24 }, //93 +/*S_BLST_24*/ { SPR_BLST, 4, 2, { A_ReFire }, S_BLST_13 }, //94 +/*S_GREN_00*/ { SPR_GREN, 0, 1, { A_WeaponReady }, S_GREN_00 }, //95 +/*S_GREN_01*/ { SPR_GREN, 0, 1, { A_Lower }, S_GREN_01 }, //96 +/*S_GREN_02*/ { SPR_GREN, 0, 1, { A_Raise }, S_GREN_02 }, //97 +/*S_GREN_03*/ { SPR_GREN, 0, 5, { A_FireGrenade }, S_GREN_04 }, //98 +/*S_GREN_04*/ { SPR_GREN, 1, 10, { NULL }, S_GREN_05 }, //99 +/*S_GREN_05*/ { SPR_GREN, 0, 5, { A_FireGrenade }, S_GREN_06 }, //100 +/*S_GREN_06*/ { SPR_GREN, 2, 10, { NULL }, S_GREN_07 }, //101 +/*S_GREN_07*/ { SPR_GREN, 0, 0, { A_ReFire }, S_GREN_00 }, //102 +/*S_GREF_00*/ { SPR_GREF, 32768, 5, { A_Light1 }, S_PNCH_00 }, //103 +/*S_GREF_01*/ { SPR_GREF, 0, 10, { A_Light0 }, S_PNCH_00 }, //104 +/*S_GREF_02*/ { SPR_GREF, 32769, 5, { A_Light2 }, S_PNCH_00 }, //105 +/*S_GREN_08*/ { SPR_GREN, 3, 1, { A_WeaponReady }, S_GREN_08 }, //106 +/*S_GREN_09*/ { SPR_GREN, 3, 1, { A_Lower }, S_GREN_09 }, //107 +/*S_GREN_10*/ { SPR_GREN, 3, 1, { A_Raise }, S_GREN_10 }, //108 +/*S_GREN_11*/ { SPR_GREN, 3, 5, { A_FireGrenade }, S_GREN_12 }, //109 +/*S_GREN_12*/ { SPR_GREN, 4, 10, { NULL }, S_GREN_13 }, //110 +/*S_GREN_13*/ { SPR_GREN, 3, 5, { A_FireGrenade }, S_GREN_14 }, //111 +/*S_GREN_14*/ { SPR_GREN, 5, 10, { NULL }, S_GREN_15 }, //112 +/*S_GREN_15*/ { SPR_GREN, 0, 0, { A_ReFire }, S_GREN_08 }, //113 +/*S_GREF_03*/ { SPR_GREF, 32770, 5, { A_Light1 }, S_PNCH_00 }, //114 +/*S_GREF_04*/ { SPR_GREF, 2, 10, { A_Light0 }, S_PNCH_00 }, //115 +/*S_GREF_05*/ { SPR_GREF, 32771, 5, { A_Light2 }, S_PNCH_00 }, //116 +/*S_SIGH_00*/ { SPR_SIGH, 32768, 1, { A_WeaponReady }, S_SIGH_00 }, //117 +/*S_SIGH_01*/ { SPR_SIGH, 32769, -1, { NULL }, S_NULL }, //118 +/*S_SIGH_02*/ { SPR_SIGH, 32770, -1, { NULL }, S_NULL }, //119 +/*S_SIGH_03*/ { SPR_SIGH, 32771, -1, { NULL }, S_NULL }, //120 +/*S_SIGH_04*/ { SPR_SIGH, 32772, -1, { NULL }, S_NULL }, //121 +/*S_SIGH_05*/ { SPR_SIGH, 32768, 1, { A_Lower }, S_SIGH_05 }, //122 +/*S_SIGH_06*/ { SPR_SIGH, 32768, 1, { A_Raise }, S_SIGH_06 }, //123 +/*S_SIGH_07*/ { SPR_SIGH, 32768, 18, { A_SigilSound }, S_SIGH_08 }, //124 +/*S_SIGH_08*/ { SPR_SIGH, 32768, 3, { A_GunFlash }, S_SIGH_09 }, //125 +/*S_SIGH_09*/ { SPR_SIGH, 0, 10, { A_FireSigil }, S_SIGH_10 }, //126 +/*S_SIGH_10*/ { SPR_SIGH, 0, 5, { A_GunFlashThinker }, S_SIGH_00 }, //127 +/*S_SIGF_00*/ { SPR_SIGF, 32768, 4, { A_Light2 }, S_SIGF_01 }, //128 +/*S_SIGF_01*/ { SPR_SIGF, 32769, 6, { A_SigilShock }, S_SIGF_02 }, //129 +/*S_SIGF_02*/ { SPR_SIGF, 32770, 4, { A_Light1 }, S_PNCH_00 }, //130 +/*S_POW1_00*/ { SPR_POW1, 0, 4, { NULL }, S_POW1_01 }, //131 +/*S_POW1_01*/ { SPR_POW1, 1, 4, { NULL }, S_POW1_02 }, //132 +/*S_POW1_02*/ { SPR_POW1, 2, 4, { NULL }, S_POW1_03 }, //133 +/*S_POW1_03*/ { SPR_POW1, 3, 4, { NULL }, S_POW1_04 }, //134 +/*S_POW1_04*/ { SPR_POW1, 4, 4, { NULL }, S_NULL }, //135 +/*S_POW1_05*/ { SPR_POW1, 5, 4, { NULL }, S_POW1_06 }, //136 +/*S_POW1_06*/ { SPR_POW1, 6, 4, { NULL }, S_POW1_07 }, //137 +/*S_POW1_07*/ { SPR_POW1, 7, 4, { NULL }, S_POW1_08 }, //138 +/*S_POW1_08*/ { SPR_POW1, 8, 4, { NULL }, S_POW1_09 }, //139 +/*S_POW1_09*/ { SPR_POW1, 9, 4, { NULL }, S_NULL }, //140 +/*S_POW2_00*/ { SPR_POW2, 0, 4, { NULL }, S_POW2_01 }, //141 +/*S_POW2_01*/ { SPR_POW2, 1, 4, { NULL }, S_POW2_02 }, //142 +/*S_POW2_02*/ { SPR_POW2, 2, 4, { NULL }, S_POW2_03 }, //143 +/*S_POW2_03*/ { SPR_POW2, 3, 4, { NULL }, S_NULL }, //144 +/*S_POW3_00*/ { SPR_POW3, 0, 3, { NULL }, S_POW3_01 }, //145 +/*S_POW3_01*/ { SPR_POW3, 1, 3, { NULL }, S_POW3_02 }, //146 +/*S_POW3_02*/ { SPR_POW3, 2, 3, { NULL }, S_POW3_03 }, //147 +/*S_POW3_03*/ { SPR_POW3, 3, 3, { NULL }, S_POW3_04 }, //148 +/*S_POW3_04*/ { SPR_POW3, 4, 3, { NULL }, S_POW3_05 }, //149 +/*S_POW3_05*/ { SPR_POW3, 5, 3, { NULL }, S_POW3_06 }, //150 +/*S_POW3_06*/ { SPR_POW3, 6, 3, { NULL }, S_POW3_07 }, //151 +/*S_POW3_07*/ { SPR_POW3, 7, 3, { NULL }, S_NULL }, //152 +/*S_ZAP1_00*/ { SPR_ZAP1, 1, 3, { A_DeathExplode3 }, S_ZAP1_02 }, //153 +/*S_ZAP1_01*/ { SPR_ZAP1, 0, 3, { A_RaiseAlarm }, S_ZAP1_02 }, //154 +/*S_ZAP1_02*/ { SPR_ZAP1, 1, 3, { NULL }, S_ZAP1_03 }, //155 +/*S_ZAP1_03*/ { SPR_ZAP1, 2, 3, { NULL }, S_ZAP1_04 }, //156 +/*S_ZAP1_04*/ { SPR_ZAP1, 3, 3, { NULL }, S_ZAP1_05 }, //157 +/*S_ZAP1_05*/ { SPR_ZAP1, 4, 3, { NULL }, S_ZAP1_06 }, //158 +/*S_ZAP1_06*/ { SPR_ZAP1, 5, 3, { NULL }, S_ZAP1_07 }, //159 +/*S_ZAP1_07*/ { SPR_ZAP1, 4, 3, { NULL }, S_ZAP1_08 }, //160 +/*S_ZAP1_08*/ { SPR_ZAP1, 3, 2, { NULL }, S_ZAP1_09 }, //161 +/*S_ZAP1_09*/ { SPR_ZAP1, 2, 2, { NULL }, S_ZAP1_10 }, //162 +/*S_ZAP1_10*/ { SPR_ZAP1, 1, 2, { NULL }, S_ZAP1_11 }, //163 +/*S_ZAP1_11*/ { SPR_ZAP1, 0, 1, { NULL }, S_NULL }, //164 +/*S_SPRY_00*/ { SPR_SPRY, 0, 3, { NULL }, S_SPRY_01 }, //165 +/*S_SPRY_01*/ { SPR_SPRY, 1, 3, { NULL }, S_SPRY_02 }, //166 +/*S_SPRY_02*/ { SPR_SPRY, 2, 3, { NULL }, S_SPRY_03 }, //167 +/*S_SPRY_03*/ { SPR_SPRY, 3, 3, { NULL }, S_SPRY_04 }, //168 +/*S_SPRY_04*/ { SPR_SPRY, 4, 3, { NULL }, S_SPRY_05 }, //169 +/*S_SPRY_05*/ { SPR_SPRY, 5, 3, { NULL }, S_SPRY_06 }, //170 +/*S_SPRY_06*/ { SPR_SPRY, 6, 2, { NULL }, S_NULL }, //171 +/*S_BLOD_00*/ { SPR_BLOD, 2, 8, { NULL }, S_BLOD_01 }, //172 +/*S_BLOD_01*/ { SPR_BLOD, 1, 8, { NULL }, S_BLOD_02 }, //173 +/*S_BLOD_02*/ { SPR_BLOD, 0, 8, { NULL }, S_NULL }, //174 +/*S_PUFY_00*/ { SPR_PUFY, 32768, 4, { NULL }, S_PUFY_01 }, //175 +/*S_PUFY_01*/ { SPR_PUFY, 1, 4, { NULL }, S_PUFY_02 }, //176 +/*S_PUFY_02*/ { SPR_PUFY, 2, 4, { NULL }, S_PUFY_03 }, //177 +/*S_PUFY_03*/ { SPR_PUFY, 3, 4, { NULL }, S_NULL }, //178 +/*S_SHT1_00*/ { SPR_SHT1, 0, 4, { NULL }, S_SHT1_01 }, //179 +/*S_SHT1_01*/ { SPR_SHT1, 1, 4, { NULL }, S_SHT1_00 }, //180 +/*S_SHT2_00*/ { SPR_SHT2, 0, 5, { NULL }, S_SHT2_01 }, //181 +/*S_SHT2_01*/ { SPR_SHT2, 1, 5, { NULL }, S_POW1_00 }, //182 +/*S_GRIN_00*/ { SPR_GRIN, 0, 3, { A_MissileTick }, S_GRIN_01 }, //183 +/*S_GRIN_01*/ { SPR_GRIN, 1, 3, { A_MissileTick }, S_GRIN_00 }, //184 +/*S_GRAP_00*/ { SPR_GRAP, 0, 3, { A_MissileTick }, S_GRAP_01 }, //185 +/*S_GRAP_01*/ { SPR_GRAP, 1, 3, { A_MissileTick }, S_GRAP_00 }, //186 +/*S_UBAM_00*/ { SPR_UBAM, 0, 3, { A_MissileTick }, S_UBAM_01 }, //187 +/*S_UBAM_01*/ { SPR_UBAM, 1, 3, { A_MissileTick }, S_UBAM_00 }, //188 +/*S_BNG2_00*/ { SPR_BNG2, 32768, 4, { A_DeathExplode5 }, S_BNG2_01 }, //189 +/*S_BNG2_01*/ { SPR_BNG2, 32769, 4, { NULL }, S_BNG2_02 }, //190 +/*S_BNG2_02*/ { SPR_BNG2, 32770, 4, { NULL }, S_BNG2_03 }, //191 +/*S_BNG2_03*/ { SPR_BNG2, 32771, 4, { NULL }, S_BNG2_04 }, //192 +/*S_BNG2_04*/ { SPR_BNG2, 32772, 4, { NULL }, S_BNG2_05 }, //193 +/*S_BNG2_05*/ { SPR_BNG2, 32773, 4, { NULL }, S_BNG2_06 }, //194 +/*S_BNG2_06*/ { SPR_BNG2, 32774, 4, { NULL }, S_BNG2_07 }, //195 +/*S_BNG2_07*/ { SPR_BNG2, 32775, 4, { NULL }, S_BNG2_08 }, //196 +/*S_BNG2_08*/ { SPR_BNG2, 32776, 4, { NULL }, S_NULL }, //197 +/*S_BNG4_00*/ { SPR_BNG4, 32768, 2, { A_DeathExplode5 }, S_BNG4_01 }, //198 +/*S_BNG4_01*/ { SPR_BNG4, 32769, 3, { NULL }, S_BNG4_02 }, //199 +/*S_BNG4_02*/ { SPR_BNG4, 32770, 3, { NULL }, S_BNG4_03 }, //200 +/*S_BNG4_03*/ { SPR_BNG4, 32771, 3, { NULL }, S_BNG4_04 }, //201 +/*S_BNG4_04*/ { SPR_BNG4, 32772, 3, { NULL }, S_BNG4_05 }, //202 +/*S_BNG4_05*/ { SPR_BNG4, 32773, 3, { NULL }, S_BNG4_06 }, //203 +/*S_BNG4_06*/ { SPR_BNG4, 32774, 3, { NULL }, S_BNG4_07 }, //204 +/*S_BNG4_07*/ { SPR_BNG4, 32775, 3, { NULL }, S_BNG4_08 }, //205 +/*S_BNG4_08*/ { SPR_BNG4, 32776, 3, { NULL }, S_BNG4_09 }, //206 +/*S_BNG4_09*/ { SPR_BNG4, 32777, 3, { NULL }, S_BNG4_10 }, //207 +/*S_BNG4_10*/ { SPR_BNG4, 32778, 3, { NULL }, S_BNG4_11 }, //208 +/*S_BNG4_11*/ { SPR_BNG4, 32779, 3, { NULL }, S_BNG4_12 }, //209 +/*S_BNG4_12*/ { SPR_BNG4, 32780, 3, { NULL }, S_BNG4_13 }, //210 +/*S_BNG4_13*/ { SPR_BNG4, 32781, 3, { NULL }, S_NULL }, //211 +/*S_BNG3_00*/ { SPR_BNG3, 32768, 3, { A_DeathExplode5 }, S_BNG3_01 }, //212 +/*S_BNG3_01*/ { SPR_BNG3, 32769, 3, { NULL }, S_BNG3_02 }, //213 +/*S_BNG3_02*/ { SPR_BNG3, 32770, 3, { NULL }, S_BNG3_03 }, //214 +/*S_BNG3_03*/ { SPR_BNG3, 32771, 3, { NULL }, S_BNG3_04 }, //215 +/*S_BNG3_04*/ { SPR_BNG3, 32772, 3, { NULL }, S_BNG3_05 }, //216 +/*S_BNG3_05*/ { SPR_BNG3, 32773, 3, { NULL }, S_BNG3_06 }, //217 +/*S_BNG3_06*/ { SPR_BNG3, 32774, 3, { NULL }, S_BNG3_07 }, //218 +/*S_BNG3_07*/ { SPR_BNG3, 32775, 3, { NULL }, S_NULL }, //219 +/*S_BNG3_08*/ { SPR_BNG3, 0, 1, { A_SpawnGrenadeFire }, S_NULL }, //220 +/*S_BNG3_09*/ { SPR_BNG3, 32769, 2, { A_DeathExplode1 }, S_BNG3_10 }, //221 +/*S_BNG3_10*/ { SPR_BNG3, 32770, 2, { A_MissileTick }, S_FLBE_00 }, //222 +/*S_FLBE_00*/ { SPR_FLBE, 32768, 2, { A_BurnSpread }, S_FLBE_01 }, //223 +/*S_FLBE_01*/ { SPR_FLBE, 32769, 2, { A_MissileTick }, S_FLBE_02 }, //224 +/*S_FLBE_02*/ { SPR_FLBE, 32770, 2, { A_DeathExplode1 }, S_FLBE_03 }, //225 +/*S_FLBE_03*/ { SPR_FLBE, 32771, 3, { A_MissileTick }, S_FLBE_04 }, //226 +/*S_FLBE_04*/ { SPR_FLBE, 32772, 3, { A_DeathExplode1 }, S_FLBE_05 }, //227 +/*S_FLBE_05*/ { SPR_FLBE, 32773, 3, { A_MissileTick }, S_FLBE_06 }, //228 +/*S_FLBE_06*/ { SPR_FLBE, 32774, 3, { A_BurnSpread }, S_FLBE_03 }, //229 +/*S_FLBE_07*/ { SPR_FLBE, 32775, 2, { NULL }, S_FLBE_08 }, //230 +/*S_FLBE_08*/ { SPR_FLBE, 32776, 2, { A_BurnSpread }, S_FLBE_09 }, //231 +/*S_FLBE_09*/ { SPR_FLBE, 32777, 2, { NULL }, S_FLBE_10 }, //232 +/*S_FLBE_10*/ { SPR_FLBE, 32778, 2, { NULL }, S_NULL }, //233 +/*S_XPRK_00*/ { SPR_XPRK, 0, 1, { A_ClearForceField }, S_NULL }, //234 +/*S_OCLW_00*/ { SPR_OCLW, 0, 2, { A_FireChainShot }, S_OCLW_00 }, //235 +/*S_CCLW_00*/ { SPR_CCLW, 0, 6, { NULL }, S_NULL }, //236 +/*S_TEND_00*/ { SPR_TEND, 0, 20, { NULL }, S_NULL }, //237 +/*S_MICR_00*/ { SPR_MICR, 32768, 6, { A_MissileSmoke }, S_MICR_00 }, //238 +/*S_MISS_00*/ { SPR_MISS, 32768, 4, { A_MissileSmoke }, S_MISS_01 }, //239 +/*S_MISS_01*/ { SPR_MISS, 32769, 3, { A_Tracer }, S_MISS_00 }, //240 +/*S_AROW_00*/ { SPR_AROW, 0, 10, { A_ActiveSound }, S_AROW_00 }, //241 +/*S_ARWP_00*/ { SPR_ARWP, 0, 10, { A_ActiveSound }, S_ARWP_00 }, //242 +/*S_AROW_01*/ { SPR_AROW, 0, 1, { NULL }, S_NULL }, //243 +/*S_TORP_00*/ { SPR_TORP, 32768, 4, { NULL }, S_TORP_01 }, //244 +/*S_TORP_01*/ { SPR_TORP, 32769, 4, { NULL }, S_TORP_02 }, //245 +/*S_TORP_02*/ { SPR_TORP, 32770, 4, { NULL }, S_TORP_03 }, //246 +/*S_TORP_03*/ { SPR_TORP, 32771, 4, { NULL }, S_TORP_00 }, //247 +/*S_THIT_00*/ { SPR_THIT, 32768, 8, { NULL }, S_THIT_01 }, //248 +/*S_THIT_01*/ { SPR_THIT, 32769, 8, { NULL }, S_THIT_02 }, //249 +/*S_THIT_02*/ { SPR_THIT, 32770, 8, { A_TorpedoExplode }, S_THIT_03 }, //250 +/*S_THIT_03*/ { SPR_THIT, 32771, 8, { NULL }, S_THIT_04 }, //251 +/*S_THIT_04*/ { SPR_THIT, 32772, 8, { NULL }, S_NULL }, //252 +/*S_TWAV_00*/ { SPR_TWAV, 32768, 9, { NULL }, S_TWAV_01 }, //253 +/*S_TWAV_01*/ { SPR_TWAV, 32769, 9, { NULL }, S_TWAV_02 }, //254 +/*S_TWAV_02*/ { SPR_TWAV, 32770, 9, { NULL }, S_NULL }, //255 +/*S_MISL_00*/ { SPR_MISL, 32768, 5, { NULL }, S_MISL_02 }, //256 +/*S_MISL_01*/ { SPR_MISL, 32768, 5, { A_DeathExplode2 }, S_MISL_02 }, //257 +/*S_MISL_02*/ { SPR_MISL, 32769, 5, { NULL }, S_MISL_03 }, //258 +/*S_MISL_03*/ { SPR_MISL, 32770, 4, { NULL }, S_MISL_04 }, //259 +/*S_MISL_04*/ { SPR_MISL, 32771, 2, { NULL }, S_MISL_05 }, //260 +/*S_MISL_05*/ { SPR_MISL, 32772, 2, { NULL }, S_MISL_06 }, //261 +/*S_MISL_06*/ { SPR_MISL, 32773, 2, { NULL }, S_MISL_07 }, //262 +/*S_MISL_07*/ { SPR_MISL, 32774, 2, { NULL }, S_NULL }, //263 +/*S_TFOG_00*/ { SPR_TFOG, 32768, 6, { NULL }, S_TFOG_01 }, //264 +/*S_TFOG_01*/ { SPR_TFOG, 32769, 6, { NULL }, S_TFOG_02 }, //265 +/*S_TFOG_02*/ { SPR_TFOG, 32770, 6, { NULL }, S_TFOG_03 }, //266 +/*S_TFOG_03*/ { SPR_TFOG, 32771, 6, { NULL }, S_TFOG_04 }, //267 +/*S_TFOG_04*/ { SPR_TFOG, 32772, 6, { NULL }, S_TFOG_05 }, //268 +/*S_TFOG_05*/ { SPR_TFOG, 32773, 6, { NULL }, S_TFOG_06 }, //269 +/*S_TFOG_06*/ { SPR_TFOG, 32772, 6, { NULL }, S_TFOG_07 }, //270 +/*S_TFOG_07*/ { SPR_TFOG, 32771, 6, { NULL }, S_TFOG_08 }, //271 +/*S_TFOG_08*/ { SPR_TFOG, 32770, 6, { NULL }, S_TFOG_09 }, //272 +/*S_TFOG_09*/ { SPR_TFOG, 32769, 6, { NULL }, S_NULL }, //273 +/*S_IFOG_00*/ { SPR_IFOG, 32768, 6, { NULL }, S_IFOG_01 }, //274 +/*S_IFOG_01*/ { SPR_IFOG, 32769, 6, { NULL }, S_IFOG_02 }, //275 +/*S_IFOG_02*/ { SPR_IFOG, 32768, 6, { NULL }, S_IFOG_03 }, //276 +/*S_IFOG_03*/ { SPR_IFOG, 32769, 6, { NULL }, S_IFOG_04 }, //277 +/*S_IFOG_04*/ { SPR_IFOG, 32770, 6, { NULL }, S_IFOG_05 }, //278 +/*S_IFOG_05*/ { SPR_IFOG, 32771, 6, { NULL }, S_IFOG_06 }, //279 +/*S_IFOG_06*/ { SPR_IFOG, 32772, 6, { NULL }, S_NULL }, //280 +/*S_SHRD_00*/ { SPR_SHRD, 0, 128, { NULL }, S_NULL }, //281 +/*S_SHRD_01*/ { SPR_SHRD, 1, 128, { NULL }, S_NULL }, //282 +/*S_SHRD_02*/ { SPR_SHRD, 2, 128, { NULL }, S_NULL }, //283 +/*S_SHRD_03*/ { SPR_SHRD, 3, 128, { NULL }, S_NULL }, //284 +/*S_SHRD_04*/ { SPR_SHRD, 4, 128, { NULL }, S_NULL }, //285 +/*S_SHRD_05*/ { SPR_SHRD, 5, 128, { NULL }, S_NULL }, //286 +/*S_PLAY_00*/ { SPR_PLAY, 0, -1, { NULL }, S_NULL }, //287 +/*S_PLAY_01*/ { SPR_PLAY, 0, 4, { NULL }, S_PLAY_02 }, //288 +/*S_PLAY_02*/ { SPR_PLAY, 1, 4, { NULL }, S_PLAY_03 }, //289 +/*S_PLAY_03*/ { SPR_PLAY, 2, 4, { NULL }, S_PLAY_04 }, //290 +/*S_PLAY_04*/ { SPR_PLAY, 3, 4, { NULL }, S_PLAY_01 }, //291 +/*S_PLAY_05*/ { SPR_PLAY, 4, 12, { NULL }, S_PLAY_00 }, //292 +/*S_PLAY_06*/ { SPR_PLAY, 5, 6, { NULL }, S_PLAY_05 }, //293 +/*S_PLAY_07*/ { SPR_PLAY, 16, 4, { A_Pain }, S_PLAY_08 }, //294 +/*S_PLAY_08*/ { SPR_PLAY, 16, 4, { NULL }, S_PLAY_00 }, //295 +/*S_PLAY_09*/ { SPR_PLAY, 6, 4, { NULL }, S_PLAY_10 }, //296 +/*S_PLAY_10*/ { SPR_PLAY, 7, 3, { A_PlayerScream }, S_PLAY_11 }, //297 +/*S_PLAY_11*/ { SPR_PLAY, 8, 3, { A_Fall }, S_PLAY_12 }, //298 +/*S_PLAY_12*/ { SPR_PLAY, 9, 4, { NULL }, S_PLAY_13 }, //299 +/*S_PLAY_13*/ { SPR_PLAY, 10, 4, { NULL }, S_PLAY_14 }, //300 +/*S_PLAY_14*/ { SPR_PLAY, 11, 4, { NULL }, S_PLAY_15 }, //301 +/*S_PLAY_15*/ { SPR_PLAY, 12, 4, { NULL }, S_PLAY_16 }, //302 +/*S_PLAY_16*/ { SPR_PLAY, 13, 4, { NULL }, S_PLAY_17 }, //303 +/*S_PLAY_17*/ { SPR_PLAY, 14, 4, { NULL }, S_PLAY_18 }, //304 +/*S_PLAY_18*/ { SPR_PLAY, 15, 700, { NULL }, S_RGIB_07 }, //305 +/*S_RGIB_00*/ { SPR_RGIB, 0, 5, { A_BodyParts }, S_RGIB_01 }, //306 +/*S_RGIB_01*/ { SPR_RGIB, 1, 5, { A_XScream }, S_RGIB_02 }, //307 +/*S_RGIB_02*/ { SPR_RGIB, 2, 5, { A_Fall }, S_RGIB_03 }, //308 +/*S_RGIB_03*/ { SPR_RGIB, 3, 5, { A_BodyParts }, S_RGIB_04 }, //309 +/*S_RGIB_04*/ { SPR_RGIB, 4, 5, { A_BodyParts }, S_RGIB_05 }, //310 +/*S_RGIB_05*/ { SPR_RGIB, 5, 5, { A_BodyParts }, S_RGIB_06 }, //311 +/*S_RGIB_06*/ { SPR_RGIB, 6, 5, { A_BodyParts }, S_RGIB_07 }, //312 +/*S_RGIB_07*/ { SPR_RGIB, 7, 1400, { NULL }, S_NULL }, //313 +/*S_MRYS_00*/ { SPR_MRYS, 0, 30, { NULL }, S_MRST_00 }, //314 +/*S_MRNO_00*/ { SPR_MRNO, 0, 6, { NULL }, S_MRNO_01 }, //315 +/*S_MRNO_01*/ { SPR_MRNO, 1, 6, { NULL }, S_MRNO_02 }, //316 +/*S_MRNO_02*/ { SPR_MRNO, 2, 10, { NULL }, S_MRNO_03 }, //317 +/*S_MRNO_03*/ { SPR_MRNO, 1, 6, { NULL }, S_MRNO_04 }, //318 +/*S_MRNO_04*/ { SPR_MRNO, 0, 6, { NULL }, S_MRST_00 }, //319 +/*S_MRST_00*/ { SPR_MRST, 0, 10, { A_FriendLook }, S_MRST_00 }, //320 +/*S_MRLK_00*/ { SPR_MRLK, 0, 30, { A_ActiveSound }, S_MRST_00 }, //321 +/*S_MRLK_01*/ { SPR_MRLK, 1, 30, { NULL }, S_MRST_00 }, //322 +/*S_MRBD_00*/ { SPR_MRBD, 0, 4, { NULL }, S_MRBD_01 }, //323 +/*S_MRBD_01*/ { SPR_MRBD, 1, 4, { NULL }, S_MRBD_02 }, //324 +/*S_MRBD_02*/ { SPR_MRBD, 2, 4, { NULL }, S_MRBD_03 }, //325 +/*S_MRBD_03*/ { SPR_MRBD, 3, 4, { NULL }, S_MRBD_04 }, //326 +/*S_MRBD_04*/ { SPR_MRBD, 4, 4, { NULL }, S_MRBD_05 }, //327 +/*S_MRBD_05*/ { SPR_MRBD, 3, 4, { NULL }, S_MRBD_06 }, //328 +/*S_MRBD_06*/ { SPR_MRBD, 2, 4, { NULL }, S_MRBD_07 }, //329 +/*S_MRBD_07*/ { SPR_MRBD, 1, 4, { NULL }, S_MRBD_08 }, //330 +/*S_MRBD_08*/ { SPR_MRBD, 0, 5, { NULL }, S_MRBD_09 }, //331 +/*S_MRBD_09*/ { SPR_MRBD, 5, 6, { NULL }, S_MRST_00 }, //332 +/*S_MRPN_00*/ { SPR_MRPN, 0, 3, { NULL }, S_MRPN_01 }, //333 +/*S_MRPN_01*/ { SPR_MRPN, 1, 3, { A_Pain }, S_MRPN_02 }, //334 +/*S_MRPN_02*/ { SPR_MRPN, 2, 3, { NULL }, S_MRPN_03 }, //335 +/*S_MRPN_03*/ { SPR_MRPN, 3, 9, { A_MerchantPain }, S_MRPN_04 }, //336 +/*S_MRPN_04*/ { SPR_MRPN, 2, 4, { NULL }, S_MRPN_05 }, //337 +/*S_MRPN_05*/ { SPR_MRPN, 1, 3, { NULL }, S_MRPN_06 }, //338 +/*S_MRPN_06*/ { SPR_MRPN, 0, 3, { A_ClearSoundTarget }, S_MRST_00 }, //339 +/*S_MRGT_00*/ { SPR_MRGT, 0, 5, { NULL }, S_MRGT_01 }, //340 +/*S_MRGT_01*/ { SPR_MRGT, 1, 5, { NULL }, S_MRGT_02 }, //341 +/*S_MRGT_02*/ { SPR_MRGT, 2, 5, { NULL }, S_MRGT_03 }, //342 +/*S_MRGT_03*/ { SPR_MRGT, 3, 5, { NULL }, S_MRGT_04 }, //343 +/*S_MRGT_04*/ { SPR_MRGT, 4, 5, { NULL }, S_MRGT_05 }, //344 +/*S_MRGT_05*/ { SPR_MRGT, 5, 5, { NULL }, S_MRGT_06 }, //345 +/*S_MRGT_06*/ { SPR_MRGT, 6, 5, { NULL }, S_MRGT_07 }, //346 +/*S_MRGT_07*/ { SPR_MRGT, 7, 5, { NULL }, S_MRGT_08 }, //347 +/*S_MRGT_08*/ { SPR_MRGT, 8, 5, { NULL }, S_MRST_00 }, //348 +/*S_BURN_00*/ { SPR_BURN, 0, 3, { A_Scream }, S_BURN_01 }, //349 +/*S_BURN_01*/ { SPR_BURN, 1, 3, { A_DropBurnFlesh }, S_BURN_02 }, //350 +/*S_BURN_02*/ { SPR_BURN, 2, 3, { A_RandomWalk }, S_BURN_03 }, //351 +/*S_BURN_03*/ { SPR_BURN, 3, 3, { A_Fall }, S_BURN_04 }, //352 +/*S_BURN_04*/ { SPR_BURN, 4, 5, { A_DropBurnFlesh }, S_BURN_05 }, //353 +/*S_BURN_05*/ { SPR_BURN, 5, 5, { A_RandomWalk }, S_BURN_06 }, //354 +/*S_BURN_06*/ { SPR_BURN, 6, 5, { A_RandomWalk }, S_BURN_07 }, //355 +/*S_BURN_07*/ { SPR_BURN, 7, 5, { A_RandomWalk }, S_BURN_08 }, //356 +/*S_BURN_08*/ { SPR_BURN, 8, 5, { A_DropBurnFlesh }, S_BURN_09 }, //357 +/*S_BURN_09*/ { SPR_BURN, 9, 5, { A_RandomWalk }, S_BURN_10 }, //358 +/*S_BURN_10*/ { SPR_BURN, 10, 5, { A_RandomWalk }, S_BURN_11 }, //359 +/*S_BURN_11*/ { SPR_BURN, 11, 5, { A_RandomWalk }, S_BURN_12 }, //360 +/*S_BURN_12*/ { SPR_BURN, 12, 3, { A_DropBurnFlesh }, S_BURN_13 }, //361 +/*S_BURN_13*/ { SPR_BURN, 13, 3, { NULL }, S_BURN_14 }, //362 +/*S_BURN_14*/ { SPR_BURN, 14, 5, { NULL }, S_BURN_15 }, //363 +/*S_BURN_15*/ { SPR_BURN, 15, 5, { NULL }, S_BURN_16 }, //364 +/*S_BURN_16*/ { SPR_BURN, 16, 5, { NULL }, S_BURN_17 }, //365 +/*S_BURN_17*/ { SPR_BURN, 15, 5, { NULL }, S_BURN_18 }, //366 +/*S_BURN_18*/ { SPR_BURN, 16, 5, { NULL }, S_BURN_19 }, //367 +/*S_BURN_19*/ { SPR_BURN, 17, 7, { NULL }, S_BURN_20 }, //368 +/*S_BURN_20*/ { SPR_BURN, 18, 7, { NULL }, S_BURN_21 }, //369 +/*S_BURN_21*/ { SPR_BURN, 19, 7, { NULL }, S_BURN_22 }, //370 +/*S_BURN_22*/ { SPR_BURN, 20, 7, { NULL }, S_BURN_23 }, //371 +/*S_BURN_23*/ { SPR_BURN, 21, 700, { A_PeasantCrash }, S_NULL }, //372 +/*S_DISR_00*/ { SPR_DISR, 0, 5, { NULL }, S_DISR_01 }, //373 +/*S_DISR_01*/ { SPR_DISR, 1, 5, { NULL }, S_DISR_02 }, //374 +/*S_DISR_02*/ { SPR_DISR, 2, 5, { NULL }, S_DISR_03 }, //375 +/*S_DISR_03*/ { SPR_DISR, 3, 5, { A_Fall }, S_DISR_04 }, //376 +/*S_DISR_04*/ { SPR_DISR, 4, 5, { NULL }, S_DISR_05 }, //377 +/*S_DISR_05*/ { SPR_DISR, 5, 5, { NULL }, S_DISR_06 }, //378 +/*S_DISR_06*/ { SPR_DISR, 6, 4, { NULL }, S_DISR_07 }, //379 +/*S_DISR_07*/ { SPR_DISR, 7, 4, { NULL }, S_DISR_08 }, //380 +/*S_DISR_08*/ { SPR_DISR, 8, 4, { NULL }, S_DISR_09 }, //381 +/*S_DISR_09*/ { SPR_DISR, 9, 4, { NULL }, S_MEAT_03 }, //382 +/*S_PEAS_00*/ { SPR_PEAS, 0, 10, { A_FriendLook }, S_PEAS_00 }, //383 +/*S_PEAS_01*/ { SPR_PEAS, 0, 5, { A_RandomWalk }, S_PEAS_02 }, //384 +/*S_PEAS_02*/ { SPR_PEAS, 0, 5, { A_RandomWalk }, S_PEAS_03 }, //385 +/*S_PEAS_03*/ { SPR_PEAS, 1, 5, { A_RandomWalk }, S_PEAS_04 }, //386 +/*S_PEAS_04*/ { SPR_PEAS, 1, 5, { A_RandomWalk }, S_PEAS_05 }, //387 +/*S_PEAS_05*/ { SPR_PEAS, 2, 5, { A_RandomWalk }, S_PEAS_06 }, //388 +/*S_PEAS_06*/ { SPR_PEAS, 2, 5, { A_RandomWalk }, S_PEAS_07 }, //389 +/*S_PEAS_07*/ { SPR_PEAS, 3, 5, { A_RandomWalk }, S_PEAS_08 }, //390 +/*S_PEAS_08*/ { SPR_PEAS, 3, 5, { A_RandomWalk }, S_PEAS_00 }, //391 +/*S_PEAS_09*/ { SPR_PEAS, 4, 10, { A_FaceTarget }, S_PEAS_10 }, //392 +/*S_PEAS_10*/ { SPR_PEAS, 5, 8, { A_PeasantPunch }, S_PEAS_11 }, //393 +/*S_PEAS_11*/ { SPR_PEAS, 4, 8, { NULL }, S_PEAS_01 }, //394 +/*S_PEAS_12*/ { SPR_PEAS, 14, 3, { NULL }, S_PEAS_13 }, //395 +/*S_PEAS_13*/ { SPR_PEAS, 14, 3, { A_Pain }, S_PEAS_09 }, //396 +/*S_PEAS_14*/ { SPR_PEAS, 6, 5, { NULL }, S_PEAS_15 }, //397 +/*S_PEAS_15*/ { SPR_PEAS, 7, 10, { A_PeasantCrash }, S_PEAS_16 }, //398 +/*S_PEAS_16*/ { SPR_PEAS, 8, 6, { NULL }, S_PEAS_15 }, //399 +/*S_PEAS_17*/ { SPR_PEAS, 6, 5, { NULL }, S_PEAS_18 }, //400 +/*S_PEAS_18*/ { SPR_PEAS, 7, 5, { A_Scream }, S_PEAS_19 }, //401 +/*S_PEAS_19*/ { SPR_PEAS, 8, 6, { NULL }, S_PEAS_20 }, //402 +/*S_PEAS_20*/ { SPR_PEAS, 9, 5, { A_Fall }, S_PEAS_21 }, //403 +/*S_PEAS_21*/ { SPR_PEAS, 10, 5, { NULL }, S_PEAS_22 }, //404 +/*S_PEAS_22*/ { SPR_PEAS, 11, 6, { NULL }, S_PEAS_23 }, //405 +/*S_PEAS_23*/ { SPR_PEAS, 12, 8, { NULL }, S_PEAS_24 }, //406 +/*S_PEAS_24*/ { SPR_PEAS, 13, 1400, { NULL }, S_GIBS_08 }, //407 +/*S_GIBS_00*/ { SPR_GIBS, 12, 5, { A_BodyParts }, S_GIBS_01 }, //408 +/*S_GIBS_01*/ { SPR_GIBS, 13, 5, { A_XScream }, S_GIBS_02 }, //409 +/*S_GIBS_02*/ { SPR_GIBS, 14, 5, { A_Fall }, S_GIBS_03 }, //410 +/*S_GIBS_03*/ { SPR_GIBS, 15, 4, { A_BodyParts }, S_GIBS_04 }, //411 +/*S_GIBS_04*/ { SPR_GIBS, 16, 4, { A_BodyParts }, S_GIBS_05 }, //412 +/*S_GIBS_05*/ { SPR_GIBS, 17, 4, { A_BodyParts }, S_GIBS_06 }, //413 +/*S_GIBS_06*/ { SPR_GIBS, 18, 4, { A_BodyParts }, S_GIBS_07 }, //414 +/*S_GIBS_07*/ { SPR_GIBS, 19, 4, { NULL }, S_GIBS_08 }, //415 +/*S_GIBS_08*/ { SPR_GIBS, 20, 5, { NULL }, S_GIBS_09 }, //416 +/*S_GIBS_09*/ { SPR_GIBS, 21, 1400, { NULL }, S_NULL }, //417 +/*S_PEAS_25*/ { SPR_PEAS, 0, 5, { A_ZombieInSpecialSector }, S_PEAS_25 }, //418 +/*S_AGRD_00*/ { SPR_AGRD, 0, 5, { A_ZombieInSpecialSector }, S_AGRD_00 }, //419 +/*S_ARMR_00*/ { SPR_ARMR, 0, -1, { NULL }, S_NULL }, //420 +/*S_ARMR_01*/ { SPR_ARMR, 0, -1, { A_HideZombie }, S_NULL }, //421 +/*S_PLAY_19*/ { SPR_PLAY, 0, 175, { A_SpawnZombie }, S_PLAY_19 }, //422 +/*S_SACR_00*/ { SPR_SACR, 0, -1, { NULL }, S_NULL }, //423 +/*S_TNK1_00*/ { SPR_TNK1, 0, 15, { NULL }, S_TNK1_01 }, //424 +/*S_TNK1_01*/ { SPR_TNK1, 1, 11, { NULL }, S_TNK1_02 }, //425 +/*S_TNK1_02*/ { SPR_TNK1, 2, 40, { NULL }, S_TNK1_00 }, //426 +/*S_TNK2_00*/ { SPR_TNK2, 0, 15, { NULL }, S_TNK2_01 }, //427 +/*S_TNK2_01*/ { SPR_TNK2, 1, 11, { NULL }, S_TNK2_02 }, //428 +/*S_TNK2_02*/ { SPR_TNK2, 2, 40, { NULL }, S_TNK2_00 }, //429 +/*S_TNK3_00*/ { SPR_TNK3, 0, 15, { NULL }, S_TNK3_01 }, //430 +/*S_TNK3_01*/ { SPR_TNK3, 1, 11, { NULL }, S_TNK3_02 }, //431 +/*S_TNK3_02*/ { SPR_TNK3, 2, 40, { NULL }, S_TNK3_00 }, //432 +/*S_TNK4_00*/ { SPR_TNK4, 0, 15, { NULL }, S_TNK4_01 }, //433 +/*S_TNK4_01*/ { SPR_TNK4, 1, 11, { NULL }, S_TNK4_02 }, //434 +/*S_TNK4_02*/ { SPR_TNK4, 2, 40, { NULL }, S_TNK4_00 }, //435 +/*S_TNK5_00*/ { SPR_TNK5, 0, 15, { NULL }, S_TNK5_01 }, //436 +/*S_TNK5_01*/ { SPR_TNK5, 1, 11, { NULL }, S_TNK5_02 }, //437 +/*S_TNK5_02*/ { SPR_TNK5, 2, 40, { NULL }, S_TNK5_00 }, //438 +/*S_TNK6_00*/ { SPR_TNK6, 0, 15, { NULL }, S_TNK6_01 }, //439 +/*S_TNK6_01*/ { SPR_TNK6, 1, 11, { NULL }, S_TNK6_02 }, //440 +/*S_TNK6_02*/ { SPR_TNK6, 2, 40, { NULL }, S_TNK6_00 }, //441 +/*S_NEAL_00*/ { SPR_NEAL, 0, 15, { A_ActiveSound }, S_NEAL_01 }, //442 +/*S_NEAL_01*/ { SPR_NEAL, 1, 40, { A_ActiveSound }, S_NEAL_00 }, //443 +/*S_NEAL_02*/ { SPR_NEAL, 2, 5, { A_ShadowOn }, S_NEAL_03 }, //444 +/*S_NEAL_03*/ { SPR_NEAL, 1, 4, { A_Pain }, S_NEAL_04 }, //445 +/*S_NEAL_04*/ { SPR_NEAL, 2, 5, { A_ShadowOff }, S_NEAL_00 }, //446 +/*S_NEAL_05*/ { SPR_NEAL, 1, 6, { NULL }, S_NEAL_06 }, //447 +/*S_NEAL_06*/ { SPR_NEAL, 2, 13, { A_PeasantCrash }, S_NEAL_05 }, //448 +/*S_NEAL_07*/ { SPR_NEAL, 3, 5, { NULL }, S_NEAL_08 }, //449 +/*S_NEAL_08*/ { SPR_NEAL, 4, 5, { A_Scream }, S_NEAL_09 }, //450 +/*S_NEAL_09*/ { SPR_NEAL, 5, 6, { NULL }, S_NEAL_10 }, //451 +/*S_NEAL_10*/ { SPR_NEAL, 6, 5, { A_Fall }, S_NEAL_11 }, //452 +/*S_NEAL_11*/ { SPR_NEAL, 7, 5, { NULL }, S_NEAL_12 }, //453 +/*S_NEAL_12*/ { SPR_NEAL, 8, 6, { NULL }, S_NEAL_13 }, //454 +/*S_NEAL_13*/ { SPR_NEAL, 9, -1, { NULL }, S_NULL }, //455 +/*S_BEGR_00*/ { SPR_BEGR, 0, 10, { A_Look }, S_BEGR_00 }, //456 +/*S_BEGR_01*/ { SPR_BEGR, 0, 4, { A_RandomWalk }, S_BEGR_02 }, //457 +/*S_BEGR_02*/ { SPR_BEGR, 0, 4, { A_RandomWalk }, S_BEGR_03 }, //458 +/*S_BEGR_03*/ { SPR_BEGR, 1, 4, { A_RandomWalk }, S_BEGR_04 }, //459 +/*S_BEGR_04*/ { SPR_BEGR, 1, 4, { A_RandomWalk }, S_BEGR_05 }, //460 +/*S_BEGR_05*/ { SPR_BEGR, 2, 4, { A_RandomWalk }, S_BEGR_06 }, //461 +/*S_BEGR_06*/ { SPR_BEGR, 2, 4, { A_RandomWalk }, S_BEGR_01 }, //462 +/*S_BEGR_07*/ { SPR_BEGR, 3, 8, { NULL }, S_BEGR_08 }, //463 +/*S_BEGR_08*/ { SPR_BEGR, 4, 8, { A_PeasantPunch }, S_BEGR_09 }, //464 +/*S_BEGR_09*/ { SPR_BEGR, 4, 1, { A_Chase }, S_BEGR_10 }, //465 +/*S_BEGR_10*/ { SPR_BEGR, 3, 8, { A_CheckTargetVisible }, S_BEGR_07 }, //466 +/*S_BEGR_11*/ { SPR_BEGR, 0, 3, { A_Pain }, S_BEGR_12 }, //467 +/*S_BEGR_12*/ { SPR_BEGR, 0, 3, { A_Chase }, S_BEGR_07 }, //468 +/*S_BEGR_13*/ { SPR_BEGR, 5, 4, { NULL }, S_BEGR_14 }, //469 +/*S_BEGR_14*/ { SPR_BEGR, 6, 4, { A_Scream }, S_BEGR_15 }, //470 +/*S_BEGR_15*/ { SPR_BEGR, 7, 4, { NULL }, S_BEGR_16 }, //471 +/*S_BEGR_16*/ { SPR_BEGR, 8, 4, { A_Fall }, S_BEGR_17 }, //472 +/*S_BEGR_17*/ { SPR_BEGR, 9, 4, { NULL }, S_BEGR_18 }, //473 +/*S_BEGR_18*/ { SPR_BEGR, 10, 4, { NULL }, S_BEGR_19 }, //474 +/*S_BEGR_19*/ { SPR_BEGR, 11, 4, { NULL }, S_BEGR_20 }, //475 +/*S_BEGR_20*/ { SPR_BEGR, 12, 4, { NULL }, S_BEGR_21 }, //476 +/*S_BEGR_21*/ { SPR_BEGR, 13, -1, { NULL }, S_NULL }, //477 +/*S_BEGR_22*/ { SPR_BEGR, 5, 5, { A_BodyParts }, S_GIBS_01 }, //478 +/*S_HMN1_00*/ { SPR_HMN1, 15, 5, { A_FriendLook }, S_HMN1_00 }, //479 +/*S_HMN1_01*/ { SPR_HMN1, 16, 8, { NULL }, S_HMN1_00 }, //480 +/*S_HMN1_02*/ { SPR_HMN1, 17, 8, { NULL }, S_HMN1_00 }, //481 +/*S_HMN1_03*/ { SPR_HMN1, 0, 6, { A_RandomWalk }, S_HMN1_04 }, //482 +/*S_HMN1_04*/ { SPR_HMN1, 1, 6, { A_RandomWalk }, S_HMN1_05 }, //483 +/*S_HMN1_05*/ { SPR_HMN1, 2, 6, { A_RandomWalk }, S_HMN1_06 }, //484 +/*S_HMN1_06*/ { SPR_HMN1, 3, 6, { A_RandomWalk }, S_HMN1_07 }, //485 +/*S_HMN1_07*/ { SPR_HMN1, 0, 6, { A_RandomWalk }, S_HMN1_08 }, //486 +/*S_HMN1_08*/ { SPR_HMN1, 1, 6, { A_RandomWalk }, S_HMN1_09 }, //487 +/*S_HMN1_09*/ { SPR_HMN1, 2, 6, { A_RandomWalk }, S_HMN1_10 }, //488 +/*S_HMN1_10*/ { SPR_HMN1, 3, 6, { A_RandomWalk }, S_HMN1_00 }, //489 +/*S_HMN1_11*/ { SPR_HMN1, 0, 3, { A_Chase }, S_HMN1_12 }, //490 +/*S_HMN1_12*/ { SPR_HMN1, 0, 3, { A_Chase }, S_HMN1_13 }, //491 +/*S_HMN1_13*/ { SPR_HMN1, 1, 3, { A_Chase }, S_HMN1_14 }, //492 +/*S_HMN1_14*/ { SPR_HMN1, 1, 3, { A_Chase }, S_HMN1_15 }, //493 +/*S_HMN1_15*/ { SPR_HMN1, 2, 3, { A_Chase }, S_HMN1_16 }, //494 +/*S_HMN1_16*/ { SPR_HMN1, 2, 3, { A_Chase }, S_HMN1_17 }, //495 +/*S_HMN1_17*/ { SPR_HMN1, 3, 3, { A_Chase }, S_HMN1_18 }, //496 +/*S_HMN1_18*/ { SPR_HMN1, 3, 3, { A_Chase }, S_HMN1_11 }, //497 +/*S_HMN1_19*/ { SPR_HMN1, 4, 10, { A_FaceTarget }, S_HMN1_20 }, //498 +/*S_HMN1_20*/ { SPR_HMN1, 32773, 10, { A_BulletAttack }, S_HMN1_21 }, //499 +/*S_HMN1_21*/ { SPR_HMN1, 4, 10, { A_BulletAttack }, S_HMN1_11 }, //500 +/*S_HMN1_22*/ { SPR_HMN1, 14, 3, { NULL }, S_HMN1_23 }, //501 +/*S_HMN1_23*/ { SPR_HMN1, 14, 3, { A_Pain }, S_HMN1_11 }, //502 +/*S_HMN1_24*/ { SPR_HMN1, 6, 5, { NULL }, S_HMN1_25 }, //503 +/*S_HMN1_25*/ { SPR_HMN1, 7, 5, { A_Scream }, S_HMN1_26 }, //504 +/*S_HMN1_26*/ { SPR_HMN1, 8, 3, { A_Fall }, S_HMN1_27 }, //505 +/*S_HMN1_27*/ { SPR_HMN1, 9, 4, { NULL }, S_HMN1_28 }, //506 +/*S_HMN1_28*/ { SPR_HMN1, 10, 3, { NULL }, S_HMN1_29 }, //507 +/*S_HMN1_29*/ { SPR_HMN1, 11, 3, { NULL }, S_HMN1_30 }, //508 +/*S_HMN1_30*/ { SPR_HMN1, 12, 3, { NULL }, S_HMN1_31 }, //509 +/*S_HMN1_31*/ { SPR_HMN1, 13, -1, { NULL }, S_NULL }, //510 +/*S_RGIB_08*/ { SPR_RGIB, 0, 4, { A_BodyParts }, S_RGIB_09 }, //511 +/*S_RGIB_09*/ { SPR_RGIB, 1, 4, { A_XScream }, S_RGIB_10 }, //512 +/*S_RGIB_10*/ { SPR_RGIB, 2, 3, { A_Fall }, S_RGIB_11 }, //513 +/*S_RGIB_11*/ { SPR_RGIB, 3, 3, { A_BodyParts }, S_RGIB_12 }, //514 +/*S_RGIB_12*/ { SPR_RGIB, 4, 3, { A_BodyParts }, S_RGIB_13 }, //515 +/*S_RGIB_13*/ { SPR_RGIB, 5, 3, { A_BodyParts }, S_RGIB_14 }, //516 +/*S_RGIB_14*/ { SPR_RGIB, 6, 3, { NULL }, S_RGIB_15 }, //517 +/*S_RGIB_15*/ { SPR_RGIB, 7, 1400, { NULL }, S_NULL }, //518 +/*S_LEDR_00*/ { SPR_LEDR, 2, 5, { A_FriendLook }, S_LEDR_00 }, //519 +/*S_LEDR_01*/ { SPR_LEDR, 0, 8, { NULL }, S_LEDR_00 }, //520 +/*S_LEDR_02*/ { SPR_LEDR, 1, 8, { NULL }, S_LEDR_00 }, //521 +/*S_LEAD_00*/ { SPR_LEAD, 0, 6, { A_RandomWalk }, S_LEAD_01 }, //522 +/*S_LEAD_01*/ { SPR_LEAD, 1, 6, { A_RandomWalk }, S_LEAD_02 }, //523 +/*S_LEAD_02*/ { SPR_LEAD, 2, 6, { A_RandomWalk }, S_LEAD_03 }, //524 +/*S_LEAD_03*/ { SPR_LEAD, 3, 6, { A_RandomWalk }, S_LEDR_00 }, //525 +/*S_LEAD_04*/ { SPR_LEAD, 0, 3, { A_Chase }, S_LEAD_05 }, //526 +/*S_LEAD_05*/ { SPR_LEAD, 0, 3, { A_Chase }, S_LEAD_06 }, //527 +/*S_LEAD_06*/ { SPR_LEAD, 1, 3, { A_Chase }, S_LEAD_07 }, //528 +/*S_LEAD_07*/ { SPR_LEAD, 1, 3, { A_Chase }, S_LEAD_08 }, //529 +/*S_LEAD_08*/ { SPR_LEAD, 2, 3, { A_Chase }, S_LEAD_09 }, //530 +/*S_LEAD_09*/ { SPR_LEAD, 2, 3, { A_Chase }, S_LEAD_10 }, //531 +/*S_LEAD_10*/ { SPR_LEAD, 3, 3, { A_Chase }, S_LEAD_11 }, //532 +/*S_LEAD_11*/ { SPR_LEAD, 3, 3, { A_Chase }, S_LEAD_04 }, //533 +/*S_LEAD_12*/ { SPR_LEAD, 4, 2, { A_FaceTarget }, S_LEAD_13 }, //534 +/*S_LEAD_13*/ { SPR_LEAD, 32773, 2, { A_BulletAttack }, S_LEAD_14 }, //535 +/*S_LEAD_14*/ { SPR_LEAD, 4, 1, { A_CheckTargetVisible }, S_LEAD_12 }, //536 +/*S_LEAD_15*/ { SPR_LEAD, 24, 3, { NULL }, S_LEAD_16 }, //537 +/*S_LEAD_16*/ { SPR_LEAD, 24, 3, { A_Pain }, S_LEAD_04 }, //538 +/*S_LEAD_17*/ { SPR_LEAD, 4, 4, { A_FaceTarget }, S_LEAD_18 }, //539 +/*S_LEAD_18*/ { SPR_LEAD, 32773, 4, { A_BulletAttack }, S_LEAD_19 }, //540 +/*S_LEAD_19*/ { SPR_LEAD, 4, 2, { A_CheckTargetVisible }, S_LEAD_17 }, //541 +/*S_LEAD_20*/ { SPR_LEAD, 6, 5, { NULL }, S_LEAD_21 }, //542 +/*S_LEAD_21*/ { SPR_LEAD, 7, 5, { A_Scream }, S_LEAD_22 }, //543 +/*S_LEAD_22*/ { SPR_LEAD, 8, 4, { NULL }, S_LEAD_23 }, //544 +/*S_LEAD_23*/ { SPR_LEAD, 9, 4, { NULL }, S_LEAD_24 }, //545 +/*S_LEAD_24*/ { SPR_LEAD, 10, 3, { NULL }, S_LEAD_25 }, //546 +/*S_LEAD_25*/ { SPR_LEAD, 11, 3, { A_Fall }, S_LEAD_26 }, //547 +/*S_LEAD_26*/ { SPR_LEAD, 12, 3, { NULL }, S_LEAD_27 }, //548 +/*S_LEAD_27*/ { SPR_LEAD, 13, 3, { NULL }, S_LEAD_28 }, //549 +/*S_LEAD_28*/ { SPR_LEAD, 14, 3, { NULL }, S_LEAD_29 }, //550 +/*S_LEAD_29*/ { SPR_LEAD, 15, 3, { NULL }, S_LEAD_30 }, //551 +/*S_LEAD_30*/ { SPR_LEAD, 16, 3, { NULL }, S_LEAD_31 }, //552 +/*S_LEAD_31*/ { SPR_LEAD, 17, 3, { NULL }, S_LEAD_32 }, //553 +/*S_LEAD_32*/ { SPR_LEAD, 18, 3, { NULL }, S_LEAD_33 }, //554 +/*S_LEAD_33*/ { SPR_LEAD, 19, 3, { NULL }, S_LEAD_34 }, //555 +/*S_LEAD_34*/ { SPR_LEAD, 20, 3, { NULL }, S_LEAD_35 }, //556 +/*S_LEAD_35*/ { SPR_LEAD, 21, 3, { NULL }, S_LEAD_36 }, //557 +/*S_LEAD_36*/ { SPR_LEAD, 22, 3, { A_SpawnSpectreD }, S_LEAD_37 }, //558 +/*S_LEAD_37*/ { SPR_LEAD, 23, -1, { NULL }, S_NULL }, //559 +/*S_PUFY_04*/ { SPR_PUFY, 1, 4, { NULL }, S_PUFY_05 }, //560 +/*S_PUFY_05*/ { SPR_PUFY, 2, 4, { NULL }, S_PUFY_06 }, //561 +/*S_PUFY_06*/ { SPR_PUFY, 1, 4, { NULL }, S_PUFY_07 }, //562 +/*S_PUFY_07*/ { SPR_PUFY, 2, 4, { NULL }, S_PUFY_08 }, //563 +/*S_PUFY_08*/ { SPR_PUFY, 3, 4, { NULL }, S_NULL }, //564 +/*S_MICR_01*/ { SPR_MICR, 32768, 2, { A_Tracer }, S_MICR_02 }, //565 +/*S_MICR_02*/ { SPR_MICR, 32768, 2, { A_Tracer }, S_MICR_01 }, //566 +/*S_ROB1_00*/ { SPR_ROB1, 0, 10, { A_Look }, S_ROB1_01 }, //567 +/*S_ROB1_01*/ { SPR_ROB1, 0, 10, { A_Look }, S_ROB1_00 }, //568 +/*S_ROB1_02*/ { SPR_ROB1, 1, 3, { A_Chase }, S_ROB1_03 }, //569 +/*S_ROB1_03*/ { SPR_ROB1, 1, 3, { A_Chase }, S_ROB1_04 }, //570 +/*S_ROB1_04*/ { SPR_ROB1, 2, 3, { A_Chase }, S_ROB1_05 }, //571 +/*S_ROB1_05*/ { SPR_ROB1, 2, 3, { A_Chase }, S_ROB1_06 }, //572 +/*S_ROB1_06*/ { SPR_ROB1, 3, 3, { A_Chase }, S_ROB1_07 }, //573 +/*S_ROB1_07*/ { SPR_ROB1, 3, 3, { A_Chase }, S_ROB1_08 }, //574 +/*S_ROB1_08*/ { SPR_ROB1, 4, 3, { A_Chase }, S_ROB1_09 }, //575 +/*S_ROB1_09*/ { SPR_ROB1, 4, 3, { A_Chase }, S_ROB1_02 }, //576 +/*S_ROB1_10*/ { SPR_ROB1, 7, 6, { A_FaceTarget }, S_ROB1_11 }, //577 +/*S_ROB1_11*/ { SPR_ROB1, 8, 8, { A_RobotMelee }, S_ROB1_12 }, //578 +/*S_ROB1_12*/ { SPR_ROB1, 7, 6, { NULL }, S_ROB1_02 }, //579 +/*S_ROB1_13*/ { SPR_ROB1, 5, 8, { A_FaceTarget }, S_ROB1_14 }, //580 +/*S_ROB1_14*/ { SPR_ROB1, 32774, 11, { A_ReaverAttack }, S_ROB1_02 }, //581 +/*S_ROB1_15*/ { SPR_ROB1, 0, 2, { NULL }, S_ROB1_16 }, //582 +/*S_ROB1_16*/ { SPR_ROB1, 0, 2, { A_Pain }, S_ROB1_02 }, //583 +/*S_ROB1_17*/ { SPR_ROB1, 32777, 6, { NULL }, S_ROB1_18 }, //584 +/*S_ROB1_18*/ { SPR_ROB1, 32778, 6, { A_Scream }, S_ROB1_19 }, //585 +/*S_ROB1_19*/ { SPR_ROB1, 32779, 5, { NULL }, S_ROB1_20 }, //586 +/*S_ROB1_20*/ { SPR_ROB1, 32780, 5, { A_Fall }, S_ROB1_21 }, //587 +/*S_ROB1_21*/ { SPR_ROB1, 32781, 5, { NULL }, S_ROB1_22 }, //588 +/*S_ROB1_22*/ { SPR_ROB1, 32782, 5, { NULL }, S_ROB1_23 }, //589 +/*S_ROB1_23*/ { SPR_ROB1, 32783, 5, { NULL }, S_ROB1_24 }, //590 +/*S_ROB1_24*/ { SPR_ROB1, 32784, 6, { A_DeathExplode3 }, S_ROB1_25 }, //591 +/*S_ROB1_25*/ { SPR_ROB1, 17, -1, { NULL }, S_NULL }, //592 +/*S_ROB1_26*/ { SPR_ROB1, 32779, 5, { A_BodyParts }, S_ROB1_27 }, //593 +/*S_ROB1_27*/ { SPR_ROB1, 32780, 5, { A_XScream }, S_ROB1_28 }, //594 +/*S_ROB1_28*/ { SPR_ROB1, 32781, 5, { A_BodyParts }, S_ROB1_29 }, //595 +/*S_ROB1_29*/ { SPR_ROB1, 32782, 5, { A_Fall }, S_ROB1_30 }, //596 +/*S_ROB1_30*/ { SPR_ROB1, 32783, 5, { A_BodyParts }, S_ROB1_31 }, //597 +/*S_ROB1_31*/ { SPR_ROB1, 32784, 5, { A_DeathExplode3 }, S_ROB1_32 }, //598 +/*S_ROB1_32*/ { SPR_ROB1, 17, -1, { NULL }, S_NULL }, //599 +/*S_AGRD_01*/ { SPR_AGRD, 0, 5, { A_FriendLook }, S_AGRD_01 }, //600 +/*S_AGRD_02*/ { SPR_AGRD, 1, 8, { A_ShadowOff }, S_AGRD_01 }, //601 +/*S_AGRD_03*/ { SPR_AGRD, 3, 8, { NULL }, S_AGRD_01 }, //602 +/*S_AGRD_04*/ { SPR_AGRD, 0, 5, { A_RandomWalk }, S_AGRD_05 }, //603 +/*S_AGRD_05*/ { SPR_AGRD, 1, 5, { A_RandomWalk }, S_AGRD_06 }, //604 +/*S_AGRD_06*/ { SPR_AGRD, 2, 5, { A_RandomWalk }, S_AGRD_07 }, //605 +/*S_AGRD_07*/ { SPR_AGRD, 3, 5, { A_RandomWalk }, S_AGRD_08 }, //606 +/*S_AGRD_08*/ { SPR_AGRD, 0, 5, { A_RandomWalk }, S_AGRD_09 }, //607 +/*S_AGRD_09*/ { SPR_AGRD, 1, 5, { A_RandomWalk }, S_AGRD_10 }, //608 +/*S_AGRD_10*/ { SPR_AGRD, 2, 5, { A_RandomWalk }, S_AGRD_11 }, //609 +/*S_AGRD_11*/ { SPR_AGRD, 3, 5, { A_RandomWalk }, S_AGRD_01 }, //610 +/*S_AGRD_12*/ { SPR_AGRD, 0, 6, { A_ModifyVisibility }, S_AGRD_14 }, //611 +/*S_AGRD_13*/ { SPR_AGRD, 0, 6, { A_SetTLOptions }, S_AGRD_14 }, //612 +/*S_AGRD_14*/ { SPR_AGRD, 1, 6, { A_Chase }, S_AGRD_15 }, //613 +/*S_AGRD_15*/ { SPR_AGRD, 2, 6, { A_Chase }, S_AGRD_16 }, //614 +/*S_AGRD_16*/ { SPR_AGRD, 3, 6, { A_Chase }, S_AGRD_13 }, //615 +/*S_AGRD_17*/ { SPR_AGRD, 4, 8, { A_FaceTarget }, S_AGRD_18 }, //616 +/*S_AGRD_18*/ { SPR_AGRD, 5, 4, { A_BulletAttack }, S_AGRD_19 }, //617 +/*S_AGRD_19*/ { SPR_AGRD, 4, 4, { A_BulletAttack }, S_AGRD_20 }, //618 +/*S_AGRD_20*/ { SPR_AGRD, 5, 6, { A_BulletAttack }, S_AGRD_13 }, //619 +/*S_AGRD_21*/ { SPR_AGRD, 14, 0, { A_ShadowOn }, S_AGRD_22 }, //620 +/*S_AGRD_22*/ { SPR_AGRD, 14, 8, { A_Pain }, S_AGRD_12 }, //621 +/*S_AGRD_23*/ { SPR_AGRD, 14, 8, { A_Pain }, S_AGRD_13 }, //622 +/*S_AGRD_24*/ { SPR_AGRD, 6, 4, { NULL }, S_AGRD_25 }, //623 +/*S_AGRD_25*/ { SPR_AGRD, 7, 4, { A_Scream }, S_AGRD_26 }, //624 +/*S_AGRD_26*/ { SPR_AGRD, 8, 4, { NULL }, S_AGRD_27 }, //625 +/*S_AGRD_27*/ { SPR_AGRD, 9, 3, { NULL }, S_AGRD_28 }, //626 +/*S_AGRD_28*/ { SPR_AGRD, 10, 3, { A_Fall }, S_AGRD_29 }, //627 +/*S_AGRD_29*/ { SPR_AGRD, 11, 3, { NULL }, S_AGRD_30 }, //628 +/*S_AGRD_30*/ { SPR_AGRD, 12, 3, { A_AcolyteSpecial }, S_AGRD_31 }, //629 +/*S_AGRD_31*/ { SPR_AGRD, 13, 1400, { NULL }, S_GIBS_20 }, //630 +/*S_GIBS_10*/ { SPR_GIBS, 0, 5, { A_Fall }, S_GIBS_11 }, //631 +/*S_GIBS_11*/ { SPR_GIBS, 1, 5, { A_BodyParts }, S_GIBS_12 }, //632 +/*S_GIBS_12*/ { SPR_GIBS, 2, 5, { A_BodyParts }, S_GIBS_13 }, //633 +/*S_GIBS_13*/ { SPR_GIBS, 3, 4, { A_BodyParts }, S_GIBS_14 }, //634 +/*S_GIBS_14*/ { SPR_GIBS, 4, 4, { A_XScream }, S_GIBS_15 }, //635 +/*S_GIBS_15*/ { SPR_GIBS, 5, 4, { A_BodyParts }, S_GIBS_16 }, //636 +/*S_GIBS_16*/ { SPR_GIBS, 6, 4, { NULL }, S_GIBS_17 }, //637 +/*S_GIBS_17*/ { SPR_GIBS, 7, 4, { NULL }, S_GIBS_18 }, //638 +/*S_GIBS_18*/ { SPR_GIBS, 8, 5, { NULL }, S_GIBS_19 }, //639 +/*S_GIBS_19*/ { SPR_GIBS, 9, 5, { A_AcolyteSpecial }, S_GIBS_20 }, //640 +/*S_GIBS_20*/ { SPR_GIBS, 10, 5, { NULL }, S_GIBS_21 }, //641 +/*S_GIBS_21*/ { SPR_GIBS, 11, 1400, { NULL }, S_NULL }, //642 +/*S_PGRD_00*/ { SPR_PGRD, 0, 5, { A_FriendLook }, S_PGRD_00 }, //643 +/*S_PGRD_01*/ { SPR_PGRD, 1, 10, { NULL }, S_PGRD_00 }, //644 +/*S_PGRD_02*/ { SPR_PGRD, 2, 10, { NULL }, S_PGRD_00 }, //645 +/*S_PGRD_03*/ { SPR_PGRD, 1, 10, { A_RandomWalk }, S_PGRD_00 }, //646 +/*S_PGRD_04*/ { SPR_PGRD, 0, 3, { A_Chase }, S_PGRD_05 }, //647 +/*S_PGRD_05*/ { SPR_PGRD, 0, 3, { A_Chase }, S_PGRD_06 }, //648 +/*S_PGRD_06*/ { SPR_PGRD, 1, 3, { A_Chase }, S_PGRD_07 }, //649 +/*S_PGRD_07*/ { SPR_PGRD, 1, 3, { A_Chase }, S_PGRD_08 }, //650 +/*S_PGRD_08*/ { SPR_PGRD, 2, 3, { A_Chase }, S_PGRD_09 }, //651 +/*S_PGRD_09*/ { SPR_PGRD, 2, 3, { A_Chase }, S_PGRD_10 }, //652 +/*S_PGRD_10*/ { SPR_PGRD, 3, 3, { A_Chase }, S_PGRD_11 }, //653 +/*S_PGRD_11*/ { SPR_PGRD, 3, 3, { A_Chase }, S_PGRD_04 }, //654 +/*S_PGRD_12*/ { SPR_PGRD, 4, 8, { A_FaceTarget }, S_PGRD_13 }, //655 +/*S_PGRD_13*/ { SPR_PGRD, 5, 8, { A_RobotMelee }, S_PGRD_04 }, //656 +/*S_PGRD_14*/ { SPR_PGRD, 32774, 8, { A_FaceTarget }, S_PGRD_15 }, //657 +/*S_PGRD_15*/ { SPR_PGRD, 32775, 8, { A_TemplarMauler }, S_PGRD_04 }, //658 +/*S_PGRD_16*/ { SPR_PGRD, 0, 2, { NULL }, S_PGRD_17 }, //659 +/*S_PGRD_17*/ { SPR_PGRD, 0, 2, { A_Pain }, S_PGRD_04 }, //660 +/*S_PGRD_18*/ { SPR_PGRD, 32776, 4, { A_BodyParts }, S_PGRD_19 }, //661 +/*S_PGRD_19*/ { SPR_PGRD, 32777, 4, { A_Scream }, S_PGRD_20 }, //662 +/*S_PGRD_20*/ { SPR_PGRD, 32778, 4, { A_BodyParts }, S_PGRD_21 }, //663 +/*S_PGRD_21*/ { SPR_PGRD, 32779, 4, { A_Fall }, S_PGRD_22 }, //664 +/*S_PGRD_22*/ { SPR_PGRD, 32780, 4, { NULL }, S_PGRD_23 }, //665 +/*S_PGRD_23*/ { SPR_PGRD, 32781, 4, { NULL }, S_PGRD_24 }, //666 +/*S_PGRD_24*/ { SPR_PGRD, 14, 4, { A_BodyParts }, S_PGRD_25 }, //667 +/*S_PGRD_25*/ { SPR_PGRD, 15, 4, { NULL }, S_PGRD_26 }, //668 +/*S_PGRD_26*/ { SPR_PGRD, 16, 4, { NULL }, S_PGRD_27 }, //669 +/*S_PGRD_27*/ { SPR_PGRD, 17, 4, { NULL }, S_PGRD_28 }, //670 +/*S_PGRD_28*/ { SPR_PGRD, 18, 3, { NULL }, S_PGRD_29 }, //671 +/*S_PGRD_29*/ { SPR_PGRD, 19, 3, { NULL }, S_PGRD_30 }, //672 +/*S_PGRD_30*/ { SPR_PGRD, 20, 3, { NULL }, S_PGRD_31 }, //673 +/*S_PGRD_31*/ { SPR_PGRD, 21, 3, { NULL }, S_PGRD_32 }, //674 +/*S_PGRD_32*/ { SPR_PGRD, 22, 3, { NULL }, S_PGRD_33 }, //675 +/*S_PGRD_33*/ { SPR_PGRD, 23, 3, { NULL }, S_PGRD_34 }, //676 +/*S_PGRD_34*/ { SPR_PGRD, 24, 3, { NULL }, S_PGRD_35 }, //677 +/*S_PGRD_35*/ { SPR_PGRD, 25, 3, { NULL }, S_PGRD_36 }, //678 +/*S_PGRD_36*/ { SPR_PGRD, 26, 3, { NULL }, S_PGRD_37 }, //679 +/*S_PGRD_37*/ { SPR_PGRD, 27, -1, { NULL }, S_NULL }, //680 +/*S_ROB2_00*/ { SPR_ROB2, 16, 10, { A_Look }, S_ROB2_00 }, //681 +/*S_ROB2_01*/ { SPR_ROB2, 0, 3, { A_Chase }, S_ROB2_02 }, //682 +/*S_ROB2_02*/ { SPR_ROB2, 0, 3, { A_Chase }, S_ROB2_03 }, //683 +/*S_ROB2_03*/ { SPR_ROB2, 1, 3, { A_Chase }, S_ROB2_04 }, //684 +/*S_ROB2_04*/ { SPR_ROB2, 1, 3, { A_Chase }, S_ROB2_05 }, //685 +/*S_ROB2_05*/ { SPR_ROB2, 2, 3, { A_Chase }, S_ROB2_06 }, //686 +/*S_ROB2_06*/ { SPR_ROB2, 2, 3, { A_Chase }, S_ROB2_07 }, //687 +/*S_ROB2_07*/ { SPR_ROB2, 3, 3, { A_Chase }, S_ROB2_08 }, //688 +/*S_ROB2_08*/ { SPR_ROB2, 3, 3, { A_Chase }, S_ROB2_01 }, //689 +/*S_ROB2_09*/ { SPR_ROB2, 4, 3, { A_FaceTarget }, S_ROB2_10 }, //690 +/*S_ROB2_10*/ { SPR_ROB2, 32773, 2, { A_CrusaderAttack }, S_ROB2_11 }, //691 +/*S_ROB2_11*/ { SPR_ROB2, 32772, 2, { A_CrusaderLeft }, S_ROB2_12 }, //692 +/*S_ROB2_12*/ { SPR_ROB2, 32773, 3, { A_CrusaderLeft }, S_ROB2_13 }, //693 +/*S_ROB2_13*/ { SPR_ROB2, 32772, 2, { A_CrusaderLeft }, S_ROB2_14 }, //694 +/*S_ROB2_14*/ { SPR_ROB2, 32773, 2, { A_CrusaderLeft }, S_ROB2_15 }, //695 +/*S_ROB2_15*/ { SPR_ROB2, 32772, 2, { A_CrusaderRight }, S_ROB2_16 }, //696 +/*S_ROB2_16*/ { SPR_ROB2, 32773, 2, { A_CrusaderRight }, S_ROB2_17 }, //697 +/*S_ROB2_17*/ { SPR_ROB2, 32772, 2, { A_CrusaderRight }, S_ROB2_18 }, //698 +/*S_ROB2_18*/ { SPR_ROB2, 5, 2, { A_CheckTargetVisible2 }, S_ROB2_09 }, //699 +/*S_ROB2_19*/ { SPR_ROB2, 3, 1, { A_Pain }, S_ROB2_01 }, //700 +/*S_ROB2_20*/ { SPR_ROB2, 6, 3, { A_Scream }, S_ROB2_21 }, //701 +/*S_ROB2_21*/ { SPR_ROB2, 7, 5, { A_BodyParts }, S_ROB2_22 }, //702 +/*S_ROB2_22*/ { SPR_ROB2, 32776, 4, { A_BodyParts }, S_ROB2_23 }, //703 +/*S_ROB2_23*/ { SPR_ROB2, 32777, 4, { A_DeathExplode2 }, S_ROB2_24 }, //704 +/*S_ROB2_24*/ { SPR_ROB2, 32778, 4, { A_Fall }, S_ROB2_25 }, //705 +/*S_ROB2_25*/ { SPR_ROB2, 11, 4, { A_DeathExplode2 }, S_ROB2_26 }, //706 +/*S_ROB2_26*/ { SPR_ROB2, 12, 4, { A_BodyParts }, S_ROB2_27 }, //707 +/*S_ROB2_27*/ { SPR_ROB2, 13, 4, { A_BodyParts }, S_ROB2_28 }, //708 +/*S_ROB2_28*/ { SPR_ROB2, 14, 4, { A_DeathExplode2 }, S_ROB2_29 }, //709 +/*S_ROB2_29*/ { SPR_ROB2, 15, -1, { A_BossDeath }, S_NULL }, //710 +/*S_MLDR_00*/ { SPR_MLDR, 0, 10, { A_Look }, S_MLDR_00 }, //711 +/*S_MLDR_01*/ { SPR_MLDR, 0, 3, { A_Chase }, S_MLDR_02 }, //712 +/*S_MLDR_02*/ { SPR_MLDR, 0, 3, { A_Chase }, S_MLDR_03 }, //713 +/*S_MLDR_03*/ { SPR_MLDR, 1, 3, { A_Chase }, S_MLDR_04 }, //714 +/*S_MLDR_04*/ { SPR_MLDR, 1, 3, { A_Chase }, S_MLDR_05 }, //715 +/*S_MLDR_05*/ { SPR_MLDR, 2, 3, { A_Chase }, S_MLDR_06 }, //716 +/*S_MLDR_06*/ { SPR_MLDR, 2, 3, { A_Chase }, S_MLDR_07 }, //717 +/*S_MLDR_07*/ { SPR_MLDR, 3, 3, { A_Chase }, S_MLDR_08 }, //718 +/*S_MLDR_08*/ { SPR_MLDR, 3, 3, { A_Chase }, S_MLDR_01 }, //719 +/*S_MLDR_09*/ { SPR_MLDR, 4, 3, { A_FaceTarget }, S_MLDR_10 }, //720 +/*S_MLDR_10*/ { SPR_MLDR, 32773, 2, { A_BishopAttack }, S_MLDR_01 }, //721 +/*S_MLDR_11*/ { SPR_MLDR, 3, 1, { A_Pain }, S_MLDR_01 }, //722 +/*S_MLDR_12*/ { SPR_MLDR, 32774, 3, { NULL }, S_MLDR_13 }, //723 +/*S_MLDR_13*/ { SPR_MLDR, 32775, 5, { A_Scream }, S_MLDR_14 }, //724 +/*S_MLDR_14*/ { SPR_MLDR, 32776, 4, { A_BodyParts }, S_MLDR_15 }, //725 +/*S_MLDR_15*/ { SPR_MLDR, 32777, 4, { A_DeathExplode2 }, S_MLDR_16 }, //726 +/*S_MLDR_16*/ { SPR_MLDR, 32778, 4, { NULL }, S_MLDR_17 }, //727 +/*S_MLDR_17*/ { SPR_MLDR, 32779, 4, { NULL }, S_MLDR_18 }, //728 +/*S_MLDR_18*/ { SPR_MLDR, 32780, 4, { A_Fall }, S_MLDR_19 }, //729 +/*S_MLDR_19*/ { SPR_MLDR, 32781, 4, { NULL }, S_MLDR_20 }, //730 +/*S_MLDR_20*/ { SPR_MLDR, 32782, 4, { A_BodyParts }, S_MLDR_21 }, //731 +/*S_MLDR_21*/ { SPR_MLDR, 32783, 4, { NULL }, S_MLDR_22 }, //732 +/*S_MLDR_22*/ { SPR_MLDR, 32784, 4, { A_BodyParts }, S_MLDR_23 }, //733 +/*S_MLDR_23*/ { SPR_MLDR, 32785, 4, { NULL }, S_MLDR_24 }, //734 +/*S_MLDR_24*/ { SPR_MLDR, 32786, 4, { A_BodyParts }, S_MLDR_25 }, //735 +/*S_MLDR_25*/ { SPR_MLDR, 32787, 4, { NULL }, S_MLDR_26 }, //736 +/*S_MLDR_26*/ { SPR_MLDR, 32788, 4, { A_BodyParts }, S_MLDR_27 }, //737 +/*S_MLDR_27*/ { SPR_MLDR, 21, 4, { A_SpawnSpectreB }, S_NULL }, //738 +/*S_ORCL_00*/ { SPR_ORCL, 0, -1, { NULL }, S_NULL }, //739 +/*S_ORCL_01*/ { SPR_ORCL, 1, 5, { NULL }, S_ORCL_02 }, //740 +/*S_ORCL_02*/ { SPR_ORCL, 2, 5, { NULL }, S_ORCL_03 }, //741 +/*S_ORCL_03*/ { SPR_ORCL, 3, 5, { NULL }, S_ORCL_04 }, //742 +/*S_ORCL_04*/ { SPR_ORCL, 4, 5, { NULL }, S_ORCL_05 }, //743 +/*S_ORCL_05*/ { SPR_ORCL, 5, 5, { NULL }, S_ORCL_06 }, //744 +/*S_ORCL_06*/ { SPR_ORCL, 6, 5, { NULL }, S_ORCL_07 }, //745 +/*S_ORCL_07*/ { SPR_ORCL, 7, 5, { NULL }, S_ORCL_08 }, //746 +/*S_ORCL_08*/ { SPR_ORCL, 8, 5, { NULL }, S_ORCL_09 }, //747 +/*S_ORCL_09*/ { SPR_ORCL, 9, 5, { NULL }, S_ORCL_10 }, //748 +/*S_ORCL_10*/ { SPR_ORCL, 10, 5, { NULL }, S_ORCL_11 }, //749 +/*S_ORCL_11*/ { SPR_ORCL, 11, 5, { A_Fall }, S_ORCL_12 }, //750 +/*S_ORCL_12*/ { SPR_ORCL, 12, 5, { NULL }, S_ORCL_13 }, //751 +/*S_ORCL_13*/ { SPR_ORCL, 13, 5, { A_AlertSpectreC }, S_ORCL_14 }, //752 +/*S_ORCL_14*/ { SPR_ORCL, 14, 5, { NULL }, S_ORCL_15 }, //753 +/*S_ORCL_15*/ { SPR_ORCL, 15, 5, { NULL }, S_ORCL_16 }, //754 +/*S_ORCL_16*/ { SPR_ORCL, 16, -1, { NULL }, S_NULL }, //755 +/*S_PRST_00*/ { SPR_PRST, 0, 10, { A_Look }, S_PRST_01 }, //756 +/*S_PRST_01*/ { SPR_PRST, 1, 10, { A_FloatWeave }, S_PRST_00 }, //757 +/*S_PRST_02*/ { SPR_PRST, 0, 4, { A_Chase }, S_PRST_03 }, //758 +/*S_PRST_03*/ { SPR_PRST, 0, 4, { A_FloatWeave }, S_PRST_04 }, //759 +/*S_PRST_04*/ { SPR_PRST, 1, 4, { A_Chase }, S_PRST_05 }, //760 +/*S_PRST_05*/ { SPR_PRST, 1, 4, { A_FloatWeave }, S_PRST_06 }, //761 +/*S_PRST_06*/ { SPR_PRST, 2, 4, { A_Chase }, S_PRST_07 }, //762 +/*S_PRST_07*/ { SPR_PRST, 2, 4, { A_FloatWeave }, S_PRST_08 }, //763 +/*S_PRST_08*/ { SPR_PRST, 3, 4, { A_Chase }, S_PRST_09 }, //764 +/*S_PRST_09*/ { SPR_PRST, 3, 4, { A_FloatWeave }, S_PRST_02 }, //765 +/*S_PRST_10*/ { SPR_PRST, 4, 4, { A_FaceTarget }, S_PRST_11 }, //766 +/*S_PRST_11*/ { SPR_PRST, 5, 4, { A_BossMeleeAtk }, S_PRST_12 }, //767 +/*S_PRST_12*/ { SPR_PRST, 4, 4, { A_FloatWeave }, S_PRST_02 }, //768 +/*S_PRST_13*/ { SPR_PRST, 4, 4, { A_FaceTarget }, S_PRST_14 }, //769 +/*S_PRST_14*/ { SPR_PRST, 5, 4, { A_FireHookShot }, S_PRST_15 }, //770 +/*S_PRST_15*/ { SPR_PRST, 4, 4, { A_FloatWeave }, S_PRST_02 }, //771 +/*S_PDED_00*/ { SPR_PDED, 0, 6, { NULL }, S_PDED_01 }, //772 +/*S_PDED_01*/ { SPR_PDED, 1, 6, { A_Scream }, S_PDED_02 }, //773 +/*S_PDED_02*/ { SPR_PDED, 2, 6, { NULL }, S_PDED_03 }, //774 +/*S_PDED_03*/ { SPR_PDED, 3, 6, { A_Fall }, S_PDED_04 }, //775 +/*S_PDED_04*/ { SPR_PDED, 4, 6, { NULL }, S_PDED_05 }, //776 +/*S_PDED_05*/ { SPR_PDED, 5, 5, { NULL }, S_PDED_06 }, //777 +/*S_PDED_06*/ { SPR_PDED, 6, 5, { NULL }, S_PDED_07 }, //778 +/*S_PDED_07*/ { SPR_PDED, 7, 5, { NULL }, S_PDED_08 }, //779 +/*S_PDED_08*/ { SPR_PDED, 8, 5, { NULL }, S_PDED_09 }, //780 +/*S_PDED_09*/ { SPR_PDED, 9, 5, { NULL }, S_PDED_10 }, //781 +/*S_PDED_10*/ { SPR_PDED, 8, 5, { NULL }, S_PDED_11 }, //782 +/*S_PDED_11*/ { SPR_PDED, 9, 5, { NULL }, S_PDED_12 }, //783 +/*S_PDED_12*/ { SPR_PDED, 8, 5, { NULL }, S_PDED_14 }, //784 +/*S_PDED_13*/ { SPR_PDED, 9, 5, { NULL }, S_PDED_14 }, //785 +/*S_PDED_14*/ { SPR_PDED, 10, 5, { NULL }, S_PDED_15 }, //786 +/*S_PDED_15*/ { SPR_PDED, 11, 5, { NULL }, S_PDED_16 }, //787 +/*S_PDED_16*/ { SPR_PDED, 12, 4, { NULL }, S_PDED_17 }, //788 +/*S_PDED_17*/ { SPR_PDED, 13, 4, { NULL }, S_PDED_18 }, //789 +/*S_PDED_18*/ { SPR_PDED, 14, 4, { NULL }, S_PDED_19 }, //790 +/*S_PDED_19*/ { SPR_PDED, 15, 4, { NULL }, S_PDED_20 }, //791 +/*S_PDED_20*/ { SPR_PDED, 16, 4, { A_SpawnSpectreE }, S_PDED_21 }, //792 +/*S_PDED_21*/ { SPR_PDED, 17, 4, { NULL }, S_PDED_22 }, //793 +/*S_PDED_22*/ { SPR_PDED, 18, 4, { NULL }, S_PDED_23 }, //794 +/*S_PDED_23*/ { SPR_PDED, 19, -1, { NULL }, S_NULL }, //795 +/*S_ALN1_00*/ { SPR_ALN1, 0, 10, { A_Look }, S_ALN1_01 }, //796 +/*S_ALN1_01*/ { SPR_ALN1, 1, 10, { A_FloatWeave }, S_ALN1_00 }, //797 +/*S_ALN1_02*/ { SPR_ALN1, 32768, 4, { A_Chase }, S_ALN1_03 }, //798 +/*S_ALN1_03*/ { SPR_ALN1, 32769, 4, { A_Chase }, S_ALN1_04 }, //799 +/*S_ALN1_04*/ { SPR_ALN1, 32770, 4, { A_FloatWeave }, S_ALN1_05 }, //800 +/*S_ALN1_05*/ { SPR_ALN1, 32771, 4, { A_Chase }, S_ALN1_06 }, //801 +/*S_ALN1_06*/ { SPR_ALN1, 32772, 4, { A_Chase }, S_ALN1_07 }, //802 +/*S_ALN1_07*/ { SPR_ALN1, 32773, 4, { A_Chase }, S_ALN1_08 }, //803 +/*S_ALN1_08*/ { SPR_ALN1, 32774, 4, { A_FloatWeave }, S_ALN1_09 }, //804 +/*S_ALN1_09*/ { SPR_ALN1, 32775, 4, { A_Chase }, S_ALN1_10 }, //805 +/*S_ALN1_10*/ { SPR_ALN1, 32776, 4, { A_Chase }, S_ALN1_11 }, //806 +/*S_ALN1_11*/ { SPR_ALN1, 32777, 4, { A_Chase }, S_ALN1_12 }, //807 +/*S_ALN1_12*/ { SPR_ALN1, 32778, 4, { A_FloatWeave }, S_ALN1_02 }, //808 +/*S_ALN1_13*/ { SPR_ALN1, 32777, 4, { A_FaceTarget }, S_ALN1_14 }, //809 +/*S_ALN1_14*/ { SPR_ALN1, 32776, 4, { A_BossMeleeAtk }, S_ALN1_15 }, //810 +/*S_ALN1_15*/ { SPR_ALN1, 32775, 4, { NULL }, S_ALN1_04 }, //811 +/*S_ALN1_16*/ { SPR_ALN1, 32777, 4, { A_FaceTarget }, S_ALN1_17 }, //812 +/*S_ALN1_17*/ { SPR_ALN1, 32776, 4, { A_ProgrammerAttack }, S_ALN1_18 }, //813 +/*S_ALN1_18*/ { SPR_ALN1, 32775, 4, { NULL }, S_ALN1_12 }, //814 +/*S_ALN1_19*/ { SPR_ALN1, 9, 2, { A_Pain }, S_ALN1_08 }, //815 +/*S_AL1P_00*/ { SPR_AL1P, 32768, 6, { A_NodeChunk }, S_AL1P_01 }, //816 +/*S_AL1P_01*/ { SPR_AL1P, 32769, 6, { A_Scream }, S_AL1P_02 }, //817 +/*S_AL1P_02*/ { SPR_AL1P, 32770, 6, { A_NodeChunk }, S_AL1P_03 }, //818 +/*S_AL1P_03*/ { SPR_AL1P, 32771, 6, { NULL }, S_AL1P_04 }, //819 +/*S_AL1P_04*/ { SPR_AL1P, 32772, 6, { NULL }, S_AL1P_05 }, //820 +/*S_AL1P_05*/ { SPR_AL1P, 32773, 6, { A_NodeChunk }, S_AL1P_06 }, //821 +/*S_AL1P_06*/ { SPR_AL1P, 32774, 6, { NULL }, S_AL1P_07 }, //822 +/*S_AL1P_07*/ { SPR_AL1P, 32775, 6, { A_NodeChunk }, S_AL1P_08 }, //823 +/*S_AL1P_08*/ { SPR_AL1P, 32776, 6, { NULL }, S_AL1P_09 }, //824 +/*S_AL1P_09*/ { SPR_AL1P, 32777, 6, { NULL }, S_AL1P_10 }, //825 +/*S_AL1P_10*/ { SPR_AL1P, 32778, 6, { NULL }, S_AL1P_11 }, //826 +/*S_AL1P_11*/ { SPR_AL1P, 32779, 5, { NULL }, S_AL1P_12 }, //827 +/*S_AL1P_12*/ { SPR_AL1P, 32780, 5, { NULL }, S_AL1P_13 }, //828 +/*S_AL1P_13*/ { SPR_AL1P, 32781, 5, { A_HeadChunk }, S_AL1P_14 }, //829 +/*S_AL1P_14*/ { SPR_AL1P, 32782, 5, { NULL }, S_AL1P_15 }, //830 +/*S_AL1P_15*/ { SPR_AL1P, 32783, 5, { NULL }, S_AL1P_16 }, //831 +/*S_AL1P_16*/ { SPR_AL1P, 32784, 5, { NULL }, S_AL1P_17 }, //832 +/*S_AL1P_17*/ { SPR_AL1P, 32785, 5, { A_BossDeath }, S_NULL }, //833 +/*S_NODE_00*/ { SPR_NODE, 32768, 6, { NULL }, S_NODE_01 }, //834 +/*S_NODE_01*/ { SPR_NODE, 32769, 6, { NULL }, S_NODE_02 }, //835 +/*S_NODE_02*/ { SPR_NODE, 32770, 6, { NULL }, S_NODE_03 }, //836 +/*S_NODE_03*/ { SPR_NODE, 32771, 6, { NULL }, S_NODE_04 }, //837 +/*S_NODE_04*/ { SPR_NODE, 32772, 6, { NULL }, S_NODE_05 }, //838 +/*S_NODE_05*/ { SPR_NODE, 32773, 6, { NULL }, S_NODE_06 }, //839 +/*S_NODE_06*/ { SPR_NODE, 32774, 6, { NULL }, S_NULL }, //840 +/*S_MTHD_00*/ { SPR_MTHD, 32768, 5, { NULL }, S_MTHD_01 }, //841 +/*S_MTHD_01*/ { SPR_MTHD, 32769, 5, { NULL }, S_MTHD_02 }, //842 +/*S_MTHD_02*/ { SPR_MTHD, 32770, 5, { NULL }, S_MTHD_03 }, //843 +/*S_MTHD_03*/ { SPR_MTHD, 32771, 5, { NULL }, S_MTHD_04 }, //844 +/*S_MTHD_04*/ { SPR_MTHD, 32772, 5, { NULL }, S_MTHD_05 }, //845 +/*S_MTHD_05*/ { SPR_MTHD, 32773, 5, { NULL }, S_MTHD_06 }, //846 +/*S_MTHD_06*/ { SPR_MTHD, 32774, 5, { NULL }, S_MTHD_07 }, //847 +/*S_MTHD_07*/ { SPR_MTHD, 32775, 5, { NULL }, S_MTHD_08 }, //848 +/*S_MTHD_08*/ { SPR_MTHD, 32776, 5, { NULL }, S_MTHD_09 }, //849 +/*S_MTHD_09*/ { SPR_MTHD, 32777, 5, { NULL }, S_MTHD_10 }, //850 +/*S_MTHD_10*/ { SPR_MTHD, 32778, 5, { NULL }, S_NULL }, //851 +/*S_ALN1_20*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_21 }, //852 +/*S_ALN1_21*/ { SPR_ALN1, 8, 4, { A_FireSigilEOffshoot }, S_ALN1_22 }, //853 +/*S_ALN1_22*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_12 }, //854 +/*S_ALN1_23*/ { SPR_ALN1, 0, 5, { A_FloatWeave }, S_ALN1_24 }, //855 +/*S_ALN1_24*/ { SPR_ALN1, 1, 5, { A_FloatWeave }, S_ALN1_25 }, //856 +/*S_ALN1_25*/ { SPR_ALN1, 2, 5, { A_FloatWeave }, S_ALN1_26 }, //857 +/*S_ALN1_26*/ { SPR_ALN1, 3, 5, { A_FloatWeave }, S_ALN1_27 }, //858 +/*S_ALN1_27*/ { SPR_ALN1, 4, 5, { A_FloatWeave }, S_ALN1_28 }, //859 +/*S_ALN1_28*/ { SPR_ALN1, 5, 5, { A_FloatWeave }, S_ALN1_29 }, //860 +/*S_ALN1_29*/ { SPR_ALN1, 6, 5, { A_FloatWeave }, S_ALN1_30 }, //861 +/*S_ALN1_30*/ { SPR_ALN1, 7, 5, { A_FloatWeave }, S_ALN1_31 }, //862 +/*S_ALN1_31*/ { SPR_ALN1, 8, 5, { A_FloatWeave }, S_ALN1_32 }, //863 +/*S_ALN1_32*/ { SPR_ALN1, 9, 5, { A_FloatWeave }, S_ALN1_33 }, //864 +/*S_ALN1_33*/ { SPR_ALN1, 10, 5, { A_FloatWeave }, S_ALN1_23 }, //865 +/*S_ALN1_34*/ { SPR_ALN1, 0, 5, { A_Chase }, S_ALN1_35 }, //866 +/*S_ALN1_35*/ { SPR_ALN1, 1, 5, { A_Chase }, S_ALN1_36 }, //867 +/*S_ALN1_36*/ { SPR_ALN1, 2, 5, { A_FloatWeave }, S_ALN1_37 }, //868 +/*S_ALN1_37*/ { SPR_ALN1, 3, 5, { A_Chase }, S_ALN1_38 }, //869 +/*S_ALN1_38*/ { SPR_ALN1, 4, 5, { A_Chase }, S_ALN1_39 }, //870 +/*S_ALN1_39*/ { SPR_ALN1, 5, 5, { A_Chase }, S_ALN1_40 }, //871 +/*S_ALN1_40*/ { SPR_ALN1, 6, 5, { A_FloatWeave }, S_ALN1_41 }, //872 +/*S_ALN1_41*/ { SPR_ALN1, 7, 5, { A_Chase }, S_ALN1_42 }, //873 +/*S_ALN1_42*/ { SPR_ALN1, 8, 5, { A_Chase }, S_ALN1_43 }, //874 +/*S_ALN1_43*/ { SPR_ALN1, 9, 5, { A_Chase }, S_ALN1_44 }, //875 +/*S_ALN1_44*/ { SPR_ALN1, 10, 5, { A_FloatWeave }, S_ALN1_34 }, //876 +/*S_ALN1_45*/ { SPR_ALN1, 9, 4, { A_FaceTarget }, S_ALN1_46 }, //877 +/*S_ALN1_46*/ { SPR_ALN1, 8, 4, { A_BossMeleeAtk }, S_ALN1_47 }, //878 +/*S_ALN1_47*/ { SPR_ALN1, 2, 4, { NULL }, S_ALN1_36 }, //879 +/*S_ALN1_48*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_49 }, //880 +/*S_ALN1_49*/ { SPR_ALN1, 8, 4, { A_SpectreCAttack }, S_ALN1_50 }, //881 +/*S_ALN1_50*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_44 }, //882 +/*S_ALN1_51*/ { SPR_ALN1, 9, 2, { A_Pain }, S_ALN1_40 }, //883 +/*S_ALN1_52*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_53 }, //884 +/*S_ALN1_53*/ { SPR_ALN1, 8, 4, { A_SpectreDAttack }, S_ALN1_54 }, //885 +/*S_ALN1_54*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_12 }, //886 +/*S_ALN1_55*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_56 }, //887 +/*S_ALN1_56*/ { SPR_ALN1, 8, 4, { A_SpectreEAttack }, S_ALN1_57 }, //888 +/*S_ALN1_57*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_12 }, //889 +/*S_MNAM_00*/ { SPR_MNAM, 0, 100, { A_FloatWeave }, S_MNAM_01 }, //890 +/*S_MNAM_01*/ { SPR_MNAM, 32769, 60, { A_FloatWeave }, S_MNAM_02 }, //891 +/*S_MNAM_02*/ { SPR_MNAM, 32770, 4, { A_FloatWeave }, S_MNAM_03 }, //892 +/*S_MNAM_03*/ { SPR_MNAM, 32771, 4, { A_FloatWeave }, S_MNAM_04 }, //893 +/*S_MNAM_04*/ { SPR_MNAM, 32772, 4, { A_FloatWeave }, S_MNAM_05 }, //894 +/*S_MNAM_05*/ { SPR_MNAM, 32773, 4, { A_FloatWeave }, S_MNAM_06 }, //895 +/*S_MNAM_06*/ { SPR_MNAM, 32774, 4, { A_FloatWeave }, S_MNAM_07 }, //896 +/*S_MNAM_07*/ { SPR_MNAM, 32775, 4, { A_FloatWeave }, S_MNAM_08 }, //897 +/*S_MNAM_08*/ { SPR_MNAM, 32776, 4, { A_FloatWeave }, S_MNAM_09 }, //898 +/*S_MNAM_09*/ { SPR_MNAM, 32777, 4, { A_FloatWeave }, S_MNAM_10 }, //899 +/*S_MNAM_10*/ { SPR_MNAM, 32778, 4, { A_FloatWeave }, S_MNAM_11 }, //900 +/*S_MNAM_11*/ { SPR_MNAM, 32779, 4, { A_FloatWeave }, S_MNAL_00 }, //901 +/*S_MNAL_00*/ { SPR_MNAL, 32768, 4, { A_Look }, S_MNAL_01 }, //902 +/*S_MNAL_01*/ { SPR_MNAL, 32769, 4, { A_FloatWeave }, S_MNAL_00 }, //903 +/*S_MNAL_02*/ { SPR_MNAL, 32768, 4, { A_Chase }, S_MNAL_03 }, //904 +/*S_MNAL_03*/ { SPR_MNAL, 32769, 4, { A_Chase }, S_MNAL_04 }, //905 +/*S_MNAL_04*/ { SPR_MNAL, 32770, 4, { A_FloatWeave }, S_MNAL_05 }, //906 +/*S_MNAL_05*/ { SPR_MNAL, 32771, 4, { A_Chase }, S_MNAL_06 }, //907 +/*S_MNAL_06*/ { SPR_MNAL, 32772, 4, { A_Chase }, S_MNAL_07 }, //908 +/*S_MNAL_07*/ { SPR_MNAL, 32773, 4, { A_Chase }, S_MNAL_08 }, //909 +/*S_MNAL_08*/ { SPR_MNAL, 32774, 4, { A_FloatWeave }, S_MNAL_09 }, //910 +/*S_MNAL_09*/ { SPR_MNAL, 32775, 4, { A_Chase }, S_MNAL_10 }, //911 +/*S_MNAL_10*/ { SPR_MNAL, 32776, 4, { A_Chase }, S_MNAL_11 }, //912 +/*S_MNAL_11*/ { SPR_MNAL, 32777, 4, { A_Chase }, S_MNAL_12 }, //913 +/*S_MNAL_12*/ { SPR_MNAL, 32778, 4, { A_FloatWeave }, S_MNAL_02 }, //914 +/*S_MNAL_13*/ { SPR_MNAL, 32777, 4, { A_FaceTarget }, S_MNAL_14 }, //915 +/*S_MNAL_14*/ { SPR_MNAL, 32776, 4, { A_BossMeleeAtk }, S_MNAL_15 }, //916 +/*S_MNAL_15*/ { SPR_MNAL, 32770, 4, { NULL }, S_MNAL_04 }, //917 +/*S_MNAL_16*/ { SPR_MNAL, 32773, 4, { A_FaceTarget }, S_MNAL_17 }, //918 +/*S_MNAL_17*/ { SPR_MNAL, 32776, 4, { A_FireSigilWeapon }, S_MNAL_18 }, //919 +/*S_MNAL_18*/ { SPR_MNAL, 32772, 4, { NULL }, S_MNAL_12 }, //920 +/*S_MNAL_19*/ { SPR_MNAL, 32777, 2, { A_Pain }, S_MNAL_08 }, //921 +/*S_MNAL_20*/ { SPR_MNAL, 32779, 7, { A_NodeChunk }, S_MNAL_21 }, //922 +/*S_MNAL_21*/ { SPR_MNAL, 32780, 7, { A_Scream }, S_MNAL_22 }, //923 +/*S_MNAL_22*/ { SPR_MNAL, 32781, 7, { A_NodeChunk }, S_MNAL_23 }, //924 +/*S_MNAL_23*/ { SPR_MNAL, 32782, 7, { A_NodeChunk }, S_MNAL_24 }, //925 +/*S_MNAL_24*/ { SPR_MNAL, 32783, 7, { A_HeadChunk }, S_MNAL_25 }, //926 +/*S_MNAL_25*/ { SPR_MNAL, 32784, 64, { A_NodeChunk }, S_MNAL_26 }, //927 +/*S_MNAL_26*/ { SPR_MNAL, 32784, 6, { A_EntityDeath }, S_NULL }, //928 +/*S_MNAL_27*/ { SPR_MNAL, 32785, 10, { A_Look }, S_MNAL_27 }, //929 +/*S_MNAL_28*/ { SPR_MNAL, 32785, 5, { A_FloatWeave }, S_MNAL_29 }, //930 +/*S_MNAL_29*/ { SPR_MNAL, 32786, 5, { A_Chase }, S_MNAL_30 }, //931 +/*S_MNAL_30*/ { SPR_MNAL, 32787, 5, { A_Chase }, S_MNAL_31 }, //932 +/*S_MNAL_31*/ { SPR_MNAL, 32788, 5, { A_FloatWeave }, S_MNAL_32 }, //933 +/*S_MNAL_32*/ { SPR_MNAL, 32789, 5, { A_Chase }, S_MNAL_33 }, //934 +/*S_MNAL_33*/ { SPR_MNAL, 32790, 5, { A_FloatWeave }, S_MNAL_28 }, //935 +/*S_MNAL_34*/ { SPR_MNAL, 32786, 4, { A_FaceTarget }, S_MNAL_35 }, //936 +/*S_MNAL_35*/ { SPR_MNAL, 32785, 4, { A_BossMeleeAtk }, S_MNAL_36 }, //937 +/*S_MNAL_36*/ { SPR_MNAL, 32787, 4, { A_FloatWeave }, S_MNAL_29 }, //938 +/*S_MNAL_37*/ { SPR_MNAL, 32790, 4, { A_FaceTarget }, S_MNAL_38 }, //939 +/*S_MNAL_38*/ { SPR_MNAL, 32788, 4, { A_FireSigilEOffshoot }, S_MNAL_39 }, //940 +/*S_MNAL_39*/ { SPR_MNAL, 32789, 4, { A_FloatWeave }, S_MNAL_32 }, //941 +/*S_MNAL_40*/ { SPR_MNAL, 32785, 2, { A_Pain }, S_MNAL_28 }, //942 +/*S_MDTH_00*/ { SPR_MDTH, 32768, 3, { A_Scream }, S_MDTH_01 }, //943 +/*S_MDTH_01*/ { SPR_MDTH, 32769, 3, { A_BodyParts }, S_MDTH_02 }, //944 +/*S_MDTH_02*/ { SPR_MDTH, 32770, 3, { A_Fall }, S_MDTH_03 }, //945 +/*S_MDTH_03*/ { SPR_MDTH, 32771, 3, { A_BodyParts }, S_MDTH_04 }, //946 +/*S_MDTH_04*/ { SPR_MDTH, 32772, 3, { A_BodyParts }, S_MDTH_05 }, //947 +/*S_MDTH_05*/ { SPR_MDTH, 32773, 3, { A_BodyParts }, S_MDTH_06 }, //948 +/*S_MDTH_06*/ { SPR_MDTH, 32774, 3, { A_BodyParts }, S_MDTH_07 }, //949 +/*S_MDTH_07*/ { SPR_MDTH, 32775, 3, { A_BodyParts }, S_MDTH_08 }, //950 +/*S_MDTH_08*/ { SPR_MDTH, 32776, 3, { A_BodyParts }, S_MDTH_09 }, //951 +/*S_MDTH_09*/ { SPR_MDTH, 32777, 3, { A_BodyParts }, S_MDTH_10 }, //952 +/*S_MDTH_10*/ { SPR_MDTH, 32778, 3, { A_BodyParts }, S_MDTH_11 }, //953 +/*S_MDTH_11*/ { SPR_MDTH, 32779, 3, { A_BodyParts }, S_MDTH_12 }, //954 +/*S_MDTH_12*/ { SPR_MDTH, 32780, 3, { A_BodyParts }, S_MDTH_13 }, //955 +/*S_MDTH_13*/ { SPR_MDTH, 32781, 3, { A_BodyParts }, S_MDTH_14 }, //956 +/*S_MDTH_14*/ { SPR_MDTH, 32782, 3, { A_BossDeath }, S_NULL }, //957 +/*S_NEST_00*/ { SPR_NEST, 0, -1, { NULL }, S_NULL }, //958 +/*S_PODD_00*/ { SPR_PODD, 0, 60, { A_Look }, S_PODD_00 }, //959 +/*S_PODD_01*/ { SPR_PODD, 0, 360, { NULL }, S_PODD_02 }, //960 +/*S_PODD_02*/ { SPR_PODD, 1, 9, { A_Fall }, S_PODD_03 }, //961 +/*S_PODD_03*/ { SPR_PODD, 2, 9, { NULL }, S_PODD_04 }, //962 +/*S_PODD_04*/ { SPR_PODD, 3, 9, { A_SpawnEntity }, S_PODD_05 }, //963 +/*S_PODD_05*/ { SPR_PODD, 4, -1, { NULL }, S_NULL }, //964 +/*S_ZAP6_00*/ { SPR_ZAP6, 32768, 4, { NULL }, S_ZAP6_01 }, //965 +/*S_ZAP6_01*/ { SPR_ZAP6, 32769, 4, { A_SigilTrail }, S_ZAP6_02 }, //966 +/*S_ZAP6_02*/ { SPR_ZAP6, 32770, 4, { A_SigilTrail }, S_ZAP6_00 }, //967 +/*S_ZOT3_00*/ { SPR_ZOT3, 32768, 4, { NULL }, S_ZOT3_01 }, //968 +/*S_ZOT3_01*/ { SPR_ZOT3, 32769, 4, { NULL }, S_ZOT3_02 }, //969 +/*S_ZOT3_02*/ { SPR_ZOT3, 32770, 4, { NULL }, S_ZOT3_03 }, //970 +/*S_ZOT3_03*/ { SPR_ZOT3, 32771, 4, { NULL }, S_ZOT3_04 }, //971 +/*S_ZOT3_04*/ { SPR_ZOT3, 32772, 4, { NULL }, S_ZOT3_00 }, //972 +/*S_ZAP6_03*/ { SPR_ZAP6, 32768, 5, { NULL }, S_ZAP6_04 }, //973 +/*S_ZAP6_04*/ { SPR_ZAP6, 32769, 5, { NULL }, S_ZAP6_05 }, //974 +/*S_ZAP6_05*/ { SPR_ZAP6, 32770, 5, { NULL }, S_NULL }, //975 +/*S_ZAP7_00*/ { SPR_ZAP7, 32768, 4, { A_Sigil_E_Action }, S_ZAP7_01 }, //976 +/*S_ZAP7_01*/ { SPR_ZAP7, 32769, 4, { A_Sigil_E_Action }, S_ZAP7_02 }, //977 +/*S_ZAP7_02*/ { SPR_ZAP7, 32770, 6, { A_Sigil_E_Action }, S_ZAP7_03 }, //978 +/*S_ZAP7_03*/ { SPR_ZAP7, 32771, 6, { A_Sigil_E_Action }, S_ZAP7_04 }, //979 +/*S_ZAP7_04*/ { SPR_ZAP7, 32772, 6, { A_Sigil_E_Action }, S_ZAP7_00 }, //980 +/*S_ZOT1_00*/ { SPR_ZOT1, 32768, 4, { NULL }, S_ZOT1_01 }, //981 +/*S_ZOT1_01*/ { SPR_ZOT1, 32769, 4, { NULL }, S_ZOT1_02 }, //982 +/*S_ZOT1_02*/ { SPR_ZOT1, 32770, 6, { NULL }, S_ZOT1_03 }, //983 +/*S_ZOT1_03*/ { SPR_ZOT1, 32771, 6, { NULL }, S_ZOT1_04 }, //984 +/*S_ZOT1_04*/ { SPR_ZOT1, 32771, 6, { NULL }, S_ZOT1_00 }, //985 +/*S_ZAP5_00*/ { SPR_ZAP5, 32768, 4, { A_MissileTick }, S_ZAP5_01 }, //986 +/*S_ZAP5_01*/ { SPR_ZAP5, 32769, 4, { A_Sigil_A_Action }, S_ZAP5_02 }, //987 +/*S_ZAP5_02*/ { SPR_ZAP5, 32770, 4, { A_MissileTick }, S_ZAP5_03 }, //988 +/*S_ZAP5_03*/ { SPR_ZAP5, 32771, 4, { A_MissileTick }, S_ZAP5_00 }, //989 +/*S_ZOT2_00*/ { SPR_ZOT2, 32768, 4, { A_Tracer }, S_ZOT2_01 }, //990 +/*S_ZOT2_01*/ { SPR_ZOT2, 32769, 4, { A_Tracer }, S_ZOT2_02 }, //991 +/*S_ZOT2_02*/ { SPR_ZOT2, 32770, 6, { A_Tracer }, S_ZOT2_03 }, //992 +/*S_ZOT2_03*/ { SPR_ZOT2, 32771, 6, { A_Tracer }, S_ZOT2_04 }, //993 +/*S_ZOT2_04*/ { SPR_ZOT2, 32772, 5, { A_Tracer }, S_ZOT2_00 }, //994 +/*S_SEWR_00*/ { SPR_SEWR, 0, 10, { A_Look }, S_SEWR_00 }, //995 +/*S_SEWR_01*/ { SPR_SEWR, 0, 6, { A_FloatWeave }, S_SEWR_02 }, //996 +/*S_SEWR_02*/ { SPR_SEWR, 0, 6, { A_Chase }, S_SEWR_01 }, //997 +/*S_SEWR_03*/ { SPR_SEWR, 1, 4, { A_FaceTarget }, S_SEWR_04 }, //998 +/*S_SEWR_04*/ { SPR_SEWR, 32770, 8, { A_SentinelAttack }, S_SEWR_05 }, //999 +/*S_SEWR_05*/ { SPR_SEWR, 32770, 4, { A_CheckTargetVisible }, S_SEWR_04 }, //1000 +/*S_SEWR_06*/ { SPR_SEWR, 3, 5, { A_Pain }, S_SEWR_05 }, //1001 +/*S_SEWR_07*/ { SPR_SEWR, 3, 7, { A_Fall }, S_SEWR_08 }, //1002 +/*S_SEWR_08*/ { SPR_SEWR, 32772, 8, { A_BodyParts }, S_SEWR_09 }, //1003 +/*S_SEWR_09*/ { SPR_SEWR, 32773, 5, { A_Scream }, S_SEWR_10 }, //1004 +/*S_SEWR_10*/ { SPR_SEWR, 32774, 4, { A_BodyParts }, S_SEWR_11 }, //1005 +/*S_SEWR_11*/ { SPR_SEWR, 32775, 4, { A_BodyParts }, S_SEWR_12 }, //1006 +/*S_SEWR_12*/ { SPR_SEWR, 8, 4, { NULL }, S_SEWR_13 }, //1007 +/*S_SEWR_13*/ { SPR_SEWR, 9, 5, { NULL }, S_NULL }, //1008 +/*S_SPID_00*/ { SPR_SPID, 0, 1, { A_StalkerSetLook }, S_SPID_00 }, //1009 +/*S_SPID_01*/ { SPR_SPID, 0, 10, { A_Look }, S_SPID_01 }, //1010 +/*S_SPID_02*/ { SPR_SPID, 9, 10, { A_Look }, S_SPID_02 }, //1011 +/*S_SPID_03*/ { SPR_SPID, 0, 1, { A_StalkerThink }, S_SPID_04 }, //1012 +/*S_SPID_04*/ { SPR_SPID, 0, 3, { A_Chase }, S_SPID_05 }, //1013 +/*S_SPID_05*/ { SPR_SPID, 1, 3, { A_Chase }, S_SPID_06 }, //1014 +/*S_SPID_06*/ { SPR_SPID, 1, 3, { A_Chase }, S_SPID_07 }, //1015 +/*S_SPID_07*/ { SPR_SPID, 2, 3, { A_StalkerChase }, S_SPID_08 }, //1016 +/*S_SPID_08*/ { SPR_SPID, 2, 3, { A_Chase }, S_SPID_03 }, //1017 +/*S_SPID_09*/ { SPR_SPID, 9, 3, { A_FaceTarget }, S_SPID_10 }, //1018 +/*S_SPID_10*/ { SPR_SPID, 10, 3, { A_StalkerScratch }, S_SPID_18 }, //1019 +/*S_SPID_11*/ { SPR_SPID, 2, 2, { A_StalkerDrop }, S_SPID_12 }, //1020 +/*S_SPID_12*/ { SPR_SPID, 8, 3, { NULL }, S_SPID_13 }, //1021 +/*S_SPID_13*/ { SPR_SPID, 7, 3, { NULL }, S_SPID_14 }, //1022 +/*S_SPID_14*/ { SPR_SPID, 6, 3, { NULL }, S_SPID_15 }, //1023 +/*S_SPID_15*/ { SPR_SPID, 5, 3, { NULL }, S_SPID_16 }, //1024 +/*S_SPID_16*/ { SPR_SPID, 4, 3, { NULL }, S_SPID_17 }, //1025 +/*S_SPID_17*/ { SPR_SPID, 3, 3, { NULL }, S_SPID_09 }, //1026 +/*S_SPID_18*/ { SPR_SPID, 9, 3, { A_StalkerChase }, S_SPID_19 }, //1027 +/*S_SPID_19*/ { SPR_SPID, 9, 3, { A_Chase }, S_SPID_20 }, //1028 +/*S_SPID_20*/ { SPR_SPID, 10, 3, { A_Chase }, S_SPID_21 }, //1029 +/*S_SPID_21*/ { SPR_SPID, 10, 3, { A_Chase }, S_SPID_22 }, //1030 +/*S_SPID_22*/ { SPR_SPID, 11, 3, { A_StalkerChase }, S_SPID_23 }, //1031 +/*S_SPID_23*/ { SPR_SPID, 11, 3, { A_Chase }, S_SPID_18 }, //1032 +/*S_SPID_24*/ { SPR_SPID, 11, 1, { A_Pain }, S_SPID_03 }, //1033 +/*S_SPID_25*/ { SPR_SPID, 14, 4, { NULL }, S_SPID_26 }, //1034 +/*S_SPID_26*/ { SPR_SPID, 15, 4, { A_Scream }, S_SPID_27 }, //1035 +/*S_SPID_27*/ { SPR_SPID, 16, 4, { NULL }, S_SPID_28 }, //1036 +/*S_SPID_28*/ { SPR_SPID, 17, 4, { NULL }, S_SPID_29 }, //1037 +/*S_SPID_29*/ { SPR_SPID, 18, 4, { NULL }, S_SPID_30 }, //1038 +/*S_SPID_30*/ { SPR_SPID, 19, 4, { NULL }, S_SPID_31 }, //1039 +/*S_SPID_31*/ { SPR_SPID, 20, 4, { A_Fall }, S_SPID_32 }, //1040 +/*S_SPID_32*/ { SPR_SPID, 21, 4, { NULL }, S_SPID_33 }, //1041 +/*S_SPID_33*/ { SPR_SPID, 22, 4, { NULL }, S_SPID_34 }, //1042 +/*S_SPID_34*/ { SPR_SPID, 32791, 4, { NULL }, S_SPID_35 }, //1043 +/*S_SPID_35*/ { SPR_SPID, 32792, 4, { NULL }, S_SPID_36 }, //1044 +/*S_SPID_36*/ { SPR_SPID, 32793, 4, { NULL }, S_SPID_37 }, //1045 +/*S_SPID_37*/ { SPR_SPID, 32794, 4, { NULL }, S_NULL }, //1046 +/*S_ROB3_00*/ { SPR_ROB3, 0, 10, { A_Look }, S_ROB3_01 }, //1047 +/*S_ROB3_01*/ { SPR_ROB3, 1, 10, { A_Look }, S_ROB3_00 }, //1048 +/*S_ROB3_02*/ { SPR_ROB3, 1, 3, { A_InqChase }, S_ROB3_03 }, //1049 +/*S_ROB3_03*/ { SPR_ROB3, 1, 3, { A_Chase }, S_ROB3_04 }, //1050 +/*S_ROB3_04*/ { SPR_ROB3, 2, 4, { A_Chase }, S_ROB3_05 }, //1051 +/*S_ROB3_05*/ { SPR_ROB3, 2, 4, { A_Chase }, S_ROB3_06 }, //1052 +/*S_ROB3_06*/ { SPR_ROB3, 3, 4, { A_Chase }, S_ROB3_07 }, //1053 +/*S_ROB3_07*/ { SPR_ROB3, 3, 4, { A_Chase }, S_ROB3_08 }, //1054 +/*S_ROB3_08*/ { SPR_ROB3, 4, 3, { A_InqChase }, S_ROB3_09 }, //1055 +/*S_ROB3_09*/ { SPR_ROB3, 4, 3, { A_InqFlyCheck }, S_ROB3_02 }, //1056 +/*S_ROB3_10*/ { SPR_ROB3, 0, 2, { A_InqFlyCheck }, S_ROB3_11 }, //1057 +/*S_ROB3_11*/ { SPR_ROB3, 5, 6, { A_FaceTarget }, S_ROB3_12 }, //1058 +/*S_ROB3_12*/ { SPR_ROB3, 32774, 8, { A_ReaverAttack }, S_ROB3_13 }, //1059 +/*S_ROB3_13*/ { SPR_ROB3, 6, 8, { A_ReaverAttack }, S_ROB3_02 }, //1060 +/*S_ROB3_14*/ { SPR_ROB3, 10, 12, { A_FaceTarget }, S_ROB3_15 }, //1061 +/*S_ROB3_15*/ { SPR_ROB3, 32777, 6, { A_InqGrenade }, S_ROB3_16 }, //1062 +/*S_ROB3_16*/ { SPR_ROB3, 10, 12, { NULL }, S_ROB3_02 }, //1063 +/*S_ROB3_17*/ { SPR_ROB3, 32775, 8, { A_InqTakeOff }, S_ROB3_18 }, //1064 +/*S_ROB3_18*/ { SPR_ROB3, 32776, 4, { A_InqFly }, S_ROB3_19 }, //1065 +/*S_ROB3_19*/ { SPR_ROB3, 32775, 4, { A_InqFly }, S_ROB3_18 }, //1066 +/*S_ROB3_20*/ { SPR_ROB3, 11, 4, { A_BodyParts }, S_ROB3_21 }, //1067 +/*S_ROB3_21*/ { SPR_ROB3, 12, 4, { A_Scream }, S_ROB3_22 }, //1068 +/*S_ROB3_22*/ { SPR_ROB3, 13, 4, { A_BodyParts }, S_ROB3_23 }, //1069 +/*S_ROB3_23*/ { SPR_ROB3, 32782, 4, { A_DeathExplode1 }, S_ROB3_24 }, //1070 +/*S_ROB3_24*/ { SPR_ROB3, 32783, 4, { A_BodyParts }, S_ROB3_25 }, //1071 +/*S_ROB3_25*/ { SPR_ROB3, 32784, 4, { A_Fall }, S_ROB3_26 }, //1072 +/*S_ROB3_26*/ { SPR_ROB3, 17, 4, { A_BodyParts }, S_ROB3_27 }, //1073 +/*S_ROB3_27*/ { SPR_ROB3, 18, 4, { A_BodyParts }, S_ROB3_28 }, //1074 +/*S_ROB3_28*/ { SPR_ROB3, 19, 4, { A_BodyParts }, S_ROB3_29 }, //1075 +/*S_ROB3_29*/ { SPR_ROB3, 20, 4, { A_BodyParts }, S_ROB3_30 }, //1076 +/*S_ROB3_30*/ { SPR_ROB3, 21, 4, { A_BodyParts }, S_ROB3_31 }, //1077 +/*S_ROB3_31*/ { SPR_ROB3, 32790, 4, { A_DeathExplode1 }, S_ROB3_32 }, //1078 +/*S_ROB3_32*/ { SPR_ROB3, 32791, 4, { A_BodyParts }, S_ROB3_33 }, //1079 +/*S_ROB3_33*/ { SPR_ROB3, 32792, 4, { A_BodyParts }, S_ROB3_34 }, //1080 +/*S_ROB3_34*/ { SPR_ROB3, 25, 4, { A_BodyParts }, S_ROB3_35 }, //1081 +/*S_ROB3_35*/ { SPR_ROB3, 26, 4, { A_BodyParts }, S_ROB3_36 }, //1082 +/*S_ROB3_36*/ { SPR_ROB3, 27, 3, { A_BodyParts }, S_ROB3_37 }, //1083 +/*S_ROB3_37*/ { SPR_ROB3, 32796, 3, { A_DeathExplode1 }, S_RBB3_00 }, //1084 +/*S_RBB3_00*/ { SPR_RBB3, 32768, 3, { A_InqTossArm }, S_RBB3_01 }, //1085 +/*S_RBB3_01*/ { SPR_RBB3, 32769, 3, { A_BodyParts }, S_RBB3_02 }, //1086 +/*S_RBB3_02*/ { SPR_RBB3, 2, 3, { A_BodyParts }, S_RBB3_03 }, //1087 +/*S_RBB3_03*/ { SPR_RBB3, 3, 3, { A_BodyParts }, S_RBB3_04 }, //1088 +/*S_RBB3_04*/ { SPR_RBB3, 4, -1, { A_BossDeath }, S_NULL }, //1089 +/*S_RBB3_05*/ { SPR_RBB3, 32773, 5, { NULL }, S_RBB3_06 }, //1090 +/*S_RBB3_06*/ { SPR_RBB3, 32774, 5, { NULL }, S_RBB3_07 }, //1091 +/*S_RBB3_07*/ { SPR_RBB3, 7, -1, { NULL }, S_NULL }, //1092 +/*S_PRGR_00*/ { SPR_PRGR, 0, 5, { A_Look }, S_PRGR_01 }, //1093 +/*S_PRGR_01*/ { SPR_PRGR, 0, 1, { A_FloatWeave }, S_PRGR_00 }, //1094 +/*S_PRGR_02*/ { SPR_PRGR, 0, 160, { A_FloatWeave }, S_PRGR_03 }, //1095 +/*S_PRGR_03*/ { SPR_PRGR, 1, 5, { A_FloatWeave }, S_PRGR_04 }, //1096 +/*S_PRGR_04*/ { SPR_PRGR, 2, 5, { A_FloatWeave }, S_PRGR_05 }, //1097 +/*S_PRGR_05*/ { SPR_PRGR, 3, 5, { A_FloatWeave }, S_PRGR_06 }, //1098 +/*S_PRGR_06*/ { SPR_PRGR, 4, 2, { A_FloatWeave }, S_PRGR_07 }, //1099 +/*S_PRGR_07*/ { SPR_PRGR, 5, 2, { A_FloatWeave }, S_PRGR_08 }, //1100 +/*S_PRGR_08*/ { SPR_PRGR, 4, 3, { A_Chase }, S_PRGR_09 }, //1101 +/*S_PRGR_09*/ { SPR_PRGR, 5, 3, { A_Chase }, S_PRGR_06 }, //1102 +/*S_PRGR_10*/ { SPR_PRGR, 4, 2, { A_FloatWeave }, S_PRGR_11 }, //1103 +/*S_PRGR_11*/ { SPR_PRGR, 5, 3, { A_FloatWeave }, S_PRGR_12 }, //1104 +/*S_PRGR_12*/ { SPR_PRGR, 4, 3, { A_FaceTarget }, S_PRGR_13 }, //1105 +/*S_PRGR_13*/ { SPR_PRGR, 5, 4, { A_ProgrammerMelee }, S_PRGR_06 }, //1106 +/*S_PRGR_14*/ { SPR_PRGR, 6, 5, { A_FaceTarget }, S_PRGR_15 }, //1107 +/*S_PRGR_15*/ { SPR_PRGR, 7, 5, { A_FloatWeave }, S_PRGR_16 }, //1108 +/*S_PRGR_16*/ { SPR_PRGR, 32776, 5, { A_FaceTarget }, S_PRGR_17 }, //1109 +/*S_PRGR_17*/ { SPR_PRGR, 32777, 5, { A_ProgrammerAttack }, S_PRGR_06 }, //1110 +/*S_PRGR_18*/ { SPR_PRGR, 10, 5, { A_Pain }, S_PRGR_19 }, //1111 +/*S_PRGR_19*/ { SPR_PRGR, 11, 5, { A_FloatWeave }, S_PRGR_06 }, //1112 +/*S_PRGR_20*/ { SPR_PRGR, 32779, 7, { A_BodyParts }, S_PRGR_21 }, //1113 +/*S_PRGR_21*/ { SPR_PRGR, 32780, 7, { A_Scream }, S_PRGR_22 }, //1114 +/*S_PRGR_22*/ { SPR_PRGR, 32781, 7, { A_BodyParts }, S_PRGR_23 }, //1115 +/*S_PRGR_23*/ { SPR_PRGR, 32782, 7, { A_Fall }, S_PRGR_24 }, //1116 +/*S_PRGR_24*/ { SPR_PRGR, 32783, 7, { A_BodyParts }, S_PRGR_25 }, //1117 +/*S_PRGR_25*/ { SPR_PRGR, 32784, 7, { A_ProgrammerDie }, S_PRGR_26 }, //1118 +/*S_PRGR_26*/ { SPR_PRGR, 32785, 7, { NULL }, S_PRGR_27 }, //1119 +/*S_PRGR_27*/ { SPR_PRGR, 32786, 6, { NULL }, S_PRGR_28 }, //1120 +/*S_PRGR_28*/ { SPR_PRGR, 32787, 5, { NULL }, S_PRGR_29 }, //1121 +/*S_PRGR_29*/ { SPR_PRGR, 32788, 5, { NULL }, S_PRGR_30 }, //1122 +/*S_PRGR_30*/ { SPR_PRGR, 32789, 5, { NULL }, S_PRGR_31 }, //1123 +/*S_PRGR_31*/ { SPR_PRGR, 32790, 5, { NULL }, S_PRGR_32 }, //1124 +/*S_PRGR_32*/ { SPR_PRGR, 32791, 32, { NULL }, S_PRGR_33 }, //1125 +/*S_PRGR_33*/ { SPR_PRGR, 32791, -1, { A_BossDeath }, S_NULL }, //1126 +/*S_BASE_00*/ { SPR_BASE, 32768, 5, { A_DeathExplode3 }, S_BASE_01 }, //1127 +/*S_BASE_01*/ { SPR_BASE, 32769, 5, { NULL }, S_BASE_02 }, //1128 +/*S_BASE_02*/ { SPR_BASE, 32770, 5, { NULL }, S_BASE_03 }, //1129 +/*S_BASE_03*/ { SPR_BASE, 32771, 5, { NULL }, S_BASE_04 }, //1130 +/*S_BASE_04*/ { SPR_BASE, 4, 5, { NULL }, S_BASE_05 }, //1131 +/*S_BASE_05*/ { SPR_BASE, 5, 5, { NULL }, S_BASE_06 }, //1132 +/*S_BASE_06*/ { SPR_BASE, 6, 5, { NULL }, S_BASE_07 }, //1133 +/*S_BASE_07*/ { SPR_BASE, 7, -1, { NULL }, S_NULL }, //1134 +/*S_FRBL_00*/ { SPR_FRBL, 32768, 3, { NULL }, S_FRBL_01 }, //1135 +/*S_FRBL_01*/ { SPR_FRBL, 32769, 3, { NULL }, S_FRBL_02 }, //1136 +/*S_FRBL_02*/ { SPR_FRBL, 32770, 3, { A_MissileTick }, S_FRBL_00 }, //1137 +/*S_FRBL_03*/ { SPR_FRBL, 32771, 5, { A_FlameDeath }, S_FRBL_04 }, //1138 +/*S_FRBL_04*/ { SPR_FRBL, 32772, 5, { NULL }, S_FRBL_05 }, //1139 +/*S_FRBL_05*/ { SPR_FRBL, 32773, 5, { NULL }, S_FRBL_06 }, //1140 +/*S_FRBL_06*/ { SPR_FRBL, 32774, 5, { NULL }, S_FRBL_07 }, //1141 +/*S_FRBL_07*/ { SPR_FRBL, 32775, 5, { NULL }, S_FRBL_08 }, //1142 +/*S_FRBL_08*/ { SPR_FRBL, 32776, 5, { NULL }, S_NULL }, //1143 +/*S_KLAX_00*/ { SPR_KLAX, 0, 5, { A_Listen }, S_KLAX_00 }, //1144 +/*S_KLAX_01*/ { SPR_KLAX, 1, 6, { A_ClaxonBlare }, S_KLAX_02 }, //1145 +/*S_KLAX_02*/ { SPR_KLAX, 2, 60, { NULL }, S_KLAX_01 }, //1146 +/*S_TURT_00*/ { SPR_TURT, 0, 5, { A_Listen }, S_TURT_00 }, //1147 +/*S_TURT_01*/ { SPR_TURT, 0, 2, { A_Chase }, S_TURT_01 }, //1148 +/*S_TURT_02*/ { SPR_TURT, 1, 4, { A_BulletAttack }, S_TURT_03 }, //1149 +/*S_TURT_03*/ { SPR_TURT, 3, 3, { A_CheckTargetVisible }, S_TURT_04 }, //1150 +/*S_TURT_04*/ { SPR_TURT, 0, 4, { A_CheckTargetVisible }, S_TURT_02 }, //1151 +/*S_BALL_00*/ { SPR_BALL, 32768, 6, { NULL }, S_BALL_01 }, //1152 +/*S_BALL_01*/ { SPR_BALL, 32769, 6, { NULL }, S_BALL_02 }, //1153 +/*S_BALL_02*/ { SPR_BALL, 32770, 6, { NULL }, S_BALL_03 }, //1154 +/*S_BALL_03*/ { SPR_BALL, 32771, 6, { NULL }, S_BALL_04 }, //1155 +/*S_BALL_04*/ { SPR_BALL, 32772, 6, { NULL }, S_TURT_05 }, //1156 +/*S_TURT_05*/ { SPR_TURT, 2, -1, { NULL }, S_NULL }, //1157 +/*S_PSTN_00*/ { SPR_PSTN, 0, 8, { NULL }, S_PSTN_01 }, //1158 +/*S_PSTN_01*/ { SPR_PSTN, 1, 8, { NULL }, S_PSTN_00 }, //1159 +/*S_PSTN_02*/ { SPR_PSTN, 32768, 4, { A_Scream }, S_PSTN_03 }, //1160 +/*S_PSTN_03*/ { SPR_PSTN, 32769, 4, { A_Fall }, S_PSTN_04 }, //1161 +/*S_PSTN_04*/ { SPR_PSTN, 32770, 4, { A_QuestMsg }, S_PSTN_05 }, //1162 +/*S_PSTN_05*/ { SPR_PSTN, 32771, 4, { A_SpawnSparkPuff }, S_PSTN_06 }, //1163 +/*S_PSTN_06*/ { SPR_PSTN, 32772, 4, { A_BodyParts }, S_PSTN_07 }, //1164 +/*S_PSTN_07*/ { SPR_PSTN, 32773, 4, { NULL }, S_PSTN_08 }, //1165 +/*S_PSTN_08*/ { SPR_PSTN, 32774, 4, { A_SpawnSparkPuff }, S_PSTN_09 }, //1166 +/*S_PSTN_09*/ { SPR_PSTN, 7, 4, { NULL }, S_PSTN_10 }, //1167 +/*S_PSTN_10*/ { SPR_PSTN, 8, -1, { NULL }, S_NULL }, //1168 +/*S_SECR_00*/ { SPR_SECR, 32768, 4, { NULL }, S_SECR_01 }, //1169 +/*S_SECR_01*/ { SPR_SECR, 32769, 4, { NULL }, S_SECR_02 }, //1170 +/*S_SECR_02*/ { SPR_SECR, 32770, 4, { NULL }, S_SECR_03 }, //1171 +/*S_SECR_03*/ { SPR_SECR, 32771, 4, { NULL }, S_SECR_00 }, //1172 +/*S_SECR_04*/ { SPR_SECR, 32772, 5, { A_SpawnSparkPuff }, S_SECR_05 }, //1173 +/*S_SECR_05*/ { SPR_SECR, 32773, 5, { A_Fall }, S_SECR_06 }, //1174 +/*S_SECR_06*/ { SPR_SECR, 32774, 5, { A_QuestMsg }, S_SECR_07 }, //1175 +/*S_SECR_07*/ { SPR_SECR, 32775, 5, { A_BodyParts }, S_SECR_08 }, //1176 +/*S_SECR_08*/ { SPR_SECR, 32776, 5, { A_SpawnSparkPuff }, S_SECR_09 }, //1177 +/*S_SECR_09*/ { SPR_SECR, 9, 5, { NULL }, S_SECR_10 }, //1178 +/*S_SECR_10*/ { SPR_SECR, 10, 5, { A_SpawnSparkPuff }, S_SECR_11 }, //1179 +/*S_SECR_11*/ { SPR_SECR, 11, 5, { NULL }, S_SECR_12 }, //1180 +/*S_SECR_12*/ { SPR_SECR, 12, 5, { A_SpawnSparkPuff }, S_SECR_13 }, //1181 +/*S_SECR_13*/ { SPR_SECR, 13, 5, { NULL }, S_SECR_14 }, //1182 +/*S_SECR_14*/ { SPR_SECR, 14, 5, { A_SpawnSparkPuff }, S_SECR_15 }, //1183 +/*S_SECR_15*/ { SPR_SECR, 15, -1, { NULL }, S_NULL }, //1184 +/*S_XPRK_01*/ { SPR_XPRK, 0, -1, { NULL }, S_NULL }, //1185 +/*S_XPRK_02*/ { SPR_XPRK, 0, 1, { A_ClearForceField }, S_BNG3_00 }, //1186 +/*S_TARG_00*/ { SPR_TARG, 0, -1, { NULL }, S_NULL }, //1187 +/*S_RING_00*/ { SPR_RING, 0, -1, { NULL }, S_NULL }, //1188 +/*S_EARS_00*/ { SPR_EARS, 0, -1, { NULL }, S_NULL }, //1189 +/*S_COMM_00*/ { SPR_COMM, 0, -1, { NULL }, S_NULL }, //1190 +/*S_BOOM_00*/ { SPR_BOOM, 32768, 1, { A_CrystalRadiusAtk }, S_BOOM_01 }, //1191 +/*S_BOOM_01*/ { SPR_BOOM, 32769, 3, { A_QuestMsg }, S_BOOM_02 }, //1192 +/*S_BOOM_02*/ { SPR_BOOM, 32770, 2, { A_CrystalExplode }, S_BOOM_03 }, //1193 +/*S_BOOM_03*/ { SPR_BOOM, 32771, 3, { A_SpawnSparkPuff }, S_BOOM_04 }, //1194 +/*S_BOOM_04*/ { SPR_BOOM, 32772, 3, { NULL }, S_BOOM_05 }, //1195 +/*S_BOOM_05*/ { SPR_BOOM, 32773, 3, { NULL }, S_BOOM_06 }, //1196 +/*S_BOOM_06*/ { SPR_BOOM, 32774, 3, { A_SpawnSparkPuff }, S_BOOM_07 }, //1197 +/*S_BOOM_07*/ { SPR_BOOM, 32775, 1, { A_CrystalRadiusAtk }, S_BOOM_08 }, //1198 +/*S_BOOM_08*/ { SPR_BOOM, 32776, 3, { NULL }, S_BOOM_09 }, //1199 +/*S_BOOM_09*/ { SPR_BOOM, 32777, 3, { A_SpawnSparkPuff }, S_BOOM_10 }, //1200 +/*S_BOOM_10*/ { SPR_BOOM, 32778, 3, { A_SpawnSparkPuff }, S_BOOM_11 }, //1201 +/*S_BOOM_11*/ { SPR_BOOM, 32779, 3, { A_SpawnSparkPuff }, S_BOOM_12 }, //1202 +/*S_BOOM_12*/ { SPR_BOOM, 32780, 3, { NULL }, S_BOOM_13 }, //1203 +/*S_BOOM_13*/ { SPR_BOOM, 32781, 3, { NULL }, S_BOOM_14 }, //1204 +/*S_BOOM_14*/ { SPR_BOOM, 32782, 3, { A_SpawnSparkPuff }, S_BOOM_15 }, //1205 +/*S_BOOM_15*/ { SPR_BOOM, 32783, 3, { NULL }, S_BOOM_16 }, //1206 +/*S_BOOM_16*/ { SPR_BOOM, 32784, 3, { NULL }, S_BOOM_17 }, //1207 +/*S_BOOM_17*/ { SPR_BOOM, 32785, 3, { NULL }, S_BOOM_18 }, //1208 +/*S_BOOM_18*/ { SPR_BOOM, 32786, 3, { NULL }, S_BOOM_19 }, //1209 +/*S_BOOM_19*/ { SPR_BOOM, 32787, 3, { NULL }, S_BOOM_20 }, //1210 +/*S_BOOM_20*/ { SPR_BOOM, 32788, 3, { A_ExtraLightOff }, S_BOOM_21 }, //1211 +/*S_BOOM_21*/ { SPR_BOOM, 32789, 3, { NULL }, S_BOOM_22 }, //1212 +/*S_BOOM_22*/ { SPR_BOOM, 32790, 3, { NULL }, S_BOOM_23 }, //1213 +/*S_BOOM_23*/ { SPR_BOOM, 32791, 3, { NULL }, S_BOOM_24 }, //1214 +/*S_BOOM_24*/ { SPR_BOOM, 32792, 3, { NULL }, S_NULL }, //1215 +/*S_RATT_00*/ { SPR_RATT, 0, 10, { A_Look }, S_RATT_00 }, //1216 +/*S_RATT_01*/ { SPR_RATT, 0, 4, { A_Chase }, S_RATT_02 }, //1217 +/*S_RATT_02*/ { SPR_RATT, 0, 4, { A_Chase }, S_RATT_03 }, //1218 +/*S_RATT_03*/ { SPR_RATT, 1, 4, { A_Chase }, S_RATT_04 }, //1219 +/*S_RATT_04*/ { SPR_RATT, 1, 4, { A_Chase }, S_RATT_01 }, //1220 +/*S_RATT_05*/ { SPR_RATT, 0, 8, { A_RandomWalk }, S_RATT_06 }, //1221 +/*S_RATT_06*/ { SPR_RATT, 1, 4, { A_RandomWalk }, S_RATT_01 }, //1222 +/*S_HOGN_00*/ { SPR_HOGN, 0, 2, { A_ZombieInSpecialSector }, S_HOGN_00 }, //1223 +/*S_HOGN_01*/ { SPR_HOGN, 1, 1, { A_ZombieInSpecialSector }, S_HOGN_02 }, //1224 +/*S_HOGN_02*/ { SPR_HOGN, 2, 1, { A_Pain }, S_HOGN_00 }, //1225 +/*S_DEAD_00*/ { SPR_DEAD, 0, -1, { NULL }, S_NULL }, //1226 +/*S_SBAN_00*/ { SPR_SBAN, 0, -1, { NULL }, S_NULL }, //1227 +/*S_BOTR_00*/ { SPR_BOTR, 0, -1, { NULL }, S_NULL }, //1228 +/*S_HATR_00*/ { SPR_HATR, 0, -1, { NULL }, S_NULL }, //1229 +/*S_TOPR_00*/ { SPR_TOPR, 0, -1, { NULL }, S_NULL }, //1230 +/*S_COUP_00*/ { SPR_COUP, 0, 5, { NULL }, S_COUP_01 }, //1231 +/*S_COUP_01*/ { SPR_COUP, 1, 5, { NULL }, S_COUP_00 }, //1232 +/*S_COUP_02*/ { SPR_COUP, 2, -1, { NULL }, S_COUP_01 }, //1233 +/*S_BUBB_00*/ { SPR_BUBB, 0, 4, { A_ActiveSound }, S_BUBB_00 }, //1234 +/*S_BUBF_00*/ { SPR_BUBF, 0, 4, { A_ActiveSound }, S_BUBF_00 }, //1235 +/*S_BUBC_00*/ { SPR_BUBC, 0, 4, { A_ActiveSound }, S_BUBC_00 }, //1236 +/*S_ASPR_00*/ { SPR_ASPR, 0, 4, { A_ActiveSound }, S_ASPR_00 }, //1237 +/*S_SPDL_00*/ { SPR_SPDL, 0, 5, { A_ActiveSound }, S_SPDL_01 }, //1238 +/*S_SPDL_01*/ { SPR_SPDL, 1, 5, { A_ActiveSound }, S_SPDL_02 }, //1239 +/*S_SPDL_02*/ { SPR_SPDL, 2, 5, { A_ActiveSound }, S_SPDL_00 }, //1240 +/*S_TOKN_00*/ { SPR_TOKN, 0, -1, { NULL }, S_NULL }, //1241 +/*S_OTOK_00*/ { SPR_OTOK, 0, -1, { NULL }, S_NULL }, //1242 +/*S_HELT_00*/ { SPR_HELT, 0, -1, { NULL }, S_NULL }, //1243 +/*S_GUNT_00*/ { SPR_GUNT, 0, -1, { NULL }, S_NULL }, //1244 +/*S_FULL_00*/ { SPR_FULL, 0, 35, { NULL }, S_FULL_01 }, //1245 +/*S_FULL_01*/ { SPR_FULL, 1, 35, { NULL }, S_FULL_00 }, //1246 +/*S_MEAT_00*/ { SPR_MEAT, 0, 700, { NULL }, S_NULL }, //1247 +/*S_MEAT_01*/ { SPR_MEAT, 1, 700, { NULL }, S_NULL }, //1248 +/*S_MEAT_02*/ { SPR_MEAT, 2, 700, { NULL }, S_NULL }, //1249 +/*S_MEAT_03*/ { SPR_MEAT, 3, 700, { NULL }, S_NULL }, //1250 +/*S_MEAT_04*/ { SPR_MEAT, 4, 700, { NULL }, S_NULL }, //1251 +/*S_MEAT_05*/ { SPR_MEAT, 5, 700, { NULL }, S_NULL }, //1252 +/*S_MEAT_06*/ { SPR_MEAT, 6, 700, { NULL }, S_NULL }, //1253 +/*S_MEAT_07*/ { SPR_MEAT, 7, 700, { NULL }, S_NULL }, //1254 +/*S_MEAT_08*/ { SPR_MEAT, 8, 700, { NULL }, S_NULL }, //1255 +/*S_MEAT_09*/ { SPR_MEAT, 9, 700, { NULL }, S_NULL }, //1256 +/*S_MEAT_10*/ { SPR_MEAT, 10, 700, { NULL }, S_NULL }, //1257 +/*S_MEAT_11*/ { SPR_MEAT, 11, 700, { NULL }, S_NULL }, //1258 +/*S_MEAT_12*/ { SPR_MEAT, 12, 700, { NULL }, S_NULL }, //1259 +/*S_MEAT_13*/ { SPR_MEAT, 13, 700, { NULL }, S_NULL }, //1260 +/*S_MEAT_14*/ { SPR_MEAT, 14, 700, { NULL }, S_NULL }, //1261 +/*S_MEAT_15*/ { SPR_MEAT, 15, 700, { NULL }, S_NULL }, //1262 +/*S_MEAT_16*/ { SPR_MEAT, 16, 700, { NULL }, S_NULL }, //1263 +/*S_MEAT_17*/ { SPR_MEAT, 17, 700, { NULL }, S_NULL }, //1264 +/*S_MEAT_18*/ { SPR_MEAT, 18, 700, { NULL }, S_NULL }, //1265 +/*S_MEAT_19*/ { SPR_MEAT, 19, 700, { NULL }, S_NULL }, //1266 +/*S_JUNK_00*/ { SPR_JUNK, 0, 700, { NULL }, S_NULL }, //1267 +/*S_JUNK_01*/ { SPR_JUNK, 1, 700, { NULL }, S_NULL }, //1268 +/*S_JUNK_02*/ { SPR_JUNK, 2, 700, { NULL }, S_NULL }, //1269 +/*S_JUNK_03*/ { SPR_JUNK, 3, 700, { NULL }, S_NULL }, //1270 +/*S_JUNK_04*/ { SPR_JUNK, 4, 700, { NULL }, S_NULL }, //1271 +/*S_JUNK_05*/ { SPR_JUNK, 5, 700, { NULL }, S_NULL }, //1272 +/*S_JUNK_06*/ { SPR_JUNK, 6, 700, { NULL }, S_NULL }, //1273 +/*S_JUNK_07*/ { SPR_JUNK, 7, 700, { NULL }, S_NULL }, //1274 +/*S_JUNK_08*/ { SPR_JUNK, 8, 700, { NULL }, S_NULL }, //1275 +/*S_JUNK_09*/ { SPR_JUNK, 9, 700, { NULL }, S_NULL }, //1276 +/*S_JUNK_10*/ { SPR_JUNK, 10, 700, { NULL }, S_NULL }, //1277 +/*S_JUNK_11*/ { SPR_JUNK, 11, 700, { NULL }, S_NULL }, //1278 +/*S_JUNK_12*/ { SPR_JUNK, 12, 700, { NULL }, S_NULL }, //1279 +/*S_JUNK_13*/ { SPR_JUNK, 13, 700, { NULL }, S_NULL }, //1280 +/*S_JUNK_14*/ { SPR_JUNK, 14, 700, { NULL }, S_NULL }, //1281 +/*S_JUNK_15*/ { SPR_JUNK, 15, 700, { NULL }, S_NULL }, //1282 +/*S_JUNK_16*/ { SPR_JUNK, 16, 700, { NULL }, S_NULL }, //1283 +/*S_JUNK_17*/ { SPR_JUNK, 17, 700, { NULL }, S_NULL }, //1284 +/*S_JUNK_18*/ { SPR_JUNK, 18, 700, { NULL }, S_NULL }, //1285 +/*S_JUNK_19*/ { SPR_JUNK, 19, 700, { NULL }, S_NULL }, //1286 +/*S_FFOT_00*/ { SPR_FFOT, 0, 9, { NULL }, S_FFOT_01 }, //1287 +/*S_FFOT_01*/ { SPR_FFOT, 1, 9, { NULL }, S_FFOT_02 }, //1288 +/*S_FFOT_02*/ { SPR_FFOT, 2, 9, { NULL }, S_FFOT_03 }, //1289 +/*S_FFOT_03*/ { SPR_FFOT, 3, 9, { NULL }, S_NULL }, //1290 +/*S_DIE1_00*/ { SPR_DIE1, 0, -1, { NULL }, S_NULL }, //1291 +/*S_BEAC_00*/ { SPR_BEAC, 0, -1, { NULL }, S_NULL }, //1292 +/*S_BEAC_01*/ { SPR_BEAC, 0, 30, { NULL }, S_BEAC_02 }, //1293 +/*S_BEAC_02*/ { SPR_BEAC, 0, 160, { A_TeleportBeacon }, S_BEAC_01 }, //1294 +/*S_ARM1_00*/ { SPR_ARM1, 0, -1, { NULL }, S_NULL }, //1295 +/*S_ARM2_00*/ { SPR_ARM2, 0, -1, { NULL }, S_NULL }, //1296 +/*S_BARW_00*/ { SPR_BARW, 0, -1, { NULL }, S_NULL }, //1297 +/*S_BARW_01*/ { SPR_BARW, 1, 2, { A_Scream }, S_BARW_02 }, //1298 +/*S_BARW_02*/ { SPR_BARW, 2, 2, { NULL }, S_BARW_03 }, //1299 +/*S_BARW_03*/ { SPR_BARW, 3, 2, { A_Fall }, S_BARW_04 }, //1300 +/*S_BARW_04*/ { SPR_BARW, 4, 2, { NULL }, S_BARW_05 }, //1301 +/*S_BARW_05*/ { SPR_BARW, 5, 2, { NULL }, S_BARW_06 }, //1302 +/*S_BARW_06*/ { SPR_BARW, 6, 2, { NULL }, S_BARW_07 }, //1303 +/*S_BARW_07*/ { SPR_BARW, 7, -1, { NULL }, S_NULL }, //1304 +/*S_BART_00*/ { SPR_BART, 0, -1, { NULL }, S_NULL }, //1305 +/*S_BART_01*/ { SPR_BART, 32769, 2, { A_Scream }, S_BART_02 }, //1306 +/*S_BART_02*/ { SPR_BART, 32770, 2, { NULL }, S_BART_03 }, //1307 +/*S_BART_03*/ { SPR_BART, 32771, 2, { NULL }, S_BART_04 }, //1308 +/*S_BART_04*/ { SPR_BART, 32772, 2, { A_Fall }, S_BART_05 }, //1309 +/*S_BART_05*/ { SPR_BART, 32773, 2, { A_DeathExplode2 }, S_BART_06 }, //1310 +/*S_BART_06*/ { SPR_BART, 32774, 2, { NULL }, S_BART_07 }, //1311 +/*S_BART_07*/ { SPR_BART, 32775, 2, { NULL }, S_BART_08 }, //1312 +/*S_BART_08*/ { SPR_BART, 32776, 2, { NULL }, S_BART_09 }, //1313 +/*S_BART_09*/ { SPR_BART, 32777, 3, { NULL }, S_BART_10 }, //1314 +/*S_BART_10*/ { SPR_BART, 32778, 3, { NULL }, S_BART_11 }, //1315 +/*S_BART_11*/ { SPR_BART, 11, -1, { NULL }, S_NULL }, //1316 +/*S_LAMP_00*/ { SPR_LAMP, 0, -1, { NULL }, S_NULL }, //1317 +/*S_LANT_00*/ { SPR_LANT, 0, -1, { NULL }, S_NULL }, //1318 +/*S_BARL_00*/ { SPR_BARL, 32768, 4, { NULL }, S_BARL_01 }, //1319 +/*S_BARL_01*/ { SPR_BARL, 32769, 4, { NULL }, S_BARL_02 }, //1320 +/*S_BARL_02*/ { SPR_BARL, 32770, 4, { NULL }, S_BARL_03 }, //1321 +/*S_BARL_03*/ { SPR_BARL, 32771, 4, { NULL }, S_BARL_00 }, //1322 +/*S_BOWL_00*/ { SPR_BOWL, 32768, 4, { A_ActiveSound }, S_BOWL_01 }, //1323 +/*S_BOWL_01*/ { SPR_BOWL, 32769, 4, { NULL }, S_BOWL_02 }, //1324 +/*S_BOWL_02*/ { SPR_BOWL, 32770, 4, { NULL }, S_BOWL_03 }, //1325 +/*S_BOWL_03*/ { SPR_BOWL, 32771, 4, { NULL }, S_BOWL_00 }, //1326 +/*S_BRAZ_00*/ { SPR_BRAZ, 32768, 4, { A_ActiveSound }, S_BRAZ_01 }, //1327 +/*S_BRAZ_01*/ { SPR_BRAZ, 32769, 4, { NULL }, S_BRAZ_02 }, //1328 +/*S_BRAZ_02*/ { SPR_BRAZ, 32770, 4, { NULL }, S_BRAZ_03 }, //1329 +/*S_BRAZ_03*/ { SPR_BRAZ, 32771, 4, { NULL }, S_BRAZ_00 }, //1330 +/*S_TRCH_00*/ { SPR_TRCH, 32768, 4, { A_ActiveSound }, S_TRCH_01 }, //1331 +/*S_TRCH_01*/ { SPR_TRCH, 32769, 4, { NULL }, S_TRCH_02 }, //1332 +/*S_TRCH_02*/ { SPR_TRCH, 32770, 4, { NULL }, S_TRCH_03 }, //1333 +/*S_TRCH_03*/ { SPR_TRCH, 32771, 4, { NULL }, S_TRCH_00 }, //1334 +/*S_LTRH_00*/ { SPR_LTRH, 32768, 4, { NULL }, S_LTRH_01 }, //1335 +/*S_LTRH_01*/ { SPR_LTRH, 32769, 4, { NULL }, S_LTRH_02 }, //1336 +/*S_LTRH_02*/ { SPR_LTRH, 32770, 4, { NULL }, S_LTRH_03 }, //1337 +/*S_LTRH_03*/ { SPR_LTRH, 32771, 4, { NULL }, S_LTRH_00 }, //1338 +/*S_LMPC_00*/ { SPR_LMPC, 32768, 4, { A_ActiveSound }, S_LMPC_01 }, //1339 +/*S_LMPC_01*/ { SPR_LMPC, 32769, 4, { NULL }, S_LMPC_02 }, //1340 +/*S_LMPC_02*/ { SPR_LMPC, 32770, 4, { NULL }, S_LMPC_03 }, //1341 +/*S_LMPC_03*/ { SPR_LMPC, 32771, 4, { NULL }, S_LMPC_00 }, //1342 +/*S_LOGS_00*/ { SPR_LOGS, 32768, 4, { A_ActiveSound }, S_LOGS_01 }, //1343 +/*S_LOGS_01*/ { SPR_LOGS, 32769, 4, { NULL }, S_LOGS_02 }, //1344 +/*S_LOGS_02*/ { SPR_LOGS, 32770, 4, { NULL }, S_LOGS_03 }, //1345 +/*S_LOGS_03*/ { SPR_LOGS, 32771, 4, { NULL }, S_LOGS_00 }, //1346 +/*S_TRHO_00*/ { SPR_TRHO, 0, -1, { NULL }, S_NULL }, //1347 +/*S_WATR_00*/ { SPR_WATR, 0, -1, { NULL }, S_NULL }, //1348 +/*S_MUGG_00*/ { SPR_MUGG, 0, -1, { NULL }, S_NULL }, //1349 +/*S_FUSL_00*/ { SPR_FUSL, 0, -1, { NULL }, S_NULL }, //1350 +/*S_CRD1_00*/ { SPR_CRD1, 0, -1, { NULL }, S_NULL }, //1351 +/*S_CRD2_00*/ { SPR_CRD2, 0, -1, { NULL }, S_NULL }, //1352 +/*S_TPAS_00*/ { SPR_TPAS, 0, -1, { NULL }, S_NULL }, //1353 +/*S_KY1G_00*/ { SPR_KY1G, 0, -1, { NULL }, S_NULL }, //1354 +/*S_KY2S_00*/ { SPR_KY2S, 0, -1, { NULL }, S_NULL }, //1355 +/*S_KY3B_00*/ { SPR_KY3B, 0, -1, { NULL }, S_NULL }, //1356 +/*S_HAND_00*/ { SPR_HAND, 0, -1, { NULL }, S_NULL }, //1357 +/*S_CRYS_00*/ { SPR_CRYS, 0, 16, { A_ActiveSound }, S_CRYS_01 }, //1358 +/*S_CRYS_01*/ { SPR_CRYS, 1, 5, { A_ActiveSound }, S_CRYS_02 }, //1359 +/*S_CRYS_02*/ { SPR_CRYS, 2, 4, { A_ActiveSound }, S_CRYS_03 }, //1360 +/*S_CRYS_03*/ { SPR_CRYS, 3, 4, { A_ActiveSound }, S_CRYS_04 }, //1361 +/*S_CRYS_04*/ { SPR_CRYS, 4, 4, { A_ActiveSound }, S_CRYS_05 }, //1362 +/*S_CRYS_05*/ { SPR_CRYS, 5, 4, { A_ActiveSound }, S_CRYS_00 }, //1363 +/*S_PRIS_00*/ { SPR_PRIS, 0, -1, { NULL }, S_NULL }, //1364 +/*S_PWR1_00*/ { SPR_PWR1, 0, -1, { NULL }, S_NULL }, //1365 +/*S_PWR2_00*/ { SPR_PWR2, 0, -1, { NULL }, S_NULL }, //1366 +/*S_PWR3_00*/ { SPR_PWR3, 0, -1, { NULL }, S_NULL }, //1367 +/*S_ORAC_00*/ { SPR_ORAC, 0, -1, { NULL }, S_NULL }, //1368 +/*S_GYID_00*/ { SPR_GYID, 0, -1, { NULL }, S_NULL }, //1369 +/*S_FUBR_00*/ { SPR_FUBR, 0, -1, { NULL }, S_NULL }, //1370 +/*S_WARE_00*/ { SPR_WARE, 0, -1, { NULL }, S_NULL }, //1371 +/*S_RCRY_00*/ { SPR_RCRY, 32768, -1, { NULL }, S_NULL }, //1372 +/*S_BCRY_00*/ { SPR_BCRY, 32768, -1, { NULL }, S_NULL }, //1373 +/*S_CHAP_00*/ { SPR_CHAP, 0, -1, { NULL }, S_NULL }, //1374 +/*S_TUNL_00*/ { SPR_TUNL, 0, -1, { NULL }, S_NULL }, //1375 +/*S_BLTK_00*/ { SPR_BLTK, 0, -1, { NULL }, S_NULL }, //1376 +/*S_SECK_00*/ { SPR_SECK, 0, -1, { NULL }, S_NULL }, //1377 +/*S_MINE_00*/ { SPR_MINE, 0, -1, { NULL }, S_NULL }, //1378 +/*S_REBL_00*/ { SPR_REBL, 0, -1, { NULL }, S_NULL }, //1379 +/*S_PROC_00*/ { SPR_PROC, 0, -1, { NULL }, S_NULL }, //1380 +/*S_ANKH_00*/ { SPR_ANKH, 0, -1, { NULL }, S_NULL }, //1381 +/*S_GOID_00*/ { SPR_GOID, 0, -1, { NULL }, S_NULL }, //1382 +/*S_STMP_00*/ { SPR_STMP, 0, -1, { NULL }, S_NULL }, //1383 +/*S_MDKT_00*/ { SPR_MDKT, 0, -1, { NULL }, S_NULL }, //1384 +/*S_COIN_00*/ { SPR_COIN, 0, -1, { NULL }, S_NULL }, //1385 +/*S_CRED_00*/ { SPR_CRED, 0, -1, { NULL }, S_NULL }, //1386 +/*S_SACK_00*/ { SPR_SACK, 0, -1, { NULL }, S_NULL }, //1387 +/*S_CHST_00*/ { SPR_CHST, 0, -1, { NULL }, S_NULL }, //1388 +/*S_SHD1_00*/ { SPR_SHD1, 0, 17, { A_ShadowOff }, S_SHD1_01 }, //1389 +/*S_SHD1_01*/ { SPR_SHD1, 0, 17, { A_ModifyVisibility }, S_SHD1_02 }, //1390 +/*S_SHD1_02*/ { SPR_SHD1, 0, 17, { A_ShadowOn }, S_SHD1_03 }, //1391 +/*S_SHD1_03*/ { SPR_SHD1, 0, 17, { A_ModifyVisibility }, S_SHD1_00 }, //1392 +/*S_MASK_00*/ { SPR_MASK, 0, -1, { NULL }, S_NULL }, //1393 +/*S_UNIF_00*/ { SPR_UNIF, 0, -1, { NULL }, S_NULL }, //1394 +/*S_OFIC_00*/ { SPR_OFIC, 0, -1, { NULL }, S_NULL }, //1395 +/*S_PMAP_00*/ { SPR_PMAP, 32768, 6, { NULL }, S_PMAP_01 }, //1396 +/*S_PMAP_01*/ { SPR_PMAP, 32769, 6, { NULL }, S_PMAP_00 }, //1397 +/*S_PMUP_00*/ { SPR_PMUP, 32768, 6, { NULL }, S_PMUP_01 }, //1398 +/*S_PMUP_01*/ { SPR_PMUP, 32769, 6, { NULL }, S_PMUP_00 }, //1399 +/*S_BLIT_00*/ { SPR_BLIT, 0, -1, { NULL }, S_NULL }, //1400 +/*S_BBOX_00*/ { SPR_BBOX, 0, -1, { NULL }, S_NULL }, //1401 +/*S_MSSL_00*/ { SPR_MSSL, 0, -1, { NULL }, S_NULL }, //1402 +/*S_ROKT_00*/ { SPR_ROKT, 0, -1, { NULL }, S_NULL }, //1403 +/*S_BRY1_00*/ { SPR_BRY1, 0, 6, { NULL }, S_BRY1_01 }, //1404 +/*S_BRY1_01*/ { SPR_BRY1, 1, 6, { NULL }, S_BRY1_00 }, //1405 +/*S_CPAC_00*/ { SPR_CPAC, 0, 6, { NULL }, S_CPAC_01 }, //1406 +/*S_CPAC_01*/ { SPR_CPAC, 1, 6, { NULL }, S_CPAC_00 }, //1407 +/*S_PQRL_00*/ { SPR_PQRL, 0, -1, { NULL }, S_NULL }, //1408 +/*S_XQRL_00*/ { SPR_XQRL, 0, -1, { NULL }, S_NULL }, //1409 +/*S_GRN1_00*/ { SPR_GRN1, 0, -1, { NULL }, S_NULL }, //1410 +/*S_GRN2_00*/ { SPR_GRN2, 0, -1, { NULL }, S_NULL }, //1411 +/*S_BKPK_00*/ { SPR_BKPK, 0, -1, { NULL }, S_NULL }, //1412 +/*S_RELC_00*/ { SPR_RELC, 32768, -1, { NULL }, S_NULL }, //1413 +/*S_RIFL_00*/ { SPR_RIFL, 0, -1, { NULL }, S_NULL }, //1414 +/*S_RIFL_01*/ { SPR_RIFL, 1, -1, { NULL }, S_NULL }, //1415 +/*S_FLAM_00*/ { SPR_FLAM, 0, -1, { NULL }, S_NULL }, //1416 +/*S_BFLM_00*/ { SPR_BFLM, 0, -1, { NULL }, S_NULL }, //1417 +/*S_MMSL_00*/ { SPR_MMSL, 0, -1, { NULL }, S_NULL }, //1418 +/*S_TRPD_00*/ { SPR_TRPD, 0, -1, { NULL }, S_NULL }, //1419 +/*S_GRND_00*/ { SPR_GRND, 0, -1, { NULL }, S_NULL }, //1420 +/*S_CBOW_00*/ { SPR_CBOW, 0, -1, { NULL }, S_NULL }, //1421 +/*S_SIGL_00*/ { SPR_SIGL, 0, -1, { NULL }, S_NULL }, //1422 +/*S_SIGL_01*/ { SPR_SIGL, 1, -1, { NULL }, S_NULL }, //1423 +/*S_SIGL_02*/ { SPR_SIGL, 2, -1, { NULL }, S_NULL }, //1424 +/*S_SIGL_03*/ { SPR_SIGL, 3, -1, { NULL }, S_NULL }, //1425 +/*S_SIGL_04*/ { SPR_SIGL, 4, -1, { NULL }, S_NULL }, //1426 +/*S_LITE_00*/ { SPR_LITE, 32768, -1, { NULL }, S_NULL }, //1427 +/*S_CNDL_00*/ { SPR_CNDL, 32768, -1, { NULL }, S_NULL }, //1428 +/*S_CLBR_00*/ { SPR_CLBR, 32768, -1, { NULL }, S_NULL }, //1429 +/*S_LITS_00*/ { SPR_LITS, 32768, -1, { NULL }, S_NULL }, //1430 +/*S_LITB_00*/ { SPR_LITB, 32768, -1, { NULL }, S_NULL }, //1431 +/*S_LITG_00*/ { SPR_LITG, 32768, -1, { NULL }, S_NULL }, //1432 +/*S_ROK1_00*/ { SPR_ROK1, 0, -1, { NULL }, S_NULL }, //1433 +/*S_ROK2_00*/ { SPR_ROK2, 0, -1, { NULL }, S_NULL }, //1434 +/*S_ROK3_00*/ { SPR_ROK3, 0, -1, { NULL }, S_NULL }, //1435 +/*S_ROK4_00*/ { SPR_ROK4, 0, -1, { NULL }, S_NULL }, //1436 +/*S_LOGG_00*/ { SPR_LOGG, 0, 5, { A_ActiveSound }, S_LOGG_01 }, //1437 +/*S_LOGG_01*/ { SPR_LOGG, 1, 5, { A_ActiveSound }, S_LOGG_02 }, //1438 +/*S_LOGG_02*/ { SPR_LOGG, 2, 5, { A_ActiveSound }, S_LOGG_03 }, //1439 +/*S_LOGG_03*/ { SPR_LOGG, 3, 5, { A_ActiveSound }, S_LOGG_00 }, //1440 +/*S_RUB1_00*/ { SPR_RUB1, 0, -1, { NULL }, S_NULL }, //1441 +/*S_RUB2_00*/ { SPR_RUB2, 0, -1, { NULL }, S_NULL }, //1442 +/*S_RUB3_00*/ { SPR_RUB3, 0, -1, { NULL }, S_NULL }, //1443 +/*S_RUB4_00*/ { SPR_RUB4, 0, -1, { NULL }, S_NULL }, //1444 +/*S_RUB5_00*/ { SPR_RUB5, 0, -1, { NULL }, S_NULL }, //1445 +/*S_RUB6_00*/ { SPR_RUB6, 0, -1, { NULL }, S_NULL }, //1446 +/*S_RUB7_00*/ { SPR_RUB7, 0, -1, { NULL }, S_NULL }, //1447 +/*S_RUB8_00*/ { SPR_RUB8, 0, -1, { NULL }, S_NULL }, //1448 +/*S_CHAN_00*/ { SPR_CHAN, 0, -1, { NULL }, S_NULL }, //1449 +/*S_STAT_00*/ { SPR_STAT, 0, -1, { NULL }, S_NULL }, //1450 +/*S_DSTA_00*/ { SPR_DSTA, 0, -1, { NULL }, S_NULL }, //1451 +/*S_CRAB_00*/ { SPR_CRAB, 0, -1, { NULL }, S_NULL }, //1452 +/*S_CAGE_00*/ { SPR_CAGE, 0, -1, { NULL }, S_NULL }, //1453 +/*S_TREE_00*/ { SPR_TREE, 0, -1, { NULL }, S_NULL }, //1454 +/*S_TREE_01*/ { SPR_TREE, 1, -1, { NULL }, S_NULL }, //1455 +/*S_TREE_02*/ { SPR_TREE, 2, -1, { NULL }, S_NULL }, //1456 +/*S_TRE1_00*/ { SPR_TRE1, 0, -1, { NULL }, S_NULL }, //1457 +/*S_BUSH_00*/ { SPR_BUSH, 0, -1, { NULL }, S_NULL }, //1458 +/*S_SHRB_00*/ { SPR_SHRB, 0, -1, { NULL }, S_NULL }, //1459 +/*S_STAK_00*/ { SPR_STAK, 0, -1, { NULL }, S_NULL }, //1460 +/*S_BAR1_00*/ { SPR_BAR1, 0, -1, { NULL }, S_NULL }, //1461 +/*S_VASE_00*/ { SPR_VASE, 0, -1, { NULL }, S_NULL }, //1462 +/*S_VASE_01*/ { SPR_VASE, 1, -1, { NULL }, S_NULL }, //1463 +/*S_STOL_00*/ { SPR_STOL, 0, -1, { NULL }, S_NULL }, //1464 +/*S_POT1_00*/ { SPR_POT1, 0, -1, { NULL }, S_NULL }, //1465 +/*S_TUB1_00*/ { SPR_TUB1, 0, -1, { NULL }, S_NULL }, //1466 +/*S_ANVL_00*/ { SPR_ANVL, 0, -1, { NULL }, S_NULL }, //1467 +/*S_TLMP_00*/ { SPR_TLMP, 0, -1, { NULL }, S_NULL }, //1468 +/*S_TLMP_01*/ { SPR_TLMP, 1, -1, { NULL }, S_NULL }, //1469 +/*S_TRAY_00*/ { SPR_TRAY, 0, -1, { NULL }, S_NULL }, //1470 +/*S_APOW_00*/ { SPR_APOW, 0, 4, { A_ActiveSound }, S_APOW_00 }, //1471 +/*S_AFED_00*/ { SPR_AFED, 0, -1, { NULL }, S_NULL }, //1472 +/*S_DRIP_00*/ { SPR_DRIP, 0, 6, { A_ActiveSound }, S_DRIP_01 }, //1473 +/*S_DRIP_01*/ { SPR_DRIP, 1, 4, { NULL }, S_DRIP_02 }, //1474 +/*S_DRIP_02*/ { SPR_DRIP, 2, 4, { NULL }, S_DRIP_03 }, //1475 +/*S_DRIP_03*/ { SPR_DRIP, 3, 4, { A_ActiveSound }, S_DRIP_04 }, //1476 +/*S_DRIP_04*/ { SPR_DRIP, 4, 4, { NULL }, S_DRIP_05 }, //1477 +/*S_DRIP_05*/ { SPR_DRIP, 5, 4, { NULL }, S_DRIP_06 }, //1478 +/*S_DRIP_06*/ { SPR_DRIP, 6, 4, { A_ActiveSound }, S_DRIP_07 }, //1479 +/*S_DRIP_07*/ { SPR_DRIP, 7, 4, { NULL }, S_DRIP_00 }, //1480 +/*S_CDRP_00*/ { SPR_CDRP, 0, 10, { NULL }, S_CDRP_01 }, //1481 +/*S_CDRP_01*/ { SPR_CDRP, 1, 8, { NULL }, S_CDRP_02 }, //1482 +/*S_CDRP_02*/ { SPR_CDRP, 2, 8, { NULL }, S_CDRP_03 }, //1483 +/*S_CDRP_03*/ { SPR_CDRP, 3, 8, { NULL }, S_CDRP_00 }, //1484 +/*S_SPLH_00*/ { SPR_SPLH, 0, 4, { NULL }, S_SPLH_01 }, //1485 +/*S_SPLH_01*/ { SPR_SPLH, 1, 4, { NULL }, S_SPLH_02 }, //1486 +/*S_SPLH_02*/ { SPR_SPLH, 2, 4, { NULL }, S_SPLH_03 }, //1487 +/*S_SPLH_03*/ { SPR_SPLH, 3, 8, { NULL }, S_SPLH_04 }, //1488 +/*S_SPLH_04*/ { SPR_SPLH, 4, 4, { NULL }, S_SPLH_05 }, //1489 +/*S_SPLH_05*/ { SPR_SPLH, 5, 4, { NULL }, S_SPLH_06 }, //1490 +/*S_SPLH_06*/ { SPR_SPLH, 6, 4, { NULL }, S_SPLH_07 }, //1491 +/*S_SPLH_07*/ { SPR_SPLH, 7, 4, { A_ActiveSound }, S_SPLH_00 }, //1492 +/*S_WTFT_00*/ { SPR_WTFT, 0, 4, { NULL }, S_WTFT_01 }, //1493 +/*S_WTFT_01*/ { SPR_WTFT, 1, 4, { NULL }, S_WTFT_02 }, //1494 +/*S_WTFT_02*/ { SPR_WTFT, 2, 4, { NULL }, S_WTFT_03 }, //1495 +/*S_WTFT_03*/ { SPR_WTFT, 3, 4, { A_ActiveSound }, S_WTFT_00 }, //1496 +/*S_HERT_00*/ { SPR_HERT, 32768, 4, { NULL }, S_HERT_01 }, //1497 +/*S_HERT_01*/ { SPR_HERT, 32769, 4, { NULL }, S_HERT_02 }, //1498 +/*S_HERT_02*/ { SPR_HERT, 32770, 4, { NULL }, S_HERT_00 }, //1499 +/*S_TELP_00*/ { SPR_TELP, 32768, 3, { NULL }, S_TELP_01 }, //1500 +/*S_TELP_01*/ { SPR_TELP, 32769, 3, { NULL }, S_TELP_02 }, //1501 +/*S_TELP_02*/ { SPR_TELP, 32770, 3, { NULL }, S_TELP_03 }, //1502 +/*S_TELP_03*/ { SPR_TELP, 32771, 3, { NULL }, S_TELP_00 }, //1503 +/*S_MONI_00*/ { SPR_MONI, 0, -1, { NULL }, S_NULL }, //1504 +/*S_STEL_00*/ { SPR_STEL, 0, -1, { NULL }, S_NULL }, //1505 +/*S_STLA_00*/ { SPR_STLA, 0, -1, { NULL }, S_NULL }, //1506 +/*S_STLE_00*/ { SPR_STLE, 0, -1, { NULL }, S_NULL }, //1507 +/*S_HUGE_00*/ { SPR_HUGE, 0, 4, { NULL }, S_HUGE_01 }, //1508 +/*S_HUGE_01*/ { SPR_HUGE, 1, 5, { NULL }, S_HUGE_02 }, //1509 +/*S_HUGE_02*/ { SPR_HUGE, 2, 5, { NULL }, S_HUGE_03 }, //1510 +/*S_HUGE_03*/ { SPR_HUGE, 3, 5, { NULL }, S_HUGE_00 }, //1511 +/*S_STLG_00*/ { SPR_STLG, 0, -1, { NULL }, S_NULL }, //1512 +/*S_STLG_01*/ { SPR_STLG, 1, -1, { NULL }, S_NULL }, //1513 +/*S_STLG_02*/ { SPR_STLG, 2, -1, { NULL }, S_NULL }, //1514 +/*S_STLG_03*/ { SPR_STLG, 3, -1, { NULL }, S_NULL }, //1515 +/*S_STLG_04*/ { SPR_STLG, 4, -1, { NULL }, S_NULL }, //1516 +/*S_STLG_05*/ { SPR_STLG, 5, -1, { NULL }, S_NULL }, //1517 +}; + + +// villsa [STRIFE] +mobjinfo_t mobjinfo[NUMMOBJTYPES] = +{ + { /*MT_FIELDGUARD*/ + 25, //doomednum + S_TOKN_00, //spawnstate + 10, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_XPRK_00, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 2*FRACUNIT, //radius + 1*FRACUNIT, //height + 10000, //mass + 0, //damage + sfx_None, //activesound + MF_SHOOTABLE|MF_NOSECTOR|MF_NODIALOG, //flags + NULL, //namepointer + }, + + { /*MT_PLAYER*/ + -1, //doomednum + S_PLAY_00, //spawnstate + 100, //spawnhealth + S_PLAY_01, //seestate + sfx_None, //seesound + 0, //reactiontime + sfx_None, //attacksound + S_PLAY_07, //painstate + 255, //painchance + sfx_plpain, //painsound + S_NULL, //meleestate + S_PLAY_05, //missilestate + S_NULL, //crashstate + S_PLAY_09, //deathstate + S_RGIB_00, //xdeathstate + sfx_pldeth, //deathsound + 0, //speed + 18*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_NOTDMATCH|MF_ALLY, //flags + NULL, //namepointer + }, + + { /*MT_SHOPKEEPER_W*/ + 116, //doomednum + S_MRST_00, //spawnstate + 10000000, //spawnhealth + S_MRPN_00, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_MRPN_00, //painstate + 150, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 5000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH, //flags + "Weapon_Smith", //namepointer + }, + + { /*MT_SHOPKEEPER_B*/ + 72, //doomednum + S_MRST_00, //spawnstate + 10000000, //spawnhealth + S_MRPN_00, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_MRPN_00, //painstate + 150, //painchance + sfx_ambbar, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 5000, //mass + 0, //damage + sfx_ambppl, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH|MF_COLORSWAP1|MF_COLORSWAP3, //flags + "Bar_Keep", //namepointer + }, + + { /*MT_SHOPKEEPER_A*/ + 73, //doomednum + S_MRST_00, //spawnstate + 10000000, //spawnhealth + S_MRPN_00, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_MRPN_00, //painstate + 150, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 5000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH|MF_COLORSWAP2|MF_COLORSWAP3, //flags + "Armorer", //namepointer + }, + + { /*MT_SHOPKEEPER_M*/ + 74, //doomednum + S_MRST_00, //spawnstate + 10000000, //spawnhealth + S_MRPN_00, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_MRPN_00, //painstate + 150, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH|MF_COLORSWAP1|MF_COLORSWAP2 + |MF_COLORSWAP3, //flags + "Medic", //namepointer + }, + + { /*MT_PEASANT2_A*/ + 3004, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 4, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT2_B*/ + 130, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 5, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT2_C*/ + 131, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 5, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT5_A*/ + 65, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 7, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT5_B*/ + 132, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 7, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT5_C*/ + 133, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 7, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT4_A*/ + 66, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP2, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT4_B*/ + 134, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP2, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT4_C*/ + 135, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP2, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT6_A*/ + 67, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT6_B*/ + 136, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 7, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT6_C*/ + 137, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT3_A*/ + 172, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT3_B*/ + 173, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT3_C*/ + 174, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT8_A*/ + 175, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2 + |MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT8_B*/ + 176, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2 + |MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT8_C*/ + 177, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2 + |MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT7_A*/ + 178, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT7_B*/ + 179, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT7_C*/ + 180, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_PEASANT1*/ + 181, //doomednum + S_PEAS_00, //spawnstate + 31, //spawnhealth + S_PEAS_01, //seestate + sfx_rebact, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_PEAS_12, //painstate + 200, //painchance + sfx_pespna, //painsound + S_PEAS_09, //meleestate + S_NULL, //missilestate + S_PEAS_14, //crashstate + S_PEAS_17, //deathstate + S_GIBS_00, //xdeathstate + sfx_psdtha, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 + |MF_COLORSWAP2|MF_COLORSWAP3, //flags + NULL, //namepointer + }, + + { /*MT_ZOMBIE*/ + 169, //doomednum + S_PEAS_25, //spawnstate + 31, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_AGRD_00, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_GIBS_00, //deathstate + S_NULL, //xdeathstate + sfx_psdtha, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1, //flags + NULL, //namepointer + }, + + { /*MT_BECOMING*/ + 201, //doomednum + S_ARMR_00, //spawnstate + 61, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_ARMR_01, //painstate + 255, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_GIBS_10, //deathstate + S_NULL, //xdeathstate + sfx_psdtha, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_ZOMBIESPAWNER*/ + 170, //doomednum + S_PLAY_19, //spawnstate + 20, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_telept, //activesound + MF_SHOOTABLE|MF_NOSECTOR, //flags + NULL, //namepointer + }, + + { /*MT_HUGE_TANK_1*/ + 209, //doomednum + S_TNK1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 192*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_HUGE_TANK_2*/ + 210, //doomednum + S_TNK2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 192*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_HUGE_TANK_3*/ + 211, //doomednum + S_TNK3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 192*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TANK_4*/ + 213, //doomednum + S_TNK4_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 56*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TANK_5*/ + 214, //doomednum + S_TNK5_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 56*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TANK_6*/ + 229, //doomednum + S_TNK6_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 56*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_KNEELING_GUY*/ + 204, //doomednum + S_NEAL_00, //spawnstate + 51, //spawnhealth + S_NEAL_00, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NEAL_02, //painstate + 255, //painchance + sfx_static, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NEAL_05, //crashstate + S_NEAL_07, //deathstate + S_NULL, //xdeathstate + sfx_static, //deathsound + 0, //speed + 6*FRACUNIT, //radius + 6*FRACUNIT, //height + 50000, //mass + 0, //damage + sfx_chant, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_BEGGAR1*/ + 141, //doomednum + S_BEGR_00, //spawnstate + 20, //spawnhealth + S_BEGR_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_BEGR_11, //painstate + 250, //painchance + sfx_pespna, //painsound + S_BEGR_07, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BEGR_13, //deathstate + S_BEGR_22, //xdeathstate + sfx_psdtha, //deathsound + 3, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + "Beggar", //namepointer + }, + + { /*MT_BEGGAR2*/ + 155, //doomednum + S_BEGR_00, //spawnstate + 20, //spawnhealth + S_BEGR_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_BEGR_11, //painstate + 250, //painchance + sfx_pespna, //painsound + S_BEGR_07, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BEGR_13, //deathstate + S_BEGR_22, //xdeathstate + sfx_psdtha, //deathsound + 3, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + "Beggar", //namepointer + }, + + { /*MT_BEGGAR3*/ + 156, //doomednum + S_BEGR_00, //spawnstate + 20, //spawnhealth + S_BEGR_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_BEGR_11, //painstate + 250, //painchance + sfx_pespna, //painsound + S_BEGR_07, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BEGR_13, //deathstate + S_BEGR_22, //xdeathstate + sfx_psdtha, //deathsound + 3, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + "Beggar", //namepointer + }, + + { /*MT_BEGGAR4*/ + 157, //doomednum + S_BEGR_00, //spawnstate + 20, //spawnhealth + S_BEGR_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_BEGR_11, //painstate + 250, //painchance + sfx_pespna, //painsound + S_BEGR_07, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BEGR_13, //deathstate + S_BEGR_22, //xdeathstate + sfx_psdtha, //deathsound + 3, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + "Beggar", //namepointer + }, + + { /*MT_BEGGAR5*/ + 158, //doomednum + S_BEGR_00, //spawnstate + 20, //spawnhealth + S_BEGR_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_meatht, //attacksound + S_BEGR_11, //painstate + 250, //painchance + sfx_pespna, //painsound + S_BEGR_07, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BEGR_13, //deathstate + S_BEGR_22, //xdeathstate + sfx_psdtha, //deathsound + 3, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags + "Beggar", //namepointer + }, + + { /*MT_REBEL1*/ + 9, //doomednum + S_HMN1_00, //spawnstate + 60, //spawnhealth + S_HMN1_11, //seestate + sfx_wpnup, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HMN1_22, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_HMN1_19, //missilestate + S_NULL, //crashstate + S_HMN1_24, //deathstate + S_RGIB_08, //xdeathstate + sfx_rebdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags + "Rebel", //namepointer + }, + + { /*MT_REBEL2*/ + 144, //doomednum + S_HMN1_00, //spawnstate + 60, //spawnhealth + S_HMN1_11, //seestate + sfx_wpnup, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HMN1_22, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_HMN1_19, //missilestate + S_NULL, //crashstate + S_HMN1_24, //deathstate + S_RGIB_08, //xdeathstate + sfx_rebdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags + "Rebel", //namepointer + }, + + { /*MT_REBEL3*/ + 145, //doomednum + S_HMN1_00, //spawnstate + 60, //spawnhealth + S_HMN1_11, //seestate + sfx_wpnup, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HMN1_22, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_HMN1_19, //missilestate + S_NULL, //crashstate + S_HMN1_24, //deathstate + S_RGIB_08, //xdeathstate + sfx_rebdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags + "Rebel", //namepointer + }, + + { /*MT_REBEL4*/ + 149, //doomednum + S_HMN1_00, //spawnstate + 60, //spawnhealth + S_HMN1_11, //seestate + sfx_wpnup, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HMN1_22, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_HMN1_19, //missilestate + S_NULL, //crashstate + S_HMN1_24, //deathstate + S_RGIB_08, //xdeathstate + sfx_rebdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags + "Rebel", //namepointer + }, + + { /*MT_REBEL5*/ + 150, //doomednum + S_HMN1_00, //spawnstate + 60, //spawnhealth + S_HMN1_11, //seestate + sfx_wpnup, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HMN1_22, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_HMN1_19, //missilestate + S_NULL, //crashstate + S_HMN1_24, //deathstate + S_RGIB_08, //xdeathstate + sfx_rebdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags + "Rebel", //namepointer + }, + + { /*MT_REBEL6*/ + 151, //doomednum + S_HMN1_00, //spawnstate + 60, //spawnhealth + S_HMN1_11, //seestate + sfx_wpnup, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HMN1_22, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_HMN1_19, //missilestate + S_NULL, //crashstate + S_HMN1_24, //deathstate + S_RGIB_08, //xdeathstate + sfx_rebdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags + "Rebel", //namepointer + }, + + { /*MT_RLEADER*/ + 64, //doomednum + S_LEDR_00, //spawnstate + 95, //spawnhealth + S_LEAD_04, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_LEAD_15, //painstate + 250, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_LEAD_12, //missilestate + S_NULL, //crashstate + S_LEAD_04, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_NOTDMATCH, //flags + "MACIL", //namepointer + }, + + { /*MT_RLEADER2*/ + 200, //doomednum + S_LEDR_00, //spawnstate + 95, //spawnhealth + S_LEAD_04, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_LEAD_15, //painstate + 200, //painchance + sfx_pespna, //painsound + S_NULL, //meleestate + S_LEAD_17, //missilestate + S_NULL, //crashstate + S_LEAD_20, //deathstate + S_LEAD_20, //xdeathstate + sfx_slop, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_rebact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_NOTDMATCH|MF_SPECTRAL, //flags + "MACIL", //namepointer + }, + + { /*MT_MISSILESMOKE*/ + -1, //doomednum + S_PUFY_04, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_rflite, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags + NULL, //namepointer + }, + + { /*MT_REAVER*/ + 3001, //doomednum + S_ROB1_00, //spawnstate + 150, //spawnhealth + S_ROB1_02, //seestate + sfx_revsee, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_ROB1_15, //painstate + 128, //painchance + sfx_reavpn, //painsound + S_ROB1_10, //meleestate + S_ROB1_13, //missilestate + S_NULL, //crashstate + S_ROB1_17, //deathstate + S_ROB1_26, //xdeathstate + sfx_revdth, //deathsound + 12, //speed + 20*FRACUNIT, //radius + 60*FRACUNIT, //height + 500, //mass + 0, //damage + sfx_revact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_GUARD1*/ + 3002, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac1, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD2*/ + 142, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac2, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD3*/ + 143, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac3, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP2, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD4*/ + 146, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac1, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1|MF_COLORSWAP2, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD5*/ + 147, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac2, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP3, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD6*/ + 148, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac3, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1|MF_COLORSWAP3, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD7*/ + 232, //doomednum + S_AGRD_01, //spawnstate + 60, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac3, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP2|MF_COLORSWAP3, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_GUARD8*/ + 231, //doomednum + S_AGRD_01, //spawnstate + 60, //spawnhealth + S_AGRD_13, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_23, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac3, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1|MF_COLORSWAP2 + |MF_COLORSWAP3, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_SHADOWGUARD*/ + 58, //doomednum + S_AGRD_01, //spawnstate + 70, //spawnhealth + S_AGRD_12, //seestate + sfx_agrsee, //seesound + 8, //reactiontime + sfx_rifle, //attacksound + S_AGRD_21, //painstate + 150, //painchance + sfx_agrdpn, //painsound + S_NULL, //meleestate + S_AGRD_17, //missilestate + S_NULL, //crashstate + S_AGRD_24, //deathstate + S_GIBS_10, //xdeathstate + sfx_agrdth, //deathsound + 7, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_agrac2, //activesound + MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, //flags + "ACOLYTE", //namepointer + }, + + { /*MT_PGUARD*/ + 3003, //doomednum + S_PGRD_00, //spawnstate + 300, //spawnhealth + S_PGRD_04, //seestate + sfx_pgrsee, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_PGRD_16, //painstate + 100, //painchance + sfx_pgrdpn, //painsound + S_PGRD_12, //meleestate + S_PGRD_14, //missilestate + S_NULL, //crashstate + S_PGRD_18, //deathstate + S_NULL, //xdeathstate + sfx_pgrdth, //deathsound + 8, //speed + 20*FRACUNIT, //radius + 60*FRACUNIT, //height + 500, //mass + 0, //damage + sfx_pgract, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD|MF_COUNTKILL, //flags + "TEMPLAR", //namepointer + }, + + { /*MT_CRUSADER*/ + 3005, //doomednum + S_ROB2_00, //spawnstate + 400, //spawnhealth + S_ROB2_01, //seestate + sfx_rb2see, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_ROB2_19, //painstate + 128, //painchance + sfx_rb2pn, //painsound + S_NULL, //meleestate + S_ROB2_09, //missilestate + S_NULL, //crashstate + S_ROB2_20, //deathstate + S_NULL, //xdeathstate + sfx_rb2dth, //deathsound + 8, //speed + 40*FRACUNIT, //radius + 56*FRACUNIT, //height + 400, //mass + 0, //damage + sfx_rb2act, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_BISHOP*/ + 187, //doomednum + S_MLDR_00, //spawnstate + 500, //spawnhealth + S_MLDR_01, //seestate + sfx_rb2see, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_MLDR_11, //painstate + 128, //painchance + sfx_rb2pn, //painsound + S_NULL, //meleestate + S_MLDR_09, //missilestate + S_NULL, //crashstate + S_MLDR_12, //deathstate + S_NULL, //xdeathstate + sfx_pgrdth, //deathsound + 8, //speed + 40*FRACUNIT, //radius + 56*FRACUNIT, //height + 500, //mass + 0, //damage + sfx_rb2act, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL + |MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_ORACLE*/ + 199, //doomednum + S_ORCL_00, //spawnstate + 1, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ORCL_01, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 15*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH, //flags + "ORACLE", //namepointer + }, + + { /*MT_PRIEST*/ + 12, //doomednum + S_PRST_00, //spawnstate + 800, //spawnhealth + S_PRST_02, //seestate + sfx_lorsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_lorpn, //painsound + S_PRST_10, //meleestate + S_PRST_13, //missilestate + S_NULL, //crashstate + S_PDED_00, //deathstate + S_NULL, //xdeathstate + sfx_slop, //deathsound + 10, //speed + 15*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_tend, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST|MF_FLOAT + |MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH, //flags + "PRIEST", //namepointer + }, + + { /*MT_SPECTRE_A*/ + 129, //doomednum + S_ALN1_00, //spawnstate + 1000, //spawnhealth + S_ALN1_02, //seestate + sfx_alnsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_ALN1_19, //painstate + 250, //painchance + sfx_alnpn, //painsound + S_ALN1_13, //meleestate + S_ALN1_16, //missilestate + S_NULL, //crashstate + S_AL1P_00, //deathstate + S_NULL, //xdeathstate + sfx_alndth, //deathsound + 12, //speed + 64*FRACUNIT, //radius + 64*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_NODE*/ + -1, //doomednum + S_NODE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_SPECTREHEAD*/ + -1, //doomednum + S_MTHD_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_SPECTRE_B*/ + 75, //doomednum + S_ALN1_00, //spawnstate + 1200, //spawnhealth + S_ALN1_02, //seestate + sfx_alnsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_ALN1_19, //painstate + 50, //painchance + sfx_alnpn, //painsound + S_ALN1_13, //meleestate + S_ALN1_20, //missilestate + S_NULL, //crashstate + S_AL1P_00, //deathstate + S_NULL, //xdeathstate + sfx_alndth, //deathsound + 12, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SPECTRE_C*/ + 76, //doomednum + S_ALN1_23, //spawnstate + 1500, //spawnhealth + S_ALN1_34, //seestate + sfx_alnsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_ALN1_51, //painstate + 50, //painchance + sfx_alnpn, //painsound + S_ALN1_45, //meleestate + S_ALN1_48, //missilestate + S_NULL, //crashstate + S_AL1P_00, //deathstate + S_NULL, //xdeathstate + sfx_alndth, //deathsound + 12, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SPECTRE_D*/ + 167, //doomednum + S_ALN1_00, //spawnstate + 1700, //spawnhealth + S_ALN1_02, //seestate + sfx_alnsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_ALN1_19, //painstate + 50, //painchance + sfx_alnpn, //painsound + S_ALN1_13, //meleestate + S_ALN1_52, //missilestate + S_NULL, //crashstate + S_AL1P_00, //deathstate + S_NULL, //xdeathstate + sfx_alndth, //deathsound + 12, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SPECTRE_E*/ + 168, //doomednum + S_ALN1_00, //spawnstate + 2000, //spawnhealth + S_ALN1_02, //seestate + sfx_alnsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_ALN1_19, //painstate + 50, //painchance + sfx_alnpn, //painsound + S_ALN1_13, //meleestate + S_ALN1_55, //missilestate + S_NULL, //crashstate + S_AL1P_00, //deathstate + S_NULL, //xdeathstate + sfx_alndth, //deathsound + 12, //speed + 24*FRACUNIT, //radius + 64*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_ENTITY*/ + 128, //doomednum + S_MNAM_00, //spawnstate + 2500, //spawnhealth + S_MNAL_02, //seestate + sfx_mnalse, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_MNAL_19, //painstate + 255, //painchance + sfx_alnpn, //painsound + S_MNAL_13, //meleestate + S_MNAL_16, //missilestate + S_NULL, //crashstate + S_MNAL_20, //deathstate + S_NULL, //xdeathstate + sfx_mnaldt, //deathsound + 13, //speed + 130*FRACUNIT, //radius + 200*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SUBENTITY*/ + -1, //doomednum + S_MNAL_27, //spawnstate + 990, //spawnhealth + S_MNAL_28, //seestate + sfx_alnsee, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_MNAL_40, //painstate + 255, //painchance + sfx_alnpn, //painsound + S_MNAL_34, //meleestate + S_MNAL_37, //missilestate + S_NULL, //crashstate + S_MDTH_00, //deathstate + S_NULL, //xdeathstate + sfx_alndth, //deathsound + 14, //speed + 130*FRACUNIT, //radius + 200*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_alnact, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH + |MF_MVIS|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_NEST*/ + 26, //doomednum + S_NEST_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 84*FRACUNIT, //radius + 47*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_POD*/ + 198, //doomednum + S_PODD_00, //spawnstate + 1000, //spawnhealth + S_PODD_01, //seestate + sfx_slop, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 25*FRACUNIT, //radius + 91*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_B_SHOT*/ + -1, //doomednum + S_ZAP6_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_00, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 30*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 70, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_SB_SHOT*/ + -1, //doomednum + S_ZAP6_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_00, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 30*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 20, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_C_SHOT*/ + -1, //doomednum + S_ZOT3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_00, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 30*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 70, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_SC_SHOT*/ + -1, //doomednum + S_ZOT3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_00, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 30*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 20, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_E_OFFSHOOT*/ + -1, //doomednum + S_ZAP6_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_00, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 30*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 10, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_TRAIL*/ + -1, //doomednum + S_ZAP6_03, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_E_SHOT*/ + -1, //doomednum + S_ZAP7_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_02, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 18*FRACUNIT, //speed + 20*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 130, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_SE_SHOT*/ + -1, //doomednum + S_ZAP7_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_02, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 18*FRACUNIT, //speed + 20*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 30, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_A_ZAP_LEFT*/ + -1, //doomednum + S_ZOT1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_06, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 22*FRACUNIT, //speed + 8*FRACUNIT, //radius + 24*FRACUNIT, //height + 100, //mass + 100, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_A_ZAP_RIGHT*/ + -1, //doomednum + S_ZOT1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_06, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 22*FRACUNIT, //speed + 8*FRACUNIT, //radius + 24*FRACUNIT, //height + 100, //mass + 50, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_A_GROUND*/ + -1, //doomednum + S_ZAP5_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 70, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_01, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 18*FRACUNIT, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_SHADOW, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_D_SHOT*/ + -1, //doomednum + S_ZOT2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_01, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 28*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 120, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SIGIL_SD_SHOT*/ + -1, //doomednum + S_ZOT2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_sigil, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_01, //deathstate + S_NULL, //xdeathstate + sfx_sglhit, //deathsound + 28*FRACUNIT, //speed + 8*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 60, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags + NULL, //namepointer + }, + + { /*MT_SENTINEL*/ + 3006, //doomednum + S_SEWR_00, //spawnstate + 100, //spawnhealth + S_SEWR_01, //seestate + sfx_sntsee, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_SEWR_06, //painstate + 255, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_SEWR_03, //missilestate + S_NULL, //crashstate + S_SEWR_07, //deathstate + S_NULL, //xdeathstate + sfx_sntdth, //deathsound + 7, //speed + 23*FRACUNIT, //radius + 53*FRACUNIT, //height + 300, //mass + 0, //damage + sfx_sntact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_SPAWNCEILING|MF_NOGRAVITY|MF_GIVEQUEST + |MF_FLOAT|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_STALKER*/ + 186, //doomednum + S_SPID_00, //spawnstate + 80, //spawnhealth + S_SPID_03, //seestate + sfx_spisit, //seesound + 8, //reactiontime + sfx_spdatk, //attacksound + S_SPID_24, //painstate + 40, //painchance + sfx_spdatk, //painsound + S_SPID_09, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_SPID_25, //deathstate + S_NULL, //xdeathstate + sfx_spidth, //deathsound + 16, //speed + 31*FRACUNIT, //radius + 25*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_spisit, //activesound + MF_SOLID|MF_SHOOTABLE|MF_SPAWNCEILING|MF_NOGRAVITY|MF_DROPOFF + |MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_INQUISITOR*/ + 16, //doomednum + S_ROB3_00, //spawnstate + 1000, //spawnhealth + S_ROB3_02, //seestate + sfx_inqsee, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_ROB3_10, //missilestate + S_NULL, //crashstate + S_ROB3_20, //deathstate + S_NULL, //xdeathstate + sfx_inqdth, //deathsound + 12, //speed + 40*FRACUNIT, //radius + 110*FRACUNIT, //height + 1000, //mass + 0, //damage + sfx_inqact, //activesound + MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_NOBLOOD|MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_INQARM*/ + -1, //doomednum + S_RBB3_05, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 25, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_PROGRAMMER*/ + 71, //doomednum + S_PRGR_00, //spawnstate + 1100, //spawnhealth + S_PRGR_02, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_revbld, //attacksound + S_PRGR_18, //painstate + 50, //painchance + sfx_prgpn, //painsound + S_PRGR_10, //meleestate + S_PRGR_14, //missilestate + S_NULL, //crashstate + S_PRGR_20, //deathstate + S_NULL, //xdeathstate + sfx_rb2dth, //deathsound + 26, //speed + 45*FRACUNIT, //radius + 60*FRACUNIT, //height + 800, //mass + 4, //damage + sfx_progac, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST|MF_FLOAT + |MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_PROGRAMMERBASE*/ + -1, //doomednum + S_BASE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_HOOKSHOT*/ + -1, //doomednum + S_OCLW_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_chain, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_CCLW_00, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 20*FRACUNIT, //speed + 10*FRACUNIT, //radius + 14*FRACUNIT, //height + 100, //mass + 2, //damage + sfx_swish, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_CHAINSHOT*/ + -1, //doomednum + S_TEND_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_tend, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_MINIMISSLE*/ + -1, //doomednum + S_MICR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_rlaunc, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_MISL_01, //deathstate + S_NULL, //xdeathstate + sfx_mislht, //deathsound + 20*FRACUNIT, //speed + 10*FRACUNIT, //radius + 14*FRACUNIT, //height + 100, //mass + 10, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_C_MISSILE*/ + -1, //doomednum + S_MICR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_rlaunc, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_MISL_00, //deathstate + S_NULL, //xdeathstate + sfx_mislht, //deathsound + 20*FRACUNIT, //speed + 10*FRACUNIT, //radius + 14*FRACUNIT, //height + 100, //mass + 7, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_SEEKMISSILE*/ + -1, //doomednum + S_MISS_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_rlaunc, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_MISL_01, //deathstate + S_NULL, //xdeathstate + sfx_mislht, //deathsound + 20*FRACUNIT, //speed + 10*FRACUNIT, //radius + 14*FRACUNIT, //height + 100, //mass + 10, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_ELECARROW*/ + -1, //doomednum + S_AROW_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_swish, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_ZAP1_01, //deathstate + S_NULL, //xdeathstate + sfx_firxpl, //deathsound + 30*FRACUNIT, //speed + 10*FRACUNIT, //radius + 10*FRACUNIT, //height + 100, //mass + 10, //damage + sfx_swish, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_POISARROW*/ + -1, //doomednum + S_ARWP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_swish, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_AROW_01, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 30*FRACUNIT, //speed + 10*FRACUNIT, //radius + 10*FRACUNIT, //height + 100, //mass + 500, //damage + sfx_swish, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_R_LASER*/ + -1, //doomednum + S_SHT1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_POW1_09, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 40*FRACUNIT, //speed + 10*FRACUNIT, //radius + 8*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_L_LASER*/ + -1, //doomednum + S_SHT1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_plasma, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_POW1_05, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 40*FRACUNIT, //speed + 10*FRACUNIT, //radius + 8*FRACUNIT, //height + 100, //mass + 1, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_HEGRENADE*/ + -1, //doomednum + S_GRAP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_phoot, //seesound + 30, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BNG4_00, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 15*FRACUNIT, //speed + 13*FRACUNIT, //radius + 13*FRACUNIT, //height + 20, //mass + 1, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_PGRENADE*/ + -1, //doomednum + S_GRIN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_phoot, //seesound + 40, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BNG3_08, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 15*FRACUNIT, //speed + 13*FRACUNIT, //radius + 13*FRACUNIT, //height + 20, //mass + 1, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_INQGRENADE*/ + -1, //doomednum + S_UBAM_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_phoot, //seesound + 15, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BNG2_00, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 25*FRACUNIT, //speed + 13*FRACUNIT, //radius + 13*FRACUNIT, //height + 15, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_PFLAME*/ + -1, //doomednum + S_BNG3_09, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 120, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_FLBE_07, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_TORPEDO*/ + -1, //doomednum + S_TORP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_protfl, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_THIT_00, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 20*FRACUNIT, //speed + 13*FRACUNIT, //radius + 8*FRACUNIT, //height + 100, //mass + 1, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_TORPEDOSPREAD*/ + -1, //doomednum + S_TWAV_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_TWAV_02, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 35*FRACUNIT, //speed + 13*FRACUNIT, //radius + 13*FRACUNIT, //height + 100, //mass + 10, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_SFIREBALL*/ + -1, //doomednum + S_FRBL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_flburn, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_FRBL_03, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 15*FRACUNIT, //speed + 8*FRACUNIT, //radius + 11*FRACUNIT, //height + 10, //mass + 4, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_C_FLAME*/ + -1, //doomednum + S_FRBL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_flburn, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_FRBL_03, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 35*FRACUNIT, //speed + 8*FRACUNIT, //radius + 11*FRACUNIT, //height + 50, //mass + 1, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags + NULL, //namepointer + }, + + { /*MT_STRIFEPUFF3*/ + -1, //doomednum + S_SHT2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_STRIFEPUFF*/ + -1, //doomednum + S_PUFY_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags + NULL, //namepointer + }, + + { /*MT_SPARKPUFF*/ + -1, //doomednum + S_POW3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_BLOOD_DEATH*/ + -1, //doomednum + S_SPRY_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_TFOG*/ + -1, //doomednum + S_TFOG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags + NULL, //namepointer + }, + + { /*MT_IFOG*/ + -1, //doomednum + S_IFOG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags + NULL, //namepointer + }, + + { /*MT_TELEPORTMAN*/ + 14, //doomednum + S_NULL, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOSECTOR|MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_01*/ + 24, //doomednum + S_KLAX_00, //spawnstate + 1000, //spawnhealth + S_KLAX_01, //seestate + sfx_None, //seesound + 60, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_STAND|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_TURRET*/ + 27, //doomednum + S_TURT_00, //spawnstate + 125, //spawnhealth + S_TURT_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_TURT_02, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_TURT_02, //missilestate + S_NULL, //crashstate + S_BALL_00, //deathstate + S_NULL, //xdeathstate + sfx_mislht, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 10000000, //mass + 0, //damage + sfx_None, //activesound + MF_SHOOTABLE|MF_STAND|MF_SPAWNCEILING|MF_NOGRAVITY|MF_NOBLOOD + |MF_COUNTKILL, //flags + NULL, //namepointer + }, + + { /*MT_GATE*/ + 45, //doomednum + S_PSTN_00, //spawnstate + 100, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_PSTN_02, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 16, //speed + 20*FRACUNIT, //radius + 76*FRACUNIT, //height + 10000000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_GIVEQUEST|MF_NODIALOG|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_COMPUTER*/ + 182, //doomednum + S_SECR_00, //spawnstate + 80, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_SECR_04, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 27, //speed + 26*FRACUNIT, //radius + 128*FRACUNIT, //height + 100000, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_GIVEQUEST|MF_NODIALOG|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_INV_MED1*/ + 2011, //doomednum + S_STMP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 20, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Med_patch", //namepointer + }, + + { /*MT_INV_MED2*/ + 2012, //doomednum + S_MDKT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 15, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Medical_kit", //namepointer + }, + + { /*MT_INV_MED3*/ + 83, //doomednum + S_FULL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 5, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Surgery_Kit", //namepointer + }, + + { /*MT_DEGNINORE*/ + 59, //doomednum + S_XPRK_01, //spawnstate + 10, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_XPRK_02, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 16*FRACUNIT, //height + 10, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags + "Degnin_Ore", //namepointer + }, + + { /*MT_INV_ARMOR2*/ + 2019, //doomednum + S_ARM1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 3, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Metal_Armor", //namepointer + }, + + { /*MT_INV_ARMOR1*/ + 2018, //doomednum + S_ARM2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 5, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Leather_Armor", //namepointer + }, + + { /*MT_MISC_22*/ + 2014, //doomednum + S_WATR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_MISC_11*/ + 164, //doomednum + S_MUGG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_KEY_BASE*/ + 230, //doomednum + S_FUSL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Base_Key", //namepointer + }, + + { /*MT_GOVSKEY*/ + -1, //doomednum + S_REBL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Govs_Key", //namepointer + }, + + { /*MT_KEY_TRAVEL*/ + 185, //doomednum + S_TPAS_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Passcard", //namepointer + }, + + { /*MT_KEY_ID_BLUE*/ + 184, //doomednum + S_CRD1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "ID_Badge", //namepointer + }, + + { /*MT_PRISONKEY*/ + -1, //doomednum + S_PRIS_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 11, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags + "Prison_Key", //namepointer + }, + + { /*MT_KEY_HAND*/ + 91, //doomednum + S_HAND_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 12, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags + "Severed_Hand", //namepointer + }, + + { /*MT_POWER1KEY*/ + -1, //doomednum + S_PWR1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Power1_Key", //namepointer + }, + + { /*MT_POWER2KEY*/ + -1, //doomednum + S_PWR2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Power2_Key", //namepointer + }, + + { /*MT_POWER3KEY*/ + -1, //doomednum + S_PWR3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Power3_Key", //namepointer + }, + + { /*MT_KEY_GOLD*/ + 40, //doomednum + S_KY1G_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Gold_Key", //namepointer + }, + + { /*MT_KEY_ID_GOLD*/ + 13, //doomednum + S_CRD2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "ID_Card", //namepointer + }, + + { /*MT_KEY_SILVER*/ + 38, //doomednum + S_KY2S_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Silver_Key", //namepointer + }, + + { /*MT_KEY_ORACLE*/ + 61, //doomednum + S_ORAC_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Oracle_Key", //namepointer + }, + + { /*MT_MILITARYID*/ + -1, //doomednum + S_GYID_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Military_ID", //namepointer + }, + + { /*MT_KEY_ORDER*/ + 86, //doomednum + S_FUBR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Order_Key", //namepointer + }, + + { /*MT_KEY_WAREHOUSE*/ + 166, //doomednum + S_WARE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Warehouse_Key", //namepointer + }, + + { /*MT_KEY_BRASS*/ + 39, //doomednum + S_KY3B_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Brass_Key", //namepointer + }, + + { /*MT_KEY_RED_CRYSTAL*/ + 192, //doomednum + S_RCRY_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Red_Crystal_Key", //namepointer + }, + + { /*MT_KEY_BLUE_CRYSTAL*/ + 193, //doomednum + S_BCRY_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Blue_Crystal_Key", //namepointer + }, + + { /*MT_KEY_CHAPEL*/ + 195, //doomednum + S_CHAP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Chapel_Key", //namepointer + }, + + { /*MT_CATACOMBKEY*/ + -1, //doomednum + S_TUNL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 28, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags + "Catacomb_Key", //namepointer + }, + + { /*MT_SECURITYKEY*/ + -1, //doomednum + S_SECK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Security_Key", //namepointer + }, + + { /*MT_KEY_CORE*/ + 236, //doomednum + S_GOID_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Core_Key", //namepointer + }, + + { /*MT_KEY_MAULER*/ + 233, //doomednum + S_BLTK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Mauler_Key", //namepointer + }, + + { /*MT_KEY_FACTORY*/ + 234, //doomednum + S_PROC_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Factory_Key", //namepointer + }, + + { /*MT_KEY_MINE*/ + 235, //doomednum + S_MINE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "MINE_KEY", //namepointer + }, + + { /*MT_NEWKEY5*/ + -1, //doomednum + S_BLTK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "New_Key5", //namepointer + }, + + { /*MT_INV_SHADOWARMOR*/ + 2024, //doomednum + S_SHD1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 2, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Shadow_armor", //namepointer + }, + + { /*MT_INV_SUIT*/ + 2025, //doomednum + S_MASK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 5, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Environmental_Suit", //namepointer + }, + + { /*MT_QUEST_UNIFORM*/ + 90, //doomednum + S_UNIF_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 15, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST, //flags + "Guard_Uniform", //namepointer + }, + + { /*MT_QUEST_GUARD_UNIFORM*/ + 52, //doomednum + S_OFIC_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Officer's_Uniform", //namepointer + }, + + { /*MT_INV_SUPERMAP*/ + 2026, //doomednum + S_PMAP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "map", //namepointer + }, + + { /*MT_INV_RADAR*/ + 2027, //doomednum + S_PMUP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 1, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "scanner", //namepointer + }, + + { /*MT_BEACON*/ + 10, //doomednum + S_BEAC_00, //spawnstate + 5, //spawnhealth + S_BEAC_01, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 16*FRACUNIT, //height + 3, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_DROPPED, //flags + "Teleporter_Beacon", //namepointer + }, + + { /*MT_INV_TARGETER*/ + 207, //doomednum + S_TARG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 5, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Targeter", //namepointer + }, + + { /*MT_MONY_1*/ + 93, //doomednum + S_COIN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 2147483647, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags + "coin", //namepointer + }, + + { /*MT_MONY_10*/ + 138, //doomednum + S_CRED_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags + "10_gold", //namepointer + }, + + { /*MT_MONY_25*/ + 139, //doomednum + S_SACK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags + "25_gold", //namepointer + }, + + { /*MT_MONY_50*/ + 140, //doomednum + S_CHST_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags + "50_gold", //namepointer + }, + + { /*MT_MONY_300*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 3, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_DROPPED, //flags + "300_gold", //namepointer + }, + + { /*MT_TOKEN_RING*/ + -1, //doomednum + S_RING_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 1, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags + "ring", //namepointer + }, + + { /*MT_INV_CHALICE*/ + 205, //doomednum + S_RELC_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 2, //speed + 10*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_DROPPED, //flags + "Offering_Chalice", //namepointer + }, + + { /*MT_TOKEN_EAR*/ + -1, //doomednum + S_EARS_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 9, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST, //flags + "ear", //namepointer + }, + + { /*MT_INV_COMMUNICATOR*/ + 206, //doomednum + S_COMM_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_NOTDMATCH, //flags + "Communicator", //namepointer + }, + + { /*MT_AGREN*/ + 152, //doomednum + S_GRN1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "HE-Grenade_Rounds", //namepointer + }, + + { /*MT_APGREN*/ + 153, //doomednum + S_GRN2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Phosphorus-Grenade_Rounds", //namepointer + }, + + { /*MT_ACLIP*/ + 2007, //doomednum + S_BLIT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "clip_of_bullets", //namepointer + }, + + { /*MT_AAMMOBOX*/ + 2048, //doomednum + S_BBOX_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "ammo", //namepointer + }, + + { /*MT_AMINI*/ + 2010, //doomednum + S_MSSL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "mini_missiles", //namepointer + }, + + { /*MT_AMINIBOX*/ + 2046, //doomednum + S_ROKT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "crate_of_missiles", //namepointer + }, + + { /*MT_ACELL*/ + 2047, //doomednum + S_BRY1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "energy_pod", //namepointer + }, + + { /*MT_APCELL*/ + 17, //doomednum + S_CPAC_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "energy_pack", //namepointer + }, + + { /*MT_APAROW*/ + 115, //doomednum + S_PQRL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "poison_bolts", //namepointer + }, + + { /*MT_AAROW*/ + 114, //doomednum + S_XQRL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "electric_bolts", //namepointer + }, + + { /*MT_INV_SATCHEL*/ + 183, //doomednum + S_BKPK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "ammo_satchel", //namepointer + }, + + { /*MT_PULSE*/ + 2002, //doomednum + S_RIFL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "assault_gun", //namepointer + }, + + { /*MT_RIFLESTAND*/ + 2006, //doomednum + S_RIFL_01, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "assault_gun", //namepointer + }, + + { /*MT_FLAMETHROWER*/ + 2005, //doomednum + S_FLAM_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "flame_thrower", //namepointer + }, + + { /*MT_TOKEN_FLAME_THROWER_PARTS*/ + -1, //doomednum + S_BFLM_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "flame_thrower_parts", //namepointer + }, + + { /*MT_MISSILELAUNCHER*/ + 2003, //doomednum + S_MMSL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "mini_missile_launcher", //namepointer + }, + + { /*MT_BLASTER*/ + 2004, //doomednum + S_TRPD_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "mauler", //namepointer + }, + + { /*MT_CROSSBOW*/ + 2001, //doomednum + S_CBOW_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "crossbow", //namepointer + }, + + { /*MT_GRENADELAUNCHER*/ + 154, //doomednum + S_GRND_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Grenade_launcher", //namepointer + }, + + { /*MT_SIGIL_A*/ + 77, //doomednum + S_SIGL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "SIGIL", //namepointer + }, + + { /*MT_SIGIL_B*/ + 78, //doomednum + S_SIGL_01, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "SIGIL", //namepointer + }, + + { /*MT_SIGIL_C*/ + 79, //doomednum + S_SIGL_02, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "SIGIL", //namepointer + }, + + { /*MT_SIGIL_D*/ + 80, //doomednum + S_SIGL_03, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "SIGIL", //namepointer + }, + + { /*MT_SIGIL_E*/ + 81, //doomednum + S_SIGL_04, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "SIGIL", //namepointer + }, + + { /*MT_POWER_CRYSTAL*/ + 92, //doomednum + S_CRYS_00, //spawnstate + 50, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BOOM_00, //deathstate + S_NULL, //xdeathstate + sfx_explod, //deathsound + 14, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 99999999, //mass + 0, //damage + sfx_reactr, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_RAT*/ + 85, //doomednum + S_RATT_00, //spawnstate + 5, //spawnhealth + S_RATT_01, //seestate + sfx_ratact, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_RATT_05, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_MEAT_16, //deathstate + S_NULL, //xdeathstate + sfx_ratact, //deathsound + 13, //speed + 10*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_ratact, //activesound + MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags + "rat_buddy", //namepointer + }, + + { /*MT_MISC_05*/ + 82, //doomednum + S_BARW_00, //spawnstate + 10, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BARW_01, //deathstate + S_NULL, //xdeathstate + sfx_wbrldt, //deathsound + 0, //speed + 10*FRACUNIT, //radius + 32*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_MISC_06*/ + 94, //doomednum + S_BART_00, //spawnstate + 30, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_BART_01, //deathstate + S_NULL, //xdeathstate + sfx_barexp, //deathsound + 0, //speed + 10*FRACUNIT, //radius + 32*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_MISC_15*/ + 208, //doomednum + S_HOGN_00, //spawnstate + 99999999, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_HOGN_01, //painstate + 255, //painchance + sfx_mtalht, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 10*FRACUNIT, //radius + 72*FRACUNIT, //height + 9999999, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT14*/ + 95, //doomednum + S_LITS_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 4*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT13*/ + 96, //doomednum + S_LITB_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 4*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT12*/ + 97, //doomednum + S_LITG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 4*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT18*/ + 2028, //doomednum + S_LITE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR2*/ + 48, //doomednum + S_MONI_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR3*/ + 54, //doomednum + S_STEL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR4*/ + 55, //doomednum + S_STLA_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 80*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR5*/ + 56, //doomednum + S_STLE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR6*/ + 57, //doomednum + S_HUGE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 24*FRACUNIT, //radius + 192*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR7*/ + 227, //doomednum + S_APOW_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 24*FRACUNIT, //radius + 192*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_amaln2, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_CAVE2*/ + 98, //doomednum + S_STLG_02, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 54*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_CAVE3*/ + 161, //doomednum + S_STLG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_CAVE4*/ + 160, //doomednum + S_STLG_01, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_CAVE6*/ + 159, //doomednum + S_STLG_03, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_CAVE7*/ + 162, //doomednum + S_STLG_04, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_CAVE5*/ + 163, //doomednum + S_STLG_05, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 25*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT2*/ + 34, //doomednum + S_CNDL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT3*/ + 35, //doomednum + S_CLBR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_03*/ + 103, //doomednum + S_DRIP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_wdrip, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_13*/ + 104, //doomednum + S_SPLH_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_wfall, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_02*/ + 53, //doomednum + S_CDRP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 1*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_MISC_07*/ + 112, //doomednum + S_WTFT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_wsplsh, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_BIO2*/ + 113, //doomednum + S_HERT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TELEPORTSTAND*/ + 23, //doomednum + S_TELP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_SHADOW, //flags + NULL, //namepointer + }, + + { /*MT_DEADTHING1*/ + 22, //doomednum + S_ROB2_28, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_DEADTHING2*/ + 15, //doomednum + S_PLAY_18, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_DEADTHING3*/ + 18, //doomednum + S_PEAS_24, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_DEADTHING4*/ + 21, //doomednum + S_AGRD_31, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_DEADTHING5*/ + 20, //doomednum + S_ROB1_25, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_DEADTHING6*/ + 19, //doomednum + S_HMN1_31, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_BIO1*/ + 212, //doomednum + S_SACR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_GIBS*/ + 54, //doomednum + S_DEAD_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_MISC_04*/ + 70, //doomednum + S_BARL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 48*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT11*/ + 105, //doomednum + S_BOWL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_smfire, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT10*/ + 106, //doomednum + S_BRAZ_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 10*FRACUNIT, //radius + 32*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_smfire, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT9*/ + 107, //doomednum + S_TRCH_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 0*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_smfire, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT8*/ + 108, //doomednum + S_TRHO_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 0*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_14*/ + 109, //doomednum + S_CHAN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 93*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT1*/ + 28, //doomednum + S_CAGE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 3*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR8*/ + 110, //doomednum + S_STAT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 64*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR9*/ + 44, //doomednum + S_DSTA_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT15*/ + 111, //doomednum + S_LTRH_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 4*FRACUNIT, //radius + 72*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT4*/ + 43, //doomednum + S_LAMP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 3*FRACUNIT, //radius + 80*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT5*/ + 46, //doomednum + S_LANT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 3*FRACUNIT, //radius + 80*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_ROCK1*/ + 99, //doomednum + S_ROK1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_ROCK2*/ + 100, //doomednum + S_ROK2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_ROCK3*/ + 101, //doomednum + S_ROK3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_ROCK4*/ + 102, //doomednum + S_ROK4_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_TREE7*/ + 215, //doomednum + S_LOGG_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_wriver, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE1*/ + 29, //doomednum + S_RUB1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE2*/ + 30, //doomednum + S_RUB2_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE3*/ + 31, //doomednum + S_RUB3_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE4*/ + 32, //doomednum + S_RUB4_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE5*/ + 36, //doomednum + S_RUB5_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE6*/ + 37, //doomednum + S_RUB6_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE7*/ + 41, //doomednum + S_RUB7_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_RUBBLE8*/ + 42, //doomednum + S_RUB8_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_08*/ + 117, //doomednum + S_CRAB_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT6*/ + 47, //doomednum + S_LMPC_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 10*FRACUNIT, //radius + 72*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_smfire, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT7*/ + 50, //doomednum + S_LOGS_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 10*FRACUNIT, //radius + 80*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_smfire, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TREE2*/ + 51, //doomednum + S_TREE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 15*FRACUNIT, //radius + 109*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TREE3*/ + 202, //doomednum + S_TREE_01, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 15*FRACUNIT, //radius + 109*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TREE4*/ + 203, //doomednum + S_TREE_02, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 15*FRACUNIT, //radius + 64*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TREE1*/ + 33, //doomednum + S_TRE1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 15*FRACUNIT, //radius + 80*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TREE6*/ + 60, //doomednum + S_BUSH_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 15*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_TREE5*/ + 62, //doomednum + S_SHRB_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 64*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_CAVE1*/ + 63, //doomednum + S_STAK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 64*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR1*/ + 69, //doomednum + S_BAR1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_10*/ + 165, //doomednum + S_VASE_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 12*FRACUNIT, //radius + 24*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_09*/ + 188, //doomednum + S_VASE_01, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 12*FRACUNIT, //radius + 32*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_17*/ + 189, //doomednum + S_STOL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 6*FRACUNIT, //radius + 24*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_18*/ + 190, //doomednum + S_POT1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_19*/ + 191, //doomednum + S_TUB1_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_20*/ + 194, //doomednum + S_ANVL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 32*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT16*/ + 196, //doomednum + S_TLMP_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 11*FRACUNIT, //radius + 64*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT17*/ + 197, //doomednum + S_TLMP_01, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 8*FRACUNIT, //radius + 64*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_21*/ + 68, //doomednum + S_TRAY_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 24*FRACUNIT, //radius + 40*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_12*/ + 228, //doomednum + S_AFED_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 12*FRACUNIT, //radius + 24*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MISC_26*/ + 216, //doomednum + S_SBAN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 24*FRACUNIT, //radius + 96*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_23*/ + 217, //doomednum + S_BOTR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_24*/ + 218, //doomednum + S_HATR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_MISC_25*/ + 219, //doomednum + S_TOPR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP, //flags + NULL, //namepointer + }, + + { /*MT_COUPLING*/ + 220, //doomednum + S_COUP_00, //spawnstate + 40, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 6, //speed + 17*FRACUNIT, //radius + 64*FRACUNIT, //height + 999999, //mass + 0, //damage + sfx_None, //activesound + MF_SOLID|MF_SHOOTABLE|MF_GIVEQUEST|MF_NODIALOG|MF_DROPPED + |MF_NOBLOOD|MF_NOTDMATCH, //flags + NULL, //namepointer + }, + + { /*MT_COUPLING_BROKEN*/ + 226, //doomednum + S_COUP_02, //spawnstate + 40, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 512*FRACUNIT, //speed + 16*FRACUNIT, //radius + 16*FRACUNIT, //height + 1, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST|MF_DROPPED, //flags + "BROKEN_POWER_COUPLING", //namepointer + }, + + { /*MT_PILLAR10*/ + 221, //doomednum + S_BUBB_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_amaln5, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR11*/ + 222, //doomednum + S_BUBF_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 72*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_amaln6, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR12*/ + 223, //doomednum + S_BUBF_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 72*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_amaln4, //activesound + MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags + NULL, //namepointer + }, + + { /*MT_PILLAR13*/ + 224, //doomednum + S_ASPR_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 16*FRACUNIT, //radius + 128*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_amaln3, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_LIGHT19*/ + 225, //doomednum + S_SPDL_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 32*FRACUNIT, //radius + 56*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_amaln1, //activesound + MF_SOLID, //flags + NULL, //namepointer + }, + + { /*MT_MEAT*/ + -1, //doomednum + S_MEAT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_JUNK*/ + -1, //doomednum + S_JUNK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_BURNDROP*/ + -1, //doomednum + S_FFOT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_NOBLOCKMAP|MF_NOCLIP, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_AMMO*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Ammo", //namepointer + }, + + { /*MT_TOKEN_HEALTH*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Health", //namepointer + }, + + { /*MT_TOKEN*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "info", //namepointer + }, + + { /*MT_TOKEN_ALARM*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "alarm", //namepointer + }, + + { /*MT_TOKEN_DOOR1*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_SHOPCLOSE*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_PRISON_PASS*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 10, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST, //flags + "Prison_pass", //namepointer + }, + + { /*MT_TOKEN_DOOR3*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_STAMINA*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_NEW_ACCURACY*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_REPORT*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "report", //namepointer + }, + + { /*MT_TOKEN_TOUGHNESS*/ + -1, //doomednum + S_HELT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Toughness", //namepointer + }, + + { /*MT_TOKEN_ACCURACY*/ + -1, //doomednum + S_GUNT_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + "Accuracy", //namepointer + }, + + { /*MT_TOKEN_ORACLE_PASS*/ + -1, //doomednum + S_OTOK_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 18, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL|MF_GIVEQUEST, //flags + "Oracle_Pass", //namepointer + }, + + { /*MT_TOKEN_QUEST1*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST2*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST3*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST4*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "quest4", //namepointer + }, + + { /*MT_TOKEN_QUEST5*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "quest5", //namepointer + }, + + { /*MT_TOKEN_QUEST6*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "quest6", //namepointer + }, + + { /*MT_TOKEN_QUEST7*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST8*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST9*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST10*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST11*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST12*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST13*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_CRYSTAL*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You've_Blown_Up_the_Crystal", //namepointer + }, + + { /*MT_TOKEN_QUEST15*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_GATEQUEST*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You've_Blown_Up_the_Gates", //namepointer + }, + + { /*MT_TOKEN_QUEST17*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST18*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST19*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST20*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_BISHOP*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You_Killed_the_Bishop!", //namepointer + }, + + { /*MT_TOKEN_QUEST22*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_ORACLE*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You've_Killed_The_Oracle!", //namepointer + }, + + { /*MT_TOKEN_MACIL*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You_Killed_Macil!", //namepointer + }, + + { /*MT_TOKEN_QUEST25*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_LOREMASTER*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You've_Killed_The_Loremaster!", //namepointer + }, + + { /*MT_SECRQUEST*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + "You've_Blown_Up_the_Computer", //namepointer + }, + + { /*MT_TOKEN_QUEST28*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST29*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST30*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_TOKEN_QUEST31*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + 0, //flags + NULL, //namepointer + }, + + { /*MT_SLIDESHOW*/ + -1, //doomednum + S_TOKN_00, //spawnstate + 1000, //spawnhealth + S_NULL, //seestate + sfx_None, //seesound + 8, //reactiontime + sfx_None, //attacksound + S_NULL, //painstate + 0, //painchance + sfx_None, //painsound + S_NULL, //meleestate + S_NULL, //missilestate + S_NULL, //crashstate + S_NULL, //deathstate + S_NULL, //xdeathstate + sfx_None, //deathsound + 0, //speed + 20*FRACUNIT, //radius + 16*FRACUNIT, //height + 100, //mass + 0, //damage + sfx_None, //activesound + MF_SPECIAL, //flags + NULL, //namepointer + }, + +}; + + + diff --git a/games/NXDoom/src/strife/info.h b/games/NXDoom/src/strife/info.h new file mode 100644 index 00000000000..4c8edc7b61a --- /dev/null +++ b/games/NXDoom/src/strife/info.h @@ -0,0 +1,2219 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Thing frame/state LUT, +// generated by multigen utilitiy. +// This one is the original DOOM version, preserved. +// + +#ifndef __INFO__ +#define __INFO__ + +// Needed for action function pointer handling. +#include "d_think.h" + +// villsa [STRIFE] +typedef enum +{ + SPR_PLAY, // 0 + SPR_PNCH, // 1 + SPR_WAVE, // 2 + SPR_RBPY, // 3 + SPR_TRGT, // 4 + SPR_XBOW, // 5 + SPR_MMIS, // 6 + SPR_RIFG, // 7 + SPR_RIFF, // 8 + SPR_FLMT, // 9 + SPR_FLMF, // 10 + SPR_BLST, // 11 + SPR_BLSF, // 12 + SPR_GREN, // 13 + SPR_GREF, // 14 + SPR_SIGH, // 15 + SPR_SIGF, // 16 + SPR_POW1, // 17 + SPR_POW2, // 18 + SPR_POW3, // 19 + SPR_ZAP1, // 20 + SPR_SPRY, // 21 + SPR_BLOD, // 22 + SPR_PUFY, // 23 + SPR_SHT1, // 24 + SPR_SHT2, // 25 + SPR_GRIN, // 26 + SPR_GRAP, // 27 + SPR_UBAM, // 28 + SPR_BNG2, // 29 + SPR_BNG4, // 30 + SPR_BNG3, // 31 + SPR_FLBE, // 32 + SPR_XPRK, // 33 + SPR_OCLW, // 34 + SPR_CCLW, // 35 + SPR_TEND, // 36 + SPR_MICR, // 37 + SPR_MISS, // 38 + SPR_AROW, // 39 + SPR_ARWP, // 40 + SPR_TORP, // 41 + SPR_THIT, // 42 + SPR_TWAV, // 43 + SPR_MISL, // 44 + SPR_TFOG, // 45 + SPR_IFOG, // 46 + SPR_SHRD, // 47 + SPR_RGIB, // 48 + SPR_MRYS, // 49 + SPR_MRNO, // 50 + SPR_MRST, // 51 + SPR_MRLK, // 52 + SPR_MRBD, // 53 + SPR_MRPN, // 54 + SPR_MRGT, // 55 + SPR_BURN, // 56 + SPR_DISR, // 57 + SPR_PEAS, // 58 + SPR_GIBS, // 59 + SPR_AGRD, // 60 + SPR_ARMR, // 61 + SPR_SACR, // 62 + SPR_TNK1, // 63 + SPR_TNK2, // 64 + SPR_TNK3, // 65 + SPR_TNK4, // 66 + SPR_TNK5, // 67 + SPR_TNK6, // 68 + SPR_NEAL, // 69 + SPR_BEGR, // 70 + SPR_HMN1, // 71 + SPR_LEDR, // 72 + SPR_LEAD, // 73 + SPR_ROB1, // 74 + SPR_PGRD, // 75 + SPR_ROB2, // 76 + SPR_MLDR, // 77 + SPR_ORCL, // 78 + SPR_PRST, // 79 + SPR_PDED, // 80 + SPR_ALN1, // 81 + SPR_AL1P, // 82 + SPR_NODE, // 83 + SPR_MTHD, // 84 + SPR_MNAM, // 85 + SPR_MNAL, // 86 + SPR_MDTH, // 87 + SPR_NEST, // 88 + SPR_PODD, // 89 + SPR_ZAP6, // 90 + SPR_ZOT3, // 91 + SPR_ZAP7, // 92 + SPR_ZOT1, // 93 + SPR_ZAP5, // 94 + SPR_ZOT2, // 95 + SPR_SEWR, // 96 + SPR_SPID, // 97 + SPR_ROB3, // 98 + SPR_RBB3, // 99 + SPR_PRGR, // 100 + SPR_BASE, // + SPR_FRBL, // + SPR_KLAX, // + SPR_TURT, // + SPR_BALL, // 105 + SPR_PSTN, // + SPR_SECR, // + SPR_TARG, // + SPR_RING, // + SPR_EARS, // 110 + SPR_COMM, // + SPR_BOOM, // + SPR_RATT, // + SPR_HOGN, // + SPR_DEAD, // 115 + SPR_SBAN, // + SPR_BOTR, // + SPR_HATR, // + SPR_TOPR, // + SPR_COUP, // 120 + SPR_BUBB, // + SPR_BUBF, // + SPR_BUBC, // + SPR_ASPR, // + SPR_SPDL, // 125 + SPR_TOKN, // + SPR_OTOK, // + SPR_HELT, // + SPR_GUNT, // + SPR_FULL, // 130 + SPR_MEAT, // + SPR_JUNK, // + SPR_FFOT, // + SPR_DIE1, // + SPR_BEAC, // 135 + SPR_ARM1, // + SPR_ARM2, // + SPR_BARW, // + SPR_BART, // + SPR_LAMP, // 140 + SPR_LANT, // + SPR_BARL, // + SPR_BOWL, // + SPR_BRAZ, // + SPR_TRCH, // 145 + SPR_LTRH, // + SPR_LMPC, // + SPR_LOGS, // + SPR_TRHO, // + SPR_WATR, // 150 + SPR_MUGG, // + SPR_FUSL, // + SPR_CRD1, // + SPR_CRD2, // + SPR_TPAS, // 155 + SPR_KY1G, // + SPR_KY2S, // + SPR_KY3B, // + SPR_HAND, // + SPR_CRYS, // 160 + SPR_PRIS, // + SPR_PWR1, // + SPR_PWR2, // + SPR_PWR3, // + SPR_ORAC, // 165 + SPR_GYID, // + SPR_FUBR, // + SPR_WARE, // + SPR_RCRY, // + SPR_BCRY, // 170 + SPR_CHAP, // + SPR_TUNL, // + SPR_BLTK, // + SPR_SECK, // + SPR_MINE, // 175 + SPR_REBL, // + SPR_PROC, // + SPR_ANKH, // + SPR_GOID, // + SPR_STMP, // 180 + SPR_MDKT, // + SPR_COIN, // + SPR_CRED, // + SPR_SACK, // + SPR_CHST, // 185 + SPR_SHD1, // + SPR_MASK, // + SPR_UNIF, // + SPR_OFIC, // + SPR_PMAP, // 190 + SPR_PMUP, // + SPR_BLIT, // + SPR_BBOX, // + SPR_MSSL, // + SPR_ROKT, // 195 + SPR_BRY1, // + SPR_CPAC, // + SPR_PQRL, // + SPR_XQRL, // + SPR_GRN1, // 200 + SPR_GRN2, // + SPR_BKPK, // + SPR_RELC, // + SPR_RIFL, // + SPR_FLAM, // 205 + SPR_BFLM, // + SPR_MMSL, // + SPR_TRPD, // + SPR_GRND, // + SPR_CBOW, // 210 + SPR_SIGL, // + SPR_LITE, // + SPR_CNDL, // + SPR_CLBR, // + SPR_LITS, // 215 + SPR_LITB, // + SPR_LITG, // + SPR_ROK1, // + SPR_ROK2, // + SPR_ROK3, // 220 + SPR_ROK4, // + SPR_LOGG, // + SPR_RUB1, // + SPR_RUB2, // + SPR_RUB3, // 225 + SPR_RUB4, // + SPR_RUB5, // + SPR_RUB6, // + SPR_RUB7, // + SPR_RUB8, // 230 + SPR_CHAN, // + SPR_STAT, // + SPR_DSTA, // + SPR_CRAB, // + SPR_CAGE, // 235 + SPR_TREE, // + SPR_TRE1, // + SPR_BUSH, // + SPR_SHRB, // + SPR_STAK, // 240 + SPR_BAR1, // + SPR_VASE, // + SPR_STOL, // + SPR_POT1, // + SPR_TUB1, // 245 + SPR_ANVL, // + SPR_TLMP, // + SPR_TRAY, // + SPR_APOW, // + SPR_AFED, // 250 + SPR_DRIP, // + SPR_CDRP, // + SPR_SPLH, // + SPR_WTFT, // + SPR_HERT, // + SPR_TELP, // + SPR_MONI, // + SPR_STEL, // + SPR_STLA, // + SPR_STLE, // 260 + SPR_HUGE, // 261 + SPR_STLG, // 262 + NUMSPRITES + +} spritenum_t; + +// villsa [STRIFE] +typedef enum +{ + S_NULL, // 00 + S_PNCH_00, // 01 + S_WAVE_00, // 02 + S_WAVE_01, // 03 + S_WAVE_02, // 04 + S_WAVE_03, // 05 + S_RBPY_00, // 06 + S_RBPY_01, // 07 + S_RBPY_02, // 08 + S_RBPY_03, // 09 + S_TRGT_00, // 10 + S_TRGT_01, // 11 + S_TRGT_02, // 12 + S_PNCH_01, // 13 + S_PNCH_02, // 14 + S_PNCH_03, // 15 + S_PNCH_04, // 16 + S_PNCH_05, // 17 + S_PNCH_06, // 18 + S_PNCH_07, // 19 + S_PNCH_08, // 20 + S_XBOW_00, // 21 + S_XBOW_01, // 22 + S_XBOW_02, // 23 + S_XBOW_03, // 24 + S_XBOW_04, // 25 + S_XBOW_05, // 26 + S_XBOW_06, // 27 + S_XBOW_07, // 28 + S_XBOW_08, // 29 + S_XBOW_09, // 30 + S_XBOW_10, // 31 + S_XBOW_11, // 32 + S_XBOW_12, // 33 + S_XBOW_13, // 34 + S_XBOW_14, // 35 + S_XBOW_15, // 36 + S_XBOW_16, // 37 + S_XBOW_17, // 38 + S_XBOW_18, // 39 + S_XBOW_19, // 40 + S_XBOW_20, // 41 + S_XBOW_21, // 42 + S_XBOW_22, // 43 + S_MMIS_00, // 44 + S_MMIS_01, // 45 + S_MMIS_02, // 46 + S_MMIS_03, // 47 + S_MMIS_04, // 48 + S_MMIS_05, // 49 + S_MMIS_06, // 50 + S_MMIS_07, // 51 + S_MMIS_08, // 52 + S_MMIS_09, // 53 + S_RIFG_00, // 54 + S_RIFG_01, // 55 + S_RIFG_02, // 56 + S_RIFF_00, // 57 + S_RIFF_01, // 58 + S_RIFG_03, // 59 + S_RIFG_04, // 60 + S_RIFG_05, // 61 + S_FLMT_00, // 62 + S_FLMT_01, // 63 + S_FLMT_02, // 64 + S_FLMT_03, // 65 + S_FLMF_00, // 66 + S_FLMF_01, // 67 + S_BLST_00, // 68 + S_BLST_01, // 69 + S_BLST_02, // 70 + S_BLST_03, // 71 + S_BLST_04, // 72 + S_BLST_05, // 73 + S_BLSF_00, // 74 + S_BLST_06, // 75 + S_BLST_07, // 76 + S_BLST_08, // 77 + S_BLST_09, // 78 + S_BLST_10, // 79 + S_BLST_11, // 80 + S_BLST_12, // 81 + S_BLST_13, // 82 + S_BLST_14, // 83 + S_BLST_15, // 84 + S_BLST_16, // 85 + S_BLST_17, // 86 + S_BLST_18, // 87 + S_BLST_19, // 88 + S_BLST_20, // 89 + S_BLSF_01, // 90 + S_BLST_21, // 91 + S_BLST_22, // 92 + S_BLST_23, // 93 + S_BLST_24, // 94 + S_GREN_00, // 95 + S_GREN_01, // 96 + S_GREN_02, // 97 + S_GREN_03, // 98 + S_GREN_04, // 99 + S_GREN_05, // 100 + S_GREN_06, // 101 + S_GREN_07, // 102 + S_GREF_00, // 103 + S_GREF_01, // 104 + S_GREF_02, // 105 + S_GREN_08, // 106 + S_GREN_09, // 107 + S_GREN_10, // 108 + S_GREN_11, // 109 + S_GREN_12, // 110 + S_GREN_13, // 111 + S_GREN_14, // 112 + S_GREN_15, // 113 + S_GREF_03, // 114 + S_GREF_04, // 115 + S_GREF_05, // 116 + S_SIGH_00, // 117 + S_SIGH_01, // 118 + S_SIGH_02, // 119 + S_SIGH_03, // 120 + S_SIGH_04, // 121 + S_SIGH_05, // 122 + S_SIGH_06, // 123 + S_SIGH_07, // 124 + S_SIGH_08, // 125 + S_SIGH_09, // 126 + S_SIGH_10, // 127 + S_SIGF_00, // 128 + S_SIGF_01, // 129 + S_SIGF_02, // 130 + S_POW1_00, // 131 + S_POW1_01, // 132 + S_POW1_02, // 133 + S_POW1_03, // 134 + S_POW1_04, // 135 + S_POW1_05, // 136 + S_POW1_06, // 137 + S_POW1_07, // 138 + S_POW1_08, // 139 + S_POW1_09, // 140 + S_POW2_00, // 141 + S_POW2_01, // 142 + S_POW2_02, // 143 + S_POW2_03, // 144 + S_POW3_00, // 145 + S_POW3_01, // 146 + S_POW3_02, // 147 + S_POW3_03, // 148 + S_POW3_04, // 149 + S_POW3_05, // 150 + S_POW3_06, // 151 + S_POW3_07, // 152 + S_ZAP1_00, // 153 + S_ZAP1_01, // 154 + S_ZAP1_02, // 155 + S_ZAP1_03, // 156 + S_ZAP1_04, // 157 + S_ZAP1_05, // 158 + S_ZAP1_06, // 159 + S_ZAP1_07, // 160 + S_ZAP1_08, // 161 + S_ZAP1_09, // 162 + S_ZAP1_10, // 163 + S_ZAP1_11, // 164 + S_SPRY_00, // 165 + S_SPRY_01, // 166 + S_SPRY_02, // 167 + S_SPRY_03, // 168 + S_SPRY_04, // 169 + S_SPRY_05, // 170 + S_SPRY_06, // 171 + S_BLOD_00, // 172 + S_BLOD_01, // 173 + S_BLOD_02, // 174 + S_PUFY_00, // 175 + S_PUFY_01, // 176 + S_PUFY_02, // 177 + S_PUFY_03, // 178 + S_SHT1_00, // 179 + S_SHT1_01, // 180 + S_SHT2_00, // 181 + S_SHT2_01, // 182 + S_GRIN_00, // 183 + S_GRIN_01, // 184 + S_GRAP_00, // 185 + S_GRAP_01, // 186 + S_UBAM_00, // 187 + S_UBAM_01, // 188 + S_BNG2_00, // 189 + S_BNG2_01, // 190 + S_BNG2_02, // 191 + S_BNG2_03, // 192 + S_BNG2_04, // 193 + S_BNG2_05, // 194 + S_BNG2_06, // 195 + S_BNG2_07, // 196 + S_BNG2_08, // 197 + S_BNG4_00, // 198 + S_BNG4_01, // 199 + S_BNG4_02, // 200 + S_BNG4_03, // 201 + S_BNG4_04, // 202 + S_BNG4_05, // 203 + S_BNG4_06, // 204 + S_BNG4_07, // 205 + S_BNG4_08, // 206 + S_BNG4_09, // 207 + S_BNG4_10, // 208 + S_BNG4_11, // 209 + S_BNG4_12, // 210 + S_BNG4_13, // 211 + S_BNG3_00, // 212 + S_BNG3_01, // 213 + S_BNG3_02, // 214 + S_BNG3_03, // 215 + S_BNG3_04, // 216 + S_BNG3_05, // 217 + S_BNG3_06, // 218 + S_BNG3_07, // 219 + S_BNG3_08, // 220 + S_BNG3_09, // 221 + S_BNG3_10, // 222 + S_FLBE_00, // 223 + S_FLBE_01, // 224 + S_FLBE_02, // 225 + S_FLBE_03, // 226 + S_FLBE_04, // 227 + S_FLBE_05, // 228 + S_FLBE_06, // 229 + S_FLBE_07, // 230 + S_FLBE_08, // 231 + S_FLBE_09, // 232 + S_FLBE_10, // 233 + S_XPRK_00, // 234 + S_OCLW_00, // 235 + S_CCLW_00, // 236 + S_TEND_00, // 237 + S_MICR_00, // 238 + S_MISS_00, // 239 + S_MISS_01, // 240 + S_AROW_00, // 241 + S_ARWP_00, // 242 + S_AROW_01, // 243 + S_TORP_00, // 244 + S_TORP_01, // 245 + S_TORP_02, // 246 + S_TORP_03, // 247 + S_THIT_00, // 248 + S_THIT_01, // 249 + S_THIT_02, // 250 + S_THIT_03, // 251 + S_THIT_04, // 252 + S_TWAV_00, // 253 + S_TWAV_01, // 254 + S_TWAV_02, // 255 + S_MISL_00, // 256 + S_MISL_01, // 257 + S_MISL_02, // 258 + S_MISL_03, // 259 + S_MISL_04, // 260 + S_MISL_05, // 261 + S_MISL_06, // 262 + S_MISL_07, // 263 + S_TFOG_00, // 264 + S_TFOG_01, // 265 + S_TFOG_02, // 266 + S_TFOG_03, // 267 + S_TFOG_04, // 268 + S_TFOG_05, // 269 + S_TFOG_06, // 270 + S_TFOG_07, // 271 + S_TFOG_08, // 272 + S_TFOG_09, // 273 + S_IFOG_00, // 274 + S_IFOG_01, // 275 + S_IFOG_02, // 276 + S_IFOG_03, // 277 + S_IFOG_04, // 278 + S_IFOG_05, // 279 + S_IFOG_06, // 280 + S_SHRD_00, // 281 + S_SHRD_01, // 282 + S_SHRD_02, // 283 + S_SHRD_03, // 284 + S_SHRD_04, // 285 + S_SHRD_05, // 286 + S_PLAY_00, // 287 + S_PLAY_01, // 288 + S_PLAY_02, // 289 + S_PLAY_03, // 290 + S_PLAY_04, // 291 + S_PLAY_05, // 292 + S_PLAY_06, // 293 + S_PLAY_07, // 294 + S_PLAY_08, // 295 + S_PLAY_09, // 296 + S_PLAY_10, // 297 + S_PLAY_11, // 298 + S_PLAY_12, // 299 + S_PLAY_13, // 300 + S_PLAY_14, // 301 + S_PLAY_15, // 302 + S_PLAY_16, // 303 + S_PLAY_17, // 304 + S_PLAY_18, // 305 + S_RGIB_00, // 306 + S_RGIB_01, // 307 + S_RGIB_02, // 308 + S_RGIB_03, // 309 + S_RGIB_04, // 310 + S_RGIB_05, // 311 + S_RGIB_06, // 312 + S_RGIB_07, // 313 + S_MRYS_00, // 314 + S_MRNO_00, // 315 + S_MRNO_01, // 316 + S_MRNO_02, // 317 + S_MRNO_03, // 318 + S_MRNO_04, // 319 + S_MRST_00, // 320 + S_MRLK_00, // 321 + S_MRLK_01, // 322 + S_MRBD_00, // 323 + S_MRBD_01, // 324 + S_MRBD_02, // 325 + S_MRBD_03, // 326 + S_MRBD_04, // 327 + S_MRBD_05, // 328 + S_MRBD_06, // 329 + S_MRBD_07, // 330 + S_MRBD_08, // 331 + S_MRBD_09, // 332 + S_MRPN_00, // 333 + S_MRPN_01, // 334 + S_MRPN_02, // 335 + S_MRPN_03, // 336 + S_MRPN_04, // 337 + S_MRPN_05, // 338 + S_MRPN_06, // 339 + S_MRGT_00, // 340 + S_MRGT_01, // 341 + S_MRGT_02, // 342 + S_MRGT_03, // 343 + S_MRGT_04, // 344 + S_MRGT_05, // 345 + S_MRGT_06, // 346 + S_MRGT_07, // 347 + S_MRGT_08, // 348 + S_BURN_00, // 349 + S_BURN_01, // 350 + S_BURN_02, // 351 + S_BURN_03, // 352 + S_BURN_04, // 353 + S_BURN_05, // 354 + S_BURN_06, // 355 + S_BURN_07, // 356 + S_BURN_08, // 357 + S_BURN_09, // 358 + S_BURN_10, // 359 + S_BURN_11, // 360 + S_BURN_12, // 361 + S_BURN_13, // 362 + S_BURN_14, // 363 + S_BURN_15, // 364 + S_BURN_16, // 365 + S_BURN_17, // 366 + S_BURN_18, // 367 + S_BURN_19, // 368 + S_BURN_20, // 369 + S_BURN_21, // 370 + S_BURN_22, // 371 + S_BURN_23, // 372 + S_DISR_00, // 373 + S_DISR_01, // 374 + S_DISR_02, // 375 + S_DISR_03, // 376 + S_DISR_04, // 377 + S_DISR_05, // 378 + S_DISR_06, // 379 + S_DISR_07, // 380 + S_DISR_08, // 381 + S_DISR_09, // 382 + S_PEAS_00, // 383 + S_PEAS_01, // 384 + S_PEAS_02, // 385 + S_PEAS_03, // 386 + S_PEAS_04, // 387 + S_PEAS_05, // 388 + S_PEAS_06, // 389 + S_PEAS_07, // 390 + S_PEAS_08, // 391 + S_PEAS_09, // 392 + S_PEAS_10, // 393 + S_PEAS_11, // 394 + S_PEAS_12, // 395 + S_PEAS_13, // 396 + S_PEAS_14, // 397 + S_PEAS_15, // 398 + S_PEAS_16, // 399 + S_PEAS_17, // 400 + S_PEAS_18, // 401 + S_PEAS_19, // 402 + S_PEAS_20, // 403 + S_PEAS_21, // 404 + S_PEAS_22, // 405 + S_PEAS_23, // 406 + S_PEAS_24, // 407 + S_GIBS_00, // 408 + S_GIBS_01, // 409 + S_GIBS_02, // 410 + S_GIBS_03, // 411 + S_GIBS_04, // 412 + S_GIBS_05, // 413 + S_GIBS_06, // 414 + S_GIBS_07, // 415 + S_GIBS_08, // 416 + S_GIBS_09, // 417 + S_PEAS_25, // 418 + S_AGRD_00, // 419 + S_ARMR_00, // 420 + S_ARMR_01, // 421 + S_PLAY_19, // 422 + S_SACR_00, // 423 + S_TNK1_00, // 424 + S_TNK1_01, // 425 + S_TNK1_02, // 426 + S_TNK2_00, // 427 + S_TNK2_01, // 428 + S_TNK2_02, // 429 + S_TNK3_00, // 430 + S_TNK3_01, // 431 + S_TNK3_02, // 432 + S_TNK4_00, // 433 + S_TNK4_01, // 434 + S_TNK4_02, // 435 + S_TNK5_00, // 436 + S_TNK5_01, // 437 + S_TNK5_02, // 438 + S_TNK6_00, // 439 + S_TNK6_01, // 440 + S_TNK6_02, // 441 + S_NEAL_00, // 442 + S_NEAL_01, // 443 + S_NEAL_02, // 444 + S_NEAL_03, // 445 + S_NEAL_04, // 446 + S_NEAL_05, // 447 + S_NEAL_06, // 448 + S_NEAL_07, // 449 + S_NEAL_08, // 450 + S_NEAL_09, // 451 + S_NEAL_10, // 452 + S_NEAL_11, // 453 + S_NEAL_12, // 454 + S_NEAL_13, // 455 + S_BEGR_00, // 456 + S_BEGR_01, // 457 + S_BEGR_02, // 458 + S_BEGR_03, // 459 + S_BEGR_04, // 460 + S_BEGR_05, // 461 + S_BEGR_06, // 462 + S_BEGR_07, // 463 + S_BEGR_08, // 464 + S_BEGR_09, // 465 + S_BEGR_10, // 466 + S_BEGR_11, // 467 + S_BEGR_12, // 468 + S_BEGR_13, // 469 + S_BEGR_14, // 470 + S_BEGR_15, // 471 + S_BEGR_16, // 472 + S_BEGR_17, // 473 + S_BEGR_18, // 474 + S_BEGR_19, // 475 + S_BEGR_20, // 476 + S_BEGR_21, // 477 + S_BEGR_22, // 478 + S_HMN1_00, // 479 + S_HMN1_01, // 480 + S_HMN1_02, // 481 + S_HMN1_03, // 482 + S_HMN1_04, // 483 + S_HMN1_05, // 484 + S_HMN1_06, // 485 + S_HMN1_07, // 486 + S_HMN1_08, // 487 + S_HMN1_09, // 488 + S_HMN1_10, // 489 + S_HMN1_11, // 490 + S_HMN1_12, // 491 + S_HMN1_13, // 492 + S_HMN1_14, // 493 + S_HMN1_15, // 494 + S_HMN1_16, // 495 + S_HMN1_17, // 496 + S_HMN1_18, // 497 + S_HMN1_19, // 498 + S_HMN1_20, // 499 + S_HMN1_21, // 500 + S_HMN1_22, // 501 + S_HMN1_23, // 502 + S_HMN1_24, // 503 + S_HMN1_25, // 504 + S_HMN1_26, // 505 + S_HMN1_27, // 506 + S_HMN1_28, // 507 + S_HMN1_29, // 508 + S_HMN1_30, // 509 + S_HMN1_31, // 510 + S_RGIB_08, // 511 + S_RGIB_09, // 512 + S_RGIB_10, // 513 + S_RGIB_11, // 514 + S_RGIB_12, // 515 + S_RGIB_13, // 516 + S_RGIB_14, // 517 + S_RGIB_15, // 518 + S_LEDR_00, // 519 + S_LEDR_01, // 520 + S_LEDR_02, // 521 + S_LEAD_00, // 522 + S_LEAD_01, // 523 + S_LEAD_02, // 524 + S_LEAD_03, // 525 + S_LEAD_04, // 526 + S_LEAD_05, // 527 + S_LEAD_06, // 528 + S_LEAD_07, // 529 + S_LEAD_08, // 530 + S_LEAD_09, // 531 + S_LEAD_10, // 532 + S_LEAD_11, // 533 + S_LEAD_12, // 534 + S_LEAD_13, // 535 + S_LEAD_14, // 536 + S_LEAD_15, // 537 + S_LEAD_16, // 538 + S_LEAD_17, // 539 + S_LEAD_18, // 540 + S_LEAD_19, // 541 + S_LEAD_20, // 542 + S_LEAD_21, // 543 + S_LEAD_22, // 544 + S_LEAD_23, // 545 + S_LEAD_24, // 546 + S_LEAD_25, // 547 + S_LEAD_26, // 548 + S_LEAD_27, // 549 + S_LEAD_28, // 550 + S_LEAD_29, // 551 + S_LEAD_30, // 552 + S_LEAD_31, // 553 + S_LEAD_32, // 554 + S_LEAD_33, // 555 + S_LEAD_34, // 556 + S_LEAD_35, // 557 + S_LEAD_36, // 558 + S_LEAD_37, // 559 + S_PUFY_04, // 560 + S_PUFY_05, // 561 + S_PUFY_06, // 562 + S_PUFY_07, // 563 + S_PUFY_08, // 564 + S_MICR_01, // 565 + S_MICR_02, // 566 + S_ROB1_00, // 567 + S_ROB1_01, // 568 + S_ROB1_02, // 569 + S_ROB1_03, // 570 + S_ROB1_04, // 571 + S_ROB1_05, // 572 + S_ROB1_06, // 573 + S_ROB1_07, // 574 + S_ROB1_08, // 575 + S_ROB1_09, // 576 + S_ROB1_10, // 577 + S_ROB1_11, // 578 + S_ROB1_12, // 579 + S_ROB1_13, // 580 + S_ROB1_14, // 581 + S_ROB1_15, // 582 + S_ROB1_16, // 583 + S_ROB1_17, // 584 + S_ROB1_18, // 585 + S_ROB1_19, // 586 + S_ROB1_20, // 587 + S_ROB1_21, // 588 + S_ROB1_22, // 589 + S_ROB1_23, // 590 + S_ROB1_24, // 591 + S_ROB1_25, // 592 + S_ROB1_26, // 593 + S_ROB1_27, // 594 + S_ROB1_28, // 595 + S_ROB1_29, // 596 + S_ROB1_30, // 597 + S_ROB1_31, // 598 + S_ROB1_32, // 599 + S_AGRD_01, // 600 + S_AGRD_02, // 601 + S_AGRD_03, // 602 + S_AGRD_04, // 603 + S_AGRD_05, // 604 + S_AGRD_06, // 605 + S_AGRD_07, // 606 + S_AGRD_08, // 607 + S_AGRD_09, // 608 + S_AGRD_10, // 609 + S_AGRD_11, // 610 + S_AGRD_12, // 611 + S_AGRD_13, // 612 + S_AGRD_14, // 613 + S_AGRD_15, // 614 + S_AGRD_16, // 615 + S_AGRD_17, // 616 + S_AGRD_18, // 617 + S_AGRD_19, // 618 + S_AGRD_20, // 619 + S_AGRD_21, // 620 + S_AGRD_22, // 621 + S_AGRD_23, // 622 + S_AGRD_24, // 623 + S_AGRD_25, // 624 + S_AGRD_26, // 625 + S_AGRD_27, // 626 + S_AGRD_28, // 627 + S_AGRD_29, // 628 + S_AGRD_30, // 629 + S_AGRD_31, // 630 + S_GIBS_10, // 631 + S_GIBS_11, // 632 + S_GIBS_12, // 633 + S_GIBS_13, // 634 + S_GIBS_14, // 635 + S_GIBS_15, // 636 + S_GIBS_16, // 637 + S_GIBS_17, // 638 + S_GIBS_18, // 639 + S_GIBS_19, // 640 + S_GIBS_20, // 641 + S_GIBS_21, // 642 + S_PGRD_00, // 643 + S_PGRD_01, // 644 + S_PGRD_02, // 645 + S_PGRD_03, // 646 + S_PGRD_04, // 647 + S_PGRD_05, // 648 + S_PGRD_06, // 649 + S_PGRD_07, // 650 + S_PGRD_08, // 651 + S_PGRD_09, // 652 + S_PGRD_10, // 653 + S_PGRD_11, // 654 + S_PGRD_12, // 655 + S_PGRD_13, // 656 + S_PGRD_14, // 657 + S_PGRD_15, // 658 + S_PGRD_16, // 659 + S_PGRD_17, // 660 + S_PGRD_18, // 661 + S_PGRD_19, // 662 + S_PGRD_20, // 663 + S_PGRD_21, // 664 + S_PGRD_22, // 665 + S_PGRD_23, // 666 + S_PGRD_24, // 667 + S_PGRD_25, // 668 + S_PGRD_26, // 669 + S_PGRD_27, // 670 + S_PGRD_28, // 671 + S_PGRD_29, // 672 + S_PGRD_30, // 673 + S_PGRD_31, // 674 + S_PGRD_32, // 675 + S_PGRD_33, // 676 + S_PGRD_34, // 677 + S_PGRD_35, // 678 + S_PGRD_36, // 679 + S_PGRD_37, // 680 + S_ROB2_00, // 681 + S_ROB2_01, // 682 + S_ROB2_02, // 683 + S_ROB2_03, // 684 + S_ROB2_04, // 685 + S_ROB2_05, // 686 + S_ROB2_06, // 687 + S_ROB2_07, // 688 + S_ROB2_08, // 689 + S_ROB2_09, // 690 + S_ROB2_10, // 691 + S_ROB2_11, // 692 + S_ROB2_12, // 693 + S_ROB2_13, // 694 + S_ROB2_14, // 695 + S_ROB2_15, // 696 + S_ROB2_16, // 697 + S_ROB2_17, // 698 + S_ROB2_18, // 699 + S_ROB2_19, // 700 + S_ROB2_20, // 701 + S_ROB2_21, // 702 + S_ROB2_22, // 703 + S_ROB2_23, // 704 + S_ROB2_24, // 705 + S_ROB2_25, // 706 + S_ROB2_26, // 707 + S_ROB2_27, // 708 + S_ROB2_28, // 709 + S_ROB2_29, // 710 + S_MLDR_00, // 711 + S_MLDR_01, // 712 + S_MLDR_02, // 713 + S_MLDR_03, // 714 + S_MLDR_04, // 715 + S_MLDR_05, // 716 + S_MLDR_06, // 717 + S_MLDR_07, // 718 + S_MLDR_08, // 719 + S_MLDR_09, // 720 + S_MLDR_10, // 721 + S_MLDR_11, // 722 + S_MLDR_12, // 723 + S_MLDR_13, // 724 + S_MLDR_14, // 725 + S_MLDR_15, // 726 + S_MLDR_16, // 727 + S_MLDR_17, // 728 + S_MLDR_18, // 729 + S_MLDR_19, // 730 + S_MLDR_20, // 731 + S_MLDR_21, // 732 + S_MLDR_22, // 733 + S_MLDR_23, // 734 + S_MLDR_24, // 735 + S_MLDR_25, // 736 + S_MLDR_26, // 737 + S_MLDR_27, // 738 + S_ORCL_00, // 739 + S_ORCL_01, // 740 + S_ORCL_02, // 741 + S_ORCL_03, // 742 + S_ORCL_04, // 743 + S_ORCL_05, // 744 + S_ORCL_06, // 745 + S_ORCL_07, // 746 + S_ORCL_08, // 747 + S_ORCL_09, // 748 + S_ORCL_10, // 749 + S_ORCL_11, // 750 + S_ORCL_12, // 751 + S_ORCL_13, // 752 + S_ORCL_14, // 753 + S_ORCL_15, // 754 + S_ORCL_16, // 755 + S_PRST_00, // 756 + S_PRST_01, // 757 + S_PRST_02, // 758 + S_PRST_03, // 759 + S_PRST_04, // 760 + S_PRST_05, // 761 + S_PRST_06, // 762 + S_PRST_07, // 763 + S_PRST_08, // 764 + S_PRST_09, // 765 + S_PRST_10, // 766 + S_PRST_11, // 767 + S_PRST_12, // 768 + S_PRST_13, // 769 + S_PRST_14, // 770 + S_PRST_15, // 771 + S_PDED_00, // 772 + S_PDED_01, // 773 + S_PDED_02, // 774 + S_PDED_03, // 775 + S_PDED_04, // 776 + S_PDED_05, // 777 + S_PDED_06, // 778 + S_PDED_07, // 779 + S_PDED_08, // 780 + S_PDED_09, // 781 + S_PDED_10, // 782 + S_PDED_11, // 783 + S_PDED_12, // 784 + S_PDED_13, // 785 + S_PDED_14, // 786 + S_PDED_15, // 787 + S_PDED_16, // 788 + S_PDED_17, // 789 + S_PDED_18, // 790 + S_PDED_19, // 791 + S_PDED_20, // 792 + S_PDED_21, // 793 + S_PDED_22, // 794 + S_PDED_23, // 795 + S_ALN1_00, // 796 + S_ALN1_01, // 797 + S_ALN1_02, // 798 + S_ALN1_03, // 799 + S_ALN1_04, // 800 + S_ALN1_05, // 801 + S_ALN1_06, // 802 + S_ALN1_07, // 803 + S_ALN1_08, // 804 + S_ALN1_09, // 805 + S_ALN1_10, // 806 + S_ALN1_11, // 807 + S_ALN1_12, // 808 + S_ALN1_13, // 809 + S_ALN1_14, // 810 + S_ALN1_15, // 811 + S_ALN1_16, // 812 + S_ALN1_17, // 813 + S_ALN1_18, // 814 + S_ALN1_19, // 815 + S_AL1P_00, // 816 + S_AL1P_01, // 817 + S_AL1P_02, // 818 + S_AL1P_03, // 819 + S_AL1P_04, // 820 + S_AL1P_05, // 821 + S_AL1P_06, // 822 + S_AL1P_07, // 823 + S_AL1P_08, // 824 + S_AL1P_09, // 825 + S_AL1P_10, // 826 + S_AL1P_11, // 827 + S_AL1P_12, // 828 + S_AL1P_13, // 829 + S_AL1P_14, // 830 + S_AL1P_15, // 831 + S_AL1P_16, // 832 + S_AL1P_17, // 833 + S_NODE_00, // 834 + S_NODE_01, // 835 + S_NODE_02, // 836 + S_NODE_03, // 837 + S_NODE_04, // 838 + S_NODE_05, // 839 + S_NODE_06, // 840 + S_MTHD_00, // 841 + S_MTHD_01, // 842 + S_MTHD_02, // 843 + S_MTHD_03, // 844 + S_MTHD_04, // 845 + S_MTHD_05, // 846 + S_MTHD_06, // 847 + S_MTHD_07, // 848 + S_MTHD_08, // 849 + S_MTHD_09, // 850 + S_MTHD_10, // 851 + S_ALN1_20, // 852 + S_ALN1_21, // 853 + S_ALN1_22, // 854 + S_ALN1_23, // 855 + S_ALN1_24, // 856 + S_ALN1_25, // 857 + S_ALN1_26, // 858 + S_ALN1_27, // 859 + S_ALN1_28, // 860 + S_ALN1_29, // 861 + S_ALN1_30, // 862 + S_ALN1_31, // 863 + S_ALN1_32, // 864 + S_ALN1_33, // 865 + S_ALN1_34, // 866 + S_ALN1_35, // 867 + S_ALN1_36, // 868 + S_ALN1_37, // 869 + S_ALN1_38, // 870 + S_ALN1_39, // 871 + S_ALN1_40, // 872 + S_ALN1_41, // 873 + S_ALN1_42, // 874 + S_ALN1_43, // 875 + S_ALN1_44, // 876 + S_ALN1_45, // 877 + S_ALN1_46, // 878 + S_ALN1_47, // 879 + S_ALN1_48, // 880 + S_ALN1_49, // 881 + S_ALN1_50, // 882 + S_ALN1_51, // 883 + S_ALN1_52, // 884 + S_ALN1_53, // 885 + S_ALN1_54, // 886 + S_ALN1_55, // 887 + S_ALN1_56, // 888 + S_ALN1_57, // 889 + S_MNAM_00, // 890 + S_MNAM_01, // 891 + S_MNAM_02, // 892 + S_MNAM_03, // 893 + S_MNAM_04, // 894 + S_MNAM_05, // 895 + S_MNAM_06, // 896 + S_MNAM_07, // 897 + S_MNAM_08, // 898 + S_MNAM_09, // 899 + S_MNAM_10, // 900 + S_MNAM_11, // 901 + S_MNAL_00, // 902 + S_MNAL_01, // 903 + S_MNAL_02, // 904 + S_MNAL_03, // 905 + S_MNAL_04, // 906 + S_MNAL_05, // 907 + S_MNAL_06, // 908 + S_MNAL_07, // 909 + S_MNAL_08, // 910 + S_MNAL_09, // 911 + S_MNAL_10, // 912 + S_MNAL_11, // 913 + S_MNAL_12, // 914 + S_MNAL_13, // 915 + S_MNAL_14, // 916 + S_MNAL_15, // 917 + S_MNAL_16, // 918 + S_MNAL_17, // 919 + S_MNAL_18, // 920 + S_MNAL_19, // 921 + S_MNAL_20, // 922 + S_MNAL_21, // 923 + S_MNAL_22, // 924 + S_MNAL_23, // 925 + S_MNAL_24, // 926 + S_MNAL_25, // 927 + S_MNAL_26, // 928 + S_MNAL_27, // 929 + S_MNAL_28, // 930 + S_MNAL_29, // 931 + S_MNAL_30, // 932 + S_MNAL_31, // 933 + S_MNAL_32, // 934 + S_MNAL_33, // 935 + S_MNAL_34, // 936 + S_MNAL_35, // 937 + S_MNAL_36, // 938 + S_MNAL_37, // 939 + S_MNAL_38, // 940 + S_MNAL_39, // 941 + S_MNAL_40, // 942 + S_MDTH_00, // 943 + S_MDTH_01, // 944 + S_MDTH_02, // 945 + S_MDTH_03, // 946 + S_MDTH_04, // 947 + S_MDTH_05, // 948 + S_MDTH_06, // 949 + S_MDTH_07, // 950 + S_MDTH_08, // 951 + S_MDTH_09, // 952 + S_MDTH_10, // 953 + S_MDTH_11, // 954 + S_MDTH_12, // 955 + S_MDTH_13, // 956 + S_MDTH_14, // 957 + S_NEST_00, // 958 + S_PODD_00, // 959 + S_PODD_01, // 960 + S_PODD_02, // 961 + S_PODD_03, // 962 + S_PODD_04, // 963 + S_PODD_05, // 964 + S_ZAP6_00, // 965 + S_ZAP6_01, // 966 + S_ZAP6_02, // 967 + S_ZOT3_00, // 968 + S_ZOT3_01, // 969 + S_ZOT3_02, // 970 + S_ZOT3_03, // 971 + S_ZOT3_04, // 972 + S_ZAP6_03, // 973 + S_ZAP6_04, // 974 + S_ZAP6_05, // 975 + S_ZAP7_00, // 976 + S_ZAP7_01, // 977 + S_ZAP7_02, // 978 + S_ZAP7_03, // 979 + S_ZAP7_04, // 980 + S_ZOT1_00, // 981 + S_ZOT1_01, // 982 + S_ZOT1_02, // 983 + S_ZOT1_03, // 984 + S_ZOT1_04, // 985 + S_ZAP5_00, // 986 + S_ZAP5_01, // 987 + S_ZAP5_02, // 988 + S_ZAP5_03, // 989 + S_ZOT2_00, // 990 + S_ZOT2_01, // 991 + S_ZOT2_02, // 992 + S_ZOT2_03, // 993 + S_ZOT2_04, // 994 + S_SEWR_00, // 995 + S_SEWR_01, // 996 + S_SEWR_02, // 997 + S_SEWR_03, // 998 + S_SEWR_04, // 999 + S_SEWR_05, // 1000 + S_SEWR_06, // 1001 + S_SEWR_07, // 1002 + S_SEWR_08, // 1003 + S_SEWR_09, // 1004 + S_SEWR_10, // 1005 + S_SEWR_11, // 1006 + S_SEWR_12, // 1007 + S_SEWR_13, // 1008 + S_SPID_00, // 1009 + S_SPID_01, // 1010 + S_SPID_02, // 1011 + S_SPID_03, // 1012 + S_SPID_04, // 1013 + S_SPID_05, // 1014 + S_SPID_06, // 1015 + S_SPID_07, // 1016 + S_SPID_08, // 1017 + S_SPID_09, // 1018 + S_SPID_10, // 1019 + S_SPID_11, // 1020 + S_SPID_12, // 1021 + S_SPID_13, // 1022 + S_SPID_14, // 1023 + S_SPID_15, // 1024 + S_SPID_16, // 1025 + S_SPID_17, // 1026 + S_SPID_18, // 1027 + S_SPID_19, // 1028 + S_SPID_20, // 1029 + S_SPID_21, // 1030 + S_SPID_22, // 1031 + S_SPID_23, // 1032 + S_SPID_24, // 1033 + S_SPID_25, // 1034 + S_SPID_26, // 1035 + S_SPID_27, // 1036 + S_SPID_28, // 1037 + S_SPID_29, // 1038 + S_SPID_30, // 1039 + S_SPID_31, // 1040 + S_SPID_32, // 1041 + S_SPID_33, // 1042 + S_SPID_34, // 1043 + S_SPID_35, // 1044 + S_SPID_36, // 1045 + S_SPID_37, // 1046 + S_ROB3_00, // 1047 + S_ROB3_01, // 1048 + S_ROB3_02, // 1049 + S_ROB3_03, // 1050 + S_ROB3_04, // 1051 + S_ROB3_05, // 1052 + S_ROB3_06, // 1053 + S_ROB3_07, // 1054 + S_ROB3_08, // 1055 + S_ROB3_09, // 1056 + S_ROB3_10, // 1057 + S_ROB3_11, // 1058 + S_ROB3_12, // 1059 + S_ROB3_13, // 1060 + S_ROB3_14, // 1061 + S_ROB3_15, // 1062 + S_ROB3_16, // 1063 + S_ROB3_17, // 1064 + S_ROB3_18, // 1065 + S_ROB3_19, // 1066 + S_ROB3_20, // 1067 + S_ROB3_21, // 1068 + S_ROB3_22, // 1069 + S_ROB3_23, // 1070 + S_ROB3_24, // 1071 + S_ROB3_25, // 1072 + S_ROB3_26, // 1073 + S_ROB3_27, // 1074 + S_ROB3_28, // 1075 + S_ROB3_29, // 1076 + S_ROB3_30, // 1077 + S_ROB3_31, // 1078 + S_ROB3_32, // 1079 + S_ROB3_33, // 1080 + S_ROB3_34, // 1081 + S_ROB3_35, // 1082 + S_ROB3_36, // 1083 + S_ROB3_37, // 1084 + S_RBB3_00, // 1085 + S_RBB3_01, // 1086 + S_RBB3_02, // 1087 + S_RBB3_03, // 1088 + S_RBB3_04, // 1089 + S_RBB3_05, // 1090 + S_RBB3_06, // 1091 + S_RBB3_07, // 1092 + S_PRGR_00, // 1093 + S_PRGR_01, // 1094 + S_PRGR_02, // 1095 + S_PRGR_03, // 1096 + S_PRGR_04, // 1097 + S_PRGR_05, // 1098 + S_PRGR_06, // 1099 + S_PRGR_07, // 1100 + S_PRGR_08, // 1101 + S_PRGR_09, // 1102 + S_PRGR_10, // 1103 + S_PRGR_11, // 1104 + S_PRGR_12, // 1105 + S_PRGR_13, // 1106 + S_PRGR_14, // 1107 + S_PRGR_15, // 1108 + S_PRGR_16, // 1109 + S_PRGR_17, // 1110 + S_PRGR_18, // 1111 + S_PRGR_19, // 1112 + S_PRGR_20, // 1113 + S_PRGR_21, // 1114 + S_PRGR_22, // 1115 + S_PRGR_23, // 1116 + S_PRGR_24, // 1117 + S_PRGR_25, // 1118 + S_PRGR_26, // 1119 + S_PRGR_27, // 1120 + S_PRGR_28, // 1121 + S_PRGR_29, // 1122 + S_PRGR_30, // 1123 + S_PRGR_31, // 1124 + S_PRGR_32, // 1125 + S_PRGR_33, // 1126 + S_BASE_00, // 1127 + S_BASE_01, // 1128 + S_BASE_02, // 1129 + S_BASE_03, // 1130 + S_BASE_04, // 1131 + S_BASE_05, // 1132 + S_BASE_06, // 1133 + S_BASE_07, // 1134 + S_FRBL_00, // 1135 + S_FRBL_01, // 1136 + S_FRBL_02, // 1137 + S_FRBL_03, // 1138 + S_FRBL_04, // 1139 + S_FRBL_05, // 1140 + S_FRBL_06, // 1141 + S_FRBL_07, // 1142 + S_FRBL_08, // 1143 + S_KLAX_00, // 1144 + S_KLAX_01, // 1145 + S_KLAX_02, // 1146 + S_TURT_00, // 1147 + S_TURT_01, // 1148 + S_TURT_02, // 1149 + S_TURT_03, // 1150 + S_TURT_04, // 1151 + S_BALL_00, // 1152 + S_BALL_01, // 1153 + S_BALL_02, // 1154 + S_BALL_03, // 1155 + S_BALL_04, // 1156 + S_TURT_05, // 1157 + S_PSTN_00, // 1158 + S_PSTN_01, // 1159 + S_PSTN_02, // 1160 + S_PSTN_03, // 1161 + S_PSTN_04, // 1162 + S_PSTN_05, // 1163 + S_PSTN_06, // 1164 + S_PSTN_07, // 1165 + S_PSTN_08, // 1166 + S_PSTN_09, // 1167 + S_PSTN_10, // 1168 + S_SECR_00, // 1169 + S_SECR_01, // 1170 + S_SECR_02, // 1171 + S_SECR_03, // 1172 + S_SECR_04, // 1173 + S_SECR_05, // 1174 + S_SECR_06, // 1175 + S_SECR_07, // 1176 + S_SECR_08, // 1177 + S_SECR_09, // 1178 + S_SECR_10, // 1179 + S_SECR_11, // 1180 + S_SECR_12, // 1181 + S_SECR_13, // 1182 + S_SECR_14, // 1183 + S_SECR_15, // 1184 + S_XPRK_01, // 1185 + S_XPRK_02, // 1186 + S_TARG_00, // 1187 + S_RING_00, // 1188 + S_EARS_00, // 1189 + S_COMM_00, // 1190 + S_BOOM_00, // 1191 + S_BOOM_01, // 1192 + S_BOOM_02, // 1193 + S_BOOM_03, // 1194 + S_BOOM_04, // 1195 + S_BOOM_05, // 1196 + S_BOOM_06, // 1197 + S_BOOM_07, // 1198 + S_BOOM_08, // 1199 + S_BOOM_09, // 1200 + S_BOOM_10, // 1201 + S_BOOM_11, // 1202 + S_BOOM_12, // 1203 + S_BOOM_13, // 1204 + S_BOOM_14, // 1205 + S_BOOM_15, // 1206 + S_BOOM_16, // 1207 + S_BOOM_17, // 1208 + S_BOOM_18, // 1209 + S_BOOM_19, // 1210 + S_BOOM_20, // 1211 + S_BOOM_21, // 1212 + S_BOOM_22, // 1213 + S_BOOM_23, // 1214 + S_BOOM_24, // 1215 + S_RATT_00, // 1216 + S_RATT_01, // 1217 + S_RATT_02, // 1218 + S_RATT_03, // 1219 + S_RATT_04, // 1220 + S_RATT_05, // 1221 + S_RATT_06, // 1222 + S_HOGN_00, // 1223 + S_HOGN_01, // 1224 + S_HOGN_02, // 1225 + S_DEAD_00, // 1226 + S_SBAN_00, // 1227 + S_BOTR_00, // 1228 + S_HATR_00, // 1229 + S_TOPR_00, // 1230 + S_COUP_00, // 1231 + S_COUP_01, // 1232 + S_COUP_02, // 1233 + S_BUBB_00, // 1234 + S_BUBF_00, // 1235 + S_BUBC_00, // 1236 + S_ASPR_00, // 1237 + S_SPDL_00, // 1238 + S_SPDL_01, // 1239 + S_SPDL_02, // 1240 + S_TOKN_00, // 1241 + S_OTOK_00, // 1242 + S_HELT_00, // 1243 + S_GUNT_00, // 1244 + S_FULL_00, // 1245 + S_FULL_01, // 1246 + S_MEAT_00, // 1247 + S_MEAT_01, // 1248 + S_MEAT_02, // 1249 + S_MEAT_03, // 1250 + S_MEAT_04, // 1251 + S_MEAT_05, // 1252 + S_MEAT_06, // 1253 + S_MEAT_07, // 1254 + S_MEAT_08, // 1255 + S_MEAT_09, // 1256 + S_MEAT_10, // 1257 + S_MEAT_11, // 1258 + S_MEAT_12, // 1259 + S_MEAT_13, // 1260 + S_MEAT_14, // 1261 + S_MEAT_15, // 1262 + S_MEAT_16, // 1263 + S_MEAT_17, // 1264 + S_MEAT_18, // 1265 + S_MEAT_19, // 1266 + S_JUNK_00, // 1267 + S_JUNK_01, // 1268 + S_JUNK_02, // 1269 + S_JUNK_03, // 1270 + S_JUNK_04, // 1271 + S_JUNK_05, // 1272 + S_JUNK_06, // 1273 + S_JUNK_07, // 1274 + S_JUNK_08, // 1275 + S_JUNK_09, // 1276 + S_JUNK_10, // 1277 + S_JUNK_11, // 1278 + S_JUNK_12, // 1279 + S_JUNK_13, // 1280 + S_JUNK_14, // 1281 + S_JUNK_15, // 1282 + S_JUNK_16, // 1283 + S_JUNK_17, // 1284 + S_JUNK_18, // 1285 + S_JUNK_19, // 1286 + S_FFOT_00, // 1287 + S_FFOT_01, // 1288 + S_FFOT_02, // 1289 + S_FFOT_03, // 1290 + S_DIE1_00, // 1291 + S_BEAC_00, // 1292 + S_BEAC_01, // 1293 + S_BEAC_02, // 1294 + S_ARM1_00, // 1295 + S_ARM2_00, // 1296 + S_BARW_00, // 1297 + S_BARW_01, // 1298 + S_BARW_02, // 1299 + S_BARW_03, // 1300 + S_BARW_04, // 1301 + S_BARW_05, // 1302 + S_BARW_06, // 1303 + S_BARW_07, // 1304 + S_BART_00, // 1305 + S_BART_01, // 1306 + S_BART_02, // 1307 + S_BART_03, // 1308 + S_BART_04, // 1309 + S_BART_05, // 1310 + S_BART_06, // 1311 + S_BART_07, // 1312 + S_BART_08, // 1313 + S_BART_09, // 1314 + S_BART_10, // 1315 + S_BART_11, // 1316 + S_LAMP_00, // 1317 + S_LANT_00, // 1318 + S_BARL_00, // 1319 + S_BARL_01, // 1320 + S_BARL_02, // 1321 + S_BARL_03, // 1322 + S_BOWL_00, // 1323 + S_BOWL_01, // 1324 + S_BOWL_02, // 1325 + S_BOWL_03, // 1326 + S_BRAZ_00, // 1327 + S_BRAZ_01, // 1328 + S_BRAZ_02, // 1329 + S_BRAZ_03, // 1330 + S_TRCH_00, // 1331 + S_TRCH_01, // 1332 + S_TRCH_02, // 1333 + S_TRCH_03, // 1334 + S_LTRH_00, // 1335 + S_LTRH_01, // 1336 + S_LTRH_02, // 1337 + S_LTRH_03, // 1338 + S_LMPC_00, // 1339 + S_LMPC_01, // 1340 + S_LMPC_02, // 1341 + S_LMPC_03, // 1342 + S_LOGS_00, // 1343 + S_LOGS_01, // 1344 + S_LOGS_02, // 1345 + S_LOGS_03, // 1346 + S_TRHO_00, // 1347 + S_WATR_00, // 1348 + S_MUGG_00, // 1349 + S_FUSL_00, // 1350 + S_CRD1_00, // 1351 + S_CRD2_00, // 1352 + S_TPAS_00, // 1353 + S_KY1G_00, // 1354 + S_KY2S_00, // 1355 + S_KY3B_00, // 1356 + S_HAND_00, // 1357 + S_CRYS_00, // 1358 + S_CRYS_01, // 1359 + S_CRYS_02, // 1360 + S_CRYS_03, // 1361 + S_CRYS_04, // 1362 + S_CRYS_05, // 1363 + S_PRIS_00, // 1364 + S_PWR1_00, // 1365 + S_PWR2_00, // 1366 + S_PWR3_00, // 1367 + S_ORAC_00, // 1368 + S_GYID_00, // 1369 + S_FUBR_00, // 1370 + S_WARE_00, // 1371 + S_RCRY_00, // 1372 + S_BCRY_00, // 1373 + S_CHAP_00, // 1374 + S_TUNL_00, // 1375 + S_BLTK_00, // 1376 + S_SECK_00, // 1377 + S_MINE_00, // 1378 + S_REBL_00, // 1379 + S_PROC_00, // 1380 + S_ANKH_00, // 1381 + S_GOID_00, // 1382 + S_STMP_00, // 1383 + S_MDKT_00, // 1384 + S_COIN_00, // 1385 + S_CRED_00, // 1386 + S_SACK_00, // 1387 + S_CHST_00, // 1388 + S_SHD1_00, // 1389 + S_SHD1_01, // 1390 + S_SHD1_02, // 1391 + S_SHD1_03, // 1392 + S_MASK_00, // 1393 + S_UNIF_00, // 1394 + S_OFIC_00, // 1395 + S_PMAP_00, // 1396 + S_PMAP_01, // 1397 + S_PMUP_00, // 1398 + S_PMUP_01, // 1399 + S_BLIT_00, // 1400 + S_BBOX_00, // 1401 + S_MSSL_00, // 1402 + S_ROKT_00, // 1403 + S_BRY1_00, // 1404 + S_BRY1_01, // 1405 + S_CPAC_00, // 1406 + S_CPAC_01, // 1407 + S_PQRL_00, // 1408 + S_XQRL_00, // 1409 + S_GRN1_00, // 1410 + S_GRN2_00, // 1411 + S_BKPK_00, // 1412 + S_RELC_00, // 1413 + S_RIFL_00, // 1414 + S_RIFL_01, // 1415 + S_FLAM_00, // 1416 + S_BFLM_00, // 1417 + S_MMSL_00, // 1418 + S_TRPD_00, // 1419 + S_GRND_00, // 1420 + S_CBOW_00, // 1421 + S_SIGL_00, // 1422 + S_SIGL_01, // 1423 + S_SIGL_02, // 1424 + S_SIGL_03, // 1425 + S_SIGL_04, // 1426 + S_LITE_00, // 1427 + S_CNDL_00, // 1428 + S_CLBR_00, // 1429 + S_LITS_00, // 1430 + S_LITB_00, // 1431 + S_LITG_00, // 1432 + S_ROK1_00, // 1433 + S_ROK2_00, // 1434 + S_ROK3_00, // 1435 + S_ROK4_00, // 1436 + S_LOGG_00, // 1437 + S_LOGG_01, // 1438 + S_LOGG_02, // 1439 + S_LOGG_03, // 1440 + S_RUB1_00, // 1441 + S_RUB2_00, // 1442 + S_RUB3_00, // 1443 + S_RUB4_00, // 1444 + S_RUB5_00, // 1445 + S_RUB6_00, // 1446 + S_RUB7_00, // 1447 + S_RUB8_00, // 1448 + S_CHAN_00, // 1449 + S_STAT_00, // 1450 + S_DSTA_00, // 1451 + S_CRAB_00, // 1452 + S_CAGE_00, // 1453 + S_TREE_00, // 1454 + S_TREE_01, // 1455 + S_TREE_02, // 1456 + S_TRE1_00, // 1457 + S_BUSH_00, // 1458 + S_SHRB_00, // 1459 + S_STAK_00, // 1460 + S_BAR1_00, // 1461 + S_VASE_00, // 1462 + S_VASE_01, // 1463 + S_STOL_00, // 1464 + S_POT1_00, // 1465 + S_TUB1_00, // 1466 + S_ANVL_00, // 1467 + S_TLMP_00, // 1468 + S_TLMP_01, // 1469 + S_TRAY_00, // 1470 + S_APOW_00, // 1471 + S_AFED_00, // 1472 + S_DRIP_00, // 1473 + S_DRIP_01, // 1474 + S_DRIP_02, // 1475 + S_DRIP_03, // 1476 + S_DRIP_04, // 1477 + S_DRIP_05, // 1478 + S_DRIP_06, // 1479 + S_DRIP_07, // 1480 + S_CDRP_00, // 1481 + S_CDRP_01, // 1482 + S_CDRP_02, // 1483 + S_CDRP_03, // 1484 + S_SPLH_00, // 1485 + S_SPLH_01, // 1486 + S_SPLH_02, // 1487 + S_SPLH_03, // 1488 + S_SPLH_04, // 1489 + S_SPLH_05, // 1490 + S_SPLH_06, // 1491 + S_SPLH_07, // 1492 + S_WTFT_00, // 1493 + S_WTFT_01, // 1494 + S_WTFT_02, // 1495 + S_WTFT_03, // 1496 + S_HERT_00, // 1497 + S_HERT_01, // 1498 + S_HERT_02, // 1499 + S_TELP_00, // 1500 + S_TELP_01, // 1501 + S_TELP_02, // 1502 + S_TELP_03, // 1503 + S_MONI_00, // 1504 + S_STEL_00, // 1505 + S_STLA_00, // 1506 + S_STLE_00, // 1507 + S_HUGE_00, // 1508 + S_HUGE_01, // 1509 + S_HUGE_02, // 1510 + S_HUGE_03, // 1511 + S_STLG_00, // 1512 + S_STLG_01, // 1513 + S_STLG_02, // 1514 + S_STLG_03, // 1515 + S_STLG_04, // 1516 + S_STLG_05, // 1517 + NUMSTATES + +} statenum_t; + + +typedef struct +{ + spritenum_t sprite; + int frame; + int tics; + // void (*action) (); + actionf_t action; + statenum_t nextstate; + //int misc1; // villsa [STRIFE] unused + //int misc2; // villsa [STRIFE] unused +} state_t; + +extern state_t states[NUMSTATES]; +extern const char *sprnames[]; + +typedef enum +{ + MT_FIELDGUARD, //000 + MT_PLAYER, //001 + MT_SHOPKEEPER_W, //002 + MT_SHOPKEEPER_B, //003 + MT_SHOPKEEPER_A, //004 + MT_SHOPKEEPER_M, //005 + MT_PEASANT2_A, //006 + MT_PEASANT2_B, //007 + MT_PEASANT2_C, //008 + MT_PEASANT5_A, //009 + MT_PEASANT5_B, //010 + MT_PEASANT5_C, //011 + MT_PEASANT4_A, //012 + MT_PEASANT4_B, //013 + MT_PEASANT4_C, //014 + MT_PEASANT6_A, //015 + MT_PEASANT6_B, //016 + MT_PEASANT6_C, //017 + MT_PEASANT3_A, //018 + MT_PEASANT3_B, //019 + MT_PEASANT3_C, //020 + MT_PEASANT8_A, //021 + MT_PEASANT8_B, //022 + MT_PEASANT8_C, //023 + MT_PEASANT7_A, //024 + MT_PEASANT7_B, //025 + MT_PEASANT7_C, //026 + MT_PEASANT1, //027 + MT_ZOMBIE, //028 + MT_BECOMING, //029 + MT_ZOMBIESPAWNER, //030 + MT_HUGE_TANK_1, //031 + MT_HUGE_TANK_2, //032 + MT_HUGE_TANK_3, //033 + MT_TANK_4, //034 + MT_TANK_5, //035 + MT_TANK_6, //036 + MT_KNEELING_GUY, //037 + MT_BEGGAR1, //038 + MT_BEGGAR2, //039 + MT_BEGGAR3, //040 + MT_BEGGAR4, //041 + MT_BEGGAR5, //042 + MT_REBEL1, //043 + MT_REBEL2, //044 + MT_REBEL3, //045 + MT_REBEL4, //046 + MT_REBEL5, //047 + MT_REBEL6, //048 + MT_RLEADER, //049 + MT_RLEADER2, //050 + MT_MISSILESMOKE, //051 + MT_REAVER, //052 + MT_GUARD1, //053 + MT_GUARD2, //054 + MT_GUARD3, //055 + MT_GUARD4, //056 + MT_GUARD5, //057 + MT_GUARD6, //058 + MT_GUARD7, //059 + MT_GUARD8, //060 + MT_SHADOWGUARD, //061 + MT_PGUARD, //062 + MT_CRUSADER, //063 + MT_BISHOP, //064 + MT_ORACLE, //065 + MT_PRIEST, //066 + MT_SPECTRE_A, //067 + MT_NODE, //068 + MT_SPECTREHEAD, //069 + MT_SPECTRE_B, //070 + MT_SPECTRE_C, //071 + MT_SPECTRE_D, //072 + MT_SPECTRE_E, //073 + MT_ENTITY, //074 + MT_SUBENTITY, //075 + MT_NEST, //076 + MT_POD, //077 + MT_SIGIL_B_SHOT, //078 + MT_SIGIL_SB_SHOT, //079 + MT_SIGIL_C_SHOT, //080 + MT_SIGIL_SC_SHOT, //081 + MT_SIGIL_E_OFFSHOOT, //082 + MT_SIGIL_TRAIL, //083 + MT_SIGIL_E_SHOT, //084 + MT_SIGIL_SE_SHOT, //085 + MT_SIGIL_A_ZAP_LEFT, //086 + MT_SIGIL_A_ZAP_RIGHT, //087 + MT_SIGIL_A_GROUND, //088 + MT_SIGIL_D_SHOT, //089 + MT_SIGIL_SD_SHOT, //090 + MT_SENTINEL, //091 + MT_STALKER, //092 + MT_INQUISITOR, //093 + MT_INQARM, //094 + MT_PROGRAMMER, //095 + MT_PROGRAMMERBASE, //096 + MT_HOOKSHOT, //097 + MT_CHAINSHOT, //098 + MT_MINIMISSLE, //099 + MT_C_MISSILE, //100 + MT_SEEKMISSILE, //101 + MT_ELECARROW, //102 + MT_POISARROW, //103 + MT_R_LASER, //104 + MT_L_LASER, //105 + MT_HEGRENADE, //106 + MT_PGRENADE, //107 + MT_INQGRENADE, //108 + MT_PFLAME, //109 + MT_TORPEDO, //110 + MT_TORPEDOSPREAD, //111 + MT_SFIREBALL, //112 + MT_C_FLAME, //113 + MT_STRIFEPUFF3, //114 + MT_STRIFEPUFF, //115 + MT_SPARKPUFF, //116 + MT_BLOOD_DEATH, //117 + MT_TFOG, //118 + MT_IFOG, //119 + MT_TELEPORTMAN, //120 + MT_MISC_01, //121 + MT_TURRET, //122 + MT_GATE, //123 + MT_COMPUTER, //124 + MT_INV_MED1, //125 + MT_INV_MED2, //126 + MT_INV_MED3, //127 + MT_DEGNINORE, //128 + MT_INV_ARMOR2, //129 + MT_INV_ARMOR1, //130 + MT_MISC_22, //131 + MT_MISC_11, //132 + MT_KEY_BASE, //133 + MT_GOVSKEY, //134 + MT_KEY_TRAVEL, //135 + MT_KEY_ID_BLUE, //136 + MT_PRISONKEY, //137 + MT_KEY_HAND, //138 + MT_POWER1KEY, //139 + MT_POWER2KEY, //140 + MT_POWER3KEY, //141 + MT_KEY_GOLD, //142 + MT_KEY_ID_GOLD, //143 + MT_KEY_SILVER, //144 + MT_KEY_ORACLE, //145 + MT_MILITARYID, //146 + MT_KEY_ORDER, //147 + MT_KEY_WAREHOUSE, //148 + MT_KEY_BRASS, //149 + MT_KEY_RED_CRYSTAL, //150 + MT_KEY_BLUE_CRYSTAL, //151 + MT_KEY_CHAPEL, //152 + MT_CATACOMBKEY, //153 + MT_SECURITYKEY, //154 + MT_KEY_CORE, //155 + MT_KEY_MAULER, //156 + MT_KEY_FACTORY, //157 + MT_KEY_MINE, //158 + MT_NEWKEY5, //159 + MT_INV_SHADOWARMOR, //160 + MT_INV_SUIT, //161 + MT_QUEST_UNIFORM, //162 + MT_QUEST_GUARD_UNIFORM, //163 + MT_INV_SUPERMAP, //164 + MT_INV_RADAR, //165 + MT_BEACON, //166 + MT_INV_TARGETER, //167 + MT_MONY_1, //168 + MT_MONY_10, //169 + MT_MONY_25, //170 + MT_MONY_50, //171 + MT_MONY_300, //172 + MT_TOKEN_RING, //173 + MT_INV_CHALICE, //174 + MT_TOKEN_EAR, //175 + MT_INV_COMMUNICATOR, //176 + MT_AGREN, //177 + MT_APGREN, //178 + MT_ACLIP, //179 + MT_AAMMOBOX, //180 + MT_AMINI, //181 + MT_AMINIBOX, //182 + MT_ACELL, //183 + MT_APCELL, //184 + MT_APAROW, //185 + MT_AAROW, //186 + MT_INV_SATCHEL, //187 + MT_PULSE, //188 + MT_RIFLESTAND, //189 + MT_FLAMETHROWER, //190 + MT_TOKEN_FLAME_THROWER_PARTS, //191 + MT_MISSILELAUNCHER, //192 + MT_BLASTER, //193 + MT_CROSSBOW, //194 + MT_GRENADELAUNCHER, //195 + MT_SIGIL_A, //196 + MT_SIGIL_B, //197 + MT_SIGIL_C, //198 + MT_SIGIL_D, //199 + MT_SIGIL_E, //200 + MT_POWER_CRYSTAL, //201 + MT_RAT, //202 + MT_MISC_05, //203 + MT_MISC_06, //204 + MT_MISC_15, //205 + MT_LIGHT14, //206 + MT_LIGHT13, //207 + MT_LIGHT12, //208 + MT_LIGHT18, //209 + MT_PILLAR2, //210 + MT_PILLAR3, //211 + MT_PILLAR4, //212 + MT_PILLAR5, //213 + MT_PILLAR6, //214 + MT_PILLAR7, //215 + MT_CAVE2, //216 + MT_CAVE3, //217 + MT_CAVE4, //218 + MT_CAVE6, //219 + MT_CAVE7, //220 + MT_CAVE5, //221 + MT_LIGHT2, //222 + MT_LIGHT3, //223 + MT_MISC_03, //224 + MT_MISC_13, //225 + MT_MISC_02, //226 + MT_MISC_07, //227 + MT_BIO2, //228 + MT_TELEPORTSTAND, //229 + MT_DEADTHING1, //230 + MT_DEADTHING2, //231 + MT_DEADTHING3, //232 + MT_DEADTHING4, //233 + MT_DEADTHING5, //234 + MT_DEADTHING6, //235 + MT_BIO1, //236 + MT_GIBS, //237 + MT_MISC_04, //238 + MT_LIGHT11, //239 + MT_LIGHT10, //240 + MT_LIGHT9, //241 + MT_LIGHT8, //242 + MT_MISC_14, //243 + MT_LIGHT1, //244 + MT_PILLAR8, //245 + MT_PILLAR9, //246 + MT_LIGHT15, //247 + MT_LIGHT4, //248 + MT_LIGHT5, //249 + MT_ROCK1, //250 + MT_ROCK2, //251 + MT_ROCK3, //252 + MT_ROCK4, //253 + MT_TREE7, //254 + MT_RUBBLE1, //255 + MT_RUBBLE2, //256 + MT_RUBBLE3, //257 + MT_RUBBLE4, //258 + MT_RUBBLE5, //259 + MT_RUBBLE6, //260 + MT_RUBBLE7, //261 + MT_RUBBLE8, //262 + MT_MISC_08, //263 + MT_LIGHT6, //264 + MT_LIGHT7, //265 + MT_TREE2, //266 + MT_TREE3, //267 + MT_TREE4, //268 + MT_TREE1, //269 + MT_TREE6, //270 + MT_TREE5, //271 + MT_CAVE1, //272 + MT_PILLAR1, //273 + MT_MISC_10, //274 + MT_MISC_09, //275 + MT_MISC_17, //276 + MT_MISC_18, //277 + MT_MISC_19, //278 + MT_MISC_20, //279 + MT_LIGHT16, //280 + MT_LIGHT17, //281 + MT_MISC_21, //282 + MT_MISC_12, //283 + MT_MISC_26, //284 + MT_MISC_23, //285 + MT_MISC_24, //286 + MT_MISC_25, //287 + MT_COUPLING, //288 + MT_COUPLING_BROKEN, //289 + MT_PILLAR10, //290 + MT_PILLAR11, //291 + MT_PILLAR12, //292 + MT_PILLAR13, //293 + MT_LIGHT19, //294 + MT_MEAT, //295 + MT_JUNK, //296 + MT_BURNDROP, //297 + MT_TOKEN_AMMO, //298 + MT_TOKEN_HEALTH, //299 + MT_TOKEN, //300 + MT_TOKEN_ALARM, //301 + MT_TOKEN_DOOR1, //302 + MT_TOKEN_SHOPCLOSE, //303 + MT_TOKEN_PRISON_PASS, //304 + MT_TOKEN_DOOR3, //305 + MT_TOKEN_STAMINA, //306 + MT_TOKEN_NEW_ACCURACY, //307 + MT_TOKEN_REPORT, //308 + MT_TOKEN_TOUGHNESS, //309 + MT_TOKEN_ACCURACY, //310 + MT_TOKEN_ORACLE_PASS, //311 + MT_TOKEN_QUEST1, //312 + MT_TOKEN_QUEST2, //313 + MT_TOKEN_QUEST3, //314 + MT_TOKEN_QUEST4, //315 + MT_TOKEN_QUEST5, //316 + MT_TOKEN_QUEST6, //317 + MT_TOKEN_QUEST7, //318 + MT_TOKEN_QUEST8, //319 + MT_TOKEN_QUEST9, //320 + MT_TOKEN_QUEST10, //321 + MT_TOKEN_QUEST11, //322 + MT_TOKEN_QUEST12, //323 + MT_TOKEN_QUEST13, //324 + MT_TOKEN_CRYSTAL, //325 + MT_TOKEN_QUEST15, //326 + MT_GATEQUEST, //327 + MT_TOKEN_QUEST17, //328 + MT_TOKEN_QUEST18, //329 + MT_TOKEN_QUEST19, //330 + MT_TOKEN_QUEST20, //331 + MT_TOKEN_BISHOP, //332 + MT_TOKEN_QUEST22, //333 + MT_TOKEN_ORACLE, //334 + MT_TOKEN_MACIL, //335 + MT_TOKEN_QUEST25, //336 + MT_TOKEN_LOREMASTER, //337 + MT_SECRQUEST, //338 + MT_TOKEN_QUEST28, //339 + MT_TOKEN_QUEST29, //340 + MT_TOKEN_QUEST30, //341 + MT_TOKEN_QUEST31, //342 + MT_SLIDESHOW, //343 + NUMMOBJTYPES + +} mobjtype_t; + +// villsa [STRIFE] updated mobjinfo struct +typedef struct +{ + int doomednum; + int spawnstate; + int spawnhealth; + int seestate; + int seesound; + int reactiontime; + int attacksound; + int painstate; + int painchance; + int painsound; + int meleestate; + int missilestate; + int crashstate; + int deathstate; + int xdeathstate; + int deathsound; + int speed; + int radius; + int height; + int mass; + int damage; + int activesound; + int flags; + const char *name; +} mobjinfo_t; + +extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; + +#endif diff --git a/games/NXDoom/src/strife/m_menu.c b/games/NXDoom/src/strife/m_menu.c new file mode 100644 index 00000000000..d277fd3c718 --- /dev/null +++ b/games/NXDoom/src/strife/m_menu.c @@ -0,0 +1,2466 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// DOOM selection menu, options, episode etc. +// Sliders and icons. Kinda widget stuff. +// + + +#include +#include + + +#include "doomdef.h" +#include "doomkeys.h" +#include "dstrings.h" + +#include "d_main.h" +#include "deh_main.h" + +#include "i_input.h" +#include "i_joystick.h" +#include "i_swap.h" +#include "i_system.h" +#include "i_timer.h" +#include "i_video.h" +#include "z_zone.h" +#include "v_video.h" +#include "w_wad.h" + +#include "r_local.h" + + +#include "hu_stuff.h" + +#include "g_game.h" + +#include "m_argv.h" +#include "m_controls.h" +#include "m_misc.h" +#include "m_saves.h" // [STRIFE] +#include "p_saveg.h" + +#include "s_sound.h" + +#include "doomstat.h" + +// Data. +#include "sounds.h" + +#include "m_menu.h" +#include "p_dialog.h" + + +void M_QuitStrife(int); + + +// +// defaulted values +// +int mouseSensitivity = 5; + +// [STRIFE]: removed this entirely +// Show messages has default, 0 = off, 1 = on +//int showMessages = 1; + + +// Blocky mode, has default, 0 = high, 1 = normal +int detailLevel = 0; +int screenblocks = 10; // [STRIFE] default 10, not 9 + +// temp for screenblocks (0-9) +int screenSize; + +// -1 = no quicksave slot picked! +int quickSaveSlot; + + // 1 = message to be printed +int messageToPrint; +// ...and here is the message string! +const char *messageString; + +// message x & y +int messx; +int messy; +int messageLastMenuActive; + +// timed message = no input from user +boolean messageNeedsInput; + +void (*messageRoutine)(int response); + +char gammamsg[5][26] = +{ + GAMMALVL0, + GAMMALVL1, + GAMMALVL2, + GAMMALVL3, + GAMMALVL4 +}; + +// we are going to be entering a savegame string +int saveStringEnter; +int saveSlot; // which slot to save in +int saveCharIndex; // which char we're editing +// old save description before edit +char saveOldString[SAVESTRINGSIZE]; + +boolean inhelpscreens; +boolean menuactive; +boolean menupause; // haleyjd 08/29/10: [STRIFE] New global +int menupausetime; // haleyjd 09/04/10: [STRIFE] New global +boolean menuindialog; // haleyjd 09/04/10: ditto + +// haleyjd 08/27/10: [STRIFE] SKULLXOFF == -28, LINEHEIGHT == 19 +#define CURSORXOFF -28 +#define LINEHEIGHT 19 + +char savegamestrings[10][SAVESTRINGSIZE]; + +char endstring[160]; + +// haleyjd 09/04/10: [STRIFE] Moved menuitem / menu structures into header +// because they are needed externally by the dialog engine. + +// haleyjd 08/27/10: [STRIFE] skull* stuff changed to cursor* stuff +short itemOn; // menu item skull is on +short cursorAnimCounter; // skull animation counter +short whichCursor; // which skull to draw + +// graphic name of cursors +// haleyjd 08/27/10: [STRIFE] M_SKULL* -> M_CURS* +const char *cursorName[8] = {"M_CURS1", "M_CURS2", "M_CURS3", "M_CURS4", + "M_CURS5", "M_CURS6", "M_CURS7", "M_CURS8" }; + +// haleyjd 20110210 [STRIFE]: skill level for menus +int menuskill; + +// current menudef +menu_t* currentMenu; + +// haleyjd 03/01/13: [STRIFE] v1.31-only: +// Keeps track of whether the save game menu is being used to name a new +// character slot, or to just save the current game. In the v1.31 disassembly +// this was the new dword_8632C variable. +boolean namingCharacter; + +// +// PROTOTYPES +// +void M_NewGame(int choice); +void M_Episode(int choice); +void M_ChooseSkill(int choice); +void M_LoadGame(int choice); +void M_SaveGame(int choice); +void M_Options(int choice); +void M_EndGame(int choice); +void M_ReadThis(int choice); +void M_ReadThis2(int choice); +void M_ReadThis3(int choice); // [STRIFE] + +//void M_ChangeMessages(int choice); [STRIFE] +void M_ChangeSensitivity(int choice); +void M_SfxVol(int choice); +void M_VoiceVol(int choice); // [STRIFE] +void M_MusicVol(int choice); +void M_SizeDisplay(int choice); +void M_StartGame(int choice); +void M_Sound(int choice); + +//void M_FinishReadThis(int choice); - [STRIFE] unused +void M_SaveSelect(int choice); +void M_ReadSaveStrings(void); +void M_QuickSave(void); +void M_QuickLoad(void); + +void M_DrawMainMenu(void); +void M_DrawReadThis1(void); +void M_DrawReadThis2(void); +void M_DrawReadThis3(void); // [STRIFE] +void M_DrawNewGame(void); +void M_DrawEpisode(void); +void M_DrawOptions(void); +void M_DrawSound(void); +void M_DrawLoad(void); +void M_DrawSave(void); + +void M_DrawSaveLoadBorder(int x,int y); +void M_SetupNextMenu(menu_t *menudef); +void M_DrawThermo(int x,int y,int thermWidth,int thermDot); +void M_DrawEmptyCell(menu_t *menu,int item); +void M_DrawSelCell(menu_t *menu,int item); +int M_StringWidth(const char *string); +int M_StringHeight(const char *string); +void M_StartMessage(const char *string,void *routine,boolean input); +void M_StopMessage(void); + + + + +// +// DOOM MENU +// +enum +{ + newgame = 0, + options, + loadgame, + savegame, + readthis, + quitdoom, + main_end +} main_e; + +menuitem_t MainMenu[]= +{ + {1,"M_NGAME",M_NewGame,'n'}, + {1,"M_OPTION",M_Options,'o'}, + {1,"M_LOADG",M_LoadGame,'l'}, + {1,"M_SAVEG",M_SaveGame,'s'}, + // Another hickup with Special edition. + {1,"M_RDTHIS",M_ReadThis,'h'}, // haleyjd 08/28/10: 'r' -> 'h' + {1,"M_QUITG",M_QuitStrife,'q'} +}; + +menu_t MainDef = +{ + main_end, + NULL, + MainMenu, + M_DrawMainMenu, + 97,45, // haleyjd 08/28/10: [STRIFE] changed y coord + 0 +}; + + +// +// EPISODE SELECT +// +/* +enum +{ + ep1, + ep2, + ep3, + ep4, + ep_end +} episodes_e; + +menuitem_t EpisodeMenu[]= +{ + {1,"M_EPI1", M_Episode,'k'}, + {1,"M_EPI2", M_Episode,'t'}, + {1,"M_EPI3", M_Episode,'i'}, + {1,"M_EPI4", M_Episode,'t'} +}; + +menu_t EpiDef = +{ + ep_end, // # of menu items + &MainDef, // previous menu + EpisodeMenu, // menuitem_t -> + M_DrawEpisode, // drawing routine -> + 48,63, // x,y + ep1 // lastOn +}; +*/ + +// +// NEW GAME +// +enum +{ + killthings, + toorough, + hurtme, + violence, + nightmare, + newg_end +} newgame_e; + +menuitem_t NewGameMenu[]= +{ + // haleyjd 08/28/10: [STRIFE] changed all shortcut letters + {1,"M_JKILL", M_ChooseSkill, 't'}, + {1,"M_ROUGH", M_ChooseSkill, 'r'}, + {1,"M_HURT", M_ChooseSkill, 'v'}, + {1,"M_ULTRA", M_ChooseSkill, 'e'}, + {1,"M_NMARE", M_ChooseSkill, 'b'} +}; + +menu_t NewDef = +{ + newg_end, // # of menu items + &MainDef, // previous menu - haleyjd [STRIFE] changed to MainDef + NewGameMenu, // menuitem_t -> + M_DrawNewGame, // drawing routine -> + 48,63, // x,y + toorough // lastOn - haleyjd [STRIFE]: default to skill 1 +}; + +// +// OPTIONS MENU +// +enum +{ + // haleyjd 08/28/10: [STRIFE] Removed messages, mouse sens., detail. + endgame, + scrnsize, + option_empty1, + soundvol, + opt_end +} options_e; + +menuitem_t OptionsMenu[]= +{ + // haleyjd 08/28/10: [STRIFE] Removed messages, mouse sens., detail. + {1,"M_ENDGAM", M_EndGame,'e'}, + {2,"M_SCRNSZ", M_SizeDisplay,'s'}, + {-1,"",0,'\0'}, + {1,"M_SVOL", M_Sound,'s'} +}; + +menu_t OptionsDef = +{ + opt_end, + &MainDef, + OptionsMenu, + M_DrawOptions, + 60,37, + 0 +}; + +// +// Read This! MENU 1 & 2 & [STRIFE] 3 +// +enum +{ + rdthsempty1, + read1_end +} read_e; + +menuitem_t ReadMenu1[] = +{ + {1,"",M_ReadThis2,0} +}; + +menu_t ReadDef1 = +{ + read1_end, + &MainDef, + ReadMenu1, + M_DrawReadThis1, + 280,185, + 0 +}; + +enum +{ + rdthsempty2, + read2_end +} read_e2; + +menuitem_t ReadMenu2[]= +{ + {1,"",M_ReadThis3,0} // haleyjd 08/28/10: [STRIFE] Go to ReadThis3 +}; + +menu_t ReadDef2 = +{ + read2_end, + &ReadDef1, + ReadMenu2, + M_DrawReadThis2, + 250,185, // haleyjd 08/28/10: [STRIFE] changed coords + 0 +}; + +// haleyjd 08/28/10: Added Read This! menu 3 +enum +{ + rdthsempty3, + read3_end +} read_e3; + +menuitem_t ReadMenu3[]= +{ + {1,"",M_ClearMenus,0} +}; + +menu_t ReadDef3 = +{ + read3_end, + &ReadDef2, + ReadMenu3, + M_DrawReadThis3, + 250, 185, + 0 +}; + +// +// SOUND VOLUME MENU +// +enum +{ + sfx_vol, + sfx_empty1, + music_vol, + sfx_empty2, + voice_vol, + sfx_empty3, + sfx_mouse, + sfx_empty4, + sound_end +} sound_e; + +// haleyjd 08/29/10: +// [STRIFE] +// * Added voice volume +// * Moved mouse sensitivity here (who knows why...) +menuitem_t SoundMenu[]= +{ + {2,"M_SFXVOL",M_SfxVol,'s'}, + {-1,"",0,'\0'}, + {2,"M_MUSVOL",M_MusicVol,'m'}, + {-1,"",0,'\0'}, + {2,"M_VOIVOL",M_VoiceVol,'v'}, + {-1,"",0,'\0'}, + {2,"M_MSENS",M_ChangeSensitivity,'m'}, + {-1,"",0,'\0'} +}; + +menu_t SoundDef = +{ + sound_end, + &OptionsDef, + SoundMenu, + M_DrawSound, + 80,35, // [STRIFE] changed y coord 64 -> 35 + 0 +}; + +// +// LOAD GAME MENU +// +enum +{ + load1, + load2, + load3, + load4, + load5, + load6, + load_end +} load_e; + +menuitem_t LoadMenu[]= +{ + {1,"", M_LoadSelect,'1'}, + {1,"", M_LoadSelect,'2'}, + {1,"", M_LoadSelect,'3'}, + {1,"", M_LoadSelect,'4'}, + {1,"", M_LoadSelect,'5'}, + {1,"", M_LoadSelect,'6'} +}; + +menu_t LoadDef = +{ + load_end, + &MainDef, + LoadMenu, + M_DrawLoad, + 80,54, + 0 +}; + +// +// SAVE GAME MENU +// +menuitem_t SaveMenu[]= +{ + {1,"", M_SaveSelect,'1'}, + {1,"", M_SaveSelect,'2'}, + {1,"", M_SaveSelect,'3'}, + {1,"", M_SaveSelect,'4'}, + {1,"", M_SaveSelect,'5'}, + {1,"", M_SaveSelect,'6'} +}; + +menu_t SaveDef = +{ + load_end, + &MainDef, + SaveMenu, + M_DrawSave, + 80,54, + 0 +}; + +void M_DrawNameChar(void); + +// +// NAME CHARACTER MENU +// +// [STRIFE] +// haleyjd 20110210: New "Name Your Character" Menu +// +menu_t NameCharDef = +{ + load_end, + &NewDef, + SaveMenu, + M_DrawNameChar, + 80,54, + 0 +}; + + +// +// M_ReadSaveStrings +// read the strings from the savegame files +// +// [STRIFE] +// haleyjd 20110210: Rewritten to read "name" file in each slot directory +// +void M_ReadSaveStrings(void) +{ + FILE *handle; + int i; + char *fname = NULL; + + for(i = 0; i < load_end; i++) + { + int retval; + if(fname) + Z_Free(fname); + fname = M_SafeFilePath(savegamedir, M_MakeStrifeSaveDir(i, "\\name")); + + handle = M_fopen(fname, "rb"); + if(handle == NULL) + { + M_StringCopy(savegamestrings[i], DEH_String(EMPTYSTRING), + sizeof(savegamestrings[i])); + LoadMenu[i].status = 0; + continue; + } + retval = fread(savegamestrings[i], 1, SAVESTRINGSIZE, handle); + fclose(handle); + LoadMenu[i].status = retval == SAVESTRINGSIZE; + } + + if(fname) + Z_Free(fname); +} + +// +// M_DrawNameChar +// +// haleyjd 09/22/10: [STRIFE] New function +// Handler for drawing the "Name Your Character" menu. +// +void M_DrawNameChar(void) +{ + int i; + + M_WriteText(72, 28, DEH_String("Name Your Character")); + + for (i = 0;i < load_end; i++) + { + M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); + M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + } + + if (saveStringEnter) + { + i = M_StringWidth(savegamestrings[quickSaveSlot]); + M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*quickSaveSlot,"_"); + } +} + +// +// M_DoNameChar +// +// haleyjd 09/22/10: [STRIFE] New function +// Handler for items in the "Name Your Character" menu. +// +void M_DoNameChar(int choice) +{ + int map; + + // 20130301: clear naming character flag for 1.31 save logic + if(gameversion == exe_strife_1_31) + namingCharacter = false; + sendsave = 1; + ClearTmp(); + G_WriteSaveName(choice, savegamestrings[choice]); + quickSaveSlot = choice; + SaveDef.lastOn = choice; + ClearSlot(); + FromCurr(); + + if(isdemoversion) + map = 33; + else + map = 2; + + G_DeferedInitNew(menuskill, map); + M_ClearMenus(0); +} + +// +// M_LoadGame & Cie. +// +void M_DrawLoad(void) +{ + int i; + + V_DrawPatchDirect(72, 28, + W_CacheLumpName(DEH_String("M_LOADG"), PU_CACHE)); + + for (i = 0;i < load_end; i++) + { + M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); + M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + } +} + + + +// +// Draw border for the savegame description +// +void M_DrawSaveLoadBorder(int x,int y) +{ + int i; + + V_DrawPatchDirect(x - 8, y + 7, + W_CacheLumpName(DEH_String("M_LSLEFT"), PU_CACHE)); + + for (i = 0;i < 24;i++) + { + V_DrawPatchDirect(x, y + 7, + W_CacheLumpName(DEH_String("M_LSCNTR"), PU_CACHE)); + x += 8; + } + + V_DrawPatchDirect(x, y + 7, + W_CacheLumpName(DEH_String("M_LSRGHT"), PU_CACHE)); +} + + + +// +// User wants to load this game +// +void M_LoadSelect(int choice) +{ + // [STRIFE]: completely rewritten + char *name = NULL; + + G_WriteSaveName(choice, savegamestrings[choice]); + ToCurr(); + + // use safe & portable filepath concatenation for Choco + name = M_SafeFilePath(savegamedir, M_MakeStrifeSaveDir(choice, "")); + + G_ReadCurrent(name); + quickSaveSlot = choice; + M_ClearMenus(0); + + Z_Free(name); +} + +// +// Selected from DOOM menu +// +// [STRIFE] Verified unmodified +// +void M_LoadGame (int choice) +{ + if (netgame) + { + M_StartMessage(DEH_String(LOADNET), NULL, false); + return; + } + + M_SetupNextMenu(&LoadDef); + M_ReadSaveStrings(); +} + + +// +// M_SaveGame & Cie. +// +void M_DrawSave(void) +{ + int i; + + V_DrawPatchDirect(72, 28, W_CacheLumpName(DEH_String("M_SAVEG"), PU_CACHE)); + for (i = 0;i < load_end; i++) + { + M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); + M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + } + + if (saveStringEnter) + { + i = M_StringWidth(savegamestrings[quickSaveSlot]); + M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*quickSaveSlot,"_"); + } +} + +// +// M_Responder calls this when user is finished +// +void M_DoSave(int slot) +{ + // [STRIFE]: completely rewritten + if(slot >= 0) + { + sendsave = 1; + G_WriteSaveName(slot, savegamestrings[slot]); + M_ClearMenus(0); + quickSaveSlot = slot; + // haleyjd 20130922: slight divergence. We clear the destination slot + // of files here, which vanilla did not do. As a result, 1.31 had + // broken save behavior to the point of unusability. fraggle agrees + // this is detrimental enough to be fixed - unconditionally, for now. + ClearSlot(); + FromCurr(); + } + else + M_StartMessage(DEH_String(QSAVESPOT), NULL, false); +} + +// +// User wants to save. Start string input for M_Responder +// +void M_SaveSelect(int choice) +{ + int x, y; + + // we are going to be intercepting all chars + saveStringEnter = 1; + + // We need to turn on text input: + x = LoadDef.x - 11; + y = LoadDef.y + choice * LINEHEIGHT - 4; + I_StartTextInput(x, y, x + 8 + 24 * 8 + 8, y + LINEHEIGHT - 2); + + // [STRIFE] + quickSaveSlot = choice; + //saveSlot = choice; + + M_StringCopy(saveOldString, savegamestrings[choice], sizeof(saveOldString)); + if (!strcmp(savegamestrings[choice], DEH_String(EMPTYSTRING))) + savegamestrings[choice][0] = 0; + saveCharIndex = strlen(savegamestrings[choice]); +} + +// +// Selected from DOOM menu +// +void M_SaveGame (int choice) +{ + // [STRIFE] + if (netgame) + { + // haleyjd 20110211: Hooray for Rogue's awesome multiplayer support... + M_StartMessage(DEH_String("You can't save a netgame"), NULL, false); + return; + } + if (!usergame) + { + M_StartMessage(DEH_String(SAVEDEAD),NULL,false); + return; + } + + if (gamestate != GS_LEVEL) + return; + + // [STRIFE] + if(gameversion == exe_strife_1_31) + { + // haleyjd 20130301: in 1.31, we can choose a slot again. + M_SetupNextMenu(&SaveDef); + M_ReadSaveStrings(); + } + else + { + // In 1.2 and lower, you save over your character slot exclusively + M_ReadSaveStrings(); + M_DoSave(quickSaveSlot); + } +} + + + +// +// M_QuickSave +// +char tempstring[80]; + +void M_QuickSaveResponse(int key) +{ + if (key == key_menu_confirm) + { + M_DoSave(quickSaveSlot); + S_StartSound(NULL, sfx_mtalht); // [STRIFE] sound + } +} + +void M_QuickSave(void) +{ + if (netgame) + { + // haleyjd 20110211 [STRIFE]: More fun... + M_StartMessage(DEH_String("You can't save a netgame"), NULL, false); + return; + } + + if (!usergame) + { + S_StartSound(NULL, sfx_oof); + return; + } + + if (gamestate != GS_LEVEL) + return; + + if (quickSaveSlot < 0) + { + M_StartControlPanel(); + M_ReadSaveStrings(); + M_SetupNextMenu(&SaveDef); + quickSaveSlot = -2; // means to pick a slot now + return; + } + DEH_snprintf(tempstring, 80, QSPROMPT, savegamestrings[quickSaveSlot]); + M_StartMessage(tempstring,M_QuickSaveResponse,true); +} + + + +// +// M_QuickLoadResponse +// +void M_QuickLoadResponse(int key) +{ + if (key == key_menu_confirm) + { + M_LoadSelect(quickSaveSlot); + S_StartSound(NULL, sfx_mtalht); // [STRIFE] sound + } +} + +// +// M_QuickLoad +// +// [STRIFE] Verified unmodified +// +void M_QuickLoad(void) +{ + if (netgame) + { + M_StartMessage(DEH_String(QLOADNET),NULL,false); + return; + } + + if (quickSaveSlot < 0) + { + M_StartMessage(DEH_String(QSAVESPOT),NULL,false); + return; + } + DEH_snprintf(tempstring, 80, QLPROMPT, savegamestrings[quickSaveSlot]); + M_StartMessage(tempstring,M_QuickLoadResponse,true); +} + + + + +// +// Read This Menus +// Had a "quick hack to fix romero bug" +// haleyjd 08/28/10: [STRIFE] Draw HELP1, unconditionally. +// +void M_DrawReadThis1(void) +{ + inhelpscreens = true; + + V_DrawPatchDirect (0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE)); +} + + + +// +// Read This Menus +// haleyjd 08/28/10: [STRIFE] Not optional, draws HELP2 +// +void M_DrawReadThis2(void) +{ + inhelpscreens = true; + + V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP2"), PU_CACHE)); +} + + +// +// Read This Menus +// haleyjd 08/28/10: [STRIFE] New function to draw HELP3. +// +void M_DrawReadThis3(void) +{ + inhelpscreens = true; + + V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP3"), PU_CACHE)); +} + +// +// Change Sfx & Music volumes +// +// haleyjd 08/29/10: [STRIFE] +// * Changed title graphic coordinates +// * Added voice volume and sensitivity sliders +// +void M_DrawSound(void) +{ + V_DrawPatchDirect (100, 10, W_CacheLumpName(DEH_String("M_SVOL"), PU_CACHE)); + + M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), + 16,sfxVolume); + + M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), + 16,musicVolume); + + M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(voice_vol+1), + 16,voiceVolume); + + M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_mouse+1), + 16,mouseSensitivity); +} + +void M_Sound(int choice) +{ + M_SetupNextMenu(&SoundDef); +} + +void M_SfxVol(int choice) +{ + switch(choice) + { + case 0: + if (sfxVolume) + sfxVolume--; + break; + case 1: + if (sfxVolume < 15) + sfxVolume++; + break; + } + + S_SetSfxVolume(sfxVolume * 8); +} + +// +// M_VoiceVol +// +// haleyjd 08/29/10: [STRIFE] New function +// Sets voice volume level. +// +void M_VoiceVol(int choice) +{ + switch(choice) + { + case 0: + if (voiceVolume) + voiceVolume--; + break; + case 1: + if (voiceVolume < 15) + voiceVolume++; + break; + } + + S_SetVoiceVolume(voiceVolume * 8); +} + +void M_MusicVol(int choice) +{ + switch(choice) + { + case 0: + if (musicVolume) + musicVolume--; + break; + case 1: + if (musicVolume < 15) + musicVolume++; + break; + } + + S_SetMusicVolume(musicVolume * 8); +} + + + + +// +// M_DrawMainMenu +// +// haleyjd 08/27/10: [STRIFE] Changed x coordinate; M_DOOM -> M_STRIFE +// +void M_DrawMainMenu(void) +{ + V_DrawPatchDirect(84, 2, + W_CacheLumpName(DEH_String("M_STRIFE"), PU_CACHE)); +} + + + + +// +// M_NewGame +// +// haleyjd 08/31/10: [STRIFE] Changed M_NEWG -> M_NGAME +// +void M_DrawNewGame(void) +{ + V_DrawPatchDirect(96, 14, W_CacheLumpName(DEH_String("M_NGAME"), PU_CACHE)); + V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_SKILL"), PU_CACHE)); +} + +void M_NewGame(int choice) +{ + if (netgame && !demoplayback) + { + M_StartMessage(DEH_String(NEWGAME),NULL,false); + return; + } + // haleyjd 09/07/10: [STRIFE] Removed Chex Quest and DOOM gamemodes + if(gameversion == exe_strife_1_31) + namingCharacter = true; // for 1.31 save logic + M_SetupNextMenu(&NewDef); +} + + +// +// M_Episode +// + +// haleyjd: [STRIFE] Unused +/* +int epi; + +void M_DrawEpisode(void) +{ + V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_EPISOD"), PU_CACHE)); +} + +void M_VerifyNightmare(int key) +{ + if (key != key_menu_confirm) + return; + + G_DeferedInitNew(nightmare, 1); + M_ClearMenus (0); +} +*/ + +void M_ChooseSkill(int choice) +{ + // haleyjd 09/07/10: Removed nightmare confirmation + // [STRIFE]: start "Name Your Character" menu + menuskill = choice; + currentMenu = &NameCharDef; + itemOn = NameCharDef.lastOn; + M_ReadSaveStrings(); +} + +/* +// haleyjd [STRIFE] Unused +void M_Episode(int choice) +{ + if ( (gamemode == shareware) + && choice) + { + M_StartMessage(DEH_String(SWSTRING),NULL,false); + M_SetupNextMenu(&ReadDef1); + return; + } + + // Yet another hack... + if ( (gamemode == registered) + && (choice > 2)) + { + fprintf( stderr, + "M_Episode: 4th episode requires UltimateDOOM\n"); + choice = 0; + } + + epi = choice; + M_SetupNextMenu(&NewDef); +} +*/ + + +// +// M_Options +// +char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"}; +char msgNames[2][9] = {"M_MSGOFF","M_MSGON"}; + + +void M_DrawOptions(void) +{ + // haleyjd 08/27/10: [STRIFE] M_OPTTTL -> M_OPTION + V_DrawPatchDirect(108, 15, + W_CacheLumpName(DEH_String("M_OPTION"), PU_CACHE)); + + // haleyjd 08/26/10: [STRIFE] Removed messages, sensitivity, detail. + + M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), + 9,screenSize); +} + +void M_Options(int choice) +{ + M_SetupNextMenu(&OptionsDef); +} + +// +// M_AutoUseHealth +// +// [STRIFE] New function +// haleyjd 20110211: toggle autouse health state +// +void M_AutoUseHealth(void) +{ + if(!netgame && usergame) + { + players[consoleplayer].cheats ^= CF_AUTOHEALTH; + + if(players[consoleplayer].cheats & CF_AUTOHEALTH) + players[consoleplayer].message = DEH_String("Auto use health ON"); + else + players[consoleplayer].message = DEH_String("Auto use health OFF"); + } +} + +// +// M_ChangeShowText +// +// [STRIFE] New function +// +void M_ChangeShowText(void) +{ + dialogshowtext ^= true; + + if(dialogshowtext) + players[consoleplayer].message = DEH_String("Conversation Text On"); + else + players[consoleplayer].message = DEH_String("Conversation Text Off"); +} + +// +// Toggle messages on/off +// +// [STRIFE] Messages cannot be disabled in Strife +/* +void M_ChangeMessages(int choice) +{ + // warning: unused parameter `int choice' + choice = 0; + showMessages = 1 - showMessages; + + if (!showMessages) + players[consoleplayer].message = DEH_String(MSGOFF); + else + players[consoleplayer].message = DEH_String(MSGON); + + message_dontfuckwithme = true; +} +*/ + + +// +// M_EndGame +// +void M_EndGameResponse(int key) +{ + if (key != key_menu_confirm) + return; + + currentMenu->lastOn = itemOn; + M_ClearMenus (0); + D_StartTitle (); +} + +void M_EndGame(int choice) +{ + choice = 0; + if (!usergame) + { + S_StartSound(NULL,sfx_oof); + return; + } + + if (netgame) + { + M_StartMessage(DEH_String(NETEND),NULL,false); + return; + } + + M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true); +} + + + + +// +// M_ReadThis +// +void M_ReadThis(int choice) +{ + choice = 0; + M_SetupNextMenu(&ReadDef1); +} + +// +// M_ReadThis2 +// +// haleyjd 08/28/10: [STRIFE] Eliminated DOOM stuff. +// +void M_ReadThis2(int choice) +{ + choice = 0; + M_SetupNextMenu(&ReadDef2); +} + +// +// M_ReadThis3 +// +// haleyjd 08/28/10: [STRIFE] New function. +// +void M_ReadThis3(int choice) +{ + choice = 0; + M_SetupNextMenu(&ReadDef3); +} + +/* +// haleyjd 08/28/10: [STRIFE] Not used. +void M_FinishReadThis(int choice) +{ + choice = 0; + M_SetupNextMenu(&MainDef); +} +*/ + +#if 0 + +// +// M_CheckStartCast +// +// [STRIFE] New but unused function. Was going to start a cast +// call from within the menu system... not functional even in +// the earliest demo version. +// +void M_CheckStartCast() +{ + if(usergame) + { + M_StartMessage(DEH_String("You have to end your game first."), NULL, false); + return; + } + + F_StartCast(); + M_ClearMenus(0); +} +#endif + +// +// M_QuitResponse +// +// haleyjd 09/11/10: [STRIFE] Modifications to start up endgame +// demosequence. +// +void M_QuitResponse(int key) +{ + char buffer[20]; + + if (key != key_menu_confirm) + return; + + if(netgame) + I_Quit(); + else + { + DEH_snprintf(buffer, sizeof(buffer), "qfmrm%i", gametic % 8 + 1); + I_StartVoice(buffer); + D_QuitGame(); + } +} + +/* +// haleyjd 09/11/10: [STRIFE] Unused +static char *M_SelectEndMessage(void) +{ +} +*/ + +// +// M_QuitStrife +// +// [STRIFE] Renamed from M_QuitDOOM +// haleyjd 09/11/10: No randomized text message; that's taken care of +// by the randomized voice message after confirmation. +// +void M_QuitStrife(int choice) +{ + DEH_snprintf(endstring, sizeof(endstring), + "Do you really want to leave?\n\n" DOSY); + + M_StartMessage(endstring, M_QuitResponse, true); +} + + + + +void M_ChangeSensitivity(int choice) +{ + switch(choice) + { + case 0: + if (mouseSensitivity) + mouseSensitivity--; + break; + case 1: + if (mouseSensitivity < 9) + mouseSensitivity++; + break; + } +} + +/* +// haleyjd [STRIFE] Unused +void M_ChangeDetail(int choice) +{ + choice = 0; + detailLevel = 1 - detailLevel; + + R_SetViewSize (screenblocks, detailLevel); + + if (!detailLevel) + players[consoleplayer].message = DEH_String(DETAILHI); + else + players[consoleplayer].message = DEH_String(DETAILLO); +} +*/ + +// [STRIFE] Verified unmodified +void M_SizeDisplay(int choice) +{ + switch(choice) + { + case 0: + if (screenSize > 0) + { + screenblocks--; + screenSize--; + } + break; + case 1: + if (screenSize < 8) + { + screenblocks++; + screenSize++; + } + break; + } + + R_SetViewSize (screenblocks, detailLevel); +} + + + + +// +// Menu Functions +// + +// +// M_DrawThermo +// +// haleyjd 08/28/10: [STRIFE] Changes to some patch coordinates. +// +void +M_DrawThermo +( int x, + int y, + int thermWidth, + int thermDot ) +{ + int xx; + int yy; // [STRIFE] Needs a temp y coordinate variable + int i; + + xx = x; + yy = y + 6; // [STRIFE] +6 to y coordinate + V_DrawPatchDirect(xx, yy, W_CacheLumpName(DEH_String("M_THERML"), PU_CACHE)); + xx += 8; + for (i=0;ix - 10, menu->y + item * LINEHEIGHT - 1, + W_CacheLumpName(DEH_String("M_CELL1"), PU_CACHE)); +} + +void +M_DrawSelCell +( menu_t* menu, + int item ) +{ + V_DrawPatchDirect(menu->x - 10, menu->y + item * LINEHEIGHT - 1, + W_CacheLumpName(DEH_String("M_CELL2"), PU_CACHE)); +} + + +void +M_StartMessage +( const char *string, + void* routine, + boolean input ) +{ + messageLastMenuActive = menuactive; + messageToPrint = 1; + messageString = string; + messageRoutine = routine; + messageNeedsInput = input; + menuactive = true; + return; +} + + + +void M_StopMessage(void) +{ + menuactive = messageLastMenuActive; + messageToPrint = 0; +} + + + +// +// Find string width from hu_font chars +// +int M_StringWidth(const char *string) +{ + size_t i; + int w = 0; + int c; + + for (i = 0;i < strlen(string);i++) + { + c = toupper(string[i]) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE) + w += 4; + else + w += SHORT (hu_font[c]->width); + } + + return w; +} + + + +// +// Find string height from hu_font chars +// +int M_StringHeight(const char *string) +{ + size_t i; + int h; + int height = SHORT(hu_font[0]->height); + + h = height; + for (i = 0;i < strlen(string);i++) + if (string[i] == '\n') + h += height; + + return h; +} + + +// +// M_WriteText +// +// Write a string using the hu_font +// haleyjd 09/04/10: [STRIFE] +// * Rogue made a lot of changes to this for the dialog system. +// +int +M_WriteText +( int x, + int y, + const char* string) // haleyjd: made const for safety w/dialog engine +{ + int w; + const char* ch; + int c; + int cx; + int cy; + + ch = string; + cx = x; + cy = y; + + while(1) + { + c = *ch++; + if (!c) + break; + + // haleyjd 09/04/10: [STRIFE] Don't draw spaces at the start of lines. + if(c == ' ' && cx == x) + continue; + + if (c == '\n') + { + cx = x; + cy += 11; // haleyjd 09/04/10: [STRIFE]: Changed 12 -> 11 + continue; + } + + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c>= HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT (hu_font[c]->width); + + // haleyjd 09/04/10: [STRIFE] Different linebreak handling + if (cx + w > SCREENWIDTH - 20) + { + cx = x; + cy += 11; + --ch; + } + else + { + V_DrawPatchDirect(cx, cy, hu_font[c]); + cx += w; + } + } + + // [STRIFE] Return final y coordinate. + return cy + 12; +} + +// +// M_DialogDimMsg +// +// [STRIFE] New function +// haleyjd 09/04/10: Painstakingly transformed from the assembly code, as the +// decompiler could not touch it. Redimensions a string to fit on screen, leaving +// at least a 20 pixel margin on the right side. The string passed in must be +// writable. +// +void M_DialogDimMsg(int x, int y, char *str, boolean useyfont) +{ + int rightbound = (SCREENWIDTH - 20) - x; + patch_t **fontarray; // ebp + int linewidth = 0; // esi + int i = 0; // edx + char *message = str; // edi + char bl; // bl + + if(useyfont) + fontarray = yfont; + else + fontarray = hu_font; + + bl = toupper(*message); + + if(!bl) + return; + + // outer loop - run to end of string + do + { + if(bl != '\n') + { + int charwidth; // eax + int tempwidth; // ecx + + if(bl < HU_FONTSTART || bl > HU_FONTEND) + charwidth = 4; + else + charwidth = SHORT(fontarray[bl - HU_FONTSTART]->width); + + tempwidth = linewidth + charwidth; + + // Test if the line still fits within the boundary... + if(tempwidth >= rightbound) + { + // Doesn't fit... + char *tempptr = &message[i]; // ebx + char al; // al + + // inner loop - run backward til a space (or the start of the + // string) is found, subtracting width off the current line. + // BUG: shouldn't we stop at a previous '\n' too? + while(*tempptr != ' ' && i > 0) + { + tempptr--; + // BUG: they didn't add the first char to linewidth yet... + linewidth -= charwidth; + i--; + al = toupper(*tempptr); + if(al < HU_FONTSTART || al > HU_FONTEND) + charwidth = 4; + else + charwidth = SHORT(fontarray[al - HU_FONTSTART]->width); + } + // Replace the space with a linebreak. + // BUG: what if i is zero? ... infinite loop time! + message[i] = '\n'; + linewidth = 0; + } + else + { + // The line does fit. + // Spaces at the start of a line don't count though. + if(!(bl == ' ' && linewidth == 0)) + linewidth += charwidth; + } + } + else + linewidth = 0; // '\n' seen, so reset the line width + } + while((bl = toupper(message[++i])) != 0); // step to the next character +} + +// These keys evaluate to a "null" key in Vanilla Doom that allows weird +// jumping in the menus. Preserve this behavior for accuracy. + +static boolean IsNullKey(int key) +{ + return key == KEY_PAUSE || key == KEY_CAPSLOCK + || key == KEY_SCRLCK || key == KEY_NUMLOCK; +} + +// +// CONTROL PANEL +// + +// +// M_Responder +// +boolean M_Responder (event_t* ev) +{ + int ch; + int key; + int i; + static int joywait = 0; + static int mousewait = 0; + static int mousey = 0; + static int lasty = 0; + static int mousex = 0; + static int lastx = 0; + int dir; + + // In testcontrols mode, none of the function keys should do anything + // - the only key is escape to quit. + + if (testcontrols) + { + if (ev->type == ev_quit + || (ev->type == ev_keydown + && (ev->data1 == key_menu_activate || ev->data1 == key_menu_quit))) + { + I_Quit(); + return true; + } + + return false; + } + + // "close" button pressed on window? + if (ev->type == ev_quit) + { + // First click on close button = bring up quit confirm message. + // Second click on close button = confirm quit + + if (menuactive && messageToPrint && messageRoutine == M_QuitResponse) + { + M_QuitResponse(key_menu_confirm); + } + else + { + S_StartSound(NULL, sfx_swtchn); + M_QuitStrife(0); + } + + return true; + } + + // key is the key pressed, ch is the actual character typed + + ch = 0; + key = -1; + + if (ev->type == ev_joystick && joywait < I_GetTime()) + { + if (JOY_GET_DPAD(ev->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_DPAD(ev->data6); + } + else if (JOY_GET_LSTICK(ev->data6) != JOY_DIR_NONE) + { + dir = JOY_GET_LSTICK(ev->data6); + } + else + { + dir = JOY_GET_RSTICK(ev->data6); + } + + if (dir & JOY_DIR_UP) + { + key = key_menu_up; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_DOWN) + { + key = key_menu_down; + joywait = I_GetTime() + 5; + } + if (dir & JOY_DIR_LEFT) + { + key = key_menu_left; + joywait = I_GetTime() + 5; + } + else if (dir & JOY_DIR_RIGHT) + { + key = key_menu_right; + joywait = I_GetTime() + 5; + } + +#define JOY_BUTTON_MAPPED(x) ((x) >= 0) +#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (ev->data1 & (1 << (x))) != 0) + + if (JOY_BUTTON_PRESSED(joybfire)) + { + // Simulate a 'Y' keypress when Doom show a Y/N dialog with Fire button. + if (messageToPrint && messageNeedsInput) + { + key = key_menu_confirm; + } + else + { + key = key_menu_forward; + } + joywait = I_GetTime() + 5; + joystick_fire_countdown = 5; + } + if (JOY_BUTTON_PRESSED(joybuse)) + { + // Simulate a 'N' keypress when Doom show a Y/N dialog with Use button. + if (messageToPrint && messageNeedsInput) + { + key = key_menu_abort; + } + else + { + key = key_menu_back; + } + joywait = I_GetTime() + 5; + } + if (JOY_BUTTON_PRESSED(joybmenu)) + { + key = key_menu_activate; + joywait = I_GetTime() + 5; + } + } + else + { + if (ev->type == ev_mouse && mousewait < I_GetTime()) + { + mousey += ev->data3; + if (mousey < lasty-30) + { + key = key_menu_down; + mousewait = I_GetTime() + 5; + mousey = lasty -= 30; + } + else if (mousey > lasty+30) + { + key = key_menu_up; + mousewait = I_GetTime() + 5; + mousey = lasty += 30; + } + + mousex += ev->data2; + if (mousex < lastx-30) + { + key = key_menu_left; + mousewait = I_GetTime() + 5; + mousex = lastx -= 30; + } + else if (mousex > lastx+30) + { + key = key_menu_right; + mousewait = I_GetTime() + 5; + mousex = lastx += 30; + } + + if (ev->data1&1) + { + key = key_menu_forward; + mousewait = I_GetTime() + 15; + mouse_fire_countdown = 5; // villsa [STRIFE] + } + + if (ev->data1&2) + { + key = key_menu_back; + mousewait = I_GetTime() + 15; + } + } + else + { + if (ev->type == ev_keydown) + { + key = ev->data1; + ch = ev->data2; + } + } + } + + if (key == -1) + return false; + + // Save Game string input + if (saveStringEnter) + { + switch(key) + { + case KEY_BACKSPACE: + if (saveCharIndex > 0) + { + saveCharIndex--; + savegamestrings[quickSaveSlot][saveCharIndex] = 0; + } + break; + + case KEY_ESCAPE: + saveStringEnter = 0; + I_StopTextInput(); + M_StringCopy(savegamestrings[quickSaveSlot], saveOldString, + sizeof(savegamestrings[quickSaveSlot])); + break; + + case KEY_ENTER: + // [STRIFE] + saveStringEnter = 0; + I_StopTextInput(); + if(gameversion == exe_strife_1_31 && !namingCharacter) + { + // In 1.31, we can be here as a result of normal saving again, + // whereas in 1.2 this only ever happens when naming your + // character to begin a new game. + M_DoSave(quickSaveSlot); + return true; + } + if (savegamestrings[quickSaveSlot][0]) + M_DoNameChar(quickSaveSlot); + break; + + default: + // Savegame name entry. This is complicated. + // Vanilla has a bug where the shift key is ignored when entering + // a savegame name. If vanilla_keyboard_mapping is on, we want + // to emulate this bug by using ev->data1. But if it's turned off, + // it implies the user doesn't care about Vanilla emulation: + // instead, use ev->data3 which gives the fully-translated and + // modified key input. + + if (ev->type != ev_keydown) + { + break; + } + + if (vanilla_keyboard_mapping) + { + ch = ev->data1; + } + else + { + ch = ev->data3; + } + + ch = toupper(ch); + + if (ch != ' ' + && (ch - HU_FONTSTART < 0 || ch - HU_FONTSTART >= HU_FONTSIZE)) + { + break; + } + + if (ch >= 32 && ch <= 127 && + saveCharIndex < SAVESTRINGSIZE-1 && + M_StringWidth(savegamestrings[quickSaveSlot]) < + (SAVESTRINGSIZE-2)*8) + { + savegamestrings[quickSaveSlot][saveCharIndex++] = ch; + savegamestrings[quickSaveSlot][saveCharIndex] = 0; + } + break; + } + return true; + } + + // Take care of any messages that need input + if (messageToPrint) + { + if (messageNeedsInput) + { + if (key != ' ' && key != KEY_ESCAPE + && key != key_menu_confirm && key != key_menu_abort) + { + return false; + } + } + + menuactive = messageLastMenuActive; + messageToPrint = 0; + if (messageRoutine) + messageRoutine(key); + + menupause = false; // [STRIFE] unpause + menuactive = false; + S_StartSound(NULL, sfx_mtalht); // [STRIFE] sound + return true; + } + + // [STRIFE]: + // * In v1.2 this is moved to F9 (quickload) + // * In v1.31 it is moved to F12 with DM spy, and quicksave + // functionality is restored separate from normal saving + /* + if (devparm && key == key_menu_help) + { + G_ScreenShot (); + return true; + } + */ + + // F-Keys + if (!menuactive) + { + if (key == key_menu_decscreen) // Screen size down + { + if (automapactive || chat_on) + return false; + M_SizeDisplay(0); + S_StartSound(NULL, sfx_stnmov); + return true; + } + else if (key == key_menu_incscreen) // Screen size up + { + if (automapactive || chat_on) + return false; + M_SizeDisplay(1); + S_StartSound(NULL, sfx_stnmov); + return true; + } + else if (key == key_menu_help) // Help key + { + M_StartControlPanel (); + // haleyjd 08/29/10: [STRIFE] always ReadDef1 + currentMenu = &ReadDef1; + + itemOn = 0; + S_StartSound(NULL, sfx_swtchn); + return true; + } + else if (key == key_menu_save) // Save + { + // [STRIFE]: Hub saves + if(gameversion == exe_strife_1_31) + namingCharacter = false; // just saving normally, in 1.31 + + if(netgame || players[consoleplayer].health <= 0 || + players[consoleplayer].cheats & CF_ONFIRE) + { + S_StartSound(NULL, sfx_oof); + } + else + { + M_StartControlPanel(); + S_StartSound(NULL, sfx_swtchn); + M_SaveGame(0); + } + return true; + } + else if (key == key_menu_load) // Load + { + // [STRIFE]: Hub saves + if(gameversion == exe_strife_1_31) + { + // 1.31: normal save loading + namingCharacter = false; + M_StartControlPanel(); + M_LoadGame(0); + S_StartSound(NULL, sfx_swtchn); + } + else + { + // Pre 1.31: quickload only + S_StartSound(NULL, sfx_swtchn); + M_QuickLoad(); + } + return true; + } + else if (key == key_menu_volume) // Sound Volume + { + M_StartControlPanel (); + currentMenu = &SoundDef; + itemOn = sfx_vol; + S_StartSound(NULL, sfx_swtchn); + return true; + } + else if (key == key_menu_detail) // Detail toggle + { + //M_ChangeDetail(0); + M_AutoUseHealth(); // [STRIFE] + S_StartSound(NULL, sfx_swtchn); + return true; + } + else if (key == key_menu_qsave) // Quicksave + { + // [STRIFE]: Hub saves + if(gameversion == exe_strife_1_31) + namingCharacter = false; // for 1.31 save changes + + if(netgame || players[consoleplayer].health <= 0 || + players[consoleplayer].cheats & CF_ONFIRE) + { + S_StartSound(NULL, sfx_oof); + } + else + { + S_StartSound(NULL, sfx_swtchn); + M_QuickSave(); + } + return true; + } + else if (key == key_menu_endgame) // End game + { + S_StartSound(NULL, sfx_swtchn); + M_EndGame(0); + return true; + } + else if (key == key_menu_messages) // Toggle messages + { + //M_ChangeMessages(0); + M_ChangeShowText(); // [STRIFE] + S_StartSound(NULL, sfx_swtchn); + return true; + } + else if (key == key_menu_qload) // Quickload + { + // [STRIFE] + // * v1.2: takes a screenshot + // * v1.31: does quickload again + if(gameversion == exe_strife_1_31) + { + namingCharacter = false; + S_StartSound(NULL, sfx_swtchn); + M_QuickLoad(); + } + else + G_ScreenShot(); + return true; + } + else if (key == key_menu_quit) // Quit DOOM + { + S_StartSound(NULL, sfx_swtchn); + M_QuitStrife(0); + return true; + } + else if (key == key_menu_gamma) // gamma toggle + { + usegamma++; + if (usegamma > 4) + usegamma = 0; + players[consoleplayer].message = DEH_String(gammamsg[usegamma]); + I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); + return true; + } + else if(gameversion == exe_strife_1_31 && key == key_spy) + { + // haleyjd 20130301: 1.31 moved screenshots to F12. + G_ScreenShot(); + return true; + } + else if (key != 0 && key == key_menu_screenshot) + { + G_ScreenShot(); + return true; + } + } + + // Pop-up menu? + if (!menuactive) + { + if (key == key_menu_activate) + { + M_StartControlPanel (); + S_StartSound(NULL, sfx_swtchn); + return true; + } + return false; + } + + + // Keys usable within menu + + if (key == key_menu_down) + { + // Move down to next item + + do + { + if (itemOn+1 > currentMenu->numitems-1) + itemOn = 0; + else itemOn++; + S_StartSound(NULL, sfx_pstop); + } while(currentMenu->menuitems[itemOn].status==-1); + + return true; + } + else if (key == key_menu_up) + { + // Move back up to previous item + + do + { + if (!itemOn) + itemOn = currentMenu->numitems-1; + else itemOn--; + S_StartSound(NULL, sfx_pstop); + } while(currentMenu->menuitems[itemOn].status==-1); + + return true; + } + else if (key == key_menu_left) + { + // Slide slider left + + if (currentMenu->menuitems[itemOn].routine && + currentMenu->menuitems[itemOn].status == 2) + { + S_StartSound(NULL, sfx_stnmov); + currentMenu->menuitems[itemOn].routine(0); + } + return true; + } + else if (key == key_menu_right) + { + // Slide slider right + + if (currentMenu->menuitems[itemOn].routine && + currentMenu->menuitems[itemOn].status == 2) + { + S_StartSound(NULL, sfx_stnmov); + currentMenu->menuitems[itemOn].routine(1); + } + return true; + } + else if (key == key_menu_forward) + { + // Activate menu item + + if (currentMenu->menuitems[itemOn].routine && + currentMenu->menuitems[itemOn].status) + { + currentMenu->lastOn = itemOn; + if (currentMenu->menuitems[itemOn].status == 2) + { + currentMenu->menuitems[itemOn].routine(1); // right arrow + S_StartSound(NULL, sfx_stnmov); + } + else + { + currentMenu->menuitems[itemOn].routine(itemOn); + //S_StartSound(NULL, sfx_swish); [STRIFE] No sound is played here. + } + } + return true; + } + else if (key == key_menu_activate) + { + // Deactivate menu + if(gameversion == exe_strife_1_31) // [STRIFE]: 1.31 saving + namingCharacter = false; + + if(menuindialog) // [STRIFE] - Get out of dialog engine semi-gracefully + P_DialogDoChoice(-1); + + currentMenu->lastOn = itemOn; + M_ClearMenus (0); + S_StartSound(NULL, sfx_mtalht); // villsa [STRIFE]: sounds + return true; + } + else if (key == key_menu_back) + { + // Go back to previous menu + + currentMenu->lastOn = itemOn; + if (currentMenu->prevMenu) + { + currentMenu = currentMenu->prevMenu; + itemOn = currentMenu->lastOn; + S_StartSound(NULL, sfx_swtchn); + } + return true; + } + + // Keyboard shortcut? + // Vanilla Strife has a weird behavior where it jumps to the scroll bars + // when certain keys are pressed, so emulate this. + + else if (ch != 0 || IsNullKey(key)) + { + // Keyboard shortcut? + + for (i = itemOn+1;i < currentMenu->numitems;i++) + { + if (currentMenu->menuitems[i].alphaKey == ch) + { + itemOn = i; + S_StartSound(NULL, sfx_pstop); + return true; + } + } + + for (i = 0;i <= itemOn;i++) + { + if (currentMenu->menuitems[i].alphaKey == ch) + { + itemOn = i; + S_StartSound(NULL, sfx_pstop); + return true; + } + } + } + + return false; +} + + + +// +// M_StartControlPanel +// +void M_StartControlPanel (void) +{ + // intro might call this repeatedly + if (menuactive) + return; + + menuactive = 1; + menupause = true; + currentMenu = &MainDef; // JDC + itemOn = currentMenu->lastOn; // JDC +} + + +// +// M_Drawer +// Called after the view has been rendered, +// but before it has been blitted. +// +void M_Drawer (void) +{ + static short x; + static short y; + unsigned int i; + unsigned int max; + char string[80]; + const char *name; + int start; + + inhelpscreens = false; + + // Horiz. & Vertically center string and print it. + if (messageToPrint) + { + start = 0; + y = 100 - M_StringHeight(messageString) / 2; + while (messageString[start] != '\0') + { + int foundnewline = 0; + + for (i = 0; i < strlen(messageString + start); i++) + { + if (messageString[start + i] == '\n') + { + M_StringCopy(string, messageString + start, + sizeof(string)); + if (i < sizeof(string)) + { + string[i] = '\0'; + } + + foundnewline = 1; + start += i + 1; + break; + } + } + + if (!foundnewline) + { + M_StringCopy(string, messageString + start, + sizeof(string)); + start += strlen(string); + } + + x = 160 - M_StringWidth(string) / 2; + M_WriteText(x, y, string); + y += SHORT(hu_font[0]->height); + } + + return; + } + + if (!menuactive) + return; + + if (currentMenu->routine) + currentMenu->routine(); // call Draw routine + + // DRAW MENU + x = currentMenu->x; + y = currentMenu->y; + max = currentMenu->numitems; + + for (i=0;imenuitems[i].name); + + if (name[0]) + { + V_DrawPatchDirect (x, y, W_CacheLumpName(name, PU_CACHE)); + } + y += LINEHEIGHT; + } + + + // haleyjd 08/27/10: [STRIFE] Adjust to draw spinning Sigil + // DRAW SIGIL + V_DrawPatchDirect(x + CURSORXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT, + W_CacheLumpName(DEH_String(cursorName[whichCursor]), + PU_CACHE)); + +} + + +// +// M_ClearMenus +// +// haleyjd 08/28/10: [STRIFE] Added an int param so this can be called by menus. +// 09/08/10: Added menupause. +// +void M_ClearMenus (int choice) +{ + choice = 0; // haleyjd: for no warning; not from decompilation. + menuactive = 0; + menupause = 0; +} + + + + +// +// M_SetupNextMenu +// +void M_SetupNextMenu(menu_t *menudef) +{ + currentMenu = menudef; + itemOn = currentMenu->lastOn; +} + + +// +// M_Ticker +// +// haleyjd 08/27/10: [STRIFE] Rewritten for Sigil cursor +// +void M_Ticker (void) +{ + if (--cursorAnimCounter <= 0) + { + whichCursor = (whichCursor + 1) % 8; + cursorAnimCounter = 5; + } +} + + +// +// M_Init +// +// haleyjd 08/27/10: [STRIFE] Removed DOOM gamemode stuff +// +void M_Init (void) +{ + currentMenu = &MainDef; + menuactive = 0; + itemOn = currentMenu->lastOn; + whichCursor = 0; + cursorAnimCounter = 10; + screenSize = screenblocks - 3; + messageToPrint = 0; + messageString = NULL; + messageLastMenuActive = menuactive; // STRIFE-FIXME: assigns 0 here... + quickSaveSlot = -1; + + // [STRIFE]: Initialize savegame paths and clear temporary directory + G_WriteSaveName(5, "ME"); + ClearTmp(); + + // Here we could catch other version dependencies, + // like HELP1/2, and four episodes. +} + diff --git a/games/NXDoom/src/strife/m_menu.h b/games/NXDoom/src/strife/m_menu.h new file mode 100644 index 00000000000..08ad1a244dc --- /dev/null +++ b/games/NXDoom/src/strife/m_menu.h @@ -0,0 +1,104 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Menu widget stuff, episode selection and such. +// + + +#ifndef __M_MENU__ +#define __M_MENU__ + +#include "d_event.h" + +// +// MENU TYPEDEFS +// + +// haleyjd 09/04/10: [STRIFE] Made external + +typedef struct +{ + // 0 = no cursor here, 1 = ok, 2 = arrows ok + short status; + + char name[10]; + + // choice = menu item #. + // if status = 2, + // choice=0:leftarrow,1:rightarrow + void (*routine)(int choice); + + // hotkey in menu + char alphaKey; +} menuitem_t; + +typedef struct menu_s +{ + short numitems; // # of menu items + struct menu_s* prevMenu; // previous menu + menuitem_t* menuitems; // menu items + void (*routine)(); // draw routine + short x; + short y; // x,y of menu + short lastOn; // last item user was on in menu +} menu_t; + +extern menu_t* currentMenu; // villsa [STRIFE] made external +extern short itemOn; + +// +// MENUS +// +// Called by main loop, +// saves config file and calls I_Quit when user exits. +// Even when the menu is not displayed, +// this can resize the view and change game parameters. +// Does all the real work of the menu interaction. +boolean M_Responder (event_t *ev); + + +// Called by main loop, +// only used for menu (skull cursor) animation. +void M_Ticker (void); + +// Called by main loop, +// draws the menus directly into the screen buffer. +void M_Drawer (void); + +// Called by D_DoomMain, +// loads the config file. +void M_Init (void); + +// Called by intro code to force menu up upon a keypress, +// does nothing if menu is already up. +void M_StartControlPanel (void); + +// haleyjd 09/04/10: Externalized. Draws menu text. +int M_WriteText(int x, int y, const char *string); + +// haleyjd 09/04/10: [STRIFE] New function. +void M_DialogDimMsg(int x, int y, char *str, boolean useyfont); + +// haleyjd [STRIFE] Externalized +void M_ClearMenus (int choice); +void M_LoadSelect(int choice); + +extern int detailLevel; +extern int screenblocks; + +extern boolean inhelpscreens; + + +#endif diff --git a/games/NXDoom/src/strife/m_random.c b/games/NXDoom/src/strife/m_random.c new file mode 100644 index 00000000000..2098c1a7a90 --- /dev/null +++ b/games/NXDoom/src/strife/m_random.c @@ -0,0 +1,80 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Random number LUT. +// + + +#include + +#include "m_random.h" + +// +// M_Random +// Returns a 0-255 number +// + +static const unsigned char rndtable[256] = { + 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 , + 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 , + 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 , + 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 , + 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 , + 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 , + 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 , + 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 , + 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 , + 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 , + 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 , + 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 , + 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 , + 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 , + 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 , + 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 , + 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 , + 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 , + 120, 163, 236, 249 +}; + +int rndindex = 0; +int prndindex = 0; + +// Which one is deterministic? +int P_Random (void) +{ + prndindex = (prndindex+1)&0xff; + return rndtable[prndindex]; +} + +int M_Random (void) +{ + rndindex = (rndindex+1)&0xff; + return rndtable[rndindex]; +} + +// +// M_ClearRandom +// +// haleyjd 20110204 [STRIFE]: No "seeding" of M_Random index +// +void M_ClearRandom (void) +{ + prndindex = 0; + rndindex = 0; +} + + + + diff --git a/games/NXDoom/src/strife/m_random.h b/games/NXDoom/src/strife/m_random.h new file mode 100644 index 00000000000..aa6291ae9e4 --- /dev/null +++ b/games/NXDoom/src/strife/m_random.h @@ -0,0 +1,39 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __M_RANDOM__ +#define __M_RANDOM__ + + +#include "doomtype.h" + + + +// Returns a number from 0 to 255, +// from a lookup table. +int M_Random (void); + +// As M_Random, but used only by the play simulation. +int P_Random (void); + +// Fix randoms for demos. +void M_ClearRandom (void); + + +#endif diff --git a/games/NXDoom/src/strife/m_saves.c b/games/NXDoom/src/strife/m_saves.c new file mode 100644 index 00000000000..561ec6a23ce --- /dev/null +++ b/games/NXDoom/src/strife/m_saves.c @@ -0,0 +1,482 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2010 James Haley, Samuel Villarreal +// +// 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. +// +// DESCRIPTION: +// +// [STRIFE] New Module +// +// Strife Hub Saving Code +// + +#include +#include +#include + +#include "z_zone.h" +#include "i_glob.h" +#include "i_system.h" +#include "d_player.h" +#include "deh_str.h" +#include "doomstat.h" +#include "m_misc.h" +#include "m_saves.h" +#include "p_dialog.h" + +// +// File Paths +// +// Strife maintains multiple file paths related to savegames. +// +char *savepath; // The actual path of the selected saveslot +char *savepathtemp; // The path of the temporary saveslot (strfsav6.ssg) +char *loadpath; // Path used while loading the game + +char character_name[CHARACTER_NAME_LEN]; // Name of "character" for saveslot + +// +// ClearTmp +// +// Clear the temporary save directory +// +void ClearTmp(void) +{ + glob_t *glob; + + if(savepathtemp == NULL) + I_Error("you fucked up savedir man!"); + + glob = I_StartGlob(savepathtemp, "*", 0); + if (glob == NULL) + I_Error("ClearTmp: Couldn't open dir %s", savepathtemp); + + for (;;) + { + const char *path = I_NextGlob(glob); + + if (path == NULL) + { + break; + } + M_remove(path); + } + + I_EndGlob(glob); +} + +// +// ClearSlot +// +// Clear a single save slot folder +// +void ClearSlot(void) +{ + glob_t *glob; + + if(savepath == NULL) + I_Error("userdir is fucked up man!"); + + glob = I_StartGlob(savepath, "*", 0); + if (glob == NULL) + I_Error("ClearSlot: Couldn't open dir %s", savepath); + + for (;;) + { + const char *filepath = I_NextGlob(glob); + + if (filepath == NULL) + { + break; + } + + M_remove(filepath); + } + + I_EndGlob(glob); +} + +// +// FromCurr +// +// Copying files from savepathtemp to savepath +// +void FromCurr(void) +{ + glob_t *glob; + + glob = I_StartGlob(savepathtemp, "*", 0); + + if (glob == NULL) + I_Error("FromCurr: Couldn't open dir %s", savepathtemp); + + for (;;) + { + byte *filebuffer; + int filelen; + const char *srcfilename; + char *dstfilename; + + srcfilename = I_NextGlob(glob); + if (srcfilename == NULL) + { + break; + } + + dstfilename = M_SafeFilePath(savepath, M_BaseName(srcfilename)); + + filelen = M_ReadFile(srcfilename, &filebuffer); + M_WriteFile(dstfilename, filebuffer, filelen); + + Z_Free(filebuffer); + Z_Free(dstfilename); + } + + I_EndGlob(glob); +} + +// +// ToCurr +// +// Copying files from savepath to savepathtemp +// +void ToCurr(void) +{ + glob_t *glob; + + ClearTmp(); + + // BUG: Rogue copypasta'd this error message, which is why we don't know + // the real original name of this function. + glob = I_StartGlob(savepath, "*", 0); + if (glob == NULL) + I_Error("ClearSlot: Couldn't open dir %s", savepath); + + for (;;) + { + byte *filebuffer; + int filelen; + const char *srcfilename; + char *dstfilename; + + srcfilename = I_NextGlob(glob); + if (srcfilename == NULL) + { + break; + } + + dstfilename = M_SafeFilePath(savepathtemp, M_BaseName(srcfilename)); + + filelen = M_ReadFile(srcfilename, &filebuffer); + M_WriteFile(dstfilename, filebuffer, filelen); + + Z_Free(filebuffer); + Z_Free(dstfilename); + } + + I_EndGlob(glob); +} + +// +// M_SaveMoveMapToHere +// +// Moves a map to the "HERE" save. +// +void M_SaveMoveMapToHere(void) +{ + char *mapsave = NULL; + char *heresave = NULL; + char tmpnum[33]; + + // haleyjd: no itoa available... + M_snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap); + + // haleyjd: use M_SafeFilePath, not sprintf + mapsave = M_SafeFilePath(savepath, tmpnum); + heresave = M_SafeFilePath(savepath, "here"); + + // haleyjd: use M_FileExists, not access + if(M_FileExists(mapsave)) + { + M_remove(heresave); + M_rename(mapsave, heresave); + } + + Z_Free(mapsave); + Z_Free(heresave); +} + +// +// M_SaveMoveHereToMap +// +// Moves the "HERE" save to a map. +// +void M_SaveMoveHereToMap(void) +{ + char *mapsave = NULL; + char *heresave = NULL; + char tmpnum[33]; + + // haleyjd: no itoa available... + M_snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap); + + mapsave = M_SafeFilePath(savepathtemp, tmpnum); + heresave = M_SafeFilePath(savepathtemp, "here"); + + if(M_FileExists(heresave)) + { + M_remove(mapsave); + M_rename(heresave, mapsave); + } + + Z_Free(mapsave); + Z_Free(heresave); +} + +// +// M_SaveMisObj +// +// Writes the mission objective into the MIS_OBJ file. +// +boolean M_SaveMisObj(const char *path) +{ + boolean result; + char *destpath = NULL; + + // haleyjd 20110210: use M_SafeFilePath, not sprintf + destpath = M_SafeFilePath(path, "mis_obj"); + result = M_WriteFile(destpath, mission_objective, OBJECTIVE_LEN); + + Z_Free(destpath); + return result; +} + +// +// M_ReadMisObj +// +// Reads the mission objective from the MIS_OBJ file. +// +void M_ReadMisObj(void) +{ + FILE *f = NULL; + char *srcpath = NULL; + + // haleyjd: use M_SafeFilePath, not sprintf + srcpath = M_SafeFilePath(savepathtemp, "mis_obj"); + + if((f = M_fopen(srcpath, "rb"))) + { + int retval = fread(mission_objective, 1, OBJECTIVE_LEN, f); + fclose(f); + if (retval != OBJECTIVE_LEN) + { + I_Error("M_ReadMisObj: error while reading mission objective"); + } + } + + Z_Free(srcpath); +} + +//============================================================================= +// +// Original Routines +// +// haleyjd - None of the below code is derived from Strife itself, but has been +// adapted or created in order to provide secure, portable filepath handling +// for the purposes of savegame support. This is partially needed to allow for +// differences in Choco due to it being multiplatform. The rest exists because +// I cannot stand programming in an impoverished ANSI C environment that +// calls sprintf on fixed-size buffers. :P +// + +// +// M_Calloc +// +// haleyjd 20110210 - original routine +// Because Choco doesn't have Z_Calloc O_o +// +void *M_Calloc(size_t n1, size_t n2) +{ + return (n1 *= n2) ? memset(Z_Malloc(n1, PU_STATIC, NULL), 0, n1) : NULL; +} + +// +// M_StringAlloc +// +// haleyjd: This routine takes any number of strings and a number of extra +// characters, calculates their combined length, and calls Z_Alloca to create +// a temporary buffer of that size. This is extremely useful for allocation of +// file paths, and is used extensively in d_main.c. The pointer returned is +// to a temporary Z_Alloca buffer, which lives until the next main loop +// iteration, so don't cache it. Note that this idiom is not possible with the +// normal non-standard alloca function, which allocates stack space. +// +// [STRIFE] - haleyjd 20110210 +// This routine is taken from the Eternity Engine and adapted to do without +// Z_Alloca. I need secure string concatenation for filepath handling. The +// only difference from use in EE is that the pointer returned in *str must +// be manually freed. +// +int M_StringAlloc(char **str, int numstrs, size_t extra, const char *str1, ...) +{ + va_list args; + size_t len = extra; + + if(numstrs < 1) + I_Error("M_StringAlloc: invalid input\n"); + + len += strlen(str1); + + --numstrs; + + if(numstrs != 0) + { + va_start(args, str1); + + while(numstrs != 0) + { + const char *argstr = va_arg(args, const char *); + + len += strlen(argstr); + + --numstrs; + } + + va_end(args); + } + + ++len; + + *str = (char *)(M_Calloc(1, len)); + + return len; +} + +// +// M_SafeFilePath +// +// haleyjd 20110210 - original routine. +// This routine performs safe, portable concatenation of a base file path +// with another path component or file name. The returned string is Z_Malloc'd +// and should be freed when it has exhausted its usefulness. +// +char *M_SafeFilePath(const char *basepath, const char *newcomponent) +{ + int newstrlen = 0; + char *newstr = NULL; + + if (!strcmp(basepath, "")) + { + basepath = "."; + } + + // Always throw in a slash. M_NormalizeSlashes will remove it in the case + // that either basepath or newcomponent includes a redundant slash at the + // end or beginning respectively. + newstrlen = M_StringAlloc(&newstr, 3, 1, basepath, "/", newcomponent); + M_snprintf(newstr, newstrlen, "%s/%s", basepath, newcomponent); + M_NormalizeSlashes(newstr); + + return newstr; +} + +// +// M_CreateSaveDirs +// +// haleyjd 20110210: Vanilla Strife went tits-up if it didn't have the full set +// of save folders which were created externally by the installer. fraggle says +// that's no good for Choco purposes, and I agree, so this routine will create +// the full set of folders under the configured savegamedir. +// +void M_CreateSaveDirs(const char *savedir) +{ + int i; + + for(i = 0; i < 7; i++) + { + char *compositedir; + + // compose the full path by concatenating with savedir + compositedir = M_SafeFilePath(savedir, M_MakeStrifeSaveDir(i, "")); + + M_MakeDirectory(compositedir); + + Z_Free(compositedir); + } +} + +// +// M_MakeStrifeSaveDir +// +// haleyjd 20110211: Convenience routine +// +char *M_MakeStrifeSaveDir(int slotnum, const char *extra) +{ + static char tmpbuffer[32]; + + M_snprintf(tmpbuffer, sizeof(tmpbuffer), + "strfsav%d.ssg%s", slotnum, extra); + + return tmpbuffer; +} + +// +// M_GetFilePath +// +// haleyjd: STRIFE-FIXME: Temporary? +// Code borrowed from Eternity, and modified to return separator char +// +char M_GetFilePath(const char *fn, char *dest, size_t len) +{ + boolean found_slash = false; + char *p; + char sepchar = '\0'; + + memset(dest, 0, len); + + p = dest + len - 1; + + M_StringCopy(dest, fn, len); + + while(p >= dest) + { + if(*p == '/' || *p == '\\') + { + sepchar = *p; + found_slash = true; // mark that the path ended with a slash + *p = '\0'; + break; + } + *p = '\0'; + p--; + } + + // haleyjd: in the case that no slash was ever found, yet the + // path string is empty, we are dealing with a file local to the + // working directory. The proper path to return for such a string is + // not "", but ".", since the format strings add a slash now. When + // the string is empty but a slash WAS found, we really do want to + // return the empty string, since the path is relative to the root. + if(!found_slash && *dest == '\0') + *dest = '.'; + + // if a separator is not found, default to forward, because Windows + // supports that too. + if(sepchar == '\0') + sepchar = '/'; + + return sepchar; +} + +// EOF + + diff --git a/games/NXDoom/src/strife/m_saves.h b/games/NXDoom/src/strife/m_saves.h new file mode 100644 index 00000000000..ce278cba96d --- /dev/null +++ b/games/NXDoom/src/strife/m_saves.h @@ -0,0 +1,55 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2010 James Haley, Samuel Villareal +// +// 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. +// +// DESCRIPTION: +// +// [STRIFE] New Module +// +// Strife Hub Saving Code +// + +#ifndef M_SAVES_H__ +#define M_SAVES_H__ + +#define CHARACTER_NAME_LEN 32 + +extern char *savepath; +extern char *savepathtemp; +extern char *loadpath; +extern char character_name[CHARACTER_NAME_LEN]; + +// Strife Savegame Functions +void ClearTmp(void); +void ClearSlot(void); +void FromCurr(void); +void ToCurr(void); +void M_SaveMoveMapToHere(void); +void M_SaveMoveHereToMap(void); + +boolean M_SaveMisObj(const char *path); +void M_ReadMisObj(void); + +// Custom Utilities for Filepath Handling +void *M_Calloc(size_t n1, size_t n2); +int M_StringAlloc(char **str, int numstrs, size_t extra, const char *str1, ...); +char *M_SafeFilePath(const char *basepath, const char *newcomponent); +char M_GetFilePath(const char *fn, char *dest, size_t len); +char *M_MakeStrifeSaveDir(int slotnum, const char *extra); +void M_CreateSaveDirs(const char *savedir); + +#endif + +// EOF + + diff --git a/games/NXDoom/src/strife/p_ceilng.c b/games/NXDoom/src/strife/p_ceilng.c new file mode 100644 index 00000000000..93c0c7f2e15 --- /dev/null +++ b/games/NXDoom/src/strife/p_ceilng.c @@ -0,0 +1,343 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising) +// + + + +#include "z_zone.h" +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "sounds.h" + +// +// CEILINGS +// + + +ceiling_t* activeceilings[MAXCEILINGS]; + + +// +// T_MoveCeiling +// + +void T_MoveCeiling (ceiling_t* ceiling) +{ + result_e res; + + switch(ceiling->direction) + { + case 0: + // IN STASIS + break; + case 1: + // UP + res = T_MovePlane(ceiling->sector, + ceiling->speed, + ceiling->topheight, + false,1,ceiling->direction); + + if (!(leveltime&7)) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + break; + default: + S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); + // ? + break; + } + } + + if (res == pastdest) + { + switch(ceiling->type) + { + case raiseToHighest: + P_RemoveActiveCeiling(ceiling); + break; + + case silentCrushAndRaise: + S_StartSound(&ceiling->sector->soundorg, sfx_pstop); + case fastCrushAndRaise: + case crushAndRaise: + ceiling->direction = -1; + break; + + default: + break; + } + + } + break; + + case -1: + // DOWN + res = T_MovePlane(ceiling->sector, + ceiling->speed, + ceiling->bottomheight, + ceiling->crush,1,ceiling->direction); + + if (!(leveltime&7)) + { + switch(ceiling->type) + { + case silentCrushAndRaise: break; + default: + S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); + } + } + + if (res == pastdest) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + S_StartSound(&ceiling->sector->soundorg, sfx_pstop); + case crushAndRaise: + ceiling->speed = CEILSPEED; + case fastCrushAndRaise: + ceiling->direction = 1; + break; + + case lowerAndCrush: + case lowerToFloor: + P_RemoveActiveCeiling(ceiling); + break; + + default: + break; + } + } + else // ( res != pastdest ) + { + if (res == crushed) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + case crushAndRaise: + case lowerAndCrush: + ceiling->speed = CEILSPEED / 8; + break; + + default: + break; + } + } + } + break; + } +} + + +// +// EV_DoCeiling +// Move a ceiling up/down and all around! +// +// haleyjd 10/04/10: [STRIFE] Changes: +// * Fast crushers were made 2x as fast. +// * lowerAndCrush was apparently "fixed" to actually crush, and was also +// altered to lower all the way to the floor rather than remain 8 above. +// * silentCrushAndRaise and crushAndRaise no longer crush. +int +EV_DoCeiling +( line_t* line, + ceiling_e type ) +{ + int secnum; + int rtn; + sector_t* sec; + ceiling_t* ceiling; + + secnum = -1; + rtn = 0; + + // Reactivate in-stasis ceilings...for certain types. + switch(type) + { + case fastCrushAndRaise: + case silentCrushAndRaise: + case crushAndRaise: + P_ActivateInStasisCeiling(line); + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + // new door thinker + rtn = 1; + ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); + P_AddThinker (&ceiling->thinker); + sec->specialdata = ceiling; + ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = false; + + switch(type) + { + case fastCrushAndRaise: + // [STRIFE]: Speed of fast crushers increased by 2x! + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); + ceiling->direction = -1; + ceiling->speed = CEILSPEED * 4; // [STRIFE] Was CEILSPEED * 2 + break; + + case lowerAndCrush: + // [STRIFE] lowerAndCrush doesn't seem to have crushed in DOOM, + // but it was certainly made to do so in Strife! It is also + // changed to lower all the way to the floor. + ceiling->crush = 1; + ceiling->direction = -1; + ceiling->speed = CEILSPEED; + ceiling->bottomheight = sec->floorheight; + break; + + case silentCrushAndRaise: + case crushAndRaise: + // [STRIFE] haleyjd 20130209: Turns out these types do NOT crush + // in Strife... yeah, that makes a lot of sense. Thanks to Gez for + // having detected this difference. + //ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + + case lowerToFloor: + ceiling->bottomheight = sec->floorheight; + if (type != lowerToFloor) + ceiling->bottomheight += 8*FRACUNIT; + ceiling->direction = -1; + ceiling->speed = CEILSPEED; + break; + + case raiseToHighest: + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + ceiling->speed = CEILSPEED; + break; + } + + ceiling->tag = sec->tag; + ceiling->type = type; + P_AddActiveCeiling(ceiling); + } + return rtn; +} + + +// +// Add an active ceiling +// +void P_AddActiveCeiling(ceiling_t* c) +{ + int i; + + for (i = 0; i < MAXCEILINGS;i++) + { + if (activeceilings[i] == NULL) + { + activeceilings[i] = c; + return; + } + } +} + + + +// +// Remove a ceiling's thinker +// +void P_RemoveActiveCeiling(ceiling_t* c) +{ + int i; + + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] == c) + { + activeceilings[i]->sector->specialdata = NULL; + P_RemoveThinker (&activeceilings[i]->thinker); + activeceilings[i] = NULL; + break; + } + } +} + + + +// +// Restart a ceiling that's in-stasis +// +void P_ActivateInStasisCeiling(line_t* line) +{ + int i; + + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] + && (activeceilings[i]->tag == line->tag) + && (activeceilings[i]->direction == 0)) + { + activeceilings[i]->direction = activeceilings[i]->olddirection; + activeceilings[i]->thinker.function.acp1 + = (actionf_p1)T_MoveCeiling; + } + } +} + + + +// +// EV_CeilingCrushStop +// Stop a ceiling from crushing! +// +int EV_CeilingCrushStop(line_t *line) +{ + int i; + int rtn; + + rtn = 0; + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] + && (activeceilings[i]->tag == line->tag) + && (activeceilings[i]->direction != 0)) + { + activeceilings[i]->olddirection = activeceilings[i]->direction; + activeceilings[i]->thinker.function.acv = (actionf_v)NULL; + activeceilings[i]->direction = 0; // in-stasis + rtn = 1; + } + } + + + return rtn; +} diff --git a/games/NXDoom/src/strife/p_dialog.c b/games/NXDoom/src/strife/p_dialog.c new file mode 100644 index 00000000000..e2988a481bb --- /dev/null +++ b/games/NXDoom/src/strife/p_dialog.c @@ -0,0 +1,1413 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2010 James Haley, Samuel Villarreal +// +// 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. +// +// DESCRIPTION: +// +// [STRIFE] New Module +// +// Dialog Engine for Strife +// + +#include + +#include "z_zone.h" +#include "w_wad.h" +#include "deh_str.h" +#include "d_main.h" +#include "d_mode.h" +#include "d_player.h" +#include "doomstat.h" +#include "m_random.h" +#include "m_menu.h" +#include "m_misc.h" +#include "r_main.h" +#include "v_video.h" +#include "p_local.h" +#include "sounds.h" +#include "p_dialog.h" +#include "s_sound.h" +#include "p_local.h" +#include "p_inter.h" + +// +// Defines and Macros +// + +// haleyjd: size of the original Strife mapdialog_t structure. +#define ORIG_MAPDIALOG_SIZE 0x5EC + +#define DIALOG_INT(field, ptr) \ + field = ((int)ptr[0] | \ + ((int)ptr[1] << 8) | \ + ((int)ptr[2] << 16) | \ + ((int)ptr[3] << 24)); \ + ptr += 4; + +#define DIALOG_STR(field, ptr, len) \ + memcpy(field, ptr, len); \ + ptr += len; + +// +// Globals +// + +// This can be toggled at runtime to determine if the full dialog messages +// are subtitled on screen or not. Defaults to off. +int dialogshowtext = false; + +// The global mission objective buffer. This gets written to and read from file, +// and is set by dialogs and line actions. +char mission_objective[OBJECTIVE_LEN]; + +// +// Static Globals +// + +// True if SCRIPT00 is loaded. +static boolean script0loaded; + +// Number of dialogs defined in the current level's script. +static int numleveldialogs; + +// The actual level dialogs. This didn't exist in Strife, but is new to account +// for structure alignment/packing concerns, given that Chocolate Doom is +// multiplatform. +static mapdialog_t *leveldialogs; + +// The actual script00 dialogs. As above. +static mapdialog_t *script0dialogs; + +// Number of dialogs defined in the SCRIPT00 lump. +static int numscript0dialogs; + +// The player engaged in dialog. This is always player 1, though, since Rogue +// never completed the ability to use dialog outside of single-player mode. +static player_t *dialogplayer; + +// The object to which the player is speaking. +static mobj_t *dialogtalker; + +// The talker's current angle +static angle_t dialogtalkerangle; + +// The currently active mapdialog object. +static mapdialog_t *currentdialog; + +// Text at the end of the choices +static char dialoglastmsgbuffer[48]; + +// Item to display to player when picked up or recieved +static char pickupstring[46]; + +// Health based on gameskill given by the front's medic +static const int healthamounts[] = { -100 , -75, -50, -50, -100 }; + +//============================================================================= +// +// Dialog State Sets +// +// These are used to animate certain actors in response to what happens in +// their dialog sequences. +// + +typedef struct dialogstateset_s +{ + mobjtype_t type; // the type of object + statenum_t greet; // greeting state, for start of dialog + statenum_t yes; // "yes" state, for an affirmative response + statenum_t no; // "no" state, when you don't have the right items +} dialogstateset_t; + +static dialogstateset_t dialogstatesets[] = +{ + { MT_PLAYER, S_NULL, S_NULL, S_NULL }, + { MT_SHOPKEEPER_W, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, + { MT_SHOPKEEPER_B, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, + { MT_SHOPKEEPER_A, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, + { MT_SHOPKEEPER_M, S_MRGT_00, S_MRYS_00, S_MRNO_00 } +}; + +// Rogue stored this in a static global rather than making it a define... +static int numdialogstatesets = arrlen(dialogstatesets); + +// Current dialog talker state +static dialogstateset_t *dialogtalkerstates; + +//============================================================================= +// +// Random Messages +// +// Rogue hard-coded these so they wouldn't have to repeat them several times +// in the SCRIPT00 lump, apparently. +// + +#define MAXRNDMESSAGES 10 + +typedef struct rndmessage_s +{ + const char *type_name; + int nummessages; + const char *messages[MAXRNDMESSAGES]; +} rndmessage_t; + +static rndmessage_t rndMessages[] = +{ + // Peasants + { + "PEASANT", + 10, + { + "PLEASE DON'T HURT ME.", + + "IF YOU'RE LOOKING TO HURT ME, I'M \n" + "NOT REALLY WORTH THE EFFORT.", + + "I DON'T KNOW ANYTHING.", + + "GO AWAY OR I'LL CALL THE GUARDS!", + + "I WISH SOMETIMES THAT ALL THESE \n" + "REBELS WOULD JUST LEARN THEIR \n" + "PLACE AND STOP THIS NONSENSE.", + + "JUST LEAVE ME ALONE, OK?", + + "I'M NOT SURE, BUT SOMETIMES I THINK \n" + "THAT I KNOW SOME OF THE ACOLYTES.", + + "THE ORDER'S GOT EVERYTHING AROUND HERE PRETTY WELL LOCKED UP TIGHT.", + + "THERE'S NO WAY THAT THIS IS JUST A \n" + "SECURITY FORCE.", + + "I'VE HEARD THAT THE ORDER IS REALLY \n" + "NERVOUS ABOUT THE FRONT'S \n" + "ACTIONS AROUND HERE." + } + }, + // Rebel + { + "REBEL", + 10, + { + "THERE'S NO WAY THE ORDER WILL \n" + "STAND AGAINST US.", + + "WE'RE ALMOST READY TO STRIKE. \n" + "MACIL'S PLANS ARE FALLING IN PLACE.", + + "WE'RE ALL BEHIND YOU, DON'T WORRY.", + + "DON'T GET TOO CLOSE TO ANY OF THOSE BIG ROBOTS. THEY'LL MELT YOU DOWN \n" + "FOR SCRAP!", + + "THE DAY OF OUR GLORY WILL SOON \n" + "COME, AND THOSE WHO OPPOSE US WILL \n" + "BE CRUSHED!", + + "DON'T GET TOO COMFORTABLE. WE'VE \n" + "STILL GOT OUR WORK CUT OUT FOR US.", + + "MACIL SAYS THAT YOU'RE THE NEW \n" + "HOPE. BEAR THAT IN MIND.", + + "ONCE WE'VE TAKEN THESE CHARLATANS DOWN, WE'LL BE ABLE TO REBUILD THIS " + "WORLD AS IT SHOULD BE.", + + "REMEMBER THAT YOU AREN'T FIGHTING \n" + "JUST FOR YOURSELF, BUT FOR \n" + "EVERYONE HERE AND OUTSIDE.", + + "AS LONG AS ONE OF US STILL STANDS, \n" + "WE WILL WIN." + } + }, + // Acolyte + { + "AGUARD", + 10, + { + "MOVE ALONG, PEASANT.", + + "FOLLOW THE TRUE FAITH, ONLY THEN \n" + "WILL YOU BEGIN TO UNDERSTAND.", + + "ONLY THROUGH DEATH CAN ONE BE \n" + "TRULY REBORN.", + + "I'M NOT INTERESTED IN YOUR USELESS \n" + "DRIVEL.", + + "IF I HAD WANTED TO TALK TO YOU I \n" + "WOULD HAVE TOLD YOU SO.", + + "GO AND ANNOY SOMEONE ELSE!", + + "KEEP MOVING!", + + "IF THE ALARM GOES OFF, JUST STAY OUT OF OUR WAY!", + + "THE ORDER WILL CLEANSE THE WORLD \n" + "AND USHER IT INTO THE NEW ERA.", + + "PROBLEM? NO, I THOUGHT NOT.", + } + }, + // Beggar + { + "BEGGAR", + 10, + { + "ALMS FOR THE POOR?", + + "WHAT ARE YOU LOOKING AT, SURFACER?", + + "YOU WOULDN'T HAVE ANY EXTRA FOOD, WOULD YOU?", + + "YOU SURFACE PEOPLE WILL NEVER \n" + " " + " UNDERSTAND US.", + + "HA, THE GUARDS CAN'T FIND US. THOSE \n" + "IDIOTS DON'T EVEN KNOW WE EXIST.", + + "ONE DAY EVERYONE BUT THOSE WHO SERVE THE ORDER WILL BE FORCED TO " + " JOIN US.", + + "STARE NOW, BUT YOU KNOW THAT THIS WILL BE YOUR OWN FACE ONE DAY.", + + // Note: "NOTHING THING" is an authentic typo + "THERE'S NOTHING THING MORE \n" + "ANNOYING THAN A SURFACER WITH AN ATTITUDE!", + + "THE ORDER WILL MAKE SHORT WORK OF YOUR PATHETIC FRONT.", + + "WATCH YOURSELF SURFACER. WE KNOW OUR ENEMIES!" + } + }, + // Templar + { + "PGUARD", + 10, + { + "WE ARE THE HANDS OF FATE. TO EARN \n" + "OUR WRATH IS TO FIND OBLIVION!", + + "THE ORDER WILL CLEANSE THE WORLD \n" + "OF THE WEAK AND CORRUPT!", + + "OBEY THE WILL OF THE MASTERS!", + + "LONG LIFE TO THE BROTHERS OF THE \n" + "ORDER!", + + "FREE WILL IS AN ILLUSION THAT BINDS \n" + "THE WEAK MINDED.", + + "POWER IS THE PATH TO GLORY. TO \n" + "FOLLOW THE ORDER IS TO WALK THAT \n" + "PATH!", + + "TAKE YOUR PLACE AMONG THE \n" + "RIGHTEOUS, JOIN US!", + + "THE ORDER PROTECTS ITS OWN.", + + "ACOLYTES? THEY HAVE YET TO SEE THE FULL GLORY OF THE ORDER.", + + "IF THERE IS ANY HONOR INSIDE THAT \n" + "PATHETIC SHELL OF A BODY, \n" + "YOU'LL ENTER INTO THE ARMS OF THE \n" + "ORDER." + } + } +}; + +// And again, this could have been a define, but was a variable. +static int numrndmessages = arrlen(rndMessages); + +//============================================================================= +// +// Dialog Menu Structure +// +// The Strife dialog system is actually just a serious abuse of the DOOM menu +// engine. Hence why it doesn't work in multiplayer games or during demo +// recording. +// + +#define NUMDIALOGMENUITEMS 6 + +static void P_DialogDrawer(void); + +static menuitem_t dialogmenuitems[] = +{ + { 1, "", P_DialogDoChoice, '1' }, // These items are loaded dynamically + { 1, "", P_DialogDoChoice, '2' }, + { 1, "", P_DialogDoChoice, '3' }, + { 1, "", P_DialogDoChoice, '4' }, + { 1, "", P_DialogDoChoice, '5' }, + { 1, "", P_DialogDoChoice, '6' } // Item 6 is always the dismissal item +}; + +static menu_t dialogmenu = +{ + NUMDIALOGMENUITEMS, + NULL, + dialogmenuitems, + P_DialogDrawer, + 42, + 75, + 0 +}; + +// Lump number of the dialog background picture, if any. +static int dialogbgpiclumpnum; + +// Name of current speaking character. +static const char *dialogname; + +// Current dialog text. +static const char *dialogtext; + +//============================================================================= +// +// Routines +// + +// +// P_ParseDialogLump +// +// haleyjd 09/02/10: This is an original function added to parse out the +// dialogs from the dialog lump rather than reading them raw from the lump +// pointer. This avoids problems with structure packing. +// +static void P_ParseDialogLump(byte *lump, mapdialog_t **dialogs, + int numdialogs, int tag) +{ + int i; + byte *rover = lump; + + *dialogs = Z_Malloc(numdialogs * sizeof(mapdialog_t), tag, NULL); + + for(i = 0; i < numdialogs; i++) + { + int j; + mapdialog_t *curdialog = &((*dialogs)[i]); + + DIALOG_INT(curdialog->speakerid, rover); + DIALOG_INT(curdialog->dropitem, rover); + DIALOG_INT(curdialog->checkitem[0], rover); + DIALOG_INT(curdialog->checkitem[1], rover); + DIALOG_INT(curdialog->checkitem[2], rover); + DIALOG_INT(curdialog->jumptoconv, rover); + DIALOG_STR(curdialog->name, rover, MDLG_NAMELEN); + DIALOG_STR(curdialog->voice, rover, MDLG_LUMPLEN); + DIALOG_STR(curdialog->backpic, rover, MDLG_LUMPLEN); + DIALOG_STR(curdialog->text, rover, MDLG_TEXTLEN); + + // copy choices + for(j = 0; j < 5; j++) + { + mapdlgchoice_t *curchoice = &(curdialog->choices[j]); + DIALOG_INT(curchoice->giveitem, rover); + DIALOG_INT(curchoice->needitems[0], rover); + DIALOG_INT(curchoice->needitems[1], rover); + DIALOG_INT(curchoice->needitems[2], rover); + DIALOG_INT(curchoice->needamounts[0], rover); + DIALOG_INT(curchoice->needamounts[1], rover); + DIALOG_INT(curchoice->needamounts[2], rover); + DIALOG_STR(curchoice->text, rover, MDLG_CHOICELEN); + DIALOG_STR(curchoice->textok, rover, MDLG_MSGLEN); + DIALOG_INT(curchoice->next, rover); + DIALOG_INT(curchoice->objective, rover); + DIALOG_STR(curchoice->textno, rover, MDLG_MSGLEN); + } + } +} + +// +// P_DialogLoad +// +// [STRIFE] New function +// haleyjd 09/02/10: Loads the dialog script for the current map. Also loads +// SCRIPT00 if it has not yet been loaded. +// +void P_DialogLoad(void) +{ + char lumpname[9]; + int lumpnum; + + // load the SCRIPTxy lump corresponding to MAPxy, if it exists. + DEH_snprintf(lumpname, sizeof(lumpname), "script%02d", gamemap); + if((lumpnum = W_CheckNumForName(lumpname)) == -1) + numleveldialogs = 0; + else + { + byte *leveldialogptr = W_CacheLumpNum(lumpnum, PU_STATIC); + numleveldialogs = W_LumpLength(lumpnum) / ORIG_MAPDIALOG_SIZE; + P_ParseDialogLump(leveldialogptr, &leveldialogs, numleveldialogs, + PU_LEVEL); + Z_Free(leveldialogptr); // haleyjd: free the original lump + } + + // also load SCRIPT00 if it has not been loaded yet + if(!script0loaded) + { + byte *script0ptr; + + script0loaded = true; + // BUG: Rogue should have used W_GetNumForName here... + lumpnum = W_CheckNumForName(DEH_String("script00")); + script0ptr = W_CacheLumpNum(lumpnum, PU_STATIC); + numscript0dialogs = W_LumpLength(lumpnum) / ORIG_MAPDIALOG_SIZE; + P_ParseDialogLump(script0ptr, &script0dialogs, numscript0dialogs, + PU_STATIC); + Z_Free(script0ptr); // haleyjd: free the original lump + } +} + +// +// P_PlayerHasItem +// +// [STRIFE] New function +// haleyjd 09/02/10: Checks for inventory items, quest flags, etc. for dialogs. +// Returns the amount possessed, or 0 if none. +// +int P_PlayerHasItem(player_t *player, mobjtype_t type) +{ + int i; + + if(type > 0) + { + // check keys + if(type >= MT_KEY_BASE && type < MT_INV_SHADOWARMOR) + return (player->cards[type - MT_KEY_BASE]); + + // check sigil pieces + if(type >= MT_SIGIL_A && type <= MT_SIGIL_E) + return (type - MT_SIGIL_A <= player->sigiltype); + + // check quest tokens + if(type >= MT_TOKEN_QUEST1 && type <= MT_TOKEN_QUEST31) + return (player->questflags & (1 << (type - MT_TOKEN_QUEST1))); + + // check inventory + for(i = 0; i < 32; i++) + { + if(type == player->inventory[i].type) + return player->inventory[i].amount; + } + } + return 0; +} + +// +// P_DialogFind +// +// [STRIFE] New function +// haleyjd 09/03/10: Looks for a dialog definition matching the given +// Script ID # for an mobj. +// +mapdialog_t *P_DialogFind(mobjtype_t type, int jumptoconv) +{ + int i; + + // check the map-specific dialogs first + for(i = 0; i < numleveldialogs; i++) + { + if(type == leveldialogs[i].speakerid) + { + if(jumptoconv <= 1) + return &leveldialogs[i]; + else + --jumptoconv; + } + } + + // check SCRIPT00 dialogs next + for(i = 0; i < numscript0dialogs; i++) + { + if(type == script0dialogs[i].speakerid) + return &script0dialogs[i]; + } + + // the default dialog is script 0 in the SCRIPT00 lump. + return &script0dialogs[0]; +} + +// +// P_DialogGetStates +// +// [STRIFE] New function +// haleyjd 09/03/10: Find the set of special dialog states (greetings, yes, no) +// for a particular thing type. +// +static dialogstateset_t *P_DialogGetStates(mobjtype_t type) +{ + int i; + + // look for a match by type + for(i = 0; i < numdialogstatesets; i++) + { + if(type == dialogstatesets[i].type) + return &dialogstatesets[i]; + } + + // return the default 0 record if no match. + return &dialogstatesets[0]; +} + +// +// P_DialogGetMsg +// +// [STRIFE] New function +// haleyjd 09/03/10: Redirects dialog messages when the script indicates that +// the actor should use a random message stored in the executable instead. +// +static const char *P_DialogGetMsg(const char *message) +{ + // if the message starts with "RANDOM"... + if(!strncasecmp(message, DEH_String("RANDOM"), 6)) + { + int i; + const char *nameloc = message + 7; + + // look for a match in rndMessages for the string starting + // 7 chars after "RANDOM_" + for(i = 0; i < numrndmessages; i++) + { + if(!strncasecmp(nameloc, rndMessages[i].type_name, 4)) + { + // found a match, so return a random message + int rnd = M_Random(); + int nummessages = rndMessages[i].nummessages; + return DEH_String(rndMessages[i].messages[rnd % nummessages]); + } + } + } + + // otherwise, just return the message passed in. + return message; +} + +// +// P_GiveInventoryItem +// +// [STRIFE] New function +// haleyjd 09/03/10: Give an inventory item to the player, if possible. +// villsa 09/09/10: Fleshed out routine +// +boolean P_GiveInventoryItem(player_t *player, int sprnum, mobjtype_t type) +{ + int curinv = 0; + int i; + boolean ok = false; + mobjtype_t item = 0; + inventory_t* invtail; + + // repaint the status bar due to inventory changing + player->st_update = true; + + while(1) + { + // inventory is full + if(curinv > player->numinventory) + return true; + + item = player->inventory[curinv].type; + if(type < item) + { + if(curinv != MAXINVENTORYSLOTS) + { + // villsa - sort inventory item if needed + invtail = &player->inventory[player->numinventory - 1]; + if(player->numinventory >= (curinv + 1)) + { + for(i = player->numinventory; i >= (curinv + 1); --i) + { + invtail[1].sprite = invtail[0].sprite; + invtail[1].type = invtail[0].type; + invtail[1].amount = invtail[0].amount; + + invtail--; + } + } + + // villsa - add inventory item + player->inventory[curinv].amount = 1; + player->inventory[curinv].sprite = sprnum; + player->inventory[curinv].type = type; + + // sort cursor if needed + if(player->numinventory) + { + if(curinv <= player->inventorycursor) + player->inventorycursor++; + } + + player->numinventory++; + + return true; + } + + return false; + } + + if(type == item) + break; + + curinv++; + } + + // check amount of inventory item by using the mass from mobjinfo + if(player->inventory[curinv].amount < mobjinfo[item].mass) + { + player->inventory[curinv].amount++; + ok = true; + } + else + ok = false; + + return ok; +} + +// +// P_GiveItemToPlayer +// +// [STRIFE] New function +// haleyjd 09/03/10: Sorts out how to give something to the player. +// Not strictly just for inventory items. +// villsa 09/09/10: Fleshed out function +// +boolean P_GiveItemToPlayer(player_t *player, int sprnum, mobjtype_t type) +{ + int i = 0; + line_t junk; + int sound = sfx_itemup; // haleyjd 09/21/10: different sounds for items + + // set quest if mf_givequest flag is set + if(mobjinfo[type].flags & MF_GIVEQUEST) + player->questflags |= 1 << (mobjinfo[type].speed - 1); + + // check for keys + if(type >= MT_KEY_BASE && type <= MT_NEWKEY5) + { + P_GiveCard(player, type - MT_KEY_BASE); + return true; + } + + // check for quest tokens + if(type >= MT_TOKEN_QUEST1 && type <= MT_TOKEN_QUEST31) + { + if(mobjinfo[type].name) + { + M_StringCopy(pickupstring, DEH_String(mobjinfo[type].name), 39); + player->message = pickupstring; + } + player->questflags |= 1 << (type - MT_TOKEN_QUEST1); + + if(player == &players[consoleplayer]) + S_StartSound(NULL, sound); + return true; + } + + // haleyjd 09/22/10: Refactored to give sprites higher priority than + // mobjtypes and to implement missing logic. + switch(sprnum) + { + case SPR_HELT: // This is given only by the "DONNYTRUMP" cheat (aka Midas) + P_GiveInventoryItem(player, SPR_HELT, MT_TOKEN_TOUGHNESS); + P_GiveInventoryItem(player, SPR_GUNT, MT_TOKEN_ACCURACY); + + // [STRIFE] Bizarre... + for(i = 0; i < 5 * player->accuracy + 300; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + case SPR_ARM1: // Armor 1 + if(!P_GiveArmor(player, -2)) + P_GiveInventoryItem(player, sprnum, type); + break; + + case SPR_ARM2: // Armor 2 + if(!P_GiveArmor(player, -1)) + P_GiveInventoryItem(player, sprnum, type); + break; + + case SPR_COIN: // 1 Gold + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + case SPR_CRED: // 10 Gold + for(i = 0; i < 10; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + case SPR_SACK: // 25 gold + for(i = 0; i < 25; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + case SPR_CHST: // 50 gold + for(i = 0; i < 50; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; // haleyjd 20141215: missing break, caused Rowan to not take ring from you. + + case SPR_BBOX: // Box of Bullets + if(!P_GiveAmmo(player, am_bullets, 5)) + return false; + break; + + case SPR_BLIT: // Bullet Clip + if(!P_GiveAmmo(player, am_bullets, 1)) + return false; + break; + + case SPR_PMAP: // Map powerup + if(!P_GivePower(player, pw_allmap)) + return false; + sound = sfx_yeah; // bluh-doop! + break; + + case SPR_COMM: // Communicator + if(!P_GivePower(player, pw_communicator)) + return false; + sound = sfx_yeah; // bluh-doop! + break; + + case SPR_MSSL: // Mini-missile + if(!P_GiveAmmo(player, am_missiles, 1)) + return false; + break; + + case SPR_ROKT: // Crate of missiles + if(!P_GiveAmmo(player, am_missiles, 5)) + return false; + break; + + case SPR_BRY1: // Battery cell + if(!P_GiveAmmo(player, am_cell, 1)) + return false; + break; + + case SPR_CPAC: // Cell pack + if(!P_GiveAmmo(player, am_cell, 5)) + return false; + break; + + case SPR_PQRL: // Poison bolts + if(!P_GiveAmmo(player, am_poisonbolts, 5)) + return false; + break; + + case SPR_XQRL: // Electric bolts + if(!P_GiveAmmo(player, am_elecbolts, 5)) + return false; + break; + + case SPR_GRN1: // HE Grenades + if(!P_GiveAmmo(player, am_hegrenades, 1)) + return false; + break; + + case SPR_GRN2: // WP Grenades + if(!P_GiveAmmo(player, am_wpgrenades, 1)) + return false; + break; + + case SPR_BKPK: // Backpack (aka Ammo Satchel) + if(!player->backpack) + { + for(i = 0; i < NUMAMMO; i++) + player->maxammo[i] *= 2; + + player->backpack = true; + } + for(i = 0; i < NUMAMMO; i++) + P_GiveAmmo(player, i, 1); + break; + + case SPR_RIFL: // Assault Rifle + if(player->weaponowned[wp_rifle]) + return false; + + if(!P_GiveWeapon(player, wp_rifle, false)) + return false; + + sound = sfx_wpnup; // SHK-CHK! + break; + + case SPR_FLAM: // Flamethrower + if(player->weaponowned[wp_flame]) + return false; + + if(!P_GiveWeapon(player, wp_flame, false)) + return false; + + sound = sfx_wpnup; // SHK-CHK! + break; + + case SPR_MMSL: // Mini-missile Launcher + if(player->weaponowned[wp_missile]) + return false; + + if(!P_GiveWeapon(player, wp_missile, false)) + return false; + + sound = sfx_wpnup; // SHK-CHK! + break; + + case SPR_TRPD: // Mauler + if(player->weaponowned[wp_mauler]) + return false; + + if(!P_GiveWeapon(player, wp_mauler, false)) + return false; + + sound = sfx_wpnup; // SHK-CHK! + break; + + case SPR_CBOW: // Here's a crossbow. Just aim straight, and *SPLAT!* + if(player->weaponowned[wp_elecbow]) + return false; + + if(!P_GiveWeapon(player, wp_elecbow, false)) + return false; + + sound = sfx_wpnup; // SHK-CHK! + break; + + case SPR_TOKN: // Miscellaneous items - These are determined by thingtype. + switch(type) + { + case MT_KEY_HAND: // Severed hand + P_GiveCard(player, key_SeveredHand); + break; + + case MT_MONY_300: // 300 Gold (this is the only way to get it, in fact) + for(i = 0; i < 300; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + case MT_TOKEN_AMMO: // Ammo token - you get this from the Weapons Trainer + if(player->ammo[am_bullets] >= 50) + return false; + + player->ammo[am_bullets] = 50; + break; + + case MT_TOKEN_HEALTH: // Health token - from the Front's doctor + if(!P_GiveBody(player, healthamounts[gameskill])) + return false; + break; + + case MT_TOKEN_ALARM: // Alarm token - particularly from the Oracle. + P_NoiseAlert(player->mo, player->mo); + A_AlertSpectreC(dialogtalker); // BUG: assumes in a dialog o_O + break; + + case MT_TOKEN_DOOR1: // Door special 1 + junk.tag = 222; + EV_DoDoor(&junk, vld_open); + break; + + case MT_TOKEN_PRISON_PASS: // Door special 1 - Prison pass + junk.tag = 223; + EV_DoDoor(&junk, vld_open); + if(gamemap == 2) // If on Tarnhill, give Prison pass object + P_GiveInventoryItem(player, sprnum, type); + break; + + case MT_TOKEN_SHOPCLOSE: // Door special 3 - "Shop close" - unused? + junk.tag = 222; + EV_DoDoor(&junk, vld_close); + break; + + case MT_TOKEN_DOOR3: // Door special 4 (or 3? :P ) + junk.tag = 224; + EV_DoDoor(&junk, vld_close); + break; + + case MT_TOKEN_STAMINA: // Stamina upgrade + if(player->stamina >= 100) + return false; + + player->stamina += 10; + P_GiveBody(player, 200); // full healing + break; + + case MT_TOKEN_NEW_ACCURACY: // Accuracy upgrade + if(player->accuracy >= 100) + return false; + + player->accuracy += 10; + break; + + case MT_SLIDESHOW: // Slideshow (start a finale) + gameaction = ga_victory; + if(gamemap == 10) + P_GiveItemToPlayer(player, SPR_TOKN, MT_TOKEN_QUEST17); + break; + + default: // The default is to just give it as an inventory item. + P_GiveInventoryItem(player, sprnum, type); + break; + } + break; + + default: // The ultimate default: Give it as an inventory item. + if(!P_GiveInventoryItem(player, sprnum, type)) + return false; + break; + } + + // Play sound. + if(player == &players[consoleplayer]) + S_StartSound(NULL, sound); + + return true; +} + +// +// P_TakeDialogItem +// +// [STRIFE] New function +// haleyjd 09/03/10: Removes needed items from the player's inventory. +// +static void P_TakeDialogItem(player_t *player, int type, int amount) +{ + int i; + + if(amount <= 0) + return; + + for(i = 0; i < player->numinventory; i++) + { + // find a matching item + if(type != player->inventory[i].type) + continue; + + // if there is none left... + if((player->inventory[i].amount -= amount) < 1) + { + // ...shift everything above it down + int j; + + // BUG: They should have stopped at j < numinventory. This + // seems to implicitly assume that numinventory is always at + // least one less than the max # of slots, otherwise it + // pulls in data from the following player_t fields: + // st_update, numinventory, inventorycursor, accuracy, stamina + for(j = i + 1; j <= player->numinventory; j++) + { + inventory_t *item1 = &(player->inventory[j - 1]); + inventory_t *item2 = &(player->inventory[j]); + + *item1 = *item2; + } + + // blank the topmost slot + // BUG: This will overwrite the aforementioned fields if + // numinventory is equal to the number of slots! + // STRIFE-TODO: Overflow emulation? + player->inventory[player->numinventory].type = NUMMOBJTYPES; + player->inventory[player->numinventory].sprite = -1; + player->numinventory--; + + // update cursor position + if(player->inventorycursor >= player->numinventory) + { + if(player->inventorycursor) + player->inventorycursor--; + } + } // end if + + return; // done! + + } // end for +} + +// +// P_DialogDrawer +// +// This function is set as the drawer callback for the dialog menu. +// +static void P_DialogDrawer(void) +{ + angle_t angle; + int y; + int i; + int height; + int finaly; + char choicetext[64]; + char choicetext2[64]; + + // Run down bonuscount faster than usual so that flashes from being given + // items are less obvious. + if(dialogplayer->bonuscount) + { + dialogplayer->bonuscount -= 3; + if(dialogplayer->bonuscount < 0) + dialogplayer->bonuscount = 0; + } + + angle = R_PointToAngle2(dialogplayer->mo->x, + dialogplayer->mo->y, + dialogtalker->x, + dialogtalker->y); + angle -= dialogplayer->mo->angle; + + // Dismiss the dialog if the player is out of alignment, or the thing he was + // talking to is now engaged in battle. + if ((angle > ANG45 && angle < (ANG270+ANG45)) + || (dialogtalker->flags & MF_NODIALOG) != 0) + { + P_DialogDoChoice(dialogmenu.numitems - 1); + } + + dialogtalker->reactiontime = 2; + + // draw background + if(dialogbgpiclumpnum != -1) + { + patch_t *patch = W_CacheLumpNum(dialogbgpiclumpnum, PU_CACHE); + V_DrawPatchDirect(0, 0, patch); + } + + // if there's a valid background pic, delay drawing the rest of the menu + // for a while; otherwise, it will appear immediately + if(dialogbgpiclumpnum == -1 || menupausetime <= gametic) + { + if(menuindialog) + { + // time to pause the game? + if(menupausetime + 3 < gametic) + menupause = true; + } + + // draw character name + M_WriteText(12, 18, dialogname); + y = 28; + + // show text (optional for dialogs with voices) + if(dialogshowtext || currentdialog->voice[0] == '\0') + y = M_WriteText(20, 28, dialogtext); + + height = 20 * dialogmenu.numitems; + + finaly = 175 - height; // preferred height + if(y > finaly) + finaly = 199 - height; // height it will bump down to if necessary. + + // draw divider + M_WriteText(42, finaly - 6, DEH_String("______________________________")); + + dialogmenu.y = finaly + 6; + y = 0; + + // draw the menu items + for(i = 0; i < dialogmenu.numitems - 1; i++) + { + DEH_snprintf(choicetext, sizeof(choicetext), + "%d) %s", i + 1, currentdialog->choices[i].text); + + // alternate text for items that need money + if(currentdialog->choices[i].needamounts[0] > 0) + { + // haleyjd 20120401: necessary to avoid undefined behavior: + M_StringCopy(choicetext2, choicetext, sizeof(choicetext2)); + DEH_snprintf(choicetext, sizeof(choicetext), + "%s for %d", choicetext2, + currentdialog->choices[i].needamounts[0]); + } + + M_WriteText(dialogmenu.x, dialogmenu.y + 3 + y, choicetext); + y += 19; + } + + // draw the final item for dismissing the dialog + M_WriteText(dialogmenu.x, 19 * i + dialogmenu.y + 3, dialoglastmsgbuffer); + } +} + +// +// P_DialogDoChoice +// +// [STRIFE] New function +// haleyjd 09/05/10: Handles making a choice in a dialog. Installed as the +// callback for all items in the dialogmenu structure. +// +void P_DialogDoChoice(int choice) +{ + int i = 0, nextdialog = 0; + boolean candochoice = true; + const char *message = NULL; + mapdlgchoice_t *currentchoice; + + if(choice == -1) + choice = dialogmenu.numitems - 1; + + currentchoice = &(currentdialog->choices[choice]); + + I_StartVoice(NULL); // STRIFE-TODO: verify (should stop previous voice I believe) + + // villsa 09/08/10: converted into for loop + for(i = 0; i < MDLG_MAXITEMS; i++) + { + if(P_PlayerHasItem(dialogplayer, currentchoice->needitems[i]) < + currentchoice->needamounts[i]) + { + candochoice = false; // nope, missing something + } + } + + if(choice != dialogmenu.numitems - 1 && candochoice) + { + int item; + + message = currentchoice->textok; + if(dialogtalkerstates->yes) + P_SetMobjState(dialogtalker, dialogtalkerstates->yes); + + item = currentchoice->giveitem; + if(item < 0 || + P_GiveItemToPlayer(dialogplayer, + states[mobjinfo[item].spawnstate].sprite, + item)) + { + // if successful, take needed items + int count = 0; + // villsa 09/08/10: converted into for loop + for(count = 0; count < MDLG_MAXITEMS; count++) + { + P_TakeDialogItem(dialogplayer, + currentchoice->needitems[count], + currentchoice->needamounts[count]); + } + } + else + message = DEH_String("You seem to have enough!"); + + // store next dialog into the talking actor + nextdialog = currentchoice->next; + if(nextdialog != 0) + dialogtalker->miscdata = (byte)(abs(nextdialog)); + } + else + { + // not successful + message = currentchoice->textno; + if(dialogtalkerstates->no) + P_SetMobjState(dialogtalker, dialogtalkerstates->no); + } + + if(choice != dialogmenu.numitems - 1) + { + int objective; + char *objlump; + + if((objective = currentchoice->objective)) + { + DEH_snprintf(mission_objective, OBJECTIVE_LEN, "log%i", objective); + objlump = W_CacheLumpName(mission_objective, PU_CACHE); + M_StringCopy(mission_objective, objlump, OBJECTIVE_LEN); + } + // haleyjd 20130301: v1.31 hack: if first char of message is a period, + // clear the player's message. Is this actually used anywhere? + if(gameversion == exe_strife_1_31 && message[0] == '.') + message = NULL; + dialogplayer->message = message; + } + + dialogtalker->angle = dialogtalkerangle; + dialogplayer->st_update = true; + M_ClearMenus(0); + + if(nextdialog >= 0 || gameaction == ga_victory) // Macil hack + menuindialog = false; + else + P_DialogStart(dialogplayer); +} + +// +// P_DialogStartP1 +// +// [STRIFE] New function +// haleyjd 09/13/10: This is a hack used by the finale system. +// +void P_DialogStartP1(void) +{ + P_DialogStart(&players[0]); +} + +// +// P_DialogStart +// +// villsa [STRIFE] New function +// +void P_DialogStart(player_t *player) +{ + int i = 0; + int pic; + int rnd = 0; + const char *byetext; + int jumptoconv; + + if(menuactive || netgame) + return; + + // are we facing towards our NPC? + P_AimLineAttack(player->mo, player->mo->angle, (128*FRACUNIT)); + if(!linetarget) + { + P_AimLineAttack(player->mo, player->mo->angle + (ANG90/16), (128*FRACUNIT)); + if(!linetarget) + P_AimLineAttack(player->mo, player->mo->angle - (ANG90/16), (128*FRACUNIT)); + } + + if(!linetarget) + return; + + // already in combat, can't talk to it + if(linetarget->flags & MF_NODIALOG) + return; + + // set pointer to the character talking + dialogtalker = linetarget; + + // play a sound + if(player == &players[consoleplayer]) + S_StartSound(0, sfx_radio); + + linetarget->target = player->mo; // target the player + dialogtalker->reactiontime = 2; // set reactiontime + dialogtalkerangle = dialogtalker->angle; // remember original angle + + // face talker towards player + A_FaceTarget(dialogtalker); + + // face towards NPC's direction + player->mo->angle = R_PointToAngle2(player->mo->x, + player->mo->y, + dialogtalker->x, + dialogtalker->y); + // set pointer to player talking + dialogplayer = player; + + // haleyjd 09/08/10: get any stored dialog state from this object + jumptoconv = linetarget->miscdata; + + // check item requirements + while(1) + { + int i = 0; + currentdialog = P_DialogFind(linetarget->type, jumptoconv); + + // dialog's jumptoconv equal to 0? There's nothing to jump to. + if(currentdialog->jumptoconv == 0) + break; + + // villsa 09/08/10: converted into for loop + for(i = 0; i < MDLG_MAXITEMS; i++) + { + // if the item is non-zero, the player must have at least one in his + // or her inventory + if(currentdialog->checkitem[i] != 0 && + P_PlayerHasItem(dialogplayer, currentdialog->checkitem[i]) < 1) + break; + } + + if(i < MDLG_MAXITEMS) // didn't find them all? this is our dialog! + break; + + jumptoconv = currentdialog->jumptoconv; + } + + M_DialogDimMsg(20, 28, currentdialog->text, false); + dialogtext = P_DialogGetMsg(currentdialog->text); + + // get states + dialogtalkerstates = P_DialogGetStates(linetarget->type); + + // have talker greet the player + if(dialogtalkerstates->greet) + P_SetMobjState(dialogtalker, dialogtalkerstates->greet); + + // get talker's name + if(currentdialog->name[0]) + dialogname = currentdialog->name; + else + { + // use a fallback: + if(mobjinfo[linetarget->type].name) + dialogname = DEH_String(mobjinfo[linetarget->type].name); // mobjtype name + else + dialogname = DEH_String("Person"); // default name - like Joe in Doom 3 :P + } + + // setup number of choices to choose from + for(i = 0; i < MDLG_MAXCHOICES; i++) + { + if(!currentdialog->choices[i].giveitem) + break; + } + + // set number of choices to menu + dialogmenu.numitems = i + 1; + + rnd = M_Random() % 3; + + // setup dialog menu + M_StartControlPanel(); + menupause = false; + menuindialog = true; + menupausetime = gametic + 17; + currentMenu = &dialogmenu; + + if(i >= dialogmenu.lastOn) + itemOn = dialogmenu.lastOn; + else + itemOn = 0; + + // get backdrop + pic = W_CheckNumForName(currentdialog->backpic); + dialogbgpiclumpnum = pic; + if(pic != -1) + V_DrawPatchDirect(0, 0, W_CacheLumpNum(pic, PU_CACHE)); + + // get voice + I_StartVoice(currentdialog->voice); + + // get bye text + switch(rnd) + { + case 2: + byetext = DEH_String("BYE!"); + break; + case 1: + byetext = DEH_String("Thanks, Bye!"); + break; + default: + case 0: + byetext = DEH_String("See you later!"); + break; + } + + DEH_snprintf(dialoglastmsgbuffer, sizeof(dialoglastmsgbuffer), + "%d) %s", i + 1, byetext); +} + +// EOF + + diff --git a/games/NXDoom/src/strife/p_dialog.h b/games/NXDoom/src/strife/p_dialog.h new file mode 100644 index 00000000000..08bef81ea75 --- /dev/null +++ b/games/NXDoom/src/strife/p_dialog.h @@ -0,0 +1,102 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1996 Rogue Entertainment / Velocity, Inc. +// Copyright(C) 2010 James Haley, Samuel Villareal +// +// 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. +// +// DESCRIPTION: +// +// [STRIFE] New Module +// +// Dialog Engine for Strife +// + +#ifndef P_DIALOG_H__ +#define P_DIALOG_H__ + +#define OBJECTIVE_LEN 300 + +#define MAXINVENTORYSLOTS 30 + +#define MDLG_CHOICELEN 32 +#define MDLG_MSGLEN 80 +#define MDLG_NAMELEN 16 +#define MDLG_LUMPLEN 8 +#define MDLG_TEXTLEN 320 +#define MDLG_MAXCHOICES 5 +#define MDLG_MAXITEMS 3 + +extern char mission_objective[OBJECTIVE_LEN]; + +extern int dialogshowtext; + +// villsa - convenient macro for giving objective logs to player +#define GiveObjective(x, minlumpnum) \ +do { \ + int obj_ln = W_CheckNumForName(DEH_String(x)); \ + if(obj_ln > minlumpnum) \ + M_StringCopy(mission_objective, W_CacheLumpNum(obj_ln, PU_CACHE), \ + OBJECTIVE_LEN);\ +} while(0) + +// haleyjd - voice and objective in one +#define GiveVoiceObjective(voice, log, minlumpnum) \ +do { \ + int obj_ln = W_CheckNumForName(DEH_String(log)); \ + I_StartVoice(DEH_String(voice)); \ + if(obj_ln > minlumpnum) \ + M_StringCopy(mission_objective, W_CacheLumpNum(obj_ln, PU_CACHE), \ + OBJECTIVE_LEN);\ +} while(0) + +typedef struct mapdlgchoice_s +{ + int giveitem; // item given when successful + int needitems[MDLG_MAXITEMS]; // item needed for success + int needamounts[MDLG_MAXITEMS]; // amount of items needed + char text[MDLG_CHOICELEN]; // normal text + char textok[MDLG_MSGLEN]; // message given on success + int next; // next dialog? + int objective; // ??? + char textno[MDLG_MSGLEN]; // message given on failure +} mapdlgchoice_t; + +typedef struct mapdialog_s +{ + int speakerid; // script ID# for mobjtype that will use this dialog + int dropitem; // item to drop if that thingtype is killed + int checkitem[MDLG_MAXITEMS]; // item(s) needed to see this dialog + int jumptoconv; // conversation to jump to when... ? + char name[MDLG_NAMELEN]; // name of speaker + char voice[MDLG_LUMPLEN]; // voice file to play + char backpic[MDLG_LUMPLEN]; // backdrop pic for character, if any + char text[MDLG_TEXTLEN]; // main message text + + // options that this dialog gives the player + mapdlgchoice_t choices[MDLG_MAXCHOICES]; +} mapdialog_t; + +void P_DialogLoad(void); +void P_DialogStart(player_t *player); +void P_DialogDoChoice(int choice); +boolean P_GiveItemToPlayer(player_t *player, int sprnum, mobjtype_t type); +boolean P_GiveInventoryItem(player_t *player, int sprnum, mobjtype_t type); +boolean P_UseInventoryItem(player_t* player, int item); +void P_DialogStartP1(void); +mapdialog_t* P_DialogFind(mobjtype_t type, int jumptoconv); +int P_PlayerHasItem(player_t *player, mobjtype_t type); + +#endif + +// EOF + + diff --git a/games/NXDoom/src/strife/p_doors.c b/games/NXDoom/src/strife/p_doors.c new file mode 100644 index 00000000000..30f6e311809 --- /dev/null +++ b/games/NXDoom/src/strife/p_doors.c @@ -0,0 +1,1370 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: Door animation code (opening/closing) +// + + + +#include "z_zone.h" +#include "doomdef.h" +#include "deh_main.h" +#include "p_local.h" + +#include "s_sound.h" + + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "dstrings.h" +#include "sounds.h" + +// [STRIFE] +#include "p_dialog.h" +#include "i_system.h" + + +// +// VERTICAL DOORS +// + +// +// T_VerticalDoor +// +void T_VerticalDoor(vldoor_t* door) +{ + result_e res1; + result_e res2; + + switch(door->direction) + { + case 0: + // WAITING + if (!--door->topcountdown) + { + switch(door->type) + { + case vld_blazeRaise: + door->direction = -1; // time to go back down + S_StartSound(&door->sector->soundorg, sfx_bdcls); + break; + + case vld_normal: + door->direction = -1; // time to go back down + // villsa [STRIFE] closesound added + S_StartSound(&door->sector->soundorg, door->closesound); + break; + + // villsa [STRIFE] + case vld_shopClose: + door->direction = 1; + door->speed = (2*FRACUNIT); + S_StartSound(&door->sector->soundorg, door->opensound); + break; + + case vld_close30ThenOpen: + door->direction = 1; + + // villsa [STRIFE] opensound added + S_StartSound(&door->sector->soundorg, door->opensound); + break; + + default: + break; + } + } + break; + + case 2: + // INITIAL WAIT + if (!--door->topcountdown) + { + switch(door->type) + { + case vld_raiseIn5Mins: + door->direction = 1; + door->type = vld_normal; + + // villsa [STRIFE] opensound added + S_StartSound(&door->sector->soundorg, door->opensound); + break; + + default: + break; + } + } + break; + + // villsa [STRIFE] + case -2: + // SPLIT + res1 = T_MovePlane(door->sector, door->speed, door->topheight, 0, 1, 1); + res2 = T_MovePlane(door->sector, door->speed, door->topwait, 0, 0, -1); + + if(res1 == pastdest && res2 == pastdest) + { + door->sector->specialdata = NULL; + P_RemoveThinker(&door->thinker); // unlink and free + } + + break; + + case -1: + // DOWN + res1 = T_MovePlane(door->sector, door->speed, door->sector->floorheight, false, 1, door->direction); + if(res1 == pastdest) + { + switch(door->type) + { + case vld_normal: + case vld_close: + case vld_blazeRaise: + case vld_blazeClose: + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); // unlink and free + // villsa [STRIFE] no sounds + break; + + case vld_close30ThenOpen: + door->direction = 0; + door->topcountdown = TICRATE*30; + break; + + // villsa [STRIFE] + case vld_shopClose: + door->direction = 0; + door->topcountdown = TICRATE*120; + break; + + default: + break; + } + } + else if(res1 == crushed) + { + switch(door->type) + { + case vld_blazeClose: + case vld_close: // DO NOT GO BACK UP! + case vld_shopClose: // villsa [STRIFE] + break; + + default: + door->direction = 1; + // villsa [STRIFE] opensound added + S_StartSound(&door->sector->soundorg, door->opensound); + break; + } + } + break; + + case 1: + // UP + res1 = T_MovePlane(door->sector, + door->speed, + door->topheight, + false,1,door->direction); + + if(res1 == pastdest) + { + switch(door->type) + { + case vld_blazeRaise: + case vld_normal: + door->direction = 0; // wait at top + door->topcountdown = door->topwait; + break; + + case vld_close30ThenOpen: + case vld_blazeOpen: + case vld_open: + case vld_shopClose: // villsa [STRIFE] + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); // unlink and free + break; + + default: + break; + } + } + break; + } +} + + +// +// EV_DoLockedDoor +// Move a locked door up/down +// +// [STRIFE] This game has a crap load of keys. And this function doesn't even +// deal with all of them... +// +int EV_DoLockedDoor(line_t* line, vldoor_e type, mobj_t* thing) +{ + player_t* p; + + p = thing->player; + + if(!p) + return 0; + + switch(line->special) + { + case 99: + case 133: + if(!p->cards[key_IDCard]) + { + p->message = DEH_String("You need an id card"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 134: + case 135: + if(!p->cards[key_IDBadge]) + { + p->message = DEH_String("You need an id badge"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 136: + case 137: + if(!p->cards[key_Passcard]) + { + p->message = DEH_String("You need a pass card"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 151: + case 164: + if(!p->cards[key_GoldKey]) + { + p->message = DEH_String("You need a gold key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 153: + case 163: + if(!p->cards[key_SilverKey]) + { + p->message = DEH_String("You need a silver key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 152: + case 162: + if(!p->cards[key_BrassKey]) + { + p->message = DEH_String("You need a brass key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 167: + case 168: + if(!p->cards[key_SeveredHand]) + { + p->message = DEH_String("Hand print not on file"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 171: + if(!p->cards[key_PrisonKey]) + { + p->message = DEH_String("You don't have the key to the prison"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 172: + if(!p->cards[key_Power1Key]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 173: + if(!p->cards[key_Power2Key]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 176: + if(!p->cards[key_Power3Key]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 189: + if(!p->cards[key_OracleKey]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 191: + if(!p->cards[key_MilitaryID]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 192: + if(!p->cards[key_WarehouseKey]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + + case 223: + if(!p->cards[key_MineKey]) + { + p->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return 0; + } + break; + } + + return EV_DoDoor(line,type); +} + + +// +// EV_DoDoor +// + +int EV_DoDoor(line_t* line, vldoor_e type) +{ + int secnum, rtn; + sector_t* sec; + vldoor_t* door; + + secnum = -1; + rtn = 0; + + while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if(sec->specialdata) + continue; + + + // new door thinker + rtn = 1; + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + door->sector = sec; + door->type = type; + door->topwait = VDOORWAIT; + door->speed = VDOORSPEED; + R_SoundNumForDoor(door); // villsa [STRIFE] set door sounds + + switch(type) + { + // villsa [STRIFE] new door type + case vld_splitOpen: + door->direction = -2; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->speed = FRACUNIT; + // yes, it using topwait to get the floor height + door->topwait = P_FindLowestFloorSurrounding(sec); + if(door->topheight == sec->ceilingheight) + continue; + + S_StartSound(&sec->soundorg, door->opensound); + break; + + // villsa [STRIFE] new door type + case vld_splitRaiseNearest: + door->direction = -2; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->speed = FRACUNIT; + // yes, it using topwait to get the floor height + door->topwait = P_FindHighestFloorSurrounding(sec); + if(door->topheight == sec->ceilingheight) + continue; + + S_StartSound(&sec->soundorg, door->opensound); + break; + + case vld_blazeClose: + case vld_shopClose: // villsa [STRIFE] + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->direction = -1; + door->speed = VDOORSPEED * 4; + S_StartSound(&door->sector->soundorg, sfx_bdcls); + break; + + case vld_close: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->direction = -1; + + // villsa [STRIFE] set door sounds + S_StartSound(&door->sector->soundorg, door->opensound); + break; + + case vld_close30ThenOpen: + door->topheight = sec->ceilingheight; + door->direction = -1; + + // villsa [STRIFE] set door sounds + S_StartSound(&door->sector->soundorg, door->closesound); + break; + + case vld_blazeRaise: + case vld_blazeOpen: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->speed = VDOORSPEED * 4; + if (door->topheight != sec->ceilingheight) + S_StartSound(&door->sector->soundorg, sfx_bdopn); + break; + + case vld_normal: + case vld_open: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + + if(door->topheight != sec->ceilingheight) + S_StartSound(&door->sector->soundorg, door->opensound); + break; + + default: + break; + } + + } + return rtn; +} + +// +// EV_ClearForceFields +// +// villsa [STRIFE] new function +// +boolean EV_ClearForceFields(line_t* line) +{ + int secnum; + sector_t* sec; + int i; + line_t* secline; + boolean ret = false; + + secnum = -1; + + while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + line->special = 0; + ret = true; + + // haleyjd 09/18/10: fixed to continue w/linecount == 0, not return + for(i = 0; i < sec->linecount; i++) + { + secline = sec->lines[i]; + if(!(secline->flags & ML_TWOSIDED)) + continue; + if(secline->special != 148) + continue; + + secline->flags &= ~ML_BLOCKING; + secline->special = 0; + sides[secline->sidenum[0]].midtexture = 0; + sides[secline->sidenum[1]].midtexture = 0; + } + } + + return ret; +} + + +// +// EV_VerticalDoor : open a door manually, no tag value +// +// [STRIFE] Tons of new door types were added. +// +void EV_VerticalDoor(line_t* line, mobj_t* thing) +{ + player_t* player; + sector_t* sec; + vldoor_t* door; + int side; + + side = 0; // only front sides can be used + + // Check for locks + player = thing->player; + + // haleyjd 09/15/10: [STRIFE] myriad checks here... + switch(line->special) + { + case 26: // DR ID Card door + case 32: // D1 ID Card door + if(!player->cards[key_IDCard]) + { + player->message = DEH_String("You need an id card to open this door"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 27: // DR Pass Card door + case 34: // D1 Pass Card door + if(!player->cards[key_Passcard]) + { + player->message = DEH_String("You need a pass card key to open this door"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 28: // DR ID Badge door + case 33: // D1 ID Badge door + if(!player->cards[key_IDBadge]) + { + player->message = DEH_String("You need an id badge to open this door"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 156: // D1 brass key door + case 161: // DR brass key door + if(!player->cards[key_BrassKey]) + { + player->message = DEH_String("You need a brass key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 157: // D1 silver key door + case 160: // DR silver key door + if(!player->cards[key_SilverKey]) + { + player->message = DEH_String("You need a silver key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 158: // D1 gold key door + case 159: // DR gold key door + if(!player->cards[key_GoldKey]) + { + player->message = DEH_String("You need a gold key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + // villsa [STRIFE] added 09/15/10 + case 165: + player->message = DEH_String("That doesn't seem to work"); + S_StartSound(NULL, sfx_oof); + return; + + case 166: // DR Hand Print door + if(!player->cards[key_SeveredHand]) + { + player->message = DEH_String("Hand print not on file"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 169: // DR Base key door + if(!player->cards[key_BaseKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 170: // DR Gov's Key door + if(!player->cards[key_GovsKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 190: // DR Order Key door + if(!player->cards[key_OrderKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 205: // DR "Only in retail" + player->message = DEH_String("THIS AREA IS ONLY AVAILABLE IN THE " + "RETAIL VERSION OF STRIFE"); + S_StartSound(NULL, sfx_oof); + return; + + case 213: // DR Chalice door + if(!P_PlayerHasItem(player, MT_INV_CHALICE)) + { + player->message = DEH_String("You need the chalice!"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 217: // DR Core Key door + if(!player->cards[key_CoreKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 221: // DR Mauler Key door + if(!player->cards[key_MaulerKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 224: // DR Chapel Key door + if(!player->cards[key_ChapelKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 225: // DR Catacomb Key door + if(!player->cards[key_CatacombKey]) + { + player->message = DEH_String("You don't have the key"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + case 232: // DR Oracle Pass door + if(!(player->questflags & QF_QUEST18)) + { + player->message = DEH_String("You need the Oracle Pass!"); + S_StartSound(NULL, sfx_oof); + return; + } + break; + + default: + break; + } + + // if the sector has an active thinker, use it + sec = sides[ line->sidenum[side^1]] .sector; + + if (sec->specialdata) + { + door = sec->specialdata; + // [STRIFE] Adjusted to handle linetypes handled here by Strife. + // BUG: Not all door types are checked here. This means that certain + // door lines are allowed to fall through and start a new thinker on the + // sector! This is why some doors can become jammed in Strife - stuck in + // midair, or unable to be opened at all. Multiple thinkers will fight + // over how to move the door. They should have added a default return if + // they weren't going to handle this unconditionally... + switch(line->special) + { + case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s + case 26: + case 27: + case 28: + case 117: + case 159: // villsa + case 160: // haleyjd + case 161: // villsa + case 166: // villsa + case 169: // villsa + case 170: // villsa + case 190: // villsa + case 213: // villsa + case 232: // villsa + if(door->direction == -1) + door->direction = 1; // go back up + else + { + if (!thing->player) + return; + + // When is a door not a door? + // In Vanilla, door->direction is set, even though + // "specialdata" might not actually point at a door. + + if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor) + { + door->direction = -1; // start going down immediately + } + else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise) + { + // Erm, this is a plat, not a door. + // This notably causes a problem in ep1-0500.lmp where + // a plat and a door are cross-referenced; the door + // doesn't open on 64-bit. + // The direction field in vldoor_t corresponds to the wait + // field in plat_t. Let's set that to -1 instead. + + plat_t *plat; + + plat = (plat_t *) door; + plat->wait = -1; + } + else + { + // This isn't a door OR a plat. Now we're in trouble. + + fprintf(stderr, "EV_VerticalDoor: Tried to close " + "something that wasn't a door.\n"); + + // Try closing it anyway. At least it will work on 32-bit + // machines. + + door->direction = -1; + } + } + return; + default: + break; + } + } + + // haleyjd 09/15/10: [STRIFE] Removed DOOM door sounds + + // new door thinker + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; + door->sector = sec; + door->direction = 1; + door->speed = VDOORSPEED; + door->topwait = VDOORWAIT; + R_SoundNumForDoor(door); // haleyjd 09/15/10: [STRIFE] Get door sounds + + // for proper sound - [STRIFE] - verified complete + switch(line->special) + { + case 117: // BLAZING DOOR RAISE + case 118: // BLAZING DOOR OPEN + S_StartSound(&sec->soundorg, sfx_bdopn); + break; + + default: // NORMAL DOOR SOUND + S_StartSound(&sec->soundorg, door->opensound); + break; + } + + // haleyjd: [STRIFE] - verified all. + switch(line->special) + { + case 1: + case 26: + case 27: + case 28: + door->type = vld_normal; + break; + + case 31: + case 32: + case 33: + case 34: + case 156: // villsa [STRIFE] + case 157: // villsa [STRIFE] + case 158: // villsa [STRIFE] + door->type = vld_open; + line->special = 0; + break; + + case 117: // blazing door raise + door->type = vld_blazeRaise; + door->speed = VDOORSPEED*4; + break; + + case 118: // blazing door open + door->type = vld_blazeOpen; + line->special = 0; + door->speed = VDOORSPEED*4; + break; + + default: + // haleyjd: [STRIFE] pretty important to have this here! + door->type = vld_normal; + break; + } + + // find the top and bottom of the movement range + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; +} + + +// +// Spawn a door that closes after 30 seconds +// +void P_SpawnDoorCloseIn30 (sector_t* sec) +{ + vldoor_t* door; + + door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + + P_AddThinker (&door->thinker); + + sec->specialdata = door; + sec->special = 0; + + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + door->sector = sec; + door->direction = 0; + door->type = vld_normal; + door->speed = VDOORSPEED; + door->topcountdown = 30 * TICRATE; +} + +// +// Spawn a door that opens after 5 minutes +// +void +P_SpawnDoorRaiseIn5Mins +( sector_t* sec, + int secnum ) +{ + vldoor_t* door; + + door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + + P_AddThinker (&door->thinker); + + sec->specialdata = door; + sec->special = 0; + + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + door->sector = sec; + door->direction = 2; + door->type = vld_raiseIn5Mins; + door->speed = VDOORSPEED; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->topwait = VDOORWAIT; + door->topcountdown = 5 * 60 * TICRATE; +} + + +// villsa [STRIFE] resurrected sliding doors +// + +// +// villsa [STRIFE] +// +// Sliding door name information +// +static slidename_t slideFrameNames[MAXSLIDEDOORS] = +{ + // SIGLDR + { + "SIGLDR01", // frame1 + "SIGLDR02", // frame2 + "SIGLDR03", // frame3 + "SIGLDR04", // frame4 + "SIGLDR05", // frame5 + "SIGLDR06", // frame6 + "SIGLDR07", // frame7 + "SIGLDR08" // frame8 + }, + // DORSTN + { + "DORSTN01", // frame1 + "DORSTN02", // frame2 + "DORSTN03", // frame3 + "DORSTN04", // frame4 + "DORSTN05", // frame5 + "DORSTN06", // frame6 + "DORSTN07", // frame7 + "DORSTN08" // frame8 + }, + + // DORQTR + { + "DORQTR01", // frame1 + "DORQTR02", // frame2 + "DORQTR03", // frame3 + "DORQTR04", // frame4 + "DORQTR05", // frame5 + "DORQTR06", // frame6 + "DORQTR07", // frame7 + "DORQTR08" // frame8 + }, + + // DORCRG + { + "DORCRG01", // frame1 + "DORCRG02", // frame2 + "DORCRG03", // frame3 + "DORCRG04", // frame4 + "DORCRG05", // frame5 + "DORCRG06", // frame6 + "DORCRG07", // frame7 + "DORCRG08" // frame8 + }, + + // DORCHN + { + "DORCHN01", // frame1 + "DORCHN02", // frame2 + "DORCHN03", // frame3 + "DORCHN04", // frame4 + "DORCHN05", // frame5 + "DORCHN06", // frame6 + "DORCHN07", // frame7 + "DORCHN08" // frame8 + }, + + // DORIRS + { + "DORIRS01", // frame1 + "DORIRS02", // frame2 + "DORIRS03", // frame3 + "DORIRS04", // frame4 + "DORIRS05", // frame5 + "DORIRS06", // frame6 + "DORIRS07", // frame7 + "DORIRS08" // frame8 + }, + + // DORALN + { + "DORALN01", // frame1 + "DORALN02", // frame2 + "DORALN03", // frame3 + "DORALN04", // frame4 + "DORALN05", // frame5 + "DORALN06", // frame6 + "DORALN07", // frame7 + "DORALN08" // frame8 + }, + + {"\0","\0","\0","\0","\0","\0","\0","\0"} +}; + +// +// villsa [STRIFE] +// +// Sliding door open sounds +// +static sfxenum_t slideOpenSounds[MAXSLIDEDOORS] = +{ + sfx_drlmto, sfx_drston, sfx_airlck, sfx_drsmto, + sfx_drchno, sfx_airlck, sfx_airlck, sfx_None +}; + +// +// villsa [STRIFE] +// +// Sliding door close sounds +// +static sfxenum_t slideCloseSounds[MAXSLIDEDOORS] = +{ + sfx_drlmtc, sfx_drston, sfx_airlck, sfx_drsmtc, + sfx_drchnc, sfx_airlck, sfx_airlck, sfx_None +}; + +slideframe_t slideFrames[MAXSLIDEDOORS]; + +// +// P_InitSlidingDoorFrames +// +// villsa [STRIFE] resurrected +// +void P_InitSlidingDoorFrames(void) +{ + int i; + int f1; + int f2; + int f3; + int f4; + + memset(slideFrames, 0, sizeof(slideframe_t) * MAXSLIDEDOORS); + + for(i = 0; i < MAXSLIDEDOORS; i++) + { + if(!slideFrameNames[i].frame1[0]) + break; + + f1 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame1)); + f2 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame2)); + f3 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame3)); + f4 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame4)); + + slideFrames[i].frames[0] = f1; + slideFrames[i].frames[1] = f2; + slideFrames[i].frames[2] = f3; + slideFrames[i].frames[3] = f4; + + f1 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame5)); + f2 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame6)); + f3 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame7)); + f4 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame8)); + + slideFrames[i].frames[4] = f1; + slideFrames[i].frames[5] = f2; + slideFrames[i].frames[6] = f3; + slideFrames[i].frames[7] = f4; + } +} + + +// +// P_FindSlidingDoorType +// +// Return index into "slideFrames" array +// for which door type to use +// +// villsa [STRIFE] resurrected +// +int P_FindSlidingDoorType(line_t* line) +{ + int i; + int val; + + for(i = 0; i < MAXSLIDEDOORS-1; i++) + { + val = sides[line->sidenum[0]].toptexture; + if(val == slideFrames[i].frames[0]) + return i; + } + + return -1; +} + +// +// T_SlidingDoor +// +// villsa [STRIFE] resurrected +// +void T_SlidingDoor(slidedoor_t* door) +{ + sector_t* sec; + + sec = door->frontsector; + + switch(door->status) + { + case sd_opening: + if(!door->timer--) + { + if(++door->frame == SNUMFRAMES) + { + // IF DOOR IS DONE OPENING... + door->line1->flags &= ~ML_BLOCKING; + door->line2->flags &= ~ML_BLOCKING; + + if(door->type == sdt_openOnly) + { + door->frontsector->specialdata = NULL; + P_RemoveThinker (&door->thinker); + return; + } + + door->timer = SDOORWAIT; + door->status = sd_waiting; + } + else + { + // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... + door->timer = SWAITTICS; + + sides[door->line2->sidenum[0]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + + sides[door->line2->sidenum[1]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + + sides[door->line1->sidenum[0]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + + sides[door->line1->sidenum[1]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + } + } + + return; + + case sd_waiting: + // IF DOOR IS DONE WAITING... + if(!door->timer--) + { + fixed_t speed; + fixed_t cheight; + + sec = door->frontsector; + + // CAN DOOR CLOSE? + if(sec->thinglist != NULL) + { + door->timer = SDOORWAIT; + return; + } + else + { + + cheight = sec->ceilingheight; + speed = cheight - sec->floorheight - (10*FRACUNIT); + + // something blocking it? + if(T_MovePlane(sec, speed, sec->floorheight, 0, 1, -1) == crushed) + { + door->timer = SDOORWAIT; + return; + } + else + { + // Instantly move plane + T_MovePlane(sec, (128*FRACUNIT), cheight, 0, 1, 1); + + // turn line blocking back on + door->line1->flags |= ML_BLOCKING; + door->line2->flags |= ML_BLOCKING; + + // play close sound + S_StartSound(&sec->soundorg, slideCloseSounds[door->whichDoorIndex]); + + door->status = sd_closing; + door->timer = SWAITTICS; + } + } + } + + return; + + case sd_closing: + if (!door->timer--) + { + if(--door->frame < 0) + { + // IF DOOR IS DONE CLOSING... + T_MovePlane(sec, (128*FRACUNIT), sec->floorheight, 0, 1, -1); + door->frontsector->specialdata = NULL; + P_RemoveThinker (&door->thinker); + return; + } + else + { + // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... + door->timer = SWAITTICS; + + sides[door->line2->sidenum[0]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + + sides[door->line2->sidenum[1]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + + sides[door->line1->sidenum[0]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + + sides[door->line1->sidenum[1]].midtexture = + slideFrames[door->whichDoorIndex].frames[door->frame]; + } + } + + return; + } +} + +// +// EV_RemoteSlidingDoor +// +// villsa [STRIFE] new function +// +int EV_RemoteSlidingDoor(line_t* line, mobj_t* thing) +{ + int secnum; + sector_t* sec; + int i; + int rtn; + line_t* secline; + + secnum = -1; + rtn = 0; + + while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if(sec->specialdata) + continue; + + for(i = 0; i < 4; i++) + { + secline = sec->lines[i]; + + if(P_FindSlidingDoorType(secline) < 0) + continue; + + EV_SlidingDoor(secline, thing); + rtn = 1; + } + } + + return rtn; +} + + +// +// EV_SlidingDoor +// +// villsa [STRIFE] +// +void EV_SlidingDoor(line_t* line, mobj_t* thing) +{ + sector_t* sec; + slidedoor_t* door; + int i; + line_t* secline; + + // Make sure door isn't already being animated + sec = sides[line->sidenum[1]].sector; + door = NULL; + if(sec->specialdata) + { + if (!thing->player) + return; + + door = sec->specialdata; + if(door->type == sdt_openAndClose) + { + if(door->status == sd_waiting) + { + door->status = sd_closing; + door->timer = SWAITTICS; // villsa [STRIFE] + } + } + else + return; + } + + // Init sliding door vars + if(!door) + { + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + + sec->specialdata = door; + + door->type = sdt_openAndClose; + door->status = sd_opening; + door->whichDoorIndex = P_FindSlidingDoorType(line); + + // villsa [STRIFE] different error message + if(door->whichDoorIndex < 0) + I_Error(DEH_String("EV_SlidingDoor: Textures are not defined for sliding door!")); + + sides[line->sidenum[0]].midtexture = sides[line->sidenum[0]].toptexture; + + // villsa [STRIFE] + door->line1 = line; + door->line2 = line; + + // villsa [STRIFE] this loop assumes that the sliding door is made up + // of only four linedefs! + for(i = 0; i < 4; i++) + { + secline = sec->lines[i]; + if(secline != line) + { + side_t* side1; + side_t* side2; + + side1 = &sides[secline->sidenum[0]]; + side2 = &sides[line->sidenum[0]]; + + if(side1->toptexture == side2->toptexture) + door->line2 = secline; + } + } + + door->thinker.function.acp1 = (actionf_p1)T_SlidingDoor; + door->timer = SWAITTICS; + door->frontsector = sec; + door->frame = 0; + + // villsa [STRIFE] preset flags + door->line1->flags |= ML_BLOCKING; + door->line2->flags |= ML_BLOCKING; + + // villsa [STRIFE] set the closing sector + T_MovePlane( + door->frontsector, + (128*FRACUNIT), + P_FindLowestCeilingSurrounding(door->frontsector), + 0, + 1, + 1); + + // villsa [STRIFE] play open sound + S_StartSound(&door->frontsector->soundorg, slideOpenSounds[door->whichDoorIndex]); + } +} + diff --git a/games/NXDoom/src/strife/p_enemy.c b/games/NXDoom/src/strife/p_enemy.c new file mode 100644 index 00000000000..7763a87b015 --- /dev/null +++ b/games/NXDoom/src/strife/p_enemy.c @@ -0,0 +1,3388 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Enemy thinking, AI. +// Action Pointer Functions +// that are associated with states/frames. +// + +#include +#include + +#include "m_random.h" +#include "i_system.h" +#include "doomdef.h" +#include "m_misc.h" +#include "p_local.h" +#include "s_sound.h" +#include "g_game.h" +#include "z_zone.h" // villsa [STRIFE] + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "sounds.h" + +// [STRIFE] Dialog / Inventory +#include "p_dialog.h" +#include "deh_str.h" +#include "w_wad.h" +#include "f_finale.h" +#include "p_inter.h" + +// Forward Declarations: +void A_RandomWalk(mobj_t *); +void A_ProgrammerAttack(mobj_t* actor); +void A_FireSigilEOffshoot(mobj_t *actor); +void A_SpectreCAttack(mobj_t *actor); +void A_SpectreDAttack(mobj_t *actor); +void A_SpectreEAttack(mobj_t *actor); + +void P_ThrustMobj(mobj_t *actor, angle_t angle, fixed_t force); + +typedef enum +{ + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS + +} dirtype_t; + + +// +// P_NewChaseDir related LUT. +// +dirtype_t opposite[] = +{ + DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, + DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR +}; + +dirtype_t diags[] = +{ + DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST +}; + + + + + +void A_Fall (mobj_t *actor); + + +// +// ENEMY THINKING +// Enemies are allways spawned +// with targetplayer = -1, threshold = 0 +// Most monsters are spawned unaware of all players, +// but some can be made preaware +// + + +// +// Called by P_NoiseAlert. +// Recursively traverse adjacent sectors, +// sound blocking lines cut off traversal. +// +// haleyjd 09/05/10: [STRIFE] Verified unmodified +// + +mobj_t* soundtarget; + +void +P_RecursiveSound +( sector_t* sec, + int soundblocks ) +{ + int i; + line_t* check; + sector_t* other; + + // wake up all monsters in this sector + if (sec->validcount == validcount + && sec->soundtraversed <= soundblocks+1) + { + return; // already flooded + } + + sec->validcount = validcount; + sec->soundtraversed = soundblocks+1; + sec->soundtarget = soundtarget; + + for (i=0 ;ilinecount ; i++) + { + check = sec->lines[i]; + if (! (check->flags & ML_TWOSIDED) ) + continue; + + P_LineOpening (check); + + if (openrange <= 0) + continue; // closed door + + if ( sides[ check->sidenum[0] ].sector == sec) + other = sides[ check->sidenum[1] ] .sector; + else + other = sides[ check->sidenum[0] ].sector; + + if (check->flags & ML_SOUNDBLOCK) + { + if (!soundblocks) + P_RecursiveSound (other, 1); + } + else + P_RecursiveSound (other, soundblocks); + } +} + + + +// +// P_NoiseAlert +// If a monster yells at a player, +// it will alert other monsters to the player. +// +// haleyjd 09/05/10: [STRIFE] Verified unmodified +// +void +P_NoiseAlert +( mobj_t* target, + mobj_t* emmiter ) +{ + soundtarget = target; + validcount++; + P_RecursiveSound (emmiter->subsector->sector, 0); +} + +// +// P_WakeUpThing +// +// villsa [STRIFE] New function +// Wakes up an mobj.nearby when somebody has been punched. +// +static void P_WakeUpThing(mobj_t* puncher, mobj_t* bystander) +{ + if(!(bystander->flags & MF_NODIALOG)) + { + bystander->target = puncher; + if(bystander->info->seesound) + S_StartSound(bystander, bystander->info->seesound); + P_SetMobjState(bystander, bystander->info->seestate); + } +} + +// +// P_DoPunchAlert +// +// villsa [STRIFE] New function (by Quasar ;) +// Wake up buddies nearby when the player thinks he's gotten too clever +// with the punch dagger. Walks sector links. +// +void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee) +{ + mobj_t *rover; + + // don't bother with this crap if we're already on alert + if(punchee->subsector->sector->soundtarget) + return; + + // gotta still be alive to call for help + if(punchee->health <= 0) + return; + + // has to be something you can wake up and kill too + if(!(punchee->flags & MF_COUNTKILL) || punchee->flags & MF_NODIALOG) + return; + + // make the punchee hurt - haleyjd 09/05/10: Fixed to use painstate. + punchee->target = puncher; + P_SetMobjState(punchee, punchee->info->painstate); + + // wake up everybody nearby + + // scan forward on sector list + for(rover = punchee->snext; rover; rover = rover->snext) + { + // we only wake up certain thing types (Acolytes and Templars?) + if(rover->health > 0 && rover->type >= MT_GUARD1 && rover->type <= MT_PGUARD && + (P_CheckSight(rover, puncher) || P_CheckSight(rover, punchee))) + { + P_WakeUpThing(puncher, rover); + rover->flags |= MF_NODIALOG; + } + } + + // scan backward on sector list + for(rover = punchee->sprev; rover; rover = rover->sprev) + { + // we only wake up certain thing types (Acolytes and Templars?) + if(rover->health > 0 && rover->type >= MT_GUARD1 && rover->type <= MT_PGUARD && + (P_CheckSight(rover, puncher) || P_CheckSight(rover, punchee))) + { + P_WakeUpThing(puncher, rover); + rover->flags |= MF_NODIALOG; + } + } +} + + + + +// +// P_CheckMeleeRange +// +// [STRIFE] Minor change to meleerange. +// +boolean P_CheckMeleeRange(mobj_t* actor) +{ + mobj_t* pl; + fixed_t dist; + + if(!actor->target) + return false; + + pl = actor->target; + if(actor->z + 3 * actor->height / 2 < pl->z) // villsa [STRIFE] + return false; + + dist = P_AproxDistance(pl->x - actor->x, pl->y - actor->y); + + if(dist >= MELEERANGE - 20*FRACUNIT + pl->info->radius) + return false; + + if(!P_CheckSight (actor, actor->target)) + return false; + + return true; +} + +// +// P_CheckMissileRange +// +// [STRIFE] +// Changes to eliminate DOOM-specific code and to allow for +// varying attack ranges for Strife monsters, as well as a general tweak +// to considered distance for all monsters. +// +boolean P_CheckMissileRange(mobj_t* actor) +{ + fixed_t dist; + + if(!P_CheckSight(actor, actor->target)) + return false; + + if(actor->flags & MF_JUSTHIT) + { + // the target just hit the enemy, + // so fight back! + actor->flags &= ~MF_JUSTHIT; + return true; + } + + if(actor->reactiontime) + return false; // do not attack yet + + // OPTIMIZE: get this from a global checksight + dist = P_AproxDistance(actor->x-actor->target->x, + actor->y-actor->target->y) - 64*FRACUNIT; + + if (!actor->info->meleestate) + dist -= 128*FRACUNIT; // no melee attack, so fire more + + dist >>= 16; + + // villsa [STRIFE] checks for acolytes + // haleyjd 09/05/10: Repaired to match disassembly: Was including + // SHADOWGUARD in the wrong case, was missing MT_SENTINEL entirely. + // Structure of ASM also indicates this was probably a switch + // statement turned into a cascading if/else by the compiler. + switch(actor->type) + { + case MT_GUARD1: + case MT_GUARD2: + case MT_GUARD3: + case MT_GUARD4: + case MT_GUARD5: + case MT_GUARD6: + // oddly, not all Acolytes are included here... + dist >>= 4; + break; + case MT_SHADOWGUARD: + case MT_CRUSADER: + case MT_SENTINEL: + dist >>= 1; + break; + default: + break; + } + + // villsa [STRIFE] changed to 150 + if (dist > 150) + dist = 150; + + // haleyjd 20100910: Hex-Rays was leaving this out completely: + if (actor->type == MT_CRUSADER && dist > 120) + dist = 120; + + // haleyjd 20110224 [STRIFE]: reversed predicate + return (dist < P_Random()); +} + +// +// P_CheckRobotRange +// +// villsa [STRIFE] New function +// +boolean P_CheckRobotRange(mobj_t *actor) +{ + fixed_t dist; + + if(!P_CheckSight(actor, actor->target)) + return false; + + if(actor->reactiontime) + return false; // do not attack yet + + dist = (P_AproxDistance(actor->x-actor->target->x, + actor->y-actor->target->y) - 64*FRACUNIT) >> FRACBITS; + + return (dist < 200); +} + + +// +// P_Move +// Move in the current direction, +// returns false if the move is blocked. +// +// [STRIFE] +// villsa/haleyjd 09/05/10: Modified for terrain types and 3D object +// clipping. Below constants are verified to be unmodified: +// +fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; +fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; + + +boolean P_Move (mobj_t* actor) +{ + fixed_t tryx; + fixed_t tryy; + + line_t* ld; + + // warning: 'catch', 'throw', and 'try' + // are all C++ reserved words + boolean try_ok; + boolean good; + + if (actor->movedir == DI_NODIR) + return false; + + if ((unsigned)actor->movedir >= 8) + I_Error ("Weird actor->movedir!"); + + tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; + tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; + + try_ok = P_TryMove (actor, tryx, tryy); + + if (!try_ok) + { + // open any specials + if (actor->flags & MF_FLOAT && floatok) + { + // must adjust height + if (actor->z < tmfloorz) + actor->z += FLOATSPEED; // [STRIFE] Note FLOATSPEED == 5*FRACUNIT + else + actor->z -= FLOATSPEED; + + actor->flags |= MF_INFLOAT; + return true; + } + + if (!numspechit) + return false; + + actor->movedir = DI_NODIR; + good = false; + while (numspechit--) + { + ld = spechit[numspechit]; + // if the special is not a door + // that can be opened, + // return false + if (P_UseSpecialLine (actor, ld,0)) + good = true; + } + return good; + } + else + { + actor->flags &= ~(MF_INFLOAT|MF_FEETCLIPPED); // villsa [STRIFE] + + // villsa [STRIFE] + if(P_GetTerrainType(actor) != FLOOR_SOLID) + actor->flags |= MF_FEETCLIPPED; + } + + + // villsa [STRIFE] Removed pulling non-floating actors down to the ground. + // (haleyjd 09/05/10: Verified) + /*if (! (actor->flags & MF_FLOAT) ) + actor->z = actor->floorz;*/ + + return true; +} + + +// +// TryWalk +// Attempts to move actor on +// in its current (ob->moveangle) direction. +// If blocked by either a wall or an actor +// returns FALSE +// If move is either clear or blocked only by a door, +// returns TRUE and sets... +// If a door is in the way, +// an OpenDoor call is made to start it opening. +// +// haleyjd 09/05/10: [STRIFE] Verified unmodified. +// +boolean P_TryWalk (mobj_t* actor) +{ + if (!P_Move (actor)) + { + return false; + } + + actor->movecount = P_Random()&15; + return true; +} + + + +// +// P_NewChaseDir +// + +void P_NewChaseDir(mobj_t* actor) +{ + fixed_t deltax; + fixed_t deltay; + + dirtype_t d[3]; + + int tdir; + dirtype_t olddir; + + dirtype_t turnaround; + + // villsa [STRIFE] don't bomb out and instead set spawnstate + if(!actor->target) + { + //I_Error("P_NewChaseDir: called with no target"); + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + olddir = actor->movedir; + turnaround=opposite[olddir]; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + + if (deltax>10*FRACUNIT) + d[1]= DI_EAST; + else if (deltax<-10*FRACUNIT) + d[1]= DI_WEST; + else + d[1]=DI_NODIR; + + if (deltay<-10*FRACUNIT) + d[2]= DI_SOUTH; + else if (deltay>10*FRACUNIT) + d[2]= DI_NORTH; + else + d[2]=DI_NODIR; + + // try direct route + if (d[1] != DI_NODIR + && d[2] != DI_NODIR) + { + actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; + if (actor->movedir != (int) turnaround && P_TryWalk(actor)) + return; + } + + // try other directions + if (P_Random() > 200 + || abs(deltay)>abs(deltax)) + { + tdir=d[1]; + d[1]=d[2]; + d[2]=tdir; + } + + if (d[1]==turnaround) + d[1]=DI_NODIR; + if (d[2]==turnaround) + d[2]=DI_NODIR; + + if (d[1]!=DI_NODIR) + { + actor->movedir = d[1]; + if (P_TryWalk(actor)) + { + // either moved forward or attacked + return; + } + } + + if (d[2]!=DI_NODIR) + { + actor->movedir =d[2]; + + if (P_TryWalk(actor)) + return; + } + + // there is no direct path to the player, + // so pick another direction. + if (olddir!=DI_NODIR) + { + actor->movedir =olddir; + + if (P_TryWalk(actor)) + return; + } + + // randomly determine direction of search + if (P_Random()&1) + { + for ( tdir=DI_EAST; + tdir<=DI_SOUTHEAST; + tdir++ ) + { + if (tdir != (int) turnaround) + { + actor->movedir =tdir; + + if ( P_TryWalk(actor) ) + return; + } + } + } + else + { + for ( tdir=DI_SOUTHEAST; + tdir != (DI_EAST-1); + tdir-- ) + { + if (tdir != (int) turnaround) + { + actor->movedir = tdir; + + if ( P_TryWalk(actor) ) + return; + } + } + } + + if (turnaround != DI_NODIR) + { + actor->movedir =turnaround; + if ( P_TryWalk(actor) ) + return; + } + + actor->movedir = DI_NODIR; // can not move +} + +// +// P_NewRandomDir +// +// villsa [STRIFE] new function +// +// haleyjd: Almost identical to the tail-end of P_NewChaseDir, this function +// finds a purely random direction for an object to walk. Called from +// A_RandomWalk. +// +// Shockingly similar to the RandomWalk pointer in Eternity :) +// +void P_NewRandomDir(mobj_t* actor) +{ + int dir = 0; + int omovedir = opposite[actor->movedir]; // haleyjd 20110223: nerfed this... + + // randomly determine direction of search + if(P_Random() & 1) + { + // Try all non-reversal directions forward, first + for(dir = 0; dir < DI_NODIR; dir++) + { + if(dir != omovedir) + { + actor->movedir = dir; + if(P_Random() & 1) + { + if(P_TryWalk(actor)) + break; + } + } + } + + // haleyjd 20110223: logic missing entirely: + // failed all non-reversal directions? try reversing + if(dir > DI_SOUTHEAST) + { + if(omovedir == DI_NODIR) + { + actor->movedir = DI_NODIR; + return; + } + actor->movedir = omovedir; + if(P_TryWalk(actor)) + return; + else + { + actor->movedir = DI_NODIR; + return; + } + } + } + else + { + // Try directions one at a time in backward order + dir = DI_SOUTHEAST; + while(1) + { + // haleyjd 09/05/10: missing random code. + if(dir != omovedir) + { + actor->movedir = dir; + + // villsa 09/06/10: un-inlined code + if(P_TryWalk(actor)) + return; + } + + // Ran out of non-reversal directions to try? Reverse. + if(--dir == -1) + { + if(omovedir == DI_NODIR) + { + actor->movedir = DI_NODIR; + return; + } + actor->movedir = omovedir; + // villsa 09/06/10: un-inlined code + if(P_TryWalk(actor)) + return; + else + { + actor->movedir = DI_NODIR; + return; + } + } // end if(--dir == -1) + } // end while(1) + } // end else +} + + +// +// P_LookForPlayers +// +// If allaround is false, only look 180 degrees in front. +// Returns true if a player is targeted. +// +// [STRIFE] +// haleyjd 09/05/10: Modifications to support friendly units. +// +boolean +P_LookForPlayers +( mobj_t* actor, + boolean allaround ) +{ + int c; + int stop; + player_t* player; + angle_t an; + fixed_t dist; + mobj_t * master = players[actor->miscdata].mo; + int consecutive_missing = 0; // for breaking infinite loop + + // haleyjd 09/05/10: handle Allies + if(actor->flags & MF_ALLY) + { + // Deathmatch: support team behavior for Rebels. + if(netgame) + { + // Rebels adopt the allied player's target if it is not of the same + // allegiance. Other allies do it unconditionally. + if(master && master->target && + (master->target->type != MT_REBEL1 || + master->target->miscdata != actor->miscdata)) + { + actor->target = master->target; + } + else + { + // haleyjd 09/06/10: Note that this sets actor->target in Strife! + P_BulletSlope(actor); + + // Clear target if nothing is visible, or if the target is a + // friendly Rebel or the allied player. + if (linetarget == NULL + || (actor->target->type == MT_REBEL1 + && actor->target->miscdata == actor->miscdata) + || actor->target == master) + { + actor->target = NULL; + return false; + } + } + } + else + { + // Single-player: Adopt any non-allied player target. + if(master && master->target && !(master->target->flags & MF_ALLY)) + { + actor->target = master->target; + return true; + } + + // haleyjd 09/06/10: Note that this sets actor->target in Strife! + P_BulletSlope(actor); + + // Clear target if nothing is visible, or if the target is an ally. + if(!linetarget || actor->target->flags & MF_ALLY) + { + actor->target = NULL; + return false; + } + } + + return true; + } + + c = 0; + + // The 3 below is probably a mistake (it should be MAXPLAYERS - 1, or 7) + // and in vanilla this can potentially cause an infinite loop in + // multiplayer. Unfortunately we can't correct the mistake - doing so will + // cause desyncs. Upon spawning, each enemy's lastlook is initialized to a + // random value between 0 and 7 (i.e MAXPLAYERS - 1). There's a chance + // that the first call of this function for that enemy will return early + // courtesy of the actor->lastlook == stop condition. In a single-player + // game this occurs when (actor->lastlook - 1) & 3 equals 0, or when + // lastlook equals 1 or 5. + + // If you use MAXPLAYERS - 1, it has the side effect of altering which + // enemies are affected by an early actor->lastlook == stop return. Now it + // happens when (actor->lastlook - 1) & 7 equals 0, or when lastlook equals + // 1, *not* 1 and 5 as above. + + stop = (actor->lastlook-1)&3; + + for ( ; ; actor->lastlook = (actor->lastlook+1)&3 ) + { + if (!playeringame[actor->lastlook]) + { + // Break the vanilla infinite loop here. It can occur if there are + // > 4 players and players 0 - 3 all quit the game. Error out + // instead. + if (consecutive_missing == 4) + { + I_Error("P_LookForPlayers: No player 1 - 4.\n"); + } + consecutive_missing++; + continue; + } + + consecutive_missing = 0; + + if (c++ == 2 + || actor->lastlook == stop) + { + // done looking + return false; + } + + player = &players[actor->lastlook]; + + if (player->health <= 0) + continue; // dead + + if (!P_CheckSight (actor, player->mo)) + continue; // out of sight + + if (!allaround) + { + an = R_PointToAngle2(actor->x, + actor->y, + player->mo->x, + player->mo->y) - actor->angle; + + if (an > ANG90 && an < ANG270) + { + dist = P_AproxDistance (player->mo->x - actor->x, + player->mo->y - actor->y); + // if real close, react anyway + if (dist > MELEERANGE) + continue; // behind back + } + } + + actor->target = player->mo; + return true; + } + + return false; +} + +// haleyjd 09/05/10: [STRIFE] Removed A_KeenDie + +// +// ACTION ROUTINES +// + +// +// A_Look +// Stay in state until a player is sighted. +// +// [STRIFE] +// haleyjd 09/05/10: Adjusted for allies, Inquisitors, etc. +// +void A_Look (mobj_t* actor) +{ + mobj_t* targ; + + actor->threshold = 0; // any shot will wake up + targ = actor->subsector->sector->soundtarget; + + if (targ + && (targ->flags & MF_SHOOTABLE) ) + { + // [STRIFE] Allies wander when they call this. + if(actor->flags & MF_ALLY) + A_RandomWalk(actor); + else + { + actor->target = targ; + + if ( actor->flags & MF_AMBUSH ) + { + if (P_CheckSight (actor, actor->target)) + goto seeyou; + } + else + goto seeyou; + } + } + + // haleyjd 09/05/10: This is bizarre, as Rogue keeps using the GIVEQUEST flag + // as a parameter to control allaround look behavior. Did they just run out of + // flags, or what? + // STRIFE-TODO: Needs serious verification. + if (!P_LookForPlayers(actor, (actor->flags & MF_GIVEQUEST) != 0)) + return; + + // go into chase state +seeyou: + if (actor->info->seesound) + { + int sound = actor->info->seesound; + mobj_t * emitter = actor; + + // [STRIFE] Removed DOOM random sounds. + + // [STRIFE] Only Inquisitors roar loudly here. + if (actor->type == MT_INQUISITOR) + emitter = NULL; + + S_StartSound (emitter, sound); + } + + // [STRIFE] Set threshold (kinda odd as it's still set to 0 above...) + actor->threshold = 20; + + P_SetMobjState (actor, actor->info->seestate); +} + +// +// A_RandomWalk +// +// [STRIFE] New function. +// haleyjd 09/05/10: Action routine used to meander about. +// +void A_RandomWalk(mobj_t* actor) +{ + // Standing actors do not wander. + if(actor->flags & MF_STAND) + return; + + if(actor->reactiontime) + actor->reactiontime--; // count down reaction time + else + { + // turn to a new angle + if(actor->movedir < DI_NODIR) + { + int delta; + + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + + if(delta < 0) + actor->angle += ANG90/2; + else if(delta > 0) + actor->angle -= ANG90/2; + } + + // try moving + if(--actor->movecount < 0 || !P_Move(actor)) + { + P_NewRandomDir(actor); + actor->movecount += 5; + } + } +} + +// +// A_FriendLook +// +// [STRIFE] New function +// haleyjd 09/05/10: Action function used mostly by mundane characters such as +// peasants. +// +void A_FriendLook(mobj_t* actor) +{ + mobj_t *soundtarget = actor->subsector->sector->soundtarget; + + actor->threshold = 0; + + if(soundtarget && soundtarget->flags & MF_SHOOTABLE) + { + // Handle allies, except on maps 3 and 34 (Front Base/Movement Base) + if((actor->flags & MF_ALLY) == (soundtarget->flags & MF_ALLY) && + gamemap != 3 && gamemap != 34) + { + // STRIFE-TODO: Needs serious verification. + if(P_LookForPlayers(actor, (actor->flags & MF_GIVEQUEST) != 0)) + { + P_SetMobjState(actor, actor->info->seestate); + actor->flags |= MF_NODIALOG; + return; + } + } + else + { + actor->target = soundtarget; + + if(!(actor->flags & MF_AMBUSH) || P_CheckSight(actor, actor->target)) + { + actor->threshold = 10; + P_SetMobjState(actor, actor->info->seestate); + return; + } + } + } + + // do some idle animation + if(P_Random() < 30) + { + int t = P_Random(); + P_SetMobjState(actor, (t & 1) + actor->info->spawnstate + 1); + } + + // wander around a bit + if(!(actor->flags & MF_STAND) && P_Random() < 40) + P_SetMobjState(actor, actor->info->spawnstate + 3); +} + +// +// A_Listen +// +// [STRIFE] New function +// haleyjd 09/05/10: Action routine used to strictly listen for a target. +// +void A_Listen(mobj_t* actor) +{ + mobj_t *soundtarget; + + actor->threshold = 0; + + soundtarget = actor->subsector->sector->soundtarget; + + if(soundtarget && (soundtarget->flags & MF_SHOOTABLE)) + { + if((actor->flags & MF_ALLY) != (soundtarget->flags & MF_ALLY)) + { + actor->target = soundtarget; + + if(!(actor->flags & MF_AMBUSH) || P_CheckSight(actor, actor->target)) + { + if(actor->info->seesound) + S_StartSound(actor, actor->info->seesound); + + actor->threshold = 10; + + P_SetMobjState(actor, actor->info->seestate); + } + } + } +} + + +// +// A_Chase +// Actor has a melee attack, +// so it tries to close as fast as possible +// +// haleyjd 09/05/10: [STRIFE] Various minor changes +// +void A_Chase (mobj_t* actor) +{ + int delta; + + if (actor->reactiontime) + actor->reactiontime--; + + // modify target threshold + if (actor->threshold) + { + // haleyjd 20110204 [STRIFE]: No health <= 0 check here! + if (actor->target) + actor->threshold--; + else + actor->threshold = 0; + } + + // turn towards movement direction if not there yet + if (actor->movedir < 8) + { + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANG90/2; + else if (delta < 0) + actor->angle += ANG90/2; + } + + if (!actor->target + || !(actor->target->flags&MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true)) + return; // got a new target + + P_SetMobjState (actor, actor->info->spawnstate); + return; + } + + // do not attack twice in a row + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + // [STRIFE] Checks only against fastparm, not gameskill == 5 + if (!fastparm) + P_NewChaseDir (actor); + return; + } + + // check for melee attack + if (actor->info->meleestate + && P_CheckMeleeRange (actor)) + { + if (actor->info->attacksound) + S_StartSound (actor, actor->info->attacksound); + + P_SetMobjState (actor, actor->info->meleestate); + return; + } + + // check for missile attack + if (actor->info->missilestate) + { + // [STRIFE] Checks only fastparm. + if (!fastparm && actor->movecount) + { + goto nomissile; + } + + if (!P_CheckMissileRange (actor)) + goto nomissile; + + P_SetMobjState (actor, actor->info->missilestate); + + // [STRIFE] Add NODIALOG flag to disable dialog + actor->flags |= (MF_NODIALOG|MF_JUSTATTACKED); + return; + } + + // ? +nomissile: + // possibly choose another target + if (netgame + && !actor->threshold + && !P_CheckSight (actor, actor->target) ) + { + if (P_LookForPlayers(actor, true)) + return; // got a new target + } + + // chase towards player + if (--actor->movecount<0 + || !P_Move (actor)) + { + P_NewChaseDir (actor); + } + + // [STRIFE] Changes to active sound behavior: + // * Significantly more frequent + // * Acolytes have randomized wandering sounds + + // make active sound + if (actor->info->activesound && P_Random () < 38) + { + if(actor->info->activesound >= sfx_agrac1 && + actor->info->activesound <= sfx_agrac4) + { + S_StartSound(actor, sfx_agrac1 + P_Random() % 4); + } + else + S_StartSound(actor, actor->info->activesound); + } +} + + +// +// A_FaceTarget +// +// [STRIFE] +// haleyjd 09/05/10: Handling for visibility-modifying flags. +// +void A_FaceTarget (mobj_t* actor) +{ + if (!actor->target) + return; + + actor->flags &= ~MF_AMBUSH; + + actor->angle = R_PointToAngle2 (actor->x, + actor->y, + actor->target->x, + actor->target->y); + + if(actor->target->flags & MF_SHADOW) + { + // [STRIFE] increased SHADOW inaccuracy by a power of 2 + int t = P_Random(); + actor->angle += (t - P_Random()) << 22; + } + else if(actor->target->flags & MF_MVIS) + { + // [STRIFE] MVIS gives even worse aiming! + int t = P_Random(); + actor->angle += (t - P_Random()) << 23; + } +} + +// +// A_PeasantPunch +// +// [STRIFE] New function +// haleyjd 09/05/10: Attack used by Peasants as a one-time retaliation +// when the player or a monster injures them. Weak doesn't begin to +// describe it :P +// +void A_PeasantPunch(mobj_t* actor) +{ + if(!actor->target) + return; + + A_FaceTarget(actor); + if(P_CheckMeleeRange(actor)) + P_DamageMobj(actor->target, actor, actor, 2 * (P_Random() % 5) + 2); +} + +// +// A_ReaverAttack +// +// [STRIFE] New function +// haleyjd 09/06/10: Action routine used by Reavers to fire bullets. +// Also apparently used by Inquistors, though they don't seem to use +// it too often, as they're content to blow your face off with their +// HE grenades instead. +// +void A_ReaverAttack(mobj_t* actor) +{ + int i = 0; + fixed_t slope; + + if(!actor->target) + return; + + S_StartSound(actor, sfx_reavat); + A_FaceTarget(actor); + + slope = P_AimLineAttack(actor, actor->angle, 2048*FRACUNIT); + + do + { + int t = P_Random(); + angle_t shootangle = actor->angle + ((t - P_Random()) << 20); + int damage = 3*((P_Random() & 7) + 1); + + P_LineAttack(actor, shootangle, 2048*FRACUNIT, slope, damage); + ++i; + } + while(i < 3); +} + +// +// A_BulletAttack +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for generic bullet attacks. Used by +// a lot of different characters, including Acolytes, Rebels, and Macil. +// +void A_BulletAttack(mobj_t* actor) +{ + int t, damage; + fixed_t slope; + angle_t shootangle; + + if(!actor->target) + return; + + S_StartSound(actor, sfx_rifle); + A_FaceTarget(actor); + + slope = P_AimLineAttack(actor, actor->angle, 2048*FRACUNIT); + t = P_Random(); + shootangle = ((t - P_Random()) << 19) + actor->angle; + damage = 3 * (P_Random() % 5 + 1); + + P_LineAttack(actor, shootangle, 2048*FRACUNIT, slope, damage); +} + +// +// A_CheckTargetVisible +// +// [STRIFE] New function +// haleyjd 09/06/10: Action routine which sets a thing back to its +// seestate at random, or if it cannot see its target, or its target +// is dead. Used by diverse actors. +// +void A_CheckTargetVisible(mobj_t* actor) +{ + A_FaceTarget(actor); + + if(P_Random() >= 30) + { + mobj_t *target = actor->target; + + if(!target || target->health <= 0 || !P_CheckSight(actor, target) || + P_Random() < 40) + { + P_SetMobjState(actor, actor->info->seestate); + } + } +} + +// +// A_SentinelAttack +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function implementing the Sentinel's laser attack +// villsa 09/06/10 implemented +// +void A_SentinelAttack(mobj_t* actor) +{ + mobj_t* mo; + mobj_t* mo2; + fixed_t x; + fixed_t y; + fixed_t z; + angle_t an; + int i; + + mo = P_SpawnFacingMissile(actor, actor->target, MT_L_LASER); + an = actor->angle >> ANGLETOFINESHIFT; + + if(mo->momy | mo->momx) // villsa - fixed typo (yes, they actually used '|' instead of'||') + { + for(i = 8; i > 1; i--) + { + x = mo->x + FixedMul(mobjinfo[MT_L_LASER].radius * i, finecosine[an]); + y = mo->y + FixedMul(mobjinfo[MT_L_LASER].radius * i, finesine[an]); + z = mo->z + i * (mo->momz >> 2); + mo2 = P_SpawnMobj(x, y, z, MT_R_LASER); + mo2->target = actor; + mo2->momx = mo->momx; + mo2->momy = mo->momy; + mo2->momz = mo->momz; + P_CheckMissileSpawn(mo2); + } + } + + mo->z += mo->momz >> 2; +} + +// +// A_StalkerThink +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function to drive Stalker logic. +// +void A_StalkerThink(mobj_t* actor) +{ + statenum_t statenum; + + if(actor->flags & MF_NOGRAVITY) + { + if(actor->ceilingz - actor->info->height <= actor->z) + return; + statenum = S_SPID_11; // 1020 + } + else + statenum = S_SPID_18; // 1027 + + P_SetMobjState(actor, statenum); +} + +// +// A_StalkerSetLook +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function to marshall transitions to the +// Stalker's spawnstate. +// +void A_StalkerSetLook(mobj_t* actor) +{ + statenum_t statenum; + + if(!actor) // weird; totally unnecessary. + return; + + if(actor->flags & MF_NOGRAVITY) + { + if(actor->state->nextstate == S_SPID_01) // 1010 + return; + statenum = S_SPID_01; // 1010 + } + else + { + if(actor->state->nextstate == S_SPID_02) // 1011 + return; + statenum = S_SPID_02; // 1011 + } + + P_SetMobjState(actor, statenum); +} + +// +// A_StalkerDrop +// +// [STRIFE] New function +// haleyjd 09/06/10: Dead simple: removes NOGRAVITY status. +// +void A_StalkerDrop(mobj_t* actor) +{ + actor->flags &= ~MF_NOGRAVITY; +} + +// +// A_StalkerScratch +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for Stalker's attack. +// +void A_StalkerScratch(mobj_t* actor) +{ + if(actor->flags & MF_NOGRAVITY) + { + // Drop him down before he can attack + P_SetMobjState(actor, S_SPID_11); // 1020 + return; + } + + if(!actor->target) + return; + + A_FaceTarget(actor); + if(P_CheckMeleeRange(actor)) + P_DamageMobj(actor->target, actor, actor, 2 * (P_Random() % 8) + 2); +} + +// +// A_FloatWeave +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function which is responsible for floating +// actors' constant upward and downward movement. Probably a really bad +// idea in retrospect given how dodgy the 3D clipping implementation is. +// +void A_FloatWeave(mobj_t* actor) +{ + fixed_t height; + fixed_t z; + + if(actor->threshold) + return; + + if(actor->flags & MF_INFLOAT) + return; + + height = actor->info->height; // v2 + z = actor->floorz + 96*FRACUNIT; // v1 + + if ( z > actor->ceilingz - height - 16*FRACUNIT ) + z = actor->ceilingz - height - 16*FRACUNIT; + + if ( z >= actor->z ) + actor->momz += FRACUNIT; + else + actor->momz -= FRACUNIT; + + if ( z == actor->z ) + actor->threshold = 4; + else + actor->threshold = 8; +} + +// +// A_RobotMelee +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for Reaver and Templar melee attacks. +// +void A_RobotMelee(mobj_t* actor) +{ + if(!actor->target) + return; + + A_FaceTarget(actor); + if(P_CheckMeleeRange(actor)) + { + S_StartSound(actor, sfx_revbld); + P_DamageMobj(actor->target, actor, actor, 3 * (P_Random() % 8 + 1)); + } +} + +// +// A_TemplarMauler +// +// [STRIFE] New function +// haleyjd 09/06/10: Exactly what it sounds like. Kicks your ass. +// +void A_TemplarMauler(mobj_t* actor) +{ + int i, t; + int angle; + int bangle; + int damage; + int slope; + + if(!actor->target) + return; + + S_StartSound(actor, sfx_pgrdat); + A_FaceTarget(actor); + bangle = actor->angle; + slope = P_AimLineAttack(actor, bangle, 2048*FRACUNIT); + + for(i = 0; i < 10; i++) + { + // haleyjd 09/06/10: Very carefully preserved order of P_Random calls + damage = (P_Random() & 4) * 2; + t = P_Random(); + angle = bangle + ((t - P_Random()) << 19); + t = P_Random(); + slope = ((t - P_Random()) << 5) + slope; + P_LineAttack(actor, angle, 2112*FRACUNIT, slope, damage); + } +} + +// +// A_CrusaderAttack +// +// villsa [STRIFE] new codepointer +// 09/06/10: Action function for the Crusader's Flamethrower. +// Very similar to the player's flamethrower, seeing how it was ripped +// off a Crusader by the Rat People ;) +// +void A_CrusaderAttack(mobj_t* actor) +{ + if(!actor->target) + return; + + actor->z += (8*FRACUNIT); + + if(P_CheckRobotRange(actor)) + { + A_FaceTarget(actor); + actor->angle -= (ANG90 / 8); + P_SpawnFacingMissile(actor, actor->target, MT_C_FLAME); + } + else if(P_CheckMissileRange(actor)) + { + A_FaceTarget(actor); + actor->z += (16*FRACUNIT); + P_SpawnFacingMissile(actor, actor->target, MT_C_MISSILE); + + actor->angle -= (ANG45 / 32); + actor->z -= (16*FRACUNIT); + P_SpawnFacingMissile(actor, actor->target, MT_C_MISSILE); + + actor->angle += (ANG45 / 16); + P_SpawnFacingMissile(actor, actor->target, MT_C_MISSILE); + + P_SetMobjState(actor, actor->info->seestate); + actor->reactiontime += 15; + } + else + P_SetMobjState(actor, actor->info->seestate); + + actor->z -= (8*FRACUNIT); +} + +// +// A_CrusaderLeft +// +// villsa [STRIFE] new codepointer +// +void A_CrusaderLeft(mobj_t* actor) +{ + mobj_t* mo; + + actor->angle += (ANG90 / 16); + mo = P_SpawnFacingMissile(actor, actor->target, MT_C_FLAME); + mo->momz = FRACUNIT; + mo->z += (16*FRACUNIT); + +} + +// +// A_CrusaderRight +// +// villsa [STRIFE] new codepointer +// +void A_CrusaderRight(mobj_t* actor) +{ + mobj_t* mo; + + actor->angle -= (ANG90 / 16); + mo = P_SpawnFacingMissile(actor, actor->target, MT_C_FLAME); + mo->momz = FRACUNIT; + mo->z += (16*FRACUNIT); +} + +// +// A_CheckTargetVisible2 +// +// [STRIFE] New function +// haleyjd 09/06/10: Mostly the same as CheckTargetVisible, except without +// the randomness. +// +void A_CheckTargetVisible2(mobj_t* actor) +{ + if(!actor->target || actor->target->health <= 0 || + !P_CheckSight(actor, actor->target)) + { + P_SetMobjState(actor, actor->info->seestate); + } +} + +// +// A_InqFlyCheck +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function to check if an Inquisitor wishes +// to take to flight. +// +void A_InqFlyCheck(mobj_t* actor) +{ + if(!actor->target) + return; + + A_FaceTarget(actor); + + // if not in "robot" range, shoot grenades. + if(!P_CheckRobotRange(actor)) + P_SetMobjState(actor, S_ROB3_14); // 1061 + + if(actor->z != actor->target->z) + { + // Take off all zig! + if(actor->z + actor->height + 54*FRACUNIT < actor->ceilingz) + P_SetMobjState(actor, S_ROB3_17); // 1064 + } +} + +// +// A_InqGrenade +// +// villsa [STRIFE] new codepointer +// 09/06/10: Inquisitor grenade attack action routine. +// +void A_InqGrenade(mobj_t* actor) +{ + mobj_t* mo; + + if(!actor->target) + return; + + A_FaceTarget(actor); + + actor->z += MAXRADIUS; + + // grenade 1 + actor->angle -= (ANG45 / 32); + mo = P_SpawnFacingMissile(actor, actor->target, MT_INQGRENADE); + mo->momz += (9*FRACUNIT); + + // grenade 2 + actor->angle += (ANG45 / 16); + mo = P_SpawnFacingMissile(actor, actor->target, MT_INQGRENADE); + mo->momz += (16*FRACUNIT); + + actor->z -= MAXRADIUS; +} + +// +// A_InqTakeOff +// +// [STRIFE] New function +// haleyjd 09/06/10: Makes an Inquisitor start flying. +// +void A_InqTakeOff(mobj_t* actor) +{ + angle_t an; + fixed_t speed = actor->info->speed * (2 * FRACUNIT / 3); + fixed_t dist; + + if(!actor->target) + return; + + S_StartSound(actor, sfx_inqjmp); + + actor->z += 64 * FRACUNIT; + + A_FaceTarget(actor); + + an = actor->angle >> ANGLETOFINESHIFT; + + actor->momx = FixedMul(finecosine[an], speed); + actor->momy = FixedMul(finesine[an], speed); + + dist = P_AproxDistance(actor->target->x - actor->x, + actor->target->y - actor->y); + + dist /= speed; + if(dist < 1) + dist = 1; + + actor->momz = (actor->target->z - actor->z) / dist; + actor->reactiontime = 60; + actor->flags |= MF_NOGRAVITY; +} + +// +// A_InqFly +// +// [STRIFE] New function +// haleyjd 09/06/10: Handles an Inquisitor in flight. +// +void A_InqFly(mobj_t* actor) +{ + if(!(leveltime & 7)) + S_StartSound(actor, sfx_inqjmp); + + if(--actor->reactiontime < 0 || !actor->momx || !actor->momy || + actor->z <= actor->floorz) + { + // Come in for a landing. + P_SetMobjState(actor, actor->info->seestate); + actor->reactiontime = 0; + actor->flags &= ~MF_NOGRAVITY; + } +} + +// +// A_FireSigilWeapon +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for the Entity's attack. +// +void A_FireSigilWeapon(mobj_t* actor) +{ + int choice = P_Random() % 5; + + // STRIFE-TODO: Needs verification. This switch is just weird. + switch(choice) + { + case 0: + A_ProgrammerAttack(actor); + break; + // ain't not seen no case 1, bub... + case 2: + A_FireSigilEOffshoot(actor); + break; + case 3: + A_SpectreCAttack(actor); + break; + case 4: + A_SpectreDAttack(actor); + break; + case 5: // BUG: never used? wtf were they thinking? + A_SpectreEAttack(actor); + break; + default: + break; + } +} + +// +// A_ProgrammerAttack +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for the Programmer's main +// attack; equivalent to the player's first Sigil. +// +void A_ProgrammerAttack(mobj_t* actor) +{ + mobj_t *mo; + + if(!actor->target) + return; + + mo = P_SpawnMobj(actor->target->x, actor->target->y, ONFLOORZ, + MT_SIGIL_A_GROUND); + mo->threshold = 25; + mo->target = actor; + mo->health = -2; + mo->tracer = actor->target; +} + +// +// A_Sigil_A_Action +// +// [STRIFE] New function +// haleyjd 09/06/10: Called by MT_SIGIL_A_GROUND to zot anyone nearby with +// corny looking lightning bolts. +// +void A_Sigil_A_Action(mobj_t* actor) +{ + int t, x, y, type; + mobj_t *mo; + + if(actor->threshold) + actor->threshold--; + + t = P_Random(); + actor->momx += ((t & 3) - (P_Random() & 3)) << FRACBITS; + t = P_Random(); + actor->momy += ((t & 3) - (P_Random() & 3)) << FRACBITS; + + t = P_Random(); + x = 50*FRACUNIT * ((t & 3) - (P_Random() & 3)) + actor->x; + t = P_Random(); + y = 50*FRACUNIT * ((t & 3) - (P_Random() & 3)) + actor->y; + + if(actor->threshold <= 25) + type = MT_SIGIL_A_ZAP_LEFT; + else + type = MT_SIGIL_A_ZAP_RIGHT; + + mo = P_SpawnMobj(x, y, ONCEILINGZ, type); + mo->momz = -18 * FRACUNIT; + mo->target = actor->target; + mo->health = actor->health; + + mo = P_SpawnMobj(actor->x, actor->y, ONCEILINGZ, MT_SIGIL_A_ZAP_RIGHT); + mo->momz = -18 * FRACUNIT; + mo->target = actor->target; + mo->health = actor->health; +} + +// +// A_SpectreEAttack +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for the Loremaster's Spectre. +// Equivalent to the player's final Sigil attack. +// +void A_SpectreEAttack(mobj_t* actor) +{ + mobj_t *mo; + + if(!actor->target) + return; + + mo = P_SpawnMissile(actor, actor->target, MT_SIGIL_SE_SHOT); + mo->health = -2; +} + +// +// A_SpectreCAttack +// +// villsa [STRIFE] new codepointer +// 09/06/10: Action routine for the Oracle's Spectre. Equivalent to the player's +// third Sigil attack. +// +void A_SpectreCAttack(mobj_t* actor) +{ + mobj_t* mo; + int i; + + if(!actor->target) + return; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + (32*FRACUNIT), MT_SIGIL_A_ZAP_RIGHT); + mo->momz = -(18*FRACUNIT); + mo->target = actor; + mo->health = -2; + mo->tracer = actor->target; + + actor->angle -= ANG90; + for(i = 0; i < 20; i++) + { + actor->angle += (ANG90 / 10); + mo = P_SpawnMortar(actor, MT_SIGIL_C_SHOT); + mo->health = -2; + mo->z = actor->z + (32*FRACUNIT); + } + actor->angle -= ANG90; +} + +// +// A_AlertSpectreC +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function called by the Oracle when it is +// killed. Finds an MT_SPECTRE_C anywhere on the map and awakens it. +// +void A_AlertSpectreC(mobj_t* actor) +{ + thinker_t *th; + + for(th = thinkercap.next; th != &thinkercap; th = th->next) + { + if(th->function.acp1 == (actionf_p1)P_MobjThinker) + { + mobj_t *mo = (mobj_t *)th; + + if(mo->type == MT_SPECTRE_C) + { + P_SetMobjState(mo, mo->info->seestate); + mo->target = actor->target; + return; + } + } + } +} + +// +// A_Sigil_E_Action +// +// villsa [STRIFE] new codepointer +// 09/06/10: Action routine for Sigil "E" shots. Spawns the room-filling +// lightning bolts that seem to often do almost nothing. +// +void A_Sigil_E_Action(mobj_t* actor) +{ + actor->angle += ANG90; + P_SpawnMortar(actor, MT_SIGIL_E_OFFSHOOT); + + actor->angle -= ANG180; + P_SpawnMortar(actor, MT_SIGIL_E_OFFSHOOT); + + actor->angle += ANG90; + P_SpawnMortar(actor, MT_SIGIL_E_OFFSHOOT); + +} + +// +// A_SigilTrail +// +// villsa [STRIFE] new codepointer +// +void A_SigilTrail(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x - actor->momx, + actor->y - actor->momy, + actor->z, MT_SIGIL_TRAIL); + + mo->angle = actor->angle; + mo->health = actor->health; + +} + +// +// A_SpectreDAttack +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function for Macil's Spectre. +// Equivalent of the player's fourth Sigil attack. +// +void A_SpectreDAttack(mobj_t* actor) +{ + mobj_t *mo; + + if(!actor->target) + return; + + mo = P_SpawnMissile(actor, actor->target, MT_SIGIL_SD_SHOT); + mo->health = -2; + mo->tracer = actor->target; +} + +// +// A_FireSigilEOffshoot +// +// [STRIFE] New function +// haleyjd 09/06/10: Action function to fire part of a Sigil E +// attack. Used at least by the Entity. +// +void A_FireSigilEOffshoot(mobj_t* actor) +{ + mobj_t *mo; + + if(!actor->target) + return; + + mo = P_SpawnMissile(actor, actor->target, MT_SIGIL_E_OFFSHOOT); + mo->health = -2; +} + +// +// A_ShadowOff +// +// villsa [STRIFE] new codepointer +// 09/06/10: Disables SHADOW and MVIS flags. +// +void A_ShadowOff(mobj_t* actor) +{ + actor->flags &= ~(MF_SHADOW|MF_MVIS); +} + +// +// A_ModifyVisibility +// +// villsa [STRIFE] new codepointer +// 09/06/10: Turns on SHADOW, and turns off MVIS. +// +void A_ModifyVisibility(mobj_t* actor) +{ + actor->flags |= MF_SHADOW; + actor->flags &= ~MF_MVIS; +} + +// +// A_ShadowOn +// +// villsa [STRIFE] new codepointer +// 09/06/10: Turns on SHADOW and MVIS. +// +void A_ShadowOn(mobj_t* actor) +{ + actor->flags |= (MF_SHADOW|MF_MVIS); +} + +// +// A_SetTLOptions +// +// villsa [STRIFE] new codepointer +// 09/06/10: Sets SHADOW and/or MVIS based on the thing's spawnpoint options. +// +void A_SetTLOptions(mobj_t* actor) +{ + if(actor->spawnpoint.options & MTF_TRANSLUCENT) + actor->flags |= MF_SHADOW; + if(actor->spawnpoint.options & MTF_MVIS) + actor->flags |= MF_MVIS; +} + +// +// A_BossMeleeAtk +// +// villsa [STRIFE] new codepointer +// 09/06/10: Gratuitous melee attack used by multiple boss characters, +// just for the sake of having one. It's not like anybody in their right +// mind would get close to any of the maniacs that use this ;) +// +void A_BossMeleeAtk(mobj_t* actor) +{ + if(!actor->target) + return; + + P_DamageMobj(actor->target, actor, actor, 10 * (P_Random() & 9)); +} + +// +// A_BishopAttack +// +// villsa [STRIFE] new codepointer +// 09/06/10: Bishop's homing missile attack. +// +void A_BishopAttack(mobj_t* actor) +{ + mobj_t* mo; + + if(!actor->target) + return; + + actor->z += MAXRADIUS; + + mo = P_SpawnMissile(actor, actor->target, MT_SEEKMISSILE); + mo->tracer = actor->target; + + actor->z -= MAXRADIUS; +} + +// +// A_FireHookShot +// +// villsa [STRIFE] new codepointer +// 09/06/10: Action function for the Loremaster's hookshot attack. +// +void A_FireHookShot(mobj_t* actor) +{ + if(!actor->target) + return; + + P_SpawnMissile(actor, actor->target, MT_HOOKSHOT); +} + +// +// A_FireChainShot +// +// villsa [STRIFE] new codepointer +// 09/06/10: Action function for the hookshot projectile. Spawns echoes +// to create a chain-like appearance. +// +void A_FireChainShot(mobj_t* actor) +{ + S_StartSound(actor, sfx_tend); + + P_SpawnMobj(actor->x, actor->y, actor->z, MT_CHAINSHOT); // haleyjd: fixed type + + P_SpawnMobj(actor->x - (actor->momx >> 1), + actor->y - (actor->momy >> 1), + actor->z, MT_CHAINSHOT); + + P_SpawnMobj(actor->x - actor->momx, + actor->y - actor->momy, + actor->z, MT_CHAINSHOT); +} + +// +// A_MissileSmoke +// +// villsa [STRIFE] new codepointer +// +void A_MissileSmoke(mobj_t* actor) +{ + mobj_t* mo; + + S_StartSound(actor, sfx_rflite); + P_SpawnPuff(actor->x, actor->y, actor->z); + mo = P_SpawnMobj(actor->x - actor->momx, + actor->y - actor->momy, + actor->z, MT_MISSILESMOKE); + + mo->momz = FRACUNIT; +} + +// +// A_SpawnSparkPuff +// +// villsa [STRIFE] new codepointer +// +void A_SpawnSparkPuff(mobj_t* actor) +{ + int r; + mobj_t* mo; + fixed_t x; + fixed_t y; + + r = P_Random(); + x = (10*FRACUNIT) * ((r & 3) - (P_Random() & 3)) + actor->x; + r = P_Random(); + y = (10*FRACUNIT) * ((r & 3) - (P_Random() & 3)) + actor->y; + + mo = P_SpawnMobj(x, y, actor->z, MT_SPARKPUFF); + P_SetMobjState(mo, S_BNG4_01); // 199 + mo->momz = FRACUNIT; +} + + +// haleyjd 09/05/10: [STRIFE] Removed: +// A_PosAttack, A_SPosAttack, A_CPosAttack, A_CPosRefire, A_SpidRefire, +// A_BspiAttack, A_TroopAttack, A_SargAttack, A_HeadAttack, A_CyberAttack, +// A_BruisAttack, A_SkelMissile + + +int TRACEANGLE = 0xE000000; // villsa [STRIFE] changed from 0xC000000 to 0xE000000 + +// +// A_Tracer +// +void A_Tracer (mobj_t* actor) +{ + angle_t exact; + fixed_t dist; + fixed_t slope; + mobj_t* dest; + //mobj_t* th; + + // villsa [STRIFE] removed all randomization and puff code + + // adjust direction + dest = actor->tracer; + + if(!dest || dest->health <= 0) + return; + + // change angle + exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); + + if(exact != actor->angle) + { + // villsa [STRIFE] slightly different algorithm + if(exact - actor->angle <= 0x80000000) + { + actor->angle += TRACEANGLE; + if(exact - actor->angle > 0x80000000) + actor->angle = exact; + } + else + { + actor->angle -= TRACEANGLE; + if (exact - actor->angle < 0x80000000) + actor->angle = exact; + } + } + + exact = actor->angle>>ANGLETOFINESHIFT; + actor->momx = FixedMul (actor->info->speed, finecosine[exact]); + actor->momy = FixedMul (actor->info->speed, finesine[exact]); + + // change slope + dist = P_AproxDistance (dest->x - actor->x, + dest->y - actor->y); + + dist = dist / actor->info->speed; + + if (dist < 1) + dist = 1; + slope = (dest->z+40*FRACUNIT - actor->z) / dist; + + if (slope < actor->momz) + actor->momz -= FRACUNIT/8; + else + actor->momz += FRACUNIT/8; +} + +// +// A_ProgrammerMelee +// +// villsa [STRIFE] new codepointer +// 09/08/10: Melee attack for the Programmer. +// haleyjd - fixed damage formula +// +void A_ProgrammerMelee(mobj_t* actor) +{ + if(!actor->target) + return; + + A_FaceTarget(actor); + if(P_CheckMeleeRange(actor)) + { + int damage = 6 * (P_Random() % 10 + 1); + + S_StartSound(actor, sfx_mtalht); + P_DamageMobj(actor->target, actor, actor, damage); + } + +} + +// haleyjd 09/05/10: [STRIFE] Removed: +// A_SkelWhoosh, A_SkelFist, PIT_VileCheck, A_VileChase, A_VileStart, +// A_StartFire, A_FireCrackle, A_Fire, A_VileTarget, A_VileAttack +// A_FatRaise, A_FatAttack1, A_FatAttack2, A_FatAttack3, A_SkullAttack, +// A_PainShootSkull, A_PainAttack, A_PainDie + +// +// A_Scream +// +// villsa [STRIFE] +// * Has no random death sounds, so play deathsound directly +// * Full-volume roars for the Entity and Inquisitor. +// +void A_Scream(mobj_t* actor) +{ + if(!actor->info->deathsound) + return; + + // Check for bosses. + if(actor->type == MT_ENTITY || actor->type == MT_INQUISITOR) + S_StartSound(NULL, actor->info->deathsound); // full volume + else + S_StartSound(actor, actor->info->deathsound); +} + +// +// A_XScream +// +// villsa [STRIFE] +// * Robots will play deathsound while non-robots play the slop sfx +// +void A_XScream(mobj_t* actor) +{ + int sound; + + if(actor->flags & MF_NOBLOOD && actor->info->deathsound) + sound = actor->info->deathsound; + else + sound = sfx_slop; + + S_StartSound(actor, sound); +} + +// +// A_Pain +// +// villsa [STRIFE] +// * Play random peasant sounds; otherwise play painsound directly +// +void A_Pain(mobj_t* actor) +{ + int sound = actor->info->painsound; + + if(sound) + { + if(sound >= sfx_pespna && sound <= sfx_pespnd) + sound = sfx_pespna + (P_Random() % 4); + + S_StartSound(actor, sound); + } +} + +// +// A_PeasantCrash +// +// villsa [STRIFE] new codepointer +// 09/08/10: Called from Peasant's "crash" state (not to be confused with +// Heretic crash states), which is invoked when the Peasant has taken +// critical but sub-fatal damage. It will "bleed out" the rest of its +// health by calling this function repeatedly. +// +void A_PeasantCrash(mobj_t* actor) +{ + // Set NODIALOG, because you probably wouldn't feel like talking either + // if somebody just stabbed you in the gut with a punch dagger... + actor->flags |= MF_NODIALOG; + + if(!(P_Random() % 5)) + { + A_Pain(actor); // inlined in asm + actor->health--; + } + + if(actor->health <= 0) + P_KillMobj(actor->target, actor); +} + +// +// A_Fall +// +// [STRIFE] +// * Set NODIALOG, and clear NOGRAVITY and SHADOW +// +void A_Fall (mobj_t *actor) +{ + // villsa [STRIFE] set NODIALOG flag to stop dialog + actor->flags |= MF_NODIALOG; + + // actor is on ground, it can be walked over + // villsa [STRIFE] remove nogravity/shadow flags as well + actor->flags &= ~(MF_SOLID|MF_NOGRAVITY|MF_SHADOW); +} + +// +// A_HideZombie +// +// villsa [STRIFE] new codepointer +// Used by the "Becoming" Acolytes on the Loremaster's level. +// +void A_HideZombie(mobj_t* actor) +{ + line_t junk; + + junk.tag = 999; + EV_DoDoor(&junk, vld_blazeClose); + + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// +// A_MerchantPain +// +// villsa [STRIFE] new codepointer +// 09/08/10: Pain pointer for merchant characters. They close up shop for +// a while and set off the alarm. +// +void A_MerchantPain(mobj_t* actor) +{ + line_t junk; + + junk.tag = 999; + EV_DoDoor(&junk, vld_shopClose); + + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// haleyjd 09/05/10: Removed unused CheckBossEnd Choco routine. + +// haleyjd 09/05/10: [STRIFE] Removed: +// A_Hoof, A_Metal, A_BabyMetal, A_OpenShotgun2, A_LoadShotgun2, +// A_CloseShotgun2, A_BrainAwake, A_BrainPain, A_BrainScream, A_BrainExplode, +// A_BrainDie, A_BrainSpit, A_SpawnSound, A_SpawnFly + +// +// A_ProgrammerDie +// +// villsa [STRIFE] new codepointer +// 09/08/10: Action routine for the Programmer's grisly death. Spawns the +// separate mechanical base object and sends it flying off in some random +// direction. +// +void A_ProgrammerDie(mobj_t* actor) +{ + int r; + angle_t an; + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 24*FRACUNIT, MT_PROGRAMMERBASE); + + // haleyjd 20110223: fix add w/ANG180 + r = P_Random(); + an = ((r - P_Random()) << 22) + actor->angle + ANG180; + mo->angle = an; + + P_ThrustMobj(mo, an, mo->info->speed); // inlined in asm + + mo->momz = P_Random() << 9; +} + +// +// A_InqTossArm +// +// villsa [STRIFE] new codepointer +// 09/08/10: Inquisitor death action. Spawns an arm and tosses it. +// +void A_InqTossArm(mobj_t* actor) +{ + int r; + angle_t an; + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + (24*FRACUNIT), MT_INQARM); + + r = P_Random(); + an = ((r - P_Random()) << 22) + actor->angle - ANG90; + mo->angle = an; + + P_ThrustMobj(mo, an, mo->info->speed); // inlined in asm + + mo->momz = P_Random() << 10; +} + +// +// A_SpawnSpectreA +// +// villsa [STRIFE] new codepointer (unused) +// 09/08/10: Spawns Spectre A. Or would, if anything actually used this. +// This is evidence that the Programmer's spectre, which appears in the +// Catacombs in the final version, was originally meant to be spawned +// after his death. +// +void A_SpawnSpectreA(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_A); + mo->momz = P_Random() << 9; +} + +// +// A_SpawnSpectreB +// +// villsa [STRIFE] new codepointer +// 09/08/10: Action function to spawn the Bishop's spectre. +// +void A_SpawnSpectreB(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_B); + mo->momz = P_Random() << 9; +} + +// +// A_SpawnSpectreC +// +// villsa [STRIFE] new codepointer (unused) +// 09/08/10: Action function to spawn the Oracle's spectre. Also +// unused, because the Oracle's spectre is already present on the +// map and is awakened on his death. Also left over from the +// unreleased beta (and demo) versions. +// +void A_SpawnSpectreC(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_C); + mo->momz = P_Random() << 9; +} + +// +// A_SpawnSpectreD +// +// villsa [STRIFE] new codepointer +// 09/08/10: Action function to spawn Macil's Spectre. +// +void A_SpawnSpectreD(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_D); + mo->momz = P_Random() << 9; +} + +// +// A_SpawnSpectreE +// +// villsa [STRIFE] new codepointer +// 09/08/10: Action function to spawn the Loremaster's Spectre. +// +void A_SpawnSpectreE(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_E); + mo->momz = P_Random() << 9; +} + +// [STRIFE] New statics - Remember the Entity's spawning position. +static fixed_t entity_pos_x = 0; +static fixed_t entity_pos_y = 0; +static fixed_t entity_pos_z = 0; + +// +// A_SpawnEntity +// +// villsa [STRIFE] new codepointer +// 09/08/10: You will fall on your knees before the True God, the One Light. +// +void A_SpawnEntity(mobj_t* actor) +{ + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 70*FRACUNIT, MT_ENTITY); + mo->momz = 5*FRACUNIT; + + entity_pos_x = mo->x; + entity_pos_y = mo->y; + entity_pos_z = mo->z; +} + +// +// P_ThrustMobj +// +// villsa [STRIFE] new function +// Thrusts an thing in a specified force/direction +// Beware! This is inlined everywhere in the asm +// +void P_ThrustMobj(mobj_t *actor, angle_t angle, fixed_t force) +{ + angle_t an = angle >> ANGLETOFINESHIFT; + actor->momx += FixedMul(finecosine[an], force); + actor->momy += FixedMul(finesine[an], force); +} + +// +// A_EntityDeath +// +// [STRIFE] +// haleyjd 09/08/10: The death of the Entity's spectre brings forth +// three subentities, which are significantly less dangerous on their +// own but threatening together. +// +void A_EntityDeath(mobj_t* actor) +{ + mobj_t *subentity; + angle_t an; + fixed_t dist; + + dist = 2 * mobjinfo[MT_SUBENTITY].radius; + + // Subentity One + an = actor->angle >> ANGLETOFINESHIFT; + subentity = P_SpawnMobj(FixedMul(finecosine[an], dist) + entity_pos_x, + FixedMul(finesine[an], dist) + entity_pos_y, + entity_pos_z, MT_SUBENTITY); + subentity->target = actor->target; + A_FaceTarget(subentity); + P_ThrustMobj(subentity, subentity->angle, 625 << 13); + + // Subentity Two + an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; + subentity = P_SpawnMobj(FixedMul(finecosine[an], dist) + entity_pos_x, + FixedMul(finesine[an], dist) + entity_pos_y, + entity_pos_z, MT_SUBENTITY); + subentity->target = actor->target; + P_ThrustMobj(subentity, actor->angle + ANG90, 4); + A_FaceTarget(subentity); + + // Subentity Three + an = (actor->angle - ANG90) >> ANGLETOFINESHIFT; + subentity = P_SpawnMobj(FixedMul(finecosine[an], dist) + entity_pos_x, + FixedMul(finesine[an], dist) + entity_pos_y, + entity_pos_z, MT_SUBENTITY); + subentity->target = actor->target; + P_ThrustMobj(subentity, actor->angle - ANG90, 4); + A_FaceTarget(subentity); +} + +// +// A_SpawnZombie +// +// villsa [STRIFE] new codepointer +// +void A_SpawnZombie(mobj_t* actor) +{ + P_SpawnMobj(actor->x, actor->y, actor->z, MT_ZOMBIE); +} + +// +// A_ZombieInSpecialSector +// +// villsa [STRIFE] new codepointer +// +void A_ZombieInSpecialSector(mobj_t* actor) +{ + sector_t* sector; + fixed_t force; + angle_t angle; + int tagval; + + sector = actor->subsector->sector; + if(actor->z != sector->floorheight) + return; + + if(sector->special <= 15) + P_DamageMobj(actor, NULL, NULL, 999); + else if(sector->special == 18) + { + tagval = sector->tag - 100; + force = (tagval % 10) << 12; + angle = (tagval / 10) << 29; + P_ThrustMobj(actor, angle, force); // inlined in asm + } +} + +// +// A_CrystalExplode +// +// villsa [STRIFE] new codepointer +// Throws out debris from the Power Crystal and sets its sector floorheight +// to the lowest surrounding floor (this is maybe the only time a direct +// level-changing action is done by an object in this fashion in any of +// the DOOM engine games... they usually call a line special instead) +// +void A_CrystalExplode(mobj_t* actor) +{ + sector_t* sector; + mobj_t* rubble; + int i; + int r; + + sector = actor->subsector->sector; + sector->lightlevel = 0; + sector->floorheight = P_FindLowestFloorSurrounding(sector); + + // spawn rubble + for(i = 0; i < 8; i++) + { + rubble = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RUBBLE1 + i); + r = P_Random(); + rubble->momx = ((r & 0x0f) - (P_Random() & 7)) << FRACBITS; + r = P_Random(); + rubble->momy = ((r & 7) - (P_Random() & 7)) << FRACBITS; + rubble->momz = ((P_Random() & 3) << FRACBITS) + (7*FRACUNIT); + } +} + +// [STRIFE] New static global - buffer used for various player messages. +static char pmsgbuffer[80]; + +// +// P_FreePrisoners +// +// haleyjd 09/08/10: [STRIFE] New function +// * Called when the prisoners get freed, obviously. Gives a +// message and awards quest token 13. +// +void P_FreePrisoners(void) +{ + int i; + + DEH_snprintf(pmsgbuffer, sizeof(pmsgbuffer), "You've freed the prisoners!"); + + for(i = 0; i < MAXPLAYERS; i++) + { + P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_QUEST13); + players[i].message = pmsgbuffer; + } +} + +// +// P_DestroyConverter +// +// haleyjd 09/08/10: [STRIFE] New function +// * Called when the converter is shut down in the factory. +// Gives several items and a message. +// +void P_DestroyConverter(void) +{ + int i; + + DEH_snprintf(pmsgbuffer, sizeof(pmsgbuffer), "You've destroyed the Converter!"); + + for(i = 0; i < MAXPLAYERS; i++) + { + P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_QUEST25); + P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_STAMINA); + P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_NEW_ACCURACY); + players[i].message = pmsgbuffer; + } +} + +// +// A_QuestMsg +// +// villsa [STRIFE] new codepointer +// Displays text based on quest item's name +// Quest item is based on actor's speed +// +void A_QuestMsg(mobj_t* actor) +{ + const char *name; + int quest; + int i; + + // get name + name = DEH_String(mobjinfo[(MT_TOKEN_QUEST1 - 1) + actor->info->speed].name); + M_StringCopy(pmsgbuffer, name, sizeof(pmsgbuffer)); // inlined in asm + + // give quest and display message to players + for(i = 0; i < MAXPLAYERS; i++) + { + quest = 1 << (actor->info->speed - 1); + players[i].message = pmsgbuffer; + players[i].questflags |= quest; + } +} + +// +// A_ExtraLightOff +// +// villsa [STRIFE] new codepointer +// 09/08/10: Called by the Power Crystal to turn off the extended +// flash of light caused by its explosion. +// +void A_ExtraLightOff(mobj_t* actor) +{ + if(!actor->target) + return; + + if(!actor->target->player) + return; + + actor->target->player->extralight = 0; +} + +// +// A_CrystalRadiusAtk +// +// villsa [STRIFE] new codepointer +// 09/08/10: Called by the power crystal when it dies. +// +void A_CrystalRadiusAtk(mobj_t* actor) +{ + P_RadiusAttack(actor, actor->target, 512); + + if(!(actor->target && actor->target->player)) + return; + + // set extralight to 5 for near full-bright + actor->target->player->extralight = 5; +} + +// +// A_DeathExplode5 +// +// villsa [STRIFE] new codepointer +// +void A_DeathExplode5(mobj_t* actor) +{ + P_RadiusAttack(actor, actor->target, 192); + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// +// A_DeathExplode1 +// +// villsa [STRIFE] new codepointer +// +void A_DeathExplode1(mobj_t* actor) +{ + P_RadiusAttack(actor, actor->target, 128); + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// +// A_DeathExplode2 +// +// villsa [STRIFE] new codepointer +// +void A_DeathExplode2(mobj_t* actor) +{ + P_RadiusAttack(actor, actor->target, 64); + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// +// A_DeathExplode3 +// +// villsa [STRIFE] new codepointer +// +void A_DeathExplode3(mobj_t* actor) +{ + P_RadiusAttack(actor, actor->target, 32); + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// +// A_RaiseAlarm +// +// villsa [STRIFE] new codepointer +// 09/08/10: Set off the infamous alarm. This is just a noise alert. +// +void A_RaiseAlarm(mobj_t* actor) +{ + if(actor->target && actor->target->player) + P_NoiseAlert(actor->target, actor); // inlined in asm +} + +// +// A_MissileTick +// villsa [STRIFE] - new codepointer +// +void A_MissileTick(mobj_t* actor) +{ + if(--actor->reactiontime <= 0) + { + P_ExplodeMissile(actor); + actor->flags &= ~MF_MISSILE; + } +} + +// +// A_SpawnGrenadeFire +// villsa [STRIFE] - new codepointer +// +void A_SpawnGrenadeFire(mobj_t* actor) +{ + P_SpawnMobj(actor->x, actor->y, actor->z, MT_PFLAME); +} + +// +// A_NodeChunk +// +// villsa [STRIFE] - new codepointer +// Throw out "nodes" from a spectral entity +// +void A_NodeChunk(mobj_t* actor) +{ + int r; + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 10*FRACUNIT, MT_NODE); + r = P_Random(); + mo->momx = ((r & 0x0f) - (P_Random() & 7)) << FRACBITS; + r = P_Random(); + mo->momy = ((r & 7) - (P_Random() & 0x0f)) << FRACBITS; + mo->momz = (P_Random() & 0x0f) << FRACBITS; +} + +// +// A_HeadChunk +// +// villsa [STRIFE] - new codepointer +// Throw out the little "eye"-like object from a spectral entity when it dies. +// +void A_HeadChunk(mobj_t* actor) +{ + int r; + mobj_t* mo; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + 10*FRACUNIT, MT_SPECTREHEAD); + r = P_Random(); + mo->momx = ((r & 7) - (P_Random() & 0x0f)) << FRACBITS; + r = P_Random(); + mo->momy = ((r & 0x0f) - (P_Random() & 7)) << FRACBITS; + mo->momz = (P_Random() & 7) << FRACBITS; +} + +// +// A_BurnSpread +// villsa [STRIFE] - new codepointer +// +void A_BurnSpread(mobj_t* actor) +{ + int t; + mobj_t* mo; + fixed_t x; + fixed_t y; + + actor->momz -= (8*FRACUNIT); + + t = P_Random(); + actor->momx += ((t & 3) - (P_Random() & 3)) << FRACBITS; + t = P_Random(); + actor->momy += ((t & 3) - (P_Random() & 3)) << FRACBITS; + + S_StartSound(actor, sfx_lgfire); + + if(actor->flags & MF_DROPPED) + return; // not the parent + + // haleyjd 20110223: match order of calls in binary + y = actor->y + (((P_Random() + 12) & 31) << FRACBITS); + x = actor->x + (((P_Random() + 12) & 31) << FRACBITS); + + // spawn child + mo = P_SpawnMobj(x, y, actor->z + (4*FRACUNIT), MT_PFLAME); + + t = P_Random(); + mo->momx += ((t & 7) - (P_Random() & 7)) << FRACBITS; + t = P_Random(); + mo->momy += ((t & 7) - (P_Random() & 7)) << FRACBITS; + mo->momz -= FRACUNIT; + mo->flags |= MF_DROPPED; + mo->reactiontime = (P_Random() & 3) + 2; +} + +// +// A_BossDeath +// +// Possibly trigger special effects +// if on first boss level +// +// haleyjd 09/17/10: [STRIFE] +// * Modified to handle all Strife bosses. +// +void A_BossDeath (mobj_t* actor) +{ + int i; + thinker_t *th; + line_t junk; + + // only the following types can be a boss: + switch(actor->type) + { + case MT_CRUSADER: + case MT_SPECTRE_A: + case MT_SPECTRE_B: + case MT_SPECTRE_C: + case MT_SPECTRE_D: + case MT_SPECTRE_E: + case MT_SUBENTITY: + case MT_PROGRAMMER: + break; + default: + return; + } + + // check for a living player + for(i = 0; i < MAXPLAYERS; i++) + { + if(playeringame[i] && players[i].health > 0) + break; + } + if(i == MAXPLAYERS) + return; // everybody's dead. + + // check for a still living boss + for(th = thinkercap.next; th != &thinkercap; th = th->next) + { + if(th->function.acp1 == (actionf_p1) P_MobjThinker) + { + mobj_t *mo = (mobj_t *)th; + + if(mo != actor && mo->type == actor->type && mo->health > 0) + return; // one is still alive. + } + } + + // Victory! + switch(actor->type) + { + case MT_CRUSADER: + junk.tag = 667; + EV_DoFloor(&junk, lowerFloorToLowest); + break; + + case MT_SPECTRE_A: + GiveVoiceObjective("VOC95", "LOG95", 0); + junk.tag = 999; + EV_DoFloor(&junk, lowerFloorToLowest); + break; + + case MT_SPECTRE_B: + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_BISHOP); + GiveVoiceObjective("VOC74", "LOG74", 0); + break; + + case MT_SPECTRE_C: + // Look for an MT_ORACLE - this is for in case the player awakened the + // Oracle's spectre without killing the Oracle, which is possible by + // looking up to max and firing the Sigil at it. If this were not done, + // a serious sequence break possibility would arise where one could + // kill both the Oracle AND Macil, possibly throwing the game out of + // sorts entirely. Too bad they thought of it ;) However this also + // causes a bug sometimes! The Oracle, in its death state, sets the + // Spectre C back to its seestate. If the Spectre C is already dead, + // it becomes an undead ghost monster. Then it's a REAL spectre ;) + for(th = thinkercap.next; th != &thinkercap; th = th->next) + { + if(th->function.acp1 == (actionf_p1) P_MobjThinker) + { + mobj_t *mo = (mobj_t *)th; + + // KILL ALL ORACLES! RAWWR! + if(mo != actor && mo->type == MT_ORACLE && mo->health > 0) + P_KillMobj(actor, mo); + } + } + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_ORACLE); + + // Bishop is dead? - verify. + if(players[0].questflags & QF_QUEST21) + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_QUEST22); + + // Macil is dead? + if(players[0].questflags & QF_QUEST24) + { + // Loremaster is dead? + if(players[0].questflags & QF_QUEST26) + { + // We wield the complete sigil, blahblah + GiveVoiceObjective("VOC85", "LOG85", 0); + } + } + else + { + // So much for prognostication! + GiveVoiceObjective("VOC87", "LOG87", 0); + } + junk.tag = 222; // Open the exit door again; + EV_DoDoor(&junk, vld_open); // Note this is NOT the Loremaster door... + break; + + case MT_SPECTRE_D: + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_MACIL); + if(players[0].questflags & QF_QUEST25) // Destroyed converter? + GiveVoiceObjective("VOC106", "LOG106", 0); + else + GiveVoiceObjective("VOC79", "LOG79", 0); + break; + + case MT_SPECTRE_E: + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_LOREMASTER); + if(!netgame) + { + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_STAMINA); + P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_NEW_ACCURACY); + } + if(players[0].sigiltype == 4) + GiveVoiceObjective("VOC85", "LOG85", 0); + else + GiveVoiceObjective("VOC83", "LOG83", 0); + junk.tag = 666; + EV_DoFloor(&junk, lowerFloorToLowest); + break; + + case MT_SUBENTITY: + F_StartFinale(); + break; + + case MT_PROGRAMMER: + F_StartFinale(); + G_ExitLevel(0); + break; + + default: + // Real classy, Rogue. + if(actor->type) + I_Error("Error: Unconnected BossDeath id %d", actor->type); + break; + } +} + +// +// A_AcolyteSpecial +// +// villsa [STRIFE] - new codepointer +// Awards quest #7 when all the Blue Acolytes are killed in Tarnhill +// +void A_AcolyteSpecial(mobj_t* actor) +{ + int i; + thinker_t* th; + + if(actor->type != MT_GUARD8) + return; // must be MT_GUARD8 + + for(i = 0; i < MAXPLAYERS; i++) + { + if(playeringame[i] && players[i].health > 0) + break; + } + + if(i == 8) + return; + + for(th = thinkercap.next; th != &thinkercap; th = th->next) + { + if(th->function.acp1 == (actionf_p1) P_MobjThinker) + { + mobj_t *mo = (mobj_t *)th; + + // Found a living MT_GUARD8? + if(mo != actor && mo->type == actor->type && mo->health > 0) + return; + } + } + + // All MT_GUARD8 are dead, give quest token #7 to all players + for(i = 0; i < MAXPLAYERS; i++) + P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_QUEST7); + + // play voice, give objective + GiveVoiceObjective("VOC14", "LOG14", 0); +} + +// +// A_InqChase +// villsa [STRIFE] - new codepointer +// +void A_InqChase(mobj_t* actor) +{ + S_StartSound(actor, sfx_inqact); + A_Chase(actor); +} + +// +// A_StalkerChase +// villsa [STRIFE] - new codepointer +// +void A_StalkerChase(mobj_t* actor) +{ + S_StartSound(actor, sfx_spdwlk); + A_Chase(actor); +} + +// +// A_PlayerScream +// +// [STRIFE] +// * Modified to eliminate gamemode check and to use Strife sound. +// +void A_PlayerScream (mobj_t* mo) +{ + // Default death sound. + int sound = sfx_pldeth; + + // villsa [STRIFE] don't check for gamemode + if(mo->health < -50) + { + // IF THE PLAYER DIES + // LESS THAN -50% WITHOUT GIBBING + sound = sfx_plxdth; // villsa [STRIFE] different sound + } + + S_StartSound (mo, sound); +} + +// +// A_TeleportBeacon +// +// villsa [STRIFE] - new codepointer +// +void A_TeleportBeacon(mobj_t* actor) +{ + mobj_t* mobj; + mobj_t* fog; + fixed_t fog_x; + fixed_t fog_y; + + if(actor->target != players[actor->miscdata].mo) + actor->target = players[actor->miscdata].mo; + + mobj = P_SpawnMobj(actor->x, actor->y, ONFLOORZ, MT_REBEL1); + + // haleyjd 20141024: missing code from disassembly; transfer allegiance + // originally from master player to the rebel. + mobj->miscdata = actor->miscdata; + + if(!P_TryMove(mobj, mobj->x, mobj->y)) + { + // Rebel is probably stuck in something.. too bad + P_RemoveMobj(mobj); + return; + } + + // beacon no longer special + actor->flags &= ~MF_SPECIAL; + + // 20160306: set rebel threshold + mobj->threshold = 100; + + // set rebel color and flags + mobj->flags |= ((actor->miscdata << MF_TRANSSHIFT) | MF_NODIALOG); + mobj->target = NULL; + + // double Rebel's health in deathmatch mode + if(deathmatch) + mobj->health <<= 1; + + if(actor->target) + { + mobj_t* targ = actor->target->target; + + if(targ) + { + if(targ->type != MT_REBEL1 || targ->miscdata != mobj->miscdata) + mobj->target = targ; + } + } + + P_SetMobjState(mobj, mobj->info->seestate); + mobj->angle = actor->angle; + + fog_x = mobj->x + FixedMul(20*FRACUNIT, finecosine[actor->angle>>ANGLETOFINESHIFT]); + fog_y = mobj->y + FixedMul(20*FRACUNIT, finesine[actor->angle>>ANGLETOFINESHIFT]); + + fog = P_SpawnMobj(fog_x, fog_y, mobj->z, MT_TFOG); + S_StartSound(fog, sfx_telept); + + if(--actor->health < 0) + P_RemoveMobj(actor); +} + +// +// A_BodyParts +// +// villsa [STRIFE] new codepointer +// 09/06/10: Spawns gibs when organic actors get splattered, or junk +// when robots explode. +// +void A_BodyParts(mobj_t* actor) +{ + mobjtype_t type; + mobj_t* mo; + angle_t an; + + if(actor->flags & MF_NOBLOOD) // Robots are flagged NOBLOOD + type = MT_JUNK; + else + type = MT_MEAT; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + (24*FRACUNIT), type); + P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 19)); + + an = (P_Random() << 13) / 255; + mo->angle = an << ANGLETOFINESHIFT; + + mo->momx = FixedMul(finecosine[an], (P_Random() & 0x0f) << FRACBITS); + mo->momy = FixedMul(finesine[an], (P_Random() & 0x0f) << FRACBITS); + mo->momz = (P_Random() & 0x0f) << FRACBITS; +} + +// +// A_ClaxonBlare +// +// [STRIFE] New function +// haleyjd 09/08/10: The ever-dreadful Strife alarm! +// +void A_ClaxonBlare(mobj_t* actor) +{ + // Timer ran down? + if(--actor->reactiontime < 0) + { + // reset to initial state + actor->target = NULL; + actor->reactiontime = actor->info->reactiontime; + + // listen for more noise + A_Listen(actor); + + // If we heard something, stay on for a while, + // otherwise return to spawnstate. + if(actor->target) + actor->reactiontime = 50; + else + P_SetMobjState(actor, actor->info->spawnstate); + } + + // When almost ran down, clear the soundtarget so it doesn't + // retrigger the alarm. + // Also, play the harsh, grating claxon. + if(actor->reactiontime == 2) + actor->subsector->sector->soundtarget = NULL; + else if(actor->reactiontime > 50) + S_StartSound(actor, sfx_alarm); +} + +// +// A_ActiveSound +// +// villsa [STRIFE] new codepointer +// 09/06/10: Plays an object's active sound periodically. +// +void A_ActiveSound(mobj_t* actor) +{ + if(actor->info->activesound) + { + if(!(leveltime & 7)) // haleyjd: added parens + S_StartSound(actor, actor->info->activesound); + } +} + +// +// A_ClearSoundTarget +// +// villsa [STRIFE] new codepointer +// 09/06/10: Clears the actor's sector soundtarget, so that the actor +// will not be continually alerted/awakened ad infinitum. Used by +// shopkeepers. +// +void A_ClearSoundTarget(mobj_t* actor) +{ + actor->subsector->sector->soundtarget = NULL; +} + +// +// A_DropBurnFlesh +// +// villsa [STRIFE] new codepointer +// +void A_DropBurnFlesh(mobj_t* actor) +{ + mobj_t* mo; + mobjtype_t type; + + type = actor->type; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z + (24*FRACUNIT), MT_BURNDROP); + mo->momz = -FRACUNIT; + + actor->type = MT_SFIREBALL; + P_RadiusAttack(actor, actor, 64); + actor->type = type; +} + +// +// A_FlameDeath +// +// villsa [STRIFE] new codepointer +// 09/06/10: Death animation for flamethrower fireballs. +// +void A_FlameDeath(mobj_t* actor) +{ + actor->flags |= MF_NOGRAVITY; + actor->momz = (P_Random() & 3) << FRACBITS; +} + +// +// A_ClearForceField +// +// villsa [STRIFE] new codepointer +// check for all matching lines in the sector +// and disable blocking/midtextures +// +void A_ClearForceField(mobj_t* actor) +{ + int i; + sector_t *sec; + line_t *secline; + + actor->flags &= ~(MF_SOLID|MF_SPECIAL); + sec = actor->subsector->sector; + + if(!sec->linecount) + return; + + for(i = 0; i < sec->linecount; i++) + { + secline = sec->lines[i]; + // BUG: will crash if 1S line has TWOSIDED flag! + if(!(secline->flags & ML_TWOSIDED)) + continue; + if(secline->special != 148) + continue; + + secline->flags &= ~ML_BLOCKING; + secline->special = 0; + sides[secline->sidenum[0]].midtexture = 0; + sides[secline->sidenum[1]].midtexture = 0; + } +} + diff --git a/games/NXDoom/src/strife/p_floor.c b/games/NXDoom/src/strife/p_floor.c new file mode 100644 index 00000000000..8efb52ccab6 --- /dev/null +++ b/games/NXDoom/src/strife/p_floor.c @@ -0,0 +1,597 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Floor animation: raising stairs. +// + + + +#include "z_zone.h" +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" +// Data. +#include "sounds.h" + +//entryway +#define STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE 10 + +// +// FLOORS +// + +// +// Move a plane (floor or ceiling) and check for crushing +// +// [STRIFE] Various changes were made to remove calls to P_ChangeSector when +// P_ChangeSector returns true. +// +result_e +T_MovePlane +( sector_t* sector, + fixed_t speed, + fixed_t dest, + boolean crush, + int floorOrCeiling, + int direction ) +{ + boolean flag; + fixed_t lastpos; + + switch(floorOrCeiling) + { + case 0: + // FLOOR + switch(direction) + { + case -1: + // DOWN + if (sector->floorheight - speed < dest) + { + // villsa [STRIFE] unused + //lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector,crush); + + // villsa [STRIFE] unused + /*if (flag == true) + { + sector->floorheight =lastpos; + P_ChangeSector(sector,crush); + //return crushed; + }*/ + return pastdest; + } + else + { + // villsa [STRIFE] unused + //lastpos = sector->floorheight; + sector->floorheight -= speed; + flag = P_ChangeSector(sector,crush); + + // villsa [STRIFE] unused + /*if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + }*/ + return ok; + } + break; + + case 1: + // UP + if (sector->floorheight + speed > dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + //return crushed; + } + return pastdest; + } + else + { + // COULD GET CRUSHED + lastpos = sector->floorheight; + sector->floorheight += speed; + flag = P_ChangeSector(sector,crush); + if (flag == true) + { + // haleyjd 20130210: Bug fix - Strife DOES do this. + if (crush == true) + return crushed; + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + } + else + return ok; + } + break; + } + break; + + case 1: + // CEILING + switch(direction) + { + case -1: + // DOWN + if (sector->ceilingheight - speed < dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = P_ChangeSector(sector,crush); + + if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + //return crushed; + } + return pastdest; + } + else + { + // COULD GET CRUSHED + lastpos = sector->ceilingheight; + sector->ceilingheight -= speed; + flag = P_ChangeSector(sector,crush); + + if (flag == true) + { + if (crush == true) + return crushed; + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + return crushed; + } + } + break; + + case 1: + // UP + if (sector->ceilingheight + speed > dest) + { + // villsa [STRIFE] unused + //lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + + // villsa [STRIFE] unused + //flag = P_ChangeSector(sector,crush); + /*if (flag == true) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + //return crushed; + }*/ + return pastdest; + } + else + { + // villsa [STRIFE] unused + //lastpos = sector->ceilingheight; + sector->ceilingheight += speed; + + // villsa [STRIFE] unused + //flag = P_ChangeSector(sector,crush); + return ok; + } + break; + } + break; + + } + return ok; +} + + +// +// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) +// +void T_MoveFloor(floormove_t* floor) +{ + result_e res; + + res = T_MovePlane(floor->sector, + floor->speed, + floor->floordestheight, + floor->crush,0,floor->direction); + + if (!(leveltime&7)) + S_StartSound(&floor->sector->soundorg, sfx_stnmov); + + if (res == pastdest) + { + floor->sector->specialdata = NULL; + + if (floor->direction == 1) + { + switch(floor->type) + { + case donutRaise: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + else if (floor->direction == -1) + { + switch(floor->type) + { + case lowerAndChange: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + P_RemoveThinker(&floor->thinker); + + S_StartSound(&floor->sector->soundorg, sfx_pstop); + } + +} + +// +// HANDLE FLOOR TYPES +// +// haleyjd 09/16/2010: [STRIFE] Modifications to floortypes: +// * raiseFloor24 was changed into raiseFloor64 +// * turboLower does not appear to adjust the floor height (STRIFE-TODO: verify) +// * raiseFloor512AndChange type was added. +// +int +EV_DoFloor +( line_t* line, + floor_e floortype ) +{ + int secnum; + int rtn; + int i; + sector_t* sec; + floormove_t* floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // new floor thinker + rtn = 1; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = floortype; + floor->crush = false; + + switch(floortype) + { + case lowerFloor: // [STRIFE] verified unmodified + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindHighestFloorSurrounding(sec); + break; + + case lowerFloorToLowest: // [STRIFE] verified unmodified + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindLowestFloorSurrounding(sec); + break; + + case turboLower: // [STRIFE] Modified: does not += 8 + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED * 4; + floor->floordestheight = + P_FindHighestFloorSurrounding(sec); + //if (floor->floordestheight != sec->floorheight) + // floor->floordestheight += 8*FRACUNIT; + break; + + case raiseFloorCrush: // [STRIFE] verified unmodified + floor->crush = true; + case raiseFloor: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindLowestCeilingSurrounding(sec); + if (floor->floordestheight > sec->ceilingheight) + floor->floordestheight = sec->ceilingheight; + floor->floordestheight -= (8*FRACUNIT)* + (floortype == raiseFloorCrush); + break; + + case raiseFloorTurbo: // [STRIFE] verified unmodified + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED*4; + floor->floordestheight = + P_FindNextHighestFloor(sec,sec->floorheight); + break; + + case raiseFloorToNearest: // [STRIFE] verified unmodified + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindNextHighestFloor(sec,sec->floorheight); + break; + + case raiseFloor64: // [STRIFE] modified from raiseFloor24! + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 64 * FRACUNIT; // [STRIFE] + break; + + case raiseFloor512: // [STRIFE] verified unmodified + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 512 * FRACUNIT; + break; + + case raiseFloor24AndChange: // [STRIFE] verified unmodified + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 24 * FRACUNIT; + sec->floorpic = line->frontsector->floorpic; + sec->special = line->frontsector->special; + break; + + case raiseFloor512AndChange: // [STRIFE] New floor type + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = floor->sector->floorheight + + 512 * FRACUNIT; + sec->floorpic = line->frontsector->floorpic; + sec->special = line->frontsector->special; + break; + + case raiseToTexture: // [STRIFE] verified unmodified + { + int minsize = INT_MAX; + side_t* side; + + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + for (i = 0; i < sec->linecount; i++) + { + if (twoSided (secnum, i) ) + { + side = getSide(secnum,i,0); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < + minsize) + minsize = + textureheight[side->bottomtexture]; + side = getSide(secnum,i,1); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < + minsize) + minsize = + textureheight[side->bottomtexture]; + } + } + floor->floordestheight = + floor->sector->floorheight + minsize; + } + break; + + case lowerAndChange: // [STRIFE] verified unmodified + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + P_FindLowestFloorSurrounding(sec); + floor->texture = sec->floorpic; + + for (i = 0; i < sec->linecount; i++) + { + if ( twoSided(secnum, i) ) + { + if (getSide(secnum,i,0)->sector-sectors == secnum) + { + sec = getSector(secnum,i,1); + + if (sec->floorheight == floor->floordestheight) + { + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + else + { + sec = getSector(secnum,i,0); + + if (sec->floorheight == floor->floordestheight) + { + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + } + } + default: + break; + } + } + return rtn; +} + + + + +// +// BUILD A STAIRCASE! +// +int +EV_BuildStairs +( line_t* line, + stair_e type ) +{ + int secnum; + int height; + int i; + int newsecnum; + int texture; + int ok; + int rtn; + + sector_t* sec; + sector_t* tsec; + + floormove_t* floor; + + // Either Watcom or Rogue moved the switch out of the loop below, probably + // because it was a loop invariant, and put the default values in the + // initializers here. I cannot be bothered to figure it out without doing + // this myself :P + fixed_t stairsize = 8*FRACUNIT; + fixed_t speed = FLOORSPEED; + int direction = 1; + + switch(type) + { + case build8: // [STRIFE] Verified unmodified. + speed = FLOORSPEED/4; + break; + case turbo16: // [STRIFE] Verified unmodified. + speed = FLOORSPEED*4; + stairsize = 16*FRACUNIT; + break; + case buildDown16: // [STRIFE] New stair type + stairsize = -16*FRACUNIT; + direction = -1; + break; + } + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (sec->specialdata) + continue; + + // new floor thinker + rtn = 1; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->tag = 0; // haleyjd 20140919: [STRIFE] clears tag of first stair sector + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->direction = direction; // haleyjd 20140919: bug fix: direction, not "1" + floor->sector = sec; + floor->speed = speed; + height = sec->floorheight + stairsize; + floor->floordestheight = height; + // Initialize + floor->type = lowerFloor; + // entryway + // Uninitialized crush field will not be equal to 0 or 1 (true) + // with high probability. So, initialize it with any other value + floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; + + texture = sec->floorpic; + + // Find next sector to raise + // 1. Find 2-sided line with same sector side[0] + // 2. Other side is the next sector to raise + do + { + ok = 0; + for (i = 0;i < sec->linecount;i++) + { + if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) + continue; + + tsec = (sec->lines[i])->frontsector; + newsecnum = tsec-sectors; + + if (secnum != newsecnum) + continue; + + tsec = (sec->lines[i])->backsector; + newsecnum = tsec - sectors; + + if (tsec->floorpic != texture) + continue; + + height += stairsize; + + if (tsec->specialdata) + continue; + + sec = tsec; + secnum = newsecnum; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + + P_AddThinker (&floor->thinker); + + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->direction = direction; // [STRIFE]: for buildDown16 + floor->sector = sec; + floor->speed = speed; + floor->floordestheight = height; + // Initialize + floor->type = lowerFloor; + // entryway + // Uninitialized crush field will not be equal to 0 or 1 (true) + // with high probability. So, initialize it with any other value + floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; + ok = 1; + break; + } + } while(ok); + } + return rtn; +} + diff --git a/games/NXDoom/src/strife/p_inter.c b/games/NXDoom/src/strife/p_inter.c new file mode 100644 index 00000000000..bf36cb14776 --- /dev/null +++ b/games/NXDoom/src/strife/p_inter.c @@ -0,0 +1,1411 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handling interactions (i.e., collisions). +// + +// Data. +#include "doomdef.h" +#include "dstrings.h" +#include "sounds.h" +#include "deh_main.h" +#include "deh_misc.h" +#include "doomstat.h" +#include "m_misc.h" +#include "m_random.h" +#include "i_system.h" +#include "am_map.h" +#include "p_local.h" +#include "p_dialog.h" // villsa [STRIFE] +#include "s_sound.h" +#include "p_inter.h" + +#include "hu_stuff.h" // villsa [STRIFE] +#include "z_zone.h" // villsa [STRIFE] + +// haleyjd [STRIFE] +#include "w_wad.h" +#include "p_pspr.h" +#include "p_dialog.h" +#include "f_finale.h" + + +#define BONUSADD 6 + + +// a weapon is found with two clip loads, +// a big item has five clip loads +// villsa [STRIFE] updated arrays +int maxammo[NUMAMMO] = { 250, 50, 25, 400, 100, 30, 16 }; +int clipammo[NUMAMMO] = { 10, 4, 2, 20, 4, 6, 4 }; + + +// +// GET STUFF +// + +// +// P_GiveAmmo +// Num is the number of clip loads, +// not the individual count (0= 1/2 clip). +// Returns false if the ammo can't be picked up at all +// +// [STRIFE] Modified for Strife ammo types +// +boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int num) +{ + int oldammo; + + if(ammo == am_noammo) + return false; + + if(ammo >= NUMAMMO) + I_Error ("P_GiveAmmo: bad type %i", ammo); + + if(player->ammo[ammo] == player->maxammo[ammo]) + return false; + + if(num) + num *= clipammo[ammo]; + else + num = clipammo[ammo]/2; + + if(gameskill == sk_baby + || gameskill == sk_nightmare) + { + // give double ammo in trainer mode, + // you'll need in nightmare + num <<= 1; + } + + oldammo = player->ammo[ammo]; + player->ammo[ammo] += num; + + if(player->ammo[ammo] > player->maxammo[ammo]) + player->ammo[ammo] = player->maxammo[ammo]; + + // If non zero ammo, + // don't change up weapons, + // player was lower on purpose. + if(oldammo) + return true; + + // We were down to zero, + // so select a new weapon. + // Preferences are not user selectable. + + // villsa [STRIFE] ammo update + // where's the check for grenades? - haleyjd: verified no switch to grenades + // haleyjd 10/03/10: don't change to electric bow when picking up poison + // arrows. + if(!player->readyweapon) + { + switch(ammo) + { + case am_bullets: + if(player->weaponowned[wp_rifle]) + player->pendingweapon = wp_rifle; + break; + + case am_elecbolts: + if(player->weaponowned[wp_elecbow]) + player->pendingweapon = wp_elecbow; + break; + + case am_cell: + if(player->weaponowned[wp_mauler]) + player->pendingweapon = wp_mauler; + break; + + case am_missiles: + if(player->weaponowned[wp_missile]) + player->pendingweapon = wp_missile; + break; + + default: + break; + } + } + + return true; +} + + +// +// P_GiveWeapon +// The weapon name may have a MF_DROPPED flag ored in. +// +// villsa [STRIFE] some stuff has been changed/moved around +// +boolean P_GiveWeapon(player_t* player, weapontype_t weapon, boolean dropped) +{ + boolean gaveammo; + boolean gaveweapon; + + // villsa [STRIFE] new code for giving alternate version + // of the weapon to player + if(player->weaponowned[weapon]) + gaveweapon = false; + else + { + gaveweapon = true; + player->weaponowned[weapon] = true; + + // Alternate "sister" weapons that you also get as a bonus: + switch(weapon) + { + case wp_elecbow: + player->weaponowned[wp_poisonbow] = true; + break; + + case wp_hegrenade: + player->weaponowned[wp_wpgrenade] = true; + break; + + case wp_mauler: + player->weaponowned[wp_torpedo] = true; + break; + + default: + break; + } + + // check for the standard weapons only + if(weapon > player->readyweapon && weapon <= wp_sigil) + player->pendingweapon = weapon; + + } + + if(netgame && (deathmatch != 2) && !dropped) + { + // leave placed weapons forever on net games + if(!gaveweapon) + return false; + + player->bonuscount += BONUSADD; + player->weaponowned[weapon] = true; + + if(deathmatch) + P_GiveAmmo(player, weaponinfo[weapon].ammo, 5); + else + P_GiveAmmo(player, weaponinfo[weapon].ammo, 2); + + if(player == &players[consoleplayer]) + S_StartSound (NULL, sfx_wpnup); + return false; + } + + if(weaponinfo[weapon].ammo != am_noammo) + { + // give one clip with a dropped weapon, + // two clips with a found weapon + if(dropped) + gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1); + else + gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); + } + else + gaveammo = false; + + return(gaveweapon || gaveammo); +} + + + +// +// P_GiveBody +// Returns false if the body isn't needed at all +// +// villsa [STRIFE] a lot of changes have been added for stamina +// +boolean P_GiveBody(player_t* player, int num) +{ + int maxhealth; + int healing; + + maxhealth = MAXHEALTH + player->stamina; + + if(num >= 0) // haleyjd 20100923: fixed to give proper amount of health + { + mobj_t *mo; // haleyjd 20110225: needed below... + + // any healing to do? + if(player->health >= maxhealth) + return false; + + // give, and cap to maxhealth + player->health += num; + if(player->health >= maxhealth) + player->health = maxhealth; + + // Set mo->health for consistency. + // haleyjd 20110225: Seems Strife can call this on a NULL player->mo + // when giving items to players that are not in the game... + mo = P_SubstNullMobj(player->mo); + mo->health = player->health; + } + else + { + // [STRIFE] handle healing from the Front's medic + // The amount the player's health will be set to scales up with stamina + // increases. + // Ex 1: On the wimpiest skill level, -100 is sent in. This restores + // full health no matter what your stamina. + // (100*100)/100 = 100 + // (200*100)/100 = 200 + // Ex 2: On the most stringent skill levels, -50 is sent in. This will + // restore at most half of your health. + // (100*50)/100 = 50 + // (200*50)/100 = 100 + healing = (-num * maxhealth) / MAXHEALTH; + + // This is also the "threshold" of healing. You need less health than + // the amount that will be restored in order to get any benefit. + // So on the easiest skill you will always be fully healed. + // On the hardest skill you must have less than 50 health, and will + // only recover to 50 (assuming base stamina stat) + if(player->health >= healing) + return false; + + // Set health. BUG: Oddly, mo->health is NOT set here... + player->health = healing; + } + + return true; +} + + + +// +// P_GiveArmor +// Returns false if the armor is worse +// than the current armor. +// +// [STRIFE] Modified for Strife armor items +// +boolean P_GiveArmor(player_t* player, int armortype) +{ + int hits; + + // villsa [STRIFE] + if(armortype < 0) + { + if(player->armorpoints) + return false; + + armortype = -armortype; + } + + hits = armortype * 100; + if(player->armorpoints >= hits) + return false; // don't pick up + + player->armortype = armortype; + player->armorpoints = hits; + + return true; +} + + + +// +// P_GiveCard +// +// [STRIFE] Modified to use larger bonuscount +// +boolean P_GiveCard(player_t* player, card_t card) +{ + if (player->cards[card]) + return false; + + // villsa [STRIFE] multiply by 2 + player->bonuscount = BONUSADD * 2; + player->cards[card] = true; + + return true; +} + + +// +// P_GivePower +// +// [STRIFE] Modifications for new powerups +// +boolean P_GivePower(player_t* player, powertype_t power) +{ + // haleyjd 09/14/10: [STRIFE] moved to top, exception for Shadow Armor + if(player->powers[power] && power != pw_invisibility) + return false; // already got it + + // if giving pw_invisibility and player already has MVIS, no can do. + if(power == pw_invisibility && (player->mo->flags & MF_MVIS)) + return false; + + // villsa [STRIFE] + switch (power) { + case pw_targeter: + { + player->powers[power] = TARGTICS; + P_SetPsprite(player, ps_targcenter, S_TRGT_00); // 10 + P_SetPsprite(player, ps_targleft, S_TRGT_01); // 11 + P_SetPsprite(player, ps_targright, S_TRGT_02); // 12 + + player->psprites[ps_targcenter].sx = (160*FRACUNIT); + player->psprites[ps_targleft ].sy = (100*FRACUNIT); + player->psprites[ps_targcenter].sy = (100*FRACUNIT); + player->psprites[ps_targright ].sy = (100*FRACUNIT); + return true; + } + + case pw_invisibility: + { + // if player already had this power... + if(player->powers[power]) + { + // remove SHADOW, give MVIS. + player->mo->flags &= ~MF_SHADOW; + player->mo->flags |= MF_MVIS; + } + else // give SHADOW + player->mo->flags |= MF_SHADOW; + + // set tics if giving shadow, or renew them if MVIS. + player->powers[power] = INVISTICS; + + return true; + } + + case pw_ironfeet: + { + player->powers[power] = IRONTICS; + return true; + } + + case pw_strength: + { + P_GiveBody(player, 100); + player->powers[power] = 1; + return true; + } + + // villsa [STRIFE] + case pw_allmap: + { + // remember in mapstate + if(gamemap < 40) + player->mapstate[gamemap] = true; + + player->powers[power] = 1; + return true; + } + + // villsa [STRIFE] + case pw_communicator: + { + player->powers[power] = 1; + return true; + } + + case NUMPOWERS: + // This should never actually happen + break; + } + + return true; +} + + +// villsa [STRIFE] +static char pickupmsg[80]; + +// +// P_TouchSpecialThing +// +// [STRIFE] Rewritten for Strife collectables. +// +void P_TouchSpecialThing(mobj_t* special, mobj_t* toucher) +{ + player_t* player; + int i; + fixed_t delta; + int sound; + + delta = special->z - toucher->z; + + if(delta > toucher->height || delta < -8*FRACUNIT) + return; // out of reach + + sound = sfx_itemup; + player = toucher->player; + + // Dead thing touching. + // Can happen with a sliding player corpse. + if(toucher->health <= 0) + return; + + // villsa [STRIFE] damage toucher if special is spectral + // haleyjd 09/21/10: corrected to test for SPECTRE thingtypes specifically + switch(special->type) + { + case MT_SPECTRE_A: + case MT_SPECTRE_B: + case MT_SPECTRE_C: + case MT_SPECTRE_D: + case MT_SPECTRE_E: + case MT_ENTITY: + case MT_SUBENTITY: + P_DamageMobj(toucher, NULL, NULL, 5); + return; + default: + break; + } + + // villsa [STRIFE] + pickupmsg[0] = 0; + + // Identify by sprite. + // villsa [STRIFE] new items + switch(special->sprite) + { + // bullets + case SPR_BLIT: // haleyjd: fixed missing MF_DROPPED check + if(!P_GiveAmmo(player, am_bullets, !(special->flags & MF_DROPPED))) + return; + break; + + // box of bullets + case SPR_BBOX: + if(!P_GiveAmmo(player, am_bullets, 5)) + return; + break; + + // missile + case SPR_MSSL: + if(!P_GiveAmmo(player, am_missiles, 1)) + return; + break; + + // box of missiles + case SPR_ROKT: + if(!P_GiveAmmo(player, am_missiles, 5)) + return; + break; + + // battery + case SPR_BRY1: + if(!P_GiveAmmo(player, am_cell, 1)) + return; + break; + + // cell pack + case SPR_CPAC: + if(!P_GiveAmmo(player, am_cell, 5)) + return; + break; + + // poison bolts + case SPR_PQRL: + if(!P_GiveAmmo(player, am_poisonbolts, 5)) + return; + break; + + // electric bolts + case SPR_XQRL: + if(!P_GiveAmmo(player, am_elecbolts, 5)) + return; + break; + + // he grenades + case SPR_GRN1: + if(!P_GiveAmmo(player, am_hegrenades, 1)) + return; + break; + + // wp grenades + case SPR_GRN2: + if(!P_GiveAmmo(player, am_wpgrenades, 1)) + return; + break; + + // rifle + case SPR_RIFL: + if(!P_GiveWeapon(player, wp_rifle, (special->flags & MF_DROPPED) != 0)) + return; + sound = sfx_wpnup; // haleyjd: SHK-CHK! + break; + + // flame thrower + case SPR_FLAM: + if(!P_GiveWeapon(player, wp_flame, false)) + return; + // haleyjd: gives extra ammo. + P_GiveAmmo(player, am_cell, 3); + sound = sfx_wpnup; // haleyjd: SHK-CHK! + break; + + // missile launcher + case SPR_MMSL: + if(!P_GiveWeapon(player, wp_missile, false)) + return; + sound = sfx_wpnup; // haleyjd: SHK-CHK! + break; + + // grenade launcher + case SPR_GRND: + if(!P_GiveWeapon(player, wp_hegrenade, + (special->flags & MF_DROPPED) != 0)) + return; + sound = sfx_wpnup; // haleyjd: SHK-CHK! + break; + + // mauler + case SPR_TRPD: + if(!P_GiveWeapon(player, wp_mauler, false)) + return; + sound = sfx_wpnup; // haleyjd: SHK-CHK! + break; + + // electric bolt crossbow + case SPR_CBOW: + if(!P_GiveWeapon(player, wp_elecbow, + (special->flags & MF_DROPPED) != 0)) + return; + sound = sfx_wpnup; // haleyjd: SHK-CHK! + break; + + // haleyjd 09/21/10: missed case: THE SIGIL! + case SPR_SIGL: + if(!P_GiveWeapon(player, wp_sigil, (special->flags & MF_DROPPED) != 0)) + { + player->sigiltype = special->frame; + return; + } + + if(netgame) + player->sigiltype = 4; + + player->pendingweapon = wp_sigil; + player->st_update = true; + if(deathmatch) + return; + sound = sfx_wpnup; + break; + + // backpack + case SPR_BKPK: + if(!player->backpack) + { + for(i = 0; i < NUMAMMO; i++) + player->maxammo[i] *= 2; + + player->backpack = true; + } + for(i = 0; i < NUMAMMO; i++) + P_GiveAmmo(player, i, 1); + break; + + // 1 Gold + case SPR_COIN: + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + // 10 Gold + case SPR_CRED: + for(i = 0; i < 10; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + // 25 Gold + case SPR_SACK: + // haleyjd 09/21/10: missed code: if a SPR_SACK object has negative + // health, it will give that much gold - STRIFE-TODO: verify + if(special->health < 0) + { + for(i = special->health; i != 0; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + } + else + { + for(i = 0; i < 25; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + } + break; + + // 50 Gold + case SPR_CHST: + for(i = 0; i < 50; i++) + P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); + break; + + // Leather Armor + case SPR_ARM1: + if(!P_GiveArmor(player, -2)) + if(!P_GiveInventoryItem(player, special->sprite, special->type)) + pickupmsg[0] = '!'; + break; + + // Metal Armor + case SPR_ARM2: + if(!P_GiveArmor(player, -1)) + if(!P_GiveInventoryItem(player, special->sprite, special->type)) + pickupmsg[0] = '!'; + break; + + // All-map powerup + case SPR_PMAP: + if(!P_GivePower(player, pw_allmap)) + return; + sound = sfx_yeah; + break; + + // The Comm Unit - because you need Blackbird whining in your ear the + // whole time and telling you how lost she is :P + case SPR_COMM: + if(!P_GivePower(player, pw_communicator)) + return; + sound = sfx_yeah; + break; + + // haleyjd 09/21/10: missed case - Shadow Armor; though, I do not know why + // this has a case distinct from generic inventory items... Maybe it started + // out as an auto-use-if-possible item much like regular armor... + case SPR_SHD1: + if(!P_GiveInventoryItem(player, SPR_SHD1, special->type)) + pickupmsg[0] = '!'; + break; + + // villsa [STRIFE] check default items + case SPR_TOKN: + default: + if(special->type >= MT_KEY_BASE && special->type <= MT_NEWKEY5) + { + // haleyjd 09/21/10: Strife player still picks up keys that + // he has already found. (break, not return) + if(!P_GiveCard(player, special->type - MT_KEY_BASE)) + break; + } + else + { + if(!P_GiveInventoryItem(player, special->sprite, special->type)) + pickupmsg[0] = '!'; + } + break; + } + + // villsa [STRIFE] set message + if(!pickupmsg[0]) + { + if(special->info->name) + { + DEH_snprintf(pickupmsg, sizeof(pickupmsg), + "You picked up the %s.", DEH_String(special->info->name)); + } + else + DEH_snprintf(pickupmsg, sizeof(pickupmsg), "You picked up the item."); + } + // use the first character to indicate that the player is full on items + else if(pickupmsg[0] == '!') + { + DEH_snprintf(pickupmsg, sizeof(pickupmsg), "You cannot hold any more."); + player->message = pickupmsg; + return; + } + + if(special->flags & MF_GIVEQUEST) + { + // [STRIFE]: Award quest flag based on the thing's speed. Quest 8 was + // apparently at some point given by the Broken Power Coupling, which is + // why they don't want to award it if you have Quest 6 (which is + // acquired by destroying the Front's working power coupling). BUT, the + // broken coupling object's speed is NOT 8... it is 512*FRACUNIT. For + // strict portability beyond the x86, we need to AND the operand by 31. + if(special->info->speed != 8 || !(player->questflags & QF_QUEST6)) + player->questflags |= 1 << ((special->info->speed - 1) & 31); + } + + + // haleyjd 08/30/10: [STRIFE] No itemcount + //if (special->flags & MF_COUNTITEM) + // player->itemcount++; + + P_RemoveMobj(special); + player->message = pickupmsg; + player->bonuscount += BONUSADD; + + if(player == &players[consoleplayer]) + S_StartSound(NULL, sound); +} + +// villsa [STRIFE] +static char plrkilledmsg[80]; + +// +// KillMobj +// +// [STRIFE] Major modifications for drop types, no tic randomization, etc. +// +void P_KillMobj(mobj_t* source, mobj_t* target) +{ + mobjtype_t item; + mobj_t* mo; + line_t junk; + int i; + + // villsa [STRIFE] corpse and dropoff are removed, but why when these two flags + // are set a few lines later? watcom nonsense perhaps? + target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_BOUNCE|MF_CORPSE|MF_DROPOFF); + + // villsa [STRIFE] unused + /* + if (target->type != MT_SKULL) + target->flags &= ~MF_NOGRAVITY; + */ + + target->flags |= MF_CORPSE|MF_DROPOFF; + target->height = FRACUNIT; // villsa [STRIFE] set to fracunit instead of >>= 2 + + if(source && source->player) + { + // count for intermission + if(target->flags & MF_COUNTKILL) + source->player->killcount++; + + if(target->player) + { + source->player->frags[target->player-players]++; + + // villsa [STRIFE] new messages when fragging players + // haleyjd 20141024: corrected; uses player->allegiance, not mo->miscdata + DEH_snprintf(plrkilledmsg, sizeof(plrkilledmsg), + "%s killed %s", + player_names[source->player->allegiance], + player_names[target->player->allegiance]); + + if(netgame) + players[consoleplayer].message = plrkilledmsg; + } + } + else if(!netgame && (target->flags & MF_COUNTKILL)) + { + // count all monster deaths, + // even those caused by other monsters + players[0].killcount++; + } + + if(target->player) + { + // count environment kills against you + if(!source) + target->player->frags[target->player-players]++; + + if(gamemap == 29 && !netgame) + { + // haleyjd 09/13/10: [STRIFE] Give player the bad ending. + F_StartFinale(); + return; + } + + // villsa [STRIFE] spit out inventory items when killed + if(netgame) + { + int amount = 0; + mobj_t* loot; + int r = 0; + + while(1) + { + if(target->player->inventory[0].amount <= 0) + break; + + item = target->player->inventory[0].type; + if(item == MT_MONY_1) + { + loot = P_SpawnMobj(target->x, target->y, + target->z + (24*FRACUNIT), MT_MONY_25); + + // [STRIFE] TODO - what the hell is it doing here? + loot->health = target->player->inventory[0].amount; + loot->health = -target->player->inventory[0].amount; + + amount = target->player->inventory[0].amount; + } + else + { + loot = P_SpawnMobj(target->x, target->y, + target->z + (24*FRACUNIT), item); + amount = 1; + } + + P_RemoveInventoryItem(target->player, 0, amount); + r = P_Random(); + loot->momx += ((r & 7) - (P_Random() & 7)) << FRACBITS; + loot->momy += ((P_Random() & 7) + 1) << FRACBITS; + loot->flags |= MF_DROPPED; + } + } + + //target->flags &= ~MF_SOLID; + target->player->playerstate = PST_DEAD; + target->player->mo->momz += 5*FRACUNIT; // [STRIFE]: small hop! + P_DropWeapon(target->player); + + if(target->player == &players[consoleplayer] + && automapactive) + { + // don't die in auto map, + // switch view prior to dying + AM_Stop (); + } + + } + + // villsa [STRIFE] some modifications to setting states + if(target->state != &states[S_BURN_23]) + { + if(target->health == -6666) + P_SetMobjState(target, S_DISR_00); // 373 + else + { + // haleyjd [STRIFE] 20160111: Rogue changed check from < to <= + if(target->health <= -target->info->spawnhealth + && target->info->xdeathstate) + P_SetMobjState(target, target->info->xdeathstate); + else + P_SetMobjState(target, target->info->deathstate); + } + } + + // villsa [STRIFE] no death tics randomization + + // Drop stuff. + // villsa [STRIFE] get item from dialog target + item = P_DialogFind(target->type, target->miscdata)->dropitem; + + if(!item) + { + // villsa [STRIFE] drop default items + switch(target->type) + { + case MT_ORACLE: + item = MT_MEAT; + break; + + case MT_PROGRAMMER: + item = MT_SIGIL_A; + break; + + case MT_PRIEST: + item = MT_JUNK; + break; + + case MT_BISHOP: + item = MT_AMINIBOX; + break; + + case MT_PGUARD: + case MT_CRUSADER: + item = MT_ACELL; + break; + + case MT_RLEADER: + item = MT_AAMMOBOX; + break; + + case MT_GUARD1: + case MT_REBEL1: + case MT_SHADOWGUARD: + item = MT_ACLIP; + break; + + case MT_SPECTRE_B: + item = MT_SIGIL_B; + break; + + case MT_SPECTRE_C: + item = MT_SIGIL_C; + break; + + case MT_SPECTRE_D: + item = MT_SIGIL_D; + break; + + case MT_SPECTRE_E: + item = MT_SIGIL_E; + break; + + case MT_COUPLING: + junk.tag = 225; + EV_DoDoor(&junk, vld_close); + + junk.tag = 44; + EV_DoFloor(&junk, lowerFloor); + + GiveVoiceObjective("VOC13", "LOG13", 0); + + item = MT_COUPLING_BROKEN; + players[0].questflags |= (1 << (mobjinfo[MT_COUPLING].speed - 1)); + break; + + default: + return; + } + } + + // handle special case for scripted target's dropped item + switch(item) + { + case MT_TOKEN_SHOPCLOSE: + junk.tag = 222; + EV_DoDoor(&junk, vld_close); + P_NoiseAlert(players[0].mo, players[0].mo); + + M_snprintf(plrkilledmsg, sizeof(plrkilledmsg), + "%s", DEH_String("You're dead! You set off the alarm.")); + if(!deathmatch) + players[consoleplayer].message = plrkilledmsg; + + return; + + case MT_TOKEN_PRISON_PASS: + junk.tag = 223; + EV_DoDoor(&junk, vld_open); + return; + + case MT_TOKEN_DOOR3: + junk.tag = 224; + EV_DoDoor(&junk, vld_open); + return; + + case MT_SIGIL_A: + case MT_SIGIL_B: + case MT_SIGIL_C: + case MT_SIGIL_D: + case MT_SIGIL_E: + for(i = 0; i < MAXPLAYERS; i++) + { + if(!P_GiveWeapon(&players[i], wp_sigil, false)) + { + if(players[i].sigiltype++ > 4) + players[i].sigiltype = 4; + } + + // haleyjd 20110225: fixed these two assignments which Watcom munged + // up in the assembly by pre-incrementing the pointer into players[] + players[i].st_update = true; + players[i].pendingweapon = wp_sigil; + } + return; + + case MT_TOKEN_ALARM: + P_NoiseAlert(players[0].mo, players[0].mo); + + M_snprintf(plrkilledmsg, sizeof(plrkilledmsg), + "%s", DEH_String("You Fool! You've set off the alarm")); + if(!deathmatch) + players[consoleplayer].message = plrkilledmsg; + return; + + default: + break; + } + + // villsa [STRIFE] toss out item + if(!deathmatch || !(mobjinfo[item].flags & MF_NOTDMATCH)) + { + int r; + + mo = P_SpawnMobj(target->x, target->y, target->z + (24*FRACUNIT), item); + r = P_Random(); + mo->momx += ((r & 7) - (P_Random() & 7)) << FRACBITS; + r = P_Random(); + mo->momy += ((r & 7) - (P_Random() & 7)) << FRACBITS; + mo->flags |= (MF_SPECIAL|MF_DROPPED); // special versions of items + } +} + +// +// P_IsMobjBoss +// +// villsa [STRIFE] new function +// +static boolean P_IsMobjBoss(mobjtype_t type) +{ + switch(type) + { + case MT_PROGRAMMER: + case MT_BISHOP: + case MT_RLEADER: + case MT_ORACLE: + case MT_PRIEST: + return true; + + default: + return false; + } +} + + +// +// P_DamageMobj +// Damages both enemies and players +// "inflictor" is the thing that caused the damage +// creature or missile, can be NULL (slime, etc) +// "source" is the thing to target after taking damage +// creature or NULL +// Source and inflictor are the same for melee attacks. +// Source can be NULL for slime, barrel explosions +// and other environmental stuff. +// +// [STRIFE] Extensive changes for spectrals, fire damage, disintegration, and +// a plethora of mobjtype-specific hacks. +// +void P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage) +{ + angle_t ang; + int saved; + player_t* player; + fixed_t thrust; + int temp; + + if(!(target->flags & MF_SHOOTABLE) ) + return; // shouldn't happen... + + if(target->health <= 0) + return; + + player = target->player; + + // villsa [STRIFE] unused - skullfly check (removed) + + // villsa [STRIFE] handle spectral stuff + // notes on projectile health: + // -2 == enemy spectral projectile + // -1 == player spectral projectile + + // haleyjd 20110203: refactored completely + if(inflictor && (inflictor->flags & MF_SPECTRAL)) + { + // players aren't damaged by their own (or others???) sigils + // STRIFE-TODO: verify in deathmatch + if(target->type == MT_PLAYER && inflictor->health == -1) + return; + // enemies aren't damaged by enemy sigil attacks + if((target->flags & MF_SPECTRAL) && inflictor->health == -2) + return; + // Macil2, Oracle, and Spectre C cannot be damaged by Sigil A + switch(target->type) + { + case MT_RLEADER2: + case MT_ORACLE: + case MT_SPECTRE_C: + // haleyjd: added source->player validity check for safety... + if(source->player && source->player->sigiltype < 1) + return; + default: + break; + } + } + + // villsa [STRIFE] new checks for various actors + if(inflictor) + { + // Fire damage inflictors + if(inflictor->type == MT_SFIREBALL || + inflictor->type == MT_C_FLAME || + inflictor->type == MT_PFLAME) + { + temp = damage / 2; + + if(P_IsMobjBoss(target->type)) + damage /= 2; + else if(inflictor->type == MT_PFLAME) + { + damage /= 2; + // robots take very little damage + if(target->flags & MF_NOBLOOD) + damage = temp / 2; + } + } + else + { + switch(inflictor->type) + { + case MT_HOOKSHOT: + // haleyjd 20110203: should use source, not inflictor + ang = R_PointToAngle2( + target->x, + target->y, + source->x, + source->y) >> ANGLETOFINESHIFT; + + target->momx += FixedMul(finecosine[ang], (12750*FRACUNIT) / target->info->mass); + target->momy += FixedMul(finesine[ang], (12750*FRACUNIT) / target->info->mass); + target->reactiontime += 10; + + temp = P_AproxDistance(target->x - source->x, target->y - source->y); + temp /= target->info->mass; + + if(temp < 1) + temp = 1; + + target->momz = (source->z - target->z) / temp; + break; + + case MT_POISARROW: + // don't affect robots + if(target->flags & MF_NOBLOOD) + return; + + // instant kill + damage = target->health + 10; + break; + + default: + // Spectral retaliation, though this may in fact be unreachable + // since non-spectral inflictors are mostly filtered out. + if(target->flags & MF_SPECTRAL + && !(inflictor->flags & MF_SPECTRAL)) + { + P_SetMobjState(target, target->info->missilestate); + return; // take no damage + } + break; + } + } + } + + // villsa [STRIFE] special cases for shopkeepers and macil + if((target->type >= MT_SHOPKEEPER_W && target->type <= MT_SHOPKEEPER_M) + || target->type == MT_RLEADER) + { + if(source) + target->target = source; + + P_SetMobjState(target, target->info->painstate); + return; + } + + // villsa [STRIFE] handle fieldguard damage + if(target->type == MT_FIELDGUARD) + { + // degnin ores are only allowed to damage the fieldguard + if(!inflictor || inflictor->type != MT_DEGNINORE) + return; + + damage = target->health; + } + + if(player && gameskill == sk_baby) + damage >>= 1; // take half damage in trainer mode + + + // Some close combat weapons should not + // inflict thrust and push the victim out of reach, + // thus kick away unless using the chainsaw. + if (inflictor + && !(target->flags & MF_NOCLIP) + && (!source + || !source->player + || source->player->readyweapon != wp_flame)) + { + ang = R_PointToAngle2(inflictor->x, + inflictor->y, + target->x, + target->y); + + thrust = damage * (FRACUNIT>>3) * 100 / target->info->mass; + + // make fall forwards sometimes + if(damage < 40 + && damage > target->health + && target->z - inflictor->z > 64*FRACUNIT + && (P_Random() & 1)) + { + ang += ANG180; + thrust *= 4; + } + + ang >>= ANGLETOFINESHIFT; + target->momx += FixedMul (thrust, finecosine[ang]); + target->momy += FixedMul (thrust, finesine[ang]); + } + + // player specific + if(player) + { + // end of game hell hack + if (target->subsector->sector->special == 11 + && damage >= target->health) + { + damage = target->health - 1; + } + + + // Below certain threshold, + // ignore damage in GOD mode. + // villsa [STRIFE] removed pw_invulnerability check + if(damage < 1000 && (player->cheats & CF_GODMODE)) + return; + + // villsa [STRIFE] flame attacks don't damage player if wearing envirosuit + if(player->powers[pw_ironfeet] && inflictor) + { + if(inflictor->type == MT_SFIREBALL || + inflictor->type == MT_C_FLAME || + inflictor->type == MT_PFLAME) + { + damage = 0; + } + } + + if(player->armortype) + { + if (player->armortype == 1) + saved = damage/3; + else + saved = damage/2; + + if(player->armorpoints <= saved) + { + // armor is used up + saved = player->armorpoints; + player->armortype = 0; + + // villsa [STRIFE] + P_UseInventoryItem(player, SPR_ARM1); + P_UseInventoryItem(player, SPR_ARM2); + } + player->armorpoints -= saved; + damage -= saved; + } + player->health -= damage; // mirror mobj health here for Dave + + // [STRIFE] haleyjd 20130302: bug fix - this is *not* capped here. + //if(player->health < 0) + // player->health = 0; + + player->attacker = source; + player->damagecount += damage; // add damage after armor / invuln + + // haleyjd 20110203 [STRIFE]: target->target set here + if(target != source) + target->target = source; + + if(player->damagecount > 100) + player->damagecount = 100; // teleport stomp does 10k points... + + temp = damage < 100 ? damage : 100; + + if(player == &players[consoleplayer]) + I_Tactile (40,10,40+temp*2); + } + + // do the damage + target->health -= damage; + + // villsa [STRIFE] auto use medkits + if(player && player->health < 50) + { + if(deathmatch || player->cheats & CF_AUTOHEALTH) + { + while(player->health < 50 && P_UseInventoryItem(player, SPR_MDKT)); + while(player->health < 50 && P_UseInventoryItem(player, SPR_STMP)); + } + } + + + if(target->health <= 0) + { + // villsa [STRIFE] grenades hurt... OUCH + if(inflictor && inflictor->type == MT_HEGRENADE) + target->health = -target->info->spawnhealth; + else if(!(target->flags & MF_NOBLOOD)) + { + // villsa [STRIFE] disintegration death + if(inflictor && + (inflictor->type == MT_STRIFEPUFF3 || + inflictor->type == MT_L_LASER || + inflictor->type == MT_TORPEDO || + inflictor->type == MT_TORPEDOSPREAD)) + { + S_StartSound(target, sfx_dsrptr); + target->health = -6666; + } + } + + // villsa [STRIFE] flame death stuff + if(!(target->flags & MF_NOBLOOD) + && inflictor + && (inflictor->type == MT_SFIREBALL || + inflictor->type == MT_C_FLAME || + inflictor->type == MT_PFLAME)) + { + target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SHADOW|MF_MVIS); + if(target->player) + { + target->player->cheats |= CF_ONFIRE; + target->player->powers[pw_invisibility] = false; + target->player->readyweapon = 0; + P_SetPsprite(target->player, ps_weapon, S_WAVE_00); // 02 + P_SetPsprite(target->player, ps_flash, S_NULL); + } + + P_SetMobjState(target, S_BURN_00); // 349 + S_StartSound(target, sfx_burnme); + + return; + } + + P_KillMobj(source, target); + return; + } + + // villsa [STRIFE] set crash state + if(target->health <= 6 && target->info->crashstate) + { + P_SetMobjState(target, target->info->crashstate); + return; + } + + if(damage) + { + // villsa [STRIFE] removed unused skullfly flag + if(P_Random() < target->info->painchance) + { + target->flags |= MF_JUSTHIT; // fight back! + P_SetMobjState (target, target->info->painstate); + } + } + + target->reactiontime = 0; // we're awake now... + + // villsa [STRIFE] new checks for thing types + if (target->type != MT_PROGRAMMER + && (!target->threshold || target->type == MT_ENTITY) + && source && source != target + && source->type != MT_ENTITY + && ((source->flags & MF_ALLY) != (target->flags & MF_ALLY))) + { + // if not intent on another player, + // chase after this one + target->target = source; + target->threshold = BASETHRESHOLD; + + if(target->state == &states[target->info->spawnstate] + && target->info->seestate != S_NULL) + P_SetMobjState (target, target->info->seestate); + } +} + diff --git a/games/NXDoom/src/strife/p_inter.h b/games/NXDoom/src/strife/p_inter.h new file mode 100644 index 00000000000..c43fc0156c6 --- /dev/null +++ b/games/NXDoom/src/strife/p_inter.h @@ -0,0 +1,32 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// +// + + +#ifndef __P_INTER__ +#define __P_INTER__ + +// haleyjd [STRIFE]: Multiple externals added +boolean P_GiveCard(player_t* player, card_t card); +boolean P_GiveBody(player_t* player, int num); +boolean P_GiveArmor(player_t* player, int armortype); +boolean P_GivePower(player_t* player, powertype_t power); +boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int num); +boolean P_GiveWeapon(player_t* player, weapontype_t weapon, boolean dropped); +void P_KillMobj(mobj_t* source, mobj_t* target); + +#endif diff --git a/games/NXDoom/src/strife/p_lights.c b/games/NXDoom/src/strife/p_lights.c new file mode 100644 index 00000000000..7fe509939ed --- /dev/null +++ b/games/NXDoom/src/strife/p_lights.c @@ -0,0 +1,372 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handle Sector base lighting effects. +// Muzzle flash? +// + + + +#include "z_zone.h" +#include "m_random.h" + +#include "doomdef.h" +#include "p_local.h" + + +// State. +#include "r_state.h" + +// +// FIRELIGHT FLICKER +// + +// +// T_FireFlicker +// +// [STRIFE] +// haleyjd 2011023: Changes to amount and duration of flicker +// +void T_FireFlicker (fireflicker_t* flick) +{ + int amount; + + if (--flick->count) + return; + + amount = (P_Random() & 3) * 8; // [STRIFE] 16 -> 8 + + if (flick->sector->lightlevel - amount < flick->minlight) + flick->sector->lightlevel = flick->minlight; + else + flick->sector->lightlevel = flick->maxlight - amount; + + // [STRIFE] flicker count made random! + flick->count = (P_Random() & 3) + 1; +} + + + +// +// P_SpawnFireFlicker +// +// [STRIFE] +// haleyjd 2011023: Changes to minimum light level and initial duration +// +void P_SpawnFireFlicker (sector_t* sector) +{ + fireflicker_t* flick; + + // Note that we are resetting sector attributes. + // Nothing special about it during gameplay. + sector->special = 0; + + flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); + + P_AddThinker (&flick->thinker); + + flick->thinker.function.acp1 = (actionf_p1) T_FireFlicker; + flick->sector = sector; + flick->maxlight = sector->lightlevel; + flick->minlight = sector->lightlevel - 32; // [STRIFE] changed from min surrounding+16 + flick->count = 2; // [STRIFE]: Initial count 4 -> 2 +} + + + +// +// BROKEN LIGHT FLASHING +// + + +// +// T_LightFlash +// Do flashing lights. +// +// [STRIFE] Verified unmodified +// +void T_LightFlash (lightflash_t* flash) +{ + if (--flash->count) + return; + + if (flash->sector->lightlevel == flash->maxlight) + { + flash->sector->lightlevel = flash->minlight; + flash->count = (P_Random()&flash->mintime)+1; + } + else + { + flash->sector->lightlevel = flash->maxlight; + flash->count = (P_Random()&flash->maxtime)+1; + } +} + + + + +// +// P_SpawnLightFlash +// After the map has been loaded, scan each sector +// for specials that spawn thinkers +// +// [STRIFE] Verified unmodified +// +void P_SpawnLightFlash (sector_t* sector) +{ + lightflash_t* flash; + + // nothing special about it during gameplay + sector->special = 0; + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + + P_AddThinker (&flash->thinker); + + flash->thinker.function.acp1 = (actionf_p1) T_LightFlash; + flash->sector = sector; + flash->maxlight = sector->lightlevel; + + flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); + flash->maxtime = 64; + flash->mintime = 7; + flash->count = (P_Random()&flash->maxtime)+1; +} + + + +// +// STROBE LIGHT FLASHING +// + + +// +// T_StrobeFlash +// +// [STRIFE] Verified unmodified +// +void T_StrobeFlash (strobe_t* flash) +{ + if (--flash->count) + return; + + if (flash->sector->lightlevel == flash->minlight) + { + flash-> sector->lightlevel = flash->maxlight; + flash->count = flash->brighttime; + } + else + { + flash-> sector->lightlevel = flash->minlight; + flash->count =flash->darktime; + } +} + + + +// +// P_SpawnStrobeFlash +// After the map has been loaded, scan each sector +// for specials that spawn thinkers +// +// [STRIFE] Verified unmodified +// +void +P_SpawnStrobeFlash +( sector_t* sector, + int fastOrSlow, + int inSync ) +{ + strobe_t* flash; + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + + P_AddThinker (&flash->thinker); + + flash->sector = sector; + flash->darktime = fastOrSlow; + flash->brighttime = STROBEBRIGHT; + flash->thinker.function.acp1 = (actionf_p1) T_StrobeFlash; + flash->maxlight = sector->lightlevel; + flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); + + if (flash->minlight == flash->maxlight) + flash->minlight = 0; + + // nothing special about it during gameplay + sector->special = 0; + + if (!inSync) + flash->count = (P_Random()&7)+1; + else + flash->count = 1; +} + + +// +// Start strobing lights (usually from a trigger) +// +// [STRIFE] Verified unmodified +// +void EV_StartLightStrobing(line_t* line) +{ + int secnum; + sector_t* sec; + + secnum = -1; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + if (sec->specialdata) + continue; + + P_SpawnStrobeFlash (sec, SLOWDARK, 0); + } +} + + + +// +// TURN LINE'S TAG LIGHTS OFF +// +// [STRIFE] Verified unmodified +// +void EV_TurnTagLightsOff(line_t* line) +{ + int i; + int j; + int min; + sector_t* sector; + sector_t* tsec; + line_t* templine; + + sector = sectors; + + for (j = 0;j < numsectors; j++, sector++) + { + if (sector->tag == line->tag) + { + min = sector->lightlevel; + for (i = 0;i < sector->linecount; i++) + { + templine = sector->lines[i]; + tsec = getNextSector(templine,sector); + if (!tsec) + continue; + if (tsec->lightlevel < min) + min = tsec->lightlevel; + } + sector->lightlevel = min; + } + } +} + + +// +// TURN LINE'S TAG LIGHTS ON +// +// [STRIFE] Verified unmodified +// +void +EV_LightTurnOn +( line_t* line, + int bright ) +{ + int i; + int j; + sector_t* sector; + sector_t* temp; + line_t* templine; + + sector = sectors; + + for (i=0;itag == line->tag) + { + // bright = 0 means to search + // for highest light level + // surrounding sector + if (!bright) + { + for (j = 0;j < sector->linecount; j++) + { + templine = sector->lines[j]; + temp = getNextSector(templine,sector); + + if (!temp) + continue; + + if (temp->lightlevel > bright) + bright = temp->lightlevel; + } + } + sector-> lightlevel = bright; + } + } +} + + +// +// Spawn glowing light +// +// [STRIFE] Verified unmodified +// +void T_Glow(glow_t* g) +{ + switch(g->direction) + { + case -1: + // DOWN + g->sector->lightlevel -= GLOWSPEED; + if (g->sector->lightlevel <= g->minlight) + { + g->sector->lightlevel += GLOWSPEED; + g->direction = 1; + } + break; + + case 1: + // UP + g->sector->lightlevel += GLOWSPEED; + if (g->sector->lightlevel >= g->maxlight) + { + g->sector->lightlevel -= GLOWSPEED; + g->direction = -1; + } + break; + } +} + +// +// [STRIFE] Verified unmodified +// +void P_SpawnGlowingLight(sector_t* sector) +{ + glow_t* g; + + g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); + + P_AddThinker(&g->thinker); + + g->sector = sector; + g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); + g->maxlight = sector->lightlevel; + g->thinker.function.acp1 = (actionf_p1) T_Glow; + g->direction = -1; + + sector->special = 0; +} + diff --git a/games/NXDoom/src/strife/p_local.h b/games/NXDoom/src/strife/p_local.h new file mode 100644 index 00000000000..abbb071ba4b --- /dev/null +++ b/games/NXDoom/src/strife/p_local.h @@ -0,0 +1,311 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Play functions, animation, global header. +// + + +#ifndef __P_LOCAL__ +#define __P_LOCAL__ + +#ifndef __R_LOCAL__ +#include "r_local.h" +#endif + +#define FLOATSPEED (FRACUNIT*5) // villsa [STRIFE] change to 5 (was 4) + + +#define MAXHEALTH 100 +#define VIEWHEIGHT (41*FRACUNIT) + +// mapblocks are used to check movement +// against lines and things +#define MAPBLOCKUNITS 128 +#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) +#define MAPBLOCKSHIFT (FRACBITS+7) +#define MAPBMASK (MAPBLOCKSIZE-1) +#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) + + +// player radius for movement checking +#define PLAYERRADIUS 16*FRACUNIT + +// MAXRADIUS is for precalculated sector block boxes +// the spider demon is larger, +// but we do not have any moving sectors nearby +#define MAXRADIUS 32*FRACUNIT + +#define GRAVITY FRACUNIT +#define MAXMOVE (30*FRACUNIT) + +#define USERANGE (64*FRACUNIT) +#define MELEERANGE (64*FRACUNIT) +#define PLAYERMELEERANGE (80*FRACUNIT) // haleyjd [STRIFE] New constant +#define MISSILERANGE (32*64*FRACUNIT) + +// follow a player exlusively for 3 seconds +#define BASETHRESHOLD 100 + + + +// +// P_TICK +// + +// both the head and tail of the thinker list +extern thinker_t thinkercap; + + +void P_InitThinkers (void); +void P_AddThinker (thinker_t* thinker); +void P_RemoveThinker (thinker_t* thinker); + + +// +// P_PSPR +// +void P_SetupPsprites (player_t* curplayer); +void P_MovePsprites (player_t* curplayer); +void P_DropWeapon (player_t* player); + + +// +// P_USER +// + +// haleyjd 09/15/10: externalized +#define INVERSECOLORMAP 32 + +void P_PlayerThink (player_t* player); +// haleyjd 08/30/10: [STRIFE] Needed externally +void P_Thrust (player_t* player, angle_t angle, fixed_t move); +// villsa [STRIFE] +const char *P_RemoveInventoryItem(player_t *player, int slot, int amount); + + +// +// P_MOBJ +// +#define ONFLOORZ INT_MIN +#define ONCEILINGZ INT_MAX + +// Time interval for item respawning. +#define ITEMQUESIZE 128 + +extern mapthing_t itemrespawnque[ITEMQUESIZE]; +extern int itemrespawntime[ITEMQUESIZE]; +extern int iquehead; +extern int iquetail; + + +void P_RespawnSpecials (void); + +mobj_t* +P_SpawnMobj +( fixed_t x, + fixed_t y, + fixed_t z, + mobjtype_t type ); + +void P_RemoveMobj (mobj_t* th); +mobj_t* P_SubstNullMobj (mobj_t* th); +boolean P_SetMobjState (mobj_t* mobj, statenum_t state); +void P_MobjThinker (mobj_t* mobj); + +void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); +mobj_t* P_SpawnSparkPuff(fixed_t x, fixed_t y, fixed_t z); // villsa [STRIFE] +void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); +mobj_t* P_SpawnMissile (mobj_t* source, mobj_t* dest, mobjtype_t type); +mobj_t* P_SpawnFacingMissile(mobj_t* source, mobj_t* target, mobjtype_t type); // villsa [STRIFE] +mobj_t* P_SpawnPlayerMissile(mobj_t* source, mobjtype_t type); +mobj_t* P_SpawnMortar(mobj_t *source, mobjtype_t type); // villsa [STRIFE] +void P_ExplodeMissile (mobj_t* mo); // villsa [STRIFE] + + +// +// P_ENEMY +// +void P_NoiseAlert (mobj_t* target, mobj_t* emmiter); +void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee); // villsa [STRIFE] +void A_BodyParts(mobj_t *actor); // haleyjd: [STRIFE] +void A_AlertSpectreC(mobj_t* actor); +void A_FaceTarget (mobj_t* actor); +void P_FreePrisoners(void); +void P_DestroyConverter(void); + +// +// P_MAPUTL +// +typedef struct +{ + fixed_t x; + fixed_t y; + fixed_t dx; + fixed_t dy; + +} divline_t; + +typedef struct +{ + fixed_t frac; // along trace line + boolean isaline; + union { + mobj_t* thing; + line_t* line; + } d; +} intercept_t; + +// Extended MAXINTERCEPTS, to allow for intercepts overrun emulation. + +#define MAXINTERCEPTS_ORIGINAL 128 +#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61) + +extern intercept_t intercepts[MAXINTERCEPTS]; +extern intercept_t* intercept_p; + +typedef boolean (*traverser_t) (intercept_t *in); + +fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); +int P_PointOnLineSide (fixed_t x, fixed_t y, line_t* line); +int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t* line); +void P_MakeDivline (line_t* li, divline_t* dl); +fixed_t P_InterceptVector (divline_t* v2, divline_t* v1); +int P_BoxOnLineSide (fixed_t* tmbox, line_t* ld); + +extern fixed_t opentop; +extern fixed_t openbottom; +extern fixed_t openrange; +extern fixed_t lowfloor; + +void P_LineOpening (line_t* linedef); + +boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); +boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ); + +#define PT_ADDLINES 1 +#define PT_ADDTHINGS 2 +#define PT_EARLYOUT 4 + +extern divline_t trace; + +boolean +P_PathTraverse +( fixed_t x1, + fixed_t y1, + fixed_t x2, + fixed_t y2, + int flags, + boolean (*trav) (intercept_t *)); + +void P_UnsetThingPosition (mobj_t* thing); +void P_SetThingPosition (mobj_t* thing); + + +// +// P_MAP +// + +// If "floatok" true, move would be ok +// if within "tmfloorz - tmceilingz". +extern boolean floatok; +extern fixed_t tmfloorz; +extern fixed_t tmceilingz; + +extern line_t *ceilingline; +extern line_t *blockingline; // [STRIFE] New global + +extern int numspechit; +extern line_t *spechit[]; + +extern fixed_t attackrange; + +// slopes to top and bottom of target +extern fixed_t topslope; +extern fixed_t bottomslope; + + +boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); +boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); +boolean P_CheckPositionZ(mobj_t* thing, fixed_t z); // villsa [STRIFE] +boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y); +void P_SlideMove (mobj_t* mo); +boolean P_CheckSight (mobj_t* t1, mobj_t* t2); +void P_UseLines (player_t* player); + +boolean P_ChangeSector (sector_t* sector, boolean crunch); + +extern mobj_t* linetarget; // who got hit (or NULL) + +fixed_t +P_AimLineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance ); + +void +P_LineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance, + fixed_t slope, + int damage ); + +void +P_RadiusAttack +( mobj_t* spot, + mobj_t* source, + int damage ); + + + +// +// P_SETUP +// +extern byte* rejectmatrix; // for fast sight rejection +extern short* blockmaplump; // offsets in blockmap are from here +extern short* blockmap; +extern int bmapwidth; +extern int bmapheight; // in mapblocks +extern fixed_t bmaporgx; +extern fixed_t bmaporgy; // origin of block map +extern mobj_t** blocklinks; // for thing chains + + +// +// P_INTER +// +extern int maxammo[NUMAMMO]; +extern int clipammo[NUMAMMO]; + +void +P_TouchSpecialThing +( mobj_t* special, + mobj_t* toucher ); + +void +P_DamageMobj +( mobj_t* target, + mobj_t* inflictor, + mobj_t* source, + int damage ); + + +// +// P_SPEC +// +#include "p_spec.h" + + +#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/strife/p_map.c b/games/NXDoom/src/strife/p_map.c new file mode 100644 index 00000000000..0aa2862f937 --- /dev/null +++ b/games/NXDoom/src/strife/p_map.c @@ -0,0 +1,1643 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard, Andrey Budko +// +// 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. +// +// DESCRIPTION: +// Movement, collision handling. +// Shooting and aiming. +// + +#include +#include + +#include "deh_misc.h" + +#include "m_bbox.h" +#include "m_random.h" +#include "i_system.h" + +#include "doomdef.h" +#include "m_argv.h" +#include "m_misc.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" +// Data. +#include "sounds.h" + +// Spechit overrun magic value. +// +// This is the value used by PrBoom-plus. I think the value below is +// actually better and works with more demos. However, I think +// it's better for the spechits emulation to be compatible with +// PrBoom-plus, at least so that the big spechits emulation list +// on Doomworld can also be used with Chocolate Doom. + +#define DEFAULT_SPECHIT_MAGIC 0x01C09C98 + +// This is from a post by myk on the Doomworld forums, +// outputted from entryway's spechit_magic generator for +// s205n546.lmp. The _exact_ value of this isn't too +// important; as long as it is in the right general +// range, it will usually work. Otherwise, we can use +// the generator (hacked doom2.exe) and provide it +// with -spechit. + +//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8 + + +fixed_t tmbbox[4]; +mobj_t* tmthing; +int tmflags; +fixed_t tmx; +fixed_t tmy; + + +// If "floatok" true, move would be ok +// if within "tmfloorz - tmceilingz". +boolean floatok; + +fixed_t tmfloorz; +fixed_t tmceilingz; +fixed_t tmdropoffz; + +// keep track of the line that lowers the ceiling, +// so missiles don't explode against sky hack walls +line_t* ceilingline; + +// haleyjd 20110203: [STRIFE] New global +// "blockingline" tracks the linedef responsible for blocking motion of an mobj +// for purposes of doing impact special activation by missiles. Suspiciously +// similar to the solution used by Raven in Heretic and Hexen. +line_t *blockingline; + +// keep track of special lines as they are hit, +// but don't process them until the move is proven valid + +// fraggle: I have increased the size of this buffer. In the original Doom, +// overrunning past this limit caused other bits of memory to be overwritten, +// affecting demo playback. However, in doing so, the limit was still +// exceeded. So we have to support more than 8 specials. +// +// We keep the original limit, to detect what variables in memory were +// overwritten (see SpechitOverrun()) + +#define MAXSPECIALCROSS 20 +#define MAXSPECIALCROSS_ORIGINAL 8 + +line_t* spechit[MAXSPECIALCROSS]; +int numspechit; + + + +// +// TELEPORT MOVE +// + +// +// PIT_StompThing +// +// [STRIFE] haleyjd 09/15/10: Modified so monsters can telestomp. +// +boolean PIT_StompThing (mobj_t* thing) +{ + fixed_t blockdist; + + if (!(thing->flags & MF_SHOOTABLE) ) + return true; + + blockdist = thing->radius + tmthing->radius; + + if ( abs(thing->x - tmx) >= blockdist + || abs(thing->y - tmy) >= blockdist ) + { + // didn't hit it + return true; + } + + // don't clip against self + if (thing == tmthing) + return true; + + // [STRIFE] monsters DO stomp things, on all levels + // Basically, one thing involved must be a player. + // Monsters can telefrag players, and players can telefrag monsters, but + // monsters cannot telefrag other monsters. + if (!(tmthing->player || thing->player)) + return false; + + P_DamageMobj (thing, tmthing, tmthing, 10000); + + return true; +} + + +// +// P_TeleportMove +// +// [STRIFE] +// haleyjd 09/15/10: Modified to set thing z position. +// +boolean P_TeleportMove(mobj_t* thing, fixed_t x, fixed_t y) +{ + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + + subsector_t* newsubsec; + + // kill anything occupying the position + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector (x,y); + ceilingline = NULL; + + // The base floor/ceiling is from the subsector + // that contains the point. + // Any contacted lines the step closer together + // will adjust them. + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + // stomp on any things contacted + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + for (bx=xl ; bx<=xh ; bx++) + for (by=yl ; by<=yh ; by++) + if (!P_BlockThingsIterator(bx,by,PIT_StompThing)) + return false; + + // the move is ok, + // so link the thing into its new position + P_UnsetThingPosition (thing); + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + thing->z = tmfloorz; // haleyjd 09/15/10: [STRIFE] Rogue added a z-set here + + P_SetThingPosition (thing); + + return true; +} + + +// +// MOVEMENT ITERATOR FUNCTIONS +// + +static void SpechitOverrun(line_t *ld); + +// +// PIT_CheckLine +// Adjusts tmfloorz and tmceilingz as lines are contacted +// +boolean PIT_CheckLine (line_t* ld) +{ + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] + || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] + || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) + return true; + + if (P_BoxOnLineSide (tmbbox, ld) != -1) + return true; + + // A line has been hit + + // The moving thing's destination position will cross + // the given line. + // If this should not be allowed, return false. + // If the line is special, keep track of it + // to process later if the move is proven ok. + // NOTE: specials are NOT sorted by order, + // so two special lines that are only 8 pixels apart + // could be crossed in either order. + + if (!ld->backsector) + return false; // one sided line + + if (!(tmthing->flags & MF_MISSILE) ) + { + // villsa [STRIFE] include jumpover flag + if ( ld->flags & ML_BLOCKING && + (!(ld->flags & ML_JUMPOVER) || tmfloorz + (32*FRACUNIT) > tmthing->z) ) + return false; // explicitly blocking everything + + // villsa [STRIFE] exclude floaters from blockmonster lines + if ( !tmthing->player && (ld->flags & ML_BLOCKMONSTERS) && + !(tmthing->flags & MF_FLOAT)) + return false; // block monsters only + + // villsa [STRIFE] + if ( ld->flags & ML_BLOCKFLOATERS && tmthing->flags & MF_FLOAT ) + return false; // block floaters only + } + + // set openrange, opentop, openbottom + P_LineOpening (ld); + + // adjust floor / ceiling heights + if (opentop < tmceilingz) + { + tmceilingz = opentop; + ceilingline = ld; + } + + if (openbottom > tmfloorz) + tmfloorz = openbottom; + + if (lowfloor < tmdropoffz) + tmdropoffz = lowfloor; + + // if contacted a special line, add it to the list + if (ld->special) + { + spechit[numspechit] = ld; + numspechit++; + + // fraggle: spechits overrun emulation code from prboom-plus + if (numspechit > MAXSPECIALCROSS_ORIGINAL) + { + SpechitOverrun(ld); + } + } + + return true; +} + +// +// PIT_CheckThing +// +boolean PIT_CheckThing (mobj_t* thing) +{ + fixed_t blockdist; + boolean solid; + int damage; + + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) )) + return true; + + // don't clip against self + if (thing == tmthing) + return true; + + blockdist = thing->radius + tmthing->radius; + + if ( abs(thing->x - tmx) >= blockdist + || abs(thing->y - tmy) >= blockdist ) + { + // didn't hit it + return true; + } + + // villsa [STRIFE] see if it went over / under + if(thing->height + thing->z < tmthing->z) + return true; // overhead + + // villsa [STRIFE] see if it went over / under + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + // villsa [STRIFE] unused + // check for skulls slamming into things (removed) + + // missiles can hit other things + if (tmthing->flags & MF_MISSILE) + { + // villsa [STRIFE] code to check over/under clipping moved to the beginning of the + // function, so that it applies to everything. + + // villsa [STRIFE] updated to strife version + if (tmthing->target && (tmthing->target->type == thing->type)) + { + // Don't hit same species as originator. + if (thing == tmthing->target) + return true; + + // sdh: Add deh_species_infighting here. We can override the + // "monsters of the same species cant hurt each other" behavior + // through dehacked patches + + if (thing->type != MT_PLAYER && !deh_species_infighting) + { + // Explode, but do no damage. + // Let players missile other players. + return false; + } + } + + if (!(thing->flags & MF_SHOOTABLE)) + { + // didn't do any damage + return !(thing->flags & MF_SOLID); + } + + // haleyjd 09/01/10: [STRIFE] Spectral check: + // Missiles cannot hit SPECTRAL entities unless the missiles are also + // flagged as SPECTRAL. + if (thing->flags & MF_SPECTRAL && !(tmthing->flags & MF_SPECTRAL)) + return true; // keep going + + // damage / explode + // haleyjd 09/01/10: [STRIFE] Modified missile damage formula + damage = ((P_Random()&3)+1)*tmthing->info->damage; + P_DamageMobj (thing, tmthing, tmthing->target, damage); + + // don't traverse any more + return false; + } + + // check for special pickup + if (thing->flags & MF_SPECIAL) + { + solid = (thing->flags & MF_SOLID) != 0; + if (tmthing->player) // villsa [STRIFE] no longer checks MF_PICKUP flag + { + // can remove thing + P_TouchSpecialThing (thing, tmthing); + } + return !solid; + } + + return !(thing->flags & MF_SOLID); +} + + +// +// MOVEMENT CLIPPING +// + +// +// P_CheckPosition +// This is purely informative, nothing is modified +// (except things picked up). +// +// in: +// a mobj_t (can be valid or invalid) +// a position to be checked +// (doesn't need to be related to the mobj_t->x,y) +// +// during: +// special things are touched if MF_PICKUP +// early out on solid lines? +// +// out: +// newsubsec +// floorz +// ceilingz +// tmdropoffz +// the lowest point contacted +// (monsters won't move to a dropoff) +// speciallines[] +// numspeciallines +// +// haleyjd 20110203: +// [STRIFE] Modified to clear blockingline in advance of P_BlockLinesIterator +// +boolean +P_CheckPosition +( mobj_t* thing, + fixed_t x, + fixed_t y ) +{ + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + subsector_t* newsubsec; + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = R_PointInSubsector (x,y); + + // [STRIFE] clear blockingline (see P_XYMovement, P_BlockLinesIterator) + blockingline = NULL; + ceilingline = NULL; + + // The base floor / ceiling is from the subsector + // that contains the point. + // Any contacted lines the step closer together + // will adjust them. + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + if ( tmflags & MF_NOCLIP ) + return true; + + // Check things first, possibly picking things up. + // The bounding box is extended by MAXRADIUS + // because mobj_ts are grouped into mapblocks + // based on their origin point, and can overlap + // into adjacent blocks by up to MAXRADIUS units. + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + for (bx=xl ; bx<=xh ; bx++) + for (by=yl ; by<=yh ; by++) + if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) + return false; + + // check lines + xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + + for (bx=xl ; bx<=xh ; bx++) + for (by=yl ; by<=yh ; by++) + if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) + return false; + + return true; +} + + +// +// P_TryMove +// Attempt to move to a new position, +// crossing special lines unless MF_TELEPORT is set. +// +boolean +P_TryMove +( mobj_t* thing, + fixed_t x, + fixed_t y ) +{ + fixed_t oldx; + fixed_t oldy; + int side; + int oldside; + line_t* ld; + + floatok = false; + if (!P_CheckPosition (thing, x, y)) + return false; // solid wall or thing + + if ( !(thing->flags & MF_NOCLIP) ) + { + if (tmceilingz - tmfloorz < thing->height) + return false; // doesn't fit + + floatok = true; + + // villsa [STRIFE] Removed MF_TELEPORT + if (tmceilingz - thing->z < thing->height) + return false; // mobj must lower itself to fit + + // villsa [STRIFE] non-robots are limited to 16 unit step height + if ((thing->flags & MF_NOBLOOD) == 0 && tmfloorz - thing->z > (16*FRACUNIT)) + return false; + if (tmfloorz - thing->z > 24*FRACUNIT) + return false; // too big a step up + + // villsa [STRIFE] special case for missiles + if((thing->flags & MF_MISSILE) && tmfloorz - thing->z > 4*FRACUNIT) + return false; + + // haleyjd 20110204 [STRIFE]: dropoff height changed 24 -> 32 + if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) + && tmfloorz - tmdropoffz > 32*FRACUNIT ) + return false; // don't stand over a dropoff + } + + // the move is ok, + // so link the thing into its new position + P_UnsetThingPosition (thing); + + oldx = thing->x; + oldy = thing->y; + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + P_SetThingPosition (thing); + + // if any special lines were hit, do the effect + if (! (thing->flags&MF_NOCLIP) ) // villsa [STRIFE] MF_TELEPORT not used + { + while (numspechit--) + { + // see if the line was crossed + ld = spechit[numspechit]; + side = P_PointOnLineSide (thing->x, thing->y, ld); + oldside = P_PointOnLineSide (oldx, oldy, ld); + if (side != oldside) + { + if (ld->special) + P_CrossSpecialLine (ld-lines, oldside, thing); + } + } + } + + return true; +} + +// +// P_CheckPositionZ +// +// villsa [STRIFE] new function +// Check colliding things on top of one another; ie., 3D Object Clipping +// +boolean P_CheckPositionZ(mobj_t* thing, fixed_t height) +{ + fixed_t x; + fixed_t y; + fixed_t z; + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + subsector_t* newsubsec; + + x = thing->x; + y = thing->y; + z = thing->z; + + thing->z = height; + + tmthing = thing; + tmflags = thing->flags; + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + ceilingline = 0; + newsubsec = thing->subsector; + + // The base floor / ceiling is from the subsector + // that contains the point. + // Any contacted lines the step closer together + // will adjust them. + + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + if(tmflags & MF_NOCLIP) + return true; + + // Check things first, possibly picking things up. + // The bounding box is extended by MAXRADIUS + // because mobj_ts are grouped into mapblocks + // based on their origin point, and can overlap + // into adjacent blocks by up to MAXRADIUS units. + + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + + for(bx = xl; bx <= xh; bx++) + { + for(by = yl; by <= yh; by++) + { + if(!P_BlockThingsIterator(bx, by, PIT_CheckThing)) + { + tmthing->z = z; + return false; + } + } + } + + return true; +} + + +// +// P_ThingHeightClip +// Takes a valid thing and adjusts the thing->floorz, +// thing->ceilingz, and possibly thing->z. +// This is called for all nearby monsters +// whenever a sector changes height. +// If the thing doesn't fit, +// the z will be set to the lowest value +// and false will be returned. +// +// [STRIFE] Verified unmodified +// +boolean P_ThingHeightClip (mobj_t* thing) +{ + boolean onfloor; + + onfloor = (thing->z == thing->floorz); + + P_CheckPosition (thing, thing->x, thing->y); + // what about stranding a monster partially off an edge? + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + + if (onfloor) + { + // walking monsters rise and fall with the floor + thing->z = thing->floorz; + } + else + { + // don't adjust a floating monster unless forced to + if (thing->z+thing->height > thing->ceilingz) + thing->z = thing->ceilingz - thing->height; + } + + if (thing->ceilingz - thing->floorz < thing->height) + return false; + + return true; +} + + + +// +// SLIDE MOVE +// Allows the player to slide along any angled walls. +// +fixed_t bestslidefrac; +fixed_t secondslidefrac; + +line_t* bestslideline; +line_t* secondslideline; + +mobj_t* slidemo; + +fixed_t tmxmove; +fixed_t tmymove; + + + +// +// P_HitSlideLine +// Adjusts the xmove / ymove +// so that the next move will slide along the wall. +// +// [STRIFE] Verified unmodified +// +void P_HitSlideLine (line_t* ld) +{ + int side; + + angle_t lineangle; + angle_t moveangle; + angle_t deltaangle; + + fixed_t movelen; + fixed_t newlen; + + + if (ld->slopetype == ST_HORIZONTAL) + { + tmymove = 0; + return; + } + + if (ld->slopetype == ST_VERTICAL) + { + tmxmove = 0; + return; + } + + side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); + + lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); + + if (side == 1) + lineangle += ANG180; + + moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); + deltaangle = moveangle-lineangle; + + if (deltaangle > ANG180) + deltaangle += ANG180; + // I_Error ("SlideLine: ang>ANG180"); + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = P_AproxDistance (tmxmove, tmymove); + newlen = FixedMul (movelen, finecosine[deltaangle]); + + tmxmove = FixedMul (newlen, finecosine[lineangle]); + tmymove = FixedMul (newlen, finesine[lineangle]); +} + + +// +// PTR_SlideTraverse +// +// [STRIFE] Modified for smaller step-up height +// +boolean PTR_SlideTraverse (intercept_t* in) +{ + line_t* li; + + if (!in->isaline) + I_Error ("PTR_SlideTraverse: not a line?"); + + li = in->d.line; + + if ( ! (li->flags & ML_TWOSIDED) ) + { + if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) + { + // don't hit the back side + return true; + } + goto isblocking; + } + + // set openrange, opentop, openbottom + P_LineOpening (li); + + if (openrange < slidemo->height) + goto isblocking; // doesn't fit + + if (opentop - slidemo->z < slidemo->height) + goto isblocking; // mobj is too high + + // villsa [STRIFE] change from 24 to 16 + if (openbottom - slidemo->z > 16*FRACUNIT ) + goto isblocking; // too big a step up + + // this line doesn't block movement + return true; + + // the line does block movement, + // see if it is closer than best so far +isblocking: + if (in->frac < bestslidefrac) + { + secondslidefrac = bestslidefrac; + secondslideline = bestslideline; + bestslidefrac = in->frac; + bestslideline = li; + } + + return false; // stop +} + + + +// +// P_SlideMove +// The momx / momy move is bad, so try to slide +// along a wall. +// Find the first line hit, move flush to it, +// and slide along it +// +// This is a kludgy mess. +// +// [STRIFE] Verified unmodified +// +void P_SlideMove (mobj_t* mo) +{ + fixed_t leadx; + fixed_t leady; + fixed_t trailx; + fixed_t traily; + fixed_t newx; + fixed_t newy; + int hitcount; + + slidemo = mo; + hitcount = 0; + +retry: + if (++hitcount == 3) + goto stairstep; // don't loop forever + + // trace along the three leading corners + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT+1; + + P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, + PT_ADDLINES, PTR_SlideTraverse ); + P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, + PT_ADDLINES, PTR_SlideTraverse ); + P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, + PT_ADDLINES, PTR_SlideTraverse ); + + // move up to the wall + if (bestslidefrac == FRACUNIT+1) + { + // the move most have hit the middle, so stairstep +stairstep: + if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) + P_TryMove (mo, mo->x + mo->momx, mo->y); + return; + } + + // fudge a bit to make sure it doesn't hit + bestslidefrac -= 0x800; + if (bestslidefrac > 0) + { + newx = FixedMul (mo->momx, bestslidefrac); + newy = FixedMul (mo->momy, bestslidefrac); + + if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) + goto stairstep; + } + + // Now continue along the wall. + // First calculate remainder. + bestslidefrac = FRACUNIT-(bestslidefrac+0x800); + + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; + + if (bestslidefrac <= 0) + return; + + tmxmove = FixedMul (mo->momx, bestslidefrac); + tmymove = FixedMul (mo->momy, bestslidefrac); + + P_HitSlideLine (bestslideline); // clip the moves + + mo->momx = tmxmove; + mo->momy = tmymove; + + if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove)) + { + goto retry; + } +} + + +// +// P_LineAttack +// +mobj_t* linetarget; // who got hit (or NULL) +mobj_t* shootthing; + +// Height if not aiming up or down +// ???: use slope for monsters? +fixed_t shootz; + +int la_damage; +fixed_t attackrange; + +fixed_t aimslope; + + +// +// PTR_AimTraverse +// Sets linetaget and aimslope when a target is aimed at. +// +// [STRIFE] Verified unmodified +// +boolean +PTR_AimTraverse (intercept_t* in) +{ + line_t* li; + mobj_t* th; + fixed_t slope; + fixed_t thingtopslope; + fixed_t thingbottomslope; + fixed_t dist; + + if (in->isaline) + { + li = in->d.line; + + if ( !(li->flags & ML_TWOSIDED) ) + return false; // stop + + // Crosses a two sided line. + // A two sided line will restrict + // the possible target ranges. + P_LineOpening (li); + + if (openbottom >= opentop) + return false; // stop + + dist = FixedMul (attackrange, in->frac); + + // Return false if there is no back sector. This should never + // be the case if the line is two-sided; however, some WADs + // (eg. ottawau.wad) use this as an "impassible glass" trick + // and rely on Vanilla Doom's (unintentional) support for this. + + if (li->backsector == NULL) + { + return false; + } + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv (openbottom - shootz , dist); + if (slope > bottomslope) + bottomslope = slope; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv (opentop - shootz , dist); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + + return true; // shot continues + } + + // shoot a thing + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + + if (!(th->flags&MF_SHOOTABLE)) + return true; // corpse or something + + // check angles to see if the thing can be aimed at + dist = FixedMul (attackrange, in->frac); + thingtopslope = FixedDiv (th->z+th->height - shootz , dist); + + if (thingtopslope < bottomslope) + return true; // shot over the thing + + thingbottomslope = FixedDiv (th->z - shootz, dist); + + if (thingbottomslope > topslope) + return true; // shot under the thing + + // this thing can be hit! + if (thingtopslope > topslope) + thingtopslope = topslope; + + if (thingbottomslope < bottomslope) + thingbottomslope = bottomslope; + + aimslope = (thingtopslope+thingbottomslope)/2; + linetarget = th; + + return false; // don't go any farther +} + + +// +// PTR_ShootTraverse +// +// [STRIFE] Changes for Spectres and Mauler puff/damage inflictor +// +boolean PTR_ShootTraverse (intercept_t* in) +{ + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t frac; + + line_t* li; + + mobj_t* th; + mobj_t* th2; // villsa [STRIFE] + + fixed_t slope; + fixed_t dist; + fixed_t thingtopslope; + fixed_t thingbottomslope; + + if (in->isaline) + { + li = in->d.line; + + if (li->special) + P_ShootSpecialLine (shootthing, li); + + if ( !(li->flags & ML_TWOSIDED) ) + goto hitline; + + // crosses a two sided line + P_LineOpening (li); + + dist = FixedMul (attackrange, in->frac); + + // Check if backsector is NULL. See comment in PTR_AimTraverse. + + if (li->backsector == NULL) + { + goto hitline; + } + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv (openbottom - shootz , dist); + if (slope > aimslope) + goto hitline; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv (opentop - shootz , dist); + if (slope < aimslope) + goto hitline; + } + + // shot continues + return true; + + + // hit line +hitline: + // position a bit closer + frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); + x = trace.x + FixedMul (trace.dx, frac); + y = trace.y + FixedMul (trace.dy, frac); + z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); + + if (li->frontsector->ceilingpic == skyflatnum) + { + // don't shoot the sky! + if (z > li->frontsector->ceilingheight) + return false; + + // it's a sky hack wall + if (li->backsector && li->backsector->ceilingpic == skyflatnum) + return false; + } + + // villsa [STRIFE] + if(la_damage > 0) + { + // villsa [STRIFE] Test against Mauler attack range + if(attackrange != 2112*FRACUNIT) + P_SpawnPuff(x, y, z); // Spawn bullet puffs. + else + P_SpawnMobj(x, y, z, MT_STRIFEPUFF3); + } + + // don't go any farther + return false; + } + + // shoot a thing + th = in->d.thing; + if (th == shootthing) + return true; // can't shoot self + + if (!(th->flags&MF_SHOOTABLE)) + return true; // corpse or something + + // haleyjd 09/18/10: [STRIFE] Corrected - not MVIS, but SPECTRAL. + if(th->flags & MF_SPECTRAL) + return true; // is a spectral entity + + // check angles to see if the thing can be aimed at + dist = FixedMul (attackrange, in->frac); + thingtopslope = FixedDiv (th->z+th->height - shootz , dist); + + if (thingtopslope < aimslope) + return true; // shot over the thing + + thingbottomslope = FixedDiv (th->z - shootz, dist); + + if (thingbottomslope > aimslope) + return true; // shot under the thing + + // hit thing + // position a bit closer + frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); + + x = trace.x + FixedMul (trace.dx, frac); + y = trace.y + FixedMul (trace.dy, frac); + z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); + + // villsa [STRIFE] Check for Mauler attack range + if(attackrange == 2112*FRACUNIT) + { + th2 = P_SpawnMobj(x, y, z, MT_STRIFEPUFF3); + th2->momz = -FRACUNIT; + P_DamageMobj(th, th2, shootthing, la_damage); + return false; + } + + // villsa [STRIFE] disabled check for damage + //if (la_damage) + P_DamageMobj (th, shootthing, shootthing, la_damage); + + // Spawn bullet puffs or blod spots, + // depending on target type. + if (in->d.thing->flags & MF_NOBLOOD) + P_SpawnSparkPuff(x, y, z); // villsa [STRIFE] call spark puff function instead + else + P_SpawnBlood (x,y,z, la_damage); + + // don't go any farther + return false; + +} + + +// +// P_AimLineAttack +// +// [STRIFE] Modified to support player->pitch +// +fixed_t +P_AimLineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance ) +{ + fixed_t x2; + fixed_t y2; + + t1 = P_SubstNullMobj(t1); + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + + x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; + y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; + shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; + + // can't shoot outside view angles + topslope = 100*FRACUNIT/160; + bottomslope = -100*FRACUNIT/160; + + attackrange = distance; + linetarget = NULL; + + P_PathTraverse ( t1->x, t1->y, + x2, y2, + PT_ADDLINES|PT_ADDTHINGS, + PTR_AimTraverse ); + + if (linetarget) + return aimslope; + else // villsa [STRIFE] checks for player pitch + { + if(t1->player) + return (t1->player->pitch << FRACBITS) / 160; + } + + return 0; +} + + +// +// P_LineAttack +// If damage == 0, it is just a test trace +// that will leave linetarget set. +// +// [STRIFE] Modified to check lines only if damage <= 0 (see P_RadiusAttack) +// +void +P_LineAttack +( mobj_t* t1, + angle_t angle, + fixed_t distance, + fixed_t slope, + int damage ) +{ + fixed_t x2; + fixed_t y2; + int traverseflags; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + la_damage = damage; + x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; + y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; + shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; + attackrange = distance; + aimslope = slope; + + // villsa [STRIFE] test lines only if damage is <= 0 + if(damage >= 1) + traverseflags = (PT_ADDLINES|PT_ADDTHINGS); + else + traverseflags = PT_ADDLINES; + + P_PathTraverse(t1->x, t1->y, + x2, y2, + traverseflags, + PTR_ShootTraverse); +} + + + +// +// USE LINES +// +// [STRIFE] Verified unmodified +// +mobj_t* usething; + +boolean PTR_UseTraverse (intercept_t* in) +{ + int side; + + if (!in->d.line->special) + { + P_LineOpening (in->d.line); + if (openrange <= 0) + { + S_StartSound (usething, sfx_noway); + + // can't use through a wall + return false; + } + // not a special line, but keep checking + return true ; + } + + side = 0; + if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) + side = 1; + + // return false; // don't use back side + + P_UseSpecialLine (usething, in->d.line, side); + + // can't use for than one special line in a row + return false; +} + + +// +// P_UseLines +// Looks for special lines in front of the player to activate. +// +// [STRIFE] Verified unmodified +// +void P_UseLines (player_t* player) +{ + int angle; + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + usething = player->mo; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; + y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; + + P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); +} + + +// +// RADIUS ATTACK +// +mobj_t* bombsource; +mobj_t* bombspot; +int bombdamage; + + +// +// PIT_RadiusAttack +// "bombsource" is the creature +// that caused the explosion at "bombspot". +// +// [STRIFE] Modified for Spectral and Inquisitor exclusions +// +boolean PIT_RadiusAttack (mobj_t* thing) +{ + fixed_t dx; + fixed_t dy; + fixed_t dist; + + if (!(thing->flags & MF_SHOOTABLE)) + return true; + + // haleyjd 10/04/10: Spectrals are not damaged by blast radii + if(thing->flags & MF_SPECTRAL) + return true; + + // Boss spider and cyborg + // take no damage from concussion. + // villsa [STRIFE] unused + // - haleyjd: INQUISITOR + + if(thing->type == MT_INQUISITOR) + return true; + + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + + dist = dx>dy ? dx : dy; + dist = (dist - thing->radius) >> FRACBITS; + + if (dist < 0) + dist = 0; + + if (dist >= bombdamage) + return true; // out of range + + if ( P_CheckSight (thing, bombspot) ) + { + // must be in direct path + P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist); + } + + return true; +} + + +// +// P_RadiusAttack +// Source is the creature that caused the explosion at spot. +// +// [STRIFE] Modified to emit "test" tracers which can shatter glass screens +// and windows. +// +void +P_RadiusAttack +( mobj_t* spot, + mobj_t* source, + int damage ) +{ + int x; + int y; + + int xl; + int xh; + int yl; + int yh; + + fixed_t dist; + + dist = (damage+MAXRADIUS)<y + dist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; + bombspot = spot; + bombsource = source; + bombdamage = damage; + + for (y=yl ; y<=yh ; y++) + for (x=xl ; x<=xh ; x++) + P_BlockThingsIterator (x, y, PIT_RadiusAttack ); + + // villsa [STRIFE] Send out 0 damage tracers to shatter nearby glass. + spot->z += 32*FRACUNIT; + P_LineAttack(spot, 0, dist, 1, 0); + P_LineAttack(spot, ANG90, dist, 1, 0); + P_LineAttack(spot, ANG180, dist, 1, 0); + P_LineAttack(spot, ANG270, dist, 1, 0); + spot->z -= 32*FRACUNIT; +} + + + +// +// SECTOR HEIGHT CHANGING +// After modifying a sectors floor or ceiling height, +// call this routine to adjust the positions +// of all things that touch the sector. +// +// If anything doesn't fit anymore, true will be returned. +// If crunch is true, they will take damage +// as they are being crushed. +// If Crunch is false, you should set the sector height back +// the way it was and call P_ChangeSector again +// to undo the changes. +// +boolean crushchange; +boolean nofit; + + +// +// PIT_ChangeSector +// +// [STRIFE] Changes to crushing behavior +// +boolean PIT_ChangeSector (mobj_t* thing) +{ + mobj_t* mo; + + if (P_ThingHeightClip (thing)) + { + // keep checking + return true; + } + + // crunch bodies to giblets + if (thing->health <= 0) + { + // villsa [STRIFE] do something with the player + if(thing->player && thing->subsector->sector->specialdata) + { + nofit = true; + return false; + } + //P_SetMobjState (thing, S_GIBS); // villsa [STRIFE] unused + + A_BodyParts(thing); // villsa [STRIFE] spit out meat/junk stuff + thing->flags &= ~MF_SOLID; + thing->height = 0; + thing->radius = 0; + + // keep checking + return true; + } + + // crunch dropped items + if (thing->flags & MF_DROPPED) + { + P_RemoveMobj (thing); + + // keep checking + return true; + } + + if (! (thing->flags & MF_SHOOTABLE) ) + { + // assume it is bloody gibs or something + return true; + } + + nofit = true; + + if (crushchange && !(leveltime&3) ) + { + int t; + S_StartSound(thing, sfx_pcrush); // villsa [STRIFE] + P_DamageMobj(thing,NULL,NULL,10); + + // spray blood in a random direction + mo = P_SpawnMobj (thing->x, + thing->y, + thing->z + thing->height/2, MT_BLOOD_DEATH); + + t = P_Random(); + mo->momx = (t - P_Random ()) << 12; + t = P_Random(); + mo->momy = (t - P_Random ()) << 12; + } + + // keep checking (crush other things) + return true; +} + + + +// +// P_ChangeSector +// +// [STRIFE] Verified unmodified +// +boolean +P_ChangeSector +( sector_t* sector, + boolean crunch ) +{ + int x; + int y; + + nofit = false; + crushchange = crunch; + + // re-check heights for all things near the moving sector + for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) + for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) + P_BlockThingsIterator (x, y, PIT_ChangeSector); + + return nofit; +} + +// Code to emulate the behavior of Vanilla Doom when encountering an overrun +// of the spechit array. This is by Andrey Budko (e6y) and comes from his +// PrBoom plus port. A big thanks to Andrey for this. + +static void SpechitOverrun(line_t *ld) +{ + static unsigned int baseaddr = 0; + unsigned int addr; + + if (baseaddr == 0) + { + int p; + + // This is the first time we have had an overrun. Work out + // what base address we are going to use. + // Allow a spechit value to be specified on the command line. + + //! + // @category compat + // @arg + // + // Use the specified magic value when emulating spechit overruns. + // + + p = M_CheckParmWithArgs("-spechit", 1); + + if (p > 0) + { + M_StrToInt(myargv[p+1], (int *) &baseaddr); + } + else + { + baseaddr = DEFAULT_SPECHIT_MAGIC; + } + } + + // Calculate address used in doom2.exe + + addr = baseaddr + (ld - lines) * 0x3E; + + switch(numspechit) + { + case 9: + case 10: + case 11: + case 12: + tmbbox[numspechit-9] = addr; + break; + case 13: + nofit = addr; // haleyjd 20110204: nofit/crushchange are in opposite + break; // order in the Strife binary. + case 14: + crushchange = addr; + break; + default: + fprintf(stderr, "SpechitOverrun: Warning: unable to emulate" + "an overrun where numspechit=%i\n", + numspechit); + break; + } +} + diff --git a/games/NXDoom/src/strife/p_maputl.c b/games/NXDoom/src/strife/p_maputl.c new file mode 100644 index 00000000000..78ae34712fd --- /dev/null +++ b/games/NXDoom/src/strife/p_maputl.c @@ -0,0 +1,1056 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// Copyright(C) 2005, 2006 Andrey Budko +// +// 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. +// +// DESCRIPTION: +// Movement/collision utility functions, +// as used by function in p_map.c. +// BLOCKMAP Iterator functions, +// and some PIT_* functions to use for iteration. +// + + + +#include + + +#include "m_bbox.h" +#include "m_misc.h" + +#include "doomdef.h" +#include "doomstat.h" +#include "p_local.h" + + +// State. +#include "r_state.h" + +// +// P_AproxDistance +// Gives an estimation of distance (not exact) +// +// [STRIFE] Verified unmodified +// +fixed_t +P_AproxDistance +( fixed_t dx, + fixed_t dy ) +{ + dx = abs(dx); + dy = abs(dy); + if (dx < dy) + return dx+dy-(dx>>1); + return dx+dy-(dy>>1); +} + + +// +// P_PointOnLineSide +// Returns 0 or 1 +// +// [STRIFE] Verified unmodified +// +int +P_PointOnLineSide +( fixed_t x, + fixed_t y, + line_t* line ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!line->dx) + { + if (x <= line->v1->x) + return line->dy > 0; + + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->v1->y) + return line->dx < 0; + + return line->dx > 0; + } + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = FixedMul ( line->dy>>FRACBITS , dx ); + right = FixedMul ( dy , line->dx>>FRACBITS ); + + if (right < left) + return 0; // front side + return 1; // back side +} + + + +// +// P_BoxOnLineSide +// Considers the line to be infinite +// Returns side 0 or 1, -1 if box crosses the line. +// +// [STRIFE] Verified unmodified +// +int +P_BoxOnLineSide +( fixed_t* tmbox, + line_t* ld ) +{ + int p1 = 0; + int p2 = 0; + + switch (ld->slopetype) + { + case ST_HORIZONTAL: + p1 = tmbox[BOXTOP] > ld->v1->y; + p2 = tmbox[BOXBOTTOM] > ld->v1->y; + if (ld->dx < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + + case ST_VERTICAL: + p1 = tmbox[BOXRIGHT] < ld->v1->x; + p2 = tmbox[BOXLEFT] < ld->v1->x; + if (ld->dy < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + + case ST_POSITIVE: + p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); + break; + + case ST_NEGATIVE: + p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); + p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); + break; + } + + if (p1 == p2) + return p1; + return -1; +} + + +// +// P_PointOnDivlineSide +// Returns 0 or 1. +// +// [STRIFE] Verified unmodified +// +int +P_PointOnDivlineSide +( fixed_t x, + fixed_t y, + divline_t* line ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!line->dx) + { + if (x <= line->x) + return line->dy > 0; + + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->y) + return line->dx < 0; + + return line->dx > 0; + } + + dx = (x - line->x); + dy = (y - line->y); + + // try to quickly decide by looking at sign bits + if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) + { + if ( (line->dy ^ dx) & 0x80000000 ) + return 1; // (left is negative) + return 0; + } + + left = FixedMul ( line->dy>>8, dx>>8 ); + right = FixedMul ( dy>>8 , line->dx>>8 ); + + if (right < left) + return 0; // front side + return 1; // back side +} + + + +// +// P_MakeDivline +// +void +P_MakeDivline +( line_t* li, + divline_t* dl ) +{ + dl->x = li->v1->x; + dl->y = li->v1->y; + dl->dx = li->dx; + dl->dy = li->dy; +} + + + +// +// P_InterceptVector +// Returns the fractional intercept point +// along the first divline. +// This is only called by the addthings +// and addlines traversers. +// +// [STRIFE] Verified unmodified +// +fixed_t +P_InterceptVector +( divline_t* v2, + divline_t* v1 ) +{ +#if 1 + fixed_t frac; + fixed_t num; + fixed_t den; + + den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); + + if (den == 0) + return 0; + // I_Error ("P_InterceptVector: parallel"); + + num = + FixedMul ( (v1->x - v2->x)>>8 ,v1->dy ) + +FixedMul ( (v2->y - v1->y)>>8, v1->dx ); + + frac = FixedDiv (num , den); + + return frac; +#else // UNUSED, float debug. + float frac; + float num; + float den; + float v1x; + float v1y; + float v1dx; + float v1dy; + float v2x; + float v2y; + float v2dx; + float v2dy; + + v1x = (float)v1->x/FRACUNIT; + v1y = (float)v1->y/FRACUNIT; + v1dx = (float)v1->dx/FRACUNIT; + v1dy = (float)v1->dy/FRACUNIT; + v2x = (float)v2->x/FRACUNIT; + v2y = (float)v2->y/FRACUNIT; + v2dx = (float)v2->dx/FRACUNIT; + v2dy = (float)v2->dy/FRACUNIT; + + den = v1dy*v2dx - v1dx*v2dy; + + if (den == 0) + return 0; // parallel + + num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; + frac = num / den; + + return frac*FRACUNIT; +#endif +} + + +// +// P_LineOpening +// Sets opentop and openbottom to the window +// through a two sided line. +// OPTIMIZE: keep this precalculated +// +// [STRIFE] Verified unmodified +// +fixed_t opentop; +fixed_t openbottom; +fixed_t openrange; +fixed_t lowfloor; + + +void P_LineOpening (line_t* linedef) +{ + sector_t* front; + sector_t* back; + + if (linedef->sidenum[1] == -1) + { + // single sided line + openrange = 0; + return; + } + + front = linedef->frontsector; + back = linedef->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; + } + + openrange = opentop - openbottom; +} + + +// +// THING POSITION SETTING +// + + +// +// P_UnsetThingPosition +// Unlinks a thing from block map and sectors. +// On each position change, BLOCKMAP and other +// lookups maintaining lists ot things inside +// these structures need to be updated. +// +// [STRIFE] Verified unmodified +// +void P_UnsetThingPosition (mobj_t* thing) +{ + int blockx; + int blocky; + + if ( ! (thing->flags & MF_NOSECTOR) ) + { + // inert things don't need to be in blockmap? + // unlink from subsector + if (thing->snext) + thing->snext->sprev = thing->sprev; + + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + } + + if ( ! (thing->flags & MF_NOBLOCKMAP) ) + { + // inert things don't need to be in blockmap + // unlink from block map + if (thing->bnext) + thing->bnext->bprev = thing->bprev; + + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; + + if (blockx>=0 && blockx < bmapwidth + && blocky>=0 && blocky bnext; + } + } + } +} + + +// +// P_SetThingPosition +// Links a thing into both a block and a subsector +// based on it's x y. +// Sets thing->subsector properly +// +// [STRIFE] Verified unmodified +// +void +P_SetThingPosition (mobj_t* thing) +{ + subsector_t* ss; + sector_t* sec; + int blockx; + int blocky; + mobj_t** link; + + + // link into subsector + ss = R_PointInSubsector (thing->x,thing->y); + thing->subsector = ss; + + if ( ! (thing->flags & MF_NOSECTOR) ) + { + // invisible things don't go into the sector links + sec = ss->sector; + + thing->sprev = NULL; + thing->snext = sec->thinglist; + + if (sec->thinglist) + sec->thinglist->sprev = thing; + + sec->thinglist = thing; + } + + + // link into blockmap + if ( ! (thing->flags & MF_NOBLOCKMAP) ) + { + // inert things don't need to be in blockmap + blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; + + if (blockx>=0 + && blockx < bmapwidth + && blocky>=0 + && blocky < bmapheight) + { + link = &blocklinks[blocky*bmapwidth+blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) + (*link)->bprev = thing; + + *link = thing; + } + else + { + // thing is off the map + thing->bnext = thing->bprev = NULL; + } + } +} + + + +// +// BLOCK MAP ITERATORS +// For each line/thing in the given mapblock, +// call the passed PIT_* function. +// If the function returns false, +// exit with false without checking anything else. +// + + +// +// P_BlockLinesIterator +// The validcount flags are used to avoid checking lines +// that are marked in multiple mapblocks, +// so increment validcount before the first call +// to P_BlockLinesIterator, then make one or more calls +// to it. +// +// haleyjd 20110203: +// [STRIFE] Modified to track blockingline +// +boolean +P_BlockLinesIterator +( int x, + int y, + boolean(*func)(line_t*) ) +{ + int offset; + short* list; + line_t* ld; + + if (x<0 + || y<0 + || x>=bmapwidth + || y>=bmapheight) + { + return true; + } + + offset = y*bmapwidth+x; + + offset = *(blockmap+offset); + + for ( list = blockmaplump+offset ; *list != -1 ; list++) + { + ld = &lines[*list]; + + // [STRIFE]: set blockingline (see P_XYMovement @ p_mobj.c) + blockingline = ld; + + if (ld->validcount == validcount) + continue; // line has already been checked + + ld->validcount = validcount; + + if ( !func(ld) ) + return false; + } + return true; // everything was checked +} + + +// +// P_BlockThingsIterator +// +// [STRIFE] Verified unmodified +// +boolean +P_BlockThingsIterator +( int x, + int y, + boolean(*func)(mobj_t*) ) +{ + mobj_t* mobj; + + if ( x<0 + || y<0 + || x>=bmapwidth + || y>=bmapheight) + { + return true; + } + + LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); + + for (mobj = blocklinks[y*bmapwidth+x] ; + mobj ; + mobj = mobj->bnext) + { + if (!func( mobj ) ) + return false; + } + return true; +} + + + +// +// INTERCEPT ROUTINES +// +intercept_t intercepts[MAXINTERCEPTS]; +intercept_t* intercept_p; + +divline_t trace; +boolean earlyout; +int ptflags; + +//static void InterceptsOverrun(int num_intercepts, intercept_t *intercept); + +// +// PIT_AddLineIntercepts. +// Looks for lines in the given block +// that intercept the given trace +// to add to the intercepts list. +// +// A line is crossed if its endpoints +// are on opposite sides of the trace. +// Returns true if earlyout and a solid line hit. +// +// haleyjd 20110204 [STRIFE]: Added Rogue's fix for intercepts overflows +// +boolean +PIT_AddLineIntercepts (line_t* ld) +{ + int s1; + int s2; + fixed_t frac; + divline_t dl; + + // avoid precision problems with two routines + if ( trace.dx > FRACUNIT*16 + || trace.dy > FRACUNIT*16 + || trace.dx < -FRACUNIT*16 + || trace.dy < -FRACUNIT*16) + { + s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); + } + else + { + s1 = P_PointOnLineSide (trace.x, trace.y, ld); + s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); + } + + if (s1 == s2) + return true; // line isn't crossed + + // hit the line + P_MakeDivline (ld, &dl); + frac = P_InterceptVector (&trace, &dl); + + if (frac < 0) + return true; // behind source + + // try to early out the check + if (earlyout + && frac < FRACUNIT + && !ld->backsector) + { + return false; // stop checking + } + + + intercept_p->frac = frac; + intercept_p->isaline = true; + intercept_p->d.line = ld; + intercept_p++; + + // haleyjd 20110204 [STRIFE] + // Evidently Rogue had trouble with intercepts overflows during + // development, as they added this check here which will stop adding + // intercepts if the array would be overflown. + if(intercept_p <= &intercepts[MAXINTERCEPTS_ORIGINAL-2]) + return true; // continue + else + return false; + + // [STRIFE] Not needed? + //InterceptsOverrun(intercept_p - intercepts, intercept_p); +} + + + +// +// PIT_AddThingIntercepts +// +boolean PIT_AddThingIntercepts (mobj_t* thing) +{ + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + int s1; + int s2; + + boolean tracepositive; + + divline_t dl; + + fixed_t frac; + + tracepositive = (trace.dx ^ trace.dy)>0; + + // check a corner to corner crossection for hit + if (tracepositive) + { + x1 = thing->x - thing->radius; + y1 = thing->y + thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y - thing->radius; + } + else + { + x1 = thing->x - thing->radius; + y1 = thing->y - thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y + thing->radius; + } + + s1 = P_PointOnDivlineSide (x1, y1, &trace); + s2 = P_PointOnDivlineSide (x2, y2, &trace); + + if (s1 == s2) + return true; // line isn't crossed + + dl.x = x1; + dl.y = y1; + dl.dx = x2-x1; + dl.dy = y2-y1; + + frac = P_InterceptVector (&trace, &dl); + + if (frac < 0) + return true; // behind source + + intercept_p->frac = frac; + intercept_p->isaline = false; + intercept_p->d.thing = thing; + + intercept_p++; + + // haleyjd 20110204 [STRIFE]: As above, protection against intercepts + // overflows, courtesy of Rogue Software. + if(intercept_p <= &intercepts[MAXINTERCEPTS_ORIGINAL-2]) + return true; // keep going + else + return false; + + // haleyjd [STRIFE]: Not needed? + //InterceptsOverrun(intercept_p - intercepts, intercept_p); +} + + +// +// P_TraverseIntercepts +// Returns true if the traverser function returns true +// for all lines. +// +// [STRIFE] Verified unmodified. +// +boolean +P_TraverseIntercepts +( traverser_t func, + fixed_t maxfrac ) +{ + int count; + fixed_t dist; + intercept_t* scan; + intercept_t* in; + + count = intercept_p - intercepts; + + in = 0; // shut up compiler warning + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts ; scanfrac < dist) + { + dist = scan->frac; + in = scan; + } + } + + if (dist > maxfrac) + return true; // checked everything in range + +#if 0 // UNUSED + { + // don't check these yet, there may be others inserted + in = scan = intercepts; + for ( scan = intercepts ; scanfrac > maxfrac) + *in++ = *scan; + intercept_p = in; + return false; + } +#endif + + if ( !func (in) ) + return false; // don't bother going farther + + in->frac = INT_MAX; + } + + return true; // everything was traversed +} + + +#if 0 +// Intercepts Overrun emulation, from PrBoom-plus. +// Thanks to Andrey Budko (entryway) for researching this and his +// implementation of Intercepts Overrun emulation in PrBoom-plus +// which this is based on. + +typedef struct +{ + int len; + void *addr; + boolean int16_array; +} intercepts_overrun_t; + +// Intercepts memory table. This is where various variables are located +// in memory in Vanilla Doom. When the intercepts table overflows, we +// need to write to them. +// +// Almost all of the values to overwrite are 32-bit integers, except for +// playerstarts, which is effectively an array of 16-bit integers and +// must be treated differently. + +// haleyjd 20110204: NB: This array has *not* been updated for Strife, +// because Strife has protection against intercepts overflows. The memory +// layout of the 1.2 and 1.31 EXEs is radically different with respect +// to this area of the BSS segment, so it would have to be redone entirely +// if it were needed. + +static intercepts_overrun_t intercepts_overrun[] = +{ + {4, NULL, false}, + {4, NULL, /* &earlyout, */ false}, + {4, NULL, /* &intercept_p, */ false}, + {4, &lowfloor, false}, + {4, &openbottom, false}, + {4, &opentop, false}, + {4, &openrange, false}, + {4, NULL, false}, + {120, NULL, /* &activeplats, */ false}, + {8, NULL, false}, + {4, &bulletslope, false}, + {4, NULL, /* &swingx, */ false}, + {4, NULL, /* &swingy, */ false}, + {4, NULL, false}, + {40, &playerstarts, true}, + {4, NULL, /* &blocklinks, */ false}, + {4, &bmapwidth, false}, + {4, NULL, /* &blockmap, */ false}, + {4, &bmaporgx, false}, + {4, &bmaporgy, false}, + {4, NULL, /* &blockmaplump, */ false}, + {4, &bmapheight, false}, + {0, NULL, false}, +}; + +// Overwrite a specific memory location with a value. + +static void InterceptsMemoryOverrun(int location, int value) +{ + int i, offset; + int index; + void *addr; + + i = 0; + offset = 0; + + // Search down the array until we find the right entry + + while (intercepts_overrun[i].len != 0) + { + if (offset + intercepts_overrun[i].len > location) + { + addr = intercepts_overrun[i].addr; + + // Write the value to the memory location. + // 16-bit and 32-bit values are written differently. + + if (addr != NULL) + { + if (intercepts_overrun[i].int16_array) + { + index = (location - offset) / 2; + ((short *) addr)[index] = value & 0xffff; + ((short *) addr)[index + 1] = (value >> 16) & 0xffff; + } + else + { + index = (location - offset) / 4; + ((int *) addr)[index] = value; + } + } + + break; + } + + offset += intercepts_overrun[i].len; + ++i; + } +} + +// Emulate overruns of the intercepts[] array. + +static void InterceptsOverrun(int num_intercepts, intercept_t *intercept) +{ + int location; + + if (num_intercepts <= MAXINTERCEPTS_ORIGINAL) + { + // No overrun + + return; + } + + location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12; + + // Overwrite memory that is overwritten in Vanilla Doom, using + // the values from the intercept structure. + // + // Note: the ->d.{thing,line} member should really have its + // address translated into the correct address value for + // Vanilla Doom. + + InterceptsMemoryOverrun(location, intercept->frac); + InterceptsMemoryOverrun(location + 4, intercept->isaline); + InterceptsMemoryOverrun(location + 8, (int) intercept->d.thing); +} +#endif + + +// +// P_PathTraverse +// Traces a line from x1,y1 to x2,y2, +// calling the traverser function for each. +// Returns true if the traverser function returns true +// for all lines. +// +// [STRIFE] Verified unmodified +// +boolean +P_PathTraverse +( fixed_t x1, + fixed_t y1, + fixed_t x2, + fixed_t y2, + int flags, + boolean (*trav) (intercept_t *)) +{ + fixed_t xt1; + fixed_t yt1; + fixed_t xt2; + fixed_t yt2; + + fixed_t xstep; + fixed_t ystep; + + fixed_t partial; + + fixed_t xintercept; + fixed_t yintercept; + + int mapx; + int mapy; + + int mapxstep; + int mapystep; + + int count; + + earlyout = (flags & PT_EARLYOUT) != 0; + + validcount++; + intercept_p = intercepts; + + if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) + x1 += FRACUNIT; // don't side exactly on a line + + if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) + y1 += FRACUNIT; // don't side exactly on a line + + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1>>MAPBLOCKSHIFT; + yt1 = y1>>MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2>>MAPBLOCKSHIFT; + yt2 = y2>>MAPBLOCKSHIFT; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); + ystep = FixedDiv (y2-y1,abs(x2-x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); + ystep = FixedDiv (y2-y1,abs(x2-x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256*FRACUNIT; + } + + yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); + + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); + xstep = FixedDiv (x2-x1,abs(y2-y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); + xstep = FixedDiv (x2-x1,abs(y2-y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256*FRACUNIT; + } + xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); + + // Step through map blocks. + // Count is present to prevent a round off error + // from skipping the break. + mapx = xt1; + mapy = yt1; + + for (count = 0 ; count < 64 ; count++) + { + if (flags & PT_ADDLINES) + { + if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) + return false; // early out + } + + if (flags & PT_ADDTHINGS) + { + if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) + return false; // early out + } + + if (mapx == xt2 + && mapy == yt2) + { + break; + } + + if ( (yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ( (xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + + } + // go through the sorted list + return P_TraverseIntercepts ( trav, FRACUNIT ); +} + + + diff --git a/games/NXDoom/src/strife/p_mobj.c b/games/NXDoom/src/strife/p_mobj.c new file mode 100644 index 00000000000..038c3edbe80 --- /dev/null +++ b/games/NXDoom/src/strife/p_mobj.c @@ -0,0 +1,1360 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Moving object handling. Spawn functions. +// + +#include + +#include "i_system.h" +#include "z_zone.h" +#include "m_random.h" +#include "doomdef.h" +#include "p_local.h" +#include "sounds.h" +#include "st_stuff.h" +#include "hu_stuff.h" +#include "s_sound.h" +#include "doomstat.h" +#include "d_main.h" // villsa [STRIFE] + + +void G_PlayerReborn (int player); +void P_SpawnMapThing (mapthing_t* mthing); + + +// +// P_SetMobjState +// Returns true if the mobj is still present. +// +// [STRIFE] Verified unmodified +// +int test; + +boolean +P_SetMobjState +( mobj_t* mobj, + statenum_t state ) +{ + state_t* st; + + do + { + if (state == S_NULL) + { + mobj->state = (state_t *) S_NULL; + P_RemoveMobj (mobj); + return false; + } + + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // Modified handling. + // Call action functions when the state is set + if (st->action.acp1) + st->action.acp1(mobj); + + state = st->nextstate; + } while (!mobj->tics); + + return true; +} + + +// +// P_ExplodeMissile +// +// [STRIFE] Removed randomization of deathstate tics +// +void P_ExplodeMissile (mobj_t* mo) +{ + mo->momx = mo->momy = mo->momz = 0; + + P_SetMobjState (mo, mobjinfo[mo->type].deathstate); + + // villsa [STRIFE] removed tics randomization + + mo->flags &= ~MF_MISSILE; + + if (mo->info->deathsound) + S_StartSound (mo, mo->info->deathsound); +} + + +// +// P_XYMovement +// +// [STRIFE] Modifications for: +// * No SKULLFLY logic (replaced by BOUNCE flag) +// * Missiles can activate G1/GR line types +// * Player walking logic +// * Air friction for players +// +#define STOPSPEED 0x1000 +#define FRICTION 0xe800 +#define AIRFRICTION 0xfff0 // [STRIFE] + +void P_XYMovement (mobj_t* mo) +{ + fixed_t ptryx; + fixed_t ptryy; + player_t* player; + fixed_t xmove; + fixed_t ymove; + + // villsa [STRIFE] unused + /* + if (!mo->momx && !mo->momy) + { + if (mo->flags & MF_SKULLFLY) + { + // the skull slammed into something + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + + P_SetMobjState (mo, mo->info->spawnstate); + } + return; + } + */ + + player = mo->player; + + if (mo->momx > MAXMOVE) + mo->momx = MAXMOVE; + else if (mo->momx < -MAXMOVE) + mo->momx = -MAXMOVE; + + if (mo->momy > MAXMOVE) + mo->momy = MAXMOVE; + else if (mo->momy < -MAXMOVE) + mo->momy = -MAXMOVE; + + xmove = mo->momx; + ymove = mo->momy; + + do + { + if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) + { + ptryx = mo->x + xmove/2; + ptryy = mo->y + ymove/2; + xmove >>= 1; + ymove >>= 1; + } + else + { + ptryx = mo->x + xmove; + ptryy = mo->y + ymove; + xmove = ymove = 0; + } + + if (!P_TryMove (mo, ptryx, ptryy)) + { + // blocked move + if (mo->player) + { // try to slide along it + P_SlideMove (mo); + } + // villsa [STRIFE] check for bouncy missiles + else if(mo->flags & MF_BOUNCE) + { + mo->momx >>= 3; + mo->momy >>= 3; + + if (P_TryMove(mo, mo->x - xmove, ymove + mo->y)) + mo->momy = -mo->momy; + else + mo->momx = -mo->momx; + + xmove = 0; + ymove = 0; + } + else if (mo->flags & MF_MISSILE) + { + // haley 20110203: [STRIFE] + // This modification allows missiles to activate shoot specials. + // *** BUG: In vanilla Strife the second condition is simply + // if(numspechit). However, numspechit can be negative, and + // when it is, this accesses spechit[-2]. This always causes the + // DOS exe to read from NULL, and the 'special' value there (in + // DOS 6.22 at least) is 0x70, which does nothing. + if(blockingline && blockingline->special) + P_ShootSpecialLine(mo, blockingline); + if(numspechit > 0) + P_ShootSpecialLine(mo, spechit[numspechit-1]); + + // explode a missile + if (ceilingline && + ceilingline->backsector && + ceilingline->backsector->ceilingpic == skyflatnum) + { + // Hack to prevent missiles exploding + // against the sky. + // Does not handle sky floors. + P_RemoveMobj (mo); + return; + } + P_ExplodeMissile (mo); + } + else + mo->momx = mo->momy = 0; + } + } while (xmove || ymove); + + // slow down + if (player && player->cheats & CF_NOMOMENTUM) + { + // debug option for no sliding at all + mo->momx = mo->momy = 0; + return; + } + + // villsa [STRIFE] replace skullfly flag with MF_BOUNCE + if (mo->flags & (MF_MISSILE | MF_BOUNCE) ) + return; // no friction for missiles ever + + // haleyjd 20110224: [STRIFE] players experience friction even in the air, + // although less than when on the ground. With this fix, the 1.2-and-up + // IWAD demo is now in sync! + if (mo->z > mo->floorz) + { + if(player) + { + mo->momx = FixedMul (mo->momx, AIRFRICTION); + mo->momy = FixedMul (mo->momy, AIRFRICTION); + } + return; // no friction when airborne + } + + if (mo->flags & MF_CORPSE) + { + // do not stop sliding + // if halfway off a step with some momentum + if (mo->momx > FRACUNIT/4 + || mo->momx < -FRACUNIT/4 + || mo->momy > FRACUNIT/4 + || mo->momy < -FRACUNIT/4) + { + if (mo->floorz != mo->subsector->sector->floorheight) + return; + } + } + + if (mo->momx > -STOPSPEED + && mo->momx < STOPSPEED + && mo->momy > -STOPSPEED + && mo->momy < STOPSPEED + && (!player + || (player->cmd.forwardmove == 0 + && player->cmd.sidemove == 0 ) ) ) + { + // if in a walking frame, stop moving + // villsa [STRIFE]: different player state (haleyjd - verified 20110202) + if ( player&&(unsigned)((player->mo->state - states) - S_PLAY_01) < 4) + P_SetMobjState (player->mo, S_PLAY_00); + + mo->momx = 0; + mo->momy = 0; + } + else + { + mo->momx = FixedMul (mo->momx, FRICTION); + mo->momy = FixedMul (mo->momy, FRICTION); + } +} + +// +// P_ZMovement +// +// [STRIFE] Modifications for: +// * 3D Object Clipping +// * Different momz handling +// * No SKULLFLY logic (replaced with BOUNCE) +// * Missiles don't hit sky flats +// +void P_ZMovement (mobj_t* mo) +{ + fixed_t dist; + fixed_t delta; + + // check for smooth step up + if (mo->player && mo->z < mo->floorz) + { + mo->player->viewheight -= mo->floorz-mo->z; + + mo->player->deltaviewheight + = (VIEWHEIGHT - mo->player->viewheight)>>3; + } + + // adjust height + // villsa [STRIFE] check for things standing on top of other things + if(!P_CheckPositionZ(mo, mo->z + mo->momz)) + { + if(mo->momz >= 0) + mo->ceilingz = mo->height + mo->z; + else + mo->floorz = mo->z; + } + + //mo->z += mo->momz; // villsa [STRIFE] unused + + if ( mo->flags & MF_FLOAT + && mo->target) + { + // float down towards target if too close + if ( /*!(mo->flags & MF_SKULLFLY) // villsa [STRIFE] unused + &&*/ !(mo->flags & MF_INFLOAT) ) + { + dist = P_AproxDistance (mo->x - mo->target->x, + mo->y - mo->target->y); + + delta =(mo->target->z + (mo->height>>1)) - mo->z; + + if (delta<0 && dist < -(delta*3) ) + mo->z -= FLOATSPEED; + else if (delta>0 && dist < (delta*3) ) + mo->z += FLOATSPEED; + } + } + + // clip movement + if (mo->z <= mo->floorz) + { + // hit the floor + + if (mo->flags & MF_BOUNCE) + { + // the skull slammed into something + // villsa [STRIFE] affect reactiontime + // momz is also shifted by 1 + mo->momz = -mo->momz >> 1; + mo->reactiontime >>= 1; + + // villsa [STRIFE] get terrain type + if(P_GetTerrainType(mo) != FLOOR_SOLID) + mo->flags &= ~MF_BOUNCE; + } + + if (mo->momz < 0) + { + if (mo->player + && mo->momz < -GRAVITY*8) + { + // Squat down. + // Decrease viewheight for a moment + // after hitting the ground (hard), + // and utter appropriate sound. + mo->player->deltaviewheight = mo->momz>>3; + + // villsa [STRIFE] fall damage + // haleyjd 09/18/10: Repaired calculation + if(mo->momz < -20*FRACUNIT) + P_DamageMobj(mo, NULL, mo, mo->momz / -25000); + + // haleyjd 20110224: *Any* fall centers your view, not just + // damaging falls (moved outside the above if). + mo->player->centerview = 1; + S_StartSound (mo, sfx_oof); + } + mo->momz = 0; + } + mo->z = mo->floorz; + + + // cph 2001/05/26 - + // See lost soul bouncing comment above. We need this here for bug + // compatibility with original Doom2 v1.9 - if a soul is charging and + // hit by a raising floor this incorrectly reverses its Y momentum. + // + + // villsa [STRIFE] unused + /* + if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) + mo->momz = -mo->momz; + */ + + // villsa [STRIFE] also check for MF_BOUNCE + if ( (mo->flags & MF_MISSILE) + && !(mo->flags & (MF_NOCLIP|MF_BOUNCE)) ) + { + P_ExplodeMissile (mo); + } + } + else // haleyjd 20110224: else here, not else if - Strife change or what? + { + if (! (mo->flags & MF_NOGRAVITY) ) + { + if (mo->momz == 0) + mo->momz = -GRAVITY*2; + else + mo->momz -= GRAVITY; + } + + if (mo->z + mo->height > mo->ceilingz) + { + // villsa [STRIFE] replace skullfly flag with MF_BOUNCE + if (mo->flags & MF_BOUNCE) + { + // villsa [STRIFE] affect reactiontime + // momz is also shifted by 1 + mo->momz = -mo->momz >> 1; + mo->reactiontime >>= 1; + } + + // hit the ceiling + if (mo->momz > 0) + mo->momz = 0; + + mo->z = mo->ceilingz - mo->height; + + // villsa [STRIFE] also check for MF_BOUNCE + if ( (mo->flags & MF_MISSILE) + && !(mo->flags & (MF_NOCLIP|MF_BOUNCE)) ) + { + // villsa [STRIFE] check against skies + if(mo->subsector->sector->ceilingpic == skyflatnum) + P_RemoveMobj(mo); + else + P_ExplodeMissile (mo); + } + } + } +} + + + +// +// P_NightmareRespawn +// +// [STRIFE] Modifications for: +// * Destination fog z coordinate +// * Restoration of all Strife mapthing flags +// +void +P_NightmareRespawn (mobj_t* mobj) +{ + fixed_t x; + fixed_t y; + fixed_t z; + mobj_t* mo; + mapthing_t* mthing; + + x = mobj->spawnpoint.x << FRACBITS; + y = mobj->spawnpoint.y << FRACBITS; + + // somthing is occupying it's position? + if (!P_CheckPosition (mobj, x, y) ) + return; // no respwan + + // spawn a teleport fog at old spot + // because of removal of the body? + mo = P_SpawnMobj (mobj->x, + mobj->y, + mobj->subsector->sector->floorheight , MT_TFOG); + // initiate teleport sound + S_StartSound (mo, sfx_telept); + + // spawn a teleport fog at the new spot + //ss = R_PointInSubsector (x,y); + + // haleyjd [STRIFE]: Uses ONFLOORZ instead of ss->sector->floorheight + mo = P_SpawnMobj (x, y, ONFLOORZ , MT_TFOG); + + S_StartSound (mo, sfx_telept); + + // spawn the new monster + mthing = &mobj->spawnpoint; + + // spawn it + if (mobj->info->flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + // inherit attributes from deceased one + mo = P_SpawnMobj (x,y,z, mobj->type); + mo->spawnpoint = mobj->spawnpoint; + mo->angle = ANG45 * (mthing->angle/45); + + if (mthing->options & MTF_AMBUSH) + mo->flags |= MF_AMBUSH; + if (mthing->options & MTF_STAND) // [STRIFE] Standing mode, for NPCs + mobj->flags |= MF_STAND; + if (mthing->options & MTF_FRIEND) // [STRIFE] Allies + mobj->flags |= MF_ALLY; + if (mthing->options & MTF_TRANSLUCENT) // [STRIFE] Translucent object + mobj->flags |= MF_SHADOW; + if (mthing->options & MTF_MVIS) // [STRIFE] Alt. Translucency + mobj->flags |= MF_MVIS; + + mo->reactiontime = 18; + + // remove the old monster, + P_RemoveMobj (mobj); +} + + +// +// P_MobjThinker +// +// [STRIFE] Modified for: +// * Terrain effects +// * Stonecold cheat +// * Altered skill 5 respawn behavior +// +void P_MobjThinker (mobj_t* mobj) +{ + // momentum movement + if (mobj->momx + || mobj->momy + /*|| (mobj->flags&MF_SKULLFLY)*/ ) // villsa [STRIFE] unused + { + P_XYMovement (mobj); + + // FIXME: decent NOP/NULL/Nil function pointer please. + if (mobj->thinker.function.acv == (actionf_v) (-1)) + return; // mobj was removed + + // villsa [STRIFE] terrain clipping + if(P_GetTerrainType(mobj) == FLOOR_SOLID) + mobj->flags &= ~MF_FEETCLIPPED; + else + mobj->flags |= MF_FEETCLIPPED; + + } + if ( (mobj->z != mobj->floorz && !(mobj->flags & MF_NOGRAVITY)) // villsa [STRIFE] + || mobj->momz ) + { + P_ZMovement (mobj); + + // FIXME: decent NOP/NULL/Nil function pointer please. + if (mobj->thinker.function.acv == (actionf_v) (-1)) + return; // mobj was removed + + // villsa [STRIFE] terrain clipping and sounds + if(P_GetTerrainType(mobj) == FLOOR_SOLID) + mobj->flags &= ~MF_FEETCLIPPED; + else + { + S_StartSound(mobj, sfx_wsplsh); + mobj->flags |= MF_FEETCLIPPED; + } + + } + + + // cycle through states, + // calling action functions at transitions + if (mobj->tics != -1) + { + mobj->tics--; + + // villsa [STRIFE] stonecold cheat + if(stonecold) + { + if(mobj->flags & MF_COUNTKILL) + P_DamageMobj(mobj, mobj, mobj, 10); + } + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState (mobj, mobj->state->nextstate) ) + return; // freed itself + } + else + { + // check for nightmare respawn + if (! (mobj->flags & MF_COUNTKILL) ) + return; + + if (!respawnmonsters) + return; + + mobj->movecount++; + + // haleyjd [STRIFE]: respawn time increased from 12 to 16 + if (mobj->movecount < 16*TICRATE) + return; + + if ( leveltime&31 ) + return; + + if (P_Random () > 4) + return; + + // haleyjd [STRIFE]: NOTDMATCH things don't respawn + if(mobj->flags & MF_NOTDMATCH) + return; + + P_NightmareRespawn (mobj); + } +} + + +// +// P_SpawnMobj +// +// [STRIFE] Modifications to reactiontime and for terrain types. +// +mobj_t* +P_SpawnMobj +( fixed_t x, + fixed_t y, + fixed_t z, + mobjtype_t type ) +{ + mobj_t* mobj; + state_t* st; + mobjinfo_t* info; + + mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); + memset (mobj, 0, sizeof (*mobj)); + info = &mobjinfo[type]; + + mobj->type = type; + mobj->info = info; + mobj->x = x; + mobj->y = y; + mobj->radius = info->radius; + mobj->height = info->height; + mobj->flags = info->flags; + mobj->health = info->spawnhealth; + + // haleyjd 09/25/10: [STRIFE] Doesn't do this; messes up flamethrower + // and a lot of other stuff using reactiontime as a counter. + //if (gameskill != sk_nightmare) + mobj->reactiontime = info->reactiontime; + + mobj->lastlook = P_Random () % MAXPLAYERS; + // do not set the state with P_SetMobjState, + // because action routines can not be called yet + st = &states[info->spawnstate]; + + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // set subsector and/or block links + P_SetThingPosition (mobj); + + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + + if (z == ONFLOORZ) + { + mobj->z = mobj->floorz; + + // villsa [STRIFE] + if(P_GetTerrainType(mobj) != FLOOR_SOLID) + mobj->flags |= MF_FEETCLIPPED; + + } + else if (z == ONCEILINGZ) + mobj->z = mobj->ceilingz - mobj->info->height; + else + mobj->z = z; + + mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; + + P_AddThinker (&mobj->thinker); + + return mobj; +} + + +// +// P_RemoveMobj +// +// [STRIFE] Modifications for item respawn timing +// +mapthing_t itemrespawnque[ITEMQUESIZE]; +int itemrespawntime[ITEMQUESIZE]; +int iquehead; +int iquetail; + +void P_RemoveMobj (mobj_t* mobj) +{ + // villsa [STRIFE] removed invuln/invis. sphere exceptions + if ((mobj->flags & MF_SPECIAL) + && !(mobj->flags & MF_DROPPED)) + { + itemrespawnque[iquehead] = mobj->spawnpoint; + itemrespawntime[iquehead] = leveltime + 30*TICRATE; // [STRIFE] + + // [STRIFE] haleyjd 20130915 + // -random parameter affects the behavior of respawning items here. + if(randomparm && iquehead != iquetail) + { + short type = itemrespawnque[iquehead].type; + short options = itemrespawnque[iquehead].options; + + // swap the type and options of iquehead and iquetail + itemrespawnque[iquehead].type = itemrespawnque[iquetail].type; + itemrespawnque[iquehead].options = itemrespawnque[iquetail].options; + itemrespawnque[iquetail].type = type; + itemrespawnque[iquetail].options = options; + } + + iquehead = (iquehead+1)&(ITEMQUESIZE-1); + + // lose one off the end? + if (iquehead == iquetail) + iquetail = (iquetail+1)&(ITEMQUESIZE-1); + } + + // unlink from sector and block lists + P_UnsetThingPosition (mobj); + + // stop any playing sound + S_StopSound (mobj); + + // free block + P_RemoveThinker ((thinker_t*)mobj); +} + + + + +// +// P_RespawnSpecials +// +// [STRIFE] modification to item respawn time handling +// +void P_RespawnSpecials (void) +{ + fixed_t x; + fixed_t y; + fixed_t z; + + subsector_t* ss; + mobj_t* mo; + mapthing_t* mthing; + + int i; + + // only respawn items in deathmatch + if (deathmatch != 2) + return; + + // nothing left to respawn? + if (iquehead == iquetail) + return; + + // haleyjd [STRIFE]: 30 second wait is not accounted for here, see above. + if (leveltime < itemrespawntime[iquetail]) + return; + + mthing = &itemrespawnque[iquetail]; + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + // spawn a teleport fog at the new spot + ss = R_PointInSubsector (x,y); + mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); + S_StartSound (mo, sfx_itmbk); + + // find which type to spawn + for (i=0 ; i< NUMMOBJTYPES ; i++) + { + if (mthing->type == mobjinfo[i].doomednum) + break; + } + + if (i >= NUMMOBJTYPES) + { + I_Error("P_RespawnSpecials: Failed to find mobj type with doomednum " + "%d when respawning thing. This would cause a buffer overrun " + "in vanilla Strife.", mthing->type); + } + + // spawn it + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + mo = P_SpawnMobj (x,y,z, i); + mo->spawnpoint = *mthing; + mo->angle = ANG45 * (mthing->angle/45); + + // pull it from the que + iquetail = (iquetail+1)&(ITEMQUESIZE-1); +} + + + + +// +// P_SpawnPlayer +// Called when a player is spawned on the level. +// Most of the player structure stays unchanged +// between levels. +// +// [STRIFE] Modifications for: +// * stonecold cheat, -workparm +// * default inventory/questflags +// +void P_SpawnPlayer(mapthing_t* mthing) +{ + player_t* p; + fixed_t x; + fixed_t y; + fixed_t z; + mobj_t* mobj; + + if(mthing->type == 0) + return; + + // not playing? + if(!playeringame[mthing->type-1]) + return; + + p = &players[mthing->type-1]; + + if (p->playerstate == PST_REBORN) + G_PlayerReborn (mthing->type-1); + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = ONFLOORZ; + mobj = P_SpawnMobj (x,y,z, MT_PLAYER); + + // set color translations for player sprites + if(mthing->type > 1) + mobj->flags |= (mthing->type-1)<angle = ANG45 * (mthing->angle/45); + mobj->player = p; + mobj->health = p->health; + + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + p->message = NULL; + p->damagecount = 0; + p->bonuscount = 0; + p->extralight = 0; + p->fixedcolormap = 0; + p->viewheight = VIEWHEIGHT; + + // setup gun psprite + P_SetupPsprites(p); + + // villsa [STRIFE] + stonecold = false; + + // villsa [STRIFE] what a nasty hack... + if(gamemap == 10) + p->weaponowned[wp_sigil] = true; + + // villsa [STRIFE] instead of just giving cards in deathmatch mode, also + // set accuracy to 50 and give all quest flags + if(deathmatch) + { + int i; + + p->accuracy = 50; + p->questflags = QF_ALLQUESTS; // 0x7fffffff + + for(i = 0; i < NUMCARDS; i++) + p->cards[i] = true; + } + + // villsa [STRIFE] set godmode? + if(workparm) + p->cheats |= CF_GODMODE; + + if(mthing->type - 1 == consoleplayer) + { + // wake up the status bar + ST_Start (); + // wake up the heads up text + HU_Start (); + } +} + + +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +// [STRIFE] Modifications for: +// * No Lost Souls, item count +// * New mapthing_t flag bits +// * 8-player support +// +void P_SpawnMapThing (mapthing_t* mthing) +{ + int i; + int bit; + mobj_t* mobj; + fixed_t x; + fixed_t y; + fixed_t z; + + // count deathmatch start positions + if (mthing->type == 11) + { + if (deathmatch_p < &deathmatchstarts[10]) + { + memcpy (deathmatch_p, mthing, sizeof(*mthing)); + deathmatch_p++; + } + return; + } + + if (mthing->type <= 0) + { + // Thing type 0 is actually "player -1 start". + // For some reason, Vanilla Doom accepts/ignores this. + + return; + } + + // check for players specially + // haleyjd 20120209: [STRIFE] 8 player starts + if (mthing->type <= 8) + { + // save spots for respawning in network games + playerstarts[mthing->type-1] = *mthing; + if (!deathmatch) + P_SpawnPlayer (mthing); + + return; + } + + // check for appropriate skill level + if (!netgame && (mthing->options & 16) ) + return; + + if (gameskill == sk_baby) + bit = 1; + else if (gameskill == sk_nightmare) + bit = 4; + else + // avoid undefined behavior (left shift by negative value and rhs too big) + // by accurately emulating what doom.exe did: reduce mod 32. + // For more details check: + // https://github.com/chocolate-doom/chocolate-doom/issues/1677 + bit = (int) (1U << ((gameskill - 1) & 0x1F)); + + if (!(mthing->options & bit) ) + return; + + // find which type to spawn + for (i=0 ; i< NUMMOBJTYPES ; i++) + if (mthing->type == mobjinfo[i].doomednum) + break; + + if (i==NUMMOBJTYPES) + I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)", + mthing->type, + mthing->x, mthing->y); + + // don't spawn keycards and players in deathmatch + if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) + return; + + // don't spawn any monsters if -nomonsters + // villsa [STRIFE] Removed MT_SKULL + if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) + return; + + // spawn it + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + mobj = P_SpawnMobj (x,y,z, i); + mobj->spawnpoint = *mthing; + + if (mobj->tics > 0) + mobj->tics = 1 + (P_Random () % mobj->tics); + if (mobj->flags & MF_COUNTKILL) + totalkills++; + + // villsa [STRIFE] unused + /* + if (mobj->flags & MF_COUNTITEM) + totalitems++; + */ + + mobj->angle = ANG45 * (mthing->angle/45); + if (mthing->options & MTF_AMBUSH) + mobj->flags |= MF_AMBUSH; + if (mthing->options & MTF_STAND) // [STRIFE] Standing mode, for NPCs + mobj->flags |= MF_STAND; + if (mthing->options & MTF_FRIEND) // [STRIFE] Allies + mobj->flags |= MF_ALLY; + if (mthing->options & MTF_TRANSLUCENT) // [STRIFE] Translucent object + mobj->flags |= MF_SHADOW; + if (mthing->options & MTF_MVIS) // [STRIFE] Alt. Translucency + mobj->flags |= MF_MVIS; +} + + + +// +// GAME SPAWN FUNCTIONS +// + + +// +// P_SpawnPuff +// +// [STRIFE] Modifications for: +// * No spawn tics randomization +// * Player melee behavior +// + +void +P_SpawnPuff +( fixed_t x, + fixed_t y, + fixed_t z ) +{ + mobj_t* th; + int t; + + t = P_Random(); + z += ((t - P_Random()) << 10); + + // [STRIFE] removed momz and tics randomization + + th = P_SpawnMobj(x, y, z, MT_STRIFEPUFF); // [STRIFE]: new type + + // don't make punches spark on the wall + // [STRIFE] Use a separate melee attack range for the player + if(attackrange == PLAYERMELEERANGE) + P_SetMobjState(th, S_POW2_00); // 141 + + // villsa [STRIFE] unused + /* + if (th->tics < 1) + th->tics = 1; + */ +} + +// +// P_SpawnSparkPuff +// +// villsa [STRIFE] new function +// +mobj_t* P_SpawnSparkPuff(fixed_t x, fixed_t y, fixed_t z) +{ + int t = P_Random(); + return P_SpawnMobj(x, y, ((t - P_Random()) << 10) + z, MT_SPARKPUFF); +} + +// +// P_SpawnBlood +// +// [STRIFE] Modifications for: +// * No spawn tics randomization +// * Different damage ranges for state setting +// +void +P_SpawnBlood +( fixed_t x, + fixed_t y, + fixed_t z, + int damage ) +{ + mobj_t* th; + int temp; + + temp = P_Random(); + z += (temp - P_Random()) << 10; + th = P_SpawnMobj(x, y, z, MT_BLOOD_DEATH); + th->momz = FRACUNIT*2; + + // villsa [STRIFE]: removed tics randomization + + // villsa [STRIFE] different checks for damage range + if(damage >= 10 && damage <= 13) + P_SetMobjState(th, S_BLOD_00); + else if(damage >= 7 && damage < 10) + P_SetMobjState(th, S_BLOD_01); + else if(damage < 7) + P_SetMobjState(th, S_BLOD_02); +} + + + +// +// P_CheckMissileSpawn +// Moves the missile forward a bit +// and possibly explodes it right there. +// +// [STRIFE] Modifications for: +// * No spawn tics randomization +// +void P_CheckMissileSpawn (mobj_t* th) +{ + // villsa [STRIFE] removed tics randomization + + // move a little forward so an angle can + // be computed if it immediately explodes + th->x += (th->momx>>1); + th->y += (th->momy>>1); + th->z += (th->momz>>1); + + if (!P_TryMove (th, th->x, th->y)) + P_ExplodeMissile (th); +} + +// Certain functions assume that a mobj_t pointer is non-NULL, +// causing a crash in some situations where it is NULL. Vanilla +// Doom did not crash because of the lack of proper memory +// protection. This function substitutes NULL pointers for +// pointers to a dummy mobj, to avoid a crash. + +mobj_t *P_SubstNullMobj(mobj_t *mobj) +{ + if (mobj == NULL) + { + static mobj_t dummy_mobj; + + dummy_mobj.x = 0; + dummy_mobj.y = 0; + dummy_mobj.z = 0; + dummy_mobj.flags = 0; + + mobj = &dummy_mobj; + } + + return mobj; +} + +// +// P_SpawnMissile +// +// [STRIFE] Added MVIS inaccuracy +// +mobj_t* +P_SpawnMissile +( mobj_t* source, + mobj_t* dest, + mobjtype_t type ) +{ + mobj_t* th; + angle_t an; + int dist; + + th = P_SpawnMobj (source->x, + source->y, + source->z + 4*8*FRACUNIT, type); + + if (th->info->seesound) + S_StartSound (th, th->info->seesound); + + th->target = source; // where it came from + an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); + + // fuzzy player + if (dest->flags & MF_SHADOW) + { + int t = P_Random(); // haleyjd 20110223: remove order-of-evaluation dependencies + an += (t - P_Random()) << 21; + } + // villsa [STRIFE] check for heavily transparent things + else if(dest->flags & MF_MVIS) + { + int t = P_Random(); + an += (t - P_Random()) << 22; + } + + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul (th->info->speed, finecosine[an]); + th->momy = FixedMul (th->info->speed, finesine[an]); + + dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + + if (dist < 1) + dist = 1; + + th->momz = (dest->z - source->z) / dist; + P_CheckMissileSpawn (th); + + return th; +} + +// +// P_SpawnFacingMissile +// +// villsa [STRIFE] new function +// Spawn a missile based on source's angle +// +mobj_t* P_SpawnFacingMissile(mobj_t* source, mobj_t* target, mobjtype_t type) +{ + mobj_t* th; + angle_t an; + fixed_t dist; + + th = P_SpawnMobj(source->x, source->y, source->z + (32*FRACUNIT), type); + + if(th->info->seesound) + S_StartSound(th, th->info->seesound); + + th->target = source; // where it came from + th->angle = source->angle; // haleyjd 09/06/10: fix0red + an = th->angle; + + // fuzzy player + if (target->flags & MF_SHADOW) + { + int t = P_Random(); + an += (t - P_Random()) << 21; + } + // villsa [STRIFE] check for heavily transparent things + else if(target->flags & MF_MVIS) + { + int t = P_Random(); + an += (t - P_Random()) << 22; + } + + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul (th->info->speed, finecosine[an]); + th->momy = FixedMul (th->info->speed, finesine[an]); + + dist = P_AproxDistance (target->x - source->x, target->y - source->y); + dist = dist / th->info->speed; + + if(dist < 1) + dist = 1; + + th->momz = (target->z - source->z) / dist; + P_CheckMissileSpawn (th); + + return th; +} + +// +// P_SpawnPlayerMissile +// +// Tries to aim at a nearby monster +// villsa [STRIFE] now returns a mobj +// * Also modified to allow up/down look, and to account for foot-clipping +// by liquid terrain. +// +mobj_t* P_SpawnPlayerMissile(mobj_t* source, mobjtype_t type) +{ + mobj_t* th; + angle_t an; + + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t slope; + + // see which target is to be aimed at + an = source->angle; + slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); + + if (!linetarget) + { + an += 1<<26; + slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); + + if (!linetarget) + { + an -= 2<<26; + slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); + } + + if (!linetarget) + { + an = source->angle; + + // haleyjd 09/21/10: [STRIFE] Removed, for look up/down support. + //slope = 0; + } + } + + // villsa [STRIFE] + if(linetarget) + source->target = linetarget; + + x = source->x; + y = source->y; + + // villsa [STRIFE] + if(!(source->flags & MF_FEETCLIPPED)) + z = source->z + 32*FRACUNIT; + else + z = source->z + 22*FRACUNIT; + + th = P_SpawnMobj (x,y,z, type); + + if (th->info->seesound) + S_StartSound (th, th->info->seesound); + + th->target = source; + th->angle = an; + th->momx = FixedMul( th->info->speed, + finecosine[an>>ANGLETOFINESHIFT]); + th->momy = FixedMul( th->info->speed, + finesine[an>>ANGLETOFINESHIFT]); + th->momz = FixedMul( th->info->speed, slope); + + P_CheckMissileSpawn (th); + + return th; +} + +// +// P_SpawnMortar +// +// villsa [STRIFE] new function +// Spawn a high-arcing ballistic projectile +// +mobj_t* P_SpawnMortar(mobj_t *source, mobjtype_t type) +{ + mobj_t* th; + angle_t an; + fixed_t slope; + + an = source->angle; + + th = P_SpawnMobj(source->x, source->y, source->z, type); + th->target = source; + th->angle = an; + an >>= ANGLETOFINESHIFT; + + // haleyjd 20110203: corrected order of function calls + th->momx = FixedMul(th->info->speed, finecosine[an]); + th->momy = FixedMul(th->info->speed, finesine[an]); + + P_CheckMissileSpawn(th); + + slope = P_AimLineAttack(source, source->angle, 1024*FRACUNIT); + th->momz = FixedMul(th->info->speed, slope); + + return th; +} diff --git a/games/NXDoom/src/strife/p_mobj.h b/games/NXDoom/src/strife/p_mobj.h new file mode 100644 index 00000000000..3872f9d03aa --- /dev/null +++ b/games/NXDoom/src/strife/p_mobj.h @@ -0,0 +1,330 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Map Objects, MObj, definition and handling. +// + + +#ifndef __P_MOBJ__ +#define __P_MOBJ__ + +// Basics. +#include "tables.h" +#include "m_fixed.h" + +// We need the thinker_t stuff. +#include "d_think.h" + +// We need the WAD data structure for Map things, +// from the THINGS lump. +#include "doomdata.h" + +// States are tied to finite states are +// tied to animation frames. +// Needs precompiled tables/data structures. +#include "info.h" + + + + + + +// +// NOTES: mobj_t +// +// mobj_ts are used to tell the refresh where to draw an image, +// tell the world simulation when objects are contacted, +// and tell the sound driver how to position a sound. +// +// The refresh uses the next and prev links to follow +// lists of things in sectors as they are being drawn. +// The sprite, frame, and angle elements determine which patch_t +// is used to draw the sprite if it is visible. +// The sprite and frame values are allmost allways set +// from state_t structures. +// The statescr.exe utility generates the states.h and states.c +// files that contain the sprite/frame numbers from the +// statescr.txt source file. +// The xyz origin point represents a point at the bottom middle +// of the sprite (between the feet of a biped). +// This is the default origin position for patch_ts grabbed +// with lumpy.exe. +// A walking creature will have its z equal to the floor +// it is standing on. +// +// The sound code uses the x,y, and subsector fields +// to do stereo positioning of any sound effited by the mobj_t. +// +// The play simulation uses the blocklinks, x,y,z, radius, height +// to determine when mobj_ts are touching each other, +// touching lines in the map, or hit by trace lines (gunshots, +// lines of sight, etc). +// The mobj_t->flags element has various bit flags +// used by the simulation. +// +// Every mobj_t is linked into a single sector +// based on its origin coordinates. +// The subsector_t is found with R_PointInSubsector(x,y), +// and the sector_t can be found with subsector->sector. +// The sector links are only used by the rendering code, +// the play simulation does not care about them at all. +// +// Any mobj_t that needs to be acted upon by something else +// in the play world (block movement, be shot, etc) will also +// need to be linked into the blockmap. +// If the thing has the MF_NOBLOCK flag set, it will not use +// the block links. It can still interact with other things, +// but only as the instigator (missiles will run into other +// things, but nothing can run into a missile). +// Each block in the grid is 128*128 units, and knows about +// every line_t that it contains a piece of, and every +// interactable mobj_t that has its origin contained. +// +// A valid mobj_t is a mobj_t that has the proper subsector_t +// filled in for its xy coordinates and is linked into the +// sector from which the subsector was made, or has the +// MF_NOSECTOR flag set (the subsector_t needs to be valid +// even if MF_NOSECTOR is set), and is linked into a blockmap +// block or has the MF_NOBLOCKMAP flag set. +// Links should only be modified by the P_[Un]SetThingPosition() +// functions. +// Do not change the MF_NO? flags while a thing is valid. +// +// Any questions? +// + +// +// Misc. mobj flags +// +typedef enum +{ + // Call P_SpecialThing when touched. + MF_SPECIAL = 1, + + // Blocks. + MF_SOLID = 2, + + // Can be hit. + MF_SHOOTABLE = 4, + + // Don't use the sector links (invisible but touchable). + MF_NOSECTOR = 8, + + // Don't use the blocklinks (inert but displayable) + MF_NOBLOCKMAP = 16, + + // villsa [STRIFE] Stand around until alerted + MF_STAND = 32, + + // Will try to attack right back. + MF_JUSTHIT = 64, + + // Will take at least one step before attacking. + MF_JUSTATTACKED = 128, + + // On level spawning (initial position), + // hang from ceiling instead of stand on floor. + MF_SPAWNCEILING = 256, + + // Don't apply gravity (every tic), + // that is, object will float, keeping current height + // or changing it actively. + MF_NOGRAVITY = 512, + + // Movement flags. + // This allows jumps from high places. + MF_DROPOFF = 0x400, + + // villsa [STRIFE] For players, count as quest item + MF_GIVEQUEST = 0x800, + + // Player cheat. ??? + MF_NOCLIP = 0x1000, + + // villsa [STRIFE] are feet clipped into water/slude floor? + MF_FEETCLIPPED = 0x2000, + + // Allow moves to any height, no gravity. + // For active floaters, e.g. cacodemons, pain elementals. + MF_FLOAT = 0x4000, + + // villsa [STRIFE] can NPC talk? + MF_NODIALOG = 0x8000, + + // Don't hit same species, explode on block. + // Player missiles as well as fireballs of various kinds. + MF_MISSILE = 0x10000, + + // Dropped by a demon, not level spawned. + // E.g. ammo clips dropped by dying former humans. + MF_DROPPED = 0x20000, + + // Use fuzzy draw (shadow demons or spectres), + // temporary player invisibility powerup. + MF_SHADOW = 0x40000, + + // Flag: don't bleed when shot (use puff), + // barrels and shootable furniture shall not bleed. + MF_NOBLOOD = 0x80000, + + // Don't stop moving halfway off a step, + // that is, have dead bodies slide down all the way. + MF_CORPSE = 0x100000, + + // Floating to a height for a move, ??? + // don't auto float to target's height. + MF_INFLOAT = 0x200000, + + // On kill, count this enemy object + // towards intermission kill total. + // Happy gathering. + MF_COUNTKILL = 0x400000, + + // Not to be activated by sound, deaf monster. + MF_AMBUSH = 0x800000, + + // villsa [STRIFE] flag used for bouncing projectiles + MF_BOUNCE = 0x1000000, + + // Don't spawn this object + // in death match mode (e.g. key cards). + MF_NOTDMATCH = 0x2000000, + + // villsa [STRIFE] friendly towards player with matching flag + MF_ALLY = 0x4000000, + + // villsa [STRIFE] 75% or 25% transparency? -- NEEDS VERIFICATION + MF_MVIS = 0x8000000, + + // villsa [STRIFE] color translation + MF_COLORSWAP1 = 0x10000000, + + // villsa [STRIFE] color translation + MF_COLORSWAP2 = 0x20000000, + + // villsa [STRIFE] color translation + MF_COLORSWAP3 = 0x40000000, + + // villsa [STRIFE] spectral entity, only damaged by spectral missiles + MF_SPECTRAL = 0x80000000, + + // Player sprites in multiplayer modes are modified + // using an internal color lookup table for re-indexing. + // haleyjd 09/06/10: redid for Strife translations + MF_TRANSLATION = (MF_COLORSWAP1|MF_COLORSWAP2|MF_COLORSWAP3), + + // Turns 0x10000000 into 0x01 to get a translation index. + // villsa [STRIFE] change from 26 to 28 + MF_TRANSSHIFT = 28 + +} mobjflag_t; + + +// Map Object definition. +// +// [STRIFE]: Amazingly, only one modification was made to mobj_t over DOOM +// 1.666, and that was the addition of the single-byte allegiance field for +// tracking with which player friendly monsters are allied. +// +typedef struct mobj_s +{ + // List: thinker links. + thinker_t thinker; + + // Info for drawing: position. + fixed_t x; + fixed_t y; + fixed_t z; + + // More list: links in sector (if needed) + struct mobj_s* snext; + struct mobj_s* sprev; + + //More drawing info: to determine current sprite. + angle_t angle; // orientation + spritenum_t sprite; // used to find patch_t and flip value + int frame; // might be ORed with FF_FULLBRIGHT + + // Interaction info, by BLOCKMAP. + // Links in blocks (if needed). + struct mobj_s* bnext; + struct mobj_s* bprev; + + struct subsector_s* subsector; + + // The closest interval over all contacted Sectors. + fixed_t floorz; + fixed_t ceilingz; + + // For movement checking. + fixed_t radius; + fixed_t height; + + // Momentums, used to update position. + fixed_t momx; + fixed_t momy; + fixed_t momz; + + // If == validcount, already checked. + int validcount; + + mobjtype_t type; + mobjinfo_t* info; // &mobjinfo[mobj->type] + + int tics; // state tic counter + state_t* state; + int flags; + int health; + + // Movement direction, movement generation (zig-zagging). + int movedir; // 0-7 + int movecount; // when 0, select a new dir + + // Thing being chased/attacked (or NULL), + // also the originator for missiles. + struct mobj_s* target; + + // Reaction time: if non 0, don't attack yet. + // Used by player to freeze a bit after teleporting. + int reactiontime; + + // If >0, the target will be chased + // no matter what (even if shot) + int threshold; + + // Additional info record for player avatars only. + // Only valid if type == MT_PLAYER + struct player_s* player; + + // Player number last looked for. + int lastlook; + + // For nightmare respawn. + mapthing_t spawnpoint; + + // Thing being chased/attacked for tracers. + struct mobj_s* tracer; + + // [STRIFE] haleyjd 09/05/10: + // * In multiplayer this stores allegiance, for friends and teleport beacons + // * In single-player this tracks dialog state. + byte miscdata; + +} mobj_t; + +// haleyjd [STRIFE] Exported +void P_CheckMissileSpawn (mobj_t* th); + +#endif diff --git a/games/NXDoom/src/strife/p_plats.c b/games/NXDoom/src/strife/p_plats.c new file mode 100644 index 00000000000..aeb0eb5aa9a --- /dev/null +++ b/games/NXDoom/src/strife/p_plats.c @@ -0,0 +1,358 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Plats (i.e. elevator platforms) code, raising/lowering. +// + +#include + +#include "i_system.h" +#include "z_zone.h" +#include "m_random.h" + +#include "doomdef.h" +#include "p_local.h" + +#include "s_sound.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// Data. +#include "sounds.h" + + +plat_t* activeplats[MAXPLATS]; + + + +// +// Move a plat up and down +// +void T_PlatRaise(plat_t* plat) +{ + result_e res; + + switch(plat->status) + { + case up: + res = T_MovePlane(plat->sector, plat->speed, plat->high, plat->crush, 0, 1); + + if(plat->type == raiseAndChange + || plat->type == raiseToNearestAndChange) + { + if(!(leveltime&7)) + S_StartSound(&plat->sector->soundorg, sfx_stnmov); + } + + // villsa [STRIFE] + if(plat->type == slowDWUS) + { + if(!(leveltime&7)) + S_StartSound(&plat->sector->soundorg, sfx_stnmov); + } + + + if(res == crushed && (!plat->crush)) + { + plat->count = plat->wait; + plat->status = down; + S_StartSound(&plat->sector->soundorg, sfx_pstart); + } + else + { + if(res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound(&plat->sector->soundorg, sfx_pstop); + + switch(plat->type) + { + case blazeDWUS: + case downWaitUpStay: + case raiseAndChange: + case slowDWUS: // villsa [STRIFE] + case raiseToNearestAndChange: + P_RemoveActivePlat(plat); + break; + + default: + break; + } + } + } + break; + + case down: + res = T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, -1); + + // villsa [STRIFE] + if(plat->type == slowDWUS) + { + if(!(leveltime&7)) + S_StartSound(&plat->sector->soundorg, sfx_stnmov); + } + + if(res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound(&plat->sector->soundorg,sfx_pstop); + + // villsa [STRIFE] + if(plat->type == upWaitDownStay) + P_RemoveActivePlat(plat); + } + break; + + case waiting: + if(!--plat->count) + { + if(plat->sector->floorheight == plat->low) + plat->status = up; + else + plat->status = down; + S_StartSound(&plat->sector->soundorg,sfx_pstart); + } + + case in_stasis: + break; + } +} + + +// +// EV_DoPlat +// +// Do Platforms "amount" is only used for SOME platforms. +// +int EV_DoPlat(line_t* line, plattype_e type, int amount) +{ + plat_t* plat; + int secnum; + int rtn; + sector_t* sec; + + secnum = -1; + rtn = 0; + + + // Activate all plats that are in_stasis + switch(type) + { + case perpetualRaise: + P_ActivateInStasis(line->tag); + break; + + default: + break; + } + + while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + sec = §ors[secnum]; + + if (sec->specialdata) + continue; + + // Find lowest & highest floors around sector + rtn = 1; + plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); + P_AddThinker(&plat->thinker); + + plat->type = type; + plat->sector = sec; + plat->sector->specialdata = plat; + plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise; + plat->crush = false; + plat->tag = line->tag; + + switch(type) + { + case raiseToNearestAndChange: + plat->speed = PLATSPEED/2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = P_FindNextHighestFloor(sec,sec->floorheight); + plat->wait = 0; + plat->status = up; + + // NO MORE DAMAGE, IF APPLICABLE + sec->special = 0; + + S_StartSound(&sec->soundorg, sfx_stnmov); + break; + + case raiseAndChange: + plat->speed = PLATSPEED/2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = sec->floorheight + amount * FRACUNIT; + plat->wait = 0; + plat->status = up; + + S_StartSound(&sec->soundorg, sfx_stnmov); + break; + + // villsa [STRIFE] + case upWaitDownStay: + plat->speed = PLATSPEED * 4; + plat->high = P_FindNextHighestFloor(sec, sec->floorheight); + plat->low = sec->floorheight; + plat->wait = TICRATE * PLATWAIT; + plat->status = up; + S_StartSound(&sec->soundorg, sfx_pstart); + break; + + case downWaitUpStay: + plat->speed = PLATSPEED * 4; + plat->low = P_FindLowestFloorSurrounding(sec); + + if(plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = sec->floorheight; + plat->wait = TICRATE * PLATWAIT; + plat->status = down; + S_StartSound(&sec->soundorg, sfx_pstart); + break; + + // villsa [STRIFE] + case slowDWUS: + plat->speed = PLATSPEED; + plat->low = P_FindLowestFloorSurrounding(sec); + + if(plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = sec->floorheight; + plat->wait = TICRATE * (PLATWAIT * 10); + plat->status = down; + S_StartSound(&sec->soundorg,sfx_pstart); + break; + + case blazeDWUS: + plat->speed = PLATSPEED * 8; + plat->low = P_FindLowestFloorSurrounding(sec); + + if(plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = sec->floorheight; + plat->wait = TICRATE * PLATWAIT; + plat->status = down; + S_StartSound(&sec->soundorg, sfx_pstart); + break; + + case perpetualRaise: + plat->speed = PLATSPEED; + plat->low = P_FindLowestFloorSurrounding(sec); + + if(plat->low > sec->floorheight) + plat->low = sec->floorheight; + + plat->high = P_FindHighestFloorSurrounding(sec); + + if(plat->high < sec->floorheight) + plat->high = sec->floorheight; + + plat->wait = TICRATE * PLATWAIT; + plat->status = P_Random() & 1; + + S_StartSound(&sec->soundorg, sfx_pstart); + break; + } + + P_AddActivePlat(plat); + } + return rtn; +} + + +// +// P_ActivateInStasis +// +void P_ActivateInStasis(int tag) +{ + int i; + + for(i = 0; i < MAXPLATS; i++) + if(activeplats[i] + && (activeplats[i])->tag == tag + && (activeplats[i])->status == in_stasis) + { + (activeplats[i])->status = (activeplats[i])->oldstatus; + (activeplats[i])->thinker.function.acp1 + = (actionf_p1)T_PlatRaise; + } +} + +// +// EV_StopPlat +// +void EV_StopPlat(line_t* line) +{ + int j; + + for(j = 0; j < MAXPLATS; j++) + if (activeplats[j] + && ((activeplats[j])->status != in_stasis) + && ((activeplats[j])->tag == line->tag)) + { + (activeplats[j])->oldstatus = (activeplats[j])->status; + (activeplats[j])->status = in_stasis; + (activeplats[j])->thinker.function.acv = (actionf_v)NULL; + } +} + +// +// P_AddActivePlat +// +void P_AddActivePlat(plat_t* plat) +{ + int i; + + for(i = 0; i < MAXPLATS; i++) + { + if (activeplats[i] == NULL) + { + activeplats[i] = plat; + return; + } + } + + I_Error("P_AddActivePlat: no more plats!"); +} + +// +// P_RemoveActivePlat +// +void P_RemoveActivePlat(plat_t* plat) +{ + int i; + for(i = 0; i < MAXPLATS; i++) + { + if(plat == activeplats[i]) + { + (activeplats[i])->sector->specialdata = NULL; + P_RemoveThinker(&(activeplats[i])->thinker); + activeplats[i] = NULL; + + return; + } + } + + I_Error("P_RemoveActivePlat: can't find plat!"); +} diff --git a/games/NXDoom/src/strife/p_pspr.c b/games/NXDoom/src/strife/p_pspr.c new file mode 100644 index 00000000000..f7f2839351e --- /dev/null +++ b/games/NXDoom/src/strife/p_pspr.c @@ -0,0 +1,1003 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Weapon sprite animation, weapon objects. +// Action functions for weapons. +// + + +#include "doomdef.h" +#include "d_event.h" + +#include "deh_misc.h" + +#include "m_random.h" +#include "p_local.h" +#include "s_sound.h" + +// State. +#include "doomstat.h" + +// Data. +#include "sounds.h" + +#include "p_pspr.h" + +#define LOWERSPEED FRACUNIT*6 +#define RAISESPEED FRACUNIT*6 + +#define WEAPONBOTTOM 128*FRACUNIT +#define WEAPONTOP 32*FRACUNIT + + + +// +// P_SetPsprite +// +// [STRIFE] +// villsa: Removed psprite sx, sy modification via misc1/2 +// +void +P_SetPsprite +( player_t* player, + int position, + statenum_t stnum ) +{ + pspdef_t* psp; + state_t* state; + + psp = &player->psprites[position]; + + do + { + if (!stnum) + { + // object removed itself + psp->state = NULL; + break; + } + + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; // could be 0 + + // villsa [STRIFE] unused + /*if (state->misc1) + { + // coordinate set + psp->sx = state->misc1 << FRACBITS; + psp->sy = state->misc2 << FRACBITS; + }*/ + + // Call action routine. + // Modified handling. + if (state->action.acp2) + { + state->action.acp2(player, psp); + if (!psp->state) + break; + } + + stnum = psp->state->nextstate; + + } while (!psp->tics); + // an initial state of 0 could cycle through +} + +// haleyjd 09/06/10: [STRIFE] Removed P_CalcSwing + +// +// P_BringUpWeapon +// Starts bringing the pending weapon up +// from the bottom of the screen. +// Uses player +// +// villsa [STRIFE] Modifications for Strife weapons +// +void P_BringUpWeapon (player_t* player) +{ + statenum_t newstate; + + if (player->pendingweapon == wp_nochange) + player->pendingweapon = player->readyweapon; + + if (player->pendingweapon == wp_flame) + S_StartSound (player->mo, sfx_flidl); // villsa [STRIFE] flame sounds + + newstate = weaponinfo[player->pendingweapon].upstate; + + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + P_SetPsprite (player, ps_weapon, newstate); + + // villsa [STRIFE] set various flash states + if(player->pendingweapon == wp_elecbow) + P_SetPsprite(player, ps_flash, S_XBOW_10); // 31 + else if(player->pendingweapon == wp_sigil && player->sigiltype) + P_SetPsprite(player, ps_flash, S_SIGH_00 + player->sigiltype); // 117 + else + P_SetPsprite(player, ps_flash, S_NULL); + + player->pendingweapon = wp_nochange; +} + +// +// P_CheckAmmo +// Returns true if there is enough ammo to shoot. +// If not, selects the next weapon to use. +// +// villsa [STRIFE] Changes to handle Strife weapons +// +boolean P_CheckAmmo (player_t* player) +{ + ammotype_t ammo; + int count; + + ammo = weaponinfo[player->readyweapon].ammo; + + // Minimal amount for one shot varies. + if (player->readyweapon == wp_torpedo) + count = 30; + else if (player->readyweapon == wp_mauler) + count = 20; + else + count = 1; // Regular. + + // Some do not need ammunition anyway. + // Return if current ammunition sufficient. + if (ammo == am_noammo || player->ammo[ammo] >= count) + return true; + + // Out of ammo, pick a weapon to change to. + // Preferences are set here. + + // villsa [STRIFE] new weapon preferences + if (player->weaponowned[wp_mauler] && player->ammo[am_cell] >= 20) + player->pendingweapon = wp_mauler; + + else if(player->weaponowned[wp_rifle] && player->ammo[am_bullets]) + player->pendingweapon = wp_rifle; + + else if (player->weaponowned[wp_elecbow] && player->ammo[am_elecbolts]) + player->pendingweapon = wp_elecbow; + + else if (player->weaponowned[wp_missile] && player->ammo[am_missiles]) + player->pendingweapon = wp_missile; + + else if (player->weaponowned[wp_flame] && player->ammo[am_cell]) + player->pendingweapon = wp_flame; + + else if (player->weaponowned[wp_hegrenade] && player->ammo[am_hegrenades]) + player->pendingweapon = wp_hegrenade; + + else if (player->weaponowned[wp_poisonbow] && player->ammo[am_poisonbolts]) + player->pendingweapon = wp_poisonbow; + + else if (player->weaponowned[wp_wpgrenade] && player->ammo[am_wpgrenades]) + player->pendingweapon = wp_wpgrenade; + + // BUG: This will *never* be selected for an automatic switch because the + // normal Mauler is higher priority and uses less ammo. + else if (player->weaponowned[wp_torpedo] && player->ammo[am_cell] >= 30) + player->pendingweapon = wp_torpedo; + + else + player->pendingweapon = wp_fist; + + + // Now set appropriate weapon overlay. + P_SetPsprite(player, ps_weapon, weaponinfo[player->readyweapon].downstate); + + return false; +} + + +// +// P_FireWeapon. +// +// villsa [STRIFE] Changes for player state and weapons +// +void P_FireWeapon (player_t* player) +{ + statenum_t newstate; + + if (!P_CheckAmmo (player)) + return; + + P_SetMobjState (player->mo, S_PLAY_05); // 292 + newstate = weaponinfo[player->readyweapon].atkstate; + P_SetPsprite (player, ps_weapon, newstate); + + // villsa [STRIFE] exclude these weapons from causing noise + if(player->readyweapon > wp_elecbow && player->readyweapon != wp_poisonbow) + P_NoiseAlert (player->mo, player->mo); +} + + + +// +// P_DropWeapon +// Player died, so put the weapon away. +// +void P_DropWeapon (player_t* player) +{ + P_SetPsprite (player, + ps_weapon, + weaponinfo[player->readyweapon].downstate); +} + + + +// +// A_WeaponReady +// The player can fire the weapon +// or change to another weapon at this time. +// Follows after getting weapon up, +// or after previous attack/fire sequence. +// +void A_WeaponReady( player_t* player, pspdef_t* psp) +{ + statenum_t newstate; + int angle; + + // get out of attack state + if (player->mo->state == &states[S_PLAY_05] || // 292 + player->mo->state == &states[S_PLAY_06]) // 293 + { + P_SetMobjState (player->mo, S_PLAY_00); // 287 + } + + // villsa [STRIFE] check for wp_flame instead of chainsaw + // haleyjd 09/06/10: fixed state (00 rather than 01) + if (player->readyweapon == wp_flame + && psp->state == &states[S_FLMT_00]) // 62 + { + S_StartSound (player->mo, sfx_flidl); + } + + // check for change + // if player is dead, put the weapon away + if (player->pendingweapon != wp_nochange || !player->health) + { + // change weapon + // (pending weapon should allready be validated) + newstate = weaponinfo[player->readyweapon].downstate; + P_SetPsprite (player, ps_weapon, newstate); + return; + } + + // check for fire + // the missile launcher and torpedo do not auto fire + if (player->cmd.buttons & BT_ATTACK) + { + if ( !player->attackdown + || (player->readyweapon != wp_missile + && player->readyweapon != wp_torpedo)) // villsa [STRIFE] replace bfg with torpedo + { + player->attackdown = true; + P_FireWeapon (player); + return; + } + } + else + player->attackdown = false; + + // bob the weapon based on movement speed + angle = (128*leveltime)&FINEMASK; + psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); + angle &= FINEANGLES/2-1; + psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); +} + + + +// +// A_ReFire +// The player can re-fire the weapon +// without lowering it entirely. +// +void A_ReFire +( player_t* player, + pspdef_t* psp ) +{ + + // check for fire + // (if a weaponchange is pending, let it go through instead) + if ( (player->cmd.buttons & BT_ATTACK) + && player->pendingweapon == wp_nochange + && player->health) + { + player->refire++; + P_FireWeapon (player); + } + else + { + player->refire = 0; + P_CheckAmmo (player); + } +} + +// +// A_CheckReload +// +void A_CheckReload(player_t* player, pspdef_t* psp) +{ + P_CheckAmmo(player); + + // villsa [STRIFE] set animating sprite for crossbow + if(player->readyweapon == wp_elecbow) + P_SetPsprite(player, player->readyweapon, S_XBOW_10); +} + + + +// +// A_Lower +// Lowers current weapon, +// and changes weapon at bottom. +// +void +A_Lower +( player_t* player, + pspdef_t* psp ) +{ + psp->sy += LOWERSPEED; + + // Is already down. + if (psp->sy < WEAPONBOTTOM ) + return; + + // Player is dead. + if (player->playerstate == PST_DEAD) + { + psp->sy = WEAPONBOTTOM; + + // don't bring weapon back up + return; + } + + // The old weapon has been lowered off the screen, + // so change the weapon and start raising it + if (!player->health) + { + // Player is dead, so keep the weapon off screen. + P_SetPsprite (player, ps_weapon, S_NULL); + return; + } + + player->readyweapon = player->pendingweapon; + + P_BringUpWeapon (player); +} + + +// +// A_Raise +// +void +A_Raise +( player_t* player, + pspdef_t* psp ) +{ + statenum_t newstate; + + psp->sy -= RAISESPEED; + + if (psp->sy > WEAPONTOP ) + return; + + psp->sy = WEAPONTOP; + + // The weapon has been raised all the way, + // so change to the ready state. + newstate = weaponinfo[player->readyweapon].readystate; + + P_SetPsprite (player, ps_weapon, newstate); +} + + + +// +// A_GunFlash +// +void +A_GunFlash +( player_t* player, + pspdef_t* psp ) +{ + P_SetMobjState (player->mo, S_PLAY_06); + P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); +} + + + +// +// WEAPON ATTACKS +// + + +// +// A_Punch +// + +void A_Punch(player_t* player, pspdef_t* psp) +{ + angle_t angle; + int damage; + int slope; + int sound; + int stamina; + int t; + + // villsa [STRIFE] new damage formula + // haleyjd 09/19/10: seriously corrected... + stamina = player->stamina; + damage = (P_Random() & ((stamina/10) + 7)) * ((stamina/10) + 2); + + if(player->powers[pw_strength]) + damage *= 10; + + angle = player->mo->angle; + t = P_Random(); + angle += (t - P_Random()) << 18; + slope = P_AimLineAttack (player->mo, angle, PLAYERMELEERANGE); + P_LineAttack (player->mo, angle, PLAYERMELEERANGE, slope, damage); + + // turn to face target + if(linetarget) + { + // villsa [STRIFE] check for non-flesh types + if(linetarget->flags & MF_NOBLOOD) + sound = sfx_mtalht; + else + sound = sfx_meatht; + + S_StartSound (player->mo, sound); + player->mo->angle = R_PointToAngle2 (player->mo->x, + player->mo->y, + linetarget->x, + linetarget->y); + + // villsa [STRIFE] apply flag + player->mo->flags |= MF_JUSTATTACKED; + + // villsa [STRIFE] do punch alert routine + P_DoPunchAlert(player->mo, linetarget); + } + else + S_StartSound (player->mo, sfx_swish); +} + + +// +// A_FireFlameThrower +// +// villsa [STRIFE] new codepointer +// +void A_FireFlameThrower(player_t* player, pspdef_t* psp) +{ + mobj_t* mo; + int t; + + P_SetMobjState(player->mo, S_PLAY_06); + player->ammo[weaponinfo[player->readyweapon].ammo]--; + t = P_Random(); + player->mo->angle += (t - P_Random()) << 18; + + mo = P_SpawnPlayerMissile(player->mo, MT_SFIREBALL); + mo->momz += (5*FRACUNIT); +} + +// +// A_FireMissile +// +// villsa [STRIFE] completly new compared to the original +// +void A_FireMissile(player_t* player, pspdef_t* psp) +{ + angle_t an; + int t; + + // haleyjd 09/19/10: I previously missed an add op that meant it should be + // accuracy * 5, not 4. Checks out with other sources. + an = player->mo->angle; + t = P_Random(); + player->mo->angle += (t - P_Random()) << (19 - (player->accuracy * 5 / 100)); + P_SetMobjState(player->mo, S_PLAY_06); + player->ammo[weaponinfo[player->readyweapon].ammo]--; + P_SpawnPlayerMissile(player->mo, MT_MINIMISSLE); + player->mo->angle = an; +} + +// +// A_FireMauler2 +// +// villsa [STRIFE] - new codepointer +// +void A_FireMauler2(player_t* player, pspdef_t* pspr) +{ + P_SetMobjState(player->mo, S_PLAY_06); + P_DamageMobj(player->mo, player->mo, NULL, 20); + player->ammo[weaponinfo[player->readyweapon].ammo] -= 30; + P_SpawnPlayerMissile(player->mo, MT_TORPEDO); + P_Thrust(player, player->mo->angle + ANG180, 512000); +} + +// +// A_FireGrenade +// +// villsa [STRIFE] - new codepointer +// +void A_FireGrenade(player_t* player, pspdef_t* pspr) +{ + mobjtype_t type; + mobj_t* mo; + state_t* st1; + state_t* st2; + angle_t an; + fixed_t radius; + + // decide on what type of grenade to spawn + if(player->readyweapon == wp_hegrenade) + { + type = MT_HEGRENADE; + } + else if(player->readyweapon == wp_wpgrenade) + { + type = MT_PGRENADE; + } + else + { + type = MT_HEGRENADE; + fprintf(stderr, "Warning: A_FireGrenade used on wrong weapon!\n"); + } + + player->ammo[weaponinfo[player->readyweapon].ammo]--; + + // set flash frame + st1 = &states[(pspr->state - states) + weaponinfo[player->readyweapon].flashstate]; + st2 = &states[weaponinfo[player->readyweapon].atkstate]; + P_SetPsprite(player, ps_flash, st1 - st2); + + player->mo->z += 32*FRACUNIT; // ugh + mo = P_SpawnMortar(player->mo, type); + player->mo->z -= 32*FRACUNIT; // ugh + + // change momz based on player's pitch + mo->momz = FixedMul((player->pitch<info->speed) + (8*FRACUNIT); + S_StartSound(mo, mo->info->seesound); + + radius = mobjinfo[type].radius + player->mo->info->radius; + an = (player->mo->angle >> ANGLETOFINESHIFT); + + mo->x += FixedMul(finecosine[an], radius + (4*FRACUNIT)); + mo->y += FixedMul(finesine[an], radius + (4*FRACUNIT)); + + // shoot grenade from left or right side? + if(&states[weaponinfo[player->readyweapon].atkstate] == pspr->state) + an = (player->mo->angle - ANG90) >> ANGLETOFINESHIFT; + else + an = (player->mo->angle + ANG90) >> ANGLETOFINESHIFT; + + mo->x += FixedMul((15*FRACUNIT), finecosine[an]); + mo->y += FixedMul((15*FRACUNIT), finesine[an]); + + // set bounce flag + mo->flags |= MF_BOUNCE; +} + +// +// A_FireElectricBolt +// villsa [STRIFE] - new codepointer +// + +void A_FireElectricBolt(player_t* player, pspdef_t* pspr) +{ + angle_t an = player->mo->angle; + int t; + + // haleyjd 09/19/10: Use 5 mul on accuracy here as well + t = P_Random(); + player->mo->angle += (t - P_Random()) << (18 - (player->accuracy * 5 / 100)); + player->ammo[weaponinfo[player->readyweapon].ammo]--; + P_SpawnPlayerMissile(player->mo, MT_ELECARROW); + player->mo->angle = an; + S_StartSound(player->mo, sfx_xbow); +} + +// +// A_FirePoisonBolt +// villsa [STRIFE] - new codepointer +// + +void A_FirePoisonBolt(player_t* player, pspdef_t* pspr) +{ + angle_t an = player->mo->angle; + int t; + + // haleyjd 09/19/10: Use 5 mul on accuracy here as well + t = P_Random(); + player->mo->angle += (t - P_Random()) << (18 - (player->accuracy * 5 / 100)); + player->ammo[weaponinfo[player->readyweapon].ammo]--; + P_SpawnPlayerMissile(player->mo, MT_POISARROW); + player->mo->angle = an; + S_StartSound(player->mo, sfx_xbow); +} + +// +// P_BulletSlope +// Sets a slope so a near miss is at aproximately +// the height of the intended target +// +// haleyjd 09/06/10 [STRIFE] Modified with a little target hack... +// +fixed_t bulletslope; + + +void P_BulletSlope (mobj_t *mo) +{ + angle_t an; + + // see which target is to be aimed at + an = mo->angle; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + + if (!linetarget) + { + an += 1<<26; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + if (!linetarget) + { + an -= 2<<26; + bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + } + } + + // haleyjd 09/06/10: [STRIFE] Somebody added this here, and without it, you + // will get spurious crashing in routines such as P_LookForPlayers! + if(linetarget) + mo->target = linetarget; +} + + +// +// P_GunShot +// +// [STRIFE] Modifications to support accuracy. +// +void +P_GunShot +( mobj_t* mo, + boolean accurate ) +{ + angle_t angle; + int damage; + + angle = mo->angle; + + // villsa [STRIFE] apply player accuracy + // haleyjd 09/18/10: made some corrections: use 5x accuracy; + // eliminated order-of-evaluation dependency + if (!accurate) + { + int t = P_Random(); + angle += (t - P_Random()) << (20 - ((mo->player->accuracy * 5) / 100)); + } + + // haleyjd 09/18/10 [STRIFE] corrected damage formula and moved down to + // preserve proper P_Random call order. + damage = 4 * (P_Random() % 3 + 1); + + P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage); +} + +// +// A_FireRifle +// +// villsa [STRIFE] - new codepointer +// +void A_FireRifle(player_t* player, pspdef_t* pspr) +{ + S_StartSound(player->mo, sfx_rifle); + + if(player->ammo[weaponinfo[player->readyweapon].ammo]) + { + P_SetMobjState(player->mo, S_PLAY_06); // 293 + player->ammo[weaponinfo[player->readyweapon].ammo]--; + P_BulletSlope(player->mo); + P_GunShot(player->mo, !player->refire); + } +} + +// +// A_FireMauler1 +// +// villsa [STRIFE] - new codepointer +// +void A_FireMauler1(player_t* player, pspdef_t* pspr) +{ + int i; + angle_t angle; + int damage; + + // haleyjd 09/18/10: Corrected ammo check to use >= + if(player->ammo[weaponinfo[player->readyweapon].ammo] >= 20) + { + player->ammo[weaponinfo[player->readyweapon].ammo] -= 20; + P_BulletSlope(player->mo); + S_StartSound(player->mo, sfx_pgrdat); + + for(i = 0; i < 20; i++) + { + int t; + damage = 5*(P_Random ()%3+1); + angle = player->mo->angle; + t = P_Random(); + angle += (t - P_Random()) << 19; + t = P_Random(); + P_LineAttack(player->mo, angle, 2112*FRACUNIT, + bulletslope + ((t - P_Random())<<5), damage); + } + } +} + +// +// A_SigilSound +// +// villsa [STRIFE] - new codepointer +// +void A_SigilSound(player_t* player, pspdef_t* pspr) +{ + S_StartSound(player->mo, sfx_siglup); + player->extralight = 2; + +} + +// +// A_FireSigil +// +// villsa [STRIFE] - new codepointer +// +void A_FireSigil(player_t* player, pspdef_t* pspr) +{ + mobj_t* mo; + angle_t an; + int i; + + // keep info on armor because sigil does piercing damage + i = player->armortype; + player->armortype = 0; + + // BUG: setting inflictor causes firing the Sigil to always push the player + // toward the east, no matter what direction he is facing. + P_DamageMobj(player->mo, player->mo, NULL, 4 * (player->sigiltype + 1)); + + // restore armor + player->armortype = i; + + S_StartSound(player->mo, sfx_siglup); + + switch(player->sigiltype) + { + // falling lightning bolts from the sky + case 0: + P_BulletSlope(player->mo); + if(linetarget) + { + // haleyjd 09/18/10: corrected z coordinate + mo = P_SpawnMobj(linetarget->x, linetarget->y, ONFLOORZ, + MT_SIGIL_A_GROUND); + mo->tracer = linetarget; + } + else + { + an = player->mo->angle>>ANGLETOFINESHIFT; + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, + MT_SIGIL_A_GROUND); + mo->momx += FixedMul((28*FRACUNIT), finecosine[an]); + mo->momy += FixedMul((28*FRACUNIT), finesine[an]); + } + mo->health = -1; + mo->target = player->mo; + break; + + // simple projectile + case 1: + P_SpawnPlayerMissile(player->mo, MT_SIGIL_B_SHOT)->health = -1; + break; + + // spread shot + case 2: + player->mo->angle -= ANG90; // starting at 270... + for(i = 0; i < 20; i++) // increment by 1/10 of 90, 20 times. + { + player->mo->angle += (ANG90 / 10); + mo = P_SpawnMortar(player->mo, MT_SIGIL_C_SHOT); + mo->health = -1; + mo->z = player->mo->z + (32*FRACUNIT); + } + player->mo->angle -= ANG90; // subtract off the extra 90 + break; + + // tracer attack + case 3: + P_BulletSlope(player->mo); + if(linetarget) + { + mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_D_SHOT); + mo->tracer = linetarget; + } + else + { + an = player->mo->angle >> ANGLETOFINESHIFT; + mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_D_SHOT); + mo->momx += FixedMul(mo->info->speed, finecosine[an]); + mo->momy += FixedMul(mo->info->speed, finesine[an]); + } + mo->health = -1; + break; + + // mega blast + case 4: + mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_E_SHOT); + mo->health = -1; + if(!linetarget) + { + an = (unsigned int)player->pitch >> ANGLETOFINESHIFT; + mo->momz += FixedMul(finesine[an], mo->info->speed); + } + break; + + default: + break; + } +} + +// +// A_GunFlashThinker +// +// villsa [STRIFE] - new codepointer +// +void A_GunFlashThinker(player_t* player, pspdef_t* pspr) +{ + if(player->readyweapon == wp_sigil && player->sigiltype) + P_SetPsprite(player, ps_flash, S_SIGH_00 + player->sigiltype); + else + P_SetPsprite(player, ps_flash, S_NULL); + +} + + +// +// ? +// +void A_Light0 (player_t *player, pspdef_t *psp) +{ + player->extralight = 0; +} + +void A_Light1 (player_t *player, pspdef_t *psp) +{ + player->extralight = 1; +} + +void A_Light2 (player_t *player, pspdef_t *psp) +{ + player->extralight = 2; +} + +// +// A_SigilShock +// +// villsa [STRIFE] - new codepointer +// +void A_SigilShock (player_t *player, pspdef_t *psp) +{ + player->extralight = -3; +} + +// +// A_TorpedoExplode +// +// villsa [STRIFE] - new codepointer +// +void A_TorpedoExplode(mobj_t* actor) +{ + int i; + + actor->angle -= ANG180; + + for(i = 0; i < 80; i++) + { + actor->angle += (ANG90 / 20); + P_SpawnMortar(actor, MT_TORPEDOSPREAD)->target = actor->target; + } +} + +// +// A_MaulerSound +// +// villsa [STRIFE] - new codepointer +// +void A_MaulerSound(player_t *player, pspdef_t *psp) +{ + int t; + S_StartSound(player->mo, sfx_proton); + t = P_Random(); + psp->sx += (t - P_Random()) << 10; + t = P_Random(); + psp->sy += (t - P_Random()) << 10; + +} + + +// +// P_SetupPsprites +// Called at start of level for each player. +// +void P_SetupPsprites(player_t* player) +{ + int i; + + // remove all psprites + for(i = 0; i < NUMPSPRITES; i++) + player->psprites[i].state = NULL; + + // spawn the gun + player->pendingweapon = player->readyweapon; + P_BringUpWeapon(player); +} + + + + +// +// P_MovePsprites +// Called every tic by player thinking routine. +// +void P_MovePsprites (player_t* player) +{ + int i; + pspdef_t* psp; + + psp = &player->psprites[0]; + for(i = 0; i < NUMPSPRITES; i++, psp++) + { + // a null state means not active + if(psp->state) + { + // drop tic count and possibly change state + + // a -1 tic count never changes + if(psp->tics != -1) + { + psp->tics--; + if(!psp->tics) + P_SetPsprite (player, i, psp->state->nextstate); + } + } + } + + player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; + player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; + + // villsa [STRIFE] extra stuff for targeter + player->psprites[ps_targleft].sx = + (160*FRACUNIT) - ((100 - player->accuracy) << FRACBITS); + + player->psprites[ps_targright].sx = + ((100 - player->accuracy) << FRACBITS) + (160*FRACUNIT); +} + + diff --git a/games/NXDoom/src/strife/p_pspr.h b/games/NXDoom/src/strife/p_pspr.h new file mode 100644 index 00000000000..ec4d13700e6 --- /dev/null +++ b/games/NXDoom/src/strife/p_pspr.h @@ -0,0 +1,86 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Sprite animation. +// + + +#ifndef __P_PSPR__ +#define __P_PSPR__ + +// Basic data types. +// Needs fixed point, and BAM angles. +#include "m_fixed.h" +#include "p_mobj.h" +#include "tables.h" + + +// +// Needs to include the precompiled +// sprite animation tables. +// Header generated by multigen utility. +// This includes all the data for thing animation, +// i.e. the Thing Atrributes table +// and the Frame Sequence table. +#include "info.h" + + + +// +// Frame flags: +// handles maximum brightness (torches, muzzle flare, light sources) +// +#define FF_FULLBRIGHT 0x8000 // flag in thing->frame +#define FF_FRAMEMASK 0x7fff + + + +// +// Overlay psprites are scaled shapes +// drawn directly on the view screen, +// coordinates are given for a 320*200 view screen. +// +typedef enum +{ + ps_weapon, + ps_flash, + ps_targcenter, // villsa [STRIFE] + ps_targleft, // villsa [STRIFE] + ps_targright, // villsa [STRIFE] + NUMPSPRITES + +} psprnum_t; + +typedef struct +{ + state_t* state; // a NULL state means not active + int tics; + fixed_t sx; + fixed_t sy; + +} pspdef_t; + +typedef struct player_s *playerptr; + + +extern fixed_t bulletslope; + + +// haleyjd [STRIFE] Exported +void P_SetPsprite(playerptr player, int position, statenum_t stnum); +void P_BulletSlope(mobj_t *mo); + + +#endif diff --git a/games/NXDoom/src/strife/p_saveg.c b/games/NXDoom/src/strife/p_saveg.c new file mode 100644 index 00000000000..f1782c1e511 --- /dev/null +++ b/games/NXDoom/src/strife/p_saveg.c @@ -0,0 +1,2208 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Archiving: SaveGame I/O. +// + + +#include +#include + +#include "dstrings.h" +#include "deh_main.h" +#include "i_system.h" +#include "z_zone.h" +#include "m_misc.h" +#include "p_local.h" +#include "p_saveg.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +#define SAVEGAME_EOF 0x1d + +// haleyjd 09/28/10: [STRIFE] VERSIONSIZE == 8 +#define VERSIONSIZE 8 + +FILE *save_stream; +int savegamelength; +boolean savegame_error; + +// Get the filename of a temporary file to write the savegame to. After +// the file has been successfully saved, it will be renamed to the +// real file. + +char *P_TempSaveGameFile(void) +{ + static char *filename = NULL; + + if (filename == NULL) + { + filename = M_StringJoin(savegamedir, "temp.dsg", NULL); + } + + return filename; +} + +// Get the filename of the save game file to use for the specified slot. + +char *P_SaveGameFile(int slot) +{ + static char *filename = NULL; + static size_t filename_size; + char basename[32]; + + if (filename == NULL) + { + filename_size = strlen(savegamedir) + 32; + filename = malloc(filename_size); + } + + DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot); + + M_snprintf(filename, filename_size, "%s%s", savegamedir, basename); + + return filename; +} + +// Endian-safe integer read/write functions + +static byte saveg_read8(void) +{ + byte result; + + if (fread(&result, 1, 1, save_stream) < 1) + { + if (!savegame_error) + { + fprintf(stderr, "saveg_read8: Unexpected end of file while " + "reading save game\n"); + + savegame_error = true; + } + } + + return result; +} + +static void saveg_write8(byte value) +{ + if (fwrite(&value, 1, 1, save_stream) < 1) + { + if (!savegame_error) + { + fprintf(stderr, "saveg_write8: Error while writing save game\n"); + + savegame_error = true; + } + } +} + +static short saveg_read16(void) +{ + int result; + + result = saveg_read8(); + result |= saveg_read8() << 8; + + return result; +} + +static void saveg_write16(short value) +{ + saveg_write8(value & 0xff); + saveg_write8((value >> 8) & 0xff); +} + +static int saveg_read32(void) +{ + int result; + + result = saveg_read8(); + result |= saveg_read8() << 8; + result |= saveg_read8() << 16; + result |= saveg_read8() << 24; + + return result; +} + +static void saveg_write32(int value) +{ + saveg_write8(value & 0xff); + saveg_write8((value >> 8) & 0xff); + saveg_write8((value >> 16) & 0xff); + saveg_write8((value >> 24) & 0xff); +} + +// Pad to 4-byte boundaries + +static void saveg_read_pad(void) +{ + unsigned long pos; + int padding; + int i; + + pos = ftell(save_stream); + + padding = (4 - (pos & 3)) & 3; + + for (i=0; ix = saveg_read16(); + + // short y; + str->y = saveg_read16(); + + // short angle; + str->angle = saveg_read16(); + + // short type; + str->type = saveg_read16(); + + // short options; + str->options = saveg_read16(); +} + +static void saveg_write_mapthing_t(mapthing_t *str) +{ + // short x; + saveg_write16(str->x); + + // short y; + saveg_write16(str->y); + + // short angle; + saveg_write16(str->angle); + + // short type; + saveg_write16(str->type); + + // short options; + saveg_write16(str->options); +} + +// +// actionf_t +// + +static void saveg_read_actionf_t(actionf_t *str) +{ + // actionf_p1 acp1; + str->acp1 = saveg_readp(); +} + +static void saveg_write_actionf_t(actionf_t *str) +{ + // actionf_p1 acp1; + saveg_writep(str->acp1); +} + +// +// think_t +// +// This is just an actionf_t. +// + +#define saveg_read_think_t saveg_read_actionf_t +#define saveg_write_think_t saveg_write_actionf_t + +// +// thinker_t +// + +static void saveg_read_thinker_t(thinker_t *str) +{ + // struct thinker_s* prev; + str->prev = saveg_readp(); + + // struct thinker_s* next; + str->next = saveg_readp(); + + // think_t function; + saveg_read_think_t(&str->function); +} + +static void saveg_write_thinker_t(thinker_t *str) +{ + // struct thinker_s* prev; + saveg_writep(str->prev); + + // struct thinker_s* next; + saveg_writep(str->next); + + // think_t function; + saveg_write_think_t(&str->function); +} + +// +// mobj_t +// +// haleyjd 09/28/10: [STRIFE] Changed to match Strife binary mobj_t structure. +// + +static void saveg_read_mobj_t(mobj_t *str) +{ + int pl; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // fixed_t x; + str->x = saveg_read32(); + + // fixed_t y; + str->y = saveg_read32(); + + // fixed_t z; + str->z = saveg_read32(); + + // struct mobj_s* snext; + str->snext = saveg_readp(); + + // struct mobj_s* sprev; + str->sprev = saveg_readp(); + + // angle_t angle; + str->angle = saveg_read32(); + + // spritenum_t sprite; + str->sprite = saveg_read_enum(); + + // int frame; + str->frame = saveg_read32(); + + // struct mobj_s* bnext; + str->bnext = saveg_readp(); + + // struct mobj_s* bprev; + str->bprev = saveg_readp(); + + // struct subsector_s* subsector; + str->subsector = saveg_readp(); + + // fixed_t floorz; + str->floorz = saveg_read32(); + + // fixed_t ceilingz; + str->ceilingz = saveg_read32(); + + // fixed_t radius; + str->radius = saveg_read32(); + + // fixed_t height; + str->height = saveg_read32(); + + // fixed_t momx; + str->momx = saveg_read32(); + + // fixed_t momy; + str->momy = saveg_read32(); + + // fixed_t momz; + str->momz = saveg_read32(); + + // int validcount; + str->validcount = saveg_read32(); + + // mobjtype_t type; + str->type = saveg_read_enum(); + + // mobjinfo_t* info; + str->info = saveg_readp(); + + // int tics; + str->tics = saveg_read32(); + + // state_t* state; + str->state = &states[saveg_read32()]; + + // int flags; + str->flags = saveg_read32(); + + // int health; + str->health = saveg_read32(); + + // int movedir; + str->movedir = saveg_read32(); + + // int movecount; + str->movecount = saveg_read32(); + + // struct mobj_s* target; + str->target = saveg_readp(); + + // int reactiontime; + str->reactiontime = saveg_read32(); + + // int threshold; + str->threshold = saveg_read32(); + + // struct player_s* player; + pl = saveg_read32(); + + if (pl > 0) + { + str->player = &players[pl - 1]; + str->player->mo = str; + } + else + { + str->player = NULL; + } + + // int lastlook; + str->lastlook = saveg_read32(); + + // mapthing_t spawnpoint; + saveg_read_mapthing_t(&str->spawnpoint); + + // struct mobj_s* tracer; + str->tracer = saveg_readp(); + + // byte miscdata; + str->miscdata = saveg_read8(); // [STRIFE] Only change to mobj_t. +} + +static void saveg_write_mobj_t(mobj_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // fixed_t x; + saveg_write32(str->x); + + // fixed_t y; + saveg_write32(str->y); + + // fixed_t z; + saveg_write32(str->z); + + // struct mobj_s* snext; + saveg_writep(str->snext); + + // struct mobj_s* sprev; + saveg_writep(str->sprev); + + // angle_t angle; + saveg_write32(str->angle); + + // spritenum_t sprite; + saveg_write_enum(str->sprite); + + // int frame; + saveg_write32(str->frame); + + // struct mobj_s* bnext; + saveg_writep(str->bnext); + + // struct mobj_s* bprev; + saveg_writep(str->bprev); + + // struct subsector_s* subsector; + saveg_writep(str->subsector); + + // fixed_t floorz; + saveg_write32(str->floorz); + + // fixed_t ceilingz; + saveg_write32(str->ceilingz); + + // fixed_t radius; + saveg_write32(str->radius); + + // fixed_t height; + saveg_write32(str->height); + + // fixed_t momx; + saveg_write32(str->momx); + + // fixed_t momy; + saveg_write32(str->momy); + + // fixed_t momz; + saveg_write32(str->momz); + + // int validcount; + saveg_write32(str->validcount); + + // mobjtype_t type; + saveg_write_enum(str->type); + + // mobjinfo_t* info; + saveg_writep(str->info); + + // int tics; + saveg_write32(str->tics); + + // state_t* state; + saveg_write32(str->state - states); + + // int flags; + saveg_write32(str->flags); + + // int health; + saveg_write32(str->health); + + // int movedir; + saveg_write32(str->movedir); + + // int movecount; + saveg_write32(str->movecount); + + // struct mobj_s* target; + saveg_writep(str->target); + + // int reactiontime; + saveg_write32(str->reactiontime); + + // int threshold; + saveg_write32(str->threshold); + + // struct player_s* player; + if (str->player) + { + saveg_write32(str->player - players + 1); + } + else + { + saveg_write32(0); + } + + // int lastlook; + saveg_write32(str->lastlook); + + // mapthing_t spawnpoint; + saveg_write_mapthing_t(&str->spawnpoint); + + // struct mobj_s* tracer; + saveg_writep(str->tracer); + + // byte miscdata; + saveg_write8(str->miscdata); // [STRIFE] Only change to mobj_t. +} + + +// +// ticcmd_t +// +// haleyjd 09/28/10: [STRIFE] Modified for Strife binary ticcmd_t structure. +// + +static void saveg_read_ticcmd_t(ticcmd_t *str) +{ + // signed char forwardmove; + str->forwardmove = saveg_read8(); + + // signed char sidemove; + str->sidemove = saveg_read8(); + + // short angleturn; + str->angleturn = saveg_read16(); + + // short consistancy; + // STRIFE-FIXME: throwing away top byte of consistancy until + // the true Strife ticcmd_t structure is available. + str->consistancy = (byte)saveg_read16(); + + // byte chatchar; + str->chatchar = saveg_read8(); + + // byte buttons; + str->buttons = saveg_read8(); + + // byte buttons2; + str->buttons2 = saveg_read8(); // [STRIFE] + + // int inventory; + str->inventory = saveg_read32(); // [STRIFE] +} + +static void saveg_write_ticcmd_t(ticcmd_t *str) +{ + // signed char forwardmove; + saveg_write8(str->forwardmove); + + // signed char sidemove; + saveg_write8(str->sidemove); + + // short angleturn; + saveg_write16(str->angleturn); + + // short consistancy; + saveg_write16(str->consistancy); + + // byte chatchar; + saveg_write8(str->chatchar); + + // byte buttons; + saveg_write8(str->buttons); + + // byte buttons2; + saveg_write8(str->buttons2); // [STRIFE] + + // int inventory; + saveg_write32(str->inventory); // [STRIFE] +} + +// +// pspdef_t +// + +static void saveg_read_pspdef_t(pspdef_t *str) +{ + int state; + + // state_t* state; + state = saveg_read32(); + + if (state > 0) + { + str->state = &states[state]; + } + else + { + str->state = NULL; + } + + // int tics; + str->tics = saveg_read32(); + + // fixed_t sx; + str->sx = saveg_read32(); + + // fixed_t sy; + str->sy = saveg_read32(); +} + +static void saveg_write_pspdef_t(pspdef_t *str) +{ + // state_t* state; + if (str->state) + { + saveg_write32(str->state - states); + } + else + { + saveg_write32(0); + } + + // int tics; + saveg_write32(str->tics); + + // fixed_t sx; + saveg_write32(str->sx); + + // fixed_t sy; + saveg_write32(str->sy); +} + +// +// inventory_t +// +// haleyjd 09/28/10: [STRIFE] handle inventory input/output +// + +static void saveg_read_inventory_t(inventory_t *str) +{ + //int sprite; + str->sprite = saveg_read32(); + + //int type; + str->type = saveg_read32(); + + //int amount; + str->amount = saveg_read32(); +} + +static void saveg_write_inventory_t(inventory_t *str) +{ + saveg_write32(str->sprite); + saveg_write32(str->type); + saveg_write32(str->amount); +} + +// +// player_t +// +// haleyjd 09/28/10: [STRIFE] Modified for Strife binary player_t structure. +// + +static void saveg_read_player_t(player_t *str) +{ + int i; + + // mobj_t* mo; + str->mo = saveg_readp(); + + // playerstate_t playerstate; + str->playerstate = saveg_read_enum(); + + // ticcmd_t cmd; + saveg_read_ticcmd_t(&str->cmd); + + // fixed_t viewz; + str->viewz = saveg_read32(); + + // fixed_t viewheight; + str->viewheight = saveg_read32(); + + // fixed_t deltaviewheight; + str->deltaviewheight = saveg_read32(); + + // fixed_t bob; + str->bob = saveg_read32(); + + // int health; + str->health = saveg_read32(); + + // int armorpoints; + str->armorpoints = saveg_read16(); // [STRIFE] 32 -> 16 + + // int armortype; + str->armortype = saveg_read16(); // [STRIFE] 32 -> 16 + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i] = saveg_read32(); + } + + // int sigiltype; + str->sigiltype = saveg_read32(); // [STRIFE] + + // int nukagecount; + str->nukagecount = saveg_read32(); // [STRIFE] + + // int questflags; + str->questflags = saveg_read32(); // [STRIFE] + + // int pitch; + str->pitch = saveg_read32(); // [STRIFE] + + // int centerview; + str->centerview = saveg_read32(); // [STRIFE] + + // inventory_t inventory[NUMINVENTORY]; + for(i = 0; i < NUMINVENTORY; i++) + { + saveg_read_inventory_t(&(str->inventory[i])); // [STRIFE] + } + + // int st_update; + str->st_update = saveg_read32(); // [STRIFE] + + // short numinventory; + str->numinventory = saveg_read16(); // [STRIFE] + + // short inventorycursor; + str->inventorycursor = saveg_read16(); // [STRIFE] + + // short accuracy; + str->accuracy = saveg_read16(); // [STRIFE] + + // short stamina; + str->stamina = saveg_read16(); // [STRIFE] + + // boolean cards[NUMCARDS]; + for (i=0; icards[i] = saveg_read32(); + } + + // boolean backpack; + str->backpack = saveg_read32(); + + // int attackdown; + str->attackdown = saveg_read32(); + + // int usedown; + str->usedown = saveg_read32(); + + // int inventorydown; + str->inventorydown = saveg_read32(); // [STRIFE] + + // int frags[MAXPLAYERS]; + for (i=0; ifrags[i] = saveg_read32(); + } + + // weapontype_t readyweapon; + str->readyweapon = saveg_read_enum(); + + // weapontype_t pendingweapon; + str->pendingweapon = saveg_read_enum(); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i] = saveg_read32(); + } + + // int ammo[NUMAMMO]; + for (i=0; iammo[i] = saveg_read32(); + } + + // int maxammo[NUMAMMO]; + for (i=0; imaxammo[i] = saveg_read32(); + } + + // int cheats; + str->cheats = saveg_read32(); + + // int refire; + str->refire = saveg_read32(); + + // short killcount; + str->killcount = saveg_read16(); // [STRIFE] 32 -> 16 + + // haleyjd 08/30/10 [STRIFE] No itemcount. + // int itemcount; + //str->itemcount = saveg_read32(); + + // haleyjd 08/30/10 [STRIFE] No secretcount. + // int secretcount; + //str->secretcount = saveg_read32(); + + // char* message; + str->message = saveg_readp(); + + // int damagecount; + str->damagecount = saveg_read32(); + + // int bonuscount; + str->bonuscount = saveg_read32(); + + // mobj_t* attacker; + str->attacker = saveg_readp(); + + // int extralight; + str->extralight = saveg_read32(); + + // int fixedcolormap; + str->fixedcolormap = saveg_read32(); + + // int colormap; - [STRIFE] no such field + //str->colormap = saveg_read32(); + + // short allegiance; + str->allegiance = saveg_read16(); // [STRIFE] + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // int mapstate[40]; + for(i = 0; i < 40; ++i) // [STRIFE] + { + str->mapstate[i] = saveg_read32(); + } + + // haleyjd 08/30/10: [STRIFE] No intermission, no didsecret. + // boolean didsecret; + //str->didsecret = saveg_read32(); +} + +static void saveg_write_player_t(player_t *str) +{ + int i; + + // mobj_t* mo; + saveg_writep(str->mo); + + // playerstate_t playerstate; + saveg_write_enum(str->playerstate); + + // ticcmd_t cmd; + saveg_write_ticcmd_t(&str->cmd); + + // fixed_t viewz; + saveg_write32(str->viewz); + + // fixed_t viewheight; + saveg_write32(str->viewheight); + + // fixed_t deltaviewheight; + saveg_write32(str->deltaviewheight); + + // fixed_t bob; + saveg_write32(str->bob); + + // int health; + saveg_write32(str->health); + + // int armorpoints; + saveg_write16(str->armorpoints); // [STRIFE] 32 -> 16 + + // int armortype; + saveg_write16(str->armortype); // [STRIFE] 32 -> 16 + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i]); + } + + // int sigiltype; + saveg_write32(str->sigiltype); // [STRIFE] + + // int nukagecount; + saveg_write32(str->nukagecount); // [STRIFE] + + // int questflags; + saveg_write32(str->questflags); // [STRIFE] + + // int pitch; + saveg_write32(str->pitch); // [STRIFE] + + // int centerview; + saveg_write32(str->centerview); // [STRIFE] + + // inventory_t inventory[NUMINVENTORY]; + for(i = 0; i < NUMINVENTORY; ++i) // [STRIFE] + { + saveg_write_inventory_t(&str->inventory[i]); + } + + // int st_update; + saveg_write32(str->st_update); // [STRIFE] + + // short numinventory; + saveg_write16(str->numinventory); // [STRIFE] + + // short inventorycursor; + saveg_write16(str->inventorycursor); // [STRIFE] + + // short accuracy; + saveg_write16(str->accuracy); // [STRIFE] + + // short stamina; + saveg_write16(str->stamina); // [STRIFE] + + // boolean cards[NUMCARDS]; + for (i=0; icards[i]); + } + + // boolean backpack; + saveg_write32(str->backpack); + + // int attackdown; + saveg_write32(str->attackdown); + + // int usedown; + saveg_write32(str->usedown); + + // int inventorydown; + saveg_write32(str->inventorydown); // [STRIFE] + + // int frags[MAXPLAYERS]; + for (i=0; ifrags[i]); + } + + // weapontype_t readyweapon; + saveg_write_enum(str->readyweapon); + + // weapontype_t pendingweapon; + saveg_write_enum(str->pendingweapon); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i]); + } + + // int ammo[NUMAMMO]; + for (i=0; iammo[i]); + } + + // int maxammo[NUMAMMO]; + for (i=0; imaxammo[i]); + } + + + // int cheats; + saveg_write32(str->cheats); + + // int refire; + saveg_write32(str->refire); + + // short killcount; + saveg_write16(str->killcount); // [STRIFE] 32 -> 16 + + // haleyjd 08/30/10 [STRIFE] No itemcount + // int itemcount; + //saveg_write32(str->itemcount); + + // haleyjd 08/30/10 [STRIFE] No secretcount + // int secretcount; + //saveg_write32(str->secretcount); + + // char* message; + saveg_writep(str->message); + + // int damagecount; + saveg_write32(str->damagecount); + + // int bonuscount; + saveg_write32(str->bonuscount); + + // mobj_t* attacker; + saveg_writep(str->attacker); + + // int extralight; + saveg_write32(str->extralight); + + // int fixedcolormap; + saveg_write32(str->fixedcolormap); + + // int colormap; [STRIFE] no such field + //saveg_write32(str->colormap); + + // short allegiance; + saveg_write16(str->allegiance); // [STRIFE] + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // int mapstate[40]; + for(i = 0; i < 40; ++i) // [STRIFE] + { + saveg_write32(str->mapstate[i]); + } + + // haleyjd 08/30/10: [STRIFE] No intermission, no secret. + // boolean didsecret; + //saveg_write32(str->didsecret); +} + + +// +// ceiling_t +// + +static void saveg_read_ceiling_t(ceiling_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // ceiling_e type; + str->type = saveg_read_enum(); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // fixed_t bottomheight; + str->bottomheight = saveg_read32(); + + // fixed_t topheight; + str->topheight = saveg_read32(); + + // fixed_t speed; + str->speed = saveg_read32(); + + // boolean crush; + str->crush = saveg_read32(); + + // int direction; + str->direction = saveg_read32(); + + // int tag; + str->tag = saveg_read32(); + + // int olddirection; + str->olddirection = saveg_read32(); +} + +static void saveg_write_ceiling_t(ceiling_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // ceiling_e type; + saveg_write_enum(str->type); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // fixed_t bottomheight; + saveg_write32(str->bottomheight); + + // fixed_t topheight; + saveg_write32(str->topheight); + + // fixed_t speed; + saveg_write32(str->speed); + + // boolean crush; + saveg_write32(str->crush); + + // int direction; + saveg_write32(str->direction); + + // int tag; + saveg_write32(str->tag); + + // int olddirection; + saveg_write32(str->olddirection); +} + +// +// vldoor_t +// +// haleyjd 09/28/10: [STRIFE] Modified for Strife binary vldoor_t structure. +// + +static void saveg_read_vldoor_t(vldoor_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // vldoor_e type; + str->type = saveg_read_enum(); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // fixed_t topheight; + str->topheight = saveg_read32(); + + // fixed_t speed; + str->speed = saveg_read32(); + + // int direction; + str->direction = saveg_read32(); + + // int topwait; + str->topwait = saveg_read32(); + + // int topcountdown; + str->topcountdown = saveg_read32(); + + // villsa [STRIFE] new field - sound to play when opening + //int opensound; + str->opensound = saveg_read32(); + + // villsa [STRIFE] new field - sound to play when closing + //int closesound; + str->closesound = saveg_read32(); +} + +static void saveg_write_vldoor_t(vldoor_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // vldoor_e type; + saveg_write_enum(str->type); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // fixed_t topheight; + saveg_write32(str->topheight); + + // fixed_t speed; + saveg_write32(str->speed); + + // int direction; + saveg_write32(str->direction); + + // int topwait; + saveg_write32(str->topwait); + + // int topcountdown; + saveg_write32(str->topcountdown); + + // villsa [STRIFE] new field - sound to play when opening + //int opensound; + saveg_write32(str->opensound); + + // villsa [STRIFE] new field - sound to play when closing + //int closesound; + saveg_write32(str->closesound); +} + +// +// slidedoor_t [STRIFE]: new thinker type +// + +static void saveg_read_slidedoor_t(slidedoor_t *str) +{ + int sector; + int line; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sdt_e type; + str->type = saveg_read_enum(); + + // line_t *line1; + line = saveg_read32(); + str->line1 = &lines[line]; + + // line_t *line2; + line = saveg_read32(); + str->line2 = &lines[line]; + + // int frame; + str->frame = saveg_read32(); + + // int whichDoorIndex; + str->whichDoorIndex = saveg_read32(); + + // int timer; + str->timer = saveg_read32(); + + // sector_t *frontsector; + sector = saveg_read32(); + str->frontsector = §ors[sector]; + + // sd_e status; + str->status = saveg_read_enum(); +} + +static void saveg_write_slidedoor_t(slidedoor_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sdt_e type; + saveg_write_enum(str->type); + + // line_t *line1; + saveg_write32(str->line1 - lines); + + // line_t *line2; + saveg_write32(str->line2 - lines); + + // int frame; + saveg_write32(str->frame); + + // int whichDoorIndex; + saveg_write32(str->whichDoorIndex); + + // int timer; + saveg_write32(str->timer); + + // sector_t *frontsector; + saveg_write32(str->frontsector - sectors); + + // sd_e status; + saveg_write_enum(str->status); +} + +// +// floormove_t +// + +static void saveg_read_floormove_t(floormove_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // floor_e type; + str->type = saveg_read_enum(); + + // boolean crush; + str->crush = saveg_read32(); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int direction; + str->direction = saveg_read32(); + + // int newspecial; + str->newspecial = saveg_read32(); + + // short texture; + str->texture = saveg_read16(); + + // fixed_t floordestheight; + str->floordestheight = saveg_read32(); + + // fixed_t speed; + str->speed = saveg_read32(); +} + +static void saveg_write_floormove_t(floormove_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // floor_e type; + saveg_write_enum(str->type); + + // boolean crush; + saveg_write32(str->crush); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int direction; + saveg_write32(str->direction); + + // int newspecial; + saveg_write32(str->newspecial); + + // short texture; + saveg_write16(str->texture); + + // fixed_t floordestheight; + saveg_write32(str->floordestheight); + + // fixed_t speed; + saveg_write32(str->speed); +} + +// +// plat_t +// + +static void saveg_read_plat_t(plat_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // fixed_t speed; + str->speed = saveg_read32(); + + // fixed_t low; + str->low = saveg_read32(); + + // fixed_t high; + str->high = saveg_read32(); + + // int wait; + str->wait = saveg_read32(); + + // int count; + str->count = saveg_read32(); + + // plat_e status; + str->status = saveg_read_enum(); + + // plat_e oldstatus; + str->oldstatus = saveg_read_enum(); + + // boolean crush; + str->crush = saveg_read32(); + + // int tag; + str->tag = saveg_read32(); + + // plattype_e type; + str->type = saveg_read_enum(); +} + +static void saveg_write_plat_t(plat_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // fixed_t speed; + saveg_write32(str->speed); + + // fixed_t low; + saveg_write32(str->low); + + // fixed_t high; + saveg_write32(str->high); + + // int wait; + saveg_write32(str->wait); + + // int count; + saveg_write32(str->count); + + // plat_e status; + saveg_write_enum(str->status); + + // plat_e oldstatus; + saveg_write_enum(str->oldstatus); + + // boolean crush; + saveg_write32(str->crush); + + // int tag; + saveg_write32(str->tag); + + // plattype_e type; + saveg_write_enum(str->type); +} + +// +// lightflash_t +// + +static void saveg_read_lightflash_t(lightflash_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int count; + str->count = saveg_read32(); + + // int maxlight; + str->maxlight = saveg_read32(); + + // int minlight; + str->minlight = saveg_read32(); + + // int maxtime; + str->maxtime = saveg_read32(); + + // int mintime; + str->mintime = saveg_read32(); +} + +static void saveg_write_lightflash_t(lightflash_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int count; + saveg_write32(str->count); + + // int maxlight; + saveg_write32(str->maxlight); + + // int minlight; + saveg_write32(str->minlight); + + // int maxtime; + saveg_write32(str->maxtime); + + // int mintime; + saveg_write32(str->mintime); +} + +// +// strobe_t +// + +static void saveg_read_strobe_t(strobe_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int count; + str->count = saveg_read32(); + + // int minlight; + str->minlight = saveg_read32(); + + // int maxlight; + str->maxlight = saveg_read32(); + + // int darktime; + str->darktime = saveg_read32(); + + // int brighttime; + str->brighttime = saveg_read32(); +} + +static void saveg_write_strobe_t(strobe_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int count; + saveg_write32(str->count); + + // int minlight; + saveg_write32(str->minlight); + + // int maxlight; + saveg_write32(str->maxlight); + + // int darktime; + saveg_write32(str->darktime); + + // int brighttime; + saveg_write32(str->brighttime); +} + +// +// glow_t +// + +static void saveg_read_glow_t(glow_t *str) +{ + int sector; + + // thinker_t thinker; + saveg_read_thinker_t(&str->thinker); + + // sector_t* sector; + sector = saveg_read32(); + str->sector = §ors[sector]; + + // int minlight; + str->minlight = saveg_read32(); + + // int maxlight; + str->maxlight = saveg_read32(); + + // int direction; + str->direction = saveg_read32(); +} + +static void saveg_write_glow_t(glow_t *str) +{ + // thinker_t thinker; + saveg_write_thinker_t(&str->thinker); + + // sector_t* sector; + saveg_write32(str->sector - sectors); + + // int minlight; + saveg_write32(str->minlight); + + // int maxlight; + saveg_write32(str->maxlight); + + // int direction; + saveg_write32(str->direction); +} + +// +// Write the header for a savegame +// +// haleyjd 09/28/10: [STRIFE] numerous modifications. +// + +void P_WriteSaveGameHeader(char *description) +{ + char name[VERSIONSIZE]; + int i; + + /* + [STRIFE] This is in the "NAME" file in a Strife save directory. + for (i=0; description[i] != '\0'; ++i) + saveg_write8(description[i]); + for (; i> 16) & 0xff); + saveg_write8((leveltime >> 8) & 0xff); + saveg_write8(leveltime & 0xff); +} + +// +// Read the header for a savegame +// + +boolean P_ReadSaveGameHeader(void) +{ + int i; + byte a, b, c; + char vcheck[VERSIONSIZE]; + char read_vcheck[VERSIONSIZE]; + + // skip the description field + /* + for (i=0; ifloorheight >> FRACBITS); + saveg_write16(sec->ceilingheight >> FRACBITS); + saveg_write16(sec->floorpic); + //saveg_write16(sec->ceilingpic); [STRIFE] not saved. + saveg_write16(sec->lightlevel); + saveg_write16(sec->special); // needed? + //saveg_write16(sec->tag); // needed? [STRIFE] not saved. + } + + + // do lines + for (i=0, li = lines ; iflags); + saveg_write16(li->special); + //saveg_write16(li->tag); [STRIFE] not saved. + for (j=0 ; j<2 ; j++) + { + if (li->sidenum[j] == -1) + continue; + + si = &sides[li->sidenum[j]]; + + // [STRIFE] offsets not saved. + //saveg_write16(si->textureoffset >> FRACBITS); + //saveg_write16(si->rowoffset >> FRACBITS); + saveg_write16(si->toptexture); + saveg_write16(si->bottomtexture); + saveg_write16(si->midtexture); + } + } +} + + + +// +// P_UnArchiveWorld +// +void P_UnArchiveWorld (void) +{ + int i; + int j; + sector_t* sec; + line_t* li; + side_t* si; + + // do sectors + for (i=0, sec = sectors ; ifloorheight = saveg_read16() << FRACBITS; + sec->ceilingheight = saveg_read16() << FRACBITS; + sec->floorpic = saveg_read16(); + //sec->ceilingpic = saveg_read16(); [STRIFE] not saved + sec->lightlevel = saveg_read16(); + sec->special = saveg_read16(); // needed? + //sec->tag = saveg_read16(); // needed? [STRIFE] not saved + sec->specialdata = 0; + sec->soundtarget = 0; + } + + // do lines + for (i=0, li = lines ; iflags = saveg_read16(); + li->special = saveg_read16(); + //li->tag = saveg_read16(); [STRIFE] not saved + for (j=0 ; j<2 ; j++) + { + if (li->sidenum[j] == -1) + continue; + si = &sides[li->sidenum[j]]; + // [STRIFE] offsets not saved. + //si->textureoffset = saveg_read16() << FRACBITS; + //si->rowoffset = saveg_read16() << FRACBITS; + si->toptexture = saveg_read16(); + si->bottomtexture = saveg_read16(); + si->midtexture = saveg_read16(); + } + } +} + + + + + +// +// Thinkers +// +typedef enum +{ + tc_end, + tc_mobj + +} thinkerclass_t; + + +// +// P_ArchiveThinkers +// +// [STRIFE] Verified unmodified. +// +void P_ArchiveThinkers (void) +{ + thinker_t* th; + + // save off the current thinkers + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + { + saveg_write8(tc_mobj); + saveg_write_pad(); + saveg_write_mobj_t((mobj_t *) th); + + continue; + } + + // haleyjd: This may seem mysterious but in the DOOM prebeta, + // different types of things used different thinker functions. + // Those would have all been handled here and this message is + // probably a relic of that old system, not to mention the odd + // name of this function, and use of an enumeration with only + // two values in it. + + // I_Error ("P_ArchiveThinkers: Unknown thinker function"); + } + + // add a terminating marker + saveg_write8(tc_end); +} + + + +// +// P_UnArchiveThinkers +// +void P_UnArchiveThinkers (void) +{ + byte tclass; + thinker_t* currentthinker; + thinker_t* next; + mobj_t* mobj; + + // remove all the current thinkers + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + next = currentthinker->next; + + if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + P_RemoveMobj ((mobj_t *)currentthinker); + else + Z_Free (currentthinker); + + currentthinker = next; + } + P_InitThinkers (); + + // read in saved thinkers + while (1) + { + tclass = saveg_read8(); + switch (tclass) + { + case tc_end: + return; // end of list + + case tc_mobj: + saveg_read_pad(); + mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); + saveg_read_mobj_t(mobj); + + // haleyjd 09/29/10: Strife sets the targets of non-allied creatures + // who had a non-NULL target at save time to players[0].mo so that + // they won't fall back asleep. + // + // BUG: As the player may not have been spawned yet, we could be + // setting monsters' targets to the mobj which was spawned by + // P_SetupLevel and then removed just above. Due to a subtle glitch + // in the DOOM engine whereby all things removed in this function + // are leaked until the next time P_SetupLevel is called, this is a + // safe operation - the call to P_InitThinkers above stops any of + // the objects removed, including the player's previous body, from + // being passed to Z_Free. One glitch relying on another! + + if(mobj->target != NULL && (mobj->flags & MF_ALLY) != MF_ALLY) + mobj->target = players[0].mo; + else + mobj->target = NULL; + + // WARNING! Strife does not seem to set tracer! I am leaving it be + // for now because so far no crashes have been observed, and failing + // to set this here will almost certainly crash Choco. + mobj->tracer = NULL; + P_SetThingPosition (mobj); + mobj->info = &mobjinfo[mobj->type]; + // [STRIFE]: doesn't set these + //mobj->floorz = mobj->subsector->sector->floorheight; + //mobj->ceilingz = mobj->subsector->sector->ceilingheight; + mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; + P_AddThinker (&mobj->thinker); + break; + + default: + I_Error ("Unknown tclass %i in savegame",tclass); + } + } +} + + +// +// P_ArchiveSpecials +// +enum +{ + tc_ceiling, + tc_door, + tc_floor, + tc_plat, + tc_flash, + tc_strobe, + tc_glow, + tc_slidingdoor, // [STRIFE] + tc_endspecials + +} specials_e; + + + +// +// Things to handle: +// +// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list +// T_VerticalDoor, (vldoor_t: sector_t * swizzle), +// T_SlidingDoor, (slidedoor_t: sector_t *, line_t * x 2 swizzle) [STRIFE] +// T_MoveFloor, (floormove_t: sector_t * swizzle), +// T_LightFlash, (lightflash_t: sector_t * swizzle), +// T_StrobeFlash, (strobe_t: sector_t *), +// T_Glow, (glow_t: sector_t *), +// T_PlatRaise, (plat_t: sector_t *), - active list +// +void P_ArchiveSpecials (void) +{ + thinker_t* th; + int i; + + // save off the current thinkers + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acv == (actionf_v)NULL) + { + for (i = 0; i < MAXCEILINGS;i++) + if (activeceilings[i] == (ceiling_t *)th) + break; + + if (ifunction.acp1 == (actionf_p1)T_MoveCeiling) + { + saveg_write8(tc_ceiling); + saveg_write_pad(); + saveg_write_ceiling_t((ceiling_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_VerticalDoor) + { + saveg_write8(tc_door); + saveg_write_pad(); + saveg_write_vldoor_t((vldoor_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_SlidingDoor) + { + saveg_write8(tc_slidingdoor); + saveg_write_pad(); + saveg_write_slidedoor_t((slidedoor_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_MoveFloor) + { + saveg_write8(tc_floor); + saveg_write_pad(); + saveg_write_floormove_t((floormove_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_PlatRaise) + { + saveg_write8(tc_plat); + saveg_write_pad(); + saveg_write_plat_t((plat_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_LightFlash) + { + saveg_write8(tc_flash); + saveg_write_pad(); + saveg_write_lightflash_t((lightflash_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_StrobeFlash) + { + saveg_write8(tc_strobe); + saveg_write_pad(); + saveg_write_strobe_t((strobe_t *) th); + continue; + } + + if (th->function.acp1 == (actionf_p1)T_Glow) + { + saveg_write8(tc_glow); + saveg_write_pad(); + saveg_write_glow_t((glow_t *) th); + continue; + } + } + + // add a terminating marker + saveg_write8(tc_endspecials); +} + + +// +// P_UnArchiveSpecials +// +void P_UnArchiveSpecials (void) +{ + byte tclass; + ceiling_t* ceiling; + vldoor_t* door; + slidedoor_t* slidedoor; // haleyjd [STRIFE] + floormove_t* floor; + plat_t* plat; + lightflash_t* flash; + strobe_t* strobe; + glow_t* glow; + + + // read in saved thinkers + while (1) + { + tclass = saveg_read8(); + + switch (tclass) + { + case tc_endspecials: + return; // end of list + + case tc_ceiling: + saveg_read_pad(); + ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL); + saveg_read_ceiling_t(ceiling); + ceiling->sector->specialdata = ceiling; + + if (ceiling->thinker.function.acp1) + ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; + + P_AddThinker (&ceiling->thinker); + P_AddActiveCeiling(ceiling); + break; + + case tc_door: + saveg_read_pad(); + door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL); + saveg_read_vldoor_t(door); + door->sector->specialdata = door; + door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; + P_AddThinker (&door->thinker); + break; + + case tc_slidingdoor: + // haleyjd 09/29/10: [STRIFE] New thinker type for sliding doors + saveg_read_pad(); + slidedoor = Z_Malloc(sizeof(*slidedoor), PU_LEVEL, NULL); + saveg_read_slidedoor_t(slidedoor); + slidedoor->frontsector->specialdata = slidedoor; + slidedoor->thinker.function.acp1 = (actionf_p1)T_SlidingDoor; + P_AddThinker(&slidedoor->thinker); + break; + + case tc_floor: + saveg_read_pad(); + floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); + saveg_read_floormove_t(floor); + floor->sector->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; + P_AddThinker (&floor->thinker); + break; + + case tc_plat: + saveg_read_pad(); + plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); + saveg_read_plat_t(plat); + plat->sector->specialdata = plat; + + if (plat->thinker.function.acp1) + plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise; + + P_AddThinker (&plat->thinker); + P_AddActivePlat(plat); + break; + + case tc_flash: + saveg_read_pad(); + flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); + saveg_read_lightflash_t(flash); + flash->thinker.function.acp1 = (actionf_p1)T_LightFlash; + P_AddThinker (&flash->thinker); + break; + + case tc_strobe: + saveg_read_pad(); + strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); + saveg_read_strobe_t(strobe); + strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; + P_AddThinker (&strobe->thinker); + break; + + case tc_glow: + saveg_read_pad(); + glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); + saveg_read_glow_t(glow); + glow->thinker.function.acp1 = (actionf_p1)T_Glow; + P_AddThinker (&glow->thinker); + break; + + default: + I_Error ("P_UnarchiveSpecials:Unknown tclass %i " + "in savegame",tclass); + } + } +} + diff --git a/games/NXDoom/src/strife/p_saveg.h b/games/NXDoom/src/strife/p_saveg.h new file mode 100644 index 00000000000..d36f3b0da91 --- /dev/null +++ b/games/NXDoom/src/strife/p_saveg.h @@ -0,0 +1,62 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Savegame I/O, archiving, persistence. +// + + +#ifndef __P_SAVEG__ +#define __P_SAVEG__ + +#include + +// maximum size of a savegame description + +#define SAVESTRINGSIZE 24 + +// temporary filename to use while saving. + +char *P_TempSaveGameFile(void); + +// filename to use for a savegame slot + +char *P_SaveGameFile(int slot); + +// Savegame file header read/write functions + +boolean P_ReadSaveGameHeader(void); +void P_WriteSaveGameHeader(char *description); + +// Savegame end-of-file read/write functions + +boolean P_ReadSaveGameEOF(void); +void P_WriteSaveGameEOF(void); + +// Persistent storage/archiving. +// These are the load / save game routines. +void P_ArchivePlayers (void); +void P_UnArchivePlayers (boolean userload); +void P_ArchiveWorld (void); +void P_UnArchiveWorld (void); +void P_ArchiveThinkers (void); +void P_UnArchiveThinkers (void); +void P_ArchiveSpecials (void); +void P_UnArchiveSpecials (void); + +extern FILE *save_stream; +extern boolean savegame_error; + + +#endif diff --git a/games/NXDoom/src/strife/p_setup.c b/games/NXDoom/src/strife/p_setup.c new file mode 100644 index 00000000000..d6c3057b56c --- /dev/null +++ b/games/NXDoom/src/strife/p_setup.c @@ -0,0 +1,808 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Do all the WAD I/O, get map description, +// set up initial state and misc. LUTs. +// + + + +#include + +#include "z_zone.h" + +#include "deh_main.h" +#include "i_swap.h" +#include "m_argv.h" +#include "m_bbox.h" + +#include "g_game.h" + +#include "i_system.h" +#include "w_wad.h" + +#include "doomdef.h" +#include "p_local.h" +#include "p_rejectpad.h" + +#include "s_sound.h" + +#include "doomstat.h" + + +void P_SpawnMapThing (mapthing_t* mthing); + + +// +// MAP related Lookup tables. +// Store VERTEXES, LINEDEFS, SIDEDEFS, etc. +// +int numvertexes; +vertex_t* vertexes; + +int numsegs; +seg_t* segs; + +int numsectors; +sector_t* sectors; + +int numsubsectors; +subsector_t* subsectors; + +int numnodes; +node_t* nodes; + +int numlines; +line_t* lines; + +int numsides; +side_t* sides; + +static int totallines; + +// BLOCKMAP +// Created from axis aligned bounding box +// of the map, a rectangular array of +// blocks of size ... +// Used to speed up collision detection +// by spatial subdivision in 2D. +// +// Blockmap size. +int bmapwidth; +int bmapheight; // size in mapblocks +short* blockmap; // int for larger maps +// offsets in blockmap are from here +short* blockmaplump; +// origin of block map +fixed_t bmaporgx; +fixed_t bmaporgy; +// for thing chains +mobj_t** blocklinks; + + +// REJECT +// For fast sight rejection. +// Speeds up enemy AI by skipping detailed +// LineOf Sight calculation. +// Without special effect, this could be +// used as a PVS lookup as well. +// +byte* rejectmatrix; + + +// Maintain single and multi player starting spots. +#define MAX_DEATHMATCH_STARTS 10 + +mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS]; +mapthing_t* deathmatch_p; +mapthing_t playerstarts[MAXPLAYERS]; + +// haleyjd 08/24/10: [STRIFE] rift spots for player spawning +mapthing_t riftSpots[MAXRIFTSPOTS]; + + + + +// +// P_LoadVertexes +// +void P_LoadVertexes (int lump) +{ + byte* data; + int i; + mapvertex_t* ml; + vertex_t* li; + + // Determine number of lumps: + // total lump length / vertex record length. + numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t); + + // Allocate zone memory for buffer. + vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0); + + // Load data into cache. + data = W_CacheLumpNum (lump, PU_STATIC); + + ml = (mapvertex_t *)data; + li = vertexes; + + // Copy and convert vertex coordinates, + // internal representation as fixed. + for (i=0 ; ix = SHORT(ml->x)<y = SHORT(ml->y)<v1 = &vertexes[SHORT(ml->v1)]; + li->v2 = &vertexes[SHORT(ml->v2)]; + + li->angle = (SHORT(ml->angle))<<16; + li->offset = (SHORT(ml->offset))<<16; + linedef = SHORT(ml->linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + side = SHORT(ml->side); + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; + + if (ldef-> flags & ML_TWOSIDED) + { + sidenum = ldef->sidenum[side ^ 1]; + + // If the sidenum is out of range, this may be a "glass hack" + // impassible window. Point at side #0 (this may not be + // the correct Vanilla behavior; however, it seems to work for + // OTTAWAU.WAD, which is the one place I've seen this trick + // used). + + if (sidenum < 0 || sidenum >= numsides) + { + sidenum = 0; + } + + li->backsector = sides[sidenum].sector; + } + else + { + li->backsector = 0; + } + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadSubsectors +// +void P_LoadSubsectors (int lump) +{ + byte* data; + int i; + mapsubsector_t* ms; + subsector_t* ss; + + numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t); + subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0); + data = W_CacheLumpNum (lump,PU_STATIC); + + ms = (mapsubsector_t *)data; + memset (subsectors,0, numsubsectors*sizeof(subsector_t)); + ss = subsectors; + + for (i=0 ; inumlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); + } + + W_ReleaseLumpNum(lump); +} + + + +// +// P_LoadSectors +// +void P_LoadSectors (int lump) +{ + byte* data; + int i; + mapsector_t* ms; + sector_t* ss; + + numsectors = W_LumpLength (lump) / sizeof(mapsector_t); + sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0); + memset (sectors, 0, numsectors*sizeof(sector_t)); + data = W_CacheLumpNum (lump,PU_STATIC); + + ms = (mapsector_t *)data; + ss = sectors; + for (i=0 ; ifloorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = R_FlatNumForName(ms->floorpic); + ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); + ss->lightlevel = SHORT(ms->lightlevel); + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + ss->thinglist = NULL; + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadNodes +// +void P_LoadNodes (int lump) +{ + byte* data; + int i; + int j; + int k; + mapnode_t* mn; + node_t* no; + + numnodes = W_LumpLength (lump) / sizeof(mapnode_t); + nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0); + data = W_CacheLumpNum (lump,PU_STATIC); + + mn = (mapnode_t *)data; + no = nodes; + + for (i=0 ; ix = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); + for (k=0 ; k<4 ; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k])<type)) + { + case 68: // Arachnotron + case 64: // Archvile + case 88: // Boss Brain + case 89: // Boss Shooter + case 69: // Hell Knight + case 67: // Mancubus + case 71: // Pain Elemental + case 65: // Former Human Commando + case 66: // Revenant + case 84: // Wolf SS + spawn = false; + break; + } + } + if (spawn == false) + break; + */ + + // Do spawn all other stuff. + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + spawnthing.options = SHORT(mt->options); + + // haleyjd 08/24/2010: Special Strife checks + if(spawnthing.type >= 118 && spawnthing.type < 128) + { + // initialize riftSpots + int riftSpotNum = spawnthing.type - 118; + riftSpots[riftSpotNum] = spawnthing; + riftSpots[riftSpotNum].type = 1; + } + else if(spawnthing.type >= 9001 && spawnthing.type < 9011) + { + // STRIFE-TODO: mystery array of 90xx objects + } + else + P_SpawnMapThing(&spawnthing); + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadLineDefs +// Also counts secret lines for intermissions. +// +void P_LoadLineDefs (int lump) +{ + byte* data; + int i; + maplinedef_t* mld; + line_t* ld; + vertex_t* v1; + vertex_t* v2; + + numlines = W_LumpLength (lump) / sizeof(maplinedef_t); + lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0); + memset (lines, 0, numlines*sizeof(line_t)); + data = W_CacheLumpNum (lump,PU_STATIC); + + mld = (maplinedef_t *)data; + ld = lines; + for (i=0 ; iflags = SHORT(mld->flags); + ld->special = SHORT(mld->special); + ld->tag = SHORT(mld->tag); + v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; + v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else + { + if (FixedDiv (ld->dy , ld->dx) > 0) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + } + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + + if (ld->sidenum[0] != -1) + ld->frontsector = sides[ld->sidenum[0]].sector; + else + ld->frontsector = 0; + + if (ld->sidenum[1] != -1) + ld->backsector = sides[ld->sidenum[1]].sector; + else + ld->backsector = 0; + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadSideDefs +// +void P_LoadSideDefs (int lump) +{ + byte* data; + int i; + mapsidedef_t* msd; + side_t* sd; + + numsides = W_LumpLength (lump) / sizeof(mapsidedef_t); + sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0); + memset (sides, 0, numsides*sizeof(side_t)); + data = W_CacheLumpNum (lump,PU_STATIC); + + msd = (mapsidedef_t *)data; + sd = sides; + for (i=0 ; itextureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<toptexture = R_TextureNumForName(msd->toptexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->sector = §ors[SHORT(msd->sector)]; + } + + W_ReleaseLumpNum(lump); +} + + +// +// P_LoadBlockMap +// +void P_LoadBlockMap (int lump) +{ + int i; + int count; + int lumplen; + + lumplen = W_LumpLength(lump); + count = lumplen / 2; + + blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); + W_ReadLump(lump, blockmaplump); + blockmap = blockmaplump + 4; + + // Swap all short integers to native byte ordering. + + for (i=0; ifirstline]; + ss->sector = seg->sidedef->sector; + } + + // count number of lines in each sector + li = lines; + totallines = 0; + for (i=0 ; ifrontsector->linecount++; + + if (li->backsector && li->backsector != li->frontsector) + { + li->backsector->linecount++; + totallines++; + } + } + + // build line tables for each sector + linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0); + + for (i=0; ifrontsector != NULL) + { + sector = li->frontsector; + + sector->lines[sector->linecount] = li; + ++sector->linecount; + } + + if (li->backsector != NULL && li->frontsector != li->backsector) + { + sector = li->backsector; + + sector->lines[sector->linecount] = li; + ++sector->linecount; + } + } + + // Generate bounding boxes for sectors + + sector = sectors; + for (i=0 ; ilinecount; j++) + { + li = sector->lines[j]; + + M_AddToBox (bbox, li->v1->x, li->v1->y); + M_AddToBox (bbox, li->v2->x, li->v2->y); + } + + // set the degenmobj_t to the middle of the bounding box + sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2; + sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2; + + // adjust bounding box to map blocks + block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; + block = block >= bmapheight ? bmapheight-1 : block; + sector->blockbox[BOXTOP]=block; + + block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXBOTTOM]=block; + + block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; + block = block >= bmapwidth ? bmapwidth-1 : block; + sector->blockbox[BOXRIGHT]=block; + + block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXLEFT]=block; + } + +} + + +static void P_LoadReject(int lumpnum) +{ + int minlength; + int lumplen; + + // Calculate the size that the REJECT lump *should* be. + + minlength = (numsectors * numsectors + 7) / 8; + + // If the lump meets the minimum length, it can be loaded directly. + // Otherwise, we need to allocate a buffer of the correct size + // and pad it with appropriate data. + + lumplen = W_LumpLength(lumpnum); + + if (lumplen >= minlength) + { + rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + else + { + rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); + W_ReadLump(lumpnum, rejectmatrix); + + PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); + } +} + +// +// P_SetupLevel +// +void +P_SetupLevel +( int map, + int playermask, + skill_t skill) +{ + int i; + char lumpname[9]; + int lumpnum; + + // haleyjd 20110205 [STRIFE]: removed totalitems and wminfo + totalkills = totalsecret = 0; + + for (i=0 ; idx) + { + if (x==node->x) + return 2; + + if (x <= node->x) + return node->dy > 0; + + return node->dy < 0; + } + + if (!node->dy) + { + if (x==node->y) + return 2; + + if (y <= node->y) + return node->dx < 0; + + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + + left = (node->dy>>FRACBITS) * (dx>>FRACBITS); + right = (dy>>FRACBITS) * (node->dx>>FRACBITS); + + if (right < left) + return 0; // front side + + if (left == right) + return 2; + return 1; // back side +} + + +// +// P_InterceptVector2 +// Returns the fractional intercept point +// along the first divline. +// This is only called by the addthings and addlines traversers. +// +// [STRIFE] Verified unmodified +// +fixed_t +P_InterceptVector2 +( divline_t* v2, + divline_t* v1 ) +{ + fixed_t frac; + fixed_t num; + fixed_t den; + + den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); + + if (den == 0) + return 0; + // I_Error ("P_InterceptVector: parallel"); + + num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + + FixedMul ( (v2->y - v1->y)>>8 , v1->dx); + frac = FixedDiv (num , den); + + return frac; +} + +// +// P_CrossSubsector +// Returns true +// if strace crosses the given subsector successfully. +// +// [STRIFE] Verified unmodified +// +boolean P_CrossSubsector (int num) +{ + seg_t* seg; + line_t* line; + int s1; + int s2; + int count; + subsector_t* sub; + sector_t* front; + sector_t* back; + fixed_t opentop; + fixed_t openbottom; + divline_t divl; + vertex_t* v1; + vertex_t* v2; + fixed_t frac; + fixed_t slope; + +#ifdef RANGECHECK + if (num>=numsubsectors) + I_Error ("P_CrossSubsector: ss %i with numss = %i", + num, + numsubsectors); +#endif + + sub = &subsectors[num]; + + // check lines + count = sub->numlines; + seg = &segs[sub->firstline]; + + for ( ; count ; seg++, count--) + { + line = seg->linedef; + + // allready checked other side? + if (line->validcount == validcount) + continue; + + line->validcount = validcount; + + v1 = line->v1; + v2 = line->v2; + s1 = P_DivlineSide (v1->x, v1->y, &strace); + s2 = P_DivlineSide (v2->x, v2->y, &strace); + + // line isn't crossed? + if (s1 == s2) + continue; + + divl.x = v1->x; + divl.y = v1->y; + divl.dx = v2->x - v1->x; + divl.dy = v2->y - v1->y; + s1 = P_DivlineSide (strace.x, strace.y, &divl); + s2 = P_DivlineSide (t2x, t2y, &divl); + + // line isn't crossed? + if (s1 == s2) + continue; + + // Backsector may be NULL if this is an "impassible + // glass" hack line. + + if (line->backsector == NULL) + { + return false; + } + + // stop because it is not two sided anyway + // might do this after updating validcount? + if ( !(line->flags & ML_TWOSIDED) ) + return false; + + // crosses a two sided line + front = seg->frontsector; + back = seg->backsector; + + // no wall to block sight with? + if (front->floorheight == back->floorheight + && front->ceilingheight == back->ceilingheight) + continue; + + // possible occluder + // because of ceiling height differences + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + + // because of ceiling height differences + if (front->floorheight > back->floorheight) + openbottom = front->floorheight; + else + openbottom = back->floorheight; + + // quick test for totally closed doors + if (openbottom >= opentop) + return false; // stop + + frac = P_InterceptVector2 (&strace, &divl); + + if (front->floorheight != back->floorheight) + { + slope = FixedDiv (openbottom - sightzstart , frac); + if (slope > bottomslope) + bottomslope = slope; + } + + if (front->ceilingheight != back->ceilingheight) + { + slope = FixedDiv (opentop - sightzstart , frac); + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + } + // passed the subsector ok + return true; +} + + + +// +// P_CrossBSPNode +// Returns true +// if strace crosses the given node successfully. +// +// [STRIFE] Verified unmodified +// +boolean P_CrossBSPNode (int bspnum) +{ + node_t* bsp; + int side; + + if (bspnum & NF_SUBSECTOR) + { + if (bspnum == -1) + return P_CrossSubsector (0); + else + return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); + } + + bsp = &nodes[bspnum]; + + // decide which side the start point is on + side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp); + if (side == 2) + side = 0; // an "on" should cross both sides + + // cross the starting side + if (!P_CrossBSPNode (bsp->children[side]) ) + return false; + + // the partition plane is crossed here + if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp)) + { + // the line doesn't touch the other side + return true; + } + + // cross the ending side + return P_CrossBSPNode (bsp->children[side^1]); +} + + +// +// P_CheckSight +// Returns true +// if a straight line between t1 and t2 is unobstructed. +// Uses REJECT. +// +// [STRIFE] Verified unmodified +// +boolean +P_CheckSight +( mobj_t* t1, + mobj_t* t2 ) +{ + int s1; + int s2; + int pnum; + int bytenum; + int bitnum; + + // First check for trivial rejection. + + // Determine subsector entries in REJECT table. + s1 = (t1->subsector->sector - sectors); + s2 = (t2->subsector->sector - sectors); + pnum = s1*numsectors + s2; + bytenum = pnum>>3; + bitnum = 1 << (pnum&7); + + // Check in REJECT table. + if (rejectmatrix[bytenum]&bitnum) + { + sightcounts[0]++; + + // can't possibly be connected + return false; + } + + // An unobstructed LOS is possible. + // Now look from eyes of t1 to any part of t2. + sightcounts[1]++; + + validcount++; + + sightzstart = t1->z + t1->height - (t1->height>>2); + topslope = (t2->z+t2->height) - sightzstart; + bottomslope = (t2->z) - sightzstart; + + strace.x = t1->x; + strace.y = t1->y; + t2x = t2->x; + t2y = t2->y; + strace.dx = t2->x - t1->x; + strace.dy = t2->y - t1->y; + + // the head node is the last node output + return P_CrossBSPNode (numnodes-1); +} + + diff --git a/games/NXDoom/src/strife/p_spec.c b/games/NXDoom/src/strife/p_spec.c new file mode 100644 index 00000000000..de01eaa44d0 --- /dev/null +++ b/games/NXDoom/src/strife/p_spec.c @@ -0,0 +1,1984 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Implements special effects: +// Texture animation, height or lighting changes +// according to adjacent sectors, respective +// utility functions, etc. +// Line Tag handling. Line and Sector triggers. +// + + +#include + +#include "doomdef.h" +#include "doomstat.h" + +#include "deh_main.h" +#include "i_system.h" +#include "z_zone.h" +#include "m_argv.h" +#include "m_misc.h" +#include "m_random.h" +#include "w_wad.h" + +#include "r_local.h" +#include "p_local.h" + +#include "g_game.h" + +#include "s_sound.h" + +// State. +#include "r_state.h" + +// Data. +#include "sounds.h" + +// [STRIFE] +#include "hu_stuff.h" +#include "p_dialog.h" + + +// +// Animating textures and planes +// There is another anim_t used in wi_stuff, unrelated. +// +typedef struct +{ + boolean istexture; + int picnum; + int basepic; + int numpics; + int speed; + +} anim_t; + +// +// source animation definition +// +typedef struct +{ + int istexture; // if false, it is a flat + char endname[9]; + char startname[9]; + int speed; +} animdef_t; + + +// haleyjd 08/30/10: [STRIFE] MAXANIMS raised from 32 to 40 +#define MAXANIMS 40 + +// +// P_InitPicAnims +// + +// Floor/ceiling animation sequences, +// defined by first and last frame, +// i.e. the flat (64x64 tile) name to +// be used. +// The full animation sequence is given +// using all the flats between the start +// and end entry, in the order found in +// the WAD file. +// +// haleyjd 08/29/10: [STRIFE] Changed animdefs. +// +animdef_t animdefs[] = +{ + { false, "F_SCANR8", "F_SCANR5", 4}, + { false, "F_WATR03", "F_WATR01", 8}, + { false, "F_PWATR3", "F_PWATR1", 11}, + { false, "F_SCANR4", "F_SCANR1", 4}, + { true, "SCAN08", "SCAN05", 4}, + { true, "SWTRMG03", "SWTRMG01", 4}, + { true, "SCAN04", "SCAN01", 4}, + { true, "COMP04", "COMP01", 4}, + { true, "COMP08", "COMP05", 6}, + { true, "COMP12", "COMP09", 11}, + { true, "COMP16", "COMP13", 12}, + { true, "COMP20", "COMP17", 12}, + { true, "COMP24", "COMP21", 12}, + { true, "COMP28", "COMP25", 12}, + { true, "COMP32", "COMP29", 12}, + { true, "COMP37", "COMP33", 12}, + { true, "COMP41", "COMP38", 12}, + { true, "COMP49", "COMP42", 10}, + { true, "BRKGRY16", "BRKGRY13", 10}, + { true, "BRNSCN04", "BRNSCN01", 10}, + { true, "CONCRT12", "CONCRT09", 11}, + { true, "CONCRT25", "CONCRT22", 11}, + { true, "WALPMP02", "WALPMP01", 16}, + { true, "WALTEK17", "WALTEK16", 8}, + { true, "FORCE04", "FORCE01", 4}, + { true, "FORCE08", "FORCE05", 4}, + { true, "FAN02", "FAN01", 4}, + { false, "F_VWATR3", "P_VWATR1", 4}, + { false, "F_HWATR3", "F_HWATR1", 4}, + { false, "F_TELE2", "F_TELE1", 4}, + { false, "F_FAN2", "F_FAN1", 4}, + { false, "F_CONVY2", "F_CONVY1", 4}, + { false, "F_RDALN4", "F_RDALN1", 4}, + { -1, "", "", 0}, +}; + +anim_t anims[MAXANIMS]; +anim_t* lastanim; + +// +// Animating line specials +// +// haleyjd 08/29/10: [STRIFE] MAXLINEANIMS raised from 64 to 96 +#define MAXLINEANIMS 96 + +short numlinespecials = 0; +line_t *linespeciallist[MAXLINEANIMS]; + + + +void P_InitPicAnims (void) +{ + int i; + + + // Init animation + lastanim = anims; + for (i=0 ; animdefs[i].istexture != -1 ; i++) + { + const char *startname, *endname; + + startname = DEH_String(animdefs[i].startname); + endname = DEH_String(animdefs[i].endname); + + if (animdefs[i].istexture) + { + // different episode ? + if (R_CheckTextureNumForName(startname) == -1) + continue; + + lastanim->picnum = R_TextureNumForName(endname); + lastanim->basepic = R_TextureNumForName(startname); + } + else + { + if (W_CheckNumForName(startname) == -1) + continue; + + lastanim->picnum = R_FlatNumForName(endname); + lastanim->basepic = R_FlatNumForName(startname); + } + + lastanim->istexture = animdefs[i].istexture; + lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; + + if (lastanim->numpics < 2) + I_Error ("P_InitPicAnims: bad cycle from %s to %s", + startname, endname); + + lastanim->speed = animdefs[i].speed; + lastanim++; + } + +} + +// villsa [STRIFE] terrain type definitions +typedef struct +{ + const char *flat; + int type; + int num; +} terraintype_t; + +terraintype_t terraintypes[] = +{ + { "F_WATR03", FLOOR_WATER, -1 }, + { "F_WATR02", FLOOR_WATER, -1 }, + { "F_WATR01", FLOOR_WATER, -1 }, + { "F_VWATR3", FLOOR_WATER, -1 }, + { "F_VWATR2", FLOOR_WATER, -1 }, + { "P_VWATR1", FLOOR_WATER, -1 }, + { "F_HWATR3", FLOOR_WATER, -1 }, + { "F_HWATR2", FLOOR_WATER, -1 }, + { "F_HWATR1", FLOOR_WATER, -1 }, + { "F_PWATR3", FLOOR_SLIME, -1 }, + { "F_PWATR2", FLOOR_SLIME, -1 }, + { "F_PWATR1", FLOOR_SLIME, -1 }, + { "END", FLOOR_END, -1 }, +}; + +// +// P_GetTerrainType +// villsa [STRIFE] new function +// + +terraintype_e P_GetTerrainType(mobj_t* mobj) +{ + int i = 0; + subsector_t* ss = mobj->subsector; + + if(mobj->z <= ss->sector->floorheight && + terraintypes[0].type != FLOOR_END) + { + while(ss->sector->floorpic != terraintypes[i].num) + { + if(terraintypes[i+1].type == FLOOR_END) + return FLOOR_SOLID; + + i++; + } + + return terraintypes[i].type; + } + + return FLOOR_SOLID; +} + +// +// P_InitTerrainTypes +// villsa [STRIFE] new function +// Initialize terrain types +// + +void P_InitTerrainTypes(void) +{ + int i = 0; + + if(terraintypes[0].type != FLOOR_END) + { + while(terraintypes[i].type != FLOOR_END) + { + terraintypes[i].num = R_FlatNumForName(terraintypes[i].flat); + i++; + } + } +} + + + +// +// UTILITIES +// + + + +// +// getSide() +// Will return a side_t* +// given the number of the current sector, +// the line number, and the side (0/1) that you want. +// +side_t* +getSide +( int currentSector, + int line, + int side ) +{ + return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; +} + + +// +// getSector() +// Will return a sector_t* +// given the number of the current sector, +// the line number and the side (0/1) that you want. +// +sector_t* +getSector +( int currentSector, + int line, + int side ) +{ + return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; +} + + +// +// twoSided() +// Given the sector number and the line number, +// it will tell you whether the line is two-sided or not. +// +int +twoSided +( int sector, + int line ) +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} + + + + +// +// getNextSector() +// Return sector_t * of sector next to current. +// NULL if not two-sided line +// +sector_t* +getNextSector +( line_t* line, + sector_t* sec ) +{ + if (!(line->flags & ML_TWOSIDED)) + return NULL; + + if (line->frontsector == sec) + return line->backsector; + + return line->frontsector; +} + + + +// +// P_FindLowestFloorSurrounding() +// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +fixed_t P_FindLowestFloorSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t floor = sec->floorheight; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight < floor) + floor = other->floorheight; + } + return floor; +} + + + +// +// P_FindHighestFloorSurrounding() +// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS +// +fixed_t P_FindHighestFloorSurrounding(sector_t *sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t floor = -500*FRACUNIT; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight > floor) + floor = other->floorheight; + } + return floor; +} + + + +// +// P_FindNextHighestFloor +// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS +// Note: this should be doable w/o a fixed array. + +// Thanks to entryway for the Vanilla overflow emulation. + +// 20 adjoining sectors max! +#define MAX_ADJOINING_SECTORS 20 + +fixed_t +P_FindNextHighestFloor +( sector_t* sec, + int currentheight ) +{ + int i; + int h; + int min; + line_t* check; + sector_t* other; + fixed_t height = currentheight; + fixed_t heightlist[MAX_ADJOINING_SECTORS + 2]; + + for (i=0, h=0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->floorheight > height) + { + // Emulation of memory (stack) overflow + if (h == MAX_ADJOINING_SECTORS + 1) + { + height = other->floorheight; + } + else if (h == MAX_ADJOINING_SECTORS + 2) + { + // Fatal overflow: game crashes at 22 sectors + I_Error("Sector with more than 22 adjoining sectors. " + "Vanilla will crash here"); + } + + heightlist[h++] = other->floorheight; + } + } + + // Find lowest height in list + if (!h) + { + return currentheight; + } + + min = heightlist[0]; + + // Range checking? + for (i = 1; i < h; i++) + { + if (heightlist[i] < min) + { + min = heightlist[i]; + } + } + + return min; +} + +// +// FIND LOWEST CEILING IN THE SURROUNDING SECTORS +// +fixed_t +P_FindLowestCeilingSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t height = INT_MAX; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->ceilingheight < height) + height = other->ceilingheight; + } + return height; +} + + +// +// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS +// +fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) +{ + int i; + line_t* check; + sector_t* other; + fixed_t height = 0; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + + if (!other) + continue; + + if (other->ceilingheight > height) + height = other->ceilingheight; + } + return height; +} + + + +// +// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO +// +int +P_FindSectorFromLineTag +( line_t* line, + int start ) +{ + int i; + + for (i=start+1;itag) + return i; + + return -1; +} + + + + +// +// Find minimum light from an adjacent sector +// +int +P_FindMinSurroundingLight +( sector_t* sector, + int max ) +{ + int i; + int min; + line_t* line; + sector_t* check; + + min = max; + for (i=0 ; i < sector->linecount ; i++) + { + line = sector->lines[i]; + check = getNextSector(line,sector); + + if (!check) + continue; + + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} + + + +// +// EVENTS +// Events are operations triggered by using, crossing, +// or shooting special lines, or by timed thinkers. +// + +// [STRIFE] +static char crosslinestr[90]; + +// +// P_CrossSpecialLine - TRIGGER +// Called every time a thing origin is about +// to cross a line with a non 0 special. +// +void +P_CrossSpecialLine +( int linenum, + int side, + mobj_t* thing ) +{ + line_t* line; + side_t* sidedef; // [STRIFE] + int flag; // [STRIFE] + int ok; + + line = &lines[linenum]; + + // haleyjd 09/21/10: corpses and missiles cannot activate any cross-over + // line types, *except* 182 (which is for the sake of missiles). + if((thing->flags & (MF_MISSILE|MF_CORPSE)) && line->special != 182) + return; + + // Triggers that other things can activate + if (!thing->player) + { + // Things that should NOT trigger specials... + // villsa [STRIFE] unused + // haleyjd: removed dead switch. Strife only excludes missiles and + // corpses, which is handled above. + + ok = 0; + + // [STRIFE] Added several line types. Removed none. + switch(line->special) + { + case 97: // TELEPORT RETRIGGER + case 185: // haleyjd: [STRIFE] Silent Teleport (used for Converter) + case 195: // haleyjd: [STRIFE] Silent Teleport and Change Zombie + case 231: // haleyjd: [STRIFE] WR Teleport (Silent at Source) + case 125: // TELEPORT MONSTERONLY TRIGGER + case 126: // TELEPORT MONSTERONLY RETRIGGER + case 182: // haleyjd: [STRIFE] Break glass - it's a W1 type too! + case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER + case 39: // TELEPORT TRIGGER + case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER + case 4: // RAISE DOOR + ok = 1; + break; + } + if (!ok) + return; + } + + + // Note: could use some const's here. + switch (line->special) + { + // + // TRIGGERS. + // All from here to RETRIGGERS. + // + case 230: + // haleyjd 09/21/10: [STRIFE] W1 Open Door if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; + + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 2: + // Open Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_open); + line->special = 0; + break; + + case 227: + // haleyjd 09/21/10: [STRIFE] W1 Close Door if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; + + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 3: + // Close Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_close); + line->special = 0; + break; + + case 4: + // Raise Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_normal); + line->special = 0; + break; + + case 5: + // Raise Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor); + line->special = 0; + break; + + case 6: + // Fast Ceiling Crush & Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,fastCrushAndRaise); + line->special = 0; + break; + + case 8: + // Build Stairs - [STRIFE] Verified unmodified. + EV_BuildStairs(line,build8); + line->special = 0; + break; + + case 10: + // PlatDownWaitUp - [STRIFE] Verified unmodified. + EV_DoPlat(line,downWaitUpStay,0); + line->special = 0; + break; + + case 12: + // Light Turn On - brightest near - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,0); + line->special = 0; + break; + + case 13: + // Light Turn On 255 - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,255); + line->special = 0; + break; + + case 16: + // Close Door 30 - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_close30ThenOpen); + line->special = 0; + break; + + case 17: + // Start Light Strobing - [STRIFE] Verified unmodified. + EV_StartLightStrobing(line); + line->special = 0; + break; + + case 19: + // Lower Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerFloor); + line->special = 0; + break; + + case 22: + // villsa [STRIFE] Verified unmodified. + // Raise floor to nearest height and change texture + EV_DoPlat(line,raiseToNearestAndChange,0); + line->special = 0; + break; + + case 25: + // Ceiling Crush and Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,crushAndRaise); + line->special = 0; + break; + + case 30: + // Raise floor to shortest texture height - [STRIFE] Verified unmodified. + // on either side of lines. + EV_DoFloor(line,raiseToTexture); + line->special = 0; + break; + + case 35: + // Lights Very Dark - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,35); + line->special = 0; + break; + + case 36: + // Lower Floor (TURBO) - [STRIFE] Verified unmodified. + EV_DoFloor(line,turboLower); + line->special = 0; + break; + + case 37: + // LowerAndChange - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerAndChange); + line->special = 0; + break; + + case 193: + // haleyjd 09/21/10: [STRIFE] W1 Floor Lower to Lowest if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t + + // must have the questflag indicated in the line's y offset + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 38: + // Lower Floor To Lowest - [STRIFE] Verified unmodified. + EV_DoFloor( line, lowerFloorToLowest ); + line->special = 0; + break; + + case 39: + // TELEPORT! - [STRIFE] Verified unmodified (except for 0 flags param) + EV_Teleport( line, side, thing, TF_NORMAL ); + line->special = 0; + break; + + /*case 40: + // RaiseCeilingLowerFloor + EV_DoCeiling( line, raiseToHighest ); + EV_DoFloor( line, lowerFloorToLowest ); + line->special = 0; + break;*/ + + case 44: + // Ceiling Crush - [STRIFE] Verified unmodified. + EV_DoCeiling( line, lowerAndCrush ); + line->special = 0; + break; + + case 52: + // EXIT! - haleyjd 09/21/10: [STRIFE] Exit to level tag/100 + G_ExitLevel (line->tag / 100); + break; + + case 53: + // Perpetual Platform Raise - [STRIFE] Verified unmodified. + EV_DoPlat(line,perpetualRaise,0); + line->special = 0; + break; + + case 54: + // Platform Stop - [STRIFE] Verified unmodified. + EV_StopPlat(line); + line->special = 0; + break; + + case 56: + // Raise Floor Crush - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorCrush); + line->special = 0; + break; + + case 57: + // Ceiling Crush Stop - [STRIFE] Verified unmodified. + EV_CeilingCrushStop(line); + line->special = 0; + break; + + case 58: + // [STRIFE] raiseFloor24 was modified into raiseFloor64 + // Raise Floor 64 + EV_DoFloor(line,raiseFloor64); + line->special = 0; + break; + + case 59: + // Raise Floor 24 And Change - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor24AndChange); + line->special = 0; + break; + + case 104: + // Turn lights off in sector(tag) - [STRIFE] Verified unmodified. + EV_TurnTagLightsOff(line); + line->special = 0; + break; + + case 108: + // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,vld_blazeRaise); + line->special = 0; + break; + + case 109: + // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,vld_blazeOpen); + line->special = 0; + break; + + case 100: + // Build Stairs Turbo 16 - [STRIFE] Verified unmodified. + EV_BuildStairs(line,turbo16); + line->special = 0; + break; + + case 197: + // haleyjd 09/21/10: [STRIFE] Blazing Door Close if Has Sigil B + if(thing->player->sigiltype <= 0) + break; + // fall-through: + case 110: + // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,vld_blazeClose); + line->special = 0; + break; + + case 119: + // Raise floor to nearest surr. floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorToNearest); + line->special = 0; + break; + + case 121: + // villsa [STRIFE] Verified unmodified. + // Blazing PlatDownWaitUpStay + EV_DoPlat(line,blazeDWUS,0); + line->special = 0; + break; + + case 124: + // haleyjd 09/21/10: [STRIFE] W1 Start Finale + // Altered from G_SecretExitLevel. + G_StartFinale(); + break; + + case 125: + // TELEPORT MonsterONLY - [STRIFE] Verified unmodified + // (except for 0 flags parameter) + if (!thing->player) + { + EV_Teleport( line, side, thing, TF_NORMAL ); + line->special = 0; + } + break; + + case 130: + // Raise Floor Turbo - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorTurbo); + line->special = 0; + break; + + case 141: + // Silent Ceiling Crush & Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,silentCrushAndRaise); + line->special = 0; + break; + + case 174: + // villsa [STRIFE] Split Open + EV_DoDoor(line, vld_splitOpen); + line->special = 0; + break; + + case 183: + // villsa [STRIFE] Split Raise Nearest + EV_DoDoor(line, vld_splitRaiseNearest); + line->special = 0; + break; + + case 178: + // haleyjd 09/24/10: [STRIFE] W1 Build Stairs Down 16 + EV_BuildStairs(line, buildDown16); + line->special = 0; + break; + + case 179: + // haleyjd 09/25/10: [STRIFE] W1 Ceiling Lower to Floor + EV_DoCeiling(line, lowerToFloor); + line->special = 0; + break; + + case 182: + // haleyjd 09/21/10: [STRIFE] Break Glass + // 182 is a unique linetype in that it is both a G1 and a W1 linetype, + // but only missiles may activate it as a W1 type. + if(thing->flags & MF_MISSILE) + P_ChangeSwitchTexture(line, 1); // why 1? it will be cleared anyway. + break; + + case 187: + // haleyjd 09/21/10: [STRIFE] W1 Clear Force Fields if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t + + // must have the questflag indicated in the line's y offset + if(!(thing->player->questflags & (1 << flag))) + break; + + // Do it! + EV_ClearForceFields(line); + line->special = 0; + break; + + case 188: + // haleyjd 09/21/10: [STRIFE] W1 Open Door if Quest 16 (Gate Mechanism + // Destroyed) + if(!(thing->player->questflags & QF_QUEST16)) + break; + EV_DoDoor(line, vld_open); + line->special = 0; + break; + + case 196: + // haleyjd 09/26/10: [STRIFE] W1 Floor Lower to Lowest if Sigil Type > 0 + if(thing->player->sigiltype > 0) + { + EV_DoFloor(line, lowerFloorToLowest); + line->special = 0; + } + break; + + case 200: + // haleyjd 09/21/10: [STRIFE] W1 Open Door if Sigil Owned + if(!(thing->player->weaponowned[wp_sigil])) + break; + EV_DoDoor(line, vld_open); + line->special = 0; + break; + + case 201: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective (First Side Only) + if(side == 1) + break; + // fall-through: + case 202: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective (Tag = VOC/LOG #) + // must be consoleplayer + if(thing->player != &players[consoleplayer]) + break; + + // must have comm unit + if(!(thing->player->powers[pw_communicator])) + break; + + // load voice + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag); + I_StartVoice(crosslinestr); + + // load objective + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag); + GiveObjective(crosslinestr, 0); + + // Put up a message + thing->player->message = DEH_String("Incoming Message..."); + line->special = 0; + break; + + case 210: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective if Flamethrower???? + // I don't think this is actually used anywhere o_O + // must be player 1... + if(thing->player != &players[0]) + break; + + // must have comm unit + if(!(thing->player->powers[pw_communicator])) + break; + + // must have... the flamethrower?! + if(!(thing->player->weaponowned[wp_flame])) + break; + + // load voice + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag); + I_StartVoice(crosslinestr); + + // load objective + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag); + GiveObjective(crosslinestr, 0); + + // Put up a message + thing->player->message = DEH_String("Incoming Message from BlackBird..."); + line->special = 0; + break; + + case 212: + // haleyjd 09/25/10: [STRIFE] W1 Floor Lower to Lowest if Have Flamethrower + if(thing->player->weaponowned[wp_flame]) + { + EV_DoFloor(line, lowerFloorToLowest); + line->special = 0; + } + break; + + case 215: + // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective if Quest (Tag/100, Tag%100) + // must be player 1... + if(thing->player != &players[0]) + break; + + // must have comm unit + if(!(thing->player->powers[pw_communicator])) + break; + + if(line->tag != 0) + { + // test for questflag + if(!(thing->player->questflags & (1 << (line->tag % 100 - 1)))) + break; + } + + // start voice + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag/100); + I_StartVoice(crosslinestr); + + // give objective + DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag/100); + GiveObjective(crosslinestr, 0); + + // Put up a message + thing->player->message = DEH_String("Incoming Message from BlackBird..."); + line->special = 0; + break; + + case 204: + // haleyjd 09/21/10: [STRIFE] W1 Change Music (unused!) + if(thing->player != &players[0]) + break; + S_ChangeMusic(line->tag, 1); + line->special = 0; + break; + + case 228: + // haleyjd 09/21/10: [STRIFE] W1 Entity Voice? + if(!(thing->player->questflags & QF_QUEST24)) // Not killed Macil??? + break; // STRIFE-TODO: verify... + + if(!(thing->player->questflags & QF_QUEST28)) // ????? STRIFE-TODO + I_StartVoice(DEH_String("voc128")); + else + I_StartVoice(DEH_String("voc130")); + + line->special = 0; + break; + + // + // RETRIGGERS. All from here till end. + // + case 72: + // Ceiling Crush - [STRIFE] Verified unmodified. + EV_DoCeiling( line, lowerAndCrush ); + break; + + case 73: + // Ceiling Crush and Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,crushAndRaise); + break; + + case 74: + // Ceiling Crush Stop - [STRIFE] Verified unmodified. + EV_CeilingCrushStop(line); + break; + + case 75: + // Close Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_close); + break; + + case 76: + // Close Door 30 - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_close30ThenOpen); + break; + + case 77: + // Fast Ceiling Crush & Raise - [STRIFE] Verified unmodified. + EV_DoCeiling(line,fastCrushAndRaise); + break; + + case 79: + // Lights Very Dark - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,35); + break; + + case 80: + // Light Turn On - brightest near - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,0); + break; + + case 81: + // Light Turn On 255 - [STRIFE] Verified unmodified. + EV_LightTurnOn(line,255); + break; + + case 82: + // Lower Floor To Lowest - [STRIFE] Verified unmodified. + EV_DoFloor( line, lowerFloorToLowest ); + break; + + case 83: + // Lower Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerFloor); + break; + + case 84: + // LowerAndChange - [STRIFE] Verified unmodified. + EV_DoFloor(line,lowerAndChange); + break; + + case 86: + // Open Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_open); + break; + + case 87: + // Perpetual Platform Raise - [STRIFE] Verified unmodified. + EV_DoPlat(line,perpetualRaise,0); + break; + + case 88: + // PlatDownWaitUp - [STRIFE] Verified unmodified. + EV_DoPlat(line,downWaitUpStay,0); + break; + + case 89: + // Platform Stop - [STRIFE] Verified unmodified. + EV_StopPlat(line); + break; + + case 216: + // haleyjd 09/21/10: [STRIFE] WR Raise Door if Quest + sidedef = &sides[line->sidenum[0]]; + flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t. + + if(!(thing->player->questflags & (1 << flag))) + break; + // fall-through: + case 90: + // Raise Door - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_normal); + break; + + case 91: + // Raise Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor); + break; + + case 92: + // [STRIFE] raiseFloor24 changed to raiseFloor64 + // Raise Floor 64 + EV_DoFloor(line,raiseFloor64); + break; + + case 93: + // Raise Floor 24 And Change - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloor24AndChange); + break; + + case 94: + // Raise Floor Crush - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorCrush); + break; + + case 95: + // villsa [STRIFE] Verified unmodified. + // Raise floor to nearest height + // and change texture. + EV_DoPlat(line,raiseToNearestAndChange,0); + break; + + case 96: + // Raise floor to shortest texture height - [STRIFE] Verified unmodified. + // on either side of lines. + EV_DoFloor(line,raiseToTexture); + break; + + case 97: + // TELEPORT! - [STRIFE] Verified unmodified (except for 0 flags param) + EV_Teleport( line, side, thing, TF_NORMAL ); + break; + + case 98: + // Lower Floor (TURBO) - [STRIFE] Verified unmodified. + EV_DoFloor(line,turboLower); + break; + + case 105: + // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,vld_blazeRaise); + break; + + case 106: + // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,vld_blazeOpen); + break; + + case 107: + // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified. + EV_DoDoor (line,vld_blazeClose); + break; + + case 120: + // villsa [STRIFE] Verified unmodified. + // Blazing PlatDownWaitUpStay. + EV_DoPlat(line,blazeDWUS,0); + break; + + case 126: + // TELEPORT MonsterONLY. - [STRIFE] Verified unmodified (except for 0 flags param) + if (!thing->player) + EV_Teleport( line, side, thing, TF_NORMAL ); + break; + + case 128: + // Raise To Nearest Floor - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorToNearest); + break; + + case 129: + // Raise Floor Turbo - [STRIFE] Verified unmodified. + EV_DoFloor(line,raiseFloorTurbo); + break; + + case 186: + // haleyjd [STRIFE] Exit Level to Spot, First Side Only + if(side == 1) + break; + // fall-through: + case 145: + // haleyjd [STRIFE] Exit Level to Spot + thing->momx = thing->momy = thing->momz = 0; + { + int map = line->tag / 100; + int spot = line->tag % 100; + + if(thing->player->weaponowned[wp_sigil]) + { + if(map == 3) + map = 30; + else if(map == 7) + map = 10; + } + + DEH_snprintf(crosslinestr, sizeof(crosslinestr), + "Entering%s", + DEH_String(mapnames[map - 1]) + 8); + thing->player->message = crosslinestr; + + if(netgame && deathmatch) + { + if(levelTimer && levelTimeCount != 0) + { + DEH_snprintf(crosslinestr, sizeof(crosslinestr), + "%d min left", + (levelTimeCount/TICRATE)/60); + break; + } + + // raise switch from floor + EV_DoFloor(line, raiseFloor64); + } + else + { + // normal single-player exit + + // BUG: Here is the opening for a flaming player to cross past + // the exit line and hit a deathmatch switch ;) It's not so much + // that this is incorrect, as that they forgot to add such a + // check to the other kind of exit lines too ;) + if(thing->player->health <= 0) + break; + + G_RiftExitLevel(map, spot, thing->angle); + } + } + break; + + case 175: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if < 16 Above Floor + if(thing->z < thing->floorz + 16 * FRACUNIT) + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 198: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if No Guard Uniform + if(P_PlayerHasItem(thing->player, MT_QUEST_GUARD_UNIFORM)) + break; + // fall-through: + case 150: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 208: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if Have Flamethrower + // O_o - this is definitely unused. Was an entire flamethrower quest + // cut out of the game before release? + if(thing->player->weaponowned[wp_flame]) + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 206: + // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if Have Chalice + // This *is* used, inside the Tavern in Tarnhill. Oddly there is also + // one just randomly placed outside the entrance to the Power Station. + if(P_PlayerHasItem(thing->player, MT_INV_CHALICE)) + P_NoiseAlert(thing->player->mo, thing->player->mo); + break; + + case 184: + // villsa [STRIFE] plat up wait down stay + if(EV_DoPlat(line, upWaitDownStay, 0)) + P_ChangeSwitchTexture(line, 1); // In P_CrossSpecialLine? Copypasta error? + break; + + case 185: + // haleyjd 09/21/10: [STRIFE] Silent Teleport (used for Converter) + EV_Teleport(line, side, thing, TF_FULLSILENCE); + break; + + case 195: + // haleyjd 09/21/10: [STRIFE] Silent Teleport and Change Zombie + EV_Teleport(line, side, thing, TF_FULLSILENCE); + P_SetMobjState(thing, S_AGRD_00); // 419 + break; + + case 203: + // haleyjd 09/21/10: [STRIFE] WR Change Music + if(thing->player != &players[0]) + break; + S_ChangeMusic(line->tag, 1); + break; + + case 231: + // haleyjd 09/21/10: [STRIFE] WR Teleport (Silent at Source) + EV_Teleport(line, side, thing, TF_SRCSILENCE); + break; + + // haleyjd 09/21/10: Moved one-time-use lines up above with the others. + } +} + + + +// +// P_ShootSpecialLine - IMPACT SPECIALS +// Called when a thing shoots a special line. +// +void +P_ShootSpecialLine +( mobj_t* thing, + line_t* line ) +{ + int ok; + + // Impacts that other things can activate. + if (!thing->player) + { + ok = 0; + switch(line->special) + { + case 46: // OPEN DOOR IMPACT + case 182: // villsa [STRIFE] for windows + ok = 1; + break; + } + if (!ok) + return; + } + + switch(line->special) + { + case 24: + // RAISE FLOOR - [STRIFE] Verified unmodified + EV_DoFloor(line,raiseFloor); + P_ChangeSwitchTexture(line,0); + break; + + case 46: + // OPEN DOOR - [STRIFE] Verified unmodified. + EV_DoDoor(line,vld_open); + P_ChangeSwitchTexture(line,1); + break; + + case 47: + // villsa [STRIFE] Verified unmodified. + // RAISE FLOOR NEAR AND CHANGE + EV_DoPlat(line,raiseToNearestAndChange,0); + P_ChangeSwitchTexture(line,0); + break; + + case 180: + // haleyjd 09/22/10: [STRIFE] G1 Raise Floor 512 & Change + EV_DoFloor(line, raiseFloor512AndChange); + P_ChangeSwitchTexture(line, 0); + break; + + case 182: + // villsa [STRIFE] G1 Break Glass + // haleyjd: note that 182 is also a W1 type in P_CrossSpecialLine, but + // can only be activated in that manner by an MF_MISSILE object. + P_ChangeSwitchTexture(line, 0); + break; + } +} + + + +// +// P_PlayerInSpecialSector +// Called every tic frame +// that the player origin is in a special sector +// +// [STRIFE] Modified for new sector types and changes to old ones. +// +void P_PlayerInSpecialSector (player_t* player) +{ + sector_t* sector; + + sector = player->mo->subsector->sector; + + // Falling, not all the way down yet? + if (player->mo->z != sector->floorheight) + return; + + // Has hitten ground. + switch (sector->special) + { + case 5: + // HELLSLIME DAMAGE + // [STRIFE] +2 to nukagecount + if(!player->powers[pw_ironfeet]) + player->nukagecount += 2; + break; + + case 16: + // [STRIFE] +4 to nukagecount + if(!player->powers[pw_ironfeet]) + player->nukagecount += 4; + break; + + case 4: + case 7: + // [STRIFE] Immediate 5 damage every 31 tics + if(!player->powers[pw_ironfeet]) + if(!(leveltime & 0x1f)) + P_DamageMobj(player->mo, NULL, NULL, 5); + break; + + case 9: + // SECRET SECTOR + //player->secretcount++; [STRIFE] Don't have a secret count. + sector->special = 0; + if(player - players == consoleplayer) + S_StartSound(NULL, sfx_yeah); + break; + + case 11: + // EXIT SUPER DAMAGE! (for E1M8 finale) + player->cheats &= ~CF_GODMODE; + + if (!(leveltime&0x1f)) + P_DamageMobj (player->mo, NULL, NULL, 20); + + if (player->health <= 10) + G_ExitLevel(0); + break; + + case 15: + // haleyjd 08/30/10: [STRIFE] "Instant" Death sector + P_DamageMobj(player->mo, NULL, NULL, 999); + break; + + + case 18: + // haleyjd 08/30/10: [STRIFE] Water current + { + int tagval = sector->tag - 100; + fixed_t force; + angle_t angle; + + if(player->cheats & CF_NOCLIP) + return; + + force = (tagval % 10) << 12; + angle = (tagval / 10) << 29; + + P_Thrust(player, angle, force); + } + break; + + default: + I_Error ("P_PlayerInSpecialSector: " + "unknown special %i", + sector->special); + break; + }; +} + + + + +// +// P_UpdateSpecials +// Animate planes, scroll walls, etc. +// +// [STRIFE] Modifications to support multiple scrolling line types. +// +boolean levelTimer; +int levelTimeCount; + +void P_UpdateSpecials (void) +{ + anim_t* anim; + int pic; + int i; + line_t* line; + + + // LEVEL TIMER + if (levelTimer == true) + { + if(levelTimeCount) // [STRIFE] Does not allow to go negative + levelTimeCount--; + + /* + // [STRIFE] Not done here. Exit lines check this manually instead. + if (!levelTimeCount) + G_ExitLevel(0); + */ + } + + // ANIMATE FLATS AND TEXTURES GLOBALLY + for (anim = anims ; anim < lastanim ; anim++) + { + for (i=anim->basepic ; ibasepic+anim->numpics ; i++) + { + pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); + if (anim->istexture) + texturetranslation[i] = pic; + else + flattranslation[i] = pic; + } + } + + + // ANIMATE LINE SPECIALS + for (i = 0; i < numlinespecials; i++) + { + line = linespeciallist[i]; + switch(line->special) + { + case 48: + // EFFECT FIRSTCOL SCROLL + + sides[line->sidenum[0]].textureoffset += FRACUNIT; + break; + + case 142: + // haleyjd 09/25/10 [STRIFE] Scroll Up Slow + sides[line->sidenum[0]].rowoffset += FRACUNIT; + break; + + case 143: + // haleyjd 09/25/10 [STRIFE] Scroll Down Fast (3 Units/Tic) + sides[line->sidenum[0]].rowoffset -= 3*FRACUNIT; + break; + + case 149: + // haleyjd 09/25/10 [STRIFE] Scroll Down Slow + sides[line->sidenum[0]].rowoffset -= FRACUNIT; + break; + } + } + + + // DO BUTTONS + for (i = 0; i < MAXBUTTONS; i++) + if (buttonlist[i].btimer) + { + buttonlist[i].btimer--; + if (!buttonlist[i].btimer) + { + switch(buttonlist[i].where) + { + case top: + sides[buttonlist[i].line->sidenum[0]].toptexture = + buttonlist[i].btexture; + break; + + case middle: + sides[buttonlist[i].line->sidenum[0]].midtexture = + buttonlist[i].btexture; + break; + + case bottom: + sides[buttonlist[i].line->sidenum[0]].bottomtexture = + buttonlist[i].btexture; + break; + } + S_StartSound(&buttonlist[i].soundorg,sfx_swtchn); + memset(&buttonlist[i],0,sizeof(button_t)); + } + } +} + + +// +// Donut overrun emulation +// +// Derived from the code from PrBoom+. Thanks go to Andrey Budko (entryway) +// as usual :-) +// + +#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000 +#define DONUT_FLOORPIC_DEFAULT 0x16 + +static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic, + line_t *line, sector_t *pillar_sector) +{ + static int first = 1; + static int tmp_s3_floorheight; + static int tmp_s3_floorpic; + + if (first) + { + int p; + + // This is the first time we have had an overrun. + first = 0; + + // Default values + tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT; + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + + //! + // @category compat + // @arg + // + // Use the specified magic values when emulating behavior caused + // by memory overruns from improperly constructed donuts. + // In Vanilla Strife this can differ depending on the operating + // system. The default (if this option is not specified) is to + // emulate the behavior when running under Windows 98. + + p = M_CheckParmWithArgs("-donut", 2); + + if (p > 0) + { + // Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008 + // + // C:\>debug + // -d 0:0 + // + // DOS 6.22: + // 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) + // DOS 7.1: + // 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) + // Win98: + // 0000:0000 (00 00 00 00) 65 04 70 00-(16 00) + // DOSBox under XP: + // 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + + M_StrToInt(myargv[p + 1], &tmp_s3_floorheight); + M_StrToInt(myargv[p + 2], &tmp_s3_floorpic); + + if (tmp_s3_floorpic >= numflats) + { + fprintf(stderr, + "DonutOverrun: The second parameter for \"-donut\" " + "switch should be greater than 0 and less than number " + "of flats (%d). Using default value (%d) instead. \n", + numflats, DONUT_FLOORPIC_DEFAULT); + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + } + } + } + + /* + fprintf(stderr, + "Linedef: %d; Sector: %d; " + "New floor height: %d; New floor pic: %d\n", + line->iLineID, pillar_sector->iSectorID, + tmp_s3_floorheight >> 16, tmp_s3_floorpic); + */ + + *s3_floorheight = (fixed_t) tmp_s3_floorheight; + *s3_floorpic = (short) tmp_s3_floorpic; +} + + +// +// Special Stuff that can not be categorized +// +int EV_DoDonut(line_t* line) +{ + sector_t* s1; + sector_t* s2; + sector_t* s3; + int secnum; + int rtn; + int i; + floormove_t* floor; + fixed_t s3_floorheight; + short s3_floorpic; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + { + s1 = §ors[secnum]; + + // ALREADY MOVING? IF SO, KEEP GOING... + if (s1->specialdata) + continue; + + rtn = 1; + s2 = getNextSector(s1->lines[0],s1); + + // Vanilla Doom does not check if the linedef is one sided. The + // game does not crash, but reads invalid memory and causes the + // sector floor to move "down" to some unknown height. + // DOSbox prints a warning about an invalid memory access. + // + // I'm not sure exactly what invalid memory is being read. This + // isn't something that should be done, anyway. + // Just print a warning and return. + + if (s2 == NULL) + { + fprintf(stderr, + "EV_DoDonut: linedef had no second sidedef! " + "Unexpected behavior may occur in Vanilla Doom. \n"); + break; + } + + for (i = 0; i < s2->linecount; i++) + { + s3 = s2->lines[i]->backsector; + + if (s3 == s1) + continue; + + if (s3 == NULL) + { + // e6y + // s3 is NULL, so + // s3->floorheight is an int at 0000:0000 + // s3->floorpic is a short at 0000:0008 + // Trying to emulate + + fprintf(stderr, + "EV_DoDonut: WARNING: emulating buffer overrun due to " + "NULL back sector. " + "Unexpected behavior may occur in Vanilla Doom.\n"); + + DonutOverrun(&s3_floorheight, &s3_floorpic, line, s1); + } + else + { + s3_floorheight = s3->floorheight; + s3_floorpic = s3->floorpic; + } + + // Spawn rising slime + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s2->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = donutRaise; + floor->crush = false; + floor->direction = 1; + floor->sector = s2; + floor->speed = FLOORSPEED / 2; + floor->texture = s3_floorpic; + floor->newspecial = 0; + floor->floordestheight = s3_floorheight; + + // Spawn lowering donut-hole + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s1->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; + floor->type = lowerFloor; + floor->crush = false; + floor->direction = -1; + floor->sector = s1; + floor->speed = FLOORSPEED / 2; + floor->floordestheight = s3_floorheight; + break; + } + } + return rtn; +} + + + +// +// SPECIAL SPAWNING +// + +// +// P_SpawnSpecials +// After the map has been loaded, scan for specials +// that spawn thinkers +// + + +// Parses command line parameters. +// +// haleyjd 09/25/10: [STRIFE] Modifications for more scrolling line types and +// for initialization of sliding door resources. +// +void P_SpawnSpecials (void) +{ + sector_t* sector; + int i; + + // See if -TIMER was specified. + + if (timelimit > 0 && deathmatch) + { + levelTimer = true; + levelTimeCount = timelimit * 60 * TICRATE; + } + else + { + levelTimer = false; + } + + // Init special SECTORs - [STRIFE] Verified unmodified. + sector = sectors; + for (i=0 ; ispecial) + continue; + + switch (sector->special) + { + case 1: + // FLICKERING LIGHTS + P_SpawnLightFlash (sector); + break; + + case 2: + // STROBE FAST + P_SpawnStrobeFlash(sector,FASTDARK,0); + break; + + case 3: + // STROBE SLOW + P_SpawnStrobeFlash(sector,SLOWDARK,0); + break; + + case 4: + // STROBE FAST/DEATH SLIME + P_SpawnStrobeFlash(sector,FASTDARK,0); + sector->special = 4; + break; + + case 8: + // GLOWING LIGHT + P_SpawnGlowingLight(sector); + break; + case 9: + // SECRET SECTOR + totalsecret++; + break; + + case 10: + // DOOR CLOSE IN 30 SECONDS + P_SpawnDoorCloseIn30 (sector); + break; + + case 12: + // SYNC STROBE SLOW + P_SpawnStrobeFlash (sector, SLOWDARK, 1); + break; + + case 13: + // SYNC STROBE FAST + P_SpawnStrobeFlash (sector, FASTDARK, 1); + break; + + case 14: + // DOOR RAISE IN 5 MINUTES + P_SpawnDoorRaiseIn5Mins (sector, i); + break; + + case 17: + P_SpawnFireFlicker(sector); + break; + } + } + + + // Init line EFFECTs + numlinespecials = 0; + for (i = 0;i < numlines; i++) + { + switch(lines[i].special) + { + case 48: // EFFECT FIRSTCOL SCROLL+ + case 142: + case 143: + case 149: + linespeciallist[numlinespecials] = &lines[i]; + numlinespecials++; + break; + } + } + + // Init other misc stuff + for (i = 0;i < MAXCEILINGS;i++) + activeceilings[i] = NULL; + + for (i = 0;i < MAXPLATS;i++) + activeplats[i] = NULL; + + for (i = 0;i < MAXBUTTONS;i++) + memset(&buttonlist[i],0,sizeof(button_t)); + + // villsa [STRIFE] + P_InitSlidingDoorFrames(); +} diff --git a/games/NXDoom/src/strife/p_spec.h b/games/NXDoom/src/strife/p_spec.h new file mode 100644 index 00000000000..684386afec7 --- /dev/null +++ b/games/NXDoom/src/strife/p_spec.h @@ -0,0 +1,678 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// Implements special effects: +// Texture animation, height or lighting changes +// according to adjacent sectors, respective +// utility functions, etc. +// + + +#ifndef __P_SPEC__ +#define __P_SPEC__ + + +// +// End-level timer (-TIMER option) +// +extern boolean levelTimer; +extern int levelTimeCount; + + +// Define values for map objects +#define MO_TELEPORTMAN 14 + + +// at game start +void P_InitPicAnims (void); + +// villsa [STRIFE] +typedef enum +{ + FLOOR_WATER = 0, + FLOOR_SLIME = 1, + FLOOR_SOLID = 2, + FLOOR_END = -1 +} terraintype_e; + +void P_InitTerrainTypes(void); // villsa [STRIFE] +terraintype_e P_GetTerrainType(mobj_t* mobj); // villsa [STRIFE] + +// at map load +void P_SpawnSpecials (void); + +// every tic +void P_UpdateSpecials (void); + +// when needed +boolean +P_UseSpecialLine +( mobj_t* thing, + line_t* line, + int side ); + +void +P_ShootSpecialLine +( mobj_t* thing, + line_t* line ); + +void +P_CrossSpecialLine +( int linenum, + int side, + mobj_t* thing ); + +void P_PlayerInSpecialSector (player_t* player); + +int +twoSided +( int sector, + int line ); + +sector_t* +getSector +( int currentSector, + int line, + int side ); + +side_t* +getSide +( int currentSector, + int line, + int side ); + +fixed_t P_FindLowestFloorSurrounding(sector_t* sec); +fixed_t P_FindHighestFloorSurrounding(sector_t* sec); + +fixed_t +P_FindNextHighestFloor +( sector_t* sec, + int currentheight ); + +fixed_t P_FindLowestCeilingSurrounding(sector_t* sec); +fixed_t P_FindHighestCeilingSurrounding(sector_t* sec); + +int +P_FindSectorFromLineTag +( line_t* line, + int start ); + +int +P_FindMinSurroundingLight +( sector_t* sector, + int max ); + +sector_t* +getNextSector +( line_t* line, + sector_t* sec ); + + +// +// SPECIAL +// +int EV_DoDonut(line_t* line); +boolean EV_ClearForceFields(line_t* line); // villsa [STRIFE] + + +// +// P_LIGHTS +// +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int count; + int maxlight; + int minlight; + +} fireflicker_t; + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int count; + int maxlight; + int minlight; + int maxtime; + int mintime; + +} lightflash_t; + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int count; + int minlight; + int maxlight; + int darktime; + int brighttime; + +} strobe_t; + + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + int minlight; + int maxlight; + int direction; + +} glow_t; + + +#define GLOWSPEED 8 +#define STROBEBRIGHT 5 +#define FASTDARK 15 +#define SLOWDARK 35 + +void P_SpawnFireFlicker (sector_t* sector); +void T_LightFlash (lightflash_t* flash); +void P_SpawnLightFlash (sector_t* sector); +void T_StrobeFlash (strobe_t* flash); + +void +P_SpawnStrobeFlash +( sector_t* sector, + int fastOrSlow, + int inSync ); + +void EV_StartLightStrobing(line_t* line); +void EV_TurnTagLightsOff(line_t* line); + +void +EV_LightTurnOn +( line_t* line, + int bright ); + +void T_Glow(glow_t* g); +void P_SpawnGlowingLight(sector_t* sector); + + + + +// +// P_SWITCH +// +typedef struct +{ + char name1[9]; + char name2[9]; + short episode; + int sound; // villsa [STRIFE] + +} switchlist_t; + + +typedef enum +{ + top, + middle, + bottom + +} bwhere_e; + + +typedef struct +{ + line_t* line; + bwhere_e where; + int btexture; + int btimer; + degenmobj_t *soundorg; + +} button_t; + + + + + // max # of wall switches in a level +#define MAXSWITCHES 80 // villsa [STRIFE] changed from 50 to 80 + + // 4 players, 4 buttons each at once, max. +#define MAXBUTTONS 16 + + // 1 second, in ticks. +#define BUTTONTIME 35 + +extern button_t buttonlist[MAXBUTTONS]; + +void +P_ChangeSwitchTexture +( line_t* line, + int useAgain ); + +void P_InitSwitchList(void); + + +// +// P_PLATS +// +typedef enum +{ + up, + down, + waiting, + in_stasis + +} plat_e; + + + +typedef enum +{ + perpetualRaise, + downWaitUpStay, + slowDWUS, // villsa [STRIFE] + raiseAndChange, + raiseToNearestAndChange, + blazeDWUS, + upWaitDownStay // villsa [STRIFE] + +} plattype_e; + + + +typedef struct +{ + thinker_t thinker; + sector_t* sector; + fixed_t speed; + fixed_t low; + fixed_t high; + int wait; + int count; + plat_e status; + plat_e oldstatus; + boolean crush; + int tag; + plattype_e type; + +} plat_t; + + + +#define PLATWAIT 3 +#define PLATSPEED FRACUNIT +#define MAXPLATS 30 + + +extern plat_t* activeplats[MAXPLATS]; + +void T_PlatRaise(plat_t* plat); + +int +EV_DoPlat +( line_t* line, + plattype_e type, + int amount ); + +void P_AddActivePlat(plat_t* plat); +void P_RemoveActivePlat(plat_t* plat); +void EV_StopPlat(line_t* line); +void P_ActivateInStasis(int tag); + + +// +// P_DOORS +// +typedef enum +{ + vld_normal, + vld_close30ThenOpen, + vld_close, + vld_open, + vld_raiseIn5Mins, + vld_blazeRaise, + vld_blazeOpen, + vld_blazeClose, + vld_shopClose, // villsa [STRIFE] + vld_splitRaiseNearest, // villsa [STRIFE] + vld_splitOpen // villsa [STRIFE] + +} vldoor_e; + + + +typedef struct +{ + thinker_t thinker; + vldoor_e type; + sector_t* sector; + fixed_t topheight; + fixed_t speed; + + // 1 = up, 0 = waiting at top, -1 = down + int direction; + + // tics to wait at the top + int topwait; + // (keep in case a door going down is reset) + // when it reaches 0, start going down + int topcountdown; + + // villsa [STRIFE] new field - sound to play when opening + int opensound; + + // villsa [STRIFE] new field - sound to play when closing + int closesound; + +} vldoor_t; + + + +#define VDOORSPEED FRACUNIT*2 +#define VDOORWAIT 150 + +void +EV_VerticalDoor +( line_t* line, + mobj_t* thing ); + +int +EV_DoDoor +( line_t* line, + vldoor_e type ); + +int +EV_DoLockedDoor +( line_t* line, + vldoor_e type, + mobj_t* thing ); + +void T_VerticalDoor (vldoor_t* door); +void P_SpawnDoorCloseIn30 (sector_t* sec); + +void +P_SpawnDoorRaiseIn5Mins +( sector_t* sec, + int secnum ); + + + +// villsa [STRIFE] resurrected sliding doors +// +// Sliding doors... +// +typedef enum +{ + sd_opening, + sd_waiting, + sd_closing + +} sd_e; + + + +typedef enum +{ + sdt_openOnly, + sdt_closeOnly, + sdt_openAndClose + +} sdt_e; + + + +// villsa [STRIFE] Rogue added a second line_t in the struct +// backsector is removed +typedef struct +{ + thinker_t thinker; + sdt_e type; + line_t* line1; + line_t* line2; + int frame; + int whichDoorIndex; + int timer; + sector_t* frontsector; + sd_e status; + +} slidedoor_t; + +// villsa [STRIFE] no front/back frames +typedef struct +{ + char frame1[9]; + char frame2[9]; + char frame3[9]; + char frame4[9]; + char frame5[9]; + char frame6[9]; + char frame7[9]; + char frame8[9]; + +} slidename_t; + +// villsa [STRIFE] no front/back frames +typedef struct +{ + int frames[8]; + +} slideframe_t; + +// haleyjd 09/29/10: [STRIFE] Externalized for savegames +void T_SlidingDoor(slidedoor_t* door); + + +// how many frames of animation +#define SNUMFRAMES 8 // villsa [STRIFE] changed from 4 to 8 + +#define SDOORWAIT TICRATE*3 +#define SWAITTICS 4 + +// how many diff. types of anims +#define MAXSLIDEDOORS 8 // villsa [STRIFE] changed from 5 to 8 + +void P_InitSlidingDoorFrames(void); +void EV_SlidingDoor(line_t* line, mobj_t* thing); +int EV_RemoteSlidingDoor(line_t* line, mobj_t* thing); + + + +// +// P_CEILNG +// +typedef enum +{ + lowerToFloor, + raiseToHighest, + lowerAndCrush, + crushAndRaise, + fastCrushAndRaise, + silentCrushAndRaise + +} ceiling_e; + + + +typedef struct +{ + thinker_t thinker; + ceiling_e type; + sector_t* sector; + fixed_t bottomheight; + fixed_t topheight; + fixed_t speed; + boolean crush; + + // 1 = up, 0 = waiting, -1 = down + int direction; + + // ID + int tag; + int olddirection; + +} ceiling_t; + + + + + +#define CEILSPEED FRACUNIT +#define CEILWAIT 150 +#define MAXCEILINGS 30 + +extern ceiling_t* activeceilings[MAXCEILINGS]; + +int +EV_DoCeiling +( line_t* line, + ceiling_e type ); + +void T_MoveCeiling (ceiling_t* ceiling); +void P_AddActiveCeiling(ceiling_t* c); +void P_RemoveActiveCeiling(ceiling_t* c); +int EV_CeilingCrushStop(line_t* line); +void P_ActivateInStasisCeiling(line_t* line); + + +// +// P_FLOOR +// +typedef enum +{ + // lower floor to highest surrounding floor + lowerFloor, + + // lower floor to lowest surrounding floor + lowerFloorToLowest, + + // lower floor to highest surrounding floor VERY FAST + turboLower, + + // raise floor to lowest surrounding CEILING + raiseFloor, + + // raise floor to next highest surrounding floor + raiseFloorToNearest, + + // raise floor to shortest height texture around it + raiseToTexture, + + // lower floor to lowest surrounding floor + // and change floorpic + lowerAndChange, + + raiseFloor64, // [STRIFE] changed from 24 to 64 + raiseFloor24AndChange, + raiseFloorCrush, + + // raise to next highest floor, turbo-speed + raiseFloorTurbo, + donutRaise, + raiseFloor512, + + // [STRIFE] New floor type - used for the coolant reactor pit + raiseFloor512AndChange + +} floor_e; + + + + +typedef enum +{ + build8, // slowly build by 8 + turbo16, // quickly build by 16 + buildDown16 // haleyjd 09/24/10: [STRIFE] new stair type +} stair_e; + + + +typedef struct +{ + thinker_t thinker; + floor_e type; + boolean crush; + sector_t* sector; + int direction; + int newspecial; + short texture; + fixed_t floordestheight; + fixed_t speed; + +} floormove_t; + + + +#define FLOORSPEED FRACUNIT + +typedef enum +{ + ok, + crushed, + pastdest + +} result_e; + +result_e +T_MovePlane +( sector_t* sector, + fixed_t speed, + fixed_t dest, + boolean crush, + int floorOrCeiling, + int direction ); + +int +EV_BuildStairs +( line_t* line, + stair_e type ); + +int +EV_DoFloor +( line_t* line, + floor_e floortype ); + +void T_MoveFloor( floormove_t* floor); + +// +// P_TELEPT +// + +// [STRIFE] Teleportation flags - teleflags +// Not to be conflated with telefrags, though they be tangentially related ;) +typedef enum teleflags +{ + TF_NOSRCSND = 0x01, + TF_NODSTSND = 0x02, + TF_NODSTFOG = 0x10, + TF_NOSRCFOG = 0x20, + + TF_NORMAL = 0, + TF_DSTSILENCE = (TF_NODSTSND|TF_NODSTFOG), // 0x12 (18) (Not used) + TF_SRCSILENCE = (TF_NOSRCSND|TF_NOSRCFOG), // 0x21 (33) + TF_FULLSILENCE = (TF_SRCSILENCE|TF_DSTSILENCE) // 0x33 (51) + +} teleflags_e; + +int +EV_Teleport +( line_t* line, + int side, + mobj_t* thing, + teleflags_e flags); + +#endif diff --git a/games/NXDoom/src/strife/p_switch.c b/games/NXDoom/src/strife/p_switch.c new file mode 100644 index 00000000000..849ab2bc07f --- /dev/null +++ b/games/NXDoom/src/strife/p_switch.c @@ -0,0 +1,1078 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// +// DESCRIPTION: +// Switches, buttons. Two-state animation. Exits. +// + +#include + +#include "i_system.h" +#include "deh_main.h" +#include "doomdef.h" +#include "p_local.h" + +#include "g_game.h" +#include "d_main.h" // villsa [STRIFE] +#include "z_zone.h" // villsa [STRIFE] +#include "w_wad.h" // villsa [STRIFE] +#include "s_sound.h" +#include "m_random.h" // haleyjd [STRIFE] +#include "p_dialog.h" +#include "p_local.h" // haleyjd [STRIFE] +#include "m_bbox.h" // villsa [STRIFE] +#include "m_misc.h" + +// Data. +#include "sounds.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +// +// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE +// +// villsa [STRIFE] new switch list +switchlist_t alphSwitchList[] = +{ + { "GLASS01", "GLASS02", 1, sfx_bglass }, + { "GLASS03", "GLASS04", 1, sfx_bglass }, + { "GLASS05", "GLASS06", 1, sfx_bglass }, + { "GLASS07", "GLASS08", 1, sfx_bglass }, + { "GLASS17", "GLASS18", 1, sfx_bglass }, + { "GLASS19", "GLASS20", 1, sfx_bglass }, + { "SWKNOB01", "SWKNOB02", 1, sfx_swknob }, + { "SWLITE01", "SWLITE02", 1, sfx_None }, + { "SWCHN01", "SWCHN02", 1, sfx_pulchn }, + { "COMP01", "COMP04B", 1, sfx_bglass }, + { "COMP05", "COMP12B", 1, sfx_bglass }, + { "COMP09", "COMP12B", 1, sfx_bglass }, + { "COMP12", "COMP04B", 1, sfx_bglass }, + { "COMP13", "COMP12B", 1, sfx_bglass }, + { "COMP17", "COMP20B", 1, sfx_bglass }, + { "COMP21", "COMP28B", 1, sfx_bglass }, + { "WALTEK09", "WALTEKB1", 1, sfx_None }, + { "WALTEK10", "WALTEKB1", 1, sfx_None }, + { "WALTEK15", "WALTEKB1", 1, sfx_None }, + { "SWFORC01", "SWFORC02", 1, sfx_None }, + { "SWEXIT01", "SWEXIT02", 1, sfx_None }, + { "DORSBK01", "DORSBK02", 1, sfx_swston }, + { "SWSLD01", "SWSLD02", 1, sfx_None }, + { "DORWS04", "DORWS05", 1, sfx_swbolt }, + { "SWIRON01", "SWIRON02", 1, sfx_None }, + { "GLASS09", "GLASS10", 2, sfx_bglass }, + { "GLASS11", "GLASS12", 2, sfx_bglass }, + { "GLASS13", "GLASS14", 2, sfx_bglass }, + { "GLASS15", "GLASS16", 2, sfx_bglass }, + { "SWFORC03", "SWFORC04", 2, sfx_None }, + { "SWCIT01", "SWCIT02", 2, sfx_None }, + { "SWTRMG01", "SWTRMG04", 2, sfx_None }, + { "SWMETL01", "SWMETL02", 2, sfx_None }, + { "SWWOOD01", "SWWOOD02", 2, sfx_None }, + { "SWTKBL01", "SWTKBL02", 2, sfx_None }, + { "AZWAL21", "AZWAL22", 2, sfx_None }, + { "SWINDT01", "SWINDT02", 2, sfx_None }, + { "SWRUST01", "SWRUST02", 2, sfx_None }, + { "SWCHAP01", "SWCHAP02", 2, sfx_None }, + { "SWALIN01", "SWALIN02", 2, sfx_None }, + { "SWWALG01", "SWWALG02", 2, sfx_None }, + { "SWWALG03", "SWWALG04", 2, sfx_None }, + { "SWTRAM01", "SWTRAM02", 2, sfx_None }, + { "SWTRAM03", "SWTRAM04", 2, sfx_None }, + { "SWORC01", "SWORC02", 2, sfx_None }, + { "SWBRIK01", "SWBRIK02", 2, sfx_None }, + { "SWIRON03", "SWIRON04", 2, sfx_None }, + { "SWIRON05", "SWIRON06", 2, sfx_None }, + { "SWIRON07", "SWIRON08", 2, sfx_None }, + { "SWCARD01", "SWCARD02", 2, sfx_keycrd }, + { "SWSIGN01", "SWSIGN02", 2, sfx_None }, + { "SWLEV01", "SWLEV02", 2, sfx_None }, + { "SWLEV03", "SWLEV04", 2, sfx_None }, + { "SWLEV05", "SWLEV06", 2, sfx_None }, + { "SWBRN01", "SWBRN02", 2, sfx_keycrd }, + { "SWPIP01", "SWPIP02", 2, sfx_valve }, + { "SWPALM01", "SWPALM02", 2, sfx_swscan }, + { "SWKNOB03", "SWKNOB04", 2, sfx_swknob }, + { "ALTSW01", "ALTSW02", 2, sfx_None }, + { "COMP25", "COMP28B", 2, sfx_bglass }, + { "COMP29", "COMP20B", 2, sfx_bglass }, + { "COMP33", "COMP50", 2, sfx_bglass }, + { "COMP42", "COMP51", 2, sfx_bglass }, + { "GODSCRN1", "GODSCRN2", 2, sfx_difool }, + { "ALIEN04", "ALIEN05", 2, sfx_None }, + { "CITADL04", "CITADL05", 2, sfx_None }, + { "SWITE03", "SWITE04", 2, sfx_None }, + { "SWTELP01", "SWTELP02", 2, sfx_None }, + { "BRNSCN01", "BRNSCN05", 2, sfx_firxpl }, +}; + +int switchlist[MAXSWITCHES * 2]; +int numswitches; +button_t buttonlist[MAXBUTTONS]; + +// +// P_InitSwitchList +// Only called at game initialization. +// +void P_InitSwitchList(void) +{ + int i, slindex, episode; + + // Note that this is called "episode" here but it's actually something + // quite different. As we progress from Shareware->Registered->Doom II + // we support more switch textures. + if (isregistered) + { + episode = 2; + } + else + { + episode = 1; + } + + slindex = 0; + + for (i = 0; i < arrlen(alphSwitchList); i++) + { + if (alphSwitchList[i].episode <= episode) + { + switchlist[slindex++] = + R_TextureNumForName(DEH_String(alphSwitchList[i].name1)); + switchlist[slindex++] = + R_TextureNumForName(DEH_String(alphSwitchList[i].name2)); + } + } + + numswitches = slindex / 2; + switchlist[slindex] = -1; +} + + +// +// P_StartButton +// Start a button counting down till it turns off. +// +void P_StartButton(line_t* line, bwhere_e w, int texture, int time) +{ + int i; + + // See if button is already pressed + for(i = 0; i < MAXBUTTONS; i++) + { + if(buttonlist[i].btimer && buttonlist[i].line == line) + return; + } + + + + for(i = 0; i < MAXBUTTONS; i++) + { + if(!buttonlist[i].btimer) + { + buttonlist[i].line = line; + buttonlist[i].where = w; + buttonlist[i].btexture = texture; + buttonlist[i].btimer = time; + buttonlist[i].soundorg = &line->frontsector->soundorg; + return; + } + } + + I_Error("P_StartButton: no button slots left!"); +} + + +// +// P_SpawnBrokenGlass +// villsa [STRIFE] new function +// +static void P_SpawnBrokenGlass(line_t* line) +{ + fixed_t x1; + fixed_t x2; + fixed_t y1; + fixed_t y2; + int i; + mobj_t* glass; + angle_t an; + + x1 = (line->v2->x + line->v1->x) / 2; + y1 = (line->v2->y + line->v1->y) / 2; + x2 = ((line->frontsector->soundorg.x - x1) / 5) + x1; + y2 = ((line->frontsector->soundorg.y - y1) / 5) + y1; + + for(i = 0; i < 7; i++) + { + glass = P_SpawnMobj(x2, y2, ONFLOORZ, MT_JUNK); + glass->z += (24*FRACUNIT); + glass->flags |= (MF_SHADOW|MF_MVIS); + + P_SetMobjState(glass, P_Random() % 3 + S_SHRD_03); // 284 + + an = ((P_Random() << 13) / 255); + + glass->angle = (an << ANGLETOFINESHIFT); + glass->momx = FixedMul(finecosine[an], (P_Random() & 3) << FRACBITS); + glass->momy = FixedMul(finesine[an], (P_Random() & 3) << FRACBITS); + glass->momz = (P_Random() & 7) << FRACBITS; + glass->tics += (P_Random() + 7) & 7; + } +} + + +// +// Function that changes wall texture. +// Tell it if switch is ok to use again (1=yes, it's a button). +// +void P_ChangeSwitchTexture(line_t* line, int useAgain) +{ + int texTop; + int texMid; + int texBot; + int i; + int sound; + boolean breakglass; // villsa [STRIFE] + switchlist_t* sl; // villsa [STRIFE] + + breakglass = false; // villsa [STRIFE] + + texTop = sides[line->sidenum[0]].toptexture; + texMid = sides[line->sidenum[0]].midtexture; + texBot = sides[line->sidenum[0]].bottomtexture; + + sound = sfx_swtchn; + + // villsa [STRIFE] check for linetype 182 (break glass) + if(line->special == 182) + { + line->flags &= ~ML_BLOCKING; + breakglass = true; + + if(useAgain) + { + // haleyjd 09/21/10: Corrected (>> 16 == next field) + texTop = 0; + texBot = 0; + } + + if(texMid) // haleyjd 09/21/10: Corrected (>> 16 == next field) + useAgain = 0; + + sound = sfx_bglass; + } + + if(!useAgain) + line->special = 0; + + for(i = 0; i < numswitches*2; i++) + { + sl = &alphSwitchList[i / 2]; // villsa [STRIFE] + + if(switchlist[i] == texTop) + { + // villsa [STRIFE] set sound + if(sl->sound) + sound = sl->sound; + + // haleyjd 20141026: [STRIFE]: Rogue fixed wrong sound origin + S_StartSound(&line->frontsector->soundorg, sound); + sides[line->sidenum[0]].toptexture = switchlist[i^1]; + + if(useAgain) + P_StartButton(line,top,switchlist[i],BUTTONTIME); + + if(breakglass) + P_SpawnBrokenGlass(line); + + return; + } + else + { + if(switchlist[i] == texMid) + { + // villsa [STRIFE] set sound + if(sl->sound) + sound = sl->sound; + + // haleyjd 20141026: [STRIFE]: Rogue fixed wrong sound origin + S_StartSound(&line->frontsector->soundorg, sound); + sides[line->sidenum[0]].midtexture = switchlist[i^1]; + + // villsa [STRIFE] affect second side of line + // BUG: will crash if 1S line is marked with TWOSIDED flag! + if(line->flags & ML_TWOSIDED) + sides[line->sidenum[1]].midtexture = switchlist[i^1]; + + if(useAgain) + P_StartButton(line, middle,switchlist[i],BUTTONTIME); + + // villsa [STRIFE]: Mines Transmitter hack + if(sound == sfx_firxpl) + { + breakglass = true; + + // give quest flag 29 to player + players[0].questflags |= QF_QUEST29; + + // give stamina/accuracy items + if(!netgame) + { + P_GiveItemToPlayer(players, SPR_TOKN, MT_TOKEN_STAMINA); + P_GiveItemToPlayer(players, SPR_TOKN, MT_TOKEN_NEW_ACCURACY); + } + + } + + // villsa [STRIFE] + if(breakglass || sound == sfx_bglass) + P_SpawnBrokenGlass(line); + + return; + } + else + { + if(switchlist[i] == texBot) + { + // villsa [STRIFE] set sound + if(sl->sound) + sound = sl->sound; + + // haleyjd 20141026: [STRIFE]: Rogue fixed wrong sound origin + S_StartSound(&line->frontsector->soundorg, sound); + sides[line->sidenum[0]].bottomtexture = switchlist[i^1]; + + if(useAgain) + P_StartButton(line, bottom,switchlist[i],BUTTONTIME); + + if(breakglass) + P_SpawnBrokenGlass(line); + + return; + } + } + } + } +} + +// +// P_MoveWall +// +// villsa [STRIFE] New function. +// Dynamically move a solid line. Unused in Strife +// +static void P_MoveWall(line_t *line, mobj_t *thing) +{ + vertex_t *v2; + vertex_t *v1; + fixed_t x; + fixed_t y; + + v1 = line->v1; + v2 = line->v2; + S_StartSound(thing, sfx_stnmov); + + if (line->dx) + { + if (thing->x >= v1->x) + { + v1->y -= (8 * FRACUNIT); + v2->y -= (8 * FRACUNIT); + } + else + { + v1->y += (8 * FRACUNIT); + v2->y += (8 * FRACUNIT); + } + } + else + { + if (thing->y >= v1->y) + { + v1->x -= (8 * FRACUNIT); + v2->x -= (8 * FRACUNIT); + } + else + { + v1->x += (8 * FRACUNIT); + v2->x += (8 * FRACUNIT); + } + } + + if (v1->x >= v2->x) + { + line->bbox[BOXLEFT] = v2->x; + x = v1->x; + } + else + { + line->bbox[BOXLEFT] = v1->x; + x = v2->x; + } + + line->bbox[BOXRIGHT] = x; + + if (v1->y >= v2->y) + { + line->bbox[BOXBOTTOM] = v2->y; + y = v1->y; + } + else + { + line->bbox[BOXBOTTOM] = v1->y; + y = v2->y; + } + + line->bbox[BOXTOP] = y; +} + +// villsa [STRIFE] +static char usemessage[92]; + +// +// P_UseSpecialLine +// Called when a thing uses a special line. +// Only the front sides of lines are usable. +// +boolean P_UseSpecialLine(mobj_t* thing, line_t* line, int side) +{ + // Err... + // Use the back sides of VERY SPECIAL lines... + if (side) + { + switch(line->special) + { + case 148: // haleyjd [STRIFE] + break; + + default: + return false; + } + } + + // Switches that other things can activate. + if (!thing->player) + { + // never open secret doors + if (line->flags & ML_SECRET) + return false; + + switch(line->special) + { + case 1: // MANUAL DOOR RAISE + case 31: // haleyjd [STRIFE] + case 144: // haleyjd [STRIFE] Manual sliding door + break; + + default: + return false; + break; + } + } + + // do something + switch(line->special) + { + // MANUALS + case 1: // Vertical Door + case 26: // DR ID Card + case 27: // DR Pass Card + case 28: // DR ID Badge + case 31: // Manual door open + case 32: // D1 ID Card + case 33: // D1 ID Badge + case 34: // D1 Pass Card + case 117: // Blazing door raise + case 118: // Blazing door open + case 156: // haleyjd [STRIFE] D1 Brass Key + case 157: // haleyjd [STRIFE] D1 Silver Key + case 158: // haleyjd [STRIFE] D1 Gold Key + case 159: // haleyjd [STRIFE] DR Gold Key + case 160: // haleyjd [STRIFE] DR Silver Key + case 161: // haleyjd [STRIFE] DR Brass Key + case 165: // villsa [STRIFE] That doesn't seem to work + case 166: // haleyjd [STRIFE] DR Hand Print + case 169: // haleyjd [STRIFE] DR Base Key + case 170: // haleyjd [STRIFE] DR Gov's Key + case 190: // haleyjd [STRIFE] DR Order Key + case 205: // villsa [STRIFE] Available in retail only + case 213: // haleyjd [STRIFE] DR Chalice + case 217: // haleyjd [STRIFE] DR Core Key + case 221: // haleyjd [STRIFE] DR Mauler Key + case 224: // haleyjd [STRIFE] DR Chapel Key + case 225: // haleyjd [STRIFE] DR Catacomb Key + case 232: // villsa [STRIFE] DR Oracle Pass + EV_VerticalDoor (line, thing); + break; + + // haleyjd: For the sake of our sanity, I have reordered all the line + // specials from this point down so that they are strictly in numeric + // order, and not divided up in a semi-arbitrary fashion. + + case 7: + // Build Stairs - [STRIFE] Verified unmodified + if (EV_BuildStairs(line,build8)) + P_ChangeSwitchTexture(line,0); + break; + + case 9: + // Change Donut - [STRIFE] Verified unmodified + if (EV_DoDonut(line)) + P_ChangeSwitchTexture(line,0); + break; + + case 11: + // Exit level - [STRIFE] Modified to take tag, etc. + P_ChangeSwitchTexture(line, 1); + if(levelTimer && levelTimeCount) + break; + G_ExitLevel(line->tag); + break; + + case 14: + // Raise Floor 32 and change texture - [STRIFE] Verified unmodified + if (EV_DoPlat(line, raiseAndChange,32)) + P_ChangeSwitchTexture(line,0); + break; + + case 15: + // Raise Floor 24 and change texture + if (EV_DoPlat(line, raiseAndChange,24)) + P_ChangeSwitchTexture(line,0); + break; + + case 18: + // Raise Floor to next highest floor - [STRIFE] Verified unmodified + if (EV_DoFloor(line, raiseFloorToNearest)) + P_ChangeSwitchTexture(line,0); + break; + + case 20: + // Raise Plat next highest floor and change texture - [STRIFE] Verified unmodified + if(EV_DoPlat(line, raiseToNearestAndChange, 0)) + P_ChangeSwitchTexture(line,0); + break; + + case 21: + // PlatDownWaitUpStay - [STRIFE] Verified unmodified + if (EV_DoPlat(line, downWaitUpStay,0)) + P_ChangeSwitchTexture(line,0); + break; + + case 23: + // Lower Floor to Lowest - [STRIFE] Verified unmodified + if (EV_DoFloor(line,lowerFloorToLowest)) + P_ChangeSwitchTexture(line,0); + break; + + case 29: + // Raise Door - [STRIFE] Verified unmodified + if (EV_DoDoor(line,vld_normal)) + P_ChangeSwitchTexture(line,0); + break; + + case 40: + // villsa [STRIFE] Split Open Door + if(EV_DoDoor(line, vld_splitOpen)) + P_ChangeSwitchTexture(line, 0); + break; // haleyjd + + case 41: + // Lower Ceiling to Floor - [STRIFE] Verified unmodified + if (EV_DoCeiling(line,lowerToFloor)) + P_ChangeSwitchTexture(line,0); + break; + + case 42: + // Close Door - [STRIFE] Verified unmodified + if (EV_DoDoor(line,vld_close)) + P_ChangeSwitchTexture(line,1); + break; + + case 43: + // Lower Ceiling to Floor - [STRIFE] Verified unmodified + if (EV_DoCeiling(line,lowerToFloor)) + P_ChangeSwitchTexture(line,1); + break; + + case 45: + // Lower Floor to Surrounding floor height - [STRIFE] Verified unmodified + if (EV_DoFloor(line,lowerFloor)) + P_ChangeSwitchTexture(line,1); + break; + + case 49: + // Ceiling Crush And Raise - [STRIFE] Verified unmodified + if (EV_DoCeiling(line,crushAndRaise)) + P_ChangeSwitchTexture(line,0); + break; + + case 50: + // Close Door - [STRIFE] Verified unmodified + if (EV_DoDoor(line,vld_close)) + P_ChangeSwitchTexture(line,0); + break; + + case 51: + // [STRIFE] Modifed into S1 Start Finale (was Secret Exit) + P_ChangeSwitchTexture(line,0); + G_StartFinale(); + break; + + case 55: + // Raise Floor Crush - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloorCrush)) + P_ChangeSwitchTexture(line,0); + break; + + case 60: + // Lower Floor to Lowest - [STRIFE] Verified unmodified + if (EV_DoFloor(line,lowerFloorToLowest)) + P_ChangeSwitchTexture(line,1); + break; + + case 61: + // Open Door - [STRIFE] Verified unmodified + if (EV_DoDoor(line,vld_open)) + P_ChangeSwitchTexture(line,1); + break; + + case 62: + // PlatDownWaitUpStay - [STRIFE] Verified unmodified + if (EV_DoPlat(line, downWaitUpStay,1)) + P_ChangeSwitchTexture(line,1); + break; + + case 63: + // Raise Door - [STRIFE] Verified unmodified + if (EV_DoDoor(line,vld_normal)) + P_ChangeSwitchTexture(line,1); + break; + + case 64: + // Raise Floor to ceiling - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloor)) + P_ChangeSwitchTexture(line,1); + break; + + case 65: + // Raise Floor Crush - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloorCrush)) + P_ChangeSwitchTexture(line,1); + break; + + case 66: + // Raise Floor 24 and change texture - [STRIFE] Verified unmodified + if (EV_DoPlat(line, raiseAndChange, 24)) + P_ChangeSwitchTexture(line,1); + break; + + case 67: + // Raise Floor 32 and change texture - [STRIFE] Verified unmodified + if (EV_DoPlat(line, raiseAndChange, 32)) + P_ChangeSwitchTexture(line,1); + break; + + case 68: + // Raise Plat to next highest floor and change texture - [STRIFE] Verified unmodified + if (EV_DoPlat(line, raiseToNearestAndChange, 0)) + P_ChangeSwitchTexture(line,1); + break; + + case 69: + // Raise Floor to next highest floor - [STRIFE] Verified unmodified + if (EV_DoFloor(line, raiseFloorToNearest)) + P_ChangeSwitchTexture(line,1); + break; + + case 70: + // Turbo Lower Floor - [STRIFE] Verified unmodified + if (EV_DoFloor(line,turboLower)) + P_ChangeSwitchTexture(line,1); + break; + + case 71: + // Turbo Lower Floor - [STRIFE] Verified unmodified + if (EV_DoFloor(line,turboLower)) + P_ChangeSwitchTexture(line,0); + break; + + case 101: + // Raise Floor - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloor)) + P_ChangeSwitchTexture(line,0); + break; + + case 102: + // Lower Floor to Surrounding floor height - [STRIFE] Verified unmodified + if (EV_DoFloor(line,lowerFloor)) + P_ChangeSwitchTexture(line,0); + break; + + case 103: + // Open Door - [STRIFE] Verified unmodified + if (EV_DoDoor(line,vld_open)) + P_ChangeSwitchTexture(line,0); + break; + + case 111: + // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified + if (EV_DoDoor (line,vld_blazeRaise)) + P_ChangeSwitchTexture(line,0); + break; + + case 112: + // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified + if (EV_DoDoor (line,vld_blazeOpen)) + P_ChangeSwitchTexture(line,0); + break; + + case 113: + // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified + if (EV_DoDoor (line,vld_blazeClose)) + P_ChangeSwitchTexture(line,0); + break; + + case 114: + // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified + if (EV_DoDoor (line,vld_blazeRaise)) + P_ChangeSwitchTexture(line,1); + break; + + case 115: + // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified + if (EV_DoDoor (line,vld_blazeOpen)) + P_ChangeSwitchTexture(line,1); + break; + + case 116: + // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified + if (EV_DoDoor (line,vld_blazeClose)) + P_ChangeSwitchTexture(line,1); + break; + + case 122: + // Blazing PlatDownWaitUpStay - [STRIFE] Verified unmodified + if(EV_DoPlat(line, blazeDWUS, 0)) + P_ChangeSwitchTexture(line,0); + break; + + case 123: + // Blazing PlatDownWaitUpStay - [STRIFE] Verified unmodified + if(EV_DoPlat(line, blazeDWUS, 0)) + P_ChangeSwitchTexture(line,1); + break; + + case 127: + // Build Stairs Turbo 16 - [STRIFE] Verified unmodified + if (EV_BuildStairs(line,turbo16)) + P_ChangeSwitchTexture(line,0); + break; + + case 131: + // Raise Floor Turbo - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloorTurbo)) + P_ChangeSwitchTexture(line,0); + break; + + case 132: + // Raise Floor Turbo - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloorTurbo)) + P_ChangeSwitchTexture(line,1); + break; + + case 133: // [STRIFE] TODO - which key is it? + case 135: // [STRIFE] TODO - which key is it? + case 137: // [STRIFE] TODO - which key is it? + if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) + P_ChangeSwitchTexture(line,0); + break; + + case 99: // [STRIFE] TODO: which key is it? + case 134: // [STRIFE] TODO: which key is it? + case 136: // [STRIFE] TODO: which key is it? + if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) + P_ChangeSwitchTexture(line,1); + break; + + case 138: + // Light Turn On - [STRIFE] Verified unmodified + EV_LightTurnOn(line,255); + P_ChangeSwitchTexture(line,1); + break; + + case 139: + // Light Turn Off - [STRIFE] Verified unmodified + EV_LightTurnOn(line,35); + P_ChangeSwitchTexture(line,1); + break; + + case 140: + // Raise Floor 512 - [STRIFE] Verified unmodified + if (EV_DoFloor(line,raiseFloor512)) + P_ChangeSwitchTexture(line,0); + break; + + case 144: + // villsa [STRIFE] manual sliding door + EV_SlidingDoor(line, thing); + break; + + case 146: + // haleyjd 09/24/10: [STRIFE] S1 Build Stairs Down 16 (new type) + if(EV_BuildStairs(line, buildDown16)) + P_ChangeSwitchTexture(line, 0); + break; + + case 147: + // haleyjd 09/24/10: [STRIFE] S1 Clear Force Fields + if(EV_ClearForceFields(line)) + P_ChangeSwitchTexture(line, 0); + break; + + case 148: + // haleyjd 09/16/10: [STRIFE] using forcefields hurts + P_DamageMobj(thing, NULL, NULL, 16); + P_Thrust(thing->player, thing->angle + ANG180, 125*FRACUNIT/16); + break; + + case 151: // villsa [STRIFE] BlzOpenDoor Gold key + case 152: // [STRIFE] TODO: which key is it? + case 153: // [STRIFE] TODO: which key is it? + if(EV_DoLockedDoor(line, vld_blazeOpen, thing)) + P_ChangeSwitchTexture(line, 1); + break; + + case 154: + // villsa [STRIFE] plat lower wait rise if have gold key + if(thing->player->cards[key_GoldKey]) + { + if(EV_DoPlat(line, downWaitUpStay, 0)) + P_ChangeSwitchTexture(line, 1); + } + else + { + thing->player->message = DEH_String("You need a gold key"); + S_StartSound(thing, sfx_oof); + } + break; + + case 155: + // villsa [STRIFE] raise plat wait lower + if(EV_DoPlat(line, upWaitDownStay, 0)) + P_ChangeSwitchTexture(line, 1); + break; + + case 162: // [STRIFE] TODO: which key is it? + case 163: // [STRIFE] TODO: which key is it? + case 164: // villsa [STRIFE] BlzOpenDoor Gold key + case 167: // [STRIFE] TODO: which key is it? + if(EV_DoLockedDoor(line, vld_blazeOpen, thing)) + P_ChangeSwitchTexture(line, 0); + break; + + case 168: // [STRIFE] TODO: which key is it? + // haleyjd 09/25/10: [STRIFE] SR Blaze Open Door ???? Key + if(EV_DoLockedDoor(line, vld_blazeOpen, thing)) + P_ChangeSwitchTexture(line, 1); + break; + + case 171: // [STRIFE] TODO: which key is it? + // haleyjd 09/25/10: [STRIFE] S1 Open Door ???? Key + if(EV_DoLockedDoor(line, vld_open, thing)) + P_ChangeSwitchTexture(line, 0); + break; + + case 172: // [STRIFE] TODO: which key is it? + case 173: // [STRIFE] TODO: which key is it? + case 176: // [STRIFE] TODO: which key is it? + case 191: // [STRIFE] TODO: which key is it? + case 192: // [STRIFE] TODO: which key is it? + case 223: // [STRIFE] TODO: which key is it? + if(EV_DoLockedDoor(line, vld_normal, thing)) + P_ChangeSwitchTexture(line, 1); + break; + + case 177: + // villsa [STRIFE] plat lower wait rise if have power3 key + if(thing->player->cards[key_Power3Key]) + { + if(EV_DoPlat(line, downWaitUpStay, 0)) + P_ChangeSwitchTexture(line, 1); + } + else + { + thing->player->message = DEH_String("You don't have the key"); + S_StartSound(thing, sfx_oof); + } + break; + + case 181: + // haleyjd 09/25/10: [STRIFE] S1 Floor Raise 512 & Change + if(EV_DoFloor(line, raiseFloor512AndChange)) + P_ChangeSwitchTexture(line, 0); + break; + + case 189: // [STRIFE] TODO: which key is it??? + // haleyjd 09/25/10: [STRIFE] S1 Split Open Door ???? Key + if(EV_DoLockedDoor(line, vld_splitOpen, thing)) + P_ChangeSwitchTexture(line, 0); + break; + + case 194: + // villsa [STRIFE] S1 Free Prisoners + if(EV_DoDoor(line, vld_open)) + { + P_ChangeSwitchTexture(line, 0); + P_FreePrisoners(); + } + break; + + case 199: + // haleyjd 09/25/10: [STRIFE] S1 Destroy Converter + if(EV_DoCeiling(line, lowerAndCrush)) + { + P_ChangeSwitchTexture(line, 0); + P_DestroyConverter(); + } + break; + + case 207: + // villsa [STRIFE] SR Remote Sliding Door + if(EV_RemoteSlidingDoor(line, thing)) + P_ChangeSwitchTexture(line, 1); + break; // haleyjd + + case 209: + // haleyjd 09/24/10: [STRIFE] S1 Build Stairs Down 16 if Have Chalice + if(!P_PlayerHasItem(thing->player, MT_INV_CHALICE)) + { + DEH_snprintf(usemessage, sizeof(usemessage), "You need the chalice!"); + thing->player->message = usemessage; + S_StartSound(thing, sfx_oof); + break; + } + else if(EV_BuildStairs(line, buildDown16)) + P_ChangeSwitchTexture(line, 0); + break; + + case 211: + // villsa [STRIFE] S1 Play VOC## sound + if(&players[consoleplayer] == thing->player && + thing->player->powers[pw_communicator]) + { + DEH_snprintf(usemessage, sizeof(usemessage), "voc%i", line->tag); + I_StartVoice(usemessage); + line->special = 0; + } + break; + + case 214: + // villsa [STRIFE] S1 slow lift lower wait up stay + if(EV_DoPlat(line, slowDWUS, 1)) + P_ChangeSwitchTexture(line, 1); + break; + + case 219: + // haleyjd 09/25/10: S1 Lower Floor Blue Crystal + if(!thing->player->cards[key_BlueCrystalKey]) + { + thing->player->message = DEH_String("You need the Blue Crystal"); + S_StartSound(thing, sfx_oof); + } + else if(EV_DoFloor(line, lowerFloor)) + P_ChangeSwitchTexture(line, 0); + break; + + case 220: + // haleyjd 09/25/10: S1 Lower Floor Red Crystal + if(!thing->player->cards[key_RedCrystalKey]) + { + thing->player->message = DEH_String("You need the Red Crystal"); + S_StartSound(thing, sfx_oof); + } + else if(EV_DoFloor(line, lowerFloor)) + P_ChangeSwitchTexture(line, 0); + break; + + case 226: + // villsa [STRIFE] S1 Complete Training Area + if(EV_DoFloor(line, lowerFloor)) + { + P_GiveItemToPlayer(thing->player, SPR_TOKN, MT_TOKEN_STAMINA); + P_GiveItemToPlayer(thing->player, SPR_TOKN, MT_TOKEN_NEW_ACCURACY); + P_ChangeSwitchTexture(line, 0); + DEH_snprintf(usemessage, sizeof(usemessage), + "Congratulations! You have completed the training area."); + thing->player->message = usemessage; + } + break; + + case 229: + // villsa [STRIFE] SR Sigil Sliding Door + if(thing->player->sigiltype == 4) + { + if(EV_RemoteSlidingDoor(line, thing)) + P_ChangeSwitchTexture(line, 1); + } + break; // haleyjd + + case 233: + // villsa [STRIFE] objective given after revealing the computer + if(!EV_DoDoor(line, vld_splitOpen)) + return true; + + P_ChangeSwitchTexture(line, 1); + GiveVoiceObjective("voc70", "log70", 0); + + // haleyjd: Strife used sprintf here, not a direct set. + DEH_snprintf(usemessage, sizeof(usemessage), + "Incoming Message from BlackBird..."); + thing->player->message = usemessage; + + break; + + case 234: + // haleyjd 09/24/10: [STRIFE] SR Raise Door if Quest 3 + if(!(thing->player->questflags & QF_QUEST3)) // QUEST3 == Irale + { + // BUG: doesn't make sfx_oof sound like all other message- + // giving door types. I highly doubt this was intentional. + DEH_snprintf(usemessage, sizeof(usemessage), + "That doesn't seem to work!"); + thing->player->message = usemessage; + } + else if(EV_DoDoor(line, vld_normal)) + P_ChangeSwitchTexture(line, 1); + break; + + case 235: + // haleyjd 09/25/10: [STRIFE] S1 Split Open Door if Have Sigil 4 + if(thing->player->sigiltype == 4) + { + if(EV_DoDoor(line, vld_splitOpen)) + P_ChangeSwitchTexture(line, 0); + } + break; + + case 666: + // villsa [STRIFE] SR Move Wall + P_MoveWall(line, thing); + break; + } + + return true; +} + diff --git a/games/NXDoom/src/strife/p_telept.c b/games/NXDoom/src/strife/p_telept.c new file mode 100644 index 00000000000..aff3b0c3b12 --- /dev/null +++ b/games/NXDoom/src/strife/p_telept.c @@ -0,0 +1,151 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Teleportation. +// + + + + +#include "doomdef.h" +#include "doomstat.h" + +#include "s_sound.h" + +#include "p_local.h" + + +// Data. +#include "sounds.h" + +// State. +#include "r_state.h" + + + +// +// TELEPORTATION +// +// haleyjd 09/22/10: [STRIFE] Modified to take a flags parameter to control +// silent teleportation. Rogue also removed the check for missiles, and the +// z-set was replaced with one in P_TeleportMove. +// +int +EV_Teleport +( line_t* line, + int side, + mobj_t* thing, + teleflags_e flags) +{ + int i; + int tag; + mobj_t* m; + mobj_t* fog = NULL; + unsigned an; + thinker_t* thinker; + sector_t* sector; + fixed_t oldx; + fixed_t oldy; + fixed_t oldz; + + // haleyjd 20110205 [STRIFE]: this is not checked here + // don't teleport missiles + //if (thing->flags & MF_MISSILE) + // return 0; + + // Don't teleport if hit back of line, + // so you can get out of teleporter. + if (side == 1) + return 0; + + tag = line->tag; + for (i = 0; i < numsectors; i++) + { + if (sectors[ i ].tag == tag ) + { + for (thinker = thinkercap.next; + thinker != &thinkercap; + thinker = thinker->next) + { + // not a mobj + if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + m = (mobj_t *)thinker; + + // not a teleportman + if (m->type != MT_TELEPORTMAN ) + continue; + + sector = m->subsector->sector; + // wrong sector + if (sector-sectors != i ) + continue; + + oldx = thing->x; + oldy = thing->y; + oldz = thing->z; + + if (!P_TeleportMove (thing, m->x, m->y)) + return 0; + + // fraggle: this was changed in final doom, + // problem between normal doom2 1.9 and final doom + // + // Note that although chex.exe is based on Final Doom, + // it does not have this quirk. + // + // haleyjd 20110205 [STRIFE] This code is *not* present, + // because of a z-set which Rogue added to P_TeleportMove. + /* + if (gameversion < exe_final || gameversion == exe_chex) + thing->z = thing->floorz; + */ + + if (thing->player) + thing->player->viewz = thing->z+thing->player->viewheight; + + // spawn teleport fog at source and destination + // haleyjd 09/22/10: [STRIFE] controlled by teleport flags + // BUG: Behavior would be undefined if this function were passed + // any combination of teleflags that has the NO*FOG but not the + // corresponding NO*SND flag - fortunately this is never done + // anywhere in the code. + if(!(flags & TF_NOSRCFOG)) + fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); + if(!(flags & TF_NOSRCSND)) + S_StartSound (fog, sfx_telept); + + an = m->angle >> ANGLETOFINESHIFT; + + if(!(flags & TF_NODSTFOG)) + fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an], + thing->z, MT_TFOG); + if(!(flags & TF_NODSTSND)) + S_StartSound (fog, sfx_telept); + + // don't move for a bit + if (thing->player) + thing->reactiontime = 18; + + thing->angle = m->angle; + thing->momx = thing->momy = thing->momz = 0; + return 1; + } + } + } + return 0; +} + diff --git a/games/NXDoom/src/strife/p_tick.c b/games/NXDoom/src/strife/p_tick.c new file mode 100644 index 00000000000..3c6caa06c21 --- /dev/null +++ b/games/NXDoom/src/strife/p_tick.c @@ -0,0 +1,160 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Archiving: SaveGame I/O. +// Thinker, Ticker. +// + + +#include "z_zone.h" +#include "p_local.h" + +#include "doomstat.h" + + +int leveltime; + +// +// THINKERS +// All thinkers should be allocated by Z_Malloc +// so they can be operated on uniformly. +// The actual structures will vary in size, +// but the first element must be thinker_t. +// + + + +// Both the head and tail of the thinker list. +thinker_t thinkercap; + + +// +// P_InitThinkers +// +// [STRIFE] Verified unmodified +// +void P_InitThinkers (void) +{ + thinkercap.prev = thinkercap.next = &thinkercap; +} + + + + +// +// P_AddThinker +// Adds a new thinker at the end of the list. +// +// [STRIFE] Verified unmodified +// +void P_AddThinker (thinker_t* thinker) +{ + thinkercap.prev->next = thinker; + thinker->next = &thinkercap; + thinker->prev = thinkercap.prev; + thinkercap.prev = thinker; +} + + + +// +// P_RemoveThinker +// Deallocation is lazy -- it will not actually be freed +// until its thinking turn comes up. +// +// [STRIFE] Verified unmodified +// +void P_RemoveThinker (thinker_t* thinker) +{ + // FIXME: NOP. + thinker->function.acv = (actionf_v)(-1); +} + + + +// +// P_AllocateThinker +// Allocates memory and adds a new thinker at the end of the list. +// +void P_AllocateThinker (thinker_t* thinker) +{ +} + +// +// P_RunThinkers +// +// [STRIFE] Verified unmodified +// +void P_RunThinkers (void) +{ + thinker_t *currentthinker, *nextthinker; + + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + if ( currentthinker->function.acv == (actionf_v)(-1) ) + { + // time to remove it + nextthinker = currentthinker->next; + currentthinker->next->prev = currentthinker->prev; + currentthinker->prev->next = currentthinker->next; + Z_Free (currentthinker); + } + else + { + if (currentthinker->function.acp1) + currentthinker->function.acp1 (currentthinker); + nextthinker = currentthinker->next; + } + + currentthinker = nextthinker; + } +} + +// +// P_Ticker +// +// [STRIFE] Menu pause behavior modified +// +void P_Ticker (void) +{ + int i; + + // run the tic + if (paused) + return; + + // pause if in menu and at least one tic has been run + // haleyjd 09/08/10 [STRIFE]: menuactive -> menupause + if (!netgame + && menupause + && !demoplayback + && players[consoleplayer].viewz != 1) + { + return; + } + + + for (i=0 ; i + +#include "doomdef.h" +#include "d_event.h" +#include "p_local.h" +#include "sounds.h" // villsa [STRIFE] +#include "p_dialog.h" // villsa [STRIFE] +#include "d_main.h" // villsa [STRIFE] +#include "doomstat.h" +#include "deh_str.h" // haleyjd [STRIFE] +#include "z_zone.h" +#include "w_wad.h" +#include "p_pspr.h" +#include "m_misc.h" +#include "m_random.h" +#include "s_sound.h" +#include "p_inter.h" + + + +// Index of the special effects (INVUL inverse) map. +#define LOOKPITCHAMOUNT 6 // villsa [STRIFE] +#define CENTERVIEWAMOUNT (LOOKPITCHAMOUNT + 2) // villsa [STRIFE] +#define LOOKUPMAX 90 // villsa [STRIFE] +#define LOOKDOWNMAX -110 // villsa [STRIFE] + + +void P_DropInventoryItem(player_t* player, int sprite); // villsa [STRIFE] +boolean P_ItemBehavior(player_t* player, int item); // villsa [STRIFE] +static char useinventorymsg[44]; // villsa [STRIFE] + +// +// Movement. +// + +// 16 pixels of bob +#define MAXBOB 0x100000 + +boolean onground; + + +// +// P_Thrust +// Moves the given origin along a given angle. +// +// [STRIFE] Verified unmodified +// +void +P_Thrust +( player_t* player, + angle_t angle, + fixed_t move ) +{ + angle >>= ANGLETOFINESHIFT; + + player->mo->momx += FixedMul(move,finecosine[angle]); + player->mo->momy += FixedMul(move,finesine[angle]); +} + + + + +// +// P_CalcHeight +// Calculate the walking / running height adjustment +// +// [STRIFE] Some odd adjustments, and terrain view height adjustment +// +void P_CalcHeight (player_t* player) +{ + int angle; + fixed_t bob; + + // Regular movement bobbing + // (needs to be calculated for gun swing + // even if not on ground) + // OPTIMIZE: tablify angle + // Note: a LUT allows for effects + // like a ramp with low health. + player->bob = + FixedMul (player->mo->momx, player->mo->momx) + + FixedMul (player->mo->momy,player->mo->momy); + + player->bob >>= 2; + + if (player->bob>MAXBOB) + player->bob = MAXBOB; + + // haleyjd 20110205 [STRIFE]: No CF_NOMOMENTUM check, and Rogue also removed + // the dead code inside. + if (!onground) + { + /* + player->viewz = player->mo->z + VIEWHEIGHT; + + if (player->viewz > player->mo->ceilingz-4*FRACUNIT) + player->viewz = player->mo->ceilingz-4*FRACUNIT; + */ + + player->viewz = player->mo->z + player->viewheight; + return; + } + + angle = (FINEANGLES/20*leveltime)&FINEMASK; + bob = FixedMul ( player->bob/2, finesine[angle]); + + // move viewheight + if (player->playerstate == PST_LIVE) + { + player->viewheight += player->deltaviewheight; + + if (player->viewheight > VIEWHEIGHT) + { + player->viewheight = VIEWHEIGHT; + player->deltaviewheight = 0; + } + + if (player->viewheight < VIEWHEIGHT/2) + { + player->viewheight = VIEWHEIGHT/2; + if (player->deltaviewheight <= 0) + player->deltaviewheight = 1; + } + + if (player->deltaviewheight) + { + player->deltaviewheight += FRACUNIT/4; + if (!player->deltaviewheight) + player->deltaviewheight = 1; + } + } + player->viewz = player->mo->z + player->viewheight + bob; + + // villsa [STRIFE] account for terrain lowering the view + if(player->mo->flags & MF_FEETCLIPPED) + player->viewz -= 13*FRACUNIT; + + if (player->viewz > player->mo->ceilingz-4*FRACUNIT) + player->viewz = player->mo->ceilingz-4*FRACUNIT; + + // haleyjd [STRIFE]: added a floorz clip here + if (player->viewz < player->mo->floorz) + player->viewz = player->mo->floorz; +} + + + +// +// P_MovePlayer +// +// [STRIFE] Adjustments to allow air control, jumping, and up/down look. +// +void P_MovePlayer (player_t* player) +{ + ticcmd_t* cmd; + + cmd = &player->cmd; + + player->mo->angle += (cmd->angleturn<<16); + + // Do not let the player control movement + // if not onground. + onground = (player->mo->z <= player->mo->floorz); + + // villsa [STRIFE] allows player to climb over things by jumping + // haleyjd 20110205: air control thrust should be 256, not cmd->forwardmove + if(!onground) + { + if(cmd->forwardmove) + P_Thrust (player, player->mo->angle, 256); + } + else + { + // villsa [STRIFE] jump button + if (cmd->buttons2 & BT2_JUMP) + { + if(!player->deltaviewheight) + player->mo->momz += 8*FRACUNIT; + } + + // haleyjd 20110205 [STRIFE] Either Rogue or Watcom removed the + // redundant "onground" checks from these if's. + if (cmd->forwardmove) + P_Thrust (player, player->mo->angle, cmd->forwardmove*2048); + + if (cmd->sidemove) + P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048); + } + + // villsa [STRIFE] player walking state set + if ( (cmd->forwardmove || cmd->sidemove) + && player->mo->state == &states[S_PLAY_00] ) + { + P_SetMobjState (player->mo, S_PLAY_01); + } + + // villsa [STRIFE] centerview button + if (cmd->buttons2 & BT2_CENTERVIEW) + player->centerview = 1; + + // villsa [STRIFE] adjust player's pitch when centerviewing + if (player->centerview) + { + if (player->pitch <= 0) + { + if (player->pitch < 0) + player->pitch = player->pitch + CENTERVIEWAMOUNT; + } + else + { + player->pitch = player->pitch - CENTERVIEWAMOUNT; + } + if (abs(player->pitch) < CENTERVIEWAMOUNT) + { + player->pitch = 0; + player->centerview = 0; + } + } + + // villsa [STRIFE] look up action + if (cmd->buttons2 & BT2_LOOKUP) + { + player->pitch += LOOKPITCHAMOUNT; + if (player->pitch > LOOKUPMAX || + player->pitch < LOOKDOWNMAX) + player->pitch -= LOOKPITCHAMOUNT; + } + else + { + // villsa [STRIFE] look down action + if (cmd->buttons2 & BT2_LOOKDOWN) + { + player->pitch -= LOOKPITCHAMOUNT; + if (player->pitch > LOOKUPMAX || + player->pitch < LOOKDOWNMAX) + player->pitch += LOOKPITCHAMOUNT; + } + } + +} + + + +// +// P_DeathThink +// Fall on your face when dying. +// Decrease POV height to floor height. +// +// [STRIFE] Modifications for up/down look. +// +#define ANG5 (ANG90/18) + +void P_DeathThink(player_t* player) +{ + angle_t angle; + angle_t delta; + + P_MovePsprites(player); + + // fall to the ground + if (player->viewheight > 6*FRACUNIT) + player->viewheight -= FRACUNIT; + + if (player->viewheight < 6*FRACUNIT) + player->viewheight = 6*FRACUNIT; + + player->deltaviewheight = 0; + onground = (player->mo->z <= player->mo->floorz); + P_CalcHeight(player); + + if(player->attacker && player->attacker != player->mo) + { + angle = R_PointToAngle2 (player->mo->x, + player->mo->y, + player->attacker->x, + player->attacker->y); + + delta = angle - player->mo->angle; + + if (delta < ANG5 || delta > (unsigned)-ANG5) + { + // Looking at killer, + // so fade damage flash down. + player->mo->angle = angle; + + if (player->damagecount) + player->damagecount--; + } + else if (delta < ANG180) + player->mo->angle += ANG5; + else + player->mo->angle -= ANG5; + } + else if (player->damagecount) + player->damagecount--; + + // villsa [STRIFE] + if(player->pitch <= 90) + player->pitch = player->pitch + 3; + + if(player->cmd.buttons & BT_USE) + player->playerstate = PST_REBORN; +} + + + +// +// P_PlayerThink +// +// [STRIFE] Massive changes/additions: +// * NOCLIP hack removed +// * P_DeathThink moved up +// * Inventory use/dropping +// * Strife weapons logic +// * Dialog +// * Strife powerups and nukage behavior +// * Fire Death/Sigil Shock +// +void P_PlayerThink (player_t* player) +{ + ticcmd_t* cmd; + weapontype_t newweapon; + + // villsa [STRIFE] unused code (see ST_Responder) + /* + // fixme: do this in the cheat code + if (player->cheats & CF_NOCLIP) + player->mo->flags |= MF_NOCLIP; + else + player->mo->flags &= ~MF_NOCLIP; + */ + + // haleyjd 20110205 [STRIFE]: P_DeathThink moved up + if (player->playerstate == PST_DEAD) + { + P_DeathThink (player); + return; + } + + // chain saw run forward + cmd = &player->cmd; + if (player->mo->flags & MF_JUSTATTACKED) + { + cmd->angleturn = 0; + cmd->forwardmove = 0xc800/512; + cmd->sidemove = 0; + player->mo->flags &= ~MF_JUSTATTACKED; + } + + // Move around. + // Reactiontime is used to prevent movement + // for a bit after a teleport. + if (player->mo->reactiontime) + player->mo->reactiontime--; + else + P_MovePlayer (player); + + P_CalcHeight (player); + + if (player->mo->subsector->sector->special) + P_PlayerInSpecialSector (player); + + // villsa [STRIFE] handle inventory input + if(cmd->buttons2 & (BT2_HEALTH|BT2_INVUSE|BT2_INVDROP)) + { + if(!player->inventorydown) + { + if(cmd->buttons2 & BT2_HEALTH) + P_UseInventoryItem(player, SPR_FULL); + else if(cmd->buttons2 & BT2_INVUSE) + P_UseInventoryItem(player, cmd->inventory); + else if(cmd->buttons2 & BT2_INVDROP) + { + P_DropInventoryItem(player, cmd->inventory); + + // haleyjd 20110205: removed incorrect "else" here + // villsa [STRIFE] + if(workparm) + { + int cheat = player->cheats ^ 1; + player->cheats ^= CF_NOCLIP; + + if(cheat & CF_NOCLIP) + { + player->message = DEH_String("No Clipping Mode ON"); + player->mo->flags |= MF_NOCLIP; + } + else + { + player->mo->flags &= ~MF_NOCLIP; + player->message = DEH_String("No Clipping Mode OFF"); + } + } + } + } + + player->inventorydown = true; + } + else + player->inventorydown = false; + + // Check for weapon change. + + // A special event has no other buttons. + if(cmd->buttons & BT_SPECIAL) + cmd->buttons = 0; + + if(cmd->buttons & BT_CHANGE) + { + // The actual changing of the weapon is done + // when the weapon psprite can do it + // (read: not in the middle of an attack). + newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; + + // villsa [STRIFE] select poison bow + if(newweapon == wp_elecbow) + { + if(player->weaponowned[wp_poisonbow] && player->readyweapon == wp_elecbow) + { + if(player->ammo[weaponinfo[wp_poisonbow].ammo]) + newweapon = wp_poisonbow; + } + } + + // villsa [STRIFE] select wp grenade launcher + if(newweapon == wp_hegrenade) + { + if(player->weaponowned[wp_wpgrenade] && player->readyweapon == wp_hegrenade) + { + if(player->ammo[weaponinfo[wp_wpgrenade].ammo]) + newweapon = wp_wpgrenade; + } + } + + // villsa [STRIFE] select torpedo + if(newweapon == wp_mauler) + { + if(player->weaponowned[wp_torpedo] && player->readyweapon == wp_mauler) + { + // haleyjd 20140924: bug fix - using wrong enum value am_cell + // caused this to check the missile launcher for rocket ammo + if(player->ammo[weaponinfo[wp_torpedo].ammo] >= 30) + newweapon = wp_torpedo; + } + } + + if(player->weaponowned[newweapon] && newweapon != player->readyweapon) + { + // villsa [STRIFE] check weapon if in demo mode or not + if(weaponinfo[newweapon].availabledemo || !isdemoversion) + { + if(player->ammo[weaponinfo[newweapon].ammo]) + player->pendingweapon = newweapon; + else + { + // decide between electric bow or poison arrow + if(newweapon == wp_elecbow && + player->ammo[am_poisonbolts] && + player->readyweapon != wp_poisonbow) + { + player->pendingweapon = wp_poisonbow; + } + // decide between hp grenade launcher or wp grenade launcher + else if(newweapon == wp_hegrenade && + player->ammo[am_wpgrenades] && + player->readyweapon != wp_wpgrenade) + { + player->pendingweapon = wp_wpgrenade; + } + + // villsa [STRIFE] - no check for mauler/torpedo?? + } + } + } + } + + // check for use + if(cmd->buttons & BT_USE) + { + if(!player->usedown) + { + P_DialogStart(player); // villsa [STRIFE] + P_UseLines (player); + player->usedown = true; + } + } + else + player->usedown = false; + + // cycle psprites + P_MovePsprites (player); + + // Counters, time dependend power ups. + + // Strength counts up to diminish fade. + if (player->powers[pw_strength]) + player->powers[pw_strength]++; + + // villsa [STRIFE] targeter powerup + if(player->powers[pw_targeter]) + { + player->powers[pw_targeter]--; + if(player->powers[pw_targeter] == 1) + { + P_SetPsprite(player, ps_targcenter, S_NULL); + P_SetPsprite(player, ps_targleft, S_NULL); + P_SetPsprite(player, ps_targright, S_NULL); + } + else if(player->powers[pw_targeter] - 1 < 5*TICRATE) + { + if(player->powers[pw_targeter] & 32) + { + P_SetPsprite(player, ps_targright, S_NULL); + P_SetPsprite(player, ps_targleft, S_TRGT_01); // 11 + } + else if(player->powers[pw_targeter] & 16) // haleyjd 20110205: missing else + { + P_SetPsprite(player, ps_targright, S_TRGT_02); // 12 + P_SetPsprite(player, ps_targleft, S_NULL); + } + } + } + + if(player->powers[pw_invisibility]) + { + // villsa [STRIFE] remove mvis flag as well + if(!--player->powers[pw_invisibility]) + player->mo->flags &= ~(MF_SHADOW|MF_MVIS); + } + + if(player->powers[pw_ironfeet]) + { + player->powers[pw_ironfeet]--; + + // villsa [STRIFE] gasmask sound + if(!(leveltime & 0x3f)) + S_StartSound(player->mo, sfx_mask); + } + + if(player->powers[pw_allmap] > 1) + player->powers[pw_allmap]--; + + // haleyjd 08/30/10: [STRIFE] + // Nukage count keeps track of exposure to hazardous conditions over time. + // After accumulating 16 total seconds or more of exposure, you will take + // 5 damage roughly once per second until the count drops back under 560 + // tics. + if(player->nukagecount) + { + player->nukagecount--; + if(!(leveltime & 0x1f) && player->nukagecount > 16*TICRATE) + P_DamageMobj(player->mo, NULL, NULL, 5); + } + + if(player->damagecount) + player->damagecount--; + + if(player->bonuscount) + player->bonuscount--; + + // villsa [STRIFE] checks for extralight + if(player->extralight >= 0) + { + if(player->cheats & CF_ONFIRE) + player->fixedcolormap = 1; + else + player->fixedcolormap = 0; + } + else // Sigil shock: + player->fixedcolormap = INVERSECOLORMAP; +} + + +// +// P_RemoveInventoryItem +// villsa [STRIFE] new function +// +const char* P_RemoveInventoryItem(player_t *player, int slot, int amount) +{ + mobjtype_t type; + + player->inventory[slot].amount -= amount; + player->st_update = true; + + type = player->inventory[slot].type; + + if(!player->inventory[slot].amount) + { + // shift everything above it down + // see P_TakeDialogItem for notes on possible bugs + int j; + + for(j = slot + 1; j <= player->numinventory; j++) + { + inventory_t *item1 = &(player->inventory[j - 1]); + inventory_t *item2 = &(player->inventory[j]); + + *item1 = *item2; + } + + player->inventory[player->numinventory].type = NUMMOBJTYPES; + player->inventory[player->numinventory].sprite = -1; + player->numinventory--; + + // update cursor position + if(player->inventorycursor >= player->numinventory) + { + if(player->inventorycursor) + player->inventorycursor--; + } + } + + return mobjinfo[type].name; +} + +// +// P_DropInventoryItem +// villsa [STRIFE] new function +// +void P_DropInventoryItem(player_t* player, int sprite) +{ + int invslot; + inventory_t *item; + mobjtype_t type; + int amount; + + invslot = 0; + amount = 1; + + while(invslot < player->numinventory && sprite != player->inventory[invslot].sprite) + invslot++; + + item = &(player->inventory[invslot]); + type = item->type; + + if(item->amount) + { + angle_t angle; + fixed_t dist; + mobj_t* mo; + mobj_t* mobjitem; + fixed_t x; + fixed_t y; + fixed_t z; + int r; + + if(item->type == MT_MONY_1) + { + if(item->amount >= 50) + { + type = MT_MONY_50; + amount = 50; + } + else if(item->amount >= 25) + { + type = MT_MONY_25; + amount = 25; + } + else if(item->amount >= 10) + { + type = MT_MONY_10; + amount = 10; + } + } + + if(type >= NUMMOBJTYPES) + return; + + angle = player->mo->angle; + r = P_Random(); + angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT; + + if(angle < 7618 && angle >= 6718) + angle = 7618; + + else if(angle < 5570 && angle >= 4670) + angle = 5570; + + else if(angle < 3522 && angle >= 2622) + angle = 3522; + + else if(angle < 1474 && angle >= 574) + angle = 1474; + + mo = player->mo; + dist = mobjinfo[type].radius + mo->info->radius + (4*FRACUNIT); + + x = mo->x + FixedMul(finecosine[angle], dist); + y = mo->y + FixedMul(finesine[angle], dist); + z = mo->z + (10*FRACUNIT); + mobjitem = P_SpawnMobj(x, y, z, type); + mobjitem->flags |= (MF_SPECIAL|MF_DROPPED); + + if(P_CheckPosition(mobjitem, x, y)) + { + mobjitem->angle = (angle << ANGLETOFINESHIFT); + mobjitem->momx = FixedMul(finecosine[angle], (5*FRACUNIT)) + mo->momx; + mobjitem->momy = FixedMul(finesine[angle], (5*FRACUNIT)) + mo->momy; + mobjitem->momz = FRACUNIT; + + P_RemoveInventoryItem(player, invslot, amount); + } + else + P_RemoveMobj(mobjitem); + } +} + +// +// P_TossDegninOre +// villsa [STRIFE] new function +// +boolean P_TossDegninOre(player_t* player) +{ + angle_t angle; + mobj_t* mo; + mobj_t* ore; + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t dist; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + + if(angle < 7618 && angle >= 6718) + angle = 7618; + + else if(angle < 5570 && angle >= 4670) + angle = 5570; + + else if(angle < 3522 && angle >= 2622) + angle = 3522; + + else if(angle < 1474 && angle >= 574) + angle = 1474; + + mo = player->mo; + dist = mobjinfo[MT_DEGNINORE].radius + mo->info->radius + (4*FRACUNIT); + + x = mo->x + FixedMul(finecosine[angle], dist); + y = mo->y + FixedMul(finesine[angle], dist); + z = mo->z + (10*FRACUNIT); + ore = P_SpawnMobj(x, y, z, MT_DEGNINORE); + + if(P_CheckPosition(ore, x, y)) + { + ore->target = mo; + ore->angle = (angle << ANGLETOFINESHIFT); + ore->momx = FixedMul(finecosine[angle], (5*FRACUNIT)); + ore->momy = FixedMul(finesine[angle], (5*FRACUNIT)); + ore->momz = FRACUNIT; + return true; + } + else + P_RemoveMobj(ore); + + return false; +} + +// +// P_SpawnTeleportBeacon +// +// villsa [STRIFE] new function +// haleyjd 20140918: bug fixed to propagate allegiance properly. +// +boolean P_SpawnTeleportBeacon(player_t* player) +{ + angle_t angle; + int r; + mobj_t* mo; + mobj_t* beacon; + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t dist; + + angle = player->mo->angle; + r = P_Random(); + angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT; + + if(angle < 7618 && angle >= 6718) + angle = 7618; + + else if(angle < 5570 && angle >= 4670) + angle = 5570; + + else if(angle < 3522 && angle >= 2622) + angle = 3522; + + else if(angle < 1474 && angle >= 574) + angle = 1474; + + mo = player->mo; + dist = mobjinfo[MT_BEACON].radius + mo->info->radius + (4*FRACUNIT); + + x = mo->x + FixedMul(finecosine[angle], dist); + y = mo->y + FixedMul(finesine[angle], dist); + z = mo->z + (10*FRACUNIT); + beacon = P_SpawnMobj(x, y, z, MT_BEACON); + + if(P_CheckPosition(beacon, x, y)) + { + beacon->target = mo; + beacon->miscdata = (byte)(player->allegiance); + beacon->angle = (angle << ANGLETOFINESHIFT); + beacon->momx = FixedMul(finecosine[angle], (5*FRACUNIT)); + beacon->momy = FixedMul(finesine[angle], (5*FRACUNIT)); + beacon->momz = FRACUNIT; + P_SetMobjState(beacon, beacon->info->seestate); + return true; + } + else + P_RemoveMobj(beacon); + + return false; +} + +// +// P_UseInventoryItem +// villsa [STRIFE] new function +// +boolean P_UseInventoryItem(player_t* player, int item) +{ + int i; + const char *name; + + if(player->cheats & CF_ONFIRE) + return false; + + for(i = 0; i < player->numinventory; i++) + { + if(item != player->inventory[i].sprite) + continue; + + if(!P_ItemBehavior(player, item)) + return false; + + name = P_RemoveInventoryItem(player, i, 1); + if(name == NULL) + name = "Item"; + + M_snprintf(useinventorymsg, sizeof(useinventorymsg), + "You used the %s.", name); + player->message = useinventorymsg; + + if(player == &players[consoleplayer]) + S_StartSound(NULL, sfx_itemup); + + return true; + } + + return false; +} + +// +// P_ItemBehavior +// villsa [STRIFE] new function +// +boolean P_ItemBehavior(player_t* player, int item) +{ + switch(item) + { + case SPR_ARM1: // 136 + return P_GiveArmor(player, 2); + + case SPR_ARM2: // 137 + return P_GiveArmor(player, 1); + + case SPR_SHD1: // 186 + return P_GivePower(player, pw_invisibility); + + case SPR_MASK: // 187 + return P_GivePower(player, pw_ironfeet); + + case SPR_PMUP: // 191 + if(!player->powers[pw_allmap]) + { + player->message = "The scanner won't work without a map!"; + return false; + } + player->powers[pw_allmap] = PMUPTICS; + return true; // haleyjd 20110228: repaired + + case SPR_STMP: // 180 + return P_GiveBody(player, 10); + + case SPR_MDKT: // 181 + return P_GiveBody(player, 25); + + case SPR_FULL: // 130 + return P_GiveBody(player, 200); + + case SPR_BEAC: // 135 + return P_SpawnTeleportBeacon(player); + + case SPR_TARG: // 108 + return P_GivePower(player, pw_targeter); + } + + return false; +} diff --git a/games/NXDoom/src/strife/r_bsp.c b/games/NXDoom/src/strife/r_bsp.c new file mode 100644 index 00000000000..64b9d5dfe58 --- /dev/null +++ b/games/NXDoom/src/strife/r_bsp.c @@ -0,0 +1,583 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// BSP traversal, handling of LineSegs for rendering. +// + + + + +#include "doomdef.h" + +#include "m_bbox.h" + +#include "i_system.h" + +#include "r_main.h" +#include "r_plane.h" +#include "r_things.h" + +// State. +#include "doomstat.h" +#include "r_state.h" + +//#include "r_local.h" + + + +seg_t* curline; +side_t* sidedef; +line_t* linedef; +sector_t* frontsector; +sector_t* backsector; + +drawseg_t drawsegs[MAXDRAWSEGS]; +drawseg_t* ds_p; + + +void +R_StoreWallRange +( int start, + int stop ); + + + + +// +// R_ClearDrawSegs +// +void R_ClearDrawSegs (void) +{ + ds_p = drawsegs; +} + + + +// +// ClipWallSegment +// Clips the given range of columns +// and includes it in the new clip list. +// +typedef struct +{ + int first; + int last; + +} cliprange_t; + +// We must expand MAXSEGS to the theoretical limit of the number of solidsegs +// that can be generated in a scene by the DOOM engine. This was determined by +// Lee Killough during BOOM development to be a function of the screensize. +// The simplest thing we can do, other than fix this bug, is to let the game +// render overage and then bomb out by detecting the overflow after the +// fact. -haleyjd +//#define MAXSEGS 32 +#define MAXSEGS (SCREENWIDTH / 2 + 1) + +// newend is one past the last valid seg +cliprange_t* newend; +cliprange_t solidsegs[MAXSEGS]; + + + + +// +// R_ClipSolidWallSegment +// Does handle solid walls, +// e.g. single sided LineDefs (middle texture) +// that entirely block the view. +// +void +R_ClipSolidWallSegment +( int first, + int last ) +{ + cliprange_t* next; + cliprange_t* start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first-1) + start++; + + if (first < start->first) + { + if (last < start->first-1) + { + // Post is entirely visible (above start), + // so insert a new clippost. + R_StoreWallRange (first, last); + next = newend; + newend++; + + while (next != start) + { + *next = *(next-1); + next--; + } + next->first = first; + next->last = last; + return; + } + + // There is a fragment above *start. + R_StoreWallRange (first, start->first - 1); + // Now adjust the clip size. + start->first = first; + } + + // Bottom contained in start? + if (last <= start->last) + return; + + next = start; + while (last >= (next+1)->first-1) + { + // There is a fragment between two posts. + R_StoreWallRange (next->last + 1, (next+1)->first - 1); + next++; + + if (last <= next->last) + { + // Bottom is contained in next. + // Adjust the clip size. + start->last = next->last; + goto crunch; + } + } + + // There is a fragment after *next. + R_StoreWallRange (next->last + 1, last); + // Adjust the clip size. + start->last = last; + + // Remove start+1 to next from the clip list, + // because start now covers their area. + crunch: + if (next == start) + { + // Post just extended past the bottom of one post. + return; + } + + + while (next++ != newend) + { + // Remove a post. + *++start = *next; + } + + newend = start+1; +} + + + +// +// R_ClipPassWallSegment +// Clips the given range of columns, +// but does not includes it in the clip list. +// Does handle windows, +// e.g. LineDefs with upper and lower texture. +// +void +R_ClipPassWallSegment +( int first, + int last ) +{ + cliprange_t* start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = solidsegs; + while (start->last < first-1) + start++; + + if (first < start->first) + { + if (last < start->first-1) + { + // Post is entirely visible (above start). + R_StoreWallRange (first, last); + return; + } + + // There is a fragment above *start. + R_StoreWallRange (first, start->first - 1); + } + + // Bottom contained in start? + if (last <= start->last) + return; + + while (last >= (start+1)->first-1) + { + // There is a fragment between two posts. + R_StoreWallRange (start->last + 1, (start+1)->first - 1); + start++; + + if (last <= start->last) + return; + } + + // There is a fragment after *next. + R_StoreWallRange (start->last + 1, last); +} + + + +// +// R_ClearClipSegs +// +void R_ClearClipSegs (void) +{ + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs+2; +} + +// +// R_AddLine +// Clips the given segment +// and adds any visible pieces to the line list. +// +void R_AddLine (seg_t* line) +{ + int x1; + int x2; + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + curline = line; + + // OPTIMIZE: quickly reject orthogonal back sides. + angle1 = R_PointToAngle (line->v1->x, line->v1->y); + angle2 = R_PointToAngle (line->v2->x, line->v2->y); + + // Clip to view edges. + // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). + span = angle1 - angle2; + + // Back side? I.e. backface culling? + if (span >= ANG180) + return; + + // Global angle needed by segcalc. + rw_angle1 = angle1; + angle1 -= viewangle; + angle2 -= viewangle; + + tspan = angle1 + clipangle; + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + angle2 = 0 - clipangle; + } + + // The seg is in the view range, + // but not necessarily visible. + angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; + angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; + + // Does not cross a pixel? + if (x1 == x2) + return; + + backsector = line->backsector; + + // Single sided line? + if (!backsector) + goto clipsolid; + + // Closed door. + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + goto clipsolid; + + // Window. + if (backsector->ceilingheight != frontsector->ceilingheight + || backsector->floorheight != frontsector->floorheight) + goto clippass; + + // Reject empty lines used for triggers + // and special events. + // Identical floor and ceiling on both sides, + // identical light levels on both sides, + // and no middle texture. + if (backsector->ceilingpic == frontsector->ceilingpic + && backsector->floorpic == frontsector->floorpic + && backsector->lightlevel == frontsector->lightlevel + && curline->sidedef->midtexture == 0) + { + return; + } + + + clippass: + R_ClipPassWallSegment (x1, x2-1); + return; + + clipsolid: + R_ClipSolidWallSegment (x1, x2-1); +} + + +// +// R_CheckBBox +// Checks BSP node/subtree bounding box. +// Returns true +// if some part of the bbox might be visible. +// +int checkcoord[12][4] = +{ + {3,0,2,1}, + {3,0,2,0}, + {3,1,2,0}, + {0}, + {2,0,2,1}, + {0,0,0,0}, + {3,1,3,0}, + {0}, + {2,0,3,1}, + {2,1,3,1}, + {2,1,3,0} +}; + + +boolean R_CheckBBox (fixed_t* bspcoord) +{ + int boxx; + int boxy; + int boxpos; + + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + cliprange_t* start; + + int sx1; + int sx2; + + // Find the corners of the box + // that define the edges from current viewpoint. + if (viewx <= bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx < bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy >= bspcoord[BOXTOP]) + boxy = 0; + else if (viewy > bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy<<2)+boxx; + if (boxpos == 5) + return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + // check clip list for an open space + angle1 = R_PointToAngle (x1, y1) - viewangle; + angle2 = R_PointToAngle (x2, y2) - viewangle; + + span = angle1 - angle2; + + // Sitting on a line? + if (span >= ANG180) + return true; + + tspan = angle1 + clipangle; + + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle1 = clipangle; + } + tspan = clipangle - angle2; + if (tspan > 2*clipangle) + { + tspan -= 2*clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle2 = 0 - clipangle; + } + + + // Find the first clippost + // that touches the source post + // (adjacent pixels are touching). + angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; + angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; + sx1 = viewangletox[angle1]; + sx2 = viewangletox[angle2]; + + // Does not cross a pixel. + if (sx1 == sx2) + return false; + sx2--; + + start = solidsegs; + while (start->last < sx2) + start++; + + if (sx1 >= start->first + && sx2 <= start->last) + { + // The clippost contains the new span. + return false; + } + + return true; +} + + + +// +// R_Subsector +// Determine floor/ceiling planes. +// Add sprites of things in sector. +// Draw one or more line segments. +// +void R_Subsector (int num) +{ + int count; + seg_t* line; + subsector_t* sub; + +#ifdef RANGECHECK + if (num>=numsubsectors) + I_Error ("R_Subsector: ss %i with numss = %i", + num, + numsubsectors); +#endif + + sscount++; + sub = &subsectors[num]; + frontsector = sub->sector; + count = sub->numlines; + line = &segs[sub->firstline]; + + if (frontsector->floorheight < viewz) + { + floorplane = R_FindPlane (frontsector->floorheight, + frontsector->floorpic, + frontsector->lightlevel); + } + else + floorplane = NULL; + + if (frontsector->ceilingheight > viewz + || frontsector->ceilingpic == skyflatnum) + { + ceilingplane = R_FindPlane (frontsector->ceilingheight, + frontsector->ceilingpic, + frontsector->lightlevel); + } + else + ceilingplane = NULL; + + R_AddSprites (frontsector); + + while (count--) + { + R_AddLine (line); + line++; + } + + // check for solidsegs overflow - extremely unsatisfactory! + if(newend > &solidsegs[32]) + I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); +} + + + + +// +// RenderBSPNode +// Renders all subsectors below a given node, +// traversing subtree recursively. +// Just call with BSP root. +void R_RenderBSPNode (int bspnum) +{ + node_t* bsp; + int side; + + // Found a subsector? + if (bspnum & NF_SUBSECTOR) + { + if (bspnum == -1) + R_Subsector (0); + else + R_Subsector (bspnum&(~NF_SUBSECTOR)); + return; + } + + bsp = &nodes[bspnum]; + + // Decide which side the view point is on. + side = R_PointOnSide (viewx, viewy, bsp); + + // Recursively divide front space. + R_RenderBSPNode (bsp->children[side]); + + // Possibly divide back space. + if (R_CheckBBox (bsp->bbox[side^1])) + R_RenderBSPNode (bsp->children[side^1]); +} + + diff --git a/games/NXDoom/src/strife/r_bsp.h b/games/NXDoom/src/strife/r_bsp.h new file mode 100644 index 00000000000..1723e686147 --- /dev/null +++ b/games/NXDoom/src/strife/r_bsp.h @@ -0,0 +1,61 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh module, BSP traversal and handling. +// + + +#ifndef __R_BSP__ +#define __R_BSP__ + + + +extern seg_t* curline; +extern side_t* sidedef; +extern line_t* linedef; +extern sector_t* frontsector; +extern sector_t* backsector; + +extern int rw_x; +extern int rw_stopx; + +extern boolean segtextured; + +// false if the back side is the same plane +extern boolean markfloor; +extern boolean markceiling; + +extern boolean skymap; + +extern drawseg_t drawsegs[MAXDRAWSEGS]; +extern drawseg_t* ds_p; + +extern lighttable_t** hscalelight; +extern lighttable_t** vscalelight; +extern lighttable_t** dscalelight; + + +typedef void (*drawfunc_t) (int start, int stop); + + +// BSP? +void R_ClearClipSegs (void); +void R_ClearDrawSegs (void); + + +void R_RenderBSPNode (int bspnum); + + +#endif diff --git a/games/NXDoom/src/strife/r_data.c b/games/NXDoom/src/strife/r_data.c new file mode 100644 index 00000000000..e7d70e073b1 --- /dev/null +++ b/games/NXDoom/src/strife/r_data.c @@ -0,0 +1,1010 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Preparation of data for rendering, +// generation of lookups, caching, retrieval by name. +// + +#include + +#include "d_main.h" +#include "deh_main.h" +#include "i_swap.h" +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" +#include "doomdef.h" +#include "r_local.h" +#include "p_local.h" +#include "doomstat.h" +#include "m_misc.h" +#include "r_sky.h" +#include "r_data.h" +#include "sounds.h" // villsa [STRIFE] + +// +// Graphics. +// DOOM graphics for walls and sprites +// is stored in vertical runs of opaque pixels (posts). +// A column is composed of zero or more posts, +// a patch or sprite is composed of zero or more columns. +// + + + +// +// Texture definition. +// Each texture is composed of one or more patches, +// with patches being lumps stored in the WAD. +// The lumps are referenced by number, and patched +// into the rectangular texture space using origin +// and possibly other attributes. +// +typedef PACKED_STRUCT ( +{ + short originx; + short originy; + short patch; + //short stepdir; // villsa [STRIFE] removed + //short colormap; // villsa [STRIFE] removed +}) mappatch_t; + + +// +// Texture definition. +// A DOOM wall texture is a list of patches +// which are to be combined in a predefined order. +// +typedef PACKED_STRUCT ( +{ + char name[8]; + int masked; + short width; + short height; + //int obsolete; // villsa [STRIFE] removed + short patchcount; + mappatch_t patches[1]; +}) maptexture_t; + + +// A single patch from a texture definition, +// basically a rectangular area within +// the texture rectangle. +typedef struct +{ + // Block origin (allways UL), + // which has allready accounted + // for the internal origin of the patch. + short originx; + short originy; + int patch; +} texpatch_t; + + +// A maptexturedef_t describes a rectangular texture, +// which is composed of one or more mappatch_t structures +// that arrange graphic patches. + +typedef struct texture_s texture_t; + +struct texture_s +{ + // Keep name for switch changing, etc. + char name[8]; + short width; + short height; + + // Index in textures list + + int index; + + // Next in hash table chain + + texture_t *next; + + // All the patches[patchcount] + // are drawn back to front into the cached texture. + short patchcount; + texpatch_t patches[1]; +}; + + + +int firstflat; +int lastflat; +int numflats; + +int firstpatch; +int lastpatch; +int numpatches; + +int firstspritelump; +int lastspritelump; +int numspritelumps; + +int numtextures; +texture_t** textures; +texture_t** textures_hashtable; + + +int* texturewidthmask; +// needed for texture pegging +fixed_t* textureheight; +int* texturecompositesize; +short** texturecolumnlump; +unsigned short** texturecolumnofs; +byte** texturecomposite; + +// for global animation +int* flattranslation; +int* texturetranslation; + +// needed for pre rendering +fixed_t* spritewidth; +fixed_t* spriteoffset; +fixed_t* spritetopoffset; + +lighttable_t *colormaps; + + +// +// MAPTEXTURE_T CACHING +// When a texture is first needed, +// it counts the number of composite columns +// required in the texture and allocates space +// for a column directory and any new columns. +// The directory will simply point inside other patches +// if there is only one patch in a given column, +// but any columns with multiple patches +// will have new column_ts generated. +// + + + +// +// R_DrawColumnInCache +// Clip and draw a column +// from a patch into a cached post. +// +void +R_DrawColumnInCache +( column_t* patch, + byte* cache, + int originy, + int cacheheight ) +{ + int count; + int position; + byte* source; + + while (patch->topdelta != 0xff) + { + source = (byte *)patch + 3; + count = patch->length; + position = originy + patch->topdelta; + + if (position < 0) + { + count += position; + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + if (count > 0) + memcpy (cache + position, source, count); + + patch = (column_t *)( (byte *)patch + patch->length + 4); + } +} + + + +// +// R_GenerateComposite +// Using the texture definition, +// the composite texture is created from the patches, +// and each column is cached. +// +void R_GenerateComposite (int texnum) +{ + byte* block; + texture_t* texture; + texpatch_t* patch; + patch_t* realpatch; + int x; + int x1; + int x2; + int i; + column_t* patchcol; + short* collump; + unsigned short* colofs; + + texture = textures[texnum]; + + block = Z_Malloc (texturecompositesize[texnum], + PU_STATIC, + &texturecomposite[texnum]); + + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + + // Composite the columns together. + for (i=0 , patch = texture->patches; + ipatchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1<0) + x = 0; + else + x = x1; + + if (x2 > texture->width) + x2 = texture->width; + + for ( ; x= 0) + continue; + + patchcol = (column_t *)((byte *)realpatch + + LONG(realpatch->columnofs[x-x1])); + R_DrawColumnInCache (patchcol, + block + colofs[x], + patch->originy, + texture->height); + } + + } + + // Now that the texture has been built in column cache, + // it is purgable from zone memory. + Z_ChangeTag (block, PU_CACHE); +} + + + +// +// R_GenerateLookup +// +void R_GenerateLookup (int texnum) +{ + texture_t* texture; + byte* patchcount; // patchcount[texture->width] + texpatch_t* patch; + patch_t* realpatch; + int x; + int x1; + int x2; + int i; + short* collump; + unsigned short* colofs; + + texture = textures[texnum]; + + // Composited texture not created yet. + texturecomposite[texnum] = 0; + + texturecompositesize[texnum] = 0; + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + + // Now count the number of columns + // that are covered by more than one patch. + // Fill in the lump / offset, so columns + // with only a single patch are all done. + patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); + memset (patchcount, 0, texture->width); + + for (i=0 , patch = texture->patches; + ipatchcount; + i++, patch++) + { + realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1 < 0) + x = 0; + else + x = x1; + + if (x2 > texture->width) + x2 = texture->width; + for ( ; xpatch; + colofs[x] = LONG(realpatch->columnofs[x-x1])+3; + } + } + + for (x=0 ; xwidth ; x++) + { + if (!patchcount[x]) + { + printf ("R_GenerateLookup: column without a patch (%s)\n", + texture->name); + return; + } + // I_Error ("R_GenerateLookup: column without a patch"); + + if (patchcount[x] > 1) + { + // Use the cached block. + collump[x] = -1; + colofs[x] = texturecompositesize[texnum]; + + if (texturecompositesize[texnum] > 0x10000-texture->height) + { + I_Error ("R_GenerateLookup: texture %i is >64k", + texnum); + } + + texturecompositesize[texnum] += texture->height; + } + } + + Z_Free(patchcount); +} + + + + +// +// R_GetColumn +// +byte* +R_GetColumn +( int tex, + int col ) +{ + int lump; + int ofs; + + col &= texturewidthmask[tex]; + lump = texturecolumnlump[tex][col]; + ofs = texturecolumnofs[tex][col]; + + if (lump > 0) + return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs; + + if (!texturecomposite[tex]) + R_GenerateComposite (tex); + + return texturecomposite[tex] + ofs; +} + + +static void GenerateTextureHashTable(void) +{ + texture_t **rover; + int i; + int key; + + textures_hashtable + = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); + + memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); + + // Add all textures to hash table + + for (i=0; iindex = i; + + // Vanilla Doom does a linear search of the texures array + // and stops at the first entry it finds. If there are two + // entries with the same name, the first one in the array + // wins. The new entry must therefore be added at the end + // of the hash chain, so that earlier entries win. + + key = W_LumpNameHash(textures[i]->name) % numtextures; + + rover = &textures_hashtable[key]; + + while (*rover != NULL) + { + rover = &(*rover)->next; + } + + // Hook into hash table + + textures[i]->next = NULL; + *rover = textures[i]; + } +} + + +// +// R_InitTextures +// Initializes the texture list +// with the textures from the world map. +// +void R_InitTextures (void) +{ + maptexture_t* mtexture; + texture_t* texture; + mappatch_t* mpatch; + texpatch_t* patch; + + int i; + int j; + + int* maptex; + int* maptex2; + int* maptex1; + + char name[9]; + char* names; + char* name_p; + + int* patchlookup; + + int nummappatches; + int offset; + int maxoff; + int maxoff2; + int numtextures1; + int numtextures2; + + int* directory; + + int temp1; + int temp2; + int temp3; + + + // Load the patch names from pnames.lmp. + names = W_CacheLumpName (DEH_String("PNAMES"), PU_STATIC); + nummappatches = LONG ( *((int *)names) ); + name_p = names+4; + patchlookup = Z_Malloc(nummappatches*sizeof(*patchlookup), PU_STATIC, NULL); + + for (i = 0; i < nummappatches; i++) + { + M_StringCopy(name, name_p + i * 8, sizeof(name)); + patchlookup[i] = W_CheckNumForName (name); + } + W_ReleaseLumpName(DEH_String("PNAMES")); + + // Load the map texture definitions from textures.lmp. + // The data is contained in one or two lumps, + // TEXTURE1 for shareware, plus TEXTURE2 for commercial. + maptex = maptex1 = W_CacheLumpName (DEH_String("TEXTURE1"), PU_STATIC); + numtextures1 = LONG(*maptex); + maxoff = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE1"))); + directory = maptex+1; + + if (W_CheckNumForName (DEH_String("TEXTURE2")) != -1) + { + maptex2 = W_CacheLumpName (DEH_String("TEXTURE2"), PU_STATIC); + numtextures2 = LONG(*maptex2); + maxoff2 = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE2"))); + } + else + { + maptex2 = NULL; + numtextures2 = 0; + maxoff2 = 0; + } + numtextures = numtextures1 + numtextures2; + + textures = Z_Malloc (numtextures * sizeof(*textures), PU_STATIC, 0); + texturecolumnlump = Z_Malloc (numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0); + texturecolumnofs = Z_Malloc (numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0); + texturecomposite = Z_Malloc (numtextures * sizeof(*texturecomposite), PU_STATIC, 0); + texturecompositesize = Z_Malloc (numtextures * sizeof(*texturecompositesize), PU_STATIC, 0); + texturewidthmask = Z_Malloc (numtextures * sizeof(*texturewidthmask), PU_STATIC, 0); + textureheight = Z_Malloc (numtextures * sizeof(*textureheight), PU_STATIC, 0); + + // Really complex printing shit... + temp1 = W_GetNumForName (DEH_String("S_START")); // P_??????? + temp2 = W_GetNumForName (DEH_String("S_END")) - 1; + temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64); + + // If stdout is a real console, use the classic vanilla "filling + // up the box" effect, which uses backspace to "step back" inside + // the box. If stdout is a file, don't draw the box. + + // haleyjd 20110206 [STRIFE]: box is in devparm only + if (devparm && I_ConsoleStdout()) + { + printf("["); + for (i = 0; i < temp3 + 9; i++) + printf(" "); + printf("]"); + for (i = 0; i < temp3 + 10; i++) + printf("\b"); + } + + for (i=0 ; i maxoff) + I_Error ("R_InitTextures: bad texture directory"); + + mtexture = (maptexture_t *) ( (byte *)maptex + offset); + + texture = textures[i] = + Z_Malloc (sizeof(texture_t) + + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), + PU_STATIC, 0); + + texture->width = SHORT(mtexture->width); + texture->height = SHORT(mtexture->height); + texture->patchcount = SHORT(mtexture->patchcount); + + memcpy (texture->name, mtexture->name, sizeof(texture->name)); + mpatch = &mtexture->patches[0]; + patch = &texture->patches[0]; + + for (j=0 ; jpatchcount ; j++, mpatch++, patch++) + { + patch->originx = SHORT(mpatch->originx); + patch->originy = SHORT(mpatch->originy); + patch->patch = patchlookup[SHORT(mpatch->patch)]; + if (patch->patch == -1) + { + I_Error ("R_InitTextures: Missing patch in texture %s", + texture->name); + } + } + texturecolumnlump[i] = Z_Malloc (texture->width*sizeof(**texturecolumnlump), PU_STATIC,0); + texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(**texturecolumnofs), PU_STATIC,0); + + j = 1; + while (j*2 <= texture->width) + j<<=1; + + texturewidthmask[i] = j-1; + textureheight[i] = texture->height<width)<leftoffset)<topoffset)<name, name, 8) ) + return texture->index; + + texture = texture->next; + } + + return -1; +} + + + +// +// R_TextureNumForName +// Calls R_CheckTextureNumForName, +// aborts with error message. +// +int R_TextureNumForName (const char* name) +{ + int i; + + i = R_CheckTextureNumForName (name); + + if (i==-1) + { + I_Error ("R_TextureNumForName: %s not found", + name); + } + return i; +} + +// +// R_SoundNumForDoor +// +// villsa [STRIFE] - new function +// Set sounds associated with door though why +// on earth is this function placed here? +// +void R_SoundNumForDoor(vldoor_t* door) +{ + int i; + sector_t *sector; + line_t *line; + texture_t *texture; + char name[8]; + char c1; + char c2; + + // set default sounds + door->opensound = sfx_drsmto; + door->closesound = sfx_drsmtc; + + for(sector = door->sector, i = 0; i < sector->linecount; i++) + { + line = sector->lines[i]; + + if(!(line->flags & ML_TWOSIDED)) + continue; + + texture = textures[sides[line->sidenum[0]].toptexture]; + memcpy(name, texture->name, 8); + + if(strncmp(name, "DOR", 3)) + continue; + + c1 = name[3]; + c2 = name[4]; + + // S type + if(c1 == 'S') + { + door->opensound = sfx_drston; + door->closesound = sfx_drston; + return; + } + + // M type + if(c1 == 'M') + { + // L subtype + if(c2 == 'L') + { + door->opensound = sfx_drlmto; + door->closesound = sfx_drlmtc; + } + // S subtype + else if(c2 == 'S') + { + door->opensound = sfx_drsmto; + door->closesound = sfx_drsmtc; + } + return; + } + // W type + else if(c1 == 'W') + { + // L subtype + if(c2 == 'L') + { + door->opensound = sfx_drlwud; + door->closesound = sfx_drlwud; + } + // S subtype + else if(c2 == 'S') + { + door->opensound = sfx_drswud; + door->closesound = sfx_drswud; + } + return; + } + } +} + + + + +// +// R_PrecacheLevel +// Preloads all relevant graphics for the level. +// +int flatmemory; +int texturememory; +int spritememory; + +void R_PrecacheLevel (void) +{ + char* flatpresent; + char* texturepresent; + char* spritepresent; + + int i; + int j; + int k; + int lump; + + texture_t* texture; + thinker_t* th; + spriteframe_t* sf; + + if (demoplayback) + return; + + // Precache flats. + flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); + memset (flatpresent,0,numflats); + + for (i=0 ; isize; + W_CacheLumpNum(lump, PU_CACHE); + } + } + + Z_Free(flatpresent); + + // Precache textures. + texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); + memset (texturepresent,0, numtextures); + + for (i=0 ; ipatchcount ; j++) + { + lump = texture->patches[j].patch; + texturememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump , PU_CACHE); + } + } + + Z_Free(texturepresent); + + // Precache sprites. + spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); + memset (spritepresent,0, numsprites); + + for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + { + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + spritepresent[((mobj_t *)th)->sprite] = 1; + } + + spritememory = 0; + for (i=0 ; ilump[k]; + spritememory += lumpinfo[lump]->size; + W_CacheLumpNum(lump , PU_CACHE); + } + } + } + + Z_Free(spritepresent); +} + + + + diff --git a/games/NXDoom/src/strife/r_data.h b/games/NXDoom/src/strife/r_data.h new file mode 100644 index 00000000000..efeb4f7533e --- /dev/null +++ b/games/NXDoom/src/strife/r_data.h @@ -0,0 +1,56 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh module, data I/O, caching, retrieval of graphics +// by name. +// + + +#ifndef __R_DATA__ +#define __R_DATA__ + +#include "r_defs.h" +#include "r_state.h" +#include "p_spec.h" // villsa [STRIFE] + + +extern int numflats; + + +// Retrieve column data for span blitting. +byte* +R_GetColumn +( int tex, + int col ); + + +// I/O, setting up the stuff. +void R_InitData (void); +void R_PrecacheLevel (void); + + +// Retrieval. +// Floor/ceiling opaque texture tiles, +// lookup by name. For animation? +int R_FlatNumForName(const char *name); + + +// Called by P_Ticker for switches and animations, +// returns the texture number for the texture name. +int R_TextureNumForName (const char *name); +int R_CheckTextureNumForName (const char *name); +void R_SoundNumForDoor(vldoor_t* door); // villsa [STRIFE] + +#endif diff --git a/games/NXDoom/src/strife/r_defs.h b/games/NXDoom/src/strife/r_defs.h new file mode 100644 index 00000000000..a64ac8424ac --- /dev/null +++ b/games/NXDoom/src/strife/r_defs.h @@ -0,0 +1,448 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh/rendering module, shared data struct definitions. +// + + +#ifndef __R_DEFS__ +#define __R_DEFS__ + + +// Screenwidth. +#include "doomdef.h" + +// Some more or less basic data types +// we depend on. +#include "m_fixed.h" + +// We rely on the thinker data struct +// to handle sound origins in sectors. +#include "d_think.h" +// SECTORS do store MObjs anyway. +#include "p_mobj.h" + +#include "i_video.h" + +#include "v_patch.h" + + + + +// Silhouette, needed for clipping Segs (mainly) +// and sprites representing things. +#define SIL_NONE 0 +#define SIL_BOTTOM 1 +#define SIL_TOP 2 +#define SIL_BOTH 3 + +#define MAXDRAWSEGS 256 + + + + + +// +// INTERNAL MAP TYPES +// used by play and refresh +// + +// +// Your plain vanilla vertex. +// Note: transformed values not buffered locally, +// like some DOOM-alikes ("wt", "WebView") did. +// +typedef struct +{ + fixed_t x; + fixed_t y; + +} vertex_t; + + +// Forward of LineDefs, for Sectors. +struct line_s; + +// Each sector has a degenmobj_t in its center +// for sound origin purposes. +// I suppose this does not handle sound from +// moving objects (doppler), because +// position is prolly just buffered, not +// updated. +typedef struct +{ + thinker_t thinker; // not used for anything + fixed_t x; + fixed_t y; + fixed_t z; + +} degenmobj_t; + +// +// The SECTORS record, at runtime. +// Stores things/mobjs. +// +typedef struct +{ + fixed_t floorheight; + fixed_t ceilingheight; + short floorpic; + short ceilingpic; + short lightlevel; + short special; + short tag; + + // 0 = untraversed, 1,2 = sndlines -1 + int soundtraversed; + + // thing that made a sound (or null) + mobj_t* soundtarget; + + // mapblock bounding box for height changes + int blockbox[4]; + + // origin for any sounds played by the sector + degenmobj_t soundorg; + + // if == validcount, already checked + int validcount; + + // list of mobjs in sector + mobj_t* thinglist; + + // thinker_t for reversable actions + void* specialdata; + + int linecount; + struct line_s** lines; // [linecount] size + +} sector_t; + + + + +// +// The SideDef. +// + +typedef struct +{ + // add this to the calculated texture column + fixed_t textureoffset; + + // add this to the calculated texture top + fixed_t rowoffset; + + // Texture indices. + // We do not maintain names here. + short toptexture; + short bottomtexture; + short midtexture; + + // Sector the SideDef is facing. + sector_t* sector; + +} side_t; + + + +// +// Move clipping aid for LineDefs. +// +typedef enum +{ + ST_HORIZONTAL, + ST_VERTICAL, + ST_POSITIVE, + ST_NEGATIVE + +} slopetype_t; + + + +typedef struct line_s +{ + // Vertices, from v1 to v2. + vertex_t* v1; + vertex_t* v2; + + // Precalculated v2 - v1 for side checking. + fixed_t dx; + fixed_t dy; + + // Animation related. + short flags; + short special; + short tag; + + // Visual appearance: SideDefs. + // sidenum[1] will be -1 if one sided + short sidenum[2]; + + // Neat. Another bounding box, for the extent + // of the LineDef. + fixed_t bbox[4]; + + // To aid move clipping. + slopetype_t slopetype; + + // Front and back sector. + // Note: redundant? Can be retrieved from SideDefs. + sector_t* frontsector; + sector_t* backsector; + + // if == validcount, already checked + int validcount; + + // thinker_t for reversable actions + void* specialdata; +} line_t; + + + + +// +// A SubSector. +// References a Sector. +// Basically, this is a list of LineSegs, +// indicating the visible walls that define +// (all or some) sides of a convex BSP leaf. +// +typedef struct subsector_s +{ + sector_t* sector; + short numlines; + short firstline; + +} subsector_t; + + + +// +// The LineSeg. +// +typedef struct +{ + vertex_t* v1; + vertex_t* v2; + + fixed_t offset; + + angle_t angle; + + side_t* sidedef; + line_t* linedef; + + // Sector references. + // Could be retrieved from linedef, too. + // backsector is NULL for one sided lines + sector_t* frontsector; + sector_t* backsector; + +} seg_t; + + + +// +// BSP node. +// +typedef struct +{ + // Partition line. + fixed_t x; + fixed_t y; + fixed_t dx; + fixed_t dy; + + // Bounding box for each child. + fixed_t bbox[2][4]; + + // If NF_SUBSECTOR its a subsector. + unsigned short children[2]; + +} node_t; + + + + +// PC direct to screen pointers +//B UNUSED - keep till detailshift in r_draw.c resolved +//extern byte* destview; +//extern byte* destscreen; + + + + + +// +// OTHER TYPES +// + +// This could be wider for >8 bit display. +// Indeed, true color support is posibble +// precalculating 24bpp lightmap/colormap LUT. +// from darkening PLAYPAL to all black. +// Could even us emore than 32 levels. +typedef byte lighttable_t; + + + + +// +// ? +// +typedef struct drawseg_s +{ + seg_t* curline; + int x1; + int x2; + + fixed_t scale1; + fixed_t scale2; + fixed_t scalestep; + + // 0=none, 1=bottom, 2=top, 3=both + int silhouette; + + // do not clip sprites above this + fixed_t bsilheight; + + // do not clip sprites below this + fixed_t tsilheight; + + // Pointers to lists for sprite clipping, + // all three adjusted so [x1] is first value. + short* sprtopclip; + short* sprbottomclip; + short* maskedtexturecol; + +} drawseg_t; + + + +// A vissprite_t is a thing +// that will be drawn during a refresh. +// I.e. a sprite object that is partly visible. +typedef struct vissprite_s +{ + // Doubly linked list. + struct vissprite_s* prev; + struct vissprite_s* next; + + int x1; + int x2; + + // for line side calculation + fixed_t gx; + fixed_t gy; + + // global bottom / top for silhouette clipping + fixed_t gz; + fixed_t gzt; + + // horizontal position of x1 + fixed_t startfrac; + + fixed_t scale; + + // negative if flipped + fixed_t xiscale; + + fixed_t texturemid; + int patch; + + // for color translation and shadow draw, + // maxbright frames as well + lighttable_t* colormap; + + int mobjflags; + +} vissprite_t; + + +// +// Sprites are patches with a special naming convention +// so they can be recognized by R_InitSprites. +// The base name is NNNNFx or NNNNFxFx, with +// x indicating the rotation, x = 0, 1-7. +// The sprite and frame specified by a thing_t +// is range checked at run time. +// A sprite is a patch_t that is assumed to represent +// a three dimensional object and may have multiple +// rotations pre drawn. +// Horizontal flipping is used to save space, +// thus NNNNF2F5 defines a mirrored patch. +// Some sprites will only have one picture used +// for all views: NNNNF0 +// +typedef struct +{ + // If false use 0 for any position. + // Note: as eight entries are available, + // we might as well insert the same name eight times. + boolean rotate; + + // Lump to use for view angles 0-7. + short lump[8]; + + // Flip bit (1 = flip) to use for view angles 0-7. + byte flip[8]; + +} spriteframe_t; + + + +// +// A sprite definition: +// a number of animation frames. +// +typedef struct +{ + int numframes; + spriteframe_t* spriteframes; + +} spritedef_t; + + + +// +// Now what is a visplane, anyway? +// +typedef struct +{ + fixed_t height; + int picnum; + int lightlevel; + int minx; + int maxx; + + // leave pads for [minx-1]/[maxx+1] + + byte pad1; + // Here lies the rub for all + // dynamic resize/change of resolution. + byte top[SCREENWIDTH]; + byte pad2; + byte pad3; + // See above. + byte bottom[SCREENWIDTH]; + byte pad4; + +} visplane_t; + + + + +#endif diff --git a/games/NXDoom/src/strife/r_draw.c b/games/NXDoom/src/strife/r_draw.c new file mode 100644 index 00000000000..de6d1d0a979 --- /dev/null +++ b/games/NXDoom/src/strife/r_draw.c @@ -0,0 +1,968 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The actual span/column drawing functions. +// Here find the main potential for optimization, +// e.g. inline assembly, different algorithms. +// + + + + +#include "doomdef.h" +#include "deh_main.h" + +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" + +#include "r_local.h" + +// Needs access to LFB (guess what). +#include "v_video.h" + +// State. +#include "doomstat.h" + + +// ? +#define MAXWIDTH 1120 +#define MAXHEIGHT 832 + +// status bar height at bottom of screen +// haleyjd 08/31/10: Verified unmodified. +#define SBARHEIGHT 32 + +// +// All drawing to the view buffer is accomplished in this file. +// The other refresh files only know about ccordinates, +// not the architecture of the frame buffer. +// Conveniently, the frame buffer is a linear one, +// and we need only the base address, +// and the total size == width*height*depth/8., +// + + +byte* viewimage; +int viewwidth; +int scaledviewwidth; +int viewheight; +int viewwindowx; +int viewwindowy; +byte* ylookup[MAXHEIGHT]; +int columnofs[MAXWIDTH]; + +// Color tables for different players, +// translate a limited part to another +// (color ramps used for suit colors). +// +// [STRIFE] Unused. +//byte translations[3][256]; + +// Backing buffer containing the bezel drawn around the screen and +// surrounding background. + +static byte *background_buffer = NULL; + +// haleyjd 08/29/10: [STRIFE] Rogue added the ability to customize the view +// border flat by storing it in the configuration file. +char *back_flat = "F_PAVE01"; + +// +// R_DrawColumn +// Source is the top of the column to scale. +// +lighttable_t* dc_colormap; +int dc_x; +int dc_yl; +int dc_yh; +fixed_t dc_iscale; +fixed_t dc_texturemid; + +// first pixel in a column (possibly virtual) +byte* dc_source; + +// just for profiling +int dccount; + +// +// A column is a vertical slice/span from a wall texture that, +// given the DOOM style restrictions on the view orientation, +// will always have constant z depth. +// Thus a special case loop for very fast rendering can +// be used. It has also been used with Wolfenstein 3D. +// +void R_DrawColumn (void) +{ + int count; + byte* dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + // Zero length, column does not exceed a pixel. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + // Framebuffer destination address. + // Use ylookup LUT to avoid multiply with ScreenWidth. + // Use columnofs LUT for subwindows? + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Determine scaling, + // which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + // Inner loop that does the actual texture mapping, + // e.g. a DDA-lile scaling. + // This is as fast as it gets. + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; + + dest += SCREENWIDTH; + frac += fracstep; + + } while (count--); +} + + + +// UNUSED. +// Loop unrolled. +#if 0 +void R_DrawColumn (void) +{ + int count; + byte* source; + byte* dest; + byte* colormap; + + unsigned frac; + unsigned fracstep; + unsigned fracstep2; + unsigned fracstep3; + unsigned fracstep4; + + count = dc_yh - dc_yl + 1; + + source = dc_source; + colormap = dc_colormap; + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale<<9; + frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; + + fracstep2 = fracstep+fracstep; + fracstep3 = fracstep2+fracstep; + fracstep4 = fracstep3+fracstep; + + while (count >= 8) + { + dest[0] = colormap[source[frac>>25]]; + dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; + dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; + dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]]; + + frac += fracstep4; + + dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; + dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; + dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; + dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; + + frac += fracstep4; + dest += SCREENWIDTH*8; + count -= 8; + } + + while (count > 0) + { + *dest = colormap[source[frac>>25]]; + dest += SCREENWIDTH; + frac += fracstep; + count--; + } +} +#endif + +// haleyjd 09/06/10 [STRIFE] Removed low detail + +// +// Spectre/Invisibility. +// + +// haleyjd 09/06/10: ]STRIFE] replaced fuzzdraw with translucency. + +// +// R_DrawMVisTLColumn +// +// villsa [STRIFE] new function +// Replacement for R_DrawFuzzColumn +// +void R_DrawMVisTLColumn(void) +{ + int count; + byte* dest; + fixed_t frac; + fixed_t fracstep; + + // Adjust borders. Low... + if (!dc_yl) + dc_yl = 1; + + // .. and high. + if (dc_yh == viewheight-1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + { + I_Error ("R_DrawFuzzColumn: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + do + { + byte src = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; + byte col = xlatab[*dest + (src << 8)]; + *dest = col; + dest += SCREENWIDTH; + frac += fracstep; + } while(count--); +} + +// +// R_DrawTLColumn +// +// villsa [STRIFE] new function +// Achieves a second translucency level using the same lookup table, +// via inversion of the colors in the index computation. +// +void R_DrawTLColumn(void) +{ + int count; + byte* dest; + fixed_t frac; + fixed_t fracstep; + + // Adjust borders. Low... + if (!dc_yl) + dc_yl = 1; + + // .. and high. + if (dc_yh == viewheight-1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + { + I_Error ("R_DrawFuzzColumn2: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + do + { + byte src = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; + byte col = xlatab[(*dest << 8) + src]; + *dest = col; + dest += SCREENWIDTH; + frac += fracstep; + } while(count--); +} + + + +// +// R_DrawTranslatedColumn +// Used to draw player sprites +// with the green colorramp mapped to others. +// Could be used with different translation +// tables, e.g. the lighter colored version +// of the BaronOfHell, the HellKnight, uses +// identical sprites, kinda brightened up. +// +byte* dc_translation; +byte* translationtables; + +void R_DrawTranslatedColumn (void) +{ + int count; + byte* dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + { + I_Error ( "R_DrawColumn: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } + +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + // Here we do an additional index re-mapping. + do + { + // Translation tables are used + // to map certain colorramps to other ones, + // used with PLAY sprites. + // Thus the "green" ramp of the player 0 sprite + // is mapped to gray, red, black/indigo. + *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; + dest += SCREENWIDTH; + frac += fracstep; + } while (count--); +} + +// haleyjd 09/06/10 [STRIFE] Removed low detail + +// +// R_DrawTRTLColumn +// +// villsa [STRIFE] new function +// Combines translucency and color translation. +// +void R_DrawTRTLColumn(void) +{ + int count; + byte* dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH + || dc_yl < 0 + || dc_yh >= SCREENHEIGHT) + { + I_Error ( "R_DrawColumn: %i to %i at %i", + dc_yl, dc_yh, dc_x); + } +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl-centery)*fracstep; + + // Here we do an additional index re-mapping. + do + { + byte src = dc_colormap[dc_translation[dc_source[frac>>FRACBITS&127]]]; + byte col = xlatab[(*dest << 8) + src]; + *dest = col; + dest += SCREENWIDTH; + frac += fracstep; + } while (count--); +} + + +// +// R_InitTranslationTables +// Creates the translation tables to map +// the green color ramp to gray, brown, red. +// Assumes a given structure of the PLAYPAL. +// Could be read from a lump instead. +// +// haleyjd 08/26/10: [STRIFE] +// * Added loading of XLATAB +// +void R_InitTranslationTables (void) +{ + int i; + byte col1, col2; + + // [STRIFE] Load xlatab. Here's how Rogue did it: + // v7 = W_CacheLumpName("XLATAB", PU_CACHE); // note potential cache bug... + // HIWORD(v8) = (Z_Malloc(131072, PU_STATIC, NULL) + 65535) >> 16; + // LOWORD(v8) = 0; // aligning to a 64K boundary, as if this is Wolf3D. + // xlatab = v8; + // memcpy(v8, v7, 65536); + // As you can see, they copypasta'd id's unnecessary 64K boundary alignment + // from the colormap code. Since this doesn't accomplish anything, and isn't + // strictly portable, all we need to do is this: + + // villsa [STRIFE] 09/26/10: load table through this function instead + V_LoadXlaTable(); + + // villsa [STRIFE] allocate a larger size for translation tables + translationtables = Z_Malloc (256*8, PU_STATIC, 0); + + col1 = 0xFA; + col2 = 0xE0; + + // villsa [STRIFE] setup all translation tables + for(i = 0; i < 256; i++) + { + if(i >= 0x80 && i <= 0x8f) + { + translationtables [i ] = (i & 0x0f) + 64; + translationtables [i+ 256] = (i & 0x0f) - 80; + translationtables [i+2*256] = (i & 0x0f) + 16; + translationtables [i+3*256] = (i & 0x0f) + 48; + translationtables [i+4*256] = (i & 0x0f) + 80; + translationtables [i+5*256] = (i & 0x0f) + 96; + translationtables [i+6*256] = (i & 0x0f) - 112; + } + else if(i >= 0x50 && i<= 0x5f) + { + translationtables [i ] = i; + translationtables [i+ 256] = i; + translationtables [i+2*256] = i; + translationtables [i+3*256] = i; + translationtables [i+4*256] = (i & 0x0f) + 0x80; + translationtables [i+5*256] = (i & 0x0f) + 16; + translationtables [i+6*256] = (i & 0x0f) + 64; + } + else if(i >= 0xd0 && i<= 0xdf) + { + translationtables [i ] = i; + translationtables [i+ 256] = i; + translationtables [i+2*256] = i; + translationtables [i+3*256] = i; + translationtables [i+4*256] = (i & 0x0f) - 80; + translationtables [i+5*256] = (i & 0x0f) + 48; + translationtables [i+6*256] = (i & 0x0f) + 16; + } + else if(i >= 0xc0 && i<= 0xcf) + { + translationtables [i ] = i; + translationtables [i+ 256] = i; + translationtables [i+2*256] = i; + translationtables [i+3*256] = i; + translationtables [i+4*256] = (i & 0x0f) - 96; + translationtables [i+5*256] = (i & 0x0f) + 32; + translationtables [i+6*256] = (i & 0x0f); + // haleyjd 20110213: missing code: + if(!(i & 0x0f)) + translationtables[i+6*256] = 1; + } + else if(i >= 0xf7 && i<= 0xfb) + { + translationtables [i ] = col1; + translationtables [i+ 256] = i; + translationtables [i+2*256] = i; + translationtables [i+3*256] = i; + translationtables [i+4*256] = i; + translationtables [i+5*256] = i; + translationtables [i+6*256] = i; + } + else if(i >= 0xf1 && i<= 0xf6) + { + translationtables [i ] = (i & 0x0f) - 33; + translationtables [i+ 256] = i; + translationtables [i+2*256] = i; + translationtables [i+3*256] = i; + translationtables [i+4*256] = i; + translationtables [i+5*256] = i; + translationtables [i+6*256] = i; + } + else if(i >= 0x20 && i <= 0x3f) // haleyjd 20110213: fixed upper end + { + translationtables [i ] = col2; + translationtables [i+ 256] = col2; + translationtables [i+2*256] = (i & 0x0f) - 48; + translationtables [i+3*256] = (i & 0x0f) - 48; + translationtables [i+4*256] = col2; + translationtables [i+5*256] = col2; + translationtables [i+6*256] = col2; + } + else // Keep all other colors as is. + { + translationtables[i]= + translationtables[i+256]= + translationtables[i+2*256]= + translationtables[i+3*256]= + translationtables[i+4*256]= + translationtables[i+5*256]= + translationtables[i+6*256]=i; + } + + ++col1; + ++col2; + } +} + + + + +// +// R_DrawSpan +// With DOOM style restrictions on view orientation, +// the floors and ceilings consist of horizontal slices +// or spans with constant z depth. +// However, rotation around the world z axis is possible, +// thus this mapping, while simpler and faster than +// perspective correct texture mapping, has to traverse +// the texture at an angle in all but a few cases. +// In consequence, flats are not stored by column (like walls), +// and the inner loop has to step in texture space u and v. +// +int ds_y; +int ds_x1; +int ds_x2; + +lighttable_t* ds_colormap; + +fixed_t ds_xfrac; +fixed_t ds_yfrac; +fixed_t ds_xstep; +fixed_t ds_ystep; + +// start of a 64*64 tile image +byte* ds_source; + +// just for profiling +int dscount; + + +// +// Draws the actual span. +void R_DrawSpan (void) +{ + unsigned int position, step; + byte *dest; + int count; + int spot; + unsigned int xtemp, ytemp; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 + || ds_x1<0 + || ds_x2>=SCREENWIDTH + || (unsigned)ds_y>SCREENHEIGHT) + { + I_Error( "R_DrawSpan: %i to %i at %i", + ds_x1,ds_x2,ds_y); + } +// dscount++; +#endif + + // Pack position and step variables into a single 32-bit integer, + // with x in the top 16 bits and y in the bottom 16 bits. For + // each 16-bit part, the top 6 bits are the integer part and the + // bottom 10 bits are the fractional part of the pixel position. + + position = ((ds_xfrac << 10) & 0xffff0000) + | ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) + | ((ds_ystep >> 6) & 0x0000ffff); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + + // We do not check for zero spans here? + count = ds_x2 - ds_x1; + + do + { + // Calculate current texture index in u,v. + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + // Lookup pixel from flat texture tile, + // re-index using light/colormap. + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + + } while (count--); +} + + + +// UNUSED. +// Loop unrolled by 4. +#if 0 +void R_DrawSpan (void) +{ + unsigned position, step; + + byte* source; + byte* colormap; + byte* dest; + + unsigned count; + usingned spot; + unsigned value; + unsigned temp; + unsigned xtemp; + unsigned ytemp; + + position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff); + step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff); + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; + + while (count >= 4) + { + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[0] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[1] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[2] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[3] = colormap[source[spot]]; + + count -= 4; + dest += 4; + } + while (count > 0) + { + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + *dest++ = colormap[source[spot]]; + count--; + } +} +#endif + + +// +// Again.. +// +void R_DrawSpanLow (void) +{ + unsigned int position, step; + unsigned int xtemp, ytemp; + byte *dest; + int count; + int spot; + +#ifdef RANGECHECK + if (ds_x2 < ds_x1 + || ds_x1<0 + || ds_x2>=SCREENWIDTH + || (unsigned)ds_y>SCREENHEIGHT) + { + I_Error( "R_DrawSpan: %i to %i at %i", + ds_x1,ds_x2,ds_y); + } +// dscount++; +#endif + + position = ((ds_xfrac << 10) & 0xffff0000) + | ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) + | ((ds_ystep >> 6) & 0x0000ffff); + + count = (ds_x2 - ds_x1); + + // Blocky mode, need to multiply by 2. + ds_x1 <<= 1; + ds_x2 <<= 1; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + + do + { + // Calculate current texture index in u,v. + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + // Lowres/blocky mode does it twice, + // while scale is adjusted appropriately. + *dest++ = ds_colormap[ds_source[spot]]; + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + + } while (count--); +} + +// +// R_InitBuffer +// Creats lookup tables that avoid +// multiplies and other hazzles +// for getting the framebuffer address +// of a pixel to draw. +// +void +R_InitBuffer +( int width, + int height ) +{ + int i; + + // Handle resize, + // e.g. smaller view windows + // with border and/or status bar. + viewwindowx = (SCREENWIDTH-width) >> 1; + + // Column offset. For windows. + for (i=0 ; i> 1; + + // Preclaculate all row offsets. + for (i=0 ; i +#include + + +#include "doomdef.h" +#include "doomstat.h" // villsa [STRIFE] +#include "d_main.h" + +#include "m_bbox.h" +#include "m_menu.h" + +#include "r_local.h" +#include "r_sky.h" + + + + + +// Fineangles in the SCREENWIDTH wide window. +#define FIELDOFVIEW 2048 + + + +int viewangleoffset; + +// increment every time a check is made +int validcount = 1; + + +lighttable_t* fixedcolormap; + +int centerx; +int centery; + +fixed_t centerxfrac; +fixed_t centeryfrac; +fixed_t projection; + +// just for profiling purposes +int framecount; + +int sscount; +int linecount; +int loopcount; + +fixed_t viewx; +fixed_t viewy; +fixed_t viewz; + +int viewpitch; // villsa [STRIFE] + +angle_t viewangle; + +fixed_t viewcos; +fixed_t viewsin; + +player_t* viewplayer; + +// 0 = high, 1 = low +int detailshift; + +// +// precalculated math tables +// +angle_t clipangle; + +// The viewangletox[viewangle + FINEANGLES/4] lookup +// maps the visible view angles to screen X coordinates, +// flattening the arc to a flat projection plane. +// There will be many angles mapped to the same X. +int viewangletox[FINEANGLES/2]; + +// The xtoviewangleangle[] table maps a screen pixel +// to the lowest viewangle that maps back to x ranges +// from clipangle to -clipangle. +angle_t xtoviewangle[SCREENWIDTH+1]; + +lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +lighttable_t* scalelightfixed[MAXLIGHTSCALE]; +lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ]; + +// bumped light from gun blasts +int extralight; + + + +void (*colfunc) (void); +void (*basecolfunc) (void); +void (*fuzzcolfunc) (void); +void (*transcolfunc) (void); +void (*spanfunc) (void); + + + +// +// R_AddPointToBox +// Expand a given bbox +// so that it encloses a given point. +// +void +R_AddPointToBox +( int x, + int y, + fixed_t* box ) +{ + if (x< box[BOXLEFT]) + box[BOXLEFT] = x; + if (x> box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y< box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + if (y> box[BOXTOP]) + box[BOXTOP] = y; +} + + +// +// R_PointOnSide +// Traverse BSP (sub) tree, +// check point against partition plane. +// Returns side 0 (front) or 1 (back). +// +int +R_PointOnSide +( fixed_t x, + fixed_t y, + node_t* node ) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!node->dx) + { + if (x <= node->x) + return node->dy > 0; + + return node->dy < 0; + } + if (!node->dy) + { + if (y <= node->y) + return node->dx < 0; + + return node->dx > 0; + } + + dx = (x - node->x); + dy = (y - node->y); + + // Try to quickly decide by looking at sign bits. + if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 ) + { + if ( (node->dy ^ dx) & 0x80000000 ) + { + // (left is negative) + return 1; + } + return 0; + } + + left = FixedMul ( node->dy>>FRACBITS , dx ); + right = FixedMul ( dy , node->dx>>FRACBITS ); + + if (right < left) + { + // front side + return 0; + } + // back side + return 1; +} + + +int +R_PointOnSegSide +( fixed_t x, + fixed_t y, + seg_t* line ) +{ + fixed_t lx; + fixed_t ly; + fixed_t ldx; + fixed_t ldy; + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + lx = line->v1->x; + ly = line->v1->y; + + ldx = line->v2->x - lx; + ldy = line->v2->y - ly; + + if (!ldx) + { + if (x <= lx) + return ldy > 0; + + return ldy < 0; + } + if (!ldy) + { + if (y <= ly) + return ldx < 0; + + return ldx > 0; + } + + dx = (x - lx); + dy = (y - ly); + + // Try to quickly decide by looking at sign bits. + if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 ) + { + if ( (ldy ^ dx) & 0x80000000 ) + { + // (left is negative) + return 1; + } + return 0; + } + + left = FixedMul ( ldy>>FRACBITS , dx ); + right = FixedMul ( dy , ldx>>FRACBITS ); + + if (right < left) + { + // front side + return 0; + } + // back side + return 1; +} + + +// +// R_PointToAngle +// To get a global angle from cartesian coordinates, +// the coordinates are flipped until they are in +// the first octant of the coordinate system, then +// the y (<=x) is scaled and divided by x to get a +// tangent (slope) value which is looked up in the +// tantoangle[] table. + +// + + + + +angle_t +R_PointToAngle +( fixed_t x, + fixed_t y ) +{ + x -= viewx; + y -= viewy; + + if ( (!x) && (!y) ) + return 0; + + if (x>= 0) + { + // x >=0 + if (y>= 0) + { + // y>= 0 + + if (x>y) + { + // octant 0 + return tantoangle[ SlopeDiv(y,x)]; + } + else + { + // octant 1 + return ANG90-1-tantoangle[ SlopeDiv(x,y)]; + } + } + else + { + // y<0 + y = -y; + + if (x>y) + { + // octant 8 + return 0 - tantoangle[SlopeDiv(y,x)]; + } + else + { + // octant 7 + return ANG270+tantoangle[ SlopeDiv(x,y)]; + } + } + } + else + { + // x<0 + x = -x; + + if (y>= 0) + { + // y>= 0 + if (x>y) + { + // octant 3 + return ANG180-1-tantoangle[ SlopeDiv(y,x)]; + } + else + { + // octant 2 + return ANG90+ tantoangle[ SlopeDiv(x,y)]; + } + } + else + { + // y<0 + y = -y; + + if (x>y) + { + // octant 4 + return ANG180+tantoangle[ SlopeDiv(y,x)]; + } + else + { + // octant 5 + return ANG270-1-tantoangle[ SlopeDiv(x,y)]; + } + } + } + return 0; +} + + +angle_t +R_PointToAngle2 +( fixed_t x1, + fixed_t y1, + fixed_t x2, + fixed_t y2 ) +{ + viewx = x1; + viewy = y1; + + return R_PointToAngle (x2, y2); +} + + +fixed_t +R_PointToDist +( fixed_t x, + fixed_t y ) +{ + int angle; + fixed_t dx; + fixed_t dy; + fixed_t temp; + fixed_t dist; + fixed_t frac; + + dx = abs(x - viewx); + dy = abs(y - viewy); + + if (dy>dx) + { + temp = dx; + dx = dy; + dy = temp; + } + + // Fix crashes in udm1.wad + + if (dx != 0) + { + frac = FixedDiv(dy, dx); + } + else + { + frac = 0; + } + + angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT; + + // use as cosine + dist = FixedDiv (dx, finesine[angle] ); + + return dist; +} + + + + +// +// R_InitPointToAngle +// +void R_InitPointToAngle (void) +{ + // UNUSED - now getting from tables.c +#if 0 + int i; + long t; + float f; +// +// slope (tangent) to angle lookup +// + for (i=0 ; i<=SLOPERANGE ; i++) + { + f = atan( (float)i/SLOPERANGE )/(3.141592657*2); + t = 0xffffffff*f; + tantoangle[i] = t; + } +#endif +} + + +// +// R_ScaleFromGlobalAngle +// Returns the texture mapping scale +// for the current line (horizontal span) +// at the given angle. +// rw_distance must be calculated first. +// +fixed_t R_ScaleFromGlobalAngle (angle_t visangle) +{ + fixed_t scale; + angle_t anglea; + angle_t angleb; + int sinea; + int sineb; + fixed_t num; + int den; + + // UNUSED +#if 0 +{ + fixed_t dist; + fixed_t z; + fixed_t sinv; + fixed_t cosv; + + sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; + dist = FixedDiv (rw_distance, sinv); + cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; + z = abs(FixedMul (dist, cosv)); + scale = FixedDiv(projection, z); + return scale; +} +#endif + + anglea = ANG90 + (visangle-viewangle); + angleb = ANG90 + (visangle-rw_normalangle); + + // both sines are allways positive + sinea = finesine[anglea>>ANGLETOFINESHIFT]; + sineb = finesine[angleb>>ANGLETOFINESHIFT]; + num = FixedMul(projection,sineb)< num>>16) + { + scale = FixedDiv (num, den); + + if (scale > 64*FRACUNIT) + scale = 64*FRACUNIT; + else if (scale < 256) + scale = 256; + } + else + scale = 64*FRACUNIT; + + return scale; +} + + + +// +// R_InitTables +// +void R_InitTables (void) +{ + // UNUSED: now getting from tables.c +#if 0 + int i; + float a; + float fv; + int t; + + // viewangle tangent table + for (i=0 ; i FRACUNIT*2) + t = -1; + else if (finetangent[i] < -FRACUNIT*2) + t = viewwidth+1; + else + { + t = FixedMul (finetangent[i], focallength); + t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS; + + if (t < -1) + t = -1; + else if (t>viewwidth+1) + t = viewwidth+1; + } + viewangletox[i] = t; + } + + // Scan viewangletox[] to generate xtoviewangle[]: + // xtoviewangle will give the smallest view angle + // that maps to x. + for (x=0;x<=viewwidth;x++) + { + i = 0; + while (viewangletox[i]>x) + i++; + xtoviewangle[x] = (i<>= LIGHTSCALESHIFT; + level = startmap - scale/DISTMAP; + + if (level < 0) + level = 0; + + if (level >= NUMCOLORMAPS) + level = NUMCOLORMAPS-1; + + zlight[i][j] = colormaps + level*256; + } + } +} + + + +// +// R_SetViewSize +// Do not really change anything here, +// because it might be in the middle of a refresh. +// The change will take effect next refresh. +// +boolean setsizeneeded; +int setblocks; +int setdetail; + + +void +R_SetViewSize +( int blocks, + int detail ) +{ + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; +} + + +// +// R_ExecuteSetViewSize +// +void R_ExecuteSetViewSize (void) +{ + fixed_t cosadj; + fixed_t dy; + int i; + int j; + int level; + int startmap; + + setsizeneeded = false; + + if (setblocks == 11) + { + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; + } + else + { + scaledviewwidth = setblocks*32; + viewheight = (setblocks*168/10)&~7; + } + + detailshift = setdetail; + viewwidth = scaledviewwidth>>detailshift; + + // villsa [STRIFE] calculate centery from player's pitch + centery = (setblocks*players[consoleplayer].pitch); + centery = (unsigned int)(centery/10)+viewheight/2; + + centerx = viewwidth/2; + centerxfrac = centerx< centery, accounts for up/down look + dy = ((i - centery)<>ANGLETOFINESHIFT]); + distscale[i] = FixedDiv (FRACUNIT,cosadj); + } + + // Calculate the light levels to use + // for each level / scale combination. + for (i=0 ; i< LIGHTLEVELS ; i++) + { + startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; + for (j=0 ; j= NUMCOLORMAPS) + level = NUMCOLORMAPS-1; + + scalelight[i][j] = colormaps + level*256; + } + } +} + + + +// +// R_Init +// + + + +void R_Init (void) +{ + R_InitData (); + if(devparm) + printf ("."); + else + D_IntroTick(); // [STRIFE] tick intro + + R_InitPointToAngle (); + if(devparm) + printf ("."); + + R_InitTables (); + // viewwidth / viewheight / detailLevel are set by the defaults + if(devparm) + printf ("."); + + R_SetViewSize (screenblocks, detailLevel); + R_InitPlanes (); + if(devparm) + printf ("."); + + R_InitLightTables (); + if(devparm) + printf ("."); + else + D_IntroTick(); + + R_InitSkyMap (); + if(!devparm) + D_IntroTick(); + + R_InitTranslationTables (); + if(devparm) + printf ("."); + else + D_IntroTick(); + + framecount = 0; +} + + +// +// R_PointInSubsector +// +subsector_t* +R_PointInSubsector +( fixed_t x, + fixed_t y ) +{ + node_t* node; + int side; + int nodenum; + + // single subsector is a special case + if (!numnodes) + return subsectors; + + nodenum = numnodes-1; + + while (! (nodenum & NF_SUBSECTOR) ) + { + node = &nodes[nodenum]; + side = R_PointOnSide (x, y, node); + nodenum = node->children[side]; + } + + return &subsectors[nodenum & ~NF_SUBSECTOR]; +} + +// +// R_SetupPitch +// villsa [STRIFE] new function +// Calculate centery/centeryfrac for player viewpitch +// + +void R_SetupPitch(player_t* player) +{ + int pitchfrac; + int i = 0; + + if(viewpitch != player->pitch) + { + viewpitch = player->pitch; + pitchfrac = (setblocks * player->pitch) / 10; + centery = pitchfrac + viewheight / 2; + centeryfrac = centery << FRACBITS; + + for(i = 0; i < viewheight; i++) + { + yslope[i] = FixedDiv(viewwidth / 2 * FRACUNIT, + abs(((i - centery) << FRACBITS) + (FRACUNIT/2))); + } + } +} + + +// +// R_SetupFrame +// +void R_SetupFrame (player_t* player) +{ + int i; + + R_SetupPitch(player); // villsa [STRIFE] + + viewplayer = player; + viewx = player->mo->x; + viewy = player->mo->y; + viewangle = player->mo->angle + viewangleoffset; + extralight = player->extralight; + + viewz = player->viewz; + + viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; + viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; + + sscount = 0; + + if (player->fixedcolormap) + { + fixedcolormap = + colormaps + + player->fixedcolormap*256*sizeof(lighttable_t); + + walllights = scalelightfixed; + + for (i=0 ; i +#include + +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" + +#include "doomdef.h" +#include "doomstat.h" + +#include "r_local.h" +#include "r_sky.h" + + + +planefunction_t floorfunc; +planefunction_t ceilingfunc; + +// +// opening +// + +// Here comes the obnoxious "visplane". +// haleyjd 08/29/10: [STRIFE] MAXVISPLANES increased to 200 +#define MAXVISPLANES 200 +visplane_t visplanes[MAXVISPLANES]; +visplane_t* lastvisplane; +visplane_t* floorplane; +visplane_t* ceilingplane; + +// ? +#define MAXOPENINGS SCREENWIDTH*64 +short openings[MAXOPENINGS]; +short* lastopening; + + +// +// Clip values are the solid pixel bounding the range. +// floorclip starts out SCREENHEIGHT +// ceilingclip starts out -1 +// +short floorclip[SCREENWIDTH]; +short ceilingclip[SCREENWIDTH]; + +// +// spanstart holds the start of a plane span +// initialized to 0 at start +// +int spanstart[SCREENHEIGHT]; +int spanstop[SCREENHEIGHT]; + +// +// texture mapping +// +lighttable_t** planezlight; +fixed_t planeheight; + +fixed_t yslope[SCREENHEIGHT]; +fixed_t distscale[SCREENWIDTH]; +fixed_t basexscale; +fixed_t baseyscale; + +fixed_t cachedheight[SCREENHEIGHT]; +fixed_t cacheddistance[SCREENHEIGHT]; +fixed_t cachedxstep[SCREENHEIGHT]; +fixed_t cachedystep[SCREENHEIGHT]; + + + +// +// R_InitPlanes +// Only at game startup. +// +void R_InitPlanes (void) +{ + // Doh! +} + + +// +// R_MapPlane +// +// Uses global vars: +// planeheight +// ds_source +// basexscale +// baseyscale +// viewx +// viewy +// +// BASIC PRIMITIVE +// +void +R_MapPlane +( int y, + int x1, + int x2 ) +{ + angle_t angle; + fixed_t distance; + fixed_t length; + unsigned index; + +#ifdef RANGECHECK + if (x2 < x1 + || x1 < 0 + || x2 >= viewwidth + || y > viewheight) + { + I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); + } +#endif + + if (planeheight != cachedheight[y]) + { + cachedheight[y] = planeheight; + distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]); + ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale); + ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale); + } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + length = FixedMul (distance,distscale[x1]); + angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; + ds_xfrac = viewx + FixedMul(finecosine[angle], length); + ds_yfrac = -viewy - FixedMul(finesine[angle], length); + + if (fixedcolormap) + ds_colormap = fixedcolormap; + else + { + index = distance >> LIGHTZSHIFT; + + if (index >= MAXLIGHTZ ) + index = MAXLIGHTZ-1; + + ds_colormap = planezlight[index]; + } + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + // high or low detail + spanfunc (); +} + + +// +// R_ClearPlanes +// At begining of frame. +// +void R_ClearPlanes (void) +{ + int i; + angle_t angle; + + // opening / clipping determination + for (i=0 ; i>ANGLETOFINESHIFT; + + // scale will be unit scale at SCREENWIDTH/2 distance + basexscale = FixedDiv (finecosine[angle],centerxfrac); + baseyscale = -FixedDiv (finesine[angle],centerxfrac); +} + + + + +// +// R_FindPlane +// +visplane_t* +R_FindPlane +( fixed_t height, + int picnum, + int lightlevel ) +{ + visplane_t* check; + + if (picnum == skyflatnum) + { + height = 0; // all skys map together + lightlevel = 0; + } + + for (check=visplanes; checkheight + && picnum == check->picnum + && lightlevel == check->lightlevel) + { + break; + } + } + + + if (check < lastvisplane) + return check; + + if (lastvisplane - visplanes == MAXVISPLANES) + I_Error ("R_FindPlane: no more visplanes"); + + lastvisplane++; + + check->height = height; + check->picnum = picnum; + check->lightlevel = lightlevel; + check->minx = SCREENWIDTH; + check->maxx = -1; + + memset (check->top,0xff,sizeof(check->top)); + + return check; +} + + +// +// R_CheckPlane +// +visplane_t* +R_CheckPlane +( visplane_t* pl, + int start, + int stop ) +{ + int intrl; + int intrh; + int unionl; + int unionh; + int x; + + if (start < pl->minx) + { + intrl = pl->minx; + unionl = start; + } + else + { + unionl = pl->minx; + intrl = start; + } + + if (stop > pl->maxx) + { + intrh = pl->maxx; + unionh = stop; + } + else + { + unionh = pl->maxx; + intrh = stop; + } + + for (x=intrl ; x<= intrh ; x++) + if (pl->top[x] != 0xff) + break; + + if (x > intrh) + { + pl->minx = unionl; + pl->maxx = unionh; + + // use the same one + return pl; + } + + // make a new visplane + lastvisplane->height = pl->height; + lastvisplane->picnum = pl->picnum; + lastvisplane->lightlevel = pl->lightlevel; + + pl = lastvisplane++; + pl->minx = start; + pl->maxx = stop; + + memset (pl->top,0xff,sizeof(pl->top)); + + return pl; +} + + +// +// R_MakeSpans +// +void +R_MakeSpans +( int x, + int t1, + int b1, + int t2, + int b2 ) +{ + while (t1 < t2 && t1<=b1) + { + R_MapPlane (t1,spanstart[t1],x-1); + t1++; + } + while (b1 > b2 && b1>=t1) + { + R_MapPlane (b1,spanstart[b1],x-1); + b1--; + } + + while (t2 < t1 && t2<=b2) + { + spanstart[t2] = x; + t2++; + } + while (b2 > b1 && b2>=t2) + { + spanstart[b2] = x; + b2--; + } +} + + + +// +// R_DrawPlanes +// At the end of each frame. +// +void R_DrawPlanes (void) +{ + visplane_t* pl; + int light; + int x; + int stop; + int angle; + int lumpnum; + +#ifdef RANGECHECK + if (ds_p - drawsegs > MAXDRAWSEGS) + I_Error ("R_DrawPlanes: drawsegs overflow (%td)", + ds_p - drawsegs); + + if (lastvisplane - visplanes > MAXVISPLANES) + I_Error ("R_DrawPlanes: visplane overflow (%td)", + lastvisplane - visplanes); + + if (lastopening - openings > MAXOPENINGS) + I_Error ("R_DrawPlanes: opening overflow (%td)", + lastopening - openings); +#endif + + for (pl = visplanes ; pl < lastvisplane ; pl++) + { + if (pl->minx > pl->maxx) + continue; + + + // sky flat + if (pl->picnum == skyflatnum) + { + dc_iscale = pspriteiscale>>detailshift; + + // Sky is allways drawn full bright, + // i.e. colormaps[0] is used. + // Because of this hack, sky is not affected + // by INVUL inverse mapping. + dc_colormap = colormaps; + dc_texturemid = skytexturemid; + for (x=pl->minx ; x <= pl->maxx ; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + + if (dc_yl <= dc_yh) + { + angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; + dc_x = x; + dc_source = R_GetColumn(skytexture, angle); + colfunc (); + } + } + continue; + } + + // regular flat + lumpnum = firstflat + flattranslation[pl->picnum]; + ds_source = W_CacheLumpNum(lumpnum, PU_STATIC); + + planeheight = abs(pl->height-viewz); + light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (light >= LIGHTLEVELS) + light = LIGHTLEVELS-1; + + if (light < 0) + light = 0; + + planezlight = zlight[light]; + + pl->top[pl->maxx+1] = 0xff; + pl->top[pl->minx-1] = 0xff; + + stop = pl->maxx + 1; + + for (x=pl->minx ; x<= stop ; x++) + { + R_MakeSpans(x,pl->top[x-1], + pl->bottom[x-1], + pl->top[x], + pl->bottom[x]); + } + + W_ReleaseLumpNum(lumpnum); + } +} diff --git a/games/NXDoom/src/strife/r_plane.h b/games/NXDoom/src/strife/r_plane.h new file mode 100644 index 00000000000..57b50e5bc5e --- /dev/null +++ b/games/NXDoom/src/strife/r_plane.h @@ -0,0 +1,76 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh, visplane stuff (floor, ceilings). +// + + +#ifndef __R_PLANE__ +#define __R_PLANE__ + + +#include "r_data.h" + + + +// Visplane related. +extern short* lastopening; + + +typedef void (*planefunction_t) (int top, int bottom); + +extern planefunction_t floorfunc; +extern planefunction_t ceilingfunc_t; + +extern short floorclip[SCREENWIDTH]; +extern short ceilingclip[SCREENWIDTH]; + +extern fixed_t yslope[SCREENHEIGHT]; +extern fixed_t distscale[SCREENWIDTH]; + +void R_InitPlanes (void); +void R_ClearPlanes (void); + +void +R_MapPlane +( int y, + int x1, + int x2 ); + +void +R_MakeSpans +( int x, + int t1, + int b1, + int t2, + int b2 ); + +void R_DrawPlanes (void); + +visplane_t* +R_FindPlane +( fixed_t height, + int picnum, + int lightlevel ); + +visplane_t* +R_CheckPlane +( visplane_t* pl, + int start, + int stop ); + + + +#endif diff --git a/games/NXDoom/src/strife/r_segs.c b/games/NXDoom/src/strife/r_segs.c new file mode 100644 index 00000000000..179565035a2 --- /dev/null +++ b/games/NXDoom/src/strife/r_segs.c @@ -0,0 +1,754 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// All the clipping: columns, horizontal spans, sky columns. +// + + + + + + +#include +#include + +#include "i_system.h" + +#include "doomdef.h" +#include "doomstat.h" + +#include "r_local.h" +#include "r_sky.h" + + +// OPTIMIZE: closed two sided lines as single sided + +// True if any of the segs textures might be visible. +boolean segtextured; + +// False if the back side is the same plane. +boolean markfloor; +boolean markceiling; + +boolean maskedtexture; +int toptexture; +int bottomtexture; +int midtexture; + + +angle_t rw_normalangle; +// angle to line origin +int rw_angle1; + +// +// regular wall +// +int rw_x; +int rw_stopx; +angle_t rw_centerangle; +fixed_t rw_offset; +fixed_t rw_distance; +fixed_t rw_scale; +fixed_t rw_scalestep; +fixed_t rw_midtexturemid; +fixed_t rw_toptexturemid; +fixed_t rw_bottomtexturemid; + +int worldtop; +int worldbottom; +int worldhigh; +int worldlow; + +fixed_t pixhigh; +fixed_t pixlow; +fixed_t pixhighstep; +fixed_t pixlowstep; + +fixed_t topfrac; +fixed_t topstep; + +fixed_t bottomfrac; +fixed_t bottomstep; + + +lighttable_t** walllights; + +short* maskedtexturecol; + + + +// +// R_RenderMaskedSegRange +// +void +R_RenderMaskedSegRange +( drawseg_t* ds, + int x1, + int x2 ) +{ + unsigned index; + column_t* col; + int lightnum; + int texnum; + + // Calculate light table. + // Use different light tables + // for horizontal / vertical / diagonal. Diagonal? + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + curline = ds->curline; + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = texturetranslation[curline->sidedef->midtexture]; + + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS-1]; + else + walllights = scalelight[lightnum]; + + maskedtexturecol = ds->maskedtexturecol; + + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + + // find positioning + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + { + dc_texturemid = frontsector->floorheight > backsector->floorheight + ? frontsector->floorheight : backsector->floorheight; + dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; + } + else + { + dc_texturemid =frontsector->ceilingheightceilingheight + ? frontsector->ceilingheight : backsector->ceilingheight; + dc_texturemid = dc_texturemid - viewz; + } + dc_texturemid += curline->sidedef->rowoffset; + + if (fixedcolormap) + dc_colormap = fixedcolormap; + + // villsa [STRIFE] render as transparent (25% or 75%?) + if(curline->linedef->flags & ML_TRANSPARENT1) + colfunc = fuzzcolfunc; + + // villsa [STRIFE] render as transparent (25% or 75%?) + if(curline->linedef->flags & ML_TRANSPARENT2) + colfunc = R_DrawMVisTLColumn; + + // draw the columns + for (dc_x = x1 ; dc_x <= x2 ; dc_x++) + { + // calculate lighting + if (maskedtexturecol[dc_x] != SHRT_MAX) + { + if (!fixedcolormap) + { + index = spryscale>>LIGHTSCALESHIFT; + + if (index >= MAXLIGHTSCALE ) + index = MAXLIGHTSCALE-1; + + dc_colormap = walllights[index]; + } + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)( + (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3); + + // villsa [STRIFE] added 0 argument + R_DrawMaskedColumn (col, 0); + maskedtexturecol[dc_x] = SHRT_MAX; + } + spryscale += rw_scalestep; + } + + colfunc = basecolfunc; // villsa [STRIFE] reset draw routines + +} + + + + +// +// R_RenderSegLoop +// Draws zero, one, or two textures (and possibly a masked +// texture) for walls. +// Can draw or mark the starting pixel of floor and ceiling +// textures. +// CALLED: CORE LOOPING ROUTINE. +// +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1<>HEIGHTBITS; + + // no space above wall? + if (yl < ceilingclip[rw_x]+1) + yl = ceilingclip[rw_x]+1; + + if (markceiling) + { + top = ceilingclip[rw_x]+1; + bottom = yl-1; + + if (bottom >= floorclip[rw_x]) + bottom = floorclip[rw_x]-1; + + if (top <= bottom) + { + ceilingplane->top[rw_x] = top; + ceilingplane->bottom[rw_x] = bottom; + } + } + + yh = bottomfrac>>HEIGHTBITS; + + if (yh >= floorclip[rw_x]) + yh = floorclip[rw_x]-1; + + if (markfloor) + { + top = yh+1; + bottom = floorclip[rw_x]-1; + if (top <= ceilingclip[rw_x]) + top = ceilingclip[rw_x]+1; + if (top <= bottom) + { + floorplane->top[rw_x] = top; + floorplane->bottom[rw_x] = bottom; + } + } + + // texturecolumn and lighting are independent of wall tiers + if (segtextured) + { + // calculate texture offset + angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; + texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance); + texturecolumn >>= FRACBITS; + // calculate lighting + index = rw_scale>>LIGHTSCALESHIFT; + + if (index >= MAXLIGHTSCALE ) + index = MAXLIGHTSCALE-1; + + dc_colormap = walllights[index]; + dc_x = rw_x; + dc_iscale = 0xffffffffu / (unsigned)rw_scale; + } + else + { + // purely to shut up the compiler + + texturecolumn = 0; + } + + // draw the wall tiers + if (midtexture) + { + // single sided line + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_source = R_GetColumn(midtexture,texturecolumn); + colfunc (); + ceilingclip[rw_x] = viewheight; + floorclip[rw_x] = -1; + } + else + { + // two sided line + if (toptexture) + { + // top wall + mid = pixhigh>>HEIGHTBITS; + pixhigh += pixhighstep; + + if (mid >= floorclip[rw_x]) + mid = floorclip[rw_x]-1; + + if (mid >= yl) + { + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_source = R_GetColumn(toptexture,texturecolumn); + colfunc (); + ceilingclip[rw_x] = mid; + } + else + ceilingclip[rw_x] = yl-1; + } + else + { + // no top wall + if (markceiling) + ceilingclip[rw_x] = yl-1; + } + + if (bottomtexture) + { + // bottom wall + mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; + pixlow += pixlowstep; + + // no space above wall? + if (mid <= ceilingclip[rw_x]) + mid = ceilingclip[rw_x]+1; + + if (mid <= yh) + { + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_source = R_GetColumn(bottomtexture, + texturecolumn); + colfunc (); + floorclip[rw_x] = mid; + } + else + floorclip[rw_x] = yh+1; + } + else + { + // no bottom wall + if (markfloor) + floorclip[rw_x] = yh+1; + } + + if (maskedtexture) + { + // save texturecol + // for backdrawing of masked mid texture + maskedtexturecol[rw_x] = texturecolumn; + } + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; + } +} + + + + +// +// R_StoreWallRange +// A wall segment will be drawn +// between start and stop pixels (inclusive). +// +void +R_StoreWallRange +( int start, + int stop ) +{ + fixed_t hyp; + fixed_t sineval; + angle_t distangle, offsetangle; + fixed_t vtop; + int lightnum; + + // don't overflow and crash + if (ds_p == &drawsegs[MAXDRAWSEGS]) + return; + +#ifdef RANGECHECK + if (start >=viewwidth || start > stop) + I_Error ("Bad R_RenderWallRange: %i to %i", start , stop); +#endif + + sidedef = curline->sidedef; + linedef = curline->linedef; + + // mark the segment as visible for auto map + linedef->flags |= ML_MAPPED; + + // calculate rw_distance for scale calculation + rw_normalangle = curline->angle + ANG90; + offsetangle = abs((int) rw_normalangle - (int) rw_angle1); + + if (offsetangle > ANG90) + offsetangle = ANG90; + + distangle = ANG90 - offsetangle; + hyp = R_PointToDist (curline->v1->x, curline->v1->y); + sineval = finesine[distangle>>ANGLETOFINESHIFT]; + rw_distance = FixedMul (hyp, sineval); + + + ds_p->x1 = rw_x = start; + ds_p->x2 = stop; + ds_p->curline = curline; + rw_stopx = stop+1; + + // calculate scale at both ends and step + ds_p->scale1 = rw_scale = + R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]); + + if (stop > start ) + { + ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]); + ds_p->scalestep = rw_scalestep = + (ds_p->scale2 - rw_scale) / (stop-start); + } + else + { + // UNUSED: try to fix the stretched line bug +#if 0 + if (rw_distance < FRACUNIT/2) + { + fixed_t trx,try; + fixed_t gxt,gyt; + + trx = curline->v1->x - viewx; + try = curline->v1->y - viewy; + + gxt = FixedMul(trx,viewcos); + gyt = -FixedMul(try,viewsin); + ds_p->scale1 = FixedDiv(projection, gxt-gyt)<scale2 = ds_p->scale1; + } + + // calculate texture boundaries + // and decide if floor / ceiling marks are needed + worldtop = frontsector->ceilingheight - viewz; + worldbottom = frontsector->floorheight - viewz; + + midtexture = toptexture = bottomtexture = maskedtexture = 0; + ds_p->maskedtexturecol = NULL; + + if (!backsector) + { + // single sided line + midtexture = texturetranslation[sidedef->midtexture]; + // a single sided line is terminal, so it must mark ends + markfloor = markceiling = true; + if (linedef->flags & ML_DONTPEGBOTTOM) + { + vtop = frontsector->floorheight + + textureheight[sidedef->midtexture]; + // bottom of texture at bottom + rw_midtexturemid = vtop - viewz; + } + else + { + // top of texture at top + rw_midtexturemid = worldtop; + } + rw_midtexturemid += sidedef->rowoffset; + + ds_p->silhouette = SIL_BOTH; + ds_p->sprtopclip = screenheightarray; + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->tsilheight = INT_MIN; + } + else + { + // two sided line + ds_p->sprtopclip = ds_p->sprbottomclip = NULL; + ds_p->silhouette = 0; + + if (frontsector->floorheight > backsector->floorheight) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = frontsector->floorheight; + } + else if (backsector->floorheight > viewz) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + // ds_p->sprbottomclip = negonearray; + } + + if (frontsector->ceilingheight < backsector->ceilingheight) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = frontsector->ceilingheight; + } + else if (backsector->ceilingheight < viewz) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + // ds_p->sprtopclip = screenheightarray; + } + + if (backsector->ceilingheight <= frontsector->floorheight) + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } + + if (backsector->floorheight >= frontsector->ceilingheight) + { + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT_MIN; + ds_p->silhouette |= SIL_TOP; + } + + worldhigh = backsector->ceilingheight - viewz; + worldlow = backsector->floorheight - viewz; + + // hack to allow height changes in outdoor areas + if (frontsector->ceilingpic == skyflatnum + && backsector->ceilingpic == skyflatnum) + { + worldtop = worldhigh; + } + + + if (worldlow != worldbottom + || backsector->floorpic != frontsector->floorpic + || backsector->lightlevel != frontsector->lightlevel) + { + markfloor = true; + } + else + { + // same plane on both sides + markfloor = false; + } + + + if (worldhigh != worldtop + || backsector->ceilingpic != frontsector->ceilingpic + || backsector->lightlevel != frontsector->lightlevel) + { + markceiling = true; + } + else + { + // same plane on both sides + markceiling = false; + } + + if (backsector->ceilingheight <= frontsector->floorheight + || backsector->floorheight >= frontsector->ceilingheight) + { + // closed door + markceiling = markfloor = true; + } + + + if (worldhigh < worldtop) + { + // top texture + toptexture = texturetranslation[sidedef->toptexture]; + if (linedef->flags & ML_DONTPEGTOP) + { + // top of texture at top + rw_toptexturemid = worldtop; + } + else + { + vtop = + backsector->ceilingheight + + textureheight[sidedef->toptexture]; + + // bottom of texture + rw_toptexturemid = vtop - viewz; + } + } + if (worldlow > worldbottom) + { + // bottom texture + bottomtexture = texturetranslation[sidedef->bottomtexture]; + + if (linedef->flags & ML_DONTPEGBOTTOM ) + { + // bottom of texture at bottom + // top of texture at top + rw_bottomtexturemid = worldtop; + } + else // top of texture at top + rw_bottomtexturemid = worldlow; + } + rw_toptexturemid += sidedef->rowoffset; + rw_bottomtexturemid += sidedef->rowoffset; + + // allocate space for masked texture tables + if (sidedef->midtexture) + { + // masked midtexture + maskedtexture = true; + ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; + } + } + + // calculate rw_offset (only needed for textured lines) + segtextured = midtexture | toptexture | bottomtexture | maskedtexture; + + if (segtextured) + { + offsetangle = rw_normalangle-rw_angle1; + + if (offsetangle > ANG180) + offsetangle = 0 - offsetangle; + + if (offsetangle > ANG90) + offsetangle = ANG90; + + sineval = finesine[offsetangle >>ANGLETOFINESHIFT]; + rw_offset = FixedMul (hyp, sineval); + + if (rw_normalangle-rw_angle1 < ANG180) + rw_offset = -rw_offset; + + rw_offset += sidedef->textureoffset + curline->offset; + rw_centerangle = ANG90 + viewangle - rw_normalangle; + + // calculate light table + // use different light tables + // for horizontal / vertical / diagonal + // OPTIMIZE: get rid of LIGHTSEGSHIFT globally + if (!fixedcolormap) + { + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS-1]; + else + walllights = scalelight[lightnum]; + } + } + + // if a floor / ceiling plane is on the wrong side + // of the view plane, it is definitely invisible + // and doesn't need to be marked. + + + if (frontsector->floorheight >= viewz) + { + // above view plane + markfloor = false; + } + + if (frontsector->ceilingheight <= viewz + && frontsector->ceilingpic != skyflatnum) + { + // below view plane + markceiling = false; + } + + + // calculate incremental stepping values for texture edges + worldtop >>= 4; + worldbottom >>= 4; + + topstep = -FixedMul (rw_scalestep, worldtop); + topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); + + bottomstep = -FixedMul (rw_scalestep,worldbottom); + bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); + + if (backsector) + { + worldhigh >>= 4; + worldlow >>= 4; + + if (worldhigh < worldtop) + { + pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); + pixhighstep = -FixedMul (rw_scalestep,worldhigh); + } + + if (worldlow > worldbottom) + { + pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); + pixlowstep = -FixedMul (rw_scalestep,worldlow); + } + } + + // render it + if (markceiling) + ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); + + if (markfloor) + floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); + + R_RenderSegLoop (); + + + // save sprite clipping info + if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) + && !ds_p->sprtopclip) + { + memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) + && !ds_p->sprbottomclip) + { + memcpy (lastopening, floorclip+start, 2*(rw_stopx-start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if (maskedtexture && !(ds_p->silhouette&SIL_TOP)) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + } + if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM)) + { + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + } + ds_p++; +} + diff --git a/games/NXDoom/src/strife/r_segs.h b/games/NXDoom/src/strife/r_segs.h new file mode 100644 index 00000000000..8e6a768f454 --- /dev/null +++ b/games/NXDoom/src/strife/r_segs.h @@ -0,0 +1,34 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh module, drawing LineSegs from BSP. +// + + +#ifndef __R_SEGS__ +#define __R_SEGS__ + + +extern lighttable_t **walllights; + + +void +R_RenderMaskedSegRange +( drawseg_t* ds, + int x1, + int x2 ); + + +#endif diff --git a/games/NXDoom/src/strife/r_sky.c b/games/NXDoom/src/strife/r_sky.c new file mode 100644 index 00000000000..007740a8a1c --- /dev/null +++ b/games/NXDoom/src/strife/r_sky.c @@ -0,0 +1,54 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Sky rendering. The DOOM sky is a texture map like any +// wall, wrapping around. A 1024 columns equal 360 degrees. +// The default sky map is 256 columns and repeats 4 times +// on a 320 screen? +// +// + + + +// Needed for FRACUNIT. +#include "m_fixed.h" + +// Needed for Flat retrieval. +#include "r_data.h" + + +#include "r_sky.h" + +// +// sky mapping +// +int skyflatnum; +int skytexture; +int skytexturemid; + + + +// +// R_InitSkyMap +// Called whenever the view size changes. +// +void R_InitSkyMap (void) +{ + // haleyjd 10/03/10: [STRIFE] Sky is set here, not in G_DoLoadLevel. + // Also skytexturemid changed from 100 to 199. + skyflatnum = R_FlatNumForName ( SKYFLATNAME ); + skytexturemid = 199*FRACUNIT; +} + diff --git a/games/NXDoom/src/strife/r_sky.h b/games/NXDoom/src/strife/r_sky.h new file mode 100644 index 00000000000..fbcfa1ae9bd --- /dev/null +++ b/games/NXDoom/src/strife/r_sky.h @@ -0,0 +1,37 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Sky rendering. +// + + +#ifndef __R_SKY__ +#define __R_SKY__ + + + +// SKY, store the number for name. +#define SKYFLATNAME "F_SKY001" // villsa [STRIFE] + +// The sky map is 256*128*4 maps. +#define ANGLETOSKYSHIFT 22 + +extern int skytexture; +extern int skytexturemid; + +// Called whenever the view size changes. +void R_InitSkyMap (void); + +#endif diff --git a/games/NXDoom/src/strife/r_state.h b/games/NXDoom/src/strife/r_state.h new file mode 100644 index 00000000000..2a60e2fe8e1 --- /dev/null +++ b/games/NXDoom/src/strife/r_state.h @@ -0,0 +1,127 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh/render internal state variables (global). +// + + +#ifndef __R_STATE__ +#define __R_STATE__ + +// Need data structure definitions. +#include "d_player.h" +#include "r_data.h" + + + + + + +// +// Refresh internal data structures, +// for rendering. +// + +// needed for texture pegging +extern fixed_t* textureheight; + +// needed for pre rendering (fracs) +extern fixed_t* spritewidth; + +extern fixed_t* spriteoffset; +extern fixed_t* spritetopoffset; + +extern lighttable_t* colormaps; + +extern int viewwidth; +extern int scaledviewwidth; +extern int viewheight; + +extern int firstflat; + +// for global animation +extern int* flattranslation; +extern int* texturetranslation; + + +// Sprite.... +extern int firstspritelump; +extern int lastspritelump; +extern int numspritelumps; + + + +// +// Lookup tables for map data. +// +extern int numsprites; +extern spritedef_t* sprites; + +extern int numvertexes; +extern vertex_t* vertexes; + +extern int numsegs; +extern seg_t* segs; + +extern int numsectors; +extern sector_t* sectors; + +extern int numsubsectors; +extern subsector_t* subsectors; + +extern int numnodes; +extern node_t* nodes; + +extern int numlines; +extern line_t* lines; + +extern int numsides; +extern side_t* sides; + + +// +// POV data. +// +extern fixed_t viewx; +extern fixed_t viewy; +extern fixed_t viewz; + +extern angle_t viewangle; +extern player_t* viewplayer; + + +// ? +extern angle_t clipangle; + +extern int viewangletox[FINEANGLES/2]; +extern angle_t xtoviewangle[SCREENWIDTH+1]; +//extern fixed_t finetangent[FINEANGLES/2]; + +extern fixed_t rw_distance; +extern angle_t rw_normalangle; + + + +// angle to line origin +extern int rw_angle1; + +// Segs count? +extern int sscount; + +extern visplane_t* floorplane; +extern visplane_t* ceilingplane; + + +#endif diff --git a/games/NXDoom/src/strife/r_things.c b/games/NXDoom/src/strife/r_things.c new file mode 100644 index 00000000000..e49f7bc104c --- /dev/null +++ b/games/NXDoom/src/strife/r_things.c @@ -0,0 +1,1067 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh of things, i.e. objects represented by sprites. +// + + + + +#include +#include + + +#include "deh_main.h" +#include "doomdef.h" + +#include "i_swap.h" +#include "i_system.h" +#include "z_zone.h" +#include "w_wad.h" + +#include "r_local.h" + +#include "doomstat.h" + +// haleyjd +#include "p_local.h" + + + +#define MINZ (FRACUNIT*4) +#define BASEYCENTER 100 + +//void R_DrawColumn (void); +//void R_DrawFuzzColumn (void); + + + +typedef struct +{ + int x1; + int x2; + + int column; + int topclip; + int bottomclip; + +} maskdraw_t; + + + +// +// Sprite rotation 0 is facing the viewer, +// rotation 1 is one angle turn CLOCKWISE around the axis. +// This is not the same as the angle, +// which increases counter clockwise (protractor). +// There was a lot of stuff grabbed wrong, so I changed it... +// +fixed_t pspritescale; +fixed_t pspriteiscale; + +lighttable_t** spritelights; + +// constant arrays +// used for psprite clipping and initializing clipping +short negonearray[SCREENWIDTH]; +short screenheightarray[SCREENWIDTH]; + + +// +// INITIALIZATION FUNCTIONS +// + +// variables used to look up +// and range check thing_t sprites patches +spritedef_t* sprites; +int numsprites; + +spriteframe_t sprtemp[29]; +int maxframe; +const char *spritename; + + + + +// +// R_InstallSpriteLump +// Local function for R_InitSprites. +// +void +R_InstallSpriteLump +( int lump, + unsigned frame, + unsigned rotation, + boolean flipped ) +{ + int r; + + if (frame >= 29 || rotation > 8) + I_Error("R_InstallSpriteLump: " + "Bad frame characters in lump %i", lump); + + if ((int)frame > maxframe) + maxframe = frame; + + if (rotation == 0) + { + // the lump should be used for all rotations + if (sprtemp[frame].rotate == false) + I_Error ("R_InitSprites: Sprite %s frame %c has " + "multip rot=0 lump", spritename, 'A'+frame); + + if (sprtemp[frame].rotate == true) + I_Error ("R_InitSprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", spritename, 'A'+frame); + + sprtemp[frame].rotate = false; + for (r=0 ; r<8 ; r++) + { + sprtemp[frame].lump[r] = lump - firstspritelump; + sprtemp[frame].flip[r] = (byte)flipped; + } + return; + } + + // the lump is only used for one rotation + if (sprtemp[frame].rotate == false) + I_Error ("R_InitSprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", spritename, 'A'+frame); + + sprtemp[frame].rotate = true; + + // make 0 based + rotation--; + if (sprtemp[frame].lump[rotation] != -1) + I_Error ("R_InitSprites: Sprite %s : %c : %c " + "has two lumps mapped to it", + spritename, 'A'+frame, '1'+rotation); + + sprtemp[frame].lump[rotation] = lump - firstspritelump; + sprtemp[frame].flip[rotation] = (byte)flipped; +} + + + + +// +// R_InitSpriteDefs +// Pass a null terminated list of sprite names +// (4 chars exactly) to be used. +// Builds the sprite rotation matrixes to account +// for horizontally flipped sprites. +// Will report an error if the lumps are inconsistant. +// Only called at startup. +// +// Sprite lump names are 4 characters for the actor, +// a letter for the frame, and a number for the rotation. +// A sprite that is flippable will have an additional +// letter/number appended. +// The rotation character can be 0 to signify no rotations. +// +void R_InitSpriteDefs (const char** namelist) +{ + const char **check; + int i; + int l; + int frame; + int rotation; + int start; + int end; + int patched; + + // count the number of sprite names + check = namelist; + while (*check != NULL) + check++; + + numsprites = check-namelist; + + if (!numsprites) + return; + + sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); + + start = firstspritelump-1; + end = lastspritelump+1; + + // scan all the lump names for each of the names, + // noting the highest frame letter. + // Just compare 4 characters as ints + for (i=0 ; iname, spritename, 4)) + { + frame = lumpinfo[l]->name[4] - 'A'; + rotation = lumpinfo[l]->name[5] - '0'; + + if (modifiedgame) + patched = W_GetNumForName (lumpinfo[l]->name); + else + patched = l; + + R_InstallSpriteLump (patched, frame, rotation, false); + + if (lumpinfo[l]->name[6]) + { + frame = lumpinfo[l]->name[6] - 'A'; + rotation = lumpinfo[l]->name[7] - '0'; + R_InstallSpriteLump (l, frame, rotation, true); + } + } + } + + // check the frames that were found for completeness + if (maxframe == -1) + { + sprites[i].numframes = 0; + continue; + } + + maxframe++; + + for (frame = 0 ; frame < maxframe ; frame++) + { + switch ((int)sprtemp[frame].rotate) + { + case -1: + // no rotations were found for that frame at all + I_Error ("R_InitSprites: No patches found " + "for %s frame %c", spritename, frame+'A'); + break; + + case 0: + // only the first rotation is needed + break; + + case 1: + // must have all 8 frames + for (rotation=0 ; rotation<8 ; rotation++) + if (sprtemp[frame].lump[rotation] == -1) + I_Error ("R_InitSprites: Sprite %s frame %c " + "is missing rotations", + spritename, frame+'A'); + break; + } + } + + // allocate space for the frames present and copy sprtemp to it + sprites[i].numframes = maxframe; + sprites[i].spriteframes = + Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); + } + +} + + + + +// +// GAME FUNCTIONS +// +vissprite_t vissprites[MAXVISSPRITES]; +vissprite_t* vissprite_p; +int newvissprite; +int sprbotscreen; // villsa [STRIFE] + + + +// +// R_InitSprites +// Called at program start. +// +void R_InitSprites (const char** namelist) +{ + int i; + + for (i=0 ; itopdelta != 0xff ; ) + { + // calculate unclipped screen coordinates + // for post + topscreen = sprtopscreen + spryscale*column->topdelta; + bottomscreen = topscreen + spryscale*column->length; + + dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x]-1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x]+1; + + // villsa [STRIFE] checks for clipping + if(baseclip) + { + if(dc_yh > baseclip) + dc_yh = baseclip; + } + + if (dc_yl <= dc_yh) + { + dc_source = (byte *)column + 3; + dc_texturemid = basetexturemid - (column->topdelta<topdelta; + + // Drawn by either R_DrawColumn + // or (SHADOW) R_DrawFuzzColumn. + colfunc (); + } + column = (column_t *)( (byte *)column + column->length + 4); + } + + dc_texturemid = basetexturemid; +} + + + +// +// R_DrawVisSprite +// mfloorclip and mceilingclip should also be set. +// +void +R_DrawVisSprite +( vissprite_t* vis, + int x1, + int x2 ) +{ + column_t* column; + int texturecolumn; + fixed_t frac; + patch_t* patch; + int clip; // villsa [STRIFE] + int translation; // villsa [STRIFE] + + patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); + + dc_colormap = vis->colormap; + + // villsa [STRIFE] + // haleyjd 09/06/10: updated MF_TRANSLATION for Strife + translation = vis->mobjflags & MF_TRANSLATION; + + // villsa [STRIFE] unused + /*if (!dc_colormap) + { + // NULL colormap = shadow draw + colfunc = fuzzcolfunc; + }*/ + + // villsa [STRIFE] Handle the two types of translucency + if(vis->mobjflags & MF_SHADOW) + { + if(!translation) + { + if(vis->mobjflags & MF_MVIS) + colfunc = R_DrawMVisTLColumn; + else + colfunc = fuzzcolfunc; + } + else + { + colfunc = R_DrawTRTLColumn; + dc_translation = translationtables - 256 + (translation >> (MF_TRANSSHIFT - 8)); + } + } + else if(vis->mobjflags & MF_MVIS) + { + // haleyjd 20141215: [STRIFE] Objects which are *only* MF_MVIS (players + // using double Shadow Armors, in particular) are totally invisible. + // Upstreamed after discovered in SVE. Note this causes a + // vanilla-accurate glitch with Shadow Acolytes - if they die while + // MF_MVIS is set, A_Fall fails to remove it and their corpse will + // completely disappear (that's also fixed in SVE, but not here). + return; + } + else if(translation) // villsa [STRIFE] new translation tables + { + colfunc = transcolfunc; + dc_translation = translationtables - 256 + (translation >> (MF_TRANSSHIFT - 8)); + } + + dc_iscale = abs(vis->xiscale)>>detailshift; + dc_texturemid = vis->texturemid; + frac = vis->startfrac; + spryscale = vis->scale; + sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); + + // villsa [STRIFE] clip sprite's feet if needed + if(vis->mobjflags & MF_FEETCLIPPED) + { + sprbotscreen = sprtopscreen + FixedMul(spryscale, SHORT(patch->height) << FRACBITS); + clip = (sprbotscreen - FixedMul(10*FRACUNIT, spryscale)) >> FRACBITS; + } + else + clip = 0; + + for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) + { + texturecolumn = frac>>FRACBITS; +#ifdef RANGECHECK + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error ("R_DrawSpriteRange: bad texturecolumn"); +#endif + column = (column_t *) ((byte *)patch + + LONG(patch->columnofs[texturecolumn])); + R_DrawMaskedColumn (column, clip); // villsa [STRIFE] clip argument + } + + colfunc = basecolfunc; +} + + + +// +// R_ProjectSprite +// Generates a vissprite for a thing +// if it might be visible. +// +void R_ProjectSprite (mobj_t* thing) +{ + fixed_t tr_x; + fixed_t tr_y; + + fixed_t gxt; + fixed_t gyt; + + fixed_t tx; + fixed_t tz; + + fixed_t xscale; + + int x1; + int x2; + + spritedef_t* sprdef; + spriteframe_t* sprframe; + int lump; + + unsigned rot; + boolean flip; + + int index; + + vissprite_t* vis; + + angle_t ang; + fixed_t iscale; + + // transform the origin point + tr_x = thing->x - viewx; + tr_y = thing->y - viewy; + + gxt = FixedMul(tr_x,viewcos); + gyt = -FixedMul(tr_y,viewsin); + + tz = gxt-gyt; + + // thing is behind view plane? + if (tz < MINZ) + return; + + xscale = FixedDiv(projection, tz); + + gxt = -FixedMul(tr_x,viewsin); + gyt = FixedMul(tr_y,viewcos); + tx = -(gyt+gxt); + + // too far off the side? + if (abs(tx)>(tz<<2)) + return; + + // decide which patch to use for sprite relative to player +#ifdef RANGECHECK + if ((unsigned int) thing->sprite >= (unsigned int) numsprites) + I_Error ("R_ProjectSprite: invalid sprite number %i ", + thing->sprite); +#endif + sprdef = &sprites[thing->sprite]; +#ifdef RANGECHECK + if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) + I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", + thing->sprite, thing->frame); +#endif + sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; + + if (sprframe->rotate) + { + // choose a different rotation based on player view + ang = R_PointToAngle (thing->x, thing->y); + rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; + lump = sprframe->lump[rot]; + flip = (boolean)sprframe->flip[rot]; + } + else + { + // use single rotation for all views + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + } + + // calculate edges of the shape + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; + + // off the right side? + if (x1 > viewwidth) + return; + + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; + + // off the left side + if (x2 < 0) + return; + + // store information in a vissprite + vis = R_NewVisSprite (); + vis->mobjflags = thing->flags; + vis->scale = xscale<gx = thing->x; + vis->gy = thing->y; + vis->gz = thing->z; + + // villsa [STRIFE] + if(thing->flags & MF_FEETCLIPPED) + vis->gz -= (10*FRACUNIT); + + // villsa [STRIFE] + vis->gzt = vis->gz + spritetopoffset[lump]; + + vis->texturemid = vis->gzt - viewz; + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + iscale = FixedDiv (FRACUNIT, xscale); + + if (flip) + { + vis->startfrac = spritewidth[lump]-1; + vis->xiscale = -iscale; + } + else + { + vis->startfrac = 0; + vis->xiscale = iscale; + } + + if (vis->x1 > x1) + vis->startfrac += vis->xiscale*(vis->x1-x1); + vis->patch = lump; + + // get light level + // villsa [STRIFE] unused + /*if (thing->flags & MF_SHADOW) + { + // shadow draw + vis->colormap = NULL; + } + else */if (fixedcolormap) + { + // fixed map + vis->colormap = fixedcolormap; + } + else if (thing->frame & FF_FULLBRIGHT) + { + // full bright + vis->colormap = colormaps; + } + + else + { + // diminished light + index = xscale>>(LIGHTSCALESHIFT-detailshift); + + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE-1; + + vis->colormap = spritelights[index]; + } +} + + + + +// +// R_AddSprites +// During BSP traversal, this adds sprites by sector. +// +void R_AddSprites (sector_t* sec) +{ + mobj_t* thing; + int lightnum; + + // BSP is traversed by subsector. + // A sector might have been split into several + // subsectors during BSP building. + // Thus we check whether its already added. + if (sec->validcount == validcount) + return; + + // Well, now it will be done. + sec->validcount = validcount; + + lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS-1]; + else + spritelights = scalelight[lightnum]; + + // Handle all things in sector. + for (thing = sec->thinglist ; thing ; thing = thing->snext) + R_ProjectSprite (thing); +} + + +// +// R_DrawPSprite +// +void R_DrawPSprite (pspdef_t* psp) +{ + fixed_t tx; + int x1; + int x2; + spritedef_t* sprdef; + spriteframe_t* sprframe; + int lump; + boolean flip; + vissprite_t* vis; + vissprite_t avis; + + // decide which patch to use +#ifdef RANGECHECK + if ( (unsigned)psp->state->sprite >= (unsigned int) numsprites) + I_Error ("R_ProjectSprite: invalid sprite number %i ", + psp->state->sprite); +#endif + sprdef = &sprites[psp->state->sprite]; +#ifdef RANGECHECK + if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", + psp->state->sprite, psp->state->frame); +#endif + sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; + + lump = sprframe->lump[0]; + // [STRIFE] haleyjd 20110629: -flip replaces this. + //flip = (boolean)sprframe->flip[0]; + flip = flipparm; + + // calculate edges of the shape + tx = psp->sx-160*FRACUNIT; + + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; + + // off the right side + if (x1 > viewwidth) + return; + + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; + + // off the left side + if (x2 < 0) + return; + + // store information in a vissprite + vis = &avis; + vis->mobjflags = 0; + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; + vis->scale = pspritescale<xiscale = -pspriteiscale; + vis->startfrac = spritewidth[lump]-1; + } + else + { + vis->xiscale = pspriteiscale; + vis->startfrac = 0; + } + + // villsa [STRIFE] calculate y offset with view pitch + vis->texturemid = ((BASEYCENTER<sy-spritetopoffset[lump]) + + FixedMul(vis->xiscale, (centery-viewheight/2)<x1 > x1) + vis->startfrac += vis->xiscale*(vis->x1-x1); + + vis->patch = lump; + + if (viewplayer->powers[pw_invisibility] > 4*32 + || (viewplayer->powers[pw_invisibility] & 8)) + { + // shadow draw + vis->colormap = spritelights[MAXLIGHTSCALE-1]; + vis->mobjflags |= MF_SHADOW; + } + else if(viewplayer->powers[pw_invisibility] & 4) + { + vis->mobjflags |= (MF_SHADOW|MF_MVIS); + } + + // When not MVIS, or if SHADOW, behave normally: + if(!(viewplayer->mo->flags & MF_MVIS) || (viewplayer->mo->flags & MF_SHADOW)) + { + if (fixedcolormap) + { + // fixed color + vis->colormap = fixedcolormap; + } + else if (psp->state->frame & FF_FULLBRIGHT) + { + // full bright + vis->colormap = colormaps; + } + else + { + // local light + vis->colormap = spritelights[MAXLIGHTSCALE-1]; + } + } + else + { + // When MVIS, use invulnerability colormap + vis->colormap = colormaps + INVERSECOLORMAP * 256 * sizeof(lighttable_t); + } + + R_DrawVisSprite (vis, vis->x1, vis->x2); +} + + + +// +// R_DrawPlayerSprites +// +void R_DrawPlayerSprites (void) +{ + int i; + int lightnum; + pspdef_t* psp; + + // get light level + lightnum = + (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + +extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS-1]; + else + spritelights = scalelight[lightnum]; + + // clip to screen bounds + mfloorclip = screenheightarray; + mceilingclip = negonearray; + + // add all active psprites + for (i=0, psp=viewplayer->psprites; + istate) + R_DrawPSprite (psp); + } +} + + + + +// +// R_SortVisSprites +// +vissprite_t vsprsortedhead; + + +void R_SortVisSprites (void) +{ + int i; + int count; + vissprite_t* ds; + vissprite_t* best; + static vissprite_t unsorted; + fixed_t bestscale; + + count = vissprite_p - vissprites; + + unsorted.next = unsorted.prev = &unsorted; + + if (!count) + return; + + for (ds=vissprites ; dsnext = ds+1; + ds->prev = ds-1; + } + + vissprites[0].prev = &unsorted; + unsorted.next = &vissprites[0]; + (vissprite_p-1)->next = &unsorted; + unsorted.prev = vissprite_p-1; + + // pull the vissprites out by scale + + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i=0 ; inext) + { + if (ds->scale < bestscale) + { + bestscale = ds->scale; + best = ds; + } + } + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; + } +} + + + +// +// R_DrawSprite +// +void R_DrawSprite (vissprite_t* spr) +{ + drawseg_t* ds; + short clipbot[SCREENWIDTH]; + short cliptop[SCREENWIDTH]; + int x; + int r1; + int r2; + fixed_t scale; + fixed_t lowscale; + int silhouette; + + for (x = spr->x1 ; x<=spr->x2 ; x++) + clipbot[x] = cliptop[x] = -2; + + // Scan drawsegs from end to start for obscuring segs. + // The first drawseg that has a greater scale + // is the clip seg. + for (ds=ds_p-1 ; ds >= drawsegs ; ds--) + { + // determine if the drawseg obscures the sprite + if (ds->x1 > spr->x2 + || ds->x2 < spr->x1 + || (!ds->silhouette + && !ds->maskedtexturecol) ) + { + // does not cover sprite + continue; + } + + r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; + r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->scale + || ( lowscale < spr->scale + && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) + { + // masked mid texture? + if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, r1, r2); + // seg is behind sprite + continue; + } + + + // clip this piece of the sprite + silhouette = ds->silhouette; + + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == 1) + { + // bottom sil + for (x=r1 ; x<=r2 ; x++) + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + } + else if (silhouette == 2) + { + // top sil + for (x=r1 ; x<=r2 ; x++) + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == 3) + { + // both + for (x=r1 ; x<=r2 ; x++) + { + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + } + + } + + // all clipping has been performed, so draw the sprite + + // check for unclipped columns + for (x = spr->x1 ; x<=spr->x2 ; x++) + { + if (clipbot[x] == -2) + clipbot[x] = viewheight; + + if (cliptop[x] == -2) + cliptop[x] = -1; + } + + mfloorclip = clipbot; + mceilingclip = cliptop; + R_DrawVisSprite (spr, spr->x1, spr->x2); +} + + + + +// +// R_DrawMasked +// +void R_DrawMasked (void) +{ + vissprite_t* spr; + drawseg_t* ds; + + R_SortVisSprites (); + + if (vissprite_p > vissprites) + { + // draw all vissprites back to front + for (spr = vsprsortedhead.next ; + spr != &vsprsortedhead ; + spr=spr->next) + { + + R_DrawSprite (spr); + } + } + + // render any remaining masked mid textures + for (ds=ds_p-1 ; ds >= drawsegs ; ds--) + if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, ds->x1, ds->x2); + + // draw the psprites on top of everything + // but does not draw on side views + if (!viewangleoffset) + R_DrawPlayerSprites (); +} + + + diff --git a/games/NXDoom/src/strife/r_things.h b/games/NXDoom/src/strife/r_things.h new file mode 100644 index 00000000000..edb14a54d39 --- /dev/null +++ b/games/NXDoom/src/strife/r_things.h @@ -0,0 +1,66 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Rendering of moving objects, sprites. +// + + +#ifndef __R_THINGS__ +#define __R_THINGS__ + + + +#define MAXVISSPRITES 128 + +extern vissprite_t vissprites[MAXVISSPRITES]; +extern vissprite_t* vissprite_p; +extern vissprite_t vsprsortedhead; + +// Constant arrays used for psprite clipping +// and initializing clipping. +extern short negonearray[SCREENWIDTH]; +extern short screenheightarray[SCREENWIDTH]; + +// vars for R_DrawMaskedColumn +extern short* mfloorclip; +extern short* mceilingclip; +extern fixed_t spryscale; +extern fixed_t sprtopscreen; + +extern fixed_t pspritescale; +extern fixed_t pspriteiscale; + + +// villsa [STIFE] new argument +void R_DrawMaskedColumn (column_t *column, int baseclip); + + +void R_SortVisSprites (void); + +void R_AddSprites (sector_t* sec); +void R_AddPSprites (void); +void R_DrawSprites (void); +void R_InitSprites (const char** namelist); +void R_ClearSprites (void); +void R_DrawMasked (void); + +void +R_ClipVisSprite +( vissprite_t* vis, + int xl, + int xh ); + + +#endif diff --git a/games/NXDoom/src/strife/s_sound.c b/games/NXDoom/src/strife/s_sound.c new file mode 100644 index 00000000000..1de853fc079 --- /dev/null +++ b/games/NXDoom/src/strife/s_sound.c @@ -0,0 +1,825 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: none +// + +#include +#include +#include + +#include "i_sound.h" +#include "i_system.h" + +#include "deh_str.h" + +#include "doomstat.h" +#include "doomtype.h" + +#include "sounds.h" +#include "s_sound.h" + +#include "m_misc.h" +#include "m_random.h" +#include "m_argv.h" + +#include "p_local.h" +#include "w_wad.h" +#include "z_zone.h" + +// when to clip out sounds +// Does not fit the large outdoor areas. + +#define S_CLIPPING_DIST (1200 * FRACUNIT) + +// Distance tp origin when sounds should be maxed out. +// This should relate to movement clipping resolution +// (see BLOCKMAP handling). +// In the source code release: (160*FRACUNIT). Changed back to the +// Vanilla value of 200 (why was this changed?) + +#define S_CLOSE_DIST (200 * FRACUNIT) + +// The range over which sound attenuates + +#define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS) + +// Stereo separation + +#define S_STEREO_SWING (96 * FRACUNIT) + +#define NORM_PRIORITY 64 +#define NORM_SEP 128 + +typedef struct +{ + // sound information (if null, channel avail.) + sfxinfo_t *sfxinfo; + + // origin of sound + mobj_t *origin; + + // handle of the sound being played + int handle; + + int pitch; + +} channel_t; + +// The set of channels available + +static channel_t *channels; + +// Maximum volume of a sound effect. +// Internal default is max out of 0-15. + +int sfxVolume = 8; + +// Maximum volume of music. + +int musicVolume = 13; + +// haleyjd 08/29/10: [STRIFE] New global variable +// Volume of voice channel. + +int voiceVolume = 15; + +// Internal volume level, ranging from 0-127 + +static int snd_SfxVolume; + +// haleyjd 09/11/10: [STRIFE] Internal voice volume level + +static int snd_VoiceVolume; + +// Whether songs are mus_paused + +static boolean mus_paused; + +// Music currently being played + +static musicinfo_t *mus_playing = NULL; + +// Number of channels to use + +int snd_channels = 8; + +// haleyjd 09/11/10: [STRIFE] Handle of current voice channel. +// This has been implemented at a higher level than it was implemented +// in strife1.exe, as there it relied on a priority system which was +// implicit in the SFX_PlayPatch API of DMX. Here we'll just ignore +// the current voice channel when doing normal sound playing. + +static int i_voicehandle = -1; + +// haleyjd 09/11/10: [STRIFE] whether to play voices or not +int disable_voices = 0; + +// +// Initializes sound stuff, including volume +// Sets channels, SFX and music volume, +// allocates channel buffer, sets S_sfx lookup. +// +// haleyjd 09/11/10: [STRIFE] Added voice volume +// +void S_Init(int sfxVolume, int musicVolume, int voiceVolume) +{ + int i; + + I_SetOPLDriverVer(opl_doom_1_9); + I_PrecacheSounds(S_sfx, NUMSFX); + + S_SetSfxVolume(sfxVolume); + S_SetMusicVolume(musicVolume); + S_SetVoiceVolume(voiceVolume); + + // Allocating the internal channels for mixing + // (the maximum numer of sounds rendered + // simultaneously) within zone memory. + channels = Z_Malloc(snd_channels*sizeof(channel_t), PU_STATIC, 0); + + // Free all channels for use + for (i=0 ; isfxinfo) + { + // stop the sound playing + + if (I_SoundIsPlaying(c->handle)) + { + I_StopSound(c->handle); + } + + // check to see if other channels are playing the sound + + for (i=0; isfxinfo == channels[i].sfxinfo) + { + break; + } + } + + // degrade usefulness of sound data + + c->sfxinfo->usefulness--; + c->sfxinfo = NULL; + } +} + +// +// Per level startup code. +// Kills playing sounds at start of level, +// determines music if any, changes music. +// +// haleyjd 08/31/10: [STRIFE] +// * Removed DOOM music handling and replaced with Strife code. +// +void S_Start(void) +{ + int cnum; + int mnum; + + // kill all playing sounds at start of level + // (trust me - a good idea) + for (cnum=0 ; cnumpriority > channels[cnum].sfxinfo->priority) + return -1; + + S_StopChannel(cnum); + break; + } + } + + // None available + if (cnum == snd_channels) + { + // Look for lower priority + for (cnum=0 ; cnumpriority >= sfxinfo->priority) + { + // haleyjd 09/11/10: [STRIFE] voice has absolute priority + if (isvoice || cnum != i_voicehandle) + break; + } + } + + if (cnum == snd_channels) + { + // FUCK! No lower priority. Sorry, Charlie. + return -1; + } + else + { + // Otherwise, kick out lower priority. + S_StopChannel(cnum); + } + } + + c = &channels[cnum]; + + // channel is decided to be cnum. + c->sfxinfo = sfxinfo; + c->origin = origin; + + return cnum; +} + +// +// Changes volume and stereo-separation variables +// from the norm of a sound effect to be played. +// If the sound is not audible, returns a 0. +// Otherwise, modifies parameters and returns 1. +// +// [STRIFE] +// haleyjd 20110220: changed to eliminate the gamemap == 8 hack that was +// left over from Doom 1's original boss levels. Kind of amazing that Rogue +// was able to catch the smallest things like that. +// +static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, + int *vol, int *sep) +{ + fixed_t approx_dist; + fixed_t adx; + fixed_t ady; + angle_t angle; + + // calculate the distance to sound origin + // and clip it if necessary + adx = abs(listener->x - source->x); + ady = abs(listener->y - source->y); + + // From _GG1_ p.428. Appox. eucledian distance fast. + approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1); + + // [STRIFE] removed gamemap == 8 hack + if (approx_dist > S_CLIPPING_DIST) + { + return 0; + } + + // angle of source to listener + angle = R_PointToAngle2(listener->x, + listener->y, + source->x, + source->y); + + if (angle > listener->angle) + { + angle = angle - listener->angle; + } + else + { + angle = angle + (0xffffffff - listener->angle); + } + + angle >>= ANGLETOFINESHIFT; + + // stereo separation + *sep = 128 - (FixedMul(S_STEREO_SWING, finesine[angle]) >> FRACBITS); + + // volume calculation + // [STRIFE] Removed gamemap == 8 hack + if (approx_dist < S_CLOSE_DIST) + { + *vol = snd_SfxVolume; + } + else + { + // distance effect + *vol = (snd_SfxVolume + * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) + / S_ATTENUATOR; + } + + return (*vol > 0); +} + +void S_StartSound(void *origin_p, int sfx_id) +{ + sfxinfo_t *sfx; + mobj_t *origin; + int rc; + int sep; + int pitch; + int cnum; + int volume; + + origin = (mobj_t *) origin_p; + volume = snd_SfxVolume; + + // check for bogus sound # + if (sfx_id < 1 || sfx_id > NUMSFX) + { + // [STRIFE]: BUG - Note: vanilla had some extremely buggy and dangerous + // code here that tried to print the sprite name of the object playing + // the bad sound. Because it invokes multiple undefined behaviors and + // is of basically no consequence, it has deliberately not been ported. + I_Error("Bad sfx #: %d", sfx_id); + } + + sfx = &S_sfx[sfx_id]; + + // Initialize sound parameters + if (sfx->link) + { + volume += sfx->volume; + + if (volume < 1) + { + return; + } + + if (volume > snd_SfxVolume) + { + volume = snd_SfxVolume; + } + } + + + // Check to see if it is audible, + // and if not, modify the params + if (origin && origin != players[consoleplayer].mo) + { + rc = S_AdjustSoundParams(players[consoleplayer].mo, + origin, + &volume, + &sep); + + if (origin->x == players[consoleplayer].mo->x + && origin->y == players[consoleplayer].mo->y) + { + sep = NORM_SEP; + } + + if (!rc) + { + return; + } + } + else + { + sep = NORM_SEP; + } + pitch = NORM_PITCH; + + // kill old sound [STRIFE] - nope! + //S_StopSound(origin); + + // try to find a channel + cnum = S_GetChannel(origin, sfx, false); // haleyjd: not a voice. + + if (cnum < 0) + { + return; + } + + // increase the usefulness + if (sfx->usefulness++ < 0) + { + sfx->usefulness = 1; + } + + if (sfx->lumpnum < 0) + { + sfx->lumpnum = I_GetSfxLumpNum(sfx); + } + + channels[cnum].handle = I_StartSound(sfx, cnum, volume, sep, pitch); +} + + +// haleyjd 09/11/10: [STRIFE] +// None of this was necessary in the vanilla EXE but Choco's low-level code +// won't play nice with a temporary sfxinfo because it insists that the +// "driver_data" member remain valid from the last time the sound was used, +// even if it has already stopped playing. Thanks to this cuteness I get +// to maintain a dynamic cache of sfxinfo objects! + +typedef struct voiceinfo_s +{ + sfxinfo_t sfx; + struct voiceinfo_s *next; // next on hash chain +} voiceinfo_t; + +#define NUMVOICECHAINS 257 + +// +// Ripped from Eternity. +// +static unsigned int S_voiceHash(const char *str) +{ + const char *c = str; + unsigned int h = 0; + + if(!str) + I_Error("S_voiceHash: cannot hash NULL string!\n"); + + // note: this needs to be case insensitive for lump names + while(*c) + { + h = 5 * h + toupper(*c); + ++c; + } + + return h; +} + +static voiceinfo_t *voices[NUMVOICECHAINS]; + +// +// S_getVoice +// +// Gets an entry from the voice table, if it exists. If it does not, one will be +// created. +// +static voiceinfo_t *S_getVoice(const char *name, int lumpnum) +{ + voiceinfo_t *voice; + unsigned int hashkey = S_voiceHash(name) % NUMVOICECHAINS; + + voice = voices[hashkey]; + + while(voice && strcasecmp(voice->sfx.name, name)) + voice = voice->next; + + if(!voice) + { + voice = calloc(1, sizeof(voiceinfo_t)); + + M_StringCopy(voice->sfx.name, name, sizeof(voice->sfx.name)); + voice->sfx.priority = INT_MIN; // make highest possible priority + voice->sfx.pitch = -1; + voice->sfx.volume = -1; + voice->sfx.numchannels = -1; + voice->sfx.usefulness = -1; + voice->sfx.lumpnum = lumpnum; + + // throw it onto the table. + voice->next = voices[hashkey]; + voices[hashkey] = voice; + } + + return voice; +} + +// +// I_StartVoice +// +// haleyjd 09/11/10: [STRIFE] New function +// Note this was in i_sound.c in Strife itself, but relied on DMX-specific +// features to ensure voice channels had absolute priority. Here we must +// populate a fake sfxinfo_t and send the sound through some of the normal +// routines. But in the end, it still works the same. +// +void I_StartVoice(const char *lumpname) +{ + int lumpnum; + voiceinfo_t *voice; // choco-specific + char lumpnamedup[9]; + + // no voices in deathmatch mode. + if(netgame) + return; + + // STRIFE-TODO: checks if snd_SfxDevice == 83 + // This is probably turning off voice if using PC speaker... + + // user has disabled voices? + if(disable_voices) + return; + + // have a voice playing already? stop it. + if(i_voicehandle >= 0) + S_StopChannel(i_voicehandle); + + // Vanilla STRIFE appears to have stopped any current voice without + // starting a new one if NULL was passed in here, though I cannot + // find an explicit check for NULL in the assembly. Either way, it + // didn't crash, so do a check now: + if(lumpname == NULL) + return; + + // Because of constness problems... + M_StringCopy(lumpnamedup, lumpname, sizeof(lumpnamedup)); + + if((lumpnum = W_CheckNumForName(lumpnamedup)) != -1) + { + // haleyjd: Choco-specific: get a voice structure + voice = S_getVoice(lumpnamedup, lumpnum); + + // get a channel for the voice + i_voicehandle = S_GetChannel(NULL, &voice->sfx, true); + + channels[i_voicehandle].handle + = I_StartSound(&voice->sfx, i_voicehandle, snd_VoiceVolume, NORM_SEP, NORM_PITCH); + } +} + +// +// Stop and resume music, during game PAUSE. +// + +void S_PauseSound(void) +{ + if (mus_playing && !mus_paused) + { + I_PauseSong(); + mus_paused = true; + } +} + +void S_ResumeSound(void) +{ + if (mus_playing && mus_paused) + { + I_ResumeSong(); + mus_paused = false; + } +} + +// +// Updates music & sounds +// + +void S_UpdateSounds(mobj_t *listener) +{ + int audible; + int cnum; + int volume; + int sep; + sfxinfo_t* sfx; + channel_t* c; + + I_UpdateSound(); + + for (cnum=0; cnumsfxinfo; + + if (c->sfxinfo) + { + if (I_SoundIsPlaying(c->handle)) + { + // initialize parameters + volume = snd_SfxVolume; + sep = NORM_SEP; + + if (sfx->link) + { + volume += sfx->volume; + if (volume < 1) + { + S_StopChannel(cnum); + continue; + } + else if (volume > snd_SfxVolume) + { + volume = snd_SfxVolume; + } + } + + // check non-local sounds for distance clipping + // or modify their params + if (c->origin && listener != c->origin) + { + audible = S_AdjustSoundParams(listener, + c->origin, + &volume, + &sep); + + if (!audible) + { + S_StopChannel(cnum); + } + else + { + I_UpdateSoundParams(c->handle, volume, sep); + } + } + } + else + { + // if channel is allocated but sound has stopped, + // free it + S_StopChannel(cnum); + } + } + } +} + +void S_SetMusicVolume(int volume) +{ + if (volume < 0 || volume > 127) + { + I_Error("Attempt to set music volume at %d", + volume); + } + + I_SetMusicVolume(volume); +} + +void S_SetSfxVolume(int volume) +{ + if (volume < 0 || volume > 127) + { + I_Error("Attempt to set sfx volume at %d", volume); + } + + snd_SfxVolume = volume; +} + +// +// S_SetVoiceVolume +// +// haleyjd 09/11/10: [STRIFE] +// Set the internal voice volume level. +// +void S_SetVoiceVolume(int volume) +{ + if (volume < 0 || volume > 127) + { + I_Error("Attempt to set voice volume at %d", volume); + } + + snd_VoiceVolume = volume; +} + +// +// Starts some music with the music id found in sounds.h. +// + +void S_StartMusic(int m_id) +{ + S_ChangeMusic(m_id, false); +} + +void S_ChangeMusic(int musicnum, int looping) +{ + musicinfo_t *music = NULL; + char namebuf[9]; + void *handle; + + if (musicnum <= mus_None || musicnum >= NUMMUSIC) + { + I_Error("Bad music number %d", musicnum); + } + else + { + music = &S_music[musicnum]; + } + + if (mus_playing == music) + { + return; + } + + // shutdown old music + S_StopMusic(); + + // get lumpnum if neccessary + if (!music->lumpnum) + { + M_snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name)); + music->lumpnum = W_GetNumForName(namebuf); + } + + music->data = W_CacheLumpNum(music->lumpnum, PU_STATIC); + + handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum)); + music->handle = handle; + I_PlaySong(handle, looping); + + mus_playing = music; +} + +boolean S_MusicPlaying(void) +{ + return I_MusicIsPlaying(); +} + +void S_StopMusic(void) +{ + if (mus_playing) + { + if (mus_paused) + { + I_ResumeSong(); + } + + I_StopSong(); + I_UnRegisterSong(mus_playing->handle); + W_ReleaseLumpNum(mus_playing->lumpnum); + mus_playing->data = NULL; + mus_playing = NULL; + } +} + diff --git a/games/NXDoom/src/strife/s_sound.h b/games/NXDoom/src/strife/s_sound.h new file mode 100644 index 00000000000..0521a94e1ce --- /dev/null +++ b/games/NXDoom/src/strife/s_sound.h @@ -0,0 +1,95 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The not so system specific sound interface. +// + + +#ifndef __S_SOUND__ +#define __S_SOUND__ + +#include "p_mobj.h" +#include "sounds.h" + +// +// Initializes sound stuff, including volume +// Sets channels, SFX and music volume, +// allocates channel buffer, sets S_sfx lookup. +// + +void S_Init(int sfxVolume, int musicVolume, int voiceVolume); + + +// Shut down sound + +void S_Shutdown(void); + + + +// +// Per level startup code. +// Kills playing sounds at start of level, +// determines music if any, changes music. +// + +void S_Start(void); + +// +// Start sound for thing at +// using from sounds.h +// + +void S_StartSound(void *origin, int sound_id); + +// haleyjd 09/11/10: [STRIFE] Start a voice. +void I_StartVoice(const char *lumpname); + +// Stop sound for thing at +void S_StopSound(mobj_t *origin); + + +// Start music using from sounds.h +void S_StartMusic(int music_id); + +// Start music using from sounds.h, +// and set whether looping +void S_ChangeMusic(int music_id, int looping); + +// query if music is playing +boolean S_MusicPlaying(void); + +// Stops the music fer sure. +void S_StopMusic(void); + +// Stop and resume music, during game PAUSE. +void S_PauseSound(void); +void S_ResumeSound(void); + + +// +// Updates music & sounds +// +void S_UpdateSounds(mobj_t *listener); + +void S_SetMusicVolume(int volume); +void S_SetSfxVolume(int volume); +void S_SetVoiceVolume(int volume); // haleyjd 09/11/10: [STRIFE] + +extern int snd_channels; + +extern int disable_voices; + +#endif + diff --git a/games/NXDoom/src/strife/sounds.c b/games/NXDoom/src/strife/sounds.c new file mode 100644 index 00000000000..27a4948f291 --- /dev/null +++ b/games/NXDoom/src/strife/sounds.c @@ -0,0 +1,227 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Created by a sound utility. +// Kept as a sample, DOOM2 sounds. +// + + +#include + + +#include "doomtype.h" +#include "sounds.h" + +// +// Information about all the music +// + +#define MUSIC(name) \ + { name, 0, NULL, NULL } + +// villsa [STRIFE] +musicinfo_t S_music[] = +{ + MUSIC(NULL), + MUSIC("logo"), + MUSIC("action"), + MUSIC("tavern"), + MUSIC("danger"), + MUSIC("fast"), + MUSIC("intro"), + MUSIC("darker"), + MUSIC("strike"), + MUSIC("slide"), + MUSIC("tribal"), + MUSIC("march"), + MUSIC("danger"), + MUSIC("mood"), + MUSIC("castle"), + MUSIC("darker"), + MUSIC("action"), + MUSIC("fight"), + MUSIC("spense"), + MUSIC("slide"), + MUSIC("strike"), + MUSIC("dark"), + MUSIC("tech"), + MUSIC("slide"), + MUSIC("drone"), + MUSIC("panthr"), + MUSIC("sad"), + MUSIC("instry"), + MUSIC("tech"), + MUSIC("action"), + MUSIC("instry"), + MUSIC("drone"), + MUSIC("fight"), + MUSIC("happy"), + MUSIC("end") + + +}; + + +// +// Information about all the sfx +// + +#define SOUND(name, priority) \ + { NULL, name, priority, NULL, -1, -1, 0, 0, -1, NULL } +#define SOUND_LINK(name, priority, link_id, pitch, volume) \ + { NULL, name, priority, &S_sfx[link_id], pitch, volume, 0, 0, -1, NULL } + +// villsa [STRIFE] +sfxinfo_t S_sfx[] = +{ + // S_sfx[0] needs to be a dummy for odd reasons. + SOUND("none", 0), + SOUND("swish", 64), + SOUND("meatht", 64), + SOUND("mtalht", 64), + SOUND("wpnup", 78), + SOUND("rifle", 64), + SOUND("mislht", 64), + SOUND("barexp", 32), + SOUND("flburn", 64), + SOUND("flidl", 118), + SOUND("agrsee", 98), + SOUND("plpain", 96), + SOUND("pcrush", 96), + SOUND("pespna", 98), + SOUND("pespnb", 98), + SOUND("pespnc", 98), + SOUND("pespnd", 98), + SOUND("agrdpn", 98), + SOUND("pldeth", 32), + SOUND("plxdth", 32), + SOUND("slop", 78), + SOUND("rebdth", 98), + SOUND("agrdth", 98), + SOUND("lgfire", 211), + SOUND("smfire", 211), + SOUND("alarm", 210), + SOUND("drlmto", 98), + SOUND("drlmtc", 98), + SOUND("drsmto", 98), + SOUND("drsmtc", 98), + SOUND("drlwud", 98), + SOUND("drswud", 98), + SOUND("drston", 98), + SOUND("bdopn", 98), + SOUND("bdcls", 98), + SOUND("swtchn", 78), + SOUND("swbolt", 98), + SOUND("swscan", 98), + SOUND("yeah", 10), + SOUND("mask", 210), + SOUND("pstart", 100), + SOUND("pstop", 100), + SOUND("itemup", 78), + SOUND("bglass", 200), + SOUND("wriver", 201), + SOUND("wfall", 201), + SOUND("wdrip", 201), + SOUND("wsplsh", 95), + SOUND("rebact", 200), + SOUND("agrac1", 98), + SOUND("agrac2", 98), + SOUND("agrac3", 98), + SOUND("agrac4", 98), + SOUND("ambppl", 218), + SOUND("ambbar", 218), + SOUND("telept", 32), + SOUND("ratact", 99), + SOUND("itmbk", 100), + SOUND("xbow", 99), + SOUND("burnme", 95), + SOUND("oof", 96), + SOUND("wbrldt", 98), + SOUND("psdtha", 109), + SOUND("psdthb", 109), + SOUND("psdthc", 109), + SOUND("rb2pn", 96), + SOUND("rb2dth", 32), + SOUND("rb2see", 98), + SOUND("rb2act", 98), + SOUND("firxpl", 70), + SOUND("stnmov", 100), + SOUND("noway", 78), + SOUND("rlaunc", 64), + SOUND("rflite", 65), + SOUND("radio", 60), + SOUND("pulchn", 98), + SOUND("swknob", 98), + SOUND("keycrd", 98), + SOUND("swston", 98), + SOUND("sntsee", 98), + SOUND("sntdth", 98), + SOUND("sntact", 98), + SOUND("pgrdat", 64), + SOUND("pgrsee", 90), + SOUND("pgrdpn", 96), + SOUND("pgrdth", 32), + SOUND("pgract", 120), + SOUND("proton", 64), + SOUND("protfl", 64), + SOUND("plasma", 64), + SOUND("dsrptr", 30), + SOUND("reavat", 64), + SOUND("revbld", 64), + SOUND("revsee", 90), + SOUND("reavpn", 96), + SOUND("revdth", 32), + SOUND("revact", 120), + SOUND("spisit", 90), + SOUND("spdwlk", 65), + SOUND("spidth", 32), + SOUND("spdatk", 32), + SOUND("chant", 218), + SOUND("static", 32), + SOUND("chain", 70), + SOUND("tend", 100), + SOUND("phoot", 32), + SOUND("explod", 32), + SOUND("sigil", 32), + SOUND("sglhit", 32), + SOUND("siglup", 32), + SOUND("prgpn", 96), + SOUND("progac", 120), + SOUND("lorpn", 96), + SOUND("lorsee", 90), + SOUND("difool", 32), + SOUND("inqdth", 32), + SOUND("inqact", 98), + SOUND("inqsee", 90), + SOUND("inqjmp", 65), + SOUND("amaln1", 99), + SOUND("amaln2", 99), + SOUND("amaln3", 99), + SOUND("amaln4", 99), + SOUND("amaln5", 99), + SOUND("amaln6", 99), + SOUND("mnalse", 64), + SOUND("alnsee", 64), + SOUND("alnpn", 96), + SOUND("alnact", 120), + SOUND("alndth", 32), + SOUND("mnaldt", 32), + SOUND("reactr", 31), + SOUND("airlck", 98), + SOUND("drchno", 98), + SOUND("drchnc", 98), + SOUND("valve", 98) +}; + diff --git a/games/NXDoom/src/strife/sounds.h b/games/NXDoom/src/strife/sounds.h new file mode 100644 index 00000000000..38ed0bfcf8a --- /dev/null +++ b/games/NXDoom/src/strife/sounds.h @@ -0,0 +1,222 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Created by the sound utility written by Dave Taylor. +// Kept as a sample, DOOM2 sounds. Frozen. +// + +#ifndef __SOUNDS__ +#define __SOUNDS__ + +#include "i_sound.h" + +// the complete set of sound effects +extern sfxinfo_t S_sfx[]; + +// the complete set of music +extern musicinfo_t S_music[]; + +// +// Identifiers for all music in game. +// + +// villsa [STRIFE] +typedef enum +{ + mus_None, + mus_logo, + mus_action, + mus_tavern, + mus_danger, + mus_fast, + mus_intro, + mus_darker, + mus_strike, + mus_slide, + mus_tribal, + mus_march, + mus_danger2, + mus_mood, + mus_castle, + mus_darker2, + mus_action2, + mus_fight, + mus_spense, + mus_slide2, + mus_strike2, + mus_dark, + mus_tech, + mus_slide3, + mus_drone, + mus_panthr, + mus_sad, + mus_instry, + mus_tech2, + mus_action3, + mus_instry2, + mus_drone2, + mus_fight2, + mus_happy, + mus_end, + NUMMUSIC +} musicenum_t; + + +// +// Identifiers for all sfx in game. +// + +typedef enum +{ + sfx_None, + sfx_swish, + sfx_meatht, + sfx_mtalht, + sfx_wpnup, + sfx_rifle, + sfx_mislht, + sfx_barexp, + sfx_flburn, + sfx_flidl, + sfx_agrsee, + sfx_plpain, + sfx_pcrush, + sfx_pespna, + sfx_pespnb, + sfx_pespnc, + sfx_pespnd, + sfx_agrdpn, + sfx_pldeth, + sfx_plxdth, + sfx_slop, + sfx_rebdth, + sfx_agrdth, + sfx_lgfire, + sfx_smfire, + sfx_alarm, + sfx_drlmto, + sfx_drlmtc, + sfx_drsmto, + sfx_drsmtc, + sfx_drlwud, + sfx_drswud, + sfx_drston, + sfx_bdopn, + sfx_bdcls, + sfx_swtchn, + sfx_swbolt, + sfx_swscan, + sfx_yeah, + sfx_mask, + sfx_pstart, + sfx_pstop, + sfx_itemup, + sfx_bglass, + sfx_wriver, + sfx_wfall, + sfx_wdrip, + sfx_wsplsh, + sfx_rebact, + sfx_agrac1, + sfx_agrac2, + sfx_agrac3, + sfx_agrac4, + sfx_ambppl, + sfx_ambbar, + sfx_telept, + sfx_ratact, + sfx_itmbk, + sfx_xbow, + sfx_burnme, + sfx_oof, + sfx_wbrldt, + sfx_psdtha, + sfx_psdthb, + sfx_psdthc, + sfx_rb2pn, + sfx_rb2dth, + sfx_rb2see, + sfx_rb2act, + sfx_firxpl, + sfx_stnmov, + sfx_noway, + sfx_rlaunc, + sfx_rflite, + sfx_radio, + sfx_pulchn, + sfx_swknob, + sfx_keycrd, + sfx_swston, + sfx_sntsee, + sfx_sntdth, + sfx_sntact, + sfx_pgrdat, + sfx_pgrsee, + sfx_pgrdpn, + sfx_pgrdth, + sfx_pgract, + sfx_proton, + sfx_protfl, + sfx_plasma, + sfx_dsrptr, + sfx_reavat, + sfx_revbld, + sfx_revsee, + sfx_reavpn, + sfx_revdth, + sfx_revact, + sfx_spisit, + sfx_spdwlk, + sfx_spidth, + sfx_spdatk, + sfx_chant, + sfx_static, + sfx_chain, + sfx_tend, + sfx_phoot, + sfx_explod, + sfx_sigil, + sfx_sglhit, + sfx_siglup, + sfx_prgpn, + sfx_progac, + sfx_lorpn, + sfx_lorsee, + sfx_difool, + sfx_inqdth, + sfx_inqact, + sfx_inqsee, + sfx_inqjmp, + sfx_amaln1, + sfx_amaln2, + sfx_amaln3, + sfx_amaln4, + sfx_amaln5, + sfx_amaln6, + sfx_mnalse, + sfx_alnsee, + sfx_alnpn, + sfx_alnact, + sfx_alndth, + sfx_mnaldt, + sfx_reactr, + sfx_airlck, + sfx_drchno, + sfx_drchnc, + sfx_valve, + NUMSFX +} sfxenum_t; + +#endif diff --git a/games/NXDoom/src/strife/st_lib.c b/games/NXDoom/src/strife/st_lib.c new file mode 100644 index 00000000000..3ade0955744 --- /dev/null +++ b/games/NXDoom/src/strife/st_lib.c @@ -0,0 +1,326 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The status bar widget code. +// + + +#include +#include + +#include "deh_main.h" +#include "doomdef.h" + +#include "z_zone.h" +#include "v_video.h" + +#include "i_swap.h" +#include "i_system.h" + +#include "w_wad.h" + +#include "st_stuff.h" +#include "st_lib.h" +#include "r_local.h" + + +// +// Hack display negative frags. +// Loads and store the stminus lump. +// +patch_t* sttminus; + +void STlib_init(void) +{ + // haleyjd 08/28/10: [STRIFE] STTMINUS -> STCFN045 + sttminus = (patch_t *) W_CacheLumpName(DEH_String("STCFN045"), PU_STATIC); +} + + +// +// STlib_initNum +// +// haleyjd 09/01/10: [STRIFE] +// * Rogue removed the "on" member of st_number_t. +void +STlib_initNum +( st_number_t* n, + int x, + int y, + patch_t** pl, + int* num, + int width ) +{ + n->x = x; + n->y = y; + n->width = width; + n->num = num; + n->p = pl; +} + + +// +// STlib_drawNum +// +// A fairly efficient way to draw a number +// based on differences from the old number. +// Note: worth the trouble? +// +// haleyjd 09/01/10: [STRIFE] +// * Rogue removed the "refresh" parameter and caching code +// +void +STlib_drawNum +( st_number_t* n) +{ + int numdigits = n->width; + int num = *n->num; + + int w = SHORT(n->p[0]->width) + 1; // [STRIFE] +1 + int x = n->x; + + int neg; + + neg = num < 0; + + if (neg) + { + if (numdigits == 2 && num < -9) + num = -9; + else if (numdigits == 3 && num < -99) + num = -99; + + num = -num; + } + + /* haleyjd 09/01/10: [STRIFE] Widget caching system removed by Rogue + // clear the area + x = n->x - numdigits*w; + + if (n->y - ST_Y < 0) + I_Error("drawNum: n->y - ST_Y < 0"); + + V_CopyRect(x, n->y - ST_Y, st_backing_screen, w*numdigits, h, x, n->y); + */ + + // if non-number, do not draw it + if (num == 1994) + return; + + x = n->x; + + // in the special case of 0, you draw 0 + if (!num) + V_DrawPatch(x - w, n->y, n->p[ 0 ]); + + // draw the new number + while (num && numdigits--) + { + x -= w; + V_DrawPatch(x, n->y, n->p[ num % 10 ]); + num /= 10; + } + + // draw a minus sign if necessary + if (neg) + V_DrawPatch(x - 8, n->y, sttminus); +} + + +// +// STlib_drawNumPositive +// +// haleyjd 09/01/10: [STRIFE] New function. +// * Mostly the same as STlib_drawNum, except doesn't draw negatives. +// +void +STlib_drawNumPositive +( st_number_t* n) +{ + int numdigits = n->width; + int num = *n->num; + + int w = SHORT(n->p[0]->width) + 1; // [STRIFE] +1 + int x = n->x; + + // Don't draw negative values. + if (num < 0) + num = 0; + + // if non-number, do not draw it + if (num == 1994) + return; + + x = n->x; + + // in the special case of 0, you draw 0 + if (!num) + V_DrawPatch(x - w, n->y, n->p[ 0 ]); + + // draw the new number + while (num && numdigits--) + { + x -= w; + V_DrawPatch(x, n->y, n->p[ num % 10 ]); + num /= 10; + } +} + + +// haleyjd 09/01/10: [STRIFE] All other functions were removed. +/* +void +STlib_updateNum +( st_number_t* n, + boolean refresh ) +{ + if (*n->on) STlib_drawNum(n, refresh); +} + + +// +void +STlib_initPercent +( st_percent_t* p, + int x, + int y, + patch_t** pl, + int* num, + boolean* on, + patch_t* percent ) +{ + STlib_initNum(&p->n, x, y, pl, num, on, 3); + p->p = percent; +} + + + + +void +STlib_updatePercent +( st_percent_t* per, + int refresh ) +{ + if (refresh && *per->n.on) + V_DrawPatch(per->n.x, per->n.y, per->p); + + STlib_updateNum(&per->n, refresh); +} + + + +void +STlib_initMultIcon +( st_multicon_t* i, + int x, + int y, + patch_t** il, + int* inum, + boolean* on ) +{ + i->x = x; + i->y = y; + i->oldinum = -1; + i->inum = inum; + i->on = on; + i->p = il; +} + + + +void +STlib_updateMultIcon +( st_multicon_t* mi, + boolean refresh ) +{ + int w; + int h; + int x; + int y; + + if (*mi->on + && (mi->oldinum != *mi->inum || refresh) + && (*mi->inum!=-1)) + { + if (mi->oldinum != -1) + { + x = mi->x - SHORT(mi->p[mi->oldinum]->leftoffset); + y = mi->y - SHORT(mi->p[mi->oldinum]->topoffset); + w = SHORT(mi->p[mi->oldinum]->width); + h = SHORT(mi->p[mi->oldinum]->height); + + if (y - ST_Y < 0) + I_Error("updateMultIcon: y - ST_Y < 0"); + + V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); + } + V_DrawPatch(mi->x, mi->y, mi->p[*mi->inum]); + mi->oldinum = *mi->inum; + } +} + + + +void +STlib_initBinIcon +( st_binicon_t* b, + int x, + int y, + patch_t* i, + boolean* val, + boolean* on ) +{ + b->x = x; + b->y = y; + b->oldval = false; + b->val = val; + b->on = on; + b->p = i; +} + + + +void +STlib_updateBinIcon +( st_binicon_t* bi, + boolean refresh ) +{ + int x; + int y; + int w; + int h; + + if (*bi->on + && (bi->oldval != *bi->val || refresh)) + { + x = bi->x - SHORT(bi->p->leftoffset); + y = bi->y - SHORT(bi->p->topoffset); + w = SHORT(bi->p->width); + h = SHORT(bi->p->height); + + if (y - ST_Y < 0) + I_Error("updateBinIcon: y - ST_Y < 0"); + + if (*bi->val) + V_DrawPatch(bi->x, bi->y, bi->p); + else + V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); + + bi->oldval = *bi->val; + } + +} +*/ + diff --git a/games/NXDoom/src/strife/st_lib.h b/games/NXDoom/src/strife/st_lib.h new file mode 100644 index 00000000000..b2c85a818e9 --- /dev/null +++ b/games/NXDoom/src/strife/st_lib.h @@ -0,0 +1,221 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// The status bar widget code. +// + +#ifndef __STLIB__ +#define __STLIB__ + + +// We are referring to patches. +#include "r_defs.h" + +// +// Typedefs of widgets +// + +// Number widget + +typedef struct +{ + // upper right-hand corner + // of the number (right-justified) + int x; + int y; + + // max # of digits in number + int width; + + // haleyjd 09/01/10: [STRIFE] Removed "oldnum" member + //int oldnum; + + // pointer to current value + int* num; + + // haleyjd 09/01/10: [STRIFE] Removed "on" member + // boolean* on; + + // list of patches for 0-9 + patch_t** p; + + // user data + int data; + +} st_number_t; + + + +// Percent widget ("child" of number widget, +// or, more precisely, contains a number widget.) +typedef struct +{ + // number information + st_number_t n; + + // percent sign graphic + patch_t* p; + +} st_percent_t; + + + +// Multiple Icon widget +typedef struct +{ + // center-justified location of icons + int x; + int y; + + // last icon number + int oldinum; + + // pointer to current icon + int* inum; + + // pointer to boolean stating + // whether to update icon + boolean* on; + + // list of icons + patch_t** p; + + // user data + int data; + +} st_multicon_t; + + + + +// Binary Icon widget + +typedef struct +{ + // center-justified location of icon + int x; + int y; + + // last icon value + boolean oldval; + + // pointer to current icon status + boolean* val; + + // pointer to boolean + // stating whether to update icon + boolean* on; + + + patch_t* p; // icon + int data; // user data + +} st_binicon_t; + + + +// +// Widget creation, access, and update routines +// + +// Initializes widget library. +// More precisely, initialize STMINUS, +// everything else is done somewhere else. +// +void STlib_init(void); + + + +// Number widget routines + +// haleyjd 09/01/10: [STRIFE] Removed "on" parameter. +void +STlib_initNum +( st_number_t* n, + int x, + int y, + patch_t** pl, + int* num, + int width ); + +// haleyjd 09/01/10: [STRIFE] Made globally visible. +void +STlib_drawNum +( st_number_t* n); + +// haleyjd 09/01/10: [STRIFE] New function +void +STlib_drawNumPositive +( st_number_t* n); + +/* haleyjd 09/01/10: [STRIFE] All the below were removed +void +STlib_updateNum +( st_number_t* n, + boolean refresh ); + + +// Percent widget routines +void +STlib_initPercent +( st_percent_t* p, + int x, + int y, + patch_t** pl, + int* num, + boolean* on, + patch_t* percent ); + + +void +STlib_updatePercent +( st_percent_t* per, + int refresh ); + + +// Multiple Icon widget routines +void +STlib_initMultIcon +( st_multicon_t* mi, + int x, + int y, + patch_t** il, + int* inum, + boolean* on ); + + +void +STlib_updateMultIcon +( st_multicon_t* mi, + boolean refresh ); + +// Binary Icon widget routines + +void +STlib_initBinIcon +( st_binicon_t* b, + int x, + int y, + patch_t* i, + boolean* val, + boolean* on ); + +void +STlib_updateBinIcon +( st_binicon_t* bi, + boolean refresh ); +*/ + +#endif diff --git a/games/NXDoom/src/strife/st_stuff.c b/games/NXDoom/src/strife/st_stuff.c new file mode 100644 index 00000000000..ae1d4cd90bd --- /dev/null +++ b/games/NXDoom/src/strife/st_stuff.c @@ -0,0 +1,1605 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Status bar code. +// Does the face/direction indicator animatin. +// Does palette indicators as well (red pain/berserk, bright pickup) +// + + + +#include + +#include "i_system.h" +#include "i_video.h" +#include "z_zone.h" +#include "m_random.h" +#include "w_wad.h" + +#include "deh_main.h" +#include "deh_misc.h" +#include "doomdef.h" +#include "doomkeys.h" + +#include "g_game.h" + +#include "st_stuff.h" +#include "st_lib.h" +#include "r_local.h" + +#include "p_local.h" +#include "p_inter.h" +#include "p_dialog.h" // villsa [STRIFE] + +#include "am_map.h" +#include "m_cheat.h" +#include "m_menu.h" // villsa [STRIFE] +#include "m_misc.h" + +#include "s_sound.h" + +// Needs access to LFB. +#include "v_video.h" +#include "i_swap.h" + +// State. +#include "doomstat.h" +#include "d_main.h" // [STRIFE] + +// Data. +#include "dstrings.h" +#include "sounds.h" +#include "m_controls.h" +#include "hu_lib.h" // [STRIFE] +#include "hu_stuff.h" + +// +// STATUS BAR DATA +// + +// Palette indices. +// For damage/bonus red-/gold-shifts +#define STARTREDPALS 1 +#define STARTBONUSPALS 9 +#define NUMREDPALS 8 +#define NUMBONUSPALS 4 +// Radiation suit, green shift. +#define RADIATIONPAL 13 + +// Location of status bar +#define ST_X 0 + +// Location and size of statistics, +// justified according to widget type. +// Problem is, within which space? STbar? Screen? +// Note: this could be read in by a lump. +// Problem is, is the stuff rendered +// into a buffer, +// or into the frame buffer? + +// AMMO number pos. +// haleyjd 20100901: [STRIFE] Adjusted. +#define ST_AMMOWIDTH 3 +#define ST_AMMOX 311 +#define ST_AMMOY 162 + +// HEALTH number pos. +// haleyjd 20100901: [STRIFE] Adjusted. +#define ST_HEALTHWIDTH 3 +#define ST_HEALTHX 79 +#define ST_HEALTHY 162 + +// [STRIFE] +// Removed: +// * Weapon pos. +// * Frags pos. +// * ARMOR number pos. +// * Key icon positions. + +// Ammunition counter. +// haleyjd 20110213 [STRIFE]: ammo counters for the popup widget +#define ST_POPUPAMMOX 206 +static const int st_yforammo[NUMAMMO] = { 75, 99, 91, 139, 131, 115, 123 }; +static const int st_wforammo[NUMAMMO] = { 3, 3, 2, 3, 3, 2, 3 }; + +// Indicate maximum ammunition. +// Only needed because backpack exists. +// haleyjd 20110213 [STRIFE]: maxammo counters for the popup widget +#define ST_POPUPMAXAMMOX 239 + +// [STRIFE] +// Removed: +// * Doom weapon stuff +// * DETH title (???) + +// Dimensions given in characters. +#define ST_MSGWIDTH 52 + +// haleyjd 20100831: [STRIFE] +// * Removed faces. +// haleyjd 20100901: +// * Removed DOOM pre-beta cruft. +// * Removed deathmatch frags/arms-related stuff. +// * Removed arms panel stuff. +// * Removed unused widgets. +// * Removed more faces, keyboxes, st_randomnumber + +// graphics are drawn to a backing screen and blitted to the real screen +//byte *st_backing_screen; - [STRIFE]: Unused. + +// main player in game +static player_t* plyr; + +// ST_Start() has just been called +static boolean st_firsttime; + +// lump number for PLAYPAL +static int lu_palette; + +// whether left-side main status bar is active +static boolean st_statusbaron; + +// villsa [STRIFE] +static boolean st_dosizedisplay = false; + +// haleyjd 09/01/10: [STRIFE] +// Whether or not a popup is currently displayed +static boolean st_displaypopup = false; + +// villsa [STRIFE] +static int st_popupdisplaytics = 0; + +// villsa [STRIFE] +// Whether or not show popup objective screen +static boolean st_showobjective = false; + +// villsa [STRIFE] +static boolean st_showinvpop = false; + +// villsa [STRIFE] +static boolean st_showkeys = false; + +// villsa [STRIFE] TODO - identify variables +static int st_keypage = -1; +// [unused] static int dword_88490 = 0; + +// haleyjd 09/19/10: [STRIFE] Cached player data +static int st_lastcursorpos; +static int st_lastammo; +static int st_lastarmortype; +static int st_lasthealth; + +// haleyjd 20100901: [STRIFE] sbar -> invback +// main inventory background and other bits +static patch_t* invback; // main bar +static patch_t* stback; // multiplayer background +static patch_t* invtop; // top bit +static patch_t* invpop; // popup frame with text +static patch_t* invpop2; // plain popup frame +static patch_t* invpbak; // popup background w/details +static patch_t* invpbak2; // plain popup background +static patch_t* invcursor; // cursor + +// ammo/weapon/armor patches +static patch_t* invammo[NUMAMMO]; // ammo/weapons +static patch_t* invsigil[5]; // sigil pieces +static patch_t* invarmor[2]; // armor icons + +// names for ammo patches +static const char *invammonames[NUMAMMO] = +{ + "I_BLIT", + "I_XQRL", + "I_PQRL", + "I_BRY1", + "I_ROKT", + "I_GRN1", + "I_GRN2" +}; + +// haleyjd 20100901: [STRIFE] Replaced tallnum, shortnum w/inv fonts +// 0-9, green numbers +static patch_t* invfontg[10]; + +// 0-9, yellow numbers +static patch_t* invfonty[10]; + +// [unused] 3 key-cards, 3 skulls -- [STRIFE] has a lot more keys than 3 :P +//static patch_t* keys[NUMCARDS]; + +// ready-weapon widget +static st_number_t w_ready; // haleyjd [STRIFE]: This is still used. + +// haleyjd: [STRIFE] This is still used but was changed to a st_number_t. +// health widget +static st_number_t w_health; + +// ammo widgets +static st_number_t w_ammo[NUMAMMO]; // haleyjd [STRIFE]: Still used. + +// max ammo widgets +static st_number_t w_maxammo[NUMAMMO]; // haleyjd [STRIFE]: Still used. + +// [unused] number of frags so far in deathmatch +//static int st_fragscount; + + +cheatseq_t cheat_mus = CHEAT("spin", 2); // [STRIFE]: idmus -> spin +cheatseq_t cheat_god = CHEAT("omnipotent", 0); // [STRIFE]: iddqd -> omnipotent +cheatseq_t cheat_ammo = CHEAT("boomstix", 0); // [STRIFE]: idfa -> boomstix +cheatseq_t cheat_noclip = CHEAT("elvis", 0); // [STRIFE]: idclip -> elvis +cheatseq_t cheat_clev = CHEAT("rift", 2); // [STRIFE]: idclev -> rift +cheatseq_t cheat_mypos = CHEAT("gps", 0); // [STRIFE]: idmypos -> gps +cheatseq_t cheat_scoot = CHEAT("scoot", 1); // [STRIFE]: new cheat scoot +cheatseq_t cheat_nuke = CHEAT("stonecold", 0); // [STRIFE]: new cheat stonecold +cheatseq_t cheat_keys = CHEAT("jimmy", 0); // [STRIFE]: new cheat jimmy (all keys) +cheatseq_t cheat_stealth = CHEAT("gripper", 0); // [STRIFE]: new cheat gripper +cheatseq_t cheat_midas = CHEAT("donnytrump", 0); // [STRIFE]: new cheat +cheatseq_t cheat_lego = CHEAT("lego", 0); // [STRIFE]: new cheat +cheatseq_t cheat_dev = CHEAT("dots", 0); // [STRIFE]: new cheat + +// haleyjd 20110224: enumeration for access to powerup cheats +enum +{ + ST_PUMPUP_B, + ST_PUMPUP_I, + ST_PUMPUP_M, + ST_PUMPUP_H, + ST_PUMPUP_P, + ST_PUMPUP_S, + ST_PUMPUP_T, + ST_PUMPUP, + NUM_ST_PUMPUP +}; + +cheatseq_t cheat_powerup[NUM_ST_PUMPUP] = // [STRIFE] +{ + CHEAT("pumpupb", 0), + CHEAT("pumpupi", 0), + CHEAT("pumpupm", 0), + CHEAT("pumpuph", 0), + CHEAT("pumpupp", 0), + CHEAT("pumpups", 0), + CHEAT("pumpupt", 0), + CHEAT("pumpup", 0), +}; + +//cheatseq_t cheat_choppers = CHEAT("idchoppers", 0); [STRIFE] no such thing + +void M_SizeDisplay(int choice); // villsa [STRIFE] + +// +// STATUS BAR CODE +// +void ST_Stop(void); + +// [STRIFE] +static char st_msgbuf[ST_MSGWIDTH]; + +// Respond to keyboard input events, +// intercept cheats. +boolean ST_Responder(event_t* ev) +{ + // haleyjd 09/27/10: made static to ST_Responder + static boolean st_keystate = false; + int i; + + // Filter automap on/off. + if(ev->type == ev_keyup) + { + if((ev->data1 & 0xffff0000) == AM_MSGHEADER) + { + switch(ev->data1) + { + case AM_MSGENTERED: + st_firsttime = true; + break; + + case AM_MSGEXITED: + break; + } + + return false; + } + + // villsa [STRIFE] + if(ev->data1 != key_invpop && + ev->data1 != key_mission && + ev->data1 != key_invkey) + return false; + + // villsa [STRIFE] + if(ev->data1 == key_invpop) + st_showinvpop = false; + else + { + if(ev->data1 == key_mission) + st_showobjective = false; + else + { + if(ev->data1 == key_invkey) + { + st_showkeys = false; + st_keystate = false; + } + } + } + + if(!st_showkeys && !st_showobjective && !st_showinvpop) + { + if(!st_popupdisplaytics) + { + st_displaypopup = false; + if(st_dosizedisplay) + M_SizeDisplay(true); + + st_dosizedisplay = false; + } + } + + return true; + } + + // if a user keypress... + if(ev->type != ev_keydown) + return false; + + // haleyjd 20100927: No input allowed when the player is dead + if(plyr->mo->health <= 0) + return false; + + // keydown events + if(ev->data1 == key_invquery) // inventory query + { + inventory_t *inv = &(plyr->inventory[plyr->inventorycursor]); + if(inv->amount) + { + DEH_snprintf(st_msgbuf, sizeof(st_msgbuf), "%d %s", + inv->amount, + DEH_String(mobjinfo[inv->type].name)); + plyr->message = st_msgbuf; + } + } + + // villsa [STRIFE] + if(ev->data1 == key_invpop || ev->data1 == key_invkey || ev->data1 == key_mission) + { + if(ev->data1 == key_invkey) + { + st_showobjective = false; + st_showinvpop = false; + + if(!st_keystate) + { + st_keystate = true; + if(++st_keypage > 2) + { + st_popupdisplaytics = 0; + st_showkeys = false; + st_displaypopup = false; + st_keypage = -1; + return true; + } + } + + if(netgame) + st_popupdisplaytics = 20; + else + st_popupdisplaytics = 50; + + st_showkeys = true; + } + else + { + if(ev->data1 != key_mission || netgame) + { + if(ev->data1 == key_invpop) + { + st_keypage = -1; + st_popupdisplaytics = false; + st_showkeys = false; + st_showobjective = false; + st_showinvpop = true; + } + } + else + { + st_showkeys = netgame; + st_showinvpop = netgame; + st_keypage = -1; + + st_popupdisplaytics = ev->data2 ^ key_mission; + + st_showobjective = true; + } + } + + if(st_showkeys || st_showobjective || st_showinvpop) + { + st_displaypopup = true; + if(viewheight == SCREENHEIGHT) + { + M_SizeDisplay(false); + st_dosizedisplay = true; + } + } + } + + if(ev->data1 == key_invleft) // inventory move left + { + if(plyr->inventorycursor > 0) + plyr->inventorycursor--; + return true; + } + else if(ev->data1 == key_invright) + { + if(plyr->inventorycursor < plyr->numinventory - 1) + plyr->inventorycursor++; + return true; + } + else if(ev->data1 == key_invhome) + { + plyr->inventorycursor = 0; + return true; + } + else if(ev->data1 == key_invend) + { + if(plyr->numinventory) + plyr->inventorycursor = plyr->numinventory - 1; + else + plyr->inventorycursor = 0; + return true; + } + + // + // [STRIFE] Cheats which are allowed in netgames/demos: + // + + // 'spin' cheat for changing music + if (cht_CheckCheat(&cheat_mus, ev->data2)) + { + char buf[3]; + int musnum; + + plyr->message = DEH_String(STSTR_MUS); + cht_GetParam(&cheat_mus, buf); + + musnum = (buf[0] - '0') * 10 + buf[1] - '0'; + + if (((buf[0]-'0')*10 + buf[1]-'0') > 35) + plyr->message = DEH_String(STSTR_NOMUS); + else + S_ChangeMusic(musnum, 1); + } + // [STRIFE]: "dev" cheat - "DOTS" + else if (cht_CheckCheat(&cheat_dev, ev->data2)) + { + devparm = !devparm; + if (devparm) + plyr->message = DEH_String("devparm ON"); + else + plyr->message = DEH_String("devparm OFF"); + } + + // [STRIFE] Cheats below are not allowed in netgames or demos + if(netgame || !usergame) + return false; + + if (cht_CheckCheat(&cheat_god, ev->data2)) + { + // 'omnipotent' cheat for toggleable god mode + plyr->cheats ^= CF_GODMODE; + if (plyr->cheats & CF_GODMODE) + { + if (plyr->mo) + plyr->mo->health = 100; + + plyr->health = deh_god_mode_health; + plyr->st_update = true; // [STRIFE] + plyr->message = DEH_String(STSTR_DQDON); + } + else + { + plyr->st_update = true; + plyr->message = DEH_String(STSTR_DQDOFF); + } + } + else if (cht_CheckCheat(&cheat_ammo, ev->data2)) + { + // [STRIFE]: "BOOMSTIX" cheat for all normal weapons + plyr->armorpoints = deh_idkfa_armor; + plyr->armortype = deh_idkfa_armor_class; + + for (i = 0; i < NUMWEAPONS; i++) + if(!isdemoversion || weaponinfo[i].availabledemo) + plyr->weaponowned[i] = true; + + // Takes away the Sigil, even if you already had it... + plyr->weaponowned[wp_sigil] = false; + + for (i=0;iammo[i] = plyr->maxammo[i]; + + plyr->message = DEH_String(STSTR_FAADDED); + } + else if(cht_CheckCheat(&cheat_keys, ev->data2)) + { + // villsa [STRIFE]: "JIMMY" cheat for all keys + #define FIRSTKEYSETAMOUNT 16 + + if(plyr->cards[FIRSTKEYSETAMOUNT - 1]) + { + if(plyr->cards[NUMCARDS - 1] || isdemoversion) + { + for(i = 0; i < NUMCARDS; i++) + plyr->cards[i] = false; + + plyr->message = DEH_String("Keys removed"); + } + else + { + for(i = 0; i < NUMCARDS; i++) + plyr->cards[i] = true; + + plyr->message = DEH_String("Cheater Keys Added"); + } + } + else + { + for(i = 0; i < FIRSTKEYSETAMOUNT; i++) + plyr->cards[i] = true; + + plyr->message = DEH_String("Cheater Keys Added"); + } + } + else if (cht_CheckCheat(&cheat_noclip, ev->data2)) + { + // [STRIFE] Removed idspispopd, added NOCLIP flag setting/removal + // Noclip cheat - "ELVIS" (hah-hah :P ) + + plyr->cheats ^= CF_NOCLIP; + + if (plyr->cheats & CF_NOCLIP) + { + plyr->message = DEH_String(STSTR_NCON); + plyr->mo->flags |= MF_NOCLIP; + } + else + { + plyr->message = DEH_String(STSTR_NCOFF); + plyr->mo->flags &= ~MF_NOCLIP; + } + } + else if(cht_CheckCheat(&cheat_stealth, ev->data2)) + { + // villsa [STRIFE]: "GRIPPER" cheat; nothing to do with stealth... + plyr->cheats ^= CF_NOMOMENTUM; + if(plyr->cheats & CF_NOMOMENTUM) + plyr->message = DEH_String("STEALTH BOOTS ON"); + else + plyr->message = DEH_String("STEALTH BOOTS OFF"); + } + + for(i = 0; i < ST_PUMPUP_B + 3; ++i) + { + // [STRIFE]: Handle berserk, invisibility, and envirosuit + if(cht_CheckCheat(&cheat_powerup[i], ev->data2)) + { + if(plyr->powers[i]) + plyr->powers[i] = (i != 1); + else + P_GivePower(plyr, i); + plyr->message = DEH_String(STSTR_BEHOLDX); + } + } + if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_H], ev->data2)) + { + // [STRIFE]: PUMPUPH gives medical inventory items + P_GiveItemToPlayer(plyr, SPR_STMP, MT_INV_MED1); + P_GiveItemToPlayer(plyr, SPR_MDKT, MT_INV_MED2); + P_GiveItemToPlayer(plyr, SPR_FULL, MT_INV_MED3); + plyr->message = DEH_String("you got the stuff!"); + } + if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_P], ev->data2)) + { + // [STRIFE]: PUMPUPP gives backpack + if(!plyr->backpack) + { + for(i = 0; i < NUMAMMO; ++i) + plyr->maxammo[i] = 2 * plyr->maxammo[i]; + } + plyr->backpack = true; + + for(i = 0; i < NUMAMMO; ++i) + P_GiveAmmo(plyr, i, 1); + plyr->message = DEH_String("you got the stuff!"); + } + if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_S], ev->data2)) + { + // [STRIFE]: PUMPUPS gives stamina and accuracy upgrades + P_GiveItemToPlayer(plyr, SPR_TOKN, MT_TOKEN_STAMINA); + P_GiveItemToPlayer(plyr, SPR_TOKN, MT_TOKEN_NEW_ACCURACY); + plyr->message = DEH_String("you got the stuff!"); + } + if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_T], ev->data2)) + { + // [STRIFE] PUMPUPT gives targeter + P_GivePower(plyr, pw_targeter); + plyr->message = DEH_String("you got the stuff!"); + } + // [STRIFE]: PUMPUP + if (cht_CheckCheat(&cheat_powerup[ST_PUMPUP], ev->data2)) + { + // 'behold' power-up menu + plyr->message = DEH_String(STSTR_BEHOLD); + return false; + } + + if (cht_CheckCheat(&cheat_mypos, ev->data2)) + { + // [STRIFE] 'GPS' for player position + static char buf[ST_MSGWIDTH]; + M_snprintf(buf, sizeof(buf), + "ang=0x%x;x,y=(0x%x,0x%x)", + players[consoleplayer].mo->angle, + players[consoleplayer].mo->x, + players[consoleplayer].mo->y); + plyr->message = buf; + } + + // 'rift' change-level cheat + if (cht_CheckCheat(&cheat_clev, ev->data2)) + { + char buf[3]; + int map; + + cht_GetParam(&cheat_clev, buf); + + map = (buf[0] - '0') * 10 + buf[1] - '0'; + + // haleyjd 20100901: Removed Chex Quest stuff. + // haleyjd 20100915: Removed retail/registered/shareware stuff + + // haleyjd 20130301: different bounds in v1.31 + // Ohmygod - this is not going to work. + if(gameversion == exe_strife_1_31) + { + if ((isdemoversion && (map < 32 || map > 34)) || + (isregistered && (map <= 0 || map > 34))) + return false; + } + else + { + if (map <= 0 || map > 40) + return false; + } + + // So be it. + plyr->message = DEH_String(STSTR_CLEV); + G_RiftExitLevel(map, 0, plyr->mo->angle); + } + else if(cht_CheckCheat(&cheat_scoot, ev->data2)) + { + char buf[3]; + int spot; + + cht_GetParam(&cheat_scoot, buf); + + spot = buf[0] - '0'; + + // BUG: should be <= 9. Shouldn't do anything bad though... + if(spot <= 10) + { + plyr->message = DEH_String("Spawning to spot"); + G_RiftCheat(spot); + return false; + } + } + + // villsa [STRIFE] + if(cht_CheckCheat(&cheat_nuke, ev->data2)) + { + stonecold ^= 1; + plyr->message = DEH_String("Kill 'em. Kill 'em All"); + return false; + } + + // villsa [STRIFE] + if(cht_CheckCheat(&cheat_midas, ev->data2)) + { + plyr->message = DEH_String("YOU GOT THE MIDAS TOUCH, BABY"); + P_GiveItemToPlayer(plyr, SPR_HELT, MT_TOKEN_TOUGHNESS); + } + + // villsa [STRIFE] + // haleyjd 20110224: No sigil in demo version + if(!isdemoversion && cht_CheckCheat(&cheat_lego, ev->data2)) + { + plyr->st_update = true; + if(plyr->weaponowned[wp_sigil]) + { + if(++plyr->sigiltype > 4) + { + plyr->sigiltype = -1; + plyr->pendingweapon = wp_fist; + plyr->weaponowned[wp_sigil] = false; + } + } + else + { + plyr->weaponowned[wp_sigil] = true; + plyr->sigiltype = 0; + } + // BUG: This brings up a bad version of the Sigil (sigiltype -1) which + // causes some VERY interesting behavior, when you type LEGO for the + // sixth time. This shouldn't be done when taking it away, and yet it + // is here... verified with vanilla. + plyr->pendingweapon = wp_sigil; + } + + return false; +} + + +/* +int ST_calcPainOffset(void) +{ + // haleyjd 08/31/10: [STRIFE] Removed. +} +*/ + +// +// This is a not-very-pretty routine which handles +// the face states and their timing. +// the precedence of expressions is: +// dead > evil grin > turned head > straight ahead +// +/* +void ST_updateFaceWidget(void) +{ + // haleyjd 08/31/10: [STRIFE] Removed. +} +*/ + +/* +void ST_updateWidgets(void) +{ + // haleyjd 09/01/10: [STRIFE] Rogue merged this into ST_Ticker below. +} +*/ + +// +// ST_Ticker +// +// haleyjd 09/01/10: [STRIFE] +// * Removed st_clock and st_randomnumber. +// * Merged ST_updateWidgets here. Wasn't inlined, as doesn't exist separately +// in the binary as inlined functions normally do. +// +void ST_Ticker (void) +{ + static int largeammo = 1994; // means "n/a" + + // must redirect the pointer if the ready weapon has changed. + if (weaponinfo[plyr->readyweapon].ammo == am_noammo) + w_ready.num = &largeammo; + else + w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo]; + + w_ready.data = plyr->readyweapon; + + // STRIFE-TODO: Gobbledeegunk. + /* + v2 = dword_88490-- == 1; // no clue yet... + if(v2) + dword_DC7F4 = dword_DC7F0;*/ + + if(st_popupdisplaytics) + { + int tics = st_popupdisplaytics; + + --st_popupdisplaytics; + if(tics == 1) + { + st_displaypopup = false; + st_showkeys = false; + st_keypage = -1; + + if(st_dosizedisplay) + M_SizeDisplay(true); // mondo hack? + + st_dosizedisplay = false; + } + } + + // haleyjd 20100901: [STRIFE] Keys are handled on a popup + // haleyjd 20100831: [STRIFE] No face widget + // haleyjd 20100901: [STRIFE] Armor, weapons, frags, etc. handled elsewhere + + // haleyjd: This is from the PRE-BETA! Left here because it amuses me ;) + // get rid of chat window if up because of message + //if (!--st_msgcounter) + // st_chat = st_oldchat; +} + +static int st_palette = 0; + +// +// ST_doPaletteStuff +// +// haleyjd 20100831: [STRIFE] +// * Changed radsuit palette handling for Strife nukagecount. +// * All other logic verified to be unmodified. +// +void ST_doPaletteStuff(void) +{ + + int palette; + byte* pal; + int cnt; + int bzc; + + cnt = plyr->damagecount; + + if (plyr->powers[pw_strength]) + { + // slowly fade the berzerk out + bzc = 12 - (plyr->powers[pw_strength]>>6); + + if (bzc > cnt) + cnt = bzc; + } + + if (cnt) + { + palette = (cnt+7)>>3; + + if (palette >= NUMREDPALS) + palette = NUMREDPALS-1; + + palette += STARTREDPALS; + } + + else if (plyr->bonuscount) + { + palette = (plyr->bonuscount+7)>>3; + + if (palette >= NUMBONUSPALS) + palette = NUMBONUSPALS-1; + + palette += STARTBONUSPALS; + } + // haleyjd 20100831: [STRIFE] Flash green when in nukage, not when has + // an environment suit (a breathing sound is played to indicate that + // instead). + else if ( plyr->nukagecount > 16*TICRATE || + (plyr->nukagecount & 8)) + palette = RADIATIONPAL; + else + palette = 0; + + // haleyjd 08/31/10: Removed Chex Quest + + if (palette != st_palette) + { + st_palette = palette; + pal = (byte *) W_CacheLumpNum (lu_palette, PU_CACHE)+palette*768; + I_SetPalette (pal); + } + +} + +/* +void ST_drawWidgets(boolean refresh) +{ + haleyjd 09/01/10: [STRIFE] Removed +} +*/ + +// +// ST_drawNumFontY +// +// haleyjd 20100919: [STRIFE] New function +// Draws a small yellow number for inventory etc. +// +void ST_drawNumFontY(int x, int y, int num) +{ + if(!num) + V_DrawPatch(x, y, invfonty[0]); + + while(num) + { + V_DrawPatch(x, y, invfonty[num % 10]); + x -= SHORT(invfonty[0]->width) + 1; + num /= 10; + } +} + +// +// ST_drawNumFontY2 +// +// haleyjd 20100919: [STRIFE] New function +// As above, but turns negative numbers into zero. +// +void ST_drawNumFontY2(int x, int y, int num) +{ + if(!num) + V_DrawPatch(x, y, invfonty[0]); + + if(num < 0) + num = 0; + + while(num) + { + V_DrawPatchDirect(x, y, invfonty[num % 10]); + x -= SHORT(invfonty[0]->width) + 1; + num /= 10; + } +} + +// +// ST_drawLine +// +// haleyjd 20100920: [STRIFE] New function +// Basic horizontal line drawing routine used for the health bars. +// +void ST_drawLine(int x, int y, int len, int color) +{ + byte putcolor = (byte)(color); + byte *drawpos = I_VideoBuffer + y * SCREENWIDTH + x; + int i = 0; + + while(i < len) + { + *drawpos++ = putcolor; + ++i; + } +} + +// +// ST_doRefresh +// +// haleyjd 20100920: Evidence more than suggests that Rogue moved all status bar +// drawing down to this function. +// +void ST_doRefresh(void) +{ + // draw status bar background to off-screen buff + if (st_statusbaron) + { + int firstinventory, icon_x, num_x, i, numdrawn; + + // haleyjd 20100919: No backscreen caching in Strife. + //V_UseBuffer(st_backing_screen); + + // TODO: only sometimes drawing? + + plyr->st_update = false; + + // cache data + st_lastcursorpos = plyr->inventorycursor; + st_lastammo = weaponinfo[plyr->readyweapon].ammo; + st_lastarmortype = plyr->armortype; + st_lasthealth = plyr->health; + st_firsttime = false; + + // draw main status bar + V_DrawPatch(ST_X, ST_Y, invback); + + // draw multiplayer armor backdrop if netgame + // haleyjd 20131031: BUG - vanilla is accessing a NULL pointer here when + // playing back netdemos! It doesn't appear to draw anything, and there + // is no apparent ill effect on gameplay, so the best we can do is check. + if(netgame && stback) + V_DrawPatch(ST_X, 173, stback); + + if(plyr->inventorycursor >= 6) + firstinventory = plyr->inventorycursor - 5; + else + firstinventory = 0; + + // Draw cursor. + if(plyr->numinventory) + { + V_DrawPatch(35 * (plyr->inventorycursor - firstinventory) + 42, + 180, invcursor); + } + + // Draw inventory bar + for(num_x = 68, icon_x = 48, i = firstinventory, numdrawn = 0; + num_x < 278; + num_x += 35, icon_x += 35, i++, numdrawn++) + { + int lumpnum; + patch_t *patch; + char iconname[8]; + + if(plyr->numinventory <= numdrawn) + break; + + DEH_snprintf(iconname, sizeof(iconname), "I_%s", + DEH_String(sprnames[plyr->inventory[i].sprite])); + + lumpnum = W_CheckNumForName(iconname); + if(lumpnum == -1) + patch = W_CacheLumpName(DEH_String("STCFN063"), PU_CACHE); + else + patch = W_CacheLumpNum(lumpnum, PU_STATIC); + + V_DrawPatch(icon_x, 182, patch); + ST_drawNumFontY(num_x, 191, plyr->inventory[i].amount); + } + + // haleyjd 20100919: Draw sigil icon + if(plyr->weaponowned[wp_sigil]) + V_DrawPatch(253, 175, invsigil[plyr->sigiltype]); + + // haleyjd 20100919: Draw ammo + if(st_lastammo < NUMAMMO) + V_DrawPatch(290, 180, invammo[st_lastammo]); + + // haleyjd 20100919: Draw armor + if(plyr->armortype) + { + V_DrawPatch(2, 177, invarmor[plyr->armortype - 1]); + ST_drawNumFontY(20, 191, plyr->armorpoints); + } + + // haleyjd 20100920: Draw life bars. + { + int barlength; + int lifecolor1; + int lifecolor2; + + barlength = plyr->health; + if(barlength > 100) + barlength = 200 - plyr->health; + barlength *= 2; + + if(plyr->health < 11) // Danger, Will Robinson! + lifecolor1 = 64; + else if(plyr->health < 21) // Caution + lifecolor1 = 80; + else // All is well. + lifecolor1 = 96; + + if(plyr->cheats & CF_GODMODE) // Gold, probably a throwback to DOOM. + lifecolor1 = 226; + + lifecolor2 = lifecolor1 + 3; + + // Draw the normal health bars + ST_drawLine(49, 172, barlength, lifecolor1); + ST_drawLine(49, 173, barlength, lifecolor2); + ST_drawLine(49, 175, barlength, lifecolor1); + ST_drawLine(49, 176, barlength, lifecolor2); + + // Draw the > 100 health lines + if(plyr->health > 100) + { + int oldbarlength = barlength; + lifecolor1 = 112; // Shades of blue + lifecolor2 = lifecolor1 + 3; + + // take up the difference not drawn by the first (<= 100) bar + barlength = 200 - barlength; + + ST_drawLine(49 + oldbarlength, 172, barlength, lifecolor1); + ST_drawLine(49 + oldbarlength, 173, barlength, lifecolor2); + ST_drawLine(49 + oldbarlength, 175, barlength, lifecolor1); + ST_drawLine(49 + oldbarlength, 176, barlength, lifecolor2); + } + } // end local-scope block + + // haleyjd 20100919: nope, not in Strife. + //V_RestoreBuffer(); + //V_CopyRect(ST_X, 0, st_backing_screen, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y); + } +} + +// haleyjd [STRIFE]: Removed ST_diffDraw + +void ST_Drawer (boolean fullscreen, boolean refresh) +{ + st_statusbaron = (!fullscreen) || automapactive; + st_firsttime = st_firsttime || refresh; + + // Do red-/gold-shifts from damage/items + ST_doPaletteStuff(); + + // If just after ST_Start(), refresh all + ST_doRefresh(); + // Otherwise, update as little as possible + //ST_diffDraw(); [STRIFE]: nope +} + +// +// ST_calcFrags +// +// haleyjd [STRIFE] New function. +// Calculate frags for display on the frags popup. +// +static int ST_calcFrags(int pnum) +{ + int i; + int result = 0; + + for(i = 0; i < MAXPLAYERS; i++) + { + if(i == pnum) // self-frags + result -= players[pnum].frags[i]; + else + result += players[pnum].frags[i]; + } + + return result; +} + +// +// ST_drawTime +// +// villsa [STRIFE] New function. +// Draws game time on pop up screen +// +static void ST_drawTime(int x, int y, int time) +{ + int hours; + int minutes; + int seconds; + char string[16]; + + // haleyjd 20110213: fixed minutes + hours = time / 3600; + minutes = (time / 60) % 60; + seconds = time % 60; + + DEH_snprintf(string, 16, "%02d:%02d:%02d", hours, minutes, seconds); + HUlib_drawYellowText(x, y, string); +} + +#define ST_KEYSPERPAGE 10 +#define ST_KEYS_X 20 +#define ST_KEYS_Y 63 +#define ST_KEYNAME_X 17 +#define ST_KEYNAME_Y 4 +#define ST_KEYS_YSTEP 17 +#define ST_KEYS_NUMROWS 4 +#define ST_KEYS_COL2X 160 + +// +// ST_drawKeysPopup +// +// haleyjd 20110213: [STRIFE] New function +// This has taken the longest out of almost everything to get working properly. +// +static boolean ST_drawKeysPopup(void) +{ + int x, y, yt, key, keycount; + mobjinfo_t *info; + + V_DrawXlaPatch(0, 56, invpbak2); + V_DrawPatchDirect(0, 56, invpop2); + + if(deathmatch) + { + int pnum; + patch_t *colpatch; + char buffer[128]; + int frags; + + // In deathmatch, the keys popup is replaced by a chart of frag counts + + // first column + y = 64; + yt = 66; + for(pnum = 0; pnum < MAXPLAYERS/2; pnum++) + { + DEH_snprintf(buffer, sizeof(buffer), "stcolor%d", pnum+1); + colpatch = W_CacheLumpName(buffer, PU_CACHE); + V_DrawPatchDirect(28, y, colpatch); + frags = ST_calcFrags(pnum); + DEH_snprintf(buffer, sizeof(buffer), "%s%d", player_names[pnum], frags); + HUlib_drawYellowText(38, yt, buffer); + if(!playeringame[pnum]) + HUlib_drawYellowText(28, pnum*17 + 65, "X"); + y += 17; + yt += 17; + } + + // second column + y = 64; + yt = 66; + for(pnum = MAXPLAYERS/2; pnum < MAXPLAYERS; pnum++) + { + DEH_snprintf(buffer, sizeof(buffer), "stcolor%d", pnum+1); + colpatch = W_CacheLumpName(buffer, PU_CACHE); + V_DrawPatchDirect(158, y, colpatch); + frags = ST_calcFrags(pnum); + DEH_snprintf(buffer, sizeof(buffer), "%s%d", player_names[pnum], frags); + HUlib_drawYellowText(168, yt, buffer); + if(!playeringame[pnum]) + HUlib_drawYellowText(158, pnum*17 - 3, "X"); + y += 17; + yt += 17; + } + } + else + { + // Bounds-check page number + if(st_keypage < 0 || st_keypage > 2) + { + st_keypage = -1; + st_popupdisplaytics = 0; + st_displaypopup = false; + + return false; + } + + // Are there any keys to display on this page? + if(st_keypage > 0) + { + boolean haskeyinrange = false; + + for(key = ST_KEYSPERPAGE * st_keypage, keycount = 0; + keycount < ST_KEYSPERPAGE && key < NUMCARDS; + ++key, ++keycount) + { + if(plyr->cards[key]) + haskeyinrange = true; + } + + if(!haskeyinrange) + { + st_displaypopup = false; + st_showkeys = false; + st_keypage = -1; + + return false; + } + } + + // Draw the keys for the current page + key = ST_KEYSPERPAGE * st_keypage; + keycount = 0; + x = ST_KEYS_X; + y = ST_KEYS_Y; + info = &mobjinfo[MT_KEY_BASE + key]; + + for(; keycount < ST_KEYSPERPAGE && key < NUMCARDS; ++key, ++keycount, ++info) + { + char sprname[8]; + patch_t *patch; + memset(sprname, 0, sizeof(sprname)); + + if(plyr->cards[key]) + { + // Get spawnstate sprite name and load corresponding icon + DEH_snprintf(sprname, sizeof(sprname), "I_%s", + sprnames[states[info->spawnstate].sprite]); + patch = W_CacheLumpName(sprname, PU_CACHE); + V_DrawPatchDirect(x, y, patch); + HUlib_drawYellowText(x + ST_KEYNAME_X, y + ST_KEYNAME_Y, info->name); + } + + if(keycount != ST_KEYS_NUMROWS) + y += ST_KEYS_YSTEP; + else + { + x = ST_KEYS_COL2X; + y = ST_KEYS_Y; + } + } + } + + return true; +} + +// +// ST_DrawExternal +// +// haleyjd 20100901: [STRIFE] New function. +// * Draws external portions of the status bar such the top bar and popups. +// +boolean ST_DrawExternal(void) +{ + int i; + + if(st_statusbaron) + { + V_DrawPatchDirect(0, 160, invtop); + STlib_drawNumPositive(&w_health); + STlib_drawNumPositive(&w_ready); + } + else + { + ammotype_t ammo; + + ST_drawNumFontY2(15, 194, plyr->health); + ammo = weaponinfo[plyr->readyweapon].ammo; + if (ammo != am_noammo) + ST_drawNumFontY2(310, 194, plyr->ammo[ammo]); + } + + if(!st_displaypopup) + return false; + + // villsa [STRIFE] added 20100926 + if(st_showobjective) + { + V_DrawXlaPatch(0, 56, invpbak2); + V_DrawPatchDirect(0, 56, invpop2); + M_DialogDimMsg(24, 74, mission_objective, true); + HUlib_drawYellowText(24, 74, mission_objective); + ST_drawTime(210, 64, leveltime / TICRATE); + } + else + { + int keys = 0; + + // villsa [STRIFE] keys popup + if(st_showkeys || st_popupdisplaytics) + return ST_drawKeysPopup(); + + V_DrawXlaPatch(0, 56, invpbak); + V_DrawPatchDirect(0, 56, invpop); + + for(i = 0; i < NUMCARDS; i++) + { + if(plyr->cards[i]) + keys++; + } + + ST_drawNumFontY2(261, 132, keys); + + if(plyr->weaponowned[wp_elecbow]) + { + V_DrawPatchDirect(38, 86, + W_CacheLumpName(DEH_String("CBOWA0"), PU_CACHE)); + } + if(plyr->weaponowned[wp_rifle]) + { + V_DrawPatchDirect(40, 107, + W_CacheLumpName(DEH_String("RIFLA0"), PU_CACHE)); + } + if(plyr->weaponowned[wp_missile]) + { + V_DrawPatchDirect(39, 131, + W_CacheLumpName(DEH_String("MMSLA0"), PU_CACHE)); + } + if(plyr->weaponowned[wp_hegrenade]) + { + V_DrawPatchDirect(78, 87, + W_CacheLumpName(DEH_String("GRNDA0"), PU_CACHE)); + } + if(plyr->weaponowned[wp_flame]) + { + V_DrawPatchDirect(80, 117, + W_CacheLumpName(DEH_String("FLAMA0"), PU_CACHE)); + } + if(plyr->weaponowned[wp_mauler]) + { + V_DrawPatchDirect(75, 142, + W_CacheLumpName(DEH_String("TRPDA0"), PU_CACHE)); + } + + // haleyjd 20110213: draw ammo + for(i = 0; i < NUMAMMO; i++) + { + STlib_drawNumPositive(&w_ammo[i]); + STlib_drawNumPositive(&w_maxammo[i]); + } + + ST_drawNumFontY2(261, 84, plyr->accuracy); + ST_drawNumFontY2(261, 108, plyr->stamina); + + if(plyr->powers[pw_communicator]) + { + V_DrawPatchDirect(280, 130, + W_CacheLumpName(DEH_String("I_COMM"), PU_CACHE)); + } + } + + return true; +} + +typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + +// +// ST_loadUnloadGraphics +// +// Iterates through all graphics to be loaded or unloaded, along with +// the variable they use, invoking the specified callback function. +// +// [STRIFE] Altered to load all Strife status bar resources. +// +static void ST_loadUnloadGraphics(load_callback_t callback) +{ + int i; + char namebuf[9]; + + // haleyjd 20100901: [STRIFE] + // Load the numbers, green and yellow + for (i=0;i<10;i++) + { + DEH_snprintf(namebuf, 9, "INVFONG%d", i); + callback(namebuf, &invfontg[i]); + + DEH_snprintf(namebuf, 9, "INVFONY%d", i); + callback(namebuf, &invfonty[i]); + } + + // haleyjd 20100919: load Sigil patches + if(!isdemoversion) + { + for(i = 0; i < 5; i++) + { + DEH_snprintf(namebuf, 9, "I_SGL%d", i+1); + callback(namebuf, &invsigil[i]); + } + } + + // load ammo patches + for(i = 0; i < NUMAMMO; i++) + callback(DEH_String(invammonames[i]), &invammo[i]); + + // load armor patches + callback(DEH_String("I_ARM2"), &invarmor[0]); + callback(DEH_String("I_ARM1"), &invarmor[1]); + + // haleyjd 20100919: [STRIFE] + // * No face, but there is this patch, which appears behind the armor + DEH_snprintf(namebuf, 9, "STBACK0%d", consoleplayer + 1); + if(netgame) + callback(namebuf, &stback); + + // 20100901: + // * Removed all unused DOOM stuff (arms, numbers, %, etc). + + // haleyjd 20100901: [STRIFE]: stbar -> invback, added new patches + // status bar background bits + callback(DEH_String("INVBACK"), &invback); + callback(DEH_String("INVTOP"), &invtop); + callback(DEH_String("INVPOP"), &invpop); + callback(DEH_String("INVPOP2"), &invpop2); + callback(DEH_String("INVPBAK"), &invpbak); + callback(DEH_String("INVPBAK2"), &invpbak2); + callback(DEH_String("INVCURS"), &invcursor); +} + +static void ST_loadCallback(const char *lumpname, patch_t **variable) +{ + *variable = W_CacheLumpName(lumpname, PU_STATIC); +} + +void ST_loadGraphics(void) +{ + ST_loadUnloadGraphics(ST_loadCallback); +} + +void ST_loadData(void) +{ +// static int dword_8848C = 1; // STRIFE-TODO: what is the purpose of this? +// dword_8848C = 0; + + lu_palette = W_GetNumForName (DEH_String("PLAYPAL")); + ST_loadGraphics(); +} + +static void ST_unloadCallback(const char *lumpname, patch_t **variable) +{ + W_ReleaseLumpName(lumpname); + *variable = NULL; +} + +void ST_unloadGraphics(void) +{ + ST_loadUnloadGraphics(ST_unloadCallback); +} + +void ST_unloadData(void) +{ + ST_unloadGraphics(); +} + +// +// ST_initData +// +// haleyjd 20100901: [STRIFE] +// * Removed prebeta cruft, face stuff, keyboxes, and oldwe +// +void ST_initData(void) +{ + st_firsttime = true; + plyr = &players[consoleplayer]; + + st_statusbaron = true; + + st_palette = -1; + + STlib_init(); +} + + + +void ST_createWidgets(void) +{ + int i; + + // ready weapon ammo + STlib_initNum(&w_ready, + ST_AMMOX, + ST_AMMOY, + invfontg, + &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], + ST_AMMOWIDTH); + + // the last weapon type + w_ready.data = plyr->readyweapon; + + // health percentage + STlib_initNum(&w_health, + ST_HEALTHX, + ST_HEALTHY, + invfontg, + &plyr->health, + ST_HEALTHWIDTH); + + // haleyjd 20100831: [STRIFE] + // * No face. + // 20100901: + // * No arms, weaponsowned, frags, armor, keyboxes + + // haleyjd 20110213: Ammo Widgets!!! + for(i = 0; i < NUMAMMO; i++) + { + STlib_initNum(&w_ammo[i], ST_POPUPAMMOX, st_yforammo[i], + invfonty, &plyr->ammo[i], st_wforammo[i]); + + STlib_initNum(&w_maxammo[i], ST_POPUPMAXAMMOX, st_yforammo[i], + invfonty, &plyr->maxammo[i], st_wforammo[i]); + } +} + +static boolean st_stopped = true; + + +void ST_Start (void) +{ + if (!st_stopped) + ST_Stop(); + + ST_initData(); + ST_createWidgets(); + st_stopped = false; +} + +void ST_Stop (void) +{ + if (st_stopped) + return; + + I_SetPalette (W_CacheLumpNum (lu_palette, PU_CACHE)); + + st_stopped = true; +} + +void ST_Init (void) +{ + ST_loadData(); + + // haleyjd 20100919: This is not used by Strife. More memory for voices! + //st_backing_screen = (byte *) Z_Malloc(ST_WIDTH * ST_HEIGHT, PU_STATIC, 0); +} + diff --git a/games/NXDoom/src/strife/st_stuff.h b/games/NXDoom/src/strife/st_stuff.h new file mode 100644 index 00000000000..167888ed743 --- /dev/null +++ b/games/NXDoom/src/strife/st_stuff.h @@ -0,0 +1,80 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Status bar code. +// Does the face/direction indicator animatin. +// Does palette indicators as well (red pain/berserk, bright pickup) +// + +#ifndef __STSTUFF_H__ +#define __STSTUFF_H__ + +#include "doomtype.h" +#include "d_event.h" +#include "m_cheat.h" + +// Size of statusbar. +// Now sensitive for scaling. +#define ST_HEIGHT 32 +#define ST_WIDTH SCREENWIDTH +#define ST_Y (SCREENHEIGHT - ST_HEIGHT) + + +// +// STATUS BAR +// + +// Called by main loop. +boolean ST_Responder (event_t* ev); + +// Called by main loop. +void ST_Ticker (void); + +// Called by main loop. +void ST_Drawer (boolean fullscreen, boolean refresh); + +// haleyjd 09/01/10: [STRIFE] New function. +// Called by main loop to draw external status bar bits. +// Returns true if a popup is drawing. +boolean ST_DrawExternal(void); + +// Called when the console player is spawned on each level. +void ST_Start (void); + +// Called by startup code. +void ST_Init (void); + + + +extern byte *st_backing_screen; + +extern cheatseq_t cheat_mus; // [STRIFE]: idmus -> spin +extern cheatseq_t cheat_god; // [STRIFE]: iddqd -> omnipotent +extern cheatseq_t cheat_ammo; // [STRIFE]: idfa -> boomstix +extern cheatseq_t cheat_noclip; // [STRIFE]: idclip -> elvis +extern cheatseq_t cheat_clev; // [STRIFE]: idclev -> rift +extern cheatseq_t cheat_mypos; // [STRIFE]: idmypos -> gps +extern cheatseq_t cheat_scoot; // [STRIFE]: new cheat scoot +extern cheatseq_t cheat_nuke; // [STRIFE]: new cheat stonecold +extern cheatseq_t cheat_keys; // [STRIFE]: new cheat jimmy (all keys) +extern cheatseq_t cheat_stealth; // [STRIFE]: new cheat gripper +extern cheatseq_t cheat_midas; // [STRIFE]: new cheat +extern cheatseq_t cheat_lego; // [STRIFE]: new cheat +extern cheatseq_t cheat_dev; // [STRIFE]: new cheat + +extern cheatseq_t cheat_powerup[]; + + +#endif diff --git a/games/NXDoom/src/strife/strife_icon.c b/games/NXDoom/src/strife/strife_icon.c new file mode 100644 index 00000000000..93c43f9ad2f --- /dev/null +++ b/games/NXDoom/src/strife/strife_icon.c @@ -0,0 +1,2736 @@ +static int strife_icon_w = 128; +static int strife_icon_h = 128; + +static const unsigned int strife_icon_data[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, + 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, + 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, + 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, + 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, + 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, + 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, + 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, + 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, + 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, + 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, + 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, + 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, + 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, + 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, + 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, + 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, + 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, + 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, + 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, + 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, + 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, + 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, + 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, + 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, + 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, + 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, + 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, + 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, + 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, + 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, + 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, + 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, + 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, + 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, + 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, + 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, + 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, + 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, + 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, + 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, + 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, + 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, + 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, + 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, + 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, + 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, + 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, + 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, + 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, + 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, + 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, + 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, + 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, + 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, + 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, + 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, + 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, + 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, + 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, + 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x93756aff, 0x91766aff, 0xa89078ff, 0xb6a07fff, + 0xb6a07fff, 0xb6a07fff, 0xb6a07fff, 0xb6a07fff, 0xb6a07fff, 0xbca88bff, + 0xc7baa6ff, 0xc6b9a5ff, 0xc6b9a5ff, 0xc5b7a4ff, 0xc5b7a4ff, 0xc4b6a2ff, + 0xc3b5a0ff, 0xc3b5a0ff, 0xc2b49fff, 0xbba78bff, 0xb69e7bff, 0xb69d7bff, + 0xb69d7bff, 0xb69d7aff, 0xb59b79ff, 0xb39976ff, 0xb19774ff, 0xaf9572ff, + 0xae9573ff, 0xb3a188ff, 0xb3a38eff, 0xb1a18cff, 0xb0a08aff, 0xae9e88ff, + 0xac9c85ff, 0xab9a84ff, 0xa99883ff, 0xa79580ff, 0xa49179ff, 0x9a7d58ff, + 0x987b56ff, 0x977a55ff, 0x957852ff, 0x937550ff, 0x91734eff, 0x90724dff, + 0x8e704aff, 0x8c6e48ff, 0x8f7556ff, 0x93816aff, 0x917e68ff, 0x907d66ff, + 0x8e7a64ff, 0x8c7963ff, 0x8b7861ff, 0x89755fff, 0x86735cff, 0x86735cff, + 0x7c603eff, 0x775631ff, 0x755430ff, 0x785835ff, 0x7a5b3bff, 0x7d5c41ff, + 0x7f5f46ff, 0x74564aff, 0x5f464bff, 0x674e55ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, + 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, + 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, + 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, + 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, + 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, + 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, + 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, + 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, + 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, + 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, + 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, + 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, + 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, + 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, + 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, + 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, + 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, + 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, + 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, + 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, + 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, + 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, + 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, + 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, + 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, + 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, + 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, + 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, + 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, + 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, + 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, + 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, + 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, + 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, + 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, + 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, + 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, + 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, + 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, + 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, + 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, + 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, + 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, + 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, + 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, + 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, + 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, + 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, + 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, + 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfaf2b8ff, 0xfaf3bcff, + 0xf9f2baff, 0xf9f2baff, 0xf8f0b7ff, 0xf8efb7ff, 0xf7eeb5ff, 0xf7edb4ff, + 0xf6ecb3ff, 0xf8ecaaff, 0xffee97ff, 0xffee96ff, 0xffed95ff, 0xffec94ff, + 0xffec93ff, 0xffeb92ff, 0xffea90ff, 0xffe98fff, 0xffe88eff, 0xf7e49aff, + 0xf0e0a3ff, 0xefdea1ff, 0xefdea1ff, 0xeedd9fff, 0xecda9cff, 0xebd89aff, + 0xe9d698ff, 0xe8d596ff, 0xe6d293ff, 0xf3d67cff, 0xf5d676ff, 0xf3d373ff, + 0xf2d171ff, 0xf0cf6eff, 0xefcc6cff, 0xedca68ff, 0xecc867ff, 0xeac563ff, + 0xe5c367ff, 0xd7bd79ff, 0xd4ba78ff, 0xd2b876ff, 0xd1b674ff, 0xcfb472ff, + 0xceb271ff, 0xccb16fff, 0xcbaf6eff, 0xc9ad6cff, 0xcfac5eff, 0xd8ad4cff, + 0xd6aa4aff, 0xd5a848ff, 0xd3a646ff, 0xd2a545ff, 0xd0a243ff, 0xcfa042ff, + 0xcd9e40ff, 0xcc9d3eff, 0xbd9851ff, 0xb69658ff, 0xb59455ff, 0xb69659ff, + 0xb6965bff, 0xb7965dff, 0xb99761ff, 0xb99863ff, 0xba9966ff, 0xb99967ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcec71ff, 0xffef71ff, 0xffee70ff, 0xffed6eff, 0xffec6cff, 0xffeb6aff, + 0xffe969ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, + 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, + 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, + 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, + 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, + 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, + 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, + 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, + 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, + 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, + 0xffb027ff, 0xfcae26ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfceb6fff, 0xffee70ff, 0xffed6eff, 0xffec6cff, + 0xffeb6aff, 0xffe969ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, + 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, + 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, + 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, + 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, + 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, + 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, + 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, + 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, + 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xfcad25ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcea6eff, 0xffed6eff, + 0xffec6cff, 0xffeb6aff, 0xffe969ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, + 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, + 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, + 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, + 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, + 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, + 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, + 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, + 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, + 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xfcac25ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfce96cff, 0xffec6cff, 0xffeb6aff, 0xffe969ff, 0xffe867ff, 0xffe765ff, + 0xffe663ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, + 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, + 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, + 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, + 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, + 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, + 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, + 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, + 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, + 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, + 0xffae26ff, 0xfcab25ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfce86aff, 0xffeb6aff, 0xffe969ff, 0xffe867ff, + 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, + 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, + 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, + 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, + 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, + 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, + 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, + 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, + 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, + 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xfcab24ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfce768ff, 0xffe969ff, + 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, + 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, + 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, + 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, + 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, + 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, + 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, + 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, + 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, + 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, + 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xfcaa24ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfce567ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, + 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, + 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, + 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, + 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, + 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, + 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, + 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, + 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, + 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, + 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, + 0xffac25ff, 0xfca924ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfce465ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, + 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, + 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, + 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, + 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, + 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, + 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, + 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, + 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, + 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, + 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xfca823ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfce363ff, 0xffe663ff, + 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, + 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, + 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, + 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, + 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, + 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, + 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, + 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, + 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, + 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xfca823ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfce261ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, + 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, + 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, + 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, + 0xffcb3aff, 0xffca38ff, 0xe8bf48ff, 0xbfac62ff, 0x9f9c74ff, 0x90937aff, + 0x828a7fff, 0x7f877dff, 0x7e847aff, 0x7c8277ff, 0x7b7f74ff, 0x7a7d70ff, + 0x797a6dff, 0x77776aff, 0x767567ff, 0x757264ff, 0x737060ff, 0x726d5eff, + 0x706a5aff, 0x6f6757ff, 0x6d6454ff, 0x6c6250ff, 0x6c5f4eff, 0x796647ff, + 0xaf8539ff, 0xfcb42aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, + 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, + 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, + 0xffaa24ff, 0xfca723ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfce260ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, + 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, + 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, + 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, + 0xffcd3cff, 0xffcb3aff, 0xdbbb52ff, 0x959c82ff, 0x7c8e91ff, 0x7a8b8dff, + 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, + 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, + 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, + 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x987336ff, 0xfeb429ff, 0xffb429ff, + 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xfca622ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfce15eff, 0xffe35eff, + 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, + 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, + 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, + 0xffce3dff, 0xffcd3cff, 0xf7c740ff, 0xa6a47aff, 0x7d9194ff, 0x7c8e91ff, + 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, + 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, + 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, + 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x5b4c3eff, + 0xe6a027ff, 0xfeb228ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, + 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, + 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xfca522ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfce05cff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, + 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, + 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, + 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xedc348ff, 0x939c88ff, 0x7d9194ff, + 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, + 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, + 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, + 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, + 0x594b3fff, 0x58483bff, 0xca8c27ff, 0xeda425ff, 0xfeb128ff, 0xffb127ff, + 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, + 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, + 0xffa723ff, 0xfca522ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcdf5bff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, + 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, + 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, + 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xf6c742ff, 0x919b8aff, + 0x7d9194ff, 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, + 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, + 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, + 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, + 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0xc88b27ff, 0xe49b24ff, + 0xeca124ff, 0xfeaf27ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, + 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, + 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xfca421ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcde59ff, 0xffdf59ff, + 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, + 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, + 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xfecb3bff, + 0x9fa180ff, 0x7d9194ff, 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, + 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, + 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, + 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, + 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, + 0xc88926ff, 0xe49b23ff, 0xe49a23ff, 0xeca024ff, 0xfeae26ff, 0xffae26ff, + 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, + 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xfca321ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcdc57ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, + 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, + 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, + 0xffcb3aff, 0xcdb55dff, 0x7d9194ff, 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, + 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, + 0x6f7572ff, 0x6d726eff, 0x797563ff, 0x9c834eff, 0xa28648ff, 0xa18446ff, + 0xa08244ff, 0x746954ff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, + 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, + 0x554335ff, 0x544031ff, 0xca8b25ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, + 0xed9f23ff, 0xfeac26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, + 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, + 0xffa522ff, 0xfca221ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcdb55ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, + 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, + 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, + 0xffcd3cff, 0xffcb3aff, 0xfac83bff, 0x8b978aff, 0x7c8e91ff, 0x7a8b8dff, + 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, + 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x998452ff, 0xe2a529ff, 0xe4a528ff, + 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, 0x826e4bff, 0x625c53ff, 0x615950ff, + 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, + 0x574538ff, 0x554335ff, 0x544031ff, 0x58412eff, 0xdd9623ff, 0xe49a23ff, + 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xed9f22ff, 0xfeab25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, + 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xfca120ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcda54ff, 0xffdc54ff, + 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, + 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, + 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xd2b657ff, 0x7c8e91ff, + 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, + 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x727268ff, 0xdda42bff, + 0xe4a528ff, 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, 0xe4a227ff, 0x816d48ff, + 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, + 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x9f6e26ff, + 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, + 0xee9e23ff, 0xfea924ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, + 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xfca120ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcd952ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, + 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, + 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, + 0xa9a271ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, + 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, + 0x83785cff, 0xe4a528ff, 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, 0xe4a227ff, + 0xe4a127ff, 0x806a46ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, + 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x674a2cff, + 0xb27a25ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xe79922ff, + 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xef9e22ff, 0xfea824ff, 0xffa823ff, + 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, + 0xffa321ff, 0xfca020ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcd850ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, + 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, + 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, + 0xffc937ff, 0xffc835ff, 0x849086ff, 0x79888aff, 0x778586ff, 0x768383ff, + 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, + 0x6c6f6bff, 0x6b6c68ff, 0x736f5fff, 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, + 0xe4a227ff, 0xe4a127ff, 0xe4a127ff, 0x92733eff, 0x5e5349ff, 0x5c5146ff, + 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x694d2fff, + 0xae7827ff, 0xe19923ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, + 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, + 0xf09d21ff, 0xfea623ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, + 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xfc9f1fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcd74eff, 0xffd94fff, + 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, + 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, + 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xf9c437ff, 0x79888aff, 0x778586ff, + 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, + 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0xbc8f38ff, + 0xe4a327ff, 0xe4a227ff, 0xe4a127ff, 0xe4a127ff, 0xe4a126ff, 0xca912dff, + 0x5e5246ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x674f33ff, + 0xab772aff, 0xe19a23ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe69923ff, + 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, + 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xef9c21ff, 0xfea522ff, 0xffa522ff, + 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xfc9e1fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcd64dff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, + 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, + 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xecbd3dff, + 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, + 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, + 0x66645dff, 0x716755ff, 0xd3992eff, 0xe4a127ff, 0xe4a127ff, 0xe4a126ff, + 0xe4a026ff, 0xe49f26ff, 0xbf8a2dff, 0x765c3aff, 0x5e4b3aff, 0x735634ff, + 0xaf7b2bff, 0xe19a24ff, 0xe49b23ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, + 0xe69923ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, + 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, + 0xf09920ff, 0xfea322ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, + 0xffa020ff, 0xfc9e1fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcd54bff, 0xffd74bff, 0xffd54aff, 0xffd448ff, + 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, + 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, + 0xffc631ff, 0xebbc3dff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, + 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, + 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x73644eff, 0xce942eff, + 0xe4a126ff, 0xe4a026ff, 0xe49f26ff, 0xe49f25ff, 0xe49e25ff, 0xe49d25ff, + 0xe49c24ff, 0xe49c24ff, 0xe49b24ff, 0xe49b23ff, 0xe49a23ff, 0xe49a23ff, + 0xe59a22ff, 0xe69923ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, + 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, + 0xea961fff, 0xeb951fff, 0xeb941fff, 0xf1981fff, 0xfea221ff, 0xffa221ff, + 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xfc9d1eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcd44aff, 0xffd54aff, + 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, + 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, + 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xf6c035ff, 0x75807fff, 0x737d7cff, + 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, + 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, + 0x615950ff, 0x675a4aff, 0xb38433ff, 0xe49f26ff, 0xe49f25ff, 0xe49e25ff, + 0xe49d25ff, 0xe49c24ff, 0xe49c24ff, 0xe49b24ff, 0xe49b23ff, 0xe49a23ff, + 0xe49a23ff, 0xe59a22ff, 0xe69923ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, + 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, + 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, + 0xf29820ff, 0xfea020ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xfc9c1eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcd249ff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, + 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, + 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xfec32fff, + 0x798079ff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, + 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, + 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x876839ff, + 0xd89727ff, 0xe49d25ff, 0xe49c24ff, 0xe49c24ff, 0xe49b24ff, 0xe49b23ff, + 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xe79922ff, + 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, + 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, + 0xeb941eff, 0xec941fff, 0xec931eff, 0xf3971fff, 0xfe9f20ff, 0xff9f1fff, + 0xff9e1fff, 0xfc9b1eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcd147ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, + 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, + 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, + 0xffc32fff, 0xffc32fff, 0x9b8f64ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, + 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, + 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, + 0x5b4e42ff, 0x594b3fff, 0x655039ff, 0xb8812aff, 0xe49c24ff, 0xe49b24ff, + 0xe49b23ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, + 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, + 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, + 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, + 0xf3961eff, 0xfe9d1fff, 0xff9d1fff, 0xfc9b1dff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcd045ff, 0xffd244ff, + 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, + 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, + 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xc2a24dff, 0x6f7572ff, + 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, + 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, + 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, + 0x88622cff, 0xdb9524ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, + 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, + 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, + 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, + 0xee931eff, 0xed921dff, 0xee921dff, 0xf3951eff, 0xfe9c1eff, 0xfc9a1dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfccf43ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, + 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, + 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, + 0xf7bb31ff, 0x777869ff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, + 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, + 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, + 0x554335ff, 0x544031ff, 0x523d2eff, 0x60442aff, 0xba7e24ff, 0xe59a22ff, + 0xe59922ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, + 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, + 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, + 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, + 0xf4941dff, 0xfb981dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcce42ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, + 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, + 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, + 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xba9a4aff, 0x6b6c68ff, 0x696a64ff, + 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, + 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, + 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, + 0x4f3624ff, 0x926120ff, 0xe39822ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, + 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, + 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, + 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, + 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf2921bff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfccd40ff, 0xffcf3fff, + 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, + 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, + 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xfdbd2dff, + 0x8f7e56ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, + 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, + 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, + 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x71481cff, 0xdb9022ff, + 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, + 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, + 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, + 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xee8e1bff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfccc3eff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, + 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, + 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, + 0xffbe2dff, 0xffbd2dff, 0xf1b431ff, 0x7f7255ff, 0x65615aff, 0x635e57ff, + 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, + 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, + 0x513a2aff, 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, + 0x492c1aff, 0x603d1bff, 0xd48a20ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, + 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, + 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, + 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, + 0xf08f1cff, 0xef8e1bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfccb3cff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, + 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, + 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, + 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xf2b330ff, + 0x82704fff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, + 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, + 0x523d2eff, 0x513a2aff, 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, + 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x5b391bff, 0xd78d20ff, + 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, + 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, + 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, + 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xef8d1aff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcca3bff, 0xffcb3aff, + 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, + 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, + 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, + 0xffbb2cff, 0xffba2bff, 0xfab62dff, 0xa38141ff, 0x60574cff, 0x5e5349ff, + 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, + 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, + 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, + 0x442b1aff, 0x5d3b1bff, 0xdf9020ff, 0xe99720ff, 0xea961fff, 0xeb951fff, + 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, + 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, + 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf08c1aff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcc839ff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, + 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, + 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, + 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, + 0xdda230ff, 0x816840ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, + 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, 0x4e3524ff, + 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, + 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x734a1cff, 0xe9951fff, + 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, + 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, + 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, + 0xf28e1bff, 0xf08d1aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcc737ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, + 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, + 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, + 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, + 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xfeb529ff, 0xc28e31ff, 0x6a543aff, + 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, + 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, + 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, + 0x3f291aff, 0xa6691dff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, + 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, + 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, + 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf08c19ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcc636ff, 0xffc835ff, + 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, + 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, + 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, + 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, + 0xffb429ff, 0xfbb128ff, 0xc08a2dff, 0x6d5130ff, 0x523d2eff, 0x513a2aff, + 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, + 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, + 0x40291aff, 0x3f291aff, 0x3e281aff, 0x4b311bff, 0xe08d1eff, 0xeb941eff, + 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, + 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, + 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf18c19ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcc534ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, + 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, + 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, + 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, + 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xfcaf27ff, + 0xbd8428ff, 0x674827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, + 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, + 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, + 0x8f5b1bff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, + 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, + 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, + 0xf38d1aff, 0xf18b19ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcc432ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, + 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, + 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, + 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, + 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xfcad26ff, 0xb87c24ff, 0x5a391eff, + 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, + 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, + 0x3b271aff, 0x3a271aff, 0x49301bff, 0xe8911eff, 0xed931eff, 0xee931eff, + 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, + 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, + 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf28b19ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcc330ff, 0xffc530ff, + 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, + 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, + 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, + 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, + 0xffad26ff, 0xf3a425ff, 0x8e5c1eff, 0x472c1aff, 0x462c1aff, 0x452b1aff, + 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, + 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0xb6721dff, + 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, + 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, + 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf18a19ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcc22fff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, + 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, + 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, + 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, + 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, + 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xae731fff, + 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, + 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, + 0x37261aff, 0x81531bff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, + 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, + 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, + 0xf58c19ff, 0xf28a19ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcc12fff, 0xffc32fff, 0xffc32fff, 0xffc22fff, + 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, + 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, + 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, + 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0x925f1eff, 0x432a1aff, 0x412a1aff, 0x40291aff, + 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, + 0x38261aff, 0x37261aff, 0x35251aff, 0x593b1bff, 0xee921dff, 0xee911dff, + 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, + 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, + 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf28919ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcc02eff, 0xffc32fff, + 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, + 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, + 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, + 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, + 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, + 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xef9e22ff, 0x452c1aff, + 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, + 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x38261aff, + 0xea8f1dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, + 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, + 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf38a19ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcc02eff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, + 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, + 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, + 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, + 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, + 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, + 0xffa723ff, 0x5d3d1bff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, + 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, + 0x33241aff, 0x32241bff, 0xe18a1cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, + 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, + 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, + 0xf58b19ff, 0xf38819ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcbf2eff, 0xffc12eff, 0xffc02eff, 0xffc02eff, + 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, + 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, + 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, + 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, + 0xffa823ff, 0xffa723ff, 0xffa723ff, 0x68441bff, 0x3e281aff, 0x3d281aff, + 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, + 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0xd7841bff, 0xf0911cff, + 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, + 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, + 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf48719ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcbe2dff, 0xffc02eff, + 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, + 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, + 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, + 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, + 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0x5b3b1bff, + 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, + 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, + 0xcf7e1cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, + 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, + 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf48718ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcbd2dff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, + 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, + 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, + 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, + 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, + 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, + 0xf8a022ff, 0x412a1aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, + 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, + 0x2f231bff, 0x2e221bff, 0xdd841cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, + 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, + 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, + 0xf78818ff, 0xf48718ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcbd2dff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, + 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, + 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, + 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, + 0xffa622ff, 0xffa522ff, 0xcb8320ff, 0x3b271aff, 0x3a271aff, 0x39261aff, + 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, + 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2f241bff, 0xed8e1cff, 0xf18f1cff, + 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, + 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, + 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf58717ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcbc2cff, 0xffbe2dff, + 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, + 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, + 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, + 0xfcae27ff, 0xf8aa26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, + 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, + 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0x764c1cff, 0x3a271aff, + 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, + 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x4a321bff, + 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, + 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, + 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf58616ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcbb2cff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, + 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, + 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, + 0xf4a928ff, 0x8e6327ff, 0x543824ff, 0x4e3320ff, 0x7b501fff, 0xd28d23ff, + 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, + 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xb8761eff, + 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, + 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, + 0x2c211bff, 0x85531cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, + 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, + 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, + 0xf88816ff, 0xf68516ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcba2cff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, + 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, + 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0x875e27ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, + 0x4a2d1aff, 0x492c1aff, 0x744b1dff, 0xd18a22ff, 0xffaa24ff, 0xffa924ff, + 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xfda322ff, + 0xa96c1eff, 0x3e291aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, + 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, + 0x2d221bff, 0x2c211bff, 0x2b211bff, 0xc5761bff, 0xf28e1bff, 0xf28e1bff, + 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, + 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, + 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf78516ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb92bff, 0xffbc2cff, + 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, + 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xf3a827ff, 0x4f3624ff, 0x4d3220ff, + 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, + 0x724a1dff, 0xd08921ff, 0xffa723ff, 0xffa723ff, 0xfba422ff, 0xd88b20ff, + 0xa86d1fff, 0x56381bff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, + 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, + 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x2b211bff, 0x5e3e1bff, 0xf28e1bff, + 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, + 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, + 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xf68515ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcb92bff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, + 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, + 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xe59d25ff, + 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, + 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x55361bff, 0x4b301aff, + 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, + 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, + 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x2b211bff, 0x2b221bff, + 0xcb781bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, + 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, + 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, + 0xfa8715ff, 0xf78415ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcb82bff, 0xffba2bff, 0xffb92bff, 0xffb92bff, + 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, + 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xf8a926ff, 0x4f321dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, + 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, + 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, + 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, + 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x2b211bff, + 0x29211bff, 0x90591bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, + 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, + 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, + 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xf78315ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb72aff, 0xffb92bff, + 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, + 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, + 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0x7e521eff, 0x492c1aff, + 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, + 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, + 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, + 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x2c211bff, + 0x2b211bff, 0x29211bff, 0x6e471bff, 0xf18d1bff, 0xf28d1aff, 0xf38d1aff, + 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, + 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, + 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xf88315ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcb62aff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, + 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, + 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, + 0xd69023ff, 0x482d1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, + 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, + 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, + 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, + 0x2c211bff, 0x2b211bff, 0x29211bff, 0x81511bff, 0xef8c1bff, 0xf28d1aff, + 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, + 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, + 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, + 0xfa8414ff, 0xf88315ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcb62aff, 0xffb82aff, 0xffb72aff, 0xffb62aff, + 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, + 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xa96f1fff, 0x452b1aff, 0x442b1aff, + 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, + 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, + 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, + 0x2d221bff, 0x2c211bff, 0x2b211bff, 0x3f2d1bff, 0xac671bff, 0xf28e1bff, + 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, + 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, + 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, + 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xf98215ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb529ff, 0xffb72aff, + 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, + 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, + 0xb47620ff, 0x52341bff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, + 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, + 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, + 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x4a321bff, 0x935c1bff, 0xeb891bff, + 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, + 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, + 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, + 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xf88114ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcb429ff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, + 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, + 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, + 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xec9a22ff, 0xb1731eff, 0x8e5b1cff, + 0x83541cff, 0x83531cff, 0x81521cff, 0x81521cff, 0x80521cff, 0x80521cff, + 0x80521cff, 0x7f511cff, 0x7e501cff, 0x7e501cff, 0x7d501cff, 0x7d4f1bff, + 0x7c4f1bff, 0x7f501cff, 0x8f5a1bff, 0xa4641bff, 0xd37e1cff, 0xf28f1bff, + 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, + 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, + 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, + 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, + 0xfb8314ff, 0xf98014ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcb329ff, 0xffb629ff, 0xffb529ff, 0xffb429ff, + 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, + 0xf49e21ff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, + 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, + 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, + 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, + 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, + 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, + 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, + 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfa8014ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb328ff, 0xffb529ff, + 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, + 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, + 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, + 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xf49c21ff, 0xeb941eff, 0xeb941eff, + 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, + 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, + 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, + 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, + 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, + 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, + 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfa7f13ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcb228ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, + 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, + 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, + 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, + 0xf59c20ff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, + 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, + 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, + 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, + 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, + 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, + 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, + 0xfd8113ff, 0xfb7f13ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcb128ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, + 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, + 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, + 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, + 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xf59a1fff, 0xed931eff, 0xee931eff, + 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, + 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, + 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, + 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, + 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, + 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, + 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfb7e13ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb027ff, 0xffb328ff, + 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, + 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, + 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, + 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, + 0xf69a1fff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, + 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, + 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, + 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, + 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, + 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, + 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfb7f12ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcb027ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, + 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, + 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, + 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, + 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xf6971eff, 0xee911dff, 0xef921cff, + 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, + 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, + 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, + 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, + 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, + 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, + 0xfe8012ff, 0xfb7e12ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcb027ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, + 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, + 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, + 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, + 0xf7971eff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, + 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, + 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, + 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, + 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, + 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, + 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xfc7e12ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcaf26ff, 0xffb027ff, + 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, + 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, + 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, + 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, + 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xf7951eff, 0xf0901cff, 0xf08f1cff, + 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, + 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, + 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, + 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, + 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, + 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xfc7d11ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcae26ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, + 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, + 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, + 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, + 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, + 0xf7941dff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, + 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, + 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, + 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, + 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, + 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, + 0xff7e11ff, 0xfc7d11ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcae26ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, + 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, + 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, + 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, + 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, + 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xf8931bff, 0xf28e1bff, 0xf28e1bff, + 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, + 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, + 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, + 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, + 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, + 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xfc7c11ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcad25ff, 0xffae26ff, + 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, + 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, + 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, + 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, + 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, + 0xf8921bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, + 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, + 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, + 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, + 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, + 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xfc7b10ff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcac25ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, + 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, + 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, + 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, + 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, + 0xff971cff, 0xff971cff, 0xff961bff, 0xf9911aff, 0xf38c1aff, 0xf48d1aff, + 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, + 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, + 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, + 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, + 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, + 0xff7c10ff, 0xfc7a10ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfcab25ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, + 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, + 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, + 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, + 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, + 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, + 0xfa901aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, + 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, + 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, + 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, + 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, + 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xfc7a10ff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcab24ff, 0xffac25ff, + 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, + 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, + 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, + 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, + 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, + 0xff941bff, 0xff941bff, 0xff931aff, 0xf98e19ff, 0xf58b1aff, 0xf58b19ff, + 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, + 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, + 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, + 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, + 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xfc790fff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfcaa24ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, + 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, + 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, + 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, + 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, + 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, + 0xfa8e18ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, + 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, + 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, + 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, + 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, + 0xff7a0fff, 0xfc780fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfca924ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, + 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, + 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, + 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, + 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, + 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, + 0xff911aff, 0xff9119ff, 0xff9019ff, 0xfa8c18ff, 0xf78818ff, 0xf78918ff, + 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, + 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, + 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, + 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, + 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xfc770fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfca823ff, 0xffaa24ff, + 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, + 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, + 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, + 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, + 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, + 0xff921aff, 0xff911aff, 0xff9119ff, 0xff9019ff, 0xff8f19ff, 0xff8e18ff, + 0xfb8c17ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, + 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, + 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, + 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, + 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xff780fff, 0xfc770eff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfca823ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, + 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, + 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, + 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, + 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, + 0xff931aff, 0xff921aff, 0xff911aff, 0xff9119ff, 0xff9019ff, 0xff8f19ff, + 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, 0xfc8a17ff, 0xf98716ff, 0xf98616ff, + 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, + 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, + 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, + 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xff780fff, + 0xff780eff, 0xfc760eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xfca723ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, + 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, + 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, + 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, + 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, + 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, 0xff9119ff, 0xff9019ff, + 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, 0xff8c17ff, 0xff8b17ff, + 0xfb8817ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, + 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, + 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, + 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, 0xff790fff, + 0xff780fff, 0xff780eff, 0xff770eff, 0xfc750eff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xec9921ff, 0xffa723ff, + 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, + 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, + 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, + 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, + 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, 0xff9119ff, + 0xff9019ff, 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, 0xff8c17ff, + 0xff8b17ff, 0xff8a17ff, 0xff8a16ff, 0xfc8716ff, 0xfa8515ff, 0xfa8414ff, + 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, + 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, + 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, + 0xff790fff, 0xff780fff, 0xff780eff, 0xff770eff, 0xff760eff, 0xeb6b0dff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc9791dea, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, + 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, + 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, + 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, + 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, + 0xff9119ff, 0xff9019ff, 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, + 0xff8c17ff, 0xff8b17ff, 0xff8a17ff, 0xff8a16ff, 0xff8916ff, 0xff8816ff, + 0xfc8515ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, + 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, + 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, + 0xff7a0fff, 0xff790fff, 0xff780fff, 0xff780eff, 0xff770eff, 0xff760eff, + 0xff750dff, 0xc85b10e9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xb4622622, 0xd3821df7, 0xffa522ff, 0xffa422ff, + 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, + 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, + 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, + 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, + 0xff911aff, 0xff9119ff, 0xff9019ff, 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, + 0xff8d18ff, 0xff8c17ff, 0xff8b17ff, 0xff8a17ff, 0xff8a16ff, 0xff8916ff, + 0xff8816ff, 0xff8715ff, 0xff8715ff, 0xfd8415ff, 0xfb8314ff, 0xfc8214ff, + 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, + 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, + 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xff780fff, 0xff780eff, 0xff770eff, + 0xff760eff, 0xff750dff, 0xd25f10f6, 0xaf502020, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xb4631b4b, 0xba671d97, 0xb7661c9b, 0xb7661c9b, 0xb7661c9b, 0xb7661c9b, + 0xb7661c9b, 0xb7641a9b, 0xb7641a9b, 0xb7641a9b, 0xb7641a9b, 0xb7641a9b, + 0xb7631a9b, 0xb7631a9b, 0xb7631a9b, 0xb7631a9b, 0xb763199b, 0xb761199b, + 0xb761199b, 0xb761199b, 0xb761199b, 0xb75f199b, 0xb75f199b, 0xb75f199b, + 0xb75f199b, 0xb75f199b, 0xb75f199b, 0xb75e199b, 0xb75e199b, 0xb75e179b, + 0xb75e179b, 0xb75e179b, 0xb75c179b, 0xb75c179b, 0xb75c179b, 0xb75c179b, + 0xb75c179b, 0xb75a179b, 0xb75a179b, 0xb75a179b, 0xb75a179b, 0xb759159b, + 0xb759159b, 0xb759159b, 0xb759159b, 0xb759159b, 0xb757159b, 0xb757159b, + 0xb757159b, 0xb757159b, 0xb757159b, 0xb757159b, 0xb756159b, 0xb756149b, + 0xb756149b, 0xb756149b, 0xb756149b, 0xb754149b, 0xb754149b, 0xb754149b, + 0xb754149b, 0xb752149b, 0xba531397, 0xb452114b, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; diff --git a/games/NXDoom/src/strife/wi_stuff.c b/games/NXDoom/src/strife/wi_stuff.c new file mode 100644 index 00000000000..f8193b19bb1 --- /dev/null +++ b/games/NXDoom/src/strife/wi_stuff.c @@ -0,0 +1,1836 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Intermission screens. +// + +// haleyjd 08/23/2010: There is no intermission in Strife +#if 0 +#include + +#include "z_zone.h" + +#include "m_random.h" + +#include "deh_main.h" +#include "i_swap.h" +#include "i_system.h" + +#include "w_wad.h" + +#include "g_game.h" + +#include "r_local.h" +#include "s_sound.h" + +#include "doomstat.h" + +// Data. +#include "sounds.h" + +// Needs access to LFB. +#include "v_video.h" + +#include "wi_stuff.h" + +// +// Data needed to add patches to full screen intermission pics. +// Patches are statistics messages, and animations. +// Loads of by-pixel layout and placement, offsets etc. +// + + +// +// Different vetween registered DOOM (1994) and +// Ultimate DOOM - Final edition (retail, 1995?). +// This is supposedly ignored for commercial +// release (aka DOOM II), which had 34 maps +// in one episode. So there. +#define NUMEPISODES 4 +#define NUMMAPS 9 + + +// in tics +//U #define PAUSELEN (TICRATE*2) +//U #define SCORESTEP 100 +//U #define ANIMPERIOD 32 +// pixel distance from "(YOU)" to "PLAYER N" +//U #define STARDIST 10 +//U #define WK 1 + + +// GLOBAL LOCATIONS +#define WI_TITLEY 2 +#define WI_SPACINGY 33 + +// SINGPLE-PLAYER STUFF +#define SP_STATSX 50 +#define SP_STATSY 50 + +#define SP_TIMEX 16 +#define SP_TIMEY (SCREENHEIGHT-32) + + +// NET GAME STUFF +#define NG_STATSY 50 +#define NG_STATSX (32 + SHORT(star->width)/2 + 32*!dofrags) + +#define NG_SPACINGX 64 + + +// DEATHMATCH STUFF +#define DM_MATRIXX 42 +#define DM_MATRIXY 68 + +#define DM_SPACINGX 40 + +#define DM_TOTALSX 269 + +#define DM_KILLERSX 10 +#define DM_KILLERSY 100 +#define DM_VICTIMSX 5 +#define DM_VICTIMSY 50 + + + + +typedef enum +{ + ANIM_ALWAYS, + ANIM_RANDOM, + ANIM_LEVEL + +} animenum_t; + +typedef struct +{ + int x; + int y; + +} point_t; + + +// +// Animation. +// There is another anim_t used in p_spec. +// +typedef struct +{ + animenum_t type; + + // period in tics between animations + int period; + + // number of animation frames + int nanims; + + // location of animation + point_t loc; + + // ALWAYS: n/a, + // RANDOM: period deviation (<256), + // LEVEL: level + int data1; + + // ALWAYS: n/a, + // RANDOM: random base period, + // LEVEL: n/a + int data2; + + // actual graphics for frames of animations + patch_t* p[3]; + + // following must be initialized to zero before use! + + // next value of bcnt (used in conjunction with period) + int nexttic; + + // last drawn animation frame + int lastdrawn; + + // next frame number to animate + int ctr; + + // used by RANDOM and LEVEL when animating + int state; + +} anim_t; + + +static point_t lnodes[NUMEPISODES][NUMMAPS] = +{ + // Episode 0 World Map + { + { 185, 164 }, // location of level 0 (CJ) + { 148, 143 }, // location of level 1 (CJ) + { 69, 122 }, // location of level 2 (CJ) + { 209, 102 }, // location of level 3 (CJ) + { 116, 89 }, // location of level 4 (CJ) + { 166, 55 }, // location of level 5 (CJ) + { 71, 56 }, // location of level 6 (CJ) + { 135, 29 }, // location of level 7 (CJ) + { 71, 24 } // location of level 8 (CJ) + }, + + // Episode 1 World Map should go here + { + { 254, 25 }, // location of level 0 (CJ) + { 97, 50 }, // location of level 1 (CJ) + { 188, 64 }, // location of level 2 (CJ) + { 128, 78 }, // location of level 3 (CJ) + { 214, 92 }, // location of level 4 (CJ) + { 133, 130 }, // location of level 5 (CJ) + { 208, 136 }, // location of level 6 (CJ) + { 148, 140 }, // location of level 7 (CJ) + { 235, 158 } // location of level 8 (CJ) + }, + + // Episode 2 World Map should go here + { + { 156, 168 }, // location of level 0 (CJ) + { 48, 154 }, // location of level 1 (CJ) + { 174, 95 }, // location of level 2 (CJ) + { 265, 75 }, // location of level 3 (CJ) + { 130, 48 }, // location of level 4 (CJ) + { 279, 23 }, // location of level 5 (CJ) + { 198, 48 }, // location of level 6 (CJ) + { 140, 25 }, // location of level 7 (CJ) + { 281, 136 } // location of level 8 (CJ) + } + +}; + + +// +// Animation locations for episode 0 (1). +// Using patches saves a lot of space, +// as they replace 320x200 full screen frames. +// + +#define ANIM(type, period, nanims, x, y, nexttic) \ + { (type), (period), (nanims), { (x), (y) }, (nexttic), \ + 0, { NULL, NULL, NULL }, 0, 0, 0, 0 } + + +static anim_t epsd0animinfo[] = +{ + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0), +}; + +static anim_t epsd1animinfo[] = +{ + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7), + ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8), + ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8), +}; + +static anim_t epsd2animinfo[] = +{ + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0), + ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0), + ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0), +}; + +static int NUMANIMS[NUMEPISODES] = +{ + arrlen(epsd0animinfo), + arrlen(epsd1animinfo), + arrlen(epsd2animinfo), +}; + +static anim_t *anims[NUMEPISODES] = +{ + epsd0animinfo, + epsd1animinfo, + epsd2animinfo +}; + + +// +// GENERAL DATA +// + +// +// Locally used stuff. +// + +// States for single-player +#define SP_KILLS 0 +#define SP_ITEMS 2 +#define SP_SECRET 4 +#define SP_FRAGS 6 +#define SP_TIME 8 +#define SP_PAR ST_TIME + +#define SP_PAUSE 1 + +// in seconds +#define SHOWNEXTLOCDELAY 4 +//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY + + +// used to accelerate or skip a stage +static int acceleratestage; + +// wbs->pnum +static int me; + + // specifies current state +static stateenum_t state; + +// contains information passed into intermission +static wbstartstruct_t* wbs; + +static wbplayerstruct_t* plrs; // wbs->plyr[] + +// used for general timing +static int cnt; + +// used for timing of background animation +static int bcnt; + +// signals to refresh everything for one frame +static int firstrefresh; + +static int cnt_kills[MAXPLAYERS]; +static int cnt_items[MAXPLAYERS]; +static int cnt_secret[MAXPLAYERS]; +static int cnt_time; +static int cnt_par; +static int cnt_pause; + +// # of commercial levels +static int NUMCMAPS; + + +// +// GRAPHICS +// + +// You Are Here graphic +static patch_t* yah[3] = { NULL, NULL, NULL }; + +// splat +static patch_t* splat[2] = { NULL, NULL }; + +// %, : graphics +static patch_t* percent; +static patch_t* colon; + +// 0-9 graphic +static patch_t* num[10]; + +// minus sign +static patch_t* wiminus; + +// "Finished!" graphics +static patch_t* finished; + +// "Entering" graphic +static patch_t* entering; + +// "secret" +static patch_t* sp_secret; + + // "Kills", "Scrt", "Items", "Frags" +static patch_t* kills; +static patch_t* secret; +static patch_t* items; +static patch_t* frags; + +// Time sucks. +static patch_t* timepatch; +static patch_t* par; +static patch_t* sucks; + +// "killers", "victims" +static patch_t* killers; +static patch_t* victims; + +// "Total", your face, your dead face +static patch_t* total; +static patch_t* star; +static patch_t* bstar; + +// "red P[1..MAXPLAYERS]" +static patch_t* p[MAXPLAYERS]; + +// "gray P[1..MAXPLAYERS]" +static patch_t* bp[MAXPLAYERS]; + + // Name graphics of each level (centered) +static patch_t** lnames; + +// Buffer storing the backdrop +static patch_t *background; + +// +// CODE +// + +// slam background +void WI_slamBackground(void) +{ + V_DrawPatch(0, 0, background); +} + +// The ticker is used to detect keys +// because of timing issues in netgames. +boolean WI_Responder(event_t* ev) +{ + return false; +} + + +// Draws " Finished!" +void WI_drawLF(void) +{ + int y = WI_TITLEY; + + if (gamemode != commercial || wbs->last < NUMCMAPS) + { + // draw + V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2, + y, lnames[wbs->last]); + + // draw "Finished!" + y += (5*SHORT(lnames[wbs->last]->height))/4; + + V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); + } + else if (wbs->last == NUMCMAPS) + { + // MAP33 - nothing is displayed! + } + else if (wbs->last > NUMCMAPS) + { + // > MAP33. Doom bombs out here with a Bad V_DrawPatch error. + // I'm pretty sure that doom2.exe is just reading into random + // bits of memory at this point, but let's try to be accurate + // anyway. This deliberately triggers a V_DrawPatch error. + + patch_t tmp = { SCREENWIDTH, SCREENHEIGHT, 1, 1, + { 0, 0, 0, 0, 0, 0, 0, 0 } }; + + V_DrawPatch(0, y, &tmp); + } +} + + + +// Draws "Entering " +void WI_drawEL(void) +{ + int y = WI_TITLEY; + + // draw "Entering" + V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2, + y, + entering); + + // draw level + y += (5*SHORT(lnames[wbs->next]->height))/4; + + V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2, + y, + lnames[wbs->next]); + +} + +void +WI_drawOnLnode +( int n, + patch_t* c[] ) +{ + + int i; + int left; + int top; + int right; + int bottom; + boolean fits = false; + + i = 0; + do + { + left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset); + top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset); + right = left + SHORT(c[i]->width); + bottom = top + SHORT(c[i]->height); + + if (left >= 0 + && right < SCREENWIDTH + && top >= 0 + && bottom < SCREENHEIGHT) + { + fits = true; + } + else + { + i++; + } + } while (!fits && i!=2 && c[i] != NULL); + + if (fits && i<2) + { + V_DrawPatch(lnodes[wbs->epsd][n].x, + lnodes[wbs->epsd][n].y, + c[i]); + } + else + { + // DEBUG + printf("Could not place patch on level %d", n+1); + } +} + + + +void WI_initAnimatedBack(void) +{ + int i; + anim_t* a; + + if (gamemode == commercial) + return; + + if (wbs->epsd > 2) + return; + + for (i=0;iepsd];i++) + { + a = &anims[wbs->epsd][i]; + + // init variables + a->ctr = -1; + + // specify the next time to draw it + if (a->type == ANIM_ALWAYS) + a->nexttic = bcnt + 1 + (M_Random()%a->period); + else if (a->type == ANIM_RANDOM) + a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1); + else if (a->type == ANIM_LEVEL) + a->nexttic = bcnt + 1; + } + +} + +void WI_updateAnimatedBack(void) +{ + int i; + anim_t* a; + + if (gamemode == commercial) + return; + + if (wbs->epsd > 2) + return; + + for (i=0;iepsd];i++) + { + a = &anims[wbs->epsd][i]; + + if (bcnt == a->nexttic) + { + switch (a->type) + { + case ANIM_ALWAYS: + if (++a->ctr >= a->nanims) a->ctr = 0; + a->nexttic = bcnt + a->period; + break; + + case ANIM_RANDOM: + a->ctr++; + if (a->ctr == a->nanims) + { + a->ctr = -1; + a->nexttic = bcnt+a->data2+(M_Random()%a->data1); + } + else a->nexttic = bcnt + a->period; + break; + + case ANIM_LEVEL: + // gawd-awful hack for level anims + if (!(state == StatCount && i == 7) + && wbs->next == a->data1) + { + a->ctr++; + if (a->ctr == a->nanims) a->ctr--; + a->nexttic = bcnt + a->period; + } + break; + } + } + + } + +} + +void WI_drawAnimatedBack(void) +{ + int i; + anim_t* a; + + if (gamemode == commercial) + return; + + if (wbs->epsd > 2) + return; + + for (i=0 ; iepsd] ; i++) + { + a = &anims[wbs->epsd][i]; + + if (a->ctr >= 0) + V_DrawPatch(a->loc.x, a->loc.y, a->p[a->ctr]); + } + +} + +// +// Draws a number. +// If digits > 0, then use that many digits minimum, +// otherwise only use as many as necessary. +// Returns new x position. +// + +int +WI_drawNum +( int x, + int y, + int n, + int digits ) +{ + + int fontwidth = SHORT(num[0]->width); + int neg; + int temp; + + if (digits < 0) + { + if (!n) + { + // make variable-length zeros 1 digit long + digits = 1; + } + else + { + // figure out # of digits in # + digits = 0; + temp = n; + + while (temp) + { + temp /= 10; + digits++; + } + } + } + + neg = n < 0; + if (neg) + n = -n; + + // if non-number, do not draw it + if (n == 1994) + return 0; + + // draw the new number + while (digits--) + { + x -= fontwidth; + V_DrawPatch(x, y, num[ n % 10 ]); + n /= 10; + } + + // draw a minus sign if necessary + if (neg) + V_DrawPatch(x-=8, y, wiminus); + + return x; + +} + +void +WI_drawPercent +( int x, + int y, + int p ) +{ + if (p < 0) + return; + + V_DrawPatch(x, y, percent); + WI_drawNum(x, y, p, -1); +} + + + +// +// Display level completion time and par, +// or "sucks" message if overflow. +// +void +WI_drawTime +( int x, + int y, + int t ) +{ + + int div; + int n; + + if (t<0) + return; + + if (t <= 61*59) + { + div = 1; + + do + { + n = (t / div) % 60; + x = WI_drawNum(x, y, n, 2) - SHORT(colon->width); + div *= 60; + + // draw + if (div==60 || t / div) + V_DrawPatch(x, y, colon); + + } while (t / div); + } + else + { + // "sucks" + V_DrawPatch(x - SHORT(sucks->width), y, sucks); + } +} + + +void WI_End(void) +{ + void WI_unloadData(void); + WI_unloadData(); +} + +void WI_initNoState(void) +{ + state = NoState; + acceleratestage = 0; + cnt = 10; +} + +void WI_updateNoState(void) { + + WI_updateAnimatedBack(); + + if (!--cnt) + { + // Don't call WI_End yet. G_WorldDone doesnt immediately + // change gamestate, so WI_Drawer is still going to get + // run until that happens. If we do that after WI_End + // (which unloads all the graphics), we're in trouble. + //WI_End(); + G_WorldDone(); + } + +} + +static boolean snl_pointeron = false; + + +void WI_initShowNextLoc(void) +{ + state = ShowNextLoc; + acceleratestage = 0; + cnt = SHOWNEXTLOCDELAY * TICRATE; + + WI_initAnimatedBack(); +} + +void WI_updateShowNextLoc(void) +{ + WI_updateAnimatedBack(); + + if (!--cnt || acceleratestage) + WI_initNoState(); + else + snl_pointeron = (cnt & 31) < 20; +} + +void WI_drawShowNextLoc(void) +{ + + int i; + int last; + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + + if ( gamemode != commercial) + { + if (wbs->epsd > 2) + { + WI_drawEL(); + return; + } + + last = (wbs->last == 8) ? wbs->next - 1 : wbs->last; + + // draw a splat on taken cities. + for (i=0 ; i<=last ; i++) + WI_drawOnLnode(i, splat); + + // splat the secret level? + if (wbs->didsecret) + WI_drawOnLnode(8, splat); + + // draw flashing ptr + if (snl_pointeron) + WI_drawOnLnode(wbs->next, yah); + } + + // draws which level you are entering.. + if ( (gamemode != commercial) + || wbs->next != 30) + WI_drawEL(); + +} + +void WI_drawNoState(void) +{ + snl_pointeron = true; + WI_drawShowNextLoc(); +} + +int WI_fragSum(int playernum) +{ + int i; + int frags = 0; + + for (i=0 ; i 99) + dm_frags[i][j] = 99; + + if (dm_frags[i][j] < -99) + dm_frags[i][j] = -99; + + stillticking = true; + } + } + dm_totals[i] = WI_fragSum(i); + + if (dm_totals[i] > 99) + dm_totals[i] = 99; + + if (dm_totals[i] < -99) + dm_totals[i] = -99; + } + + } + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + dm_state++; + } + + } + else if (dm_state == 4) + { + if (acceleratestage) + { + S_StartSound(0, sfx_slop); + + if ( gamemode == commercial) + WI_initNoState(); + else + WI_initShowNextLoc(); + } + } + else if (dm_state & 1) + { + if (!--cnt_pause) + { + dm_state++; + cnt_pause = TICRATE; + } + } +} + + + +void WI_drawDeathmatchStats(void) +{ + + int i; + int j; + int x; + int y; + int w; + + int lh; // line height + + lh = WI_SPACINGY; + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + WI_drawLF(); + + // draw stat titles (top line) + V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2, + DM_MATRIXY-WI_SPACINGY+10, + total); + + V_DrawPatch(DM_KILLERSX, DM_KILLERSY, killers); + V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, victims); + + // draw P? + x = DM_MATRIXX + DM_SPACINGX; + y = DM_MATRIXY; + + for (i=0 ; iwidth)/2, + DM_MATRIXY - WI_SPACINGY, + p[i]); + + V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, + y, + p[i]); + + if (i == me) + { + V_DrawPatch(x-SHORT(p[i]->width)/2, + DM_MATRIXY - WI_SPACINGY, + bstar); + + V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, + y, + star); + } + } + else + { + // V_DrawPatch(x-SHORT(bp[i]->width)/2, + // DM_MATRIXY - WI_SPACINGY, bp[i]); + // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2, + // y, bp[i]); + } + x += DM_SPACINGX; + y += WI_SPACINGY; + } + + // draw stats + y = DM_MATRIXY+10; + w = SHORT(num[0]->width); + + for (i=0 ; imaxkills; + cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; + cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; + + if (dofrags) + cnt_frags[i] = WI_fragSum(i); + } + S_StartSound(0, sfx_barexp); + ng_state = 10; + } + + if (ng_state == 2) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (plrs[i].skills * 100) / wbs->maxkills) + cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; + else + stillticking = true; + } + + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + ng_state++; + } + } + else if (ng_state == 4) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (plrs[i].sitems * 100) / wbs->maxitems) + cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; + else + stillticking = true; + } + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + ng_state++; + } + } + else if (ng_state == 6) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (plrs[i].ssecret * 100) / wbs->maxsecret) + cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; + else + stillticking = true; + } + + if (!stillticking) + { + S_StartSound(0, sfx_barexp); + ng_state += 1 + 2*!dofrags; + } + } + else if (ng_state == 8) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + stillticking = false; + + for (i=0 ; i= (fsum = WI_fragSum(i))) + cnt_frags[i] = fsum; + else + stillticking = true; + } + + if (!stillticking) + { + S_StartSound(0, sfx_pldeth); + ng_state++; + } + } + else if (ng_state == 10) + { + if (acceleratestage) + { + S_StartSound(0, sfx_sgcock); + if ( gamemode == commercial ) + WI_initNoState(); + else + WI_initShowNextLoc(); + } + } + else if (ng_state & 1) + { + if (!--cnt_pause) + { + ng_state++; + cnt_pause = TICRATE; + } + } +} + + + +void WI_drawNetgameStats(void) +{ + int i; + int x; + int y; + int pwidth = SHORT(percent->width); + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + + WI_drawLF(); + + // draw stat titles (top line) + V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width), + NG_STATSY, kills); + + V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width), + NG_STATSY, items); + + V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width), + NG_STATSY, secret); + + if (dofrags) + V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width), + NG_STATSY, frags); + + // draw stats + y = NG_STATSY + SHORT(kills->height); + + for (i=0 ; iwidth), y, p[i]); + + if (i == me) + V_DrawPatch(x-SHORT(p[i]->width), y, star); + + x += NG_SPACINGX; + WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX; + WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX; + WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX; + + if (dofrags) + WI_drawNum(x, y+10, cnt_frags[i], -1); + + y += WI_SPACINGY; + } + +} + +static int sp_state; + +void WI_initStats(void) +{ + state = StatCount; + acceleratestage = 0; + sp_state = 1; + cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1; + cnt_time = cnt_par = -1; + cnt_pause = TICRATE; + + WI_initAnimatedBack(); +} + +void WI_updateStats(void) +{ + + WI_updateAnimatedBack(); + + if (acceleratestage && sp_state != 10) + { + acceleratestage = 0; + cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; + cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; + cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; + cnt_time = plrs[me].stime / TICRATE; + cnt_par = wbs->partime / TICRATE; + S_StartSound(0, sfx_barexp); + sp_state = 10; + } + + if (sp_state == 2) + { + cnt_kills[0] += 2; + + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills) + { + cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + else if (sp_state == 4) + { + cnt_items[0] += 2; + + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems) + { + cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + else if (sp_state == 6) + { + cnt_secret[0] += 2; + + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret) + { + cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + + else if (sp_state == 8) + { + if (!(bcnt&3)) + S_StartSound(0, sfx_pistol); + + cnt_time += 3; + + if (cnt_time >= plrs[me].stime / TICRATE) + cnt_time = plrs[me].stime / TICRATE; + + cnt_par += 3; + + if (cnt_par >= wbs->partime / TICRATE) + { + cnt_par = wbs->partime / TICRATE; + + if (cnt_time >= plrs[me].stime / TICRATE) + { + S_StartSound(0, sfx_barexp); + sp_state++; + } + } + } + else if (sp_state == 10) + { + if (acceleratestage) + { + S_StartSound(0, sfx_sgcock); + + if (gamemode == commercial) + WI_initNoState(); + else + WI_initShowNextLoc(); + } + } + else if (sp_state & 1) + { + if (!--cnt_pause) + { + sp_state++; + cnt_pause = TICRATE; + } + } + +} + +void WI_drawStats(void) +{ + // line height + int lh; + + lh = (3*SHORT(num[0]->height))/2; + + WI_slamBackground(); + + // draw animated background + WI_drawAnimatedBack(); + + WI_drawLF(); + + V_DrawPatch(SP_STATSX, SP_STATSY, kills); + WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]); + + V_DrawPatch(SP_STATSX, SP_STATSY+lh, items); + WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]); + + V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, sp_secret); + WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]); + + V_DrawPatch(SP_TIMEX, SP_TIMEY, timepatch); + WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time); + + if (wbs->epsd < 3) + { + V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par); + WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par); + } + +} + +void WI_checkForAccelerate(void) +{ + int i; + player_t *player; + + // check for button presses to skip delays + for (i=0, player = players ; icmd.buttons & BT_ATTACK) + { + if (!player->attackdown) + acceleratestage = 1; + player->attackdown = true; + } + else + player->attackdown = false; + if (player->cmd.buttons & BT_USE) + { + if (!player->usedown) + acceleratestage = 1; + player->usedown = true; + } + else + player->usedown = false; + } + } +} + + + +// Updates stuff each tick +void WI_Ticker(void) +{ + // counter for general background animation + bcnt++; + + if (bcnt == 1) + { + // intermission music + if ( gamemode == commercial ) + S_ChangeMusic(mus_dm2int, true); + else + S_ChangeMusic(mus_inter, true); + } + + WI_checkForAccelerate(); + + switch (state) + { + case StatCount: + if (deathmatch) WI_updateDeathmatchStats(); + else if (netgame) WI_updateNetgameStats(); + else WI_updateStats(); + break; + + case ShowNextLoc: + WI_updateShowNextLoc(); + break; + + case NoState: + WI_updateNoState(); + break; + } + +} + +typedef void (*load_callback_t)(char *lumpname, patch_t **variable); + +// Common load/unload function. Iterates over all the graphics +// lumps to be loaded/unloaded into memory. + +static void WI_loadUnloadData(load_callback_t callback) +{ + int i, j; + char name[9]; + anim_t *a; + + if (gamemode == commercial) + { + for (i=0 ; iepsd, i); + callback(name, &lnames[i]); + } + + // you are here + callback(DEH_String("WIURH0"), &yah[0]); + + // you are here (alt.) + callback(DEH_String("WIURH1"), &yah[1]); + + // splat + callback(DEH_String("WISPLAT"), &splat[0]); + + if (wbs->epsd < 3) + { + for (j=0;jepsd];j++) + { + a = &anims[wbs->epsd][j]; + for (i=0;inanims;i++) + { + // MONDO HACK! + if (wbs->epsd != 1 || j != 8) + { + // animations + DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i); + callback(name, &a->p[i]); + } + else + { + // HACK ALERT! + a->p[i] = anims[1][4].p[i]; + } + } + } + } + } + + // More hacks on minus sign. + callback(DEH_String("WIMINUS"), &wiminus); + + for (i=0;i<10;i++) + { + // numbers 0-9 + DEH_snprintf(name, 9, "WINUM%d", i); + callback(name, &num[i]); + } + + // percent sign + callback(DEH_String("WIPCNT"), &percent); + + // "finished" + callback(DEH_String("WIF"), &finished); + + // "entering" + callback(DEH_String("WIENTER"), &entering); + + // "kills" + callback(DEH_String("WIOSTK"), &kills); + + // "scrt" + callback(DEH_String("WIOSTS"), &secret); + + // "secret" + callback(DEH_String("WISCRT2"), &sp_secret); + + // french wad uses WIOBJ (?) + if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0) + { + // "items" + if (netgame && !deathmatch) + callback(DEH_String("WIOBJ"), &items); + else + callback(DEH_String("WIOSTI"), &items); + } else { + callback(DEH_String("WIOSTI"), &items); + } + + // "frgs" + callback(DEH_String("WIFRGS"), &frags); + + // ":" + callback(DEH_String("WICOLON"), &colon); + + // "time" + callback(DEH_String("WITIME"), &timepatch); + + // "sucks" + callback(DEH_String("WISUCKS"), &sucks); + + // "par" + callback(DEH_String("WIPAR"), &par); + + // "killers" (vertical) + callback(DEH_String("WIKILRS"), &killers); + + // "victims" (horiz) + callback(DEH_String("WIVCTMS"), &victims); + + // "total" + callback(DEH_String("WIMSTT"), &total); + + for (i=0 ; iepsd == 3) + { + M_StringCopy(name, DEH_String("INTERPIC"), sizeof(name)); + name[8] = '\0'; + } + else + { + DEH_snprintf(name, 9, "WIMAP%d", wbs->epsd); + } + + // Draw backdrop and save to a temporary buffer + + callback(name, &background); +} + +static void WI_loadCallback(char *name, patch_t **variable) +{ + *variable = W_CacheLumpName(name, PU_STATIC); +} + +void WI_loadData(void) +{ + if (gamemode == commercial) + { + NUMCMAPS = 32; + lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS, + PU_STATIC, NULL); + } + else + { + lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS, + PU_STATIC, NULL); + } + + WI_loadUnloadData(WI_loadCallback); + + // These two graphics are special cased because we're sharing + // them with the status bar code + + // your face + star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC); + + // dead face + bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC); +} + +static void WI_unloadCallback(char *name, patch_t **variable) +{ + W_ReleaseLumpName(name); + *variable = NULL; +} + +void WI_unloadData(void) +{ + WI_loadUnloadData(WI_unloadCallback); + + // We do not free these lumps as they are shared with the status + // bar code. + + // W_ReleaseLumpName("STFST01"); + // W_ReleaseLumpName("STFDEAD0"); +} + +void WI_Drawer (void) +{ + switch (state) + { + case StatCount: + if (deathmatch) + WI_drawDeathmatchStats(); + else if (netgame) + WI_drawNetgameStats(); + else + WI_drawStats(); + break; + + case ShowNextLoc: + WI_drawShowNextLoc(); + break; + + case NoState: + WI_drawNoState(); + break; + } +} + + +void WI_initVariables(wbstartstruct_t* wbstartstruct) +{ + + wbs = wbstartstruct; + +#ifdef RANGECHECKING + if (gamemode != commercial) + { + if ( gamemode == retail ) + RNGCHECK(wbs->epsd, 0, 3); + else + RNGCHECK(wbs->epsd, 0, 2); + } + else + { + RNGCHECK(wbs->last, 0, 8); + RNGCHECK(wbs->next, 0, 8); + } + RNGCHECK(wbs->pnum, 0, MAXPLAYERS); + RNGCHECK(wbs->pnum, 0, MAXPLAYERS); +#endif + + acceleratestage = 0; + cnt = bcnt = 0; + firstrefresh = 1; + me = wbs->pnum; + plrs = wbs->plyr; + + if (!wbs->maxkills) + wbs->maxkills = 1; + + if (!wbs->maxitems) + wbs->maxitems = 1; + + if (!wbs->maxsecret) + wbs->maxsecret = 1; + + if ( gamemode != retail ) + if (wbs->epsd > 2) + wbs->epsd -= 3; +} + +void WI_Start(wbstartstruct_t* wbstartstruct) +{ + WI_initVariables(wbstartstruct); + WI_loadData(); + + if (deathmatch) + WI_initDeathmatchStats(); + else if (netgame) + WI_initNetgameStats(); + else + WI_initStats(); +} +#endif diff --git a/games/NXDoom/src/strife/wi_stuff.h b/games/NXDoom/src/strife/wi_stuff.h new file mode 100644 index 00000000000..88ed1c63612 --- /dev/null +++ b/games/NXDoom/src/strife/wi_stuff.h @@ -0,0 +1,51 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Intermission. +// + +#ifndef __WI_STUFF__ +#define __WI_STUFF__ + +// haleyjd 08/23/2010: Strife does not have an intermission +#if 0 +//#include "v_video.h" + +#include "doomdef.h" + +// States for the intermission + +typedef enum +{ + NoState = -1, + StatCount, + ShowNextLoc, +} stateenum_t; + +// Called by main loop, animate the intermission. +void WI_Ticker (void); + +// Called by main loop, +// draws the intermission directly into the screen buffer. +void WI_Drawer (void); + +// Setup for an intermission screen. +void WI_Start(wbstartstruct_t* wbstartstruct); + +// Shut down the intermission screen +void WI_End(void); + +#endif +#endif diff --git a/games/NXDoom/src/tables.c b/games/NXDoom/src/tables.c new file mode 100644 index 00000000000..698ae98f571 --- /dev/null +++ b/games/NXDoom/src/tables.c @@ -0,0 +1,2227 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Lookup tables. +// Do not try to look them up :-). +// In the order of appearance: +// +// int finetangent[4096] - Tangens LUT. +// Should work with BAM fairly well (12 of 16bit, +// effectively, by shifting). +// +// int finesine[10240] - Sine lookup. +// Guess what, serves as cosine, too. +// Remarkable thing is, how to use BAMs with this? +// +// int tantoangle[2049] - ArcTan LUT, +// maps tan(angle) to angle fast. Gotta search. +// +// + +#include "tables.h" + +// to get a global angle from cartesian coordinates, the coordinates are +// flipped until they are in the first octant of the coordinate system, then +// the y (<=x) is scaled and divided by x to get a tangent (slope) value +// which is looked up in the tantoangle[] table. The +1 size is to handle +// the case when x==y without additional checking. + +int SlopeDiv(unsigned int num, unsigned int den) +{ + unsigned ans; + + if (den < 512) + { + return SLOPERANGE; + } + else + { + ans = (num << 3) / (den >> 8); + + if (ans <= SLOPERANGE) + { + return ans; + } + else + { + return SLOPERANGE; + } + } +} + +const fixed_t finetangent[4096] = +{ + -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683, + -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368, + -5178251,-4882318,-4618375,-4381502,-4167737,-3973855,-3797206,-3635590, + -3487165,-3350381,-3223918,-3106651,-2997613,-2895966,-2800983,-2712030, + -2628549,-2550052,-2476104,-2406322,-2340362,-2277919,-2218719,-2162516, + -2109087,-2058233,-2009771,-1963536,-1919378,-1877161,-1836758,-1798063, + -1760956,-1725348,-1691149,-1658278,-1626658,-1596220,-1566898,-1538632, + -1511367,-1485049,-1459630,-1435065,-1411312,-1388330,-1366084,-1344537, + -1323658,-1303416,-1283783,-1264730,-1246234,-1228269,-1210813,-1193846, + -1177345,-1161294,-1145673,-1130465,-1115654,-1101225,-1087164,-1073455, + -1060087,-1047046,-1034322,-1021901,-1009774,-997931,-986361,-975054, + -964003,-953199,-942633,-932298,-922186,-912289,-902602,-893117, + -883829,-874730,-865817,-857081,-848520,-840127,-831898,-823827, + -815910,-808143,-800521,-793041,-785699,-778490,-771411,-764460, + -757631,-750922,-744331,-737853,-731486,-725227,-719074,-713023, + -707072,-701219,-695462,-689797,-684223,-678737,-673338,-668024, + -662792,-657640,-652568,-647572,-642651,-637803,-633028,-628323, + -623686,-619117,-614613,-610174,-605798,-601483,-597229,-593033, + -588896,-584815,-580789,-576818,-572901,-569035,-565221,-561456, + -557741,-554074,-550455,-546881,-543354,-539870,-536431,-533034, + -529680,-526366,-523094,-519861,-516667,-513512,-510394,-507313, + -504269,-501261,-498287,-495348,-492443,-489571,-486732,-483925, + -481150,-478406,-475692,-473009,-470355,-467730,-465133,-462565, + -460024,-457511,-455024,-452564,-450129,-447720,-445337,-442978, + -440643,-438332,-436045,-433781,-431540,-429321,-427125,-424951, + -422798,-420666,-418555,-416465,-414395,-412344,-410314,-408303, + -406311,-404338,-402384,-400448,-398530,-396630,-394747,-392882, + -391034,-389202,-387387,-385589,-383807,-382040,-380290,-378555, + -376835,-375130,-373440,-371765,-370105,-368459,-366826,-365208, + -363604,-362013,-360436,-358872,-357321,-355783,-354257,-352744, + -351244,-349756,-348280,-346816,-345364,-343924,-342495,-341078, + -339671,-338276,-336892,-335519,-334157,-332805,-331464,-330133, + -328812,-327502,-326201,-324910,-323629,-322358,-321097,-319844, + -318601,-317368,-316143,-314928,-313721,-312524,-311335,-310154, + -308983,-307819,-306664,-305517,-304379,-303248,-302126,-301011, + -299904,-298805,-297714,-296630,-295554,-294485,-293423,-292369, + -291322,-290282,-289249,-288223,-287204,-286192,-285186,-284188, + -283195,-282210,-281231,-280258,-279292,-278332,-277378,-276430, + -275489,-274553,-273624,-272700,-271782,-270871,-269965,-269064, + -268169,-267280,-266397,-265519,-264646,-263779,-262917,-262060, + -261209,-260363,-259522,-258686,-257855,-257029,-256208,-255392, + -254581,-253774,-252973,-252176,-251384,-250596,-249813,-249035, + -248261,-247492,-246727,-245966,-245210,-244458,-243711,-242967, + -242228,-241493,-240763,-240036,-239314,-238595,-237881,-237170, + -236463,-235761,-235062,-234367,-233676,-232988,-232304,-231624, + -230948,-230275,-229606,-228941,-228279,-227621,-226966,-226314, + -225666,-225022,-224381,-223743,-223108,-222477,-221849,-221225, + -220603,-219985,-219370,-218758,-218149,-217544,-216941,-216341, + -215745,-215151,-214561,-213973,-213389,-212807,-212228,-211652, + -211079,-210509,-209941,-209376,-208815,-208255,-207699,-207145, + -206594,-206045,-205500,-204956,-204416,-203878,-203342,-202809, + -202279,-201751,-201226,-200703,-200182,-199664,-199149,-198636, + -198125,-197616,-197110,-196606,-196105,-195606,-195109,-194614, + -194122,-193631,-193143,-192658,-192174,-191693,-191213,-190736, + -190261,-189789,-189318,-188849,-188382,-187918,-187455,-186995, + -186536,-186080,-185625,-185173,-184722,-184274,-183827,-183382, + -182939,-182498,-182059,-181622,-181186,-180753,-180321,-179891, + -179463,-179037,-178612,-178190,-177769,-177349,-176932,-176516, + -176102,-175690,-175279,-174870,-174463,-174057,-173653,-173251, + -172850,-172451,-172053,-171657,-171263,-170870,-170479,-170089, + -169701,-169315,-168930,-168546,-168164,-167784,-167405,-167027, + -166651,-166277,-165904,-165532,-165162,-164793,-164426,-164060, + -163695,-163332,-162970,-162610,-162251,-161893,-161537,-161182, + -160828,-160476,-160125,-159775,-159427,-159079,-158734,-158389, + -158046,-157704,-157363,-157024,-156686,-156349,-156013,-155678, + -155345,-155013,-154682,-154352,-154024,-153697,-153370,-153045, + -152722,-152399,-152077,-151757,-151438,-151120,-150803,-150487, + -150172,-149859,-149546,-149235,-148924,-148615,-148307,-148000, + -147693,-147388,-147084,-146782,-146480,-146179,-145879,-145580, + -145282,-144986,-144690,-144395,-144101,-143808,-143517,-143226, + -142936,-142647,-142359,-142072,-141786,-141501,-141217,-140934, + -140651,-140370,-140090,-139810,-139532,-139254,-138977,-138701, + -138426,-138152,-137879,-137607,-137335,-137065,-136795,-136526, + -136258,-135991,-135725,-135459,-135195,-134931,-134668,-134406, + -134145,-133884,-133625,-133366,-133108,-132851,-132594,-132339, + -132084,-131830,-131576,-131324,-131072,-130821,-130571,-130322, + -130073,-129825,-129578,-129332,-129086,-128841,-128597,-128353, + -128111,-127869,-127627,-127387,-127147,-126908,-126669,-126432, + -126195,-125959,-125723,-125488,-125254,-125020,-124787,-124555, + -124324,-124093,-123863,-123633,-123404,-123176,-122949,-122722, + -122496,-122270,-122045,-121821,-121597,-121374,-121152,-120930, + -120709,-120489,-120269,-120050,-119831,-119613,-119396,-119179, + -118963,-118747,-118532,-118318,-118104,-117891,-117678,-117466, + -117254,-117044,-116833,-116623,-116414,-116206,-115998,-115790, + -115583,-115377,-115171,-114966,-114761,-114557,-114354,-114151, + -113948,-113746,-113545,-113344,-113143,-112944,-112744,-112546, + -112347,-112150,-111952,-111756,-111560,-111364,-111169,-110974, + -110780,-110586,-110393,-110200,-110008,-109817,-109626,-109435, + -109245,-109055,-108866,-108677,-108489,-108301,-108114,-107927, + -107741,-107555,-107369,-107184,-107000,-106816,-106632,-106449, + -106266,-106084,-105902,-105721,-105540,-105360,-105180,-105000, + -104821,-104643,-104465,-104287,-104109,-103933,-103756,-103580, + -103404,-103229,-103054,-102880,-102706,-102533,-102360,-102187, + -102015,-101843,-101671,-101500,-101330,-101159,-100990,-100820, + -100651,-100482,-100314,-100146,-99979,-99812,-99645,-99479, + -99313,-99148,-98982,-98818,-98653,-98489,-98326,-98163, + -98000,-97837,-97675,-97513,-97352,-97191,-97030,-96870, + -96710,-96551,-96391,-96233,-96074,-95916,-95758,-95601, + -95444,-95287,-95131,-94975,-94819,-94664,-94509,-94354, + -94200,-94046,-93892,-93739,-93586,-93434,-93281,-93129, + -92978,-92826,-92675,-92525,-92375,-92225,-92075,-91926, + -91777,-91628,-91480,-91332,-91184,-91036,-90889,-90742, + -90596,-90450,-90304,-90158,-90013,-89868,-89724,-89579, + -89435,-89292,-89148,-89005,-88862,-88720,-88577,-88435, + -88294,-88152,-88011,-87871,-87730,-87590,-87450,-87310, + -87171,-87032,-86893,-86755,-86616,-86479,-86341,-86204, + -86066,-85930,-85793,-85657,-85521,-85385,-85250,-85114, + -84980,-84845,-84710,-84576,-84443,-84309,-84176,-84043, + -83910,-83777,-83645,-83513,-83381,-83250,-83118,-82987, + -82857,-82726,-82596,-82466,-82336,-82207,-82078,-81949, + -81820,-81691,-81563,-81435,-81307,-81180,-81053,-80925, + -80799,-80672,-80546,-80420,-80294,-80168,-80043,-79918, + -79793,-79668,-79544,-79420,-79296,-79172,-79048,-78925, + -78802,-78679,-78557,-78434,-78312,-78190,-78068,-77947, + -77826,-77705,-77584,-77463,-77343,-77223,-77103,-76983, + -76864,-76744,-76625,-76506,-76388,-76269,-76151,-76033, + -75915,-75797,-75680,-75563,-75446,-75329,-75213,-75096, + -74980,-74864,-74748,-74633,-74517,-74402,-74287,-74172, + -74058,-73944,-73829,-73715,-73602,-73488,-73375,-73262, + -73149,-73036,-72923,-72811,-72699,-72587,-72475,-72363, + -72252,-72140,-72029,-71918,-71808,-71697,-71587,-71477, + -71367,-71257,-71147,-71038,-70929,-70820,-70711,-70602, + -70494,-70385,-70277,-70169,-70061,-69954,-69846,-69739, + -69632,-69525,-69418,-69312,-69205,-69099,-68993,-68887, + -68781,-68676,-68570,-68465,-68360,-68255,-68151,-68046, + -67942,-67837,-67733,-67629,-67526,-67422,-67319,-67216, + -67113,-67010,-66907,-66804,-66702,-66600,-66498,-66396, + -66294,-66192,-66091,-65989,-65888,-65787,-65686,-65586, + -65485,-65385,-65285,-65185,-65085,-64985,-64885,-64786, + -64687,-64587,-64488,-64389,-64291,-64192,-64094,-63996, + -63897,-63799,-63702,-63604,-63506,-63409,-63312,-63215, + -63118,-63021,-62924,-62828,-62731,-62635,-62539,-62443, + -62347,-62251,-62156,-62060,-61965,-61870,-61775,-61680, + -61585,-61491,-61396,-61302,-61208,-61114,-61020,-60926, + -60833,-60739,-60646,-60552,-60459,-60366,-60273,-60181, + -60088,-59996,-59903,-59811,-59719,-59627,-59535,-59444, + -59352,-59261,-59169,-59078,-58987,-58896,-58805,-58715, + -58624,-58534,-58443,-58353,-58263,-58173,-58083,-57994, + -57904,-57815,-57725,-57636,-57547,-57458,-57369,-57281, + -57192,-57104,-57015,-56927,-56839,-56751,-56663,-56575, + -56487,-56400,-56312,-56225,-56138,-56051,-55964,-55877, + -55790,-55704,-55617,-55531,-55444,-55358,-55272,-55186, + -55100,-55015,-54929,-54843,-54758,-54673,-54587,-54502, + -54417,-54333,-54248,-54163,-54079,-53994,-53910,-53826, + -53741,-53657,-53574,-53490,-53406,-53322,-53239,-53156, + -53072,-52989,-52906,-52823,-52740,-52657,-52575,-52492, + -52410,-52327,-52245,-52163,-52081,-51999,-51917,-51835, + -51754,-51672,-51591,-51509,-51428,-51347,-51266,-51185, + -51104,-51023,-50942,-50862,-50781,-50701,-50621,-50540, + -50460,-50380,-50300,-50221,-50141,-50061,-49982,-49902, + -49823,-49744,-49664,-49585,-49506,-49427,-49349,-49270, + -49191,-49113,-49034,-48956,-48878,-48799,-48721,-48643, + -48565,-48488,-48410,-48332,-48255,-48177,-48100,-48022, + -47945,-47868,-47791,-47714,-47637,-47560,-47484,-47407, + -47331,-47254,-47178,-47102,-47025,-46949,-46873,-46797, + -46721,-46646,-46570,-46494,-46419,-46343,-46268,-46193, + -46118,-46042,-45967,-45892,-45818,-45743,-45668,-45593, + -45519,-45444,-45370,-45296,-45221,-45147,-45073,-44999, + -44925,-44851,-44778,-44704,-44630,-44557,-44483,-44410, + -44337,-44263,-44190,-44117,-44044,-43971,-43898,-43826, + -43753,-43680,-43608,-43535,-43463,-43390,-43318,-43246, + -43174,-43102,-43030,-42958,-42886,-42814,-42743,-42671, + -42600,-42528,-42457,-42385,-42314,-42243,-42172,-42101, + -42030,-41959,-41888,-41817,-41747,-41676,-41605,-41535, + -41465,-41394,-41324,-41254,-41184,-41113,-41043,-40973, + -40904,-40834,-40764,-40694,-40625,-40555,-40486,-40416, + -40347,-40278,-40208,-40139,-40070,-40001,-39932,-39863, + -39794,-39726,-39657,-39588,-39520,-39451,-39383,-39314, + -39246,-39178,-39110,-39042,-38973,-38905,-38837,-38770, + -38702,-38634,-38566,-38499,-38431,-38364,-38296,-38229, + -38161,-38094,-38027,-37960,-37893,-37826,-37759,-37692, + -37625,-37558,-37491,-37425,-37358,-37291,-37225,-37158, + -37092,-37026,-36959,-36893,-36827,-36761,-36695,-36629, + -36563,-36497,-36431,-36365,-36300,-36234,-36168,-36103, + -36037,-35972,-35907,-35841,-35776,-35711,-35646,-35580, + -35515,-35450,-35385,-35321,-35256,-35191,-35126,-35062, + -34997,-34932,-34868,-34803,-34739,-34675,-34610,-34546, + -34482,-34418,-34354,-34289,-34225,-34162,-34098,-34034, + -33970,-33906,-33843,-33779,-33715,-33652,-33588,-33525, + -33461,-33398,-33335,-33272,-33208,-33145,-33082,-33019, + -32956,-32893,-32830,-32767,-32705,-32642,-32579,-32516, + -32454,-32391,-32329,-32266,-32204,-32141,-32079,-32017, + -31955,-31892,-31830,-31768,-31706,-31644,-31582,-31520, + -31458,-31396,-31335,-31273,-31211,-31150,-31088,-31026, + -30965,-30904,-30842,-30781,-30719,-30658,-30597,-30536, + -30474,-30413,-30352,-30291,-30230,-30169,-30108,-30048, + -29987,-29926,-29865,-29805,-29744,-29683,-29623,-29562, + -29502,-29441,-29381,-29321,-29260,-29200,-29140,-29080, + -29020,-28959,-28899,-28839,-28779,-28719,-28660,-28600, + -28540,-28480,-28420,-28361,-28301,-28241,-28182,-28122, + -28063,-28003,-27944,-27884,-27825,-27766,-27707,-27647, + -27588,-27529,-27470,-27411,-27352,-27293,-27234,-27175, + -27116,-27057,-26998,-26940,-26881,-26822,-26763,-26705, + -26646,-26588,-26529,-26471,-26412,-26354,-26295,-26237, + -26179,-26120,-26062,-26004,-25946,-25888,-25830,-25772, + -25714,-25656,-25598,-25540,-25482,-25424,-25366,-25308, + -25251,-25193,-25135,-25078,-25020,-24962,-24905,-24847, + -24790,-24732,-24675,-24618,-24560,-24503,-24446,-24389, + -24331,-24274,-24217,-24160,-24103,-24046,-23989,-23932, + -23875,-23818,-23761,-23704,-23647,-23591,-23534,-23477, + -23420,-23364,-23307,-23250,-23194,-23137,-23081,-23024, + -22968,-22911,-22855,-22799,-22742,-22686,-22630,-22573, + -22517,-22461,-22405,-22349,-22293,-22237,-22181,-22125, + -22069,-22013,-21957,-21901,-21845,-21789,-21733,-21678, + -21622,-21566,-21510,-21455,-21399,-21343,-21288,-21232, + -21177,-21121,-21066,-21010,-20955,-20900,-20844,-20789, + -20734,-20678,-20623,-20568,-20513,-20457,-20402,-20347, + -20292,-20237,-20182,-20127,-20072,-20017,-19962,-19907, + -19852,-19797,-19742,-19688,-19633,-19578,-19523,-19469, + -19414,-19359,-19305,-19250,-19195,-19141,-19086,-19032, + -18977,-18923,-18868,-18814,-18760,-18705,-18651,-18597, + -18542,-18488,-18434,-18380,-18325,-18271,-18217,-18163, + -18109,-18055,-18001,-17946,-17892,-17838,-17784,-17731, + -17677,-17623,-17569,-17515,-17461,-17407,-17353,-17300, + -17246,-17192,-17138,-17085,-17031,-16977,-16924,-16870, + -16817,-16763,-16710,-16656,-16603,-16549,-16496,-16442, + -16389,-16335,-16282,-16229,-16175,-16122,-16069,-16015, + -15962,-15909,-15856,-15802,-15749,-15696,-15643,-15590, + -15537,-15484,-15431,-15378,-15325,-15272,-15219,-15166, + -15113,-15060,-15007,-14954,-14901,-14848,-14795,-14743, + -14690,-14637,-14584,-14531,-14479,-14426,-14373,-14321, + -14268,-14215,-14163,-14110,-14057,-14005,-13952,-13900, + -13847,-13795,-13742,-13690,-13637,-13585,-13533,-13480, + -13428,-13375,-13323,-13271,-13218,-13166,-13114,-13062, + -13009,-12957,-12905,-12853,-12800,-12748,-12696,-12644, + -12592,-12540,-12488,-12436,-12383,-12331,-12279,-12227, + -12175,-12123,-12071,-12019,-11967,-11916,-11864,-11812, + -11760,-11708,-11656,-11604,-11552,-11501,-11449,-11397, + -11345,-11293,-11242,-11190,-11138,-11086,-11035,-10983, + -10931,-10880,-10828,-10777,-10725,-10673,-10622,-10570, + -10519,-10467,-10415,-10364,-10312,-10261,-10209,-10158, + -10106,-10055,-10004,-9952,-9901,-9849,-9798,-9747, + -9695,-9644,-9592,-9541,-9490,-9438,-9387,-9336, + -9285,-9233,-9182,-9131,-9080,-9028,-8977,-8926, + -8875,-8824,-8772,-8721,-8670,-8619,-8568,-8517, + -8466,-8414,-8363,-8312,-8261,-8210,-8159,-8108, + -8057,-8006,-7955,-7904,-7853,-7802,-7751,-7700, + -7649,-7598,-7547,-7496,-7445,-7395,-7344,-7293, + -7242,-7191,-7140,-7089,-7038,-6988,-6937,-6886, + -6835,-6784,-6733,-6683,-6632,-6581,-6530,-6480, + -6429,-6378,-6327,-6277,-6226,-6175,-6124,-6074, + -6023,-5972,-5922,-5871,-5820,-5770,-5719,-5668, + -5618,-5567,-5517,-5466,-5415,-5365,-5314,-5264, + -5213,-5162,-5112,-5061,-5011,-4960,-4910,-4859, + -4808,-4758,-4707,-4657,-4606,-4556,-4505,-4455, + -4404,-4354,-4303,-4253,-4202,-4152,-4101,-4051, + -4001,-3950,-3900,-3849,-3799,-3748,-3698,-3648, + -3597,-3547,-3496,-3446,-3395,-3345,-3295,-3244, + -3194,-3144,-3093,-3043,-2992,-2942,-2892,-2841, + -2791,-2741,-2690,-2640,-2590,-2539,-2489,-2439, + -2388,-2338,-2288,-2237,-2187,-2137,-2086,-2036, + -1986,-1935,-1885,-1835,-1784,-1734,-1684,-1633, + -1583,-1533,-1483,-1432,-1382,-1332,-1281,-1231, + -1181,-1131,-1080,-1030,-980,-929,-879,-829, + -779,-728,-678,-628,-578,-527,-477,-427, + -376,-326,-276,-226,-175,-125,-75,-25, + 25,75,125,175,226,276,326,376, + 427,477,527,578,628,678,728,779, + 829,879,929,980,1030,1080,1131,1181, + 1231,1281,1332,1382,1432,1483,1533,1583, + 1633,1684,1734,1784,1835,1885,1935,1986, + 2036,2086,2137,2187,2237,2288,2338,2388, + 2439,2489,2539,2590,2640,2690,2741,2791, + 2841,2892,2942,2992,3043,3093,3144,3194, + 3244,3295,3345,3395,3446,3496,3547,3597, + 3648,3698,3748,3799,3849,3900,3950,4001, + 4051,4101,4152,4202,4253,4303,4354,4404, + 4455,4505,4556,4606,4657,4707,4758,4808, + 4859,4910,4960,5011,5061,5112,5162,5213, + 5264,5314,5365,5415,5466,5517,5567,5618, + 5668,5719,5770,5820,5871,5922,5972,6023, + 6074,6124,6175,6226,6277,6327,6378,6429, + 6480,6530,6581,6632,6683,6733,6784,6835, + 6886,6937,6988,7038,7089,7140,7191,7242, + 7293,7344,7395,7445,7496,7547,7598,7649, + 7700,7751,7802,7853,7904,7955,8006,8057, + 8108,8159,8210,8261,8312,8363,8414,8466, + 8517,8568,8619,8670,8721,8772,8824,8875, + 8926,8977,9028,9080,9131,9182,9233,9285, + 9336,9387,9438,9490,9541,9592,9644,9695, + 9747,9798,9849,9901,9952,10004,10055,10106, + 10158,10209,10261,10312,10364,10415,10467,10519, + 10570,10622,10673,10725,10777,10828,10880,10931, + 10983,11035,11086,11138,11190,11242,11293,11345, + 11397,11449,11501,11552,11604,11656,11708,11760, + 11812,11864,11916,11967,12019,12071,12123,12175, + 12227,12279,12331,12383,12436,12488,12540,12592, + 12644,12696,12748,12800,12853,12905,12957,13009, + 13062,13114,13166,13218,13271,13323,13375,13428, + 13480,13533,13585,13637,13690,13742,13795,13847, + 13900,13952,14005,14057,14110,14163,14215,14268, + 14321,14373,14426,14479,14531,14584,14637,14690, + 14743,14795,14848,14901,14954,15007,15060,15113, + 15166,15219,15272,15325,15378,15431,15484,15537, + 15590,15643,15696,15749,15802,15856,15909,15962, + 16015,16069,16122,16175,16229,16282,16335,16389, + 16442,16496,16549,16603,16656,16710,16763,16817, + 16870,16924,16977,17031,17085,17138,17192,17246, + 17300,17353,17407,17461,17515,17569,17623,17677, + 17731,17784,17838,17892,17946,18001,18055,18109, + 18163,18217,18271,18325,18380,18434,18488,18542, + 18597,18651,18705,18760,18814,18868,18923,18977, + 19032,19086,19141,19195,19250,19305,19359,19414, + 19469,19523,19578,19633,19688,19742,19797,19852, + 19907,19962,20017,20072,20127,20182,20237,20292, + 20347,20402,20457,20513,20568,20623,20678,20734, + 20789,20844,20900,20955,21010,21066,21121,21177, + 21232,21288,21343,21399,21455,21510,21566,21622, + 21678,21733,21789,21845,21901,21957,22013,22069, + 22125,22181,22237,22293,22349,22405,22461,22517, + 22573,22630,22686,22742,22799,22855,22911,22968, + 23024,23081,23137,23194,23250,23307,23364,23420, + 23477,23534,23591,23647,23704,23761,23818,23875, + 23932,23989,24046,24103,24160,24217,24274,24331, + 24389,24446,24503,24560,24618,24675,24732,24790, + 24847,24905,24962,25020,25078,25135,25193,25251, + 25308,25366,25424,25482,25540,25598,25656,25714, + 25772,25830,25888,25946,26004,26062,26120,26179, + 26237,26295,26354,26412,26471,26529,26588,26646, + 26705,26763,26822,26881,26940,26998,27057,27116, + 27175,27234,27293,27352,27411,27470,27529,27588, + 27647,27707,27766,27825,27884,27944,28003,28063, + 28122,28182,28241,28301,28361,28420,28480,28540, + 28600,28660,28719,28779,28839,28899,28959,29020, + 29080,29140,29200,29260,29321,29381,29441,29502, + 29562,29623,29683,29744,29805,29865,29926,29987, + 30048,30108,30169,30230,30291,30352,30413,30474, + 30536,30597,30658,30719,30781,30842,30904,30965, + 31026,31088,31150,31211,31273,31335,31396,31458, + 31520,31582,31644,31706,31768,31830,31892,31955, + 32017,32079,32141,32204,32266,32329,32391,32454, + 32516,32579,32642,32705,32767,32830,32893,32956, + 33019,33082,33145,33208,33272,33335,33398,33461, + 33525,33588,33652,33715,33779,33843,33906,33970, + 34034,34098,34162,34225,34289,34354,34418,34482, + 34546,34610,34675,34739,34803,34868,34932,34997, + 35062,35126,35191,35256,35321,35385,35450,35515, + 35580,35646,35711,35776,35841,35907,35972,36037, + 36103,36168,36234,36300,36365,36431,36497,36563, + 36629,36695,36761,36827,36893,36959,37026,37092, + 37158,37225,37291,37358,37425,37491,37558,37625, + 37692,37759,37826,37893,37960,38027,38094,38161, + 38229,38296,38364,38431,38499,38566,38634,38702, + 38770,38837,38905,38973,39042,39110,39178,39246, + 39314,39383,39451,39520,39588,39657,39726,39794, + 39863,39932,40001,40070,40139,40208,40278,40347, + 40416,40486,40555,40625,40694,40764,40834,40904, + 40973,41043,41113,41184,41254,41324,41394,41465, + 41535,41605,41676,41747,41817,41888,41959,42030, + 42101,42172,42243,42314,42385,42457,42528,42600, + 42671,42743,42814,42886,42958,43030,43102,43174, + 43246,43318,43390,43463,43535,43608,43680,43753, + 43826,43898,43971,44044,44117,44190,44263,44337, + 44410,44483,44557,44630,44704,44778,44851,44925, + 44999,45073,45147,45221,45296,45370,45444,45519, + 45593,45668,45743,45818,45892,45967,46042,46118, + 46193,46268,46343,46419,46494,46570,46646,46721, + 46797,46873,46949,47025,47102,47178,47254,47331, + 47407,47484,47560,47637,47714,47791,47868,47945, + 48022,48100,48177,48255,48332,48410,48488,48565, + 48643,48721,48799,48878,48956,49034,49113,49191, + 49270,49349,49427,49506,49585,49664,49744,49823, + 49902,49982,50061,50141,50221,50300,50380,50460, + 50540,50621,50701,50781,50862,50942,51023,51104, + 51185,51266,51347,51428,51509,51591,51672,51754, + 51835,51917,51999,52081,52163,52245,52327,52410, + 52492,52575,52657,52740,52823,52906,52989,53072, + 53156,53239,53322,53406,53490,53574,53657,53741, + 53826,53910,53994,54079,54163,54248,54333,54417, + 54502,54587,54673,54758,54843,54929,55015,55100, + 55186,55272,55358,55444,55531,55617,55704,55790, + 55877,55964,56051,56138,56225,56312,56400,56487, + 56575,56663,56751,56839,56927,57015,57104,57192, + 57281,57369,57458,57547,57636,57725,57815,57904, + 57994,58083,58173,58263,58353,58443,58534,58624, + 58715,58805,58896,58987,59078,59169,59261,59352, + 59444,59535,59627,59719,59811,59903,59996,60088, + 60181,60273,60366,60459,60552,60646,60739,60833, + 60926,61020,61114,61208,61302,61396,61491,61585, + 61680,61775,61870,61965,62060,62156,62251,62347, + 62443,62539,62635,62731,62828,62924,63021,63118, + 63215,63312,63409,63506,63604,63702,63799,63897, + 63996,64094,64192,64291,64389,64488,64587,64687, + 64786,64885,64985,65085,65185,65285,65385,65485, + 65586,65686,65787,65888,65989,66091,66192,66294, + 66396,66498,66600,66702,66804,66907,67010,67113, + 67216,67319,67422,67526,67629,67733,67837,67942, + 68046,68151,68255,68360,68465,68570,68676,68781, + 68887,68993,69099,69205,69312,69418,69525,69632, + 69739,69846,69954,70061,70169,70277,70385,70494, + 70602,70711,70820,70929,71038,71147,71257,71367, + 71477,71587,71697,71808,71918,72029,72140,72252, + 72363,72475,72587,72699,72811,72923,73036,73149, + 73262,73375,73488,73602,73715,73829,73944,74058, + 74172,74287,74402,74517,74633,74748,74864,74980, + 75096,75213,75329,75446,75563,75680,75797,75915, + 76033,76151,76269,76388,76506,76625,76744,76864, + 76983,77103,77223,77343,77463,77584,77705,77826, + 77947,78068,78190,78312,78434,78557,78679,78802, + 78925,79048,79172,79296,79420,79544,79668,79793, + 79918,80043,80168,80294,80420,80546,80672,80799, + 80925,81053,81180,81307,81435,81563,81691,81820, + 81949,82078,82207,82336,82466,82596,82726,82857, + 82987,83118,83250,83381,83513,83645,83777,83910, + 84043,84176,84309,84443,84576,84710,84845,84980, + 85114,85250,85385,85521,85657,85793,85930,86066, + 86204,86341,86479,86616,86755,86893,87032,87171, + 87310,87450,87590,87730,87871,88011,88152,88294, + 88435,88577,88720,88862,89005,89148,89292,89435, + 89579,89724,89868,90013,90158,90304,90450,90596, + 90742,90889,91036,91184,91332,91480,91628,91777, + 91926,92075,92225,92375,92525,92675,92826,92978, + 93129,93281,93434,93586,93739,93892,94046,94200, + 94354,94509,94664,94819,94975,95131,95287,95444, + 95601,95758,95916,96074,96233,96391,96551,96710, + 96870,97030,97191,97352,97513,97675,97837,98000, + 98163,98326,98489,98653,98818,98982,99148,99313, + 99479,99645,99812,99979,100146,100314,100482,100651, + 100820,100990,101159,101330,101500,101671,101843,102015, + 102187,102360,102533,102706,102880,103054,103229,103404, + 103580,103756,103933,104109,104287,104465,104643,104821, + 105000,105180,105360,105540,105721,105902,106084,106266, + 106449,106632,106816,107000,107184,107369,107555,107741, + 107927,108114,108301,108489,108677,108866,109055,109245, + 109435,109626,109817,110008,110200,110393,110586,110780, + 110974,111169,111364,111560,111756,111952,112150,112347, + 112546,112744,112944,113143,113344,113545,113746,113948, + 114151,114354,114557,114761,114966,115171,115377,115583, + 115790,115998,116206,116414,116623,116833,117044,117254, + 117466,117678,117891,118104,118318,118532,118747,118963, + 119179,119396,119613,119831,120050,120269,120489,120709, + 120930,121152,121374,121597,121821,122045,122270,122496, + 122722,122949,123176,123404,123633,123863,124093,124324, + 124555,124787,125020,125254,125488,125723,125959,126195, + 126432,126669,126908,127147,127387,127627,127869,128111, + 128353,128597,128841,129086,129332,129578,129825,130073, + 130322,130571,130821,131072,131324,131576,131830,132084, + 132339,132594,132851,133108,133366,133625,133884,134145, + 134406,134668,134931,135195,135459,135725,135991,136258, + 136526,136795,137065,137335,137607,137879,138152,138426, + 138701,138977,139254,139532,139810,140090,140370,140651, + 140934,141217,141501,141786,142072,142359,142647,142936, + 143226,143517,143808,144101,144395,144690,144986,145282, + 145580,145879,146179,146480,146782,147084,147388,147693, + 148000,148307,148615,148924,149235,149546,149859,150172, + 150487,150803,151120,151438,151757,152077,152399,152722, + 153045,153370,153697,154024,154352,154682,155013,155345, + 155678,156013,156349,156686,157024,157363,157704,158046, + 158389,158734,159079,159427,159775,160125,160476,160828, + 161182,161537,161893,162251,162610,162970,163332,163695, + 164060,164426,164793,165162,165532,165904,166277,166651, + 167027,167405,167784,168164,168546,168930,169315,169701, + 170089,170479,170870,171263,171657,172053,172451,172850, + 173251,173653,174057,174463,174870,175279,175690,176102, + 176516,176932,177349,177769,178190,178612,179037,179463, + 179891,180321,180753,181186,181622,182059,182498,182939, + 183382,183827,184274,184722,185173,185625,186080,186536, + 186995,187455,187918,188382,188849,189318,189789,190261, + 190736,191213,191693,192174,192658,193143,193631,194122, + 194614,195109,195606,196105,196606,197110,197616,198125, + 198636,199149,199664,200182,200703,201226,201751,202279, + 202809,203342,203878,204416,204956,205500,206045,206594, + 207145,207699,208255,208815,209376,209941,210509,211079, + 211652,212228,212807,213389,213973,214561,215151,215745, + 216341,216941,217544,218149,218758,219370,219985,220603, + 221225,221849,222477,223108,223743,224381,225022,225666, + 226314,226966,227621,228279,228941,229606,230275,230948, + 231624,232304,232988,233676,234367,235062,235761,236463, + 237170,237881,238595,239314,240036,240763,241493,242228, + 242967,243711,244458,245210,245966,246727,247492,248261, + 249035,249813,250596,251384,252176,252973,253774,254581, + 255392,256208,257029,257855,258686,259522,260363,261209, + 262060,262917,263779,264646,265519,266397,267280,268169, + 269064,269965,270871,271782,272700,273624,274553,275489, + 276430,277378,278332,279292,280258,281231,282210,283195, + 284188,285186,286192,287204,288223,289249,290282,291322, + 292369,293423,294485,295554,296630,297714,298805,299904, + 301011,302126,303248,304379,305517,306664,307819,308983, + 310154,311335,312524,313721,314928,316143,317368,318601, + 319844,321097,322358,323629,324910,326201,327502,328812, + 330133,331464,332805,334157,335519,336892,338276,339671, + 341078,342495,343924,345364,346816,348280,349756,351244, + 352744,354257,355783,357321,358872,360436,362013,363604, + 365208,366826,368459,370105,371765,373440,375130,376835, + 378555,380290,382040,383807,385589,387387,389202,391034, + 392882,394747,396630,398530,400448,402384,404338,406311, + 408303,410314,412344,414395,416465,418555,420666,422798, + 424951,427125,429321,431540,433781,436045,438332,440643, + 442978,445337,447720,450129,452564,455024,457511,460024, + 462565,465133,467730,470355,473009,475692,478406,481150, + 483925,486732,489571,492443,495348,498287,501261,504269, + 507313,510394,513512,516667,519861,523094,526366,529680, + 533034,536431,539870,543354,546881,550455,554074,557741, + 561456,565221,569035,572901,576818,580789,584815,588896, + 593033,597229,601483,605798,610174,614613,619117,623686, + 628323,633028,637803,642651,647572,652568,657640,662792, + 668024,673338,678737,684223,689797,695462,701219,707072, + 713023,719074,725227,731486,737853,744331,750922,757631, + 764460,771411,778490,785699,793041,800521,808143,815910, + 823827,831898,840127,848520,857081,865817,874730,883829, + 893117,902602,912289,922186,932298,942633,953199,964003, + 975054,986361,997931,1009774,1021901,1034322,1047046,1060087, + 1073455,1087164,1101225,1115654,1130465,1145673,1161294,1177345, + 1193846,1210813,1228269,1246234,1264730,1283783,1303416,1323658, + 1344537,1366084,1388330,1411312,1435065,1459630,1485049,1511367, + 1538632,1566898,1596220,1626658,1658278,1691149,1725348,1760956, + 1798063,1836758,1877161,1919378,1963536,2009771,2058233,2109087, + 2162516,2218719,2277919,2340362,2406322,2476104,2550052,2628549, + 2712030,2800983,2895966,2997613,3106651,3223918,3350381,3487165, + 3635590,3797206,3973855,4167737,4381502,4618375,4882318,5178251, + 5512368,5892567,6329090,6835455,7429880,8137527,8994149,10052327, + 11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304 +}; + + +const fixed_t finesine[10240] = +{ + 25,75,125,175,226,276,326,376, + 427,477,527,578,628,678,728,779, + 829,879,929,980,1030,1080,1130,1181, + 1231,1281,1331,1382,1432,1482,1532,1583, + 1633,1683,1733,1784,1834,1884,1934,1985, + 2035,2085,2135,2186,2236,2286,2336,2387, + 2437,2487,2537,2587,2638,2688,2738,2788, + 2839,2889,2939,2989,3039,3090,3140,3190, + 3240,3291,3341,3391,3441,3491,3541,3592, + 3642,3692,3742,3792,3843,3893,3943,3993, + 4043,4093,4144,4194,4244,4294,4344,4394, + 4445,4495,4545,4595,4645,4695,4745,4796, + 4846,4896,4946,4996,5046,5096,5146,5197, + 5247,5297,5347,5397,5447,5497,5547,5597, + 5647,5697,5748,5798,5848,5898,5948,5998, + 6048,6098,6148,6198,6248,6298,6348,6398, + 6448,6498,6548,6598,6648,6698,6748,6798, + 6848,6898,6948,6998,7048,7098,7148,7198, + 7248,7298,7348,7398,7448,7498,7548,7598, + 7648,7697,7747,7797,7847,7897,7947,7997, + 8047,8097,8147,8196,8246,8296,8346,8396, + 8446,8496,8545,8595,8645,8695,8745,8794, + 8844,8894,8944,8994,9043,9093,9143,9193, + 9243,9292,9342,9392,9442,9491,9541,9591, + 9640,9690,9740,9790,9839,9889,9939,9988, + 10038,10088,10137,10187,10237,10286,10336,10386, + 10435,10485,10534,10584,10634,10683,10733,10782, + 10832,10882,10931,10981,11030,11080,11129,11179, + 11228,11278,11327,11377,11426,11476,11525,11575, + 11624,11674,11723,11773,11822,11872,11921,11970, + 12020,12069,12119,12168,12218,12267,12316,12366, + 12415,12464,12514,12563,12612,12662,12711,12760, + 12810,12859,12908,12957,13007,13056,13105,13154, + 13204,13253,13302,13351,13401,13450,13499,13548, + 13597,13647,13696,13745,13794,13843,13892,13941, + 13990,14040,14089,14138,14187,14236,14285,14334, + 14383,14432,14481,14530,14579,14628,14677,14726, + 14775,14824,14873,14922,14971,15020,15069,15118, + 15167,15215,15264,15313,15362,15411,15460,15509, + 15557,15606,15655,15704,15753,15802,15850,15899, + 15948,15997,16045,16094,16143,16191,16240,16289, + 16338,16386,16435,16484,16532,16581,16629,16678, + 16727,16775,16824,16872,16921,16970,17018,17067, + 17115,17164,17212,17261,17309,17358,17406,17455, + 17503,17551,17600,17648,17697,17745,17793,17842, + 17890,17939,17987,18035,18084,18132,18180,18228, + 18277,18325,18373,18421,18470,18518,18566,18614, + 18663,18711,18759,18807,18855,18903,18951,19000, + 19048,19096,19144,19192,19240,19288,19336,19384, + 19432,19480,19528,19576,19624,19672,19720,19768, + 19816,19864,19912,19959,20007,20055,20103,20151, + 20199,20246,20294,20342,20390,20438,20485,20533, + 20581,20629,20676,20724,20772,20819,20867,20915, + 20962,21010,21057,21105,21153,21200,21248,21295, + 21343,21390,21438,21485,21533,21580,21628,21675, + 21723,21770,21817,21865,21912,21960,22007,22054, + 22102,22149,22196,22243,22291,22338,22385,22433, + 22480,22527,22574,22621,22668,22716,22763,22810, + 22857,22904,22951,22998,23045,23092,23139,23186, + 23233,23280,23327,23374,23421,23468,23515,23562, + 23609,23656,23703,23750,23796,23843,23890,23937, + 23984,24030,24077,24124,24171,24217,24264,24311, + 24357,24404,24451,24497,24544,24591,24637,24684, + 24730,24777,24823,24870,24916,24963,25009,25056, + 25102,25149,25195,25241,25288,25334,25381,25427, + 25473,25520,25566,25612,25658,25705,25751,25797, + 25843,25889,25936,25982,26028,26074,26120,26166, + 26212,26258,26304,26350,26396,26442,26488,26534, + 26580,26626,26672,26718,26764,26810,26856,26902, + 26947,26993,27039,27085,27131,27176,27222,27268, + 27313,27359,27405,27450,27496,27542,27587,27633, + 27678,27724,27770,27815,27861,27906,27952,27997, + 28042,28088,28133,28179,28224,28269,28315,28360, + 28405,28451,28496,28541,28586,28632,28677,28722, + 28767,28812,28858,28903,28948,28993,29038,29083, + 29128,29173,29218,29263,29308,29353,29398,29443, + 29488,29533,29577,29622,29667,29712,29757,29801, + 29846,29891,29936,29980,30025,30070,30114,30159, + 30204,30248,30293,30337,30382,30426,30471,30515, + 30560,30604,30649,30693,30738,30782,30826,30871, + 30915,30959,31004,31048,31092,31136,31181,31225, + 31269,31313,31357,31402,31446,31490,31534,31578, + 31622,31666,31710,31754,31798,31842,31886,31930, + 31974,32017,32061,32105,32149,32193,32236,32280, + 32324,32368,32411,32455,32499,32542,32586,32630, + 32673,32717,32760,32804,32847,32891,32934,32978, + 33021,33065,33108,33151,33195,33238,33281,33325, + 33368,33411,33454,33498,33541,33584,33627,33670, + 33713,33756,33799,33843,33886,33929,33972,34015, + 34057,34100,34143,34186,34229,34272,34315,34358, + 34400,34443,34486,34529,34571,34614,34657,34699, + 34742,34785,34827,34870,34912,34955,34997,35040, + 35082,35125,35167,35210,35252,35294,35337,35379, + 35421,35464,35506,35548,35590,35633,35675,35717, + 35759,35801,35843,35885,35927,35969,36011,36053, + 36095,36137,36179,36221,36263,36305,36347,36388, + 36430,36472,36514,36555,36597,36639,36681,36722, + 36764,36805,36847,36889,36930,36972,37013,37055, + 37096,37137,37179,37220,37262,37303,37344,37386, + 37427,37468,37509,37551,37592,37633,37674,37715, + 37756,37797,37838,37879,37920,37961,38002,38043, + 38084,38125,38166,38207,38248,38288,38329,38370, + 38411,38451,38492,38533,38573,38614,38655,38695, + 38736,38776,38817,38857,38898,38938,38979,39019, + 39059,39100,39140,39180,39221,39261,39301,39341, + 39382,39422,39462,39502,39542,39582,39622,39662, + 39702,39742,39782,39822,39862,39902,39942,39982, + 40021,40061,40101,40141,40180,40220,40260,40300, + 40339,40379,40418,40458,40497,40537,40576,40616, + 40655,40695,40734,40773,40813,40852,40891,40931, + 40970,41009,41048,41087,41127,41166,41205,41244, + 41283,41322,41361,41400,41439,41478,41517,41556, + 41595,41633,41672,41711,41750,41788,41827,41866, + 41904,41943,41982,42020,42059,42097,42136,42174, + 42213,42251,42290,42328,42366,42405,42443,42481, + 42520,42558,42596,42634,42672,42711,42749,42787, + 42825,42863,42901,42939,42977,43015,43053,43091, + 43128,43166,43204,43242,43280,43317,43355,43393, + 43430,43468,43506,43543,43581,43618,43656,43693, + 43731,43768,43806,43843,43880,43918,43955,43992, + 44029,44067,44104,44141,44178,44215,44252,44289, + 44326,44363,44400,44437,44474,44511,44548,44585, + 44622,44659,44695,44732,44769,44806,44842,44879, + 44915,44952,44989,45025,45062,45098,45135,45171, + 45207,45244,45280,45316,45353,45389,45425,45462, + 45498,45534,45570,45606,45642,45678,45714,45750, + 45786,45822,45858,45894,45930,45966,46002,46037, + 46073,46109,46145,46180,46216,46252,46287,46323, + 46358,46394,46429,46465,46500,46536,46571,46606, + 46642,46677,46712,46747,46783,46818,46853,46888, + 46923,46958,46993,47028,47063,47098,47133,47168, + 47203,47238,47273,47308,47342,47377,47412,47446, + 47481,47516,47550,47585,47619,47654,47688,47723, + 47757,47792,47826,47860,47895,47929,47963,47998, + 48032,48066,48100,48134,48168,48202,48237,48271, + 48305,48338,48372,48406,48440,48474,48508,48542, + 48575,48609,48643,48676,48710,48744,48777,48811, + 48844,48878,48911,48945,48978,49012,49045,49078, + 49112,49145,49178,49211,49244,49278,49311,49344, + 49377,49410,49443,49476,49509,49542,49575,49608, + 49640,49673,49706,49739,49771,49804,49837,49869, + 49902,49935,49967,50000,50032,50065,50097,50129, + 50162,50194,50226,50259,50291,50323,50355,50387, + 50420,50452,50484,50516,50548,50580,50612,50644, + 50675,50707,50739,50771,50803,50834,50866,50898, + 50929,50961,50993,51024,51056,51087,51119,51150, + 51182,51213,51244,51276,51307,51338,51369,51401, + 51432,51463,51494,51525,51556,51587,51618,51649, + 51680,51711,51742,51773,51803,51834,51865,51896, + 51926,51957,51988,52018,52049,52079,52110,52140, + 52171,52201,52231,52262,52292,52322,52353,52383, + 52413,52443,52473,52503,52534,52564,52594,52624, + 52653,52683,52713,52743,52773,52803,52832,52862, + 52892,52922,52951,52981,53010,53040,53069,53099, + 53128,53158,53187,53216,53246,53275,53304,53334, + 53363,53392,53421,53450,53479,53508,53537,53566, + 53595,53624,53653,53682,53711,53739,53768,53797, + 53826,53854,53883,53911,53940,53969,53997,54026, + 54054,54082,54111,54139,54167,54196,54224,54252, + 54280,54308,54337,54365,54393,54421,54449,54477, + 54505,54533,54560,54588,54616,54644,54672,54699, + 54727,54755,54782,54810,54837,54865,54892,54920, + 54947,54974,55002,55029,55056,55084,55111,55138, + 55165,55192,55219,55246,55274,55300,55327,55354, + 55381,55408,55435,55462,55489,55515,55542,55569, + 55595,55622,55648,55675,55701,55728,55754,55781, + 55807,55833,55860,55886,55912,55938,55965,55991, + 56017,56043,56069,56095,56121,56147,56173,56199, + 56225,56250,56276,56302,56328,56353,56379,56404, + 56430,56456,56481,56507,56532,56557,56583,56608, + 56633,56659,56684,56709,56734,56760,56785,56810, + 56835,56860,56885,56910,56935,56959,56984,57009, + 57034,57059,57083,57108,57133,57157,57182,57206, + 57231,57255,57280,57304,57329,57353,57377,57402, + 57426,57450,57474,57498,57522,57546,57570,57594, + 57618,57642,57666,57690,57714,57738,57762,57785, + 57809,57833,57856,57880,57903,57927,57950,57974, + 57997,58021,58044,58067,58091,58114,58137,58160, + 58183,58207,58230,58253,58276,58299,58322,58345, + 58367,58390,58413,58436,58459,58481,58504,58527, + 58549,58572,58594,58617,58639,58662,58684,58706, + 58729,58751,58773,58795,58818,58840,58862,58884, + 58906,58928,58950,58972,58994,59016,59038,59059, + 59081,59103,59125,59146,59168,59190,59211,59233, + 59254,59276,59297,59318,59340,59361,59382,59404, + 59425,59446,59467,59488,59509,59530,59551,59572, + 59593,59614,59635,59656,59677,59697,59718,59739, + 59759,59780,59801,59821,59842,59862,59883,59903, + 59923,59944,59964,59984,60004,60025,60045,60065, + 60085,60105,60125,60145,60165,60185,60205,60225, + 60244,60264,60284,60304,60323,60343,60363,60382, + 60402,60421,60441,60460,60479,60499,60518,60537, + 60556,60576,60595,60614,60633,60652,60671,60690, + 60709,60728,60747,60766,60785,60803,60822,60841, + 60859,60878,60897,60915,60934,60952,60971,60989, + 61007,61026,61044,61062,61081,61099,61117,61135, + 61153,61171,61189,61207,61225,61243,61261,61279, + 61297,61314,61332,61350,61367,61385,61403,61420, + 61438,61455,61473,61490,61507,61525,61542,61559, + 61577,61594,61611,61628,61645,61662,61679,61696, + 61713,61730,61747,61764,61780,61797,61814,61831, + 61847,61864,61880,61897,61913,61930,61946,61963, + 61979,61995,62012,62028,62044,62060,62076,62092, + 62108,62125,62141,62156,62172,62188,62204,62220, + 62236,62251,62267,62283,62298,62314,62329,62345, + 62360,62376,62391,62407,62422,62437,62453,62468, + 62483,62498,62513,62528,62543,62558,62573,62588, + 62603,62618,62633,62648,62662,62677,62692,62706, + 62721,62735,62750,62764,62779,62793,62808,62822, + 62836,62850,62865,62879,62893,62907,62921,62935, + 62949,62963,62977,62991,63005,63019,63032,63046, + 63060,63074,63087,63101,63114,63128,63141,63155, + 63168,63182,63195,63208,63221,63235,63248,63261, + 63274,63287,63300,63313,63326,63339,63352,63365, + 63378,63390,63403,63416,63429,63441,63454,63466, + 63479,63491,63504,63516,63528,63541,63553,63565, + 63578,63590,63602,63614,63626,63638,63650,63662, + 63674,63686,63698,63709,63721,63733,63745,63756, + 63768,63779,63791,63803,63814,63825,63837,63848, + 63859,63871,63882,63893,63904,63915,63927,63938, + 63949,63960,63971,63981,63992,64003,64014,64025, + 64035,64046,64057,64067,64078,64088,64099,64109, + 64120,64130,64140,64151,64161,64171,64181,64192, + 64202,64212,64222,64232,64242,64252,64261,64271, + 64281,64291,64301,64310,64320,64330,64339,64349, + 64358,64368,64377,64387,64396,64405,64414,64424, + 64433,64442,64451,64460,64469,64478,64487,64496, + 64505,64514,64523,64532,64540,64549,64558,64566, + 64575,64584,64592,64601,64609,64617,64626,64634, + 64642,64651,64659,64667,64675,64683,64691,64699, + 64707,64715,64723,64731,64739,64747,64754,64762, + 64770,64777,64785,64793,64800,64808,64815,64822, + 64830,64837,64844,64852,64859,64866,64873,64880, + 64887,64895,64902,64908,64915,64922,64929,64936, + 64943,64949,64956,64963,64969,64976,64982,64989, + 64995,65002,65008,65015,65021,65027,65033,65040, + 65046,65052,65058,65064,65070,65076,65082,65088, + 65094,65099,65105,65111,65117,65122,65128,65133, + 65139,65144,65150,65155,65161,65166,65171,65177, + 65182,65187,65192,65197,65202,65207,65212,65217, + 65222,65227,65232,65237,65242,65246,65251,65256, + 65260,65265,65270,65274,65279,65283,65287,65292, + 65296,65300,65305,65309,65313,65317,65321,65325, + 65329,65333,65337,65341,65345,65349,65352,65356, + 65360,65363,65367,65371,65374,65378,65381,65385, + 65388,65391,65395,65398,65401,65404,65408,65411, + 65414,65417,65420,65423,65426,65429,65431,65434, + 65437,65440,65442,65445,65448,65450,65453,65455, + 65458,65460,65463,65465,65467,65470,65472,65474, + 65476,65478,65480,65482,65484,65486,65488,65490, + 65492,65494,65496,65497,65499,65501,65502,65504, + 65505,65507,65508,65510,65511,65513,65514,65515, + 65516,65518,65519,65520,65521,65522,65523,65524, + 65525,65526,65527,65527,65528,65529,65530,65530, + 65531,65531,65532,65532,65533,65533,65534,65534, + 65534,65535,65535,65535,65535,65535,65535,65535, + 65535,65535,65535,65535,65535,65535,65535,65534, + 65534,65534,65533,65533,65532,65532,65531,65531, + 65530,65530,65529,65528,65527,65527,65526,65525, + 65524,65523,65522,65521,65520,65519,65518,65516, + 65515,65514,65513,65511,65510,65508,65507,65505, + 65504,65502,65501,65499,65497,65496,65494,65492, + 65490,65488,65486,65484,65482,65480,65478,65476, + 65474,65472,65470,65467,65465,65463,65460,65458, + 65455,65453,65450,65448,65445,65442,65440,65437, + 65434,65431,65429,65426,65423,65420,65417,65414, + 65411,65408,65404,65401,65398,65395,65391,65388, + 65385,65381,65378,65374,65371,65367,65363,65360, + 65356,65352,65349,65345,65341,65337,65333,65329, + 65325,65321,65317,65313,65309,65305,65300,65296, + 65292,65287,65283,65279,65274,65270,65265,65260, + 65256,65251,65246,65242,65237,65232,65227,65222, + 65217,65212,65207,65202,65197,65192,65187,65182, + 65177,65171,65166,65161,65155,65150,65144,65139, + 65133,65128,65122,65117,65111,65105,65099,65094, + 65088,65082,65076,65070,65064,65058,65052,65046, + 65040,65033,65027,65021,65015,65008,65002,64995, + 64989,64982,64976,64969,64963,64956,64949,64943, + 64936,64929,64922,64915,64908,64902,64895,64887, + 64880,64873,64866,64859,64852,64844,64837,64830, + 64822,64815,64808,64800,64793,64785,64777,64770, + 64762,64754,64747,64739,64731,64723,64715,64707, + 64699,64691,64683,64675,64667,64659,64651,64642, + 64634,64626,64617,64609,64600,64592,64584,64575, + 64566,64558,64549,64540,64532,64523,64514,64505, + 64496,64487,64478,64469,64460,64451,64442,64433, + 64424,64414,64405,64396,64387,64377,64368,64358, + 64349,64339,64330,64320,64310,64301,64291,64281, + 64271,64261,64252,64242,64232,64222,64212,64202, + 64192,64181,64171,64161,64151,64140,64130,64120, + 64109,64099,64088,64078,64067,64057,64046,64035, + 64025,64014,64003,63992,63981,63971,63960,63949, + 63938,63927,63915,63904,63893,63882,63871,63859, + 63848,63837,63825,63814,63803,63791,63779,63768, + 63756,63745,63733,63721,63709,63698,63686,63674, + 63662,63650,63638,63626,63614,63602,63590,63578, + 63565,63553,63541,63528,63516,63504,63491,63479, + 63466,63454,63441,63429,63416,63403,63390,63378, + 63365,63352,63339,63326,63313,63300,63287,63274, + 63261,63248,63235,63221,63208,63195,63182,63168, + 63155,63141,63128,63114,63101,63087,63074,63060, + 63046,63032,63019,63005,62991,62977,62963,62949, + 62935,62921,62907,62893,62879,62865,62850,62836, + 62822,62808,62793,62779,62764,62750,62735,62721, + 62706,62692,62677,62662,62648,62633,62618,62603, + 62588,62573,62558,62543,62528,62513,62498,62483, + 62468,62453,62437,62422,62407,62391,62376,62360, + 62345,62329,62314,62298,62283,62267,62251,62236, + 62220,62204,62188,62172,62156,62141,62125,62108, + 62092,62076,62060,62044,62028,62012,61995,61979, + 61963,61946,61930,61913,61897,61880,61864,61847, + 61831,61814,61797,61780,61764,61747,61730,61713, + 61696,61679,61662,61645,61628,61611,61594,61577, + 61559,61542,61525,61507,61490,61473,61455,61438, + 61420,61403,61385,61367,61350,61332,61314,61297, + 61279,61261,61243,61225,61207,61189,61171,61153, + 61135,61117,61099,61081,61062,61044,61026,61007, + 60989,60971,60952,60934,60915,60897,60878,60859, + 60841,60822,60803,60785,60766,60747,60728,60709, + 60690,60671,60652,60633,60614,60595,60576,60556, + 60537,60518,60499,60479,60460,60441,60421,60402, + 60382,60363,60343,60323,60304,60284,60264,60244, + 60225,60205,60185,60165,60145,60125,60105,60085, + 60065,60045,60025,60004,59984,59964,59944,59923, + 59903,59883,59862,59842,59821,59801,59780,59759, + 59739,59718,59697,59677,59656,59635,59614,59593, + 59572,59551,59530,59509,59488,59467,59446,59425, + 59404,59382,59361,59340,59318,59297,59276,59254, + 59233,59211,59190,59168,59146,59125,59103,59081, + 59059,59038,59016,58994,58972,58950,58928,58906, + 58884,58862,58840,58818,58795,58773,58751,58729, + 58706,58684,58662,58639,58617,58594,58572,58549, + 58527,58504,58481,58459,58436,58413,58390,58367, + 58345,58322,58299,58276,58253,58230,58207,58183, + 58160,58137,58114,58091,58067,58044,58021,57997, + 57974,57950,57927,57903,57880,57856,57833,57809, + 57785,57762,57738,57714,57690,57666,57642,57618, + 57594,57570,57546,57522,57498,57474,57450,57426, + 57402,57377,57353,57329,57304,57280,57255,57231, + 57206,57182,57157,57133,57108,57083,57059,57034, + 57009,56984,56959,56935,56910,56885,56860,56835, + 56810,56785,56760,56734,56709,56684,56659,56633, + 56608,56583,56557,56532,56507,56481,56456,56430, + 56404,56379,56353,56328,56302,56276,56250,56225, + 56199,56173,56147,56121,56095,56069,56043,56017, + 55991,55965,55938,55912,55886,55860,55833,55807, + 55781,55754,55728,55701,55675,55648,55622,55595, + 55569,55542,55515,55489,55462,55435,55408,55381, + 55354,55327,55300,55274,55246,55219,55192,55165, + 55138,55111,55084,55056,55029,55002,54974,54947, + 54920,54892,54865,54837,54810,54782,54755,54727, + 54699,54672,54644,54616,54588,54560,54533,54505, + 54477,54449,54421,54393,54365,54337,54308,54280, + 54252,54224,54196,54167,54139,54111,54082,54054, + 54026,53997,53969,53940,53911,53883,53854,53826, + 53797,53768,53739,53711,53682,53653,53624,53595, + 53566,53537,53508,53479,53450,53421,53392,53363, + 53334,53304,53275,53246,53216,53187,53158,53128, + 53099,53069,53040,53010,52981,52951,52922,52892, + 52862,52832,52803,52773,52743,52713,52683,52653, + 52624,52594,52564,52534,52503,52473,52443,52413, + 52383,52353,52322,52292,52262,52231,52201,52171, + 52140,52110,52079,52049,52018,51988,51957,51926, + 51896,51865,51834,51803,51773,51742,51711,51680, + 51649,51618,51587,51556,51525,51494,51463,51432, + 51401,51369,51338,51307,51276,51244,51213,51182, + 51150,51119,51087,51056,51024,50993,50961,50929, + 50898,50866,50834,50803,50771,50739,50707,50675, + 50644,50612,50580,50548,50516,50484,50452,50420, + 50387,50355,50323,50291,50259,50226,50194,50162, + 50129,50097,50065,50032,50000,49967,49935,49902, + 49869,49837,49804,49771,49739,49706,49673,49640, + 49608,49575,49542,49509,49476,49443,49410,49377, + 49344,49311,49278,49244,49211,49178,49145,49112, + 49078,49045,49012,48978,48945,48911,48878,48844, + 48811,48777,48744,48710,48676,48643,48609,48575, + 48542,48508,48474,48440,48406,48372,48338,48304, + 48271,48237,48202,48168,48134,48100,48066,48032, + 47998,47963,47929,47895,47860,47826,47792,47757, + 47723,47688,47654,47619,47585,47550,47516,47481, + 47446,47412,47377,47342,47308,47273,47238,47203, + 47168,47133,47098,47063,47028,46993,46958,46923, + 46888,46853,46818,46783,46747,46712,46677,46642, + 46606,46571,46536,46500,46465,46429,46394,46358, + 46323,46287,46252,46216,46180,46145,46109,46073, + 46037,46002,45966,45930,45894,45858,45822,45786, + 45750,45714,45678,45642,45606,45570,45534,45498, + 45462,45425,45389,45353,45316,45280,45244,45207, + 45171,45135,45098,45062,45025,44989,44952,44915, + 44879,44842,44806,44769,44732,44695,44659,44622, + 44585,44548,44511,44474,44437,44400,44363,44326, + 44289,44252,44215,44178,44141,44104,44067,44029, + 43992,43955,43918,43880,43843,43806,43768,43731, + 43693,43656,43618,43581,43543,43506,43468,43430, + 43393,43355,43317,43280,43242,43204,43166,43128, + 43091,43053,43015,42977,42939,42901,42863,42825, + 42787,42749,42711,42672,42634,42596,42558,42520, + 42481,42443,42405,42366,42328,42290,42251,42213, + 42174,42136,42097,42059,42020,41982,41943,41904, + 41866,41827,41788,41750,41711,41672,41633,41595, + 41556,41517,41478,41439,41400,41361,41322,41283, + 41244,41205,41166,41127,41088,41048,41009,40970, + 40931,40891,40852,40813,40773,40734,40695,40655, + 40616,40576,40537,40497,40458,40418,40379,40339, + 40300,40260,40220,40180,40141,40101,40061,40021, + 39982,39942,39902,39862,39822,39782,39742,39702, + 39662,39622,39582,39542,39502,39462,39422,39382, + 39341,39301,39261,39221,39180,39140,39100,39059, + 39019,38979,38938,38898,38857,38817,38776,38736, + 38695,38655,38614,38573,38533,38492,38451,38411, + 38370,38329,38288,38248,38207,38166,38125,38084, + 38043,38002,37961,37920,37879,37838,37797,37756, + 37715,37674,37633,37592,37551,37509,37468,37427, + 37386,37344,37303,37262,37220,37179,37137,37096, + 37055,37013,36972,36930,36889,36847,36805,36764, + 36722,36681,36639,36597,36556,36514,36472,36430, + 36388,36347,36305,36263,36221,36179,36137,36095, + 36053,36011,35969,35927,35885,35843,35801,35759, + 35717,35675,35633,35590,35548,35506,35464,35421, + 35379,35337,35294,35252,35210,35167,35125,35082, + 35040,34997,34955,34912,34870,34827,34785,34742, + 34699,34657,34614,34571,34529,34486,34443,34400, + 34358,34315,34272,34229,34186,34143,34100,34057, + 34015,33972,33929,33886,33843,33799,33756,33713, + 33670,33627,33584,33541,33498,33454,33411,33368, + 33325,33281,33238,33195,33151,33108,33065,33021, + 32978,32934,32891,32847,32804,32760,32717,32673, + 32630,32586,32542,32499,32455,32411,32368,32324, + 32280,32236,32193,32149,32105,32061,32017,31974, + 31930,31886,31842,31798,31754,31710,31666,31622, + 31578,31534,31490,31446,31402,31357,31313,31269, + 31225,31181,31136,31092,31048,31004,30959,30915, + 30871,30826,30782,30738,30693,30649,30604,30560, + 30515,30471,30426,30382,30337,30293,30248,30204, + 30159,30114,30070,30025,29980,29936,29891,29846, + 29801,29757,29712,29667,29622,29577,29533,29488, + 29443,29398,29353,29308,29263,29218,29173,29128, + 29083,29038,28993,28948,28903,28858,28812,28767, + 28722,28677,28632,28586,28541,28496,28451,28405, + 28360,28315,28269,28224,28179,28133,28088,28042, + 27997,27952,27906,27861,27815,27770,27724,27678, + 27633,27587,27542,27496,27450,27405,27359,27313, + 27268,27222,27176,27131,27085,27039,26993,26947, + 26902,26856,26810,26764,26718,26672,26626,26580, + 26534,26488,26442,26396,26350,26304,26258,26212, + 26166,26120,26074,26028,25982,25936,25889,25843, + 25797,25751,25705,25658,25612,25566,25520,25473, + 25427,25381,25334,25288,25241,25195,25149,25102, + 25056,25009,24963,24916,24870,24823,24777,24730, + 24684,24637,24591,24544,24497,24451,24404,24357, + 24311,24264,24217,24171,24124,24077,24030,23984, + 23937,23890,23843,23796,23750,23703,23656,23609, + 23562,23515,23468,23421,23374,23327,23280,23233, + 23186,23139,23092,23045,22998,22951,22904,22857, + 22810,22763,22716,22668,22621,22574,22527,22480, + 22433,22385,22338,22291,22243,22196,22149,22102, + 22054,22007,21960,21912,21865,21817,21770,21723, + 21675,21628,21580,21533,21485,21438,21390,21343, + 21295,21248,21200,21153,21105,21057,21010,20962, + 20915,20867,20819,20772,20724,20676,20629,20581, + 20533,20485,20438,20390,20342,20294,20246,20199, + 20151,20103,20055,20007,19959,19912,19864,19816, + 19768,19720,19672,19624,19576,19528,19480,19432, + 19384,19336,19288,19240,19192,19144,19096,19048, + 19000,18951,18903,18855,18807,18759,18711,18663, + 18614,18566,18518,18470,18421,18373,18325,18277, + 18228,18180,18132,18084,18035,17987,17939,17890, + 17842,17793,17745,17697,17648,17600,17551,17503, + 17455,17406,17358,17309,17261,17212,17164,17115, + 17067,17018,16970,16921,16872,16824,16775,16727, + 16678,16629,16581,16532,16484,16435,16386,16338, + 16289,16240,16191,16143,16094,16045,15997,15948, + 15899,15850,15802,15753,15704,15655,15606,15557, + 15509,15460,15411,15362,15313,15264,15215,15167, + 15118,15069,15020,14971,14922,14873,14824,14775, + 14726,14677,14628,14579,14530,14481,14432,14383, + 14334,14285,14236,14187,14138,14089,14040,13990, + 13941,13892,13843,13794,13745,13696,13646,13597, + 13548,13499,13450,13401,13351,13302,13253,13204, + 13154,13105,13056,13007,12957,12908,12859,12810, + 12760,12711,12662,12612,12563,12514,12464,12415, + 12366,12316,12267,12218,12168,12119,12069,12020, + 11970,11921,11872,11822,11773,11723,11674,11624, + 11575,11525,11476,11426,11377,11327,11278,11228, + 11179,11129,11080,11030,10981,10931,10882,10832, + 10782,10733,10683,10634,10584,10534,10485,10435, + 10386,10336,10286,10237,10187,10137,10088,10038, + 9988,9939,9889,9839,9790,9740,9690,9640, + 9591,9541,9491,9442,9392,9342,9292,9243, + 9193,9143,9093,9043,8994,8944,8894,8844, + 8794,8745,8695,8645,8595,8545,8496,8446, + 8396,8346,8296,8246,8196,8147,8097,8047, + 7997,7947,7897,7847,7797,7747,7697,7648, + 7598,7548,7498,7448,7398,7348,7298,7248, + 7198,7148,7098,7048,6998,6948,6898,6848, + 6798,6748,6698,6648,6598,6548,6498,6448, + 6398,6348,6298,6248,6198,6148,6098,6048, + 5998,5948,5898,5848,5798,5748,5697,5647, + 5597,5547,5497,5447,5397,5347,5297,5247, + 5197,5146,5096,5046,4996,4946,4896,4846, + 4796,4745,4695,4645,4595,4545,4495,4445, + 4394,4344,4294,4244,4194,4144,4093,4043, + 3993,3943,3893,3843,3792,3742,3692,3642, + 3592,3541,3491,3441,3391,3341,3291,3240, + 3190,3140,3090,3039,2989,2939,2889,2839, + 2788,2738,2688,2638,2587,2537,2487,2437, + 2387,2336,2286,2236,2186,2135,2085,2035, + 1985,1934,1884,1834,1784,1733,1683,1633, + 1583,1532,1482,1432,1382,1331,1281,1231, + 1181,1130,1080,1030,980,929,879,829, + 779,728,678,628,578,527,477,427, + 376,326,276,226,175,125,75,25, + -25,-75,-125,-175,-226,-276,-326,-376, + -427,-477,-527,-578,-628,-678,-728,-779, + -829,-879,-929,-980,-1030,-1080,-1130,-1181, + -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583, + -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985, + -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387, + -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788, + -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190, + -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592, + -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993, + -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394, + -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796, + -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197, + -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597, + -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998, + -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398, + -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798, + -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198, + -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598, + -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997, + -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396, + -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794, + -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193, + -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591, + -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988, + -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386, + -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782, + -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179, + -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575, + -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970, + -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366, + -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760, + -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154, + -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548, + -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941, + -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334, + -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726, + -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118, + -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509, + -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899, + -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289, + -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678, + -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067, + -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455, + -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842, + -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228, + -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614, + -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000, + -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384, + -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768, + -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151, + -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533, + -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915, + -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295, + -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675, + -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054, + -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433, + -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810, + -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186, + -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562, + -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937, + -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311, + -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684, + -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056, + -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427, + -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797, + -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166, + -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534, + -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902, + -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268, + -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633, + -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997, + -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360, + -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722, + -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083, + -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443, + -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801, + -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159, + -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515, + -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871, + -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225, + -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578, + -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930, + -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280, + -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630, + -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978, + -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325, + -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670, + -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015, + -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358, + -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699, + -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040, + -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379, + -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717, + -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053, + -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388, + -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722, + -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055, + -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386, + -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715, + -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043, + -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370, + -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695, + -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019, + -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341, + -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662, + -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982, + -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299, + -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616, + -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931, + -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244, + -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556, + -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866, + -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174, + -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481, + -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787, + -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091, + -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393, + -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693, + -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992, + -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289, + -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585, + -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879, + -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171, + -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462, + -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750, + -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037, + -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323, + -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606, + -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888, + -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168, + -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446, + -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723, + -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998, + -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271, + -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542, + -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811, + -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078, + -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344, + -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608, + -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869, + -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129, + -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387, + -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644, + -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898, + -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150, + -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401, + -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649, + -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896, + -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140, + -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383, + -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624, + -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862, + -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099, + -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334, + -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566, + -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797, + -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026, + -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252, + -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477, + -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699, + -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920, + -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138, + -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354, + -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569, + -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781, + -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991, + -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199, + -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404, + -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608, + -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810, + -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009, + -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206, + -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402, + -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594, + -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785, + -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974, + -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160, + -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345, + -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527, + -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706, + -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884, + -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059, + -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233, + -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404, + -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572, + -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739, + -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903, + -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065, + -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225, + -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382, + -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537, + -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690, + -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841, + -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989, + -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135, + -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279, + -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420, + -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559, + -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696, + -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831, + -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963, + -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092, + -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220, + -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345, + -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468, + -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588, + -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706, + -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822, + -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935, + -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046, + -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155, + -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261, + -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365, + -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466, + -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565, + -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662, + -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756, + -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848, + -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938, + -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025, + -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109, + -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192, + -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271, + -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349, + -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424, + -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496, + -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566, + -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634, + -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699, + -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762, + -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822, + -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880, + -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936, + -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989, + -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040, + -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088, + -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133, + -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177, + -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217, + -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256, + -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292, + -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325, + -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356, + -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385, + -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411, + -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434, + -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455, + -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474, + -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490, + -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504, + -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515, + -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524, + -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530, + -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534, + -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535, + -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534, + -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531, + -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525, + -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516, + -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505, + -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492, + -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476, + -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458, + -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437, + -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414, + -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388, + -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360, + -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329, + -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296, + -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260, + -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222, + -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182, + -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139, + -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094, + -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046, + -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995, + -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943, + -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887, + -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830, + -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770, + -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707, + -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642, + -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575, + -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505, + -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433, + -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358, + -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281, + -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202, + -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120, + -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035, + -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949, + -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859, + -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768, + -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674, + -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578, + -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479, + -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378, + -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274, + -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168, + -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060, + -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949, + -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836, + -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721, + -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603, + -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483, + -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360, + -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236, + -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108, + -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979, + -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847, + -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713, + -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577, + -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438, + -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297, + -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153, + -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007, + -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859, + -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709, + -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556, + -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402, + -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244, + -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085, + -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923, + -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759, + -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593, + -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425, + -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254, + -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081, + -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906, + -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729, + -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549, + -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367, + -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183, + -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997, + -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809, + -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618, + -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426, + -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231, + -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034, + -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835, + -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633, + -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430, + -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225, + -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017, + -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807, + -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595, + -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381, + -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165, + -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947, + -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727, + -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505, + -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280, + -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054, + -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826, + -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595, + -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363, + -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128, + -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892, + -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653, + -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413, + -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171, + -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926, + -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680, + -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432, + -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182, + -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929, + -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675, + -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420, + -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162, + -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902, + -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640, + -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377, + -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112, + -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844, + -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575, + -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305, + -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032, + -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757, + -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481, + -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203, + -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923, + -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642, + -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358, + -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073, + -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786, + -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498, + -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207, + -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915, + -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622, + -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326, + -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029, + -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731, + -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430, + -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128, + -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825, + -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520, + -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213, + -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904, + -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595, + -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283, + -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970, + -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655, + -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339, + -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021, + -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702, + -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382, + -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059, + -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736, + -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411, + -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084, + -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756, + -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427, + -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096, + -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764, + -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430, + -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095, + -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759, + -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421, + -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082, + -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742, + -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400, + -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057, + -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713, + -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368, + -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021, + -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673, + -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324, + -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974, + -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622, + -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269, + -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915, + -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560, + -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204, + -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846, + -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488, + -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128, + -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767, + -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405, + -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042, + -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678, + -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313, + -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947, + -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580, + -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212, + -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843, + -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473, + -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102, + -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730, + -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357, + -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984, + -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609, + -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233, + -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857, + -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480, + -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102, + -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723, + -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343, + -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962, + -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581, + -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199, + -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816, + -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432, + -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048, + -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663, + -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277, + -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890, + -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503, + -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115, + -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727, + -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338, + -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948, + -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557, + -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167, + -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775, + -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383, + -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990, + -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597, + -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204, + -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810, + -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415, + -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020, + -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624, + -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228, + -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832, + -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435, + -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038, + -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640, + -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243, + -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844, + -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446, + -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047, + -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648, + -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248, + -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848, + -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448, + -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048, + -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647, + -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247, + -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846, + -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445, + -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043, + -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642, + -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240, + -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839, + -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437, + -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035, + -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633, + -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231, + -1181,-1130,-1080,-1030,-980,-929,-879,-829, + -779,-728,-678,-628,-578,-527,-477,-427, + -376,-326,-276,-226,-175,-125,-75,-25, + 25,75,125,175,226,276,326,376, + 427,477,527,578,628,678,728,779, + 829,879,929,980,1030,1080,1130,1181, + 1231,1281,1331,1382,1432,1482,1532,1583, + 1633,1683,1733,1784,1834,1884,1934,1985, + 2035,2085,2135,2186,2236,2286,2336,2387, + 2437,2487,2537,2587,2638,2688,2738,2788, + 2839,2889,2939,2989,3039,3090,3140,3190, + 3240,3291,3341,3391,3441,3491,3542,3592, + 3642,3692,3742,3792,3843,3893,3943,3993, + 4043,4093,4144,4194,4244,4294,4344,4394, + 4445,4495,4545,4595,4645,4695,4745,4796, + 4846,4896,4946,4996,5046,5096,5146,5197, + 5247,5297,5347,5397,5447,5497,5547,5597, + 5647,5697,5747,5798,5848,5898,5948,5998, + 6048,6098,6148,6198,6248,6298,6348,6398, + 6448,6498,6548,6598,6648,6698,6748,6798, + 6848,6898,6948,6998,7048,7098,7148,7198, + 7248,7298,7348,7398,7448,7498,7548,7598, + 7648,7697,7747,7797,7847,7897,7947,7997, + 8047,8097,8147,8196,8246,8296,8346,8396, + 8446,8496,8545,8595,8645,8695,8745,8794, + 8844,8894,8944,8994,9043,9093,9143,9193, + 9243,9292,9342,9392,9442,9491,9541,9591, + 9640,9690,9740,9790,9839,9889,9939,9988, + 10038,10088,10137,10187,10237,10286,10336,10386, + 10435,10485,10534,10584,10634,10683,10733,10782, + 10832,10882,10931,10981,11030,11080,11129,11179, + 11228,11278,11327,11377,11426,11476,11525,11575, + 11624,11674,11723,11773,11822,11872,11921,11970, + 12020,12069,12119,12168,12218,12267,12316,12366, + 12415,12464,12514,12563,12612,12662,12711,12760, + 12810,12859,12908,12957,13007,13056,13105,13154, + 13204,13253,13302,13351,13401,13450,13499,13548, + 13597,13647,13696,13745,13794,13843,13892,13941, + 13990,14040,14089,14138,14187,14236,14285,14334, + 14383,14432,14481,14530,14579,14628,14677,14726, + 14775,14824,14873,14922,14971,15020,15069,15118, + 15167,15215,15264,15313,15362,15411,15460,15509, + 15557,15606,15655,15704,15753,15802,15850,15899, + 15948,15997,16045,16094,16143,16191,16240,16289, + 16338,16386,16435,16484,16532,16581,16629,16678, + 16727,16775,16824,16872,16921,16970,17018,17067, + 17115,17164,17212,17261,17309,17358,17406,17455, + 17503,17551,17600,17648,17697,17745,17793,17842, + 17890,17939,17987,18035,18084,18132,18180,18228, + 18277,18325,18373,18421,18470,18518,18566,18614, + 18663,18711,18759,18807,18855,18903,18951,19000, + 19048,19096,19144,19192,19240,19288,19336,19384, + 19432,19480,19528,19576,19624,19672,19720,19768, + 19816,19864,19912,19959,20007,20055,20103,20151, + 20199,20246,20294,20342,20390,20438,20485,20533, + 20581,20629,20676,20724,20772,20819,20867,20915, + 20962,21010,21057,21105,21153,21200,21248,21295, + 21343,21390,21438,21485,21533,21580,21628,21675, + 21723,21770,21817,21865,21912,21960,22007,22054, + 22102,22149,22196,22243,22291,22338,22385,22432, + 22480,22527,22574,22621,22668,22716,22763,22810, + 22857,22904,22951,22998,23045,23092,23139,23186, + 23233,23280,23327,23374,23421,23468,23515,23562, + 23609,23656,23703,23750,23796,23843,23890,23937, + 23984,24030,24077,24124,24171,24217,24264,24311, + 24357,24404,24451,24497,24544,24591,24637,24684, + 24730,24777,24823,24870,24916,24963,25009,25056, + 25102,25149,25195,25241,25288,25334,25381,25427, + 25473,25520,25566,25612,25658,25705,25751,25797, + 25843,25889,25936,25982,26028,26074,26120,26166, + 26212,26258,26304,26350,26396,26442,26488,26534, + 26580,26626,26672,26718,26764,26810,26856,26902, + 26947,26993,27039,27085,27131,27176,27222,27268, + 27313,27359,27405,27450,27496,27542,27587,27633, + 27678,27724,27770,27815,27861,27906,27952,27997, + 28042,28088,28133,28179,28224,28269,28315,28360, + 28405,28451,28496,28541,28586,28632,28677,28722, + 28767,28812,28858,28903,28948,28993,29038,29083, + 29128,29173,29218,29263,29308,29353,29398,29443, + 29488,29533,29577,29622,29667,29712,29757,29801, + 29846,29891,29936,29980,30025,30070,30114,30159, + 30204,30248,30293,30337,30382,30427,30471,30516, + 30560,30604,30649,30693,30738,30782,30826,30871, + 30915,30959,31004,31048,31092,31136,31181,31225, + 31269,31313,31357,31402,31446,31490,31534,31578, + 31622,31666,31710,31754,31798,31842,31886,31930, + 31974,32017,32061,32105,32149,32193,32236,32280, + 32324,32368,32411,32455,32499,32542,32586,32630, + 32673,32717,32760,32804,32847,32891,32934,32978, + 33021,33065,33108,33151,33195,33238,33281,33325, + 33368,33411,33454,33498,33541,33584,33627,33670, + 33713,33756,33799,33843,33886,33929,33972,34015, + 34057,34100,34143,34186,34229,34272,34315,34358, + 34400,34443,34486,34529,34571,34614,34657,34699, + 34742,34785,34827,34870,34912,34955,34997,35040, + 35082,35125,35167,35210,35252,35294,35337,35379, + 35421,35464,35506,35548,35590,35633,35675,35717, + 35759,35801,35843,35885,35927,35969,36011,36053, + 36095,36137,36179,36221,36263,36305,36347,36388, + 36430,36472,36514,36556,36597,36639,36681,36722, + 36764,36805,36847,36889,36930,36972,37013,37055, + 37096,37137,37179,37220,37262,37303,37344,37386, + 37427,37468,37509,37551,37592,37633,37674,37715, + 37756,37797,37838,37879,37920,37961,38002,38043, + 38084,38125,38166,38207,38248,38288,38329,38370, + 38411,38451,38492,38533,38573,38614,38655,38695, + 38736,38776,38817,38857,38898,38938,38979,39019, + 39059,39100,39140,39180,39221,39261,39301,39341, + 39382,39422,39462,39502,39542,39582,39622,39662, + 39702,39742,39782,39822,39862,39902,39942,39982, + 40021,40061,40101,40141,40180,40220,40260,40299, + 40339,40379,40418,40458,40497,40537,40576,40616, + 40655,40695,40734,40773,40813,40852,40891,40931, + 40970,41009,41048,41087,41127,41166,41205,41244, + 41283,41322,41361,41400,41439,41478,41517,41556, + 41595,41633,41672,41711,41750,41788,41827,41866, + 41904,41943,41982,42020,42059,42097,42136,42174, + 42213,42251,42290,42328,42366,42405,42443,42481, + 42520,42558,42596,42634,42672,42711,42749,42787, + 42825,42863,42901,42939,42977,43015,43053,43091, + 43128,43166,43204,43242,43280,43317,43355,43393, + 43430,43468,43506,43543,43581,43618,43656,43693, + 43731,43768,43806,43843,43880,43918,43955,43992, + 44029,44067,44104,44141,44178,44215,44252,44289, + 44326,44363,44400,44437,44474,44511,44548,44585, + 44622,44659,44695,44732,44769,44806,44842,44879, + 44915,44952,44989,45025,45062,45098,45135,45171, + 45207,45244,45280,45316,45353,45389,45425,45462, + 45498,45534,45570,45606,45642,45678,45714,45750, + 45786,45822,45858,45894,45930,45966,46002,46037, + 46073,46109,46145,46180,46216,46252,46287,46323, + 46358,46394,46429,46465,46500,46536,46571,46606, + 46642,46677,46712,46747,46783,46818,46853,46888, + 46923,46958,46993,47028,47063,47098,47133,47168, + 47203,47238,47273,47308,47342,47377,47412,47446, + 47481,47516,47550,47585,47619,47654,47688,47723, + 47757,47792,47826,47861,47895,47929,47963,47998, + 48032,48066,48100,48134,48168,48202,48237,48271, + 48305,48338,48372,48406,48440,48474,48508,48542, + 48575,48609,48643,48676,48710,48744,48777,48811, + 48844,48878,48911,48945,48978,49012,49045,49078, + 49112,49145,49178,49211,49244,49278,49311,49344, + 49377,49410,49443,49476,49509,49542,49575,49608, + 49640,49673,49706,49739,49771,49804,49837,49869, + 49902,49935,49967,50000,50032,50064,50097,50129, + 50162,50194,50226,50259,50291,50323,50355,50387, + 50420,50452,50484,50516,50548,50580,50612,50644, + 50675,50707,50739,50771,50803,50834,50866,50898, + 50929,50961,50993,51024,51056,51087,51119,51150, + 51182,51213,51244,51276,51307,51338,51369,51401, + 51432,51463,51494,51525,51556,51587,51618,51649, + 51680,51711,51742,51773,51803,51834,51865,51896, + 51926,51957,51988,52018,52049,52079,52110,52140, + 52171,52201,52231,52262,52292,52322,52353,52383, + 52413,52443,52473,52503,52534,52564,52594,52624, + 52653,52683,52713,52743,52773,52803,52832,52862, + 52892,52922,52951,52981,53010,53040,53069,53099, + 53128,53158,53187,53216,53246,53275,53304,53334, + 53363,53392,53421,53450,53479,53508,53537,53566, + 53595,53624,53653,53682,53711,53739,53768,53797, + 53826,53854,53883,53912,53940,53969,53997,54026, + 54054,54082,54111,54139,54167,54196,54224,54252, + 54280,54309,54337,54365,54393,54421,54449,54477, + 54505,54533,54560,54588,54616,54644,54672,54699, + 54727,54755,54782,54810,54837,54865,54892,54920, + 54947,54974,55002,55029,55056,55084,55111,55138, + 55165,55192,55219,55246,55274,55300,55327,55354, + 55381,55408,55435,55462,55489,55515,55542,55569, + 55595,55622,55648,55675,55701,55728,55754,55781, + 55807,55833,55860,55886,55912,55938,55965,55991, + 56017,56043,56069,56095,56121,56147,56173,56199, + 56225,56250,56276,56302,56328,56353,56379,56404, + 56430,56456,56481,56507,56532,56557,56583,56608, + 56633,56659,56684,56709,56734,56760,56785,56810, + 56835,56860,56885,56910,56935,56959,56984,57009, + 57034,57059,57083,57108,57133,57157,57182,57206, + 57231,57255,57280,57304,57329,57353,57377,57402, + 57426,57450,57474,57498,57522,57546,57570,57594, + 57618,57642,57666,57690,57714,57738,57762,57785, + 57809,57833,57856,57880,57903,57927,57950,57974, + 57997,58021,58044,58067,58091,58114,58137,58160, + 58183,58207,58230,58253,58276,58299,58322,58345, + 58367,58390,58413,58436,58459,58481,58504,58527, + 58549,58572,58594,58617,58639,58662,58684,58706, + 58729,58751,58773,58795,58818,58840,58862,58884, + 58906,58928,58950,58972,58994,59016,59038,59059, + 59081,59103,59125,59146,59168,59190,59211,59233, + 59254,59276,59297,59318,59340,59361,59382,59404, + 59425,59446,59467,59488,59509,59530,59551,59572, + 59593,59614,59635,59656,59677,59697,59718,59739, + 59759,59780,59801,59821,59842,59862,59883,59903, + 59923,59944,59964,59984,60004,60025,60045,60065, + 60085,60105,60125,60145,60165,60185,60205,60225, + 60244,60264,60284,60304,60323,60343,60363,60382, + 60402,60421,60441,60460,60479,60499,60518,60537, + 60556,60576,60595,60614,60633,60652,60671,60690, + 60709,60728,60747,60766,60785,60803,60822,60841, + 60859,60878,60897,60915,60934,60952,60971,60989, + 61007,61026,61044,61062,61081,61099,61117,61135, + 61153,61171,61189,61207,61225,61243,61261,61279, + 61297,61314,61332,61350,61367,61385,61403,61420, + 61438,61455,61473,61490,61507,61525,61542,61559, + 61577,61594,61611,61628,61645,61662,61679,61696, + 61713,61730,61747,61764,61780,61797,61814,61831, + 61847,61864,61880,61897,61913,61930,61946,61963, + 61979,61995,62012,62028,62044,62060,62076,62092, + 62108,62125,62141,62156,62172,62188,62204,62220, + 62236,62251,62267,62283,62298,62314,62329,62345, + 62360,62376,62391,62407,62422,62437,62453,62468, + 62483,62498,62513,62528,62543,62558,62573,62588, + 62603,62618,62633,62648,62662,62677,62692,62706, + 62721,62735,62750,62764,62779,62793,62808,62822, + 62836,62850,62865,62879,62893,62907,62921,62935, + 62949,62963,62977,62991,63005,63019,63032,63046, + 63060,63074,63087,63101,63114,63128,63141,63155, + 63168,63182,63195,63208,63221,63235,63248,63261, + 63274,63287,63300,63313,63326,63339,63352,63365, + 63378,63390,63403,63416,63429,63441,63454,63466, + 63479,63491,63504,63516,63528,63541,63553,63565, + 63578,63590,63602,63614,63626,63638,63650,63662, + 63674,63686,63698,63709,63721,63733,63745,63756, + 63768,63779,63791,63803,63814,63825,63837,63848, + 63859,63871,63882,63893,63904,63915,63927,63938, + 63949,63960,63971,63981,63992,64003,64014,64025, + 64035,64046,64057,64067,64078,64088,64099,64109, + 64120,64130,64140,64151,64161,64171,64181,64192, + 64202,64212,64222,64232,64242,64252,64261,64271, + 64281,64291,64301,64310,64320,64330,64339,64349, + 64358,64368,64377,64387,64396,64405,64414,64424, + 64433,64442,64451,64460,64469,64478,64487,64496, + 64505,64514,64523,64532,64540,64549,64558,64566, + 64575,64584,64592,64600,64609,64617,64626,64634, + 64642,64651,64659,64667,64675,64683,64691,64699, + 64707,64715,64723,64731,64739,64747,64754,64762, + 64770,64777,64785,64793,64800,64808,64815,64822, + 64830,64837,64844,64852,64859,64866,64873,64880, + 64887,64895,64902,64908,64915,64922,64929,64936, + 64943,64949,64956,64963,64969,64976,64982,64989, + 64995,65002,65008,65015,65021,65027,65033,65040, + 65046,65052,65058,65064,65070,65076,65082,65088, + 65094,65099,65105,65111,65117,65122,65128,65133, + 65139,65144,65150,65155,65161,65166,65171,65177, + 65182,65187,65192,65197,65202,65207,65212,65217, + 65222,65227,65232,65237,65242,65246,65251,65256, + 65260,65265,65270,65274,65279,65283,65287,65292, + 65296,65300,65305,65309,65313,65317,65321,65325, + 65329,65333,65337,65341,65345,65349,65352,65356, + 65360,65363,65367,65371,65374,65378,65381,65385, + 65388,65391,65395,65398,65401,65404,65408,65411, + 65414,65417,65420,65423,65426,65429,65431,65434, + 65437,65440,65442,65445,65448,65450,65453,65455, + 65458,65460,65463,65465,65467,65470,65472,65474, + 65476,65478,65480,65482,65484,65486,65488,65490, + 65492,65494,65496,65497,65499,65501,65502,65504, + 65505,65507,65508,65510,65511,65513,65514,65515, + 65516,65518,65519,65520,65521,65522,65523,65524, + 65525,65526,65527,65527,65528,65529,65530,65530, + 65531,65531,65532,65532,65533,65533,65534,65534, + 65534,65535,65535,65535,65535,65535,65535,65535 +}; + +const fixed_t *finecosine = &finesine[FINEANGLES/4]; + +const angle_t tantoangle[2049] = +{ + 0,333772,667544,1001315,1335086,1668857,2002626,2336395, + 2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492, + 5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435, + 8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145, + 10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539, + 13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536, + 16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054, + 18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014, + 21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332, + 24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930, + 26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724, + 29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636, + 32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584, + 34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492, + 37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272, + 40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848, + 42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140, + 45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072, + 47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556, + 50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524, + 53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888, + 55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576, + 58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508, + 61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604, + 63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788, + 66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984, + 69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112, + 71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096, + 74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864, + 77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336, + 79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440, + 82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096, + 85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240, + 87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792, + 90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672, + 92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816, + 95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144, + 98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592, + 100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080, + 103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552, + 105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920, + 108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120, + 111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080, + 113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744, + 116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024, + 118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864, + 121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200, + 124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960, + 126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072, + 129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480, + 131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120, + 134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912, + 136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808, + 139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752, + 142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664, + 144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480, + 147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152, + 149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616, + 152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824, + 154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696, + 157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168, + 159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208, + 162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752, + 164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736, + 167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096, + 169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800, + 172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784, + 174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984, + 177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368, + 179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856, + 182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416, + 184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000, + 187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560, + 189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016, + 192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352, + 194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520, + 197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456, + 199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128, + 202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472, + 204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456, + 207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048, + 209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184, + 211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816, + 214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928, + 216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472, + 219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384, + 221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664, + 223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232, + 226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088, + 228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152, + 231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440, + 233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872, + 235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416, + 238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072, + 240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776, + 242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496, + 245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216, + 247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904, + 249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512, + 252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008, + 254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392, + 256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600, + 259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632, + 261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456, + 263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024, + 266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336, + 268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360, + 270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048, + 272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432, + 275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416, + 277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032, + 279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248, + 281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032, + 284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384, + 286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240, + 288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632, + 290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528, + 293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864, + 295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704, + 297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952, + 299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640, + 301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768, + 303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272, + 306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152, + 308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408, + 310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040, + 312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016, + 314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336, + 316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968, + 319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912, + 321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200, + 323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736, + 325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584, + 327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712, + 329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120, + 331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776, + 333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712, + 335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864, + 337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296, + 340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976, + 342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904, + 344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048, + 346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440, + 348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048, + 350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872, + 352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944, + 354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264, + 356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768, + 358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520, + 360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488, + 362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704, + 364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136, + 366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784, + 368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680, + 370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792, + 372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152, + 374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760, + 376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584, + 377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688, + 379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040, + 381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640, + 383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488, + 385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616, + 387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024, + 389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712, + 391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680, + 393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960, + 395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520, + 396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424, + 398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608, + 400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136, + 402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008, + 404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224, + 406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784, + 408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720, + 409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032, + 411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720, + 413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784, + 415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288, + 417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200, + 418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552, + 420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344, + 422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576, + 424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280, + 425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488, + 427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168, + 429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352, + 431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040, + 432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296, + 434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088, + 436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416, + 438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344, + 439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872, + 441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968, + 443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696, + 444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088, + 446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112, + 448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800, + 450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152, + 451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232, + 453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008, + 454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512, + 456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744, + 458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768, + 459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584, + 461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160, + 463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560, + 464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816, + 466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896, + 468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832, + 469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688, + 471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400, + 472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064, + 474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648, + 475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184, + 477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704, + 479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240, + 480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760, + 482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296, + 483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912, + 485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576, + 486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320, + 488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176, + 489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144, + 491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256, + 492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544, + 494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008, + 495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680, + 497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560, + 498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680, + 500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040, + 501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704, + 503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672, + 504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944, + 506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552, + 507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528, + 509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872, + 510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616, + 511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792, + 513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368, + 514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440, + 516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976, + 517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008, + 519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568, + 520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656, + 521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304, + 523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512, + 524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344, + 526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800, + 527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880, + 528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648, + 530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072, + 531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184, + 532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048, + 534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632, + 535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000, + 536870912 +}; + +// Now where did these came from? +const byte gammatable[5][256] = +{ + { + 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, + 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, + 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, + 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96, + 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, + 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 + }, + + { + 2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23, + 24,25,26,27,29,30,31,32,33,34,36,37,38,39,40,41, + 42,44,45,46,47,48,49,50,51,52,54,55,56,57,58,59, + 60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76, + 77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92, + 93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108, + 109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124, + 125,126,127,128,129,129,130,131,132,133,134,135,136,137,138,139, + 140,141,142,143,144,145,146,147,148,148,149,150,151,152,153,154, + 155,156,157,158,159,160,161,162,163,163,164,165,166,167,168,169, + 170,171,172,173,174,175,175,176,177,178,179,180,181,182,183,184, + 185,186,186,187,188,189,190,191,192,193,194,195,196,196,197,198, + 199,200,201,202,203,204,205,205,206,207,208,209,210,211,212,213, + 214,214,215,216,217,218,219,220,221,222,222,223,224,225,226,227, + 228,229,230,230,231,232,233,234,235,236,237,237,238,239,240,241, + 242,243,244,245,245,246,247,248,249,250,251,252,252,253,254,255 + }, + + { + 4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32, + 33,35,36,38,39,40,42,43,45,46,47,48,50,51,52,54, + 55,56,57,59,60,61,62,63,65,66,67,68,69,70,72,73, + 74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90, + 91,92,93,94,95,96,97,98,100,101,102,103,104,105,106,107, + 108,109,110,111,112,113,114,114,115,116,117,118,119,120,121,122, + 123,124,125,126,127,128,129,130,131,132,133,133,134,135,136,137, + 138,139,140,141,142,143,144,144,145,146,147,148,149,150,151,152, + 153,153,154,155,156,157,158,159,160,160,161,162,163,164,165,166, + 166,167,168,169,170,171,172,172,173,174,175,176,177,178,178,179, + 180,181,182,183,183,184,185,186,187,188,188,189,190,191,192,193, + 193,194,195,196,197,197,198,199,200,201,201,202,203,204,205,206, + 206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218, + 219,220,221,221,222,223,224,224,225,226,227,228,228,229,230,231, + 231,232,233,234,235,235,236,237,238,238,239,240,241,241,242,243, + 244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,255 + }, + + { + 8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45, + 47,49,50,52,53,55,57,58,60,61,63,64,65,67,68,70, + 71,72,74,75,76,77,79,80,81,82,84,85,86,87,88,90, + 91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107, + 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123, + 124,125,126,127,128,129,130,131,132,133,134,135,135,136,137,138, + 139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152, + 153,154,155,155,156,157,158,159,160,160,161,162,163,164,165,165, + 166,167,168,169,169,170,171,172,173,173,174,175,176,176,177,178, + 179,180,180,181,182,183,183,184,185,186,186,187,188,189,189,190, + 191,192,192,193,194,195,195,196,197,197,198,199,200,200,201,202, + 202,203,204,205,205,206,207,207,208,209,210,210,211,212,212,213, + 214,214,215,216,216,217,218,219,219,220,221,221,222,223,223,224, + 225,225,226,227,227,228,229,229,230,231,231,232,233,233,234,235, + 235,236,237,237,238,238,239,240,240,241,242,242,243,244,244,245, + 246,246,247,247,248,249,249,250,251,251,252,253,253,254,254,255 + }, + + + { + 16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64, + 66,68,69,71,73,75,76,78,80,81,83,84,86,87,89,90, + 92,93,94,96,97,98,100,101,102,103,105,106,107,108,109,110, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156, + 157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169, + 169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180, + 181,182,182,183,184,184,185,186,187,187,188,189,189,190,191,191, + 192,193,193,194,195,195,196,196,197,198,198,199,200,200,201,202, + 202,203,203,204,205,205,206,207,207,208,208,209,210,210,211,211, + 212,213,213,214,214,215,216,216,217,217,218,219,219,220,220,221, + 221,222,223,223,224,224,225,225,226,227,227,228,228,229,229,230, + 230,231,232,232,233,233,234,234,235,235,236,236,237,237,238,239, + 239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247, + 247,248,248,249,249,250,250,251,251,252,252,253,254,254,255,255 + } +}; + diff --git a/games/NXDoom/src/tables.h b/games/NXDoom/src/tables.h new file mode 100644 index 00000000000..f72406da4d1 --- /dev/null +++ b/games/NXDoom/src/tables.h @@ -0,0 +1,96 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Lookup tables. +// Do not try to look them up :-). +// In the order of appearance: +// +// int finetangent[4096] - Tangens LUT. +// Should work with BAM fairly well (12 of 16bit, +// effectively, by shifting). +// +// int finesine[10240] - Sine lookup. +// Guess what, serves as cosine, too. +// Remarkable thing is, how to use BAMs with this? +// +// int tantoangle[2049] - ArcTan LUT, +// maps tan(angle) to angle fast. Gotta search. +// + + +#ifndef __TABLES__ +#define __TABLES__ + +#include "doomtype.h" + +#include "m_fixed.h" + +#define FINEANGLES 8192 +#define FINEMASK (FINEANGLES-1) + + +// 0x100000000 to 0x2000 +#define ANGLETOFINESHIFT 19 + +// Effective size is 10240. +extern const fixed_t finesine[5*FINEANGLES/4]; + +// Re-use data, is just PI/2 pahse shift. +extern const fixed_t *finecosine; + + +// Effective size is 4096. +extern const fixed_t finetangent[FINEANGLES/2]; + +// Gamma correction tables. +extern const byte gammatable[5][256]; + +// Binary Angle Measument, BAM. + +#define ANG45 0x20000000 +#define ANG90 0x40000000 +#define ANG180 0x80000000 +#define ANG270 0xc0000000 +#define ANG_MAX 0xffffffff + +#define ANG1 (ANG45 / 45) +#define ANG60 (ANG180 / 3) + +// Heretic code uses this definition as though it represents one +// degree, but it is not! This is actually ~1.40 degrees. + +#define ANG1_X 0x01000000 + +#define SLOPERANGE 2048 +#define SLOPEBITS 11 +#define DBITS (FRACBITS-SLOPEBITS) + +typedef unsigned int angle_t; + + +// Effective size is 2049; +// The +1 size is to handle the case when x==y +// without additional checking. +extern const angle_t tantoangle[SLOPERANGE+1]; + + +// Utility function, +// called by R_PointToAngle. +int SlopeDiv(unsigned int num, unsigned int den); + + +#endif + diff --git a/games/NXDoom/src/v_diskicon.c b/games/NXDoom/src/v_diskicon.c new file mode 100644 index 00000000000..1631ba7b992 --- /dev/null +++ b/games/NXDoom/src/v_diskicon.c @@ -0,0 +1,160 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Disk load indicator. +// + +#include "doomtype.h" +#include "deh_str.h" +#include "i_swap.h" +#include "i_video.h" +#include "m_argv.h" +#include "v_video.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "v_diskicon.h" + +#include + +// Only display the disk icon if more then this much bytes have been read +// during the previous tic. + +static const int diskicon_threshold = 20*1024; + +// Two buffers: disk_data contains the data representing the disk icon +// (raw, not a patch_t) while saved_background is an equivalently-sized +// buffer where we save the background data while the disk is on screen. +static pixel_t *disk_data; +static pixel_t *saved_background; + +static int loading_disk_xoffs = 0; +static int loading_disk_yoffs = 0; + +// Number of bytes read since the last call to V_DrawDiskIcon(). +static size_t recent_bytes_read = 0; +static boolean disk_drawn; + +static void CopyRegion(pixel_t *dest, int dest_pitch, + pixel_t *src, int src_pitch, + int w, int h) +{ + pixel_t *s, *d; + int y; + + s = src; d = dest; + for (y = 0; y < h; ++y) + { + memcpy(d, s, w * sizeof(*d)); + s += src_pitch; + d += dest_pitch; + } +} + +static void SaveDiskData(const char *disk_lump, int xoffs, int yoffs) +{ + pixel_t *tmpscreen; + patch_t *disk; + + // Allocate a complete temporary screen where we'll draw the patch. + tmpscreen = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*tmpscreen), + PU_STATIC, NULL); + memset(tmpscreen, 0, SCREENWIDTH * SCREENHEIGHT * sizeof(*tmpscreen)); + V_UseBuffer(tmpscreen); + + // Buffer where we'll save the disk data. + + if (disk_data != NULL) + { + Z_Free(disk_data); + disk_data = NULL; + } + + disk_data = Z_Malloc(LOADING_DISK_W * LOADING_DISK_H * sizeof(*disk_data), + PU_STATIC, NULL); + + // Draw the patch and save the result to disk_data. + disk = W_CacheLumpName(disk_lump, PU_STATIC); + V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk); + CopyRegion(disk_data, LOADING_DISK_W, + tmpscreen + yoffs * SCREENWIDTH + xoffs, SCREENWIDTH, + LOADING_DISK_W, LOADING_DISK_H); + W_ReleaseLumpName(disk_lump); + + V_RestoreBuffer(); + Z_Free(tmpscreen); +} + +void V_EnableLoadingDisk(const char *lump_name, int xoffs, int yoffs) +{ + loading_disk_xoffs = xoffs; + loading_disk_yoffs = yoffs; + + if (saved_background != NULL) + { + Z_Free(saved_background); + saved_background = NULL; + } + + saved_background = Z_Malloc(LOADING_DISK_W * LOADING_DISK_H + * sizeof(*saved_background), + PU_STATIC, NULL); + SaveDiskData(lump_name, xoffs, yoffs); +} + +void V_BeginRead(size_t nbytes) +{ + recent_bytes_read += nbytes; +} + +static pixel_t *DiskRegionPointer(void) +{ + return I_VideoBuffer + + loading_disk_yoffs * SCREENWIDTH + + loading_disk_xoffs; +} + +void V_DrawDiskIcon(void) +{ + if (disk_data != NULL && recent_bytes_read > diskicon_threshold) + { + // Save the background behind the disk before we draw it. + CopyRegion(saved_background, LOADING_DISK_W, + DiskRegionPointer(), SCREENWIDTH, + LOADING_DISK_W, LOADING_DISK_H); + + // Write the disk to the screen buffer. + CopyRegion(DiskRegionPointer(), SCREENWIDTH, + disk_data, LOADING_DISK_W, + LOADING_DISK_W, LOADING_DISK_H); + disk_drawn = true; + } + + recent_bytes_read = 0; +} + +void V_RestoreDiskBackground(void) +{ + if (disk_drawn) + { + // Restore the background. + CopyRegion(DiskRegionPointer(), SCREENWIDTH, + saved_background, LOADING_DISK_W, + LOADING_DISK_W, LOADING_DISK_H); + + disk_drawn = false; + } +} + diff --git a/games/NXDoom/src/v_diskicon.h b/games/NXDoom/src/v_diskicon.h new file mode 100644 index 00000000000..0dee04d1989 --- /dev/null +++ b/games/NXDoom/src/v_diskicon.h @@ -0,0 +1,32 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Disk load indicator. +// + +#ifndef __V_DISKICON__ +#define __V_DISKICON__ + +// Dimensions of the flashing "loading" disk icon + +#define LOADING_DISK_W 16 +#define LOADING_DISK_H 16 + +extern void V_EnableLoadingDisk(const char *lump_name, int xoffs, int yoffs); +extern void V_BeginRead(size_t nbytes); +extern void V_DrawDiskIcon(void); +extern void V_RestoreDiskBackground(void); + +#endif diff --git a/games/NXDoom/src/v_patch.h b/games/NXDoom/src/v_patch.h new file mode 100644 index 00000000000..767f9e3a288 --- /dev/null +++ b/games/NXDoom/src/v_patch.h @@ -0,0 +1,50 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh/rendering module, shared data struct definitions. +// + + +#ifndef V_PATCH_H +#define V_PATCH_H + +// Patches. +// A patch holds one or more columns. +// Patches are used for sprites and all masked pictures, +// and we compose textures from the TEXTURE1/2 lists +// of patches. + +typedef PACKED_STRUCT ( +{ + short width; // bounding box size + short height; + short leftoffset; // pixels to the left of origin + short topoffset; // pixels below the origin + int columnofs[8]; // only [width] used + // the [0] is &columnofs[width] +}) patch_t; + +// posts are runs of non masked source pixels +typedef PACKED_STRUCT ( +{ + byte topdelta; // -1 is the last post in a column + byte length; // length data bytes follows +}) post_t; + +// column_t is a list of 0 or more post_t, (byte)-1 terminated +typedef post_t column_t; + +#endif + diff --git a/games/NXDoom/src/v_video.c b/games/NXDoom/src/v_video.c new file mode 100644 index 00000000000..c35f259f405 --- /dev/null +++ b/games/NXDoom/src/v_video.c @@ -0,0 +1,1023 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Gamma correction LUT stuff. +// Functions to draw patches (by post) directly to screen. +// Functions to blit a block to the screen. +// + +#include +#include +#include +#include + +#include "i_system.h" + +#include "doomtype.h" + +#include "deh_str.h" +#include "i_input.h" +#include "i_swap.h" +#include "i_video.h" +#include "m_bbox.h" +#include "m_misc.h" +#include "v_video.h" +#include "w_wad.h" +#include "z_zone.h" + +#include "config.h" +#ifdef HAVE_LIBPNG +#include +#endif + +// TODO: There are separate RANGECHECK defines for different games, but this +// is common code. Fix this. +#define RANGECHECK + +// Blending table used for fuzzpatch, etc. +// Only used in Heretic/Hexen + +byte *tinttable = NULL; + +// villsa [STRIFE] Blending table used for Strife +byte *xlatab = NULL; + +// The screen buffer that the v_video.c code draws to. + +static pixel_t *dest_screen = NULL; + +int dirtybox[4]; + +// haleyjd 08/28/10: clipping callback function for patches. +// This is needed for Chocolate Strife, which clips patches to the screen. +static vpatchclipfunc_t patchclip_callback = NULL; + +// +// V_MarkRect +// +void V_MarkRect(int x, int y, int width, int height) +{ + // If we are temporarily using an alternate screen, do not + // affect the update box. + + if (dest_screen == I_VideoBuffer) + { + M_AddToBox (dirtybox, x, y); + M_AddToBox (dirtybox, x + width-1, y + height-1); + } +} + + +// +// V_CopyRect +// +void V_CopyRect(int srcx, int srcy, pixel_t *source, + int width, int height, + int destx, int desty) +{ + pixel_t *src; + pixel_t *dest; + +#ifdef RANGECHECK + if (srcx < 0 + || srcx + width > SCREENWIDTH + || srcy < 0 + || srcy + height > SCREENHEIGHT + || destx < 0 + || destx + width > SCREENWIDTH + || desty < 0 + || desty + height > SCREENHEIGHT) + { + I_Error ("Bad V_CopyRect"); + } +#endif + + V_MarkRect(destx, desty, width, height); + + src = source + SCREENWIDTH * srcy + srcx; + dest = dest_screen + SCREENWIDTH * desty + destx; + + for ( ; height>0 ; height--) + { + memcpy(dest, src, width * sizeof(*dest)); + src += SCREENWIDTH; + dest += SCREENWIDTH; + } +} + +// +// V_SetPatchClipCallback +// +// haleyjd 08/28/10: Added for Strife support. +// By calling this function, you can setup runtime error checking for patch +// clipping. Strife never caused errors by drawing patches partway off-screen. +// Some versions of vanilla DOOM also behaved differently than the default +// implementation, so this could possibly be extended to those as well for +// accurate emulation. +// +void V_SetPatchClipCallback(vpatchclipfunc_t func) +{ + patchclip_callback = func; +} + +// +// V_DrawPatch +// Masks a column based masked pic to the screen. +// + +void V_DrawPatch(int x, int y, patch_t *patch) +{ + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + int w; + + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + // haleyjd 08/28/10: Strife needs silent error checking here. + if(patchclip_callback) + { + if(!patchclip_callback(patch, x, y)) + return; + } + +#ifdef RANGECHECK + if (x < 0 + || x + SHORT(patch->width) > SCREENWIDTH + || y < 0 + || y + SHORT(patch->height) > SCREENHEIGHT) + { + I_Error("Bad V_DrawPatch"); + } +#endif + + V_MarkRect(x, y, SHORT(patch->width), SHORT(patch->height)); + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + + w = SHORT(patch->width); + + for ( ; colcolumnofs[col])); + + // step through the posts in a column + while (column->topdelta != 0xff) + { + source = (byte *)column + 3; + dest = desttop + column->topdelta*SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = *source++; + dest += SCREENWIDTH; + } + column = (column_t *)((byte *)column + column->length + 4); + } + } +} + +// +// V_DrawPatchFlipped +// Masks a column based masked pic to the screen. +// Flips horizontally, e.g. to mirror face. +// + +void V_DrawPatchFlipped(int x, int y, patch_t *patch) +{ + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + int w; + + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + // haleyjd 08/28/10: Strife needs silent error checking here. + if(patchclip_callback) + { + if(!patchclip_callback(patch, x, y)) + return; + } + +#ifdef RANGECHECK + if (x < 0 + || x + SHORT(patch->width) > SCREENWIDTH + || y < 0 + || y + SHORT(patch->height) > SCREENHEIGHT) + { + I_Error("Bad V_DrawPatchFlipped"); + } +#endif + + V_MarkRect (x, y, SHORT(patch->width), SHORT(patch->height)); + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + + w = SHORT(patch->width); + + for ( ; colcolumnofs[w-1-col])); + + // step through the posts in a column + while (column->topdelta != 0xff ) + { + source = (byte *)column + 3; + dest = desttop + column->topdelta*SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = *source++; + dest += SCREENWIDTH; + } + column = (column_t *)((byte *)column + column->length + 4); + } + } +} + + + +// +// V_DrawPatchDirect +// Draws directly to the screen on the pc. +// + +void V_DrawPatchDirect(int x, int y, patch_t *patch) +{ + V_DrawPatch(x, y, patch); +} + +// +// V_DrawTLPatch +// +// Masks a column based translucent masked pic to the screen. +// + +void V_DrawTLPatch(int x, int y, patch_t * patch) +{ + int count, col; + column_t *column; + pixel_t *desttop, *dest; + byte *source; + int w; + + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + if (x < 0 + || x + SHORT(patch->width) > SCREENWIDTH + || y < 0 + || y + SHORT(patch->height) > SCREENHEIGHT) + { + I_Error("Bad V_DrawTLPatch"); + } + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++) + { + column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + + // step through the posts in a column + + while (column->topdelta != 0xff) + { + source = (byte *) column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = tinttable[*dest + ((*source++) << 8)]; + dest += SCREENWIDTH; + } + column = (column_t *) ((byte *) column + column->length + 4); + } + } +} + +// +// V_DrawXlaPatch +// +// villsa [STRIFE] Masks a column based translucent masked pic to the screen. +// + +void V_DrawXlaPatch(int x, int y, patch_t * patch) +{ + int count, col; + column_t *column; + pixel_t *desttop, *dest; + byte *source; + int w; + + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + if(patchclip_callback) + { + if(!patchclip_callback(patch, x, y)) + return; + } + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + + w = SHORT(patch->width); + for(; col < w; x++, col++, desttop++) + { + column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + + // step through the posts in a column + + while(column->topdelta != 0xff) + { + source = (byte *) column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; + + while(count--) + { + *dest = xlatab[*dest + ((*source) << 8)]; + source++; + dest += SCREENWIDTH; + } + column = (column_t *) ((byte *) column + column->length + 4); + } + } +} + +// +// V_DrawAltTLPatch +// +// Masks a column based translucent masked pic to the screen. +// + +void V_DrawAltTLPatch(int x, int y, patch_t * patch) +{ + int count, col; + column_t *column; + pixel_t *desttop, *dest; + byte *source; + int w; + + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + if (x < 0 + || x + SHORT(patch->width) > SCREENWIDTH + || y < 0 + || y + SHORT(patch->height) > SCREENHEIGHT) + { + I_Error("Bad V_DrawAltTLPatch"); + } + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++) + { + column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + + // step through the posts in a column + + while (column->topdelta != 0xff) + { + source = (byte *) column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = tinttable[((*dest) << 8) + *source++]; + dest += SCREENWIDTH; + } + column = (column_t *) ((byte *) column + column->length + 4); + } + } +} + +// +// V_DrawShadowedPatch +// +// Masks a column based masked pic to the screen. +// + +void V_DrawShadowedPatch(int x, int y, patch_t *patch) +{ + int count, col; + column_t *column; + pixel_t *desttop, *dest; + byte *source; + pixel_t *desttop2, *dest2; + int w; + + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + if (x < 0 + || x + SHORT(patch->width) > SCREENWIDTH + || y < 0 + || y + SHORT(patch->height) > SCREENHEIGHT) + { + I_Error("Bad V_DrawShadowedPatch"); + } + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + desttop2 = dest_screen + (y + 2) * SCREENWIDTH + x + 2; + + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++, desttop2++) + { + column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + + // step through the posts in a column + + while (column->topdelta != 0xff) + { + source = (byte *) column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + dest2 = desttop2 + column->topdelta * SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest2 = tinttable[((*dest2) << 8)]; + dest2 += SCREENWIDTH; + *dest = *source++; + dest += SCREENWIDTH; + + } + column = (column_t *) ((byte *) column + column->length + 4); + } + } +} + +// +// Load tint table from TINTTAB lump. +// + +void V_LoadTintTable(void) +{ + tinttable = W_CacheLumpName("TINTTAB", PU_STATIC); +} + +// +// V_LoadXlaTable +// +// villsa [STRIFE] Load xla table from XLATAB lump. +// + +void V_LoadXlaTable(void) +{ + xlatab = W_CacheLumpName("XLATAB", PU_STATIC); +} + +// +// V_DrawBlock +// Draw a linear block of pixels into the view buffer. +// + +void V_DrawBlock(int x, int y, int width, int height, pixel_t *src) +{ + pixel_t *dest; + +#ifdef RANGECHECK + if (x < 0 + || x + width >SCREENWIDTH + || y < 0 + || y + height > SCREENHEIGHT) + { + I_Error ("Bad V_DrawBlock"); + } +#endif + + V_MarkRect (x, y, width, height); + + dest = dest_screen + y * SCREENWIDTH + x; + + while (height--) + { + memcpy (dest, src, width * sizeof(*dest)); + src += width; + dest += SCREENWIDTH; + } +} + +void V_DrawFilledBox(int x, int y, int w, int h, int c) +{ + pixel_t *buf, *buf1; + int x1, y1; + + buf = I_VideoBuffer + SCREENWIDTH * y + x; + + for (y1 = 0; y1 < h; ++y1) + { + buf1 = buf; + + for (x1 = 0; x1 < w; ++x1) + { + *buf1++ = c; + } + + buf += SCREENWIDTH; + } +} + +void V_DrawHorizLine(int x, int y, int w, int c) +{ + pixel_t *buf; + int x1; + + buf = I_VideoBuffer + SCREENWIDTH * y + x; + + for (x1 = 0; x1 < w; ++x1) + { + *buf++ = c; + } +} + +void V_DrawVertLine(int x, int y, int h, int c) +{ + pixel_t *buf; + int y1; + + buf = I_VideoBuffer + SCREENWIDTH * y + x; + + for (y1 = 0; y1 < h; ++y1) + { + *buf = c; + buf += SCREENWIDTH; + } +} + +void V_DrawBox(int x, int y, int w, int h, int c) +{ + V_DrawHorizLine(x, y, w, c); + V_DrawHorizLine(x, y+h-1, w, c); + V_DrawVertLine(x, y, h, c); + V_DrawVertLine(x+w-1, y, h, c); +} + +// +// Draw a "raw" screen (lump containing raw data to blit directly +// to the screen) +// + +void V_DrawRawScreen(pixel_t *raw) +{ + memcpy(dest_screen, raw, SCREENWIDTH * SCREENHEIGHT * sizeof(*dest_screen)); +} + +// +// V_Init +// +void V_Init (void) +{ + // no-op! + // There used to be separate screens that could be drawn to; these are + // now handled in the upper layers. +} + +// Set the buffer that the code draws to. + +void V_UseBuffer(pixel_t *buffer) +{ + dest_screen = buffer; +} + +// Restore screen buffer to the i_video screen buffer. + +void V_RestoreBuffer(void) +{ + dest_screen = I_VideoBuffer; +} + +// +// SCREEN SHOTS +// + +typedef PACKED_STRUCT ( +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + + unsigned short xmin; + unsigned short ymin; + unsigned short xmax; + unsigned short ymax; + + unsigned short hres; + unsigned short vres; + + unsigned char palette[48]; + + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + + char filler[58]; + unsigned char data; // unbounded +}) pcx_t; + + +// +// WritePCXfile +// + +void WritePCXfile(char *filename, pixel_t *data, + int width, int height, + byte *palette) +{ + int i; + int length; + pcx_t* pcx; + byte* pack; + + pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL); + + pcx->manufacturer = 0x0a; // PCX id + pcx->version = 5; // 256 color + pcx->encoding = 1; // uncompressed + pcx->bits_per_pixel = 8; // 256 color + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = SHORT(width-1); + pcx->ymax = SHORT(height-1); + pcx->hres = SHORT(1); + pcx->vres = SHORT(1); + memset (pcx->palette,0,sizeof(pcx->palette)); + pcx->reserved = 0; // PCX spec: reserved byte must be zero + pcx->color_planes = 1; // chunky image + pcx->bytes_per_line = SHORT(width); + pcx->palette_type = SHORT(2); // not a grey scale + memset (pcx->filler,0,sizeof(pcx->filler)); + + // pack the image + pack = &pcx->data; + + for (i=0 ; i= mouse_threshold) + { + // Undo acceleration and get back the original mouse speed + original_speed = speed - mouse_threshold; + original_speed = (int) (original_speed / mouse_acceleration); + original_speed += mouse_threshold; + + linelen = (original_speed * redline_x) / mouse_threshold; + } + else + { + linelen = (speed * redline_x) / mouse_threshold; + } + + // Horizontal "thermometer" + if (linelen > MOUSE_SPEED_BOX_WIDTH - 1) + { + linelen = MOUSE_SPEED_BOX_WIDTH - 1; + } + + if (linelen < redline_x) + { + V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + linelen, white); + } + else + { + V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + redline_x, white); + V_DrawHorizLine(MOUSE_SPEED_BOX_X + redline_x, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + linelen - redline_x, yellow); + } + + // Draw acceleration threshold line + V_DrawVertLine(MOUSE_SPEED_BOX_X + redline_x, MOUSE_SPEED_BOX_Y + 1, + MOUSE_SPEED_BOX_HEIGHT - 2, red); +} + +// Highest seen mouse turn speed. We scale the range of the thermometer +// according to this value, so that it never exceeds the range. Initially +// this is set to a 1:1 setting where 1 pixel = 1 unit of speed. +static int max_seen_speed = MOUSE_SPEED_BOX_WIDTH - 1; + +static void DrawNonAcceleratingBox(int speed) +{ + int white; + int linelen; + + white = I_GetPaletteIndex(0xff, 0xff, 0xff); + + if (speed > max_seen_speed) + { + max_seen_speed = speed; + } + + // Draw horizontal "thermometer": + linelen = speed * (MOUSE_SPEED_BOX_WIDTH - 1) / max_seen_speed; + + V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + linelen, white); +} + +void V_DrawMouseSpeedBox(int speed) +{ + int bgcolor, bordercolor, black; + + // If the mouse is turned off, don't draw the box at all. + if (!usemouse) + { + return; + } + + // Get palette indices for colors for widget. These depend on the + // palette of the game being played. + + bgcolor = I_GetPaletteIndex(0x77, 0x77, 0x77); + bordercolor = I_GetPaletteIndex(0x55, 0x55, 0x55); + black = I_GetPaletteIndex(0x00, 0x00, 0x00); + + // Calculate box position + + V_DrawFilledBox(MOUSE_SPEED_BOX_X, MOUSE_SPEED_BOX_Y, + MOUSE_SPEED_BOX_WIDTH, MOUSE_SPEED_BOX_HEIGHT, bgcolor); + V_DrawBox(MOUSE_SPEED_BOX_X, MOUSE_SPEED_BOX_Y, + MOUSE_SPEED_BOX_WIDTH, MOUSE_SPEED_BOX_HEIGHT, bordercolor); + V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, MOUSE_SPEED_BOX_Y + 4, + MOUSE_SPEED_BOX_WIDTH - 2, black); + + // If acceleration is used, draw a box that helps to calibrate the + // threshold point. + if (mouse_threshold > 0 && fabs(mouse_acceleration - 1) > 0.01) + { + DrawAcceleratingBox(speed); + } + else + { + DrawNonAcceleratingBox(speed); + } +} + diff --git a/games/NXDoom/src/v_video.h b/games/NXDoom/src/v_video.h new file mode 100644 index 00000000000..f9c18f9a74a --- /dev/null +++ b/games/NXDoom/src/v_video.h @@ -0,0 +1,108 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Gamma correction LUT. +// Functions to draw patches (by post) directly to screen. +// Functions to blit a block to the screen. +// + + +#ifndef __V_VIDEO__ +#define __V_VIDEO__ + +#include "doomtype.h" + +// Needed because we are refering to patches. +#include "v_patch.h" + +// +// VIDEO +// + +#define CENTERY (SCREENHEIGHT/2) + + +extern int dirtybox[4]; + +extern byte *tinttable; + +// haleyjd 08/28/10: implemented for Strife support +// haleyjd 08/28/10: Patch clipping callback, implemented to support Choco +// Strife. +typedef boolean (*vpatchclipfunc_t)(patch_t *, int, int); +void V_SetPatchClipCallback(vpatchclipfunc_t func); + + +// Allocates buffer screens, call before R_Init. +void V_Init (void); + +// Draw a block from the specified source screen to the screen. + +void V_CopyRect(int srcx, int srcy, pixel_t *source, + int width, int height, + int destx, int desty); + +void V_DrawPatch(int x, int y, patch_t *patch); +void V_DrawPatchFlipped(int x, int y, patch_t *patch); +void V_DrawTLPatch(int x, int y, patch_t *patch); +void V_DrawAltTLPatch(int x, int y, patch_t * patch); +void V_DrawShadowedPatch(int x, int y, patch_t *patch); +void V_DrawXlaPatch(int x, int y, patch_t * patch); // villsa [STRIFE] +void V_DrawPatchDirect(int x, int y, patch_t *patch); + +// Draw a linear block of pixels into the view buffer. + +void V_DrawBlock(int x, int y, int width, int height, pixel_t *src); + +void V_MarkRect(int x, int y, int width, int height); + +void V_DrawFilledBox(int x, int y, int w, int h, int c); +void V_DrawHorizLine(int x, int y, int w, int c); +void V_DrawVertLine(int x, int y, int h, int c); +void V_DrawBox(int x, int y, int w, int h, int c); + +// Draw a raw screen lump + +void V_DrawRawScreen(pixel_t *raw); + +// Temporarily switch to using a different buffer to draw graphics, etc. + +void V_UseBuffer(pixel_t *buffer); + +// Return to using the normal screen buffer to draw graphics. + +void V_RestoreBuffer(void); + +// Save a screenshot of the current screen to a file, named in the +// format described in the string passed to the function, eg. +// "DOOM%02i.pcx" + +void V_ScreenShot(const char *format); + +// Load the lookup table for translucency calculations from the TINTTAB +// lump. + +void V_LoadTintTable(void); + +// villsa [STRIFE] +// Load the lookup table for translucency calculations from the XLATAB +// lump. + +void V_LoadXlaTable(void); + +void V_DrawMouseSpeedBox(int speed); + +#endif + diff --git a/games/NXDoom/src/w_checksum.c b/games/NXDoom/src/w_checksum.c new file mode 100644 index 00000000000..09d8d2a6ce5 --- /dev/null +++ b/games/NXDoom/src/w_checksum.c @@ -0,0 +1,88 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Generate a checksum of the WAD directory. +// + +#include +#include +#include + +#include "i_system.h" +#include "m_misc.h" +#include "sha1.h" +#include "w_checksum.h" +#include "w_wad.h" + +static wad_file_t **open_wadfiles = NULL; +static int num_open_wadfiles = 0; + +static int GetFileNumber(wad_file_t *handle) +{ + int i; + int result; + + for (i = 0; i < num_open_wadfiles; ++i) + { + if (open_wadfiles[i] == handle) + { + return i; + } + } + + // Not found in list. This is a new file we haven't seen yet. + // Allocate another slot for this file. + + open_wadfiles = I_Realloc(open_wadfiles, + sizeof(wad_file_t *) * (num_open_wadfiles + 1)); + open_wadfiles[num_open_wadfiles] = handle; + + result = num_open_wadfiles; + ++num_open_wadfiles; + + return result; +} + +static void ChecksumAddLump(sha1_context_t *sha1_context, lumpinfo_t *lump) +{ + char buf[9]; + + M_StringCopy(buf, lump->name, sizeof(buf)); + SHA1_UpdateString(sha1_context, buf); + SHA1_UpdateInt32(sha1_context, GetFileNumber(lump->wad_file)); + SHA1_UpdateInt32(sha1_context, lump->position); + SHA1_UpdateInt32(sha1_context, lump->size); +} + +void W_Checksum(sha1_digest_t digest) +{ + sha1_context_t sha1_context; + unsigned int i; + + SHA1_Init(&sha1_context); + + num_open_wadfiles = 0; + + // Go through each entry in the WAD directory, adding information + // about each entry to the SHA1 hash. + + for (i = 0; i < numlumps; ++i) + { + ChecksumAddLump(&sha1_context, lumpinfo[i]); + } + + SHA1_Final(digest, &sha1_context); +} + diff --git a/games/NXDoom/src/w_checksum.h b/games/NXDoom/src/w_checksum.h new file mode 100644 index 00000000000..e1ce5b89e87 --- /dev/null +++ b/games/NXDoom/src/w_checksum.h @@ -0,0 +1,27 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Generate a checksum of the WAD directory. +// + +#ifndef W_CHECKSUM_H +#define W_CHECKSUM_H + +#include "doomtype.h" + +extern void W_Checksum(sha1_digest_t digest); + +#endif /* #ifndef W_CHECKSUM_H */ + diff --git a/games/NXDoom/src/w_file.c b/games/NXDoom/src/w_file.c new file mode 100644 index 00000000000..87fc2c95ade --- /dev/null +++ b/games/NXDoom/src/w_file.c @@ -0,0 +1,84 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// WAD I/O functions. +// + +#include + +#include "config.h" + +#include "doomtype.h" +#include "m_argv.h" + +#include "w_file.h" + + +static wad_file_class_t *wad_file_classes[] = +{ +#ifdef _WIN32 + &win32_wad_file, +#endif +#ifdef HAVE_MMAP + &posix_wad_file, +#endif + &stdc_wad_file, +}; + +wad_file_t *W_OpenFile(const char *path) +{ + wad_file_t *result; + int i; + + //! + // @category obscure + // + // Use the OS's virtual memory subsystem to map WAD files + // directly into memory. + // + + if (!M_CheckParm("-mmap")) + { + return stdc_wad_file.OpenFile(path); + } + + // Try all classes in order until we find one that works + + result = NULL; + + for (i=0; iOpenFile(path); + + if (result != NULL) + { + break; + } + } + + return result; +} + +void W_CloseFile(wad_file_t *wad) +{ + wad->file_class->CloseFile(wad); +} + +size_t W_Read(wad_file_t *wad, unsigned int offset, + void *buffer, size_t buffer_len) +{ + return wad->file_class->Read(wad, offset, buffer, buffer_len); +} + diff --git a/games/NXDoom/src/w_file.h b/games/NXDoom/src/w_file.h new file mode 100644 index 00000000000..be8065cc36e --- /dev/null +++ b/games/NXDoom/src/w_file.h @@ -0,0 +1,86 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// WAD I/O functions. +// + + +#ifndef __W_FILE__ +#define __W_FILE__ + +#include +#include "doomtype.h" + +typedef struct _wad_file_s wad_file_t; + +typedef struct +{ + // Open a file for reading. + wad_file_t *(*OpenFile)(const char *path); + + // Close the specified file. + void (*CloseFile)(wad_file_t *file); + + // Read data from the specified position in the file into the + // provided buffer. Returns the number of bytes read. + size_t (*Read)(wad_file_t *file, unsigned int offset, + void *buffer, size_t buffer_len); +} wad_file_class_t; + + +extern wad_file_class_t stdc_wad_file; + +#ifdef _WIN32 +extern wad_file_class_t win32_wad_file; +#endif + +#ifdef HAVE_MMAP +extern wad_file_class_t posix_wad_file; +#endif + + +struct _wad_file_s +{ + // Class of this file. + wad_file_class_t *file_class; + + // If this is NULL, the file cannot be mapped into memory. If this + // is non-NULL, it is a pointer to the mapped file. + byte *mapped; + + // Length of the file, in bytes. + unsigned int length; + + // File's location on disk. + const char *path; +}; + +// Open the specified file. Returns a pointer to a new wad_file_t +// handle for the WAD file, or NULL if it could not be opened. + +wad_file_t *W_OpenFile(const char *path); + +// Close the specified WAD file. + +void W_CloseFile(wad_file_t *wad); + +// Read data from the specified file into the provided buffer. The +// data is read from the specified offset from the start of the file. +// Returns the number of bytes read. + +size_t W_Read(wad_file_t *wad, unsigned int offset, + void *buffer, size_t buffer_len); + +#endif /* #ifndef __W_FILE__ */ diff --git a/games/NXDoom/src/w_file_posix.c b/games/NXDoom/src/w_file_posix.c new file mode 100644 index 00000000000..d4fdc22f9e3 --- /dev/null +++ b/games/NXDoom/src/w_file_posix.c @@ -0,0 +1,176 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// WAD I/O functions. +// + +#include "config.h" + +#ifdef HAVE_MMAP + +#include +#include +#include +#include +#include + +#include "m_misc.h" +#include "w_file.h" +#include "z_zone.h" + +typedef struct +{ + wad_file_t wad; + int handle; +} posix_wad_file_t; + + +static void MapFile(posix_wad_file_t *wad, const char *filename) +{ + void *result; + int protection; + int flags; + + // Mapped area can be read and written to. Ideally + // this should be read-only, as none of the Doom code should + // change the WAD files after being read. However, there may + // be code lurking in the source that does. + + protection = PROT_READ|PROT_WRITE; + + // Writes to the mapped area result in private changes that are + // *not* written to disk. + + flags = MAP_PRIVATE; + + result = mmap(NULL, wad->wad.length, + protection, flags, + wad->handle, 0); + + if (result == NULL || result == (void *)-1) + { + fprintf(stderr, "W_POSIX_OpenFile: Unable to mmap() %s - %s\n", + filename, strerror(errno)); + } + else + { + wad->wad.mapped = result; + } +} + +unsigned int GetFileLength(int handle) +{ + return lseek(handle, 0, SEEK_END); +} + +static wad_file_t *W_POSIX_OpenFile(const char *path) +{ + posix_wad_file_t *result; + int handle; + + handle = open(path, 0); + + if (handle < 0) + { + return NULL; + } + + // Create a new posix_wad_file_t to hold the file handle. + + result = Z_Malloc(sizeof(posix_wad_file_t), PU_STATIC, 0); + result->wad.file_class = &posix_wad_file; + result->wad.length = GetFileLength(handle); + result->wad.path = M_StringDuplicate(path); + result->wad.mapped = NULL; + result->handle = handle; + + // Try to map the file into memory with mmap: + + MapFile(result, path); + + return &result->wad; +} + +static void W_POSIX_CloseFile(wad_file_t *wad) +{ + posix_wad_file_t *posix_wad; + + posix_wad = (posix_wad_file_t *) wad; + + // If mapped, unmap it. + + // Close the file + + if (posix_wad->wad.mapped) + { + munmap(posix_wad->wad.mapped, posix_wad->wad.length); + } + close(posix_wad->handle); + Z_Free(posix_wad); +} + +// Read data from the specified position in the file into the +// provided buffer. Returns the number of bytes read. + +size_t W_POSIX_Read(wad_file_t *wad, unsigned int offset, + void *buffer, size_t buffer_len) +{ + posix_wad_file_t *posix_wad; + byte *byte_buffer; + size_t bytes_read; + int result; + + posix_wad = (posix_wad_file_t *) wad; + + // Jump to the specified position in the file. + + lseek(posix_wad->handle, offset, SEEK_SET); + + // Read into the buffer. + + bytes_read = 0; + byte_buffer = buffer; + + while (buffer_len > 0) { + result = read(posix_wad->handle, byte_buffer, buffer_len); + + if (result < 0) { + perror("W_POSIX_Read"); + break; + } else if (result == 0) { + break; + } + + // Successfully read some bytes + + byte_buffer += result; + buffer_len -= result; + bytes_read += result; + } + + return bytes_read; +} + + +wad_file_class_t posix_wad_file = +{ + W_POSIX_OpenFile, + W_POSIX_CloseFile, + W_POSIX_Read, +}; + + +#endif /* #ifdef HAVE_MMAP */ + diff --git a/games/NXDoom/src/w_file_stdc.c b/games/NXDoom/src/w_file_stdc.c new file mode 100644 index 00000000000..90846a4e156 --- /dev/null +++ b/games/NXDoom/src/w_file_stdc.c @@ -0,0 +1,96 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// WAD I/O functions. +// + +#include + +#include "m_misc.h" +#include "w_file.h" +#include "z_zone.h" + +typedef struct +{ + wad_file_t wad; + FILE *fstream; +} stdc_wad_file_t; + + +static wad_file_t *W_StdC_OpenFile(const char *path) +{ + stdc_wad_file_t *result; + FILE *fstream; + + fstream = M_fopen(path, "rb"); + + if (fstream == NULL) + { + return NULL; + } + + // Create a new stdc_wad_file_t to hold the file handle. + + result = Z_Malloc(sizeof(stdc_wad_file_t), PU_STATIC, 0); + result->wad.file_class = &stdc_wad_file; + result->wad.mapped = NULL; + result->wad.length = M_FileLength(fstream); + result->wad.path = M_StringDuplicate(path); + result->fstream = fstream; + + return &result->wad; +} + +static void W_StdC_CloseFile(wad_file_t *wad) +{ + stdc_wad_file_t *stdc_wad; + + stdc_wad = (stdc_wad_file_t *) wad; + + fclose(stdc_wad->fstream); + Z_Free(stdc_wad); +} + +// Read data from the specified position in the file into the +// provided buffer. Returns the number of bytes read. + +size_t W_StdC_Read(wad_file_t *wad, unsigned int offset, + void *buffer, size_t buffer_len) +{ + stdc_wad_file_t *stdc_wad; + size_t result; + + stdc_wad = (stdc_wad_file_t *) wad; + + // Jump to the specified position in the file. + + fseek(stdc_wad->fstream, offset, SEEK_SET); + + // Read into the buffer. + + result = fread(buffer, 1, buffer_len, stdc_wad->fstream); + + return result; +} + + +wad_file_class_t stdc_wad_file = +{ + W_StdC_OpenFile, + W_StdC_CloseFile, + W_StdC_Read, +}; + + diff --git a/games/NXDoom/src/w_file_win32.c b/games/NXDoom/src/w_file_win32.c new file mode 100644 index 00000000000..dba576be33b --- /dev/null +++ b/games/NXDoom/src/w_file_win32.c @@ -0,0 +1,204 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// WAD I/O functions. +// + +#include "config.h" + +#ifdef _WIN32 + +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include + +#include "i_system.h" +#include "m_misc.h" +#include "w_file.h" +#include "z_zone.h" + +// This constant doesn't exist in VC6: + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER 0xffffffff +#endif + +typedef struct +{ + wad_file_t wad; + HANDLE handle; + HANDLE handle_map; +} win32_wad_file_t; + + +static void MapFile(win32_wad_file_t *wad, const char *filename) +{ + wad->handle_map = CreateFileMapping(wad->handle, + NULL, + PAGE_WRITECOPY, + 0, + 0, + NULL); + + if (wad->handle_map == NULL) + { + fprintf(stderr, "W_Win32_OpenFile: Unable to CreateFileMapping() " + "for %s\n", filename); + return; + } + + wad->wad.mapped = MapViewOfFile(wad->handle_map, + FILE_MAP_COPY, + 0, 0, 0); + + if (wad->wad.mapped == NULL) + { + fprintf(stderr, "W_Win32_OpenFile: Unable to MapViewOfFile() for %s\n", + filename); + } +} + +unsigned int GetFileLength(HANDLE handle) +{ + DWORD result; + + result = SetFilePointer(handle, 0, NULL, FILE_END); + + if (result == INVALID_SET_FILE_POINTER) + { + I_Error("W_Win32_OpenFile: Failed to read file length"); + } + + return result; +} + +static wad_file_t *W_Win32_OpenFile(const char *path) +{ + win32_wad_file_t *result; + wchar_t *wpath = NULL; + HANDLE handle; + + // Open the file: + + wpath = M_ConvertUtf8ToWide(path); + + if (wpath == NULL) + { + return NULL; + } + + handle = CreateFileW(wpath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + free(wpath); + + if (handle == INVALID_HANDLE_VALUE) + { + return NULL; + } + + // Create a new win32_wad_file_t to hold the file handle. + + result = Z_Malloc(sizeof(win32_wad_file_t), PU_STATIC, 0); + result->wad.file_class = &win32_wad_file; + result->wad.length = GetFileLength(handle); + result->wad.path = M_StringDuplicate(path); + result->handle = handle; + + // Try to map the file into memory with mmap: + + MapFile(result, path); + + return &result->wad; +} + +static void W_Win32_CloseFile(wad_file_t *wad) +{ + win32_wad_file_t *win32_wad; + + win32_wad = (win32_wad_file_t *) wad; + + // If mapped, unmap it. + + if (win32_wad->wad.mapped != NULL) + { + UnmapViewOfFile(win32_wad->wad.mapped); + } + + if (win32_wad->handle_map != NULL) + { + CloseHandle(win32_wad->handle_map); + } + + // Close the file + + if (win32_wad->handle != NULL) + { + CloseHandle(win32_wad->handle); + } + + Z_Free(win32_wad); +} + +// Read data from the specified position in the file into the +// provided buffer. Returns the number of bytes read. + +size_t W_Win32_Read(wad_file_t *wad, unsigned int offset, + void *buffer, size_t buffer_len) +{ + win32_wad_file_t *win32_wad; + DWORD bytes_read; + DWORD result; + + win32_wad = (win32_wad_file_t *) wad; + + // Jump to the specified position in the file. + + result = SetFilePointer(win32_wad->handle, offset, NULL, FILE_BEGIN); + + if (result == INVALID_SET_FILE_POINTER) + { + I_Error("W_Win32_Read: Failed to set file pointer to %i", + offset); + } + + // Read into the buffer. + + if (!ReadFile(win32_wad->handle, buffer, buffer_len, &bytes_read, NULL)) + { + I_Error("W_Win32_Read: Error reading from file"); + } + + return bytes_read; +} + + +wad_file_class_t win32_wad_file = +{ + W_Win32_OpenFile, + W_Win32_CloseFile, + W_Win32_Read, +}; + + +#endif /* #ifdef _WIN32 */ + diff --git a/games/NXDoom/src/w_main.c b/games/NXDoom/src/w_main.c new file mode 100644 index 00000000000..3496fd1dd69 --- /dev/null +++ b/games/NXDoom/src/w_main.c @@ -0,0 +1,268 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Common code to parse command line, identifying WAD files to load. +// + +#include + +#include "config.h" +#include "d_iwad.h" +#include "i_glob.h" +#include "i_system.h" +#include "m_argv.h" +#include "w_main.h" +#include "w_merge.h" +#include "w_wad.h" +#include "z_zone.h" + +// Parse the command line, merging WAD files that are sppecified. +// Returns true if at least one file was added. +boolean W_ParseCommandLine(void) +{ + boolean modifiedgame = false; + int p; + + // Merged PWADs are loaded first, because they are supposed to be + // modified IWADs. + + //! + // @arg + // @category mod + // + // Simulates the behavior of deutex's -merge option, merging a PWAD + // into the main IWAD. Multiple files may be specified. + // + + p = M_CheckParmWithArgs("-merge", 1); + + if (p > 0) + { + for (p = p + 1; p + // @category mod + // + // Simulates the behavior of NWT's -merge option. Multiple files + // may be specified. + + p = M_CheckParmWithArgs("-nwtmerge", 1); + + if (p > 0) + { + for (p = p + 1; p + // @category mod + // + // Simulates the behavior of NWT's -af option, merging flats into + // the main IWAD directory. Multiple files may be specified. + // + + p = M_CheckParmWithArgs("-af", 1); + + if (p > 0) + { + for (p = p + 1; p + // @category mod + // + // Simulates the behavior of NWT's -as option, merging sprites + // into the main IWAD directory. Multiple files may be specified. + // + + p = M_CheckParmWithArgs("-as", 1); + + if (p > 0) + { + for (p = p + 1; p + // @category mod + // + // Equivalent to "-af -as ". + // + + p = M_CheckParmWithArgs("-aa", 1); + + if (p > 0) + { + for (p = p + 1; p + // @vanilla + // + // Load the specified PWAD files. Each succeeding argument is + // treated as a PWAD file name until one starts with a dash or the + // argument list is exhausted. + // + + p = M_CheckParmWithArgs ("-file", 1); + if (p) + { + // the parms after p are wadfile/lump names, + // until end of parms or another - preceded parm + modifiedgame = true; // homebrew levels + while (++p != myargc && myargv[p][0] != '-') + { + char *filename; + + filename = D_TryFindWADByName(myargv[p]); + + printf(" adding %s\n", filename); + W_AddFile(filename); + free(filename); + } + } + +// W_PrintDirectory(); + + return modifiedgame; +} + +// Load all WAD files from the given directory. +void W_AutoLoadWADs(const char *path) +{ + glob_t *glob; + const char *filename; + + glob = I_StartMultiGlob(path, GLOB_FLAG_NOCASE|GLOB_FLAG_SORTED, + "*.wad", "*.lmp", NULL); + for (;;) + { + filename = I_NextGlob(glob); + if (filename == NULL) + { + break; + } + printf(" [autoload] merging %s\n", filename); + W_MergeFile(filename); + } + + I_EndGlob(glob); +} + +// Lump names that are unique to particular game types. This lets us check +// the user is not trying to play with the wrong executable, eg. +// chocolate-doom -iwad hexen.wad. +static const struct +{ + GameMission_t mission; + const char *lumpname; +} unique_lumps[] = { + { doom, "POSSA1" }, + { heretic, "IMPXA1" }, + { hexen, "ETTNA1" }, + { strife, "AGRDA1" }, +}; + +void W_CheckCorrectIWAD(GameMission_t mission) +{ + int i; + lumpindex_t lumpnum; + + for (i = 0; i < arrlen(unique_lumps); ++i) + { + if (mission != unique_lumps[i].mission) + { + lumpnum = W_CheckNumForName(unique_lumps[i].lumpname); + + if (lumpnum >= 0) + { + I_Error("\nYou are trying to use a %s IWAD file with " + "the %s%s binary.\nThis isn't going to work.\n" + "You probably want to use the %s%s binary.", + D_SuggestGameName(unique_lumps[i].mission, + indetermined), + PROGRAM_PREFIX, + D_GameMissionString(mission), + PROGRAM_PREFIX, + D_GameMissionString(unique_lumps[i].mission)); + } + } + } +} + diff --git a/games/NXDoom/src/w_main.h b/games/NXDoom/src/w_main.h new file mode 100644 index 00000000000..4565c657fc2 --- /dev/null +++ b/games/NXDoom/src/w_main.h @@ -0,0 +1,30 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Common code to parse command line, identifying WAD files to load. +// + +#ifndef W_MAIN_H +#define W_MAIN_H + +#include "d_mode.h" + +boolean W_ParseCommandLine(void); +void W_CheckCorrectIWAD(GameMission_t mission); + +// Autoload all .wad files from the given directory: +void W_AutoLoadWADs(const char *path); + +#endif /* #ifndef W_MAIN_H */ + diff --git a/games/NXDoom/src/w_merge.c b/games/NXDoom/src/w_merge.c new file mode 100644 index 00000000000..3d71a9aee96 --- /dev/null +++ b/games/NXDoom/src/w_merge.c @@ -0,0 +1,722 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handles merging of PWADs, similar to deutex's -merge option +// +// Ideally this should work exactly the same as in deutex, but trying to +// read the deutex source code made my brain hurt. +// + +#include +#include +#include +#include + +#include "doomtype.h" +#include "i_system.h" +#include "m_misc.h" +#include "w_merge.h" +#include "w_wad.h" +#include "z_zone.h" + +typedef enum +{ + SECTION_NORMAL, + SECTION_FLATS, + SECTION_SPRITES, +} section_t; + +typedef struct +{ + lumpinfo_t **lumps; + int numlumps; +} searchlist_t; + +typedef struct +{ + char sprname[4]; + char frame; + lumpinfo_t *angle_lumps[8]; +} sprite_frame_t; + +static searchlist_t iwad; +static searchlist_t iwad_sprites; +static searchlist_t pwad; + +static searchlist_t iwad_flats; +static searchlist_t pwad_sprites; +static searchlist_t pwad_flats; + +// lumps with these sprites must be replaced in the IWAD +static sprite_frame_t *sprite_frames; +static int num_sprite_frames; +static int sprite_frames_alloced; + +// Search in a list to find a lump with a particular name +// Linear search (slow!) +// +// Returns -1 if not found + +static int FindInList(searchlist_t *list, const char *name) +{ + int i; + + for (i=0; inumlumps; ++i) + { + if (!strncasecmp(list->lumps[i]->name, name, 8)) + return i; + } + + return -1; +} + +static boolean SetupList(searchlist_t *list, searchlist_t *src_list, + const char *startname, const char *endname, + const char *startname2, const char *endname2) +{ + int startlump, endlump; + + list->numlumps = 0; + startlump = FindInList(src_list, startname); + + if (startname2 != NULL && startlump < 0) + { + startlump = FindInList(src_list, startname2); + } + + if (startlump >= 0) + { + endlump = FindInList(src_list, endname); + + if (endname2 != NULL && endlump < 0) + { + endlump = FindInList(src_list, endname2); + } + + if (endlump > startlump) + { + list->lumps = src_list->lumps + startlump + 1; + list->numlumps = endlump - startlump - 1; + return true; + } + } + + return false; +} + +// Sets up the sprite/flat search lists + +static void SetupLists(void) +{ + // IWAD + + if (!SetupList(&iwad_flats, &iwad, "F_START", "F_END", NULL, NULL)) + { + I_Error("Flats section not found in IWAD"); + } + + if (!SetupList(&iwad_sprites, &iwad, "S_START", "S_END", NULL, NULL)) + + { + I_Error("Sprites section not found in IWAD"); + } + + // PWAD + + SetupList(&pwad_flats, &pwad, "F_START", "F_END", "FF_START", "FF_END"); + SetupList(&pwad_sprites, &pwad, "S_START", "S_END", "SS_START", "SS_END"); +} + +// Initialize the replace list + +static void InitSpriteList(void) +{ + if (sprite_frames == NULL) + { + sprite_frames_alloced = 128; + sprite_frames = Z_Malloc(sizeof(*sprite_frames) * sprite_frames_alloced, + PU_STATIC, NULL); + } + + num_sprite_frames = 0; +} + +static boolean ValidSpriteLumpName(char *name) +{ + if (name[0] == '\0' || name[1] == '\0' + || name[2] == '\0' || name[3] == '\0') + { + return false; + } + + // First frame: + + if (name[4] == '\0' || !isdigit(name[5])) + { + return false; + } + + // Second frame (optional): + + if (name[6] != '\0' && !isdigit(name[7])) + { + return false; + } + + return true; +} + +// Find a sprite frame + +static sprite_frame_t *FindSpriteFrame(char *name, int frame) +{ + sprite_frame_t *result; + int i; + + // Search the list and try to find the frame + + for (i=0; isprname, name, 4) && cur->frame == frame) + { + return cur; + } + } + + // Not found in list; Need to add to the list + + // Grow list? + + if (num_sprite_frames >= sprite_frames_alloced) + { + sprite_frame_t *newframes; + + newframes = Z_Malloc(sprite_frames_alloced * 2 * sizeof(*sprite_frames), + PU_STATIC, NULL); + memcpy(newframes, sprite_frames, + sprite_frames_alloced * sizeof(*sprite_frames)); + Z_Free(sprite_frames); + sprite_frames_alloced *= 2; + sprite_frames = newframes; + } + + // Add to end of list + + result = &sprite_frames[num_sprite_frames]; + memcpy(result->sprname, name, 4); + result->frame = frame; + + for (i=0; i<8; ++i) + result->angle_lumps[i] = NULL; + + ++num_sprite_frames; + + return result; +} + +// Check if sprite lump is needed in the new wad + +static boolean SpriteLumpNeeded(lumpinfo_t *lump) +{ + sprite_frame_t *sprite; + int angle_num; + int i; + + if (!ValidSpriteLumpName(lump->name)) + { + return true; + } + + // check the first frame + + sprite = FindSpriteFrame(lump->name, lump->name[4]); + angle_num = lump->name[5] - '0'; + + if (angle_num == 0) + { + // must check all frames + + for (i=0; i<8; ++i) + { + if (sprite->angle_lumps[i] == lump) + return true; + } + } + else + { + // check if this lump is being used for this frame + + if (sprite->angle_lumps[angle_num - 1] == lump) + return true; + } + + // second frame if any + + // no second frame? + if (lump->name[6] == '\0') + return false; + + sprite = FindSpriteFrame(lump->name, lump->name[6]); + angle_num = lump->name[7] - '0'; + + if (angle_num == 0) + { + // must check all frames + + for (i=0; i<8; ++i) + { + if (sprite->angle_lumps[i] == lump) + return true; + } + } + else + { + // check if this lump is being used for this frame + + if (sprite->angle_lumps[angle_num - 1] == lump) + return true; + } + + return false; +} + +static void AddSpriteLump(lumpinfo_t *lump) +{ + sprite_frame_t *sprite; + int angle_num; + int i; + + if (!ValidSpriteLumpName(lump->name)) + { + return; + } + + // first angle + + sprite = FindSpriteFrame(lump->name, lump->name[4]); + angle_num = lump->name[5] - '0'; + + if (angle_num == 0) + { + for (i=0; i<8; ++i) + sprite->angle_lumps[i] = lump; + } + else + { + sprite->angle_lumps[angle_num - 1] = lump; + } + + // second angle + + // no second angle? + + if (lump->name[6] == '\0') + return; + + sprite = FindSpriteFrame(lump->name, lump->name[6]); + angle_num = lump->name[7] - '0'; + + if (angle_num == 0) + { + for (i=0; i<8; ++i) + sprite->angle_lumps[i] = lump; + } + else + { + sprite->angle_lumps[angle_num - 1] = lump; + } +} + +// Generate the list. Run at the start, before merging + +static void GenerateSpriteList(void) +{ + int i; + + InitSpriteList(); + + // Add all sprites from the IWAD + + for (i=0; iname, "F_START", 8)) + { + current_section = SECTION_FLATS; + } + else if (!strncasecmp(lump->name, "S_START", 8)) + { + current_section = SECTION_SPRITES; + } + + newlumps[num_newlumps++] = lump; + + break; + + case SECTION_FLATS: + + // Have we reached the end of the section? + + if (!strncasecmp(lump->name, "F_END", 8)) + { + // Add all new flats from the PWAD to the end + // of the section + + for (n=0; nname); + + if (lumpindex < 0) + { + newlumps[num_newlumps++] = lump; + } + } + + break; + + case SECTION_SPRITES: + + // Have we reached the end of the section? + + if (!strncasecmp(lump->name, "S_END", 8)) + { + // add all the PWAD sprites + + for (n=0; nname, "F_START", 8) + || !strncasecmp(lump->name, "FF_START", 8)) + { + current_section = SECTION_FLATS; + } + else if (!strncasecmp(lump->name, "S_START", 8) + || !strncasecmp(lump->name, "SS_START", 8)) + { + current_section = SECTION_SPRITES; + } + else + { + // Don't include the headers of sections + + newlumps[num_newlumps++] = lump; + } + break; + + case SECTION_FLATS: + + // PWAD flats are ignored (already merged) + + if (!strncasecmp(lump->name, "FF_END", 8) + || !strncasecmp(lump->name, "F_END", 8)) + { + // end of section + current_section = SECTION_NORMAL; + } + break; + + case SECTION_SPRITES: + + // PWAD sprites are ignored (already merged) + + if (!strncasecmp(lump->name, "SS_END", 8) + || !strncasecmp(lump->name, "S_END", 8)) + { + // end of section + current_section = SECTION_NORMAL; + } + break; + } + } + + // Switch to the new lumpinfo, and free the old one + + free(lumpinfo); + lumpinfo = newlumps; + numlumps = num_newlumps; +} + +void W_PrintDirectory(void) +{ + unsigned int i, n; + + // debug + for (i=0; iname[n] != '\0'; ++n) + putchar(lumpinfo[i]->name[n]); + putchar('\n'); + } +} + +// Merge in a file by name + +void W_MergeFile(const char *filename) +{ + int old_numlumps; + + old_numlumps = numlumps; + + // Load PWAD + + if (W_AddFile(filename) == NULL) + return; + + // IWAD is at the start, PWAD was appended to the end + + iwad.lumps = lumpinfo; + iwad.numlumps = old_numlumps; + + pwad.lumps = lumpinfo + old_numlumps; + pwad.numlumps = numlumps - old_numlumps; + + // Setup sprite/flat lists + + SetupLists(); + + // Generate list of sprites to be replaced by the PWAD + + GenerateSpriteList(); + + // Perform the merge + + DoMerge(); +} + +// Replace lumps in the given list with lumps from the PWAD + +static void W_NWTAddLumps(searchlist_t *list) +{ + int i; + + // Go through the IWAD list given, replacing lumps with lumps of + // the same name from the PWAD + for (i=0; inumlumps; ++i) + { + int index; + + index = FindInList(&pwad, list->lumps[i]->name); + + if (index > 0) + { + memcpy(list->lumps[i], pwad.lumps[index], + sizeof(lumpinfo_t)); + } + } +} + +// Merge sprites and flats in the way NWT does with its -af and -as +// command-line options. + +void W_NWTMergeFile(const char *filename, int flags) +{ + int old_numlumps; + + old_numlumps = numlumps; + + // Load PWAD + + if (W_AddFile(filename) == NULL) + return; + + // IWAD is at the start, PWAD was appended to the end + + iwad.lumps = lumpinfo; + iwad.numlumps = old_numlumps; + + pwad.lumps = lumpinfo + old_numlumps; + pwad.numlumps = numlumps - old_numlumps; + + // Setup sprite/flat lists + + SetupLists(); + + // Merge in flats? + + if (flags & W_NWT_MERGE_FLATS) + { + W_NWTAddLumps(&iwad_flats); + } + + // Sprites? + + if (flags & W_NWT_MERGE_SPRITES) + { + W_NWTAddLumps(&iwad_sprites); + } + + // Discard the PWAD + + numlumps = old_numlumps; +} + +// Simulates the NWT -merge command line parameter. What this does is load +// a PWAD, then search the IWAD sprites, removing any sprite lumps that also +// exist in the PWAD. + +void W_NWTDashMerge(const char *filename) +{ + wad_file_t *wad_file; + int old_numlumps; + int i; + + old_numlumps = numlumps; + + // Load PWAD + + wad_file = W_AddFile(filename); + + if (wad_file == NULL) + { + return; + } + + // IWAD is at the start, PWAD was appended to the end + + iwad.lumps = lumpinfo; + iwad.numlumps = old_numlumps; + + pwad.lumps = lumpinfo + old_numlumps; + pwad.numlumps = numlumps - old_numlumps; + + // Setup sprite/flat lists + + SetupLists(); + + // Search through the IWAD sprites list. + + for (i=0; iname) >= 0) + { + // Replace this entry with an empty string. This is what + // nwt -merge does. + + M_StringCopy(iwad_sprites.lumps[i]->name, "", 8); + } + } + + // Discard PWAD + // The PWAD must now be added in again with -file. + + numlumps = old_numlumps; + + W_CloseFile(wad_file); +} + diff --git a/games/NXDoom/src/w_merge.h b/games/NXDoom/src/w_merge.h new file mode 100644 index 00000000000..b88c9a3a1ef --- /dev/null +++ b/games/NXDoom/src/w_merge.h @@ -0,0 +1,44 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handles merging of PWADs, similar to deutex's -merge option +// +// Ideally this should work exactly the same as in deutex, but trying to +// read the deutex source code made my brain hurt. +// + +#ifndef W_MERGE_H +#define W_MERGE_H + +#define W_NWT_MERGE_SPRITES 0x1 +#define W_NWT_MERGE_FLATS 0x2 + +// Add a new WAD and merge it into the main directory + +void W_MergeFile(const char *filename); + +// NWT-style merging + +void W_NWTMergeFile(const char *filename, int flags); + +// Acts the same as NWT's "-merge" option. + +void W_NWTDashMerge(const char *filename); + +// Debug function that prints the WAD directory. + +void W_PrintDirectory(void); + +#endif /* #ifndef W_MERGE_H */ + diff --git a/games/NXDoom/src/w_wad.c b/games/NXDoom/src/w_wad.c new file mode 100644 index 00000000000..1b091834f79 --- /dev/null +++ b/games/NXDoom/src/w_wad.c @@ -0,0 +1,629 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Handles WAD file header, directory, lump I/O. +// + + + + +#include +#include +#include +#include + +#include "doomtype.h" + +#include "i_swap.h" +#include "i_system.h" +#include "i_video.h" +#include "m_misc.h" +#include "v_diskicon.h" +#include "z_zone.h" + +#include "w_wad.h" + +typedef PACKED_STRUCT ( +{ + // Should be "IWAD" or "PWAD". + char identification[4]; + int numlumps; + int infotableofs; +}) wadinfo_t; + + +typedef PACKED_STRUCT ( +{ + int filepos; + int size; + char name[8]; +}) filelump_t; + +// +// GLOBALS +// + +// Location of each lump on disk. +lumpinfo_t **lumpinfo; +unsigned int numlumps = 0; + +// Hash table for fast lookups +static lumpindex_t *lumphash; + +// Variables for the reload hack: filename of the PWAD to reload, and the +// lumps from WADs before the reload file, so we can resent numlumps and +// load the file again. +static wad_file_t *reloadhandle = NULL; +static lumpinfo_t *reloadlumps = NULL; +static char *reloadname = NULL; +static int reloadlump = -1; + +// Hash function used for lump names. +unsigned int W_LumpNameHash(const char *s) +{ + // This is the djb2 string hash function, modded to work on strings + // that have a maximum length of 8. + + unsigned int result = 5381; + unsigned int i; + + for (i=0; i < 8 && s[i] != '\0'; ++i) + { + result = ((result << 5) ^ result ) ^ toupper(s[i]); + } + + return result; +} + +// +// LUMP BASED ROUTINES. +// + +// +// W_AddFile +// All files are optional, but at least one file must be +// found (PWAD, if all required lumps are present). +// Files with a .wad extension are wadlink files +// with multiple lumps. +// Other files are single lumps with the base filename +// for the lump name. + +wad_file_t *W_AddFile (const char *filename) +{ + wadinfo_t header; + lumpindex_t i; + wad_file_t *wad_file; + int length; + int startlump; + filelump_t *fileinfo; + filelump_t *filerover; + lumpinfo_t *filelumps; + int numfilelumps; + + // If the filename begins with a ~, it indicates that we should use the + // reload hack. + if (filename[0] == '~') + { + if (reloadname != NULL) + { + I_Error("Prefixing a WAD filename with '~' indicates that the " + "WAD should be reloaded\n" + "on each level restart, for use by level authors for " + "rapid development. You\n" + "can only reload one WAD file, and it must be the last " + "file in the -file list."); + } + + reloadname = strdup(filename); + reloadlump = numlumps; + ++filename; + } + + // Open the file and add to directory + wad_file = W_OpenFile(filename); + + if (wad_file == NULL) + { + printf (" couldn't open %s\n", filename); + return NULL; + } + + if (strcasecmp(filename+strlen(filename)-3 , "wad" ) ) + { + // single lump file + + // fraggle: Swap the filepos and size here. The WAD directory + // parsing code expects a little-endian directory, so will swap + // them back. Effectively we're constructing a "fake WAD directory" + // here, as it would appear on disk. + + fileinfo = Z_Malloc(sizeof(filelump_t), PU_STATIC, 0); + fileinfo->filepos = LONG(0); + fileinfo->size = LONG(wad_file->length); + + // Name the lump after the base of the filename (without the + // extension). + + M_ExtractFileBase (filename, fileinfo->name); + numfilelumps = 1; + } + else + { + // WAD file + W_Read(wad_file, 0, &header, sizeof(header)); + + if (strncmp(header.identification,"IWAD",4)) + { + // Homebrew levels? + if (strncmp(header.identification,"PWAD",4)) + { + W_CloseFile(wad_file); + I_Error ("Wad file %s doesn't have IWAD " + "or PWAD id\n", filename); + } + + // ???modifiedgame = true; + } + + header.numlumps = LONG(header.numlumps); + + // Vanilla Doom doesn't like WADs with more than 4046 lumps + // https://www.doomworld.com/vb/post/1010985 + if (!strncmp(header.identification,"PWAD",4) && header.numlumps > 4046) + { + W_CloseFile(wad_file); + I_Error ("Error: Vanilla limit for lumps in a WAD is 4046, " + "PWAD %s has %d", filename, header.numlumps); + } + + header.infotableofs = LONG(header.infotableofs); + length = header.numlumps*sizeof(filelump_t); + fileinfo = Z_Malloc(length, PU_STATIC, 0); + + W_Read(wad_file, header.infotableofs, fileinfo, length); + numfilelumps = header.numlumps; + } + + // Increase size of numlumps array to accomodate the new file. + filelumps = calloc(numfilelumps, sizeof(lumpinfo_t)); + if (filelumps == NULL) + { + W_CloseFile(wad_file); + I_Error("Failed to allocate array for lumps from new file."); + } + + startlump = numlumps; + numlumps += numfilelumps; + lumpinfo = I_Realloc(lumpinfo, numlumps * sizeof(lumpinfo_t *)); + filerover = fileinfo; + + for (i = startlump; i < numlumps; ++i) + { + lumpinfo_t *lump_p = &filelumps[i - startlump]; + lump_p->wad_file = wad_file; + lump_p->position = LONG(filerover->filepos); + lump_p->size = LONG(filerover->size); + lump_p->cache = NULL; + strncpy(lump_p->name, filerover->name, 8); + lumpinfo[i] = lump_p; + + ++filerover; + } + + Z_Free(fileinfo); + + if (lumphash != NULL) + { + Z_Free(lumphash); + lumphash = NULL; + } + + // If this is the reload file, we need to save some details about the + // file so that we can close it later on when we do a reload. + if (reloadname) + { + reloadhandle = wad_file; + reloadlumps = filelumps; + } + + return wad_file; +} + + + +// +// W_NumLumps +// +int W_NumLumps (void) +{ + return numlumps; +} + + + +// +// W_CheckNumForName +// Returns -1 if name not found. +// + +lumpindex_t W_CheckNumForName(const char *name) +{ + lumpindex_t i; + + // Do we have a hash table yet? + + if (lumphash != NULL) + { + int hash; + + // We do! Excellent. + + hash = W_LumpNameHash(name) % numlumps; + + for (i = lumphash[hash]; i != -1; i = lumpinfo[i]->next) + { + if (!strncasecmp(lumpinfo[i]->name, name, 8)) + { + return i; + } + } + } + else + { + // We don't have a hash table generate yet. Linear search :-( + // + // scan backwards so patch lump files take precedence + + for (i = numlumps - 1; i >= 0; --i) + { + if (!strncasecmp(lumpinfo[i]->name, name, 8)) + { + return i; + } + } + } + + // TFB. Not found. + + return -1; +} + + + + +// +// W_GetNumForName +// Calls W_CheckNumForName, but bombs out if not found. +// +lumpindex_t W_GetNumForName(const char *name) +{ + lumpindex_t i; + + i = W_CheckNumForName (name); + + if (i < 0) + { + I_Error ("W_GetNumForName: %s not found!", name); + } + + return i; +} + + +// +// W_LumpLength +// Returns the buffer size needed to load the given lump. +// +int W_LumpLength(lumpindex_t lump) +{ + if (lump >= numlumps) + { + I_Error ("W_LumpLength: %i >= numlumps", lump); + } + + return lumpinfo[lump]->size; +} + + + +// +// W_ReadLump +// Loads the lump into the given buffer, +// which must be >= W_LumpLength(). +// +void W_ReadLump(lumpindex_t lump, void *dest) +{ + int c; + lumpinfo_t *l; + + if (lump >= numlumps) + { + I_Error ("W_ReadLump: %i >= numlumps", lump); + } + + l = lumpinfo[lump]; + + V_BeginRead(l->size); + + c = W_Read(l->wad_file, l->position, dest, l->size); + + if (c < l->size) + { + I_Error("W_ReadLump: only read %i of %i on lump %i", + c, l->size, lump); + } +} + + + + +// +// W_CacheLumpNum +// +// Load a lump into memory and return a pointer to a buffer containing +// the lump data. +// +// 'tag' is the type of zone memory buffer to allocate for the lump +// (usually PU_STATIC or PU_CACHE). If the lump is loaded as +// PU_STATIC, it should be released back using W_ReleaseLumpNum +// when no longer needed (do not use Z_ChangeTag). +// + +void *W_CacheLumpNum(lumpindex_t lumpnum, int tag) +{ + byte *result; + lumpinfo_t *lump; + + if ((unsigned)lumpnum >= numlumps) + { + I_Error ("W_CacheLumpNum: %i >= numlumps", lumpnum); + } + + lump = lumpinfo[lumpnum]; + + // Get the pointer to return. If the lump is in a memory-mapped + // file, we can just return a pointer to within the memory-mapped + // region. If the lump is in an ordinary file, we may already + // have it cached; otherwise, load it into memory. + + if (lump->wad_file->mapped != NULL) + { + // Memory mapped file, return from the mmapped region. + + result = lump->wad_file->mapped + lump->position; + } + else if (lump->cache != NULL) + { + // Already cached, so just switch the zone tag. + + result = lump->cache; + Z_ChangeTag(lump->cache, tag); + } + else + { + // Not yet loaded, so load it now + + lump->cache = Z_Malloc(W_LumpLength(lumpnum), tag, &lump->cache); + W_ReadLump (lumpnum, lump->cache); + result = lump->cache; + } + + return result; +} + + + +// +// W_CacheLumpName +// +void *W_CacheLumpName(const char *name, int tag) +{ + return W_CacheLumpNum(W_GetNumForName(name), tag); +} + +// +// Release a lump back to the cache, so that it can be reused later +// without having to read from disk again, or alternatively, discarded +// if we run out of memory. +// +// Back in Vanilla Doom, this was just done using Z_ChangeTag +// directly, but now that we have WAD mmap, things are a bit more +// complicated ... +// + +void W_ReleaseLumpNum(lumpindex_t lumpnum) +{ + lumpinfo_t *lump; + + if ((unsigned)lumpnum >= numlumps) + { + I_Error ("W_ReleaseLumpNum: %i >= numlumps", lumpnum); + } + + lump = lumpinfo[lumpnum]; + + if (lump->wad_file->mapped != NULL) + { + // Memory-mapped file, so nothing needs to be done here. + } + else + { + Z_ChangeTag(lump->cache, PU_CACHE); + } +} + +void W_ReleaseLumpName(const char *name) +{ + W_ReleaseLumpNum(W_GetNumForName(name)); +} + +#if 0 + +// +// W_Profile +// +int info[2500][10]; +int profilecount; + +void W_Profile (void) +{ + int i; + memblock_t* block; + void* ptr; + char ch; + FILE* f; + int j; + char name[9]; + + + for (i=0 ; itag < PU_PURGELEVEL) + ch = 'S'; + else + ch = 'P'; + } + info[i][profilecount] = ch; + } + profilecount++; + + f = M_fopen ("waddump.txt","w"); + name[8] = 0; + + for (i=0 ; i 0) + { + lumphash = Z_Malloc(sizeof(lumpindex_t) * numlumps, PU_STATIC, NULL); + + for (i = 0; i < numlumps; ++i) + { + lumphash[i] = -1; + } + + for (i = 0; i < numlumps; ++i) + { + unsigned int hash; + + hash = W_LumpNameHash(lumpinfo[i]->name) % numlumps; + + // Hook into the hash table + + lumpinfo[i]->next = lumphash[hash]; + lumphash[hash] = i; + } + } + + // All done! +} + +// The Doom reload hack. The idea here is that if you give a WAD file to -file +// prefixed with the ~ hack, that WAD file will be reloaded each time a new +// level is loaded. This lets you use a level editor in parallel and make +// incremental changes to the level you're working on without having to restart +// the game after every change. +// But: the reload feature is a fragile hack... +void W_Reload(void) +{ + char *filename; + lumpindex_t i; + + if (reloadname == NULL) + { + return; + } + + // We must free any lumps being cached from the PWAD we're about to reload: + for (i = reloadlump; i < numlumps; ++i) + { + if (lumpinfo[i]->cache != NULL) + { + Z_Free(lumpinfo[i]->cache); + } + } + + // Reset numlumps to remove the reload WAD file: + numlumps = reloadlump; + + // Now reload the WAD file. + filename = reloadname; + + W_CloseFile(reloadhandle); + free(reloadlumps); + + reloadname = NULL; + reloadlump = -1; + reloadhandle = NULL; + W_AddFile(filename); + free(filename); + + // The WAD directory has changed, so we have to regenerate the + // fast lookup hashtable: + W_GenerateHashTable(); +} + +const char *W_WadNameForLump(const lumpinfo_t *lump) +{ + return M_BaseName(lump->wad_file->path); +} + +boolean W_IsIWADLump(const lumpinfo_t *lump) +{ + return lump->wad_file == lumpinfo[0]->wad_file; +} diff --git a/games/NXDoom/src/w_wad.h b/games/NXDoom/src/w_wad.h new file mode 100644 index 00000000000..ae5977a27bb --- /dev/null +++ b/games/NXDoom/src/w_wad.h @@ -0,0 +1,78 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// WAD I/O functions. +// + + +#ifndef __W_WAD__ +#define __W_WAD__ + +#include + +#include "doomtype.h" +#include "w_file.h" + + +// +// TYPES +// + +// +// WADFILE I/O related stuff. +// + +typedef struct lumpinfo_s lumpinfo_t; +typedef int lumpindex_t; + +struct lumpinfo_s +{ + char name[8]; + wad_file_t *wad_file; + int position; + int size; + void *cache; + + // Used for hash table lookups + lumpindex_t next; +}; + + +extern lumpinfo_t **lumpinfo; +extern unsigned int numlumps; + +wad_file_t *W_AddFile(const char *filename); +void W_Reload(void); + +lumpindex_t W_CheckNumForName(const char *name); +lumpindex_t W_GetNumForName(const char *name); + +int W_LumpLength(lumpindex_t lump); +void W_ReadLump(lumpindex_t lump, void *dest); + +void *W_CacheLumpNum(lumpindex_t lump, int tag); +void *W_CacheLumpName(const char *name, int tag); + +void W_GenerateHashTable(void); + +extern unsigned int W_LumpNameHash(const char *s); + +void W_ReleaseLumpNum(lumpindex_t lump); +void W_ReleaseLumpName(const char *name); + +const char *W_WadNameForLump(const lumpinfo_t *lump); +boolean W_IsIWADLump(const lumpinfo_t *lump); + +#endif diff --git a/games/NXDoom/src/z_native.c b/games/NXDoom/src/z_native.c new file mode 100644 index 00000000000..c7f8f3cd55e --- /dev/null +++ b/games/NXDoom/src/z_native.c @@ -0,0 +1,506 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Zone Memory Allocation. Neat. +// +// This is an implementation of the zone memory API which +// uses native calls to malloc() and free(). +// + + +#include +#include + +#include "z_zone.h" +#include "i_system.h" +#include "doomtype.h" + +#define ZONEID 0x1d4a11 + +typedef struct memblock_s memblock_t; + +struct memblock_s +{ + int id; // = ZONEID + int tag; + int size; + void **user; + memblock_t *prev; + memblock_t *next; +}; + +// Linked list of allocated blocks for each tag type + +static memblock_t *allocated_blocks[PU_NUM_TAGS]; + +#ifdef TESTING + +static int test_malloced = 0; + +void *test_malloc(size_t size) +{ + int *result; + + if (test_malloced + size > 2 * 1024 * 1024) + { + return NULL; + } + + test_malloced += size; + + result = malloc(size + sizeof(int)); + + *result = size; + + return result + 1; +} + +void test_free(void *data) +{ + int *i; + + i = ((int *) data) - 1; + + test_malloced -= *i; + + free(i); +} + +#define malloc test_malloc +#define free test_free + +#endif /* #ifdef TESTING */ + + +// Add a block into the linked list for its type. + +static void Z_InsertBlock(memblock_t *block) +{ + block->prev = NULL; + block->next = allocated_blocks[block->tag]; + allocated_blocks[block->tag] = block; + + if (block->next != NULL) + { + block->next->prev = block; + } +} + +// Remove a block from its linked list. + +static void Z_RemoveBlock(memblock_t *block) +{ + // Unlink from list + + if (block->prev == NULL) + { + // Start of list + + allocated_blocks[block->tag] = block->next; + } + else + { + if (block->prev->next != block) + { + I_Error("Z_RemoveBlock: Doubly-linked list corrupted!"); + } + block->prev->next = block->next; + } + + if (block->next != NULL) + { + if (block->next->prev != block) + { + I_Error("Z_RemoveBlock: Doubly-linked list corrupted!"); + } + block->next->prev = block->prev; + } +} + +// +// Z_Init +// +void Z_Init (void) +{ + memset(allocated_blocks, 0, sizeof(allocated_blocks)); + printf("zone memory: Using native C allocator.\n"); +} + + +// +// Z_Free +// +void Z_Free (void* ptr) +{ + memblock_t* block; + + block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + + if (block->id != ZONEID) + { + I_Error ("Z_Free: freed a pointer without ZONEID"); + } + + if (block->tag != PU_FREE && block->user != NULL) + { + // clear the user's mark + + *block->user = NULL; + } + + Z_RemoveBlock(block); + + // Free back to system + + free(block); +} + +// Empty data from the cache list to allocate enough data of the size +// required. +// +// Returns true if any blocks were freed. + +static boolean ClearCache(int size) +{ + memblock_t *block; + memblock_t *next_block; + int remaining; + + block = allocated_blocks[PU_CACHE]; + + if (block == NULL) + { + // Cache is already empty. + + return false; + } + + // Search to the end of the PU_CACHE list. The blocks at the end + // of the list are the ones that have been free for longer and + // are more likely to be unneeded now. + + while (block->next != NULL) + { + block = block->next; + } + + //printf("out of memory; cleaning out the cache: %i\n", test_malloced); + + // Search backwards through the list freeing blocks until we have + // freed the amount of memory required. + + remaining = size; + + while (remaining > 0) + { + if (block == NULL) + { + // No blocks left to free; we've done our best. + + break; + } + + next_block = block->prev; + + Z_RemoveBlock(block); + + remaining -= block->size; + + if (block->user) + { + *block->user = NULL; + } + + free(block); + + block = next_block; + } + + return true; +} + +// +// Z_Malloc +// You can pass a NULL user if the tag is < PU_PURGELEVEL. +// + +void *Z_Malloc(int size, int tag, void *user) +{ + memblock_t *newblock; + unsigned char *data; + void *result; + + if (tag < 0 || tag >= PU_NUM_TAGS || tag == PU_FREE) + { + I_Error("Z_Malloc: attempted to allocate a block with an invalid " + "tag: %i", tag); + } + + if (user == NULL && tag >= PU_PURGELEVEL) + { + I_Error ("Z_Malloc: an owner is required for purgable blocks"); + } + + // Malloc a block of the required size + + newblock = NULL; + + while (newblock == NULL) + { + newblock = (memblock_t *) malloc(sizeof(memblock_t) + size); + + if (newblock == NULL) + { + if (!ClearCache(sizeof(memblock_t) + size)) + { + I_Error("Z_Malloc: failed on allocation of %i bytes", size); + } + } + } + + newblock->tag = tag; + + // Hook into the linked list for this tag type + + newblock->id = ZONEID; + newblock->user = user; + newblock->size = size; + + Z_InsertBlock(newblock); + + data = (unsigned char *) newblock; + result = data + sizeof(memblock_t); + + if (user != NULL) + { + *newblock->user = result; + } + + return result; +} + + + +// +// Z_FreeTags +// + +void Z_FreeTags(int lowtag, int hightag) +{ + int i; + + for (i=lowtag; i<= hightag; ++i) + { + memblock_t *block; + memblock_t *next; + + // Free all in this chain + + for (block=allocated_blocks[i]; block != NULL; ) + { + next = block->next; + + // Free this block + + if (block->user != NULL) + { + *block->user = NULL; + } + + free(block); + + // Jump to the next in the chain + + block = next; + } + + // This chain is empty now + + allocated_blocks[i] = NULL; + } +} + + + +// +// Z_DumpHeap +// +void Z_DumpHeap(int lowtag, int hightag) +{ + // broken + +#if 0 + memblock_t* block; + + printf ("zone size: %i location: %p\n", + mainzone->size,mainzone); + + printf ("tag range: %i to %i\n", + lowtag, hightag); + + for (block = mainzone->blocklist.next ; ; block = block->next) + { + if (block->tag >= lowtag && block->tag <= hightag) + printf ("block:%p size:%7i user:%p tag:%3i\n", + block, block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + // all blocks have been hit + break; + } + + if ( (byte *)block + block->size != (byte *)block->next) + printf ("ERROR: block size does not touch the next block\n"); + + if ( block->next->prev != block) + printf ("ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + printf ("ERROR: two consecutive free blocks\n"); + } +#endif +} + + +// +// Z_FileDumpHeap +// +void Z_FileDumpHeap(FILE *f) +{ + // broken +#if 0 + memblock_t* block; + + fprintf (f,"zone size: %i location: %p\n",mainzone->size,mainzone); + + for (block = mainzone->blocklist.next ; ; block = block->next) + { + fprintf (f,"block:%p size:%7i user:%p tag:%3i\n", + block, block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + // all blocks have been hit + break; + } + + if ( (byte *)block + block->size != (byte *)block->next) + fprintf (f,"ERROR: block size does not touch the next block\n"); + + if ( block->next->prev != block) + fprintf (f,"ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + fprintf (f,"ERROR: two consecutive free blocks\n"); + } +#endif +} + + + +// +// Z_CheckHeap +// +void Z_CheckHeap (void) +{ + memblock_t *block; + memblock_t *prev; + int i; + + // Check all chains + + for (i=0; inext) + { + if (block->id != ZONEID) + { + I_Error("Z_CheckHeap: Block without a ZONEID!"); + } + + if (block->prev != prev) + { + I_Error("Z_CheckHeap: Doubly-linked list corrupted!"); + } + + prev = block; + } + } +} + + + + +// +// Z_ChangeTag +// + +void Z_ChangeTag2(void *ptr, int tag, const char *file, int line) +{ + memblock_t* block; + + block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + + if (block->id != ZONEID) + I_Error("%s:%i: Z_ChangeTag: block without a ZONEID!", + file, line); + + if (tag >= PU_PURGELEVEL && block->user == NULL) + I_Error("%s:%i: Z_ChangeTag: an owner is required " + "for purgable blocks", file, line); + + // Remove the block from its current list, and rehook it into + // its new list. + + Z_RemoveBlock(block); + block->tag = tag; + Z_InsertBlock(block); +} + +void Z_ChangeUser(void *ptr, void **user) +{ + memblock_t* block; + + block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + + if (block->id != ZONEID) + { + I_Error("Z_ChangeUser: Tried to change user for invalid block!"); + } + + block->user = user; + *user = ptr; +} + + +// +// Z_FreeMemory +// + +int Z_FreeMemory(void) +{ + // Limited by the system?? + + return -1; +} + +unsigned int Z_ZoneSize(void) +{ + return 0; +} + diff --git a/games/NXDoom/src/z_zone.c b/games/NXDoom/src/z_zone.c new file mode 100644 index 00000000000..c5c2dbf7c15 --- /dev/null +++ b/games/NXDoom/src/z_zone.c @@ -0,0 +1,552 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Zone Memory Allocation. Neat. +// + +#include + +#include "doomtype.h" +#include "i_system.h" +#include "m_argv.h" + +#include "z_zone.h" + + +// +// ZONE MEMORY ALLOCATION +// +// There is never any space between memblocks, +// and there will never be two contiguous free memblocks. +// The rover can be left pointing at a non-empty block. +// +// It is of no value to free a cachable block, +// because it will get overwritten automatically if needed. +// + +#define MEM_ALIGN sizeof(void *) +#define ZONEID 0x1d4a11 + +typedef struct memblock_s +{ + int size; // including the header and possibly tiny fragments + void** user; + int tag; // PU_FREE if this is free + int id; // should be ZONEID + struct memblock_s* next; + struct memblock_s* prev; +} memblock_t; + + +typedef struct +{ + // total bytes malloced, including header + int size; + + // start / end cap for linked list + memblock_t blocklist; + + memblock_t* rover; + +} memzone_t; + + + +static memzone_t *mainzone; +static boolean zero_on_free; +static boolean scan_on_free; + + +// +// Z_ClearZone +// +void Z_ClearZone (memzone_t* zone) +{ + memblock_t* block; + + // set the entire zone to one free block + zone->blocklist.next = + zone->blocklist.prev = + block = (memblock_t *)( (byte *)zone + sizeof(memzone_t) ); + + zone->blocklist.user = (void *)zone; + zone->blocklist.tag = PU_STATIC; + zone->rover = block; + + block->prev = block->next = &zone->blocklist; + + // a free block. + block->tag = PU_FREE; + + block->size = zone->size - sizeof(memzone_t); +} + + + +// +// Z_Init +// +void Z_Init (void) +{ + memblock_t* block; + int size; + + mainzone = (memzone_t *)I_ZoneBase (&size); + mainzone->size = size; + + // set the entire zone to one free block + mainzone->blocklist.next = + mainzone->blocklist.prev = + block = (memblock_t *)( (byte *)mainzone + sizeof(memzone_t) ); + + mainzone->blocklist.user = (void *)mainzone; + mainzone->blocklist.tag = PU_STATIC; + mainzone->rover = block; + + block->prev = block->next = &mainzone->blocklist; + + // free block + block->tag = PU_FREE; + + block->size = mainzone->size - sizeof(memzone_t); + + // [Deliberately undocumented] + // Zone memory debugging flag. If set, memory is zeroed after it is freed + // to deliberately break any code that attempts to use it after free. + // + zero_on_free = M_ParmExists("-zonezero"); + + // [Deliberately undocumented] + // Zone memory debugging flag. If set, each time memory is freed, the zone + // heap is scanned to look for remaining pointers to the freed block. + // + scan_on_free = M_ParmExists("-zonescan"); +} + +// Scan the zone heap for pointers within the specified range, and warn about +// any remaining pointers. +static void ScanForBlock(void *start, void *end) +{ + memblock_t *block; + void **mem; + int i, len, tag; + + block = mainzone->blocklist.next; + + while (block->next != &mainzone->blocklist) + { + tag = block->tag; + + if (tag == PU_STATIC || tag == PU_LEVEL || tag == PU_LEVSPEC) + { + // Scan for pointers on the assumption that pointers are aligned + // on word boundaries (word size depending on pointer size): + mem = (void **) ((byte *) block + sizeof(memblock_t)); + len = (block->size - sizeof(memblock_t)) / sizeof(void *); + + for (i = 0; i < len; ++i) + { + if (start <= mem[i] && mem[i] <= end) + { + fprintf(stderr, + "%p has dangling pointer into freed block " + "%p (%p -> %p)\n", + mem, start, &mem[i], mem[i]); + } + } + } + + block = block->next; + } +} + +// +// Z_Free +// +void Z_Free (void* ptr) +{ + memblock_t* block; + memblock_t* other; + + block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); + + if (block->id != ZONEID) + I_Error ("Z_Free: freed a pointer without ZONEID"); + + if (block->tag != PU_FREE && block->user != NULL) + { + // clear the user's mark + *block->user = 0; + } + + // mark as free + block->tag = PU_FREE; + block->user = NULL; + block->id = 0; + + // If the -zonezero flag is provided, we zero out the block on free + // to break code that depends on reading freed memory. + if (zero_on_free) + { + memset(ptr, 0, block->size - sizeof(memblock_t)); + } + if (scan_on_free) + { + ScanForBlock(ptr, + (byte *) ptr + block->size - sizeof(memblock_t)); + } + + other = block->prev; + + if (other->tag == PU_FREE) + { + // merge with previous free block + other->size += block->size; + other->next = block->next; + other->next->prev = other; + + if (block == mainzone->rover) + mainzone->rover = other; + + block = other; + } + + other = block->next; + if (other->tag == PU_FREE) + { + // merge the next free block onto the end + block->size += other->size; + block->next = other->next; + block->next->prev = block; + + if (other == mainzone->rover) + mainzone->rover = block; + } +} + + + +// +// Z_Malloc +// You can pass a NULL user if the tag is < PU_PURGELEVEL. +// +#define MINFRAGMENT 64 + + +void* +Z_Malloc +( int size, + int tag, + void* user ) +{ + int extra; + memblock_t* start; + memblock_t* rover; + memblock_t* newblock; + memblock_t* base; + void *result; + + size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); + + // scan through the block list, + // looking for the first free block + // of sufficient size, + // throwing out any purgable blocks along the way. + + // account for size of block header + size += sizeof(memblock_t); + + // if there is a free block behind the rover, + // back up over them + base = mainzone->rover; + + if (base->prev->tag == PU_FREE) + base = base->prev; + + rover = base; + start = base->prev; + + do + { + if (rover == start) + { + // scanned all the way around the list + I_Error ("Z_Malloc: failed on allocation of %i bytes", size); + } + + if (rover->tag != PU_FREE) + { + if (rover->tag < PU_PURGELEVEL) + { + // hit a block that can't be purged, + // so move base past it + base = rover = rover->next; + } + else + { + // free the rover block (adding the size to base) + + // the rover can be the base block + base = base->prev; + Z_Free ((byte *)rover+sizeof(memblock_t)); + base = base->next; + rover = base->next; + } + } + else + { + rover = rover->next; + } + + } while (base->tag != PU_FREE || base->size < size); + + + // found a block big enough + extra = base->size - size; + + if (extra > MINFRAGMENT) + { + // there will be a free fragment after the allocated block + newblock = (memblock_t *) ((byte *)base + size ); + newblock->size = extra; + + newblock->tag = PU_FREE; + newblock->user = NULL; + newblock->prev = base; + newblock->next = base->next; + newblock->next->prev = newblock; + + base->next = newblock; + base->size = size; + } + + if (user == NULL && tag >= PU_PURGELEVEL) + I_Error ("Z_Malloc: an owner is required for purgable blocks"); + + base->user = user; + base->tag = tag; + + result = (void *) ((byte *)base + sizeof(memblock_t)); + + if (base->user) + { + *base->user = result; + } + + // next allocation will start looking here + mainzone->rover = base->next; + + base->id = ZONEID; + + return result; +} + + + +// +// Z_FreeTags +// +void +Z_FreeTags +( int lowtag, + int hightag ) +{ + memblock_t* block; + memblock_t* next; + + for (block = mainzone->blocklist.next ; + block != &mainzone->blocklist ; + block = next) + { + // get link before freeing + next = block->next; + + // free block? + if (block->tag == PU_FREE) + continue; + + if (block->tag >= lowtag && block->tag <= hightag) + Z_Free ( (byte *)block+sizeof(memblock_t)); + } +} + + + +// +// Z_DumpHeap +// Note: TFileDumpHeap( stdout ) ? +// +void +Z_DumpHeap +( int lowtag, + int hightag ) +{ + memblock_t* block; + + printf ("zone size: %i location: %p\n", + mainzone->size,mainzone); + + printf ("tag range: %i to %i\n", + lowtag, hightag); + + for (block = mainzone->blocklist.next ; ; block = block->next) + { + if (block->tag >= lowtag && block->tag <= hightag) + printf ("block:%p size:%7i user:%p tag:%3i\n", + block, block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + // all blocks have been hit + break; + } + + if ( (byte *)block + block->size != (byte *)block->next) + printf ("ERROR: block size does not touch the next block\n"); + + if ( block->next->prev != block) + printf ("ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + printf ("ERROR: two consecutive free blocks\n"); + } +} + + +// +// Z_FileDumpHeap +// +void Z_FileDumpHeap (FILE* f) +{ + memblock_t* block; + + fprintf (f,"zone size: %i location: %p\n",mainzone->size,mainzone); + + for (block = mainzone->blocklist.next ; ; block = block->next) + { + fprintf (f,"block:%p size:%7i user:%p tag:%3i\n", + block, block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + // all blocks have been hit + break; + } + + if ( (byte *)block + block->size != (byte *)block->next) + fprintf (f,"ERROR: block size does not touch the next block\n"); + + if ( block->next->prev != block) + fprintf (f,"ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + fprintf (f,"ERROR: two consecutive free blocks\n"); + } +} + + + +// +// Z_CheckHeap +// +void Z_CheckHeap (void) +{ + memblock_t* block; + + for (block = mainzone->blocklist.next ; ; block = block->next) + { + if (block->next == &mainzone->blocklist) + { + // all blocks have been hit + break; + } + + if ( (byte *)block + block->size != (byte *)block->next) + I_Error ("Z_CheckHeap: block size does not touch the next block\n"); + + if ( block->next->prev != block) + I_Error ("Z_CheckHeap: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + I_Error ("Z_CheckHeap: two consecutive free blocks\n"); + } +} + + + + +// +// Z_ChangeTag +// +void Z_ChangeTag2(void *ptr, int tag, const char *file, int line) +{ + memblock_t* block; + + block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + + if (block->id != ZONEID) + I_Error("%s:%i: Z_ChangeTag: block without a ZONEID!", + file, line); + + if (tag >= PU_PURGELEVEL && block->user == NULL) + I_Error("%s:%i: Z_ChangeTag: an owner is required " + "for purgable blocks", file, line); + + block->tag = tag; +} + +void Z_ChangeUser(void *ptr, void **user) +{ + memblock_t* block; + + block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + + if (block->id != ZONEID) + { + I_Error("Z_ChangeUser: Tried to change user for invalid block!"); + } + + block->user = user; + *user = ptr; +} + + + +// +// Z_FreeMemory +// +int Z_FreeMemory (void) +{ + memblock_t* block; + int free; + + free = 0; + + for (block = mainzone->blocklist.next ; + block != &mainzone->blocklist; + block = block->next) + { + if (block->tag == PU_FREE || block->tag >= PU_PURGELEVEL) + free += block->size; + } + + return free; +} + +unsigned int Z_ZoneSize(void) +{ + return mainzone->size; +} + diff --git a/games/NXDoom/src/z_zone.h b/games/NXDoom/src/z_zone.h new file mode 100644 index 00000000000..22bd6264318 --- /dev/null +++ b/games/NXDoom/src/z_zone.h @@ -0,0 +1,73 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Zone Memory Allocation, perhaps NeXT ObjectiveC inspired. +// Remark: this was the only stuff that, according +// to John Carmack, might have been useful for +// Quake. +// + + + +#ifndef __Z_ZONE__ +#define __Z_ZONE__ + +#include + +// +// ZONE MEMORY +// PU - purge tags. + +enum +{ + PU_STATIC = 1, // static entire execution time + PU_SOUND, // static while playing + PU_MUSIC, // static while playing + PU_FREE, // a free block + PU_LEVEL, // static until level exited + PU_LEVSPEC, // a special thinker in a level + + // Tags >= PU_PURGELEVEL are purgable whenever needed. + + PU_PURGELEVEL, + PU_CACHE, + + // Total number of different tag types + + PU_NUM_TAGS +}; + + +void Z_Init (void); +void* Z_Malloc (int size, int tag, void *ptr); +void Z_Free (void *ptr); +void Z_FreeTags (int lowtag, int hightag); +void Z_DumpHeap (int lowtag, int hightag); +void Z_FileDumpHeap (FILE *f); +void Z_CheckHeap (void); +void Z_ChangeTag2 (void *ptr, int tag, const char *file, int line); +void Z_ChangeUser(void *ptr, void **user); +int Z_FreeMemory (void); +unsigned int Z_ZoneSize(void); + +// +// This is used to get the local FILE:LINE info from CPP +// prior to really call the function in question. +// +#define Z_ChangeTag(p,t) \ + Z_ChangeTag2((p), (t), __FILE__, __LINE__) + + +#endif diff --git a/games/NXDoom/textscreen/.gitignore b/games/NXDoom/textscreen/.gitignore new file mode 100644 index 00000000000..3be8ec0c79f --- /dev/null +++ b/games/NXDoom/textscreen/.gitignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +.deps +*.a +tags +TAGS diff --git a/games/NXDoom/textscreen/CMakeLists.txt b/games/NXDoom/textscreen/CMakeLists.txt new file mode 100644 index 00000000000..7e33826d6df --- /dev/null +++ b/games/NXDoom/textscreen/CMakeLists.txt @@ -0,0 +1,33 @@ +add_library(textscreen STATIC + textscreen.h + txt_conditional.c txt_conditional.h + txt_checkbox.c txt_checkbox.h + txt_desktop.c txt_desktop.h + txt_dropdown.c txt_dropdown.h + txt_fileselect.c txt_fileselect.h + txt_gui.c txt_gui.h + txt_inputbox.c txt_inputbox.h + txt_io.c txt_io.h + txt_main.h + txt_button.c txt_button.h + txt_label.c txt_label.h + txt_radiobutton.c txt_radiobutton.h + txt_scrollpane.c txt_scrollpane.h + txt_separator.c txt_separator.h + txt_spinctrl.c txt_spinctrl.h + txt_sdl.c txt_sdl.h + txt_strut.c txt_strut.h + txt_table.c txt_table.h + txt_utf8.c txt_utf8.h + txt_widget.c txt_widget.h + txt_window.c txt_window.h + txt_window_action.c txt_window_action.h) +target_include_directories(textscreen + INTERFACE "." + PRIVATE "../src/") +if (DEFINED EMSCRIPTEN) + set_target_properties(textscreen PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") + set_target_properties(textscreen PROPERTIES LINK_FLAGS "-s USE_SDL=2") +else() + target_link_libraries(textscreen m SDL2::SDL2) +endif() diff --git a/games/NXDoom/textscreen/Doxyfile b/games/NXDoom/textscreen/Doxyfile new file mode 100644 index 00000000000..84b607a04d5 --- /dev/null +++ b/games/NXDoom/textscreen/Doxyfile @@ -0,0 +1,2451 @@ +# Doxyfile 1.8.13 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "libtextscreen" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /I&x@ zw3sq#ARDr<#%BFqC+U-3gVO3o_d6CQiSky|vCstj&Gf)zjJ?r`J;VN{-Xg4A4`kSF z28l8GM9+%a+h1HPYKq1&<_~oiY@my88NM+#J`DqM2R)beaNXeNEdIgx`1jf5I!S`G zDy3Ve(Rn&|Bgjl7np2?OG5PCwxP30G^#U0tB>h4xK1EclupKH&^XmX=EU;aq3XYd` z@oTSfK!bPo>Z#53k_vRJam8~iUSUf%%>7uS;3zm_dfXrZrkTjVpsAvzbzSZo!8@|r zJB=*!!gavBS0|>6KdNU^yFJWgG(zxEJe-(QOHRH5%2&F&_bq3_q!7~=9!LfRqBLng z1>R%ua0R+B{2g=O;rBrlBVFe8v}n#ntVW121z=JVrV%PRK>8yz!ukH39Y)2H=uejp z=~*lHHB;^ou9dJMC0I8QOHVHF2E?ac`KoIKfIPkcY%K;`iy|dOepxw^gy^DA$$F*u zZ8CT?YS;{`OIbQ7<<{n^j(O|Lgo~@H5SsdX$82Sw8XZFhXW7uDUPOlQ*f6(rF?ap# zn8mSf{hM8(L>9^T^%Lt=LF`>_|4#W5T?)N%NjqLu$(R7qp}%J1qQ(fRCW{*}5KAR+ z=PVONrt8_!dH%kIA?)+iGZl=p?)9sF_;6xXXrz;q+pv=AJ=ywa%T3DgB z9VT-*mU7 zP!_GQB@;OKVhtq7fix~YjJb_j>J4)^?EnS^OtC;LLd43V6l$8Di?wv1EpT_uJTu;ykk_*P~^Ju z{}1p11%9vNTj) zektUEi{KS5tZuvlqRMHo-A{T$6u|7yOMG^Wx6S}^luQPijC z>wFe^6VO4d&rlD@T+TZN7_mmWX-7#!bK>tMpGUM8?Fg{z=z4UE+tKp!MXn-qq|nsK zp5+-PJU@xB!3ytx7ty;n!_tl8cUcZAz|dWLRlajaB6i3B=G1asTzQKECoctcycth z3*KiHB9*_qsfG`p0t(0fNB8%hBVywvdH;mfanIfe;0}zWuSTcwQbl$(UPo-fGHu+M zi5^ntnQ^~yBS*4zhR={BGdC8Of2`s;uPQoPCI~_(%RR!Y7x=`zfb~9KCLPbiycN!V z^S7M$74%)xC>dNTvJ&?DYD)jv1{Wko$( zQPDz~QjAQ_|2!jZxw*H?$M^n!|NouW>+qcCdCocS_xo(`^WGj5iVZa#h5Xo1VyJJj zDAXEwjlm4%eWs#No^mJ@KmSmE(@YeqMiGS)6C27Ohwm-ZMxj(yzvrbiNVUiYe;V_n4cR;PgGtG(vU z+n+l{zn9J|UqOmb=8-C&QL|NP$qa#;(gsO8I}Ye*beCPZdh%0goSk>LqiA>6%P%!d z^J|Xw+0NO{kH7RgtZAHP{rkTua*w+?KQE&Ud~MRSnVT|ugLSyGktXaX@2lL&W3o`i@JZBR-TC&^Gtu-T1tt zGV*S1oj&^u275uf)4rNFt?`7$*+u?hjTpbhQl`8G4|Nk3bowqoog#;oaO=m5Z`VrH zE7^Us6b#~tAKvzbeV(_1qR@bjeM!CE?%A|Fgb_zfl=r?tZ4b_mPNjEWPz8!L`{b!IV??iO$}r9kG3yJL0-GP)@a7xN*VGdar^^Blj*BZxo;x?)i2m@gdLS z;3op*XPVA?dk?rxDYUD&<*>;AWz4kF>uoM8BHE3%oRTh!?h@XraCGsj zR+o0EHV%zb%)qeF=NF0$qvA`izp%KoQC!yA{ncd+jTUA1t${0#*6P$NVLMCmqO*m0 zB7u@hTY2l!j*hJUdk?)geeTW6aGrfTrtgJ1F{`QD4?IhA{J7=t#!aj0K8hZA`J$`( zV$F_{j#n|e3RIL!uXFC}`rv)crCRUy)h{P!%HJ+j>HpS;zP9Vz#yn@H&sOnYbd_E7aMq?ry>M^XgZd zcg50kPe>c}d``&>S|~4~d)9}5ZwzI7O1cGJ+&ZN}pTf8tpQK{&;Ow~oa;r!$Pf5Ur z>-{Ch4oRXW6$z(`#O{Q4;2xK?2^W!D%~}{OaqqkY7;K!LH@Ysr@UW;x8&uhdJa5t- z%us2r;VP>85K!N9iMj7}_>q|SEMejHlZNw@UY?eqNDR!%U#!tR-|>ULfRUyVY%L>k z-r@etAPe+1EMKrv!Fw{f0D(dvlcZI^h} zVtu!?XHV-`*b;5+F=wH!(e+Btf{sS3@V0CXv#L#o8~YB%?5NrrQoDcus>}PAwB8b1 zu2|V$g^TNZ*0oP5zCXo&d)ya&VZEqi<{iw@qXcE6=`?1xYyF{KmfQU*G%uez;kUFJNcTHiyxJMuF5 zyp3_z%&oXK8&TuO=k;n2TrTg*?vnd5@3!*C>x)__yce+K=W3Xho`TE$q*-Ij~Yb7`-mkvYPD|(}>t@&yM;`i*S3Z6ds zx9yI!#AqshxUX=e>FbC2_3s*v?LT6n^3tud?)3-z*5|u4;7HAZ%Jxbg5k3Fru946A!q<*b%LeUof;(!|P6fR#oAt_W4=ggcHY{Tg*OQ`NDG7t9 zRcB<|x0XxR*J+i^DHtL)bsx4K6@yx4=mDzCV9r=bB;)~#V^m@BfAdx?(7ox)112!6hZ3azHo zt`{5kNm;6M#C!`r>-6f;iDg~X(jB%ZZXR8fh53k)KK5yC_JQ~XzESeu#1b8~j%eoM z#N}qGoeOub`Si4|bW4xHj*lOMjujMGrr*BvWARODy_kxa22qP+AZgSlSsI3i;xCN$#GcF%7{2GPn*)0&T%B`?ZSUaDMBTF8S& zhdlAhI%o%MgqQLLef_-lket7zm6cU-cy}w=kqbrb%ig=!L_WoKOI6kU%&e@^ydaKO zXEzZ^99>tRHw%=@NJ&`P*f_T72#ScTp_awQY9;7ypA-7djzB&P!R_sO@~|{&F5h5O zU44Du^Qkc;*}*yRG)~5z264<`l_bB(CxUn8SmfOXoII4?6`mb{>1^W z_3O7+Rka%UH5@N@Jxa^H;lQX6C{Mj0!ZiP;njp6&;=|?FjfE}E&HQ*g-tZLhi1%O# zO=n+Dj_2C7CkjHjzTqSbjU=51O0XKf<`Sw)XRB>78i&tyI2Z5(4irv*agFo^am?c*KR2 z6dj~*6iTHYC(3xx`mWWHR-8Y7-c2XL)OxS5TUA9~wSbAx<{2R&Avvj3pVh0AlQ_^} zRZ|biz2GorupPBsyQp)=wr#4~+KnHh=5odzT+;j?ET^%tveMM?op!ooSMIhTdef^} z`6*_}{r&w)uu*QjTvm;+F*)X;_n8LoE( zOmg+ODfi#Jk;`%?_g|zTZRv-ttEn3d6BHC&6%i5P8Yy>lMq>V9B~nOfdskQ2#ZLkx z`9MYkzdp^VkR|q=vfA{)RX-=Y|Y1K)4_uWl?q$98EF^&*gZXO7YaT5O+B# zj^rGGlBj&}z_tkvG$Emv^tKy9>Iv_+_Xarh#~gqq+df~v(q?I<8#id6p`jtP(0Ik)!^?T}HN4s>GueS1tii)b+uxHO6 zVZ*Pc9ALUvA={=IH8nMc8>v1@_%}qR`Q_!?mn%1^pBY^GY{eoo-S7{~UGaPO?|(I4 zCF=gM0F!gh4j)dCZv8Qt3@X`v2>ME9ekWree6&8t*h$El<8`c0Nu@_Fz2;I|Ks zS}|_koNBQ{B$OUt+jt#gX6EGVEdKT}M|a~cwS*HV0Ntw3w!+>t?QAgR~)0>t~=j!Bv&sw@qEpb z=%yUO+vm)eyB$xC99-KW@uL6n8s{3v%_R}BnJ1&GvQA!m+SyeKu<}{zMd(xR1s@-; za*-{$bc9boFNyvYR#@E#j>y^F1wC@USWE zalvDk5Z`yaF9&#v`^v>Tl=lZTJ964bN(&w`i6kT~nQ`*ds@*OzdI5O}PTr{SINEbY z^&)7nFjJSOl__dx%SzY0avN_67;7eO9I?S3bG2x>GhILu2hpFU@s} zwyK`kx^C8~`jVi5bCDNYGi%Fyn)yz+o>e;?>AEkj;H!W33Fcy_4 z!vW638@qPDucThO{eEZcbQ&$3UdqTl=em9eJVJ29DLts57ON<3Ky}VS2{U;H8|kih zC_}I5GyKloLzP#!i+0cgKDIbZb=X#2h) z;P!R;-~N^!S~L|uHRT;AGoifm+TO#n#it*5U}WP%QBF&uM7sK}j7(@Eq-14k4dBGh zgKljs>Sz<1gMLrzz66QzrZpSn^?R)_vrW@Iq-kMLcU{lwDqBVdiCIT?Cvk}`U$D2~ ziCNa|N`P|0Qq`}nYnF5E`^LSAYY?Y+mx|x*h6&96+xVAZr(y0`bq}+;~5w(1l zi}T+HWPQs$7rJ&DCFQf{QML^t?OR*n`(74CLhyqOmi=Rd{m zRhjuR(vzKMub~H_a>S9Ci7&A3 zPSOJc^=2Mr`&W>fd6?RQ38B+b&o@%vESef4V4M?BvsPp3JPD?)aFE%}3ip|meBQhn zdyWM#IP)02+`xoS_Lr0{s;vVGK+&p}Os0Izj;y2U_S_!@MoV9Z`yLU)z_c08lyW_b;U7C%U zJ)B0FHo9+1Hs)2wNF0&LCozR~2~9l`LVt~2FW%u|DK~{${#xOP%@ zlKm@;3uvXE)MO2w(_0GB6anc+hn!|RTIH`D5N3KDWZQ76-dIL2C%|jpltXeIwYHZ9 z!TiUqQ=e7@9LrkU_R2PU)#-34<~QG7ok}#PSp$2`S<|L~XnlrK7Y`ih4Ur72Zj#02 zX%`B#YS-?SuiEdd=qOo6>yNoxv#&ggE?F5ab-gt<_=K5!BhTPh?)CB11%6JOuYZ0A z7cj}rS^2Jqztxm~n|*vmqN#@^%_b`}H1Z;ENZ1Lxx|dwluNP%xmYdVSDhUH;fq7O_ ztraunr6FYOb=x$HM7I_TMn29o2@|ppdm`~9oRELWx-uX$Pl~4Rr7LWaZWeJ(v9_@< zB_Z23aY@IgUBalmK0{5B0PEdaZE-F)^3tcdaY?XQD`(D87qp#Wz!4|Jn4f@~&wl#W zmV+is){wTgad5e!8c2*fE4A*PBck+vTMg!#u#4$|VJDWmfvx0nq9J9zm+zOzvx!tr zLuRU{0k-Y4?M>e!LJr+VO#PJ?;ttcBdWom^sXcmVs=d$;I6|(R5d`FZ&nlSw3qOi_^DmO^uoY-uJYKzRz={-;X(0cz-ahGT_Lx zEoYlHgyt*H^Mi}^1|c$DI~%RLd~JtLrOJ#s9_sgNRkBXi##HomTIGM)TV7`rBef)g zJ9hAhFS}(^8`U!Ft2P(KSr#iNb8@}?K61X!n}<3jgE^9^muWH88Nh^a@QA^F6%GJjyqhiv;5_bcON+7A5FcdIDfesZa4ax zZ{)?^epiJSlAO$zL`p@HH?g{s&m@4RqZZA{mWAHFVu|2@-S}Q6s_QwL9dF$ONvLQ~gY> z*>@mpAl}{KWR)!^`6;e^A-?zw7wUQnHF@uc_?uq>W>&AEt55sro2|dm6!#z#Ro+r< ziHEBoejzq;i}8b}F&QWfj@vua^9(=toq^U=8bt=zx&(J-yC(ihV&S6#Pgi>Q*IIW< zt3w;dLutEo%|^IqU`)R7lMfrF#J@bX^NkegZh&>|ml>ziFMG;aup8J3;3NDl=LVH4 ziNxO)_01(4EwWlV3hmxUjN7Pe`n6XAkmcUf;|0;Pz?NjU(_-0L+`ardd{qXxeI3ZVP{mnu8hL_Ovfd-E@8@?+>)^Qfgl{9H_zTX z(9dz?NkC(FV>b1cd3;Gy{5QQG?>uu}ks6LWzO~V2Iu$#PaL`xp4_xQ0>vTDt;i2sR zigJDLh1s*P5%?`?OAVG??mQ8dzxBn_`E{YDnZY$}0VQSJklVt{eYZXNOm4rkC>h`D zBp&~GZ}{Pyd$%M4O+Cs^&z0cWc0`75a&HQEfQt0uw{^ALa_f&988!R9qXnG5qIK>J zSHqq)#&E4Z@@=Ddp1whb(Fa$KX9X7m51un1u0571SxX}Ky*3o79#Cp45YOv4kz{-| zF?UKrZwYGlQ%iadaIfPqShnr5@`G1c5gQtK>~>Lj%9(BW%*>Sh2c!tGyzLy1u1w(> zEG&1YT-Lt3a7y!LxTKsgEq9Z$Dr_`1ncD5JrB8mwk_EHSDz^+Y`7l%ZUK0d&grB)6 zf)At@p(%yu&T};suu;0ch616z`{g2p`8iLnRB_zWVpmnDFeRzGp;ATh7DKPDKjGSK zdG{~Eg`CtxXF(9jVpQo&1FIvy0Tz(4I=B`x5V86ls@=EBH z^_42+R}aT$NtMi7tJ+qIjpMqCdh31E{xz+j2U-1MzG8P>YG#(1oX|+{do5`??Z&qN9mp&l*Gn$MiXY@uK=$+0# z`1E2kWQRR=(sU|_Tt?wjXSx^*h98b#pKME zqe*c~Am2JmjA`rKe}843KD(f!kJ@`fX1;Fs+k_Nqr6U`PPp~|{GN4j~H1m?AU7CXS znfoD(EM9}c&#AN`l_=SY0MB{ldQ;*nQYgOcH`suV&q{W;h?4<_+xn8ds#D8FD0d4q zyvdL4jv<3-I*I%+rN4Sp{oUG+PmLLrx6;q>W=}{OfppLI^QcAv)GQ-rS-Famv_a9} zyo4uK(bK_0a%DHs;URH1k1BI*d@RD`bn!9V*R;NR=*@`Jp;Y_E8VWO~NO#T>%YZz4 zUJBKLtGI!6atNbeom=jv!T~vUzMUylBc_rjDv%yP7@RN7yzRyb`@SB&=b9+$VP|0E zBv?sJqc6%i9d@}(1Kw_#8Rw7t`8EIrET;UmB?%v{Xb@frU=BdEjl<_!`u4JP<3xK;B{kfI1 z!;`UvG@Z8r)}LaIYo^xIZn(EtUxnKjeAzvPPCOV`ix-)dl2#dKgAp$$t=z1iC^7Ut zCwzbVQ*OHJ8-!TRY`}dZ-EpNL78S7h`r?X!cR}7xFYXmLYf*rq zJ$z%0Qjbo1D?hrY;?sc((#0>4*|mrp!ePirGa@M4Tjj@w)9gR0if-$5xIHyYoypgW zf_=*o=S|c3y5Z8zg32nbnpk^-N{;I2kMuBAruG5A8Y15B&T=#AsHr0olKqyzH1A6dnIU3~e}B*|oc49~ zett&8dQP{x)1vg2rkTY>)0X7&@Gy%k4c4!C9Xa@g)_p6UY97%2ZJlaOY}>Pa&l809 z%xrZmGaw-%o8FHBd2Hn#73jd{+V#xq>w3K%k0&smc%%+gKGC{5MMvi4wbGb5E8IvV z=JSlu>BW26isJUz#KvaDmwaXFlgNh$5(Pe>y9J8P!tXKHlovTH-}hpd*uf+FsP6_gFOR%Ei{a(y6St8XJ2R-GN`%fg{-G1yB6bAJ5y3(5FwiCdQ{XEiN|C z7)3r;wb-a>ZQg6YqJ59oCs3Eai&njKXG+CUIF@2RepCT=W!_) zH$G0t+thc~!jvO!<7#(eeBli=eRbkN_ZP3Q+F_4DbviZ^Ocrlc}EWqAhEpl}Fd;*TZA?=H{V z@ik_(vbf{oYjYTJC0#v@m$aY8)jni~9jsMXJ(avMiNE=J?BJIV^nvB7)8txLXeGF8 zHCeL1Zwq&Slg&jQN(zxpv5S4(6mm$sFq%fOj*=?L&=5E?4WwA-^MoP>G5grIB#Oql^V7;3+jL6VDM8a>p2Xw<=_~!VqH<(|kGoXa zg_&z|HzxKNoXWhs!rfd>gxdQ$vNETlf;tB-v&DuCw$`i1BSS3%1P3=<5Ov`WuCw26 z!4cQ12OhRcQ2Y30aZ@Rg_V5LBW!_2syDxbKGgXk}5-6dU}>@zk!6=crP zTH;bp{SY~5ZWebunX1hDJf3QuL^UNApP5$tSc76oH(ODX99Q_d|NKg48VO1O$<<|i zDA$edn8C9A=4B2{E35(Usq)()fpLiJ5PjgZM*M6m*Lcwf-XFV#dM@cdvbt3%kbgw5 zCXkMnV17t5$@Doz&rxLyp0*=o4&(;nilHEn|H8#7l+6P5@|<&HTcKPKcp#E3UZza# zUbw_pKD*5XSbqrGkd-)J*TL47RSyW z5>vC|hBa)O1!fjKr~M!*_yA;|L1*dx3aZKzZ`5bLK~3Y8x)^q91zMj-7K&zr8tm>i zot_&Bn6C(s_jaXBZxCgqaVG3s#>(#uo!(%>co9T?X7Q zAP%Um2u7MI+MvkvR1)Rjrh7NKZ=u#T#Fq!G2{}+15b2}G@Eb6``pq?!YRUmu)af(H zQzB^zS$FSNxVL~O@2Mip-q2}~XX006)CIpuDmeEX_Dt9SiJ6lXI$d=WT`1+i$&2tX z{^Wi4)FGxKer^i&6+Ysa^b$)~r6x!a>NQA^xlog#Ap?b7#|x6;G$8-GZ90K`-kK(F zfE8wL;30G6mM@&bzk$(N#KVB}_~fLM7e;Tu%zgFpX9h)UpAUN;dRU!$t~`TPyKJ*r<@jIh6MliPtfOET(DJB+mU6*9ze4` zl;wPDvooe1iO_x!1?>c(dEt;zApD0yLBqo0DMN{sAN7YzCxFO1+dG?}usVkz@0mlC z_1G^U>z*Shvm!@OYDJE)`0{K%#nr@7#YVCO<@GyfiC6)&&;o$vp9gpehJYVu00gmm zfW)H>M7cD8u;hxJBLzlX5L5zpqs5m2Zqh=4AsPc5pAjI8szX@XWA~_HBUz$a$Znj3 z7cA=rc=${KhR^VaIt*EG2>wNRevRmD-%U~r0|H7R055(NU<7UgG^PjOATHcQBUT-JvYweE z1x8(n=qBwJ(~JfDirWA|_BJ5OuLcAeKY-?a2=NF5+=8ZnptyES{6+Lqc1!9c0};(b zKv*pf4C8{-ffdXKXmMMBSM(dRyxy{`eZJv^V1aWsSnit(7C3DKCN}ZFbV(GD(e?t` zCaZyhen`$Jut&0?sTWW7^z?uaA3lKh@85%m4tS1~fQW`a5K&nUM77pIS}cSA*8;565+I_V7&xlfNLElcaXr5_86b1u z&;R3C_mOu-3XHl?aXwC#UXTuibYp?U{5?QGD+Y+0?t*p20`Yk}VLl4*X~k|BRcs_{ z5>Lfg#M9OpZ)jer(eX^AR_5D=J*_q1+RinIk%_{T(1@lt$Bj;0si|u=Y#e0#paw5}X0=>*VXwt!o} z6s|LdL+i|6v>_z!{M+>tmDiW!rI!OVF&!ocxF#?9WgA4i@yI?QAo=_C^Q#7x6XaIH z^}Ye1vGo8$h=l8$`A=;S2=jm%`T!8Z!8r;0LqKx*Z^O^88eC4Cy$0|~Cjc~_4%?^& zyjTiA^DP}}gJ23|F-L(AuPbY9XZ44aOT}3IIr_eUT4=d|qA&Qljfdaca0DdGDL~*| z{!^dxOSo2!u4k;gfOGg8}gy>lhJEhyQyT;+*PEm387oiHB9|lkorqcj;FFF81i2P~7Yl{`;RUZ(0<6$k zh{q3Y2$%p~Igj7&Uy^o0xrBBC5YOc5>c>7u+Q5l!1sHKS4F0zoWBVU7n}n* z2abXryY_1_r>#j~_v6Yb!u_gSNId(9qDp z;tNilIt6lba{)AV17tE8By9)+L4M@6(e;d#7c+>@71Q!#@e2z2UO;M&KOm{N0%>gz zAg#9!@XOl+0eL$hrsV~Qa!UcPlnoG@6Pr6$eWULawW4!GP4}|+285>&G0pnhYoyHR zddA96cKx!8(u>tsTma%`djY>@I8bvv%eqGR7&X`8p=-$7sJa%ht_5}D0YNq7#8~i- zzHb)sFx1%pGE>*<+!P06;NN zqLY%4x)DB13?>tpM))uc3bhjQcS!nw;fGQ8x5Y{?e~FcHZpR@>(y1LU?%2*N?$AyU zvu`Je*me*_m$nl{U?MGP=NGnV7ZkQ`7ZO_BE-Yx(P7<_wDJZ+zX1us!Wmi5!<{5JS zM9#1n$TMOEAWuh}2lsblz{hJabOyu@@pVFIUDml)gjXu{$zkhAdL!9WtSrjECLyu2qB*&}|00R#C$EaW$b&*FavgOHHTxZ5Yp zUPHx5IQClSqnvWI?v!JP(J z-ZaR&TaF2X0%j9X#z6iCo}~~N1VopOyM2D;^;ABV%pn-^*l&kmz#oEgl;e;V9)E&C z8kYv!J^=U#Mt{r;v1PRJj(>iY04gGTL15sO34t)YX2F2Pp9KWWeK-$Rjldv++X-Z_ z$KiSJ=ebD~9e?`*szFo%ML(AOX9$L{Kj?tF0C+KvSacxb(&5?Q1cb-8X8Kl>2|KDhvZ6^67Hc<~bq$XRn}eK7io z4!q*aUW~@;ck?8TNUEqtBp8N)I6EHTC7%Ia321^ZbO~TZW8ix5VrX7qUc<2f<(#ZF z>JJ$36KG#VE1HV%_y`O_Dp7zSu@;_#s-P^g91tX(S@VK*o)AxkFnj_S^p7yWb&?;- zY$cs(zl-na_e8YFR0-{P);U91?I;jXDFXzBZ-7sBFFZ5-F&;+4faY@rJOXpUEVyrD zW!%QS{)lSFQ4#qi0)wzt2@uq%1463VKaGds_2EYtu)HUr3}p#x-^9wU7%8|JhT*>WaZLUS z2E5D)2*c36iSRI^`}KG8?m-2wvk%<{dvYs)e{>O87gY!nx19r9(=Pz>#*@HxZ5FU! zxgD$t+68<9w*h9w`8l3I44!d? z6rg-c$q7iPxd2fm2SAWs0{CT?0Esyfzb&5{-9Aw*lppqev znd|{LxIZI&I+BD9w*x5W9mykgjIQ^0^GI27^Fsh5h#G_e5xr0#tOI3>TET!{BM|VZ z1^`}V|1lF@5$b2;JOH11=+)8n{%(GLVw=9r#*WHG$uG+m#8FG;MLj=l7~FJ3*Y9DD z+Ny?K@=i6IG%NZW{<0?`$Dz%(MK zkV2vGTtf-o{_pqy7zOYOtBZL=tOt2WR)c8ag@YKFu)>yuSfK@jI6;d+oWT4+Jipl> zFLB-=AD`(UAFuHs)WHo35Mbgp8Wg}A4hrH728FQtgF+a+L1FZqK@wVbPz0?#D9SUG zND|IxCW|aQlJ;MRGrdOm39fav-}W(~=N#JJReIHxKQ#TkB`MEC~~J>*~F0A*N+J;t#7=AYsqj5QpX zEcnrqjsrYmOQHT_3>*Z^SoRZ$ermip2;(LXevFjUz>wVR7dSwjFc#`l5xp%ULmMv+ zLOA0|qd!*KWdI{#|6T6(0}fCIiiU8r&eu>5HW3^I@g|c8zs&LhMECR)4p1l04bR4i z?h*Z6uZ^7m4g$QB2R}~6Z2&nxjo<+FfWzndVfo`kaS-60J8AUC%efCA`ajkgkhBiU zDBxKb$^!nEI0z6-Ck=jH`BekF@Qi`rfDwQ?Uo@2UK)EZHHx=4W1w%R0A9CQ|=?8w? zJh(3m*?$c05Bz-dCJ}zm0Ynyn;D8lA$&wEtIA92|Fopah90Yl7fH5}($YaBXWV+w? zI3m$((%^@3{{cRE&mo<=@MV_$03v@L!XXCs!)CY!A+p!M?gxHor#FY^2GHO+3T=Gg zUd^(>8QP~O6MjAg?*YVygN1{vH{=^0{(wUpgx!xNv&8dm9TNvWK3ky9a|g<^PryBT z?w|H)zDcA%QE}}6BG>vEhX+64@Dla`v;a?SuOG$G^k@ z%L{F#zw1H9K4t%ovAl%RfUFsmTi+clki%NhIwuHLT)v!Nm zArAc`W9e^k5SmQ*BL;@_R)65YFSiQd#N(h%Vm`Frd<$&{s{oE<1@o(h_GuQsCc_Awm#CH!KK8w&@1 zOV$|zv8_hr8a$#)Ck=j4t=NGfz26WHqMF;F?E3@DW>ZkL4C(;m|8i{|;=O+!OBmiA z0F9jEzRNYZ#U~Md?YIHNMspYk5uE}kH@^pUhtRfljCJWx{L*kg2o(Y}p%Gw2*8g;# z=8>?QH2RC{#1Ba8ZDQG(4&yL9mVUJ^jmc}Ua2Ptr{dAs2Y?>tPCk=iHoumOoZ#t38H&O?!A5c7F1VPgIl+5 zfoIR2fyTy0)^%xVDL8lT96;=tj~_qI(gPqDAWZ{6=i?_72`~*K@M~=|`@#DvU zLZPti$A{rRdh{sE7GUq*y&yX~8|38VjKII%b0tWR2m#w-6DDo^D4B-QHB9}1y6Jl8 zBp(PY9b>@)hZt5ewAujg`vWzTbwJhF4;U>921Zsvz;Iz8&^1SF*P(7-a|P7nyMo!e z?m)$GB~a3L2MW5&fuOuC5Q0fU(GJLJucc4c_`%Kg`hZ9LN7Ocq=+TGu?TD_Qs2TOA z`-n{dzs`_P-SE4}e~h#X5Y$cn)B8vplLq7#3*=q^!^V z={`aO*=1M%bpJp2$L>9ZHviFo$R6h37(YZ+-yW@1SAl7G6Uz<+u^o|J0)3z1994BG z0`sFVdP_&1(h(Fv%OFF=_fgezEJn_eU_#7kc3~^ft zRGm-%d|w9oUP&$gGBGH}E^QH6L!Z596Of*t2&Cr41BtnDK-`!NL=9sBNk0Y%&xrwPLi{yP$ex3+DRt6J4B4q z!Y2mhf2IE~DS+@}(5(qI@}Gu6aUl8s{!b1aM$sFw(=vf69;OjHEqLPwj2?ib|9<~b z;D12@ezhQDqH>_~NK){3CjO8F;q}kS7v_i4S{Fe%B*FamM3VD%{$-Me_eaudXEAA* zH&HysTb||P_)lp7eceWE_@F=P|AGeNg@2;u z5ZU ztNus>G@%&Ab=n2jJj8Z*$bR_$f(8@CW4z^uZFYxgfZ@9hcz9sk1$+*R21u+iUi`lQ z$v6Ysc&bgq3Nd*?O z>VX7q`7dcOQ9Q<5o)zoj2O6OH-i_E)4buQagg%WtJ#g>$9@jXSjol39&Uy&#qEACU z+2ohJ@_6B&Xt^PKV;E!fI}LCm(Dnqzc^I}U`-29MPk`|j2)JX=E`Q!{j{_OpR$##0 z1T@h_&>no=knh$n&I=R8W4z`0XAj$4|44%izoY?{W%rBNn_mAd8c5={10C)bpo%#M zl3Ge5N;b#ODvV_t^)HIPJKhwCMb-Ta$pritP)-tvM<0YDJO4q(ML8G{BmkzcO|INYi4 zbD@ki7YNXXTb#QSh+@hhuWSbI4aIW(9U6=m{)v_og0V0WTfTA80LGr-W%&{G03x~> z#_;WiafvG7c>$gs{^5CHqIitAys&cch+XM;Xn=*WkcMd>z(a>)9>zo(2ahyf_$OM9 zq_Tk(TW8pB;csa`D*4mC@FNZQ(TJ~=^FOA+MDZAJd6H@vAgTTy4S40&Ksng0A^(R_ zJkpOe;DdAEk2BMdAHm<9oyQCRM9Yb&g|mDn{+V1 z_tV+=?`bemJjPpIR6P>fXa6+~pe_vHMNpNi~$F2qhz6fqUZqhC4zo80x*`nxE;%1cIeFX z`KL1zvL5^s8jKhIiIx-BB!BmL8BK!_7<&q` zmuiP&e<6&s!aoM27N@X#nG!AbRKV!avb+h|drbW9~;9kkqrF9q>26FBc8t z|6OLq|KpWsLK=L9^zi;mUio)vz}g>Se3xOp^F;9&Z+S`WBp{)a_$L~OXlw<7>Q?}t z$~Qnzf=Pi1{ija;7Oy-O4e+>ga7`SNsiL91!H>H4@xnjRa#AqPA+Ct6N=4)pngu_k|}K?)GjJ_GlK#Ig6r z@4ni9cV0kffS2}xduA@&JIL_+J-^mBP85&vmY31n41LBn|AGcTuZc+f&9Ql;zm^}c zXaM7L{;X&ES?@ev_$OLUR&VQfpR<3L1{1|&yya!}(}1l0wtt-lU-@09k|W z|2hpOipO}%-+%NHw6wkkPoA}drYA2z!^2ikTGk9x6DYloq(*SP@-e8o^8kJqr2$ml ztOeI8w?T2q4Ul*A8pzJO2=-(bfo;2wgUsyXApg(_kdu1^WM$`rJsJB!P*^H(_lg8g z?!my;X&rD}z7F{Kg@Uk%SP&ga260hwAUP)fU*rD}e>=q2?%lh0EWg2F-@zf9?;-z3 z8jS{edwaqC`}aqDAd&C7A>VUBeDP{(YDRqVii?ZE>C>mdi4!LP;#0VL_im7wmx zBSC0rDA>7kCo4`bIW`7t+qRA67nz!x`mf=S;5qDbh~WMs{=@#02>!?qp#c(u81Vre z#{bcyN33|nh#w-75d0C`N8=wG8w=9Y(^)==h)<};a#xTVANT(i_#?O>H0bK;8o?il zfBf|6QID?$tb)F* zD}nC(wZLehFVMH}272aRK-bI@h^smP5d~WysbUZ0)f|C}meaq6|18nPEc<7~pX^5; z*3s7!ea^$Gf2gg|bt5p0cmJAbIiziZY7m(1e4FJf_$Sz)Z8#o&iw*jEvHZ|}^&E-S zJ=^Iv;Ddf`zj_YiZUA}5o6sLG>6g#{ZTyLv(C-l9hxkAL3Vs6Ak0H+ypS@o_$HBOH z$a4XmgkL^K!?>8pb76yRzkL25{{Qay|F8f58~^|RI{&%h`Y$;@9ayKl0<-N)fb`-M zBT38*`PSiL=(|j2Jy&wRGV%<0PuwCGaKmq|5R`qvVpv|yz5J)=l9u^M%pd4??E)4h zy#Sh?w|;sqweT?X*M{GD_!sv-ZZT^hvtTE1+}#D#JZ=L;m&%bOyQG*Uqb1FW0#19n zfTmaV$TQ?UIXh@8DFJmr%3iGUx_)WI=|J9k50G25 z8^~Dhgz*q|z;A)4!S8=>1EO=c0ukda@S7)_fsp=2fW#L0r%3?DMj>iOL%u7R_1zMJ z>V`>+EBJSGvEBOSzFYQ3;GFRRIPB~M%hKKgn@t_SD)}Xh4bcYXM?VL1!&(6R1_#jd ze+;zOJ_H(G4M25e9Z+0tB1O9NPUuP%kq(l8 zfb>wr00ADqdH=kbcXRvg-R|7(&D}Tq$0j~7(W9f`qyYc`bO!p`X4e|^pHNX;W3QUa z@U;)amliX6{_a(~+G$-_fNJt0s9l2L}t)zo!-#Wsl3EoZq7< zIKBQCI$zb=G*fLI^8|DW+}UcN(7KuC)kpP+DwXO{iseU$E5ub>P?#pwOOJ!ek5SO< z#ltiiQ)g{gW3Lo_uavONZm{$R85h<>XXD?LxG?-pD8SYqsOL1%36tnN&ZYyEx9}9Bo7(%%r!qS>jGf=`tA%*|C~#X_zjaw zylONR#YBunDZJvEYuY8h_56pWa;K1Z{Q6mN!-|z(R=_AAE=X%;Uc4apr_iXYRa6B$kJaO_238F>ifQItaJHp8K`0gJa)d?L=MHpUz;vK(@btnTP`Wq+}kBG-_Hvg^t z;I=Ep6YW(_nosGhg67x`Vt;QrwZ;5|A;0*a)fJ)mj0-5St;532duKT$_}cC2p4;m= zh|VllN3q3=on+L~z0Y!>@3vY~+3a@Z6-$x8GW3V}AHFpGhJrgy8IIc4rFUnZv4e(F zhpELILMKT_tYUPV?f)ijZ5!PyYJ?IMp4K7UCrB#(0xBc7O5&++xN9zNd={+ZR&%oX zYtN(**%`wp=X1KbVNx?mS}8YvwWX8)My$%_*Jk^8vQF2*HQA52FAnNH)oP98<*gn# zjaKI(KXAg`Iu(P(EJ^6q4`geV2fmGu9(~6tLh4%C%t?ELgFB>;HmOM&1#jmif_hBW z%89>2KCG(Hc!B`0CCRxAog8luL{9~3ZC(VWo(3%zsfQM8F#3%fu6nqSlhgiW;RI_G z_&5WeR-u8%Eff^rH~ybti<;ESLD|WbyrJ@#%f?b(BJplLvPmW5cs{>yYKny-u$D0z zC`cl5wEL8!&MXqO%B3IOie;Iq{G2P*$h_^E%Y*IISXgs|`ACV76)4 zZL!L6*oo_Z*<~`66>0-bEnypEpSijlD0H7bY6l#oDC6V@))E;i=BEFB{k0Wlbjq>- zJ+ZxaP-~Y77K-otwcY?#90^6Oh>sH`U*!0?G{jBiMZM!3y=;rA@QG8}Pd%G&>`*2f zX6VS+1DiZ28Ftwp?H~HUq=p$w4Gg@P;+leOhRz${{;=9cVLxfKxW&b}oNYT)?oYXm zk|$IwU7dHrzF6PPGL)8=2a%RrJ!aA8{#ED6pd7wu|57ap62tFB7$An<8QIz53gXWhmR3}pgF8Zc5?Mq<+269| zfzhi9JR2KNcm)LojndYRp0I;JRt8^M>*F$x74MV>L@&_)%>-7EshdJ`TpvF!+ilm5 z-Q3({vnyRyFg7s>b0bSzP5Fb&(CZ}7iPK2fOmZNqALd0&B^g@whB13mpFM5$w4@#yF%PdysB)XuF}7e3S* z9Oe3@RD_nFR_ppwGqD9;At9MdZQ<3Nk`Qjipihd>pU}EIoMw-?K5H)SM}_=&Z~)hi z6-|1bpYJ%iQ7uv_r=_K3E}k`@f|Pxen=6n6sh_qF9+jh|qw`Z5_y76^sB&6#)nib! zYN49Ix35_{F9K$YF-z9@zs*uQ5=0Xr(l-3ODU zPPK_9mUrn2YetF135UDBRN3-=b@VbMi%7B-?76D4Rh|TIF?D4-{3K1gyVyVSSs+DP zbQfSk%w%3`Y@gpw*yX^0)G13TjtPG?zgG^v47_kMLdY^?|F(+uOLY=Z_m(TOSY7QK z9yVIBDQfT85wk98|2-R~TJ0q?*QTuSq$3t55;*fLU{ZEg4h1A;%j|r8bHq_k%tlDO zL9OvR1G?nYxoU~A=|JLTD3Fw3G*ly$Oo0KYh2fq}d6Lm# z3$HM67ktOa8z3vy(?&-%ZrD{pnhKqvgdnTOoPR`Z8zWv7-zTU~CGEEzgo0z+CCNP8 z3GgQ;#+YBvAj+s})V5HMUIZXS)l>&~mbt1!)n7_Ci4;cGZ{gcM6*w)URx9sJ98-Lp{9mJU~ZPCYa-Qlk2 zQne_{sLrM9j;;)7cIP3CEAe0g`ZUGNv@;wC&ZqxK=FzaF7j3q1sT|?m0XBsXvCBCL zR@ttC5q)sZ^Z`@E&?L9H^q)!h0))g?^IEi2!1wKX;=<&+-WNBl%pp2ISLl7e9`dJO z*9%&EI?6h4v$U07@6k5ZehJ$MJvl7XAkL*^jwMA9F=WbZ4xg7@Lm{3TW5m}&3l{FnPAa}nqh;ViOH3QfgH#cIt#Kg9srEQ_6*7`Z zdO{yX+x9pS*jXgZT?Q_OJY(i09jio1rdr#MRTMyIiZCzEYA9!^h;Afn;{Cm1IUJJ; zXf4cr_kwuUQ7!*Ek?UyQ*!O*;-IGPAm;lZie<+tfRClMAjPGoY+!ugkhAO0ZXAT)IjjVV~VEdzphjK}SWFHAu=w8uGwC}gT25;8KAf)=G*H2x$ z%R@qY;i>(=n!_3+EVi0cfKTUlU*J^@B?YpC6HVnxQk{|A6Geekhmw7HLilTaXnXYB zmY6f#D>~VAg z_B{3Vm-N^hG|yKmO&3jCDZ2PPfp&E2i45HRp1Rx~Ug*wy1OtWVTjGfB{74TN))G^K zyuB}~_AWFx5w^^VxOd1n(I(dWQ!MJ9^H!a z@6n4@hw3ao@Okiyk;tdSRA4mKO21sp@&`>Pu!O#v-de{+3p-rxqM*Gwo%WP}n2G7d8Hy+tBm)PBwyeotChnqc%Ozx;=k1g8V3W33o>k% z3*`rFO>z1NggN(KX=-q;_tVym>0X#x4&C2bB@NZ$8%vi<(8V=sz7w7*X%o`RikJmi zHjnMMz|J>iheFl!Qt77fQ#ZdD(t*M#{H~1#LnUdSUYqoM*TQqj;ztDe=SH}zr^P+S zwJe|1u;;~AIFstdK+3|Ez$iZv%9I5m!o?0rBrWm>d)Jx;q1MVbPhFh8X-asGuc(n1 z8QltqWJmsh>>ms*u4UOSq6hsh%~gbF%?M8yNHwZ^U_JjLbuI^Q-C4Y6Vz1`7(2HF4 z6Cfh*pw6y3Xw^@z7W^}+BTjYI6yc|@yIx$F4p%4mUX!gAl}wJ5!L}_A2RAh}_fcJr zEe|4J&EG*J6L;HCVc6xxb;$TTUW9-UaZQHc$%;U*;8&B)7WdarEqke06%Pmr(Ws7> zkAm^%KgsKFbiJ!wxPDZ3So7T>dvx~nPK^HFxOBHEYPi*?mP6=rIC35i;Xkq1#23_`xR!CV_^}}KTCagVQw8ss;E5g4D&mkdt$VjW{vk2`<8w*JZ|uSmpm7Fh8DC(0 z(GYjQnpzOl#ftmq$?%G>C3C@%OB7{+Ms71e zVDwR0;#)*v^o;h9+;)DYS62o%g!$`?{|8J+6IFC_L0U6!O7CF`yi{QK%#En3VMM zxeWmd^#op{qWXM(c0CFuBY;9NFnm704xf7rSLfNaMQ1bGh&)F4FsBI@u zsB=16s+%`ZZ-7m2-mRvz54npJBBX1Rlhp30(AuLy{E?N~k;Mi^;lLv;y_a%=NLdvQG6f!4--I6kj0Yrw zy?aNk|-K2mXR zi&tqhL8MPMr<@XVFfx75esH*SGghGo_3`CvUtz}FjJ2)v_B`5+%>{@cXuvPD>@fF^a zDjYQWFsIN&P7$|FgLQ-Ox=kB5H8C*|;4yzhTPRfKRS#}bC*@y@$2G%75M;sF%Gski zc-|`OW@@9G)YPd<6B~w3i*)f6yLR3>F-z`sz8ssa&fD7BD#9W6+Dza~!u1T9lVfFV zl*6UGSoso%2OAA&?~UH&usq%_Y?@t8zgbu_n>91EQrTZFMb2*KuD1b8ml`DsLnSga zL7b^r;>zV&tKiN`{N(r}H<^? z8LeYDpc1GheBTX!>uYxM^b(2#)@h8DxdcI^RM&{y@Dt;ru53h^cAXw=ASiqHO0<8`St^P1&E(u8Zv)LpMd!_Byo6Q{c!MaVP`RY- zSO(M6cs(Wf^JA~{Z+$vxU6FOUo-EG)2zqxu=E{wZh9W_OimVvQD{t1IirzeZvd33B zfdXCCe8jIJE0XfcMt`@iiRY(V+=fc2&*Q0NVXoZih{+DoD?zzikA3hq*d-uuJDr7M zcfY46I#jyhJl=WCT?pJONjzhzlBh5z8^^XSUi_9Xh$N*-4AB;pJY%M|4`l>=I}Ypm z5GK(`dZv76y_g~X+W!W5vB|OCy)~UF?-$G}SO}hs`N}?ha^B+od}%x*9i^PfU6PC- z58Go$E&C{?)*CK>+ZtJzgFc!xBKGCV)~_bUs$+#cm676#WmI4+@QFhDXs?4!8<>)&_?1%;oM@+`d1`JJar6x|drMNm|wQSA!=? zgq+SF4Xk@q72OyehJH~bv3F_>`JD8o9deS)O>VEL>zZjJo#&r%)Fj+do%z)1l5!`X z)%q|NH5d9p(B5Wu^@)8K=@lwaYI#XwUN3S3hgqzyZa2Pnt%}NFZ}kZwRjlK-QnE7D zjCzCi-dnmyZsoAQDvD%o+!{wYCs;__cs?bjgm!)1qZHZmO4Jk{=i7unPG2~&yYo~i zIyQ`ee)O!DA{WFQzLB!0jikk1;50+H19_c)V zA-_v=j%3&CDB3qPr%-Vhi@jWhcVai~oH4IPsa5xEj&&}m4fOXu36|9?2WzSl6%tFr@cJ)g4Ao98|QM& zAH_ZNS*L&7x8jy$M_x(A(~m{06%-G1<8(H0xxl(8}0C#%=B7AXOPzZV|EdFg>u_DQB1j;q8s_{sl=|;s7jT)UT?I6 z+I4?Nu24z*r>mO_yv=%nuEmY#4ig9GGHEgz?+Lq3PJT*E=Emf4-xM8BJ8C)eB+gze_6DOioVkA;rNh2cWv#ygqW~w0e8aiDcxgInp&L+V6b|X3*vYqM;LE2+ zP;L94dDNeDe^hYLc8QWR&e|>I5d0|ax`%C#+`USsi%VkNTy^kBFPDhC>u|fd&ppwe z)#d|@GpqZdFouu(A<4H+@3imhyOcC+z+$8ojY+Gie-?d;yze@S=$*bIVQ*4KYLDfH zs-#|Or#x@Q=LNSfoS0+Gaw}+k+(HSp6Z>5GM8H+%8DDW)IO z;gwYs2(UH9Z+S%*?D~Q{l|M@QQ0)ynZ?EL=a}`Vn=2^4c3U&G@>TMUUk?>fgM$(y- z)CL6+%VzCal%6~G+({}ythtUqJSp)5YGUHpWtoW5+d0>&l3U5V7lIyS>f0Z)Ykru~ z=2>&YPC8#dyY9656T_DhDDsocmZL4Zj5(l@^m`V z>c=kEkKyBe&^SZ7H^+-BgjSThL>tQ@vDd62kO(*=9&r~pJd(bKcn1OG6u7q} zdklfuKpvNtpA`~R+j*rayU*CN>Rj-{$lXG4b&kw$zE&+S=O{jE#+fbuymwfz~xNcvxPs z{df`U6o_8GeqBA)>n=^F5=s@>MasYF^!fAWbLT~^tgJTekQ8=!A7F!Jwmo{Z(Thm@ zuBgc&8o@>qPSifui}Rv%;lYv2sv|4}n`#dB-m~BRCa#6F)n!LcSCVtNu&8KzdsGsJ z`u>Z@QtX{>j9K$(_zWzb(HK^GMp7bz?h+Tf9G7XVH-vEXmKo`@so9-qO-oDW+qZ8^ z+)iq0Q@&A3eDafe$f@8B{$`{KI_Bo|g?1^S?d|(iE>Oot!zS>LJAHobFA8zQ-k&#+#Bh?<6`BMx)z?%kNS3{`6u0{l~`BvJdz zSy@@y6MQ^84@Rf0%FIY(&_zW>+GF=-?>+(^`lRXDm{rAxN~dm9>Y?sO zaNtn0tPO2YBRagtmnOVU(bm>hWh8bz)?RQ2{#80LOBD((EE%M0fJT$U;Cs*QQm)6) zLr72Ex#=yX3k~cX994twX6)z^uMId$3YBD9n%h5x>}3wtT|H#GSZy7uNXt$hq8msW zFfwvvQ%!y2{2Uqn(D-b zddt>cpo!l{G*eh8X9`CeJ1?)6$0rlh$(?}*XUF>eOk;LI z4IS{MNo}e7_-@c^K49d4Z_?$_y0!iQY6mZ!RZQ3pv_%z=-(+4l=p<3~^DIT<@ zkD5mo;#QkrGY5?=l}X^`(K8%XA|x0w-Pzk>)B^_LFh&@mcrW zwLMyhCQ&P_l{G@|{aALX$kd4OR$$>+9-!Pmbhm1@v+!=mGm1M&both_=nU?t3u)bB zY4@)VI@%1_Mm^b0bc%(5>8=QIe}H;mCZ$4aYrAqL=4Azo!Tqt4Lk{#u9)t;H1goo? z#CWMYir>9%9Qj~DxqqLA5~hU9or`ayI+5t{8&@(qFg|nqLZ2wC zcaJN1zS$a?tJ%jl_-5xJ*$~G^WVh5K)B4wEYU`*HvYHlfT|KE#z2=%QI(LsR$58yX zSNQS`IYS0hZp@}A)Skt=JuxMCH2;Is6D*+TKq0$?e!LtSH{H|LKFB7$xJO=k`U$4K* zEelR=%#y`&UN&hkw}D9H9mDP@sg*lECy`0(Wr*(VV%A1CDjW2L*&aCIvTusScSxGR zKOl~tQT)x2@Ph)lulB%#Bv9_;v$rz$9gH&SNVC1{`!umm#BgafNY2_$PyWj)+ ztxfOe#m=AJ!LcSSVpz2@AySc@_oTIr>H25KDKk_r5D_P(818WKzdFQ+f)bcQJUszi zKAKxgwho{h$m(3XYTj19y%lmjHOeoS$rMGvVS>eD4WIBsDK(Ptd$fOKzj)^9xhLD6 zk?Bm4nC;x;UmZt}7tK18vxa}aFC#%TTPXA8k*bsVWLfzYr6vt>FC+L+8%%uhG~U*2 z_g9+Q$e6(I>s*$_M1_CEK!%9xxG5)=PI$S>V>je) z93UBAKhw?nz+b)@#jb;8)24dV;_JTWbrz#Cb_|`xD;3TWUB?zHXCjhMHsEmfdTEqj z+U4O={Nf{zlXU~Hu64>G9qJOfFc>Z!INc(C9!oe8o}Kw2@){Rf=9m!$7sm9F4~cAz z5MNo4ZQ{9bEZz*0@T?B$=|Q`Z$}3r}!_TiD3yQdT2bD3B%+38M(h2Kxm5x~QARkKB zWP0sp&D&c#RLhB4^4YK=o5Rdc@}oow2ow?1Zxp9s?fIj|OeuT8Rk1{$!bA(9*?! z(p>_zBgItu!@TkQU=^j&+yjdCSkUWq#A(jK_o1(swsz^l#VENchlNoZES3+1JfY7C zvGH_E5|;5GdMjbKbu{_j*}*W$voDw^6^M?$rY@ct1vQB-#`!Zmh%B(4s@Ttw1XX`- z-pY(5%dF&d8*>ortrjnOpJq8a_ekq_w0b4KR}5y5V)THgzi7cjwax46l%8 zwAZ*-6bAFjt*57VFbvDASozA?@o_+LveTzS#N7@@s45}2AK=97poTh%Huf5=3GPn_M0bc)Z)v17PKJhqM+p9!sRi$^Lj2EOh0Uy=!J;cpfuIJQ`*dKfuB9S~tmw z1-(#`)zl(_UStlJezz4hH!c(+gm&X*OU)%H?2VoBURXr2CA&%(bM-oH#pgurJUHZw z+3bq1(CIZtUp{R>E8=%N_06ZJl*WeO$$l-lcV}f=n7gJ_<7D2y&4L^Bx$@cMwoz=w zyG~Bt@{`+(8uRIvTG@7Oq`qW+nxrS(dSXG-tT#~`D}=qI&WpYnJK>9;op&q9KNOFl z?~HtL_mtEQ;^W2R0rU6r<%cL0Ca0TPs)ir8;Xh(H*~P)WrhTnEFYi?G$6FasoocVl zi`?;t5AnM+x@$>c)#TIG9?&B?O!|s$QO}rJ)51SoW6y1E`kq)Q6iv_gaoEaQ@XEua)FThhS{hMIL{&pY3c(_K&+bT(17fbCx2i45iW`}p0a`ZZS#7UQB@NbzPRj38F}@KGX;$u)%=_*dCrnHPd6T(UlE=o1x<)sHV4mhH^N|;P zCr)b{dOyRKVLO98q(XAttICQ_8*Ib(QLI4aHl)oHIToMnO+Bjqu9CUsm;Oxc1SQQEk0L*`TkgEi`~p)X$9$JALT!-X^=;5li_ z`{~tts-TNPSo=*iLydOF2i|4IkIsKOwQa(i_U0KLKeyW=x@Y7i;cjOXK~E4aQy4&) z>MlX}gk;a;i>YlUo=+SC0)`A1>x~v)e3F~`bbdDDb(|*F++>X9GZANabXhO77?#^_fl}CFd%jWm5!0Tj(mq~dSx4e&5~+xHmZ}1t zkBI_v;cIIOYvk-V#4=9!ObXzk+tlq}phcZN^hK*Ky4X#24jkUUm=gPBeyY%I>Vbi= z+U~`(e(me=wxPBn9aqn;K?(ArWg3mipHCE;K6-p7*c(j%}v*6%?t{ku}R zXNu}}Qm+~?rhEgFSIBWINVi#?>a(rfQd7a1uaAzjPlt_Odz15W+9*IxfSNk#sonTK zY8qoT{Y9Y)H*PVEBa2l<`(4+Tq(tN5ff4lNN8QK;>W1Mif5u@mGoOLu-e%h9VG@E( z<3(=-=zL$q>UfwBP57qlA%d*llnZ{(VYuf%=N;smm93f2K(};`Np<8L3Z-)EUvO-k zlA^picC1Aqv(Gcmyd&*KaV#OdM>=N8K)>rmLu`}# z%Xh=uBjk!s3g@rUblFtPXpI_@_x1AZGi^?6adVt}(P6aM(|f}}KqWMrSI)0=&SGER z6yMyVmZG;&`Ez|-ej~GC!$Ed@nmRQ$So?9mk8APqGFqn43;k@~pxQj&weQ;X;hn78 zuvLqRS)^xGD^T_6^RAI*dRmrQ57uXbgf|YK=rx31?Cm*sGeJId7#Qu=v^U)|1)k4g zh69|m8@f4)^IOC(!L2~!e!$iy66*JxHOt;NtJ*d>P_Y89u0a!*zEq}9bb@St?i;q@ z?}fZ)aU6y&y|}5(ME3aHbh$Hjq2W!uQjBVemS%ZyE-O}v zyeZG!X*hUy52@)yR!&jGix-zeQ^WaqU7en?U^2z9y9O6Xx`Hl|$9OuRTi#f7x8|M2 zTB-WB%KIO2xlSryi>i;F|1f9W(l2zPz>{=%non$P&iimXMd$Kh5}N8)nRL-7uwz}B z$wh(b!xePHgx4KxET-dj*iM|$xF{TVtBL*&u|6^)pvXv=ARw~%BCY?vAsD_^|Frf| z$C0)zgaeK*jUvs7PG#HCp6D)Qio4F@zT=rjzaK6+1h_#*5jpP607^5q#J){U{q&zwi~y6JVaJ&ldK^5B88w-YFb zTqbV`mc&op_^sZxJKQ0?U`jsV{f!6Z&)g=AicFgC#@SP`#+KR*j&5fqoKjC%1LYGs zC`v8PX|R#8m{-V02%%1L`(5m+ z@o_V$;XzkWx!H7y_wmf+rVl5(zrB3+!Ol4PwEX;#jl5VEyDs~eh4bd#1!uT&Dq^#< z>$8ToHifTKz+Y|5aDKeS}I;&jjeLXw@4_PY233v$EfAjc3mooLpFPw7CoKTieWs({LrJj zH+6(2Im|R2_t28HU{vLiyly_#TVv+1K4gSm-bCb6@v&7o*Kp4?4e{*POsy zuHIGhj4SnyUPARQ(c#&+xJfxN5U3j_#eJL4hqD9WWL{nt%5Wgvs{DelI9n<~%9@X2 z#|ehuhePK~*GwvAI0B6fnaeJ6N?GB30g z&40kyIh55&P@0p`b!ko%j)!p<(wld-y&{RfdNNY`OWkUR3(XDQ z-Wnk(lxw_q{$}e7A#^XFB}&bmh@aV;D8d%2EoX~If^m__P`!39Yll?wYhm3?jmim< z$${4eTefLx`x4PHQ3Y+|eG@W|k`sSp7$)~g$_NVLyWpO>Hh4l?)1J(j>!w$>bY22no>oNm(HtG z(pRsA;+#Hq%%ZTV;VR{hmWQ^3(OvmnQ}?Hu&clWEDlvMx#qfN`0F(|tyy-n&kw_M9 z9FrDV9O>6k?O`&V@5I!p`(daMBx@0dge62@(VW?rJru6oE`@Kk$dt-Bd{rVEL+2{) zd>lPY8A>YUL_aFbnM&L%dcT2V1RO6fG3nw|M@l%;nn9=pfLb@1x^$IH5~|8YbFdisfn9V>Ji z!n_u{))8dnc>yB(x%$OXF{B<@y-VYHRB)F@g<@BnhjlXG-h!+ zhCJWBYM1wD#G323?GE>Ts81dLpy{jG^|86ispwr#h{WJy7N3$Q2CTjAqcVJXPh__x z+**vZvaQdt-0emoUsBJNlVOg?W5W43;13qbq&i5<2f6gU5g|^5?e4j$Lk% z#XMXHM>iH{@@(ga3oMn$Nh(!dS@A)a1{EK&^3j4q*@m0QuE&<9NikH2$$k5Q5E}7! z@K0IWRTSS;_fn+{mnjzU1| zbNaBNFHgh7#tq1-*EH2j*1u4RetOr#+D5{MjG2_b+sG)k(`#LO9J=Hh<9uLRMW@wh z_5m|rdzbr!Q7l*%{ud_AUo z+|#e+jf2laWx4VTPQFEWcUi7&)t6c6;!E6V@}20AUOpawa5&x>`b zzCuUKrBbxu@<6D{Gfx2(3_Mqdz2{%C9>;bJ4!DqNj|_DQx8}aQ<)zKZcI7Cyzgzo@ z>vMSBe0hv=l`-cm-KUE|?eHG%;|B4m24-HtUK3tX`t&*4I)meObF)28)M)g;$qxxK zF7l0N4?C7Z%sX)!(J{5wpySuHchp6lagvyiaM)R{df6gje*Tl!^=GE4yhD`!+4yOb z@3ao=)S#7!#Q63qk3wF@AeHPrOHTKlq&a%uxL|s}$WKA6`xbWRGz|~EnARG8F|GZ| z#UZV5KtpqogbE7LS<>&`ZrD_#(Hhi!`JmComYV9C(cGc44uXf=jod5Ztls6Qnhj!d zvRMtLdJXVhJIlFZ$@Ym*DBzJ+kh0HB_41AQIB}{|(xEDQCww0I^}CY@d85l`{95FE zpV{yhPwIu4db(GKgn805-xogRU&WP^^CG>@JmcCuf!#ERLS8gEn_7=28@h6>ZK4d8 zs)R+%L(3O|ccd5U?TwyJrB2r*L5%_L-7D2ma@|Z&^Ih@=HB~SiuH@v|mR!-jPw<3L zc%Od3K*br2OQT|%Trb4YlQ=CugT|$y!gItBq*^Xgez+99?TABX&cewQ@SFJ6`SD)W4!JT*a_+ar}cSu|bzGtGREHO+*u)#X2=N)wEOW=nEt4%BaM) z~55E>$Qzh$9&_qJH*%do1wMe*r78S5b8f#xNOYmv&{v}g=m+i4~o+N4h z!}0uUpmzHd7t#ivwe4kr^=7q=8GH5nA|?;`JBEC6^yGKnERWZuJyp+hcxaUt(lf_>5S!uWWnOFmr-WSSkmS=m!^?QABIDsQ&qP<*Qol!gwH);o|9pL#r8cq3F| z8`ZIs7~b{$DKE*>qRqO7-g675pm%yyomJr=3%B}4MWrrWmpOwPjjE`j& zkZQa2;cUSDsoudx@2knq&nzA$3T!FNnhSNf`|?~Pf$1U&PT%Jbh9^3DI=3fUSu{;l zUd|Y|zmW{p(xe;wTQzqP#?FflkiIlpoJ7kUAKtLgT&jI9i@^p$&Q%M9yZ zYY3i-LemuVVrZt`<83;EwWobRR4!gc#NsFRs!6U@?!z$#Q`9C;to;iGXsFRNABuMh zmv2|}KTCOfuW!=ifczvQ(;i=)smx$!FVwCL^1d{x0t$T47irJpOe8;QgPJc5^kd*# zznL97sG7+H4uY*So7b=Lua3gh4%D{q*$OS8YzhtZN);$}CD{9TLf9@AKc=lse52|9 z&ME$DxzK&GeVhG{V52qChr+$kSEf#fdZE^G`xTujk)kDNgYEXyzgJhs2FSxE9I-Wz z9`_NIvtL$fpr7?US2!=)z5~BLu+>yPss@k6@2EbX<52IKh)wCG3?Ce!5$oWVL~g0z zy>LdNxC9BHm5CzV#f?}!Xaj0@?$)vO(17JJj7)TkSG=tzTUhq^wsi<^O~aQL3}Ae& z(!e(xhk<@HfrceQN3<*9ISthPvd9t~hLfnz4=ykweT->vN^V0%k!?EF{iZ5rJ`Yyj z;v^2Qu7?gbDDJ*3oA6lBde9{&@QyQKn;Z$Wyh%c@oV^6I1j+2!VfnTGOvLI=48p1b z0(%w}6yYf&6EB4H%-IrpeHh+(> zAF$pjq2R=DxkC1|@#0n)|0ANQ7eidcA{=M@C{BmmjEft?P`^snvHDnH+Ys+}k;OT9 zz~=qB)Op@VhtW~z{ciQ_Jz<@_zfXP_H1}P%IqJRG%PeA$=}6yhQLMjVCiprjmG@M* zo~{eyWA?q-jqh*L5Y_u;-xqLrF(kKExaEawhrmOH>s-upXGv|C6q;Z1?Vs<` z2oaNzHku_m6?Z1*de{+n=lrVl0&d_q7siG6N)r4h&s?1I?t`=uu%?@Mlcb*#%Ni8? z>{ixN%2qfSzz&Z|VPSv;acjnXpeu7OdQO7}if>s9#I~#hk}KLkp7~aN zZf?ye1&Xz}{)I^iK!DS6;B(C8Z*6d}tHpe)J`ay}lnMiI~7dYz5f+M>{ zft8vB(Bh&6`^7kcl(=5fx9E2|_~Om!>1i-NJ`Tpl#z03$2PiHs2I=YPAS5INc${zq z4i=8(->T0b6X?hwWD7V%O#q{i4PfHa2TUT?fQn5MFp5|Ka%K%cCl%oMt@_mB0mrFC zeZeL=4e;f+AMQHx%(v?E8C~~fQHudI;y!>$IT~yi@dk_vk+3Zvz^E7j&piQ!h>!EP z>dX6MNLBrxACq(Lwh*&#)8jU;SK&BNr?ga1Txz;e6>iCZv>KL8-XPWj4} z>($C*DY#}Wty?niSdMHhZv8{*tZwI9=ih37X)4 zt#f`ZrAlONLHfAhegYgb)&ohA7eHHE8)#@~02faA04psuaKh98EaCAZ?F(=#RjSc% z02b2R;N81-0Qyma;{05&f0raMkdpw{(^ElZWhE#qECjpR>2ZBuE_(_nI90?4s5fWkZ3;LgqKK!KGW)YsJkucKB#gmfK_R-BB|_gA;`t#e^s zl}cnkLHh8u)CX^0zXHm9P|*$Xc>er3P~>C+br0?XbG2PS5Vnu>@gwvR5m2er;UEE~ zk~_iko-TlV9L@Fv>;2l`kj`#kt*-^1K79)A-N^-Vj8u>hSPOn+e2NOHRqo^20uG4o z026OsfwwP*!Q9*@P<}5D6y@FqBg4bsQDXyWsC@twcaY-7*^jg@F059G>{Un~2W41+ z7CQ+zt|^7X1NxVOeNuuzcH26j#kPHU4F5>`5+b`R4TZ>Y`ytW?LM!BbJgh1K4d@b} zu$>S$c2}+&KhnOW_@2rGVie$OeJqWurTMYc#}BnHp;2inNdy#p1N%RT{IKBblDd-g9|Kl-IXLUQ@I{)46v#H1A3Yy&oj7kZBO4tnu7~jDiBYcd2 zaqj11$lLH6=irX1#r?rHey1DXf_L?GCHD>&Is4*yajU#JA(LBJZvE>YS+z1gFsP)= z&?|jewu_(ouw5$1dUZSh8|QFQL48Eg|CWNZjqqU%u*k!*%!fe%&;s&zNcnI0uyF6) z$4f6X$jcxw{GSRpJ^u&~y#TH(KMU)!aq4OREUr9EqR*Dr$$$D@l4+OZTG_vNJERWM z#?SW8$0&mNr+$%pl28Uj_{t^Tay1M{8^5D}M0Q`|JH`K!$-f4}uk_E)^mY7^z7f7u z_%9v>(FuGD23`iC=Rb?T0JA7&NlsmQ4@loaBx`{p>kg0z_oBGa^FWz}7RQTy4F*02 z;h*kbkVOomw0+&Otc>){PqGGZZ(a*5G*oarZFO}uFjtjd<_A~9@GJNWvWa03egT0& zk#Zdfa<&H=Vtl}Kw<0LMn-5xAT5vGjg!&9)$OCH&Z~%t`dXVoWTpp7=^n%~Lf3AK{ zLhRxgRl4;!eZgrP6Pz4BIy#Emvzs3_fw+*fAUZe@RFsthgbrn8W#Hbud*IL>#pUtv zEB%XbNMI2C4FW?-un(A-nZd#Eu)Y?E(Nln39E?DLjR8nAP=UKS*~>6E9W-7Z4?J`N zFIMCAz2~A_5*T&nO<)NIL?%FBIBv2Z$4_H07|`9_4G!*60ycVDxOd@w%=&Nhf_sPH zPxmjzBZ+~od+_b<*X zh0%sQI0D07ZVFIQkc;ERLw($Ux(GLDeb@*Z9@GF8J~rTU+!j1}@&w9z;XsU%7zcyY z*0tbQ)*lHzDGZ{wLSQJoo{H-m`S)RF8rVQth6Bp4?3>qsgPJPfX?GXs?d`?E5EkGI z$KPkY=dbiHDIkNnJ{gOi>-SX@}Z$vhKpU*ljI8F~R;VES=m64B{3L)izBuM8x3 zm*taR>0e4v7K6w`OE5U}oP=ffbv-4djn_XHVHXFz&XvqIfBJCtXI4NL@yi z%YbyJ@p60gO37dgyT$T3-L6=$mCJhhoK`LZkn`9tpZ_=a&nO?*B6p%0aOxERw!L?t z%MUJmIwf1N6G-dNd@klMk)xQMdSCN>_0t$WyK+bFb%|ga)3*Xa0Kq2T-y1L!(Jy#AGkkSqw zsa6jhtWfjA6exQ3-I6)kbw%8+BT3*;Yb1wZ(^(F~hOZVD?czv!g^QQzWnu)sx4%E} z9J0PFqELQ+q9A=EdJ4o=bP$$hJ;hEGifrTO0x$pj`7fgY7pr2fIOWzw2?~;*Dq`fM zi(=bI7sa=c{8ixbinfrpxmcC6e-~LqXy`sI@ozu!jmYOx(60f}!N?#5>Sb_#4v0Qz zg-!@*6Y1l3!7sd>X6{GeMxMpN4&^08hlAKE{}T>KAOBb2M_`wLurJy4z6Xc@EAS(* zi$mC#bXebugV6s0`XjK5Lj5CRClrM`xF5kmn2P$hjUQ2J+W$EI5!i(x?1-InNmubB zI0#YwzVR9S$1hoBd`lX{U<-vL)t>UPq2pz2y$}*N3?f;_j?fjo$&A2F^AaT zzlMV>gq;uSO?aRVlNZ8YRB#vEzkeTRH@|)3`gf0|-${Q7I=VR}>d&^=l{g@<^Aba! zsm%m99jw6C4FINw!O39=4u~u$M!w;@a1f;Yed9-xo_-Few_Sn5ZiX$ueD^NE3CBCf zrZqTQKcYWHd?Ow`dbEr~h_5G5<6ywyAWps>7)lER+3h4>tgXKlekS@k)g7PpzDw`n zR#FVkPoV|seWT9?LLaurIQbjV`K`vGq__wKx;TOxSFhk?<5MT?ar)quYpVd|?^}PQ zm>K5~AC4s)td&KC$?6|SCG#`*T zy&LLcON$DZ=kyW|h`;2@{o%L5&&o81_&Y4&phmX=B%XE$(-8h89LzP90qZ7wa7bGX z6hVKKyViOTr|H!g2&uQ%3g!9u` z!T}jechVAY@1d{vDd2$XkTRt83pkFDvDDYshZ|2S+$=bss)~|g91iEa+`hWU@o(Gy z+u)aHXP!fJldEw+=ib2C59+GXfE~i`Y-#$p`GDYX4BC$n`_?UJQ$p6In6qbq0Nf{5 z@6&w06Ml}JbJ}dgIJ?729B!vw1dEG{V4%Mba6o@zEpdME_U+qc91wfVZfFBT=0i2y z3y^gQSx=FDdL<6XI1>7e{Ld~fmN~??XeACoC#}K9*$;@wjl;ogj{*({*CXbjz2y;T zfwq+6&@YY+&ItnrspYlxVPhjW2IuY)4v5b&vJd`F{#k*Wbq=w4Ea4F6e-a1x%6~)8 z`+*`i6AlMtEFpFnWIoHX(SxSCTHJg5%K!tWQa5LTu z_Aqbzn@#I?!>=O1KDS@+v!CEf9G2$8(%P!Sz7=N^T*3j1#R7iHO+X0BlPmdF1m4x< zcaDEmL5?}Z2l0Dw7<)N_dk4tBm%~FqgnS)X;`#mwhu;amnlQ&4VsrZ*9FhXvKurO( z{lgOL=e*4G{U;oLC;YobIOh-_&F{rwja3u5CmdEfH! z|JAEkalQZv2?^lh#fu;*DQOx0K7J?sh#vxjO4=9wQcDH_CiNR%T&EK80XwzwzPOIi zfK9jbi|hZw|LwPj(B@zIf1WRYV*F6@ADtFCR0o%B*r^%`)B^^VuOn?y2s$CY9q+z90)Fidql`P2 zPTCuA?o9*R#r-}PF<-EmaUY--bpqV_SO0dMgn2)p60ie21~>lSby$y-#R%eN0r-t> z{rx(t3G`_)dH-ure!I4+N7E#y`dPrD8~}DI`U9q2et=QV7tqW2fE`lafL6i_P>XrM z_+fWIDdYy}>H1v-#^L~SZadr>Od;et_-zP&?T-5Cq0s%2Z{F*My?U=5JUp!)_+nDc z7c;Kp_3VwTQ_m|Yht3f(+qNM=%SSJGOdBzrM)iH)Q`q&<80OuX!#m`oM(AWOxcwTG z|JMHBqyWN?!LTOO^7nHTiV!*f_xtzIVHLd*KP`D!{9#%4(}EXjVD{7;v-Rc3Kj$j?QCwF)kKm5P zKH>b}$OxC;|M$=Uf#GN2|J8c`6Zj*xNd)gDAHW}_!GAOU2=3w#cO(XM$=78m?~K%U zj)VVJ{1MwI;$O1lWAd{!ko_+l{|N41^TYfZ8X$Ybug>G2tuMdr$Jajuci|PW;H!O6 zf1Cz?4*y*g>%gvUU)pL{ukTCe2<}13+rGLz?(BMzLe+5cHoZb3+XdnY|7l61U zekl@EBrpb48ywxQ1CGLP8|Y6b1+T62*ZSUZAOqLQpB=xyT2B$l{{!Rf5xe(4(E!1n z5Bj|D5P$Zebva}T9z1w}i$6zf5s1&7Ba9LMxpDC4@K>V#f4K&}MFRwP9*8^QBZl}J zA~ZPfEbboNHq>4Z>ZI;rx!@ym^DOCl3t`0SxrD?1wqL z5W6fA7yVB(K>YHNH4(}EiP&fnf9hi}7b}AQmo)fu^Iwf|(`TP+BfTXM;xk$5+x|$?x}4Oe8pHKi3VBMGr=x8@-Jv0 z33Ipn>U;dz`n#Dv=Q_dpApJ#yGqxsRc6Jt*_XM%SucW~<`0mZrm7ov$=k;LanuzQR zh#&WTI7e3Q3oFNg#cqW!3*Eg zE8?@e3;Mmf95%=KRPTa$BA50?gfBvT*;mq_w6qlXIoJVl7_0InkM!s8SKmntkbF0* zX@JZHf6M(~?DebVaZq1f1%1dr`}`i%QUyJ54Om(a+S^)jIdKpg@RFc{tcl2autbB# z`Z~b3Wj$^j_}JSn?~PYelKxR%5Q8~be{~%HY<*3(&$)iSMS~HT8xrv~M%IIqhm3JC z1RA0|U#y8sG(ddu5kApYPkVW9yq9+e=ZpU>nF+~3`?K)>YCSD>QkYwGDemCQanRS* z0Ty5mAcO`!$E|Vsha_Mg)s<`F%5fmJV;hc7M0lhn{vhY(^<`iFuh9U}7yT+8KU-g$ z^K-7HuhBrAg97wD{hU)4p+RnD2F~{%$-#8}QsNghNRA3$-WQUg|M?PsfaK{Cg|gvN zJi|&FAUe}OssGa9ggIe3VcZ5g$=}9-rK%{vz?h$vpV<%Zfx=($4~WlqbZ`J@d(;G4 zni@a|j3eMCTaV+FFrvM zTUm)ea@<`100=>T9*M=l<>LA)4uowpK5k#+-L?srpLuCLSV@CM$QxqEXIl#}Qj-3H2D#d@%EZ$xO28XNru?tl9I>+zAp z_>`@B_<{zF52|6T zH~f7NxF$+Kz0p7E6PM=xpT^%nhys^u??-7+o_%c@f8+oe2e+@JLHwaD5ZV;JN2j_( zgFiX`4TWLucHz(Y27iPGnbBwehCgx=doBP-Lw)*6J<@7@;u6j)zyBouMxvi{9sVc{ zT=px07tgxE=!o4)KIhiQ#XSAQIQW*_h{SSzFAe@A z{>I{;b4@PCuKfWT{7L*xB(~#X#*loQe~Jcw5`R-E>gAZT-$esNr}|HG;ZNdkCQS`i z#@+oc8vN6G@F(#%m!SdXGTZ+s4gMtly-%9Ki~b&ffqPkBPbcW^Xa)@x`Jka3DS0qn zJr6Wimw-q0_hF8M`=I`Q6{ta%fzteJkeiVNZl=V5jQB8+5^)x!B}9X(>6buyaw14c zhyw}mH{*Qa@83CC8~`@(caaXk{MCn{ee8s-74UX-2LA3Y;EabWIOpm1$Mio)yxr38 zDj{)$ORKk`9n zfaD-XVknpJNAg4 zk&(DeB&HO>-`w~B?sp->VJ@cs3-~Y502%Mdd_eMmd<}mj-vbg)i@bM)4&^Xc(bw?5 zbm{VLntDfp^)Wwi zZ`ayDBKQ7sx9c!|P^X7yRC(Yy@N#3;+kODq!JI0$e<*fR|4l@QE1yG5j~tYvSTO zk$AF|F|4bPfAu~wuKmw_t!^8E;aA_|&(=r!-o}3da2nO&Vgp!z{4A43=1UU5z z0E_00<-(wZ{MMl+j9vD{-RChXS-yun$EcbDHZ$nJnDL`P6V?|nul(D6=G|$4m{}jj zT^|7Ir(XbJ%i6!)-?=9P#%sghdH93--)06az^WDj45HowfrE8``#|+_Vbl5lw&6do zyx)IW%c}noli&O|Nj(LZ1F6#p+5VqTDFo>MRIq-F?DHt{TA@4t3#!Ka7XYdW?SJ{- zrr3N)kO6D|g!bP5Zx*}gzd_iH|9ZjG|LX=# z`>*Xk<-exiV&=0%|ycc-?ch7%$$L{}f_FeyFY&-u;TetrQoh?Et zmIR)SB5qO*Y2W<$idp7$5hlqx2tQqtr0Qn&R8oNLRAhUoX;M1<^N9o}b4&Yi6HKsv40PEYb!vFvP diff --git a/games/NXDoom/data/setup.png b/games/NXDoom/data/setup.png deleted file mode 100644 index 3a775d24ba96063062dd1ab5ac2ef813a6a64423..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5654 zcmV+x7U}7UP)}X31psnVzk?XL_qT-~FSydb($Nt4XF$lkWF< zW~#dCELHXU>MUQKIt3I}R8d70Ra8+$6;*IzGBYOv>so*A`&Gf-D6J*7-BtmA2RIrOufo z2%089LjMzj08Ky$0TKiu1cVm1&-ksINOV8N#TOuLd>;uKkFV)}0OjO71qfpifuJf7 zh=}OAhJZ>4s2Tw5uC|q}y!xdBo}3)e1aTRe0zjq9`mDoMIy2`PGX}<`7JLaBQ^hF* zA^&e>c809HEwVD^7OS##`+od&XA?XlW3moIs_Y6!O^F3A zt5PEC7^E4%wtqHZ<8ymtWuF%cX#$zXs5C>;BCw_tQEm^SbB zks!7;4}wVV3D_+beE*AQqOzh4P5av5@p#k59|}b9%s~$V5fR&V`^C#Kzp);jEnR4D z?@t?lETUms(;z%!VE{lR_32K#q!|Fk^}@bz?#U>xsQ>^h@{M7rEBytWRc^=I{iE;( z^)CHYE0@AO!wmp9amieC?{7;Rf2PZh*5Ls5d-S%)Wgj>Wv*+s_k`qpv58E5>WQ^ZG z8o|qLLjZtfv#YS|l;Z&a3r|@9G2%@)zhqL6BW&K=3qWq8R9Y1fe}#f^cWfw-{_X{U zU_>AociZ^tn$%w5We65(s64ug4$H zpGmX;X(d3scD>mI)i(w;9LBEZJ~RylQidf0T807$YvWgW_r7+xtpMj7`w#VESC2n! zeqG)$di~+p@0PA1wCvmqTbUC*9Ui=RXfSR3;h=`*!SSApKM+CFYj2^fx)NT`ApY9q zfhJO0K`vnMHLLhjajT2CNK^9PO^ihOHs&a`^1=W*eEI_zBA~;Y-NTq<@d4oQ z6ykUJ!qB2t)b2AMe<&2eX!PM!&uADCAu`0sA4xOS3mRQyTy(~O1(gnX!vejd;S4d8 zYqrY{D`#jO$^0}hnQBU`sCHV=JQ$1_gBg|C6wGni(K-@DP&H=&3S)Sx%_oILUKl{3 zOQr$jMHNt#JV|>TymHMKp#g|kN}zIk(lDhi7iP?w6>DP=5eNX0hz;i=K^W}shi_yA zvDO&rVTJM1h!9|mp}MXP7OOS7k068wE&4JE5kV6I;ZO)&ZEboy(qAYs(jX!TO@j~u zW##3la978@yrMzGy{Mu^Uq0#S=!D! zxujJAMCr@_a5xOV-w&J329L)R0~!z3SZ`=(fZOd(h_7iHB9Tb!@9^QnaJgLQ>+3@( z6iSF6pC+IWEQv%SP*pWyX{RSkAWIc$y!*z6Us zJ1Ssvl*48(gM)YA8@GL>SOpjghr{rAJo=qhRyGN)84(dWJ3BEtItq)$g1WjoSS(X7 z_^ehdTrL*?z~}S9=QBTe#1Ll$J39=B^dp$2Q+a0qkw^rCgX1H10l?*Qp{AzBbXr7& z_V#x8{o@zdFakwUOs8kHT2WeBny}65^su z)>cz>vZ5#`D=SNB1ZLX`{r&y$cqYH7bCP-SH$ zX3Uro`#lx-hB)UaDJcPqdqabW5`LReUtb^k`ubwO6-B|4B}-6JlDrKeQ_>tknxJA)DLt9&0+B!dzIOlLWod^U1v3~rKsHdj~nx=tsj>U@?!|8M$ahlU1 zX$G)iqPPZK{CO*H(_$SC?eUI?MZj4(dD zo@O^1YRchk^+J#UV-_%Q5aZxX0b?92x|Ahpt&v&he2IuSfGA8#G=!wv^_A$Raf3XutXM}M7%LV2M%<4iO`|xE;Vk58!KOZEw1SrCnF6r|F6yeL2 zR6jrwzI;hDfFk_-Q2zA-^pzs~94Wtg0s2Z2ehwwE3IK}m$-UVy$* zgfB@FCyFEhET`}nFPMW{Z}=RlD#|7v4FF(p$cOL$cq8^5Y%d7-fb41Fa(w4M_`MtP zzSB-jdq}hDEAZiqz6!>z$2@#MavLDm#s1Po^D-XRvZW_L1o|Pg@G%b`klhQ&A^e)E za+GE>=vHO@*slzig*fpcchh=K+n zG>G5;NQ93$_<-zT;W>iuu-UNu8U&etzTiF4}j))|oAInaWw+g`%k`3=|Zf#;=NNUC5-heul+W5?>z`u%0S$f z_V^043dp{nzwXA*O&Pw|=f@>i+>8s>T$>R-K-lx|1Gx0^|H75m-46fgm}&S#1R}!P zFJGkJUYZ|FOl|VZTu8nnD7sA7pSM`d&*uXGJ-r@$_!D2mQ&0a5WKd57pW?P}-S#pr zyySZHdj?IxHGlV4pgH~5Kqo2~4B^r%ZpK@C5158; zXy5);TyxWUgu@Y2@DH_h;RpBs3JI523*@B{$g2W?tl)!ygDqY7;6-1>mM6Dmm9`K9 z>+gC9+h5x?3BJ{$;Id0TjVFG2A6|QLGj_cATRi^Qy}0Bv=fP@?ZxicP&g*aP#eEO{ zI&1jbp5K8hu33+^!@UVi!G!#Yq2eX25m>$S0usbc`SwXu@#Qri#J%77I_$RO z4J#o8+B>?j?0ug`AQYWAItu@|d9$(U=l5dag2tpk_w8@NRoC5)Lx;QKQsi(tZ20S+ z9zjFBJ0<*3D2)3b{tf={)C)+wuXOlv|3KUcigPCyWFs(}JAdMKa0QQUegz-;#1&{c z)IKT6ac9h?N$_Vj)Z)*-`$OX}P6@xGvlmz0 z@ZGH70~}0*@}?w^SOu7aZ)|6rW6!~XN!39-kf)!0(a0paB;57wuc5xqov|pdtF6X2 zZ@mTvd|eFBzqm7HvA^}X?Re+FA!GwTwpWC~gbLY`{(86>_(1f*5#w02Xi+Swcpz=< zU1)AOoB)5;j5?h6v9q(T$3MRE1DM%hlmZL@LwiRrdU`xb<224`fEoD4Hb(M|;9b!R zNPr)0sn=BNF5ihjJG*)&wf4_?|LIA?rs~=O!26ajg8|U}(sjG_2EMxO+{&k2$s& z7!{xa90`1o{^Tzi(8>zeq<;SJh}RT+eL#p0@$dnL(o$#Auz_F@Q-v>E`P~ah0Usa? zM(@UnFzRcojpSqhcK&OR=?6QzcJEJs4*<0_l}W?;d}HrQ_&`4Q0@A=I0`@nxCxtP0 z&P>$T*Nle+(A3<9f9!ZOYxp~M?m>Hdcl1bgP<3_HXsDmuiy$Jjck~_sd1*`^lEWBVK&!;%m^{+CJel$31+UD*zaT zph*or1AgP&8Ti?Tbto-yq=Y|lxo2++?%A*zBi^yZG$*b{je|2FIIyFDp9N$n_8+?Y zCR6Z*5O9^1;?bXc4|TQiADl{b@9Lk9OAWuqU4b90zrhrIBEr(ejkx}*^AppYxSl7y z0r|av4DdlfRYj>O_{RGD##wl3^Fvs+bRj0fpXlV72!HXSd3f~UZ({bWI@3-hB0_1Y z1KGnb)LuXq@Ck(bANjp$_{Orn&W$Y_@5lGD2n)npp z3nB32Gdto=HvjH?L(-1IHGh>pC^Q3nqr3RWU#-X4XD%}Zf8sJ23}O4u-FWHm|3YhP zN7QZ1P~)z|{CP9+f%l(^<)@wqi$$4I`o?ni-WGiOp5H{zG;?o&GeU4+yA&4E44`b@ zD&t!b8Q~LvMaR#^i%gE3y+%#RnyRNsCUx-Oz;T|j8P#Pz{jG!0CVsSk?IGj z@!thb-Oq2Rufd(`uEu*#Uz`>EH~()x?s?z|cn0Dpd@$kLHv!)W9`d|eSdGA`-1+fh zmNGDlEBY(Flc%S50I$EXH|t{m&D{rb24A-1y&Zf6@C`9b82|>R8J~ww?d0j~?$5fx z*V7yS5$NfLFSj=!-xWMX_=cFJ6cjatbRNF$-hr&UhrNA+iSdDHgfCZ8OMoMVZ-^KtN+t$-JgxtX=Fp2H}xnB$cju^fnrj!7dQsdY7A_`|<(1%bck`aC= z9KrC&Xk5b63m+uc50GEO!lwv7CdCOdj35p^pu3OT+PgD4hB`X?bq5uYBluH0)uSbe zRe*j0jv9PJiW3BYi9mG2xQ%c4$rfC5<%K9Mae#`0>($U?Lc|;Yi2rPZ#{?h#=1^1?C4h+IRj$DGm@fCY8!x_<+p&KhFk) z9CaxU5O?M|e7TK)y!me6v`Mi;a3_lJlS|@9qcHvO4JkH|z=Sz^@&&%k3Lp;#gybwc zZi}0*FQ4ESY!#4u=|&JYb7#K5m*@zR``I`NB5u_$I~jBI$cIl5Q#zNUp@J#_3<+)p zm<{;>Uv4!}kOlw%f?EJ)Ow}e6zFZZo0RR(?0FvMr8-Y?4GlBwy4-^dm03f&my**r5 z@PVQM#3Z-^V#ag{g#jNZ8bE@GDIjJ+p}+@<1~5s)c+?1vefWSx18^|;^W>(IZUjos z;5(VTiKC?%z&xkFUsm4Ph!~H9I=y#(qjRk9s2ubZB+UR$Di>!qI=sQmA>~Og1&m8H zP4Ml$z>+GQarBPboTOJupFL^eCj*-GQ>vi6eJ&vY4gr1a)@1J;0SR|fR_;9uXR1?) w{AJ7DgU=kDqb#bZqKYc2sG^E0s;DgW|5Y=g%lS4jEC2ui07*qoM6N<$f{5&*2LJ#7 diff --git a/games/NXDoom/data/strife.ico b/games/NXDoom/data/strife.ico deleted file mode 100644 index 85ef389ec584dae829ec91c5ae28f299c8280ebb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44131 zcmeIb2|QKX8$WzBcN-`fG99xrOGP1)QVB)KJX8vmDf1jM4;eCrhARzJ;T~K935^34*R3SapU3z za5zhJ%)l^`-#ZP5BcpSytRwm0**M%zVH}Q|dnA7b-Pb9N!%0eh&ZB!{Rd6^ZrIGv+ zWgJe<8ixzns-ZgX54Jy0(epNKRMEn&VrdpuwUNUaRHuN^CY80@T^qVmJ>vNFyaKN$Hii{^`%|usrLO zB_Su{_X-?hrkhrC(w-PKr^`S^Y4*YwENfL5RBTip1#@%9q-!N!%y^W$aNfzQ%-ezo zc~3Ghed7Fdp5fzy+o~#7HEiXC4vXqQ(jUBUSjf-PBzSKzn^HU@*jY5=n#m0xrDiKbt0in-E}3>!$=rR-!apu1XsR-#`e;y3h*Q+x-B4P?i6dTT9un@% zeFMHZOP=!Z?&YKyo2Q+uS)IOR-y_x!%Uum(8F|`UZ58ki1}vFw z2IVAW4Hjz1D>t^ascPhxWX1l$w|WhQ99_j$h*z&Nq5BrSsY_F2wV+l=w{zX&KNkI= zx|pPu9V&6Tajn^Z>b4AyE7!djE!q8yH+wP9=19$g zft&lu4aS?#ONrwSG&I0snKx{?FOJ67Y_uK_?EC0kS7RN{cp^W$v){Syk?#8qO2(IO z6`X8ZaW#2k{+zulF6|QC)^vJ3YpRI~`KC2PbgREFX(s9R4dPlQeRGB!$-(QM43diC zdTVBFB)#IkDckdyo14i$;AGgGZG$JxN!;9le#%Rq-mIB1Re?@(PTH(AiF<36Ogrx^ zkH{8KWH{41HKXP&k^lbC<+DvykFCS!;L7ZYgxJ~g2M-40ITWhqun3h~4m&4UTJc04 z>OP}p%Uh{*XSxz!Daq``l&PYkt%G6NYaTXNo9=a4dUWN9>6Ta4T+vTY+7iH7SmT`V zlsTMzDsHeUoAVOUF!cUz1@Zfqjm8@cCB<=E3eIU|X$pkyWuiPg*K|s!evDw}U4hQK zb?nPm%L#}J%$nyrulik>c9;0=g<6+ytrW+Fvrju_YIIKSfzF3pdW7O@`MJ^hMsMmr zs@=~>5I;50u*)l*MUZ9Hifeftj;2m#BH8&}Y;S6otZOfmbu@Qq>aF7qKYc~s&5BDi zo06YE-5zI}Kfqup<07qarC7S!m^-r$43kJ%WtT2ZFJ;yx)OnY2lJmNXogLEJO3tc< zt7p_H_-NWZe7MW?z`hgRxyPxc)Cb$u!_^9M-*?7l>5)Z>6rnxa+^+2Co1KcC_CrF| zvFdx+mi6?^SO56o-H;(Sv|OA@p(x}YKh)emeS=2Yo;UC9*0m|7JtXRB8ttmc7W-tT zc}#J*j~whG5Vk+*#_~PhM2-g2B91iXTb}y@7#aHlss1i6E3V1B7hm(tz_I`B?8n-U z^Ymv{hu`llN@u^YN`2`)0{w%2>`wAp^3u*s zt?6BEPt*NtGTSfOmf7cZ+&s^|%*S_KC|9<@!0T+Ld}yrr$;HlkC>cnH1fSb z*V>9zQ^1aGus4F!>6u?hQT#G-+!;ok0TFKvUvG=lf*Wun2Ob zyLHWZIk78SJ@m?|mLK5U<;Bxg`*M2HnJd{ntqyyO?AzZbp6g{}eOu&5w>2m;(sY;A zE#Ya?N*@~StCx?|{PTvao}nP2ZbkbF>17pK{-xZPZ+$q``@|_T-IeTRSovXliAu6+wR-koK}{@6`EG}O4VR|3uD&0kF74(V5SXRu z%;|5JHtVjVn&-g%r=f;8=__H!2473>Q_Kl-)r-j>E#H|baVama#M9X;y;wVmLp7+~ z&3aes?Sd_;~3pAyj?2kRK*<^XN;MIV-UP(-kqowd&m!Q+(99`K#^L&?G zZFl^5Lz-#-D$~K1o$Us?cb^7sJ1xFFQVY_Xo8{$hQM2znQ(jqE{`{1XaD#@X1W_?6 z;@U2%fz1YuV|!XuT5FPh`bws^Irh&qj417%vO{#n&Z)%~QmpJa=CIrKxSSnxOK14r zvyfbg6J_?lL}zx1HGCc}?4H>^-2dj*Ki;lpnb&J@@Q-)#7d>h&vvu4rv#qIc)mznz1p+2sk=EfaxJNRPHob$eLFs} zx$Ndvo6U}!?!EF_`Sa(M=lchF<>i+*#gM{^bE~&VG|pe;U=^99rY0)C6*9>KR{C_3b&9bfAKwUXoXJqR`DY%GF6+iqU?NL}Sg}?lf6P z{dB&&j^W}h1_lJG`lk8wP6w|JZPpHxSI`3Y{s+f}+8oLvxmIRcgl9OSO6I;Z>RjU$ zf5>o--iHV7$*1_{%zd!3?eX683+xxsACu}NzS)` z6u!N7cjdNE2R27{L@tO}op5cn3U~YZa(8iF?vr!6lqLO%jqdwz@2p#J{gYn%N20CB z)n|JNsw$5R_;?3*M_qfi%W+MZT2AzA>IQ~X#b?{D&X{KGx+d_t+2X55-yG!kIsa+l zHcPeM-a{nPJ-4IPrYeuTTdyA9U~h3|Ba853D0lCvsk1-N3-Srz|mD zUhi1KGqwyP4w=K98|+^!xyUZ@0{yZ^GOkmL%gCytSWL^XkUbFRsyz6%j2gd9L#4r3 z>HI2Ja%yMyIu%xScD|%7F?Pm+f`X3>#A0uLlEt%fgJ3!$7gq`GBp2f(^a-Qc@lx-lQo;0 zn@?3J_TMYB=WzG%NJ>oP=F&UpE?&2K1M?zwNRycfZ5$7lay z+XRXm}YLh5aCAo(W@4Gq;7xH;xmO(}LVMwzXfPsCXqI1m{a7})3X0>{y2=OBdZ zoiB5p&Tet=EJjAg^`xmI~(<%UtD^qz-V28NoN^j=mYFKd3C@9R!oIBRa+ z`}gk~U82xEnB})`WmO2HkT^NENOwQt(7f|=l$Nd+Wj3rM&M>`#*t`7d_3grUUNP4d z@DX%x&ro8Dh*3PApP$mzm@C6SjZMHuNjU!G`Sa&_yjCbveK!Ot=?Rzi-wuc`nz0gB zx%VoC4i#$TRIAe&!OOJX z*X~soO<9R6FRE#4YfBdNDUJ_N%6U#ecP|VnVG8u^ys3UcO@)<{v+zB`+pey*ON~o2{xpW(SoY!DYn)>FW>_^vvj9#NTYiDiQvL$P^_)#K;&h=~#*>FnbRL$fe!D-&rT z4-LuMz4DERWm4S%+`P)GQ%h}Yr}yac%?dhV8IqvYReJVzXGxlyv>SzpY@1QiF*|P5RKIuY>Cp&}> z2+vo%&=An=6j<(CRg#gpX#>yV-OoLHbG78fjy_|n$*?jw_%2T0Aog)JV|CjfnJtg^ znzHn;Xc7bhtxneLRk13m7|2My(;N`}P+&*7(*h@stHP;~=a&~LtH0GMtc|MDFu$HV zAUdeFJCk1I>9)?N7J;oF5H5ryZKI?f9b2Ob>knlviok z-#ormb^{mpKBHZh8(vC$RQZ$Jyw>eTWux!`y<}bci`hd@gxjuF%2%};+NO!98(y>Q zc&eRA*u7$=jrN(G(}_ne7hEXtdQN!yF0-IeSCOgL$VXjGU;WK~p>T&g#hj-NY!75n z4p-Ra=qMgGv&1d3y+F~WvJJBaxY6Ns zy+wS6ljq(oz~vAPNqQG5IPTBEiNGIyJ4otZPM)if967lnA^TLNj;_J!bJvOe8VLk> zm^T+EQWT%AGbA&scS>=kZL6u8`e8E@+z!%tYjHy7uf|$$ z9oIDOlZoo8vWl-ATDBjv$+a9z7zlroPUP7_WM`eyHXV1cfU=74TIkeF*OohLPcN&e z)O@p|%9M0g{W)QgBFU*xliE-%0xc2;cowA_COdn|R;m_VPl_sV3r{189Jyxf-Mg^3 z0Qc66G+lP}&2%4G4-v=buA4qQsxV#E6KWMmzAG*6)9b$o-q-f#UA#=poh?1}_|(?) z`=34(SLjJDm)o&ae`Y0qi^r#3p>>4iRXS5Oc&0Uo7WpkkFYDlON}1pQ(M70-yLtV} za0;*TLq-$UkcEy{=6+&QKA!V7BcZC2u;u<7-}$lddQR?#4>wYJ7us@@{MYPZ;dEGK zZc(~N&1agbPLb{oQcAE}8QsBf%7;E_3Bn^{*sQd4Q^F07a80*CZ_-faHN=l;ZPS%h z%OyNJ->bQL4&Iz6rWjb1k@NNj$CmqpgK6T|<4t6azayq3;1J&eOsMz>j+UA*iG~lv zu)XIp<~z^y%r-C)@sURDT3H+d1L>&dZ*}=vs_P6szQOG_oO0``hPU*vj3iE36k_nN ztIB#xdpXy&NbIAVmaX<&{b5y*?=xMhrG*JDV7oU1*J_tJPm;Emw-<-=)Xj@ERf!F)J*v1v^HyeJV&CGo_Vye(L>cDZDck`>zB_kW4wTkC z-cHJX$JyLhC$FX_YG}mNr(zdRD0o1;j4>-I^ZgZ@=9e-=f#z zGjy!i+@Vy0oiT@)&4Os&MI<-8ep{b*y0WOyCb_H0F|akLwuQcXxi;0~zYxgJMSNoIifldasgA|3q_tKFh`&y!lC z=J?`P^-OV1Dz2JQaF5r@ftxxzr|43v?iJu>9iea^OKy1fDSOD`qKiIp>Jm1&hV<~g z^YQoX2M=?E?2wGoQn!i6FNj;{IZyk_niTg#3^_#8*{EFwx2OihKJizNH&v0&U)1W* zGV^U{D;uv5Z-?XH5J!+{9N&Va56l#ZGkrR2mInC7La1FKkzJM9F`B!-%q$X-)j$L0 zZZxn4D0wqj9@T1*&wQsk_&{vEtkjK=&Kakl@hcYV6sj3DrMKNzd4IV@Q^j+>Y5MDK zb_f2GRX(+K8%co_uWBLul&0PJQ}uYUKKU{i$8!X~;54(gm|Vd?qmavMlEyvjGkF)h zxj(d}YzVnQO-99dnYipsjw-NVA-$Fg^qj~p!!9{4K6Y)_;oi(~Vs+_3px#D9z z^-|z8!r=36i`f}Yw}~?Y^BdhA3ff!m9=zx1)QZaKR*Y+N@i9M2wl%1$vsm+WnM14Cx+oM#(EeI5n%%$BxNH`UUaH&?f| zXbWvLG)4&N8FakWTIu`iihA#GL+9Dl7Ehf^2Agw5JXaq!qEZ-d4=lf8WemAfb-jyA zaI-=vvr3xwrFd6oyLDK|qz~7KpJqA5u0cKSSj}R|@`*^8|1_3RJQo{TcomgQ<(n)> zRrFQ0$5KOkD}tOqwvf8#3HjXe3Cymrojs^aHArN^-c!JXkmZkFN|Qv}UWIAydtIft zn7eru`(~^owlO`1-C{ylf!pA;vvJ*}h{oT0R_g}%N~W^uCPpn4|f8nVB-=ex2(QOneMd_Iq& z`punB2~jYpTXK$nTOTdoX=6#0-HIHwpYk9$B`#m2+_7~HFHkHE4royTY7Hj z-9vxJUlsRmAIYEb&q0I4>W$uR^N?fxE;^xk)U1YRe(tLfZ-G)p4B>R@w3}|C65BZyE|7*LB<#JnxLlR4W}4ft}8{tjc;@%{slo% zvP#a>;pP$pRz=cO(t@?VTXY9|v)c!|rHbSm|#z2VJSy)oA3N+#XO%nzuDf+7p4E?z42&&e_f2?UNVv1>sDVJVH;6IK(Lz* zHBC-lpGV%k4_B=r4r#w<-^kdeN$t2U;aS}-S4N3E;`7{Q=PWe7&aA+{;Cx&8u`ye& ztn^6wz1JIs22*8>cJ;JvInzpin#8u| zqk2@$;@O21!2?wPv)FA314TY|Aq0}p3gRURqgGT>@k0LuGj^K+chZBliJSGQyvpcIuWh7*P}n? zL$mg7!XE)!ymy=ZfyROyo>mFlPPN&#`Fv%WFH>6gyR^Lxy=LmYl=1)uPi#;_y~ZTs zG@5Gm*^#R7p9BMQi32Mk}I z77;IKj{oqSu)TmR`KLwK5mfnyGvdz7%;-J}b{}6=^=2PF{!<^G$#Je3?%ZbL6+88+ ziT46mVu79gYER<%(7wGhEN2vNh$}j}-^scmPRsL^x)gOVz4V6r`6pT=|Nb6)-H8}N zIUR1xT;B*`#RStQ5&6bzKHlOVXkxQM{ikt2qs3+F9p0itm3_NVOYn^^I;qfhhfH8? zpK2T0d^2OygE;)FPqJI?2dR3mlfliMi&hkMXWrd1H1cl0V9%kt!kBuztHLo^vcmR_ z>~S|bv({|GC#f=dluCt~-C>P$Npxv9HoCUxRd!EF^p7txQMWDRyQA*$;?0v}fg)U{ z(DK(Ygo0_b<%CG>pT4Hl8ylars=m4(And(#XR9qeMv_l0)wZzI{J7o<9dA13%aXB2 zAC=oiO_iK2;?qQBvTN4JJWHIJtRa3>gL5CUJ6X=4Ju=fn=cDwLu%a8Kse+ zjYOZbK6O^ND6{U1o!wfF|7696`sNN&-6QZkO(M=Y?nGj26f1ITL^3KWLw&e<_rWKv zEX5KBERht@OF`1-lq`x!zhcUPTNHsTO4ptHSeXq_v2E!}88z<(8#gHP7A@;NHu8Ke zRYHA^_MFEDNpxD5?8=Mwr7p&LIAT#FII_NLE26wEa9KL^50Ho??~< zX1Tm{1NOinFz2dU8?Rjfr)J^flOs+d0g$)5?t%0>n9XWbr!!MSiPLvz`{Pk(!=%I7$)s?p|eY{~pI= z)pSNKx0PiP`J6AEWGlt$^3;#On?KuJiejqpiR*e>qi%d4DhMwpid-_Cn!GN!MNw|P z52d!1sF$7#Nmth3sh)@Fy~OX-S5y&dhU^_#}9T4=(rZ zp4GOW4o!c)(7(TY*E8>XX_-Nu)Gik0RaeVe@%TuGDwFom)`8`euAN*yq@1!CJ>mT4 z#5o^I*JaE!KVmv}3$Awxj&2(hy;@i8{^dHQ z^F!|%8PhIecRpVr_Zd&(9o}PXwUqZUZRJ)E7&BLd-DusNtL#np($V8(RZfMi#SAo* z(Ct5p_uF^To~1*6bxW_G#2`m~+oRY+pR}liw*{8wmo_Wwn>e3uDe@93aQ7K(k@=*g zv~DW*G@}0_!g{pUVd);sF?oi@hf{y7ab-RBN6-aIS4n{_9TID%q}<$lhEjVcaFh2m z?_Ql8TSwW}+=Lm@q5W0#IXkbMR191|BoyLb+Nf z944Qs|45%gsm+d9N|S%k^inO>efX$PkL94I?ID$`PxrRcqwa_c*x+4mdXk(`cavR< z%Cg_Tx`1hDVMb|AW%iaA)G{QF9iiMF9(chnLhZ0URSpfEuO(hi8LrUU`L4%CKM+eJR&W1}@Un`FMxLX`#d$K@I{n ztG7_|FZ$8Hm@emDrKi59+_uAs4k;Lxddv(|p&kbpicy@paVSt8h$iiOXJwuM*Ns1< zCA3Bn=X5UcK3^eGdyNh2dko9aph&ij$ng>JeC@#%mA2$qibMc$K;U)S)KD3YMe`4w z+VbaPpH%)LKRngq}1_csDy$yhzKpR2CBrs_^n}HH0tb3*YIcdmz{Cdn`dw51vlBN9ax%h;>oXxqANc z+Iukv1^cm}6&&(eQ3F-3NU*~>a#G~e452~Dp^)aEe@-1HP$ zf*R5(YZd!i^-3#>JX=%z(8RlzICJ=*5K~Cr&Q|)PH)az>*7-2*Gs8XFMx1$22wQXM z)$M96a=@gFIK@0ds_!m&h|wppOB972Wv-o=i>L%GB&-XtkTq?lNT z1gx72LshouldN(mGY-%t4y-T>s=_~Fnz>a}Z2BEE&WaWJk+JnZ(wp3C^4npOvrjjR z(n)QR(e#$IXEF0H$6s~2$8>2gRSfBzGAT1Gk(|JgLx+~7F87v(&yH)zqM%ZIlQ6vw zJ)4%)diitc`Dj8h4{mB1Zsl>xZFON*#t&EHi|X6iTFa1f16LnSWLd|ZrnqrQXS`-E zF~#gmaOib4-b-Vm*dRt zR^eZ0mU44d6g|LHY}oSPFq%7Jm&`#+vf8URvkO-xu9`J#10r6)!gqBOeC(sS{jWN?bd6nRLX#__e%A6O`bRw+A35efJ$ zb8-Hy^xb8rllYolBX_&fmU#x66^nG$F9lc9&rSZUBHBUf ze74AmX@QV!T0CJcq76-ETeU?`25%oWDXuKCm%?<6=by#l85w$8WF%*y7J(MUp)1xK z2X^OI~5|j`evsP18^@~%=&K@hU zM>S0kpMykeR8sco;HjaPugtS$AW56tTdEaaoQGpg`9!o`CjvLELuD7a%v^bhGAmsC z)lSyZ>BWwFD80JW(x)v`0x#W;Ou)aoF}t1Pu(=UV-j1Jqu_8(Nks+zhIQD$;a~v^B zLim>RV=tk@uP+vbJ$#eN@_3KSy_5L|8t@*QmLG~QqFb?Q_eqzNly@AIzHRMA-tWtv zq?byD&%ycH$|q3CT$~~E`)_2wc&x|z+U-pV8xP9)>k3>GH&`1>Ww zyw?vQ2W8_aCAU*+>IC0dUkQ$zA1>@8UAyo^X-nu~gX#-T&ytwPPZOjxg$bYN+^-d7 z^VJ$8T=1-o3psr*ZL6)6aC-jZo971x`kq-0*KIjbaF0W~OppTP9()qinZ10K{!>RK z%$MoiUaBHzgT@nbq^JmTx58~&uc2~L+3e5~bd3DBklWXYvljZn;gG{u&eV}a%a8fT zyz3GR`>xz1ww<{ti%oM=SWHkd$W39=&rMmRi;`Au(j5IuEMp!U&2m}iMe}6>a32TY zOa@?&17Ha!15@A-F#1t}!4rT{J1=_lfiVa8eYr6L7XU`fh#LU5@LpgI9vCfyNjEoU z%wwZj9=qI_C078jGPpg8fWs^i*wK1}&Hwdi87z7~c-|p5M&t$nRtA?*1mNv10NXM( zV3*l8N(YO<)!5Mr#~koE<;I8=0emR~qk}`k71)I3fg`GCqzr@W<37K{EjLE;9spK` z)Y%qTX5H1D>9d3p|Lh5reP-p64{4u$q!xb}?y{Emd;4FoH7b{%t6ql>T|ulz0lp=4P9Mb@Z`x8xN+kKoH%g;!otG9&E5`d zJdz8?JT{u;RtT`;k#_`?uXCldjm@Ci8MKB4~e3H8BGXe{^y%z-HR ze1t_FA7PliEFN3VczJGz!eVR;8CwTO>>zC{Ssd2?O&yDN{Dblj78VO#8W}IY z)PYax2aY2>z!CZJyLB)b{CfF3&V|KGuK|3i1Ap)`uy1hz_RR-@W0O6wn7!FpGUoW5Ev#?nFHo(_)(0G+a zMe|QMuq{zQ}R@PgP6^?hV` z+WsCY9@j!{eKVZ7Qw3=`xp3svIj{;p1~!Kx;81V`So)^F99zzK`Gox1C&=*zK7RZN zFJHa{Og4D^`ZYXy^oS-GAjcy}O-+R(M~;BEw>S77vf*q0< z_JYKE8xT@H2t2EH!cwI@uw5^K_l#HGM4kr#+#n7=AqguRlf$@CQbK7|4nqq-b0ptk>Hmhm#k($PaU3jdW_K)Y zWp^lTWwk}=Kxr$>K9sCWTbZp&TbV3T+FjbZ$fC5B(fnR3qgiR|LX*B!H*0dobYuZKrWZJrRp%2j3w)AcQ z3wGRn@w@foT}uf3=SJ4QcIiKaxu{0zM(AK}~kwlt2Hy#a4CjX*-?-ByG_8&_F_pv^j z{K9#p`=>N8ncewq{`2~j5SCsa(La2l0q>X%>?^keo46`X7GxJ)3mozWz;1c&yL@0a z`+fX;ekBB&JpF}+Y$~uxZ3Q-w^}wOD3(=u9BJ=Vu19o09q+2=h4Gk<7#jk$1{qY?t zA&3@ymbbsq5O524BOU{-U!0}_r(xtM4IGl|VQhQ&H}wkymJl%A%QrN9)h2mD9|N0^ z+z1T<%aLBE>+dw|{(by{hf4?&cSiI--=zVq3-IRgXlxmPNnK|E0kt z1Z=(VJsLz}9)ggj{m8ljwFis_4#TK#`UUIW->+XRyo9i_Vq`t>g$D85epv5(1e7%l zVZ}Nf5R%oT(ZH^}2e@OKf$Q_y;tL-ZTm63hQjsMDO!p=86%E_NPk`|*OPZ|yg$4lw zf8dEDpmoRF5xv?M8e)22@xI@G|0|+P2r7?9^lumqQYBPy@^S+k+kG?|G>ol4BH$YE zA8SEtpO(*SpTB6p9~%O8+u!g1t71wB*m~#-4YCzf@C)$)H+Kgb4XdJVfJn-7P|`*6 zu0;^=h29^bA?Y3PoEV_Zo1FH)U%x_p2|=rIWWDr-2K&<&;c%b}jRtN1qp;5Z)L-vH z)e!g+-T?pUfsye6&E1?1zhD2_#1aCgzxY@NGS%N&Hx_5N+X z;Bxx?`qw9y5X_M7b1V&5n^Y8-7m%)Covi3cgKJ48&BKwK9b;4*8s$K0YrBIq`c{av=`kFRr?<7YlyI?tP>pa z>%rm5LomyF2&$P+K_%@zY&&`bOcU~8i_gV(zgz#sr_DXs8nL~-9f{OH(;;JeCSFc`$bLY;%v17-;$HxakLqoyR(h@?0gTOm5cHnpGKU4mq6RY>b zhYz%b)!Wn40~87c>gwvCqM`!w^73f)pFDXIl9Q7mK0Y225)#1J*cif`9l-lgOz-d3 zFR;e@j?kLDAdK|iE7a^jdb2HvuG73SDFDI(vjm= zngFx7J}eg7fv&m!vVLbQoh(vLMcfGXgAI)>EjfaIIdq(pdiqWu0Z2xHf|K|F6 zlme<1?H?lj;5881b_uQ7T|wbMIf&@xjpSuKLC*RPh#BP5@@%UPfsADVNE+Ru<=N#9 zW4x&RReq1XPho#yC9je@;N_ixYqb+_$RHic3I|}7wgYBKTUaE%f84|5i)4r8_FVn*=m( z9KkCmoy04|E&J8_CgVPAe4*lSK9iBKx-mTkW-Bs7X;e?akHay}8A<5$e}Dg%ae&h% zF9#ppO2x-?P`QqDP&uPIs2mX;RQ52GLOZBz!5!4ahfxabptAaRP+9yssLb9SR3;5@#_cyRP83_XL+Xbxy$>(4 zA^449n{^K-y#eG9xl z>xA3^=v`6TSwA#U^y9DPo6OP!x8=GN9>%xieYgi ziDoy%d_#T-gXP50&l6csrs>Uo5d(V+>9bAp)30OLJ8|^$M%9xAvp?(Ieue@0)<;!nq@U1Y_R=kMm_<6CKfa(d_X;t7*DFHhyWEe*sMoDsKerKJ`EB(~BmM ze!+x#GN!lv2E#?<6R{lWjzy8~7}@%1dPB^o;CmQE6@lHKFfN8gcC{16f5F6hvS|K@ z-uG`9vMIp3#+at><5WZbSRvKG8~YmYuKCC(PxssRu*GfMwltyiCnNfipU8JHWORW* zB7tV#7x-#y<%w)U{vGmv$FOwOxZ~0y`zI5|f1#9mGEJW|9)_>_^w$_TR_T4ymN>%N zzKem$VdCgtl3Gv3{7?Q7hBH*)Sgk+eWAmjy2(CbL!~5^f56q4eNB`2ada}gb5kH+@ z!hqQU_8|YGF@2g{&Hy;anIBjVKAy1lBYL8qOtTyO48vtAEQzcHJ~i7BJHnW8iPI`$ z#GddS46IHQN590Wdh+t}&vu7#Ff2=}gViSPG#dow+r+zE<8K%^N^XFLpRqp!nO0}D{qGN$=vVRn?SF|f<%0Y0pjX3M~QwZ4a8vFoD= zqkrX@dNQWt{vHOE6BRU{FMYFJG`;^f7*Jc{jjTgH&Le(cn4k0aFf4YPIR39bS5L-O+t3Dm^gZmo8 zvb$vP@;*rOiNow3UofayIDpuZ3J^$Z8L>sBAY0Tp7`PLOz@3id5Wk6|U+H2!8M9lB z#UN8gruo}_jltCB0Eng3g3yT;SmBWY3Yz91ZW#gmQIEdCz;mnzcu!GjIsp#jr)_$9-8( za|BEr{i>Ji$(Rq~_b?ddK8C0WkH29s@D2wx-z3;>Y5Vs+t)dHjM_&NnaU?ULIqqv& zgY)pj(XV!`o{ZVt#>24h!p(0meBB=~Ti};*Nf7l3A>@nvWi9#z16T0G(XWwPPsV&S ze}qA+unFu=WP(d{Bsc^GfsLO(>~!-5Lq|{0ws8fu-A=IDH3gPlMRW9+bsUBPA2M`*zg!jM+*s+cS3V-Me>CSy>6CrKRxV#S3`$>>2GiH#Zk9U%m{OAM=?r zXJ~d{KR-WkadCl&hzQuddp86h4up`95C{zlg^8gahpR*MWAtLS>Myo)>=?6IWAtNx zt*x!2^ke?lH*emA>({T-=s$h>G-PIG(&+d1_Xo7oB^*6^6ws!JV7Gf0gd+?SN&l0! z?qQ5ZDwRsZfcc9zHa7l^e$0;?<9%&yEff_M(fr51(4Uc!LGuMjOiYBNq$Eg5Ng1X8 zz)o|Bb9ID>!=V$_e#DfWKdj#F0&;rpu*Sd>wpj&(=H4J$T5swLt90E#cDoy_)OH1B zBX3w|>H0l&uOZ_Z;p5Yo>7=KO#3kN@^C-u%b^k^V9n z?T1Cux_5;|J}A4?(fmL#-w~m$*{}fhQAvYrSnuBW)%hG0N4p!AYMp?MJ}*bl3vRsx zOvt~3U-by69eO=_9xID^nIq=g@p1eX@b9khD7cciobyMykQ;>@^@b8 z2%+dlrwgo7XuQ-r``3B&9D{&9!e$PV`dNQJFKC2(nvDAX9hKuht?E|wL0Byq z1lAt{{&l{WgemehBLa{ioNYsWl1~W@L zH;+%jzq_L5-x98Sq_a;u@?D>1P;0MRz?%;ny$Rha9xpoAI5xbKvwhYkV^!0#Z0CbF zV#bvOVg2%^Ur9@JiU@q0GFv&7V%oUYM7aDrD*t=>|0D-6c?^X$;YNR7;czpt{C~d_ z!-p~a#{9IDQ1V4-)K3eYxQliVz|wzz|8d}d!2xdb%Zi-l*Yr6}zmts6xvvr%I%d=V zPSQo^#wP7+`YdD9R&?&G#JcUW;{O7}@0P*oUeU>$F%oY$>UWlobXBQe`JN>q-!m-! z@QeRhEC3dV_{9f}H3G#Wh9N(+P?UlJ`JxR27MD2ci{^{@qoKIO&;Do(9>^EX4Pd@2 zO3vumprYe<>HoLS@tz`$=%@czJow^^7l`oxDi0h<6Q&pW8GrcC3MgQ@x%OG9(YY6{_J5|?A$-*!O@XeaE>VChl<66{~I27Paggymk@sBTZP4X z|0)l-68lGDeq)diE9S@gZ+YNDnY8hL>E+>3TjQ_r;4dH8uKyhmCKLbFVPtRp9Pj^= zcEFSRi5Bbpmv7GhhzGtyllK0FuOa-`k>Bl4c);yd3>@mtz`n*D*cH&8I>^_GUCt0C zedNQp1L?PPfnC`W*mpz$yYKUVHXis*p8O}AJ3QjE`vV^Ec;2M#zwno@-;|#OkN5NbZ9khA{3j8A-Y{*iOq$Q{I6PoqZ8YM)jO{rv z>hJgy9`J|&`}Uw;YX|;=lh*!4ZX*0Qzw&z?%Y$43qU{~G$eI5uQf9A*!KjuMD|D@p;yM^!< zA;0Zk;lU4NB(B}5X$KO>?^;^V5yTa=XnP@zl@CUFAZLWIzx~RWe;ghl zIdP);_s_~*RWVH4Yw1^bAer?J*4iAV?E@vZaR)69V_Y6cX#oCkHQ?jXzO#ReXZQ{e zCK12<{b984?8tsoKjMMxnHQk_*;jg#w#koqfMNG6La`hp`$GMc2Wao&pS`Dvx~}wa zm=-hfBOa`{-VNrq4z&HR^h|cr{Kd!Rfub4k1Xg~I1;OzD0uQ1-Od9@mkA`9Gqmj6g z@pzycdzKbIvdh})hddBA4gkK`=fIcL_Ejv&Pk4alMXsdDTmP#*9;WRz_9GrR`g((d zlkK=XP}*(@V!ogEL_={X*uH4L#DlnQWM@P3XUgR1|297zhK(rh2HWfGdpuZiXApdR zooIWXeUAsKR^G5QsU8H$jhX;wBD4vH* z+pCUdb4{B({M+h>LGyFm&v-ltI1>C_9w>)rgV3KS*5qUhtPH*mUyq5)RSjUNWejaR z;7$6A2Rvw>KHd!S-)*kPCl9|)!!T{Hy&v&l|JiF05$66454InQgQXeGG#;!9zVh99 zK~!VkXglCZc?ae;rp-jjH$N-a^z|?pe~#Pw84uKNw}Vew@;~B%qMkJ@$sYW%jpg*@;kRfWrtLNP zt31GDq>V-IKqu!u=w}wg_CJeY+wnrsNG*WP$u~h2?E$GAn+Hl!*Fioq55&)n?2q|F z`vUU8_}P1!sOy%k!?3e$WWUXS!UJp{&L6E8eyUIWT9<}=FeVD$&&suWJ4}l?n^Ybk zAB>;TIZ@a5cMOB|=eWB`;{o!)m?(TdE7$J*FdRVpyiO_)kPpVs=$xqQFZ%|d`6K!! zNzX?hboIdV_dRfb0HCTLpt293{1f`^?1lR;o1v=VC6qmDggZ6QAg}f%oNIUor=B#! zvHMLBUs4MxH%sBcPH`oZa79GC<)fwABg6a`)( z(QqjA2pkTJnKb-Zyd4&6*U`~IiyQnBJ4kayM*pz*$5*djL4SWg)YR0B#z114*8=n%NMxq*|D6GTTx)As50_VR@A@NimO z|lw$Zz4Gq9+-(H9c@Po;I{}?Xp590yW-m(7B z)YSA{{3H^I7Eg=4cZ?5(g@xb6pO%(Ji$}%YIkrbNmd4`uwAlm69!`)D6fkM+Uk>dt zy>Vv%Y_SQWrERv6VC{bltPZ8XUcVIdt*2x#af^pd)?u&_CDpy5u--Bl)Y1L=2cuz! zLlj#3gu}Ldp|BQxqjH6wCoI!(2T2s?D!$DHC?E{PweQvAUTg z?Lk<-j20{S4Q(i%mr-~(x?WC;L;K!!Y_D$N9c93b;@ZA{ydwsI; zvn)q(hX@}Q|NK4rnZ#{r*Rhzr?_FQGbSLflVi~{hUZ>~VLA%Z&AO79z|KXq9_W$4e z|F8Z3|F!?mL*qZ+`Z&-CYyn}NYapP0b~JITVBb1aN4}ljwCiH}H%G5w_wlHv!aVM+ zC}!Lm)Y0=&rp14|&bR3}%;(cVan}Z*=Kltk?=1b>b^gt#P`oz!&ch_mfAhFCKyYI; z=*7GTDYG&VHMldHgtq3uJiG>Qu5yPRvF~B|?#j_?*nLa3=fZs6?Fj#F+ViqD)qlG# ztaAev2p9nax<@DK9mv}~`TKRf0yMXx?`TXSevTD?eYfL#bKC!kbMtw&Pn!Ir6G4EL z#wS5iHxb0O6F^MsD2QkxyM{(AEK!RA!A;R}`#4(nrvb?*`rIPSB2c2b#fc zuqB`w?G5o7)_XL;TIWVU-{64N`)gsP)f153{Rkw@AAqP~B~7lu#?F6|mg?L=`>x~w z_xe=iM~=R+EEk+VQTTqP+>P!p#n*eimRslbYL$|6qwG4@H!C){zLr+DYh0#eS1YMt zTQ9D(_nD}i%_9+6>jz7hTU7~3npF#k8C3E9P7={6tT(FR2kv_M<50U8uZ|7we(%^xYyB1O`oL7KP);wCbhv`t&bjuWf4 z!&-hxsQ=&B9=z9 zNaL8Yl@2^D7FzpSi}+eww$f-V+E>~S0ui(hT+iRm|4|8Q+1Ga9E2rXnjvI*WiFRBc z%d1;Qp8Ub7SGMzd)?A;d6CeBIkM5nCNWPF7&FmE|1c63$_|aM*&}gj@EoiOLLCdjd zJ2a8TacN1fk)U}@v^3KP;Rj?}{!fii@iaAGQ}uKs98mRzsviKnv?Dq8@RR@fT7FwD z=qgzzP6{xQO?)?<9o@U_Csqn&87=r$sp9K{SL)0EWa|9J3?P%u+-2(A@xdRe_LpEWLn7RgI25{&{C;93#FPl1jEL0CP zua{hQjV6p0O2(>yXMS|j)Tv{q#hP!-0F0FYbA|Fs_`SF9;+H=3Hr%?)k;60iL9lK* zE%566GS8h`TG_X6YK-6e_&e{$@a>F3KH|210x;J^)&95}cifZGq=hF&VJ z`v2O=zg779k;{PDMyatXp!E*bTAtW?b>pWOpyp|6EssrUxw;Z|H<4aMSgbYuK}$=O zmCNy}^=qaFSg3j{;Y!UVX!w`BYWSXaEDQp#coIh6XU;8XCZWYiIxiu2>jAtM7aR59+4UcjH#qEs47F-(8(Z z;x^}KeZ|56&X>Xg7!f#M+}vPHyYv8OyGVbbXZ6Zz4)m$#S*GSo3H)K;JEXC=iYmWxD)AUG!9T|t2h1!ZSbfU4O z&5hXzcO`88ZAT-jfif9g?cHES6ysrj7eibNf0g?(HcRK7~2U}GTfHNf)X7x;tDzl z2>d#g{OLxVMjp{36=~*ar*b%B(~SixjRhwnE8#$gZGy^`vv`#fS_`(5z_OFrDv4z$ zC|4ck7ZvIB2+V$COYir3GFAnMY+U}kuFLZBGRb6;d_Lc}`FiEMHN0of9;T+IR;3Su z0MGMQK4;IKC7aDMH#bMUUSE~IHBSg9mUy0r@B6F1qp(s6%d+r&pOKM~w$~JWzxLW| z&Hy~mV_~5= zV;3Ns%`!bb-Em$b!nt$jSYB@4;K&GU+wM5OL?XfH=;*3_#bS}ArKNRJtS`%g(bN?z z)}Q{i9g39!w1Xcho6WLw=gv*%B_hnu&bEC*ZQEvgdb%Scux*=kI^Fiz;^HEUi;J7i z%d!+Za&;WbyLRL)R%{Hw_k9)@7u&**l*{GVwQJWk^AZtGojOIaxc>Zp+qRjUoZOTV zSe8X9)xMz`X<=c3LZNWYylmUzx}6CUPCT4Nu`mGN_gPw6+7N!ETrS7%-MiO4E+Wj# z%xtPywk(TWE{A2Ue;briBoc{h<^^!&$`!6$xw7tY+qSv!`bm<>__&IV8-VZo6pO`8 z!H+aPKF*#!d)Dk15l){z-BF!v+cslkW9u40r)`D#`FZmBwM+dS$L6;EH<3wi&X~4K zMhzec0+yGTJAxl+Vq${puDfn!yBqkCEX!hKWCYc+LPJDWZFi!%xjE+M=2o_C+vcvj z?qX!5eH+50j5&gWAfQ|>cLhJv#KZ(5LJ$PZ&dzRF=U+>fWs%8bs8*{h{rFyV>Cz>F zAi%OL?!5C(GMP-zd2WS_8Gx?*I~mJCRKugE1CY?mhX^7Pc99BKXdGya`$pj~-lPaM ze~g66Ffkr^2Q@kfny-jyY-cOq#lmel*7#OFVhcLy<2epRcLzbD;m~P)&5Sf(S(8i^ z$xJP@yt=00{0W+IL|$ddo1(5SB04}>4q&0Mu#^MJLMa3nJV@*fuRN8y|hu z_NwEJuwK2LZhTh7ZI_RG)plz>Xs|RW&EB+xZsq8Sjl$6b9ECR(Cm$Z%ApS$W4<8GKw8~AJD(kJ+hgPVzONaofCMn(D%elu)91`R+rZpIM)U>m>?J{YtB zvu%JO{APSZGFJj<0o4ZhAi^I=188jn3_AS5>;>qS8#IJ(N`?(UZ8`kQs&pT-?Jmv-fbZINk!$Zvghgw~Gf2mu+B$F5EyNfeJ4pP>ndC0}vgBHN|C% zZ_a1Ayb$o~50yekZm%VUA;qT(=o9>!>+safyE%GgZxi|&_^nTQGfumGdQ}PGx0D<{ z|9w2oM-MEqXNL-3_10@OVL0D-gl6bm}N zY50x`m>SgpEA@Zfg+j?^a?IX*?_e;ifZm^cM00H629~O+O~X&%^6<^a*T4@qgH6NN zLBL}NYNVVde1$?G)a$TV3TFm2^N$~VFkS-C6MRHCn%~<|oj;jbCZ&Qk@DWx!el~zV zHRAF3J$3HAS+9XF5-zx`*ELHh#z(C6dj|vU2)f!2&;@)%b7EmZ9f zQ-QrM{OJ*wNA9li_FH^xwf4!6;3I-kg6j%J5po%8ZSP>{2)e2b&;@+gw+89iVxY)H)j{Kwrs0F}5`dmY^}@~0`}sxJ;wvxQ%rD+^hF#fO zOGzNyK3(JXhiX^V&)vgUA}9gR6H4WP?1+mICGspbz8uY1_rY?b^dvtqWiO$rN9Gev0Lq zbxruK;ZEU)=@hP~DObbvac~3~UKh|kd?dW-w~o*E?B0F(T#`RKw1Xq(8w)qrfxljB zf3xtTYxaDhT-AtP9mj-XU;y305A%RGPhIYdZ@*X;{`Lo>eC^pZRhKP;AI6u^2x{RH zxB)H!dV`M$@4W6jX}j8&fgK5aessd(3r{8a>3Owf@T2aaA80By2}=S)ikB<6i#dGh zM8F4co$U+!XkTGD;7i|yZ~jn+lb5#uew2qF2vygd1;n5V=pKH!EqrkQId0pr&=>g8 zJVEXI9C|U}&;P|`xw9Za$ZmHqwRlqPE)S;5B>l*0=Eu+ zYkbFo2k!9ri%(Vg%wsOQa^1rhV6h@R^F(mUJnwe|Ux4d#;Hci$^WaTg&!Vm4(uGB33&0O$KCsEo_HX^ zTW_}3&0lNy=jVOC^gX|0_yRn*zd!IzdIHTZ4n?gCXEX4ZYw+B$_M>_)&j$SN-v=Dn zXY;8C91h+T)^>g%%v{v`-&x^XFZi4C??n`F^K6@r$dQ4Gqg;K2@=+5Ay;J4o0yyjluDNlYy@1wm2k;R{IdJf1bxruI0QLy~kvGAo-$CEt zn{ETd%MsK8{3!k>-k%6xGy+=={}cDX=O1az_|RSO zi35;I(AQ$W6~4(|6gBS%>Jfev|M7cm?!V3Ae~5;r`ZF_0gJL>wXD4VzyFD zj0ihN;NV`xzRA_suvPE}v;=7U=>z;I&Qw5 z{3x7BhWP4UYnu4LAJ8_y_P~$wOeY{^Tf`E+!Ct@{dn};Cc0@WMq@3;V=R-WIyCoF|y zi5d8VX#nwoAB7VZIF1;AZ_WbZI~K6b@T2sOQY0+47rwy~ARaSwB_rL29+)_RLArA>r(aj)Lj?pK{QJjYcR+2;CeCB7^A+aLZ`;pug98fvJa kh8k+9p@tf2sIAfe16Om4l7&%U(*OVf07*qoM6N<$g6ECEtpET3 diff --git a/games/NXDoom/data/wadfile.png b/games/NXDoom/data/wadfile.png deleted file mode 100644 index a5888438812c0b270fb26bf1ed949b896b37ba8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8681 zcmZu%cQoA3*Z$aL5xo-xLDcA?vuYyId$+Pml<3jR5;X`SqD4#8=q*~XLZY`Qs|2gF zI>G8c-}mo#&XjZJ%$b>c=FT(sK6heuw4RdOyMGS=021|QDtdP<;=e)wxvRV6Z3gZd zLicB;UI4&l^+EAN^7Ci^7_8m) zZZUuLE$@QpsS?{VOoGS<&p>{Up}~kaJa$uYEt(gD z+<%QM>$W|f&-}au1VDZd;uW4Mh5mU#c7yE+y}C(rGW300A`bD}IZnJ`626f^GViOH z!x~ME&ExgoicTv`!@rD(EEz9eQte-F&ln5lnAspk-hm1f{{f@Z|tB9iP3%rh9m@k|H^*jUrqBA{HF z$+1i*pGq5FUpoJs$k#6+A&mYP$7l1ti{mv*O}b(dVA<1dxLc9ztu#U_bhJm#cQI~k zHh@So&@PD_WSYY^B5G?I#Xo}NPkO{$;P{R|YZ)_aXwh`QloPye%EZLfl(rB0x0D-n z7K&XIG``%hM=aj_{n{~%zQqL;j+Afra%r%c5#%3mm>%^W6AwbG=9H^Y%Af3}=N5mR zZ;Y(WIowiQUOr$CVq4k^-uE8~^l|l`+du)ifvYSye_PsuL1zocZvlYKb7yxy%(PcY zHQ|A70|j2?O-(LiX$ts6(_Ir`UT3sOJ+U*Jez2et5z#BEY;&2xz>n+6#;QVU51}Xx zhl*pBt;YU{I{kVAL?Trntgq!t$#vf1Pn1%7;O%A`eAjaZ>7YdWM*%<_`o(Xz zqTDegZYm!*Sb@fzb{gkx_Mq*o#cnK&7;x)junxv9Y0n2P1}mI!xRP^vp^%$z!?cQ> z>mmRo(3hV{A}{rHl~}q|;RQ8^NpaT-+F}gnBNs=~chHm6W)=wrqu*6vR&vf~AE=?> zV!P;zg*TrAG5i5-@{qS|QC)T}uU(cZ+=3a6o;t&37E(TQgdS}@RR}iDZzlS3&Hzxn z(R$7q<&;g7X+`pRh+`coR3rM`MbWMT^IA^pvDP~=K{KP5_|lWyv{Dh|Xbb2n!;x%s zuUB=iX2NPZ*-Ia^8e4^eqtY{OMWu)`LCem`GQls4jIdD_m}65!>Ke`8o1(dzwzi6_ zAF0*Ym1vfb%?E#h%q$#9EJUn#mF}gWjh0YkPY8t%6pqJcDli&k^9N#J`331Al&M~= zquK7BZgr@N-)VDkG6&&Ba35~h z5+&p%{z5cK)|ECJ8avU%E$^ZZ^B zK9VI1aPF{p{>)L}B>1F|4?wsU$5}NdhG=JkLGA;L3y2ghZH%-;%&&d9s{<}=8t2#1 zX6bm;m*ov|G^-D2ZM7%)O4*H5lI(C&B_K zSdBYwWHE5i4|JP^As?+ZJsxs5C!>c-#&caJYl`H}DgIH{?3tP7DD-?*#G?+4y~?rI z7iGG(VljQ9I<*a#H2Hbc`M|Y#?Ic}`%Wvt32ym|hu5aLp*XtbtsMfuXpjS!HOT<|a zAji{Gd1V=QjaAE%NfD1%YSROATtD4T)UZw>-82RA*uSJ$exMVnMJg-785I0^+1Do! zyGaBNvT2OYE*-ZiofXQ^5Xz2c7A4OWfsU# zK8#Z+O`Y9@mGa}}9+ps9Ib4<0iA*x`v7lj7ke9~pfUH1C$PoYczbpjQppciKNBk*L%9KO6*;n=ZU}D=uB!4z4nD^%LS2V0_gx!yiaH;yp$xYEKZ%}4M)7p-xR*y?PHk3kem7diis+iRX zej5md?3=w?Y|ec7t*ES}V%#xm%X@hczhb--CQg)87j}2T*KdO@nlBy-Sl$Q-Shh#Z z&s$c*I6fk{RWp6=aQAP>W!9Lw%xwOJTkiQF*T`U)QP}J;jx3Q*JPvh#%9}x@9_?0; zncxn4=f^EOyv2(BsxwO4FK=1QbHnM$`Llm-*@la$Cl!<~f!A4GR3eIVuAkKI+osz) z?ZTv0KW+5Z61Q2AZGU~^l0B_9t1isc&$Fx$v~3Q{1OIfB$D-fv`yF)R?;6;W-pR^s z47PDx{2tg6R#;js-e-}*>&rd1Wf#OKG`2eB|rgWT0K(Y*24j0gRt z@bK%lVA<=zaqL{jd1%vjFOqDrUu9NrK#W<8W-~ed*QKZ*+vGZ`rE)B+?-b_9WW4s3 zq@=824)Xg}x#5SOf`V+3DAdi8;m<-IfPlQOop4w!+Gvt55lZuMydz{oKJ@M4~9B!0})}V zsdk@#Y!$ekm7?U{948JZFq>Hr9asS2AJ!l0`CmR5b1)52AHRLGzsiYq~aNP@}cptl@yRJpd$pUkcHCn9s@nat!H zHo>?V!b1QO-;%^uWtZ`UkiNAB^7}Hy(#1W51Bu#l+xcL4{%zO)lm7s&V`kpmZr#wj`QU9xbOJ*PBMb{K)`CWfF zgwj?&3{jU{8PqSmS_-kQLzzAh@2b5(V=YNQRB!d1B z0wg=lTZNQ$2Lu7O{049^+W{Upq|qO=fC4FS=)(@BZT-Sz1ZA-Nh&cG91e+r2dZdoY zvDoxLK%J5}TKO)2mSn@bDopcn7s`Rj?V=62TtNqKOlg}K1!cf_8hrx>hO$uW3Oj4- zZHNi%GfyB_m)TPwNC?hPzw&uZ+n}53?yB2+_o6_BUw;=m2;Hx+acqhg(-dYR6{aV4 zcXtPHZsPnuxYZk~0XN zC`|i`xV`=Cgm}|&NK3kd*GRcATK5xMUWyMCFhWgLhq?oZ_Tpto!yPQL3T&;lDCSCx zszJ%BCJ6grLr4ev@*>c_1+9HXnrR8oXJjf3dTb!#cx4^^mLZ_-UW#Rb5mh>63M!r; zLM(ONR)~J{`P1X6IVGmNdwvr49v!zStO1$WL^^__s>d4qN&u!LxbUdLH>U*tQ!VA5*D9DD{N{+NHm?ip)E<88v1BW74YMcro zr+vhF;b{a&^`& z)11^BP)ttW@FA4`biREV368q{B%Qat>(Po%+iArY4hU=dD2Ch!4l0hDpM4e+W=wh0 z)W*r|&%E*rUQpX+?q*>kvM;$3HqJerS;9=YFWr1^pI0C*(1{#av_(UP;xpts(^!Wr z#B|B8r>c5io}@A{Q0Xk7vA8j9l<)h`v~j=X4y7G7F+>v`Ns_*!HL_oE!emW+3UVhc z!Ou_PCPACkn_}^mRgw+-R3_f-ljf!BxF3*|nOWAt$|#Bb$|CXfOU68k!pkSig`8SF zBDCl1zHbv0;b7Y9IzzR>1wEsA)D0`727Ey;IG-5!rmlU?cT~r#KXflSUZgxP4z8x~ z*sG^|{Z2Q6ZRay1PVWg4g<+A$W^$!>Hm4KbL`ysXB93bbB+w3G)PYJm6$JewYR-A5 zl6k)xfa221Co!j*FJb~2&f|A;48Rqfn)Et4EJ60}u2<@TWbojL_FG)hPA(%fpLKT~ z%xWk1eikChsgi>!la>;{`jAQHPdmsR`F7xZBIP*C-%F6g zPY1ru-X2*}z8_R)4|EY&{TP46=zQ_Kr|L*7tsqP4li|eOiOS%3W~xTMRGrHcnIWa6 ztMr_ZEuXl21c-K~SxJ}H{;VHKKr?VvlVYth!wkx9E(}m&1UAmQKCMqj@CjO9;*gp3 z2aLuI>)LF3k80z&^DECNRy{uF)g~?Ya}r?I2RsWrpvG6IKF^0#lYM<8MC`mgUl--} zB=d%!RlZA_`0;u(fXYnUY!az%+XA}OH=E@67{{4{s_)AVfiEB&+nl{EvIi(m?C%+P zw>YB3N?Vj_A`9#Z257%YCS*OZAYYI*EOl~gGK1<4?Jpymg zx``0EL4XxjLj;@6T!0qF;*&pj@*4yQ(LL_Q&m;HyTGQL{yX?^u=q%v`kt=Q~EV7Ycc1&HJ?#|=9Qp||>PWhLf1hqdX~^r1bYsS!4;V$qj6 zI){jEVH}{Wr~MljPR{liveJvq!|%@UaF^-2n5F>EA_Y|6WgiB=8-1Fj+x7^}$HICz zxAdFNmOhDh{lY`7`jBvv&I>F@$Gv4tGPv7xvA%z|d?c-*nxf@N6-Ut#ZP?e}n2-dd z@fLJ#?)!8Jn!ic`LyUnY$-pzl&YX_Ksc9xK$;UV@M9KpjB=vfAs~=BFyICc38rq## z=3Bo#&N;?Ee{O7F`W?pvX-SxCbMJ3)n4L@?lQFT`jLnwh$20||2CM}j<4>#&l<+>Z zB5jg$??N7BD!-n80^QmwoWkYRPAwJRC!<$1T63o2jZyM%>}t?fPIft)k3H54^Z*h| zz7q;br59y7?xa4CM+tRCR99r>@-R5X&dwCP znBrpzeH8nWD7~U6C*xCSh$OBMP>0d24j}$RdS@6#Pz&R%#rBuQ5@;CRIdc+#bx9<1 zn^mF^>nhl~6vHlxt51lxp0_YcEfOa>X_=vyh2!kk&+VF^;^=mfvBt!z&rUN*MRUT*k-PcWo%3~;FeYyj9479nRX@L}r zF(AB|-`+S3OI@}nt#A$I(L}<$Yl%!cuF4WX&_}Pm8;@O}8S-RL`V7>4U4oi-y4hX{ zdjJkXFN=2+nWEL00 zRxq8pcIb4tb;IFT4RF(IgIU#9pSpZ_M_LULw?;cC2v`ISihxyR=sv-xB-q`k)ClBN zT>GN}&l;?YG@)FrF%`uM9Gz7)hhGQzdlxBm@V~MAlF0o;@@e1`TjX}0oqzP#$RF&z zW{CTFmkfs@E@ApbEKu~p>$`n?dLWeOtjcLveex$ZNlTFaVB7VI+YT2X{4A$YzW9(y zx?U6=Hyx*w$P~;19SMtT9zNeRjQr@Vx%zo-3{u(H@ejxgji@out1#0lqN_fch)#N+ zTeY#HS`?ZC86_qhf~_eV*-=aWRU@m1_{7uF<0lzd&l0H#G?83_dq}YZ_pUOWu}7J< z0XXIx50XA8y!gqiR>DtY!X;iaJ{0f>xf@`sMGk)_ojRF!ssYsyaqgt1_GeMUE8zX`{W zT{-2oJ?*+@)PF;ka#Vc}+iNPfp^YBI#o!q96BrI#&DU;GR?gql_5Z4Fvkwo*hl~Gu z$yt~F@cWC4>WLgOoxCQLHC~Y2U_8*UqDNY7mTCFX0A+()BwzVsEtHk9{YjEHBzvJZCN!WxY_F8m~4Unqdy*QHABK`zu=F+4yPuD3OJxg~onSI}Vp3$z!#%pa2 ziM@lYq9PYU&dt-$i+C}Y-3W7-!+3%W4fjRGyeGN$!uopDxj(&E`yh)E z(<+%Y4D@pSEAtiI3Rp+oZJ?l?DPZO}VpW<{**SdXgS4@U1VlcdsR)Uhf9VqvZnfs> zS_$`e?CX1M=j;~L+eiAOOf|ajv6%}~-g6A!M4Rk>E?kaef>e#9)TcAsp+Q@R47G=~ z(|EEcrpPl+U6`GY_oVSjb!`i!Plu40$M0%l3Wq56`vkm^x1(tNPM%t1*G{W4k)CA_ zwa|&j?)zIiqy#DVPEc+}O>^^B7z-m2*#$^ng+6@Q&dx~Y2~2Sus-9pNQp%ENwYTF+ zn5F-1dyrfVJG0KP6;gX{LtlIwUon*6dC>MJ-_d*6-6UrxS+q<9?|nR(j?xga_=A5f zGw$UPo(YZYi=P|mY(f`JJ{vtruUi)6O`{Fiba>8z`W3U@(+m7WwwM?F{0Os`KrZK3 z%}SsHBc*t|^Z}}2M!Fq<&aFYW`YgV=Q2R<@#C-5oiD8>5t=WIpbwN_?RVO~|#8NRD z=%B~_=qnPg_oe+moqBz9BFds%87`}KTI5uQ}g_@ znipjn_&$il8z4)huyT|K5Ke9#IM_c6bm5BJa19DImGGc_+E|=wQue`kictWyc*EEG zWMAj(<;sSzd4>gJMcT8F@?Y&SwJ3=p;$*sKlJPo{jlh5Gi%u#=u(WLF8fR65!bC1u zzYxRtn1Tyzcf6mZ*F)UaJYK#}RV{trMl6%0J^$y5^=w3wWmYFan5jE&s2vtaFbplo zqgE038*VdkzXo(>h}pK_XM;USZrNdFVPaITU{h+&q*z1DwC*n6h}Id`PlETK4h=#H zsjA^x>xIAWW+>>;IJuncrAN$?iWS#6{GaTNS)Cs{S=QWZARV!*`bm1Qz-49|T(1QY z%XmUsMWR?Rpjptt3#{tt(Z|f%%!g4iA@1;ARJ&a9(5jAlhr>lG2H3kq1Oa7iG*K6y|Fc9~|#?TN7gqsoxm!y<`NXtf8agXDbdiAh?4T`^|q{4rnpt zv}&=L=sIbs6*Kt z5KF|^E5oq;`ll@n{ciNI<<{!F5hdzTKtRM_9q*25}glry{lDf#o4Q!j~<2=2I)cMQMjQV z_34s88u!_3#`Ae)h`n?+Y0>zgOYbP`z4ju0%|GdXw@Zys83!B;+gv*lzMDUAe&p<; z`N#)2oCcH%70q{FwgP%^uOMTHHUi;QngoSYZsjt7Z9TncD(?P6iN*?Nsh|`N3 zP!|#zz5={<46~|=*81>}u2~jt7{<#EQk-(zsR#2;1ce5R{p`nhsw`Wo5om1&VB8g{ zt4gAED<}Z6E7h7#S$QZZF)SkVyFsA`k3QY;E|R~B-+W_85@TCn8R$Pq>5^e|A1XYE z!Q3|*v?sMIXU^Kqau-;ou6>!Cm*;cuYq4fVlJGRK+CL;JI@hy){ z8daDti|H#hCvh{>1?cT#0Xd-g*il830Wl%Y%nd0SKQ5VffYA9s3`IMSF!!Lyy*&X9 zena7mg}Ra7G{!U>5ho-kO`n$NkDQ`-hC=LZ39CQxzTZB7x83~8m3J5)Px{-Nist>@@JqSY98azgU&!jk0`YAOjo zcy#Hxfs^i<-O`cI4kn2!ZX$97fPx>D3;=fMr&WoWM^ov*CdtJ#(?8(_1>}ui{2hNS zn>H)Bb;tR8*VK!3!$wgt>`5NuJh=>m9exVyg)ztanfkeBVi0>v{a~kzw=Kj;CE5fx zd8fR{{B*$mYz;3pUx6u4fk}ndl7IRMs8=gP#Gb%wK856}{9WnXplBiG{sn~T0&r!E zB8(e?6qAC<`N2)O4-lNRvTR=#{6uQ#lCG0C9=g(KAg1d;le0(?`iv>ahDNKCi1PHg z-tTn9N#kzSAA{UYFGlfKz;|>k2u48E!dC(kuZL1mDn)4wc0V0cQL}U0g~@JEc&lo z+?V_bm1Uxt-a`>Yg5%>Ry77;B!9f;P6f<(Un*(`9vbR+}y@~IB$L&U2cy9 zODHjb9GpSj{ByqR9+v*Bl%${V{$fw*TejVa>BWeG*KMG7w){2A3Ete?oa9N=_~soL zJzi4G=$MT87gf1VZC=_mX0Y)-McS~-M1nzEi8tuPkgeOBT)_}RS}fS4`h-h)ND^u} zZ%RY(oUNe~_#^h}ac7b!-jG;4do9iy4OD6;eM>5s6!t|PzG40%h}0Tff1lvx$7s4Y z;GTmaTmv&vr0^t{PrK-JZ%)~QxPBAmqMvRFkI=7QtPXbM?Xl#Yhr;6Qr0qD2^Ii=~ zSjT#LZ+h5|H5eA%Lyu0MWgh~}*t_ZTDTdfHT&H!x`w;f^ire&{W%Nq8HQye~*C)U| z2Yhw+z4Y~BUeP;(=w2QiJy*=gQYc+?d%KkjtTb%$i-(W4-~GS<)K#@qDwSa2{{x5e Bj!^&r diff --git a/games/NXDoom/man/.gitignore b/games/NXDoom/man/.gitignore deleted file mode 100644 index d974b54eb01..00000000000 --- a/games/NXDoom/man/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -CMDLINE.doom -CMDLINE.doom.md -CMDLINE.heretic -CMDLINE.heretic.md -CMDLINE.hexen -CMDLINE.hexen.md -CMDLINE.strife -CMDLINE.strife.md -INSTALL.doom -INSTALL.heretic -INSTALL.hexen -INSTALL.strife -Makefile.in -Makefile -*.6 -*.5 diff --git a/games/NXDoom/man/CMDLINE.template b/games/NXDoom/man/CMDLINE.template deleted file mode 100644 index 2c59938366a..00000000000 --- a/games/NXDoom/man/CMDLINE.template +++ /dev/null @@ -1,8 +0,0 @@ -== Command line parameters == - -This is a full list of the supported command line parameters. A number of -additional parameters are supported in addition to those present in the DOS -version. - -@content - diff --git a/games/NXDoom/man/CMDLINE.template.md b/games/NXDoom/man/CMDLINE.template.md deleted file mode 100644 index b7c800a7023..00000000000 --- a/games/NXDoom/man/CMDLINE.template.md +++ /dev/null @@ -1,8 +0,0 @@ -# Command line parameters - -This is a full list of the supported command line parameters. A number of -additional parameters are supported in addition to those present in the DOS -version. - -@content - diff --git a/games/NXDoom/man/INSTALL.template b/games/NXDoom/man/INSTALL.template deleted file mode 100644 index c889cbdbef0..00000000000 --- a/games/NXDoom/man/INSTALL.template +++ /dev/null @@ -1,316 +0,0 @@ -#ifdef DOOM -#define DEFAULT_IWAD doom2.wad -#elif HERETIC -#define DEFAULT_IWAD heretic.wad -#elif HEXEN -#define DEFAULT_IWAD hexen.wad -#elif STRIFE -#define DEFAULT_IWAD strife1.wad -#endif -# LONG_GAME_NAME installation - -These are instructions for how to install and set up LONG_GAME_NAME -for play. - -#if !PRECOMPILED -# Building LONG_GAME_NAME - -Before you can play LONG_GAME_NAME, you need to compile a binary that -you can run. For compilation, LONG_GAME_NAME requires the following -to be installed: - - * A C compiler (gcc is recommended) - * make (GNU make is recommended) - * SDL2 (see https://www.libsdl.org/) - * SDL2_mixer (see https://www.libsdl.org/projects/SDL_mixer/) - * SDL2_net (see https://www.libsdl.org/projects/SDL_net/) - * Python (optional) - -Follow the standard instructions for installing an autotools-based -package: - - 1. Run `./configure` to initialize the package. - 2. Run `make` to compile the package. - 3. Run `make install` to install the package. - -An automated build script is available that installs the necessary -dependencies and builds the source code automatically. See the build -instructions on the website. - -Advanced topics such as cross-compilation are beyond the scope of this -document. Please see the GNU autoconf / automake documentation for more -information. - -#endif -# Obtaining an IWAD file - -To play, you need an IWAD file. This file contains the game data -(graphics, sounds, etc). The full versions of the games are -proprietary and need to be bought. The IWAD file has one of the -following names: - -| IWAD | Game | -| -------------------------- | ------------------------------- | -#if DOOM -| doom1.wad | Shareware Doom | -| doom.wad | Registered / Ultimate Doom | -| doom2.wad | Doom 2 | -| tnt.wad | Final Doom: TNT: Evilution | -| plutonia.wad | Final Doom: Plutonia Experiment | -| chex.wad | Chex Quest | -| freedoom1.wad | Freedoom: Phase 1 | -| freedoom2.wad | Freedoom: Phase 2 | -| freedm.wad | FreeDM | -#endif -#if HERETIC -| heretic1.wad | Shareware Heretic | -| heretic.wad | Registered / Commercial Heretic | -#endif -#if HEXEN -| hexen.wad | Hexen | -#endif -#if STRIFE -| strife1.wad (+voices.wad) | Strife | -#endif - -#if DOOM -If you don’t have a copy of a commercial version, you can download -the shareware version of Doom (extract the file named doom1.wad): - - * https://www.doomworld.com/idgames/idstuff/doom/win95/doom95 - (idstuff/doom/win95/doom95.zip in your nearest /idgames mirror) - -#endif -If you have a commercial version on a CD-ROM, obtaining the IWAD -file is usually straightforward. Simply locate the IWAD file on the -disc and copy it off. - -#if !__MACOSX__ -#if DOOM -The Doom games are available to purchase for download on Steam -(https://store.steampowered.com/), all releases containing the classic -games including Doom 3: BFG Edition are supported. -#endif -#if HERETIC -Heretic is available to purchase for download on Steam -(https://store.steampowered.com/). -#endif -#if HEXEN -Hexen and its expansion pack are available to purchase for download on -Steam (https://store.steampowered.com/). -#endif -#if STRIFE -Strife: Veteran Edition is available to purchase for download on Steam -(https://store.steampowered.com/). -#endif -#if !_WIN32 -For Steam on Linux, you need to enable “Steam Play” for all titles in -order to install the games. You may do this from the Steam menu, -Setup, and the Steam Play tab. -#endif -LONG_GAME_NAME will autodetect IWADs installed by Steam and you do not -need to do anything. -#else -The Doom, Heretic, Hexen, and Strife games are available to purchase -for download on Steam (https://store.steampowered.com/), but are only -available for Windows. To find the IWAD files on a Windows or Wine -system, look in the Steam directory (usually within “Program Files”), -under the “steamapps/common” path. -#endif - -#if DOOM || STRIFE -The Doom and Strife: Veteran Edition games are available for purchase -on GOG.com (https://www.gog.com/). -#if _WIN32 -LONG_GAME_NAME will autodetect IWADs from the standalone or GOG Galaxy -installers and you do not need to do anything. -#else -The games are only available for Windows, but you may find the IWAD -files on a Windows or Wine system, typically within the “C:\GOG Games” -or “C:\Program Files\GOG Galaxy” directories. -#endif - -#endif -#if DOOM || HERETIC -Older floppy disk versions are harder to deal with. The easiest way -to install from floppies is to run the original installer program -inside an emulator such as DOSbox (https://www.dosbox.com/). -As an alternative to using an emulator, it is possible to extract the -files manually. On the install disk(s), you will find several files -with numbered extensions (eg. “doom_se.1”). - -From the command line it is possible to combine these files into a -single large file, using a command similar to the following: - -#if _WIN32 - copy doom_se.1+doom_se.2+doom_se.3+doom_se.4+doom_se.5 doom_se.lzh -#else - cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.lzh -#endif - -The resulting file is an LHA archive file, and it can be extracted -using an LHA archive tool (there is one available for almost every -operating system). - -#endif -# Running the game - -#if __MACOSX__ -Once you have an IWAD file, you can specify its location within the -graphical launcher program. Click the “Configure...” button, and then -click “Set...” for each IWAD to choose its location. From the main -launcher dialog you can then choose which game you want to play and -click the “Launch” button to start the game. - -If you are an advanced user and like to run Doom from the command -line, you can use the “Command Prompt...” menu item to open a Terminal -window. The DOOMWADPATH environment variable is preconfigured -to point to the locations of the IWAD files set within the launcher. -You can launch the game with a specific IWAD file by typing, for -example: - - LONG_EXE_NAME -iwad tnt.wad -#else -LONG_GAME_NAME needs to know where to find your IWAD file. To do this, -do one of the following: - -#if _WIN32 - * Within Explorer, simply place the IWAD file in the same folder as - the LONG_GAME_NAME files, and double-click `LONG_EXE_NAME.exe`. - - * Run LONG_GAME_NAME from the command prompt with the `-iwad` command - line parameter to specify the IWAD file to use, eg. - - LONG_EXE_NAME -iwad c:\games\DEFAULT_IWAD - - * Set the environment variable DOOMWADDIR to the location of a - directory containing your IWAD files. - - * If you have multiple IWADs in different directories, set the - environment variable DOOMWADPATH to be a semicolon-separated list - of directories to search (similar to the PATH environment - variable). -#else - * Run LONG_GAME_NAME from the Unix console with the `-iwad` command - line parameter to specify the IWAD file to use, eg. - - LONG_EXE_NAME -iwad /root/DEFAULT_IWAD - - * Put the file into one of the following directories: - - $HOME/.local/share/games/doom - /usr/share/doom - /usr/share/games/doom - /usr/local/share/doom - /usr/local/share/games/doom - - * Set the environment variable DOOMWADDIR to specify the path to a - directory containing your IWAD files. - - * If you have multiple IWADs in different directories, set the - environment variable DOOMWADPATH to be a colon-separated list of - directories to search (similar to the Unix PATH environment - variable). -#endif -#endif - -#if DOOM -# Playing with Freedoom - -Freedoom is an open content project to create a Doom engine-based game -that is entirely free software. The website can be found here: - - https://freedoom.github.io/ - -Check out the [Chocolate Doom wiki’s page on -Freedoom](https://www.chocolate-doom.org/wiki/index.php/Freedoom) -for more information. - -# Playing with Chex Quest - -Chex Quest is a game based on Doom with some minor modifications that -was distributed with boxes of Chex cereal in 1997. It is possible to -play Chex Quest using LONG_GAME_NAME. To do this, the following files -are needed: - - * The IWAD file “chex.wad”, from the Chex Quest CD. - - * The dehacked patch “chex.deh”, which can be found here: - https://www.doomworld.com/idgames/themes/chex/chexdeh - (themes/chex/chexdeh.zip in your nearest /idgames mirror) - -Copy these files into a directory together and use the `-iwad` command -line parameter to specify the Chex Quest IWAD file: - - LONG_EXE_NAME -iwad chex.wad - -#endif -# Installing upgrades - -#if DOOM -LONG_GAME_NAME requires a version 1.9 IWAD file. Generally, if you -install a recent version of Doom you should have a version 1.9 IWAD. -#elif HERETIC -LONG_GAME_NAME requires a version 1.2 (Shareware) or version 1.3 -(Shadow of the Serpent Riders) IWAD file. Generally, if you install a -recent version of Heretic you should have a version 1.2 or 1.3 IWAD. -#elif HEXEN -LONG_GAME_NAME requires a version 1.1 IWAD file. Generally, if you -install a recent version of Hexen you should have a version 1.1 IWAD. -#elif STRIFE -LONG_GAME_NAME requires a version 1.2 IWAD file. Generally, if you -install a recent version of Strife you should have a version 1.2 IWAD. -Please note that Strife version 1.3 does not update the IWAD, if your -version.txt file says “STRIFE(TM) VERSION 1.3”, you are still good. -#endif -However, if you are installing from a very old CD version or from -floppy disks, you might find you have an older version. - -The most obvious symptom of an out of date IWAD file is that the game -will exit at the title screen before the demo starts, with the message -“Demo is from a different game version!”. If this happens, your IWAD -file is out of date and you need to upgrade. - -Upgrade patches are available that will update your game to the latest -version, the following sites have the patches: - -#if DOOM - * http://www.doom2.net/doom2/utils.html - * http://www.gamers.org/pub/idgames/idstuff/doom - * http://www.gamers.org/pub/idgames/idstuff/doom2 -#elif HERETIC - * http://www.gamers.org/pub/idgames/idstuff/heretic -#elif HEXEN - * http://www.gamers.org/pub/idgames/idstuff/hexen -#elif STRIFE - * http://www.gamers.org/pub/idgames/roguestuff -#endif - -Please see the -[Doom Wiki’s page on game patches](https://doomwiki.org/wiki/Game_patch) -for more information. - -#if _WIN32 -As the patches are binary patches that run as DOS executables, on -recent 64-bit versions of Windows you will need to use a DOS emulator -(such as DOSBox) to run them. -#else -As the patches are binary patches that run as DOS executables, you -will need to use a DOS emulator (such as DOSBox) to run them. -#endif - -# Music support - -LONG_GAME_NAME includes OPL emulation code that accurately reproduces -the way that the in-game music sounded under DOS when using an -Adlib/Soundblaster card. This is, however, not to everyone’s taste. - -LONG_GAME_NAME includes a number of different options for better -quality MIDI playback; see the file README.Music for more details of -how to set these up. - -#if !PRECOMPILED -When compiling from source, be sure to compile and install Timidity -before installing SDL2_mixer. - -#endif diff --git a/games/NXDoom/man/Makefile.am b/games/NXDoom/man/Makefile.am deleted file mode 100644 index 2e1e0474562..00000000000 --- a/games/NXDoom/man/Makefile.am +++ /dev/null @@ -1,226 +0,0 @@ -SUBDIRS = bash-completion - -MANPAGE_GEN_FILES = environ.man \ - iwad_paths.man \ - doom.template \ - heretic.template \ - hexen.template \ - strife.template \ - docgen \ - default.cfg.template \ - extra.cfg.template \ - server.template \ - setup.template - -doomdocsdir = ${docdir}/../${PROGRAM_PREFIX}doom -hereticdocsdir = ${docdir}/../${PROGRAM_PREFIX}heretic -hexendocsdir = ${docdir}/../${PROGRAM_PREFIX}hexen -strifedocsdir = ${docdir}/../${PROGRAM_PREFIX}strife - -if HAVE_DOC - -GENERATED_MAN_PAGES = \ - @PROGRAM_PREFIX@doom.6 \ - default.cfg.5 \ - @PROGRAM_PREFIX@doom.cfg.5 \ - @PROGRAM_PREFIX@heretic.6 \ - heretic.cfg.5 \ - @PROGRAM_PREFIX@heretic.cfg.5 \ - @PROGRAM_PREFIX@hexen.6 \ - hexen.cfg.5 \ - @PROGRAM_PREFIX@hexen.cfg.5 \ - @PROGRAM_PREFIX@strife.6 \ - strife.cfg.5 \ - @PROGRAM_PREFIX@strife.cfg.5 \ - @PROGRAM_PREFIX@server.6 - -SETUP_MAN_PAGES = \ - @PROGRAM_PREFIX@doom-setup.6 \ - @PROGRAM_PREFIX@heretic-setup.6 \ - @PROGRAM_PREFIX@hexen-setup.6 \ - @PROGRAM_PREFIX@strife-setup.6 - -man_MANS = $(GENERATED_MAN_PAGES) \ - $(SETUP_MAN_PAGES) - -doomdocs_DATA = INSTALL.doom CMDLINE.doom -hereticdocs_DATA = INSTALL.heretic CMDLINE.heretic -hexendocs_DATA = INSTALL.hexen CMDLINE.hexen -strifedocs_DATA = INSTALL.strife CMDLINE.strife - -if HAVE_WINDRES - -WIN32=-D_WIN32 - -doomdocs_DATA += CMDLINE.doom.md -hereticdocs_DATA += CMDLINE.heretic.md -hexendocs_DATA += CMDLINE.hexen.md -strifedocs_DATA += CMDLINE.strife.md - -endif - -CLEANFILES = $(GENERATED_MAN_PAGES) $(SETUP_MAN_PAGES) \ - $(doomdocs_DATA) $(hereticdocs_DATA) \ - $(hexendocs_DATA) $(strifedocs_DATA) -DOCGEN = $(srcdir)/docgen -DOCGEN_COMMON_ARGS = -n "@PROGRAM_SPREFIX@" \ - -s "@PACKAGE_NAME@" \ - -z "@PACKAGE_SHORTNAME@" \ - -v "@VERSION@" - -@PROGRAM_PREFIX@doom.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g doom -m $(srcdir)/doom.template \ - $(top_srcdir)/src $(top_srcdir)/src/doom > $@ - -default.cfg.5: $(top_srcdir)/src $(srcdir)/default.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g doom -m $(srcdir)/default.cfg.template \ - -c default $(top_srcdir)/src/m_config.c > $@ - -@PROGRAM_PREFIX@doom.cfg.5: $(top_srcdir)/src extra.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g doom -m $(srcdir)/extra.cfg.template \ - -c extended $(top_srcdir)/src/m_config.c > $@ - -CMDLINE.doom : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/doom - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -p $(srcdir)/CMDLINE.template \ - $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@ - -CMDLINE.doom.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/doom - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -M $(srcdir)/CMDLINE.template.md \ - $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@ - -CMDLINE.doom.wikitext : $(top_srcdir)/src $(top_srcdir)/src/doom - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -w $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@ - -INSTALL.doom: INSTALL.template - $(srcdir)/simplecpp -DDOOM $(WIN32) \ - -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \ - -DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \ - -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ - -@PROGRAM_PREFIX@heretic.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) heretic.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g heretic -m $(srcdir)/heretic.template \ - $(top_srcdir)/src $(top_srcdir)/src/heretic > $@ - -heretic.cfg.5: $(top_srcdir)/src $(srcdir)/default.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g heretic -m $(srcdir)/default.cfg.template \ - -c default $(top_srcdir)/src/m_config.c > $@ - -@PROGRAM_PREFIX@heretic.cfg.5: $(top_srcdir)/src extra.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g heretic -m $(srcdir)/extra.cfg.template \ - -c extended $(top_srcdir)/src/m_config.c > $@ - -CMDLINE.heretic : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/heretic - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -p $(srcdir)/CMDLINE.template \ - $(top_srcdir)/src/ $(top_srcdir)/src/heretic/ > $@ - -CMDLINE.heretic.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/heretic - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -M $(srcdir)/CMDLINE.template.md \ - $(top_srcdir)/src/ $(top_srcdir)/src/heretic/ > $@ - -INSTALL.heretic: INSTALL.template - $(srcdir)/simplecpp -DHERETIC $(WIN32) \ - -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Heretic" \ - -DLONG_EXE_NAME="@PROGRAM_PREFIX@heretic" \ - -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ - - -@PROGRAM_PREFIX@hexen.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g hexen -m $(srcdir)/hexen.template \ - $(top_srcdir)/src $(top_srcdir)/src/hexen > $@ - -hexen.cfg.5: $(top_srcdir)/src default.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g hexen -m $(srcdir)/default.cfg.template \ - -c default $(top_srcdir)/src/m_config.c > $@ - -@PROGRAM_PREFIX@hexen.cfg.5: $(top_srcdir)/src extra.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g hexen -m $(srcdir)/extra.cfg.template \ - -c extended $(top_srcdir)/src/m_config.c > $@ - -CMDLINE.hexen : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/hexen - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -p $(srcdir)/CMDLINE.template \ - $(top_srcdir)/src/ $(top_srcdir)/src/hexen/ > $@ - -CMDLINE.hexen.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/hexen - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -M $(srcdir)/CMDLINE.template.md \ - $(top_srcdir)/src/ $(top_srcdir)/src/hexen/ > $@ - -INSTALL.hexen: INSTALL.template - $(srcdir)/simplecpp -DHEXEN $(WIN32) \ - -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Hexen" \ - -DLONG_EXE_NAME="@PROGRAM_PREFIX@hexen" \ - -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ - -@PROGRAM_PREFIX@strife.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g strife -m $(srcdir)/strife.template \ - $(top_srcdir)/src $(top_srcdir)/src/strife > $@ - -@PROGRAM_PREFIX@server.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g server -m $(srcdir)/server.template \ - $(top_srcdir)/src > $@ - -$(SETUP_MAN_PAGES): $(top_srcdir)/src $(MANPAGE_GEN_FILES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g $(patsubst @PROGRAM_PREFIX@%-setup.6,%,$@) \ - -m $(srcdir)/setup.template \ - $(top_srcdir)/src > $@ - -strife.cfg.5: $(top_srcdir)/src default.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g strife -m $(srcdir)/default.cfg.template \ - -c default $(top_srcdir)/src/m_config.c > $@ - -@PROGRAM_PREFIX@strife.cfg.5: $(top_srcdir)/src extra.cfg.template - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g strife -m $(srcdir)/extra.cfg.template \ - -c extended $(top_srcdir)/src/m_config.c > $@ - -CMDLINE.strife : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/strife - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -p $(srcdir)/CMDLINE.template \ - $(top_srcdir)/src/ $(top_srcdir)/src/strife/ > $@ - -CMDLINE.strife.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/strife - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -M $(srcdir)/CMDLINE.template.md \ - $(top_srcdir)/src/ $(top_srcdir)/src/strife/ > $@ - -INSTALL.strife: INSTALL.template - $(srcdir)/simplecpp -DSTRIFE $(WIN32) \ - -DLONG_EXE_NAME="@PROGRAM_PREFIX@strife" \ - -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Strife" \ - -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ - - -INSTALL: INSTALL.template - $(srcdir)//simplecpp -DDOOM -DHERETIC -DHEXEN -DSTRIFE \ - -DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \ - -DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \ - -DPRECOMPILED < $(srcdir)/INSTALL.template > $@ - -endif - -EXTRA_DIST = $(man_MANS) $(MANPAGE_GEN_FILES) \ - wikipages \ - CMDLINE.template \ - CMDLINE.template.md \ - INSTALL.template \ - simplecpp - diff --git a/games/NXDoom/man/bash-completion/.gitignore b/games/NXDoom/man/bash-completion/.gitignore deleted file mode 100644 index 488df26aad6..00000000000 --- a/games/NXDoom/man/bash-completion/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*doom -*heretic -*hexen -*strife -*.template diff --git a/games/NXDoom/man/bash-completion/Makefile.am b/games/NXDoom/man/bash-completion/Makefile.am deleted file mode 100644 index a79fe6239b2..00000000000 --- a/games/NXDoom/man/bash-completion/Makefile.am +++ /dev/null @@ -1,52 +0,0 @@ -bashcompletiondir=@datadir@/bash-completion/completions - -BASH_COMPLETION_TEMPLATES = \ - doom.template \ - heretic.template \ - hexen.template \ - strife.template - -if HAVE_BASH_COMPLETION - -BASH_COMPLETION_SCRIPTLETS = \ - @PROGRAM_PREFIX@doom \ - @PROGRAM_PREFIX@heretic \ - @PROGRAM_PREFIX@hexen \ - @PROGRAM_PREFIX@strife - -bashcompletion_DATA = $(BASH_COMPLETION_SCRIPTLETS) -CLEANFILES = $(BASH_COMPLETION_SCRIPTLETS) - -DOCGEN = $(top_srcdir)/man/docgen -DOCGEN_COMMON_ARGS = -n "@PROGRAM_SPREFIX@" -s "@PACKAGE_NAME@" -z "@PACKAGE_SHORTNAME@" - -@PROGRAM_PREFIX@doom: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g doom -b doom.template \ - $(top_srcdir)/src $(top_srcdir)/src/doom > $@ - -@PROGRAM_PREFIX@heretic: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g heretic -b heretic.template \ - $(top_srcdir)/src $(top_srcdir)/src/heretic > $@ - -@PROGRAM_PREFIX@hexen: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g hexen -b hexen.template \ - $(top_srcdir)/src $(top_srcdir)/src/hexen > $@ - -@PROGRAM_PREFIX@strife: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES) - $(DOCGEN) $(DOCGEN_COMMON_ARGS) \ - -g strife -b strife.template \ - $(top_srcdir)/src $(top_srcdir)/src/strife > $@ - -EXTRA_DIST = \ - $(BASH_COMPLETION_TEMPLATES) \ - $(BASH_COMPLETION_SCRIPTLETS) - -else - -EXTRA_DIST = \ - $(BASH_COMPLETION_TEMPLATES) - -endif diff --git a/games/NXDoom/man/bash-completion/doom.template.in b/games/NXDoom/man/bash-completion/doom.template.in deleted file mode 100644 index 6db3baf059d..00000000000 --- a/games/NXDoom/man/bash-completion/doom.template.in +++ /dev/null @@ -1,51 +0,0 @@ -# bash completion for @PACKAGE_SHORTNAME@ Doom -*- shell-script -*- - -_@PROGRAM_SPREFIX@_doom() -{ - local cur prev words cword - _init_completion || return - - # Save the previous switch on the command line in the prevsw variable - local i prevsw="" - for (( i=1; $cword > 1 && i <= $cword; i++ )); do - if [[ ${words[i]} == -* ]]; then - prevsw=${words[i]} - fi - done - - # Allow adding more than one file with the same extension to the same switch - case $prevsw in - -config|-extraconfig) - _filedir cfg - ;; - -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) - _filedir wad - ;; - -playdemo|-timedemo) - _filedir lmp - ;; - -deh) - _filedir '@(bex|deh)' - ;; - esac - - case $prev in - -pack) - COMPREPLY=(doom2 tnt plutonia) - ;; - -gameversion) - COMPREPLY=(1.666 1.7 1.8 1.9 ultimate final final2 hacx chex) - ;; - -setmem) - COMPREPLY=(dos622 dos71 dosbox) - ;; - esac - - if [[ $cur == -* ]]; then - COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) - fi -} && - -complete -F _@PROGRAM_SPREFIX@_doom @PROGRAM_PREFIX@doom - -# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/bash-completion/heretic.template.in b/games/NXDoom/man/bash-completion/heretic.template.in deleted file mode 100644 index a46b19cc31c..00000000000 --- a/games/NXDoom/man/bash-completion/heretic.template.in +++ /dev/null @@ -1,48 +0,0 @@ -# bash completion for @PACKAGE_SHORTNAME@ Heretic -*- shell-script -*- - -_@PROGRAM_SPREFIX@_heretic() -{ - local cur prev words cword - _init_completion || return - - # Save the previous switch on the command line in the prevsw variable - local i prevsw="" - for (( i=1; $cword > 1 && i <= $cword; i++ )); do - if [[ ${words[i]} == -* ]]; then - prevsw=${words[i]} - fi - done - - # Allow adding more than one file with the same extension to the same switch - case $prevsw in - -config|-extraconfig) - _filedir cfg - ;; - -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) - _filedir wad - ;; - -playdemo|-timedemo) - _filedir lmp - ;; - -deh) - _filedir hhe - ;; - esac - - case $prev in - -hhever) - COMPREPLY=(1.0 1.2 1.3) - ;; - -setmem) - COMPREPLY=(dos622 dos71 dosbox) - ;; - esac - - if [[ $cur == -* ]]; then - COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) - fi -} && - -complete -F _@PROGRAM_SPREFIX@_heretic @PROGRAM_PREFIX@heretic - -# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/bash-completion/hexen.template.in b/games/NXDoom/man/bash-completion/hexen.template.in deleted file mode 100644 index e93fc71cbeb..00000000000 --- a/games/NXDoom/man/bash-completion/hexen.template.in +++ /dev/null @@ -1,45 +0,0 @@ -# bash completion for @PACKAGE_SHORTNAME@ Hexen -*- shell-script -*- - -_@PROGRAM_SPREFIX@_hexen() -{ - local cur prev words cword - _init_completion || return - - # Save the previous switch on the command line in the prevsw variable - local i prevsw="" - for (( i=1; $cword > 1 && i <= $cword; i++ )); do - if [[ ${words[i]} == -* ]]; then - prevsw=${words[i]} - fi - done - - # Allow adding more than one file with the same extension to the same switch - case $prevsw in - -config|-extraconfig) - _filedir cfg - ;; - -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) - _filedir wad - ;; - -playdemo|-timedemo) - _filedir lmp - ;; - esac - - case $prev in - -gameversion) - COMPREPLY=(1.1 1.1r2) - ;; - -setmem) - COMPREPLY=(dos622 dos71 dosbox) - ;; - esac - - if [[ $cur == -* ]]; then - COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) - fi -} && - -complete -F _@PROGRAM_SPREFIX@_hexen @PROGRAM_PREFIX@hexen - -# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/bash-completion/strife.template.in b/games/NXDoom/man/bash-completion/strife.template.in deleted file mode 100644 index a044ef0b742..00000000000 --- a/games/NXDoom/man/bash-completion/strife.template.in +++ /dev/null @@ -1,48 +0,0 @@ -# bash completion for @PACKAGE_SHORTNAME@ Strife -*- shell-script -*- - -_@PROGRAM_SPREFIX@_strife() -{ - local cur prev words cword - _init_completion || return - - # Save the previous switch on the command line in the prevsw variable - local i prevsw="" - for (( i=1; $cword > 1 && i <= $cword; i++ )); do - if [[ ${words[i]} == -* ]]; then - prevsw=${words[i]} - fi - done - - # Allow adding more than one file with the same extension to the same switch - case $prevsw in - -config|-extraconfig) - _filedir cfg - ;; - -file|-iwad|-aa|-af|-as|-merge|-nwtmerge) - _filedir wad - ;; - -playdemo|-timedemo) - _filedir lmp - ;; - -deh) - _filedir seh - ;; - esac - - case $prev in - -gameversion) - COMPREPLY=(1.2 1.31) - ;; - -setmem) - COMPREPLY=(dos622 dos71 dosbox) - ;; - esac - - if [[ $cur == -* ]]; then - COMPREPLY=( $( compgen -W '@content' -- "$cur" ) ) - fi -} && - -complete -F _@PROGRAM_SPREFIX@_strife @PROGRAM_PREFIX@strife - -# ex: ts=4 sw=4 et filetype=sh diff --git a/games/NXDoom/man/default.cfg.template b/games/NXDoom/man/default.cfg.template deleted file mode 100644 index 5d07322a6f5..00000000000 --- a/games/NXDoom/man/default.cfg.template +++ /dev/null @@ -1,50 +0,0 @@ -.TH @CFGFILE@ 5 2017-11-30 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@CFGFILE@ \- @PACKAGE_SHORTNAME@ @GAME_UPPER@ configuration file -.SH DESCRIPTION -.PP -\fI@CFGFILE@\fR -is the configuration file for \fB@PROGRAM_SPREFIX@\-@GAME@\fR(6). The configuration -options stored in the file are the same as those stored in the -original DOS Vanilla @GAME_UPPER@. -Extra @PACKAGE_SHORTNAME@ @GAME_UPPER@-specific options are stored in a separate -configuration file, \fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. -.PP -\fI@CFGFILE@\fR is normally stored in the user's home directory, -as \fI~/.local/share/@PROGRAM_SPREFIX@\-@GAME@/@CFGFILE@\fR. The path can be -overridden using the \fBXDG_DATA_HOME\fR environment variable (see the XDG -Base Directory Specification). -.PP -The \fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) tool provides a simple to use front-end -for editing \fI@CFGFILE@\fR. -.SH FILE FORMAT -The file is a plain-text file, consisting of a list of configuration -options and their values, separated by whitespace. Each option is stored -on a separate line. Options have different types; an option may have -either an integer, floating point or string value. If the option is -of a string type, the value is surrounded by quotes ("). -.PP -For example: -.RS -.PP -.EX -integer_value 1 -integer_value2 1 -floating_point_value 4.2 -string_value "hello world" -.EE -.RE -.PP -Invalid lines or comments in the file will be ignored, but it is advisable -not to put them in the file; the file is rewritten from scratch every time -the game exits, so any invalid lines or comments will be lost. -.PP -Some options are used for keyboard key bindings; these are stored as -integer values containing the keyboard scan code of the key to be bound to. -Boolean values are also stored as integers, with a value of zero usually -indicating "false" and a non-zero value indicating "true". -@content -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6), -\fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR(5), -\fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) diff --git a/games/NXDoom/man/docgen b/games/NXDoom/man/docgen deleted file mode 100755 index 8760e8f72c6..00000000000 --- a/games/NXDoom/man/docgen +++ /dev/null @@ -1,624 +0,0 @@ -#!/usr/bin/env python3 -# -# Chocolate Doom self-documentation tool. This works similar to javadoc -# or doxygen, but documents command line parameters and configuration -# file values, generating documentation in Unix manpage, wikitext and -# plain text forms. -# -# Comments are read from the source code in the following form: -# -# //! -# // @arg -# // @category Category -# // @platform -# // -# // Long description of the parameter -# // -# -# something_involving = M_CheckParm("-param"); -# -# For configuration file values: -# -# //! @begin_config_file myconfig -# -# //! -# // Description of the configuration file value. -# // -# -# CONFIG_VARIABLE_INT(my_variable, c_variable), -# - -import io -import sys -import os -import re -import glob -import getopt - -TEXT_WRAP_WIDTH = 78 -INCLUDE_STATEMENT_RE = re.compile(r"@include\s+(\S+)") - -# Use appropriate stdout function for Python 2 or 3 - -def stdout(buf): - if sys.version_info.major < 3: - sys.stdout.write(buf) - else: - sys.stdout.buffer.write(buf) - -# Find the maximum width of a list of parameters (for plain text output) - -def parameter_list_width(params): - w = 0 - - for p in params: - pw = len(p.name) + 5 - - if p.args: - pw += len(p.args) - - if pw > w: - w = pw - - return w - -class ConfigFile: - def __init__(self, filename): - self.filename = filename - self.variables = [] - - def add_variable(self, variable): - self.variables.append(variable) - - def manpage_output(self): - result = ".SH CONFIGURATION VARIABLES\n" - - for v in self.variables: - result += ".TP\n" - result += v.manpage_output() - - return result - - def plaintext_output(self): - result = "" - - w = parameter_list_width(self.variables) - - for p in self.variables: - result += p.plaintext_output(w) - - result = result.rstrip() + "\n" - - return result - -class Category: - def __init__(self, description): - self.description = description - self.params = [] - - def add_param(self, param): - self.params.append(param) - - # Plain text output - - def plaintext_output(self): - result = "=== %s ===\n\n" % self.description - - self.params.sort() - - w = parameter_list_width(self.params) - - for p in self.params: - if p.should_show(): - result += p.plaintext_output(w) - - result = result.rstrip() + "\n" - - return result - - def markdown_output(self): - result = "## %s\n\n| Parameter | Description |\n| - | - |\n" % self.description - - self.params.sort() - - for p in self.params: - if p.should_show(): - result += p.markdown_output() - - result = result.rstrip() + "\n" - - return result - - def completion_output(self): - result = "" - - self.params.sort() - - for p in self.params: - if p.should_show(): - result += p.completion_output(0) - - result = result.rstrip() - - return result - - def manpage_output(self): - result = ".SH " + self.description.upper() + "\n" - - self.params.sort() - - for p in self.params: - if p.should_show(): - result += ".TP\n" - result += p.manpage_output() - - return result - - def wiki_output(self): - result = "=== %s ===\n" % self.description - - self.params.sort() - - for p in self.params: - if p.should_show(): - result += "; " + p.wiki_output() + "\n" - - # Escape special HTML characters - - result = result.replace("&", "&") - result = result.replace("<", "<") - result = result.replace(">", ">") - - return result - -categories = ( - (None, Category("General options")), - ("game", Category("Game start options")), - ("video", Category("Display options")), - ("net", Category("Networking options")), - ("mod", Category("Dehacked and WAD merging")), - ("demo", Category("Demo options")), - ("compat", Category("Compatibility")), - ("obscure", Category("Obscure and less-used options")), -) - -wikipages = [] -config_files = {} - -# Show options that are in Vanilla Doom? Or only new options? - -show_vanilla_options = True - -class Parameter: - def __lt__(self, other): - return self.name < other.name - - def __init__(self): - self.text = "" - self.name = "" - self.args = None - self.platform = None - self.category = None - self.vanilla_option = False - self.games = None - - def should_show(self): - return not self.vanilla_option or show_vanilla_options - - def add_text(self, text): - if len(text) <= 0: - pass - elif text[0] == "@": - match = re.match(r'@(\S+)\s*(.*)', text) - - if not match: - raise "Malformed option line: %s" % text - - option_type = match.group(1) - data = match.group(2) - - if option_type == "arg": - self.args = data - elif option_type == "platform": - self.platform = data - elif option_type == "category": - self.category = data - elif option_type == "vanilla": - self.vanilla_option = True - elif option_type == "game": - self.games = re.split(r'\s+', data.strip()) - else: - raise "Unknown option type '%s'" % option_type - - else: - self.text += text + " " - - def _games_only_text(self, pattern="(%s only)"): - if not match_game and self.games: - games_list = ", ".join(map(str.capitalize, self.games)) - return " " + (pattern % games_list) - else: - return "" - - def manpage_output(self): - if self.args: - # Special cases -- GBR is not proud. - if self.args == "[ | ]": - result = ".BR " + self.name + " \\~\\c\n" \ - + ".RI [ x\\~y | xy ]\n" - elif self.args == "": - result = ".BI " + self.name + "\\~ W x H\n" - elif self.args == " ": - result = ".BI " + self.name + "\\~ \"x y\"\n" - elif self.args == "": - result = ".BI " + self.name + "\\~ \"file\\~\\c\n" \ - + "\\&.\\|.\\|.\n" - elif self.args == " ": - result = ".BI " + self.name \ - + "\\~ \"save-num demo-name\"\n" - else: - self.args = re.sub(r'[<>]', '', self.args) - result = ".BI " + self.name + "\\~ " + self.args + "\n" - else: - result = ".B " + self.name + "\n" - - if self.platform: - result += "[%s only] " % self.platform - - escaped = re.sub(r'\\', r'\\\\', self.text) - - result += escaped + self._games_only_text() + "\n" - - return result - - def wiki_output(self): - result = self.name - - if self.args: - result += " " + self.args - - result += ": " - - result += add_wiki_links(self.text) - - if self.platform: - result += "'''(%s only)'''" % self.platform - result += self._games_only_text("'''(%s only)'''") - - return result - - def markdown_output(self): - if self.args: - name = "%s %s" % (self.name, self.args) - else: - name = "%s" % self.name - - name = name.replace("|", "\\|") - - text = self.text - if self.platform: - text += " (%s only)" % self.platform - - text = text.replace("|", "\\|") - - result = "| %s | %s |\n" % (name, text) - - # html escape - result = result.replace("<", "<") - result = result.replace(">", ">") - - return result - - def plaintext_output(self, indent): - # Build the first line, with the argument on - start = " " + self.name - if self.args: - start += " " + self.args - - # pad up to the plaintext width - start += " " * (indent - len(start)) - - # Build the description text - description = self.text - if self.platform: - description += " (%s only)" % self.platform - description += self._games_only_text() - - # Build the complete text for the argument - # Split the description into words and add a word at a time - result = "" - words = [word for word in re.split(r'\s+', description) if word] - maxlen = TEXT_WRAP_WIDTH - indent - outlines = [[]] - for word in words: - linelen = sum(len(w) + 1 for w in outlines[-1]) - if linelen + len(word) > maxlen: - outlines.append([]) - outlines[-1].append(word) - - linesep = "\n" + " " * indent - - return (start + - linesep.join(" ".join(line) for line in outlines) + - "\n\n") - - def completion_output(self, w): - - result = self.name + " " - - return result - -# Read list of wiki pages - -def read_wikipages(): - f = io.open("wikipages", encoding='UTF-8') - - try: - for line in f: - line = line.rstrip() - - line = re.sub(r'\#.*$', '', line) - - if not re.match(r'^\s*$', line): - wikipages.append(line) - finally: - f.close() - -# Add wiki page links - -def add_wiki_links(text): - def replace_name(m): - linktext = m.group(1) - if linktext == pagename: - return '[[%s]]' % pagename - else: - return '[[%s|%s]]' % (pagename, linktext) - - for pagename in wikipages: - text = re.sub(r'\b(%s)\b' % re.escape(pagename), replace_name, - text, count=0, flags=re.IGNORECASE) - - return text - -def add_parameter(param, line, config_file): - - # If we're only targeting a particular game, check this is one of - # the ones we're targeting. - - if match_game and param.games and match_game not in param.games: - return - - # Is this documenting a command line parameter? - - match = re.search(r'(M_CheckParm(WithArgs)|M_ParmExists)?\s*\(\s*"(.*?)"', - line) - - if match: - param.name = match.group(3) - category = dict(categories)[param.category] - category.add_param(param) - return - - # Documenting a configuration file variable? - - match = re.search(r'CONFIG_VARIABLE_\S+\s*\(\s*(\S+?)\),', line) - - if match: - param.name = match.group(1) - config_file.add_variable(param) - return - - raise Exception(param.text) - -def process_file(filename): - - current_config_file = None - - f = io.open(filename, encoding='UTF-8') - - try: - param = None - waiting_for_checkparm = False - - for line in f: - line = line.rstrip() - - # Ignore empty lines - - if re.match(r'\s*$', line): - continue - - # Currently reading a doc comment? - - if param: - # End of doc comment - - if not re.match(r'\s*//', line): - waiting_for_checkparm = True - - # The first non-empty line after the documentation comment - # ends must contain the thing being documented. - - if waiting_for_checkparm: - add_parameter(param, line, current_config_file) - param = None - else: - # More documentation text - - munged_line = re.sub(r'\s*\/\/\s*', '', line, count=1) - munged_line = re.sub(r'\s*$', '', munged_line) - param.add_text(munged_line) - - # Check for start of a doc comment - - if re.search("//!", line): - match = re.search(r"@begin_config_file\s*(\S+)", line) - - if match: - # Beginning a configuration file - tagname = match.group(1) - current_config_file = ConfigFile(tagname) - config_files[tagname] = current_config_file - else: - # Start of a normal comment - param = Parameter() - waiting_for_checkparm = False - finally: - f.close() - -def process_files(path): - # Process all C source files. - - if os.path.isdir(path): - files = glob.glob(path + "/*.c") - - for filename in files: - process_file(filename) - else: - # Special case to allow a single file to be specified as a target - - process_file(path) - -def print_template(template_file, substs, content): - f = io.open(template_file, encoding='UTF-8') - - try: - for line in f: - match = INCLUDE_STATEMENT_RE.search(line) - if match: - filename = match.group(1) - filename = os.path.join(os.path.dirname(template_file), - filename) - print_template(filename, substs, content) - else: - line = line.replace("@content", content) - for k,v in substs.items(): - line = line.replace(k,v) - stdout(line.rstrip().encode('UTF-8') + b'\n') - finally: - f.close() - -def manpage_output(targets, substs, template_file): - - content = "" - - for t in targets: - content += t.manpage_output() - - content = content.replace("-", "\\-") - - print_template(template_file, substs, content) - -def wiki_output(targets, _, template): - read_wikipages() - - for t in targets: - stdout(t.wiki_output().encode('UTF-8') + b'\n') - -def markdown_output(targets, substs, template_file): - content = "" - - for t in targets: - content += t.markdown_output() + "\n" - - print_template(template_file, substs, content) - -def plaintext_output(targets, substs, template_file): - - content = "" - - for t in targets: - content += t.plaintext_output() + "\n" - - print_template(template_file, substs, content) - -def completion_output(targets, substs, template_file): - - content = "" - - for t in targets: - content += t.completion_output() + "\n" - - print_template(template_file, substs, content) - -def usage(): - print("Usage: %s [-V] [-c tag] [-g game] -n program_name -s package_name [ -z shortname ] ( -M | -m | -w | -p ) ..." \ - % sys.argv[0]) - print(" -c : Provide documentation for the specified configuration file") - print(" (matches the given tag name in the source file)") - print(" -s : Package name, e.g. Chocolate Doom (for substitution)") - print(" -z : Package short-name, e.g. Chocolate (for substitution)") - print(" -v : Package version, e.g. 7.0 (for substitution)") - print(" -n : Program name, e.g. chocolate (for substitution)") - print(" -M : Markdown output") - print(" -m : Manpage output") - print(" -w : Wikitext output") - print(" -p : Plaintext output") - print(" -b : Bash-Completion output") - print(" -V : Don't show Vanilla Doom options") - print(" -g : Only document options for specified game.") - sys.exit(0) - -# Parse command line - -opts, args = getopt.getopt(sys.argv[1:], "n:s:z:v:M:m:wp:b:c:g:V") - -output_function = None -template = None -doc_config_file = None -match_game = None -substs = {} - -for opt in opts: - if opt[0] == "-n": - substs["@PROGRAM_SPREFIX@"] = opt[1] - if opt[0] == "-s": - substs["@PACKAGE_NAME@"] = opt[1] - if opt[0] == "-z": - substs["@PACKAGE_SHORTNAME@"] = opt[1] - if opt[0] == "-v": - substs["@VERSION@"] = opt[1] - if opt[0] == "-m": - output_function = manpage_output - template = opt[1] - elif opt[0] == "-M": - output_function = markdown_output - template = opt[1] - elif opt[0] == "-w": - output_function = wiki_output - elif opt[0] == "-p": - output_function = plaintext_output - template = opt[1] - elif opt[0] == "-b": - output_function = completion_output - template = opt[1] - elif opt[0] == "-V": - show_vanilla_options = False - elif opt[0] == "-c": - doc_config_file = opt[1] - elif opt[0] == "-g": - match_game = opt[1] - substs["@GAME@"] = opt[1] - substs["@GAME_UPPER@"] = opt[1].title() - if "doom" == opt[1]: - substs["@CFGFILE@"] = "default.cfg" - else: - substs["@CFGFILE@"] = opt[1] + ".cfg" - -if output_function == None or len(args) < 1: - usage() -else: - # Process specified files - - for path in args: - process_files(path) - - # Build a list of things to document - if doc_config_file: - documentation_targets = [config_files[doc_config_file]] - else: - documentation_targets = [c for _, c in categories] - - # Generate the output - output_function(documentation_targets, substs, template) - diff --git a/games/NXDoom/man/doom.template b/games/NXDoom/man/doom.template deleted file mode 100644 index bbf1c62aafa..00000000000 --- a/games/NXDoom/man/doom.template +++ /dev/null @@ -1,45 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-doom 6 2018-01-09 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-doom \- historically compatible Doom engine -.SH SYNOPSIS -.B @PROGRAM_SPREFIX@\-doom -.RI [ options ] -.SH DESCRIPTION -.PP -@PACKAGE_SHORTNAME@ Doom is a port of Id Software's 1993 game -.I Doom -that is designed to behave as similarly to the original DOS version of -Doom as is possible. -@content -.SH IWAD SEARCH PATHS -@include iwad_paths.man -.SH ENVIRONMENT -This section describes environment variables that control -@PACKAGE_SHORTNAME@ Doom's behavior. -@include environ.man -.SH FILES -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/default.cfg -The main configuration file for @PACKAGE_NAME@. -See \fBdefault.cfg\fR(5). -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-doom.cfg -Extra configuration values that are specific to @PACKAGE_NAME@ and not -present in Vanilla Doom. -See \fB@PROGRAM_SPREFIX@\-doom.cfg\fR(5). -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-server\fR(6), -\fB@PROGRAM_SPREFIX@\-setup\fR(6), -\fB@PROGRAM_SPREFIX@\-heretic\fR(6), -\fB@PROGRAM_SPREFIX@\-hexen\fR(6), -\fB@PROGRAM_SPREFIX@\-strife\fR(6) -.SH AUTHOR -Chocolate Doom is written and maintained by Simon Howard. -It is based on the LinuxDoom source code, released by Id Software. -.SH COPYRIGHT -Copyright \(co id Software Inc. -Copyright \(co 2005-2016 Simon Howard. -.PP -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License . -There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/environ.man b/games/NXDoom/man/environ.man deleted file mode 100644 index 414f5037e66..00000000000 --- a/games/NXDoom/man/environ.man +++ /dev/null @@ -1,34 +0,0 @@ -.TP -.I DOOMWADDIR -.TQ -.I DOOMWADPATH -See section \(lqIWAD SEARCH PATHS\(rq above. -.TP -.I PCSOUND_DRIVER -When running in PC speaker sound effect mode, this environment variable -specifies a PC speaker driver to use for sound effect playback. -Valid options are -.RB \(lq Linux \(rq -for the Linux console mode driver, -.RB \(lq BSD \(rq -for the NetBSD/OpenBSD PC speaker driver, -and -.RB \(lq SDL \(rq -for SDL-based emulated PC speaker playback (using the digital output). -.TP -.I OPL_DRIVER -When using OPL MIDI playback, this environment variable specifies an -OPL backend driver to use. -Valid options are -.RB \(lq SDL \(rq -for an SDL-based software emulated OPL chip, -.RB \(lq Linux \(rq -for the Linux hardware OPL driver, -and -.RB \(lq OpenBSD \(rq -for the OpenBSD/NetBSD hardware OPL driver. -.IP -Generally speaking, a real hardware OPL chip sounds better than software -emulation; however, modern machines do not often include one. -If present, it may still require extra work to set up and elevated -security privileges to access. diff --git a/games/NXDoom/man/extra.cfg.template b/games/NXDoom/man/extra.cfg.template deleted file mode 100644 index de6f40666fe..00000000000 --- a/games/NXDoom/man/extra.cfg.template +++ /dev/null @@ -1,28 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-@GAME@.cfg 5 2024-01-23 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-@GAME@.cfg \- @PACKAGE_SHORTNAME@ @GAME_UPPER@ configuration file -.SH DESCRIPTION -.PP -\fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR -is a configuration file for \fB@PROGRAM_SPREFIX@\-@GAME@\fR(6). This file acts -as an auxiliary configuration file; the main configuration options -are stored in \fB@CFGFILE@\fR, which contains the same configuration -options as Vanilla @GAME_UPPER@ (for compatibility). \fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR -contains configuration options that are specific to @PACKAGE_SHORTNAME@\-@GAME_UPPER@ -only. -.PP -\fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR is normally stored in the user's home directory, -as \fI~/.local/share/@PROGRAM_SPREFIX@\-@GAME@/@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. The path can be -overridden using the \fBXDG_DATA_HOME\fR environment variable (see the XDG -Base Directory Specification). -.PP -The \fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) tool provides a simple to use front-end -for editing \fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. -.SH FILE FORMAT -.PP -The file format is the same as that used for \fB@CFGFILE@\fR(5). -@content -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6), -\fB@CFGFILE@\fR(5), -\fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) diff --git a/games/NXDoom/man/heretic.template b/games/NXDoom/man/heretic.template deleted file mode 100644 index 394af610436..00000000000 --- a/games/NXDoom/man/heretic.template +++ /dev/null @@ -1,47 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-heretic 6 2017-11-27 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-heretic \- historically compatible Heretic engine -.SH SYNOPSIS -.B @PROGRAM_SPREFIX@\-heretic -.RI [ options ] -.SH DESCRIPTION -.PP -@PACKAGE_SHORTNAME@ Heretic is a port of Raven Software's 1994 game -.I Heretic -that aims to behave as similar to the original DOS version of Heretic as -possible. -@content -.SH IWAD SEARCH PATHS -@include iwad_paths.man -.SH ENVIRONMENT -This section describes environment variables that control -@PACKAGE_SHORTNAME@ Heretic's behavior. -@include environ.man -.SH FILES -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/heretic.cfg -The main configuration file for @PACKAGE_SHORTNAME@ Heretic. -See \fBheretic.cfg\fR(5). -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-heretic.cfg -Extra configuration values that are specific to @PACKAGE_SHORTNAME@ Heretic and not -present in Vanilla Heretic. -See \fB@PROGRAM_SPREFIX@\-heretic.cfg\fR(5). -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-doom\fR(6), -\fB@PROGRAM_SPREFIX@\-hexen\fR(6), -\fB@PROGRAM_SPREFIX@\-server\fR(6), -\fB@PROGRAM_SPREFIX@\-setup\fR(6) -.SH AUTHOR -Chocolate Heretic is part of the Chocolate Doom project, written and -maintained by Simon Howard. -It is based on the Heretic source code, -released by Raven Software. -.SH COPYRIGHT -Copyright \(co id Software Inc. -Copyright \(co Raven Software Inc. -Copyright \(co 2005-2013 Simon Howard. -.PP -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License . -There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/hexen.template b/games/NXDoom/man/hexen.template deleted file mode 100644 index 22e900f017c..00000000000 --- a/games/NXDoom/man/hexen.template +++ /dev/null @@ -1,47 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-hexen 6 2017-11-27 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-hexen \- historically compatible Hexen engine -.SH SYNOPSIS -.B @PROGRAM_SPREFIX@\-hexen -.RI [ options ] -.SH DESCRIPTION -.PP -@PACKAGE_SHORTNAME@ Hexen is a port of Raven Software's 1995 game -.I Hexen -that aims to behave as similar to the original DOS version of Hexen as -possible. -@content -.SH IWAD SEARCH PATHS -@include iwad_paths.man -.SH ENVIRONMENT -This section describes environment variables that control -@PACKAGE_SHORTNAME@ Hexen's behavior. -@include environ.man -.SH FILES -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/hexen.cfg -The main configuration file for @PACKAGE_SHORTNAME@ Hexen. -See \fBhexen.cfg\fR(5). -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-hexen.cfg -Extra configuration values that are specific to @PACKAGE_SHORTNAME@ -Hexen and not present in Vanilla Hexen. -See \fB@PROGRAM_SPREFIX@\-hexen.cfg\fR(5). -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-doom\fR(6), -\fB@PROGRAM_SPREFIX@\-heretic\fR(6), -\fB@PROGRAM_SPREFIX@\-server\fR(6), -\fB@PROGRAM_SPREFIX@\-setup\fR(6) -.SH AUTHOR -Chocolate Hexen is part of the Chocolate Doom project, written and -maintained by Simon Howard. -It is based on the Hexen source code, -released by Raven Software. -.SH COPYRIGHT -Copyright \(co id Software Inc. -Copyright \(co Raven Software Inc. -Copyright \(co 2005-2013 Simon Howard. -.PP -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License . -There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/iwad_paths.man b/games/NXDoom/man/iwad_paths.man deleted file mode 100644 index 5b4268094ad..00000000000 --- a/games/NXDoom/man/iwad_paths.man +++ /dev/null @@ -1,73 +0,0 @@ -To play, an IWAD file is needed. -This is a large file containing all of the levels, graphics, -sound effects, music and other material that make up the game. -IWAD files are named according to the game; the standard names are: -.TP -.IR doom.wad ,\~\c -.IR doom1.wad ,\~\c -.IR doom2.wad ,\~\c -.IR tnt.wad ,\~\c -.I plutonia.wad -Doom, Doom II, Final Doom -.TP -.IR heretic.wad ,\~\c -.IR hexen.wad ,\~\c -.I strife.wad -Heretic, Hexen and Strife (commercial Doom engine games). -.TP -.IR hacx.wad ,\~\c -.I chex.wad -Hacx and Chex Quest - more obscure games based on the Doom engine. -.TP -.IR freedm.wad ,\~\c -.IR freedoom1.wad ,\~\c -.I freedoom2.wad -The Freedoom open content IWAD files. -.LP -The following directory paths are searched in order to find an IWAD: -.TP -Current working directory -Any IWAD files found in the current working directory will be used in -preference to IWADs found in any other directories. -.TP -.I DOOMWADDIR -This environment variable can be set to contain a path to a single -directory in which to look for IWAD files. -This environment variable is supported by most Doom source ports. -.TP -.I DOOMWADPATH -This environment variable, if set, can contain a colon-separated list of -directories in which to look for IWAD files, or alternatively full paths to -specific IWAD files. -.TP -.I $HOME/.local/share/games/doom -Writeable directory in the user's home directory. -The path can be overridden using the -.I \%XDG_DATA_HOME -environment variable (see the XDG Base Directory Specification). -.TP -.I /usr/local/share/doom -.TQ -.I /usr/local/share/games/doom -.TQ -.I /usr/share/doom -.TQ -.I /usr/share/games/doom -System-wide locations that can be accessed by all users. -The path -.I /usr/share/games/doom -is a standard path that is supported by most Doom source ports. -These paths can be overridden using the -.I \%XDG_DATA_DIRS -environment variable (see the XDG Base Directory Specification). -.LP -The above can be overridden on a one-time basis by using the -.B \-iwad -command line parameter to provide the path to an IWAD file to use.This -parameter can also be used to specify the name of a particular IWAD to use -from one of the above paths. -For example, -.RB \(lq "\-iwad doom.wad" \(rq -will search the above paths for the file -.I doom.wad -to use. diff --git a/games/NXDoom/man/server.template b/games/NXDoom/man/server.template deleted file mode 100644 index 7ce2a3b3708..00000000000 --- a/games/NXDoom/man/server.template +++ /dev/null @@ -1,55 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-server 6 2018-01-15 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-server \- dedicated server for @PROGRAM_SPREFIX@\-doom -.SH SYNOPSIS -.B @PROGRAM_SPREFIX@\-server -.RI [ options ] -.SH DESCRIPTION -.PP -@PACKAGE_NAME@ is a modern Doom engine designed to behave -as similarly to the original Doom game as is possible. -.PP -.I \%@PROGRAM_SPREFIX@\-server -is a dedicated server for @PACKAGE_SHORTNAME@. -It is equivalent to running -\fB@PROGRAM_SPREFIX@-doom\fR(6) -with the -.B \%\-dedicated -option. -.PP -Game options are not specified to the server, which merely acts to -retransmit data between players in the game; parameters for the -game should be specified by the first player to connect to the server, -who is designated the controlling player. -.SH OPTIONS -.TP -.B \-ignoreversion -Ignore version mismatches between the server and the client. -Using this option may cause game desyncs to occur, -or differences in protocol may mean the netgame will simply not function -at all. -.TP -.BI \-port\~ n -Use UDP port -.I n -for communications instead of the default (2342). -.TP -.B \-privateserver -Don't register with the global master server. -.TP -.BI \-servername\~ name -Specify a name for the server. -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@-doom\fR(6), -\fB@PROGRAM_SPREFIX@-setup\fR(6) -.SH AUTHOR -Chocolate Doom is written and maintained by Simon Howard. -.PP -This manual was written by Jonathan Dowland. -.SH COPYRIGHT -Copyright \(co id Software Inc. -Copyright \(co 2005-8 Simon Howard. -.PP -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License . -There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/setup.template b/games/NXDoom/man/setup.template deleted file mode 100644 index 1fd057c66bc..00000000000 --- a/games/NXDoom/man/setup.template +++ /dev/null @@ -1,46 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-@GAME@-setup 6 2017-11-30 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-@GAME@-setup \- configuration tool for @PROGRAM_SPREFIX@\-@GAME@ -.SH SYNOPSIS -.B @PROGRAM_SPREFIX@\-@GAME@-setup -.RI [ options ] -.SH DESCRIPTION -.PP -@PACKAGE_SHORTNAME@ @GAME_UPPER@ is a modern @GAME_UPPER@ engine -designed to behave as similarly to the original @GAME_UPPER@ game as is -possible. -.PP -.I @PROGRAM_SPREFIX@\-@GAME@-setup -is a tool for configuring @PACKAGE_SHORTNAME@ @GAME_UPPER@. -It provides a menu-based interface for the display, joystick, keyboard, -mouse, sound and compatibility settings. -.PP -.I @PROGRAM_SPREFIX@\-@GAME@-setup -can also be used to start and join network games. -.PP -.SH OPTIONS -.TP -.BI \-config\~ file -Load configuration from the specified file, -instead of -.IR @CFGFILE@ . -.TP -.BI \-extraconfig\~ file -Load extra configuration from the specified file, -instead of -.IR @PROGRAM_SPREFIX@\-@GAME@.cfg . -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6), -\fBdefault.cfg\fR(5), -\fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR(5) -.SH AUTHOR -Chocolate Doom is written and maintained by Simon Howard. -.PP -This manual was written by Jonathan Dowland. -.SH COPYRIGHT -Copyright \(co id Software Inc. -Copyright \(co 2005-8 Simon Howard. -.PP -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License . -There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/simplecpp b/games/NXDoom/man/simplecpp deleted file mode 100755 index 7749c269a71..00000000000 --- a/games/NXDoom/man/simplecpp +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 -# Contributors to the Freedoom project. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the freedoom project nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# -# simple cpp-style preprocessor -# -# Understands most features of the C preprocessor, including: -# #if .. #elif .. #else .. #endif -# - with expressions -# #ifdef -# #define -# #include -# - -import collections -import io -import sys -import re - -debug = False -defines = collections.defaultdict(lambda: False) - -command_re = re.compile(r"\#(\w+)(\s+(.*))?") -include_re = re.compile(r"\s*\"(.*)\"\s*") -define_re = re.compile(r"\s*(\S+)\s*(.*?)\s*$") - -def debug_msg(message): - if debug: - sys.stderr.write(message) - -# Parse command line options - -def parse_cmdline(): - for arg in sys.argv[1:]: - if not arg.startswith("-D"): - continue - - name = arg[2:] - if '=' in name: - name, value = name.split('=', 1) - else: - value = True - - defines[name] = value - -def parse_stream(stream): - result = read_block(stream, False) - - if result is not None: - raise Exception("Mismatched #if in '%s'" % stream.name) - -def parse_file(filename): - f = io.open(filename, encoding='UTF-8') - - try: - parse_stream(f) - finally: - f.close() - -# Evaluate an expression using Python's eval() function. - -def eval_expr(expr): - expr = expr.replace("||", " or ") \ - .replace("&&", " and ") \ - .replace("!", "not ") - - code = compile(expr, "", "eval") - result = eval(code, {}, defines) - return result - -# #include - -def cmd_include(arg): - # Extract the filename - - match = include_re.match(arg) - - if not match: - raise Exception("Invalid 'include' command") - - filename = match.group(1) - - # Open the file and process it - - parse_file(filename) - -# #define - -def cmd_define(arg): - match = define_re.match(arg) - name = match.group(1) - value = match.group(2) - if value == '': - value = True - - defines[name] = value - -# #undef - -def cmd_undef(arg): - if arg in defines: - del defines[arg] - -# #ifdef/#ifndef - -def cmd_ifdef(arg, command, stream, ignore): - - # Get the define name - - debug_msg("%s %s >\n" % (command, arg)) - - # Should we ignore the contents of this block? - - sub_ignore = not eval_expr(arg) - - if "n" in command: - sub_ignore = not sub_ignore - - # Parse the block - - result, newarg = read_block(stream, ignore or sub_ignore) - - debug_msg("%s %s < (%s)\n" % (command, arg, result)) - - # There may be a second "else" block to parse: - - if result == "else": - debug_msg("%s %s else >\n" % (command, arg)) - result, arg = read_block(stream, ignore or (not sub_ignore)) - debug_msg("%s %s else < (%s)\n" % (command, arg, result)) - - if result == "elif": - debug_msg("%s %s elif %s>\n" % (command, arg, newarg)) - cmd_ifdef(newarg, "if", stream, ignore or (not sub_ignore)) - result = "endif" - - # Should end in an endif: - - if result != "endif": - raise Exception("'if' block did not end in an 'endif'") - -commands = { - "include" : cmd_include, - "define" : cmd_define, - "undef" : cmd_undef, - "if" : cmd_ifdef, - "ifdef" : cmd_ifdef, - "ifn" : cmd_ifdef, - "ifndef" : cmd_ifdef, -} - -# Recursive block reading function -# if 'ignore' argument is 1, contents are ignored - -def read_block(stream, ignore): - - for line in stream: - - # Remove newline - - line = line[0:-1] - - # Check if this line has a command - - match = command_re.match(line) - - if match: - command = match.group(1) - arg = match.group(3) - - if command in ("else", "elif", "endif"): - return (command, arg) - elif command not in commands: - raise Exception("Unknown command: '%s'" % \ - command) - - # Get the callback function. - - func = commands[command] - - # Invoke the callback function. #ifdef commands - # are a special case and need extra arguments. - # Other commands are only executed if we are not - # ignoring this block. - - if func == cmd_ifdef: - cmd_ifdef(arg, command=command, - stream=stream, - ignore=ignore) - elif not ignore: - func(arg) - else: - if not ignore: - for key, value in defines.items(): - if isinstance(value, str): - line = line.replace(key, value) - print(line) - -parse_cmdline() -parse_stream(sys.stdin) - diff --git a/games/NXDoom/man/strife.template b/games/NXDoom/man/strife.template deleted file mode 100644 index 51defaecba5..00000000000 --- a/games/NXDoom/man/strife.template +++ /dev/null @@ -1,91 +0,0 @@ -.TH @PROGRAM_SPREFIX@\-strife 6 2018-01-15 "@PACKAGE_NAME@ @VERSION@" -.SH NAME -@PROGRAM_SPREFIX@\-strife \- historically compatible Strife engine -.SH SYNOPSIS -.B @PROGRAM_SPREFIX@\-strife -.RI [ options ] -.SH DESCRIPTION -.PP -@PACKAGE_SHORTNAME@ Strife is an accurate and complete recreation of -Rogue Entertainment's -.IR "Strife: Quest for the Sigil" . -It was created through -more than two years of reverse engineering effort with the blessings -of the original programmers of the game; -see section \(lqHISTORY\(rq below. -@content -.SH IWAD SEARCH PATHS -@include iwad_paths.man -.SH ENVIRONMENT -This section describes environment variables that control -@PACKAGE_SHORTNAME@ Strife's behavior. -@include environ.man -.SH FILES -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/strife.cfg -The main configuration file for @PACKAGE_SHORTNAME@ Strife. -See \fBstrife.cfg\fR(5). -.TP -.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-strife.cfg -Extra configuration values that are specific to @PACKAGE_SHORTNAME@ -Strife and not present in Vanilla Strife. -See \fB@PROGRAM_SPREFIX@\-strife.cfg\fR(5). -.SH SEE ALSO -\fB@PROGRAM_SPREFIX@\-doom\fR(6), -\fB@PROGRAM_SPREFIX@\-server\fR(6), -\fB@PROGRAM_SPREFIX@\-setup\fR(6) -.SH HISTORY -The source code for Strife was lost, which means, unlike the code for -all the other commercial games using the Doom engine, it cannot be -released. -The only access we have to the code is the binary executable file. -Reverse engineering tools were employed to disassemble and decompile the -executables, which were cross-referenced against the Linux Doom and -DOS Heretic sources and painstakingly combed over multiple times, -instruction by instruction, to ensure that the resulting -Chocolate-Doom-based executable is as close as possible to the original. -.SH LEGALITY -Reverse engineering is a protected activity so long as the original code -is not used directly in the product. -Due to the vast amount of information lost through the process of -compilation, and the need to refactor large portions of code in order to -eliminate non-portable idioms or to adapt them properly to Chocolate -Doom's framework, the resulting code behaves the same, but is not the -.I same -code. -.PP -In addition, James Monroe and John Carmack have both stated that they -have no objections to the project. -Because they are the original authors of the code, and neither Rogue nor -their publisher, Velocity, Inc., exist any longer as legal entities, -this is effectively legal permission. -.SH BUGS -@PACKAGE_SHORTNAME@ Strife is almost, but not entirely perfect, in -recreating the behavior of Vanilla Strife. -Help us by reporting any discrepancies you might notice between this -executable and the vanilla DOS program. -.PP -However, do -.I not -report any glitch that you can replicate in the vanilla EXE as a bug. -The point of @PACKAGE_SHORTNAME@ Strife, like Chocolate Doom before it, -is to be as bug-compatible with the original game as possible. -Also be aware that some glitches are impossible to compatibly recreate, -and wherever this is the case, @PACKAGE_SHORTNAME@ Strife has erred on -the side of not crashing the program, for example by initializing -pointers to -.I NULL -rather than using them without setting a value first. -.SH AUTHORS -Chocolate Strife is part of the Chocolate Doom project. -It was reverse engineered from the DOS versions of Strife by James Haley -and Samuel Villarreal. -Chocolate Doom was written and maintained by Simon Howard, and is based -on the LinuxDoom source code released by Id Software. -.SH COPYRIGHT -Copyright \(co id Software Inc. -Copyright \(co 2005-2013 Simon Howard, James Haley, Samuel Villarreal. -.PP -This is free software. You may redistribute copies of it under the terms of -the GNU General Public License . -There is NO WARRANTY, to the extent permitted by law. diff --git a/games/NXDoom/man/wikipages b/games/NXDoom/man/wikipages deleted file mode 100644 index 429c47dde06..00000000000 --- a/games/NXDoom/man/wikipages +++ /dev/null @@ -1,7 +0,0 @@ -# This is a list of wiki pages to automatically link to when generating -# wikitext output. -Dehacked -Doom 1.91 -Merging -Multiplayer -Three screen mode diff --git a/games/NXDoom/opl/.gitignore b/games/NXDoom/opl/.gitignore deleted file mode 100644 index 8aac4e778ff..00000000000 --- a/games/NXDoom/opl/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile.in -Makefile -.deps -libopl.a -*.rc -tags -TAGS diff --git a/games/NXDoom/opl/CMakeLists.txt b/games/NXDoom/opl/CMakeLists.txt deleted file mode 100644 index 289ca279d49..00000000000 --- a/games/NXDoom/opl/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -add_library(opl STATIC - opl_internal.h - opl.c opl.h - opl_linux.c - opl_obsd.c - opl_queue.c opl_queue.h - opl_sdl.c - opl_timer.c opl_timer.h - opl_win32.c - ioperm_sys.c ioperm_sys.h - opl3.c opl3.h) -target_include_directories(opl - INTERFACE "." - PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") -if (DEFINED EMSCRIPTEN) - if(ENABLE_SDL2_MIXER) - set_target_properties(opl PROPERTIES COMPILE_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") - set_target_properties(opl PROPERTIES LINK_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") - else() - set_target_properties(opl PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") - set_target_properties(opl PROPERTIES LINK_FLAGS "-s USE_SDL=2") - endif() -else() - target_link_libraries(opl SDL2::SDL2) - if(ENABLE_SDL2_MIXER) - target_link_libraries(opl SDL2_mixer::SDL2_mixer) - endif() -endif() diff --git a/games/NXDoom/opl/Makefile.am b/games/NXDoom/opl/Makefile.am deleted file mode 100644 index 430953e3348..00000000000 --- a/games/NXDoom/opl/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ - -AM_CFLAGS=@SDLMIXER_CFLAGS@ - -EXTRA_DIST=CMakeLists.txt - -SUBDIRS = . examples - -noinst_LIBRARIES=libopl.a - -libopl_a_SOURCES = \ - opl_internal.h \ - opl.c opl.h \ - opl_linux.c \ - opl_obsd.c \ - opl_queue.c opl_queue.h \ - opl_sdl.c \ - opl_timer.c opl_timer.h \ - opl_win32.c \ - ioperm_sys.c ioperm_sys.h \ - opl3.c opl3.h - diff --git a/games/NXDoom/opl/examples/.gitignore b/games/NXDoom/opl/examples/.gitignore deleted file mode 100644 index 4d589c73824..00000000000 --- a/games/NXDoom/opl/examples/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile.in -Makefile -.deps -droplay -*.exe -tags -TAGS diff --git a/games/NXDoom/opl/examples/Makefile.am b/games/NXDoom/opl/examples/Makefile.am deleted file mode 100644 index 9afcd513c74..00000000000 --- a/games/NXDoom/opl/examples/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ - -AM_CFLAGS = -I$(top_srcdir)/opl - -noinst_PROGRAMS=droplay - -droplay_LDADD = ../libopl.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ -droplay_SOURCES = droplay.c - diff --git a/games/NXDoom/opl/examples/droplay.c b/games/NXDoom/opl/examples/droplay.c deleted file mode 100644 index 16e10c3c9b2..00000000000 --- a/games/NXDoom/opl/examples/droplay.c +++ /dev/null @@ -1,210 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Demonstration program for OPL library to play back DRO -// format files. -// - - -#include -#include -#include - -#include "SDL.h" - -#include "opl.h" - -#define HEADER_STRING "DBRAWOPL" -#define ADLIB_PORT 0x388 - -void WriteReg(unsigned int reg, unsigned int val) -{ - int i; - - // This was recorded from an OPL2, but we are probably playing - // back on an OPL3, so we need to enable the original OPL2 - // channels. Doom does this already, but other games don't. - - if ((reg & 0xf0) == OPL_REGS_FEEDBACK) - { - val |= 0x30; - } - - OPL_WritePort(OPL_REGISTER_PORT, reg); - - for (i=0; i<6; ++i) - { - OPL_ReadPort(OPL_REGISTER_PORT); - } - - OPL_WritePort(OPL_DATA_PORT, val); - - for (i=0; i<35; ++i) - { - OPL_ReadPort(OPL_REGISTER_PORT); - } -} - -void ClearAllRegs(void) -{ - int i; - - for (i=0; i<=0xff; ++i) - { - WriteReg(i, 0x00); - } -} - -void Init(void) -{ - if (SDL_Init(SDL_INIT_TIMER) < 0) - { - fprintf(stderr, "Unable to initialise SDL timer\n"); - exit(-1); - } - - if (!OPL_Init(ADLIB_PORT)) - { - fprintf(stderr, "Unable to initialise OPL layer\n"); - exit(-1); - } -} - -void Shutdown(void) -{ - OPL_Shutdown(); -} - -struct timer_data -{ - int running; - FILE *fstream; -}; - -void TimerCallback(void *data) -{ - struct timer_data *timer_data = data; - int delay; - - if (!timer_data->running) - { - return; - } - - // Read data until we must make a delay. - - for (;;) - { - int reg, val; - - // End of file? - - if (feof(timer_data->fstream)) - { - timer_data->running = 0; - return; - } - - reg = fgetc(timer_data->fstream); - val = fgetc(timer_data->fstream); - - // Register value of 0 or 1 indicates a delay. - - if (reg == 0x00) - { - delay = val; - break; - } - else if (reg == 0x01) - { - val |= (fgetc(timer_data->fstream) << 8); - delay = val; - break; - } - else - { - WriteReg(reg, val); - } - } - - // Schedule the next timer callback. - - OPL_SetCallback(delay * OPL_MS, TimerCallback, timer_data); -} - -void PlayFile(char *filename) -{ - struct timer_data timer_data; - int running; - char buf[8]; - - timer_data.fstream = fopen(filename, "rb"); - - if (timer_data.fstream == NULL) - { - fprintf(stderr, "Failed to open %s\n", filename); - exit(-1); - } - - if (fread(buf, 1, 8, timer_data.fstream) < 8) - { - fprintf(stderr, "failed to read raw OPL header\n"); - exit(-1); - } - - if (strncmp(buf, HEADER_STRING, 8) != 0) - { - fprintf(stderr, "Raw OPL header not found\n"); - exit(-1); - } - - fseek(timer_data.fstream, 28, SEEK_SET); - timer_data.running = 1; - - // Start callback loop sequence. - - OPL_SetCallback(0, TimerCallback, &timer_data); - - // Sleep until the playback finishes. - - do - { - OPL_Lock(); - running = timer_data.running; - OPL_Unlock(); - - SDL_Delay(100 * OPL_MS); - } while (running); - - fclose(timer_data.fstream); -} - -int main(int argc, char *argv[]) -{ - if (argc < 2) - { - printf("Usage: %s \n", argv[0]); - exit(-1); - } - - Init(); - - PlayFile(argv[1]); - - ClearAllRegs(); - Shutdown(); - - return 0; -} - diff --git a/games/NXDoom/opl/ioperm_sys.c b/games/NXDoom/opl/ioperm_sys.c deleted file mode 100644 index 6d0c63a5c9c..00000000000 --- a/games/NXDoom/opl/ioperm_sys.c +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright(C) 2002, 2003 Marcel Telka -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Interface to the ioperm.sys driver, based on code from the -// Cygwin ioperm library. -// - -#ifdef _WIN32 - -#include - -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include - -#include "ioperm_sys.h" - -#define IOPERM_FILE L"\\\\.\\ioperm" - -#define IOCTL_IOPERM \ - CTL_CODE(FILE_DEVICE_UNKNOWN, 0xA00, METHOD_BUFFERED, FILE_ANY_ACCESS) - -struct ioperm_data -{ - unsigned long from; - unsigned long num; - int turn_on; -}; - -// Function pointers for advapi32.dll. This DLL does not exist on -// Windows 9x, so they are dynamically loaded from the DLL at runtime. - -// haleyjd 09/09/10: Moved calling conventions into ()'s - -static SC_HANDLE (WINAPI *MyOpenSCManagerW)(wchar_t *lpMachineName, - wchar_t *lpDatabaseName, - DWORD dwDesiredAccess) = NULL; -static SC_HANDLE (WINAPI *MyCreateServiceW)(SC_HANDLE hSCManager, - wchar_t *lpServiceName, - wchar_t *lpDisplayName, - DWORD dwDesiredAccess, - DWORD dwServiceType, - DWORD dwStartType, - DWORD dwErrorControl, - wchar_t *lpBinaryPathName, - wchar_t *lpLoadOrderGroup, - LPDWORD lpdwTagId, - wchar_t *lpDependencies, - wchar_t *lpServiceStartName, - wchar_t *lpPassword); -static SC_HANDLE (WINAPI *MyOpenServiceW)(SC_HANDLE hSCManager, - wchar_t *lpServiceName, - DWORD dwDesiredAccess); -static BOOL (WINAPI *MyStartServiceW)(SC_HANDLE hService, - DWORD dwNumServiceArgs, - wchar_t **lpServiceArgVectors); -static BOOL (WINAPI *MyControlService)(SC_HANDLE hService, - DWORD dwControl, - LPSERVICE_STATUS lpServiceStatus); -static BOOL (WINAPI *MyCloseServiceHandle)(SC_HANDLE hSCObject); -static BOOL (WINAPI *MyDeleteService)(SC_HANDLE hService); - -static struct -{ - char *name; - void **fn; -} dll_functions[] = { - { "OpenSCManagerW", (void **) &MyOpenSCManagerW }, - { "CreateServiceW", (void **) &MyCreateServiceW }, - { "OpenServiceW", (void **) &MyOpenServiceW }, - { "StartServiceW", (void **) &MyStartServiceW }, - { "ControlService", (void **) &MyControlService }, - { "CloseServiceHandle", (void **) &MyCloseServiceHandle }, - { "DeleteService", (void **) &MyDeleteService }, -}; - -// Globals - -static SC_HANDLE scm = NULL; -static SC_HANDLE svc = NULL; -static int service_was_created = 0; -static int service_was_started = 0; - -static int LoadLibraryPointers(void) -{ - HMODULE dll; - int i; - - // Already loaded? - - if (MyOpenSCManagerW != NULL) - { - return 1; - } - - dll = LoadLibraryW(L"advapi32.dll"); - - if (dll == NULL) - { - fprintf(stderr, "LoadLibraryPointers: Failed to open advapi32.dll\n"); - return 0; - } - - for (i = 0; i < sizeof(dll_functions) / sizeof(*dll_functions); ++i) - { - *dll_functions[i].fn = GetProcAddress(dll, dll_functions[i].name); - - if (*dll_functions[i].fn == NULL) - { - fprintf(stderr, "LoadLibraryPointers: Failed to get address " - "for '%s'\n", dll_functions[i].name); - return 0; - } - } - - return 1; -} - -int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on) -{ - HANDLE h; - struct ioperm_data ioperm_data; - DWORD BytesReturned; - BOOL r; - - h = CreateFileW(IOPERM_FILE, GENERIC_READ, 0, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (h == INVALID_HANDLE_VALUE) - { - errno = ENODEV; - return -1; - } - - ioperm_data.from = from; - ioperm_data.num = num; - ioperm_data.turn_on = turn_on; - - r = DeviceIoControl(h, IOCTL_IOPERM, - &ioperm_data, sizeof ioperm_data, - NULL, 0, - &BytesReturned, NULL); - - if (!r) - { - errno = EPERM; - } - - CloseHandle(h); - - return r != 0; -} - -// Load ioperm.sys driver. -// Returns 1 for success, 0 for failure. -// Remember to call IOperm_UninstallDriver to uninstall the driver later. - -int IOperm_InstallDriver(void) -{ - wchar_t driver_path[MAX_PATH]; - int error; - int result = 1; - - if (!LoadLibraryPointers()) - { - return 0; - } - - scm = MyOpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); - - if (scm == NULL) - { - error = GetLastError(); - fprintf(stderr, "IOperm_InstallDriver: OpenSCManager failed (%i).\n", - error); - return 0; - } - - // Get the full path to the driver file. - - GetFullPathNameW(L"ioperm.sys", MAX_PATH, driver_path, NULL); - - // Create the service. - - svc = MyCreateServiceW(scm, - L"ioperm", - L"ioperm support for Cygwin driver", - SERVICE_ALL_ACCESS, - SERVICE_KERNEL_DRIVER, - SERVICE_AUTO_START, - SERVICE_ERROR_NORMAL, - driver_path, - NULL, - NULL, - NULL, - NULL, - NULL); - - if (svc == NULL) - { - error = GetLastError(); - - if (error != ERROR_SERVICE_EXISTS) - { - fprintf(stderr, - "IOperm_InstallDriver: Failed to create service (%i).\n", - error); - } - else - { - svc = MyOpenServiceW(scm, L"ioperm", SERVICE_ALL_ACCESS); - - if (svc == NULL) - { - error = GetLastError(); - - fprintf(stderr, - "IOperm_InstallDriver: Failed to open service (%i).\n", - error); - } - } - - if (svc == NULL) - { - MyCloseServiceHandle(scm); - return 0; - } - } - else - { - service_was_created = 1; - } - - // Start the service. If the service already existed, it might have - // already been running as well. - - if (!MyStartServiceW(svc, 0, NULL)) - { - error = GetLastError(); - - if (error != ERROR_SERVICE_ALREADY_RUNNING) - { - fprintf(stderr, "IOperm_InstallDriver: Failed to start service (%i).\n", - error); - - result = 0; - } - else - { - printf("IOperm_InstallDriver: ioperm driver already running.\n"); - } - } - else - { - printf("IOperm_InstallDriver: ioperm driver installed.\n"); - service_was_started = 1; - } - - // If we failed to start the driver running, we need to clean up - // before finishing. - - if (result == 0) - { - IOperm_UninstallDriver(); - } - - return result; -} - -int IOperm_UninstallDriver(void) -{ - SERVICE_STATUS stat; - int result = 1; - int error; - - // If we started the service, stop it. - - if (service_was_started) - { - if (!MyControlService(svc, SERVICE_CONTROL_STOP, &stat)) - { - error = GetLastError(); - - if (error == ERROR_SERVICE_NOT_ACTIVE) - { - fprintf(stderr, - "IOperm_UninstallDriver: Service not active? (%i)\n", - error); - } - else - { - fprintf(stderr, - "IOperm_UninstallDriver: Failed to stop service (%i).\n", - error); - result = 0; - } - } - } - - // If we created the service, delete it. - - if (service_was_created) - { - if (!MyDeleteService(svc)) - { - error = GetLastError(); - - fprintf(stderr, - "IOperm_UninstallDriver: DeleteService failed (%i).\n", - error); - - result = 0; - } - else if (service_was_started) - { - printf("IOperm_UnInstallDriver: ioperm driver uninstalled.\n"); - } - } - - // Close handles. - - if (svc != NULL) - { - MyCloseServiceHandle(svc); - svc = NULL; - } - - if (scm != NULL) - { - MyCloseServiceHandle(scm); - scm = NULL; - } - - service_was_created = 0; - service_was_started = 0; - - return result; -} - -#endif /* #ifndef _WIN32 */ - diff --git a/games/NXDoom/opl/ioperm_sys.h b/games/NXDoom/opl/ioperm_sys.h deleted file mode 100644 index 1a27c3f122f..00000000000 --- a/games/NXDoom/opl/ioperm_sys.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright(C) 2002, 2003 Marcel Telka -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Interface to the ioperm.sys driver, based on code from the -// Cygwin ioperm library. -// - -#ifndef IOPERM_SYS_H -#define IOPERM_SYS_H - -int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on); -int IOperm_InstallDriver(void); -int IOperm_UninstallDriver(void); - -#endif /* #ifndef IOPERM_SYS_H */ - diff --git a/games/NXDoom/opl/opl.c b/games/NXDoom/opl/opl.c deleted file mode 100644 index e99821cbb16..00000000000 --- a/games/NXDoom/opl/opl.c +++ /dev/null @@ -1,530 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL interface. -// - -#include "config.h" - -#include -#include -#include - -#include "SDL.h" - -#include "opl.h" -#include "opl_internal.h" - -//#define OPL_DEBUG_TRACE - -#ifdef EMSCRIPTEN -#include -#endif - - -static opl_driver_t *drivers[] = -{ -#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) - &opl_linux_driver, -#endif -#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64) - &opl_openbsd_driver, -#endif -#ifdef _WIN32 - &opl_win32_driver, -#endif -#ifndef DISABLE_SDL2MIXER - &opl_sdl_driver, -#endif // DISABLE_SDL2MIXER - NULL -}; - -static opl_driver_t *driver = NULL; -static int init_stage_reg_writes = 1; - -unsigned int opl_sample_rate = 22050; - -// -// Init/shutdown code. -// - -// Initialize the specified driver and detect an OPL chip. Returns -// true if an OPL is detected. - -static opl_init_result_t InitDriver(opl_driver_t *_driver, - unsigned int port_base) -{ - opl_init_result_t result1, result2; - - // Initialize the driver. - - if (!_driver->init_func(port_base)) - { - return OPL_INIT_NONE; - } - - // The driver was initialized okay, so we now have somewhere - // to write to. It doesn't mean there's an OPL chip there, - // though. Perform the detection sequence to make sure. - // (it's done twice, like how Doom does it). - - driver = _driver; - init_stage_reg_writes = 1; - - result1 = OPL_Detect(); - result2 = OPL_Detect(); - if (result1 == OPL_INIT_NONE || result2 == OPL_INIT_NONE) - { - printf("OPL_Init: No OPL detected using '%s' driver.\n", _driver->name); - _driver->shutdown_func(); - driver = NULL; - return OPL_INIT_NONE; - } - - init_stage_reg_writes = 0; - - printf("OPL_Init: Using driver '%s'.\n", driver->name); - - return result2; -} - -// Find a driver automatically by trying each in the list. - -static opl_init_result_t AutoSelectDriver(unsigned int port_base) -{ - int i; - opl_init_result_t result; - - for (i = 0; drivers[i] != NULL; ++i) - { - result = InitDriver(drivers[i], port_base); - if (result != OPL_INIT_NONE) - { - return result; - } - } - - printf("OPL_Init: Failed to find a working driver.\n"); - - return OPL_INIT_NONE; -} - -// Initialize the OPL library. Return value indicates type of OPL chip -// detected, if any. - -opl_init_result_t OPL_Init(unsigned int port_base) -{ - char *driver_name; - int i; - int result; - - driver_name = getenv("OPL_DRIVER"); - - if (driver_name != NULL) - { - // Search the list until we find the driver with this name. - - for (i=0; drivers[i] != NULL; ++i) - { - if (!strcmp(driver_name, drivers[i]->name)) - { - result = InitDriver(drivers[i], port_base); - if (result) - { - return result; - } - else - { - printf("OPL_Init: Failed to initialize " - "driver: '%s'.\n", driver_name); - return OPL_INIT_NONE; - } - } - } - - printf("OPL_Init: unknown driver: '%s'.\n", driver_name); - - return OPL_INIT_NONE; - } - else - { - return AutoSelectDriver(port_base); - } -} - -// Shut down the OPL library. - -void OPL_Shutdown(void) -{ - if (driver != NULL) - { - driver->shutdown_func(); - driver = NULL; - } -} - -// Set the sample rate used for software OPL emulation. - -void OPL_SetSampleRate(unsigned int rate) -{ - opl_sample_rate = rate; -} - -void OPL_WritePort(opl_port_t port, unsigned int value) -{ - if (driver != NULL) - { -#ifdef OPL_DEBUG_TRACE - printf("OPL_write: %i, %x\n", port, value); - fflush(stdout); -#endif - driver->write_port_func(port, value); - } -} - -unsigned int OPL_ReadPort(opl_port_t port) -{ - if (driver != NULL) - { - unsigned int result; - -#ifdef OPL_DEBUG_TRACE - printf("OPL_read: %i...\n", port); - fflush(stdout); -#endif - - result = driver->read_port_func(port); - -#ifdef OPL_DEBUG_TRACE - printf("OPL_read: %i -> %x\n", port, result); - fflush(stdout); -#endif - - return result; - } - else - { - return 0; - } -} - -// -// Higher-level functions, based on the lower-level functions above -// (register write, etc). -// - -unsigned int OPL_ReadStatus(void) -{ - return OPL_ReadPort(OPL_REGISTER_PORT); -} - -// Write an OPL register value - -void OPL_WriteRegister(int reg, int value) -{ - int i; - - if (reg & 0x100) - { - OPL_WritePort(OPL_REGISTER_PORT_OPL3, reg); - } - else - { - OPL_WritePort(OPL_REGISTER_PORT, reg); - } - - // For timing, read the register port six times after writing the - // register number to cause the appropriate delay - - for (i=0; i<6; ++i) - { - // An oddity of the Doom OPL code: at startup initialization, - // the spacing here is performed by reading from the register - // port; after initialization, the data port is read, instead. - - if (init_stage_reg_writes) - { - OPL_ReadPort(OPL_REGISTER_PORT); - } - else - { - OPL_ReadPort(OPL_DATA_PORT); - } - } - - OPL_WritePort(OPL_DATA_PORT, value); - - // Read the register port 24 times after writing the value to - // cause the appropriate delay - - for (i=0; i<24; ++i) - { - OPL_ReadStatus(); - } -} - -// Detect the presence of an OPL chip - -opl_init_result_t OPL_Detect(void) -{ - int result1, result2; - int i; - - // Reset both timers: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); - - // Enable interrupts: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); - - // Read status - result1 = OPL_ReadStatus(); - - // Set timer: - OPL_WriteRegister(OPL_REG_TIMER1, 0xff); - - // Start timer 1: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x21); - - // Wait for 80 microseconds - // This is how Doom does it: - - for (i=0; i<200; ++i) - { - OPL_ReadStatus(); - } - - OPL_Delay(1 * OPL_MS); - - // Read status - result2 = OPL_ReadStatus(); - - // Reset both timers: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); - - // Enable interrupts: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); - - if ((result1 & 0xe0) == 0x00 && (result2 & 0xe0) == 0xc0) - { - result1 = OPL_ReadPort(OPL_REGISTER_PORT); - result2 = OPL_ReadPort(OPL_REGISTER_PORT_OPL3); - if (result1 == 0x00) - { - return OPL_INIT_OPL3; - } - else - { - return OPL_INIT_OPL2; - } - } - else - { - return OPL_INIT_NONE; - } -} - -// Initialize registers on startup - -void OPL_InitRegisters(int opl3) -{ - int r; - - // Initialize level registers - - for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) - { - OPL_WriteRegister(r, 0x3f); - } - - // Initialize other registers - // These two loops write to registers that actually don't exist, - // but this is what Doom does ... - // Similarly, the <= is also intenational. - - for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) - { - OPL_WriteRegister(r, 0x00); - } - - // More registers ... - - for (r=1; r < OPL_REGS_LEVEL; ++r) - { - OPL_WriteRegister(r, 0x00); - } - - // Re-initialize the low registers: - - // Reset both timers and enable interrupts: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); - - // "Allow FM chips to control the waveform of each operator": - OPL_WriteRegister(OPL_REG_WAVEFORM_ENABLE, 0x20); - - if (opl3) - { - OPL_WriteRegister(OPL_REG_NEW, 0x01); - - // Initialize level registers - - for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) - { - OPL_WriteRegister(r | 0x100, 0x3f); - } - - // Initialize other registers - // These two loops write to registers that actually don't exist, - // but this is what Doom does ... - // Similarly, the <= is also intenational. - - for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) - { - OPL_WriteRegister(r | 0x100, 0x00); - } - - // More registers ... - - for (r=1; r < OPL_REGS_LEVEL; ++r) - { - OPL_WriteRegister(r | 0x100, 0x00); - } - } - - // Keyboard split point on (?) - OPL_WriteRegister(OPL_REG_FM_MODE, 0x40); - - if (opl3) - { - OPL_WriteRegister(OPL_REG_NEW, 0x01); - } -} - -// -// Timer functions. -// - -void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data) -{ - if (driver != NULL) - { - driver->set_callback_func(us, callback, data); - } -} - -void OPL_ClearCallbacks(void) -{ - if (driver != NULL) - { - driver->clear_callbacks_func(); - } -} - -void OPL_Lock(void) -{ - if (driver != NULL) - { - driver->lock_func(); - } -} - -void OPL_Unlock(void) -{ - if (driver != NULL) - { - driver->unlock_func(); - } -} - -typedef struct -{ - int finished; - - SDL_mutex *mutex; - SDL_cond *cond; -} delay_data_t; - -static void DelayCallback(void *_delay_data) -{ - delay_data_t *delay_data = _delay_data; - - SDL_LockMutex(delay_data->mutex); - delay_data->finished = 1; - - SDL_CondSignal(delay_data->cond); - - SDL_UnlockMutex(delay_data->mutex); -} - -// Delay for specified number of microseconds after OPL subsystem is initialized - -void OPL_Delay(uint64_t us) -{ - delay_data_t delay_data; - - if (driver == NULL) - { - return; - } - - // Create a callback that will signal this thread after the - // specified time. - - // Note that this is not just a simple time-based delay, it will ensure - // that the OPL system is initialized and the queue has begun processing - // before releasing the mutex lock - - delay_data.finished = 0; - delay_data.mutex = SDL_CreateMutex(); - delay_data.cond = SDL_CreateCond(); - - OPL_SetCallback(us, DelayCallback, &delay_data); - - // Wait until the callback is invoked. - - SDL_LockMutex(delay_data.mutex); - - while (!delay_data.finished) - { - SDL_CondWait(delay_data.cond, delay_data.mutex); -#ifdef EMSCRIPTEN - // Use async sleep to avoid locking browser main thread - emscripten_sleep(us / 1000); -#endif - } - - SDL_UnlockMutex(delay_data.mutex); - - // Clean up. - - SDL_DestroyMutex(delay_data.mutex); - SDL_DestroyCond(delay_data.cond); -} - -void OPL_SetPaused(int paused) -{ - if (driver != NULL) - { - driver->set_paused_func(paused); - } -} - -void OPL_AdjustCallbacks(float value) -{ - if (driver != NULL) - { - driver->adjust_callbacks_func(value); - } -} - diff --git a/games/NXDoom/opl/opl.h b/games/NXDoom/opl/opl.h deleted file mode 100644 index deaa442dde2..00000000000 --- a/games/NXDoom/opl/opl.h +++ /dev/null @@ -1,153 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL interface. -// - - -#ifndef OPL_OPL_H -#define OPL_OPL_H - -#include - -typedef void (*opl_callback_t)(void *data); - -// Result from OPL_Init(), indicating what type of OPL chip was detected, -// if any. -typedef enum -{ - OPL_INIT_NONE, - OPL_INIT_OPL2, - OPL_INIT_OPL3, -} opl_init_result_t; - -typedef enum -{ - OPL_REGISTER_PORT = 0, - OPL_DATA_PORT = 1, - OPL_REGISTER_PORT_OPL3 = 2 -} opl_port_t; - -#define OPL_NUM_OPERATORS 21 -#define OPL_NUM_VOICES 9 - -#define OPL_REG_WAVEFORM_ENABLE 0x01 -#define OPL_REG_TIMER1 0x02 -#define OPL_REG_TIMER2 0x03 -#define OPL_REG_TIMER_CTRL 0x04 -#define OPL_REG_FM_MODE 0x08 -#define OPL_REG_NEW 0x105 - -// Operator registers (21 of each): - -#define OPL_REGS_TREMOLO 0x20 -#define OPL_REGS_LEVEL 0x40 -#define OPL_REGS_ATTACK 0x60 -#define OPL_REGS_SUSTAIN 0x80 -#define OPL_REGS_WAVEFORM 0xE0 - -// Voice registers (9 of each): - -#define OPL_REGS_FREQ_1 0xA0 -#define OPL_REGS_FREQ_2 0xB0 -#define OPL_REGS_FEEDBACK 0xC0 - -// Times - -#define OPL_SECOND ((uint64_t) 1000 * 1000) -#define OPL_MS ((uint64_t) 1000) -#define OPL_US ((uint64_t) 1) - -// -// Low-level functions. -// - -// Initialize the OPL subsystem. - -opl_init_result_t OPL_Init(unsigned int port_base); - -// Shut down the OPL subsystem. - -void OPL_Shutdown(void); - -// Set the sample rate used for software emulation. - -void OPL_SetSampleRate(unsigned int rate); - -// Write to one of the OPL I/O ports: - -void OPL_WritePort(opl_port_t port, unsigned int value); - -// Read from one of the OPL I/O ports: - -unsigned int OPL_ReadPort(opl_port_t port); - -// -// Higher-level functions. -// - -// Read the cuurrent status byte of the OPL chip. - -unsigned int OPL_ReadStatus(void); - -// Write to an OPL register. - -void OPL_WriteRegister(int reg, int value); - -// Perform a detection sequence to determine that an -// OPL chip is present. - -opl_init_result_t OPL_Detect(void); - -// Initialize all registers, performed on startup. - -void OPL_InitRegisters(int opl3); - -// -// Timer callback functions. -// - -// Set a timer callback. After the specified number of microseconds -// have elapsed, the callback will be invoked. - -void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data); - -// Adjust callback times by the specified factor. For example, a value of -// 0.5 will halve all remaining times. - -void OPL_AdjustCallbacks(float factor); - -// Clear all OPL callbacks that have been set. - -void OPL_ClearCallbacks(void); - -// Begin critical section, during which, OPL callbacks will not be -// invoked. - -void OPL_Lock(void); - -// End critical section. - -void OPL_Unlock(void); - -// Block until the specified number of microseconds have elapsed. - -void OPL_Delay(uint64_t us); - -// Pause the OPL callbacks. - -void OPL_SetPaused(int paused); - -#endif - diff --git a/games/NXDoom/opl/opl3.c b/games/NXDoom/opl/opl3.c deleted file mode 100644 index f5bca4c4e04..00000000000 --- a/games/NXDoom/opl/opl3.c +++ /dev/null @@ -1,1377 +0,0 @@ -// -// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) -// -// 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. -// -// -// Nuked OPL3 emulator. -// Thanks: -// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): -// Feedback and Rhythm part calculation information. -// forums.submarine.org.uk(carbon14, opl3): -// Tremolo and phase generator calculation information. -// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): -// OPL2 ROMs. -// siliconpr0n.org(John McMaster, digshadow): -// YMF262 and VRC VII decaps and die shots. -// -// version: 1.8 -// - -#include -#include -#include -#include "opl3.h" - -#define RSM_FRAC 10 - -// Channel types - -enum { - ch_2op = 0, - ch_4op = 1, - ch_4op2 = 2, - ch_drum = 3 -}; - -// Envelope key types - -enum { - egk_norm = 0x01, - egk_drum = 0x02 -}; - - -// -// logsin table -// - -static const Bit16u logsinrom[256] = { - 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, - 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365, - 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, - 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261, - 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, - 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd, - 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, - 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166, - 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, - 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118, - 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, - 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db, - 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, - 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9, - 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, - 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081, - 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, - 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060, - 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, - 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045, - 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, - 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f, - 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, - 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e, - 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, - 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011, - 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, - 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007, - 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, - 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002, - 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 -}; - -// -// exp table -// - -static const Bit16u exprom[256] = { - 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, - 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9, - 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f, - 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756, - 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e, - 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706, - 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0, - 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba, - 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695, - 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671, - 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e, - 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b, - 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609, - 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8, - 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8, - 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8, - 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589, - 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b, - 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d, - 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530, - 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514, - 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8, - 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc, - 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2, - 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8, - 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e, - 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475, - 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d, - 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445, - 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d, - 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416, - 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 -}; - -// -// freq mult table multiplied by 2 -// -// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 -// - -static const Bit8u mt[16] = { - 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 -}; - -// -// ksl table -// - -static const Bit8u kslrom[16] = { - 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 -}; - -static const Bit8u kslshift[4] = { - 8, 1, 2, 0 -}; - -// -// envelope generator constants -// - -static const Bit8u eg_incstep[4][4] = { - { 0, 0, 0, 0 }, - { 1, 0, 0, 0 }, - { 1, 0, 1, 0 }, - { 1, 1, 1, 0 } -}; - -// -// address decoding -// - -static const Bit8s ad_slot[0x20] = { - 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, - 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static const Bit8u ch_slot[18] = { - 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 -}; - -// -// Envelope generator -// - -typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope); -typedef void(*envelope_genfunc)(opl3_slot *slott); - -static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) -{ - if (level > 0x1fff) - { - level = 0x1fff; - } - return (exprom[level & 0xff] << 1) >> (level >> 8); -} - -static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - Bit16u neg = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - neg = 0xffff; - } - if (phase & 0x100) - { - out = logsinrom[(phase & 0xff) ^ 0xff]; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; -} - -static Bit16s OPL3_EnvelopeCalcSin1(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - out = 0x1000; - } - else if (phase & 0x100) - { - out = logsinrom[(phase & 0xff) ^ 0xff]; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin2(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x100) - { - out = logsinrom[(phase & 0xff) ^ 0xff]; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin3(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x100) - { - out = 0x1000; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - Bit16u neg = 0; - phase &= 0x3ff; - if ((phase & 0x300) == 0x100) - { - neg = 0xffff; - } - if (phase & 0x200) - { - out = 0x1000; - } - else if (phase & 0x80) - { - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; - } - else - { - out = logsinrom[(phase << 1) & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; -} - -static Bit16s OPL3_EnvelopeCalcSin5(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - out = 0x1000; - } - else if (phase & 0x80) - { - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; - } - else - { - out = logsinrom[(phase << 1) & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope) -{ - Bit16u neg = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - neg = 0xffff; - } - return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg; -} - -static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - Bit16u neg = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - neg = 0xffff; - phase = (phase & 0x1ff) ^ 0x1ff; - } - out = phase << 3; - return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; -} - -static const envelope_sinfunc envelope_sin[8] = { - OPL3_EnvelopeCalcSin0, - OPL3_EnvelopeCalcSin1, - OPL3_EnvelopeCalcSin2, - OPL3_EnvelopeCalcSin3, - OPL3_EnvelopeCalcSin4, - OPL3_EnvelopeCalcSin5, - OPL3_EnvelopeCalcSin6, - OPL3_EnvelopeCalcSin7 -}; - -enum envelope_gen_num -{ - envelope_gen_num_attack = 0, - envelope_gen_num_decay = 1, - envelope_gen_num_sustain = 2, - envelope_gen_num_release = 3 -}; - -static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) -{ - Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) - - ((0x08 - slot->channel->block) << 5); - if (ksl < 0) - { - ksl = 0; - } - slot->eg_ksl = (Bit8u)ksl; -} - -static void OPL3_EnvelopeCalc(opl3_slot *slot) -{ - Bit8u nonzero; - Bit8u rate; - Bit8u rate_hi; - Bit8u rate_lo; - Bit8u reg_rate = 0; - Bit8u ks; - Bit8u eg_shift, shift; - Bit16u eg_rout; - Bit16s eg_inc; - Bit8u eg_off; - Bit8u reset = 0; - slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) - + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; - if (slot->key && slot->eg_gen == envelope_gen_num_release) - { - reset = 1; - reg_rate = slot->reg_ar; - } - else - { - switch (slot->eg_gen) - { - case envelope_gen_num_attack: - reg_rate = slot->reg_ar; - break; - case envelope_gen_num_decay: - reg_rate = slot->reg_dr; - break; - case envelope_gen_num_sustain: - if (!slot->reg_type) - { - reg_rate = slot->reg_rr; - } - break; - case envelope_gen_num_release: - reg_rate = slot->reg_rr; - break; - } - } - slot->pg_reset = reset; - ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); - nonzero = (reg_rate != 0); - rate = ks + (reg_rate << 2); - rate_hi = rate >> 2; - rate_lo = rate & 0x03; - if (rate_hi & 0x10) - { - rate_hi = 0x0f; - } - eg_shift = rate_hi + slot->chip->eg_add; - shift = 0; - if (nonzero) - { - if (rate_hi < 12) - { - if (slot->chip->eg_state) - { - switch (eg_shift) - { - case 12: - shift = 1; - break; - case 13: - shift = (rate_lo >> 1) & 0x01; - break; - case 14: - shift = rate_lo & 0x01; - break; - default: - break; - } - } - } - else - { - shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; - if (shift & 0x04) - { - shift = 0x03; - } - if (!shift) - { - shift = slot->chip->eg_state; - } - } - } - eg_rout = slot->eg_rout; - eg_inc = 0; - eg_off = 0; - // Instant attack - if (reset && rate_hi == 0x0f) - { - eg_rout = 0x00; - } - // Envelope off - if ((slot->eg_rout & 0x1f8) == 0x1f8) - { - eg_off = 1; - } - if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) - { - eg_rout = 0x1ff; - } - switch (slot->eg_gen) - { - case envelope_gen_num_attack: - if (!slot->eg_rout) - { - slot->eg_gen = envelope_gen_num_decay; - } - else if (slot->key && shift > 0 && rate_hi != 0x0f) - { - eg_inc = ((~slot->eg_rout) << shift) >> 4; - } - break; - case envelope_gen_num_decay: - if ((slot->eg_rout >> 4) == slot->reg_sl) - { - slot->eg_gen = envelope_gen_num_sustain; - } - else if (!eg_off && !reset && shift > 0) - { - eg_inc = 1 << (shift - 1); - } - break; - case envelope_gen_num_sustain: - case envelope_gen_num_release: - if (!eg_off && !reset && shift > 0) - { - eg_inc = 1 << (shift - 1); - } - break; - } - slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; - // Key off - if (reset) - { - slot->eg_gen = envelope_gen_num_attack; - } - if (!slot->key) - { - slot->eg_gen = envelope_gen_num_release; - } -} - -static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) -{ - slot->key |= type; -} - -static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) -{ - slot->key &= ~type; -} - -// -// Phase Generator -// - -static void OPL3_PhaseGenerate(opl3_slot *slot) -{ - opl3_chip *chip; - Bit16u f_num; - Bit32u basefreq; - Bit8u rm_xor, n_bit; - Bit32u noise; - Bit16u phase; - - chip = slot->chip; - f_num = slot->channel->f_num; - if (slot->reg_vib) - { - Bit8s range; - Bit8u vibpos; - - range = (f_num >> 7) & 7; - vibpos = slot->chip->vibpos; - - if (!(vibpos & 3)) - { - range = 0; - } - else if (vibpos & 1) - { - range >>= 1; - } - range >>= slot->chip->vibshift; - - if (vibpos & 4) - { - range = -range; - } - f_num += range; - } - basefreq = (f_num << slot->channel->block) >> 1; - phase = (Bit16u)(slot->pg_phase >> 9); - if (slot->pg_reset) - { - slot->pg_phase = 0; - } - slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; - // Rhythm mode - noise = chip->noise; - slot->pg_phase_out = phase; - if (slot->slot_num == 13) // hh - { - chip->rm_hh_bit2 = (phase >> 2) & 1; - chip->rm_hh_bit3 = (phase >> 3) & 1; - chip->rm_hh_bit7 = (phase >> 7) & 1; - chip->rm_hh_bit8 = (phase >> 8) & 1; - } - if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc - { - chip->rm_tc_bit3 = (phase >> 3) & 1; - chip->rm_tc_bit5 = (phase >> 5) & 1; - } - if (chip->rhy & 0x20) - { - rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) - | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) - | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); - switch (slot->slot_num) - { - case 13: // hh - slot->pg_phase_out = rm_xor << 9; - if (rm_xor ^ (noise & 1)) - { - slot->pg_phase_out |= 0xd0; - } - else - { - slot->pg_phase_out |= 0x34; - } - break; - case 16: // sd - slot->pg_phase_out = (chip->rm_hh_bit8 << 9) - | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); - break; - case 17: // tc - slot->pg_phase_out = (rm_xor << 9) | 0x80; - break; - default: - break; - } - } - n_bit = ((noise >> 14) ^ noise) & 0x01; - chip->noise = (noise >> 1) | (n_bit << 22); -} - -// -// Slot -// - -static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) -{ - if ((data >> 7) & 0x01) - { - slot->trem = &slot->chip->tremolo; - } - else - { - slot->trem = (Bit8u*)&slot->chip->zeromod; - } - slot->reg_vib = (data >> 6) & 0x01; - slot->reg_type = (data >> 5) & 0x01; - slot->reg_ksr = (data >> 4) & 0x01; - slot->reg_mult = data & 0x0f; -} - -static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) -{ - slot->reg_ksl = (data >> 6) & 0x03; - slot->reg_tl = data & 0x3f; - OPL3_EnvelopeUpdateKSL(slot); -} - -static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) -{ - slot->reg_ar = (data >> 4) & 0x0f; - slot->reg_dr = data & 0x0f; -} - -static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) -{ - slot->reg_sl = (data >> 4) & 0x0f; - if (slot->reg_sl == 0x0f) - { - slot->reg_sl = 0x1f; - } - slot->reg_rr = data & 0x0f; -} - -static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) -{ - slot->reg_wf = data & 0x07; - if (slot->chip->newm == 0x00) - { - slot->reg_wf &= 0x03; - } -} - -static void OPL3_SlotGenerate(opl3_slot *slot) -{ - slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); -} - -static void OPL3_SlotCalcFB(opl3_slot *slot) -{ - if (slot->channel->fb != 0x00) - { - slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb); - } - else - { - slot->fbmod = 0; - } - slot->prout = slot->out; -} - -// -// Channel -// - -static void OPL3_ChannelSetupAlg(opl3_channel *channel); - -static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) -{ - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; - Bit8u chnum; - - chip->rhy = data & 0x3f; - if (chip->rhy & 0x20) - { - channel6 = &chip->channel[6]; - channel7 = &chip->channel[7]; - channel8 = &chip->channel[8]; - channel6->out[0] = &channel6->slots[1]->out; - channel6->out[1] = &channel6->slots[1]->out; - channel6->out[2] = &chip->zeromod; - channel6->out[3] = &chip->zeromod; - channel7->out[0] = &channel7->slots[0]->out; - channel7->out[1] = &channel7->slots[0]->out; - channel7->out[2] = &channel7->slots[1]->out; - channel7->out[3] = &channel7->slots[1]->out; - channel8->out[0] = &channel8->slots[0]->out; - channel8->out[1] = &channel8->slots[0]->out; - channel8->out[2] = &channel8->slots[1]->out; - channel8->out[3] = &channel8->slots[1]->out; - for (chnum = 6; chnum < 9; chnum++) - { - chip->channel[chnum].chtype = ch_drum; - } - OPL3_ChannelSetupAlg(channel6); - OPL3_ChannelSetupAlg(channel7); - OPL3_ChannelSetupAlg(channel8); - //hh - if (chip->rhy & 0x01) - { - OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum); - } - //tc - if (chip->rhy & 0x02) - { - OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum); - } - //tom - if (chip->rhy & 0x04) - { - OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum); - } - //sd - if (chip->rhy & 0x08) - { - OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum); - } - //bd - if (chip->rhy & 0x10) - { - OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum); - } - } - else - { - for (chnum = 6; chnum < 9; chnum++) - { - chip->channel[chnum].chtype = ch_2op; - OPL3_ChannelSetupAlg(&chip->channel[chnum]); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[0], egk_drum); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[1], egk_drum); - } - } -} - -static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) -{ - if (channel->chip->newm && channel->chtype == ch_4op2) - { - return; - } - channel->f_num = (channel->f_num & 0x300) | data; - channel->ksv = (channel->block << 1) - | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); - if (channel->chip->newm && channel->chtype == ch_4op) - { - channel->pair->f_num = channel->f_num; - channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - } -} - -static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) -{ - if (channel->chip->newm && channel->chtype == ch_4op2) - { - return; - } - channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8); - channel->block = (data >> 2) & 0x07; - channel->ksv = (channel->block << 1) - | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); - if (channel->chip->newm && channel->chtype == ch_4op) - { - channel->pair->f_num = channel->f_num; - channel->pair->block = channel->block; - channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - } -} - -static void OPL3_ChannelSetupAlg(opl3_channel *channel) -{ - if (channel->chtype == ch_drum) - { - if (channel->ch_num == 7 || channel->ch_num == 8) - { - channel->slots[0]->mod = &channel->chip->zeromod; - channel->slots[1]->mod = &channel->chip->zeromod; - return; - } - switch (channel->alg & 0x01) - { - case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; - break; - case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->chip->zeromod; - break; - } - return; - } - if (channel->alg & 0x08) - { - return; - } - if (channel->alg & 0x04) - { - channel->pair->out[0] = &channel->chip->zeromod; - channel->pair->out[1] = &channel->chip->zeromod; - channel->pair->out[2] = &channel->chip->zeromod; - channel->pair->out[3] = &channel->chip->zeromod; - switch (channel->alg & 0x03) - { - case 0x00: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; - channel->out[1] = &channel->chip->zeromod; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x01: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->chip->zeromod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[1]->out; - channel->out[1] = &channel->slots[1]->out; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x02: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->chip->zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x03: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->chip->zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->chip->zeromod; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[0]->out; - channel->out[2] = &channel->slots[1]->out; - channel->out[3] = &channel->chip->zeromod; - break; - } - } - else - { - switch (channel->alg & 0x01) - { - case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; - channel->out[1] = &channel->chip->zeromod; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->chip->zeromod; - channel->out[0] = &channel->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - } - } -} - -static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) -{ - channel->fb = (data & 0x0e) >> 1; - channel->con = data & 0x01; - channel->alg = channel->con; - if (channel->chip->newm) - { - if (channel->chtype == ch_4op) - { - channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con); - channel->alg = 0x08; - OPL3_ChannelSetupAlg(channel->pair); - } - else if (channel->chtype == ch_4op2) - { - channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con); - channel->pair->alg = 0x08; - OPL3_ChannelSetupAlg(channel); - } - else - { - OPL3_ChannelSetupAlg(channel); - } - } - else - { - OPL3_ChannelSetupAlg(channel); - } - if (channel->chip->newm) - { - channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; - channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; - } - else - { - channel->cha = channel->chb = (Bit16u)~0; - } -} - -static void OPL3_ChannelKeyOn(opl3_channel *channel) -{ - if (channel->chip->newm) - { - if (channel->chtype == ch_4op) - { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm); - } - else if (channel->chtype == ch_2op || channel->chtype == ch_drum) - { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - } - } - else - { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - } -} - -static void OPL3_ChannelKeyOff(opl3_channel *channel) -{ - if (channel->chip->newm) - { - if (channel->chtype == ch_4op) - { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm); - } - else if (channel->chtype == ch_2op || channel->chtype == ch_drum) - { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - } - } - else - { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - } -} - -static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data) -{ - Bit8u bit; - Bit8u chnum; - for (bit = 0; bit < 6; bit++) - { - chnum = bit; - if (bit >= 3) - { - chnum += 9 - 3; - } - if ((data >> bit) & 0x01) - { - chip->channel[chnum].chtype = ch_4op; - chip->channel[chnum + 3].chtype = ch_4op2; - } - else - { - chip->channel[chnum].chtype = ch_2op; - chip->channel[chnum + 3].chtype = ch_2op; - } - } -} - -static Bit16s OPL3_ClipSample(Bit32s sample) -{ - if (sample > 32767) - { - sample = 32767; - } - else if (sample < -32768) - { - sample = -32768; - } - return (Bit16s)sample; -} - -void OPL3_Generate(opl3_chip *chip, Bit16s *buf) -{ - Bit8u ii; - Bit8u jj; - Bit16s accm; - Bit8u shift = 0; - - buf[1] = OPL3_ClipSample(chip->mixbuff[1]); - - for (ii = 0; ii < 15; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); - } - - chip->mixbuff[0] = 0; - for (ii = 0; ii < 18; ii++) - { - accm = 0; - for (jj = 0; jj < 4; jj++) - { - accm += *chip->channel[ii].out[jj]; - } - chip->mixbuff[0] += (Bit16s)(accm & chip->channel[ii].cha); - } - - for (ii = 15; ii < 18; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); - } - - buf[0] = OPL3_ClipSample(chip->mixbuff[0]); - - for (ii = 18; ii < 33; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); - } - - chip->mixbuff[1] = 0; - for (ii = 0; ii < 18; ii++) - { - accm = 0; - for (jj = 0; jj < 4; jj++) - { - accm += *chip->channel[ii].out[jj]; - } - chip->mixbuff[1] += (Bit16s)(accm & chip->channel[ii].chb); - } - - for (ii = 33; ii < 36; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); - } - - if ((chip->timer & 0x3f) == 0x3f) - { - chip->tremolopos = (chip->tremolopos + 1) % 210; - } - if (chip->tremolopos < 105) - { - chip->tremolo = chip->tremolopos >> chip->tremoloshift; - } - else - { - chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift; - } - - if ((chip->timer & 0x3ff) == 0x3ff) - { - chip->vibpos = (chip->vibpos + 1) & 7; - } - - chip->timer++; - - chip->eg_add = 0; - if (chip->eg_timer) - { - while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) - { - shift++; - } - if (shift > 12) - { - chip->eg_add = 0; - } - else - { - chip->eg_add = shift + 1; - } - } - - if (chip->eg_timerrem || chip->eg_state) - { - if (chip->eg_timer == 0xfffffffff) - { - chip->eg_timer = 0; - chip->eg_timerrem = 1; - } - else - { - chip->eg_timer++; - chip->eg_timerrem = 0; - } - } - - chip->eg_state ^= 1; - - while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) - { - if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200)) - { - break; - } - chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; - OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, - chip->writebuf[chip->writebuf_cur].data); - chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; - } - chip->writebuf_samplecnt++; -} - -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) -{ - while (chip->samplecnt >= chip->rateratio) - { - chip->oldsamples[0] = chip->samples[0]; - chip->oldsamples[1] = chip->samples[1]; - OPL3_Generate(chip, chip->samples); - chip->samplecnt -= chip->rateratio; - } - buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) - + chip->samples[0] * chip->samplecnt) / chip->rateratio); - buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) - + chip->samples[1] * chip->samplecnt) / chip->rateratio); - chip->samplecnt += 1 << RSM_FRAC; -} - -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) -{ - Bit8u slotnum; - Bit8u channum; - - memset(chip, 0, sizeof(opl3_chip)); - for (slotnum = 0; slotnum < 36; slotnum++) - { - chip->slot[slotnum].chip = chip; - chip->slot[slotnum].mod = &chip->zeromod; - chip->slot[slotnum].eg_rout = 0x1ff; - chip->slot[slotnum].eg_out = 0x1ff; - chip->slot[slotnum].eg_gen = envelope_gen_num_release; - chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod; - chip->slot[slotnum].slot_num = slotnum; - } - for (channum = 0; channum < 18; channum++) - { - chip->channel[channum].slots[0] = &chip->slot[ch_slot[channum]]; - chip->channel[channum].slots[1] = &chip->slot[ch_slot[channum] + 3]; - chip->slot[ch_slot[channum]].channel = &chip->channel[channum]; - chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum]; - if ((channum % 9) < 3) - { - chip->channel[channum].pair = &chip->channel[channum + 3]; - } - else if ((channum % 9) < 6) - { - chip->channel[channum].pair = &chip->channel[channum - 3]; - } - chip->channel[channum].chip = chip; - chip->channel[channum].out[0] = &chip->zeromod; - chip->channel[channum].out[1] = &chip->zeromod; - chip->channel[channum].out[2] = &chip->zeromod; - chip->channel[channum].out[3] = &chip->zeromod; - chip->channel[channum].chtype = ch_2op; - chip->channel[channum].cha = 0xffff; - chip->channel[channum].chb = 0xffff; - chip->channel[channum].ch_num = channum; - OPL3_ChannelSetupAlg(&chip->channel[channum]); - } - chip->noise = 1; - chip->rateratio = (samplerate << RSM_FRAC) / 49716; - chip->tremoloshift = 4; - chip->vibshift = 1; -} - -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) -{ - Bit8u high = (reg >> 8) & 0x01; - Bit8u regm = reg & 0xff; - switch (regm & 0xf0) - { - case 0x00: - if (high) - { - switch (regm & 0x0f) - { - case 0x04: - OPL3_ChannelSet4Op(chip, v); - break; - case 0x05: - chip->newm = v & 0x01; - break; - } - } - else - { - switch (regm & 0x0f) - { - case 0x08: - chip->nts = (v >> 6) & 0x01; - break; - } - } - break; - case 0x20: - case 0x30: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0x40: - case 0x50: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0x60: - case 0x70: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0x80: - case 0x90: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0xe0: - case 0xf0: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0xa0: - if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v); - } - break; - case 0xb0: - if (regm == 0xbd && !high) - { - chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2; - chip->vibshift = ((v >> 6) & 0x01) ^ 1; - OPL3_ChannelUpdateRhythm(chip, v); - } - else if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v); - if (v & 0x20) - { - OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]); - } - else - { - OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]); - } - } - break; - case 0xc0: - if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v); - } - break; - } -} - -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) -{ - Bit64u time1, time2; - - if (chip->writebuf[chip->writebuf_last].reg & 0x200) - { - OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, - chip->writebuf[chip->writebuf_last].data); - - chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; - chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; - } - - chip->writebuf[chip->writebuf_last].reg = reg | 0x200; - chip->writebuf[chip->writebuf_last].data = v; - time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; - time2 = chip->writebuf_samplecnt; - - if (time1 < time2) - { - time1 = time2; - } - - chip->writebuf[chip->writebuf_last].time = time1; - chip->writebuf_lasttime = time1; - chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; -} - -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) -{ - Bit32u i; - - for(i = 0; i < numsamples; i++) - { - OPL3_GenerateResampled(chip, sndptr); - sndptr += 2; - } -} diff --git a/games/NXDoom/opl/opl3.h b/games/NXDoom/opl/opl3.h deleted file mode 100644 index 2a64037a5ab..00000000000 --- a/games/NXDoom/opl/opl3.h +++ /dev/null @@ -1,150 +0,0 @@ -// -// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT) -// -// 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. -// -// -// Nuked OPL3 emulator. -// Thanks: -// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): -// Feedback and Rhythm part calculation information. -// forums.submarine.org.uk(carbon14, opl3): -// Tremolo and phase generator calculation information. -// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): -// OPL2 ROMs. -// siliconpr0n.org(John McMaster, digshadow): -// YMF262 and VRC VII decaps and die shots. -// -// version: 1.8 -// - -#ifndef OPL_OPL3_H -#define OPL_OPL3_H - -#include - -#define OPL_WRITEBUF_SIZE 1024 -#define OPL_WRITEBUF_DELAY 2 - -typedef uintptr_t Bitu; -typedef intptr_t Bits; -typedef uint64_t Bit64u; -typedef int64_t Bit64s; -typedef uint32_t Bit32u; -typedef int32_t Bit32s; -typedef uint16_t Bit16u; -typedef int16_t Bit16s; -typedef uint8_t Bit8u; -typedef int8_t Bit8s; - -typedef struct _opl3_slot opl3_slot; -typedef struct _opl3_channel opl3_channel; -typedef struct _opl3_chip opl3_chip; - -struct _opl3_slot { - opl3_channel *channel; - opl3_chip *chip; - Bit16s out; - Bit16s fbmod; - Bit16s *mod; - Bit16s prout; - Bit16s eg_rout; - Bit16s eg_out; - Bit8u eg_inc; - Bit8u eg_gen; - Bit8u eg_rate; - Bit8u eg_ksl; - Bit8u *trem; - Bit8u reg_vib; - Bit8u reg_type; - Bit8u reg_ksr; - Bit8u reg_mult; - Bit8u reg_ksl; - Bit8u reg_tl; - Bit8u reg_ar; - Bit8u reg_dr; - Bit8u reg_sl; - Bit8u reg_rr; - Bit8u reg_wf; - Bit8u key; - Bit32u pg_reset; - Bit32u pg_phase; - Bit16u pg_phase_out; - Bit8u slot_num; -}; - -struct _opl3_channel { - opl3_slot *slots[2]; - opl3_channel *pair; - opl3_chip *chip; - Bit16s *out[4]; - Bit8u chtype; - Bit16u f_num; - Bit8u block; - Bit8u fb; - Bit8u con; - Bit8u alg; - Bit8u ksv; - Bit16u cha, chb; - Bit8u ch_num; -}; - -typedef struct _opl3_writebuf { - Bit64u time; - Bit16u reg; - Bit8u data; -} opl3_writebuf; - -struct _opl3_chip { - opl3_channel channel[18]; - opl3_slot slot[36]; - Bit16u timer; - Bit64u eg_timer; - Bit8u eg_timerrem; - Bit8u eg_state; - Bit8u eg_add; - Bit8u newm; - Bit8u nts; - Bit8u rhy; - Bit8u vibpos; - Bit8u vibshift; - Bit8u tremolo; - Bit8u tremolopos; - Bit8u tremoloshift; - Bit32u noise; - Bit16s zeromod; - Bit32s mixbuff[2]; - Bit8u rm_hh_bit2; - Bit8u rm_hh_bit3; - Bit8u rm_hh_bit7; - Bit8u rm_hh_bit8; - Bit8u rm_tc_bit3; - Bit8u rm_tc_bit5; - //OPL3L - Bit32s rateratio; - Bit32s samplecnt; - Bit16s oldsamples[2]; - Bit16s samples[2]; - - Bit64u writebuf_samplecnt; - Bit32u writebuf_cur; - Bit32u writebuf_last; - Bit64u writebuf_lasttime; - opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; -}; - -void OPL3_Generate(opl3_chip *chip, Bit16s *buf); -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf); -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate); -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); -#endif diff --git a/games/NXDoom/opl/opl_internal.h b/games/NXDoom/opl/opl_internal.h deleted file mode 100644 index 68fd0b82f19..00000000000 --- a/games/NXDoom/opl/opl_internal.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL internal interface. -// - - -#ifndef OPL_INTERNAL_H -#define OPL_INTERNAL_H - -#include "opl.h" - -typedef int (*opl_init_func)(unsigned int port_base); -typedef void (*opl_shutdown_func)(void); -typedef unsigned int (*opl_read_port_func)(opl_port_t port); -typedef void (*opl_write_port_func)(opl_port_t port, unsigned int value); -typedef void (*opl_set_callback_func)(uint64_t us, - opl_callback_t callback, - void *data); -typedef void (*opl_clear_callbacks_func)(void); -typedef void (*opl_lock_func)(void); -typedef void (*opl_unlock_func)(void); -typedef void (*opl_set_paused_func)(int paused); -typedef void (*opl_adjust_callbacks_func)(float value); - -typedef struct -{ - const char *name; - - opl_init_func init_func; - opl_shutdown_func shutdown_func; - opl_read_port_func read_port_func; - opl_write_port_func write_port_func; - opl_set_callback_func set_callback_func; - opl_clear_callbacks_func clear_callbacks_func; - opl_lock_func lock_func; - opl_unlock_func unlock_func; - opl_set_paused_func set_paused_func; - opl_adjust_callbacks_func adjust_callbacks_func; -} opl_driver_t; - -// Sample rate to use when doing software emulation. - -extern unsigned int opl_sample_rate; - - -#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) -extern opl_driver_t opl_linux_driver; -#endif -#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64) -extern opl_driver_t opl_openbsd_driver; -#endif -#ifdef _WIN32 -extern opl_driver_t opl_win32_driver; -#endif -extern opl_driver_t opl_sdl_driver; - - -#endif /* #ifndef OPL_INTERNAL_H */ - diff --git a/games/NXDoom/opl/opl_linux.c b/games/NXDoom/opl/opl_linux.c deleted file mode 100644 index 03160fa1bfc..00000000000 --- a/games/NXDoom/opl/opl_linux.c +++ /dev/null @@ -1,103 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL Linux interface. -// - -#include "config.h" - -#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) - -#include -#include -#include -#include -#include - -#include "opl.h" -#include "opl_internal.h" -#include "opl_timer.h" - -static unsigned int opl_port_base; - -static int OPL_Linux_Init(unsigned int port_base) -{ - // Try to get permissions: - - if (ioperm(port_base, 3, 1) < 0) - { - fprintf(stderr, "Failed to get I/O port permissions for 0x%x: %s\n", - port_base, strerror(errno)); - - if (errno == EPERM) - { - fprintf(stderr, - "\tYou may need to run the program as root in order\n" - "\tto acquire I/O port permissions for OPL MIDI playback.\n"); - } - - return 0; - } - - opl_port_base = port_base; - - // Start callback thread - - if (!OPL_Timer_StartThread()) - { - ioperm(port_base, 2, 0); - return 0; - } - - return 1; -} - -static void OPL_Linux_Shutdown(void) -{ - // Stop callback thread - - OPL_Timer_StopThread(); - - // Release permissions - - ioperm(opl_port_base, 2, 0); -} - -static unsigned int OPL_Linux_PortRead(opl_port_t port) -{ - return inb(opl_port_base + port); -} - -static void OPL_Linux_PortWrite(opl_port_t port, unsigned int value) -{ - outb(value, opl_port_base + port); -} - -opl_driver_t opl_linux_driver = -{ - "Linux", - OPL_Linux_Init, - OPL_Linux_Shutdown, - OPL_Linux_PortRead, - OPL_Linux_PortWrite, - OPL_Timer_SetCallback, - OPL_Timer_ClearCallbacks, - OPL_Timer_Lock, - OPL_Timer_Unlock, - OPL_Timer_SetPaused, - OPL_Timer_AdjustCallbacks, -}; - -#endif /* #if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) */ - diff --git a/games/NXDoom/opl/opl_obsd.c b/games/NXDoom/opl/opl_obsd.c deleted file mode 100644 index 39e0c156066..00000000000 --- a/games/NXDoom/opl/opl_obsd.c +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL OpenBSD interface (also NetBSD) -// - -#include "config.h" - -// OpenBSD has a i386_iopl on i386 and amd64_iopl on x86_64, -// even though they do the same thing. Take care of this -// here, and map set_iopl to point to the appropriate name. - -#if defined(HAVE_LIBI386) - -#include -#include -#include -#define set_iopl i386_iopl - -#elif defined(HAVE_LIBAMD64) - -#include -#include -#include -#define set_iopl amd64_iopl - -#else -#define NO_OBSD_DRIVER -#endif - -// If the above succeeded, proceed with the rest. - -#ifndef NO_OBSD_DRIVER - -#include -#include -#include -#include - -#include "opl.h" -#include "opl_internal.h" -#include "opl_timer.h" - -static unsigned int opl_port_base; - -static int OPL_OpenBSD_Init(unsigned int port_base) -{ - // Try to get permissions: - - if (set_iopl(3) < 0) - { - fprintf(stderr, "Failed to get raise I/O privilege level: " - "check that you are running as root.\n"); - return 0; - } - - opl_port_base = port_base; - - // Start callback thread - - if (!OPL_Timer_StartThread()) - { - set_iopl(0); - return 0; - } - - return 1; -} - -static void OPL_OpenBSD_Shutdown(void) -{ - // Stop callback thread - - OPL_Timer_StopThread(); - - // Release I/O port permissions: - - set_iopl(0); -} - -static unsigned int OPL_OpenBSD_PortRead(opl_port_t port) -{ - return inb(opl_port_base + port); -} - -static void OPL_OpenBSD_PortWrite(opl_port_t port, unsigned int value) -{ - outb(opl_port_base + port, value); -} - -opl_driver_t opl_openbsd_driver = -{ - "OpenBSD", - OPL_OpenBSD_Init, - OPL_OpenBSD_Shutdown, - OPL_OpenBSD_PortRead, - OPL_OpenBSD_PortWrite, - OPL_Timer_SetCallback, - OPL_Timer_ClearCallbacks, - OPL_Timer_Lock, - OPL_Timer_Unlock, - OPL_Timer_SetPaused, - OPL_Timer_AdjustCallbacks, -}; - -#endif /* #ifndef NO_OBSD_DRIVER */ - diff --git a/games/NXDoom/opl/opl_queue.c b/games/NXDoom/opl/opl_queue.c deleted file mode 100644 index e948b641315..00000000000 --- a/games/NXDoom/opl/opl_queue.c +++ /dev/null @@ -1,285 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Queue of waiting callbacks, stored in a binary min heap, so that we -// can always get the first callback. -// - -#include -#include -#include - -#include "opl_queue.h" - -#define MAX_OPL_QUEUE 64 - -typedef struct -{ - opl_callback_t callback; - void *data; - uint64_t time; -} opl_queue_entry_t; - -struct opl_callback_queue_s -{ - opl_queue_entry_t entries[MAX_OPL_QUEUE]; - unsigned int num_entries; -}; - -opl_callback_queue_t *OPL_Queue_Create(void) -{ - opl_callback_queue_t *queue; - - queue = malloc(sizeof(opl_callback_queue_t)); - queue->num_entries = 0; - - return queue; -} - -void OPL_Queue_Destroy(opl_callback_queue_t *queue) -{ - free(queue); -} - -int OPL_Queue_IsEmpty(opl_callback_queue_t *queue) -{ - return queue->num_entries == 0; -} - -void OPL_Queue_Clear(opl_callback_queue_t *queue) -{ - queue->num_entries = 0; -} - -void OPL_Queue_Push(opl_callback_queue_t *queue, - opl_callback_t callback, void *data, - uint64_t time) -{ - int entry_id; - int parent_id; - - if (queue->num_entries >= MAX_OPL_QUEUE) - { - fprintf(stderr, "OPL_Queue_Push: Exceeded maximum callbacks\n"); - return; - } - - // Add to last queue entry. - - entry_id = queue->num_entries; - ++queue->num_entries; - - // Shift existing entries down in the heap. - - while (entry_id > 0) - { - parent_id = (entry_id - 1) / 2; - - // Is the heap condition satisfied? - - if (time >= queue->entries[parent_id].time) - { - break; - } - - // Move the existing entry down in the heap. - - memcpy(&queue->entries[entry_id], - &queue->entries[parent_id], - sizeof(opl_queue_entry_t)); - - // Advance to the parent. - - entry_id = parent_id; - } - - // Insert new callback data. - - queue->entries[entry_id].callback = callback; - queue->entries[entry_id].data = data; - queue->entries[entry_id].time = time; -} - -int OPL_Queue_Pop(opl_callback_queue_t *queue, - opl_callback_t *callback, void **data) -{ - opl_queue_entry_t *entry; - int child1, child2; - int i, next_i; - - // Empty? - - if (queue->num_entries <= 0) - { - return 0; - } - - // Store the result: - - *callback = queue->entries[0].callback; - *data = queue->entries[0].data; - - // Decrease the heap size, and keep pointer to the last entry in - // the heap, which must now be percolated down from the top. - - --queue->num_entries; - entry = &queue->entries[queue->num_entries]; - - // Percolate down. - - i = 0; - - for (;;) - { - child1 = i * 2 + 1; - child2 = i * 2 + 2; - - if (child1 < queue->num_entries - && queue->entries[child1].time < entry->time) - { - // Left child is less than entry. - // Use the minimum of left and right children. - - if (child2 < queue->num_entries - && queue->entries[child2].time < queue->entries[child1].time) - { - next_i = child2; - } - else - { - next_i = child1; - } - } - else if (child2 < queue->num_entries - && queue->entries[child2].time < entry->time) - { - // Right child is less than entry. Go down the right side. - - next_i = child2; - } - else - { - // Finished percolating. - break; - } - - // Percolate the next value up and advance. - - memcpy(&queue->entries[i], - &queue->entries[next_i], - sizeof(opl_queue_entry_t)); - i = next_i; - } - - // Store the old last-entry at its new position. - - memcpy(&queue->entries[i], entry, sizeof(opl_queue_entry_t)); - - return 1; -} - -uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue) -{ - if (queue->num_entries > 0) - { - return queue->entries[0].time; - } - else - { - return 0; - } -} - -void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue, - uint64_t time, float factor) -{ - int64_t offset; - int i; - - for (i = 0; i < queue->num_entries; ++i) - { - offset = queue->entries[i].time - time; - queue->entries[i].time = time + (uint64_t) (offset / factor); - } -} - -#ifdef TEST - -#include - -static void PrintQueueNode(opl_callback_queue_t *queue, int node, int depth) -{ - int i; - - if (node >= queue->num_entries) - { - return; - } - - for (i=0; ientries[node].time); - - PrintQueueNode(queue, node * 2 + 1, depth + 1); - PrintQueueNode(queue, node * 2 + 2, depth + 1); -} - -static void PrintQueue(opl_callback_queue_t *queue) -{ - PrintQueueNode(queue, 0, 0); -} - -int main() -{ - opl_callback_queue_t *queue; - int iteration; - - queue = OPL_Queue_Create(); - - for (iteration=0; iteration<5000; ++iteration) - { - opl_callback_t callback; - void *data; - unsigned int time; - unsigned int newtime; - int i; - - for (i=0; i= time); - time = newtime; - } - - assert(OPL_Queue_IsEmpty(queue)); - assert(!OPL_Queue_Pop(queue, &callback, &data)); - } -} - -#endif - diff --git a/games/NXDoom/opl/opl_queue.h b/games/NXDoom/opl/opl_queue.h deleted file mode 100644 index 8b4f0dbee36..00000000000 --- a/games/NXDoom/opl/opl_queue.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL callback queue. -// - -#ifndef OPL_QUEUE_H -#define OPL_QUEUE_H - -#include "opl.h" - -typedef struct opl_callback_queue_s opl_callback_queue_t; - -opl_callback_queue_t *OPL_Queue_Create(void); -int OPL_Queue_IsEmpty(opl_callback_queue_t *queue); -void OPL_Queue_Clear(opl_callback_queue_t *queue); -void OPL_Queue_Destroy(opl_callback_queue_t *queue); -void OPL_Queue_Push(opl_callback_queue_t *queue, - opl_callback_t callback, void *data, - uint64_t time); -int OPL_Queue_Pop(opl_callback_queue_t *queue, - opl_callback_t *callback, void **data); -uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue); -void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue, - uint64_t time, float factor); - -#endif /* #ifndef OPL_QUEUE_H */ - diff --git a/games/NXDoom/opl/opl_sdl.c b/games/NXDoom/opl/opl_sdl.c deleted file mode 100644 index 2517de15c0a..00000000000 --- a/games/NXDoom/opl/opl_sdl.c +++ /dev/null @@ -1,521 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL SDL interface. -// - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "SDL.h" -#ifndef DISABLE_SDL2MIXER -#include "SDL_mixer.h" -#endif // DISABLE_SDL2MIXER - -#include "opl3.h" - -#include "opl.h" -#include "opl_internal.h" - -#include "opl_queue.h" - - -#ifndef DISABLE_SDL2MIXER - - -#define MAX_SOUND_SLICE_TIME 100 /* ms */ - -typedef struct -{ - unsigned int rate; // Number of times the timer is advanced per sec. - unsigned int enabled; // Non-zero if timer is enabled. - unsigned int value; // Last value that was set. - uint64_t expire_time; // Calculated time that timer will expire. -} opl_timer_t; - -// When the callback mutex is locked using OPL_Lock, callback functions -// are not invoked. - -static SDL_mutex *callback_mutex = NULL; - -// Queue of callbacks waiting to be invoked. - -static opl_callback_queue_t *callback_queue; - -// Mutex used to control access to the callback queue. - -static SDL_mutex *callback_queue_mutex = NULL; - -// Current time, in us since startup: - -static uint64_t current_time; - -// If non-zero, playback is currently paused. - -static int opl_sdl_paused; - -// Time offset (in us) due to the fact that callbacks -// were previously paused. - -static uint64_t pause_offset; - -// OPL software emulator structure. - -static opl3_chip opl_chip; -static int opl_opl3mode; - -// Temporary mixing buffer used by the mixing callback. - -static uint8_t *mix_buffer = NULL; - -// Register number that was written. - -static int register_num = 0; - -// Timers; DBOPL does not do timer stuff itself. - -static opl_timer_t timer1 = { 12500, 0, 0, 0 }; -static opl_timer_t timer2 = { 3125, 0, 0, 0 }; - -// SDL parameters. - -static int sdl_was_initialized = 0; -static int mixing_freq, mixing_channels; -static Uint16 mixing_format; - -static int SDLIsInitialized(void) -{ - int freq, channels; - Uint16 format; - - return Mix_QuerySpec(&freq, &format, &channels); -} - -// Advance time by the specified number of samples, invoking any -// callback functions as appropriate. - -static void AdvanceTime(unsigned int nsamples) -{ - opl_callback_t callback; - void *callback_data; - uint64_t us; - - SDL_LockMutex(callback_queue_mutex); - - // Advance time. - - us = ((uint64_t) nsamples * OPL_SECOND) / mixing_freq; - current_time += us; - - if (opl_sdl_paused) - { - pause_offset += us; - } - - // Are there callbacks to invoke now? Keep invoking them - // until there are no more left. - - while (!OPL_Queue_IsEmpty(callback_queue) - && current_time >= OPL_Queue_Peek(callback_queue) + pause_offset) - { - // Pop the callback from the queue to invoke it. - - if (!OPL_Queue_Pop(callback_queue, &callback, &callback_data)) - { - break; - } - - // The mutex stuff here is a bit complicated. We must - // hold callback_mutex when we invoke the callback (so that - // the control thread can use OPL_Lock() to prevent callbacks - // from being invoked), but we must not be holding - // callback_queue_mutex, as the callback must be able to - // call OPL_SetCallback to schedule new callbacks. - - SDL_UnlockMutex(callback_queue_mutex); - - SDL_LockMutex(callback_mutex); - callback(callback_data); - SDL_UnlockMutex(callback_mutex); - - SDL_LockMutex(callback_queue_mutex); - } - - SDL_UnlockMutex(callback_queue_mutex); -} - -// Call the OPL emulator code to fill the specified buffer. - -static void FillBuffer(uint8_t *buffer, unsigned int nsamples) -{ - // This seems like a reasonable assumption. mix_buffer is - // 1 second long, which should always be much longer than the - // SDL mix buffer. - assert(nsamples < mixing_freq); - - // OPL output is generated into temporary buffer and then mixed - // (to avoid overflows etc.) - OPL3_GenerateStream(&opl_chip, (Bit16s *) mix_buffer, nsamples); - SDL_MixAudioFormat(buffer, mix_buffer, AUDIO_S16SYS, nsamples * 4, - SDL_MIX_MAXVOLUME); -} - -// Callback function to fill a new sound buffer: - -static void OPL_Mix_Callback(int chan, void *stream, int len, void *udata) -{ - unsigned int filled, buffer_samples; - Uint8 *buffer = (Uint8*)stream; - - // Repeatedly call the OPL emulator update function until the buffer is - // full. - filled = 0; - buffer_samples = len / 4; - - while (filled < buffer_samples) - { - uint64_t next_callback_time; - uint64_t nsamples; - - SDL_LockMutex(callback_queue_mutex); - - // Work out the time until the next callback waiting in - // the callback queue must be invoked. We can then fill the - // buffer with this many samples. - - if (opl_sdl_paused || OPL_Queue_IsEmpty(callback_queue)) - { - nsamples = buffer_samples - filled; - } - else - { - next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset; - - nsamples = (next_callback_time - current_time) * mixing_freq; - nsamples = (nsamples + OPL_SECOND - 1) / OPL_SECOND; - - if (nsamples > buffer_samples - filled) - { - nsamples = buffer_samples - filled; - } - } - - SDL_UnlockMutex(callback_queue_mutex); - - // Add emulator output to buffer. - - FillBuffer(buffer + filled * 4, nsamples); - filled += nsamples; - - // Invoke callbacks for this point in time. - - AdvanceTime(nsamples); - } -} - -static void OPL_SDL_Shutdown(void) -{ - Mix_HookMusic(NULL, NULL); - - if (sdl_was_initialized) - { - Mix_CloseAudio(); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - OPL_Queue_Destroy(callback_queue); - free(mix_buffer); - sdl_was_initialized = 0; - } - -/* - if (opl_chip != NULL) - { - OPLDestroy(opl_chip); - opl_chip = NULL; - } - */ - - if (callback_mutex != NULL) - { - SDL_DestroyMutex(callback_mutex); - callback_mutex = NULL; - } - - if (callback_queue_mutex != NULL) - { - SDL_DestroyMutex(callback_queue_mutex); - callback_queue_mutex = NULL; - } -} - -static unsigned int GetSliceSize(void) -{ - int limit; - int n; - - limit = (opl_sample_rate * MAX_SOUND_SLICE_TIME) / 1000; - - // Try all powers of two, not exceeding the limit. - - for (n=0;; ++n) - { - // 2^n <= limit < 2^n+1 ? - - if ((1 << (n + 1)) > limit) - { - return (1 << n); - } - } - - // Should never happen? - - return 1024; -} - -static int OPL_SDL_Init(unsigned int port_base) -{ - // Check if SDL_mixer has been opened already - // If not, we must initialize it now - - if (!SDLIsInitialized()) - { - if (SDL_Init(SDL_INIT_AUDIO) < 0) - { - fprintf(stderr, "Unable to set up sound.\n"); - return 0; - } - - if (Mix_OpenAudioDevice(opl_sample_rate, AUDIO_S16SYS, 2, GetSliceSize(), NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) - { - fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError()); - - SDL_QuitSubSystem(SDL_INIT_AUDIO); - return 0; - } - - SDL_PauseAudio(0); - - // When this module shuts down, it has the responsibility to - // shut down SDL. - - sdl_was_initialized = 1; - } - else - { - sdl_was_initialized = 0; - } - - opl_sdl_paused = 0; - pause_offset = 0; - - // Queue structure of callbacks to invoke. - - callback_queue = OPL_Queue_Create(); - current_time = 0; - - // Get the mixer frequency, format and number of channels. - - Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels); - - // Only supports AUDIO_S16SYS - - if (mixing_format != AUDIO_S16SYS || mixing_channels != 2) - { - fprintf(stderr, - "OPL_SDL only supports native signed 16-bit LSB, " - "stereo format!\n"); - - OPL_SDL_Shutdown(); - return 0; - } - - // Mix buffer: four bytes per sample (16 bits * 2 channels): - mix_buffer = malloc(mixing_freq * 4); - - // Create the emulator structure: - - OPL3_Reset(&opl_chip, mixing_freq); - opl_opl3mode = 0; - - callback_mutex = SDL_CreateMutex(); - callback_queue_mutex = SDL_CreateMutex(); - - // Set postmix that adds the OPL music. This is deliberately done - // as a postmix and not using Mix_HookMusic() as the latter disables - // normal SDL_mixer music mixing. - Mix_RegisterEffect(MIX_CHANNEL_POST, OPL_Mix_Callback, NULL, NULL); - - return 1; -} - -static unsigned int OPL_SDL_PortRead(opl_port_t port) -{ - unsigned int result = 0; - - if (port == OPL_REGISTER_PORT_OPL3) - { - return 0xff; - } - - if (timer1.enabled && current_time > timer1.expire_time) - { - result |= 0x80; // Either have expired - result |= 0x40; // Timer 1 has expired - } - - if (timer2.enabled && current_time > timer2.expire_time) - { - result |= 0x80; // Either have expired - result |= 0x20; // Timer 2 has expired - } - - return result; -} - -static void OPLTimer_CalculateEndTime(opl_timer_t *timer) -{ - int tics; - - // If the timer is enabled, calculate the time when the timer - // will expire. - - if (timer->enabled) - { - tics = 0x100 - timer->value; - timer->expire_time = current_time - + ((uint64_t) tics * OPL_SECOND) / timer->rate; - } -} - -static void WriteRegister(unsigned int reg_num, unsigned int value) -{ - switch (reg_num) - { - case OPL_REG_TIMER1: - timer1.value = value; - OPLTimer_CalculateEndTime(&timer1); - break; - - case OPL_REG_TIMER2: - timer2.value = value; - OPLTimer_CalculateEndTime(&timer2); - break; - - case OPL_REG_TIMER_CTRL: - if (value & 0x80) - { - timer1.enabled = 0; - timer2.enabled = 0; - } - else - { - if ((value & 0x40) == 0) - { - timer1.enabled = (value & 0x01) != 0; - OPLTimer_CalculateEndTime(&timer1); - } - - if ((value & 0x20) == 0) - { - timer2.enabled = (value & 0x02) != 0; - OPLTimer_CalculateEndTime(&timer2); - } - } - - break; - - case OPL_REG_NEW: - opl_opl3mode = value & 0x01; - - default: - OPL3_WriteRegBuffered(&opl_chip, reg_num, value); - break; - } -} - -static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value) -{ - if (port == OPL_REGISTER_PORT) - { - register_num = value; - } - else if (port == OPL_REGISTER_PORT_OPL3) - { - register_num = value | 0x100; - } - else if (port == OPL_DATA_PORT) - { - WriteRegister(register_num, value); - } -} - -static void OPL_SDL_SetCallback(uint64_t us, opl_callback_t callback, - void *data) -{ - SDL_LockMutex(callback_queue_mutex); - OPL_Queue_Push(callback_queue, callback, data, - current_time - pause_offset + us); - SDL_UnlockMutex(callback_queue_mutex); -} - -static void OPL_SDL_ClearCallbacks(void) -{ - SDL_LockMutex(callback_queue_mutex); - OPL_Queue_Clear(callback_queue); - SDL_UnlockMutex(callback_queue_mutex); -} - -static void OPL_SDL_Lock(void) -{ - SDL_LockMutex(callback_mutex); -} - -static void OPL_SDL_Unlock(void) -{ - SDL_UnlockMutex(callback_mutex); -} - -static void OPL_SDL_SetPaused(int paused) -{ - opl_sdl_paused = paused; -} - -static void OPL_SDL_AdjustCallbacks(float factor) -{ - SDL_LockMutex(callback_queue_mutex); - OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor); - SDL_UnlockMutex(callback_queue_mutex); -} - -opl_driver_t opl_sdl_driver = -{ - "SDL", - OPL_SDL_Init, - OPL_SDL_Shutdown, - OPL_SDL_PortRead, - OPL_SDL_PortWrite, - OPL_SDL_SetCallback, - OPL_SDL_ClearCallbacks, - OPL_SDL_Lock, - OPL_SDL_Unlock, - OPL_SDL_SetPaused, - OPL_SDL_AdjustCallbacks, -}; - - -#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/opl/opl_timer.c b/games/NXDoom/opl/opl_timer.c deleted file mode 100644 index 2c4ce273ea7..00000000000 --- a/games/NXDoom/opl/opl_timer.c +++ /dev/null @@ -1,250 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL timer thread. -// Once started using OPL_Timer_StartThread, the thread sleeps, -// waking up to invoke callbacks set using OPL_Timer_SetCallback. -// - -#include "SDL.h" - -#include "opl_timer.h" -#include "opl_queue.h" - -typedef enum -{ - THREAD_STATE_STOPPED, - THREAD_STATE_RUNNING, - THREAD_STATE_STOPPING, -} thread_state_t; - -static SDL_Thread *timer_thread = NULL; -static thread_state_t timer_thread_state; -static uint64_t current_time; - -// If non-zero, callbacks are currently paused. - -static int opl_timer_paused; - -// Offset in microseconds to adjust time due to the fact that playback -// was paused. - -static uint64_t pause_offset = 0; - -// Queue of callbacks waiting to be invoked. -// The callback queue mutex is held while the callback queue structure -// or current_time is being accessed. - -static opl_callback_queue_t *callback_queue; -static SDL_mutex *callback_queue_mutex; - -// The timer mutex is held while timer callback functions are being -// invoked, so that the calling code can prevent clashes. - -static SDL_mutex *timer_mutex; - -// Returns true if there is a callback at the head of the queue ready -// to be invoked. Otherwise, next_time is set to the time when the -// timer thread must wake up again to check. - -static int CallbackWaiting(uint64_t *next_time) -{ - // If paused, just wait in 50ms increments until unpaused. - // Update pause_offset so after we unpause, the callback - // times will be right. - - if (opl_timer_paused) - { - *next_time = current_time + 50 * OPL_MS; - pause_offset += 50 * OPL_MS; - return 0; - } - - // If there are no queued callbacks, sleep for 50ms at a time - // until a callback is added. - - if (OPL_Queue_IsEmpty(callback_queue)) - { - *next_time = current_time + 50 * OPL_MS; - return 0; - } - - // Read the time of the first callback in the queue. - // If the time for the callback has not yet arrived, - // we must sleep until the callback time. - - *next_time = OPL_Queue_Peek(callback_queue) + pause_offset; - - return *next_time <= current_time; -} - -static uint64_t GetNextTime(void) -{ - opl_callback_t callback; - void *callback_data; - uint64_t next_time; - int have_callback; - - // Keep running through callbacks until there are none ready to - // run. When we run out of callbacks, next_time will be set. - - do - { - SDL_LockMutex(callback_queue_mutex); - - // Check if the callback at the head of the list is ready to - // be invoked. If so, pop from the head of the queue. - - have_callback = CallbackWaiting(&next_time); - - if (have_callback) - { - OPL_Queue_Pop(callback_queue, &callback, &callback_data); - } - - SDL_UnlockMutex(callback_queue_mutex); - - // Now invoke the callback, if we have one. - // The timer mutex is held while the callback is invoked. - - if (have_callback) - { - SDL_LockMutex(timer_mutex); - callback(callback_data); - SDL_UnlockMutex(timer_mutex); - } - } while (have_callback); - - return next_time; -} - -static int ThreadFunction(void *unused) -{ - uint64_t next_time; - uint64_t now; - - // Keep running until OPL_Timer_StopThread is called. - - while (timer_thread_state == THREAD_STATE_RUNNING) - { - // Get the next time that we must sleep until, and - // wait until that time. - - next_time = GetNextTime(); - now = SDL_GetTicks() * OPL_MS; - - if (next_time > now) - { - SDL_Delay((next_time - now) / OPL_MS); - } - - // Update the current time. - - SDL_LockMutex(callback_queue_mutex); - current_time = next_time; - SDL_UnlockMutex(callback_queue_mutex); - } - - timer_thread_state = THREAD_STATE_STOPPED; - - return 0; -} - -static void InitResources(void) -{ - callback_queue = OPL_Queue_Create(); - timer_mutex = SDL_CreateMutex(); - callback_queue_mutex = SDL_CreateMutex(); -} - -static void FreeResources(void) -{ - OPL_Queue_Destroy(callback_queue); - SDL_DestroyMutex(callback_queue_mutex); - SDL_DestroyMutex(timer_mutex); -} - -int OPL_Timer_StartThread(void) -{ - InitResources(); - - timer_thread_state = THREAD_STATE_RUNNING; - current_time = SDL_GetTicks(); - opl_timer_paused = 0; - pause_offset = 0; - - timer_thread = SDL_CreateThread(ThreadFunction, "OPL timer thread", NULL); - - if (timer_thread == NULL) - { - timer_thread_state = THREAD_STATE_STOPPED; - FreeResources(); - - return 0; - } - - return 1; -} - -void OPL_Timer_StopThread(void) -{ - timer_thread_state = THREAD_STATE_STOPPING; - - while (timer_thread_state != THREAD_STATE_STOPPED) - { - SDL_Delay(1); - } - - FreeResources(); -} - -void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data) -{ - SDL_LockMutex(callback_queue_mutex); - OPL_Queue_Push(callback_queue, callback, data, - current_time + us - pause_offset); - SDL_UnlockMutex(callback_queue_mutex); -} - -void OPL_Timer_ClearCallbacks(void) -{ - SDL_LockMutex(callback_queue_mutex); - OPL_Queue_Clear(callback_queue); - SDL_UnlockMutex(callback_queue_mutex); -} - -void OPL_Timer_AdjustCallbacks(float factor) -{ - SDL_LockMutex(callback_queue_mutex); - OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor); - SDL_UnlockMutex(callback_queue_mutex); -} - -void OPL_Timer_Lock(void) -{ - SDL_LockMutex(timer_mutex); -} - -void OPL_Timer_Unlock(void) -{ - SDL_UnlockMutex(timer_mutex); -} - -void OPL_Timer_SetPaused(int paused) -{ - SDL_LockMutex(callback_queue_mutex); - opl_timer_paused = paused; - SDL_UnlockMutex(callback_queue_mutex); -} - diff --git a/games/NXDoom/opl/opl_timer.h b/games/NXDoom/opl/opl_timer.h deleted file mode 100644 index adf815038df..00000000000 --- a/games/NXDoom/opl/opl_timer.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL timer thread. -// - -#ifndef OPL_TIMER_H -#define OPL_TIMER_H - -#include "opl.h" - -int OPL_Timer_StartThread(void); -void OPL_Timer_StopThread(void); -void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data); -void OPL_Timer_ClearCallbacks(void); -void OPL_Timer_Lock(void); -void OPL_Timer_Unlock(void); -void OPL_Timer_SetPaused(int paused); -void OPL_Timer_AdjustCallbacks(float factor); - -#endif /* #ifndef OPL_TIMER_H */ - diff --git a/games/NXDoom/opl/opl_win32.c b/games/NXDoom/opl/opl_win32.c deleted file mode 100644 index f0fd31c3655..00000000000 --- a/games/NXDoom/opl/opl_win32.c +++ /dev/null @@ -1,192 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// OPL Win32 native interface. -// - -#include "config.h" - -#ifdef _WIN32 - -#include - -#define WIN32_LEAN_AND_MEAN -#include - -#include "opl.h" -#include "opl_internal.h" -#include "opl_timer.h" - -#include "ioperm_sys.h" - -static unsigned int opl_port_base; - -// MingW? - -#if defined(__GNUC__) && defined(__i386__) - -static unsigned int OPL_Win32_PortRead(opl_port_t port) -{ - unsigned char result; - - __asm__ volatile ( - "movl %1, %%edx\n" - "inb %%dx, %%al\n" - "movb %%al, %0" - : "=m" (result) - : "r" (opl_port_base + port) - : "edx", "al", "memory" - ); - - return result; -} - -static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) -{ - __asm__ volatile ( - "movl %0, %%edx\n" - "movb %1, %%al\n" - "outb %%al, %%dx" - : - : "r" (opl_port_base + port), "r" ((unsigned char) value) - : "edx", "al" - ); -} - -// haleyjd 20110417: MSVC version -#elif defined(_MSC_VER) && defined(_M_IX86) - -static unsigned int OPL_Win32_PortRead(opl_port_t port) -{ - unsigned char result; - opl_port_t dst_port = opl_port_base + port; - - __asm - { - mov edx, dword ptr [dst_port] - in al, dx - mov byte ptr [result], al - } - - return result; -} - -static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) -{ - opl_port_t dst_port = opl_port_base + port; - - __asm - { - mov edx, dword ptr [dst_port] - mov al, byte ptr [value] - out dx, al - } -} - -#else - -// Not x86, or don't know how to do port R/W on this compiler. - -#define NO_PORT_RW - -static unsigned int OPL_Win32_PortRead(opl_port_t port) -{ - return 0; -} - -static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value) -{ -} - -#endif - -static int OPL_Win32_Init(unsigned int port_base) -{ - - OSVERSIONINFO version_info; - - opl_port_base = port_base; - - // Check the OS version. - - memset(&version_info, 0, sizeof(version_info)); - version_info.dwOSVersionInfoSize = sizeof(version_info); - - GetVersionEx(&version_info); - -#ifndef NO_PORT_RW - // On NT-based systems, we must acquire I/O port permissions - // using the ioperm.sys driver. - - if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - // Install driver. - - if (!IOperm_InstallDriver()) - { - return 0; - } - - // Open port range. - - if (!IOperm_EnablePortRange(opl_port_base, 2, 1)) - { - IOperm_UninstallDriver(); - return 0; - } - } - - // Start callback thread - - if (!OPL_Timer_StartThread()) - { - IOperm_UninstallDriver(); - return 0; - } - - return 1; - -#endif - - return 0; -} - -static void OPL_Win32_Shutdown(void) -{ - // Stop callback thread - - OPL_Timer_StopThread(); - - // Unload IOperm library. - - IOperm_UninstallDriver(); -} - -opl_driver_t opl_win32_driver = -{ - "Win32", - OPL_Win32_Init, - OPL_Win32_Shutdown, - OPL_Win32_PortRead, - OPL_Win32_PortWrite, - OPL_Timer_SetCallback, - OPL_Timer_ClearCallbacks, - OPL_Timer_Lock, - OPL_Timer_Unlock, - OPL_Timer_SetPaused, - OPL_Timer_AdjustCallbacks, -}; - -#endif /* #ifdef _WIN32 */ - diff --git a/games/NXDoom/pcsound/CMakeLists.txt b/games/NXDoom/pcsound/CMakeLists.txt deleted file mode 100644 index 6f199018110..00000000000 --- a/games/NXDoom/pcsound/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_library(pcsound STATIC - pcsound.c pcsound.h - pcsound_bsd.c - pcsound_sdl.c - pcsound_linux.c - pcsound_win32.c - pcsound_internal.h) -target_include_directories(pcsound - INTERFACE "." - PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") -if (DEFINED EMSCRIPTEN) - if(ENABLE_SDL2_MIXER) - set_target_properties(pcsound PROPERTIES COMPILE_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") - set_target_properties(pcsound PROPERTIES LINK_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2") - else() - set_target_properties(pcsound PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") - set_target_properties(pcsound PROPERTIES LINK_FLAGS "-s USE_SDL=2") - endif() -else() - target_link_libraries(pcsound SDL2::SDL2) - if(ENABLE_SDL2_MIXER) - target_link_libraries(pcsound SDL2_mixer::SDL2_mixer) - endif() -endif() diff --git a/games/NXDoom/pcsound/Makefile.am b/games/NXDoom/pcsound/Makefile.am deleted file mode 100644 index 12b2ae49d60..00000000000 --- a/games/NXDoom/pcsound/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ - -AM_CFLAGS=@SDLMIXER_CFLAGS@ - -EXTRA_DIST=CMakeLists.txt - -noinst_LIBRARIES=libpcsound.a - -libpcsound_a_SOURCES = \ - pcsound.c pcsound.h \ - pcsound_bsd.c \ - pcsound_sdl.c \ - pcsound_linux.c \ - pcsound_win32.c \ - pcsound_internal.h - diff --git a/games/NXDoom/pcsound/pcsound.c b/games/NXDoom/pcsound/pcsound.c index b57fe73a614..8e7b73bd6e1 100644 --- a/games/NXDoom/pcsound/pcsound.c +++ b/games/NXDoom/pcsound/pcsound.c @@ -1,19 +1,28 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker interface. -// +/**************************************************************************** + * apps/games/NXDoom/pcsound/pcsound.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * PC speaker interface. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -23,97 +32,98 @@ #include "pcsound.h" #include "pcsound_internal.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ -static pcsound_driver_t *drivers[] = +static pcsound_driver_t *g_drivers[] = { #ifdef HAVE_LINUX_KD_H - &pcsound_linux_driver, + &pcsound_linux_driver, #endif -#ifdef HAVE_BSD_SPEAKER - &pcsound_bsd_driver, -#endif -#ifdef _WIN32 - &pcsound_win32_driver, -#endif -#ifndef DISABLE_SDL2MIXER - &pcsound_sdl_driver, -#endif // DISABLE_SDL2MIXER - NULL, + NULL, }; -static pcsound_driver_t *pcsound_driver = NULL; +static pcsound_driver_t *g_pcsound_driver = NULL; + +/**************************************************************************** + * Public Data + ****************************************************************************/ int pcsound_sample_rate; -void PCSound_SetSampleRate(int rate) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void pc_sound_set_sample_rate(int rate) { - pcsound_sample_rate = rate; + pcsound_sample_rate = rate; } -int PCSound_Init(pcsound_callback_func callback_func) +int pc_sound_init(pcsound_callback_func callback_func) { - char *driver_name; - int i; + char *driver_name; + int i; - if (pcsound_driver != NULL) + if (g_pcsound_driver != NULL) { - return 1; + return 1; } - // Check if the environment variable is set + /* Check if the environment variable is set */ - driver_name = getenv("PCSOUND_DRIVER"); + driver_name = getenv("PCSOUND_DRIVER"); - if (driver_name != NULL) + if (driver_name != NULL) { - for (i=0; drivers[i] != NULL; ++i) + for (i = 0; g_drivers[i] != NULL; ++i) { - if (!strcmp(drivers[i]->name, driver_name)) + if (!strcmp(g_drivers[i]->name, driver_name)) { - // Found the driver! + /* Found the driver! */ - if (drivers[i]->init_func(callback_func)) + if (g_drivers[i]->init_func(callback_func)) { - pcsound_driver = drivers[i]; + g_pcsound_driver = g_drivers[i]; } - else + else { - printf("Failed to initialize PC sound driver: %s\n", - drivers[i]->name); - break; + printf("Failed to initialize PC sound driver: %s\n", + g_drivers[i]->name); + break; } } } } - else + else { - // Try all drivers until we find a working one + /* Try all drivers until we find a working one */ - for (i=0; drivers[i] != NULL; ++i) + for (i = 0; g_drivers[i] != NULL; ++i) { - if (drivers[i]->init_func(callback_func)) + if (g_drivers[i]->init_func(callback_func)) { - pcsound_driver = drivers[i]; - break; + g_pcsound_driver = g_drivers[i]; + break; } } } - - if (pcsound_driver != NULL) + + if (g_pcsound_driver != NULL) { - printf("Using PC sound driver: %s\n", pcsound_driver->name); - return 1; + printf("Using PC sound driver: %s\n", g_pcsound_driver->name); + return 1; } - else + else { - printf("Failed to find a working PC sound driver.\n"); - return 0; + printf("Failed to find a working PC sound driver.\n"); + return 0; } } -void PCSound_Shutdown(void) +void pc_sound_shutdown(void) { - pcsound_driver->shutdown_func(); - pcsound_driver = NULL; + g_pcsound_driver->shutdown_func(); + g_pcsound_driver = NULL; } - diff --git a/games/NXDoom/pcsound/pcsound.h b/games/NXDoom/pcsound/pcsound.h index 4d567f2400a..0d1e0f3ba75 100644 --- a/games/NXDoom/pcsound/pcsound.h +++ b/games/NXDoom/pcsound/pcsound.h @@ -1,38 +1,52 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker interface. -// +/**************************************************************************** + * apps/games/NXDoom/pcsound/pcsound.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * PC speaker interface. + * + ****************************************************************************/ #ifndef PCSOUND_H #define PCSOUND_H +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef void (*pcsound_callback_func)(int *duration, int *frequency); -// Initialise the PC speaker subsystem. The given function is called -// periodically to request more sound data to play. +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -int PCSound_Init(pcsound_callback_func callback_func); +/* Initialise the PC speaker subsystem. The given function is called + * periodically to request more sound data to play. + */ -// Shut down the PC speaker subsystem. +int pc_sound_init(pcsound_callback_func callback_func); -void PCSound_Shutdown(void); +/* Shut down the PC speaker subsystem. */ -// Set the preferred output sample rate when emulating a PC speaker. -// This must be called before PCSound_Init. +void pc_sound_shutdown(void); -void PCSound_SetSampleRate(int rate); +/* Set the preferred output sample rate when emulating a PC speaker. + * This must be called before pc_sound_init. + */ -#endif /* #ifndef PCSOUND_H */ +void pc_sound_set_sample_rate(int rate); +#endif /* PCSOUND_H */ diff --git a/games/NXDoom/pcsound/pcsound_bsd.c b/games/NXDoom/pcsound/pcsound_bsd.c deleted file mode 100644 index a3055e7db62..00000000000 --- a/games/NXDoom/pcsound/pcsound_bsd.c +++ /dev/null @@ -1,321 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker driver for [Open]BSD -// (Should be NetBSD as well, but untested). -// - -#include "config.h" - -// OpenBSD/NetBSD: - -#ifdef HAVE_DEV_ISA_SPKRIO_H -#define HAVE_BSD_SPEAKER -#include -#endif - -// FreeBSD - -#ifdef HAVE_DEV_SPEAKER_SPEAKER_H -#define HAVE_BSD_SPEAKER -#include -#endif - -#ifdef HAVE_BSD_SPEAKER - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "SDL.h" -#include "SDL_thread.h" - -#include "pcsound.h" -#include "pcsound_internal.h" - -#define SPEAKER_DEVICE "/dev/speaker" - -// -// This driver is far more complicated than it should be, because -// OpenBSD has sucky support for threads. Because multithreading -// is done in userspace, invoking the ioctl to make the speaker -// beep will lock all threads until the beep has completed. -// -// Thus, to get the beeping to occur in real-time, we must invoke -// the ioctl in a separate process. To do this, a separate -// sound server is forked that listens on a socket for tones to -// play. When a tone is received, a reply is sent back to the -// main process and the tone played. -// -// Meanwhile, back in the main process, there is a sound thread -// that runs, invoking the pcsound callback function to get -// more tones. This blocks on the sound server socket, waiting -// for replies. In this way, when the sound server finishes -// playing a tone, the next one is sent. -// -// This driver is a bit less accurate than the others, because -// we can only specify sound durations in 1/100ths of a second, -// as opposed to the normal millisecond durations. - -static pcsound_callback_func callback; -static int sound_server_pid; -static int sleep_adjust = 0; -static int sound_thread_running; -static SDL_Thread *sound_thread_handle; -static int sound_server_pipe[2]; - -// Play a sound, checking how long the system call takes to complete -// and autoadjusting for drift. - -static void AdjustedBeep(int speaker_handle, int ms, int freq) -{ - unsigned int start_time; - unsigned int end_time; - unsigned int actual_time; - tone_t tone; - - // Adjust based on previous error to keep the tempo right - - if (sleep_adjust > ms) - { - sleep_adjust -= ms; - return; - } - else - { - ms -= sleep_adjust; - } - - // Invoke the system call and time how long it takes - - start_time = SDL_GetTicks(); - - tone.duration = ms / 10; // in 100ths of a second - tone.frequency = freq; - - // Always a positive duration - - if (tone.duration < 1) - { - tone.duration = 1; - } - - if (ioctl(speaker_handle, SPKRTONE, &tone) != 0) - { - perror("ioctl"); - return; - } - - end_time = SDL_GetTicks(); - - if (end_time > start_time) - { - actual_time = end_time - start_time; - } - else - { - actual_time = ms; - } - - if (actual_time < ms) - { - actual_time = ms; - } - - // Save sleep_adjust for next time - - sleep_adjust = actual_time - ms; -} - -static void SoundServer(int speaker_handle) -{ - tone_t tone; - int result; - - // Run in a loop, invoking the callback - - for (;;) - { - result = read(sound_server_pipe[1], &tone, sizeof(tone_t)); - - if (result < 0) - { - perror("read"); - return; - } - - // Send back a response, so the main process knows to send another - - write(sound_server_pipe[1], &tone, sizeof(tone_t)); - - // Beep! (blocks until complete) - - AdjustedBeep(speaker_handle, tone.duration, tone.frequency); - } -} - -// Start up the sound server. Returns non-zero if successful. - -static int StartSoundServer(void) -{ - int result; - int speaker_handle; - - // Try to open the speaker device - - speaker_handle = open(SPEAKER_DEVICE, O_WRONLY); - - if (speaker_handle == -1) - { - // Don't have permissions for the console device? - - fprintf(stderr, "StartSoundServer: Failed to open '%s': %s\n", - SPEAKER_DEVICE, strerror(errno)); - return 0; - } - - // Create a pipe for communications - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sound_server_pipe) < 0) - { - perror("socketpair"); - close(speaker_handle); - return 0; - } - - // Start a separate process to generate PC speaker output - // We can't use the SDL threading functions because OpenBSD's - // threading sucks :-( - - result = fork(); - - if (result < 0) - { - fprintf(stderr, "Failed to fork sound server!\n"); - close(speaker_handle); - return 0; - } - else if (result == 0) - { - // This is the child (sound server) - - SoundServer(speaker_handle); - close(speaker_handle); - - exit(0); - } - else - { - // This is the parent - - sound_server_pid = result; - close(speaker_handle); - } - - return 1; -} - -static void StopSoundServer(void) -{ - int status; - - kill(sound_server_pid, SIGINT); - waitpid(sound_server_pid, &status, 0); -} - -static int SoundThread(void *unused) -{ - tone_t tone; - int duration; - int frequency; - - while (sound_thread_running) - { - // Get the next frequency to play - - callback(&duration, &frequency); - -//printf("dur: %i, freq: %i\n", duration, frequency); - - // Build up a tone structure and send to the sound server - - tone.frequency = frequency; - tone.duration = duration; - - if (write(sound_server_pipe[0], &tone, sizeof(tone_t)) < 0) - { - perror("write"); - break; - } - - // Wait until the sound server responds before sending another - - if (read(sound_server_pipe[0], &tone, sizeof(tone_t)) < 0) - { - perror("read"); - break; - } - } - - return 0; -} - -static int PCSound_BSD_Init(pcsound_callback_func callback_func) -{ - callback = callback_func; - - if (!StartSoundServer()) - { - fprintf(stderr, "PCSound_BSD_Init: Failed to start sound server.\n"); - return 0; - } - - sound_thread_running = 1; - sound_thread_handle = - SDL_CreateThread(SoundThread, "PC speaker thread", NULL); - - return 1; -} - -static void PCSound_BSD_Shutdown(void) -{ - // Stop the sound thread - - sound_thread_running = 0; - - SDL_WaitThread(sound_thread_handle, NULL); - - // Stop the sound server - - StopSoundServer(); -} - -pcsound_driver_t pcsound_bsd_driver = -{ - "BSD", - PCSound_BSD_Init, - PCSound_BSD_Shutdown, -}; - -#endif /* #ifdef HAVE_BSD_SPEAKER */ - diff --git a/games/NXDoom/pcsound/pcsound_internal.h b/games/NXDoom/pcsound/pcsound_internal.h index 7611c595f4c..295ad6266be 100644 --- a/games/NXDoom/pcsound/pcsound_internal.h +++ b/games/NXDoom/pcsound/pcsound_internal.h @@ -1,33 +1,43 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker interface. -// +/**************************************************************************** + * apps/games/NXDoom/pcsound/pcsound_internal.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * PC speaker interface. + * + ****************************************************************************/ #ifndef PCSOUND_INTERNAL_H #define PCSOUND_INTERNAL_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "pcsound.h" -#ifdef HAVE_DEV_ISA_SPKRIO_H -#define HAVE_BSD_SPEAKER -#endif -#ifdef HAVE_DEV_SPEAKER_SPEAKER_H -#define HAVE_BSD_SPEAKER -#endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#define PCSOUND_8253_FREQUENCY 1193280 +#define PCSOUND_8253_FREQUENCY (1193280) + +/**************************************************************************** + * Public Types + ****************************************************************************/ typedef struct pcsound_driver_s pcsound_driver_t; typedef int (*pcsound_init_func)(pcsound_callback_func callback); @@ -35,21 +45,16 @@ typedef void (*pcsound_shutdown_func)(void); struct pcsound_driver_s { - const char *name; - pcsound_init_func init_func; - pcsound_shutdown_func shutdown_func; + const char *name; + pcsound_init_func init_func; + pcsound_shutdown_func shutdown_func; }; -extern int pcsound_sample_rate; - +/**************************************************************************** + * Public Data + ****************************************************************************/ -#ifdef _WIN32 -extern pcsound_driver_t pcsound_win32_driver; -#endif - -#ifdef HAVE_BSD_SPEAKER -extern pcsound_driver_t pcsound_bsd_driver; -#endif +extern int pcsound_sample_rate; #ifdef HAVE_LINUX_KD_H extern pcsound_driver_t pcsound_linux_driver; @@ -57,6 +62,4 @@ extern pcsound_driver_t pcsound_linux_driver; extern pcsound_driver_t pcsound_sdl_driver; - -#endif /* #ifndef PCSOUND_INTERNAL_H */ - +#endif /* PCSOUND_INTERNAL_H */ diff --git a/games/NXDoom/pcsound/pcsound_linux.c b/games/NXDoom/pcsound/pcsound_linux.c deleted file mode 100644 index 7cb59c9b9c0..00000000000 --- a/games/NXDoom/pcsound/pcsound_linux.c +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker driver for Linux. -// - -#include "config.h" - -#ifdef HAVE_LINUX_KD_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "SDL.h" -#include "SDL_thread.h" - -#include "pcsound.h" -#include "pcsound_internal.h" - -#define CONSOLE_DEVICE "/dev/console" - -static int console_handle; -static pcsound_callback_func callback; -static int sound_thread_running = 0; -static SDL_Thread *sound_thread_handle; -static int sleep_adjust = 0; - -static void AdjustedSleep(unsigned int ms) -{ - unsigned int start_time; - unsigned int end_time; - unsigned int actual_time; - - // Adjust based on previous error to keep the tempo right - - if (sleep_adjust > ms) - { - sleep_adjust -= ms; - return; - } - else - { - ms -= sleep_adjust; - } - - // Do the sleep and record how long it takes - - start_time = SDL_GetTicks(); - - SDL_Delay(ms); - - end_time = SDL_GetTicks(); - - if (end_time > start_time) - { - actual_time = end_time - start_time; - } - else - { - actual_time = ms; - } - - if (actual_time < ms) - { - actual_time = ms; - } - - // Save sleep_adjust for next time - - sleep_adjust = actual_time - ms; -} - -static int SoundThread(void *unused) -{ - int current_freq = 0; - int frequency; - int duration; - int cycles; - - while (sound_thread_running) - { - callback(&duration, &frequency); - - if (current_freq != frequency) - { - current_freq = frequency; - if (frequency != 0) - { - cycles = PCSOUND_8253_FREQUENCY / frequency; - } - else - { - cycles = 0; - } - - ioctl(console_handle, KIOCSOUND, cycles); - } - - AdjustedSleep(duration); - } - - return 0; -} - -static int PCSound_Linux_Init(pcsound_callback_func callback_func) -{ - // Try to open the console - - console_handle = open(CONSOLE_DEVICE, O_WRONLY); - - if (console_handle == -1) - { - // Don't have permissions for the console device? - - fprintf(stderr, "PCSound_Linux_Init: Failed to open '%s': %s\n", - CONSOLE_DEVICE, strerror(errno)); - return 0; - } - - if (ioctl(console_handle, KIOCSOUND, 0) < 0) - { - // KIOCSOUND not supported: non-PC linux? - - close(console_handle); - return 0; - } - - // Start a thread up to generate PC speaker output - - callback = callback_func; - sound_thread_running = 1; - - sound_thread_handle = - SDL_CreateThread(SoundThread, "PC speaker thread", NULL); - - return 1; -} - -static void PCSound_Linux_Shutdown(void) -{ - sound_thread_running = 0; - SDL_WaitThread(sound_thread_handle, NULL); - close(console_handle); -} - -pcsound_driver_t pcsound_linux_driver = -{ - "Linux", - PCSound_Linux_Init, - PCSound_Linux_Shutdown, -}; - -#endif /* #ifdef HAVE_LINUX_KD_H */ - diff --git a/games/NXDoom/pcsound/pcsound_sdl.c b/games/NXDoom/pcsound/pcsound_sdl.c deleted file mode 100644 index d38a97b8245..00000000000 --- a/games/NXDoom/pcsound/pcsound_sdl.c +++ /dev/null @@ -1,254 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker interface. -// - -#include -#include - -#include "config.h" - -#include "SDL.h" - -#include "pcsound.h" -#include "pcsound_internal.h" - - -#ifndef DISABLE_SDL2MIXER - -#include "SDL_mixer.h" - - -#define MAX_SOUND_SLICE_TIME 70 /* ms */ -#define SQUARE_WAVE_AMP 0x2000 - -// If true, we initialized SDL and have the responsibility to shut it -// down - -static int sdl_was_initialized = 0; - -// Callback function to invoke when we want new sound data - -static pcsound_callback_func callback; - -// Output sound format - -static int mixing_freq; -static Uint16 mixing_format; -static int mixing_channels; - -// Currently playing sound -// current_remaining is the number of remaining samples that must be played -// before we invoke the callback to get the next frequency. - -static int current_remaining; -static int current_freq; - -static int phase_offset = 0; - -// Mixer function that does the PC speaker emulation - -static void PCSound_Mix_Callback(int chan, void *stream, int len, void *udata) -{ - Sint16 *leftptr; - Sint16 *rightptr; - Sint16 this_value; - int frequency; - int i; - int nsamples; - - // Number of samples is quadrupled, because of 16-bit and stereo - - nsamples = len / 4; - - leftptr = (Sint16 *) stream; - rightptr = ((Sint16 *) stream) + 1; - - // Fill the output buffer - - for (i=0; i limit) - { - return (1 << n); - } - } - - // Should never happen? - - return 1024; -} - -static int PCSound_SDL_Init(pcsound_callback_func callback_func) -{ - int slicesize; - - // Check if SDL_mixer has been opened already - // If not, we must initialize it now - - if (!SDLIsInitialized()) - { - if (SDL_Init(SDL_INIT_AUDIO) < 0) - { - fprintf(stderr, "Unable to set up sound.\n"); - return 0; - } - - slicesize = GetSliceSize(); - - if (Mix_OpenAudioDevice(pcsound_sample_rate, AUDIO_S16SYS, 2, slicesize, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) - { - fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError()); - - SDL_QuitSubSystem(SDL_INIT_AUDIO); - return 0; - } - - SDL_PauseAudio(0); - - // When this module shuts down, it has the responsibility to - // shut down SDL. - - sdl_was_initialized = 1; - } - - // Get the mixer frequency, format and number of channels. - - Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels); - - // Only supports AUDIO_S16SYS - - if (mixing_format != AUDIO_S16SYS || mixing_channels != 2) - { - fprintf(stderr, - "PCSound_SDL only supports native signed 16-bit LSB, " - "stereo format!\n"); - - PCSound_SDL_Shutdown(); - return 0; - } - - callback = callback_func; - current_freq = 0; - current_remaining = 0; - - Mix_RegisterEffect(MIX_CHANNEL_POST, PCSound_Mix_Callback, NULL, NULL); - - return 1; -} - -pcsound_driver_t pcsound_sdl_driver = -{ - "SDL", - PCSound_SDL_Init, - PCSound_SDL_Shutdown, -}; - - -#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/pcsound/pcsound_win32.c b/games/NXDoom/pcsound/pcsound_win32.c deleted file mode 100644 index 91885f685cf..00000000000 --- a/games/NXDoom/pcsound/pcsound_win32.c +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// PC speaker interface. -// - -#ifdef _WIN32 - -#include "SDL.h" -#include "SDL_thread.h" -#include - -#include "pcsound.h" -#include "pcsound_internal.h" - -static SDL_Thread *sound_thread_handle; -static int sound_thread_running; -static pcsound_callback_func callback; - -static int SoundThread(void *unused) -{ - int frequency; - int duration; - - while (sound_thread_running) - { - callback(&duration, &frequency); - - if (frequency != 0) - { - Beep(frequency, duration); - } - else - { - Sleep(duration); - } - } - - return 0; -} - -static int PCSound_Win32_Init(pcsound_callback_func callback_func) -{ - OSVERSIONINFO osvi; - BOOL result; - - // Temporarily disabled - the Windows scheduler is strange and - // stupid. - - return 0; - - // Find the OS version - - osvi.dwOSVersionInfoSize = sizeof(osvi); - - result = GetVersionEx(&osvi); - - if (!result) - { - return 0; - } - - // Beep() ignores its arguments on win9x, so this driver will - // not work there. - if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) - { - return 0; - } - - // Start a thread to play sound. - - callback = callback_func; - sound_thread_running = 1; - - sound_thread_handle = - SDL_CreateThread(SoundThread, "PC speaker thread", NULL); - - return 1; -} - -static void PCSound_Win32_Shutdown(void) -{ - sound_thread_running = 0; - SDL_WaitThread(sound_thread_handle, NULL); -} - -pcsound_driver_t pcsound_win32_driver = -{ - "Windows", - PCSound_Win32_Init, - PCSound_Win32_Shutdown, -}; - -#endif /* #ifdef _WIN32 */ - diff --git a/games/NXDoom/pkg/.gitignore b/games/NXDoom/pkg/.gitignore deleted file mode 100644 index a1dd1cde42a..00000000000 --- a/games/NXDoom/pkg/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -Makefile.in -config.make diff --git a/games/NXDoom/pkg/Makefile.am b/games/NXDoom/pkg/Makefile.am deleted file mode 100644 index 3a287b2464f..00000000000 --- a/games/NXDoom/pkg/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ - -OSX_FILES= \ -osx/Resources/app.png \ -osx/Resources/launcher.nib/designable.nib \ -osx/Resources/launcher.nib/keyedobjects.nib \ -osx/disk/dir.DS_Store \ -osx/disk/background.png \ -osx/GNUmakefile \ -osx/Info.plist.in \ -osx/PkgInfo \ -osx/cp-with-libs \ -osx/dmgfix \ -osx/main.m \ -osx/AppController.m osx/AppController.h \ -osx/Execute.m osx/Execute.h \ -osx/IWADController.m osx/IWADController.h \ -osx/LauncherManager.m osx/LauncherManager.h - -WIN32_FILES= \ -win32/GNUmakefile \ -win32/cp-with-libs \ -win32/README - -EXTRA_DIST=style.html $(OSX_FILES) $(WIN32_FILES) - diff --git a/games/NXDoom/pkg/config.make.in b/games/NXDoom/pkg/config.make.in deleted file mode 100644 index 972be10e461..00000000000 --- a/games/NXDoom/pkg/config.make.in +++ /dev/null @@ -1,30 +0,0 @@ -# Shared file included by the makefiles used to build packages. -# This contains various information needed by the makefiles, -# and is autogenerated by configure to include various -# necessary details. - -# Tools needed: - -CC = @CC@ -OBJDUMP = @OBJDUMP@ -STRIP = @STRIP@ -LDFLAGS = @LDFLAGS@ - -# Package name and version number: - -PROGRAM_PREFIX = @PROGRAM_PREFIX@ -PACKAGE = @PACKAGE@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ - -TARGET_OS = @TARGET_OS@ - -# Documentation files to distribute with packages. - -DOC_FILES = README.md \ - README.Music.md \ - COPYING.md \ - NEWS.md - diff --git a/games/NXDoom/pkg/osx/.gitignore b/games/NXDoom/pkg/osx/.gitignore deleted file mode 100644 index a2b2f72de8d..00000000000 --- a/games/NXDoom/pkg/osx/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -Info.plist -app.iconset -app.icns -wadfile.iconset -wadfile.icns -launcher -*.o -*.d -*.dmg -staging diff --git a/games/NXDoom/pkg/osx/AppController.h b/games/NXDoom/pkg/osx/AppController.h deleted file mode 100644 index 37340ca2cb7..00000000000 --- a/games/NXDoom/pkg/osx/AppController.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef LAUNCHER_APPCONTROLLER_H -#define LAUNCHER_APPCONTROLLER_H - -#include - -#include "LauncherManager.h" - -@interface AppController : NSObject -{ - LauncherManager *launcherManager; - BOOL filesAdded; -} - -+ (void)initialize; - -- (id)init; -- (void)dealloc; - -- (void)awakeFromNib; - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotif; -- (BOOL)applicationShouldTerminate:(id)sender; -- (void)applicationWillTerminate:(NSNotification *)aNotif; -- (BOOL)application:(NSApplication *)application openFile:(NSString *)fileName; - -- (void)showPrefPanel:(id)sender; - -@end - -#endif - diff --git a/games/NXDoom/pkg/osx/AppController.m b/games/NXDoom/pkg/osx/AppController.m deleted file mode 100644 index 428eb9d0755..00000000000 --- a/games/NXDoom/pkg/osx/AppController.m +++ /dev/null @@ -1,146 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include "AppController.h" - -#include "config.h" - -@implementation AppController - -+ (void)initialize -{ - NSMutableDictionary *defaults = [NSMutableDictionary dictionary]; - - /* - * Register your app's defaults here by adding objects to the - * dictionary, eg - * - * [defaults setObject:anObject forKey:keyForThatObject]; - * - */ - - [[NSUserDefaults standardUserDefaults] registerDefaults:defaults]; - [[NSUserDefaults standardUserDefaults] synchronize]; -} - -- (id)init -{ - if ((self = [super init])) - { - } - - self->filesAdded = NO; - - return self; -} - -- (void)dealloc -{ - [super dealloc]; -} - -- (void)awakeFromNib -{ - [[NSApp mainMenu] setTitle:@PACKAGE_NAME]; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotif -{ -// Uncomment if your application is Renaissance-based -// [NSBundle loadGSMarkupNamed:@"Main" owner:self]; -} - -- (BOOL)applicationShouldTerminate:(id)sender -{ - return YES; -} - -- (void)applicationWillTerminate:(NSNotification *)aNotif -{ -} - -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)_ { - return YES; -} - -- (BOOL) application:(NSApplication *) application - openFile:(NSString *) fileName -{ - NSString *extension; - - // This may be an IWAD. If so, add it to the IWAD configuration; - // don't add it like a PWAD. - - if ([self->launcherManager addIWADPath: fileName]) - { - return YES; - } - - // If this is the first file added, clear out the existing - // command line. This allows us to select multiple files - // in the finder and open them all together (for TCs, etc). - - if (!self->filesAdded) - { - [self->launcherManager clearCommandLine]; - } - - // Add file with appropriate command line option based on extension: - - extension = [fileName pathExtension]; - - if (![extension caseInsensitiveCompare: @"wad"]) - { - [self->launcherManager addFileToCommandLine: fileName - forArgument: @"-merge"]; - } - else if (![extension caseInsensitiveCompare: @"lmp"]) - { - [self->launcherManager addFileToCommandLine: fileName - forArgument: @"-playdemo"]; - } - else if (![extension caseInsensitiveCompare: @"deh"]) - { - [self->launcherManager addFileToCommandLine: fileName - forArgument: @"-deh"]; - [self->launcherManager selectGameByName: "doom"]; - } - else if (![extension caseInsensitiveCompare: @"hhe"]) - { - [self->launcherManager addFileToCommandLine: fileName - forArgument: @"-deh"]; - [self->launcherManager selectGameByName: "heretic"]; - } - else if (![extension caseInsensitiveCompare: @"seh"]) - { - [self->launcherManager addFileToCommandLine: fileName - forArgument: @"-deh"]; - [self->launcherManager selectGameByName: "strife"]; - } - else - { - return NO; - } - - self->filesAdded = YES; - - return YES; -} - -- (void)showPrefPanel:(id)sender -{ -} - -@end - diff --git a/games/NXDoom/pkg/osx/Execute.h b/games/NXDoom/pkg/osx/Execute.h deleted file mode 100644 index fbb19c6f8c9..00000000000 --- a/games/NXDoom/pkg/osx/Execute.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef LAUNCHER_EXECUTE_H -#define LAUNCHER_EXECUTE_H - -void SetProgramLocation(const char *path); -void ExecuteProgram(const char *executable, const char *iwad, const char *args); -void OpenTerminalWindow(const char *doomwadpath); -void OpenDocumentation(const char *filename); - -#endif /* #ifndef LAUNCHER_EXECUTE_H */ - diff --git a/games/NXDoom/pkg/osx/Execute.m b/games/NXDoom/pkg/osx/Execute.m deleted file mode 100644 index 2d5d59310ac..00000000000 --- a/games/NXDoom/pkg/osx/Execute.m +++ /dev/null @@ -1,226 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "config.h" - -#define RESPONSE_FILE "/tmp/launcher.rsp" -#define TEMP_SCRIPT "/tmp/tempscript.sh" -#define WINDOW_TITLE PACKAGE_STRING " command prompt" - -static char *executable_path; - -// Called on startup to save the location of the launcher program -// (within a package, other executables should be in the same directory) - -void SetProgramLocation(const char *path) -{ - char *p; - - executable_path = strdup(path); - - p = strrchr(executable_path, '/'); - *p = '\0'; -} - -// Write out the response file containing command line arguments. - -static void WriteResponseFile(const char *iwad, const char *args) -{ - FILE *fstream; - - fstream = fopen(RESPONSE_FILE, "w"); - - if (iwad != NULL) - { - fprintf(fstream, "-iwad \"%s\"", iwad); - } - - if (args != NULL) - { - fprintf(fstream, "%s", args); - } - - fclose(fstream); -} - -static void DoExec(const char *executable, const char *iwad, const char *args) -{ - char *argv[3]; - - asprintf(&argv[0], "%s/%s", executable_path, executable); - - if (iwad != NULL || args != NULL) - { - WriteResponseFile(iwad, args); - - argv[1] = "@" RESPONSE_FILE; - argv[2] = NULL; - } - else - { - argv[1] = NULL; - } - - execv(argv[0], argv); - exit(-1); -} - -// Execute the specified executable contained in the same directory -// as the launcher, with the specified arguments. - -void ExecuteProgram(const char *executable, const char *iwad, const char *args) -{ - pid_t childpid; - char *homedir; - - childpid = fork(); - - if (childpid == 0) - { - signal(SIGCHLD, SIG_DFL); - - // Change directory to home dir before launch, so that any demos - // are saved somewhere sensible. - - homedir = getenv("HOME"); - - if (homedir != NULL) - { - chdir(homedir); - } - - DoExec(executable, iwad, args); - } - else - { - signal(SIGCHLD, SIG_IGN); - } -} - -// Write a sequence of commands that will display the specified message -// via shell commands. - -static void WriteMessage(FILE *script, char *msg) -{ - char *p; - - fprintf(script, "echo \""); - - for (p=msg; *p != '\0'; ++p) - { - // Start new line? - - if (*p == '\n') - { - fprintf(script, "\"\necho \""); - continue; - } - - // Escaped character? - - if (*p == '\\' || *p == '\"') - { - fprintf(script, "\\"); - } - - fprintf(script, "%c", *p); - } - - fprintf(script, "\"\n"); -} - -// Open a terminal window with the PATH set appropriately, and DOOMWADPATH -// set to the specified value. - -void OpenTerminalWindow(const char *doomwadpath) -{ - FILE *stream; - - // Generate a shell script that sets the PATH to include the location - // where the Doom binaries are, and DOOMWADPATH to include the - // IWAD files that have been configured in the launcher interface. - // The script then deletes itself and starts a shell. - - stream = fopen(TEMP_SCRIPT, "w"); - - fprintf(stream, "#!/bin/sh\n"); - //fprintf(stream, "set -x\n"); - fprintf(stream, "PATH=\"%s:$PATH\"\n", executable_path); - - // MANPATH is set to point to the directory within the bundle that - // contains the Unix manpages. However, the bundle name or path to - // it can contain a space, and OS X doesn't like this! As a - // workaround, create a symlink in /tmp to point to the real directory, - // and put *this* in MANPATH. - - fprintf(stream, "rm -f \"/tmp/%s.man\"\n", PACKAGE_TARNAME); - fprintf(stream, "ln -s \"%s/man\" \"/tmp/%s.man\"\n", - executable_path, PACKAGE_TARNAME); - fprintf(stream, "MANPATH=\"/tmp/%s.man:$(manpath)\"\n", PACKAGE_TARNAME); - fprintf(stream, "export MANPATH\n"); - - fprintf(stream, "DOOMWADPATH=\"%s\"\n", doomwadpath); - fprintf(stream, "export DOOMWADPATH\n"); - fprintf(stream, "rm -f \"%s\"\n", TEMP_SCRIPT); - - // Window title to something more interesting than "tempscript": - fprintf(stream, "echo -en \"\\033]0;%s\\a\"\n", WINDOW_TITLE); - - // Display a useful message: - - fprintf(stream, "clear\n"); - WriteMessage(stream, - "\n" - "This command line has the PATH variable configured so that you may\n" - "launch the game with whatever parameters you desire.\n" - "\n" - "For example:\n" - "\n" - " " PACKAGE_TARNAME " -iwad doom2.wad -file sid.wad -warp 1\n" - "\n" - "Type 'exit' to exit.\n"); - - fprintf(stream, "exec $SHELL\n"); - fprintf(stream, "\n"); - - fclose(stream); - - chmod(TEMP_SCRIPT, 0755); - - // Tell the terminal to open a window to run the script. - - [[NSWorkspace sharedWorkspace] openFile: @TEMP_SCRIPT - withApplication: @"Terminal"]; -} - -void OpenDocumentation(const char *filename) -{ - NSString *path; - - path = [NSString stringWithFormat: @"%s/Documentation/%s", - executable_path, filename]; - - [[NSWorkspace sharedWorkspace] openFile: path]; -} - diff --git a/games/NXDoom/pkg/osx/GNUmakefile b/games/NXDoom/pkg/osx/GNUmakefile deleted file mode 100644 index 55d7ac81011..00000000000 --- a/games/NXDoom/pkg/osx/GNUmakefile +++ /dev/null @@ -1,132 +0,0 @@ -# Makefile for building the OS X launcher program and DMG package. - -include ../config.make - -DOC_FILES += README.Strife.md NOT-BUGS.md - -export MACOSX_DEPLOYMENT_TARGET=10.7 - -ifeq ($(TARGET_OS),arm) - POSTFIX=arm64 -else - POSTFIX=x86 -endif - -STAGING_DIR=staging -DMG=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-$(POSTFIX).dmg - -TOPLEVEL=../.. -TOPLEVEL_DOCS=$(patsubst %,../../%,$(DOC_FILES)) - -# DMG file containing package: - -$(DMG) : tmp.dmg - rm -f $@ - sleep 2 # pause to workaround occasional "Can’t get disk" (-1728) issues - ./dmgfix "$(realpath tmp.dmg)" "$(PACKAGE_STRING)" "$(PACKAGE_NAME).app" - hdiutil convert -format UDBZ -o $@ tmp.dmg - rm -f tmp.dmg - -tmp.dmg : $(STAGING_DIR) - rm -f $@ - hdiutil makehybrid -hfs -hfs-volume-name "$(PACKAGE_STRING)" \ - -hfs-openfolder $(STAGING_DIR) $(STAGING_DIR) \ - -o tmp.dmg - -# Staging dir build for package: - -APP_DIR=$(STAGING_DIR)/$(PACKAGE_NAME).app - -APP_TOP_DIR=$(APP_DIR)/Contents -APP_BIN_DIR=$(APP_DIR)/Contents/MacOS -SRC_INFO_PLIST=Info.plist - -APP_DOC_DIR=$(APP_BIN_DIR)/Documentation -APP_DOC_RELDIR=$(patsubst $(STAGING_DIR)/%,%,$(APP_DOC_DIR)) - -$(STAGING_DIR): launcher $(TOPLEVEL_DOCS) app.icns wadfile.icns - rm -rf $(STAGING_DIR) - mkdir $(STAGING_DIR) - - mkdir -p "$(APP_TOP_DIR)" - cp -R Resources "$(APP_TOP_DIR)" - cp app.icns wadfile.icns "$(APP_TOP_DIR)/Resources" - cp $(TOPLEVEL)/data/doom.png "$(APP_TOP_DIR)/Resources/128x128.png" - cp PkgInfo "$(APP_TOP_DIR)" - cp $(SRC_INFO_PLIST) "$(APP_TOP_DIR)" - - mkdir -p "$(APP_BIN_DIR)" - - mkdir -p "$(APP_DOC_DIR)" - cp $(TOPLEVEL_DOCS) "$(APP_DOC_DIR)" - - mv "$(APP_DOC_DIR)/README.md" "$(APP_DOC_DIR)/README" - mv "$(APP_DOC_DIR)/COPYING.md" "$(APP_DOC_DIR)/COPYING" - ln -s "$(APP_DOC_RELDIR)/COPYING" "$(STAGING_DIR)/Software License" - ln -s "$(APP_DOC_RELDIR)/README" "$(STAGING_DIR)/README" - ln -s /Applications "$(STAGING_DIR)" - - cp launcher "$(APP_BIN_DIR)" - $(STRIP) "$(APP_BIN_DIR)/launcher" - - ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom "$(APP_BIN_DIR)" - $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)doom" - ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic "$(APP_BIN_DIR)" - $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)heretic" - ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen "$(APP_BIN_DIR)" - $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)hexen" - ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)strife "$(APP_BIN_DIR)" - $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)strife" - ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)" - $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup" - - $(TOPLEVEL)/man/simplecpp -DPRECOMPILED -D__MACOSX__ \ - -DDOOM -DHERETIC -DHEXEN -DSTRIFE \ - < $(TOPLEVEL)/man/INSTALL.template \ - > "$(APP_DOC_DIR)/INSTALL" - - mkdir -p "$(APP_BIN_DIR)/man/man5" "$(APP_BIN_DIR)/man/man6" - cp $(TOPLEVEL)/man/*.5 "$(APP_BIN_DIR)/man/man5" - cp $(TOPLEVEL)/man/*.6 "$(APP_BIN_DIR)/man/man6" - for game in doom heretic hexen strife; do \ - cp $(TOPLEVEL)/man/CMDLINE.$$game \ - "$(APP_DOC_DIR)/CMDLINE-$$game"; \ - done - cp disk/dir.DS_Store $(STAGING_DIR)/.DS_Store - cp disk/background.png $(STAGING_DIR)/background.png - -app.icns: $(TOPLEVEL)/data/doom.png - mkdir -p app.iconset - sips -z 64 64 $< --out app.iconset/icon_32x32@2x.png - iconutil -c icns app.iconset - -wadfile.icns: $(TOPLEVEL)/data/wadfile.png - mkdir -p wadfile.iconset - sips -z 64 64 $< --out wadfile.iconset/icon_32x32@2x.png - iconutil -c icns wadfile.iconset - -clean : launcher_clean - rm -f $(DMG) - rm -rf $(STAGING_DIR) - rm -rf app.icns app.iconset wadfile.icns wadfile.iconset - -# Launcher build: -CFLAGS = -Wall -I$(TOPLEVEL) -LDFLAGS = -framework Cocoa - -LAUNCHER_OBJS= \ - AppController.o \ - Execute.o \ - IWADController.o \ - LauncherManager.o \ - main.o - -launcher : $(LAUNCHER_OBJS) - $(CC) $(LDFLAGS) $(LAUNCHER_OBJS) -o $@ - -%.o : %.m - $(CC) -c $(CFLAGS) $^ -o $@ - -launcher_clean : - rm -f $(LAUNCHER_OBJS) launcher - diff --git a/games/NXDoom/pkg/osx/IWADController.h b/games/NXDoom/pkg/osx/IWADController.h deleted file mode 100644 index 404bffad0a2..00000000000 --- a/games/NXDoom/pkg/osx/IWADController.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef LAUNCHER_IWADCONTROLLER_H -#define LAUNCHER_IWADCONTROLLER_H - -#include -#include - -@interface IWADController : NSObject -{ - id iwadSelector; - id configWindow; - - id chex; - id doom1; - id doom2; - id plutonia; - id tnt; - id freedoom1; - id freedoom2; - id freedm; - - id heretic; - id hexen; - id strife; -} - -- (void) closeConfigWindow: (id)sender; -- (void) openConfigWindow: (id)sender; -- (NSString *) getIWADLocation; -- (NSString *) autoloadPath; -- (void) awakeFromNib; -- (BOOL) setDropdownList; -- (void) setDropdownSelection; -- (void) saveConfig; -- (char *) doomWadPath; -- (void) setEnvironment; -- (const char *) getGameName; -- (BOOL) addIWADPath: (NSString *) path; -- (BOOL) selectGameByName: (const char *) name; - -@end - -#endif /* #ifndef LAUNCHER_IWADCONTROLLER_H */ - diff --git a/games/NXDoom/pkg/osx/IWADController.m b/games/NXDoom/pkg/osx/IWADController.m deleted file mode 100644 index c131105c374..00000000000 --- a/games/NXDoom/pkg/osx/IWADController.m +++ /dev/null @@ -1,482 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include -#include - -#include "config.h" -#include "IWADController.h" - -typedef enum -{ - IWAD_DOOM1, - IWAD_DOOM2, - IWAD_TNT, - IWAD_PLUTONIA, - IWAD_CHEX, - IWAD_HERETIC, - IWAD_HEXEN, - IWAD_STRIFE, - IWAD_FREEDOOM1, - IWAD_FREEDOOM2, - IWAD_FREEDM, - NUM_IWAD_TYPES -} IWAD; - -static NSString *IWADLabels[NUM_IWAD_TYPES] = -{ - @"Doom", - @"Doom II: Hell on Earth", - @"Final Doom: TNT: Evilution", - @"Final Doom: Plutonia Experiment", - @"Chex Quest", - @"Heretic", - @"Hexen", - @"Strife", - @"Freedoom: Phase 1", - @"Freedoom: Phase 2", - @"FreeDM", -}; - -static NSString *IWADFilenames[NUM_IWAD_TYPES + 1] = -{ - @"doom.wad", - @"doom2.wad", - @"tnt.wad", - @"plutonia.wad", - @"chex.wad", - @"heretic.wad", - @"hexen.wad", - @"strife.wad", - @"freedoom1.wad", - @"freedoom2.wad", - @"freedm.wad", - @"undefined" -}; - -@implementation IWADController - -- (void) getIWADList: (NSPathControl **) iwadList -{ - iwadList[IWAD_DOOM1] = self->doom1; - iwadList[IWAD_DOOM2] = self->doom2; - iwadList[IWAD_TNT] = self->tnt; - iwadList[IWAD_PLUTONIA] = self->plutonia; - iwadList[IWAD_CHEX] = self->chex; - iwadList[IWAD_HERETIC] = self->heretic; - iwadList[IWAD_HEXEN] = self->hexen; - iwadList[IWAD_STRIFE] = self->strife; - iwadList[IWAD_FREEDOOM1] = self->freedoom1; - iwadList[IWAD_FREEDOOM2] = self->freedoom2; - iwadList[IWAD_FREEDM] = self->freedm; -} - -- (IWAD) getSelectedIWAD -{ - unsigned int i; - - for (i=0; iiwadSelector titleOfSelectedItem] == IWADLabels[i]) - { - return i; - } - } - - return NUM_IWAD_TYPES; -} - -// Get the location of the selected IWAD. - -- (NSString *) getIWADLocation -{ - IWAD selectedIWAD; - NSPathControl *iwadList[NUM_IWAD_TYPES]; - - selectedIWAD = [self getSelectedIWAD]; - - if (selectedIWAD == NUM_IWAD_TYPES) - { - return nil; - } - else - { - [self getIWADList: iwadList]; - - return [[iwadList[selectedIWAD] URL] path]; - } -} - -static const char *NameForIWAD(IWAD iwad) -{ - switch (iwad) - { - case IWAD_HERETIC: - return "heretic"; - - case IWAD_HEXEN: - return "hexen"; - - case IWAD_STRIFE: - return "strife"; - - default: - return "doom"; - } -} - -// Get the name used for the executable for the selected IWAD. - -- (const char *) getGameName -{ - return NameForIWAD([self getSelectedIWAD]); -} - -- (void) setIWADConfig -{ - NSPathControl *iwadList[NUM_IWAD_TYPES]; - NSUserDefaults *defaults; - NSString *key; - NSString *value; - unsigned int i; - - [self getIWADList: iwadList]; - - // Load IWAD filename paths - - defaults = [NSUserDefaults standardUserDefaults]; - - for (i=0; iiwadSelector selectItemWithTitle:IWADLabels[i]]; - break; - } - } -} - -// Set the dropdown list to include an entry for each IWAD that has -// been configured. Returns true if at least one IWAD is configured. - -- (BOOL) setDropdownList -{ - NSPathControl *iwadList[NUM_IWAD_TYPES]; - BOOL have_wads; - id location; - unsigned int i; - unsigned int enabled_wads; - - // Build the new list. - - [self getIWADList: iwadList]; - [self->iwadSelector removeAllItems]; - - enabled_wads = 0; - - for (i=0; i 0) - { - [self->iwadSelector addItemWithTitle: IWADLabels[i]]; - ++enabled_wads; - } - } - - // Enable/disable the dropdown depending on whether there - // were any configured IWADs. - - have_wads = enabled_wads > 0; - [self->iwadSelector setEnabled: have_wads]; - - // Restore the old selection. - - [self setDropdownSelection]; - - return have_wads; -} - -- (void) saveConfig -{ - NSPathControl *iwadList[NUM_IWAD_TYPES]; - IWAD selectedIWAD; - NSUserDefaults *defaults; - NSString *key; - NSString *value; - unsigned int i; - - [self getIWADList: iwadList]; - - // Store all IWAD locations to user defaults. - - defaults = [NSUserDefaults standardUserDefaults]; - - for (i=0; iconfigWindow isVisible]) - { - [self->configWindow makeKeyAndOrderFront: sender]; - } -} - -// Callback method invoked when the close button is clicked. - -- (void) closeConfigWindow: (id)sender -{ - [self->configWindow orderOut: sender]; - [self saveConfig]; - [self setDropdownList]; -} - -- (void) awakeFromNib -{ - [self->configWindow center]; - - // Set configuration for all IWADs from configuration file. - - [self setIWADConfig]; - - // Populate the dropdown IWAD list. - - if ([self setDropdownList]) - { - [self setDropdownSelection]; - } -} - -// Generate a value to set for the DOOMWADPATH environment variable -// that contains each of the configured IWAD files. - -- (char *) doomWadPath -{ - NSPathControl *iwadList[NUM_IWAD_TYPES]; - NSString *location; - unsigned int i; - BOOL first; - char *env; - size_t env_len; - - [self getIWADList: iwadList]; - - // Calculate length of environment string. - - env_len = 0; - - for (i=0; i 0) - { - env_len += [location length] + 1; - } - } - - // Build string. - - env = malloc(env_len); - strlcpy(env, "", env_len); - - first = YES; - - for (i=0; i 0) - { - if (!first) - { - strlcat(env, ":", env_len); - } - - strlcat(env, [location UTF8String], env_len); - first = NO; - } - } - - return env; -} - -- (NSString *) autoloadPath -{ - NSArray *array = NSSearchPathForDirectoriesInDomains( - NSApplicationSupportDirectory, NSUserDomainMask, YES); - if ([array count] == 0) - { - return nil; - } - - IWAD selectedIWAD = [self getSelectedIWAD]; - if (selectedIWAD == NUM_IWAD_TYPES) - { - return nil; - } - - NSString *base = [array objectAtIndex:0]; - return [NSString pathWithComponents: - [NSArray arrayWithObjects: base, @PACKAGE_TARNAME, @"autoload", - IWADFilenames[selectedIWAD], nil]]; -} - -// Set the DOOMWADPATH environment variable to contain the path to each -// of the configured IWAD files. - -- (void) setEnvironment -{ - char *doomwadpath; - char *env; - - // Get the value for the path. - - doomwadpath = [self doomWadPath]; - - asprintf(&env, "DOOMWADPATH=%s", doomwadpath); - - free(doomwadpath); - - // Load into environment: - - putenv(env); - - //free(env); -} - -// Examine a path to a WAD and determine whether it is an IWAD file. -// If so, it is added to the IWAD configuration, and true is returned. - -- (BOOL) addIWADPath: (NSString *) path -{ - NSPathControl *iwadList[NUM_IWAD_TYPES]; - NSArray *pathComponents; - NSString *filename; - unsigned int i; - - [self getIWADList: iwadList]; - - // Find an IWAD file that matches the filename in the path that we - // have been given. - - pathComponents = [path pathComponents]; - filename = [pathComponents objectAtIndex: [pathComponents count] - 1]; - - for (i = 0; i < NUM_IWAD_TYPES; ++i) - { - if ([filename caseInsensitiveCompare: IWADFilenames[i]] == 0) - { - // Configure this IWAD. - - [iwadList[i] setURL: [NSURL fileURLWithPath: path]]; - - // Rebuild dropdown list and select the new IWAD. - - [self setDropdownList]; - [self->iwadSelector selectItemWithTitle:IWADLabels[i]]; - return YES; - } - } - - // No IWAD found with this name. - - return NO; -} - -- (BOOL) selectGameByName: (const char *) name -{ - NSPathControl *iwadList[NUM_IWAD_TYPES]; - NSString *location; - const char *name2; - int i; - - // Already selected an IWAD of the desired type? Just return - // success. - if (!strcmp(name, [self getGameName])) - { - return YES; - } - - // Search through the configured IWADs and try to select the - // desired game. - [self getIWADList: iwadList]; - - for (i = 0; i < NUM_IWAD_TYPES; ++i) - { - location = [[iwadList[i] URL] path]; - name2 = NameForIWAD(i); - - if (!strcmp(name, name2) - && location != nil && [location length] > 0) - { - [self->iwadSelector selectItemWithTitle:IWADLabels[i]]; - return YES; - } - } - - // User hasn't configured any WAD(s) for the desired game type. - return NO; -} - -@end - diff --git a/games/NXDoom/pkg/osx/Info.plist.in b/games/NXDoom/pkg/osx/Info.plist.in deleted file mode 100644 index 13da040dd8a..00000000000 --- a/games/NXDoom/pkg/osx/Info.plist.in +++ /dev/null @@ -1,104 +0,0 @@ - - - - - CFBundleIdentifier - org.chocolate-doom.launcher - CFBundleDevelopmentRegion - English - CFBundleDisplayName - @PACKAGE_NAME@ - CFBundleExecutable - launcher - CFBundleGetInfoString - @PACKAGE_STRING@ - CFBundleIconFile - app.icns - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - @PACKAGE_NAME@ - CFBundlePackageType - APPL - CFBundleShortVersionString - @PACKAGE_VERSION@ - CFBundleVersion - @PACKAGE_VERSION@ - NSHighResolutionCapable - true - NSPrincipalClass - NSApplication - NSMainNibFile - launcher - NSHumanReadableCopyright - Copyright (C) 1993-2015, id Software and Raven Software, Simon Howard, James Haley, Samuel Villarreal and other contributors. - -Licensed under the GNU GPL v2. - - - - CFBundleDocumentTypes - - - CFBundleTypeName - Doom WAD file - CFBundleTypeIconFile - wadfile.icns - CFBundleTypeRole - Viewer - CFBundleTypeExtensions - - wad - - - - CFBundleTypeName - Doom demo recording - CFBundleTypeIconFile - wadfile.icns - CFBundleTypeRole - Viewer - CFBundleTypeExtensions - - lmp - - - - CFBundleTypeName - Doom Dehacked patch - CFBundleTypeIconFile - wadfile.icns - CFBundleTypeRole - Viewer - CFBundleTypeExtensions - - deh - - - - CFBundleTypeName - Heretic HHE patch - CFBundleTypeIconFile - wadfile.icns - CFBundleTypeRole - Viewer - CFBundleTypeExtensions - - hhe - - - - CFBundleTypeName - Strife Sehacked patch - CFBundleTypeIconFile - wadfile.icns - CFBundleTypeRole - Viewer - CFBundleTypeExtensions - - seh - - - - - diff --git a/games/NXDoom/pkg/osx/LauncherManager.h b/games/NXDoom/pkg/osx/LauncherManager.h deleted file mode 100644 index fb8a5cf5d86..00000000000 --- a/games/NXDoom/pkg/osx/LauncherManager.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef LAUNCHER_LAUNCHERMANAGER_H -#define LAUNCHER_LAUNCHERMANAGER_H - -#include -#include -#include "IWADController.h" - -@interface LauncherManager : NSObject -{ - IWADController *iwadController; - - id launcherWindow; - id launchButton; - - id commandLineArguments; -} - -- (void) launch: (id)sender; -- (void) runSetup: (id)sender; -- (void) awakeFromNib; -- (void) clearCommandLine; -- (BOOL) addIWADPath: (NSString *) path; -- (void) addFileToCommandLine: (NSString *) fileName - forArgument: (NSString *) args; -- (BOOL) selectGameByName: (const char *) name; -- (void) openTerminal: (id) sender; - -- (void) openREADME: (id) sender; -- (void) openINSTALL: (id) sender; -- (void) openCMDLINE: (id) sender; -- (void) openCOPYING: (id) sender; -- (void) openDocumentation: (id) sender; - -@end - -#endif /* #ifndef LAUNCHER_LAUNCHERMANAGER_H */ - diff --git a/games/NXDoom/pkg/osx/LauncherManager.m b/games/NXDoom/pkg/osx/LauncherManager.m deleted file mode 100644 index 4e6e33e5296..00000000000 --- a/games/NXDoom/pkg/osx/LauncherManager.m +++ /dev/null @@ -1,410 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include "Execute.h" -#include "LauncherManager.h" -#include "config.h" - -@implementation LauncherManager - -// Save configuration. Invoked when we launch the game or quit. - -- (void) saveConfig -{ - NSUserDefaults *defaults; - - // Save IWAD configuration and selected IWAD. - - [self->iwadController saveConfig]; - - // Save command line arguments. - - defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:[self->commandLineArguments stringValue] - forKey:@"command_line_args"]; -} - -// Load configuration, invoked on startup. - -- (void) setConfig -{ - NSUserDefaults *defaults; - NSString *args; - - defaults = [NSUserDefaults standardUserDefaults]; - - args = [defaults stringForKey:@"command_line_args"]; - - if (args != nil) - { - [self->commandLineArguments setStringValue:args]; - } -} - -// Get the next command line argument from the command line. -// The position counter used to iterate over arguments is in 'pos'. -// The index of the argument that was found is saved in arg_pos. - -static NSString *GetNextArgument(NSString *commandLine, int *pos, int *arg_pos) -{ - NSRange arg_range; - - // Skip past any whitespace - - while (*pos < [commandLine length] - && isspace([commandLine characterAtIndex: *pos])) - { - ++*pos; - } - - if (*pos >= [commandLine length]) - { - *arg_pos = *pos; - return nil; - } - - // We are at the start of the argument. This may be a quoted - // string argument, or a "normal" one. - - if ([commandLine characterAtIndex: *pos] == '\"') - { - // Quoted string, skip past first quote - - ++*pos; - - // Save start position: - - *arg_pos = *pos; - - while (*pos < [commandLine length] - && [commandLine characterAtIndex: *pos] != '\"') - { - ++*pos; - } - - // Unexpected end of string? - - if (*pos >= [commandLine length]) - { - return nil; - } - - arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos); - - // Skip past last quote - - ++*pos; - } - else - { - // Normal argument - - // Save position: - - *arg_pos = *pos; - - // Read until end: - - while (*pos < [commandLine length] - && !isspace([commandLine characterAtIndex: *pos])) - { - ++*pos; - } - - arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos); - } - - return [commandLine substringWithRange: arg_range]; -} - -// Given the specified command line argument, find the index -// to insert the new file within the command line. Returns -1 if the -// argument is not already within the arguments string. - -static int GetFileInsertIndex(NSString *commandLine, NSString *needle) -{ - NSString *arg; - int arg_pos; - int pos; - - pos = 0; - - // Find the command line parameter we are searching - // for (-merge, -deh, etc) - - for (;;) - { - arg = GetNextArgument(commandLine, &pos, &arg_pos); - - // Searched to end of string and never found? - - if (arg == nil) - { - return -1; - } - - if (![arg caseInsensitiveCompare: needle]) - { - break; - } - } - - // Now skip over existing files. For example, if we - // have -file foo.wad bar.wad, the new file should be appended - // to the end of the list. - - for (;;) - { - arg = GetNextArgument(commandLine, &pos, &arg_pos); - - // If we search to the end of the string now, it is fine; - // the new string should be added to the end of the command - // line. Otherwise, if we find an argument that begins - // with '-', it is a new command line parameter and the end - // of the list. - - if (arg == nil || [arg characterAtIndex: 0] == '-') - { - break; - } - } - - // arg_pos should now contain the offset to insert the new filename. - - return arg_pos; -} - -// Given the specified string, append a filename, quoted if necessary. - -static NSString *AppendQuotedFilename(NSString *str, NSString *fileName) -{ - int i; - - // Search the filename for spaces, and quote if necessary. - - for (i=0; i<[fileName length]; ++i) - { - if (isspace([fileName characterAtIndex: i])) - { - str = [str stringByAppendingString: @" \""]; - str = [str stringByAppendingString: fileName]; - str = [str stringByAppendingString: @"\" "]; - - return str; - } - } - - str = [str stringByAppendingString: @" "]; - str = [str stringByAppendingString: fileName]; - - return str; -} - -// Clear out the existing command line options. -// Invoked before the first file is added. - -- (void) clearCommandLine -{ - [self->commandLineArguments setStringValue: @""]; -} - -// Add a file to the command line to load with the game. - -- (void) addFileToCommandLine: (NSString *) fileName - forArgument: (NSString *) arg -{ - NSString *commandLine; - int insert_pos; - - // Get the current command line - - commandLine = [self->commandLineArguments stringValue]; - - // Find the location to insert the new filename: - - insert_pos = GetFileInsertIndex(commandLine, arg); - - // If position < 0, we should add the new argument and filename - // to the end. Otherwise, append the new filename to the existing - // list of files. - - if (insert_pos < 0) - { - commandLine = [commandLine stringByAppendingString: @" "]; - commandLine = [commandLine stringByAppendingString: arg]; - commandLine = AppendQuotedFilename(commandLine, fileName); - } - else - { - NSString *start; - NSString *end; - - // Divide existing command line in half: - - start = [commandLine substringToIndex: insert_pos]; - end = [commandLine substringFromIndex: insert_pos]; - - // Construct new command line: - - commandLine = AppendQuotedFilename(start, fileName); - commandLine = [commandLine stringByAppendingString: @" "]; - commandLine = [commandLine stringByAppendingString: end]; - } - - [self->commandLineArguments setStringValue: commandLine]; -} - -- (void) launch: (id)sender -{ - NSString *iwad; - NSString *args; - char *executable_name; - const char *game_name; - - [self saveConfig]; - - iwad = [self->iwadController getIWADLocation]; - args = [self->commandLineArguments stringValue]; - - if (iwad == nil) - { - NSRunAlertPanel(@"No IWAD selected", - @"You have not selected an IWAD (game) file.\n\n" - "You must configure and select a valid IWAD file " - "in order to launch the game.", - @"OK", nil, nil); - return; - } - - game_name = [self->iwadController getGameName]; - asprintf(&executable_name, "%s%s", PROGRAM_PREFIX, game_name); - - ExecuteProgram(executable_name, [iwad UTF8String], - [args UTF8String]); - [NSApp terminate:sender]; -} - -// Invoked when the "Setup Tool" button is clicked, to run the setup tool: - -- (void) runSetup: (id)sender -{ - const char *game_name; - char *arg; - - [self saveConfig]; - [self->iwadController setEnvironment]; - - // Provide the -game command line parameter to select the game - // to configure, based on the game selected in the dropdown. - - game_name = [self->iwadController getGameName]; - asprintf(&arg, "-game %s", game_name); - - ExecuteProgram(PROGRAM_PREFIX "setup", NULL, arg); - - free(arg); -} - -// Invoked when the "Terminal" option is selected from the menu, to open -// a terminal window. - -- (void) openTerminal: (id) sender -{ - char *doomwadpath; - - [self saveConfig]; - - doomwadpath = [self->iwadController doomWadPath]; - - OpenTerminalWindow(doomwadpath); - - free(doomwadpath); -} - -- (void) openREADME: (id) sender -{ - OpenDocumentation("README"); -} - -- (void) openINSTALL: (id) sender -{ - OpenDocumentation("INSTALL"); -} - -- (void) openCMDLINE: (id) sender -{ - const char *game_name; - char filename[32]; - - // We need to open the appropriate doc file for the currently - // selected game. - - game_name = [self->iwadController getGameName]; - snprintf(filename, sizeof(filename), "CMDLINE-%s", game_name); - - OpenDocumentation(filename); -} - -- (void) openCOPYING: (id) sender -{ - OpenDocumentation("COPYING"); -} - -- (void) openDocumentation: (id) sender -{ - OpenDocumentation(""); -} - -- (void) openAutoload: (id) sender -{ - NSFileManager *fm = [NSFileManager defaultManager]; - NSString *path = [self->iwadController autoloadPath]; - - if (path == nil) - { - return; - } - - if (![fm fileExistsAtPath:path]) - { - [fm createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:nil]; - } - - [[NSWorkspace sharedWorkspace] openFile:path withApplication:@"Finder"]; -} - -- (void) awakeFromNib -{ - [self->launcherWindow setTitle: @PACKAGE_NAME " Launcher"]; - [self->launcherWindow center]; - [self->launcherWindow setDefaultButtonCell: [self->launchButton cell]]; - [self setConfig]; -} - -- (BOOL) addIWADPath: (NSString *) path -{ - return [self->iwadController addIWADPath: path]; -} - -- (BOOL) selectGameByName: (const char *) name -{ - return [self->iwadController selectGameByName: name]; -} - -@end - diff --git a/games/NXDoom/pkg/osx/PkgInfo b/games/NXDoom/pkg/osx/PkgInfo deleted file mode 100644 index 6f749b0f376..00000000000 --- a/games/NXDoom/pkg/osx/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPL???? diff --git a/games/NXDoom/pkg/osx/Resources/app.png b/games/NXDoom/pkg/osx/Resources/app.png deleted file mode 100644 index 5b932e8cf86ca68c79b71a41458df6c1809011f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4597 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L009O7009O8&C@fy00007bV*G`2iXY` z5H$-ml?{Rb01kT^*L4B9(Mi*Z$G7)9>>>&-=XZ_k9EZ&oALE{*MeOwZAT4*KV)&8Snop z01?oD2oM7TfCH3(GEl7nsnl+}2Jp`YNP3gO>p%indCSc={naD)eD~f&Q`6G_dj6#{ z(Dd%>uDxVvXxIS4HK0Nb;GYe|n_)l!8i6%G|H18dH06(OGA)~}AGrxx_v5*z;_L0{ zv4+Nzuk6};V9(EfdH-X;F<`pJh*x{3P$xC-e*=IBgn$)y|MSh?+_oh8?w|kqL9D7v z)UOc@Xb@~f^K4eET*dNrm*Q3mOqIN2*L?H~p9PKrQ#DD+HFl&LJ7%5K{wxxj(|rrD z_LfiG@bP2)M}nK)^#MM4>sQ!(#deCWN=4B4=x1&t5b!fRFvt@R@4zTdM#Ei~SGo`M zj@RnM0eqkCNL;2%Qrl?R)N9PTZ&hZ}MYxT>7W|qYe)G$>Y+18-?dmPp(9yM)^uT_K zQzuxlVKaWwBH7nXw7HE$>mt@%eicq7&*f{DZd!HOw$`VgeWACO?ZCB(h7Voc)b!oU zB7xQ2*=*W$J)su-n+76XAb6!#j2*!Gf4}S7w_d$=(UpnSTbOwL1*VU_h9l{;ZM+ge z5E$9FlcNXrG2QnX@#c1fs>O-%NnU#9Dc-Yb=~A`1EBo5M?oq&47xr!beJ*&_fwH>v z=FZsmC5D{XH(N;6*!F5nT~vKY7bw^WuVSXEj1b)1 zQxb%yvyu_je5?Pyv*BF|4gKk`4me!+nLSH za(r~0gx|3} z9=zmWwlGz8T`p7~(m8@}1vc#b%{_Nir;mjM)u26UFnD}~!O;m63EJ8haqZhTQ<@wk zIoQMVk3YiR*Lw))Dy~(=b{w8NGR5+sjo#3PS4@#uaVgehpZ@TkW6v-1=`lwMUvk_O z&a&}}3%d%UI%=zJH+4q0uMFz#`!l&|@06_Eg^f|F3*M-?&HAT*@%_7+b-UfnB*~?d zy!!fK%9$kZxpq72H*ThD{U*}0Ssr_OCwmU`V@NIqvr5UTV%jc>BJo)FNj5BMK=mw^ zZQMpWm87YCDfj;V`IkEVdRW#YmkgB!@qF5zbp)QtNxG^UT{kUnd{;;jIGimeYa@$Q z1AO55>QfKj)uKD?f*>LY(Ad_=+NEu5yZTyQ=@}%MO7X%oPt$*>hmbB|RvmnP z1J`vqJT}9L={&tBGU$p3qKIYN%nbFgc=aVzig|#5g(oS}#r4o#SwZ~Lu-vHlTR#82 zE$i+EnreM%o`f`@<<77E!&lZf2yaUdA7El^4A*se`GuWKjF0nbcQ10az|`mod~S(U zW|ore5Y$!Ns>5J1M>1=YGcBfb72dug!Czi?6_c4F5)M_{WbDu$-uZ!#X|M0zlZl4o zYx~QRC`uxtC~|$&p(;w`JPA=0=iP`Rhf1P!MO;*#Jvs45AYE&W$o1Ve9t*3EW1$#+ zD$~a~a(IF#d&gPa=%+IlM3*G8WsAe(84@9#235wVYaBf}L)5R4&Rdwa!#mfs(cqUk zI(UMJP@-fTuN0?1Znh1pg?Cc&UnH{7h;$!#lAYDyiwqCl1-V@1*swY%6LqRq4GeOE(em^mR zAx&|8Ya6qnCVp3r&a)gzbA(#(V!iWFo8xCc^^dpzWV9%Z{r2Sn)~#BBu1d&~$i|K+ z9qYF6wsl=-ibVfJ7EL!usx7Qo+Cf)KlnpDF@{#vk&9bhQcnG+z$Nm!;9@#s>k+BS! zqDeM6jx5Q=HbW8OeqB}#gSlJMC47dApo%=6nxILuQR<$nhC#&8{I!^cg$y`A4jA7# zRCp{s*!Ss?VMxRxeDQ-@x&9-cAlSB?N-mAw*~|5Yj%1g}O^uMAEV4Sbi2lhL9)9{o zuHUwikfCwi)-|k7<`D2GI3maLV&;(4-h2CZ@7eM0j>e6$CZih0nd~a30Gu8LGyzpK z<~J#=D4h?0TN|_rKfV9K?%n@(8-vp&-gfy``d<7U-~9U5dGDr9Y)|6kRGQhcO=rwc zAQ;4ROoDzN%NBRg7H_~GZ=p0ZftAY2*MtDHy| zX{@?5_!S(pLTgJ5&#@>bM@UVLGg~NgB3-1@lb9$RuUa8sX|HBmH7;a@;nA4 zO+fV)GN7EbhN%aj0)c0Lx8qiIrk`*y$YYQEmV#Nuth#iyM#1&yK9)jLMcQKlI^upN zvlTjG63NMNvLy>e6e-ybBk2PBkEO_$ZS1N`xsc}*AG>kGeZSfu(RyC&O!!6cL4xRKvj%+J}T+z zSvwx}034vwbKuZ(ZTXq2qmsq0iCN-}&3u0ICVu&+muQdq=x7WQ@hMbn2T_pF6&Xzt zaXknc3ga^+_8d#m)f}QN=3`Y`lqb56(;U|EQl;HM(ej*%W=Qh@$W;lyz5sx>umtB}rDSds{`e9N`39h^)({Mg+;ei9HY&#R;-CaX@*;nSLMm*nQx zfStiP^yoYQnai8b+NN0uAoIg}e)`PqxBcxE*Q~X+P0ki6TNaVZ5t6P)wqzjy)A1T=-|e1#1wL+D|Tu2!8HuSh7O(AF9Py~sUx|KeWYHDDBoih@wJr$?&R;E^)` zTH^Qu(KFfhir9k#^98?ZlYJoxxj+#}$%>LYIFu$=u_=^ox)#HM{tWGLKk2;1rp0kI zMIu+W7%Zjms~%(dBI$y~(ujef3FOQQ!4k;YmAj$;1TbFfHGW5+DrwTZKm-YV`kCoo za?c+21XUCy2^{APi28BXtL@#S|LKk&{W#*+mo?!-zQ&u8!_H1?jz67(qy6lZuP znc}6fDO_N~>JUrY4K7_B#HUF##dX>eK3Wq7i3Yt=3%oqHM05qg71jBZv@3e}jZ;?Y zGh`I~Yyh4tVyKdMzCJKl$a!GY*Vfgq9-q-Rt&bwhBFS`_v8>5Jd792v9|_kbHLFlE z9mXar1pP9i0HL5v#d1+(fw5$T=74C`5>q|>5*JT36m+dF<0|+J`E+U(TbTF!R38vg z6-A=#%=H6rApjRB0HdG#&aeI&*tqg5@Bc=NHkz1Bnq0G`fqlI>UfDlGYm<&F3oL3f zNM$TmE(uUE9pVv%P*5Wp)+m&!Jk^~&v;ctTfvbl!B4O>!=%9=E3<@nwFS9<$AkOp0C)hF>v%>`AskZY1JLEu0K}?DB&_1qRf^&h1x**_Hv%v>7tH{Z zgCnK=*KhK@);jGFbk z3NC`H`!phfzj8*dq_t(>g7ja|>S9Z%Cl zFA_e(fTn>@cPSOe>FckON=rn-^J_p;M08CO&u63OVxkOWN0VA5pUvtazeKTAMbi{S zv5bd6-_R86SBB_p3(?xzjx1UD4GGV)87;OQUs%9%->qsA;W`Fn$tIJYVCa~F>&k>f zX9pz9B8Db8a|`-60^rpE%$B9Kd%6}Eu6q3WB#Ya9j80aF#bPwa6%50NuDC#zTxNu7 z6&yjqtW;36#db|TPW|`Vw(DxLM5L|;3I&CHULX`WcQC4^(A*L!7fffmj?oJOp!V`? zZ(q8*bCY+~`>tuiaTTVsRa`62%lj&1^EO*IwK8-f$HvtW6i*`LSFo%iN0Qj}TOg-x z)Nwpj6VGy)^Id^Rzzw%FPuzOvuCE>Ln;x25&|eGy8_3`Lvj<*%|K_b=w;8)4zN-S=bDU}MuV?IVsrdiZt(0w>_mW2XXmgB05-`L1wd+#H?t zdOrNghyTU0oTEVU%`o8B0>}?=R#-gdCC$>G?9DY$>HC8=O?fI1{kiL^pr2Q2Iewm z0(pO=eejZ{>DI#oDJmm5x|YR>H8fJGm{_KTNQsfLG#$+XimGw&@bPn6XdMHn;d3(} zD7u?>gHxaV+H-gA>797FHUwsBnRhSNh3Xqy(YBq6B17k*78*iT_8v?!natrhE}=-2 zXsm^mU49gwK{i*WBCj8VL-iIq-_vCY|2Y^a34Zh7aOJ>9Z+q~L@+rwo)W)0YxxVLO z0N6nB<}d&2gZut?<8=r74pJ)0MB|;bGzch)PPvq!FngS!5x^?tn9Wp>)g|Y%&{GnT z1pI2<>jjZy#h<(H(Se7){o~y`YLZFS9Zj9{x)=a+2XUoRK1+LR7(ozla#NUPl|MW^ z$u(OWFufRxS0-=8Ni>$3O=4XDz`R3?swcanv)a^WzV^(WdwNbwX7*h2dn*9uPU6ds zV`7>%g+hf`Q#*!kbIlb|{A!M4qbF%x9-&%HGE=ab$vWo)-~m-ZI2BmdHq4&ka_hpNFq(1+k==^MykS3QWS3@)RJ=*`s?LXT6K%L86P%>{7fDM%LcH4nQ@6Z)T2d3$0^|NAG zCqci=#AFgfE#lZN2ohF#hT7`RJV!7#kg9s}AwM3_+|ik#=YZ!RVyTg5OHaJA?s}tKa*R_nIcv8qmVUO6FV# zdR$~7+k0Lg?`vs_<5mk8{s^m - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select a game: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Command line arguments: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - WAD - wad - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WAD - wad - - - - - - - - - diff --git a/games/NXDoom/pkg/osx/Resources/launcher.nib/keyedobjects.nib b/games/NXDoom/pkg/osx/Resources/launcher.nib/keyedobjects.nib deleted file mode 100644 index 7e7859ae3ed051b76c381ded90e1a05bbd97aa25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31078 zcmeEv2Xqrh5a{hnI>{$v4%3@0+qm1ZCHLNC%T2cBf=w|l!WOQ$P(pw^LJ7S?D4~WH z2qc8wA@mx02@nV&5JCt6k`O}R&z@XFOY;AJ|God-|28L|?)G-d&d$!x%ngOr<;L1N zZ|`#yqA(?*#FT`h<$dG@-MbAi)YKZQD!X^9D(q({s;kZIR!~z^YJ|&~-Ri2Uttm8m z(YjW61|_9rlr7~zb)(!UFDjkNp!8HGl|>a$71aCGP--$Yh5Cq^L(Qj_Q!A*I)ECrN zYA3aqIzSz!PEaSQv(zQ(I(3)&iTZ_lh+3g`s1xdpx*%`lhx}0}3Pa&23dJD}ibshk z3F%M<%0WF)8LC9@p&{sfG!zX(!x4vgGy;8q#-I<;G&Bp%Msv}}XgOMe)}hbQRie`!CiI$62i`Iy~6m1Y~73~)t5giqs7M&4Y6x|ekC%Ps2 zS@b~kSoB2nLiAEB70bld;@0BM;x1w*v9s7q>@5x!hlpduvEo#*PMjm|E-n-oiOa<0 z;sN4;;^AUWJYGCWJXt(j{E>L6c%^ui_;c|W;!Wbc;)CKt;*;W2;&b9}#ovo>i|>nn z7C#dIEx{6zgptT4tfaHVMq(>*mZ&6ZNw6eD5+~6}QYAV`t|U)VC@GQ@OAL~}k}^rT zq`#y_GEg!|GE_25@_}TeWUOSIWU^$6WTs@6WS(TcWU*w4WQAm<`s=nv>I^dx#RJ%ye@&!gwlAJYryCG;x#Q+hSMhW?!1OmCsL(%b0W^g;R% zeV9H%pQO*zSLko(tMoPcJNifZ9{m&jkp6>yO8-f}kV>SqR4TQUwwAV$wv~30c9trn zc2Xy)r&KBRlCGAnm9CR+kZzRjkRFmAmL8E_mVPh&S^9_csq}9dB||bs)>_s^W+Ste zxygKFVX|;poGewQljX|tWJR)aS%s`pHb^#9Hca-RY?5rUY?^GAY_4pfY?bU&*;?5; z*_X0yvhA|nvOTh+vQx6JWfx_aWY;Wm85&tp$<$irOJ)PLluBbZGMkvq%ob)VvyIu# z>|k~>yO`a~9%e7IkNJw(&m3S5GKZMM%n{}&bBsC8oM28erEOU-I&s<i7`th|-nTHadTM&4H5PTpSLLEcf`N#0rBMc!3zBe#_+ID_o+eM1XUO&POnH_(Tb?7&llRK%R#{(O{tab8F_fIL zq*_o`R7;AbT2aN zrs{RZ;@a$j@_IvUKHCz$niRC@3N&u`o@5vd_dBNQql$_QwYA1VW4W(QVfzZ7DTbjSUqXv|!YHG8)6_pp%*5;WIBds~i4d&4gJo=tTD|tMPlfVa$ zr}B6@k8Yo#6hN~bW#0n`BTuFlR2VoBCkEW3s$oScDj<}ep&ThE%9(P>Gxc8yt-6~| z4Yj@D(fZoDstOaaOQ4-=_eRpsQ0@T0gHi%Y$|@6g7E_)a&BcGqwxYZ#6{V(pC|}Bt z@}~l*Kq?5D2U8(bC>2J9QxQ}o6-7l;F;pxSM`@^d_|;O0R1!>$6e<<&rNJPWSe5~! zlFxQc)o0ZjYP6MghMK+wMFwr1p+Z}1sH`*gH5zJwEK}o5V_mr+H&vffFi3BF&(PFK zw$U(u83rJ-rT~U0pY0?x(SQ``i)svpN*IAUfMI%u+$v9bhE%E{D}7nIaCQ6LN#3>(2%IL~KWH9n=U8(eNk zDX1;uq#VV`xB;A;tGD0=!fzcnh+|l6-DeO*aTXlKO7qzcLx%YHd3z{)0|SS8D2Dj? zs67;_AitqQK?q&a0E2=OgMvtgt0K9ezOty)Py+*OLa_G`wXcuTPaOo0cn1uPwYSrIeBCN0o6cID0OHOXV`S zJg$%{jvZ?-nS1wgU)lzj-JvD$D2%;5B^#LrCDGf~X7(;n^P6Iyq ztPRYA@^YAu$yFsV8OoCj23OVB#Tsi&DgY4I*H;^A2o?FPW2!zADAX7Y<;79u#*)ek zkO?x<+R9o(U2V3>jDxX^t0ZDn%(djKWSkugj+~<`^4WGnhNuF8j{!bp7<~L;NK~q! zLoZXqsNsM+NAc7M>H}&dHHsPygnvklrN+Uem_SXWCXopYm^aD@5vZD~@&<7R9ILBp zV0M6n5Q!?Osj9Cmj;SiIs)5mmCrb-z3W{LHq#29K3^fhtL6?Lap&1NTgNzcb*91vz zEv7(@T5t-k71zds>&mg#Y$Qd&XzLB-K)IqoQ33-S%$%d9Qq!pEK*kJeCN+zi4Xh@^ z4FlX)KpMUi5p#&NhaTalm6Z)=&9%;Ft(8O*8T5l|VJc^7H9(n3AI+ua!9(Qx5^65x zdLH`zm|8$Bq!v+&sU@&zenKrHY$0Tlt_kAgTwe`(0mLk(pst|2s)XEv0T*s@UAT5E z&9&v)XPe;lEHW`txO<*jMSThoRs*Cp)MwOMY8|y09?dB=)|q;*0MUjq2kmVQJqlW} z8Dz4z(%)Mhpz`wx@S#%SOXE*~LdA->4qTUW)OzYmY6En?k=jIUrnY3J>b0?1@DURO za8jy@4dtu_*O8^T&S$7?&~7`m18yjbffQYx&BF^bP0t1{kwb;XIO}uzhu1bOxL!!g*nRSymLBd%*dczBQUGI1h*OOQrP*$v6SeL`RKv+DteHc%lb2RT-qc z8%2pjiw&`Hrt9LqWmQQ82be1&ui*42<jB0MB=!4=fR#lt!9O1gu}Mg^eGtEfWw zECQ{46AYAEQ0xPQvl3w^TL9P8&|VG3fC1VVK${z(RT*3_f%Dr<_sMs%_pN}>YPeGc z3x$y?hvyovDum_3^c?A<3J&s(^m|w6w+Px2cuF{8Y?i^Ap@604KHM*bvlQxvaAgqS zR{`H+;A%bGD}i%!D5mGr1YAuxkoyG6j}1_&;E7@ZmgzYHl`L(fPb0K@5AG4%1j@zj zVfW|*M~FCC947XL>+#S}0X3NN6t0H~*BYTVQ%-36u?cE_z?DECTqD$zvu4hic)S<* zRR>qgfkLv1l2)~V&2xCBtl??%XMj&rI@P;WSI?T1uI;@XTAQ#?jHt;s7M+^>uz~Kk zjoO>gJzp6&ow-~Hl2ZJJTmXF7m3}R`E;&aj;P3a6^OC!8_KoB!{9bOtCk^m#ln26l z6Awy&52kO;l2s&JA!AVvzhqqA#It$KO#P5HW<4O00GG&Yl+X*gTLA|dS%bh+)A-fH zIk8Ln3Qv1d=2*TiQPA6=_jh!l6c;A!IYKGcuv-r|QKvXB-qQ1|<)QccR!-?uUEO>6 z`+pg#o9~iwFpNq4J(U{a;r+SyeeX}a*LXknzTVuz`=a;H-sim+!=0Z*(?uIaJHf-T zO>~@6z_)Fpy`rtc*&5Lf`2C{kxmP9J#DiBQoXA^IgG3V!)iubJx$Kkq+BnAvzZ$tk z+Bc3=KY?p+j)b|ykP-WD7@7BDnstqH!ZbR}NhiE6IYgH!UYS{00LcipFqxIL0KXi*4}PtUY2Fjus!$JM z4Bs*n#5Q7;SPPm-M=8WnVn1?r1f>x31;BQKV^B~fy4s2RjZ>X56>cKU}lF~YbU|%Y< zl|@Pqh1y#Ms~fSINE?cJoG#cxsNM0R`kDczYsBUS?<@oMR2y&**nr2?1x7>-8`uz7 zGvmMp(1G7Im+B34l)^~X0B7F^>wPpe9z3u!!CGAi#_1|BAlHMHw*x$|2dQJ!*VK9H z8(2?nga7p*^*i+!LP&~Qpw_4(vPF)_9jQ?ucwpmDGWcC{Q6E$Se%E^Nx_*GhgP(OS zT8vhqFTlUL7aal5>Sc5j{fHi+XIO+S!JFC@J7F*Iqeg-6G!ys2CAdF+503=z=|^}8 zUV}H`z2GH1k8j|g@NXhYBp0<4*@-+wfub0Z4!od!MKz*fqH*B&Tq0TvI^dA#tmua5 zzUWUe4Sr39*b_!EL7W9X%>LqG;tArp;IrH$-Y-5YzA1hvej#Zg=^}9lZ=_bzT~Y!* z$I;+nTrSxNzQpt3J^Y=f>2@$a0Wfa4bU%6sJpp`s>*zi7Y5ErZ8~ErtO5LSlQk}Fw zS|=SXog-Z%-7P&My)AtzlY{q7Ez^L#67ZL&IJ^`NCiOUIT`Eqk|oujQ#wYDwHCE@XdTnKsPzY}KWTlS_3buv8|OCK zHvQU+Z}VB3lWiWhwQlR%HoNVhw)5KVY+}!b6CvhjYPU)Qnc3RNsK&Shi z+jI`;T-147=k=YhbirNRx@2@2(q(Cv<6VC1YST5oYjxK-UBBvj-=>{Sq)k7Y88*9Y zeza|E8*Xc~ongD%_MW1xB1%!N_(-u|@zAb|U4mV`-D10wc7NGB+h^I2uwQ3?&4F2grHa>P- z?8!LmxU9Ijao08Wni9=w&BJ)V_#yFo5+n&p2~!g;YP)KSw5zla69W>5ChkwNOwuRK zP5Lg`Ex9InTMAA|Oqrf?HPtb-GIg_#(rIOQplvD{9%#@sD=(!A`v z<$1sLi0d)4$L*eeJxBMv(95~kpk7CMcj{fU^8#JLl7im~ zwT1Hw9~Q+F%`W<>II?&~@sEZu!!*O4zF~c*^}SmXRx-Wh$I^(>S*7=lF~+&ZU;8EW zTiEZ9GF{nb?c#oJi;>ia&A8Z@hbtE_P)~NVV zt4CXnt{HuCOvsppABsOTet2@M&)7L*UyLgrcXYh>_*vthPbivjbfRkFM-yL8>O1M= zWdF$vrqEL=r(BpCF?Hp%R@2^_c58ad^i4AqGsew$GBbbXky*a87S3j7*U!H3QSwJy z=5(7gWzO@trE|~Ei=MY`ewX=U=l}6>@yBNtL@rpnu8n3Qj{o|URYrg(0 z_OmT(J=ZQ?*KXbT&#BMrKfm`ypD!+~Pg=k4%fK(!ZgAW%e`D*7<2Ip9gEu|gT)O$j zmfS6;w!7crBL%y=P<39z3T#ckF!X`O_D&E?m0U^Wu$5#h310F2DTil>t}& z`i27|e%v+o+N|qct}pr4_1kqf{BP{M8GG~iclz(Xxm9%Qr|)aOe|~%94=sL}b;tJ3 zs=MmDJATys`1QRW_iq1G{nKCfNB`XF=lKs@9&Gp}@|WWeyFa}BYt64OA5D1N@$rf$ zzEAf3miF8A-z$Fq>yL3yJ3d|cXW*ZQp5;8d^Vh)V(&r!j?fUn&7fCO!zN~oplIvu0 zLG7Y;gCi-WzK;0wV!;Wsl-dQJ4_EL@k#D9(`>3y8aXl@e_EWB}TrssfNF8eQLoES= z;5CQVQNf{g96VGu;GeS1XW0hVRFjX++&y&)tO>zA741#Mcq>%IyJUiLjyf;+Vw*gb z#F_UAb&k3~T@=uY5`r7#Do{cGn4Y^#U1@L#3jWPy)MYSMu2R=1S8!-Hx*JXIXlU2u z0GmZS@CuR7X)y zsXr->dPe;PyV<|NoA!cwNv%Z`*j*TjkQhm*VkD(B$O17)4&Dt7vO+BpD|q+Pz&TY_ zY%CHY4Fd|w1*WFe82TD&Y7E73#U%#tnWh*j>q!J6pKVPX$>3qFET}UydQw4jqU-DG zswxEssL%m~Y~uRY8=*gNBf=P)J*BMxH@qqI(9kPkGWb}VT+J|E1fU6%2J~VL0A0YSR$m7=2@e4ms|Kc3)f!3A2Y79UotjN*{StmgMpBWSJLhUm zkBFo=H_nB#ZzZEFI1kRb6`EpU!6Gh*MNQsbWQ|%AZ?8in_?XB~D@j}8)-`X?o-|-t zayc#S8`PEh6WM^l3y~>ghwPC9>ITNI6AXe2az$=n24m`5q=cdHB6F|OP*GKBEK05_ z65QL33(q`FFhg)l6Qjo@x(K~0IF4kSp32*F>08!$UljDrlt!UNXB zfo{&j8X|-g=gTQMKh71T)ss`71>{tKrW*MmUy%C7;jZQUxd1LO7rd4RMJ0TkMFG$( z5Cx%N6heH`jj=XhGK^wXeNB;p_@Oy3PQ`fx77c?9aUjxXOsS!$tfHW%Oqd8L0!0d< zVRA4xKEDJ-P_E{HVujv(gr=kyfue@NZk1nMRh?B$2GycE*qRMM1JNKZoQvQh zxhO80i{WCqI8MXG=d)f#RTWC&UpFYL3m~*nSXEF{tgME~X{p$7x@>%K6&84 z0-r$@@K;q*R$O0Oq4M_itsc~WaD8ckx_VIUfPvlyKfl7-ih)H10mVMGg#$rp*$D76 zwHl3LfUnZ~O<;}mr^df|udRt{GS_O;1Xhx9GYQd1G>Xh;(;}@m)Gb9L(P+vQ!Yc3u zLYxr&4D^NQX8>6bYcv*(gU$5>A?UUlO+=H>Bw-ntf~JyXheY`V zr2zp~5U8k1V+C-omRy2pp@B%QWcz%TDfXoT9N2bG4 z^buK+P50)Z`HlC;Ok9TMHBN%&1=cLKi58%Ru)w|&+vL(X-P@v#YCj>`NY=`CM;rS# zM;p;vY7&H3n<9Sc5JHTpg78dbv7+2qX;6Sht*;>XI!9PSjB zuNjLd1d(9{mu11_Sb!ey+Po4SM2FB}vQ$B6g#5I^)?7B%x)0ne4J}KyQKeLKndTF*B0TC3G1y z*Ei@Yx<aI#5Pe=lgK zd=~iW698d-Uw@Nf1a=X`_w$AXkYR_9q1V7b8V07(6EKcO3FgsAK!+Gd#3&jKjwB2Q z(S0z9O5yAw`W4C1BY~x(M}Q&V%DGv~fM;M2s2z?GNiDn^7W6p7qxxV~Jmj57cSipo38;~yL$_dgSPZ{-< z3ebf0)r!ojs`7upT#3CJF!wRTyqc>rVP5$P=0VM@_X#A~AtuyGqR79Zj>F94tqeyu zqHeN4iI|xfU%~Y!H1sfKrH~-8A+I@oMUX1$Do$8x+NTJ!0L0x}(DS~&a2gm8Fm$MS z3X3`jl3rjH@HYPeVR?a^tzVJZjIQjy&qjqpm!% z<&hna9C+l&BWE7D^2nV>o;>p6ksptOc@)8;SRQG4l**$F9%b_=k4HUu)SE|rcvQ%v zQXW6i>y|DOWHp;a=0#CXDb*sszu*<2Vjh zff0=$=K@Hc6T=>;F~2FLpb~alkR8(o3@fs#X@%@xzUZ?eFEK$ z;>5kRIZ?6AB=j~8EP$LFAuk6gGV6mX!>ffpD!321VLi)*94nJ$Yu?Hee<8G@xpCaE z-lkTD8k5*Hw_5~${LRpABsYPZ!wqZDLNFF!9w1^6=TWtI8{Uq0Py_HTyc>S^f=PUX zY;QsIoA&aiw5Pa1)diI#`JAYROk;H|H9iIWo0D4Y0rUCrdInAtzlZQh*d^*@(sCA_$ z1GtGiYTKMfxPasjnz9E20>HFT2?n%p0O&@a02nLSRgoE>C~8;~g*gvPu8J(gkSi## zPh>%~V+Rof;U-H_3z3zmCEg@zC9)Q^7PS$zg%DJGQ3p{+Q72JnQ5R8Hk&Vb!q!8J0 zi@4?78g4zeh1&%qwVyl2o#M`N7rAe^Z@F9C9qvB&hJyV={=k zi5wdzgUGFMGH^?|C5@84m`J(_U$57sxKUDlynO}J>K`Rl#Nf*!hDfR?NEA$M1~O*D zke7jq}G2S#S%!d6iBHT4FFQs04ZyLl+U>@^4Tu0lTuw?4_-TCK{Gvr{}VmK zM8lit8QDb7Ms7nRJzqA{GxlBds0I7wU+8H8^t2G@nJ$_E^sEPZ)&o78xXt-&=hx{0 z|Bj)~Skz3;?Egg0e9^~EgQAje7|=L->p%wg8g zh9jTb!R>s@v;m!HsB9)?<9{M%n`nCzF?*Vb*~{%|BxZLrF$dm7jQ@Yp0WE=;mI5)S zL|+3jyMUNoK+HbwtGA3zEv!;~4XS2x&c2NtVe@F_01#ag!RAr)4KF!LHr}R$`+vlywHY>@0Gm_I*qrH3uu*8W!S6z-tJvl(2%YE7 zy@8M)SX=5q)85D*mUAKoZ)Z;%GlZ0Y(Aj2$E`R`=k9cNkX0Re|fDr~BY{++FsS>N- zg5_oI(i>Q+h;^Y>3)9Sxyr%F@EZdr484XxoY{v3R_XLx|dnZD1V$E9+y2f373qs(V zQUwXiC2>=|8=-b)2xS98-!vn1Jv)J@taqZ5E6#fhIybo+Z=w?j(^dt(GFZKR$>}@! z)7}i7et^!m&FFlWLrmkohIisqA+CH2KDW8=-^9mP@VW?M6+pZI@5HBr89u`RpIgoN z{LljeAcGX?@Rn8GD>#{X%f!5RgvmJ}9!*qUgJ0+#_oK-?YC2@!QiMS-PV#=#(4ev0~#B;=R8`m1~!lt$67w$ph zTJv+$S|k4C9czsbVEXSSS|?a*I+3+TyjHvp)|&gU*4zgr{gC_hEgKtRZ#FG7;`MJ^ zXkOn)iZ_e5G|{rNiI(5ECylf`Zl-15YqSuz9NFbHtUmv2ZFUAyIt!#67oPx99swzj zfRx|4KOnO4x=GU)Udt*rBj)S>M9g{dg(hOYX(Hw??pY%-e>M|y;~m79bm+g>XI+4p zE&?(4#6JNsPl1@HK+JRQZ+M68t;D>t7Z5-APxL$%KWU=p&qjK91g~dPjTF6Xrs&0M z6g6&bRHkL>Ur6c-By}YuNn{cWAn65=^n%Oh5$2KTABbu;Z6ua&BkFa(xTKZD8fH59 z#U<^Uj2jJ)q&%VpFF21R=9690rD3wSX?VTr6&Lt__IrzLn*H9Uxej|vIDyIjj>T8v zB5{3FP4bB0k;SWu61?*&e^5hy0&0H$xQy5~>q$wF=sxUjn-nFF}}Eu&HsHU3WBtuVtWh2UgqhEq%M0}!l;aseB#w4m0Y zP`wkuG)el~5VYn|t5*>Oo&|xK5-6AgD#2IuPWtNvEf5Yb{>Lf7=ei!Jw12-&-(5f=?%ZM0Bm2e+?q@5b>tIh9smedRPAMvOQ zH!Rzvz04bQl?)LYfJeiI8mi94j0V993U6IVfo zhmr#?xtdd-gN7>PAlZg|B|9WLCA%QiLCDky#(=OeeWWu>0y;RZ~H(71Y(&z~$g3#=>heZ6p^6 zs1S%Mpl|?20+WBDu1yScmt28-9Kx<^$cuvrLa2#dVXw05rsO-xEe_yAU+Z|Zy?az4 zygLi=C0GoqY9P%*;0q+AR2D<(gK#sgpwduohRYqiNb)1WC6XJ-qnLLPe#JC=l3yeb z3E`n+_;?h}qbN=d%zo1e2{@#CK;)~cT6lH4X-1nt{vEjRlt7LnTuAsA$S))>%^=6~ zNW-Z!6O6@%^wO+S_|x1mEuq@bQqplE={V(|JEmLER%RV1^C$^APOmrCrT5Q+Y_bXx zNipxe4fNiQ^sXblr@yOrx)TC$X#lTt zs0pAP9_79ROw(khg9w^5AnKXK zsD);^Y@|M$&LPwn@u&ovzD1SMc_t>)z3ASA`eM_l_T`bGDP4^&pbL>Nk9P8C7Z(Vx zDc7YB$}Fm{3vPr`N*f6jBah1e1xgiNZ3d-`NBw}wi@Y@gy{)Qof46&f9{k1h@R8bCy$`W#vq_Q3yOE7zn2AX*H<-lxsYB&x_qBU z!~dnr<@5@(E{E}GD5uVAc#$3^M0!D=txh<(XFW}t``!U(<6EiBr@WnVpHPGNWKmz+#o1SB`82~lsA_>KtNdb z=sTumZ-Qyro5rbo!n9UE0!2wZsIH!*e=TH`MkObk0k{tU9uNRC34q!E2;jF@0L&un zY}d$6A;(I{Gd5HfnSjNl#3pM~&8c|?z@8Iea|keq2ELmbspu78bA>fCrK-lDD6T3J z61jxHov?0O6VhVMFE44Er#S} z3xp^GDx~_N1yl+80#d3jQAYHf>WACG!lINWNVSqHl5_NSX^P~I)LxnEMIFQy;Oyc>oy2oQoyD6)UBu@_UB!<@Hj-8%TZxNEAqf@PNz(9#(&f?>(v{Lx zJX*!kkPy^@YsuL|wzLQ23x_}oZ7QT8W^kD>D7|5+?F)-z8LXk8=2!D*E$9$1J3;I4 z2=*tDFd{tql1CeOw24Ps!4?C%28;|IZ3FX(M>}AB6I3-Qzum&B2ul_$F|Z(jvfTq~ zzhEzet?-p#{vQCH0V)QjI7~vA8az5I2rJ}D%ma_XB8d1d=T<@7Zym(SHbQ`DJH%!7 zauXouVLyaUj&Ucz`FI_L*T8Ff6Fil-VfnrXezjk~A@v*hasDEKXC%a) zr9$`_w)~bnvVx5#kF2>NJUYgslRUc4qnq3;A?-!FhO+0;r>|FDGTVMgzmTq%eo55Y zXFOWNqodtZ3XGK`f!ZW#o2c?nq*`gNv`7kU0A2!nfCmR4?ET7?$6mS*_3Y1pX=OAcgtx*;)qiiKAIw6%IeH59OcEfnPW zYHMSSwL*CvVMVe40^BShO;7!wyL|1rcXF?B{X-ZgXNL3%;hylUiDw|P@Nc7uXL?d2 z2x@1;H_$zPx6yZPmw|XUq%0a^|_t^Uq}}xz~9M(W(fj? zlt&ksc+ey_Fg@WP7@8nAnIzj@pi!ov%2&RwzTP#F-zf_wQ`cM;1ar4}!2bi%pfSIc z?0gMr&>HY>uYh#6$<<>*I|61{qlPutEbm0oORr%I8V&w|nL}8dU?{IP;o5^LUv9nvyhZPIyG$k-0SA+;X^Mf7 z1Hj1SGEJ}sI}4_eFpGKs#smsMmz+21Ad=}_jY&zO?1n6}?o_RG1>|{a@GdG!R!2el zh77)e;*(iG0vW}ltHym*dN_5z^(d zk+M;;(Xuf@GN378s-XlE$*_WT;1~yn))_(Hp5@Uw9-XqLAQ}IxY%FCh8wYqzkWGX% zL}ej(B_UT#Sp%<2)j?%dg4t;veGRWAkT)@cy}Zh+Afdk$UWo8A-+G!z3<~u22~w;4 z0uaO|1x3cnx~kezMMA7O zV<5RkV8SJ^<=sZk;UsIBJv%NZvA`AN_P2`aENL6uM74h)SYP4U{S`JEK0C04RG{@ zqXdppIE--ggQJXU(_m4OMZV!zn%;Ou{=$7?QNHpE*N8$m3I4W%!y1m(aI}G=EgTTD5w(Y-0~{UU=mbY+IJ&^m6%HFXY~fJA zVMpLdm&36Va)fb%K`C!ADCJ;K%E6$NgFz_=gHjF#r5p@OIT)1ShH5e>O~#A)Cm59G zUrp!GeuuDJnHH_rKH=^jVO=n-4)6(AOa`S%12=pMc;W_oaw6E16TzOG2=?SeuqP*i zJvkBV$%$Z3P6T^$BG{7?!JeE5_T)scCnthEIT7s1iC|Ao1bcEK*pm~%o}37QG|0Ua zlMfmBup}QWfkjjtd|W4HB&Y|AJR%>T0>}QJ+j0CKPp}6z|NlJ=$*2AIJ1EEmP`xAifPHPPzT1EY0b1@+A{5!_Dlz+Bh!iL%yeP8GB%7YqhRb9 zd&Yt3#yB!gP%*}Zab?^XcgBP9WR#2-%mij4Gl`kZOkt)n)0pYZ3}z-X zix$JQnj9!kILWr977L*n-ClkL5hJt1ZFCKgISjA&Ck9~OT%VR$t`|~(}$ALT!;&CvKLwFp@ z<1ikF^EiUXkvxv#aWs!(cpS^)I38jg={(Nh zv7X17JkH{AHji_7+?~g{JkH~B4<7gAaW5YC=5aoc`|!Ac$AvsD;&CyL4Lt74;}Ra1 z^4Q4ZempMYaXF7GcwEWjDjrw!xId3;cwEclIv&^acmR(F@^}!B2lMzn9uML1`#c`X z<6%4=&SQ?pJda24_yZn~6>%;o8eyl$mzy`8GY%m+bhO%L7I2*x6vQca_ z)KQ9M<5&$F&nB>1HjzzcQ`l5i$ELCAYzC`mGubRQo6TXnv$<>@+k@@N_F{WO@rFK7 zf2oiyVvAV=+m|h2OIah^k1b=%*$TFjtzxU${%j3f%hs{=>;QHkJBS_3zQ+z>-)DzH z-KOCz$MWn5_5*e#JBl66j$uD!$Fk$t@$3Y4B0Gtl%uZpaveVe<>u*=xx>;$CpeRE!%g7I2UZ1ZB+Z!G7?A@|+Ry-vacPERZY%({B%yQoJE~PPe38p^REG zodc!0deFTgf>aE}`HgfrT?GaD>*-vM5=WEC&ka_mK6H<;x0Wg|cE+coH>K}xX`X``J{zK*uD0MG|a`vsEkbQe7PwxjM=%b*d ze4)HbK2$zRK1M!PK3+aiK3P6XzEr+NzDIsS{+;|6`3pw2y0y{^A>eQqPMX<=h+<80$<<8I?=<7E?VlVg)- z)7z$xO`%Ph%}|@sHq&k9+AOtMXS2;_zs)h5i?)<4wiVk-Y^AmqwsPARwk>U0+m5!K zY`fSx+WOjt*v8oQv|Vkx$M%fvHQUDuq-d>hQp6|{6+IRG6~h%%6^j&06sr}VDb^`A zC^jj!D7GnfDt0OMDE281C=MzPDUK+PDNZP^EAA-nDefyCC|=qjJMi|}(RNZhU%P0# zY`c6rqg|cdP`gof6Yb{OErfz!%k5U$eQLMHZmr$tcI)jn*zL7DVRy>zwB1>|Yj*eS zez%v{OYJS}<@T-Z9qpC&QT7^pJ(LH_vCp+Hx99A~+Rw0`WB-Z$XZD}lueaY|zteud z{So^!_CMG^cEAoT9XdETIrun)I`nsV-(jl5#|{e|7C9_-Sn9CMVY$Ofhff{WIIMN} z++n@Lc847fyBrQVTyePSaNXgC!*>qfJN)2q*WsSSeTN6#6x~9*6?Plm?aOX29TkqD zj+u_V9Q!%;cO2+A)p5P!HphLACmhc^UUamXg zXNj}a*}_@wZ0X$1ImNlaxu0{nbER{&bARVr=Q`&B&V!uCI!|++={(zcj`IrV9nQO) z_c-r!-tT=NP<2F1`KU7}rLT{JEUE{QHFE;^Sqmt2=Tm!2+l zF2h|mxa@SnJB%MUJhUGBL&c6sh9ab;b@Tq9hgT%%oM zT{W%=u8FS6uBom%*Y2*lu034qT!*`EaNXp(#dVwO4%c0-dtCRq?sq-y`ofKZvTGtY ziJR2T!cFeh!mXtn>(HjkYi zdpy4KIOuW2s8hEkS*njzb5-+I3sj3#i&aZht5u(?)~hzCHmSZ= z{igau^{47D)!(X@YNYO}c2c{mJ=I=nmAbdOkGfD@q&BEa)JAogx6r@2Y=Q|E_+jex`ozSZLl=@8cnd~#wXS&Z!pV>ZhptRp!pMyS!eUADZ_xaQ3FQ31CUiebJ z*jMaJ`^tPRd>P-?z8!o!`F8QO@eTCt<(uzY;9CTx084z0zGHl+_|Ej5?K{VJp6_Ab zqrS&|PxzklJ?(qe_q^{#-%GxieZTX)cQwju39I)roz z=@Q}+k`sp$hb{?i#KR4+swm4+#$o?-yPXULD>)yf(Z(d|>$C@FC&vhYt-O z9X>vMV)*3nso|@`zYaeWelGk%_@(e~!mo$Fh>%8DMp#9#5!MkA5z!HG5t@jEh{TAL z2wg;aggzoOqE|%kh&~YmBi2N$jrcrbeZ$+T1N&%21kZQhDSz5Mn%R%Y9do3heQsGx}IbCKsGFGgO8{3WVOlx>uKltYwblyj78lzWtClrl;aRTfnlRUK6mRTotsH8ASE zsL4@tqn1UjkNPU=K-8hAqfy7B&P3gcx*c^V>R#0Ss7KMFXi2m*nu)fIZXMk%+9}#4 z+CADcIv_eBIx#vqS{I!j-6Og@x-z;tx;DB#dT8{d=qb_DqGv|Wj{Z1$ZS?2S>!B>? z=IH&==c6x1Uyi;SeLeb4^wa2P(a)n_#-JEkOvjkcFoik%m`C3aiv&e+|tdt>*<9*n&h zdpY)M?6jX86E$-*>os3#4r&f-j%iM6e$hPAJkk8Fd8+wK z^LIQQZyWCs?-j3xqNUmKx$!;Xd&TF+7seOI8{-GWkBJ`}KR$j^{M7hm@tfke#BYn= z8NVm~aQx-?Z{n}T--y2z|8x9{1S$bTu~S(>*95l&&jjxTpM=bWoP^wj9tph@3KEJE zsuOAx1|$qhct2rS!UqXc5~e52N|=+dEn#QE?u5Mw`x6c&97#Bt@O8q4gj)$eB>b3g zU)w^v|Y6J+HP8RZJ;(p8?KGg7HSRJ60K2NrmfUgYX@qFYbR(YYo}>v zYBy=OYPV~5YWHZr(jL$r)gITL(SED_PJ3H>H_;-|GSMoLO>CXmF0n(RL!x7%cVbv# zWMWLBCb1;3Ut)P;Wn%xty2JsAL!eCS2Z=KhXD7}{oS(QbaZln`i3bu7B_2&Yk$5Wc zR^si%$4TNOX_5t$a&4L9o#d0`mlTi`oD`N6k(8E{k(8CxJ*h`hX;QzW0ZC($#wATi znw&H(X2WffY@OUTxqWiSNI63ZF7EWpv8elnE)TQdXy|P5C@! zeagm^%_(1{oKCrtdMfoy>bcYlsh3i(q+U(Eo_ZtoyVUPfe@MNXdN1{U>VwpWsgF{h zKtcMasn1fMr@qi3omeN;F}fByR@YkBPS;V_MQ5wC*E#B3bnZH(PNnnJ1?YlxVY*0N zj7|eZZIg96U4|}8*Im~`*IQShE7q0h`spfk)w){U0Nr5S5ZzGSa2>DvKsQP^MmJVB zUN=!USvM7m;m*{}*3Hq)(|xR4s9UUCs#~U8pEEPZOaCGL zkMuv&pQpdfz!~xk%M7awMTRybIU_Ygmyw>K&&bTk&gh=OXN=4koiQe3Y{vME2^o_z zreu7aaWvyZ#;J_c8D}#tWL(a;n(=MM&5R#1e$i8Uk)GCD=q>dv_15~f`VRU|`WU@N zpP<+3lk_Qih!N^D^uzTd^dt47^&jfT>nG`_>SyR@=|9#l*RRvB*KgEs(Qnu9)c>IW zQU8WBqTL;!Mv>?@V>3Z>E1{P-bXm1QaNa&D3UQWaeiUW*Ra}Gs`k7 zGy7-OW`2}8FZ1Kfg_(;omt-!@T$Z^a^UKWLnRhdP%DkWXbLKCZzh*wk{5|u}%x77m zELj$lWtnA_)gdb^D>Ex6D>tiWR(@7tmLaP&t0L>YtPxq0vZiEB&zhCBIcrbW!K`Ch zSF^s&x|ww=>tWXK*@|rYZ1-&MY@clZ?7-~Y?ELKF?2_z$*%jGU+5NNYvIl36&Yqq< zGy9|LdD-i-w`Bj1n(q9!=R1xAcwBKbb);yDrj9wfqH{EL)45VdI;7rxecrG4=kZ(f39d zoBAfiG&W(TsR=jDO$XD%^fGDquQe%Vz4_6knsl?n>@pck%B16Tiq6sn%A!kjg|5*Jx<%P^hwf1h<%&Rq?8MH7X(L+Fp*zYUt}fQ~aJ^kW*WV3t@otz)a3fu!Gfw@3{t^F}f6_nW zpZBx;%lh3OexCo>FYurFMgB{_#DC+L`S1M-sVX(3mIO&%X&?%ajzLaV5mCTYkGGD%y z#qy0Tmv3d2d@t+d2iYh;$rkxpw#s(dCA(#x9FW6uR8GigIVTt8l3bM=a$D}meaV$a zk}prCP+mx}yp~dVC*|_DR?+HOQ|oB3*4GeitYO+rBebQq)^-}D9kr8o)mZJJy|thA z*FhSu!!$uhYN95oRbQcFb-Yg0$vRc1>r9=k^K^kO(j~e~lXa!8*0q|V8#GlnYnrC( zHr=Tix>xt>K|QRQdQ4B~DLtd-^nzyTCB358^oHKjY`vrRG)Hswq2_76KG6a#)aP2H z#rjH1v{c_}nU?DZtw0r2Lk-kKZ3H10_0RwzXoOINp((-Le(90b4^jKg?Lz$8q@6imZ(%)l(n#$3$D z0xZO0EWuJNM>1Am6;@*n)*%J!u@R}*ge^$JFW8E0*nwThz#ius#d=E{F|V0|MmYjFz+8?l+_ym diff --git a/games/NXDoom/pkg/osx/cp-with-libs b/games/NXDoom/pkg/osx/cp-with-libs deleted file mode 100755 index f4869063f41..00000000000 --- a/games/NXDoom/pkg/osx/cp-with-libs +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/bash -# -# Copy a program to the specified destination, along -# with libraries it depends upon. - -src_bin=$1 -dest_dir=$2 - -# Returns true if the specified file is a dylib. - -is_dylib() { - case "$1" in - *.dylib) - true - ;; - *) - false - ;; - esac -} - -# Returns true if the specified file is in a system location -# (/System or /usr): - -is_sys_lib() { - case "$1" in - /System/*) - true - ;; - /usr/local/*) # homebrew/manual install - false - ;; - /usr/*) - true - ;; - *) - false - ;; - esac -} - -# Install the specified file to the location in dest_dir, along with -# any libraries it depends upon (recursively): - -install_with_deps() { - local src_file - local bin_name - local dest_file - local lib_name - - src_file=$1 - bin_name=$(basename "$src_file") - dest_file="$dest_dir/$bin_name" - - # Already copied into the package? Don't copy again. - # Prevents endless recursion. - - if [ -e "$dest_file" ]; then - return - fi - - echo "Installing $bin_name..." - - # Copy file into package. - - cp "$src_file" "$dest_file" - - # Copy libraries that this file depends on: - - otool -L "$src_file" | tail -n +2 | sed 's/^.//; s/ (.*//' | while read; do - # Don't copy system libraries - - if is_sys_lib "$REPLY"; then - continue - fi - - #echo " - $bin_name depends on $REPLY" - - # Copy this library into the package, and: - # recursively install any libraries that _this_ library depends on: - - install_with_deps "$REPLY" - - # Change destination binary to depend on the - # copy inside the package: - - lib_name=$(basename "$REPLY") - install_name_tool -change "$REPLY" "@executable_path/$lib_name" \ - "$dest_file" - done - - # If this is a library that we have installed, change its id: - - if is_dylib "$dest_file"; then - install_name_tool -id "@executable_path/$bin_name" "$dest_file" - fi - - # The install_name_tool calls above break signatures. Recent versions - # of macOS make signatures mandatory, even if just ad-hoc ones. - codesign --remove-signature "$dest_file" - codesign --force -s - "$dest_file" # ad-hoc signature -} - -# Install the file, and recursively install any libraries: - -install_with_deps "$src_bin" - diff --git a/games/NXDoom/pkg/osx/disk/background.png b/games/NXDoom/pkg/osx/disk/background.png deleted file mode 100644 index c7063aee73d9cf2f67ed6ea05ad8f9ea910fe7c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227363 zcmV)&K#aeMP){zQ zmT57lM8bfCKrjf26o`xm;NbFAk9J}trs zkQHt`nO?nq-<9k4=F^cc@_aG^&^X;O*4}*fDI&6#0MHmqWRQrxV|L+I##jIp@v3S} zgotD;BHDNWpa7sMpn7z4G#ZVrU%zgQF~$O-s;UaRqBFTFVx!pDsK_SuI2apw?+=fT ziRixjAMoC>D?&Gj3?kV$MSvooh_Epc64@vTgNcas{mDkwMo&NWq=+2s?^$aBzlHY^>X!YA3=*B^u4M1Rq^$b`Rb~%>#@h4krw zYy?mh5mg1mFmwu9YY(alpsHG}K&?KmKdDDs>yuOwd*=cXv3kn34xIi^s_sL0FU0Uh z2mladutM3HdUK(%5hwt*cI=kVM^LJ{1 zT14HtuxO6++?ZST9udiy^L$Sg)~+tbXQt&Xyz_iF?v_i~tHN20nD8@?d@7q9?_IuE z*pV?v@; zQfarVXmGStst$X1(v_&eE3n?HN#iGFr`Na3*S6hNgSNL-gRg7WgaxmQRJ5;%i zE}RQIfiL9Lrm&voN5Qg3rRqafRZvA}nEu)x>eGmg(!sFWKCZhMjPtXzM)X{cAl0u> z`L|-Bs&25J%f@=5EubAi2&!=5PHH04yH-?%knSAsfr>OwJp>HC<|PBT=7QhQ!=~Mb zh@5_BA>wp&OV~SC2$$!-%X3l5^8%xEPzx?$VUI|N2%rc!$#QF$RS^IYnZ2*{vfw{- z-m7Y40TD%%j4?I}-o@}XL69O6Ab9ph$wmp0nR#D9kxUpXM4~bhiQW|eYN7-IjkVQ4 zs4%yW8zKVs1we4+p|A@U7$Abm{Qgl<08NtET9Y8Dh%54NBSeZ5J00DA`q9tsU%7X< zcd7ZTW&}b-O6RJos+QWrGSMI)>#qY>q?5e{n%k&rMLqauQ*5QM5yPCBTHo_xnH*uwSHYpLQ107_$CmTFGhIior& z@QgjXgjl{&*e{)fJ*cx`?iQVp;rv9v`8LfLX&$q^joYr5a(ArLXIrg}i&jti1)->j z65<^r2u0e*B_cxDQL^PbZ>U;rC!S9AK*OrP1D|;oQ zh(v^l(=4~vGkYRT)6{$KT+3~h7iDS>Ap&?~qc{ar(8`;KNJJ(~HhZr`DIyXzUk!;= z%ajwsD1;JK1wd^S6Inzg761&pt0kNe5sh~RRGB-o^bl;UsQ_GrW zVta5FEcj9}D!ZY8W}(zaq*aHtsxT4&njkenK$TVGR2FEE6Nbv^*q)ar_@&KE5K28t z&EY!Rqjs(vXDSPuX zYppS443)N;DzTI{JsBjj(pexHmcK}uO(P=O9!?QK5oWG4Rmzl{VE&>88LYvPDxx4r zRJqY+?L!zs8nK@;Gp5oULvS)|A}Eu1aDJW#ad>NuNt}&Z(vn+`6)fa<#|1)Axh~|E3L6x&pvkhxi9Zsz88_K zA&4j%>{|9wGGOnI$BzgzyUaT$-cc0AY0S*3a`VQGJkMVK;491MAeo(mtG>vJY%(1m zkB<-cE??W(zXS@ZeDmoq7kLH%!aN<_1_0+cNYE^IS?)^RA3#+{N4F7RoE3&BiCYWF zd3K(Y$Qn}`SSrVWnxwnFimtPF;TjBg2fO>XpMU;%bi9+sh#1EP0Cx7TD6@09isaeE zkV(>^cSVs;Y?PQ9_MjT>MugX{T?m-!Mk$cLkld-b&eAd%v zGo8TKRsW=sdZUE1(U|Y^Cg$^k7=AOIp>bs6vg3Qpnei{&3-R3Iqm^f};kXMPF)2Mf z*wm_2OWm{dLX=2@%KKOUDW$)z%!n!DzLlZYwwW5cy_r5!12fu+edCVdDYImm^5HNG z(v)}%Y`IAhOWU{p7na6j`7fOLzsqb-EKOo5P3N%qiHwaRV|MAo=5uFG zYg?S9|K^U}=)I?C&pC;LFDWU((?cgEOlon^hN zGP@IuH4^n^+-&#SZn}1@H8Fb|C4ea2Z6$8e&cj@5eUENElZ|d4AKns?C^7(g^}bgs z2mpESAA9(rz5V_D{R1L{#)vDJ{pjensvcavYNOZ{89*8JDNRE}GKP$G+0?t-|QoeR7}TYjIl|`AZdymVHRO(SYx{fSD4uqnToi48YP2dup6d3{E)p1-cdxH9N$ur zBA+1QVE3|(;&?E;@ywGqo_Q*XqsUSim8|eAGE7>!ZEcw5g^wd^2zPdNkbK(PJ9XwS7eSc2azLoY+ zBVtO;5Z%fBF{hYB5!TA&J&SYWZoHaE_FASiX&jbL@fO6yqRZYHY81})(n&QAJcph) z0M}d91zTusxVQ;ubs>arv}H+^f2juhv9uUVq1&>zW;ZGE=!8V2={Ga@%9vw4^9{37 z>$_;vaIAzpsEC9ZA6B+tjpSDq0i^Kw%67#-2vDsw1?`;QrDcO{i?J~pVV3GuT5B5` zynjfnHOsIwFl=YJzTHz_#t1T5d_8-!!e+{n{lh@8o}ao4)IE>ujcD+omx z`qikjokeDM$|o%D`D_Z>dWW>WA_LVa-@v-gO~mQ)5rm!gZ(U?xbUcJhU$z_elTDQ0 zX0Av5ZllrY#xqY}yLJy5QuZq1i$cWvA{XY8=q2!asAQ9IHXU8N|3M;?PmYUx+A+t2 z6f5$HE2e}75Q!`R1ka(3Q&9CqrV7Fi$q*5oLSYx8Wa5&uA9gRlQ>6AqgF;2u<`|zK9K$!D9 zvr+u&H+~0uuG}rOIqY2n99uXr21E^4f^VwWf!c1(v!)T%QxTabBdl=!3nd^Tof{E{ z1a>-O%z|i+DhPWbi#8VaA#6GCqYi9+>z~>cdmNsa2u;|7oJ0x=I~6fe(rfycol!M5 z21H?Z0*@Ucl8NfWNxUaxaJgSim3>iyaA{TJ-qBb$JMv7##QGK?TugrEcGRV%`Bb_* zKdrS}&Pd~4wpcG(VH6Se99)hf0#wKJL`rY%j66+Mg}ID}Ezu9cuPJ~`T2VIzow2f2 z5yb$62=-ohvWNuzrfyuuEGw%}q}*D8#k4xyvBV0N5lRiVnlV-aD-Chbe&(bGLKP*| zhDd0btpS)J;WI)aV}j+^yo)a~VR89Xb&<`a+gRRR*w%?O?nUs1rAl}C<@p<53wjH| zG>7HT6vR!({S<)3P89qkv#pB_<2IIDPxch-JWh2TV!!guPHKCfF1Pt?t{O)eP{_K7 z5m<%wY^br%RoK?Bp1C-jsGuUOm*%S_Ky8C%fOy*EZ*8oD`Q46fT*8tMp%KGtb}tgM`j|H=T^)WDqBVbhvAxSeR8M zopZ*hwKfH5sI^g94hSRS=u89k#rYh**J&yvy_HaX?awcwr9D zGBys@Rlr9QYMQ3O(#rB26e3$TtE^(RHm;(fqLscMM-~yBbKd(XG9i6O*x!2kktiJw z_O1k^{E1`0h&2yRN$h}RU~adr##2}MLF>xAxo!l(f1c>x@=#ie#xmuiBQ**QRCVVF zH%LL9+UVd2cV6lR?cNiSfMy{ZEzxr89s)?zLpNK&1hJ&JEAbUoV{Ce#Hnk41O+_8< zfNh#UKt!6+#mNFPvv9YD38+iB<^$vxXLzTLPV{gB=**=z*J8P7YY4&y92)_^^a?^z zWw^Tq;ZpvWO;EZaP4T?6pr%_#o4(CnL8x6sD=rd*&6^-%nhxOLlJ`zU%5n`RnrVoL z>|HitV`H*$Vxtr>B(N}hVJ?X&>xD!V>PGY|%+@TF(k{STgR=#Z$XZp!Yzn~63zD?G zTO#V)v!J4Z)G-p_YJX}ax)2fB6$SfvxC?;HKG4dLF~&p+Anchv``p+#P18`<;_0WJ z6z1U|HU{Hlw+1BD{>cD-5APYrh7hy7U>1W(NMjZD&p-Xh{?!MDdskIueWZN9Gqb(_ zd&@oqW(Ko3-#CbiIT5>&U;Vr(E&>_C3frb~)0xHmrP%N)Z?N-N0w`qJ^XIVJojzj^ z-hBCV8|*y;gpq7F647a_%9}cJ=L(O6f;WO%< znvQP8KAws-L|Y{Yt9*s}yhdG0oVdYEw%d1lx#;udU)2U%uUn>zKh++L|C+sh!Cmw2 zyWV95EyiJ;Wr=9ukg+9`O9hE&i1-%V0Ym`nbP}wet{O1XIPtmI^Q}s$`OQJ+C;fzK0NT6JOa%W^?R}oG!tGH}kd@ zr4L}~Hed24eJl;DJeQpoxXFUTRar$V9*%(_7?&KmRl~*i#45`SH(Ks%dv@#cHGRxb z>xwq8WsXL}9A2VIu*=tf855^vWECKU;<3(EVISC>0U!i>Te?gMAy=d>Bul)TW!%~p z)Ku6jd$Lg-zZLIP#Kh^`oqMj(jnkvoPipBYEpWWluy@3@sOILI)tNQRf6nY&o)!6| zT8O2=M>bX@0FBf1^5rYcTuetk&z#HB;eN=*4EAF1Nvf)d6H#B`plvjWlGNoBRb^iY zfQjN@cY9ncL488`~%XK*aq;26j5wLo!7+E*&z6R4Ieb z`7C$F*a&SlISiO(W1=`6)=DLrD2O^{&m1U4^z5fq>k_uoWGll@$k#XB+< zX(j3Z(#D8fWc{|yDn!4rF{m(yY$G#EKk01@aeX{4N$y`Gfwpa3=}NpgcFt!+T8sAp zu{X5Kvoscaq^Dzf3eCTt9&<{Oo`v|n9A8J!^?7U1xF0IY7 zi;L6|T;d2{Q-e9lY$2XvGtS!wx~3JmEe&u(oQ7^{)2tC_D08*e;@9MsYC=( zA0}V8)>ylDn`s27!tAE=UFoPiT}8O93(w5QVBXFD#5;hNlC@ItS=o)#s`KlG<(D+u z7#+Xr{?s7I4_Oa&o@A2j04TFpk$ikeCQ5fNf$GcSD4$NBd-{pNa5o+9*f_Pxph+n* zt00e*40c^nFlVJ!TjT}%C>a1^2t2SWpu!Org}2s5QDmdU#z|-p@+~LFw*ln#aTZ5D z;PXm+g^ij4!k|`%A`Ae4WRhf{s`=!&`~YN_#&HypjdphS0iejn;(cfwB?DER9^aCN zGHavQn0P!oQdRE@BC~&R**W*zjhg^4NTM(!0fW!%>SgV{h-i`+RY+4S0?$47tlGiB z^&YB(l3&mjWv;)f_s*F0veH%ADkOWoGFsw<$r4{)?af zm(z-XL@?*wt%wAg=yj~jxH_&diw?FL69#xzwVo7b0fuIULTp%>SUYm(w`n`&u13n2 zQ3%9N5kvtf>jU+A783wXJ4yz=z z)ej@H+uXm^hqmooTht}1mA$An!z=<(NxI$RZz2lr`&nLcV-KuUrsn5Z&Wq^i1U6hB z$o;IY&Qr=X%!X!D6a{;KFx(57iUF-$C9qUUDXK&yBFB?Sk>&T^|3D2aQiWu=f91ZR zuoL0i&)>Xt`*4tESUNCanmZzltx?r!?jjauhCD|Yg>{$}4iwTfGK9k<0>sI9RCYJd z5z(=D&pSJVG$~`i%nYFE&c3iOvM~TA!~Gzd-Ds5MQ&BK^wzEeex7%1OIS#UM5c1;H zIZo0vPSTL+?tI7~H^xTO@gW&|?b27})1 z#mp$oE=Mw|AuAml)DUF>_uz5qO%QMMNGJd<&WF?{`d)<_ZfIQvO;Er!Bb~ZtKvCF( zaEnc1ON~!?(JUB=r@M~g*h#F%KK*n|w5Sygi z=b(z560m*{V`(ba7nzn#88I2bOQEDpWQ$4t9u5dP?ju)a;s9IvD z%A_w{6wyIM6=jho$_-S=kc}cnKt=#$5vg34S_&-^C73aBx71w`sW8HIA^R5mLztO6 z+cImvUnoWSBb&wEeS+9l&$&j^Jrl>9rtf>YP+$EK9 zw3YCtT{}P(kaUHkNtga}9R*xht_Q?TdDk}4{nsjGb~=3e=I3Yc8MY}Ne^n|etZ*2d zrFGuS5=NXkX_|e)&J*#x574d2+NC|WNCXOID^z%hodWI)7Za9b9Z=(5?IJly&Bp7V z;C-*GpazoGDv;90wf>Z>&l|Z?Db~g4_{FMCKUi?n#=UraW-jt9K+57|fay?#5yWK^ z07W!5N`||}7$fWe36QesL{+Rc!!%J9&{@@pBAa-Z2fKI zlUycj$TD9`vuKH`0?77@uxklnEGvyvAJ(u)5kAc!jlmXgmoM)gTq?^Cnf@_{5^c0h zB3%e@3o%rX4+n9tk7^@9R02}9*Oo;@QW3o)A!;^s9br4=j0Jcd4x{^3hADU*UttFZgl>X%e2B40nu;tevQ;ce${rs=37h7J`-S5j60WNNOEo?{x3s_I%I0?RGJ zP)B~g&)arXl+ox;Bs;JLtq?YAn6Y*0P_GM0TjMMnJ!%D!&Bcj^8B0UoSDW7r7g=7x zEw6Y&%GNU%gxho#;<*z}bk@=;0JF~JHm}*?2L1w1wUVnFbu%0)i+pK+mT*Egq#a_z zn}Pk4(yR_qr7w}OHu%sHRYjPasb3Y|F3@`l8HI|eJe-)#(bb9!aprlfvZ!ii8EoJR z%32cji)hQ~SQWgJu6MK~x@%5Cn+jk~+n|bHwCWO7@2iO35E)~jl!aAoMJVMK5g}nc z5tS>m^dXxH%wH9_s4{;lue^5q)^r8o;22D2V z-5G1u8>@)hE96PzfD2fDRU0S$)snGdA!vFn!W71-s<3lm{{-TK(73|7F4}1gw6d|6 z?|JF|m3#8Zk+460{+a17!C*+n?CkDUqOA;R0swpGU6H2A-rnwWH*ShZ5;;VSV~YsZQjLoU z^9v;?s9u0E7+P{_Q-dvRRugoN4Xak+4bj#%l&Z2vq&tUUScCz1zMq}6cxk5Bo!}`a zDT%&KE2oj}q?@J$p0yu!etfVh3%b%KW?>?0Yy@}Swe=-_VMe~rCmO7w$gSh&Y()!t zwLzW7y)M3w&SyrMlHlD9j1r9ZDy`kWcx6y zXAi0%?Lls!Cz{y&ZgRA09Uj#h;ZX`LJ>8b+Fan%+d`0j4jo<5;x|^92o5c(9T+2P4 ze39S=uXaaX%LL(E8Z@vrz)BeMiQp5VhTMvAT#J_=Fp%}18gV)V zMDc!67PVOfln#4l#v~UM$!NV=pe1}2k;aG5jt`$7A3i4{)MQg^1B$N7;K< z>|cFg@6tVoH=jJd`OI+dQm}Xwnt9lm4tANHcSRJZHcGSUILb5cgMsKP%5M`TgQl;< z`=Y@~jZlKqB}uF*6#2Mbgn2fO;xvj=S4>@zh3p1Q24rj?dGbZBs^VR!uNGOelg4>o z9FHcK4#XgevWSq05QD`p2b0v^Ky^BuFR<3-001BWNkl&Sw5BBQj`A(;d=Yjqypge}7?dH70_PC$&9EuPVw+wiEr)V7)a((7ARWqN}{yYiRzuFyB7J#Y!6B{%7e5gFxp1;xoH*HTP~wPhOg3+A^>Z5r7c6 z4&XtjgE&X1UOl^f9c?l#;5>SIS&HF&_W1&uJ*-pJ%VJ42P(2uIrB)MIu}cP5nDOwH zb}O~0!y9&Yh5E-u5xUwApWQ%3fe>+VNy0muE(c|>EQmA{?`nbv0_0-TQDXjwtWFdm`6dZj!`DI%6u(pqGEs+2TZYq2GS z1a$TtktED{mZ@r1_%uy-hJzv--+uNn02u5Y2(zlsCS%V&O%g<^&DM}wBkWy1CB!sM zi=t4~!Z8c)A6yoZA{z?}02piHbRf(%(qGtzJicmeV3>%am_|`zOA|_?co-);$49qR zSjUG57$?I@^a8U31OpUBaTLWxo?BBKk0x3f3`x493c`*>rny(hvC6n<<{s_rUkW9e zB5MXB6=9PiB72uB8ykfsjR4k?hz^FAh|okas7^+=276bGjk=bHLZ}bkEPx0Y z5|EfGYwB585`b~Nd9g*@ETKko$8#M@ z4~N5it}v`LY5iv)*;WRLK)afJNV0FjY1dI~I|oh&|68euqM+Eu6$b$F)+ejZ)ehAB&Yc6YH6(U%5W+iA-Ip8%y?+8h~Puu*fqq(cYzNs-m}_x7KhKiin~V zjcF^eGh;mj4sDc%hdJ-PF9D{Oh!DNY0l-8tiogsDQ5F0PEN-A6SmML#ir6B|o_rCE z-SB>%SwxJXmcoKyZH$5BpJ3|T`uEAt-8+eQjqqgho&)EElkPmh=;k+n8XcK|e- zjA4PM<~=hDVosGEA0-15ML}Q(P`0X;1@5~g%dxlU{5sPed?z!O2BPj_Uc%~L1L_eP zz6VuNY>QIMPx!p#u`fsN(i1sgk$Zv&9O=@;9ANOVPtDT2*ONc$QXrr4o_fKqLT4n z9i)jhHjdLBRT&>2^*XCn)p=%SfZUKFV-P8d2gb%krX(vCQ1yW%WxixNohbN^NJs<% z^>PghshMxOq!?R60%5~X+k#Qf4ti4&qRuCtEZZ-Y%4J##bO83x&b9v3Zn*HPR2k>a zjrRNXu^dzi9CRu$$tvEw^)UP0J0l`c=*>xnZOIF6t~i|hEM2o3t0|p3>zU_0?P2?` zn=G>+1Q9)hZ>Q37fQLDX!&;aw|!m+|t4uNjIXji-HR0^Cq=_;tXsDNNe z1`!;X<@+fjmhz!;U6z?XWUyM75{$44m)=Y-nI+AZDw0sS-xlTCK4Kvj)+DEq$kM>++#Gb&#!rtq; zN1W>E&c8-~w9kBAaZt?ltzoxr+e42hnXe_30_$cz_O0jk2qA)96FoXtU#TBLegZ72 zSr65If@?`OcHoXY**&2r-CV_cG}O^z7ByaizHfpM$k@`X>0}~=5V|fZCSFRf+Q{y5 zCNy%U13IE~W|Bcf??r@*VyvoH?|A?~v&l$RO1c^G)+Ui1SQ|me=TUNfxOE*HyIr}mQd|MRrhyOL>x~G4%sw@b}Gkd zUbw!0DnV*LyLte;0ZzSXNSlK~UY*uG$0P3~VZb?ED!kwDSj(9gQc->Lsrg(>qKejgD zvO{T^m4;QRAA~LQWuCBV#iAj?jY@B>zSb3l+vO1I$ZSLu?`D}6-AY}oBISA2q4Oze zw8F@AvSU?5&IqQ}I~t30+galhOcKmTvm6njbF^(D3~K~**K9T$Bk@SaS~EI2eD=x5 z9(d)~7-O^Xk@qh65M4eEbJQ%CaqH&I$#fe2PLpVNkc zQdNEa)-9i9m#$t1q(BY_%Erbvipf}Gqq2m(cOse%d+gUFa@XaACl9NxMS?zVU7 zo-5bx@$AI=-OKkNl86U|Y;s&G^#BNvXVd9)6xNLM>^u)N0>EIH!p-N9(3mor$ho2@ z@=$cXx#OaEV2mk>!}$S>;&iyXH=T@%Y&x0VR@KOwnwvC9hX9&QM0_;w@Gl z-{|5~ROoCPOpAct%U509xYLc3pu&TRU<{I3Lb0a0fyK5_L1gk7GgO3k0(y<_&_pZj||RJjE6@v(vmJ471n zUh=N+MOG59wb9UsI2|7XAWcWro0iPZA}rpqcQ#HDG>I*tCP`v!6c2_0kY@}HC=!>A zo_`hy5h$M=hlx;;C`m=cyBq=I!44UWA```fC{FWy;_~Tm_YxpYMn~Qim#*HUp>z@A zezN1T@pOFXS@J>*QB~Ggz027*^L^A6(|{CK5oVvHX*w8YlVedS3NNg~K@0${n6Bd# zV((6Y^sBd3&zHtV<;XPdUqPEoo{CM6!MdJe8;-pQ=)K5S-)KDNmOd#e95*5XSbvN= zsPN8-q{}drYd=FODmztUV?Y#k3-5e^V3I%|-*`o`wmzMf^?6S8k*UZxgq_PvWH6Zy zYufVTYlh;JHt)*X;**(!YjhoMusJ6u0@=777G7XZ@NzT z?~(?H*^98)s!mxsq1xzC%}@nz}k#!f`Td% zg);Od2DHhtwxwmZ>bJUTiNfg*>%N}q>2A1$m;9ut@Us#Ur(_J+d~okr0>1fv;>LZ} zo&zE5uhXt5JxK}$*nqp7sW|~R8qo2L8rE~@PMt4Ck8`;pi*Tc=3UUTDtXHdDGCLVp z0g&rHFM@(L+V_mcD$RNoVzh#~LmzImsg{NSYS(1!AZ+FvltI)Ia|D3G&KH>>Bs8iZ zEh&X@vQxMspH7oBO_G#l!Ym6&z=6G!77qXd60{>^VQqx)KwbP+RXjUpM{L7ehH#w- zXOklpHP!&Y3?ikfASxUR0jdhSqISs!p6)14$runpK*Ca0^od1@#i`BVN!- zQcI_jBMJsmpc7bx95Vhl21)h5VCXp-bCP$j7(C`Rs`~g^6s1F=`m9^|l-W#)2Zq{1 zqkYHjVgr5Is5bi<*3yZOM_pXmw58H*$>pfZAkE;zx>wl#onEOZ09Wi$3&$1_kW2?7 zzx>Q!;TjDof^`-6@?0n_Pi&Rao_mco1b07f^z3R_ub8nKoIpfmRA%Is^JS^EB~y60 zQnP8<|K#rgP|x>bHWiRN{5B# ztnl%`#OcsG&)(reSCVT6^Q+}PzbiEq(F;0<2nPT@d&edU!H6ITRX7_T0e~?i(jrj{ zrGA5uYG*fSkximFjp9K~PlIGaB#A|w=Ma4i9u@Bj5f1=1vZkZ}#pBULM8a_yS))3m z*hR!ZWm9FZmcqdr0)y7ZsxB`)0>sv+21unWaE<1OhHP}=J)t7K*%Q4WdObyc!711U zsrLm#;Y$!9A~}d?91+yg_Ji$oeQ%HlZk3>_CEb}V?n6fo1hC2geQ$j z_41AexDJv*Lra#fBAP&qwH&0sU~TjW!kK>FtP5EK+wF@((DM`vU-+D}g0sMFaQbZt4|PjHs>8$Wu{lcuUK*wuo# z&WdU=3N+WooUPEjt%Y`p=LQB-Riz!bY?Mph9u)Lq26;UIa?^a=_AIZ0Hm~w3%-wD+ z+-T2P!M?O_Oq3)$flah1iV#B<4gNih(}6)4BsNV4@o;xK9rr5QL>3y^@ZJ@!$c?dN zXgnH;2y>aBfkaW1hBh`%5b=0Y{FR^kC%tE28pl^J?Y#EY4}8nl-234Dmm_Obq&Kyl z*&$-61u@vURF)eK))=C(ac{X?3}pX}uzV1KX>3J=SwwZ3yUKY$*RJkqmgTt%kw#zS z-WQ1YJAd%m(IgkquX*tL8@}qk-C>MGHcAP}J(uQe5z4}1`Yi>jpx>^<(#Gk~#OYx3mpbeJJOA*rw~nR& z;91`In)^i+8_()bF~f^ocX!Jc?AEYstMexrz!#YWUeN1h!2ydoJIc7ak{ zGe@^fa}#ZSCkuO*XT$x=hi zH@p&211(&f3;{9E#>(E9xGpH@UBT?UD}sMC@PM-`0(&aPRd5C6o9N$4W9Lc|RU&LQ?0i}S|%HVncB zsuk*reKoor8#Wvw&e1)TCE){vpixJ#cjX{plcKr?Nz@I#`^{hX=fC%x*cGahW%-lO z-Tt>9`s_oGJ{P|If8YCwZ+`7d)5Kzxsa6H|bl%eHvL%;j`L1C)3sz#AB789pB&5h} zt8&eY*NfMS*F{}+O*QcRu6gHgLyRpk8iYN}Mb2OmQP4Stl({E*hZ~GWAHTNCGXStr zT;eEZplNNAZU!+^#1#q^11ZvN)`KmDmMK7BOFFYOK9^7XI$^WXKl|KXS4`Kd2H z4FKQz`j`LJw|xsDq!ouavp+n%9Yyp%{nPh-=8%b+H@@zNfAB3kgLI3E{Gw)^pRBYhPGELy z}!pI_yoe zrsuavs%!K?Yxfk-JFT!LzN^6F&;*7CoTG?_0!g5?>~C0-95rn9f?X z6ChwIp#ktmzWWV95CXu*9(wAn-}tJ|;C%GckN)(BLrbBoh zPm9N&x&7XceBsBx|M*A#^fw_NGqeE(Ek7V*OLTlFN;k)Crd1vJi%pWQ^xP6p+A2gI;Qv}y zeh1+-C9yC&=Z1Ti5HXt^i+81P(yDS3Vz5wIb77B&Sy2$;a5yy9I_Ho~GTcJ|)WCIw z!d`^Q7$maRs;V(o6^xCLFtQOKghHkYn(=h@f;LKr`(=gq!Csh@*B)Fs*c%)kPXXY| z&mCUAdfghTL#=t?f9co%usNO6$>@`x|8i3b?(HPrOP&AutMB^gx4q%z_gxo2m}bQ< z{K~s)DOg`0d+13+*cf?4MCL$js>YasjS%%)-|+GW@4x)MKl)-`cmR0C16RKG!Rz;5 z+jCy5m7o9R-+bsxPxcP`^S6)R{`0@|fBnMWI@sH32vB{|Rh`6(N5XDJkrzVOAyO#i<$VP|;5ZM*p7MfAc4SgQn~l5dd&iqA!kZlqBr(?|buW zrkVTTCm#!f@M|Bu{-fXbCeQ3Wzwe`;|Lnu16nx!RKlnHP^4nhVl6#+f{_vmt+PmKW z!H)yLt;6Gg^sB$~H~;Dnx0Ri3)e3)65Z;O1S_$+v>t&KJU<^3Hk+PcN<4&I0Q%l~KT5WKH{%mE!^$dpeE^&?CA^kXg7`P{4mV>MJ z?Cf7IrlX4C46-aU&arohX0Us}?6}B-+2?)E-dP&~V6e8wM>ma$lHnczYOn~&NCPOX zs=^#f433K&stDzHGO61Xl^oWhh!`g1%kRC{O&jZ z!*~2P0OW=H+#^qX!|T544pFvix{OU1(w!~_msY4>S@PmMM?=oHK4q8UW9@5Mah?|i z;aAo*t9OnYv|n4iuRsmYu<9+w@CJ~4J+)5D$Rf^e+6#Es5IgLcjGcyU@I<9@HmX5X zMd?5nzhJ27)~r!~IGR?zQ`#A(!Y#6rSHARmgAO8ihV?_A_|k8^?_&==`iw3FLCEum zqx#ziuIyzb8;h$d?R_PU##fj{c$yN-J=V!$pm)=(ISVD?1Ub!H!-}ZRs0L2( z>m`fOE{E)RVA|-=eW9@J_M5GW(EV6NPx)IRY*w_dFoXb?$n1qb6 zHc|jLnc65daZEO9Ef?bT~8bkhAe2vmYdu zh}gS-_1=&E~Em3YcHL-UmMVxmwqG z{j2T+z#eN9XXbWZ_;>uyhr-{ldD*r9{3pKW{(G*ncjIYZ3&K!|ad$W)GkW^wF*Jjk zsy7cOGaGL<8zBU$4X*GOrX?t5`#Xc0)a{9^=Le@I?6JBTr-%QsRfd=Z#nP;%stgqx8v!pOcIwW3OJ`uYnmK`ox$1lRx+7*o4A| z{K+poc{DD~{Sf9<)ycH5mg0DswM~R+5)IS%6%Snf(i1lT;CDaxC;#bRe%tQOpdR~o zzW*bo85-HwzUIMGdN?*T(ApL1*XMZXE36m{yQ(bW@?ZOwy3pZ*M-(m)agGLgbCFBt zV(|dY(Kzv$CUdd>UIV(G6hy3@K%ole+QW6Orum(AZT-!4@qgB8dEwd4=huVYLNN7* zYks?;nv5>{NmYm)8t{CTuzRbTL!w&ZD8k`B2R715l4I=?=(X-b#X*_*16rJC-C@6d zJpICB&wlao8()0kFX z<7x4Kzw;yW2JxF;|Elos=Z_}8_>T8J`}}d?{6|0e=r6wGz4L}^pvYNZ$^Zalxv!by z{`9whUHEW3&HnZ;{L?Qz{=1^naKk!Enec+EC>b=$OF!|{pdUKVc(pnp2B2Y!dB({k7^85D< zQK+}|EC2cde5`RIo~`DoKiQPpIW zG)+qdUs=VM_3aUjA?J!gT!sLD?_*zj^2X8EJb2HK{+Vxh>o>gOJs8_~%PY#Zm!d4%O)9+EL86=g1On_*!)$^AfGA+VV%Bij zkT+T?Eg=>VfaGmbqi*9$&rwxSDOcU9fJ3|Rx-988hE%KikXf8R5yp90ZB?z#Puz@D zYvG+&o02mz5o&$kT`EM8O+>t1wjcDOYN7F5FYs)Rg>^A@diMyzk{}-%sK-@;u*CMU z_eGZO9+X*~s_|ftOeEfU@8H%gW?y8JC>hu&5>a76V=EgGCt02@jWbzmn^TO4z}N(S ztTP?=T-p1ZKk?S$d*!{;+&}W<&2XNjX^Mz8PFSLzjX`UvD2lIpK_JH2{HhHA{AjTB2iTNN?3&v4YU)=dKx#x zvnnH*)m#T%SH+T&9aPnAt_Yu(IO^6gm&^O;HfM0@52<YKhQj;JopS~+rCj=oTfR}mE8$N$4`x_&Tt_Xj`s#IuKSWM1`> ztAF+_uY1#L9(d%*n?Vr1>kmKkXTR%B_gvWnfNy)lE3W^{5B#eSeC9J>dU`x9u3p;t z_BTBEAHC(ZKl=~f8SWlgqbdL-A_@vfM8UO)!7lvK?|aiAO+NCe$8Ovnd6p7t0&w|Y z=a>J^fAP-uf8=*R{P8b7`qXGVP1E?L_g(*vZ+h*I{J>l4sNq>`^v3?!&?xI~uWPv7 zaP@uW*b`>ng0l1@Zu*+40xH_5`lx-ZybHoKn;tv5;AJ=4adUH2e}boQ`Qp+UJpUv5 zZa7Q-?LYe;*J($_+?gWBG;{9HK+^QqS0j3XM3w9MYDDJdQx6|K|CILvfWw_#V~mNC z5PN6#PdxtE{=vbe%U3`Fkn-tKJ{=ABt^nZp=(hI-5vg{K)Fn0o5yf!~09lr?XyLpy z6j|e0oaamXyNFm6g{q9Fg)x*w77>GIvfl3FX*S97VHy)+9LHf^JoE8rLPS@uTy{l~ zWz%#pOwvK9sZ@GmnN>O6xm4N1>hfu@Zk@}$E21bh)+#{Z{9pO+{#jsI`=LMey1($f zZzx$tZ5%}j5*cF;4-bz=ql3MHA+k||Xo`Fkf|NnjA6&ct`b%G}=T6?=i-=ffT`Wmw zD>nk?izFqItqrD`b=7wHbnYLPjg4YNbVW`?>+kCsBBGQiI4{vd$;`7DVKPxIc!b^h zCriuL++f49%F?MR@2uhrH0Ja)Z{?2X?H5E^}P1CfDa(5VSLIjMltoO+BW8KdB!)1Krop`FsET zeUCl;eDJpZmp}QIm)w&gqKN+bdp=fkjlSw7S1UM28CODWc%HRc+7N3aM?&RZy^yKI z(=3A%-5FaLiQWc_@j|D{+3x=#-qky?J&d^aoYpl#UpyX{yVT0@>qgEJLi78Q2j+I>>JhH?)~{GK^jX8)A=IWiyGH&p{gQmY@81Ef^r>deZ}dH zh%d4!Gb5rfyCNrJjg65^6sONT{gf(Py>@*sj>Ccpz=?p40K|B(lMHsU(NR7f85;qh ziDDv?jSmB@8mOi_JX?EYCZnT#GDbu|+Pidx$nLWvGA4=vz&jT#3hy#kWY@0WJJ`E4 zJw8+wL{tT1t#<_rtH|-;Z7*6lo@9mUVGVY6PG>m!`>qT>_=zutzyGVh|J$#4 z;7S_Xr*0h8Ai{gE?7rzW_cx3!&)yjm8yf{G_Ba_3(R4Cl_VwTs(ZS`b>2UW<&m$4u zs<}DiA)7};^cs0>bJ8oclKy>>FVA-i!^OU={h_M94}o(E%eZT+*=RdCx*J%59ZQ6l zzo4@BA`->PN$-p*tiTO3-3sTc4lc7c1;<%RsD>C4UaNji>nFl1LzRdDD#oGc(1|U= zd0_0Fp?|#y)jyrwpP6hSXxPX&Muu)( z89pRt(#&?8smWzH5SonOsHJkIb&Ee&jo-V{LZia{Np!1_3$$Q;90)#_>Jb! zTs_!%`%iwCX_q1?mp?YM=4KtMt<7_&;);NGuG+s|6@_!Q1nT(uooo)4OoUtLXFn0+ z-C#fC8MLfU3M9nR&twCoR*k#tsZ6v;?P~*LE9vdK3+{aNi@Df_o@o$qQ&V#N1}C!- zYjM@Kl4(ifiW?M-iENZiT@ETWvM?BVq3F_dI?eOk8nVWugJCk*yQi!a$n0_?Qx$Zq zQ?c>Zji)EmX=I2HtTl*eqa^5V!p!+J#M`WmY@E7c>WV}50)Qf31euQjbg+B5URuIl zL6sQ*jEUI0>G;SOS)C%0Pew?zcW|Y24XKK7k!N|H4TrmNl9oP7DFJIl#wIDKdYAwA zKl2}d?6Z%)|Bt@#=#w{Z9v*wo!!&;2`u;b+_Q5~%ov%aAYPsn>M^O}~3434UlX}%5 zVmcUvUFN+%9*q!b$WHkzc)66l-wF>)fMa(+-}7*65eK^2vzYz1*14{s<2M^G@wfzw zvy-l)pm@GDKQK`0tFZ6Gil_nrclx=8j5mGYeHE{;+O$&P>ipLb{tOtQ>M%d2P+CI_ zt?SzDGBd29J5EQ3B0k_~EWm0=%wn0khSa?X%jQMn?qvFBAi-|ra^h@9hO7i;1T7&_ zNTFh_FKhqyB;zrQD+-D&5UHX9hPuIMs0kP?18XIHn+7EqQ5&Jk#>_UMETu^}%hFL5 zR3xH0poj>;hD9PWrfi6TH(ZIxkWm0)52)Yx+6UkKrmwbfGC97LPe;e&8~_gX_oB$= z+&PpHkSe%X2ggzh#hH10XRmf$^JCroaa+o#*Nq`@o3{zE=W{$f0^NM5MYeDbwz+!r z1kJSC+Ap-j94ohfun4;l$P(ST;FpbP0TP{KwX9Pq7p*?urGlzk$w8MlXf~Vws=u+Y zuty}M64k`)gt?Z2agwBI8by(fVpLFJ(K;oB!Z?@pD~Loyg$X51B11%kMd1~|c?E!j zgUcd7WE7OW17C#WGERm?o^fSAArd06_kax~ev_+D1iTNw752fx3;hot5*e~qv)r>3 zd9EVH8mI!>ga&N+e!j>d)IL-Zk>Kzc3{n6P=0c>@iODJiiX35IXoWU0gv?$A8{13= zgOre>WMHCrxq-5_nyd|1^Onzu)=|(0#|~S*fj6(+FpLdAXJAJNLPfW?{+qaneg|y3 z@m;X1Rb@*SbE*01He*A9nqY?0-SEyAPuLb#U>|}L!&W8(pmDlOWV*~Up~WHr*7TY# zX?90l4R}79yHgO(XV$DK2p9Q?7D!DI_JpLMB3?wqJCPZ#IgaD~{R11PQ8LKJN5yok z^?mUFXYakE?l_J+(W>sAnVY_d97q66V9ul@Qh}DJoTXz~vV!Hc*0xr**U$Eo9M`+6 zwY~C_?Df;JpVyWwhhs^USILq|1xh4M5+K0r9C1Z7r0DzM%fGCy6%p^5HOUD2agg~;I^V_iyrD73< z@PeXJ{xr>=vo(ZFr!?KzwiR&Cc_Zl1se?g%cM)OSAY?0aay*v~`fC@?jQUz+>v+^Z4@yxfME!PNVc{1l)4_v!C zk#%LR3A;8CrKKpx$E*M8kG`CJ<^ylO{++MBEc3=N0XLJ95fms0*s;O1C`of=FU&-i zn3?<8hE9F(N1r+HnSZ#`{r#C=ee0U#1HkmalY9T{pAv%5|K~T~xAFXQ9Q%dCe$#Ru zXz|dc7s-rCFMfK1?qBF4K12YtWb?$F-`ljk85?V9{i@;XFFnT{-178+|M#nj_S2vI z=XYJcad5tTX1s_H(JUI(XN3&57v?Y^fDm2UGP6#$^|S0*tISKUnIm1Cr3bu#X_NmU zo*m-HX9OhJyV?lzejJfebD~9m0d*nH-q)$)+US%A`TA)j+hN|1^qR!ruOaK^1jeM=V z(P3B}2OAfHq-H9P<7|Z&iXI?Z9Wj7ZzR_B1YeF4s8~92|p>-V*%L7A7c}7RZnDOyR z04S#4cKfDh9Yf9QZn)sOOV8fD>!(zcby8Z zcP}tzN(xd^lr~dI{P&03c(L~%8QXtkEWa8VTJB^bVv$^1+U|>eo=&P@-(#ImXG^-@ zYf~tMc2+j0DA>KNWD#p7G|2NQ6v>6g^FZoOfj5matd2SJfwun7Jg?!&luvqmobyx( z^ZW8yeX1u1TR;7rekV`!%{)6zo*5P_w~&&TqU1&JDl+62PiHyo3-XduogxVLG*hgl z;a%sREu})l4zF1ViBirLQ*wwo07g;dHaH?$zIq)BT)D1djXtzzyAZ-!El2^NG10Dl zM-Lnw>-e6#AA05kZ@i{Z8te#Yn7K4CiikRDk~Q^-1@=?@O6grS@ za&pRAyJGn=W-@UIh<;EcCmf&1>9t;-7x+P0D({Mo-lu*(VPadgbPxcvv5hbeJS7lT zoO`|ya_sqoQP}VcWk8V1XC@OT&Gnv=z9+5aNE=TnM4+@D$5U$A(k1RR9qTA+_8jMp z>z4iIhhFXeUb$pYc|JH1j28~*Lqsna=(mSD03ewNb8z9AtaN)fqC`2XD6pfE-049I z=_kPlQ(Fw=2Ph;8#pI~P=5otY36$2x(+@ieg+el!q*nw{2-T@ihrn#vn%*a)AQSce z<{7xTTW$5NlM$%zHS;W^ZA4Kh4d%o2bhH;vBY;8%XSH2G#M=1L#?+WsC}*?%C8+a7 z8T!tB!*#hHY;(q4Z&eP@Yhx0<|M7%}r4V@Mty#Kl_YnZt{N(-*yz$yr;0Oo+-@Wgd zul?|G09d(n=r4Zjy_+82bH}FbhmK7Mfft^;?5#I%yzKndS%CPRd!G904;}@8yK8_?biZ-?r)C^Akddi`FfF?;CEobi>N&Z~d7)M?RM(4*%rW-g*AorI18<5XI)U zf7`U_u^oqwp47$;4U{&nU-_n2Uw!q(=XQL_<2#Pr``GTihsUdpDDc&i;mT#_ue#;B z3pcDu4B@B0@V#gDJfD5!M-T1%(L+10yl~a0e(sj%_8~y!n;oVv9!g2lqbmN1y*^_xF##{Fw)~ZvX0c z?%uuss5a)@)yv-S>g(S9hMPLPvB$RU`sVjHZQHSLvf8MWi_4Y_U4Qw7Z@=~BE0>L& zN<@U`em?i215N1adY?bN;%4tymou7&nHNhdD#ct3+Hn3f^Ex3=$R4?Xtmq4)gMpjn zqbKj&vLicr>-Ga%w;y=ltyjJCmdg-31+|ID8V!i~NK{JC3ko9Ez;N_r^?!Zkz7rGm z?A?-#okfVD{EjwZ5%d-?n4lH@lQ;LwzT6Ra(kBP579Xu+OR))AoGq6OVc=edDgDwmy5vwJl_yI62kGTfyx0wL2ew z&^$Z-JRw;x9>Tgw}OM^AS;alfUo}Gkz-?3 z0J!O@4R5*m;)0*-Qx}}O{0%SPc-_To`aBaRqTl_~zsp;}{A+BY`kVjbe@|BH-C3f~ z|HHSTt0rRe)@L4k>{<8smdBsXtl(g!bj8N?>((q!Ot`h5`{FmpCu{Qx>$vm1S$4;_ zwelD_uR;@0|Yo``F8jD-QEN4f!LT|IK2Adi`kI4bJnw{57`@zGMa4 z-H|kIelbUc!~_iD1>%sM6C>1ueu!+>PjTLnpT(sTSsMhw(9n=0G1oe>RtppfBR8?J z#8G4{`M&S_{ynML2z<5i+$Dm|#T!;^+kF%Owmy5fP#SbCf@Cd|$q0@uv8Ut*-gNCX zmu_e_{Pw>;bHf$q8ErD5C2}Xf`TC324qFy?KD7JZN0P1on|E(})s0sQ zA-%$6b{Aey2#N!Z+LX?f)kRU*Y}B-l?|XdD^J9rUxaQ(>KK!;D2TH+~C-;2mUmrA< z0N{@MpMKe8YXRV%t-IZ6l~VA@58tw8`JhsA)8l*p_ctDJw&3Yqhi- zwfQjs7@w?u;j4H2U%&944);__@!KE&nOEO%c@*ov`O59z`O$;!_#;p5c=6{9D&LGW_f`eycY6Rkg_zeo(yr+A9zK_b=@^ zcnkpc96Hf3a@mp*ztGCkDZl8KDibG51}H^x4^EeXXcMgN!Hbwl7w0CUq7 z=RCLX`FkGS4FLO&jMwVTa?u|dDBf_{Ib`YL^~;wImz+@I#T%CA@XUseqmF3G8tvp2 zO?!2_5Yp(Fto`;6H@hRnLhvV_`q*Hl1OVr(TJ~Rl{lmNVAKriH7yx|#o`*m2k#`n? zwi)~Wx83sES6l@EO39CZ=xul0{jjkX08WfgCDCLW@YS2q^Cu_IUA+tdUUBUuzy2TI zt+fGw^=ntmY+A7AVeDstn5o|^#y-K&EGal<XA2?8f`>=+^Dc-@ zCb%}&a0P+w0t}%me-Kh-Gx#SYM>sF#=obN++6RtlozU3_ExPP^i`X**p&s70uMsBI zZZEs+TnD3Gf9bh@o0b~f_2APtT(%B!ogCShyym(K^PukQZru2#ZzmRF@8J_yoWCMZ zCHk7{FJz*mF`wv-ue|cFznWlxyZ0YmGBQB9B10x(YaPvK`$`lHbl}*8J8;?gD~rWK zB4v)^gKxS1r(b^!F;}Z~&sS2a_rK{{DX~0x4rh|fAvrQ>Y}%2cJ9CCvJ3JbfB7{RXN}B-z#kr}oEV$T zTio?)S3J3W4*(oHIq}io`s_KYmR)`6d6!?b{-$d$Svop2$7O;GSSQnbd>Xy`7n3!3 z33#04n&=oVJS_vxZkHg=bOT${@5OHjyQRoxjMYv<6XX{ zVfEkTGO*RuexmQ1XO{W9`QkM{T-hd26Shn5;JH#ygJU6fx$wlWo8P+(!kJ&o~UKI!E08n zSh8YG)Tmmc{bE@N>3H4tJh!b>9$2z$h0*cmty=KMIjxSuja!L00u@e&=?=Be`c5-Qsm$I8C@I&u`{a|K%-7#4B_Y>H?kNc% zGF^E@kuOpAltdJHmk@haIxsV{$#IuB&EcGaVynsD1;F3Ed+XnP?XK+nWy9t3)-JjH z{FPt)_Lg=x2HQOu#@=B!aC<>~_bJn7M}(Nc?OirH^u^Eo#%=$0&yVigdUB$ge{1X0 zyMFb*{?%uH_di~-as5kE{-xJX^oz56WJ0^&=H1TnOQcjFg#8I%JYwdKAQFXmK`L%$ zY|@xh$mptII&2+T11`mg7&WHqQ)3++&DK&J8%WeAN~Oxs=50^9>XPYS|Nh91pStl9 z_ji`Go2WJ{F#r%V3RxT&9k1_g*)~Cln6=4I)|ycq`JRx{N0ffxpPXv7Ee}b2YuNdPGLt@BQt9FH1R6Guc=D(}e2>d~=%z*L=@xT0J{&4 zGA3hC%F`@*aOzk)UV1IE=P!hmQb?KbKPcyvCs5f-5#cOG@FyXuor?l9hoA*v0V5;< z&^-@7JDV?j;<*D8)kdYz=0HTTdGwhB*KS;umY>6&o1e}uVD0kZ_OQ}E_Uxe>FF!X4 ztN?zz<=HH#I(PLb{ll}xk9}#sdg(P?P}q}y8&SFR!;G_wh)#{l_F3@CwWzb~?-ZZTS3VZ(88|Mm zqhBe3h+!D|L2=cFO8}rgag2!$96Y>j*CBV#l^3r0@LR8E24gi7pkQFQZ|k1hH*E(1 zBEI*L=ic;+jfvNszW(+b5B&T)uD|h$LNn4|zw^-@`x2D(@(b52Upj0}oWJV7``3pU z;Mz;pMcRJr?x%JhIG&t*!J0~`0MI5jW}-%;da~oL<2WL#iR|^4p7U?_Jp%w^ll8y+ z%8!5cP1hC!?}3N5Z+>i7ayu8SjA9eTt(woHC#K@434pam^o_fo%EdRbR-KZvEnC-& zv|Ce3N|j4~gv~}27K75@J6?a&=lXbuGys57scv4n+4@N+ zQHg#tpRAcvyH4L=H~Th3oHGW4;)Ph7IqghbSkmjI*Xa#z(j{i1keOyTbr9yud;8+? zC4S;&N@`-2@);O~1m^o5+m&UzUUlsSYgY^da~#J+_8}E8}mn(Mt z_eXdB`=dMaXB7kQ%{O1d%xjko34yM%=Bqz={JH%ni23PV&pSJp?9|Lm1VR8{G4RHr z2>|yzyyM`}v5VF%d(SPGxBq@ZEb#VQU-6wgH$S)gAOLKAdgssm#%DUNbg)wT#h-oa zT%S`R@Na$PwRhaL1puDex&Ph2_+QtpS)rsnaO7CMk-)jPzVhnDLk&*TV#7203SWvr z&&o}$SF@s9o?_ZKGSMk@^RG(zB#B~2-Nwc{W;>Ih^%a27A8*S|BrGv{yD(=XR{l}gkt17Pmx%!v4 zz3P(g-RlEyyzY|oR;8mYvZ(Z}uk1P*;pg7|@{7)0nkojjEY!G(tJ+yt-{>%#Abls)zfBS1)SefW@yUDzGnXQhhrG zg;X9OAfr%93hDa=APVaVd&|B4<6Wl z^hDM3R?-f_zn7q46HYAaB+xpA?!VPwh$FMn^AtTkFnPb%-4OE-M}_doRQJ0E%c zxq~OhYs9={xP0v;=f3N8*NqMqC&x~>>wNEPuUI}>xpT{o!^furPpw-$^46O#x$2@- zhmP0AChGuj$9+$|@f8;jl)Ny~?|#kYzLJk@KQuPkFqQxXGi0qA?mndQq*6kt<;zCD z^yk0x-8(nkwQ1|ly$5TxW})DpvwHc>H(c?)xBgTyn5UyzE*3uj-+twL_dImh=ErvJ zJ6x?boMpXe!bQ>T6UUDdQBVkk5MEGXBBP^39DvChqx`^8rZIzwn#|;&(PkJ6DSRanQA#0% z5JD=?mtOGoA8h&O+aGcf;g|mKXNYX6GVGca$kOo>CrYJKrBX3EGCIC}({o?_{-f^X zfBf`^5P-;0eyikCiL5os^QH0;0fjhm{J3L7WdKM1i3r5d4CBC8g}`%$P%2Ld>5^n_ zJus6?M-kbHlgEV+nVdBd6O+sKd7c6U-!DQ-)1JaGs?{5wl3toTD-=tJSg+T$)*~Y$ z)|w~`0iakaRYq2fuH4Y3Q=gG)BrB4sf5R)Cf;eN|`NDZ2nmrXKPU(7ip<4A(DmCri z$X$TQi)2?h!%@9Pb*y^wh!d=LT=03S4>i4O*5Tdcdl<7GgX!!9v$f_d8ZW6lAe!?v zGaI9&n5`t+3;yc4u?EG8ACycSS)=2yt|MJ259>Ir*J=Rlc?r*?j>yIl05EW|GK`2q z)XB*g2$WI)KpY#Tlw%h&I?{2g&7j_lwK3L=A)-{m(YrL8&1N%^1I#PPOXVrgpEz+$ zdA=7E0JvG7(%LpcJvcZxP$)&snvR?0q5{YS=nWz&C78JhK*U;G6uu`tB4c&j+F6)Y zP)aQkG$LILykfz#maQe0Q89GY+ook<1kiL1pR{hfx z7j`sX<+n#iiO_FH?H)8HlAaGQy%xhQl0tbwG4KC5U`hD}oPYZSx0JNFS3CCEI$S-4 z17>-HFN#rUEz~ycc<%UjPHzyo)tN4!jnh3VRcRZfM3)Cz0bbvn5U2X*nGyn1UiF?6 z_Fc+xz_ooe?V$y9v;p~TIuT7wFNw1YOmO9v4eC-|z#N@4_Clrer_IdE{NnfevHvmb z4;tZ%_TF319jC+0W<24g*CK%j^B234%Aeh7-uy3+h{y_|P@KjkF^_9TRA;&4hKSAD zcvzo|n{^kZDd`g#Ddp(0mCV$vPP+X%C=C?LgC~w1otPLaH5vlZ4+0@@Xk;0aH97*s z!I42COV;{@l2<5|2KMEUBgtBiu2>BW((?gvr5{+MO&mEhR@`mFmwSFe>xe8JJ9;P#8c3&QeNE;&JIJQa}#Co|hh=@*WqEM_DW5Q~c znZt+*+H`Da(hFw!ToCcpK%>?rJ{D>Ih#5%UnLF6wnW%$bn>rh`m}Y~`Aa=)^9ib$V z&9LaxT=Yj|`m%^K_n^7xg&ZvWHLLv2i`o&hWa6+cgv!Rj?elKiIinlu8Mu$6^&(?L znNQ9+KNSI;%5^>|+MXcgq=P#b`s7dGv#YiUQ}rBXz~o*y7kMG%NZB$BD+35}+kDoy z%8>tG?o>+RMc1dF0|0w8q^CLU3@ZdmInmNfgG|Rf7X{|4WU&vd(fU!MwlnkGa?Tue z=WDP{GY)gtlkvAD!SQtP<_i`ME}}Z!nG?0(izkv??A86!7)(QsGF`FE83NUv(np9w zoIJG4T5WYiM1D|WwnoQ9Tx*2ILa|&fSrZ$hmFEkgble00<@tz0`30@xiSY>pE|&r! zrIfz4+8XWo1tH|f%JpXp4=*CtCXYw8Npj4XM9eHbpR9?SH9+)(l8&P&Y`Dmb$XaWM zMwSX8$ZBRX#xPMF$A}md3PMP!JZA}n5YEanbA4(;>v+lXRm{Z1%w*!orE{1pGc}q~ z7)6y*kV2hY9$b=fgSzaI(Xre9sYnB1+E>m^qFbv9@8_TqvbL;K9Km zAyDgx$@+y#irE4)4UDc_vg*8iu?!jAV!7xE$S-nskgYN8CSsmno)@4`BRP#iAgbQq ziAW|w6ett`lhuo7sko2c{la3~Gp0-GRD!g;5UlQOM7$bPW0NNiC4EG>_92&X{@tPe~I7_8CO z#zF{AT2qoh1`%^D4cN<><}+l*03ahHWQj5YPJ%@uMkD}oPew=~gd{S+m={-KB2I%# zCd)4D#unDs0@ItVAvl;C>;5hS7zg3|OK=C#CK z_yz(KB5!6AQXv2d2@JxOx~4&|V;CpI^fHntv!@lwm!G9*fWxC)(zKg68yOh*^gnSv z1z*7cG+j`bzyex}&zl=iE>kTQTlV3MFa@XbH zIHi;jqBOV!PgnM$yX}_|t&ZZTq5NWYzs{Ig%K)t7CL$Kg1MWR*w6(_Q7!lc87u*OT zd_TyHTvk5k*cigF$waX>##j?aneqcMArpc?6ev&$;YkscDnbah)-`9f#UDg*9Hp9{ zEQGST=t_`eCij4K90IVEzEny`<+>DHj2?weYqb}YiHze8B*WGkYuRaME2Wh3g+N49 zN(v$B^%^3@h7d9E0%K!lEhWlS&ca&bXbAwN5F!=PW^1%HhR9^)k%$f)<{tbw%nRI+ z-NSW>5F(3dMccHSKlOeelgtXZl%x`%5cVz z>JqSXR2E?`I)eepS@! zV`|Lkh>4A{L<}4ebDnTAWzA@%1HskZCbT=&{gO6TNESlaG?#?{)$yauth_)<_588p zzVD9=4+B8hth%#YrGBAUR8kfyBl7eZLgwxUGDI{wj>5X~3Xn5|nDkn((V-Un7WQh{t4uL3S95$>aZH%>KboAYOpKeAPfG=1(dez2rM7nWE zDU}q3;((CS;nf|UthF|dB19piL`0O5b(GnUO^@&Vvw!-r`}@zK@em+ETYg8lK|FIEQBbRMuo8e{NsmqMcOj+ zhSj6jU%HkFJ-^@@1CZGQF@rUltl?bgJf|$Fn;+fwsXzH!ckmzn>{I8RyNa1NJ+ke0 zKJx{4@b5qO$qnbMoYUiVBPJ06k=uLw`_G6z;VC;H)S{4ximYip3+_g8?My#nx!2rV z&?~XcjEIN}g-H<{%s`72JDt%KIkS8a^2|2pvs@9?v7^jvtwtds0eJ{fGBW@Hzo_*H zyDI$>?;vdxL;w&%Ivh)&0Kq~CAeK^cGExZ18cT)rgh*;E5}y&J5DefN$lHD!1qz9r zc>S)$+)XJV9RCP8i6^(KSQBSRV2g7ZVOG_-bHPJ+8cZmyI&nEdq68ge1|lHhgkT}r z_$Vo^!30Zei)fPm3XxU0pb&zSiW^|Q{l0BuQw;!k%gq;Geet=uq8N7~F=5(@hiMqa zttdUQB_gj1*!j4#XuhQ%m=r)k|GYV(vtmhxFDsLAPm0(&=fGLAA3V5YqS^$2*T3w- z>n>RfT}f?pdP9p=2hTHa<~^aGnLfkQy_a5mn{p-33SdN>2A?{EfK5y>ZREKiY}q)R z9#ioGummswp8fqTu1zY}SDK%n2ynJVgmY5h>sDYu6xGS2#}DrGgOcY5Dkv2PN9y$& z5tYhiXa6z_8ih5bB#~8K;1|j+!&mZ00Ki%U%+_e7d33>MvkQl5X##v5tA zqy%g&@oY=v$&%LAT8l`Hdes^Oz(U9%2#9%nVk(HWjYGds3W^nNOtTpli$z3~QVAh+ z9C406K`PG=in*jA6^mtN(sl~0O)6Yk@QYM_!9`A<@B2XzH>#Z4KEF@~1Supi8?p{z zX0lwZRP4=bTZ4$o3z)4nrgvc4KgZEG&5<70QHWxGrLZid5<(K` znYI+!k-s1^z$9eQ6M11vv)-)4OdzBaToj0>xBa94M0%lwTIc8I2%)6%AgL+<0M2Vk z{$%M9CXB;Ux-!L7{2W?Q0|VyDJ~|3DT5xM_S4+wnDJ_ubVEIg!FaslZ_^r(O{&f_N z%1%m@Qn}wpA%&3Ler`8l*!TI*iR}Qped_iG0PO7)cWltPUI=a*s#aS?TO8M;_9Wf& z5E;_WjrLHhmCDTD?#1g@{`P-(qbpclv1A|@nc{haMY+KhmryQq|@`4|CkCnxJF0%6)UIdfo6klh{ zmuUT~ExJZ!jb6ksT1xMf0?G^NEVf1;+qcycX-$673(7-rSkujVBaE2Y3&=wmg*7Rp z7Zf1duM@%g7==U>&MOa_4P(sE@CaEO$4x{Giqg$UDOI63NG5Jfo{Xag0DFG1!-=y- z2fnvr`7*bgdS2jpf$|H?5b5KV;_<15=Xpbeg8;ni@w+>Ql&xKT{?&`ly(E?JJXstZ z5kmTf5|Ndj&(`Xw0f6h)FR^5;Hoz2z4Jn~iDnXJLEC}i8v?Cr7gJQ+#usZR)=NGe_ zSsXPTJ^%mu%6&TyoXCFn_D#>;zUkSkE?V<@AA3_WK4kBGZ14SBckMlVqSlB?1%K7D zp=&p;ee=zi4GffxG0kSv^E{XQLm~1!VcYi}{j-1ik^B3PKJnI4K~dbi|A~G7-~ZX{ z4u0j2Km6$SL*KgliG$BiTH-a!hhKBu1#i0P(vHH;XZ9TX!2{3jI&`wyh$=;Y$x!90 zi_f|BWfzq_iHPOOz#shOzdp04C3yS2&Ch;s^Rri+zw(nmcZ<&~8DJ_)}%I9>7GP7}1k<5z@jh^XgRUs9z>4J`1&OsJ7bm=d; z2q7(;=>fWShi$G48{5JU?6qiJ8mc`=Ovwb2HkT~=NvO=E6jEl*&;`^qKdd@wlUgzI=LKiab63*UMm`{$lRC-xjV@#K!fpZw_SvopW(<0tbbmCv{e*72Sal=hluAk|*_)Fh@;P(4k-%vAAZU2$o`;UD6j(b1${PyUbBoLzJE;*~DRO0;QC$NHVR$(Ar7~N)aFyN<#p|#92TSM^UMq+l7S`fPPTQ zTQy^}HIY=FlrEvdMn@SsN;y623>CprR$+Ob>n5{ zY*;<=i{~)_kd3GD{mBww9zkc!kr6VJHC9NWrft*aUNK_Fv*X#zhxJM; z&NV2U6BtX@x;nDfQ|tc-L@tHq?ph=%?bdG_qlJ_`Gi}p8TWdJmVFE}=-)&dKj_ zIxT0H6|_b-t78CM9$9X5q?-*lce5fsL{S-CAw7T5bA)GfUWAzuIbAS>AbT!CPPw6( zbM5ZLWNmldR(F?SpM+WOxy4!UHc{39E`;plC36jT#IABx>zJ9X@m;J&i@{%$o9M{} zwc5{^i43!9(U|pdu{dKFBO-ENgVtJWEX$;B;#JpdSTZtn|Kod{3E8-A+52w25&*QZ z_dm90$NuB)t1jNK^5@@m^V;RZC&ngj`@z;tkM9P6iE86(KivA>TQ13dXnM4~)k>cs zz(Rcdr(b#Xg)74-{^mW~?tCzjPJH6ogI8a;5&-UgWS2X#cE!-AfBB7`Qodh!Wc$I- zeCY=O5NrGJGY4LA*_zkgaDfoG`N@6RU3~a$FLS}~j~{wAHG#qJ{lcvq)~+a4mTZ3d z&>#Qhm)$i#xqWxHAHg(xD#0MuPGA*2-2Q%uxeS9)gM1k42Z%|2vgU~36cN-2p6Ol*t+ zz(NoJfK*-rnj^}DK`kI1>o`QGtXC)sdDL*Jxh5*56v+2qG?qDJC{@_2oXP^`SK)F)> zh`^XuT=nLgFS&N( zDqt=Z{P({0%DW!kX)OW3iHWK)8UUv1Nxr8Unz5;9_3{EBUVrJiAA9#ru{PG)6(bd= zHf7su0km zs4@+cwQQ{|R|ZfBr`igMP`fXL@PncTFmWh^6jJ$8L4afpGg)G7j31P&(Hao}{6eYO z3~RMo+BHZ*pf(l&l$2@tA!QqdwG?S91qy+_FO`&1dWcBcW+7;{r%R~J4qIv4n`FvX!g= zKnPhVRX_+Sm5C$eZV!dW1k6sNPf7q5$_ui!?sHKu{PRBiECF3Z{K?i08UQUfAi13y?WWuW#_NDc>T)jFI_iS_UrXJ04OCKNR}TW zYYh@gAwT$*8-(<%)njAh&+IvN`1s^RT66SeCW62QlJnaRxcUYS!bnQLNq~p;2fKZ-NejG<}6qU+@ zez8bK1EP?g=%*z~WZND2o`chU+Ns-)a|6g?CP|-^UchF=kWOdqOpX0|(-*kFz(xj= z%6vz(L|{oM9}wfH0l6F@_cW(%J7qt2Ajg;S0$J4Ap%V;wnhjSXpP=*1-AE*-edS5r ze6sj0Q&K@fWSJ@9-*j{yPOk^i(N-EuNko{IQ@Y8=Oema;yX)aV*T2q;X~Bvk+Z3ts z8Qz<;x#gB-N#?x8@fJR4<^xw^E=#me*N*zWNjMayIQUCxT07*naRIQ1@#MW96 z7SI5qQeIXK!zl`xDA^OWs(8`{jI8gzB{JB)K*uK<*+N~pbSQDrlB>a0OIvpF_*m6Z ze`U#-EVRgr0STdmREpc0_J%4YDWy{)R7z%nZzi|&o}apE%TxQO>Y+P+`1s`Ey{^XfAhy%ckDm5P%MzSKZoZWOh~_I=#0V}ahgqL`kkHU zjPhmf1)>1qC=wC|2TGF=Ef*x$Ns|D?Ks&$4jI?w`EEBd#v9vo2?VbbxxOM%4Q|RrL9wKxM(W!p@Q%@us~ItI7)1?bwN%=e$eM&W zpR7g1`owWgt3q|u6u?WCjApvnD8%t&$B3w0u6Uku)ILH;CaPD*f`YG<@1E0CwN|S) zi`pWBwM5L;SRqxhR07~QYFKNm(SX1V$_te8lo9~K_lqb53K_@ov7?6ppgMMFV06`z zRp-wV9nFJ3?(&R|m|1J1wGB!GMn_~~w_L&~oERT>pIW|Z&GJ=i9bH*io3uuILD4Bl z5VJK6L=;k4qn+an%$`>O0IfqHYvPbwVY)FoVj`OhFRYHkdez}hI%=X2Ou0}`hdOKk zvqP;1hDWo#raV~9P8%Fqx^($cOSZgkEIYVl$>@^dN)*<}n2}|xWZEt6d46SRl*tAK z`?=qI&o}OTbkh@iCu?DTxSrm1&kiUkz1`vjw72iDCsN2B9t zKIW5bvpNna09Yztd7g=5YmK!Un5|`I)|R9YL7?(Gs+7X>B!jg&s@JNn1Ybzu1tliy z7zc$^E<$`8b} ztt4sX#;k_hO~x}_sy-tJOY?9(18%nAld+Yb^R;&!*5 z(|D*=5RoaM=ju7Kp7tbmauV<@qOx?^Cyf@Zwtu%!l}tD?X4g=WYujk+^Jq^}U`t3L zD>ZTo6IpoIw%9TUy2U$;*>6C~Nzm>yB90D~vr5|MPfles(7leHm}(ibp$g`eAlxJA z?s-XAz1wKJDG9n0x%<4FMCRuYRf<3JhHKvWnoIT{o!oig#ID2RPwhP77-+Sj+kW`? zAAIcAUicv(LZr=??|9f9x$xYjpZMvU*Q{Jts0@QYkT-<0?p2swlQ=GLT_B&HGL~#U z@M7G?v<*33p-+CyF%#lRWl8ebMqVI`(*om+ez1)V0y~6GAl*gMuAu}LNe?onghL|b zHSM3QnEP7`2oT$A%5YX=n==zG*zII1$7#_io;Fo8m-*j!b_mFmMECz`HBHTQyUW?> z3uLAqg+$0af_b{7r%AVu*$ay0;Uzk3#9_lP7X3nrt!1`RSYx6_qNcGK4X~2az!diRm_*kLf6$4KxUwOWcqcE;^R6=^5TDEiv z5gj{mvJvi|IB{@z={ZBo&Y5w+ph(o%5rxrlqdHa@TILoiAV!TTYqX9dB07BJ=*W^~ z7hZBj($NuzakJX2O#*XJ8W2*EHN@6NaVrgG4NBP|dnSb^u&pN6DL6{y6@9gS^^!e@ zP5{8>CwBk*yTb|s0K{PfQGEZt$CH~?^1^eMleNs`ls!xwI#h$0bkxWtz^v6#OS7=u zr9;GKbv#pqU~6m~ot&)y^}pQfcC@#?>Wb^H+<5(!8<`=}`VT(;&0Pmi0>HszlUf_k z3kC)&`6Z^c1%SOrj%7N9Z@c-@;Yz{b4f_usZOhEf63_2iP$rHR2x-p7=JnK+PQ@8$ z_8YM^nuwf;V+!81Nmn>-Gv)dDlUpfJ9nbq_U75Aj5da9~Aqo?RLP{?v67z|%3Fq4l z3=9qgMKp$)OO+8oVNIN&?hesce!*eQe!(qOS0hR$wxHeC zGStqw|7Qwba&b07BphO{r5GWiqBF=vHq<7SLaYBfs$b-n0cy!!5 zbW<+jOikPX01!qx3x;3+ic8#|%`pDV7w_1A(@q#Cp=ANhN^#$CylVAr5HCNoPm5dkp87I_>l1Lgn$l?~D;5Z=&SG=Mp4&(TnaFo`pOFc0^?+iOcel@EnVWKR2)auTD@GZlq$m$ z<72KQMTn%MUr32UE?qL}1ZJZ~_1OMrPzYccT((vSm7kscl-m$-YH|!1hzXeeLYbKS z(ttH)d@{+skVoenk_=3u zo>YFp4@$LKtyZrM3=9+tMYohDCa1L4YuBCUBxO7ySFT!POr*nx?+LO-dA{@lwwjp3 zX2V+R=-1t<@DqPorpyBd30)Pm=Ld<-jH>_uh?`YQ#^_iI%|OZ^6(P#5!!v}8^G;GS^NazdwdNF= zKp_>Ph?_M;;TOwpdbmDmhfJ`gT*o*7z(OjQcme;-9xqOEH!a@h1>oaS3It5KAuuhD zaZyfE4bR}D^sGCWrQw*Jb~#GkOJp(4*D{ey^P&(v>#3NX9-cl4(IJQ%gP_QMyu86iye{nk4@}i}6o>KPkK5L}A@&>SE$e=QhwpAW1m2 zjrMHi^eKTP0eZy+s}p3!*loLy>^gAVJ)mFz;4Q0{4)*-~K)LYSKmWSnfkKys!?|QN zayb#`ct*fXA9>pi7p+^KUEAKnCwCq=o>{@`FJ1Sp*IpxpL_{LGWJBxBXZIc7dw6W1 zTzJPVS7g!QL)#8)d1_xXjNbqD*DM`L?rVIqmZY58Q<}4QK&L2WFuTmne2`b{$VPWO zwEP0k&#qZaryge5dCWv)jY%xJTO`(6YefZcj>Ka_wAK>YtT4S*l-~AR0Qqs~9*~~zwqJJcQ@wjtPH`G)rbezlx3IwfxUH#% z9k|yPEcbevicUXkD!W3G-n>fP@k%?Pk#1$XQOqf}X0nv3!x&?=G14z0ibA1CWQ~rA zD2j~`qEIM0?1IT!6Qe-Eth~VUJY(v_eHFlBCKI zCF0=Fu;(cu6>F`vb(Nx8#{z}&JVZ<-*RzHcY%LlhvNi|;W)?`mER|=iZ8RDHP%H#V zldiR74Y9VCiuEa>lwT-|q(e4o?B!&Zv{~z*SONg6BWvAEbx^4FloY^ZjkP9q6fBcv z7X=Do;s}Ir`nSf!h{Ev^BPQWd%kc!3%KPx!UtTN~A9#G%@v$jm$+f;B;!vgVsgJzo ziQOk2d}`nRqhs}ET=2bB%Z9GI%-mS8cfYnhSt55eR|BV(~+7xuH}j zYW6!}8<5K|etsicF z%Pm)}TsoZZBP8z8T$ml~4(y<#AssQ_rqbI7X?2-kx-~=EpaRzDZfC+Z5#`ea9ie{5 zzailznoSy#$jQMka62K=aY$sN*r2eUXQY6@SDxod&sWS$q+*@YH(4^8IUzpugOb~A z$Qoj1GS0;$;wUxyKR~Uu)<#O9q;P12)ASKip^!RmppXiK#LXkHmH;gyFdALD zd|+res#lq995$Hk#8lJw{o&zZM<%1AFbb<~$oxXt^NWqz7!yUYv6extsep)?>a|*ej=#&I-u@+2ZIT{7xSrZw7Ht+kD{S+aDwRH{6@+-2F+=iI=S0KxD1aWbN4TBgOJSWpLQ&n5;>l(NYCbxPY}jH7=#{ z3Pom!8da&h>^ZuR3UrjmBWPAfyOVjU-E6*jXb<}jg zo$>dl*021(hHpRjhao@BP69P6ifLvI14?(Ij5iI@hLZ-7v)D2>pr{7 z=$4;cpe;ni>e%!7FL5cujChNgrBazWJX7@ud$L`0=RBr`d9aVIb@I7VN=!2%?3&O) zWHh8i0Mx8cud5C0g|eGDFmgR5RL}SokqrB3WB*$3X%2f zCSg;?t<~~qa$0v;Vhj?s^w!_)^HNADEfMq)2z9Aa2M8w_zLqzL3~hKz4tBsiho{T` zCA{^aPSD`A&&0*Q;8+M+k|0T;QxYgsf)Tse0&NmK z6LU*Vfm@C$U`kT}0E~HXjMFw4=R6Y;k(9EFav&+k=1le@9eg1KB8XOyo!qar7A2n+ zg~AN;!P%bNB_-cyS+#MEE)s~kX!x6(0*Jk~52AGOCdacxX`&;YMaGDL!hu!pG?8*F zxQUVG9WaxiNxHIIuu!faBUeq25JvSc^T* zX(h})bXJSfKhz`r-sQCR`QaU2)Rm66e<*2K-~c;XQ# zA5kb73goC+W9DWvE|$vW%21uGQ+snDE$9rBu06VW#o%3Ex+NrvR~3^itcFsXK8{C>vv@rm6rO$Hw=3zgQHA zN}waJF*;1S@vu=Hvkqh;o|u>jg1{*S0&uZZ^8LcmqelU-I5^rJ5i*lCiH-Dv;=u4S ztz#f7g+!S|awck8YnzdgzAh#t`m)8b!Car3Fh(~bEd>T%!;QRYhEc3NB|RlQ&+|Ml ziXtM4w6#R#C=yZ@if!}@aTLZ;B#WDkdK@<0 zmSc4c$c5s7C92jVA+S&=6A_V-%2!^&Rf$@ooRwy>rNI%lR>u)D#ZgmA85GJ<7&hwT zZgk3(0Tiv)C=|l;3Wz9_=PIq-2)dnkWOyjmrpM~!gv${!o9fY{LnBKHrOHeh6P^a@ zaj<$W|Wjpo#e6V9g@9vLZ@2b5o6=6dt6 z*3rmd354*x0003+sZ=hN%AAtpvo&6!42ULfvaxAnyCBmx9#x@K?|Qm?>coj) z_X2V|DpE>WTK&{ajIUt4Ibg?F~<3FGnuR zvu3Hl)VFmx+)RQ4TEtR49&{S`2@$=Ya@ z=p^A+${g4#nipw{OIt&K))A6>knXv=aZ3j?-}~RDP2Wl%Vk?Ty)q1oSL?rWUAs*`K zT`mZxTM+_hJksk7?7n7f>&@qmP&fIaw1GVz`g5+>xD}~)_!iKDKt#sGk)SvtT_6ly z^7Ng3P6;OQ|Fie*F_vv-_*5iBp9`nEA%!uvfZYI9cCxP$c z!^KlxS~V@V3nZc>QP+TY$gM2n%xbC8%H+`kW90VlTg*3=5`>ivGZ-HI9jtQJN7 zI`94a-Z%p!B9{li<>lq&Wqoo&i1^0)-;cz_Q95`qS|x?h?8f%n0K@Aqm5|sMxtP4$ zZ<~6TMfo3n;KSu&wLO1}$gwXV>-U?PO54=+ez!V(usXeOV3^}C!W4t1RBxZl#fg4%jRCSCJ9Yr$=T1yLw4pcv1cAXJL}>g- z3hfZ^RjX4~$u^mf-+7{@F|^K?)$-KLLcL3&)hxbchU^HCeUa~VwYK|@G{sh8Kq6HM z^+t765=TH{r)rPiervHuIymzU zSOd$-ZbpMIeV=Si&ELlyWUL@#|2xDiPcx|nPoU>x@H@w&->z1EQ`;a%JUyn&)Oz|y zcTIpsgCAkvRXtSlog{x(T)-5+4u^k%G=}pbl=7YjbpVao6 z;7HTZ(vE{poVVHF2n(In zObR0jsTWt6w~Xg%i-#wX*N<`8#!-)PmXUNFYO_w1{)$Qg;yg{l>yy9v>H{w!u<(M# zfIb<+cfZ^Hd?Ajbe0m}gheJkqrM1a1j|2h1r4$j7pSQ_p@YR)g&M}BUlo*F^a^r^l zY4I{siLImf{tKY4P#T6jbZ?QRsuB*&1d=o`ACh?w2_P#g;07*erR;LeR3{RdsMZ^d9&ti%x21oqp z;e$LIB}ODsNqFe@J6~bUklet&f=>4UedS0Jz|*$gpFjR&Od3;q_}UxyU;kikCxm7f z_FFJDiK$0qb$(XPSBpicx3S%;BmnFE+w$gVh`_!CFbR!F(v$)-634a%Gm&Vfr)LiU ztleKCAp3&YnN#Qd`t*J-v}W|ziJ2j$wnoI&dJTYC*-KSI+q6x+zIVS`o}^G80Yql8 zK&5J?``xZ->htqw!?ZbB6@!k>q{B_fZkh&(sH%;0Y%rC??42(F36aebn5L9orY3ne zH}-dPhobA6Rd>uVdzmEcd9h}eLL(_OZ32Mx={@J1rUYG3h>*Q4Paou9P-2^6V&}-< z?4AdJXHVYtzC5}A2mn&s5@5@fIKs?H>?5KTvD_Z&t z7uF@#4PH~syG4>`HynBXwQgcxbC>GlmAKOkB{_EcxZ#|MT~RJfq}e{pf%i1Eb+?_3 zw|QHRtY$jKpH8nnR{_XeS2EQkV&=zGW6T^gij+F;onnu^?Me4Th;Kc^9y=D@*cBw# zY3ugXoKajUZ;&Ia7N&y|kuvyk2I4cA9|1FupNJ4>3ehxELZ0B=pU>2`gOnMEz_0HP zj=W@%lsfxjk(~2&Oar@GA0Pt(vXBI^;2{@&q#<`W(N2E8YbX+tnW{(!;qC3HD0BHc zLGUgpmqB3*5sA?hvGc1UVrHkrHxrepYy2SsB-O*z^XP-W_>VsE;Wtjfo;y)+(%k*W zF(Z7nDd9CPiJ1&Ic@}nWYkqCeOrfX03@tUC{s`H|Mf0u!?}C9QrvTaKx@q zNC2_R*iz74>bR+rL{ez$tOA2XOq}}%2ofc#gu*jB&&&ovM6*O$j7e3K?oBNvK?LWr za44&SWZy#3rfCq7nVc&^vri(92@&^ojnlKMa(qH-OKlgWj{#U-?D}LwK{oa3SXcf;fQ_l}K&S>H6l$<*TJrU9Vg3I5c}=CUV&bEXB|l_Mt2*V$PWm07^C=v#ArRfcmTMiliJH9@kgpkHr=XwRteo=N77sD!gx1WrHy`%hvNs~Icl`lt6m|q zsHA$^i7;n|3=z(Fgl1}The`Mf-~3)}glGmaNvWAiNZzq?e)fbW#eGRB*v=OVDi!i<>Qk2wAb;x47@4N{SnTcbl+Vs9$RT2MgjE;b_(fO2)3pr?rK_uH~soSr=}uz2xAokQeK+M}>WTL*vRtM~>_#8WF$zMtE1i_9QPk zhT&Wvzg}l&KV80GWGcc9n{F?Q)%_Sk*lxF{r>A9AxfrHkT_h^1rJ1c$FxA-XxhS1S z07Q1yHpBQV$_l_FwgBjgQY1C|UEWQ7xgd7g7qgQ*O@SzL1NSvV=j zQZWhiI$q9Kh=?FXQM#fccI=#pY2FBDm^I64K1ans>U!|+X6gF?)?}SA&WJwCJRIcb z08?)XL6{!-#Zy1KKK!~lW$d6&yyw+#&%^Ws&%3)LK+mVh9LqXBZ0Ceao9pHX3x9dAI`h&f=ceu4+s3h&wKyh{XajNc`N_>Fa7$yjeqlgl%wI8F zUrFuKCehFpZArWu>T$>7n&A<)=(?{aBxags`J2*u*D?Z5H=8>{WIwow6mS$$I zs0y`3>6t(!<*5@xGh3s{mBePYZ^CK0T%SE^_Luw3({i!)#LG|hguIXQc{K6@DIU2N+)-YI%xC)pBL3_Z}>>HJzCi-@)92`YLv(KX?A9)~&BVr5<05CgX&Y46H3io;Yj3G4AILE|T@AtWmN}as`K6>=1 zn>oJx?9cuD1pGrk{xkVEfA1f?`Dgx{pZe}U{1vCGswlXBg6NBdzI3k0J7`;PG&YVI zOfN4liRkR?>^gC^O#FX!S%zwg`-~`6a*o8^7vz4IlfpH_w0INB{QYXWJ>!|6PuV z?_$(&Q&r{$uadc;0nF~+t^e5po^Jl9Ys_kF<|@#+TMrJP6FTXE!@!UYOa@+djPC~6 zkV=jseElp!z^TU};G9h}r8Er-(0l^qk5Co~?7m}4tC&iB{FB$apXyFEl@8-emDC5t zgG7@dGZ7JcBz`{T^*TcR?Q+fB;JKwX>vKhZZy;=%nS?sD?XC%aak4ypP(OZqS8q;F z7KF4sdC>KovUh_d0BGyoJD;laCGPf5LrnKhDk5@4Nyzt4m!h_-TU9&1+;i^2<^UEQ zGt^BoQ*L7)LZ-*>Ji%~ zJC~0?Q7qQb$4!W+GoSa~dfqIBRwOw|mi5NWMB=m_O3Xxl@N!et*w(6<jo`+c@XF z_e4z2I}tEQp#cC_l;n%2kKc6Ouhyrza=^~BqoE8SDHi1d5LE?Koi9v{*r{r}-{cGQ zjq9*9y_}O31?|J*__CNWNpZczE{ue&y1NTLZi5`~K3p8%{E~FzQMtC*xJG+Bg z)6Kai-nuS3?bAz6;*Wp=#nF`QH>4J0P8Q7`yzw~zRBz8U#i!@z-Z^#!BAO&qRY}Ei zT`o?V{YBXC9=!H`Ky3FLm9*dQo$I~b5hccUzlouap<(vJBIbOBgfUzY({V-0xgw=@ zcK&9Cciig^meq-*;9Q%M?CY>ZHw7dCK;fAv+lF$nI_Gyf|VG|WZ-p}XPX!N2l%fBx@({4+D&KhDyg`{oxdXkBNscYP8$Gpx__^8;$Z_0YJ~Ca=ay>W4DZ{FCNd6*6*%L0e3a)E8+%DL8d8M~29F|QF zlt)qw8AOy~Q*WPDg)3iswA*eCw5SA;cblg~ob{dWom9>j-e((FU9$tE++9~mU{)@PACKAGE_SHORTDESC@ - CC0-1.0 - GPL-2.0+ - @PACKAGE_MAINTAINER@ - @PACKAGE_URL@ - @PACKAGE_BUGREPORT@ - -

- @PACKAGE_SHORTNAME@ Doom is a conservative, - historically-accurate Doom source port, which is compatible with - the thousands of mods and levels that were made before the Doom - source code was released. Unlike other source ports, the goal - is to preserve the original look, feel, limitations, and bugs of - the original DOS executable. -

-

- Full support for single- and multi-player games is provided, for - all of the original Doom games, Chex Quest, and Hacx. Unlike - the original executable, network play is implemented on the IP - network stack, allowing it to function on modern LANs and the - Internet. -

-

- The easiest way to run @PACKAGE_SHORTNAME@ Doom is to copy a - supported game file (known as a "WAD") to the root of your home - directory and launch the application. If you have trouble with - the automatic game file detection or need to manage multiple WAD - files, you can run the application from the command line with a - path to the selected game file: -

-

- flatpak run @PACKAGE_RDNS@.Doom -iwad ~/PATH/TO/GAME.WAD -

-
- - - https://www.chocolate-doom.org/wiki/images/9/97/GNOME_FreeDM_DEMO4.png - FreeDM, DM05: Metal - - - https://www.chocolate-doom.org/wiki/images/a/a6/GNOME_Doom_II_DEMO2.png - Doom II, Level 5: The Waste Tunnels - - - https://www.chocolate-doom.org/wiki/images/4/41/GNOME_Doomsday_of_UAC.png - Doomsday of UAC (uac_dead.wad) - - - https://www.chocolate-doom.org/wiki/images/2/2a/GNOME_Freedoom_DTWID_DEMO3.png - Doom the Way id Did, on Freedoom. Level 3-2: City of Corpses - - - - intense - intense - intense - intense - intense - - - - - - - - - - diff --git a/games/NXDoom/src/Doom_Screensaver.desktop.in b/games/NXDoom/src/Doom_Screensaver.desktop.in deleted file mode 100644 index deb7274aa54..00000000000 --- a/games/NXDoom/src/Doom_Screensaver.desktop.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_SHORTNAME@ Doom -Comment=@PACKAGE_SHORTDESC@ -TryExec=@PROGRAM_PREFIX@doom -Exec=@PROGRAM_PREFIX@doom -StartupNotify=false -Terminal=false -Type=Application -OnlyShowIn=GNOME;MATE; -Categories=Screensaver; diff --git a/games/NXDoom/src/Heretic.desktop.in b/games/NXDoom/src/Heretic.desktop.in deleted file mode 100644 index ed841628bf5..00000000000 --- a/games/NXDoom/src/Heretic.desktop.in +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_SHORTNAME@ Heretic -Exec=@PROGRAM_PREFIX@heretic -Icon=@PROGRAM_PREFIX@heretic -Type=Application -Comment=@PACKAGE_SHORTDESC@ -Categories=Game;ActionGame; -Keywords=first;person;shooter;doom;vanilla; diff --git a/games/NXDoom/src/Heretic.metainfo.xml.in b/games/NXDoom/src/Heretic.metainfo.xml.in deleted file mode 100644 index 9f4bdc316f5..00000000000 --- a/games/NXDoom/src/Heretic.metainfo.xml.in +++ /dev/null @@ -1,47 +0,0 @@ - - - - @PACKAGE_RDNS@.Heretic - @PACKAGE_RDNS@.Heretic.desktop - @PACKAGE_SHORTNAME@ Heretic - @PACKAGE_SHORTDESC@ - CC0-1.0 - GPL-2.0+ - @PACKAGE_MAINTAINER@ - @PACKAGE_URL@ - @PACKAGE_BUGREPORT@ - -

- @PACKAGE_SHORTNAME@ Heretic is a conservative, - historically-accurate Heretic source port, which is compatible - with mods and levels that were made before the Heretic source - code was released. Unlike other source ports, the goal is to - preserve the original look, feel, limitations, and bugs of the - original DOS executable. -

-

- Full support for single- and multi-player games is provided. - Unlike the original executable, network play is implemented on - the IP network stack, allowing it to function on modern LANs and - the Internet. -

-
- - - https://www.chocolate-doom.org/wiki/images/9/93/GNOME_Heretic_E5M4.png - Level E5M4: Courtyard - - - https://www.chocolate-doom.org/wiki/images/1/14/GNOME_Heretic_Shareware_DEMO3.png - Shareware Level E1M9: The Graveyard - - - https://www.chocolate-doom.org/wiki/images/3/34/GNOME_Heretic_E4M1.png - Level E4M1: Catafalque - - - https://www.chocolate-doom.org/wiki/images/4/42/GNOME_Heretic_Shareware_DEMO1.png - Shareware Level E1M3: The Gatehouse - - -
diff --git a/games/NXDoom/src/Hexen.desktop.in b/games/NXDoom/src/Hexen.desktop.in deleted file mode 100644 index 4854efcae6a..00000000000 --- a/games/NXDoom/src/Hexen.desktop.in +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_SHORTNAME@ Hexen -Exec=@PROGRAM_PREFIX@hexen -Icon=@PROGRAM_PREFIX@hexen -Type=Application -Comment=@PACKAGE_SHORTDESC@ -Categories=Game;ActionGame; -Keywords=first;person;shooter;doom;vanilla; diff --git a/games/NXDoom/src/Hexen.metainfo.xml.in b/games/NXDoom/src/Hexen.metainfo.xml.in deleted file mode 100644 index 93370152297..00000000000 --- a/games/NXDoom/src/Hexen.metainfo.xml.in +++ /dev/null @@ -1,47 +0,0 @@ - - - - @PACKAGE_RDNS@.Hexen - @PACKAGE_RDNS@.Hexen.desktop - @PACKAGE_SHORTNAME@ Hexen - @PACKAGE_SHORTDESC@ - CC0-1.0 - GPL-2.0+ - @PACKAGE_MAINTAINER@ - @PACKAGE_URL@ - @PACKAGE_BUGREPORT@ - -

- @PACKAGE_SHORTNAME@ Hexen is a conservative, - historically-accurate Hexen source port, which is compatible - with mods and levels that were made before the Hexen source code - was released. Unlike other source ports, the goal is to - preserve the original look, feel, limitations, and bugs of the - original DOS executable. -

-

- Full support for single- and multi-player games is provided. - Unlike the original executable, network play is implemented on - the IP network stack, allowing it to function on modern LANs and - the Internet. -

-
- - - https://www.chocolate-doom.org/wiki/images/0/0f/GNOME_Hexen_Guardian_of_Fire.png - Level "Guardian of Fire" - - - https://www.chocolate-doom.org/wiki/images/5/5c/GNOME_Hexen_Effluvium.png - Level "Effluvium" - - - https://www.chocolate-doom.org/wiki/images/c/c1/GNOME_Hexen_Dragon_Chapel.png - Level "Dragon Chapel" - - - https://www.chocolate-doom.org/wiki/images/a/a7/GNOME_Hexen_Darkmere.png - Level "Darkmere" - - -
diff --git a/games/NXDoom/src/Makefile.am b/games/NXDoom/src/Makefile.am deleted file mode 100644 index 4fbade07b7a..00000000000 --- a/games/NXDoom/src/Makefile.am +++ /dev/null @@ -1,299 +0,0 @@ - -SUBDIRS = doom heretic hexen strife setup - -execgamesdir = ${bindir} - -execgames_PROGRAMS = @PROGRAM_PREFIX@doom \ - @PROGRAM_PREFIX@heretic \ - @PROGRAM_PREFIX@hexen \ - @PROGRAM_PREFIX@strife \ - @PROGRAM_PREFIX@server - -noinst_PROGRAMS = @PROGRAM_PREFIX@setup - -SETUP_BINARIES = @PROGRAM_PREFIX@doom-setup$(EXEEXT) \ - @PROGRAM_PREFIX@heretic-setup$(EXEEXT) \ - @PROGRAM_PREFIX@hexen-setup$(EXEEXT) \ - @PROGRAM_PREFIX@strife-setup$(EXEEXT) - -execgames_SCRIPTS = $(SETUP_BINARIES) - -AM_CFLAGS = -I$(top_srcdir)/textscreen \ - -I$(top_srcdir)/opl \ - -I$(top_srcdir)/pcsound \ - -I$(top_srcdir)/win32 \ - @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ - -# Common source files used by absolutely everything: - -COMMON_SOURCE_FILES=\ -i_main.c \ -i_system.c i_system.h \ -m_argv.c m_argv.h \ -m_misc.c m_misc.h - -# Dedicated server (chocolate-server): - -DEDSERV_FILES=\ -d_dedicated.c \ -d_iwad.c d_iwad.h \ -d_mode.c d_mode.h \ -deh_str.c deh_str.h \ -i_timer.c i_timer.h \ -m_config.c m_config.h \ -net_common.c net_common.h \ -net_dedicated.c net_dedicated.h \ -net_io.c net_io.h \ -net_packet.c net_packet.h \ -net_sdl.c net_sdl.h \ -net_query.c net_query.h \ -net_server.c net_server.h \ -net_structrw.c net_structrw.h \ -z_native.c z_zone.h - -@PROGRAM_PREFIX@server_SOURCES=$(COMMON_SOURCE_FILES) $(DEDSERV_FILES) -@PROGRAM_PREFIX@server_LDADD = @LDFLAGS@ @SDLNET_LIBS@ - -# Source files used by the game binaries (chocolate-doom, etc.) - -GAME_BASE_FILES=\ -aes_prng.c aes_prng.h \ -d_event.c d_event.h \ - doomkeys.h \ - doomtype.h \ -d_iwad.c d_iwad.h \ -d_loop.c d_loop.h \ -d_mode.c d_mode.h \ - d_ticcmd.h \ -deh_str.c deh_str.h \ -gusconf.c gusconf.h \ -i_cdmus.c i_cdmus.h \ -i_endoom.c i_endoom.h \ -i_flmusic.c \ -i_glob.c i_glob.h \ -i_input.c i_input.h \ -i_joystick.c i_joystick.h \ - i_swap.h \ -i_musicpack.c \ -i_oplmusic.c \ -i_pcsound.c \ -i_sdlmusic.c \ -i_sdlsound.c \ -i_sound.c i_sound.h \ -i_timer.c i_timer.h \ -i_video.c i_video.h \ -i_videohr.c i_videohr.h \ -i_winmusic.c \ -midifallback.c midifallback.h \ -midifile.c midifile.h \ -mus2mid.c mus2mid.h \ -m_bbox.c m_bbox.h \ -m_cheat.c m_cheat.h \ -m_config.c m_config.h \ -m_controls.c m_controls.h \ -m_fixed.c m_fixed.h \ -net_client.c net_client.h \ -net_common.c net_common.h \ -net_dedicated.c net_dedicated.h \ -net_defs.h \ -net_gui.c net_gui.h \ -net_io.c net_io.h \ -net_loop.c net_loop.h \ -net_packet.c net_packet.h \ -net_petname.c net_petname.h \ -net_query.c net_query.h \ -net_sdl.c net_sdl.h \ -net_server.c net_server.h \ -net_structrw.c net_structrw.h \ -p_rejectpad.c p_rejectpad.h \ -sha1.c sha1.h \ -memio.c memio.h \ -tables.c tables.h \ -v_diskicon.c v_diskicon.h \ -v_video.c v_video.h \ - v_patch.h \ -w_checksum.c w_checksum.h \ -w_main.c w_main.h \ -w_wad.c w_wad.h \ -w_file.c w_file.h \ -w_file_stdc.c \ -w_file_posix.c \ -w_file_win32.c \ -w_merge.c w_merge.h \ -$(top_builddir)/win32/win_opendir.c \ -$(top_builddir)/win32/win_opendir.h - - -MEMORY_NATIVE_SOURCE_FILES=\ -z_native.c z_zone.h - -MEMORY_ZONE_SOURCE_FILES=\ -z_zone.c z_zone.h - -if HAVE_ZPOOL -GAME_SOURCE_FILES=$(GAME_BASE_FILES) $(MEMORY_ZONE_SOURCE_FILES) -else -GAME_SOURCE_FILES=$(GAME_BASE_FILES) $(MEMORY_NATIVE_SOURCE_FILES) -endif - -DEHACKED_SOURCE_FILES = \ -deh_defs.h \ -deh_io.c deh_io.h \ -deh_main.c deh_main.h \ -deh_mapping.c deh_mapping.h \ -deh_text.c - -# Some games support dehacked patches, some don't: - -SOURCE_FILES = $(COMMON_SOURCE_FILES) $(GAME_SOURCE_FILES) -SOURCE_FILES_WITH_DEH = $(SOURCE_FILES) $(DEHACKED_SOURCE_FILES) - -EXTRA_LIBS = \ - $(top_builddir)/textscreen/libtextscreen.a \ - $(top_builddir)/pcsound/libpcsound.a \ - $(top_builddir)/opl/libopl.a \ - @LDFLAGS@ \ - @EM_LDFLAGS@ \ - @SDL_LIBS@ \ - @SDLMIXER_LIBS@ \ - @SDLNET_LIBS@ - -if HAVE_WINDRES -@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) doom-res.rc -else -@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) -endif - -@PROGRAM_PREFIX@doom_LDADD = doom/libdoom.a $(EXTRA_LIBS) - -if HAVE_WINDRES -@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH) heretic-res.rc -else -@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH) -endif - -@PROGRAM_PREFIX@heretic_LDADD = heretic/libheretic.a $(EXTRA_LIBS) - -if HAVE_WINDRES -@PROGRAM_PREFIX@hexen_SOURCES=$(SOURCE_FILES) hexen-res.rc -else -@PROGRAM_PREFIX@hexen_SOURCES=$(SOURCE_FILES) -endif - -@PROGRAM_PREFIX@hexen_LDADD = hexen/libhexen.a $(EXTRA_LIBS) - -if HAVE_WINDRES -@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES_WITH_DEH) strife-res.rc -else -@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES_WITH_DEH) -endif - -@PROGRAM_PREFIX@strife_LDADD = strife/libstrife.a $(EXTRA_LIBS) - -$(SETUP_BINARIES): @PROGRAM_PREFIX@setup$(EXEEXT) - cp @PROGRAM_PREFIX@setup$(EXEEXT) $@ - -# Make "make" aware of convenience libraries in subdirectories - -doom/libdoom.a: - $(MAKE) -C doom - -heretic/libheretic.a: - $(MAKE) -C heretic - -hexen/libhexen.a: - $(MAKE) -C hexen - -strife/libstrife.a: - $(MAKE) -C strife - -# Source files needed for chocolate-setup: - -SETUP_FILES= \ -deh_str.c deh_str.h \ -d_mode.c d_mode.h \ -d_iwad.c d_iwad.h \ -i_timer.c i_timer.h \ -m_config.c m_config.h \ -m_controls.c m_controls.h \ -net_io.c net_io.h \ -net_packet.c net_packet.h \ -net_petname.c net_petname.h \ -net_sdl.c net_sdl.h \ -net_query.c net_query.h \ -net_structrw.c net_structrw.h \ -z_native.c z_zone.h - -if HAVE_WINDRES -@PROGRAM_PREFIX@setup_SOURCES=$(SETUP_FILES) $(COMMON_SOURCE_FILES) setup-res.rc -else -@PROGRAM_PREFIX@setup_SOURCES=$(SETUP_FILES) $(COMMON_SOURCE_FILES) -endif -@PROGRAM_PREFIX@setup_LDADD = setup/libsetup.a \ - $(top_builddir)/textscreen/libtextscreen.a \ - @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@ @SDLNET_LIBS@ - -EXTRA_DIST = \ - CMakeLists.txt \ - Doom_Screensaver.desktop.in \ - manifest.xml - -metainfodir = $(prefix)/share/metainfo -metainfo_DATA = \ - @PACKAGE_RDNS@.Doom.metainfo.xml \ - @PACKAGE_RDNS@.Heretic.metainfo.xml \ - @PACKAGE_RDNS@.Hexen.metainfo.xml \ - @PACKAGE_RDNS@.Strife.metainfo.xml - -@PACKAGE_RDNS@.Doom.metainfo.xml : Doom.metainfo.xml - cp Doom.metainfo.xml $@ - -@PACKAGE_RDNS@.Heretic.metainfo.xml : Heretic.metainfo.xml - cp Heretic.metainfo.xml $@ - -@PACKAGE_RDNS@.Hexen.metainfo.xml : Hexen.metainfo.xml - cp Hexen.metainfo.xml $@ - -@PACKAGE_RDNS@.Strife.metainfo.xml : Strife.metainfo.xml - cp Strife.metainfo.xml $@ - -appdir = $(prefix)/share/applications -app_DATA = \ - @PACKAGE_RDNS@.Doom.desktop \ - @PACKAGE_RDNS@.Heretic.desktop \ - @PACKAGE_RDNS@.Hexen.desktop \ - @PACKAGE_RDNS@.Strife.desktop - -@PACKAGE_RDNS@.Doom.desktop : Doom.desktop - cp Doom.desktop $@ - -@PACKAGE_RDNS@.Heretic.desktop : Heretic.desktop - cp Heretic.desktop $@ - -@PACKAGE_RDNS@.Hexen.desktop : Hexen.desktop - cp Hexen.desktop $@ - -@PACKAGE_RDNS@.Strife.desktop : Strife.desktop - cp Strife.desktop $@ - -screensaverdir = $(prefix)/share/applications/screensavers -screensaver_DATA = @PACKAGE_RDNS@.Doom_Screensaver.desktop - -@PACKAGE_RDNS@.Doom_Screensaver.desktop: Doom_Screensaver.desktop - cp Doom_Screensaver.desktop $@ - -CLEANFILES = $(execgames_SCRIPTS) $(metainfo_DATA) $(app_DATA) $(screensaver_DATA) - -.rc.o: - $(WINDRES) $< -o $@ -%.o : %.rc - $(WINDRES) $< -o $@ - -midiread : midifile.c - $(CC) -DTEST $(CFLAGS) @LDFLAGS@ midifile.c -o $@ - -MUS2MID_SRC_FILES = mus2mid.c memio.c z_native.c i_system.c m_argv.c m_misc.c -mus2mid : $(MUS2MID_SRC_FILES) - $(CC) -DSTANDALONE -I$(top_builddir) $(CFLAGS) @LDFLAGS@ \ - $(MUS2MID_SRC_FILES) -o $@ - diff --git a/games/NXDoom/src/Strife.desktop.in b/games/NXDoom/src/Strife.desktop.in deleted file mode 100644 index 862d20749c3..00000000000 --- a/games/NXDoom/src/Strife.desktop.in +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_SHORTNAME@ Strife -Exec=@PROGRAM_PREFIX@strife -Icon=@PROGRAM_PREFIX@strife -Type=Application -Comment=@PACKAGE_SHORTDESC@ -Categories=Game;ActionGame; -Keywords=first;person;shooter;doom;vanilla; diff --git a/games/NXDoom/src/Strife.metainfo.xml.in b/games/NXDoom/src/Strife.metainfo.xml.in deleted file mode 100644 index 4fdd16a708c..00000000000 --- a/games/NXDoom/src/Strife.metainfo.xml.in +++ /dev/null @@ -1,48 +0,0 @@ - - - - @PACKAGE_RDNS@.Strife - @PACKAGE_RDNS@.Strife.desktop - @PACKAGE_SHORTNAME@ Strife - @PACKAGE_SHORTDESC@ - CC0-1.0 - GPL-2.0+ - @PACKAGE_MAINTAINER@ - @PACKAGE_URL@ - @PACKAGE_BUGREPORT@ - -

- @PACKAGE_SHORTNAME@ Strife is a conservative, - historically-accurate recreation of the Strife engine. It is - completely compatible with the original game and mods created - with the original engine in mind. Made with a great reverse - engineering effort, it has the goal of preserving the original - look, feel, limitations, and bugs of the original DOS - executable. -

-

- Full support for single- and multi-player games is provided. - Unlike the original executable, network play is implemented on - the IP network stack, allowing it to function on modern LANs and - the Internet. -

-
- - - https://www.chocolate-doom.org/wiki/images/b/b2/GNOME_Strife_Rowan.png - Talking to Rowan - - - https://www.chocolate-doom.org/wiki/images/1/1f/GNOME_Strife_Town.png - The Town - - - https://www.chocolate-doom.org/wiki/images/8/8a/GNOME_Strife_Opening.png - Opening Cinematic - - - https://www.chocolate-doom.org/wiki/images/c/c4/GNOME_Strife_Sewage.png - In the sewage - - -
diff --git a/games/NXDoom/src/aes_prng.c b/games/NXDoom/src/aes_prng.c index aad0a38a1be..04de172ef12 100644 --- a/games/NXDoom/src/aes_prng.c +++ b/games/NXDoom/src/aes_prng.c @@ -1,38 +1,32 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// This implements a cryptographically secure pseudorandom number -// generator for implementing secure demos. The approach taken is to -// use the AES (Rijndael) stream cipher in "counter" mode, encrypting -// an incrementing counter. The cipher key acts as the random seed. -// Cryptanalysis of AES used in this way has shown it to be an -// effective PRNG (see: Empirical Evidence concerning AES, Hellekalek -// & Wegenkittl, 2003). -// -// AES implementation is taken from the Linux kernel's AES -// implementation, found in crypto/aes_generic.c. It has been hacked -// up to work independently. -// - -#include - -#include "aes_prng.h" -#include "doomtype.h" -#include "i_swap.h" - -/* - * Cryptographic API. +/**************************************************************************** + * apps/games/NXDoom/src/aes_prng.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * + * This implements a cryptographically secure pseudorandom number + * generator for implementing secure demos. The approach taken is to + * use the AES (Rijndael) stream cipher in "counter" mode, encrypting + * an incrementing counter. The cipher key acts as the random seed. + * Cryptanalysis of AES used in this way has shown it to be an + * effective PRNG (see: Empirical Evidence concerning AES, Hellekalek + * & Wegenkittl, 2003). + * + * AES implementation is taken from the Linux kernel's AES + * implementation, found in crypto/aes_generic.c. It has been hacked + * up to work independently. * * AES Cipher Algorithm. * @@ -49,7 +43,6 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * --------------------------------------------------------------------------- * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. * All rights reserved. * @@ -68,889 +61,870 @@ * 3. the copyright holder's name is not used to endorse products * built using this software without specific written permission. * - * ALTERNATIVELY, provided that this notice is retained in full, this product - * may be distributed under the terms of the GNU General Public License (GPL), - * in which case the provisions of the GPL apply INSTEAD OF those given above. + * ALTERNATIVELY, provided that this notice is retained in full, this + * product may be distributed under the terms of the GNU General Public + * License (GPL), in which case the provisions of the GPL apply INSTEAD OF + * those given above. * * DISCLAIMER * * This software is provided 'as is' with no explicit or implied warranties * in respect of its properties, including, but not limited to, correctness * and/or fitness for purpose. - * --------------------------------------------------------------------------- - */ + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "aes_prng.h" +#include "doomtype.h" +#include "i_swap.h" -#define AES_MIN_KEY_SIZE 16 -#define AES_MAX_KEY_SIZE 32 -#define AES_KEYSIZE_128 16 -#define AES_KEYSIZE_192 24 -#define AES_KEYSIZE_256 32 -#define AES_BLOCK_SIZE 16 -#define AES_MAX_KEYLENGTH (15 * 16) -#define AES_MAX_KEYLENGTH_U32 (AES_MAX_KEYLENGTH / sizeof(uint32_t)) - -/* - * Please ensure that the first two fields are 16-byte aligned +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 +#define AES_KEYSIZE_128 16 +#define AES_KEYSIZE_192 24 +#define AES_KEYSIZE_256 32 +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEYLENGTH (15 * 16) +#define AES_MAX_KEYLENGTH_U32 (AES_MAX_KEYLENGTH / sizeof(uint32_t)) + +#define cpu_to_le32(x) htole32(x) +#define le32_to_cpu(x) le32toh(x) + +#define star_x(x) \ + (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y, x) \ + do \ + { \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= aes_ror32(u ^ t, 8) ^ aes_ror32(v ^ t, 16) ^ aes_ror32(t, 24); \ + } \ + while (0) + +#define ls_box(x) \ + crypto_fl_tab[0][get_byte(x, 0)] ^ crypto_fl_tab[1][get_byte(x, 1)] ^ \ + crypto_fl_tab[2][get_byte(x, 2)] ^ crypto_fl_tab[3][get_byte(x, 3)] + +#define loop4(i) \ + do \ + { \ + t = aes_ror32(t, 8); \ + t = ls_box(t) ^ rco_tab[i]; \ + t ^= ctx->key_enc[4 * i]; \ + ctx->key_enc[4 * i + 4] = t; \ + t ^= ctx->key_enc[4 * i + 1]; \ + ctx->key_enc[4 * i + 5] = t; \ + t ^= ctx->key_enc[4 * i + 2]; \ + ctx->key_enc[4 * i + 6] = t; \ + t ^= ctx->key_enc[4 * i + 3]; \ + ctx->key_enc[4 * i + 7] = t; \ + } \ + while (0) + +#define loop6(i) \ + do \ + { \ + t = aes_ror32(t, 8); \ + t = ls_box(t) ^ rco_tab[i]; \ + t ^= ctx->key_enc[6 * i]; \ + ctx->key_enc[6 * i + 6] = t; \ + t ^= ctx->key_enc[6 * i + 1]; \ + ctx->key_enc[6 * i + 7] = t; \ + t ^= ctx->key_enc[6 * i + 2]; \ + ctx->key_enc[6 * i + 8] = t; \ + t ^= ctx->key_enc[6 * i + 3]; \ + ctx->key_enc[6 * i + 9] = t; \ + t ^= ctx->key_enc[6 * i + 4]; \ + ctx->key_enc[6 * i + 10] = t; \ + t ^= ctx->key_enc[6 * i + 5]; \ + ctx->key_enc[6 * i + 11] = t; \ + } \ + while (0) + +#define loop8tophalf(i) \ + do \ + { \ + t = aes_ror32(t, 8); \ + t = ls_box(t) ^ rco_tab[i]; \ + t ^= ctx->key_enc[8 * i]; \ + ctx->key_enc[8 * i + 8] = t; \ + t ^= ctx->key_enc[8 * i + 1]; \ + ctx->key_enc[8 * i + 9] = t; \ + t ^= ctx->key_enc[8 * i + 2]; \ + ctx->key_enc[8 * i + 10] = t; \ + t ^= ctx->key_enc[8 * i + 3]; \ + ctx->key_enc[8 * i + 11] = t; \ + } \ + while (0) + +#define loop8(i) \ + do \ + { \ + loop8tophalf(i); \ + t = ctx->key_enc[8 * i + 4] ^ ls_box(t); \ + ctx->key_enc[8 * i + 12] = t; \ + t ^= ctx->key_enc[8 * i + 5]; \ + ctx->key_enc[8 * i + 13] = t; \ + t ^= ctx->key_enc[8 * i + 6]; \ + ctx->key_enc[8 * i + 14] = t; \ + t ^= ctx->key_enc[8 * i + 7]; \ + ctx->key_enc[8 * i + 15] = t; \ + } \ + while (0) + +/* encrypt a block of text */ + +#define f_rn(bo, bi, n, k) \ + do \ + { \ + bo[n] = crypto_ft_tab[0][get_byte(bi[n], 0)] ^ \ + crypto_ft_tab[1][get_byte(bi[(n + 1) & 3], 1)] ^ \ + crypto_ft_tab[2][get_byte(bi[(n + 2) & 3], 2)] ^ \ + crypto_ft_tab[3][get_byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ + } \ + while (0) + +#define f_nround(bo, bi, k) \ + do \ + { \ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4; \ + } \ + while (0) + +#define f_rl(bo, bi, n, k) \ + do \ + { \ + bo[n] = crypto_fl_tab[0][get_byte(bi[n], 0)] ^ \ + crypto_fl_tab[1][get_byte(bi[(n + 1) & 3], 1)] ^ \ + crypto_fl_tab[2][get_byte(bi[(n + 2) & 3], 2)] ^ \ + crypto_fl_tab[3][get_byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ + } \ + while (0) + +#define f_lround(bo, bi, k) \ + do \ + { \ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, k); \ + f_rl(bo, bi, 2, k); \ + f_rl(bo, bi, 3, k); \ + } \ + while (0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Please ensure that the first two fields are 16-byte aligned * relative to the start of the structure, i.e., don't move them! */ + typedef struct { - uint32_t key_enc[AES_MAX_KEYLENGTH_U32]; - uint32_t key_dec[AES_MAX_KEYLENGTH_U32]; - uint32_t key_length; + uint32_t key_enc[AES_MAX_KEYLENGTH_U32]; + uint32_t key_dec[AES_MAX_KEYLENGTH_U32]; + uint32_t key_length; } aes_context_t; -static inline uint8_t get_byte(const uint32_t x, const unsigned n) -{ - return x >> (n << 3); -} +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static boolean prng_enabled = false; +static aes_context_t prng_context; +static uint32_t prng_input_counter; +static uint32_t prng_values[4]; +static unsigned int prng_value_index = 0; -static const uint32_t rco_tab[10] = { 1, 2, 4, 8, 16, 32, 64, 128, 27, 54 }; +static const uint32_t rco_tab[10] = +{ + 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, +}; -static const uint32_t crypto_ft_tab[4][256] = { +static const uint32_t crypto_ft_tab[4][256] = +{ { - 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, - 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, - 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, - 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, - 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, - 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, - 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, - 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, - 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, - 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, - 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, - 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, - 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, - 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, - 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, - 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, - 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, - 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, - 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, - 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, - 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, - 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, - 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, - 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, - 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, - 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, - 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, - 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, - 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, - 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, - 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, - 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, - 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, - 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, - 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, - 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, - 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, - 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, - 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, - 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, - 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, - 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, - 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, - 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, - 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, - 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, - 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, - 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, - 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, - 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, - 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, - 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, - 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, - 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, - 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, - 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, - 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, - 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, - 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, - 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, - 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, - 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, - 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, - 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, - }, { - 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, - 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, - 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, - 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, - 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, - 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, - 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, - 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, - 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, - 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, - 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, - 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, - 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, - 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, - 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, - 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, - 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, - 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, - 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, - 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, - 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, - 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, - 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, - 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, - 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, - 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, - 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81, - 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, - 0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, - 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, - 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, - 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, - 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, - 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, - 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, - 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, - 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, - 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83, - 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, - 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, - 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, - 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, - 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, - 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, - 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, - 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, - 0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, - 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, - 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, - 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, - 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, - 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, - 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, - 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12, - 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, - 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, - 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, - 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, - 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, - 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, - 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, - 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, - 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, - 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a, - }, { - 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, - 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, - 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, - 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, - 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, - 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, - 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, - 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, - 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, - 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, - 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, - 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, - 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, - 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, - 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, - 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, - 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, - 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, - 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, - 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, - 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, - 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, - 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, - 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, - 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, - 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, - 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f, - 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, - 0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, - 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, - 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, - 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, - 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, - 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, - 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, - 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, - 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, - 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388, - 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, - 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, - 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, - 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, - 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, - 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, - 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, - 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, - 0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, - 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, - 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, - 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, - 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, - 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, - 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, - 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e, - 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, - 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, - 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, - 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, - 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, - 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, - 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, - 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, - 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f, - 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16, - }, { - 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, - 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, - 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, - 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, - 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, - 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, - 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, - 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, - 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, - 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, - 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, - 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, - 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, - 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, - 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, - 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, - 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, - 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, - 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, - 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, - 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, - 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, - 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, - 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, - 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, - 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, - 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f, - 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, - 0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f, - 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, - 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, - 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, - 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, - 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, - 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, - 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, - 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, - 0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888, - 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, - 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, - 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, - 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, - 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, - 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, - 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, - 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, - 0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, - 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, - 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, - 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, - 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, - 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, - 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, - 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e, - 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, - 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, - 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, - 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, - 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, - 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, - 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, - 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, - 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, - 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616, - } + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, + 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, + 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, + 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, + 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41, + 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, + 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, + 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, + 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795, + 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, + 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, + 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, + 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, + 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, + 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, + 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, + 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, + 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, + 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, + 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, + 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080, + 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, + 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, + 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, + 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, + 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, + 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, + 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, + 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, + 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd, + 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, + 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, + 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, + 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, + 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, + 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, + 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, + 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, + 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, + 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, + 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, + 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, + 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, + 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, + 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, + 0x3a16162c, + }, + { + 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, + 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, + 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, + 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, + 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec, + 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, + 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae, + 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, + 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293, + 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552, + 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, + 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, + 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, + 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, + 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, + 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, + 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, + 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46, + 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, + 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, + 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf, + 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, + 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0, + 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, + 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, + 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, + 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc, + 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, + 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0, + 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, + 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, + 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, + 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, + 0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e, + 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, + 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, + 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, + 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, + 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f, + 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, + 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd, + 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42, + 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, + 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, + 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, + 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, + 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592, + 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, + 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, + 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, + 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, + 0x16162c3a, + }, + { + 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, + 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, + 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, + 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, + 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad, + 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, + 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93, + 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, + 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371, + 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7, + 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, + 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, + 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, + 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, + 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6, + 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, + 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, + 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb, + 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, + 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, + 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45, + 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, + 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040, + 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, + 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, + 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, + 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44, + 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, + 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060, + 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, + 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, + 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, + 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, + 0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3, + 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, + 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, + 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, + 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, + 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25, + 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, + 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b, + 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e, + 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, + 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, + 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, + 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, + 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287, + 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, + 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, + 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, + 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, + 0x162c3a16, + }, + { + 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, + 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, + 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, + 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, + 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad, + 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, + 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, + 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, + 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171, + 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7, + 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505, + 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, + 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, + 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, + 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6, + 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, + 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, + 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb, + 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, + 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, + 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545, + 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, + 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040, + 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, + 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, + 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, + 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444, + 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, + 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060, + 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, + 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, + 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, + 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, + 0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3, + 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, + 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, + 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, + 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, + 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525, + 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, + 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b, + 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e, + 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, + 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, + 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, + 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, + 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787, + 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, + 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, + 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999, + 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, + 0x2c3a1616, + }, }; -static const uint32_t crypto_fl_tab[4][256] = { +static const uint32_t crypto_fl_tab[4][256] = +{ { - 0x00000063, 0x0000007c, 0x00000077, 0x0000007b, - 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5, - 0x00000030, 0x00000001, 0x00000067, 0x0000002b, - 0x000000fe, 0x000000d7, 0x000000ab, 0x00000076, - 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d, - 0x000000fa, 0x00000059, 0x00000047, 0x000000f0, - 0x000000ad, 0x000000d4, 0x000000a2, 0x000000af, - 0x0000009c, 0x000000a4, 0x00000072, 0x000000c0, - 0x000000b7, 0x000000fd, 0x00000093, 0x00000026, - 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc, - 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1, - 0x00000071, 0x000000d8, 0x00000031, 0x00000015, - 0x00000004, 0x000000c7, 0x00000023, 0x000000c3, - 0x00000018, 0x00000096, 0x00000005, 0x0000009a, - 0x00000007, 0x00000012, 0x00000080, 0x000000e2, - 0x000000eb, 0x00000027, 0x000000b2, 0x00000075, - 0x00000009, 0x00000083, 0x0000002c, 0x0000001a, - 0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0, - 0x00000052, 0x0000003b, 0x000000d6, 0x000000b3, - 0x00000029, 0x000000e3, 0x0000002f, 0x00000084, - 0x00000053, 0x000000d1, 0x00000000, 0x000000ed, - 0x00000020, 0x000000fc, 0x000000b1, 0x0000005b, - 0x0000006a, 0x000000cb, 0x000000be, 0x00000039, - 0x0000004a, 0x0000004c, 0x00000058, 0x000000cf, - 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb, - 0x00000043, 0x0000004d, 0x00000033, 0x00000085, - 0x00000045, 0x000000f9, 0x00000002, 0x0000007f, - 0x00000050, 0x0000003c, 0x0000009f, 0x000000a8, - 0x00000051, 0x000000a3, 0x00000040, 0x0000008f, - 0x00000092, 0x0000009d, 0x00000038, 0x000000f5, - 0x000000bc, 0x000000b6, 0x000000da, 0x00000021, - 0x00000010, 0x000000ff, 0x000000f3, 0x000000d2, - 0x000000cd, 0x0000000c, 0x00000013, 0x000000ec, - 0x0000005f, 0x00000097, 0x00000044, 0x00000017, - 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d, - 0x00000064, 0x0000005d, 0x00000019, 0x00000073, - 0x00000060, 0x00000081, 0x0000004f, 0x000000dc, - 0x00000022, 0x0000002a, 0x00000090, 0x00000088, - 0x00000046, 0x000000ee, 0x000000b8, 0x00000014, - 0x000000de, 0x0000005e, 0x0000000b, 0x000000db, - 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a, - 0x00000049, 0x00000006, 0x00000024, 0x0000005c, - 0x000000c2, 0x000000d3, 0x000000ac, 0x00000062, - 0x00000091, 0x00000095, 0x000000e4, 0x00000079, - 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d, - 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9, - 0x0000006c, 0x00000056, 0x000000f4, 0x000000ea, - 0x00000065, 0x0000007a, 0x000000ae, 0x00000008, - 0x000000ba, 0x00000078, 0x00000025, 0x0000002e, - 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6, - 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f, - 0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a, - 0x00000070, 0x0000003e, 0x000000b5, 0x00000066, - 0x00000048, 0x00000003, 0x000000f6, 0x0000000e, - 0x00000061, 0x00000035, 0x00000057, 0x000000b9, - 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e, - 0x000000e1, 0x000000f8, 0x00000098, 0x00000011, - 0x00000069, 0x000000d9, 0x0000008e, 0x00000094, - 0x0000009b, 0x0000001e, 0x00000087, 0x000000e9, - 0x000000ce, 0x00000055, 0x00000028, 0x000000df, - 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d, - 0x000000bf, 0x000000e6, 0x00000042, 0x00000068, - 0x00000041, 0x00000099, 0x0000002d, 0x0000000f, - 0x000000b0, 0x00000054, 0x000000bb, 0x00000016, - }, { - 0x00006300, 0x00007c00, 0x00007700, 0x00007b00, - 0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500, - 0x00003000, 0x00000100, 0x00006700, 0x00002b00, - 0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600, - 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00, - 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000, - 0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00, - 0x00009c00, 0x0000a400, 0x00007200, 0x0000c000, - 0x0000b700, 0x0000fd00, 0x00009300, 0x00002600, - 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00, - 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100, - 0x00007100, 0x0000d800, 0x00003100, 0x00001500, - 0x00000400, 0x0000c700, 0x00002300, 0x0000c300, - 0x00001800, 0x00009600, 0x00000500, 0x00009a00, - 0x00000700, 0x00001200, 0x00008000, 0x0000e200, - 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500, - 0x00000900, 0x00008300, 0x00002c00, 0x00001a00, - 0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000, - 0x00005200, 0x00003b00, 0x0000d600, 0x0000b300, - 0x00002900, 0x0000e300, 0x00002f00, 0x00008400, - 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00, - 0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00, - 0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900, - 0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00, - 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00, - 0x00004300, 0x00004d00, 0x00003300, 0x00008500, - 0x00004500, 0x0000f900, 0x00000200, 0x00007f00, - 0x00005000, 0x00003c00, 0x00009f00, 0x0000a800, - 0x00005100, 0x0000a300, 0x00004000, 0x00008f00, - 0x00009200, 0x00009d00, 0x00003800, 0x0000f500, - 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100, - 0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200, - 0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00, - 0x00005f00, 0x00009700, 0x00004400, 0x00001700, - 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00, - 0x00006400, 0x00005d00, 0x00001900, 0x00007300, - 0x00006000, 0x00008100, 0x00004f00, 0x0000dc00, - 0x00002200, 0x00002a00, 0x00009000, 0x00008800, - 0x00004600, 0x0000ee00, 0x0000b800, 0x00001400, - 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00, - 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00, - 0x00004900, 0x00000600, 0x00002400, 0x00005c00, - 0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200, - 0x00009100, 0x00009500, 0x0000e400, 0x00007900, - 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00, - 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900, - 0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00, - 0x00006500, 0x00007a00, 0x0000ae00, 0x00000800, - 0x0000ba00, 0x00007800, 0x00002500, 0x00002e00, - 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600, - 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00, - 0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00, - 0x00007000, 0x00003e00, 0x0000b500, 0x00006600, - 0x00004800, 0x00000300, 0x0000f600, 0x00000e00, - 0x00006100, 0x00003500, 0x00005700, 0x0000b900, - 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00, - 0x0000e100, 0x0000f800, 0x00009800, 0x00001100, - 0x00006900, 0x0000d900, 0x00008e00, 0x00009400, - 0x00009b00, 0x00001e00, 0x00008700, 0x0000e900, - 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00, - 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00, - 0x0000bf00, 0x0000e600, 0x00004200, 0x00006800, - 0x00004100, 0x00009900, 0x00002d00, 0x00000f00, - 0x0000b000, 0x00005400, 0x0000bb00, 0x00001600, - }, { - 0x00630000, 0x007c0000, 0x00770000, 0x007b0000, - 0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000, - 0x00300000, 0x00010000, 0x00670000, 0x002b0000, - 0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000, - 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000, - 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000, - 0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000, - 0x009c0000, 0x00a40000, 0x00720000, 0x00c00000, - 0x00b70000, 0x00fd0000, 0x00930000, 0x00260000, - 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000, - 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000, - 0x00710000, 0x00d80000, 0x00310000, 0x00150000, - 0x00040000, 0x00c70000, 0x00230000, 0x00c30000, - 0x00180000, 0x00960000, 0x00050000, 0x009a0000, - 0x00070000, 0x00120000, 0x00800000, 0x00e20000, - 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000, - 0x00090000, 0x00830000, 0x002c0000, 0x001a0000, - 0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000, - 0x00520000, 0x003b0000, 0x00d60000, 0x00b30000, - 0x00290000, 0x00e30000, 0x002f0000, 0x00840000, - 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000, - 0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000, - 0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000, - 0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000, - 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000, - 0x00430000, 0x004d0000, 0x00330000, 0x00850000, - 0x00450000, 0x00f90000, 0x00020000, 0x007f0000, - 0x00500000, 0x003c0000, 0x009f0000, 0x00a80000, - 0x00510000, 0x00a30000, 0x00400000, 0x008f0000, - 0x00920000, 0x009d0000, 0x00380000, 0x00f50000, - 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000, - 0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000, - 0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000, - 0x005f0000, 0x00970000, 0x00440000, 0x00170000, - 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000, - 0x00640000, 0x005d0000, 0x00190000, 0x00730000, - 0x00600000, 0x00810000, 0x004f0000, 0x00dc0000, - 0x00220000, 0x002a0000, 0x00900000, 0x00880000, - 0x00460000, 0x00ee0000, 0x00b80000, 0x00140000, - 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000, - 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000, - 0x00490000, 0x00060000, 0x00240000, 0x005c0000, - 0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000, - 0x00910000, 0x00950000, 0x00e40000, 0x00790000, - 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000, - 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000, - 0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000, - 0x00650000, 0x007a0000, 0x00ae0000, 0x00080000, - 0x00ba0000, 0x00780000, 0x00250000, 0x002e0000, - 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000, - 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000, - 0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000, - 0x00700000, 0x003e0000, 0x00b50000, 0x00660000, - 0x00480000, 0x00030000, 0x00f60000, 0x000e0000, - 0x00610000, 0x00350000, 0x00570000, 0x00b90000, - 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000, - 0x00e10000, 0x00f80000, 0x00980000, 0x00110000, - 0x00690000, 0x00d90000, 0x008e0000, 0x00940000, - 0x009b0000, 0x001e0000, 0x00870000, 0x00e90000, - 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000, - 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000, - 0x00bf0000, 0x00e60000, 0x00420000, 0x00680000, - 0x00410000, 0x00990000, 0x002d0000, 0x000f0000, - 0x00b00000, 0x00540000, 0x00bb0000, 0x00160000, - }, { - 0x63000000, 0x7c000000, 0x77000000, 0x7b000000, - 0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000, - 0x30000000, 0x01000000, 0x67000000, 0x2b000000, - 0xfe000000, 0xd7000000, 0xab000000, 0x76000000, - 0xca000000, 0x82000000, 0xc9000000, 0x7d000000, - 0xfa000000, 0x59000000, 0x47000000, 0xf0000000, - 0xad000000, 0xd4000000, 0xa2000000, 0xaf000000, - 0x9c000000, 0xa4000000, 0x72000000, 0xc0000000, - 0xb7000000, 0xfd000000, 0x93000000, 0x26000000, - 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000, - 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000, - 0x71000000, 0xd8000000, 0x31000000, 0x15000000, - 0x04000000, 0xc7000000, 0x23000000, 0xc3000000, - 0x18000000, 0x96000000, 0x05000000, 0x9a000000, - 0x07000000, 0x12000000, 0x80000000, 0xe2000000, - 0xeb000000, 0x27000000, 0xb2000000, 0x75000000, - 0x09000000, 0x83000000, 0x2c000000, 0x1a000000, - 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000, - 0x52000000, 0x3b000000, 0xd6000000, 0xb3000000, - 0x29000000, 0xe3000000, 0x2f000000, 0x84000000, - 0x53000000, 0xd1000000, 0x00000000, 0xed000000, - 0x20000000, 0xfc000000, 0xb1000000, 0x5b000000, - 0x6a000000, 0xcb000000, 0xbe000000, 0x39000000, - 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000, - 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000, - 0x43000000, 0x4d000000, 0x33000000, 0x85000000, - 0x45000000, 0xf9000000, 0x02000000, 0x7f000000, - 0x50000000, 0x3c000000, 0x9f000000, 0xa8000000, - 0x51000000, 0xa3000000, 0x40000000, 0x8f000000, - 0x92000000, 0x9d000000, 0x38000000, 0xf5000000, - 0xbc000000, 0xb6000000, 0xda000000, 0x21000000, - 0x10000000, 0xff000000, 0xf3000000, 0xd2000000, - 0xcd000000, 0x0c000000, 0x13000000, 0xec000000, - 0x5f000000, 0x97000000, 0x44000000, 0x17000000, - 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000, - 0x64000000, 0x5d000000, 0x19000000, 0x73000000, - 0x60000000, 0x81000000, 0x4f000000, 0xdc000000, - 0x22000000, 0x2a000000, 0x90000000, 0x88000000, - 0x46000000, 0xee000000, 0xb8000000, 0x14000000, - 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000, - 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000, - 0x49000000, 0x06000000, 0x24000000, 0x5c000000, - 0xc2000000, 0xd3000000, 0xac000000, 0x62000000, - 0x91000000, 0x95000000, 0xe4000000, 0x79000000, - 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000, - 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000, - 0x6c000000, 0x56000000, 0xf4000000, 0xea000000, - 0x65000000, 0x7a000000, 0xae000000, 0x08000000, - 0xba000000, 0x78000000, 0x25000000, 0x2e000000, - 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000, - 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000, - 0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000, - 0x70000000, 0x3e000000, 0xb5000000, 0x66000000, - 0x48000000, 0x03000000, 0xf6000000, 0x0e000000, - 0x61000000, 0x35000000, 0x57000000, 0xb9000000, - 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000, - 0xe1000000, 0xf8000000, 0x98000000, 0x11000000, - 0x69000000, 0xd9000000, 0x8e000000, 0x94000000, - 0x9b000000, 0x1e000000, 0x87000000, 0xe9000000, - 0xce000000, 0x55000000, 0x28000000, 0xdf000000, - 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000, - 0xbf000000, 0xe6000000, 0x42000000, 0x68000000, - 0x41000000, 0x99000000, 0x2d000000, 0x0f000000, - 0xb0000000, 0x54000000, 0xbb000000, 0x16000000, - } + 0x00000063, 0x0000007c, 0x00000077, 0x0000007b, 0x000000f2, + 0x0000006b, 0x0000006f, 0x000000c5, 0x00000030, 0x00000001, + 0x00000067, 0x0000002b, 0x000000fe, 0x000000d7, 0x000000ab, + 0x00000076, 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d, + 0x000000fa, 0x00000059, 0x00000047, 0x000000f0, 0x000000ad, + 0x000000d4, 0x000000a2, 0x000000af, 0x0000009c, 0x000000a4, + 0x00000072, 0x000000c0, 0x000000b7, 0x000000fd, 0x00000093, + 0x00000026, 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc, + 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1, 0x00000071, + 0x000000d8, 0x00000031, 0x00000015, 0x00000004, 0x000000c7, + 0x00000023, 0x000000c3, 0x00000018, 0x00000096, 0x00000005, + 0x0000009a, 0x00000007, 0x00000012, 0x00000080, 0x000000e2, + 0x000000eb, 0x00000027, 0x000000b2, 0x00000075, 0x00000009, + 0x00000083, 0x0000002c, 0x0000001a, 0x0000001b, 0x0000006e, + 0x0000005a, 0x000000a0, 0x00000052, 0x0000003b, 0x000000d6, + 0x000000b3, 0x00000029, 0x000000e3, 0x0000002f, 0x00000084, + 0x00000053, 0x000000d1, 0x00000000, 0x000000ed, 0x00000020, + 0x000000fc, 0x000000b1, 0x0000005b, 0x0000006a, 0x000000cb, + 0x000000be, 0x00000039, 0x0000004a, 0x0000004c, 0x00000058, + 0x000000cf, 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb, + 0x00000043, 0x0000004d, 0x00000033, 0x00000085, 0x00000045, + 0x000000f9, 0x00000002, 0x0000007f, 0x00000050, 0x0000003c, + 0x0000009f, 0x000000a8, 0x00000051, 0x000000a3, 0x00000040, + 0x0000008f, 0x00000092, 0x0000009d, 0x00000038, 0x000000f5, + 0x000000bc, 0x000000b6, 0x000000da, 0x00000021, 0x00000010, + 0x000000ff, 0x000000f3, 0x000000d2, 0x000000cd, 0x0000000c, + 0x00000013, 0x000000ec, 0x0000005f, 0x00000097, 0x00000044, + 0x00000017, 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d, + 0x00000064, 0x0000005d, 0x00000019, 0x00000073, 0x00000060, + 0x00000081, 0x0000004f, 0x000000dc, 0x00000022, 0x0000002a, + 0x00000090, 0x00000088, 0x00000046, 0x000000ee, 0x000000b8, + 0x00000014, 0x000000de, 0x0000005e, 0x0000000b, 0x000000db, + 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a, 0x00000049, + 0x00000006, 0x00000024, 0x0000005c, 0x000000c2, 0x000000d3, + 0x000000ac, 0x00000062, 0x00000091, 0x00000095, 0x000000e4, + 0x00000079, 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d, + 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9, 0x0000006c, + 0x00000056, 0x000000f4, 0x000000ea, 0x00000065, 0x0000007a, + 0x000000ae, 0x00000008, 0x000000ba, 0x00000078, 0x00000025, + 0x0000002e, 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6, + 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f, 0x0000004b, + 0x000000bd, 0x0000008b, 0x0000008a, 0x00000070, 0x0000003e, + 0x000000b5, 0x00000066, 0x00000048, 0x00000003, 0x000000f6, + 0x0000000e, 0x00000061, 0x00000035, 0x00000057, 0x000000b9, + 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e, 0x000000e1, + 0x000000f8, 0x00000098, 0x00000011, 0x00000069, 0x000000d9, + 0x0000008e, 0x00000094, 0x0000009b, 0x0000001e, 0x00000087, + 0x000000e9, 0x000000ce, 0x00000055, 0x00000028, 0x000000df, + 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d, 0x000000bf, + 0x000000e6, 0x00000042, 0x00000068, 0x00000041, 0x00000099, + 0x0000002d, 0x0000000f, 0x000000b0, 0x00000054, 0x000000bb, + 0x00000016, + }, + { + 0x00006300, 0x00007c00, 0x00007700, 0x00007b00, 0x0000f200, + 0x00006b00, 0x00006f00, 0x0000c500, 0x00003000, 0x00000100, + 0x00006700, 0x00002b00, 0x0000fe00, 0x0000d700, 0x0000ab00, + 0x00007600, 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00, + 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000, 0x0000ad00, + 0x0000d400, 0x0000a200, 0x0000af00, 0x00009c00, 0x0000a400, + 0x00007200, 0x0000c000, 0x0000b700, 0x0000fd00, 0x00009300, + 0x00002600, 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00, + 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100, 0x00007100, + 0x0000d800, 0x00003100, 0x00001500, 0x00000400, 0x0000c700, + 0x00002300, 0x0000c300, 0x00001800, 0x00009600, 0x00000500, + 0x00009a00, 0x00000700, 0x00001200, 0x00008000, 0x0000e200, + 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500, 0x00000900, + 0x00008300, 0x00002c00, 0x00001a00, 0x00001b00, 0x00006e00, + 0x00005a00, 0x0000a000, 0x00005200, 0x00003b00, 0x0000d600, + 0x0000b300, 0x00002900, 0x0000e300, 0x00002f00, 0x00008400, + 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00, 0x00002000, + 0x0000fc00, 0x0000b100, 0x00005b00, 0x00006a00, 0x0000cb00, + 0x0000be00, 0x00003900, 0x00004a00, 0x00004c00, 0x00005800, + 0x0000cf00, 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00, + 0x00004300, 0x00004d00, 0x00003300, 0x00008500, 0x00004500, + 0x0000f900, 0x00000200, 0x00007f00, 0x00005000, 0x00003c00, + 0x00009f00, 0x0000a800, 0x00005100, 0x0000a300, 0x00004000, + 0x00008f00, 0x00009200, 0x00009d00, 0x00003800, 0x0000f500, + 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100, 0x00001000, + 0x0000ff00, 0x0000f300, 0x0000d200, 0x0000cd00, 0x00000c00, + 0x00001300, 0x0000ec00, 0x00005f00, 0x00009700, 0x00004400, + 0x00001700, 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00, + 0x00006400, 0x00005d00, 0x00001900, 0x00007300, 0x00006000, + 0x00008100, 0x00004f00, 0x0000dc00, 0x00002200, 0x00002a00, + 0x00009000, 0x00008800, 0x00004600, 0x0000ee00, 0x0000b800, + 0x00001400, 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00, + 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00, 0x00004900, + 0x00000600, 0x00002400, 0x00005c00, 0x0000c200, 0x0000d300, + 0x0000ac00, 0x00006200, 0x00009100, 0x00009500, 0x0000e400, + 0x00007900, 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00, + 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900, 0x00006c00, + 0x00005600, 0x0000f400, 0x0000ea00, 0x00006500, 0x00007a00, + 0x0000ae00, 0x00000800, 0x0000ba00, 0x00007800, 0x00002500, + 0x00002e00, 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600, + 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00, 0x00004b00, + 0x0000bd00, 0x00008b00, 0x00008a00, 0x00007000, 0x00003e00, + 0x0000b500, 0x00006600, 0x00004800, 0x00000300, 0x0000f600, + 0x00000e00, 0x00006100, 0x00003500, 0x00005700, 0x0000b900, + 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00, 0x0000e100, + 0x0000f800, 0x00009800, 0x00001100, 0x00006900, 0x0000d900, + 0x00008e00, 0x00009400, 0x00009b00, 0x00001e00, 0x00008700, + 0x0000e900, 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00, + 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00, 0x0000bf00, + 0x0000e600, 0x00004200, 0x00006800, 0x00004100, 0x00009900, + 0x00002d00, 0x00000f00, 0x0000b000, 0x00005400, 0x0000bb00, + 0x00001600, + }, + { + 0x00630000, 0x007c0000, 0x00770000, 0x007b0000, 0x00f20000, + 0x006b0000, 0x006f0000, 0x00c50000, 0x00300000, 0x00010000, + 0x00670000, 0x002b0000, 0x00fe0000, 0x00d70000, 0x00ab0000, + 0x00760000, 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000, + 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000, 0x00ad0000, + 0x00d40000, 0x00a20000, 0x00af0000, 0x009c0000, 0x00a40000, + 0x00720000, 0x00c00000, 0x00b70000, 0x00fd0000, 0x00930000, + 0x00260000, 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000, + 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000, 0x00710000, + 0x00d80000, 0x00310000, 0x00150000, 0x00040000, 0x00c70000, + 0x00230000, 0x00c30000, 0x00180000, 0x00960000, 0x00050000, + 0x009a0000, 0x00070000, 0x00120000, 0x00800000, 0x00e20000, + 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000, 0x00090000, + 0x00830000, 0x002c0000, 0x001a0000, 0x001b0000, 0x006e0000, + 0x005a0000, 0x00a00000, 0x00520000, 0x003b0000, 0x00d60000, + 0x00b30000, 0x00290000, 0x00e30000, 0x002f0000, 0x00840000, + 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000, 0x00200000, + 0x00fc0000, 0x00b10000, 0x005b0000, 0x006a0000, 0x00cb0000, + 0x00be0000, 0x00390000, 0x004a0000, 0x004c0000, 0x00580000, + 0x00cf0000, 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000, + 0x00430000, 0x004d0000, 0x00330000, 0x00850000, 0x00450000, + 0x00f90000, 0x00020000, 0x007f0000, 0x00500000, 0x003c0000, + 0x009f0000, 0x00a80000, 0x00510000, 0x00a30000, 0x00400000, + 0x008f0000, 0x00920000, 0x009d0000, 0x00380000, 0x00f50000, + 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000, 0x00100000, + 0x00ff0000, 0x00f30000, 0x00d20000, 0x00cd0000, 0x000c0000, + 0x00130000, 0x00ec0000, 0x005f0000, 0x00970000, 0x00440000, + 0x00170000, 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000, + 0x00640000, 0x005d0000, 0x00190000, 0x00730000, 0x00600000, + 0x00810000, 0x004f0000, 0x00dc0000, 0x00220000, 0x002a0000, + 0x00900000, 0x00880000, 0x00460000, 0x00ee0000, 0x00b80000, + 0x00140000, 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000, + 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000, 0x00490000, + 0x00060000, 0x00240000, 0x005c0000, 0x00c20000, 0x00d30000, + 0x00ac0000, 0x00620000, 0x00910000, 0x00950000, 0x00e40000, + 0x00790000, 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000, + 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000, 0x006c0000, + 0x00560000, 0x00f40000, 0x00ea0000, 0x00650000, 0x007a0000, + 0x00ae0000, 0x00080000, 0x00ba0000, 0x00780000, 0x00250000, + 0x002e0000, 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000, + 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000, 0x004b0000, + 0x00bd0000, 0x008b0000, 0x008a0000, 0x00700000, 0x003e0000, + 0x00b50000, 0x00660000, 0x00480000, 0x00030000, 0x00f60000, + 0x000e0000, 0x00610000, 0x00350000, 0x00570000, 0x00b90000, + 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000, 0x00e10000, + 0x00f80000, 0x00980000, 0x00110000, 0x00690000, 0x00d90000, + 0x008e0000, 0x00940000, 0x009b0000, 0x001e0000, 0x00870000, + 0x00e90000, 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000, + 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000, 0x00bf0000, + 0x00e60000, 0x00420000, 0x00680000, 0x00410000, 0x00990000, + 0x002d0000, 0x000f0000, 0x00b00000, 0x00540000, 0x00bb0000, + 0x00160000, + }, + { + 0x63000000, 0x7c000000, 0x77000000, 0x7b000000, 0xf2000000, + 0x6b000000, 0x6f000000, 0xc5000000, 0x30000000, 0x01000000, + 0x67000000, 0x2b000000, 0xfe000000, 0xd7000000, 0xab000000, + 0x76000000, 0xca000000, 0x82000000, 0xc9000000, 0x7d000000, + 0xfa000000, 0x59000000, 0x47000000, 0xf0000000, 0xad000000, + 0xd4000000, 0xa2000000, 0xaf000000, 0x9c000000, 0xa4000000, + 0x72000000, 0xc0000000, 0xb7000000, 0xfd000000, 0x93000000, + 0x26000000, 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000, + 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000, 0x71000000, + 0xd8000000, 0x31000000, 0x15000000, 0x04000000, 0xc7000000, + 0x23000000, 0xc3000000, 0x18000000, 0x96000000, 0x05000000, + 0x9a000000, 0x07000000, 0x12000000, 0x80000000, 0xe2000000, + 0xeb000000, 0x27000000, 0xb2000000, 0x75000000, 0x09000000, + 0x83000000, 0x2c000000, 0x1a000000, 0x1b000000, 0x6e000000, + 0x5a000000, 0xa0000000, 0x52000000, 0x3b000000, 0xd6000000, + 0xb3000000, 0x29000000, 0xe3000000, 0x2f000000, 0x84000000, + 0x53000000, 0xd1000000, 0x00000000, 0xed000000, 0x20000000, + 0xfc000000, 0xb1000000, 0x5b000000, 0x6a000000, 0xcb000000, + 0xbe000000, 0x39000000, 0x4a000000, 0x4c000000, 0x58000000, + 0xcf000000, 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000, + 0x43000000, 0x4d000000, 0x33000000, 0x85000000, 0x45000000, + 0xf9000000, 0x02000000, 0x7f000000, 0x50000000, 0x3c000000, + 0x9f000000, 0xa8000000, 0x51000000, 0xa3000000, 0x40000000, + 0x8f000000, 0x92000000, 0x9d000000, 0x38000000, 0xf5000000, + 0xbc000000, 0xb6000000, 0xda000000, 0x21000000, 0x10000000, + 0xff000000, 0xf3000000, 0xd2000000, 0xcd000000, 0x0c000000, + 0x13000000, 0xec000000, 0x5f000000, 0x97000000, 0x44000000, + 0x17000000, 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000, + 0x64000000, 0x5d000000, 0x19000000, 0x73000000, 0x60000000, + 0x81000000, 0x4f000000, 0xdc000000, 0x22000000, 0x2a000000, + 0x90000000, 0x88000000, 0x46000000, 0xee000000, 0xb8000000, + 0x14000000, 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000, + 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000, 0x49000000, + 0x06000000, 0x24000000, 0x5c000000, 0xc2000000, 0xd3000000, + 0xac000000, 0x62000000, 0x91000000, 0x95000000, 0xe4000000, + 0x79000000, 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000, + 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000, 0x6c000000, + 0x56000000, 0xf4000000, 0xea000000, 0x65000000, 0x7a000000, + 0xae000000, 0x08000000, 0xba000000, 0x78000000, 0x25000000, + 0x2e000000, 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000, + 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000, 0x4b000000, + 0xbd000000, 0x8b000000, 0x8a000000, 0x70000000, 0x3e000000, + 0xb5000000, 0x66000000, 0x48000000, 0x03000000, 0xf6000000, + 0x0e000000, 0x61000000, 0x35000000, 0x57000000, 0xb9000000, + 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000, 0xe1000000, + 0xf8000000, 0x98000000, 0x11000000, 0x69000000, 0xd9000000, + 0x8e000000, 0x94000000, 0x9b000000, 0x1e000000, 0x87000000, + 0xe9000000, 0xce000000, 0x55000000, 0x28000000, 0xdf000000, + 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000, 0xbf000000, + 0xe6000000, 0x42000000, 0x68000000, 0x41000000, 0x99000000, + 0x2d000000, 0x0f000000, 0xb0000000, 0x54000000, 0xbb000000, + 0x16000000, + }, }; +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline uint8_t get_byte(const uint32_t x, const unsigned n) +{ + return x >> (n << 3); +} + /* initialise the key schedule from the user supplied key */ static uint32_t aes_ror32(uint32_t word, unsigned int shift) { - return (word >> shift) | (word << (32 - shift)); + return (word >> shift) | (word << (32 - shift)); } -#define cpu_to_le32(x) SDL_SwapLE32(x) -#define le32_to_cpu(x) SDL_SwapLE32(x) - -#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) - -#define imix_col(y, x) do { \ - u = star_x(x); \ - v = star_x(u); \ - w = star_x(v); \ - t = w ^ (x); \ - (y) = u ^ v ^ w; \ - (y) ^= aes_ror32(u ^ t, 8) ^ \ - aes_ror32(v ^ t, 16) ^ \ - aes_ror32(t, 24); \ -} while (0) - -#define ls_box(x) \ - crypto_fl_tab[0][get_byte(x, 0)] ^ \ - crypto_fl_tab[1][get_byte(x, 1)] ^ \ - crypto_fl_tab[2][get_byte(x, 2)] ^ \ - crypto_fl_tab[3][get_byte(x, 3)] - -#define loop4(i) do { \ - t = aes_ror32(t, 8); \ - t = ls_box(t) ^ rco_tab[i]; \ - t ^= ctx->key_enc[4 * i]; \ - ctx->key_enc[4 * i + 4] = t; \ - t ^= ctx->key_enc[4 * i + 1]; \ - ctx->key_enc[4 * i + 5] = t; \ - t ^= ctx->key_enc[4 * i + 2]; \ - ctx->key_enc[4 * i + 6] = t; \ - t ^= ctx->key_enc[4 * i + 3]; \ - ctx->key_enc[4 * i + 7] = t; \ -} while (0) - -#define loop6(i) do { \ - t = aes_ror32(t, 8); \ - t = ls_box(t) ^ rco_tab[i]; \ - t ^= ctx->key_enc[6 * i]; \ - ctx->key_enc[6 * i + 6] = t; \ - t ^= ctx->key_enc[6 * i + 1]; \ - ctx->key_enc[6 * i + 7] = t; \ - t ^= ctx->key_enc[6 * i + 2]; \ - ctx->key_enc[6 * i + 8] = t; \ - t ^= ctx->key_enc[6 * i + 3]; \ - ctx->key_enc[6 * i + 9] = t; \ - t ^= ctx->key_enc[6 * i + 4]; \ - ctx->key_enc[6 * i + 10] = t; \ - t ^= ctx->key_enc[6 * i + 5]; \ - ctx->key_enc[6 * i + 11] = t; \ -} while (0) - -#define loop8tophalf(i) do { \ - t = aes_ror32(t, 8); \ - t = ls_box(t) ^ rco_tab[i]; \ - t ^= ctx->key_enc[8 * i]; \ - ctx->key_enc[8 * i + 8] = t; \ - t ^= ctx->key_enc[8 * i + 1]; \ - ctx->key_enc[8 * i + 9] = t; \ - t ^= ctx->key_enc[8 * i + 2]; \ - ctx->key_enc[8 * i + 10] = t; \ - t ^= ctx->key_enc[8 * i + 3]; \ - ctx->key_enc[8 * i + 11] = t; \ -} while (0) - -#define loop8(i) do { \ - loop8tophalf(i); \ - t = ctx->key_enc[8 * i + 4] ^ ls_box(t); \ - ctx->key_enc[8 * i + 12] = t; \ - t ^= ctx->key_enc[8 * i + 5]; \ - ctx->key_enc[8 * i + 13] = t; \ - t ^= ctx->key_enc[8 * i + 6]; \ - ctx->key_enc[8 * i + 14] = t; \ - t ^= ctx->key_enc[8 * i + 7]; \ - ctx->key_enc[8 * i + 15] = t; \ -} while (0) - -/** - * AES_ExpandKey - Expands the AES key as described in FIPS-197 +/* aes_expand_key - Expands the AES key as described in FIPS-197 * @ctx: The location where the computed key will be stored. * @in_key: The supplied key. * @key_len: The length of the supplied key. * * Returns 0 on success. The function fails only if an invalid key size (or * pointer) is supplied. - * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes - * key schedule plus a 16 bytes key which is used before the first round). - * The decryption key is prepared for the "Equivalent Inverse Cipher" as - * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is - * for the initial combination, the second slot for the first round and so on. + * + * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 + * bytes key schedule plus a 16 bytes key which is used before the first + * round). The decryption key is prepared for the "Equivalent Inverse Cipher" + * as described in FIPS-197. The first slot (16 bytes) of each key (enc or + * dec) is for the initial combination, the second slot for the first round + * and so on. */ -static int AES_ExpandKey(aes_context_t *ctx, const uint8_t *in_key, + +static int aes_expand_key(aes_context_t *ctx, const uint8_t *in_key, unsigned int key_len) { - const uint32_t *key = (const uint32_t *)in_key; - uint32_t i, t, u, v, w, j; - - if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 && - key_len != AES_KEYSIZE_256) - return -1; - - ctx->key_length = key_len; - - ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]); - ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]); - ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]); - ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]); - - switch (key_len) { - case AES_KEYSIZE_128: - t = ctx->key_enc[3]; - for (i = 0; i < 10; ++i) - loop4(i); - break; - - case AES_KEYSIZE_192: - ctx->key_enc[4] = le32_to_cpu(key[4]); - t = ctx->key_enc[5] = le32_to_cpu(key[5]); - for (i = 0; i < 8; ++i) - loop6(i); - break; - - case AES_KEYSIZE_256: - ctx->key_enc[4] = le32_to_cpu(key[4]); - ctx->key_enc[5] = le32_to_cpu(key[5]); - ctx->key_enc[6] = le32_to_cpu(key[6]); - t = ctx->key_enc[7] = le32_to_cpu(key[7]); - for (i = 0; i < 6; ++i) - loop8(i); - loop8tophalf(i); - break; + const uint32_t *key = (const uint32_t *)in_key; + uint32_t i; + uint32_t t; + uint32_t u; + uint32_t v; + uint32_t w; + uint32_t j; + + if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 && + key_len != AES_KEYSIZE_256) + { + return -1; } - ctx->key_dec[0] = ctx->key_enc[key_len + 24]; - ctx->key_dec[1] = ctx->key_enc[key_len + 25]; - ctx->key_dec[2] = ctx->key_enc[key_len + 26]; - ctx->key_dec[3] = ctx->key_enc[key_len + 27]; + ctx->key_length = key_len; + + ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]); + ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]); + ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]); + ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]); - for (i = 4; i < key_len + 24; ++i) { - j = key_len + 24 - (i & ~3) + (i & 3); - imix_col(ctx->key_dec[j], ctx->key_enc[i]); + switch (key_len) + { + case AES_KEYSIZE_128: + t = ctx->key_enc[3]; + for (i = 0; i < 10; ++i) + loop4(i); + break; + + case AES_KEYSIZE_192: + ctx->key_enc[4] = le32_to_cpu(key[4]); + t = ctx->key_enc[5] = le32_to_cpu(key[5]); + for (i = 0; i < 8; ++i) + loop6(i); + break; + + case AES_KEYSIZE_256: + ctx->key_enc[4] = le32_to_cpu(key[4]); + ctx->key_enc[5] = le32_to_cpu(key[5]); + ctx->key_enc[6] = le32_to_cpu(key[6]); + t = ctx->key_enc[7] = le32_to_cpu(key[7]); + for (i = 0; i < 6; ++i) + loop8(i); + loop8tophalf(i); + break; + } + + ctx->key_dec[0] = ctx->key_enc[key_len + 24]; + ctx->key_dec[1] = ctx->key_enc[key_len + 25]; + ctx->key_dec[2] = ctx->key_enc[key_len + 26]; + ctx->key_dec[3] = ctx->key_enc[key_len + 27]; + + for (i = 4; i < key_len + 24; ++i) + { + j = key_len + 24 - (i & ~3) + (i & 3); + imix_col(ctx->key_dec[j], ctx->key_enc[i]); } - return 0; + + return 0; } -/** - * AES_SetKey - Set the AES key. +/* aes_set_key - Set the AES key. * @ctx: AES context struct. * @in_key: The input key. * @key_len: The size of the key. * * Returns 0 on success, on failure -1 is returned. - * The function uses AES_ExpandKey() to expand the key. + * The function uses aes_expand_key() to expand the key. */ -static int AES_SetKey(aes_context_t *ctx, const uint8_t *in_key, + +static int aes_set_key(aes_context_t *ctx, const uint8_t *in_key, unsigned int key_len) { - int ret; + int ret; - ret = AES_ExpandKey(ctx, in_key, key_len); - if (!ret) - return 0; + ret = aes_expand_key(ctx, in_key, key_len); + if (!ret) return 0; - return -1; + return -1; } -/* encrypt a block of text */ - -#define f_rn(bo, bi, n, k) do { \ - bo[n] = crypto_ft_tab[0][get_byte(bi[n], 0)] ^ \ - crypto_ft_tab[1][get_byte(bi[(n + 1) & 3], 1)] ^ \ - crypto_ft_tab[2][get_byte(bi[(n + 2) & 3], 2)] ^ \ - crypto_ft_tab[3][get_byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ -} while (0) - -#define f_nround(bo, bi, k) do {\ - f_rn(bo, bi, 0, k); \ - f_rn(bo, bi, 1, k); \ - f_rn(bo, bi, 2, k); \ - f_rn(bo, bi, 3, k); \ - k += 4; \ -} while (0) - -#define f_rl(bo, bi, n, k) do { \ - bo[n] = crypto_fl_tab[0][get_byte(bi[n], 0)] ^ \ - crypto_fl_tab[1][get_byte(bi[(n + 1) & 3], 1)] ^ \ - crypto_fl_tab[2][get_byte(bi[(n + 2) & 3], 2)] ^ \ - crypto_fl_tab[3][get_byte(bi[(n + 3) & 3], 3)] ^ *(k + n); \ -} while (0) - -#define f_lround(bo, bi, k) do {\ - f_rl(bo, bi, 0, k); \ - f_rl(bo, bi, 1, k); \ - f_rl(bo, bi, 2, k); \ - f_rl(bo, bi, 3, k); \ -} while (0) - -static void AES_Encrypt(aes_context_t *ctx, uint8_t *out, - const uint8_t *in) +static void aes_encrypt(aes_context_t *ctx, uint8_t *out, const uint8_t *in) { - const uint32_t *src = (const uint32_t *)in; - uint32_t *dst = (uint32_t *)out; - uint32_t b0[4], b1[4]; - const uint32_t *kp = ctx->key_enc + 4; - const int key_len = ctx->key_length; - - b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0]; - b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1]; - b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2]; - b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3]; - - if (key_len > 24) { - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); + const uint32_t *src = (const uint32_t *)in; + uint32_t *dst = (uint32_t *)out; + uint32_t b0[4]; + uint32_t b1[4]; + const uint32_t *kp = ctx->key_enc + 4; + const int key_len = ctx->key_length; + + b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0]; + b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1]; + b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2]; + b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3]; + + if (key_len > 24) + { + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); } - if (key_len > 16) { - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); + if (key_len > 16) + { + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); } - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_nround(b0, b1, kp); - f_nround(b1, b0, kp); - f_lround(b0, b1, kp); - - dst[0] = cpu_to_le32(b0[0]); - dst[1] = cpu_to_le32(b0[1]); - dst[2] = cpu_to_le32(b0[2]); - dst[3] = cpu_to_le32(b0[3]); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_nround(b0, b1, kp); + f_nround(b1, b0, kp); + f_lround(b0, b1, kp); + + dst[0] = cpu_to_le32(b0[0]); + dst[1] = cpu_to_le32(b0[1]); + dst[2] = cpu_to_le32(b0[2]); + dst[3] = cpu_to_le32(b0[3]); } -static boolean prng_enabled = false; -static aes_context_t prng_context; -static uint32_t prng_input_counter; -static uint32_t prng_values[4]; -static unsigned int prng_value_index = 0; - -// Initialize Pseudo-RNG using the specified 128-bit key. - -void PRNG_Start(prng_seed_t key) -{ - AES_SetKey(&prng_context, key, sizeof(prng_seed_t)); - prng_value_index = 4; - prng_input_counter = 0; - prng_enabled = true; -} - -void PRNG_Stop(void) -{ - prng_enabled = false; -} - -// Generate a set of new PRNG values by encrypting a new block. +/* Generate a set of new PRNG values by encrypting a new block. */ -static void PRNG_Generate(void) +static void prng_generate(void) { - byte input[16], output[16]; - unsigned int i; + byte input[16]; + byte output[16]; + unsigned int i; - // Input for the cipher is a consecutively increasing 32-bit counter. + /* Input for the cipher is a consecutively increasing 32-bit counter. */ - for (i = 0; i < 4; ++i) + for (i = 0; i < 4; ++i) { - input[4*i] = prng_input_counter & 0xff; - input[4*i + 1] = (prng_input_counter >> 8) & 0xff; - input[4*i + 2] = (prng_input_counter >> 16) & 0xff; - input[4*i + 3] = (prng_input_counter >> 24) & 0xff; - ++prng_input_counter; + input[4 * i] = prng_input_counter & 0xff; + input[4 * i + 1] = (prng_input_counter >> 8) & 0xff; + input[4 * i + 2] = (prng_input_counter >> 16) & 0xff; + input[4 * i + 3] = (prng_input_counter >> 24) & 0xff; + ++prng_input_counter; } - AES_Encrypt(&prng_context, output, input); + aes_encrypt(&prng_context, output, input); - for (i = 0; i < 4; ++i) + for (i = 0; i < 4; ++i) { - prng_values[i] = output[4*i] - | (output[4*i + 1] << 8) - | (output[4*i + 2] << 16) - | (output[4*i + 3] << 24); + prng_values[i] = output[4 * i] | (output[4 * i + 1] << 8) | + (output[4 * i + 2] << 16) | (output[4 * i + 3] << 24); } - prng_value_index = 0; + prng_value_index = 0; } -// Read a random 32-bit integer from the PRNG. +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Initialize Pseudo-RNG using the specified 128-bit key. */ -unsigned int PRNG_Random(void) +void prng_start(prng_seed_t key) { - unsigned int result; + aes_set_key(&prng_context, key, sizeof(prng_seed_t)); + prng_value_index = 4; + prng_input_counter = 0; + prng_enabled = true; +} - if (!prng_enabled) +void prng_stop(void) +{ + prng_enabled = false; +} + +/* Read a random 32-bit integer from the PRNG. */ + +unsigned int prng_random(void) +{ + unsigned int result; + + if (!prng_enabled) { - return 0; + return 0; } - if (prng_value_index >= 4) + if (prng_value_index >= 4) { - PRNG_Generate(); + prng_generate(); } - result = prng_values[prng_value_index]; - ++prng_value_index; + result = prng_values[prng_value_index]; + ++prng_value_index; - return result; + return result; } - diff --git a/games/NXDoom/src/aes_prng.h b/games/NXDoom/src/aes_prng.h index f255db17561..eed8dd78c60 100644 --- a/games/NXDoom/src/aes_prng.h +++ b/games/NXDoom/src/aes_prng.h @@ -1,32 +1,44 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Pseudo-random number generator for secure demos. -// +/**************************************************************************** + * apps/games/NXDoom/src/aes_prng.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Pseudo-random number generator for secure demos. + * + ****************************************************************************/ #ifndef __AES_PRNG_H__ #define __AES_PRNG_H__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -// Nonce value used as random seed for secure demos. +/* Nonce value used as random seed for secure demos. */ typedef byte prng_seed_t[16]; -void PRNG_Start(prng_seed_t seed); -void PRNG_Stop(void); -unsigned int PRNG_Random(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef __AES_PRNG_H__ */ +void prng_start(prng_seed_t seed); +void prng_stop(void); +unsigned int prng_random(void); +#endif /* __AES_PRNG_H__ */ diff --git a/games/NXDoom/src/config.h b/games/NXDoom/src/config.h new file mode 100644 index 00000000000..b6427530015 --- /dev/null +++ b/games/NXDoom/src/config.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * apps/games/NXDoom/src/config.h + * + * SPDX-License-Identifer: GPLv2 + * + * NuttX compatible config.h file. + * + * TODO: can we take a cleaner approach later by baking this into logic? + * + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define HAVE_DECL_STRCASECMP 1 +#define HAVE_DECL_STRNCASECMP 1 + +#define PACKAGE_TARNAME "nxdoom" +#define PACKAGE_NAME "NXDoom" +#define PACKAGE_STRING "NXDoom v0.0.0" +#define PROGRAM_PREFIX "" + +#define DISABLE_SDL2MIXER +#define DISABLE_SDL2NET diff --git a/games/NXDoom/src/d_dedicated.c b/games/NXDoom/src/d_dedicated.c index 72220049965..307010f34e6 100644 --- a/games/NXDoom/src/d_dedicated.c +++ b/games/NXDoom/src/d_dedicated.c @@ -1,22 +1,31 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Code specific to the standalone dedicated server. -// +/**************************************************************************** + * apps/games/NXDoom/src/d_dedicated.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Code specific to the standalone dedicated server. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include -#include #include "config.h" @@ -27,21 +36,25 @@ #include "net_server.h" #include "z_zone.h" -void NET_CL_Run(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void net_cl_run(void) { - // No client present :-) - // - // This is here because the server code sometimes runs this - // to let the client do some processing if it needs to. - // In a standalone dedicated server, we don't have a client. + /* No client present :-) + * + * This is here because the server code sometimes runs this + * to let the client do some processing if it needs to. + * In a standalone dedicated server, we don't have a client. + */ } -void D_DoomMain(void) +void d_doom_main(void) { - printf(PACKAGE_NAME " standalone dedicated server\n"); + printf(PACKAGE_NAME " standalone dedicated server\n"); - Z_Init(); + z_init(); - NET_DedicatedServer(); + net_dedicated_server(); } - diff --git a/games/NXDoom/src/d_event.c b/games/NXDoom/src/d_event.c index 3eef57282a8..0b2a29e6ce3 100644 --- a/games/NXDoom/src/d_event.c +++ b/games/NXDoom/src/d_event.c @@ -1,63 +1,81 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: Event handling. -// -// Events are asynchronous inputs generally generated by the game user. -// Events can be discarded if no responder claims them -// +/**************************************************************************** + * apps/games/NXDoom/src/d_event.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: Event handling. + * + * Events are asynchronous inputs generally generated by the game user. + * Events can be discarded if no responder claims them + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include #include "d_event.h" +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ #define MAXEVENTS 64 +/**************************************************************************** + * Private Data + ****************************************************************************/ + static event_t events[MAXEVENTS]; static int eventhead; static int eventtail; -// -// D_PostEvent -// Called by the I/O functions when input is detected -// -void D_PostEvent (event_t* ev) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* d_post_event + * Called by the I/O functions when input is detected + */ + +void d_post_event(event_t *ev) { - events[eventhead] = *ev; - eventhead = (eventhead + 1) % MAXEVENTS; + events[eventhead] = *ev; + eventhead = (eventhead + 1) % MAXEVENTS; } -// Read an event from the queue. +/* Read an event from the queue. */ -event_t *D_PopEvent(void) +event_t *d_pop_event(void) { - event_t *result; + event_t *result; - // No more events waiting. + /* No more events waiting. */ - if (eventtail == eventhead) + if (eventtail == eventhead) { - return NULL; + return NULL; } - - result = &events[eventtail]; - // Advance to the next event in the queue. + result = &events[eventtail]; - eventtail = (eventtail + 1) % MAXEVENTS; - - return result; -} + /* Advance to the next event in the queue. */ + eventtail = (eventtail + 1) % MAXEVENTS; + return result; +} diff --git a/games/NXDoom/src/d_event.h b/games/NXDoom/src/d_event.h index bc1050aeb9d..f1f43133ff9 100644 --- a/games/NXDoom/src/d_event.h +++ b/games/NXDoom/src/d_event.h @@ -1,147 +1,192 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - +/**************************************************************************** + * apps/games/NXDoom/src/d_event.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * + ****************************************************************************/ #ifndef __D_EVENT__ #define __D_EVENT__ +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "doomtype.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Event handling. */ -// -// Event handling. -// +/* Input event types. */ -// Input event types. typedef enum { - // Key press/release events. - // data1: Key code (from doomkeys.h) of the key that was - // pressed or released. This is the key as it appears - // on a US keyboard layout, and does not change with - // layout. - // For ev_keydown only: - // data2: ASCII representation of the key that was pressed that - // changes with the keyboard layout; eg. if 'Z' is - // pressed on a German keyboard, data1='y',data2='z'. - // Not affected by modifier keys. - // data3: ASCII input, fully modified according to keyboard - // layout and any modifier keys that are held down. - // Only set if I_StartTextInput() has been called. - ev_keydown, - ev_keyup, - - // Mouse movement event. - // data1: Bitfield of buttons currently held down. - // (bit 0 = left; bit 1 = right; bit 2 = middle). - // data2: X axis mouse movement (turn). - // data3: Y axis mouse movement (forward/backward). - ev_mouse, - - // Joystick state. - // data1: Bitfield of buttons currently pressed. - // data2: X axis mouse movement (turn). - // data3: Y axis mouse movement (forward/backward). - // data4: Third axis mouse movement (strafe). - // data5: Fourth axis mouse movement (look) - // data6: Dpad and analog stick direction. - ev_joystick, - - // Quit event. Triggered when the user clicks the "close" button - // to terminate the application. - ev_quit + /* Key press/release events. + * data1: Key code (from doomkeys.h) of the key that was + * pressed or released. This is the key as it appears + * on a US keyboard layout, and does not change with + * layout. + * For ev_keydown only: + * data2: ASCII representation of the key that was pressed that + * changes with the keyboard layout; eg. if 'Z' is + * pressed on a German keyboard, data1='y',data2='z'. + * Not affected by modifier keys. + * data3: ASCII input, fully modified according to keyboard + * layout and any modifier keys that are held down. + * Only set if i_start_text_input() has been called. + */ + + ev_keydown, + ev_keyup, + + /* Mouse movement event. + * data1: Bitfield of buttons currently held down. + * (bit 0 = left; bit 1 = right; bit 2 = middle). + * data2: X axis mouse movement (turn). + * data3: Y axis mouse movement (forward/backward). + */ + + ev_mouse, + + /* Joystick state. + * data1: Bitfield of buttons currently pressed. + * data2: X axis mouse movement (turn). + * data3: Y axis mouse movement (forward/backward). + * data4: Third axis mouse movement (strafe). + * data5: Fourth axis mouse movement (look) + * data6: Dpad and analog stick direction. + */ + + ev_joystick, + + /* Quit event. Triggered when the user clicks the "close" button + * to terminate the application. + */ + + ev_quit } evtype_t; -// Event structure. +/* Event structure. */ + typedef struct { - evtype_t type; + evtype_t type; - // Event-specific data; see the descriptions given above. - int data1, data2, data3, data4, data5, data6; + /* Event-specific data; see the descriptions given above. */ + + int data1; + int data2; + int data3; + int data4; + int data5; + int data6; } event_t; - -// -// Button/action code definitions. -// +/* Button/action code definitions. */ + typedef enum { - // Press "Fire". - BT_ATTACK = 1, - // Use button, to open doors, activate switches. - BT_USE = 2, - - // Flag: game events, not really buttons. - BT_SPECIAL = 128, - BT_SPECIALMASK = 3, - - // Flag, weapon change pending. - // If true, the next 3 bits hold weapon num. - BT_CHANGE = 4, - // The 3bit weapon mask and shift, convenience. - BT_WEAPONMASK = (8+16+32), - BT_WEAPONSHIFT = 3, - - // Pause the game. - BTS_PAUSE = 1, - // Save the game at each console. - BTS_SAVEGAME = 2, - - // Savegame slot numbers - // occupy the second byte of buttons. - BTS_SAVEMASK = (4+8+16), - BTS_SAVESHIFT = 2, - + /* Press "Fire". */ + + BT_ATTACK = 1, + + /* Use button, to open doors, activate switches. */ + + BT_USE = 2, + + /* Flag: game events, not really buttons. */ + + BT_SPECIAL = 128, + BT_SPECIALMASK = 3, + + /* Flag, weapon change pending. + * If true, the next 3 bits hold weapon num. + */ + + BT_CHANGE = 4, + + /* The 3bit weapon mask and shift, convenience. */ + + BT_WEAPONMASK = (8 + 16 + 32), + BT_WEAPONSHIFT = 3, + + /* Pause the game. */ + + BTS_PAUSE = 1, + + /* Save the game at each console. */ + + BTS_SAVEGAME = 2, + + /* Savegame slot numbers occupy the second byte of buttons. */ + + BTS_SAVEMASK = (4 + 8 + 16), + BTS_SAVESHIFT = 2, } buttoncode_t; -// villsa [STRIFE] Strife specific buttons -// TODO - not finished +/* villsa [STRIFE] Strife specific buttons + * TODO - not finished + */ + typedef enum { - // Player view look up - BT2_LOOKUP = 1, - // Player view look down - BT2_LOOKDOWN = 2, - // Center player's view - BT2_CENTERVIEW = 4, - // Use inventory item - BT2_INVUSE = 8, - // Drop inventory item - BT2_INVDROP = 16, - // Jump up and down - BT2_JUMP = 32, - // Use medkit - BT2_HEALTH = 128, - -} buttoncode2_t; + /* Player view look up */ + + BT2_LOOKUP = 1, + + /* Player view look down */ + + BT2_LOOKDOWN = 2, + /* Center player's view */ + BT2_CENTERVIEW = 4, + /* Use inventory item */ + + BT2_INVUSE = 8, + + /* Drop inventory item */ + + BT2_INVDROP = 16, + + /* Jump up and down */ + + BT2_JUMP = 32, + + /* Use medkit */ + + BT2_HEALTH = 128, +} buttoncode2_t; -// Called by IO functions when input is detected. -void D_PostEvent (event_t *ev); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Read an event from the event queue +/* Called by IO functions when input is detected. */ -event_t *D_PopEvent(void); +void d_post_event(event_t *ev); +/* Read an event from the event queue */ -#endif +event_t *d_pop_event(void); +#endif /* __D_EVENT__ */ diff --git a/games/NXDoom/src/d_iwad.c b/games/NXDoom/src/d_iwad.c index e05b75f0fc3..a6f1cd9453d 100644 --- a/games/NXDoom/src/d_iwad.c +++ b/games/NXDoom/src/d_iwad.c @@ -1,29 +1,38 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Search for and locate an IWAD file, and initialize according -// to the IWAD type. -// +/**************************************************************************** + * apps/games/NXDoom/src/d_iwad.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Search for and locate an IWAD file, and initialize according + * to the IWAD type. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include -#include #include +#include "d_iwad.h" #include "deh_str.h" #include "doomkeys.h" -#include "d_iwad.h" #include "i_system.h" #include "m_argv.h" #include "m_config.h" @@ -31,1017 +40,500 @@ #include "w_wad.h" #include "z_zone.h" -static const iwad_t iwads[] = -{ - { "doom2.wad", doom2, commercial, "Doom II" }, - { "plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment" }, - { "tnt.wad", pack_tnt, commercial, "Final Doom: TNT: Evilution" }, - { "doom.wad", doom, retail, "Doom" }, - { "doom1.wad", doom, shareware, "Doom Shareware" }, - { "doom2f.wad", doom2, commercial, "Doom II: L'Enfer sur Terre" }, - { "chex.wad", pack_chex, retail, "Chex Quest" }, - { "hacx.wad", pack_hacx, commercial, "Hacx" }, - { "freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" }, - { "freedoom1.wad", doom, retail, "Freedoom: Phase 1" }, - { "freedm.wad", doom2, commercial, "FreeDM" }, - { "heretic.wad", heretic, retail, "Heretic" }, - { "heretic1.wad", heretic, shareware, "Heretic Shareware" }, - { "hexen.wad", hexen, commercial, "Hexen" }, - //{ "strife0.wad", strife, commercial, "Strife" }, // haleyjd: STRIFE-FIXME - { "strife1.wad", strife, commercial, "Strife" }, -}; - -boolean D_IsIWADName(const char *name) -{ - int i; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ - for (i = 0; i < arrlen(iwads); i++) - { - if (!strcasecmp(name, iwads[i].name)) - { - return true; - } - } - - return false; -} - -// Array of locations to search for IWAD files -// -// "128 IWAD search directories should be enough for anybody". +/* Array of locations to search for IWAD files + * + * "128 IWAD search directories should be enough for anybody". + */ #define MAX_IWAD_DIRS 128 -static boolean iwad_dirs_built = false; -static const char *iwad_dirs[MAX_IWAD_DIRS]; -static int num_iwad_dirs = 0; - -static void AddIWADDir(const char *dir) -{ - if (num_iwad_dirs < MAX_IWAD_DIRS) - { - iwad_dirs[num_iwad_dirs] = dir; - ++num_iwad_dirs; - } -} - -// This is Windows-specific code that automatically finds the location -// of installed IWAD files. The registry is inspected to find special -// keys installed by the Windows installers for various CD versions -// of Doom. From these keys we can deduce where to find an IWAD. - -#if defined(_WIN32) && !defined(_WIN32_WCE) - -#define WIN32_LEAN_AND_MEAN -#include - -typedef struct -{ - HKEY root; - char *path; - char *value; -} registry_value_t; - -#define UNINSTALLER_STRING "\\uninstl.exe /S " - -// Keys installed by the various CD editions. These are actually the -// commands to invoke the uninstaller and look like this: -// -// C:\Program Files\Path\uninstl.exe /S C:\Program Files\Path -// -// With some munging we can find where Doom was installed. - -// [AlexMax] From the persepctive of a 64-bit executable, 32-bit registry -// keys are located in a different spot. -#if _WIN64 -#define SOFTWARE_KEY "Software\\Wow6432Node" -#else -#define SOFTWARE_KEY "Software" -#endif - -static registry_value_t uninstall_values[] = -{ - // Ultimate Doom, CD version (Depths of Doom trilogy) - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" - "Uninstall\\Ultimate Doom for Windows 95", - "UninstallString", - }, - - // Doom II, CD version (Depths of Doom trilogy) - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" - "Uninstall\\Doom II for Windows 95", - "UninstallString", - }, - - // Final Doom - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" - "Uninstall\\Final Doom for Windows 95", - "UninstallString", - }, - - // Shareware version - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\" - "Uninstall\\Doom Shareware for Windows 95", - "UninstallString", - }, -}; - -// Values installed by the GOG.com and Collector's Edition versions - -static registry_value_t root_path_keys[] = -{ - // Doom Collector's Edition - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\Activision\\DOOM Collector's Edition\\v1.0", - "INSTALLPATH", - }, - - // Doom II - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1435848814", - "PATH", - }, - - // Doom 3: BFG Edition - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1135892318", - "PATH", - }, - - // Final Doom +/**************************************************************************** + * Private Data + ****************************************************************************/ - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1435848742", - "PATH", - }, - - // Ultimate Doom - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1435827232", - "PATH", - }, - - // Strife: Veteran Edition - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1432899949", - "PATH", - }, - - // Heretic - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1290366318", - "PATH", - }, - - // Hexen - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1247951670", - "PATH", - }, - - // Hexen: Deathkings of a Dark Citadel - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1983497091", - "PATH", - }, - - // Heretic + Hexen Rerelease - - { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\GOG.com\\Games\\1776058590", - "PATH" - }, -}; - -// Subdirectories of the above install path, where IWADs are installed. - -static char *root_path_subdirs[] = -{ - "Doom2", - "Final Doom", - "Ultimate Doom", - "Plutonia", - "TNT", - "base\\wads", - "dos\\base\\heretic", - "dos\\base\\hexen", - ".", -}; - -// Location where Steam is installed - -static registry_value_t steam_install_location = +static const iwad_t g_iwads[] = { - HKEY_LOCAL_MACHINE, - SOFTWARE_KEY "\\Valve\\Steam", - "InstallPath", + {"doom2.wad", doom2, commercial, "Doom II"}, + {"plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment"}, + {"tnt.wad", pack_tnt, commercial, "Final Doom: TNT: Evilution"}, + {"doom.wad", doom, retail, "Doom"}, + {"doom1.wad", doom, shareware, "Doom Shareware"}, + {"doom2f.wad", doom2, commercial, "Doom II: L'Enfer sur Terre"}, + {"chex.wad", pack_chex, retail, "Chex Quest"}, + {"hacx.wad", pack_hacx, commercial, "Hacx"}, + {"freedoom2.wad", doom2, commercial, "Freedoom: Phase 2"}, + {"freedoom1.wad", doom, retail, "Freedoom: Phase 1"}, + {"freedm.wad", doom2, commercial, "FreeDM"}, + {"heretic.wad", heretic, retail, "Heretic"}, + {"heretic1.wad", heretic, shareware, "Heretic Shareware"}, + {"hexen.wad", hexen, commercial, "Hexen"}, + {"strife1.wad", strife, commercial, "Strife"}, }; -// Subdirs of the steam install directory where IWADs are found - -static char *steam_install_subdirs[] = -{ - "steamapps\\common\\doom 2\\base", - "steamapps\\common\\doom 2\\finaldoombase", - "steamapps\\common\\final doom\\base", - "steamapps\\common\\ultimate doom\\base", - "steamapps\\common\\heretic shadow of the serpent riders\\base", - "steamapps\\common\\hexen\\base", - "steamapps\\common\\hexen deathkings of the dark citadel\\base", - - // From Doom 3: BFG Edition: - - "steamapps\\common\\DOOM 3 BFG Edition\\base\\wads", - - // From Heretic + Hexen Rerelease: - - "steamapps\\common\\Heretic + Hexen\\dos\\base\\heretic", - "steamapps\\common\\Heretic + Hexen\\dos\\base\\hexen", - - // From Strife: Veteran Edition: - - "steamapps\\common\\Strife", -}; - -#define STEAM_BFG_GUS_PATCHES \ - "steamapps\\common\\DOOM 3 BFG Edition\\base\\classicmusic\\instruments" - -static char *GetRegistryString(registry_value_t *reg_val) -{ - HKEY key; - DWORD len; - DWORD valtype; - char *result; - - // Open the key (directory where the value is stored) - - if (RegOpenKeyEx(reg_val->root, reg_val->path, - 0, KEY_READ, &key) != ERROR_SUCCESS) - { - return NULL; - } - - result = NULL; - - // Find the type and length of the string, and only accept strings. - - if (RegQueryValueEx(key, reg_val->value, - NULL, &valtype, NULL, &len) == ERROR_SUCCESS - && valtype == REG_SZ) - { - // Allocate a buffer for the value and read the value - - result = malloc(len + 1); - - if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, - (unsigned char *) result, &len) != ERROR_SUCCESS) - { - free(result); - result = NULL; - } - else - { - // Ensure the value is null-terminated - result[len] = '\0'; - } - } - - // Close the key - - RegCloseKey(key); - - return result; -} +static boolean iwad_dirs_built = false; +static const char *iwad_dirs[MAX_IWAD_DIRS]; +static int num_iwad_dirs = 0; -// Check for the uninstall strings from the CD versions +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static void CheckUninstallStrings(void) +static void add_iwad_dir(const char *dir) { - unsigned int i; - - for (i=0; i 0) + if (!strcmp(dir, ".")) { - return; + filename = m_string_duplicate(iwadname); } - - install_path = GetRegistryString(&steam_install_location); - - if (install_path == NULL) + else { - return; + filename = m_string_join(dir, DIR_SEPARATOR_S, iwadname, NULL); } - patch_path = M_StringJoin(install_path, "\\", STEAM_BFG_GUS_PATCHES, - NULL); - test_patch_path = M_StringJoin(patch_path, "\\ACBASS.PAT", NULL); + free(probe); + probe = m_file_case_exists(filename); + free(filename); - // Does acbass.pat exist? If so, then set gus_patch_path. - if (M_FileExists(test_patch_path)) + if (probe != NULL) { - M_SetVariable("gus_patch_path", patch_path); + return probe; } - free(test_patch_path); - free(patch_path); - free(install_path); + return NULL; } -// Default install directories for DOS Doom +/* Search a directory to try to find an IWAD + * Returns the location of the IWAD if found, otherwise NULL. + */ -static void CheckDOSDefaults(void) +static char *search_dir_for_iwad(const char *dir, int mask, + gamemission_t *mission) { - // These are the default install directories used by the deice - // installer program: - - AddIWADDir("\\doom2"); // Doom II - AddIWADDir("\\plutonia"); // Final Doom - AddIWADDir("\\tnt"); - AddIWADDir("\\doom_se"); // Ultimate Doom - AddIWADDir("\\doom"); // Shareware / Registered Doom - AddIWADDir("\\dooms"); // Shareware versions - AddIWADDir("\\doomsw"); - - AddIWADDir("\\heretic"); // Heretic - AddIWADDir("\\hrtic_se"); // Heretic Shareware from Quake disc - - AddIWADDir("\\hexen"); // Hexen - AddIWADDir("\\hexendk"); // Hexen Deathkings of the Dark Citadel - - AddIWADDir("\\strife"); // Strife -} - -#endif + char *filename; + size_t i; -// Returns true if the specified path is a path to a file -// of the specified name. - -static boolean DirIsFile(const char *path, const char *filename) -{ - return strchr(path, DIR_SEPARATOR) != NULL - && !strcasecmp(M_BaseName(path), filename); -} - -// Check if the specified directory contains the specified IWAD -// file, returning the full path to the IWAD if found, or NULL -// if not found. - -static char *CheckDirectoryHasIWAD(const char *dir, const char *iwadname) -{ - char *filename; - char *probe; - - // As a special case, the "directory" may refer directly to an - // IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH. - - probe = M_FileCaseExists(dir); - if (DirIsFile(dir, iwadname) && probe != NULL) - { - return probe; - } - - // Construct the full path to the IWAD if it is located in - // this directory, and check if it exists. - - if (!strcmp(dir, ".")) - { - filename = M_StringDuplicate(iwadname); - } - else - { - filename = M_StringJoin(dir, DIR_SEPARATOR_S, iwadname, NULL); - } - - free(probe); - probe = M_FileCaseExists(filename); - free(filename); - if (probe != NULL) - { - return probe; - } - - return NULL; -} - -// Search a directory to try to find an IWAD -// Returns the location of the IWAD if found, otherwise NULL. - -static char *SearchDirectoryForIWAD(const char *dir, int mask, GameMission_t *mission) -{ - char *filename; - size_t i; - - for (i=0; i -static void AddXdgDirs(void) -{ - const char *env; - char *tmp_env; - - // Quote: - // > $XDG_DATA_HOME defines the base directory relative to which - // > user specific data files should be stored. If $XDG_DATA_HOME - // > is either not set or empty, a default equal to - // > $HOME/.local/share should be used. - env = getenv("XDG_DATA_HOME"); - tmp_env = NULL; - - if (env == NULL) - { - const char *homedir = getenv("HOME"); - if (homedir == NULL) - { - homedir = "/"; - } - - tmp_env = M_StringJoin(homedir, "/.local/share", NULL); - env = tmp_env; - } - - // We support $XDG_DATA_HOME/games/doom (which will usually be - // ~/.local/share/games/doom) as a user-writeable extension to - // the usual /usr/share/games/doom location. - AddIWADDir(M_StringJoin(env, "/games/doom", NULL)); - free(tmp_env); - - // Quote: - // > $XDG_DATA_DIRS defines the preference-ordered set of base - // > directories to search for data files in addition to the - // > $XDG_DATA_HOME base directory. The directories in $XDG_DATA_DIRS - // > should be seperated with a colon ':'. - // > - // > If $XDG_DATA_DIRS is either not set or empty, a value equal to - // > /usr/local/share/:/usr/share/ should be used. - env = getenv("XDG_DATA_DIRS"); - if (env == NULL) - { - // (Trailing / omitted from paths, as it is added below) - env = "/usr/local/share:/usr/share"; - } - - // The "standard" location for IWADs on Unix that is supported by most - // source ports is /usr/share/games/doom - we support this through the - // XDG_DATA_DIRS mechanism, through which it can be overridden. - AddIWADPath(env, "/games/doom"); - AddIWADPath(env, "/doom"); +/* Build a list of IWAD files */ - // The convention set by RBDOOM-3-BFG is to install Doom 3: BFG - // Edition into this directory, under which includes the Doom - // Classic WADs. - AddIWADPath(env, "/games/doom3bfg/base/wads"); -} - -#ifndef __MACOSX__ -// Steam on Linux allows installing some select Windows games, -// including the classic Doom series (running DOSBox via Wine). We -// could parse *.vdf files to more accurately detect installation -// locations, but the defaults are likely to be good enough for just -// about everyone. -static void AddSteamDirs(void) +static void buld_iwad_dir_list(void) { - const char *homedir; - char *steampath; + char *env; - homedir = getenv("HOME"); - if (homedir == NULL) + if (iwad_dirs_built) { - homedir = "/"; + return; } - steampath = M_StringJoin(homedir, "/.steam/root/steamapps/common", NULL); - - AddIWADPath(steampath, "/Doom 2/base"); - AddIWADPath(steampath, "/Doom 2/finaldoombase"); - AddIWADPath(steampath, "/Master Levels of Doom/doom2"); - AddIWADPath(steampath, "/Ultimate Doom/base"); - AddIWADPath(steampath, "/Final Doom/base"); - AddIWADPath(steampath, "/DOOM 3 BFG Edition/base/wads"); - AddIWADPath(steampath, "/Heretic Shadow of the Serpent Riders/base"); - AddIWADPath(steampath, "/Hexen/base"); - AddIWADPath(steampath, "/Hexen Deathkings of the Dark Citadel/base"); - AddIWADPath(steampath, "/Heretic + Hexen/dos/base/heretic"); - AddIWADPath(steampath, "/Heretic + Hexen/dos/base/hexen"); - AddIWADPath(steampath, "/Strife"); - free(steampath); -} -#endif // __MACOSX__ -#endif // !_WIN32 -// -// Build a list of IWAD files -// + /* Look in the current directory. Doom always does this. */ -static void BuildIWADDirList(void) -{ - char *env; + add_iwad_dir("."); - if (iwad_dirs_built) - { - return; - } + /* Next check the directory where the executable is located. This might + * be different from the current directory. + */ - // Look in the current directory. Doom always does this. - AddIWADDir("."); + add_iwad_dir(m_dir_name(myargv[0])); - // Next check the directory where the executable is located. This might - // be different from the current directory. - AddIWADDir(M_DirName(myargv[0])); + /* Add DOOMWADDIR if it is in the environment */ - // Add DOOMWADDIR if it is in the environment - env = M_getenv("DOOMWADDIR"); - if (env != NULL) + env = getenv("DOOMWADDIR"); + if (env != NULL) { - AddIWADDir(env); + add_iwad_dir(env); } - // Add dirs from DOOMWADPATH: - env = M_getenv("DOOMWADPATH"); - if (env != NULL) + /* Add dirs from DOOMWADPATH: */ + + env = getenv("DOOMWADPATH"); + if (env != NULL) { - AddIWADPath(env, ""); + add_iwad_path(env, ""); } -#ifdef _WIN32 - - // Search the registry and find where IWADs have been installed. - - CheckUninstallStrings(); - CheckInstallRootPaths(); - CheckSteamEdition(); - CheckDOSDefaults(); - - // Check for GUS patches installed with the BFG edition! + /* Don't run this function again. */ - CheckSteamGUSPatches(); + iwad_dirs_built = true; +} -#else - AddXdgDirs(); -#ifndef __MACOSX__ - AddSteamDirs(); -#endif -#endif +/**************************************************************************** + * Public Functions + ****************************************************************************/ - // Don't run this function again. +/* Searches WAD search paths for an WAD with a specific filename. */ - iwad_dirs_built = true; -} +char *d_find_wad_by_name(const char *name) +{ + char *path; + char *probe; + int i; -// -// Searches WAD search paths for an WAD with a specific filename. -// + /* Absolute path? */ -char *D_FindWADByName(const char *name) -{ - char *path; - char *probe; - int i; - - // Absolute path? - - probe = M_FileCaseExists(name); - if (probe != NULL) + probe = m_file_case_exists(name); + if (probe != NULL) { - return probe; + return probe; } - BuildIWADDirList(); + buld_iwad_dir_list(); - // Search through all IWAD paths for a file with the given name. + /* Search through all IWAD paths for a file with the given name. */ - for (i=0; i - // + /* Check for the -iwad parameter + * + * Specify an IWAD file to use. + * + * @arg + * + */ - iwadparm = M_CheckParmWithArgs("-iwad", 1); + iwadparm = m_check_parm_with_args("-iwad", 1); - if (iwadparm) + if (iwadparm) { - // Search through IWAD dirs for an IWAD with the given name. + /* Search through IWAD dirs for an IWAD with the given name. */ - iwadfile = myargv[iwadparm + 1]; + iwadfile = myargv[iwadparm + 1]; - result = D_FindWADByName(iwadfile); + result = d_find_wad_by_name(iwadfile); - if (result == NULL) + if (result == NULL) { - I_Error("IWAD file '%s' not found!", iwadfile); + i_error("IWAD file '%s' not found!", iwadfile); } - - *mission = IdentifyIWADByName(result, mask); + + *mission = identify_iwad_by_name(result, mask); } - else + else { - // Search through the list and look for an IWAD + /* Search through the list and look for an IWAD */ + + result = NULL; - result = NULL; + buld_iwad_dir_list(); - BuildIWADDirList(); - - for (i=0; result == NULL && i #include @@ -30,852 +39,917 @@ #include "m_argv.h" #include "m_fixed.h" +#ifdef CONFIG_GAMES_NXDOOM_NET #include "net_client.h" #include "net_gui.h" #include "net_io.h" +#include "net_loop.h" #include "net_query.h" -#include "net_server.h" #include "net_sdl.h" -#include "net_loop.h" +#include "net_server.h" +#endif + +/* TODO: Move nonvanilla demo functions into a dedicated file. */ + +#include "m_misc.h" +#include "w_wad.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Maximum time that we wait in try_run_tics() for netgame data to be + * received before we bail out and render a frame anyway. + * Vanilla Doom used 20 for this value, but we use a smaller value + * instead for better responsiveness of the menu when we're stuck. + */ + +#define MAX_NETGAME_STALL_TICS 5 + +/**************************************************************************** + * Private Types + ****************************************************************************/ -// The complete set of data for a particular tic. +/* The complete set of data for a particular tic. */ typedef struct { - ticcmd_t cmds[NET_MAXPLAYERS]; - boolean ingame[NET_MAXPLAYERS]; + ticcmd_t cmds[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; + boolean ingame[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; } ticcmd_set_t; -// Maximum time that we wait in TryRunTics() for netgame data to be -// received before we bail out and render a frame anyway. -// Vanilla Doom used 20 for this value, but we use a smaller value -// instead for better responsiveness of the menu when we're stuck. -#define MAX_NETGAME_STALL_TICS 5 +/**************************************************************************** + * Private Data + ****************************************************************************/ -// -// gametic is the tic about to (or currently being) run -// maketic is the tic that hasn't had control made for it yet -// recvtic is the latest tic received from the server. -// -// a gametic cannot be run until ticcmds are received for it -// from all players. -// +/* gametic is the tic about to (or currently being) run + * maketic is the tic that hasn't had control made for it yet + * recvtic is the latest tic received from the server. + * + * a gametic cannot be run until ticcmds are received for it + * from all players. + */ -static ticcmd_set_t ticdata[BACKUPTICS]; +static ticcmd_set_t ticdata[CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; -// The index of the next tic to be made (with a call to BuildTiccmd). +/* The index of the next tic to be made (with a call to build_ticcmd). */ static int maketic; -// The number of complete tics received from the server so far. +/* The number of complete tics received from the server so far. */ static int recvtic; -// The number of tics that have been run (using RunTic) so far. +/* Index of the local player. */ -int gametic; +static int localplayer; -// When set to true, a single tic is run each time TryRunTics() is called. -// This is used for -timedemo mode. +/* Used for original sync code. */ -boolean singletics = false; +static int skiptics = 0; -// Index of the local player. +/* Use new client synchronization code */ -static int localplayer; +static boolean new_sync = true; + +/* Callback functions for loop code. */ -// Used for original sync code. +static loop_interface_t *loop_interface = NULL; -static int skiptics = 0; +/* Current players in the multiplayer game. + * This is distinct from playeringame[] used by the game code, which may + * modify playeringame[] when playing back multiplayer demos. + */ -// Reduce the bandwidth needed by sampling game input less and transmitting -// less. If ticdup is 2, sample half normal, 3 = one third normal, etc. +static boolean local_playeringame[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; -int ticdup; +/* Requested player class "sent" to the server on connect. + * If we are only doing a single player game then this needs to be remembered + * and saved in the game settings. + */ -// Amount to offset the timer for game sync. +static int player_class; -fixed_t offsetms; +#ifndef CONFIG_GAMES_NXDOOM_NET +static boolean net_client_connected = false; +static boolean drone = false; +#endif -// Use new client syncronisation code +static int frameon; +static int frameskip[4]; +static int oldnettics; -static boolean new_sync = true; +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Callback functions for loop code. +/* The number of tics that have been run (using run_tic) so far. */ -static loop_interface_t *loop_interface = NULL; +int gametic; -// Current players in the multiplayer game. -// This is distinct from playeringame[] used by the game code, which may -// modify playeringame[] when playing back multiplayer demos. +/* When set to true, a single tic is run each time try_run_tics() is called. + * This is used for -timedemo mode. + */ -static boolean local_playeringame[NET_MAXPLAYERS]; +boolean singletics = false; -// Requested player class "sent" to the server on connect. -// If we are only doing a single player game then this needs to be remembered -// and saved in the game settings. +/* Reduce the bandwidth needed by sampling game input less and transmitting + * less. If ticdup is 2, sample half normal, 3 = one third normal, etc. + */ -static int player_class; +int ticdup; + +/* Amount to offset the timer for game sync. */ +fixed_t offsetms; -// 35 fps clock adjusted by offsetms milliseconds +int lasttime; -static int GetAdjustedTime(void) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* 35 fps clock adjusted by offsetms milliseconds */ + +static int get_adjusted_time(void) { - int time_ms; + int time_ms; - time_ms = I_GetTimeMS(); + time_ms = i_get_time_ms(); - if (new_sync) + if (new_sync) { - // Use the adjustments from net_client.c only if we are - // using the new sync mode. + /* Use the adjustments from net_client.c only if we are + * using the new sync mode. + */ - time_ms += (offsetms / FRACUNIT); + time_ms += (offsetms / FRACUNIT); } - return (time_ms * TICRATE) / 1000; + return (time_ms * TICRATE) / 1000; } -static boolean BuildNewTic(void) +static boolean build_new_tic(void) { - int gameticdiv; - ticcmd_t cmd; + int gameticdiv; + ticcmd_t cmd; - gameticdiv = gametic/ticdup; + gameticdiv = gametic / ticdup; - I_StartTic (); - loop_interface->ProcessEvents(); + i_start_tic(); + loop_interface->process_events(); - // Always run the menu + /* Always run the menu */ - loop_interface->RunMenu(); + loop_interface->run_menu(); - if (drone) + if (drone) { - // In drone mode, do not generate any ticcmds. + /* In drone mode, do not generate any ticcmds. */ - return false; + return false; } - if (new_sync) + if (new_sync) { - // If playing single player, do not allow tics to buffer - // up very far + /* If playing single player, do not allow tics to buffer + * up very far + */ - if (!net_client_connected && maketic - gameticdiv > 2) - return false; + if (!net_client_connected && maketic - gameticdiv > 2) return false; - // Never go more than ~200ms ahead + /* Never go more than ~200ms ahead */ - if (maketic - gameticdiv > 8) - return false; + if (maketic - gameticdiv > 8) return false; } - else + else { - if (maketic - gameticdiv >= 5) - return false; + if (maketic - gameticdiv >= 5) return false; } - //printf ("mk:%i ",maketic); - memset(&cmd, 0, sizeof(ticcmd_t)); - loop_interface->BuildTiccmd(&cmd, maketic); + /* printf ("mk:%i ",maketic); */ + + memset(&cmd, 0, sizeof(ticcmd_t)); + loop_interface->build_ticcmd(&cmd, maketic); - if (net_client_connected) +#ifdef CONFIG_GAMES_NXDOOM_NET + if (net_client_connected) { - NET_CL_SendTiccmd(&cmd, maketic); + net_cl_send_ticcmd(&cmd, maketic); } +#endif - ticdata[maketic % BACKUPTICS].cmds[localplayer] = cmd; - ticdata[maketic % BACKUPTICS].ingame[localplayer] = true; + ticdata[maketic % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].cmds[localplayer] = + cmd; + ticdata[maketic % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].ingame[localplayer] = + true; - ++maketic; + ++maketic; - return true; + return true; } -// -// NetUpdate -// Builds ticcmds for console player, -// sends out a packet -// -int lasttime; - -void NetUpdate (void) +static boolean strict_demos(void) { - int nowtime; - int newtics; - int i; + /* @category demo + * + * When recording or playing back demos, disable any extensions + * of the vanilla demo format - record demos as vanilla would do, + * and play back demos as vanilla would do. + * + */ + + return m_parm_exists("-strictdemos"); +} - // If we are running with singletics (timing a demo), this - // is all done separately. +static void d_disconnected(void) +{ + /* In drone mode, the game cannot continue once disconnected. */ - if (singletics) - return; + if (drone) + { + i_error("Disconnected from server in drone mode."); + } - // Run network subsystems + /* disconnected from server */ - NET_CL_Run(); - NET_SV_Run(); + printf("Disconnected from server.\n"); +} - // check time - nowtime = GetAdjustedTime() / ticdup; - newtics = nowtime - lasttime; +static int get_low_tic(void) +{ + int lowtic; - lasttime = nowtime; + lowtic = maketic; - if (skiptics <= newtics) + if (net_client_connected) { - newtics -= skiptics; - skiptics = 0; + if (drone || recvtic < lowtic) + { + lowtic = recvtic; + } } - else + + return lowtic; +} + +static void old_net_sync(void) +{ + unsigned int i; + int keyplayer = -1; + + frameon++; + + /* ideally maketic should be 1 - 3 tics above lowtic + * if we are consistently slower, speed up time + */ + + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; i++) { - skiptics -= newtics; - newtics = 0; + if (local_playeringame[i]) + { + keyplayer = i; + break; + } } - // build new ticcmds for console player + if (keyplayer < 0) + { + /* If there are no players, we can never advance anyway */ + + return; + } - for (i=0 ; i recvtic; + oldnettics = maketic; + + if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) { - break; + skiptics = 1; } } } -static void D_Disconnected(void) +/* Returns true if there are players in the game: */ + +static boolean players_in_game(void) { - // In drone mode, the game cannot continue once disconnected. + boolean result = false; + unsigned int i; + + /* If we are connected to a server, check if there are any players + * in the game. + */ - if (drone) + if (net_client_connected) { - I_Error("Disconnected from server in drone mode."); + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; ++i) + { + result = result || local_playeringame[i]; + } } - // disconnected from server + /* Whether single or multi-player, unless we are running as a drone, + * we are in the game. + */ + + if (!drone) + { + result = true; + } - printf("Disconnected from server.\n"); + return result; } -// -// Invoked by the network engine when a complete set of ticcmds is -// available. -// +/* When using ticdup, certain values must be cleared out when running + * the duplicate ticcmds. + */ -void D_ReceiveTic(ticcmd_t *ticcmds, boolean *players_mask) +static void ticdup_squash(ticcmd_set_t *set) { - int i; - - // Disconnected from server? + ticcmd_t *cmd; + unsigned int i; - if (ticcmds == NULL && players_mask == NULL) + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; ++i) { - D_Disconnected(); - return; + cmd = &set->cmds[i]; + cmd->chatchar = 0; + if (cmd->buttons & BT_SPECIAL) cmd->buttons = 0; } +} - for (i = 0; i < NET_MAXPLAYERS; ++i) +/* When running in single player mode, clear all the ingame[] array + * except the local player. + */ + +static void single_player_clear(ticcmd_set_t *set) +{ + unsigned int i; + + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; ++i) { - if (!drone && i == localplayer) + if (i != localplayer) { - // This is us. Don't overwrite it. - } - else - { - ticdata[recvtic % BACKUPTICS].cmds[i] = ticcmds[i]; - ticdata[recvtic % BACKUPTICS].ingame[i] = players_mask[i]; + set->ingame[i] = false; } } - - ++recvtic; } -// -// Start game loop -// -// Called after the screen is set but before the game starts running. -// +/* Returns true if the given lump number corresponds to data from a .lmp + * file, as opposed to a WAD. + */ -void D_StartGameLoop(void) +static boolean is_demo_file(int lumpnum) { - lasttime = GetAdjustedTime() / ticdup; + char *lower; + boolean result; + + lower = m_string_duplicate(lumpinfo[lumpnum]->wad_file->path); + m_force_lowercase(lower); + result = m_string_ends_with(lower, ".lmp"); + free(lower); + + return result; } -// -// Block until the game start message is received from the server. -// +/* Block until the game start message is received from the server. */ -static void BlockUntilStart(net_gamesettings_t *settings, +#ifdef CONFIG_GAMES_NXDOOM_NET +static void block_until_start(net_gamesettings_t *settings, netgame_startup_callback_t callback) { - while (!NET_CL_GetSettings(settings)) + while (!net_cl_get_settings(settings)) { - NET_CL_Run(); - NET_SV_Run(); + net_cl_run(); + net_sv_run(); - if (!net_client_connected) + if (!net_client_connected) { - I_Error("Lost connection to server"); + i_error("Lost connection to server"); } - if (callback != NULL && !callback(net_client_wait_data.ready_players, - net_client_wait_data.num_players)) + if (callback != NULL && !callback(net_client_wait_data.ready_players, + net_client_wait_data.num_players)) { - I_Error("Netgame startup aborted."); + i_error("Netgame startup aborted."); } - I_Sleep(100); + usleep(100000); } } -void D_StartNetGame(net_gamesettings_t *settings, - netgame_startup_callback_t callback) -{ - int i; - - offsetms = 0; - recvtic = 0; +/* d_quit_net_game + * + * Called before quitting to leave a net game without hanging the other + * players + * + * Broadcasts special packets to other players to notify of game exit + */ - settings->consoleplayer = 0; - settings->num_players = 1; - settings->player_classes[0] = player_class; +static void d_quit_net_game(void) +{ + net_sv_shutdown(); + net_cl_disconnect(); +} +#endif /* CONFIG_GAMES_NXDOOM_NET */ - //! - // @category net - // - // Use original network client sync code rather than the improved - // sync code. - // - settings->new_sync = !M_ParmExists("-oldsync"); +/**************************************************************************** + * Public Functions + ****************************************************************************/ - //! - // @category net - // @arg - // - // Send n extra tics in every packet as insurance against dropped - // packets. - // +/* net_update + * Builds ticcmds for console player, sends out a packet + */ - i = M_CheckParmWithArgs("-extratics", 1); +void net_update(void) +{ + int nowtime; + int newtics; + int i; - if (i > 0) - settings->extratics = atoi(myargv[i+1]); - else - settings->extratics = 1; + /* If we are running with singletics (timing a demo), this + * is all done separately. + */ - //! - // @category net - // @arg - // - // Reduce the resolution of the game by a factor of n, reducing - // the amount of network bandwidth needed. - // + if (singletics) return; - i = M_CheckParmWithArgs("-dup", 1); + /* Run network subsystems */ - if (i > 0) - settings->ticdup = atoi(myargv[i+1]); - else - settings->ticdup = 1; +#ifdef CONFIG_GAMES_NXDOOM_NET + net_cl_run(); + net_sv_run(); +#endif - if (net_client_connected) - { - // Send our game settings and block until game start is received - // from the server. + /* check time */ - NET_CL_StartGame(settings); - BlockUntilStart(settings, callback); + nowtime = get_adjusted_time() / ticdup; + newtics = nowtime - lasttime; - // Read the game settings that were received. + lasttime = nowtime; - NET_CL_GetSettings(settings); + if (skiptics <= newtics) + { + newtics -= skiptics; + skiptics = 0; } - - if (drone) + else { - settings->consoleplayer = 0; + skiptics -= newtics; + newtics = 0; } - // Set the local player and playeringame[] values. - - localplayer = settings->consoleplayer; + /* build new ticcmds for console player */ - for (i = 0; i < NET_MAXPLAYERS; ++i) + for (i = 0; i < newtics; i++) { - local_playeringame[i] = i < settings->num_players; + if (!build_new_tic()) + { + break; + } } +} + +/* Invoked by the network engine when a complete set of ticcmds is + * available. + */ - // Copy settings to global variables. +void d_receive_tic(ticcmd_t *ticcmds, boolean *players_mask) +{ + int i; - ticdup = settings->ticdup; - new_sync = settings->new_sync; + /* Disconnected from server? */ - if (ticdup < 1) + if (ticcmds == NULL && players_mask == NULL) { - I_Error("D_StartNetGame: invalid ticdup value (%d)", ticdup); + d_disconnected(); + return; } - // TODO: Message disabled until we fix new_sync. - //if (!new_sync) - //{ - // printf("Syncing netgames like Vanilla Doom.\n"); - //} -} + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; ++i) + { + if (!drone && i == localplayer) + { + /* This is us. Don't overwrite it. */ + } + else + { + ticdata[recvtic % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].cmds[i] = + ticcmds[i]; + ticdata[recvtic % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].ingame[i] = + players_mask[i]; + } + } -boolean D_InitNetGame(net_connect_data_t *connect_data) -{ - boolean result = false; - net_addr_t *addr = NULL; - int i; + ++recvtic; +} - // Call D_QuitNetGame on exit: +/**************************************************************************** + * Name: d_start_game_loop + * + * Description: + * Called after the screen is set but before the game starts running. + * + ****************************************************************************/ - I_AtExit(D_QuitNetGame, true); +void d_start_game_loop(void) +{ + lasttime = get_adjusted_time() / ticdup; +} - player_class = connect_data->player_class; +void d_start_net_game(net_gamesettings_t *settings, + netgame_startup_callback_t callback) +{ + int i; - //! - // @category net - // - // Start a multiplayer server, listening for connections. - // + offsetms = 0; + recvtic = 0; - if (M_CheckParm("-server") > 0 - || M_CheckParm("-privateserver") > 0) - { - NET_SV_Init(); - NET_SV_AddModule(&net_loop_server_module); - NET_SV_AddModule(&net_sdl_module); - NET_SV_RegisterWithMaster(); + settings->consoleplayer = 0; + settings->num_players = 1; + settings->player_classes[0] = player_class; - net_loop_client_module.InitClient(); - addr = net_loop_client_module.ResolveAddress(NULL); - NET_ReferenceAddress(addr); - } - else - { - //! - // @category net - // - // Automatically search the local LAN for a multiplayer - // server and join it. - // + /* @category net + * + * Use original network client sync code rather than the improved + * sync code. + */ - i = M_CheckParm("-autojoin"); + settings->new_sync = !m_parm_exists("-oldsync"); - if (i > 0) - { - addr = NET_FindLANServer(); + /* @category net + * @arg + * + * Send n extra tics in every packet as insurance against dropped + * packets. + */ - if (addr == NULL) - { - I_Error("No server found on local LAN"); - } - } + i = m_check_parm_with_args("-extratics", 1); - //! - // @arg
- // @category net - // - // Connect to a multiplayer server running on the given - // address. - // + if (i > 0) + settings->extratics = atoi(myargv[i + 1]); + else + settings->extratics = 1; - i = M_CheckParmWithArgs("-connect", 1); + /* @category net + * @arg + * + * Reduce the resolution of the game by a factor of n, reducing + * the amount of network bandwidth needed. + */ - if (i > 0) - { - net_sdl_module.InitClient(); - addr = net_sdl_module.ResolveAddress(myargv[i+1]); - NET_ReferenceAddress(addr); + i = m_check_parm_with_args("-dup", 1); - if (addr == NULL) - { - I_Error("Unable to resolve '%s'\n", myargv[i+1]); - } - } - } + if (i > 0) + settings->ticdup = atoi(myargv[i + 1]); + else + settings->ticdup = 1; - if (addr != NULL) +#ifdef CONFIG_GAMES_NXDOOM_NET + if (net_client_connected) { - if (M_CheckParm("-drone") > 0) - { - connect_data->drone = true; - } - - if (!NET_CL_Connect(addr, connect_data)) - { - I_Error("D_InitNetGame: Failed to connect to %s:\n%s\n", - NET_AddrToString(addr), net_client_reject_reason); - } + /* Send our game settings and block until game start is received + * from the server. + */ - printf("D_InitNetGame: Connected to %s\n", NET_AddrToString(addr)); - NET_ReleaseAddress(addr); + net_cl_start_game(settings); + block_until_start(settings, callback); - // Wait for launch message received from server. + /* Read the game settings that were received. */ - NET_WaitForLaunch(); + net_cl_get_settings(settings); + } - result = true; + if (drone) + { + settings->consoleplayer = 0; } +#endif - return result; -} + /* Set the local player and playeringame[] values. */ + localplayer = settings->consoleplayer; -// -// D_QuitNetGame -// Called before quitting to leave a net game -// without hanging the other players -// -void D_QuitNetGame (void) -{ - NET_SV_Shutdown(); - NET_CL_Disconnect(); -} + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; ++i) + { + local_playeringame[i] = i < settings->num_players; + } -static int GetLowTic(void) -{ - int lowtic; + /* Copy settings to global variables. */ - lowtic = maketic; + ticdup = settings->ticdup; + new_sync = settings->new_sync; - if (net_client_connected) + if (ticdup < 1) { - if (drone || recvtic < lowtic) - { - lowtic = recvtic; - } + i_error("d_start_net_game: invalid ticdup value (%d)", ticdup); } - return lowtic; + /* TODO: Message disabled until we fix new_sync. + * + * if (!new_sync) + * { + * printf("Syncing netgames like Vanilla Doom.\n"); + * } + */ } -static int frameon; -static int frameskip[4]; -static int oldnettics; - -static void OldNetSync(void) +boolean d_init_net_game(net_connect_data_t *connect_data) { - unsigned int i; - int keyplayer = -1; +#ifdef CONFIG_GAMES_NXDOOM_NET + boolean result = false; + net_addr_t *addr = NULL; + int i; - frameon++; + /* Call d_quit_net_game on exit: */ - // ideally maketic should be 1 - 3 tics above lowtic - // if we are consistantly slower, speed up time + i_at_exit(d_quit_net_game, true); +#endif - for (i=0 ; iplayer_class; - if (keyplayer < 0) - { - // If there are no players, we can never advance anyway +#ifdef CONFIG_GAMES_NXDOOM_NET + /* @category net + * + * Start a multiplayer server, listening for connections. + */ - return; - } - - if (localplayer == keyplayer) + if (m_check_parm("-server") > 0 || m_check_parm("-privateserver") > 0) { - // the key player does not adapt + net_sv_init(); + net_sv_add_module(&net_loop_server_module); + net_sv_add_module(&net_sdl_module); + net_sv_register_with_master(); + + net_loop_client_module.init_client(); + addr = net_loop_client_module.resolve_address(NULL); + net_reference_address(addr); } - else + else { - if (maketic <= recvtic) - { - lasttime--; - // printf ("-"); - } + /* @category net + * + * Automatically search the local LAN for a multiplayer + * server and join it. + */ - frameskip[frameon & 3] = oldnettics > recvtic; - oldnettics = maketic; + i = m_check_parm("-autojoin"); - if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3]) + if (i > 0) { - skiptics = 1; - // printf ("+"); - } - } -} + addr = net_find_lan_server(); -// Returns true if there are players in the game: + if (addr == NULL) + { + i_error("No server found on local LAN"); + } + } -static boolean PlayersInGame(void) -{ - boolean result = false; - unsigned int i; + /* @arg
+ * @category net + * + * Connect to a multiplayer server running on the given + * address. + */ - // If we are connected to a server, check if there are any players - // in the game. + i = m_check_parm_with_args("-connect", 1); - if (net_client_connected) - { - for (i = 0; i < NET_MAXPLAYERS; ++i) + if (i > 0) { - result = result || local_playeringame[i]; + net_sdl_module.init_client(); + addr = net_sdl_module.resolve_address(myargv[i + 1]); + net_reference_address(addr); + + if (addr == NULL) + { + i_error("Unable to resolve '%s'\n", myargv[i + 1]); + } } } - // Whether single or multi-player, unless we are running as a drone, - // we are in the game. - - if (!drone) + if (addr != NULL) { - result = true; - } - - return result; -} - -// When using ticdup, certain values must be cleared out when running -// the duplicate ticcmds. + if (m_check_parm("-drone") > 0) + { + connect_data->drone = true; + } -static void TicdupSquash(ticcmd_set_t *set) -{ - ticcmd_t *cmd; - unsigned int i; + if (!net_cl_connect(addr, connect_data)) + { + i_error("d_init_net_game: Failed to connect to %s:\n%s\n", + net_addr_to_string(addr), net_client_reject_reason); + } - for (i = 0; i < NET_MAXPLAYERS ; ++i) - { - cmd = &set->cmds[i]; - cmd->chatchar = 0; - if (cmd->buttons & BT_SPECIAL) - cmd->buttons = 0; - } -} + printf("d_init_net_game: Connected to %s\n", net_addr_to_string(addr)); + net_release_address(addr); -// When running in single player mode, clear all the ingame[] array -// except the local player. + /* Wait for launch message received from server. */ -static void SinglePlayerClear(ticcmd_set_t *set) -{ - unsigned int i; + net_wait_for_launch(); - for (i = 0; i < NET_MAXPLAYERS; ++i) - { - if (i != localplayer) - { - set->ingame[i] = false; - } + result = true; } + + return result; +#endif + return false; } -// -// TryRunTics -// +/* try_run_tics */ -void TryRunTics (void) +void try_run_tics(void) { - int i; - int lowtic; - int entertic; - static int oldentertics; - int realtics; - int availabletics; - int counts; + int i; + int lowtic; + int entertic; + static int oldentertics; + int realtics; + int availabletics; + int counts; + + /* get real tics */ - // get real tics - entertic = I_GetTime() / ticdup; - realtics = entertic - oldentertics; - oldentertics = entertic; + entertic = i_get_time() / ticdup; + realtics = entertic - oldentertics; + oldentertics = entertic; - // in singletics mode, run a single tic every time this function - // is called. + /* in singletics mode, run a single tic every time this function + * is called. + */ - if (singletics) + if (singletics) { - BuildNewTic(); + build_new_tic(); } - else + else { - NetUpdate (); + net_update(); } - lowtic = GetLowTic(); + lowtic = get_low_tic(); - availabletics = lowtic - gametic/ticdup; + availabletics = lowtic - gametic / ticdup; - // decide how many tics to run + /* decide how many tics to run */ - if (new_sync) + if (new_sync) { - counts = availabletics; + counts = availabletics; } - else + else { - // decide how many tics to run - if (realtics < availabletics-1) - counts = realtics+1; - else if (realtics < availabletics) - counts = realtics; - else - counts = availabletics; + /* decide how many tics to run */ + + if (realtics < availabletics - 1) + counts = realtics + 1; + else if (realtics < availabletics) + counts = realtics; + else + counts = availabletics; - if (counts < 1) - counts = 1; + if (counts < 1) counts = 1; - if (net_client_connected) + if (net_client_connected) { - OldNetSync(); + old_net_sync(); } } - if (counts < 1) - counts = 1; + if (counts < 1) counts = 1; - // wait for new tics if needed - while (!PlayersInGame() || lowtic < gametic/ticdup + counts) + /* wait for new tics if needed */ + + while (!players_in_game() || lowtic < gametic / ticdup + counts) { - NetUpdate (); + net_update(); + + lowtic = get_low_tic(); - lowtic = GetLowTic(); + if (lowtic < gametic / ticdup) + i_error("try_run_tics: lowtic < gametic"); - if (lowtic < gametic/ticdup) - I_Error ("TryRunTics: lowtic < gametic"); + /* Still no tics to run? Sleep until some are available. */ - // Still no tics to run? Sleep until some are available. - if (lowtic < gametic/ticdup + counts) + if (lowtic < gametic / ticdup + counts) { - // If we're in a netgame, we might spin forever waiting for - // new network data to be received. So don't stay in here - // forever - give the menu a chance to work. - if (I_GetTime() / ticdup - entertic >= MAX_NETGAME_STALL_TICS) + /* If we're in a netgame, we might spin forever waiting for + * new network data to be received. So don't stay in here + * forever - give the menu a chance to work. + */ + + if (i_get_time() / ticdup - entertic >= MAX_NETGAME_STALL_TICS) { - return; + return; } - I_Sleep(1); + usleep(1000); } } - // run the count * ticdup dics - while (counts--) + /* run the count * ticdup dics */ + + while (counts--) { - ticcmd_set_t *set; + ticcmd_set_t *set; - if (!PlayersInGame()) + if (!players_in_game()) { - return; + return; } - set = &ticdata[(gametic / ticdup) % BACKUPTICS]; + set = &ticdata[(gametic / ticdup) % + CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; - if (!net_client_connected) + if (!net_client_connected) { - SinglePlayerClear(set); + single_player_clear(set); } - for (i=0 ; i lowtic) - I_Error ("gametic>lowtic"); + for (i = 0; i < ticdup; i++) + { + if (gametic / ticdup > lowtic) i_error("gametic>lowtic"); - memcpy(local_playeringame, set->ingame, sizeof(local_playeringame)); + memcpy(local_playeringame, set->ingame, + sizeof(local_playeringame)); - loop_interface->RunTic(set->cmds, set->ingame); - gametic++; + loop_interface->run_tic(set->cmds, set->ingame); + gametic++; - // modify command for duplicated tics + /* modify command for duplicated tics */ - TicdupSquash(set); - } + ticdup_squash(set); + } - NetUpdate (); // check for new console commands + net_update(); /* check for new console commands */ } } -void D_RegisterLoopCallbacks(loop_interface_t *i) +void d_register_loop_callbacks(loop_interface_t *i) { - loop_interface = i; + loop_interface = i; } -// TODO: Move nonvanilla demo functions into a dedicated file. -#include "m_misc.h" -#include "w_wad.h" - -static boolean StrictDemos(void) -{ - //! - // @category demo - // - // When recording or playing back demos, disable any extensions - // of the vanilla demo format - record demos as vanilla would do, - // and play back demos as vanilla would do. - // - return M_ParmExists("-strictdemos"); -} +/* If the provided conditional value is true, we're trying to record + * a demo file that will include a non-vanilla extension. The function + * will return true if the conditional is true and it's allowed to use + * this extension (no extensions are allowed if -strictdemos is given + * on the command line). A warning is shown on the console using the + * provided string describing the non-vanilla expansion. + */ -// If the provided conditional value is true, we're trying to record -// a demo file that will include a non-vanilla extension. The function -// will return true if the conditional is true and it's allowed to use -// this extension (no extensions are allowed if -strictdemos is given -// on the command line). A warning is shown on the console using the -// provided string describing the non-vanilla expansion. -boolean D_NonVanillaRecord(boolean conditional, const char *feature) +boolean d_non_vanilla_record(boolean conditional, const char *feature) { - if (!conditional || StrictDemos()) + if (!conditional || strict_demos()) { - return false; + return false; } - printf("Warning: Recording a demo file with a non-vanilla extension " - "(%s). Use -strictdemos to disable this extension.\n", - feature); + printf("Warning: Recording a demo file with a non-vanilla extension " + "(%s). Use -strictdemos to disable this extension.\n", + feature); - return true; + return true; } -// Returns true if the given lump number corresponds to data from a .lmp -// file, as opposed to a WAD. -static boolean IsDemoFile(int lumpnum) -{ - char *lower; - boolean result; - - lower = M_StringDuplicate(lumpinfo[lumpnum]->wad_file->path); - M_ForceLowercase(lower); - result = M_StringEndsWith(lower, ".lmp"); - free(lower); - - return result; -} - -// If the provided conditional value is true, we're trying to play back -// a demo that includes a non-vanilla extension. We return true if the -// conditional is true and it's allowed to use this extension, checking -// that: -// - The -strictdemos command line argument is not provided. -// - The given lumpnum identifying the demo to play back identifies a -// demo that comes from a .lmp file, not a .wad file. -// - Before proceeding, a warning is shown to the user on the console. -boolean D_NonVanillaPlayback(boolean conditional, int lumpnum, +/* If the provided conditional value is true, we're trying to play back + * a demo that includes a non-vanilla extension. We return true if the + * conditional is true and it's allowed to use this extension, checking + * that: + * - The -strictdemos command line argument is not provided. + * - The given lumpnum identifying the demo to play back identifies a + * demo that comes from a .lmp file, not a .wad file. + * - Before proceeding, a warning is shown to the user on the console. + */ + +boolean d_non_vanilla_playback(boolean conditional, int lumpnum, const char *feature) { - if (!conditional || StrictDemos()) + if (!conditional || strict_demos()) { - return false; + return false; } - if (!IsDemoFile(lumpnum)) + if (!is_demo_file(lumpnum)) { - printf("Warning: WAD contains demo with a non-vanilla extension " - "(%s)\n", feature); - return false; + printf("Warning: WAD contains demo with a non-vanilla extension " + "(%s)\n", + feature); + return false; } - printf("Warning: Playing back a demo file with a non-vanilla extension " - "(%s). Use -strictdemos to disable this extension.\n", - feature); + printf("Warning: Playing back a demo file with a non-vanilla extension " + "(%s). Use -strictdemos to disable this extension.\n", + feature); - return true; + return true; } - diff --git a/games/NXDoom/src/d_loop.h b/games/NXDoom/src/d_loop.h index c154be3a643..95c2f7a3c5a 100644 --- a/games/NXDoom/src/d_loop.h +++ b/games/NXDoom/src/d_loop.h @@ -1,96 +1,118 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Main loop stuff. -// +/**************************************************************************** + * apps/games/NXDoom/src/d_loop.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Main loop stuff. + * + ****************************************************************************/ #ifndef __D_LOOP__ #define __D_LOOP__ -#include "net_defs.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "m_fixed.h" +#include "net_defs.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ -// Callback function invoked while waiting for the netgame to start. -// The callback is invoked when new players are ready. The callback -// should return true, or return false to abort startup. +/* Callback function invoked while waiting for the netgame to start. + * The callback is invoked when new players are ready. The callback + * should return true, or return false to abort startup. + */ typedef boolean (*netgame_startup_callback_t)(int ready_players, int num_players); typedef struct { - // Read events from the event queue, and process them. + /* Read events from the event queue, and process them. */ - void (*ProcessEvents)(); + void (*process_events)(void); - // Given the current input state, fill in the fields of the specified - // ticcmd_t structure with data for a new tic. + /* Given the current input state, fill in the fields of the specified + * ticcmd_t structure with data for a new tic. + */ - void (*BuildTiccmd)(ticcmd_t *cmd, int maketic); + void (*build_ticcmd)(ticcmd_t *cmd, int maketic); - // Advance the game forward one tic, using the specified player input. + /* Advance the game forward one tic, using the specified player input. */ - void (*RunTic)(ticcmd_t *cmds, boolean *ingame); + void (*run_tic)(ticcmd_t *cmds, boolean *ingame); - // Run the menu (runs independently of the game). + /* Run the menu (runs independently of the game). */ - void (*RunMenu)(); + void (*run_menu)(void); } loop_interface_t; -// Register callback functions for the main loop code to use. -void D_RegisterLoopCallbacks(loop_interface_t *i); +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Create any new ticcmds and broadcast to other players. -void NetUpdate (void); +extern boolean singletics; +extern int gametic; +extern int ticdup; +extern fixed_t offsetms; -// Broadcasts special packets to other players -// to notify of game exit -void D_QuitNetGame (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -//? how many ticks to run? -void TryRunTics (void); +/* Register callback functions for the main loop code to use. */ -// Called at start of game loop to initialize timers -void D_StartGameLoop(void); +void d_register_loop_callbacks(loop_interface_t *i); -// Initialize networking code and connect to server. +/* Create any new ticcmds and broadcast to other players. */ -boolean D_InitNetGame(net_connect_data_t *connect_data); +void net_update(void); -// Start game with specified settings. The structure will be updated -// with the actual settings for the game. +/* ? how many ticks to run? */ -void D_StartNetGame(net_gamesettings_t *settings, - netgame_startup_callback_t callback); +void try_run_tics(void); -extern boolean singletics; -extern int gametic, ticdup; +/* Called at start of game loop to initialize timers */ -// Check if it is permitted to record a demo with a non-vanilla feature. -boolean D_NonVanillaRecord(boolean conditional, const char *feature); +void d_start_game_loop(void); -// Check if it is permitted to play back a demo with a non-vanilla feature. -boolean D_NonVanillaPlayback(boolean conditional, int lumpnum, - const char *feature); +/* Initialize networking code and connect to server. */ -void D_ReceiveTic(ticcmd_t *ticcmds, boolean *playeringame); +boolean d_init_net_game(net_connect_data_t *connect_data); +/* Start game with specified settings. The structure will be updated + * with the actual settings for the game. + */ -extern fixed_t offsetms; +void d_start_net_game(net_gamesettings_t *settings, + netgame_startup_callback_t callback); + +/* Check if it is permitted to record a demo with a non-vanilla feature. */ +boolean d_non_vanilla_record(boolean conditional, const char *feature); + +/* Check if it is permitted to play back a demo with a non-vanilla feature. */ + +boolean d_non_vanilla_playback(boolean conditional, int lumpnum, + const char *feature); -#endif +void d_receive_tic(ticcmd_t *ticcmds, boolean *playeringame); +#endif /* __D_LOOP__ */ diff --git a/games/NXDoom/src/d_mode.c b/games/NXDoom/src/d_mode.c index 95f6bb18248..6c4891cc1e0 100644 --- a/games/NXDoom/src/d_mode.c +++ b/games/NXDoom/src/d_mode.c @@ -1,233 +1,247 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: -// Functions and definitions relating to the game type and operational -// mode. -// +/**************************************************************************** + * apps/games/NXDoom/src/d_mode.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Functions and definitions relating to the game type and operational + * mode. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include "doomtype.h" #include "d_mode.h" +#include "doomtype.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Valid game mode/mission combinations, with the number of + * episodes/maps for each. + */ + +struct modemission +{ + gamemission_t mission; + game_mode_t mode; + int episode; + int map; +}; + +struct gameversion +{ + gamemission_t mission; + game_version_t version; +}; -// Valid game mode/mission combinations, with the number of -// episodes/maps for each. +/**************************************************************************** + * Private Data + ****************************************************************************/ -static struct +static struct modemission g_valid_modes[] = { - GameMission_t mission; - GameMode_t mode; - int episode; - int map; -} valid_modes[] = { - { pack_chex, retail, 1, 5 }, - { doom, shareware, 1, 9 }, - { doom, registered, 3, 9 }, - { doom, retail, 4, 9 }, - { doom2, commercial, 1, 32 }, - { pack_tnt, commercial, 1, 32 }, - { pack_plut, commercial, 1, 32 }, - { pack_hacx, commercial, 1, 32 }, - { heretic, shareware, 1, 9 }, - { heretic, registered, 3, 9 }, - { heretic, retail, 5, 9 }, - { hexen, commercial, 1, 60 }, - { strife, commercial, 1, 34 }, + {.mission = doom, .mode = shareware, .episode = 1, .map = 9}, + {.mission = doom, .mode = registered, .episode = 3, .map = 9}, + {.mission = doom, .mode = retail, .episode = 4, .map = 9}, + {.mission = doom2, .mode = commercial, .episode = 1, .map = 32}, }; -// Check that a gamemode+gamemission received over the network is valid. +/* Table of valid versions */ -boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode) +static struct gameversion g_valid_versions[] = { - int i; + {.mission = doom, .version = exe_doom_1_2}, + {.mission = doom, .version = exe_doom_1_5}, + {.mission = doom, .version = exe_doom_1_666}, + {.mission = doom, .version = exe_doom_1_7}, + {.mission = doom, .version = exe_doom_1_8}, + {.mission = doom, .version = exe_doom_1_9}, + {.mission = doom, .version = exe_hacx}, + {.mission = doom, .version = exe_ultimate}, + {.mission = doom, .version = exe_final}, + {.mission = doom, .version = exe_final2}, + {.mission = doom, .version = exe_chex}, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ - for (i=0; i= 1 && map <= 3; + return map >= 1 && map <= 3; } - else if (mode == registered && episode == 4) + else if (mode == registered && episode == 4) { - return map == 1; + return map == 1; } } - // Find the table entry for this mission/mode combination. + /* Find the table entry for this mission/mode combination. */ - for (i=0; i= 1 && episode <= valid_modes[i].episode - && map >= 1 && map <= valid_modes[i].map; + return episode >= 1 && episode <= g_valid_modes[i].episode && + map >= 1 && map <= g_valid_modes[i].map; } } - // Unknown mode/mission combination + /* Unknown mode/mission combination */ - return false; + return false; } -// Get the number of valid episodes for the specified mission/mode. +/* Get the number of valid episodes for the specified mission/mode. */ -int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode) +int d_get_num_episodes(gamemission_t mission, game_mode_t mode) { - int episode; + int episode; - episode = 1; + episode = 1; - while (D_ValidEpisodeMap(mission, mode, episode, 1)) + while (d_valid_episode_map(mission, mode, episode, 1)) { - ++episode; + ++episode; } - return episode - 1; + return episode - 1; } -// Table of valid versions - -static struct { - GameMission_t mission; - GameVersion_t version; -} valid_versions[] = { - { doom, exe_doom_1_2 }, - { doom, exe_doom_1_5 }, - { doom, exe_doom_1_666 }, - { doom, exe_doom_1_7 }, - { doom, exe_doom_1_8 }, - { doom, exe_doom_1_9 }, - { doom, exe_hacx }, - { doom, exe_ultimate }, - { doom, exe_final }, - { doom, exe_final2 }, - { doom, exe_chex }, - { heretic, exe_heretic_1_3 }, - { hexen, exe_hexen_1_1 }, - { hexen, exe_hexen_1_1r2 }, - { strife, exe_strife_1_2 }, - { strife, exe_strife_1_31 }, -}; - -boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version) +boolean d_valid_game_version(gamemission_t mission, game_version_t version) { - int i; + int i; - // All Doom variants can use the Doom versions. + /* All Doom variants can use the Doom versions. */ - if (mission == doom2 || mission == pack_plut || mission == pack_tnt - || mission == pack_hacx || mission == pack_chex) + if (mission == doom2 || mission == pack_plut || mission == pack_tnt || + mission == pack_hacx || mission == pack_chex) { - mission = doom; + mission = doom; } - for (i=0; i #include #include #include #include -#include #include "m_misc.h" #include "w_wad.h" @@ -28,330 +37,356 @@ #include "deh_defs.h" #include "deh_io.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef enum { - DEH_INPUT_FILE, - DEH_INPUT_LUMP + DEH_INPUT_FILE, + DEH_INPUT_LUMP } deh_input_type_t; struct deh_context_s { - deh_input_type_t type; - char *filename; - - // If the input comes from a memory buffer, pointer to the memory - // buffer. - unsigned char *input_buffer; - size_t input_buffer_len; - unsigned int input_buffer_pos; - int lumpnum; - - // If the input comes from a file, the file stream for reading - // data. - FILE *stream; - - // Current line number that we have reached: - int linenum; - - // Used by DEH_ReadLine: - boolean last_was_newline; - char *readbuffer; - int readbuffer_size; - - // Error handling. - boolean had_error; + deh_input_type_t type; + char *filename; + + /* If the input comes from a memory buffer, pointer to the memory + * buffer. + */ + + unsigned char *input_buffer; + size_t input_buffer_len; + unsigned int input_buffer_pos; + int lumpnum; + + /* If the input comes from a file, the file stream for reading + * data. + */ + + FILE *stream; + + /* Current line number that we have reached: */ + + int linenum; + + /* Used by deh_read_line: */ + + boolean last_was_newline; + char *readbuffer; + int readbuffer_size; + + /* Error handling. */ + + boolean had_error; }; -static deh_context_t *DEH_NewContext(void) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static deh_context_t *deh_new_context(void) { - deh_context_t *context; + deh_context_t *context; + + context = z_malloc(sizeof(*context), PU_STATIC, NULL); + + /* Initial read buffer size of 128 bytes */ + + context->readbuffer_size = 128; + context->readbuffer = z_malloc(context->readbuffer_size, PU_STATIC, NULL); + context->linenum = 0; + context->last_was_newline = true; - context = Z_Malloc(sizeof(*context), PU_STATIC, NULL); + context->had_error = false; + + return context; +} + +/* Increase the read buffer size */ + +static void increase_read_buffer(deh_context_t *context) +{ + char *newbuffer; + int newbuffer_size; - // Initial read buffer size of 128 bytes + newbuffer_size = context->readbuffer_size * 2; + newbuffer = z_malloc(newbuffer_size, PU_STATIC, NULL); - context->readbuffer_size = 128; - context->readbuffer = Z_Malloc(context->readbuffer_size, PU_STATIC, NULL); - context->linenum = 0; - context->last_was_newline = true; + memcpy(newbuffer, context->readbuffer, context->readbuffer_size); - context->had_error = false; + z_free(context->readbuffer); - return context; + context->readbuffer = newbuffer; + context->readbuffer_size = newbuffer_size; } -// Open a dehacked file for reading -// Returns NULL if open failed +/**************************************************************************** + * Public Functions + ****************************************************************************/ -deh_context_t *DEH_OpenFile(const char *filename) +/* Open a dehacked file for reading + * Returns NULL if open failed + */ + +deh_context_t *deh_open_file(const char *filename) { - FILE *fstream; - deh_context_t *context; + FILE *fstream; + deh_context_t *context; - fstream = M_fopen(filename, "r"); + fstream = fopen(filename, "r"); - if (fstream == NULL) - return NULL; + if (fstream == NULL) return NULL; - context = DEH_NewContext(); + context = deh_new_context(); - context->type = DEH_INPUT_FILE; - context->stream = fstream; - context->filename = M_StringDuplicate(filename); + context->type = DEH_INPUT_FILE; + context->stream = fstream; + context->filename = m_string_duplicate(filename); - return context; + return context; } -// Open a WAD lump for reading. +/* Open a WAD lump for reading. */ -deh_context_t *DEH_OpenLump(int lumpnum) +deh_context_t *deh_open_lump(int lumpnum) { - deh_context_t *context; - void *lump; + deh_context_t *context; + void *lump; - lump = W_CacheLumpNum(lumpnum, PU_STATIC); + lump = w_cache_lump_num(lumpnum, PU_STATIC); - context = DEH_NewContext(); + context = deh_new_context(); - context->type = DEH_INPUT_LUMP; - context->lumpnum = lumpnum; - context->input_buffer = lump; - context->input_buffer_len = W_LumpLength(lumpnum); - context->input_buffer_pos = 0; + context->type = DEH_INPUT_LUMP; + context->lumpnum = lumpnum; + context->input_buffer = lump; + context->input_buffer_len = w_lump_length(lumpnum); + context->input_buffer_pos = 0; - context->filename = malloc(9); - M_StringCopy(context->filename, lumpinfo[lumpnum]->name, 9); + context->filename = malloc(9); + m_str_copy(context->filename, lumpinfo[lumpnum]->name, 9); - return context; + return context; } -// Close dehacked file +/* Close dehacked file */ -void DEH_CloseFile(deh_context_t *context) +void deh_close_file(deh_context_t *context) { - if (context->type == DEH_INPUT_FILE) + if (context->type == DEH_INPUT_FILE) { - fclose(context->stream); + fclose(context->stream); } - else if (context->type == DEH_INPUT_LUMP) + else if (context->type == DEH_INPUT_LUMP) { - W_ReleaseLumpNum(context->lumpnum); + w_release_lump_num(context->lumpnum); } - free(context->filename); - Z_Free(context->readbuffer); - Z_Free(context); + free(context->filename); + z_free(context->readbuffer); + z_free(context); } -int DEH_GetCharFile(deh_context_t *context) +int deh_get_char_file(deh_context_t *context) { - if (feof(context->stream)) + if (feof(context->stream)) { - // end of file + /* end of file */ - return -1; + return -1; } - return fgetc(context->stream); + return fgetc(context->stream); } -int DEH_GetCharLump(deh_context_t *context) +int deh_get_char_lump(deh_context_t *context) { - int result; + int result; - if (context->input_buffer_pos >= context->input_buffer_len) + if (context->input_buffer_pos >= context->input_buffer_len) { - return -1; + return -1; } - result = context->input_buffer[context->input_buffer_pos]; - ++context->input_buffer_pos; + result = context->input_buffer[context->input_buffer_pos]; + ++context->input_buffer_pos; - return result; + return result; } -// Reads a single character from a dehacked file +/* Reads a single character from a dehacked file */ -int DEH_GetChar(deh_context_t *context) +int deh_get_char(deh_context_t *context) { - int result = 0; - boolean last_was_cr = false; + int result = 0; + boolean last_was_cr = false; - // Track the current line number + /* Track the current line number */ - if (context->last_was_newline) + if (context->last_was_newline) { - ++context->linenum; + ++context->linenum; } - // Read characters, converting CRLF to LF + /* Read characters, converting CRLF to LF */ - do + do { - switch (context->type) + switch (context->type) { - case DEH_INPUT_FILE: - result = DEH_GetCharFile(context); - break; + case DEH_INPUT_FILE: + result = deh_get_char_file(context); + break; - case DEH_INPUT_LUMP: - result = DEH_GetCharLump(context); - break; + case DEH_INPUT_LUMP: + result = deh_get_char_lump(context); + break; } - // Handle \r characters not paired with \n - if (last_was_cr && result != '\n') + /* Handle \r characters not paired with \n */ + + if (last_was_cr && result != '\n') { - switch (context->type) + switch (context->type) { - case DEH_INPUT_FILE: - ungetc(result, context->stream); - break; + case DEH_INPUT_FILE: + ungetc(result, context->stream); + break; - case DEH_INPUT_LUMP: - --context->input_buffer_pos; - break; + case DEH_INPUT_LUMP: + --context->input_buffer_pos; + break; } - return '\r'; + return '\r'; } - last_was_cr = result == '\r'; - - } while (last_was_cr); - - context->last_was_newline = result == '\n'; - - return result; -} - -// Increase the read buffer size - -static void IncreaseReadBuffer(deh_context_t *context) -{ - char *newbuffer; - int newbuffer_size; - - newbuffer_size = context->readbuffer_size * 2; - newbuffer = Z_Malloc(newbuffer_size, PU_STATIC, NULL); - - memcpy(newbuffer, context->readbuffer, context->readbuffer_size); + last_was_cr = result == '\r'; + } + while (last_was_cr); - Z_Free(context->readbuffer); + context->last_was_newline = result == '\n'; - context->readbuffer = newbuffer; - context->readbuffer_size = newbuffer_size; + return result; } -// Read a whole line +/* Read a whole line */ -char *DEH_ReadLine(deh_context_t *context, boolean extended) +char *deh_read_line(deh_context_t *context, boolean extended) { - int c; - int pos; - boolean escaped = false; + int c; + int pos; + boolean escaped = false; - for (pos = 0;;) + for (pos = 0; ; ) { - c = DEH_GetChar(context); + c = deh_get_char(context); - if (c < 0 && pos == 0) + if (c < 0 && pos == 0) { - // end of file + /* end of file */ - return NULL; + return NULL; } - // cope with lines of any length: increase the buffer size + /* cope with lines of any length: increase the buffer size */ - if (pos >= context->readbuffer_size) + if (pos >= context->readbuffer_size) { - IncreaseReadBuffer(context); + increase_read_buffer(context); } - // extended string support - if (extended && c == '\\') + /* extended string support */ + + if (extended && c == '\\') { - c = DEH_GetChar(context); + c = deh_get_char(context); - // "\n" in the middle of a string indicates an internal linefeed - if (c == 'n') + /* "\n" in the middle of a string indicates an internal linefeed */ + + if (c == 'n') { - context->readbuffer[pos] = '\n'; - ++pos; - continue; + context->readbuffer[pos] = '\n'; + ++pos; + continue; } - // values to be assigned may be split onto multiple lines by ending - // each line that is to be continued with a backslash - if (c == '\n') + /* values to be assigned may be split onto multiple lines by ending + * each line that is to be continued with a backslash + */ + + if (c == '\n') { - escaped = true; - continue; + escaped = true; + continue; } } - // blanks before the backslash are included in the string - // but indentation after the linefeed is not - if (escaped && c >= 0 && isspace(c) && c != '\n') + /* blanks before the backslash are included in the string + * but indentation after the linefeed is not + */ + + if (escaped && c >= 0 && isspace(c) && c != '\n') { - continue; + continue; } - else + else { - escaped = false; + escaped = false; } - if (c == '\n' || c < 0) + if (c == '\n' || c < 0) { - // end of line: a full line has been read + /* end of line: a full line has been read */ - context->readbuffer[pos] = '\0'; - break; + context->readbuffer[pos] = '\0'; + break; } - else if (c != '\0') + else if (c != '\0') { - // normal character; don't allow NUL characters to be - // added. + /* normal character; don't allow NUL characters to be + * added. + */ - context->readbuffer[pos] = (char) c; - ++pos; + context->readbuffer[pos] = (char)c; + ++pos; } } - - return context->readbuffer; + + return context->readbuffer; } -void DEH_Warning(deh_context_t *context, const char *msg, ...) +void deh_warning(deh_context_t *context, const char *msg, ...) { - va_list args; + va_list args; - va_start(args, msg); + va_start(args, msg); - fprintf(stderr, "%s:%i: warning: ", context->filename, context->linenum); - vfprintf(stderr, msg, args); - fprintf(stderr, "\n"); + fprintf(stderr, "%s:%i: warning: ", context->filename, context->linenum); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n"); - va_end(args); + va_end(args); } -void DEH_Error(deh_context_t *context, const char *msg, ...) +void deh_error(deh_context_t *context, const char *msg, ...) { - va_list args; + va_list args; - va_start(args, msg); + va_start(args, msg); - fprintf(stderr, "%s:%i: ", context->filename, context->linenum); - vfprintf(stderr, msg, args); - fprintf(stderr, "\n"); + fprintf(stderr, "%s:%i: ", context->filename, context->linenum); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n"); - va_end(args); + va_end(args); - context->had_error = true; + context->had_error = true; } -boolean DEH_HadError(deh_context_t *context) +boolean deh_had_error(deh_context_t *context) { - return context->had_error; + return context->had_error; } - diff --git a/games/NXDoom/src/deh_io.h b/games/NXDoom/src/deh_io.h index de6720e61f6..8ee12b5c0f5 100644 --- a/games/NXDoom/src/deh_io.h +++ b/games/NXDoom/src/deh_io.h @@ -1,33 +1,46 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dehacked I/O code (does all reads from dehacked files) -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_io.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Dehacked I/O code (does all reads from dehacked files) + * + ****************************************************************************/ #ifndef DEH_IO_H #define DEH_IO_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "deh_defs.h" -deh_context_t *DEH_OpenFile(const char *filename); -deh_context_t *DEH_OpenLump(int lumpnum); -void DEH_CloseFile(deh_context_t *context); -int DEH_GetChar(deh_context_t *context); -char *DEH_ReadLine(deh_context_t *context, boolean extended); -void DEH_Error(deh_context_t *context, const char *msg, ...) PRINTF_ATTR(2, 3); -void DEH_Warning(deh_context_t *context, const char *msg, ...) PRINTF_ATTR(2, 3); -boolean DEH_HadError(deh_context_t *context); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef DEH_IO_H */ +deh_context_t *deh_open_file(const char *filename); +deh_context_t *deh_open_lump(int lumpnum); +void deh_close_file(deh_context_t *context); +int deh_get_char(deh_context_t *context); +char *deh_read_line(deh_context_t *context, boolean extended); +void deh_error(deh_context_t *context, const char *msg, ...) + PRINTF_ATTR(2, 3); +void deh_warning(deh_context_t *context, const char *msg, ...) + PRINTF_ATTR(2, 3); +boolean deh_had_error(deh_context_t *context); +#endif /* DEH_IO_H */ diff --git a/games/NXDoom/src/deh_main.c b/games/NXDoom/src/deh_main.c index 3ef8a25c323..f6eb667ac54 100644 --- a/games/NXDoom/src/deh_main.c +++ b/games/NXDoom/src/deh_main.c @@ -1,29 +1,37 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Main dehacked code -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_main.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Main dehacked code + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include +#include "d_iwad.h" #include "doomtype.h" #include "i_glob.h" #include "i_system.h" -#include "d_iwad.h" #include "m_argv.h" #include "w_wad.h" @@ -31,489 +39,516 @@ #include "deh_io.h" #include "deh_main.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ static boolean deh_initialized = false; -// If true, we can parse [STRINGS] sections in BEX format. +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* If true, we can parse [STRINGS] sections in BEX format. */ boolean deh_allow_extended_strings = false; -// If true, we can do long string replacements. +/* If true, we can do long string replacements. */ boolean deh_allow_long_strings = false; -// If true, we can do cheat replacements longer than the originals. +/* If true, we can do cheat replacements longer than the originals. */ boolean deh_allow_long_cheats = false; -// If false, dehacked cheat replacements are ignored. +/* If false, dehacked cheat replacements are ignored. */ boolean deh_apply_cheats = true; -void DEH_Checksum(sha1_digest_t digest) -{ - sha1_context_t sha1_context; - unsigned int i; - - SHA1_Init(&sha1_context); - - for (i=0; deh_section_types[i] != NULL; ++i) - { - if (deh_section_types[i]->sha1_hash != NULL) - { - deh_section_types[i]->sha1_hash(&sha1_context); - } - } - - SHA1_Final(digest, &sha1_context); -} +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// Called on startup to call the Init functions +/* Called on startup to call the Init functions */ -static void InitializeSections(void) +static void initialize_sections(void) { - unsigned int i; + unsigned int i; - for (i=0; deh_section_types[i] != NULL; ++i) + for (i = 0; deh_section_types[i] != NULL; ++i) { - if (deh_section_types[i]->init != NULL) + if (deh_section_types[i]->init != NULL) { - deh_section_types[i]->init(); + deh_section_types[i]->init(); } } } -static void DEH_Init(void) +static void deh_init(void) { - //! - // @category mod - // - // Ignore cheats in dehacked files. - // + /* @category mod + * + * Ignore cheats in dehacked files. + */ - if (M_CheckParm("-nocheats") > 0) + if (m_check_parm("-nocheats") > 0) { - deh_apply_cheats = false; + deh_apply_cheats = false; } - // Call init functions for all the section definitions. - InitializeSections(); + /* Call init functions for all the section definitions. */ - deh_initialized = true; + initialize_sections(); + + deh_initialized = true; } -// Given a section name, get the section structure which corresponds +/* Given a section name, get the section structure which corresponds */ -static deh_section_t *GetSectionByName(char *name) +static deh_section_t *get_section_by_name(char *name) { - unsigned int i; + unsigned int i; - // we explicitely do not recognize [STRINGS] sections at all - // if extended strings are not allowed + /* we explicitly do not recognize [STRINGS] sections at all + * if extended strings are not allowed + */ - if (!deh_allow_extended_strings && !strncasecmp("[STRINGS]", name, 9)) + if (!deh_allow_extended_strings && !strncasecmp("[STRINGS]", name, 9)) { - return NULL; + return NULL; } - for (i=0; deh_section_types[i] != NULL; ++i) + for (i = 0; deh_section_types[i] != NULL; ++i) { - if (!strcasecmp(deh_section_types[i]->name, name)) + if (!strcasecmp(deh_section_types[i]->name, name)) { - return deh_section_types[i]; + return deh_section_types[i]; } } - return NULL; + return NULL; } -// Is the string passed just whitespace? +/* Is the string passed just whitespace? */ -static boolean IsWhitespace(char *s) +static boolean is_whitespace(char *s) { - for (; *s; ++s) + for (; *s; ++s) { - if (!isspace(*s)) - return false; + if (!isspace(*s)) return false; } - return true; + return true; } -// Strip whitespace from the start and end of a string +/* Strip whitespace from the start and end of a string */ -static char *CleanString(char *s) +static char *clean_string(char *s) { - char *strending; - - // Leading whitespace + char *strending; - while (*s && isspace(*s)) - ++s; + /* Leading whitespace */ - // Trailing whitespace - - strending = s + strlen(s) - 1; - - while (strlen(s) > 0 && isspace(*strending)) - { - *strending = '\0'; - --strending; - } - - return s; -} + while (*s && isspace(*s)) + ++s; -// This pattern is used a lot of times in different sections, -// an assignment is essentially just a statement of the form: -// -// Variable Name = Value -// -// The variable name can include spaces or any other characters. -// The string is split on the '=', essentially. -// -// Returns true if read correctly - -boolean DEH_ParseAssignment(char *line, char **variable_name, char **value) -{ - char *p; + /* Trailing whitespace */ - // find the equals - - p = strchr(line, '='); + strending = s + strlen(s) - 1; - if (p == NULL) + while (strlen(s) > 0 && isspace(*strending)) { - return false; + *strending = '\0'; + --strending; } - // variable name at the start - // turn the '=' into a \0 to terminate the string here - - *p = '\0'; - *variable_name = CleanString(line); - - // value immediately follows the '=' - - *value = CleanString(p+1); - - return true; + return s; } -static boolean CheckSignatures(deh_context_t *context) +static boolean check_signatures(deh_context_t *context) { - size_t i; - char *line; - - // Read the first line + size_t i; + char *line; + + /* Read the first line */ - line = DEH_ReadLine(context, false); + line = deh_read_line(context, false); - if (line == NULL) + if (line == NULL) { - return false; + return false; } - // Check all signatures to see if one matches + /* Check all signatures to see if one matches */ - for (i=0; deh_signatures[i] != NULL; ++i) + for (i = 0; deh_signatures[i] != NULL; ++i) { - if (!strcmp(deh_signatures[i], line)) + if (!strcmp(deh_signatures[i], line)) { - return true; + return true; } } - return false; + return false; } -// Parses a comment string in a dehacked file. +/* Parses a comment string in a dehacked file. */ -static void DEH_ParseComment(char *comment) +static void deh_parse_comment(char *comment) { - // - // Welcome, to the super-secret Chocolate Doom-specific Dehacked - // overrides function. - // - // Putting these magic comments into your Dehacked lumps will - // allow you to go beyond the normal limits of Vanilla Dehacked. - // Because of this, these comments are deliberately undocumented, - // and if you're using them you should be aware that your mod - // is not compatible with Vanilla Doom and you're probably a - // very naughty person. - // - - // Allow comments containing this special value to allow string - // replacements longer than those permitted by DOS dehacked. - // This allows us to use a dehacked patch for doing string - // replacements for emulating Chex Quest. - // - // If you use this, your dehacked patch may not work in Vanilla - // Doom. - - if (strstr(comment, "*allow-long-strings*") != NULL) + /* Welcome, to the super-secret Chocolate Doom-specific Dehacked + * overrides function. + * + * Putting these magic comments into your Dehacked lumps will + * allow you to go beyond the normal limits of Vanilla Dehacked. + * Because of this, these comments are deliberately undocumented, + * and if you're using them you should be aware that your mod + * is not compatible with Vanilla Doom and you're probably a + * very naughty person. + * + + * Allow comments containing this special value to allow string + * replacements longer than those permitted by DOS dehacked. + * This allows us to use a dehacked patch for doing string + * replacements for emulating Chex Quest. + * + * If you use this, your dehacked patch may not work in Vanilla + * Doom. + */ + + if (strstr(comment, "*allow-long-strings*") != NULL) { - deh_allow_long_strings = true; + deh_allow_long_strings = true; } - // Allow magic comments to allow longer cheat replacements than - // those permitted by DOS dehacked. This is also for Chex - // Quest. + /* Allow magic comments to allow longer cheat replacements than + * those permitted by DOS dehacked. This is also for Chex + * Quest. + */ - if (strstr(comment, "*allow-long-cheats*") != NULL) + if (strstr(comment, "*allow-long-cheats*") != NULL) { - deh_allow_long_cheats = true; + deh_allow_long_cheats = true; } - // Allow magic comments to allow parsing [STRINGS] section - // that are usually only found in BEX format files. This allows - // for substitution of map and episode names when loading - // Freedoom/FreeDM IWADs. + /* Allow magic comments to allow parsing [STRINGS] section + * that are usually only found in BEX format files. This allows + * for substitution of map and episode names when loading + * Freedoom/FreeDM IWADs. + */ - if (strstr(comment, "*allow-extended-strings*") != NULL) + if (strstr(comment, "*allow-extended-strings*") != NULL) { - deh_allow_extended_strings = true; + deh_allow_extended_strings = true; } } -// Parses a dehacked file by reading from the context +/* Parses a dehacked file by reading from the context */ -static void DEH_ParseContext(deh_context_t *context) +static void deh_parse_context(deh_context_t *context) { - deh_section_t *current_section = NULL; - char section_name[20]; - void *tag = NULL; - boolean extended; - char *line; + deh_section_t *current_section = NULL; + char section_name[20]; + void *tag = NULL; + boolean extended; + char *line; - // Read the header and check it matches the signature + /* Read the header and check it matches the signature */ - if (!CheckSignatures(context)) + if (!check_signatures(context)) { - DEH_Error(context, "This is not a valid dehacked patch file!"); + deh_error(context, "This is not a valid dehacked patch file!"); } - // Read the file + /* Read the file */ - while (!DEH_HadError(context)) + while (!deh_had_error(context)) { - // Read the next line. We only allow the special extended parsing - // for the BEX [STRINGS] section. - extended = current_section != NULL - && !strcasecmp(current_section->name, "[STRINGS]"); - line = DEH_ReadLine(context, extended); + /* Read the next line. We only allow the special extended parsing + * for the BEX [STRINGS] section. + */ - // end of file? + extended = current_section != NULL && + !strcasecmp(current_section->name, "[STRINGS]"); + line = deh_read_line(context, extended); - if (line == NULL) + /* end of file? */ + + if (line == NULL) { - return; + return; } - while (line[0] != '\0' && isspace(line[0])) - ++line; + while (line[0] != '\0' && isspace(line[0])) + ++line; - if (line[0] == '#') + if (line[0] == '#') { - // comment + /* comment */ - DEH_ParseComment(line); - continue; + deh_parse_comment(line); + continue; } - if (IsWhitespace(line)) + if (is_whitespace(line)) { - if (current_section != NULL) + if (current_section != NULL) { - // end of section + /* end of section */ - if (current_section->end != NULL) + if (current_section->end != NULL) { - current_section->end(context, tag); + current_section->end(context, tag); } - //printf("end %s tag\n", current_section->name); - current_section = NULL; + current_section = NULL; } } - else + else { - if (current_section != NULL) + if (current_section != NULL) { - // parse this line + /* parse this line */ - current_section->line_parser(context, line, tag); + current_section->line_parser(context, line, tag); } - else + else { - // possibly the start of a new section + /* possibly the start of a new section */ - sscanf(line, "%19s", section_name); + sscanf(line, "%19s", section_name); - current_section = GetSectionByName(section_name); + current_section = get_section_by_name(section_name); - if (current_section != NULL) + if (current_section != NULL) { - tag = current_section->start(context, line); - //printf("started %s tag\n", section_name); + tag = current_section->start(context, line); } - else + else { - //printf("unknown section name %s\n", section_name); + /* printf("unknown section name %s\n", section_name); */ } } } } } -// Parses a dehacked file +/**************************************************************************** + * Public Functions + ****************************************************************************/ -int DEH_LoadFile(const char *filename) +void deh_checksum(sha1_digest_t digest) { - deh_context_t *context; - boolean had_error; + SHA1_CTX sha1_context; + unsigned int i; + + sha1init(&sha1_context); - if (!deh_initialized) + for (i = 0; deh_section_types[i] != NULL; ++i) { - DEH_Init(); + if (deh_section_types[i]->sha1_hash != NULL) + { + deh_section_types[i]->sha1_hash(&sha1_context); + } } - // Before parsing a new file, reset special override flags to false. - // Magic comments should only apply to the file in which they were - // defined, and shouldn't carry over to subsequent files as well. - deh_allow_long_strings = false; - deh_allow_long_cheats = false; - deh_allow_extended_strings = false; + sha1final(digest, &sha1_context); +} - printf(" loading %s\n", filename); +/* This pattern is used a lot of times in different sections, + * an assignment is essentially just a statement of the form: + * + * Variable Name = Value + * + * The variable name can include spaces or any other characters. + * The string is split on the '=', essentially. + * + * Returns true if read correctly + */ + +boolean deh_parse_assignment(char *line, char **variable_name, char **value) +{ + char *p; + + /* find the equals */ - context = DEH_OpenFile(filename); + p = strchr(line, '='); - if (context == NULL) + if (p == NULL) { - fprintf(stderr, "DEH_LoadFile: Unable to open %s\n", filename); - return 0; + return false; } - DEH_ParseContext(context); + /* variable name at the start + * turn the '=' into a \0 to terminate the string here + */ + + *p = '\0'; + *variable_name = clean_string(line); + + /* value immediately follows the '=' */ + + *value = clean_string(p + 1); + + return true; +} - had_error = DEH_HadError(context); +/* Parses a dehacked file */ - DEH_CloseFile(context); +int deh_loadfile(const char *filename) +{ + deh_context_t *context; + boolean had_error; - if (had_error) + if (!deh_initialized) { - I_Error("Error parsing dehacked file"); + deh_init(); } - return 1; + /* Before parsing a new file, reset special override flags to false. + * Magic comments should only apply to the file in which they were + * defined, and shouldn't carry over to subsequent files as well. + */ + + deh_allow_long_strings = false; + deh_allow_long_cheats = false; + deh_allow_extended_strings = false; + + printf(" loading %s\n", filename); + + context = deh_open_file(filename); + + if (context == NULL) + { + fprintf(stderr, "deh_loadfile: Unable to open %s\n", filename); + return 0; + } + + deh_parse_context(context); + + had_error = deh_had_error(context); + + deh_close_file(context); + + if (had_error) + { + i_error("Error parsing dehacked file"); + } + + return 1; } -// Load all dehacked patches from the given directory. -void DEH_AutoLoadPatches(const char *path) +/* Load all dehacked patches from the given directory. */ + +void deh_auto_load_patches(const char *path) { - const char *filename; - glob_t *glob; + const char *filename; + glob_t *glob; - glob = I_StartMultiGlob(path, GLOB_FLAG_NOCASE|GLOB_FLAG_SORTED, + glob = i_start_multi_glob(path, GLOB_FLAG_NOCASE | GLOB_FLAG_SORTED, "*.deh", "*.hhe", "*.seh", NULL); - for (;;) + for (; ; ) { - filename = I_NextGlob(glob); - if (filename == NULL) + filename = i_next_glob(glob); + if (filename == NULL) { - break; + break; } - printf(" [autoload]"); - DEH_LoadFile(filename); + + printf(" [autoload]"); + deh_loadfile(filename); } - I_EndGlob(glob); + i_end_glob(glob); } -// Load dehacked file from WAD lump. -// If allow_long is set, allow long strings and cheats just for this lump. +/* Load dehacked file from WAD lump. + * If allow_long is set, allow long strings and cheats just for this lump. + */ -int DEH_LoadLump(int lumpnum, boolean allow_long, boolean allow_error) +int deh_load_lump(int lumpnum, boolean allow_long, boolean allow_error) { - deh_context_t *context; - boolean had_error; + deh_context_t *context; + boolean had_error; - if (!deh_initialized) + if (!deh_initialized) { - DEH_Init(); + deh_init(); } - // Reset all special flags to defaults. - deh_allow_long_strings = allow_long; - deh_allow_long_cheats = allow_long; - deh_allow_extended_strings = false; + /* Reset all special flags to defaults. */ + + deh_allow_long_strings = allow_long; + deh_allow_long_cheats = allow_long; + deh_allow_extended_strings = false; - context = DEH_OpenLump(lumpnum); + context = deh_open_lump(lumpnum); - if (context == NULL) + if (context == NULL) { - fprintf(stderr, "DEH_LoadFile: Unable to open lump %i\n", lumpnum); - return 0; + fprintf(stderr, "deh_loadfile: Unable to open lump %i\n", lumpnum); + return 0; } - DEH_ParseContext(context); + deh_parse_context(context); - had_error = DEH_HadError(context); + had_error = deh_had_error(context); - DEH_CloseFile(context); + deh_close_file(context); - // If there was an error while parsing, abort with an error, but allow - // errors to just be ignored if allow_error=true. - if (!allow_error && had_error) + /* If there was an error while parsing, abort with an error, but allow + * errors to just be ignored if allow_error=true. + */ + + if (!allow_error && had_error) { - I_Error("Error parsing dehacked lump"); + i_error("Error parsing dehacked lump"); } - return 1; + return 1; } -int DEH_LoadLumpByName(const char *name, boolean allow_long, boolean allow_error) +int deh_load_lump_by_name(const char *name, boolean allow_long, + boolean allow_error) { - int lumpnum; + int lumpnum; - lumpnum = W_CheckNumForName(name); + lumpnum = w_check_num_for_name(name); - if (lumpnum == -1) + if (lumpnum == -1) { - fprintf(stderr, "DEH_LoadLumpByName: '%s' lump not found\n", name); - return 0; + fprintf(stderr, "deh_load_lump_by_name: '%s' lump not found\n", name); + return 0; } - return DEH_LoadLump(lumpnum, allow_long, allow_error); + return deh_load_lump(lumpnum, allow_long, allow_error); } -// Check the command line for -deh argument, and others. -void DEH_ParseCommandLine(void) +/* Check the command line for -deh argument, and others. */ + +void deh_parse_command_line(void) { - char *filename; - int p; + char *filename; + int p; - //! - // @arg - // @category mod - // - // Load the given dehacked patch(es) - // + /* @arg + * @category mod + * + * Load the given dehacked patch(es) + */ - p = M_CheckParm("-deh"); + p = m_check_parm("-deh"); - if (p > 0) + if (p > 0) { - ++p; + ++p; - while (p < myargc && myargv[p][0] != '-') + while (p < myargc && myargv[p][0] != '-') { - filename = D_TryFindWADByName(myargv[p]); - DEH_LoadFile(filename); - free(filename); - ++p; + filename = d_try_find_wad_by_name(myargv[p]); + deh_loadfile(filename); + free(filename); + ++p; } } } - diff --git a/games/NXDoom/src/deh_main.h b/games/NXDoom/src/deh_main.h index 9ab8704020a..8ae728243ca 100644 --- a/games/NXDoom/src/deh_main.h +++ b/games/NXDoom/src/deh_main.h @@ -1,48 +1,69 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dehacked entrypoint and common code -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_main.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Dehacked entrypoint and common code + * + ****************************************************************************/ #ifndef DEH_MAIN_H #define DEH_MAIN_H -#include "doomtype.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "deh_str.h" +#include "doomtype.h" #include "sha1.h" -// These are the limits that dehacked uses (from dheinit.h in the dehacked -// source). If these limits are exceeded, it does not generate an error, but -// a warning is displayed. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* These are the limits that dehacked uses (from dheinit.h in the dehacked + * source). If these limits are exceeded, it does not generate an error, but + * a warning is displayed. + */ #define DEH_VANILLA_NUMSTATES 966 #define DEH_VANILLA_NUMSFX 107 -void DEH_ParseCommandLine(void); -int DEH_LoadFile(const char *filename); -void DEH_AutoLoadPatches(const char *path); -int DEH_LoadLump(int lumpnum, boolean allow_long, boolean allow_error); -int DEH_LoadLumpByName(const char *name, boolean allow_long, boolean allow_error); - -boolean DEH_ParseAssignment(char *line, char **variable_name, char **value); - -void DEH_Checksum(sha1_digest_t digest); +/**************************************************************************** + * Public Data + ****************************************************************************/ extern boolean deh_allow_extended_strings; extern boolean deh_allow_long_strings; extern boolean deh_allow_long_cheats; extern boolean deh_apply_cheats; -#endif /* #ifndef DEH_MAIN_H */ +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void deh_parse_command_line(void); +int deh_loadfile(const char *filename); +void deh_auto_load_patches(const char *path); +int deh_load_lump(int lumpnum, boolean allow_long, boolean allow_error); +int deh_load_lump_by_name(const char *name, boolean allow_long, + boolean allow_error); + +boolean deh_parse_assignment(char *line, char **variable_name, char **value); + +void deh_checksum(sha1_digest_t digest); +#endif /* DEH_MAIN_H */ diff --git a/games/NXDoom/src/deh_mapping.c b/games/NXDoom/src/deh_mapping.c index f96508b9c7d..17bed207421 100644 --- a/games/NXDoom/src/deh_mapping.c +++ b/games/NXDoom/src/deh_mapping.c @@ -1,21 +1,29 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dehacked "mapping" code -// Allows the fields in structures to be mapped out and accessed by -// name -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_mapping.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Dehacked "mapping" code + * Allows the fields in structures to be mapped out and accessed by + * name + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -27,174 +35,172 @@ #include "deh_mapping.h" -static deh_mapping_entry_t *GetMappingEntryByName(deh_context_t *context, - deh_mapping_t *mapping, - char *name) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static deh_mapping_entry_t *get_mapping_entry_by_name(deh_context_t *context, + deh_mapping_t *mapping, + char *name) { - int i; + int i; - for (i=0; mapping->entries[i].name != NULL; ++i) + for (i = 0; mapping->entries[i].name != NULL; ++i) { - deh_mapping_entry_t *entry = &mapping->entries[i]; + deh_mapping_entry_t *entry = &mapping->entries[i]; - if (!strcasecmp(entry->name, name)) + if (!strcasecmp(entry->name, name)) { - if (entry->location == NULL) + if (entry->location == NULL) { - DEH_Warning(context, "Field '%s' is unsupported", name); - return NULL; + deh_warning(context, "Field '%s' is unsupported", name); + return NULL; } - return entry; + return entry; } } - // Not found. + /* Not found. */ - DEH_Warning(context, "Field named '%s' not found", name); + deh_warning(context, "Field named '%s' not found", name); - return NULL; + return NULL; } -// -// Get the location of the specified field in the specified structure. -// +/* Get the location of the specified field in the specified structure. */ -static void *GetStructField(void *structptr, - deh_mapping_t *mapping, +static void *get_struct_field(void *structptr, deh_mapping_t *mapping, deh_mapping_entry_t *entry) { - unsigned int offset; + unsigned int offset; - offset = (uint8_t *)entry->location - (uint8_t *)mapping->base; + offset = (uint8_t *)entry->location - (uint8_t *)mapping->base; - return (uint8_t *)structptr + offset; + return (uint8_t *)structptr + offset; } -// -// Set the value of a particular field in a structure by name -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Set the value of a particular field in a structure by name */ -boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, +boolean deh_set_mapping(deh_context_t *context, deh_mapping_t *mapping, void *structptr, char *name, int value) { - deh_mapping_entry_t *entry; - void *location; + deh_mapping_entry_t *entry; + void *location; - entry = GetMappingEntryByName(context, mapping, name); + entry = get_mapping_entry_by_name(context, mapping, name); - if (entry == NULL) + if (entry == NULL) { - return false; + return false; } - // Sanity check: + /* Sanity check: */ - if (entry->is_string) + if (entry->is_string) { - DEH_Error(context, "Tried to set '%s' as integer (BUG)", name); - return false; + deh_error(context, "Tried to set '%s' as integer (BUG)", name); + return false; } - location = GetStructField(structptr, mapping, entry); - - // printf("Setting %p::%s to %i (%i bytes)\n", - // structptr, name, value, entry->size); + location = get_struct_field(structptr, mapping, entry); - // Set field content based on its type: + /* Set field content based on its type: */ - switch (entry->size) + switch (entry->size) { - case 1: - * ((uint8_t *) location) = value; - break; - case 2: - * ((uint16_t *) location) = value; - break; - case 4: - * ((uint32_t *) location) = value; - break; - default: - DEH_Error(context, "Unknown field type for '%s' (BUG)", name); - return false; + case 1: + *((uint8_t *)location) = value; + break; + case 2: + *((uint16_t *)location) = value; + break; + case 4: + *((uint32_t *)location) = value; + break; + default: + deh_error(context, "Unknown field type for '%s' (BUG)", name); + return false; } - return true; + return true; } -// -// Set the value of a string field in a structure by name -// +/* Set the value of a string field in a structure by name */ -boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, - void *structptr, char *name, char *value) +boolean deh_set_string_mapping(deh_context_t *context, + deh_mapping_t *mapping, void *structptr, char *name, char *value) { - deh_mapping_entry_t *entry; - void *location; + deh_mapping_entry_t *entry; + void *location; - entry = GetMappingEntryByName(context, mapping, name); + entry = get_mapping_entry_by_name(context, mapping, name); - if (entry == NULL) + if (entry == NULL) { - return false; + return false; } - // Sanity check: + /* Sanity check: */ - if (!entry->is_string) + if (!entry->is_string) { - DEH_Error(context, "Tried to set '%s' as string (BUG)", name); - return false; + deh_error(context, "Tried to set '%s' as string (BUG)", name); + return false; } - location = GetStructField(structptr, mapping, entry); + location = get_struct_field(structptr, mapping, entry); - // Copy value into field: + /* Copy value into field: */ - M_StringCopy(location, value, entry->size); + m_str_copy(location, value, entry->size); - return true; + return true; } -void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping, +void deh_struct_sha1_sum(SHA1_CTX *context, deh_mapping_t *mapping, void *structptr) { - int i; + int i; - // Go through each mapping + /* Go through each mapping */ - for (i=0; mapping->entries[i].name != NULL; ++i) + for (i = 0; mapping->entries[i].name != NULL; ++i) { - deh_mapping_entry_t *entry = &mapping->entries[i]; - void *location; + deh_mapping_entry_t *entry = &mapping->entries[i]; + void *location; - if (entry->location == NULL) + if (entry->location == NULL) { - // Unsupported field + /* Unsupported field */ - continue; + continue; } - // Add in data for this field + /* Add in data for this field */ - location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base); + location = (uint8_t *)structptr + + ((uint8_t *)entry->location - (uint8_t *)mapping->base); - switch (entry->size) + switch (entry->size) { - case 1: - SHA1_UpdateInt32(context, *((uint8_t *) location)); - break; - case 2: - SHA1_UpdateInt32(context, *((uint16_t *) location)); - break; - case 4: - SHA1_UpdateInt32(context, *((uint32_t *) location)); - break; - default: - I_Error("Unknown dehacked mapping field type for '%s' (BUG)", - entry->name); - break; + case 1: + sha1_updateint32(context, *((uint8_t *)location)); + break; + case 2: + sha1_updateint32(context, *((uint16_t *)location)); + break; + case 4: + sha1_updateint32(context, *((uint32_t *)location)); + break; + default: + i_error("Unknown dehacked mapping field type for '%s' (BUG)", + entry->name); + break; } } } - diff --git a/games/NXDoom/src/deh_mapping.h b/games/NXDoom/src/deh_mapping.h index e71468c4fe1..cd5cf5bf663 100644 --- a/games/NXDoom/src/deh_mapping.h +++ b/games/NXDoom/src/deh_mapping.h @@ -1,93 +1,106 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dehacked "mapping" code -// Allows the fields in structures to be mapped out and accessed by -// name -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_mapping.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Dehacked "mapping" code + * Allows the fields in structures to be mapped out and accessed by + * name + * + ****************************************************************************/ #ifndef DEH_MAPPING_H #define DEH_MAPPING_H -#include "doomtype.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "deh_io.h" +#include "doomtype.h" #include "sha1.h" -#define DEH_BEGIN_MAPPING(mapping_name, structname) \ - static structname deh_mapping_base; \ - static deh_mapping_t mapping_name = \ - { \ - &deh_mapping_base, \ - { - -#define DEH_MAPPING(deh_name, fieldname) \ - {deh_name, &deh_mapping_base.fieldname, \ - sizeof(deh_mapping_base.fieldname), \ - false}, +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#define DEH_MAPPING_STRING(deh_name, fieldname) \ - {deh_name, &deh_mapping_base.fieldname, \ - sizeof(deh_mapping_base.fieldname), \ - true}, +#define DEH_BEGIN_MAPPING(mapping_name, structname) \ + static structname deh_mapping_base; \ + static deh_mapping_t mapping_name = {&deh_mapping_base, { -#define DEH_UNSUPPORTED_MAPPING(deh_name) \ - {deh_name, NULL, -1, false}, +#define DEH_MAPPING(deh_name, fieldname) \ + {deh_name, &deh_mapping_base.fieldname, \ + sizeof(deh_mapping_base.fieldname), false}, -#define DEH_END_MAPPING \ - {NULL, NULL, -1} \ - } \ - }; +#define DEH_MAPPING_STRING(deh_name, fieldname) \ + {deh_name, &deh_mapping_base.fieldname, \ + sizeof(deh_mapping_base.fieldname), true}, +#define DEH_UNSUPPORTED_MAPPING(deh_name) {deh_name, NULL, -1, false}, +#define DEH_END_MAPPING \ + {NULL, NULL, -1} \ + } \ + } \ + ; #define MAX_MAPPING_ENTRIES 32 +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef struct deh_mapping_s deh_mapping_t; typedef struct deh_mapping_entry_s deh_mapping_entry_t; -struct deh_mapping_entry_s +struct deh_mapping_entry_s { - // field name - - const char *name; + /* field name */ + + const char *name; - // location relative to the base in the deh_mapping_t struct - // If this is NULL, it is an unsupported mapping + /* location relative to the base in the deh_mapping_t struct + * If this is NULL, it is an unsupported mapping + */ - void *location; + void *location; - // field size + /* field size */ - int size; + int size; - // if true, this is a string value. + /* if true, this is a string value. */ - boolean is_string; + boolean is_string; }; struct deh_mapping_s { - void *base; - deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES]; + void *base; + deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES]; }; -boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, - void *structptr, char *name, int value); -boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, - void *structptr, char *name, char *value); -void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping, - void *structptr); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef DEH_MAPPING_H */ +boolean deh_set_mapping(deh_context_t *context, deh_mapping_t *mapping, + void *structptr, char *name, int value); +boolean deh_set_string_mapping(deh_context_t *context, + deh_mapping_t *mapping, void *structptr, char *name, char *value); +void deh_struct_sha1_sum(SHA1_CTX *context, deh_mapping_t *mapping, + void *structptr); +#endif /* DEH_MAPPING_H */ diff --git a/games/NXDoom/src/deh_str.c b/games/NXDoom/src/deh_str.c index 76af188ae0c..9c3f8b8b41a 100644 --- a/games/NXDoom/src/deh_str.c +++ b/games/NXDoom/src/deh_str.c @@ -1,433 +1,228 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses Text substitution sections in dehacked files -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_str.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * + * Parses Text substitution sections in dehacked files + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include -#include "doomtype.h" #include "deh_str.h" +#include "doomtype.h" #include "m_misc.h" #include "z_zone.h" -typedef struct -{ - char *from_text; - char *to_text; -} deh_substitution_t; - -static deh_substitution_t **hash_table = NULL; -static int hash_table_entries; -static int hash_table_length = -1; - -// This is the algorithm used by glib +/**************************************************************************** + * Private Types + ****************************************************************************/ -static unsigned int strhash(const char *s) +typedef struct { - const char *p = s; - unsigned int h = *p; - - if (h) - { - for (p += 1; *p; p++) - h = (h << 5) - h + *p; - } - - return h; -} + char *from_text; + char *to_text; +} deh_substitution_t; -static deh_substitution_t *SubstitutionForString(const char *s) +typedef enum { - int entry; - - // Fallback if we have not initialized the hash table yet - if (hash_table_length < 0) - return NULL; - - entry = strhash(s) % hash_table_length; + FORMAT_ARG_INVALID, + FORMAT_ARG_INT, + FORMAT_ARG_FLOAT, + FORMAT_ARG_CHAR, + FORMAT_ARG_STRING, + FORMAT_ARG_PTR, + FORMAT_ARG_SAVE_POS +} format_arg_t; - while (hash_table[entry] != NULL) - { - if (!strcmp(hash_table[entry]->from_text, s)) - { - // substitution found! - return hash_table[entry]; - } +/**************************************************************************** + * Private Data + ****************************************************************************/ - entry = (entry + 1) % hash_table_length; - } +static deh_substitution_t **hash_table = NULL; +static int hash_table_entries; +static int hash_table_length = -1; - // no substitution found - return NULL; -} +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// Look up a string to see if it has been replaced with something else -// This will be used throughout the program to substitute text +/* This is the algorithm used by glib */ -const char *DEH_String(const char *s) +static unsigned int strhash(const char *s) { - deh_substitution_t *subst; - - subst = SubstitutionForString(s); + const char *p = s; + unsigned int h = *p; - if (subst != NULL) + if (h) { - return subst->to_text; + for (p += 1; *p; p++) + h = (h << 5) - h + *p; } - else - { - return s; - } -} -static void InitHashTable(void) -{ - // init hash table - - hash_table_entries = 0; - hash_table_length = 16; - hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length, - PU_STATIC, NULL); - memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length); + return h; } -static void DEH_AddToHashtable(deh_substitution_t *sub); - -static void IncreaseHashtable(void) +static deh_substitution_t *substitution_for_string(const char *s) { - deh_substitution_t **old_table; - int old_table_length; - int i; - - // save the old table + int entry; - old_table = hash_table; - old_table_length = hash_table_length; - - // double the size + /* Fallback if we have not initialized the hash table yet */ - hash_table_length *= 2; - hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length, - PU_STATIC, NULL); - memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length); + if (hash_table_length < 0) return NULL; - // go through the old table and insert all the old entries + entry = strhash(s) % hash_table_length; - for (i=0; ifrom_text, s)) { - DEH_AddToHashtable(old_table[i]); + return hash_table[entry]; /* substitution found! */ } - } - - // free the old table - - Z_Free(old_table); -} - -static void DEH_AddToHashtable(deh_substitution_t *sub) -{ - int entry; - - // if the hash table is more than 60% full, increase its size - if ((hash_table_entries * 10) / hash_table_length > 6) - { - IncreaseHashtable(); + entry = (entry + 1) % hash_table_length; } - // find where to insert it - entry = strhash(sub->from_text) % hash_table_length; - - while (hash_table[entry] != NULL) - { - entry = (entry + 1) % hash_table_length; - } - - hash_table[entry] = sub; - ++hash_table_entries; -} - -void DEH_AddStringReplacement(const char *from_text, const char *to_text) -{ - deh_substitution_t *sub; - size_t len; - - // Initialize the hash table if this is the first time - if (hash_table_length < 0) - { - InitHashTable(); - } - - // Check to see if there is an existing substitution already in place. - sub = SubstitutionForString(from_text); - - if (sub != NULL) - { - Z_Free(sub->to_text); - - len = strlen(to_text) + 1; - sub->to_text = Z_Malloc(len, PU_STATIC, NULL); - memcpy(sub->to_text, to_text, len); - } - else - { - // We need to allocate a new substitution. - sub = Z_Malloc(sizeof(*sub), PU_STATIC, 0); - - // We need to create our own duplicates of the provided strings. - len = strlen(from_text) + 1; - sub->from_text = Z_Malloc(len, PU_STATIC, NULL); - memcpy(sub->from_text, from_text, len); - - len = strlen(to_text) + 1; - sub->to_text = Z_Malloc(len, PU_STATIC, NULL); - memcpy(sub->to_text, to_text, len); + /* no substitution found */ - DEH_AddToHashtable(sub); - } + return NULL; } -typedef enum -{ - FORMAT_ARG_INVALID, - FORMAT_ARG_INT, - FORMAT_ARG_FLOAT, - FORMAT_ARG_CHAR, - FORMAT_ARG_STRING, - FORMAT_ARG_PTR, - FORMAT_ARG_SAVE_POS -} format_arg_t; - -// Get the type of a format argument. -// We can mix-and-match different format arguments as long as they -// are for the same data type. - -static format_arg_t FormatArgumentType(char c) +static void init_hash_table(void) { - switch (c) - { - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': - return FORMAT_ARG_INT; - - case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': - case 'a': case 'A': - return FORMAT_ARG_FLOAT; + /* init hash table */ - case 'c': case 'C': - return FORMAT_ARG_CHAR; - - case 's': case 'S': - return FORMAT_ARG_STRING; - - case 'p': - return FORMAT_ARG_PTR; - - case 'n': - return FORMAT_ARG_SAVE_POS; - - default: - return FORMAT_ARG_INVALID; - } + hash_table_entries = 0; + hash_table_length = 16; + hash_table = z_malloc(sizeof(deh_substitution_t *) * hash_table_length, + PU_STATIC, NULL); + memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length); } -// Given the specified string, get the type of the first format -// string encountered. +static void deh_add_to_hashtable(deh_substitution_t *sub); -static format_arg_t NextFormatArgument(const char **str) +static void increase_hashtable(void) { - format_arg_t argtype; + deh_substitution_t **old_table; + int old_table_length; + int i; - // Search for the '%' starting the next string. + /* save the old table */ - while (**str != '\0') - { - if (**str == '%') - { - ++*str; + old_table = hash_table; + old_table_length = hash_table_length; - // Don't stop for double-%s. + /* double the size */ - if (**str != '%') - { - break; - } - } + hash_table_length *= 2; + hash_table = z_malloc(sizeof(deh_substitution_t *) * hash_table_length, + PU_STATIC, NULL); + memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length); - ++*str; - } - - // Find the type of the format string. + /* go through the old table and insert all the old entries */ - while (**str != '\0') + for (i = 0; i < old_table_length; ++i) { - argtype = FormatArgumentType(**str); - - if (argtype != FORMAT_ARG_INVALID) + if (old_table[i] != NULL) { - ++*str; - - return argtype; + deh_add_to_hashtable(old_table[i]); } - - ++*str; } - // Stop searching, we have reached the end. - - *str = NULL; + /* free the old table */ - return FORMAT_ARG_INVALID; + z_free(old_table); } -// Check if the specified argument type is a valid replacement for -// the original. - -static boolean ValidArgumentReplacement(format_arg_t original, - format_arg_t replacement) +static void deh_add_to_hashtable(deh_substitution_t *sub) { - // In general, the original and replacement types should be - // identical. However, there are some cases where the replacement - // is valid and the types don't match. + int entry; - // Characters can be represented as ints. + /* if the hash table is more than 60% full, increase its size */ - if (original == FORMAT_ARG_CHAR && replacement == FORMAT_ARG_INT) + if ((hash_table_entries * 10) / hash_table_length > 6) { - return true; + increase_hashtable(); } - // Strings are pointers. + /* find where to insert it */ + + entry = strhash(sub->from_text) % hash_table_length; - if (original == FORMAT_ARG_STRING && replacement == FORMAT_ARG_PTR) + while (hash_table[entry] != NULL) { - return true; + entry = (entry + 1) % hash_table_length; } - return original == replacement; + hash_table[entry] = sub; + ++hash_table_entries; } -// Return true if the specified string contains no format arguments. +/**************************************************************************** + * Public Functions + ****************************************************************************/ -static boolean ValidFormatReplacement(const char *original, const char *replacement) +void deh_add_string_replacement(const char *from_text, const char *to_text) { - const char *rover1; - const char *rover2; - int argtype1, argtype2; + deh_substitution_t *sub; + size_t len; - // Check each argument in turn and compare types. + /* Initialize the hash table if this is the first time */ - rover1 = original; rover2 = replacement; - - for (;;) + if (hash_table_length < 0) { - argtype1 = NextFormatArgument(&rover1); - argtype2 = NextFormatArgument(&rover2); - - if (argtype2 == FORMAT_ARG_INVALID) - { - // No more arguments left to read from the replacement string. - - break; - } - else if (argtype1 == FORMAT_ARG_INVALID) - { - // Replacement string has more arguments than the original. - - return false; - } - else if (!ValidArgumentReplacement(argtype1, argtype2)) - { - // Not a valid replacement argument. - - return false; - } + init_hash_table(); } - return true; -} - -// Get replacement format string, checking arguments. - -static const char *FormatStringReplacement(const char *s) -{ - const char *repl; + /* Check to see if there is an existing substitution already in place. */ - repl = DEH_String(s); + sub = substitution_for_string(from_text); - if (!ValidFormatReplacement(s, repl)) + if (sub != NULL) { - printf("WARNING: Unsafe dehacked replacement provided for " - "printf format string: %s\n", s); + z_free(sub->to_text); - return s; + len = strlen(to_text) + 1; + sub->to_text = z_malloc(len, PU_STATIC, NULL); + memcpy(sub->to_text, to_text, len); } + else + { + /* We need to allocate a new substitution. */ - return repl; -} - -// printf(), performing a replacement on the format string. - -void DEH_printf(const char *fmt, ...) -{ - va_list args; - const char *repl; - - repl = FormatStringReplacement(fmt); - - va_start(args, fmt); - - vprintf(repl, args); - - va_end(args); -} - -// fprintf(), performing a replacement on the format string. - -void DEH_fprintf(FILE *fstream, const char *fmt, ...) -{ - va_list args; - const char *repl; - - repl = FormatStringReplacement(fmt); - - va_start(args, fmt); - - vfprintf(fstream, repl, args); - - va_end(args); -} - -// snprintf(), performing a replacement on the format string. + sub = z_malloc(sizeof(*sub), PU_STATIC, 0); -void DEH_snprintf(char *buffer, size_t len, const char *fmt, ...) -{ - va_list args; - const char *repl; + /* We need to create our own duplicates of the provided strings. */ - repl = FormatStringReplacement(fmt); + len = strlen(from_text) + 1; + sub->from_text = z_malloc(len, PU_STATIC, NULL); + memcpy(sub->from_text, from_text, len); - va_start(args, fmt); + len = strlen(to_text) + 1; + sub->to_text = z_malloc(len, PU_STATIC, NULL); + memcpy(sub->to_text, to_text, len); - M_vsnprintf(buffer, len, repl, args); - - va_end(args); + deh_add_to_hashtable(sub); + } } - diff --git a/games/NXDoom/src/deh_str.h b/games/NXDoom/src/deh_str.h index d547de6b9f4..3b2e6fefedb 100644 --- a/games/NXDoom/src/deh_str.h +++ b/games/NXDoom/src/deh_str.h @@ -1,45 +1,33 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dehacked string replacements -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_str.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Dehacked string replacements + * + ****************************************************************************/ #ifndef DEH_STR_H #define DEH_STR_H -#include +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#include "doomtype.h" +/* Used to do dehacked text substitutions throughout the program */ -// Used to do dehacked text substitutions throughout the program - -const char *DEH_String(const char *s) PRINTF_ARG_ATTR(1); -void DEH_printf(const char *fmt, ...) PRINTF_ATTR(1, 2); -void DEH_fprintf(FILE *fstream, const char *fmt, ...) PRINTF_ATTR(2, 3); -void DEH_snprintf(char *buffer, size_t len, const char *fmt, ...) PRINTF_ATTR(3, 4); -void DEH_AddStringReplacement(const char *from_text, const char *to_text); - - -#if 0 -// Static macro versions of the functions above - -#define DEH_String(x) (x) -#define DEH_printf printf -#define DEH_fprintf fprintf -#define DEH_snprintf snprintf - -#endif - -#endif /* #ifndef DEH_STR_H */ +void deh_add_string_replacement(const char *from_text, const char *to_text); +#endif /* DEH_STR_H */ diff --git a/games/NXDoom/src/deh_text.c b/games/NXDoom/src/deh_text.c index 9e621b43832..927a3e7c6ba 100644 --- a/games/NXDoom/src/deh_text.c +++ b/games/NXDoom/src/deh_text.c @@ -1,19 +1,27 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses Text substitution sections in dehacked files -// +/**************************************************************************** + * apps/games/NXDoom/src/deh_text.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Parses Text substitution sections in dehacked files + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -27,87 +35,106 @@ #include "deh_io.h" #include "deh_main.h" -// Given a string length, find the maximum length of a -// string that can replace it. +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ -static int TXT_MaxStringLength(int len) +static void deh_text_parse_line(deh_context_t *context, char *line, + void *tag); +static void *deh_text_start(deh_context_t *context, char *line); +static void *deh_text_start(deh_context_t *context, char *line); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_text = +{ + "Text", NULL, deh_text_start, deh_text_parse_line, NULL, NULL, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Given a string length, find the maximum length of a string that can + * replace it. + */ + +static int txt_max_string_length(int len) { - // Enough bytes for the string and the NUL terminator + /* Enough bytes for the string and the NUL terminator */ - len += 1; + len += 1; - // All strings in doom.exe are on 4-byte boundaries, so we may be able - // to support a slightly longer string. - // Extend up to the next 4-byte boundary + /* All strings in doom.exe are on 4-byte boundaries, so we may be able + * to support a slightly longer string. + * Extend up to the next 4-byte boundary + */ - len += (4 - (len % 4)) % 4; - - // Less one for the NUL terminator. + len += (4 - (len % 4)) % 4; - return len - 1; + /* Less one for the NUL terminator. */ + + return len - 1; } -static void *DEH_TextStart(deh_context_t *context, char *line) +static void *deh_text_start(deh_context_t *context, char *line) { - char *from_text, *to_text; - int fromlen, tolen; - int i; + char *from_text; + char *to_text; + int fromlen; + int to_len; + int i; - if (sscanf(line, "Text %i %i", &fromlen, &tolen) != 2) + if (sscanf(line, "Text %i %i", &fromlen, &to_len) != 2) { - DEH_Warning(context, "Parse error on section start"); - return NULL; + deh_warning(context, "Parse error on section start"); + return NULL; } - // Only allow string replacements that are possible in Vanilla Doom. - // Chocolate Doom is unforgiving! + /* Only allow string replacements that are possible in Vanilla Doom. + * Chocolate Doom is unforgiving! + */ - if (!deh_allow_long_strings && tolen > TXT_MaxStringLength(fromlen)) + if (!deh_allow_long_strings && to_len > txt_max_string_length(fromlen)) { - DEH_Error(context, "Replacement string is longer than the maximum " - "possible in doom.exe"); - return NULL; + deh_error(context, "Replacement string is longer than the maximum " + "possible in doom.exe"); + return NULL; } - from_text = malloc(fromlen + 1); - to_text = malloc(tolen + 1); + from_text = malloc(fromlen + 1); + to_text = malloc(to_len + 1); - // read in the "from" text + /* read in the "from" text */ - for (i=0; i - -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" - -1 VERSIONINFO -PRODUCTVERSION @WINDOWS_RC_VERSION@ -FILEVERSION @WINDOWS_RC_VERSION@ -FILETYPE 1 -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "@PACKAGE_VERSION@.0" - VALUE "FileDescription", "@PACKAGE_STRING@" - VALUE "InternalName", "@PACKAGE_TARNAME@" - VALUE "CompanyName", "@PACKAGE_BUGREPORT@" - VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" - VALUE "ProductName", "@PACKAGE_NAME@" - VALUE "ProductVersion", "@PACKAGE_VERSION@" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - diff --git a/games/NXDoom/src/doom/CMakeLists.txt b/games/NXDoom/src/doom/CMakeLists.txt deleted file mode 100644 index 6e878a0f139..00000000000 --- a/games/NXDoom/src/doom/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -add_library(doom STATIC - am_map.c am_map.h - deh_ammo.c - deh_bexstr.c - deh_cheat.c - deh_doom.c - deh_frame.c - deh_misc.c deh_misc.h - deh_ptr.c - deh_sound.c - deh_thing.c - deh_weapon.c - d_englsh.h - d_items.c d_items.h - d_main.c d_main.h - d_net.c - doomdata.h - doomdef.c doomdef.h - doomstat.c doomstat.h - d_player.h - dstrings.c dstrings.h - d_textur.h - d_think.h - f_finale.c f_finale.h - f_wipe.c f_wipe.h - g_game.c g_game.h - hu_lib.c hu_lib.h - hu_stuff.c hu_stuff.h - info.c info.h - m_menu.c m_menu.h - m_random.c m_random.h - p_ceilng.c - p_doors.c - p_enemy.c - p_floor.c - p_inter.c p_inter.h - p_lights.c - p_local.h - p_map.c - p_maputl.c - p_mobj.c p_mobj.h - p_plats.c - p_pspr.c p_pspr.h - p_saveg.c p_saveg.h - p_setup.c p_setup.h - p_sight.c - p_spec.c p_spec.h - p_switch.c - p_telept.c - p_tick.c p_tick.h - p_user.c - r_bsp.c r_bsp.h - r_data.c r_data.h - r_defs.h - r_draw.c r_draw.h - r_local.h - r_main.c r_main.h - r_plane.c r_plane.h - r_segs.c r_segs.h - r_sky.c r_sky.h - r_state.h - r_things.c r_things.h - s_sound.c s_sound.h - sounds.c sounds.h - statdump.c statdump.h - st_lib.c st_lib.h - st_stuff.c st_stuff.h - wi_stuff.c wi_stuff.h) - -target_include_directories(doom PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") - -if (DEFINED EMSCRIPTEN) - set(SDL_FLAGS "-s USE_SDL=2") - if(ENABLE_SDL2_MIXER) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") - endif() - if(ENABLE_SDL2_NET) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") - endif() -else() - set(SDL_LINK_LIBS SDL2::SDL2) - if(ENABLE_SDL2_MIXER) - list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) - endif() - if(ENABLE_SDL2_NET) - list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) - endif() -endif() -target_link_libraries(doom ${SDL_LINK_LIBS}) -set_target_properties(doom PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") -set_target_properties(doom PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/doom/Makefile.am b/games/NXDoom/src/doom/Makefile.am deleted file mode 100644 index 1f4e8c48efc..00000000000 --- a/games/NXDoom/src/doom/Makefile.am +++ /dev/null @@ -1,83 +0,0 @@ -AM_CFLAGS = -I$(top_srcdir)/src @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ - -EXTRA_DIST = \ - CMakeLists.txt \ - doom_icon.c - -noinst_LIBRARIES=libdoom.a - -libdoom_a_SOURCES = \ -am_map.c am_map.h \ -deh_ammo.c \ -deh_bexstr.c \ -deh_cheat.c \ -deh_doom.c \ -deh_frame.c \ -deh_misc.c deh_misc.h \ -deh_ptr.c \ -deh_sound.c \ -deh_thing.c \ -deh_weapon.c \ - d_englsh.h \ -d_items.c d_items.h \ -d_main.c d_main.h \ -d_net.c \ - doomdata.h \ -doomdef.c doomdef.h \ -doomstat.c doomstat.h \ - d_player.h \ -dstrings.c dstrings.h \ - d_textur.h \ - d_think.h \ -f_finale.c f_finale.h \ -f_wipe.c f_wipe.h \ -g_game.c g_game.h \ -hu_lib.c hu_lib.h \ -hu_stuff.c hu_stuff.h \ -info.c info.h \ -m_menu.c m_menu.h \ -m_random.c m_random.h \ -p_ceilng.c \ -p_doors.c \ -p_enemy.c \ -p_floor.c \ -p_inter.c p_inter.h \ -p_lights.c \ - p_local.h \ -p_map.c \ -p_maputl.c \ -p_mobj.c p_mobj.h \ -p_plats.c \ -p_pspr.c p_pspr.h \ -p_saveg.c p_saveg.h \ -p_setup.c p_setup.h \ -p_sight.c \ -p_spec.c p_spec.h \ -p_switch.c \ -p_telept.c \ -p_tick.c p_tick.h \ -p_user.c \ -r_bsp.c r_bsp.h \ -r_data.c r_data.h \ - r_defs.h \ -r_draw.c r_draw.h \ - r_local.h \ -r_main.c r_main.h \ -r_plane.c r_plane.h \ -r_segs.c r_segs.h \ -r_sky.c r_sky.h \ - r_state.h \ -r_things.c r_things.h \ -s_sound.c s_sound.h \ -sounds.c sounds.h \ -statdump.c statdump.h \ -st_lib.c st_lib.h \ -st_stuff.c st_stuff.h \ -wi_stuff.c wi_stuff.h - -if HAVE_ICONS - -doom_icon.c : $(top_builddir)/data/doom.png - $(top_builddir)/data/convert-icon $(top_builddir)/data/doom.png $@ - -endif diff --git a/games/NXDoom/src/doom/am_map.c b/games/NXDoom/src/doom/am_map.c index 150098edafb..02d233df2e6 100644 --- a/games/NXDoom/src/doom/am_map.c +++ b/games/NXDoom/src/doom/am_map.c @@ -1,1374 +1,1813 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: the automap code -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/am_map.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: the automap code + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include "deh_main.h" -#include "z_zone.h" -#include "doomkeys.h" #include "doomdef.h" -#include "st_stuff.h" +#include "doomkeys.h" #include "p_local.h" +#include "st_stuff.h" #include "w_wad.h" +#include "z_zone.h" -#include "m_cheat.h" -#include "m_controls.h" -#include "m_misc.h" #include "i_system.h" #include "i_timer.h" #include "i_video.h" +#include "m_cheat.h" +#include "m_controls.h" +#include "m_misc.h" + +/* Needs access to LFB. */ -// Needs access to LFB. #include "v_video.h" -// State. #include "doomstat.h" #include "r_state.h" -// Data. #include "dstrings.h" #include "am_map.h" - -// For use if I do walls with outsides/insides -#define REDS (256-5*16) -#define REDRANGE 16 -#define BLUES (256-4*16+8) -#define BLUERANGE 8 -#define GREENS (7*16) -#define GREENRANGE 16 -#define GRAYS (6*16) -#define GRAYSRANGE 16 -#define BROWNS (4*16) -#define BROWNRANGE 16 -#define YELLOWS (256-32+7) -#define YELLOWRANGE 1 -#define BLACK 0 -#define WHITE (256-47) - -// Automap colors -#define BACKGROUND BLACK -#define YOURCOLORS WHITE -#define YOURRANGE 0 -#define WALLCOLORS REDS -#define WALLRANGE REDRANGE -#define TSWALLCOLORS GRAYS -#define TSWALLRANGE GRAYSRANGE -#define FDWALLCOLORS BROWNS -#define FDWALLRANGE BROWNRANGE -#define CDWALLCOLORS YELLOWS -#define CDWALLRANGE YELLOWRANGE -#define THINGCOLORS GREENS -#define THINGRANGE GREENRANGE +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* For use if I do walls with outsides/insides */ + +#define REDS (256 - 5 * 16) +#define REDRANGE 16 +#define BLUES (256 - 4 * 16 + 8) +#define BLUERANGE 8 +#define GREENS (7 * 16) +#define GREENRANGE 16 +#define GRAYS (6 * 16) +#define GRAYSRANGE 16 +#define BROWNS (4 * 16) +#define BROWNRANGE 16 +#define YELLOWS (256 - 32 + 7) +#define YELLOWRANGE 1 +#define BLACK 0 +#define WHITE (256 - 47) + +/* Automap colors */ + +#define BACKGROUND BLACK +#define YOURCOLORS WHITE +#define YOURRANGE 0 +#define WALLCOLORS REDS +#define WALLRANGE REDRANGE +#define TSWALLCOLORS GRAYS +#define TSWALLRANGE GRAYSRANGE +#define FDWALLCOLORS BROWNS +#define FDWALLRANGE BROWNRANGE +#define CDWALLCOLORS YELLOWS +#define CDWALLRANGE YELLOWRANGE +#define THINGCOLORS GREENS +#define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE -#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) -#define GRIDRANGE 0 -#define XHAIRCOLORS GRAYS +#define GRIDCOLORS (GRAYS + GRAYSRANGE / 2) +#define GRIDRANGE 0 +#define XHAIRCOLORS GRAYS -// drawing stuff +/* drawing stuff */ #define AM_NUMMARKPOINTS 10 -// scale on entry -#define INITSCALEMTOF (.2*FRACUNIT) -// how much the automap moves window per tic in frame-buffer coordinates -// moves 140 pixels in 1 second -#define F_PANINC 4 -// how much zoom-in per tic -// goes to 2x in 1 second -#define M_ZOOMIN ((int) (1.02*FRACUNIT)) -// how much zoom-out per tic -// pulls out to 0.5x in 1 second -#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) - -// translates between frame-buffer and map distances -#define FTOM(x) FixedMul(((x)<>FRACBITS) -// translates between frame-buffer and map coordinates -#define CXMTOF(x) (f_x + MTOF((x)-m_x)) -#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) - -// the following is crap +/* scale on entry */ + +#define INITSCALEMTOF (.2 * FRACUNIT) + +/* how much the automap moves window per tic in frame-buffer coordinates + * moves 140 pixels in 1 second + */ + +#define F_PANINC 4 + +/* how much zoom-in per tic goes to 2x in 1 second */ + +#define M_ZOOMIN ((int)(1.02 * FRACUNIT)) + +/* how much zoom-out per tic pulls out to 0.5x in 1 second */ + +#define M_ZOOMOUT ((int)(FRACUNIT / 1.02)) + +/* translates between frame-buffer and map distances */ + +#define FTOM(x) fixed_mul(((x) << FRACBITS), scale_ftom) +#define MTOF(x) (fixed_mul((x), scale_mtof) >> FRACBITS) + +/* translates between frame-buffer and map coordinates */ + +#define CXMTOF(x) (f_x + MTOF((x) - m_x)) +#define CYMTOF(y) (f_y + (f_h - MTOF((y) - m_y))) + +/* the following is crap */ + #define LINE_NEVERSEE ML_DONTDRAW +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef struct { - int x, y; + int x; + int y; } fpoint_t; typedef struct { - fpoint_t a, b; + fpoint_t a; + fpoint_t b; } fline_t; typedef struct { - fixed_t x,y; + fixed_t x; + fixed_t y; } mpoint_t; typedef struct { - mpoint_t a, b; + mpoint_t a; + mpoint_t b; } mline_t; typedef struct { - fixed_t slp, islp; + fixed_t slp; + fixed_t islp; } islope_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* The vector graphics for the automap. A line drawing of the player pointing + * right, starting from the middle. + */ -// -// The vector graphics for the automap. -// A line drawing of the player pointing right, -// starting from the middle. -// -#define R ((8*PLAYERRADIUS)/7) -mline_t player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/4 } }, // -----> - { { R, 0 }, { R-R/2, -R/4 } }, - { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> - { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> - { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } +#define R ((8 * PLAYERRADIUS) / 7) +mline_t player_arrow[] = +{ + { + { + -R + R / 8, + 0, + }, + { + R, + 0, + }, + }, /* ----- */ + { + { + R, + 0, + }, + { + R - R / 2, + R / 4, + }, + }, /* -----> */ + { + { + R, + 0, + }, + { + R - R / 2, + -R / 4, + }, + }, + { + { + -R + R / 8, + 0, + }, + { + -R - R / 8, + R / 4, + }, + }, /* >----> */ + { + { + -R + R / 8, + 0, + }, + { + -R - R / 8, + -R / 4, + }, + }, + { + { + -R + 3 * R / 8, + 0, + }, + { + -R + R / 8, + R / 4, + }, + }, /* >>---> */ + { + { + -R + 3 * R / 8, + 0, + }, + { + -R + R / 8, + -R / 4, + }, + }, }; #undef R -#define R ((8*PLAYERRADIUS)/7) -mline_t cheat_player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/6 } }, // -----> - { { R, 0 }, { R-R/2, -R/6 } }, - { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> - { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> - { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, - { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> - { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, - { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, - { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> - { { -R/6, -R/6 }, { 0, -R/6 } }, - { { 0, -R/6 }, { 0, R/4 } }, - { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> - { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, - { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } +#define R ((8 * PLAYERRADIUS) / 7) +mline_t cheat_player_arrow[] = +{ + { + { + -R + R / 8, + 0, + }, + { + R, + 0, + }, + }, /* ----- */ + { + { + R, + 0, + }, + { + R - R / 2, + R / 6, + }, + }, /* -----> */ + { + { + R, + 0, + }, + { + R - R / 2, + -R / 6, + }, + }, + { + { + -R + R / 8, + 0, + }, + { + -R - R / 8, + R / 6, + }, + }, /* >-----> */ + { + { + -R + R / 8, + 0, + }, + { + -R - R / 8, + -R / 6, + }, + }, + { + { + -R + 3 * R / 8, + 0, + }, + { + -R + R / 8, + R / 6, + }, + }, /* >>-----> */ + { + { + -R + 3 * R / 8, + 0, + }, + { + -R + R / 8, + -R / 6, + }, + }, + { + { + -R / 2, + 0, + }, + { + -R / 2, + -R / 6, + }, + }, /* >>-d---> */ + { + { + -R / 2, + -R / 6, + }, + { + -R / 2 + R / 6, + -R / 6, + }, + }, + { + { + -R / 2 + R / 6, + -R / 6, + }, + { + -R / 2 + R / 6, + R / 4, + }, + }, + { + { + -R / 6, + 0, + }, + { + -R / 6, + -R / 6, + }, + }, /* >>-dd--> */ + { + { + -R / 6, + -R / 6, + }, + { + 0, + -R / 6, + }, + }, + { + { + 0, + -R / 6, + }, + { + 0, + R / 4, + }, + }, + { + { + R / 6, + R / 4, + }, + { + R / 6, + -R / 7, + }, + }, /* >>-ddt-> */ + { + { + R / 6, + -R / 7, + }, + { + R / 6 + R / 32, + -R / 7 - R / 32, + }, + }, + { + { + R / 6 + R / 32, + -R / 7 - R / 32, + }, + { + R / 6 + R / 10, + -R / 7, + }, + }, }; #undef R #define R (FRACUNIT) -mline_t triangle_guy[] = { - { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } }, - { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } }, - { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } } +mline_t triangle_guy[] = +{ + { + { + (fixed_t)(-.867 * R), + (fixed_t)(-.5 * R), + }, + { + (fixed_t)(.867 * R), + (fixed_t)(-.5 * R), + }, + }, + { + { + (fixed_t)(.867 * R), + (fixed_t)(-.5 * R), + }, + { + (fixed_t)(0), + (fixed_t)(R), + }, + }, + { + { + (fixed_t)(0), + (fixed_t)(R), + }, + { + (fixed_t)(-.867 * R), + (fixed_t)(-.5 * R), + }, + }, }; #undef R #define R (FRACUNIT) -mline_t thintriangle_guy[] = { - { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, - { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, - { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } +mline_t thintriangle_guy[] = +{ + { + { + (fixed_t)(-.5 * R), + (fixed_t)(-.7 * R), + }, + { + (fixed_t)(R), + (fixed_t)(0), + }, + }, + { + { + (fixed_t)(R), + (fixed_t)(0), + }, + { + (fixed_t)(-.5 * R), + (fixed_t)(.7 * R), + }, + }, + { + { + (fixed_t)(-.5 * R), + (fixed_t)(.7 * R), + }, + { + (fixed_t)(-.5 * R), + (fixed_t)(-.7 * R), + }, + }, }; #undef R +boolean automapactive = false; + +cheatseq_t cheat_amap = CHEAT("iddt", 0); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int cheating = 0; +static int grid = 0; + +static int finit_width = SCREENWIDTH; +static int finit_height = SCREENHEIGHT - ST_HEIGHT; + +/* location of window on screen */ +static int f_x; +static int f_y; +/* size of window on screen */ -static int cheating = 0; -static int grid = 0; +static int f_w; +static int f_h; -boolean automapactive = false; -static int finit_width = SCREENWIDTH; -static int finit_height = SCREENHEIGHT - ST_HEIGHT; +static int lightlev; /* used for funky strobing effect */ +static pixel_t *fb; /* pseudo-frame buffer */ +static int amclock; -// location of window on screen -static int f_x; -static int f_y; +/* how far the window pans each tic (map coords) */ -// size of window on screen -static int f_w; -static int f_h; +static mpoint_t m_paninc; -static int lightlev; // used for funky strobing effect -static pixel_t* fb; // pseudo-frame buffer -static int amclock; +/* how far the window zooms in each tic (map coords) */ -static mpoint_t m_paninc; // how far the window pans each tic (map coords) -static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) -static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) +static fixed_t mtof_zoommul; -static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) -static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) +/* how far the window zooms in each tic (fb coords) */ -// -// width/height of window on map (map coords) -// -static fixed_t m_w; -static fixed_t m_h; +static fixed_t ftom_zoommul; -// based on level size -static fixed_t min_x; -static fixed_t min_y; -static fixed_t max_x; -static fixed_t max_y; +/* LL x,y where the window is on the map (map coords) */ -static fixed_t max_w; // max_x-min_x, -static fixed_t max_h; // max_y-min_y +static fixed_t m_x; +static fixed_t m_y; -// based on player size -static fixed_t min_w; -static fixed_t min_h; +/* UR x,y where the window is on the map (map coords) */ +static fixed_t m_x2; +static fixed_t m_y2; -static fixed_t min_scale_mtof; // used to tell when to stop zooming out -static fixed_t max_scale_mtof; // used to tell when to stop zooming in +/* width/height of window on map (map coords) */ -// old stuff for recovery later -static fixed_t old_m_w, old_m_h; -static fixed_t old_m_x, old_m_y; +static fixed_t m_w; +static fixed_t m_h; + +/* based on level size */ + +static fixed_t min_x; +static fixed_t min_y; +static fixed_t max_x; +static fixed_t max_y; + +static fixed_t max_w; /* max_x-min_x, */ +static fixed_t max_h; /* max_y-min_y */ + +/* based on player size */ + +static fixed_t min_w; +static fixed_t min_h; + +static fixed_t min_scale_mtof; /* used to tell when to stop zooming out */ +static fixed_t max_scale_mtof; /* used to tell when to stop zooming in */ + +/* old stuff for recovery later */ + +static fixed_t old_m_w; +static fixed_t old_m_h; +static fixed_t old_m_x; +static fixed_t old_m_y; + +/* old location used by the Follower routine */ -// old location used by the Follower routine static mpoint_t f_oldloc; -// used by MTOF to scale from map-to-frame-buffer coords +/* used by MTOF to scale from map-to-frame-buffer coords */ + static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; -// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) -static fixed_t scale_ftom; -static player_t *plr; // the player represented by an arrow +/* used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) */ -static patch_t *marknums[10]; // numbers used for marking by the automap -static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are -static int markpointnum = 0; // next point to be assigned +static fixed_t scale_ftom; -static int followplayer = 1; // specifies whether to follow the player around +static player_t *plr; /* the player represented by an arrow */ -cheatseq_t cheat_amap = CHEAT("iddt", 0); +static patch_t *marknums[10]; /* numbers used for marking by the automap */ -static boolean stopped = true; +static mpoint_t markpoints[AM_NUMMARKPOINTS]; /* where the points are */ -// Calculates the slope and slope according to the x-axis of a line -// segment in map coordinates (with the upright y-axis n' all) so -// that it can be used with the brain-dead drawing stuff. +static int markpointnum = 0; /* next point to be assigned */ -void -AM_getIslope -( mline_t* ml, - islope_t* is ) -{ - int dx, dy; +/* specifies whether to follow the player around */ + +static int followplayer = 1; - dy = ml->a.y - ml->b.y; - dx = ml->b.x - ml->a.x; - if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); - else is->islp = FixedDiv(dx, dy); - if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); - else is->slp = FixedDiv(dy, dx); +static boolean stopped = true; +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: am_get_i_slope + * + * Description: + * Calculates the slope and slope according to the x-axis of a line + * segment in map coordinates (with the upright y-axis n' all) so + * that it can be used with the brain-dead drawing stuff. + * + ****************************************************************************/ + +static void am_get_i_slope(mline_t *ml, islope_t *is) +{ + int dx; + int dy; + + dy = ml->a.y - ml->b.y; + dx = ml->b.x - ml->a.x; + if (!dy) + is->islp = (dx < 0 ? -INT_MAX : INT_MAX); + else + is->islp = fixed_div(dx, dy); + if (!dx) + is->slp = (dy < 0 ? -INT_MAX : INT_MAX); + else + is->slp = fixed_div(dy, dx); } -// -// -// -void AM_activateNewScale(void) +/**************************************************************************** + * Name: am_activate_new_scale + ****************************************************************************/ + +static void am_activate_new_scale(void) { - m_x += m_w/2; - m_y += m_h/2; - m_w = FTOM(f_w); - m_h = FTOM(f_h); - m_x -= m_w/2; - m_y -= m_h/2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; + m_x += m_w / 2; + m_y += m_h / 2; + m_w = FTOM(f_w); + m_h = FTOM(f_h); + m_x -= m_w / 2; + m_y -= m_h / 2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; } -// -// -// -void AM_saveScaleAndLoc(void) +/**************************************************************************** + * Name: am_save_scale_and_loc + ****************************************************************************/ + +static void am_save_scale_and_loc(void) { - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; } -// -// -// -void AM_restoreScaleAndLoc(void) +/**************************************************************************** + * Name: am_restore_scale_and_loc + ****************************************************************************/ + +static void am_restore_scale_and_loc(void) { + m_w = old_m_w; + m_h = old_m_h; - m_w = old_m_w; - m_h = old_m_h; - if (!followplayer) + if (!followplayer) + { + m_x = old_m_x; + m_y = old_m_y; + } + else { - m_x = old_m_x; - m_y = old_m_y; - } else { - m_x = plr->mo->x - m_w/2; - m_y = plr->mo->y - m_h/2; + m_x = plr->mo->x - m_w / 2; + m_y = plr->mo->y - m_h / 2; } - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - // Change the scaling multipliers - scale_mtof = FixedDiv(f_w< max_x) - max_x = vertexes[i].x; - - if (vertexes[i].y < min_y) - min_y = vertexes[i].y; - else if (vertexes[i].y > max_y) - max_y = vertexes[i].y; + if (vertices[i].x < min_x) + min_x = vertices[i].x; + else if (vertices[i].x > max_x) + max_x = vertices[i].x; + + if (vertices[i].y < min_y) + min_y = vertices[i].y; + else if (vertices[i].y > max_y) + max_y = vertices[i].y; } - - max_w = max_x - min_x; - max_h = max_y - min_y; - min_w = 2*PLAYERRADIUS; // const? never changed? - min_h = 2*PLAYERRADIUS; + max_w = max_x - min_x; + max_h = max_y - min_y; + + min_w = 2 * PLAYERRADIUS; /* const? never changed? */ + min_h = 2 * PLAYERRADIUS; - a = FixedDiv(f_w< max_x) - m_x = max_x - m_w/2; - else if (m_x + m_w/2 < min_x) - m_x = min_x - m_w/2; - - if (m_y + m_h/2 > max_y) - m_y = max_y - m_h/2; - else if (m_y + m_h/2 < min_y) - m_y = min_y - m_h/2; - - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; + m_x += m_paninc.x; + m_y += m_paninc.y; + + if (m_x + m_w / 2 > max_x) + m_x = max_x - m_w / 2; + else if (m_x + m_w / 2 < min_x) + m_x = min_x - m_w / 2; + + if (m_y + m_h / 2 > max_y) + m_y = max_y - m_h / 2; + else if (m_y + m_h / 2 < min_y) + m_y = min_y - m_h / 2; + + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; } +/**************************************************************************** + * Name: am_init_variables + ****************************************************************************/ -// -// -// -void AM_initVariables(void) +static void am_init_variables(void) { - int pnum; - static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 }; + int pnum; + static event_t st_notify = + { + ev_keyup, AM_MSGENTERED, 0, 0 + }; + + automapactive = true; + fb = i_video_buffer; - automapactive = true; - fb = I_VideoBuffer; + f_oldloc.x = INT_MAX; + amclock = 0; + lightlev = 0; - f_oldloc.x = INT_MAX; - amclock = 0; - lightlev = 0; + m_paninc.x = m_paninc.y = 0; + ftom_zoommul = FRACUNIT; + mtof_zoommul = FRACUNIT; - m_paninc.x = m_paninc.y = 0; - ftom_zoommul = FRACUNIT; - mtof_zoommul = FRACUNIT; + m_w = FTOM(f_w); + m_h = FTOM(f_h); - m_w = FTOM(f_w); - m_h = FTOM(f_h); + /* find player to center on initially */ - // find player to center on initially - if (playeringame[consoleplayer]) + if (playeringame[consoleplayer]) { - plr = &players[consoleplayer]; + plr = &players[consoleplayer]; } - else + else { - plr = &players[0]; + plr = &players[0]; - for (pnum=0;pnummo->x - m_w/2; - m_y = plr->mo->y - m_h/2; - AM_changeWindowLoc(); + m_x = plr->mo->x - m_w / 2; + m_y = plr->mo->y - m_h / 2; + am_change_window_loc(); - // for saving & restoring - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; + /* for saving & restoring */ - // inform the status bar of the change - ST_Responder(&st_notify); + old_m_x = m_x; + old_m_y = m_y; + old_m_w = m_w; + old_m_h = m_h; + /* inform the status bar of the change */ + + st_responder(&st_notify); } -// -// -// -void AM_loadPics(void) +/**************************************************************************** + * Name: am_load_pics + ****************************************************************************/ + +static void am_load_pics(void) { - int i; - char namebuf[9]; - - for (i=0;i<10;i++) + int i; + char namebuf[9]; + + for (i = 0; i < 10; i++) { - DEH_snprintf(namebuf, 9, "AMMNUM%d", i); - marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); + snprintf(namebuf, 9, "AMMNUM%d", i); + marknums[i] = w_cache_lump_name(namebuf, PU_STATIC); } - } -void AM_unloadPics(void) +/**************************************************************************** + * Name: am_unload_pics + ****************************************************************************/ + +static void am_unload_pics(void) { - int i; - char namebuf[9]; - - for (i=0;i<10;i++) + int i; + char namebuf[9]; + + for (i = 0; i < 10; i++) { - DEH_snprintf(namebuf, 9, "AMMNUM%d", i); - W_ReleaseLumpName(namebuf); + snprintf(namebuf, 9, "AMMNUM%d", i); + w_release_lump_name(namebuf); } } -void AM_clearMarks(void) +/**************************************************************************** + * Name: am_clear_marks + ****************************************************************************/ + +static void am_clear_marks(void) { - int i; + int i; + + for (i = 0; i < AM_NUMMARKPOINTS; i++) + { + markpoints[i].x = -1; /* means empty */ + } - for (i=0;i max_scale_mtof) - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); + am_find_minmax_boundaries(); + scale_mtof = fixed_div(min_scale_mtof, (int)(0.7 * FRACUNIT)); + if (scale_mtof > max_scale_mtof) scale_mtof = min_scale_mtof; + scale_ftom = fixed_div(FRACUNIT, scale_mtof); } +/**************************************************************************** + * Name: am_start + ****************************************************************************/ + +static void am_start(void) +{ + static int lastlevel = -1; + static int lastepisode = -1; + + if (!stopped) am_stop(); + stopped = false; + if (lastlevel != gamemap || lastepisode != gameepisode) + { + am_level_init(); + lastlevel = gamemap; + lastepisode = gameepisode; + } + am_init_variables(); + am_load_pics(); +} +/**************************************************************************** + * Name: am_min_out_window_scale + * + * Description: + * set the window scale to the maximum size + * + ****************************************************************************/ -// -// -// -void AM_Stop (void) +static void am_min_out_window_scale(void) { - static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 }; + scale_mtof = min_scale_mtof; + scale_ftom = fixed_div(FRACUNIT, scale_mtof); + am_activate_new_scale(); +} + +/**************************************************************************** + * Name: am_max_out_window_scale + * + * Description: + * set the window scale to the minimum size + * + ****************************************************************************/ - AM_unloadPics(); - automapactive = false; - ST_Responder(&st_notify); - stopped = true; +static void am_max_out_window_scale(void) +{ + scale_mtof = max_scale_mtof; + scale_ftom = fixed_div(FRACUNIT, scale_mtof); + am_activate_new_scale(); } -// -// -// -void AM_Start (void) +/**************************************************************************** + * Name: am_change_window_scale + * + * Description: + * Zooming + * + ****************************************************************************/ + +static void am_change_window_scale(void) { - static int lastlevel = -1, lastepisode = -1; + /* Change the scaling multipliers */ + + scale_mtof = fixed_mul(scale_mtof, mtof_zoommul); + scale_ftom = fixed_div(FRACUNIT, scale_mtof); - if (!stopped) AM_Stop(); - stopped = false; - if (lastlevel != gamemap || lastepisode != gameepisode) + if (scale_mtof < min_scale_mtof) + am_min_out_window_scale(); + else if (scale_mtof > max_scale_mtof) + am_max_out_window_scale(); + else + am_activate_new_scale(); +} + +/**************************************************************************** + * Name: am_do_follow_player + ****************************************************************************/ + +static void am_do_follow_player(void) +{ + if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) { - AM_LevelInit(); - lastlevel = gamemap; - lastepisode = gameepisode; + m_x = FTOM(MTOF(plr->mo->x)) - m_w / 2; + m_y = FTOM(MTOF(plr->mo->y)) - m_h / 2; + m_x2 = m_x + m_w; + m_y2 = m_y + m_h; + f_oldloc.x = plr->mo->x; + f_oldloc.y = plr->mo->y; + + /* m_x = FTOM(MTOF(plr->mo->x - m_w/2)); + * m_y = FTOM(MTOF(plr->mo->y - m_h/2)); + * m_x = plr->mo->x - m_w/2; + * m_y = plr->mo->y - m_h/2; + */ } - AM_initVariables(); - AM_loadPics(); } -// -// set the window scale to the maximum size -// -void AM_minOutWindowScale(void) +/**************************************************************************** + * Name: am_update_light_lev + ****************************************************************************/ + +static void am_update_light_lev(void) { - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); + static int nexttic = 0; + + /* static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; */ + + static int litelevels[] = + { + 0, 4, 7, 10, 12, 14, 15, 15 + }; + + static int litelevelscnt = 0; + + /* Change light level */ + + if (amclock > nexttic) + { + lightlev = litelevels[litelevelscnt++]; + if (litelevelscnt == arrlen(litelevels)) litelevelscnt = 0; + nexttic = amclock + 6 - (amclock % 6); + } } -// -// set the window scale to the minimum size -// -void AM_maxOutWindowScale(void) +/**************************************************************************** + * Name: am_clear_fb + * + * Description: + * Clear automap frame buffer. + * + ****************************************************************************/ + +static void am_clear_fb(int color) { - scale_mtof = max_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); + memset(fb, color, f_w * f_h * sizeof(*fb)); } - -// -// Handle events (user inputs) in automap mode -// -boolean -AM_Responder -( event_t* ev ) +/**************************************************************************** + * Name: am_clip_m_line + * + * Description: + * Automap clipping of lines. + * Based on Cohen-Sutherland clipping algorithm but with a slightly + * faster reject and precalculated slopes. If the speed is needed, + * use a hash algorithm to handle the common cases. + * + ****************************************************************************/ + +static boolean am_clip_m_line(mline_t *ml, fline_t *fl) { + enum + { + LEFT = 1, + RIGHT = 2, + BOTTOM = 4, + TOP = 8 + }; - int rc; - static int bigstate=0; - static char buffer[20]; - int key; + register int outcode1 = 0; + register int outcode2 = 0; + register int outside; - rc = false; + fpoint_t tmp; + int dx; + int dy; - if (ev->type == ev_joystick && joybautomap >= 0 - && (ev->data1 & (1 << joybautomap)) != 0) - { - joywait = I_GetTime() + 5; +#define DOOUTCODE(oc, mx, my) \ + (oc) = 0; \ + if ((my) < 0) \ + (oc) |= TOP; \ + else if ((my) >= f_h) \ + (oc) |= BOTTOM; \ + if ((mx) < 0) \ + (oc) |= LEFT; \ + else if ((mx) >= f_w) \ + (oc) |= RIGHT; - if (!automapactive) - { - AM_Start (); - viewactive = false; - } - else - { - bigstate = 0; - viewactive = true; - AM_Stop (); - } + /* do trivial rejects and outcodes */ - return true; - } + if (ml->a.y > m_y2) + outcode1 = TOP; + else if (ml->a.y < m_y) + outcode1 = BOTTOM; - if (!automapactive) - { - if (ev->type == ev_keydown && ev->data1 == key_map_toggle) - { - AM_Start (); - viewactive = false; - rc = true; - } - } - else if (ev->type == ev_keydown) + if (ml->b.y > m_y2) + outcode2 = TOP; + else if (ml->b.y < m_y) + outcode2 = BOTTOM; + + if (outcode1 & outcode2) return false; /* trivially outside */ + + if (ml->a.x < m_x) + outcode1 |= LEFT; + else if (ml->a.x > m_x2) + outcode1 |= RIGHT; + + if (ml->b.x < m_x) + outcode2 |= LEFT; + else if (ml->b.x > m_x2) + outcode2 |= RIGHT; + + if (outcode1 & outcode2) return false; /* trivially outside */ + + /* transform to frame-buffer coordinates. */ + + fl->a.x = CXMTOF(ml->a.x); + fl->a.y = CYMTOF(ml->a.y); + fl->b.x = CXMTOF(ml->b.x); + fl->b.y = CYMTOF(ml->b.y); + + DOOUTCODE(outcode1, fl->a.x, fl->a.y); + DOOUTCODE(outcode2, fl->b.x, fl->b.y); + + if (outcode1 & outcode2) return false; + + while (outcode1 | outcode2) { - rc = true; - key = ev->data1; + /* may be partially inside box find an outside point */ - if (key == key_map_east) // pan right - { - if (!followplayer) m_paninc.x = FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_west) // pan left - { - if (!followplayer) m_paninc.x = -FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_north) // pan up - { - if (!followplayer) m_paninc.y = FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_south) // pan down - { - if (!followplayer) m_paninc.y = -FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_zoomout) // zoom out - { - mtof_zoommul = M_ZOOMOUT; - ftom_zoommul = M_ZOOMIN; - } - else if (key == key_map_zoomin) // zoom in - { - mtof_zoommul = M_ZOOMIN; - ftom_zoommul = M_ZOOMOUT; - } - else if (key == key_map_toggle) + if (outcode1) + outside = outcode1; + else + outside = outcode2; + + /* clip to each side */ + + if (outside & TOP) { - bigstate = 0; - viewactive = true; - AM_Stop (); + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx * (fl->a.y)) / dy; + tmp.y = 0; } - else if (key == key_map_maxzoom) + else if (outside & BOTTOM) { - bigstate = !bigstate; - if (bigstate) - { - AM_saveScaleAndLoc(); - AM_minOutWindowScale(); - } - else AM_restoreScaleAndLoc(); - } - else if (key == key_map_follow) - { - followplayer = !followplayer; - f_oldloc.x = INT_MAX; - if (followplayer) - plr->message = DEH_String(AMSTR_FOLLOWON); - else - plr->message = DEH_String(AMSTR_FOLLOWOFF); + dy = fl->a.y - fl->b.y; + dx = fl->b.x - fl->a.x; + tmp.x = fl->a.x + (dx * (fl->a.y - f_h)) / dy; + tmp.y = f_h - 1; } - else if (key == key_map_grid) + else if (outside & RIGHT) { - grid = !grid; - if (grid) - plr->message = DEH_String(AMSTR_GRIDON); - else - plr->message = DEH_String(AMSTR_GRIDOFF); + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy * (f_w - 1 - fl->a.x)) / dx; + tmp.x = f_w - 1; } - else if (key == key_map_mark) + else if (outside & LEFT) { - M_snprintf(buffer, sizeof(buffer), "%s %d", - DEH_String(AMSTR_MARKEDSPOT), markpointnum); - plr->message = buffer; - AM_addMark(); + dy = fl->b.y - fl->a.y; + dx = fl->b.x - fl->a.x; + tmp.y = fl->a.y + (dy * (-fl->a.x)) / dx; + tmp.x = 0; } - else if (key == key_map_clearmark) + else { - AM_clearMarks(); - plr->message = DEH_String(AMSTR_MARKSCLEARED); - } - else - { - rc = false; + tmp.x = 0; + tmp.y = 0; } - if ((!deathmatch || gameversion <= exe_doom_1_8) - && cht_CheckCheat(&cheat_amap, ev->data2)) + if (outside == outcode1) { - rc = false; - cheating = (cheating + 1) % 3; + fl->a = tmp; + DOOUTCODE(outcode1, fl->a.x, fl->a.y); } - } - else if (ev->type == ev_keyup) - { - rc = false; - key = ev->data1; - - if (key == key_map_east) + else { - if (!followplayer) m_paninc.x = 0; + fl->b = tmp; + DOOUTCODE(outcode2, fl->b.x, fl->b.y); } - else if (key == key_map_west) - { - if (!followplayer) m_paninc.x = 0; - } - else if (key == key_map_north) - { - if (!followplayer) m_paninc.y = 0; - } - else if (key == key_map_south) - { - if (!followplayer) m_paninc.y = 0; - } - else if (key == key_map_zoomout || key == key_map_zoomin) - { - mtof_zoommul = FRACUNIT; - ftom_zoommul = FRACUNIT; - } - } - return rc; + if (outcode1 & outcode2) return false; /* trivially outside */ + } + return true; } +#undef DOOUTCODE +/**************************************************************************** + * Name: am_draw_f_line + * + * Description: + * Classic Bresenham w/ whatever optimizations needed for speed + * + ****************************************************************************/ -// -// Zooming -// -void AM_changeWindowScale(void) +static void am_draw_f_line(fline_t *fl, int color) { + register int x; + register int y; + register int dx; + register int dy; + register int sx; + register int sy; + register int ax; + register int ay; + register int d; + + static int fuck = 0; + + /* For debugging only */ + + if (fl->a.x < 0 || fl->a.x >= f_w || fl->a.y < 0 || fl->a.y >= f_h || + fl->b.x < 0 || fl->b.x >= f_w || fl->b.y < 0 || fl->b.y >= f_h) + { + fprintf(stderr, "fuck %d \r", fuck++); + return; + } - // Change the scaling multipliers - scale_mtof = FixedMul(scale_mtof, mtof_zoommul); - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); +#define PUTDOT(xx, yy, cc) fb[(yy) * f_w + (xx)] = (cc) - if (scale_mtof < min_scale_mtof) - AM_minOutWindowScale(); - else if (scale_mtof > max_scale_mtof) - AM_maxOutWindowScale(); - else - AM_activateNewScale(); -} + dx = fl->b.x - fl->a.x; + ax = 2 * (dx < 0 ? -dx : dx); + sx = dx < 0 ? -1 : 1; + dy = fl->b.y - fl->a.y; + ay = 2 * (dy < 0 ? -dy : dy); + sy = dy < 0 ? -1 : 1; -// -// -// -void AM_doFollowPlayer(void) -{ + x = fl->a.x; + y = fl->a.y; - if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) + if (ax > ay) { - m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; - m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - f_oldloc.x = plr->mo->x; - f_oldloc.y = plr->mo->y; - - // m_x = FTOM(MTOF(plr->mo->x - m_w/2)); - // m_y = FTOM(MTOF(plr->mo->y - m_h/2)); - // m_x = plr->mo->x - m_w/2; - // m_y = plr->mo->y - m_h/2; + d = ay - ax / 2; + while (1) + { + PUTDOT(x, y, color); + if (x == fl->b.x) return; + if (d >= 0) + { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } } + else + { + d = ax - ay / 2; + while (1) + { + PUTDOT(x, y, color); + if (y == fl->b.y) return; + if (d >= 0) + { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } } -// -// -// -void AM_updateLightLev(void) +/**************************************************************************** + * Name: am_draw_m_line + * + * Description: + * Clip lines, draw visible part sof lines. + * + ****************************************************************************/ + +void am_draw_m_line(mline_t *ml, int color) { - static int nexttic = 0; - //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; - static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; - static int litelevelscnt = 0; - - // Change light level - if (amclock>nexttic) + static fline_t fl; + + if (am_clip_m_line(ml, &fl)) { - lightlev = litelevels[litelevelscnt++]; - if (litelevelscnt == arrlen(litelevels)) litelevelscnt = 0; - nexttic = amclock + 6 - (amclock % 6); - } + /* draws it on frame buffer using fb coords */ + am_draw_f_line(&fl, color); + } } +/**************************************************************************** + * Name: am_draw_grid + * + * Description: + * Draws flat (floor/ceiling tile) aligned grid lines. + * + ****************************************************************************/ -// -// Updates on Game Tick -// -void AM_Ticker (void) +static void am_draw_grid(int color) { + fixed_t x, y; + fixed_t start; + fixed_t end; + mline_t ml; + + /* Figure out start of vertical gridlines */ - if (!automapactive) - return; + start = m_x; + if ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)) + start += (MAPBLOCKUNITS << FRACBITS) - + ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)); + end = m_x + m_w; - amclock++; + /* draw vertical gridlines */ - if (followplayer) - AM_doFollowPlayer(); + ml.a.y = m_y; + ml.b.y = m_y + m_h; + for (x = start; x < end; x += (MAPBLOCKUNITS << FRACBITS)) + { + ml.a.x = x; + ml.b.x = x; + am_draw_m_line(&ml, color); + } - // Change the zoom if necessary - if (ftom_zoommul != FRACUNIT) - AM_changeWindowScale(); + /* Figure out start of horizontal gridlines */ - // Change x,y location - if (m_paninc.x || m_paninc.y) - AM_changeWindowLoc(); + start = m_y; + if ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)) + start += (MAPBLOCKUNITS << FRACBITS) - + ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)); + end = m_y + m_h; - // Update light level - // AM_updateLightLev(); + /* draw horizontal gridlines */ + ml.a.x = m_x; + ml.b.x = m_x + m_w; + for (y = start; y < end; y += (MAPBLOCKUNITS << FRACBITS)) + { + ml.a.y = y; + ml.b.y = y; + am_draw_m_line(&ml, color); + } } +/**************************************************************************** + * Name: am_draw_walls + * + * Description: + * Determines visible lines, draws them. This is LineDef based, not LineSeg + * based. + * + ****************************************************************************/ -// -// Clear automap frame buffer. -// -void AM_clearFB(int color) +static void am_draw_walls(void) { - memset(fb, color, f_w*f_h*sizeof(*fb)); + int i; + static mline_t l; + + for (i = 0; i < numlines; i++) + { + l.a.x = lines[i].v1->x; + l.a.y = lines[i].v1->y; + l.b.x = lines[i].v2->x; + l.b.y = lines[i].v2->y; + if (cheating || (lines[i].flags & ML_MAPPED)) + { + if ((lines[i].flags & LINE_NEVERSEE) && !cheating) continue; + if (!lines[i].backsector) + { + am_draw_m_line(&l, WALLCOLORS + lightlev); + } + else + { + if (lines[i].special == 39) + { + /* teleporters */ + + am_draw_m_line(&l, WALLCOLORS + WALLRANGE / 2); + } + else if (lines[i].flags & ML_SECRET) /* secret door */ + { + if (cheating) + am_draw_m_line(&l, SECRETWALLCOLORS + lightlev); + else + am_draw_m_line(&l, WALLCOLORS + lightlev); + } + else if (lines[i].backsector->floorheight != + lines[i].frontsector->floorheight) + { + /* floor level change */ + + am_draw_m_line(&l, FDWALLCOLORS + lightlev); + } + else if (lines[i].backsector->ceilingheight != + lines[i].frontsector->ceilingheight) + { + /* ceiling level change */ + + am_draw_m_line(&l, CDWALLCOLORS + lightlev); + } + else if (cheating) + { + am_draw_m_line(&l, TSWALLCOLORS + lightlev); + } + } + } + else if (plr->powers[pw_allmap]) + { + if (!(lines[i].flags & LINE_NEVERSEE)) + { + am_draw_m_line(&l, GRAYS + 3); + } + } + } } +/**************************************************************************** + * Name: am_rotate + * + * Description: + * Rotation in 2D. + * Used to rotate player arrow line character. + * + ****************************************************************************/ -// -// Automap clipping of lines. -// -// Based on Cohen-Sutherland clipping algorithm but with a slightly -// faster reject and precalculated slopes. If the speed is needed, -// use a hash algorithm to handle the common cases. -// -boolean -AM_clipMline -( mline_t* ml, - fline_t* fl ) +static void am_rotate(fixed_t *x, fixed_t *y, angle_t a) { - enum - { - LEFT =1, - RIGHT =2, - BOTTOM =4, - TOP =8 - }; - - register int outcode1 = 0; - register int outcode2 = 0; - register int outside; - - fpoint_t tmp; - int dx; - int dy; - - -#define DOOUTCODE(oc, mx, my) \ - (oc) = 0; \ - if ((my) < 0) (oc) |= TOP; \ - else if ((my) >= f_h) (oc) |= BOTTOM; \ - if ((mx) < 0) (oc) |= LEFT; \ - else if ((mx) >= f_w) (oc) |= RIGHT; - - - // do trivial rejects and outcodes - if (ml->a.y > m_y2) - outcode1 = TOP; - else if (ml->a.y < m_y) - outcode1 = BOTTOM; - - if (ml->b.y > m_y2) - outcode2 = TOP; - else if (ml->b.y < m_y) - outcode2 = BOTTOM; - - if (outcode1 & outcode2) - return false; // trivially outside - - if (ml->a.x < m_x) - outcode1 |= LEFT; - else if (ml->a.x > m_x2) - outcode1 |= RIGHT; - - if (ml->b.x < m_x) - outcode2 |= LEFT; - else if (ml->b.x > m_x2) - outcode2 |= RIGHT; - - if (outcode1 & outcode2) - return false; // trivially outside - - // transform to frame-buffer coordinates. - fl->a.x = CXMTOF(ml->a.x); - fl->a.y = CYMTOF(ml->a.y); - fl->b.x = CXMTOF(ml->b.x); - fl->b.y = CYMTOF(ml->b.y); - - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - - if (outcode1 & outcode2) - return false; - - while (outcode1 | outcode2) - { - // may be partially inside box - // find an outside point - if (outcode1) - outside = outcode1; - else - outside = outcode2; - - // clip to each side - if (outside & TOP) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx*(fl->a.y))/dy; - tmp.y = 0; - } - else if (outside & BOTTOM) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy; - tmp.y = f_h-1; - } - else if (outside & RIGHT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx; - tmp.x = f_w-1; - } - else if (outside & LEFT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy*(-fl->a.x))/dx; - tmp.x = 0; - } - else - { - tmp.x = 0; - tmp.y = 0; - } + fixed_t tmpx; - if (outside == outcode1) - { - fl->a = tmp; - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - } - else - { - fl->b = tmp; - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - } - - if (outcode1 & outcode2) - return false; // trivially outside - } + tmpx = fixed_mul(*x, finecosine[a >> ANGLETOFINESHIFT]) - + fixed_mul(*y, finesine[a >> ANGLETOFINESHIFT]); - return true; -} -#undef DOOUTCODE + *y = fixed_mul(*x, finesine[a >> ANGLETOFINESHIFT]) + + fixed_mul(*y, finecosine[a >> ANGLETOFINESHIFT]); + *x = tmpx; +} -// -// Classic Bresenham w/ whatever optimizations needed for speed -// -void -AM_drawFline -( fline_t* fl, - int color ) +static void am_draw_line_character(mline_t *lineguy, int lineguylines, + fixed_t scale, angle_t angle, int color, + fixed_t x, fixed_t y) { - register int x; - register int y; - register int dx; - register int dy; - register int sx; - register int sy; - register int ax; - register int ay; - register int d; - - static int fuck = 0; - - // For debugging only - if ( fl->a.x < 0 || fl->a.x >= f_w - || fl->a.y < 0 || fl->a.y >= f_h - || fl->b.x < 0 || fl->b.x >= f_w - || fl->b.y < 0 || fl->b.y >= f_h) + int i; + mline_t l; + + for (i = 0; i < lineguylines; i++) { - DEH_fprintf(stderr, "fuck %d \r", fuck++); - return; - } + l.a.x = lineguy[i].a.x; + l.a.y = lineguy[i].a.y; -#define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) + if (scale) + { + l.a.x = fixed_mul(scale, l.a.x); + l.a.y = fixed_mul(scale, l.a.y); + } - dx = fl->b.x - fl->a.x; - ax = 2 * (dx<0 ? -dx : dx); - sx = dx<0 ? -1 : 1; + if (angle) am_rotate(&l.a.x, &l.a.y, angle); - dy = fl->b.y - fl->a.y; - ay = 2 * (dy<0 ? -dy : dy); - sy = dy<0 ? -1 : 1; + l.a.x += x; + l.a.y += y; - x = fl->a.x; - y = fl->a.y; + l.b.x = lineguy[i].b.x; + l.b.y = lineguy[i].b.y; - if (ax > ay) - { - d = ay - ax/2; - while (1) - { - PUTDOT(x,y,color); - if (x == fl->b.x) return; - if (d>=0) - { - y += sy; - d -= ax; - } - x += sx; - d += ay; - } - } - else - { - d = ax - ay/2; - while (1) - { - PUTDOT(x, y, color); - if (y == fl->b.y) return; - if (d >= 0) - { - x += sx; - d -= ay; - } - y += sy; - d += ax; - } - } -} + if (scale) + { + l.b.x = fixed_mul(scale, l.b.x); + l.b.y = fixed_mul(scale, l.b.y); + } + if (angle) am_rotate(&l.b.x, &l.b.y, angle); -// -// Clip lines, draw visible part sof lines. -// -void -AM_drawMline -( mline_t* ml, - int color ) -{ - static fline_t fl; + l.b.x += x; + l.b.y += y; - if (AM_clipMline(ml, &fl)) - AM_drawFline(&fl, color); // draws it on frame buffer using fb coords + am_draw_m_line(&l, color); + } } +static void am_draw_players(void) +{ + int i; + player_t *p; + int their_color = -1; + int color; + static int their_colors[] = + { + GREENS, GRAYS, BROWNS, REDS + }; -// -// Draws flat (floor/ceiling tile) aligned grid lines. -// -void AM_drawGrid(int color) -{ - fixed_t x, y; - fixed_t start, end; - mline_t ml; - - // Figure out start of vertical gridlines - start = m_x; - if ((start-bmaporgx)%(MAPBLOCKUNITS<mo->angle, WHITE, plr->mo->x, plr->mo->y); + } + else + { + am_draw_line_character(player_arrow, arrlen(player_arrow), 0, + plr->mo->angle, WHITE, plr->mo->x, + plr->mo->y); + } + + return; } - // Figure out start of horizontal gridlines - start = m_y; - if ((start-bmaporgy)%(MAPBLOCKUNITS<powers[pw_invisibility]) + color = 246; /* *close* to black */ + else + color = their_colors[their_color]; + + am_draw_line_character(player_arrow, arrlen(player_arrow), 0, + p->mo->angle, color, p->mo->x, p->mo->y); + } } -// -// Determines visible lines, draws them. -// This is LineDef based, not LineSeg based. -// -void AM_drawWalls(void) +static void am_draw_things(int colors, int colorrange) { - int i; - static mline_t l; + int i; + mobj_t *t; - for (i=0;ix; - l.a.y = lines[i].v1->y; - l.b.x = lines[i].v2->x; - l.b.y = lines[i].v2->y; - if (cheating || (lines[i].flags & ML_MAPPED)) - { - if ((lines[i].flags & LINE_NEVERSEE) && !cheating) - continue; - if (!lines[i].backsector) - { - AM_drawMline(&l, WALLCOLORS+lightlev); - } - else - { - if (lines[i].special == 39) - { // teleporters - AM_drawMline(&l, WALLCOLORS+WALLRANGE/2); - } - else if (lines[i].flags & ML_SECRET) // secret door - { - if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev); - else AM_drawMline(&l, WALLCOLORS+lightlev); - } - else if (lines[i].backsector->floorheight - != lines[i].frontsector->floorheight) { - AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change - } - else if (lines[i].backsector->ceilingheight - != lines[i].frontsector->ceilingheight) { - AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change - } - else if (cheating) { - AM_drawMline(&l, TSWALLCOLORS+lightlev); - } - } - } - else if (plr->powers[pw_allmap]) - { - if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3); - } + t = sectors[i].thinglist; + while (t) + { + am_draw_line_character(thintriangle_guy, arrlen(thintriangle_guy), + 16 << FRACBITS, t->angle, colors + lightlev, + t->x, t->y); + t = t->snext; + } } } +static void am_draw_marks(void) +{ + int i; + int fx; + int fy; + int w; + int h; + + for (i = 0; i < AM_NUMMARKPOINTS; i++) + { + if (markpoints[i].x != -1) + { + /* w = SHORT(marknums[i]->width); + * h = SHORT(marknums[i]->height); + */ + + w = 5; /* because something's wrong with the wad, i guess */ + h = 6; /* because something's wrong with the wad, i guess */ + fx = CXMTOF(markpoints[i].x); + fy = CYMTOF(markpoints[i].y); + if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) + v_draw_patch(fx, fy, marknums[i]); + } + } +} -// -// Rotation in 2D. -// Used to rotate player arrow line character. -// -void -AM_rotate -( fixed_t* x, - fixed_t* y, - angle_t a ) +static void am_draw_crosshair(int color) { - fixed_t tmpx; + fb[(f_w * (f_h + 1)) / 2] = color; /* single point for now */ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ - tmpx = - FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT]) - - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]); - - *y = - FixedMul(*x,finesine[a>>ANGLETOFINESHIFT]) - + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]); +/**************************************************************************** + * Name: am_stop + ****************************************************************************/ - *x = tmpx; +void am_stop(void) +{ + static event_t st_notify = + { + 0, ev_keyup, AM_MSGEXITED, 0 + }; + + am_unload_pics(); + automapactive = false; + st_responder(&st_notify); + stopped = true; } -void -AM_drawLineCharacter -( mline_t* lineguy, - int lineguylines, - fixed_t scale, - angle_t angle, - int color, - fixed_t x, - fixed_t y ) +/**************************************************************************** + * Name: am_ticker + * + * Description: + * Updates on Game Tick + * + ****************************************************************************/ + +void am_ticker(void) { - int i; - mline_t l; + if (!automapactive) return; - for (i=0;imo->angle, WHITE, plr->mo->x, plr->mo->y); - else - AM_drawLineCharacter - (player_arrow, arrlen(player_arrow), 0, plr->mo->angle, - WHITE, plr->mo->x, plr->mo->y); - return; - } + rc = false; - for (i=0;itype == ev_joystick && joybautomap >= 0 && + (ev->data1 & (1 << joybautomap)) != 0) { - their_color++; - p = &players[i]; - - if ( (deathmatch && !singledemo) && p != plr) - continue; - - if (!playeringame[i]) - continue; - - if (p->powers[pw_invisibility]) - color = 246; // *close* to black - else - color = their_colors[their_color]; - - AM_drawLineCharacter - (player_arrow, arrlen(player_arrow), 0, p->mo->angle, - color, p->mo->x, p->mo->y); - } + joywait = i_get_time() + 5; -} + if (!automapactive) + { + am_start(); + viewactive = false; + } + else + { + bigstate = 0; + viewactive = true; + am_stop(); + } -void -AM_drawThings -( int colors, - int colorrange) -{ - int i; - mobj_t* t; + return true; + } - for (i=0;iangle, colors+lightlev, t->x, t->y); - t = t->snext; - } + if (ev->type == ev_keydown && ev->data1 == key_map_toggle) + { + am_start(); + viewactive = false; + rc = true; + } } -} + else if (ev->type == ev_keydown) + { + rc = true; + key = ev->data1; -void AM_drawMarks(void) -{ - int i, fx, fy, w, h; + if (key == key_map_east) /* pan right */ + { + if (!followplayer) + m_paninc.x = FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_west) /* pan left */ + { + if (!followplayer) + m_paninc.x = -FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_north) /* pan up */ + { + if (!followplayer) + m_paninc.y = FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_south) /* pan down */ + { + if (!followplayer) + m_paninc.y = -FTOM(F_PANINC); + else + rc = false; + } + else if (key == key_map_zoomout) /* zoom out */ + { + mtof_zoommul = M_ZOOMOUT; + ftom_zoommul = M_ZOOMIN; + } + else if (key == key_map_zoomin) /* zoom in */ + { + mtof_zoommul = M_ZOOMIN; + ftom_zoommul = M_ZOOMOUT; + } + else if (key == key_map_toggle) + { + bigstate = 0; + viewactive = true; + am_stop(); + } + else if (key == key_map_maxzoom) + { + bigstate = !bigstate; + if (bigstate) + { + am_save_scale_and_loc(); + am_min_out_window_scale(); + } + else + am_restore_scale_and_loc(); + } + else if (key == key_map_follow) + { + followplayer = !followplayer; + f_oldloc.x = INT_MAX; + if (followplayer) + plr->message = (AMSTR_FOLLOWON); + else + plr->message = (AMSTR_FOLLOWOFF); + } + else if (key == key_map_grid) + { + grid = !grid; + if (grid) + plr->message = (AMSTR_GRIDON); + else + plr->message = (AMSTR_GRIDOFF); + } + else if (key == key_map_mark) + { + snprintf(buffer, sizeof(buffer), "%s %d", (AMSTR_MARKEDSPOT), + markpointnum); + plr->message = buffer; + am_add_mark(); + } + else if (key == key_map_clearmark) + { + am_clear_marks(); + plr->message = (AMSTR_MARKSCLEARED); + } + else + { + rc = false; + } - for (i=0;iwidth); - // h = SHORT(marknums[i]->height); - w = 5; // because something's wrong with the wad, i guess - h = 6; // because something's wrong with the wad, i guess - fx = CXMTOF(markpoints[i].x); - fy = CYMTOF(markpoints[i].y); - if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) - V_DrawPatch(fx, fy, marknums[i]); - } + if ((!deathmatch || gameversion <= exe_doom_1_8) && + cht_check_cheat(&cheat_amap, ev->data2)) + { + rc = false; + cheating = (cheating + 1) % 3; + } } + else if (ev->type == ev_keyup) + { + rc = false; + key = ev->data1; -} - -void AM_drawCrosshair(int color) -{ - fb[(f_w*(f_h+1))/2] = color; // single point for now + if (key == key_map_east) + { + if (!followplayer) m_paninc.x = 0; + } + else if (key == key_map_west) + { + if (!followplayer) m_paninc.x = 0; + } + else if (key == key_map_north) + { + if (!followplayer) m_paninc.y = 0; + } + else if (key == key_map_south) + { + if (!followplayer) m_paninc.y = 0; + } + else if (key == key_map_zoomout || key == key_map_zoomin) + { + mtof_zoommul = FRACUNIT; + ftom_zoommul = FRACUNIT; + } + } + return rc; } -void AM_Drawer (void) +void am_drawer(void) { - if (!automapactive) return; - - AM_clearFB(BACKGROUND); - if (grid) - AM_drawGrid(GRIDCOLORS); - AM_drawWalls(); - AM_drawPlayers(); - if (cheating==2) - AM_drawThings(THINGCOLORS, THINGRANGE); - AM_drawCrosshair(XHAIRCOLORS); + if (!automapactive) return; - AM_drawMarks(); + am_clear_fb(BACKGROUND); + if (grid) am_draw_grid(GRIDCOLORS); + am_draw_walls(); + am_draw_players(); + if (cheating == 2) am_draw_things(THINGCOLORS, THINGRANGE); + am_draw_crosshair(XHAIRCOLORS); - V_MarkRect(f_x, f_y, f_w, f_h); + am_draw_marks(); + v_mark_rect(f_x, f_y, f_w, f_h); } diff --git a/games/NXDoom/src/doom/am_map.h b/games/NXDoom/src/doom/am_map.h index 572d2389bc2..38b8e4ab179 100644 --- a/games/NXDoom/src/doom/am_map.h +++ b/games/NXDoom/src/doom/am_map.h @@ -1,49 +1,95 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// AutoMap module. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/am_map.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * AutoMap module. + * + ****************************************************************************/ #ifndef __AMMAP_H__ #define __AMMAP_H__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_event.h" #include "m_cheat.h" -// Used by ST StatusBar stuff. -#define AM_MSGHEADER (('a'<<24)+('m'<<16)) -#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) -#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Used by ST StatusBar stuff. */ +#define AM_MSGHEADER (('a' << 24) + ('m' << 16)) +#define AM_MSGENTERED (AM_MSGHEADER | ('e' << 8)) +#define AM_MSGEXITED (AM_MSGHEADER | ('x' << 8)) -// Called by main loop. -boolean AM_Responder (event_t* ev); +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Called by main loop. -void AM_Ticker (void); +extern cheatseq_t cheat_amap; -// Called by main loop, -// called instead of view drawer if automap active. -void AM_Drawer (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Called to force the automap to quit -// if the level is completed while it is up. -void AM_Stop (void); +/**************************************************************************** + * Name: am_responder + * + * Description: + * Called by main loop. + * + ****************************************************************************/ +boolean am_responder(event_t *ev); -extern cheatseq_t cheat_amap; +/**************************************************************************** + * Name: am_ticker + * + * Description: + * Called by main loop. + * + ****************************************************************************/ + +void am_ticker(void); + +/**************************************************************************** + * Name: am_ticker + * + * Description: + * Called by main loop. Called instead of view drawer if automap active. + * + ****************************************************************************/ + +void am_drawer(void); + +/**************************************************************************** + * Name: am_stop + * + * Description: + * Called to force the automap to quit if the level is completed while it is + * up. + * + ****************************************************************************/ +void am_stop(void); -#endif +#endif /* __AMMAP_H__ */ diff --git a/games/NXDoom/src/doom/d_englsh.h b/games/NXDoom/src/doom/d_englsh.h index cfb05722c5c..3f0945fc9ac 100644 --- a/games/NXDoom/src/doom/d_englsh.h +++ b/games/NXDoom/src/doom/d_englsh.h @@ -1,693 +1,695 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Printed strings for translation. -// English language support (default). -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_englsh.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Printed strings for translation. + * English language support (default). + * + ****************************************************************************/ #ifndef __D_ENGLSH__ #define __D_ENGLSH__ -// -// Printed strings for translation -// - -// -// D_Main.C -// -#define D_DEVSTR "Development mode ON.\n" -#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n" - -// -// M_Menu.C -// -#define PRESSKEY "press a key." -#define PRESSYN "press y or n." -#define QUITMSG "are you sure you want to\nquit this great game?" -#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY -#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY -#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY -#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY -#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN -#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN - -#define NEWGAME \ -"you can't start a new game\n"\ -"while in a network game.\n\n"PRESSKEY - -#define NIGHTMARE \ -"are you sure? this skill level\n"\ -"isn't even remotely fair.\n\n"PRESSYN - -#define SWSTRING \ -"this is the shareware version of doom.\n\n"\ -"you need to order the entire trilogy.\n\n"PRESSKEY - -#define MSGOFF "Messages OFF" -#define MSGON "Messages ON" -#define NETEND "you can't end a netgame!\n\n"PRESSKEY -#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN - -#define DOSY "(press y to quit to dos.)" - -#define DETAILHI "High detail" -#define DETAILLO "Low detail" -#define GAMMALVL0 "Gamma correction OFF" -#define GAMMALVL1 "Gamma correction level 1" -#define GAMMALVL2 "Gamma correction level 2" -#define GAMMALVL3 "Gamma correction level 3" -#define GAMMALVL4 "Gamma correction level 4" -#define EMPTYSTRING "empty slot" - -// -// P_inter.C -// -#define GOTARMOR "Picked up the armor." -#define GOTMEGA "Picked up the MegaArmor!" -#define GOTHTHBONUS "Picked up a health bonus." -#define GOTARMBONUS "Picked up an armor bonus." -#define GOTSTIM "Picked up a stimpack." -#define GOTMEDINEED "Picked up a medikit that you REALLY need!" -#define GOTMEDIKIT "Picked up a medikit." -#define GOTSUPER "Supercharge!" - -#define GOTBLUECARD "Picked up a blue keycard." -#define GOTYELWCARD "Picked up a yellow keycard." -#define GOTREDCARD "Picked up a red keycard." -#define GOTBLUESKUL "Picked up a blue skull key." -#define GOTYELWSKUL "Picked up a yellow skull key." -#define GOTREDSKULL "Picked up a red skull key." - -#define GOTINVUL "Invulnerability!" -#define GOTBERSERK "Berserk!" -#define GOTINVIS "Partial Invisibility" -#define GOTSUIT "Radiation Shielding Suit" -#define GOTMAP "Computer Area Map" -#define GOTVISOR "Light Amplification Visor" -#define GOTMSPHERE "MegaSphere!" - -#define GOTCLIP "Picked up a clip." -#define GOTCLIPBOX "Picked up a box of bullets." -#define GOTROCKET "Picked up a rocket." -#define GOTROCKBOX "Picked up a box of rockets." -#define GOTCELL "Picked up an energy cell." -#define GOTCELLBOX "Picked up an energy cell pack." -#define GOTSHELLS "Picked up 4 shotgun shells." -#define GOTSHELLBOX "Picked up a box of shotgun shells." -#define GOTBACKPACK "Picked up a backpack full of ammo!" - -#define GOTBFG9000 "You got the BFG9000! Oh, yes." -#define GOTCHAINGUN "You got the chaingun!" -#define GOTCHAINSAW "A chainsaw! Find some meat!" -#define GOTLAUNCHER "You got the rocket launcher!" -#define GOTPLASMA "You got the plasma gun!" -#define GOTSHOTGUN "You got the shotgun!" -#define GOTSHOTGUN2 "You got the super shotgun!" - -// -// P_Doors.C -// -#define PD_BLUEO "You need a blue key to activate this object" -#define PD_REDO "You need a red key to activate this object" -#define PD_YELLOWO "You need a yellow key to activate this object" -#define PD_BLUEK "You need a blue key to open this door" -#define PD_REDK "You need a red key to open this door" -#define PD_YELLOWK "You need a yellow key to open this door" - -// -// G_game.C -// -#define GGSAVED "game saved." - -// -// HU_stuff.C -// -#define HUSTR_MSGU "[Message unsent]" - -#define HUSTR_E1M1 "E1M1: Hangar" -#define HUSTR_E1M2 "E1M2: Nuclear Plant" -#define HUSTR_E1M3 "E1M3: Toxin Refinery" -#define HUSTR_E1M4 "E1M4: Command Control" -#define HUSTR_E1M5 "E1M5: Phobos Lab" -#define HUSTR_E1M6 "E1M6: Central Processing" -#define HUSTR_E1M7 "E1M7: Computer Station" -#define HUSTR_E1M8 "E1M8: Phobos Anomaly" -#define HUSTR_E1M9 "E1M9: Military Base" - -#define HUSTR_E2M1 "E2M1: Deimos Anomaly" -#define HUSTR_E2M2 "E2M2: Containment Area" -#define HUSTR_E2M3 "E2M3: Refinery" -#define HUSTR_E2M4 "E2M4: Deimos Lab" -#define HUSTR_E2M5 "E2M5: Command Center" -#define HUSTR_E2M6 "E2M6: Halls of the Damned" -#define HUSTR_E2M7 "E2M7: Spawning Vats" -#define HUSTR_E2M8 "E2M8: Tower of Babel" -#define HUSTR_E2M9 "E2M9: Fortress of Mystery" - -#define HUSTR_E3M1 "E3M1: Hell Keep" -#define HUSTR_E3M2 "E3M2: Slough of Despair" -#define HUSTR_E3M3 "E3M3: Pandemonium" -#define HUSTR_E3M4 "E3M4: House of Pain" -#define HUSTR_E3M5 "E3M5: Unholy Cathedral" -#define HUSTR_E3M6 "E3M6: Mt. Erebus" -#define HUSTR_E3M7 "E3M7: Limbo" -#define HUSTR_E3M8 "E3M8: Dis" -#define HUSTR_E3M9 "E3M9: Warrens" - -#define HUSTR_E4M1 "E4M1: Hell Beneath" -#define HUSTR_E4M2 "E4M2: Perfect Hatred" -#define HUSTR_E4M3 "E4M3: Sever The Wicked" -#define HUSTR_E4M4 "E4M4: Unruly Evil" -#define HUSTR_E4M5 "E4M5: They Will Repent" -#define HUSTR_E4M6 "E4M6: Against Thee Wickedly" -#define HUSTR_E4M7 "E4M7: And Hell Followed" -#define HUSTR_E4M8 "E4M8: Unto The Cruel" -#define HUSTR_E4M9 "E4M9: Fear" - -#define HUSTR_1 "level 1: entryway" -#define HUSTR_2 "level 2: underhalls" -#define HUSTR_3 "level 3: the gantlet" -#define HUSTR_4 "level 4: the focus" -#define HUSTR_5 "level 5: the waste tunnels" -#define HUSTR_6 "level 6: the crusher" -#define HUSTR_7 "level 7: dead simple" -#define HUSTR_8 "level 8: tricks and traps" -#define HUSTR_9 "level 9: the pit" -#define HUSTR_10 "level 10: refueling base" -#define HUSTR_11 "level 11: 'o' of destruction!" - -#define HUSTR_12 "level 12: the factory" -#define HUSTR_13 "level 13: downtown" -#define HUSTR_14 "level 14: the inmost dens" -#define HUSTR_15 "level 15: industrial zone" -#define HUSTR_16 "level 16: suburbs" -#define HUSTR_17 "level 17: tenements" -#define HUSTR_18 "level 18: the courtyard" -#define HUSTR_19 "level 19: the citadel" -#define HUSTR_20 "level 20: gotcha!" - -#define HUSTR_21 "level 21: nirvana" -#define HUSTR_22 "level 22: the catacombs" -#define HUSTR_23 "level 23: barrels o' fun" -#define HUSTR_24 "level 24: the chasm" -#define HUSTR_25 "level 25: bloodfalls" -#define HUSTR_26 "level 26: the abandoned mines" -#define HUSTR_27 "level 27: monster condo" -#define HUSTR_28 "level 28: the spirit world" -#define HUSTR_29 "level 29: the living end" -#define HUSTR_30 "level 30: icon of sin" - -#define HUSTR_31 "level 31: wolfenstein" -#define HUSTR_32 "level 32: grosse" - -#define PHUSTR_1 "level 1: congo" -#define PHUSTR_2 "level 2: well of souls" -#define PHUSTR_3 "level 3: aztec" -#define PHUSTR_4 "level 4: caged" -#define PHUSTR_5 "level 5: ghost town" -#define PHUSTR_6 "level 6: baron's lair" -#define PHUSTR_7 "level 7: caughtyard" -#define PHUSTR_8 "level 8: realm" -#define PHUSTR_9 "level 9: abattoire" -#define PHUSTR_10 "level 10: onslaught" -#define PHUSTR_11 "level 11: hunted" - -#define PHUSTR_12 "level 12: speed" -#define PHUSTR_13 "level 13: the crypt" -#define PHUSTR_14 "level 14: genesis" -#define PHUSTR_15 "level 15: the twilight" -#define PHUSTR_16 "level 16: the omen" -#define PHUSTR_17 "level 17: compound" -#define PHUSTR_18 "level 18: neurosphere" -#define PHUSTR_19 "level 19: nme" -#define PHUSTR_20 "level 20: the death domain" - -#define PHUSTR_21 "level 21: slayer" -#define PHUSTR_22 "level 22: impossible mission" -#define PHUSTR_23 "level 23: tombstone" -#define PHUSTR_24 "level 24: the final frontier" -#define PHUSTR_25 "level 25: the temple of darkness" -#define PHUSTR_26 "level 26: bunker" -#define PHUSTR_27 "level 27: anti-christ" -#define PHUSTR_28 "level 28: the sewers" -#define PHUSTR_29 "level 29: odyssey of noises" -#define PHUSTR_30 "level 30: the gateway of hell" - -#define PHUSTR_31 "level 31: cyberden" -#define PHUSTR_32 "level 32: go 2 it" - -#define THUSTR_1 "level 1: system control" -#define THUSTR_2 "level 2: human bbq" -#define THUSTR_3 "level 3: power control" -#define THUSTR_4 "level 4: wormhole" -#define THUSTR_5 "level 5: hanger" -#define THUSTR_6 "level 6: open season" -#define THUSTR_7 "level 7: prison" -#define THUSTR_8 "level 8: metal" -#define THUSTR_9 "level 9: stronghold" -#define THUSTR_10 "level 10: redemption" -#define THUSTR_11 "level 11: storage facility" - -#define THUSTR_12 "level 12: crater" -#define THUSTR_13 "level 13: nukage processing" -#define THUSTR_14 "level 14: steel works" -#define THUSTR_15 "level 15: dead zone" -#define THUSTR_16 "level 16: deepest reaches" -#define THUSTR_17 "level 17: processing area" -#define THUSTR_18 "level 18: mill" -#define THUSTR_19 "level 19: shipping/respawning" -#define THUSTR_20 "level 20: central processing" - -#define THUSTR_21 "level 21: administration center" -#define THUSTR_22 "level 22: habitat" -#define THUSTR_23 "level 23: lunar mining project" -#define THUSTR_24 "level 24: quarry" -#define THUSTR_25 "level 25: baron's den" -#define THUSTR_26 "level 26: ballistyx" -#define THUSTR_27 "level 27: mount pain" -#define THUSTR_28 "level 28: heck" -#define THUSTR_29 "level 29: river styx" -#define THUSTR_30 "level 30: last call" - -#define THUSTR_31 "level 31: pharaoh" -#define THUSTR_32 "level 32: caribbean" - -#define HUSTR_CHATMACRO1 "I'm ready to kick butt!" -#define HUSTR_CHATMACRO2 "I'm OK." -#define HUSTR_CHATMACRO3 "I'm not looking too good!" -#define HUSTR_CHATMACRO4 "Help!" -#define HUSTR_CHATMACRO5 "You suck!" -#define HUSTR_CHATMACRO6 "Next time, scumbag..." -#define HUSTR_CHATMACRO7 "Come here!" -#define HUSTR_CHATMACRO8 "I'll take care of it." -#define HUSTR_CHATMACRO9 "Yes" -#define HUSTR_CHATMACRO0 "No" - -#define HUSTR_TALKTOSELF1 "You mumble to yourself" -#define HUSTR_TALKTOSELF2 "Who's there?" -#define HUSTR_TALKTOSELF3 "You scare yourself" -#define HUSTR_TALKTOSELF4 "You start to rave" -#define HUSTR_TALKTOSELF5 "You've lost it..." - -#define HUSTR_MESSAGESENT "[Message Sent]" - -// The following should NOT be changed unless it seems -// just AWFULLY necessary - -#define HUSTR_PLRGREEN "Green: " -#define HUSTR_PLRINDIGO "Indigo: " -#define HUSTR_PLRBROWN "Brown: " -#define HUSTR_PLRRED "Red: " - -#define HUSTR_KEYGREEN 'g' -#define HUSTR_KEYINDIGO 'i' -#define HUSTR_KEYBROWN 'b' -#define HUSTR_KEYRED 'r' - -// -// AM_map.C -// - -#define AMSTR_FOLLOWON "Follow Mode ON" -#define AMSTR_FOLLOWOFF "Follow Mode OFF" - -#define AMSTR_GRIDON "Grid ON" -#define AMSTR_GRIDOFF "Grid OFF" - -#define AMSTR_MARKEDSPOT "Marked Spot" -#define AMSTR_MARKSCLEARED "All Marks Cleared" - -// -// ST_stuff.C -// - -#define STSTR_MUS "Music Change" -#define STSTR_NOMUS "IMPOSSIBLE SELECTION" -#define STSTR_DQDON "Degreelessness Mode On" -#define STSTR_DQDOFF "Degreelessness Mode Off" - -#define STSTR_KFAADDED "Very Happy Ammo Added" -#define STSTR_FAADDED "Ammo (no keys) Added" - -#define STSTR_NCON "No Clipping Mode ON" -#define STSTR_NCOFF "No Clipping Mode OFF" - -#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" -#define STSTR_BEHOLDX "Power-up Toggled" - -#define STSTR_CHOPPERS "... doesn't suck - GM" -#define STSTR_CLEV "Changing Level..." - -// -// F_Finale.C -// -#define E1TEXT \ -"Once you beat the big badasses and\n"\ -"clean out the moon base you're supposed\n"\ -"to win, aren't you? Aren't you? Where's\n"\ -"your fat reward and ticket home? What\n"\ -"the hell is this? It's not supposed to\n"\ -"end this way!\n"\ -"\n" \ -"It stinks like rotten meat, but looks\n"\ -"like the lost Deimos base. Looks like\n"\ -"you're stuck on The Shores of Hell.\n"\ -"The only way out is through.\n"\ -"\n"\ -"To continue the DOOM experience, play\n"\ -"The Shores of Hell and its amazing\n"\ -"sequel, Inferno!\n" - - -#define E2TEXT \ -"You've done it! The hideous cyber-\n"\ -"demon lord that ruled the lost Deimos\n"\ -"moon base has been slain and you\n"\ -"are triumphant! But ... where are\n"\ -"you? You clamber to the edge of the\n"\ -"moon and look down to see the awful\n"\ -"truth.\n" \ -"\n"\ -"Deimos floats above Hell itself!\n"\ -"You've never heard of anyone escaping\n"\ -"from Hell, but you'll make the bastards\n"\ -"sorry they ever heard of you! Quickly,\n"\ -"you rappel down to the surface of\n"\ -"Hell.\n"\ -"\n" \ -"Now, it's on to the final chapter of\n"\ -"DOOM! -- Inferno." - - -#define E3TEXT \ -"The loathsome spiderdemon that\n"\ -"masterminded the invasion of the moon\n"\ -"bases and caused so much death has had\n"\ -"its ass kicked for all time.\n"\ -"\n"\ -"A hidden doorway opens and you enter.\n"\ -"You've proven too tough for Hell to\n"\ -"contain, and now Hell at last plays\n"\ -"fair -- for you emerge from the door\n"\ -"to see the green fields of Earth!\n"\ -"Home at last.\n" \ -"\n"\ -"You wonder what's been happening on\n"\ -"Earth while you were battling evil\n"\ -"unleashed. It's good that no Hell-\n"\ -"spawn could have come through that\n"\ -"door with you ..." - - -#define E4TEXT \ -"the spider mastermind must have sent forth\n"\ -"its legions of hellspawn before your\n"\ -"final confrontation with that terrible\n"\ -"beast from hell. but you stepped forward\n"\ -"and brought forth eternal damnation and\n"\ -"suffering upon the horde as a true hero\n"\ -"would in the face of something so evil.\n"\ -"\n"\ -"besides, someone was gonna pay for what\n"\ -"happened to daisy, your pet rabbit.\n"\ -"\n"\ -"but now, you see spread before you more\n"\ -"potential pain and gibbitude as a nation\n"\ -"of demons run amok among our cities.\n"\ -"\n"\ -"next stop, hell on earth!" - - -// after level 6, put this: - -#define C1TEXT \ -"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ -"STARPORT. BUT SOMETHING IS WRONG. THE\n" \ -"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ -"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ -"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ -"\n"\ -"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ -"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ -"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ -"OF THE STARBASE AND FIND THE CONTROLLING\n" \ -"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ -"HOSTAGE." - -// After level 11, put this: - -#define C2TEXT \ -"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ -"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\ -"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\ -"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\ -"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\ -"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\ -"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\ -"THAT YOU HAVE SAVED YOUR SPECIES.\n"\ -"\n"\ -"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\ -"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\ -"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\ -"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\ -"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\ -"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\ -"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\ -"UP AND RETURN TO THE FRAY." - - -// After level 20, put this: - -#define C3TEXT \ -"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\ -"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\ -"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\ -"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\ -"TEETH AND PLUNGE THROUGH IT.\n"\ -"\n"\ -"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\ -"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\ -"GOT TO GO THROUGH HELL TO GET TO IT?" - - -// After level 29, put this: - -#define C4TEXT \ -"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\ -"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\ -"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\ -"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\ -"UP AND DIES, ITS THRASHING LIMBS\n"\ -"DEVASTATING UNTOLD MILES OF HELL'S\n"\ -"SURFACE.\n"\ -"\n"\ -"YOU'VE DONE IT. THE INVASION IS OVER.\n"\ -"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\ -"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\ -"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\ -"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\ -"HOME. REBUILDING EARTH OUGHT TO BE A\n"\ -"LOT MORE FUN THAN RUINING IT WAS.\n" - - - -// Before level 31, put this: - -#define C5TEXT \ -"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\ -"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\ -"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\ -"WHO THE INMATES OF THIS CORNER OF HELL\n"\ -"WILL BE." - - -// Before level 32, put this: - -#define C6TEXT \ -"CONGRATULATIONS, YOU'VE FOUND THE\n"\ -"SUPER SECRET LEVEL! YOU'D BETTER\n"\ -"BLAZE THROUGH THIS ONE!\n" - - -// after map 06 - -#define P1TEXT \ -"You gloat over the steaming carcass of the\n"\ -"Guardian. With its death, you've wrested\n"\ -"the Accelerator from the stinking claws\n"\ -"of Hell. You relax and glance around the\n"\ -"room. Damn! There was supposed to be at\n"\ -"least one working prototype, but you can't\n"\ -"see it. The demons must have taken it.\n"\ -"\n"\ -"You must find the prototype, or all your\n"\ -"struggles will have been wasted. Keep\n"\ -"moving, keep fighting, keep killing.\n"\ -"Oh yes, keep living, too." - - -// after map 11 - -#define P2TEXT \ -"Even the deadly Arch-Vile labyrinth could\n"\ -"not stop you, and you've gotten to the\n"\ -"prototype Accelerator which is soon\n"\ -"efficiently and permanently deactivated.\n"\ -"\n"\ -"You're good at that kind of thing." - - -// after map 20 - -#define P3TEXT \ -"You've bashed and battered your way into\n"\ -"the heart of the devil-hive. Time for a\n"\ -"Search-and-Destroy mission, aimed at the\n"\ -"Gatekeeper, whose foul offspring is\n"\ -"cascading to Earth. Yeah, he's bad. But\n"\ -"you know who's worse!\n"\ -"\n"\ -"Grinning evilly, you check your gear, and\n"\ -"get ready to give the bastard a little Hell\n"\ -"of your own making!" - -// after map 30 - -#define P4TEXT \ -"The Gatekeeper's evil face is splattered\n"\ -"all over the place. As its tattered corpse\n"\ -"collapses, an inverted Gate forms and\n"\ -"sucks down the shards of the last\n"\ -"prototype Accelerator, not to mention the\n"\ -"few remaining demons. You're done. Hell\n"\ -"has gone back to pounding bad dead folks \n"\ -"instead of good live ones. Remember to\n"\ -"tell your grandkids to put a rocket\n"\ -"launcher in your coffin. If you go to Hell\n"\ -"when you die, you'll need it for some\n"\ -"final cleaning-up ..." - -// before map 31 - -#define P5TEXT \ -"You've found the second-hardest level we\n"\ -"got. Hope you have a saved game a level or\n"\ -"two previous. If not, be prepared to die\n"\ -"aplenty. For master marines only." - -// before map 32 - -#define P6TEXT \ -"Betcha wondered just what WAS the hardest\n"\ -"level we had ready for ya? Now you know.\n"\ -"No one gets out alive." - - -#define T1TEXT \ -"You've fought your way out of the infested\n"\ -"experimental labs. It seems that UAC has\n"\ -"once again gulped it down. With their\n"\ -"high turnover, it must be hard for poor\n"\ -"old UAC to buy corporate health insurance\n"\ -"nowadays..\n"\ -"\n"\ -"Ahead lies the military complex, now\n"\ -"swarming with diseased horrors hot to get\n"\ -"their teeth into you. With luck, the\n"\ -"complex still has some warlike ordnance\n"\ -"laying around." - - -#define T2TEXT \ -"You hear the grinding of heavy machinery\n"\ -"ahead. You sure hope they're not stamping\n"\ -"out new hellspawn, but you're ready to\n"\ -"ream out a whole herd if you have to.\n"\ -"They might be planning a blood feast, but\n"\ -"you feel about as mean as two thousand\n"\ -"maniacs packed into one mad killer.\n"\ -"\n"\ -"You don't plan to go down easy." - - -#define T3TEXT \ -"The vista opening ahead looks real damn\n"\ -"familiar. Smells familiar, too -- like\n"\ -"fried excrement. You didn't like this\n"\ -"place before, and you sure as hell ain't\n"\ -"planning to like it now. The more you\n"\ -"brood on it, the madder you get.\n"\ -"Hefting your gun, an evil grin trickles\n"\ -"onto your face. Time to take some names." - -#define T4TEXT \ -"Suddenly, all is silent, from one horizon\n"\ -"to the other. The agonizing echo of Hell\n"\ -"fades away, the nightmare sky turns to\n"\ -"blue, the heaps of monster corpses start \n"\ -"to evaporate along with the evil stench \n"\ -"that filled the air. Jeeze, maybe you've\n"\ -"done it. Have you really won?\n"\ -"\n"\ -"Something rumbles in the distance.\n"\ -"A blue light begins to glow inside the\n"\ -"ruined skull of the demon-spitter." - - -#define T5TEXT \ -"What now? Looks totally different. Kind\n"\ -"of like King Tut's condo. Well,\n"\ -"whatever's here can't be any worse\n"\ -"than usual. Can it? Or maybe it's best\n"\ -"to let sleeping gods lie.." - - -#define T6TEXT \ -"Time for a vacation. You've burst the\n"\ -"bowels of hell and by golly you're ready\n"\ -"for a break. You mutter to yourself,\n"\ -"Maybe someone else can kick Hell's ass\n"\ -"next time around. Ahead lies a quiet town,\n"\ -"with peaceful flowing water, quaint\n"\ -"buildings, and presumably no Hellspawn.\n"\ -"\n"\ -"As you step off the transport, you hear\n"\ -"the stomp of a cyberdemon's iron shoe." - - - -// -// Character cast strings F_FINALE.C -// -#define CC_ZOMBIE "ZOMBIEMAN" -#define CC_SHOTGUN "SHOTGUN GUY" -#define CC_HEAVY "HEAVY WEAPON DUDE" -#define CC_IMP "IMP" -#define CC_DEMON "DEMON" -#define CC_LOST "LOST SOUL" -#define CC_CACO "CACODEMON" -#define CC_HELL "HELL KNIGHT" -#define CC_BARON "BARON OF HELL" -#define CC_ARACH "ARACHNOTRON" -#define CC_PAIN "PAIN ELEMENTAL" -#define CC_REVEN "REVENANT" -#define CC_MANCU "MANCUBUS" -#define CC_ARCH "ARCH-VILE" -#define CC_SPIDER "THE SPIDER MASTERMIND" -#define CC_CYBER "THE CYBERDEMON" -#define CC_HERO "OUR HERO" - - -#endif +/* Printed strings for translation */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* D_Main.C */ + +#define D_DEVSTR "Development mode ON.\n" +#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n" + +/* M_Menu.C */ + +#define PRESSKEY "press a key." +#define PRESSYN "press y or n." +#define QUITMSG "are you sure you want to\nquit this great game?" +#define LOADNET "you can't do load while in a net game!\n\n" PRESSKEY +#define QLOADNET "you can't quickload during a netgame!\n\n" PRESSKEY +#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n" PRESSKEY +#define SAVEDEAD "you can't save if you aren't playing!\n\n" PRESSKEY +#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n" PRESSYN +#define QLPROMPT \ + "do you want to quickload the game named\n\n'%s'?\n\n" PRESSYN + +#define NEWGAME \ + "you can't start a new game\n" \ + "while in a network game.\n\n" PRESSKEY + +#define NIGHTMARE \ + "are you sure? this skill level\n" \ + "isn't even remotely fair.\n\n" PRESSYN + +#define SWSTRING \ + "this is the shareware version of doom.\n\n" \ + "you need to order the entire trilogy.\n\n" PRESSKEY + +#define MSGOFF "Messages OFF" +#define MSGON "Messages ON" +#define NETEND "you can't end a netgame!\n\n" PRESSKEY +#define ENDGAME "are you sure you want to end the game?\n\n" PRESSYN + +#define DOSY "(press y to quit to dos.)" + +#define DETAILHI "High detail" +#define DETAILLO "Low detail" +#define GAMMALVL0 "Gamma correction OFF" +#define GAMMALVL1 "Gamma correction level 1" +#define GAMMALVL2 "Gamma correction level 2" +#define GAMMALVL3 "Gamma correction level 3" +#define GAMMALVL4 "Gamma correction level 4" +#define EMPTYSTRING "empty slot" + +/* P_inter.C */ + +#define GOTARMOR "Picked up the armor." +#define GOTMEGA "Picked up the MegaArmor!" +#define GOTHTHBONUS "Picked up a health bonus." +#define GOTARMBONUS "Picked up an armor bonus." +#define GOTSTIM "Picked up a stimpack." +#define GOTMEDINEED "Picked up a medikit that you REALLY need!" +#define GOTMEDIKIT "Picked up a medikit." +#define GOTSUPER "Supercharge!" + +#define GOTBLUECARD "Picked up a blue keycard." +#define GOTYELWCARD "Picked up a yellow keycard." +#define GOTREDCARD "Picked up a red keycard." +#define GOTBLUESKUL "Picked up a blue skull key." +#define GOTYELWSKUL "Picked up a yellow skull key." +#define GOTREDSKULL "Picked up a red skull key." + +#define GOTINVUL "Invulnerability!" +#define GOTBERSERK "Berserk!" +#define GOTINVIS "Partial Invisibility" +#define GOTSUIT "Radiation Shielding Suit" +#define GOTMAP "Computer Area Map" +#define GOTVISOR "Light Amplification Visor" +#define GOTMSPHERE "MegaSphere!" + +#define GOTCLIP "Picked up a clip." +#define GOTCLIPBOX "Picked up a box of bullets." +#define GOTROCKET "Picked up a rocket." +#define GOTROCKBOX "Picked up a box of rockets." +#define GOTCELL "Picked up an energy cell." +#define GOTCELLBOX "Picked up an energy cell pack." +#define GOTSHELLS "Picked up 4 shotgun shells." +#define GOTSHELLBOX "Picked up a box of shotgun shells." +#define GOTBACKPACK "Picked up a backpack full of ammo!" + +#define GOTBFG9000 "You got the BFG9000! Oh, yes." +#define GOTCHAINGUN "You got the chaingun!" +#define GOTCHAINSAW "A chainsaw! Find some meat!" +#define GOTLAUNCHER "You got the rocket launcher!" +#define GOTPLASMA "You got the plasma gun!" +#define GOTSHOTGUN "You got the shotgun!" +#define GOTSHOTGUN2 "You got the super shotgun!" + +/* P_Doors.C */ + +#define PD_BLUEO "You need a blue key to activate this object" +#define PD_REDO "You need a red key to activate this object" +#define PD_YELLOWO "You need a yellow key to activate this object" +#define PD_BLUEK "You need a blue key to open this door" +#define PD_REDK "You need a red key to open this door" +#define PD_YELLOWK "You need a yellow key to open this door" + +/* G_game.C */ + +#define GGSAVED "game saved." + +/* HU_stuff.C */ + +#define HUSTR_MSGU "[Message unsent]" + +#define HUSTR_E1M1 "E1M1: Hangar" +#define HUSTR_E1M2 "E1M2: Nuclear Plant" +#define HUSTR_E1M3 "E1M3: Toxin Refinery" +#define HUSTR_E1M4 "E1M4: Command Control" +#define HUSTR_E1M5 "E1M5: Phobos Lab" +#define HUSTR_E1M6 "E1M6: Central Processing" +#define HUSTR_E1M7 "E1M7: Computer Station" +#define HUSTR_E1M8 "E1M8: Phobos Anomaly" +#define HUSTR_E1M9 "E1M9: Military Base" + +#define HUSTR_E2M1 "E2M1: Deimos Anomaly" +#define HUSTR_E2M2 "E2M2: Containment Area" +#define HUSTR_E2M3 "E2M3: Refinery" +#define HUSTR_E2M4 "E2M4: Deimos Lab" +#define HUSTR_E2M5 "E2M5: Command Center" +#define HUSTR_E2M6 "E2M6: Halls of the Damned" +#define HUSTR_E2M7 "E2M7: Spawning Vats" +#define HUSTR_E2M8 "E2M8: Tower of Babel" +#define HUSTR_E2M9 "E2M9: Fortress of Mystery" + +#define HUSTR_E3M1 "E3M1: Hell Keep" +#define HUSTR_E3M2 "E3M2: Slough of Despair" +#define HUSTR_E3M3 "E3M3: Pandemonium" +#define HUSTR_E3M4 "E3M4: House of Pain" +#define HUSTR_E3M5 "E3M5: Unholy Cathedral" +#define HUSTR_E3M6 "E3M6: Mt. Erebus" +#define HUSTR_E3M7 "E3M7: Limbo" +#define HUSTR_E3M8 "E3M8: Dis" +#define HUSTR_E3M9 "E3M9: Warrens" + +#define HUSTR_E4M1 "E4M1: Hell Beneath" +#define HUSTR_E4M2 "E4M2: Perfect Hatred" +#define HUSTR_E4M3 "E4M3: Sever The Wicked" +#define HUSTR_E4M4 "E4M4: Unruly Evil" +#define HUSTR_E4M5 "E4M5: They Will Repent" +#define HUSTR_E4M6 "E4M6: Against Thee Wickedly" +#define HUSTR_E4M7 "E4M7: And Hell Followed" +#define HUSTR_E4M8 "E4M8: Unto The Cruel" +#define HUSTR_E4M9 "E4M9: Fear" + +#define HUSTR_1 "level 1: entryway" +#define HUSTR_2 "level 2: underhalls" +#define HUSTR_3 "level 3: the gantlet" +#define HUSTR_4 "level 4: the focus" +#define HUSTR_5 "level 5: the waste tunnels" +#define HUSTR_6 "level 6: the crusher" +#define HUSTR_7 "level 7: dead simple" +#define HUSTR_8 "level 8: tricks and traps" +#define HUSTR_9 "level 9: the pit" +#define HUSTR_10 "level 10: refueling base" +#define HUSTR_11 "level 11: 'o' of destruction!" + +#define HUSTR_12 "level 12: the factory" +#define HUSTR_13 "level 13: downtown" +#define HUSTR_14 "level 14: the inmost dens" +#define HUSTR_15 "level 15: industrial zone" +#define HUSTR_16 "level 16: suburbs" +#define HUSTR_17 "level 17: tenements" +#define HUSTR_18 "level 18: the courtyard" +#define HUSTR_19 "level 19: the citadel" +#define HUSTR_20 "level 20: gotcha!" + +#define HUSTR_21 "level 21: nirvana" +#define HUSTR_22 "level 22: the catacombs" +#define HUSTR_23 "level 23: barrels o' fun" +#define HUSTR_24 "level 24: the chasm" +#define HUSTR_25 "level 25: bloodfalls" +#define HUSTR_26 "level 26: the abandoned mines" +#define HUSTR_27 "level 27: monster condo" +#define HUSTR_28 "level 28: the spirit world" +#define HUSTR_29 "level 29: the living end" +#define HUSTR_30 "level 30: icon of sin" + +#define HUSTR_31 "level 31: wolfenstein" +#define HUSTR_32 "level 32: grosse" + +#define PHUSTR_1 "level 1: congo" +#define PHUSTR_2 "level 2: well of souls" +#define PHUSTR_3 "level 3: aztec" +#define PHUSTR_4 "level 4: caged" +#define PHUSTR_5 "level 5: ghost town" +#define PHUSTR_6 "level 6: baron's lair" +#define PHUSTR_7 "level 7: caughtyard" +#define PHUSTR_8 "level 8: realm" +#define PHUSTR_9 "level 9: abattoire" +#define PHUSTR_10 "level 10: onslaught" +#define PHUSTR_11 "level 11: hunted" + +#define PHUSTR_12 "level 12: speed" +#define PHUSTR_13 "level 13: the crypt" +#define PHUSTR_14 "level 14: genesis" +#define PHUSTR_15 "level 15: the twilight" +#define PHUSTR_16 "level 16: the omen" +#define PHUSTR_17 "level 17: compound" +#define PHUSTR_18 "level 18: neurosphere" +#define PHUSTR_19 "level 19: nme" +#define PHUSTR_20 "level 20: the death domain" + +#define PHUSTR_21 "level 21: slayer" +#define PHUSTR_22 "level 22: impossible mission" +#define PHUSTR_23 "level 23: tombstone" +#define PHUSTR_24 "level 24: the final frontier" +#define PHUSTR_25 "level 25: the temple of darkness" +#define PHUSTR_26 "level 26: bunker" +#define PHUSTR_27 "level 27: anti-christ" +#define PHUSTR_28 "level 28: the sewers" +#define PHUSTR_29 "level 29: odyssey of noises" +#define PHUSTR_30 "level 30: the gateway of hell" + +#define PHUSTR_31 "level 31: cyberden" +#define PHUSTR_32 "level 32: go 2 it" + +#define THUSTR_1 "level 1: system control" +#define THUSTR_2 "level 2: human bbq" +#define THUSTR_3 "level 3: power control" +#define THUSTR_4 "level 4: wormhole" +#define THUSTR_5 "level 5: hanger" +#define THUSTR_6 "level 6: open season" +#define THUSTR_7 "level 7: prison" +#define THUSTR_8 "level 8: metal" +#define THUSTR_9 "level 9: stronghold" +#define THUSTR_10 "level 10: redemption" +#define THUSTR_11 "level 11: storage facility" + +#define THUSTR_12 "level 12: crater" +#define THUSTR_13 "level 13: nukage processing" +#define THUSTR_14 "level 14: steel works" +#define THUSTR_15 "level 15: dead zone" +#define THUSTR_16 "level 16: deepest reaches" +#define THUSTR_17 "level 17: processing area" +#define THUSTR_18 "level 18: mill" +#define THUSTR_19 "level 19: shipping/respawning" +#define THUSTR_20 "level 20: central processing" + +#define THUSTR_21 "level 21: administration center" +#define THUSTR_22 "level 22: habitat" +#define THUSTR_23 "level 23: lunar mining project" +#define THUSTR_24 "level 24: quarry" +#define THUSTR_25 "level 25: baron's den" +#define THUSTR_26 "level 26: ballistyx" +#define THUSTR_27 "level 27: mount pain" +#define THUSTR_28 "level 28: heck" +#define THUSTR_29 "level 29: river styx" +#define THUSTR_30 "level 30: last call" + +#define THUSTR_31 "level 31: pharaoh" +#define THUSTR_32 "level 32: caribbean" + +#define HUSTR_CHATMACRO1 "I'm ready to kick butt!" +#define HUSTR_CHATMACRO2 "I'm OK." +#define HUSTR_CHATMACRO3 "I'm not looking too good!" +#define HUSTR_CHATMACRO4 "Help!" +#define HUSTR_CHATMACRO5 "You suck!" +#define HUSTR_CHATMACRO6 "Next time, scumbag..." +#define HUSTR_CHATMACRO7 "Come here!" +#define HUSTR_CHATMACRO8 "I'll take care of it." +#define HUSTR_CHATMACRO9 "Yes" +#define HUSTR_CHATMACRO0 "No" + +#define HUSTR_TALKTOSELF1 "You mumble to yourself" +#define HUSTR_TALKTOSELF2 "Who's there?" +#define HUSTR_TALKTOSELF3 "You scare yourself" +#define HUSTR_TALKTOSELF4 "You start to rave" +#define HUSTR_TALKTOSELF5 "You've lost it..." + +#define HUSTR_MESSAGESENT "[Message Sent]" + +/* The following should NOT be changed unless it seems just AWFULLY + * necessary + */ + +#define HUSTR_PLRGREEN "Green: " +#define HUSTR_PLRINDIGO "Indigo: " +#define HUSTR_PLRBROWN "Brown: " +#define HUSTR_PLRRED "Red: " + +#define HUSTR_KEYGREEN 'g' +#define HUSTR_KEYINDIGO 'i' +#define HUSTR_KEYBROWN 'b' +#define HUSTR_KEYRED 'r' + +/* AM_map.C */ + +#define AMSTR_FOLLOWON "Follow Mode ON" +#define AMSTR_FOLLOWOFF "Follow Mode OFF" + +#define AMSTR_GRIDON "Grid ON" +#define AMSTR_GRIDOFF "Grid OFF" + +#define AMSTR_MARKEDSPOT "Marked Spot" +#define AMSTR_MARKSCLEARED "All Marks Cleared" + +/* ST_stuff.C */ + +#define STSTR_MUS "Music Change" +#define STSTR_NOMUS "IMPOSSIBLE SELECTION" +#define STSTR_DQDON "Degreelessness Mode On" +#define STSTR_DQDOFF "Degreelessness Mode Off" + +#define STSTR_KFAADDED "Very Happy Ammo Added" +#define STSTR_FAADDED "Ammo (no keys) Added" + +#define STSTR_NCON "No Clipping Mode ON" +#define STSTR_NCOFF "No Clipping Mode OFF" + +#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" +#define STSTR_BEHOLDX "Power-up Toggled" + +#define STSTR_CHOPPERS "... doesn't suck - GM" +#define STSTR_CLEV "Changing Level..." + +/* F_Finale.C */ + +#define E1TEXT \ + "Once you beat the big badasses and\n" \ + "clean out the moon base you're supposed\n" \ + "to win, aren't you? Aren't you? Where's\n" \ + "your fat reward and ticket home? What\n" \ + "the hell is this? It's not supposed to\n" \ + "end this way!\n" \ + "\n" \ + "It stinks like rotten meat, but looks\n" \ + "like the lost Deimos base. Looks like\n" \ + "you're stuck on The Shores of Hell.\n" \ + "The only way out is through.\n" \ + "\n" \ + "To continue the DOOM experience, play\n" \ + "The Shores of Hell and its amazing\n" \ + "sequel, Inferno!\n" + +#define E2TEXT \ + "You've done it! The hideous cyber-\n" \ + "demon lord that ruled the lost Deimos\n" \ + "moon base has been slain and you\n" \ + "are triumphant! But ... where are\n" \ + "you? You clamber to the edge of the\n" \ + "moon and look down to see the awful\n" \ + "truth.\n" \ + "\n" \ + "Deimos floats above Hell itself!\n" \ + "You've never heard of anyone escaping\n" \ + "from Hell, but you'll make the bastards\n" \ + "sorry they ever heard of you! Quickly,\n" \ + "you rappel down to the surface of\n" \ + "Hell.\n" \ + "\n" \ + "Now, it's on to the final chapter of\n" \ + "DOOM! -- Inferno." + +#define E3TEXT \ + "The loathsome spiderdemon that\n" \ + "masterminded the invasion of the moon\n" \ + "bases and caused so much death has had\n" \ + "its ass kicked for all time.\n" \ + "\n" \ + "A hidden doorway opens and you enter.\n" \ + "You've proven too tough for Hell to\n" \ + "contain, and now Hell at last plays\n" \ + "fair -- for you emerge from the door\n" \ + "to see the green fields of Earth!\n" \ + "Home at last.\n" \ + "\n" \ + "You wonder what's been happening on\n" \ + "Earth while you were battling evil\n" \ + "unleashed. It's good that no Hell-\n" \ + "spawn could have come through that\n" \ + "door with you ..." + +#define E4TEXT \ + "the spider mastermind must have sent forth\n" \ + "its legions of hellspawn before your\n" \ + "final confrontation with that terrible\n" \ + "beast from hell. but you stepped forward\n" \ + "and brought forth eternal damnation and\n" \ + "suffering upon the horde as a true hero\n" \ + "would in the face of something so evil.\n" \ + "\n" \ + "besides, someone was gonna pay for what\n" \ + "happened to daisy, your pet rabbit.\n" \ + "\n" \ + "but now, you see spread before you more\n" \ + "potential pain and gibbitude as a nation\n" \ + "of demons run amok among our cities.\n" \ + "\n" \ + "next stop, hell on earth!" + +/* after level 6, put this: */ + +#define C1TEXT \ + "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ + "STARPORT. BUT SOMETHING IS WRONG. THE\n" \ + "MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ + "WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ + "IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ + "\n" \ + "AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ + "FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ + "YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ + "OF THE STARBASE AND FIND THE CONTROLLING\n" \ + "SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ + "HOSTAGE." + +/* After level 11, put this: */ + +#define C2TEXT \ + "YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ + "HUMANKIND TO EVACUATE EARTH AND ESCAPE\n" \ + "THE NIGHTMARE. NOW YOU ARE THE ONLY\n" \ + "HUMAN LEFT ON THE FACE OF THE PLANET.\n" \ + "CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n" \ + "AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n" \ + "YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n" \ + "THAT YOU HAVE SAVED YOUR SPECIES.\n" \ + "\n" \ + "BUT THEN, EARTH CONTROL BEAMS DOWN A\n" \ + "MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n" \ + "THE SOURCE OF THE ALIEN INVASION. IF YOU\n" \ + "GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n" \ + "ENTRY. THE ALIEN BASE IS IN THE HEART OF\n" \ + "YOUR OWN HOME CITY, NOT FAR FROM THE\n" \ + "STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n" \ + "UP AND RETURN TO THE FRAY." + +/* After level 20, put this: */ + +#define C3TEXT \ + "YOU ARE AT THE CORRUPT HEART OF THE CITY,\n" \ + "SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n" \ + "YOU SEE NO WAY TO DESTROY THE CREATURES'\n" \ + "ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n" \ + "TEETH AND PLUNGE THROUGH IT.\n" \ + "\n" \ + "THERE MUST BE A WAY TO CLOSE IT ON THE\n" \ + "OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n" \ + "GOT TO GO THROUGH HELL TO GET TO IT?" + +/* After level 29, put this: */ + +#define C4TEXT \ + "THE HORRENDOUS VISAGE OF THE BIGGEST\n" \ + "DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n" \ + "YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n" \ + "HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n" \ + "UP AND DIES, ITS THRASHING LIMBS\n" \ + "DEVASTATING UNTOLD MILES OF HELL'S\n" \ + "SURFACE.\n" \ + "\n" \ + "YOU'VE DONE IT. THE INVASION IS OVER.\n" \ + "EARTH IS SAVED. HELL IS A WRECK. YOU\n" \ + "WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n" \ + "DIE, NOW. WIPING THE SWEAT FROM YOUR\n" \ + "FOREHEAD YOU BEGIN THE LONG TREK BACK\n" \ + "HOME. REBUILDING EARTH OUGHT TO BE A\n" \ + "LOT MORE FUN THAN RUINING IT WAS.\n" + +/* Before level 31, put this: */ + +#define C5TEXT \ + "CONGRATULATIONS, YOU'VE FOUND THE SECRET\n" \ + "LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n" \ + "HUMANS, RATHER THAN DEMONS. YOU WONDER\n" \ + "WHO THE INMATES OF THIS CORNER OF HELL\n" \ + "WILL BE." + +/* Before level 32, put this: */ + +#define C6TEXT \ + "CONGRATULATIONS, YOU'VE FOUND THE\n" \ + "SUPER SECRET LEVEL! YOU'D BETTER\n" \ + "BLAZE THROUGH THIS ONE!\n" + +/* after map 06 */ + +#define P1TEXT \ + "You gloat over the steaming carcass of the\n" \ + "Guardian. With its death, you've wrested\n" \ + "the Accelerator from the stinking claws\n" \ + "of Hell. You relax and glance around the\n" \ + "room. Damn! There was supposed to be at\n" \ + "least one working prototype, but you can't\n" \ + "see it. The demons must have taken it.\n" \ + "\n" \ + "You must find the prototype, or all your\n" \ + "struggles will have been wasted. Keep\n" \ + "moving, keep fighting, keep killing.\n" \ + "Oh yes, keep living, too." + +/* after map 11 */ + +#define P2TEXT \ + "Even the deadly Arch-Vile labyrinth could\n" \ + "not stop you, and you've gotten to the\n" \ + "prototype Accelerator which is soon\n" \ + "efficiently and permanently deactivated.\n" \ + "\n" \ + "You're good at that kind of thing." + +/* after map 20 */ + +#define P3TEXT \ + "You've bashed and battered your way into\n" \ + "the heart of the devil-hive. Time for a\n" \ + "Search-and-Destroy mission, aimed at the\n" \ + "Gatekeeper, whose foul offspring is\n" \ + "cascading to Earth. Yeah, he's bad. But\n" \ + "you know who's worse!\n" \ + "\n" \ + "Grinning evilly, you check your gear, and\n" \ + "get ready to give the bastard a little Hell\n" \ + "of your own making!" + +/* after map 30 */ + +#define P4TEXT \ + "The Gatekeeper's evil face is splattered\n" \ + "all over the place. As its tattered corpse\n" \ + "collapses, an inverted Gate forms and\n" \ + "sucks down the shards of the last\n" \ + "prototype Accelerator, not to mention the\n" \ + "few remaining demons. You're done. Hell\n" \ + "has gone back to pounding bad dead folks \n" \ + "instead of good live ones. Remember to\n" \ + "tell your grandkids to put a rocket\n" \ + "launcher in your coffin. If you go to Hell\n" \ + "when you die, you'll need it for some\n" \ + "final cleaning-up ..." + +/* before map 31 */ + +#define P5TEXT \ + "You've found the second-hardest level we\n" \ + "got. Hope you have a saved game a level or\n" \ + "two previous. If not, be prepared to die\n" \ + "aplenty. For master marines only." + +/* before map 32 */ + +#define P6TEXT \ + "Betcha wondered just what WAS the hardest\n" \ + "level we had ready for ya? Now you know.\n" \ + "No one gets out alive." + +#define T1TEXT \ + "You've fought your way out of the infested\n" \ + "experimental labs. It seems that UAC has\n" \ + "once again gulped it down. With their\n" \ + "high turnover, it must be hard for poor\n" \ + "old UAC to buy corporate health insurance\n" \ + "nowadays..\n" \ + "\n" \ + "Ahead lies the military complex, now\n" \ + "swarming with diseased horrors hot to get\n" \ + "their teeth into you. With luck, the\n" \ + "complex still has some warlike ordnance\n" \ + "laying around." + +#define T2TEXT \ + "You hear the grinding of heavy machinery\n" \ + "ahead. You sure hope they're not stamping\n" \ + "out new hellspawn, but you're ready to\n" \ + "ream out a whole herd if you have to.\n" \ + "They might be planning a blood feast, but\n" \ + "you feel about as mean as two thousand\n" \ + "maniacs packed into one mad killer.\n" \ + "\n" \ + "You don't plan to go down easy." + +#define T3TEXT \ + "The vista opening ahead looks real damn\n" \ + "familiar. Smells familiar, too -- like\n" \ + "fried excrement. You didn't like this\n" \ + "place before, and you sure as hell ain't\n" \ + "planning to like it now. The more you\n" \ + "brood on it, the madder you get.\n" \ + "Hefting your gun, an evil grin trickles\n" \ + "onto your face. Time to take some names." + +#define T4TEXT \ + "Suddenly, all is silent, from one horizon\n" \ + "to the other. The agonizing echo of Hell\n" \ + "fades away, the nightmare sky turns to\n" \ + "blue, the heaps of monster corpses start \n" \ + "to evaporate along with the evil stench \n" \ + "that filled the air. Jeeze, maybe you've\n" \ + "done it. Have you really won?\n" \ + "\n" \ + "Something rumbles in the distance.\n" \ + "A blue light begins to glow inside the\n" \ + "ruined skull of the demon-spitter." + +#define T5TEXT \ + "What now? Looks totally different. Kind\n" \ + "of like King Tut's condo. Well,\n" \ + "whatever's here can't be any worse\n" \ + "than usual. Can it? Or maybe it's best\n" \ + "to let sleeping gods lie.." + +#define T6TEXT \ + "Time for a vacation. You've burst the\n" \ + "bowels of hell and by golly you're ready\n" \ + "for a break. You mutter to yourself,\n" \ + "Maybe someone else can kick Hell's ass\n" \ + "next time around. Ahead lies a quiet town,\n" \ + "with peaceful flowing water, quaint\n" \ + "buildings, and presumably no Hellspawn.\n" \ + "\n" \ + "As you step off the transport, you hear\n" \ + "the stomp of a cyberdemon's iron shoe." + +/* Character cast strings F_FINALE.C */ + +#define CC_ZOMBIE "ZOMBIEMAN" +#define CC_SHOTGUN "SHOTGUN GUY" +#define CC_HEAVY "HEAVY WEAPON DUDE" +#define CC_IMP "IMP" +#define CC_DEMON "DEMON" +#define CC_LOST "LOST SOUL" +#define CC_CACO "CACODEMON" +#define CC_HELL "HELL KNIGHT" +#define CC_BARON "BARON OF HELL" +#define CC_ARACH "ARACHNOTRON" +#define CC_PAIN "PAIN ELEMENTAL" +#define CC_REVEN "REVENANT" +#define CC_MANCU "MANCUBUS" +#define CC_ARCH "ARCH-VILE" +#define CC_SPIDER "THE SPIDER MASTERMIND" +#define CC_CYBER "THE CYBERDEMON" +#define CC_HERO "OUR HERO" + +/* DOOM end messages */ + +#define DOOM1_ENDMSG \ + "are you sure you want to\nquit this great game?", \ + "please don't leave, there's more\ndemons to toast!", \ + "let's beat it -- this is turning\ninto a bloodbath!", \ + "i wouldn't leave if i were you.\ndos is much worse.", \ + "you're trying to say you like dos\nbetter than me, right?", \ + "don't leave yet -- there's a\ndemon around that corner!", \ + "ya know, next time you come in here\ni'm gonna toast ya.", \ + "go ahead and leave. see if i care.", + +/* QuitDOOM II messages */ + +#define DOOM2_ENDMSG \ + "are you sure you want to\nquit this great game?", \ + "you want to quit?\nthen, thou hast lost an eighth!", \ + "don't go now, there's a \ndimensional shambler waiting\nat the dos " \ + "prompt!", \ + "get outta here and go back\nto your boring programs.", \ + "if i were your boss, i'd \n deathmatch ya in a minute!", \ + "look, bud. you leave now\nand you forfeit your body count!", \ + "just leave. when you come\nback, i'll be waiting with a bat.", \ + "you're lucky i don't smack\nyou for thinking about leaving.", + +#endif /* __D_ENGLSH__ */ diff --git a/games/NXDoom/src/doom/d_french.h b/games/NXDoom/src/doom/d_french.h new file mode 100644 index 00000000000..0252aa7471d --- /dev/null +++ b/games/NXDoom/src/doom/d_french.h @@ -0,0 +1,698 @@ +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_french.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Printed strings for translation. + * French language support. + * TODO: finish implementation + * WARN: Non-ascii text does not render properly. Find a solution or cope. + * + ****************************************************************************/ + +#ifndef __D_FRENCH__ +#define __D_FRENCH__ + +/* Printed strings for translation */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* D_Main.C */ + +#define D_DEVSTR "Mode développement activé.\n" +#define D_CDROM "Version CD-ROM: default.cfg de c:\\doomdata\n" + +/* M_Menu.C */ + +#define PRESSKEY "appuie une touche." +#define PRESSYN "appuie y ou n." +#define QUITMSG "es-tu certain que tu veux quitter ce super jeu ?" +#define LOADNET "tu ne peux pas charger pendant un jeu en ligne!\n\n" PRESSKEY +#define QLOADNET \ + "tu ne peux pas charger rapidement pendant un jeu en ligne!\n\n" PRESSKEY +#define QSAVESPOT "tu n'as pas choisi un slot sauvegarde rapide\n\n" PRESSKEY +#define SAVEDEAD "tu ne peux pas sauvegarder si tu ne joue pas\n\n" PRESSKEY +#define QSPROMPT "sauvegarde ton jeu nommé\n\n'%s'?\n\n" PRESSYN +#define QLPROMPT \ + "tu veux charger rapidement le jeu nommé\n\n'%s'?\n\n" PRESSYN + +#define NEWGAME \ + "tu ne peux pas commencer un nouveau jeu\n" \ + "durant un jeu en ligne.\n\n" PRESSKEY + +#define NIGHTMARE \ + "es-tu sure? ce niveau\n" \ + "n'est absolument pas juste.\n\n" PRESSYN + +#define SWSTRING \ + "ceci est le version shareware de doom.\n\n" \ + "tu besoin de commander la trilogie entiere.\n\n" PRESSKEY + +#define MSGOFF "Messages DÉSACTIVÉS" +#define MSGON "Messages ACTIVÉS" +#define NETEND "tu ne peux pas quitter un jeu en ligne!\n\n" PRESSKEY +#define ENDGAME "es-tu sure que tu veux quitter le jeu?\n\n" PRESSYN + +#define DOSY "(appuie y pour quitter vers dos.)" + +#define DETAILHI "Haute définition" +#define DETAILLO "Faible définition" +#define GAMMALVL0 "Correction gamma DÉSACTIVÉ" +#define GAMMALVL1 "Correction gamma niveau 1" +#define GAMMALVL2 "Correction gamma niveau 2" +#define GAMMALVL3 "Correction gamma niveau 3" +#define GAMMALVL4 "Correction gamma niveau 4" +#define EMPTYSTRING "slot vide" + +/* P_inter.C */ + +#define GOTARMOR "Ramassé l'armure." +#define GOTMEGA "Ramassé le Mega Armure!" +#define GOTHTHBONUS "Ramassé un bonus de santé." +#define GOTARMBONUS "Ramassé un bonus d'armure." +#define GOTSTIM "Ramassé un stimpack." +#define GOTMEDINEED "Ramassé un medikit que tu as VRAIMENT besoin!" +#define GOTMEDIKIT "Ramassé un medikit." +#define GOTSUPER "Superchargé!" + +#define GOTBLUECARD "Ramassé une carte d'accès bleue." +#define GOTYELWCARD "Ramassé une carte d'accès jaune." +#define GOTREDCARD "Ramassé une carte d'accès rouge." +#define GOTBLUESKUL "Ramassé une clé crâne bleue." +#define GOTYELWSKUL "Ramassé une clé crâne jaune." +#define GOTREDSKULL "Ramassé une clé crâne rouge." + +#define GOTINVUL "Invulnérabilité!" +#define GOTBERSERK "Berserk!" +#define GOTINVIS "Invisibilité Partielle" +#define GOTSUIT "Radiation Shielding Suit" // TODO? +#define GOTMAP "Carte de la Zone Informatique" +#define GOTVISOR "Light Amplification Visor" // TODO? +#define GOTMSPHERE "MegaSphere!" + +#define GOTCLIP "Ramassé un clip." +#define GOTCLIPBOX "Ramassé une boîte de balles." +#define GOTROCKET "Ramassé une fusée." +#define GOTROCKBOX "Ramassé une boîte de fusées." +#define GOTCELL "Ramassé une cellule énergétique." +#define GOTCELLBOX "Ramassé un paquet de cellules énergétiques." +#define GOTSHELLS "Ramassé 4 cartouches de fusil de chasse." +#define GOTSHELLBOX "Ramassé une boîte de cartouches de fusil de chasse." +#define GOTBACKPACK "Ramassé une sac à dos plein d'ammo!" + +#define GOTBFG9000 "Tu as eu le BFG9000! Hohoho, oui!" +#define GOTCHAINGUN "Tu as eu le chaingun!" +#define GOTCHAINSAW "Un scie à chaîne! Trouve de la viande!" +#define GOTLAUNCHER "Tu as eu la lance-roquettes!" +#define GOTPLASMA "Tu as eu le pistolet à plasma!" +#define GOTSHOTGUN "Tu as eu le fusil de chasse!" +#define GOTSHOTGUN2 "Tu as eu le super fusil de chasse!" + +/* P_Doors.C */ + +#define PD_BLUEO "You need a blue key to activate this object" +#define PD_REDO "You need a red key to activate this object" +#define PD_YELLOWO "You need a yellow key to activate this object" +#define PD_BLUEK "You need a blue key to open this door" +#define PD_REDK "You need a red key to open this door" +#define PD_YELLOWK "You need a yellow key to open this door" + +/* G_game.C */ + +#define GGSAVED "game saved." + +/* HU_stuff.C */ + +#define HUSTR_MSGU "[Message unsent]" + +#define HUSTR_E1M1 "E1M1: Hangar" +#define HUSTR_E1M2 "E1M2: Nuclear Plant" +#define HUSTR_E1M3 "E1M3: Toxin Refinery" +#define HUSTR_E1M4 "E1M4: Command Control" +#define HUSTR_E1M5 "E1M5: Phobos Lab" +#define HUSTR_E1M6 "E1M6: Central Processing" +#define HUSTR_E1M7 "E1M7: Computer Station" +#define HUSTR_E1M8 "E1M8: Phobos Anomaly" +#define HUSTR_E1M9 "E1M9: Military Base" + +#define HUSTR_E2M1 "E2M1: Deimos Anomaly" +#define HUSTR_E2M2 "E2M2: Containment Area" +#define HUSTR_E2M3 "E2M3: Refinery" +#define HUSTR_E2M4 "E2M4: Deimos Lab" +#define HUSTR_E2M5 "E2M5: Command Center" +#define HUSTR_E2M6 "E2M6: Halls of the Damned" +#define HUSTR_E2M7 "E2M7: Spawning Vats" +#define HUSTR_E2M8 "E2M8: Tower of Babel" +#define HUSTR_E2M9 "E2M9: Fortress of Mystery" + +#define HUSTR_E3M1 "E3M1: Hell Keep" +#define HUSTR_E3M2 "E3M2: Slough of Despair" +#define HUSTR_E3M3 "E3M3: Pandemonium" +#define HUSTR_E3M4 "E3M4: House of Pain" +#define HUSTR_E3M5 "E3M5: Unholy Cathedral" +#define HUSTR_E3M6 "E3M6: Mt. Erebus" +#define HUSTR_E3M7 "E3M7: Limbo" +#define HUSTR_E3M8 "E3M8: Dis" +#define HUSTR_E3M9 "E3M9: Warrens" + +#define HUSTR_E4M1 "E4M1: Hell Beneath" +#define HUSTR_E4M2 "E4M2: Perfect Hatred" +#define HUSTR_E4M3 "E4M3: Sever The Wicked" +#define HUSTR_E4M4 "E4M4: Unruly Evil" +#define HUSTR_E4M5 "E4M5: They Will Repent" +#define HUSTR_E4M6 "E4M6: Against Thee Wickedly" +#define HUSTR_E4M7 "E4M7: And Hell Followed" +#define HUSTR_E4M8 "E4M8: Unto The Cruel" +#define HUSTR_E4M9 "E4M9: Fear" + +#define HUSTR_1 "niveau 1: entryway" +#define HUSTR_2 "niveau 2: underhalls" +#define HUSTR_3 "niveau 3: the gantlet" +#define HUSTR_4 "niveau 4: the focus" +#define HUSTR_5 "niveau 5: the waste tunnels" +#define HUSTR_6 "niveau 6: the crusher" +#define HUSTR_7 "niveau 7: dead simple" +#define HUSTR_8 "niveau 8: tricks and traps" +#define HUSTR_9 "niveau 9: the pit" +#define HUSTR_10 "niveau 10: refueling base" +#define HUSTR_11 "niveau 11: 'o' of destruction!" + +#define HUSTR_12 "niveau 12: the factory" +#define HUSTR_13 "niveau 13: downtown" +#define HUSTR_14 "niveau 14: the inmost dens" +#define HUSTR_15 "niveau 15: industrial zone" +#define HUSTR_16 "niveau 16: suburbs" +#define HUSTR_17 "niveau 17: tenements" +#define HUSTR_18 "niveau 18: the courtyard" +#define HUSTR_19 "niveau 19: the citadel" +#define HUSTR_20 "niveau 20: gotcha!" + +#define HUSTR_21 "niveau 21: nirvana" +#define HUSTR_22 "niveau 22: the catacombs" +#define HUSTR_23 "niveau 23: barrels o' fun" +#define HUSTR_24 "niveau 24: the chasm" +#define HUSTR_25 "niveau 25: bloodfalls" +#define HUSTR_26 "niveau 26: the abandoned mines" +#define HUSTR_27 "niveau 27: monster condo" +#define HUSTR_28 "niveau 28: the spirit world" +#define HUSTR_29 "niveau 29: the living end" +#define HUSTR_30 "niveau 30: icon of sin" + +#define HUSTR_31 "niveau 31: wolfenstein" +#define HUSTR_32 "niveau 32: grosse" + +#define PHUSTR_1 "niveau 1: congo" +#define PHUSTR_2 "niveau 2: well of souls" +#define PHUSTR_3 "niveau 3: aztec" +#define PHUSTR_4 "niveau 4: caged" +#define PHUSTR_5 "niveau 5: ghost town" +#define PHUSTR_6 "niveau 6: baron's lair" +#define PHUSTR_7 "niveau 7: caughtyard" +#define PHUSTR_8 "niveau 8: realm" +#define PHUSTR_9 "niveau 9: abattoire" +#define PHUSTR_10 "niveau 10: onslaught" +#define PHUSTR_11 "niveau 11: hunted" + +#define PHUSTR_12 "niveau 12: speed" +#define PHUSTR_13 "niveau 13: the crypt" +#define PHUSTR_14 "niveau 14: genesis" +#define PHUSTR_15 "niveau 15: the twilight" +#define PHUSTR_16 "niveau 16: the omen" +#define PHUSTR_17 "niveau 17: compound" +#define PHUSTR_18 "niveau 18: neurosphere" +#define PHUSTR_19 "niveau 19: nme" +#define PHUSTR_20 "niveau 20: the death domain" + +#define PHUSTR_21 "niveau 21: slayer" +#define PHUSTR_22 "niveau 22: impossible mission" +#define PHUSTR_23 "niveau 23: tombstone" +#define PHUSTR_24 "niveau 24: the final frontier" +#define PHUSTR_25 "niveau 25: the temple of darkness" +#define PHUSTR_26 "niveau 26: bunker" +#define PHUSTR_27 "niveau 27: anti-christ" +#define PHUSTR_28 "niveau 28: the sewers" +#define PHUSTR_29 "niveau 29: odyssey of noises" +#define PHUSTR_30 "niveau 30: the gateway of hell" + +#define PHUSTR_31 "niveau 31: cyberden" +#define PHUSTR_32 "niveau 32: go 2 it" + +#define THUSTR_1 "niveau 1: system control" +#define THUSTR_2 "niveau 2: human bbq" +#define THUSTR_3 "niveau 3: power control" +#define THUSTR_4 "niveau 4: wormhole" +#define THUSTR_5 "niveau 5: hanger" +#define THUSTR_6 "niveau 6: open season" +#define THUSTR_7 "niveau 7: prison" +#define THUSTR_8 "niveau 8: metal" +#define THUSTR_9 "niveau 9: stronghold" +#define THUSTR_10 "niveau 10: redemption" +#define THUSTR_11 "niveau 11: storage facility" + +#define THUSTR_12 "niveau 12: crater" +#define THUSTR_13 "niveau 13: nukage processing" +#define THUSTR_14 "niveau 14: steel works" +#define THUSTR_15 "niveau 15: dead zone" +#define THUSTR_16 "niveau 16: deepest reaches" +#define THUSTR_17 "niveau 17: processing area" +#define THUSTR_18 "niveau 18: mill" +#define THUSTR_19 "niveau 19: shipping/respawning" +#define THUSTR_20 "niveau 20: central processing" + +#define THUSTR_21 "niveau 21: administration center" +#define THUSTR_22 "niveau 22: habitat" +#define THUSTR_23 "niveau 23: lunar mining project" +#define THUSTR_24 "niveau 24: quarry" +#define THUSTR_25 "niveau 25: baron's den" +#define THUSTR_26 "niveau 26: ballistyx" +#define THUSTR_27 "niveau 27: mount pain" +#define THUSTR_28 "niveau 28: heck" +#define THUSTR_29 "niveau 29: river styx" +#define THUSTR_30 "niveau 30: last call" + +#define THUSTR_31 "niveau 31: pharaoh" +#define THUSTR_32 "niveau 32: caribbean" + +#define HUSTR_CHATMACRO1 "I'm ready to kick butt!" +#define HUSTR_CHATMACRO2 "I'm OK." +#define HUSTR_CHATMACRO3 "I'm not looking too good!" +#define HUSTR_CHATMACRO4 "Help!" +#define HUSTR_CHATMACRO5 "You suck!" +#define HUSTR_CHATMACRO6 "Next time, scumbag..." +#define HUSTR_CHATMACRO7 "Come here!" +#define HUSTR_CHATMACRO8 "I'll take care of it." +#define HUSTR_CHATMACRO9 "Oui" +#define HUSTR_CHATMACRO0 "Non" + +#define HUSTR_TALKTOSELF1 "You mumble to yourself" +#define HUSTR_TALKTOSELF2 "Who's there?" +#define HUSTR_TALKTOSELF3 "You scare yourself" +#define HUSTR_TALKTOSELF4 "You start to rave" +#define HUSTR_TALKTOSELF5 "You've lost it..." + +#define HUSTR_MESSAGESENT "[Message Sent]" + +/* The following should NOT be changed unless it seems just AWFULLY + * necessary + */ + +#define HUSTR_PLRGREEN "Vert: " +#define HUSTR_PLRINDIGO "Indigo: " +#define HUSTR_PLRBROWN "Brun: " +#define HUSTR_PLRRED "Rouge: " + +#define HUSTR_KEYGREEN 'g' +#define HUSTR_KEYINDIGO 'i' +#define HUSTR_KEYBROWN 'b' +#define HUSTR_KEYRED 'r' + +/* AM_map.C */ + +#define AMSTR_FOLLOWON "Follow Mode ON" +#define AMSTR_FOLLOWOFF "Follow Mode OFF" + +#define AMSTR_GRIDON "Grid ON" +#define AMSTR_GRIDOFF "Grid OFF" + +#define AMSTR_MARKEDSPOT "Marked Spot" +#define AMSTR_MARKSCLEARED "All Marks Cleared" + +/* ST_stuff.C */ + +#define STSTR_MUS "Music Change" +#define STSTR_NOMUS "IMPOSSIBLE SELECTION" +#define STSTR_DQDON "Degreelessness Mode On" +#define STSTR_DQDOFF "Degreelessness Mode Off" + +#define STSTR_KFAADDED "Very Happy Ammo Added" +#define STSTR_FAADDED "Ammo (no keys) Added" + +#define STSTR_NCON "No Clipping Mode ON" +#define STSTR_NCOFF "No Clipping Mode OFF" + +#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" +#define STSTR_BEHOLDX "Power-up Toggled" + +#define STSTR_CHOPPERS "... doesn't suck - GM" +#define STSTR_CLEV "Changing Level..." + +/* F_Finale.C */ + +#define E1TEXT \ + "Once you beat the big badasses and\n" \ + "clean out the moon base you're supposed\n" \ + "to win, aren't you? Aren't you? Where's\n" \ + "your fat reward and ticket home? What\n" \ + "the hell is this? It's not supposed to\n" \ + "end this way!\n" \ + "\n" \ + "It stinks like rotten meat, but looks\n" \ + "like the lost Deimos base. Looks like\n" \ + "you're stuck on The Shores of Hell.\n" \ + "The only way out is through.\n" \ + "\n" \ + "To continue the DOOM experience, play\n" \ + "The Shores of Hell and its amazing\n" \ + "sequel, Inferno!\n" + +#define E2TEXT \ + "You've done it! The hideous cyber-\n" \ + "demon lord that ruled the lost Deimos\n" \ + "moon base has been slain and you\n" \ + "are triumphant! But ... where are\n" \ + "you? You clamber to the edge of the\n" \ + "moon and look down to see the awful\n" \ + "truth.\n" \ + "\n" \ + "Deimos floats above Hell itself!\n" \ + "You've never heard of anyone escaping\n" \ + "from Hell, but you'll make the bastards\n" \ + "sorry they ever heard of you! Quickly,\n" \ + "you rappel down to the surface of\n" \ + "Hell.\n" \ + "\n" \ + "Now, it's on to the final chapter of\n" \ + "DOOM! -- Inferno." + +#define E3TEXT \ + "The loathsome spiderdemon that\n" \ + "masterminded the invasion of the moon\n" \ + "bases and caused so much death has had\n" \ + "its ass kicked for all time.\n" \ + "\n" \ + "A hidden doorway opens and you enter.\n" \ + "You've proven too tough for Hell to\n" \ + "contain, and now Hell at last plays\n" \ + "fair -- for you emerge from the door\n" \ + "to see the green fields of Earth!\n" \ + "Home at last.\n" \ + "\n" \ + "You wonder what's been happening on\n" \ + "Earth while you were battling evil\n" \ + "unleashed. It's good that no Hell-\n" \ + "spawn could have come through that\n" \ + "door with you ..." + +#define E4TEXT \ + "the spider mastermind must have sent forth\n" \ + "its legions of hellspawn before your\n" \ + "final confrontation with that terrible\n" \ + "beast from hell. but you stepped forward\n" \ + "and brought forth eternal damnation and\n" \ + "suffering upon the horde as a true hero\n" \ + "would in the face of something so evil.\n" \ + "\n" \ + "besides, someone was gonna pay for what\n" \ + "happened to daisy, your pet rabbit.\n" \ + "\n" \ + "but now, you see spread before you more\n" \ + "potential pain and gibbitude as a nation\n" \ + "of demons run amok among our cities.\n" \ + "\n" \ + "next stop, hell on earth!" + +/* after niveau 6, put this: */ + +#define C1TEXT \ + "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ + "STARPORT. BUT SOMETHING IS WRONG. THE\n" \ + "MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ + "WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ + "IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ + "\n" \ + "AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ + "FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ + "YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ + "OF THE STARBASE AND FIND THE CONTROLLING\n" \ + "SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ + "HOSTAGE." + +/* After niveau 11, put this: */ + +#define C2TEXT \ + "YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ + "HUMANKIND TO EVACUATE EARTH AND ESCAPE\n" \ + "THE NIGHTMARE. NOW YOU ARE THE ONLY\n" \ + "HUMAN LEFT ON THE FACE OF THE PLANET.\n" \ + "CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n" \ + "AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n" \ + "YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n" \ + "THAT YOU HAVE SAVED YOUR SPECIES.\n" \ + "\n" \ + "BUT THEN, EARTH CONTROL BEAMS DOWN A\n" \ + "MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n" \ + "THE SOURCE OF THE ALIEN INVASION. IF YOU\n" \ + "GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n" \ + "ENTRY. THE ALIEN BASE IS IN THE HEART OF\n" \ + "YOUR OWN HOME CITY, NOT FAR FROM THE\n" \ + "STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n" \ + "UP AND RETURN TO THE FRAY." + +/* After niveau 20, put this: */ + +#define C3TEXT \ + "YOU ARE AT THE CORRUPT HEART OF THE CITY,\n" \ + "SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n" \ + "YOU SEE NO WAY TO DESTROY THE CREATURES'\n" \ + "ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n" \ + "TEETH AND PLUNGE THROUGH IT.\n" \ + "\n" \ + "THERE MUST BE A WAY TO CLOSE IT ON THE\n" \ + "OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n" \ + "GOT TO GO THROUGH HELL TO GET TO IT?" + +/* After niveau 29, put this: */ + +#define C4TEXT \ + "THE HORRENDOUS VISAGE OF THE BIGGEST\n" \ + "DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n" \ + "YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n" \ + "HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n" \ + "UP AND DIES, ITS THRASHING LIMBS\n" \ + "DEVASTATING UNTOLD MILES OF HELL'S\n" \ + "SURFACE.\n" \ + "\n" \ + "YOU'VE DONE IT. THE INVASION IS OVER.\n" \ + "EARTH IS SAVED. HELL IS A WRECK. YOU\n" \ + "WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n" \ + "DIE, NOW. WIPING THE SWEAT FROM YOUR\n" \ + "FOREHEAD YOU BEGIN THE LONG TREK BACK\n" \ + "HOME. REBUILDING EARTH OUGHT TO BE A\n" \ + "LOT MORE FUN THAN RUINING IT WAS.\n" + +/* Before niveau 31, put this: */ + +#define C5TEXT \ + "CONGRATULATIONS, YOU'VE FOUND THE SECRET\n" \ + "LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n" \ + "HUMANS, RATHER THAN DEMONS. YOU WONDER\n" \ + "WHO THE INMATES OF THIS CORNER OF HELL\n" \ + "WILL BE." + +/* Before niveau 32, put this: */ + +#define C6TEXT \ + "CONGRATULATIONS, YOU'VE FOUND THE\n" \ + "SUPER SECRET LEVEL! YOU'D BETTER\n" \ + "BLAZE THROUGH THIS ONE!\n" + +/* after map 06 */ + +#define P1TEXT \ + "You gloat over the steaming carcass of the\n" \ + "Guardian. With its death, you've wrested\n" \ + "the Accelerator from the stinking claws\n" \ + "of Hell. You relax and glance around the\n" \ + "room. Damn! There was supposed to be at\n" \ + "least one working prototype, but you can't\n" \ + "see it. The demons must have taken it.\n" \ + "\n" \ + "You must find the prototype, or all your\n" \ + "struggles will have been wasted. Keep\n" \ + "moving, keep fighting, keep killing.\n" \ + "Oh yes, keep living, too." + +/* after map 11 */ + +#define P2TEXT \ + "Even the deadly Arch-Vile labyrinth could\n" \ + "not stop you, and you've gotten to the\n" \ + "prototype Accelerator which is soon\n" \ + "efficiently and permanently deactivated.\n" \ + "\n" \ + "You're good at that kind of thing." + +/* after map 20 */ + +#define P3TEXT \ + "You've bashed and battered your way into\n" \ + "the heart of the devil-hive. Time for a\n" \ + "Search-and-Destroy mission, aimed at the\n" \ + "Gatekeeper, whose foul offspring is\n" \ + "cascading to Earth. Yeah, he's bad. But\n" \ + "you know who's worse!\n" \ + "\n" \ + "Grinning evilly, you check your gear, and\n" \ + "get ready to give the bastard a little Hell\n" \ + "of your own making!" + +/* after map 30 */ + +#define P4TEXT \ + "The Gatekeeper's evil face is splattered\n" \ + "all over the place. As its tattered corpse\n" \ + "collapses, an inverted Gate forms and\n" \ + "sucks down the shards of the last\n" \ + "prototype Accelerator, not to mention the\n" \ + "few remaining demons. You're done. Hell\n" \ + "has gone back to pounding bad dead folks \n" \ + "instead of good live ones. Remember to\n" \ + "tell your grandkids to put a rocket\n" \ + "launcher in your coffin. If you go to Hell\n" \ + "when you die, you'll need it for some\n" \ + "final cleaning-up ..." + +/* before map 31 */ + +#define P5TEXT \ + "You've found the second-hardest niveau we\n" \ + "got. Hope you have a saved game a niveau or\n" \ + "two previous. If not, be prepared to die\n" \ + "aplenty. For master marines only." + +/* before map 32 */ + +#define P6TEXT \ + "Betcha wondered just what WAS the hardest\n" \ + "niveau we had ready for ya? Now you know.\n" \ + "No one gets out alive." + +#define T1TEXT \ + "You've fought your way out of the infested\n" \ + "experimental labs. It seems that UAC has\n" \ + "once again gulped it down. With their\n" \ + "high turnover, it must be hard for poor\n" \ + "old UAC to buy corporate health insurance\n" \ + "nowadays..\n" \ + "\n" \ + "Ahead lies the military complex, now\n" \ + "swarming with diseased horrors hot to get\n" \ + "their teeth into you. With luck, the\n" \ + "complex still has some warlike ordnance\n" \ + "laying around." + +#define T2TEXT \ + "You hear the grinding of heavy machinery\n" \ + "ahead. You sure hope they're not stamping\n" \ + "out new hellspawn, but you're ready to\n" \ + "ream out a whole herd if you have to.\n" \ + "They might be planning a blood feast, but\n" \ + "you feel about as mean as two thousand\n" \ + "maniacs packed into one mad killer.\n" \ + "\n" \ + "You don't plan to go down easy." + +#define T3TEXT \ + "The vista opening ahead looks real damn\n" \ + "familiar. Smells familiar, too -- like\n" \ + "fried excrement. You didn't like this\n" \ + "place before, and you sure as hell ain't\n" \ + "planning to like it now. The more you\n" \ + "brood on it, the madder you get.\n" \ + "Hefting your gun, an evil grin trickles\n" \ + "onto your face. Time to take some names." + +#define T4TEXT \ + "Suddenly, all is silent, from one horizon\n" \ + "to the other. The agonizing echo of Hell\n" \ + "fades away, the nightmare sky turns to\n" \ + "blue, the heaps of monster corpses start \n" \ + "to evaporate along with the evil stench \n" \ + "that filled the air. Jeeze, maybe you've\n" \ + "done it. Have you really won?\n" \ + "\n" \ + "Something rumbles in the distance.\n" \ + "A blue light begins to glow inside the\n" \ + "ruined skull of the demon-spitter." + +#define T5TEXT \ + "What now? Looks totally different. Kind\n" \ + "of like King Tut's condo. Well,\n" \ + "whatever's here can't be any worse\n" \ + "than usual. Can it? Or maybe it's best\n" \ + "to let sleeping gods lie.." + +#define T6TEXT \ + "Time for a vacation. You've burst the\n" \ + "bowels of hell and by golly you're ready\n" \ + "for a break. You mutter to yourself,\n" \ + "Maybe someone else can kick Hell's ass\n" \ + "next time around. Ahead lies a quiet town,\n" \ + "with peaceful flowing water, quaint\n" \ + "buildings, and presumably no Hellspawn.\n" \ + "\n" \ + "As you step off the transport, you hear\n" \ + "the stomp of a cyberdemon's iron shoe." + +/* Character cast strings F_FINALE.C */ + +#define CC_ZOMBIE "ZOMBIEMAN" +#define CC_SHOTGUN "SHOTGUN GUY" +#define CC_HEAVY "HEAVY WEAPON DUDE" +#define CC_IMP "IMP" +#define CC_DEMON "DEMON" +#define CC_LOST "LOST SOUL" +#define CC_CACO "CACODEMON" +#define CC_HELL "HELL KNIGHT" +#define CC_BARON "BARON OF HELL" +#define CC_ARACH "ARACHNOTRON" +#define CC_PAIN "PAIN ELEMENTAL" +#define CC_REVEN "REVENANT" +#define CC_MANCU "MANCUBUS" +#define CC_ARCH "ARCH-VILE" +#define CC_SPIDER "THE SPIDER MASTERMIND" +#define CC_CYBER "THE CYBERDEMON" +#define CC_HERO "OUR HERO" + +/* DOOM end messages */ + +#define DOOM1_ENDMSG \ + "are you sure you want to\nquit this great game?", \ + "please don't leave, there's more\ndemons to toast!", \ + "let's beat it -- this is turning\ninto a bloodbath!", \ + "i wouldn't leave if i were you.\ndos is much worse.", \ + "you're trying to say you like dos\nbetter than me, right?", \ + "don't leave yet -- there's a\ndemon around that corner!", \ + "ya know, next time you come in here\ni'm gonna toast ya.", \ + "go ahead and leave. see if i care.", + +/* QuitDOOM II messages */ + +#define DOOM2_ENDMSG \ + "are you sure you want to\nquit this great game?", \ + "you want to quit?\nthen, thou hast lost an eighth!", \ + "don't go now, there's a \ndimensional shambler waiting\nat the dos " \ + "prompt!", \ + "get outta here and go back\nto your boring programs.", \ + "if i were your boss, i'd \n deathmatch ya in a minute!", \ + "look, bud. you leave now\nand you forfeit your body count!", \ + "just leave. when you come\nback, i'll be waiting with a bat.", \ + "you're lucky i don't smack\nyou for thinking about leaving.", + +#endif /* __D_FRENCH__ */ diff --git a/games/NXDoom/src/doom/d_items.c b/games/NXDoom/src/doom/d_items.c index 33f310c63b3..8fc606b6c47 100644 --- a/games/NXDoom/src/doom/d_items.c +++ b/games/NXDoom/src/doom/d_items.c @@ -1,128 +1,143 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// - - -// We are referring to sprite numbers. +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_items.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* We are referring to sprite numbers. */ + #include "info.h" #include "d_items.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ -// -// PSPRITE ACTIONS for waepons. -// This struct controls the weapon animations. -// -// Each entry is: -// ammo/amunition type -// upstate -// downstate -// readystate -// atkstate, i.e. attack/fire/hit frame -// flashstate, muzzle flash -// -weaponinfo_t weaponinfo[NUMWEAPONS] = +/* PSPRITE ACTIONS for weapons. + * This struct controls the weapon animations. + * + * Each entry is: + * ammo/ammunition type + * upstate + * downstate + * readystate + * atkstate, i.e. attack/fire/hit frame + * flashstate, muzzle flash + */ + +weaponinfo_t weaponinfo[NUMWEAPONS] = { { - // fist - am_noammo, - S_PUNCHUP, - S_PUNCHDOWN, - S_PUNCH, - S_PUNCH1, - S_NULL - }, - { - // pistol - am_clip, - S_PISTOLUP, - S_PISTOLDOWN, - S_PISTOL, - S_PISTOL1, - S_PISTOLFLASH - }, - { - // shotgun - am_shell, - S_SGUNUP, - S_SGUNDOWN, - S_SGUN, - S_SGUN1, - S_SGUNFLASH1 + /* fist */ + + am_noammo, + S_PUNCHUP, + S_PUNCHDOWN, + S_PUNCH, + S_PUNCH1, + S_NULL, }, { - // chaingun - am_clip, - S_CHAINUP, - S_CHAINDOWN, - S_CHAIN, - S_CHAIN1, - S_CHAINFLASH1 + /* pistol */ + + am_clip, + S_PISTOLUP, + S_PISTOLDOWN, + S_PISTOL, + S_PISTOL1, + S_PISTOLFLASH, }, { - // missile launcher - am_misl, - S_MISSILEUP, - S_MISSILEDOWN, - S_MISSILE, - S_MISSILE1, - S_MISSILEFLASH1 + /* shotgun */ + + am_shell, + S_SGUNUP, + S_SGUNDOWN, + S_SGUN, + S_SGUN1, + S_SGUNFLASH1, }, { - // plasma rifle - am_cell, - S_PLASMAUP, - S_PLASMADOWN, - S_PLASMA, - S_PLASMA1, - S_PLASMAFLASH1 + /* chaingun */ + + am_clip, + S_CHAINUP, + S_CHAINDOWN, + S_CHAIN, + S_CHAIN1, + S_CHAINFLASH1, }, { - // bfg 9000 - am_cell, - S_BFGUP, - S_BFGDOWN, - S_BFG, - S_BFG1, - S_BFGFLASH1 + /* missile launcher */ + + am_misl, + S_MISSILEUP, + S_MISSILEDOWN, + S_MISSILE, + S_MISSILE1, + S_MISSILEFLASH1, }, { - // chainsaw - am_noammo, - S_SAWUP, - S_SAWDOWN, - S_SAW, - S_SAW1, - S_NULL + /* plasma rifle */ + + am_cell, + S_PLASMAUP, + S_PLASMADOWN, + S_PLASMA, + S_PLASMA1, + S_PLASMAFLASH1, }, { - // super shotgun - am_shell, - S_DSGUNUP, - S_DSGUNDOWN, - S_DSGUN, - S_DSGUN1, - S_DSGUNFLASH1 - }, -}; - - - - + /* bfg 9000 */ + am_cell, + S_BFGUP, + S_BFGDOWN, + S_BFG, + S_BFG1, + S_BFGFLASH1, + }, + { + /* chainsaw */ + am_noammo, + S_SAWUP, + S_SAWDOWN, + S_SAW, + S_SAW1, + S_NULL, + }, + { + /* super shotgun */ + am_shell, + S_DSGUNUP, + S_DSGUNDOWN, + S_DSGUN, + S_DSGUN1, + S_DSGUNFLASH1, + }, +}; +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/doom/d_items.h b/games/NXDoom/src/doom/d_items.h index 3d22a063030..bcc50b9af68 100644 --- a/games/NXDoom/src/doom/d_items.h +++ b/games/NXDoom/src/doom/d_items.h @@ -1,41 +1,55 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Items: key cards, artifacts, weapon, ammunition. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_items.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Items: key cards, artifacts, weapon, ammunition. + * + ****************************************************************************/ #ifndef __D_ITEMS__ #define __D_ITEMS__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomdef.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Weapon info: sprite frames, ammunition use. */ -// Weapon info: sprite frames, ammunition use. typedef struct { - ammotype_t ammo; - int upstate; - int downstate; - int readystate; - int atkstate; - int flashstate; - + ammotype_t ammo; + int upstate; + int downstate; + int readystate; + int atkstate; + int flashstate; } weaponinfo_t; -extern weaponinfo_t weaponinfo[NUMWEAPONS]; +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern weaponinfo_t weaponinfo[NUMWEAPONS]; -#endif +#endif /* __D_ITEMS__ */ diff --git a/games/NXDoom/src/doom/d_main.c b/games/NXDoom/src/doom/d_main.c index 014e4872134..52df6eda110 100644 --- a/games/NXDoom/src/doom/d_main.c +++ b/games/NXDoom/src/doom/d_main.c @@ -1,24 +1,32 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM main program (D_DoomMain) and game loop (D_DoomLoop), -// plus functions to determine game mode (shareware, registered), -// parse command line parameters, configure game parameters (turbo), -// and call the startup functions. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_main.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * DOOM main program (d_doom_main) and game loop (d_doomloop), + * plus functions to determine game mode (shareware, registered), + * parse command line parameters, configure game parameters (turbo), + * and call the startup functions. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -31,16 +39,19 @@ #include "doomstat.h" #include "dstrings.h" + +#ifdef CONFIG_GAMES_NXDOOM_SOUND +#include "s_sound.h" #include "sounds.h" +#endif #include "d_iwad.h" -#include "z_zone.h" -#include "w_main.h" -#include "w_wad.h" -#include "s_sound.h" #include "v_diskicon.h" #include "v_video.h" +#include "w_main.h" +#include "w_wad.h" +#include "z_zone.h" #include "f_finale.h" #include "f_wipe.h" @@ -48,8 +59,8 @@ #include "m_argv.h" #include "m_config.h" #include "m_controls.h" -#include "m_misc.h" #include "m_menu.h" +#include "m_misc.h" #include "p_saveg.h" #include "i_endoom.h" @@ -61,13 +72,16 @@ #include "g_game.h" +#include "am_map.h" #include "hu_stuff.h" -#include "wi_stuff.h" #include "st_stuff.h" -#include "am_map.h" +#include "wi_stuff.h" + +#ifdef CONFIG_GAMES_NXDOOM_NET #include "net_client.h" #include "net_dedicated.h" #include "net_query.h" +#endif #include "p_setup.h" #include "r_local.h" @@ -75,1928 +89,2096 @@ #include "d_main.h" -#include "doom_icon.c" +/**************************************************************************** + * Private Types + ****************************************************************************/ -// -// D-DoomLoop() -// Not a globally visible function, -// just included for source reference, -// called by D_DoomMain, never exits. -// Manages timing and IO, -// calls all ?_Responder, ?_Ticker, and ?_Drawer, -// calls I_GetTime, I_StartFrame, and I_StartTic -// -void D_DoomLoop (void); +struct pack +{ + const char *name; + int mission; +}; + +struct gameversion +{ + const char *description; + const char *cmdline; + game_version_t version; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* D-DoomLoop() + * + * Not a globally visible function, just included for source reference, + * called by d_doom_main, never exits. + * + * Manages timing and IO, calls all ?_Responder, ?_Ticker, and ?_Drawer, + * calls i_get_time, i_start_frame, and i_start_tic + */ + +void d_doomloop(void); + +void d_connect_net_game(void); +void d_check_net_game(void); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Location where savegames are stored */ -static char *gamedescription; +char *savegamedir; -// Location where savegames are stored +/* location of IWAD and WAD files */ -char * savegamedir; +char *iwadfile; -// location of IWAD and WAD files +boolean devparm; /* started game with -devparm */ +boolean nomonsters; /* checkparm of -nomonsters */ +boolean respawnparm; /* checkparm of -respawn */ +boolean fastparm; /* checkparm of -fast */ -char * iwadfile; +skill_t startskill; +int startepisode; +int startmap; +boolean autostart; +int startloadgame; +boolean advancedemo; -boolean devparm; // started game with -devparm -boolean nomonsters; // checkparm of -nomonsters -boolean respawnparm; // checkparm of -respawn -boolean fastparm; // checkparm of -fast +/* Store demo, do not accept any inputs */ +boolean storedemo; +/* If true, the main game loop has started. */ -skill_t startskill; -int startepisode; -int startmap; -boolean autostart; -int startloadgame; +boolean main_loop_started = false; -boolean advancedemo; +int show_endoom = 1; +int show_diskicon = 1; -// Store demo, do not accept any inputs -boolean storedemo; +/* wipegamestate can be set to -1 to force a wipe on the next draw */ -// If true, the main game loop has started. -boolean main_loop_started = false; +gamestate_t wipegamestate = GS_DEMOSCREEN; -int show_endoom = 1; -int show_diskicon = 1; +/* DEMO LOOP */ +int demosequence; +int pagetic; +const char *pagename; -void D_ConnectNetGame(void); -void D_CheckNetGame(void); +/* print title for every printed line */ +char title[128]; -// -// D_ProcessEvents -// Send all the events of the given timestamp down the responder chain -// -void D_ProcessEvents (void) +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Copyright message banners + * Some dehacked mods replace these. These are only displayed if they are + * replaced by dehacked. + */ + +static const char *g_copyright_banners[] = { - event_t* ev; - - // IF STORE DEMO, DO NOT ACCEPT INPUT - if (storedemo) - return; - - while ((ev = D_PopEvent()) != NULL) - { - if (M_Responder (ev)) - continue; // menu ate the event - G_Responder (ev); - } -} + "========================================================================" + "===\n" + "ATTENTION: This version of DOOM has been modified. If you would like " + "to\n" + "get a copy of the original game, call 1-800-IDGAMES or see the readme " + "file.\n" + " You will not receive technical support for modified games.\n" + " press enter to continue\n" + "========================================================================" + "===\n", + + "========================================================================" + "===\n" + " Commercial product - do not distribute!\n" + " Please report software piracy to the SPA: 1-800-388-PIR8\n" + "========================================================================" + "===\n", + + "========================================================================" + "===\n" + " Shareware!\n" + "========================================================================" + "===\n", +}; +/* These are the lumps that will be checked in IWAD, + * if any one is not present, execution will be aborted. + */ +static char g_name[23][8] = +{ + "e2m1", "e2m2", "e2m3", "e2m4", "e2m5", "e2m6", + "e2m7", "e2m8", "e2m9", "e3m1", "e3m3", "e3m3", + "e3m4", "e3m5", "e3m6", "e3m7", "e3m8", "e3m9", + "dphoof", "bfgga0", "heada1", "cybra1", "spida1d1", +}; +static char *g_gamedescription; -// -// D_Display -// draw current display, possibly wiping it from the previous -// +/* Add configuration file variable bindings. */ + +static const char *const g_chat_macro_defaults[10] = +{ + HUSTR_CHATMACRO0, HUSTR_CHATMACRO1, HUSTR_CHATMACRO2, HUSTR_CHATMACRO3, + HUSTR_CHATMACRO4, HUSTR_CHATMACRO5, HUSTR_CHATMACRO6, HUSTR_CHATMACRO7, + HUSTR_CHATMACRO8, HUSTR_CHATMACRO9, +}; -// wipegamestate can be set to -1 to force a wipe on the next draw -gamestate_t wipegamestate = GS_DEMOSCREEN; +/* Strings for dehacked replacements of the startup banner + * + * These are from the original source: some of them are perhaps + * not used in any dehacked patches + */ -boolean D_Display (void) +static const char *g_banners[] = { - static boolean viewactivestate = false; - static boolean menuactivestate = false; - static boolean inhelpscreensstate = false; - static boolean fullscreen = false; - static gamestate_t oldgamestate = -1; - static int borderdrawcount; - int y; - boolean wipe; - boolean redrawsbar; - - redrawsbar = false; - - // change the view size if needed - if (setsizeneeded) - { - R_ExecuteSetViewSize (); - oldgamestate = -1; // force background redraw - borderdrawcount = 3; - } - - // save the current screen if about to wipe - if (gamestate != wipegamestate) - { - wipe = true; - wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); - } - else - wipe = false; - - if (gamestate == GS_LEVEL && gametic) - HU_Erase(); - - // do buffered drawing - switch (gamestate) - { - case GS_LEVEL: - if (!gametic) - break; - if (automapactive) - AM_Drawer (); - if (wipe || (viewheight != SCREENHEIGHT && fullscreen)) - redrawsbar = true; - if (inhelpscreensstate && !inhelpscreens) - redrawsbar = true; // just put away the help screen - ST_Drawer (viewheight == SCREENHEIGHT, redrawsbar ); - fullscreen = viewheight == SCREENHEIGHT; - break; - - case GS_INTERMISSION: - WI_Drawer (); - break; - - case GS_FINALE: - F_Drawer (); - break; - - case GS_DEMOSCREEN: - D_PageDrawer (); - break; - } - - // draw buffered stuff to screen - I_UpdateNoBlit (); - - // draw the view directly - if (gamestate == GS_LEVEL && !automapactive && gametic) - R_RenderPlayerView (&players[displayplayer]); - - if (gamestate == GS_LEVEL && gametic) - HU_Drawer (); - - // clean up border stuff - if (gamestate != oldgamestate && gamestate != GS_LEVEL) - I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); - - // see if the border needs to be initially drawn - if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) - { - viewactivestate = false; // view was not active - R_FillBackScreen (); // draw the pattern into the back screen - } - - // see if the border needs to be updated to the screen - if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != SCREENWIDTH) - { - if (menuactive || menuactivestate || !viewactivestate) - borderdrawcount = 3; - if (borderdrawcount) - { - R_DrawViewBorder (); // erase old menu stuff - borderdrawcount--; - } - - } - - if (testcontrols) - { - // Box showing current mouse speed - - V_DrawMouseSpeedBox(testcontrols_mousespeed); - } - - menuactivestate = menuactive; - viewactivestate = viewactive; - inhelpscreensstate = inhelpscreens; - oldgamestate = wipegamestate = gamestate; - - // draw pause pic - if (paused) - { - if (automapactive) - y = 4; - else - y = viewwindowy+4; - V_DrawPatchDirect(viewwindowx + (scaledviewwidth - 68) / 2, y, - W_CacheLumpName (DEH_String("M_PAUSE"), PU_CACHE)); - } + /* doom2.wad */ + " " + "DOOM 2: Hell on Earth v%i.%i" + " ", - // menus go directly to the screen - M_Drawer (); // menu is drawn even on top of everything - NetUpdate (); // send out any new accumulation + /* doom2.wad v1.666 */ - return wipe; -} + " " + "DOOM 2: Hell on Earth v%i.%i66" + " ", + + /* doom1.wad */ + + " " + "DOOM Shareware Startup v%i.%i" + " ", + + /* doom.wad */ + + " " + "DOOM Registered Startup v%i.%i" + " ", + + /* Registered DOOM uses this */ + + " " + "DOOM System Startup v%i.%i" + " ", -static void EnableLoadingDisk(void) + /* Doom v1.666 */ + + " " + "DOOM System Startup v%i.%i66" + " " + + /* doom.wad (Ultimate DOOM) */ + + " " + "The Ultimate DOOM Startup v%i.%i" + " ", + + /* tnt.wad */ + + " " + "DOOM 2: TNT - Evilution v%i.%i" + " ", + + /* plutonia.wad */ + + " " + "DOOM 2: Plutonia Experiment v%i.%i" + " ", +}; + +static const struct gameversion g_gameversions[] = { - const char *disk_lump_name; + {"Doom 1.2", "1.2", exe_doom_1_2}, + {"Doom 1.5", "1.5", exe_doom_1_5}, + {"Doom 1.666", "1.666", exe_doom_1_666}, + {"Doom 1.7/1.7a", "1.7", exe_doom_1_7}, + {"Doom 1.8", "1.8", exe_doom_1_8}, + {"Doom 1.9", "1.9", exe_doom_1_9}, + {"Hacx", "hacx", exe_hacx}, + {"Ultimate Doom", "ultimate", exe_ultimate}, + {"Final Doom", "final", exe_final}, + {"Final Doom (alt)", "final2", exe_final2}, + {"Chex Quest", "chex", exe_chex}, + {NULL, NULL, 0}, +}; - if (show_diskicon) +static const struct pack g_packs[] = +{ + {"doom2", doom2}, + {"tnt", pack_tnt}, + {"plutonia", pack_plut}, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void enable_loading_disk(void) +{ + const char *disk_lump_name; + + if (show_diskicon) { - if (M_CheckParm("-cdrom") > 0) + if (m_check_parm("-cdrom") > 0) { - disk_lump_name = DEH_String("STCDROM"); + disk_lump_name = ("STCDROM"); } - else + else { - disk_lump_name = DEH_String("STDISK"); + disk_lump_name = ("STDISK"); } - V_EnableLoadingDisk(disk_lump_name, - SCREENWIDTH - LOADING_DISK_W, + v_enable_loading_disk(disk_lump_name, SCREENWIDTH - LOADING_DISK_W, SCREENHEIGHT - LOADING_DISK_H); } } -// -// Add configuration file variable bindings. -// - - -static const char * const chat_macro_defaults[10] = +static void d_bind_variables(void) { - HUSTR_CHATMACRO0, - HUSTR_CHATMACRO1, - HUSTR_CHATMACRO2, - HUSTR_CHATMACRO3, - HUSTR_CHATMACRO4, - HUSTR_CHATMACRO5, - HUSTR_CHATMACRO6, - HUSTR_CHATMACRO7, - HUSTR_CHATMACRO8, - HUSTR_CHATMACRO9 -}; + int i; + m_apply_platform_defaults(); -void D_BindVariables(void) -{ - int i; - - M_ApplyPlatformDefaults(); - - I_BindInputVariables(); - I_BindVideoVariables(); - I_BindJoystickVariables(); - I_BindSoundVariables(); + i_bind_input_variables(); + i_bind_video_variables(); + i_bind_joystick_variables(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + i_bind_sound_variables(); +#endif - M_BindBaseControls(); - M_BindWeaponControls(); - M_BindMapControls(); - M_BindMenuControls(); - M_BindChatControls(MAXPLAYERS); + m_bind_base_controls(); + m_bind_weapon_controls(); + m_bind_map_controls(); + m_bind_menu_controls(); + m_bind_chat_controls(MAXPLAYERS); - key_multi_msgplayer[0] = HUSTR_KEYGREEN; - key_multi_msgplayer[1] = HUSTR_KEYINDIGO; - key_multi_msgplayer[2] = HUSTR_KEYBROWN; - key_multi_msgplayer[3] = HUSTR_KEYRED; + key_multi_msgplayer[0] = HUSTR_KEYGREEN; + key_multi_msgplayer[1] = HUSTR_KEYINDIGO; + key_multi_msgplayer[2] = HUSTR_KEYBROWN; + key_multi_msgplayer[3] = HUSTR_KEYRED; - NET_BindVariables(); +#ifdef CONFIG_GAMES_NXDOOM_NET + net_bind_variables(); +#endif - M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); - M_BindIntVariable("sfx_volume", &sfxVolume); - M_BindIntVariable("music_volume", &musicVolume); - M_BindIntVariable("show_messages", &showMessages); - M_BindIntVariable("screenblocks", &screenblocks); - M_BindIntVariable("detaillevel", &detailLevel); - M_BindIntVariable("snd_channels", &snd_channels); - M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); - M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); - M_BindIntVariable("show_endoom", &show_endoom); - M_BindIntVariable("show_diskicon", &show_diskicon); + m_bind_int_variable("mouse_sensitivity", &g_mouse_sensitivity); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + m_bind_int_variable("sfx_volume", &g_sfx_volume); + m_bind_int_variable("music_volume", &g_music_volume); + m_bind_int_variable("snd_channels", &snd_channels); +#endif + m_bind_int_variable("show_messages", &g_show_messages); + m_bind_int_variable("screenblocks", &screenblocks); + m_bind_int_variable("detaillevel", &g_detail_level); + m_bind_int_variable("vanilla_savegame_limit", &vanilla_savegame_limit); + m_bind_int_variable("vanilla_demo_limit", &vanilla_demo_limit); + m_bind_int_variable("show_endoom", &show_endoom); + m_bind_int_variable("show_diskicon", &show_diskicon); - // Multiplayer chat macros + /* Multiplayer chat macros */ - for (i=0; i<10; ++i) + for (i = 0; i < 10; ++i) { - char buf[12]; + char buf[12]; - chat_macros[i] = M_StringDuplicate(chat_macro_defaults[i]); - M_snprintf(buf, sizeof(buf), "chatmacro%i", i); - M_BindStringVariable(buf, &chat_macros[i]); + chat_macros[i] = m_string_duplicate(g_chat_macro_defaults[i]); + snprintf(buf, sizeof(buf), "chatmacro%i", i); + m_bind_string_variable(buf, &chat_macros[i]); } } -// -// D_GrabMouseCallback -// -// Called to determine whether to grab the mouse pointer -// +/* Function called at exit to display the ENDOOM screen */ -boolean D_GrabMouseCallback(void) +static void d_endoom(void) { - // Drone players don't need mouse focus +#ifdef CONFIG_GAMES_NXDOOM_ENDOOM + byte *endoom; - if (drone) - return false; + /* Don't show ENDOOM if we have it disabled, or we're running + * in screensaver or control test mode. Only show it once the + * game has actually started. + */ - // when menu is active or game is paused, release the mouse - - if (menuactive || paused) - return false; + if (!show_endoom || !main_loop_started || screensaver_mode || + m_check_parm("-testcontrols") > 0) + { + return; + } - // only grab mouse when playing levels (but not demos) + endoom = w_cache_lump_name(("ENDOOM"), PU_STATIC); - return (gamestate == GS_LEVEL) && !demoplayback && !advancedemo; + i_endoom(endoom); +#else + return; +#endif } -// -// D_RunFrame -// -void D_RunFrame() +static boolean is_french_iwad(void) { - int nowtime; - int tics; - static int wipestart; - static boolean wipe; + return (gamemission == doom2 && w_check_num_for_name("M_RDTHIS") < 0 && + w_check_num_for_name("M_EPISOD") < 0 && + w_check_num_for_name("M_EPI1") < 0 && + w_check_num_for_name("M_EPI2") < 0 && + w_check_num_for_name("M_EPI3") < 0 && + w_check_num_for_name("WIOSTF") < 0 && + w_check_num_for_name("WIOBJ") >= 0); +} - if (wipe) +/* Load dehacked patches needed for certain IWADs. */ + +static void load_iwad_deh(void) +{ + /* The Freedoom IWADs have DEHACKED lumps that must be loaded. */ + + if (gamevariant == freedoom || gamevariant == freedm) { - do - { - nowtime = I_GetTime (); - tics = nowtime - wipestart; - I_Sleep(1); - } while (tics <= 0); + /* Old versions of Freedoom (before 2014-09) did not have technically + * valid DEHACKED lumps, so ignore errors and just continue if this + * is an old IWAD. + */ - wipestart = nowtime; - wipe = !wipe_ScreenWipe(wipe_Melt - , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); - I_UpdateNoBlit (); - M_Drawer (); // menu is drawn even on top of wipes - I_FinishUpdate (); // page flip or blit buffer - return; + deh_load_lump_by_name("DEHACKED", false, true); } - // frame syncronous IO operations - I_StartFrame (); + /* If this is the HACX IWAD, we need to load the DEHACKED lump. */ - TryRunTics (); // will run at least one tic + if (gameversion == exe_hacx) + { + if (!deh_load_lump_by_name("DEHACKED", true, false)) + { + i_error("DEHACKED lump not found. Please check that this is the " + "Hacx v1.2 IWAD."); + } + } - S_UpdateSounds (players[consoleplayer].mo);// move positional sounds + /* Chex Quest needs a separate Dehacked patch which must be downloaded + * and installed next to the IWAD. + */ - // Update display, next frame, with current state if no profiling is on - if (screenvisible && !nodrawers) + if (gameversion == exe_chex) { - if ((wipe = D_Display ())) + char *chex_deh = NULL; + char *dirname; + + /* Look for chex.deh in the same directory as the IWAD file. */ + + dirname = m_dir_name(iwadfile); + chex_deh = m_string_join(dirname, DIR_SEPARATOR_S, "chex.deh", NULL); + free(dirname); + + /* If the dehacked patch isn't found, try searching the WAD + * search path instead. We might find it... + */ + + if (!m_file_exists(chex_deh)) + { + free(chex_deh); + chex_deh = d_find_wad_by_name("chex.deh"); + } + + /* Still not found? */ + + if (chex_deh == NULL) { - // start wipe on this frame - wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); + i_error("Unable to find Chex Quest dehacked file (chex.deh).\n" + "The dehacked file is required in order to emulate\n" + "chex.exe correctly. It can be found in your nearest\n" + "/idgames repository mirror at:\n\n" + " themes/chex/chexdeh.zip"); + } - wipestart = I_GetTime () - 1; - } else { - // normal update - I_FinishUpdate (); // page flip or blit buffer + if (!deh_loadfile(chex_deh)) + { + i_error("Failed to load chex.deh needed for emulating chex.exe."); + } + } + + if (is_french_iwad()) + { + char *french_deh = NULL; + char *dirname; + + /* Look for french.deh in the same directory as the IWAD file. */ + + dirname = m_dir_name(iwadfile); + french_deh = + m_string_join(dirname, DIR_SEPARATOR_S, "french.deh", NULL); + printf("French version\n"); + free(dirname); + + /* If the dehacked patch isn't found, try searching the WAD + * search path instead. We might find it... + */ + + if (!m_file_exists(french_deh)) + { + free(french_deh); + french_deh = d_find_wad_by_name("french.deh"); + } + + /* Still not found? */ + + if (french_deh == NULL) + { + i_error( + "Unable to find French Doom II dehacked file\n" + "(french.deh). The dehacked file is required in order to\n" + "emulate French doom2.exe correctly. It can be found in\n" + "your nearest /idgames repository mirror at:\n\n" + " utils/exe_edit/patches/french.zip" + ); + } + + if (!deh_loadfile(french_deh)) + { + i_error("Failed to load french.deh needed for emulating French\n" + "doom2.exe."); } } } -// -// D_DoomLoop -// -void D_DoomLoop (void) +static void g_check_demo_status_at_exit(void) { - if (gamevariant == bfgedition && - (demorecording || (gameaction == ga_playdemo) || netgame)) + g_check_demo_status(); +} + +/* draw current display, possibly wiping it from the previous */ + +static boolean d_display(void) +{ + static boolean viewactivestate = false; + static boolean g_menuactivestate = false; + static boolean inhelpscreensstate = false; + static boolean d_fullscreen = false; + static gamestate_t oldgamestate = -1; + static int borderdrawcount; + int y; + boolean wipe; + boolean redrawsbar; + + redrawsbar = false; + + /* change the view size if needed */ + + if (setsizeneeded) + { + r_execute_set_view_size(); + oldgamestate = -1; /* force background redraw */ + borderdrawcount = 3; + } + + /* save the current screen if about to wipe */ + + if (gamestate != wipegamestate) + { + wipe = true; + wipe_start_screen(0, 0, SCREENWIDTH, SCREENHEIGHT); + } + else { - printf(" WARNING: You are playing using one of the Doom Classic\n" - " IWAD files shipped with the Doom 3: BFG Edition. These are\n" - " known to be incompatible with the regular IWAD files and\n" - " may cause demos and network games to get out of sync.\n"); + wipe = false; } - if (demorecording) - G_BeginRecording (); + if (gamestate == GS_LEVEL && gametic) + { + hu_erase(); + } + + /* do buffered drawing */ + + switch (gamestate) + { + case GS_LEVEL: + + if (!gametic) + { + break; + } + + if (automapactive) + { + am_drawer(); + } + + if (wipe || (viewheight != SCREENHEIGHT && d_fullscreen)) + { + redrawsbar = true; + } + + if (inhelpscreensstate && !inhelpscreens) + { + redrawsbar = true; /* just put away the help screen */ + } + + st_drawer(viewheight == SCREENHEIGHT, redrawsbar); + d_fullscreen = viewheight == SCREENHEIGHT; + break; - main_loop_started = true; + case GS_INTERMISSION: + wi_drawer(); + break; - I_SetWindowTitle(gamedescription); - I_GraphicsCheckCommandLine(); - I_SetGrabMouseCallback(D_GrabMouseCallback); - I_RegisterWindowIcon(doom_icon_data, doom_icon_w, doom_icon_h); - I_InitGraphics(); - EnableLoadingDisk(); + case GS_FINALE: + f_drawer(); + break; - TryRunTics(); + case GS_DEMOSCREEN: + d_page_drawer(); + break; + } - V_RestoreBuffer(); - R_ExecuteSetViewSize(); + /* draw buffered stuff to screen */ - D_StartGameLoop(); + i_update_no_blit(); - if (testcontrols) + /* draw the view directly */ + + if (gamestate == GS_LEVEL && !automapactive && gametic) { - wipegamestate = gamestate; + r_render_player_view(&players[displayplayer]); } - while (1) + if (gamestate == GS_LEVEL && gametic) { - D_RunFrame(); + hu_drawer(); } -} + /* clean up border stuff */ + if (gamestate != oldgamestate && gamestate != GS_LEVEL) + i_set_palette(w_cache_lump_name(("PLAYPAL"), PU_CACHE)); -// -// DEMO LOOP -// -int demosequence; -int pagetic; -const char *pagename; + /* see if the border needs to be initially drawn */ + if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) + { + viewactivestate = false; /* view was not active */ + r_fill_back_screen(); /* draw the pattern into the back screen */ + } -// -// D_PageTicker -// Handles timing for warped projection -// -void D_PageTicker (void) -{ - if (--pagetic < 0) - D_AdvanceDemo (); -} + /* see if the border needs to be updated to the screen */ + + if (gamestate == GS_LEVEL && !automapactive && + scaledviewwidth != SCREENWIDTH) + { + if (g_menuactive || g_menuactivestate || !viewactivestate) + borderdrawcount = 3; + if (borderdrawcount) + { + r_draw_view_border(); /* erase old menu stuff */ + borderdrawcount--; + } + } + if (testcontrols) + { + /* Box showing current mouse speed */ + v_draw_mouse_speed_box(testcontrols_mousespeed); + } -// -// D_PageDrawer -// -void D_PageDrawer (void) -{ - V_DrawPatch (0, 0, W_CacheLumpName(pagename, PU_CACHE)); -} + g_menuactivestate = g_menuactive; + viewactivestate = viewactive; + inhelpscreensstate = inhelpscreens; + oldgamestate = wipegamestate = gamestate; + /* draw pause pic */ -// -// D_AdvanceDemo -// Called after each demo or intro demosequence finishes -// -void D_AdvanceDemo (void) -{ - advancedemo = true; + if (paused) + { + if (automapactive) + y = 4; + else + y = viewwindowy + 4; + v_draw_patch_direct(viewwindowx + (scaledviewwidth - 68) / 2, y, + w_cache_lump_name(("M_PAUSE"), PU_CACHE)); + } + + /* menus go directly to the screen */ + + m_drawer(); /* menu is drawn even on top of everything */ + net_update(); /* send out any new accumulation */ + + return wipe; } +/**************************************************************************** + * Name: d_grab_mouse_callback + * + * Description: + * Called to determine whether to grab the mouse pointer + * + ****************************************************************************/ -// -// This cycles through the demo sequences. -// FIXME - version dependend demo numbers? -// -void D_DoAdvanceDemo (void) +static boolean d_grab_mouse_callback(void) { - players[consoleplayer].playerstate = PST_LIVE; // not reborn - advancedemo = false; - usergame = false; // no save / end game here - paused = false; - gameaction = ga_nothing; - - // The Ultimate Doom executable changed the demo sequence to add - // a DEMO4 demo. Final Doom was based on Ultimate, so also - // includes this change; however, the Final Doom IWADs do not - // include a DEMO4 lump, so the game bombs out with an error - // when it reaches this point in the demo sequence. - - // However! There is an alternate version of Final Doom that - // includes a fixed executable. - - if (gameversion == exe_ultimate || gameversion == exe_final) - demosequence = (demosequence+1)%7; - else - demosequence = (demosequence+1)%6; - - switch (demosequence) - { - case 0: - if ( gamemode == commercial ) - pagetic = TICRATE * 11; - else - pagetic = 170; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("TITLEPIC"); - if ( gamemode == commercial ) - S_StartMusic(mus_dm2ttl); - else - S_StartMusic (mus_intro); - break; - case 1: - G_DeferedPlayDemo(DEH_String("demo1")); - break; - case 2: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("CREDIT"); - break; - case 3: - G_DeferedPlayDemo(DEH_String("demo2")); - break; - case 4: - gamestate = GS_DEMOSCREEN; - if ( gamemode == commercial) - { - pagetic = TICRATE * 11; - pagename = DEH_String("TITLEPIC"); - S_StartMusic(mus_dm2ttl); - } - else - { - pagetic = 200; - - if (gameversion >= exe_ultimate) - pagename = DEH_String("CREDIT"); - else - pagename = DEH_String("HELP2"); - } - break; - case 5: - G_DeferedPlayDemo(DEH_String("demo3")); - break; - // THE DEFINITIVE DOOM Special Edition demo - case 6: - G_DeferedPlayDemo(DEH_String("demo4")); - break; - } - - // The Doom 3: BFG Edition version of doom2.wad does not have a - // TITLETPIC lump. Use INTERPIC instead as a workaround. - if (gamevariant == bfgedition && !strcasecmp(pagename, "TITLEPIC") - && W_CheckNumForName("titlepic") < 0) - { - pagename = DEH_String("INTERPIC"); - } -} + /* Drone players don't need mouse focus */ +#ifdef CONFIG_GAMES_NXDOOM_NET + if (drone) return false; +#endif + /* when menu is active or game is paused, release the mouse */ -// -// D_StartTitle -// -void D_StartTitle (void) -{ - gameaction = ga_nothing; - demosequence = -1; - D_AdvanceDemo (); + if (g_menuactive || paused) return false; + + /* only grab mouse when playing levels (but not demos) */ + + return (gamestate == GS_LEVEL) && !demoplayback && !advancedemo; } -// Strings for dehacked replacements of the startup banner -// -// These are from the original source: some of them are perhaps -// not used in any dehacked patches +/**************************************************************************** + * Name: d_run_frame + ****************************************************************************/ -static const char *banners[] = +static void d_run_frame(void) { - // doom2.wad - " " - "DOOM 2: Hell on Earth v%i.%i" - " ", - // doom2.wad v1.666 - " " - "DOOM 2: Hell on Earth v%i.%i66" - " ", - // doom1.wad - " " - "DOOM Shareware Startup v%i.%i" - " ", - // doom.wad - " " - "DOOM Registered Startup v%i.%i" - " ", - // Registered DOOM uses this - " " - "DOOM System Startup v%i.%i" - " ", - // Doom v1.666 - " " - "DOOM System Startup v%i.%i66" - " " - // doom.wad (Ultimate DOOM) - " " - "The Ultimate DOOM Startup v%i.%i" - " ", - // tnt.wad - " " - "DOOM 2: TNT - Evilution v%i.%i" - " ", - // plutonia.wad - " " - "DOOM 2: Plutonia Experiment v%i.%i" - " ", -}; + int nowtime; + int tics; + static int wipestart; + static boolean wipe; -// -// Get game name: if the startup banner has been replaced, use that. -// Otherwise, use the name given -// + if (wipe) + { + do + { + nowtime = i_get_time(); + tics = nowtime - wipestart; + usleep(1000); + } + while (tics <= 0); -static char *GetGameName(const char *gamename) -{ - size_t i; + wipestart = nowtime; + wipe = !wipe_screen_wipe(WIPE_MELT, 0, 0, + SCREENWIDTH, SCREENHEIGHT, tics); + i_update_no_blit(); + m_drawer(); /* menu is drawn even on top of wipes */ + i_finish_update(); /* page flip or blit buffer */ + return; + } + + /* frame synchronous IO operations */ + + i_start_frame(); + + try_run_tics(); /* will run at least one tic */ - for (i=0; iname, "MAP01", 8)) + if (!strncasecmp(lumpinfo[i]->name, "MAP01", 8)) { - gamemission = doom2; - break; - } - else if (!strncasecmp(lumpinfo[i]->name, "E1M1", 8)) + gamemission = doom2; + break; + } + else if (!strncasecmp(lumpinfo[i]->name, "E1M1", 8)) { - gamemission = doom; - break; + gamemission = doom; + break; } } - if (gamemission == none) + if (gamemission == none) { - // Still no idea. I don't think this is going to work. + /* Still no idea. I don't think this is going to work. */ - I_Error("Unknown or invalid IWAD file."); + i_error("Unknown or invalid IWAD file."); } } - // Make sure gamemode is set up correctly + /* Make sure gamemode is set up correctly */ - if (logical_gamemission == doom) + if (logical_gamemission == doom) { - // Doom 1. But which version? + /* Doom 1. But which version? */ - if (W_CheckNumForName("E4M1") > 0) + if (w_check_num_for_name("E4M1") > 0) { - // Ultimate Doom + /* Ultimate Doom */ - gamemode = retail; - } - else if (W_CheckNumForName("E3M1") > 0) + gamemode = retail; + } + else if (w_check_num_for_name("E3M1") > 0) { - gamemode = registered; + gamemode = registered; } - else + else { - gamemode = shareware; + gamemode = shareware; } } - else + else { - int p; + int p; + + /* Doom 2 of some kind. */ + + gamemode = commercial; - // Doom 2 of some kind. - gamemode = commercial; + /* We can manually override the gamemission that we got from the + * IWAD detection code. This allows us to eg. play Plutonia 2 + * with Freedoom and get the right level names. + */ - // We can manually override the gamemission that we got from the - // IWAD detection code. This allows us to eg. play Plutonia 2 - // with Freedoom and get the right level names. + /* @category compat + * @arg + * + * Explicitly specify a Doom II "mission pack" to run as, instead of + * detecting it based on the filename. Valid values are: "doom2", + * "tnt" and "plutonia". + * + */ - //! - // @category compat - // @arg - // - // Explicitly specify a Doom II "mission pack" to run as, instead of - // detecting it based on the filename. Valid values are: "doom2", - // "tnt" and "plutonia". - // - p = M_CheckParmWithArgs("-pack", 1); - if (p > 0) + p = m_check_parm_with_args("-pack", 1); + if (p > 0) { - SetMissionForPackName(myargv[p + 1]); + set_mission_for_pack_name(myargv[p + 1]); } } } -// Set the gamedescription string +/* Set the gamedescription string */ -static void D_SetGameDescription(void) +static void d_set_game_description(void) { - if (logical_gamemission == doom) + if (logical_gamemission == doom) { - // Doom 1. But which version? + /* Doom 1. But which version? */ - if (gamevariant == freedoom) + if (gamevariant == freedoom) { - gamedescription = GetGameName("Freedoom: Phase 1"); + g_gamedescription = get_game_name("Freedoom: Phase 1"); } - else if (gamemode == retail) + else if (gamemode == retail) { - // Ultimate Doom + /* Ultimate Doom */ - gamedescription = GetGameName("The Ultimate DOOM"); + g_gamedescription = get_game_name("The Ultimate DOOM"); } - else if (gamemode == registered) + else if (gamemode == registered) { - gamedescription = GetGameName("DOOM Registered"); + g_gamedescription = get_game_name("DOOM Registered"); } - else if (gamemode == shareware) + else if (gamemode == shareware) { - gamedescription = GetGameName("DOOM Shareware"); + g_gamedescription = get_game_name("DOOM Shareware"); } } - else + else { - // Doom 2 of some kind. But which mission? + /* Doom 2 of some kind. But which mission? */ - if (gamevariant == freedm) + if (gamevariant == freedm) { - gamedescription = GetGameName("FreeDM"); + g_gamedescription = get_game_name("FreeDM"); } - else if (gamevariant == freedoom) + else if (gamevariant == freedoom) { - gamedescription = GetGameName("Freedoom: Phase 2"); + g_gamedescription = get_game_name("Freedoom: Phase 2"); } - else if (logical_gamemission == doom2) + else if (logical_gamemission == doom2) { - gamedescription = GetGameName("DOOM 2: Hell on Earth"); + g_gamedescription = get_game_name("DOOM 2: Hell on Earth"); } - else if (logical_gamemission == pack_plut) + else if (logical_gamemission == pack_plut) { - gamedescription = GetGameName("DOOM 2: Plutonia Experiment"); + g_gamedescription = get_game_name("DOOM 2: Plutonia Experiment"); } - else if (logical_gamemission == pack_tnt) + else if (logical_gamemission == pack_tnt) { - gamedescription = GetGameName("DOOM 2: TNT - Evilution"); + g_gamedescription = get_game_name("DOOM 2: TNT - Evilution"); } } - if (gamedescription == NULL) + if (g_gamedescription == NULL) { - gamedescription = M_StringDuplicate("Unknown"); + g_gamedescription = m_string_duplicate("Unknown"); } } -// print title for every printed line -char title[128]; - -static boolean D_AddFile(char *filename) +static boolean d_addfile(char *filename) { - wad_file_t *handle; + wad_file_t *handle; - printf(" adding %s\n", filename); - handle = W_AddFile(filename); + printf(" adding %s\n", filename); + handle = w_add_file(filename); - return handle != NULL; + return handle != NULL; } -// Copyright message banners -// Some dehacked mods replace these. These are only displayed if they are -// replaced by dehacked. - -static const char *copyright_banners[] = -{ - "===========================================================================\n" - "ATTENTION: This version of DOOM has been modified. If you would like to\n" - "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n" - " You will not receive technical support for modified games.\n" - " press enter to continue\n" - "===========================================================================\n", - - "===========================================================================\n" - " Commercial product - do not distribute!\n" - " Please report software piracy to the SPA: 1-800-388-PIR8\n" - "===========================================================================\n", - - "===========================================================================\n" - " Shareware!\n" - "===========================================================================\n" -}; - -// Prints a message only if it has been modified by dehacked. +/* Prints a message only if it has been modified by dehacked. */ -void PrintDehackedBanners(void) +static void print_dehacked_banners(void) { - size_t i; + size_t i; - for (i=0; i - // @category compat - // - // Emulate a specific version of Doom. Valid values are "1.2", - // "1.5", "1.666", "1.7", "1.8", "1.9", "ultimate", "final", - // "final2", "hacx" and "chex". - // - - p = M_CheckParmWithArgs("-gameversion", 1); - - if (p) - { - for (i=0; gameversions[i].description != NULL; ++i) + byte *demolump; + char demolumpname[6]; + int demoversion; + int p; + int i; + boolean status; + + /* @arg + * @category compat + * + * Emulate a specific version of Doom. Valid values are "1.2", + * "1.5", "1.666", "1.7", "1.8", "1.9", "ultimate", "final", + * "final2", "hacx" and "chex". + * + */ + + p = m_check_parm_with_args("-gameversion", 1); + + if (p) + { + for (i = 0; g_gameversions[i].description != NULL; ++i) { - if (!strcmp(myargv[p+1], gameversions[i].cmdline)) + if (!strcmp(myargv[p + 1], g_gameversions[i].cmdline)) { - gameversion = gameversions[i].version; - break; + gameversion = g_gameversions[i].version; + break; } } - if (gameversions[i].description == NULL) + if (g_gameversions[i].description == NULL) { - printf("Supported game versions:\n"); + printf("Supported game versions:\n"); - for (i=0; gameversions[i].description != NULL; ++i) + for (i = 0; g_gameversions[i].description != NULL; ++i) { - printf("\t%s (%s)\n", gameversions[i].cmdline, - gameversions[i].description); + printf("\t%s (%s)\n", g_gameversions[i].cmdline, + g_gameversions[i].description); } - I_Error("Unknown game version '%s'", myargv[p+1]); + i_error("Unknown game version '%s'", myargv[p + 1]); } } - else + else { - // Determine automatically + /* Determine automatically */ - if (gamemission == pack_chex) + if (gamemission == pack_chex) { - // chex.exe - identified by iwad filename + /* chex.exe - identified by iwad filename */ - gameversion = exe_chex; + gameversion = exe_chex; } - else if (gamemission == pack_hacx) + else if (gamemission == pack_hacx) { - // hacx.exe: identified by iwad filename + /* hacx.exe: identified by iwad filename */ - gameversion = exe_hacx; + gameversion = exe_hacx; } - else if (gamemode == shareware || gamemode == registered - || (gamemode == commercial && gamemission == doom2)) + else if (gamemode == shareware || gamemode == registered || + (gamemode == commercial && gamemission == doom2)) { - // original - gameversion = exe_doom_1_9; + /* original */ + + gameversion = exe_doom_1_9; + + /* Detect version from demo lump */ - // Detect version from demo lump - for (i = 1; i <= 3; ++i) + for (i = 1; i <= 3; ++i) { - M_snprintf(demolumpname, 6, "demo%i", i); - if (W_CheckNumForName(demolumpname) > 0) + snprintf(demolumpname, 6, "demo%i", i); + if (w_check_num_for_name(demolumpname) > 0) { - demolump = W_CacheLumpName(demolumpname, PU_STATIC); - demoversion = demolump[0]; - W_ReleaseLumpName(demolumpname); - status = true; - switch (demoversion) + demolump = w_cache_lump_name(demolumpname, PU_STATIC); + demoversion = demolump[0]; + w_release_lump_name(demolumpname); + status = true; + switch (demoversion) { - case 0: - case 1: - case 2: - case 3: - case 4: - gameversion = exe_doom_1_2; - break; - case 106: - gameversion = exe_doom_1_666; - break; - case 107: - gameversion = exe_doom_1_7; - break; - case 108: - gameversion = exe_doom_1_8; - break; - case 109: - gameversion = exe_doom_1_9; - break; - default: - status = false; - break; + case 0: + case 1: + case 2: + case 3: + case 4: + gameversion = exe_doom_1_2; + break; + case 106: + gameversion = exe_doom_1_666; + break; + case 107: + gameversion = exe_doom_1_7; + break; + case 108: + gameversion = exe_doom_1_8; + break; + case 109: + gameversion = exe_doom_1_9; + break; + default: + status = false; + break; } - if (status) + + if (status) { - break; + break; } } } } - else if (gamemode == retail) + else if (gamemode == retail) { - gameversion = exe_ultimate; + gameversion = exe_ultimate; } - else if (gamemode == commercial) + else if (gamemode == commercial) { - // Final Doom: tnt or plutonia - // Defaults to emulating the first Final Doom executable, - // which has the crash in the demo loop; however, having - // this as the default should mean that it plays back - // most demos correctly. - - gameversion = exe_final; + /* Final Doom: tnt or plutonia + * Defaults to emulating the first Final Doom executable, + * which has the crash in the demo loop; however, having + * this as the default should mean that it plays back + * most demos correctly. + */ + + gameversion = exe_final; } } - // Deathmatch 2.0 did not exist until Doom v1.4 - if (gameversion <= exe_doom_1_2 && deathmatch == 2) + /* Deathmatch 2.0 did not exist until Doom v1.4 */ + + if (gameversion <= exe_doom_1_2 && deathmatch == 2) { - deathmatch = 1; + deathmatch = 1; } - // The original exe does not support retail - 4th episode not supported + /* The original exe does not support retail - 4th episode not supported */ - if (gameversion < exe_ultimate && gamemode == retail) + if (gameversion < exe_ultimate && gamemode == retail) { - gamemode = registered; + gamemode = registered; } - // EXEs prior to the Final Doom exes do not support Final Doom. + /* EXEs prior to the Final Doom exes do not support Final Doom. */ - if (gameversion < exe_final && gamemode == commercial - && (gamemission == pack_tnt || gamemission == pack_plut)) + if (gameversion < exe_final && gamemode == commercial && + (gamemission == pack_tnt || gamemission == pack_plut)) { - gamemission = doom2; + gamemission = doom2; } } -void PrintGameVersion(void) +static void print_game_version(void) { - int i; + int i; - for (i=0; gameversions[i].description != NULL; ++i) + for (i = 0; g_gameversions[i].description != NULL; ++i) { - if (gameversions[i].version == gameversion) + if (g_gameversions[i].version == gameversion) { - printf("Emulating the behavior of the " - "'%s' executable.\n", gameversions[i].description); - break; + printf("Emulating the behavior of the " + "'%s' executable.\n", + g_gameversions[i].description); + break; } } } -// Function called at exit to display the ENDOOM screen +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* d_process_events + * Send all the events of the given timestamp down the responder chain + */ -static void D_Endoom(void) +void d_process_events(void) { - byte *endoom; + event_t *ev; + + /* IF STORE DEMO, DO NOT ACCEPT INPUT */ - // Don't show ENDOOM if we have it disabled, or we're running - // in screensaver or control test mode. Only show it once the - // game has actually started. + if (storedemo) return; - if (!show_endoom || !main_loop_started - || screensaver_mode || M_CheckParm("-testcontrols") > 0) + while ((ev = d_pop_event()) != NULL) { - return; + if (m_responder(ev)) continue; /* menu ate the event */ + g_responder(ev); } - - endoom = W_CacheLumpName(DEH_String("ENDOOM"), PU_STATIC); - - I_Endoom(endoom); } -boolean IsFrenchIWAD(void) -{ - return (gamemission == doom2 && W_CheckNumForName("M_RDTHIS") < 0 - && W_CheckNumForName("M_EPISOD") < 0 && W_CheckNumForName("M_EPI1") < 0 - && W_CheckNumForName("M_EPI2") < 0 && W_CheckNumForName("M_EPI3") < 0 - && W_CheckNumForName("WIOSTF") < 0 && W_CheckNumForName("WIOBJ") >= 0); -} +/* d_doomloop */ -// Load dehacked patches needed for certain IWADs. -static void LoadIwadDeh(void) +void d_doomloop(void) { - // The Freedoom IWADs have DEHACKED lumps that must be loaded. - if (gamevariant == freedoom || gamevariant == freedm) + if (gamevariant == bfgedition && + (demorecording || (gameaction == ga_playdemo) || netgame)) { - // Old versions of Freedoom (before 2014-09) did not have technically - // valid DEHACKED lumps, so ignore errors and just continue if this - // is an old IWAD. - DEH_LoadLumpByName("DEHACKED", false, true); + printf(" WARNING: You are playing using one of the Doom Classic\n" + " IWAD files shipped with the Doom 3: BFG Edition. These are\n" + " known to be incompatible with the regular IWAD files and\n" + " may cause demos and network games to get out of sync.\n"); } - // If this is the HACX IWAD, we need to load the DEHACKED lump. - if (gameversion == exe_hacx) + if (demorecording) { - if (!DEH_LoadLumpByName("DEHACKED", true, false)) - { - I_Error("DEHACKED lump not found. Please check that this is the " - "Hacx v1.2 IWAD."); - } + g_begin_recording(); } - // Chex Quest needs a separate Dehacked patch which must be downloaded - // and installed next to the IWAD. - if (gameversion == exe_chex) - { - char *chex_deh = NULL; - char *dirname; + main_loop_started = true; - // Look for chex.deh in the same directory as the IWAD file. - dirname = M_DirName(iwadfile); - chex_deh = M_StringJoin(dirname, DIR_SEPARATOR_S, "chex.deh", NULL); - free(dirname); + i_set_window_title(g_gamedescription); + i_graphics_check_commandline(); + i_set_grab_mouse_callback(d_grab_mouse_callback); + i_init_graphics(); + enable_loading_disk(); - // If the dehacked patch isn't found, try searching the WAD - // search path instead. We might find it... - if (!M_FileExists(chex_deh)) - { - free(chex_deh); - chex_deh = D_FindWADByName("chex.deh"); - } + try_run_tics(); - // Still not found? - if (chex_deh == NULL) - { - I_Error("Unable to find Chex Quest dehacked file (chex.deh).\n" - "The dehacked file is required in order to emulate\n" - "chex.exe correctly. It can be found in your nearest\n" - "/idgames repository mirror at:\n\n" - " themes/chex/chexdeh.zip"); - } + v_restore_buffer(); + r_execute_set_view_size(); - if (!DEH_LoadFile(chex_deh)) - { - I_Error("Failed to load chex.deh needed for emulating chex.exe."); - } + d_start_game_loop(); + + if (testcontrols) + { + wipegamestate = gamestate; } - if (IsFrenchIWAD()) + while (1) { - char *french_deh = NULL; - char *dirname; + d_run_frame(); + } +} + +/* d_page_ticker + * Handles timing for warped projection + */ + +void d_page_ticker(void) +{ + if (--pagetic < 0) d_advance_demo(); +} + +/**************************************************************************** + * Name: d_page_drawer + ****************************************************************************/ + +void d_page_drawer(void) +{ + v_draw_patch(0, 0, w_cache_lump_name(pagename, PU_CACHE)); +} + +/**************************************************************************** + * Name: d_advance_demo + * + * Description: + * Called after each demo or intro demosequence finishes + * + ****************************************************************************/ - // Look for french.deh in the same directory as the IWAD file. - dirname = M_DirName(iwadfile); - french_deh = M_StringJoin(dirname, DIR_SEPARATOR_S, "french.deh", NULL); - printf("French version\n"); - free(dirname); +void d_advance_demo(void) +{ + advancedemo = true; +} + +/**************************************************************************** + * Name: d_do_advance_demo + * + * Description: + * This cycles through the demo sequences. + * FIXME - version dependent demo numbers? + * + ****************************************************************************/ - // If the dehacked patch isn't found, try searching the WAD - // search path instead. We might find it... - if (!M_FileExists(french_deh)) +void d_do_advance_demo(void) +{ + players[consoleplayer].playerstate = PST_LIVE; /* not reborn */ + advancedemo = false; + usergame = false; /* no save / end game here */ + paused = false; + gameaction = ga_nothing; + + /* The Ultimate Doom executable changed the demo sequence to add + * a DEMO4 demo. Final Doom was based on Ultimate, so also + * includes this change; however, the Final Doom IWADs do not + * include a DEMO4 lump, so the game bombs out with an error + * when it reaches this point in the demo sequence. + * + * However! There is an alternate version of Final Doom that + * includes a fixed executable. + */ + + if (gameversion == exe_ultimate || gameversion == exe_final) + demosequence = (demosequence + 1) % 7; + else + demosequence = (demosequence + 1) % 6; + + switch (demosequence) + { + case 0: + if (gamemode == commercial) + pagetic = TICRATE * 11; + else + pagetic = 170; + gamestate = GS_DEMOSCREEN; + pagename = ("TITLEPIC"); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gamemode == commercial) { - free(french_deh); - french_deh = D_FindWADByName("french.deh"); + s_start_music(MUS_DM2TTL); } - - // Still not found? - if (french_deh == NULL) + else { - I_Error("Unable to find French Doom II dehacked file\n" - "(french.deh). The dehacked file is required in order to\n" - "emulate French doom2.exe correctly. It can be found in\n" - "your nearest /idgames repository mirror at:\n\n" - " utils/exe_edit/patches/french.zip"); + s_start_music(MUS_INTRO); } +#endif - if (!DEH_LoadFile(french_deh)) + break; + case 1: + g_defered_play_demo(("demo1")); + break; + case 2: + pagetic = 200; + gamestate = GS_DEMOSCREEN; + pagename = ("CREDIT"); + break; + case 3: + g_defered_play_demo(("demo2")); + break; + case 4: + gamestate = GS_DEMOSCREEN; + if (gamemode == commercial) { - I_Error("Failed to load french.deh needed for emulating French\n" - "doom2.exe."); + pagetic = TICRATE * 11; + pagename = ("TITLEPIC"); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_music(MUS_DM2TTL); +#endif + } + else + { + pagetic = 200; + + if (gameversion >= exe_ultimate) + pagename = ("CREDIT"); + else + pagename = ("HELP2"); } + break; + case 5: + g_defered_play_demo(("demo3")); + break; + + /* THE DEFINITIVE DOOM Special Edition demo */ + + case 6: + g_defered_play_demo(("demo4")); + break; + } + + /* The Doom 3: BFG Edition version of doom2.wad does not have a + * TITLETPIC lump. Use INTERPIC instead as a workaround. + */ + + if (gamevariant == bfgedition && !strcasecmp(pagename, "TITLEPIC") && + w_check_num_for_name("titlepic") < 0) + { + pagename = ("INTERPIC"); } } -static void G_CheckDemoStatusAtExit (void) +/* d_start_title */ + +void d_start_title(void) { - G_CheckDemoStatus(); + gameaction = ga_nothing; + demosequence = -1; + d_advance_demo(); } -// -// D_DoomMain -// -void D_DoomMain (void) +/* d_doom_main */ + +void d_doom_main(void) { - int p; - char file[256]; - char demolumpname[9]; + int p; + char file[256]; + char demolumpname[9]; - I_AtExit(D_Endoom, false); + i_at_exit(d_endoom, false); - // print banner + /* print banner */ - I_PrintBanner(PACKAGE_STRING); + i_print_banner(PACKAGE_STRING); - DEH_printf("Z_Init: Init zone memory allocation daemon. \n"); - Z_Init (); + printf("z_init: Init zone memory allocation daemon. \n"); + z_init(); - //! - // @category net - // - // Start a dedicated server, routing packets but not participating - // in the game itself. - // +#ifdef CONFIG_GAMES_NXDOOM_NET + /* @category net + * + * Start a dedicated server, routing packets but not participating + * in the game itself. + * + */ - if (M_CheckParm("-dedicated") > 0) + if (m_check_parm("-dedicated") > 0) { - printf("Dedicated server mode.\n"); - NET_DedicatedServer(); + printf("Dedicated server mode.\n"); + net_dedicated_server(); - // Never returns + /* Never returns */ } - //! - // @category net - // - // Query the Internet master server for a global list of active - // servers. - // + /* @category net + * + * Query the Internet master server for a global list of active + * servers. + * + */ - if (M_CheckParm("-search")) + if (m_check_parm("-search")) { - NET_MasterQuery(); - exit(0); + net_master_query(); + exit(0); } - //! - // @arg
- // @category net - // - // Query the status of the server running on the given IP - // address. - // + /* @arg
+ * @category net + * + * Query the status of the server running on the given IP + * address. + * + */ - p = M_CheckParmWithArgs("-query", 1); + p = m_check_parm_with_args("-query", 1); - if (p) + if (p) { - NET_QueryAddress(myargv[p+1]); - exit(0); + net_query_address(myargv[p + 1]); + exit(0); } - //! - // @category net - // - // Search the local LAN for running servers. - // + /* @category net + * + * Search the local LAN for running servers. + * + */ - if (M_CheckParm("-localsearch")) + if (m_check_parm("-localsearch")) { - NET_LANQuery(); - exit(0); + net_lan_query(); + exit(0); } +#endif - //! - // @category game - // @vanilla - // - // Disable monsters. - // - - nomonsters = M_CheckParm ("-nomonsters"); + /* @category game + * @vanilla + * + * Disable monsters. + * + */ - //! - // @category game - // @vanilla - // - // Monsters respawn after being killed. - // + nomonsters = m_check_parm("-nomonsters"); - respawnparm = M_CheckParm ("-respawn"); + /* @category game + * @vanilla + * + * Monsters respawn after being killed. + * + */ - //! - // @category game - // @vanilla - // - // Monsters move faster. - // + respawnparm = m_check_parm("-respawn"); - fastparm = M_CheckParm ("-fast"); + /* @category game + * @vanilla + * + * Monsters move faster. + * + */ - //! - // @vanilla - // - // Developer mode. F1 saves a screenshot in the current working - // directory. - // + fastparm = m_check_parm("-fast"); - devparm = M_CheckParm ("-devparm"); + /* @vanilla + * + * Developer mode. F1 saves a screenshot in the current working + * directory. + * + */ - I_DisplayFPSDots(devparm); + devparm = m_check_parm("-devparm"); - //! - // @category net - // @vanilla - // - // Start a deathmatch game. - // + i_display_fps_dots(devparm); - if (M_CheckParm ("-deathmatch")) - deathmatch = 1; + /* @category net + * @vanilla + * + * Start a deathmatch game. + * + */ - //! - // @category net - // @vanilla - // - // Start a deathmatch 2.0 game. Weapons do not stay in place and - // all items respawn after 30 seconds. - // + if (m_check_parm("-deathmatch")) deathmatch = 1; - if (M_CheckParm ("-altdeath")) - deathmatch = 2; + /* @category net + * @vanilla + * + * Start a deathmatch 2.0 game. Weapons do not stay in place and + * all items respawn after 30 seconds. + * + */ - if (devparm) - DEH_printf(D_DEVSTR); - - // find which dir to use for config files + if (m_check_parm("-altdeath")) deathmatch = 2; -#ifdef _WIN32 + if (devparm) + { + printf(D_DEVSTR); + } - //! - // @category obscure - // @platform windows - // @vanilla - // - // Save configuration data and savegames in c:\doomdata, - // allowing play from CD. - // + /* find which dir to use for config files */ - if (M_ParmExists("-cdrom")) - { - printf(D_CDROM); + /* Auto-detect the configuration dir. */ - M_SetConfigDir("c:\\doomdata\\"); - } - else -#endif + m_set_config_dir(NULL); + + /* @category game + * @arg + * @vanilla + * + * Turbo mode. The player's speed is multiplied by x%. If unspecified, + * x defaults to 200. Values are rounded up to 10 and down to 400. + * + */ + + if ((p = m_check_parm("-turbo"))) { - // Auto-detect the configuration dir. + int scale = 200; - M_SetConfigDir(NULL); + if (p < myargc - 1) scale = atoi(myargv[p + 1]); + if (scale < 10) scale = 10; + if (scale > 400) scale = 400; + printf("turbo scale: %i%%\n", scale); + forwardmove[0] = forwardmove[0] * scale / 100; + forwardmove[1] = forwardmove[1] * scale / 100; + sidemove[0] = sidemove[0] * scale / 100; + sidemove[1] = sidemove[1] * scale / 100; } - //! - // @category game - // @arg - // @vanilla - // - // Turbo mode. The player's speed is multiplied by x%. If unspecified, - // x defaults to 200. Values are rounded up to 10 and down to 400. - // + /* init subsystems */ - if ( (p=M_CheckParm ("-turbo")) ) - { - int scale = 200; - - if (p 400) - scale = 400; - DEH_printf("turbo scale: %i%%\n", scale); - forwardmove[0] = forwardmove[0]*scale/100; - forwardmove[1] = forwardmove[1]*scale/100; - sidemove[0] = sidemove[0]*scale/100; - sidemove[1] = sidemove[1]*scale/100; - } - - // init subsystems - DEH_printf("V_Init: allocate screens.\n"); - V_Init (); + printf("v_init: allocate screens.\n"); + v_init(); + + /* Load configuration files before initialising other subsystems. */ - // Load configuration files before initialising other subsystems. - DEH_printf("M_LoadDefaults: Load system defaults.\n"); - M_SetConfigFilenames("default.cfg", PROGRAM_PREFIX "doom.cfg"); - D_BindVariables(); - M_LoadDefaults(); + printf("m_load_defaults: Load system defaults.\n"); + m_set_config_filenames("default.cfg", PROGRAM_PREFIX "doom.cfg"); + d_bind_variables(); + m_load_defaults(); - // Save configuration at exit. - I_AtExit(M_SaveDefaults, false); + /* Save configuration at exit. */ - // Find main IWAD file and load it. - iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission); + i_at_exit(m_save_defaults, false); - // None found? + /* Find main IWAD file and load it. */ - if (iwadfile == NULL) + iwadfile = d_find_iwad(IWAD_MASK_DOOM, &gamemission); + + /* None found? */ + + if (iwadfile == NULL) { - I_Error("Game mode indeterminate. No IWAD file was found. Try\n" - "specifying one with the '-iwad' command line parameter.\n"); + i_error("Game mode indeterminate. No IWAD file was found. Try\n" + "specifying one with the '-iwad' command line parameter.\n"); } - modifiedgame = false; + modifiedgame = false; + + printf("W_Init: Init WADfiles.\n"); + d_addfile(iwadfile); - DEH_printf("W_Init: Init WADfiles.\n"); - D_AddFile(iwadfile); + w_check_correct_iwad(doom); - W_CheckCorrectIWAD(doom); + /* Now that we've loaded the IWAD, we can figure out what gamemission + * we're playing and which version of Vanilla Doom we need to emulate. + */ - // Now that we've loaded the IWAD, we can figure out what gamemission - // we're playing and which version of Vanilla Doom we need to emulate. - D_IdentifyVersion(); - InitGameVersion(); + d_identify_version(); + init_game_version(); - // Check which IWAD variant we are using. + /* Check which IWAD variant we are using. */ - if (W_CheckNumForName("FREEDOOM") >= 0) + if (w_check_num_for_name("FREEDOOM") >= 0) { - if (W_CheckNumForName("FREEDM") >= 0) + if (w_check_num_for_name("FREEDM") >= 0) { - gamevariant = freedm; + gamevariant = freedm; } - else + else { - gamevariant = freedoom; + gamevariant = freedoom; } } - else if (W_CheckNumForName("DMENUPIC") >= 0) + else if (w_check_num_for_name("DMENUPIC") >= 0) { - gamevariant = bfgedition; + gamevariant = bfgedition; } - //! - // @category mod - // - // Disable automatic loading of Dehacked patches for certain - // IWAD files. - // - if (!M_ParmExists("-nodeh")) + /* @category mod + * + * Disable automatic loading of Dehacked patches for certain + * IWAD files. + * + */ + + if (!m_parm_exists("-nodeh")) { - // Some IWADs have dehacked patches that need to be loaded for - // them to be played properly. - LoadIwadDeh(); + /* Some IWADs have dehacked patches that need to be loaded for + * them to be played properly. + */ + + load_iwad_deh(); } - // Doom 3: BFG Edition includes modified versions of the classic - // IWADs which can be identified by an additional DMENUPIC lump. - // Furthermore, the M_GDHIGH lumps have been modified in a way that - // makes them incompatible to Vanilla Doom and the modified version - // of doom2.wad is missing the TITLEPIC lump. - // We specifically check for DMENUPIC here, before PWADs have been - // loaded which could probably include a lump of that name. + /* Doom 3: BFG Edition includes modified versions of the classic + * IWADs which can be identified by an additional DMENUPIC lump. + * Furthermore, the M_GDHIGH lumps have been modified in a way that + * makes them incompatible to Vanilla Doom and the modified version + * of doom2.wad is missing the TITLEPIC lump. + * We specifically check for DMENUPIC here, before PWADs have been + * loaded which could probably include a lump of that name. + */ - if (gamevariant == bfgedition) + if (gamevariant == bfgedition) { - printf("BFG Edition: Using workarounds as needed.\n"); + printf("BFG Edition: Using workarounds as needed.\n"); - // BFG Edition changes the names of the secret levels to - // censor the Wolfenstein references. It also has an extra - // secret level (MAP33). In Vanilla Doom (meaning the DOS - // version), MAP33 overflows into the Plutonia level names - // array, so HUSTR_33 is actually PHUSTR_1. - DEH_AddStringReplacement(HUSTR_31, "level 31: idkfa"); - DEH_AddStringReplacement(HUSTR_32, "level 32: keen"); - DEH_AddStringReplacement(PHUSTR_1, "level 33: betray"); + /* BFG Edition changes the names of the secret levels to + * censor the Wolfenstein references. It also has an extra + * secret level (MAP33). In Vanilla Doom (meaning the DOS + * version), MAP33 overflows into the Plutonia level names + * array, so HUSTR_33 is actually PHUSTR_1. + */ - // The BFG edition doesn't have the "low detail" menu option (fair - // enough). But bizarrely, it reuses the M_GDHIGH patch as a label - // for the options menu (says "Fullscreen:"). Why the perpetrators - // couldn't just add a new graphic lump and had to reuse this one, - // I don't know. - // - // The end result is that M_GDHIGH is too wide and causes the game - // to crash. As a workaround to get a minimum level of support for - // the BFG edition IWADs, use the "ON"/"OFF" graphics instead. - DEH_AddStringReplacement("M_GDHIGH", "M_MSGON"); - DEH_AddStringReplacement("M_GDLOW", "M_MSGOFF"); + deh_add_string_replacement(HUSTR_31, "level 31: idkfa"); + deh_add_string_replacement(HUSTR_32, "level 32: keen"); + deh_add_string_replacement(PHUSTR_1, "level 33: betray"); - // The BFG edition's "Screen Size:" graphic has also been changed - // to say "Gamepad:". Fortunately, it (along with the original - // Doom IWADs) has an unused graphic that says "Display". So we - // can swap this in instead, and it kind of makes sense. - DEH_AddStringReplacement("M_SCRNSZ", "M_DISP"); + /* The BFG edition doesn't have the "low detail" menu option (fair + * enough). But bizarrely, it reuses the M_GDHIGH patch as a label + * for the options menu (says "Fullscreen:"). Why the perpetrators + * couldn't just add a new graphic lump and had to reuse this one, + * I don't know. + * + * The end result is that M_GDHIGH is too wide and causes the game + * to crash. As a workaround to get a minimum level of support for + * the BFG edition IWADs, use the "ON"/"OFF" graphics instead. + */ + + deh_add_string_replacement("M_GDHIGH", "M_MSGON"); + deh_add_string_replacement("M_GDLOW", "M_MSGOFF"); + + /* The BFG edition's "Screen Size:" graphic has also been changed + * to say "Gamepad:". Fortunately, it (along with the original + * Doom IWADs) has an unused graphic that says "Display". So we + * can swap this in instead, and it kind of makes sense. + */ + + deh_add_string_replacement("M_SCRNSZ", "M_DISP"); } - //! - // @category mod - // - // Disable auto-loading of .wad and .deh files. - // - if (!M_ParmExists("-noautoload") && gamemode != shareware) + /* @category mod + * + * Disable auto-loading of .wad and .deh files. + * + */ + + if (!m_parm_exists("-noautoload") && gamemode != shareware) { - char *autoload_dir; + char *autoload_dir; - // common auto-loaded files for all Doom flavors + /* common auto-loaded files for all Doom flavors */ - if (gamemission < pack_chex) + if (gamemission < pack_chex) { - autoload_dir = M_GetAutoloadDir("doom-all"); - if (autoload_dir != NULL) + autoload_dir = m_get_autoload_dir("doom-all"); + if (autoload_dir != NULL) { - DEH_AutoLoadPatches(autoload_dir); - W_AutoLoadWADs(autoload_dir); - free(autoload_dir); + deh_auto_load_patches(autoload_dir); + w_auto_load_wads(autoload_dir); + free(autoload_dir); } } - // auto-loaded files per IWAD - autoload_dir = M_GetAutoloadDir(D_SaveGameIWADName(gamemission, gamevariant)); - if (autoload_dir != NULL) + /* auto-loaded files per IWAD */ + + autoload_dir = m_get_autoload_dir( + d_save_game_iwad_name(gamemission, gamevariant)); + + if (autoload_dir != NULL) { - DEH_AutoLoadPatches(autoload_dir); - W_AutoLoadWADs(autoload_dir); - free(autoload_dir); + deh_auto_load_patches(autoload_dir); + w_auto_load_wads(autoload_dir); + free(autoload_dir); } } - // Load Dehacked patches specified on the command line with -deh. - // Note that there's a very careful and deliberate ordering to how - // Dehacked patches are loaded. The order we use is: - // 1. IWAD dehacked patches. - // 2. Command line dehacked patches specified with -deh. - // 3. PWAD dehacked patches in DEHACKED lumps. - DEH_ParseCommandLine(); + /* Load Dehacked patches specified on the command line with -deh. + * Note that there's a very careful and deliberate ordering to how + * Dehacked patches are loaded. The order we use is: + * 1. IWAD dehacked patches. + * 2. Command line dehacked patches specified with -deh. + * 3. PWAD dehacked patches in DEHACKED lumps. + */ + + deh_parse_command_line(); + + /* Load PWAD files. */ - // Load PWAD files. - modifiedgame = W_ParseCommandLine(); + modifiedgame = w_parse_command_line(); - // Debug: -// W_PrintDirectory(); + /* Debug: + * w_print_directory(); + */ - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp. - // + /* @arg + * @category demo + * @vanilla + * + * Play back the demo named demo.lmp. + * + */ - p = M_CheckParmWithArgs ("-playdemo", 1); + p = m_check_parm_with_args("-playdemo", 1); - if (!p) + if (!p) { - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp, determining the framerate - // of the screen. - // - p = M_CheckParmWithArgs("-timedemo", 1); + /* @arg + * @category demo + * @vanilla + * + * Play back the demo named demo.lmp, determining the framerate + * of the screen. + * + */ + p = m_check_parm_with_args("-timedemo", 1); } - if (p) + if (p) { - char *uc_filename = strdup(myargv[p + 1]); - M_ForceUppercase(uc_filename); + char *uc_filename = strdup(myargv[p + 1]); + m_force_uppercase(uc_filename); - // With Vanilla you have to specify the file without extension, - // but make that optional. - if (M_StringEndsWith(uc_filename, ".LMP")) + /* With Vanilla you have to specify the file without extension, + * but make that optional. + */ + + if (m_string_ends_with(uc_filename, ".LMP")) { - M_StringCopy(file, myargv[p + 1], sizeof(file)); + m_str_copy(file, myargv[p + 1], sizeof(file)); } - else + else { - DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p+1]); + snprintf(file, sizeof(file), "%s.lmp", myargv[p + 1]); } - free(uc_filename); + free(uc_filename); - if (D_AddFile(file)) + if (d_addfile(file)) { - M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, - sizeof(demolumpname)); + m_str_copy(demolumpname, lumpinfo[numlumps - 1]->name, + sizeof(demolumpname)); } - else + else { - // If file failed to load, still continue trying to play - // the demo in the same way as Vanilla Doom. This makes - // tricks like "-playdemo demo1" possible. + /* If file failed to load, still continue trying to play + * the demo in the same way as Vanilla Doom. This makes + * tricks like "-playdemo demo1" possible. + */ - M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); + m_str_copy(demolumpname, myargv[p + 1], sizeof(demolumpname)); } - printf("Playing demo %s.\n", file); + printf("Playing demo %s.\n", file); } - I_AtExit(G_CheckDemoStatusAtExit, true); + i_at_exit(g_check_demo_status_at_exit, true); + + /* Generate the WAD hash table. Speed things up a bit. */ - // Generate the WAD hash table. Speed things up a bit. - W_GenerateHashTable(); + w_generate_hash_table(); - // Load DEHACKED lumps from WAD files - but only if we give the right - // command line parameter. + /* Load DEHACKED lumps from WAD files - but only if we give the right + * command line parameter. + */ - //! - // @category mod - // - // Load Dehacked patches from DEHACKED lumps contained in one of the - // loaded PWAD files. - // - if (M_ParmExists("-dehlump")) + /* @category mod + * + * Load Dehacked patches from DEHACKED lumps contained in one of the + * loaded PWAD files. + * + */ + + if (m_parm_exists("-dehlump")) { - int i, loaded = 0; - int numiwadlumps = numlumps; + int i; + int loaded = 0; + int numiwadlumps = numlumps; - while (!W_IsIWADLump(lumpinfo[numiwadlumps - 1])) + while (!w_is_iwad_lump(lumpinfo[numiwadlumps - 1])) { - numiwadlumps--; + numiwadlumps--; } - for (i = numiwadlumps; i < numlumps; ++i) + for (i = numiwadlumps; i < numlumps; ++i) { - if (!strncmp(lumpinfo[i]->name, "DEHACKED", 8)) + if (!strncmp(lumpinfo[i]->name, "DEHACKED", 8)) { - DEH_LoadLump(i, false, false); - loaded++; + deh_load_lump(i, false, false); + loaded++; } } - printf(" loaded %i DEHACKED lumps from PWAD files.\n", loaded); + printf(" loaded %i DEHACKED lumps from PWAD files.\n", loaded); } - // Set the gamedescription string. This is only possible now that - // we've finished loading Dehacked patches. - D_SetGameDescription(); + /* Set the gamedescription string. This is only possible now that + * we've finished loading Dehacked patches. + */ + + d_set_game_description(); - savegamedir = M_GetSaveGameDir(D_SaveGameIWADName(gamemission, gamevariant)); + savegamedir = + m_get_save_game_dir(d_save_game_iwad_name(gamemission, gamevariant)); - // Check for -file in shareware - if (modifiedgame && (gamevariant != freedoom)) + /* Check for -file in shareware */ + + if (modifiedgame && (gamevariant != freedoom)) { - // These are the lumps that will be checked in IWAD, - // if any one is not present, execution will be aborted. - char name[23][8]= - { - "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9", - "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9", - "dphoof","bfgga0","heada1","cybra1","spida1d1" - }; - int i; - - if ( gamemode == shareware) - I_Error(DEH_String("\nYou cannot -file with the shareware " - "version. Register!")); + int i; + + if (gamemode == shareware) + i_error(("\nYou cannot -file with the shareware " + "version. Register!")); - // Check for fake IWAD with right name, - // but w/o all the lumps of the registered version. - if (gamemode == registered) - for (i = 0;i < 23; i++) - if (W_CheckNumForName(name[i])<0) - I_Error(DEH_String("\nThis is not the registered version.")); + /* Check for fake IWAD with right name, + * but w/o all the lumps of the registered version. + */ + + if (gamemode == registered) + { + for (i = 0; i < 23; i++) + { + if (w_check_num_for_name(g_name[i]) < 0) + { + i_error(("\nThis is not the registered version.")); + } + } + } } - if (W_CheckNumForName("SS_START") >= 0 - || W_CheckNumForName("FF_END") >= 0) + if (w_check_num_for_name("SS_START") >= 0 || + w_check_num_for_name("FF_END") >= 0) { - I_PrintDivider(); - printf(" WARNING: The loaded WAD file contains modified sprites or\n" - " floor textures. You may want to use the '-merge' command\n" - " line option instead of '-file'.\n"); + i_print_divider(); + printf(" WARNING: The loaded WAD file contains modified sprites or\n" + " floor textures. You may want to use the '-merge' command\n" + " line option instead of '-file'.\n"); } - I_PrintStartupBanner(gamedescription); - PrintDehackedBanners(); + i_print_startup_banner(g_gamedescription); + print_dehacked_banners(); - DEH_printf("I_Init: Setting up machine state.\n"); - I_CheckIsScreensaver(); - I_InitTimer(); - I_InitJoystick(); - I_InitSound(doom); - I_InitMusic(); + printf("i_init: Setting up machine state.\n"); + i_check_is_screensaver(); + i_init_timer(); + i_init_joystick(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + i_init_sound(doom); + i_init_music(); +#endif + +#ifdef CONFIG_GAMES_NXDOOM_NET + printf("net_init: Init network subsystem.\n"); + net_init(); +#endif - printf ("NET_Init: Init network subsystem.\n"); - NET_Init (); + /* Initial netgame startup. Connect to server etc. */ - // Initial netgame startup. Connect to server etc. - D_ConnectNetGame(); + d_connect_net_game(); - // get skill / episode / map from parms - startskill = sk_medium; - startepisode = 1; - startmap = 1; - autostart = false; + /* get skill / episode / map from params */ - //! - // @category game - // @arg - // @vanilla - // - // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of - // 0 disables all monsters. - // + startskill = sk_medium; + startepisode = 1; + startmap = 1; + autostart = false; - p = M_CheckParmWithArgs("-skill", 1); + /* @category game + * @arg + * @vanilla + * + * Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of + * 0 disables all monsters. + * + */ - if (p) + p = m_check_parm_with_args("-skill", 1); + + if (p) { - startskill = myargv[p+1][0]-'1'; - autostart = true; + startskill = myargv[p + 1][0] - '1'; + autostart = true; } - //! - // @category game - // @arg - // @vanilla - // - // Start playing episode n (1-4). - // + /* @category game + * @arg + * @vanilla + * + * Start playing episode n (1-4). + * + */ - p = M_CheckParmWithArgs("-episode", 1); + p = m_check_parm_with_args("-episode", 1); - if (p) + if (p) { - startepisode = myargv[p+1][0]-'0'; - startmap = 1; - autostart = true; + startepisode = myargv[p + 1][0] - '0'; + startmap = 1; + autostart = true; } - - timelimit = 0; - //! - // @arg - // @category net - // @vanilla - // - // For multiplayer games: exit each level after n minutes. - // + timelimit = 0; + + /* @arg + * @category net + * @vanilla + * + * For multiplayer games: exit each level after n minutes. + * + */ - p = M_CheckParmWithArgs("-timer", 1); + p = m_check_parm_with_args("-timer", 1); - if (p) + if (p) { - timelimit = atoi(myargv[p+1]); + timelimit = atoi(myargv[p + 1]); } - //! - // @category net - // @vanilla - // - // Austin Virtual Gaming: end levels after 20 minutes. - // + /* @category net + * @vanilla + * + * Austin Virtual Gaming: end levels after 20 minutes. + * + */ - p = M_CheckParm ("-avg"); + p = m_check_parm("-avg"); - if (p) + if (p) { - timelimit = 20; + timelimit = 20; } - //! - // @category game - // @arg [ | ] - // @vanilla - // - // Start a game immediately, warping to ExMy (Doom 1) or MAPxy - // (Doom 2). - // + /* @category game + * @arg [ | ] + * @vanilla + * + * Start a game immediately, warping to ExMy (Doom 1) or MAPxy + * (Doom 2). + * + */ - p = M_CheckParmWithArgs("-warp", 1); + p = m_check_parm_with_args("-warp", 1); - if (p) + if (p) { - if (gamemode == commercial) - startmap = atoi (myargv[p+1]); - else + if (gamemode == commercial) + startmap = atoi(myargv[p + 1]); + else { - startepisode = myargv[p+1][0]-'0'; + startepisode = myargv[p + 1][0] - '0'; - if (p + 2 < myargc) + if (p + 2 < myargc) { - startmap = myargv[p+2][0]-'0'; + startmap = myargv[p + 2][0] - '0'; } - else + else { - startmap = 1; + startmap = 1; } } - autostart = true; + + autostart = true; } - // Undocumented: - // Invoked by setup to test the controls. + /* Undocumented: + * Invoked by setup to test the controls. + */ - p = M_CheckParm("-testcontrols"); + p = m_check_parm("-testcontrols"); - if (p > 0) + if (p > 0) { - startepisode = 1; - startmap = 1; - autostart = true; - testcontrols = true; + startepisode = 1; + startmap = 1; + autostart = true; + testcontrols = true; } - // Check for load game parameter - // We do this here and save the slot number, so that the network code - // can override it or send the load slot to other players. + /* Check for load game parameter + * We do this here and save the slot number, so that the network code + * can override it or send the load slot to other players. + */ - //! - // @category game - // @arg - // @vanilla - // - // Load the game in slot s. - // + /* @category game + * @arg + * @vanilla + * + * Load the game in slot s. + * + */ - p = M_CheckParmWithArgs("-loadgame", 1); - - if (p) + p = m_check_parm_with_args("-loadgame", 1); + + if (p) { - startloadgame = atoi(myargv[p+1]); + startloadgame = atoi(myargv[p + 1]); } - else + else { - // Not loading a game - startloadgame = -1; + startloadgame = -1; /* Not loading a game */ } - DEH_printf("M_Init: Init miscellaneous info.\n"); - M_Init (); + printf("m_init: Init miscellaneous info.\n"); + m_init(); - DEH_printf("R_Init: Init DOOM refresh daemon - "); - R_Init (); + printf("r_init: Init DOOM refresh daemon - "); + r_init(); - DEH_printf("\nP_Init: Init Playloop state.\n"); - P_Init (); + printf("\np_init: Init Playloop state.\n"); + p_init(); - DEH_printf("S_Init: Setting up sound.\n"); - S_Init (sfxVolume * 8, musicVolume * 8); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + printf("s_init: Setting up sound.\n"); + s_init(g_sfx_volume * 8, g_music_volume * 8); +#endif - DEH_printf("D_CheckNetGame: Checking network game status.\n"); - D_CheckNetGame (); + printf("d_check_net_game: Checking network game status.\n"); + d_check_net_game(); - PrintGameVersion(); + print_game_version(); - DEH_printf("HU_Init: Setting up heads up display.\n"); - HU_Init (); + printf("hu_init: Setting up heads up display.\n"); + hu_init(); - DEH_printf("ST_Init: Init status bar.\n"); - ST_Init (); + printf("st_init: Init status bar.\n"); + st_init(); - // If Doom II without a MAP01 lump, this is a store demo. - // Moved this here so that MAP01 isn't constantly looked up - // in the main loop. + /* If Doom II without a MAP01 lump, this is a store demo. + * Moved this here so that MAP01 isn't constantly looked up + * in the main loop. + */ - if (gamemode == commercial && W_CheckNumForName("map01") < 0) - storedemo = true; + if (gamemode == commercial && w_check_num_for_name("map01") < 0) + storedemo = true; - if (M_CheckParmWithArgs("-statdump", 1)) + if (m_check_parm_with_args("-statdump", 1)) { - I_AtExit(StatDump, true); - DEH_printf("External statistics registered.\n"); + i_at_exit(stat_dump, true); + printf("External statistics registered.\n"); } - //! - // @arg - // @category demo - // @vanilla - // - // Record a demo named x.lmp. - // + /* @arg + * @category demo + * @vanilla + * + * Record a demo named x.lmp. + */ - p = M_CheckParmWithArgs("-record", 1); + p = m_check_parm_with_args("-record", 1); - if (p) + if (p) { - G_RecordDemo (myargv[p+1]); - autostart = true; + g_record_demo(myargv[p + 1]); + autostart = true; } - p = M_CheckParmWithArgs("-playdemo", 1); - if (p) + p = m_check_parm_with_args("-playdemo", 1); + if (p) { - singledemo = true; // quit after one demo - G_DeferedPlayDemo (demolumpname); - D_DoomLoop (); // never returns + singledemo = true; /* quit after one demo */ + g_defered_play_demo(demolumpname); + d_doomloop(); /* never returns */ } - - p = M_CheckParmWithArgs("-timedemo", 1); - if (p) + + p = m_check_parm_with_args("-timedemo", 1); + if (p) { - G_TimeDemo (demolumpname); - D_DoomLoop (); // never returns + g_time_demo(demolumpname); + d_doomloop(); /* never returns */ } - - if (startloadgame >= 0) + + if (startloadgame >= 0) { - M_StringCopy(file, P_SaveGameFile(startloadgame), sizeof(file)); - G_LoadGame(file); + m_str_copy(file, p_save_game_file(startloadgame), sizeof(file)); + g_load_game(file); } - - if (gameaction != ga_loadgame ) + + if (gameaction != ga_loadgame) { - if (autostart || netgame) - G_InitNew (startskill, startepisode, startmap); - else - D_StartTitle (); // start up intro loop + if (autostart || netgame) + g_init_new(startskill, startepisode, startmap); + else + d_start_title(); /* start up intro loop */ } - D_DoomLoop (); // never returns + d_doomloop(); /* never returns */ } - diff --git a/games/NXDoom/src/doom/d_main.h b/games/NXDoom/src/doom/d_main.h index 8e430f85fad..f9742259711 100644 --- a/games/NXDoom/src/doom/d_main.h +++ b/games/NXDoom/src/doom/d_main.h @@ -1,53 +1,58 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System specific interface stuff. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_main.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System specific interface stuff. + * + ****************************************************************************/ #ifndef __D_MAIN__ #define __D_MAIN__ -#include "doomdef.h" - +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include "doomdef.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Read events from all input devices +extern gameaction_t gameaction; +extern boolean advancedemo; -void D_ProcessEvents (void); - +extern const char *pagename; -// -// BASE LEVEL -// -void D_PageTicker (void); -void D_PageDrawer (void); -void D_AdvanceDemo (void); -void D_DoAdvanceDemo (void); -void D_StartTitle (void); - -// -// GLOBAL VARIABLES -// +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -extern gameaction_t gameaction; -extern boolean advancedemo; +/* Read events from all input devices */ -extern const char *pagename; +void d_process_events(void); +/* BASE LEVEL */ -#endif +void d_page_ticker(void); +void d_page_drawer(void); +void d_advance_demo(void); +void d_do_advance_demo(void); +void d_start_title(void); +#endif /* __D_MAIN__ */ diff --git a/games/NXDoom/src/doom/d_net.c b/games/NXDoom/src/doom/d_net.c index f8969fe0289..3be74240cc3 100644 --- a/games/NXDoom/src/doom/d_net.c +++ b/games/NXDoom/src/doom/d_net.c @@ -1,34 +1,42 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM Network game communication and protocol, -// all OS independend parts. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_net.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * DOOM Network game communication and protocol, all OS independent parts. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include "d_main.h" -#include "m_argv.h" -#include "m_menu.h" -#include "m_misc.h" +#include "doomdef.h" +#include "doomstat.h" +#include "g_game.h" #include "i_system.h" #include "i_timer.h" #include "i_video.h" -#include "g_game.h" -#include "doomdef.h" -#include "doomstat.h" +#include "m_argv.h" +#include "m_menu.h" +#include "m_misc.h" #include "w_checksum.h" #include "w_wad.h" @@ -36,252 +44,290 @@ #include "d_loop.h" +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void run_tic(ticcmd_t *cmds, boolean *ingame); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static loop_interface_t g_doom_loop_interface = +{ + d_process_events, + g_build_ticcmd, + run_tic, + m_ticker, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + ticcmd_t *netcmds; -// Called when a player leaves the game +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: player_quit_game + * + * Description: + * Called when a player leaves the game + * + ****************************************************************************/ -static void PlayerQuitGame(player_t *player) +static void player_quit_game(player_t *player) { - static char exitmsg[80]; - unsigned int player_num; + static char exitmsg[80]; + unsigned int player_num; - player_num = player - players; + player_num = player - players; - // Do this the same way as Vanilla Doom does, to allow dehacked - // replacements of this message + /* Do this the same way as Vanilla Doom does, to allow dehacked + * replacements of this message + */ - M_StringCopy(exitmsg, DEH_String("Player 1 left the game"), - sizeof(exitmsg)); + m_str_copy(exitmsg, ("Player 1 left the game"), sizeof(exitmsg)); - exitmsg[7] += player_num; + exitmsg[7] += player_num; - playeringame[player_num] = false; - players[consoleplayer].message = exitmsg; + playeringame[player_num] = false; + players[consoleplayer].message = exitmsg; - // TODO: check if it is sensible to do this: + /* TODO: check if it is sensible to do this: */ - if (demorecording) + if (demorecording) { - G_CheckDemoStatus (); + g_check_demo_status(); } } -static void RunTic(ticcmd_t *cmds, boolean *ingame) +static void run_tic(ticcmd_t *cmds, boolean *ingame) { - unsigned int i; + unsigned int i; - // Check for player quits. + /* Check for player quits. */ - for (i = 0; i < MAXPLAYERS; ++i) + for (i = 0; i < MAXPLAYERS; ++i) { - if (!demoplayback && playeringame[i] && !ingame[i]) + if (!demoplayback && playeringame[i] && !ingame[i]) { - PlayerQuitGame(&players[i]); + player_quit_game(&players[i]); } } - netcmds = cmds; + netcmds = cmds; - // check that there are players in the game. if not, we cannot - // run a tic. + /* check that there are players in the game. if not, we cannot + * run a tic. + */ - if (advancedemo) - D_DoAdvanceDemo (); + if (advancedemo) d_do_advance_demo(); - G_Ticker (); + g_ticker(); } -static loop_interface_t doom_loop_interface = { - D_ProcessEvents, - G_BuildTiccmd, - RunTic, - M_Ticker -}; - - -// Load game settings from the specified structure and -// set global variables. +/**************************************************************************** + * Name: Load_Game_Settings + * + * Description: + * Load game settings from the specified structure and + * set global variables. + * + ****************************************************************************/ -static void LoadGameSettings(net_gamesettings_t *settings) +static void load_game_settings(net_gamesettings_t *settings) { - unsigned int i; - - deathmatch = settings->deathmatch; - startepisode = settings->episode; - startmap = settings->map; - startskill = settings->skill; - startloadgame = settings->loadgame; - lowres_turn = settings->lowres_turn; - nomonsters = settings->nomonsters; - fastparm = settings->fast_monsters; - respawnparm = settings->respawn_monsters; - timelimit = settings->timelimit; - consoleplayer = settings->consoleplayer; - - if (lowres_turn) + unsigned int i; + + deathmatch = settings->deathmatch; + startepisode = settings->episode; + startmap = settings->map; + startskill = settings->skill; + startloadgame = settings->loadgame; + lowres_turn = settings->lowres_turn; + nomonsters = settings->nomonsters; + fastparm = settings->fast_monsters; + respawnparm = settings->respawn_monsters; + timelimit = settings->timelimit; + consoleplayer = settings->consoleplayer; + + if (lowres_turn) { - printf("NOTE: Turning resolution is reduced; this is probably " - "because there is a client recording a Vanilla demo.\n"); + printf("NOTE: Turning resolution is reduced; this is probably " + "because there is a client recording a Vanilla demo.\n"); } - for (i = 0; i < MAXPLAYERS; ++i) + for (i = 0; i < MAXPLAYERS; ++i) { - playeringame[i] = i < settings->num_players; + playeringame[i] = i < settings->num_players; } } -// Save the game settings from global variables to the specified -// game settings structure. +/**************************************************************************** + * Name: save_game_settings + * + * Description: + * Save the game settings from global variables to the specified + * game settings structure. + * + ****************************************************************************/ -static void SaveGameSettings(net_gamesettings_t *settings) +static void save_game_settings(net_gamesettings_t *settings) { - // Fill in game settings structure with appropriate parameters - // for the new game - - settings->deathmatch = deathmatch; - settings->episode = startepisode; - settings->map = startmap; - settings->skill = startskill; - settings->loadgame = startloadgame; - settings->gameversion = gameversion; - settings->nomonsters = nomonsters; - settings->fast_monsters = fastparm; - settings->respawn_monsters = respawnparm; - settings->timelimit = timelimit; - - settings->lowres_turn = (M_ParmExists("-record") - && !M_ParmExists("-longtics")) - || M_ParmExists("-shorttics"); + /* Fill in game settings structure with appropriate parameters + * for the new game + */ + + settings->deathmatch = deathmatch; + settings->episode = startepisode; + settings->map = startmap; + settings->skill = startskill; + settings->loadgame = startloadgame; + settings->gameversion = gameversion; + settings->nomonsters = nomonsters; + settings->fast_monsters = fastparm; + settings->respawn_monsters = respawnparm; + settings->timelimit = timelimit; + + settings->lowres_turn = + (m_parm_exists("-record") && !m_parm_exists("-longtics")) || + m_parm_exists("-shorttics"); } -static void InitConnectData(net_connect_data_t *connect_data) +static void init_connect_data(net_connect_data_t *connect_data) { - boolean shorttics; + boolean shorttics; - connect_data->max_players = MAXPLAYERS; - connect_data->drone = false; + connect_data->max_players = MAXPLAYERS; + connect_data->drone = false; - //! - // @category net - // - // Run as the left screen in three screen mode. - // + /* @category net + * + * Run as the left screen in three screen mode. + */ - if (M_CheckParm("-left") > 0) + if (m_check_parm("-left") > 0) { - viewangleoffset = ANG90; - connect_data->drone = true; + viewangleoffset = ANG90; + connect_data->drone = true; } - //! - // @category net - // - // Run as the right screen in three screen mode. - // + /* @category net + * + * Run as the right screen in three screen mode. + */ - if (M_CheckParm("-right") > 0) + if (m_check_parm("-right") > 0) { - viewangleoffset = ANG270; - connect_data->drone = true; + viewangleoffset = ANG270; + connect_data->drone = true; } - // - // Connect data - // + /* Connect data */ - // Game type fields: + /* Game type fields: */ - connect_data->gamemode = gamemode; - connect_data->gamemission = gamemission; + connect_data->gamemode = gamemode; + connect_data->gamemission = gamemission; - //! - // @category demo - // - // Play with low turning resolution to emulate demo recording. - // + /* @category demo + * + * Play with low turning resolution to emulate demo recording. + */ - shorttics = M_ParmExists("-shorttics"); + shorttics = m_parm_exists("-shorttics"); - // Are we recording a demo? Possibly set lowres turn mode + /* Are we recording a demo? Possibly set lowres turn mode */ - connect_data->lowres_turn = (M_ParmExists("-record") - && !M_ParmExists("-longtics")) - || shorttics; + connect_data->lowres_turn = + (m_parm_exists("-record") && !m_parm_exists("-longtics")) || shorttics; - // Read checksums of our WAD directory and dehacked information + /* Read checksums of our WAD directory and dehacked information */ - W_Checksum(connect_data->wad_sha1sum); - DEH_Checksum(connect_data->deh_sha1sum); + w_checksum(connect_data->wad_sha1sum); + deh_checksum(connect_data->deh_sha1sum); - // Are we playing with the Freedoom IWAD? + /* Are we playing with the Freedoom IWAD? */ - connect_data->is_freedoom = W_CheckNumForName("FREEDOOM") >= 0; + connect_data->is_freedoom = w_check_num_for_name("FREEDOOM") >= 0; } -void D_ConnectNetGame(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void d_connect_net_game(void) { - net_connect_data_t connect_data; + net_connect_data_t connect_data; - InitConnectData(&connect_data); - netgame = D_InitNetGame(&connect_data); + init_connect_data(&connect_data); + netgame = d_init_net_game(&connect_data); - //! - // @category net - // - // Start the game playing as though in a netgame with a single - // player. This can also be used to play back single player netgame - // demos. - // +#ifdef CONFIG_GAMES_NXDOOM_NET + /* @category net + * + * Start the game playing as though in a netgame with a single + * player. This can also be used to play back single player netgame + * demos. + */ - if (M_CheckParm("-solo-net") > 0) + if (m_check_parm("-solo-net") > 0) { - netgame = true; + netgame = true; } +#endif } -// -// D_CheckNetGame -// Works out player numbers among the net participants -// -void D_CheckNetGame (void) +/**************************************************************************** + * Name: d_check_net_game + * + * Description: + * Works out player numbers among the net participants + * + ****************************************************************************/ + +void d_check_net_game(void) { - net_gamesettings_t settings; + net_gamesettings_t settings; - if (netgame) + if (netgame) { - autostart = true; + autostart = true; } - D_RegisterLoopCallbacks(&doom_loop_interface); + d_register_loop_callbacks(&g_doom_loop_interface); - SaveGameSettings(&settings); - D_StartNetGame(&settings, NULL); - LoadGameSettings(&settings); + save_game_settings(&settings); + d_start_net_game(&settings, NULL); + load_game_settings(&settings); - DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", - startskill, deathmatch, startmap, startepisode); + printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", + startskill, deathmatch, startmap, startepisode); - DEH_printf("player %i of %i (%i nodes)\n", - consoleplayer+1, settings.num_players, settings.num_players); + printf("player %i of %i (%i nodes)\n", consoleplayer + 1, + settings.num_players, settings.num_players); - // Show players here; the server might have specified a time limit + /* Show players here; the server might have specified a time limit */ - if (timelimit > 0 && deathmatch) + if (timelimit > 0 && deathmatch) { - // Gross hack to work like Vanilla: + /* Gross hack to work like Vanilla: */ - if (timelimit == 20 && M_CheckParm("-avg")) + if (timelimit == 20 && m_check_parm("-avg")) { - DEH_printf("Austin Virtual Gaming: Levels will end " - "after 20 minutes\n"); + printf("Austin Virtual Gaming: Levels will end " + "after 20 minutes\n"); } - else + else { - DEH_printf("Levels will end after %d minute", timelimit); - if (timelimit > 1) - printf("s"); - printf(".\n"); + printf("Levels will end after %d minute", timelimit); + if (timelimit > 1) printf("s"); + printf(".\n"); } } } - diff --git a/games/NXDoom/src/doom/d_player.h b/games/NXDoom/src/doom/d_player.h index d78482d0e00..54defc586e6 100644 --- a/games/NXDoom/src/doom/d_player.h +++ b/games/NXDoom/src/doom/d_player.h @@ -1,209 +1,236 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_player.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * + ****************************************************************************/ #ifndef __D_PLAYER__ #define __D_PLAYER__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* The player data structure depends on a number + * of other structs: items (internal inventory), + * animation states (closely tied to the sprites + * used to represent them, unfortunately). + */ -// The player data structure depends on a number -// of other structs: items (internal inventory), -// animation states (closely tied to the sprites -// used to represent them, unfortunately). #include "d_items.h" #include "p_pspr.h" -// In addition, the player is just a special -// case of the generic moving object/actor. +/* In addition, the player is just a special + * case of the generic moving object/actor. + */ + #include "p_mobj.h" -// Finally, for odd reasons, the player input -// is buffered within the player data struct, -// as commands per game tick. +/* Finally, for odd reasons, the player input + * is buffered within the player data struct, + * as commands per game tick. + */ + #include "d_ticcmd.h" #include "net_defs.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Player states. */ - -// -// Player states. -// typedef enum { - // Playing or camping. - PST_LIVE, - // Dead on the ground, view follows killer. - PST_DEAD, - // Ready to restart/respawn??? - PST_REBORN - + PST_LIVE, /* Playing or camping. */ + PST_DEAD, /* Dead on the ground, view follows killer. */ + PST_REBORN /* Ready to restart/respawn??? */ } playerstate_t; +/* Player internal flags, for cheats and debug. */ -// -// Player internal flags, for cheats and debug. -// typedef enum { - // No clipping, walk through barriers. - CF_NOCLIP = 1, - // No damage, no health loss. - CF_GODMODE = 2, - // Not really a cheat, just a debug aid. - CF_NOMOMENTUM = 4 - + CF_NOCLIP = 1, /* No clipping, walk through barriers. */ + CF_GODMODE = 2, /* No damage, no health loss. */ + CF_NOMOMENTUM = 4 /* Not really a cheat, just a debug aid. */ } cheat_t; +/* Extended player object info: player_t */ -// -// Extended player object info: player_t -// typedef struct player_s { - mobj_t* mo; - playerstate_t playerstate; - ticcmd_t cmd; - - // Determine POV, - // including viewpoint bobbing during movement. - // Focal origin above r.z - fixed_t viewz; - // Base height above floor for viewz. - fixed_t viewheight; - // Bob/squat speed. - fixed_t deltaviewheight; - // bounded/scaled total momentum. - fixed_t bob; - - // This is only used between levels, - // mo->health is used during levels. - int health; - int armorpoints; - // Armor type is 0-2. - int armortype; - - // Power ups. invinc and invis are tic counters. - int powers[NUMPOWERS]; - boolean cards[NUMCARDS]; - boolean backpack; - - // Frags, kills of other players. - int frags[MAXPLAYERS]; - weapontype_t readyweapon; - - // Is wp_nochange if not changing. - weapontype_t pendingweapon; - - int weaponowned[NUMWEAPONS]; - int ammo[NUMAMMO]; - int maxammo[NUMAMMO]; - - // True if button down last tic. - int attackdown; - int usedown; - - // Bit flags, for cheats and debug. - // See cheat_t, above. - int cheats; - - // Refired shots are less accurate. - int refire; - - // For intermission stats. - int killcount; - int itemcount; - int secretcount; - - // Hint messages. - const char *message; - - // For screen flashing (red or bright). - int damagecount; - int bonuscount; - - // Who did damage (NULL for floors/ceilings). - mobj_t* attacker; - - // So gun flashes light up areas. - int extralight; - - // Current PLAYPAL, ??? - // can be set to REDCOLORMAP for pain, etc. - int fixedcolormap; - - // Player skin colorshift, - // 0-3 for which color to draw player. - int colormap; - - // Overlay view sprites (gun, etc). - pspdef_t psprites[NUMPSPRITES]; - - // True if secret level has been done. - boolean didsecret; + mobj_t *mo; + playerstate_t playerstate; + ticcmd_t cmd; + + /* Determine POV, including viewpoint bobbing during movement. + * Focal origin above r.z + */ + + fixed_t viewz; + + /* Base height above floor for viewz. */ + + fixed_t viewheight; + + /* Bob/squat speed. */ + + fixed_t deltaviewheight; + + /* bounded/scaled total momentum. */ + + fixed_t bob; + + /* This is only used between levels, + * mo->health is used during levels. + */ + + int health; + int armorpoints; + + /* Armor type is 0-2. */ + + int armortype; + + /* Power ups. invinc and invis are tic counters. */ + + int powers[NUMPOWERS]; + boolean cards[NUMCARDS]; + boolean backpack; + + /* Frags, kills of other players. */ + + int frags[MAXPLAYERS]; + weapontype_t readyweapon; + + /* Is wp_nochange if not changing. */ + + weapontype_t pendingweapon; + + int weaponowned[NUMWEAPONS]; + int ammo[NUMAMMO]; + int maxammo[NUMAMMO]; + + /* True if button down last tic. */ + + int attackdown; + int usedown; + + /* Bit flags, for cheats and debug. + * See cheat_t, above. + */ + + int cheats; + + /* Refired shots are less accurate. */ + int refire; + + /* For intermission stats. */ + + int killcount; + int itemcount; + int secretcount; + + /* Hint messages. */ + + const char *message; + + /* For screen flashing (red or bright). */ + + int damagecount; + int bonuscount; + + /* Who did damage (NULL for floors/ceilings). */ + + mobj_t *attacker; + + /* So gun flashes light up areas. */ + + int extralight; + + /* Current PLAYPAL, ??? can be set to REDCOLORMAP for pain, etc. + */ + + int fixedcolormap; + + /* Player skin colorshift, 0-3 for which color to draw player. + */ + + int colormap; + + /* Overlay view sprites (gun, etc). */ + + pspdef_t psprites[NUMPSPRITES]; + + /* True if secret level has been done. */ + + boolean didsecret; } player_t; +/* INTERMISSION + * Structure passed e.g. to wi_start(wb) + */ -// -// INTERMISSION -// Structure passed e.g. to WI_Start(wb) -// typedef struct { - boolean in; // whether the player is in game - - // Player stats, kills, collected items etc. - int skills; - int sitems; - int ssecret; - int stime; - int frags[4]; - int score; // current score on entry, modified on return - + boolean in; /* whether the player is in game */ + + /* Player stats, kills, collected items etc. */ + + int skills; + int sitems; + int ssecret; + int stime; + int frags[4]; + int score; /* current score on entry, modified on return */ } wbplayerstruct_t; typedef struct { - int epsd; // episode # (0-2) - - // if true, splash the secret level - boolean didsecret; - - // previous and next levels, origin 0 - int last; - int next; - - int maxkills; - int maxitems; - int maxsecret; - int maxfrags; - - // the par time - int partime; - - // index of this player in game - int pnum; - - wbplayerstruct_t plyr[MAXPLAYERS]; + int epsd; /* episode # (0-2) */ -} wbstartstruct_t; + /* if true, splash the secret level */ + + boolean didsecret; + + /* previous and next levels, origin 0 */ + int last; + int next; + + int maxkills; + int maxitems; + int maxsecret; + int maxfrags; + + /* the par time */ + + int partime; + + /* index of this player in game */ + + int pnum; + + wbplayerstruct_t plyr[MAXPLAYERS]; +} wbstartstruct_t; -#endif +#endif /* __D_PLAYER__ */ diff --git a/games/NXDoom/src/doom/d_textur.h b/games/NXDoom/src/doom/d_textur.h index 1afe040eb04..cf77f38b4ce 100644 --- a/games/NXDoom/src/doom/d_textur.h +++ b/games/NXDoom/src/doom/d_textur.h @@ -1,43 +1,50 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Typedefs related to to textures etc., -// isolated here to make it easier separating modules. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_textur.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Typedefs related to to textures etc., + * isolated here to make it easier separating modules. + * + ****************************************************************************/ #ifndef __D_TEXTUR__ #define __D_TEXTUR__ -#include "doomtype.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include "doomtype.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Flats? + * + * a pic is an unmasked block of pixels + */ -// -// Flats? -// -// a pic is an unmasked block of pixels typedef struct { - byte width; - byte height; - byte data; + byte width; + byte height; + byte data; } pic_t; - - - -#endif +#endif /* __D_TEXTUR__ */ diff --git a/games/NXDoom/src/doom/d_think.h b/games/NXDoom/src/doom/d_think.h index 0966ad96023..19742248140 100644 --- a/games/NXDoom/src/doom/d_think.h +++ b/games/NXDoom/src/doom/d_think.h @@ -1,68 +1,64 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// MapObj data. Map Objects or mobjs are actors, entities, -// thinker, take-your-pick... anything that moves, acts, or -// suffers state changes of more or less violent nature. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/d_think.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * MapObj data. Map Objects or mobjs are actors, entities, + * thinker, take-your-pick... anything that moves, acts, or + * suffers state changes of more or less violent nature. + * + ****************************************************************************/ #ifndef __D_THINK__ #define __D_THINK__ +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Experimental stuff. + * To compile this as "ANSI C with classes" we will need to handle the + * various action functions cleanly. + */ - - -// -// Experimental stuff. -// To compile this as "ANSI C with classes" -// we will need to handle the various -// action functions cleanly. -// -typedef void (*actionf_v)(); -typedef void (*actionf_p1)( void* ); -typedef void (*actionf_p2)( void*, void* ); +typedef void (*actionf_v)(); +typedef void (*actionf_p1)(void *); +typedef void (*actionf_p2)(void *, void *); typedef union { - actionf_v acv; - actionf_p1 acp1; - actionf_p2 acp2; - + actionf_v acv; + actionf_p1 acp1; + actionf_p2 acp2; } actionf_t; +/* Historically, "think_t" is yet another function pointer to a routine to + * handle an actor. + */ +typedef actionf_t think_t; +/* Doubly linked list of actors. */ - -// Historically, "think_t" is yet another -// function pointer to a routine to handle -// an actor. -typedef actionf_t think_t; - - -// Doubly linked list of actors. typedef struct thinker_s { - struct thinker_s* prev; - struct thinker_s* next; - think_t function; - + struct thinker_s *prev; + struct thinker_s *next; + think_t function; } thinker_t; - - -#endif +#endif /* __D_THINK__ */ diff --git a/games/NXDoom/src/doom/deh_ammo.c b/games/NXDoom/src/doom/deh_ammo.c index dd8bee54678..83aabf00e1b 100644 --- a/games/NXDoom/src/doom/deh_ammo.c +++ b/games/NXDoom/src/doom/deh_ammo.c @@ -1,103 +1,128 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Ammo" sections in dehacked files -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/deh_ammo.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Parses "Ammo" sections in dehacked files + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include #include -#include "doomdef.h" -#include "doomtype.h" #include "deh_defs.h" #include "deh_io.h" #include "deh_main.h" +#include "doomdef.h" +#include "doomtype.h" #include "p_local.h" -static void *DEH_AmmoStart(deh_context_t *context, char *line) +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_ammo_start(deh_context_t *context, char *line); +static void deh_ammo_parse_line(deh_context_t *context, char *line, + void *tag); +static void deh_ammo_sha1_hash(SHA1_CTX *context); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_ammo = +{ + "Ammo", + NULL, + deh_ammo_start, + deh_ammo_parse_line, + NULL, + deh_ammo_sha1_hash, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_ammo_start(deh_context_t *context, char *line) { - int ammo_number = 0; + int ammo_number = 0; - if (sscanf(line, "Ammo %i", &ammo_number) != 1) + if (sscanf(line, "Ammo %i", &ammo_number) != 1) { - DEH_Warning(context, "Parse error on section start"); - return NULL; + deh_warning(context, "Parse error on section start"); + return NULL; } - if (ammo_number < 0 || ammo_number >= NUMAMMO) + if (ammo_number < 0 || ammo_number >= NUMAMMO) { - DEH_Warning(context, "Invalid ammo number: %i", ammo_number); - return NULL; + deh_warning(context, "Invalid ammo number: %i", ammo_number); + return NULL; } - - return &maxammo[ammo_number]; + + return &maxammo[ammo_number]; } -static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) +static void deh_ammo_parse_line(deh_context_t *context, char *line, + void *tag) { - char *variable_name, *value; - int ivalue; - int ammo_number; + char *variable_name; + char *value; + int ivalue; + int ammo_number; - if (tag == NULL) - return; + if (tag == NULL) return; - ammo_number = ((int *) tag) - maxammo; + ammo_number = ((int *)tag) - maxammo; - // Parse the assignment + /* Parse the assignment */ - if (!DEH_ParseAssignment(line, &variable_name, &value)) + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse + /* Failed to parse */ - DEH_Warning(context, "Failed to parse assignment"); - return; + deh_warning(context, "Failed to parse assignment"); + return; } - ivalue = atoi(value); + ivalue = atoi(value); - // maxammo + /* maxammo */ - if (!strcasecmp(variable_name, "Per ammo")) - clipammo[ammo_number] = ivalue; - else if (!strcasecmp(variable_name, "Max ammo")) - maxammo[ammo_number] = ivalue; - else + if (!strcasecmp(variable_name, "Per ammo")) + clipammo[ammo_number] = ivalue; + else if (!strcasecmp(variable_name, "Max ammo")) + maxammo[ammo_number] = ivalue; + else { - DEH_Warning(context, "Field named '%s' not found", variable_name); + deh_warning(context, "Field named '%s' not found", variable_name); } } -static void DEH_AmmoSHA1Hash(sha1_context_t *context) +static void deh_ammo_sha1_hash(SHA1_CTX *context) { - int i; + int i; - for (i=0; i #include @@ -25,15 +33,33 @@ #include "dstrings.h" -typedef struct { - const char *macro; - const char *string; +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef struct +{ + const char *macro; + const char *string; } bex_string_t; -// mnemonic keys table -static const bex_string_t bex_stringtable[] = { - // part 1 - general initialization and prompts - {"D_DEVSTR", D_DEVSTR}, +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_bex_str_start(deh_context_t *context, char *line); +static void deh_bex_str_parse_line(deh_context_t *context, char *line, + void *tag); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* mnemonic keys table */ + +static const bex_string_t g_bex_stringtable[] = +{ + {"D_DEVSTR", D_DEVSTR}, /* part 1 - general initialization and prompts */ {"D_CDROM", D_CDROM}, {"QUITMSG", QUITMSG}, {"LOADNET", LOADNET}, @@ -59,8 +85,8 @@ static const bex_string_t bex_stringtable[] = { {"EMPTYSTRING", EMPTYSTRING}, {"GGSAVED", GGSAVED}, {"SAVEGAMENAME", SAVEGAMENAME}, - // part 2 - messages when the player gets things - {"GOTARMOR", GOTARMOR}, + {"GOTARMOR", + GOTARMOR}, /* part 2 - messages when the player gets things */ {"GOTMEGA", GOTMEGA}, {"GOTHTHBONUS", GOTHTHBONUS}, {"GOTARMBONUS", GOTARMBONUS}, @@ -97,15 +123,13 @@ static const bex_string_t bex_stringtable[] = { {"GOTPLASMA", GOTPLASMA}, {"GOTSHOTGUN", GOTSHOTGUN}, {"GOTSHOTGUN2", GOTSHOTGUN2}, - // part 3 - messages when keys are needed - {"PD_BLUEO", PD_BLUEO}, + {"PD_BLUEO", PD_BLUEO}, /* part 3 - messages when keys are needed */ {"PD_REDO", PD_REDO}, {"PD_YELLOWO", PD_YELLOWO}, {"PD_BLUEK", PD_BLUEK}, {"PD_REDK", PD_REDK}, {"PD_YELLOWK", PD_YELLOWK}, - // part 4 - multiplayer messaging - {"HUSTR_MSGU", HUSTR_MSGU}, + {"HUSTR_MSGU", HUSTR_MSGU}, /* part 4 - multiplayer messaging */ {"HUSTR_MESSAGESENT", HUSTR_MESSAGESENT}, {"HUSTR_CHATMACRO0", HUSTR_CHATMACRO0}, {"HUSTR_CHATMACRO1", HUSTR_CHATMACRO1}, @@ -126,8 +150,7 @@ static const bex_string_t bex_stringtable[] = { {"HUSTR_PLRINDIGO", HUSTR_PLRINDIGO}, {"HUSTR_PLRBROWN", HUSTR_PLRBROWN}, {"HUSTR_PLRRED", HUSTR_PLRRED}, - // part 5 - level names in the automap - {"HUSTR_E1M1", HUSTR_E1M1}, + {"HUSTR_E1M1", HUSTR_E1M1}, /* part 5 - level names in the automap */ {"HUSTR_E1M2", HUSTR_E1M2}, {"HUSTR_E1M3", HUSTR_E1M3}, {"HUSTR_E1M4", HUSTR_E1M4}, @@ -259,8 +282,8 @@ static const bex_string_t bex_stringtable[] = { {"THUSTR_30", THUSTR_30}, {"THUSTR_31", THUSTR_31}, {"THUSTR_32", THUSTR_32}, - // part 6 - messages as a result of toggling states - {"AMSTR_FOLLOWON", AMSTR_FOLLOWON}, + {"AMSTR_FOLLOWON", + AMSTR_FOLLOWON}, /* part 6 - messages as a result of toggling states */ {"AMSTR_FOLLOWOFF", AMSTR_FOLLOWOFF}, {"AMSTR_GRIDON", AMSTR_GRIDON}, {"AMSTR_GRIDOFF", AMSTR_GRIDOFF}, @@ -278,8 +301,7 @@ static const bex_string_t bex_stringtable[] = { {"STSTR_BEHOLDX", STSTR_BEHOLDX}, {"STSTR_CHOPPERS", STSTR_CHOPPERS}, {"STSTR_CLEV", STSTR_CLEV}, - // part 7 - episode intermission texts - {"E1TEXT", E1TEXT}, + {"E1TEXT", E1TEXT}, /* part 7 - episode intermission texts */ {"E2TEXT", E2TEXT}, {"E3TEXT", E3TEXT}, {"E4TEXT", E4TEXT}, @@ -301,8 +323,7 @@ static const bex_string_t bex_stringtable[] = { {"T4TEXT", T4TEXT}, {"T5TEXT", T5TEXT}, {"T6TEXT", T6TEXT}, - // part 8 - creature names for the finale - {"CC_ZOMBIE", CC_ZOMBIE}, + {"CC_ZOMBIE", CC_ZOMBIE}, /* part 8 - creature names for the finale */ {"CC_SHOTGUN", CC_SHOTGUN}, {"CC_HEAVY", CC_HEAVY}, {"CC_IMP", CC_IMP}, @@ -319,8 +340,7 @@ static const bex_string_t bex_stringtable[] = { {"CC_SPIDER", CC_SPIDER}, {"CC_CYBER", CC_CYBER}, {"CC_HERO", CC_HERO}, - // part 9 - intermission tiled backgrounds - {"BGFLATE1", "FLOOR4_8"}, + {"BGFLATE1", "FLOOR4_8"}, /* part 9 - intermission tiled backgrounds */ {"BGFLATE2", "SFLR6_1"}, {"BGFLATE3", "MFLR8_4"}, {"BGFLATE4", "MFLR8_3"}, @@ -333,44 +353,54 @@ static const bex_string_t bex_stringtable[] = { {"BGCASTCALL", "BOSSBACK"}, }; -static void *DEH_BEXStrStart(deh_context_t *context, char *line) +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_bexstr = +{ + "[STRINGS]", + NULL, + deh_bex_str_start, + deh_bex_str_parse_line, + NULL, + NULL, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_bex_str_start(deh_context_t *context, char *line) { - char s[10]; + char s[10]; - if (sscanf(line, "%9s", s) == 0 || strncmp("[STRINGS]", s, sizeof(s))) + if (sscanf(line, "%9s", s) == 0 || strncmp("[STRINGS]", s, sizeof(s))) { - DEH_Warning(context, "Parse error on section start"); + deh_warning(context, "Parse error on section start"); } - return NULL; + return NULL; } -static void DEH_BEXStrParseLine(deh_context_t *context, char *line, void *tag) +static void deh_bex_str_parse_line(deh_context_t *context, char *line, + void *tag) { - char *variable_name, *value; - int i; + char *variable_name; + char *value; + int i; - if (!DEH_ParseAssignment(line, &variable_name, &value)) + if (!deh_parse_assignment(line, &variable_name, &value)) { - DEH_Warning(context, "Failed to parse assignment"); - return; + deh_warning(context, "Failed to parse assignment"); + return; } - for (i = 0; i < arrlen(bex_stringtable); i++) + for (i = 0; i < arrlen(g_bex_stringtable); i++) { - if (!strcmp(bex_stringtable[i].macro, variable_name)) - { - DEH_AddStringReplacement(bex_stringtable[i].string, value); - } + if (!strcmp(g_bex_stringtable[i].macro, variable_name)) + { + deh_add_string_replacement(g_bex_stringtable[i].string, value); + } } } - -deh_section_t deh_section_bexstr = -{ - "[STRINGS]", - NULL, - DEH_BEXStrStart, - DEH_BEXStrParseLine, - NULL, - NULL, -}; diff --git a/games/NXDoom/src/doom/deh_cheat.c b/games/NXDoom/src/doom/deh_cheat.c index 8e269c04ef8..f01c08976d6 100644 --- a/games/NXDoom/src/doom/deh_cheat.c +++ b/games/NXDoom/src/doom/deh_cheat.c @@ -1,146 +1,179 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Cheat" sections in dehacked files -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/deh_cheat.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Parses "Cheat" sections in dehacked files + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include #include "doomtype.h" +#include "am_map.h" #include "deh_defs.h" #include "deh_io.h" #include "deh_main.h" -#include "am_map.h" #include "st_stuff.h" -typedef struct +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef struct { - const char *name; - cheatseq_t *seq; + const char *name; + cheatseq_t *seq; } deh_cheat_t; -static deh_cheat_t allcheats[] = +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_cheat_start(deh_context_t *context, char *line); +static void deh_cheat_parse_line(deh_context_t *context, char *line, + void *tag); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static deh_cheat_t g_allcheats[] = { - {"Change music", &cheat_mus }, - {"Chainsaw", &cheat_choppers }, - {"God mode", &cheat_god }, - {"Ammo & Keys", &cheat_ammo }, - {"Ammo", &cheat_ammonokey }, - {"No Clipping 1", &cheat_noclip }, - {"No Clipping 2", &cheat_commercial_noclip }, - {"Invincibility", &cheat_powerup[0] }, - {"Berserk", &cheat_powerup[1] }, - {"Invisibility", &cheat_powerup[2] }, - {"Radiation Suit", &cheat_powerup[3] }, - {"Auto-map", &cheat_powerup[4] }, - {"Lite-Amp Goggles", &cheat_powerup[5] }, - {"BEHOLD menu", &cheat_powerup[6] }, - {"Level Warp", &cheat_clev }, - {"Player Position", &cheat_mypos }, - {"Map cheat", &cheat_amap }, + {"Change music", &cheat_mus}, + {"Chainsaw", &cheat_choppers}, + {"God mode", &cheat_god}, + {"Ammo & Keys", &cheat_ammo}, + {"Ammo", &cheat_ammonokey}, + {"No Clipping 1", &cheat_noclip}, + {"No Clipping 2", &cheat_commercial_noclip}, + {"Invincibility", &cheat_powerup[0]}, + {"Berserk", &cheat_powerup[1]}, + {"Invisibility", &cheat_powerup[2]}, + {"Radiation Suit", &cheat_powerup[3]}, + {"Auto-map", &cheat_powerup[4]}, + {"Lite-Amp Goggles", &cheat_powerup[5]}, + {"BEHOLD menu", &cheat_powerup[6]}, + {"Level Warp", &cheat_clev}, + {"Player Position", &cheat_mypos}, + {"Map cheat", &cheat_amap}, }; -static deh_cheat_t *FindCheatByName(char *name) +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_cheat = { - size_t i; - - for (i=0; i= cheat->seq->sequence_len) + { + deh_warning(context, "Cheat sequence longer than supported by " + "Vanilla dehacked"); + break; + } - if (!deh_allow_long_cheats && i >= cheat->seq->sequence_len) + if (deh_apply_cheats) { - DEH_Warning(context, "Cheat sequence longer than supported by " - "Vanilla dehacked"); - break; + cheat->seq->sequence[i] = unsvalue[i]; } - if (deh_apply_cheats) - { - cheat->seq->sequence[i] = unsvalue[i]; - } - ++i; + ++i; - // Absolute limit - don't exceed + /* Absolute limit - don't exceed */ - if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars) + if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars) { - DEH_Error(context, "Cheat sequence too long!"); - return; + deh_error(context, "Cheat sequence too long!"); + return; } } - if (deh_apply_cheats) + if (deh_apply_cheats) { - cheat->seq->sequence[i] = '\0'; + cheat->seq->sequence[i] = '\0'; } } - -deh_section_t deh_section_cheat = -{ - "Cheat", - NULL, - DEH_CheatStart, - DEH_CheatParseLine, - NULL, - NULL, -}; - diff --git a/games/NXDoom/src/doom/deh_doom.c b/games/NXDoom/src/doom/deh_doom.c index b7ff04a738a..419caffa8b8 100644 --- a/games/NXDoom/src/doom/deh_doom.c +++ b/games/NXDoom/src/doom/deh_doom.c @@ -1,35 +1,45 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Top-level dehacked definitions for Doom dehacked. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/deh_doom.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * + * Top-level dehacked definitions for Doom dehacked. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include #include "deh_defs.h" #include "deh_main.h" +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ const char *deh_signatures[] = { - "Patch File for DeHackEd v2.3", - "Patch File for DeHackEd v3.0", - NULL + "Patch File for DeHackEd v2.3", + "Patch File for DeHackEd v3.0", + NULL, }; - -// -// List of section types: -// +/* List of section types: */ deh_section_t *deh_section_types[] = { @@ -38,11 +48,18 @@ deh_section_t *deh_section_types[] = &deh_section_frame, &deh_section_misc, &deh_section_pointer, +#ifdef CONFIG_GAMES_NXDOOM_SOUND &deh_section_sound, +#else + NULL, +#endif &deh_section_text, &deh_section_thing, &deh_section_weapon, &deh_section_bexstr, - NULL + NULL, }; +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/doom/deh_frame.c b/games/NXDoom/src/doom/deh_frame.c index e1cd59da717..d5ec5521688 100644 --- a/games/NXDoom/src/doom/deh_frame.c +++ b/games/NXDoom/src/doom/deh_frame.c @@ -1,25 +1,33 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Frame" sections in dehacked files -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/deh_frame.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Parses "Frame" sections in dehacked files + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include -#include "doomtype.h" #include "d_items.h" +#include "doomtype.h" #include "info.h" #include "deh_defs.h" @@ -27,135 +35,164 @@ #include "deh_main.h" #include "deh_mapping.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + DEH_BEGIN_MAPPING(state_mapping, state_t) - DEH_MAPPING("Sprite number", sprite) - DEH_MAPPING("Sprite subnumber", frame) - DEH_MAPPING("Duration", tics) - DEH_MAPPING("Next frame", nextstate) - DEH_MAPPING("Unknown 1", misc1) - DEH_MAPPING("Unknown 2", misc2) - DEH_UNSUPPORTED_MAPPING("Codep frame") +DEH_MAPPING("Sprite number", sprite) +DEH_MAPPING("Sprite subnumber", frame) +DEH_MAPPING("Duration", tics) +DEH_MAPPING("Next frame", nextstate) +#if 0 +DEH_MAPPING("Unknown 1", misc1) +DEH_MAPPING("Unknown 2", misc2) +#endif +DEH_UNSUPPORTED_MAPPING("Codep frame") DEH_END_MAPPING -static void *DEH_FrameStart(deh_context_t *context, char *line) +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_frame_start(deh_context_t *context, char *line); +static void deh_frame_overflow(deh_context_t *context, char *varname, + int value); +static void deh_frame_parse_line(deh_context_t *context, char *line, + void *tag); +static void deh_frame_sha1_sum(SHA1_CTX *context); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_frame = +{ + "Frame", + NULL, + deh_frame_start, + deh_frame_parse_line, + NULL, + deh_frame_sha1_sum, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_frame_start(deh_context_t *context, char *line) { - int frame_number = 0; - state_t *state; - - if (sscanf(line, "Frame %i", &frame_number) != 1) + int frame_number = 0; + state_t *state; + + if (sscanf(line, "Frame %i", &frame_number) != 1) { - DEH_Warning(context, "Parse error on section start"); - return NULL; + deh_warning(context, "Parse error on section start"); + return NULL; } - - if (frame_number < 0 || frame_number >= NUMSTATES) + + if (frame_number < 0 || frame_number >= NUMSTATES) { - DEH_Warning(context, "Invalid frame number: %i", frame_number); - return NULL; + deh_warning(context, "Invalid frame number: %i", frame_number); + return NULL; } - if (frame_number >= DEH_VANILLA_NUMSTATES) + if (frame_number >= DEH_VANILLA_NUMSTATES) { - DEH_Warning(context, "Attempt to modify frame %i: this will cause " - "problems in Vanilla dehacked.", frame_number); + deh_warning(context, + "Attempt to modify frame %i: this will cause " + "problems in Vanilla dehacked.", + frame_number); } - state = &states[frame_number]; + state = &states[frame_number]; - return state; + return state; } -// Simulate a frame overflow: Doom has 967 frames in the states[] array, but -// DOS dehacked internally only allocates memory for 966. As a result, -// attempts to set frame 966 (the last frame) will overflow the dehacked -// array and overwrite the weaponinfo[] array instead. -// -// This is noticable in Batman Doom where it is impossible to switch weapons -// away from the fist once selected. - -static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value) +/* Simulate a frame overflow: Doom has 967 frames in the states[] array, but + * DOS dehacked internally only allocates memory for 966. As a result, + * attempts to set frame 966 (the last frame) will overflow the dehacked + * array and overwrite the weaponinfo[] array instead. + * + * This is noticeable in Batman Doom where it is impossible to switch weapons + * away from the fist once selected. + */ + +static void deh_frame_overflow(deh_context_t *context, char *varname, + int value) { - if (!strcasecmp(varname, "Duration")) + if (!strcasecmp(varname, "Duration")) { - weaponinfo[0].ammo = value; + weaponinfo[0].ammo = value; } - else if (!strcasecmp(varname, "Codep frame")) + else if (!strcasecmp(varname, "Codep frame")) { - weaponinfo[0].upstate = value; + weaponinfo[0].upstate = value; } - else if (!strcasecmp(varname, "Next frame")) + else if (!strcasecmp(varname, "Next frame")) { - weaponinfo[0].downstate = value; + weaponinfo[0].downstate = value; } - else if (!strcasecmp(varname, "Unknown 1")) + else if (!strcasecmp(varname, "Unknown 1")) { - weaponinfo[0].readystate = value; + weaponinfo[0].readystate = value; } - else if (!strcasecmp(varname, "Unknown 2")) + else if (!strcasecmp(varname, "Unknown 2")) { - weaponinfo[0].atkstate = value; + weaponinfo[0].atkstate = value; } - else + else { - DEH_Error(context, "Unable to simulate frame overflow: field '%s'", - varname); + deh_error(context, "Unable to simulate frame overflow: field '%s'", + varname); } } -static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) +static void deh_frame_parse_line(deh_context_t *context, char *line, + void *tag) { - state_t *state; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; + state_t *state; + char *variable_name; + char *value; + int ivalue; - state = (state_t *) tag; + if (tag == NULL) return; - // Parse the assignment + state = (state_t *)tag; - if (!DEH_ParseAssignment(line, &variable_name, &value)) + /* Parse the assignment */ + + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse + /* Failed to parse */ - DEH_Warning(context, "Failed to parse assignment"); - return; + deh_warning(context, "Failed to parse assignment"); + return; } - - // all values are integers - ivalue = atoi(value); - - if (state == &states[NUMSTATES - 1]) + /* all values are integers */ + + ivalue = atoi(value); + + if (state == &states[NUMSTATES - 1]) { - DEH_FrameOverflow(context, variable_name, ivalue); + deh_frame_overflow(context, variable_name, ivalue); } - else + else { - // set the appropriate field + /* set the appropriate field */ - DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); + deh_set_mapping(context, &state_mapping, state, variable_name, ivalue); } } -static void DEH_FrameSHA1Sum(sha1_context_t *context) +static void deh_frame_sha1_sum(SHA1_CTX *context) { - int i; + int i; - for (i=0; i #include -#include "doomtype.h" #include "deh_defs.h" #include "deh_io.h" #include "deh_main.h" #include "deh_misc.h" +#include "doomtype.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct misc_settings +{ + const char *deh_name; + int *value; +}; -// Dehacked: "Initial Health" -// This is the initial health a player has when starting anew. -// See G_PlayerReborn in g_game.c +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_misc_start(deh_context_t *context, char *line); +static void deh_misc_parse_line(deh_context_t *context, char *line, + void *tag); +static void deh_misc_sha1_sum(SHA1_CTX *context); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Dehacked: "Initial Health" + * This is the initial health a player has when starting anew. + * See g_player_reborn in g_game.c + */ int deh_initial_health = DEH_DEFAULT_INITIAL_HEALTH; -// Dehacked: "Initial bullets" -// This is the number of bullets the player has when starting anew. -// See G_PlayerReborn in g_game.c +/* Dehacked: "Initial bullets" + * This is the number of bullets the player has when starting anew. + * See g_player_reborn in g_game.c + */ int deh_initial_bullets = DEH_DEFAULT_INITIAL_BULLETS; -// Dehacked: "Max Health" -// This is the maximum health that can be reached using health -// potions. See P_TouchSpecialThing in p_inter.c +/* Dehacked: "Max Health" + * This is the maximum health that can be reached using health + * potions. See p_touch_special_thing in p_inter.c + */ int deh_max_health = DEH_DEFAULT_MAX_HEALTH; -// Dehacked: "Max Armor" -// This is the maximum armor which can be reached by picking up -// armor helmets. See P_TouchSpecialThing in p_inter.c +/* Dehacked: "Max Armor" + * This is the maximum armor which can be reached by picking up + * armor helmets. See p_touch_special_thing in p_inter.c + */ int deh_max_armor = DEH_DEFAULT_MAX_ARMOR; -// Dehacked: "Green Armor Class" -// This is the armor class that is given when picking up the green -// armor or an armor helmet. See P_TouchSpecialThing in p_inter.c -// -// DOS dehacked only modifies the behavior of the green armor shirt, -// the armor class set by armor helmets is not affected. +/* Dehacked: "Green Armor Class" + * This is the armor class that is given when picking up the green + * armor or an armor helmet. See p_touch_special_thing in p_inter.c + * + * DOS dehacked only modifies the behavior of the green armor shirt, + * the armor class set by armor helmets is not affected. + */ int deh_green_armor_class = DEH_DEFAULT_GREEN_ARMOR_CLASS; -// Dehacked: "Blue Armor Class" -// This is the armor class that is given when picking up the blue -// armor or a megasphere. See P_TouchSpecialThing in p_inter.c -// -// DOS dehacked only modifies the MegaArmor behavior and not -// the MegaSphere, which always gives armor type 2. +/* Dehacked: "Blue Armor Class" + * This is the armor class that is given when picking up the blue + * armor or a megasphere. See p_touch_special_thing in p_inter.c + * + * DOS dehacked only modifies the MegaArmor behavior and not + * the MegaSphere, which always gives armor type 2. + */ int deh_blue_armor_class = DEH_DEFAULT_BLUE_ARMOR_CLASS; -// Dehacked: "Max soulsphere" -// The maximum health which can be reached by picking up the -// soulsphere. See P_TouchSpecialThing in p_inter.c +/* Dehacked: "Max soulsphere" + * The maximum health which can be reached by picking up the + * soulsphere. See p_touch_special_thing in p_inter.c + */ int deh_max_soulsphere = DEH_DEFAULT_MAX_SOULSPHERE; -// Dehacked: "Soulsphere health" -// The amount of health bonus that picking up a soulsphere -// gives. See P_TouchSpecialThing in p_inter.c +/* Dehacked: "Soulsphere health" + * The amount of health bonus that picking up a soulsphere + * gives. See p_touch_special_thing in p_inter.c + */ int deh_soulsphere_health = DEH_DEFAULT_SOULSPHERE_HEALTH; -// Dehacked: "Megasphere health" -// This is what the health is set to after picking up a -// megasphere. See P_TouchSpecialThing in p_inter.c +/* Dehacked: "Megasphere health" + * This is what the health is set to after picking up a + * megasphere. See p_touch_special_thing in p_inter.c + */ int deh_megasphere_health = DEH_DEFAULT_MEGASPHERE_HEALTH; -// Dehacked: "God mode health" -// This is what the health value is set to when cheating using -// the IDDQD god mode cheat. See ST_Responder in st_stuff.c +/* Dehacked: "God mode health" + * This is what the health value is set to when cheating using + * the IDDQD god mode cheat. See st_responder in st_stuff.c + */ int deh_god_mode_health = DEH_DEFAULT_GOD_MODE_HEALTH; -// Dehacked: "IDFA Armor" -// This is what the armor is set to when using the IDFA cheat. -// See ST_Responder in st_stuff.c +/* Dehacked: "IDFA Armor" + * This is what the armor is set to when using the IDFA cheat. + * See st_responder in st_stuff.c + */ int deh_idfa_armor = DEH_DEFAULT_IDFA_ARMOR; -// Dehacked: "IDFA Armor Class" -// This is what the armor class is set to when using the IDFA cheat. -// See ST_Responder in st_stuff.c +/* Dehacked: "IDFA Armor Class" + * This is what the armor class is set to when using the IDFA cheat. + * See st_responder in st_stuff.c + */ int deh_idfa_armor_class = DEH_DEFAULT_IDFA_ARMOR_CLASS; -// Dehacked: "IDKFA Armor" -// This is what the armor is set to when using the IDKFA cheat. -// See ST_Responder in st_stuff.c +/* Dehacked: "IDKFA Armor" + * This is what the armor is set to when using the IDKFA cheat. + * See st_responder in st_stuff.c + */ int deh_idkfa_armor = DEH_DEFAULT_IDKFA_ARMOR; -// Dehacked: "IDKFA Armor Class" -// This is what the armor class is set to when using the IDKFA cheat. -// See ST_Responder in st_stuff.c +/* Dehacked: "IDKFA Armor Class" + * This is what the armor class is set to when using the IDKFA cheat. + * See st_responder in st_stuff.c + */ int deh_idkfa_armor_class = DEH_DEFAULT_IDKFA_ARMOR_CLASS; -// Dehacked: "BFG Cells/Shot" -// This is the number of CELLs firing the BFG uses up. -// See P_CheckAmmo and A_FireBFG in p_pspr.c +/* Dehacked: "BFG Cells/Shot" + * This is the number of CELLs firing the BFG uses up. + * See p_check_ammo and a_fire_bfg in p_pspr.c + */ int deh_bfg_cells_per_shot = DEH_DEFAULT_BFG_CELLS_PER_SHOT; -// Dehacked: "Monsters infight" -// This controls whether monsters can harm other monsters of the same -// species. For example, whether an imp fireball will damage other -// imps. The value of this in dehacked patches is weird - '202' means -// off, while '221' means on. -// -// See PIT_CheckThing in p_map.c +/* Dehacked: "Monsters infight" + * This controls whether monsters can harm other monsters of the same + * species. For example, whether an imp fireball will damage other + * imps. The value of this in dehacked patches is weird - '202' means + * off, while '221' means on. + * + * See pit_check_thing in p_map.c + */ int deh_species_infighting = DEH_DEFAULT_SPECIES_INFIGHTING; -static struct +deh_section_t deh_section_misc = +{ + "Misc", + NULL, + deh_misc_start, + deh_misc_parse_line, + NULL, + deh_misc_sha1_sum, +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct misc_settings misc_settings[] = { - const char *deh_name; - int *value; -} misc_settings[] = { - {"Initial Health", &deh_initial_health}, - {"Initial Bullets", &deh_initial_bullets}, - {"Max Health", &deh_max_health}, - {"Max Armor", &deh_max_armor}, - {"Green Armor Class", &deh_green_armor_class}, - {"Blue Armor Class", &deh_blue_armor_class}, - {"Max Soulsphere", &deh_max_soulsphere}, - {"Soulsphere Health", &deh_soulsphere_health}, - {"Megasphere Health", &deh_megasphere_health}, - {"God Mode Health", &deh_god_mode_health}, - {"IDFA Armor", &deh_idfa_armor}, - {"IDFA Armor Class", &deh_idfa_armor_class}, - {"IDKFA Armor", &deh_idkfa_armor}, - {"IDKFA Armor Class", &deh_idkfa_armor_class}, - {"BFG Cells/Shot", &deh_bfg_cells_per_shot}, + {"Initial Health", &deh_initial_health}, + {"Initial Bullets", &deh_initial_bullets}, + {"Max Health", &deh_max_health}, + {"Max Armor", &deh_max_armor}, + {"Green Armor Class", &deh_green_armor_class}, + {"Blue Armor Class", &deh_blue_armor_class}, + {"Max Soulsphere", &deh_max_soulsphere}, + {"Soulsphere Health", &deh_soulsphere_health}, + {"Megasphere Health", &deh_megasphere_health}, + {"God Mode Health", &deh_god_mode_health}, + {"IDFA Armor", &deh_idfa_armor}, + {"IDFA Armor Class", &deh_idfa_armor_class}, + {"IDKFA Armor", &deh_idkfa_armor}, + {"IDKFA Armor Class", &deh_idkfa_armor_class}, + {"BFG Cells/Shot", &deh_bfg_cells_per_shot}, }; -static void *DEH_MiscStart(deh_context_t *context, char *line) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_misc_start(deh_context_t *context, char *line) { - return NULL; + return NULL; } -static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag) +static void deh_misc_parse_line(deh_context_t *context, char *line, + void *tag) { - char *variable_name, *value; - int ivalue; - size_t i; + char *variable_name; + char *value; + int ivalue; + size_t i; - if (!DEH_ParseAssignment(line, &variable_name, &value)) + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse + /* Failed to parse */ - DEH_Warning(context, "Failed to parse assignment"); - return; + deh_warning(context, "Failed to parse assignment"); + return; } - ivalue = atoi(value); + ivalue = atoi(value); - if (!strcasecmp(variable_name, "Monsters Infight")) + if (!strcasecmp(variable_name, "Monsters Infight")) { - // See notes above. - - if (ivalue == 202) + /* See notes above. */ + + if (ivalue == 202) { - deh_species_infighting = 0; + deh_species_infighting = 0; } - else if (ivalue == 221) + else if (ivalue == 221) { - deh_species_infighting = 1; + deh_species_infighting = 1; } - else + else { - DEH_Warning(context, - "Invalid value for 'Monsters Infight': %i", ivalue); + deh_warning(context, "Invalid value for 'Monsters Infight': %i", + ivalue); } - - return; + + return; } - for (i=0; i #include @@ -26,117 +34,139 @@ #include "deh_io.h" #include "deh_main.h" +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void deh_pointer_init(void); +static void *deh_pointer_start(deh_context_t *context, char *line); +static void deh_pointer_parse_line(deh_context_t *context, char *line, + void *tag); +static void deh_pointer_sha1_sum(SHA1_CTX *context); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + static actionf_t codeptrs[NUMSTATES]; -static int CodePointerIndex(actionf_t *ptr) +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_pointer = +{ + "Pointer", + deh_pointer_init, + deh_pointer_start, + deh_pointer_parse_line, + NULL, + deh_pointer_sha1_sum, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int code_pointer_index(actionf_t *ptr) { - int i; + int i; - for (i=0; i= NUMSTATES) + if (frame_number < 0 || frame_number >= NUMSTATES) { - DEH_Warning(context, "Invalid frame number: %i", frame_number); - return NULL; + deh_warning(context, "Invalid frame number: %i", frame_number); + return NULL; } - return &states[frame_number]; + return &states[frame_number]; } -static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag) +static void deh_pointer_parse_line(deh_context_t *context, char *line, + void *tag) { - state_t *state; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; + state_t *state; + char *variable_name; + char *value; + int ivalue; + + if (tag == NULL) return; - state = (state_t *) tag; + state = (state_t *)tag; - // Parse the assignment + /* Parse the assignment */ - if (!DEH_ParseAssignment(line, &variable_name, &value)) + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse - DEH_Warning(context, "Failed to parse assignment"); - return; + /* Failed to parse */ + + deh_warning(context, "Failed to parse assignment"); + return; } - -// printf("Set %s to %s for state\n", variable_name, value); - // all values are integers + /* all values are integers */ - ivalue = atoi(value); - - // set the appropriate field + ivalue = atoi(value); - if (!strcasecmp(variable_name, "Codep frame")) + /* set the appropriate field */ + + if (!strcasecmp(variable_name, "Codep frame")) { - if (ivalue < 0 || ivalue >= NUMSTATES) + if (ivalue < 0 || ivalue >= NUMSTATES) { - DEH_Warning(context, "Invalid state '%i'", ivalue); + deh_warning(context, "Invalid state '%i'", ivalue); } - else - { - state->action = codeptrs[ivalue]; + else + { + state->action = codeptrs[ivalue]; } } - else + else { - DEH_Warning(context, "Unknown variable name '%s'", variable_name); + deh_warning(context, "Unknown variable name '%s'", variable_name); } } -static void DEH_PointerSHA1Sum(sha1_context_t *context) +static void deh_pointer_sha1_sum(SHA1_CTX *context) { - int i; + int i; - for (i=0; i #include -#include "doomtype.h" #include "deh_defs.h" #include "deh_main.h" #include "deh_mapping.h" +#include "doomtype.h" #include "sounds.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t) - DEH_UNSUPPORTED_MAPPING("Offset") - DEH_UNSUPPORTED_MAPPING("Zero/One") - DEH_MAPPING("Value", priority) - DEH_MAPPING("Zero 1", link) - DEH_MAPPING("Zero 2", pitch) - DEH_MAPPING("Zero 3", volume) - DEH_UNSUPPORTED_MAPPING("Zero 4") - DEH_MAPPING("Neg. One 1", usefulness) - DEH_MAPPING("Neg. One 2", lumpnum) +DEH_UNSUPPORTED_MAPPING("Offset") +DEH_UNSUPPORTED_MAPPING("Zero/One") +DEH_MAPPING("Value", priority) +DEH_MAPPING("Zero 1", link) +DEH_MAPPING("Zero 2", pitch) +DEH_MAPPING("Zero 3", volume) +DEH_UNSUPPORTED_MAPPING("Zero 4") +DEH_MAPPING("Neg. One 1", usefulness) +DEH_MAPPING("Neg. One 2", lumpnum) DEH_END_MAPPING -static void *DEH_SoundStart(deh_context_t *context, char *line) +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_sound_start(deh_context_t *context, char *line); +static void deh_sound_parse_line(deh_context_t *context, char *line, + void *tag); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_sound = +{ + "Sound", + NULL, + deh_sound_start, + deh_sound_parse_line, + NULL, + NULL, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_sound_start(deh_context_t *context, char *line) { - int sound_number = 0; - - if (sscanf(line, "Sound %i", &sound_number) != 1) + int sound_number = 0; + + if (sscanf(line, "Sound %i", &sound_number) != 1) { - DEH_Warning(context, "Parse error on section start"); - return NULL; + deh_warning(context, "Parse error on section start"); + return NULL; } - if (sound_number < 0 || sound_number >= NUMSFX) + if (sound_number < 0 || sound_number >= SFX_NUMSFX) { - DEH_Warning(context, "Invalid sound number: %i", sound_number); - return NULL; + deh_warning(context, "Invalid sound number: %i", sound_number); + return NULL; } - if (sound_number >= DEH_VANILLA_NUMSFX) + if (sound_number >= DEH_VANILLA_NUMSFX) { - DEH_Warning(context, "Attempt to modify SFX %i. This will cause " - "problems in Vanilla dehacked.", sound_number); + deh_warning(context, + "Attempt to modify SFX %i. This will cause " + "problems in Vanilla dehacked.", + sound_number); } - return &S_sfx[sound_number]; + return &s_sfx[sound_number]; } -static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag) +static void deh_sound_parse_line(deh_context_t *context, char *line, + void *tag) { - sfxinfo_t *sfx; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; + sfxinfo_t *sfx; + char *variable_name; + char *value; + int ivalue; - sfx = (sfxinfo_t *) tag; + if (tag == NULL) return; - // Parse the assignment + sfx = (sfxinfo_t *)tag; - if (!DEH_ParseAssignment(line, &variable_name, &value)) + /* Parse the assignment */ + + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse - DEH_Warning(context, "Failed to parse assignment"); - return; + /* Failed to parse */ + + deh_warning(context, "Failed to parse assignment"); + return; } - - // all values are integers - ivalue = atoi(value); - - // Set the field value + /* all values are integers */ - DEH_SetMapping(context, &sound_mapping, sfx, variable_name, ivalue); -} + ivalue = atoi(value); -deh_section_t deh_section_sound = -{ - "Sound", - NULL, - DEH_SoundStart, - DEH_SoundParseLine, - NULL, - NULL, -}; + /* Set the field value */ + deh_set_mapping(context, &sound_mapping, sfx, variable_name, ivalue); +} diff --git a/games/NXDoom/src/doom/deh_thing.c b/games/NXDoom/src/doom/deh_thing.c index a6baff1d7d6..964b423b2cb 100644 --- a/games/NXDoom/src/doom/deh_thing.c +++ b/games/NXDoom/src/doom/deh_thing.c @@ -1,19 +1,27 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Thing" sections in dehacked files -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/deh_thing.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Parses "Thing" sections in dehacked files + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -26,106 +34,128 @@ #include "info.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t) - DEH_MAPPING("ID #", doomednum) - DEH_MAPPING("Initial frame", spawnstate) - DEH_MAPPING("Hit points", spawnhealth) - DEH_MAPPING("First moving frame", seestate) - DEH_MAPPING("Alert sound", seesound) - DEH_MAPPING("Reaction time", reactiontime) - DEH_MAPPING("Attack sound", attacksound) - DEH_MAPPING("Injury frame", painstate) - DEH_MAPPING("Pain chance", painchance) - DEH_MAPPING("Pain sound", painsound) - DEH_MAPPING("Close attack frame", meleestate) - DEH_MAPPING("Far attack frame", missilestate) - DEH_MAPPING("Death frame", deathstate) - DEH_MAPPING("Exploding frame", xdeathstate) - DEH_MAPPING("Death sound", deathsound) - DEH_MAPPING("Speed", speed) - DEH_MAPPING("Width", radius) - DEH_MAPPING("Height", height) - DEH_MAPPING("Mass", mass) - DEH_MAPPING("Missile damage", damage) - DEH_MAPPING("Action sound", activesound) - DEH_MAPPING("Bits", flags) - DEH_MAPPING("Respawn frame", raisestate) +DEH_MAPPING("Bits", flags) +DEH_MAPPING("Width", radius) +DEH_MAPPING("Height", height) +DEH_MAPPING("Mass", mass) +DEH_MAPPING("Speed", speed) +DEH_MAPPING("ID #", doomednum) +DEH_MAPPING("Hit points", spawnhealth) +DEH_MAPPING("Initial frame", spawnstate) +DEH_MAPPING("First moving frame", seestate) +DEH_MAPPING("Injury frame", painstate) +DEH_MAPPING("Pain chance", painchance) +DEH_MAPPING("Close attack frame", meleestate) +DEH_MAPPING("Far attack frame", missilestate) +DEH_MAPPING("Death frame", deathstate) +DEH_MAPPING("Exploding frame", xdeathstate) +DEH_MAPPING("Respawn frame", raisestate) +DEH_MAPPING("Missile damage", damage) +#ifdef CONFIG_GAMES_NXDOOM_SOUND +DEH_MAPPING("Reaction time", reactiontime) +DEH_MAPPING("Alert sound", seesound) +DEH_MAPPING("Attack sound", attacksound) +DEH_MAPPING("Pain sound", painsound) +DEH_MAPPING("Death sound", deathsound) +DEH_MAPPING("Action sound", activesound) +#endif DEH_END_MAPPING -static void *DEH_ThingStart(deh_context_t *context, char *line) +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_thing_start(deh_context_t *context, char *line); +static void deh_thing_parse_line(deh_context_t *context, char *line, + void *tag); +static void deh_thing_sha1_sum(SHA1_CTX *context); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_thing = +{ + "Thing", + NULL, + deh_thing_start, + deh_thing_parse_line, + NULL, + deh_thing_sha1_sum, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_thing_start(deh_context_t *context, char *line) { - int thing_number = 0; - mobjinfo_t *mobj; - - if (sscanf(line, "Thing %i", &thing_number) != 1) + int thing_number = 0; + mobjinfo_t *mobj; + + if (sscanf(line, "Thing %i", &thing_number) != 1) { - DEH_Warning(context, "Parse error on section start"); - return NULL; + deh_warning(context, "Parse error on section start"); + return NULL; } - // dehacked files are indexed from 1 - --thing_number; + /* dehacked files are indexed from 1 */ - if (thing_number < 0 || thing_number >= NUMMOBJTYPES) + --thing_number; + + if (thing_number < 0 || thing_number >= NUMMOBJTYPES) { - DEH_Warning(context, "Invalid thing number: %i", thing_number); - return NULL; + deh_warning(context, "Invalid thing number: %i", thing_number); + return NULL; } - - mobj = &mobjinfo[thing_number]; - - return mobj; + + mobj = &mobjinfo[thing_number]; + + return mobj; } -static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) +static void deh_thing_parse_line(deh_context_t *context, char *line, + void *tag) { - mobjinfo_t *mobj; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; + mobjinfo_t *mobj; + char *variable_name; + char *value; + int ivalue; - mobj = (mobjinfo_t *) tag; + if (tag == NULL) return; - // Parse the assignment + mobj = (mobjinfo_t *)tag; - if (!DEH_ParseAssignment(line, &variable_name, &value)) + /* Parse the assignment */ + + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse + /* Failed to parse */ - DEH_Warning(context, "Failed to parse assignment"); - return; + deh_warning(context, "Failed to parse assignment"); + return; } - -// printf("Set %s to %s for mobj\n", variable_name, value); - // all values are integers + /* all values are integers */ + + ivalue = atoi(value); - ivalue = atoi(value); - - // Set the field value + /* Set the field value */ - DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); + deh_set_mapping(context, &thing_mapping, mobj, variable_name, ivalue); } -static void DEH_ThingSHA1Sum(sha1_context_t *context) +static void deh_thing_sha1_sum(SHA1_CTX *context) { - int i; + int i; - for (i=0; i #include @@ -27,75 +35,97 @@ #include "deh_main.h" #include "deh_mapping.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t) - DEH_MAPPING("Ammo type", ammo) - DEH_MAPPING("Deselect frame", upstate) - DEH_MAPPING("Select frame", downstate) - DEH_MAPPING("Bobbing frame", readystate) - DEH_MAPPING("Shooting frame", atkstate) - DEH_MAPPING("Firing frame", flashstate) +DEH_MAPPING("Ammo type", ammo) +DEH_MAPPING("Deselect frame", upstate) +DEH_MAPPING("Select frame", downstate) +DEH_MAPPING("Bobbing frame", readystate) +DEH_MAPPING("Shooting frame", atkstate) +DEH_MAPPING("Firing frame", flashstate) DEH_END_MAPPING -static void *DEH_WeaponStart(deh_context_t *context, char *line) +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void *deh_weapon_start(deh_context_t *context, char *line); +static void deh_weapon_parse_line(deh_context_t *context, char *line, + void *tag); +static void deh_weapon_sha1_sum(SHA1_CTX *context); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +deh_section_t deh_section_weapon = { - int weapon_number = 0; + "Weapon", + NULL, + deh_weapon_start, + deh_weapon_parse_line, + NULL, + deh_weapon_sha1_sum, +}; - if (sscanf(line, "Weapon %i", &weapon_number) != 1) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void *deh_weapon_start(deh_context_t *context, char *line) +{ + int weapon_number = 0; + + if (sscanf(line, "Weapon %i", &weapon_number) != 1) { - DEH_Warning(context, "Parse error on section start"); - return NULL; + deh_warning(context, "Parse error on section start"); + return NULL; } - if (weapon_number < 0 || weapon_number >= NUMWEAPONS) + if (weapon_number < 0 || weapon_number >= NUMWEAPONS) { - DEH_Warning(context, "Invalid weapon number: %i", weapon_number); - return NULL; + deh_warning(context, "Invalid weapon number: %i", weapon_number); + return NULL; } - - return &weaponinfo[weapon_number]; + + return &weaponinfo[weapon_number]; } -static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) +static void deh_weapon_parse_line(deh_context_t *context, char *line, + void *tag) { - char *variable_name, *value; - weaponinfo_t *weapon; - int ivalue; - - if (tag == NULL) - return; + char *variable_name; + char *value; + weaponinfo_t *weapon; + int ivalue; - weapon = (weaponinfo_t *) tag; + if (tag == NULL) return; - if (!DEH_ParseAssignment(line, &variable_name, &value)) + weapon = (weaponinfo_t *)tag; + + if (!deh_parse_assignment(line, &variable_name, &value)) { - // Failed to parse + /* Failed to parse */ - DEH_Warning(context, "Failed to parse assignment"); - return; + deh_warning(context, "Failed to parse assignment"); + return; } - ivalue = atoi(value); + ivalue = atoi(value); - DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); + deh_set_mapping(context, &weapon_mapping, weapon, variable_name, ivalue); } -static void DEH_WeaponSHA1Sum(sha1_context_t *context) +static void deh_weapon_sha1_sum(SHA1_CTX *context) { - int i; + int i; - for (i=0; i #include +#include "d_mode.h" #include "doomtype.h" #include "i_timer.h" -#include "d_mode.h" -// -// Global parameters/defines. -// -// DOOM version +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* DOOM version */ + #define DOOM_VERSION 109 -// Version code for cph's longtics hack ("v1.91") -#define DOOM_191_VERSION 111 +/* Version code for cph's longtics hack ("v1.91") */ +#define DOOM_191_VERSION 111 -// If rangecheck is undefined, -// most parameter validation debugging code will not be compiled -#define RANGECHECK +/* The maximum number of players, multiplayer/networking. */ -// The maximum number of players, multiplayer/networking. #define MAXPLAYERS 4 -// The current state of the game: whether we are -// playing, gazing at the intermission screen, -// the game final animation, or a demo. +/* Difficulty/skill settings/filters. */ + +/* Skill flags. */ + +#define MTF_EASY 1 +#define MTF_NORMAL 2 +#define MTF_HARD 4 + +/* Deaf monsters/do not react to sound. */ + +#define MTF_AMBUSH 8 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The current state of the game: whether we are playing, gazing at the + * intermission screen, the game final animation, or a demo. + */ + typedef enum { - GS_LEVEL, - GS_INTERMISSION, - GS_FINALE, - GS_DEMOSCREEN, + GS_LEVEL, + GS_INTERMISSION, + GS_FINALE, + GS_DEMOSCREEN, } gamestate_t; typedef enum { - ga_nothing, - ga_loadlevel, - ga_newgame, - ga_loadgame, - ga_savegame, - ga_playdemo, - ga_completed, - ga_victory, - ga_worlddone, - ga_screenshot + ga_nothing, + ga_loadlevel, + ga_newgame, + ga_loadgame, + ga_savegame, + ga_playdemo, + ga_completed, + ga_victory, + ga_worlddone, + ga_screenshot } gameaction_t; -// -// Difficulty/skill settings/filters. -// - -// Skill flags. -#define MTF_EASY 1 -#define MTF_NORMAL 2 -#define MTF_HARD 4 - -// Deaf monsters/do not react to sound. -#define MTF_AMBUSH 8 - +/* Key cards. */ -// -// Key cards. -// typedef enum { - it_bluecard, - it_yellowcard, - it_redcard, - it_blueskull, - it_yellowskull, - it_redskull, - - NUMCARDS - + it_bluecard, + it_yellowcard, + it_redcard, + it_blueskull, + it_yellowskull, + it_redskull, + + NUMCARDS } card_t; +/* The defined weapons, including a marker indicating user has not changed + * weapon. + */ - -// The defined weapons, -// including a marker indicating -// user has not changed weapon. typedef enum { - wp_fist, - wp_pistol, - wp_shotgun, - wp_chaingun, - wp_missile, - wp_plasma, - wp_bfg, - wp_chainsaw, - wp_supershotgun, - - NUMWEAPONS, - - // No pending weapon change. - wp_nochange + wp_fist, + wp_pistol, + wp_shotgun, + wp_chaingun, + wp_missile, + wp_plasma, + wp_bfg, + wp_chainsaw, + wp_supershotgun, + + NUMWEAPONS, + + /* No pending weapon change. */ + wp_nochange } weapontype_t; +/* Ammunition types defined. */ -// Ammunition types defined. typedef enum { - am_clip, // Pistol / chaingun ammo. - am_shell, // Shotgun / double barreled shotgun. - am_cell, // Plasma rifle, BFG. - am_misl, // Missile launcher. - NUMAMMO, - am_noammo // Unlimited for chainsaw / fist. - + am_clip, /* Pistol / chaingun ammo. */ + am_shell, /* Shotgun / double barreled shotgun. */ + am_cell, /* Plasma rifle, BFG. */ + am_misl, /* Missile launcher. */ + NUMAMMO, + am_noammo /* Unlimited for chainsaw / fist. */ } ammotype_t; +/* Power up artifacts. */ -// Power up artifacts. typedef enum { - pw_invulnerability, - pw_strength, - pw_invisibility, - pw_ironfeet, - pw_allmap, - pw_infrared, - NUMPOWERS - + pw_invulnerability, + pw_strength, + pw_invisibility, + pw_ironfeet, + pw_allmap, + pw_infrared, + NUMPOWERS } powertype_t; +/* Power up durations, how many seconds till expiration, assuming TICRATE is + * 35 ticks/second. + */ - -// -// Power up durations, -// how many seconds till expiration, -// assuming TICRATE is 35 ticks/second. -// typedef enum { - INVULNTICS = (30*TICRATE), - INVISTICS = (60*TICRATE), - INFRATICS = (120*TICRATE), - IRONTICS = (60*TICRATE) - + INVULNTICS = (30 * TICRATE), + INVISTICS = (60 * TICRATE), + INFRATICS = (120 * TICRATE), + IRONTICS = (60 * TICRATE) } powerduration_t; -#endif // __DOOMDEF__ +#endif /* __DOOMDEF__ */ diff --git a/games/NXDoom/src/doom/doomstat.c b/games/NXDoom/src/doom/doomstat.c index f8e83f3cb93..5f38dd84ccf 100644 --- a/games/NXDoom/src/doom/doomstat.c +++ b/games/NXDoom/src/doom/doomstat.c @@ -1,35 +1,49 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Put all global tate variables here. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/doomstat.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Put all global state variables here. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include "doomstat.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Game Mode - identify IWAD as shareware, retail etc. -GameMode_t gamemode = indetermined; -GameMission_t gamemission = doom; -GameVersion_t gameversion = exe_final2; -GameVariant_t gamevariant = vanilla; - -// Set if homebrew PWAD stuff has been added. -boolean modifiedgame; +/* Game Mode - identify IWAD as shareware, retail etc. */ +game_mode_t gamemode = indetermined; +gamemission_t gamemission = doom; +game_version_t gameversion = exe_final2; +game_variant_t gamevariant = vanilla; +/* Set if homebrew PWAD stuff has been added. */ +boolean modifiedgame; +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/doom/doomstat.h b/games/NXDoom/src/doom/doomstat.h index 689f595035e..55f31f13047 100644 --- a/games/NXDoom/src/doom/doomstat.h +++ b/games/NXDoom/src/doom/doomstat.h @@ -1,277 +1,273 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// All the global variables that store the internal state. -// Theoretically speaking, the internal state of the engine -// should be found by looking at the variables collected -// here, and every relevant module will have to include -// this header file. -// In practice, things are a bit messy. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/doomstat.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * All the global variables that store the internal state. + * Theoretically speaking, the internal state of the engine + * should be found by looking at the variables collected + * here, and every relevant module will have to include + * this header file. + * In practice, things are a bit messy. + * + ****************************************************************************/ #ifndef __D_STATE__ #define __D_STATE__ -// We need globally shared data structures, -// for defining the global state variables. -#include "doomdata.h" -#include "d_loop.h" - -// We need the playr data structure as well. -#include "d_player.h" - -// Game mode/mission -#include "d_mode.h" - -#include "net_defs.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ +/* We need globally shared data structures, for defining the global state + * variables. + */ +#include "d_loop.h" +#include "doomdata.h" -// ------------------------ -// Command line parameters. -// -extern boolean nomonsters; // checkparm of -nomonsters -extern boolean respawnparm; // checkparm of -respawn -extern boolean fastparm; // checkparm of -fast +/* We need the player data structure as well. */ -extern boolean devparm; // DEBUG: launched with -devparm +#include "d_player.h" +/* Game mode/mission */ -// ----------------------------------------------------- -// Game Mode - identify IWAD as shareware, retail etc. -// -extern GameMode_t gamemode; -extern GameMission_t gamemission; -extern GameVersion_t gameversion; -extern GameVariant_t gamevariant; +#include "d_mode.h" -// Convenience macro. -// 'gamemission' can be equal to pack_chex or pack_hacx, but these are -// just modified versions of doom and doom2, and should be interpreted -// as the same most of the time. +#include "net_defs.h" -#define logical_gamemission \ - (gamemission == pack_chex ? doom : \ - gamemission == pack_hacx ? doom2 : gamemission) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Set if homebrew PWAD stuff has been added. -extern boolean modifiedgame; +/* Convenience macro. + * 'gamemission' can be equal to pack_chex or pack_hacx, but these are + * just modified versions of doom and doom2, and should be interpreted + * as the same most of the time. + */ +#define logical_gamemission \ + (gamemission == pack_chex ? doom \ + : gamemission == pack_hacx ? doom2 \ + : gamemission) -// ------------------------------------------- -// Selected skill type, map etc. -// +#define MAX_DM_STARTS 10 -// Defaults for menu, methinks. -extern skill_t startskill; -extern int startepisode; -extern int startmap; +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Savegame slot to load on startup. This is the value provided to -// the -loadgame option. If this has not been provided, this is -1. +/* Command line parameters. */ -extern int startloadgame; +extern boolean nomonsters; /* checkparm of -nomonsters */ +extern boolean respawnparm; /* checkparm of -respawn */ +extern boolean fastparm; /* checkparm of -fast */ -extern boolean autostart; +extern boolean devparm; /* DEBUG: launched with -devparm */ -// Selected by user. -extern skill_t gameskill; -extern int gameepisode; -extern int gamemap; +/* Game Mode - identify IWAD as shareware, retail etc. */ -// If non-zero, exit the level after this number of minutes -extern int timelimit; +extern game_mode_t gamemode; +extern gamemission_t gamemission; +extern game_version_t gameversion; +extern game_variant_t gamevariant; -// Nightmare mode flag, single player. -extern boolean respawnmonsters; +/* Set if homebrew PWAD stuff has been added. */ -// Netgame? Only true if >1 player. -extern boolean netgame; +extern boolean modifiedgame; -// 0=Cooperative; 1=Deathmatch; 2=Altdeath -extern int deathmatch; +/* Selected skill type, map etc. */ -// ------------------------- -// Internal parameters for sound rendering. -// These have been taken from the DOS version, -// but are not (yet) supported with Linux -// (e.g. no sound volume adjustment with menu. +/* Defaults for menu, methinks. */ -// From m_menu.c: -// Sound FX volume has default, 0 - 15 -// Music volume has default, 0 - 15 -// These are multiplied by 8. -extern int sfxVolume; -extern int musicVolume; +extern skill_t startskill; +extern int startepisode; +extern int startmap; -// Current music/sfx card - index useless -// w/o a reference LUT in a sound module. -// Ideally, this would use indices found -// in: /usr/include/linux/soundcard.h -extern int snd_MusicDevice; -extern int snd_SfxDevice; -// Config file? Same disclaimer as above. -extern int snd_DesiredMusicDevice; -extern int snd_DesiredSfxDevice; +/* Savegame slot to load on startup. This is the value provided to + * the -loadgame option. If this has not been provided, this is -1. + */ +extern int startloadgame; -// ------------------------- -// Status flags for refresh. -// +extern boolean autostart; -// Depending on view size - no status bar? -// Note that there is no way to disable the -// status bar explicitely. -extern boolean statusbaractive; +/* Selected by user. */ -extern boolean automapactive; // In AutoMap mode? -extern boolean menuactive; // Menu overlayed? -extern boolean paused; // Game Pause? +extern skill_t gameskill; +extern int gameepisode; +extern int gamemap; +/* If non-zero, exit the level after this number of minutes */ -extern boolean viewactive; +extern int timelimit; -extern boolean nodrawers; +/* Nightmare mode flag, single player. */ +extern boolean respawnmonsters; -extern boolean testcontrols; -extern int testcontrols_mousespeed; +/* Netgame? Only true if >1 player. */ +extern boolean netgame; +/* 0=Cooperative; 1=Deathmatch; 2=Altdeath */ +extern int deathmatch; -// This one is related to the 3-screen display mode. -// ANG90 = left side, ANG270 = right -extern int viewangleoffset; +/* Internal parameters for sound rendering. + * These have been taken from the DOS version, + * but are not (yet) supported with Linux + * (e.g. no sound volume adjustment with menu. + * From m_menu.c: + * Sound FX volume has default, 0 - 15 + * Music volume has default, 0 - 15 + * These are multiplied by 8. + */ -// Player taking events, and displaying. -extern int consoleplayer; -extern int displayplayer; +extern int g_sfx_volume; +extern int g_music_volume; +/* Status flags for refresh. */ -// ------------------------------------- -// Scores, rating. -// Statistics on a given map, for intermission. -// -extern int totalkills; -extern int totalitems; -extern int totalsecret; +/* Depending on view size - no status bar? + * Note that there is no way to disable the status bar explicitly. + */ -// Timer, for scores. -extern int levelstarttic; // gametic at level start -extern int leveltime; // tics in game play for par +extern boolean statusbaractive; +extern boolean automapactive; /* In AutoMap mode? */ +extern boolean g_menuactive; /* Menu over-layed? */ +extern boolean paused; /* Game Pause? */ +extern boolean viewactive; -// -------------------------------------- -// DEMO playback/recording related stuff. -// No demo, there is a human player in charge? -// Disable save/end game? -extern boolean usergame; +extern boolean nodrawers; -//? -extern boolean demoplayback; -extern boolean demorecording; +extern boolean testcontrols; +extern int testcontrols_mousespeed; -// Round angleturn in ticcmds to the nearest 256. This is used when -// recording Vanilla demos in netgames. +/* This one is related to the 3-screen display mode. + * ANG90 = left side, ANG270 = right + */ -extern boolean lowres_turn; +extern int viewangleoffset; -// Quit after playing a demo from cmdline. -extern boolean singledemo; +/* Player taking events, and displaying. */ +extern int consoleplayer; +extern int displayplayer; +/* Scores, rating. + * Statistics on a given map, for intermission. + */ +extern int totalkills; +extern int totalitems; +extern int totalsecret; -//? -extern gamestate_t gamestate; +/* Timer, for scores. */ +extern int levelstarttic; /* gametic at level start */ +extern int leveltime; /* tics in game play for par */ +/* DEMO playback/recording related stuff. + * No demo, there is a human player in charge? + * Disable save/end game? + */ +extern boolean usergame; +/* ? */ +extern boolean demoplayback; +extern boolean demorecording; -//----------------------------- -// Internal parameters, fixed. -// These are set by the engine, and not changed -// according to user inputs. Partly load from -// WAD, partly set at startup time. +/* Round angleturn in ticcmds to the nearest 256. This is used when + * recording Vanilla demos in netgames. + */ +extern boolean lowres_turn; +/* Quit after playing a demo from cmdline. */ -// Bookkeeping on players - state. -extern player_t players[MAXPLAYERS]; +extern boolean singledemo; -// Alive? Disconnected? -extern boolean playeringame[MAXPLAYERS]; +/* ? */ +extern gamestate_t gamestate; -// Player spawn spots for deathmatch. -#define MAX_DM_STARTS 10 -extern mapthing_t deathmatchstarts[MAX_DM_STARTS]; -extern mapthing_t* deathmatch_p; +/* Internal parameters, fixed. + * These are set by the engine, and not changed + * according to user inputs. Partly load from + * WAD, partly set at startup time. + */ -// Player spawn spots. -extern mapthing_t playerstarts[MAXPLAYERS]; -extern boolean playerstartsingame[MAXPLAYERS]; -// Intermission stats. -// Parameters for world map / intermission. -extern wbstartstruct_t wminfo; +/* Bookkeeping on players - state. */ +extern player_t players[MAXPLAYERS]; +/* Alive? Disconnected? */ +extern boolean playeringame[MAXPLAYERS]; +/* Player spawn spots for deathmatch. */ +extern mapthing_t deathmatchstarts[MAX_DM_STARTS]; +extern mapthing_t *deathmatch_p; +/* Player spawn spots. */ -//----------------------------------------- -// Internal parameters, used for engine. -// +extern mapthing_t playerstarts[MAXPLAYERS]; +extern boolean playerstartsingame[MAXPLAYERS]; -// File handling stuff. -extern char *savegamedir; +/* Intermission stats. + * Parameters for world map / intermission. + */ -// if true, load all graphics at level load -extern boolean precache; +extern wbstartstruct_t wminfo; +/* Internal parameters, used for engine. */ -// wipegamestate can be set to -1 -// to force a wipe on the next draw -extern gamestate_t wipegamestate; +/* File handling stuff. */ -extern int mouseSensitivity; +extern char *savegamedir; -extern int bodyqueslot; +/* if true, load all graphics at level load */ +extern boolean precache; +/* wipegamestate can be set to -1 to force a wipe on the next draw */ -// Needed to store the number of the dummy sky flat. -// Used for rendering, -// as well as tracking projectiles etc. -extern int skyflatnum; +extern gamestate_t wipegamestate; +extern int g_mouse_sensitivity; +extern int bodyqueslot; -// Netgame stuff (buffers and pointers, i.e. indices). +/* Needed to store the number of the dummy sky flat. + * Used for rendering, as well as tracking projectiles etc. + */ +extern int skyflatnum; -extern int rndindex; +/* Netgame stuff (buffers and pointers, i.e. indices). */ -extern ticcmd_t *netcmds; +extern int rndindex; +extern ticcmd_t *netcmds; -#endif +#endif /* __D_STATE__ */ diff --git a/games/NXDoom/src/doom/dstrings.c b/games/NXDoom/src/doom/dstrings.c index 86433ab280f..514e8c40865 100644 --- a/games/NXDoom/src/doom/dstrings.c +++ b/games/NXDoom/src/doom/dstrings.c @@ -1,59 +1,57 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Globally defined strings. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/dstrings.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Globally defined strings. + * + ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "dstrings.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ + const char *doom1_endmsg[] = { - "are you sure you want to\nquit this great game?", - "please don't leave, there's more\ndemons to toast!", - "let's beat it -- this is turning\ninto a bloodbath!", - "i wouldn't leave if i were you.\ndos is much worse.", - "you're trying to say you like dos\nbetter than me, right?", - "don't leave yet -- there's a\ndemon around that corner!", - "ya know, next time you come in here\ni'm gonna toast ya.", - "go ahead and leave. see if i care.", + DOOM1_ENDMSG }; const char *doom2_endmsg[] = { - // QuitDOOM II messages - "are you sure you want to\nquit this great game?", - "you want to quit?\nthen, thou hast lost an eighth!", - "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!", - "get outta here and go back\nto your boring programs.", - "if i were your boss, i'd \n deathmatch ya in a minute!", - "look, bud. you leave now\nand you forfeit your body count!", - "just leave. when you come\nback, i'll be waiting with a bat.", - "you're lucky i don't smack\nyou for thinking about leaving.", + DOOM2_ENDMSG }; -#if 0 - -// UNUSED messages included in the source release +/* UNUSED messages included in the source release */ -char* endmsg[] = +#if 0 +char *endmsg[] = { - // DOOM1 + /* DOOM1 */ + QUITMSG, - // FinalDOOM? + + /* FinalDOOM? */ + "fuck you, pussy!\nget the fuck out!", "you quit and i'll jizz\nin your cystholes!", "if you leave, i'll make\nthe lord drink my jizz.", @@ -62,12 +60,12 @@ char* endmsg[] = "suck it down, asshole!\nyou're a fucking wimp!", "don't quit now! we're \nstill spending your money!", - // Internal debug. Different style, too. - "THIS IS NO MESSAGE!\nPage intentionally left blank." -}; + /* Internal debug. Different style, too. */ + "THIS IS NO MESSAGE!\nPage intentionally left blank.", +}; #endif - - - +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/doom/dstrings.h b/games/NXDoom/src/doom/dstrings.h index 81115792a29..b1330f66de2 100644 --- a/games/NXDoom/src/doom/dstrings.h +++ b/games/NXDoom/src/doom/dstrings.h @@ -1,41 +1,62 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: -// DOOM strings, by language. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/dstrings.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * DOOM strings, by language. + * + ****************************************************************************/ #ifndef __DSTRINGS__ #define __DSTRINGS__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include -// All important printed strings. +/* All important printed strings. */ +#if defined(CONFIG_GAMES_NXDOOM_LANG_EN) #include "d_englsh.h" +#elif defined(CONFIG_GAMES_NXDOOM_LANG_FR) +#include "d_french.h" +#else +#error "Unsupported language choice." +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Misc. other strings. -#define SAVEGAMENAME "doomsav" +/* Misc. other strings. */ +#define SAVEGAMENAME "doomsav" -// QuitDOOM messages -// 8 per each game type -#define NUM_QUITMESSAGES 8 +/* QuitDOOM messages; 8 per each game type */ + +#define NUM_QUITMESSAGES (8) + +/**************************************************************************** + * Public Data + ****************************************************************************/ extern const char *doom1_endmsg[]; extern const char *doom2_endmsg[]; - -#endif +#endif /* __DSTRINGS__ */ diff --git a/games/NXDoom/src/doom/f_finale.c b/games/NXDoom/src/doom/f_finale.c index 0acd6e398cc..a9d964affba 100644 --- a/games/NXDoom/src/doom/f_finale.c +++ b/games/NXDoom/src/doom/f_finale.c @@ -1,718 +1,769 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Game completion, final screen animation. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/f_finale.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Game completion, final screen animation. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include #include +#include #include -// Functions. +/* Functions. */ + #include "deh_main.h" -#include "i_system.h" #include "i_swap.h" -#include "z_zone.h" +#include "i_system.h" #include "v_video.h" #include "w_wad.h" +#include "z_zone.h" + +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* Data. */ -// Data. #include "d_main.h" #include "dstrings.h" -#include "sounds.h" #include "doomstat.h" #include "r_state.h" +#include "hu_stuff.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TEXTSPEED 3 +#define TEXTWAIT 250 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef enum { - F_STAGE_TEXT, - F_STAGE_ARTSCREEN, - F_STAGE_CAST, + F_STAGE_TEXT, + F_STAGE_ARTSCREEN, + F_STAGE_CAST, } finalestage_t; -// ? -//#include "doomstat.h" -//#include "r_local.h" -//#include "f_finale.h" +/* ? + * #include "doomstat.h" + * #include "r_local.h" + * #include "f_finale.h" + */ -// Stage of animation: -finalestage_t finalestage; +typedef struct +{ + gamemission_t mission; + int episode; + int level; + const char *background; + const char *text; +} textscreen_t; -unsigned int finalecount; +typedef struct +{ + const char *name; + mobjtype_t type; +} castinfo_t; -#define TEXTSPEED 3 -#define TEXTWAIT 250 +/**************************************************************************** + * Private Data + ****************************************************************************/ -typedef struct +static textscreen_t g_textscreens[] = { - GameMission_t mission; - int episode, level; - const char *background; - const char *text; -} textscreen_t; + {doom, 1, 8, "FLOOR4_8", E1TEXT}, + {doom, 2, 8, "SFLR6_1", E2TEXT}, + {doom, 3, 8, "MFLR8_4", E3TEXT}, + {doom, 4, 8, "MFLR8_3", E4TEXT}, + {doom2, 1, 6, "SLIME16", C1TEXT}, + {doom2, 1, 11, "RROCK14", C2TEXT}, + {doom2, 1, 20, "RROCK07", C3TEXT}, + {doom2, 1, 30, "RROCK17", C4TEXT}, + {doom2, 1, 15, "RROCK13", C5TEXT}, + {doom2, 1, 31, "RROCK19", C6TEXT}, + {pack_tnt, 1, 6, "SLIME16", T1TEXT}, + {pack_tnt, 1, 11, "RROCK14", T2TEXT}, + {pack_tnt, 1, 20, "RROCK07", T3TEXT}, + {pack_tnt, 1, 30, "RROCK17", T4TEXT}, + {pack_tnt, 1, 15, "RROCK13", T5TEXT}, + {pack_tnt, 1, 31, "RROCK19", T6TEXT}, + {pack_plut, 1, 6, "SLIME16", P1TEXT}, + {pack_plut, 1, 11, "RROCK14", P2TEXT}, + {pack_plut, 1, 20, "RROCK07", P3TEXT}, + {pack_plut, 1, 30, "RROCK17", P4TEXT}, + {pack_plut, 1, 15, "RROCK13", P5TEXT}, + {pack_plut, 1, 31, "RROCK19", P6TEXT}, +}; -static textscreen_t textscreens[] = +/* Final DOOM 2 animation + * Casting by id Software. in order of appearance + */ + +static castinfo_t g_castorder[] = { - { doom, 1, 8, "FLOOR4_8", E1TEXT}, - { doom, 2, 8, "SFLR6_1", E2TEXT}, - { doom, 3, 8, "MFLR8_4", E3TEXT}, - { doom, 4, 8, "MFLR8_3", E4TEXT}, - - { doom2, 1, 6, "SLIME16", C1TEXT}, - { doom2, 1, 11, "RROCK14", C2TEXT}, - { doom2, 1, 20, "RROCK07", C3TEXT}, - { doom2, 1, 30, "RROCK17", C4TEXT}, - { doom2, 1, 15, "RROCK13", C5TEXT}, - { doom2, 1, 31, "RROCK19", C6TEXT}, - - { pack_tnt, 1, 6, "SLIME16", T1TEXT}, - { pack_tnt, 1, 11, "RROCK14", T2TEXT}, - { pack_tnt, 1, 20, "RROCK07", T3TEXT}, - { pack_tnt, 1, 30, "RROCK17", T4TEXT}, - { pack_tnt, 1, 15, "RROCK13", T5TEXT}, - { pack_tnt, 1, 31, "RROCK19", T6TEXT}, - - { pack_plut, 1, 6, "SLIME16", P1TEXT}, - { pack_plut, 1, 11, "RROCK14", P2TEXT}, - { pack_plut, 1, 20, "RROCK07", P3TEXT}, - { pack_plut, 1, 30, "RROCK17", P4TEXT}, - { pack_plut, 1, 15, "RROCK13", P5TEXT}, - { pack_plut, 1, 31, "RROCK19", P6TEXT}, + {CC_ZOMBIE, MT_POSSESSED}, + {CC_SHOTGUN, MT_SHOTGUY}, + {CC_HEAVY, MT_CHAINGUY}, + {CC_IMP, MT_TROOP}, + {CC_DEMON, MT_SERGEANT}, + {CC_LOST, MT_SKULL}, + {CC_CACO, MT_HEAD}, + {CC_HELL, MT_KNIGHT}, + {CC_BARON, MT_BRUISER}, + {CC_ARACH, MT_BABY}, + {CC_PAIN, MT_PAIN}, + {CC_REVEN, MT_UNDEAD}, + {CC_MANCU, MT_FATSO}, + {CC_ARCH, MT_VILE}, + {CC_SPIDER, MT_SPIDER}, + {CC_CYBER, MT_CYBORG}, + {CC_HERO, MT_PLAYER}, + {NULL, 0}, }; +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Stage of animation: */ + +finalestage_t finalestage; +unsigned int finalecount; + const char *finaletext; const char *finaleflat; -void F_StartCast (void); -void F_CastTicker (void); -boolean F_CastResponder (event_t *ev); -void F_CastDrawer (void); +int castnum; +int casttics; +state_t *caststate; +boolean castdeath; +int castframes; +int castonmelee; +boolean castattacking; -// -// F_StartFinale -// -void F_StartFinale (void) -{ - size_t i; +/**************************************************************************** + * Private Functions + ****************************************************************************/ - gameaction = ga_nothing; - gamestate = GS_FINALE; - viewactive = false; - automapactive = false; +static void f_start_cast(void) +{ + wipegamestate = -1; /* force a screen wipe */ + castnum = 0; + caststate = &states[mobjinfo[g_castorder[castnum].type].seestate]; + casttics = caststate->tics; + castdeath = false; + finalestage = F_STAGE_CAST; + castframes = 0; + castonmelee = 0; + castattacking = false; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_change_music(MUS_EVIL, true); +#endif +} - if (logical_gamemission == doom) - { - S_ChangeMusic(mus_victor, true); - } - else +static void f_text_write(void) +{ + byte *src; + pixel_t *dest; + int x; + int y; + int w; + signed int count; + const char *ch; + int c; + int cx; + int cy; + + /* erase the entire screen to a tiled background */ + + src = w_cache_lump_name(finaleflat, PU_CACHE); + dest = i_video_buffer; + + for (y = 0; y < SCREENHEIGHT; y++) { - S_ChangeMusic(mus_read_m, true); + for (x = 0; x < SCREENWIDTH / 64; x++) + { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + + if (SCREENWIDTH & 63) + { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } } - // Find the right screen and set the text and background + v_mark_rect(0, 0, SCREENWIDTH, SCREENHEIGHT); - for (i=0; imission == doom) + count = ((signed int)finalecount - 10) / TEXTSPEED; + if (count < 0) count = 0; + for (; count; count--) + { + c = *ch++; + if (!c) break; + if (c == '\n') { - screen->level = 5; + cx = 10; + cy += 11; + continue; } - if (logical_gamemission == screen->mission - && (logical_gamemission != doom || gameepisode == screen->episode) - && gamemap == screen->level) + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE) { - finaletext = screen->text; - finaleflat = screen->background; + cx += 4; + continue; } - } - // Do dehacked substitutions of strings - - finaletext = DEH_String(finaletext); - finaleflat = DEH_String(finaleflat); - - finalestage = F_STAGE_TEXT; - finalecount = 0; - + w = SHORT(hu_font[c]->width); + if (cx + w > SCREENWIDTH) break; + v_draw_patch(cx, cy, hu_font[c]); + cx += w; + } } +static void f_cast_ticker(void) +{ + int st; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + int sfx; +#endif + if (--casttics > 0) return; /* not time to change state yet */ -boolean F_Responder (event_t *event) -{ - if (finalestage == F_STAGE_CAST) - return F_CastResponder (event); - - return false; -} + if (caststate->tics == -1 || caststate->nextstate == S_NULL) + { + /* switch from deathstate to next monster */ + castnum++; + castdeath = false; + if (g_castorder[castnum].name == NULL) castnum = 0; -// -// F_Ticker -// -void F_Ticker (void) -{ - size_t i; - - // check for skipping - if ( (gamemode == commercial) - && ( finalecount > 50) ) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (mobjinfo[g_castorder[castnum].type].seesound) + { + s_start_sound(NULL, mobjinfo[g_castorder[castnum].type].seesound); + } + +#endif + + caststate = &states[mobjinfo[g_castorder[castnum].type].seestate]; + castframes = 0; + } + else { - // go on to the next level - for (i=0 ; inextstate; + caststate = &states[st]; + castframes++; + + /* sound hacks.... */ + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + switch (st) + { + case S_PLAY_ATK1: + sfx = SFX_DSHTGN; + break; + case S_POSS_ATK2: + sfx = SFX_PISTOL; + break; + case S_SPOS_ATK2: + sfx = SFX_SHOTGN; + break; + case S_VILE_ATK2: + sfx = SFX_VILATK; + break; + case S_SKEL_FIST2: + sfx = SFX_SKESWG; + break; + case S_SKEL_FIST4: + sfx = SFX_SKEPCH; + break; + case S_SKEL_MISS2: + sfx = SFX_SKEATK; + break; + case S_FATT_ATK8: + case S_FATT_ATK5: + case S_FATT_ATK2: + sfx = SFX_FIRSHT; + break; + case S_CPOS_ATK2: + case S_CPOS_ATK3: + case S_CPOS_ATK4: + sfx = SFX_SHOTGN; + break; + case S_TROO_ATK3: + sfx = SFX_CLAW; + break; + case S_SARG_ATK2: + sfx = SFX_SGTATK; + break; + case S_BOSS_ATK2: + case S_BOS2_ATK2: + case S_HEAD_ATK2: + sfx = SFX_FIRSHT; + break; + case S_SKULL_ATK2: + sfx = SFX_SKLATK; + break; + case S_SPID_ATK2: + case S_SPID_ATK3: + sfx = SFX_SHOTGN; + break; + case S_BSPI_ATK2: + sfx = SFX_PLASMA; + break; + case S_CYBER_ATK2: + case S_CYBER_ATK4: + case S_CYBER_ATK6: + sfx = SFX_RLAUNC; + break; + case S_PAIN_ATK3: + sfx = SFX_SKLATK; + break; + default: + sfx = 0; + break; + } + + if (sfx) s_start_sound(NULL, sfx); +#endif } - - // advance animation - finalecount++; - - if (finalestage == F_STAGE_CAST) + + if (castframes == 12) { - F_CastTicker (); - return; + /* go into attack frame */ + + castattacking = true; + + if (castonmelee) + { + caststate = + &states[mobjinfo[g_castorder[castnum].type].meleestate]; + } + else + { + caststate = + &states[mobjinfo[g_castorder[castnum].type].missilestate]; + } + + castonmelee ^= 1; + + if (caststate == &states[S_NULL]) + { + if (castonmelee) + { + caststate = + &states[mobjinfo[g_castorder[castnum].type].meleestate]; + } + else + { + caststate = + &states[mobjinfo[g_castorder[castnum].type].missilestate]; + } + } } - - if ( gamemode == commercial) - return; - - if (finalestage == F_STAGE_TEXT - && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT) + + if (castattacking) { - finalecount = 0; - finalestage = F_STAGE_ARTSCREEN; - wipegamestate = -1; // force a wipe - if (gameepisode == 3) - S_StartMusic (mus_bunny); + if (castframes == 24 || + caststate == &states[mobjinfo[g_castorder[castnum].type].seestate]) + { + stopattack: + castattacking = false; + castframes = 0; + caststate = &states[mobjinfo[g_castorder[castnum].type].seestate]; + } } + + casttics = caststate->tics; + if (casttics == -1) casttics = 15; } +static boolean f_cast_responder(event_t *ev) +{ + if (ev->type != ev_keydown) return false; + if (castdeath) return true; /* already in dying frames */ -// -// F_TextWrite -// + /* go into death frame */ -#include "hu_stuff.h" + castdeath = true; + caststate = &states[mobjinfo[g_castorder[castnum].type].deathstate]; + casttics = caststate->tics; + castframes = 0; + castattacking = false; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (mobjinfo[g_castorder[castnum].type].deathsound) + { + s_start_sound(NULL, mobjinfo[g_castorder[castnum].type].deathsound); + } +#endif -void F_TextWrite (void) + return true; +} + +static void f_cast_print(const char *text) { - byte* src; - pixel_t* dest; - - int x,y,w; - signed int count; - const char *ch; - int c; - int cx; - int cy; - - // erase the entire screen to a tiled background - src = W_CacheLumpName ( finaleflat , PU_CACHE); - dest = I_VideoBuffer; - - for (y=0 ; y= HU_FONTSIZE) + { + width += 4; + continue; + } + + w = SHORT(hu_font[c]->width); + width += w; } - V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); - - // draw some of the text onto the screen - cx = 10; - cy = 10; - ch = finaletext; - - count = ((signed int) finalecount - 10) / TEXTSPEED; - if (count < 0) - count = 0; - for ( ; count ; count-- ) + /* draw it */ + + cx = SCREENWIDTH / 2 - width / 2; + ch = text; + while (ch) { - c = *ch++; - if (!c) - break; - if (c == '\n') - { - cx = 10; - cy += 11; - continue; - } - - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - if (cx+w > SCREENWIDTH) - break; - V_DrawPatch(cx, cy, hu_font[c]); - cx+=w; + c = *ch++; + if (!c) break; + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE) + { + cx += 4; + continue; + } + + w = SHORT(hu_font[c]->width); + v_draw_patch(cx, 180, hu_font[c]); + cx += w; } - } -// -// Final DOOM 2 animation -// Casting by id Software. -// in order of appearance -// -typedef struct +static void f_cast_drawer(void) { - const char *name; - mobjtype_t type; -} castinfo_t; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + boolean flip; + patch_t *patch; -castinfo_t castorder[] = { - {CC_ZOMBIE, MT_POSSESSED}, - {CC_SHOTGUN, MT_SHOTGUY}, - {CC_HEAVY, MT_CHAINGUY}, - {CC_IMP, MT_TROOP}, - {CC_DEMON, MT_SERGEANT}, - {CC_LOST, MT_SKULL}, - {CC_CACO, MT_HEAD}, - {CC_HELL, MT_KNIGHT}, - {CC_BARON, MT_BRUISER}, - {CC_ARACH, MT_BABY}, - {CC_PAIN, MT_PAIN}, - {CC_REVEN, MT_UNDEAD}, - {CC_MANCU, MT_FATSO}, - {CC_ARCH, MT_VILE}, - {CC_SPIDER, MT_SPIDER}, - {CC_CYBER, MT_CYBORG}, - {CC_HERO, MT_PLAYER}, - - {NULL,0} -}; + /* erase the entire screen to a background */ -int castnum; -int casttics; -state_t* caststate; -boolean castdeath; -int castframes; -int castonmelee; -boolean castattacking; + v_draw_patch(0, 0, w_cache_lump_name(("BOSSBACK"), PU_CACHE)); + f_cast_print((g_castorder[castnum].name)); -// -// F_StartCast -// -void F_StartCast (void) -{ - wipegamestate = -1; // force a screen wipe - castnum = 0; - caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - casttics = caststate->tics; - castdeath = false; - finalestage = F_STAGE_CAST; - castframes = 0; - castonmelee = 0; - castattacking = false; - S_ChangeMusic(mus_evil, true); -} + /* draw the current frame in the middle of the screen */ + sprdef = &sprites[caststate->sprite]; + sprframe = &sprdef->spriteframes[caststate->frame & FF_FRAMEMASK]; + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; -// -// F_CastTicker -// -void F_CastTicker (void) + patch = w_cache_lump_num(lump + firstspritelump, PU_CACHE); + if (flip) + v_draw_patch_flipped(SCREENWIDTH / 2, 170, patch); + else + v_draw_patch(SCREENWIDTH / 2, 170, patch); +} + +static void f_draw_patch_col(int x, patch_t *patch, int col) { - int st; - int sfx; - - if (--casttics > 0) - return; // not time to change state yet - - if (caststate->tics == -1 || caststate->nextstate == S_NULL) - { - // switch from deathstate to next monster - castnum++; - castdeath = false; - if (castorder[castnum].name == NULL) - castnum = 0; - if (mobjinfo[castorder[castnum].type].seesound) - S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound); - caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - castframes = 0; - } - else - { - // just advance to next state in animation - if (caststate == &states[S_PLAY_ATK1]) - goto stopattack; // Oh, gross hack! - st = caststate->nextstate; - caststate = &states[st]; - castframes++; - - // sound hacks.... - switch (st) - { - case S_PLAY_ATK1: sfx = sfx_dshtgn; break; - case S_POSS_ATK2: sfx = sfx_pistol; break; - case S_SPOS_ATK2: sfx = sfx_shotgn; break; - case S_VILE_ATK2: sfx = sfx_vilatk; break; - case S_SKEL_FIST2: sfx = sfx_skeswg; break; - case S_SKEL_FIST4: sfx = sfx_skepch; break; - case S_SKEL_MISS2: sfx = sfx_skeatk; break; - case S_FATT_ATK8: - case S_FATT_ATK5: - case S_FATT_ATK2: sfx = sfx_firsht; break; - case S_CPOS_ATK2: - case S_CPOS_ATK3: - case S_CPOS_ATK4: sfx = sfx_shotgn; break; - case S_TROO_ATK3: sfx = sfx_claw; break; - case S_SARG_ATK2: sfx = sfx_sgtatk; break; - case S_BOSS_ATK2: - case S_BOS2_ATK2: - case S_HEAD_ATK2: sfx = sfx_firsht; break; - case S_SKULL_ATK2: sfx = sfx_sklatk; break; - case S_SPID_ATK2: - case S_SPID_ATK3: sfx = sfx_shotgn; break; - case S_BSPI_ATK2: sfx = sfx_plasma; break; - case S_CYBER_ATK2: - case S_CYBER_ATK4: - case S_CYBER_ATK6: sfx = sfx_rlaunc; break; - case S_PAIN_ATK3: sfx = sfx_sklatk; break; - default: sfx = 0; break; - } - - if (sfx) - S_StartSound (NULL, sfx); - } - - if (castframes == 12) - { - // go into attack frame - castattacking = true; - if (castonmelee) - caststate=&states[mobjinfo[castorder[castnum].type].meleestate]; - else - caststate=&states[mobjinfo[castorder[castnum].type].missilestate]; - castonmelee ^= 1; - if (caststate == &states[S_NULL]) - { - if (castonmelee) - caststate= - &states[mobjinfo[castorder[castnum].type].meleestate]; - else - caststate= - &states[mobjinfo[castorder[castnum].type].missilestate]; - } - } - - if (castattacking) + column_t *column; + byte *source; + pixel_t *dest; + pixel_t *desttop; + int count; + + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); + desttop = i_video_buffer + x; + + /* step through the posts in a column */ + + while (column->topdelta != 0xff) { - if (castframes == 24 - || caststate == &states[mobjinfo[castorder[castnum].type].seestate] ) - { - stopattack: - castattacking = false; - castframes = 0; - caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - } + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; + + while (count--) + { + *dest = *source++; + dest += SCREENWIDTH; + } + + column = (column_t *)((byte *)column + column->length + 4); } - - casttics = caststate->tics; - if (casttics == -1) - casttics = 15; } +static void f_bunny_scroll(void) +{ + signed int scrolled; + int x; + patch_t *p1; + patch_t *p2; + char name[10]; + int stage; + static int laststage; -// -// F_CastResponder -// + p1 = w_cache_lump_name(("PFUB2"), PU_LEVEL); + p2 = w_cache_lump_name(("PFUB1"), PU_LEVEL); -boolean F_CastResponder (event_t* ev) -{ - if (ev->type != ev_keydown) - return false; - - if (castdeath) - return true; // already in dying frames - - // go into death frame - castdeath = true; - caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; - casttics = caststate->tics; - castframes = 0; - castattacking = false; - if (mobjinfo[castorder[castnum].type].deathsound) - S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound); - - return true; -} + v_mark_rect(0, 0, SCREENWIDTH, SCREENHEIGHT); + scrolled = (SCREENWIDTH - ((signed int)finalecount - 230) / 2); + if (scrolled > SCREENWIDTH) scrolled = SCREENWIDTH; + if (scrolled < 0) scrolled = 0; -void F_CastPrint (const char *text) -{ - const char *ch; - int c; - int cx; - int w; - int width; - - // find width - ch = text; - width = 0; - - while (ch) + for (x = 0; x < SCREENWIDTH; x++) { - c = *ch++; - if (!c) - break; - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE) - { - width += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - width += w; + if (x + scrolled < SCREENWIDTH) + f_draw_patch_col(x, p1, x + scrolled); + else + f_draw_patch_col(x, p2, x + scrolled - SCREENWIDTH); } - - // draw it - cx = SCREENWIDTH/2-width/2; - ch = text; - while (ch) + + if (finalecount < 1130) return; + if (finalecount < 1180) { - c = *ch++; - if (!c) - break; - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - V_DrawPatch(cx, 180, hu_font[c]); - cx+=w; + v_draw_patch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, + w_cache_lump_name(("END0"), PU_CACHE)); + laststage = 0; + return; } - -} - -// -// F_CastDrawer -// + stage = (finalecount - 1180) / 5; + if (stage > 6) stage = 6; + if (stage > laststage) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_PISTOL); +#endif + laststage = stage; + } -void F_CastDrawer (void) -{ - spritedef_t* sprdef; - spriteframe_t* sprframe; - int lump; - boolean flip; - patch_t* patch; - - // erase the entire screen to a background - V_DrawPatch (0, 0, W_CacheLumpName (DEH_String("BOSSBACK"), PU_CACHE)); - - F_CastPrint (DEH_String(castorder[castnum].name)); - - // draw the current frame in the middle of the screen - sprdef = &sprites[caststate->sprite]; - sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK]; - lump = sprframe->lump[0]; - flip = (boolean)sprframe->flip[0]; - - patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE); - if (flip) - V_DrawPatchFlipped(SCREENWIDTH/2, 170, patch); - else - V_DrawPatch(SCREENWIDTH/2, 170, patch); + snprintf(name, 10, "END%i", stage); + v_draw_patch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, + w_cache_lump_name(name, PU_CACHE)); } - -// -// F_DrawPatchCol -// -void -F_DrawPatchCol -( int x, - patch_t* patch, - int col ) +static void f_art_screen_drawer(void) { - column_t* column; - byte* source; - pixel_t* dest; - pixel_t* desttop; - int count; - - column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); - desttop = I_VideoBuffer + x; - - // step through the posts in a column - while (column->topdelta != 0xff ) + const char *lumpname; + + if (gameepisode == 3) { - source = (byte *)column + 3; - dest = desttop + column->topdelta*SCREENWIDTH; - count = column->length; - - while (count--) - { - *dest = *source++; - dest += SCREENWIDTH; - } - column = (column_t *)( (byte *)column + column->length + 4 ); + f_bunny_scroll(); + } + else + { + switch (gameepisode) + { + case 1: + if (gameversion >= exe_ultimate) + { + lumpname = "CREDIT"; + } + else + { + lumpname = "HELP2"; + } + break; + case 2: + lumpname = "VICTORY2"; + break; + case 4: + lumpname = "ENDPIC"; + break; + default: + return; + } + + lumpname = (lumpname); + + v_draw_patch(0, 0, w_cache_lump_name(lumpname, PU_CACHE)); } } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -// F_BunnyScroll -// -void F_BunnyScroll (void) +/* f_start_finale */ + +void f_start_finale(void) { - signed int scrolled; - int x; - patch_t* p1; - patch_t* p2; - char name[10]; - int stage; - static int laststage; - - p1 = W_CacheLumpName (DEH_String("PFUB2"), PU_LEVEL); - p2 = W_CacheLumpName (DEH_String("PFUB1"), PU_LEVEL); - - V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); - - scrolled = (SCREENWIDTH - ((signed int) finalecount-230)/2); - if (scrolled > SCREENWIDTH) - scrolled = SCREENWIDTH; - if (scrolled < 0) - scrolled = 0; - - for ( x=0 ; x 6) - stage = 6; - if (stage > laststage) +#endif + + /* Find the right screen and set the text and background */ + + for (i = 0; i < arrlen(g_textscreens); ++i) { - S_StartSound (NULL, sfx_pistol); - laststage = stage; + textscreen_t *screen = &g_textscreens[i]; + + /* Hack for Chex Quest */ + + if (gameversion == exe_chex && screen->mission == doom) + { + screen->level = 5; + } + + if (logical_gamemission == screen->mission && + (logical_gamemission != doom || gameepisode == screen->episode) && + gamemap == screen->level) + { + finaletext = screen->text; + finaleflat = screen->background; + } } - - DEH_snprintf(name, 10, "END%i", stage); - V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, - (SCREENHEIGHT - 8 * 8) / 2, - W_CacheLumpName (name,PU_CACHE)); + + /* Do dehacked substitutions of strings */ + + finaletext = (finaletext); + finaleflat = (finaleflat); + + finalestage = F_STAGE_TEXT; + finalecount = 0; } -static void F_ArtScreenDrawer(void) +boolean f_responder(event_t *event) { - const char *lumpname; - - if (gameepisode == 3) - { - F_BunnyScroll(); - } - else + if (finalestage == F_STAGE_CAST) return f_cast_responder(event); + + return false; +} + +void f_ticker(void) +{ + size_t i; + + /* check for skipping */ + + if ((gamemode == commercial) && (finalecount > 50)) { - switch (gameepisode) + /* go on to the next level */ + + for (i = 0; i < MAXPLAYERS; i++) { - case 1: - if (gameversion >= exe_ultimate) - { - lumpname = "CREDIT"; - } - else - { - lumpname = "HELP2"; - } - break; - case 2: - lumpname = "VICTORY2"; - break; - case 4: - lumpname = "ENDPIC"; - break; - default: - return; + if (players[i].cmd.buttons) break; } - lumpname = DEH_String(lumpname); + if (i < MAXPLAYERS) + { + if (gamemap == 30) + f_start_cast(); + else + gameaction = ga_worlddone; + } + } + + /* advance animation */ + + finalecount++; + + if (finalestage == F_STAGE_CAST) + { + f_cast_ticker(); + return; + } + + if (gamemode == commercial) return; - V_DrawPatch (0, 0, W_CacheLumpName(lumpname, PU_CACHE)); + if (finalestage == F_STAGE_TEXT && + finalecount > strlen(finaletext) * TEXTSPEED + TEXTWAIT) + { + finalecount = 0; + finalestage = F_STAGE_ARTSCREEN; + wipegamestate = -1; /* force a wipe */ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameepisode == 3) s_start_music(MUS_BUNNY); +#endif } } -// -// F_Drawer -// -void F_Drawer (void) +void f_drawer(void) { - switch (finalestage) + switch (finalestage) { - case F_STAGE_CAST: - F_CastDrawer(); - break; - case F_STAGE_TEXT: - F_TextWrite(); - break; - case F_STAGE_ARTSCREEN: - F_ArtScreenDrawer(); - break; + case F_STAGE_CAST: + f_cast_drawer(); + break; + case F_STAGE_TEXT: + f_text_write(); + break; + case F_STAGE_ARTSCREEN: + f_art_screen_drawer(); + break; } } - - diff --git a/games/NXDoom/src/doom/f_finale.h b/games/NXDoom/src/doom/f_finale.h index daa71c32a3e..3e60e15a7e2 100644 --- a/games/NXDoom/src/doom/f_finale.h +++ b/games/NXDoom/src/doom/f_finale.h @@ -1,45 +1,49 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/f_finale.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ #ifndef __F_FINALE__ #define __F_FINALE__ +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include "doomtype.h" #include "d_event.h" -// -// FINALE -// +#include "doomtype.h" -// Called by main loop. -boolean F_Responder (event_t* ev); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Called by main loop. -void F_Ticker (void); +/* Called by main loop. */ -// Called by main loop. -void F_Drawer (void); +boolean f_responder(event_t *ev); +/* Called by main loop. */ -void F_StartFinale (void); +void f_ticker(void); +/* Called by main loop. */ +void f_drawer(void); +void f_start_finale(void); -#endif +#endif /* __F_FINALE__ */ diff --git a/games/NXDoom/src/doom/f_wipe.c b/games/NXDoom/src/doom/f_wipe.c index 0fa7754dd58..e10a0bd21eb 100644 --- a/games/NXDoom/src/doom/f_wipe.c +++ b/games/NXDoom/src/doom/f_wipe.c @@ -1,294 +1,296 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Mission begin melt/wipe screen special effect. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/f_wipe.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Mission begin melt/wipe screen special effect. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include -#include "z_zone.h" #include "i_video.h" -#include "v_video.h" #include "m_random.h" +#include "v_video.h" +#include "z_zone.h" #include "doomtype.h" #include "f_wipe.h" -// -// SCREEN WIPE PACKAGE -// +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ -// when zero, stop the wipe -static boolean go = 0; +static void wipe_shitty_col_major_xform(dpixel_t *array, int width, + int height); +static int wip_init_colour_xform(int width, int height, int ticks); +static int wipe_do_colour_xform(int width, int height, int ticks); +static int wip_exit_color_xform(int width, int height, int ticks); +static int wipe_init_melt(int width, int height, int ticks); +static int wipe_do_melt(int width, int height, int ticks); +static int wipe_exit_melt(int width, int height, int ticks); -static pixel_t* wipe_scr_start; -static pixel_t* wipe_scr_end; -static pixel_t* wipe_scr; +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* when zero, stop the wipe */ -void -wipe_shittyColMajorXform -( dpixel_t* array, - int width, - int height ) +static boolean go = 0; + +static pixel_t *wipe_scr_start; +static pixel_t *wipe_scr_end; +static pixel_t *wipe_scr; + +static int *g_y; + +static int (*g_wipes[])(int, int, int) = { - int x; - int y; - dpixel_t* dest; + wip_init_colour_xform, wipe_do_colour_xform, wip_exit_color_xform, + wipe_init_melt, wipe_do_melt, wipe_exit_melt, +}; - dest = (dpixel_t*) Z_Malloc(width*height*sizeof(*dest), PU_STATIC, 0); +/**************************************************************************** + * Private Functions + ****************************************************************************/ - for(y=0;y *e) - { - newval = *w - ticks; - if (newval < *e) - *w = *e; - else - *w = newval; - changed = true; - } - else if (*w < *e) - { - newval = *w + ticks; - if (newval > *e) - *w = *e; - else - *w = newval; - changed = true; - } - } - w++; - e++; + if (*w != *e) + { + if (*w > *e) + { + newval = *w - ticks; + if (newval < *e) + *w = *e; + else + *w = newval; + changed = true; + } + else if (*w < *e) + { + newval = *w + ticks; + if (newval > *e) + *w = *e; + else + *w = newval; + changed = true; + } + } + + w++; + e++; } - return !changed; - + return !changed; } -int -wipe_exitColorXForm -( int width, - int height, - int ticks ) +static int wip_exit_color_xform(int width, int height, int ticks) { - return 0; + return 0; } +static int wipe_init_melt(int width, int height, int ticks) +{ + int i; + int r; + + /* copy start screen to main screen */ -static int* y; + memcpy(wipe_scr, wipe_scr_start, width * height * sizeof(*wipe_scr)); -int -wipe_initMelt -( int width, - int height, - int ticks ) -{ - int i, r; - - // copy start screen to main screen - memcpy(wipe_scr, wipe_scr_start, width*height*sizeof(*wipe_scr)); - - // makes this wipe faster (in theory) - // to have stuff in column-major format - wipe_shittyColMajorXform((dpixel_t*)wipe_scr_start, width/2, height); - wipe_shittyColMajorXform((dpixel_t*)wipe_scr_end, width/2, height); - - // setup initial column positions - // (y<0 => not ready to scroll yet) - y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0); - y[0] = -(M_Random()%16); - for (i=1;i not ready to scroll yet) + */ + + g_y = (int *)z_malloc(width * sizeof(int), PU_STATIC, 0); + g_y[0] = -(m_random() % 16); + for (i = 1; i < width; i++) { - r = (M_Random()%3) - 1; - y[i] = y[i-1] + r; - if (y[i] > 0) y[i] = 0; - else if (y[i] == -16) y[i] = -15; + r = (m_random() % 3) - 1; + g_y[i] = g_y[i - 1] + r; + if (g_y[i] > 0) + g_y[i] = 0; + else if (g_y[i] == -16) + g_y[i] = -15; } - return 0; + return 0; } -int -wipe_doMelt -( int width, - int height, - int ticks ) +static int wipe_do_melt(int width, int height, int ticks) { - int i; - int j; - int dy; - int idx; - - dpixel_t* s; - dpixel_t* d; - boolean done = true; - - width/=2; - - while (ticks--) + int i; + int j; + int dy; + int idx; + + dpixel_t *s; + dpixel_t *d; + boolean done = true; + + width /= 2; + + while (ticks--) { - for (i=0;i= height) dy = height - y[i]; - s = &((dpixel_t *)wipe_scr_end)[i*height+y[i]]; - d = &((dpixel_t *)wipe_scr)[y[i]*width+i]; - idx = 0; - for (j=dy;j;j--) - { - d[idx] = *(s++); - idx += width; - } - y[i] += dy; - s = &((dpixel_t *)wipe_scr_start)[i*height]; - d = &((dpixel_t *)wipe_scr)[y[i]*width+i]; - idx = 0; - for (j=height-y[i];j;j--) - { - d[idx] = *(s++); - idx += width; - } - done = false; - } - } + for (i = 0; i < width; i++) + { + if (g_y[i] < 0) + { + g_y[i]++; + done = false; + } + else if (g_y[i] < height) + { + dy = (g_y[i] < 16) ? g_y[i] + 1 : 8; + if (g_y[i] + dy >= height) dy = height - g_y[i]; + s = &((dpixel_t *)wipe_scr_end)[i * height + g_y[i]]; + d = &((dpixel_t *)wipe_scr)[g_y[i] * width + i]; + idx = 0; + for (j = dy; j; j--) + { + d[idx] = *(s++); + idx += width; + } + + g_y[i] += dy; + s = &((dpixel_t *)wipe_scr_start)[i * height]; + d = &((dpixel_t *)wipe_scr)[g_y[i] * width + i]; + idx = 0; + for (j = height - g_y[i]; j; j--) + { + d[idx] = *(s++); + idx += width; + } + + done = false; + } + } } - return done; - + return done; } -int -wipe_exitMelt -( int width, - int height, - int ticks ) +static int wipe_exit_melt(int width, int height, int ticks) { - Z_Free(y); - Z_Free(wipe_scr_start); - Z_Free(wipe_scr_end); - return 0; + z_free(g_y); + z_free(wipe_scr_start); + z_free(wipe_scr_end); + return 0; } -int -wipe_StartScreen -( int x, - int y, - int width, - int height ) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int wipe_start_screen(int x, int y, int width, int height) { - wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_start), PU_STATIC, NULL); - I_ReadScreen(wipe_scr_start); - return 0; + wipe_scr_start = z_malloc( + SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_start), PU_STATIC, NULL); + i_read_screen(wipe_scr_start); + return 0; } -int -wipe_EndScreen -( int x, - int y, - int width, - int height ) +int wipe_endscreen(int x, int y, int width, int height) { - wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_end), PU_STATIC, NULL); - I_ReadScreen(wipe_scr_end); - V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr. - return 0; + wipe_scr_end = z_malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*wipe_scr_end), + PU_STATIC, NULL); + i_read_screen(wipe_scr_end); + v_draw_block(x, y, width, height, wipe_scr_start); /* restore start scr. */ + return 0; } -int -wipe_ScreenWipe -( int wipeno, - int x, - int y, - int width, - int height, - int ticks ) +int wipe_screen_wipe(int wipeno, int x, int y, int width, int height, + int ticks) { - int rc; - static int (*wipes[])(int, int, int) = - { - wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm, - wipe_initMelt, wipe_doMelt, wipe_exitMelt - }; + int rc; + + /* initial stuff */ - // initial stuff - if (!go) + if (!go) { - go = 1; - // wipe_scr = (pixel_t *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG - wipe_scr = I_VideoBuffer; - (*wipes[wipeno*3])(width, height, ticks); + go = 1; + wipe_scr = i_video_buffer; + (*g_wipes[wipeno * 3])(width, height, ticks); } - // do a piece of wipe-in - V_MarkRect(0, 0, width, height); - rc = (*wipes[wipeno*3+1])(width, height, ticks); - // V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG + /* do a piece of wipe-in */ - // final stuff - if (rc) + v_mark_rect(0, 0, width, height); + rc = (*g_wipes[wipeno * 3 + 1])(width, height, ticks); + + /* final stuff */ + + if (rc) { - go = 0; - (*wipes[wipeno*3+2])(width, height, ticks); + go = 0; + (*g_wipes[wipeno * 3 + 2])(width, height, ticks); } - return !go; + return !go; } - diff --git a/games/NXDoom/src/doom/f_wipe.h b/games/NXDoom/src/doom/f_wipe.h index f48a9ca6515..c421385a598 100644 --- a/games/NXDoom/src/doom/f_wipe.h +++ b/games/NXDoom/src/doom/f_wipe.h @@ -1,63 +1,53 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Mission start screen wipe/melt, special effects. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/f_wipe.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Mission start screen wipe/melt, special effects. + * + ****************************************************************************/ #ifndef __F_WIPE_H__ #define __F_WIPE_H__ -// -// SCREEN WIPE PACKAGE -// +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* SCREEN WIPE PACKAGE */ enum { - // simple gradual pixel change for 8-bit only - wipe_ColorXForm, - - // weird screen melt - wipe_Melt, + /* simple gradual pixel change for 8-bit only */ - wipe_NUMWIPES + WIPE_COLORXFORM, + WIPE_MELT, /* weird screen melt */ + WIPE_NUMWIPES }; -int -wipe_StartScreen -( int x, - int y, - int width, - int height ); - +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -int -wipe_EndScreen -( int x, - int y, - int width, - int height ); +int wipe_start_screen(int x, int y, int width, int height); +int wipe_endscreen(int x, int y, int width, int height); -int -wipe_ScreenWipe -( int wipeno, - int x, - int y, - int width, - int height, - int ticks ); +int wipe_screen_wipe(int wipeno, int x, int y, int width, int height, + int ticks); -#endif +#endif /* __F_WIPE_H__ */ diff --git a/games/NXDoom/src/doom/g_game.c b/games/NXDoom/src/doom/g_game.c index 4258712179a..03589f06b24 100644 --- a/games/NXDoom/src/doom/g_game.c +++ b/games/NXDoom/src/doom/g_game.c @@ -1,2408 +1,2462 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/g_game.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: none + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - -#include -#include #include +#include +#include -#include "doomdef.h" +#include "doomdef.h" #include "doomkeys.h" #include "doomstat.h" #include "deh_main.h" #include "deh_misc.h" -#include "z_zone.h" #include "f_finale.h" -#include "m_argv.h" -#include "m_controls.h" -#include "m_misc.h" -#include "m_menu.h" -#include "m_random.h" +#include "i_input.h" #include "i_joystick.h" +#include "i_swap.h" #include "i_system.h" #include "i_timer.h" -#include "i_input.h" -#include "i_swap.h" #include "i_video.h" +#include "m_argv.h" +#include "m_controls.h" +#include "m_menu.h" +#include "m_misc.h" +#include "m_random.h" +#include "z_zone.h" -#include "p_setup.h" #include "p_saveg.h" +#include "p_setup.h" #include "p_tick.h" #include "d_main.h" -#include "wi_stuff.h" +#include "am_map.h" #include "hu_stuff.h" #include "st_stuff.h" -#include "am_map.h" #include "statdump.h" +#include "wi_stuff.h" + +/* Needs access to LFB. */ -// Needs access to LFB. #include "v_video.h" #include "w_wad.h" -#include "p_local.h" +#include "p_local.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* Data. */ -// Data. #include "dstrings.h" -#include "sounds.h" -// SKY handling - still the wrong place. +/* SKY handling - still the wrong place. */ + #include "r_data.h" #include "r_sky.h" +#include "g_game.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#include "g_game.h" +#define SAVEGAMESIZE 0x2c000 + +#define MAXPLMOVE (forwardmove[1]) + +#define TURBOTHRESHOLD 0x32 + +#define BODYQUESIZE 32 + +#define SLOWTURNTICS 6 + +#define NUMKEYS 256 +#define MAX_JOY_BUTTONS 20 + +#define DEMOMARKER 0x80 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct weapon_order +{ + weapontype_t weapon; + weapontype_t weapon_num; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void p_spawn_player(mapthing_t *mthing); +void g_player_reborn(int player); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Gamestate the last time g_ticker was called. */ + +gamestate_t oldgamestate; + +gameaction_t gameaction; +gamestate_t gamestate; +skill_t gameskill; +boolean respawnmonsters; +int gameepisode; +int gamemap; + +/* If non-zero, exit the level after this number of minutes. */ + +int timelimit; + +boolean paused; +boolean sendpause; /* send a pause event next tic */ +boolean sendsave; /* send a save event next tic */ +boolean usergame; /* ok to save / end game */ + +boolean timingdemo; /* if true, exit with report on completion */ +boolean nodrawers; /* for comparative timing purposes */ +int starttime; /* for comparative timing purposes */ + +boolean viewactive; + +int deathmatch; /* only if started as net death */ +boolean netgame; /* only true if packets are broadcast */ +boolean playeringame[MAXPLAYERS]; +player_t players[MAXPLAYERS]; +boolean turbodetected[MAXPLAYERS]; -#define SAVEGAMESIZE 0x2c000 - -void G_ReadDemoTiccmd (ticcmd_t* cmd); -void G_WriteDemoTiccmd (ticcmd_t* cmd); -void G_PlayerReborn (int player); - -void G_DoReborn (int playernum); - -void G_DoLoadLevel (void); -void G_DoNewGame (void); -void G_DoPlayDemo (void); -void G_DoCompleted (void); -void G_DoVictory (void); -void G_DoWorldDone (void); -void G_DoSaveGame (void); - -// Gamestate the last time G_Ticker was called. - -gamestate_t oldgamestate; - -gameaction_t gameaction; -gamestate_t gamestate; -skill_t gameskill; -boolean respawnmonsters; -int gameepisode; -int gamemap; - -// If non-zero, exit the level after this number of minutes. - -int timelimit; - -boolean paused; -boolean sendpause; // send a pause event next tic -boolean sendsave; // send a save event next tic -boolean usergame; // ok to save / end game - -boolean timingdemo; // if true, exit with report on completion -boolean nodrawers; // for comparative timing purposes -int starttime; // for comparative timing purposes - -boolean viewactive; - -int deathmatch; // only if started as net death -boolean netgame; // only true if packets are broadcast -boolean playeringame[MAXPLAYERS]; -player_t players[MAXPLAYERS]; - -boolean turbodetected[MAXPLAYERS]; - -int consoleplayer; // player taking events and displaying -int displayplayer; // view being displayed -int levelstarttic; // gametic at level start -int totalkills, totalitems, totalsecret; // for intermission - -char *demoname; -boolean demorecording; -boolean longtics; // cph's doom 1.91 longtics hack -boolean lowres_turn; // low resolution turning for longtics -boolean demoplayback; -boolean netdemo; -byte* demobuffer; -byte* demo_p; -byte* demoend; -boolean singledemo; // quit after playing a demo from cmdline - -boolean precache = true; // if true, load all graphics at start - -boolean testcontrols = false; // Invoked by setup to test controls -int testcontrols_mousespeed; - - - -wbstartstruct_t wminfo; // parms for world map / intermission - -byte consistancy[MAXPLAYERS][BACKUPTICS]; - -#define MAXPLMOVE (forwardmove[1]) - -#define TURBOTHRESHOLD 0x32 - -fixed_t forwardmove[2] = {0x19, 0x32}; -fixed_t sidemove[2] = {0x18, 0x28}; -fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn - -static int *weapon_keys[] = { - &key_weapon1, - &key_weapon2, - &key_weapon3, - &key_weapon4, - &key_weapon5, - &key_weapon6, - &key_weapon7, - &key_weapon8 +int consoleplayer; /* player taking events and displaying */ +int displayplayer; /* view being displayed */ +int levelstarttic; /* gametic at level start */ +int totalkills; +int totalitems; +int totalsecret; /* for intermission */ + +char *demoname; +boolean demorecording; +boolean longtics; /* cph's doom 1.91 longtics hack */ +boolean lowres_turn; /* low resolution turning for longtics */ +boolean demoplayback; +boolean netdemo; +byte *demobuffer; +byte *demo_p; +byte *demoend; +boolean singledemo; /* quit after playing a demo from cmdline */ + +boolean precache = true; /* if true, load all graphics at start */ + +boolean testcontrols = false; /* Invoked by setup to test controls */ +int testcontrols_mousespeed; + +wbstartstruct_t wminfo; /* params for world map / intermission */ + +byte consistency[MAXPLAYERS][CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; + +fixed_t forwardmove[2] = +{ + 0x19, 0x32 }; -// Set to -1 or +1 to switch to the previous or next weapon. +fixed_t sidemove[2] = +{ + 0x18, 0x28 +}; + +/* + slow turn */ + +fixed_t angleturn[3] = +{ + 640, 1280, 320 +}; + +/* mouse values are used once */ + +int mousex; +int mousey; + +mobj_t *bodyque[BODYQUESIZE]; +int bodyqueslot; + +int vanilla_savegame_limit = 1; +int vanilla_demo_limit = 1; + +/* G_DoCompleted */ + +boolean secretexit; + +char savename[256]; + +skill_t d_skill; +int d_episode; +int d_map; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int *weapon_keys[] = +{ + &key_weapon1, &key_weapon2, &key_weapon3, &key_weapon4, + &key_weapon5, &key_weapon6, &key_weapon7, &key_weapon8, +}; + +/* Set to -1 or +1 to switch to the previous or next weapon. */ static int next_weapon = 0; -// Used for prev/next weapon keys. +/* Used for prev/next weapon keys. */ -static const struct +static const struct weapon_order weapon_order_table[] = { - weapontype_t weapon; - weapontype_t weapon_num; -} weapon_order_table[] = { - { wp_fist, wp_fist }, - { wp_chainsaw, wp_fist }, - { wp_pistol, wp_pistol }, - { wp_shotgun, wp_shotgun }, - { wp_supershotgun, wp_shotgun }, - { wp_chaingun, wp_chaingun }, - { wp_missile, wp_missile }, - { wp_plasma, wp_plasma }, - { wp_bfg, wp_bfg } + {wp_fist, wp_fist}, + {wp_chainsaw, wp_fist}, + {wp_pistol, wp_pistol}, + {wp_shotgun, wp_shotgun}, + {wp_supershotgun, wp_shotgun}, + {wp_chaingun, wp_chaingun}, + {wp_missile, wp_missile}, + {wp_plasma, wp_plasma}, + {wp_bfg, wp_bfg}, }; -#define SLOWTURNTICS 6 - -#define NUMKEYS 256 -#define MAX_JOY_BUTTONS 20 +static boolean gamekeydown[NUMKEYS]; +static int turnheld; /* for accelerative turning */ + +static boolean mousearray[MAX_MOUSE_BUTTONS + 1]; +static boolean *mousebuttons = &mousearray[1]; /* allow [-1] */ + +static int dclicktime; +static boolean dclickstate; +static int dclicks; +static int dclicktime2; +static boolean dclickstate2; +static int dclicks2; + +/* joystick values are repeated */ + +static int joyxmove; +static int joyymove; +static int joystrafemove; +static boolean joyarray[MAX_JOY_BUTTONS + 1]; +static boolean *joybuttons = &joyarray[1]; /* allow [-1] */ + +static int savegameslot; +static char savedescription[32]; + +/* DOOM Par Times */ + +static const int pars[4][10] = +{ + {0}, + {0, 30, 75, 120, 90, 165, 180, 180, 30, 165}, + {0, 90, 90, 90, 120, 90, 360, 240, 30, 170}, + {0, 90, 45, 90, 150, 90, 90, 165, 30, 135}, +}; + +/* DOOM II Par Times */ + +static const int cpars[32] = +{ + 30, 90, 120, 120, 90, 150, 120, 120, 270, 90, /* 1-10 */ + 210, 150, 150, 150, 210, 150, 420, 150, 210, 150, /* 11-20 */ + 240, 150, 180, 150, 150, 300, 330, 420, 300, 180, /* 21-30 */ + 120, 30, /* 31-32 */ +}; + +/* Chex Quest Par Times */ + +static const int chexpars[6] = +{ + 0, 120, 360, 480, 200, 360, +}; + +static const char *defdemoname; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static boolean weapon_selectable(weapontype_t weapon) +{ + /* Can't select the super shotgun in Doom 1. */ + + if (weapon == wp_supershotgun && logical_gamemission == doom) + { + return false; + } + + /* These weapons aren't available in shareware. */ + + if ((weapon == wp_plasma || weapon == wp_bfg) && gamemission == doom && + gamemode == shareware) + { + return false; + } + + /* Can't select a weapon if we don't own it. */ + + if (!players[consoleplayer].weaponowned[weapon]) + { + return false; + } + + /* Can't select the fist if we have the chainsaw, unless + * we also have the berserk pack. + */ + + if (weapon == wp_fist && players[consoleplayer].weaponowned[wp_chainsaw] && + !players[consoleplayer].powers[pw_strength]) + { + return false; + } + + return true; +} + +static int g_next_weapon(int direction) +{ + weapontype_t weapon; + int start_i; + int i; + + /* Find index in the table. */ + + if (players[consoleplayer].pendingweapon == wp_nochange) + { + weapon = players[consoleplayer].readyweapon; + } + else + { + weapon = players[consoleplayer].pendingweapon; + } + + for (i = 0; i < arrlen(weapon_order_table); ++i) + { + if (weapon_order_table[i].weapon == weapon) + { + break; + } + } + + /* The current weapon must be present in weapon_order_table + * otherwise something has gone terribly wrong + */ + + if (i >= arrlen(weapon_order_table)) + { + i_error("Internal error: weapon %d not present in weapon_order_table", + weapon); + } + + /* Switch weapon. Don't loop forever. */ + + start_i = i; + do + { + i += direction; + i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); + } + while (i != start_i && !weapon_selectable(weapon_order_table[i].weapon)); + + return weapon_order_table[i].weapon_num; +} + +static int g_cmd_checksum(ticcmd_t *cmd) +{ + size_t i; + int sum = 0; + + for (i = 0; i < sizeof(*cmd) / 4 - 1; i++) + sum += ((int *)cmd)[i]; + + return sum; +} + +static void g_do_load_level(void) +{ + int i; + + /* Set the sky map. + * First thing, we have a dummy sky texture name, + * a flat. The data is in the WAD only because + * we look for an actual index, instead of simply + * setting one. + */ + + skyflatnum = r_flat_num_for_name((SKYFLATNAME)); + + /* The "Sky never changes in Doom II" bug was fixed in + * the id Anthology version of doom2.exe for Final Doom. + */ + + if ((gamemode == commercial) && + (gameversion == exe_final2 || gameversion == exe_chex)) + { + const char *skytexturename; + + if (gamemap < 12) + { + skytexturename = "SKY1"; + } + else if (gamemap < 21) + { + skytexturename = "SKY2"; + } + else + { + skytexturename = "SKY3"; + } + + skytexturename = (skytexturename); + + skytexture = r_texture_num_for_name(skytexturename); + } + + levelstarttic = gametic; /* for time calculation */ + + if (wipegamestate == GS_LEVEL) wipegamestate = -1; /* force a wipe */ + + gamestate = GS_LEVEL; + + for (i = 0; i < MAXPLAYERS; i++) + { + turbodetected[i] = false; + if (playeringame[i] && players[i].playerstate == PST_DEAD) + players[i].playerstate = PST_REBORN; + memset(players[i].frags, 0, sizeof(players[i].frags)); + } + + p_setup_level(gameepisode, gamemap, 0, gameskill); + displayplayer = consoleplayer; /* view the guy you are playing */ + gameaction = ga_nothing; + z_check_heap(); + + /* clear cmd building stuff */ + + memset(gamekeydown, 0, sizeof(gamekeydown)); + joyxmove = joyymove = joystrafemove = 0; + mousex = mousey = 0; + sendpause = sendsave = paused = false; + memset(mousearray, 0, sizeof(mousearray)); + memset(joyarray, 0, sizeof(joyarray)); + + if (testcontrols) + { + players[consoleplayer].message = "Press escape to quit."; + } +} + +static void set_joy_buttons(unsigned int buttons_mask) +{ + int i; + + for (i = 0; i < MAX_JOY_BUTTONS; ++i) + { + int button_on = (buttons_mask & (1 << i)) != 0; + + /* Detect button press: */ + + if (!joybuttons[i] && button_on) + { + /* Weapon cycling: */ + + if (i == joybprevweapon) + { + next_weapon = -1; + } + else if (i == joybnextweapon) + { + next_weapon = 1; + } + } + + joybuttons[i] = button_on; + } +} + +static void set_mouse_buttons(unsigned int buttons_mask) +{ + int i; + + for (i = 0; i < MAX_MOUSE_BUTTONS; ++i) + { + unsigned int button_on = (buttons_mask & (1 << i)) != 0; + + /* Detect button press: */ + + if (!mousebuttons[i] && button_on) + { + if (i == mousebprevweapon) + { + next_weapon = -1; + } + else if (i == mousebnextweapon) + { + next_weapon = 1; + } + } + + mousebuttons[i] = button_on; + } +} + +/* g_check_spot + * Returns false if the player cannot be respawned + * at the given mapthing_t spot because something is occupying it + */ + +static boolean g_check_spot(int playernum, mapthing_t *mthing) +{ + fixed_t x; + fixed_t y; + subsector_t *ss; + mobj_t *mo; + int i; + + if (!players[playernum].mo) + { + /* first spawn of level, before corpses */ + + for (i = 0; i < playernum; i++) + { + if (players[i].mo->x == mthing->x << FRACBITS && + players[i].mo->y == mthing->y << FRACBITS) + { + return false; + } + } + + return true; + } + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + if (!p_check_position(players[playernum].mo, x, y)) return false; + + /* flush an old corpse if needed */ + + if (bodyqueslot >= BODYQUESIZE) + { + p_remove_mobj(bodyque[bodyqueslot % BODYQUESIZE]); + } + + bodyque[bodyqueslot % BODYQUESIZE] = players[playernum].mo; + bodyqueslot++; + + /* spawn a teleport fog */ + + ss = r_point_in_subsector(x, y); + + /* The code in the released source looks like this: + * + * an = ( ANG45 * (((unsigned int) mthing->angle)/45) ) + * >> ANGLETOFINESHIFT; + * mo = p_spawn_mobj (x+20*finecosine[an], y+20*finesine[an] + * , ss->sector->floorheight + * , MT_TFOG); + * + * But 'an' can be a signed value in the DOS version. This means that + * we get a negative index and the lookups into finecosine/finesine + * end up dereferencing values in finetangent[]. + * A player spawning on a deathmatch start facing directly west spawns + * "silently" with no spawn fog. Emulate this. + * + * This code is imported from PrBoom+. + */ + + fixed_t xa; + fixed_t ya; + signed int an; + + /* This calculation overflows in Vanilla Doom, but here we deliberately + * avoid integer overflow as it is undefined behavior, so the value of + * 'an' will always be positive. + */ + + an = (ANG45 >> ANGLETOFINESHIFT) * ((signed int)mthing->angle / 45); + + switch (an) + { + case 4096: /* -4096: */ + xa = finetangent[2048]; /* finecosine[-4096] */ + ya = finetangent[0]; /* finesine[-4096] */ + break; + case 5120: /* -3072: */ + xa = finetangent[3072]; /* finecosine[-3072] */ + ya = finetangent[1024]; /* finesine[-3072] */ + break; + case 6144: /* -2048: */ + xa = finesine[0]; /* finecosine[-2048] */ + ya = finetangent[2048]; /* finesine[-2048] */ + break; + case 7168: /* -1024: */ + xa = finesine[1024]; /* finecosine[-1024] */ + ya = finetangent[3072]; /* finesine[-1024] */ + break; + case 0: + case 1024: + case 2048: + case 3072: + xa = finecosine[an]; + ya = finesine[an]; + break; + case 8192: /* 360 deg: */ + xa = tantoangle[0]; /* finecosine[8192] */ + ya = finesine[8192]; /* finesine[8192] */ + break; + default: + i_error("g_check_spot: unexpected angle %d\n", an); + xa = ya = 0; + break; + } + + mo = p_spawn_mobj(x + 20 * xa, y + 20 * ya, ss->sector->floorheight, + MT_TFOG); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (players[consoleplayer].viewz != 1) + { + /* don't start sound on first frame */ + + s_start_sound(mo, SFX_TELEPT); + } +#else + UNUSED(mo); +#endif + + return true; +} + +static void g_do_reborn(int playernum) +{ + int i; + + if (!netgame) + { + /* reload the level from scratch */ -static boolean gamekeydown[NUMKEYS]; -static int turnheld; // for accelerative turning - -static boolean mousearray[MAX_MOUSE_BUTTONS + 1]; -static boolean *mousebuttons = &mousearray[1]; // allow [-1] - -// mouse values are used once -int mousex; -int mousey; - -static int dclicktime; -static boolean dclickstate; -static int dclicks; -static int dclicktime2; -static boolean dclickstate2; -static int dclicks2; - -// joystick values are repeated -static int joyxmove; -static int joyymove; -static int joystrafemove; -static boolean joyarray[MAX_JOY_BUTTONS + 1]; -static boolean *joybuttons = &joyarray[1]; // allow [-1] - -static int savegameslot; -static char savedescription[32]; - -#define BODYQUESIZE 32 - -mobj_t* bodyque[BODYQUESIZE]; -int bodyqueslot; - -int vanilla_savegame_limit = 1; -int vanilla_demo_limit = 1; - -int G_CmdChecksum (ticcmd_t* cmd) -{ - size_t i; - int sum = 0; - - for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++) - sum += ((int *)cmd)[i]; - - return sum; -} - -static boolean WeaponSelectable(weapontype_t weapon) + gameaction = ga_loadlevel; + } + else + { + /* respawn at the start first disassociate the corpse */ + + players[playernum].mo->player = NULL; + + /* spawn at random spot if in death match */ + + if (deathmatch) + { + g_death_match_spawn_player(playernum); + return; + } + + if (g_check_spot(playernum, &playerstarts[playernum])) + { + p_spawn_player(&playerstarts[playernum]); + return; + } + + /* try to spawn at one of the other players spots */ + + for (i = 0; i < MAXPLAYERS; i++) + { + if (g_check_spot(playernum, &playerstarts[i])) + { + playerstarts[i].type = playernum + 1; /* fake as other player */ + p_spawn_player(&playerstarts[i]); + playerstarts[i].type = i + 1; /* restore */ + return; + } + + /* he's going to be inside something. Too bad. */ + } + + p_spawn_player(&playerstarts[playernum]); + } +} + +static void g_do_new_game(void) +{ + demoplayback = false; + netdemo = false; + netgame = false; + deathmatch = false; + playeringame[1] = playeringame[2] = playeringame[3] = 0; + respawnparm = false; + fastparm = false; + nomonsters = false; + consoleplayer = 0; + g_init_new(d_skill, d_episode, d_map); + gameaction = ga_nothing; +} + +static void g_do_save_game(void) { - // Can't select the super shotgun in Doom 1. + char *savegame_file; + char *temp_savegame_file; + char *recovery_savegame_file; + + recovery_savegame_file = NULL; + temp_savegame_file = p_temp_save_game_file(); + savegame_file = p_save_game_file(savegameslot); + + /* Open the savegame file for writing. We write to a temporary file + * and then rename it at the end if it was successfully written. + * This prevents an existing savegame from being overwritten by + * a corrupted one, or if a savegame buffer overrun occurs. + */ - if (weapon == wp_supershotgun && logical_gamemission == doom) + save_stream = fopen(temp_savegame_file, "wb"); + + if (save_stream == NULL) { - return false; + /* Failed to save the game, so we're going to have to abort. But + * to be nice, save to somewhere else before we call i_error(). + */ + + recovery_savegame_file = m_temp_file("recovery.dsg"); + save_stream = fopen(recovery_savegame_file, "wb"); + if (save_stream == NULL) + { + i_error("Failed to open either '%s' or '%s' to write savegame.", + temp_savegame_file, recovery_savegame_file); + } } - // These weapons aren't available in shareware. + savegame_error = false; + + p_write_save_game_header(savedescription); + + p_archive_players(); + p_archive_world(); + p_archive_thinkers(); + p_archive_specials(); + + p_write_save_game_eof(); - if ((weapon == wp_plasma || weapon == wp_bfg) - && gamemission == doom && gamemode == shareware) + /* Enforce the same savegame size limit as in Vanilla Doom, + * except if the vanilla_savegame_limit setting is turned off. + */ + + if (vanilla_savegame_limit && ftell(save_stream) > SAVEGAMESIZE) { - return false; + i_error("Savegame buffer overrun"); } - // Can't select a weapon if we don't own it. + /* Finish up, close the savegame file. */ + + fclose(save_stream); - if (!players[consoleplayer].weaponowned[weapon]) + if (recovery_savegame_file != NULL) { - return false; + /* We failed to save to the normal location, but we wrote a + * recovery file to the temp directory. Now we can bomb out + * with an error. + */ + + i_error("Failed to open savegame file '%s' for writing.\n" + "But your game has been saved to '%s' for recovery.", + temp_savegame_file, recovery_savegame_file); } - // Can't select the fist if we have the chainsaw, unless - // we also have the berserk pack. + /* Now rename the temporary savegame file to the actual savegame + * file, overwriting the old savegame if there was one there. + */ + + remove(savegame_file); + rename(temp_savegame_file, savegame_file); - if (weapon == wp_fist - && players[consoleplayer].weaponowned[wp_chainsaw] - && !players[consoleplayer].powers[pw_strength]) + gameaction = ga_nothing; + m_str_copy(savedescription, "", sizeof(savedescription)); + + players[consoleplayer].message = (GGSAVED); + + /* draw the pattern into the back screen */ + + r_fill_back_screen(); +} + +/* Generate a string describing a demo version */ + +static const char *demo_version_description(int version) +{ + static char resultbuf[16]; + + switch (version) { - return false; + case 104: + return "v1.4"; + case 105: + return "v1.5"; + case 106: + return "v1.6/v1.666"; + case 107: + return "v1.7/v1.7a"; + case 108: + return "v1.8"; + case 109: + return "v1.9"; + case 111: + return "v1.91 hack demo?"; + default: + break; } - return true; + /* Unknown version. Perhaps this is a pre-v1.4 IWAD? If the version + * byte is in the range 0-4 then it can be a v1.0-v1.2 demo. + */ + + if (version >= 0 && version <= 4) + { + return "v1.0/v1.1/v1.2"; + } + else + { + snprintf(resultbuf, sizeof(resultbuf), "%i.%i (unknown)", + version / 100, version % 100); + return resultbuf; + } } -static int G_NextWeapon(int direction) +static void g_do_play_demo(void) { - weapontype_t weapon; - int start_i, i; + skill_t skill; + int i; + int lumpnum; + int episode; + int map; + int demoversion; + boolean olddemo = false; + + lumpnum = w_get_num_for_name(defdemoname); + gameaction = ga_nothing; + demobuffer = w_cache_lump_num(lumpnum, PU_STATIC); + demo_p = demobuffer; + + demoversion = *demo_p++; + + if (demoversion >= 0 && demoversion <= 4) + { + olddemo = true; + demo_p--; + } + + longtics = false; + + /* Longtics demos use the modified format that is generated by cph's + * hacked "v1.91" doom exe. This is a non-vanilla extension. + */ + + if (d_non_vanilla_playback(demoversion == DOOM_191_VERSION, lumpnum, + "Doom 1.91 demo format")) + { + longtics = true; + } + else if (demoversion != g_vanilla_version_code() && + !(gameversion <= exe_doom_1_2 && olddemo)) + { + const char *message = "Demo is from a different game version!\n" + "(read %i, should be %i)\n" + "\n" + "*** You may need to upgrade your version " + "of Doom to v1.9. ***\n" + " See: https://www.doomworld.com/classicdoom" + "/info/patches.php\n" + " This appears to be %s."; - // Find index in the table. + i_error(message, demoversion, g_vanilla_version_code(), + demo_version_description(demoversion)); + } + + skill = *demo_p++; + episode = *demo_p++; + map = *demo_p++; - if (players[consoleplayer].pendingweapon == wp_nochange) + if (!olddemo) { - weapon = players[consoleplayer].readyweapon; + deathmatch = *demo_p++; + respawnparm = *demo_p++; + fastparm = *demo_p++; + nomonsters = *demo_p++; + consoleplayer = *demo_p++; } - else + else { - weapon = players[consoleplayer].pendingweapon; + deathmatch = 0; + respawnparm = 0; + fastparm = 0; + nomonsters = 0; + consoleplayer = 0; } - for (i=0; i 0 || + m_check_parm("-netdemo") > 0) + { + netgame = true; + netdemo = true; + } + + /* don't spend a lot of time in loadlevel */ + + precache = false; + g_init_new(skill, episode, map); + precache = true; + starttime = i_get_time(); + + usergame = false; + demoplayback = true; +} + +/* g_playerfinishlevel + * Can when a player completes a level. + */ + +static void g_player_finish_level(int player) +{ + player_t *p; + + p = &players[player]; + + memset(p->powers, 0, sizeof(p->powers)); + memset(p->cards, 0, sizeof(p->cards)); + p->mo->flags &= ~MF_SHADOW; /* cancel invisibility */ + p->extralight = 0; /* cancel gun flashes */ + p->fixedcolormap = 0; /* cancel ir gogles */ + p->damagecount = 0; /* no palette changes */ + p->bonuscount = 0; +} + +static void g_do_completed(void) +{ + int i; + + gameaction = ga_nothing; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + g_player_finish_level(i); /* take away cards and stuff */ + } + } + + if (automapactive) am_stop(); + + if (gamemode != commercial) { - if (weapon_order_table[i].weapon == weapon) + /* Chex Quest ends after 5 levels, rather than 8. */ + + if (gameversion == exe_chex) + { + if (gamemap == 5) + { + gameaction = ga_victory; + return; + } + } + else { + switch (gamemap) + { + case 8: + gameaction = ga_victory; + return; + case 9: + for (i = 0; i < MAXPLAYERS; i++) + players[i].didsecret = true; + break; + } + } + } + + /* #if 0 Hmmm - why? */ + + if ((gamemap == 8) && (gamemode != commercial)) + { + /* victory */ + + gameaction = ga_victory; + return; + } + + if ((gamemap == 9) && (gamemode != commercial)) + { + /* exit secret level */ + + for (i = 0; i < MAXPLAYERS; i++) + players[i].didsecret = true; + } + + /* #endif */ + + wminfo.didsecret = players[consoleplayer].didsecret; + wminfo.epsd = gameepisode - 1; + wminfo.last = gamemap - 1; + + /* wminfo.next is 0 biased, unlike gamemap */ + + if (gamemode == commercial) + { + if (secretexit) switch (gamemap) + { + case 15: + wminfo.next = 30; + break; + case 31: + wminfo.next = 31; break; + } + else + switch (gamemap) + { + case 31: + case 32: + wminfo.next = 15; + break; + default: + wminfo.next = gamemap; + } + } + else + { + if (secretexit) + wminfo.next = 8; /* go to secret level */ + else if (gamemap == 9) + { + /* returning from secret level */ + + switch (gameepisode) + { + case 1: + wminfo.next = 3; + break; + case 2: + wminfo.next = 5; + break; + case 3: + wminfo.next = 6; + break; + case 4: + wminfo.next = 2; + break; + } + } + else + wminfo.next = gamemap; /* go to next level */ + } + + wminfo.maxkills = totalkills; + wminfo.maxitems = totalitems; + wminfo.maxsecret = totalsecret; + wminfo.maxfrags = 0; + + /* Set par time. Exceptions are added for purposes of + * statcheck regression testing. + */ + + if (gamemode == commercial) + { + /* map33 reads its par time from beyond the cpars[] array */ + + if (gamemap == 33) + { + int cpars32; + + memcpy(&cpars32, (GAMMALVL0), sizeof(int)); + cpars32 = LONG(cpars32); + + wminfo.partime = TICRATE * cpars32; + } + else + { + wminfo.partime = TICRATE * cpars[gamemap - 1]; + } + } + + /* Doom episode 4 doesn't have a par time, so this + * overflows into the cpars array. + */ + + else if (gameepisode < 4) + { + if (gameversion == exe_chex && gameepisode == 1 && gamemap < 6) + { + wminfo.partime = TICRATE * chexpars[gamemap]; + } + else + { + wminfo.partime = TICRATE * pars[gameepisode][gamemap]; + } + } + else + { + wminfo.partime = TICRATE * cpars[gamemap]; + } + + wminfo.pnum = consoleplayer; + + for (i = 0; i < MAXPLAYERS; i++) + { + wminfo.plyr[i].in = playeringame[i]; + wminfo.plyr[i].skills = players[i].killcount; + wminfo.plyr[i].sitems = players[i].itemcount; + wminfo.plyr[i].ssecret = players[i].secretcount; + wminfo.plyr[i].stime = leveltime; + memcpy(wminfo.plyr[i].frags, players[i].frags, + sizeof(wminfo.plyr[i].frags)); + } + + gamestate = GS_INTERMISSION; + viewactive = false; + automapactive = false; + + stat_copy(&wminfo); + + wi_start(&wminfo); +} + +static void g_do_world_done(void) +{ + gamestate = GS_LEVEL; + gamemap = wminfo.next + 1; + g_do_load_level(); + gameaction = ga_nothing; + viewactive = true; +} + +/* Increase the size of the demo buffer to allow unlimited demos */ + +static void increase_demo_buffer(void) +{ + int current_length; + byte *new_demobuffer; + byte *new_demop; + int new_length; + + /* Find the current size */ + + current_length = demoend - demobuffer; + + /* Generate a new buffer twice the size */ + + new_length = current_length * 2; + + new_demobuffer = z_malloc(new_length, PU_STATIC, 0); + new_demop = new_demobuffer + (demo_p - demobuffer); + + /* Copy over the old data */ + + memcpy(new_demobuffer, demobuffer, current_length); + + /* Free the old buffer and point the demo pointers at the new buffer. */ + + z_free(demobuffer); + + demobuffer = new_demobuffer; + demo_p = new_demop; + demoend = demobuffer + new_length; +} + +/* DEMO RECORDING */ + +static void g_read_demo_ticcmd(ticcmd_t *cmd) +{ + if (*demo_p == DEMOMARKER) + { + /* end of demo data stream */ + + g_check_demo_status(); + return; + } + + cmd->forwardmove = ((signed char)*demo_p++); + cmd->sidemove = ((signed char)*demo_p++); + + /* If this is a longtics demo, read back in higher resolution */ + + if (longtics) + { + cmd->angleturn = *demo_p++; + cmd->angleturn |= (*demo_p++) << 8; + } + else + { + cmd->angleturn = ((unsigned char)*demo_p++) << 8; + } + + cmd->buttons = (unsigned char)*demo_p++; +} + +static void g_write_demo_ticcmd(ticcmd_t *cmd) +{ + byte *demo_start; + + if (gamekeydown[key_demo_quit]) /* press q to end demo recording */ + g_check_demo_status(); + + demo_start = demo_p; + + *demo_p++ = cmd->forwardmove; + *demo_p++ = cmd->sidemove; + + /* If this is a longtics demo, record in higher resolution */ + + if (longtics) + { + *demo_p++ = (cmd->angleturn & 0xff); + *demo_p++ = (cmd->angleturn >> 8) & 0xff; + } + else + { + *demo_p++ = cmd->angleturn >> 8; + } + + *demo_p++ = cmd->buttons; + + /* reset demo pointer back */ + + demo_p = demo_start; + + if (demo_p > demoend - 16) + { + if (vanilla_demo_limit) + { + /* no more space */ + + g_check_demo_status(); + return; + } + else + { + /* Vanilla demo limit disabled: unlimited + * demo lengths! + */ + + increase_demo_buffer(); } } - // The current weapon must be present in weapon_order_table - // otherwise something has gone terribly wrong - if (i >= arrlen(weapon_order_table)) { - I_Error("Internal error: weapon %d not present in weapon_order_table", weapon); - } + g_read_demo_ticcmd(cmd); /* make SURE it is exactly the same */ +} + +/* Called at the start. + * Called by the game initialization functions. + */ + +static void g_init_player(int player) +{ + /* clear everything else to defaults */ + + g_player_reborn(player); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* g_build_ticcmd + * Builds a ticcmd from all of the available inputs + * or reads it from the demo buffer. + * If recording a demo, write it out + */ + +void g_build_ticcmd(ticcmd_t *cmd, int maketic) +{ + int i; + boolean strafe; + boolean bstrafe; + int speed; + int tspeed; + int forward; + int side; + + memset(cmd, 0, sizeof(ticcmd_t)); + + cmd->consistency = + consistency[consoleplayer] + [maketic % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; + + strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] || + joybuttons[joybstrafe]; + + /* fraggle: support the old "joyb_speed = 31" hack which + * allowed an autorun effect + */ + + speed = key_speed >= NUMKEYS || joybspeed >= MAX_JOY_BUTTONS || + gamekeydown[key_speed] || joybuttons[joybspeed] || + mousebuttons[mousebspeed]; + + forward = side = 0; + + /* use two stage accelerative turning + * on the keyboard and joystick + */ + + if (joyxmove < 0 || joyxmove > 0 || gamekeydown[key_right] || + gamekeydown[key_left] || mousebuttons[mousebturnright] || + mousebuttons[mousebturnleft]) + { + turnheld += ticdup; + } + else + { + turnheld = 0; + } + + if (turnheld < SLOWTURNTICS) + { + tspeed = 2; /* slow turn */ + } + else + { + tspeed = speed; + } + + /* let movement keys cancel each other out */ - // Switch weapon. Don't loop forever. - start_i = i; - do + if (strafe) { - i += direction; - i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); - } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon)); + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + { + side += sidemove[speed]; + } - return weapon_order_table[i].weapon_num; -} + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + { + side -= sidemove[speed]; + } -// -// G_BuildTiccmd -// Builds a ticcmd from all of the available inputs -// or reads it from the demo buffer. -// If recording a demo, write it out -// -void G_BuildTiccmd (ticcmd_t* cmd, int maketic) -{ - int i; - boolean strafe; - boolean bstrafe; - int speed; - int tspeed; - int forward; - int side; - - memset(cmd, 0, sizeof(ticcmd_t)); - - cmd->consistancy = - consistancy[consoleplayer][maketic%BACKUPTICS]; - - strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] - || joybuttons[joybstrafe]; - - // fraggle: support the old "joyb_speed = 31" hack which - // allowed an autorun effect - - speed = key_speed >= NUMKEYS - || joybspeed >= MAX_JOY_BUTTONS - || gamekeydown[key_speed] - || joybuttons[joybspeed] - || mousebuttons[mousebspeed]; - - forward = side = 0; - - // use two stage accelerative turning - // on the keyboard and joystick - if (joyxmove < 0 - || joyxmove > 0 - || gamekeydown[key_right] - || gamekeydown[key_left] - || mousebuttons[mousebturnright] - || mousebuttons[mousebturnleft]) - turnheld += ticdup; - else - turnheld = 0; - - if (turnheld < SLOWTURNTICS) - tspeed = 2; // slow turn - else - tspeed = speed; - - // let movement keys cancel each other out - if (strafe) - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - { - // fprintf(stderr, "strafe right\n"); - side += sidemove[speed]; - } - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - { - // fprintf(stderr, "strafe left\n"); - side -= sidemove[speed]; - } - if (use_analog && joyxmove) + if (use_analog && joyxmove) { - joyxmove = joyxmove * joystick_move_sensitivity / 10; - joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; - joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; - side += FixedMul(sidemove[speed], joyxmove); + joyxmove = joyxmove * joystick_move_sensitivity / 10; + joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; + joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; + side += fixed_mul(sidemove[speed], joyxmove); } - else if (joystick_move_sensitivity) + else if (joystick_move_sensitivity) { - if (joyxmove > 0) - side += sidemove[speed]; - if (joyxmove < 0) - side -= sidemove[speed]; + if (joyxmove > 0) side += sidemove[speed]; + if (joyxmove < 0) side -= sidemove[speed]; } - } - else - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - cmd->angleturn -= angleturn[tspeed]; - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - cmd->angleturn += angleturn[tspeed]; - if (use_analog && joyxmove) + } + else + { + if (gamekeydown[key_right] || mousebuttons[mousebturnright]) + cmd->angleturn -= angleturn[tspeed]; + if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) + cmd->angleturn += angleturn[tspeed]; + if (use_analog && joyxmove) { - // Cubic response curve allows for finer control when stick - // deflection is small. - joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); - joyxmove = joyxmove * joystick_turn_sensitivity / 10; - cmd->angleturn -= FixedMul(angleturn[1], joyxmove); + /* Cubic response curve allows for finer control when stick + * deflection is small. + */ + + joyxmove = fixed_mul(fixed_mul(joyxmove, joyxmove), joyxmove); + joyxmove = joyxmove * joystick_turn_sensitivity / 10; + cmd->angleturn -= fixed_mul(angleturn[1], joyxmove); } - else if (joystick_turn_sensitivity) + else if (joystick_turn_sensitivity) { - if (joyxmove > 0) - cmd->angleturn -= angleturn[tspeed]; - if (joyxmove < 0) - cmd->angleturn += angleturn[tspeed]; + if (joyxmove > 0) cmd->angleturn -= angleturn[tspeed]; + if (joyxmove < 0) cmd->angleturn += angleturn[tspeed]; } - } - - if (gamekeydown[key_up]) + } + + if (gamekeydown[key_up]) { - // fprintf(stderr, "up\n"); - forward += forwardmove[speed]; + forward += forwardmove[speed]; } - if (gamekeydown[key_down]) + + if (gamekeydown[key_down]) { - // fprintf(stderr, "down\n"); - forward -= forwardmove[speed]; + forward -= forwardmove[speed]; } - if (use_analog && joyymove) + if (use_analog && joyymove) { - joyymove = joyymove * joystick_move_sensitivity / 10; - joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; - joyymove = (joyymove < -FRACUNIT) ? -FRACUNIT : joyymove; - forward -= FixedMul(forwardmove[speed], joyymove); + joyymove = joyymove * joystick_move_sensitivity / 10; + joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; + joyymove = (joyymove < -FRACUNIT) ? -FRACUNIT : joyymove; + forward -= fixed_mul(forwardmove[speed], joyymove); } - else if (joystick_move_sensitivity) + else if (joystick_move_sensitivity) { - if (joyymove < 0) - forward += forwardmove[speed]; - if (joyymove > 0) - forward -= forwardmove[speed]; + if (joyymove < 0) forward += forwardmove[speed]; + if (joyymove > 0) forward -= forwardmove[speed]; } - if (gamekeydown[key_strafeleft] - || joybuttons[joybstrafeleft] - || mousebuttons[mousebstrafeleft]) + if (gamekeydown[key_strafeleft] || joybuttons[joybstrafeleft] || + mousebuttons[mousebstrafeleft]) { - side -= sidemove[speed]; + side -= sidemove[speed]; } - if (gamekeydown[key_straferight] - || joybuttons[joybstraferight] - || mousebuttons[mousebstraferight]) + if (gamekeydown[key_straferight] || joybuttons[joybstraferight] || + mousebuttons[mousebstraferight]) { - side += sidemove[speed]; + side += sidemove[speed]; } - if (use_analog && joystrafemove) + if (use_analog && joystrafemove) { - joystrafemove = joystrafemove * joystick_move_sensitivity / 10; - joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; - joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; - side += FixedMul(sidemove[speed], joystrafemove); + joystrafemove = joystrafemove * joystick_move_sensitivity / 10; + joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; + joystrafemove = + (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; + side += fixed_mul(sidemove[speed], joystrafemove); } - else if (joystick_move_sensitivity) + else if (joystick_move_sensitivity) { - if (joystrafemove < 0) - side -= sidemove[speed]; - if (joystrafemove > 0) - side += sidemove[speed]; + if (joystrafemove < 0) side -= sidemove[speed]; + if (joystrafemove > 0) side += sidemove[speed]; } - // buttons - cmd->chatchar = HU_dequeueChatChar(); - - if (gamekeydown[key_fire] || mousebuttons[mousebfire] - || joybuttons[joybfire]) - cmd->buttons |= BT_ATTACK; - - if (gamekeydown[key_use] - || joybuttons[joybuse] - || mousebuttons[mousebuse]) - { - cmd->buttons |= BT_USE; - // clear double clicks if hit use button - dclicks = 0; - } + /* buttons */ + + cmd->chatchar = hu_dequeue_chat_char(); + + if (gamekeydown[key_fire] || mousebuttons[mousebfire] || + joybuttons[joybfire]) + cmd->buttons |= BT_ATTACK; + + if (gamekeydown[key_use] || joybuttons[joybuse] || mousebuttons[mousebuse]) + { + cmd->buttons |= BT_USE; + dclicks = 0; /* clear double clicks if hit use button */ + } - // If the previous or next weapon button is pressed, the - // next_weapon variable is set to change weapons when - // we generate a ticcmd. Choose a new weapon. + /* If the previous or next weapon button is pressed, the + * next_weapon variable is set to change weapons when + * we generate a ticcmd. Choose a new weapon. + */ - if (gamestate == GS_LEVEL && next_weapon != 0) + if (gamestate == GS_LEVEL && next_weapon != 0) { - i = G_NextWeapon(next_weapon); - cmd->buttons |= BT_CHANGE; - cmd->buttons |= i << BT_WEAPONSHIFT; + i = g_next_weapon(next_weapon); + cmd->buttons |= BT_CHANGE; + cmd->buttons |= i << BT_WEAPONSHIFT; } - else + else { - // Check weapon keys. + /* Check weapon keys. */ - for (i=0; ibuttons |= BT_CHANGE; - cmd->buttons |= i<buttons |= BT_CHANGE; + cmd->buttons |= i << BT_WEAPONSHIFT; + break; } } } - next_weapon = 0; + next_weapon = 0; + + /* mouse */ - // mouse - if (mousebuttons[mousebforward]) + if (mousebuttons[mousebforward]) { - forward += forwardmove[speed]; + forward += forwardmove[speed]; } - if (mousebuttons[mousebbackward]) + + if (mousebuttons[mousebbackward]) { - forward -= forwardmove[speed]; + forward -= forwardmove[speed]; } - if (dclick_use) + if (dclick_use) { - // forward double click - if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 ) - { - dclickstate = mousebuttons[mousebforward]; - if (dclickstate) - dclicks++; - if (dclicks == 2) - { - cmd->buttons |= BT_USE; - dclicks = 0; - } - else - dclicktime = 0; - } - else - { - dclicktime += ticdup; - if (dclicktime > 20) - { - dclicks = 0; - dclickstate = 0; - } + /* forward double click */ + + if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1) + { + dclickstate = mousebuttons[mousebforward]; + if (dclickstate) dclicks++; + if (dclicks == 2) + { + cmd->buttons |= BT_USE; + dclicks = 0; + } + else + dclicktime = 0; } - - // strafe double click - bstrafe = - mousebuttons[mousebstrafe] - || joybuttons[joybstrafe]; - if (bstrafe != dclickstate2 && dclicktime2 > 1 ) - { - dclickstate2 = bstrafe; - if (dclickstate2) - dclicks2++; - if (dclicks2 == 2) - { - cmd->buttons |= BT_USE; - dclicks2 = 0; - } - else - dclicktime2 = 0; - } - else - { - dclicktime2 += ticdup; - if (dclicktime2 > 20) - { - dclicks2 = 0; - dclickstate2 = 0; - } - } - } - - forward += mousey; - - if (strafe) - side += mousex*2; - else - cmd->angleturn -= mousex*0x8; - - if (mousex == 0) - { - // No movement in the previous frame - - testcontrols_mousespeed = 0; - } - - mousex = mousey = 0; - - if (forward > MAXPLMOVE) - forward = MAXPLMOVE; - else if (forward < -MAXPLMOVE) - forward = -MAXPLMOVE; - if (side > MAXPLMOVE) - side = MAXPLMOVE; - else if (side < -MAXPLMOVE) - side = -MAXPLMOVE; - - cmd->forwardmove += forward; - cmd->sidemove += side; - - // special buttons - if (sendpause) - { - sendpause = false; - cmd->buttons = BT_SPECIAL | BTS_PAUSE; - } - - if (sendsave) - { - sendsave = false; - cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<angleturn + carry; - - // round angleturn to the nearest 256 unit boundary - // for recording demos with single byte values for turn - - cmd->angleturn = (desired_angleturn + 128) & 0xff00; - - // Carry forward the error from the reduced resolution to the - // next tic, so that successive small movements can accumulate. - - carry = desired_angleturn - cmd->angleturn; - } -} - - -// -// G_DoLoadLevel -// -void G_DoLoadLevel (void) -{ - int i; - - // Set the sky map. - // First thing, we have a dummy sky texture name, - // a flat. The data is in the WAD only because - // we look for an actual index, instead of simply - // setting one. - - skyflatnum = R_FlatNumForName(DEH_String(SKYFLATNAME)); - - // The "Sky never changes in Doom II" bug was fixed in - // the id Anthology version of doom2.exe for Final Doom. - if ((gamemode == commercial) - && (gameversion == exe_final2 || gameversion == exe_chex)) - { - const char *skytexturename; - - if (gamemap < 12) + else { - skytexturename = "SKY1"; + dclicktime += ticdup; + if (dclicktime > 20) + { + dclicks = 0; + dclickstate = 0; + } } - else if (gamemap < 21) + + /* strafe double click */ + + bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; + if (bstrafe != dclickstate2 && dclicktime2 > 1) { - skytexturename = "SKY2"; + dclickstate2 = bstrafe; + if (dclickstate2) dclicks2++; + if (dclicks2 == 2) + { + cmd->buttons |= BT_USE; + dclicks2 = 0; + } + else + dclicktime2 = 0; } - else + else { - skytexturename = "SKY3"; + dclicktime2 += ticdup; + if (dclicktime2 > 20) + { + dclicks2 = 0; + dclickstate2 = 0; + } } + } - skytexturename = DEH_String(skytexturename); + forward += mousey; - skytexture = R_TextureNumForName(skytexturename); + if (strafe) + side += mousex * 2; + else + cmd->angleturn -= mousex * 0x8; + + if (mousex == 0) + { + /* No movement in the previous frame */ + + testcontrols_mousespeed = 0; } - levelstarttic = gametic; // for time calculation - - if (wipegamestate == GS_LEVEL) - wipegamestate = -1; // force a wipe + mousex = mousey = 0; - gamestate = GS_LEVEL; + if (forward > MAXPLMOVE) + forward = MAXPLMOVE; + else if (forward < -MAXPLMOVE) + forward = -MAXPLMOVE; + if (side > MAXPLMOVE) + side = MAXPLMOVE; + else if (side < -MAXPLMOVE) + side = -MAXPLMOVE; - for (i=0 ; iforwardmove += forward; + cmd->sidemove += side; - memset (gamekeydown, 0, sizeof(gamekeydown)); - joyxmove = joyymove = joystrafemove = 0; - mousex = mousey = 0; - sendpause = sendsave = paused = false; - memset(mousearray, 0, sizeof(mousearray)); - memset(joyarray, 0, sizeof(joyarray)); + /* special buttons */ - if (testcontrols) + if (sendpause) { - players[consoleplayer].message = "Press escape to quit."; + sendpause = false; + cmd->buttons = BT_SPECIAL | BTS_PAUSE; } -} -static void SetJoyButtons(unsigned int buttons_mask) -{ - int i; + if (sendsave) + { + sendsave = false; + cmd->buttons = + BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT); + } - for (i=0; iangleturn + carry; - if (!joybuttons[i] && button_on) - { - // Weapon cycling: + /* round angleturn to the nearest 256 unit boundary + * for recording demos with single byte values for turn + */ - if (i == joybprevweapon) - { - next_weapon = -1; - } - else if (i == joybnextweapon) - { - next_weapon = 1; - } - } + cmd->angleturn = (desired_angleturn + 128) & 0xff00; + + /* Carry forward the error from the reduced resolution to the + * next tic, so that successive small movements can accumulate. + */ - joybuttons[i] = button_on; + carry = desired_angleturn - cmd->angleturn; } } -static void SetMouseButtons(unsigned int buttons_mask) +/* g_responder + * Get info needed to make ticcmd_ts for the players. + */ + +boolean g_responder(event_t *ev) { - int i; + /* allow spy mode changes even during the demo */ - for (i=0; itype == ev_keydown && + ev->data1 == key_spy && (singledemo || !deathmatch)) { - unsigned int button_on = (buttons_mask & (1 << i)) != 0; + /* spy mode */ + + do + { + displayplayer++; + if (displayplayer == MAXPLAYERS) displayplayer = 0; + } + while (!playeringame[displayplayer] && displayplayer != consoleplayer); + return true; + } - // Detect button press: + /* any other key pops up menu if in demos */ - if (!mousebuttons[i] && button_on) + if (gameaction == ga_nothing && !singledemo && + (demoplayback || gamestate == GS_DEMOSCREEN)) + { + if (ev->type == ev_keydown || (ev->type == ev_mouse && ev->data1) || + (ev->type == ev_joystick && ev->data1)) { - if (i == mousebprevweapon) - { - next_weapon = -1; - } - else if (i == mousebnextweapon) - { - next_weapon = 1; - } + m_start_control_panel(); + joywait = i_get_time() + 5; + return true; } - mousebuttons[i] = button_on; + return false; } -} -// -// G_Responder -// Get info needed to make ticcmd_ts for the players. -// -boolean G_Responder (event_t* ev) -{ - // allow spy mode changes even during the demo - if (gamestate == GS_LEVEL && ev->type == ev_keydown - && ev->data1 == key_spy && (singledemo || !deathmatch) ) - { - // spy mode - do - { - displayplayer++; - if (displayplayer == MAXPLAYERS) - displayplayer = 0; - } while (!playeringame[displayplayer] && displayplayer != consoleplayer); - return true; - } - - // any other key pops up menu if in demos - if (gameaction == ga_nothing && !singledemo && - (demoplayback || gamestate == GS_DEMOSCREEN) - ) - { - if (ev->type == ev_keydown || - (ev->type == ev_mouse && ev->data1) || - (ev->type == ev_joystick && ev->data1) ) - { - M_StartControlPanel (); - joywait = I_GetTime() + 5; - return true; - } - return false; - } - - if (gamestate == GS_LEVEL) - { -#if 0 - if (devparm && ev->type == ev_keydown && ev->data1 == ';') - { - G_DeathMatchSpawnPlayer (0); - return true; - } -#endif - if (HU_Responder (ev)) - return true; // chat ate the event - if (ST_Responder (ev)) - return true; // status window ate it - if (AM_Responder (ev)) - return true; // automap ate it - } - - if (gamestate == GS_FINALE) - { - if (F_Responder (ev)) - return true; // finale ate the event - } - - if (testcontrols && ev->type == ev_mouse) - { - // If we are invoked by setup to test the controls, save the - // mouse speed so that we can display it on-screen. - // Perform a low pass filter on this so that the thermometer - // appears to move smoothly. - - testcontrols_mousespeed = abs(ev->data2); - } - - // If the next/previous weapon keys are pressed, set the next_weapon - // variable to change weapons when the next ticcmd is generated. - - if (ev->type == ev_keydown && ev->data1 == key_prevweapon) - { - next_weapon = -1; - } - else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) - { - next_weapon = 1; - } - - switch (ev->type) - { - case ev_keydown: - if (ev->data1 == key_pause) - { - sendpause = true; - } - else if (ev->data1 type == ev_keydown && ev->data1 == ';') { - gamekeydown[ev->data1] = true; + g_death_match_spawn_player(0); + return true; } - return true; // eat key down events - - case ev_keyup: - if (ev->data1 data1] = false; - return false; // always let key up events filter down - - case ev_mouse: - SetMouseButtons(ev->data1); - mousex = ev->data2*(mouseSensitivity+5)/10; - mousey = ev->data3*(mouseSensitivity+5)/10; - return true; // eat events - - case ev_joystick: - SetJoyButtons(ev->data1); - joyxmove = ev->data2; - joyymove = ev->data3; - joystrafemove = ev->data4; - return true; // eat events - - default: - break; - } - - return false; -} - - - -// -// G_Ticker -// Make ticcmd_ts for the players. -// -void G_Ticker (void) -{ - int i; - int buf; - ticcmd_t* cmd; - - // do player reborns if needed - for (i=0 ; iforwardmove > TURBOTHRESHOLD) - { - turbodetected[i] = true; - } +#endif + if (hu_responder(ev)) return true; /* chat ate the event */ + if (st_responder(ev)) return true; /* status window ate it */ + if (am_responder(ev)) return true; /* automap ate it */ + } - if ((gametic & 31) == 0 - && ((gametic >> 5) % MAXPLAYERS) == i - && turbodetected[i]) - { - static char turbomessage[80]; - M_snprintf(turbomessage, sizeof(turbomessage), - "%s is turbo!", player_names[i]); - players[consoleplayer].message = turbomessage; - turbodetected[i] = false; - } + if (gamestate == GS_FINALE) + { + if (f_responder(ev)) return true; /* finale ate the event */ + } - if (netgame && !netdemo && !(gametic%ticdup) ) - { - if (gametic > BACKUPTICS - && consistancy[i][buf] != cmd->consistancy) - { - I_Error ("consistency failure (%i should be %i)", - cmd->consistancy, consistancy[i][buf]); - } - if (players[i].mo) - consistancy[i][buf] = players[i].mo->x; - else - consistancy[i][buf] = rndindex; - } - } - } - - // check for special buttons - for (i=0 ; itype == ev_mouse) + { + /* If we are invoked by setup to test the controls, save the + * mouse speed so that we can display it on-screen. + * Perform a low pass filter on this so that the thermometer + * appears to move smoothly. + */ - savegameslot = - (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT; - gameaction = ga_savegame; - break; - } - } - } - } - - // Have we just finished displaying an intermission screen? - - if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION) - { - WI_End(); - } - - oldgamestate = gamestate; - - // do main actions - switch (gamestate) - { - case GS_LEVEL: - P_Ticker (); - ST_Ticker (); - AM_Ticker (); - HU_Ticker (); - break; - - case GS_INTERMISSION: - WI_Ticker (); - break; - - case GS_FINALE: - F_Ticker (); - break; - - case GS_DEMOSCREEN: - D_PageTicker (); - break; - } -} - - -// -// PLAYER STRUCTURE FUNCTIONS -// also see P_SpawnPlayer in P_Things -// - -// -// G_InitPlayer -// Called at the start. -// Called by the game initialization functions. -// -void G_InitPlayer (int player) -{ - // clear everything else to defaults - G_PlayerReborn (player); -} - - - -// -// G_PlayerFinishLevel -// Can when a player completes a level. -// -void G_PlayerFinishLevel (int player) -{ - player_t* p; - - p = &players[player]; - - memset (p->powers, 0, sizeof (p->powers)); - memset (p->cards, 0, sizeof (p->cards)); - p->mo->flags &= ~MF_SHADOW; // cancel invisibility - p->extralight = 0; // cancel gun flashes - p->fixedcolormap = 0; // cancel ir gogles - p->damagecount = 0; // no palette changes - p->bonuscount = 0; -} - - -// -// G_PlayerReborn -// Called after a player dies -// almost everything is cleared and initialized -// -void G_PlayerReborn (int player) -{ - player_t* p; - int i; - int frags[MAXPLAYERS]; - int killcount; - int itemcount; - int secretcount; - - memcpy (frags,players[player].frags,sizeof(frags)); - killcount = players[player].killcount; - itemcount = players[player].itemcount; - secretcount = players[player].secretcount; - - p = &players[player]; - memset (p, 0, sizeof(*p)); - - memcpy (players[player].frags, frags, sizeof(players[player].frags)); - players[player].killcount = killcount; - players[player].itemcount = itemcount; - players[player].secretcount = secretcount; - - p->usedown = p->attackdown = true; // don't do anything immediately - p->playerstate = PST_LIVE; - p->health = deh_initial_health; // Use dehacked value - p->readyweapon = p->pendingweapon = wp_pistol; - p->weaponowned[wp_fist] = true; - p->weaponowned[wp_pistol] = true; - p->ammo[am_clip] = deh_initial_bullets; - - for (i=0 ; imaxammo[i] = maxammo[i]; - -} + testcontrols_mousespeed = abs(ev->data2); + } -// -// G_CheckSpot -// Returns false if the player cannot be respawned -// at the given mapthing_t spot -// because something is occupying it -// -void P_SpawnPlayer (mapthing_t* mthing); - -boolean -G_CheckSpot -( int playernum, - mapthing_t* mthing ) -{ - fixed_t x; - fixed_t y; - subsector_t* ss; - mobj_t* mo; - int i; - - if (!players[playernum].mo) - { - // first spawn of level, before corpses - for (i=0 ; ix == mthing->x << FRACBITS - && players[i].mo->y == mthing->y << FRACBITS) - return false; - return true; - } - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - if (!P_CheckPosition (players[playernum].mo, x, y) ) - return false; - - // flush an old corpse if needed - if (bodyqueslot >= BODYQUESIZE) - P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); - bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; - bodyqueslot++; - - // spawn a teleport fog - ss = R_PointInSubsector (x,y); - - - // The code in the released source looks like this: - // - // an = ( ANG45 * (((unsigned int) mthing->angle)/45) ) - // >> ANGLETOFINESHIFT; - // mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] - // , ss->sector->floorheight - // , MT_TFOG); - // - // But 'an' can be a signed value in the DOS version. This means that - // we get a negative index and the lookups into finecosine/finesine - // end up dereferencing values in finetangent[]. - // A player spawning on a deathmatch start facing directly west spawns - // "silently" with no spawn fog. Emulate this. - // - // This code is imported from PrBoom+. - - { - fixed_t xa, ya; - signed int an; - - // This calculation overflows in Vanilla Doom, but here we deliberately - // avoid integer overflow as it is undefined behavior, so the value of - // 'an' will always be positive. - an = (ANG45 >> ANGLETOFINESHIFT) * ((signed int) mthing->angle / 45); - - switch (an) - { - case 4096: // -4096: - xa = finetangent[2048]; // finecosine[-4096] - ya = finetangent[0]; // finesine[-4096] - break; - case 5120: // -3072: - xa = finetangent[3072]; // finecosine[-3072] - ya = finetangent[1024]; // finesine[-3072] - break; - case 6144: // -2048: - xa = finesine[0]; // finecosine[-2048] - ya = finetangent[2048]; // finesine[-2048] - break; - case 7168: // -1024: - xa = finesine[1024]; // finecosine[-1024] - ya = finetangent[3072]; // finesine[-1024] - break; - case 0: - case 1024: - case 2048: - case 3072: - xa = finecosine[an]; - ya = finesine[an]; - break; - case 8192: // 360 deg: - xa = tantoangle[0]; // finecosine[8192] - ya = finesine[8192]; // finesine[8192] - break; - default: - I_Error("G_CheckSpot: unexpected angle %d\n", an); - xa = ya = 0; - break; - } - mo = P_SpawnMobj(x + 20 * xa, y + 20 * ya, - ss->sector->floorheight, MT_TFOG); - } - - if (players[consoleplayer].viewz != 1) - S_StartSound (mo, sfx_telept); // don't start sound on first frame - - return true; -} - - -// -// G_DeathMatchSpawnPlayer -// Spawns a player at one of the random death match spots -// called at level load and each death -// -void G_DeathMatchSpawnPlayer (int playernum) -{ - int i,j; - int selections; - - selections = deathmatch_p - deathmatchstarts; - if (selections < 4) - I_Error ("Only %i deathmatch spots, 4 required", selections); - - for (j=0 ; j<20 ; j++) - { - i = P_Random() % selections; - if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) - { - deathmatchstarts[i].type = playernum+1; - P_SpawnPlayer (&deathmatchstarts[i]); - return; - } - } - - // no good spot, so the player will probably get stuck - P_SpawnPlayer (&playerstarts[playernum]); -} - -// -// G_DoReborn -// -void G_DoReborn (int playernum) -{ - int i; - - if (!netgame) - { - // reload the level from scratch - gameaction = ga_loadlevel; - } - else - { - // respawn at the start - - // first dissasociate the corpse - players[playernum].mo->player = NULL; - - // spawn at random spot if in death match - if (deathmatch) - { - G_DeathMatchSpawnPlayer (playernum); - return; - } - - if (G_CheckSpot (playernum, &playerstarts[playernum]) ) - { - P_SpawnPlayer (&playerstarts[playernum]); - return; - } - - // try to spawn at one of the other players spots - for (i=0 ; itype == ev_keydown && ev->data1 == key_prevweapon) + { + next_weapon = -1; + } + else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) + { + next_weapon = 1; + } + + switch (ev->type) + { + case ev_keydown: + if (ev->data1 == key_pause) { - if (gamemap == 5) - { - gameaction = ga_victory; - return; - } + sendpause = true; } - else + else if (ev->data1 < NUMKEYS) { - switch(gamemap) - { - case 8: - gameaction = ga_victory; - return; - case 9: - for (i=0 ; idata1] = true; } + + return true; /* eat key down events */ + + case ev_keyup: + if (ev->data1 < NUMKEYS) gamekeydown[ev->data1] = false; + return false; /* always let key up events filter down */ + + case ev_mouse: + set_mouse_buttons(ev->data1); + mousex = ev->data2 * (g_mouse_sensitivity + 5) / 10; + mousey = ev->data3 * (g_mouse_sensitivity + 5) / 10; + return true; /* eat events */ + + case ev_joystick: + set_joy_buttons(ev->data1); + joyxmove = ev->data2; + joyymove = ev->data3; + joystrafemove = ev->data4; + return true; /* eat events */ + + default: + break; } -//#if 0 Hmmm - why? - if ( (gamemap == 8) - && (gamemode != commercial) ) - { - // victory - gameaction = ga_victory; - return; - } - - if ( (gamemap == 9) - && (gamemode != commercial) ) - { - // exit secret level - for (i=0 ; iforwardmove > TURBOTHRESHOLD) + { + turbodetected[i] = true; + } - // Enforce the same savegame size limit as in Vanilla Doom, - // except if the vanilla_savegame_limit setting is turned off. + if ((gametic & 31) == 0 && ((gametic >> 5) % MAXPLAYERS) == i && + turbodetected[i]) + { + static char turbomessage[80]; + snprintf(turbomessage, sizeof(turbomessage), "%s is turbo!", + player_names[i]); + players[consoleplayer].message = turbomessage; + turbodetected[i] = false; + } - if (vanilla_savegame_limit && ftell(save_stream) > SAVEGAMESIZE) - { - I_Error("Savegame buffer overrun"); + if (netgame && !netdemo && !(gametic % ticdup)) + { + if (gametic > CONFIG_GAMES_NXDOOM_NET_BACKUPTICS && + consistency[i][buf] != cmd->consistency) + { + i_error("consistency failure (%i should be %i)", + cmd->consistency, consistency[i][buf]); + } + + if (players[i].mo) + consistency[i][buf] = players[i].mo->x; + else + consistency[i][buf] = rndindex; + } + } } - // Finish up, close the savegame file. + /* check for special buttons */ + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (players[i].cmd.buttons & BT_SPECIAL) + { + switch (players[i].cmd.buttons & BT_SPECIALMASK) + { + case BTS_PAUSE: + paused ^= 1; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (paused) + s_pause_sound(); + else + s_resume_sound(); + break; +#endif + + case BTS_SAVEGAME: + if (!savedescription[0]) + { + m_str_copy(savedescription, "NET GAME", + sizeof(savedescription)); + } + + savegameslot = (players[i].cmd.buttons & BTS_SAVEMASK) >> + BTS_SAVESHIFT; + gameaction = ga_savegame; + break; + } + } + } + } - fclose(save_stream); + /* Have we just finished displaying an intermission screen? */ - if (recovery_savegame_file != NULL) + if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION) { - // We failed to save to the normal location, but we wrote a - // recovery file to the temp directory. Now we can bomb out - // with an error. - I_Error("Failed to open savegame file '%s' for writing.\n" - "But your game has been saved to '%s' for recovery.", - temp_savegame_file, recovery_savegame_file); + wi_end(); } - // Now rename the temporary savegame file to the actual savegame - // file, overwriting the old savegame if there was one there. + oldgamestate = gamestate; - M_remove(savegame_file); - M_rename(temp_savegame_file, savegame_file); + /* do main actions */ - gameaction = ga_nothing; - M_StringCopy(savedescription, "", sizeof(savedescription)); + switch (gamestate) + { + case GS_LEVEL: + p_ticker(); + st_ticker(); + am_ticker(); + hu_ticker(); + break; - players[consoleplayer].message = DEH_String(GGSAVED); + case GS_INTERMISSION: + wi_ticker(); + break; - // draw the pattern into the back screen - R_FillBackScreen (); -} - - -// -// G_InitNew -// Can be called by the startup code or the menu task, -// consoleplayer, displayplayer, playeringame[] should be set. -// -skill_t d_skill; -int d_episode; -int d_map; - -void -G_DeferedInitNew -( skill_t skill, - int episode, - int map) -{ - d_skill = skill; - d_episode = episode; - d_map = map; - gameaction = ga_newgame; -} - - -void G_DoNewGame (void) -{ - demoplayback = false; - netdemo = false; - netgame = false; - deathmatch = false; - playeringame[1] = playeringame[2] = playeringame[3] = 0; - respawnparm = false; - fastparm = false; - nomonsters = false; - consoleplayer = 0; - G_InitNew (d_skill, d_episode, d_map); - gameaction = ga_nothing; -} - - -void -G_InitNew -( skill_t skill, - int episode, - int map ) -{ - const char *skytexturename; - int i; + case GS_FINALE: + f_ticker(); + break; - if (paused) - { - paused = false; - S_ResumeSound (); + case GS_DEMOSCREEN: + d_page_ticker(); + break; } +} - /* - // Note: This commented-out block of code was added at some point - // between the DOS version(s) and the Doom source release. It isn't - // found in disassemblies of the DOS version and causes IDCLEV and - // the -warp command line parameter to behave differently. - // This is left here for posterity. +/* PLAYER STRUCTURE FUNCTIONS + * also see p_spawn_player in P_Things + */ - // This was quite messy with SPECIAL and commented parts. - // Supposedly hacks to make the latest edition work. - // It might not work properly. - if (episode < 1) - episode = 1; +/* g_player_reborn + * Called after a player dies almost everything is cleared and initialized + */ - if ( gamemode == retail ) - { - if (episode > 4) - episode = 4; - } - else if ( gamemode == shareware ) - { - if (episode > 1) - episode = 1; // only start episode 1 on shareware - } - else - { - if (episode > 3) - episode = 3; - } - */ +void g_player_reborn(int player) +{ + player_t *p; + int i; + int frags[MAXPLAYERS]; + int killcount; + int itemcount; + int secretcount; + + memcpy(frags, players[player].frags, sizeof(frags)); + killcount = players[player].killcount; + itemcount = players[player].itemcount; + secretcount = players[player].secretcount; + + p = &players[player]; + memset(p, 0, sizeof(*p)); + + memcpy(players[player].frags, frags, sizeof(players[player].frags)); + players[player].killcount = killcount; + players[player].itemcount = itemcount; + players[player].secretcount = secretcount; + + p->usedown = p->attackdown = true; /* don't do anything immediately */ + p->playerstate = PST_LIVE; + p->health = deh_initial_health; /* Use dehacked value */ + p->readyweapon = p->pendingweapon = wp_pistol; + p->weaponowned[wp_fist] = true; + p->weaponowned[wp_pistol] = true; + p->ammo[am_clip] = deh_initial_bullets; + + for (i = 0; i < NUMAMMO; i++) + p->maxammo[i] = maxammo[i]; +} - if (skill > sk_nightmare) - skill = sk_nightmare; +/* g_death_match_spawn_player + * Spawns a player at one of the random death match spots + * called at level load and each death + */ - if (gameversion >= exe_ultimate) - { - if (episode == 0) - { - episode = 4; - } - } - else +void g_death_match_spawn_player(int playernum) +{ + int i; + int j; + int selections; + + selections = deathmatch_p - deathmatchstarts; + if (selections < 4) + i_error("Only %i deathmatch spots, 4 required", selections); + + for (j = 0; j < 20; j++) { - if (episode < 1) - { - episode = 1; - } - if (episode > 3) + i = p_random() % selections; + if (g_check_spot(playernum, &deathmatchstarts[i])) { - episode = 3; + deathmatchstarts[i].type = playernum + 1; + p_spawn_player(&deathmatchstarts[i]); + return; } } - if (episode > 1 && gamemode == shareware) - { - episode = 1; - } + /* no good spot, so the player will probably get stuck */ - if (map < 1) - map = 1; + p_spawn_player(&playerstarts[playernum]); +} - if ( (map > 9) - && ( gamemode != commercial) ) - map = 9; +void g_screenshot(void) +{ + gameaction = ga_screenshot; +} - M_ClearRandom (); +void g_exit_level(void) +{ + secretexit = false; + gameaction = ga_completed; +} - if (skill == sk_nightmare || respawnparm ) - respawnmonsters = true; - else - respawnmonsters = false; +/* Here's for the german edition. */ - if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) ) - { - for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) - states[i].tics >>= 1; - mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT; - mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; - mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; - } - else if (skill != sk_nightmare && gameskill == sk_nightmare) - { - for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) - states[i].tics <<= 1; - mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT; - mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT; - mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; - } +void g_secret_exit_level(void) +{ + /* IF NO WOLF3D LEVELS, NO SECRET EXIT! */ - // force players to be initialized upon first level load - for (i=0 ; iforwardmove = ((signed char)*demo_p++); - cmd->sidemove = ((signed char)*demo_p++); + gameaction = ga_nothing; - // If this is a longtics demo, read back in higher resolution + save_stream = fopen(savename, "rb"); - if (longtics) + if (save_stream == NULL) { - cmd->angleturn = *demo_p++; - cmd->angleturn |= (*demo_p++) << 8; + i_error("Could not load savegame %s", savename); } - else + + savegame_error = false; + + if (!p_read_save_game_header()) { - cmd->angleturn = ((unsigned char) *demo_p++)<<8; + fclose(save_stream); + return; } - cmd->buttons = (unsigned char)*demo_p++; -} + savedleveltime = leveltime; -// Increase the size of the demo buffer to allow unlimited demos + /* load a base level */ -static void IncreaseDemoBuffer(void) -{ - int current_length; - byte *new_demobuffer; - byte *new_demop; - int new_length; + g_init_new(gameskill, gameepisode, gamemap); + + leveltime = savedleveltime; + + /* dearchive all the modifications */ - // Find the current size + p_unarchive_players(); + p_unarchive_world(); + p_unarchive_thinkers(); + p_unarchive_specials(); - current_length = demoend - demobuffer; - - // Generate a new buffer twice the size - new_length = current_length * 2; - - new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); - new_demop = new_demobuffer + (demo_p - demobuffer); + if (!p_read_save_game_eof()) i_error("Bad savegame"); - // Copy over the old data + fclose(save_stream); + + if (setsizeneeded) r_execute_set_view_size(); + + /* draw the pattern into the back screen */ + + r_fill_back_screen(); +} - memcpy(new_demobuffer, demobuffer, current_length); +/* g_save_game + * Called by the menu task. + * Description is a 24 byte text string + */ - // Free the old buffer and point the demo pointers at the new buffer. +void g_save_game(int slot, char *description) +{ + savegameslot = slot; + m_str_copy(savedescription, description, sizeof(savedescription)); + sendsave = true; +} - Z_Free(demobuffer); +/* g_init_new + * Can be called by the startup code or the menu task, + * consoleplayer, displayplayer, playeringame[] should be set. + */ - demobuffer = new_demobuffer; - demo_p = new_demop; - demoend = demobuffer + new_length; +void g_deferred_init_new(skill_t skill, int episode, int map) +{ + d_skill = skill; + d_episode = episode; + d_map = map; + gameaction = ga_newgame; } -void G_WriteDemoTiccmd (ticcmd_t* cmd) -{ - byte *demo_start; +void g_init_new(skill_t skill, int episode, int map) +{ + const char *skytexturename; + int i; + + if (paused) + { + paused = false; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_resume_sound(); +#endif + } + + /* Note: This commented-out block of code was added at some point + * between the DOS version(s) and the Doom source release. It isn't + * found in disassemblies of the DOS version and causes IDCLEV and + * the -warp command line parameter to behave differently. + * This is left here for posterity. + * This was quite messy with SPECIAL and commented parts. + * Supposedly hacks to make the latest edition work. + * It might not work properly. + * + * if (episode < 1) + * episode = 1; + * if ( gamemode == retail ) + * { + * if (episode > 4) + * episode = 4; + * } + * else if ( gamemode == shareware ) + * { + * if (episode > 1) + * episode = 1; // only start episode 1 on shareware + * } + * else + * { + * if (episode > 3) + * episode = 3; + * } + */ + + if (skill > sk_nightmare) skill = sk_nightmare; + + if (gameversion >= exe_ultimate) + { + if (episode == 0) + { + episode = 4; + } + } + else + { + if (episode < 1) + { + episode = 1; + } + + if (episode > 3) + { + episode = 3; + } + } + + if (episode > 1 && gamemode == shareware) + { + episode = 1; + } + + if (map < 1) map = 1; - if (gamekeydown[key_demo_quit]) // press q to end demo recording - G_CheckDemoStatus (); + if ((map > 9) && (gamemode != commercial)) map = 9; - demo_start = demo_p; + m_clear_random(); - *demo_p++ = cmd->forwardmove; - *demo_p++ = cmd->sidemove; + if (skill == sk_nightmare || respawnparm) + respawnmonsters = true; + else + respawnmonsters = false; - // If this is a longtics demo, record in higher resolution - - if (longtics) + if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare)) { - *demo_p++ = (cmd->angleturn & 0xff); - *demo_p++ = (cmd->angleturn >> 8) & 0xff; + for (i = S_SARG_RUN1; i <= S_SARG_PAIN2; i++) + states[i].tics >>= 1; + mobjinfo[MT_BRUISERSHOT].speed = 20 * FRACUNIT; + mobjinfo[MT_HEADSHOT].speed = 20 * FRACUNIT; + mobjinfo[MT_TROOPSHOT].speed = 20 * FRACUNIT; } - else + else if (skill != sk_nightmare && gameskill == sk_nightmare) { - *demo_p++ = cmd->angleturn >> 8; + for (i = S_SARG_RUN1; i <= S_SARG_PAIN2; i++) + states[i].tics <<= 1; + mobjinfo[MT_BRUISERSHOT].speed = 15 * FRACUNIT; + mobjinfo[MT_HEADSHOT].speed = 10 * FRACUNIT; + mobjinfo[MT_TROOPSHOT].speed = 10 * FRACUNIT; } - *demo_p++ = cmd->buttons; + /* force players to be initialized upon first level load */ - // reset demo pointer back - demo_p = demo_start; + for (i = 0; i < MAXPLAYERS; i++) + players[i].playerstate = PST_REBORN; - if (demo_p > demoend - 16) + usergame = true; /* will be set false if a demo */ + paused = false; + demoplayback = false; + automapactive = false; + viewactive = true; + gameepisode = episode; + gamemap = map; + gameskill = skill; + + /* Set the sky to use. + * + * Note: This IS broken, but it is how Vanilla Doom behaves. + * See http: *doomwiki.org/wiki/Sky_never_changes_in_Doom_II. + * + * Because we set the sky here at the start of a game, not at the + * start of a level, the sky texture never changes unless we + * restore from a saved game. This was fixed before the Doom + * source release, but this IS the way Vanilla DOS Doom behaves. + */ + + if (gamemode == commercial) { - if (vanilla_demo_limit) + skytexturename = ("SKY3"); + skytexture = r_texture_num_for_name(skytexturename); + if (gamemap < 21) { - // no more space - G_CheckDemoStatus (); - return; + skytexturename = (gamemap < 12 ? "SKY1" : "SKY2"); + skytexture = r_texture_num_for_name(skytexturename); } - else + } + else + { + switch (gameepisode) { - // Vanilla demo limit disabled: unlimited - // demo lengths! - - IncreaseDemoBuffer(); + default: + case 1: + skytexturename = "SKY1"; + break; + case 2: + skytexturename = "SKY2"; + break; + case 3: + skytexturename = "SKY3"; + break; + case 4: /* Special Edition sky */ + skytexturename = "SKY4"; + break; } - } - - G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same -} - - - -// -// G_RecordDemo -// -void G_RecordDemo (const char *name) + + skytexturename = (skytexturename); + skytexture = r_texture_num_for_name(skytexturename); + } + + g_do_load_level(); +} + +void g_record_demo(const char *name) { - size_t demoname_size; - int i; - int maxsize; - - usergame = false; - demoname_size = strlen(name) + 5; - demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); - M_snprintf(demoname, demoname_size, "%s.lmp", name); - maxsize = 0x20000; - - //! - // @arg - // @category demo - // @vanilla - // - // Specify the demo buffer size (KiB) - // - - i = M_CheckParmWithArgs("-maxdemo", 1); - if (i) - maxsize = atoi(myargv[i+1])*1024; - demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL); - demoend = demobuffer + maxsize; - - demorecording = true; -} - -// Get the demo version code appropriate for the version set in gameversion. -int G_VanillaVersionCode(void) + size_t demoname_size; + int i; + int maxsize; + + usergame = false; + demoname_size = strlen(name) + 5; + demoname = z_malloc(demoname_size, PU_STATIC, NULL); + snprintf(demoname, demoname_size, "%s.lmp", name); + maxsize = 0x20000; + + /* @arg + * @category demo + * @vanilla + * + * Specify the demo buffer size (KiB) + */ + + i = m_check_parm_with_args("-maxdemo", 1); + if (i) maxsize = atoi(myargv[i + 1]) * 1024; + demobuffer = z_malloc(maxsize, PU_STATIC, NULL); + demoend = demobuffer + maxsize; + + demorecording = true; +} + +/* Get the demo version code appropriate for the version set in gameversion. + */ + +int g_vanilla_version_code(void) { - switch (gameversion) - { - case exe_doom_1_666: - return 106; - case exe_doom_1_7: - return 107; - case exe_doom_1_8: - return 108; - case exe_doom_1_9: - default: // All other versions are variants on v1.9: - return 109; + switch (gameversion) + { + case exe_doom_1_666: + return 106; + case exe_doom_1_7: + return 107; + case exe_doom_1_8: + return 108; + case exe_doom_1_9: + default: /* All other versions are variants on v1.9: */ + return 109; } } -void G_BeginRecording (void) -{ - int i; +void g_begin_recording(void) +{ + int i; - demo_p = demobuffer; + demo_p = demobuffer; - //! - // @category demo - // - // Record a high resolution "Doom 1.91" demo. - // + /* @category demo + * + * Record a high resolution "Doom 1.91" demo. + */ - longtics = D_NonVanillaRecord(M_ParmExists("-longtics"), + longtics = d_non_vanilla_record(m_parm_exists("-longtics"), "Doom 1.91 demo format"); - // If not recording a longtics demo, record in low res - lowres_turn = !longtics; + /* If not recording a longtics demo, record in low res */ + + lowres_turn = !longtics; - if (longtics) + if (longtics) { - *demo_p++ = DOOM_191_VERSION; + *demo_p++ = DOOM_191_VERSION; } - else if (gameversion > exe_doom_1_2) + else if (gameversion > exe_doom_1_2) { - *demo_p++ = G_VanillaVersionCode(); + *demo_p++ = g_vanilla_version_code(); } - *demo_p++ = gameskill; - *demo_p++ = gameepisode; - *demo_p++ = gamemap; - if (longtics || gameversion > exe_doom_1_2) + *demo_p++ = gameskill; + *demo_p++ = gameepisode; + *demo_p++ = gamemap; + if (longtics || gameversion > exe_doom_1_2) { - *demo_p++ = deathmatch; - *demo_p++ = respawnparm; - *demo_p++ = fastparm; - *demo_p++ = nomonsters; - *demo_p++ = consoleplayer; + *demo_p++ = deathmatch; + *demo_p++ = respawnparm; + *demo_p++ = fastparm; + *demo_p++ = nomonsters; + *demo_p++ = consoleplayer; } - - for (i=0 ; i= 0 && version <= 4) - { - return "v1.0/v1.1/v1.2"; - } - else - { - M_snprintf(resultbuf, sizeof(resultbuf), - "%i.%i (unknown)", version / 100, version % 100); - return resultbuf; - } + timingdemo = true; + singletics = true; + + defdemoname = name; + gameaction = ga_playdemo; } -void G_DoPlayDemo (void) +/* g_check_demo_status + * + * Called after a death or level completion to allow demos to be cleaned up + * Returns true if a new demo loop action will take place + */ + +boolean g_check_demo_status(void) { - skill_t skill; - int i, lumpnum, episode, map; - int demoversion; - boolean olddemo = false; + int endtime; - lumpnum = W_GetNumForName(defdemoname); - gameaction = ga_nothing; - demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC); - demo_p = demobuffer; + if (timingdemo) + { + float fps; + int realtics; - demoversion = *demo_p++; + endtime = i_get_time(); + realtics = endtime - starttime; + fps = ((float)gametic * TICRATE) / realtics; - if (demoversion >= 0 && demoversion <= 4) - { - olddemo = true; - demo_p--; - } + /* Prevent recursive calls */ - longtics = false; + timingdemo = false; + demoplayback = false; - // Longtics demos use the modified format that is generated by cph's - // hacked "v1.91" doom exe. This is a non-vanilla extension. - if (D_NonVanillaPlayback(demoversion == DOOM_191_VERSION, lumpnum, - "Doom 1.91 demo format")) - { - longtics = true; + i_error("timed %i gametics in %i realtics (%f fps)", gametic, realtics, + fps); } - else if (demoversion != G_VanillaVersionCode() && - !(gameversion <= exe_doom_1_2 && olddemo)) + + if (demoplayback) { - const char *message = "Demo is from a different game version!\n" - "(read %i, should be %i)\n" - "\n" - "*** You may need to upgrade your version " - "of Doom to v1.9. ***\n" - " See: https://www.doomworld.com/classicdoom" - "/info/patches.php\n" - " This appears to be %s."; + w_release_lump_name(defdemoname); + demoplayback = false; + netdemo = false; + netgame = false; + deathmatch = false; + playeringame[1] = playeringame[2] = playeringame[3] = 0; + respawnparm = false; + fastparm = false; + nomonsters = false; + consoleplayer = 0; - I_Error(message, demoversion, G_VanillaVersionCode(), - DemoVersionDescription(demoversion)); - } + if (singledemo) + i_quit(); + else + d_advance_demo(); - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - if (!olddemo) - { - deathmatch = *demo_p++; - respawnparm = *demo_p++; - fastparm = *demo_p++; - nomonsters = *demo_p++; - consoleplayer = *demo_p++; - } - else - { - deathmatch = 0; - respawnparm = 0; - fastparm = 0; - nomonsters = 0; - consoleplayer = 0; + return true; } - - - for (i=0 ; i 0 - || M_CheckParm("-netdemo") > 0) + if (demorecording) { - netgame = true; - netdemo = true; + *demo_p++ = DEMOMARKER; + m_write_file(demoname, demobuffer, demo_p - demobuffer); + z_free(demobuffer); + demorecording = false; + i_error("Demo %s recorded", demoname); } - // don't spend a lot of time in loadlevel - precache = false; - G_InitNew (skill, episode, map); - precache = true; - starttime = I_GetTime (); - - usergame = false; - demoplayback = true; -} - -// -// G_TimeDemo -// -void G_TimeDemo (char* name) -{ - //! - // @category video - // @vanilla - // - // Disable rendering the screen entirely. - // - - nodrawers = M_CheckParm ("-nodraw"); - - timingdemo = true; - singletics = true; - - defdemoname = name; - gameaction = ga_playdemo; -} - - -/* -=================== -= -= G_CheckDemoStatus -= -= Called after a death or level completion to allow demos to be cleaned up -= Returns true if a new demo loop action will take place -=================== -*/ - -boolean G_CheckDemoStatus (void) -{ - int endtime; - - if (timingdemo) - { - float fps; - int realtics; - - endtime = I_GetTime (); - realtics = endtime - starttime; - fps = ((float) gametic * TICRATE) / realtics; - - // Prevent recursive calls - timingdemo = false; - demoplayback = false; - - I_Error ("timed %i gametics in %i realtics (%f fps)", - gametic, realtics, fps); - } - - if (demoplayback) - { - W_ReleaseLumpName(defdemoname); - demoplayback = false; - netdemo = false; - netgame = false; - deathmatch = false; - playeringame[1] = playeringame[2] = playeringame[3] = 0; - respawnparm = false; - fastparm = false; - nomonsters = false; - consoleplayer = 0; - - if (singledemo) - I_Quit (); - else - D_AdvanceDemo (); - - return true; - } - - if (demorecording) - { - *demo_p++ = DEMOMARKER; - M_WriteFile (demoname, demobuffer, demo_p - demobuffer); - Z_Free (demobuffer); - demorecording = false; - I_Error ("Demo %s recorded",demoname); - } - - return false; -} - - - + return false; +} diff --git a/games/NXDoom/src/doom/g_game.h b/games/NXDoom/src/doom/g_game.h index 1e8729d18f2..80c3fe2ee2e 100644 --- a/games/NXDoom/src/doom/g_game.h +++ b/games/NXDoom/src/doom/g_game.h @@ -1,88 +1,105 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Duh. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/g_game.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Duh. + * + ****************************************************************************/ #ifndef __G_GAME__ #define __G_GAME__ -#include "doomdef.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_event.h" #include "d_ticcmd.h" +#include "doomdef.h" #include "m_fixed.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern int vanilla_savegame_limit; +extern int vanilla_demo_limit; + +extern fixed_t forwardmove[2]; +extern fixed_t sidemove[2]; + +extern boolean sendpause; -// -// GAME -// -void G_DeathMatchSpawnPlayer (int playernum); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void G_InitNew (skill_t skill, int episode, int map); +/* GAME */ -// Can be called by the startup code or M_Responder. -// A normal game starts at map 1, -// but a warp test can start elsewhere -void G_DeferedInitNew (skill_t skill, int episode, int map); +void g_death_match_spawn_player(int playernum); -void G_DeferedPlayDemo (const char* demo); +void g_init_new(skill_t skill, int episode, int map); -// Can be called by the startup code or M_Responder, -// calls P_SetupLevel or W_EnterWorld. -void G_LoadGame (char* name); +/* Can be called by the startup code or m_responder. + * A normal game starts at map 1, + * but a warp test can start elsewhere + */ -void G_DoLoadGame (void); +void g_deferred_init_new(skill_t skill, int episode, int map); -// Called by M_Responder. -void G_SaveGame (int slot, char* description); +void g_defered_play_demo(const char *demo); -// Only called by startup code. -void G_RecordDemo (const char* name); +/* Can be called by the startup code or m_responder, + * calls p_setup_level or W_EnterWorld. + */ -void G_BeginRecording (void); +void g_load_game(char *name); -void G_PlayDemo (char* name); -void G_TimeDemo (char* name); -boolean G_CheckDemoStatus (void); +void g_do_load_game(void); -void G_ExitLevel (void); -void G_SecretExitLevel (void); +/* Called by m_responder. */ -void G_WorldDone (void); +void g_save_game(int slot, char *description); -// Read current data from inputs and build a player movement command. +/* Only called by startup code. */ -void G_BuildTiccmd (ticcmd_t *cmd, int maketic); +void g_record_demo(const char *name); -void G_Ticker (void); -boolean G_Responder (event_t* ev); +void g_begin_recording(void); -void G_ScreenShot (void); +void g_play_demo(char *name); +void g_time_demo(char *name); +boolean g_check_demo_status(void); -void G_DrawMouseSpeedBox(void); -int G_VanillaVersionCode(void); +void g_exit_level(void); +void g_secret_exit_level(void); -extern int vanilla_savegame_limit; -extern int vanilla_demo_limit; +void g_world_done(void); -extern fixed_t forwardmove[2]; -extern fixed_t sidemove[2]; +/* Read current data from inputs and build a player movement command. */ -extern boolean sendpause; +void g_build_ticcmd(ticcmd_t *cmd, int maketic); + +void g_ticker(void); +boolean g_responder(event_t *ev); +void g_screenshot(void); -#endif +int g_vanilla_version_code(void); +#endif /* __G_GAME__ */ diff --git a/games/NXDoom/src/doom/hu_lib.c b/games/NXDoom/src/doom/hu_lib.c index d32c2004d2e..cfa9623315c 100644 --- a/games/NXDoom/src/doom/hu_lib.c +++ b/games/NXDoom/src/doom/hu_lib.c @@ -1,20 +1,28 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: heads-up text and input code -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/hu_lib.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: heads-up text and input code + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -22,326 +30,289 @@ #include "doomkeys.h" #include "doomstat.h" -#include "v_video.h" #include "i_swap.h" +#include "v_video.h" #include "hu_lib.h" -#include "r_local.h" #include "r_draw.h" +#include "r_local.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* boolean : whether the screen is always erased */ -// boolean : whether the screen is always erased #define noterased viewwindowx +/**************************************************************************** + * Private Functions + ****************************************************************************/ -void HUlib_init(void) -{ -} +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void HUlib_clearTextLine(hu_textline_t* t) +void hu_lib_clear_text(hu_textline_t *t) { - t->len = 0; - t->l[0] = 0; - t->needsupdate = true; + t->len = 0; + t->l[0] = 0; + t->needsupdate = true; } -void -HUlib_initTextLine -( hu_textline_t* t, - int x, - int y, - patch_t** f, - int sc ) +void hu_lib_init_text_line(hu_textline_t *t, int x, int y, patch_t **f, + int sc) { - t->x = x; - t->y = y; - t->f = f; - t->sc = sc; - HUlib_clearTextLine(t); + t->x = x; + t->y = y; + t->f = f; + t->sc = sc; + hu_lib_clear_text(t); } -boolean -HUlib_addCharToTextLine -( hu_textline_t* t, - char ch ) +boolean hu_lib_add_char_to_text_line(hu_textline_t *t, char ch) { - - if (t->len == HU_MAXLINELENGTH) - return false; - else + if (t->len == HU_MAXLINELENGTH) { - t->l[t->len++] = ch; - t->l[t->len] = 0; - t->needsupdate = 4; - return true; + return false; + } + else + { + t->l[t->len++] = ch; + t->l[t->len] = 0; + t->needsupdate = 4; + return true; } - } -boolean HUlib_delCharFromTextLine(hu_textline_t* t) +boolean hu_lib_del_char_from_text_line(hu_textline_t *t) { - - if (!t->len) return false; - else + if (!t->len) { - t->l[--t->len] = 0; - t->needsupdate = 4; - return true; + return false; + } + else + { + t->l[--t->len] = 0; + t->needsupdate = 4; + return true; } - } -void -HUlib_drawTextLine -( hu_textline_t* l, - boolean drawcursor ) +void hu_lib_draw_text_line(hu_textline_t *l, boolean drawcursor) { + int i; + int w; + int x; + unsigned char c; - int i; - int w; - int x; - unsigned char c; + /* draw the new stuff */ - // draw the new stuff - x = l->x; - for (i=0;ilen;i++) + x = l->x; + for (i = 0; i < l->len; i++) { - c = toupper(l->l[i]); - if (c != ' ' - && c >= l->sc - && c <= '_') - { - w = SHORT(l->f[c - l->sc]->width); - if (x+w > SCREENWIDTH) - break; - V_DrawPatchDirect(x, l->y, l->f[c - l->sc]); - x += w; - } - else - { - x += 4; - if (x >= SCREENWIDTH) - break; - } + c = toupper(l->l[i]); + if (c != ' ' && c >= l->sc && c <= '_') + { + w = SHORT(l->f[c - l->sc]->width); + if (x + w > SCREENWIDTH) break; + v_draw_patch_direct(x, l->y, l->f[c - l->sc]); + x += w; + } + else + { + x += 4; + if (x >= SCREENWIDTH) break; + } } - // draw the cursor if requested - if (drawcursor - && x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH) + /* draw the cursor if requested */ + + if (drawcursor && x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH) { - V_DrawPatchDirect(x, l->y, l->f['_' - l->sc]); + v_draw_patch_direct(x, l->y, l->f['_' - l->sc]); } } +/* sorta called by hu_erase and just better darn get things straight */ -// sorta called by HU_Erase and just better darn get things straight -void HUlib_eraseTextLine(hu_textline_t* l) +void hu_lib_erase_text_line(hu_textline_t *l) { - int lh; - int y; - int yoffset; + int lh; + int y; + int yoffset; - // Only erases when NOT in automap and the screen is reduced, - // and the text must either need updating or refreshing - // (because of a recent change back from the automap) + /* Only erases when NOT in automap and the screen is reduced, and the text + * must either need updating or refreshing (because of a recent change back + * from the automap) + */ - if (!automapactive && - viewwindowx && l->needsupdate) + if (!automapactive && viewwindowx && l->needsupdate) { - lh = SHORT(l->f[0]->height) + 1; - for (y=l->y,yoffset=y*SCREENWIDTH ; yy+lh ; y++,yoffset+=SCREENWIDTH) - { - if (y < viewwindowy || y >= viewwindowy + viewheight) - R_VideoErase(yoffset, SCREENWIDTH); // erase entire line - else - { - R_VideoErase(yoffset, viewwindowx); // erase left border - R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); - // erase right border - } - } + lh = SHORT(l->f[0]->height) + 1; + for (y = l->y, yoffset = y * SCREENWIDTH; y < l->y + lh; + y++, yoffset += SCREENWIDTH) + { + if (y < viewwindowy || y >= viewwindowy + viewheight) + r_video_erase(yoffset, SCREENWIDTH); /* erase entire line */ + else + { + r_video_erase(yoffset, viewwindowx); /* erase left border */ + r_video_erase(yoffset + viewwindowx + viewwidth, viewwindowx); + + /* erase right border */ + } + } } - if (l->needsupdate) l->needsupdate--; - + if (l->needsupdate) l->needsupdate--; } -void -HUlib_initSText -( hu_stext_t* s, - int x, - int y, - int h, - patch_t** font, - int startchar, - boolean* on ) +void hu_lib_init_stext(hu_stext_t *s, int x, int y, int h, patch_t **font, + int startchar, boolean *on) { - - int i; - - s->h = h; - s->on = on; - s->laston = true; - s->cl = 0; - for (i=0;il[i], - x, y - i*(SHORT(font[0]->height)+1), - font, startchar); - + int i; + + s->h = h; + s->on = on; + s->laston = true; + s->cl = 0; + for (i = 0; i < h; i++) + hu_lib_init_text_line(&s->l[i], x, y - i * (SHORT(font[0]->height) + 1), + font, startchar); } -void HUlib_addLineToSText(hu_stext_t* s) +void hu_lib_add_line_to_stext(hu_stext_t *s) { + int i; - int i; + /* add a clear line */ - // add a clear line - if (++s->cl == s->h) - s->cl = 0; - HUlib_clearTextLine(&s->l[s->cl]); + if (++s->cl == s->h) s->cl = 0; + hu_lib_clear_text(&s->l[s->cl]); - // everything needs updating - for (i=0 ; ih ; i++) - s->l[i].needsupdate = 4; + /* everything needs updating */ + for (i = 0; i < s->h; i++) + { + s->l[i].needsupdate = 4; + } } -void -HUlib_addMessageToSText -( hu_stext_t* s, - const char* prefix, - const char* msg ) +void hu_lib_add_messsage_to_stext(hu_stext_t *s, const char *prefix, + const char *msg) { - HUlib_addLineToSText(s); - if (prefix) - while (*prefix) - HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++)); + hu_lib_add_line_to_stext(s); - while (*msg) - HUlib_addCharToTextLine(&s->l[s->cl], *(msg++)); + if (prefix) + { + while (*prefix) + { + hu_lib_add_char_to_text_line(&s->l[s->cl], *(prefix++)); + } + } + + while (*msg) + { + hu_lib_add_char_to_text_line(&s->l[s->cl], *(msg++)); + } } -void HUlib_drawSText(hu_stext_t* s) +void hu_lib_draw_stext(hu_stext_t *s) { - int i, idx; - hu_textline_t *l; + int i; + int idx; + hu_textline_t *l; + + if (!*s->on) return; /* if not on, don't draw */ - if (!*s->on) - return; // if not on, don't draw + /* draw everything */ - // draw everything - for (i=0 ; ih ; i++) + for (i = 0; i < s->h; i++) { - idx = s->cl - i; - if (idx < 0) - idx += s->h; // handle queue of lines - - l = &s->l[idx]; - - // need a decision made here on whether to skip the draw - HUlib_drawTextLine(l, false); // no cursor, please - } + idx = s->cl - i; + if (idx < 0) idx += s->h; /* handle queue of lines */ + l = &s->l[idx]; + + /* need a decision made here on whether to skip the draw */ + + hu_lib_draw_text_line(l, false); /* no cursor, please */ + } } -void HUlib_eraseSText(hu_stext_t* s) +void hu_lib_erase_stext(hu_stext_t *s) { + int i; - int i; - - for (i=0 ; ih ; i++) + for (i = 0; i < s->h; i++) { - if (s->laston && !*s->on) - s->l[i].needsupdate = 4; - HUlib_eraseTextLine(&s->l[i]); + if (s->laston && !*s->on) s->l[i].needsupdate = 4; + hu_lib_erase_text_line(&s->l[i]); } - s->laston = *s->on; + s->laston = *s->on; } -void -HUlib_initIText -( hu_itext_t* it, - int x, - int y, - patch_t** font, - int startchar, - boolean* on ) +void hu_lib_init_itext(hu_itext_t *it, int x, int y, patch_t **font, + int startchar, boolean *on) { - it->lm = 0; // default left margin is start of text - it->on = on; - it->laston = true; - HUlib_initTextLine(&it->l, x, y, font, startchar); + it->lm = 0; /* default left margin is start of text */ + it->on = on; + it->laston = true; + hu_lib_init_text_line(&it->l, x, y, font, startchar); } +/* The following deletion routines adhere to the left margin restriction */ -// The following deletion routines adhere to the left margin restriction -void HUlib_delCharFromIText(hu_itext_t* it) +void hu_lib_del_char_from_itext(hu_itext_t *it) { - if (it->l.len != it->lm) - HUlib_delCharFromTextLine(&it->l); + if (it->l.len != it->lm) hu_lib_del_char_from_text_line(&it->l); } -void HUlib_eraseLineFromIText(hu_itext_t* it) -{ - while (it->lm != it->l.len) - HUlib_delCharFromTextLine(&it->l); -} +/* Resets left margin as well */ -// Resets left margin as well -void HUlib_resetIText(hu_itext_t* it) +void hu_lib_reset_itext(hu_itext_t *it) { - it->lm = 0; - HUlib_clearTextLine(&it->l); + it->lm = 0; + hu_lib_clear_text(&it->l); } -void -HUlib_addPrefixToIText -( hu_itext_t* it, - char* str ) -{ - while (*str) - HUlib_addCharToTextLine(&it->l, *(str++)); - it->lm = it->l.len; -} +/* wrapper function for handling general keyed input. + * returns true if it ate the key + */ -// wrapper function for handling general keyed input. -// returns true if it ate the key -boolean -HUlib_keyInIText -( hu_itext_t* it, - unsigned char ch ) +boolean hu_lib_key_in_itext(hu_itext_t *it, unsigned char ch) { - ch = toupper(ch); - - if (ch >= ' ' && ch <= '_') - HUlib_addCharToTextLine(&it->l, (char) ch); - else - if (ch == KEY_BACKSPACE) - HUlib_delCharFromIText(it); - else - if (ch != KEY_ENTER) - return false; // did not eat key + ch = toupper(ch); - return true; // ate the key + if (ch >= ' ' && ch <= '_') + { + hu_lib_add_char_to_text_line(&it->l, (char)ch); + } + else if (ch == KEY_BACKSPACE) + { + hu_lib_del_char_from_itext(it); + } + else if (ch != KEY_ENTER) + { + return false; /* did not eat key */ + } + return true; /* ate the key */ } -void HUlib_drawIText(hu_itext_t* it) +void hu_lib_draw_itext(hu_itext_t *it) { + hu_textline_t *l = &it->l; - hu_textline_t *l = &it->l; - - if (!*it->on) - return; - HUlib_drawTextLine(l, true); // draw the line w/ cursor - + if (!*it->on) return; + hu_lib_draw_text_line(l, true); /* draw the line w/ cursor */ } -void HUlib_eraseIText(hu_itext_t* it) +void hu_lib_erase_itext(hu_itext_t *it) { - if (it->laston && !*it->on) - it->l.needsupdate = 4; - HUlib_eraseTextLine(&it->l); - it->laston = *it->on; + if (it->laston && !*it->on) it->l.needsupdate = 4; + hu_lib_erase_text_line(&it->l); + it->laston = *it->on; } - diff --git a/games/NXDoom/src/doom/hu_lib.h b/games/NXDoom/src/doom/hu_lib.h index ca5eb8d8c81..e9ab12a2427 100644 --- a/games/NXDoom/src/doom/hu_lib.h +++ b/games/NXDoom/src/doom/hu_lib.h @@ -1,182 +1,178 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/hu_lib.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: none + * + ****************************************************************************/ #ifndef __HULIB__ #define __HULIB__ -// We are referring to patches. +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* We are referring to patches. */ + #include "r_defs.h" -// font stuff -#define HU_CHARERASE KEY_BACKSPACE +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* font stuff */ + +#define HU_CHARERASE KEY_BACKSPACE + +#define HU_MAXLINES 4 +#define HU_MAXLINELENGTH 80 + +/**************************************************************************** + * Public Types + ****************************************************************************/ -#define HU_MAXLINES 4 -#define HU_MAXLINELENGTH 80 +/* Typedefs of widgets */ -// -// Typedefs of widgets -// +/* Text Line widget + * (parent of Scrolling Text and Input Text widgets) + */ -// Text Line widget -// (parent of Scrolling Text and Input Text widgets) typedef struct { - // left-justified position of scrolling text window - int x; - int y; - - patch_t** f; // font - int sc; // start character - char l[HU_MAXLINELENGTH+1]; // line of text - int len; // current line length - - // whether this line needs to be udpated - int needsupdate; + /* left-justified position of scrolling text window */ -} hu_textline_t; + int x; + int y; + + patch_t **f; /* font */ + int sc; /* start character */ + char l[HU_MAXLINELENGTH + 1]; /* line of text */ + int len; /* current line length */ + /* whether this line needs to be updated */ + int needsupdate; +} hu_textline_t; + +/* Scrolling Text window widget (child of Text Line widget) */ -// Scrolling Text window widget -// (child of Text Line widget) typedef struct { - hu_textline_t l[HU_MAXLINES]; // text lines to draw - int h; // height in lines - int cl; // current line number + hu_textline_t l[HU_MAXLINES]; /* text lines to draw */ + int h; /* height in lines */ + int cl; /* current line number */ - // pointer to boolean stating whether to update window - boolean* on; - boolean laston; // last value of *->on. + /* pointer to boolean stating whether to update window */ + boolean *on; + boolean laston; /* last value of *->on. */ } hu_stext_t; +/* Input Text Line widget (child of Text Line widget) */ - -// Input Text Line widget -// (child of Text Line widget) typedef struct { - hu_textline_t l; // text line to input on + hu_textline_t l; /* text line to input on */ - // left margin past which I am not to delete characters - int lm; + /* left margin past which I am not to delete characters */ - // pointer to boolean stating whether to update window - boolean* on; - boolean laston; // last value of *->on; + int lm; + /* pointer to boolean stating whether to update window */ + + boolean *on; + boolean laston; /* last value of *->on; */ } hu_itext_t; +/* Widget creation, access, and update routines */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* textline code */ + +/* clear a line of text */ + +void hu_lib_clear_text(hu_textline_t *t); + +void hu_lib_init_text_line(hu_textline_t *t, int x, int y, patch_t **f, + int sc); + +/* returns success */ + +boolean hu_lib_add_char_to_text_line(hu_textline_t *t, char ch); + +/* returns success */ + +boolean hu_lib_del_char_from_text_line(hu_textline_t *t); + +/* draws tline */ -// -// Widget creation, access, and update routines -// +void hu_lib_draw_text_line(hu_textline_t *l, boolean drawcursor); -// initializes heads-up widget library -void HUlib_init(void); +/* erases text line */ -// -// textline code -// +void hu_lib_erase_text_line(hu_textline_t *l); -// clear a line of text -void HUlib_clearTextLine(hu_textline_t *t); +/* Scrolling Text window widget routines */ -void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc); +void hu_lib_init_stext(hu_stext_t *s, int x, int y, int h, patch_t **font, + int startchar, boolean *on); -// returns success -boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); +/* add a new line */ -// returns success -boolean HUlib_delCharFromTextLine(hu_textline_t *t); +void hu_lib_add_line_to_stext(hu_stext_t *s); -// draws tline -void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor); +/* ? */ -// erases text line -void HUlib_eraseTextLine(hu_textline_t *l); +void hu_lib_add_messsage_to_stext(hu_stext_t *s, const char *prefix, + const char *msg); +/* draws stext */ -// -// Scrolling Text window widget routines -// +void hu_lib_draw_stext(hu_stext_t *s); -// ? -void -HUlib_initSText -( hu_stext_t* s, - int x, - int y, - int h, - patch_t** font, - int startchar, - boolean* on ); +/* erases all stext lines */ -// add a new line -void HUlib_addLineToSText(hu_stext_t* s); +void hu_lib_erase_stext(hu_stext_t *s); -// ? -void -HUlib_addMessageToSText -( hu_stext_t* s, - const char* prefix, - const char* msg ); +/* Input Text Line widget routines */ -// draws stext -void HUlib_drawSText(hu_stext_t* s); +void hu_lib_init_itext(hu_itext_t *it, int x, int y, patch_t **font, + int startchar, boolean *on); -// erases all stext lines -void HUlib_eraseSText(hu_stext_t* s); +/* enforces left margin */ -// Input Text Line widget routines -void -HUlib_initIText -( hu_itext_t* it, - int x, - int y, - patch_t** font, - int startchar, - boolean* on ); +void hu_lib_del_char_from_itext(hu_itext_t *it); -// enforces left margin -void HUlib_delCharFromIText(hu_itext_t* it); +/* resets line and left margin */ -// enforces left margin -void HUlib_eraseLineFromIText(hu_itext_t* it); +void hu_lib_reset_itext(hu_itext_t *it); -// resets line and left margin -void HUlib_resetIText(hu_itext_t* it); +/* whether eaten */ -// left of left-margin -void -HUlib_addPrefixToIText -( hu_itext_t* it, - char* str ); +boolean hu_lib_key_in_itext(hu_itext_t *it, unsigned char ch); -// whether eaten -boolean -HUlib_keyInIText -( hu_itext_t* it, - unsigned char ch ); +void hu_lib_draw_itext(hu_itext_t *it); -void HUlib_drawIText(hu_itext_t* it); +/* erases all itext lines */ -// erases all itext lines -void HUlib_eraseIText(hu_itext_t* it); +void hu_lib_erase_itext(hu_itext_t *it); -#endif +#endif /* __HULIB__ */ diff --git a/games/NXDoom/src/doom/hu_stuff.c b/games/NXDoom/src/doom/hu_stuff.c index bb20029649a..9dfd61abc38 100644 --- a/games/NXDoom/src/doom/hu_stuff.c +++ b/games/NXDoom/src/doom/hu_stuff.c @@ -1,20 +1,28 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Heads-up displays -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/hu_stuff.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: Heads-up displays + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -29,679 +37,605 @@ #include "i_swap.h" #include "i_video.h" -#include "hu_stuff.h" #include "hu_lib.h" +#include "hu_stuff.h" #include "m_controls.h" -#include "m_misc.h" #include "m_menu.h" +#include "m_misc.h" #include "w_wad.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "doomstat.h" -// Data. +/* Data. */ + #include "dstrings.h" -#include "sounds.h" -// -// Locally used constants, shortcuts. -// -#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1]) -#define HU_TITLE2 (mapnames_commercial[gamemap-1]) -#define HU_TITLEP (mapnames_commercial[gamemap-1 + 32]) -#define HU_TITLET (mapnames_commercial[gamemap-1 + 64]) -#define HU_TITLE_CHEX (mapnames_chex[(gameepisode-1)*9+gamemap-1]) -#define HU_TITLEHEIGHT 1 -#define HU_TITLEX 0 -#define HU_TITLEY (167 - SHORT(hu_font[0]->height)) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Locally used constants, shortcuts. */ + +#define HU_TITLE (mapnames[(gameepisode - 1) * 9 + gamemap - 1]) +#define HU_TITLE2 (mapnames_commercial[gamemap - 1]) +#define HU_TITLEP (mapnames_commercial[gamemap - 1 + 32]) +#define HU_TITLET (mapnames_commercial[gamemap - 1 + 64]) +#define HU_TITLE_CHEX (mapnames_chex[(gameepisode - 1) * 9 + gamemap - 1]) +#define HU_TITLEHEIGHT 1 +#define HU_TITLEX 0 +#define HU_TITLEY (167 - SHORT(hu_font[0]->height)) + +#define HU_INPUTTOGGLE 't' +#define HU_INPUTX HU_MSGX +#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT * (SHORT(hu_font[0]->height) + 1)) +#define HU_INPUTWIDTH 64 +#define HU_INPUTHEIGHT 1 + +#define QUEUESIZE 128 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static player_t *plr; +static hu_textline_t w_title; +static hu_itext_t w_chat; +static boolean always_off = false; +static char chat_dest[MAXPLAYERS]; +static hu_itext_t w_inputbuffer[MAXPLAYERS]; + +static boolean message_on; +static boolean message_nottobefuckedwith; + +static hu_stext_t w_message; +static int message_counter; -#define HU_INPUTTOGGLE 't' -#define HU_INPUTX HU_MSGX -#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1)) -#define HU_INPUTWIDTH 64 -#define HU_INPUTHEIGHT 1 +static boolean headsupactive = false; +static char chatchars[QUEUESIZE]; +static int head = 0; +static int tail = 0; +/**************************************************************************** + * Public Data + ****************************************************************************/ char *chat_macros[10]; const char *player_names[] = { - HUSTR_PLRGREEN, - HUSTR_PLRINDIGO, - HUSTR_PLRBROWN, - HUSTR_PLRRED + HUSTR_PLRGREEN, + HUSTR_PLRINDIGO, + HUSTR_PLRBROWN, + HUSTR_PLRRED, }; -char chat_char; // remove later. -static player_t* plr; -patch_t* hu_font[HU_FONTSIZE]; -static hu_textline_t w_title; -boolean chat_on; -static hu_itext_t w_chat; -static boolean always_off = false; -static char chat_dest[MAXPLAYERS]; -static hu_itext_t w_inputbuffer[MAXPLAYERS]; - -static boolean message_on; -boolean message_dontfuckwithme; -static boolean message_nottobefuckedwith; - -static hu_stext_t w_message; -static int message_counter; +char chat_char; /* remove later. */ +patch_t *hu_font[HU_FONTSIZE]; +boolean chat_on; +boolean message_dontfuckwithme; -static boolean headsupactive = false; +/* Builtin map names. + * The actual names can be found in DStrings.h. + */ -// -// Builtin map names. -// The actual names can be found in DStrings.h. -// +/* DOOM shareware/registered/retail (Ultimate) names. */ -const char *mapnames[] = // DOOM shareware/registered/retail (Ultimate) names. +const char *mapnames[] = { - - HUSTR_E1M1, - HUSTR_E1M2, - HUSTR_E1M3, - HUSTR_E1M4, - HUSTR_E1M5, - HUSTR_E1M6, - HUSTR_E1M7, - HUSTR_E1M8, - HUSTR_E1M9, - - HUSTR_E2M1, - HUSTR_E2M2, - HUSTR_E2M3, - HUSTR_E2M4, - HUSTR_E2M5, - HUSTR_E2M6, - HUSTR_E2M7, - HUSTR_E2M8, - HUSTR_E2M9, - - HUSTR_E3M1, - HUSTR_E3M2, - HUSTR_E3M3, - HUSTR_E3M4, - HUSTR_E3M5, - HUSTR_E3M6, - HUSTR_E3M7, - HUSTR_E3M8, - HUSTR_E3M9, - - HUSTR_E4M1, - HUSTR_E4M2, - HUSTR_E4M3, - HUSTR_E4M4, - HUSTR_E4M5, - HUSTR_E4M6, - HUSTR_E4M7, - HUSTR_E4M8, - HUSTR_E4M9, - - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL" + HUSTR_E1M1, HUSTR_E1M2, HUSTR_E1M3, HUSTR_E1M4, HUSTR_E1M5, HUSTR_E1M6, + HUSTR_E1M7, HUSTR_E1M8, HUSTR_E1M9, HUSTR_E2M1, HUSTR_E2M2, HUSTR_E2M3, + HUSTR_E2M4, HUSTR_E2M5, HUSTR_E2M6, HUSTR_E2M7, HUSTR_E2M8, HUSTR_E2M9, + HUSTR_E3M1, HUSTR_E3M2, HUSTR_E3M3, HUSTR_E3M4, HUSTR_E3M5, HUSTR_E3M6, + HUSTR_E3M7, HUSTR_E3M8, HUSTR_E3M9, HUSTR_E4M1, HUSTR_E4M2, HUSTR_E4M3, + HUSTR_E4M4, HUSTR_E4M5, HUSTR_E4M6, HUSTR_E4M7, HUSTR_E4M8, HUSTR_E4M9, + "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", + "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", }; -const char *mapnames_chex[] = // Chex Quest names. -{ +/* Chex Quest names. */ - HUSTR_E1M1, - HUSTR_E1M2, - HUSTR_E1M3, - HUSTR_E1M4, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - HUSTR_E1M5, - - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL", - "NEWLEVEL" +const char *mapnames_chex[] = +{ + HUSTR_E1M1, HUSTR_E1M2, HUSTR_E1M3, HUSTR_E1M4, HUSTR_E1M5, + HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, + HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, + HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, + HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, + HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, + HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, HUSTR_E1M5, + HUSTR_E1M5, "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", + "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", "NEWLEVEL", }; -// List of names for levels in commercial IWADs -// (doom2.wad, plutonia.wad, tnt.wad). These are stored in a -// single large array; WADs like pl2.wad have a MAP33, and rely on -// the layout in the Vanilla executable, where it is possible to -// overflow the end of one array into the next. +/* List of names for levels in commercial IWADs + * (doom2.wad, plutonia.wad, tnt.wad). These are stored in a + * single large array; WADs like pl2.wad have a MAP33, and rely on + * the layout in the Vanilla executable, where it is possible to + * overflow the end of one array into the next. + */ const char *mapnames_commercial[] = { - // DOOM 2 map names. - - HUSTR_1, - HUSTR_2, - HUSTR_3, - HUSTR_4, - HUSTR_5, - HUSTR_6, - HUSTR_7, - HUSTR_8, - HUSTR_9, - HUSTR_10, - HUSTR_11, - - HUSTR_12, - HUSTR_13, - HUSTR_14, - HUSTR_15, - HUSTR_16, - HUSTR_17, - HUSTR_18, - HUSTR_19, - HUSTR_20, - - HUSTR_21, - HUSTR_22, - HUSTR_23, - HUSTR_24, - HUSTR_25, - HUSTR_26, - HUSTR_27, - HUSTR_28, - HUSTR_29, - HUSTR_30, - HUSTR_31, - HUSTR_32, - - // Plutonia WAD map names. - - PHUSTR_1, - PHUSTR_2, - PHUSTR_3, - PHUSTR_4, - PHUSTR_5, - PHUSTR_6, - PHUSTR_7, - PHUSTR_8, - PHUSTR_9, - PHUSTR_10, - PHUSTR_11, - - PHUSTR_12, - PHUSTR_13, - PHUSTR_14, - PHUSTR_15, - PHUSTR_16, - PHUSTR_17, - PHUSTR_18, - PHUSTR_19, - PHUSTR_20, - - PHUSTR_21, - PHUSTR_22, - PHUSTR_23, - PHUSTR_24, - PHUSTR_25, - PHUSTR_26, - PHUSTR_27, - PHUSTR_28, - PHUSTR_29, - PHUSTR_30, - PHUSTR_31, - PHUSTR_32, - - // TNT WAD map names. - - THUSTR_1, - THUSTR_2, - THUSTR_3, - THUSTR_4, - THUSTR_5, - THUSTR_6, - THUSTR_7, - THUSTR_8, - THUSTR_9, - THUSTR_10, - THUSTR_11, - - THUSTR_12, - THUSTR_13, - THUSTR_14, - THUSTR_15, - THUSTR_16, - THUSTR_17, - THUSTR_18, - THUSTR_19, - THUSTR_20, - - THUSTR_21, - THUSTR_22, - THUSTR_23, - THUSTR_24, - THUSTR_25, - THUSTR_26, - THUSTR_27, - THUSTR_28, - THUSTR_29, - THUSTR_30, - THUSTR_31, - THUSTR_32, - - // Emulation: TNT maps 33-35 can be warped to and played if they exist - // so include blank names instead of spilling over - "", - "", - "" + HUSTR_1, /* DOOM 2 map names. */ + HUSTR_2, + HUSTR_3, + HUSTR_4, + HUSTR_5, + HUSTR_6, + HUSTR_7, + HUSTR_8, + HUSTR_9, + HUSTR_10, + HUSTR_11, + HUSTR_12, + HUSTR_13, + HUSTR_14, + HUSTR_15, + HUSTR_16, + HUSTR_17, + HUSTR_18, + HUSTR_19, + HUSTR_20, + HUSTR_21, + HUSTR_22, + HUSTR_23, + HUSTR_24, + HUSTR_25, + HUSTR_26, + HUSTR_27, + HUSTR_28, + HUSTR_29, + HUSTR_30, + HUSTR_31, + HUSTR_32, + PHUSTR_1, /* Plutonia WAD map names. */ + PHUSTR_2, + PHUSTR_3, + PHUSTR_4, + PHUSTR_5, + PHUSTR_6, + PHUSTR_7, + PHUSTR_8, + PHUSTR_9, + PHUSTR_10, + PHUSTR_11, + PHUSTR_12, + PHUSTR_13, + PHUSTR_14, + PHUSTR_15, + PHUSTR_16, + PHUSTR_17, + PHUSTR_18, + PHUSTR_19, + PHUSTR_20, + PHUSTR_21, + PHUSTR_22, + PHUSTR_23, + PHUSTR_24, + PHUSTR_25, + PHUSTR_26, + PHUSTR_27, + PHUSTR_28, + PHUSTR_29, + PHUSTR_30, + PHUSTR_31, + PHUSTR_32, + THUSTR_1, /* TNT WAD map names. */ + THUSTR_2, + THUSTR_3, + THUSTR_4, + THUSTR_5, + THUSTR_6, + THUSTR_7, + THUSTR_8, + THUSTR_9, + THUSTR_10, + THUSTR_11, + THUSTR_12, + THUSTR_13, + THUSTR_14, + THUSTR_15, + THUSTR_16, + THUSTR_17, + THUSTR_18, + THUSTR_19, + THUSTR_20, + THUSTR_21, + THUSTR_22, + THUSTR_23, + THUSTR_24, + THUSTR_25, + THUSTR_26, + THUSTR_27, + THUSTR_28, + THUSTR_29, + THUSTR_30, + THUSTR_31, + THUSTR_32, + + /* Emulation: TNT maps 33-35 can be warped to and played if they exist + * so include blank names instead of spilling over + */ + + "", + "", + "", }; -void HU_Init(void) -{ +/**************************************************************************** + * Private Functions + ****************************************************************************/ - int i; - int j; - char buffer[9]; +static void hu_stop(void) +{ + headsupactive = false; +} - // load the heads-up font - j = HU_FONTSTART; - for (i=0;imessage = (HUSTR_MSGU); } + else + { + chatchars[head] = c; + head = (head + 1) & (QUEUESIZE - 1); + } +} + +static void start_chat_input(int dest) +{ + chat_on = true; + hu_lib_reset_itext(&w_chat); + hu_queue_chat_char(HU_BROADCAST); + i_start_text_input(0, 8, SCREENWIDTH, 16); } -void HU_Stop(void) +static void stop_chat_input(void) { - headsupactive = false; + chat_on = false; + i_stop_text_input(); } -void HU_Start(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void hu_init(void) { + uint8_t i; + uint8_t j; + char buffer[9]; - int i; - const char *s; - - if (headsupactive) - HU_Stop(); - - plr = &players[consoleplayer]; - message_on = false; - message_dontfuckwithme = false; - message_nottobefuckedwith = false; - chat_on = false; - - // create the message widget - HUlib_initSText(&w_message, - HU_MSGX, HU_MSGY, HU_MSGHEIGHT, - hu_font, - HU_FONTSTART, &message_on); - - // create the map title widget - HUlib_initTextLine(&w_title, - HU_TITLEX, HU_TITLEY, - hu_font, - HU_FONTSTART); - - switch ( logical_gamemission ) - { - case doom: - s = HU_TITLE; - break; - case doom2: - s = HU_TITLE2; - // Pre-Final Doom compatibility: map33-map35 names don't spill over - if (gameversion <= exe_doom_1_9 && gamemap >= 33) - { - s = ""; - } - break; - case pack_plut: - s = HU_TITLEP; - break; - case pack_tnt: - s = HU_TITLET; - break; - default: - s = "Unknown level"; - break; - } + /* load the heads-up font */ - if (logical_gamemission == doom && gameversion == exe_chex) + j = HU_FONTSTART; + for (i = 0; i < HU_FONTSIZE; i++) { - s = HU_TITLE_CHEX; + snprintf(buffer, 9, "STCFN%.3u", j++); + hu_font[i] = (patch_t *)w_cache_lump_name(buffer, PU_STATIC); } +} - // dehacked substitution to get modified level name +void hu_start(void) +{ + int i; + const char *s; - s = DEH_String(s); - - while (*s) - HUlib_addCharToTextLine(&w_title, *(s++)); + if (headsupactive) hu_stop(); - // create the chat widget - HUlib_initIText(&w_chat, - HU_INPUTX, HU_INPUTY, - hu_font, - HU_FONTSTART, &chat_on); + plr = &players[consoleplayer]; + message_on = false; + message_dontfuckwithme = false; + message_nottobefuckedwith = false; + chat_on = false; - // create the inputbuffer widgets - for (i=0 ; i= 33) + { + s = ""; + } + + break; + case pack_plut: + s = HU_TITLEP; + break; + case pack_tnt: + s = HU_TITLET; + break; + default: + s = "Unknown level"; + break; + } -} + if (logical_gamemission == doom && gameversion == exe_chex) + { + s = HU_TITLE_CHEX; + } -void HU_Erase(void) -{ + /* dehacked substitution to get modified level name */ - HUlib_eraseSText(&w_message); - HUlib_eraseIText(&w_chat); - HUlib_eraseTextLine(&w_title); + s = (s); + while (*s) + { + hu_lib_add_char_to_text_line(&w_title, *(s++)); + } -} + /* create the chat widget */ -void HU_Ticker(void) -{ + hu_lib_init_itext(&w_chat, HU_INPUTX, HU_INPUTY, hu_font, HU_FONTSTART, + &chat_on); - int i, rc; - char c; + /* create the inputbuffer widgets */ - // tick down message counter if message is up - if (message_counter && !--message_counter) + for (i = 0; i < MAXPLAYERS; i++) { - message_on = false; - message_nottobefuckedwith = false; + hu_lib_init_itext(&w_inputbuffer[i], 0, 0, 0, 0, &always_off); } - if (showMessages || message_dontfuckwithme) - { + headsupactive = true; +} - // display message if necessary - if ((plr->message && !message_nottobefuckedwith) - || (plr->message && message_dontfuckwithme)) - { - HUlib_addMessageToSText(&w_message, 0, plr->message); - plr->message = 0; - message_on = true; - message_counter = HU_MSGTIMEOUT; - message_nottobefuckedwith = message_dontfuckwithme; - message_dontfuckwithme = 0; - } - - } // else message_on = false; - - // check for incoming chat characters - if (netgame) - { - for (i=0 ; i exe_doom_1_2) - S_StartSound(0, sfx_tink); - } - HUlib_resetIText(&w_inputbuffer[i]); - } - } - players[i].cmd.chatchar = 0; - } - } - } +void hu_drawer(void) +{ + hu_lib_draw_stext(&w_message); + hu_lib_draw_itext(&w_chat); + if (automapactive) hu_lib_draw_text_line(&w_title, false); +} +void hu_erase(void) +{ + hu_lib_erase_stext(&w_message); + hu_lib_erase_itext(&w_chat); + hu_lib_erase_text_line(&w_title); } -#define QUEUESIZE 128 +void hu_ticker(void) +{ + int i; + int rc; + char c; -static char chatchars[QUEUESIZE]; -static int head = 0; -static int tail = 0; + /* tick down message counter if message is up */ + if (message_counter && !--message_counter) + { + message_on = false; + message_nottobefuckedwith = false; + } -void HU_queueChatChar(char c) -{ - if (((head + 1) & (QUEUESIZE-1)) == tail) + if (g_show_messages || message_dontfuckwithme) { - plr->message = DEH_String(HUSTR_MSGU); + /* display message if necessary */ + + if ((plr->message && !message_nottobefuckedwith) || + (plr->message && message_dontfuckwithme)) + { + hu_lib_add_messsage_to_stext(&w_message, 0, plr->message); + plr->message = 0; + message_on = true; + message_counter = HU_MSGTIMEOUT; + message_nottobefuckedwith = message_dontfuckwithme; + message_dontfuckwithme = 0; + } } - else + + /* check for incoming chat characters */ + + if (netgame) { - chatchars[head] = c; - head = (head + 1) & (QUEUESIZE-1); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; + if (i != consoleplayer && (c = players[i].cmd.chatchar)) + { + if (c <= HU_BROADCAST) + chat_dest[i] = c; + else + { + rc = hu_lib_key_in_itext(&w_inputbuffer[i], c); + if (rc && c == KEY_ENTER) + { + if (w_inputbuffer[i].l.len && + (chat_dest[i] == consoleplayer + 1 || + chat_dest[i] == HU_BROADCAST)) + { + hu_lib_add_messsage_to_stext(&w_message, + (player_names[i]), + w_inputbuffer[i].l.l); + + message_nottobefuckedwith = true; + message_on = true; + message_counter = HU_MSGTIMEOUT; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gamemode == commercial) + s_start_sound(0, SFX_RADIO); + else if (gameversion > exe_doom_1_2) + s_start_sound(0, SFX_TINK); +#endif + } + + hu_lib_reset_itext(&w_inputbuffer[i]); + } + } + + players[i].cmd.chatchar = 0; + } + } } } -char HU_dequeueChatChar(void) +char hu_dequeue_chat_char(void) { - char c; + char c; - if (head != tail) + if (head != tail) { - c = chatchars[tail]; - tail = (tail + 1) & (QUEUESIZE-1); + c = chatchars[tail]; + tail = (tail + 1) & (QUEUESIZE - 1); } - else + else { - c = 0; + c = 0; } - return c; + return c; } -static void StartChatInput(int dest) +boolean hu_responder(event_t *ev) { - chat_on = true; - HUlib_resetIText(&w_chat); - HU_queueChatChar(HU_BROADCAST); - - I_StartTextInput(0, 8, SCREENWIDTH, 16); -} + static char lastmessage[HU_MAXLINELENGTH + 1]; + const char *macromessage; + boolean eatkey = false; + static boolean altdown = false; + unsigned char c; + int i; + int numplayers; -static void StopChatInput(void) -{ - chat_on = false; - I_StopTextInput(); -} + static int num_nobrainers = 0; -boolean HU_Responder(event_t *ev) -{ + numplayers = 0; + for (i = 0; i < MAXPLAYERS; i++) + numplayers += playeringame[i]; - static char lastmessage[HU_MAXLINELENGTH+1]; - const char *macromessage; - boolean eatkey = false; - static boolean altdown = false; - unsigned char c; - int i; - int numplayers; - - static int num_nobrainers = 0; - - numplayers = 0; - for (i=0 ; idata1 == KEY_RSHIFT) + if (ev->data1 == KEY_RSHIFT) { - return false; + return false; } - else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT) + else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT) { - altdown = ev->type == ev_keydown; - return false; + altdown = ev->type == ev_keydown; + return false; } - if (ev->type != ev_keydown) - return false; + if (ev->type != ev_keydown) return false; - if (!chat_on) + if (!chat_on) { - if (ev->data1 == key_message_refresh) - { - message_on = true; - message_counter = HU_MSGTIMEOUT; - eatkey = true; - } - else if (netgame && ev->data2 == key_multi_msg) - { - eatkey = true; - StartChatInput(HU_BROADCAST); - } - else if (netgame && numplayers > 2) - { - for (i=0; idata2 == key_multi_msgplayer[i]) - { - if (playeringame[i] && i!=consoleplayer) - { - eatkey = true; - StartChatInput(i + 1); - break; - } - else if (i == consoleplayer) - { - num_nobrainers++; - if (num_nobrainers < 3) - plr->message = DEH_String(HUSTR_TALKTOSELF1); - else if (num_nobrainers < 6) - plr->message = DEH_String(HUSTR_TALKTOSELF2); - else if (num_nobrainers < 9) - plr->message = DEH_String(HUSTR_TALKTOSELF3); - else if (num_nobrainers < 32) - plr->message = DEH_String(HUSTR_TALKTOSELF4); - else - plr->message = DEH_String(HUSTR_TALKTOSELF5); - } - } - } - } + if (ev->data1 == key_message_refresh) + { + message_on = true; + message_counter = HU_MSGTIMEOUT; + eatkey = true; + } + else if (netgame && ev->data2 == key_multi_msg) + { + eatkey = true; + start_chat_input(HU_BROADCAST); + } + else if (netgame && numplayers > 2) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (ev->data2 == key_multi_msgplayer[i]) + { + if (playeringame[i] && i != consoleplayer) + { + eatkey = true; + start_chat_input(i + 1); + break; + } + else if (i == consoleplayer) + { + num_nobrainers++; + if (num_nobrainers < 3) + plr->message = (HUSTR_TALKTOSELF1); + else if (num_nobrainers < 6) + plr->message = (HUSTR_TALKTOSELF2); + else if (num_nobrainers < 9) + plr->message = (HUSTR_TALKTOSELF3); + else if (num_nobrainers < 32) + plr->message = (HUSTR_TALKTOSELF4); + else + plr->message = (HUSTR_TALKTOSELF5); + } + } + } + } } - else + else { - // send a macro - if (altdown) - { - c = ev->data1 - '0'; - if (c > 9) - return false; - // fprintf(stderr, "got here\n"); - macromessage = chat_macros[c]; - - // kill last message with a '\n' - HU_queueChatChar(KEY_ENTER); // DEBUG!!! - - // send the macro message - while (*macromessage) - HU_queueChatChar(*macromessage++); - HU_queueChatChar(KEY_ENTER); - - // leave chat mode and notify that it was sent - StopChatInput(); - M_StringCopy(lastmessage, chat_macros[c], sizeof(lastmessage)); - plr->message = lastmessage; - eatkey = true; - } - else - { - c = ev->data3; - - eatkey = HUlib_keyInIText(&w_chat, c); - if (eatkey) - { - // static unsigned char buf[20]; // DEBUG - HU_queueChatChar(c); - - // M_snprintf(buf, sizeof(buf), "KEY: %d => %d", ev->data1, c); - // plr->message = buf; - } - if (c == KEY_ENTER) - { - StopChatInput(); - if (w_chat.l.len) + /* send a macro */ + + if (altdown) + { + c = ev->data1 - '0'; + if (c > 9) return false; + macromessage = chat_macros[c]; + + /* kill last message with a '\n' */ + + hu_queue_chat_char(KEY_ENTER); /* DEBUG!!! */ + + /* send the macro message */ + + while (*macromessage) + { + hu_queue_chat_char(*macromessage++); + } + + hu_queue_chat_char(KEY_ENTER); + + /* leave chat mode and notify that it was sent */ + + stop_chat_input(); + m_str_copy(lastmessage, chat_macros[c], sizeof(lastmessage)); + plr->message = lastmessage; + eatkey = true; + } + else + { + c = ev->data3; + + eatkey = hu_lib_key_in_itext(&w_chat, c); + if (eatkey) + { + hu_queue_chat_char(c); + } + + if (c == KEY_ENTER) + { + stop_chat_input(); + if (w_chat.l.len) { - M_StringCopy(lastmessage, w_chat.l.l, sizeof(lastmessage)); - plr->message = lastmessage; + m_str_copy(lastmessage, w_chat.l.l, sizeof(lastmessage)); + plr->message = lastmessage; } - } - else if (c == KEY_ESCAPE) - { - StopChatInput(); } - } + else if (c == KEY_ESCAPE) + { + stop_chat_input(); + } + } } - return eatkey; + return eatkey; } diff --git a/games/NXDoom/src/doom/hu_stuff.h b/games/NXDoom/src/doom/hu_stuff.h index c5757af6717..646a916c245 100644 --- a/games/NXDoom/src/doom/hu_stuff.h +++ b/games/NXDoom/src/doom/hu_stuff.h @@ -1,58 +1,60 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Head up display -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/hu_stuff.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: Head up display + * + ****************************************************************************/ #ifndef __HU_STUFF_H__ #define __HU_STUFF_H__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_event.h" #include "v_patch.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// -// Globally visible constants. -// -#define HU_FONTSTART '!' // the first font characters -#define HU_FONTEND '_' // the last font characters - -// Calculate # of glyphs in font. -#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) +/* Globally visible constants. */ -#define HU_BROADCAST 5 +#define HU_FONTSTART '!' /* the first font characters */ +#define HU_FONTEND '_' /* the last font characters */ -#define HU_MSGX 0 -#define HU_MSGY 0 -#define HU_MSGWIDTH 64 // in characters -#define HU_MSGHEIGHT 1 // in lines +/* Calculate # of glyphs in font. */ -#define HU_MSGTIMEOUT (4*TICRATE) +#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) -// -// HEADS UP TEXT -// +#define HU_BROADCAST 5 -void HU_Init(void); -void HU_Start(void); +#define HU_MSGX 0 +#define HU_MSGY 0 +#define HU_MSGWIDTH 64 /* in characters */ +#define HU_MSGHEIGHT 1 /* in lines */ -boolean HU_Responder(event_t* ev); +#define HU_MSGTIMEOUT (4 * TICRATE) -void HU_Ticker(void); -void HU_Drawer(void); -char HU_dequeueChatChar(void); -void HU_Erase(void); +/**************************************************************************** + * Public Data + ****************************************************************************/ extern const char *player_names[4]; extern char *chat_macros[10]; @@ -63,6 +65,20 @@ extern boolean message_dontfuckwithme; extern boolean chat_on; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* HEADS UP TEXT */ + +void hu_init(void); +void hu_start(void); + +boolean hu_responder(event_t *ev); -#endif +void hu_ticker(void); +void hu_drawer(void); +char hu_dequeue_chat_char(void); +void hu_erase(void); +#endif /* __HU_STUFF_H__ */ diff --git a/games/NXDoom/src/doom/info.c b/games/NXDoom/src/doom/info.c index 11ea1abf7c9..24cc869378f 100644 --- a/games/NXDoom/src/doom/info.c +++ b/games/NXDoom/src/doom/info.c @@ -1,4662 +1,5356 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Thing frame/state LUT, -// generated by multigen utilitiy. -// This one is the original DOOM version, preserved. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/info.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Thing frame/state LUT, generated by multigen utility. + * This one is the original DOOM version, preserved. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include -// Data. -#include "sounds.h" #include "m_fixed.h" +#include "sounds.h" #include "info.h" #include "p_mobj.h" -const char *sprnames[] = { - "TROO","SHTG","PUNG","PISG","PISF","SHTF","SHT2","CHGG","CHGF","MISG", - "MISF","SAWG","PLSG","PLSF","BFGG","BFGF","BLUD","PUFF","BAL1","BAL2", - "PLSS","PLSE","MISL","BFS1","BFE1","BFE2","TFOG","IFOG","PLAY","POSS", - "SPOS","VILE","FIRE","FATB","FBXP","SKEL","MANF","FATT","CPOS","SARG", - "HEAD","BAL7","BOSS","BOS2","SKUL","SPID","BSPI","APLS","APBX","CYBR", - "PAIN","SSWV","KEEN","BBRN","BOSF","ARM1","ARM2","BAR1","BEXP","FCAN", - "BON1","BON2","BKEY","RKEY","YKEY","BSKU","RSKU","YSKU","STIM","MEDI", - "SOUL","PINV","PSTR","PINS","MEGA","SUIT","PMAP","PVIS","CLIP","AMMO", - "ROCK","BROK","CELL","CELP","SHEL","SBOX","BPAK","BFUG","MGUN","CSAW", - "LAUN","PLAS","SHOT","SGN2","COLU","SMT2","GOR1","POL2","POL5","POL4", - "POL3","POL1","POL6","GOR2","GOR3","GOR4","GOR5","SMIT","COL1","COL2", - "COL3","COL4","CAND","CBRA","COL6","TRE1","TRE2","ELEC","CEYE","FSKU", - "COL5","TBLU","TGRN","TRED","SMBT","SMGT","SMRT","HDB1","HDB2","HDB3", - "HDB4","HDB5","HDB6","POB1","POB2","BRS1","TLMP","TLP2", NULL +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if 0 + +/* Using misc1 & misc2 */ + +#define STATE_ENTRY(s, f, t, a, ns) \ + { \ + .sprite = (s), \ + .frame = (f), \ + .tics = (t), \ + .action = {(a)}, \ + .nextstate = (ns), \ + .misc1 = 0, \ + .misc2 = 0, \ + } +#else + +/* No misc1 & misc2 members */ + +#define STATE_ENTRY(s, f, t, a, ns) \ + { \ + .sprite = (s), \ + .frame = (f), \ + .tics = (t), \ + .action = {(a)}, \ + .nextstate = (ns), \ + } +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const char *sprnames[] = +{ + "TROO", "SHTG", "PUNG", "PISG", "PISF", "SHTF", "SHT2", "CHGG", "CHGF", + "MISG", "MISF", "SAWG", "PLSG", "PLSF", "BFGG", "BFGF", "BLUD", "PUFF", + "BAL1", "BAL2", "PLSS", "PLSE", "MISL", "BFS1", "BFE1", "BFE2", "TFOG", + "IFOG", "PLAY", "POSS", "SPOS", "VILE", "FIRE", "FATB", "FBXP", "SKEL", + "MANF", "FATT", "CPOS", "SARG", "HEAD", "BAL7", "BOSS", "BOS2", "SKUL", + "SPID", "BSPI", "APLS", "APBX", "CYBR", "PAIN", "SSWV", "KEEN", "BBRN", + "BOSF", "ARM1", "ARM2", "BAR1", "BEXP", "FCAN", "BON1", "BON2", "BKEY", + "RKEY", "YKEY", "BSKU", "RSKU", "YSKU", "STIM", "MEDI", "SOUL", "PINV", + "PSTR", "PINS", "MEGA", "SUIT", "PMAP", "PVIS", "CLIP", "AMMO", "ROCK", + "BROK", "CELL", "CELP", "SHEL", "SBOX", "BPAK", "BFUG", "MGUN", "CSAW", + "LAUN", "PLAS", "SHOT", "SGN2", "COLU", "SMT2", "GOR1", "POL2", "POL5", + "POL4", "POL3", "POL1", "POL6", "GOR2", "GOR3", "GOR4", "GOR5", "SMIT", + "COL1", "COL2", "COL3", "COL4", "CAND", "CBRA", "COL6", "TRE1", "TRE2", + "ELEC", "CEYE", "FSKU", "COL5", "TBLU", "TGRN", "TRED", "SMBT", "SMGT", + "SMRT", "HDB1", "HDB2", "HDB3", "HDB4", "HDB5", "HDB6", "POB1", "POB2", + "BRS1", "TLMP", "TLP2", NULL, }; - -// Doesn't work with g++, needs actionf_p1 -void A_Light0(); -void A_WeaponReady(); -void A_Lower(); -void A_Raise(); -void A_Punch(); -void A_ReFire(); -void A_FirePistol(); -void A_Light1(); -void A_FireShotgun(); -void A_Light2(); -void A_FireShotgun2(); -void A_CheckReload(); -void A_OpenShotgun2(); -void A_LoadShotgun2(); -void A_CloseShotgun2(); -void A_FireCGun(); -void A_GunFlash(); -void A_FireMissile(); -void A_Saw(); -void A_FirePlasma(); -void A_BFGsound(); -void A_FireBFG(); -void A_BFGSpray(); -void A_Explode(); -void A_Pain(); -void A_PlayerScream(); -void A_Fall(); -void A_XScream(); -void A_Look(); -void A_Chase(); -void A_FaceTarget(); -void A_PosAttack(); -void A_Scream(); -void A_SPosAttack(); -void A_VileChase(); -void A_VileStart(); -void A_VileTarget(); -void A_VileAttack(); -void A_StartFire(); -void A_Fire(); -void A_FireCrackle(); -void A_Tracer(); -void A_SkelWhoosh(); -void A_SkelFist(); -void A_SkelMissile(); -void A_FatRaise(); -void A_FatAttack1(); -void A_FatAttack2(); -void A_FatAttack3(); -void A_BossDeath(); -void A_CPosAttack(); -void A_CPosRefire(); -void A_TroopAttack(); -void A_SargAttack(); -void A_HeadAttack(); -void A_BruisAttack(); -void A_SkullAttack(); -void A_Metal(); -void A_SpidRefire(); -void A_BabyMetal(); -void A_BspiAttack(); -void A_Hoof(); -void A_CyberAttack(); -void A_PainAttack(); -void A_PainDie(); -void A_KeenDie(); -void A_BrainPain(); -void A_BrainScream(); -void A_BrainDie(); -void A_BrainAwake(); -void A_BrainSpit(); -void A_SpawnSound(); -void A_SpawnFly(); -void A_BrainExplode(); - - -state_t states[NUMSTATES] = { - {SPR_TROO,0,-1,{NULL},S_NULL,0,0}, // S_NULL - {SPR_SHTG,4,0,{A_Light0},S_NULL,0,0}, // S_LIGHTDONE - {SPR_PUNG,0,1,{A_WeaponReady},S_PUNCH,0,0}, // S_PUNCH - {SPR_PUNG,0,1,{A_Lower},S_PUNCHDOWN,0,0}, // S_PUNCHDOWN - {SPR_PUNG,0,1,{A_Raise},S_PUNCHUP,0,0}, // S_PUNCHUP - {SPR_PUNG,1,4,{NULL},S_PUNCH2,0,0}, // S_PUNCH1 - {SPR_PUNG,2,4,{A_Punch},S_PUNCH3,0,0}, // S_PUNCH2 - {SPR_PUNG,3,5,{NULL},S_PUNCH4,0,0}, // S_PUNCH3 - {SPR_PUNG,2,4,{NULL},S_PUNCH5,0,0}, // S_PUNCH4 - {SPR_PUNG,1,5,{A_ReFire},S_PUNCH,0,0}, // S_PUNCH5 - {SPR_PISG,0,1,{A_WeaponReady},S_PISTOL,0,0},// S_PISTOL - {SPR_PISG,0,1,{A_Lower},S_PISTOLDOWN,0,0}, // S_PISTOLDOWN - {SPR_PISG,0,1,{A_Raise},S_PISTOLUP,0,0}, // S_PISTOLUP - {SPR_PISG,0,4,{NULL},S_PISTOL2,0,0}, // S_PISTOL1 - {SPR_PISG,1,6,{A_FirePistol},S_PISTOL3,0,0},// S_PISTOL2 - {SPR_PISG,2,4,{NULL},S_PISTOL4,0,0}, // S_PISTOL3 - {SPR_PISG,1,5,{A_ReFire},S_PISTOL,0,0}, // S_PISTOL4 - {SPR_PISF,32768,7,{A_Light1},S_LIGHTDONE,0,0}, // S_PISTOLFLASH - {SPR_SHTG,0,1,{A_WeaponReady},S_SGUN,0,0}, // S_SGUN - {SPR_SHTG,0,1,{A_Lower},S_SGUNDOWN,0,0}, // S_SGUNDOWN - {SPR_SHTG,0,1,{A_Raise},S_SGUNUP,0,0}, // S_SGUNUP - {SPR_SHTG,0,3,{NULL},S_SGUN2,0,0}, // S_SGUN1 - {SPR_SHTG,0,7,{A_FireShotgun},S_SGUN3,0,0}, // S_SGUN2 - {SPR_SHTG,1,5,{NULL},S_SGUN4,0,0}, // S_SGUN3 - {SPR_SHTG,2,5,{NULL},S_SGUN5,0,0}, // S_SGUN4 - {SPR_SHTG,3,4,{NULL},S_SGUN6,0,0}, // S_SGUN5 - {SPR_SHTG,2,5,{NULL},S_SGUN7,0,0}, // S_SGUN6 - {SPR_SHTG,1,5,{NULL},S_SGUN8,0,0}, // S_SGUN7 - {SPR_SHTG,0,3,{NULL},S_SGUN9,0,0}, // S_SGUN8 - {SPR_SHTG,0,7,{A_ReFire},S_SGUN,0,0}, // S_SGUN9 - {SPR_SHTF,32768,4,{A_Light1},S_SGUNFLASH2,0,0}, // S_SGUNFLASH1 - {SPR_SHTF,32769,3,{A_Light2},S_LIGHTDONE,0,0}, // S_SGUNFLASH2 - {SPR_SHT2,0,1,{A_WeaponReady},S_DSGUN,0,0}, // S_DSGUN - {SPR_SHT2,0,1,{A_Lower},S_DSGUNDOWN,0,0}, // S_DSGUNDOWN - {SPR_SHT2,0,1,{A_Raise},S_DSGUNUP,0,0}, // S_DSGUNUP - {SPR_SHT2,0,3,{NULL},S_DSGUN2,0,0}, // S_DSGUN1 - {SPR_SHT2,0,7,{A_FireShotgun2},S_DSGUN3,0,0}, // S_DSGUN2 - {SPR_SHT2,1,7,{NULL},S_DSGUN4,0,0}, // S_DSGUN3 - {SPR_SHT2,2,7,{A_CheckReload},S_DSGUN5,0,0}, // S_DSGUN4 - {SPR_SHT2,3,7,{A_OpenShotgun2},S_DSGUN6,0,0}, // S_DSGUN5 - {SPR_SHT2,4,7,{NULL},S_DSGUN7,0,0}, // S_DSGUN6 - {SPR_SHT2,5,7,{A_LoadShotgun2},S_DSGUN8,0,0}, // S_DSGUN7 - {SPR_SHT2,6,6,{NULL},S_DSGUN9,0,0}, // S_DSGUN8 - {SPR_SHT2,7,6,{A_CloseShotgun2},S_DSGUN10,0,0}, // S_DSGUN9 - {SPR_SHT2,0,5,{A_ReFire},S_DSGUN,0,0}, // S_DSGUN10 - {SPR_SHT2,1,7,{NULL},S_DSNR2,0,0}, // S_DSNR1 - {SPR_SHT2,0,3,{NULL},S_DSGUNDOWN,0,0}, // S_DSNR2 - {SPR_SHT2,32776,5,{A_Light1},S_DSGUNFLASH2,0,0}, // S_DSGUNFLASH1 - {SPR_SHT2,32777,4,{A_Light2},S_LIGHTDONE,0,0}, // S_DSGUNFLASH2 - {SPR_CHGG,0,1,{A_WeaponReady},S_CHAIN,0,0}, // S_CHAIN - {SPR_CHGG,0,1,{A_Lower},S_CHAINDOWN,0,0}, // S_CHAINDOWN - {SPR_CHGG,0,1,{A_Raise},S_CHAINUP,0,0}, // S_CHAINUP - {SPR_CHGG,0,4,{A_FireCGun},S_CHAIN2,0,0}, // S_CHAIN1 - {SPR_CHGG,1,4,{A_FireCGun},S_CHAIN3,0,0}, // S_CHAIN2 - {SPR_CHGG,1,0,{A_ReFire},S_CHAIN,0,0}, // S_CHAIN3 - {SPR_CHGF,32768,5,{A_Light1},S_LIGHTDONE,0,0}, // S_CHAINFLASH1 - {SPR_CHGF,32769,5,{A_Light2},S_LIGHTDONE,0,0}, // S_CHAINFLASH2 - {SPR_MISG,0,1,{A_WeaponReady},S_MISSILE,0,0}, // S_MISSILE - {SPR_MISG,0,1,{A_Lower},S_MISSILEDOWN,0,0}, // S_MISSILEDOWN - {SPR_MISG,0,1,{A_Raise},S_MISSILEUP,0,0}, // S_MISSILEUP - {SPR_MISG,1,8,{A_GunFlash},S_MISSILE2,0,0}, // S_MISSILE1 - {SPR_MISG,1,12,{A_FireMissile},S_MISSILE3,0,0}, // S_MISSILE2 - {SPR_MISG,1,0,{A_ReFire},S_MISSILE,0,0}, // S_MISSILE3 - {SPR_MISF,32768,3,{A_Light1},S_MISSILEFLASH2,0,0}, // S_MISSILEFLASH1 - {SPR_MISF,32769,4,{NULL},S_MISSILEFLASH3,0,0}, // S_MISSILEFLASH2 - {SPR_MISF,32770,4,{A_Light2},S_MISSILEFLASH4,0,0}, // S_MISSILEFLASH3 - {SPR_MISF,32771,4,{A_Light2},S_LIGHTDONE,0,0}, // S_MISSILEFLASH4 - {SPR_SAWG,2,4,{A_WeaponReady},S_SAWB,0,0}, // S_SAW - {SPR_SAWG,3,4,{A_WeaponReady},S_SAW,0,0}, // S_SAWB - {SPR_SAWG,2,1,{A_Lower},S_SAWDOWN,0,0}, // S_SAWDOWN - {SPR_SAWG,2,1,{A_Raise},S_SAWUP,0,0}, // S_SAWUP - {SPR_SAWG,0,4,{A_Saw},S_SAW2,0,0}, // S_SAW1 - {SPR_SAWG,1,4,{A_Saw},S_SAW3,0,0}, // S_SAW2 - {SPR_SAWG,1,0,{A_ReFire},S_SAW,0,0}, // S_SAW3 - {SPR_PLSG,0,1,{A_WeaponReady},S_PLASMA,0,0}, // S_PLASMA - {SPR_PLSG,0,1,{A_Lower},S_PLASMADOWN,0,0}, // S_PLASMADOWN - {SPR_PLSG,0,1,{A_Raise},S_PLASMAUP,0,0}, // S_PLASMAUP - {SPR_PLSG,0,3,{A_FirePlasma},S_PLASMA2,0,0}, // S_PLASMA1 - {SPR_PLSG,1,20,{A_ReFire},S_PLASMA,0,0}, // S_PLASMA2 - {SPR_PLSF,32768,4,{A_Light1},S_LIGHTDONE,0,0}, // S_PLASMAFLASH1 - {SPR_PLSF,32769,4,{A_Light1},S_LIGHTDONE,0,0}, // S_PLASMAFLASH2 - {SPR_BFGG,0,1,{A_WeaponReady},S_BFG,0,0}, // S_BFG - {SPR_BFGG,0,1,{A_Lower},S_BFGDOWN,0,0}, // S_BFGDOWN - {SPR_BFGG,0,1,{A_Raise},S_BFGUP,0,0}, // S_BFGUP - {SPR_BFGG,0,20,{A_BFGsound},S_BFG2,0,0}, // S_BFG1 - {SPR_BFGG,1,10,{A_GunFlash},S_BFG3,0,0}, // S_BFG2 - {SPR_BFGG,1,10,{A_FireBFG},S_BFG4,0,0}, // S_BFG3 - {SPR_BFGG,1,20,{A_ReFire},S_BFG,0,0}, // S_BFG4 - {SPR_BFGF,32768,11,{A_Light1},S_BFGFLASH2,0,0}, // S_BFGFLASH1 - {SPR_BFGF,32769,6,{A_Light2},S_LIGHTDONE,0,0}, // S_BFGFLASH2 - {SPR_BLUD,2,8,{NULL},S_BLOOD2,0,0}, // S_BLOOD1 - {SPR_BLUD,1,8,{NULL},S_BLOOD3,0,0}, // S_BLOOD2 - {SPR_BLUD,0,8,{NULL},S_NULL,0,0}, // S_BLOOD3 - {SPR_PUFF,32768,4,{NULL},S_PUFF2,0,0}, // S_PUFF1 - {SPR_PUFF,1,4,{NULL},S_PUFF3,0,0}, // S_PUFF2 - {SPR_PUFF,2,4,{NULL},S_PUFF4,0,0}, // S_PUFF3 - {SPR_PUFF,3,4,{NULL},S_NULL,0,0}, // S_PUFF4 - {SPR_BAL1,32768,4,{NULL},S_TBALL2,0,0}, // S_TBALL1 - {SPR_BAL1,32769,4,{NULL},S_TBALL1,0,0}, // S_TBALL2 - {SPR_BAL1,32770,6,{NULL},S_TBALLX2,0,0}, // S_TBALLX1 - {SPR_BAL1,32771,6,{NULL},S_TBALLX3,0,0}, // S_TBALLX2 - {SPR_BAL1,32772,6,{NULL},S_NULL,0,0}, // S_TBALLX3 - {SPR_BAL2,32768,4,{NULL},S_RBALL2,0,0}, // S_RBALL1 - {SPR_BAL2,32769,4,{NULL},S_RBALL1,0,0}, // S_RBALL2 - {SPR_BAL2,32770,6,{NULL},S_RBALLX2,0,0}, // S_RBALLX1 - {SPR_BAL2,32771,6,{NULL},S_RBALLX3,0,0}, // S_RBALLX2 - {SPR_BAL2,32772,6,{NULL},S_NULL,0,0}, // S_RBALLX3 - {SPR_PLSS,32768,6,{NULL},S_PLASBALL2,0,0}, // S_PLASBALL - {SPR_PLSS,32769,6,{NULL},S_PLASBALL,0,0}, // S_PLASBALL2 - {SPR_PLSE,32768,4,{NULL},S_PLASEXP2,0,0}, // S_PLASEXP - {SPR_PLSE,32769,4,{NULL},S_PLASEXP3,0,0}, // S_PLASEXP2 - {SPR_PLSE,32770,4,{NULL},S_PLASEXP4,0,0}, // S_PLASEXP3 - {SPR_PLSE,32771,4,{NULL},S_PLASEXP5,0,0}, // S_PLASEXP4 - {SPR_PLSE,32772,4,{NULL},S_NULL,0,0}, // S_PLASEXP5 - {SPR_MISL,32768,1,{NULL},S_ROCKET,0,0}, // S_ROCKET - {SPR_BFS1,32768,4,{NULL},S_BFGSHOT2,0,0}, // S_BFGSHOT - {SPR_BFS1,32769,4,{NULL},S_BFGSHOT,0,0}, // S_BFGSHOT2 - {SPR_BFE1,32768,8,{NULL},S_BFGLAND2,0,0}, // S_BFGLAND - {SPR_BFE1,32769,8,{NULL},S_BFGLAND3,0,0}, // S_BFGLAND2 - {SPR_BFE1,32770,8,{A_BFGSpray},S_BFGLAND4,0,0}, // S_BFGLAND3 - {SPR_BFE1,32771,8,{NULL},S_BFGLAND5,0,0}, // S_BFGLAND4 - {SPR_BFE1,32772,8,{NULL},S_BFGLAND6,0,0}, // S_BFGLAND5 - {SPR_BFE1,32773,8,{NULL},S_NULL,0,0}, // S_BFGLAND6 - {SPR_BFE2,32768,8,{NULL},S_BFGEXP2,0,0}, // S_BFGEXP - {SPR_BFE2,32769,8,{NULL},S_BFGEXP3,0,0}, // S_BFGEXP2 - {SPR_BFE2,32770,8,{NULL},S_BFGEXP4,0,0}, // S_BFGEXP3 - {SPR_BFE2,32771,8,{NULL},S_NULL,0,0}, // S_BFGEXP4 - {SPR_MISL,32769,8,{A_Explode},S_EXPLODE2,0,0}, // S_EXPLODE1 - {SPR_MISL,32770,6,{NULL},S_EXPLODE3,0,0}, // S_EXPLODE2 - {SPR_MISL,32771,4,{NULL},S_NULL,0,0}, // S_EXPLODE3 - {SPR_TFOG,32768,6,{NULL},S_TFOG01,0,0}, // S_TFOG - {SPR_TFOG,32769,6,{NULL},S_TFOG02,0,0}, // S_TFOG01 - {SPR_TFOG,32768,6,{NULL},S_TFOG2,0,0}, // S_TFOG02 - {SPR_TFOG,32769,6,{NULL},S_TFOG3,0,0}, // S_TFOG2 - {SPR_TFOG,32770,6,{NULL},S_TFOG4,0,0}, // S_TFOG3 - {SPR_TFOG,32771,6,{NULL},S_TFOG5,0,0}, // S_TFOG4 - {SPR_TFOG,32772,6,{NULL},S_TFOG6,0,0}, // S_TFOG5 - {SPR_TFOG,32773,6,{NULL},S_TFOG7,0,0}, // S_TFOG6 - {SPR_TFOG,32774,6,{NULL},S_TFOG8,0,0}, // S_TFOG7 - {SPR_TFOG,32775,6,{NULL},S_TFOG9,0,0}, // S_TFOG8 - {SPR_TFOG,32776,6,{NULL},S_TFOG10,0,0}, // S_TFOG9 - {SPR_TFOG,32777,6,{NULL},S_NULL,0,0}, // S_TFOG10 - {SPR_IFOG,32768,6,{NULL},S_IFOG01,0,0}, // S_IFOG - {SPR_IFOG,32769,6,{NULL},S_IFOG02,0,0}, // S_IFOG01 - {SPR_IFOG,32768,6,{NULL},S_IFOG2,0,0}, // S_IFOG02 - {SPR_IFOG,32769,6,{NULL},S_IFOG3,0,0}, // S_IFOG2 - {SPR_IFOG,32770,6,{NULL},S_IFOG4,0,0}, // S_IFOG3 - {SPR_IFOG,32771,6,{NULL},S_IFOG5,0,0}, // S_IFOG4 - {SPR_IFOG,32772,6,{NULL},S_NULL,0,0}, // S_IFOG5 - {SPR_PLAY,0,-1,{NULL},S_NULL,0,0}, // S_PLAY - {SPR_PLAY,0,4,{NULL},S_PLAY_RUN2,0,0}, // S_PLAY_RUN1 - {SPR_PLAY,1,4,{NULL},S_PLAY_RUN3,0,0}, // S_PLAY_RUN2 - {SPR_PLAY,2,4,{NULL},S_PLAY_RUN4,0,0}, // S_PLAY_RUN3 - {SPR_PLAY,3,4,{NULL},S_PLAY_RUN1,0,0}, // S_PLAY_RUN4 - {SPR_PLAY,4,12,{NULL},S_PLAY,0,0}, // S_PLAY_ATK1 - {SPR_PLAY,32773,6,{NULL},S_PLAY_ATK1,0,0}, // S_PLAY_ATK2 - {SPR_PLAY,6,4,{NULL},S_PLAY_PAIN2,0,0}, // S_PLAY_PAIN - {SPR_PLAY,6,4,{A_Pain},S_PLAY,0,0}, // S_PLAY_PAIN2 - {SPR_PLAY,7,10,{NULL},S_PLAY_DIE2,0,0}, // S_PLAY_DIE1 - {SPR_PLAY,8,10,{A_PlayerScream},S_PLAY_DIE3,0,0}, // S_PLAY_DIE2 - {SPR_PLAY,9,10,{A_Fall},S_PLAY_DIE4,0,0}, // S_PLAY_DIE3 - {SPR_PLAY,10,10,{NULL},S_PLAY_DIE5,0,0}, // S_PLAY_DIE4 - {SPR_PLAY,11,10,{NULL},S_PLAY_DIE6,0,0}, // S_PLAY_DIE5 - {SPR_PLAY,12,10,{NULL},S_PLAY_DIE7,0,0}, // S_PLAY_DIE6 - {SPR_PLAY,13,-1,{NULL},S_NULL,0,0}, // S_PLAY_DIE7 - {SPR_PLAY,14,5,{NULL},S_PLAY_XDIE2,0,0}, // S_PLAY_XDIE1 - {SPR_PLAY,15,5,{A_XScream},S_PLAY_XDIE3,0,0}, // S_PLAY_XDIE2 - {SPR_PLAY,16,5,{A_Fall},S_PLAY_XDIE4,0,0}, // S_PLAY_XDIE3 - {SPR_PLAY,17,5,{NULL},S_PLAY_XDIE5,0,0}, // S_PLAY_XDIE4 - {SPR_PLAY,18,5,{NULL},S_PLAY_XDIE6,0,0}, // S_PLAY_XDIE5 - {SPR_PLAY,19,5,{NULL},S_PLAY_XDIE7,0,0}, // S_PLAY_XDIE6 - {SPR_PLAY,20,5,{NULL},S_PLAY_XDIE8,0,0}, // S_PLAY_XDIE7 - {SPR_PLAY,21,5,{NULL},S_PLAY_XDIE9,0,0}, // S_PLAY_XDIE8 - {SPR_PLAY,22,-1,{NULL},S_NULL,0,0}, // S_PLAY_XDIE9 - {SPR_POSS,0,10,{A_Look},S_POSS_STND2,0,0}, // S_POSS_STND - {SPR_POSS,1,10,{A_Look},S_POSS_STND,0,0}, // S_POSS_STND2 - {SPR_POSS,0,4,{A_Chase},S_POSS_RUN2,0,0}, // S_POSS_RUN1 - {SPR_POSS,0,4,{A_Chase},S_POSS_RUN3,0,0}, // S_POSS_RUN2 - {SPR_POSS,1,4,{A_Chase},S_POSS_RUN4,0,0}, // S_POSS_RUN3 - {SPR_POSS,1,4,{A_Chase},S_POSS_RUN5,0,0}, // S_POSS_RUN4 - {SPR_POSS,2,4,{A_Chase},S_POSS_RUN6,0,0}, // S_POSS_RUN5 - {SPR_POSS,2,4,{A_Chase},S_POSS_RUN7,0,0}, // S_POSS_RUN6 - {SPR_POSS,3,4,{A_Chase},S_POSS_RUN8,0,0}, // S_POSS_RUN7 - {SPR_POSS,3,4,{A_Chase},S_POSS_RUN1,0,0}, // S_POSS_RUN8 - {SPR_POSS,4,10,{A_FaceTarget},S_POSS_ATK2,0,0}, // S_POSS_ATK1 - {SPR_POSS,5,8,{A_PosAttack},S_POSS_ATK3,0,0}, // S_POSS_ATK2 - {SPR_POSS,4,8,{NULL},S_POSS_RUN1,0,0}, // S_POSS_ATK3 - {SPR_POSS,6,3,{NULL},S_POSS_PAIN2,0,0}, // S_POSS_PAIN - {SPR_POSS,6,3,{A_Pain},S_POSS_RUN1,0,0}, // S_POSS_PAIN2 - {SPR_POSS,7,5,{NULL},S_POSS_DIE2,0,0}, // S_POSS_DIE1 - {SPR_POSS,8,5,{A_Scream},S_POSS_DIE3,0,0}, // S_POSS_DIE2 - {SPR_POSS,9,5,{A_Fall},S_POSS_DIE4,0,0}, // S_POSS_DIE3 - {SPR_POSS,10,5,{NULL},S_POSS_DIE5,0,0}, // S_POSS_DIE4 - {SPR_POSS,11,-1,{NULL},S_NULL,0,0}, // S_POSS_DIE5 - {SPR_POSS,12,5,{NULL},S_POSS_XDIE2,0,0}, // S_POSS_XDIE1 - {SPR_POSS,13,5,{A_XScream},S_POSS_XDIE3,0,0}, // S_POSS_XDIE2 - {SPR_POSS,14,5,{A_Fall},S_POSS_XDIE4,0,0}, // S_POSS_XDIE3 - {SPR_POSS,15,5,{NULL},S_POSS_XDIE5,0,0}, // S_POSS_XDIE4 - {SPR_POSS,16,5,{NULL},S_POSS_XDIE6,0,0}, // S_POSS_XDIE5 - {SPR_POSS,17,5,{NULL},S_POSS_XDIE7,0,0}, // S_POSS_XDIE6 - {SPR_POSS,18,5,{NULL},S_POSS_XDIE8,0,0}, // S_POSS_XDIE7 - {SPR_POSS,19,5,{NULL},S_POSS_XDIE9,0,0}, // S_POSS_XDIE8 - {SPR_POSS,20,-1,{NULL},S_NULL,0,0}, // S_POSS_XDIE9 - {SPR_POSS,10,5,{NULL},S_POSS_RAISE2,0,0}, // S_POSS_RAISE1 - {SPR_POSS,9,5,{NULL},S_POSS_RAISE3,0,0}, // S_POSS_RAISE2 - {SPR_POSS,8,5,{NULL},S_POSS_RAISE4,0,0}, // S_POSS_RAISE3 - {SPR_POSS,7,5,{NULL},S_POSS_RUN1,0,0}, // S_POSS_RAISE4 - {SPR_SPOS,0,10,{A_Look},S_SPOS_STND2,0,0}, // S_SPOS_STND - {SPR_SPOS,1,10,{A_Look},S_SPOS_STND,0,0}, // S_SPOS_STND2 - {SPR_SPOS,0,3,{A_Chase},S_SPOS_RUN2,0,0}, // S_SPOS_RUN1 - {SPR_SPOS,0,3,{A_Chase},S_SPOS_RUN3,0,0}, // S_SPOS_RUN2 - {SPR_SPOS,1,3,{A_Chase},S_SPOS_RUN4,0,0}, // S_SPOS_RUN3 - {SPR_SPOS,1,3,{A_Chase},S_SPOS_RUN5,0,0}, // S_SPOS_RUN4 - {SPR_SPOS,2,3,{A_Chase},S_SPOS_RUN6,0,0}, // S_SPOS_RUN5 - {SPR_SPOS,2,3,{A_Chase},S_SPOS_RUN7,0,0}, // S_SPOS_RUN6 - {SPR_SPOS,3,3,{A_Chase},S_SPOS_RUN8,0,0}, // S_SPOS_RUN7 - {SPR_SPOS,3,3,{A_Chase},S_SPOS_RUN1,0,0}, // S_SPOS_RUN8 - {SPR_SPOS,4,10,{A_FaceTarget},S_SPOS_ATK2,0,0}, // S_SPOS_ATK1 - {SPR_SPOS,32773,10,{A_SPosAttack},S_SPOS_ATK3,0,0}, // S_SPOS_ATK2 - {SPR_SPOS,4,10,{NULL},S_SPOS_RUN1,0,0}, // S_SPOS_ATK3 - {SPR_SPOS,6,3,{NULL},S_SPOS_PAIN2,0,0}, // S_SPOS_PAIN - {SPR_SPOS,6,3,{A_Pain},S_SPOS_RUN1,0,0}, // S_SPOS_PAIN2 - {SPR_SPOS,7,5,{NULL},S_SPOS_DIE2,0,0}, // S_SPOS_DIE1 - {SPR_SPOS,8,5,{A_Scream},S_SPOS_DIE3,0,0}, // S_SPOS_DIE2 - {SPR_SPOS,9,5,{A_Fall},S_SPOS_DIE4,0,0}, // S_SPOS_DIE3 - {SPR_SPOS,10,5,{NULL},S_SPOS_DIE5,0,0}, // S_SPOS_DIE4 - {SPR_SPOS,11,-1,{NULL},S_NULL,0,0}, // S_SPOS_DIE5 - {SPR_SPOS,12,5,{NULL},S_SPOS_XDIE2,0,0}, // S_SPOS_XDIE1 - {SPR_SPOS,13,5,{A_XScream},S_SPOS_XDIE3,0,0}, // S_SPOS_XDIE2 - {SPR_SPOS,14,5,{A_Fall},S_SPOS_XDIE4,0,0}, // S_SPOS_XDIE3 - {SPR_SPOS,15,5,{NULL},S_SPOS_XDIE5,0,0}, // S_SPOS_XDIE4 - {SPR_SPOS,16,5,{NULL},S_SPOS_XDIE6,0,0}, // S_SPOS_XDIE5 - {SPR_SPOS,17,5,{NULL},S_SPOS_XDIE7,0,0}, // S_SPOS_XDIE6 - {SPR_SPOS,18,5,{NULL},S_SPOS_XDIE8,0,0}, // S_SPOS_XDIE7 - {SPR_SPOS,19,5,{NULL},S_SPOS_XDIE9,0,0}, // S_SPOS_XDIE8 - {SPR_SPOS,20,-1,{NULL},S_NULL,0,0}, // S_SPOS_XDIE9 - {SPR_SPOS,11,5,{NULL},S_SPOS_RAISE2,0,0}, // S_SPOS_RAISE1 - {SPR_SPOS,10,5,{NULL},S_SPOS_RAISE3,0,0}, // S_SPOS_RAISE2 - {SPR_SPOS,9,5,{NULL},S_SPOS_RAISE4,0,0}, // S_SPOS_RAISE3 - {SPR_SPOS,8,5,{NULL},S_SPOS_RAISE5,0,0}, // S_SPOS_RAISE4 - {SPR_SPOS,7,5,{NULL},S_SPOS_RUN1,0,0}, // S_SPOS_RAISE5 - {SPR_VILE,0,10,{A_Look},S_VILE_STND2,0,0}, // S_VILE_STND - {SPR_VILE,1,10,{A_Look},S_VILE_STND,0,0}, // S_VILE_STND2 - {SPR_VILE,0,2,{A_VileChase},S_VILE_RUN2,0,0}, // S_VILE_RUN1 - {SPR_VILE,0,2,{A_VileChase},S_VILE_RUN3,0,0}, // S_VILE_RUN2 - {SPR_VILE,1,2,{A_VileChase},S_VILE_RUN4,0,0}, // S_VILE_RUN3 - {SPR_VILE,1,2,{A_VileChase},S_VILE_RUN5,0,0}, // S_VILE_RUN4 - {SPR_VILE,2,2,{A_VileChase},S_VILE_RUN6,0,0}, // S_VILE_RUN5 - {SPR_VILE,2,2,{A_VileChase},S_VILE_RUN7,0,0}, // S_VILE_RUN6 - {SPR_VILE,3,2,{A_VileChase},S_VILE_RUN8,0,0}, // S_VILE_RUN7 - {SPR_VILE,3,2,{A_VileChase},S_VILE_RUN9,0,0}, // S_VILE_RUN8 - {SPR_VILE,4,2,{A_VileChase},S_VILE_RUN10,0,0}, // S_VILE_RUN9 - {SPR_VILE,4,2,{A_VileChase},S_VILE_RUN11,0,0}, // S_VILE_RUN10 - {SPR_VILE,5,2,{A_VileChase},S_VILE_RUN12,0,0}, // S_VILE_RUN11 - {SPR_VILE,5,2,{A_VileChase},S_VILE_RUN1,0,0}, // S_VILE_RUN12 - {SPR_VILE,32774,0,{A_VileStart},S_VILE_ATK2,0,0}, // S_VILE_ATK1 - {SPR_VILE,32774,10,{A_FaceTarget},S_VILE_ATK3,0,0}, // S_VILE_ATK2 - {SPR_VILE,32775,8,{A_VileTarget},S_VILE_ATK4,0,0}, // S_VILE_ATK3 - {SPR_VILE,32776,8,{A_FaceTarget},S_VILE_ATK5,0,0}, // S_VILE_ATK4 - {SPR_VILE,32777,8,{A_FaceTarget},S_VILE_ATK6,0,0}, // S_VILE_ATK5 - {SPR_VILE,32778,8,{A_FaceTarget},S_VILE_ATK7,0,0}, // S_VILE_ATK6 - {SPR_VILE,32779,8,{A_FaceTarget},S_VILE_ATK8,0,0}, // S_VILE_ATK7 - {SPR_VILE,32780,8,{A_FaceTarget},S_VILE_ATK9,0,0}, // S_VILE_ATK8 - {SPR_VILE,32781,8,{A_FaceTarget},S_VILE_ATK10,0,0}, // S_VILE_ATK9 - {SPR_VILE,32782,8,{A_VileAttack},S_VILE_ATK11,0,0}, // S_VILE_ATK10 - {SPR_VILE,32783,20,{NULL},S_VILE_RUN1,0,0}, // S_VILE_ATK11 - {SPR_VILE,32794,10,{NULL},S_VILE_HEAL2,0,0}, // S_VILE_HEAL1 - {SPR_VILE,32795,10,{NULL},S_VILE_HEAL3,0,0}, // S_VILE_HEAL2 - {SPR_VILE,32796,10,{NULL},S_VILE_RUN1,0,0}, // S_VILE_HEAL3 - {SPR_VILE,16,5,{NULL},S_VILE_PAIN2,0,0}, // S_VILE_PAIN - {SPR_VILE,16,5,{A_Pain},S_VILE_RUN1,0,0}, // S_VILE_PAIN2 - {SPR_VILE,16,7,{NULL},S_VILE_DIE2,0,0}, // S_VILE_DIE1 - {SPR_VILE,17,7,{A_Scream},S_VILE_DIE3,0,0}, // S_VILE_DIE2 - {SPR_VILE,18,7,{A_Fall},S_VILE_DIE4,0,0}, // S_VILE_DIE3 - {SPR_VILE,19,7,{NULL},S_VILE_DIE5,0,0}, // S_VILE_DIE4 - {SPR_VILE,20,7,{NULL},S_VILE_DIE6,0,0}, // S_VILE_DIE5 - {SPR_VILE,21,7,{NULL},S_VILE_DIE7,0,0}, // S_VILE_DIE6 - {SPR_VILE,22,7,{NULL},S_VILE_DIE8,0,0}, // S_VILE_DIE7 - {SPR_VILE,23,5,{NULL},S_VILE_DIE9,0,0}, // S_VILE_DIE8 - {SPR_VILE,24,5,{NULL},S_VILE_DIE10,0,0}, // S_VILE_DIE9 - {SPR_VILE,25,-1,{NULL},S_NULL,0,0}, // S_VILE_DIE10 - {SPR_FIRE,32768,2,{A_StartFire},S_FIRE2,0,0}, // S_FIRE1 - {SPR_FIRE,32769,2,{A_Fire},S_FIRE3,0,0}, // S_FIRE2 - {SPR_FIRE,32768,2,{A_Fire},S_FIRE4,0,0}, // S_FIRE3 - {SPR_FIRE,32769,2,{A_Fire},S_FIRE5,0,0}, // S_FIRE4 - {SPR_FIRE,32770,2,{A_FireCrackle},S_FIRE6,0,0}, // S_FIRE5 - {SPR_FIRE,32769,2,{A_Fire},S_FIRE7,0,0}, // S_FIRE6 - {SPR_FIRE,32770,2,{A_Fire},S_FIRE8,0,0}, // S_FIRE7 - {SPR_FIRE,32769,2,{A_Fire},S_FIRE9,0,0}, // S_FIRE8 - {SPR_FIRE,32770,2,{A_Fire},S_FIRE10,0,0}, // S_FIRE9 - {SPR_FIRE,32771,2,{A_Fire},S_FIRE11,0,0}, // S_FIRE10 - {SPR_FIRE,32770,2,{A_Fire},S_FIRE12,0,0}, // S_FIRE11 - {SPR_FIRE,32771,2,{A_Fire},S_FIRE13,0,0}, // S_FIRE12 - {SPR_FIRE,32770,2,{A_Fire},S_FIRE14,0,0}, // S_FIRE13 - {SPR_FIRE,32771,2,{A_Fire},S_FIRE15,0,0}, // S_FIRE14 - {SPR_FIRE,32772,2,{A_Fire},S_FIRE16,0,0}, // S_FIRE15 - {SPR_FIRE,32771,2,{A_Fire},S_FIRE17,0,0}, // S_FIRE16 - {SPR_FIRE,32772,2,{A_Fire},S_FIRE18,0,0}, // S_FIRE17 - {SPR_FIRE,32771,2,{A_Fire},S_FIRE19,0,0}, // S_FIRE18 - {SPR_FIRE,32772,2,{A_FireCrackle},S_FIRE20,0,0}, // S_FIRE19 - {SPR_FIRE,32773,2,{A_Fire},S_FIRE21,0,0}, // S_FIRE20 - {SPR_FIRE,32772,2,{A_Fire},S_FIRE22,0,0}, // S_FIRE21 - {SPR_FIRE,32773,2,{A_Fire},S_FIRE23,0,0}, // S_FIRE22 - {SPR_FIRE,32772,2,{A_Fire},S_FIRE24,0,0}, // S_FIRE23 - {SPR_FIRE,32773,2,{A_Fire},S_FIRE25,0,0}, // S_FIRE24 - {SPR_FIRE,32774,2,{A_Fire},S_FIRE26,0,0}, // S_FIRE25 - {SPR_FIRE,32775,2,{A_Fire},S_FIRE27,0,0}, // S_FIRE26 - {SPR_FIRE,32774,2,{A_Fire},S_FIRE28,0,0}, // S_FIRE27 - {SPR_FIRE,32775,2,{A_Fire},S_FIRE29,0,0}, // S_FIRE28 - {SPR_FIRE,32774,2,{A_Fire},S_FIRE30,0,0}, // S_FIRE29 - {SPR_FIRE,32775,2,{A_Fire},S_NULL,0,0}, // S_FIRE30 - {SPR_PUFF,1,4,{NULL},S_SMOKE2,0,0}, // S_SMOKE1 - {SPR_PUFF,2,4,{NULL},S_SMOKE3,0,0}, // S_SMOKE2 - {SPR_PUFF,1,4,{NULL},S_SMOKE4,0,0}, // S_SMOKE3 - {SPR_PUFF,2,4,{NULL},S_SMOKE5,0,0}, // S_SMOKE4 - {SPR_PUFF,3,4,{NULL},S_NULL,0,0}, // S_SMOKE5 - {SPR_FATB,32768,2,{A_Tracer},S_TRACER2,0,0}, // S_TRACER - {SPR_FATB,32769,2,{A_Tracer},S_TRACER,0,0}, // S_TRACER2 - {SPR_FBXP,32768,8,{NULL},S_TRACEEXP2,0,0}, // S_TRACEEXP1 - {SPR_FBXP,32769,6,{NULL},S_TRACEEXP3,0,0}, // S_TRACEEXP2 - {SPR_FBXP,32770,4,{NULL},S_NULL,0,0}, // S_TRACEEXP3 - {SPR_SKEL,0,10,{A_Look},S_SKEL_STND2,0,0}, // S_SKEL_STND - {SPR_SKEL,1,10,{A_Look},S_SKEL_STND,0,0}, // S_SKEL_STND2 - {SPR_SKEL,0,2,{A_Chase},S_SKEL_RUN2,0,0}, // S_SKEL_RUN1 - {SPR_SKEL,0,2,{A_Chase},S_SKEL_RUN3,0,0}, // S_SKEL_RUN2 - {SPR_SKEL,1,2,{A_Chase},S_SKEL_RUN4,0,0}, // S_SKEL_RUN3 - {SPR_SKEL,1,2,{A_Chase},S_SKEL_RUN5,0,0}, // S_SKEL_RUN4 - {SPR_SKEL,2,2,{A_Chase},S_SKEL_RUN6,0,0}, // S_SKEL_RUN5 - {SPR_SKEL,2,2,{A_Chase},S_SKEL_RUN7,0,0}, // S_SKEL_RUN6 - {SPR_SKEL,3,2,{A_Chase},S_SKEL_RUN8,0,0}, // S_SKEL_RUN7 - {SPR_SKEL,3,2,{A_Chase},S_SKEL_RUN9,0,0}, // S_SKEL_RUN8 - {SPR_SKEL,4,2,{A_Chase},S_SKEL_RUN10,0,0}, // S_SKEL_RUN9 - {SPR_SKEL,4,2,{A_Chase},S_SKEL_RUN11,0,0}, // S_SKEL_RUN10 - {SPR_SKEL,5,2,{A_Chase},S_SKEL_RUN12,0,0}, // S_SKEL_RUN11 - {SPR_SKEL,5,2,{A_Chase},S_SKEL_RUN1,0,0}, // S_SKEL_RUN12 - {SPR_SKEL,6,0,{A_FaceTarget},S_SKEL_FIST2,0,0}, // S_SKEL_FIST1 - {SPR_SKEL,6,6,{A_SkelWhoosh},S_SKEL_FIST3,0,0}, // S_SKEL_FIST2 - {SPR_SKEL,7,6,{A_FaceTarget},S_SKEL_FIST4,0,0}, // S_SKEL_FIST3 - {SPR_SKEL,8,6,{A_SkelFist},S_SKEL_RUN1,0,0}, // S_SKEL_FIST4 - {SPR_SKEL,32777,0,{A_FaceTarget},S_SKEL_MISS2,0,0}, // S_SKEL_MISS1 - {SPR_SKEL,32777,10,{A_FaceTarget},S_SKEL_MISS3,0,0}, // S_SKEL_MISS2 - {SPR_SKEL,10,10,{A_SkelMissile},S_SKEL_MISS4,0,0}, // S_SKEL_MISS3 - {SPR_SKEL,10,10,{A_FaceTarget},S_SKEL_RUN1,0,0}, // S_SKEL_MISS4 - {SPR_SKEL,11,5,{NULL},S_SKEL_PAIN2,0,0}, // S_SKEL_PAIN - {SPR_SKEL,11,5,{A_Pain},S_SKEL_RUN1,0,0}, // S_SKEL_PAIN2 - {SPR_SKEL,11,7,{NULL},S_SKEL_DIE2,0,0}, // S_SKEL_DIE1 - {SPR_SKEL,12,7,{NULL},S_SKEL_DIE3,0,0}, // S_SKEL_DIE2 - {SPR_SKEL,13,7,{A_Scream},S_SKEL_DIE4,0,0}, // S_SKEL_DIE3 - {SPR_SKEL,14,7,{A_Fall},S_SKEL_DIE5,0,0}, // S_SKEL_DIE4 - {SPR_SKEL,15,7,{NULL},S_SKEL_DIE6,0,0}, // S_SKEL_DIE5 - {SPR_SKEL,16,-1,{NULL},S_NULL,0,0}, // S_SKEL_DIE6 - {SPR_SKEL,16,5,{NULL},S_SKEL_RAISE2,0,0}, // S_SKEL_RAISE1 - {SPR_SKEL,15,5,{NULL},S_SKEL_RAISE3,0,0}, // S_SKEL_RAISE2 - {SPR_SKEL,14,5,{NULL},S_SKEL_RAISE4,0,0}, // S_SKEL_RAISE3 - {SPR_SKEL,13,5,{NULL},S_SKEL_RAISE5,0,0}, // S_SKEL_RAISE4 - {SPR_SKEL,12,5,{NULL},S_SKEL_RAISE6,0,0}, // S_SKEL_RAISE5 - {SPR_SKEL,11,5,{NULL},S_SKEL_RUN1,0,0}, // S_SKEL_RAISE6 - {SPR_MANF,32768,4,{NULL},S_FATSHOT2,0,0}, // S_FATSHOT1 - {SPR_MANF,32769,4,{NULL},S_FATSHOT1,0,0}, // S_FATSHOT2 - {SPR_MISL,32769,8,{NULL},S_FATSHOTX2,0,0}, // S_FATSHOTX1 - {SPR_MISL,32770,6,{NULL},S_FATSHOTX3,0,0}, // S_FATSHOTX2 - {SPR_MISL,32771,4,{NULL},S_NULL,0,0}, // S_FATSHOTX3 - {SPR_FATT,0,15,{A_Look},S_FATT_STND2,0,0}, // S_FATT_STND - {SPR_FATT,1,15,{A_Look},S_FATT_STND,0,0}, // S_FATT_STND2 - {SPR_FATT,0,4,{A_Chase},S_FATT_RUN2,0,0}, // S_FATT_RUN1 - {SPR_FATT,0,4,{A_Chase},S_FATT_RUN3,0,0}, // S_FATT_RUN2 - {SPR_FATT,1,4,{A_Chase},S_FATT_RUN4,0,0}, // S_FATT_RUN3 - {SPR_FATT,1,4,{A_Chase},S_FATT_RUN5,0,0}, // S_FATT_RUN4 - {SPR_FATT,2,4,{A_Chase},S_FATT_RUN6,0,0}, // S_FATT_RUN5 - {SPR_FATT,2,4,{A_Chase},S_FATT_RUN7,0,0}, // S_FATT_RUN6 - {SPR_FATT,3,4,{A_Chase},S_FATT_RUN8,0,0}, // S_FATT_RUN7 - {SPR_FATT,3,4,{A_Chase},S_FATT_RUN9,0,0}, // S_FATT_RUN8 - {SPR_FATT,4,4,{A_Chase},S_FATT_RUN10,0,0}, // S_FATT_RUN9 - {SPR_FATT,4,4,{A_Chase},S_FATT_RUN11,0,0}, // S_FATT_RUN10 - {SPR_FATT,5,4,{A_Chase},S_FATT_RUN12,0,0}, // S_FATT_RUN11 - {SPR_FATT,5,4,{A_Chase},S_FATT_RUN1,0,0}, // S_FATT_RUN12 - {SPR_FATT,6,20,{A_FatRaise},S_FATT_ATK2,0,0}, // S_FATT_ATK1 - {SPR_FATT,32775,10,{A_FatAttack1},S_FATT_ATK3,0,0}, // S_FATT_ATK2 - {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK4,0,0}, // S_FATT_ATK3 - {SPR_FATT,6,5,{A_FaceTarget},S_FATT_ATK5,0,0}, // S_FATT_ATK4 - {SPR_FATT,32775,10,{A_FatAttack2},S_FATT_ATK6,0,0}, // S_FATT_ATK5 - {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK7,0,0}, // S_FATT_ATK6 - {SPR_FATT,6,5,{A_FaceTarget},S_FATT_ATK8,0,0}, // S_FATT_ATK7 - {SPR_FATT,32775,10,{A_FatAttack3},S_FATT_ATK9,0,0}, // S_FATT_ATK8 - {SPR_FATT,8,5,{A_FaceTarget},S_FATT_ATK10,0,0}, // S_FATT_ATK9 - {SPR_FATT,6,5,{A_FaceTarget},S_FATT_RUN1,0,0}, // S_FATT_ATK10 - {SPR_FATT,9,3,{NULL},S_FATT_PAIN2,0,0}, // S_FATT_PAIN - {SPR_FATT,9,3,{A_Pain},S_FATT_RUN1,0,0}, // S_FATT_PAIN2 - {SPR_FATT,10,6,{NULL},S_FATT_DIE2,0,0}, // S_FATT_DIE1 - {SPR_FATT,11,6,{A_Scream},S_FATT_DIE3,0,0}, // S_FATT_DIE2 - {SPR_FATT,12,6,{A_Fall},S_FATT_DIE4,0,0}, // S_FATT_DIE3 - {SPR_FATT,13,6,{NULL},S_FATT_DIE5,0,0}, // S_FATT_DIE4 - {SPR_FATT,14,6,{NULL},S_FATT_DIE6,0,0}, // S_FATT_DIE5 - {SPR_FATT,15,6,{NULL},S_FATT_DIE7,0,0}, // S_FATT_DIE6 - {SPR_FATT,16,6,{NULL},S_FATT_DIE8,0,0}, // S_FATT_DIE7 - {SPR_FATT,17,6,{NULL},S_FATT_DIE9,0,0}, // S_FATT_DIE8 - {SPR_FATT,18,6,{NULL},S_FATT_DIE10,0,0}, // S_FATT_DIE9 - {SPR_FATT,19,-1,{A_BossDeath},S_NULL,0,0}, // S_FATT_DIE10 - {SPR_FATT,17,5,{NULL},S_FATT_RAISE2,0,0}, // S_FATT_RAISE1 - {SPR_FATT,16,5,{NULL},S_FATT_RAISE3,0,0}, // S_FATT_RAISE2 - {SPR_FATT,15,5,{NULL},S_FATT_RAISE4,0,0}, // S_FATT_RAISE3 - {SPR_FATT,14,5,{NULL},S_FATT_RAISE5,0,0}, // S_FATT_RAISE4 - {SPR_FATT,13,5,{NULL},S_FATT_RAISE6,0,0}, // S_FATT_RAISE5 - {SPR_FATT,12,5,{NULL},S_FATT_RAISE7,0,0}, // S_FATT_RAISE6 - {SPR_FATT,11,5,{NULL},S_FATT_RAISE8,0,0}, // S_FATT_RAISE7 - {SPR_FATT,10,5,{NULL},S_FATT_RUN1,0,0}, // S_FATT_RAISE8 - {SPR_CPOS,0,10,{A_Look},S_CPOS_STND2,0,0}, // S_CPOS_STND - {SPR_CPOS,1,10,{A_Look},S_CPOS_STND,0,0}, // S_CPOS_STND2 - {SPR_CPOS,0,3,{A_Chase},S_CPOS_RUN2,0,0}, // S_CPOS_RUN1 - {SPR_CPOS,0,3,{A_Chase},S_CPOS_RUN3,0,0}, // S_CPOS_RUN2 - {SPR_CPOS,1,3,{A_Chase},S_CPOS_RUN4,0,0}, // S_CPOS_RUN3 - {SPR_CPOS,1,3,{A_Chase},S_CPOS_RUN5,0,0}, // S_CPOS_RUN4 - {SPR_CPOS,2,3,{A_Chase},S_CPOS_RUN6,0,0}, // S_CPOS_RUN5 - {SPR_CPOS,2,3,{A_Chase},S_CPOS_RUN7,0,0}, // S_CPOS_RUN6 - {SPR_CPOS,3,3,{A_Chase},S_CPOS_RUN8,0,0}, // S_CPOS_RUN7 - {SPR_CPOS,3,3,{A_Chase},S_CPOS_RUN1,0,0}, // S_CPOS_RUN8 - {SPR_CPOS,4,10,{A_FaceTarget},S_CPOS_ATK2,0,0}, // S_CPOS_ATK1 - {SPR_CPOS,32773,4,{A_CPosAttack},S_CPOS_ATK3,0,0}, // S_CPOS_ATK2 - {SPR_CPOS,32772,4,{A_CPosAttack},S_CPOS_ATK4,0,0}, // S_CPOS_ATK3 - {SPR_CPOS,5,1,{A_CPosRefire},S_CPOS_ATK2,0,0}, // S_CPOS_ATK4 - {SPR_CPOS,6,3,{NULL},S_CPOS_PAIN2,0,0}, // S_CPOS_PAIN - {SPR_CPOS,6,3,{A_Pain},S_CPOS_RUN1,0,0}, // S_CPOS_PAIN2 - {SPR_CPOS,7,5,{NULL},S_CPOS_DIE2,0,0}, // S_CPOS_DIE1 - {SPR_CPOS,8,5,{A_Scream},S_CPOS_DIE3,0,0}, // S_CPOS_DIE2 - {SPR_CPOS,9,5,{A_Fall},S_CPOS_DIE4,0,0}, // S_CPOS_DIE3 - {SPR_CPOS,10,5,{NULL},S_CPOS_DIE5,0,0}, // S_CPOS_DIE4 - {SPR_CPOS,11,5,{NULL},S_CPOS_DIE6,0,0}, // S_CPOS_DIE5 - {SPR_CPOS,12,5,{NULL},S_CPOS_DIE7,0,0}, // S_CPOS_DIE6 - {SPR_CPOS,13,-1,{NULL},S_NULL,0,0}, // S_CPOS_DIE7 - {SPR_CPOS,14,5,{NULL},S_CPOS_XDIE2,0,0}, // S_CPOS_XDIE1 - {SPR_CPOS,15,5,{A_XScream},S_CPOS_XDIE3,0,0}, // S_CPOS_XDIE2 - {SPR_CPOS,16,5,{A_Fall},S_CPOS_XDIE4,0,0}, // S_CPOS_XDIE3 - {SPR_CPOS,17,5,{NULL},S_CPOS_XDIE5,0,0}, // S_CPOS_XDIE4 - {SPR_CPOS,18,5,{NULL},S_CPOS_XDIE6,0,0}, // S_CPOS_XDIE5 - {SPR_CPOS,19,-1,{NULL},S_NULL,0,0}, // S_CPOS_XDIE6 - {SPR_CPOS,13,5,{NULL},S_CPOS_RAISE2,0,0}, // S_CPOS_RAISE1 - {SPR_CPOS,12,5,{NULL},S_CPOS_RAISE3,0,0}, // S_CPOS_RAISE2 - {SPR_CPOS,11,5,{NULL},S_CPOS_RAISE4,0,0}, // S_CPOS_RAISE3 - {SPR_CPOS,10,5,{NULL},S_CPOS_RAISE5,0,0}, // S_CPOS_RAISE4 - {SPR_CPOS,9,5,{NULL},S_CPOS_RAISE6,0,0}, // S_CPOS_RAISE5 - {SPR_CPOS,8,5,{NULL},S_CPOS_RAISE7,0,0}, // S_CPOS_RAISE6 - {SPR_CPOS,7,5,{NULL},S_CPOS_RUN1,0,0}, // S_CPOS_RAISE7 - {SPR_TROO,0,10,{A_Look},S_TROO_STND2,0,0}, // S_TROO_STND - {SPR_TROO,1,10,{A_Look},S_TROO_STND,0,0}, // S_TROO_STND2 - {SPR_TROO,0,3,{A_Chase},S_TROO_RUN2,0,0}, // S_TROO_RUN1 - {SPR_TROO,0,3,{A_Chase},S_TROO_RUN3,0,0}, // S_TROO_RUN2 - {SPR_TROO,1,3,{A_Chase},S_TROO_RUN4,0,0}, // S_TROO_RUN3 - {SPR_TROO,1,3,{A_Chase},S_TROO_RUN5,0,0}, // S_TROO_RUN4 - {SPR_TROO,2,3,{A_Chase},S_TROO_RUN6,0,0}, // S_TROO_RUN5 - {SPR_TROO,2,3,{A_Chase},S_TROO_RUN7,0,0}, // S_TROO_RUN6 - {SPR_TROO,3,3,{A_Chase},S_TROO_RUN8,0,0}, // S_TROO_RUN7 - {SPR_TROO,3,3,{A_Chase},S_TROO_RUN1,0,0}, // S_TROO_RUN8 - {SPR_TROO,4,8,{A_FaceTarget},S_TROO_ATK2,0,0}, // S_TROO_ATK1 - {SPR_TROO,5,8,{A_FaceTarget},S_TROO_ATK3,0,0}, // S_TROO_ATK2 - {SPR_TROO,6,6,{A_TroopAttack},S_TROO_RUN1,0,0}, // S_TROO_ATK3 - {SPR_TROO,7,2,{NULL},S_TROO_PAIN2,0,0}, // S_TROO_PAIN - {SPR_TROO,7,2,{A_Pain},S_TROO_RUN1,0,0}, // S_TROO_PAIN2 - {SPR_TROO,8,8,{NULL},S_TROO_DIE2,0,0}, // S_TROO_DIE1 - {SPR_TROO,9,8,{A_Scream},S_TROO_DIE3,0,0}, // S_TROO_DIE2 - {SPR_TROO,10,6,{NULL},S_TROO_DIE4,0,0}, // S_TROO_DIE3 - {SPR_TROO,11,6,{A_Fall},S_TROO_DIE5,0,0}, // S_TROO_DIE4 - {SPR_TROO,12,-1,{NULL},S_NULL,0,0}, // S_TROO_DIE5 - {SPR_TROO,13,5,{NULL},S_TROO_XDIE2,0,0}, // S_TROO_XDIE1 - {SPR_TROO,14,5,{A_XScream},S_TROO_XDIE3,0,0}, // S_TROO_XDIE2 - {SPR_TROO,15,5,{NULL},S_TROO_XDIE4,0,0}, // S_TROO_XDIE3 - {SPR_TROO,16,5,{A_Fall},S_TROO_XDIE5,0,0}, // S_TROO_XDIE4 - {SPR_TROO,17,5,{NULL},S_TROO_XDIE6,0,0}, // S_TROO_XDIE5 - {SPR_TROO,18,5,{NULL},S_TROO_XDIE7,0,0}, // S_TROO_XDIE6 - {SPR_TROO,19,5,{NULL},S_TROO_XDIE8,0,0}, // S_TROO_XDIE7 - {SPR_TROO,20,-1,{NULL},S_NULL,0,0}, // S_TROO_XDIE8 - {SPR_TROO,12,8,{NULL},S_TROO_RAISE2,0,0}, // S_TROO_RAISE1 - {SPR_TROO,11,8,{NULL},S_TROO_RAISE3,0,0}, // S_TROO_RAISE2 - {SPR_TROO,10,6,{NULL},S_TROO_RAISE4,0,0}, // S_TROO_RAISE3 - {SPR_TROO,9,6,{NULL},S_TROO_RAISE5,0,0}, // S_TROO_RAISE4 - {SPR_TROO,8,6,{NULL},S_TROO_RUN1,0,0}, // S_TROO_RAISE5 - {SPR_SARG,0,10,{A_Look},S_SARG_STND2,0,0}, // S_SARG_STND - {SPR_SARG,1,10,{A_Look},S_SARG_STND,0,0}, // S_SARG_STND2 - {SPR_SARG,0,2,{A_Chase},S_SARG_RUN2,0,0}, // S_SARG_RUN1 - {SPR_SARG,0,2,{A_Chase},S_SARG_RUN3,0,0}, // S_SARG_RUN2 - {SPR_SARG,1,2,{A_Chase},S_SARG_RUN4,0,0}, // S_SARG_RUN3 - {SPR_SARG,1,2,{A_Chase},S_SARG_RUN5,0,0}, // S_SARG_RUN4 - {SPR_SARG,2,2,{A_Chase},S_SARG_RUN6,0,0}, // S_SARG_RUN5 - {SPR_SARG,2,2,{A_Chase},S_SARG_RUN7,0,0}, // S_SARG_RUN6 - {SPR_SARG,3,2,{A_Chase},S_SARG_RUN8,0,0}, // S_SARG_RUN7 - {SPR_SARG,3,2,{A_Chase},S_SARG_RUN1,0,0}, // S_SARG_RUN8 - {SPR_SARG,4,8,{A_FaceTarget},S_SARG_ATK2,0,0}, // S_SARG_ATK1 - {SPR_SARG,5,8,{A_FaceTarget},S_SARG_ATK3,0,0}, // S_SARG_ATK2 - {SPR_SARG,6,8,{A_SargAttack},S_SARG_RUN1,0,0}, // S_SARG_ATK3 - {SPR_SARG,7,2,{NULL},S_SARG_PAIN2,0,0}, // S_SARG_PAIN - {SPR_SARG,7,2,{A_Pain},S_SARG_RUN1,0,0}, // S_SARG_PAIN2 - {SPR_SARG,8,8,{NULL},S_SARG_DIE2,0,0}, // S_SARG_DIE1 - {SPR_SARG,9,8,{A_Scream},S_SARG_DIE3,0,0}, // S_SARG_DIE2 - {SPR_SARG,10,4,{NULL},S_SARG_DIE4,0,0}, // S_SARG_DIE3 - {SPR_SARG,11,4,{A_Fall},S_SARG_DIE5,0,0}, // S_SARG_DIE4 - {SPR_SARG,12,4,{NULL},S_SARG_DIE6,0,0}, // S_SARG_DIE5 - {SPR_SARG,13,-1,{NULL},S_NULL,0,0}, // S_SARG_DIE6 - {SPR_SARG,13,5,{NULL},S_SARG_RAISE2,0,0}, // S_SARG_RAISE1 - {SPR_SARG,12,5,{NULL},S_SARG_RAISE3,0,0}, // S_SARG_RAISE2 - {SPR_SARG,11,5,{NULL},S_SARG_RAISE4,0,0}, // S_SARG_RAISE3 - {SPR_SARG,10,5,{NULL},S_SARG_RAISE5,0,0}, // S_SARG_RAISE4 - {SPR_SARG,9,5,{NULL},S_SARG_RAISE6,0,0}, // S_SARG_RAISE5 - {SPR_SARG,8,5,{NULL},S_SARG_RUN1,0,0}, // S_SARG_RAISE6 - {SPR_HEAD,0,10,{A_Look},S_HEAD_STND,0,0}, // S_HEAD_STND - {SPR_HEAD,0,3,{A_Chase},S_HEAD_RUN1,0,0}, // S_HEAD_RUN1 - {SPR_HEAD,1,5,{A_FaceTarget},S_HEAD_ATK2,0,0}, // S_HEAD_ATK1 - {SPR_HEAD,2,5,{A_FaceTarget},S_HEAD_ATK3,0,0}, // S_HEAD_ATK2 - {SPR_HEAD,32771,5,{A_HeadAttack},S_HEAD_RUN1,0,0}, // S_HEAD_ATK3 - {SPR_HEAD,4,3,{NULL},S_HEAD_PAIN2,0,0}, // S_HEAD_PAIN - {SPR_HEAD,4,3,{A_Pain},S_HEAD_PAIN3,0,0}, // S_HEAD_PAIN2 - {SPR_HEAD,5,6,{NULL},S_HEAD_RUN1,0,0}, // S_HEAD_PAIN3 - {SPR_HEAD,6,8,{NULL},S_HEAD_DIE2,0,0}, // S_HEAD_DIE1 - {SPR_HEAD,7,8,{A_Scream},S_HEAD_DIE3,0,0}, // S_HEAD_DIE2 - {SPR_HEAD,8,8,{NULL},S_HEAD_DIE4,0,0}, // S_HEAD_DIE3 - {SPR_HEAD,9,8,{NULL},S_HEAD_DIE5,0,0}, // S_HEAD_DIE4 - {SPR_HEAD,10,8,{A_Fall},S_HEAD_DIE6,0,0}, // S_HEAD_DIE5 - {SPR_HEAD,11,-1,{NULL},S_NULL,0,0}, // S_HEAD_DIE6 - {SPR_HEAD,11,8,{NULL},S_HEAD_RAISE2,0,0}, // S_HEAD_RAISE1 - {SPR_HEAD,10,8,{NULL},S_HEAD_RAISE3,0,0}, // S_HEAD_RAISE2 - {SPR_HEAD,9,8,{NULL},S_HEAD_RAISE4,0,0}, // S_HEAD_RAISE3 - {SPR_HEAD,8,8,{NULL},S_HEAD_RAISE5,0,0}, // S_HEAD_RAISE4 - {SPR_HEAD,7,8,{NULL},S_HEAD_RAISE6,0,0}, // S_HEAD_RAISE5 - {SPR_HEAD,6,8,{NULL},S_HEAD_RUN1,0,0}, // S_HEAD_RAISE6 - {SPR_BAL7,32768,4,{NULL},S_BRBALL2,0,0}, // S_BRBALL1 - {SPR_BAL7,32769,4,{NULL},S_BRBALL1,0,0}, // S_BRBALL2 - {SPR_BAL7,32770,6,{NULL},S_BRBALLX2,0,0}, // S_BRBALLX1 - {SPR_BAL7,32771,6,{NULL},S_BRBALLX3,0,0}, // S_BRBALLX2 - {SPR_BAL7,32772,6,{NULL},S_NULL,0,0}, // S_BRBALLX3 - {SPR_BOSS,0,10,{A_Look},S_BOSS_STND2,0,0}, // S_BOSS_STND - {SPR_BOSS,1,10,{A_Look},S_BOSS_STND,0,0}, // S_BOSS_STND2 - {SPR_BOSS,0,3,{A_Chase},S_BOSS_RUN2,0,0}, // S_BOSS_RUN1 - {SPR_BOSS,0,3,{A_Chase},S_BOSS_RUN3,0,0}, // S_BOSS_RUN2 - {SPR_BOSS,1,3,{A_Chase},S_BOSS_RUN4,0,0}, // S_BOSS_RUN3 - {SPR_BOSS,1,3,{A_Chase},S_BOSS_RUN5,0,0}, // S_BOSS_RUN4 - {SPR_BOSS,2,3,{A_Chase},S_BOSS_RUN6,0,0}, // S_BOSS_RUN5 - {SPR_BOSS,2,3,{A_Chase},S_BOSS_RUN7,0,0}, // S_BOSS_RUN6 - {SPR_BOSS,3,3,{A_Chase},S_BOSS_RUN8,0,0}, // S_BOSS_RUN7 - {SPR_BOSS,3,3,{A_Chase},S_BOSS_RUN1,0,0}, // S_BOSS_RUN8 - {SPR_BOSS,4,8,{A_FaceTarget},S_BOSS_ATK2,0,0}, // S_BOSS_ATK1 - {SPR_BOSS,5,8,{A_FaceTarget},S_BOSS_ATK3,0,0}, // S_BOSS_ATK2 - {SPR_BOSS,6,8,{A_BruisAttack},S_BOSS_RUN1,0,0}, // S_BOSS_ATK3 - {SPR_BOSS,7,2,{NULL},S_BOSS_PAIN2,0,0}, // S_BOSS_PAIN - {SPR_BOSS,7,2,{A_Pain},S_BOSS_RUN1,0,0}, // S_BOSS_PAIN2 - {SPR_BOSS,8,8,{NULL},S_BOSS_DIE2,0,0}, // S_BOSS_DIE1 - {SPR_BOSS,9,8,{A_Scream},S_BOSS_DIE3,0,0}, // S_BOSS_DIE2 - {SPR_BOSS,10,8,{NULL},S_BOSS_DIE4,0,0}, // S_BOSS_DIE3 - {SPR_BOSS,11,8,{A_Fall},S_BOSS_DIE5,0,0}, // S_BOSS_DIE4 - {SPR_BOSS,12,8,{NULL},S_BOSS_DIE6,0,0}, // S_BOSS_DIE5 - {SPR_BOSS,13,8,{NULL},S_BOSS_DIE7,0,0}, // S_BOSS_DIE6 - {SPR_BOSS,14,-1,{A_BossDeath},S_NULL,0,0}, // S_BOSS_DIE7 - {SPR_BOSS,14,8,{NULL},S_BOSS_RAISE2,0,0}, // S_BOSS_RAISE1 - {SPR_BOSS,13,8,{NULL},S_BOSS_RAISE3,0,0}, // S_BOSS_RAISE2 - {SPR_BOSS,12,8,{NULL},S_BOSS_RAISE4,0,0}, // S_BOSS_RAISE3 - {SPR_BOSS,11,8,{NULL},S_BOSS_RAISE5,0,0}, // S_BOSS_RAISE4 - {SPR_BOSS,10,8,{NULL},S_BOSS_RAISE6,0,0}, // S_BOSS_RAISE5 - {SPR_BOSS,9,8,{NULL},S_BOSS_RAISE7,0,0}, // S_BOSS_RAISE6 - {SPR_BOSS,8,8,{NULL},S_BOSS_RUN1,0,0}, // S_BOSS_RAISE7 - {SPR_BOS2,0,10,{A_Look},S_BOS2_STND2,0,0}, // S_BOS2_STND - {SPR_BOS2,1,10,{A_Look},S_BOS2_STND,0,0}, // S_BOS2_STND2 - {SPR_BOS2,0,3,{A_Chase},S_BOS2_RUN2,0,0}, // S_BOS2_RUN1 - {SPR_BOS2,0,3,{A_Chase},S_BOS2_RUN3,0,0}, // S_BOS2_RUN2 - {SPR_BOS2,1,3,{A_Chase},S_BOS2_RUN4,0,0}, // S_BOS2_RUN3 - {SPR_BOS2,1,3,{A_Chase},S_BOS2_RUN5,0,0}, // S_BOS2_RUN4 - {SPR_BOS2,2,3,{A_Chase},S_BOS2_RUN6,0,0}, // S_BOS2_RUN5 - {SPR_BOS2,2,3,{A_Chase},S_BOS2_RUN7,0,0}, // S_BOS2_RUN6 - {SPR_BOS2,3,3,{A_Chase},S_BOS2_RUN8,0,0}, // S_BOS2_RUN7 - {SPR_BOS2,3,3,{A_Chase},S_BOS2_RUN1,0,0}, // S_BOS2_RUN8 - {SPR_BOS2,4,8,{A_FaceTarget},S_BOS2_ATK2,0,0}, // S_BOS2_ATK1 - {SPR_BOS2,5,8,{A_FaceTarget},S_BOS2_ATK3,0,0}, // S_BOS2_ATK2 - {SPR_BOS2,6,8,{A_BruisAttack},S_BOS2_RUN1,0,0}, // S_BOS2_ATK3 - {SPR_BOS2,7,2,{NULL},S_BOS2_PAIN2,0,0}, // S_BOS2_PAIN - {SPR_BOS2,7,2,{A_Pain},S_BOS2_RUN1,0,0}, // S_BOS2_PAIN2 - {SPR_BOS2,8,8,{NULL},S_BOS2_DIE2,0,0}, // S_BOS2_DIE1 - {SPR_BOS2,9,8,{A_Scream},S_BOS2_DIE3,0,0}, // S_BOS2_DIE2 - {SPR_BOS2,10,8,{NULL},S_BOS2_DIE4,0,0}, // S_BOS2_DIE3 - {SPR_BOS2,11,8,{A_Fall},S_BOS2_DIE5,0,0}, // S_BOS2_DIE4 - {SPR_BOS2,12,8,{NULL},S_BOS2_DIE6,0,0}, // S_BOS2_DIE5 - {SPR_BOS2,13,8,{NULL},S_BOS2_DIE7,0,0}, // S_BOS2_DIE6 - {SPR_BOS2,14,-1,{NULL},S_NULL,0,0}, // S_BOS2_DIE7 - {SPR_BOS2,14,8,{NULL},S_BOS2_RAISE2,0,0}, // S_BOS2_RAISE1 - {SPR_BOS2,13,8,{NULL},S_BOS2_RAISE3,0,0}, // S_BOS2_RAISE2 - {SPR_BOS2,12,8,{NULL},S_BOS2_RAISE4,0,0}, // S_BOS2_RAISE3 - {SPR_BOS2,11,8,{NULL},S_BOS2_RAISE5,0,0}, // S_BOS2_RAISE4 - {SPR_BOS2,10,8,{NULL},S_BOS2_RAISE6,0,0}, // S_BOS2_RAISE5 - {SPR_BOS2,9,8,{NULL},S_BOS2_RAISE7,0,0}, // S_BOS2_RAISE6 - {SPR_BOS2,8,8,{NULL},S_BOS2_RUN1,0,0}, // S_BOS2_RAISE7 - {SPR_SKUL,32768,10,{A_Look},S_SKULL_STND2,0,0}, // S_SKULL_STND - {SPR_SKUL,32769,10,{A_Look},S_SKULL_STND,0,0}, // S_SKULL_STND2 - {SPR_SKUL,32768,6,{A_Chase},S_SKULL_RUN2,0,0}, // S_SKULL_RUN1 - {SPR_SKUL,32769,6,{A_Chase},S_SKULL_RUN1,0,0}, // S_SKULL_RUN2 - {SPR_SKUL,32770,10,{A_FaceTarget},S_SKULL_ATK2,0,0}, // S_SKULL_ATK1 - {SPR_SKUL,32771,4,{A_SkullAttack},S_SKULL_ATK3,0,0}, // S_SKULL_ATK2 - {SPR_SKUL,32770,4,{NULL},S_SKULL_ATK4,0,0}, // S_SKULL_ATK3 - {SPR_SKUL,32771,4,{NULL},S_SKULL_ATK3,0,0}, // S_SKULL_ATK4 - {SPR_SKUL,32772,3,{NULL},S_SKULL_PAIN2,0,0}, // S_SKULL_PAIN - {SPR_SKUL,32772,3,{A_Pain},S_SKULL_RUN1,0,0}, // S_SKULL_PAIN2 - {SPR_SKUL,32773,6,{NULL},S_SKULL_DIE2,0,0}, // S_SKULL_DIE1 - {SPR_SKUL,32774,6,{A_Scream},S_SKULL_DIE3,0,0}, // S_SKULL_DIE2 - {SPR_SKUL,32775,6,{NULL},S_SKULL_DIE4,0,0}, // S_SKULL_DIE3 - {SPR_SKUL,32776,6,{A_Fall},S_SKULL_DIE5,0,0}, // S_SKULL_DIE4 - {SPR_SKUL,9,6,{NULL},S_SKULL_DIE6,0,0}, // S_SKULL_DIE5 - {SPR_SKUL,10,6,{NULL},S_NULL,0,0}, // S_SKULL_DIE6 - {SPR_SPID,0,10,{A_Look},S_SPID_STND2,0,0}, // S_SPID_STND - {SPR_SPID,1,10,{A_Look},S_SPID_STND,0,0}, // S_SPID_STND2 - {SPR_SPID,0,3,{A_Metal},S_SPID_RUN2,0,0}, // S_SPID_RUN1 - {SPR_SPID,0,3,{A_Chase},S_SPID_RUN3,0,0}, // S_SPID_RUN2 - {SPR_SPID,1,3,{A_Chase},S_SPID_RUN4,0,0}, // S_SPID_RUN3 - {SPR_SPID,1,3,{A_Chase},S_SPID_RUN5,0,0}, // S_SPID_RUN4 - {SPR_SPID,2,3,{A_Metal},S_SPID_RUN6,0,0}, // S_SPID_RUN5 - {SPR_SPID,2,3,{A_Chase},S_SPID_RUN7,0,0}, // S_SPID_RUN6 - {SPR_SPID,3,3,{A_Chase},S_SPID_RUN8,0,0}, // S_SPID_RUN7 - {SPR_SPID,3,3,{A_Chase},S_SPID_RUN9,0,0}, // S_SPID_RUN8 - {SPR_SPID,4,3,{A_Metal},S_SPID_RUN10,0,0}, // S_SPID_RUN9 - {SPR_SPID,4,3,{A_Chase},S_SPID_RUN11,0,0}, // S_SPID_RUN10 - {SPR_SPID,5,3,{A_Chase},S_SPID_RUN12,0,0}, // S_SPID_RUN11 - {SPR_SPID,5,3,{A_Chase},S_SPID_RUN1,0,0}, // S_SPID_RUN12 - {SPR_SPID,32768,20,{A_FaceTarget},S_SPID_ATK2,0,0}, // S_SPID_ATK1 - {SPR_SPID,32774,4,{A_SPosAttack},S_SPID_ATK3,0,0}, // S_SPID_ATK2 - {SPR_SPID,32775,4,{A_SPosAttack},S_SPID_ATK4,0,0}, // S_SPID_ATK3 - {SPR_SPID,32775,1,{A_SpidRefire},S_SPID_ATK2,0,0}, // S_SPID_ATK4 - {SPR_SPID,8,3,{NULL},S_SPID_PAIN2,0,0}, // S_SPID_PAIN - {SPR_SPID,8,3,{A_Pain},S_SPID_RUN1,0,0}, // S_SPID_PAIN2 - {SPR_SPID,9,20,{A_Scream},S_SPID_DIE2,0,0}, // S_SPID_DIE1 - {SPR_SPID,10,10,{A_Fall},S_SPID_DIE3,0,0}, // S_SPID_DIE2 - {SPR_SPID,11,10,{NULL},S_SPID_DIE4,0,0}, // S_SPID_DIE3 - {SPR_SPID,12,10,{NULL},S_SPID_DIE5,0,0}, // S_SPID_DIE4 - {SPR_SPID,13,10,{NULL},S_SPID_DIE6,0,0}, // S_SPID_DIE5 - {SPR_SPID,14,10,{NULL},S_SPID_DIE7,0,0}, // S_SPID_DIE6 - {SPR_SPID,15,10,{NULL},S_SPID_DIE8,0,0}, // S_SPID_DIE7 - {SPR_SPID,16,10,{NULL},S_SPID_DIE9,0,0}, // S_SPID_DIE8 - {SPR_SPID,17,10,{NULL},S_SPID_DIE10,0,0}, // S_SPID_DIE9 - {SPR_SPID,18,30,{NULL},S_SPID_DIE11,0,0}, // S_SPID_DIE10 - {SPR_SPID,18,-1,{A_BossDeath},S_NULL,0,0}, // S_SPID_DIE11 - {SPR_BSPI,0,10,{A_Look},S_BSPI_STND2,0,0}, // S_BSPI_STND - {SPR_BSPI,1,10,{A_Look},S_BSPI_STND,0,0}, // S_BSPI_STND2 - {SPR_BSPI,0,20,{NULL},S_BSPI_RUN1,0,0}, // S_BSPI_SIGHT - {SPR_BSPI,0,3,{A_BabyMetal},S_BSPI_RUN2,0,0}, // S_BSPI_RUN1 - {SPR_BSPI,0,3,{A_Chase},S_BSPI_RUN3,0,0}, // S_BSPI_RUN2 - {SPR_BSPI,1,3,{A_Chase},S_BSPI_RUN4,0,0}, // S_BSPI_RUN3 - {SPR_BSPI,1,3,{A_Chase},S_BSPI_RUN5,0,0}, // S_BSPI_RUN4 - {SPR_BSPI,2,3,{A_Chase},S_BSPI_RUN6,0,0}, // S_BSPI_RUN5 - {SPR_BSPI,2,3,{A_Chase},S_BSPI_RUN7,0,0}, // S_BSPI_RUN6 - {SPR_BSPI,3,3,{A_BabyMetal},S_BSPI_RUN8,0,0}, // S_BSPI_RUN7 - {SPR_BSPI,3,3,{A_Chase},S_BSPI_RUN9,0,0}, // S_BSPI_RUN8 - {SPR_BSPI,4,3,{A_Chase},S_BSPI_RUN10,0,0}, // S_BSPI_RUN9 - {SPR_BSPI,4,3,{A_Chase},S_BSPI_RUN11,0,0}, // S_BSPI_RUN10 - {SPR_BSPI,5,3,{A_Chase},S_BSPI_RUN12,0,0}, // S_BSPI_RUN11 - {SPR_BSPI,5,3,{A_Chase},S_BSPI_RUN1,0,0}, // S_BSPI_RUN12 - {SPR_BSPI,32768,20,{A_FaceTarget},S_BSPI_ATK2,0,0}, // S_BSPI_ATK1 - {SPR_BSPI,32774,4,{A_BspiAttack},S_BSPI_ATK3,0,0}, // S_BSPI_ATK2 - {SPR_BSPI,32775,4,{NULL},S_BSPI_ATK4,0,0}, // S_BSPI_ATK3 - {SPR_BSPI,32775,1,{A_SpidRefire},S_BSPI_ATK2,0,0}, // S_BSPI_ATK4 - {SPR_BSPI,8,3,{NULL},S_BSPI_PAIN2,0,0}, // S_BSPI_PAIN - {SPR_BSPI,8,3,{A_Pain},S_BSPI_RUN1,0,0}, // S_BSPI_PAIN2 - {SPR_BSPI,9,20,{A_Scream},S_BSPI_DIE2,0,0}, // S_BSPI_DIE1 - {SPR_BSPI,10,7,{A_Fall},S_BSPI_DIE3,0,0}, // S_BSPI_DIE2 - {SPR_BSPI,11,7,{NULL},S_BSPI_DIE4,0,0}, // S_BSPI_DIE3 - {SPR_BSPI,12,7,{NULL},S_BSPI_DIE5,0,0}, // S_BSPI_DIE4 - {SPR_BSPI,13,7,{NULL},S_BSPI_DIE6,0,0}, // S_BSPI_DIE5 - {SPR_BSPI,14,7,{NULL},S_BSPI_DIE7,0,0}, // S_BSPI_DIE6 - {SPR_BSPI,15,-1,{A_BossDeath},S_NULL,0,0}, // S_BSPI_DIE7 - {SPR_BSPI,15,5,{NULL},S_BSPI_RAISE2,0,0}, // S_BSPI_RAISE1 - {SPR_BSPI,14,5,{NULL},S_BSPI_RAISE3,0,0}, // S_BSPI_RAISE2 - {SPR_BSPI,13,5,{NULL},S_BSPI_RAISE4,0,0}, // S_BSPI_RAISE3 - {SPR_BSPI,12,5,{NULL},S_BSPI_RAISE5,0,0}, // S_BSPI_RAISE4 - {SPR_BSPI,11,5,{NULL},S_BSPI_RAISE6,0,0}, // S_BSPI_RAISE5 - {SPR_BSPI,10,5,{NULL},S_BSPI_RAISE7,0,0}, // S_BSPI_RAISE6 - {SPR_BSPI,9,5,{NULL},S_BSPI_RUN1,0,0}, // S_BSPI_RAISE7 - {SPR_APLS,32768,5,{NULL},S_ARACH_PLAZ2,0,0}, // S_ARACH_PLAZ - {SPR_APLS,32769,5,{NULL},S_ARACH_PLAZ,0,0}, // S_ARACH_PLAZ2 - {SPR_APBX,32768,5,{NULL},S_ARACH_PLEX2,0,0}, // S_ARACH_PLEX - {SPR_APBX,32769,5,{NULL},S_ARACH_PLEX3,0,0}, // S_ARACH_PLEX2 - {SPR_APBX,32770,5,{NULL},S_ARACH_PLEX4,0,0}, // S_ARACH_PLEX3 - {SPR_APBX,32771,5,{NULL},S_ARACH_PLEX5,0,0}, // S_ARACH_PLEX4 - {SPR_APBX,32772,5,{NULL},S_NULL,0,0}, // S_ARACH_PLEX5 - {SPR_CYBR,0,10,{A_Look},S_CYBER_STND2,0,0}, // S_CYBER_STND - {SPR_CYBR,1,10,{A_Look},S_CYBER_STND,0,0}, // S_CYBER_STND2 - {SPR_CYBR,0,3,{A_Hoof},S_CYBER_RUN2,0,0}, // S_CYBER_RUN1 - {SPR_CYBR,0,3,{A_Chase},S_CYBER_RUN3,0,0}, // S_CYBER_RUN2 - {SPR_CYBR,1,3,{A_Chase},S_CYBER_RUN4,0,0}, // S_CYBER_RUN3 - {SPR_CYBR,1,3,{A_Chase},S_CYBER_RUN5,0,0}, // S_CYBER_RUN4 - {SPR_CYBR,2,3,{A_Chase},S_CYBER_RUN6,0,0}, // S_CYBER_RUN5 - {SPR_CYBR,2,3,{A_Chase},S_CYBER_RUN7,0,0}, // S_CYBER_RUN6 - {SPR_CYBR,3,3,{A_Metal},S_CYBER_RUN8,0,0}, // S_CYBER_RUN7 - {SPR_CYBR,3,3,{A_Chase},S_CYBER_RUN1,0,0}, // S_CYBER_RUN8 - {SPR_CYBR,4,6,{A_FaceTarget},S_CYBER_ATK2,0,0}, // S_CYBER_ATK1 - {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_ATK3,0,0}, // S_CYBER_ATK2 - {SPR_CYBR,4,12,{A_FaceTarget},S_CYBER_ATK4,0,0}, // S_CYBER_ATK3 - {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_ATK5,0,0}, // S_CYBER_ATK4 - {SPR_CYBR,4,12,{A_FaceTarget},S_CYBER_ATK6,0,0}, // S_CYBER_ATK5 - {SPR_CYBR,5,12,{A_CyberAttack},S_CYBER_RUN1,0,0}, // S_CYBER_ATK6 - {SPR_CYBR,6,10,{A_Pain},S_CYBER_RUN1,0,0}, // S_CYBER_PAIN - {SPR_CYBR,7,10,{NULL},S_CYBER_DIE2,0,0}, // S_CYBER_DIE1 - {SPR_CYBR,8,10,{A_Scream},S_CYBER_DIE3,0,0}, // S_CYBER_DIE2 - {SPR_CYBR,9,10,{NULL},S_CYBER_DIE4,0,0}, // S_CYBER_DIE3 - {SPR_CYBR,10,10,{NULL},S_CYBER_DIE5,0,0}, // S_CYBER_DIE4 - {SPR_CYBR,11,10,{NULL},S_CYBER_DIE6,0,0}, // S_CYBER_DIE5 - {SPR_CYBR,12,10,{A_Fall},S_CYBER_DIE7,0,0}, // S_CYBER_DIE6 - {SPR_CYBR,13,10,{NULL},S_CYBER_DIE8,0,0}, // S_CYBER_DIE7 - {SPR_CYBR,14,10,{NULL},S_CYBER_DIE9,0,0}, // S_CYBER_DIE8 - {SPR_CYBR,15,30,{NULL},S_CYBER_DIE10,0,0}, // S_CYBER_DIE9 - {SPR_CYBR,15,-1,{A_BossDeath},S_NULL,0,0}, // S_CYBER_DIE10 - {SPR_PAIN,0,10,{A_Look},S_PAIN_STND,0,0}, // S_PAIN_STND - {SPR_PAIN,0,3,{A_Chase},S_PAIN_RUN2,0,0}, // S_PAIN_RUN1 - {SPR_PAIN,0,3,{A_Chase},S_PAIN_RUN3,0,0}, // S_PAIN_RUN2 - {SPR_PAIN,1,3,{A_Chase},S_PAIN_RUN4,0,0}, // S_PAIN_RUN3 - {SPR_PAIN,1,3,{A_Chase},S_PAIN_RUN5,0,0}, // S_PAIN_RUN4 - {SPR_PAIN,2,3,{A_Chase},S_PAIN_RUN6,0,0}, // S_PAIN_RUN5 - {SPR_PAIN,2,3,{A_Chase},S_PAIN_RUN1,0,0}, // S_PAIN_RUN6 - {SPR_PAIN,3,5,{A_FaceTarget},S_PAIN_ATK2,0,0}, // S_PAIN_ATK1 - {SPR_PAIN,4,5,{A_FaceTarget},S_PAIN_ATK3,0,0}, // S_PAIN_ATK2 - {SPR_PAIN,32773,5,{A_FaceTarget},S_PAIN_ATK4,0,0}, // S_PAIN_ATK3 - {SPR_PAIN,32773,0,{A_PainAttack},S_PAIN_RUN1,0,0}, // S_PAIN_ATK4 - {SPR_PAIN,6,6,{NULL},S_PAIN_PAIN2,0,0}, // S_PAIN_PAIN - {SPR_PAIN,6,6,{A_Pain},S_PAIN_RUN1,0,0}, // S_PAIN_PAIN2 - {SPR_PAIN,32775,8,{NULL},S_PAIN_DIE2,0,0}, // S_PAIN_DIE1 - {SPR_PAIN,32776,8,{A_Scream},S_PAIN_DIE3,0,0}, // S_PAIN_DIE2 - {SPR_PAIN,32777,8,{NULL},S_PAIN_DIE4,0,0}, // S_PAIN_DIE3 - {SPR_PAIN,32778,8,{NULL},S_PAIN_DIE5,0,0}, // S_PAIN_DIE4 - {SPR_PAIN,32779,8,{A_PainDie},S_PAIN_DIE6,0,0}, // S_PAIN_DIE5 - {SPR_PAIN,32780,8,{NULL},S_NULL,0,0}, // S_PAIN_DIE6 - {SPR_PAIN,12,8,{NULL},S_PAIN_RAISE2,0,0}, // S_PAIN_RAISE1 - {SPR_PAIN,11,8,{NULL},S_PAIN_RAISE3,0,0}, // S_PAIN_RAISE2 - {SPR_PAIN,10,8,{NULL},S_PAIN_RAISE4,0,0}, // S_PAIN_RAISE3 - {SPR_PAIN,9,8,{NULL},S_PAIN_RAISE5,0,0}, // S_PAIN_RAISE4 - {SPR_PAIN,8,8,{NULL},S_PAIN_RAISE6,0,0}, // S_PAIN_RAISE5 - {SPR_PAIN,7,8,{NULL},S_PAIN_RUN1,0,0}, // S_PAIN_RAISE6 - {SPR_SSWV,0,10,{A_Look},S_SSWV_STND2,0,0}, // S_SSWV_STND - {SPR_SSWV,1,10,{A_Look},S_SSWV_STND,0,0}, // S_SSWV_STND2 - {SPR_SSWV,0,3,{A_Chase},S_SSWV_RUN2,0,0}, // S_SSWV_RUN1 - {SPR_SSWV,0,3,{A_Chase},S_SSWV_RUN3,0,0}, // S_SSWV_RUN2 - {SPR_SSWV,1,3,{A_Chase},S_SSWV_RUN4,0,0}, // S_SSWV_RUN3 - {SPR_SSWV,1,3,{A_Chase},S_SSWV_RUN5,0,0}, // S_SSWV_RUN4 - {SPR_SSWV,2,3,{A_Chase},S_SSWV_RUN6,0,0}, // S_SSWV_RUN5 - {SPR_SSWV,2,3,{A_Chase},S_SSWV_RUN7,0,0}, // S_SSWV_RUN6 - {SPR_SSWV,3,3,{A_Chase},S_SSWV_RUN8,0,0}, // S_SSWV_RUN7 - {SPR_SSWV,3,3,{A_Chase},S_SSWV_RUN1,0,0}, // S_SSWV_RUN8 - {SPR_SSWV,4,10,{A_FaceTarget},S_SSWV_ATK2,0,0}, // S_SSWV_ATK1 - {SPR_SSWV,5,10,{A_FaceTarget},S_SSWV_ATK3,0,0}, // S_SSWV_ATK2 - {SPR_SSWV,32774,4,{A_CPosAttack},S_SSWV_ATK4,0,0}, // S_SSWV_ATK3 - {SPR_SSWV,5,6,{A_FaceTarget},S_SSWV_ATK5,0,0}, // S_SSWV_ATK4 - {SPR_SSWV,32774,4,{A_CPosAttack},S_SSWV_ATK6,0,0}, // S_SSWV_ATK5 - {SPR_SSWV,5,1,{A_CPosRefire},S_SSWV_ATK2,0,0}, // S_SSWV_ATK6 - {SPR_SSWV,7,3,{NULL},S_SSWV_PAIN2,0,0}, // S_SSWV_PAIN - {SPR_SSWV,7,3,{A_Pain},S_SSWV_RUN1,0,0}, // S_SSWV_PAIN2 - {SPR_SSWV,8,5,{NULL},S_SSWV_DIE2,0,0}, // S_SSWV_DIE1 - {SPR_SSWV,9,5,{A_Scream},S_SSWV_DIE3,0,0}, // S_SSWV_DIE2 - {SPR_SSWV,10,5,{A_Fall},S_SSWV_DIE4,0,0}, // S_SSWV_DIE3 - {SPR_SSWV,11,5,{NULL},S_SSWV_DIE5,0,0}, // S_SSWV_DIE4 - {SPR_SSWV,12,-1,{NULL},S_NULL,0,0}, // S_SSWV_DIE5 - {SPR_SSWV,13,5,{NULL},S_SSWV_XDIE2,0,0}, // S_SSWV_XDIE1 - {SPR_SSWV,14,5,{A_XScream},S_SSWV_XDIE3,0,0}, // S_SSWV_XDIE2 - {SPR_SSWV,15,5,{A_Fall},S_SSWV_XDIE4,0,0}, // S_SSWV_XDIE3 - {SPR_SSWV,16,5,{NULL},S_SSWV_XDIE5,0,0}, // S_SSWV_XDIE4 - {SPR_SSWV,17,5,{NULL},S_SSWV_XDIE6,0,0}, // S_SSWV_XDIE5 - {SPR_SSWV,18,5,{NULL},S_SSWV_XDIE7,0,0}, // S_SSWV_XDIE6 - {SPR_SSWV,19,5,{NULL},S_SSWV_XDIE8,0,0}, // S_SSWV_XDIE7 - {SPR_SSWV,20,5,{NULL},S_SSWV_XDIE9,0,0}, // S_SSWV_XDIE8 - {SPR_SSWV,21,-1,{NULL},S_NULL,0,0}, // S_SSWV_XDIE9 - {SPR_SSWV,12,5,{NULL},S_SSWV_RAISE2,0,0}, // S_SSWV_RAISE1 - {SPR_SSWV,11,5,{NULL},S_SSWV_RAISE3,0,0}, // S_SSWV_RAISE2 - {SPR_SSWV,10,5,{NULL},S_SSWV_RAISE4,0,0}, // S_SSWV_RAISE3 - {SPR_SSWV,9,5,{NULL},S_SSWV_RAISE5,0,0}, // S_SSWV_RAISE4 - {SPR_SSWV,8,5,{NULL},S_SSWV_RUN1,0,0}, // S_SSWV_RAISE5 - {SPR_KEEN,0,-1,{NULL},S_KEENSTND,0,0}, // S_KEENSTND - {SPR_KEEN,0,6,{NULL},S_COMMKEEN2,0,0}, // S_COMMKEEN - {SPR_KEEN,1,6,{NULL},S_COMMKEEN3,0,0}, // S_COMMKEEN2 - {SPR_KEEN,2,6,{A_Scream},S_COMMKEEN4,0,0}, // S_COMMKEEN3 - {SPR_KEEN,3,6,{NULL},S_COMMKEEN5,0,0}, // S_COMMKEEN4 - {SPR_KEEN,4,6,{NULL},S_COMMKEEN6,0,0}, // S_COMMKEEN5 - {SPR_KEEN,5,6,{NULL},S_COMMKEEN7,0,0}, // S_COMMKEEN6 - {SPR_KEEN,6,6,{NULL},S_COMMKEEN8,0,0}, // S_COMMKEEN7 - {SPR_KEEN,7,6,{NULL},S_COMMKEEN9,0,0}, // S_COMMKEEN8 - {SPR_KEEN,8,6,{NULL},S_COMMKEEN10,0,0}, // S_COMMKEEN9 - {SPR_KEEN,9,6,{NULL},S_COMMKEEN11,0,0}, // S_COMMKEEN10 - {SPR_KEEN,10,6,{A_KeenDie},S_COMMKEEN12,0,0},// S_COMMKEEN11 - {SPR_KEEN,11,-1,{NULL},S_NULL,0,0}, // S_COMMKEEN12 - {SPR_KEEN,12,4,{NULL},S_KEENPAIN2,0,0}, // S_KEENPAIN - {SPR_KEEN,12,8,{A_Pain},S_KEENSTND,0,0}, // S_KEENPAIN2 - {SPR_BBRN,0,-1,{NULL},S_NULL,0,0}, // S_BRAIN - {SPR_BBRN,1,36,{A_BrainPain},S_BRAIN,0,0}, // S_BRAIN_PAIN - {SPR_BBRN,0,100,{A_BrainScream},S_BRAIN_DIE2,0,0}, // S_BRAIN_DIE1 - {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE3,0,0}, // S_BRAIN_DIE2 - {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE4,0,0}, // S_BRAIN_DIE3 - {SPR_BBRN,0,-1,{A_BrainDie},S_NULL,0,0}, // S_BRAIN_DIE4 - {SPR_SSWV,0,10,{A_Look},S_BRAINEYE,0,0}, // S_BRAINEYE - {SPR_SSWV,0,181,{A_BrainAwake},S_BRAINEYE1,0,0}, // S_BRAINEYESEE - {SPR_SSWV,0,150,{A_BrainSpit},S_BRAINEYE1,0,0}, // S_BRAINEYE1 - {SPR_BOSF,32768,3,{A_SpawnSound},S_SPAWN2,0,0}, // S_SPAWN1 - {SPR_BOSF,32769,3,{A_SpawnFly},S_SPAWN3,0,0}, // S_SPAWN2 - {SPR_BOSF,32770,3,{A_SpawnFly},S_SPAWN4,0,0}, // S_SPAWN3 - {SPR_BOSF,32771,3,{A_SpawnFly},S_SPAWN1,0,0}, // S_SPAWN4 - {SPR_FIRE,32768,4,{A_Fire},S_SPAWNFIRE2,0,0}, // S_SPAWNFIRE1 - {SPR_FIRE,32769,4,{A_Fire},S_SPAWNFIRE3,0,0}, // S_SPAWNFIRE2 - {SPR_FIRE,32770,4,{A_Fire},S_SPAWNFIRE4,0,0}, // S_SPAWNFIRE3 - {SPR_FIRE,32771,4,{A_Fire},S_SPAWNFIRE5,0,0}, // S_SPAWNFIRE4 - {SPR_FIRE,32772,4,{A_Fire},S_SPAWNFIRE6,0,0}, // S_SPAWNFIRE5 - {SPR_FIRE,32773,4,{A_Fire},S_SPAWNFIRE7,0,0}, // S_SPAWNFIRE6 - {SPR_FIRE,32774,4,{A_Fire},S_SPAWNFIRE8,0,0}, // S_SPAWNFIRE7 - {SPR_FIRE,32775,4,{A_Fire},S_NULL,0,0}, // S_SPAWNFIRE8 - {SPR_MISL,32769,10,{NULL},S_BRAINEXPLODE2,0,0}, // S_BRAINEXPLODE1 - {SPR_MISL,32770,10,{NULL},S_BRAINEXPLODE3,0,0}, // S_BRAINEXPLODE2 - {SPR_MISL,32771,10,{A_BrainExplode},S_NULL,0,0}, // S_BRAINEXPLODE3 - {SPR_ARM1,0,6,{NULL},S_ARM1A,0,0}, // S_ARM1 - {SPR_ARM1,32769,7,{NULL},S_ARM1,0,0}, // S_ARM1A - {SPR_ARM2,0,6,{NULL},S_ARM2A,0,0}, // S_ARM2 - {SPR_ARM2,32769,6,{NULL},S_ARM2,0,0}, // S_ARM2A - {SPR_BAR1,0,6,{NULL},S_BAR2,0,0}, // S_BAR1 - {SPR_BAR1,1,6,{NULL},S_BAR1,0,0}, // S_BAR2 - {SPR_BEXP,32768,5,{NULL},S_BEXP2,0,0}, // S_BEXP - {SPR_BEXP,32769,5,{A_Scream},S_BEXP3,0,0}, // S_BEXP2 - {SPR_BEXP,32770,5,{NULL},S_BEXP4,0,0}, // S_BEXP3 - {SPR_BEXP,32771,10,{A_Explode},S_BEXP5,0,0}, // S_BEXP4 - {SPR_BEXP,32772,10,{NULL},S_NULL,0,0}, // S_BEXP5 - {SPR_FCAN,32768,4,{NULL},S_BBAR2,0,0}, // S_BBAR1 - {SPR_FCAN,32769,4,{NULL},S_BBAR3,0,0}, // S_BBAR2 - {SPR_FCAN,32770,4,{NULL},S_BBAR1,0,0}, // S_BBAR3 - {SPR_BON1,0,6,{NULL},S_BON1A,0,0}, // S_BON1 - {SPR_BON1,1,6,{NULL},S_BON1B,0,0}, // S_BON1A - {SPR_BON1,2,6,{NULL},S_BON1C,0,0}, // S_BON1B - {SPR_BON1,3,6,{NULL},S_BON1D,0,0}, // S_BON1C - {SPR_BON1,2,6,{NULL},S_BON1E,0,0}, // S_BON1D - {SPR_BON1,1,6,{NULL},S_BON1,0,0}, // S_BON1E - {SPR_BON2,0,6,{NULL},S_BON2A,0,0}, // S_BON2 - {SPR_BON2,1,6,{NULL},S_BON2B,0,0}, // S_BON2A - {SPR_BON2,2,6,{NULL},S_BON2C,0,0}, // S_BON2B - {SPR_BON2,3,6,{NULL},S_BON2D,0,0}, // S_BON2C - {SPR_BON2,2,6,{NULL},S_BON2E,0,0}, // S_BON2D - {SPR_BON2,1,6,{NULL},S_BON2,0,0}, // S_BON2E - {SPR_BKEY,0,10,{NULL},S_BKEY2,0,0}, // S_BKEY - {SPR_BKEY,32769,10,{NULL},S_BKEY,0,0}, // S_BKEY2 - {SPR_RKEY,0,10,{NULL},S_RKEY2,0,0}, // S_RKEY - {SPR_RKEY,32769,10,{NULL},S_RKEY,0,0}, // S_RKEY2 - {SPR_YKEY,0,10,{NULL},S_YKEY2,0,0}, // S_YKEY - {SPR_YKEY,32769,10,{NULL},S_YKEY,0,0}, // S_YKEY2 - {SPR_BSKU,0,10,{NULL},S_BSKULL2,0,0}, // S_BSKULL - {SPR_BSKU,32769,10,{NULL},S_BSKULL,0,0}, // S_BSKULL2 - {SPR_RSKU,0,10,{NULL},S_RSKULL2,0,0}, // S_RSKULL - {SPR_RSKU,32769,10,{NULL},S_RSKULL,0,0}, // S_RSKULL2 - {SPR_YSKU,0,10,{NULL},S_YSKULL2,0,0}, // S_YSKULL - {SPR_YSKU,32769,10,{NULL},S_YSKULL,0,0}, // S_YSKULL2 - {SPR_STIM,0,-1,{NULL},S_NULL,0,0}, // S_STIM - {SPR_MEDI,0,-1,{NULL},S_NULL,0,0}, // S_MEDI - {SPR_SOUL,32768,6,{NULL},S_SOUL2,0,0}, // S_SOUL - {SPR_SOUL,32769,6,{NULL},S_SOUL3,0,0}, // S_SOUL2 - {SPR_SOUL,32770,6,{NULL},S_SOUL4,0,0}, // S_SOUL3 - {SPR_SOUL,32771,6,{NULL},S_SOUL5,0,0}, // S_SOUL4 - {SPR_SOUL,32770,6,{NULL},S_SOUL6,0,0}, // S_SOUL5 - {SPR_SOUL,32769,6,{NULL},S_SOUL,0,0}, // S_SOUL6 - {SPR_PINV,32768,6,{NULL},S_PINV2,0,0}, // S_PINV - {SPR_PINV,32769,6,{NULL},S_PINV3,0,0}, // S_PINV2 - {SPR_PINV,32770,6,{NULL},S_PINV4,0,0}, // S_PINV3 - {SPR_PINV,32771,6,{NULL},S_PINV,0,0}, // S_PINV4 - {SPR_PSTR,32768,-1,{NULL},S_NULL,0,0}, // S_PSTR - {SPR_PINS,32768,6,{NULL},S_PINS2,0,0}, // S_PINS - {SPR_PINS,32769,6,{NULL},S_PINS3,0,0}, // S_PINS2 - {SPR_PINS,32770,6,{NULL},S_PINS4,0,0}, // S_PINS3 - {SPR_PINS,32771,6,{NULL},S_PINS,0,0}, // S_PINS4 - {SPR_MEGA,32768,6,{NULL},S_MEGA2,0,0}, // S_MEGA - {SPR_MEGA,32769,6,{NULL},S_MEGA3,0,0}, // S_MEGA2 - {SPR_MEGA,32770,6,{NULL},S_MEGA4,0,0}, // S_MEGA3 - {SPR_MEGA,32771,6,{NULL},S_MEGA,0,0}, // S_MEGA4 - {SPR_SUIT,32768,-1,{NULL},S_NULL,0,0}, // S_SUIT - {SPR_PMAP,32768,6,{NULL},S_PMAP2,0,0}, // S_PMAP - {SPR_PMAP,32769,6,{NULL},S_PMAP3,0,0}, // S_PMAP2 - {SPR_PMAP,32770,6,{NULL},S_PMAP4,0,0}, // S_PMAP3 - {SPR_PMAP,32771,6,{NULL},S_PMAP5,0,0}, // S_PMAP4 - {SPR_PMAP,32770,6,{NULL},S_PMAP6,0,0}, // S_PMAP5 - {SPR_PMAP,32769,6,{NULL},S_PMAP,0,0}, // S_PMAP6 - {SPR_PVIS,32768,6,{NULL},S_PVIS2,0,0}, // S_PVIS - {SPR_PVIS,1,6,{NULL},S_PVIS,0,0}, // S_PVIS2 - {SPR_CLIP,0,-1,{NULL},S_NULL,0,0}, // S_CLIP - {SPR_AMMO,0,-1,{NULL},S_NULL,0,0}, // S_AMMO - {SPR_ROCK,0,-1,{NULL},S_NULL,0,0}, // S_ROCK - {SPR_BROK,0,-1,{NULL},S_NULL,0,0}, // S_BROK - {SPR_CELL,0,-1,{NULL},S_NULL,0,0}, // S_CELL - {SPR_CELP,0,-1,{NULL},S_NULL,0,0}, // S_CELP - {SPR_SHEL,0,-1,{NULL},S_NULL,0,0}, // S_SHEL - {SPR_SBOX,0,-1,{NULL},S_NULL,0,0}, // S_SBOX - {SPR_BPAK,0,-1,{NULL},S_NULL,0,0}, // S_BPAK - {SPR_BFUG,0,-1,{NULL},S_NULL,0,0}, // S_BFUG - {SPR_MGUN,0,-1,{NULL},S_NULL,0,0}, // S_MGUN - {SPR_CSAW,0,-1,{NULL},S_NULL,0,0}, // S_CSAW - {SPR_LAUN,0,-1,{NULL},S_NULL,0,0}, // S_LAUN - {SPR_PLAS,0,-1,{NULL},S_NULL,0,0}, // S_PLAS - {SPR_SHOT,0,-1,{NULL},S_NULL,0,0}, // S_SHOT - {SPR_SGN2,0,-1,{NULL},S_NULL,0,0}, // S_SHOT2 - {SPR_COLU,32768,-1,{NULL},S_NULL,0,0}, // S_COLU - {SPR_SMT2,0,-1,{NULL},S_NULL,0,0}, // S_STALAG - {SPR_GOR1,0,10,{NULL},S_BLOODYTWITCH2,0,0}, // S_BLOODYTWITCH - {SPR_GOR1,1,15,{NULL},S_BLOODYTWITCH3,0,0}, // S_BLOODYTWITCH2 - {SPR_GOR1,2,8,{NULL},S_BLOODYTWITCH4,0,0}, // S_BLOODYTWITCH3 - {SPR_GOR1,1,6,{NULL},S_BLOODYTWITCH,0,0}, // S_BLOODYTWITCH4 - {SPR_PLAY,13,-1,{NULL},S_NULL,0,0}, // S_DEADTORSO - {SPR_PLAY,18,-1,{NULL},S_NULL,0,0}, // S_DEADBOTTOM - {SPR_POL2,0,-1,{NULL},S_NULL,0,0}, // S_HEADSONSTICK - {SPR_POL5,0,-1,{NULL},S_NULL,0,0}, // S_GIBS - {SPR_POL4,0,-1,{NULL},S_NULL,0,0}, // S_HEADONASTICK - {SPR_POL3,32768,6,{NULL},S_HEADCANDLES2,0,0}, // S_HEADCANDLES - {SPR_POL3,32769,6,{NULL},S_HEADCANDLES,0,0}, // S_HEADCANDLES2 - {SPR_POL1,0,-1,{NULL},S_NULL,0,0}, // S_DEADSTICK - {SPR_POL6,0,6,{NULL},S_LIVESTICK2,0,0}, // S_LIVESTICK - {SPR_POL6,1,8,{NULL},S_LIVESTICK,0,0}, // S_LIVESTICK2 - {SPR_GOR2,0,-1,{NULL},S_NULL,0,0}, // S_MEAT2 - {SPR_GOR3,0,-1,{NULL},S_NULL,0,0}, // S_MEAT3 - {SPR_GOR4,0,-1,{NULL},S_NULL,0,0}, // S_MEAT4 - {SPR_GOR5,0,-1,{NULL},S_NULL,0,0}, // S_MEAT5 - {SPR_SMIT,0,-1,{NULL},S_NULL,0,0}, // S_STALAGTITE - {SPR_COL1,0,-1,{NULL},S_NULL,0,0}, // S_TALLGRNCOL - {SPR_COL2,0,-1,{NULL},S_NULL,0,0}, // S_SHRTGRNCOL - {SPR_COL3,0,-1,{NULL},S_NULL,0,0}, // S_TALLREDCOL - {SPR_COL4,0,-1,{NULL},S_NULL,0,0}, // S_SHRTREDCOL - {SPR_CAND,32768,-1,{NULL},S_NULL,0,0}, // S_CANDLESTIK - {SPR_CBRA,32768,-1,{NULL},S_NULL,0,0}, // S_CANDELABRA - {SPR_COL6,0,-1,{NULL},S_NULL,0,0}, // S_SKULLCOL - {SPR_TRE1,0,-1,{NULL},S_NULL,0,0}, // S_TORCHTREE - {SPR_TRE2,0,-1,{NULL},S_NULL,0,0}, // S_BIGTREE - {SPR_ELEC,0,-1,{NULL},S_NULL,0,0}, // S_TECHPILLAR - {SPR_CEYE,32768,6,{NULL},S_EVILEYE2,0,0}, // S_EVILEYE - {SPR_CEYE,32769,6,{NULL},S_EVILEYE3,0,0}, // S_EVILEYE2 - {SPR_CEYE,32770,6,{NULL},S_EVILEYE4,0,0}, // S_EVILEYE3 - {SPR_CEYE,32769,6,{NULL},S_EVILEYE,0,0}, // S_EVILEYE4 - {SPR_FSKU,32768,6,{NULL},S_FLOATSKULL2,0,0}, // S_FLOATSKULL - {SPR_FSKU,32769,6,{NULL},S_FLOATSKULL3,0,0}, // S_FLOATSKULL2 - {SPR_FSKU,32770,6,{NULL},S_FLOATSKULL,0,0}, // S_FLOATSKULL3 - {SPR_COL5,0,14,{NULL},S_HEARTCOL2,0,0}, // S_HEARTCOL - {SPR_COL5,1,14,{NULL},S_HEARTCOL,0,0}, // S_HEARTCOL2 - {SPR_TBLU,32768,4,{NULL},S_BLUETORCH2,0,0}, // S_BLUETORCH - {SPR_TBLU,32769,4,{NULL},S_BLUETORCH3,0,0}, // S_BLUETORCH2 - {SPR_TBLU,32770,4,{NULL},S_BLUETORCH4,0,0}, // S_BLUETORCH3 - {SPR_TBLU,32771,4,{NULL},S_BLUETORCH,0,0}, // S_BLUETORCH4 - {SPR_TGRN,32768,4,{NULL},S_GREENTORCH2,0,0}, // S_GREENTORCH - {SPR_TGRN,32769,4,{NULL},S_GREENTORCH3,0,0}, // S_GREENTORCH2 - {SPR_TGRN,32770,4,{NULL},S_GREENTORCH4,0,0}, // S_GREENTORCH3 - {SPR_TGRN,32771,4,{NULL},S_GREENTORCH,0,0}, // S_GREENTORCH4 - {SPR_TRED,32768,4,{NULL},S_REDTORCH2,0,0}, // S_REDTORCH - {SPR_TRED,32769,4,{NULL},S_REDTORCH3,0,0}, // S_REDTORCH2 - {SPR_TRED,32770,4,{NULL},S_REDTORCH4,0,0}, // S_REDTORCH3 - {SPR_TRED,32771,4,{NULL},S_REDTORCH,0,0}, // S_REDTORCH4 - {SPR_SMBT,32768,4,{NULL},S_BTORCHSHRT2,0,0}, // S_BTORCHSHRT - {SPR_SMBT,32769,4,{NULL},S_BTORCHSHRT3,0,0}, // S_BTORCHSHRT2 - {SPR_SMBT,32770,4,{NULL},S_BTORCHSHRT4,0,0}, // S_BTORCHSHRT3 - {SPR_SMBT,32771,4,{NULL},S_BTORCHSHRT,0,0}, // S_BTORCHSHRT4 - {SPR_SMGT,32768,4,{NULL},S_GTORCHSHRT2,0,0}, // S_GTORCHSHRT - {SPR_SMGT,32769,4,{NULL},S_GTORCHSHRT3,0,0}, // S_GTORCHSHRT2 - {SPR_SMGT,32770,4,{NULL},S_GTORCHSHRT4,0,0}, // S_GTORCHSHRT3 - {SPR_SMGT,32771,4,{NULL},S_GTORCHSHRT,0,0}, // S_GTORCHSHRT4 - {SPR_SMRT,32768,4,{NULL},S_RTORCHSHRT2,0,0}, // S_RTORCHSHRT - {SPR_SMRT,32769,4,{NULL},S_RTORCHSHRT3,0,0}, // S_RTORCHSHRT2 - {SPR_SMRT,32770,4,{NULL},S_RTORCHSHRT4,0,0}, // S_RTORCHSHRT3 - {SPR_SMRT,32771,4,{NULL},S_RTORCHSHRT,0,0}, // S_RTORCHSHRT4 - {SPR_HDB1,0,-1,{NULL},S_NULL,0,0}, // S_HANGNOGUTS - {SPR_HDB2,0,-1,{NULL},S_NULL,0,0}, // S_HANGBNOBRAIN - {SPR_HDB3,0,-1,{NULL},S_NULL,0,0}, // S_HANGTLOOKDN - {SPR_HDB4,0,-1,{NULL},S_NULL,0,0}, // S_HANGTSKULL - {SPR_HDB5,0,-1,{NULL},S_NULL,0,0}, // S_HANGTLOOKUP - {SPR_HDB6,0,-1,{NULL},S_NULL,0,0}, // S_HANGTNOBRAIN - {SPR_POB1,0,-1,{NULL},S_NULL,0,0}, // S_COLONGIBS - {SPR_POB2,0,-1,{NULL},S_NULL,0,0}, // S_SMALLPOOL - {SPR_BRS1,0,-1,{NULL},S_NULL,0,0}, // S_BRAINSTEM - {SPR_TLMP,32768,4,{NULL},S_TECHLAMP2,0,0}, // S_TECHLAMP - {SPR_TLMP,32769,4,{NULL},S_TECHLAMP3,0,0}, // S_TECHLAMP2 - {SPR_TLMP,32770,4,{NULL},S_TECHLAMP4,0,0}, // S_TECHLAMP3 - {SPR_TLMP,32771,4,{NULL},S_TECHLAMP,0,0}, // S_TECHLAMP4 - {SPR_TLP2,32768,4,{NULL},S_TECH2LAMP2,0,0}, // S_TECH2LAMP - {SPR_TLP2,32769,4,{NULL},S_TECH2LAMP3,0,0}, // S_TECH2LAMP2 - {SPR_TLP2,32770,4,{NULL},S_TECH2LAMP4,0,0}, // S_TECH2LAMP3 - {SPR_TLP2,32771,4,{NULL},S_TECH2LAMP,0,0} // S_TECH2LAMP4 +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Doesn't work with g++, needs actionf_p1 */ + +void a_light0(); +void a_weapon_ready(); +void a_lower(); +void a_raise(); +void a_punch(); +void a_refire(); +void a_fire_pistol(); +void a_light1(); +void a_fire_shotgun(); +void a_light2(); +void a_fire_shotgun2(); +void a_check_reload(); +void a_open_shotgun2(); +void a_load_shotgun2(); +void a_close_shotgun2(); +void a_fire_cgun(); +void a_gun_flash(); +void a_fire_missile(); +void a_saw(); +void a_fire_plasma(); +void a_bfg_sound(); +void a_fire_bfg(); +void a_bfg_spray(); +void a_explode(); +void a_pain(); +void a_player_screm(); +void a_fall(); +void a_xscream(); +void a_look(); +void a_chase(); +void a_face_target(); +void a_pos_attack(); +void a_scream(); +void a_s_pos_attack(); +void a_vile_chase(); +void a_vile_start(); +void a_vile_target(); +void a_vile_attack(); +void a_start_fire(); +void a_fire(); +void a_fire_crackle(); +void a_tracer(); +void a_skel_woosh(); +void a_skel_fist(); +void a_skel_missile(); +void a_fat_raise(); +void a_fat_attack1(); +void a_fat_attack2(); +void a_fat_attack3(); +void a_boss_death(); +void a_c_pos_attack(); +void a_c_pos_refire(); +void a_troop_attack(); +void a_sarg_attack(); +void a_head_attack(); +void a_bruis_attack(); +void a_skull_attack(); +void a_metal(); +void a_spid_refire(); +void a_baby_metal(); +void a_bspi_attack(); +void a_hoof(); +void a_cyber_attack(); +void a_pain_attack(); +void a_pain_die(); +void a_keen_die(); +void a_brain_pain(); +void a_brain_scream(); +void a_brain_die(); +void a_brain_awake(); +void a_brain_split(); +void a_spawn_sound(); +void a_spawn_fly(); +void a_brain_explode(); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +state_t states[NUMSTATES] = +{ + STATE_ENTRY(SPR_TROO, 0, -1, NULL, S_NULL), /* S_NULL */ + STATE_ENTRY(SPR_SHTG, 4, 0, a_light0, S_NULL), /* S_LIGHTDONE */ + STATE_ENTRY(SPR_PUNG, 0, 1, a_weapon_ready, S_PUNCH), /* S_PUNCH */ + STATE_ENTRY(SPR_PUNG, 0, 1, a_lower, S_PUNCHDOWN), /* S_PUNCHDOWN */ + STATE_ENTRY(SPR_PUNG, 0, 1, a_raise, S_PUNCHUP), /* S_PUNCHUP */ + STATE_ENTRY(SPR_PUNG, 1, 4, NULL, S_PUNCH2), /* S_PUNCH1 */ + STATE_ENTRY(SPR_PUNG, 2, 4, a_punch, S_PUNCH3), /* S_PUNCH2 */ + STATE_ENTRY(SPR_PUNG, 3, 5, NULL, S_PUNCH4), /* S_PUNCH3 */ + STATE_ENTRY(SPR_PUNG, 2, 4, NULL, S_PUNCH5), /* S_PUNCH4 */ + STATE_ENTRY(SPR_PUNG, 1, 5, a_refire, S_PUNCH), /* S_PUNCH5 */ + STATE_ENTRY(SPR_PISG, 0, 1, a_weapon_ready, S_PISTOL), /* S_PISTOL */ + STATE_ENTRY(SPR_PISG, 0, 1, a_lower, S_PISTOLDOWN), /* S_PISTOLDOWN */ + STATE_ENTRY(SPR_PISG, 0, 1, a_raise, S_PISTOLUP), /* S_PISTOLUP */ + STATE_ENTRY(SPR_PISG, 0, 4, NULL, S_PISTOL2), /* S_PISTOL1 */ + STATE_ENTRY(SPR_PISG, 1, 6, a_fire_pistol, S_PISTOL3), /* S_PISTOL2 */ + STATE_ENTRY(SPR_PISG, 2, 4, NULL, S_PISTOL4), /* S_PISTOL3 */ + STATE_ENTRY(SPR_PISG, 1, 5, a_refire, S_PISTOL), /* S_PISTOL4 */ + STATE_ENTRY(SPR_PISF, 32768, 7, a_light1, + S_LIGHTDONE), /* S_PISTOLFLASH */ + STATE_ENTRY(SPR_SHTG, 0, 1, a_weapon_ready, S_SGUN), /* S_SGUN */ + STATE_ENTRY(SPR_SHTG, 0, 1, a_lower, S_SGUNDOWN), /* S_SGUNDOWN */ + STATE_ENTRY(SPR_SHTG, 0, 1, a_raise, S_SGUNUP), /* S_SGUNUP */ + STATE_ENTRY(SPR_SHTG, 0, 3, NULL, S_SGUN2), /* S_SGUN1 */ + STATE_ENTRY(SPR_SHTG, 0, 7, a_fire_shotgun, S_SGUN3), /* S_SGUN2 */ + STATE_ENTRY(SPR_SHTG, 1, 5, NULL, S_SGUN4), /* S_SGUN3 */ + STATE_ENTRY(SPR_SHTG, 2, 5, NULL, S_SGUN5), /* S_SGUN4 */ + STATE_ENTRY(SPR_SHTG, 3, 4, NULL, S_SGUN6), /* S_SGUN5 */ + STATE_ENTRY(SPR_SHTG, 2, 5, NULL, S_SGUN7), /* S_SGUN6 */ + STATE_ENTRY(SPR_SHTG, 1, 5, NULL, S_SGUN8), /* S_SGUN7 */ + STATE_ENTRY(SPR_SHTG, 0, 3, NULL, S_SGUN9), /* S_SGUN8 */ + STATE_ENTRY(SPR_SHTG, 0, 7, a_refire, S_SGUN), /* S_SGUN9 */ + STATE_ENTRY(SPR_SHTF, 32768, 4, a_light1, + S_SGUNFLASH2), /* S_SGUNFLASH1 */ + STATE_ENTRY(SPR_SHTF, 32769, 3, a_light2, S_LIGHTDONE), /* S_SGUNFLASH2 */ + STATE_ENTRY(SPR_SHT2, 0, 1, a_weapon_ready, S_DSGUN), /* S_DSGUN */ + STATE_ENTRY(SPR_SHT2, 0, 1, a_lower, S_DSGUNDOWN), /* S_DSGUNDOWN */ + STATE_ENTRY(SPR_SHT2, 0, 1, a_raise, S_DSGUNUP), /* S_DSGUNUP */ + STATE_ENTRY(SPR_SHT2, 0, 3, NULL, S_DSGUN2), /* S_DSGUN1 */ + STATE_ENTRY(SPR_SHT2, 0, 7, a_fire_shotgun2, S_DSGUN3), /* S_DSGUN2 */ + STATE_ENTRY(SPR_SHT2, 1, 7, NULL, S_DSGUN4), /* S_DSGUN3 */ + STATE_ENTRY(SPR_SHT2, 2, 7, a_check_reload, S_DSGUN5), /* S_DSGUN4 */ + STATE_ENTRY(SPR_SHT2, 3, 7, a_open_shotgun2, S_DSGUN6), /* S_DSGUN5 */ + STATE_ENTRY(SPR_SHT2, 4, 7, NULL, S_DSGUN7), /* S_DSGUN6 */ + STATE_ENTRY(SPR_SHT2, 5, 7, a_load_shotgun2, S_DSGUN8), /* S_DSGUN7 */ + STATE_ENTRY(SPR_SHT2, 6, 6, NULL, S_DSGUN9), /* S_DSGUN8 */ + STATE_ENTRY(SPR_SHT2, 7, 6, a_close_shotgun2, S_DSGUN10), /* S_DSGUN9 */ + STATE_ENTRY(SPR_SHT2, 0, 5, a_refire, S_DSGUN), /* S_DSGUN10 */ + STATE_ENTRY(SPR_SHT2, 1, 7, NULL, S_DSNR2), /* S_DSNR1 */ + STATE_ENTRY(SPR_SHT2, 0, 3, NULL, S_DSGUNDOWN), /* S_DSNR2 */ + STATE_ENTRY(SPR_SHT2, 32776, 5, a_light1, + S_DSGUNFLASH2), /* S_DSGUNFLASH1 */ + STATE_ENTRY(SPR_SHT2, 32777, 4, a_light2, + S_LIGHTDONE), /* S_DSGUNFLASH2 */ + STATE_ENTRY(SPR_CHGG, 0, 1, a_weapon_ready, S_CHAIN), /* S_CHAIN */ + STATE_ENTRY(SPR_CHGG, 0, 1, a_lower, S_CHAINDOWN), /* S_CHAINDOWN */ + STATE_ENTRY(SPR_CHGG, 0, 1, a_raise, S_CHAINUP), /* S_CHAINUP */ + STATE_ENTRY(SPR_CHGG, 0, 4, a_fire_cgun, S_CHAIN2), /* S_CHAIN1 */ + STATE_ENTRY(SPR_CHGG, 1, 4, a_fire_cgun, S_CHAIN3), /* S_CHAIN2 */ + STATE_ENTRY(SPR_CHGG, 1, 0, a_refire, S_CHAIN), /* S_CHAIN3 */ + STATE_ENTRY(SPR_CHGF, 32768, 5, a_light1, + S_LIGHTDONE), /* S_CHAINFLASH1 */ + STATE_ENTRY(SPR_CHGF, 32769, 5, a_light2, + S_LIGHTDONE), /* S_CHAINFLASH2 */ + STATE_ENTRY(SPR_MISG, 0, 1, a_weapon_ready, S_MISSILE), /* S_MISSILE */ + STATE_ENTRY(SPR_MISG, 0, 1, a_lower, S_MISSILEDOWN), /* S_MISSILEDOWN */ + STATE_ENTRY(SPR_MISG, 0, 1, a_raise, S_MISSILEUP), /* S_MISSILEUP */ + STATE_ENTRY(SPR_MISG, 1, 8, a_gun_flash, S_MISSILE2), /* S_MISSILE1 */ + STATE_ENTRY(SPR_MISG, 1, 12, a_fire_missile, S_MISSILE3), /* S_MISSILE2 */ + STATE_ENTRY(SPR_MISG, 1, 0, a_refire, S_MISSILE), /* S_MISSILE3 */ + STATE_ENTRY(SPR_MISF, 32768, 3, a_light1, + S_MISSILEFLASH2), /* S_MISSILEFLASH1 */ + STATE_ENTRY(SPR_MISF, 32769, 4, NULL, + S_MISSILEFLASH3), /* S_MISSILEFLASH2 */ + STATE_ENTRY(SPR_MISF, 32770, 4, a_light2, + S_MISSILEFLASH4), /* S_MISSILEFLASH3 */ + STATE_ENTRY(SPR_MISF, 32771, 4, a_light2, + S_LIGHTDONE), /* S_MISSILEFLASH4 */ + STATE_ENTRY(SPR_SAWG, 2, 4, a_weapon_ready, S_SAWB), /* S_SAW */ + STATE_ENTRY(SPR_SAWG, 3, 4, a_weapon_ready, S_SAW), /* S_SAWB */ + STATE_ENTRY(SPR_SAWG, 2, 1, a_lower, S_SAWDOWN), /* S_SAWDOWN */ + STATE_ENTRY(SPR_SAWG, 2, 1, a_raise, S_SAWUP), /* S_SAWUP */ + STATE_ENTRY(SPR_SAWG, 0, 4, a_saw, S_SAW2), /* S_SAW1 */ + STATE_ENTRY(SPR_SAWG, 1, 4, a_saw, S_SAW3), /* S_SAW2 */ + STATE_ENTRY(SPR_SAWG, 1, 0, a_refire, S_SAW), /* S_SAW3 */ + STATE_ENTRY(SPR_PLSG, 0, 1, a_weapon_ready, S_PLASMA), /* S_PLASMA */ + STATE_ENTRY(SPR_PLSG, 0, 1, a_lower, S_PLASMADOWN), /* S_PLASMADOWN */ + STATE_ENTRY(SPR_PLSG, 0, 1, a_raise, S_PLASMAUP), /* S_PLASMAUP */ + STATE_ENTRY(SPR_PLSG, 0, 3, a_fire_plasma, S_PLASMA2), /* S_PLASMA1 */ + STATE_ENTRY(SPR_PLSG, 1, 20, a_refire, S_PLASMA), /* S_PLASMA2 */ + STATE_ENTRY(SPR_PLSF, 32768, 4, a_light1, + S_LIGHTDONE), /* S_PLASMAFLASH1 */ + STATE_ENTRY(SPR_PLSF, 32769, 4, a_light1, + S_LIGHTDONE), /* S_PLASMAFLASH2 */ + STATE_ENTRY(SPR_BFGG, 0, 1, a_weapon_ready, S_BFG), /* S_BFG */ + STATE_ENTRY(SPR_BFGG, 0, 1, a_lower, S_BFGDOWN), /* S_BFGDOWN */ + STATE_ENTRY(SPR_BFGG, 0, 1, a_raise, S_BFGUP), /* S_BFGUP */ + STATE_ENTRY(SPR_BFGG, 0, 20, a_bfg_sound, S_BFG2), /* S_BFG1 */ + STATE_ENTRY(SPR_BFGG, 1, 10, a_gun_flash, S_BFG3), /* S_BFG2 */ + STATE_ENTRY(SPR_BFGG, 1, 10, a_fire_bfg, S_BFG4), /* S_BFG3 */ + STATE_ENTRY(SPR_BFGG, 1, 20, a_refire, S_BFG), /* S_BFG4 */ + STATE_ENTRY(SPR_BFGF, 32768, 11, a_light1, S_BFGFLASH2), /* S_BFGFLASH1 */ + STATE_ENTRY(SPR_BFGF, 32769, 6, a_light2, S_LIGHTDONE), /* S_BFGFLASH2 */ + STATE_ENTRY(SPR_BLUD, 2, 8, NULL, S_BLOOD2), /* S_BLOOD1 */ + STATE_ENTRY(SPR_BLUD, 1, 8, NULL, S_BLOOD3), /* S_BLOOD2 */ + STATE_ENTRY(SPR_BLUD, 0, 8, NULL, S_NULL), /* S_BLOOD3 */ + STATE_ENTRY(SPR_PUFF, 32768, 4, NULL, S_PUFF2), /* S_PUFF1 */ + STATE_ENTRY(SPR_PUFF, 1, 4, NULL, S_PUFF3), /* S_PUFF2 */ + STATE_ENTRY(SPR_PUFF, 2, 4, NULL, S_PUFF4), /* S_PUFF3 */ + STATE_ENTRY(SPR_PUFF, 3, 4, NULL, S_NULL), /* S_PUFF4 */ + STATE_ENTRY(SPR_BAL1, 32768, 4, NULL, S_TBALL2), /* S_TBALL1 */ + STATE_ENTRY(SPR_BAL1, 32769, 4, NULL, S_TBALL1), /* S_TBALL2 */ + STATE_ENTRY(SPR_BAL1, 32770, 6, NULL, S_TBALLX2), /* S_TBALLX1 */ + STATE_ENTRY(SPR_BAL1, 32771, 6, NULL, S_TBALLX3), /* S_TBALLX2 */ + STATE_ENTRY(SPR_BAL1, 32772, 6, NULL, S_NULL), /* S_TBALLX3 */ + STATE_ENTRY(SPR_BAL2, 32768, 4, NULL, S_RBALL2), /* S_RBALL1 */ + STATE_ENTRY(SPR_BAL2, 32769, 4, NULL, S_RBALL1), /* S_RBALL2 */ + STATE_ENTRY(SPR_BAL2, 32770, 6, NULL, S_RBALLX2), /* S_RBALLX1 */ + STATE_ENTRY(SPR_BAL2, 32771, 6, NULL, S_RBALLX3), /* S_RBALLX2 */ + STATE_ENTRY(SPR_BAL2, 32772, 6, NULL, S_NULL), /* S_RBALLX3 */ + STATE_ENTRY(SPR_PLSS, 32768, 6, NULL, S_PLASBALL2), /* S_PLASBALL */ + STATE_ENTRY(SPR_PLSS, 32769, 6, NULL, S_PLASBALL), /* S_PLASBALL2 */ + STATE_ENTRY(SPR_PLSE, 32768, 4, NULL, S_PLASEXP2), /* S_PLASEXP */ + STATE_ENTRY(SPR_PLSE, 32769, 4, NULL, S_PLASEXP3), /* S_PLASEXP2 */ + STATE_ENTRY(SPR_PLSE, 32770, 4, NULL, S_PLASEXP4), /* S_PLASEXP3 */ + STATE_ENTRY(SPR_PLSE, 32771, 4, NULL, S_PLASEXP5), /* S_PLASEXP4 */ + STATE_ENTRY(SPR_PLSE, 32772, 4, NULL, S_NULL), /* S_PLASEXP5 */ + STATE_ENTRY(SPR_MISL, 32768, 1, NULL, S_ROCKET), /* S_ROCKET */ + STATE_ENTRY(SPR_BFS1, 32768, 4, NULL, S_BFGSHOT2), /* S_BFGSHOT */ + STATE_ENTRY(SPR_BFS1, 32769, 4, NULL, S_BFGSHOT), /* S_BFGSHOT2 */ + STATE_ENTRY(SPR_BFE1, 32768, 8, NULL, S_BFGLAND2), /* S_BFGLAND */ + STATE_ENTRY(SPR_BFE1, 32769, 8, NULL, S_BFGLAND3), /* S_BFGLAND2 */ + STATE_ENTRY(SPR_BFE1, 32770, 8, a_bfg_spray, S_BFGLAND4), /* S_BFGLAND3 */ + STATE_ENTRY(SPR_BFE1, 32771, 8, NULL, S_BFGLAND5), /* S_BFGLAND4 */ + STATE_ENTRY(SPR_BFE1, 32772, 8, NULL, S_BFGLAND6), /* S_BFGLAND5 */ + STATE_ENTRY(SPR_BFE1, 32773, 8, NULL, S_NULL), /* S_BFGLAND6 */ + STATE_ENTRY(SPR_BFE2, 32768, 8, NULL, S_BFGEXP2), /* S_BFGEXP */ + STATE_ENTRY(SPR_BFE2, 32769, 8, NULL, S_BFGEXP3), /* S_BFGEXP2 */ + STATE_ENTRY(SPR_BFE2, 32770, 8, NULL, S_BFGEXP4), /* S_BFGEXP3 */ + STATE_ENTRY(SPR_BFE2, 32771, 8, NULL, S_NULL), /* S_BFGEXP4 */ + STATE_ENTRY(SPR_MISL, 32769, 8, a_explode, S_EXPLODE2), /* S_EXPLODE1 */ + STATE_ENTRY(SPR_MISL, 32770, 6, NULL, S_EXPLODE3), /* S_EXPLODE2 */ + STATE_ENTRY(SPR_MISL, 32771, 4, NULL, S_NULL), /* S_EXPLODE3 */ + STATE_ENTRY(SPR_TFOG, 32768, 6, NULL, S_TFOG01), /* S_TFOG */ + STATE_ENTRY(SPR_TFOG, 32769, 6, NULL, S_TFOG02), /* S_TFOG01 */ + STATE_ENTRY(SPR_TFOG, 32768, 6, NULL, S_TFOG2), /* S_TFOG02 */ + STATE_ENTRY(SPR_TFOG, 32769, 6, NULL, S_TFOG3), /* S_TFOG2 */ + STATE_ENTRY(SPR_TFOG, 32770, 6, NULL, S_TFOG4), /* S_TFOG3 */ + STATE_ENTRY(SPR_TFOG, 32771, 6, NULL, S_TFOG5), /* S_TFOG4 */ + STATE_ENTRY(SPR_TFOG, 32772, 6, NULL, S_TFOG6), /* S_TFOG5 */ + STATE_ENTRY(SPR_TFOG, 32773, 6, NULL, S_TFOG7), /* S_TFOG6 */ + STATE_ENTRY(SPR_TFOG, 32774, 6, NULL, S_TFOG8), /* S_TFOG7 */ + STATE_ENTRY(SPR_TFOG, 32775, 6, NULL, S_TFOG9), /* S_TFOG8 */ + STATE_ENTRY(SPR_TFOG, 32776, 6, NULL, S_TFOG10), /* S_TFOG9 */ + STATE_ENTRY(SPR_TFOG, 32777, 6, NULL, S_NULL), /* S_TFOG10 */ + STATE_ENTRY(SPR_IFOG, 32768, 6, NULL, S_IFOG01), /* S_IFOG */ + STATE_ENTRY(SPR_IFOG, 32769, 6, NULL, S_IFOG02), /* S_IFOG01 */ + STATE_ENTRY(SPR_IFOG, 32768, 6, NULL, S_IFOG2), /* S_IFOG02 */ + STATE_ENTRY(SPR_IFOG, 32769, 6, NULL, S_IFOG3), /* S_IFOG2 */ + STATE_ENTRY(SPR_IFOG, 32770, 6, NULL, S_IFOG4), /* S_IFOG3 */ + STATE_ENTRY(SPR_IFOG, 32771, 6, NULL, S_IFOG5), /* S_IFOG4 */ + STATE_ENTRY(SPR_IFOG, 32772, 6, NULL, S_NULL), /* S_IFOG5 */ + STATE_ENTRY(SPR_PLAY, 0, -1, NULL, S_NULL), /* S_PLAY */ + STATE_ENTRY(SPR_PLAY, 0, 4, NULL, S_PLAY_RUN2), /* S_PLAY_RUN1 */ + STATE_ENTRY(SPR_PLAY, 1, 4, NULL, S_PLAY_RUN3), /* S_PLAY_RUN2 */ + STATE_ENTRY(SPR_PLAY, 2, 4, NULL, S_PLAY_RUN4), /* S_PLAY_RUN3 */ + STATE_ENTRY(SPR_PLAY, 3, 4, NULL, S_PLAY_RUN1), /* S_PLAY_RUN4 */ + STATE_ENTRY(SPR_PLAY, 4, 12, NULL, S_PLAY), /* S_PLAY_ATK1 */ + STATE_ENTRY(SPR_PLAY, 32773, 6, NULL, S_PLAY_ATK1), /* S_PLAY_ATK2 */ + STATE_ENTRY(SPR_PLAY, 6, 4, NULL, S_PLAY_PAIN2), /* S_PLAY_PAIN */ + STATE_ENTRY(SPR_PLAY, 6, 4, a_pain, S_PLAY), /* S_PLAY_PAIN2 */ + STATE_ENTRY(SPR_PLAY, 7, 10, NULL, S_PLAY_DIE2), /* S_PLAY_DIE1 */ + STATE_ENTRY(SPR_PLAY, 8, 10, a_player_screm, + S_PLAY_DIE3), /* S_PLAY_DIE2 */ + STATE_ENTRY(SPR_PLAY, 9, 10, a_fall, S_PLAY_DIE4), /* S_PLAY_DIE3 */ + STATE_ENTRY(SPR_PLAY, 10, 10, NULL, S_PLAY_DIE5), /* S_PLAY_DIE4 */ + STATE_ENTRY(SPR_PLAY, 11, 10, NULL, S_PLAY_DIE6), /* S_PLAY_DIE5 */ + STATE_ENTRY(SPR_PLAY, 12, 10, NULL, S_PLAY_DIE7), /* S_PLAY_DIE6 */ + STATE_ENTRY(SPR_PLAY, 13, -1, NULL, S_NULL), /* S_PLAY_DIE7 */ + STATE_ENTRY(SPR_PLAY, 14, 5, NULL, S_PLAY_XDIE2), /* S_PLAY_XDIE1 */ + STATE_ENTRY(SPR_PLAY, 15, 5, a_xscream, S_PLAY_XDIE3), /* S_PLAY_XDIE2 */ + STATE_ENTRY(SPR_PLAY, 16, 5, a_fall, S_PLAY_XDIE4), /* S_PLAY_XDIE3 */ + STATE_ENTRY(SPR_PLAY, 17, 5, NULL, S_PLAY_XDIE5), /* S_PLAY_XDIE4 */ + STATE_ENTRY(SPR_PLAY, 18, 5, NULL, S_PLAY_XDIE6), /* S_PLAY_XDIE5 */ + STATE_ENTRY(SPR_PLAY, 19, 5, NULL, S_PLAY_XDIE7), /* S_PLAY_XDIE6 */ + STATE_ENTRY(SPR_PLAY, 20, 5, NULL, S_PLAY_XDIE8), /* S_PLAY_XDIE7 */ + STATE_ENTRY(SPR_PLAY, 21, 5, NULL, S_PLAY_XDIE9), /* S_PLAY_XDIE8 */ + STATE_ENTRY(SPR_PLAY, 22, -1, NULL, S_NULL), /* S_PLAY_XDIE9 */ + STATE_ENTRY(SPR_POSS, 0, 10, a_look, S_POSS_STND2), /* S_POSS_STND */ + STATE_ENTRY(SPR_POSS, 1, 10, a_look, S_POSS_STND), /* S_POSS_STND2 */ + STATE_ENTRY(SPR_POSS, 0, 4, a_chase, S_POSS_RUN2), /* S_POSS_RUN1 */ + STATE_ENTRY(SPR_POSS, 0, 4, a_chase, S_POSS_RUN3), /* S_POSS_RUN2 */ + STATE_ENTRY(SPR_POSS, 1, 4, a_chase, S_POSS_RUN4), /* S_POSS_RUN3 */ + STATE_ENTRY(SPR_POSS, 1, 4, a_chase, S_POSS_RUN5), /* S_POSS_RUN4 */ + STATE_ENTRY(SPR_POSS, 2, 4, a_chase, S_POSS_RUN6), /* S_POSS_RUN5 */ + STATE_ENTRY(SPR_POSS, 2, 4, a_chase, S_POSS_RUN7), /* S_POSS_RUN6 */ + STATE_ENTRY(SPR_POSS, 3, 4, a_chase, S_POSS_RUN8), /* S_POSS_RUN7 */ + STATE_ENTRY(SPR_POSS, 3, 4, a_chase, S_POSS_RUN1), /* S_POSS_RUN8 */ + STATE_ENTRY(SPR_POSS, 4, 10, a_face_target, + S_POSS_ATK2), /* S_POSS_ATK1 */ + STATE_ENTRY(SPR_POSS, 5, 8, a_pos_attack, S_POSS_ATK3), /* S_POSS_ATK2 */ + STATE_ENTRY(SPR_POSS, 4, 8, NULL, S_POSS_RUN1), /* S_POSS_ATK3 */ + STATE_ENTRY(SPR_POSS, 6, 3, NULL, S_POSS_PAIN2), /* S_POSS_PAIN */ + STATE_ENTRY(SPR_POSS, 6, 3, a_pain, S_POSS_RUN1), /* S_POSS_PAIN2 */ + STATE_ENTRY(SPR_POSS, 7, 5, NULL, S_POSS_DIE2), /* S_POSS_DIE1 */ + STATE_ENTRY(SPR_POSS, 8, 5, a_scream, S_POSS_DIE3), /* S_POSS_DIE2 */ + STATE_ENTRY(SPR_POSS, 9, 5, a_fall, S_POSS_DIE4), /* S_POSS_DIE3 */ + STATE_ENTRY(SPR_POSS, 10, 5, NULL, S_POSS_DIE5), /* S_POSS_DIE4 */ + STATE_ENTRY(SPR_POSS, 11, -1, NULL, S_NULL), /* S_POSS_DIE5 */ + STATE_ENTRY(SPR_POSS, 12, 5, NULL, S_POSS_XDIE2), /* S_POSS_XDIE1 */ + STATE_ENTRY(SPR_POSS, 13, 5, a_xscream, S_POSS_XDIE3), /* S_POSS_XDIE2 */ + STATE_ENTRY(SPR_POSS, 14, 5, a_fall, S_POSS_XDIE4), /* S_POSS_XDIE3 */ + STATE_ENTRY(SPR_POSS, 15, 5, NULL, S_POSS_XDIE5), /* S_POSS_XDIE4 */ + STATE_ENTRY(SPR_POSS, 16, 5, NULL, S_POSS_XDIE6), /* S_POSS_XDIE5 */ + STATE_ENTRY(SPR_POSS, 17, 5, NULL, S_POSS_XDIE7), /* S_POSS_XDIE6 */ + STATE_ENTRY(SPR_POSS, 18, 5, NULL, S_POSS_XDIE8), /* S_POSS_XDIE7 */ + STATE_ENTRY(SPR_POSS, 19, 5, NULL, S_POSS_XDIE9), /* S_POSS_XDIE8 */ + STATE_ENTRY(SPR_POSS, 20, -1, NULL, S_NULL), /* S_POSS_XDIE9 */ + STATE_ENTRY(SPR_POSS, 10, 5, NULL, S_POSS_RAISE2), /* S_POSS_RAISE1 */ + STATE_ENTRY(SPR_POSS, 9, 5, NULL, S_POSS_RAISE3), /* S_POSS_RAISE2 */ + STATE_ENTRY(SPR_POSS, 8, 5, NULL, S_POSS_RAISE4), /* S_POSS_RAISE3 */ + STATE_ENTRY(SPR_POSS, 7, 5, NULL, S_POSS_RUN1), /* S_POSS_RAISE4 */ + STATE_ENTRY(SPR_SPOS, 0, 10, a_look, S_SPOS_STND2), /* S_SPOS_STND */ + STATE_ENTRY(SPR_SPOS, 1, 10, a_look, S_SPOS_STND), /* S_SPOS_STND2 */ + STATE_ENTRY(SPR_SPOS, 0, 3, a_chase, S_SPOS_RUN2), /* S_SPOS_RUN1 */ + STATE_ENTRY(SPR_SPOS, 0, 3, a_chase, S_SPOS_RUN3), /* S_SPOS_RUN2 */ + STATE_ENTRY(SPR_SPOS, 1, 3, a_chase, S_SPOS_RUN4), /* S_SPOS_RUN3 */ + STATE_ENTRY(SPR_SPOS, 1, 3, a_chase, S_SPOS_RUN5), /* S_SPOS_RUN4 */ + STATE_ENTRY(SPR_SPOS, 2, 3, a_chase, S_SPOS_RUN6), /* S_SPOS_RUN5 */ + STATE_ENTRY(SPR_SPOS, 2, 3, a_chase, S_SPOS_RUN7), /* S_SPOS_RUN6 */ + STATE_ENTRY(SPR_SPOS, 3, 3, a_chase, S_SPOS_RUN8), /* S_SPOS_RUN7 */ + STATE_ENTRY(SPR_SPOS, 3, 3, a_chase, S_SPOS_RUN1), /* S_SPOS_RUN8 */ + STATE_ENTRY(SPR_SPOS, 4, 10, a_face_target, + S_SPOS_ATK2), /* S_SPOS_ATK1 */ + STATE_ENTRY(SPR_SPOS, 32773, 10, a_s_pos_attack, + S_SPOS_ATK3), /* S_SPOS_ATK2 */ + STATE_ENTRY(SPR_SPOS, 4, 10, NULL, S_SPOS_RUN1), /* S_SPOS_ATK3 */ + STATE_ENTRY(SPR_SPOS, 6, 3, NULL, S_SPOS_PAIN2), /* S_SPOS_PAIN */ + STATE_ENTRY(SPR_SPOS, 6, 3, a_pain, S_SPOS_RUN1), /* S_SPOS_PAIN2 */ + STATE_ENTRY(SPR_SPOS, 7, 5, NULL, S_SPOS_DIE2), /* S_SPOS_DIE1 */ + STATE_ENTRY(SPR_SPOS, 8, 5, a_scream, S_SPOS_DIE3), /* S_SPOS_DIE2 */ + STATE_ENTRY(SPR_SPOS, 9, 5, a_fall, S_SPOS_DIE4), /* S_SPOS_DIE3 */ + STATE_ENTRY(SPR_SPOS, 10, 5, NULL, S_SPOS_DIE5), /* S_SPOS_DIE4 */ + STATE_ENTRY(SPR_SPOS, 11, -1, NULL, S_NULL), /* S_SPOS_DIE5 */ + STATE_ENTRY(SPR_SPOS, 12, 5, NULL, S_SPOS_XDIE2), /* S_SPOS_XDIE1 */ + STATE_ENTRY(SPR_SPOS, 13, 5, a_xscream, S_SPOS_XDIE3), /* S_SPOS_XDIE2 */ + STATE_ENTRY(SPR_SPOS, 14, 5, a_fall, S_SPOS_XDIE4), /* S_SPOS_XDIE3 */ + STATE_ENTRY(SPR_SPOS, 15, 5, NULL, S_SPOS_XDIE5), /* S_SPOS_XDIE4 */ + STATE_ENTRY(SPR_SPOS, 16, 5, NULL, S_SPOS_XDIE6), /* S_SPOS_XDIE5 */ + STATE_ENTRY(SPR_SPOS, 17, 5, NULL, S_SPOS_XDIE7), /* S_SPOS_XDIE6 */ + STATE_ENTRY(SPR_SPOS, 18, 5, NULL, S_SPOS_XDIE8), /* S_SPOS_XDIE7 */ + STATE_ENTRY(SPR_SPOS, 19, 5, NULL, S_SPOS_XDIE9), /* S_SPOS_XDIE8 */ + STATE_ENTRY(SPR_SPOS, 20, -1, NULL, S_NULL), /* S_SPOS_XDIE9 */ + STATE_ENTRY(SPR_SPOS, 11, 5, NULL, S_SPOS_RAISE2), /* S_SPOS_RAISE1 */ + STATE_ENTRY(SPR_SPOS, 10, 5, NULL, S_SPOS_RAISE3), /* S_SPOS_RAISE2 */ + STATE_ENTRY(SPR_SPOS, 9, 5, NULL, S_SPOS_RAISE4), /* S_SPOS_RAISE3 */ + STATE_ENTRY(SPR_SPOS, 8, 5, NULL, S_SPOS_RAISE5), /* S_SPOS_RAISE4 */ + STATE_ENTRY(SPR_SPOS, 7, 5, NULL, S_SPOS_RUN1), /* S_SPOS_RAISE5 */ + STATE_ENTRY(SPR_VILE, 0, 10, a_look, S_VILE_STND2), /* S_VILE_STND */ + STATE_ENTRY(SPR_VILE, 1, 10, a_look, S_VILE_STND), /* S_VILE_STND2 */ + STATE_ENTRY(SPR_VILE, 0, 2, a_vile_chase, S_VILE_RUN2), /* S_VILE_RUN1 */ + STATE_ENTRY(SPR_VILE, 0, 2, a_vile_chase, S_VILE_RUN3), /* S_VILE_RUN2 */ + STATE_ENTRY(SPR_VILE, 1, 2, a_vile_chase, S_VILE_RUN4), /* S_VILE_RUN3 */ + STATE_ENTRY(SPR_VILE, 1, 2, a_vile_chase, S_VILE_RUN5), /* S_VILE_RUN4 */ + STATE_ENTRY(SPR_VILE, 2, 2, a_vile_chase, S_VILE_RUN6), /* S_VILE_RUN5 */ + STATE_ENTRY(SPR_VILE, 2, 2, a_vile_chase, S_VILE_RUN7), /* S_VILE_RUN6 */ + STATE_ENTRY(SPR_VILE, 3, 2, a_vile_chase, S_VILE_RUN8), /* S_VILE_RUN7 */ + STATE_ENTRY(SPR_VILE, 3, 2, a_vile_chase, S_VILE_RUN9), /* S_VILE_RUN8 */ + STATE_ENTRY(SPR_VILE, 4, 2, a_vile_chase, S_VILE_RUN10), /* S_VILE_RUN9 */ + STATE_ENTRY(SPR_VILE, 4, 2, a_vile_chase, + S_VILE_RUN11), /* S_VILE_RUN10 */ + STATE_ENTRY(SPR_VILE, 5, 2, a_vile_chase, + S_VILE_RUN12), /* S_VILE_RUN11 */ + STATE_ENTRY(SPR_VILE, 5, 2, a_vile_chase, S_VILE_RUN1), /* S_VILE_RUN12 */ + STATE_ENTRY(SPR_VILE, 32774, 0, a_vile_start, + S_VILE_ATK2), /* S_VILE_ATK1 */ + STATE_ENTRY(SPR_VILE, 32774, 10, a_face_target, + S_VILE_ATK3), /* S_VILE_ATK2 */ + STATE_ENTRY(SPR_VILE, 32775, 8, a_vile_target, + S_VILE_ATK4), /* S_VILE_ATK3 */ + STATE_ENTRY(SPR_VILE, 32776, 8, a_face_target, + S_VILE_ATK5), /* S_VILE_ATK4 */ + STATE_ENTRY(SPR_VILE, 32777, 8, a_face_target, + S_VILE_ATK6), /* S_VILE_ATK5 */ + STATE_ENTRY(SPR_VILE, 32778, 8, a_face_target, + S_VILE_ATK7), /* S_VILE_ATK6 */ + STATE_ENTRY(SPR_VILE, 32779, 8, a_face_target, + S_VILE_ATK8), /* S_VILE_ATK7 */ + STATE_ENTRY(SPR_VILE, 32780, 8, a_face_target, + S_VILE_ATK9), /* S_VILE_ATK8 */ + STATE_ENTRY(SPR_VILE, 32781, 8, a_face_target, + S_VILE_ATK10), /* S_VILE_ATK9 */ + STATE_ENTRY(SPR_VILE, 32782, 8, a_vile_attack, + S_VILE_ATK11), /* S_VILE_ATK10 */ + STATE_ENTRY(SPR_VILE, 32783, 20, NULL, S_VILE_RUN1), /* S_VILE_ATK11 */ + STATE_ENTRY(SPR_VILE, 32794, 10, NULL, S_VILE_HEAL2), /* S_VILE_HEAL1 */ + STATE_ENTRY(SPR_VILE, 32795, 10, NULL, S_VILE_HEAL3), /* S_VILE_HEAL2 */ + STATE_ENTRY(SPR_VILE, 32796, 10, NULL, S_VILE_RUN1), /* S_VILE_HEAL3 */ + STATE_ENTRY(SPR_VILE, 16, 5, NULL, S_VILE_PAIN2), /* S_VILE_PAIN */ + STATE_ENTRY(SPR_VILE, 16, 5, a_pain, S_VILE_RUN1), /* S_VILE_PAIN2 */ + STATE_ENTRY(SPR_VILE, 16, 7, NULL, S_VILE_DIE2), /* S_VILE_DIE1 */ + STATE_ENTRY(SPR_VILE, 17, 7, a_scream, S_VILE_DIE3), /* S_VILE_DIE2 */ + STATE_ENTRY(SPR_VILE, 18, 7, a_fall, S_VILE_DIE4), /* S_VILE_DIE3 */ + STATE_ENTRY(SPR_VILE, 19, 7, NULL, S_VILE_DIE5), /* S_VILE_DIE4 */ + STATE_ENTRY(SPR_VILE, 20, 7, NULL, S_VILE_DIE6), /* S_VILE_DIE5 */ + STATE_ENTRY(SPR_VILE, 21, 7, NULL, S_VILE_DIE7), /* S_VILE_DIE6 */ + STATE_ENTRY(SPR_VILE, 22, 7, NULL, S_VILE_DIE8), /* S_VILE_DIE7 */ + STATE_ENTRY(SPR_VILE, 23, 5, NULL, S_VILE_DIE9), /* S_VILE_DIE8 */ + STATE_ENTRY(SPR_VILE, 24, 5, NULL, S_VILE_DIE10), /* S_VILE_DIE9 */ + STATE_ENTRY(SPR_VILE, 25, -1, NULL, S_NULL), /* S_VILE_DIE10 */ + STATE_ENTRY(SPR_FIRE, 32768, 2, a_start_fire, + S_FIRE2), /* S_FIRE1 */ + STATE_ENTRY(SPR_FIRE, 32769, 2, a_fire, S_FIRE3), /* S_FIRE2 */ + STATE_ENTRY(SPR_FIRE, 32768, 2, a_fire, S_FIRE4), /* S_FIRE3 */ + STATE_ENTRY(SPR_FIRE, 32769, 2, a_fire, S_FIRE5), /* S_FIRE4 */ + STATE_ENTRY(SPR_FIRE, 32770, 2, a_fire_crackle, + S_FIRE6), /* S_FIRE5 */ + STATE_ENTRY(SPR_FIRE, 32769, 2, a_fire, S_FIRE7), /* S_FIRE6 */ + STATE_ENTRY(SPR_FIRE, 32770, 2, a_fire, S_FIRE8), /* S_FIRE7 */ + STATE_ENTRY(SPR_FIRE, 32769, 2, a_fire, S_FIRE9), /* S_FIRE8 */ + STATE_ENTRY(SPR_FIRE, 32770, 2, a_fire, S_FIRE10), /* S_FIRE9 */ + STATE_ENTRY(SPR_FIRE, 32771, 2, a_fire, S_FIRE11), /* S_FIRE10 */ + STATE_ENTRY(SPR_FIRE, 32770, 2, a_fire, S_FIRE12), /* S_FIRE11 */ + STATE_ENTRY(SPR_FIRE, 32771, 2, a_fire, S_FIRE13), /* S_FIRE12 */ + STATE_ENTRY(SPR_FIRE, 32770, 2, a_fire, S_FIRE14), /* S_FIRE13 */ + STATE_ENTRY(SPR_FIRE, 32771, 2, a_fire, S_FIRE15), /* S_FIRE14 */ + STATE_ENTRY(SPR_FIRE, 32772, 2, a_fire, S_FIRE16), /* S_FIRE15 */ + STATE_ENTRY(SPR_FIRE, 32771, 2, a_fire, S_FIRE17), /* S_FIRE16 */ + STATE_ENTRY(SPR_FIRE, 32772, 2, a_fire, S_FIRE18), /* S_FIRE17 */ + STATE_ENTRY(SPR_FIRE, 32771, 2, a_fire, S_FIRE19), /* S_FIRE18 */ + STATE_ENTRY(SPR_FIRE, 32772, 2, a_fire_crackle, + S_FIRE20), /* S_FIRE19 */ + STATE_ENTRY(SPR_FIRE, 32773, 2, a_fire, S_FIRE21), /* S_FIRE20 */ + STATE_ENTRY(SPR_FIRE, 32772, 2, a_fire, S_FIRE22), /* S_FIRE21 */ + STATE_ENTRY(SPR_FIRE, 32773, 2, a_fire, S_FIRE23), /* S_FIRE22 */ + STATE_ENTRY(SPR_FIRE, 32772, 2, a_fire, S_FIRE24), /* S_FIRE23 */ + STATE_ENTRY(SPR_FIRE, 32773, 2, a_fire, S_FIRE25), /* S_FIRE24 */ + STATE_ENTRY(SPR_FIRE, 32774, 2, a_fire, S_FIRE26), /* S_FIRE25 */ + STATE_ENTRY(SPR_FIRE, 32775, 2, a_fire, S_FIRE27), /* S_FIRE26 */ + STATE_ENTRY(SPR_FIRE, 32774, 2, a_fire, S_FIRE28), /* S_FIRE27 */ + STATE_ENTRY(SPR_FIRE, 32775, 2, a_fire, S_FIRE29), /* S_FIRE28 */ + STATE_ENTRY(SPR_FIRE, 32774, 2, a_fire, S_FIRE30), /* S_FIRE29 */ + STATE_ENTRY(SPR_FIRE, 32775, 2, a_fire, S_NULL), /* S_FIRE30 */ + STATE_ENTRY(SPR_PUFF, 1, 4, NULL, S_SMOKE2), /* S_SMOKE1 */ + STATE_ENTRY(SPR_PUFF, 2, 4, NULL, S_SMOKE3), /* S_SMOKE2 */ + STATE_ENTRY(SPR_PUFF, 1, 4, NULL, S_SMOKE4), /* S_SMOKE3 */ + STATE_ENTRY(SPR_PUFF, 2, 4, NULL, S_SMOKE5), /* S_SMOKE4 */ + STATE_ENTRY(SPR_PUFF, 3, 4, NULL, S_NULL), /* S_SMOKE5 */ + STATE_ENTRY(SPR_FATB, 32768, 2, a_tracer, S_TRACER2), /* S_TRACER */ + STATE_ENTRY(SPR_FATB, 32769, 2, a_tracer, S_TRACER), /* S_TRACER2 */ + STATE_ENTRY(SPR_FBXP, 32768, 8, NULL, S_TRACEEXP2), /* S_TRACEEXP1 */ + STATE_ENTRY(SPR_FBXP, 32769, 6, NULL, S_TRACEEXP3), /* S_TRACEEXP2 */ + STATE_ENTRY(SPR_FBXP, 32770, 4, NULL, S_NULL), /* S_TRACEEXP3 */ + STATE_ENTRY(SPR_SKEL, 0, 10, a_look, S_SKEL_STND2), /* S_SKEL_STND */ + STATE_ENTRY(SPR_SKEL, 1, 10, a_look, S_SKEL_STND), /* S_SKEL_STND2 */ + STATE_ENTRY(SPR_SKEL, 0, 2, a_chase, S_SKEL_RUN2), /* S_SKEL_RUN1 */ + STATE_ENTRY(SPR_SKEL, 0, 2, a_chase, S_SKEL_RUN3), /* S_SKEL_RUN2 */ + STATE_ENTRY(SPR_SKEL, 1, 2, a_chase, S_SKEL_RUN4), /* S_SKEL_RUN3 */ + STATE_ENTRY(SPR_SKEL, 1, 2, a_chase, S_SKEL_RUN5), /* S_SKEL_RUN4 */ + STATE_ENTRY(SPR_SKEL, 2, 2, a_chase, S_SKEL_RUN6), /* S_SKEL_RUN5 */ + STATE_ENTRY(SPR_SKEL, 2, 2, a_chase, S_SKEL_RUN7), /* S_SKEL_RUN6 */ + STATE_ENTRY(SPR_SKEL, 3, 2, a_chase, S_SKEL_RUN8), /* S_SKEL_RUN7 */ + STATE_ENTRY(SPR_SKEL, 3, 2, a_chase, S_SKEL_RUN9), /* S_SKEL_RUN8 */ + STATE_ENTRY(SPR_SKEL, 4, 2, a_chase, S_SKEL_RUN10), /* S_SKEL_RUN9 */ + STATE_ENTRY(SPR_SKEL, 4, 2, a_chase, S_SKEL_RUN11), /* S_SKEL_RUN10 */ + STATE_ENTRY(SPR_SKEL, 5, 2, a_chase, S_SKEL_RUN12), /* S_SKEL_RUN11 */ + STATE_ENTRY(SPR_SKEL, 5, 2, a_chase, S_SKEL_RUN1), /* S_SKEL_RUN12 */ + STATE_ENTRY(SPR_SKEL, 6, 0, a_face_target, + S_SKEL_FIST2), /* S_SKEL_FIST1 */ + STATE_ENTRY(SPR_SKEL, 6, 6, a_skel_woosh, + S_SKEL_FIST3), /* S_SKEL_FIST2 */ + STATE_ENTRY(SPR_SKEL, 7, 6, a_face_target, + S_SKEL_FIST4), /* S_SKEL_FIST3 */ + STATE_ENTRY(SPR_SKEL, 8, 6, a_skel_fist, S_SKEL_RUN1), /* S_SKEL_FIST4 */ + STATE_ENTRY(SPR_SKEL, 32777, 0, a_face_target, + S_SKEL_MISS2), /* S_SKEL_MISS1 */ + STATE_ENTRY(SPR_SKEL, 32777, 10, a_face_target, + S_SKEL_MISS3), /* S_SKEL_MISS2 */ + STATE_ENTRY(SPR_SKEL, 10, 10, a_skel_missile, + S_SKEL_MISS4), /* S_SKEL_MISS3 */ + STATE_ENTRY(SPR_SKEL, 10, 10, a_face_target, + S_SKEL_RUN1), /* S_SKEL_MISS4 */ + STATE_ENTRY(SPR_SKEL, 11, 5, NULL, S_SKEL_PAIN2), /* S_SKEL_PAIN */ + STATE_ENTRY(SPR_SKEL, 11, 5, a_pain, S_SKEL_RUN1), /* S_SKEL_PAIN2 */ + STATE_ENTRY(SPR_SKEL, 11, 7, NULL, S_SKEL_DIE2), /* S_SKEL_DIE1 */ + STATE_ENTRY(SPR_SKEL, 12, 7, NULL, S_SKEL_DIE3), /* S_SKEL_DIE2 */ + STATE_ENTRY(SPR_SKEL, 13, 7, a_scream, S_SKEL_DIE4), /* S_SKEL_DIE3 */ + STATE_ENTRY(SPR_SKEL, 14, 7, a_fall, S_SKEL_DIE5), /* S_SKEL_DIE4 */ + STATE_ENTRY(SPR_SKEL, 15, 7, NULL, S_SKEL_DIE6), /* S_SKEL_DIE5 */ + STATE_ENTRY(SPR_SKEL, 16, -1, NULL, S_NULL), /* S_SKEL_DIE6 */ + STATE_ENTRY(SPR_SKEL, 16, 5, NULL, S_SKEL_RAISE2), /* S_SKEL_RAISE1 */ + STATE_ENTRY(SPR_SKEL, 15, 5, NULL, S_SKEL_RAISE3), /* S_SKEL_RAISE2 */ + STATE_ENTRY(SPR_SKEL, 14, 5, NULL, S_SKEL_RAISE4), /* S_SKEL_RAISE3 */ + STATE_ENTRY(SPR_SKEL, 13, 5, NULL, S_SKEL_RAISE5), /* S_SKEL_RAISE4 */ + STATE_ENTRY(SPR_SKEL, 12, 5, NULL, S_SKEL_RAISE6), /* S_SKEL_RAISE5 */ + STATE_ENTRY(SPR_SKEL, 11, 5, NULL, S_SKEL_RUN1), /* S_SKEL_RAISE6 */ + STATE_ENTRY(SPR_MANF, 32768, 4, NULL, S_FATSHOT2), /* S_FATSHOT1 */ + STATE_ENTRY(SPR_MANF, 32769, 4, NULL, S_FATSHOT1), /* S_FATSHOT2 */ + STATE_ENTRY(SPR_MISL, 32769, 8, NULL, S_FATSHOTX2), /* S_FATSHOTX1 */ + STATE_ENTRY(SPR_MISL, 32770, 6, NULL, S_FATSHOTX3), /* S_FATSHOTX2 */ + STATE_ENTRY(SPR_MISL, 32771, 4, NULL, S_NULL), /* S_FATSHOTX3 */ + STATE_ENTRY(SPR_FATT, 0, 15, a_look, S_FATT_STND2), /* S_FATT_STND */ + STATE_ENTRY(SPR_FATT, 1, 15, a_look, S_FATT_STND), /* S_FATT_STND2 */ + STATE_ENTRY(SPR_FATT, 0, 4, a_chase, S_FATT_RUN2), /* S_FATT_RUN1 */ + STATE_ENTRY(SPR_FATT, 0, 4, a_chase, S_FATT_RUN3), /* S_FATT_RUN2 */ + STATE_ENTRY(SPR_FATT, 1, 4, a_chase, S_FATT_RUN4), /* S_FATT_RUN3 */ + STATE_ENTRY(SPR_FATT, 1, 4, a_chase, S_FATT_RUN5), /* S_FATT_RUN4 */ + STATE_ENTRY(SPR_FATT, 2, 4, a_chase, S_FATT_RUN6), /* S_FATT_RUN5 */ + STATE_ENTRY(SPR_FATT, 2, 4, a_chase, S_FATT_RUN7), /* S_FATT_RUN6 */ + STATE_ENTRY(SPR_FATT, 3, 4, a_chase, S_FATT_RUN8), /* S_FATT_RUN7 */ + STATE_ENTRY(SPR_FATT, 3, 4, a_chase, S_FATT_RUN9), /* S_FATT_RUN8 */ + STATE_ENTRY(SPR_FATT, 4, 4, a_chase, S_FATT_RUN10), /* S_FATT_RUN9 */ + STATE_ENTRY(SPR_FATT, 4, 4, a_chase, S_FATT_RUN11), /* S_FATT_RUN10 */ + STATE_ENTRY(SPR_FATT, 5, 4, a_chase, S_FATT_RUN12), /* S_FATT_RUN11 */ + STATE_ENTRY(SPR_FATT, 5, 4, a_chase, S_FATT_RUN1), /* S_FATT_RUN12 */ + STATE_ENTRY(SPR_FATT, 6, 20, a_fat_raise, S_FATT_ATK2), /* S_FATT_ATK1 */ + STATE_ENTRY(SPR_FATT, 32775, 10, a_fat_attack1, + S_FATT_ATK3), /* S_FATT_ATK2 */ + STATE_ENTRY(SPR_FATT, 8, 5, a_face_target, S_FATT_ATK4), /* S_FATT_ATK3 */ + STATE_ENTRY(SPR_FATT, 6, 5, a_face_target, S_FATT_ATK5), /* S_FATT_ATK4 */ + STATE_ENTRY(SPR_FATT, 32775, 10, a_fat_attack2, + S_FATT_ATK6), /* S_FATT_ATK5 */ + STATE_ENTRY(SPR_FATT, 8, 5, a_face_target, S_FATT_ATK7), /* S_FATT_ATK6 */ + STATE_ENTRY(SPR_FATT, 6, 5, a_face_target, S_FATT_ATK8), /* S_FATT_ATK7 */ + STATE_ENTRY(SPR_FATT, 32775, 10, a_fat_attack3, + S_FATT_ATK9), /* S_FATT_ATK8 */ + STATE_ENTRY(SPR_FATT, 8, 5, a_face_target, + S_FATT_ATK10), /* S_FATT_ATK9 */ + STATE_ENTRY(SPR_FATT, 6, 5, a_face_target, + S_FATT_RUN1), /* S_FATT_ATK10 */ + STATE_ENTRY(SPR_FATT, 9, 3, NULL, S_FATT_PAIN2), /* S_FATT_PAIN */ + STATE_ENTRY(SPR_FATT, 9, 3, a_pain, S_FATT_RUN1), /* S_FATT_PAIN2 */ + STATE_ENTRY(SPR_FATT, 10, 6, NULL, S_FATT_DIE2), /* S_FATT_DIE1 */ + STATE_ENTRY(SPR_FATT, 11, 6, a_scream, S_FATT_DIE3), /* S_FATT_DIE2 */ + STATE_ENTRY(SPR_FATT, 12, 6, a_fall, S_FATT_DIE4), /* S_FATT_DIE3 */ + STATE_ENTRY(SPR_FATT, 13, 6, NULL, S_FATT_DIE5), /* S_FATT_DIE4 */ + STATE_ENTRY(SPR_FATT, 14, 6, NULL, S_FATT_DIE6), /* S_FATT_DIE5 */ + STATE_ENTRY(SPR_FATT, 15, 6, NULL, S_FATT_DIE7), /* S_FATT_DIE6 */ + STATE_ENTRY(SPR_FATT, 16, 6, NULL, S_FATT_DIE8), /* S_FATT_DIE7 */ + STATE_ENTRY(SPR_FATT, 17, 6, NULL, S_FATT_DIE9), /* S_FATT_DIE8 */ + STATE_ENTRY(SPR_FATT, 18, 6, NULL, S_FATT_DIE10), /* S_FATT_DIE9 */ + STATE_ENTRY(SPR_FATT, 19, -1, a_boss_death, S_NULL), /* S_FATT_DIE10 */ + STATE_ENTRY(SPR_FATT, 17, 5, NULL, S_FATT_RAISE2), /* S_FATT_RAISE1 */ + STATE_ENTRY(SPR_FATT, 16, 5, NULL, S_FATT_RAISE3), /* S_FATT_RAISE2 */ + STATE_ENTRY(SPR_FATT, 15, 5, NULL, S_FATT_RAISE4), /* S_FATT_RAISE3 */ + STATE_ENTRY(SPR_FATT, 14, 5, NULL, S_FATT_RAISE5), /* S_FATT_RAISE4 */ + STATE_ENTRY(SPR_FATT, 13, 5, NULL, S_FATT_RAISE6), /* S_FATT_RAISE5 */ + STATE_ENTRY(SPR_FATT, 12, 5, NULL, S_FATT_RAISE7), /* S_FATT_RAISE6 */ + STATE_ENTRY(SPR_FATT, 11, 5, NULL, S_FATT_RAISE8), /* S_FATT_RAISE7 */ + STATE_ENTRY(SPR_FATT, 10, 5, NULL, S_FATT_RUN1), /* S_FATT_RAISE8 */ + STATE_ENTRY(SPR_CPOS, 0, 10, a_look, S_CPOS_STND2), /* S_CPOS_STND */ + STATE_ENTRY(SPR_CPOS, 1, 10, a_look, S_CPOS_STND), /* S_CPOS_STND2 */ + STATE_ENTRY(SPR_CPOS, 0, 3, a_chase, S_CPOS_RUN2), /* S_CPOS_RUN1 */ + STATE_ENTRY(SPR_CPOS, 0, 3, a_chase, S_CPOS_RUN3), /* S_CPOS_RUN2 */ + STATE_ENTRY(SPR_CPOS, 1, 3, a_chase, S_CPOS_RUN4), /* S_CPOS_RUN3 */ + STATE_ENTRY(SPR_CPOS, 1, 3, a_chase, S_CPOS_RUN5), /* S_CPOS_RUN4 */ + STATE_ENTRY(SPR_CPOS, 2, 3, a_chase, S_CPOS_RUN6), /* S_CPOS_RUN5 */ + STATE_ENTRY(SPR_CPOS, 2, 3, a_chase, S_CPOS_RUN7), /* S_CPOS_RUN6 */ + STATE_ENTRY(SPR_CPOS, 3, 3, a_chase, S_CPOS_RUN8), /* S_CPOS_RUN7 */ + STATE_ENTRY(SPR_CPOS, 3, 3, a_chase, S_CPOS_RUN1), /* S_CPOS_RUN8 */ + STATE_ENTRY(SPR_CPOS, 4, 10, a_face_target, + S_CPOS_ATK2), /* S_CPOS_ATK1 */ + STATE_ENTRY(SPR_CPOS, 32773, 4, a_c_pos_attack, + S_CPOS_ATK3), /* S_CPOS_ATK2 */ + STATE_ENTRY(SPR_CPOS, 32772, 4, a_c_pos_attack, + S_CPOS_ATK4), /* S_CPOS_ATK3 */ + STATE_ENTRY(SPR_CPOS, 5, 1, a_c_pos_refire, + S_CPOS_ATK2), /* S_CPOS_ATK4 */ + STATE_ENTRY(SPR_CPOS, 6, 3, NULL, S_CPOS_PAIN2), /* S_CPOS_PAIN */ + STATE_ENTRY(SPR_CPOS, 6, 3, a_pain, S_CPOS_RUN1), /* S_CPOS_PAIN2 */ + STATE_ENTRY(SPR_CPOS, 7, 5, NULL, S_CPOS_DIE2), /* S_CPOS_DIE1 */ + STATE_ENTRY(SPR_CPOS, 8, 5, a_scream, S_CPOS_DIE3), /* S_CPOS_DIE2 */ + STATE_ENTRY(SPR_CPOS, 9, 5, a_fall, S_CPOS_DIE4), /* S_CPOS_DIE3 */ + STATE_ENTRY(SPR_CPOS, 10, 5, NULL, S_CPOS_DIE5), /* S_CPOS_DIE4 */ + STATE_ENTRY(SPR_CPOS, 11, 5, NULL, S_CPOS_DIE6), /* S_CPOS_DIE5 */ + STATE_ENTRY(SPR_CPOS, 12, 5, NULL, S_CPOS_DIE7), /* S_CPOS_DIE6 */ + STATE_ENTRY(SPR_CPOS, 13, -1, NULL, S_NULL), /* S_CPOS_DIE7 */ + STATE_ENTRY(SPR_CPOS, 14, 5, NULL, S_CPOS_XDIE2), /* S_CPOS_XDIE1 */ + STATE_ENTRY(SPR_CPOS, 15, 5, a_xscream, S_CPOS_XDIE3), /* S_CPOS_XDIE2 */ + STATE_ENTRY(SPR_CPOS, 16, 5, a_fall, S_CPOS_XDIE4), /* S_CPOS_XDIE3 */ + STATE_ENTRY(SPR_CPOS, 17, 5, NULL, S_CPOS_XDIE5), /* S_CPOS_XDIE4 */ + STATE_ENTRY(SPR_CPOS, 18, 5, NULL, S_CPOS_XDIE6), /* S_CPOS_XDIE5 */ + STATE_ENTRY(SPR_CPOS, 19, -1, NULL, S_NULL), /* S_CPOS_XDIE6 */ + STATE_ENTRY(SPR_CPOS, 13, 5, NULL, S_CPOS_RAISE2), /* S_CPOS_RAISE1 */ + STATE_ENTRY(SPR_CPOS, 12, 5, NULL, S_CPOS_RAISE3), /* S_CPOS_RAISE2 */ + STATE_ENTRY(SPR_CPOS, 11, 5, NULL, S_CPOS_RAISE4), /* S_CPOS_RAISE3 */ + STATE_ENTRY(SPR_CPOS, 10, 5, NULL, S_CPOS_RAISE5), /* S_CPOS_RAISE4 */ + STATE_ENTRY(SPR_CPOS, 9, 5, NULL, S_CPOS_RAISE6), /* S_CPOS_RAISE5 */ + STATE_ENTRY(SPR_CPOS, 8, 5, NULL, S_CPOS_RAISE7), /* S_CPOS_RAISE6 */ + STATE_ENTRY(SPR_CPOS, 7, 5, NULL, S_CPOS_RUN1), /* S_CPOS_RAISE7 */ + STATE_ENTRY(SPR_TROO, 0, 10, a_look, S_TROO_STND2), /* S_TROO_STND */ + STATE_ENTRY(SPR_TROO, 1, 10, a_look, S_TROO_STND), /* S_TROO_STND2 */ + STATE_ENTRY(SPR_TROO, 0, 3, a_chase, S_TROO_RUN2), /* S_TROO_RUN1 */ + STATE_ENTRY(SPR_TROO, 0, 3, a_chase, S_TROO_RUN3), /* S_TROO_RUN2 */ + STATE_ENTRY(SPR_TROO, 1, 3, a_chase, S_TROO_RUN4), /* S_TROO_RUN3 */ + STATE_ENTRY(SPR_TROO, 1, 3, a_chase, S_TROO_RUN5), /* S_TROO_RUN4 */ + STATE_ENTRY(SPR_TROO, 2, 3, a_chase, S_TROO_RUN6), /* S_TROO_RUN5 */ + STATE_ENTRY(SPR_TROO, 2, 3, a_chase, S_TROO_RUN7), /* S_TROO_RUN6 */ + STATE_ENTRY(SPR_TROO, 3, 3, a_chase, S_TROO_RUN8), /* S_TROO_RUN7 */ + STATE_ENTRY(SPR_TROO, 3, 3, a_chase, S_TROO_RUN1), /* S_TROO_RUN8 */ + STATE_ENTRY(SPR_TROO, 4, 8, a_face_target, S_TROO_ATK2), /* S_TROO_ATK1 */ + STATE_ENTRY(SPR_TROO, 5, 8, a_face_target, S_TROO_ATK3), /* S_TROO_ATK2 */ + STATE_ENTRY(SPR_TROO, 6, 6, a_troop_attack, + S_TROO_RUN1), /* S_TROO_ATK3 */ + STATE_ENTRY(SPR_TROO, 7, 2, NULL, S_TROO_PAIN2), /* S_TROO_PAIN */ + STATE_ENTRY(SPR_TROO, 7, 2, a_pain, S_TROO_RUN1), /* S_TROO_PAIN2 */ + STATE_ENTRY(SPR_TROO, 8, 8, NULL, S_TROO_DIE2), /* S_TROO_DIE1 */ + STATE_ENTRY(SPR_TROO, 9, 8, a_scream, S_TROO_DIE3), /* S_TROO_DIE2 */ + STATE_ENTRY(SPR_TROO, 10, 6, NULL, S_TROO_DIE4), /* S_TROO_DIE3 */ + STATE_ENTRY(SPR_TROO, 11, 6, a_fall, S_TROO_DIE5), /* S_TROO_DIE4 */ + STATE_ENTRY(SPR_TROO, 12, -1, NULL, S_NULL), /* S_TROO_DIE5 */ + STATE_ENTRY(SPR_TROO, 13, 5, NULL, S_TROO_XDIE2), /* S_TROO_XDIE1 */ + STATE_ENTRY(SPR_TROO, 14, 5, a_xscream, S_TROO_XDIE3), /* S_TROO_XDIE2 */ + STATE_ENTRY(SPR_TROO, 15, 5, NULL, S_TROO_XDIE4), /* S_TROO_XDIE3 */ + STATE_ENTRY(SPR_TROO, 16, 5, a_fall, S_TROO_XDIE5), /* S_TROO_XDIE4 */ + STATE_ENTRY(SPR_TROO, 17, 5, NULL, S_TROO_XDIE6), /* S_TROO_XDIE5 */ + STATE_ENTRY(SPR_TROO, 18, 5, NULL, S_TROO_XDIE7), /* S_TROO_XDIE6 */ + STATE_ENTRY(SPR_TROO, 19, 5, NULL, S_TROO_XDIE8), /* S_TROO_XDIE7 */ + STATE_ENTRY(SPR_TROO, 20, -1, NULL, S_NULL), /* S_TROO_XDIE8 */ + STATE_ENTRY(SPR_TROO, 12, 8, NULL, S_TROO_RAISE2), /* S_TROO_RAISE1 */ + STATE_ENTRY(SPR_TROO, 11, 8, NULL, S_TROO_RAISE3), /* S_TROO_RAISE2 */ + STATE_ENTRY(SPR_TROO, 10, 6, NULL, S_TROO_RAISE4), /* S_TROO_RAISE3 */ + STATE_ENTRY(SPR_TROO, 9, 6, NULL, S_TROO_RAISE5), /* S_TROO_RAISE4 */ + STATE_ENTRY(SPR_TROO, 8, 6, NULL, S_TROO_RUN1), /* S_TROO_RAISE5 */ + STATE_ENTRY(SPR_SARG, 0, 10, a_look, S_SARG_STND2), /* S_SARG_STND */ + STATE_ENTRY(SPR_SARG, 1, 10, a_look, S_SARG_STND), /* S_SARG_STND2 */ + STATE_ENTRY(SPR_SARG, 0, 2, a_chase, S_SARG_RUN2), /* S_SARG_RUN1 */ + STATE_ENTRY(SPR_SARG, 0, 2, a_chase, S_SARG_RUN3), /* S_SARG_RUN2 */ + STATE_ENTRY(SPR_SARG, 1, 2, a_chase, S_SARG_RUN4), /* S_SARG_RUN3 */ + STATE_ENTRY(SPR_SARG, 1, 2, a_chase, S_SARG_RUN5), /* S_SARG_RUN4 */ + STATE_ENTRY(SPR_SARG, 2, 2, a_chase, S_SARG_RUN6), /* S_SARG_RUN5 */ + STATE_ENTRY(SPR_SARG, 2, 2, a_chase, S_SARG_RUN7), /* S_SARG_RUN6 */ + STATE_ENTRY(SPR_SARG, 3, 2, a_chase, S_SARG_RUN8), /* S_SARG_RUN7 */ + STATE_ENTRY(SPR_SARG, 3, 2, a_chase, S_SARG_RUN1), /* S_SARG_RUN8 */ + STATE_ENTRY(SPR_SARG, 4, 8, a_face_target, S_SARG_ATK2), /* S_SARG_ATK1 */ + STATE_ENTRY(SPR_SARG, 5, 8, a_face_target, S_SARG_ATK3), /* S_SARG_ATK2 */ + STATE_ENTRY(SPR_SARG, 6, 8, a_sarg_attack, S_SARG_RUN1), /* S_SARG_ATK3 */ + STATE_ENTRY(SPR_SARG, 7, 2, NULL, S_SARG_PAIN2), /* S_SARG_PAIN */ + STATE_ENTRY(SPR_SARG, 7, 2, a_pain, S_SARG_RUN1), /* S_SARG_PAIN2 */ + STATE_ENTRY(SPR_SARG, 8, 8, NULL, S_SARG_DIE2), /* S_SARG_DIE1 */ + STATE_ENTRY(SPR_SARG, 9, 8, a_scream, S_SARG_DIE3), /* S_SARG_DIE2 */ + STATE_ENTRY(SPR_SARG, 10, 4, NULL, S_SARG_DIE4), /* S_SARG_DIE3 */ + STATE_ENTRY(SPR_SARG, 11, 4, a_fall, S_SARG_DIE5), /* S_SARG_DIE4 */ + STATE_ENTRY(SPR_SARG, 12, 4, NULL, S_SARG_DIE6), /* S_SARG_DIE5 */ + STATE_ENTRY(SPR_SARG, 13, -1, NULL, S_NULL), /* S_SARG_DIE6 */ + STATE_ENTRY(SPR_SARG, 13, 5, NULL, S_SARG_RAISE2), /* S_SARG_RAISE1 */ + STATE_ENTRY(SPR_SARG, 12, 5, NULL, S_SARG_RAISE3), /* S_SARG_RAISE2 */ + STATE_ENTRY(SPR_SARG, 11, 5, NULL, S_SARG_RAISE4), /* S_SARG_RAISE3 */ + STATE_ENTRY(SPR_SARG, 10, 5, NULL, S_SARG_RAISE5), /* S_SARG_RAISE4 */ + STATE_ENTRY(SPR_SARG, 9, 5, NULL, S_SARG_RAISE6), /* S_SARG_RAISE5 */ + STATE_ENTRY(SPR_SARG, 8, 5, NULL, S_SARG_RUN1), /* S_SARG_RAISE6 */ + STATE_ENTRY(SPR_HEAD, 0, 10, a_look, S_HEAD_STND), /* S_HEAD_STND */ + STATE_ENTRY(SPR_HEAD, 0, 3, a_chase, S_HEAD_RUN1), /* S_HEAD_RUN1 */ + STATE_ENTRY(SPR_HEAD, 1, 5, a_face_target, S_HEAD_ATK2), /* S_HEAD_ATK1 */ + STATE_ENTRY(SPR_HEAD, 2, 5, a_face_target, S_HEAD_ATK3), /* S_HEAD_ATK2 */ + STATE_ENTRY(SPR_HEAD, 32771, 5, a_head_attack, + S_HEAD_RUN1), /* S_HEAD_ATK3 */ + STATE_ENTRY(SPR_HEAD, 4, 3, NULL, S_HEAD_PAIN2), /* S_HEAD_PAIN */ + STATE_ENTRY(SPR_HEAD, 4, 3, a_pain, S_HEAD_PAIN3), /* S_HEAD_PAIN2 */ + STATE_ENTRY(SPR_HEAD, 5, 6, NULL, S_HEAD_RUN1), /* S_HEAD_PAIN3 */ + STATE_ENTRY(SPR_HEAD, 6, 8, NULL, S_HEAD_DIE2), /* S_HEAD_DIE1 */ + STATE_ENTRY(SPR_HEAD, 7, 8, a_scream, S_HEAD_DIE3), /* S_HEAD_DIE2 */ + STATE_ENTRY(SPR_HEAD, 8, 8, NULL, S_HEAD_DIE4), /* S_HEAD_DIE3 */ + STATE_ENTRY(SPR_HEAD, 9, 8, NULL, S_HEAD_DIE5), /* S_HEAD_DIE4 */ + STATE_ENTRY(SPR_HEAD, 10, 8, a_fall, S_HEAD_DIE6), /* S_HEAD_DIE5 */ + STATE_ENTRY(SPR_HEAD, 11, -1, NULL, S_NULL), /* S_HEAD_DIE6 */ + STATE_ENTRY(SPR_HEAD, 11, 8, NULL, S_HEAD_RAISE2), /* S_HEAD_RAISE1 */ + STATE_ENTRY(SPR_HEAD, 10, 8, NULL, S_HEAD_RAISE3), /* S_HEAD_RAISE2 */ + STATE_ENTRY(SPR_HEAD, 9, 8, NULL, S_HEAD_RAISE4), /* S_HEAD_RAISE3 */ + STATE_ENTRY(SPR_HEAD, 8, 8, NULL, S_HEAD_RAISE5), /* S_HEAD_RAISE4 */ + STATE_ENTRY(SPR_HEAD, 7, 8, NULL, S_HEAD_RAISE6), /* S_HEAD_RAISE5 */ + STATE_ENTRY(SPR_HEAD, 6, 8, NULL, S_HEAD_RUN1), /* S_HEAD_RAISE6 */ + STATE_ENTRY(SPR_BAL7, 32768, 4, NULL, S_BRBALL2), /* S_BRBALL1 */ + STATE_ENTRY(SPR_BAL7, 32769, 4, NULL, S_BRBALL1), /* S_BRBALL2 */ + STATE_ENTRY(SPR_BAL7, 32770, 6, NULL, S_BRBALLX2), /* S_BRBALLX1 */ + STATE_ENTRY(SPR_BAL7, 32771, 6, NULL, S_BRBALLX3), /* S_BRBALLX2 */ + STATE_ENTRY(SPR_BAL7, 32772, 6, NULL, S_NULL), /* S_BRBALLX3 */ + STATE_ENTRY(SPR_BOSS, 0, 10, a_look, S_BOSS_STND2), /* S_BOSS_STND */ + STATE_ENTRY(SPR_BOSS, 1, 10, a_look, S_BOSS_STND), /* S_BOSS_STND2 */ + STATE_ENTRY(SPR_BOSS, 0, 3, a_chase, S_BOSS_RUN2), /* S_BOSS_RUN1 */ + STATE_ENTRY(SPR_BOSS, 0, 3, a_chase, S_BOSS_RUN3), /* S_BOSS_RUN2 */ + STATE_ENTRY(SPR_BOSS, 1, 3, a_chase, S_BOSS_RUN4), /* S_BOSS_RUN3 */ + STATE_ENTRY(SPR_BOSS, 1, 3, a_chase, S_BOSS_RUN5), /* S_BOSS_RUN4 */ + STATE_ENTRY(SPR_BOSS, 2, 3, a_chase, S_BOSS_RUN6), /* S_BOSS_RUN5 */ + STATE_ENTRY(SPR_BOSS, 2, 3, a_chase, S_BOSS_RUN7), /* S_BOSS_RUN6 */ + STATE_ENTRY(SPR_BOSS, 3, 3, a_chase, S_BOSS_RUN8), /* S_BOSS_RUN7 */ + STATE_ENTRY(SPR_BOSS, 3, 3, a_chase, S_BOSS_RUN1), /* S_BOSS_RUN8 */ + STATE_ENTRY(SPR_BOSS, 4, 8, a_face_target, S_BOSS_ATK2), /* S_BOSS_ATK1 */ + STATE_ENTRY(SPR_BOSS, 5, 8, a_face_target, S_BOSS_ATK3), /* S_BOSS_ATK2 */ + STATE_ENTRY(SPR_BOSS, 6, 8, a_bruis_attack, + S_BOSS_RUN1), /* S_BOSS_ATK3 */ + STATE_ENTRY(SPR_BOSS, 7, 2, NULL, S_BOSS_PAIN2), /* S_BOSS_PAIN */ + STATE_ENTRY(SPR_BOSS, 7, 2, a_pain, S_BOSS_RUN1), /* S_BOSS_PAIN2 */ + STATE_ENTRY(SPR_BOSS, 8, 8, NULL, S_BOSS_DIE2), /* S_BOSS_DIE1 */ + STATE_ENTRY(SPR_BOSS, 9, 8, a_scream, S_BOSS_DIE3), /* S_BOSS_DIE2 */ + STATE_ENTRY(SPR_BOSS, 10, 8, NULL, S_BOSS_DIE4), /* S_BOSS_DIE3 */ + STATE_ENTRY(SPR_BOSS, 11, 8, a_fall, S_BOSS_DIE5), /* S_BOSS_DIE4 */ + STATE_ENTRY(SPR_BOSS, 12, 8, NULL, S_BOSS_DIE6), /* S_BOSS_DIE5 */ + STATE_ENTRY(SPR_BOSS, 13, 8, NULL, S_BOSS_DIE7), /* S_BOSS_DIE6 */ + STATE_ENTRY(SPR_BOSS, 14, -1, a_boss_death, S_NULL), /* S_BOSS_DIE7 */ + STATE_ENTRY(SPR_BOSS, 14, 8, NULL, S_BOSS_RAISE2), /* S_BOSS_RAISE1 */ + STATE_ENTRY(SPR_BOSS, 13, 8, NULL, S_BOSS_RAISE3), /* S_BOSS_RAISE2 */ + STATE_ENTRY(SPR_BOSS, 12, 8, NULL, S_BOSS_RAISE4), /* S_BOSS_RAISE3 */ + STATE_ENTRY(SPR_BOSS, 11, 8, NULL, S_BOSS_RAISE5), /* S_BOSS_RAISE4 */ + STATE_ENTRY(SPR_BOSS, 10, 8, NULL, S_BOSS_RAISE6), /* S_BOSS_RAISE5 */ + STATE_ENTRY(SPR_BOSS, 9, 8, NULL, S_BOSS_RAISE7), /* S_BOSS_RAISE6 */ + STATE_ENTRY(SPR_BOSS, 8, 8, NULL, S_BOSS_RUN1), /* S_BOSS_RAISE7 */ + STATE_ENTRY(SPR_BOS2, 0, 10, a_look, S_BOS2_STND2), /* S_BOS2_STND */ + STATE_ENTRY(SPR_BOS2, 1, 10, a_look, S_BOS2_STND), /* S_BOS2_STND2 */ + STATE_ENTRY(SPR_BOS2, 0, 3, a_chase, S_BOS2_RUN2), /* S_BOS2_RUN1 */ + STATE_ENTRY(SPR_BOS2, 0, 3, a_chase, S_BOS2_RUN3), /* S_BOS2_RUN2 */ + STATE_ENTRY(SPR_BOS2, 1, 3, a_chase, S_BOS2_RUN4), /* S_BOS2_RUN3 */ + STATE_ENTRY(SPR_BOS2, 1, 3, a_chase, S_BOS2_RUN5), /* S_BOS2_RUN4 */ + STATE_ENTRY(SPR_BOS2, 2, 3, a_chase, S_BOS2_RUN6), /* S_BOS2_RUN5 */ + STATE_ENTRY(SPR_BOS2, 2, 3, a_chase, S_BOS2_RUN7), /* S_BOS2_RUN6 */ + STATE_ENTRY(SPR_BOS2, 3, 3, a_chase, S_BOS2_RUN8), /* S_BOS2_RUN7 */ + STATE_ENTRY(SPR_BOS2, 3, 3, a_chase, S_BOS2_RUN1), /* S_BOS2_RUN8 */ + STATE_ENTRY(SPR_BOS2, 4, 8, a_face_target, S_BOS2_ATK2), /* S_BOS2_ATK1 */ + STATE_ENTRY(SPR_BOS2, 5, 8, a_face_target, S_BOS2_ATK3), /* S_BOS2_ATK2 */ + STATE_ENTRY(SPR_BOS2, 6, 8, a_bruis_attack, + S_BOS2_RUN1), /* S_BOS2_ATK3 */ + STATE_ENTRY(SPR_BOS2, 7, 2, NULL, S_BOS2_PAIN2), /* S_BOS2_PAIN */ + STATE_ENTRY(SPR_BOS2, 7, 2, a_pain, S_BOS2_RUN1), /* S_BOS2_PAIN2 */ + STATE_ENTRY(SPR_BOS2, 8, 8, NULL, S_BOS2_DIE2), /* S_BOS2_DIE1 */ + STATE_ENTRY(SPR_BOS2, 9, 8, a_scream, S_BOS2_DIE3), /* S_BOS2_DIE2 */ + STATE_ENTRY(SPR_BOS2, 10, 8, NULL, S_BOS2_DIE4), /* S_BOS2_DIE3 */ + STATE_ENTRY(SPR_BOS2, 11, 8, a_fall, S_BOS2_DIE5), /* S_BOS2_DIE4 */ + STATE_ENTRY(SPR_BOS2, 12, 8, NULL, S_BOS2_DIE6), /* S_BOS2_DIE5 */ + STATE_ENTRY(SPR_BOS2, 13, 8, NULL, S_BOS2_DIE7), /* S_BOS2_DIE6 */ + STATE_ENTRY(SPR_BOS2, 14, -1, NULL, S_NULL), /* S_BOS2_DIE7 */ + STATE_ENTRY(SPR_BOS2, 14, 8, NULL, S_BOS2_RAISE2), /* S_BOS2_RAISE1 */ + STATE_ENTRY(SPR_BOS2, 13, 8, NULL, S_BOS2_RAISE3), /* S_BOS2_RAISE2 */ + STATE_ENTRY(SPR_BOS2, 12, 8, NULL, S_BOS2_RAISE4), /* S_BOS2_RAISE3 */ + STATE_ENTRY(SPR_BOS2, 11, 8, NULL, S_BOS2_RAISE5), /* S_BOS2_RAISE4 */ + STATE_ENTRY(SPR_BOS2, 10, 8, NULL, S_BOS2_RAISE6), /* S_BOS2_RAISE5 */ + STATE_ENTRY(SPR_BOS2, 9, 8, NULL, S_BOS2_RAISE7), /* S_BOS2_RAISE6 */ + STATE_ENTRY(SPR_BOS2, 8, 8, NULL, S_BOS2_RUN1), /* S_BOS2_RAISE7 */ + STATE_ENTRY(SPR_SKUL, 32768, 10, a_look, + S_SKULL_STND2), /* S_SKULL_STND */ + STATE_ENTRY(SPR_SKUL, 32769, 10, a_look, + S_SKULL_STND), /* S_SKULL_STND2 */ + STATE_ENTRY(SPR_SKUL, 32768, 6, a_chase, + S_SKULL_RUN2), /* S_SKULL_RUN1 */ + STATE_ENTRY(SPR_SKUL, 32769, 6, a_chase, + S_SKULL_RUN1), /* S_SKULL_RUN2 */ + STATE_ENTRY(SPR_SKUL, 32770, 10, a_face_target, + S_SKULL_ATK2), /* S_SKULL_ATK1 */ + STATE_ENTRY(SPR_SKUL, 32771, 4, a_skull_attack, + S_SKULL_ATK3), /* S_SKULL_ATK2 */ + STATE_ENTRY(SPR_SKUL, 32770, 4, NULL, S_SKULL_ATK4), /* S_SKULL_ATK3 */ + STATE_ENTRY(SPR_SKUL, 32771, 4, NULL, S_SKULL_ATK3), /* S_SKULL_ATK4 */ + STATE_ENTRY(SPR_SKUL, 32772, 3, NULL, S_SKULL_PAIN2), /* S_SKULL_PAIN */ + STATE_ENTRY(SPR_SKUL, 32772, 3, a_pain, S_SKULL_RUN1), /* S_SKULL_PAIN2 */ + STATE_ENTRY(SPR_SKUL, 32773, 6, NULL, S_SKULL_DIE2), /* S_SKULL_DIE1 */ + STATE_ENTRY(SPR_SKUL, 32774, 6, a_scream, + S_SKULL_DIE3), /* S_SKULL_DIE2 */ + STATE_ENTRY(SPR_SKUL, 32775, 6, NULL, S_SKULL_DIE4), /* S_SKULL_DIE3 */ + STATE_ENTRY(SPR_SKUL, 32776, 6, a_fall, S_SKULL_DIE5), /* S_SKULL_DIE4 */ + STATE_ENTRY(SPR_SKUL, 9, 6, NULL, S_SKULL_DIE6), /* S_SKULL_DIE5 */ + STATE_ENTRY(SPR_SKUL, 10, 6, NULL, S_NULL), /* S_SKULL_DIE6 */ + STATE_ENTRY(SPR_SPID, 0, 10, a_look, S_SPID_STND2), /* S_SPID_STND */ + STATE_ENTRY(SPR_SPID, 1, 10, a_look, S_SPID_STND), /* S_SPID_STND2 */ + STATE_ENTRY(SPR_SPID, 0, 3, a_metal, S_SPID_RUN2), /* S_SPID_RUN1 */ + STATE_ENTRY(SPR_SPID, 0, 3, a_chase, S_SPID_RUN3), /* S_SPID_RUN2 */ + STATE_ENTRY(SPR_SPID, 1, 3, a_chase, S_SPID_RUN4), /* S_SPID_RUN3 */ + STATE_ENTRY(SPR_SPID, 1, 3, a_chase, S_SPID_RUN5), /* S_SPID_RUN4 */ + STATE_ENTRY(SPR_SPID, 2, 3, a_metal, S_SPID_RUN6), /* S_SPID_RUN5 */ + STATE_ENTRY(SPR_SPID, 2, 3, a_chase, S_SPID_RUN7), /* S_SPID_RUN6 */ + STATE_ENTRY(SPR_SPID, 3, 3, a_chase, S_SPID_RUN8), /* S_SPID_RUN7 */ + STATE_ENTRY(SPR_SPID, 3, 3, a_chase, S_SPID_RUN9), /* S_SPID_RUN8 */ + STATE_ENTRY(SPR_SPID, 4, 3, a_metal, S_SPID_RUN10), /* S_SPID_RUN9 */ + STATE_ENTRY(SPR_SPID, 4, 3, a_chase, S_SPID_RUN11), /* S_SPID_RUN10 */ + STATE_ENTRY(SPR_SPID, 5, 3, a_chase, S_SPID_RUN12), /* S_SPID_RUN11 */ + STATE_ENTRY(SPR_SPID, 5, 3, a_chase, S_SPID_RUN1), /* S_SPID_RUN12 */ + STATE_ENTRY(SPR_SPID, 32768, 20, a_face_target, + S_SPID_ATK2), /* S_SPID_ATK1 */ + STATE_ENTRY(SPR_SPID, 32774, 4, a_s_pos_attack, + S_SPID_ATK3), /* S_SPID_ATK2 */ + STATE_ENTRY(SPR_SPID, 32775, 4, a_s_pos_attack, + S_SPID_ATK4), /* S_SPID_ATK3 */ + STATE_ENTRY(SPR_SPID, 32775, 1, a_spid_refire, + S_SPID_ATK2), /* S_SPID_ATK4 */ + STATE_ENTRY(SPR_SPID, 8, 3, NULL, S_SPID_PAIN2), /* S_SPID_PAIN */ + STATE_ENTRY(SPR_SPID, 8, 3, a_pain, S_SPID_RUN1), /* S_SPID_PAIN2 */ + STATE_ENTRY(SPR_SPID, 9, 20, a_scream, S_SPID_DIE2), /* S_SPID_DIE1 */ + STATE_ENTRY(SPR_SPID, 10, 10, a_fall, S_SPID_DIE3), /* S_SPID_DIE2 */ + STATE_ENTRY(SPR_SPID, 11, 10, NULL, S_SPID_DIE4), /* S_SPID_DIE3 */ + STATE_ENTRY(SPR_SPID, 12, 10, NULL, S_SPID_DIE5), /* S_SPID_DIE4 */ + STATE_ENTRY(SPR_SPID, 13, 10, NULL, S_SPID_DIE6), /* S_SPID_DIE5 */ + STATE_ENTRY(SPR_SPID, 14, 10, NULL, S_SPID_DIE7), /* S_SPID_DIE6 */ + STATE_ENTRY(SPR_SPID, 15, 10, NULL, S_SPID_DIE8), /* S_SPID_DIE7 */ + STATE_ENTRY(SPR_SPID, 16, 10, NULL, S_SPID_DIE9), /* S_SPID_DIE8 */ + STATE_ENTRY(SPR_SPID, 17, 10, NULL, S_SPID_DIE10), /* S_SPID_DIE9 */ + STATE_ENTRY(SPR_SPID, 18, 30, NULL, S_SPID_DIE11), /* S_SPID_DIE10 */ + STATE_ENTRY(SPR_SPID, 18, -1, a_boss_death, S_NULL), /* S_SPID_DIE11 */ + STATE_ENTRY(SPR_BSPI, 0, 10, a_look, S_BSPI_STND2), /* S_BSPI_STND */ + STATE_ENTRY(SPR_BSPI, 1, 10, a_look, S_BSPI_STND), /* S_BSPI_STND2 */ + STATE_ENTRY(SPR_BSPI, 0, 20, NULL, S_BSPI_RUN1), /* S_BSPI_SIGHT */ + STATE_ENTRY(SPR_BSPI, 0, 3, a_baby_metal, S_BSPI_RUN2), /* S_BSPI_RUN1 */ + STATE_ENTRY(SPR_BSPI, 0, 3, a_chase, S_BSPI_RUN3), /* S_BSPI_RUN2 */ + STATE_ENTRY(SPR_BSPI, 1, 3, a_chase, S_BSPI_RUN4), /* S_BSPI_RUN3 */ + STATE_ENTRY(SPR_BSPI, 1, 3, a_chase, S_BSPI_RUN5), /* S_BSPI_RUN4 */ + STATE_ENTRY(SPR_BSPI, 2, 3, a_chase, S_BSPI_RUN6), /* S_BSPI_RUN5 */ + STATE_ENTRY(SPR_BSPI, 2, 3, a_chase, S_BSPI_RUN7), /* S_BSPI_RUN6 */ + STATE_ENTRY(SPR_BSPI, 3, 3, a_baby_metal, S_BSPI_RUN8), /* S_BSPI_RUN7 */ + STATE_ENTRY(SPR_BSPI, 3, 3, a_chase, S_BSPI_RUN9), /* S_BSPI_RUN8 */ + STATE_ENTRY(SPR_BSPI, 4, 3, a_chase, S_BSPI_RUN10), /* S_BSPI_RUN9 */ + STATE_ENTRY(SPR_BSPI, 4, 3, a_chase, S_BSPI_RUN11), /* S_BSPI_RUN10 */ + STATE_ENTRY(SPR_BSPI, 5, 3, a_chase, S_BSPI_RUN12), /* S_BSPI_RUN11 */ + STATE_ENTRY(SPR_BSPI, 5, 3, a_chase, S_BSPI_RUN1), /* S_BSPI_RUN12 */ + STATE_ENTRY(SPR_BSPI, 32768, 20, a_face_target, + S_BSPI_ATK2), /* S_BSPI_ATK1 */ + STATE_ENTRY(SPR_BSPI, 32774, 4, a_bspi_attack, + S_BSPI_ATK3), /* S_BSPI_ATK2 */ + STATE_ENTRY(SPR_BSPI, 32775, 4, NULL, S_BSPI_ATK4), /* S_BSPI_ATK3 */ + STATE_ENTRY(SPR_BSPI, 32775, 1, a_spid_refire, + S_BSPI_ATK2), /* S_BSPI_ATK4 */ + STATE_ENTRY(SPR_BSPI, 8, 3, NULL, S_BSPI_PAIN2), /* S_BSPI_PAIN */ + STATE_ENTRY(SPR_BSPI, 8, 3, a_pain, S_BSPI_RUN1), /* S_BSPI_PAIN2 */ + STATE_ENTRY(SPR_BSPI, 9, 20, a_scream, S_BSPI_DIE2), /* S_BSPI_DIE1 */ + STATE_ENTRY(SPR_BSPI, 10, 7, a_fall, S_BSPI_DIE3), /* S_BSPI_DIE2 */ + STATE_ENTRY(SPR_BSPI, 11, 7, NULL, S_BSPI_DIE4), /* S_BSPI_DIE3 */ + STATE_ENTRY(SPR_BSPI, 12, 7, NULL, S_BSPI_DIE5), /* S_BSPI_DIE4 */ + STATE_ENTRY(SPR_BSPI, 13, 7, NULL, S_BSPI_DIE6), /* S_BSPI_DIE5 */ + STATE_ENTRY(SPR_BSPI, 14, 7, NULL, S_BSPI_DIE7), /* S_BSPI_DIE6 */ + STATE_ENTRY(SPR_BSPI, 15, -1, a_boss_death, S_NULL), /* S_BSPI_DIE7 */ + STATE_ENTRY(SPR_BSPI, 15, 5, NULL, S_BSPI_RAISE2), /* S_BSPI_RAISE1 */ + STATE_ENTRY(SPR_BSPI, 14, 5, NULL, S_BSPI_RAISE3), /* S_BSPI_RAISE2 */ + STATE_ENTRY(SPR_BSPI, 13, 5, NULL, S_BSPI_RAISE4), /* S_BSPI_RAISE3 */ + STATE_ENTRY(SPR_BSPI, 12, 5, NULL, S_BSPI_RAISE5), /* S_BSPI_RAISE4 */ + STATE_ENTRY(SPR_BSPI, 11, 5, NULL, S_BSPI_RAISE6), /* S_BSPI_RAISE5 */ + STATE_ENTRY(SPR_BSPI, 10, 5, NULL, S_BSPI_RAISE7), /* S_BSPI_RAISE6 */ + STATE_ENTRY(SPR_BSPI, 9, 5, NULL, S_BSPI_RUN1), /* S_BSPI_RAISE7 */ + STATE_ENTRY(SPR_APLS, 32768, 5, NULL, S_ARACH_PLAZ2), /* S_ARACH_PLAZ */ + STATE_ENTRY(SPR_APLS, 32769, 5, NULL, S_ARACH_PLAZ), /* S_ARACH_PLAZ2 */ + STATE_ENTRY(SPR_APBX, 32768, 5, NULL, S_ARACH_PLEX2), /* S_ARACH_PLEX */ + STATE_ENTRY(SPR_APBX, 32769, 5, NULL, S_ARACH_PLEX3), /* S_ARACH_PLEX2 */ + STATE_ENTRY(SPR_APBX, 32770, 5, NULL, S_ARACH_PLEX4), /* S_ARACH_PLEX3 */ + STATE_ENTRY(SPR_APBX, 32771, 5, NULL, S_ARACH_PLEX5), /* S_ARACH_PLEX4 */ + STATE_ENTRY(SPR_APBX, 32772, 5, NULL, S_NULL), /* S_ARACH_PLEX5 */ + STATE_ENTRY(SPR_CYBR, 0, 10, a_look, S_CYBER_STND2), /* S_CYBER_STND */ + STATE_ENTRY(SPR_CYBR, 1, 10, a_look, S_CYBER_STND), /* S_CYBER_STND2 */ + STATE_ENTRY(SPR_CYBR, 0, 3, a_hoof, S_CYBER_RUN2), /* S_CYBER_RUN1 */ + STATE_ENTRY(SPR_CYBR, 0, 3, a_chase, S_CYBER_RUN3), /* S_CYBER_RUN2 */ + STATE_ENTRY(SPR_CYBR, 1, 3, a_chase, S_CYBER_RUN4), /* S_CYBER_RUN3 */ + STATE_ENTRY(SPR_CYBR, 1, 3, a_chase, S_CYBER_RUN5), /* S_CYBER_RUN4 */ + STATE_ENTRY(SPR_CYBR, 2, 3, a_chase, S_CYBER_RUN6), /* S_CYBER_RUN5 */ + STATE_ENTRY(SPR_CYBR, 2, 3, a_chase, S_CYBER_RUN7), /* S_CYBER_RUN6 */ + STATE_ENTRY(SPR_CYBR, 3, 3, a_metal, S_CYBER_RUN8), /* S_CYBER_RUN7 */ + STATE_ENTRY(SPR_CYBR, 3, 3, a_chase, S_CYBER_RUN1), /* S_CYBER_RUN8 */ + STATE_ENTRY(SPR_CYBR, 4, 6, a_face_target, + S_CYBER_ATK2), /* S_CYBER_ATK1 */ + STATE_ENTRY(SPR_CYBR, 5, 12, a_cyber_attack, + S_CYBER_ATK3), /* S_CYBER_ATK2 */ + STATE_ENTRY(SPR_CYBR, 4, 12, a_face_target, + S_CYBER_ATK4), /* S_CYBER_ATK3 */ + STATE_ENTRY(SPR_CYBR, 5, 12, a_cyber_attack, + S_CYBER_ATK5), /* S_CYBER_ATK4 */ + STATE_ENTRY(SPR_CYBR, 4, 12, a_face_target, + S_CYBER_ATK6), /* S_CYBER_ATK5 */ + STATE_ENTRY(SPR_CYBR, 5, 12, a_cyber_attack, + S_CYBER_RUN1), /* S_CYBER_ATK6 */ + STATE_ENTRY(SPR_CYBR, 6, 10, a_pain, S_CYBER_RUN1), /* S_CYBER_PAIN */ + STATE_ENTRY(SPR_CYBR, 7, 10, NULL, S_CYBER_DIE2), /* S_CYBER_DIE1 */ + STATE_ENTRY(SPR_CYBR, 8, 10, a_scream, S_CYBER_DIE3), /* S_CYBER_DIE2 */ + STATE_ENTRY(SPR_CYBR, 9, 10, NULL, S_CYBER_DIE4), /* S_CYBER_DIE3 */ + STATE_ENTRY(SPR_CYBR, 10, 10, NULL, S_CYBER_DIE5), /* S_CYBER_DIE4 */ + STATE_ENTRY(SPR_CYBR, 11, 10, NULL, S_CYBER_DIE6), /* S_CYBER_DIE5 */ + STATE_ENTRY(SPR_CYBR, 12, 10, a_fall, S_CYBER_DIE7), /* S_CYBER_DIE6 */ + STATE_ENTRY(SPR_CYBR, 13, 10, NULL, S_CYBER_DIE8), /* S_CYBER_DIE7 */ + STATE_ENTRY(SPR_CYBR, 14, 10, NULL, S_CYBER_DIE9), /* S_CYBER_DIE8 */ + STATE_ENTRY(SPR_CYBR, 15, 30, NULL, S_CYBER_DIE10), /* S_CYBER_DIE9 */ + STATE_ENTRY(SPR_CYBR, 15, -1, a_boss_death, S_NULL), /* S_CYBER_DIE10 */ + STATE_ENTRY(SPR_PAIN, 0, 10, a_look, S_PAIN_STND), /* S_PAIN_STND */ + STATE_ENTRY(SPR_PAIN, 0, 3, a_chase, S_PAIN_RUN2), /* S_PAIN_RUN1 */ + STATE_ENTRY(SPR_PAIN, 0, 3, a_chase, S_PAIN_RUN3), /* S_PAIN_RUN2 */ + STATE_ENTRY(SPR_PAIN, 1, 3, a_chase, S_PAIN_RUN4), /* S_PAIN_RUN3 */ + STATE_ENTRY(SPR_PAIN, 1, 3, a_chase, S_PAIN_RUN5), /* S_PAIN_RUN4 */ + STATE_ENTRY(SPR_PAIN, 2, 3, a_chase, S_PAIN_RUN6), /* S_PAIN_RUN5 */ + STATE_ENTRY(SPR_PAIN, 2, 3, a_chase, S_PAIN_RUN1), /* S_PAIN_RUN6 */ + STATE_ENTRY(SPR_PAIN, 3, 5, a_face_target, S_PAIN_ATK2), /* S_PAIN_ATK1 */ + STATE_ENTRY(SPR_PAIN, 4, 5, a_face_target, S_PAIN_ATK3), /* S_PAIN_ATK2 */ + STATE_ENTRY(SPR_PAIN, 32773, 5, a_face_target, + S_PAIN_ATK4), /* S_PAIN_ATK3 */ + STATE_ENTRY(SPR_PAIN, 32773, 0, a_pain_attack, + S_PAIN_RUN1), /* S_PAIN_ATK4 */ + STATE_ENTRY(SPR_PAIN, 6, 6, NULL, S_PAIN_PAIN2), /* S_PAIN_PAIN */ + STATE_ENTRY(SPR_PAIN, 6, 6, a_pain, S_PAIN_RUN1), /* S_PAIN_PAIN2 */ + STATE_ENTRY(SPR_PAIN, 32775, 8, NULL, S_PAIN_DIE2), /* S_PAIN_DIE1 */ + STATE_ENTRY(SPR_PAIN, 32776, 8, a_scream, S_PAIN_DIE3), /* S_PAIN_DIE2 */ + STATE_ENTRY(SPR_PAIN, 32777, 8, NULL, S_PAIN_DIE4), /* S_PAIN_DIE3 */ + STATE_ENTRY(SPR_PAIN, 32778, 8, NULL, S_PAIN_DIE5), /* S_PAIN_DIE4 */ + STATE_ENTRY(SPR_PAIN, 32779, 8, a_pain_die, + S_PAIN_DIE6), /* S_PAIN_DIE5 */ + STATE_ENTRY(SPR_PAIN, 32780, 8, NULL, S_NULL), /* S_PAIN_DIE6 */ + STATE_ENTRY(SPR_PAIN, 12, 8, NULL, S_PAIN_RAISE2), /* S_PAIN_RAISE1 */ + STATE_ENTRY(SPR_PAIN, 11, 8, NULL, S_PAIN_RAISE3), /* S_PAIN_RAISE2 */ + STATE_ENTRY(SPR_PAIN, 10, 8, NULL, S_PAIN_RAISE4), /* S_PAIN_RAISE3 */ + STATE_ENTRY(SPR_PAIN, 9, 8, NULL, S_PAIN_RAISE5), /* S_PAIN_RAISE4 */ + STATE_ENTRY(SPR_PAIN, 8, 8, NULL, S_PAIN_RAISE6), /* S_PAIN_RAISE5 */ + STATE_ENTRY(SPR_PAIN, 7, 8, NULL, S_PAIN_RUN1), /* S_PAIN_RAISE6 */ + STATE_ENTRY(SPR_SSWV, 0, 10, a_look, S_SSWV_STND2), /* S_SSWV_STND */ + STATE_ENTRY(SPR_SSWV, 1, 10, a_look, S_SSWV_STND), /* S_SSWV_STND2 */ + STATE_ENTRY(SPR_SSWV, 0, 3, a_chase, S_SSWV_RUN2), /* S_SSWV_RUN1 */ + STATE_ENTRY(SPR_SSWV, 0, 3, a_chase, S_SSWV_RUN3), /* S_SSWV_RUN2 */ + STATE_ENTRY(SPR_SSWV, 1, 3, a_chase, S_SSWV_RUN4), /* S_SSWV_RUN3 */ + STATE_ENTRY(SPR_SSWV, 1, 3, a_chase, S_SSWV_RUN5), /* S_SSWV_RUN4 */ + STATE_ENTRY(SPR_SSWV, 2, 3, a_chase, S_SSWV_RUN6), /* S_SSWV_RUN5 */ + STATE_ENTRY(SPR_SSWV, 2, 3, a_chase, S_SSWV_RUN7), /* S_SSWV_RUN6 */ + STATE_ENTRY(SPR_SSWV, 3, 3, a_chase, S_SSWV_RUN8), /* S_SSWV_RUN7 */ + STATE_ENTRY(SPR_SSWV, 3, 3, a_chase, S_SSWV_RUN1), /* S_SSWV_RUN8 */ + STATE_ENTRY(SPR_SSWV, 4, 10, a_face_target, + S_SSWV_ATK2), /* S_SSWV_ATK1 */ + STATE_ENTRY(SPR_SSWV, 5, 10, a_face_target, + S_SSWV_ATK3), /* S_SSWV_ATK2 */ + STATE_ENTRY(SPR_SSWV, 32774, 4, a_c_pos_attack, + S_SSWV_ATK4), /* S_SSWV_ATK3 */ + STATE_ENTRY(SPR_SSWV, 5, 6, a_face_target, S_SSWV_ATK5) , /* S_SSWV_ATK4 */ + STATE_ENTRY(SPR_SSWV, 32774, 4, a_c_pos_attack, + S_SSWV_ATK6), /* S_SSWV_ATK5 */ + STATE_ENTRY(SPR_SSWV, 5, 1, a_c_pos_refire, + S_SSWV_ATK2), /* S_SSWV_ATK6 */ + STATE_ENTRY(SPR_SSWV, 7, 3, NULL, S_SSWV_PAIN2), /* S_SSWV_PAIN */ + STATE_ENTRY(SPR_SSWV, 7, 3, a_pain, S_SSWV_RUN1), /* S_SSWV_PAIN2 */ + STATE_ENTRY(SPR_SSWV, 8, 5, NULL, S_SSWV_DIE2), /* S_SSWV_DIE1 */ + STATE_ENTRY(SPR_SSWV, 9, 5, a_scream, S_SSWV_DIE3), /* S_SSWV_DIE2 */ + STATE_ENTRY(SPR_SSWV, 10, 5, a_fall, S_SSWV_DIE4), /* S_SSWV_DIE3 */ + STATE_ENTRY(SPR_SSWV, 11, 5, NULL, S_SSWV_DIE5), /* S_SSWV_DIE4 */ + STATE_ENTRY(SPR_SSWV, 12, -1, NULL, S_NULL), /* S_SSWV_DIE5 */ + STATE_ENTRY(SPR_SSWV, 13, 5, NULL, S_SSWV_XDIE2), /* S_SSWV_XDIE1 */ + STATE_ENTRY(SPR_SSWV, 14, 5, a_xscream, S_SSWV_XDIE3), /* S_SSWV_XDIE2 */ + STATE_ENTRY(SPR_SSWV, 15, 5, a_fall, S_SSWV_XDIE4), /* S_SSWV_XDIE3 */ + STATE_ENTRY(SPR_SSWV, 16, 5, NULL, S_SSWV_XDIE5), /* S_SSWV_XDIE4 */ + STATE_ENTRY(SPR_SSWV, 17, 5, NULL, S_SSWV_XDIE6), /* S_SSWV_XDIE5 */ + STATE_ENTRY(SPR_SSWV, 18, 5, NULL, S_SSWV_XDIE7), /* S_SSWV_XDIE6 */ + STATE_ENTRY(SPR_SSWV, 19, 5, NULL, S_SSWV_XDIE8), /* S_SSWV_XDIE7 */ + STATE_ENTRY(SPR_SSWV, 20, 5, NULL, S_SSWV_XDIE9), /* S_SSWV_XDIE8 */ + STATE_ENTRY(SPR_SSWV, 21, -1, NULL, S_NULL), /* S_SSWV_XDIE9 */ + STATE_ENTRY(SPR_SSWV, 12, 5, NULL, S_SSWV_RAISE2), /* S_SSWV_RAISE1 */ + STATE_ENTRY(SPR_SSWV, 11, 5, NULL, S_SSWV_RAISE3), /* S_SSWV_RAISE2 */ + STATE_ENTRY(SPR_SSWV, 10, 5, NULL, S_SSWV_RAISE4), /* S_SSWV_RAISE3 */ + STATE_ENTRY(SPR_SSWV, 9, 5, NULL, S_SSWV_RAISE5), /* S_SSWV_RAISE4 */ + STATE_ENTRY(SPR_SSWV, 8, 5, NULL, S_SSWV_RUN1), /* S_SSWV_RAISE5 */ + STATE_ENTRY(SPR_KEEN, 0, -1, NULL, S_KEENSTND), /* S_KEENSTND */ + STATE_ENTRY(SPR_KEEN, 0, 6, NULL, S_COMMKEEN2), /* S_COMMKEEN */ + STATE_ENTRY(SPR_KEEN, 1, 6, NULL, S_COMMKEEN3), /* S_COMMKEEN2 */ + STATE_ENTRY(SPR_KEEN, 2, 6, a_scream, S_COMMKEEN4), /* S_COMMKEEN3 */ + STATE_ENTRY(SPR_KEEN, 3, 6, NULL, S_COMMKEEN5), /* S_COMMKEEN4 */ + STATE_ENTRY(SPR_KEEN, 4, 6, NULL, S_COMMKEEN6), /* S_COMMKEEN5 */ + STATE_ENTRY(SPR_KEEN, 5, 6, NULL, S_COMMKEEN7), /* S_COMMKEEN6 */ + STATE_ENTRY(SPR_KEEN, 6, 6, NULL, S_COMMKEEN8), /* S_COMMKEEN7 */ + STATE_ENTRY(SPR_KEEN, 7, 6, NULL, S_COMMKEEN9), /* S_COMMKEEN8 */ + STATE_ENTRY(SPR_KEEN, 8, 6, NULL, S_COMMKEEN10), /* S_COMMKEEN9 */ + STATE_ENTRY(SPR_KEEN, 9, 6, NULL, S_COMMKEEN11), /* S_COMMKEEN10 */ + STATE_ENTRY(SPR_KEEN, 10, 6, a_keen_die, S_COMMKEEN12), /* S_COMMKEEN11 */ + STATE_ENTRY(SPR_KEEN, 11, -1, NULL, S_NULL), /* S_COMMKEEN12 */ + STATE_ENTRY(SPR_KEEN, 12, 4, NULL, S_KEENPAIN2), /* S_KEENPAIN */ + STATE_ENTRY(SPR_KEEN, 12, 8, a_pain, S_KEENSTND), /* S_KEENPAIN2 */ + STATE_ENTRY(SPR_BBRN, 0, -1, NULL, S_NULL), /* S_BRAIN */ + STATE_ENTRY(SPR_BBRN, 1, 36, a_brain_pain, S_BRAIN), /* S_BRAIN_PAIN */ + STATE_ENTRY(SPR_BBRN, 0, 100, a_brain_scream, + S_BRAIN_DIE2), /* S_BRAIN_DIE1 */ + STATE_ENTRY(SPR_BBRN, 0, 10, NULL, S_BRAIN_DIE3), /* S_BRAIN_DIE2 */ + STATE_ENTRY(SPR_BBRN, 0, 10, NULL, S_BRAIN_DIE4), /* S_BRAIN_DIE3 */ + STATE_ENTRY(SPR_BBRN, 0, -1, a_brain_die, S_NULL), /* S_BRAIN_DIE4 */ + STATE_ENTRY(SPR_SSWV, 0, 10, a_look, S_BRAINEYE), /* S_BRAINEYE */ + STATE_ENTRY(SPR_SSWV, 0, 181, + a_brain_awake, S_BRAINEYE1), /* S_BRAINEYESEE */ + STATE_ENTRY(SPR_SSWV, 0, 150, + a_brain_split, S_BRAINEYE1), /* S_BRAINEYE1 */ + STATE_ENTRY(SPR_BOSF, 32768, 3, a_spawn_sound, S_SPAWN2), /* S_SPAWN1 */ + STATE_ENTRY(SPR_BOSF, 32769, 3, a_spawn_fly, S_SPAWN3), /* S_SPAWN2 */ + STATE_ENTRY(SPR_BOSF, 32770, 3, a_spawn_fly, S_SPAWN4), /* S_SPAWN3 */ + STATE_ENTRY(SPR_BOSF, 32771, 3, a_spawn_fly, S_SPAWN1), /* S_SPAWN4 */ + STATE_ENTRY(SPR_FIRE, 32768, 4, a_fire, S_SPAWNFIRE2), /* S_SPAWNFIRE1 */ + STATE_ENTRY(SPR_FIRE, 32769, 4, a_fire, S_SPAWNFIRE3), /* S_SPAWNFIRE2 */ + STATE_ENTRY(SPR_FIRE, 32770, 4, a_fire, S_SPAWNFIRE4), /* S_SPAWNFIRE3 */ + STATE_ENTRY(SPR_FIRE, 32771, 4, a_fire, S_SPAWNFIRE5), /* S_SPAWNFIRE4 */ + STATE_ENTRY(SPR_FIRE, 32772, 4, a_fire, S_SPAWNFIRE6), /* S_SPAWNFIRE5 */ + STATE_ENTRY(SPR_FIRE, 32773, 4, a_fire, S_SPAWNFIRE7), /* S_SPAWNFIRE6 */ + STATE_ENTRY(SPR_FIRE, 32774, 4, a_fire, S_SPAWNFIRE8), /* S_SPAWNFIRE7 */ + STATE_ENTRY(SPR_FIRE, 32775, 4, a_fire, S_NULL), /* S_SPAWNFIRE8 */ + STATE_ENTRY(SPR_MISL, 32769, 10, NULL, + S_BRAINEXPLODE2), /* S_BRAINEXPLODE1 */ + STATE_ENTRY(SPR_MISL, 32770, 10, NULL, + S_BRAINEXPLODE3), /* S_BRAINEXPLODE2 */ + STATE_ENTRY(SPR_MISL, 32771, 10, a_brain_explode, + S_NULL), /* S_BRAINEXPLODE3 */ + STATE_ENTRY(SPR_ARM1, 0, 6, NULL, S_ARM1A), /* S_ARM1 */ + STATE_ENTRY(SPR_ARM1, 32769, 7, NULL, S_ARM1), /* S_ARM1A */ + STATE_ENTRY(SPR_ARM2, 0, 6, NULL, S_ARM2A), /* S_ARM2 */ + STATE_ENTRY(SPR_ARM2, 32769, 6, NULL, S_ARM2), /* S_ARM2A */ + STATE_ENTRY(SPR_BAR1, 0, 6, NULL, S_BAR2), /* S_BAR1 */ + STATE_ENTRY(SPR_BAR1, 1, 6, NULL, S_BAR1), /* S_BAR2 */ + STATE_ENTRY(SPR_BEXP, 32768, 5, NULL, S_BEXP2), /* S_BEXP */ + STATE_ENTRY(SPR_BEXP, 32769, 5, a_scream, S_BEXP3), /* S_BEXP2 */ + STATE_ENTRY(SPR_BEXP, 32770, 5, NULL, S_BEXP4), /* S_BEXP3 */ + STATE_ENTRY(SPR_BEXP, 32771, 10, a_explode, S_BEXP5), /* S_BEXP4 */ + STATE_ENTRY(SPR_BEXP, 32772, 10, NULL, S_NULL), /* S_BEXP5 */ + STATE_ENTRY(SPR_FCAN, 32768, 4, NULL, S_BBAR2), /* S_BBAR1 */ + STATE_ENTRY(SPR_FCAN, 32769, 4, NULL, S_BBAR3), /* S_BBAR2 */ + STATE_ENTRY(SPR_FCAN, 32770, 4, NULL, S_BBAR1), /* S_BBAR3 */ + STATE_ENTRY(SPR_BON1, 0, 6, NULL, S_BON1A), /* S_BON1 */ + STATE_ENTRY(SPR_BON1, 1, 6, NULL, S_BON1B), /* S_BON1A */ + STATE_ENTRY(SPR_BON1, 2, 6, NULL, S_BON1C), /* S_BON1B */ + STATE_ENTRY(SPR_BON1, 3, 6, NULL, S_BON1D), /* S_BON1C */ + STATE_ENTRY(SPR_BON1, 2, 6, NULL, S_BON1E), /* S_BON1D */ + STATE_ENTRY(SPR_BON1, 1, 6, NULL, S_BON1), /* S_BON1E */ + STATE_ENTRY(SPR_BON2, 0, 6, NULL, S_BON2A), /* S_BON2 */ + STATE_ENTRY(SPR_BON2, 1, 6, NULL, S_BON2B), /* S_BON2A */ + STATE_ENTRY(SPR_BON2, 2, 6, NULL, S_BON2C), /* S_BON2B */ + STATE_ENTRY(SPR_BON2, 3, 6, NULL, S_BON2D), /* S_BON2C */ + STATE_ENTRY(SPR_BON2, 2, 6, NULL, S_BON2E), /* S_BON2D */ + STATE_ENTRY(SPR_BON2, 1, 6, NULL, S_BON2), /* S_BON2E */ + STATE_ENTRY(SPR_BKEY, 0, 10, NULL, S_BKEY2), /* S_BKEY */ + STATE_ENTRY(SPR_BKEY, 32769, 10, NULL, S_BKEY), /* S_BKEY2 */ + STATE_ENTRY(SPR_RKEY, 0, 10, NULL, S_RKEY2), /* S_RKEY */ + STATE_ENTRY(SPR_RKEY, 32769, 10, NULL, S_RKEY), /* S_RKEY2 */ + STATE_ENTRY(SPR_YKEY, 0, 10, NULL, S_YKEY2), /* S_YKEY */ + STATE_ENTRY(SPR_YKEY, 32769, 10, NULL, S_YKEY), /* S_YKEY2 */ + STATE_ENTRY(SPR_BSKU, 0, 10, NULL, S_BSKULL2), /* S_BSKULL */ + STATE_ENTRY(SPR_BSKU, 32769, 10, NULL, S_BSKULL), /* S_BSKULL2 */ + STATE_ENTRY(SPR_RSKU, 0, 10, NULL, S_RSKULL2), /* S_RSKULL */ + STATE_ENTRY(SPR_RSKU, 32769, 10, NULL, S_RSKULL), /* S_RSKULL2 */ + STATE_ENTRY(SPR_YSKU, 0, 10, NULL, S_YSKULL2), /* S_YSKULL */ + STATE_ENTRY(SPR_YSKU, 32769, 10, NULL, S_YSKULL), /* S_YSKULL2 */ + STATE_ENTRY(SPR_STIM, 0, -1, NULL, S_NULL), /* S_STIM */ + STATE_ENTRY(SPR_MEDI, 0, -1, NULL, S_NULL), /* S_MEDI */ + STATE_ENTRY(SPR_SOUL, 32768, 6, NULL, S_SOUL2), /* S_SOUL */ + STATE_ENTRY(SPR_SOUL, 32769, 6, NULL, S_SOUL3), /* S_SOUL2 */ + STATE_ENTRY(SPR_SOUL, 32770, 6, NULL, S_SOUL4), /* S_SOUL3 */ + STATE_ENTRY(SPR_SOUL, 32771, 6, NULL, S_SOUL5), /* S_SOUL4 */ + STATE_ENTRY(SPR_SOUL, 32770, 6, NULL, S_SOUL6), /* S_SOUL5 */ + STATE_ENTRY(SPR_SOUL, 32769, 6, NULL, S_SOUL), /* S_SOUL6 */ + STATE_ENTRY(SPR_PINV, 32768, 6, NULL, S_PINV2), /* S_PINV */ + STATE_ENTRY(SPR_PINV, 32769, 6, NULL, S_PINV3), /* S_PINV2 */ + STATE_ENTRY(SPR_PINV, 32770, 6, NULL, S_PINV4), /* S_PINV3 */ + STATE_ENTRY(SPR_PINV, 32771, 6, NULL, S_PINV), /* S_PINV4 */ + STATE_ENTRY(SPR_PSTR, 32768, -1, NULL, S_NULL), /* S_PSTR */ + STATE_ENTRY(SPR_PINS, 32768, 6, NULL, S_PINS2), /* S_PINS */ + STATE_ENTRY(SPR_PINS, 32769, 6, NULL, S_PINS3), /* S_PINS2 */ + STATE_ENTRY(SPR_PINS, 32770, 6, NULL, S_PINS4), /* S_PINS3 */ + STATE_ENTRY(SPR_PINS, 32771, 6, NULL, S_PINS), /* S_PINS4 */ + STATE_ENTRY(SPR_MEGA, 32768, 6, NULL, S_MEGA2), /* S_MEGA */ + STATE_ENTRY(SPR_MEGA, 32769, 6, NULL, S_MEGA3), /* S_MEGA2 */ + STATE_ENTRY(SPR_MEGA, 32770, 6, NULL, S_MEGA4), /* S_MEGA3 */ + STATE_ENTRY(SPR_MEGA, 32771, 6, NULL, S_MEGA), /* S_MEGA4 */ + STATE_ENTRY(SPR_SUIT, 32768, -1, NULL, S_NULL), /* S_SUIT */ + STATE_ENTRY(SPR_PMAP, 32768, 6, NULL, S_PMAP2), /* S_PMAP */ + STATE_ENTRY(SPR_PMAP, 32769, 6, NULL, S_PMAP3), /* S_PMAP2 */ + STATE_ENTRY(SPR_PMAP, 32770, 6, NULL, S_PMAP4), /* S_PMAP3 */ + STATE_ENTRY(SPR_PMAP, 32771, 6, NULL, S_PMAP5), /* S_PMAP4 */ + STATE_ENTRY(SPR_PMAP, 32770, 6, NULL, S_PMAP6), /* S_PMAP5 */ + STATE_ENTRY(SPR_PMAP, 32769, 6, NULL, S_PMAP), /* S_PMAP6 */ + STATE_ENTRY(SPR_PVIS, 32768, 6, NULL, S_PVIS2), /* S_PVIS */ + STATE_ENTRY(SPR_PVIS, 1, 6, NULL, S_PVIS), /* S_PVIS2 */ + STATE_ENTRY(SPR_CLIP, 0, -1, NULL, S_NULL), /* S_CLIP */ + STATE_ENTRY(SPR_AMMO, 0, -1, NULL, S_NULL), /* S_AMMO */ + STATE_ENTRY(SPR_ROCK, 0, -1, NULL, S_NULL), /* S_ROCK */ + STATE_ENTRY(SPR_BROK, 0, -1, NULL, S_NULL), /* S_BROK */ + STATE_ENTRY(SPR_CELL, 0, -1, NULL, S_NULL), /* S_CELL */ + STATE_ENTRY(SPR_CELP, 0, -1, NULL, S_NULL), /* S_CELP */ + STATE_ENTRY(SPR_SHEL, 0, -1, NULL, S_NULL), /* S_SHEL */ + STATE_ENTRY(SPR_SBOX, 0, -1, NULL, S_NULL), /* S_SBOX */ + STATE_ENTRY(SPR_BPAK, 0, -1, NULL, S_NULL), /* S_BPAK */ + STATE_ENTRY(SPR_BFUG, 0, -1, NULL, S_NULL), /* S_BFUG */ + STATE_ENTRY(SPR_MGUN, 0, -1, NULL, S_NULL), /* S_MGUN */ + STATE_ENTRY(SPR_CSAW, 0, -1, NULL, S_NULL), /* S_CSAW */ + STATE_ENTRY(SPR_LAUN, 0, -1, NULL, S_NULL), /* S_LAUN */ + STATE_ENTRY(SPR_PLAS, 0, -1, NULL, S_NULL), /* S_PLAS */ + STATE_ENTRY(SPR_SHOT, 0, -1, NULL, S_NULL), /* S_SHOT */ + STATE_ENTRY(SPR_SGN2, 0, -1, NULL, S_NULL), /* S_SHOT2 */ + STATE_ENTRY(SPR_COLU, 32768, -1, NULL, S_NULL), /* S_COLU */ + STATE_ENTRY(SPR_SMT2, 0, -1, NULL, S_NULL), /* S_STALAG */ + STATE_ENTRY(SPR_GOR1, 0, 10, NULL, S_BLOODYTWITCH2), /* S_BLOODYTWITCH */ + STATE_ENTRY(SPR_GOR1, 1, 15, NULL, S_BLOODYTWITCH3), /* S_BLOODYTWITCH2 */ + STATE_ENTRY(SPR_GOR1, 2, 8, NULL, S_BLOODYTWITCH4), /* S_BLOODYTWITCH3 */ + STATE_ENTRY(SPR_GOR1, 1, 6, NULL, S_BLOODYTWITCH), /* S_BLOODYTWITCH4 */ + STATE_ENTRY(SPR_PLAY, 13, -1, NULL, S_NULL), /* S_DEADTORSO */ + STATE_ENTRY(SPR_PLAY, 18, -1, NULL, S_NULL), /* S_DEADBOTTOM */ + STATE_ENTRY(SPR_POL2, 0, -1, NULL, S_NULL), /* S_HEADSONSTICK */ + STATE_ENTRY(SPR_POL5, 0, -1, NULL, S_NULL), /* S_GIBS */ + STATE_ENTRY(SPR_POL4, 0, -1, NULL, S_NULL), /* S_HEADONASTICK */ + STATE_ENTRY(SPR_POL3, 32768, 6, NULL, S_HEADCANDLES2), /* S_HEADCANDLES */ + STATE_ENTRY(SPR_POL3, 32769, 6, NULL, S_HEADCANDLES), /* S_HEADCANDLES2 */ + STATE_ENTRY(SPR_POL1, 0, -1, NULL, S_NULL), /* S_DEADSTICK */ + STATE_ENTRY(SPR_POL6, 0, 6, NULL, S_LIVESTICK2), /* S_LIVESTICK */ + STATE_ENTRY(SPR_POL6, 1, 8, NULL, S_LIVESTICK), /* S_LIVESTICK2 */ + STATE_ENTRY(SPR_GOR2, 0, -1, NULL, S_NULL), /* S_MEAT2 */ + STATE_ENTRY(SPR_GOR3, 0, -1, NULL, S_NULL), /* S_MEAT3 */ + STATE_ENTRY(SPR_GOR4, 0, -1, NULL, S_NULL), /* S_MEAT4 */ + STATE_ENTRY(SPR_GOR5, 0, -1, NULL, S_NULL), /* S_MEAT5 */ + STATE_ENTRY(SPR_SMIT, 0, -1, NULL, S_NULL), /* S_STALAGTITE */ + STATE_ENTRY(SPR_COL1, 0, -1, NULL, S_NULL), /* S_TALLGRNCOL */ + STATE_ENTRY(SPR_COL2, 0, -1, NULL, S_NULL), /* S_SHRTGRNCOL */ + STATE_ENTRY(SPR_COL3, 0, -1, NULL, S_NULL), /* S_TALLREDCOL */ + STATE_ENTRY(SPR_COL4, 0, -1, NULL, S_NULL), /* S_SHRTREDCOL */ + STATE_ENTRY(SPR_CAND, 32768, -1, NULL, S_NULL), /* S_CANDLESTIK */ + STATE_ENTRY(SPR_CBRA, 32768, -1, NULL, S_NULL), /* S_CANDELABRA */ + STATE_ENTRY(SPR_COL6, 0, -1, NULL, S_NULL), /* S_SKULLCOL */ + STATE_ENTRY(SPR_TRE1, 0, -1, NULL, S_NULL), /* S_TORCHTREE */ + STATE_ENTRY(SPR_TRE2, 0, -1, NULL, S_NULL), /* S_BIGTREE */ + STATE_ENTRY(SPR_ELEC, 0, -1, NULL, S_NULL), /* S_TECHPILLAR */ + STATE_ENTRY(SPR_CEYE, 32768, 6, NULL, S_EVILEYE2), /* S_EVILEYE */ + STATE_ENTRY(SPR_CEYE, 32769, 6, NULL, S_EVILEYE3), /* S_EVILEYE2 */ + STATE_ENTRY(SPR_CEYE, 32770, 6, NULL, S_EVILEYE4), /* S_EVILEYE3 */ + STATE_ENTRY(SPR_CEYE, 32769, 6, NULL, S_EVILEYE), /* S_EVILEYE4 */ + STATE_ENTRY(SPR_FSKU, 32768, 6, NULL, S_FLOATSKULL2), /* S_FLOATSKULL */ + STATE_ENTRY(SPR_FSKU, 32769, 6, NULL, S_FLOATSKULL3), /* S_FLOATSKULL2 */ + STATE_ENTRY(SPR_FSKU, 32770, 6, NULL, S_FLOATSKULL), /* S_FLOATSKULL3 */ + STATE_ENTRY(SPR_COL5, 0, 14, NULL, S_HEARTCOL2), /* S_HEARTCOL */ + STATE_ENTRY(SPR_COL5, 1, 14, NULL, S_HEARTCOL), /* S_HEARTCOL2 */ + STATE_ENTRY(SPR_TBLU, 32768, 4, NULL, S_BLUETORCH2), /* S_BLUETORCH */ + STATE_ENTRY(SPR_TBLU, 32769, 4, NULL, S_BLUETORCH3), /* S_BLUETORCH2 */ + STATE_ENTRY(SPR_TBLU, 32770, 4, NULL, S_BLUETORCH4), /* S_BLUETORCH3 */ + STATE_ENTRY(SPR_TBLU, 32771, 4, NULL, S_BLUETORCH), /* S_BLUETORCH4 */ + STATE_ENTRY(SPR_TGRN, 32768, 4, NULL, S_GREENTORCH2), /* S_GREENTORCH */ + STATE_ENTRY(SPR_TGRN, 32769, 4, NULL, S_GREENTORCH3), /* S_GREENTORCH2 */ + STATE_ENTRY(SPR_TGRN, 32770, 4, NULL, S_GREENTORCH4), /* S_GREENTORCH3 */ + STATE_ENTRY(SPR_TGRN, 32771, 4, NULL, S_GREENTORCH), /* S_GREENTORCH4 */ + STATE_ENTRY(SPR_TRED, 32768, 4, NULL, S_REDTORCH2), /* S_REDTORCH */ + STATE_ENTRY(SPR_TRED, 32769, 4, NULL, S_REDTORCH3), /* S_REDTORCH2 */ + STATE_ENTRY(SPR_TRED, 32770, 4, NULL, S_REDTORCH4), /* S_REDTORCH3 */ + STATE_ENTRY(SPR_TRED, 32771, 4, NULL, S_REDTORCH), /* S_REDTORCH4 */ + STATE_ENTRY(SPR_SMBT, 32768, 4, NULL, S_BTORCHSHRT2), /* S_BTORCHSHRT */ + STATE_ENTRY(SPR_SMBT, 32769, 4, NULL, S_BTORCHSHRT3), /* S_BTORCHSHRT2 */ + STATE_ENTRY(SPR_SMBT, 32770, 4, NULL, S_BTORCHSHRT4), /* S_BTORCHSHRT3 */ + STATE_ENTRY(SPR_SMBT, 32771, 4, NULL, S_BTORCHSHRT), /* S_BTORCHSHRT4 */ + STATE_ENTRY(SPR_SMGT, 32768, 4, NULL, S_GTORCHSHRT2), /* S_GTORCHSHRT */ + STATE_ENTRY(SPR_SMGT, 32769, 4, NULL, S_GTORCHSHRT3), /* S_GTORCHSHRT2 */ + STATE_ENTRY(SPR_SMGT, 32770, 4, NULL, S_GTORCHSHRT4), /* S_GTORCHSHRT3 */ + STATE_ENTRY(SPR_SMGT, 32771, 4, NULL, S_GTORCHSHRT), /* S_GTORCHSHRT4 */ + STATE_ENTRY(SPR_SMRT, 32768, 4, NULL, S_RTORCHSHRT2), /* S_RTORCHSHRT */ + STATE_ENTRY(SPR_SMRT, 32769, 4, NULL, S_RTORCHSHRT3), /* S_RTORCHSHRT2 */ + STATE_ENTRY(SPR_SMRT, 32770, 4, NULL, S_RTORCHSHRT4), /* S_RTORCHSHRT3 */ + STATE_ENTRY(SPR_SMRT, 32771, 4, NULL, S_RTORCHSHRT), /* S_RTORCHSHRT4 */ + STATE_ENTRY(SPR_HDB1, 0, -1, NULL, S_NULL), /* S_HANGNOGUTS */ + STATE_ENTRY(SPR_HDB2, 0, -1, NULL, S_NULL), /* S_HANGBNOBRAIN */ + STATE_ENTRY(SPR_HDB3, 0, -1, NULL, S_NULL), /* S_HANGTLOOKDN */ + STATE_ENTRY(SPR_HDB4, 0, -1, NULL, S_NULL), /* S_HANGTSKULL */ + STATE_ENTRY(SPR_HDB5, 0, -1, NULL, S_NULL), /* S_HANGTLOOKUP */ + STATE_ENTRY(SPR_HDB6, 0, -1, NULL, S_NULL), /* S_HANGTNOBRAIN */ + STATE_ENTRY(SPR_POB1, 0, -1, NULL, S_NULL), /* S_COLONGIBS */ + STATE_ENTRY(SPR_POB2, 0, -1, NULL, S_NULL), /* S_SMALLPOOL */ + STATE_ENTRY(SPR_BRS1, 0, -1, NULL, S_NULL), /* S_BRAINSTEM */ + STATE_ENTRY(SPR_TLMP, 32768, 4, NULL, S_TECHLAMP2), /* S_TECHLAMP */ + STATE_ENTRY(SPR_TLMP, 32769, 4, NULL, S_TECHLAMP3), /* S_TECHLAMP2 */ + STATE_ENTRY(SPR_TLMP, 32770, 4, NULL, S_TECHLAMP4), /* S_TECHLAMP3 */ + STATE_ENTRY(SPR_TLMP, 32771, 4, NULL, S_TECHLAMP), /* S_TECHLAMP4 */ + STATE_ENTRY(SPR_TLP2, 32768, 4, NULL, S_TECH2LAMP2), /* S_TECH2LAMP */ + STATE_ENTRY(SPR_TLP2, 32769, 4, NULL, S_TECH2LAMP3), /* S_TECH2LAMP2 */ + STATE_ENTRY(SPR_TLP2, 32770, 4, NULL, S_TECH2LAMP4), /* S_TECH2LAMP3 */ + STATE_ENTRY(SPR_TLP2, 32771, 4, NULL, S_TECH2LAMP) /* S_TECH2LAMP4 */ }; - -mobjinfo_t mobjinfo[NUMMOBJTYPES] = { - - { // MT_PLAYER - -1, // doomednum - S_PLAY, // spawnstate - 100, // spawnhealth - S_PLAY_RUN1, // seestate - sfx_None, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_PLAY_PAIN, // painstate - 255, // painchance - sfx_plpain, // painsound - S_NULL, // meleestate - S_PLAY_ATK1, // missilestate - S_PLAY_DIE1, // deathstate - S_PLAY_XDIE1, // xdeathstate - sfx_pldeth, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 56*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_POSSESSED - 3004, // doomednum - S_POSS_STND, // spawnstate - 20, // spawnhealth - S_POSS_RUN1, // seestate - sfx_posit1, // seesound - 8, // reactiontime - sfx_pistol, // attacksound - S_POSS_PAIN, // painstate - 200, // painchance - sfx_popain, // painsound - 0, // meleestate - S_POSS_ATK1, // missilestate - S_POSS_DIE1, // deathstate - S_POSS_XDIE1, // xdeathstate - sfx_podth1, // deathsound - 8, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_posact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_POSS_RAISE1 // raisestate - }, - - { // MT_SHOTGUY - 9, // doomednum - S_SPOS_STND, // spawnstate - 30, // spawnhealth - S_SPOS_RUN1, // seestate - sfx_posit2, // seesound - 8, // reactiontime - 0, // attacksound - S_SPOS_PAIN, // painstate - 170, // painchance - sfx_popain, // painsound - 0, // meleestate - S_SPOS_ATK1, // missilestate - S_SPOS_DIE1, // deathstate - S_SPOS_XDIE1, // xdeathstate - sfx_podth2, // deathsound - 8, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_posact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_SPOS_RAISE1 // raisestate - }, - - { // MT_VILE - 64, // doomednum - S_VILE_STND, // spawnstate - 700, // spawnhealth - S_VILE_RUN1, // seestate - sfx_vilsit, // seesound - 8, // reactiontime - 0, // attacksound - S_VILE_PAIN, // painstate - 10, // painchance - sfx_vipain, // painsound - 0, // meleestate - S_VILE_ATK1, // missilestate - S_VILE_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_vildth, // deathsound - 15, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 500, // mass - 0, // damage - sfx_vilact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_NULL // raisestate - }, - - { // MT_FIRE - -1, // doomednum - S_FIRE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_UNDEAD - 66, // doomednum - S_SKEL_STND, // spawnstate - 300, // spawnhealth - S_SKEL_RUN1, // seestate - sfx_skesit, // seesound - 8, // reactiontime - 0, // attacksound - S_SKEL_PAIN, // painstate - 100, // painchance - sfx_popain, // painsound - S_SKEL_FIST1, // meleestate - S_SKEL_MISS1, // missilestate - S_SKEL_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_skedth, // deathsound - 10, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 500, // mass - 0, // damage - sfx_skeact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_SKEL_RAISE1 // raisestate - }, - - { // MT_TRACER - -1, // doomednum - S_TRACER, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_skeatk, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_TRACEEXP1, // deathstate - S_NULL, // xdeathstate - sfx_barexp, // deathsound - 10*FRACUNIT, // speed - 11*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 10, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_SMOKE - -1, // doomednum - S_SMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_FATSO - 67, // doomednum - S_FATT_STND, // spawnstate - 600, // spawnhealth - S_FATT_RUN1, // seestate - sfx_mansit, // seesound - 8, // reactiontime - 0, // attacksound - S_FATT_PAIN, // painstate - 80, // painchance - sfx_mnpain, // painsound - 0, // meleestate - S_FATT_ATK1, // missilestate - S_FATT_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_mandth, // deathsound - 8, // speed - 48*FRACUNIT, // radius - 64*FRACUNIT, // height - 1000, // mass - 0, // damage - sfx_posact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_FATT_RAISE1 // raisestate - }, - - { // MT_FATSHOT - -1, // doomednum - S_FATSHOT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_firsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_FATSHOTX1, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 20*FRACUNIT, // speed - 6*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 8, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_CHAINGUY - 65, // doomednum - S_CPOS_STND, // spawnstate - 70, // spawnhealth - S_CPOS_RUN1, // seestate - sfx_posit2, // seesound - 8, // reactiontime - 0, // attacksound - S_CPOS_PAIN, // painstate - 170, // painchance - sfx_popain, // painsound - 0, // meleestate - S_CPOS_ATK1, // missilestate - S_CPOS_DIE1, // deathstate - S_CPOS_XDIE1, // xdeathstate - sfx_podth2, // deathsound - 8, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_posact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_CPOS_RAISE1 // raisestate - }, - - { // MT_TROOP - 3001, // doomednum - S_TROO_STND, // spawnstate - 60, // spawnhealth - S_TROO_RUN1, // seestate - sfx_bgsit1, // seesound - 8, // reactiontime - 0, // attacksound - S_TROO_PAIN, // painstate - 200, // painchance - sfx_popain, // painsound - S_TROO_ATK1, // meleestate - S_TROO_ATK1, // missilestate - S_TROO_DIE1, // deathstate - S_TROO_XDIE1, // xdeathstate - sfx_bgdth1, // deathsound - 8, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_bgact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_TROO_RAISE1 // raisestate - }, - - { // MT_SERGEANT - 3002, // doomednum - S_SARG_STND, // spawnstate - 150, // spawnhealth - S_SARG_RUN1, // seestate - sfx_sgtsit, // seesound - 8, // reactiontime - sfx_sgtatk, // attacksound - S_SARG_PAIN, // painstate - 180, // painchance - sfx_dmpain, // painsound - S_SARG_ATK1, // meleestate - 0, // missilestate - S_SARG_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_sgtdth, // deathsound - 10, // speed - 30*FRACUNIT, // radius - 56*FRACUNIT, // height - 400, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_SARG_RAISE1 // raisestate - }, - - { // MT_SHADOWS - 58, // doomednum - S_SARG_STND, // spawnstate - 150, // spawnhealth - S_SARG_RUN1, // seestate - sfx_sgtsit, // seesound - 8, // reactiontime - sfx_sgtatk, // attacksound - S_SARG_PAIN, // painstate - 180, // painchance - sfx_dmpain, // painsound - S_SARG_ATK1, // meleestate - 0, // missilestate - S_SARG_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_sgtdth, // deathsound - 10, // speed - 30*FRACUNIT, // radius - 56*FRACUNIT, // height - 400, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_SHADOW|MF_COUNTKILL, // flags - S_SARG_RAISE1 // raisestate - }, - - { // MT_HEAD - 3005, // doomednum - S_HEAD_STND, // spawnstate - 400, // spawnhealth - S_HEAD_RUN1, // seestate - sfx_cacsit, // seesound - 8, // reactiontime - 0, // attacksound - S_HEAD_PAIN, // painstate - 128, // painchance - sfx_dmpain, // painsound - 0, // meleestate - S_HEAD_ATK1, // missilestate - S_HEAD_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_cacdth, // deathsound - 8, // speed - 31*FRACUNIT, // radius - 56*FRACUNIT, // height - 400, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags - S_HEAD_RAISE1 // raisestate - }, - - { // MT_BRUISER - 3003, // doomednum - S_BOSS_STND, // spawnstate - 1000, // spawnhealth - S_BOSS_RUN1, // seestate - sfx_brssit, // seesound - 8, // reactiontime - 0, // attacksound - S_BOSS_PAIN, // painstate - 50, // painchance - sfx_dmpain, // painsound - S_BOSS_ATK1, // meleestate - S_BOSS_ATK1, // missilestate - S_BOSS_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_brsdth, // deathsound - 8, // speed - 24*FRACUNIT, // radius - 64*FRACUNIT, // height - 1000, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_BOSS_RAISE1 // raisestate - }, - - { // MT_BRUISERSHOT - -1, // doomednum - S_BRBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_firsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_BRBALLX1, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 15*FRACUNIT, // speed - 6*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 8, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_KNIGHT - 69, // doomednum - S_BOS2_STND, // spawnstate - 500, // spawnhealth - S_BOS2_RUN1, // seestate - sfx_kntsit, // seesound - 8, // reactiontime - 0, // attacksound - S_BOS2_PAIN, // painstate - 50, // painchance - sfx_dmpain, // painsound - S_BOS2_ATK1, // meleestate - S_BOS2_ATK1, // missilestate - S_BOS2_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_kntdth, // deathsound - 8, // speed - 24*FRACUNIT, // radius - 64*FRACUNIT, // height - 1000, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_BOS2_RAISE1 // raisestate - }, - - { // MT_SKULL - 3006, // doomednum - S_SKULL_STND, // spawnstate - 100, // spawnhealth - S_SKULL_RUN1, // seestate - 0, // seesound - 8, // reactiontime - sfx_sklatk, // attacksound - S_SKULL_PAIN, // painstate - 256, // painchance - sfx_dmpain, // painsound - 0, // meleestate - S_SKULL_ATK1, // missilestate - S_SKULL_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 8, // speed - 16*FRACUNIT, // radius - 56*FRACUNIT, // height - 50, // mass - 3, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_SPIDER - 7, // doomednum - S_SPID_STND, // spawnstate - 3000, // spawnhealth - S_SPID_RUN1, // seestate - sfx_spisit, // seesound - 8, // reactiontime - sfx_shotgn, // attacksound - S_SPID_PAIN, // painstate - 40, // painchance - sfx_dmpain, // painsound - 0, // meleestate - S_SPID_ATK1, // missilestate - S_SPID_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_spidth, // deathsound - 12, // speed - 128*FRACUNIT, // radius - 100*FRACUNIT, // height - 1000, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_NULL // raisestate - }, - - { // MT_BABY - 68, // doomednum - S_BSPI_STND, // spawnstate - 500, // spawnhealth - S_BSPI_SIGHT, // seestate - sfx_bspsit, // seesound - 8, // reactiontime - 0, // attacksound - S_BSPI_PAIN, // painstate - 128, // painchance - sfx_dmpain, // painsound - 0, // meleestate - S_BSPI_ATK1, // missilestate - S_BSPI_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_bspdth, // deathsound - 12, // speed - 64*FRACUNIT, // radius - 64*FRACUNIT, // height - 600, // mass - 0, // damage - sfx_bspact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_BSPI_RAISE1 // raisestate - }, - - { // MT_CYBORG - 16, // doomednum - S_CYBER_STND, // spawnstate - 4000, // spawnhealth - S_CYBER_RUN1, // seestate - sfx_cybsit, // seesound - 8, // reactiontime - 0, // attacksound - S_CYBER_PAIN, // painstate - 20, // painchance - sfx_dmpain, // painsound - 0, // meleestate - S_CYBER_ATK1, // missilestate - S_CYBER_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_cybdth, // deathsound - 16, // speed - 40*FRACUNIT, // radius - 110*FRACUNIT, // height - 1000, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_NULL // raisestate - }, - - { // MT_PAIN - 71, // doomednum - S_PAIN_STND, // spawnstate - 400, // spawnhealth - S_PAIN_RUN1, // seestate - sfx_pesit, // seesound - 8, // reactiontime - 0, // attacksound - S_PAIN_PAIN, // painstate - 128, // painchance - sfx_pepain, // painsound - 0, // meleestate - S_PAIN_ATK1, // missilestate - S_PAIN_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_pedth, // deathsound - 8, // speed - 31*FRACUNIT, // radius - 56*FRACUNIT, // height - 400, // mass - 0, // damage - sfx_dmact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL, // flags - S_PAIN_RAISE1 // raisestate - }, - - { // MT_WOLFSS - 84, // doomednum - S_SSWV_STND, // spawnstate - 50, // spawnhealth - S_SSWV_RUN1, // seestate - sfx_sssit, // seesound - 8, // reactiontime - 0, // attacksound - S_SSWV_PAIN, // painstate - 170, // painchance - sfx_popain, // painsound - 0, // meleestate - S_SSWV_ATK1, // missilestate - S_SSWV_DIE1, // deathstate - S_SSWV_XDIE1, // xdeathstate - sfx_ssdth, // deathsound - 8, // speed - 20*FRACUNIT, // radius - 56*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_posact, // activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_SSWV_RAISE1 // raisestate - }, - - { // MT_KEEN - 72, // doomednum - S_KEENSTND, // spawnstate - 100, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_KEENPAIN, // painstate - 256, // painchance - sfx_keenpn, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_COMMKEEN, // deathstate - S_NULL, // xdeathstate - sfx_keendt, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 72*FRACUNIT, // height - 10000000, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SHOOTABLE|MF_COUNTKILL, // flags - S_NULL // raisestate - }, - - { // MT_BOSSBRAIN - 88, // doomednum - S_BRAIN, // spawnstate - 250, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_BRAIN_PAIN, // painstate - 255, // painchance - sfx_bospn, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_BRAIN_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_bosdth, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 10000000, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE, // flags - S_NULL // raisestate - }, - - { // MT_BOSSSPIT - 89, // doomednum - S_BRAINEYE, // spawnstate - 1000, // spawnhealth - S_BRAINEYESEE, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 32*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR, // flags - S_NULL // raisestate - }, - - { // MT_BOSSTARGET - 87, // doomednum - S_NULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 32*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR, // flags - S_NULL // raisestate - }, - - { // MT_SPAWNSHOT - -1, // doomednum - S_SPAWN1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_bospit, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 10*FRACUNIT, // speed - 6*FRACUNIT, // radius - 32*FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_NOCLIP, // flags - S_NULL // raisestate - }, - - { // MT_SPAWNFIRE - -1, // doomednum - S_SPAWNFIRE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_BARREL - 2035, // doomednum - S_BAR1, // spawnstate - 20, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_BEXP, // deathstate - S_NULL, // xdeathstate - sfx_barexp, // deathsound - 0, // speed - 10*FRACUNIT, // radius - 42*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD, // flags - S_NULL // raisestate - }, - - { // MT_TROOPSHOT - -1, // doomednum - S_TBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_firsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_TBALLX1, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 10*FRACUNIT, // speed - 6*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_HEADSHOT - -1, // doomednum - S_RBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_firsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_RBALLX1, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 10*FRACUNIT, // speed - 6*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_ROCKET - -1, // doomednum - S_ROCKET, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_rlaunc, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_EXPLODE1, // deathstate - S_NULL, // xdeathstate - sfx_barexp, // deathsound - 20*FRACUNIT, // speed - 11*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 20, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_PLASMA - -1, // doomednum - S_PLASBALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_plasma, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_PLASEXP, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 25*FRACUNIT, // speed - 13*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_BFG - -1, // doomednum - S_BFGSHOT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_BFGLAND, // deathstate - S_NULL, // xdeathstate - sfx_rxplod, // deathsound - 25*FRACUNIT, // speed - 13*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 100, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_ARACHPLAZ - -1, // doomednum - S_ARACH_PLAZ, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_plasma, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_ARACH_PLEX, // deathstate - S_NULL, // xdeathstate - sfx_firxpl, // deathsound - 25*FRACUNIT, // speed - 13*FRACUNIT, // radius - 8*FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_PUFF - -1, // doomednum - S_PUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_BLOOD - -1, // doomednum - S_BLOOD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - S_NULL // raisestate - }, - - { // MT_TFOG - -1, // doomednum - S_TFOG, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_IFOG - -1, // doomednum - S_IFOG, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_TELEPORTMAN - 14, // doomednum - S_NULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOSECTOR, // flags - S_NULL // raisestate - }, - - { // MT_EXTRABFG - -1, // doomednum - S_BFGEXP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC0 - 2018, // doomednum - S_ARM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC1 - 2019, // doomednum - S_ARM2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC2 - 2014, // doomednum - S_BON1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_MISC3 - 2015, // doomednum - S_BON2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_MISC4 - 5, // doomednum - S_BKEY, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_MISC5 - 13, // doomednum - S_RKEY, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_MISC6 - 6, // doomednum - S_YKEY, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_MISC7 - 39, // doomednum - S_YSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_MISC8 - 38, // doomednum - S_RSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_MISC9 - 40, // doomednum - S_BSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOTDMATCH, // flags - S_NULL // raisestate - }, - - { // MT_MISC10 - 2011, // doomednum - S_STIM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC11 - 2012, // doomednum - S_MEDI, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC12 - 2013, // doomednum - S_SOUL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_INV - 2022, // doomednum - S_PINV, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_MISC13 - 2023, // doomednum - S_PSTR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_INS - 2024, // doomednum - S_PINS, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_MISC14 - 2025, // doomednum - S_SUIT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC15 - 2026, // doomednum - S_PMAP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_MISC16 - 2045, // doomednum - S_PVIS, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_MEGA - 83, // doomednum - S_MEGA, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_COUNTITEM, // flags - S_NULL // raisestate - }, - - { // MT_CLIP - 2007, // doomednum - S_CLIP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC17 - 2048, // doomednum - S_AMMO, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC18 - 2010, // doomednum - S_ROCK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC19 - 2046, // doomednum - S_BROK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC20 - 2047, // doomednum - S_CELL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC21 - 17, // doomednum - S_CELP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC22 - 2008, // doomednum - S_SHEL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC23 - 2049, // doomednum - S_SBOX, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC24 - 8, // doomednum - S_BPAK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC25 - 2006, // doomednum - S_BFUG, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_CHAINGUN - 2002, // doomednum - S_MGUN, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC26 - 2005, // doomednum - S_CSAW, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC27 - 2003, // doomednum - S_LAUN, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC28 - 2004, // doomednum - S_PLAS, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_SHOTGUN - 2001, // doomednum - S_SHOT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_SUPERSHOTGUN - 82, // doomednum - S_SHOT2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - S_NULL // raisestate - }, - - { // MT_MISC29 - 85, // doomednum - S_TECHLAMP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC30 - 86, // doomednum - S_TECH2LAMP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC31 - 2028, // doomednum - S_COLU, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC32 - 30, // doomednum - S_TALLGRNCOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC33 - 31, // doomednum - S_SHRTGRNCOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC34 - 32, // doomednum - S_TALLREDCOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC35 - 33, // doomednum - S_SHRTREDCOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC36 - 37, // doomednum - S_SKULLCOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC37 - 36, // doomednum - S_HEARTCOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC38 - 41, // doomednum - S_EVILEYE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC39 - 42, // doomednum - S_FLOATSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC40 - 43, // doomednum - S_TORCHTREE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC41 - 44, // doomednum - S_BLUETORCH, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC42 - 45, // doomednum - S_GREENTORCH, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC43 - 46, // doomednum - S_REDTORCH, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC44 - 55, // doomednum - S_BTORCHSHRT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC45 - 56, // doomednum - S_GTORCHSHRT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC46 - 57, // doomednum - S_RTORCHSHRT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC47 - 47, // doomednum - S_STALAGTITE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC48 - 48, // doomednum - S_TECHPILLAR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC49 - 34, // doomednum - S_CANDLESTIK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC50 - 35, // doomednum - S_CANDELABRA, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC51 - 49, // doomednum - S_BLOODYTWITCH, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 68*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC52 - 50, // doomednum - S_MEAT2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 84*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC53 - 51, // doomednum - S_MEAT3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 84*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC54 - 52, // doomednum - S_MEAT4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 68*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC55 - 53, // doomednum - S_MEAT5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 52*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC56 - 59, // doomednum - S_MEAT2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 84*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC57 - 60, // doomednum - S_MEAT4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 68*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC58 - 61, // doomednum - S_MEAT3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 52*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC59 - 62, // doomednum - S_MEAT5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 52*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC60 - 63, // doomednum - S_BLOODYTWITCH, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 68*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC61 - 22, // doomednum - S_HEAD_DIE6, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC62 - 15, // doomednum - S_PLAY_DIE7, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC63 - 18, // doomednum - S_POSS_DIE5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC64 - 21, // doomednum - S_SARG_DIE6, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC65 - 23, // doomednum - S_SKULL_DIE6, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC66 - 20, // doomednum - S_TROO_DIE5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC67 - 19, // doomednum - S_SPOS_DIE5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC68 - 10, // doomednum - S_PLAY_XDIE9, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC69 - 12, // doomednum - S_PLAY_XDIE9, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC70 - 28, // doomednum - S_HEADSONSTICK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC71 - 24, // doomednum - S_GIBS, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - 0, // flags - S_NULL // raisestate - }, - - { // MT_MISC72 - 27, // doomednum - S_HEADONASTICK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC73 - 29, // doomednum - S_HEADCANDLES, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC74 - 25, // doomednum - S_DEADSTICK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC75 - 26, // doomednum - S_LIVESTICK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC76 - 54, // doomednum - S_BIGTREE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 32*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC77 - 70, // doomednum - S_BBAR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - S_NULL // raisestate - }, - - { // MT_MISC78 - 73, // doomednum - S_HANGNOGUTS, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 88*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC79 - 74, // doomednum - S_HANGBNOBRAIN, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 88*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC80 - 75, // doomednum - S_HANGTLOOKDN, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC81 - 76, // doomednum - S_HANGTSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC82 - 77, // doomednum - S_HANGTLOOKUP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC83 - 78, // doomednum - S_HANGTNOBRAIN, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16*FRACUNIT, // radius - 64*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_MISC84 - 79, // doomednum - S_COLONGIBS, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - S_NULL // raisestate - }, - - { // MT_MISC85 - 80, // doomednum - S_SMALLPOOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - S_NULL // raisestate - }, - - { // MT_MISC86 - 81, // doomednum - S_BRAINSTEM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20*FRACUNIT, // radius - 16*FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - S_NULL // raisestate - } +mobjinfo_t mobjinfo[NUMMOBJTYPES] = +{ + { + /* MT_PLAYER */ + + .doomednum = -1, + .spawnstate = S_PLAY, + .spawnhealth = 100, + .seestate = S_PLAY_RUN1, + .reactiontime = 0, + .painstate = S_PLAY_PAIN, + .painchance = 255, + .meleestate = S_NULL, + .missilestate = S_PLAY_ATK1, + .deathstate = S_PLAY_DIE1, + .xdeathstate = S_PLAY_XDIE1, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | + MF_PICKUP | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_PLPAIN, + .deathsound = SFX_PLDETH, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_POSSESSED */ + + .doomednum = 3004, + .spawnstate = S_POSS_STND, + .spawnhealth = 20, + .seestate = S_POSS_RUN1, + .reactiontime = 8, + .painstate = S_POSS_PAIN, + .painchance = 200, + .meleestate = 0, + .missilestate = S_POSS_ATK1, + .deathstate = S_POSS_DIE1, + .xdeathstate = S_POSS_XDIE1, + .speed = 8, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_POSS_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_PISTOL, + .painsound = SFX_POPAIN, + .deathsound = SFX_PODTH1, + .activesound = SFX_POSACT, + .seesound = SFX_POSIT1, +#endif + }, + + { + /* MT_SHOTGUY */ + + .doomednum = 9, + .spawnstate = S_SPOS_STND, + .spawnhealth = 30, + .seestate = S_SPOS_RUN1, + .reactiontime = 8, + .painstate = S_SPOS_PAIN, + .painchance = 170, + .meleestate = 0, + .missilestate = S_SPOS_ATK1, + .deathstate = S_SPOS_DIE1, + .xdeathstate = S_SPOS_XDIE1, + .speed = 8, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_SPOS_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_POPAIN, + .deathsound = SFX_PODTH2, + .activesound = SFX_POSACT, + .seesound = SFX_POSIT2, +#endif + }, + + { + /* MT_VILE */ + + .doomednum = 64, + .spawnstate = S_VILE_STND, + .spawnhealth = 700, + .seestate = S_VILE_RUN1, + .reactiontime = 8, + .painstate = S_VILE_PAIN, + .painchance = 10, + .meleestate = 0, + .missilestate = S_VILE_ATK1, + .deathstate = S_VILE_DIE1, + .xdeathstate = S_NULL, + .speed = 15, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 500, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_VIPAIN, + .deathsound = SFX_VILDTH, + .activesound = SFX_VILACT, + .seesound = SFX_VILSIT, +#endif + }, + + { + /* MT_FIRE */ + + .doomednum = -1, + .spawnstate = S_FIRE1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_UNDEAD */ + + .doomednum = 66, + .spawnstate = S_SKEL_STND, + .spawnhealth = 300, + .seestate = S_SKEL_RUN1, + .reactiontime = 8, + .painstate = S_SKEL_PAIN, + .painchance = 100, + .meleestate = S_SKEL_FIST1, + .missilestate = S_SKEL_MISS1, + .deathstate = S_SKEL_DIE1, + .xdeathstate = S_NULL, + .speed = 10, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 500, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_SKEL_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_POPAIN, + .deathsound = SFX_SKEDTH, + .activesound = SFX_SKEACT, + .seesound = SFX_SKESIT, +#endif + }, + + { + /* MT_TRACER */ + + .doomednum = -1, + .spawnstate = S_TRACER, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_TRACEEXP1, + .xdeathstate = S_NULL, + .speed = 10 * FRACUNIT, + .radius = 11 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 10, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_BAREXP, + .activesound = SFX_NONE, + .seesound = SFX_SKEATK, +#endif + }, + + { + /* MT_SMOKE */ + + .doomednum = -1, + .spawnstate = S_SMOKE1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_FATSO */ + + .doomednum = 67, + .spawnstate = S_FATT_STND, + .spawnhealth = 600, + .seestate = S_FATT_RUN1, + .reactiontime = 8, + .painstate = S_FATT_PAIN, + .painchance = 80, + .meleestate = 0, + .missilestate = S_FATT_ATK1, + .deathstate = S_FATT_DIE1, + .xdeathstate = S_NULL, + .speed = 8, + .radius = 48 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 1000, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_FATT_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_MNPAIN, + .deathsound = SFX_MANDTH, + .activesound = SFX_POSACT, + .seesound = SFX_MANSIT, +#endif + }, + + { + /* MT_FATSHOT */ + + .doomednum = -1, + .spawnstate = S_FATSHOT1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_FATSHOTX1, + .xdeathstate = S_NULL, + .speed = 20 * FRACUNIT, + .radius = 6 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 8, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_FIRSHT, +#endif + }, + + { + /* MT_CHAINGUY */ + + .doomednum = 65, + .spawnstate = S_CPOS_STND, + .spawnhealth = 70, + .seestate = S_CPOS_RUN1, + .reactiontime = 8, + .painstate = S_CPOS_PAIN, + .painchance = 170, + .meleestate = 0, + .missilestate = S_CPOS_ATK1, + .deathstate = S_CPOS_DIE1, + .xdeathstate = S_CPOS_XDIE1, + .speed = 8, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_CPOS_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_POPAIN, + .deathsound = SFX_PODTH2, + .activesound = SFX_POSACT, + .seesound = SFX_POSIT2, +#endif + }, + + { + /* MT_TROOP */ + + .doomednum = 3001, + .spawnstate = S_TROO_STND, + .spawnhealth = 60, + .seestate = S_TROO_RUN1, + .reactiontime = 8, + .painstate = S_TROO_PAIN, + .painchance = 200, + .meleestate = S_TROO_ATK1, + .missilestate = S_TROO_ATK1, + .deathstate = S_TROO_DIE1, + .xdeathstate = S_TROO_XDIE1, + .speed = 8, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_TROO_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_POPAIN, + .deathsound = SFX_BGDTH1, + .activesound = SFX_BGACT, + .seesound = SFX_BGSIT1, +#endif + }, + + { + /* MT_SERGEANT */ + + .doomednum = 3002, + .spawnstate = S_SARG_STND, + .spawnhealth = 150, + .seestate = S_SARG_RUN1, + .reactiontime = 8, + .painstate = S_SARG_PAIN, + .painchance = 180, + .meleestate = S_SARG_ATK1, + .missilestate = 0, + .deathstate = S_SARG_DIE1, + .xdeathstate = S_NULL, + .speed = 10, + .radius = 30 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 400, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_SARG_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_SGTATK, + .painsound = SFX_DMPAIN, + .deathsound = SFX_SGTDTH, + .activesound = SFX_DMACT, + .seesound = SFX_SGTSIT, +#endif + }, + + { + /* MT_SHADOWS */ + + .doomednum = 58, + .spawnstate = S_SARG_STND, + .spawnhealth = 150, + .seestate = S_SARG_RUN1, + .reactiontime = 8, + .painstate = S_SARG_PAIN, + .painchance = 180, + .meleestate = S_SARG_ATK1, + .missilestate = 0, + .deathstate = S_SARG_DIE1, + .xdeathstate = S_NULL, + .speed = 10, + .radius = 30 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 400, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_SHADOW | MF_COUNTKILL, + .raisestate = S_SARG_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_SGTATK, + .painsound = SFX_DMPAIN, + .deathsound = SFX_SGTDTH, + .activesound = SFX_DMACT, + .seesound = SFX_SGTSIT, +#endif + }, + + { + /* MT_HEAD */ + + .doomednum = 3005, + .spawnstate = S_HEAD_STND, + .spawnhealth = 400, + .seestate = S_HEAD_RUN1, + .reactiontime = 8, + .painstate = S_HEAD_PAIN, + .painchance = 128, + .meleestate = 0, + .missilestate = S_HEAD_ATK1, + .deathstate = S_HEAD_DIE1, + .xdeathstate = S_NULL, + .speed = 8, + .radius = 31 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 400, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_FLOAT | + MF_NOGRAVITY | MF_COUNTKILL, + .raisestate = S_HEAD_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_DMPAIN, + .deathsound = SFX_CACDTH, + .activesound = SFX_DMACT, + .seesound = SFX_CACSIT, +#endif + }, + + { + /* MT_BRUISER */ + + .doomednum = 3003, + .spawnstate = S_BOSS_STND, + .spawnhealth = 1000, + .seestate = S_BOSS_RUN1, + .reactiontime = 8, + .painstate = S_BOSS_PAIN, + .painchance = 50, + .meleestate = S_BOSS_ATK1, + .missilestate = S_BOSS_ATK1, + .deathstate = S_BOSS_DIE1, + .xdeathstate = S_NULL, + .speed = 8, + .radius = 24 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 1000, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_BOSS_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_DMPAIN, + .deathsound = SFX_BRSDTH, + .activesound = SFX_DMACT, + .seesound = SFX_BRSSIT, +#endif + }, + + { + /* MT_BRUISERSHOT */ + + .doomednum = -1, + .spawnstate = S_BRBALL1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_BRBALLX1, + .xdeathstate = S_NULL, + .speed = 15 * FRACUNIT, + .radius = 6 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 8, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_FIRSHT, +#endif + }, + + { + /* MT_KNIGHT */ + + .doomednum = 69, + .spawnstate = S_BOS2_STND, + .spawnhealth = 500, + .seestate = S_BOS2_RUN1, + .reactiontime = 8, + .painstate = S_BOS2_PAIN, + .painchance = 50, + .meleestate = S_BOS2_ATK1, + .missilestate = S_BOS2_ATK1, + .deathstate = S_BOS2_DIE1, + .xdeathstate = S_NULL, + .speed = 8, + .radius = 24 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 1000, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_BOS2_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_DMPAIN, + .deathsound = SFX_KNTDTH, + .activesound = SFX_DMACT, + .seesound = SFX_KNTSIT, +#endif + }, + + { + /* MT_SKULL */ + + .doomednum = 3006, + .spawnstate = S_SKULL_STND, + .spawnhealth = 100, + .seestate = S_SKULL_RUN1, + .reactiontime = 8, + .painstate = S_SKULL_PAIN, + .painchance = 256, + .meleestate = 0, + .missilestate = S_SKULL_ATK1, + .deathstate = S_SKULL_DIE1, + .xdeathstate = S_NULL, + .speed = 8, + .radius = 16 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 50, + .damage = 3, + .flags = MF_SOLID | MF_SHOOTABLE | MF_FLOAT | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_SKLATK, + .painsound = SFX_DMPAIN, + .deathsound = SFX_FIRXPL, + .activesound = SFX_DMACT, + .seesound = 0, +#endif + }, + + { + /* MT_SPIDER */ + + .doomednum = 7, + .spawnstate = S_SPID_STND, + .spawnhealth = 3000, + .seestate = S_SPID_RUN1, + .reactiontime = 8, + .painstate = S_SPID_PAIN, + .painchance = 40, + .meleestate = 0, + .missilestate = S_SPID_ATK1, + .deathstate = S_SPID_DIE1, + .xdeathstate = S_NULL, + .speed = 12, + .radius = 128 * FRACUNIT, + .height = 100 * FRACUNIT, + .mass = 1000, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_SHOTGN, + .painsound = SFX_DMPAIN, + .deathsound = SFX_SPIDTH, + .activesound = SFX_DMACT, + .seesound = SFX_SPISIT, +#endif + }, + + { + /* MT_BABY */ + + .doomednum = 68, + .spawnstate = S_BSPI_STND, + .spawnhealth = 500, + .seestate = S_BSPI_SIGHT, + .reactiontime = 8, + .painstate = S_BSPI_PAIN, + .painchance = 128, + .meleestate = 0, + .missilestate = S_BSPI_ATK1, + .deathstate = S_BSPI_DIE1, + .xdeathstate = S_NULL, + .speed = 12, + .radius = 64 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 600, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_BSPI_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_DMPAIN, + .deathsound = SFX_BSPDTH, + .activesound = SFX_BSPACT, + .seesound = SFX_BSPSIT, +#endif + }, + + { + /* MT_CYBORG */ + + .doomednum = 16, + .spawnstate = S_CYBER_STND, + .spawnhealth = 4000, + .seestate = S_CYBER_RUN1, + .reactiontime = 8, + .painstate = S_CYBER_PAIN, + .painchance = 20, + .meleestate = 0, + .missilestate = S_CYBER_ATK1, + .deathstate = S_CYBER_DIE1, + .xdeathstate = S_NULL, + .speed = 16, + .radius = 40 * FRACUNIT, + .height = 110 * FRACUNIT, + .mass = 1000, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_DMPAIN, + .deathsound = SFX_CYBDTH, + .activesound = SFX_DMACT, + .seesound = SFX_CYBSIT, +#endif + }, + + { + /* MT_PAIN */ + + .doomednum = 71, + .spawnstate = S_PAIN_STND, + .spawnhealth = 400, + .seestate = S_PAIN_RUN1, + .reactiontime = 8, + .painstate = S_PAIN_PAIN, + .painchance = 128, + .meleestate = 0, + .missilestate = S_PAIN_ATK1, + .deathstate = S_PAIN_DIE1, + .xdeathstate = S_NULL, + .speed = 8, + .radius = 31 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 400, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_FLOAT | + MF_NOGRAVITY | MF_COUNTKILL, + .raisestate = S_PAIN_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_PEPAIN, + .deathsound = SFX_PEDTH, + .activesound = SFX_DMACT, + .seesound = SFX_PESIT, +#endif + }, + + { + /* MT_WOLFSS */ + + .doomednum = 84, + .spawnstate = S_SSWV_STND, + .spawnhealth = 50, + .seestate = S_SSWV_RUN1, + .reactiontime = 8, + .painstate = S_SSWV_PAIN, + .painchance = 170, + .meleestate = 0, + .missilestate = S_SSWV_ATK1, + .deathstate = S_SSWV_DIE1, + .xdeathstate = S_SSWV_XDIE1, + .speed = 8, + .radius = 20 * FRACUNIT, + .height = 56 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_SSWV_RAISE1, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = 0, + .painsound = SFX_POPAIN, + .deathsound = SFX_SSDTH, + .activesound = SFX_POSACT, + .seesound = SFX_SSSIT, +#endif + }, + + { + /* MT_KEEN */ + + .doomednum = 72, + .spawnstate = S_KEENSTND, + .spawnhealth = 100, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_KEENPAIN, + .painchance = 256, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_COMMKEEN, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 72 * FRACUNIT, + .mass = 10000000, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY | + MF_SHOOTABLE | MF_COUNTKILL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_KEENPN, + .deathsound = SFX_KEENDT, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_BOSSBRAIN */ + + .doomednum = 88, + .spawnstate = S_BRAIN, + .spawnhealth = 250, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_BRAIN_PAIN, + .painchance = 255, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_BRAIN_DIE1, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 10000000, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_BOSPN, + .deathsound = SFX_BOSDTH, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_BOSSSPIT */ + + .doomednum = 89, + .spawnstate = S_BRAINEYE, + .spawnhealth = 1000, + .seestate = S_BRAINEYESEE, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 32 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOSECTOR, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_BOSSTARGET */ + + .doomednum = 87, + .spawnstate = S_NULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 32 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOSECTOR, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_SPAWNSHOT */ + + .doomednum = -1, + .spawnstate = S_SPAWN1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 10 * FRACUNIT, + .radius = 6 * FRACUNIT, + .height = 32 * FRACUNIT, + .mass = 100, + .damage = 3, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | + MF_NOGRAVITY | MF_NOCLIP, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_BOSPIT, +#endif + }, + + { + /* MT_SPAWNFIRE */ + + .doomednum = -1, + .spawnstate = S_SPAWNFIRE1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_BARREL */ + + .doomednum = 2035, + .spawnstate = S_BAR1, + .spawnhealth = 20, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_BEXP, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 10 * FRACUNIT, + .height = 42 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_BAREXP, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_TROOPSHOT */ + + .doomednum = -1, + .spawnstate = S_TBALL1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_TBALLX1, + .xdeathstate = S_NULL, + .speed = 10 * FRACUNIT, + .radius = 6 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 3, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_FIRSHT, +#endif + }, + + { + /* MT_HEADSHOT */ + + .doomednum = -1, + .spawnstate = S_RBALL1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_RBALLX1, + .xdeathstate = S_NULL, + .speed = 10 * FRACUNIT, + .radius = 6 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 5, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_FIRSHT, +#endif + }, + + { + /* MT_ROCKET */ + + .doomednum = -1, + .spawnstate = S_ROCKET, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_EXPLODE1, + .xdeathstate = S_NULL, + .speed = 20 * FRACUNIT, + .radius = 11 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 20, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_BAREXP, + .activesound = SFX_NONE, + .seesound = SFX_RLAUNC, +#endif + }, + + { + /* MT_PLASMA */ + + .doomednum = -1, + .spawnstate = S_PLASBALL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_PLASEXP, + .xdeathstate = S_NULL, + .speed = 25 * FRACUNIT, + .radius = 13 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 5, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_PLASMA, +#endif + }, + + { + /* MT_BFG */ + + .doomednum = -1, + .spawnstate = S_BFGSHOT, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_BFGLAND, + .xdeathstate = S_NULL, + .speed = 25 * FRACUNIT, + .radius = 13 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 100, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_RXPLOD, + .activesound = SFX_NONE, + .seesound = 0, +#endif + }, + + { + /* MT_ARACHPLAZ */ + + .doomednum = -1, + .spawnstate = S_ARACH_PLAZ, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_ARACH_PLEX, + .xdeathstate = S_NULL, + .speed = 25 * FRACUNIT, + .radius = 13 * FRACUNIT, + .height = 8 * FRACUNIT, + .mass = 100, + .damage = 5, + .flags = MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_FIRXPL, + .activesound = SFX_NONE, + .seesound = SFX_PLASMA, +#endif + }, + + { + /* MT_PUFF */ + + .doomednum = -1, + .spawnstate = S_PUFF1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_BLOOD */ + + .doomednum = -1, + .spawnstate = S_BLOOD1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_TFOG */ + + .doomednum = -1, + .spawnstate = S_TFOG, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_IFOG */ + + .doomednum = -1, + .spawnstate = S_IFOG, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_TELEPORTMAN */ + + .doomednum = 14, + .spawnstate = S_NULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOSECTOR, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_EXTRABFG */ + + .doomednum = -1, + .spawnstate = S_BFGEXP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC0 */ + + .doomednum = 2018, + .spawnstate = S_ARM1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC1 */ + + .doomednum = 2019, + .spawnstate = S_ARM2, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC2 */ + + .doomednum = 2014, + .spawnstate = S_BON1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC3 */ + + .doomednum = 2015, + .spawnstate = S_BON2, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC4 */ + + .doomednum = 5, + .spawnstate = S_BKEY, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC5 */ + + .doomednum = 13, + .spawnstate = S_RKEY, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC6 */ + + .doomednum = 6, + .spawnstate = S_YKEY, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC7 */ + + .doomednum = 39, + .spawnstate = S_YSKULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC8 */ + + .doomednum = 38, + .spawnstate = S_RSKULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC9 */ + + .doomednum = 40, + .spawnstate = S_BSKULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_NOTDMATCH, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC10 */ + + .doomednum = 2011, + .spawnstate = S_STIM, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC11 */ + + .doomednum = 2012, + .spawnstate = S_MEDI, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC12 */ + + .doomednum = 2013, + .spawnstate = S_SOUL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_INV */ + + .doomednum = 2022, + .spawnstate = S_PINV, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC13 */ + + .doomednum = 2023, + .spawnstate = S_PSTR, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_INS */ + + .doomednum = 2024, + .spawnstate = S_PINS, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC14 */ + + .doomednum = 2025, + .spawnstate = S_SUIT, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC15 */ + + .doomednum = 2026, + .spawnstate = S_PMAP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC16 */ + + .doomednum = 2045, + .spawnstate = S_PVIS, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MEGA */ + + .doomednum = 83, + .spawnstate = S_MEGA, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL | MF_COUNTITEM, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_CLIP */ + + .doomednum = 2007, + .spawnstate = S_CLIP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC17 */ + + .doomednum = 2048, + .spawnstate = S_AMMO, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC18 */ + + .doomednum = 2010, + .spawnstate = S_ROCK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC19 */ + + .doomednum = 2046, + .spawnstate = S_BROK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC20 */ + + .doomednum = 2047, + .spawnstate = S_CELL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC21 */ + + .doomednum = 17, + .spawnstate = S_CELP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC22 */ + + .doomednum = 2008, + .spawnstate = S_SHEL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC23 */ + + .doomednum = 2049, + .spawnstate = S_SBOX, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC24 */ + + .doomednum = 8, + .spawnstate = S_BPAK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC25 */ + + .doomednum = 2006, + .spawnstate = S_BFUG, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_CHAINGUN */ + + .doomednum = 2002, + .spawnstate = S_MGUN, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC26 */ + + .doomednum = 2005, + .spawnstate = S_CSAW, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC27 */ + + .doomednum = 2003, + .spawnstate = S_LAUN, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC28 */ + + .doomednum = 2004, + .spawnstate = S_PLAS, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_SHOTGUN */ + + .doomednum = 2001, + .spawnstate = S_SHOT, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_SUPERSHOTGUN */ + + .doomednum = 82, + .spawnstate = S_SHOT2, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPECIAL, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC29 */ + + .doomednum = 85, + .spawnstate = S_TECHLAMP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC30 */ + + .doomednum = 86, + .spawnstate = S_TECH2LAMP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC31 */ + + .doomednum = 2028, + .spawnstate = S_COLU, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC32 */ + + .doomednum = 30, + .spawnstate = S_TALLGRNCOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC33 */ + + .doomednum = 31, + .spawnstate = S_SHRTGRNCOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC34 */ + + .doomednum = 32, + .spawnstate = S_TALLREDCOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC35 */ + + .doomednum = 33, + .spawnstate = S_SHRTREDCOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC36 */ + + .doomednum = 37, + .spawnstate = S_SKULLCOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC37 */ + + .doomednum = 36, + .spawnstate = S_HEARTCOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC38 */ + + .doomednum = 41, + .spawnstate = S_EVILEYE, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC39 */ + + .doomednum = 42, + .spawnstate = S_FLOATSKULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC40 */ + + .doomednum = 43, + .spawnstate = S_TORCHTREE, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC41 */ + + .doomednum = 44, + .spawnstate = S_BLUETORCH, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC42 */ + + .doomednum = 45, + .spawnstate = S_GREENTORCH, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC43 */ + + .doomednum = 46, + .spawnstate = S_REDTORCH, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC44 */ + + .doomednum = 55, + .spawnstate = S_BTORCHSHRT, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC45 */ + + .doomednum = 56, + .spawnstate = S_GTORCHSHRT, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC46 */ + + .doomednum = 57, + .spawnstate = S_RTORCHSHRT, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC47 */ + + .doomednum = 47, + .spawnstate = S_STALAGTITE, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC48 */ + + .doomednum = 48, + .spawnstate = S_TECHPILLAR, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC49 */ + + .doomednum = 34, + .spawnstate = S_CANDLESTIK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC50 */ + + .doomednum = 35, + .spawnstate = S_CANDELABRA, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC51 */ + + .doomednum = 49, + .spawnstate = S_BLOODYTWITCH, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 68 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC52 */ + + .doomednum = 50, + .spawnstate = S_MEAT2, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 84 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC53 */ + + .doomednum = 51, + .spawnstate = S_MEAT3, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 84 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC54 */ + + .doomednum = 52, + .spawnstate = S_MEAT4, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 68 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC55 */ + + .doomednum = 53, + .spawnstate = S_MEAT5, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 52 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC56 */ + + .doomednum = 59, + .spawnstate = S_MEAT2, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 84 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC57 */ + + .doomednum = 60, + .spawnstate = S_MEAT4, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 68 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC58 */ + + .doomednum = 61, + .spawnstate = S_MEAT3, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 52 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC59 */ + + .doomednum = 62, + .spawnstate = S_MEAT5, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 52 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC60 */ + + .doomednum = 63, + .spawnstate = S_BLOODYTWITCH, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 68 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC61 */ + + .doomednum = 22, + .spawnstate = S_HEAD_DIE6, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC62 */ + + .doomednum = 15, + .spawnstate = S_PLAY_DIE7, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC63 */ + + .doomednum = 18, + .spawnstate = S_POSS_DIE5, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC64 */ + + .doomednum = 21, + .spawnstate = S_SARG_DIE6, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC65 */ + + .doomednum = 23, + .spawnstate = S_SKULL_DIE6, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC66 */ + + .doomednum = 20, + .spawnstate = S_TROO_DIE5, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC67 */ + + .doomednum = 19, + .spawnstate = S_SPOS_DIE5, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC68 */ + + .doomednum = 10, + .spawnstate = S_PLAY_XDIE9, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC69 */ + + .doomednum = 12, + .spawnstate = S_PLAY_XDIE9, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC70 */ + + .doomednum = 28, + .spawnstate = S_HEADSONSTICK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC71 */ + + .doomednum = 24, + .spawnstate = S_GIBS, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = 0, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC72 */ + + .doomednum = 27, + .spawnstate = S_HEADONASTICK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC73 */ + + .doomednum = 29, + .spawnstate = S_HEADCANDLES, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC74 */ + + .doomednum = 25, + .spawnstate = S_DEADSTICK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC75 */ + + .doomednum = 26, + .spawnstate = S_LIVESTICK, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC76 */ + + .doomednum = 54, + .spawnstate = S_BIGTREE, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 32 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC77 */ + + .doomednum = 70, + .spawnstate = S_BBAR1, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC78 */ + + .doomednum = 73, + .spawnstate = S_HANGNOGUTS, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 88 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC79 */ + + .doomednum = 74, + .spawnstate = S_HANGBNOBRAIN, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 88 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC80 */ + + .doomednum = 75, + .spawnstate = S_HANGTLOOKDN, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC81 */ + + .doomednum = 76, + .spawnstate = S_HANGTSKULL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC82 */ + + .doomednum = 77, + .spawnstate = S_HANGTLOOKUP, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC83 */ + + .doomednum = 78, + .spawnstate = S_HANGTNOBRAIN, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 16 * FRACUNIT, + .height = 64 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC84 */ + + .doomednum = 79, + .spawnstate = S_COLONGIBS, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC85 */ + + .doomednum = 80, + .spawnstate = S_SMALLPOOL, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, + .seesound = SFX_NONE, +#endif + }, + + { + /* MT_MISC86 */ + + .doomednum = 81, + .spawnstate = S_BRAINSTEM, + .spawnhealth = 1000, + .seestate = S_NULL, + .reactiontime = 8, + .painstate = S_NULL, + .painchance = 0, + .meleestate = S_NULL, + .missilestate = S_NULL, + .deathstate = S_NULL, + .xdeathstate = S_NULL, + .speed = 0, + .radius = 20 * FRACUNIT, + .height = 16 * FRACUNIT, + .mass = 100, + .damage = 0, + .flags = MF_NOBLOCKMAP, + .raisestate = S_NULL, +#ifdef CONFIG_GAMES_NXDOOM_SOUND + .seesound = SFX_NONE, + .attacksound = SFX_NONE, + .painsound = SFX_NONE, + .deathsound = SFX_NONE, + .activesound = SFX_NONE, +#endif + }, }; +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/doom/info.h b/games/NXDoom/src/doom/info.h index c426d07bf25..508475f9d64 100644 --- a/games/NXDoom/src/doom/info.h +++ b/games/NXDoom/src/doom/info.h @@ -1,1331 +1,1380 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Thing frame/state LUT, -// generated by multigen utilitiy. -// This one is the original DOOM version, preserved. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/info.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Thing frame/state LUT, generated by multigen utility. + * This one is the original DOOM version, preserved. + * + ****************************************************************************/ #ifndef __INFO__ #define __INFO__ -// Needed for action function pointer handling. +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Needed for action function pointer handling. */ + #include "d_think.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef enum { - SPR_TROO, - SPR_SHTG, - SPR_PUNG, - SPR_PISG, - SPR_PISF, - SPR_SHTF, - SPR_SHT2, - SPR_CHGG, - SPR_CHGF, - SPR_MISG, - SPR_MISF, - SPR_SAWG, - SPR_PLSG, - SPR_PLSF, - SPR_BFGG, - SPR_BFGF, - SPR_BLUD, - SPR_PUFF, - SPR_BAL1, - SPR_BAL2, - SPR_PLSS, - SPR_PLSE, - SPR_MISL, - SPR_BFS1, - SPR_BFE1, - SPR_BFE2, - SPR_TFOG, - SPR_IFOG, - SPR_PLAY, - SPR_POSS, - SPR_SPOS, - SPR_VILE, - SPR_FIRE, - SPR_FATB, - SPR_FBXP, - SPR_SKEL, - SPR_MANF, - SPR_FATT, - SPR_CPOS, - SPR_SARG, - SPR_HEAD, - SPR_BAL7, - SPR_BOSS, - SPR_BOS2, - SPR_SKUL, - SPR_SPID, - SPR_BSPI, - SPR_APLS, - SPR_APBX, - SPR_CYBR, - SPR_PAIN, - SPR_SSWV, - SPR_KEEN, - SPR_BBRN, - SPR_BOSF, - SPR_ARM1, - SPR_ARM2, - SPR_BAR1, - SPR_BEXP, - SPR_FCAN, - SPR_BON1, - SPR_BON2, - SPR_BKEY, - SPR_RKEY, - SPR_YKEY, - SPR_BSKU, - SPR_RSKU, - SPR_YSKU, - SPR_STIM, - SPR_MEDI, - SPR_SOUL, - SPR_PINV, - SPR_PSTR, - SPR_PINS, - SPR_MEGA, - SPR_SUIT, - SPR_PMAP, - SPR_PVIS, - SPR_CLIP, - SPR_AMMO, - SPR_ROCK, - SPR_BROK, - SPR_CELL, - SPR_CELP, - SPR_SHEL, - SPR_SBOX, - SPR_BPAK, - SPR_BFUG, - SPR_MGUN, - SPR_CSAW, - SPR_LAUN, - SPR_PLAS, - SPR_SHOT, - SPR_SGN2, - SPR_COLU, - SPR_SMT2, - SPR_GOR1, - SPR_POL2, - SPR_POL5, - SPR_POL4, - SPR_POL3, - SPR_POL1, - SPR_POL6, - SPR_GOR2, - SPR_GOR3, - SPR_GOR4, - SPR_GOR5, - SPR_SMIT, - SPR_COL1, - SPR_COL2, - SPR_COL3, - SPR_COL4, - SPR_CAND, - SPR_CBRA, - SPR_COL6, - SPR_TRE1, - SPR_TRE2, - SPR_ELEC, - SPR_CEYE, - SPR_FSKU, - SPR_COL5, - SPR_TBLU, - SPR_TGRN, - SPR_TRED, - SPR_SMBT, - SPR_SMGT, - SPR_SMRT, - SPR_HDB1, - SPR_HDB2, - SPR_HDB3, - SPR_HDB4, - SPR_HDB5, - SPR_HDB6, - SPR_POB1, - SPR_POB2, - SPR_BRS1, - SPR_TLMP, - SPR_TLP2, - NUMSPRITES - + SPR_TROO, + SPR_SHTG, + SPR_PUNG, + SPR_PISG, + SPR_PISF, + SPR_SHTF, + SPR_SHT2, + SPR_CHGG, + SPR_CHGF, + SPR_MISG, + SPR_MISF, + SPR_SAWG, + SPR_PLSG, + SPR_PLSF, + SPR_BFGG, + SPR_BFGF, + SPR_BLUD, + SPR_PUFF, + SPR_BAL1, + SPR_BAL2, + SPR_PLSS, + SPR_PLSE, + SPR_MISL, + SPR_BFS1, + SPR_BFE1, + SPR_BFE2, + SPR_TFOG, + SPR_IFOG, + SPR_PLAY, + SPR_POSS, + SPR_SPOS, + SPR_VILE, + SPR_FIRE, + SPR_FATB, + SPR_FBXP, + SPR_SKEL, + SPR_MANF, + SPR_FATT, + SPR_CPOS, + SPR_SARG, + SPR_HEAD, + SPR_BAL7, + SPR_BOSS, + SPR_BOS2, + SPR_SKUL, + SPR_SPID, + SPR_BSPI, + SPR_APLS, + SPR_APBX, + SPR_CYBR, + SPR_PAIN, + SPR_SSWV, + SPR_KEEN, + SPR_BBRN, + SPR_BOSF, + SPR_ARM1, + SPR_ARM2, + SPR_BAR1, + SPR_BEXP, + SPR_FCAN, + SPR_BON1, + SPR_BON2, + SPR_BKEY, + SPR_RKEY, + SPR_YKEY, + SPR_BSKU, + SPR_RSKU, + SPR_YSKU, + SPR_STIM, + SPR_MEDI, + SPR_SOUL, + SPR_PINV, + SPR_PSTR, + SPR_PINS, + SPR_MEGA, + SPR_SUIT, + SPR_PMAP, + SPR_PVIS, + SPR_CLIP, + SPR_AMMO, + SPR_ROCK, + SPR_BROK, + SPR_CELL, + SPR_CELP, + SPR_SHEL, + SPR_SBOX, + SPR_BPAK, + SPR_BFUG, + SPR_MGUN, + SPR_CSAW, + SPR_LAUN, + SPR_PLAS, + SPR_SHOT, + SPR_SGN2, + SPR_COLU, + SPR_SMT2, + SPR_GOR1, + SPR_POL2, + SPR_POL5, + SPR_POL4, + SPR_POL3, + SPR_POL1, + SPR_POL6, + SPR_GOR2, + SPR_GOR3, + SPR_GOR4, + SPR_GOR5, + SPR_SMIT, + SPR_COL1, + SPR_COL2, + SPR_COL3, + SPR_COL4, + SPR_CAND, + SPR_CBRA, + SPR_COL6, + SPR_TRE1, + SPR_TRE2, + SPR_ELEC, + SPR_CEYE, + SPR_FSKU, + SPR_COL5, + SPR_TBLU, + SPR_TGRN, + SPR_TRED, + SPR_SMBT, + SPR_SMGT, + SPR_SMRT, + SPR_HDB1, + SPR_HDB2, + SPR_HDB3, + SPR_HDB4, + SPR_HDB5, + SPR_HDB6, + SPR_POB1, + SPR_POB2, + SPR_BRS1, + SPR_TLMP, + SPR_TLP2, + NUMSPRITES } spritenum_t; typedef enum { - S_NULL, - S_LIGHTDONE, - S_PUNCH, - S_PUNCHDOWN, - S_PUNCHUP, - S_PUNCH1, - S_PUNCH2, - S_PUNCH3, - S_PUNCH4, - S_PUNCH5, - S_PISTOL, - S_PISTOLDOWN, - S_PISTOLUP, - S_PISTOL1, - S_PISTOL2, - S_PISTOL3, - S_PISTOL4, - S_PISTOLFLASH, - S_SGUN, - S_SGUNDOWN, - S_SGUNUP, - S_SGUN1, - S_SGUN2, - S_SGUN3, - S_SGUN4, - S_SGUN5, - S_SGUN6, - S_SGUN7, - S_SGUN8, - S_SGUN9, - S_SGUNFLASH1, - S_SGUNFLASH2, - S_DSGUN, - S_DSGUNDOWN, - S_DSGUNUP, - S_DSGUN1, - S_DSGUN2, - S_DSGUN3, - S_DSGUN4, - S_DSGUN5, - S_DSGUN6, - S_DSGUN7, - S_DSGUN8, - S_DSGUN9, - S_DSGUN10, - S_DSNR1, - S_DSNR2, - S_DSGUNFLASH1, - S_DSGUNFLASH2, - S_CHAIN, - S_CHAINDOWN, - S_CHAINUP, - S_CHAIN1, - S_CHAIN2, - S_CHAIN3, - S_CHAINFLASH1, - S_CHAINFLASH2, - S_MISSILE, - S_MISSILEDOWN, - S_MISSILEUP, - S_MISSILE1, - S_MISSILE2, - S_MISSILE3, - S_MISSILEFLASH1, - S_MISSILEFLASH2, - S_MISSILEFLASH3, - S_MISSILEFLASH4, - S_SAW, - S_SAWB, - S_SAWDOWN, - S_SAWUP, - S_SAW1, - S_SAW2, - S_SAW3, - S_PLASMA, - S_PLASMADOWN, - S_PLASMAUP, - S_PLASMA1, - S_PLASMA2, - S_PLASMAFLASH1, - S_PLASMAFLASH2, - S_BFG, - S_BFGDOWN, - S_BFGUP, - S_BFG1, - S_BFG2, - S_BFG3, - S_BFG4, - S_BFGFLASH1, - S_BFGFLASH2, - S_BLOOD1, - S_BLOOD2, - S_BLOOD3, - S_PUFF1, - S_PUFF2, - S_PUFF3, - S_PUFF4, - S_TBALL1, - S_TBALL2, - S_TBALLX1, - S_TBALLX2, - S_TBALLX3, - S_RBALL1, - S_RBALL2, - S_RBALLX1, - S_RBALLX2, - S_RBALLX3, - S_PLASBALL, - S_PLASBALL2, - S_PLASEXP, - S_PLASEXP2, - S_PLASEXP3, - S_PLASEXP4, - S_PLASEXP5, - S_ROCKET, - S_BFGSHOT, - S_BFGSHOT2, - S_BFGLAND, - S_BFGLAND2, - S_BFGLAND3, - S_BFGLAND4, - S_BFGLAND5, - S_BFGLAND6, - S_BFGEXP, - S_BFGEXP2, - S_BFGEXP3, - S_BFGEXP4, - S_EXPLODE1, - S_EXPLODE2, - S_EXPLODE3, - S_TFOG, - S_TFOG01, - S_TFOG02, - S_TFOG2, - S_TFOG3, - S_TFOG4, - S_TFOG5, - S_TFOG6, - S_TFOG7, - S_TFOG8, - S_TFOG9, - S_TFOG10, - S_IFOG, - S_IFOG01, - S_IFOG02, - S_IFOG2, - S_IFOG3, - S_IFOG4, - S_IFOG5, - S_PLAY, - S_PLAY_RUN1, - S_PLAY_RUN2, - S_PLAY_RUN3, - S_PLAY_RUN4, - S_PLAY_ATK1, - S_PLAY_ATK2, - S_PLAY_PAIN, - S_PLAY_PAIN2, - S_PLAY_DIE1, - S_PLAY_DIE2, - S_PLAY_DIE3, - S_PLAY_DIE4, - S_PLAY_DIE5, - S_PLAY_DIE6, - S_PLAY_DIE7, - S_PLAY_XDIE1, - S_PLAY_XDIE2, - S_PLAY_XDIE3, - S_PLAY_XDIE4, - S_PLAY_XDIE5, - S_PLAY_XDIE6, - S_PLAY_XDIE7, - S_PLAY_XDIE8, - S_PLAY_XDIE9, - S_POSS_STND, - S_POSS_STND2, - S_POSS_RUN1, - S_POSS_RUN2, - S_POSS_RUN3, - S_POSS_RUN4, - S_POSS_RUN5, - S_POSS_RUN6, - S_POSS_RUN7, - S_POSS_RUN8, - S_POSS_ATK1, - S_POSS_ATK2, - S_POSS_ATK3, - S_POSS_PAIN, - S_POSS_PAIN2, - S_POSS_DIE1, - S_POSS_DIE2, - S_POSS_DIE3, - S_POSS_DIE4, - S_POSS_DIE5, - S_POSS_XDIE1, - S_POSS_XDIE2, - S_POSS_XDIE3, - S_POSS_XDIE4, - S_POSS_XDIE5, - S_POSS_XDIE6, - S_POSS_XDIE7, - S_POSS_XDIE8, - S_POSS_XDIE9, - S_POSS_RAISE1, - S_POSS_RAISE2, - S_POSS_RAISE3, - S_POSS_RAISE4, - S_SPOS_STND, - S_SPOS_STND2, - S_SPOS_RUN1, - S_SPOS_RUN2, - S_SPOS_RUN3, - S_SPOS_RUN4, - S_SPOS_RUN5, - S_SPOS_RUN6, - S_SPOS_RUN7, - S_SPOS_RUN8, - S_SPOS_ATK1, - S_SPOS_ATK2, - S_SPOS_ATK3, - S_SPOS_PAIN, - S_SPOS_PAIN2, - S_SPOS_DIE1, - S_SPOS_DIE2, - S_SPOS_DIE3, - S_SPOS_DIE4, - S_SPOS_DIE5, - S_SPOS_XDIE1, - S_SPOS_XDIE2, - S_SPOS_XDIE3, - S_SPOS_XDIE4, - S_SPOS_XDIE5, - S_SPOS_XDIE6, - S_SPOS_XDIE7, - S_SPOS_XDIE8, - S_SPOS_XDIE9, - S_SPOS_RAISE1, - S_SPOS_RAISE2, - S_SPOS_RAISE3, - S_SPOS_RAISE4, - S_SPOS_RAISE5, - S_VILE_STND, - S_VILE_STND2, - S_VILE_RUN1, - S_VILE_RUN2, - S_VILE_RUN3, - S_VILE_RUN4, - S_VILE_RUN5, - S_VILE_RUN6, - S_VILE_RUN7, - S_VILE_RUN8, - S_VILE_RUN9, - S_VILE_RUN10, - S_VILE_RUN11, - S_VILE_RUN12, - S_VILE_ATK1, - S_VILE_ATK2, - S_VILE_ATK3, - S_VILE_ATK4, - S_VILE_ATK5, - S_VILE_ATK6, - S_VILE_ATK7, - S_VILE_ATK8, - S_VILE_ATK9, - S_VILE_ATK10, - S_VILE_ATK11, - S_VILE_HEAL1, - S_VILE_HEAL2, - S_VILE_HEAL3, - S_VILE_PAIN, - S_VILE_PAIN2, - S_VILE_DIE1, - S_VILE_DIE2, - S_VILE_DIE3, - S_VILE_DIE4, - S_VILE_DIE5, - S_VILE_DIE6, - S_VILE_DIE7, - S_VILE_DIE8, - S_VILE_DIE9, - S_VILE_DIE10, - S_FIRE1, - S_FIRE2, - S_FIRE3, - S_FIRE4, - S_FIRE5, - S_FIRE6, - S_FIRE7, - S_FIRE8, - S_FIRE9, - S_FIRE10, - S_FIRE11, - S_FIRE12, - S_FIRE13, - S_FIRE14, - S_FIRE15, - S_FIRE16, - S_FIRE17, - S_FIRE18, - S_FIRE19, - S_FIRE20, - S_FIRE21, - S_FIRE22, - S_FIRE23, - S_FIRE24, - S_FIRE25, - S_FIRE26, - S_FIRE27, - S_FIRE28, - S_FIRE29, - S_FIRE30, - S_SMOKE1, - S_SMOKE2, - S_SMOKE3, - S_SMOKE4, - S_SMOKE5, - S_TRACER, - S_TRACER2, - S_TRACEEXP1, - S_TRACEEXP2, - S_TRACEEXP3, - S_SKEL_STND, - S_SKEL_STND2, - S_SKEL_RUN1, - S_SKEL_RUN2, - S_SKEL_RUN3, - S_SKEL_RUN4, - S_SKEL_RUN5, - S_SKEL_RUN6, - S_SKEL_RUN7, - S_SKEL_RUN8, - S_SKEL_RUN9, - S_SKEL_RUN10, - S_SKEL_RUN11, - S_SKEL_RUN12, - S_SKEL_FIST1, - S_SKEL_FIST2, - S_SKEL_FIST3, - S_SKEL_FIST4, - S_SKEL_MISS1, - S_SKEL_MISS2, - S_SKEL_MISS3, - S_SKEL_MISS4, - S_SKEL_PAIN, - S_SKEL_PAIN2, - S_SKEL_DIE1, - S_SKEL_DIE2, - S_SKEL_DIE3, - S_SKEL_DIE4, - S_SKEL_DIE5, - S_SKEL_DIE6, - S_SKEL_RAISE1, - S_SKEL_RAISE2, - S_SKEL_RAISE3, - S_SKEL_RAISE4, - S_SKEL_RAISE5, - S_SKEL_RAISE6, - S_FATSHOT1, - S_FATSHOT2, - S_FATSHOTX1, - S_FATSHOTX2, - S_FATSHOTX3, - S_FATT_STND, - S_FATT_STND2, - S_FATT_RUN1, - S_FATT_RUN2, - S_FATT_RUN3, - S_FATT_RUN4, - S_FATT_RUN5, - S_FATT_RUN6, - S_FATT_RUN7, - S_FATT_RUN8, - S_FATT_RUN9, - S_FATT_RUN10, - S_FATT_RUN11, - S_FATT_RUN12, - S_FATT_ATK1, - S_FATT_ATK2, - S_FATT_ATK3, - S_FATT_ATK4, - S_FATT_ATK5, - S_FATT_ATK6, - S_FATT_ATK7, - S_FATT_ATK8, - S_FATT_ATK9, - S_FATT_ATK10, - S_FATT_PAIN, - S_FATT_PAIN2, - S_FATT_DIE1, - S_FATT_DIE2, - S_FATT_DIE3, - S_FATT_DIE4, - S_FATT_DIE5, - S_FATT_DIE6, - S_FATT_DIE7, - S_FATT_DIE8, - S_FATT_DIE9, - S_FATT_DIE10, - S_FATT_RAISE1, - S_FATT_RAISE2, - S_FATT_RAISE3, - S_FATT_RAISE4, - S_FATT_RAISE5, - S_FATT_RAISE6, - S_FATT_RAISE7, - S_FATT_RAISE8, - S_CPOS_STND, - S_CPOS_STND2, - S_CPOS_RUN1, - S_CPOS_RUN2, - S_CPOS_RUN3, - S_CPOS_RUN4, - S_CPOS_RUN5, - S_CPOS_RUN6, - S_CPOS_RUN7, - S_CPOS_RUN8, - S_CPOS_ATK1, - S_CPOS_ATK2, - S_CPOS_ATK3, - S_CPOS_ATK4, - S_CPOS_PAIN, - S_CPOS_PAIN2, - S_CPOS_DIE1, - S_CPOS_DIE2, - S_CPOS_DIE3, - S_CPOS_DIE4, - S_CPOS_DIE5, - S_CPOS_DIE6, - S_CPOS_DIE7, - S_CPOS_XDIE1, - S_CPOS_XDIE2, - S_CPOS_XDIE3, - S_CPOS_XDIE4, - S_CPOS_XDIE5, - S_CPOS_XDIE6, - S_CPOS_RAISE1, - S_CPOS_RAISE2, - S_CPOS_RAISE3, - S_CPOS_RAISE4, - S_CPOS_RAISE5, - S_CPOS_RAISE6, - S_CPOS_RAISE7, - S_TROO_STND, - S_TROO_STND2, - S_TROO_RUN1, - S_TROO_RUN2, - S_TROO_RUN3, - S_TROO_RUN4, - S_TROO_RUN5, - S_TROO_RUN6, - S_TROO_RUN7, - S_TROO_RUN8, - S_TROO_ATK1, - S_TROO_ATK2, - S_TROO_ATK3, - S_TROO_PAIN, - S_TROO_PAIN2, - S_TROO_DIE1, - S_TROO_DIE2, - S_TROO_DIE3, - S_TROO_DIE4, - S_TROO_DIE5, - S_TROO_XDIE1, - S_TROO_XDIE2, - S_TROO_XDIE3, - S_TROO_XDIE4, - S_TROO_XDIE5, - S_TROO_XDIE6, - S_TROO_XDIE7, - S_TROO_XDIE8, - S_TROO_RAISE1, - S_TROO_RAISE2, - S_TROO_RAISE3, - S_TROO_RAISE4, - S_TROO_RAISE5, - S_SARG_STND, - S_SARG_STND2, - S_SARG_RUN1, - S_SARG_RUN2, - S_SARG_RUN3, - S_SARG_RUN4, - S_SARG_RUN5, - S_SARG_RUN6, - S_SARG_RUN7, - S_SARG_RUN8, - S_SARG_ATK1, - S_SARG_ATK2, - S_SARG_ATK3, - S_SARG_PAIN, - S_SARG_PAIN2, - S_SARG_DIE1, - S_SARG_DIE2, - S_SARG_DIE3, - S_SARG_DIE4, - S_SARG_DIE5, - S_SARG_DIE6, - S_SARG_RAISE1, - S_SARG_RAISE2, - S_SARG_RAISE3, - S_SARG_RAISE4, - S_SARG_RAISE5, - S_SARG_RAISE6, - S_HEAD_STND, - S_HEAD_RUN1, - S_HEAD_ATK1, - S_HEAD_ATK2, - S_HEAD_ATK3, - S_HEAD_PAIN, - S_HEAD_PAIN2, - S_HEAD_PAIN3, - S_HEAD_DIE1, - S_HEAD_DIE2, - S_HEAD_DIE3, - S_HEAD_DIE4, - S_HEAD_DIE5, - S_HEAD_DIE6, - S_HEAD_RAISE1, - S_HEAD_RAISE2, - S_HEAD_RAISE3, - S_HEAD_RAISE4, - S_HEAD_RAISE5, - S_HEAD_RAISE6, - S_BRBALL1, - S_BRBALL2, - S_BRBALLX1, - S_BRBALLX2, - S_BRBALLX3, - S_BOSS_STND, - S_BOSS_STND2, - S_BOSS_RUN1, - S_BOSS_RUN2, - S_BOSS_RUN3, - S_BOSS_RUN4, - S_BOSS_RUN5, - S_BOSS_RUN6, - S_BOSS_RUN7, - S_BOSS_RUN8, - S_BOSS_ATK1, - S_BOSS_ATK2, - S_BOSS_ATK3, - S_BOSS_PAIN, - S_BOSS_PAIN2, - S_BOSS_DIE1, - S_BOSS_DIE2, - S_BOSS_DIE3, - S_BOSS_DIE4, - S_BOSS_DIE5, - S_BOSS_DIE6, - S_BOSS_DIE7, - S_BOSS_RAISE1, - S_BOSS_RAISE2, - S_BOSS_RAISE3, - S_BOSS_RAISE4, - S_BOSS_RAISE5, - S_BOSS_RAISE6, - S_BOSS_RAISE7, - S_BOS2_STND, - S_BOS2_STND2, - S_BOS2_RUN1, - S_BOS2_RUN2, - S_BOS2_RUN3, - S_BOS2_RUN4, - S_BOS2_RUN5, - S_BOS2_RUN6, - S_BOS2_RUN7, - S_BOS2_RUN8, - S_BOS2_ATK1, - S_BOS2_ATK2, - S_BOS2_ATK3, - S_BOS2_PAIN, - S_BOS2_PAIN2, - S_BOS2_DIE1, - S_BOS2_DIE2, - S_BOS2_DIE3, - S_BOS2_DIE4, - S_BOS2_DIE5, - S_BOS2_DIE6, - S_BOS2_DIE7, - S_BOS2_RAISE1, - S_BOS2_RAISE2, - S_BOS2_RAISE3, - S_BOS2_RAISE4, - S_BOS2_RAISE5, - S_BOS2_RAISE6, - S_BOS2_RAISE7, - S_SKULL_STND, - S_SKULL_STND2, - S_SKULL_RUN1, - S_SKULL_RUN2, - S_SKULL_ATK1, - S_SKULL_ATK2, - S_SKULL_ATK3, - S_SKULL_ATK4, - S_SKULL_PAIN, - S_SKULL_PAIN2, - S_SKULL_DIE1, - S_SKULL_DIE2, - S_SKULL_DIE3, - S_SKULL_DIE4, - S_SKULL_DIE5, - S_SKULL_DIE6, - S_SPID_STND, - S_SPID_STND2, - S_SPID_RUN1, - S_SPID_RUN2, - S_SPID_RUN3, - S_SPID_RUN4, - S_SPID_RUN5, - S_SPID_RUN6, - S_SPID_RUN7, - S_SPID_RUN8, - S_SPID_RUN9, - S_SPID_RUN10, - S_SPID_RUN11, - S_SPID_RUN12, - S_SPID_ATK1, - S_SPID_ATK2, - S_SPID_ATK3, - S_SPID_ATK4, - S_SPID_PAIN, - S_SPID_PAIN2, - S_SPID_DIE1, - S_SPID_DIE2, - S_SPID_DIE3, - S_SPID_DIE4, - S_SPID_DIE5, - S_SPID_DIE6, - S_SPID_DIE7, - S_SPID_DIE8, - S_SPID_DIE9, - S_SPID_DIE10, - S_SPID_DIE11, - S_BSPI_STND, - S_BSPI_STND2, - S_BSPI_SIGHT, - S_BSPI_RUN1, - S_BSPI_RUN2, - S_BSPI_RUN3, - S_BSPI_RUN4, - S_BSPI_RUN5, - S_BSPI_RUN6, - S_BSPI_RUN7, - S_BSPI_RUN8, - S_BSPI_RUN9, - S_BSPI_RUN10, - S_BSPI_RUN11, - S_BSPI_RUN12, - S_BSPI_ATK1, - S_BSPI_ATK2, - S_BSPI_ATK3, - S_BSPI_ATK4, - S_BSPI_PAIN, - S_BSPI_PAIN2, - S_BSPI_DIE1, - S_BSPI_DIE2, - S_BSPI_DIE3, - S_BSPI_DIE4, - S_BSPI_DIE5, - S_BSPI_DIE6, - S_BSPI_DIE7, - S_BSPI_RAISE1, - S_BSPI_RAISE2, - S_BSPI_RAISE3, - S_BSPI_RAISE4, - S_BSPI_RAISE5, - S_BSPI_RAISE6, - S_BSPI_RAISE7, - S_ARACH_PLAZ, - S_ARACH_PLAZ2, - S_ARACH_PLEX, - S_ARACH_PLEX2, - S_ARACH_PLEX3, - S_ARACH_PLEX4, - S_ARACH_PLEX5, - S_CYBER_STND, - S_CYBER_STND2, - S_CYBER_RUN1, - S_CYBER_RUN2, - S_CYBER_RUN3, - S_CYBER_RUN4, - S_CYBER_RUN5, - S_CYBER_RUN6, - S_CYBER_RUN7, - S_CYBER_RUN8, - S_CYBER_ATK1, - S_CYBER_ATK2, - S_CYBER_ATK3, - S_CYBER_ATK4, - S_CYBER_ATK5, - S_CYBER_ATK6, - S_CYBER_PAIN, - S_CYBER_DIE1, - S_CYBER_DIE2, - S_CYBER_DIE3, - S_CYBER_DIE4, - S_CYBER_DIE5, - S_CYBER_DIE6, - S_CYBER_DIE7, - S_CYBER_DIE8, - S_CYBER_DIE9, - S_CYBER_DIE10, - S_PAIN_STND, - S_PAIN_RUN1, - S_PAIN_RUN2, - S_PAIN_RUN3, - S_PAIN_RUN4, - S_PAIN_RUN5, - S_PAIN_RUN6, - S_PAIN_ATK1, - S_PAIN_ATK2, - S_PAIN_ATK3, - S_PAIN_ATK4, - S_PAIN_PAIN, - S_PAIN_PAIN2, - S_PAIN_DIE1, - S_PAIN_DIE2, - S_PAIN_DIE3, - S_PAIN_DIE4, - S_PAIN_DIE5, - S_PAIN_DIE6, - S_PAIN_RAISE1, - S_PAIN_RAISE2, - S_PAIN_RAISE3, - S_PAIN_RAISE4, - S_PAIN_RAISE5, - S_PAIN_RAISE6, - S_SSWV_STND, - S_SSWV_STND2, - S_SSWV_RUN1, - S_SSWV_RUN2, - S_SSWV_RUN3, - S_SSWV_RUN4, - S_SSWV_RUN5, - S_SSWV_RUN6, - S_SSWV_RUN7, - S_SSWV_RUN8, - S_SSWV_ATK1, - S_SSWV_ATK2, - S_SSWV_ATK3, - S_SSWV_ATK4, - S_SSWV_ATK5, - S_SSWV_ATK6, - S_SSWV_PAIN, - S_SSWV_PAIN2, - S_SSWV_DIE1, - S_SSWV_DIE2, - S_SSWV_DIE3, - S_SSWV_DIE4, - S_SSWV_DIE5, - S_SSWV_XDIE1, - S_SSWV_XDIE2, - S_SSWV_XDIE3, - S_SSWV_XDIE4, - S_SSWV_XDIE5, - S_SSWV_XDIE6, - S_SSWV_XDIE7, - S_SSWV_XDIE8, - S_SSWV_XDIE9, - S_SSWV_RAISE1, - S_SSWV_RAISE2, - S_SSWV_RAISE3, - S_SSWV_RAISE4, - S_SSWV_RAISE5, - S_KEENSTND, - S_COMMKEEN, - S_COMMKEEN2, - S_COMMKEEN3, - S_COMMKEEN4, - S_COMMKEEN5, - S_COMMKEEN6, - S_COMMKEEN7, - S_COMMKEEN8, - S_COMMKEEN9, - S_COMMKEEN10, - S_COMMKEEN11, - S_COMMKEEN12, - S_KEENPAIN, - S_KEENPAIN2, - S_BRAIN, - S_BRAIN_PAIN, - S_BRAIN_DIE1, - S_BRAIN_DIE2, - S_BRAIN_DIE3, - S_BRAIN_DIE4, - S_BRAINEYE, - S_BRAINEYESEE, - S_BRAINEYE1, - S_SPAWN1, - S_SPAWN2, - S_SPAWN3, - S_SPAWN4, - S_SPAWNFIRE1, - S_SPAWNFIRE2, - S_SPAWNFIRE3, - S_SPAWNFIRE4, - S_SPAWNFIRE5, - S_SPAWNFIRE6, - S_SPAWNFIRE7, - S_SPAWNFIRE8, - S_BRAINEXPLODE1, - S_BRAINEXPLODE2, - S_BRAINEXPLODE3, - S_ARM1, - S_ARM1A, - S_ARM2, - S_ARM2A, - S_BAR1, - S_BAR2, - S_BEXP, - S_BEXP2, - S_BEXP3, - S_BEXP4, - S_BEXP5, - S_BBAR1, - S_BBAR2, - S_BBAR3, - S_BON1, - S_BON1A, - S_BON1B, - S_BON1C, - S_BON1D, - S_BON1E, - S_BON2, - S_BON2A, - S_BON2B, - S_BON2C, - S_BON2D, - S_BON2E, - S_BKEY, - S_BKEY2, - S_RKEY, - S_RKEY2, - S_YKEY, - S_YKEY2, - S_BSKULL, - S_BSKULL2, - S_RSKULL, - S_RSKULL2, - S_YSKULL, - S_YSKULL2, - S_STIM, - S_MEDI, - S_SOUL, - S_SOUL2, - S_SOUL3, - S_SOUL4, - S_SOUL5, - S_SOUL6, - S_PINV, - S_PINV2, - S_PINV3, - S_PINV4, - S_PSTR, - S_PINS, - S_PINS2, - S_PINS3, - S_PINS4, - S_MEGA, - S_MEGA2, - S_MEGA3, - S_MEGA4, - S_SUIT, - S_PMAP, - S_PMAP2, - S_PMAP3, - S_PMAP4, - S_PMAP5, - S_PMAP6, - S_PVIS, - S_PVIS2, - S_CLIP, - S_AMMO, - S_ROCK, - S_BROK, - S_CELL, - S_CELP, - S_SHEL, - S_SBOX, - S_BPAK, - S_BFUG, - S_MGUN, - S_CSAW, - S_LAUN, - S_PLAS, - S_SHOT, - S_SHOT2, - S_COLU, - S_STALAG, - S_BLOODYTWITCH, - S_BLOODYTWITCH2, - S_BLOODYTWITCH3, - S_BLOODYTWITCH4, - S_DEADTORSO, - S_DEADBOTTOM, - S_HEADSONSTICK, - S_GIBS, - S_HEADONASTICK, - S_HEADCANDLES, - S_HEADCANDLES2, - S_DEADSTICK, - S_LIVESTICK, - S_LIVESTICK2, - S_MEAT2, - S_MEAT3, - S_MEAT4, - S_MEAT5, - S_STALAGTITE, - S_TALLGRNCOL, - S_SHRTGRNCOL, - S_TALLREDCOL, - S_SHRTREDCOL, - S_CANDLESTIK, - S_CANDELABRA, - S_SKULLCOL, - S_TORCHTREE, - S_BIGTREE, - S_TECHPILLAR, - S_EVILEYE, - S_EVILEYE2, - S_EVILEYE3, - S_EVILEYE4, - S_FLOATSKULL, - S_FLOATSKULL2, - S_FLOATSKULL3, - S_HEARTCOL, - S_HEARTCOL2, - S_BLUETORCH, - S_BLUETORCH2, - S_BLUETORCH3, - S_BLUETORCH4, - S_GREENTORCH, - S_GREENTORCH2, - S_GREENTORCH3, - S_GREENTORCH4, - S_REDTORCH, - S_REDTORCH2, - S_REDTORCH3, - S_REDTORCH4, - S_BTORCHSHRT, - S_BTORCHSHRT2, - S_BTORCHSHRT3, - S_BTORCHSHRT4, - S_GTORCHSHRT, - S_GTORCHSHRT2, - S_GTORCHSHRT3, - S_GTORCHSHRT4, - S_RTORCHSHRT, - S_RTORCHSHRT2, - S_RTORCHSHRT3, - S_RTORCHSHRT4, - S_HANGNOGUTS, - S_HANGBNOBRAIN, - S_HANGTLOOKDN, - S_HANGTSKULL, - S_HANGTLOOKUP, - S_HANGTNOBRAIN, - S_COLONGIBS, - S_SMALLPOOL, - S_BRAINSTEM, - S_TECHLAMP, - S_TECHLAMP2, - S_TECHLAMP3, - S_TECHLAMP4, - S_TECH2LAMP, - S_TECH2LAMP2, - S_TECH2LAMP3, - S_TECH2LAMP4, - NUMSTATES + S_NULL, + S_LIGHTDONE, + S_PUNCH, + S_PUNCHDOWN, + S_PUNCHUP, + S_PUNCH1, + S_PUNCH2, + S_PUNCH3, + S_PUNCH4, + S_PUNCH5, + S_PISTOL, + S_PISTOLDOWN, + S_PISTOLUP, + S_PISTOL1, + S_PISTOL2, + S_PISTOL3, + S_PISTOL4, + S_PISTOLFLASH, + S_SGUN, + S_SGUNDOWN, + S_SGUNUP, + S_SGUN1, + S_SGUN2, + S_SGUN3, + S_SGUN4, + S_SGUN5, + S_SGUN6, + S_SGUN7, + S_SGUN8, + S_SGUN9, + S_SGUNFLASH1, + S_SGUNFLASH2, + S_DSGUN, + S_DSGUNDOWN, + S_DSGUNUP, + S_DSGUN1, + S_DSGUN2, + S_DSGUN3, + S_DSGUN4, + S_DSGUN5, + S_DSGUN6, + S_DSGUN7, + S_DSGUN8, + S_DSGUN9, + S_DSGUN10, + S_DSNR1, + S_DSNR2, + S_DSGUNFLASH1, + S_DSGUNFLASH2, + S_CHAIN, + S_CHAINDOWN, + S_CHAINUP, + S_CHAIN1, + S_CHAIN2, + S_CHAIN3, + S_CHAINFLASH1, + S_CHAINFLASH2, + S_MISSILE, + S_MISSILEDOWN, + S_MISSILEUP, + S_MISSILE1, + S_MISSILE2, + S_MISSILE3, + S_MISSILEFLASH1, + S_MISSILEFLASH2, + S_MISSILEFLASH3, + S_MISSILEFLASH4, + S_SAW, + S_SAWB, + S_SAWDOWN, + S_SAWUP, + S_SAW1, + S_SAW2, + S_SAW3, + S_PLASMA, + S_PLASMADOWN, + S_PLASMAUP, + S_PLASMA1, + S_PLASMA2, + S_PLASMAFLASH1, + S_PLASMAFLASH2, + S_BFG, + S_BFGDOWN, + S_BFGUP, + S_BFG1, + S_BFG2, + S_BFG3, + S_BFG4, + S_BFGFLASH1, + S_BFGFLASH2, + S_BLOOD1, + S_BLOOD2, + S_BLOOD3, + S_PUFF1, + S_PUFF2, + S_PUFF3, + S_PUFF4, + S_TBALL1, + S_TBALL2, + S_TBALLX1, + S_TBALLX2, + S_TBALLX3, + S_RBALL1, + S_RBALL2, + S_RBALLX1, + S_RBALLX2, + S_RBALLX3, + S_PLASBALL, + S_PLASBALL2, + S_PLASEXP, + S_PLASEXP2, + S_PLASEXP3, + S_PLASEXP4, + S_PLASEXP5, + S_ROCKET, + S_BFGSHOT, + S_BFGSHOT2, + S_BFGLAND, + S_BFGLAND2, + S_BFGLAND3, + S_BFGLAND4, + S_BFGLAND5, + S_BFGLAND6, + S_BFGEXP, + S_BFGEXP2, + S_BFGEXP3, + S_BFGEXP4, + S_EXPLODE1, + S_EXPLODE2, + S_EXPLODE3, + S_TFOG, + S_TFOG01, + S_TFOG02, + S_TFOG2, + S_TFOG3, + S_TFOG4, + S_TFOG5, + S_TFOG6, + S_TFOG7, + S_TFOG8, + S_TFOG9, + S_TFOG10, + S_IFOG, + S_IFOG01, + S_IFOG02, + S_IFOG2, + S_IFOG3, + S_IFOG4, + S_IFOG5, + S_PLAY, + S_PLAY_RUN1, + S_PLAY_RUN2, + S_PLAY_RUN3, + S_PLAY_RUN4, + S_PLAY_ATK1, + S_PLAY_ATK2, + S_PLAY_PAIN, + S_PLAY_PAIN2, + S_PLAY_DIE1, + S_PLAY_DIE2, + S_PLAY_DIE3, + S_PLAY_DIE4, + S_PLAY_DIE5, + S_PLAY_DIE6, + S_PLAY_DIE7, + S_PLAY_XDIE1, + S_PLAY_XDIE2, + S_PLAY_XDIE3, + S_PLAY_XDIE4, + S_PLAY_XDIE5, + S_PLAY_XDIE6, + S_PLAY_XDIE7, + S_PLAY_XDIE8, + S_PLAY_XDIE9, + S_POSS_STND, + S_POSS_STND2, + S_POSS_RUN1, + S_POSS_RUN2, + S_POSS_RUN3, + S_POSS_RUN4, + S_POSS_RUN5, + S_POSS_RUN6, + S_POSS_RUN7, + S_POSS_RUN8, + S_POSS_ATK1, + S_POSS_ATK2, + S_POSS_ATK3, + S_POSS_PAIN, + S_POSS_PAIN2, + S_POSS_DIE1, + S_POSS_DIE2, + S_POSS_DIE3, + S_POSS_DIE4, + S_POSS_DIE5, + S_POSS_XDIE1, + S_POSS_XDIE2, + S_POSS_XDIE3, + S_POSS_XDIE4, + S_POSS_XDIE5, + S_POSS_XDIE6, + S_POSS_XDIE7, + S_POSS_XDIE8, + S_POSS_XDIE9, + S_POSS_RAISE1, + S_POSS_RAISE2, + S_POSS_RAISE3, + S_POSS_RAISE4, + S_SPOS_STND, + S_SPOS_STND2, + S_SPOS_RUN1, + S_SPOS_RUN2, + S_SPOS_RUN3, + S_SPOS_RUN4, + S_SPOS_RUN5, + S_SPOS_RUN6, + S_SPOS_RUN7, + S_SPOS_RUN8, + S_SPOS_ATK1, + S_SPOS_ATK2, + S_SPOS_ATK3, + S_SPOS_PAIN, + S_SPOS_PAIN2, + S_SPOS_DIE1, + S_SPOS_DIE2, + S_SPOS_DIE3, + S_SPOS_DIE4, + S_SPOS_DIE5, + S_SPOS_XDIE1, + S_SPOS_XDIE2, + S_SPOS_XDIE3, + S_SPOS_XDIE4, + S_SPOS_XDIE5, + S_SPOS_XDIE6, + S_SPOS_XDIE7, + S_SPOS_XDIE8, + S_SPOS_XDIE9, + S_SPOS_RAISE1, + S_SPOS_RAISE2, + S_SPOS_RAISE3, + S_SPOS_RAISE4, + S_SPOS_RAISE5, + S_VILE_STND, + S_VILE_STND2, + S_VILE_RUN1, + S_VILE_RUN2, + S_VILE_RUN3, + S_VILE_RUN4, + S_VILE_RUN5, + S_VILE_RUN6, + S_VILE_RUN7, + S_VILE_RUN8, + S_VILE_RUN9, + S_VILE_RUN10, + S_VILE_RUN11, + S_VILE_RUN12, + S_VILE_ATK1, + S_VILE_ATK2, + S_VILE_ATK3, + S_VILE_ATK4, + S_VILE_ATK5, + S_VILE_ATK6, + S_VILE_ATK7, + S_VILE_ATK8, + S_VILE_ATK9, + S_VILE_ATK10, + S_VILE_ATK11, + S_VILE_HEAL1, + S_VILE_HEAL2, + S_VILE_HEAL3, + S_VILE_PAIN, + S_VILE_PAIN2, + S_VILE_DIE1, + S_VILE_DIE2, + S_VILE_DIE3, + S_VILE_DIE4, + S_VILE_DIE5, + S_VILE_DIE6, + S_VILE_DIE7, + S_VILE_DIE8, + S_VILE_DIE9, + S_VILE_DIE10, + S_FIRE1, + S_FIRE2, + S_FIRE3, + S_FIRE4, + S_FIRE5, + S_FIRE6, + S_FIRE7, + S_FIRE8, + S_FIRE9, + S_FIRE10, + S_FIRE11, + S_FIRE12, + S_FIRE13, + S_FIRE14, + S_FIRE15, + S_FIRE16, + S_FIRE17, + S_FIRE18, + S_FIRE19, + S_FIRE20, + S_FIRE21, + S_FIRE22, + S_FIRE23, + S_FIRE24, + S_FIRE25, + S_FIRE26, + S_FIRE27, + S_FIRE28, + S_FIRE29, + S_FIRE30, + S_SMOKE1, + S_SMOKE2, + S_SMOKE3, + S_SMOKE4, + S_SMOKE5, + S_TRACER, + S_TRACER2, + S_TRACEEXP1, + S_TRACEEXP2, + S_TRACEEXP3, + S_SKEL_STND, + S_SKEL_STND2, + S_SKEL_RUN1, + S_SKEL_RUN2, + S_SKEL_RUN3, + S_SKEL_RUN4, + S_SKEL_RUN5, + S_SKEL_RUN6, + S_SKEL_RUN7, + S_SKEL_RUN8, + S_SKEL_RUN9, + S_SKEL_RUN10, + S_SKEL_RUN11, + S_SKEL_RUN12, + S_SKEL_FIST1, + S_SKEL_FIST2, + S_SKEL_FIST3, + S_SKEL_FIST4, + S_SKEL_MISS1, + S_SKEL_MISS2, + S_SKEL_MISS3, + S_SKEL_MISS4, + S_SKEL_PAIN, + S_SKEL_PAIN2, + S_SKEL_DIE1, + S_SKEL_DIE2, + S_SKEL_DIE3, + S_SKEL_DIE4, + S_SKEL_DIE5, + S_SKEL_DIE6, + S_SKEL_RAISE1, + S_SKEL_RAISE2, + S_SKEL_RAISE3, + S_SKEL_RAISE4, + S_SKEL_RAISE5, + S_SKEL_RAISE6, + S_FATSHOT1, + S_FATSHOT2, + S_FATSHOTX1, + S_FATSHOTX2, + S_FATSHOTX3, + S_FATT_STND, + S_FATT_STND2, + S_FATT_RUN1, + S_FATT_RUN2, + S_FATT_RUN3, + S_FATT_RUN4, + S_FATT_RUN5, + S_FATT_RUN6, + S_FATT_RUN7, + S_FATT_RUN8, + S_FATT_RUN9, + S_FATT_RUN10, + S_FATT_RUN11, + S_FATT_RUN12, + S_FATT_ATK1, + S_FATT_ATK2, + S_FATT_ATK3, + S_FATT_ATK4, + S_FATT_ATK5, + S_FATT_ATK6, + S_FATT_ATK7, + S_FATT_ATK8, + S_FATT_ATK9, + S_FATT_ATK10, + S_FATT_PAIN, + S_FATT_PAIN2, + S_FATT_DIE1, + S_FATT_DIE2, + S_FATT_DIE3, + S_FATT_DIE4, + S_FATT_DIE5, + S_FATT_DIE6, + S_FATT_DIE7, + S_FATT_DIE8, + S_FATT_DIE9, + S_FATT_DIE10, + S_FATT_RAISE1, + S_FATT_RAISE2, + S_FATT_RAISE3, + S_FATT_RAISE4, + S_FATT_RAISE5, + S_FATT_RAISE6, + S_FATT_RAISE7, + S_FATT_RAISE8, + S_CPOS_STND, + S_CPOS_STND2, + S_CPOS_RUN1, + S_CPOS_RUN2, + S_CPOS_RUN3, + S_CPOS_RUN4, + S_CPOS_RUN5, + S_CPOS_RUN6, + S_CPOS_RUN7, + S_CPOS_RUN8, + S_CPOS_ATK1, + S_CPOS_ATK2, + S_CPOS_ATK3, + S_CPOS_ATK4, + S_CPOS_PAIN, + S_CPOS_PAIN2, + S_CPOS_DIE1, + S_CPOS_DIE2, + S_CPOS_DIE3, + S_CPOS_DIE4, + S_CPOS_DIE5, + S_CPOS_DIE6, + S_CPOS_DIE7, + S_CPOS_XDIE1, + S_CPOS_XDIE2, + S_CPOS_XDIE3, + S_CPOS_XDIE4, + S_CPOS_XDIE5, + S_CPOS_XDIE6, + S_CPOS_RAISE1, + S_CPOS_RAISE2, + S_CPOS_RAISE3, + S_CPOS_RAISE4, + S_CPOS_RAISE5, + S_CPOS_RAISE6, + S_CPOS_RAISE7, + S_TROO_STND, + S_TROO_STND2, + S_TROO_RUN1, + S_TROO_RUN2, + S_TROO_RUN3, + S_TROO_RUN4, + S_TROO_RUN5, + S_TROO_RUN6, + S_TROO_RUN7, + S_TROO_RUN8, + S_TROO_ATK1, + S_TROO_ATK2, + S_TROO_ATK3, + S_TROO_PAIN, + S_TROO_PAIN2, + S_TROO_DIE1, + S_TROO_DIE2, + S_TROO_DIE3, + S_TROO_DIE4, + S_TROO_DIE5, + S_TROO_XDIE1, + S_TROO_XDIE2, + S_TROO_XDIE3, + S_TROO_XDIE4, + S_TROO_XDIE5, + S_TROO_XDIE6, + S_TROO_XDIE7, + S_TROO_XDIE8, + S_TROO_RAISE1, + S_TROO_RAISE2, + S_TROO_RAISE3, + S_TROO_RAISE4, + S_TROO_RAISE5, + S_SARG_STND, + S_SARG_STND2, + S_SARG_RUN1, + S_SARG_RUN2, + S_SARG_RUN3, + S_SARG_RUN4, + S_SARG_RUN5, + S_SARG_RUN6, + S_SARG_RUN7, + S_SARG_RUN8, + S_SARG_ATK1, + S_SARG_ATK2, + S_SARG_ATK3, + S_SARG_PAIN, + S_SARG_PAIN2, + S_SARG_DIE1, + S_SARG_DIE2, + S_SARG_DIE3, + S_SARG_DIE4, + S_SARG_DIE5, + S_SARG_DIE6, + S_SARG_RAISE1, + S_SARG_RAISE2, + S_SARG_RAISE3, + S_SARG_RAISE4, + S_SARG_RAISE5, + S_SARG_RAISE6, + S_HEAD_STND, + S_HEAD_RUN1, + S_HEAD_ATK1, + S_HEAD_ATK2, + S_HEAD_ATK3, + S_HEAD_PAIN, + S_HEAD_PAIN2, + S_HEAD_PAIN3, + S_HEAD_DIE1, + S_HEAD_DIE2, + S_HEAD_DIE3, + S_HEAD_DIE4, + S_HEAD_DIE5, + S_HEAD_DIE6, + S_HEAD_RAISE1, + S_HEAD_RAISE2, + S_HEAD_RAISE3, + S_HEAD_RAISE4, + S_HEAD_RAISE5, + S_HEAD_RAISE6, + S_BRBALL1, + S_BRBALL2, + S_BRBALLX1, + S_BRBALLX2, + S_BRBALLX3, + S_BOSS_STND, + S_BOSS_STND2, + S_BOSS_RUN1, + S_BOSS_RUN2, + S_BOSS_RUN3, + S_BOSS_RUN4, + S_BOSS_RUN5, + S_BOSS_RUN6, + S_BOSS_RUN7, + S_BOSS_RUN8, + S_BOSS_ATK1, + S_BOSS_ATK2, + S_BOSS_ATK3, + S_BOSS_PAIN, + S_BOSS_PAIN2, + S_BOSS_DIE1, + S_BOSS_DIE2, + S_BOSS_DIE3, + S_BOSS_DIE4, + S_BOSS_DIE5, + S_BOSS_DIE6, + S_BOSS_DIE7, + S_BOSS_RAISE1, + S_BOSS_RAISE2, + S_BOSS_RAISE3, + S_BOSS_RAISE4, + S_BOSS_RAISE5, + S_BOSS_RAISE6, + S_BOSS_RAISE7, + S_BOS2_STND, + S_BOS2_STND2, + S_BOS2_RUN1, + S_BOS2_RUN2, + S_BOS2_RUN3, + S_BOS2_RUN4, + S_BOS2_RUN5, + S_BOS2_RUN6, + S_BOS2_RUN7, + S_BOS2_RUN8, + S_BOS2_ATK1, + S_BOS2_ATK2, + S_BOS2_ATK3, + S_BOS2_PAIN, + S_BOS2_PAIN2, + S_BOS2_DIE1, + S_BOS2_DIE2, + S_BOS2_DIE3, + S_BOS2_DIE4, + S_BOS2_DIE5, + S_BOS2_DIE6, + S_BOS2_DIE7, + S_BOS2_RAISE1, + S_BOS2_RAISE2, + S_BOS2_RAISE3, + S_BOS2_RAISE4, + S_BOS2_RAISE5, + S_BOS2_RAISE6, + S_BOS2_RAISE7, + S_SKULL_STND, + S_SKULL_STND2, + S_SKULL_RUN1, + S_SKULL_RUN2, + S_SKULL_ATK1, + S_SKULL_ATK2, + S_SKULL_ATK3, + S_SKULL_ATK4, + S_SKULL_PAIN, + S_SKULL_PAIN2, + S_SKULL_DIE1, + S_SKULL_DIE2, + S_SKULL_DIE3, + S_SKULL_DIE4, + S_SKULL_DIE5, + S_SKULL_DIE6, + S_SPID_STND, + S_SPID_STND2, + S_SPID_RUN1, + S_SPID_RUN2, + S_SPID_RUN3, + S_SPID_RUN4, + S_SPID_RUN5, + S_SPID_RUN6, + S_SPID_RUN7, + S_SPID_RUN8, + S_SPID_RUN9, + S_SPID_RUN10, + S_SPID_RUN11, + S_SPID_RUN12, + S_SPID_ATK1, + S_SPID_ATK2, + S_SPID_ATK3, + S_SPID_ATK4, + S_SPID_PAIN, + S_SPID_PAIN2, + S_SPID_DIE1, + S_SPID_DIE2, + S_SPID_DIE3, + S_SPID_DIE4, + S_SPID_DIE5, + S_SPID_DIE6, + S_SPID_DIE7, + S_SPID_DIE8, + S_SPID_DIE9, + S_SPID_DIE10, + S_SPID_DIE11, + S_BSPI_STND, + S_BSPI_STND2, + S_BSPI_SIGHT, + S_BSPI_RUN1, + S_BSPI_RUN2, + S_BSPI_RUN3, + S_BSPI_RUN4, + S_BSPI_RUN5, + S_BSPI_RUN6, + S_BSPI_RUN7, + S_BSPI_RUN8, + S_BSPI_RUN9, + S_BSPI_RUN10, + S_BSPI_RUN11, + S_BSPI_RUN12, + S_BSPI_ATK1, + S_BSPI_ATK2, + S_BSPI_ATK3, + S_BSPI_ATK4, + S_BSPI_PAIN, + S_BSPI_PAIN2, + S_BSPI_DIE1, + S_BSPI_DIE2, + S_BSPI_DIE3, + S_BSPI_DIE4, + S_BSPI_DIE5, + S_BSPI_DIE6, + S_BSPI_DIE7, + S_BSPI_RAISE1, + S_BSPI_RAISE2, + S_BSPI_RAISE3, + S_BSPI_RAISE4, + S_BSPI_RAISE5, + S_BSPI_RAISE6, + S_BSPI_RAISE7, + S_ARACH_PLAZ, + S_ARACH_PLAZ2, + S_ARACH_PLEX, + S_ARACH_PLEX2, + S_ARACH_PLEX3, + S_ARACH_PLEX4, + S_ARACH_PLEX5, + S_CYBER_STND, + S_CYBER_STND2, + S_CYBER_RUN1, + S_CYBER_RUN2, + S_CYBER_RUN3, + S_CYBER_RUN4, + S_CYBER_RUN5, + S_CYBER_RUN6, + S_CYBER_RUN7, + S_CYBER_RUN8, + S_CYBER_ATK1, + S_CYBER_ATK2, + S_CYBER_ATK3, + S_CYBER_ATK4, + S_CYBER_ATK5, + S_CYBER_ATK6, + S_CYBER_PAIN, + S_CYBER_DIE1, + S_CYBER_DIE2, + S_CYBER_DIE3, + S_CYBER_DIE4, + S_CYBER_DIE5, + S_CYBER_DIE6, + S_CYBER_DIE7, + S_CYBER_DIE8, + S_CYBER_DIE9, + S_CYBER_DIE10, + S_PAIN_STND, + S_PAIN_RUN1, + S_PAIN_RUN2, + S_PAIN_RUN3, + S_PAIN_RUN4, + S_PAIN_RUN5, + S_PAIN_RUN6, + S_PAIN_ATK1, + S_PAIN_ATK2, + S_PAIN_ATK3, + S_PAIN_ATK4, + S_PAIN_PAIN, + S_PAIN_PAIN2, + S_PAIN_DIE1, + S_PAIN_DIE2, + S_PAIN_DIE3, + S_PAIN_DIE4, + S_PAIN_DIE5, + S_PAIN_DIE6, + S_PAIN_RAISE1, + S_PAIN_RAISE2, + S_PAIN_RAISE3, + S_PAIN_RAISE4, + S_PAIN_RAISE5, + S_PAIN_RAISE6, + S_SSWV_STND, + S_SSWV_STND2, + S_SSWV_RUN1, + S_SSWV_RUN2, + S_SSWV_RUN3, + S_SSWV_RUN4, + S_SSWV_RUN5, + S_SSWV_RUN6, + S_SSWV_RUN7, + S_SSWV_RUN8, + S_SSWV_ATK1, + S_SSWV_ATK2, + S_SSWV_ATK3, + S_SSWV_ATK4, + S_SSWV_ATK5, + S_SSWV_ATK6, + S_SSWV_PAIN, + S_SSWV_PAIN2, + S_SSWV_DIE1, + S_SSWV_DIE2, + S_SSWV_DIE3, + S_SSWV_DIE4, + S_SSWV_DIE5, + S_SSWV_XDIE1, + S_SSWV_XDIE2, + S_SSWV_XDIE3, + S_SSWV_XDIE4, + S_SSWV_XDIE5, + S_SSWV_XDIE6, + S_SSWV_XDIE7, + S_SSWV_XDIE8, + S_SSWV_XDIE9, + S_SSWV_RAISE1, + S_SSWV_RAISE2, + S_SSWV_RAISE3, + S_SSWV_RAISE4, + S_SSWV_RAISE5, + S_KEENSTND, + S_COMMKEEN, + S_COMMKEEN2, + S_COMMKEEN3, + S_COMMKEEN4, + S_COMMKEEN5, + S_COMMKEEN6, + S_COMMKEEN7, + S_COMMKEEN8, + S_COMMKEEN9, + S_COMMKEEN10, + S_COMMKEEN11, + S_COMMKEEN12, + S_KEENPAIN, + S_KEENPAIN2, + S_BRAIN, + S_BRAIN_PAIN, + S_BRAIN_DIE1, + S_BRAIN_DIE2, + S_BRAIN_DIE3, + S_BRAIN_DIE4, + S_BRAINEYE, + S_BRAINEYESEE, + S_BRAINEYE1, + S_SPAWN1, + S_SPAWN2, + S_SPAWN3, + S_SPAWN4, + S_SPAWNFIRE1, + S_SPAWNFIRE2, + S_SPAWNFIRE3, + S_SPAWNFIRE4, + S_SPAWNFIRE5, + S_SPAWNFIRE6, + S_SPAWNFIRE7, + S_SPAWNFIRE8, + S_BRAINEXPLODE1, + S_BRAINEXPLODE2, + S_BRAINEXPLODE3, + S_ARM1, + S_ARM1A, + S_ARM2, + S_ARM2A, + S_BAR1, + S_BAR2, + S_BEXP, + S_BEXP2, + S_BEXP3, + S_BEXP4, + S_BEXP5, + S_BBAR1, + S_BBAR2, + S_BBAR3, + S_BON1, + S_BON1A, + S_BON1B, + S_BON1C, + S_BON1D, + S_BON1E, + S_BON2, + S_BON2A, + S_BON2B, + S_BON2C, + S_BON2D, + S_BON2E, + S_BKEY, + S_BKEY2, + S_RKEY, + S_RKEY2, + S_YKEY, + S_YKEY2, + S_BSKULL, + S_BSKULL2, + S_RSKULL, + S_RSKULL2, + S_YSKULL, + S_YSKULL2, + S_STIM, + S_MEDI, + S_SOUL, + S_SOUL2, + S_SOUL3, + S_SOUL4, + S_SOUL5, + S_SOUL6, + S_PINV, + S_PINV2, + S_PINV3, + S_PINV4, + S_PSTR, + S_PINS, + S_PINS2, + S_PINS3, + S_PINS4, + S_MEGA, + S_MEGA2, + S_MEGA3, + S_MEGA4, + S_SUIT, + S_PMAP, + S_PMAP2, + S_PMAP3, + S_PMAP4, + S_PMAP5, + S_PMAP6, + S_PVIS, + S_PVIS2, + S_CLIP, + S_AMMO, + S_ROCK, + S_BROK, + S_CELL, + S_CELP, + S_SHEL, + S_SBOX, + S_BPAK, + S_BFUG, + S_MGUN, + S_CSAW, + S_LAUN, + S_PLAS, + S_SHOT, + S_SHOT2, + S_COLU, + S_STALAG, + S_BLOODYTWITCH, + S_BLOODYTWITCH2, + S_BLOODYTWITCH3, + S_BLOODYTWITCH4, + S_DEADTORSO, + S_DEADBOTTOM, + S_HEADSONSTICK, + S_GIBS, + S_HEADONASTICK, + S_HEADCANDLES, + S_HEADCANDLES2, + S_DEADSTICK, + S_LIVESTICK, + S_LIVESTICK2, + S_MEAT2, + S_MEAT3, + S_MEAT4, + S_MEAT5, + S_STALAGTITE, + S_TALLGRNCOL, + S_SHRTGRNCOL, + S_TALLREDCOL, + S_SHRTREDCOL, + S_CANDLESTIK, + S_CANDELABRA, + S_SKULLCOL, + S_TORCHTREE, + S_BIGTREE, + S_TECHPILLAR, + S_EVILEYE, + S_EVILEYE2, + S_EVILEYE3, + S_EVILEYE4, + S_FLOATSKULL, + S_FLOATSKULL2, + S_FLOATSKULL3, + S_HEARTCOL, + S_HEARTCOL2, + S_BLUETORCH, + S_BLUETORCH2, + S_BLUETORCH3, + S_BLUETORCH4, + S_GREENTORCH, + S_GREENTORCH2, + S_GREENTORCH3, + S_GREENTORCH4, + S_REDTORCH, + S_REDTORCH2, + S_REDTORCH3, + S_REDTORCH4, + S_BTORCHSHRT, + S_BTORCHSHRT2, + S_BTORCHSHRT3, + S_BTORCHSHRT4, + S_GTORCHSHRT, + S_GTORCHSHRT2, + S_GTORCHSHRT3, + S_GTORCHSHRT4, + S_RTORCHSHRT, + S_RTORCHSHRT2, + S_RTORCHSHRT3, + S_RTORCHSHRT4, + S_HANGNOGUTS, + S_HANGBNOBRAIN, + S_HANGTLOOKDN, + S_HANGTSKULL, + S_HANGTLOOKUP, + S_HANGTNOBRAIN, + S_COLONGIBS, + S_SMALLPOOL, + S_BRAINSTEM, + S_TECHLAMP, + S_TECHLAMP2, + S_TECHLAMP3, + S_TECHLAMP4, + S_TECH2LAMP, + S_TECH2LAMP2, + S_TECH2LAMP3, + S_TECH2LAMP4, + NUMSTATES } statenum_t; +/* Tightly packed to save space! */ -typedef struct +begin_packed_struct struct state_t { - spritenum_t sprite; - int frame; - int tics; - // void (*action) (); - actionf_t action; - statenum_t nextstate; - int misc1; - int misc2; -} state_t; + actionf_t action; /* void (*action) (); */ + spritenum_t sprite; + statenum_t nextstate; -extern state_t states[NUMSTATES]; -extern const char *sprnames[]; + int32_t tics; /* -1 to 181 */ + + uint16_t frame; /* 0 to 32796 */ + + /* NOTE: as far as I can tell, these fields are never used. They are set to + * zero in the state lookup table, and the only other place directly + * referencing them is P_SetPsprite, which uses them seemingly as a fixed + * point number to set some other coordinates later. However, in my + * gameplay, the check for `if (state->misc1)` never evaluates to true. + * Therefore, in my quest to save memory in one of the games largest lookup + * tables, I am removing these fields. + */ + +#if 0 + int misc1; + int misc2; +#endif +} end_packed_struct; -typedef enum { - MT_PLAYER, - MT_POSSESSED, - MT_SHOTGUY, - MT_VILE, - MT_FIRE, - MT_UNDEAD, - MT_TRACER, - MT_SMOKE, - MT_FATSO, - MT_FATSHOT, - MT_CHAINGUY, - MT_TROOP, - MT_SERGEANT, - MT_SHADOWS, - MT_HEAD, - MT_BRUISER, - MT_BRUISERSHOT, - MT_KNIGHT, - MT_SKULL, - MT_SPIDER, - MT_BABY, - MT_CYBORG, - MT_PAIN, - MT_WOLFSS, - MT_KEEN, - MT_BOSSBRAIN, - MT_BOSSSPIT, - MT_BOSSTARGET, - MT_SPAWNSHOT, - MT_SPAWNFIRE, - MT_BARREL, - MT_TROOPSHOT, - MT_HEADSHOT, - MT_ROCKET, - MT_PLASMA, - MT_BFG, - MT_ARACHPLAZ, - MT_PUFF, - MT_BLOOD, - MT_TFOG, - MT_IFOG, - MT_TELEPORTMAN, - MT_EXTRABFG, - MT_MISC0, - MT_MISC1, - MT_MISC2, - MT_MISC3, - MT_MISC4, - MT_MISC5, - MT_MISC6, - MT_MISC7, - MT_MISC8, - MT_MISC9, - MT_MISC10, - MT_MISC11, - MT_MISC12, - MT_INV, - MT_MISC13, - MT_INS, - MT_MISC14, - MT_MISC15, - MT_MISC16, - MT_MEGA, - MT_CLIP, - MT_MISC17, - MT_MISC18, - MT_MISC19, - MT_MISC20, - MT_MISC21, - MT_MISC22, - MT_MISC23, - MT_MISC24, - MT_MISC25, - MT_CHAINGUN, - MT_MISC26, - MT_MISC27, - MT_MISC28, - MT_SHOTGUN, - MT_SUPERSHOTGUN, - MT_MISC29, - MT_MISC30, - MT_MISC31, - MT_MISC32, - MT_MISC33, - MT_MISC34, - MT_MISC35, - MT_MISC36, - MT_MISC37, - MT_MISC38, - MT_MISC39, - MT_MISC40, - MT_MISC41, - MT_MISC42, - MT_MISC43, - MT_MISC44, - MT_MISC45, - MT_MISC46, - MT_MISC47, - MT_MISC48, - MT_MISC49, - MT_MISC50, - MT_MISC51, - MT_MISC52, - MT_MISC53, - MT_MISC54, - MT_MISC55, - MT_MISC56, - MT_MISC57, - MT_MISC58, - MT_MISC59, - MT_MISC60, - MT_MISC61, - MT_MISC62, - MT_MISC63, - MT_MISC64, - MT_MISC65, - MT_MISC66, - MT_MISC67, - MT_MISC68, - MT_MISC69, - MT_MISC70, - MT_MISC71, - MT_MISC72, - MT_MISC73, - MT_MISC74, - MT_MISC75, - MT_MISC76, - MT_MISC77, - MT_MISC78, - MT_MISC79, - MT_MISC80, - MT_MISC81, - MT_MISC82, - MT_MISC83, - MT_MISC84, - MT_MISC85, - MT_MISC86, - NUMMOBJTYPES +typedef struct state_t state_t; +typedef enum +{ + MT_PLAYER, + MT_POSSESSED, + MT_SHOTGUY, + MT_VILE, + MT_FIRE, + MT_UNDEAD, + MT_TRACER, + MT_SMOKE, + MT_FATSO, + MT_FATSHOT, + MT_CHAINGUY, + MT_TROOP, + MT_SERGEANT, + MT_SHADOWS, + MT_HEAD, + MT_BRUISER, + MT_BRUISERSHOT, + MT_KNIGHT, + MT_SKULL, + MT_SPIDER, + MT_BABY, + MT_CYBORG, + MT_PAIN, + MT_WOLFSS, + MT_KEEN, + MT_BOSSBRAIN, + MT_BOSSSPIT, + MT_BOSSTARGET, + MT_SPAWNSHOT, + MT_SPAWNFIRE, + MT_BARREL, + MT_TROOPSHOT, + MT_HEADSHOT, + MT_ROCKET, + MT_PLASMA, + MT_BFG, + MT_ARACHPLAZ, + MT_PUFF, + MT_BLOOD, + MT_TFOG, + MT_IFOG, + MT_TELEPORTMAN, + MT_EXTRABFG, + MT_MISC0, + MT_MISC1, + MT_MISC2, + MT_MISC3, + MT_MISC4, + MT_MISC5, + MT_MISC6, + MT_MISC7, + MT_MISC8, + MT_MISC9, + MT_MISC10, + MT_MISC11, + MT_MISC12, + MT_INV, + MT_MISC13, + MT_INS, + MT_MISC14, + MT_MISC15, + MT_MISC16, + MT_MEGA, + MT_CLIP, + MT_MISC17, + MT_MISC18, + MT_MISC19, + MT_MISC20, + MT_MISC21, + MT_MISC22, + MT_MISC23, + MT_MISC24, + MT_MISC25, + MT_CHAINGUN, + MT_MISC26, + MT_MISC27, + MT_MISC28, + MT_SHOTGUN, + MT_SUPERSHOTGUN, + MT_MISC29, + MT_MISC30, + MT_MISC31, + MT_MISC32, + MT_MISC33, + MT_MISC34, + MT_MISC35, + MT_MISC36, + MT_MISC37, + MT_MISC38, + MT_MISC39, + MT_MISC40, + MT_MISC41, + MT_MISC42, + MT_MISC43, + MT_MISC44, + MT_MISC45, + MT_MISC46, + MT_MISC47, + MT_MISC48, + MT_MISC49, + MT_MISC50, + MT_MISC51, + MT_MISC52, + MT_MISC53, + MT_MISC54, + MT_MISC55, + MT_MISC56, + MT_MISC57, + MT_MISC58, + MT_MISC59, + MT_MISC60, + MT_MISC61, + MT_MISC62, + MT_MISC63, + MT_MISC64, + MT_MISC65, + MT_MISC66, + MT_MISC67, + MT_MISC68, + MT_MISC69, + MT_MISC70, + MT_MISC71, + MT_MISC72, + MT_MISC73, + MT_MISC74, + MT_MISC75, + MT_MISC76, + MT_MISC77, + MT_MISC78, + MT_MISC79, + MT_MISC80, + MT_MISC81, + MT_MISC82, + MT_MISC83, + MT_MISC84, + MT_MISC85, + MT_MISC86, + NUMMOBJTYPES } mobjtype_t; -typedef struct +/* Ranges for these members were obtained by analyzing the `mobjinfo` + * array at game startup. + */ + +begin_packed_struct struct mobjinfo_t { - int doomednum; - int spawnstate; - int spawnhealth; - int seestate; - int seesound; - int reactiontime; - int attacksound; - int painstate; - int painchance; - int painsound; - int meleestate; - int missilestate; - int deathstate; - int xdeathstate; - int deathsound; - int speed; - int radius; - int height; - int mass; - int damage; - int activesound; - int flags; - int raisestate; + uint32_t flags; /* 0 to 33557510 */ + uint32_t radius; /* 393216 to 8388608 */ + uint32_t height; /* 524288 to 7208960 */ + uint32_t mass; /* 50 to 10000000 */ + uint32_t speed; /* 0 to 1638400 */ + int16_t doomednum; /* -1 to 3006 */ + uint16_t spawnhealth; /* 20 to 4000 */ + uint16_t spawnstate; /* 0 to 963 */ + uint16_t seestate; /* 0 to 785 */ + uint16_t painstate; /* 0 to 779 */ + uint16_t painchance; /* 0 to 256 */ + uint16_t meleestate; /* 0 to 566 */ + uint16_t missilestate; /* 0 to 736 */ + uint16_t deathstate; /* 0 to 808 */ + uint16_t xdeathstate; /* 0 to 749 */ + uint16_t raisestate; /* 0 to 758 */ + uint8_t damage; /* 0 to 100 */ + uint8_t reactiontime; /* 0 to 8 */ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + uint8_t seesound; /* 0 to 107 */ + uint8_t attacksound; /* 0 to 52 */ + uint8_t painsound; /* 0 to 103 */ + uint8_t deathsound; /* 0 to 104 */ + uint8_t activesound; /* 0 to 105 */ +#endif +} end_packed_struct; + +typedef struct mobjinfo_t mobjinfo_t; -} mobjinfo_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern state_t states[NUMSTATES]; +extern const char *sprnames[]; + +/* Size before opt: 0000000000012604 + * Size after opt with sound: 0000000000007124 + * Size after opt without sound: 0000000000006028 + * + * Best improvement: 6576 bytes + * Best improvement: 6.42KB + */ extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; -#endif +#endif /* __INFO__ */ diff --git a/games/NXDoom/src/doom/m_menu.c b/games/NXDoom/src/doom/m_menu.c index 71b47cbf6e2..55dd9589f19 100644 --- a/games/NXDoom/src/doom/m_menu.c +++ b/games/NXDoom/src/doom/m_menu.c @@ -1,26 +1,33 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM selection menu, options, episode etc. -// Sliders and icons. Kinda widget stuff. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/m_menu.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * DOOM selection menu, options, episode etc. + * Sliders and icons. Kinda widget stuff. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include #include - +#include #include "doomdef.h" #include "doomkeys.h" @@ -42,7 +49,6 @@ #include "r_local.h" - #include "hu_stuff.h" #include "g_game.h" @@ -52,2077 +58,2097 @@ #include "p_saveg.h" #include "p_setup.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "doomstat.h" -// Data. -#include "sounds.h" +/* Data. */ #include "m_menu.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// -// defaulted values -// -int mouseSensitivity = 5; +#define SKULLXOFF -32 +#define LINEHEIGHT 16 -// Show messages has default, 0 = off, 1 = on -int showMessages = 1; - +#define JOY_BUTTON_MAPPED(x) ((x) >= 0) +#define JOY_BUTTON_PRESSED(x) \ + (JOY_BUTTON_MAPPED(x) && (ev->data1 & (1 << (x))) != 0) -// Blocky mode, has default, 0 = high, 1 = normal -int detailLevel = 0; -int screenblocks = 9; +/**************************************************************************** + * Private Types + ****************************************************************************/ -// temp for screenblocks (0-9) -int screenSize; +void (*message_routine)(int response); -// -1 = no quicksave slot picked! -int quickSaveSlot; +/* MENU TYPEDEFS */ - // 1 = message to be printed -int messageToPrint; -// ...and here is the message string! -const char *messageString; +typedef struct +{ + /* 0 = no cursor here, 1 = ok, 2 = arrows ok */ -// message x & y -int messx; -int messy; -int messageLastMenuActive; + short status; -// timed message = no input from user -boolean messageNeedsInput; + char name[10]; -void (*messageRoutine)(int response); + /* choice = menu item #. + * if status = 2, + * choice=0:leftarrow,1:rightarrow + */ -char gammamsg[5][26] = -{ - GAMMALVL0, - GAMMALVL1, - GAMMALVL2, - GAMMALVL3, - GAMMALVL4 -}; + void (*routine)(int choice); -// we are going to be entering a savegame string -int saveStringEnter; -int saveSlot; // which slot to save in -int saveCharIndex; // which char we're editing -static boolean joypadSave = false; // was the save action initiated by joypad? -// old save description before edit -char saveOldString[SAVESTRINGSIZE]; + /* hotkey in menu */ -boolean inhelpscreens; -boolean menuactive; + char alpha_key; +} menuitem_t; -#define SKULLXOFF -32 -#define LINEHEIGHT 16 +typedef struct menu_s +{ + short numitems; /* # of menu items */ + struct menu_s *prev_menu; /* previous menu */ + menuitem_t *menu_items; /* menu items */ + void (*routine)(void); /* draw routine */ + short x; + short y; /* x,y of menu */ + short last_on; /* last item user was on in menu */ +} menu_t; -char savegamestrings[10][SAVESTRINGSIZE]; +/* DOOM MENU */ -char endstring[160]; +enum +{ + MAIN_NEWGAME = 0, + MAIN_OPTIONS, + MAIN_LOADGAME, + MAIN_SAVEGAME, + MAIN_READTHIS, + MAIN_QUITDOOM, + MAIN_END +} main_e; -static boolean opldev; +/* EPISODE SELECT */ -// -// MENU TYPEDEFS -// -typedef struct +enum { - // 0 = no cursor here, 1 = ok, 2 = arrows ok - short status; - - char name[10]; - - // choice = menu item #. - // if status = 2, - // choice=0:leftarrow,1:rightarrow - void (*routine)(int choice); - - // hotkey in menu - char alphaKey; -} menuitem_t; + EPISODE_EP1, + EPISODE_EP2, + EPISODE_EP3, + EPISODE_EP4, + EPISODE_END +} episodes_e; + +/* NEW GAME */ +enum +{ + NEWGAME_KILLTHINGS, + NEWGAME_TOOROUGH, + NEWGAME_HURTME, + NEWGAME_VIOLANCE, + NEWGAME_NIGHTMARE, + NEWGAME_END +} newgame_e; +/* OPTIONS MENU */ -typedef struct menu_s +enum { - short numitems; // # of menu items - struct menu_s* prevMenu; // previous menu - menuitem_t* menuitems; // menu items - void (*routine)(); // draw routine - short x; - short y; // x,y of menu - short lastOn; // last item user was on in menu -} menu_t; + OPT_ENDGAME, + OPT_MESSAGES, + OPT_DETAIL, + OPT_SCRNSIZE, + OPT_EMPTY1, + OPT_MOUSESENS, + OPT_EMPTY2, + OPT_SOUNDVOL, + OPT_END +} options_e; -short itemOn; // menu item skull is on -short skullAnimCounter; // skull animation counter -short whichSkull; // which skull to draw - -// graphic name of skulls -// warning: initializer-string for array of chars is too long -const char *skullName[2] = {"M_SKULL1","M_SKULL2"}; - -// current menudef -menu_t* currentMenu; - -// -// PROTOTYPES -// -static void M_NewGame(int choice); -static void M_Episode(int choice); -static void M_ChooseSkill(int choice); -static void M_LoadGame(int choice); -static void M_SaveGame(int choice); -static void M_Options(int choice); -static void M_EndGame(int choice); -static void M_ReadThis(int choice); -static void M_ReadThis2(int choice); -static void M_QuitDOOM(int choice); - -static void M_ChangeMessages(int choice); -static void M_ChangeSensitivity(int choice); -static void M_SfxVol(int choice); -static void M_MusicVol(int choice); -static void M_ChangeDetail(int choice); -static void M_SizeDisplay(int choice); -static void M_Sound(int choice); - -static void M_FinishReadThis(int choice); -static void M_LoadSelect(int choice); -static void M_SaveSelect(int choice); -static void M_ReadSaveStrings(void); -static void M_QuickSave(void); -static void M_QuickLoad(void); - -static void M_DrawMainMenu(void); -static void M_DrawReadThis1(void); -static void M_DrawReadThis2(void); -static void M_DrawNewGame(void); -static void M_DrawEpisode(void); -static void M_DrawOptions(void); -static void M_DrawSound(void); -static void M_DrawLoad(void); -static void M_DrawSave(void); - -static void M_DrawSaveLoadBorder(int x,int y); -static void M_SetupNextMenu(menu_t *menudef); -static void M_DrawThermo(int x,int y,int thermWidth,int thermDot); -static void M_WriteText(int x, int y, const char *string); -static int M_StringWidth(const char *string); -static int M_StringHeight(const char *string); -static void M_StartMessage(const char *string, void *routine, boolean input); -static void M_ClearMenus (void); - - - - -// -// DOOM MENU -// enum { - newgame = 0, - options, - loadgame, - savegame, - readthis, - quitdoom, - main_end -} main_e; + RDTHSEMPTY1, + READ1_END +} read_e; -menuitem_t MainMenu[]= +enum { - {1,"M_NGAME",M_NewGame,'n'}, - {1,"M_OPTION",M_Options,'o'}, - {1,"M_LOADG",M_LoadGame,'l'}, - {1,"M_SAVEG",M_SaveGame,'s'}, - // Another hickup with Special edition. - {1,"M_RDTHIS",M_ReadThis,'r'}, - {1,"M_QUITG",M_QuitDOOM,'q'} -}; + RDTHSEMPTY2, + READ2_END +} read_e2; -menu_t MainDef = +/* SOUND VOLUME MENU */ + +enum { - main_end, - NULL, - MainMenu, - M_DrawMainMenu, - 97,64, - 0 -}; + SOUND_SFXVOL, + SOUND_SFXEMPTY1, + SOUND_MUSICVOL, + SOUND_SFXEMPTY2, + SOUND_END +} sound_e; +/* LOAD GAME MENU */ -// -// EPISODE SELECT -// enum { - ep1, - ep2, - ep3, - ep4, - ep_end -} episodes_e; + LOAD_1, + LOAD_2, + LOAD_3, + LOAD_4, + LOAD_5, + LOAD_6, + LOAD_END +} load_e; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void m_new_game(int choice); +static void m_episode(int choice); +static void m_choose_skill(int choice); +static void m_load_game(int choice); +static void m_save_game(int choice); +static void m_options(int choice); +static void m_end_game(int choice); +static void m_read_this(int choice); +static void m_read_this2(int choice); +static void m_quit_doom(int choice); + +static void m_change_messages(int choice); +static void m_change_sensitivity(int choice); +static void m_sfx_vol(int choice); +static void m_music_vol(int choice); +static void m_change_detail(int choice); +static void m_size_display(int choice); +static void m_sound(int choice); + +static void m_finish_read_this(int choice); +static void m_load_select(int choice); +static void m_save_select(int choice); +static void m_read_save_strings(void); +static void m_quick_save(void); +static void m_quick_load(void); + +static void m_drawmain_menu(void); +static void m_draw_read_this1(void); +static void m_draw_read_this2(void); +static void m_draw_new_game(void); +static void m_draw_episode(void); +static void m_draw_options(void); +static void m_draw_sound(void); +static void m_draw_load(void); +static void m_draw_save(void); + +static void m_draw_save_load_border(int x, int y); +static void m_setup_next_menu(menu_t *menudef); +static void m_draw_thermo(int x, int y, int therm_width, int therm_dot); +static void m_write_text(int x, int y, const char *string); +static int m_string_width(const char *string); +static int m_string_height(const char *string); +static void m_start_message(const char *string, + void *routine, boolean input); +static void m_clear_menus(void); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* defaulted values */ + +int g_mouse_sensitivity = 5; + +/* Show messages has default, 0 = off, 1 = on */ + +int g_show_messages = 1; + +/* Blocky mode, has default, 0 = high, 1 = normal */ + +int g_detail_level = 0; +int screenblocks = 9; + +boolean g_menuactive; +boolean inhelpscreens; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* message x & y */ + +static int g_messx; +static int g_messy; +static int g_message_last_menu_active; + +/* timed message = no input from user */ + +static boolean g_message_needs_input; + +static char g_gammamsg[5][26] = +{ + GAMMALVL0, GAMMALVL1, GAMMALVL2, GAMMALVL3, GAMMALVL4, +}; + +/* we are going to be entering a savegame string */ + +static int g_save_string_enter; +static int g_save_slot; /* which slot to save in */ +static int g_save_char_index; /* which char we're editing */ + +/* old save description before edit */ + +static char g_save_old_string[SAVESTRINGSIZE]; -menuitem_t EpisodeMenu[]= +static char g_save_game_strings[10][SAVESTRINGSIZE]; + +static char g_endstring[160]; + +static short g_item_on; /* menu item skull is on */ +static short g_skull_anim_counter; /* skull animation counter */ +static short g_which_skull; /* which skull to draw */ + +/* temp for screenblocks (0-9) */ + +static int g_screen_size; + +/* -1 = no quicksave slot picked! */ + +static int g_quick_save_slot; + +/* 1 = message to be printed */ + +static int g_message_to_print; + +/* ...and here is the message string! */ + +static const char *g_message_string; + +static int g_epi; + +/* graphic name of skulls + * warning: initializer-string for array of chars is too long + */ + +static const char *g_skull_name[2] = { - {1,"M_EPI1", M_Episode,'k'}, - {1,"M_EPI2", M_Episode,'t'}, - {1,"M_EPI3", M_Episode,'i'}, - {1,"M_EPI4", M_Episode,'t'} + "M_SKULL1", + "M_SKULL2", }; -menu_t EpiDef = +#ifdef CONFIG_GAMES_NXDOOM_SOUND +static int g_quitsounds[8] = { - ep_end, // # of menu items - &MainDef, // previous menu - EpisodeMenu, // menuitem_t -> - M_DrawEpisode, // drawing routine -> - 48,63, // x,y - ep1 // lastOn + SFX_PLDETH, SFX_DMPAIN, SFX_POPAIN, SFX_SLOP, + SFX_TELEPT, SFX_POSIT1, SFX_POSIT3, SFX_SGTATK, }; -// -// NEW GAME -// -enum +static int g_quitsounds2[8] = { - killthings, - toorough, - hurtme, - violence, - nightmare, - newg_end -} newgame_e; + SFX_VILACT, SFX_GETPOW, SFX_BOSCUB, SFX_SLOP, + SFX_SKESWG, SFX_KNTDTH, SFX_BSPACT, SFX_SGTATK, +}; +#endif + +/* was the save action initiated by joypad? */ + +static boolean g_joypad_save = false; -menuitem_t NewGameMenu[]= +static char g_tempstring[90]; + +static const char *g_detail_names[2] = { - {1,"M_JKILL", M_ChooseSkill, 'i'}, - {1,"M_ROUGH", M_ChooseSkill, 'h'}, - {1,"M_HURT", M_ChooseSkill, 'h'}, - {1,"M_ULTRA", M_ChooseSkill, 'u'}, - {1,"M_NMARE", M_ChooseSkill, 'n'} + "M_GDHIGH", + "M_GDLOW", }; -menu_t NewDef = +static const char *g_msg_names[2] = { - newg_end, // # of menu items - &EpiDef, // previous menu - NewGameMenu, // menuitem_t -> - M_DrawNewGame, // drawing routine -> - 48,63, // x,y - hurtme // lastOn + "M_MSGOFF", + "M_MSGON", }; +/* current menudef */ +static menu_t *g_current_menu; -// -// OPTIONS MENU -// -enum +static menuitem_t g_main_menu[] = { - endgame, - messages, - detail, - scrnsize, - option_empty1, - mousesens, - option_empty2, - soundvol, - opt_end -} options_e; + {1, "M_NGAME", m_new_game, 'n'}, + {1, "M_OPTION", m_options, 'o'}, + {1, "M_LOADG", m_load_game, 'l'}, + {1, "M_SAVEG", m_save_game, 's'}, + {1, "M_RDTHIS", m_read_this, 'r'}, /* Another hiccup with Special edition. */ + {1, "M_QUITG", m_quit_doom, 'q'}, +}; -menuitem_t OptionsMenu[]= +static menu_t g_main_def = { - {1,"M_ENDGAM", M_EndGame,'e'}, - {1,"M_MESSG", M_ChangeMessages,'m'}, - {1,"M_DETAIL", M_ChangeDetail,'g'}, - {2,"M_SCRNSZ", M_SizeDisplay,'s'}, - {-1,"",0,'\0'}, - {2,"M_MSENS", M_ChangeSensitivity,'m'}, - {-1,"",0,'\0'}, - {1,"M_SVOL", M_Sound,'s'} + MAIN_END, NULL, g_main_menu, m_drawmain_menu, 97, 64, 0, }; -menu_t OptionsDef = +static menuitem_t g_episode_menu[] = { - opt_end, - &MainDef, - OptionsMenu, - M_DrawOptions, - 60,37, - 0 + {1, "M_EPI1", m_episode, 'k'}, + {1, "M_EPI2", m_episode, 't'}, + {1, "M_EPI3", m_episode, 'i'}, + {1, "M_EPI4", m_episode, 't'}, }; -// -// Read This! MENU 1 & 2 -// -enum +static menu_t g_epi_def = { - rdthsempty1, - read1_end -} read_e; + EPISODE_END, /* # of menu items */ + &g_main_def, /* previous menu */ + g_episode_menu, /* menuitem_t -> */ + m_draw_episode, /* drawing routine -> */ + 48, + 63, /* x,y */ + EPISODE_EP1 /* lastOn */ +}; -menuitem_t ReadMenu1[] = +static menuitem_t new_game_menu[] = { - {1,"",M_ReadThis2,0} + {1, "M_JKILL", m_choose_skill, 'i'}, + {1, "M_ROUGH", m_choose_skill, 'h'}, + {1, "M_HURT", m_choose_skill, 'h'}, + {1, "M_ULTRA", m_choose_skill, 'u'}, + {1, "M_NMARE", m_choose_skill, 'n'}, }; -menu_t ReadDef1 = +static menu_t g_new_def = { - read1_end, - &MainDef, - ReadMenu1, - M_DrawReadThis1, - 280,185, - 0 + NEWGAME_END, /* # of menu items */ + &g_epi_def, /* previous menu */ + new_game_menu, /* menuitem_t -> */ + m_draw_new_game, /* drawing routine -> */ + 48, + 63, /* x,y */ + NEWGAME_HURTME /* lastOn */ }; -enum +static menuitem_t g_options_menu[] = { - rdthsempty2, - read2_end -} read_e2; + { + 1, + "M_ENDGAM", + m_end_game, + 'e', + }, + { + 1, + "M_MESSG", + m_change_messages, + 'm', + }, + { + 1, + "M_DETAIL", + m_change_detail, + 'g', + }, + { + 2, + "M_SCRNSZ", + m_size_display, + 's', + }, + { + -1, + "", + 0, + '\0', + }, + { + 2, + "M_MSENS", + m_change_sensitivity, + 'm', + }, + { + -1, + "", + 0, + '\0', + }, + { + 1, + "M_SVOL", + m_sound, + 's', + }, +}; -menuitem_t ReadMenu2[]= +static menu_t g_options_def = { - {1,"",M_FinishReadThis,0} + OPT_END, &g_main_def, g_options_menu, m_draw_options, 60, 37, 0, }; -menu_t ReadDef2 = +/* Read This! MENU 1 & 2 */ + +static menuitem_t g_read_menu1[] = { - read2_end, - &ReadDef1, - ReadMenu2, - M_DrawReadThis2, - 330,175, - 0 + {1, "", m_read_this2, 0}, }; -// -// SOUND VOLUME MENU -// -enum +static menu_t g_read_def1 = { - sfx_vol, - sfx_empty1, - music_vol, - sfx_empty2, - sound_end -} sound_e; + READ1_END, &g_main_def, g_read_menu1, m_draw_read_this1, 280, 185, 0, +}; -menuitem_t SoundMenu[]= +static menuitem_t g_read_menu2[] = { - {2,"M_SFXVOL",M_SfxVol,'s'}, - {-1,"",0,'\0'}, - {2,"M_MUSVOL",M_MusicVol,'m'}, - {-1,"",0,'\0'} + {1, "", m_finish_read_this, 0}, }; -menu_t SoundDef = +static menu_t g_read_def2 = { - sound_end, - &OptionsDef, - SoundMenu, - M_DrawSound, - 80,64, - 0 + READ2_END, &g_read_def1, g_read_menu2, m_draw_read_this2, 330, 175, 0, }; -// -// LOAD GAME MENU -// -enum +#ifdef CONFIG_GAMES_NXDOOM_SOUND +static menuitem_t g_sound_menu[] = { - load1, - load2, - load3, - load4, - load5, - load6, - load_end -} load_e; + { + 2, + "M_SFXVOL", + m_sfx_vol, + 's', + }, + { + -1, + "", + 0, + '\0', + }, + { + 2, + "M_MUSVOL", + m_music_vol, + 'm', + }, + { + -1, + "", + 0, + '\0', + }, +}; -menuitem_t LoadMenu[]= +static menu_t g_sound_def = { - {1,"", M_LoadSelect,'1'}, - {1,"", M_LoadSelect,'2'}, - {1,"", M_LoadSelect,'3'}, - {1,"", M_LoadSelect,'4'}, - {1,"", M_LoadSelect,'5'}, - {1,"", M_LoadSelect,'6'} + SOUND_END, &g_options_def, g_sound_menu, m_draw_sound, 80, 64, 0, }; +#endif -menu_t LoadDef = +static menuitem_t g_load_menu[] = { - load_end, - &MainDef, - LoadMenu, - M_DrawLoad, - 80,54, - 0 + {1, "", m_load_select, '1'}, + {1, "", m_load_select, '2'}, + {1, "", m_load_select, '3'}, + {1, "", m_load_select, '4'}, + {1, "", m_load_select, '5'}, + {1, "", m_load_select, '6'}, }; -// -// SAVE GAME MENU -// -menuitem_t SaveMenu[]= -{ - {1,"", M_SaveSelect,'1'}, - {1,"", M_SaveSelect,'2'}, - {1,"", M_SaveSelect,'3'}, - {1,"", M_SaveSelect,'4'}, - {1,"", M_SaveSelect,'5'}, - {1,"", M_SaveSelect,'6'} +static menu_t g_load_def = +{ + LOAD_END, &g_main_def, g_load_menu, m_draw_load, 80, 54, 0, }; -menu_t SaveDef = +/* SAVE GAME MENU */ + +static menuitem_t g_save_menu[] = +{ + {1, "", m_save_select, '1'}, + {1, "", m_save_select, '2'}, + {1, "", m_save_select, '3'}, + {1, "", m_save_select, '4'}, + {1, "", m_save_select, '5'}, + {1, "", m_save_select, '6'}, +}; + +static menu_t g_save_def = { - load_end, - &MainDef, - SaveMenu, - M_DrawSave, - 80,54, - 0 + LOAD_END, &g_main_def, g_save_menu, m_draw_save, 80, 54, 0, }; +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Generate a default save slot name when the user saves to + * an empty slot via the joypad. + */ -// -// M_ReadSaveStrings -// read the strings from the savegame files -// -void M_ReadSaveStrings(void) +static void set_default_save_name(int slot) { - FILE *handle; - int i; - char name[256]; + /* map from IWAD or PWAD? */ - for (i = 0;i < load_end;i++) + if (w_is_iwad_lump(maplumpinfo) && strcmp(savegamedir, "")) + { + snprintf(g_save_game_strings[g_item_on], SAVESTRINGSIZE, "%s", + maplumpinfo->name); + } + else { - int retval; - M_StringCopy(name, P_SaveGameFile(i), sizeof(name)); + char *wadname = m_string_duplicate(w_wad_name_for_lump(maplumpinfo)); + char *ext = strrchr(wadname, '.'); - handle = M_fopen(name, "rb"); - if (handle == NULL) + if (ext != NULL) { - M_StringCopy(savegamestrings[i], EMPTYSTRING, SAVESTRINGSIZE); - LoadMenu[i].status = 0; - continue; + *ext = '\0'; } - retval = fread(&savegamestrings[i], 1, SAVESTRINGSIZE, handle); - fclose(handle); - LoadMenu[i].status = retval == SAVESTRINGSIZE; + + snprintf(g_save_game_strings[g_item_on], SAVESTRINGSIZE, "%s (%s)", + maplumpinfo->name, wadname); + free(wadname); } + + m_force_uppercase(g_save_game_strings[g_item_on]); + g_joypad_save = false; } +/* m_responder calls this when user is finished */ -// -// M_LoadGame & Cie. -// -void M_DrawLoad(void) +static void m_do_save(int slot) { - int i; - - V_DrawPatchDirect(72, 28, - W_CacheLumpName(DEH_String("M_LOADG"), PU_CACHE)); + g_save_game(slot, g_save_game_strings[slot]); + m_clear_menus(); + + /* PICK QUICKSAVE SLOT YET? */ + + if (g_quick_save_slot == -2) g_quick_save_slot = slot; +} - for (i = 0;i < load_end; i++) +static void m_quick_save_response(int key) +{ + if (key == key_menu_confirm) { - M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); - M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + m_do_save(g_quick_save_slot); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHX); +#endif } } - - -// -// Draw border for the savegame description -// -void M_DrawSaveLoadBorder(int x,int y) +static void m_quick_load_response(int key) { - int i; - - V_DrawPatchDirect(x - 8, y + 7, - W_CacheLumpName(DEH_String("M_LSLEFT"), PU_CACHE)); - - for (i = 0;i < 24;i++) + if (key == key_menu_confirm) { - V_DrawPatchDirect(x, y + 7, - W_CacheLumpName(DEH_String("M_LSCNTR"), PU_CACHE)); - x += 8; + m_load_select(g_quick_save_slot); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHX); +#endif } - - V_DrawPatchDirect(x, y + 7, - W_CacheLumpName(DEH_String("M_LSRGHT"), PU_CACHE)); } +/* These keys evaluate to a "null" key in Vanilla Doom that allows weird + * jumping in the menus. Preserve this behavior for accuracy. + */ - -// -// User wants to load this game -// -void M_LoadSelect(int choice) +static boolean is_null_key(int key) { - char name[256]; - - M_StringCopy(name, P_SaveGameFile(choice), sizeof(name)); - - G_LoadGame (name); - M_ClearMenus (); + return key == KEY_PAUSE || key == KEY_CAPSLOCK || key == KEY_SCRLCK || + key == KEY_NUMLOCK; } -// -// Selected from DOOM menu -// -void M_LoadGame (int choice) +static void m_start_message(const char *string, void *routine, boolean input) { - if (netgame) - { - M_StartMessage(DEH_String(LOADNET),NULL,false); - return; - } - - M_SetupNextMenu(&LoadDef); - M_ReadSaveStrings(); + g_message_last_menu_active = g_menuactive; + g_message_to_print = 1; + g_message_string = string; + message_routine = routine; + g_message_needs_input = input; + g_menuactive = true; + return; } - -// -// M_SaveGame & Cie. -// -void M_DrawSave(void) +static const char *m_select_end_message(void) { - int i; - - V_DrawPatchDirect(72, 28, W_CacheLumpName(DEH_String("M_SAVEG"), PU_CACHE)); - for (i = 0;i < load_end; i++) + const char **endmsg; + + if (logical_gamemission == doom) { - M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); - M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); + /* Doom 1 */ + + endmsg = doom1_endmsg; } - - if (saveStringEnter) + else { - i = M_StringWidth(savegamestrings[saveSlot]); - M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*saveSlot,"_"); + /* Doom 2 */ + + endmsg = doom2_endmsg; } + + return endmsg[gametic % NUM_QUITMESSAGES]; } -// -// M_Responder calls this when user is finished -// -void M_DoSave(int slot) +static void m_quit_response(int key) { - G_SaveGame (slot,savegamestrings[slot]); - M_ClearMenus (); + if (key != key_menu_confirm) return; + if (!netgame) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gamemode == commercial) + s_start_sound(NULL, g_quitsounds2[(gametic >> 2) & 7]); + else + s_start_sound(NULL, g_quitsounds[(gametic >> 2) & 7]); +#endif + i_wait_vbl(105); + } - // PICK QUICKSAVE SLOT YET? - if (quickSaveSlot == -2) - quickSaveSlot = slot; + i_quit(); } -// -// Generate a default save slot name when the user saves to -// an empty slot via the joypad. -// -static void SetDefaultSaveName(int slot) +static void m_end_game_response(int key) { - // map from IWAD or PWAD? - if (W_IsIWADLump(maplumpinfo) && strcmp(savegamedir, "")) - { - M_snprintf(savegamestrings[itemOn], SAVESTRINGSIZE, - "%s", maplumpinfo->name); - } - else - { - char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo)); - char *ext = strrchr(wadname, '.'); + if (key != key_menu_confirm) return; - if (ext != NULL) - { - *ext = '\0'; - } + g_current_menu->last_on = g_item_on; + m_clear_menus(); + d_start_title(); +} - M_snprintf(savegamestrings[itemOn], SAVESTRINGSIZE, - "%s (%s)", maplumpinfo->name, - wadname); - free(wadname); - } - M_ForceUppercase(savegamestrings[itemOn]); - joypadSave = false; +static void m_draw_read_this_commercial(void) +{ + inhelpscreens = true; + + v_draw_patch_direct(0, 0, w_cache_lump_name(("HELP"), PU_CACHE)); } -// -// User wants to save. Start string input for M_Responder -// -void M_SaveSelect(int choice) +static void m_verify_nightmare(int key) { - int x, y; + if (key != key_menu_confirm) return; - // we are going to be intercepting all chars - saveStringEnter = 1; + g_deferred_init_new(NEWGAME_NIGHTMARE, g_epi + 1, 1); + m_clear_menus(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* read the strings from the savegame files */ - // We need to turn on text input: - x = LoadDef.x - 11; - y = LoadDef.y + choice * LINEHEIGHT - 4; - I_StartTextInput(x, y, x + 8 + 24 * 8 + 8, y + LINEHEIGHT - 2); +void m_read_save_strings(void) +{ + FILE *handle; + int i; + char name[256]; - saveSlot = choice; - M_StringCopy(saveOldString,savegamestrings[choice], SAVESTRINGSIZE); - if (!strcmp(savegamestrings[choice], EMPTYSTRING)) + for (i = 0; i < LOAD_END; i++) { - savegamestrings[choice][0] = 0; + int retval; + m_str_copy(name, p_save_game_file(i), sizeof(name)); - if (joypadSave) + handle = fopen(name, "rb"); + if (handle == NULL) { - SetDefaultSaveName(choice); + m_str_copy(g_save_game_strings[i], EMPTYSTRING, SAVESTRINGSIZE); + g_load_menu[i].status = 0; + continue; } + + retval = fread(&g_save_game_strings[i], 1, SAVESTRINGSIZE, handle); + fclose(handle); + g_load_menu[i].status = retval == SAVESTRINGSIZE; } - saveCharIndex = strlen(savegamestrings[choice]); } -// -// Selected from DOOM menu -// -void M_SaveGame (int choice) +void m_draw_load(void) { - if (!usergame) + int i; + + v_draw_patch_direct(72, 28, w_cache_lump_name(("M_LOADG"), PU_CACHE)); + + for (i = 0; i < LOAD_END; i++) { - M_StartMessage(DEH_String(SAVEDEAD),NULL,false); - return; + m_draw_save_load_border(g_load_def.x, g_load_def.y + LINEHEIGHT * i); + m_write_text(g_load_def.x, g_load_def.y + LINEHEIGHT * i, + g_save_game_strings[i]); } - - if (gamestate != GS_LEVEL) - return; - - M_SetupNextMenu(&SaveDef); - M_ReadSaveStrings(); } +/* Draw border for the savegame description */ +void m_draw_save_load_border(int x, int y) +{ + int i; -// -// M_QuickSave -// -static char tempstring[90]; + v_draw_patch_direct(x - 8, y + 7, + w_cache_lump_name(("M_LSLEFT"), PU_CACHE)); -void M_QuickSaveResponse(int key) -{ - if (key == key_menu_confirm) + for (i = 0; i < 24; i++) { - M_DoSave(quickSaveSlot); - S_StartSound(NULL,sfx_swtchx); + v_draw_patch_direct(x, y + 7, + w_cache_lump_name(("M_LSCNTR"), PU_CACHE)); + x += 8; } + + v_draw_patch_direct(x, y + 7, w_cache_lump_name(("M_LSRGHT"), PU_CACHE)); } -void M_QuickSave(void) +/* User wants to load this game */ + +void m_load_select(int choice) { - if (!usergame) - { - S_StartSound(NULL,sfx_oof); - return; - } + char name[256]; - if (gamestate != GS_LEVEL) - return; - - if (quickSaveSlot < 0) - { - M_StartControlPanel(); - M_ReadSaveStrings(); - M_SetupNextMenu(&SaveDef); - quickSaveSlot = -2; // means to pick a slot now - return; - } - DEH_snprintf(tempstring, sizeof(tempstring), - QSPROMPT, savegamestrings[quickSaveSlot]); - M_StartMessage(tempstring, M_QuickSaveResponse, true); -} + m_str_copy(name, p_save_game_file(choice), sizeof(name)); + g_load_game(name); + m_clear_menus(); +} +/* Selected from DOOM menu */ -// -// M_QuickLoad -// -void M_QuickLoadResponse(int key) +void m_load_game(int choice) { - if (key == key_menu_confirm) + if (netgame) { - M_LoadSelect(quickSaveSlot); - S_StartSound(NULL,sfx_swtchx); + m_start_message((LOADNET), NULL, false); + return; } + + m_setup_next_menu(&g_load_def); + m_read_save_strings(); } +/* M_SaveGame & Cie. */ -void M_QuickLoad(void) +void m_draw_save(void) { - if (netgame) + int i; + + v_draw_patch_direct(72, 28, w_cache_lump_name(("M_SAVEG"), PU_CACHE)); + for (i = 0; i < LOAD_END; i++) { - M_StartMessage(DEH_String(QLOADNET),NULL,false); - return; + m_draw_save_load_border(g_load_def.x, g_load_def.y + LINEHEIGHT * i); + m_write_text(g_load_def.x, g_load_def.y + LINEHEIGHT * i, + g_save_game_strings[i]); } - - if (quickSaveSlot < 0) + + if (g_save_string_enter) { - M_StartMessage(DEH_String(QSAVESPOT),NULL,false); - return; + i = m_string_width(g_save_game_strings[g_save_slot]); + m_write_text(g_load_def.x + i, + g_load_def.y + LINEHEIGHT * g_save_slot, "_"); } - DEH_snprintf(tempstring, sizeof(tempstring), - QLPROMPT, savegamestrings[quickSaveSlot]); - M_StartMessage(tempstring, M_QuickLoadResponse, true); } +/* User wants to save. Start string input for m_responder */ - - -// -// Read This Menus -// Had a "quick hack to fix romero bug" -// -void M_DrawReadThis1(void) +void m_save_select(int choice) { - inhelpscreens = true; - - V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP2"), PU_CACHE)); -} + int x; + int y; + /* we are going to be intercepting all chars */ + g_save_string_enter = 1; -// -// Read This Menus - optional second page. -// -void M_DrawReadThis2(void) -{ - inhelpscreens = true; + /* We need to turn on text input: */ - // We only ever draw the second page if this is - // gameversion == exe_doom_1_9 and gamemode == registered + x = g_load_def.x - 11; + y = g_load_def.y + choice * LINEHEIGHT - 4; + i_start_text_input(x, y, x + 8 + 24 * 8 + 8, y + LINEHEIGHT - 2); - V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE)); -} + g_save_slot = choice; + m_str_copy(g_save_old_string, g_save_game_strings[choice], SAVESTRINGSIZE); + if (!strcmp(g_save_game_strings[choice], EMPTYSTRING)) + { + g_save_game_strings[choice][0] = 0; -void M_DrawReadThisCommercial(void) -{ - inhelpscreens = true; + if (g_joypad_save) + { + set_default_save_name(choice); + } + } - V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP"), PU_CACHE)); + g_save_char_index = strlen(g_save_game_strings[choice]); } +/* Selected from DOOM menu */ -// -// Change Sfx & Music volumes -// -void M_DrawSound(void) +void m_save_game(int choice) { - V_DrawPatchDirect (60, 38, W_CacheLumpName(DEH_String("M_SVOL"), PU_CACHE)); + if (!usergame) + { + m_start_message((SAVEDEAD), NULL, false); + return; + } - M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), - 16,sfxVolume); + if (gamestate != GS_LEVEL) return; - M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), - 16,musicVolume); + m_setup_next_menu(&g_save_def); + m_read_save_strings(); } -void M_Sound(int choice) +void m_quick_save(void) { - M_SetupNextMenu(&SoundDef); -} + if (!usergame) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return; + } -void M_SfxVol(int choice) -{ - switch(choice) + if (gamestate != GS_LEVEL) return; + + if (g_quick_save_slot < 0) { - case 0: - if (sfxVolume) - sfxVolume--; - break; - case 1: - if (sfxVolume < 15) - sfxVolume++; - break; + m_start_control_panel(); + m_read_save_strings(); + m_setup_next_menu(&g_save_def); + g_quick_save_slot = -2; /* means to pick a slot now */ + return; } - - S_SetSfxVolume(sfxVolume * 8); + + snprintf(g_tempstring, sizeof(g_tempstring), QSPROMPT, + g_save_game_strings[g_quick_save_slot]); + m_start_message(g_tempstring, m_quick_save_response, true); } -void M_MusicVol(int choice) +void m_quick_load(void) { - switch(choice) + if (netgame) { - case 0: - if (musicVolume) - musicVolume--; - break; - case 1: - if (musicVolume < 15) - musicVolume++; - break; + m_start_message((QLOADNET), NULL, false); + return; } - - S_SetMusicVolume(musicVolume * 8); -} + if (g_quick_save_slot < 0) + { + m_start_message((QSAVESPOT), NULL, false); + return; + } + snprintf(g_tempstring, sizeof(g_tempstring), QLPROMPT, + g_save_game_strings[g_quick_save_slot]); + m_start_message(g_tempstring, m_quick_load_response, true); +} +/* Read This Menus + * Had a "quick hack to fix romero bug" + */ -// -// M_DrawMainMenu -// -void M_DrawMainMenu(void) +void m_draw_read_this1(void) { - V_DrawPatchDirect(94, 2, - W_CacheLumpName(DEH_String("M_DOOM"), PU_CACHE)); -} - + inhelpscreens = true; + v_draw_patch_direct(0, 0, w_cache_lump_name(("HELP2"), PU_CACHE)); +} +/* Read This Menus - optional second page. */ -// -// M_NewGame -// -void M_DrawNewGame(void) +void m_draw_read_this2(void) { - V_DrawPatchDirect(96, 14, W_CacheLumpName(DEH_String("M_NEWG"), PU_CACHE)); - V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_SKILL"), PU_CACHE)); -} + inhelpscreens = true; -void M_NewGame(int choice) -{ - if (netgame && !demoplayback) - { - M_StartMessage(DEH_String(NEWGAME),NULL,false); - return; - } - - // Chex Quest disabled the episode select screen, as did Doom II. + /* We only ever draw the second page if this is + * gameversion == exe_doom_1_9 and gamemode == registered + */ - if (gamemode == commercial || gameversion == exe_chex) - M_SetupNextMenu(&NewDef); - else - M_SetupNextMenu(&EpiDef); + v_draw_patch_direct(0, 0, w_cache_lump_name(("HELP1"), PU_CACHE)); } +/* Change Sfx & Music volumes */ -// -// M_Episode -// -int epi; - -void M_DrawEpisode(void) +void m_draw_sound(void) { - V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_EPISOD"), PU_CACHE)); + v_draw_patch_direct(60, 38, w_cache_lump_name(("M_SVOL"), PU_CACHE)); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + m_draw_thermo(g_sound_def.x, + g_sound_def.y + LINEHEIGHT * (SOUND_SFXVOL + 1), 16, + g_sfx_volume); + + m_draw_thermo(g_sound_def.x, + g_sound_def.y + LINEHEIGHT * (SOUND_MUSICVOL + 1), 16, + g_music_volume); +#endif } -void M_VerifyNightmare(int key) +void m_sound(int choice) { - if (key != key_menu_confirm) - return; - - G_DeferedInitNew(nightmare,epi+1,1); - M_ClearMenus (); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + m_setup_next_menu(&g_sound_def); +#endif } -void M_ChooseSkill(int choice) +void m_sfx_vol(int choice) { - if (choice == nightmare) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + switch (choice) { - M_StartMessage(DEH_String(NIGHTMARE),M_VerifyNightmare,true); - return; + case 0: + if (g_sfx_volume) g_sfx_volume--; + break; + case 1: + if (g_sfx_volume < 15) g_sfx_volume++; + break; } - - G_DeferedInitNew(choice,epi+1,1); - M_ClearMenus (); + + s_set_sfx_volume(g_sfx_volume * 8); +#endif } -void M_Episode(int choice) +void m_music_vol(int choice) { - if ( (gamemode == shareware) - && choice) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + switch (choice) { - M_StartMessage(DEH_String(SWSTRING),NULL,false); - M_SetupNextMenu(&ReadDef1); - return; + case 0: + if (g_music_volume) g_music_volume--; + break; + case 1: + if (g_music_volume < 15) g_music_volume++; + break; } - epi = choice; - M_SetupNextMenu(&NewDef); + s_set_music_volume(g_music_volume * 8); +#endif } - - -// -// M_Options -// -static const char *detailNames[2] = {"M_GDHIGH","M_GDLOW"}; -static const char *msgNames[2] = {"M_MSGOFF","M_MSGON"}; - -void M_DrawOptions(void) +void m_drawmain_menu(void) { - V_DrawPatchDirect(108, 15, W_CacheLumpName(DEH_String("M_OPTTTL"), - PU_CACHE)); - - V_DrawPatchDirect(OptionsDef.x + 175, OptionsDef.y + LINEHEIGHT * detail, - W_CacheLumpName(DEH_String(detailNames[detailLevel]), - PU_CACHE)); - - V_DrawPatchDirect(OptionsDef.x + 120, OptionsDef.y + LINEHEIGHT * messages, - W_CacheLumpName(DEH_String(msgNames[showMessages]), - PU_CACHE)); - - M_DrawThermo(OptionsDef.x, OptionsDef.y + LINEHEIGHT * (mousesens + 1), - 10, mouseSensitivity); - - M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), - 9,screenSize); + v_draw_patch_direct(94, 2, w_cache_lump_name(("M_DOOM"), PU_CACHE)); } -void M_Options(int choice) +void m_draw_new_game(void) { - M_SetupNextMenu(&OptionsDef); + v_draw_patch_direct(96, 14, w_cache_lump_name(("M_NEWG"), PU_CACHE)); + v_draw_patch_direct(54, 38, w_cache_lump_name(("M_SKILL"), PU_CACHE)); } - - -// -// Toggle messages on/off -// -void M_ChangeMessages(int choice) +void m_new_game(int choice) { - // warning: unused parameter `int choice' - choice = 0; - showMessages = 1 - showMessages; - - if (!showMessages) - players[consoleplayer].message = DEH_String(MSGOFF); - else - players[consoleplayer].message = DEH_String(MSGON); + if (netgame && !demoplayback) + { + m_start_message((NEWGAME), NULL, false); + return; + } - message_dontfuckwithme = true; -} + /* Chex Quest disabled the episode select screen, as did Doom II. */ + if (gamemode == commercial || gameversion == exe_chex) + m_setup_next_menu(&g_new_def); + else + m_setup_next_menu(&g_epi_def); +} -// -// M_EndGame -// -void M_EndGameResponse(int key) +void m_draw_episode(void) { - if (key != key_menu_confirm) - return; - - currentMenu->lastOn = itemOn; - M_ClearMenus (); - D_StartTitle (); + v_draw_patch_direct(54, 38, w_cache_lump_name(("M_EPISOD"), PU_CACHE)); } -void M_EndGame(int choice) +void m_choose_skill(int choice) { - choice = 0; - if (!usergame) + if (choice == NEWGAME_NIGHTMARE) { - S_StartSound(NULL,sfx_oof); - return; + m_start_message((NIGHTMARE), m_verify_nightmare, true); + return; } - - if (netgame) + + g_deferred_init_new(choice, g_epi + 1, 1); + m_clear_menus(); +} + +void m_episode(int choice) +{ + if ((gamemode == shareware) && choice) { - M_StartMessage(DEH_String(NETEND),NULL,false); - return; + m_start_message((SWSTRING), NULL, false); + m_setup_next_menu(&g_read_def1); + return; } - - M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true); + + g_epi = choice; + m_setup_next_menu(&g_new_def); } +void m_draw_options(void) +{ + v_draw_patch_direct(108, 15, w_cache_lump_name(("M_OPTTTL"), PU_CACHE)); + v_draw_patch_direct( + g_options_def.x + 175, g_options_def.y + LINEHEIGHT * OPT_DETAIL, + w_cache_lump_name((g_detail_names[g_detail_level]), PU_CACHE)); + v_draw_patch_direct( + g_options_def.x + 120, g_options_def.y + LINEHEIGHT * OPT_MESSAGES, + w_cache_lump_name((g_msg_names[g_show_messages]), PU_CACHE)); -// -// M_ReadThis -// -void M_ReadThis(int choice) -{ - choice = 0; - M_SetupNextMenu(&ReadDef1); -} + m_draw_thermo(g_options_def.x, + g_options_def.y + LINEHEIGHT * (OPT_MOUSESENS + 1), 10, + g_mouse_sensitivity); -void M_ReadThis2(int choice) -{ - choice = 0; - M_SetupNextMenu(&ReadDef2); + m_draw_thermo(g_options_def.x, + g_options_def.y + LINEHEIGHT * (OPT_SCRNSIZE + 1), 9, + g_screen_size); } -void M_FinishReadThis(int choice) +void m_options(int choice) { - choice = 0; - M_SetupNextMenu(&MainDef); + m_setup_next_menu(&g_options_def); } +/* Toggle messages on/off */ - - -// -// M_QuitDOOM -// -int quitsounds[8] = +void m_change_messages(int choice) { - sfx_pldeth, - sfx_dmpain, - sfx_popain, - sfx_slop, - sfx_telept, - sfx_posit1, - sfx_posit3, - sfx_sgtatk -}; - -int quitsounds2[8] = -{ - sfx_vilact, - sfx_getpow, - sfx_boscub, - sfx_slop, - sfx_skeswg, - sfx_kntdth, - sfx_bspact, - sfx_sgtatk -}; + /* warning: unused parameter `int choice' */ + choice = 0; + g_show_messages = 1 - g_show_messages; + if (!g_show_messages) + players[consoleplayer].message = (MSGOFF); + else + players[consoleplayer].message = (MSGON); -void M_QuitResponse(int key) -{ - if (key != key_menu_confirm) - return; - if (!netgame) - { - if (gamemode == commercial) - S_StartSound(NULL,quitsounds2[(gametic>>2)&7]); - else - S_StartSound(NULL,quitsounds[(gametic>>2)&7]); - I_WaitVBL(105); - } - I_Quit (); + message_dontfuckwithme = true; } - -static const char *M_SelectEndMessage(void) +void m_end_game(int choice) { - const char **endmsg; - - if (logical_gamemission == doom) + choice = 0; + if (!usergame) { - // Doom 1 - - endmsg = doom1_endmsg; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return; } - else + + if (netgame) { - // Doom 2 - - endmsg = doom2_endmsg; + m_start_message((NETEND), NULL, false); + return; } - return endmsg[gametic % NUM_QUITMESSAGES]; + m_start_message((ENDGAME), m_end_game_response, true); } - -void M_QuitDOOM(int choice) +void m_read_this(int choice) { - DEH_snprintf(endstring, sizeof(endstring), "%s\n\n" DOSY, - DEH_String(M_SelectEndMessage())); + choice = 0; + m_setup_next_menu(&g_read_def1); +} - M_StartMessage(endstring,M_QuitResponse,true); +void m_read_this2(int choice) +{ + choice = 0; + m_setup_next_menu(&g_read_def2); } +void m_finish_read_this(int choice) +{ + choice = 0; + m_setup_next_menu(&g_main_def); +} +void m_quit_doom(int choice) +{ + snprintf(g_endstring, sizeof(g_endstring), "%s\n\n" DOSY, + (m_select_end_message())); + m_start_message(g_endstring, m_quit_response, true); +} -void M_ChangeSensitivity(int choice) +void m_change_sensitivity(int choice) { - switch(choice) + switch (choice) { - case 0: - if (mouseSensitivity) - mouseSensitivity--; - break; - case 1: - if (mouseSensitivity < 9) - mouseSensitivity++; - break; + case 0: + if (g_mouse_sensitivity) g_mouse_sensitivity--; + break; + case 1: + if (g_mouse_sensitivity < 9) g_mouse_sensitivity++; + break; } } - - - -void M_ChangeDetail(int choice) +void m_change_detail(int choice) { - choice = 0; - detailLevel = 1 - detailLevel; + choice = 0; + g_detail_level = 1 - g_detail_level; - R_SetViewSize (screenblocks, detailLevel); + r_set_view_size(screenblocks, g_detail_level); - if (!detailLevel) - players[consoleplayer].message = DEH_String(DETAILHI); - else - players[consoleplayer].message = DEH_String(DETAILLO); + if (!g_detail_level) + players[consoleplayer].message = (DETAILHI); + else + players[consoleplayer].message = (DETAILLO); } - - - -void M_SizeDisplay(int choice) +void m_size_display(int choice) { - switch(choice) + switch (choice) { - case 0: - if (screenSize > 0) - { - screenblocks--; - screenSize--; - } - break; - case 1: - if (screenSize < 8) - { - screenblocks++; - screenSize++; - } - break; + case 0: + if (g_screen_size > 0) + { + screenblocks--; + g_screen_size--; + } + break; + case 1: + if (g_screen_size < 8) + { + screenblocks++; + g_screen_size++; + } + break; } - - R_SetViewSize (screenblocks, detailLevel); + r_set_view_size(screenblocks, g_detail_level); } +/* Menu Functions */ - - -// -// Menu Functions -// -void -M_DrawThermo -( int x, - int y, - int thermWidth, - int thermDot ) +void m_draw_thermo(int x, int y, int therm_width, int therm_dot) { - int xx; - int i; + int xx; + int i; - xx = x; - V_DrawPatchDirect(xx, y, W_CacheLumpName(DEH_String("M_THERML"), PU_CACHE)); - xx += 8; - for (i=0;i= HU_FONTSIZE) + w += 4; + else + w += SHORT(hu_font[c]->width); + } + + return w; } +/* Find string height from hu_font chars */ -// -// Find string width from hu_font chars -// -int M_StringWidth(const char *string) +int m_string_height(const char *string) { - size_t i; - int w = 0; - int c; - - for (i = 0;i < strlen(string);i++) + size_t i; + int h; + int height = SHORT(hu_font[0]->height); + + h = height; + for (i = 0; i < strlen(string); i++) { - c = toupper(string[i]) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE) - w += 4; - else - w += SHORT (hu_font[c]->width); + if (string[i] == '\n') h += height; } - - return w; -} + return h; +} +/* Write a string using the hu_font */ -// -// Find string height from hu_font chars -// -int M_StringHeight(const char* string) +void m_write_text(int x, int y, const char *string) { - size_t i; - int h; - int height = SHORT(hu_font[0]->height); - - h = height; - for (i = 0;i < strlen(string);i++) - if (string[i] == '\n') - h += height; - - return h; -} + int w; + const char *ch; + int c; + int cx; + int cy; + + ch = string; + cx = x; + cy = y; + + while (1) + { + c = *ch++; + if (!c) break; + if (c == '\n') + { + cx = x; + cy += 12; + continue; + } + c = toupper(c) - HU_FONTSTART; + if (c < 0 || c >= HU_FONTSIZE) + { + cx += 4; + continue; + } -// -// Write a string using the hu_font -// -void -M_WriteText -( int x, - int y, - const char *string) -{ - int w; - const char *ch; - int c; - int cx; - int cy; - - - ch = string; - cx = x; - cy = y; - - while(1) - { - c = *ch++; - if (!c) - break; - if (c == '\n') - { - cx = x; - cy += 12; - continue; - } - - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c>= HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - if (cx+w > SCREENWIDTH) - break; - V_DrawPatchDirect(cx, cy, hu_font[c]); - cx+=w; + w = SHORT(hu_font[c]->width); + if (cx + w > SCREENWIDTH) break; + v_draw_patch_direct(cx, cy, hu_font[c]); + cx += w; } } -// These keys evaluate to a "null" key in Vanilla Doom that allows weird -// jumping in the menus. Preserve this behavior for accuracy. +/* CONTROL PANEL */ -static boolean IsNullKey(int key) +boolean m_responder(event_t *ev) { - return key == KEY_PAUSE || key == KEY_CAPSLOCK - || key == KEY_SCRLCK || key == KEY_NUMLOCK; -} + int ch; + int key; + int i; + static int mousewait = 0; + static int mousey = 0; + static int lasty = 0; + static int mousex = 0; + static int lastx = 0; + int dir; + + /* In testcontrols mode, none of the function keys should do anything + * - the only key is escape to quit. + */ -// -// CONTROL PANEL -// - -// -// M_Responder -// -boolean M_Responder (event_t* ev) -{ - int ch; - int key; - int i; - static int mousewait = 0; - static int mousey = 0; - static int lasty = 0; - static int mousex = 0; - static int lastx = 0; - int dir; - - // In testcontrols mode, none of the function keys should do anything - // - the only key is escape to quit. - - if (testcontrols) - { - if (ev->type == ev_quit - || (ev->type == ev_keydown - && (ev->data1 == key_menu_activate || ev->data1 == key_menu_quit))) + if (testcontrols) + { + if (ev->type == ev_quit || + (ev->type == ev_keydown && + (ev->data1 == key_menu_activate || ev->data1 == key_menu_quit))) { - I_Quit(); - return true; + i_quit(); + return true; } - return false; + return false; } - // "close" button pressed on window? - if (ev->type == ev_quit) + /* "close" button pressed on window? */ + + if (ev->type == ev_quit) { - // First click on close button = bring up quit confirm message. - // Second click on close button = confirm quit + /* First click on close button = bring up quit confirm message. + * Second click on close button = confirm quit + */ - if (menuactive && messageToPrint && messageRoutine == M_QuitResponse) + if (g_menuactive && g_message_to_print && + message_routine == m_quit_response) { - M_QuitResponse(key_menu_confirm); + m_quit_response(key_menu_confirm); } - else + else { - S_StartSound(NULL,sfx_swtchn); - M_QuitDOOM(0); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_quit_doom(0); } - return true; + return true; } - // key is the key pressed, ch is the actual character typed - - ch = 0; - key = -1; - - if (ev->type == ev_joystick) + /* key is the key pressed, ch is the actual character typed */ + + ch = 0; + key = -1; + + if (ev->type == ev_joystick) { - // Simulate key presses from joystick events to interact with the menu. + /* Simulate key presses from joystick events to interact with the menu. + */ - if (menuactive) + if (g_menuactive) { - if (JOY_GET_DPAD(ev->data6) != JOY_DIR_NONE) + if (JOY_GET_DPAD(ev->data6) != JOY_DIR_NONE) { - dir = JOY_GET_DPAD(ev->data6); + dir = JOY_GET_DPAD(ev->data6); } - else if (JOY_GET_LSTICK(ev->data6) != JOY_DIR_NONE) + else if (JOY_GET_LSTICK(ev->data6) != JOY_DIR_NONE) { - dir = JOY_GET_LSTICK(ev->data6); + dir = JOY_GET_LSTICK(ev->data6); } - else + else { - dir = JOY_GET_RSTICK(ev->data6); + dir = JOY_GET_RSTICK(ev->data6); } - if (dir & JOY_DIR_UP) + if (dir & JOY_DIR_UP) { - key = key_menu_up; - joywait = I_GetTime() + 5; + key = key_menu_up; + joywait = i_get_time() + 5; } - else if (dir & JOY_DIR_DOWN) + else if (dir & JOY_DIR_DOWN) { - key = key_menu_down; - joywait = I_GetTime() + 5; + key = key_menu_down; + joywait = i_get_time() + 5; } - if (dir & JOY_DIR_LEFT) + + if (dir & JOY_DIR_LEFT) { - key = key_menu_left; - joywait = I_GetTime() + 5; + key = key_menu_left; + joywait = i_get_time() + 5; } - else if (dir & JOY_DIR_RIGHT) + else if (dir & JOY_DIR_RIGHT) { - key = key_menu_right; - joywait = I_GetTime() + 5; + key = key_menu_right; + joywait = i_get_time() + 5; } -#define JOY_BUTTON_MAPPED(x) ((x) >= 0) -#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (ev->data1 & (1 << (x))) != 0) - - if (JOY_BUTTON_PRESSED(joybfire)) + if (JOY_BUTTON_PRESSED(joybfire)) { - // Simulate a 'Y' keypress when Doom show a Y/N dialog with Fire button. - if (messageToPrint && messageNeedsInput) + /* Simulate a 'Y' keypress when Doom show a Y/N dialog with + * Fire button. + */ + + if (g_message_to_print && g_message_needs_input) { - key = key_menu_confirm; + key = key_menu_confirm; } - // Simulate pressing "Enter" when we are supplying a save slot name - else if (saveStringEnter) + + /* Simulate pressing "Enter" when we are supplying a save slot + * name + */ + + else if (g_save_string_enter) { - key = KEY_ENTER; + key = KEY_ENTER; } - else + else { - // if selecting a save slot via joypad, set a flag - if (currentMenu == &SaveDef) + /* if selecting a save slot via joypad, set a flag */ + + if (g_current_menu == &g_save_def) { - joypadSave = true; + g_joypad_save = true; } - key = key_menu_forward; + + key = key_menu_forward; } - joywait = I_GetTime() + 5; + + joywait = i_get_time() + 5; } - if (JOY_BUTTON_PRESSED(joybuse)) + + if (JOY_BUTTON_PRESSED(joybuse)) { - // Simulate a 'N' keypress when Doom show a Y/N dialog with Use button. - if (messageToPrint && messageNeedsInput) + /* Simulate a 'N' keypress when Doom show a Y/N dialog with Use + * button. + */ + + if (g_message_to_print && g_message_needs_input) { - key = key_menu_abort; + key = key_menu_abort; } - // If user was entering a save name, back out - else if (saveStringEnter) + + /* If user was entering a save name, back out */ + + else if (g_save_string_enter) { - key = KEY_ESCAPE; + key = KEY_ESCAPE; } - else + else { - key = key_menu_back; + key = key_menu_back; } - joywait = I_GetTime() + 5; + + joywait = i_get_time() + 5; } } - if (JOY_BUTTON_PRESSED(joybmenu)) + + if (JOY_BUTTON_PRESSED(joybmenu)) { - key = key_menu_activate; - joywait = I_GetTime() + 5; + key = key_menu_activate; + joywait = i_get_time() + 5; } } - else - { - if (ev->type == ev_mouse && mousewait < I_GetTime() && menuactive) - { - mousey += ev->data3; - if (mousey < lasty-30) - { - key = key_menu_down; - mousewait = I_GetTime() + 5; - mousey = lasty -= 30; - } - else if (mousey > lasty+30) - { - key = key_menu_up; - mousewait = I_GetTime() + 5; - mousey = lasty += 30; - } - - mousex += ev->data2; - if (mousex < lastx-30) - { - key = key_menu_left; - mousewait = I_GetTime() + 5; - mousex = lastx -= 30; - } - else if (mousex > lastx+30) - { - key = key_menu_right; - mousewait = I_GetTime() + 5; - mousex = lastx += 30; - } - - if (ev->data1&1) - { - key = key_menu_forward; - mousewait = I_GetTime() + 15; - } - - if (ev->data1&2) - { - key = key_menu_back; - mousewait = I_GetTime() + 15; - } - } - else - { - if (ev->type == ev_keydown) - { - key = ev->data1; - ch = ev->data2; - } - } + else + { + if (ev->type == ev_mouse && mousewait < i_get_time() && g_menuactive) + { + mousey += ev->data3; + if (mousey < lasty - 30) + { + key = key_menu_down; + mousewait = i_get_time() + 5; + mousey = lasty -= 30; + } + else if (mousey > lasty + 30) + { + key = key_menu_up; + mousewait = i_get_time() + 5; + mousey = lasty += 30; + } + + mousex += ev->data2; + if (mousex < lastx - 30) + { + key = key_menu_left; + mousewait = i_get_time() + 5; + mousex = lastx -= 30; + } + else if (mousex > lastx + 30) + { + key = key_menu_right; + mousewait = i_get_time() + 5; + mousex = lastx += 30; + } + + if (ev->data1 & 1) + { + key = key_menu_forward; + mousewait = i_get_time() + 15; + } + + if (ev->data1 & 2) + { + key = key_menu_back; + mousewait = i_get_time() + 15; + } + } + else + { + if (ev->type == ev_keydown) + { + key = ev->data1; + ch = ev->data2; + } + } } - - if (key == -1) - return false; - - // Save Game string input - if (saveStringEnter) - { - switch(key) - { - case KEY_BACKSPACE: - if (saveCharIndex > 0) - { - saveCharIndex--; - savegamestrings[saveSlot][saveCharIndex] = 0; - } - break; - - case KEY_ESCAPE: - saveStringEnter = 0; - I_StopTextInput(); - M_StringCopy(savegamestrings[saveSlot], saveOldString, - SAVESTRINGSIZE); - break; - - case KEY_ENTER: - saveStringEnter = 0; - I_StopTextInput(); - if (savegamestrings[saveSlot][0]) - M_DoSave(saveSlot); - break; - - default: - // Savegame name entry. This is complicated. - // Vanilla has a bug where the shift key is ignored when entering - // a savegame name. If vanilla_keyboard_mapping is on, we want - // to emulate this bug by using ev->data1. But if it's turned off, - // it implies the user doesn't care about Vanilla emulation: - // instead, use ev->data3 which gives the fully-translated and - // modified key input. - - if (ev->type != ev_keydown) + + if (key == -1) return false; + + /* Save Game string input */ + + if (g_save_string_enter) + { + switch (key) + { + case KEY_BACKSPACE: + if (g_save_char_index > 0) + { + g_save_char_index--; + g_save_game_strings[g_save_slot][g_save_char_index] = 0; + } + break; + + case KEY_ESCAPE: + g_save_string_enter = 0; + i_stop_text_input(); + m_str_copy(g_save_game_strings[g_save_slot], g_save_old_string, + SAVESTRINGSIZE); + break; + + case KEY_ENTER: + g_save_string_enter = 0; + i_stop_text_input(); + if (g_save_game_strings[g_save_slot][0]) m_do_save(g_save_slot); + break; + + default: + /* Savegame name entry. This is complicated. + * Vanilla has a bug where the shift key is ignored when entering + * a savegame name. If vanilla_keyboard_mapping is on, we want + * to emulate this bug by using ev->data1. But if it's turned off, + * it implies the user doesn't care about Vanilla emulation: + * instead, use ev->data3 which gives the fully-translated and + * modified key input. + */ + + if (ev->type != ev_keydown) { - break; + break; } - if (vanilla_keyboard_mapping) + + if (vanilla_keyboard_mapping) { - ch = ev->data1; + ch = ev->data1; } - else + else { - ch = ev->data3; + ch = ev->data3; } - ch = toupper(ch); + ch = toupper(ch); + + if (ch != ' ' && + (ch - HU_FONTSTART < 0 || ch - HU_FONTSTART >= HU_FONTSIZE)) + { + break; + } - if (ch != ' ' - && (ch - HU_FONTSTART < 0 || ch - HU_FONTSTART >= HU_FONTSIZE)) + if (ch >= 32 && ch <= 127 && + g_save_char_index < SAVESTRINGSIZE - 1 && + m_string_width(g_save_game_strings[g_save_slot]) < + (SAVESTRINGSIZE - 2) * 8) { - break; + g_save_game_strings[g_save_slot][g_save_char_index++] = ch; + g_save_game_strings[g_save_slot][g_save_char_index] = 0; } - if (ch >= 32 && ch <= 127 && - saveCharIndex < SAVESTRINGSIZE-1 && - M_StringWidth(savegamestrings[saveSlot]) < - (SAVESTRINGSIZE-2)*8) - { - savegamestrings[saveSlot][saveCharIndex++] = ch; - savegamestrings[saveSlot][saveCharIndex] = 0; - } - break; - } - return true; + break; + } + + return true; } - // Take care of any messages that need input - if (messageToPrint) + /* Take care of any messages that need input */ + + if (g_message_to_print) { - if (messageNeedsInput) + if (g_message_needs_input) { - if (key != ' ' && key != KEY_ESCAPE - && key != key_menu_confirm && key != key_menu_abort) + if (key != ' ' && key != KEY_ESCAPE && key != key_menu_confirm && + key != key_menu_abort) { - return false; + return false; } - } + } - menuactive = messageLastMenuActive; - messageToPrint = 0; - if (messageRoutine) - messageRoutine(key); + g_menuactive = g_message_last_menu_active; + g_message_to_print = 0; + if (message_routine) message_routine(key); - menuactive = false; - S_StartSound(NULL,sfx_swtchx); - return true; + g_menuactive = false; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHX); +#endif + return true; } - if ((devparm && key == key_menu_help) || - (key != 0 && key == key_menu_screenshot)) + if ((devparm && key == key_menu_help) || + (key != 0 && key == key_menu_screenshot)) { - G_ScreenShot (); - return true; + g_screenshot(); + return true; } - // F-Keys - if (!menuactive) + /* F-Keys */ + + if (!g_menuactive) { - if (key == key_menu_decscreen) // Screen size down + if (key == key_menu_decscreen) /* Screen size down */ { - if (automapactive || chat_on) - return false; - M_SizeDisplay(0); - S_StartSound(NULL,sfx_stnmov); - return true; - } - else if (key == key_menu_incscreen) // Screen size up + if (automapactive || chat_on) return false; + m_size_display(0); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_STNMOV); +#endif + return true; + } + else if (key == key_menu_incscreen) /* Screen size up */ { - if (automapactive || chat_on) - return false; - M_SizeDisplay(1); - S_StartSound(NULL,sfx_stnmov); - return true; - } - else if (key == key_menu_help) // Help key + if (automapactive || chat_on) return false; + m_size_display(1); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_STNMOV); +#endif + return true; + } + else if (key == key_menu_help) /* Help key */ { - M_StartControlPanel (); - - if (gameversion >= exe_ultimate) - currentMenu = &ReadDef2; - else - currentMenu = &ReadDef1; - - itemOn = 0; - S_StartSound(NULL,sfx_swtchn); - return true; - } - else if (key == key_menu_save) // Save + m_start_control_panel(); + + if (gameversion >= exe_ultimate) + g_current_menu = &g_read_def2; + else + g_current_menu = &g_read_def1; + + g_item_on = 0; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + return true; + } + else if (key == key_menu_save) /* Save */ { - M_StartControlPanel(); - S_StartSound(NULL,sfx_swtchn); - M_SaveGame(0); - return true; + m_start_control_panel(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_save_game(0); + return true; } - else if (key == key_menu_load) // Load + else if (key == key_menu_load) /* Load */ { - M_StartControlPanel(); - S_StartSound(NULL,sfx_swtchn); - M_LoadGame(0); - return true; + m_start_control_panel(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_load_game(0); + return true; } - else if (key == key_menu_volume) // Sound Volume + else if (key == key_menu_volume) /* Sound Volume */ { - M_StartControlPanel (); - currentMenu = &SoundDef; - itemOn = sfx_vol; - S_StartSound(NULL,sfx_swtchn); - return true; - } - else if (key == key_menu_detail) // Detail toggle + m_start_control_panel(); + g_item_on = SOUND_SFXVOL; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + g_current_menu = &g_sound_def; + s_start_sound(NULL, SFX_SWTCHN); +#endif + return true; + } + else if (key == key_menu_detail) /* Detail toggle */ { - M_ChangeDetail(0); - S_StartSound(NULL,sfx_swtchn); - return true; + m_change_detail(0); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + return true; } - else if (key == key_menu_qsave) // Quicksave + else if (key == key_menu_qsave) /* Quicksave */ { - S_StartSound(NULL,sfx_swtchn); - M_QuickSave(); - return true; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_quick_save(); + return true; } - else if (key == key_menu_endgame) // End game + else if (key == key_menu_endgame) /* End game */ { - S_StartSound(NULL,sfx_swtchn); - M_EndGame(0); - return true; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_end_game(0); + return true; } - else if (key == key_menu_messages) // Toggle messages + else if (key == key_menu_messages) /* Toggle messages */ { - M_ChangeMessages(0); - S_StartSound(NULL,sfx_swtchn); - return true; + m_change_messages(0); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + return true; } - else if (key == key_menu_qload) // Quickload + else if (key == key_menu_qload) /* Quickload */ { - S_StartSound(NULL,sfx_swtchn); - M_QuickLoad(); - return true; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_quick_load(); + return true; } - else if (key == key_menu_quit) // Quit DOOM + else if (key == key_menu_quit) /* Quit DOOM */ { - S_StartSound(NULL,sfx_swtchn); - M_QuitDOOM(0); - return true; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + m_quit_doom(0); + return true; } - else if (key == key_menu_gamma) // gamma toggle + else if (key == key_menu_gamma) /* gamma toggle */ { - usegamma++; - if (usegamma > 4) - usegamma = 0; - players[consoleplayer].message = DEH_String(gammamsg[usegamma]); - I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); - return true; - } + usegamma++; + if (usegamma > 4) usegamma = 0; + players[consoleplayer].message = (g_gammamsg[usegamma]); + i_set_palette(w_cache_lump_name(("PLAYPAL"), PU_CACHE)); + return true; + } } - // Pop-up menu? - if (!menuactive) + /* Pop-up menu? */ + + if (!g_menuactive) { - if (key == key_menu_activate) - { - M_StartControlPanel (); - S_StartSound(NULL,sfx_swtchn); - return true; - } - return false; + if (key == key_menu_activate) + { + m_start_control_panel(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + return true; + } + + return false; } - // Keys usable within menu + /* Keys usable within menu */ - if (key == key_menu_down) + if (key == key_menu_down) { - // Move down to next item + /* Move down to next item */ - do - { - if (itemOn+1 > currentMenu->numitems-1) - itemOn = 0; - else itemOn++; - S_StartSound(NULL,sfx_pstop); - } while(currentMenu->menuitems[itemOn].status==-1); + do + { + if (g_item_on + 1 > g_current_menu->numitems - 1) + g_item_on = 0; + else + g_item_on++; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_PSTOP); +#endif + } + while (g_current_menu->menu_items[g_item_on].status == -1); - return true; + return true; } - else if (key == key_menu_up) + else if (key == key_menu_up) { - // Move back up to previous item + /* Move back up to previous item */ - do - { - if (!itemOn) - itemOn = currentMenu->numitems-1; - else itemOn--; - S_StartSound(NULL,sfx_pstop); - } while(currentMenu->menuitems[itemOn].status==-1); + do + { + if (!g_item_on) + g_item_on = g_current_menu->numitems - 1; + else + g_item_on--; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_PSTOP); +#endif + } + while (g_current_menu->menu_items[g_item_on].status == -1); - return true; + return true; } - else if (key == key_menu_left) + else if (key == key_menu_left) { - // Slide slider left + /* Slide slider left */ + + if (g_current_menu->menu_items[g_item_on].routine && + g_current_menu->menu_items[g_item_on].status == 2) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_STNMOV); +#endif + g_current_menu->menu_items[g_item_on].routine(0); + } - if (currentMenu->menuitems[itemOn].routine && - currentMenu->menuitems[itemOn].status == 2) - { - S_StartSound(NULL,sfx_stnmov); - currentMenu->menuitems[itemOn].routine(0); - } - return true; + return true; } - else if (key == key_menu_right) + else if (key == key_menu_right) { - // Slide slider right + /* Slide slider right */ - if (currentMenu->menuitems[itemOn].routine && - currentMenu->menuitems[itemOn].status == 2) - { - S_StartSound(NULL,sfx_stnmov); - currentMenu->menuitems[itemOn].routine(1); - } - return true; - } - else if (key == key_menu_forward) - { - // Activate menu item - - if (currentMenu->menuitems[itemOn].routine && - currentMenu->menuitems[itemOn].status) - { - currentMenu->lastOn = itemOn; - if (currentMenu->menuitems[itemOn].status == 2) - { - currentMenu->menuitems[itemOn].routine(1); // right arrow - S_StartSound(NULL,sfx_stnmov); - } - else - { - currentMenu->menuitems[itemOn].routine(itemOn); - S_StartSound(NULL,sfx_pistol); - } - } - return true; + if (g_current_menu->menu_items[g_item_on].routine && + g_current_menu->menu_items[g_item_on].status == 2) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_STNMOV); +#endif + g_current_menu->menu_items[g_item_on].routine(1); + } + + return true; } - else if (key == key_menu_activate) + else if (key == key_menu_forward) { - // Deactivate menu + /* Activate menu item */ - currentMenu->lastOn = itemOn; - M_ClearMenus (); - S_StartSound(NULL,sfx_swtchx); - return true; + if (g_current_menu->menu_items[g_item_on].routine && + g_current_menu->menu_items[g_item_on].status) + { + g_current_menu->last_on = g_item_on; + if (g_current_menu->menu_items[g_item_on].status == 2) + { + g_current_menu->menu_items[g_item_on].routine( + 1); /* right arrow */ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_STNMOV); +#endif + } + else + { + g_current_menu->menu_items[g_item_on].routine(g_item_on); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_PISTOL); +#endif + } + } + + return true; + } + else if (key == key_menu_activate) + { + /* Deactivate menu */ + + g_current_menu->last_on = g_item_on; + m_clear_menus(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHX); +#endif + return true; } - else if (key == key_menu_back) - { - // Go back to previous menu - - currentMenu->lastOn = itemOn; - if (currentMenu->prevMenu) - { - currentMenu = currentMenu->prevMenu; - itemOn = currentMenu->lastOn; - S_StartSound(NULL,sfx_swtchn); - } - return true; + else if (key == key_menu_back) + { + /* Go back to previous menu */ + + g_current_menu->last_on = g_item_on; + if (g_current_menu->prev_menu) + { + g_current_menu = g_current_menu->prev_menu; + g_item_on = g_current_menu->last_on; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_SWTCHN); +#endif + } + + return true; } - // Keyboard shortcut? - // Vanilla Doom has a weird behavior where it jumps to the scroll bars - // when the certain keys are pressed, so emulate this. + /* Keyboard shortcut? + * Vanilla Doom has a weird behavior where it jumps to the scroll bars + * when the certain keys are pressed, so emulate this. + */ - else if (ch != 0 || IsNullKey(key)) + else if (ch != 0 || is_null_key(key)) { - for (i = itemOn+1;i < currentMenu->numitems;i++) + for (i = g_item_on + 1; i < g_current_menu->numitems; i++) { - if (currentMenu->menuitems[i].alphaKey == ch) - { - itemOn = i; - S_StartSound(NULL,sfx_pstop); - return true; - } + if (g_current_menu->menu_items[i].alpha_key == ch) + { + g_item_on = i; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_PSTOP); +#endif + return true; + } } - for (i = 0;i <= itemOn;i++) + for (i = 0; i <= g_item_on; i++) { - if (currentMenu->menuitems[i].alphaKey == ch) - { - itemOn = i; - S_StartSound(NULL,sfx_pstop); - return true; - } + if (g_current_menu->menu_items[i].alpha_key == ch) + { + g_item_on = i; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_PSTOP); +#endif + return true; + } } } - return false; + return false; } +void m_start_control_panel(void) +{ + /* intro might call this repeatedly */ + if (g_menuactive) return; -// -// M_StartControlPanel -// -void M_StartControlPanel (void) -{ - // intro might call this repeatedly - if (menuactive) - return; - - menuactive = 1; - currentMenu = &MainDef; // JDC - itemOn = currentMenu->lastOn; // JDC + g_menuactive = 1; + g_current_menu = &g_main_def; /* JDC */ + g_item_on = g_current_menu->last_on; /* JDC */ } -// Display OPL debug messages - hack for GENMIDI development. +/* Display OPL debug messages - hack for GENMIDI development. */ -static void M_DrawOPLDev(void) +#if 0 +static void m_draw_opl_dev(void) { - char debug[1024]; - char *curr, *p; - int line; + char debug[1024]; + char *curr; + char *p; + int line; - I_OPL_DevMessages(debug, sizeof(debug)); - curr = debug; - line = 0; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + i_opl_dev_messages(debug, sizeof(debug)); +#endif + curr = debug; + line = 0; - for (;;) + for (; ; ) { - p = strchr(curr, '\n'); + p = strchr(curr, '\n'); - if (p != NULL) + if (p != NULL) { - *p = '\0'; + *p = '\0'; } - M_WriteText(0, line * 8, curr); - ++line; + m_write_text(0, line * 8, curr); + ++line; - if (p == NULL) + if (p == NULL) { - break; + break; } - curr = p + 1; + curr = p + 1; } } +#endif + +/* m_drawer + * Called after the view has been rendered, + * but before it has been blitted. + */ + +void m_drawer(void) +{ + static short x; + static short y; + unsigned int i; + unsigned int max; + char string[80]; + const char *name; + int start; + + inhelpscreens = false; -// -// M_Drawer -// Called after the view has been rendered, -// but before it has been blitted. -// -void M_Drawer (void) -{ - static short x; - static short y; - unsigned int i; - unsigned int max; - char string[80]; - const char *name; - int start; - - inhelpscreens = false; - - // Horiz. & Vertically center string and print it. - if (messageToPrint) - { - start = 0; - y = SCREENHEIGHT/2 - M_StringHeight(messageString) / 2; - while (messageString[start] != '\0') - { - boolean foundnewline = false; - - for (i = 0; messageString[start + i] != '\0'; i++) + /* Horiz. & Vertically center string and print it. */ + + if (g_message_to_print) + { + start = 0; + y = SCREENHEIGHT / 2 - m_string_height(g_message_string) / 2; + while (g_message_string[start] != '\0') + { + boolean foundnewline = false; + + for (i = 0; g_message_string[start + i] != '\0'; i++) { - if (messageString[start + i] == '\n') + if (g_message_string[start + i] == '\n') { - M_StringCopy(string, messageString + start, - sizeof(string)); - if (i < sizeof(string)) + m_str_copy(string, g_message_string + start, + sizeof(string)); + if (i < sizeof(string)) { - string[i] = '\0'; + string[i] = '\0'; } - foundnewline = true; - start += i + 1; - break; + foundnewline = true; + start += i + 1; + break; } } - if (!foundnewline) + if (!foundnewline) { - M_StringCopy(string, messageString + start, sizeof(string)); - start += strlen(string); + m_str_copy(string, g_message_string + start, sizeof(string)); + start += strlen(string); } - x = SCREENWIDTH/2 - M_StringWidth(string) / 2; - M_WriteText(x, y, string); - y += SHORT(hu_font[0]->height); - } + x = SCREENWIDTH / 2 - m_string_width(string) / 2; + m_write_text(x, y, string); + y += SHORT(hu_font[0]->height); + } - return; + return; } - if (opldev) - { - M_DrawOPLDev(); - } + if (!g_menuactive) return; + + if (g_current_menu->routine) + g_current_menu->routine(); /* call Draw routine */ - if (!menuactive) - return; + /* DRAW MENU */ - if (currentMenu->routine) - currentMenu->routine(); // call Draw routine - - // DRAW MENU - x = currentMenu->x; - y = currentMenu->y; - max = currentMenu->numitems; + x = g_current_menu->x; + y = g_current_menu->y; + max = g_current_menu->numitems; - for (i=0;imenuitems[i].name); + name = (g_current_menu->menu_items[i].name); + + if (name[0] && w_check_num_for_name(name) > 0) + { + v_draw_patch_direct(x, y, w_cache_lump_name(name, PU_CACHE)); + } - if (name[0] && W_CheckNumForName(name) > 0) - { - V_DrawPatchDirect (x, y, W_CacheLumpName(name, PU_CACHE)); - } - y += LINEHEIGHT; + y += LINEHEIGHT; } - - // DRAW SKULL - V_DrawPatchDirect(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT, - W_CacheLumpName(DEH_String(skullName[whichSkull]), - PU_CACHE)); -} + /* DRAW SKULL */ + v_draw_patch_direct( + x + SKULLXOFF, g_current_menu->y - 5 + g_item_on * LINEHEIGHT, + w_cache_lump_name((g_skull_name[g_which_skull]), PU_CACHE)); +} -// -// M_ClearMenus -// -void M_ClearMenus (void) +void m_clear_menus(void) { - menuactive = 0; - // if (!netgame && usergame && paused) - // sendpause = true; + g_menuactive = 0; } - - - -// -// M_SetupNextMenu -// -void M_SetupNextMenu(menu_t *menudef) +void m_setup_next_menu(menu_t *menudef) { - currentMenu = menudef; - itemOn = currentMenu->lastOn; + g_current_menu = menudef; + g_item_on = g_current_menu->last_on; } - -// -// M_Ticker -// -void M_Ticker (void) +void m_ticker(void) { - if (--skullAnimCounter <= 0) + if (--g_skull_anim_counter <= 0) { - whichSkull ^= 1; - skullAnimCounter = 8; + g_which_skull ^= 1; + g_skull_anim_counter = 8; } } - -// -// M_Init -// -void M_Init (void) +void m_init(void) { - currentMenu = &MainDef; - menuactive = 0; - itemOn = currentMenu->lastOn; - whichSkull = 0; - skullAnimCounter = 10; - screenSize = screenblocks - 3; - messageToPrint = 0; - messageString = NULL; - messageLastMenuActive = menuactive; - quickSaveSlot = -1; + g_current_menu = &g_main_def; + g_menuactive = 0; + g_item_on = g_current_menu->last_on; + g_which_skull = 0; + g_skull_anim_counter = 10; + g_screen_size = screenblocks - 3; + g_message_to_print = 0; + g_message_string = NULL; + g_message_last_menu_active = g_menuactive; + g_quick_save_slot = -1; - // Here we could catch other version dependencies, - // like HELP1/2, and four episodes. + /* Here we could catch other version dependencies, like HELP1/2, and four + * episodes. + */ - // The same hacks were used in the original Doom EXEs. + /* The same hacks were used in the original Doom EXEs. */ - if (gameversion >= exe_ultimate) + if (gameversion >= exe_ultimate) { - MainMenu[readthis].routine = M_ReadThis2; - ReadDef2.prevMenu = NULL; + g_main_menu[MAIN_READTHIS].routine = m_read_this2; + g_read_def2.prev_menu = NULL; } - if (gameversion >= exe_final && gameversion <= exe_final2) + if (gameversion >= exe_final && gameversion <= exe_final2) { - ReadDef2.routine = M_DrawReadThisCommercial; + g_read_def2.routine = m_draw_read_this_commercial; } - if (gamemode == commercial) + if (gamemode == commercial) { - MainMenu[readthis] = MainMenu[quitdoom]; - MainDef.numitems--; - MainDef.y += 8; - NewDef.prevMenu = &MainDef; - ReadDef1.routine = M_DrawReadThisCommercial; - ReadDef1.x = 330; - ReadDef1.y = 165; - ReadMenu1[rdthsempty1].routine = M_FinishReadThis; + g_main_menu[MAIN_READTHIS] = g_main_menu[MAIN_QUITDOOM]; + g_main_def.numitems--; + g_main_def.y += 8; + g_new_def.prev_menu = &g_main_def; + g_read_def1.routine = m_draw_read_this_commercial; + g_read_def1.x = 330; + g_read_def1.y = 165; + g_read_menu1[RDTHSEMPTY1].routine = m_finish_read_this; } - // Versions of doom.exe before the Ultimate Doom release only had - // three episodes; if we're emulating one of those then don't try - // to show episode four. If we are, then do show episode four - // (should crash if missing). - if (gameversion < exe_ultimate) + /* Versions of doom.exe before the Ultimate Doom release only had + * three episodes; if we're emulating one of those then don't try + * to show episode four. If we are, then do show episode four + * (should crash if missing). + */ + + if (gameversion < exe_ultimate) { - EpiDef.numitems--; + g_epi_def.numitems--; } - // chex.exe shows only one episode. - else if (gameversion == exe_chex) + + /* chex.exe shows only one episode. */ + + else if (gameversion == exe_chex) { - EpiDef.numitems = 1; + g_epi_def.numitems = 1; } - - opldev = M_CheckParm("-opldev") > 0; } - diff --git a/games/NXDoom/src/doom/m_menu.h b/games/NXDoom/src/doom/m_menu.h index 2c7867f128b..545f3eb8a65 100644 --- a/games/NXDoom/src/doom/m_menu.h +++ b/games/NXDoom/src/doom/m_menu.h @@ -1,62 +1,76 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Menu widget stuff, episode selection and such. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/m_menu.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Menu widget stuff, episode selection and such. + * + ****************************************************************************/ #ifndef __M_MENU__ #define __M_MENU__ - +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "d_event.h" -// -// MENUS -// -// Called by main loop, -// saves config file and calls I_Quit when user exits. -// Even when the menu is not displayed, -// this can resize the view and change game parameters. -// Does all the real work of the menu interaction. -boolean M_Responder (event_t *ev); +/**************************************************************************** + * Public Data + ****************************************************************************/ +extern int g_detail_level; +extern int screenblocks; -// Called by main loop, -// only used for menu (skull cursor) animation. -void M_Ticker (void); +extern boolean inhelpscreens; +extern int g_show_messages; -// Called by main loop, -// draws the menus directly into the screen buffer. -void M_Drawer (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Called by D_DoomMain, -// loads the config file. -void M_Init (void); +/* MENUS + * + * Called by main loop, + * saves config file and calls i_quit when user exits. + * Even when the menu is not displayed, + * this can resize the view and change game parameters. + * Does all the real work of the menu interaction. + */ -// Called by intro code to force menu up upon a keypress, -// does nothing if menu is already up. -void M_StartControlPanel (void); +boolean m_responder(event_t *ev); +/* Called by main loop, only used for menu (skull cursor) animation. */ -extern int detailLevel; -extern int screenblocks; +void m_ticker(void); -extern boolean inhelpscreens; -extern int showMessages; +/* Called by main loop, draws the menus directly into the screen buffer. */ + +void m_drawer(void); + +/* Called by d_doom_main, loads the config file. */ + +void m_init(void); + +/* Called by intro code to force menu up upon a keypress, does nothing if + * menu is already up. + */ +void m_start_control_panel(void); -#endif +#endif /* __M_MENU__ */ diff --git a/games/NXDoom/src/doom/m_random.c b/games/NXDoom/src/doom/m_random.c index b4f59b33f47..1c846cc0c46 100644 --- a/games/NXDoom/src/doom/m_random.c +++ b/games/NXDoom/src/doom/m_random.c @@ -1,72 +1,90 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Random number LUT. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/m_random.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Random number LUT. + * + ****************************************************************************/ -// -// M_Random -// Returns a 0-255 number -// +/**************************************************************************** + * Private Data + ****************************************************************************/ -static const unsigned char rndtable[256] = { - 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 , - 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 , - 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 , - 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 , - 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 , - 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 , - 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 , - 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 , - 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 , - 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 , - 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 , - 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 , - 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 , - 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 , - 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 , - 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 , - 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 , - 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 , - 120, 163, 236, 249 +/* m_random + * Returns a 0-255 number + */ + +static const unsigned char rndtable[256] = +{ + 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, 74, + 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36, 95, 110, + 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, 52, 140, 202, + 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, 149, 104, 25, 178, + 252, 182, 202, 182, 141, 197, 4, 81, 181, 242, 145, 42, 39, 227, 156, + 198, 225, 193, 219, 93, 122, 175, 249, 0, 175, 143, 70, 239, 46, 246, + 163, 53, 163, 109, 168, 135, 2, 235, 25, 92, 20, 145, 138, 77, 69, + 166, 78, 176, 173, 212, 166, 113, 94, 161, 41, 50, 239, 49, 111, 164, + 70, 60, 2, 37, 171, 75, 136, 156, 11, 56, 42, 146, 138, 229, 73, + 146, 77, 61, 98, 196, 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, + 170, 247, 181, 113, 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, + 166, 103, 241, 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, + 143, 224, 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, + 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226, + 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, + 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, + 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136, 120, 163, 236, + 249, }; -int rndindex = 0; -int prndindex = 0; +/**************************************************************************** + * Public Data + ****************************************************************************/ + +int rndindex = 0; +int prndindex = 0; -// Which one is deterministic? -int P_Random (void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Which one is deterministic? */ + +int p_random(void) { - prndindex = (prndindex+1)&0xff; - return rndtable[prndindex]; + prndindex = (prndindex + 1) & 0xff; + return rndtable[prndindex]; } -int M_Random (void) +int m_random(void) { - rndindex = (rndindex+1)&0xff; - return rndtable[rndindex]; + rndindex = (rndindex + 1) & 0xff; + return rndtable[rndindex]; } -void M_ClearRandom (void) +void m_clear_random(void) { - rndindex = prndindex = 0; + rndindex = prndindex = 0; } -// inspired by the same routine in Eternity, thanks haleyjd -int P_SubRandom (void) +/* inspired by the same routine in Eternity, thanks haleyjd */ + +int p_sub_random(void) { - int r = P_Random(); - return r - P_Random(); + int r = p_random(); + return r - p_random(); } diff --git a/games/NXDoom/src/doom/m_random.h b/games/NXDoom/src/doom/m_random.h index 902691f1d5f..f5f5cf74a37 100644 --- a/games/NXDoom/src/doom/m_random.h +++ b/games/NXDoom/src/doom/m_random.h @@ -1,40 +1,50 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/m_random.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ #ifndef __M_RANDOM__ #define __M_RANDOM__ +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "doomtype.h" +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Returns a number from 0 to 255, from a lookup table. */ + +int m_random(void); + +/* As m_random, but used only by the play simulation. */ + +int p_random(void); -// Returns a number from 0 to 255, -// from a lookup table. -int M_Random (void); +/* Fix randoms for demos. */ -// As M_Random, but used only by the play simulation. -int P_Random (void); +void m_clear_random(void); -// Fix randoms for demos. -void M_ClearRandom (void); +/* Defined version of p_random() - p_random() */ -// Defined version of P_Random() - P_Random() -int P_SubRandom (void); +int p_sub_random(void); -#endif +#endif /* __M_RANDOM__ */ diff --git a/games/NXDoom/src/doom/p_ceilng.c b/games/NXDoom/src/doom/p_ceilng.c index d1e61c898b4..582ad604e5b 100644 --- a/games/NXDoom/src/doom/p_ceilng.c +++ b/games/NXDoom/src/doom/p_ceilng.c @@ -1,324 +1,327 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising) -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_ceilng.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: Ceiling aninmation (lowering, crushing, raising) + * + ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include "z_zone.h" #include "doomdef.h" #include "p_local.h" +#include "z_zone.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* State. */ -// State. #include "doomstat.h" #include "r_state.h" -// Data. -#include "sounds.h" - -// -// CEILINGS -// +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* CEILINGS */ -ceiling_t* activeceilings[MAXCEILINGS]; +ceiling_t *activeceilings[MAXCEILINGS]; +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -// T_MoveCeiling -// +/* t_move_ceiling */ -void T_MoveCeiling (ceiling_t* ceiling) +void t_move_ceiling(ceiling_t *ceiling) { - result_e res; - - switch(ceiling->direction) + result_e res; + + switch (ceiling->direction) { - case 0: - // IN STASIS - break; - case 1: - // UP - res = T_MovePlane(ceiling->sector, - ceiling->speed, - ceiling->topheight, - false,1,ceiling->direction); - - if (!(leveltime&7)) - { - switch(ceiling->type) - { - case silentCrushAndRaise: - break; - default: - S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); - // ? - break; - } - } - - if (res == pastdest) - { - switch(ceiling->type) - { - case raiseToHighest: - P_RemoveActiveCeiling(ceiling); - break; - - case silentCrushAndRaise: - S_StartSound(&ceiling->sector->soundorg, sfx_pstop); - case fastCrushAndRaise: - case crushAndRaise: - ceiling->direction = -1; - break; - - default: - break; - } - - } - break; - - case -1: - // DOWN - res = T_MovePlane(ceiling->sector, - ceiling->speed, - ceiling->bottomheight, - ceiling->crush,1,ceiling->direction); - - if (!(leveltime&7)) - { - switch(ceiling->type) - { - case silentCrushAndRaise: break; - default: - S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); - } - } - - if (res == pastdest) - { - switch(ceiling->type) - { - case silentCrushAndRaise: - S_StartSound(&ceiling->sector->soundorg, sfx_pstop); - case crushAndRaise: - ceiling->speed = CEILSPEED; - case fastCrushAndRaise: - ceiling->direction = 1; - break; - - case lowerAndCrush: - case lowerToFloor: - P_RemoveActiveCeiling(ceiling); - break; - - default: - break; - } - } - else // ( res != pastdest ) - { - if (res == crushed) - { - switch(ceiling->type) - { - case silentCrushAndRaise: - case crushAndRaise: - case lowerAndCrush: - ceiling->speed = CEILSPEED / 8; - break; - - default: - break; - } - } - } - break; + case 0: /* IN STASIS */ + break; + case 1: /* UP */ + res = t_move_plane(ceiling->sector, ceiling->speed, ceiling->topheight, + false, 1, ceiling->direction); + + if (!(leveltime & 7)) + { + switch (ceiling->type) + { + case CEIL_SILENTCRUSHANDRAISE: + break; + default: +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&ceiling->sector->soundorg, SFX_STNMOV); +#endif + /* ? */ + + break; + } + } + + if (res == pastdest) + { + switch (ceiling->type) + { + case CEIL_RAISETOHIGHEST: + p_remove_active_ceiling(ceiling); + break; + + case CEIL_SILENTCRUSHANDRAISE: +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&ceiling->sector->soundorg, SFX_PSTOP); +#endif + case CEIL_FASTCRUSHANDRAISE: + case CEIL_CRUSHANDRAISE: + ceiling->direction = -1; + break; + + default: + break; + } + } + break; + + case -1: /* DOWN */ + res = t_move_plane(ceiling->sector, ceiling->speed, + ceiling->bottomheight, ceiling->crush, 1, ceiling->direction); + + if (!(leveltime & 7)) + { + switch (ceiling->type) + { + case CEIL_SILENTCRUSHANDRAISE: + break; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + default: + s_start_sound(&ceiling->sector->soundorg, SFX_STNMOV); +#else + default: + break; +#endif + } + } + + if (res == pastdest) + { + switch (ceiling->type) + { + case CEIL_SILENTCRUSHANDRAISE: +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&ceiling->sector->soundorg, SFX_PSTOP); +#endif + case CEIL_CRUSHANDRAISE: + ceiling->speed = CEILSPEED; + case CEIL_FASTCRUSHANDRAISE: + ceiling->direction = 1; + break; + + case CEIL_LOWERANDCRUSH: + case CEIL_LOWERTOFLOOR: + p_remove_active_ceiling(ceiling); + break; + + default: + break; + } + } + else /* ( res != pastdest ) */ + { + if (res == crushed) + { + switch (ceiling->type) + { + case CEIL_SILENTCRUSHANDRAISE: + case CEIL_CRUSHANDRAISE: + case CEIL_LOWERANDCRUSH: + ceiling->speed = CEILSPEED / 8; + break; + + default: + break; + } + } + } + break; } } +/* ev_do_ceiling + * Move a ceiling up/down and all around! + */ -// -// EV_DoCeiling -// Move a ceiling up/down and all around! -// -int -EV_DoCeiling -( line_t* line, - ceiling_e type ) +int ev_do_ceiling(line_t *line, ceiling_e type) { - int secnum; - int rtn; - sector_t* sec; - ceiling_t* ceiling; - - secnum = -1; - rtn = 0; - - // Reactivate in-stasis ceilings...for certain types. - switch(type) + int secnum; + int rtn; + sector_t *sec; + ceiling_t *ceiling; + + secnum = -1; + rtn = 0; + + /* Reactivate in-stasis ceilings... for certain types. */ + + switch (type) { - case fastCrushAndRaise: - case silentCrushAndRaise: - case crushAndRaise: - P_ActivateInStasisCeiling(line); - default: - break; + case CEIL_FASTCRUSHANDRAISE: + case CEIL_SILENTCRUSHANDRAISE: + case CEIL_CRUSHANDRAISE: + p_activate_in_stasis_ceiling(line); + default: + break; } - - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - // new door thinker - rtn = 1; - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); - P_AddThinker (&ceiling->thinker); - sec->specialdata = ceiling; - ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; - ceiling->sector = sec; - ceiling->crush = false; - - switch(type) - { - case fastCrushAndRaise: - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); - ceiling->direction = -1; - ceiling->speed = CEILSPEED * 2; - break; - - case silentCrushAndRaise: - case crushAndRaise: - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - case lowerAndCrush: - case lowerToFloor: - ceiling->bottomheight = sec->floorheight; - if (type != lowerToFloor) - ceiling->bottomheight += 8*FRACUNIT; - ceiling->direction = -1; - ceiling->speed = CEILSPEED; - break; - - case raiseToHighest: - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - ceiling->speed = CEILSPEED; - break; - } - - ceiling->tag = sec->tag; - ceiling->type = type; - P_AddActiveCeiling(ceiling); + sec = §ors[secnum]; + if (sec->specialdata) continue; + + /* new door thinker */ + + rtn = 1; + ceiling = z_malloc(sizeof(*ceiling), PU_LEVSPEC, 0); + p_add_thinker(&ceiling->thinker); + sec->specialdata = ceiling; + ceiling->thinker.function.acp1 = (actionf_p1)t_move_ceiling; + ceiling->sector = sec; + ceiling->crush = false; + + switch (type) + { + case CEIL_FASTCRUSHANDRAISE: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT); + ceiling->direction = -1; + ceiling->speed = CEILSPEED * 2; + break; + + case CEIL_SILENTCRUSHANDRAISE: + case CEIL_CRUSHANDRAISE: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + case CEIL_LOWERANDCRUSH: + case CEIL_LOWERTOFLOOR: + ceiling->bottomheight = sec->floorheight; + if (type != CEIL_LOWERTOFLOOR) + { + ceiling->bottomheight += 8 * FRACUNIT; + } + + ceiling->direction = -1; + ceiling->speed = CEILSPEED; + break; + + case CEIL_RAISETOHIGHEST: + ceiling->topheight = p_find_heighest_ceiling_surrounding(sec); + ceiling->direction = 1; + ceiling->speed = CEILSPEED; + break; + } + + ceiling->tag = sec->tag; + ceiling->type = type; + p_add_active_ceiling(ceiling); } - return rtn; + + return rtn; } +/* Add an active ceiling */ -// -// Add an active ceiling -// -void P_AddActiveCeiling(ceiling_t* c) +void p_add_active_ceiling(ceiling_t *c) { - int i; - - for (i = 0; i < MAXCEILINGS;i++) + int i; + + for (i = 0; i < MAXCEILINGS; i++) { - if (activeceilings[i] == NULL) - { - activeceilings[i] = c; - return; - } + if (activeceilings[i] == NULL) + { + activeceilings[i] = c; + return; + } } } +/* Remove a ceiling's thinker */ - -// -// Remove a ceiling's thinker -// -void P_RemoveActiveCeiling(ceiling_t* c) +void p_remove_active_ceiling(ceiling_t *c) { - int i; - - for (i = 0;i < MAXCEILINGS;i++) + int i; + + for (i = 0; i < MAXCEILINGS; i++) { - if (activeceilings[i] == c) - { - activeceilings[i]->sector->specialdata = NULL; - P_RemoveThinker (&activeceilings[i]->thinker); - activeceilings[i] = NULL; - break; - } + if (activeceilings[i] == c) + { + activeceilings[i]->sector->specialdata = NULL; + p_remove_thinker(&activeceilings[i]->thinker); + activeceilings[i] = NULL; + break; + } } } +/* Restart a ceiling that's in-stasis */ - -// -// Restart a ceiling that's in-stasis -// -void P_ActivateInStasisCeiling(line_t* line) +void p_activate_in_stasis_ceiling(line_t *line) { - int i; - - for (i = 0;i < MAXCEILINGS;i++) + int i; + + for (i = 0; i < MAXCEILINGS; i++) { - if (activeceilings[i] - && (activeceilings[i]->tag == line->tag) - && (activeceilings[i]->direction == 0)) - { - activeceilings[i]->direction = activeceilings[i]->olddirection; - activeceilings[i]->thinker.function.acp1 - = (actionf_p1)T_MoveCeiling; - } + if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && + (activeceilings[i]->direction == 0)) + { + activeceilings[i]->direction = activeceilings[i]->olddirection; + activeceilings[i]->thinker.function.acp1 = + (actionf_p1)t_move_ceiling; + } } } +/* ev_ceiling_crush_stop + * Stop a ceiling from crushing! + */ - -// -// EV_CeilingCrushStop -// Stop a ceiling from crushing! -// -int EV_CeilingCrushStop(line_t *line) +int ev_ceiling_crush_stop(line_t *line) { - int i; - int rtn; - - rtn = 0; - for (i = 0;i < MAXCEILINGS;i++) + int i; + int rtn; + + rtn = 0; + for (i = 0; i < MAXCEILINGS; i++) { - if (activeceilings[i] - && (activeceilings[i]->tag == line->tag) - && (activeceilings[i]->direction != 0)) - { - activeceilings[i]->olddirection = activeceilings[i]->direction; - activeceilings[i]->thinker.function.acv = (actionf_v)NULL; - activeceilings[i]->direction = 0; // in-stasis - rtn = 1; - } + if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && + (activeceilings[i]->direction != 0)) + { + activeceilings[i]->olddirection = activeceilings[i]->direction; + activeceilings[i]->thinker.function.acv = (actionf_v)NULL; + activeceilings[i]->direction = 0; /* in-stasis */ + rtn = 1; + } } - - return rtn; + return rtn; } diff --git a/games/NXDoom/src/doom/p_doors.c b/games/NXDoom/src/doom/p_doors.c index b0947248abe..324fefa4bec 100644 --- a/games/NXDoom/src/doom/p_doors.c +++ b/games/NXDoom/src/doom/p_doors.c @@ -1,779 +1,802 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Door animation code (opening/closing) -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_doors.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: Door animation code (opening/closing) + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - -#include "z_zone.h" -#include "doomdef.h" #include "deh_main.h" -#include "p_local.h" +#include "doomdef.h" #include "i_system.h" +#include "p_local.h" +#include "z_zone.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif +/* State. */ -// State. #include "doomstat.h" #include "r_state.h" -// Data. +/* Data. */ + #include "dstrings.h" -#include "sounds.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Sliding door frame information */ #if 0 -// -// Sliding door frame information -// -slidename_t slideFrameNames[MAXSLIDEDOORS] = +slidename_t g_slide_frame_names[MAXSLIDEDOORS] = { - {"GDOORF1","GDOORF2","GDOORF3","GDOORF4", // front - "GDOORB1","GDOORB2","GDOORB3","GDOORB4"}, // back - - {"\0","\0","\0","\0"} +{ + "GDOORF1", "GDOORF2", "GDOORF3", "GDOORF4", /* front */ + "GDOORB1", "GDOORB2", "GDOORB3", "GDOORB4" /* back */ +}, +{ + "\0", "\0", "\0", "\0" +} }; + +slideframe_t g_slide_frames[MAXSLIDEDOORS]; #endif +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -// VERTICAL DOORS -// +/* VERTICAL DOORS */ -// -// T_VerticalDoor -// -void T_VerticalDoor (vldoor_t* door) +void t_vertical_door(vldoor_t *door) { - result_e res; - - switch(door->direction) + result_e res; + + switch (door->direction) { - case 0: - // WAITING - if (!--door->topcountdown) - { - switch(door->type) - { - case vld_blazeRaise: - door->direction = -1; // time to go back down - S_StartSound(&door->sector->soundorg, sfx_bdcls); - break; - - case vld_normal: - door->direction = -1; // time to go back down - S_StartSound(&door->sector->soundorg, sfx_dorcls); - break; - - case vld_close30ThenOpen: - door->direction = 1; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - - default: - break; - } - } - break; - - case 2: - // INITIAL WAIT - if (!--door->topcountdown) - { - switch(door->type) - { - case vld_raiseIn5Mins: - door->direction = 1; - door->type = vld_normal; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - - default: - break; - } - } - break; - - case -1: - // DOWN - res = T_MovePlane(door->sector, - door->speed, - door->sector->floorheight, - false,1,door->direction); - if (res == pastdest) - { - switch(door->type) - { - case vld_blazeRaise: - case vld_blazeClose: - door->sector->specialdata = NULL; - P_RemoveThinker (&door->thinker); // unlink and free - S_StartSound(&door->sector->soundorg, sfx_bdcls); - break; - - case vld_normal: - case vld_close: - door->sector->specialdata = NULL; - P_RemoveThinker (&door->thinker); // unlink and free - break; - - case vld_close30ThenOpen: - door->direction = 0; - door->topcountdown = TICRATE*30; - break; - - default: - break; - } - } - else if (res == crushed) - { - switch(door->type) - { - case vld_blazeClose: - case vld_close: // DO NOT GO BACK UP! - break; - - default: - door->direction = 1; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - } - } - break; - - case 1: - // UP - res = T_MovePlane(door->sector, - door->speed, - door->topheight, - false,1,door->direction); - - if (res == pastdest) - { - switch(door->type) - { - case vld_blazeRaise: - case vld_normal: - door->direction = 0; // wait at top - door->topcountdown = door->topwait; - break; - - case vld_close30ThenOpen: - case vld_blazeOpen: - case vld_open: - door->sector->specialdata = NULL; - P_RemoveThinker (&door->thinker); // unlink and free - break; - - default: - break; - } - } - break; + case 0: /* WAITING */ + if (!--door->topcountdown) + { + switch (door->type) + { + case VLD_BLAZERAISE: + door->direction = -1; /* time to go back down */ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_BDCLS); +#endif + break; + + case VLD_NORMAL: + door->direction = -1; /* time to go back down */ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_DORCLS); +#endif + break; + + case VLD_CLOSE30THENOPEN: + door->direction = 1; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_DOROPN); +#endif + break; + + default: + break; + } + } + break; + + case 2: /* INITIAL WAIT */ + if (!--door->topcountdown) + { + switch (door->type) + { + case VLD_RAISEIN5MINS: + door->direction = 1; + door->type = VLD_NORMAL; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_DOROPN); +#endif + break; + + default: + break; + } + } + + break; + + case -1: /* DOWN */ + res = t_move_plane(door->sector, door->speed, + door->sector->floorheight, false, 1, door->direction); + + if (res == pastdest) + { + switch (door->type) + { + case VLD_BLAZERAISE: + case VLD_BLAZECLOSE: + door->sector->specialdata = NULL; + p_remove_thinker(&door->thinker); /* unlink and free */ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_BDCLS); +#endif + break; + + case VLD_NORMAL: + case VLD_CLOSE: + door->sector->specialdata = NULL; + p_remove_thinker(&door->thinker); /* unlink and free */ + break; + + case VLD_CLOSE30THENOPEN: + door->direction = 0; + door->topcountdown = TICRATE * 30; + break; + + default: + break; + } + } + else if (res == crushed) + { + switch (door->type) + { + case VLD_BLAZECLOSE: + case VLD_CLOSE: /* DO NOT GO BACK UP! */ + break; + + default: + door->direction = 1; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_DOROPN); +#endif + break; + } + } + break; + + case 1: /* UP */ + res = t_move_plane(door->sector, door->speed, door->topheight, + false, 1, door->direction); + + if (res == pastdest) + { + switch (door->type) + { + case VLD_BLAZERAISE: + case VLD_NORMAL: + door->direction = 0; /* wait at top */ + door->topcountdown = door->topwait; + break; + + case VLD_CLOSE30THENOPEN: + case VLD_BLAZEOPEN: + case VLD_OPEN: + door->sector->specialdata = NULL; + p_remove_thinker(&door->thinker); /* unlink and free */ + break; + + default: + break; + } + } + + break; } } +/* ev_do_locked_door + * Move a locked door up/down + */ -// -// EV_DoLockedDoor -// Move a locked door up/down -// - -int -EV_DoLockedDoor -( line_t* line, - vldoor_e type, - mobj_t* thing ) +int ev_do_locked_door(line_t *line, vldoor_e type, mobj_t *thing) { - player_t* p; - - p = thing->player; - - if (!p) - return 0; - - switch(line->special) + player_t *p; + + p = thing->player; + + if (!p) return 0; + + switch (line->special) { - case 99: // Blue Lock - case 133: - if (!p->cards[it_bluecard] && !p->cards[it_blueskull]) - { - p->message = DEH_String(PD_BLUEO); - S_StartSound(NULL,sfx_oof); - return 0; - } - break; - - case 134: // Red Lock - case 135: - if (!p->cards[it_redcard] && !p->cards[it_redskull]) - { - p->message = DEH_String(PD_REDO); - S_StartSound(NULL,sfx_oof); - return 0; - } - break; - - case 136: // Yellow Lock - case 137: - if (!p->cards[it_yellowcard] && - !p->cards[it_yellowskull]) - { - p->message = DEH_String(PD_YELLOWO); - S_StartSound(NULL,sfx_oof); - return 0; - } - break; + case 99: /* Blue Lock */ + case 133: + if (!p->cards[it_bluecard] && !p->cards[it_blueskull]) + { + p->message = (PD_BLUEO); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return 0; + } + break; + + case 134: /* Red Lock */ + case 135: + if (!p->cards[it_redcard] && !p->cards[it_redskull]) + { + p->message = (PD_REDO); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return 0; + } + break; + + case 136: /* Yellow Lock */ + case 137: + if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull]) + { + p->message = (PD_YELLOWO); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return 0; + } + + break; } - return EV_DoDoor(line,type); + return ev_do_door(line, type); } - -int -EV_DoDoor -( line_t* line, - vldoor_e type ) +int ev_do_door(line_t *line, vldoor_e type) { - int secnum,rtn; - sector_t* sec; - vldoor_t* door; - - secnum = -1; - rtn = 0; - - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + int secnum; + int rtn; + sector_t *sec; + vldoor_t *door; + + secnum = -1; + rtn = 0; + + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - - // new door thinker - rtn = 1; - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); - sec->specialdata = door; - - door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; - door->sector = sec; - door->type = type; - door->topwait = VDOORWAIT; - door->speed = VDOORSPEED; - - switch(type) - { - case vld_blazeClose: - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->direction = -1; - door->speed = VDOORSPEED * 4; - S_StartSound(&door->sector->soundorg, sfx_bdcls); - break; - - case vld_close: - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->direction = -1; - S_StartSound(&door->sector->soundorg, sfx_dorcls); - break; - - case vld_close30ThenOpen: - door->topheight = sec->ceilingheight; - door->direction = -1; - S_StartSound(&door->sector->soundorg, sfx_dorcls); - break; - - case vld_blazeRaise: - case vld_blazeOpen: - door->direction = 1; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->speed = VDOORSPEED * 4; - if (door->topheight != sec->ceilingheight) - S_StartSound(&door->sector->soundorg, sfx_bdopn); - break; - - case vld_normal: - case vld_open: - door->direction = 1; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - if (door->topheight != sec->ceilingheight) - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - - default: - break; - } - + sec = §ors[secnum]; + if (sec->specialdata) continue; + + /* new door thinker */ + + rtn = 1; + door = z_malloc(sizeof(*door), PU_LEVSPEC, 0); + p_add_thinker(&door->thinker); + sec->specialdata = door; + + door->thinker.function.acp1 = (actionf_p1)t_vertical_door; + door->sector = sec; + door->type = type; + door->topwait = VDOORWAIT; + door->speed = VDOORSPEED; + + switch (type) + { + case VLD_BLAZECLOSE: + door->topheight = p_find_lowest_ceiling_surrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->direction = -1; + door->speed = VDOORSPEED * 4; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_BDCLS); +#endif + break; + + case VLD_CLOSE: + door->topheight = p_find_lowest_ceiling_surrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->direction = -1; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_DORCLS); +#endif + break; + + case VLD_CLOSE30THENOPEN: + door->topheight = sec->ceilingheight; + door->direction = -1; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&door->sector->soundorg, SFX_DORCLS); +#endif + break; + + case VLD_BLAZERAISE: + case VLD_BLAZEOPEN: + door->direction = 1; + door->topheight = p_find_lowest_ceiling_surrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->speed = VDOORSPEED * 4; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (door->topheight != sec->ceilingheight) + s_start_sound(&door->sector->soundorg, SFX_BDOPN); +#endif + break; + + case VLD_NORMAL: + case VLD_OPEN: + door->direction = 1; + door->topheight = p_find_lowest_ceiling_surrounding(sec); + door->topheight -= 4 * FRACUNIT; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (door->topheight != sec->ceilingheight) + s_start_sound(&door->sector->soundorg, SFX_DOROPN); +#endif + break; + + default: + break; + } } - return rtn; + + return rtn; } +/* ev_vertical_door : open a door manually, no tag value */ -// -// EV_VerticalDoor : open a door manually, no tag value -// -void -EV_VerticalDoor -( line_t* line, - mobj_t* thing ) +void ev_vertical_door(line_t *line, mobj_t *thing) { - player_t* player; - sector_t* sec; - vldoor_t* door; - int side; - - side = 0; // only front sides can be used - - // Check for locks - player = thing->player; - - switch(line->special) + player_t *player; + sector_t *sec; + vldoor_t *door; + int side; + + side = 0; /* only front sides can be used */ + + /* Check for locks */ + + player = thing->player; + + switch (line->special) { - case 26: // Blue Lock - case 32: - if ( !player ) - return; - - if (!player->cards[it_bluecard] && !player->cards[it_blueskull]) - { - player->message = DEH_String(PD_BLUEK); - S_StartSound(NULL,sfx_oof); - return; - } - break; - - case 27: // Yellow Lock - case 34: - if ( !player ) - return; - - if (!player->cards[it_yellowcard] && - !player->cards[it_yellowskull]) - { - player->message = DEH_String(PD_YELLOWK); - S_StartSound(NULL,sfx_oof); - return; - } - break; - - case 28: // Red Lock - case 33: - if ( !player ) - return; - - if (!player->cards[it_redcard] && !player->cards[it_redskull]) - { - player->message = DEH_String(PD_REDK); - S_StartSound(NULL,sfx_oof); - return; - } - break; + case 26: /* Blue Lock */ + case 32: + if (!player) return; + + if (!player->cards[it_bluecard] && !player->cards[it_blueskull]) + { + player->message = (PD_BLUEK); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return; + } + break; + + case 27: /* Yellow Lock */ + case 34: + if (!player) return; + + if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull]) + { + player->message = (PD_YELLOWK); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return; + } + break; + + case 28: /* Red Lock */ + case 33: + if (!player) return; + + if (!player->cards[it_redcard] && !player->cards[it_redskull]) + { + player->message = (PD_REDK); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_OOF); +#endif + return; + } + break; } - - // if the sector has an active thinker, use it - if (line->sidenum[side^1] == -1) + /* if the sector has an active thinker, use it */ + + if (line->sidenum[side ^ 1] == -1) { - I_Error("EV_VerticalDoor: DR special type on 1-sided linedef"); + i_error("ev_vertical_door: DR special type on 1-sided linedef"); } - sec = sides[ line->sidenum[side^1]] .sector; + sec = sides[line->sidenum[side ^ 1]].sector; - if (sec->specialdata) + if (sec->specialdata) { - door = sec->specialdata; - switch(line->special) - { - case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s - case 26: - case 27: - case 28: - case 117: - if (door->direction == -1) - door->direction = 1; // go back up - else - { - if (!thing->player) - return; // JDC: bad guys never close doors - - // When is a door not a door? - // In Vanilla, door->direction is set, even though - // "specialdata" might not actually point at a door. - - if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor) + door = sec->specialdata; + switch (line->special) + { + case 1: /* ONLY FOR "RAISE" DOORS, NOT "OPEN"s */ + case 26: + case 27: + case 28: + case 117: + if (door->direction == -1) + door->direction = 1; /* go back up */ + else + { + if (!thing->player) return; /* JDC: bad guys never close doors */ + + /* When is a door not a door? + * In Vanilla, door->direction is set, even though + * "specialdata" might not actually point at a door. + */ + + if (door->thinker.function.acp1 == + (actionf_p1)t_vertical_door) { - door->direction = -1; // start going down immediately + door->direction = -1; /* start going down immediately */ } - else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise) + else if (door->thinker.function.acp1 == + (actionf_p1)t_plat_raise) { - // Erm, this is a plat, not a door. - // This notably causes a problem in ep1-0500.lmp where - // a plat and a door are cross-referenced; the door - // doesn't open on 64-bit. - // The direction field in vldoor_t corresponds to the wait - // field in plat_t. Let's set that to -1 instead. - - plat_t *plat; - - plat = (plat_t *) door; - plat->wait = -1; + /* Erm, this is a plat, not a door. + * This notably causes a problem in ep1-0500.lmp where + * a plat and a door are cross-referenced; the door + * doesn't open on 64-bit. + * The direction field in vldoor_t corresponds to the wait + * field in plat_t. Let's set that to -1 instead. + */ + + plat_t *plat; + + plat = (plat_t *)door; + plat->wait = -1; } - else + else { - // This isn't a door OR a plat. Now we're in trouble. + /* This isn't a door OR a plat. Now we're in trouble. */ - fprintf(stderr, "EV_VerticalDoor: Tried to close " - "something that wasn't a door.\n"); + fprintf(stderr, "ev_vertical_door: Tried to close " + "something that wasn't a door.\n"); - // Try closing it anyway. At least it will work on 32-bit - // machines. + /* Try closing it anyway. At least it will work on 32-bit + * machines. + */ - door->direction = -1; + door->direction = -1; } - } - return; - } + } + + return; + } } - - // for proper sound - switch(line->special) + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + /* for proper sound */ + + switch (line->special) { - case 117: // BLAZING DOOR RAISE - case 118: // BLAZING DOOR OPEN - S_StartSound(&sec->soundorg,sfx_bdopn); - break; - - case 1: // NORMAL DOOR SOUND - case 31: - S_StartSound(&sec->soundorg,sfx_doropn); - break; - - default: // LOCKED DOOR SOUND - S_StartSound(&sec->soundorg,sfx_doropn); - break; + case 117: /* BLAZING DOOR RAISE */ + case 118: /* BLAZING DOOR OPEN */ + s_start_sound(&sec->soundorg, SFX_BDOPN); + break; + + case 1: /* NORMAL DOOR SOUND */ + case 31: + s_start_sound(&sec->soundorg, SFX_DOROPN); + break; + + default: /* LOCKED DOOR SOUND */ + s_start_sound(&sec->soundorg, SFX_DOROPN); + break; } - - - // new door thinker - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); - sec->specialdata = door; - door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; - door->sector = sec; - door->direction = 1; - door->speed = VDOORSPEED; - door->topwait = VDOORWAIT; - - switch(line->special) +#endif + + /* new door thinker */ + + door = z_malloc(sizeof(*door), PU_LEVSPEC, 0); + p_add_thinker(&door->thinker); + sec->specialdata = door; + door->thinker.function.acp1 = (actionf_p1)t_vertical_door; + door->sector = sec; + door->direction = 1; + door->speed = VDOORSPEED; + door->topwait = VDOORWAIT; + + switch (line->special) { - case 1: - case 26: - case 27: - case 28: - door->type = vld_normal; - break; - - case 31: - case 32: - case 33: - case 34: - door->type = vld_open; - line->special = 0; - break; - - case 117: // blazing door raise - door->type = vld_blazeRaise; - door->speed = VDOORSPEED*4; - break; - case 118: // blazing door open - door->type = vld_blazeOpen; - line->special = 0; - door->speed = VDOORSPEED*4; - break; + case 1: + case 26: + case 27: + case 28: + door->type = VLD_NORMAL; + break; + + case 31: + case 32: + case 33: + case 34: + door->type = VLD_OPEN; + line->special = 0; + break; + + case 117: /* blazing door raise */ + door->type = VLD_BLAZERAISE; + door->speed = VDOORSPEED * 4; + break; + case 118: /* blazing door open */ + door->type = VLD_BLAZEOPEN; + line->special = 0; + door->speed = VDOORSPEED * 4; + break; } - - // find the top and bottom of the movement range - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; + + /* find the top and bottom of the movement range */ + + door->topheight = p_find_lowest_ceiling_surrounding(sec); + door->topheight -= 4 * FRACUNIT; } +/* Spawn a door that closes after 30 seconds */ -// -// Spawn a door that closes after 30 seconds -// -void P_SpawnDoorCloseIn30 (sector_t* sec) +void p_spawn_door_close_in30(sector_t *sec) { - vldoor_t* door; - - door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + vldoor_t *door; + + door = z_malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); + p_add_thinker(&door->thinker); - sec->specialdata = door; - sec->special = 0; + sec->specialdata = door; + sec->special = 0; - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - door->sector = sec; - door->direction = 0; - door->type = vld_normal; - door->speed = VDOORSPEED; - door->topcountdown = 30 * TICRATE; + door->thinker.function.acp1 = (actionf_p1)t_vertical_door; + door->sector = sec; + door->direction = 0; + door->type = VLD_NORMAL; + door->speed = VDOORSPEED; + door->topcountdown = 30 * TICRATE; } -// -// Spawn a door that opens after 5 minutes -// -void -P_SpawnDoorRaiseIn5Mins -( sector_t* sec, - int secnum ) +/* Spawn a door that opens after 5 minutes */ + +void p_spawn_door_raise_in_5min(sector_t *sec, int secnum) { - vldoor_t* door; - - door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); - - P_AddThinker (&door->thinker); - - sec->specialdata = door; - sec->special = 0; - - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - door->sector = sec; - door->direction = 2; - door->type = vld_raiseIn5Mins; - door->speed = VDOORSPEED; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->topwait = VDOORWAIT; - door->topcountdown = 5 * 60 * TICRATE; -} + vldoor_t *door; + + door = z_malloc(sizeof(*door), PU_LEVSPEC, 0); + p_add_thinker(&door->thinker); + sec->specialdata = door; + sec->special = 0; -// UNUSED -// Separate into p_slidoor.c? + door->thinker.function.acp1 = (actionf_p1)t_vertical_door; + door->sector = sec; + door->direction = 2; + door->type = VLD_RAISEIN5MINS; + door->speed = VDOORSPEED; + door->topheight = p_find_lowest_ceiling_surrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->topwait = VDOORWAIT; + door->topcountdown = 5 * 60 * TICRATE; +} -#if 0 // ABANDONED TO THE MISTS OF TIME!!! -// -// EV_SlidingDoor : slide a door horizontally -// (animate midtexture, then set noblocking line) -// +/* UNUSED + * Separate into p_slidoor.c? + */ +#if 0 /* ABANDONED TO THE MISTS OF TIME!!! */ -slideframe_t slideFrames[MAXSLIDEDOORS]; +/* ev_sliding_door : slide a door horizontally + * (animate midtexture, then set noblocking line) + */ -void P_InitSlidingDoorFrames(void) +void p_init_sliding_door_frames(void) { - int i; - int f1; - int f2; - int f3; - int f4; - - // DOOM II ONLY... - if ( gamemode != commercial) - return; - - for (i = 0;i < MAXSLIDEDOORS; i++) + int i; + int f1; + int f2; + int f3; + int f4; + + /* DOOM II ONLY... */ + + if (gamemode != commercial) return; + + for (i = 0; i < MAXSLIDEDOORS; i++) { - if (!slideFrameNames[i].frontFrame1[0]) - break; - - f1 = R_TextureNumForName(slideFrameNames[i].frontFrame1); - f2 = R_TextureNumForName(slideFrameNames[i].frontFrame2); - f3 = R_TextureNumForName(slideFrameNames[i].frontFrame3); - f4 = R_TextureNumForName(slideFrameNames[i].frontFrame4); - - slideFrames[i].frontFrames[0] = f1; - slideFrames[i].frontFrames[1] = f2; - slideFrames[i].frontFrames[2] = f3; - slideFrames[i].frontFrames[3] = f4; - - f1 = R_TextureNumForName(slideFrameNames[i].backFrame1); - f2 = R_TextureNumForName(slideFrameNames[i].backFrame2); - f3 = R_TextureNumForName(slideFrameNames[i].backFrame3); - f4 = R_TextureNumForName(slideFrameNames[i].backFrame4); - - slideFrames[i].backFrames[0] = f1; - slideFrames[i].backFrames[1] = f2; - slideFrames[i].backFrames[2] = f3; - slideFrames[i].backFrames[3] = f4; + if (!g_slide_frame_names[i].front_frame1[0]) break; + + f1 = r_texture_num_for_name(g_slide_frame_names[i].front_frame1); + f2 = r_texture_num_for_name(g_slide_frame_names[i].front_frame2); + f3 = r_texture_num_for_name(g_slide_frame_names[i].front_frame3); + f4 = r_texture_num_for_name(g_slide_frame_names[i].front_frame4); + + g_slide_frames[i].front_frames[0] = f1; + g_slide_frames[i].front_frames[1] = f2; + g_slide_frames[i].front_frames[2] = f3; + g_slide_frames[i].front_frames[3] = f4; + + f1 = r_texture_num_for_name(g_slide_frame_names[i].back_frame1); + f2 = r_texture_num_for_name(g_slide_frame_names[i].back_frame2); + f3 = r_texture_num_for_name(g_slide_frame_names[i].back_frame3); + f4 = r_texture_num_for_name(g_slide_frame_names[i].back_frame4); + + g_slide_frames[i].back_frames[0] = f1; + g_slide_frames[i].back_frames[1] = f2; + g_slide_frames[i].back_frames[2] = f3; + g_slide_frames[i].back_frames[3] = f4; } } +/* Return index into "g_slide_frames" array for which door type to use */ -// -// Return index into "slideFrames" array -// for which door type to use -// -int P_FindSlidingDoorType(line_t* line) +static int p_find_sliding_door(line_t *line) { - int i; - int val; - - for (i = 0;i < MAXSLIDEDOORS;i++) + int i; + int val; + + for (i = 0; i < MAXSLIDEDOORS; i++) { - val = sides[line->sidenum[0]].midtexture; - if (val == slideFrames[i].frontFrames[0]) - return i; + val = sides[line->sidenum[0]].midtexture; + if (val == g_slide_frames[i].front_frames[0]) return i; } - - return -1; + + return -1; } -void T_SlidingDoor (slidedoor_t* door) +static void t_sliding_door(slidedoor_t *door) { - switch(door->status) + switch (door->status) { - case sd_opening: - if (!door->timer--) - { - if (++door->frame == SNUMFRAMES) - { - // IF DOOR IS DONE OPENING... - sides[door->line->sidenum[0]].midtexture = 0; - sides[door->line->sidenum[1]].midtexture = 0; - door->line->flags &= ML_BLOCKING^0xff; - - if (door->type == sdt_openOnly) - { - door->frontsector->specialdata = NULL; - P_RemoveThinker (&door->thinker); - break; - } - - door->timer = SDOORWAIT; - door->status = sd_waiting; - } - else - { - // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... - door->timer = SWAITTICS; - - sides[door->line->sidenum[0]].midtexture = - slideFrames[door->whichDoorIndex]. - frontFrames[door->frame]; - sides[door->line->sidenum[1]].midtexture = - slideFrames[door->whichDoorIndex]. - backFrames[door->frame]; - } - } - break; - - case sd_waiting: - // IF DOOR IS DONE WAITING... - if (!door->timer--) - { - // CAN DOOR CLOSE? - if (door->frontsector->thinglist != NULL || - door->backsector->thinglist != NULL) - { - door->timer = SDOORWAIT; - break; - } - - //door->frame = SNUMFRAMES-1; - door->status = sd_closing; - door->timer = SWAITTICS; - } - break; - - case sd_closing: - if (!door->timer--) - { - if (--door->frame < 0) - { - // IF DOOR IS DONE CLOSING... - door->line->flags |= ML_BLOCKING; - door->frontsector->specialdata = NULL; - P_RemoveThinker (&door->thinker); - break; - } - else - { - // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... - door->timer = SWAITTICS; - - sides[door->line->sidenum[0]].midtexture = - slideFrames[door->whichDoorIndex]. - frontFrames[door->frame]; - sides[door->line->sidenum[1]].midtexture = - slideFrames[door->whichDoorIndex]. - backFrames[door->frame]; - } - } - break; + case sd_opening: + if (!door->timer--) + { + if (++door->frame == SNUMFRAMES) + { + /* IF DOOR IS DONE OPENING... */ + + sides[door->line->sidenum[0]].midtexture = 0; + sides[door->line->sidenum[1]].midtexture = 0; + door->line->flags &= ML_BLOCKING ^ 0xff; + + if (door->type == SDT_OPENONLY) + { + door->frontsector->specialdata = NULL; + p_remove_thinker(&door->thinker); + break; + } + + door->timer = SDOORWAIT; + door->status = sd_waiting; + } + else + { + /* IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... */ + + door->timer = SWAITTICS; + + sides[door->line->sidenum[0]].midtexture = + g_slide_frames[door->which_door_index] + .front_frames[door->frame]; + sides[door->line->sidenum[1]].midtexture = + g_slide_frames[door->which_door_index] + .back_frames[door->frame]; + } + } + break; + + case sd_waiting: + + /* IF DOOR IS DONE WAITING... */ + + if (!door->timer--) + { + /* CAN DOOR CLOSE? */ + + if (door->frontsector->thinglist != NULL || + door->backsector->thinglist != NULL) + { + door->timer = SDOORWAIT; + break; + } + + /* door->frame = SNUMFRAMES-1; */ + + door->status = sd_closing; + door->timer = SWAITTICS; + } + break; + + case sd_closing: + if (!door->timer--) + { + if (--door->frame < 0) + { + /* IF DOOR IS DONE CLOSING... */ + + door->line->flags |= ML_BLOCKING; + door->frontsector->specialdata = NULL; + p_remove_thinker(&door->thinker); + break; + } + else + { + /* IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... */ + + door->timer = SWAITTICS; + + sides[door->line->sidenum[0]].midtexture = + g_slide_frames[door->which_door_index] + .front_frames[door->frame]; + sides[door->line->sidenum[1]].midtexture = + g_slide_frames[door->which_door_index] + .back_frames[door->frame]; + } + } + break; } } +void ev_sliding_door(line_t *line, mobj_t *thing) +{ + sector_t *sec; + slidedoor_t *door; + /* DOOM II ONLY... */ -void -EV_SlidingDoor -( line_t* line, - mobj_t* thing ) -{ - sector_t* sec; - slidedoor_t* door; - - // DOOM II ONLY... - if (gamemode != commercial) - return; - - // Make sure door isn't already being animated - sec = line->frontsector; - door = NULL; - if (sec->specialdata) + if (gamemode != commercial) return; + + /* Make sure door isn't already being animated */ + + sec = line->frontsector; + door = NULL; + if (sec->specialdata) { - if (!thing->player) - return; - - door = sec->specialdata; - if (door->type == sdt_openAndClose) - { - if (door->status == sd_waiting) - door->status = sd_closing; - } - else - return; + if (!thing->player) return; + + door = sec->specialdata; + if (door->type == SDT_OPENANDCLOSE) + { + if (door->status == sd_waiting) door->status = sd_closing; + } + else + return; } - - // Init sliding door vars - if (!door) + + /* Init sliding door vars */ + + if (!door) { - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); - sec->specialdata = door; - - door->type = sdt_openAndClose; - door->status = sd_opening; - door->whichDoorIndex = P_FindSlidingDoorType(line); - - if (door->whichDoorIndex < 0) - I_Error("EV_SlidingDoor: Can't use texture for sliding door!"); - - door->frontsector = sec; - door->backsector = line->backsector; - door->thinker.function = T_SlidingDoor; - door->timer = SWAITTICS; - door->frame = 0; - door->line = line; + door = z_malloc(sizeof(*door), PU_LEVSPEC, 0); + p_add_thinker(&door->thinker); + sec->specialdata = door; + + door->type = SDT_OPENANDCLOSE; + door->status = sd_opening; + door->which_door_index = p_find_sliding_door(line); + + if (door->which_door_index < 0) + i_error("ev_sliding_door: Can't use texture for sliding door!"); + + door->frontsector = sec; + door->backsector = line->backsector; + door->thinker.function = t_sliding_door; + door->timer = SWAITTICS; + door->frame = 0; + door->line = line; } } -#endif +#endif /* UNUSED */ diff --git a/games/NXDoom/src/doom/p_enemy.c b/games/NXDoom/src/doom/p_enemy.c index c6acf390e78..cf10325afda 100644 --- a/games/NXDoom/src/doom/p_enemy.c +++ b/games/NXDoom/src/doom/p_enemy.c @@ -1,2024 +1,1932 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Enemy thinking, AI. -// Action Pointer Functions -// that are associated with states/frames. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_enemy.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Enemy thinking, AI. + * Action Pointer Functions + * that are associated with states/frames. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include -#include "m_random.h" #include "i_system.h" +#include "m_random.h" #include "doomdef.h" #include "p_local.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "g_game.h" -// State. +/* State. */ + #include "doomstat.h" #include "r_state.h" -// Data. -#include "sounds.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TRACEANGLE 0xc000000 +#define FATSPREAD (ANG90 / 8) +#define SKULLSPEED (20 * FRACUNIT) +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Data. */ typedef enum { - DI_EAST, - DI_NORTHEAST, - DI_NORTH, - DI_NORTHWEST, - DI_WEST, - DI_SOUTHWEST, - DI_SOUTH, - DI_SOUTHEAST, - DI_NODIR, - NUMDIRS - + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS } dirtype_t; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void a_fall(mobj_t *actor); +void a_refire(player_t *player, pspdef_t *psp); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* p_new_chase_dir related LUT. */ -// -// P_NewChaseDir related LUT. -// dirtype_t opposite[] = { - DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, - DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR + DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, + DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR, }; dirtype_t diags[] = { - DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST + DI_NORTHWEST, + DI_NORTHEAST, + DI_SOUTHWEST, + DI_SOUTHEAST, }; +/* ENEMY THINKING + * Enemies are always spawned with targetplayer = -1, threshold = 0 + * Most monsters are spawned unaware of all players, but some can be made + * preaware + */ +/* Called by p_noise_alert. + * Recursively traverse adjacent sectors, sound blocking lines cut off + * traversal. + */ +mobj_t *soundtarget; +fixed_t xspeed[8] = +{ + FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000, 0, 47000 +}; -void A_Fall (mobj_t *actor); +fixed_t yspeed[8] = +{ + 0, 47000, FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000 +}; +mobj_t *corpsehit; +mobj_t *vileobj; +fixed_t viletryx; +fixed_t viletryy; -// -// ENEMY THINKING -// Enemies are allways spawned -// with targetplayer = -1, threshold = 0 -// Most monsters are spawned unaware of all players, -// but some can be made preaware -// +mobj_t *braintargets[32]; +int numbraintargets; +int braintargeton = 0; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// -// Called by P_NoiseAlert. -// Recursively traverse adjacent sectors, -// sound blocking lines cut off traversal. -// +static void p_recursive_sound(sector_t *sec, int soundblocks) +{ + int i; + line_t *check; + sector_t *other; -mobj_t* soundtarget; + /* wake up all monsters in this sector */ -void -P_RecursiveSound -( sector_t* sec, - int soundblocks ) -{ - int i; - line_t* check; - sector_t* other; - - // wake up all monsters in this sector - if (sec->validcount == validcount - && sec->soundtraversed <= soundblocks+1) + if (sec->validcount == validcount && + sec->soundtraversed <= soundblocks + 1) { - return; // already flooded + return; /* already flooded */ } - - sec->validcount = validcount; - sec->soundtraversed = soundblocks+1; - sec->soundtarget = soundtarget; - - for (i=0 ;ilinecount ; i++) + + sec->validcount = validcount; + sec->soundtraversed = soundblocks + 1; + sec->soundtarget = soundtarget; + + for (i = 0; i < sec->linecount; i++) { - check = sec->lines[i]; - if (! (check->flags & ML_TWOSIDED) ) - continue; - - P_LineOpening (check); - - if (openrange <= 0) - continue; // closed door - - if ( sides[ check->sidenum[0] ].sector == sec) - other = sides[ check->sidenum[1] ] .sector; - else - other = sides[ check->sidenum[0] ].sector; - - if (check->flags & ML_SOUNDBLOCK) - { - if (!soundblocks) - P_RecursiveSound (other, 1); - } - else - P_RecursiveSound (other, soundblocks); - } -} + check = sec->lines[i]; + if (!(check->flags & ML_TWOSIDED)) continue; + p_line_opening(check); + if (openrange <= 0) continue; /* closed door */ -// -// P_NoiseAlert -// If a monster yells at a player, -// it will alert other monsters to the player. -// -void -P_NoiseAlert -( mobj_t* target, - mobj_t* emmiter ) -{ - soundtarget = target; - validcount++; - P_RecursiveSound (emmiter->subsector->sector, 0); + if (sides[check->sidenum[0]].sector == sec) + other = sides[check->sidenum[1]].sector; + else + other = sides[check->sidenum[0]].sector; + + if (check->flags & ML_SOUNDBLOCK) + { + if (!soundblocks) p_recursive_sound(other, 1); + } + else + p_recursive_sound(other, soundblocks); + } } +static boolean p_check_missile_range(mobj_t *actor) +{ + fixed_t dist; + if (!p_check_sight(actor, actor->target)) return false; + if (actor->flags & MF_JUSTHIT) + { + /* the target just hit the enemy, so fight back! */ -// -// P_CheckMeleeRange -// -boolean P_CheckMeleeRange (mobj_t* actor) -{ - mobj_t* pl; - fixed_t dist; - fixed_t range; - - if (!actor->target) - return false; - - pl = actor->target; - dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); + actor->flags &= ~MF_JUSTHIT; + return true; + } - if (gameversion < exe_doom_1_5) - range = MELEERANGE; - else - range = MELEERANGE-20*FRACUNIT+pl->info->radius; + if (actor->reactiontime) return false; /* do not attack yet */ - if (dist >= range) - return false; + /* OPTIMIZE: get this from a global checksight */ - - if (! P_CheckSight (actor, actor->target) ) - return false; - - return true; -} + dist = p_approx_distance(actor->x - actor->target->x, + actor->y - actor->target->y) - + 64 * FRACUNIT; -// -// P_CheckMissileRange -// -boolean P_CheckMissileRange (mobj_t* actor) -{ - fixed_t dist; - - if (! P_CheckSight (actor, actor->target) ) - return false; - - if ( actor->flags & MF_JUSTHIT ) - { - // the target just hit the enemy, - // so fight back! - actor->flags &= ~MF_JUSTHIT; - return true; - } - - if (actor->reactiontime) - return false; // do not attack yet - - // OPTIMIZE: get this from a global checksight - dist = P_AproxDistance ( actor->x-actor->target->x, - actor->y-actor->target->y) - 64*FRACUNIT; - - if (!actor->info->meleestate) - dist -= 128*FRACUNIT; // no melee attack, so fire more - - dist >>= FRACBITS; - - if (actor->type == MT_VILE) + if (!actor->info->meleestate) + dist -= 128 * FRACUNIT; /* no melee attack, so fire more */ + + dist >>= FRACBITS; + + if (actor->type == MT_VILE) { - if (dist > 14*64) - return false; // too far away + if (dist > 14 * 64) return false; /* too far away */ } - - if (actor->type == MT_UNDEAD) + if (actor->type == MT_UNDEAD) { - if (dist < 196) - return false; // close for fist attack - dist >>= 1; + if (dist < 196) return false; /* close for fist attack */ + dist >>= 1; } - - if (actor->type == MT_CYBORG - || actor->type == MT_SPIDER - || actor->type == MT_SKULL) + if (actor->type == MT_CYBORG || actor->type == MT_SPIDER || + actor->type == MT_SKULL) { - dist >>= 1; + dist >>= 1; } - - if (dist > 200) - dist = 200; - - if (actor->type == MT_CYBORG && dist > 160) - dist = 160; - - if (P_Random () < dist) - return false; - - return true; -} - - -// -// P_Move -// Move in the current direction, -// returns false if the move is blocked. -// -fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; -fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; - -boolean P_Move (mobj_t* actor) -{ - fixed_t tryx; - fixed_t tryy; - - line_t* ld; - - // warning: 'catch', 'throw', and 'try' - // are all C++ reserved words - boolean try_ok; - boolean good; - - if (actor->movedir == DI_NODIR) - return false; - - if ((unsigned)actor->movedir >= 8) - I_Error ("Weird actor->movedir!"); - - tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; - tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; - - try_ok = P_TryMove (actor, tryx, tryy); - - if (!try_ok) + + if (dist > 200) dist = 200; + + if (actor->type == MT_CYBORG && dist > 160) dist = 160; + + if (p_random() < dist) return false; + + return true; +} + +/* p_move + * Move in the current direction, returns false if the move is blocked. + */ + +static boolean p_move(mobj_t *actor) +{ + fixed_t tryx; + fixed_t tryy; + + line_t *ld; + + /* warning: 'catch', 'throw', and 'try' are all C++ reserved words */ + + boolean try_ok; + boolean good; + + if (actor->movedir == DI_NODIR) return false; + + if ((unsigned)actor->movedir >= 8) i_error("Weird actor->movedir!"); + + tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; + tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; + + try_ok = p_try_move(actor, tryx, tryy); + + if (!try_ok) { - // open any specials - if (actor->flags & MF_FLOAT && floatok) - { - // must adjust height - if (actor->z < tmfloorz) - actor->z += FLOATSPEED; - else - actor->z -= FLOATSPEED; - - actor->flags |= MF_INFLOAT; - return true; - } - - if (!numspechit) - return false; - - actor->movedir = DI_NODIR; - good = false; - while (numspechit--) - { - ld = spechit[numspechit]; - // if the special is not a door - // that can be opened, - // return false - if (P_UseSpecialLine (actor, ld,0)) - good = true; - } - return good; + /* open any specials */ + + if (actor->flags & MF_FLOAT && floatok) + { + /* must adjust height */ + + if (actor->z < tmfloorz) + actor->z += FLOATSPEED; + else + actor->z -= FLOATSPEED; + + actor->flags |= MF_INFLOAT; + return true; + } + + if (!numspechit) return false; + + actor->movedir = DI_NODIR; + good = false; + while (numspechit--) + { + ld = spechit[numspechit]; + + /* if the special is not a door that can be opened, return false */ + + if (p_use_special_line(actor, ld, 0)) good = true; + } + + return good; } - else + else { - actor->flags &= ~MF_INFLOAT; + actor->flags &= ~MF_INFLOAT; } - - - if (! (actor->flags & MF_FLOAT) ) - actor->z = actor->floorz; - return true; -} - - -// -// TryWalk -// Attempts to move actor on -// in its current (ob->moveangle) direction. -// If blocked by either a wall or an actor -// returns FALSE -// If move is either clear or blocked only by a door, -// returns TRUE and sets... -// If a door is in the way, -// an OpenDoor call is made to start it opening. -// -boolean P_TryWalk (mobj_t* actor) -{ - if (!P_Move (actor)) + + if (!(actor->flags & MF_FLOAT)) actor->z = actor->floorz; + return true; +} + +/* p_try_walk + * + * Attempts to move actor on in its current (ob->moveangle) direction. + * If blocked by either a wall or an actor returns FALSE + * If move is either clear or blocked only by a door, returns TRUE and + * sets... + * If a door is in the way, an OpenDoor call is made to start it opening. + */ + +static boolean p_try_walk(mobj_t *actor) +{ + if (!p_move(actor)) { - return false; + return false; } - actor->movecount = P_Random()&15; - return true; + actor->movecount = p_random() & 15; + return true; } +static void p_new_chase_dir(mobj_t *actor) +{ + fixed_t deltax; + fixed_t deltay; + + dirtype_t d[3]; + int tdir; + dirtype_t olddir; + dirtype_t turnaround; -void P_NewChaseDir (mobj_t* actor) -{ - fixed_t deltax; - fixed_t deltay; - - dirtype_t d[3]; - - int tdir; - dirtype_t olddir; - - dirtype_t turnaround; + if (!actor->target) i_error("p_new_chase_dir: called with no target"); + + olddir = actor->movedir; + turnaround = opposite[olddir]; - if (!actor->target) - I_Error ("P_NewChaseDir: called with no target"); - - olddir = actor->movedir; - turnaround=opposite[olddir]; + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; - deltax = actor->target->x - actor->x; - deltay = actor->target->y - actor->y; + if (deltax > 10 * FRACUNIT) + d[1] = DI_EAST; + else if (deltax < -10 * FRACUNIT) + d[1] = DI_WEST; + else + d[1] = DI_NODIR; - if (deltax>10*FRACUNIT) - d[1]= DI_EAST; - else if (deltax<-10*FRACUNIT) - d[1]= DI_WEST; - else - d[1]=DI_NODIR; + if (deltay < -10 * FRACUNIT) + d[2] = DI_SOUTH; + else if (deltay > 10 * FRACUNIT) + d[2] = DI_NORTH; + else + d[2] = DI_NODIR; - if (deltay<-10*FRACUNIT) - d[2]= DI_SOUTH; - else if (deltay>10*FRACUNIT) - d[2]= DI_NORTH; - else - d[2]=DI_NODIR; + /* try direct route */ - // try direct route - if (d[1] != DI_NODIR - && d[2] != DI_NODIR) + if (d[1] != DI_NODIR && d[2] != DI_NODIR) { - actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; - if (actor->movedir != (int) turnaround && P_TryWalk(actor)) - return; + actor->movedir = diags[((deltay < 0) << 1) + (deltax > 0)]; + if (actor->movedir != (int)turnaround && p_try_walk(actor)) return; } - // try other directions - if (P_Random() > 200 - || abs(deltay)>abs(deltax)) + /* try other directions */ + + if (p_random() > 200 || abs(deltay) > abs(deltax)) { - tdir=d[1]; - d[1]=d[2]; - d[2]=tdir; + tdir = d[1]; + d[1] = d[2]; + d[2] = tdir; } - if (d[1]==turnaround) - d[1]=DI_NODIR; - if (d[2]==turnaround) - d[2]=DI_NODIR; - - if (d[1]!=DI_NODIR) + if (d[1] == turnaround) d[1] = DI_NODIR; + if (d[2] == turnaround) d[2] = DI_NODIR; + + if (d[1] != DI_NODIR) { - actor->movedir = d[1]; - if (P_TryWalk(actor)) - { - // either moved forward or attacked - return; - } + actor->movedir = d[1]; + if (p_try_walk(actor)) + { + return; /* either moved forward or attacked */ + } } - if (d[2]!=DI_NODIR) + if (d[2] != DI_NODIR) { - actor->movedir =d[2]; + actor->movedir = d[2]; - if (P_TryWalk(actor)) - return; + if (p_try_walk(actor)) return; } - // there is no direct path to the player, - // so pick another direction. - if (olddir!=DI_NODIR) + /* there is no direct path to the player, so pick another direction. */ + + if (olddir != DI_NODIR) { - actor->movedir =olddir; + actor->movedir = olddir; - if (P_TryWalk(actor)) - return; + if (p_try_walk(actor)) return; } - // randomly determine direction of search - if (P_Random()&1) + /* randomly determine direction of search */ + + if (p_random() & 1) { - for ( tdir=DI_EAST; - tdir<=DI_SOUTHEAST; - tdir++ ) - { - if (tdir != (int) turnaround) - { - actor->movedir =tdir; - - if ( P_TryWalk(actor) ) - return; - } - } + for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) + { + if (tdir != (int)turnaround) + { + actor->movedir = tdir; + + if (p_try_walk(actor)) return; + } + } + } + else + { + for (tdir = DI_SOUTHEAST; tdir != (DI_EAST - 1); tdir--) + { + if (tdir != (int)turnaround) + { + actor->movedir = tdir; + + if (p_try_walk(actor)) return; + } + } } - else + + if (turnaround != DI_NODIR) { - for ( tdir=DI_SOUTHEAST; - tdir != (DI_EAST-1); - tdir-- ) - { - if (tdir != (int) turnaround) - { - actor->movedir = tdir; - - if ( P_TryWalk(actor) ) - return; - } - } + actor->movedir = turnaround; + if (p_try_walk(actor)) return; } - if (turnaround != DI_NODIR) + actor->movedir = DI_NODIR; /* can not move */ +} + +/* p_look_for_players + * If allaround is false, only look 180 degrees in front. Returns true if a + * player is targeted. + */ + +static boolean p_look_for_players(mobj_t *actor, boolean allaround) +{ + int c; + int stop; + player_t *player; + angle_t an; + fixed_t dist; + + c = 0; + stop = (actor->lastlook - 1) & 3; + + for (; ; actor->lastlook = (actor->lastlook + 1) & 3) { - actor->movedir =turnaround; - if ( P_TryWalk(actor) ) - return; + if (!playeringame[actor->lastlook]) continue; + + if (c++ == 2 || actor->lastlook == stop) + { + return false; /* done looking */ + } + + player = &players[actor->lastlook]; + + if (player->health <= 0) continue; /* dead */ + + if (!p_check_sight(actor, player->mo)) continue; /* out of sight */ + + if (!allaround) + { + an = r_point_to_angle2(actor->x, actor->y, player->mo->x, + player->mo->y) - + actor->angle; + + if (an > ANG90 && an < ANG270) + { + dist = p_approx_distance(player->mo->x - actor->x, + player->mo->y - actor->y); + + /* if real close, react anyway */ + + if (dist > MELEERANGE) continue; /* behind back */ + } + } + + actor->target = player->mo; + return true; } - actor->movedir = DI_NODIR; // can not move + return false; } +/* pit_vile_check + * Detect a corpse that could be raised. + */ + +static boolean pit_vile_check(mobj_t *thing) +{ + int maxdist; + boolean check; + + if (!(thing->flags & MF_CORPSE)) return true; /* not a monster */ + + if (thing->tics != -1) return true; /* not lying still yet */ + + if (thing->info->raisestate == S_NULL) + { + return true; /* monster doesn't have a raise state */ + } + + maxdist = thing->info->radius + mobjinfo[MT_VILE].radius; + + if (abs(thing->x - viletryx) > maxdist || + abs(thing->y - viletryy) > maxdist) + { + return true; /* not actually touching */ + } + + corpsehit = thing; + corpsehit->momx = corpsehit->momy = 0; + corpsehit->height <<= 2; + check = p_check_position(corpsehit, corpsehit->x, corpsehit->y); + corpsehit->height >>= 2; + + if (!check) return true; /* doesn't fit here */ + + return false; /* got one, so stop checking */ +} +/* Check whether the death of the specified monster type is allowed + * to trigger the end of episode special action. + * + * This behavior changed in v1.9, the most notable effect of which + * was to break uac_dead.wad + */ -// -// P_LookForPlayers -// If allaround is false, only look 180 degrees in front. -// Returns true if a player is targeted. -// -boolean -P_LookForPlayers -( mobj_t* actor, - boolean allaround ) +static boolean check_boss_end(mobjtype_t motype) { - int c; - int stop; - player_t* player; - angle_t an; - fixed_t dist; + if (gameversion < exe_ultimate) + { + if (gamemap != 8) + { + return false; + } + + /* Baron death on later episodes is nothing special. */ + + if (motype == MT_BRUISER && gameepisode != 1) + { + return false; + } - c = 0; - stop = (actor->lastlook-1)&3; - - for ( ; ; actor->lastlook = (actor->lastlook+1)&3 ) + return true; + } + else { - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2 - || actor->lastlook == stop) - { - // done looking - return false; - } - - player = &players[actor->lastlook]; - - if (player->health <= 0) - continue; // dead - - if (!P_CheckSight (actor, player->mo)) - continue; // out of sight - - if (!allaround) - { - an = R_PointToAngle2 (actor->x, - actor->y, - player->mo->x, - player->mo->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - dist = P_AproxDistance (player->mo->x - actor->x, - player->mo->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - - actor->target = player->mo; - return true; + /* New logic that appeared in Ultimate Doom. + * Looks like the logic was overhauled while adding in the + * episode 4 support. Now bosses only trigger on their + * specific episode. + */ + + switch (gameepisode) + { + case 1: + return gamemap == 8 && motype == MT_BRUISER; + + case 2: + return gamemap == 8 && motype == MT_CYBORG; + + case 3: + return gamemap == 8 && motype == MT_SPIDER; + + case 4: + return (gamemap == 6 && motype == MT_CYBORG) || + (gamemap == 8 && motype == MT_SPIDER); + + default: + return gamemap == 8; + } } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* p_noise_alert + * If a monster yells at a player, + * it will alert other monsters to the player. + */ + +void p_noise_alert(mobj_t *target, mobj_t *emmiter) +{ + soundtarget = target; + validcount++; + p_recursive_sound(emmiter->subsector->sector, 0); +} + +boolean p_check_melee_range(mobj_t *actor) +{ + mobj_t *pl; + fixed_t dist; + fixed_t range; - return false; + if (!actor->target) return false; + + pl = actor->target; + dist = p_approx_distance(pl->x - actor->x, pl->y - actor->y); + + if (gameversion < exe_doom_1_5) + range = MELEERANGE; + else + range = MELEERANGE - 20 * FRACUNIT + pl->info->radius; + + if (dist >= range) return false; + + if (!p_check_sight(actor, actor->target)) return false; + + return true; } +/* a_keen_die + * DOOM II special, map 32. Uses special tag 666. + */ -// -// A_KeenDie -// DOOM II special, map 32. -// Uses special tag 666. -// -void A_KeenDie (mobj_t* mo) +void a_keen_die(mobj_t *mo) { - thinker_t* th; - mobj_t* mo2; - line_t junk; + thinker_t *th; + mobj_t *mo2; + line_t junk; + + a_fall(mo); - A_Fall (mo); - - // scan the remaining thinkers - // to see if all Keens are dead - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + /* scan the remaining thinkers to see if all Keens are dead */ + + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2 != mo - && mo2->type == mo->type - && mo2->health > 0) - { - // other Keen not dead - return; - } + if (th->function.acp1 != (actionf_p1)p_mobj_thinker) continue; + + mo2 = (mobj_t *)th; + if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) + { + return; /* other Keen not dead */ + } } - junk.tag = 666; - EV_DoDoor(&junk, vld_open); + junk.tag = 666; + ev_do_door(&junk, VLD_OPEN); } +/* ACTION ROUTINES */ -// -// ACTION ROUTINES -// +/* a_look + * Stay in state until a player is sighted. + */ -// -// A_Look -// Stay in state until a player is sighted. -// -void A_Look (mobj_t* actor) +void a_look(mobj_t *actor) { - mobj_t* targ; - - actor->threshold = 0; // any shot will wake up - targ = actor->subsector->sector->soundtarget; + mobj_t *targ; + + actor->threshold = 0; /* any shot will wake up */ + targ = actor->subsector->sector->soundtarget; - if (targ - && (targ->flags & MF_SHOOTABLE) ) + if (targ && (targ->flags & MF_SHOOTABLE)) { - actor->target = targ; - - if ( actor->flags & MF_AMBUSH ) - { - if (P_CheckSight (actor, actor->target)) - goto seeyou; - } - else - goto seeyou; + actor->target = targ; + + if (actor->flags & MF_AMBUSH) + { + if (p_check_sight(actor, actor->target)) goto seeyou; + } + else + { + goto seeyou; + } } - - - if (!P_LookForPlayers (actor, false) ) - return; - - // go into chase state - seeyou: - if (actor->info->seesound) + + if (!p_look_for_players(actor, false)) return; + + /* go into chase state */ + +seeyou: +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (actor->info->seesound) { - int sound; - - switch (actor->info->seesound) - { - case sfx_posit1: - case sfx_posit2: - case sfx_posit3: - sound = sfx_posit1+P_Random()%3; - break; - - case sfx_bgsit1: - case sfx_bgsit2: - sound = sfx_bgsit1+P_Random()%2; - break; - - default: - sound = actor->info->seesound; - break; - } - - if (actor->type==MT_SPIDER - || actor->type == MT_CYBORG) - { - // full volume - S_StartSound (NULL, sound); - } - else - S_StartSound (actor, sound); + int sound; + + switch (actor->info->seesound) + { + case SFX_POSIT1: + case SFX_POSIT2: + case SFX_POSIT3: + sound = SFX_POSIT1 + p_random() % 3; + break; + + case SFX_BGSIT1: + case SFX_BGSIT2: + sound = SFX_BGSIT1 + p_random() % 2; + break; + + default: + sound = actor->info->seesound; + break; + } + + if (actor->type == MT_SPIDER || actor->type == MT_CYBORG) + { + /* full volume */ + + s_start_sound(NULL, sound); + } + else + s_start_sound(actor, sound); } +#endif - P_SetMobjState (actor, actor->info->seestate); + p_set_mobj_state(actor, actor->info->seestate); } +/* a_chase + * Actor has a melee attack, so it tries to close as fast as possible + */ -// -// A_Chase -// Actor has a melee attack, -// so it tries to close as fast as possible -// -void A_Chase (mobj_t* actor) +void a_chase(mobj_t *actor) { - int delta; + int delta; + + if (actor->reactiontime) actor->reactiontime--; - if (actor->reactiontime) - actor->reactiontime--; - + /* modify target threshold */ - // modify target threshold - if (actor->threshold) + if (actor->threshold) { - if (gameversion > exe_doom_1_2 && - (!actor->target || actor->target->health <= 0)) - { - actor->threshold = 0; - } - else - actor->threshold--; + if (gameversion > exe_doom_1_2 && + (!actor->target || actor->target->health <= 0)) + { + actor->threshold = 0; + } + else + actor->threshold--; } - - // turn towards movement direction if not there yet - if (actor->movedir < 8) + + /* turn towards movement direction if not there yet */ + + if (actor->movedir < 8) { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANG90/2; - else if (delta < 0) - actor->angle += ANG90/2; + actor->angle &= (7u << 29); + delta = actor->angle - (actor->movedir << 29); + + if (delta > 0) + actor->angle -= ANG90 / 2; + else if (delta < 0) + actor->angle += ANG90 / 2; } - if (!actor->target - || !(actor->target->flags&MF_SHOOTABLE)) + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { - // look for a new target - if (P_LookForPlayers(actor,true)) - return; // got a new target - - P_SetMobjState (actor, actor->info->spawnstate); - return; + /* look for a new target */ + + if (p_look_for_players(actor, true)) return; /* got a new target */ + + p_set_mobj_state(actor, actor->info->spawnstate); + return; } - - // do not attack twice in a row - if (actor->flags & MF_JUSTATTACKED) + + /* do not attack twice in a row */ + + if (actor->flags & MF_JUSTATTACKED) { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare && !fastparm) - P_NewChaseDir (actor); - return; + actor->flags &= ~MF_JUSTATTACKED; + if (gameskill != sk_nightmare && !fastparm) p_new_chase_dir(actor); + return; } - - // check for melee attack - if (actor->info->meleestate - && P_CheckMeleeRange (actor)) + + /* check for melee attack */ + + if (actor->info->meleestate && p_check_melee_range(actor)) { - if (actor->info->attacksound) - S_StartSound (actor, actor->info->attacksound); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (actor->info->attacksound) + s_start_sound(actor, actor->info->attacksound); +#endif - P_SetMobjState (actor, actor->info->meleestate); - return; + p_set_mobj_state(actor, actor->info->meleestate); + return; } - - // check for missile attack - if (actor->info->missilestate) + + /* check for missile attack */ + + if (actor->info->missilestate) { - if (gameskill < sk_nightmare - && !fastparm && actor->movecount) - { - goto nomissile; - } - - if (!P_CheckMissileRange (actor)) - goto nomissile; - - P_SetMobjState (actor, actor->info->missilestate); - actor->flags |= MF_JUSTATTACKED; - return; + if (gameskill < sk_nightmare && !fastparm && actor->movecount) + { + goto nomissile; + } + + if (!p_check_missile_range(actor)) goto nomissile; + + p_set_mobj_state(actor, actor->info->missilestate); + actor->flags |= MF_JUSTATTACKED; + return; } - // ? - nomissile: - // possibly choose another target - if (netgame - && !actor->threshold - && !P_CheckSight (actor, actor->target) ) + /* ? */ + +nomissile: + + /* possibly choose another target */ + + if (netgame && !actor->threshold && !p_check_sight(actor, actor->target)) { - if (P_LookForPlayers(actor,true)) - return; // got a new target + if (p_look_for_players(actor, true)) return; /* got a new target */ } - - // chase towards player - if (--actor->movecount<0 - || !P_Move (actor)) + + /* chase towards player */ + + if (--actor->movecount < 0 || !p_move(actor)) { - P_NewChaseDir (actor); + p_new_chase_dir(actor); } - - // make active sound - if (actor->info->activesound - && P_Random () < 3) + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + + /* make active sound */ + + if (actor->info->activesound && p_random() < 3) { - S_StartSound (actor, actor->info->activesound); + s_start_sound(actor, actor->info->activesound); } +#endif +} + +void a_face_target(mobj_t *actor) +{ + if (!actor->target) return; + + actor->flags &= ~MF_AMBUSH; + + actor->angle = r_point_to_angle2(actor->x, actor->y, actor->target->x, + actor->target->y); + + if (actor->target->flags & MF_SHADOW) actor->angle += p_sub_random() << 21; } +void a_pos_attack(mobj_t *actor) +{ + int angle; + int damage; + int slope; + + if (!actor->target) return; -// -// A_FaceTarget -// -void A_FaceTarget (mobj_t* actor) -{ - if (!actor->target) - return; - - actor->flags &= ~MF_AMBUSH; - - actor->angle = R_PointToAngle2 (actor->x, - actor->y, - actor->target->x, - actor->target->y); - - if (actor->target->flags & MF_SHADOW) - actor->angle += P_SubRandom() << 21; -} - - -// -// A_PosAttack -// -void A_PosAttack (mobj_t* actor) -{ - int angle; - int damage; - int slope; - - if (!actor->target) - return; - - A_FaceTarget (actor); - angle = actor->angle; - slope = P_AimLineAttack (actor, angle, MISSILERANGE); - - S_StartSound (actor, sfx_pistol); - angle += P_SubRandom() << 20; - damage = ((P_Random()%5)+1)*3; - P_LineAttack (actor, angle, MISSILERANGE, slope, damage); -} - -void A_SPosAttack (mobj_t* actor) -{ - int i; - int angle; - int bangle; - int damage; - int slope; - - if (!actor->target) - return; - - S_StartSound (actor, sfx_shotgn); - A_FaceTarget (actor); - bangle = actor->angle; - slope = P_AimLineAttack (actor, bangle, MISSILERANGE); - - for (i=0 ; i<3 ; i++) + a_face_target(actor); + angle = actor->angle; + slope = p_aim_line_attack(actor, angle, MISSILERANGE); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_PISTOL); +#endif + angle += p_sub_random() << 20; + damage = ((p_random() % 5) + 1) * 3; + p_line_attack(actor, angle, MISSILERANGE, slope, damage); +} + +void a_s_pos_attack(mobj_t *actor) +{ + int i; + int angle; + int bangle; + int damage; + int slope; + + if (!actor->target) return; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_SHOTGN); +#endif + a_face_target(actor); + bangle = actor->angle; + slope = p_aim_line_attack(actor, bangle, MISSILERANGE); + + for (i = 0; i < 3; i++) { - angle = bangle + (P_SubRandom() << 20); - damage = ((P_Random()%5)+1)*3; - P_LineAttack (actor, angle, MISSILERANGE, slope, damage); + angle = bangle + (p_sub_random() << 20); + damage = ((p_random() % 5) + 1) * 3; + p_line_attack(actor, angle, MISSILERANGE, slope, damage); } } -void A_CPosAttack (mobj_t* actor) +void a_c_pos_attack(mobj_t *actor) { - int angle; - int bangle; - int damage; - int slope; - - if (!actor->target) - return; + int angle; + int bangle; + int damage; + int slope; + + if (!actor->target) return; - S_StartSound (actor, sfx_shotgn); - A_FaceTarget (actor); - bangle = actor->angle; - slope = P_AimLineAttack (actor, bangle, MISSILERANGE); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_SHOTGN); +#endif + a_face_target(actor); + bangle = actor->angle; + slope = p_aim_line_attack(actor, bangle, MISSILERANGE); - angle = bangle + (P_SubRandom() << 20); - damage = ((P_Random()%5)+1)*3; - P_LineAttack (actor, angle, MISSILERANGE, slope, damage); + angle = bangle + (p_sub_random() << 20); + damage = ((p_random() % 5) + 1) * 3; + p_line_attack(actor, angle, MISSILERANGE, slope, damage); } -void A_CPosRefire (mobj_t* actor) -{ - // keep firing unless target got out of sight - A_FaceTarget (actor); +void a_c_pos_refire(mobj_t *actor) +{ + /* keep firing unless target got out of sight */ + + a_face_target(actor); - if (P_Random () < 40) - return; + if (p_random() < 40) return; - if (!actor->target - || actor->target->health <= 0 - || !P_CheckSight (actor, actor->target) ) + if (!actor->target || actor->target->health <= 0 || + !p_check_sight(actor, actor->target)) { - P_SetMobjState (actor, actor->info->seestate); + p_set_mobj_state(actor, actor->info->seestate); } } +void a_spid_refire(mobj_t *actor) +{ + /* keep firing unless target got out of sight */ -void A_SpidRefire (mobj_t* actor) -{ - // keep firing unless target got out of sight - A_FaceTarget (actor); + a_face_target(actor); - if (P_Random () < 10) - return; + if (p_random() < 10) return; - if (!actor->target - || actor->target->health <= 0 - || !P_CheckSight (actor, actor->target) ) + if (!actor->target || actor->target->health <= 0 || + !p_check_sight(actor, actor->target)) { - P_SetMobjState (actor, actor->info->seestate); + p_set_mobj_state(actor, actor->info->seestate); } } -void A_BspiAttack (mobj_t *actor) -{ - if (!actor->target) - return; - - A_FaceTarget (actor); +void a_bspi_attack(mobj_t *actor) +{ + if (!actor->target) return; + + a_face_target(actor); - // launch a missile - P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ); -} + /* launch a missile */ + p_spawn_missile(actor, actor->target, MT_ARACHPLAZ); +} -// -// A_TroopAttack -// -void A_TroopAttack (mobj_t* actor) +void a_troop_attack(mobj_t *actor) { - int damage; - - if (!actor->target) - return; - - A_FaceTarget (actor); - if (P_CheckMeleeRange (actor)) + int damage; + + if (!actor->target) return; + + a_face_target(actor); + if (p_check_melee_range(actor)) { - S_StartSound (actor, sfx_claw); - damage = (P_Random()%8+1)*3; - P_DamageMobj (actor->target, actor, actor, damage); - return; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_CLAW); +#endif + damage = (p_random() % 8 + 1) * 3; + p_damage_mobj(actor->target, actor, actor, damage); + return; } - - // launch a missile - P_SpawnMissile (actor, actor->target, MT_TROOPSHOT); -} + /* launch a missile */ + p_spawn_missile(actor, actor->target, MT_TROOPSHOT); +} -void A_SargAttack (mobj_t* actor) +void a_sarg_attack(mobj_t *actor) { - int damage; + int damage; + + if (!actor->target) return; - if (!actor->target) - return; - - A_FaceTarget (actor); + a_face_target(actor); - if (gameversion >= exe_doom_1_5) + if (gameversion >= exe_doom_1_5) { - if (!P_CheckMeleeRange (actor)) - return; + if (!p_check_melee_range(actor)) return; } - damage = ((P_Random()%10)+1)*4; + damage = ((p_random() % 10) + 1) * 4; - if (gameversion <= exe_doom_1_2) - P_LineAttack(actor, actor->angle, MELEERANGE, 0, damage); - else - P_DamageMobj (actor->target, actor, actor, damage); + if (gameversion <= exe_doom_1_2) + p_line_attack(actor, actor->angle, MELEERANGE, 0, damage); + else + p_damage_mobj(actor->target, actor, actor, damage); } -void A_HeadAttack (mobj_t* actor) +void a_head_attack(mobj_t *actor) { - int damage; - - if (!actor->target) - return; - - A_FaceTarget (actor); - if (P_CheckMeleeRange (actor)) + int damage; + + if (!actor->target) return; + + a_face_target(actor); + if (p_check_melee_range(actor)) { - damage = (P_Random()%6+1)*10; - P_DamageMobj (actor->target, actor, actor, damage); - return; + damage = (p_random() % 6 + 1) * 10; + p_damage_mobj(actor->target, actor, actor, damage); + return; } - - // launch a missile - P_SpawnMissile (actor, actor->target, MT_HEADSHOT); -} -void A_CyberAttack (mobj_t* actor) -{ - if (!actor->target) - return; - - A_FaceTarget (actor); - P_SpawnMissile (actor, actor->target, MT_ROCKET); + /* launch a missile */ + + p_spawn_missile(actor, actor->target, MT_HEADSHOT); } +void a_cyber_attack(mobj_t *actor) +{ + if (!actor->target) return; + + a_face_target(actor); + p_spawn_missile(actor, actor->target, MT_ROCKET); +} -void A_BruisAttack (mobj_t* actor) +void a_bruis_attack(mobj_t *actor) { - int damage; - - if (!actor->target) - return; - - if (P_CheckMeleeRange (actor)) + int damage; + + if (!actor->target) return; + + if (p_check_melee_range(actor)) { - S_StartSound (actor, sfx_claw); - damage = (P_Random()%8+1)*10; - P_DamageMobj (actor->target, actor, actor, damage); - return; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_CLAW); +#endif + damage = (p_random() % 8 + 1) * 10; + p_damage_mobj(actor->target, actor, actor, damage); + return; } - - // launch a missile - P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT); -} - - -// -// A_SkelMissile -// -void A_SkelMissile (mobj_t* actor) -{ - mobj_t* mo; - - if (!actor->target) - return; - - A_FaceTarget (actor); - actor->z += 16*FRACUNIT; // so missile spawns higher - mo = P_SpawnMissile (actor, actor->target, MT_TRACER); - actor->z -= 16*FRACUNIT; // back to normal - - mo->x += mo->momx; - mo->y += mo->momy; - mo->tracer = actor->target; -} - -int TRACEANGLE = 0xc000000; - -void A_Tracer (mobj_t* actor) -{ - angle_t exact; - fixed_t dist; - fixed_t slope; - mobj_t* dest; - mobj_t* th; - - if (gametic & 3) - return; - - // spawn a puff of smoke behind the rocket - P_SpawnPuff (actor->x, actor->y, actor->z); - - th = P_SpawnMobj (actor->x-actor->momx, - actor->y-actor->momy, - actor->z, MT_SMOKE); - - th->momz = FRACUNIT; - th->tics -= P_Random()&3; - if (th->tics < 1) - th->tics = 1; - - // adjust direction - dest = actor->tracer; - - if (!dest || dest->health <= 0) - return; - - // change angle - exact = R_PointToAngle2 (actor->x, - actor->y, - dest->x, - dest->y); - - if (exact != actor->angle) + + /* launch a missile */ + + p_spawn_missile(actor, actor->target, MT_BRUISERSHOT); +} + +void a_skel_missile(mobj_t *actor) +{ + mobj_t *mo; + + if (!actor->target) return; + + a_face_target(actor); + actor->z += 16 * FRACUNIT; /* so missile spawns higher */ + mo = p_spawn_missile(actor, actor->target, MT_TRACER); + actor->z -= 16 * FRACUNIT; /* back to normal */ + + mo->x += mo->momx; + mo->y += mo->momy; + mo->tracer = actor->target; +} + +void a_tracer(mobj_t *actor) +{ + angle_t exact; + fixed_t dist; + fixed_t slope; + mobj_t *dest; + mobj_t *th; + + if (gametic & 3) return; + + /* spawn a puff of smoke behind the rocket */ + + p_spawn_puff(actor->x, actor->y, actor->z); + + th = p_spawn_mobj(actor->x - actor->momx, actor->y - actor->momy, actor->z, + MT_SMOKE); + + th->momz = FRACUNIT; + th->tics -= p_random() & 3; + if (th->tics < 1) th->tics = 1; + + /* adjust direction */ + + dest = actor->tracer; + + if (!dest || dest->health <= 0) return; + + /* change angle */ + + exact = r_point_to_angle2(actor->x, actor->y, dest->x, dest->y); + + if (exact != actor->angle) { - if (exact - actor->angle > 0x80000000) - { - actor->angle -= TRACEANGLE; - if (exact - actor->angle < 0x80000000) - actor->angle = exact; - } - else - { - actor->angle += TRACEANGLE; - if (exact - actor->angle > 0x80000000) - actor->angle = exact; - } + if (exact - actor->angle > 0x80000000) + { + actor->angle -= TRACEANGLE; + if (exact - actor->angle < 0x80000000) actor->angle = exact; + } + else + { + actor->angle += TRACEANGLE; + if (exact - actor->angle > 0x80000000) actor->angle = exact; + } } - - exact = actor->angle>>ANGLETOFINESHIFT; - actor->momx = FixedMul (actor->info->speed, finecosine[exact]); - actor->momy = FixedMul (actor->info->speed, finesine[exact]); - - // change slope - dist = P_AproxDistance (dest->x - actor->x, - dest->y - actor->y); - - dist = dist / actor->info->speed; - if (dist < 1) - dist = 1; - slope = (dest->z+40*FRACUNIT - actor->z) / dist; + exact = actor->angle >> ANGLETOFINESHIFT; + actor->momx = fixed_mul(actor->info->speed, finecosine[exact]); + actor->momy = fixed_mul(actor->info->speed, finesine[exact]); - if (slope < actor->momz) - actor->momz -= FRACUNIT/8; - else - actor->momz += FRACUNIT/8; -} + /* change slope */ + + dist = p_approx_distance(dest->x - actor->x, dest->y - actor->y); + dist = dist / actor->info->speed; -void A_SkelWhoosh (mobj_t* actor) + if (dist < 1) dist = 1; + slope = (dest->z + 40 * FRACUNIT - actor->z) / dist; + + if (slope < actor->momz) + actor->momz -= FRACUNIT / 8; + else + actor->momz += FRACUNIT / 8; +} + +void a_skel_woosh(mobj_t *actor) { - if (!actor->target) - return; - A_FaceTarget (actor); - S_StartSound (actor,sfx_skeswg); + if (!actor->target) return; + a_face_target(actor); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_SKESWG); +#endif } -void A_SkelFist (mobj_t* actor) +void a_skel_fist(mobj_t *actor) { - int damage; + int damage; - if (!actor->target) - return; - - A_FaceTarget (actor); - - if (P_CheckMeleeRange (actor)) + if (!actor->target) return; + + a_face_target(actor); + + if (p_check_melee_range(actor)) { - damage = ((P_Random()%10)+1)*6; - S_StartSound (actor, sfx_skepch); - P_DamageMobj (actor->target, actor, actor, damage); + damage = ((p_random() % 10) + 1) * 6; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_SKEPCH); +#endif + p_damage_mobj(actor->target, actor, actor, damage); } } +/* a_vile_chase + * Check for resurrecting a body + */ + +void a_vile_chase(mobj_t *actor) +{ + int xl; + int xh; + int yl; + int yh; + + int bx; + int by; + mobjinfo_t *info; + mobj_t *temp; -// -// PIT_VileCheck -// Detect a corpse that could be raised. -// -mobj_t* corpsehit; -mobj_t* vileobj; -fixed_t viletryx; -fixed_t viletryy; - -boolean PIT_VileCheck (mobj_t* thing) -{ - int maxdist; - boolean check; - - if (!(thing->flags & MF_CORPSE) ) - return true; // not a monster - - if (thing->tics != -1) - return true; // not lying still yet - - if (thing->info->raisestate == S_NULL) - return true; // monster doesn't have a raise state - - maxdist = thing->info->radius + mobjinfo[MT_VILE].radius; - - if ( abs(thing->x - viletryx) > maxdist - || abs(thing->y - viletryy) > maxdist ) - return true; // not actually touching - - corpsehit = thing; - corpsehit->momx = corpsehit->momy = 0; - corpsehit->height <<= 2; - check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); - corpsehit->height >>= 2; - - if (!check) - return true; // doesn't fit here - - return false; // got one, so stop checking -} - - - -// -// A_VileChase -// Check for ressurecting a body -// -void A_VileChase (mobj_t* actor) -{ - int xl; - int xh; - int yl; - int yh; - - int bx; - int by; - - mobjinfo_t* info; - mobj_t* temp; - - if (actor->movedir != DI_NODIR) + if (actor->movedir != DI_NODIR) { - // check for corpses to raise - viletryx = - actor->x + actor->info->speed*xspeed[actor->movedir]; - viletryy = - actor->y + actor->info->speed*yspeed[actor->movedir]; - - xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT; - xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT; - yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT; - yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT; - - vileobj = actor; - for (bx=xl ; bx<=xh ; bx++) - { - for (by=yl ; by<=yh ; by++) - { - // Call PIT_VileCheck to check - // whether object is a corpse - // that canbe raised. - if (!P_BlockThingsIterator(bx,by,PIT_VileCheck)) - { - // got one! - temp = actor->target; - actor->target = corpsehit; - A_FaceTarget (actor); - actor->target = temp; - - P_SetMobjState (actor, S_VILE_HEAL1); - S_StartSound (corpsehit, sfx_slop); - info = corpsehit->info; - - P_SetMobjState (corpsehit,info->raisestate); - corpsehit->height <<= 2; - corpsehit->flags = info->flags; - corpsehit->health = info->spawnhealth; - corpsehit->target = NULL; - - return; - } - } - } + /* check for corpses to raise */ + + viletryx = actor->x + actor->info->speed * xspeed[actor->movedir]; + viletryy = actor->y + actor->info->speed * yspeed[actor->movedir]; + + xl = (viletryx - bmaporgx - MAXRADIUS * 2) >> MAPBLOCKSHIFT; + xh = (viletryx - bmaporgx + MAXRADIUS * 2) >> MAPBLOCKSHIFT; + yl = (viletryy - bmaporgy - MAXRADIUS * 2) >> MAPBLOCKSHIFT; + yh = (viletryy - bmaporgy + MAXRADIUS * 2) >> MAPBLOCKSHIFT; + + vileobj = actor; + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + /* Call pit_vile_check to check whether object is a corpse that + * can be raised. + */ + + if (!p_block_things_iterator(bx, by, pit_vile_check)) + { + /* got one! */ + + temp = actor->target; + actor->target = corpsehit; + a_face_target(actor); + actor->target = temp; + + p_set_mobj_state(actor, S_VILE_HEAL1); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(corpsehit, SFX_SLOP); +#endif + info = corpsehit->info; + + p_set_mobj_state(corpsehit, info->raisestate); + corpsehit->height <<= 2; + corpsehit->flags = info->flags; + corpsehit->health = info->spawnhealth; + corpsehit->target = NULL; + + return; + } + } + } } - // Return to normal attack. - A_Chase (actor); + /* Return to normal attack. */ + + a_chase(actor); } +/* Keep fire in front of player unless out of sight */ -// -// A_VileStart -// -void A_VileStart (mobj_t* actor) +void a_fire(mobj_t *actor) { - S_StartSound (actor, sfx_vilatk); -} + mobj_t *dest; + mobj_t *target; + unsigned an; + + dest = actor->tracer; + if (!dest) return; + + target = p_subst_null_mobj(actor->target); + + /* don't move it if the vile lost sight */ + if (!p_check_sight(target, dest)) return; -// -// A_Fire -// Keep fire in front of player unless out of sight -// -void A_Fire (mobj_t* actor); + an = dest->angle >> ANGLETOFINESHIFT; -void A_StartFire (mobj_t* actor) + p_unset_thing_position(actor); + actor->x = dest->x + fixed_mul(24 * FRACUNIT, finecosine[an]); + actor->y = dest->y + fixed_mul(24 * FRACUNIT, finesine[an]); + actor->z = dest->z; + p_set_thing_position(actor); +} + +void a_vile_start(mobj_t *actor) { - S_StartSound(actor,sfx_flamst); - A_Fire(actor); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_VILATK); +#endif } -void A_FireCrackle (mobj_t* actor) +void a_start_fire(mobj_t *actor) { - S_StartSound(actor,sfx_flame); - A_Fire(actor); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_FLAMST); +#endif + a_fire(actor); } -void A_Fire (mobj_t* actor) +void a_fire_crackle(mobj_t *actor) { - mobj_t* dest; - mobj_t* target; - unsigned an; - - dest = actor->tracer; - if (!dest) - return; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_FLAME); +#endif + a_fire(actor); +} - target = P_SubstNullMobj(actor->target); - - // don't move it if the vile lost sight - if (!P_CheckSight (target, dest) ) - return; +/* a_vile_target + * Spawn the hellfire + */ - an = dest->angle >> ANGLETOFINESHIFT; +void a_vile_target(mobj_t *actor) +{ + mobj_t *fog; - P_UnsetThingPosition (actor); - actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]); - actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]); - actor->z = dest->z; - P_SetThingPosition (actor); -} + if (!actor->target) return; + + a_face_target(actor); + fog = p_spawn_mobj(actor->target->x, actor->target->x, actor->target->z, + MT_FIRE); + actor->tracer = fog; + fog->target = actor; + fog->tracer = actor->target; + a_fire(fog); +} -// -// A_VileTarget -// Spawn the hellfire -// -void A_VileTarget (mobj_t* actor) +void a_vile_attack(mobj_t *actor) { - mobj_t* fog; - - if (!actor->target) - return; + mobj_t *fire; + int an; - A_FaceTarget (actor); + if (!actor->target) return; - fog = P_SpawnMobj (actor->target->x, - actor->target->x, - actor->target->z, MT_FIRE); - - actor->tracer = fog; - fog->target = actor; - fog->tracer = actor->target; - A_Fire (fog); -} + a_face_target(actor); + + if (!p_check_sight(actor, actor->target)) return; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_BAREXP); +#endif + p_damage_mobj(actor->target, actor, actor, 20); + actor->target->momz = 1000 * FRACUNIT / actor->target->info->mass; + an = actor->angle >> ANGLETOFINESHIFT; + fire = actor->tracer; -// -// A_VileAttack -// -void A_VileAttack (mobj_t* actor) -{ - mobj_t* fire; - int an; - - if (!actor->target) - return; - - A_FaceTarget (actor); + if (!fire) return; - if (!P_CheckSight (actor, actor->target) ) - return; + /* move the fire between the vile and the player */ - S_StartSound (actor, sfx_barexp); - P_DamageMobj (actor->target, actor, actor, 20); - actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; - - an = actor->angle >> ANGLETOFINESHIFT; + fire->x = actor->target->x - fixed_mul(24 * FRACUNIT, finecosine[an]); + fire->y = actor->target->y - fixed_mul(24 * FRACUNIT, finesine[an]); + p_radius_attack(fire, actor, 70); +} - fire = actor->tracer; +/* Mancubus attack, + * firing three missiles (bruisers) in three different directions? + * Doesn't look like it. + */ - if (!fire) - return; - - // move the fire between the vile and the player - fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]); - fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]); - P_RadiusAttack (fire, actor, 70 ); +void a_fat_raise(mobj_t *actor) +{ + a_face_target(actor); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_MANATK); +#endif } +void a_fat_attack1(mobj_t *actor) +{ + mobj_t *mo; + mobj_t *target; + int an; + a_face_target(actor); + /* Change direction to ... */ -// -// Mancubus attack, -// firing three missiles (bruisers) -// in three different directions? -// Doesn't look like it. -// -#define FATSPREAD (ANG90/8) + actor->angle += FATSPREAD; + target = p_subst_null_mobj(actor->target); + p_spawn_missile(actor, target, MT_FATSHOT); -void A_FatRaise (mobj_t *actor) -{ - A_FaceTarget (actor); - S_StartSound (actor, sfx_manatk); + mo = p_spawn_missile(actor, target, MT_FATSHOT); + mo->angle += FATSPREAD; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = fixed_mul(mo->info->speed, finecosine[an]); + mo->momy = fixed_mul(mo->info->speed, finesine[an]); } - -void A_FatAttack1 (mobj_t* actor) +void a_fat_attack2(mobj_t *actor) { - mobj_t* mo; - mobj_t* target; - int an; + mobj_t *mo; + mobj_t *target; + int an; + + a_face_target(actor); - A_FaceTarget (actor); + /* Now here choose opposite deviation. */ - // Change direction to ... - actor->angle += FATSPREAD; - target = P_SubstNullMobj(actor->target); - P_SpawnMissile (actor, target, MT_FATSHOT); + actor->angle -= FATSPREAD; + target = p_subst_null_mobj(actor->target); + p_spawn_missile(actor, target, MT_FATSHOT); - mo = P_SpawnMissile (actor, target, MT_FATSHOT); - mo->angle += FATSPREAD; - an = mo->angle >> ANGLETOFINESHIFT; - mo->momx = FixedMul (mo->info->speed, finecosine[an]); - mo->momy = FixedMul (mo->info->speed, finesine[an]); + mo = p_spawn_missile(actor, target, MT_FATSHOT); + mo->angle -= FATSPREAD * 2; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = fixed_mul(mo->info->speed, finecosine[an]); + mo->momy = fixed_mul(mo->info->speed, finesine[an]); } -void A_FatAttack2 (mobj_t* actor) +void a_fat_attack3(mobj_t *actor) { - mobj_t* mo; - mobj_t* target; - int an; + mobj_t *mo; + mobj_t *target; + int an; - A_FaceTarget (actor); - // Now here choose opposite deviation. - actor->angle -= FATSPREAD; - target = P_SubstNullMobj(actor->target); - P_SpawnMissile (actor, target, MT_FATSHOT); + a_face_target(actor); - mo = P_SpawnMissile (actor, target, MT_FATSHOT); - mo->angle -= FATSPREAD*2; - an = mo->angle >> ANGLETOFINESHIFT; - mo->momx = FixedMul (mo->info->speed, finecosine[an]); - mo->momy = FixedMul (mo->info->speed, finesine[an]); + target = p_subst_null_mobj(actor->target); + + mo = p_spawn_missile(actor, target, MT_FATSHOT); + mo->angle -= FATSPREAD / 2; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = fixed_mul(mo->info->speed, finecosine[an]); + mo->momy = fixed_mul(mo->info->speed, finesine[an]); + + mo = p_spawn_missile(actor, target, MT_FATSHOT); + mo->angle += FATSPREAD / 2; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = fixed_mul(mo->info->speed, finecosine[an]); + mo->momy = fixed_mul(mo->info->speed, finesine[an]); } -void A_FatAttack3 (mobj_t* actor) +/* SkullAttack + * Fly at the player like a missile. + */ + +void a_skull_attack(mobj_t *actor) { - mobj_t* mo; - mobj_t* target; - int an; + mobj_t *dest; + angle_t an; + int dist; - A_FaceTarget (actor); + if (!actor->target) return; - target = P_SubstNullMobj(actor->target); - - mo = P_SpawnMissile (actor, target, MT_FATSHOT); - mo->angle -= FATSPREAD/2; - an = mo->angle >> ANGLETOFINESHIFT; - mo->momx = FixedMul (mo->info->speed, finecosine[an]); - mo->momy = FixedMul (mo->info->speed, finesine[an]); + dest = actor->target; + actor->flags |= MF_SKULLFLY; - mo = P_SpawnMissile (actor, target, MT_FATSHOT); - mo->angle += FATSPREAD/2; - an = mo->angle >> ANGLETOFINESHIFT; - mo->momx = FixedMul (mo->info->speed, finecosine[an]); - mo->momy = FixedMul (mo->info->speed, finesine[an]); -} +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, actor->info->attacksound); +#endif + a_face_target(actor); + an = actor->angle >> ANGLETOFINESHIFT; + actor->momx = fixed_mul(SKULLSPEED, finecosine[an]); + actor->momy = fixed_mul(SKULLSPEED, finesine[an]); + dist = p_approx_distance(dest->x - actor->x, dest->y - actor->y); + dist = dist / SKULLSPEED; + if (dist < 1) dist = 1; + actor->momz = (dest->z + (dest->height >> 1) - actor->z) / dist; +} -// -// SkullAttack -// Fly at the player like a missile. -// -#define SKULLSPEED (20*FRACUNIT) +/* a_pain_shoot_skull + * Spawn a lost soul and launch it at the target + */ -void A_SkullAttack (mobj_t* actor) +void a_pain_shoot_skull(mobj_t *actor, angle_t angle) { - mobj_t* dest; - angle_t an; - int dist; + fixed_t x; + fixed_t y; + fixed_t z; - if (!actor->target) - return; - - dest = actor->target; - actor->flags |= MF_SKULLFLY; + mobj_t *newmobj; + angle_t an; + int prestep; + int count; + thinker_t *currentthinker; - S_StartSound (actor, actor->info->attacksound); - A_FaceTarget (actor); - an = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul (SKULLSPEED, finecosine[an]); - actor->momy = FixedMul (SKULLSPEED, finesine[an]); - dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); - dist = dist / SKULLSPEED; - - if (dist < 1) - dist = 1; - actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist; -} + /* count total number of skull currently on the level */ + count = 0; -// -// A_PainShootSkull -// Spawn a lost soul and launch it at the target -// -void -A_PainShootSkull -( mobj_t* actor, - angle_t angle ) -{ - fixed_t x; - fixed_t y; - fixed_t z; - - mobj_t* newmobj; - angle_t an; - int prestep; - int count; - thinker_t* currentthinker; - - // count total number of skull currently on the level - count = 0; - - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) { - if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - && ((mobj_t *)currentthinker)->type == MT_SKULL) - count++; - currentthinker = currentthinker->next; + if ((currentthinker->function.acp1 == (actionf_p1)p_mobj_thinker) && + ((mobj_t *)currentthinker)->type == MT_SKULL) + count++; + currentthinker = currentthinker->next; } - // if there are allready 20 skulls on the level, - // don't spit another one - if (count > 20) - return; - - - // okay, there's playe for another one - an = angle >> ANGLETOFINESHIFT; - - prestep = - 4*FRACUNIT - + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2; - - x = actor->x + FixedMul (prestep, finecosine[an]); - y = actor->y + FixedMul (prestep, finesine[an]); - z = actor->z + 8*FRACUNIT; - - newmobj = P_SpawnMobj (x , y, z, MT_SKULL); - - // Check for movements. - if (!P_TryMove (newmobj, newmobj->x, newmobj->y)) + /* if there are already 20 skulls on the level, don't spit another one */ + + if (count > 20) return; + + /* okay, there's player for another one */ + + an = angle >> ANGLETOFINESHIFT; + + prestep = 4 * FRACUNIT + + 3 * (actor->info->radius + mobjinfo[MT_SKULL].radius) / 2; + + x = actor->x + fixed_mul(prestep, finecosine[an]); + y = actor->y + fixed_mul(prestep, finesine[an]); + z = actor->z + 8 * FRACUNIT; + + newmobj = p_spawn_mobj(x, y, z, MT_SKULL); + + /* Check for movements. */ + + if (!p_try_move(newmobj, newmobj->x, newmobj->y)) { - // kill it immediately - P_DamageMobj (newmobj,actor,actor,10000); - return; + /* kill it immediately */ + + p_damage_mobj(newmobj, actor, actor, 10000); + return; } - - newmobj->target = actor->target; - A_SkullAttack (newmobj); + + newmobj->target = actor->target; + a_skull_attack(newmobj); } +/* a_pain_attack + * Spawn a lost soul and launch it at the target + */ -// -// A_PainAttack -// Spawn a lost soul and launch it at the target -// -void A_PainAttack (mobj_t* actor) +void a_pain_attack(mobj_t *actor) { - if (!actor->target) - return; + if (!actor->target) return; - A_FaceTarget (actor); - A_PainShootSkull (actor, actor->angle); + a_face_target(actor); + a_pain_shoot_skull(actor, actor->angle); } - -void A_PainDie (mobj_t* actor) +void a_pain_die(mobj_t *actor) { - A_Fall (actor); - A_PainShootSkull (actor, actor->angle+ANG90); - A_PainShootSkull (actor, actor->angle+ANG180); - A_PainShootSkull (actor, actor->angle+ANG270); + a_fall(actor); + a_pain_shoot_skull(actor, actor->angle + ANG90); + a_pain_shoot_skull(actor, actor->angle + ANG180); + a_pain_shoot_skull(actor, actor->angle + ANG270); } - - - - - -void A_Scream (mobj_t* actor) +void a_scream(mobj_t *actor) { - int sound; - - switch (actor->info->deathsound) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + int sound; + + switch (actor->info->deathsound) { - case 0: - return; - - case sfx_podth1: - case sfx_podth2: - case sfx_podth3: - sound = sfx_podth1 + P_Random ()%3; - break; - - case sfx_bgdth1: - case sfx_bgdth2: - sound = sfx_bgdth1 + P_Random ()%2; - break; - - default: - sound = actor->info->deathsound; - break; + case 0: + return; + + case SFX_PODTH1: + case SFX_PODTH2: + case SFX_PODTH3: + sound = SFX_PODTH1 + p_random() % 3; + break; + + case SFX_BGDTH1: + case SFX_BGDTH2: + sound = SFX_BGDTH1 + p_random() % 2; + break; + + default: + sound = actor->info->deathsound; + break; } - // Check for bosses. - if (actor->type==MT_SPIDER - || actor->type == MT_CYBORG) + /* Check for bosses. */ + + if (actor->type == MT_SPIDER || actor->type == MT_CYBORG) { - // full volume - S_StartSound (NULL, sound); + s_start_sound(NULL, sound); /* full volume */ } - else - S_StartSound (actor, sound); + else + s_start_sound(actor, sound); +#endif } - -void A_XScream (mobj_t* actor) +void a_xscream(mobj_t *actor) { - S_StartSound (actor, sfx_slop); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(actor, SFX_SLOP); +#endif } -void A_Pain (mobj_t* actor) +void a_pain(mobj_t *actor) { - if (actor->info->painsound) - S_StartSound (actor, actor->info->painsound); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (actor->info->painsound) s_start_sound(actor, actor->info->painsound); +#endif } - - -void A_Fall (mobj_t *actor) +void a_fall(mobj_t *actor) { - // actor is on ground, it can be walked over - actor->flags &= ~MF_SOLID; + /* actor is on ground, it can be walked over */ - // So change this if corpse objects - // are meant to be obstacles. -} + actor->flags &= ~MF_SOLID; + /* So change this if corpse objects are meant to be obstacles. */ +} -// -// A_Explode -// -void A_Explode (mobj_t* thingy) +void a_explode(mobj_t *thingy) { - P_RadiusAttack(thingy, thingy->target, 128); + p_radius_attack(thingy, thingy->target, 128); } -// Check whether the death of the specified monster type is allowed -// to trigger the end of episode special action. -// -// This behavior changed in v1.9, the most notable effect of which -// was to break uac_dead.wad +/* a_boss_death + * Possibly trigger special effects if on first boss level + */ -static boolean CheckBossEnd(mobjtype_t motype) +void a_boss_death(mobj_t *mo) { - if (gameversion < exe_ultimate) - { - if (gamemap != 8) - { - return false; - } + thinker_t *th; + mobj_t *mo2; + line_t junk; + int i; - // Baron death on later episodes is nothing special. + if (gamemode == commercial) + { + if (gamemap != 7) return; - if (motype == MT_BRUISER && gameepisode != 1) + if ((mo->type != MT_FATSO) && (mo->type != MT_BABY)) return; + } + else + { + if (!check_boss_end(mo->type)) { - return false; + return; } - - return true; } - else - { - // New logic that appeared in Ultimate Doom. - // Looks like the logic was overhauled while adding in the - // episode 4 support. Now bosses only trigger on their - // specific episode. - - switch(gameepisode) - { - case 1: - return gamemap == 8 && motype == MT_BRUISER; - case 2: - return gamemap == 8 && motype == MT_CYBORG; + /* make sure there is a player alive for victory */ - case 3: - return gamemap == 8 && motype == MT_SPIDER; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].health > 0) break; + } - case 4: - return (gamemap == 6 && motype == MT_CYBORG) - || (gamemap == 8 && motype == MT_SPIDER); + if (i == MAXPLAYERS) return; /* no one left alive, so do not end game */ - default: - return gamemap == 8; - } - } -} + /* scan the remaining thinkers to see if all bosses are dead */ -// -// A_BossDeath -// Possibly trigger special effects -// if on first boss level -// -void A_BossDeath (mobj_t* mo) -{ - thinker_t* th; - mobj_t* mo2; - line_t junk; - int i; - - if ( gamemode == commercial) - { - if (gamemap != 7) - return; - - if ((mo->type != MT_FATSO) - && (mo->type != MT_BABY)) - return; - } - else + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - if (!CheckBossEnd(mo->type)) + if (th->function.acp1 != (actionf_p1)p_mobj_thinker) continue; + + mo2 = (mobj_t *)th; + if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) { - return; + return; /* other boss not dead */ } } - // make sure there is a player alive for victory - for (i=0 ; i 0) - break; - - if (i==MAXPLAYERS) - return; // no one left alive, so do not end game - - // scan the remaining thinkers to see - // if all bosses are dead - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2 != mo - && mo2->type == mo->type - && mo2->health > 0) - { - // other boss not dead - return; - } - } - - // victory! - if ( gamemode == commercial) + /* victory! */ + + if (gamemode == commercial) { - if (gamemap == 7) - { - if (mo->type == MT_FATSO) - { - junk.tag = 666; - EV_DoFloor(&junk,lowerFloorToLowest); - return; - } - - if (mo->type == MT_BABY) - { - junk.tag = 667; - EV_DoFloor(&junk,raiseToTexture); - return; - } - } + if (gamemap == 7) + { + if (mo->type == MT_FATSO) + { + junk.tag = 666; + ev_do_floor(&junk, FLOOR_LOWERFLOORTOLOWEST); + return; + } + + if (mo->type == MT_BABY) + { + junk.tag = 667; + ev_do_floor(&junk, FLOOR_RAISETOTEXTURE); + return; + } + } } - else + else { - switch(gameepisode) - { - case 1: - junk.tag = 666; - EV_DoFloor (&junk, lowerFloorToLowest); - return; - break; - - case 4: - switch(gamemap) - { - case 6: - junk.tag = 666; - EV_DoDoor (&junk, vld_blazeOpen); - return; - break; - - case 8: - junk.tag = 666; - EV_DoFloor (&junk, lowerFloorToLowest); - return; - break; - } - } + switch (gameepisode) + { + case 1: + junk.tag = 666; + ev_do_floor(&junk, FLOOR_LOWERFLOORTOLOWEST); + return; + break; + + case 4: + switch (gamemap) + { + case 6: + junk.tag = 666; + ev_do_door(&junk, VLD_BLAZEOPEN); + return; + break; + + case 8: + junk.tag = 666; + ev_do_floor(&junk, FLOOR_LOWERFLOORTOLOWEST); + return; + break; + } + } } - - G_ExitLevel (); -} + g_exit_level(); +} -void A_Hoof (mobj_t* mo) +void a_hoof(mobj_t *mo) { - S_StartSound (mo, sfx_hoof); - A_Chase (mo); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_HOOF); +#endif + a_chase(mo); } -void A_Metal (mobj_t* mo) +void a_metal(mobj_t *mo) { - S_StartSound (mo, sfx_metal); - A_Chase (mo); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_METAL); +#endif + a_chase(mo); } -void A_BabyMetal (mobj_t* mo) +void a_baby_metal(mobj_t *mo) { - S_StartSound (mo, sfx_bspwlk); - A_Chase (mo); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_BSPWLK); +#endif + a_chase(mo); } -void -A_OpenShotgun2 -( player_t* player, - pspdef_t* psp ) +void a_open_shotgun2(player_t *player, pspdef_t *psp) { - S_StartSound (player->mo, sfx_dbopn); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_DBOPN); +#endif } -void -A_LoadShotgun2 -( player_t* player, - pspdef_t* psp ) +void a_load_shotgun2(player_t *player, pspdef_t *psp) { - S_StartSound (player->mo, sfx_dbload); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_DBLOAD); +#endif } -void -A_ReFire -( player_t* player, - pspdef_t* psp ); - -void -A_CloseShotgun2 -( player_t* player, - pspdef_t* psp ) +void a_close_shotgun2(player_t *player, pspdef_t *psp) { - S_StartSound (player->mo, sfx_dbcls); - A_ReFire(player,psp); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_DBCLS); +#endif + a_refire(player, psp); } +void a_brain_awake(mobj_t *mo) +{ + thinker_t *thinker; + mobj_t *m; + /* find all the target spots */ -mobj_t* braintargets[32]; -int numbraintargets; -int braintargeton = 0; - -void A_BrainAwake (mobj_t* mo) -{ - thinker_t* thinker; - mobj_t* m; - - // find all the target spots - numbraintargets = 0; - braintargeton = 0; + numbraintargets = 0; + braintargeton = 0; - for (thinker = thinkercap.next ; - thinker != &thinkercap ; - thinker = thinker->next) + for (thinker = thinkercap.next; thinker != &thinkercap; + thinker = thinker->next) { - if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj + if (thinker->function.acp1 != (actionf_p1)p_mobj_thinker) + { + continue; /* not a mobj */ + } - m = (mobj_t *)thinker; + m = (mobj_t *)thinker; - if (m->type == MT_BOSSTARGET ) - { - braintargets[numbraintargets] = m; - numbraintargets++; - } + if (m->type == MT_BOSSTARGET) + { + braintargets[numbraintargets] = m; + numbraintargets++; + } } - - S_StartSound (NULL,sfx_bossit); -} +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_BOSSIT); +#endif +} -void A_BrainPain (mobj_t* mo) +void a_brain_pain(mobj_t *mo) { - S_StartSound (NULL,sfx_bospn); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_BOSPN); +#endif } - -void A_BrainScream (mobj_t* mo) +void a_brain_scream(mobj_t *mo) { - int x; - int y; - int z; - mobj_t* th; - - for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8) + int x; + int y; + int z; + mobj_t *th; + + for (x = mo->x - 196 * FRACUNIT; x < mo->x + 320 * FRACUNIT; + x += FRACUNIT * 8) { - y = mo->y - 320*FRACUNIT; - z = 128 + P_Random()*2*FRACUNIT; - th = P_SpawnMobj (x,y,z, MT_ROCKET); - th->momz = P_Random()*512; + y = mo->y - 320 * FRACUNIT; + z = 128 + p_random() * 2 * FRACUNIT; + th = p_spawn_mobj(x, y, z, MT_ROCKET); + th->momz = p_random() * 512; - P_SetMobjState (th, S_BRAINEXPLODE1); + p_set_mobj_state(th, S_BRAINEXPLODE1); - th->tics -= P_Random()&7; - if (th->tics < 1) - th->tics = 1; + th->tics -= p_random() & 7; + if (th->tics < 1) th->tics = 1; } - - S_StartSound (NULL,sfx_bosdth); -} - +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_BOSDTH); +#endif +} -void A_BrainExplode (mobj_t* mo) +void a_brain_explode(mobj_t *mo) { - int x; - int y; - int z; - mobj_t* th; - - x = mo->x + P_SubRandom() * 2048; - y = mo->y; - z = 128 + P_Random()*2*FRACUNIT; - th = P_SpawnMobj (x,y,z, MT_ROCKET); - th->momz = P_Random()*512; + int x; + int y; + int z; + mobj_t *th; - P_SetMobjState (th, S_BRAINEXPLODE1); + x = mo->x + p_sub_random() * 2048; + y = mo->y; + z = 128 + p_random() * 2 * FRACUNIT; + th = p_spawn_mobj(x, y, z, MT_ROCKET); + th->momz = p_random() * 512; - th->tics -= P_Random()&7; - if (th->tics < 1) - th->tics = 1; -} + p_set_mobj_state(th, S_BRAINEXPLODE1); + th->tics -= p_random() & 7; + if (th->tics < 1) th->tics = 1; +} -void A_BrainDie (mobj_t* mo) +void a_brain_die(mobj_t *mo) { - G_ExitLevel (); + g_exit_level(); } -void A_BrainSpit (mobj_t* mo) +void a_brain_split(mobj_t *mo) { - mobj_t* targ; - mobj_t* newmobj; - - static int easy = 0; - - easy ^= 1; - if (gameskill <= sk_easy && (!easy)) - return; - - // shoot a cube at current target - targ = braintargets[braintargeton]; - if (numbraintargets == 0) + mobj_t *targ; + mobj_t *newmobj; + + static int easy = 0; + + easy ^= 1; + if (gameskill <= sk_easy && (!easy)) return; + + /* shoot a cube at current target */ + + targ = braintargets[braintargeton]; + if (numbraintargets == 0) { - I_Error("A_BrainSpit: numbraintargets was 0 (vanilla crashes here)"); + i_error("a_brain_split: numbraintargets was 0 (vanilla crashes here)"); } - braintargeton = (braintargeton+1)%numbraintargets; - // spawn brain missile - newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT); - newmobj->target = targ; - newmobj->reactiontime = - ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics; + braintargeton = (braintargeton + 1) % numbraintargets; + + /* spawn brain missile */ + + newmobj = p_spawn_missile(mo, targ, MT_SPAWNSHOT); + newmobj->target = targ; + newmobj->reactiontime = + ((targ->y - mo->y) / newmobj->momy) / newmobj->state->tics; - S_StartSound(NULL, sfx_bospit); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(NULL, SFX_BOSPIT); +#endif } +void a_spawn_fly(mobj_t *mo) +{ + mobj_t *newmobj; + mobj_t *fog; + mobj_t *targ; + int r; + mobjtype_t type; + if (--mo->reactiontime) return; /* still flying */ -void A_SpawnFly (mobj_t* mo); + targ = p_subst_null_mobj(mo->target); -// travelling cube sound -void A_SpawnSound (mobj_t* mo) -{ - S_StartSound (mo,sfx_boscub); - A_SpawnFly(mo); -} + /* First spawn teleport fog. */ -void A_SpawnFly (mobj_t* mo) -{ - mobj_t* newmobj; - mobj_t* fog; - mobj_t* targ; - int r; - mobjtype_t type; - - if (--mo->reactiontime) - return; // still flying - - targ = P_SubstNullMobj(mo->target); + fog = p_spawn_mobj(targ->x, targ->y, targ->z, MT_SPAWNFIRE); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(fog, SFX_TELEPT); +#else + UNUSED(fog); +#endif + + /* Randomly select monster to spawn. */ + + r = p_random(); - // First spawn teleport fog. - fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE); - S_StartSound (fog, sfx_telept); + /* Probability distribution (kind of :), decreasing likelihood. */ - // Randomly select monster to spawn. - r = P_Random (); + if (r < 50) + type = MT_TROOP; + else if (r < 90) + type = MT_SERGEANT; + else if (r < 120) + type = MT_SHADOWS; + else if (r < 130) + type = MT_PAIN; + else if (r < 160) + type = MT_HEAD; + else if (r < 162) + type = MT_VILE; + else if (r < 172) + type = MT_UNDEAD; + else if (r < 192) + type = MT_BABY; + else if (r < 222) + type = MT_FATSO; + else if (r < 246) + type = MT_KNIGHT; + else + type = MT_BRUISER; - // Probability distribution (kind of :), - // decreasing likelihood. - if ( r<50 ) - type = MT_TROOP; - else if (r<90) - type = MT_SERGEANT; - else if (r<120) - type = MT_SHADOWS; - else if (r<130) - type = MT_PAIN; - else if (r<160) - type = MT_HEAD; - else if (r<162) - type = MT_VILE; - else if (r<172) - type = MT_UNDEAD; - else if (r<192) - type = MT_BABY; - else if (r<222) - type = MT_FATSO; - else if (r<246) - type = MT_KNIGHT; - else - type = MT_BRUISER; + newmobj = p_spawn_mobj(targ->x, targ->y, targ->z, type); + if (p_look_for_players(newmobj, true)) + p_set_mobj_state(newmobj, newmobj->info->seestate); - newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type); - if (P_LookForPlayers (newmobj, true) ) - P_SetMobjState (newmobj, newmobj->info->seestate); - - // telefrag anything in this spot - P_TeleportMove (newmobj, newmobj->x, newmobj->y); + /* telefrag anything in this spot */ - // remove self (i.e., cube). - P_RemoveMobj (mo); + p_teleport_move(newmobj, newmobj->x, newmobj->y); + + /* remove self (i.e., cube). */ + + p_remove_mobj(mo); } +/* travelling cube sound */ +void a_spawn_sound(mobj_t *mo) +{ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_BOSCUB); +#endif + a_spawn_fly(mo); +} -void A_PlayerScream (mobj_t* mo) +void a_player_screm(mobj_t *mo) { - // Default death sound. - int sound = sfx_pldeth; - - if ( (gamemode == commercial) - && (mo->health < -50)) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + + /* Default death sound. */ + + int sound = SFX_PLDETH; + + if ((gamemode == commercial) && (mo->health < -50)) { - // IF THE PLAYER DIES - // LESS THAN -50% WITHOUT GIBBING - sound = sfx_pdiehi; + /* IF THE PLAYER DIES LESS THAN -50% WITHOUT GIBBING */ + + sound = SFX_PDIEHI; } - - S_StartSound (mo, sound); + + s_start_sound(mo, sound); +#else + UNUSED(mo); +#endif } diff --git a/games/NXDoom/src/doom/p_floor.c b/games/NXDoom/src/doom/p_floor.c index 2bf42e55d79..6562407852c 100644 --- a/games/NXDoom/src/doom/p_floor.c +++ b/games/NXDoom/src/doom/p_floor.c @@ -1,561 +1,569 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Floor animation: raising stairs. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_floor.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Floor animation: raising stairs. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - -#include "z_zone.h" #include "doomdef.h" #include "p_local.h" +#include "z_zone.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* State. */ -// State. #include "doomstat.h" #include "r_state.h" -// Data. -#include "sounds.h" -//e6y +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* e6y */ + #define STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE 10 -// -// FLOORS -// - -// -// Move a plane (floor or ceiling) and check for crushing -// -result_e -T_MovePlane -( sector_t* sector, - fixed_t speed, - fixed_t dest, - boolean crush, - int floorOrCeiling, - int direction ) +/* FLOORS */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Move a plane (floor or ceiling) and check for crushing */ + +result_e t_move_plane(sector_t *sector, fixed_t speed, fixed_t dest, + boolean crush, int floor_or_ceiling, int direction) { - boolean flag; - fixed_t lastpos; - - switch(floorOrCeiling) + boolean flag; + fixed_t lastpos; + + switch (floor_or_ceiling) { - case 0: - // FLOOR - switch(direction) - { - case -1: - // DOWN - if (sector->floorheight - speed < dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - sector->floorheight =lastpos; - P_ChangeSector(sector,crush); - //return crushed; - } - return pastdest; - } - else - { - lastpos = sector->floorheight; - sector->floorheight -= speed; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - } - } - break; - - case 1: - // UP - if (sector->floorheight + speed > dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector,crush); - //return crushed; - } - return pastdest; - } - else - { - // COULD GET CRUSHED - lastpos = sector->floorheight; - sector->floorheight += speed; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - if (crush == true) - return crushed; - sector->floorheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - } - } - break; - } - break; - - case 1: - // CEILING - switch(direction) - { - case -1: - // DOWN - if (sector->ceilingheight - speed < dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector,crush); - - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - //return crushed; - } - return pastdest; - } - else - { - // COULD GET CRUSHED - lastpos = sector->ceilingheight; - sector->ceilingheight -= speed; - flag = P_ChangeSector(sector,crush); - - if (flag == true) - { - if (crush == true) - return crushed; - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - } - } - break; - - case 1: - // UP - if (sector->ceilingheight + speed > dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - //return crushed; - } - return pastdest; - } - else - { - lastpos = sector->ceilingheight; - sector->ceilingheight += speed; - flag = P_ChangeSector(sector,crush); -// UNUSED -#if 0 - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - } + case 0: /* FLOOR */ + switch (direction) + { + case -1: /* DOWN */ + if (sector->floorheight - speed < dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = p_change_sector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + p_change_sector(sector, crush); + + /* return crushed; */ + } + + return pastdest; + } + else + { + lastpos = sector->floorheight; + sector->floorheight -= speed; + flag = p_change_sector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + p_change_sector(sector, crush); + return crushed; + } + } + + break; + + case 1: /* UP */ + if (sector->floorheight + speed > dest) + { + lastpos = sector->floorheight; + sector->floorheight = dest; + flag = p_change_sector(sector, crush); + if (flag == true) + { + sector->floorheight = lastpos; + p_change_sector(sector, crush); + + /* return crushed; */ + } + + return pastdest; + } + else + { + /* COULD GET CRUSHED */ + + lastpos = sector->floorheight; + sector->floorheight += speed; + flag = p_change_sector(sector, crush); + if (flag == true) + { + if (crush == true) return crushed; + sector->floorheight = lastpos; + p_change_sector(sector, crush); + return crushed; + } + } + break; + } + break; + + case 1: /* CEILING */ + switch (direction) + { + case -1: /* DOWN */ + if (sector->ceilingheight - speed < dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = p_change_sector(sector, crush); + + if (flag == true) + { + sector->ceilingheight = lastpos; + p_change_sector(sector, crush); + + /* return crushed; */ + } + + return pastdest; + } + else + { + /* COULD GET CRUSHED */ + + lastpos = sector->ceilingheight; + sector->ceilingheight -= speed; + flag = p_change_sector(sector, crush); + + if (flag == true) + { + if (crush == true) return crushed; + sector->ceilingheight = lastpos; + p_change_sector(sector, crush); + return crushed; + } + } + break; + + case 1: /* UP */ + if (sector->ceilingheight + speed > dest) + { + lastpos = sector->ceilingheight; + sector->ceilingheight = dest; + flag = p_change_sector(sector, crush); + if (flag == true) + { + sector->ceilingheight = lastpos; + p_change_sector(sector, crush); + + /* return crushed; */ + } + + return pastdest; + } + else + { + lastpos = sector->ceilingheight; + sector->ceilingheight += speed; + flag = p_change_sector(sector, crush); + +#if 0 /* UNUSED */ + if (flag == true) + { + sector->ceilingheight = lastpos; + p_change_sector(sector, crush); + return crushed; + } #endif - } - break; - } - break; - + } + break; + } + break; } - return ok; + + return ok; } +/* MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) */ -// -// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) -// -void T_MoveFloor(floormove_t* floor) +void t_move_floor(floormove_t *floor) { - result_e res; - - res = T_MovePlane(floor->sector, - floor->speed, - floor->floordestheight, - floor->crush,0,floor->direction); - - if (!(leveltime&7)) - S_StartSound(&floor->sector->soundorg, sfx_stnmov); - - if (res == pastdest) + result_e res; + + res = t_move_plane(floor->sector, floor->speed, floor->floordestheight, + floor->crush, 0, floor->direction); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(leveltime & 7)) s_start_sound(&floor->sector->soundorg, SFX_STNMOV); +#endif + + if (res == pastdest) { - floor->sector->specialdata = NULL; - - if (floor->direction == 1) - { - switch(floor->type) - { - case donutRaise: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - } - else if (floor->direction == -1) - { - switch(floor->type) - { - case lowerAndChange: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - } - P_RemoveThinker(&floor->thinker); - - S_StartSound(&floor->sector->soundorg, sfx_pstop); + floor->sector->specialdata = NULL; + + if (floor->direction == 1) + { + switch (floor->type) + { + case FLOOR_DONUTRAISE: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + else if (floor->direction == -1) + { + switch (floor->type) + { + case FLOOR_LOWERANDCHANGE: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + + p_remove_thinker(&floor->thinker); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&floor->sector->soundorg, SFX_PSTOP); +#endif } - } -// -// HANDLE FLOOR TYPES -// -int -EV_DoFloor -( line_t* line, - floor_e floortype ) +/* HANDLE FLOOR TYPES */ + +int ev_do_floor(line_t *line, floor_e floortype) { - int secnum; - int rtn; - int i; - sector_t* sec; - floormove_t* floor; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + int secnum; + int rtn; + int i; + sector_t *sec; + floormove_t *floor; + + secnum = -1; + rtn = 0; + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // new floor thinker - rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - sec->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->type = floortype; - floor->crush = false; - - switch(floortype) - { - case lowerFloor: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindHighestFloorSurrounding(sec); - break; - - case lowerFloorToLowest: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindLowestFloorSurrounding(sec); - break; - - case turboLower: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED * 4; - floor->floordestheight = - P_FindHighestFloorSurrounding(sec); - if (gameversion <= exe_doom_1_2 || - floor->floordestheight != sec->floorheight) - floor->floordestheight += 8*FRACUNIT; - break; - - case raiseFloorCrush: - floor->crush = true; - case raiseFloor: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindLowestCeilingSurrounding(sec); - if (floor->floordestheight > sec->ceilingheight) - floor->floordestheight = sec->ceilingheight; - floor->floordestheight -= (8*FRACUNIT)* - (floortype == raiseFloorCrush); - break; - - case raiseFloorTurbo: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED*4; - floor->floordestheight = - P_FindNextHighestFloor(sec,sec->floorheight); - break; - - case raiseFloorToNearest: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindNextHighestFloor(sec,sec->floorheight); - break; - - case raiseFloor24: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 24 * FRACUNIT; - break; - case raiseFloor512: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 512 * FRACUNIT; - break; - - case raiseFloor24AndChange: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 24 * FRACUNIT; - sec->floorpic = line->frontsector->floorpic; - sec->special = line->frontsector->special; - break; - - case raiseToTexture: - { - int minsize = INT_MAX; - side_t* side; - - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - for (i = 0; i < sec->linecount; i++) - { - if (twoSided (secnum, i) ) - { - side = getSide(secnum,i,0); - if (side->bottomtexture >= 0) - if (textureheight[side->bottomtexture] < - minsize) - minsize = - textureheight[side->bottomtexture]; - side = getSide(secnum,i,1); - if (side->bottomtexture >= 0) - if (textureheight[side->bottomtexture] < - minsize) - minsize = - textureheight[side->bottomtexture]; - } - } - floor->floordestheight = - floor->sector->floorheight + minsize; - } - break; - - case lowerAndChange: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindLowestFloorSurrounding(sec); - floor->texture = sec->floorpic; - - for (i = 0; i < sec->linecount; i++) - { - if ( twoSided(secnum, i) ) - { - if (getSide(secnum,i,0)->sector-sectors == secnum) - { - sec = getSector(secnum,i,1); - - if (sec->floorheight == floor->floordestheight) - { - floor->texture = sec->floorpic; - floor->newspecial = sec->special; - break; - } - } - else - { - sec = getSector(secnum,i,0); - - if (sec->floorheight == floor->floordestheight) - { - floor->texture = sec->floorpic; - floor->newspecial = sec->special; - break; - } - } - } - } - default: - break; - } + sec = §ors[secnum]; + + /* ALREADY MOVING? IF SO, KEEP GOING... */ + + if (sec->specialdata) continue; + + /* new floor thinker */ + + rtn = 1; + floor = z_malloc(sizeof(*floor), PU_LEVSPEC, 0); + p_add_thinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)t_move_floor; + floor->type = floortype; + floor->crush = false; + + switch (floortype) + { + case FLOOR_LOWERFLOOR: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = p_find_highest_floor_surrounding(sec); + break; + + case FLOOR_LOWERFLOORTOLOWEST: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = p_find_lowest_floor_surrounding(sec); + break; + + case FLOOR_TURBOLOWER: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED * 4; + floor->floordestheight = p_find_highest_floor_surrounding(sec); + if (gameversion <= exe_doom_1_2 || + floor->floordestheight != sec->floorheight) + floor->floordestheight += 8 * FRACUNIT; + break; + + case FLOOR_RAISEFLOORCRUSH: + floor->crush = true; + case FLOOR_RAISEFLOOR: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = p_find_lowest_ceiling_surrounding(sec); + if (floor->floordestheight > sec->ceilingheight) + floor->floordestheight = sec->ceilingheight; + floor->floordestheight -= + (8 * FRACUNIT) * (floortype == FLOOR_RAISEFLOORCRUSH); + break; + + case FLOOR_RAISEFLOORTURBO: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED * 4; + floor->floordestheight = + p_find_next_highest_floor(sec, sec->floorheight); + break; + + case FLOOR_RAISEFLOORTONEAREST: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + p_find_next_highest_floor(sec, sec->floorheight); + break; + + case FLOOR_RAISEFLOOR24: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + floor->sector->floorheight + 24 * FRACUNIT; + break; + + case FLOOR_RAISEFLOOR512: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + floor->sector->floorheight + 512 * FRACUNIT; + break; + + case FLOOR_RAISEFLOOR24ANDCHANGE: + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = + floor->sector->floorheight + 24 * FRACUNIT; + sec->floorpic = line->frontsector->floorpic; + sec->special = line->frontsector->special; + break; + + case FLOOR_RAISETOTEXTURE: + { + int minsize = INT_MAX; + side_t *side; + + floor->direction = 1; + floor->sector = sec; + floor->speed = FLOORSPEED; + for (i = 0; i < sec->linecount; i++) + { + if (two_sided(secnum, i)) + { + side = get_side(secnum, i, 0); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < minsize) + minsize = textureheight[side->bottomtexture]; + side = get_side(secnum, i, 1); + if (side->bottomtexture >= 0) + if (textureheight[side->bottomtexture] < minsize) + minsize = textureheight[side->bottomtexture]; + } + } + + floor->floordestheight = floor->sector->floorheight + minsize; + } + break; + + case FLOOR_LOWERANDCHANGE: + floor->direction = -1; + floor->sector = sec; + floor->speed = FLOORSPEED; + floor->floordestheight = p_find_lowest_floor_surrounding(sec); + floor->texture = sec->floorpic; + + for (i = 0; i < sec->linecount; i++) + { + if (two_sided(secnum, i)) + { + if (get_side(secnum, i, 0)->sector - sectors == secnum) + { + sec = get_sector(secnum, i, 1); + + if (sec->floorheight == floor->floordestheight) + { + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + else + { + sec = get_sector(secnum, i, 0); + + if (sec->floorheight == floor->floordestheight) + { + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + } + } + + default: + break; + } } - return rtn; + + return rtn; } +/* BUILD A STAIRCASE! */ +int ev_build_stairs(line_t *line, stair_e type) +{ + int secnum; + int height; + int i; + int newsecnum; + int texture; + int is_ok; + int rtn; + sector_t *sec; + sector_t *tsec; -// -// BUILD A STAIRCASE! -// -int -EV_BuildStairs -( line_t* line, - stair_e type ) -{ - int secnum; - int height; - int i; - int newsecnum; - int texture; - int ok; - int rtn; - - sector_t* sec; - sector_t* tsec; - - floormove_t* floor; - - fixed_t stairsize = 0; - fixed_t speed = 0; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + floormove_t *floor; + + fixed_t stairsize = 0; + fixed_t speed = 0; + + secnum = -1; + rtn = 0; + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // new floor thinker - rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - sec->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->direction = 1; - floor->sector = sec; - switch(type) - { - case build8: - speed = FLOORSPEED/4; - stairsize = 8*FRACUNIT; - break; - case turbo16: - speed = FLOORSPEED*4; - stairsize = 16*FRACUNIT; - break; - } - floor->speed = speed; - height = sec->floorheight + stairsize; - floor->floordestheight = height; - // Initialize - floor->type = lowerFloor; - // e6y - // Uninitialized crush field will not be equal to 0 or 1 (true) - // with high probability. So, initialize it with any other value - floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; - - texture = sec->floorpic; - - // Find next sector to raise - // 1. Find 2-sided line with same sector side[0] - // 2. Other side is the next sector to raise - do - { - ok = 0; - for (i = 0;i < sec->linecount;i++) - { - if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) - continue; - - tsec = (sec->lines[i])->frontsector; - newsecnum = tsec-sectors; - - if (secnum != newsecnum) - continue; - - tsec = (sec->lines[i])->backsector; - newsecnum = tsec - sectors; - - if (tsec->floorpic != texture) - continue; - - height += stairsize; - - if (tsec->specialdata) - continue; - - sec = tsec; - secnum = newsecnum; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - - P_AddThinker (&floor->thinker); - - sec->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->direction = 1; - floor->sector = sec; - floor->speed = speed; - floor->floordestheight = height; - // Initialize - floor->type = lowerFloor; - // e6y - // Uninitialized crush field will not be equal to 0 or 1 (true) - // with high probability. So, initialize it with any other value - floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; - ok = 1; - break; - } - } while(ok); + sec = §ors[secnum]; + + /* ALREADY MOVING? IF SO, KEEP GOING... */ + + if (sec->specialdata) continue; + + /* new floor thinker */ + + rtn = 1; + floor = z_malloc(sizeof(*floor), PU_LEVSPEC, 0); + p_add_thinker(&floor->thinker); + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)t_move_floor; + floor->direction = 1; + floor->sector = sec; + + switch (type) + { + case STAIR_BUILD8: + speed = FLOORSPEED / 4; + stairsize = 8 * FRACUNIT; + break; + case STAIR_TURBO16: + speed = FLOORSPEED * 4; + stairsize = 16 * FRACUNIT; + break; + } + + floor->speed = speed; + height = sec->floorheight + stairsize; + floor->floordestheight = height; + + /* Initialize */ + + floor->type = FLOOR_LOWERFLOOR; + + /* e6y + * Uninitialized crush field will not be equal to 0 or 1 (true) + * with high probability. So, initialize it with any other value + */ + + floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; + + texture = sec->floorpic; + + /* Find next sector to raise + * 1. Find 2-sided line with same sector side[0] + * 2. Other side is the next sector to raise + */ + + do + { + is_ok = 0; + for (i = 0; i < sec->linecount; i++) + { + if (!((sec->lines[i])->flags & ML_TWOSIDED)) continue; + + tsec = (sec->lines[i])->frontsector; + newsecnum = tsec - sectors; + + if (secnum != newsecnum) continue; + + tsec = (sec->lines[i])->backsector; + newsecnum = tsec - sectors; + + if (tsec->floorpic != texture) continue; + + height += stairsize; + + if (tsec->specialdata) continue; + + sec = tsec; + secnum = newsecnum; + floor = z_malloc(sizeof(*floor), PU_LEVSPEC, 0); + + p_add_thinker(&floor->thinker); + + sec->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)t_move_floor; + floor->direction = 1; + floor->sector = sec; + floor->speed = speed; + floor->floordestheight = height; + + /* Initialize */ + + floor->type = FLOOR_LOWERFLOOR; + + /* e6y + * Uninitialized crush field will not be equal to 0 or 1 + * (true) with high probability. So, initialize it with any + * other value + */ + + floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; + is_ok = 1; + break; + } + } + while (is_ok); } - return rtn; -} + return rtn; +} diff --git a/games/NXDoom/src/doom/p_inter.c b/games/NXDoom/src/doom/p_inter.c index b6e403298d7..cd77f8ca7c9 100644 --- a/games/NXDoom/src/doom/p_inter.c +++ b/games/NXDoom/src/doom/p_inter.c @@ -1,931 +1,890 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handling interactions (i.e., collisions). -// - - - - -// Data. +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_inter.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Handling interactions (i.e., collisions). + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Data. */ + #include "doomdef.h" #include "dstrings.h" -#include "sounds.h" #include "deh_main.h" #include "deh_misc.h" #include "doomstat.h" -#include "m_random.h" #include "i_system.h" +#include "m_random.h" #include "am_map.h" #include "p_local.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "p_inter.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#define BONUSADD 6 +#define BONUSADD 6 +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* a weapon is found with two clip loads, a big item has five clip loads */ +int maxammo[NUMAMMO] = +{ + 200, 50, 300, 50 +}; -// a weapon is found with two clip loads, -// a big item has five clip loads -int maxammo[NUMAMMO] = {200, 50, 300, 50}; -int clipammo[NUMAMMO] = {10, 4, 20, 1}; +int clipammo[NUMAMMO] = +{ + 10, 4, 20, 1 +}; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// -// GET STUFF -// +/* GET STUFF */ -// -// P_GiveAmmo -// Num is the number of clip loads, -// not the individual count (0= 1/2 clip). -// Returns false if the ammo can't be picked up at all -// +/* p_give_ammo + * + * Num is the number of clip loads, not the individual count (0= 1/2 clip). + * + * Returns false if the ammo can't be picked up at all + */ -boolean -P_GiveAmmo -( player_t* player, - ammotype_t ammo, - int num ) +static boolean p_give_ammo(player_t *player, ammotype_t ammo, int num) { - int oldammo; - - if (ammo == am_noammo) - return false; - - if (ammo >= NUMAMMO) - I_Error ("P_GiveAmmo: bad type %i", ammo); - - if ( player->ammo[ammo] == player->maxammo[ammo] ) - return false; - - if (num) - num *= clipammo[ammo]; - else - num = clipammo[ammo]/2; - - if (gameskill == sk_baby - || gameskill == sk_nightmare) + int oldammo; + + if (ammo == am_noammo) return false; + + if (ammo >= NUMAMMO) i_error("p_give_ammo: bad type %i", ammo); + + if (player->ammo[ammo] == player->maxammo[ammo]) return false; + + if (num) + num *= clipammo[ammo]; + else + num = clipammo[ammo] / 2; + + if (gameskill == sk_baby || gameskill == sk_nightmare) { - // give double ammo in trainer mode, - // you'll need in nightmare - num <<= 1; + /* give double ammo in trainer mode, you'll need in nightmare */ + + num <<= 1; } - - - oldammo = player->ammo[ammo]; - player->ammo[ammo] += num; - - if (player->ammo[ammo] > player->maxammo[ammo]) - player->ammo[ammo] = player->maxammo[ammo]; - - // If non zero ammo, - // don't change up weapons, - // player was lower on purpose. - if (oldammo) - return true; - - // We were down to zero, - // so select a new weapon. - // Preferences are not user selectable. - switch (ammo) + + oldammo = player->ammo[ammo]; + player->ammo[ammo] += num; + + if (player->ammo[ammo] > player->maxammo[ammo]) + player->ammo[ammo] = player->maxammo[ammo]; + + /* If non zero ammo, don't change up weapons, player was lower on purpose. + */ + + if (oldammo) return true; + + /* We were down to zero, so select a new weapon. Preferences are not user + * selectable. + */ + + switch (ammo) { - case am_clip: - if (player->readyweapon == wp_fist) - { - if (player->weaponowned[wp_chaingun]) - player->pendingweapon = wp_chaingun; - else - player->pendingweapon = wp_pistol; - } - break; - - case am_shell: - if (player->readyweapon == wp_fist - || player->readyweapon == wp_pistol) - { - if (player->weaponowned[wp_shotgun]) - player->pendingweapon = wp_shotgun; - } - break; - - case am_cell: - if (player->readyweapon == wp_fist - || player->readyweapon == wp_pistol) - { - if (player->weaponowned[wp_plasma]) - player->pendingweapon = wp_plasma; - } - break; - - case am_misl: - if (player->readyweapon == wp_fist) - { - if (player->weaponowned[wp_missile]) - player->pendingweapon = wp_missile; - } - default: - break; + case am_clip: + if (player->readyweapon == wp_fist) + { + if (player->weaponowned[wp_chaingun]) + player->pendingweapon = wp_chaingun; + else + player->pendingweapon = wp_pistol; + } + + break; + + case am_shell: + if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol) + { + if (player->weaponowned[wp_shotgun]) + player->pendingweapon = wp_shotgun; + } + + break; + + case am_cell: + if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol) + { + if (player->weaponowned[wp_plasma]) + player->pendingweapon = wp_plasma; + } + + break; + + case am_misl: + if (player->readyweapon == wp_fist) + { + if (player->weaponowned[wp_missile]) + player->pendingweapon = wp_missile; + } + + default: + break; } - - return true; + + return true; } +/* p_give_weapon + * + * The weapon name may have a MF_DROPPED flag ored in. + */ -// -// P_GiveWeapon -// The weapon name may have a MF_DROPPED flag ored in. -// -boolean -P_GiveWeapon -( player_t* player, - weapontype_t weapon, - boolean dropped ) +static boolean p_give_weapon(player_t *player, weapontype_t weapon, + boolean dropped) { - boolean gaveammo; - boolean gaveweapon; - - if (netgame - && (deathmatch!=2) - && !dropped ) + boolean gaveammo; + boolean gaveweapon; + + if (netgame && (deathmatch != 2) && !dropped) { - // leave placed weapons forever on net games - if (player->weaponowned[weapon]) - return false; - - player->bonuscount += BONUSADD; - player->weaponowned[weapon] = true; - - if (deathmatch) - P_GiveAmmo (player, weaponinfo[weapon].ammo, 5); - else - P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); - player->pendingweapon = weapon; - - if (player == &players[consoleplayer]) - S_StartSound (NULL, sfx_wpnup); - return false; + /* leave placed weapons forever on net games */ + + if (player->weaponowned[weapon]) return false; + + player->bonuscount += BONUSADD; + player->weaponowned[weapon] = true; + + if (deathmatch) + p_give_ammo(player, weaponinfo[weapon].ammo, 5); + else + p_give_ammo(player, weaponinfo[weapon].ammo, 2); + player->pendingweapon = weapon; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (player == &players[consoleplayer]) s_start_sound(NULL, SFX_WPNUP); +#endif + return false; } - - if (weaponinfo[weapon].ammo != am_noammo) + + if (weaponinfo[weapon].ammo != am_noammo) { - // give one clip with a dropped weapon, - // two clips with a found weapon - if (dropped) - gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1); - else - gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); + /* give one clip with a dropped weapon, two clips with a found weapon */ + + if (dropped) + gaveammo = p_give_ammo(player, weaponinfo[weapon].ammo, 1); + else + gaveammo = p_give_ammo(player, weaponinfo[weapon].ammo, 2); } - else - gaveammo = false; - - if (player->weaponowned[weapon]) - gaveweapon = false; - else + else + gaveammo = false; + + if (player->weaponowned[weapon]) + gaveweapon = false; + else { - gaveweapon = true; - player->weaponowned[weapon] = true; - player->pendingweapon = weapon; + gaveweapon = true; + player->weaponowned[weapon] = true; + player->pendingweapon = weapon; } - - return (gaveweapon || gaveammo); + + return (gaveweapon || gaveammo); } - +/* p_give_body + * Returns false if the body isn't needed at all + */ -// -// P_GiveBody -// Returns false if the body isn't needed at all -// -boolean -P_GiveBody -( player_t* player, - int num ) +static boolean p_give_body(player_t *player, int num) { - if (player->health >= MAXHEALTH) - return false; - - player->health += num; - if (player->health > MAXHEALTH) - player->health = MAXHEALTH; - player->mo->health = player->health; - - return true; -} + if (player->health >= MAXHEALTH) return false; + + player->health += num; + if (player->health > MAXHEALTH) player->health = MAXHEALTH; + player->mo->health = player->health; + return true; +} +/* p_give_armor + * Returns false if the armor is worse than the current armor. + */ -// -// P_GiveArmor -// Returns false if the armor is worse -// than the current armor. -// -boolean -P_GiveArmor -( player_t* player, - int armortype ) +static boolean p_give_armor(player_t *player, int armortype) { - int hits; - - hits = armortype*100; - if (player->armorpoints >= hits) - return false; // don't pick up - - player->armortype = armortype; - player->armorpoints = hits; - - return true; -} + int hits; + hits = armortype * 100; + if (player->armorpoints >= hits) return false; /* don't pick up */ + player->armortype = armortype; + player->armorpoints = hits; -// -// P_GiveCard -// -void -P_GiveCard -( player_t* player, - card_t card ) -{ - if (player->cards[card]) - return; - - player->bonuscount = BONUSADD; - player->cards[card] = 1; + return true; } +static void p_give_card(player_t *player, card_t card) +{ + if (player->cards[card]) return; + + player->bonuscount = BONUSADD; + player->cards[card] = 1; +} -// -// P_GivePower -// -boolean -P_GivePower -( player_t* player, - int /*powertype_t*/ power ) +static void p_kill_mobj(mobj_t *source, mobj_t *target) { - if (power == pw_invulnerability) - { - player->powers[power] = INVULNTICS; - return true; - } - - if (power == pw_invisibility) + mobjtype_t item; + mobj_t *mo; + + target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY); + + if (target->type != MT_SKULL) target->flags &= ~MF_NOGRAVITY; + + target->flags |= MF_CORPSE | MF_DROPOFF; + target->height >>= 2; + + if (source && source->player) { - player->powers[power] = INVISTICS; - player->mo->flags |= MF_SHADOW; - return true; + /* count for intermission */ + + if (target->flags & MF_COUNTKILL) source->player->killcount++; + + if (target->player) source->player->frags[target->player - players]++; } - - if (power == pw_infrared) + else if (!netgame && (target->flags & MF_COUNTKILL)) { - player->powers[power] = INFRATICS; - return true; + /* count all monster deaths, even those caused by other monsters */ + + players[0].killcount++; } - - if (power == pw_ironfeet) + + if (target->player) { - player->powers[power] = IRONTICS; - return true; + /* count environment kills against you */ + + if (!source) target->player->frags[target->player - players]++; + + target->flags &= ~MF_SOLID; + target->player->playerstate = PST_DEAD; + p_drop_weapon(target->player); + + if (target->player == &players[consoleplayer] && automapactive) + { + /* don't die in auto map, switch view prior to dying */ + + am_stop(); + } } - - if (power == pw_strength) + + if (target->health < -target->info->spawnhealth && + target->info->xdeathstate) { - P_GiveBody (player, 100); - player->powers[power] = 1; - return true; + p_set_mobj_state(target, target->info->xdeathstate); } - - if (player->powers[power]) - return false; // already got it - - player->powers[power] = 1; - return true; -} + else + p_set_mobj_state(target, target->info->deathstate); + target->tics -= p_random() & 3; + if (target->tics < 1) target->tics = 1; -// -// P_TouchSpecialThing -// -void -P_TouchSpecialThing -( mobj_t* special, - mobj_t* toucher ) -{ - player_t* player; - int i; - fixed_t delta; - int sound; - - delta = special->z - toucher->z; - - if (delta > toucher->height - || delta < -8*FRACUNIT) + /* In Chex Quest, monsters don't drop items. */ + + if (gameversion == exe_chex) { - // out of reach - return; + return; } - - - sound = sfx_itemup; - player = toucher->player; - - // Dead thing touching. - // Can happen with a sliding player corpse. - if (toucher->health <= 0) - return; - - // Identify by sprite. - switch (special->sprite) + + /* Drop stuff. + * This determines the kind of object spawned during the death frame of a + * thing. + */ + + switch (target->type) { - // armor - case SPR_ARM1: - if (!P_GiveArmor (player, deh_green_armor_class)) - return; - player->message = DEH_String(GOTARMOR); - break; - - case SPR_ARM2: - if (!P_GiveArmor (player, deh_blue_armor_class)) - return; - player->message = DEH_String(GOTMEGA); - break; - - // bonus items - case SPR_BON1: - player->health++; // can go over 100% - if (player->health > deh_max_health) - player->health = deh_max_health; - player->mo->health = player->health; - player->message = DEH_String(GOTHTHBONUS); - break; - - case SPR_BON2: - player->armorpoints++; // can go over 100% - if (player->armorpoints > deh_max_armor && gameversion > exe_doom_1_2) - player->armorpoints = deh_max_armor; - // deh_green_armor_class only applies to the green armor shirt; - // for the armor helmets, armortype 1 is always used. - if (!player->armortype) - player->armortype = 1; - player->message = DEH_String(GOTARMBONUS); - break; - - case SPR_SOUL: - player->health += deh_soulsphere_health; - if (player->health > deh_max_soulsphere) - player->health = deh_max_soulsphere; - player->mo->health = player->health; - player->message = DEH_String(GOTSUPER); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - case SPR_MEGA: - if (gamemode != commercial) - return; - player->health = deh_megasphere_health; - player->mo->health = player->health; - // We always give armor type 2 for the megasphere; dehacked only - // affects the MegaArmor. - P_GiveArmor (player, 2); - player->message = DEH_String(GOTMSPHERE); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - // cards - // leave cards for everyone - case SPR_BKEY: - if (!player->cards[it_bluecard]) - player->message = DEH_String(GOTBLUECARD); - P_GiveCard (player, it_bluecard); - if (!netgame) - break; - return; - - case SPR_YKEY: - if (!player->cards[it_yellowcard]) - player->message = DEH_String(GOTYELWCARD); - P_GiveCard (player, it_yellowcard); - if (!netgame) - break; - return; - - case SPR_RKEY: - if (!player->cards[it_redcard]) - player->message = DEH_String(GOTREDCARD); - P_GiveCard (player, it_redcard); - if (!netgame) - break; - return; - - case SPR_BSKU: - if (!player->cards[it_blueskull]) - player->message = DEH_String(GOTBLUESKUL); - P_GiveCard (player, it_blueskull); - if (!netgame) - break; - return; - - case SPR_YSKU: - if (!player->cards[it_yellowskull]) - player->message = DEH_String(GOTYELWSKUL); - P_GiveCard (player, it_yellowskull); - if (!netgame) - break; - return; - - case SPR_RSKU: - if (!player->cards[it_redskull]) - player->message = DEH_String(GOTREDSKULL); - P_GiveCard (player, it_redskull); - if (!netgame) - break; - return; - - // medikits, heals - case SPR_STIM: - if (!P_GiveBody (player, 10)) - return; - player->message = DEH_String(GOTSTIM); - break; - - case SPR_MEDI: - if (!P_GiveBody (player, 25)) - return; - - if (player->health < 25) - player->message = DEH_String(GOTMEDINEED); - else - player->message = DEH_String(GOTMEDIKIT); - break; - - - // power ups - case SPR_PINV: - if (!P_GivePower (player, pw_invulnerability)) - return; - player->message = DEH_String(GOTINVUL); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - case SPR_PSTR: - if (!P_GivePower (player, pw_strength)) - return; - player->message = DEH_String(GOTBERSERK); - if (player->readyweapon != wp_fist) - player->pendingweapon = wp_fist; - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - case SPR_PINS: - if (!P_GivePower (player, pw_invisibility)) - return; - player->message = DEH_String(GOTINVIS); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - case SPR_SUIT: - if (!P_GivePower (player, pw_ironfeet)) - return; - player->message = DEH_String(GOTSUIT); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - case SPR_PMAP: - if (!P_GivePower (player, pw_allmap)) - return; - player->message = DEH_String(GOTMAP); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - case SPR_PVIS: - if (!P_GivePower (player, pw_infrared)) - return; - player->message = DEH_String(GOTVISOR); - if (gameversion > exe_doom_1_2) - sound = sfx_getpow; - break; - - // ammo - case SPR_CLIP: - if (special->flags & MF_DROPPED) - { - if (!P_GiveAmmo (player,am_clip,0)) - return; - } - else - { - if (!P_GiveAmmo (player,am_clip,1)) - return; - } - player->message = DEH_String(GOTCLIP); - break; - - case SPR_AMMO: - if (!P_GiveAmmo (player, am_clip,5)) - return; - player->message = DEH_String(GOTCLIPBOX); - break; - - case SPR_ROCK: - if (!P_GiveAmmo (player, am_misl,1)) - return; - player->message = DEH_String(GOTROCKET); - break; - - case SPR_BROK: - if (!P_GiveAmmo (player, am_misl,5)) - return; - player->message = DEH_String(GOTROCKBOX); - break; - - case SPR_CELL: - if (!P_GiveAmmo (player, am_cell,1)) - return; - player->message = DEH_String(GOTCELL); - break; - - case SPR_CELP: - if (!P_GiveAmmo (player, am_cell,5)) - return; - player->message = DEH_String(GOTCELLBOX); - break; - - case SPR_SHEL: - if (!P_GiveAmmo (player, am_shell,1)) - return; - player->message = DEH_String(GOTSHELLS); - break; - - case SPR_SBOX: - if (!P_GiveAmmo (player, am_shell,5)) - return; - player->message = DEH_String(GOTSHELLBOX); - break; - - case SPR_BPAK: - if (!player->backpack) - { - for (i=0 ; imaxammo[i] *= 2; - player->backpack = true; - } - for (i=0 ; imessage = DEH_String(GOTBACKPACK); - break; - - // weapons - case SPR_BFUG: - if (!P_GiveWeapon (player, wp_bfg, false) ) - return; - player->message = DEH_String(GOTBFG9000); - sound = sfx_wpnup; - break; - - case SPR_MGUN: - if (!P_GiveWeapon(player, wp_chaingun, - (special->flags & MF_DROPPED) != 0)) - return; - player->message = DEH_String(GOTCHAINGUN); - sound = sfx_wpnup; - break; - - case SPR_CSAW: - if (!P_GiveWeapon (player, wp_chainsaw, false) ) - return; - player->message = DEH_String(GOTCHAINSAW); - sound = sfx_wpnup; - break; - - case SPR_LAUN: - if (!P_GiveWeapon (player, wp_missile, false) ) - return; - player->message = DEH_String(GOTLAUNCHER); - sound = sfx_wpnup; - break; - - case SPR_PLAS: - if (!P_GiveWeapon (player, wp_plasma, false) ) - return; - player->message = DEH_String(GOTPLASMA); - sound = sfx_wpnup; - break; - - case SPR_SHOT: - if (!P_GiveWeapon(player, wp_shotgun, - (special->flags & MF_DROPPED) != 0)) - return; - player->message = DEH_String(GOTSHOTGUN); - sound = sfx_wpnup; - break; - - case SPR_SGN2: - if (!P_GiveWeapon(player, wp_supershotgun, - (special->flags & MF_DROPPED) != 0)) - return; - player->message = DEH_String(GOTSHOTGUN2); - sound = sfx_wpnup; - break; - - default: - I_Error ("P_SpecialThing: Unknown gettable thing"); - } - - if (special->flags & MF_COUNTITEM) - player->itemcount++; - P_RemoveMobj (special); - player->bonuscount += BONUSADD; - if (player == &players[consoleplayer]) - S_StartSound (NULL, sound); -} + case MT_WOLFSS: + case MT_POSSESSED: + item = MT_CLIP; + break; + case MT_SHOTGUY: + item = MT_SHOTGUN; + break; -// -// KillMobj -// -void -P_KillMobj -( mobj_t* source, - mobj_t* target ) -{ - mobjtype_t item; - mobj_t* mo; - - target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); + case MT_CHAINGUY: + item = MT_CHAINGUN; + break; + + default: + return; + } - if (target->type != MT_SKULL) - target->flags &= ~MF_NOGRAVITY; + mo = p_spawn_mobj(target->x, target->y, ONFLOORZ, item); + mo->flags |= MF_DROPPED; /* special versions of items */ +} - target->flags |= MF_CORPSE|MF_DROPOFF; - target->height >>= 2; +/**************************************************************************** + * Public Functions + ****************************************************************************/ - if (source && source->player) +boolean p_give_power(player_t *player, int /* powertype_t */ power) +{ + if (power == pw_invulnerability) { - // count for intermission - if (target->flags & MF_COUNTKILL) - source->player->killcount++; + player->powers[power] = INVULNTICS; + return true; + } - if (target->player) - source->player->frags[target->player-players]++; + if (power == pw_invisibility) + { + player->powers[power] = INVISTICS; + player->mo->flags |= MF_SHADOW; + return true; } - else if (!netgame && (target->flags & MF_COUNTKILL) ) + + if (power == pw_infrared) { - // count all monster deaths, - // even those caused by other monsters - players[0].killcount++; + player->powers[power] = INFRATICS; + return true; } - - if (target->player) + + if (power == pw_ironfeet) { - // count environment kills against you - if (!source) - target->player->frags[target->player-players]++; - - target->flags &= ~MF_SOLID; - target->player->playerstate = PST_DEAD; - P_DropWeapon (target->player); - - if (target->player == &players[consoleplayer] - && automapactive) - { - // don't die in auto map, - // switch view prior to dying - AM_Stop (); - } - + player->powers[power] = IRONTICS; + return true; } - if (target->health < -target->info->spawnhealth - && target->info->xdeathstate) + if (power == pw_strength) { - P_SetMobjState (target, target->info->xdeathstate); + p_give_body(player, 100); + player->powers[power] = 1; + return true; } - else - P_SetMobjState (target, target->info->deathstate); - target->tics -= P_Random()&3; - if (target->tics < 1) - target->tics = 1; - - // I_StartSound (&actor->r, actor->info->deathsound); + if (player->powers[power]) return false; /* already got it */ + + player->powers[power] = 1; + return true; +} + +void p_touch_special_thing(mobj_t *special, mobj_t *toucher) +{ + player_t *player; + int i; + fixed_t delta; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + int sound; +#endif - // In Chex Quest, monsters don't drop items. + delta = special->z - toucher->z; - if (gameversion == exe_chex) + if (delta > toucher->height || delta < -8 * FRACUNIT) { - return; + return; /* out of reach */ } - // Drop stuff. - // This determines the kind of object spawned - // during the death frame of a thing. - switch (target->type) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_ITEMUP; +#endif + player = toucher->player; + + /* Dead thing touching. Can happen with a sliding player corpse. */ + + if (toucher->health <= 0) return; + + /* Identify by sprite. */ + + switch (special->sprite) { - case MT_WOLFSS: - case MT_POSSESSED: - item = MT_CLIP; - break; - - case MT_SHOTGUY: - item = MT_SHOTGUN; - break; - - case MT_CHAINGUY: - item = MT_CHAINGUN; - break; - - default: - return; + /* armor */ + + case SPR_ARM1: + if (!p_give_armor(player, deh_green_armor_class)) return; + player->message = (GOTARMOR); + break; + + case SPR_ARM2: + if (!p_give_armor(player, deh_blue_armor_class)) return; + player->message = (GOTMEGA); + break; + + /* bonus items */ + + case SPR_BON1: + player->health++; /* can go over 100% */ + if (player->health > deh_max_health) player->health = deh_max_health; + player->mo->health = player->health; + player->message = (GOTHTHBONUS); + break; + + case SPR_BON2: + player->armorpoints++; /* can go over 100% */ + if (player->armorpoints > deh_max_armor && gameversion > exe_doom_1_2) + { + player->armorpoints = deh_max_armor; + } + + /* deh_green_armor_class only applies to the green armor shirt; + * for the armor helmets, armortype 1 is always used. + */ + + if (!player->armortype) player->armortype = 1; + player->message = (GOTARMBONUS); + break; + + case SPR_SOUL: + player->health += deh_soulsphere_health; + if (player->health > deh_max_soulsphere) + player->health = deh_max_soulsphere; + player->mo->health = player->health; + player->message = (GOTSUPER); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + case SPR_MEGA: + if (gamemode != commercial) return; + player->health = deh_megasphere_health; + player->mo->health = player->health; + + /* We always give armor type 2 for the megasphere; dehacked only + * affects the MegaArmor. + */ + + p_give_armor(player, 2); + player->message = (GOTMSPHERE); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + /* cards + * leave cards for everyone + */ + + case SPR_BKEY: + if (!player->cards[it_bluecard]) player->message = (GOTBLUECARD); + p_give_card(player, it_bluecard); + if (!netgame) break; + return; + + case SPR_YKEY: + if (!player->cards[it_yellowcard]) player->message = (GOTYELWCARD); + p_give_card(player, it_yellowcard); + if (!netgame) break; + return; + + case SPR_RKEY: + if (!player->cards[it_redcard]) player->message = (GOTREDCARD); + p_give_card(player, it_redcard); + if (!netgame) break; + return; + + case SPR_BSKU: + if (!player->cards[it_blueskull]) player->message = (GOTBLUESKUL); + p_give_card(player, it_blueskull); + if (!netgame) break; + return; + + case SPR_YSKU: + if (!player->cards[it_yellowskull]) player->message = (GOTYELWSKUL); + p_give_card(player, it_yellowskull); + if (!netgame) break; + return; + + case SPR_RSKU: + if (!player->cards[it_redskull]) player->message = (GOTREDSKULL); + p_give_card(player, it_redskull); + if (!netgame) break; + return; + + /* medikits, heals */ + + case SPR_STIM: + if (!p_give_body(player, 10)) return; + player->message = (GOTSTIM); + break; + + case SPR_MEDI: + if (!p_give_body(player, 25)) return; + + if (player->health < 25) + player->message = (GOTMEDINEED); + else + player->message = (GOTMEDIKIT); + break; + + /* power ups */ + + case SPR_PINV: + if (!p_give_power(player, pw_invulnerability)) return; + player->message = (GOTINVUL); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + case SPR_PSTR: + if (!p_give_power(player, pw_strength)) return; + player->message = (GOTBERSERK); + if (player->readyweapon != wp_fist) player->pendingweapon = wp_fist; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + case SPR_PINS: + if (!p_give_power(player, pw_invisibility)) return; + player->message = (GOTINVIS); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + case SPR_SUIT: + if (!p_give_power(player, pw_ironfeet)) return; + player->message = (GOTSUIT); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + case SPR_PMAP: + if (!p_give_power(player, pw_allmap)) return; + player->message = (GOTMAP); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + case SPR_PVIS: + if (!p_give_power(player, pw_infrared)) return; + player->message = (GOTVISOR); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (gameversion > exe_doom_1_2) sound = SFX_GETPOW; +#endif + break; + + /* ammo */ + + case SPR_CLIP: + if (special->flags & MF_DROPPED) + { + if (!p_give_ammo(player, am_clip, 0)) return; + } + else + { + if (!p_give_ammo(player, am_clip, 1)) return; + } + + player->message = (GOTCLIP); + break; + + case SPR_AMMO: + if (!p_give_ammo(player, am_clip, 5)) return; + player->message = (GOTCLIPBOX); + break; + + case SPR_ROCK: + if (!p_give_ammo(player, am_misl, 1)) return; + player->message = (GOTROCKET); + break; + + case SPR_BROK: + if (!p_give_ammo(player, am_misl, 5)) return; + player->message = (GOTROCKBOX); + break; + + case SPR_CELL: + if (!p_give_ammo(player, am_cell, 1)) return; + player->message = (GOTCELL); + break; + + case SPR_CELP: + if (!p_give_ammo(player, am_cell, 5)) return; + player->message = (GOTCELLBOX); + break; + + case SPR_SHEL: + if (!p_give_ammo(player, am_shell, 1)) return; + player->message = (GOTSHELLS); + break; + + case SPR_SBOX: + if (!p_give_ammo(player, am_shell, 5)) return; + player->message = (GOTSHELLBOX); + break; + + case SPR_BPAK: + if (!player->backpack) + { + for (i = 0; i < NUMAMMO; i++) + player->maxammo[i] *= 2; + player->backpack = true; + } + + for (i = 0; i < NUMAMMO; i++) + p_give_ammo(player, i, 1); + player->message = (GOTBACKPACK); + break; + + /* weapons */ + + case SPR_BFUG: + if (!p_give_weapon(player, wp_bfg, false)) return; + player->message = (GOTBFG9000); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + case SPR_MGUN: + if (!p_give_weapon(player, wp_chaingun, + (special->flags & MF_DROPPED) != 0)) + return; + player->message = (GOTCHAINGUN); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + case SPR_CSAW: + if (!p_give_weapon(player, wp_chainsaw, false)) return; + player->message = (GOTCHAINSAW); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + case SPR_LAUN: + if (!p_give_weapon(player, wp_missile, false)) return; + player->message = (GOTLAUNCHER); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + case SPR_PLAS: + if (!p_give_weapon(player, wp_plasma, false)) return; + player->message = (GOTPLASMA); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + case SPR_SHOT: + if (!p_give_weapon(player, wp_shotgun, + (special->flags & MF_DROPPED) != 0)) + return; + player->message = (GOTSHOTGUN); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + case SPR_SGN2: + if (!p_give_weapon(player, wp_supershotgun, + (special->flags & MF_DROPPED) != 0)) + return; + player->message = (GOTSHOTGUN2); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_WPNUP; +#endif + break; + + default: + i_error("P_SpecialThing: Unknown gettable thing"); } - mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item); - mo->flags |= MF_DROPPED; // special versions of items + if (special->flags & MF_COUNTITEM) player->itemcount++; + p_remove_mobj(special); + player->bonuscount += BONUSADD; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (player == &players[consoleplayer]) s_start_sound(NULL, sound); +#endif } +/* p_damage_mobj + * Damages both enemies and players "inflictor" is the thing that caused the + * damage creature or missile, can be NULL (slime, etc) "source" is the thing + * to target after taking damage creature or NULL + * + * Source and inflictor are the same for melee attacks. + * Source can be NULL for slime, barrel explosions and other environmental + * stuff. + */ + +void p_damage_mobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, + int damage) +{ + unsigned ang; + int saved; + player_t *player; + fixed_t thrust; + int temp; + if (!(target->flags & MF_SHOOTABLE)) return; /* shouldn't happen... */ + if (target->health <= 0) return; -// -// P_DamageMobj -// Damages both enemies and players -// "inflictor" is the thing that caused the damage -// creature or missile, can be NULL (slime, etc) -// "source" is the thing to target after taking damage -// creature or NULL -// Source and inflictor are the same for melee attacks. -// Source can be NULL for slime, barrel explosions -// and other environmental stuff. -// -void -P_DamageMobj -( mobj_t* target, - mobj_t* inflictor, - mobj_t* source, - int damage ) -{ - unsigned ang; - int saved; - player_t* player; - fixed_t thrust; - int temp; - - if ( !(target->flags & MF_SHOOTABLE) ) - return; // shouldn't happen... - - if (target->health <= 0) - return; - - if ( target->flags & MF_SKULLFLY ) + if (target->flags & MF_SKULLFLY) { - target->momx = target->momy = target->momz = 0; + target->momx = target->momy = target->momz = 0; } - - player = target->player; - if (player && gameskill == sk_baby) - damage >>= 1; // take half damage in trainer mode - - - // Some close combat weapons should not - // inflict thrust and push the victim out of reach, - // thus kick away unless using the chainsaw. - if (inflictor - && !(target->flags & MF_NOCLIP) - && (!source - || !source->player - || source->player->readyweapon != wp_chainsaw)) + + player = target->player; + if (player && gameskill == sk_baby) + damage >>= 1; /* take half damage in trainer mode */ + + /* Some close combat weapons should not + * inflict thrust and push the victim out of reach, + * thus kick away unless using the chainsaw. + */ + + if (inflictor && !(target->flags & MF_NOCLIP) && + (!source || !source->player || + source->player->readyweapon != wp_chainsaw)) { - ang = R_PointToAngle2 ( inflictor->x, - inflictor->y, - target->x, - target->y); - - thrust = damage*(FRACUNIT>>3)*100/target->info->mass; - - // make fall forwards sometimes - if ( damage < 40 - && damage > target->health - && target->z - inflictor->z > 64*FRACUNIT - && (P_Random ()&1) ) - { - ang += ANG180; - thrust *= 4; - } - - ang >>= ANGLETOFINESHIFT; - target->momx += FixedMul (thrust, finecosine[ang]); - target->momy += FixedMul (thrust, finesine[ang]); + ang = r_point_to_angle2(inflictor->x, inflictor->y, + target->x, target->y); + + thrust = damage * (FRACUNIT >> 3) * 100 / target->info->mass; + + /* make fall forwards sometimes */ + + if (damage < 40 && damage > target->health && + target->z - inflictor->z > 64 * FRACUNIT && (p_random() & 1)) + { + ang += ANG180; + thrust *= 4; + } + + ang >>= ANGLETOFINESHIFT; + target->momx += fixed_mul(thrust, finecosine[ang]); + target->momy += fixed_mul(thrust, finesine[ang]); } - - // player specific - if (player) + + /* player specific */ + + if (player) { - // end of game hell hack - if (target->subsector->sector->special == 11 - && damage >= target->health) - { - damage = target->health - 1; - } - - - // Below certain threshold, - // ignore damage in GOD mode, or with INVUL power. - if ( damage < 1000 - && ( (player->cheats&CF_GODMODE) - || player->powers[pw_invulnerability] ) ) - { - return; - } - - if (player->armortype) - { - if (player->armortype == 1) - saved = damage/3; - else - saved = damage/2; - - if (player->armorpoints <= saved) - { - // armor is used up - saved = player->armorpoints; - player->armortype = 0; - } - player->armorpoints -= saved; - damage -= saved; - } - player->health -= damage; // mirror mobj health here for Dave - if (player->health < 0) - player->health = 0; - - player->attacker = source; - player->damagecount += damage; // add damage after armor / invuln - - if (player->damagecount > 100) - player->damagecount = 100; // teleport stomp does 10k points... - - temp = damage < 100 ? damage : 100; - - if (player == &players[consoleplayer]) - I_Tactile (40,10,40+temp*2); + /* end of game hell hack */ + + if (target->subsector->sector->special == 11 && + damage >= target->health) + { + damage = target->health - 1; + } + + /* Below certain threshold, ignore damage in GOD mode, or with INVUL + * power. + */ + + if (damage < 1000 && ((player->cheats & CF_GODMODE) || + player->powers[pw_invulnerability])) + { + return; + } + + if (player->armortype) + { + if (player->armortype == 1) + saved = damage / 3; + else + saved = damage / 2; + + if (player->armorpoints <= saved) + { + /* armor is used up */ + + saved = player->armorpoints; + player->armortype = 0; + } + + player->armorpoints -= saved; + damage -= saved; + } + + player->health -= damage; /* mirror mobj health here for Dave */ + if (player->health < 0) player->health = 0; + + player->attacker = source; + player->damagecount += damage; /* add damage after armor / invuln */ + + if (player->damagecount > 100) + { + player->damagecount = 100; /* teleport stomp does 10k points... */ + } + + temp = damage < 100 ? damage : 100; + + if (player == &players[consoleplayer]) + { + i_tactile(40, 10, 40 + temp * 2); + } } - - // do the damage - target->health -= damage; - if (target->health <= 0) + + /* do the damage */ + + target->health -= damage; + if (target->health <= 0) { - P_KillMobj (source, target); - return; + p_kill_mobj(source, target); + return; } - if ( (P_Random () < target->info->painchance) - && !(target->flags&MF_SKULLFLY) ) + if ((p_random() < target->info->painchance) && + !(target->flags & MF_SKULLFLY)) { - target->flags |= MF_JUSTHIT; // fight back! - - P_SetMobjState (target, target->info->painstate); + target->flags |= MF_JUSTHIT; /* fight back! */ + + p_set_mobj_state(target, target->info->painstate); } - - target->reactiontime = 0; // we're awake now... - if ( (!target->threshold || target->type == MT_VILE) - && source && (source != target || gameversion < exe_doom_1_5) - && source->type != MT_VILE) + target->reactiontime = 0; /* we're awake now... */ + + if ((!target->threshold || target->type == MT_VILE) && source && + (source != target || gameversion < exe_doom_1_5) && + source->type != MT_VILE) { - // if not intent on another player, - // chase after this one - target->target = source; - target->threshold = BASETHRESHOLD; - if (target->state == &states[target->info->spawnstate] - && target->info->seestate != S_NULL) - P_SetMobjState (target, target->info->seestate); + /* if not intent on another player, chase after this one */ + + target->target = source; + target->threshold = BASETHRESHOLD; + if (target->state == &states[target->info->spawnstate] && + target->info->seestate != S_NULL) + p_set_mobj_state(target, target->info->seestate); } - } - diff --git a/games/NXDoom/src/doom/p_inter.h b/games/NXDoom/src/doom/p_inter.h index 5764d5dab51..450349e9c7c 100644 --- a/games/NXDoom/src/doom/p_inter.h +++ b/games/NXDoom/src/doom/p_inter.h @@ -1,30 +1,30 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_inter.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ #ifndef __P_INTER__ #define __P_INTER__ +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +boolean p_give_power(player_t *, int); - -boolean P_GivePower(player_t*, int); - - - -#endif +#endif /* __P_INTER__ */ diff --git a/games/NXDoom/src/doom/p_lights.c b/games/NXDoom/src/doom/p_lights.c index 863338dcf3c..019e1c941db 100644 --- a/games/NXDoom/src/doom/p_lights.c +++ b/games/NXDoom/src/doom/p_lights.c @@ -1,350 +1,314 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handle Sector base lighting effects. -// Muzzle flash? -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_lights.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Handle Sector base lighting effects. + * Muzzle flash? + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - -#include "z_zone.h" #include "m_random.h" +#include "z_zone.h" #include "doomdef.h" #include "p_local.h" +/* State. */ -// State. #include "r_state.h" -// -// FIRELIGHT FLICKER -// +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* FIRELIGHT FLICKER */ + +/* t_fire_flicker */ -// -// T_FireFlicker -// -void T_FireFlicker (fireflicker_t* flick) +static void t_fire_flicker(fireflicker_t *flick) { - int amount; - - if (--flick->count) - return; - - amount = (P_Random()&3)*16; - - if (flick->sector->lightlevel - amount < flick->minlight) - flick->sector->lightlevel = flick->minlight; - else - flick->sector->lightlevel = flick->maxlight - amount; - - flick->count = 4; -} + int amount; + if (--flick->count) return; + amount = (p_random() & 3) * 16; -// -// P_SpawnFireFlicker -// -void P_SpawnFireFlicker (sector_t* sector) -{ - fireflicker_t* flick; - - // Note that we are resetting sector attributes. - // Nothing special about it during gameplay. - sector->special = 0; - - flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); - - P_AddThinker (&flick->thinker); - - flick->thinker.function.acp1 = (actionf_p1) T_FireFlicker; - flick->sector = sector; - flick->maxlight = sector->lightlevel; - flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16; - flick->count = 4; + if (flick->sector->lightlevel - amount < flick->minlight) + flick->sector->lightlevel = flick->minlight; + else + flick->sector->lightlevel = flick->maxlight - amount; + + flick->count = 4; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void p_spawn_fire_flicker(sector_t *sector) +{ + fireflicker_t *flick; + + /* Note that we are resetting sector attributes. Nothing special about it + * during gameplay. + */ + + sector->special = 0; + + flick = z_malloc(sizeof(*flick), PU_LEVSPEC, 0); + p_add_thinker(&flick->thinker); -// -// BROKEN LIGHT FLASHING -// + flick->thinker.function.acp1 = (actionf_p1)t_fire_flicker; + flick->sector = sector; + flick->maxlight = sector->lightlevel; + flick->minlight = p_find_min_surrounding(sector, sector->lightlevel) + 16; + flick->count = 4; +} + +/* BROKEN LIGHT FLASHING */ +/* t_light_flash + * Do flashing lights. + */ -// -// T_LightFlash -// Do flashing lights. -// -void T_LightFlash (lightflash_t* flash) +void t_light_flash(lightflash_t *flash) { - if (--flash->count) - return; - - if (flash->sector->lightlevel == flash->maxlight) + if (--flash->count) return; + + if (flash->sector->lightlevel == flash->maxlight) { - flash-> sector->lightlevel = flash->minlight; - flash->count = (P_Random()&flash->mintime)+1; + flash->sector->lightlevel = flash->minlight; + flash->count = (p_random() & flash->mintime) + 1; } - else + else { - flash-> sector->lightlevel = flash->maxlight; - flash->count = (P_Random()&flash->maxtime)+1; + flash->sector->lightlevel = flash->maxlight; + flash->count = (p_random() & flash->maxtime) + 1; } - } +/* p_spawn_light_flash + * After the map has been loaded, scan each sector for specials that spawn + * thinkers + */ - - -// -// P_SpawnLightFlash -// After the map has been loaded, scan each sector -// for specials that spawn thinkers -// -void P_SpawnLightFlash (sector_t* sector) +void p_spawn_light_flash(sector_t *sector) { - lightflash_t* flash; + lightflash_t *flash; - // nothing special about it during gameplay - sector->special = 0; - - flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + /* nothing special about it during gameplay */ - P_AddThinker (&flash->thinker); + sector->special = 0; - flash->thinker.function.acp1 = (actionf_p1) T_LightFlash; - flash->sector = sector; - flash->maxlight = sector->lightlevel; - - flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); - flash->maxtime = 64; - flash->mintime = 7; - flash->count = (P_Random()&flash->maxtime)+1; -} + flash = z_malloc(sizeof(*flash), PU_LEVSPEC, 0); + p_add_thinker(&flash->thinker); + flash->thinker.function.acp1 = (actionf_p1)t_light_flash; + flash->sector = sector; + flash->maxlight = sector->lightlevel; -// -// STROBE LIGHT FLASHING -// + flash->minlight = p_find_min_surrounding(sector, sector->lightlevel); + flash->maxtime = 64; + flash->mintime = 7; + flash->count = (p_random() & flash->maxtime) + 1; +} +/* STROBE LIGHT FLASHING */ -// -// T_StrobeFlash -// -void T_StrobeFlash (strobe_t* flash) +void t_strobe_flash(strobe_t *flash) { - if (--flash->count) - return; - - if (flash->sector->lightlevel == flash->minlight) + if (--flash->count) return; + + if (flash->sector->lightlevel == flash->minlight) { - flash-> sector->lightlevel = flash->maxlight; - flash->count = flash->brighttime; + flash->sector->lightlevel = flash->maxlight; + flash->count = flash->brighttime; } - else + else { - flash-> sector->lightlevel = flash->minlight; - flash->count =flash->darktime; + flash->sector->lightlevel = flash->minlight; + flash->count = flash->darktime; } - } +/* p_spawn_strobe_flash + * After the map has been loaded, scan each sector for specials that spawn + * thinkers + */ - -// -// P_SpawnStrobeFlash -// After the map has been loaded, scan each sector -// for specials that spawn thinkers -// -void -P_SpawnStrobeFlash -( sector_t* sector, - int fastOrSlow, - int inSync ) +void p_spawn_strobe_flash(sector_t *sector, int fast_or_slow, int in_sync) { - strobe_t* flash; - - flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); - - P_AddThinker (&flash->thinker); - - flash->sector = sector; - flash->darktime = fastOrSlow; - flash->brighttime = STROBEBRIGHT; - flash->thinker.function.acp1 = (actionf_p1) T_StrobeFlash; - flash->maxlight = sector->lightlevel; - flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); - - if (flash->minlight == flash->maxlight) - flash->minlight = 0; - - // nothing special about it during gameplay - sector->special = 0; - - if (!inSync) - flash->count = (P_Random()&7)+1; - else - flash->count = 1; + strobe_t *flash; + + flash = z_malloc(sizeof(*flash), PU_LEVSPEC, 0); + + p_add_thinker(&flash->thinker); + + flash->sector = sector; + flash->darktime = fast_or_slow; + flash->brighttime = STROBEBRIGHT; + flash->thinker.function.acp1 = (actionf_p1)t_strobe_flash; + flash->maxlight = sector->lightlevel; + flash->minlight = p_find_min_surrounding(sector, sector->lightlevel); + + if (flash->minlight == flash->maxlight) flash->minlight = 0; + + /* nothing special about it during gameplay */ + + sector->special = 0; + + if (!in_sync) + flash->count = (p_random() & 7) + 1; + else + flash->count = 1; } +/* Start strobing lights (usually from a trigger) */ -// -// Start strobing lights (usually from a trigger) -// -void EV_StartLightStrobing(line_t* line) +void ev_start_light_strobing(line_t *line) { - int secnum; - sector_t* sec; - - secnum = -1; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + int secnum; + sector_t *sec; + + secnum = -1; + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - P_SpawnStrobeFlash (sec,SLOWDARK, 0); + sec = §ors[secnum]; + if (sec->specialdata) continue; + + p_spawn_strobe_flash(sec, SLOWDARK, 0); } } +/* TURN LINE'S TAG LIGHTS OFF */ - -// -// TURN LINE'S TAG LIGHTS OFF -// -void EV_TurnTagLightsOff(line_t* line) +void ev_turn_tag_lights_off(line_t *line) { - int i; - int j; - int min; - sector_t* sector; - sector_t* tsec; - line_t* templine; - - sector = sectors; - - for (j = 0;j < numsectors; j++, sector++) + int i; + int j; + int min; + sector_t *sector; + sector_t *tsec; + line_t *templine; + + sector = sectors; + + for (j = 0; j < numsectors; j++, sector++) { - if (sector->tag == line->tag) - { - min = sector->lightlevel; - for (i = 0;i < sector->linecount; i++) - { - templine = sector->lines[i]; - tsec = getNextSector(templine,sector); - if (!tsec) - continue; - if (tsec->lightlevel < min) - min = tsec->lightlevel; - } - sector->lightlevel = min; - } + if (sector->tag == line->tag) + { + min = sector->lightlevel; + for (i = 0; i < sector->linecount; i++) + { + templine = sector->lines[i]; + tsec = get_next_sector(templine, sector); + if (!tsec) continue; + if (tsec->lightlevel < min) min = tsec->lightlevel; + } + + sector->lightlevel = min; + } } } +/* TURN LINE'S TAG LIGHTS ON */ -// -// TURN LINE'S TAG LIGHTS ON -// -void -EV_LightTurnOn -( line_t* line, - int bright ) +void ev_light_turn_on(line_t *line, int bright) { - int i; - int j; - sector_t* sector; - sector_t* temp; - line_t* templine; - - sector = sectors; - - for (i=0;itag == line->tag) - { - // bright = 0 means to search - // for highest light level - // surrounding sector - if (!bright) - { - for (j = 0;j < sector->linecount; j++) - { - templine = sector->lines[j]; - temp = getNextSector(templine,sector); - - if (!temp) - continue; - - if (temp->lightlevel > bright) - bright = temp->lightlevel; - } - } - sector-> lightlevel = bright; - } + if (sector->tag == line->tag) + { + /* bright = 0 means to search for highest light level surrounding + * sector + */ + + if (!bright) + { + for (j = 0; j < sector->linecount; j++) + { + templine = sector->lines[j]; + temp = get_next_sector(templine, sector); + + if (!temp) continue; + + if (temp->lightlevel > bright) bright = temp->lightlevel; + } + } + + sector->lightlevel = bright; + } } } - -// -// Spawn glowing light -// +/* Spawn glowing light */ -void T_Glow(glow_t* g) +void t_glow(glow_t *g) { - switch(g->direction) + switch (g->direction) { - case -1: - // DOWN - g->sector->lightlevel -= GLOWSPEED; - if (g->sector->lightlevel <= g->minlight) - { - g->sector->lightlevel += GLOWSPEED; - g->direction = 1; - } - break; - - case 1: - // UP - g->sector->lightlevel += GLOWSPEED; - if (g->sector->lightlevel >= g->maxlight) - { - g->sector->lightlevel -= GLOWSPEED; - g->direction = -1; - } - break; + case -1: /* DOWN */ + g->sector->lightlevel -= GLOWSPEED; + if (g->sector->lightlevel <= g->minlight) + { + g->sector->lightlevel += GLOWSPEED; + g->direction = 1; + } + break; + + case 1: /* UP */ + g->sector->lightlevel += GLOWSPEED; + if (g->sector->lightlevel >= g->maxlight) + { + g->sector->lightlevel -= GLOWSPEED; + g->direction = -1; + } + break; } } - -void P_SpawnGlowingLight(sector_t* sector) +void p_spawn_glowing_light(sector_t *sector) { - glow_t* g; - - g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); + glow_t *g; - P_AddThinker(&g->thinker); + g = z_malloc(sizeof(*g), PU_LEVSPEC, 0); - g->sector = sector; - g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); - g->maxlight = sector->lightlevel; - g->thinker.function.acp1 = (actionf_p1) T_Glow; - g->direction = -1; + p_add_thinker(&g->thinker); - sector->special = 0; -} + g->sector = sector; + g->minlight = p_find_min_surrounding(sector, sector->lightlevel); + g->maxlight = sector->lightlevel; + g->thinker.function.acp1 = (actionf_p1)t_glow; + g->direction = -1; + sector->special = 0; +} diff --git a/games/NXDoom/src/doom/p_local.h b/games/NXDoom/src/doom/p_local.h index 41159676223..30bd51d635a 100644 --- a/games/NXDoom/src/doom/p_local.h +++ b/games/NXDoom/src/doom/p_local.h @@ -1,305 +1,268 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Play functions, animation, global header. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_local.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Play functions, animation, global header. + * + ****************************************************************************/ #ifndef __P_LOCAL__ #define __P_LOCAL__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #ifndef __R_LOCAL__ #include "r_local.h" #endif -#define FLOATSPEED (FRACUNIT*4) +/* P_SPEC */ +#include "p_spec.h" -#define MAXHEALTH 100 -#define VIEWHEIGHT (41*FRACUNIT) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// mapblocks are used to check movement -// against lines and things -#define MAPBLOCKUNITS 128 -#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) -#define MAPBLOCKSHIFT (FRACBITS+7) -#define MAPBMASK (MAPBLOCKSIZE-1) -#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) +#define FLOATSPEED (FRACUNIT * 4) +#define MAXHEALTH 100 +#define VIEWHEIGHT (41 * FRACUNIT) -// player radius for movement checking -#define PLAYERRADIUS 16*FRACUNIT +/* mapblocks are used to check movement against lines and things */ -// MAXRADIUS is for precalculated sector block boxes -// the spider demon is larger, -// but we do not have any moving sectors nearby -#define MAXRADIUS 32*FRACUNIT +#define MAPBLOCKUNITS 128 +#define MAPBLOCKSIZE (MAPBLOCKUNITS * FRACUNIT) +#define MAPBLOCKSHIFT (FRACBITS + 7) +#define MAPBMASK (MAPBLOCKSIZE - 1) +#define MAPBTOFRAC (MAPBLOCKSHIFT - FRACBITS) -#define GRAVITY FRACUNIT -#define MAXMOVE (30*FRACUNIT) +/* player radius for movement checking */ -#define USERANGE (64*FRACUNIT) -#define MELEERANGE (64*FRACUNIT) -#define MISSILERANGE (32*64*FRACUNIT) +#define PLAYERRADIUS 16 * FRACUNIT -// follow a player exlusively for 3 seconds -#define BASETHRESHOLD 100 +/* MAXRADIUS is for precalculated sector block boxes the spider demon is + * larger, but we do not have any moving sectors nearby + */ +#define MAXRADIUS 32 * FRACUNIT +#define GRAVITY FRACUNIT +#define MAXMOVE (30 * FRACUNIT) -// -// P_TICK -// +#define USERANGE (64 * FRACUNIT) +#define MELEERANGE (64 * FRACUNIT) +#define MISSILERANGE (32 * 64 * FRACUNIT) -// both the head and tail of the thinker list -extern thinker_t thinkercap; +/* follow a player exclusively for 3 seconds */ +#define BASETHRESHOLD 100 -void P_InitThinkers (void); -void P_AddThinker (thinker_t* thinker); -void P_RemoveThinker (thinker_t* thinker); +#define ONFLOORZ INT_MIN +#define ONCEILINGZ INT_MAX +/* Time interval for item respawning. */ -// -// P_PSPR -// -void P_SetupPsprites (player_t* curplayer); -void P_MovePsprites (player_t* curplayer); -void P_DropWeapon (player_t* player); +#define ITEMQUESIZE 128 +/* Extended MAXINTERCEPTS, to allow for intercepts overrun emulation. */ -// -// P_USER -// -void P_PlayerThink (player_t* player); +#define MAXINTERCEPTS_ORIGINAL 128 +#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61) +#define PT_ADDLINES 1 +#define PT_ADDTHINGS 2 +#define PT_EARLYOUT 4 -// -// P_MOBJ -// -#define ONFLOORZ INT_MIN -#define ONCEILINGZ INT_MAX +/* fraggle: I have increased the size of this buffer. In the original Doom, + * overrunning past this limit caused other bits of memory to be overwritten, + * affecting demo playback. However, in doing so, the limit was still + * exceeded. So we have to support more than 8 specials. + * + * We keep the original limit, to detect what variables in memory were + * overwritten (see SpechitOverrun()) + */ -// Time interval for item respawning. -#define ITEMQUESIZE 128 +#define MAXSPECIALCROSS 20 +#define MAXSPECIALCROSS_ORIGINAL 8 -extern mapthing_t itemrespawnque[ITEMQUESIZE]; -extern int itemrespawntime[ITEMQUESIZE]; -extern int iquehead; -extern int iquetail; +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* P_MAPUTL */ -void P_RespawnSpecials (void); +typedef struct +{ + fixed_t x; + fixed_t y; + fixed_t dx; + fixed_t dy; +} divline_t; -mobj_t* -P_SpawnMobj -( fixed_t x, - fixed_t y, - fixed_t z, - mobjtype_t type ); +typedef struct +{ + fixed_t frac; /* along trace line */ + boolean isaline; + union + { + mobj_t *thing; + line_t *line; + } d; +} intercept_t; -void P_RemoveMobj (mobj_t* th); -mobj_t* P_SubstNullMobj (mobj_t* th); -boolean P_SetMobjState (mobj_t* mobj, statenum_t state); -void P_MobjThinker (mobj_t* mobj); +typedef boolean (*traverser_t)(intercept_t *in); -void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); -void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); -mobj_t* P_SpawnMissile (mobj_t* source, mobj_t* dest, mobjtype_t type); -void P_SpawnPlayerMissile (mobj_t* source, mobjtype_t type); +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* P_TICK */ -// -// P_ENEMY -// -void P_NoiseAlert (mobj_t* target, mobj_t* emmiter); +/* both the head and tail of the thinker list */ +extern thinker_t thinkercap; -// -// P_MAPUTL -// -typedef struct -{ - fixed_t x; - fixed_t y; - fixed_t dx; - fixed_t dy; - -} divline_t; +extern mapthing_t itemrespawnque[ITEMQUESIZE]; +extern int itemrespawntime[ITEMQUESIZE]; +extern int iquehead; +extern int iquetail; -typedef struct -{ - fixed_t frac; // along trace line - boolean isaline; - union { - mobj_t* thing; - line_t* line; - } d; -} intercept_t; +extern intercept_t intercepts[MAXINTERCEPTS]; +extern intercept_t *intercept_p; -// Extended MAXINTERCEPTS, to allow for intercepts overrun emulation. +extern fixed_t opentop; +extern fixed_t openbottom; +extern fixed_t openrange; +extern fixed_t lowfloor; -#define MAXINTERCEPTS_ORIGINAL 128 -#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61) +extern divline_t trace; -extern intercept_t intercepts[MAXINTERCEPTS]; -extern intercept_t* intercept_p; +/* If "floatok" true, move would be ok if within "tmfloorz - tmceilingz". */ -typedef boolean (*traverser_t) (intercept_t *in); +extern boolean floatok; +extern fixed_t tmfloorz; +extern fixed_t tmceilingz; -fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); -int P_PointOnLineSide (fixed_t x, fixed_t y, line_t* line); -int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t* line); -void P_MakeDivline (line_t* li, divline_t* dl); -fixed_t P_InterceptVector (divline_t* v2, divline_t* v1); -int P_BoxOnLineSide (fixed_t* tmbox, line_t* ld); +extern line_t *ceilingline; -extern fixed_t opentop; -extern fixed_t openbottom; -extern fixed_t openrange; -extern fixed_t lowfloor; +extern line_t *spechit[MAXSPECIALCROSS]; +extern int numspechit; -void P_LineOpening (line_t* linedef); +extern mobj_t *linetarget; /* who got hit (or NULL) */ -boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); -boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ); +extern fixed_t attackrange; -#define PT_ADDLINES 1 -#define PT_ADDTHINGS 2 -#define PT_EARLYOUT 4 +/* slopes to top and bottom of target */ -extern divline_t trace; +extern fixed_t topslope; +extern fixed_t bottomslope; -boolean -P_PathTraverse -( fixed_t x1, - fixed_t y1, - fixed_t x2, - fixed_t y2, - int flags, - boolean (*trav) (intercept_t *)); +extern byte *rejectmatrix; /* for fast sight rejection */ +extern short *blockmaplump; /* offsets in blockmap are from here */ +extern short *blockmap; +extern int bmapwidth; +extern int bmapheight; /* in mapblocks */ +extern fixed_t bmaporgx; +extern fixed_t bmaporgy; /* origin of block map */ +extern mobj_t **blocklinks; /* for thing chains */ -void P_UnsetThingPosition (mobj_t* thing); -void P_SetThingPosition (mobj_t* thing); +extern int maxammo[NUMAMMO]; +extern int clipammo[NUMAMMO]; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// -// P_MAP -// +void p_init_thinkers(void); +void p_add_thinker(thinker_t *thinker); +void p_remove_thinker(thinker_t *thinker); -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -extern boolean floatok; -extern fixed_t tmfloorz; -extern fixed_t tmceilingz; +/* P_PSPR */ +void p_setup_psprites(player_t *curplayer); +void p_move_psprites(player_t *curplayer); +void p_drop_weapon(player_t *player); -extern line_t* ceilingline; +/* P_USER */ -// fraggle: I have increased the size of this buffer. In the original Doom, -// overrunning past this limit caused other bits of memory to be overwritten, -// affecting demo playback. However, in doing so, the limit was still -// exceeded. So we have to support more than 8 specials. -// -// We keep the original limit, to detect what variables in memory were -// overwritten (see SpechitOverrun()) +void p_player_think(player_t *player); -#define MAXSPECIALCROSS 20 -#define MAXSPECIALCROSS_ORIGINAL 8 +/* P_MOBJ */ -extern line_t* spechit[MAXSPECIALCROSS]; -extern int numspechit; +void p_respawn_specials(void); -boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); -boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); -boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y); -void P_SlideMove (mobj_t* mo); -boolean P_CheckSight (mobj_t* t1, mobj_t* t2); -void P_UseLines (player_t* player); +mobj_t *p_spawn_mobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); -boolean P_ChangeSector (sector_t* sector, boolean crunch); +void p_remove_mobj(mobj_t *th); +mobj_t *p_subst_null_mobj(mobj_t *th); +boolean p_set_mobj_state(mobj_t *mobj, statenum_t state); +void p_mobj_thinker(mobj_t *mobj); -extern mobj_t* linetarget; // who got hit (or NULL) +void p_spawn_puff(fixed_t x, fixed_t y, fixed_t z); +void p_spawn_blood(fixed_t x, fixed_t y, fixed_t z, int damage); +mobj_t *p_spawn_missile(mobj_t *source, mobj_t *dest, mobjtype_t type); +void p_spawn_player_missile(mobj_t *source, mobjtype_t type); +/* P_ENEMY */ -extern fixed_t attackrange; +void p_noise_alert(mobj_t *target, mobj_t *emmiter); -// slopes to top and bottom of target -extern fixed_t topslope; -extern fixed_t bottomslope; - - -fixed_t -P_AimLineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance ); - -void -P_LineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance, - fixed_t slope, - int damage ); - -void -P_RadiusAttack -( mobj_t* spot, - mobj_t* source, - int damage ); - - - -// -// P_SETUP -// -extern byte* rejectmatrix; // for fast sight rejection -extern short* blockmaplump; // offsets in blockmap are from here -extern short* blockmap; -extern int bmapwidth; -extern int bmapheight; // in mapblocks -extern fixed_t bmaporgx; -extern fixed_t bmaporgy; // origin of block map -extern mobj_t** blocklinks; // for thing chains - - - -// -// P_INTER -// -extern int maxammo[NUMAMMO]; -extern int clipammo[NUMAMMO]; - -void -P_TouchSpecialThing -( mobj_t* special, - mobj_t* toucher ); - -void -P_DamageMobj -( mobj_t* target, - mobj_t* inflictor, - mobj_t* source, - int damage ); - - -// -// P_SPEC -// -#include "p_spec.h" +fixed_t p_approx_distance(fixed_t dx, fixed_t dy); +int p_point_on_line_side(fixed_t x, fixed_t y, line_t *line); +int p_point_on_divline_side(fixed_t x, fixed_t y, divline_t *line); +int p_box_on_line_side(fixed_t *tmbox, line_t *ld); + +void p_line_opening(line_t *linedef); + +boolean p_block_lines_iterator(int x, int y, boolean (*func)(line_t *)); +boolean p_block_things_iterator(int x, int y, boolean (*func)(mobj_t *)); + +boolean p_path_traverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, + int flags, boolean (*trav)(intercept_t *)); + +void p_unset_thing_position(mobj_t *thing); +void p_set_thing_position(mobj_t *thing); + +/* P_MAP */ + +boolean p_check_position(mobj_t *thing, fixed_t x, fixed_t y); +boolean p_try_move(mobj_t *thing, fixed_t x, fixed_t y); +boolean p_teleport_move(mobj_t *thing, fixed_t x, fixed_t y); +void p_slide_move(mobj_t *mo); +boolean p_check_sight(mobj_t *t1, mobj_t *t2); +void p_use_lines(player_t *player); + +boolean p_change_sector(sector_t *sector, boolean crunch); + +fixed_t p_aim_line_attack(mobj_t *t1, angle_t angle, fixed_t distance); + +void p_line_attack(mobj_t *t1, angle_t angle, fixed_t distance, + fixed_t slope, int damage); + +void p_radius_attack(mobj_t *spot, mobj_t *source, int damage); + +/* P_INTER */ + +void p_touch_special_thing(mobj_t *special, mobj_t *toucher); +void p_damage_mobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, + int damage); -#endif // __P_LOCAL__ +#endif /* __P_LOCAL__ */ diff --git a/games/NXDoom/src/doom/p_map.c b/games/NXDoom/src/doom/p_map.c index 425416ce7fc..2b4aa4386b4 100644 --- a/games/NXDoom/src/doom/p_map.c +++ b/games/NXDoom/src/doom/p_map.c @@ -1,1445 +1,1470 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard, Andrey Budko -// -// 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. -// -// DESCRIPTION: -// Movement, collision handling. -// Shooting and aiming. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_map.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard, Andrey Budko + * + * 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. + * + * DESCRIPTION: + * Movement, collision handling. + * Shooting and aiming. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include #include "deh_misc.h" +#include "i_system.h" #include "m_bbox.h" #include "m_random.h" -#include "i_system.h" #include "doomdef.h" #include "m_argv.h" #include "m_misc.h" #include "p_local.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif -// State. #include "doomstat.h" #include "r_state.h" -// Data. -#include "sounds.h" -// Spechit overrun magic value. -// -// This is the value used by PrBoom-plus. I think the value below is -// actually better and works with more demos. However, I think -// it's better for the spechits emulation to be compatible with -// PrBoom-plus, at least so that the big spechits emulation list -// on Doomworld can also be used with Chocolate Doom. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Spechit overrun magic value. + * + * This is the value used by PrBoom-plus. I think the value below is + * actually better and works with more demos. However, I think + * it's better for the spechits emulation to be compatible with + * PrBoom-plus, at least so that the big spechits emulation list + * on Doomworld can also be used with Chocolate Doom. + */ #define DEFAULT_SPECHIT_MAGIC 0x01C09C98 -// This is from a post by myk on the Doomworld forums, -// outputted from entryway's spechit_magic generator for -// s205n546.lmp. The _exact_ value of this isn't too -// important; as long as it is in the right general -// range, it will usually work. Otherwise, we can use -// the generator (hacked doom2.exe) and provide it -// with -spechit. +/* This is from a post by myk on the Doomworld forums, + * outputted from entryway's spechit_magic generator for + * s205n546.lmp. The _exact_ value of this isn't too + * important; as long as it is in the right general + * range, it will usually work. Otherwise, we can use + * the generator (hacked doom2.exe) and provide it + * with -spechit. + */ -//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8 +/* #define DEFAULT_SPECHIT_MAGIC 0x84f968e8 */ +/**************************************************************************** + * Public Data + ****************************************************************************/ -fixed_t tmbbox[4]; -mobj_t* tmthing; -int tmflags; -fixed_t tmx; -fixed_t tmy; +fixed_t tmbbox[4]; +mobj_t *tmthing; +int tmflags; +fixed_t tmx; +fixed_t tmy; +/* If "floatok" true, move would be ok + * if within "tmfloorz - tmceilingz". + */ -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -boolean floatok; +boolean floatok; -fixed_t tmfloorz; -fixed_t tmceilingz; -fixed_t tmdropoffz; +fixed_t tmfloorz; +fixed_t tmceilingz; +fixed_t tmdropoffz; -// keep track of the line that lowers the ceiling, -// so missiles don't explode against sky hack walls -line_t* ceilingline; +/* keep track of the line that lowers the ceiling, + * so missiles don't explode against sky hack walls + */ -// keep track of special lines as they are hit, -// but don't process them until the move is proven valid +line_t *ceilingline; -line_t* spechit[MAXSPECIALCROSS]; -int numspechit; +/* keep track of special lines as they are hit, + * but don't process them until the move is proven valid + */ +line_t *spechit[MAXSPECIALCROSS]; +int numspechit; +/* SLIDE MOVE + * Allows the player to slide along any angled walls. + */ -// -// TELEPORT MOVE -// +fixed_t bestslidefrac; +fixed_t secondslidefrac; -// -// PIT_StompThing -// -boolean PIT_StompThing (mobj_t* thing) -{ - fixed_t blockdist; - - if (!(thing->flags & MF_SHOOTABLE) ) - return true; - - blockdist = thing->radius + tmthing->radius; - - if ( abs(thing->x - tmx) >= blockdist - || abs(thing->y - tmy) >= blockdist ) - { - // didn't hit it - return true; - } - - // don't clip against self - if (thing == tmthing) - return true; - - // monsters don't stomp things except on boss level - if ( !tmthing->player && gamemap != 30) - return false; - - P_DamageMobj (thing, tmthing, tmthing, 10000); - - return true; -} +line_t *bestslideline; +line_t *secondslideline; +mobj_t *slidemo; -// -// P_TeleportMove -// -boolean -P_TeleportMove -( mobj_t* thing, - fixed_t x, - fixed_t y ) -{ - int xl; - int xh; - int yl; - int yh; - int bx; - int by; - - subsector_t* newsubsec; - - // kill anything occupying the position - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector (x,y); - ceilingline = NULL; - - // The base floor/ceiling is from the subsector - // that contains the point. - // Any contacted lines the step closer together - // will adjust them. - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - - // stomp on any things contacted - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockThingsIterator(bx,by,PIT_StompThing)) - return false; - - // the move is ok, - // so link the thing into its new position - P_UnsetThingPosition (thing); - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - - P_SetThingPosition (thing); - - return true; -} +fixed_t tmxmove; +fixed_t tmymove; + +/* p_line_attack */ + +mobj_t *linetarget; /* who got hit (or NULL) */ +mobj_t *shootthing; +/* Height if not aiming up or down + * ???: use slope for monsters? + */ -// -// MOVEMENT ITERATOR FUNCTIONS -// +fixed_t shootz; -static void SpechitOverrun(line_t *ld); +int la_damage; +fixed_t attackrange; -// -// PIT_CheckLine -// Adjusts tmfloorz and tmceilingz as lines are contacted -// -boolean PIT_CheckLine (line_t* ld) +fixed_t aimslope; + +/* USE LINES */ + +mobj_t *usething; + +/* RADIUS ATTACK */ + +mobj_t *bombsource; +mobj_t *bombspot; +int bombdamage; + +/* SECTOR HEIGHT CHANGING + * After modifying a sectors floor or ceiling height, + * call this routine to adjust the positions + * of all things that touch the sector. + * + * If anything doesn't fit anymore, true will be returned. + * + * If crunch is true, they will take damage as they are being crushed. + * + * If Crunch is false, you should set the sector height back the way it was + * and call p_change_sector again to undo the changes. + */ + +boolean crushchange; +boolean nofit; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* TELEPORT MOVE */ + +static boolean pit_stomp_thing(mobj_t *thing) { - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) - return true; - - if (P_BoxOnLineSide (tmbbox, ld) != -1) - return true; - - // A line has been hit - - // The moving thing's destination position will cross - // the given line. - // If this should not be allowed, return false. - // If the line is special, keep track of it - // to process later if the move is proven ok. - // NOTE: specials are NOT sorted by order, - // so two special lines that are only 8 pixels apart - // could be crossed in either order. - - if (!ld->backsector) - return false; // one sided line - - if (!(tmthing->flags & MF_MISSILE) ) - { - if ( ld->flags & ML_BLOCKING ) - return false; // explicitly blocking everything + fixed_t blockdist; - if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS ) - return false; // block monsters only - } + if (!(thing->flags & MF_SHOOTABLE)) return true; + + blockdist = thing->radius + tmthing->radius; - // set openrange, opentop, openbottom - P_LineOpening (ld); - - // adjust floor / ceiling heights - if (opentop < tmceilingz) + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) { - tmceilingz = opentop; - ceilingline = ld; + return true; /* didn't hit it */ } - if (openbottom > tmfloorz) - tmfloorz = openbottom; + /* don't clip against self */ - if (lowfloor < tmdropoffz) - tmdropoffz = lowfloor; - - // if contacted a special line, add it to the list - if (ld->special) + if (thing == tmthing) return true; + + /* monsters don't stomp things except on boss level */ + + if (!tmthing->player && gamemap != 30) return false; + + p_damage_mobj(thing, tmthing, tmthing, 10000); + + return true; +} + +/* Code to emulate the behavior of Vanilla Doom when encountering an overrun + * of the spechit array. This is by Andrey Budko (e6y) and comes from his + * PrBoom plus port. A big thanks to Andrey for this. + */ + +static void spechit_overrun(line_t *ld) +{ + static unsigned int baseaddr = 0; + unsigned int addr; + + if (baseaddr == 0) { - spechit[numspechit] = ld; - numspechit++; + int p; + + /* This is the first time we have had an overrun. Work out + * what base address we are going to use. + * Allow a spechit value to be specified on the command line. + */ + + /* @category compat + * @arg + * + * Use the specified magic value when emulating spechit overruns. + */ + + p = m_check_parm_with_args("-spechit", 1); - // fraggle: spechits overrun emulation code from prboom-plus - if (numspechit > MAXSPECIALCROSS_ORIGINAL) + if (p > 0) { - SpechitOverrun(ld); + m_str_to_int(myargv[p + 1], (int *)&baseaddr); + } + else + { + baseaddr = DEFAULT_SPECHIT_MAGIC; } } - return true; + /* Calculate address used in doom2.exe */ + + addr = baseaddr + (ld - lines) * 0x3e; + + switch (numspechit) + { + case 9: + case 10: + case 11: + case 12: + tmbbox[numspechit - 9] = addr; + break; + case 13: + crushchange = addr; + break; + case 14: + nofit = addr; + break; + default: + fprintf(stderr, + "SpechitOverrun: Warning: unable to emulate" + "an overrun where numspechit=%i\n", + numspechit); + break; + } } -// -// PIT_CheckThing -// -boolean PIT_CheckThing (mobj_t* thing) +/* pit_check_line + * Adjusts tmfloorz and tmceilingz as lines are contacted + */ + +static boolean pit_check_line(line_t *ld) { - fixed_t blockdist; - boolean solid; - int damage; - - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) )) - return true; - - blockdist = thing->radius + tmthing->radius; - - if ( abs(thing->x - tmx) >= blockdist - || abs(thing->y - tmy) >= blockdist ) + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || + tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || + tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || + tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) { - // didn't hit it - return true; + return true; } - - // don't clip against self - if (thing == tmthing) - return true; - - // check for skulls slamming into things - if (tmthing->flags & MF_SKULLFLY) + + if (p_box_on_line_side(tmbbox, ld) != -1) return true; + + /* A line has been hit */ + + /* The moving thing's destination position will cross + * the given line. + * If this should not be allowed, return false. + * If the line is special, keep track of it + * to process later if the move is proven ok. + * NOTE: specials are NOT sorted by order, + * so two special lines that are only 8 pixels apart + * could be crossed in either order. + */ + + if (!ld->backsector) return false; /* one sided line */ + + if (!(tmthing->flags & MF_MISSILE)) { - damage = ((P_Random()%8)+1)*tmthing->info->damage; - - P_DamageMobj (thing, tmthing, tmthing, damage); - - tmthing->flags &= ~MF_SKULLFLY; - tmthing->momx = tmthing->momy = tmthing->momz = 0; - - P_SetMobjState (tmthing, tmthing->info->spawnstate); - - return false; // stop moving + if (ld->flags & ML_BLOCKING) + { + return false; /* explicitly blocking everything */ + } + + if (!tmthing->player && ld->flags & ML_BLOCKMONSTERS) + { + return false; /* block monsters only */ + } } - - // missiles can hit other things - if (tmthing->flags & MF_MISSILE) + /* set openrange, opentop, openbottom */ + + p_line_opening(ld); + + /* adjust floor / ceiling heights */ + + if (opentop < tmceilingz) { - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z+tmthing->height < thing->z) - return true; // underneath - - if (tmthing->target - && (tmthing->target->type == thing->type || - (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)|| - (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) ) - { - // Don't hit same species as originator. - if (thing == tmthing->target) - return true; - - // sdh: Add deh_species_infighting here. We can override the - // "monsters of the same species cant hurt each other" behavior - // through dehacked patches - - if (thing->type != MT_PLAYER && !deh_species_infighting) - { - // Explode, but do no damage. - // Let players missile other players. - return false; - } - } - - if (! (thing->flags & MF_SHOOTABLE) ) - { - // didn't do any damage - return !(thing->flags & MF_SOLID); - } - - // damage / explode - damage = ((P_Random()%8)+1)*tmthing->info->damage; - P_DamageMobj (thing, tmthing, tmthing->target, damage); - - // don't traverse any more - return false; + tmceilingz = opentop; + ceilingline = ld; } - - // check for special pickup - if (thing->flags & MF_SPECIAL) + + if (openbottom > tmfloorz) tmfloorz = openbottom; + + if (lowfloor < tmdropoffz) tmdropoffz = lowfloor; + + /* if contacted a special line, add it to the list */ + + if (ld->special) { - solid = (thing->flags & MF_SOLID) != 0; - if (tmflags&MF_PICKUP) - { - // can remove thing - P_TouchSpecialThing (thing, tmthing); - } - return !solid; + spechit[numspechit] = ld; + numspechit++; + + /* fraggle: spechits overrun emulation code from prboom-plus */ + + if (numspechit > MAXSPECIALCROSS_ORIGINAL) + { + spechit_overrun(ld); + } } - - return !(thing->flags & MF_SOLID); + + return true; } +/* pit_radius_attack + * "bombsource" is the creature that caused the explosion at "bombspot". + */ -// -// MOVEMENT CLIPPING -// - -// -// P_CheckPosition -// This is purely informative, nothing is modified -// (except things picked up). -// -// in: -// a mobj_t (can be valid or invalid) -// a position to be checked -// (doesn't need to be related to the mobj_t->x,y) -// -// during: -// special things are touched if MF_PICKUP -// early out on solid lines? -// -// out: -// newsubsec -// floorz -// ceilingz -// tmdropoffz -// the lowest point contacted -// (monsters won't move to a dropoff) -// speciallines[] -// numspeciallines -// -boolean -P_CheckPosition -( mobj_t* thing, - fixed_t x, - fixed_t y ) +static boolean pit_radius_attack(mobj_t *thing) { - int xl; - int xh; - int yl; - int yh; - int bx; - int by; - subsector_t* newsubsec; - - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector (x,y); - ceilingline = NULL; - - // The base floor / ceiling is from the subsector - // that contains the point. - // Any contacted lines the step closer together - // will adjust them. - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - - if ( tmflags & MF_NOCLIP ) - return true; - - // Check things first, possibly picking things up. - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) - return false; - - // check lines - xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; - - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) - return false; - - return true; -} + fixed_t dx; + fixed_t dy; + fixed_t dist; + if (!(thing->flags & MF_SHOOTABLE)) return true; -// -// P_TryMove -// Attempt to move to a new position, -// crossing special lines unless MF_TELEPORT is set. -// -boolean -P_TryMove -( mobj_t* thing, - fixed_t x, - fixed_t y ) -{ - fixed_t oldx; - fixed_t oldy; - int side; - int oldside; - line_t* ld; - - floatok = false; - if (!P_CheckPosition (thing, x, y)) - return false; // solid wall or thing - - if ( !(thing->flags & MF_NOCLIP) ) - { - if (tmceilingz - tmfloorz < thing->height) - return false; // doesn't fit - - floatok = true; - - if ( !(thing->flags&MF_TELEPORT) - &&tmceilingz - thing->z < thing->height) - return false; // mobj must lower itself to fit - - if ( !(thing->flags&MF_TELEPORT) - && tmfloorz - thing->z > 24*FRACUNIT ) - return false; // too big a step up - - if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) - && tmfloorz - tmdropoffz > 24*FRACUNIT ) - return false; // don't stand over a dropoff - } - - // the move is ok, - // so link the thing into its new position - P_UnsetThingPosition (thing); - - oldx = thing->x; - oldy = thing->y; - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - - P_SetThingPosition (thing); - - // if any special lines were hit, do the effect - if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) ) + /* Boss spider and cyborg take no damage from concussion. */ + + if (thing->type == MT_CYBORG || thing->type == MT_SPIDER) return true; + + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + + dist = dx > dy ? dx : dy; + dist = (dist - thing->radius) >> FRACBITS; + + if (dist < 0) dist = 0; + + if (dist >= bombdamage) return true; /* out of range */ + + if (p_check_sight(thing, bombspot)) { - while (numspechit--) - { - // see if the line was crossed - ld = spechit[numspechit]; - side = P_PointOnLineSide (thing->x, thing->y, ld); - oldside = P_PointOnLineSide (oldx, oldy, ld); - if (side != oldside) - { - if (ld->special) - P_CrossSpecialLine (ld-lines, oldside, thing); - } - } + /* must be in direct path */ + + p_damage_mobj(thing, bombspot, bombsource, bombdamage - dist); } - return true; + return true; } - -// -// P_ThingHeightClip -// Takes a valid thing and adjusts the thing->floorz, -// thing->ceilingz, and possibly thing->z. -// This is called for all nearby monsters -// whenever a sector changes height. -// If the thing doesn't fit, -// the z will be set to the lowest value -// and false will be returned. -// -boolean P_ThingHeightClip (mobj_t* thing) +/* p_things_height_clip + * Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, and + * possibly thing->z. + * + * This is called for all nearby monsters whenever a sector changes height. + * + * If the thing doesn't fit, the z will be set to the lowest value and false + * will be returned. + */ + +static boolean p_things_height_clip(mobj_t *thing) { - boolean onfloor; - - onfloor = (thing->z == thing->floorz); - - P_CheckPosition (thing, thing->x, thing->y); - // what about stranding a monster partially off an edge? - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - - if (onfloor) + boolean onfloor; + + onfloor = (thing->z == thing->floorz); + + p_check_position(thing, thing->x, thing->y); + + /* what about stranding a monster partially off an edge? */ + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + + if (onfloor) { - // walking monsters rise and fall with the floor - thing->z = thing->floorz; + /* walking monsters rise and fall with the floor */ + + thing->z = thing->floorz; } - else + else { - // don't adjust a floating monster unless forced to - if (thing->z+thing->height > thing->ceilingz) - thing->z = thing->ceilingz - thing->height; - } - - if (thing->ceilingz - thing->floorz < thing->height) - return false; - - return true; -} - + /* don't adjust a floating monster unless forced to */ + if (thing->z + thing->height > thing->ceilingz) + thing->z = thing->ceilingz - thing->height; + } -// -// SLIDE MOVE -// Allows the player to slide along any angled walls. -// -fixed_t bestslidefrac; -fixed_t secondslidefrac; + if (thing->ceilingz - thing->floorz < thing->height) return false; -line_t* bestslideline; -line_t* secondslideline; + return true; +} -mobj_t* slidemo; +/* p_hit_slide_line + * Adjusts the xmove / ymove so that the next move will slide along the wall. + */ -fixed_t tmxmove; -fixed_t tmymove; +static void p_hit_slide_line(line_t *ld) +{ + int side; + angle_t lineangle; + angle_t moveangle; + angle_t deltaangle; + fixed_t movelen; + fixed_t newlen; -// -// P_HitSlideLine -// Adjusts the xmove / ymove -// so that the next move will slide along the wall. -// -void P_HitSlideLine (line_t* ld) -{ - int side; - - angle_t lineangle; - angle_t moveangle; - angle_t deltaangle; - - fixed_t movelen; - fixed_t newlen; - - - if (ld->slopetype == ST_HORIZONTAL) + if (ld->slopetype == ST_HORIZONTAL) { - tmymove = 0; - return; + tmymove = 0; + return; } - - if (ld->slopetype == ST_VERTICAL) + + if (ld->slopetype == ST_VERTICAL) { - tmxmove = 0; - return; + tmxmove = 0; + return; } - - side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); - - lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); - if (side == 1) - lineangle += ANG180; + side = p_point_on_line_side(slidemo->x, slidemo->y, ld); - moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); - deltaangle = moveangle-lineangle; + lineangle = r_point_to_angle2(0, 0, ld->dx, ld->dy); - if (deltaangle > ANG180) - deltaangle += ANG180; - // I_Error ("SlideLine: ang>ANG180"); + if (side == 1) lineangle += ANG180; - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance (tmxmove, tmymove); - newlen = FixedMul (movelen, finecosine[deltaangle]); + moveangle = r_point_to_angle2(0, 0, tmxmove, tmymove); + deltaangle = moveangle - lineangle; - tmxmove = FixedMul (newlen, finecosine[lineangle]); - tmymove = FixedMul (newlen, finesine[lineangle]); + if (deltaangle > ANG180) deltaangle += ANG180; + + lineangle >>= ANGLETOFINESHIFT; + deltaangle >>= ANGLETOFINESHIFT; + + movelen = p_approx_distance(tmxmove, tmymove); + newlen = fixed_mul(movelen, finecosine[deltaangle]); + + tmxmove = fixed_mul(newlen, finecosine[lineangle]); + tmymove = fixed_mul(newlen, finesine[lineangle]); } +/* ptr_slide_traverse */ -// -// PTR_SlideTraverse -// -boolean PTR_SlideTraverse (intercept_t* in) +static boolean ptr_slide_traverse(intercept_t *in) { - line_t* li; - - if (!in->isaline) - I_Error ("PTR_SlideTraverse: not a line?"); - - li = in->d.line; - - if ( ! (li->flags & ML_TWOSIDED) ) - { - if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) - { - // don't hit the back side - return true; - } - goto isblocking; - } + line_t *li; + + if (!in->isaline) i_error("ptr_slide_traverse: not a line?"); - // set openrange, opentop, openbottom - P_LineOpening (li); - - if (openrange < slidemo->height) - goto isblocking; // doesn't fit - - if (opentop - slidemo->z < slidemo->height) - goto isblocking; // mobj is too high - - if (openbottom - slidemo->z > 24*FRACUNIT ) - goto isblocking; // too big a step up - - // this line doesn't block movement - return true; - - // the line does block movement, - // see if it is closer than best so far - isblocking: - if (in->frac < bestslidefrac) + li = in->d.line; + + if (!(li->flags & ML_TWOSIDED)) { - secondslidefrac = bestslidefrac; - secondslideline = bestslideline; - bestslidefrac = in->frac; - bestslideline = li; + if (p_point_on_line_side(slidemo->x, slidemo->y, li)) + { + return true; /* don't hit the back side */ + } + + goto isblocking; } - - return false; // stop -} + /* set openrange, opentop, openbottom */ + p_line_opening(li); -// -// P_SlideMove -// The momx / momy move is bad, so try to slide -// along a wall. -// Find the first line hit, move flush to it, -// and slide along it -// -// This is a kludgy mess. -// -void P_SlideMove (mobj_t* mo) -{ - fixed_t leadx; - fixed_t leady; - fixed_t trailx; - fixed_t traily; - fixed_t newx; - fixed_t newy; - int hitcount; - - slidemo = mo; - hitcount = 0; - - retry: - if (++hitcount == 3) - goto stairstep; // don't loop forever - - - // trace along the three leading corners - if (mo->momx > 0) + if (openrange < slidemo->height) { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; + goto isblocking; /* doesn't fit */ } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) + + if (opentop - slidemo->z < slidemo->height) { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; + goto isblocking; /* mobj is too high */ } - else + + if (openbottom - slidemo->z > 24 * FRACUNIT) { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; + goto isblocking; /* too big a step up */ } - - bestslidefrac = FRACUNIT+1; - - P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, - PT_ADDLINES, PTR_SlideTraverse ); - P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, - PT_ADDLINES, PTR_SlideTraverse ); - P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, - PT_ADDLINES, PTR_SlideTraverse ); - - // move up to the wall - if (bestslidefrac == FRACUNIT+1) + + /* this line doesn't block movement */ + + return true; + + /* the line does block movement, + * see if it is closer than best so far + */ + +isblocking: + if (in->frac < bestslidefrac) { - // the move most have hit the middle, so stairstep - stairstep: - if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) - P_TryMove (mo, mo->x + mo->momx, mo->y); - return; + secondslidefrac = bestslidefrac; + secondslideline = bestslideline; + bestslidefrac = in->frac; + bestslideline = li; } - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) + return false; /* stop */ +} + +static boolean ptr_use_traverse(intercept_t *in) +{ + int side; + + if (!in->d.line->special) { - newx = FixedMul (mo->momx, bestslidefrac); - newy = FixedMul (mo->momy, bestslidefrac); - - if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) - goto stairstep; + p_line_opening(in->d.line); + if (openrange <= 0) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(usething, SFX_NOWAY); +#endif + + /* can't use through a wall */ + + return false; + } + + /* not a special line, but keep checking */ + + return true; } - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT-(bestslidefrac+0x800); - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) - return; - - tmxmove = FixedMul (mo->momx, bestslidefrac); - tmymove = FixedMul (mo->momy, bestslidefrac); - - P_HitSlideLine (bestslideline); // clip the moves - - mo->momx = tmxmove; - mo->momy = tmymove; - - if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove)) + + side = 0; + if (p_point_on_line_side(usething->x, usething->y, in->d.line) == 1) { - goto retry; + side = 1; } -} - -// -// P_LineAttack -// -mobj_t* linetarget; // who got hit (or NULL) -mobj_t* shootthing; + /* return false; don't use back side */ -// Height if not aiming up or down -// ???: use slope for monsters? -fixed_t shootz; + p_use_special_line(usething, in->d.line, side); -int la_damage; -fixed_t attackrange; + /* can't use for than one special line in a row */ -fixed_t aimslope; + return false; +} +/* ptr_aim_traverse + * Sets linetaget and aimslope when a target is aimed at. + */ -// -// PTR_AimTraverse -// Sets linetaget and aimslope when a target is aimed at. -// -boolean -PTR_AimTraverse (intercept_t* in) +static boolean ptr_aim_traverse(intercept_t *in) { - line_t* li; - mobj_t* th; - fixed_t slope; - fixed_t thingtopslope; - fixed_t thingbottomslope; - fixed_t dist; - - if (in->isaline) + line_t *li; + mobj_t *th; + fixed_t slope; + fixed_t thingtopslope; + fixed_t thingbottomslope; + fixed_t dist; + + if (in->isaline) { - li = in->d.line; - - if ( !(li->flags & ML_TWOSIDED) ) - return false; // stop - - // Crosses a two sided line. - // A two sided line will restrict - // the possible target ranges. - P_LineOpening (li); - - if (openbottom >= opentop) - return false; // stop - - dist = FixedMul (attackrange, in->frac); - - if (li->backsector == NULL - || li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv (openbottom - shootz , dist); - if (slope > bottomslope) - bottomslope = slope; - } - - if (li->backsector == NULL - || li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv (opentop - shootz , dist); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - - return true; // shot continues + li = in->d.line; + + if (!(li->flags & ML_TWOSIDED)) return false; /* stop */ + + /* Crosses a two sided line. + * A two sided line will restrict + * the possible target ranges. + */ + + p_line_opening(li); + + if (openbottom >= opentop) return false; /* stop */ + + dist = fixed_mul(attackrange, in->frac); + + if (li->backsector == NULL || + li->frontsector->floorheight != li->backsector->floorheight) + { + slope = fixed_div(openbottom - shootz, dist); + if (slope > bottomslope) bottomslope = slope; + } + + if (li->backsector == NULL || + li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = fixed_div(opentop - shootz, dist); + if (slope < topslope) topslope = slope; + } + + if (topslope <= bottomslope) return false; /* stop */ + + return true; /* shot continues */ } - - // shoot a thing - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - - if (!(th->flags&MF_SHOOTABLE)) - return true; // corpse or something - - // check angles to see if the thing can be aimed at - dist = FixedMul (attackrange, in->frac); - thingtopslope = FixedDiv (th->z+th->height - shootz , dist); - - if (thingtopslope < bottomslope) - return true; // shot over the thing - - thingbottomslope = FixedDiv (th->z - shootz, dist); - - if (thingbottomslope > topslope) - return true; // shot under the thing - - // this thing can be hit! - if (thingtopslope > topslope) - thingtopslope = topslope; - - if (thingbottomslope < bottomslope) - thingbottomslope = bottomslope; - - aimslope = (thingtopslope+thingbottomslope)/2; - linetarget = th; - - return false; // don't go any farther + + /* shoot a thing */ + + th = in->d.thing; + if (th == shootthing) return true; /* can't shoot self */ + + if (!(th->flags & MF_SHOOTABLE)) return true; /* corpse or something */ + + /* check angles to see if the thing can be aimed at */ + + dist = fixed_mul(attackrange, in->frac); + thingtopslope = fixed_div(th->z + th->height - shootz, dist); + + if (thingtopslope < bottomslope) return true; /* shot over the thing */ + + thingbottomslope = fixed_div(th->z - shootz, dist); + + if (thingbottomslope > topslope) return true; /* shot under the thing */ + + /* this thing can be hit! */ + + if (thingtopslope > topslope) thingtopslope = topslope; + + if (thingbottomslope < bottomslope) thingbottomslope = bottomslope; + + aimslope = (thingtopslope + thingbottomslope) / 2; + linetarget = th; + + return false; /* don't go any farther */ } +/* ptr_shoot_traverse */ -// -// PTR_ShootTraverse -// -boolean PTR_ShootTraverse (intercept_t* in) +static boolean ptr_shoot_traverse(intercept_t *in) { - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t frac; - - line_t* li; - - mobj_t* th; - - fixed_t slope; - fixed_t dist; - fixed_t thingtopslope; - fixed_t thingbottomslope; - - if (in->isaline) + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t frac; + + line_t *li; + + mobj_t *th; + + fixed_t slope; + fixed_t dist; + fixed_t thingtopslope; + fixed_t thingbottomslope; + + if (in->isaline) { - li = in->d.line; - - if (li->special) - P_ShootSpecialLine (shootthing, li); - - if ( !(li->flags & ML_TWOSIDED) ) - goto hitline; - - // crosses a two sided line - P_LineOpening (li); - - dist = FixedMul (attackrange, in->frac); - - // e6y: emulation of missed back side on two-sided lines. - // backsector can be NULL when emulating missing back side. - - if (li->backsector == NULL) + li = in->d.line; + + if (li->special) p_shoot_special_line(shootthing, li); + + if (!(li->flags & ML_TWOSIDED)) goto hitline; + + /* crosses a two sided line */ + + p_line_opening(li); + + dist = fixed_mul(attackrange, in->frac); + + /* e6y: emulation of missed back side on two-sided lines. + * backsector can be NULL when emulating missing back side. + */ + + if (li->backsector == NULL) { - slope = FixedDiv (openbottom - shootz , dist); - if (slope > aimslope) - goto hitline; + slope = fixed_div(openbottom - shootz, dist); + if (slope > aimslope) goto hitline; - slope = FixedDiv (opentop - shootz , dist); - if (slope < aimslope) - goto hitline; + slope = fixed_div(opentop - shootz, dist); + if (slope < aimslope) goto hitline; } - else + else { - if (li->frontsector->floorheight != li->backsector->floorheight) + if (li->frontsector->floorheight + != li->backsector->floorheight) { - slope = FixedDiv (openbottom - shootz , dist); - if (slope > aimslope) - goto hitline; + slope = fixed_div(openbottom - shootz, dist); + if (slope > aimslope) goto hitline; } - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + if (li->frontsector->ceilingheight + != li->backsector->ceilingheight) { - slope = FixedDiv (opentop - shootz , dist); - if (slope < aimslope) - goto hitline; + slope = fixed_div(opentop - shootz, dist); + if (slope < aimslope) goto hitline; } } - // shot continues - return true; - - - // hit line - hitline: - // position a bit closer - frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); - x = trace.x + FixedMul (trace.dx, frac); - y = trace.y + FixedMul (trace.dy, frac); - z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); - - if (li->frontsector->ceilingpic == skyflatnum) - { - // don't shoot the sky! - if (z > li->frontsector->ceilingheight) - return false; - - // it's a sky hack wall - if (li->backsector && li->backsector->ceilingpic == skyflatnum) - return false; - } - - // Spawn bullet puffs. - P_SpawnPuff (x,y,z); - - // don't go any farther - return false; + /* shot continues */ + + return true; + + /* hit line */ + + hitline: + + /* position a bit closer */ + + frac = in->frac - fixed_div(4 * FRACUNIT, attackrange); + x = trace.x + fixed_mul(trace.dx, frac); + y = trace.y + fixed_mul(trace.dy, frac); + z = shootz + fixed_mul(aimslope, fixed_mul(frac, attackrange)); + + if (li->frontsector->ceilingpic == skyflatnum) + { + /* don't shoot the sky! */ + + if (z > li->frontsector->ceilingheight) return false; + + /* it's a sky hack wall */ + + if (li->backsector && + li->backsector->ceilingpic == skyflatnum) + { + return false; + } + } + + /* Spawn bullet puffs. */ + + p_spawn_puff(x, y, z); + + /* don't go any farther */ + + return false; } - - // shoot a thing - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - - if (!(th->flags&MF_SHOOTABLE)) - return true; // corpse or something - - // check angles to see if the thing can be aimed at - dist = FixedMul (attackrange, in->frac); - thingtopslope = FixedDiv (th->z+th->height - shootz , dist); - - if (thingtopslope < aimslope) - return true; // shot over the thing - - thingbottomslope = FixedDiv (th->z - shootz, dist); - - if (thingbottomslope > aimslope) - return true; // shot under the thing - - - // hit thing - // position a bit closer - frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); - - x = trace.x + FixedMul (trace.dx, frac); - y = trace.y + FixedMul (trace.dy, frac); - z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); - - // Spawn bullet puffs or blod spots, - // depending on target type. - if (in->d.thing->flags & MF_NOBLOOD) - P_SpawnPuff (x,y,z); - else - P_SpawnBlood (x,y,z, la_damage); - - if (la_damage) - P_DamageMobj (th, shootthing, shootthing, la_damage); - - // don't go any farther - return false; - + + /* shoot a thing */ + + th = in->d.thing; + if (th == shootthing) return true; /* can't shoot self */ + + if (!(th->flags & MF_SHOOTABLE)) return true; /* corpse or something */ + + /* check angles to see if the thing can be aimed at */ + + dist = fixed_mul(attackrange, in->frac); + thingtopslope = fixed_div(th->z + th->height - shootz, dist); + + if (thingtopslope < aimslope) return true; /* shot over the thing */ + + thingbottomslope = fixed_div(th->z - shootz, dist); + + if (thingbottomslope > aimslope) return true; /* shot under the thing */ + + /* hit thing position a bit closer */ + + frac = in->frac - fixed_div(10 * FRACUNIT, attackrange); + + x = trace.x + fixed_mul(trace.dx, frac); + y = trace.y + fixed_mul(trace.dy, frac); + z = shootz + fixed_mul(aimslope, fixed_mul(frac, attackrange)); + + /* Spawn bullet puffs or blod spots, + * depending on target type. + */ + + if (in->d.thing->flags & MF_NOBLOOD) + p_spawn_puff(x, y, z); + else + p_spawn_blood(x, y, z, la_damage); + + if (la_damage) p_damage_mobj(th, shootthing, shootthing, la_damage); + + /* don't go any farther */ + + return false; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -// P_AimLineAttack -// -fixed_t -P_AimLineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance ) +/* p_teleport_move */ + +boolean p_teleport_move(mobj_t *thing, fixed_t x, fixed_t y) { - fixed_t x2; - fixed_t y2; - - t1 = P_SubstNullMobj(t1); - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; - - // can't shoot outside view angles - topslope = (SCREENHEIGHT/2)*FRACUNIT/(SCREENWIDTH/2); - bottomslope = -(SCREENHEIGHT/2)*FRACUNIT/(SCREENWIDTH/2); - - attackrange = distance; - linetarget = NULL; - - P_PathTraverse ( t1->x, t1->y, - x2, y2, - PT_ADDLINES|PT_ADDTHINGS, - PTR_AimTraverse ); - - if (linetarget) - return aimslope; - - return 0; + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + + subsector_t *newsubsec; + + /* kill anything occupying the position */ + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = r_point_in_subsector(x, y); + ceilingline = NULL; + + /* The base floor/ceiling is from the subsector + * that contains the point. + * Any contacted lines the step closer together + * will adjust them. + */ + + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + /* stomp on any things contacted */ + + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (!p_block_things_iterator(bx, by, pit_stomp_thing)) + { + return false; + } + } + } + + /* the move is ok, + * so link the thing into its new position + */ + + p_unset_thing_position(thing); + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + p_set_thing_position(thing); + + return true; } - - -// -// P_LineAttack -// If damage == 0, it is just a test trace -// that will leave linetarget set. -// -void -P_LineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance, - fixed_t slope, - int damage ) + +boolean pit_check_thing(mobj_t *thing) { - fixed_t x2; - fixed_t y2; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - la_damage = damage; - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; - attackrange = distance; - aimslope = slope; - - P_PathTraverse ( t1->x, t1->y, - x2, y2, - PT_ADDLINES|PT_ADDTHINGS, - PTR_ShootTraverse ); -} - + fixed_t blockdist; + boolean solid; + int damage; + + if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) return true; + + blockdist = thing->radius + tmthing->radius; + + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + { + return true; /* didn't hit it */ + } + + /* don't clip against self */ + + if (thing == tmthing) return true; + + /* check for skulls slamming into things */ + + if (tmthing->flags & MF_SKULLFLY) + { + damage = ((p_random() % 8) + 1) * tmthing->info->damage; + + p_damage_mobj(thing, tmthing, tmthing, damage); + + tmthing->flags &= ~MF_SKULLFLY; + tmthing->momx = tmthing->momy = tmthing->momz = 0; + + p_set_mobj_state(tmthing, tmthing->info->spawnstate); + + return false; /* stop moving */ + } + + /* missiles can hit other things */ + + if (tmthing->flags & MF_MISSILE) + { + /* see if it went over / under */ + + if (tmthing->z > thing->z + thing->height) + { + return true; /* overhead */ + } + + if (tmthing->z + tmthing->height < thing->z) + { + return true; /* underneath */ + } + + if (tmthing->target && + (tmthing->target->type == thing->type || + (tmthing->target->type == MT_KNIGHT && + thing->type == MT_BRUISER) || + (tmthing->target->type == MT_BRUISER && + thing->type == MT_KNIGHT))) + { + /* Don't hit same species as originator. */ + + if (thing == tmthing->target) return true; + + /* sdh: Add deh_species_infighting here. We can override the + * "monsters of the same species can't hurt each other" behavior + * through dehacked patches + */ + + if (thing->type != MT_PLAYER && !deh_species_infighting) + { + /* Explode, but do no damage. + * Let players missile other players. + */ + return false; + } + } + + if (!(thing->flags & MF_SHOOTABLE)) + { + /* didn't do any damage */ + + return !(thing->flags & MF_SOLID); + } -// -// USE LINES -// -mobj_t* usething; + /* damage / explode */ + + damage = ((p_random() % 8) + 1) * tmthing->info->damage; + p_damage_mobj(thing, tmthing, tmthing->target, damage); + + /* don't traverse any more */ + + return false; + } + + /* check for special pickup */ + + if (thing->flags & MF_SPECIAL) + { + solid = (thing->flags & MF_SOLID) != 0; + if (tmflags & MF_PICKUP) + { + /* can remove thing */ + + p_touch_special_thing(thing, tmthing); + } + + return !solid; + } -boolean PTR_UseTraverse (intercept_t* in) + return !(thing->flags & MF_SOLID); +} + +/* MOVEMENT CLIPPING */ + +/* p_check_position + * This is purely informative, nothing is modified + * (except things picked up). + * + * in: + * a mobj_t (can be valid or invalid) + * a position to be checked + * (doesn't need to be related to the mobj_t->x,y) + * + * during: + * special things are touched if MF_PICKUP + * early out on solid lines? + * + * out: + * newsubsec + * floorz + * ceilingz + * tmdropoffz + * the lowest point contacted + * (monsters won't move to a dropoff) + * speciallines[] + * numspeciallines + */ + +boolean p_check_position(mobj_t *thing, fixed_t x, fixed_t y) { - int side; - - if (!in->d.line->special) + int xl; + int xh; + int yl; + int yh; + int bx; + int by; + subsector_t *newsubsec; + + tmthing = thing; + tmflags = thing->flags; + + tmx = x; + tmy = y; + + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; + + newsubsec = r_point_in_subsector(x, y); + ceilingline = NULL; + + /* The base floor / ceiling is from the subsector + * that contains the point. + * Any contacted lines the step closer together + * will adjust them. + */ + + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + validcount++; + numspechit = 0; + + if (tmflags & MF_NOCLIP) return true; + + /* Check things first, possibly picking things up. + * The bounding box is extended by MAXRADIUS + * because mobj_ts are grouped into mapblocks + * based on their origin point, and can overlap + * into adjacent blocks by up to MAXRADIUS units. + */ + + xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (!p_block_things_iterator(bx, by, pit_check_thing)) + { + return false; + } + } + } + + /* check lines */ + + xl = (tmbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; + + for (bx = xl; bx <= xh; bx++) { - P_LineOpening (in->d.line); - if (openrange <= 0) - { - S_StartSound (usething, sfx_noway); - - // can't use through a wall - return false; - } - // not a special line, but keep checking - return true ; + for (by = yl; by <= yh; by++) + { + if (!p_block_lines_iterator(bx, by, pit_check_line)) + { + return false; + } + } } - - side = 0; - if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) - side = 1; - - // return false; // don't use back side - - P_UseSpecialLine (usething, in->d.line, side); - - // can't use for than one special line in a row - return false; + + return true; } +/* p_try_move + * Attempt to move to a new position, + * crossing special lines unless MF_TELEPORT is set. + */ -// -// P_UseLines -// Looks for special lines in front of the player to activate. -// -void P_UseLines (player_t* player) +boolean p_try_move(mobj_t *thing, fixed_t x, fixed_t y) { - int angle; - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - usething = player->mo; - - angle = player->mo->angle >> ANGLETOFINESHIFT; - - x1 = player->mo->x; - y1 = player->mo->y; - x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; - y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; - - P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); -} + fixed_t oldx; + fixed_t oldy; + int side; + int oldside; + line_t *ld; + + floatok = false; + if (!p_check_position(thing, x, y)) + { + return false; /* solid wall or thing */ + } + + if (!(thing->flags & MF_NOCLIP)) + { + if (tmceilingz - tmfloorz < thing->height) + { + return false; /* doesn't fit */ + } + + floatok = true; + if (!(thing->flags & MF_TELEPORT) && + tmceilingz - thing->z < thing->height) + { + return false; /* mobj must lower itself to fit */ + } -// -// RADIUS ATTACK -// -mobj_t* bombsource; -mobj_t* bombspot; -int bombdamage; + if (!(thing->flags & MF_TELEPORT) && + tmfloorz - thing->z > 24 * FRACUNIT) + { + return false; /* too big a step up */ + } + if (!(thing->flags & (MF_DROPOFF | MF_FLOAT)) && + tmfloorz - tmdropoffz > 24 * FRACUNIT) + { + return false; /* don't stand over a dropoff */ + } + } -// -// PIT_RadiusAttack -// "bombsource" is the creature -// that caused the explosion at "bombspot". -// -boolean PIT_RadiusAttack (mobj_t* thing) -{ - fixed_t dx; - fixed_t dy; - fixed_t dist; - - if (!(thing->flags & MF_SHOOTABLE) ) - return true; - - // Boss spider and cyborg - // take no damage from concussion. - if (thing->type == MT_CYBORG - || thing->type == MT_SPIDER) - return true; - - dx = abs(thing->x - bombspot->x); - dy = abs(thing->y - bombspot->y); - - dist = dx>dy ? dx : dy; - dist = (dist - thing->radius) >> FRACBITS; - - if (dist < 0) - dist = 0; - - if (dist >= bombdamage) - return true; // out of range - - if ( P_CheckSight (thing, bombspot) ) + /* the move is ok, + * so link the thing into its new position + */ + + p_unset_thing_position(thing); + + oldx = thing->x; + oldy = thing->y; + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + thing->x = x; + thing->y = y; + + p_set_thing_position(thing); + + /* if any special lines were hit, do the effect */ + + if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) { - // must be in direct path - P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist); + while (numspechit--) + { + /* see if the line was crossed */ + + ld = spechit[numspechit]; + side = p_point_on_line_side(thing->x, thing->y, ld); + oldside = p_point_on_line_side(oldx, oldy, ld); + if (side != oldside) + { + if (ld->special) + { + p_cross_special_line(ld - lines, oldside, thing); + } + } + } } - - return true; + + return true; } +/* p_slide_move + * The momx / momy move is bad, so try to slide + * along a wall. + * Find the first line hit, move flush to it, + * and slide along it + * + * This is a kludgy mess. + */ -// -// P_RadiusAttack -// Source is the creature that caused the explosion at spot. -// -void -P_RadiusAttack -( mobj_t* spot, - mobj_t* source, - int damage ) +void p_slide_move(mobj_t *mo) { - int x; - int y; - - int xl; - int xh; - int yl; - int yh; - - fixed_t dist; - - dist = (damage+MAXRADIUS)<y + dist - bmaporgy)>>MAPBLOCKSHIFT; - yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; - xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; - xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; - bombspot = spot; - bombsource = source; - bombdamage = damage; - - for (y=yl ; y<=yh ; y++) - for (x=xl ; x<=xh ; x++) - P_BlockThingsIterator (x, y, PIT_RadiusAttack ); -} + fixed_t leadx; + fixed_t leady; + fixed_t trailx; + fixed_t traily; + fixed_t newx; + fixed_t newy; + int hitcount; + slidemo = mo; + hitcount = 0; +retry: + if (++hitcount == 3) goto stairstep; /* don't loop forever */ -// -// SECTOR HEIGHT CHANGING -// After modifying a sectors floor or ceiling height, -// call this routine to adjust the positions -// of all things that touch the sector. -// -// If anything doesn't fit anymore, true will be returned. -// If crunch is true, they will take damage -// as they are being crushed. -// If Crunch is false, you should set the sector height back -// the way it was and call P_ChangeSector again -// to undo the changes. -// -boolean crushchange; -boolean nofit; - - -// -// PIT_ChangeSector -// -boolean PIT_ChangeSector (mobj_t* thing) -{ - mobj_t* mo; - - if (P_ThingHeightClip (thing)) + /* trace along the three leading corners */ + + if (mo->momx > 0) { - // keep checking - return true; + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; } - - // crunch bodies to giblets - if (thing->health <= 0) + if (mo->momy > 0) { - P_SetMobjState (thing, S_GIBS); + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } - if (gameversion > exe_doom_1_2) - thing->flags &= ~MF_SOLID; - thing->height = 0; - thing->radius = 0; + bestslidefrac = FRACUNIT + 1; - // keep checking - return true; - } + p_path_traverse(leadx, leady, leadx + mo->momx, leady + mo->momy, + PT_ADDLINES, ptr_slide_traverse); + p_path_traverse(trailx, leady, trailx + mo->momx, leady + mo->momy, + PT_ADDLINES, ptr_slide_traverse); + p_path_traverse(leadx, traily, leadx + mo->momx, traily + mo->momy, + PT_ADDLINES, ptr_slide_traverse); - // crunch dropped items - if (thing->flags & MF_DROPPED) + /* move up to the wall */ + + if (bestslidefrac == FRACUNIT + 1) { - P_RemoveMobj (thing); - - // keep checking - return true; + /* the move most have hit the middle, so stairstep */ + + stairstep: + if (!p_try_move(mo, mo->x, mo->y + mo->momy)) + p_try_move(mo, mo->x + mo->momx, mo->y); + return; } - if (! (thing->flags & MF_SHOOTABLE) ) + /* fudge a bit to make sure it doesn't hit */ + + bestslidefrac -= 0x800; + if (bestslidefrac > 0) { - // assume it is bloody gibs or something - return true; + newx = fixed_mul(mo->momx, bestslidefrac); + newy = fixed_mul(mo->momy, bestslidefrac); + + if (!p_try_move(mo, mo->x + newx, mo->y + newy)) goto stairstep; } - - nofit = true; - if (crushchange && !(leveltime&3) ) + /* Now continue along the wall. + * First calculate remainder. + */ + + bestslidefrac = FRACUNIT - (bestslidefrac + 0x800); + + if (bestslidefrac > FRACUNIT) bestslidefrac = FRACUNIT; + + if (bestslidefrac <= 0) return; + + tmxmove = fixed_mul(mo->momx, bestslidefrac); + tmymove = fixed_mul(mo->momy, bestslidefrac); + + p_hit_slide_line(bestslideline); /* clip the moves */ + + mo->momx = tmxmove; + mo->momy = tmymove; + + if (!p_try_move(mo, mo->x + tmxmove, mo->y + tmymove)) { - P_DamageMobj(thing,NULL,NULL,10); - - // spray blood in a random direction - mo = P_SpawnMobj (thing->x, - thing->y, - thing->z + thing->height/2, MT_BLOOD); - - mo->momx = P_SubRandom() << 12; - mo->momy = P_SubRandom() << 12; + goto retry; } +} + +/* p_aim_line_attack */ + +fixed_t p_aim_line_attack(mobj_t *t1, angle_t angle, fixed_t distance) +{ + fixed_t x2; + fixed_t y2; + + t1 = p_subst_null_mobj(t1); + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + + x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; + shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; + + /* can't shoot outside view angles */ + + topslope = (SCREENHEIGHT / 2) * FRACUNIT / (SCREENWIDTH / 2); + bottomslope = -(SCREENHEIGHT / 2) * FRACUNIT / (SCREENWIDTH / 2); + + attackrange = distance; + linetarget = NULL; - // keep checking (crush other things) - return true; + p_path_traverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + ptr_aim_traverse); + + if (linetarget) return aimslope; + + return 0; } +/* p_line_attack + * + * If damage == 0, it is just a test trace that will leave linetarget set. + */ +void p_line_attack(mobj_t *t1, angle_t angle, fixed_t distance, + fixed_t slope, int damage) +{ + fixed_t x2; + fixed_t y2; + + angle >>= ANGLETOFINESHIFT; + shootthing = t1; + la_damage = damage; + x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; + y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; + shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; + attackrange = distance; + aimslope = slope; + + p_path_traverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, + ptr_shoot_traverse); +} -// -// P_ChangeSector -// -boolean -P_ChangeSector -( sector_t* sector, - boolean crunch ) +/* p_use_lines + * Looks for special lines in front of the player to activate. + */ + +void p_use_lines(player_t *player) { - int x; - int y; - - nofit = false; - crushchange = crunch; - - // re-check heights for all things near the moving sector - for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) - for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) - P_BlockThingsIterator (x, y, PIT_ChangeSector); - - - return nofit; + int angle; + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + usething = player->mo; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; + y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; + + p_path_traverse(x1, y1, x2, y2, PT_ADDLINES, ptr_use_traverse); } -// Code to emulate the behavior of Vanilla Doom when encountering an overrun -// of the spechit array. This is by Andrey Budko (e6y) and comes from his -// PrBoom plus port. A big thanks to Andrey for this. +/* p_radius_attack + * Source is the creature that caused the explosion at spot. + */ -static void SpechitOverrun(line_t *ld) +void p_radius_attack(mobj_t *spot, mobj_t *source, int damage) { - static unsigned int baseaddr = 0; - unsigned int addr; - - if (baseaddr == 0) + int x; + int y; + + int xl; + int xh; + int yl; + int yh; + + fixed_t dist; + + dist = (damage + MAXRADIUS) << FRACBITS; + yh = (spot->y + dist - bmaporgy) >> MAPBLOCKSHIFT; + yl = (spot->y - dist - bmaporgy) >> MAPBLOCKSHIFT; + xh = (spot->x + dist - bmaporgx) >> MAPBLOCKSHIFT; + xl = (spot->x - dist - bmaporgx) >> MAPBLOCKSHIFT; + bombspot = spot; + bombsource = source; + bombdamage = damage; + + for (y = yl; y <= yh; y++) { - int p; - - // This is the first time we have had an overrun. Work out - // what base address we are going to use. - // Allow a spechit value to be specified on the command line. - - //! - // @category compat - // @arg - // - // Use the specified magic value when emulating spechit overruns. - // - - p = M_CheckParmWithArgs("-spechit", 1); - - if (p > 0) - { - M_StrToInt(myargv[p+1], (int *) &baseaddr); - } - else + for (x = xl; x <= xh; x++) { - baseaddr = DEFAULT_SPECHIT_MAGIC; + p_block_things_iterator(x, y, pit_radius_attack); } } - - // Calculate address used in doom2.exe +} - addr = baseaddr + (ld - lines) * 0x3E; +/* pit_change_sector */ - switch(numspechit) +static boolean pit_change_sector(mobj_t *thing) +{ + mobj_t *mo; + + if (p_things_height_clip(thing)) + { + return true; /* keep checking */ + } + + /* crunch bodies to giblets */ + + if (thing->health <= 0) { - case 9: - case 10: - case 11: - case 12: - tmbbox[numspechit-9] = addr; - break; - case 13: - crushchange = addr; - break; - case 14: - nofit = addr; - break; - default: - fprintf(stderr, "SpechitOverrun: Warning: unable to emulate" - "an overrun where numspechit=%i\n", - numspechit); - break; + p_set_mobj_state(thing, S_GIBS); + + if (gameversion > exe_doom_1_2) thing->flags &= ~MF_SOLID; + thing->height = 0; + thing->radius = 0; + + /* keep checking */ + + return true; } + + /* crunch dropped items */ + + if (thing->flags & MF_DROPPED) + { + p_remove_mobj(thing); + + return true; /* keep checking */ + } + + if (!(thing->flags & MF_SHOOTABLE)) + { + return true; /* assume it is bloody gibs or something */ + } + + nofit = true; + + if (crushchange && !(leveltime & 3)) + { + p_damage_mobj(thing, NULL, NULL, 10); + + /* spray blood in a random direction */ + + mo = p_spawn_mobj(thing->x, thing->y, thing->z + thing->height / 2, + MT_BLOOD); + + mo->momx = p_sub_random() << 12; + mo->momy = p_sub_random() << 12; + } + + /* keep checking (crush other things) */ + + return true; } +/* p_change_sector */ + +boolean p_change_sector(sector_t *sector, boolean crunch) +{ + int x; + int y; + + nofit = false; + crushchange = crunch; + + /* re-check heights for all things near the moving sector */ + + for (x = sector->blockbox[BOXLEFT]; x <= sector->blockbox[BOXRIGHT]; x++) + { + for (y = sector->blockbox[BOXBOTTOM]; y <= sector->blockbox[BOXTOP]; + y++) + { + p_block_things_iterator(x, y, pit_change_sector); + } + } + + return nofit; +} diff --git a/games/NXDoom/src/doom/p_maputl.c b/games/NXDoom/src/doom/p_maputl.c index cb74c942f23..f5c1932740f 100644 --- a/games/NXDoom/src/doom/p_maputl.c +++ b/games/NXDoom/src/doom/p_maputl.c @@ -1,30 +1,36 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// Copyright(C) 2005, 2006 Andrey Budko -// -// 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. -// -// DESCRIPTION: -// Movement/collision utility functions, -// as used by function in p_map.c. -// BLOCKMAP Iterator functions, -// and some PIT_* functions to use for iteration. -// - - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_maputl.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * Copyright(C) 2005, 2006 Andrey Budko + * + * 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. + * + * DESCRIPTION: + * Movement/collision utility functions, + * as used by function in p_map.c. + * BLOCKMAP Iterator functions, + * and some PIT_* functions to use for iteration. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include - #include "m_bbox.h" #include "m_misc.h" @@ -32,971 +38,902 @@ #include "doomstat.h" #include "p_local.h" +/* State. */ -// State. #include "r_state.h" -// -// P_AproxDistance -// Gives an estimation of distance (not exact) -// +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Intercepts Overrun emulation, from PrBoom-plus. + * Thanks to Andrey Budko (entryway) for researching this and his + * implementation of Intercepts Overrun emulation in PrBoom-plus + * which this is based on. + */ -fixed_t -P_AproxDistance -( fixed_t dx, - fixed_t dy ) +typedef struct { - dx = abs(dx); - dy = abs(dy); - if (dx < dy) - return dx+dy-(dx>>1); - return dx+dy-(dy>>1); -} + int len; + void *addr; + boolean int16_array; +} intercepts_overrun_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +fixed_t p_intercept_vector(divline_t *v2, divline_t *v1); -// -// P_PointOnLineSide -// Returns 0 or 1 -// -int -P_PointOnLineSide -( fixed_t x, - fixed_t y, - line_t* line ) +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Intercepts memory table. This is where various variables are located + * in memory in Vanilla Doom. When the intercepts table overflows, we + * need to write to them. + * + * Almost all of the values to overwrite are 32-bit integers, except for + * playerstarts, which is effectively an array of 16-bit integers and + * must be treated differently. + */ + +static intercepts_overrun_t g_intercepts_overrun[] = { - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - if (!line->dx) - { - if (x <= line->v1->x) - return line->dy > 0; - - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->v1->y) - return line->dx < 0; - - return line->dx > 0; - } - - dx = (x - line->v1->x); - dy = (y - line->v1->y); - - left = FixedMul ( line->dy>>FRACBITS , dx ); - right = FixedMul ( dy , line->dx>>FRACBITS ); - - if (right < left) - return 0; // front side - return 1; // back side -} + {4, NULL, false}, + {4, NULL, /* &earlyout, */ false}, + {4, NULL, /* &intercept_p, */ false}, + {4, &lowfloor, false}, + {4, &openbottom, false}, + {4, &opentop, false}, + {4, &openrange, false}, + {4, NULL, false}, + {120, NULL, /* &activeplats, */ false}, + {8, NULL, false}, + {4, &bulletslope, false}, + {4, NULL, /* &swingx, */ false}, + {4, NULL, /* &swingy, */ false}, + {4, NULL, false}, + {40, &playerstarts, true}, + {4, NULL, /* &blocklinks, */ false}, + {4, &bmapwidth, false}, + {4, NULL, /* &blockmap, */ false}, + {4, &bmaporgx, false}, + {4, &bmaporgy, false}, + {4, NULL, /* &blockmaplump, */ false}, + {4, &bmapheight, false}, + {0, NULL, false}, +}; +/**************************************************************************** + * Public Data + ****************************************************************************/ + +fixed_t opentop; +fixed_t openbottom; +fixed_t openrange; +fixed_t lowfloor; +/* INTERCEPT ROUTINES */ -// -// P_BoxOnLineSide -// Considers the line to be infinite -// Returns side 0 or 1, -1 if box crosses the line. -// -int -P_BoxOnLineSide -( fixed_t* tmbox, - line_t* ld ) +intercept_t intercepts[MAXINTERCEPTS]; +intercept_t *intercept_p; + +divline_t trace; +boolean earlyout; +int ptflags; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void p_make_divline(line_t *li, divline_t *dl) { - int p1 = 0; - int p2 = 0; - - switch (ld->slopetype) - { - case ST_HORIZONTAL: - p1 = tmbox[BOXTOP] > ld->v1->y; - p2 = tmbox[BOXBOTTOM] > ld->v1->y; - if (ld->dx < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - - case ST_VERTICAL: - p1 = tmbox[BOXRIGHT] < ld->v1->x; - p2 = tmbox[BOXLEFT] < ld->v1->x; - if (ld->dy < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - - case ST_POSITIVE: - p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); - break; - - case ST_NEGATIVE: - p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); - break; - } - - if (p1 == p2) - return p1; - return -1; + dl->x = li->v1->x; + dl->y = li->v1->y; + dl->dx = li->dx; + dl->dy = li->dy; } +/* Overwrite a specific memory location with a value. */ -// -// P_PointOnDivlineSide -// Returns 0 or 1. -// -int -P_PointOnDivlineSide -( fixed_t x, - fixed_t y, - divline_t* line ) +static void intercepts_mem_overrun(int location, int value) { - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - if (!line->dx) - { - if (x <= line->x) - return line->dy > 0; - - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->y) - return line->dx < 0; - - return line->dx > 0; - } - - dx = (x - line->x); - dy = (y - line->y); - - // try to quickly decide by looking at sign bits - if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) - { - if ( (line->dy ^ dx) & 0x80000000 ) - return 1; // (left is negative) - return 0; - } - - left = FixedMul ( line->dy>>8, dx>>8 ); - right = FixedMul ( dy>>8 , line->dx>>8 ); - - if (right < left) - return 0; // front side - return 1; // back side -} + int i; + int offset; + int index; + void *addr; + i = 0; + offset = 0; + /* Search down the array until we find the right entry */ -// -// P_MakeDivline -// -void -P_MakeDivline -( line_t* li, - divline_t* dl ) -{ - dl->x = li->v1->x; - dl->y = li->v1->y; - dl->dx = li->dx; - dl->dy = li->dy; -} + while (g_intercepts_overrun[i].len != 0) + { + if (offset + g_intercepts_overrun[i].len > location) + { + addr = g_intercepts_overrun[i].addr; + /* Write the value to the memory location. + * 16-bit and 32-bit values are written differently. + */ + if (addr != NULL) + { + if (g_intercepts_overrun[i].int16_array) + { + index = (location - offset) / 2; + ((short *)addr)[index] = value & 0xffff; + ((short *)addr)[index + 1] = (value >> 16) & 0xffff; + } + else + { + index = (location - offset) / 4; + ((int *)addr)[index] = value; + } + } -// -// P_InterceptVector -// Returns the fractional intercept point -// along the first divline. -// This is only called by the addthings -// and addlines traversers. -// -fixed_t -P_InterceptVector -( divline_t* v2, - divline_t* v1 ) -{ -#if 1 - fixed_t frac; - fixed_t num; - fixed_t den; - - den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); - - if (den == 0) - return 0; - // I_Error ("P_InterceptVector: parallel"); - - num = - FixedMul ( (v1->x - v2->x)>>8 ,v1->dy ) - +FixedMul ( (v2->y - v1->y)>>8, v1->dx ); - - frac = FixedDiv (num , den); - - return frac; -#else // UNUSED, float debug. - float frac; - float num; - float den; - float v1x; - float v1y; - float v1dx; - float v1dy; - float v2x; - float v2y; - float v2dx; - float v2dy; - - v1x = (float)v1->x/FRACUNIT; - v1y = (float)v1->y/FRACUNIT; - v1dx = (float)v1->dx/FRACUNIT; - v1dy = (float)v1->dy/FRACUNIT; - v2x = (float)v2->x/FRACUNIT; - v2y = (float)v2->y/FRACUNIT; - v2dx = (float)v2->dx/FRACUNIT; - v2dy = (float)v2->dy/FRACUNIT; - - den = v1dy*v2dx - v1dx*v2dy; - - if (den == 0) - return 0; // parallel - - num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; - frac = num / den; - - return frac*FRACUNIT; -#endif + break; + } + + offset += g_intercepts_overrun[i].len; + ++i; + } } +/* Emulate overruns of the intercepts[] array. */ -// -// P_LineOpening -// Sets opentop and openbottom to the window -// through a two sided line. -// OPTIMIZE: keep this precalculated -// -fixed_t opentop; -fixed_t openbottom; -fixed_t openrange; -fixed_t lowfloor; +static void intercepts_overrun(int num_intercepts, intercept_t *intercept) +{ + int location; + + if (num_intercepts <= MAXINTERCEPTS_ORIGINAL) + { + return; /* No overrun */ + } + location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12; -void P_LineOpening (line_t* linedef) + /* Overwrite memory that is overwritten in Vanilla Doom, using + * the values from the intercept structure. + * + * Note: the ->d.{thing,line} member should really have its + * address translated into the correct address value for + * Vanilla Doom. + */ + + intercepts_mem_overrun(location, intercept->frac); + intercepts_mem_overrun(location + 4, intercept->isaline); + intercepts_mem_overrun(location + 8, (intptr_t)intercept->d.thing); +} + +/* pit_add_line_intercepts. + * Looks for lines in the given block + * that intercept the given trace + * to add to the intercepts list. + * + * A line is crossed if its endpoints + * are on opposite sides of the trace. + * Returns true if earlyout and a solid line hit. + */ + +static boolean pit_add_line_intercepts(line_t *ld) { - sector_t* front; - sector_t* back; - - if (linedef->sidenum[1] == -1) + int s1; + int s2; + fixed_t frac; + divline_t dl; + + /* avoid precision problems with two routines */ + + if (trace.dx > FRACUNIT * 16 || trace.dy > FRACUNIT * 16 || + trace.dx < -FRACUNIT * 16 || trace.dy < -FRACUNIT * 16) { - // single sided line - openrange = 0; - return; + s1 = p_point_on_divline_side(ld->v1->x, ld->v1->y, &trace); + s2 = p_point_on_divline_side(ld->v2->x, ld->v2->y, &trace); } - - front = linedef->frontsector; - back = linedef->backsector; - - if (front->ceilingheight < back->ceilingheight) - opentop = front->ceilingheight; - else - opentop = back->ceilingheight; - - if (front->floorheight > back->floorheight) + else { - openbottom = front->floorheight; - lowfloor = back->floorheight; + s1 = p_point_on_line_side(trace.x, trace.y, ld); + s2 = p_point_on_line_side(trace.x + trace.dx, trace.y + trace.dy, ld); } - else + + if (s1 == s2) return true; /* line isn't crossed */ + + /* hit the line */ + + p_make_divline(ld, &dl); + frac = p_intercept_vector(&trace, &dl); + + if (frac < 0) return true; /* behind source */ + + /* try to early out the check */ + + if (earlyout && frac < FRACUNIT && !ld->backsector) { - openbottom = back->floorheight; - lowfloor = front->floorheight; + return false; /* stop checking */ } - - openrange = opentop - openbottom; + + intercept_p->frac = frac; + intercept_p->isaline = true; + intercept_p->d.line = ld; + intercepts_overrun(intercept_p - intercepts, intercept_p); + intercept_p++; + + return true; /* continue */ } +static boolean pit_add_thing_intercepts(mobj_t *thing) +{ + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; -// -// THING POSITION SETTING -// + int s1; + int s2; + boolean tracepositive; -// -// P_UnsetThingPosition -// Unlinks a thing from block map and sectors. -// On each position change, BLOCKMAP and other -// lookups maintaining lists ot things inside -// these structures need to be updated. -// -void P_UnsetThingPosition (mobj_t* thing) -{ - int blockx; - int blocky; - - if ( ! (thing->flags & MF_NOSECTOR) ) - { - // inert things don't need to be in blockmap? - // unlink from subsector - if (thing->snext) - thing->snext->sprev = thing->sprev; - - if (thing->sprev) - thing->sprev->snext = thing->snext; - else - thing->subsector->sector->thinglist = thing->snext; - } - - if ( ! (thing->flags & MF_NOBLOCKMAP) ) - { - // inert things don't need to be in blockmap - // unlink from block map - if (thing->bnext) - thing->bnext->bprev = thing->bprev; - - if (thing->bprev) - thing->bprev->bnext = thing->bnext; - else - { - blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; - - if (blockx>=0 && blockx < bmapwidth - && blocky>=0 && blocky bnext; - } - } + divline_t dl; + + fixed_t frac; + + tracepositive = (trace.dx ^ trace.dy) > 0; + + /* check a corner to corner cross-section for hit */ + + if (tracepositive) + { + x1 = thing->x - thing->radius; + y1 = thing->y + thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y - thing->radius; + } + else + { + x1 = thing->x - thing->radius; + y1 = thing->y - thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y + thing->radius; } + + s1 = p_point_on_divline_side(x1, y1, &trace); + s2 = p_point_on_divline_side(x2, y2, &trace); + + if (s1 == s2) return true; /* line isn't crossed */ + + dl.x = x1; + dl.y = y1; + dl.dx = x2 - x1; + dl.dy = y2 - y1; + + frac = p_intercept_vector(&trace, &dl); + + if (frac < 0) return true; /* behind source */ + + intercept_p->frac = frac; + intercept_p->isaline = false; + intercept_p->d.thing = thing; + intercepts_overrun(intercept_p - intercepts, intercept_p); + intercept_p++; + + return true; /* keep going */ } +/* p_traverse_intercepts + * Returns true if the traverser function returns true for all lines. + */ -// -// P_SetThingPosition -// Links a thing into both a block and a subsector -// based on it's x y. -// Sets thing->subsector properly -// -void -P_SetThingPosition (mobj_t* thing) +static boolean p_traverse_intercepts(traverser_t func, fixed_t maxfrac) { - subsector_t* ss; - sector_t* sec; - int blockx; - int blocky; - mobj_t** link; - - - // link into subsector - ss = R_PointInSubsector (thing->x,thing->y); - thing->subsector = ss; - - if ( ! (thing->flags & MF_NOSECTOR) ) - { - // invisible things don't go into the sector links - sec = ss->sector; - - thing->sprev = NULL; - thing->snext = sec->thinglist; - - if (sec->thinglist) - sec->thinglist->sprev = thing; - - sec->thinglist = thing; - } - - - // link into blockmap - if ( ! (thing->flags & MF_NOBLOCKMAP) ) - { - // inert things don't need to be in blockmap - blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; - - if (blockx>=0 - && blockx < bmapwidth - && blocky>=0 - && blocky < bmapheight) - { - link = &blocklinks[blocky*bmapwidth+blockx]; - thing->bprev = NULL; - thing->bnext = *link; - if (*link) - (*link)->bprev = thing; - - *link = thing; - } - else - { - // thing is off the map - thing->bnext = thing->bprev = NULL; - } + int count; + fixed_t dist; + intercept_t *scan; + intercept_t *in; + + count = intercept_p - intercepts; + + in = 0; /* shut up compiler warning */ + + while (count--) + { + dist = INT_MAX; + for (scan = intercepts; scan < intercept_p; scan++) + { + if (scan->frac < dist) + { + dist = scan->frac; + in = scan; + } + } + + if (dist > maxfrac) return true; /* checked everything in range */ + +#if 0 /* UNUSED */ + + /* don't check these yet, there may be others inserted */ + + in = scan = intercepts; + for (scan = intercepts; scan < intercept_p; scan++) + { + if (scan->frac > maxfrac) *in++ = *scan; + } + + intercept_p = in; + return false; +#endif + + if (!func(in)) return false; /* don't bother going farther */ + + in->frac = INT_MAX; } + + return true; /* everything was traversed */ } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* p_approx_distance + * Gives an estimation of distance (not exact) + */ + +fixed_t p_approx_distance(fixed_t dx, fixed_t dy) +{ + dx = abs(dx); + dy = abs(dy); + if (dx < dy) return dx + dy - (dx >> 1); + return dx + dy - (dy >> 1); +} +/* p_point_on_line_side + * Returns 0 or 1 + */ -// -// BLOCK MAP ITERATORS -// For each line/thing in the given mapblock, -// call the passed PIT_* function. -// If the function returns false, -// exit with false without checking anything else. -// - - -// -// P_BlockLinesIterator -// The validcount flags are used to avoid checking lines -// that are marked in multiple mapblocks, -// so increment validcount before the first call -// to P_BlockLinesIterator, then make one or more calls -// to it. -// -boolean -P_BlockLinesIterator -( int x, - int y, - boolean(*func)(line_t*) ) +int p_point_on_line_side(fixed_t x, fixed_t y, line_t *line) { - int offset; - short* list; - line_t* ld; - - if (x<0 - || y<0 - || x>=bmapwidth - || y>=bmapheight) + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + if (!line->dx) { - return true; + if (x <= line->v1->x) return line->dy > 0; + + return line->dy < 0; } - - offset = y*bmapwidth+x; - - offset = *(blockmap+offset); - for ( list = blockmaplump+offset ; *list != -1 ; list++) + if (!line->dy) { - ld = &lines[*list]; - - if (ld->validcount == validcount) - continue; // line has already been checked + if (y <= line->v1->y) return line->dx < 0; - ld->validcount = validcount; - - if ( !func(ld) ) - return false; + return line->dx > 0; } - return true; // everything was checked + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = fixed_mul(line->dy >> FRACBITS, dx); + right = fixed_mul(dy, line->dx >> FRACBITS); + + if (right < left) return 0; /* front side */ + + return 1; /* back side */ } +/* p_box_on_line_side + * Considers the line to be infinite + * Returns side 0 or 1, -1 if box crosses the line. + */ -// -// P_BlockThingsIterator -// -boolean -P_BlockThingsIterator -( int x, - int y, - boolean(*func)(mobj_t*) ) +int p_box_on_line_side(fixed_t *tmbox, line_t *ld) { - mobj_t* mobj; + int p1 = 0; + int p2 = 0; - if ( x<0 - || y<0 - || x>=bmapwidth - || y>=bmapheight) + switch (ld->slopetype) { - return true; + case ST_HORIZONTAL: + p1 = tmbox[BOXTOP] > ld->v1->y; + p2 = tmbox[BOXBOTTOM] > ld->v1->y; + if (ld->dx < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + + case ST_VERTICAL: + p1 = tmbox[BOXRIGHT] < ld->v1->x; + p2 = tmbox[BOXLEFT] < ld->v1->x; + if (ld->dy < 0) + { + p1 ^= 1; + p2 ^= 1; + } + break; + + case ST_POSITIVE: + p1 = p_point_on_line_side(tmbox[BOXLEFT], tmbox[BOXTOP], ld); + p2 = p_point_on_line_side(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); + break; + + case ST_NEGATIVE: + p1 = p_point_on_line_side(tmbox[BOXRIGHT], tmbox[BOXTOP], ld); + p2 = p_point_on_line_side(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); + break; } - LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); + if (p1 == p2) return p1; + return -1; +} + +/* p_point_on_divline_side + * Returns 0 or 1. + */ + +int p_point_on_divline_side(fixed_t x, fixed_t y, divline_t *line) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; - for (mobj = blocklinks[y*bmapwidth+x] ; - mobj ; - mobj = mobj->bnext) + if (!line->dx) { - if (!func( mobj ) ) - return false; + if (x <= line->x) return line->dy > 0; + + return line->dy < 0; } - return true; -} + if (!line->dy) + { + if (y <= line->y) return line->dx < 0; + return line->dx > 0; + } -// -// INTERCEPT ROUTINES -// -intercept_t intercepts[MAXINTERCEPTS]; -intercept_t* intercept_p; + dx = (x - line->x); + dy = (y - line->y); -divline_t trace; -boolean earlyout; -int ptflags; + /* try to quickly decide by looking at sign bits */ -static void InterceptsOverrun(int num_intercepts, intercept_t *intercept); + if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000) + { + if ((line->dy ^ dx) & 0x80000000) return 1; /* (left is negative) */ + return 0; + } -// -// PIT_AddLineIntercepts. -// Looks for lines in the given block -// that intercept the given trace -// to add to the intercepts list. -// -// A line is crossed if its endpoints -// are on opposite sides of the trace. -// Returns true if earlyout and a solid line hit. -// -boolean -PIT_AddLineIntercepts (line_t* ld) -{ - int s1; - int s2; - fixed_t frac; - divline_t dl; - - // avoid precision problems with two routines - if ( trace.dx > FRACUNIT*16 - || trace.dy > FRACUNIT*16 - || trace.dx < -FRACUNIT*16 - || trace.dy < -FRACUNIT*16) - { - s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); - } - else - { - s1 = P_PointOnLineSide (trace.x, trace.y, ld); - s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); - } - - if (s1 == s2) - return true; // line isn't crossed - - // hit the line - P_MakeDivline (ld, &dl); - frac = P_InterceptVector (&trace, &dl); - - if (frac < 0) - return true; // behind source - - // try to early out the check - if (earlyout - && frac < FRACUNIT - && !ld->backsector) - { - return false; // stop checking - } - - - intercept_p->frac = frac; - intercept_p->isaline = true; - intercept_p->d.line = ld; - InterceptsOverrun(intercept_p - intercepts, intercept_p); - intercept_p++; - - return true; // continue -} + left = fixed_mul(line->dy >> 8, dx >> 8); + right = fixed_mul(dy >> 8, line->dx >> 8); + + if (right < left) return 0; /* front side */ + return 1; /* back side */ +} +/* p_intercept_vector + * + * Returns the fractional intercept point along the first divline. + * This is only called by the addthings and addlines traversers. + */ -// -// PIT_AddThingIntercepts -// -boolean PIT_AddThingIntercepts (mobj_t* thing) +fixed_t p_intercept_vector(divline_t *v2, divline_t *v1) { - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - int s1; - int s2; - - boolean tracepositive; - - divline_t dl; - - fixed_t frac; - - tracepositive = (trace.dx ^ trace.dy)>0; - - // check a corner to corner crossection for hit - if (tracepositive) - { - x1 = thing->x - thing->radius; - y1 = thing->y + thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y - thing->radius; - } - else - { - x1 = thing->x - thing->radius; - y1 = thing->y - thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y + thing->radius; - } - - s1 = P_PointOnDivlineSide (x1, y1, &trace); - s2 = P_PointOnDivlineSide (x2, y2, &trace); - - if (s1 == s2) - return true; // line isn't crossed - - dl.x = x1; - dl.y = y1; - dl.dx = x2-x1; - dl.dy = y2-y1; - - frac = P_InterceptVector (&trace, &dl); - - if (frac < 0) - return true; // behind source - - intercept_p->frac = frac; - intercept_p->isaline = false; - intercept_p->d.thing = thing; - InterceptsOverrun(intercept_p - intercepts, intercept_p); - intercept_p++; - - return true; // keep going +#if 1 + fixed_t frac; + fixed_t num; + fixed_t den; + + den = fixed_mul(v1->dy >> 8, v2->dx) - fixed_mul(v1->dx >> 8, v2->dy); + + if (den == 0) return 0; + + num = fixed_mul((v1->x - v2->x) >> 8, v1->dy) + + fixed_mul((v2->y - v1->y) >> 8, v1->dx); + + frac = fixed_div(num, den); + + return frac; +#else /* UNUSED, float debug. */ + float frac; + float num; + float den; + float v1x; + float v1y; + float v1dx; + float v1dy; + float v2x; + float v2y; + float v2dx; + float v2dy; + + v1x = (float)v1->x / FRACUNIT; + v1y = (float)v1->y / FRACUNIT; + v1dx = (float)v1->dx / FRACUNIT; + v1dy = (float)v1->dy / FRACUNIT; + v2x = (float)v2->x / FRACUNIT; + v2y = (float)v2->y / FRACUNIT; + v2dx = (float)v2->dx / FRACUNIT; + v2dy = (float)v2->dy / FRACUNIT; + + den = v1dy * v2dx - v1dx * v2dy; + + if (den == 0) return 0; /* parallel */ + + num = (v1x - v2x) * v1dy + (v2y - v1y) * v1dx; + frac = num / den; + + return frac * FRACUNIT; +#endif } +/* p_line_opening + * Sets opentop and openbottom to the window through a two sided line. + * OPTIMIZE: keep this precalculated + */ -// -// P_TraverseIntercepts -// Returns true if the traverser function returns true -// for all lines. -// -boolean -P_TraverseIntercepts -( traverser_t func, - fixed_t maxfrac ) +void p_line_opening(line_t *p_linedef) { - int count; - fixed_t dist; - intercept_t* scan; - intercept_t* in; - - count = intercept_p - intercepts; - - in = 0; // shut up compiler warning - - while (count--) - { - dist = INT_MAX; - for (scan = intercepts ; scanfrac < dist) - { - dist = scan->frac; - in = scan; - } - } - - if (dist > maxfrac) - return true; // checked everything in range - -#if 0 // UNUSED - { - // don't check these yet, there may be others inserted - in = scan = intercepts; - for ( scan = intercepts ; scanfrac > maxfrac) - *in++ = *scan; - intercept_p = in; - return false; + sector_t *front; + sector_t *back; + + if (p_linedef->sidenum[1] == -1) + { + /* single sided line */ + + openrange = 0; + return; } -#endif - if ( !func (in) ) - return false; // don't bother going farther + front = p_linedef->frontsector; + back = p_linedef->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; - in->frac = INT_MAX; + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; } - - return true; // everything was traversed + + openrange = opentop - openbottom; } +/* THING POSITION SETTING */ -// Intercepts Overrun emulation, from PrBoom-plus. -// Thanks to Andrey Budko (entryway) for researching this and his -// implementation of Intercepts Overrun emulation in PrBoom-plus -// which this is based on. +/* p_unset_thing_position + * + * Unlinks a thing from block map and sectors. + * + * On each position change, BLOCKMAP and other lookups maintaining lists to + * things inside these structures need to be updated. + */ -typedef struct +void p_unset_thing_position(mobj_t *thing) { - int len; - void *addr; - boolean int16_array; -} intercepts_overrun_t; + int blockx; + int blocky; -// Intercepts memory table. This is where various variables are located -// in memory in Vanilla Doom. When the intercepts table overflows, we -// need to write to them. -// -// Almost all of the values to overwrite are 32-bit integers, except for -// playerstarts, which is effectively an array of 16-bit integers and -// must be treated differently. + if (!(thing->flags & MF_NOSECTOR)) + { + /* inert things don't need to be in blockmap? unlink from subsector */ -static intercepts_overrun_t intercepts_overrun[] = -{ - {4, NULL, false}, - {4, NULL, /* &earlyout, */ false}, - {4, NULL, /* &intercept_p, */ false}, - {4, &lowfloor, false}, - {4, &openbottom, false}, - {4, &opentop, false}, - {4, &openrange, false}, - {4, NULL, false}, - {120, NULL, /* &activeplats, */ false}, - {8, NULL, false}, - {4, &bulletslope, false}, - {4, NULL, /* &swingx, */ false}, - {4, NULL, /* &swingy, */ false}, - {4, NULL, false}, - {40, &playerstarts, true}, - {4, NULL, /* &blocklinks, */ false}, - {4, &bmapwidth, false}, - {4, NULL, /* &blockmap, */ false}, - {4, &bmaporgx, false}, - {4, &bmaporgy, false}, - {4, NULL, /* &blockmaplump, */ false}, - {4, &bmapheight, false}, - {0, NULL, false}, -}; + if (thing->snext) thing->snext->sprev = thing->sprev; + + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + } + + if (!(thing->flags & MF_NOBLOCKMAP)) + { + /* inert things don't need to be in blockmap unlink from block map */ + + if (thing->bnext) thing->bnext->bprev = thing->bprev; + + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + + if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 && + blocky < bmapheight) + { + blocklinks[blocky * bmapwidth + blockx] = thing->bnext; + } + } + } +} -// Overwrite a specific memory location with a value. +/* p_set_thing_position + * Links a thing into both a block and a subsector based on it's x y. + * Sets thing->subsector properly + */ -static void InterceptsMemoryOverrun(int location, int value) +void p_set_thing_position(mobj_t *thing) { - int i, offset; - int index; - void *addr; + subsector_t *ss; + sector_t *sec; + int blockx; + int blocky; + mobj_t **link; - i = 0; - offset = 0; + /* link into subsector */ - // Search down the array until we find the right entry + ss = r_point_in_subsector(thing->x, thing->y); + thing->subsector = ss; - while (intercepts_overrun[i].len != 0) + if (!(thing->flags & MF_NOSECTOR)) { - if (offset + intercepts_overrun[i].len > location) - { - addr = intercepts_overrun[i].addr; + /* invisible things don't go into the sector links */ - // Write the value to the memory location. - // 16-bit and 32-bit values are written differently. + sec = ss->sector; - if (addr != NULL) - { - if (intercepts_overrun[i].int16_array) - { - index = (location - offset) / 2; - ((short *) addr)[index] = value & 0xffff; - ((short *) addr)[index + 1] = (value >> 16) & 0xffff; - } - else - { - index = (location - offset) / 4; - ((int *) addr)[index] = value; - } - } + thing->sprev = NULL; + thing->snext = sec->thinglist; - break; + if (sec->thinglist) sec->thinglist->sprev = thing; + + sec->thinglist = thing; + } + + /* link into blockmap */ + + if (!(thing->flags & MF_NOBLOCKMAP)) + { + /* inert things don't need to be in blockmap */ + + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + + if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 && + blocky < bmapheight) + { + link = &blocklinks[blocky * bmapwidth + blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) (*link)->bprev = thing; + + *link = thing; } + else + { + /* thing is off the map */ - offset += intercepts_overrun[i].len; - ++i; + thing->bnext = thing->bprev = NULL; + } } } -// Emulate overruns of the intercepts[] array. - -static void InterceptsOverrun(int num_intercepts, intercept_t *intercept) +/* BLOCK MAP ITERATORS + * For each line/thing in the given mapblock, + * call the passed PIT_* function. + * If the function returns false, + * exit with false without checking anything else. + */ + +/* p_block_lines_iterator + * The validcount flags are used to avoid checking lines + * that are marked in multiple mapblocks, + * so increment validcount before the first call + * to p_block_lines_iterator, then make one or more calls + * to it. + */ + +boolean p_block_lines_iterator(int x, int y, boolean (*func)(line_t *)) { - int location; + int offset; + short *list; + line_t *ld; - if (num_intercepts <= MAXINTERCEPTS_ORIGINAL) + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) { - // No overrun + return true; + } + + offset = y * bmapwidth + x; - return; + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + + if (ld->validcount == validcount) + continue; /* line has already been checked */ + + ld->validcount = validcount; + + if (!func(ld)) return false; } - location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12; + return true; /* everything was checked */ +} - // Overwrite memory that is overwritten in Vanilla Doom, using - // the values from the intercept structure. - // - // Note: the ->d.{thing,line} member should really have its - // address translated into the correct address value for - // Vanilla Doom. +boolean p_block_things_iterator(int x, int y, boolean (*func)(mobj_t *)) +{ + mobj_t *mobj; - InterceptsMemoryOverrun(location, intercept->frac); - InterceptsMemoryOverrun(location + 4, intercept->isaline); - InterceptsMemoryOverrun(location + 8, (intptr_t) intercept->d.thing); + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + { + return true; + } + + LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y * bmapwidth + x], bnext); + + for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext) + { + if (!func(mobj)) return false; + } + + return true; } +/* p_path_traverse + * + * Traces a line from x1,y1 to x2,y2, calling the traverser function for + * each. + * Returns true if the traverser function returns true for all lines. + */ -// -// P_PathTraverse -// Traces a line from x1,y1 to x2,y2, -// calling the traverser function for each. -// Returns true if the traverser function returns true -// for all lines. -// -boolean -P_PathTraverse -( fixed_t x1, - fixed_t y1, - fixed_t x2, - fixed_t y2, - int flags, - boolean (*trav) (intercept_t *)) +boolean p_path_traverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, + int flags, boolean (*trav)(intercept_t *)) { - fixed_t xt1; - fixed_t yt1; - fixed_t xt2; - fixed_t yt2; - - fixed_t xstep; - fixed_t ystep; - - fixed_t partial; - - fixed_t xintercept; - fixed_t yintercept; - - int mapx; - int mapy; - - int mapxstep; - int mapystep; - - int count; - - earlyout = (flags & PT_EARLYOUT) != 0; - - validcount++; - intercept_p = intercepts; - - if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) - x1 += FRACUNIT; // don't side exactly on a line - - if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) - y1 += FRACUNIT; // don't side exactly on a line - - trace.x = x1; - trace.y = y1; - trace.dx = x2 - x1; - trace.dy = y2 - y1; - - x1 -= bmaporgx; - y1 -= bmaporgy; - xt1 = x1>>MAPBLOCKSHIFT; - yt1 = y1>>MAPBLOCKSHIFT; - - x2 -= bmaporgx; - y2 -= bmaporgy; - xt2 = x2>>MAPBLOCKSHIFT; - yt2 = y2>>MAPBLOCKSHIFT; - - if (xt2 > xt1) - { - mapxstep = 1; - partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); - ystep = FixedDiv (y2-y1,abs(x2-x1)); - } - else if (xt2 < xt1) - { - mapxstep = -1; - partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); - ystep = FixedDiv (y2-y1,abs(x2-x1)); - } - else - { - mapxstep = 0; - partial = FRACUNIT; - ystep = 256*FRACUNIT; - } - - yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); - - - if (yt2 > yt1) - { - mapystep = 1; - partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); - xstep = FixedDiv (x2-x1,abs(y2-y1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); - xstep = FixedDiv (x2-x1,abs(y2-y1)); - } - else - { - mapystep = 0; - partial = FRACUNIT; - xstep = 256*FRACUNIT; - } - xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); - - // Step through map blocks. - // Count is present to prevent a round off error - // from skipping the break. - mapx = xt1; - mapy = yt1; - - for (count = 0 ; count < 64 ; count++) - { - if (flags & PT_ADDLINES) - { - if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) - return false; // early out - } - - if (flags & PT_ADDTHINGS) - { - if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) - return false; // early out - } - - if (mapx == xt2 - && mapy == yt2) - { - break; - } - - if ( (yintercept >> FRACBITS) == mapy) - { - yintercept += ystep; - mapx += mapxstep; - } - else if ( (xintercept >> FRACBITS) == mapx) - { - xintercept += xstep; - mapy += mapystep; - } - - } - // go through the sorted list - return P_TraverseIntercepts ( trav, FRACUNIT ); -} + fixed_t xt1; + fixed_t yt1; + fixed_t xt2; + fixed_t yt2; + + fixed_t xstep; + fixed_t ystep; + + fixed_t partial; + fixed_t xintercept; + fixed_t yintercept; + int mapx; + int mapy; + int mapxstep; + int mapystep; + + int count; + + earlyout = (flags & PT_EARLYOUT) != 0; + + validcount++; + intercept_p = intercepts; + + if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) + { + x1 += FRACUNIT; /* don't side exactly on a line */ + } + + if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) + { + y1 += FRACUNIT; /* don't side exactly on a line */ + } + + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1 >> MAPBLOCKSHIFT; + yt1 = y1 >> MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2 >> MAPBLOCKSHIFT; + yt2 = y2 >> MAPBLOCKSHIFT; + + if (xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + ystep = fixed_div(y2 - y1, abs(x2 - x1)); + } + else if (xt2 < xt1) + { + mapxstep = -1; + partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); + ystep = fixed_div(y2 - y1, abs(x2 - x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256 * FRACUNIT; + } + + yintercept = (y1 >> MAPBTOFRAC) + fixed_mul(partial, ystep); + + if (yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); + xstep = fixed_div(x2 - x1, abs(y2 - y1)); + } + else if (yt2 < yt1) + { + mapystep = -1; + partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); + xstep = fixed_div(x2 - x1, abs(y2 - y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256 * FRACUNIT; + } + + xintercept = (x1 >> MAPBTOFRAC) + fixed_mul(partial, xstep); + + /* Step through map blocks. + * Count is present to prevent a round off error + * from skipping the break. + */ + + mapx = xt1; + mapy = yt1; + + for (count = 0; count < 64; count++) + { + if (flags & PT_ADDLINES) + { + if (!p_block_lines_iterator(mapx, mapy, pit_add_line_intercepts)) + { + return false; /* early out */ + } + } + + if (flags & PT_ADDTHINGS) + { + if (!p_block_things_iterator(mapx, mapy, pit_add_thing_intercepts)) + { + return false; /* early out */ + } + } + + if (mapx == xt2 && mapy == yt2) + { + break; + } + + if ((yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if ((xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + } + + /* go through the sorted list */ + + return p_traverse_intercepts(trav, FRACUNIT); +} diff --git a/games/NXDoom/src/doom/p_mobj.c b/games/NXDoom/src/doom/p_mobj.c index 481c52822d1..4b81fa45afc 100644 --- a/games/NXDoom/src/doom/p_mobj.c +++ b/games/NXDoom/src/doom/p_mobj.c @@ -1,1072 +1,1126 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Moving object handling. Spawn functions. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_mobj.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Moving object handling. Spawn functions. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include "i_system.h" -#include "z_zone.h" #include "m_random.h" +#include "z_zone.h" #include "doomdef.h" #include "p_local.h" -#include "sounds.h" -#include "st_stuff.h" #include "hu_stuff.h" +#include "st_stuff.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "doomstat.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ -void G_PlayerReborn (int player); -void P_SpawnMapThing (mapthing_t* mthing); +/* Use a heuristic approach to detect infinite state cycles: Count the number + * of times the loop in p_set_mobj_state() executes and exit with an error + * once an arbitrary very large limit is reached. + */ +#define MOBJ_CYCLE_LIMIT 1000000 + +#define STOPSPEED 0x1000 +#define FRICTION 0xe800 + +/**************************************************************************** + * Public Data + ****************************************************************************/ -// -// P_SetMobjState -// Returns true if the mobj is still present. -// int test; -// Use a heuristic approach to detect infinite state cycles: Count the number -// of times the loop in P_SetMobjState() executes and exit with an error once -// an arbitrary very large limit is reached. +mapthing_t itemrespawnque[ITEMQUESIZE]; +int itemrespawntime[ITEMQUESIZE]; +int iquehead; +int iquetail; -#define MOBJ_CYCLE_LIMIT 1000000 +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -boolean -P_SetMobjState -( mobj_t* mobj, - statenum_t state ) -{ - state_t* st; - int cycle_counter = 0; +void g_player_reborn(int player); +void p_spawn_map_thing(mapthing_t *mthing); - do - { - if (state == S_NULL) - { - mobj->state = (state_t *) S_NULL; - P_RemoveMobj (mobj); - return false; - } - - st = &states[state]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - - // Modified handling. - // Call action functions when the state is set - if (st->action.acp1) - st->action.acp1(mobj); - - state = st->nextstate; - - if (cycle_counter++ > MOBJ_CYCLE_LIMIT) - { - I_Error("P_SetMobjState: Infinite state cycle detected!"); - } - } while (!mobj->tics); - - return true; -} +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: p_explode_missile + ****************************************************************************/ -// -// P_ExplodeMissile -// -void P_ExplodeMissile (mobj_t* mo) +static void p_explode_missile(mobj_t *mo) { - mo->momx = mo->momy = mo->momz = 0; + mo->momx = mo->momy = mo->momz = 0; - P_SetMobjState (mo, mobjinfo[mo->type].deathstate); + p_set_mobj_state(mo, mobjinfo[mo->type].deathstate); - mo->tics -= P_Random()&3; + mo->tics -= p_random() & 3; - if (mo->tics < 1) - mo->tics = 1; + if (mo->tics < 1) mo->tics = 1; - mo->flags &= ~MF_MISSILE; + mo->flags &= ~MF_MISSILE; - if (mo->info->deathsound) - S_StartSound (mo, mo->info->deathsound); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (mo->info->deathsound) s_start_sound(mo, mo->info->deathsound); +#endif } +/**************************************************************************** + * Name: p_xy_movement + ****************************************************************************/ -// -// P_XYMovement -// -#define STOPSPEED 0x1000 -#define FRICTION 0xe800 - -void P_XYMovement (mobj_t* mo) -{ - fixed_t ptryx; - fixed_t ptryy; - player_t* player; - fixed_t xmove; - fixed_t ymove; - - if (!mo->momx && !mo->momy) +static void p_xy_movement(mobj_t *mo) +{ + fixed_t ptryx; + fixed_t ptryy; + player_t *player; + fixed_t xmove; + fixed_t ymove; + + if (!mo->momx && !mo->momy) { - if (mo->flags & MF_SKULLFLY) - { - // the skull slammed into something - mo->flags &= ~MF_SKULLFLY; - mo->momx = mo->momy = mo->momz = 0; - - P_SetMobjState (mo, mo->info->spawnstate); - } - return; + if (mo->flags & MF_SKULLFLY) + { + /* the skull slammed into something */ + + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + + p_set_mobj_state(mo, mo->info->spawnstate); + } + + return; } - - player = mo->player; - - if (mo->momx > MAXMOVE) - mo->momx = MAXMOVE; - else if (mo->momx < -MAXMOVE) - mo->momx = -MAXMOVE; - - if (mo->momy > MAXMOVE) - mo->momy = MAXMOVE; - else if (mo->momy < -MAXMOVE) - mo->momy = -MAXMOVE; - - xmove = mo->momx; - ymove = mo->momy; - - do + + player = mo->player; + + if (mo->momx > MAXMOVE) + mo->momx = MAXMOVE; + else if (mo->momx < -MAXMOVE) + mo->momx = -MAXMOVE; + + if (mo->momy > MAXMOVE) + mo->momy = MAXMOVE; + else if (mo->momy < -MAXMOVE) + mo->momy = -MAXMOVE; + + xmove = mo->momx; + ymove = mo->momy; + + do { - if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) - { - ptryx = mo->x + xmove/2; - ptryy = mo->y + ymove/2; - xmove >>= 1; - ymove >>= 1; - } - else - { - ptryx = mo->x + xmove; - ptryy = mo->y + ymove; - xmove = ymove = 0; - } - - if (!P_TryMove (mo, ptryx, ptryy)) - { - // blocked move - if (mo->player) - { // try to slide along it - P_SlideMove (mo); - } - else if (mo->flags & MF_MISSILE) - { - // explode a missile - if (ceilingline && - ceilingline->backsector && - ceilingline->backsector->ceilingpic == skyflatnum) - { - // Hack to prevent missiles exploding - // against the sky. - // Does not handle sky floors. - P_RemoveMobj (mo); - return; - } - P_ExplodeMissile (mo); - } - else - mo->momx = mo->momy = 0; - } - } while (xmove || ymove); - - // slow down - if (player && player->cheats & CF_NOMOMENTUM) + if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2) + { + ptryx = mo->x + xmove / 2; + ptryy = mo->y + ymove / 2; + xmove >>= 1; + ymove >>= 1; + } + else + { + ptryx = mo->x + xmove; + ptryy = mo->y + ymove; + xmove = ymove = 0; + } + + if (!p_try_move(mo, ptryx, ptryy)) + { + /* blocked move */ + + if (mo->player) + { + /* try to slide along it */ + + p_slide_move(mo); + } + else if (mo->flags & MF_MISSILE) + { + /* explode a missile */ + + if (ceilingline && ceilingline->backsector && + ceilingline->backsector->ceilingpic == skyflatnum) + { + /* Hack to prevent missiles exploding + * against the sky. + * Does not handle sky floors. + */ + + p_remove_mobj(mo); + return; + } + + p_explode_missile(mo); + } + else + mo->momx = mo->momy = 0; + } + } + while (xmove || ymove); + + /* slow down */ + + if (player && player->cheats & CF_NOMOMENTUM) { - // debug option for no sliding at all - mo->momx = mo->momy = 0; - return; + /* debug option for no sliding at all */ + + mo->momx = mo->momy = 0; + return; } - if (mo->flags & (MF_MISSILE | MF_SKULLFLY) ) - return; // no friction for missiles ever - - if (mo->z > mo->floorz) - return; // no friction when airborne + if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) + return; /* no friction for missiles ever */ - if (mo->flags & MF_CORPSE) + if (mo->z > mo->floorz) return; /* no friction when airborne */ + + if (mo->flags & MF_CORPSE) { - // do not stop sliding - // if halfway off a step with some momentum - if (mo->momx > FRACUNIT/4 - || mo->momx < -FRACUNIT/4 - || mo->momy > FRACUNIT/4 - || mo->momy < -FRACUNIT/4) - { - if (mo->floorz != mo->subsector->sector->floorheight) - return; - } + /* do not stop sliding + * if halfway off a step with some momentum + */ + + if (mo->momx > FRACUNIT / 4 || mo->momx < -FRACUNIT / 4 || + mo->momy > FRACUNIT / 4 || mo->momy < -FRACUNIT / 4) + { + if (mo->floorz != mo->subsector->sector->floorheight) return; + } } - if (mo->momx > -STOPSPEED - && mo->momx < STOPSPEED - && mo->momy > -STOPSPEED - && mo->momy < STOPSPEED - && (!player - || (player->cmd.forwardmove== 0 - && player->cmd.sidemove == 0 ) ) ) + if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED && + mo->momy > -STOPSPEED && mo->momy < STOPSPEED && + (!player || + (player->cmd.forwardmove == 0 && player->cmd.sidemove == 0))) { - // if in a walking frame, stop moving - if ( player&&(unsigned)((player->mo->state - states)- S_PLAY_RUN1) < 4) - P_SetMobjState (player->mo, S_PLAY); - - mo->momx = 0; - mo->momy = 0; + /* if in a walking frame, stop moving */ + + if (player && + (unsigned)((player->mo->state - states) - S_PLAY_RUN1) < 4) + p_set_mobj_state(player->mo, S_PLAY); + + mo->momx = 0; + mo->momy = 0; } - else + else { - mo->momx = FixedMul (mo->momx, FRICTION); - mo->momy = FixedMul (mo->momy, FRICTION); + mo->momx = fixed_mul(mo->momx, FRICTION); + mo->momy = fixed_mul(mo->momy, FRICTION); } } -// -// P_ZMovement -// -void P_ZMovement (mobj_t* mo) +/**************************************************************************** + * Name: p_z_movement + ****************************************************************************/ + +static void p_z_movement(mobj_t *mo) { - fixed_t dist; - fixed_t delta; - - // check for smooth step up - if (mo->player && mo->z < mo->floorz) + fixed_t dist; + fixed_t delta; + + /* check for smooth step up */ + + if (mo->player && mo->z < mo->floorz) { - mo->player->viewheight -= mo->floorz-mo->z; + mo->player->viewheight -= mo->floorz - mo->z; - mo->player->deltaviewheight - = (VIEWHEIGHT - mo->player->viewheight)>>3; + mo->player->deltaviewheight = + (VIEWHEIGHT - mo->player->viewheight) >> 3; } - - // adjust height - mo->z += mo->momz; - - if ( mo->flags & MF_FLOAT - && mo->target) + + mo->z += mo->momz; /* adjust height */ + + if (mo->flags & MF_FLOAT && mo->target) { - // float down towards target if too close - if ( !(mo->flags & MF_SKULLFLY) - && !(mo->flags & MF_INFLOAT) ) - { - dist = P_AproxDistance (mo->x - mo->target->x, - mo->y - mo->target->y); - - delta =(mo->target->z + (mo->height>>1)) - mo->z; - - if (delta<0 && dist < -(delta*3) ) - mo->z -= FLOATSPEED; - else if (delta>0 && dist < (delta*3) ) - mo->z += FLOATSPEED; - } - + /* float down towards target if too close */ + + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = p_approx_distance(mo->x - mo->target->x, + mo->y - mo->target->y); + + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + + if (delta < 0 && dist < -(delta * 3)) + mo->z -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->z += FLOATSPEED; + } } - - // clip movement - if (mo->z <= mo->floorz) + + /* clip movement */ + + if (mo->z <= mo->floorz) { - // hit the floor - - // Note (id): - // somebody left this after the setting momz to 0, - // kinda useless there. - // - // cph - This was the a bug in the linuxdoom-1.10 source which - // caused it not to sync Doom 2 v1.9 demos. Someone - // added the above comment and moved up the following code. So - // demos would desync in close lost soul fights. - // Note that this only applies to original Doom 1 or Doom2 demos - not - // Final Doom and Ultimate Doom. So we test demo_compatibility *and* - // gamemission. (Note we assume that Doom1 is always Ult Doom, which - // seems to hold for most published demos.) - // - // fraggle - cph got the logic here slightly wrong. There are three - // versions of Doom 1.9: - // - // * The version used in registered doom 1.9 + doom2 - no bounce - // * The version used in ultimate doom - has bounce - // * The version used in final doom - has bounce - // - // So we need to check that this is either retail or commercial - // (but not doom2) - - int correct_lost_soul_bounce = gameversion >= exe_ultimate; - - if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) - { - // the skull slammed into something - mo->momz = -mo->momz; - } - - if (mo->momz < 0) - { - if (mo->player - && mo->momz < -GRAVITY*8) - { - // Squat down. - // Decrease viewheight for a moment - // after hitting the ground (hard), - // and utter appropriate sound. - mo->player->deltaviewheight = mo->momz>>3; - S_StartSound (mo, sfx_oof); - } - mo->momz = 0; - } - mo->z = mo->floorz; - - - // cph 2001/05/26 - - // See lost soul bouncing comment above. We need this here for bug - // compatibility with original Doom2 v1.9 - if a soul is charging and - // hit by a raising floor this incorrectly reverses its Y momentum. - // - - if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) - mo->momz = -mo->momz; - - if ( (mo->flags & MF_MISSILE) - && !(mo->flags & MF_NOCLIP) ) - { - P_ExplodeMissile (mo); - return; - } + /* hit the floor */ + + /* Note (id): + * somebody left this after the setting momz to 0, + * kinda useless there. + * + * cph - This was the a bug in the linuxdoom-1.10 source which + * caused it not to sync Doom 2 v1.9 demos. Someone + * added the above comment and moved up the following code. So + * demos would desync in close lost soul fights. + * Note that this only applies to original Doom 1 or Doom2 demos - not + * Final Doom and Ultimate Doom. So we test demo_compatibility *and* + * gamemission. (Note we assume that Doom1 is always Ult Doom, which + * seems to hold for most published demos.) + * + * fraggle - cph got the logic here slightly wrong. There are three + * versions of Doom 1.9: + * + * * The version used in registered doom 1.9 + doom2 - no bounce + * * The version used in ultimate doom - has bounce + * * The version used in final doom - has bounce + * + * So we need to check that this is either retail or commercial + * (but not doom2) + */ + + int correct_lost_soul_bounce = gameversion >= exe_ultimate; + + if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) + { + /* the skull slammed into something */ + + mo->momz = -mo->momz; + } + + if (mo->momz < 0) + { + if (mo->player && mo->momz < -GRAVITY * 8) + { + /* Squat down. + * Decrease viewheight for a moment after hitting the ground + * (hard), and utter appropriate sound. + */ + + mo->player->deltaviewheight = mo->momz >> 3; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_OOF); +#endif + } + + mo->momz = 0; + } + + mo->z = mo->floorz; + + /* cph 2001/05/26 - + * See lost soul bouncing comment above. We need this here for bug + * compatibility with original Doom2 v1.9 - if a soul is charging and + * hit by a raising floor this incorrectly reverses its Y momentum. + */ + + if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) + mo->momz = -mo->momz; + + if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) + { + p_explode_missile(mo); + return; + } } - else if (! (mo->flags & MF_NOGRAVITY) ) + else if (!(mo->flags & MF_NOGRAVITY)) { - if (mo->momz == 0) - mo->momz = -GRAVITY*2; - else - mo->momz -= GRAVITY; + if (mo->momz == 0) + mo->momz = -GRAVITY * 2; + else + mo->momz -= GRAVITY; } - - if (mo->z + mo->height > mo->ceilingz) + + if (mo->z + mo->height > mo->ceilingz) { - // hit the ceiling - if (mo->momz > 0) - mo->momz = 0; - { - mo->z = mo->ceilingz - mo->height; - } - - if (mo->flags & MF_SKULLFLY) - { // the skull slammed into something - mo->momz = -mo->momz; - } - - if ( (mo->flags & MF_MISSILE) - && !(mo->flags & MF_NOCLIP) ) - { - P_ExplodeMissile (mo); - return; - } + /* hit the ceiling */ + + if (mo->momz > 0) + { + mo->momz = 0; + } + + mo->z = mo->ceilingz - mo->height; + + if (mo->flags & MF_SKULLFLY) + { + /* the skull slammed into something */ + + mo->momz = -mo->momz; + } + + if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) + { + p_explode_missile(mo); + return; + } } -} +} + +/**************************************************************************** + * Name: p_nightmare_respawn + ****************************************************************************/ + +static void p_nightmare_respawn(mobj_t *mobj) +{ + fixed_t x; + fixed_t y; + fixed_t z; + subsector_t *ss; + mobj_t *mo; + mapthing_t *mthing; + x = mobj->spawnpoint.x << FRACBITS; + y = mobj->spawnpoint.y << FRACBITS; + /* something is occupying it's position? */ -// -// P_NightmareRespawn -// -void -P_NightmareRespawn (mobj_t* mobj) + if (!p_check_position(mobj, x, y)) return; /* no respawn */ + + /* spawn a teleport fog at old spot because of removal of the body? */ + + mo = p_spawn_mobj(mobj->x, mobj->y, mobj->subsector->sector->floorheight, + MT_TFOG); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + /* initiate teleport sound */ + + s_start_sound(mo, SFX_TELEPT); +#endif + + /* spawn a teleport fog at the new spot */ + + ss = r_point_in_subsector(x, y); + + mo = p_spawn_mobj(x, y, ss->sector->floorheight, MT_TFOG); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_TELEPT); +#endif + + mthing = &mobj->spawnpoint; /* spawn the new monster */ + + /* spawn it */ + + if (mobj->info->flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + /* inherit attributes from deceased one */ + + mo = p_spawn_mobj(x, y, z, mobj->type); + mo->spawnpoint = mobj->spawnpoint; + mo->angle = ANG45 * (mthing->angle / 45); + + if (mthing->options & MTF_AMBUSH) mo->flags |= MF_AMBUSH; + + mo->reactiontime = 18; + + /* remove the old monster, */ + + p_remove_mobj(mobj); +} + +/**************************************************************************** + * Name: p_check_missile_spawn + * + * Description: + * Moves the missile forward a bit and possibly explodes it right there. + * + ****************************************************************************/ + +static void p_check_missile_spawn(mobj_t *th) +{ + th->tics -= p_random() & 3; + if (th->tics < 1) th->tics = 1; + + /* move a little forward so an angle can be computed if it immediately + * explodes + */ + + th->x += (th->momx >> 1); + th->y += (th->momy >> 1); + th->z += (th->momz >> 1); + + if (!p_try_move(th, th->x, th->y)) p_explode_missile(th); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: p_set_mobj_state + * + * Description: + * Returns true if the mobj is still present. + * + ****************************************************************************/ + +boolean p_set_mobj_state(mobj_t *mobj, statenum_t state) { - fixed_t x; - fixed_t y; - fixed_t z; - subsector_t* ss; - mobj_t* mo; - mapthing_t* mthing; - - x = mobj->spawnpoint.x << FRACBITS; - y = mobj->spawnpoint.y << FRACBITS; - - // somthing is occupying it's position? - if (!P_CheckPosition (mobj, x, y) ) - return; // no respwan - - // spawn a teleport fog at old spot - // because of removal of the body? - mo = P_SpawnMobj (mobj->x, - mobj->y, - mobj->subsector->sector->floorheight , MT_TFOG); - // initiate teleport sound - S_StartSound (mo, sfx_telept); - - // spawn a teleport fog at the new spot - ss = R_PointInSubsector (x,y); - - mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG); - - S_StartSound (mo, sfx_telept); - - // spawn the new monster - mthing = &mobj->spawnpoint; - - // spawn it - if (mobj->info->flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; - - // inherit attributes from deceased one - mo = P_SpawnMobj (x,y,z, mobj->type); - mo->spawnpoint = mobj->spawnpoint; - mo->angle = ANG45 * (mthing->angle/45); - - if (mthing->options & MTF_AMBUSH) - mo->flags |= MF_AMBUSH; - - mo->reactiontime = 18; - - // remove the old monster, - P_RemoveMobj (mobj); + state_t *st; + int cycle_counter = 0; + + do + { + if (state == S_NULL) + { + mobj->state = (state_t *)S_NULL; + p_remove_mobj(mobj); + return false; + } + + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + /* Modified handling. + * Call action functions when the state is set + */ + + if (st->action.acp1) st->action.acp1(mobj); + + state = st->nextstate; + + if (cycle_counter++ > MOBJ_CYCLE_LIMIT) + { + i_error("p_set_mobj_state: Infinite state cycle detected!"); + } + } + while (!mobj->tics); + + return true; } +/**************************************************************************** + * Name: p_mobj_thinker + ****************************************************************************/ -// -// P_MobjThinker -// -void P_MobjThinker (mobj_t* mobj) +void p_mobj_thinker(mobj_t *mobj) { - // momentum movement - if (mobj->momx - || mobj->momy - || (mobj->flags&MF_SKULLFLY) ) + /* momentum movement */ + + if (mobj->momx || mobj->momy || (mobj->flags & MF_SKULLFLY)) { - P_XYMovement (mobj); + p_xy_movement(mobj); + + /* FIXME: decent NOP/NULL/Nil function pointer please. */ - // FIXME: decent NOP/NULL/Nil function pointer please. - if (mobj->thinker.function.acv == (actionf_v) (-1)) - return; // mobj was removed + if (mobj->thinker.function.acv == (actionf_v)(-1)) + return; /* mobj was removed */ } - if ( (mobj->z != mobj->floorz) - || mobj->momz ) + + if ((mobj->z != mobj->floorz) || mobj->momz) { - P_ZMovement (mobj); - - // FIXME: decent NOP/NULL/Nil function pointer please. - if (mobj->thinker.function.acv == (actionf_v) (-1)) - return; // mobj was removed + p_z_movement(mobj); + + /* FIXME: decent NOP/NULL/Nil function pointer please. */ + + if (mobj->thinker.function.acv == (actionf_v)(-1)) + return; /* mobj was removed */ } - - // cycle through states, - // calling action functions at transitions - if (mobj->tics != -1) + /* cycle through states, calling action functions at transitions */ + + if (mobj->tics != -1) { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState (mobj, mobj->state->nextstate) ) - return; // freed itself + mobj->tics--; + + /* you can cycle through multiple states in a tic */ + + if (!mobj->tics) + { + if (!p_set_mobj_state(mobj, mobj->state->nextstate)) + { + return; /* freed itself */ + } + } } - else + else { - // check for nightmare respawn - if (! (mobj->flags & MF_COUNTKILL) ) - return; + /* check for nightmare respawn */ - if (!respawnmonsters) - return; + if (!(mobj->flags & MF_COUNTKILL)) return; - mobj->movecount++; + if (!respawnmonsters) return; - if (mobj->movecount < 12*TICRATE) - return; + mobj->movecount++; - if ( leveltime&31 ) - return; + if (mobj->movecount < 12 * TICRATE) return; - if (P_Random () > 4) - return; + if (leveltime & 31) return; - P_NightmareRespawn (mobj); - } + if (p_random() > 4) return; + p_nightmare_respawn(mobj); + } } +/**************************************************************************** + * Name: p_spawn_mobj + ****************************************************************************/ -// -// P_SpawnMobj -// -mobj_t* -P_SpawnMobj -( fixed_t x, - fixed_t y, - fixed_t z, - mobjtype_t type ) +mobj_t *p_spawn_mobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { - mobj_t* mobj; - state_t* st; - mobjinfo_t* info; - - mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); - memset (mobj, 0, sizeof (*mobj)); - info = &mobjinfo[type]; - - mobj->type = type; - mobj->info = info; - mobj->x = x; - mobj->y = y; - mobj->radius = info->radius; - mobj->height = info->height; - mobj->flags = info->flags; - mobj->health = info->spawnhealth; - - if (gameskill != sk_nightmare) - mobj->reactiontime = info->reactiontime; - - mobj->lastlook = P_Random () % MAXPLAYERS; - // do not set the state with P_SetMobjState, - // because action routines can not be called yet - st = &states[info->spawnstate]; - - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - - // set subsector and/or block links - P_SetThingPosition (mobj); - - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - - if (z == ONFLOORZ) - mobj->z = mobj->floorz; - else if (z == ONCEILINGZ) - mobj->z = mobj->ceilingz - mobj->info->height; - else - mobj->z = z; - - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; - - P_AddThinker (&mobj->thinker); - - return mobj; -} + mobj_t *mobj; + state_t *st; + mobjinfo_t *info; + + mobj = z_malloc(sizeof(*mobj), PU_LEVEL, NULL); + memset(mobj, 0, sizeof(*mobj)); + info = &mobjinfo[type]; + + mobj->type = type; + mobj->info = info; + mobj->x = x; + mobj->y = y; + mobj->radius = info->radius; + mobj->height = info->height; + mobj->flags = info->flags; + mobj->health = info->spawnhealth; + + if (gameskill != sk_nightmare) mobj->reactiontime = info->reactiontime; + + mobj->lastlook = p_random() % MAXPLAYERS; + + /* do not set the state with p_set_mobj_state, + * because action routines can not be called yet + */ + + st = &states[info->spawnstate]; + + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + /* set subsector and/or block links */ -// -// P_RemoveMobj -// -mapthing_t itemrespawnque[ITEMQUESIZE]; -int itemrespawntime[ITEMQUESIZE]; -int iquehead; -int iquetail; + p_set_thing_position(mobj); + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; -void P_RemoveMobj (mobj_t* mobj) + if (z == ONFLOORZ) + mobj->z = mobj->floorz; + else if (z == ONCEILINGZ) + mobj->z = mobj->ceilingz - mobj->info->height; + else + mobj->z = z; + + mobj->thinker.function.acp1 = (actionf_p1)p_mobj_thinker; + + p_add_thinker(&mobj->thinker); + + return mobj; +} + +/**************************************************************************** + * Name: p_remove_mobj + ****************************************************************************/ + +void p_remove_mobj(mobj_t *mobj) { - if ((mobj->flags & MF_SPECIAL) - && !(mobj->flags & MF_DROPPED) - && (mobj->type != MT_INV) - && (mobj->type != MT_INS)) + if ((mobj->flags & MF_SPECIAL) && !(mobj->flags & MF_DROPPED) && + (mobj->type != MT_INV) && (mobj->type != MT_INS)) { - itemrespawnque[iquehead] = mobj->spawnpoint; - itemrespawntime[iquehead] = leveltime; - iquehead = (iquehead+1)&(ITEMQUESIZE-1); + itemrespawnque[iquehead] = mobj->spawnpoint; + itemrespawntime[iquehead] = leveltime; + iquehead = (iquehead + 1) & (ITEMQUESIZE - 1); + + /* lose one off the end? */ - // lose one off the end? - if (iquehead == iquetail) - iquetail = (iquetail+1)&(ITEMQUESIZE-1); + if (iquehead == iquetail) + { + iquetail = (iquetail + 1) & (ITEMQUESIZE - 1); + } } - - // unlink from sector and block lists - P_UnsetThingPosition (mobj); - - // stop any playing sound - S_StopSound (mobj); - - // free block - P_RemoveThinker ((thinker_t*)mobj); -} + /* unlink from sector and block lists */ + + p_unset_thing_position(mobj); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + /* stop any playing sound */ + s_stop_sound(mobj); +#endif + p_remove_thinker((thinker_t *)mobj); /* free block */ +} + +/**************************************************************************** + * Name: p_respawn_specials + ****************************************************************************/ -// -// P_RespawnSpecials -// -void P_RespawnSpecials (void) +void p_respawn_specials(void) { - fixed_t x; - fixed_t y; - fixed_t z; - - subsector_t* ss; - mobj_t* mo; - mapthing_t* mthing; - - int i; - - // only respawn items in deathmatch - if (deathmatch != 2) - return; // - - // nothing left to respawn? - if (iquehead == iquetail) - return; - - // wait at least 30 seconds - if (leveltime - itemrespawntime[iquetail] < 30*TICRATE) - return; - - mthing = &itemrespawnque[iquetail]; - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - // spawn a teleport fog at the new spot - ss = R_PointInSubsector (x,y); - mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); - S_StartSound (mo, sfx_itmbk); - - // find which type to spawn - for (i=0 ; i< NUMMOBJTYPES ; i++) + fixed_t x; + fixed_t y; + fixed_t z; + + subsector_t *ss; + mobj_t *mo; + mapthing_t *mthing; + + int i; + + /* only respawn items in deathmatch */ + + if (deathmatch != 2) return; + + /* nothing left to respawn? */ + + if (iquehead == iquetail) return; + + /* wait at least 30 seconds */ + + if (leveltime - itemrespawntime[iquetail] < 30 * TICRATE) return; + + mthing = &itemrespawnque[iquetail]; + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + /* spawn a teleport fog at the new spot */ + + ss = r_point_in_subsector(x, y); + mo = p_spawn_mobj(x, y, ss->sector->floorheight, MT_IFOG); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(mo, SFX_ITMBK); +#endif + + /* find which type to spawn */ + + for (i = 0; i < NUMMOBJTYPES; i++) { - if (mthing->type == mobjinfo[i].doomednum) - break; + if (mthing->type == mobjinfo[i].doomednum) break; } - if (i >= NUMMOBJTYPES) + if (i >= NUMMOBJTYPES) { - I_Error("P_RespawnSpecials: Failed to find mobj type with doomednum " - "%d when respawning thing. This would cause a buffer overrun " - "in vanilla Doom", mthing->type); + i_error("p_respawn_specials: Failed to find mobj type with doomednum " + "%d when respawning thing. This would cause a buffer overrun " + "in vanilla Doom", + mthing->type); } - // spawn it - if (mobjinfo[i].flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; + /* spawn it */ - mo = P_SpawnMobj (x,y,z, i); - mo->spawnpoint = *mthing; - mo->angle = ANG45 * (mthing->angle/45); + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; - // pull it from the que - iquetail = (iquetail+1)&(ITEMQUESIZE-1); -} + mo = p_spawn_mobj(x, y, z, i); + mo->spawnpoint = *mthing; + mo->angle = ANG45 * (mthing->angle / 45); + /* pull it from the que */ + iquetail = (iquetail + 1) & (ITEMQUESIZE - 1); +} +/**************************************************************************** + * Name: p_spawn_player + * + * Description: + * Called when a player is spawned on the level. + * Most of the player structure stays unchanged between levels. + * + ****************************************************************************/ -// -// P_SpawnPlayer -// Called when a player is spawned on the level. -// Most of the player structure stays unchanged -// between levels. -// -void P_SpawnPlayer (mapthing_t* mthing) +void p_spawn_player(mapthing_t *mthing) { - player_t* p; - fixed_t x; - fixed_t y; - fixed_t z; + player_t *p; + fixed_t x; + fixed_t y; + fixed_t z; - mobj_t* mobj; + mobj_t *mobj; - int i; + int i; - if (mthing->type == 0) + if (mthing->type == 0) { - return; + return; } - // not playing? - if (!playeringame[mthing->type-1]) - return; - - p = &players[mthing->type-1]; - - if (p->playerstate == PST_REBORN) - G_PlayerReborn (mthing->type-1); - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - z = ONFLOORZ; - mobj = P_SpawnMobj (x,y,z, MT_PLAYER); - - // set color translations for player sprites - if (mthing->type > 1) - mobj->flags |= (mthing->type-1)<angle = ANG45 * (mthing->angle/45); - mobj->player = p; - mobj->health = p->health; - - p->mo = mobj; - p->playerstate = PST_LIVE; - p->refire = 0; - p->message = NULL; - p->damagecount = 0; - p->bonuscount = 0; - p->extralight = 0; - p->fixedcolormap = 0; - p->viewheight = VIEWHEIGHT; - - // setup gun psprite - P_SetupPsprites (p); - - // give all cards in death match mode - if (deathmatch) - for (i=0 ; icards[i] = true; - - if (mthing->type-1 == consoleplayer) + /* not playing? */ + + if (!playeringame[mthing->type - 1]) return; + + p = &players[mthing->type - 1]; + + if (p->playerstate == PST_REBORN) g_player_reborn(mthing->type - 1); + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = ONFLOORZ; + mobj = p_spawn_mobj(x, y, z, MT_PLAYER); + + /* set color translations for player sprites */ + + if (mthing->type > 1) mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT; + + mobj->angle = ANG45 * (mthing->angle / 45); + mobj->player = p; + mobj->health = p->health; + + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + p->message = NULL; + p->damagecount = 0; + p->bonuscount = 0; + p->extralight = 0; + p->fixedcolormap = 0; + p->viewheight = VIEWHEIGHT; + + p_setup_psprites(p); /* setup gun psprite */ + + /* give all cards in death match mode */ + + if (deathmatch) + { + for (i = 0; i < NUMCARDS; i++) + { + p->cards[i] = true; + } + } + + if (mthing->type - 1 == consoleplayer) { - // wake up the status bar - ST_Start (); - // wake up the heads up text - HU_Start (); + st_start(); /* wake up the status bar */ + hu_start(); /* wake up the heads up text */ } } +/**************************************************************************** + * Name: p_spawn_map_thing + * + * Description: + * The fields of the mapthing should already be in host byte order. + * + ****************************************************************************/ -// -// P_SpawnMapThing -// The fields of the mapthing should -// already be in host byte order. -// -void P_SpawnMapThing (mapthing_t* mthing) +void p_spawn_map_thing(mapthing_t *mthing) { - int i; - int bit; - mobj_t* mobj; - fixed_t x; - fixed_t y; - fixed_t z; - - // count deathmatch start positions - if (mthing->type == 11) + int i; + int bit; + mobj_t *mobj; + fixed_t x; + fixed_t y; + fixed_t z; + + /* count deathmatch start positions */ + + if (mthing->type == 11) { - if (deathmatch_p < &deathmatchstarts[10]) - { - memcpy (deathmatch_p, mthing, sizeof(*mthing)); - deathmatch_p++; - } - return; + if (deathmatch_p < &deathmatchstarts[10]) + { + memcpy(deathmatch_p, mthing, sizeof(*mthing)); + deathmatch_p++; + } + + return; + } + + if (mthing->type <= 0) + { + /* Thing type 0 is actually "player -1 start". + * For some reason, Vanilla Doom accepts/ignores this. + */ + + return; } - if (mthing->type <= 0) + /* check for players specially */ + + if (mthing->type <= 4) { - // Thing type 0 is actually "player -1 start". - // For some reason, Vanilla Doom accepts/ignores this. + /* save spots for respawning in network games */ - return; + playerstarts[mthing->type - 1] = *mthing; + playerstartsingame[mthing->type - 1] = true; + if (!deathmatch) p_spawn_player(mthing); + + return; } - - // check for players specially - if (mthing->type <= 4) + + /* check for appropriate skill level */ + + if (!netgame && (mthing->options & 16)) return; + + if (gameskill == sk_baby) { - // save spots for respawning in network games - playerstarts[mthing->type-1] = *mthing; - playerstartsingame[mthing->type-1] = true; - if (!deathmatch) - P_SpawnPlayer (mthing); + bit = 1; + } + else if (gameskill == sk_nightmare) + { + bit = 4; + } + else + { + /* avoid undefined behavior (left shift by negative value and rhs too + * big) by accurately emulating what doom.exe did: reduce mod 32. For + * more details check: + * https://github.com/chocolate-doom/chocolate-doom/issues/1677 + */ - return; + bit = (int)(1U << ((gameskill - 1) & 0x1f)); } - // check for appropriate skill level - if (!netgame && (mthing->options & 16) ) - return; - - if (gameskill == sk_baby) - bit = 1; - else if (gameskill == sk_nightmare) - bit = 4; - else - // avoid undefined behavior (left shift by negative value and rhs too big) - // by accurately emulating what doom.exe did: reduce mod 32. - // For more details check: - // https://github.com/chocolate-doom/chocolate-doom/issues/1677 - bit = (int) (1U << ((gameskill - 1) & 0x1F)); - - if (!(mthing->options & bit) ) - return; - - // find which type to spawn - for (i=0 ; i< NUMMOBJTYPES ; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i==NUMMOBJTYPES) - I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)", - mthing->type, - mthing->x, mthing->y); - - // don't spawn keycards and players in deathmatch - if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) - return; - - // don't spawn any monsters if -nomonsters - if (nomonsters - && ( i == MT_SKULL - || (mobjinfo[i].flags & MF_COUNTKILL)) ) + if (!(mthing->options & bit)) return; + + /* find which type to spawn */ + + for (i = 0; i < NUMMOBJTYPES; i++) { - return; + if (mthing->type == mobjinfo[i].doomednum) break; } - - // spawn it - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - if (mobjinfo[i].flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; - - mobj = P_SpawnMobj (x,y,z, i); - mobj->spawnpoint = *mthing; - - if (mobj->tics > 0) - mobj->tics = 1 + (P_Random () % mobj->tics); - if (mobj->flags & MF_COUNTKILL) - totalkills++; - if (mobj->flags & MF_COUNTITEM) - totalitems++; - - mobj->angle = ANG45 * (mthing->angle/45); - if (mthing->options & MTF_AMBUSH) - mobj->flags |= MF_AMBUSH; -} + if (i == NUMMOBJTYPES) + i_error("p_spawn_map_thing: Unknown type %i at (%i, %i)", mthing->type, + mthing->x, mthing->y); + /* don't spawn keycards and players in deathmatch */ -// -// GAME SPAWN FUNCTIONS -// + if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) return; + /* don't spawn any monsters if -nomonsters */ -// -// P_SpawnPuff -// + if (nomonsters && (i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL))) + { + return; + } -void -P_SpawnPuff -( fixed_t x, - fixed_t y, - fixed_t z ) -{ - mobj_t* th; - - z += (P_SubRandom() << 10); - - th = P_SpawnMobj (x,y,z, MT_PUFF); - th->momz = FRACUNIT; - th->tics -= P_Random()&3; - - if (th->tics < 1) - th->tics = 1; - - // don't make punches spark on the wall - if (attackrange == MELEERANGE) - P_SetMobjState (th, S_PUFF3); -} + /* spawn it */ + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; -// -// P_SpawnBlood -// -void -P_SpawnBlood -( fixed_t x, - fixed_t y, - fixed_t z, - int damage ) -{ - mobj_t* th; - - z += (P_SubRandom() << 10); - th = P_SpawnMobj (x,y,z, MT_BLOOD); - th->momz = FRACUNIT*2; - th->tics -= P_Random()&3; - - if (th->tics < 1) - th->tics = 1; - - if (damage <= 12 && damage >= 9) - P_SetMobjState (th,S_BLOOD2); - else if (damage < 9) - P_SetMobjState (th,S_BLOOD3); + mobj = p_spawn_mobj(x, y, z, i); + mobj->spawnpoint = *mthing; + + if (mobj->tics > 0) mobj->tics = 1 + (p_random() % mobj->tics); + if (mobj->flags & MF_COUNTKILL) totalkills++; + if (mobj->flags & MF_COUNTITEM) totalitems++; + + mobj->angle = ANG45 * (mthing->angle / 45); + if (mthing->options & MTF_AMBUSH) mobj->flags |= MF_AMBUSH; } +/* GAME SPAWN FUNCTIONS */ +/**************************************************************************** + * Name: p_spawn_puff + ****************************************************************************/ -// -// P_CheckMissileSpawn -// Moves the missile forward a bit -// and possibly explodes it right there. -// -void P_CheckMissileSpawn (mobj_t* th) +void p_spawn_puff(fixed_t x, fixed_t y, fixed_t z) { - th->tics -= P_Random()&3; - if (th->tics < 1) - th->tics = 1; - - // move a little forward so an angle can - // be computed if it immediately explodes - th->x += (th->momx>>1); - th->y += (th->momy>>1); - th->z += (th->momz>>1); - - if (!P_TryMove (th, th->x, th->y)) - P_ExplodeMissile (th); + mobj_t *th; + + z += (p_sub_random() << 10); + + th = p_spawn_mobj(x, y, z, MT_PUFF); + th->momz = FRACUNIT; + th->tics -= p_random() & 3; + + if (th->tics < 1) th->tics = 1; + + /* don't make punches spark on the wall */ + + if (attackrange == MELEERANGE) p_set_mobj_state(th, S_PUFF3); } -// Certain functions assume that a mobj_t pointer is non-NULL, -// causing a crash in some situations where it is NULL. Vanilla -// Doom did not crash because of the lack of proper memory -// protection. This function substitutes NULL pointers for -// pointers to a dummy mobj, to avoid a crash. +/**************************************************************************** + * Name: p_spawn_blood + ****************************************************************************/ + +void p_spawn_blood(fixed_t x, fixed_t y, fixed_t z, int damage) +{ + mobj_t *th; + + z += (p_sub_random() << 10); + th = p_spawn_mobj(x, y, z, MT_BLOOD); + th->momz = FRACUNIT * 2; + th->tics -= p_random() & 3; + + if (th->tics < 1) th->tics = 1; + + if (damage <= 12 && damage >= 9) + p_set_mobj_state(th, S_BLOOD2); + else if (damage < 9) + p_set_mobj_state(th, S_BLOOD3); +} -mobj_t *P_SubstNullMobj(mobj_t *mobj) +/**************************************************************************** + * Name: p_subst_null_mobj + * + * Description: + * Certain functions assume that a mobj_t pointer is non-NULL, + * causing a crash in some situations where it is NULL. Vanilla + * Doom did not crash because of the lack of proper memory + * protection. This function substitutes NULL pointers for + * pointers to a dummy mobj, to avoid a crash. + * + ****************************************************************************/ + +mobj_t *p_subst_null_mobj(mobj_t *mobj) { - if (mobj == NULL) + if (mobj == NULL) { - static mobj_t dummy_mobj; + static mobj_t dummy_mobj; - dummy_mobj.x = 0; - dummy_mobj.y = 0; - dummy_mobj.z = 0; - dummy_mobj.flags = 0; + dummy_mobj.x = 0; + dummy_mobj.y = 0; + dummy_mobj.z = 0; + dummy_mobj.flags = 0; - mobj = &dummy_mobj; + mobj = &dummy_mobj; } - return mobj; + return mobj; } -// -// P_SpawnMissile -// -mobj_t* -P_SpawnMissile -( mobj_t* source, - mobj_t* dest, - mobjtype_t type ) +/**************************************************************************** + * Name: p_spawn_missile + ****************************************************************************/ + +mobj_t *p_spawn_missile(mobj_t *source, mobj_t *dest, mobjtype_t type) { - mobj_t* th; - angle_t an; - int dist; - - th = P_SpawnMobj (source->x, - source->y, - source->z + 4*8*FRACUNIT, type); - - if (th->info->seesound) - S_StartSound (th, th->info->seesound); - - th->target = source; // where it came from - an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); - - // fuzzy player - if (dest->flags & MF_SHADOW) - an += P_SubRandom() << 20; - - th->angle = an; - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul (th->info->speed, finecosine[an]); - th->momy = FixedMul (th->info->speed, finesine[an]); - - dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); - dist = dist / th->info->speed; - - if (dist < 1) - dist = 1; - - th->momz = (dest->z - source->z) / dist; - P_CheckMissileSpawn (th); - - return th; + mobj_t *th; + angle_t an; + int dist; + + th = p_spawn_mobj(source->x, source->y, + source->z + 4 * 8 * FRACUNIT, type); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (th->info->seesound) s_start_sound(th, th->info->seesound); +#endif + + th->target = source; /* where it came from */ + an = r_point_to_angle2(source->x, source->y, dest->x, dest->y); + + /* fuzzy player */ + + if (dest->flags & MF_SHADOW) an += p_sub_random() << 20; + + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = fixed_mul(th->info->speed, finecosine[an]); + th->momy = fixed_mul(th->info->speed, finesine[an]); + + dist = p_approx_distance(dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + + if (dist < 1) dist = 1; + + th->momz = (dest->z - source->z) / dist; + p_check_missile_spawn(th); + + return th; } +/**************************************************************************** + * Name: p_spawn_player_missile + * + * Description: + * Tries to aim at a nearby monster + * + ****************************************************************************/ -// -// P_SpawnPlayerMissile -// Tries to aim at a nearby monster -// -void -P_SpawnPlayerMissile -( mobj_t* source, - mobjtype_t type ) +void p_spawn_player_missile(mobj_t *source, mobjtype_t type) { - mobj_t* th; - angle_t an; - - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t slope; - - // see which target is to be aimed at - an = source->angle; - slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); - - if (!linetarget) + mobj_t *th; + angle_t an; + + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t slope; + + /* see which target is to be aimed at */ + + an = source->angle; + slope = p_aim_line_attack(source, an, 16 * 64 * FRACUNIT); + + if (!linetarget) { - an += 1<<26; - slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); - - if (!linetarget) - { - an -= 2<<26; - slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); - } - - if (!linetarget) - { - an = source->angle; - slope = 0; - } + an += 1 << 26; + slope = p_aim_line_attack(source, an, 16 * 64 * FRACUNIT); + + if (!linetarget) + { + an -= 2 << 26; + slope = p_aim_line_attack(source, an, 16 * 64 * FRACUNIT); + } + + if (!linetarget) + { + an = source->angle; + slope = 0; + } } - - x = source->x; - y = source->y; - z = source->z + 4*8*FRACUNIT; - - th = P_SpawnMobj (x,y,z, type); - - if (th->info->seesound) - S_StartSound (th, th->info->seesound); - - th->target = source; - th->angle = an; - th->momx = FixedMul( th->info->speed, - finecosine[an>>ANGLETOFINESHIFT]); - th->momy = FixedMul( th->info->speed, - finesine[an>>ANGLETOFINESHIFT]); - th->momz = FixedMul( th->info->speed, slope); - - P_CheckMissileSpawn (th); -} + x = source->x; + y = source->y; + z = source->z + 4 * 8 * FRACUNIT; + + th = p_spawn_mobj(x, y, z, type); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (th->info->seesound) s_start_sound(th, th->info->seesound); +#endif + + th->target = source; + th->angle = an; + th->momx = fixed_mul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); + th->momy = fixed_mul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); + th->momz = fixed_mul(th->info->speed, slope); + + p_check_missile_spawn(th); +} diff --git a/games/NXDoom/src/doom/p_mobj.h b/games/NXDoom/src/doom/p_mobj.h index 90ed764b91c..6cd73f3a67b 100644 --- a/games/NXDoom/src/doom/p_mobj.h +++ b/games/NXDoom/src/doom/p_mobj.h @@ -1,284 +1,357 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Map Objects, MObj, definition and handling. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_mobj.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Map Objects, MObj, definition and handling. + * + ****************************************************************************/ #ifndef __P_MOBJ__ #define __P_MOBJ__ -// Basics. -#include "tables.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Basics. */ + #include "m_fixed.h" +#include "tables.h" + +/* We need the thinker_t stuff. */ -// We need the thinker_t stuff. #include "d_think.h" -// We need the WAD data structure for Map things, -// from the THINGS lump. +/* We need the WAD data structure for Map things, from the THINGS lump. */ + #include "doomdata.h" -// States are tied to finite states are -// tied to animation frames. -// Needs precompiled tables/data structures. +/* States are tied to finite states are tied to animation frames. + * Needs precompiled tables/data structures. + */ + #include "info.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* NOTES: mobj_t + * + * mobj_ts are used to tell the refresh where to draw an image, + * tell the world simulation when objects are contacted, + * and tell the sound driver how to position a sound. + * + * The refresh uses the next and prev links to follow + * lists of things in sectors as they are being drawn. + * The sprite, frame, and angle elements determine which patch_t + * is used to draw the sprite if it is visible. + * The sprite and frame values are almost always set + * from state_t structures. + * The statescr.exe utility generates the states.h and states.c + * files that contain the sprite/frame numbers from the + * statescr.txt source file. + * The xyz origin point represents a point at the bottom middle + * of the sprite (between the feet of a biped). + * This is the default origin position for patch_ts grabbed + * with lumpy.exe. + * A walking creature will have its z equal to the floor + * it is standing on. + * + * The sound code uses the x,y, and subsector fields + * to do stereo positioning of any sound effited by the mobj_t. + * + * The play simulation uses the blocklinks, x,y,z, radius, height + * to determine when mobj_ts are touching each other, + * touching lines in the map, or hit by trace lines (gunshots, + * lines of sight, etc). + * The mobj_t->flags element has various bit flags + * used by the simulation. + * + * Every mobj_t is linked into a single sector + * based on its origin coordinates. + * The subsector_t is found with r_point_in_subsector(x,y), + * and the sector_t can be found with subsector->sector. + * The sector links are only used by the rendering code, + * the play simulation does not care about them at all. + * + * Any mobj_t that needs to be acted upon by something else + * in the play world (block movement, be shot, etc) will also + * need to be linked into the blockmap. + * If the thing has the MF_NOBLOCK flag set, it will not use + * the block links. It can still interact with other things, + * but only as the instigator (missiles will run into other + * things, but nothing can run into a missile). + * Each block in the grid is 128*128 units, and knows about + * every line_t that it contains a piece of, and every + * interactable mobj_t that has its origin contained. + * + * A valid mobj_t is a mobj_t that has the proper subsector_t + * filled in for its xy coordinates and is linked into the + * sector from which the subsector was made, or has the + * MF_NOSECTOR flag set (the subsector_t needs to be valid + * even if MF_NOSECTOR is set), and is linked into a blockmap + * block or has the MF_NOBLOCKMAP flag set. + * Links should only be modified by the P_[Un]SetThingPosition() + * functions. + * Do not change the MF_NO? flags while a thing is valid. + * + * Any questions? + */ + +/* Misc. mobj flags */ +typedef enum +{ + MF_SPECIAL = 1, /* Call P_SpecialThing when touched. */ + MF_SOLID = 2, /* Blocks. */ + MF_SHOOTABLE = 4, /* Can be hit. */ + /* Don't use the sector links (invisible but touchable). */ + MF_NOSECTOR = 8, + /* Don't use the blocklinks (inert but displayable) */ -// -// NOTES: mobj_t -// -// mobj_ts are used to tell the refresh where to draw an image, -// tell the world simulation when objects are contacted, -// and tell the sound driver how to position a sound. -// -// The refresh uses the next and prev links to follow -// lists of things in sectors as they are being drawn. -// The sprite, frame, and angle elements determine which patch_t -// is used to draw the sprite if it is visible. -// The sprite and frame values are allmost allways set -// from state_t structures. -// The statescr.exe utility generates the states.h and states.c -// files that contain the sprite/frame numbers from the -// statescr.txt source file. -// The xyz origin point represents a point at the bottom middle -// of the sprite (between the feet of a biped). -// This is the default origin position for patch_ts grabbed -// with lumpy.exe. -// A walking creature will have its z equal to the floor -// it is standing on. -// -// The sound code uses the x,y, and subsector fields -// to do stereo positioning of any sound effited by the mobj_t. -// -// The play simulation uses the blocklinks, x,y,z, radius, height -// to determine when mobj_ts are touching each other, -// touching lines in the map, or hit by trace lines (gunshots, -// lines of sight, etc). -// The mobj_t->flags element has various bit flags -// used by the simulation. -// -// Every mobj_t is linked into a single sector -// based on its origin coordinates. -// The subsector_t is found with R_PointInSubsector(x,y), -// and the sector_t can be found with subsector->sector. -// The sector links are only used by the rendering code, -// the play simulation does not care about them at all. -// -// Any mobj_t that needs to be acted upon by something else -// in the play world (block movement, be shot, etc) will also -// need to be linked into the blockmap. -// If the thing has the MF_NOBLOCK flag set, it will not use -// the block links. It can still interact with other things, -// but only as the instigator (missiles will run into other -// things, but nothing can run into a missile). -// Each block in the grid is 128*128 units, and knows about -// every line_t that it contains a piece of, and every -// interactable mobj_t that has its origin contained. -// -// A valid mobj_t is a mobj_t that has the proper subsector_t -// filled in for its xy coordinates and is linked into the -// sector from which the subsector was made, or has the -// MF_NOSECTOR flag set (the subsector_t needs to be valid -// even if MF_NOSECTOR is set), and is linked into a blockmap -// block or has the MF_NOBLOCKMAP flag set. -// Links should only be modified by the P_[Un]SetThingPosition() -// functions. -// Do not change the MF_NO? flags while a thing is valid. -// -// Any questions? -// - -// -// Misc. mobj flags -// -typedef enum -{ - // Call P_SpecialThing when touched. - MF_SPECIAL = 1, - // Blocks. - MF_SOLID = 2, - // Can be hit. - MF_SHOOTABLE = 4, - // Don't use the sector links (invisible but touchable). - MF_NOSECTOR = 8, - // Don't use the blocklinks (inert but displayable) - MF_NOBLOCKMAP = 16, - - // Not to be activated by sound, deaf monster. - MF_AMBUSH = 32, - // Will try to attack right back. - MF_JUSTHIT = 64, - // Will take at least one step before attacking. - MF_JUSTATTACKED = 128, - // On level spawning (initial position), - // hang from ceiling instead of stand on floor. - MF_SPAWNCEILING = 256, - // Don't apply gravity (every tic), - // that is, object will float, keeping current height - // or changing it actively. - MF_NOGRAVITY = 512, - - // Movement flags. - // This allows jumps from high places. - MF_DROPOFF = 0x400, - // For players, will pick up items. - MF_PICKUP = 0x800, - // Player cheat. ??? - MF_NOCLIP = 0x1000, - // Player: keep info about sliding along walls. - MF_SLIDE = 0x2000, - // Allow moves to any height, no gravity. - // For active floaters, e.g. cacodemons, pain elementals. - MF_FLOAT = 0x4000, - // Don't cross lines - // ??? or look at heights on teleport. - MF_TELEPORT = 0x8000, - // Don't hit same species, explode on block. - // Player missiles as well as fireballs of various kinds. - MF_MISSILE = 0x10000, - // Dropped by a demon, not level spawned. - // E.g. ammo clips dropped by dying former humans. - MF_DROPPED = 0x20000, - // Use fuzzy draw (shadow demons or spectres), - // temporary player invisibility powerup. - MF_SHADOW = 0x40000, - // Flag: don't bleed when shot (use puff), - // barrels and shootable furniture shall not bleed. - MF_NOBLOOD = 0x80000, - // Don't stop moving halfway off a step, - // that is, have dead bodies slide down all the way. - MF_CORPSE = 0x100000, - // Floating to a height for a move, ??? - // don't auto float to target's height. - MF_INFLOAT = 0x200000, - - // On kill, count this enemy object - // towards intermission kill total. - // Happy gathering. - MF_COUNTKILL = 0x400000, - - // On picking up, count this item object - // towards intermission item total. - MF_COUNTITEM = 0x800000, - - // Special handling: skull in flight. - // Neither a cacodemon nor a missile. - MF_SKULLFLY = 0x1000000, - - // Don't spawn this object - // in death match mode (e.g. key cards). - MF_NOTDMATCH = 0x2000000, - - // Player sprites in multiplayer modes are modified - // using an internal color lookup table for re-indexing. - // If 0x4 0x8 or 0xc, - // use a translation table for player colormaps - MF_TRANSLATION = 0xc000000, - // Hmm ???. - MF_TRANSSHIFT = 26 + MF_NOBLOCKMAP = 16, + + /* Not to be activated by sound, deaf monster. */ + + MF_AMBUSH = 32, + + /* Will try to attack right back. */ + + MF_JUSTHIT = 64, + + /* Will take at least one step before attacking. */ + + MF_JUSTATTACKED = 128, + + /* On level spawning (initial position), hang from ceiling instead of stand + * on floor. + */ + + MF_SPAWNCEILING = 256, + + /* Don't apply gravity (every tic), that is, object will float, keeping + * current height or changing it actively. + */ + + MF_NOGRAVITY = 512, + + /* Movement flags. This allows jumps from high places. */ + + MF_DROPOFF = 0x400, + + /* For players, will pick up items. */ + + MF_PICKUP = 0x800, + + /* Player cheat. ??? */ + + MF_NOCLIP = 0x1000, + + /* Player: keep info about sliding along walls. */ + + MF_SLIDE = 0x2000, + + /* Allow moves to any height, no gravity. + * For active floaters, e.g. cacodemons, pain elementals. + */ + + MF_FLOAT = 0x4000, + + /* Don't cross lines ??? or look at heights on teleport. */ + + MF_TELEPORT = 0x8000, + + /* Don't hit same species, explode on block. + * Player missiles as well as fireballs of various kinds. + */ + + MF_MISSILE = 0x10000, + + /* Dropped by a demon, not level spawned. + * E.g. ammo clips dropped by dying former humans. + */ + + MF_DROPPED = 0x20000, + + /* Use fuzzy draw (shadow demons or spectres), temporary player + * invisibility powerup. + */ + + MF_SHADOW = 0x40000, + + /* Flag: don't bleed when shot (use puff), barrels and shootable furniture + * shall not bleed. + */ + + MF_NOBLOOD = 0x80000, + + /* Don't stop moving halfway off a step, that is, have dead bodies slide + * down all the way. + */ + + MF_CORPSE = 0x100000, + + /* Floating to a height for a move, ??? don't auto float to target's + * height. + */ + + MF_INFLOAT = 0x200000, + + /* On kill, count this enemy object towards intermission kill total. + * Happy gathering. + */ + MF_COUNTKILL = 0x400000, + + /* On picking up, count this item object towards intermission item total. */ + + MF_COUNTITEM = 0x800000, + + /* Special handling: skull in flight. + * Neither a cacodemon nor a missile. + */ + + MF_SKULLFLY = 0x1000000, + + /* Don't spawn this object in death match mode (e.g. key cards). + */ + + MF_NOTDMATCH = 0x2000000, + + /* Player sprites in multiplayer modes are modified using an internal color + * lookup table for re-indexing. + * + * If 0x4 0x8 or 0xc, use a translation table for player colormaps + */ + + MF_TRANSLATION = 0xc000000, + + /* Hmm ???. */ + + MF_TRANSSHIFT = 26 } mobjflag_t; +/* Map Object definition. */ -// Map Object definition. typedef struct mobj_s { - // List: thinker links. - thinker_t thinker; - - // Info for drawing: position. - fixed_t x; - fixed_t y; - fixed_t z; - - // More list: links in sector (if needed) - struct mobj_s* snext; - struct mobj_s* sprev; - - //More drawing info: to determine current sprite. - angle_t angle; // orientation - spritenum_t sprite; // used to find patch_t and flip value - int frame; // might be ORed with FF_FULLBRIGHT - - // Interaction info, by BLOCKMAP. - // Links in blocks (if needed). - struct mobj_s* bnext; - struct mobj_s* bprev; - - struct subsector_s* subsector; - - // The closest interval over all contacted Sectors. - fixed_t floorz; - fixed_t ceilingz; - - // For movement checking. - fixed_t radius; - fixed_t height; - - // Momentums, used to update position. - fixed_t momx; - fixed_t momy; - fixed_t momz; - - // If == validcount, already checked. - int validcount; - - mobjtype_t type; - mobjinfo_t* info; // &mobjinfo[mobj->type] - - int tics; // state tic counter - state_t* state; - int flags; - int health; - - // Movement direction, movement generation (zig-zagging). - int movedir; // 0-7 - int movecount; // when 0, select a new dir - - // Thing being chased/attacked (or NULL), - // also the originator for missiles. - struct mobj_s* target; - - // Reaction time: if non 0, don't attack yet. - // Used by player to freeze a bit after teleporting. - int reactiontime; - - // If >0, the target will be chased - // no matter what (even if shot) - int threshold; - - // Additional info record for player avatars only. - // Only valid if type == MT_PLAYER - struct player_s* player; - - // Player number last looked for. - int lastlook; - - // For nightmare respawn. - mapthing_t spawnpoint; - - // Thing being chased/attacked for tracers. - struct mobj_s* tracer; - -} mobj_t; + /* List: thinker links. */ + + thinker_t thinker; + + /* Info for drawing: position. */ + + fixed_t x; + fixed_t y; + fixed_t z; + + /* More list: links in sector (if needed) */ + + struct mobj_s *snext; + struct mobj_s *sprev; + + /* More drawing info: to determine current sprite. */ + + angle_t angle; /* orientation */ + spritenum_t sprite; /* used to find patch_t and flip value */ + int frame; /* might be ORed with FF_FULLBRIGHT */ + + /* Interaction info, by BLOCKMAP. + * Links in blocks (if needed). + */ + + struct mobj_s *bnext; + struct mobj_s *bprev; + + struct subsector_s *subsector; + + /* The closest interval over all contacted Sectors. */ + + fixed_t floorz; + fixed_t ceilingz; + /* For movement checking. */ + fixed_t radius; + fixed_t height; + + /* Momentums, used to update position. */ + + fixed_t momx; + fixed_t momy; + fixed_t momz; + + /* If == validcount, already checked. */ + + int validcount; + + mobjtype_t type; + mobjinfo_t *info; /* &mobjinfo[mobj->type] */ + + int tics; /* state tic counter */ + state_t *state; + int flags; + int health; + + /* Movement direction, movement generation (zig-zagging). */ + + int movedir; /* 0-7 */ + int movecount; /* when 0, select a new dir */ + + /* Thing being chased/attacked (or NULL), + * also the originator for missiles. + */ + + struct mobj_s *target; + + /* Reaction time: if non 0, don't attack yet. + * Used by player to freeze a bit after teleporting. + */ + + int reactiontime; + + /* If >0, the target will be chased + * no matter what (even if shot) + */ + + int threshold; + + /* Additional info record for player avatars only. + * Only valid if type == MT_PLAYER + */ + + struct player_s *player; + + /* Player number last looked for. */ + + int lastlook; + + /* For nightmare re-spawn. */ + + mapthing_t spawnpoint; + + /* Thing being chased/attacked for tracers. */ + + struct mobj_s *tracer; +} mobj_t; -#endif +#endif /* __P_MOBJ__ */ diff --git a/games/NXDoom/src/doom/p_plats.c b/games/NXDoom/src/doom/p_plats.c index 9e773d55cbd..8cbbf70529e 100644 --- a/games/NXDoom/src/doom/p_plats.c +++ b/games/NXDoom/src/doom/p_plats.c @@ -1,304 +1,336 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Plats (i.e. elevator platforms) code, raising/lowering. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_plats.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Plats (i.e. elevator platforms) code, raising/lowering. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include "i_system.h" -#include "z_zone.h" #include "m_random.h" +#include "z_zone.h" #include "doomdef.h" #include "p_local.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* State. */ -// State. #include "doomstat.h" #include "r_state.h" -// Data. -#include "sounds.h" - +/**************************************************************************** + * Public Data + ****************************************************************************/ -plat_t* activeplats[MAXPLATS]; +plat_t *activeplats[MAXPLATS]; +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/* Move a plat up and down */ -// -// Move a plat up and down -// -void T_PlatRaise(plat_t* plat) +void t_plat_raise(plat_t *plat) { - result_e res; - - switch(plat->status) + result_e res; + + switch (plat->status) { - case up: - res = T_MovePlane(plat->sector, - plat->speed, - plat->high, - plat->crush,0,1); - - if (plat->type == raiseAndChange - || plat->type == raiseToNearestAndChange) - { - if (!(leveltime&7)) - S_StartSound(&plat->sector->soundorg, sfx_stnmov); - } - - - if (res == crushed && (!plat->crush)) - { - plat->count = plat->wait; - plat->status = down; - S_StartSound(&plat->sector->soundorg, sfx_pstart); - } - else - { - if (res == pastdest) - { - plat->count = plat->wait; - plat->status = waiting; - S_StartSound(&plat->sector->soundorg, sfx_pstop); - - switch(plat->type) - { - case blazeDWUS: - case downWaitUpStay: - P_RemoveActivePlat(plat); - break; - - case raiseAndChange: - case raiseToNearestAndChange: - P_RemoveActivePlat(plat); - break; - - default: - break; - } - } - } - break; - - case down: - res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1); - - if (res == pastdest) - { - plat->count = plat->wait; - plat->status = waiting; - S_StartSound(&plat->sector->soundorg,sfx_pstop); - } - break; - - case waiting: - if (!--plat->count) - { - if (plat->sector->floorheight == plat->low) - plat->status = up; - else - plat->status = down; - S_StartSound(&plat->sector->soundorg,sfx_pstart); - } - case in_stasis: - break; + case up: + res = t_move_plane(plat->sector, plat->speed, + plat->high, plat->crush, 0, 1); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (plat->type == PLAT_RAISEANDCHANGE || + plat->type == PLAT_RAISETONEARESTANDCHANGE) + { + if (!(leveltime & 7)) + s_start_sound(&plat->sector->soundorg, SFX_STNMOV); + } +#endif + + if (res == crushed && (!plat->crush)) + { + plat->count = plat->wait; + plat->status = down; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&plat->sector->soundorg, SFX_PSTART); +#endif + } + else + { + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&plat->sector->soundorg, SFX_PSTOP); +#endif + + switch (plat->type) + { + case PLAT_BLAZEDWUS: + case PLAT_DOWNWAITUPSTAY: + p_remove_active_plat(plat); + break; + + case PLAT_RAISEANDCHANGE: + case PLAT_RAISETONEARESTANDCHANGE: + p_remove_active_plat(plat); + break; + + default: + break; + } + } + } + break; + + case down: + res = t_move_plane(plat->sector, plat->speed, plat->low, false, 0, -1); + + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&plat->sector->soundorg, SFX_PSTOP); +#endif + } + break; + + case waiting: + if (!--plat->count) + { + if (plat->sector->floorheight == plat->low) + plat->status = up; + else + plat->status = down; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&plat->sector->soundorg, SFX_PSTART); +#endif + } + + case in_stasis: + break; } } +/* Do Platforms + * "amount" is only used for SOME platforms. + */ -// -// Do Platforms -// "amount" is only used for SOME platforms. -// -int -EV_DoPlat -( line_t* line, - plattype_e type, - int amount ) +int ev_do_plat(line_t *line, plattype_e type, int amount) { - plat_t* plat; - int secnum; - int rtn; - sector_t* sec; - - secnum = -1; - rtn = 0; - - - // Activate all plats that are in_stasis - switch(type) + plat_t *plat; + int secnum; + int rtn; + sector_t *sec; + + secnum = -1; + rtn = 0; + + /* Activate all plats that are in_stasis */ + + switch (type) { - case perpetualRaise: - P_ActivateInStasis(line->tag); - break; - - default: - break; + case PLAT_PERPETUALRAISE: + p_activate_in_stasis(line->tag); + break; + + default: + break; } - - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - sec = §ors[secnum]; - - if (sec->specialdata) - continue; - - // Find lowest & highest floors around sector - rtn = 1; - plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); - P_AddThinker(&plat->thinker); - - plat->type = type; - plat->sector = sec; - plat->sector->specialdata = plat; - plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise; - plat->crush = false; - plat->tag = line->tag; - - switch(type) - { - case raiseToNearestAndChange: - plat->speed = PLATSPEED/2; - sec->floorpic = sides[line->sidenum[0]].sector->floorpic; - plat->high = P_FindNextHighestFloor(sec,sec->floorheight); - plat->wait = 0; - plat->status = up; - // NO MORE DAMAGE, IF APPLICABLE - sec->special = 0; - - S_StartSound(&sec->soundorg,sfx_stnmov); - break; - - case raiseAndChange: - plat->speed = PLATSPEED/2; - sec->floorpic = sides[line->sidenum[0]].sector->floorpic; - plat->high = sec->floorheight + amount*FRACUNIT; - plat->wait = 0; - plat->status = up; - - S_StartSound(&sec->soundorg,sfx_stnmov); - break; - - case downWaitUpStay: - plat->speed = PLATSPEED * 4; - plat->low = P_FindLowestFloorSurrounding(sec); - - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = sec->floorheight; - plat->wait = TICRATE*PLATWAIT; - plat->status = down; - S_StartSound(&sec->soundorg,sfx_pstart); - break; - - case blazeDWUS: - plat->speed = PLATSPEED * 8; - plat->low = P_FindLowestFloorSurrounding(sec); - - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = sec->floorheight; - plat->wait = TICRATE*PLATWAIT; - plat->status = down; - S_StartSound(&sec->soundorg,sfx_pstart); - break; - - case perpetualRaise: - plat->speed = PLATSPEED; - plat->low = P_FindLowestFloorSurrounding(sec); - - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = P_FindHighestFloorSurrounding(sec); - - if (plat->high < sec->floorheight) - plat->high = sec->floorheight; - - plat->wait = TICRATE*PLATWAIT; - plat->status = P_Random()&1; - - S_StartSound(&sec->soundorg,sfx_pstart); - break; - } - P_AddActivePlat(plat); - } - return rtn; -} + sec = §ors[secnum]; + + if (sec->specialdata) continue; + + /* Find lowest & highest floors around sector */ + + rtn = 1; + plat = z_malloc(sizeof(*plat), PU_LEVSPEC, 0); + p_add_thinker(&plat->thinker); + + plat->type = type; + plat->sector = sec; + plat->sector->specialdata = plat; + plat->thinker.function.acp1 = (actionf_p1)t_plat_raise; + plat->crush = false; + plat->tag = line->tag; + + switch (type) + { + case PLAT_RAISETONEARESTANDCHANGE: + plat->speed = PLATSPEED / 2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = p_find_next_highest_floor(sec, sec->floorheight); + plat->wait = 0; + plat->status = up; + + /* NO MORE DAMAGE, IF APPLICABLE */ + + sec->special = 0; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&sec->soundorg, SFX_STNMOV); +#endif + break; + + case PLAT_RAISEANDCHANGE: + plat->speed = PLATSPEED / 2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = sec->floorheight + amount * FRACUNIT; + plat->wait = 0; + plat->status = up; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&sec->soundorg, SFX_STNMOV); +#endif + break; + + case PLAT_DOWNWAITUPSTAY: + plat->speed = PLATSPEED * 4; + plat->low = p_find_lowest_floor_surrounding(sec); + + if (plat->low > sec->floorheight) plat->low = sec->floorheight; + plat->high = sec->floorheight; + plat->wait = TICRATE * PLATWAIT; + plat->status = down; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&sec->soundorg, SFX_PSTART); +#endif + break; + case PLAT_BLAZEDWUS: + plat->speed = PLATSPEED * 8; + plat->low = p_find_lowest_floor_surrounding(sec); -void P_ActivateInStasis(int tag) + if (plat->low > sec->floorheight) plat->low = sec->floorheight; + + plat->high = sec->floorheight; + plat->wait = TICRATE * PLATWAIT; + plat->status = down; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&sec->soundorg, SFX_PSTART); +#endif + break; + + case PLAT_PERPETUALRAISE: + plat->speed = PLATSPEED; + plat->low = p_find_lowest_floor_surrounding(sec); + + if (plat->low > sec->floorheight) plat->low = sec->floorheight; + + plat->high = p_find_highest_floor_surrounding(sec); + + if (plat->high < sec->floorheight) plat->high = sec->floorheight; + + plat->wait = TICRATE * PLATWAIT; + plat->status = p_random() & 1; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&sec->soundorg, SFX_PSTART); +#endif + break; + } + + p_add_active_plat(plat); + } + + return rtn; +} + +void p_activate_in_stasis(int tag) { - int i; - - for (i = 0;i < MAXPLATS;i++) - if (activeplats[i] - && (activeplats[i])->tag == tag - && (activeplats[i])->status == in_stasis) - { - (activeplats[i])->status = (activeplats[i])->oldstatus; - (activeplats[i])->thinker.function.acp1 - = (actionf_p1) T_PlatRaise; - } + int i; + + for (i = 0; i < MAXPLATS; i++) + { + if (activeplats[i] && (activeplats[i])->tag == tag && + (activeplats[i])->status == in_stasis) + { + (activeplats[i])->status = (activeplats[i])->oldstatus; + (activeplats[i])->thinker.function.acp1 = (actionf_p1)t_plat_raise; + } + } } -void EV_StopPlat(line_t* line) +void ev_stop_plat(line_t *line) { - int j; - - for (j = 0;j < MAXPLATS;j++) - if (activeplats[j] - && ((activeplats[j])->status != in_stasis) - && ((activeplats[j])->tag == line->tag)) - { - (activeplats[j])->oldstatus = (activeplats[j])->status; - (activeplats[j])->status = in_stasis; - (activeplats[j])->thinker.function.acv = (actionf_v)NULL; - } + int j; + + for (j = 0; j < MAXPLATS; j++) + { + if (activeplats[j] && ((activeplats[j])->status != in_stasis) && + ((activeplats[j])->tag == line->tag)) + { + (activeplats[j])->oldstatus = (activeplats[j])->status; + (activeplats[j])->status = in_stasis; + (activeplats[j])->thinker.function.acv = (actionf_v)NULL; + } + } } -void P_AddActivePlat(plat_t* plat) +void p_add_active_plat(plat_t *plat) { - int i; - - for (i = 0;i < MAXPLATS;i++) - if (activeplats[i] == NULL) - { - activeplats[i] = plat; - return; - } - I_Error ("P_AddActivePlat: no more plats!"); + int i; + + for (i = 0; i < MAXPLATS; i++) + { + if (activeplats[i] == NULL) + { + activeplats[i] = plat; + return; + } + } + + i_error("p_add_active_plat: no more plats!"); } -void P_RemoveActivePlat(plat_t* plat) +void p_remove_active_plat(plat_t *plat) { - int i; - for (i = 0;i < MAXPLATS;i++) - if (plat == activeplats[i]) - { - (activeplats[i])->sector->specialdata = NULL; - P_RemoveThinker(&(activeplats[i])->thinker); - activeplats[i] = NULL; - - return; - } - I_Error ("P_RemoveActivePlat: can't find plat!"); + int i; + for (i = 0; i < MAXPLATS; i++) + { + if (plat == activeplats[i]) + { + (activeplats[i])->sector->specialdata = NULL; + p_remove_thinker(&(activeplats[i])->thinker); + activeplats[i] = NULL; + + return; + } + } + + i_error("p_remove_active_plat: can't find plat!"); } diff --git a/games/NXDoom/src/doom/p_pspr.c b/games/NXDoom/src/doom/p_pspr.c index c8c1776ca04..9800b0e7cad 100644 --- a/games/NXDoom/src/doom/p_pspr.c +++ b/games/NXDoom/src/doom/p_pspr.c @@ -1,887 +1,786 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Weapon sprite animation, weapon objects. -// Action functions for weapons. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_pspr.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Weapon sprite animation, weapon objects. + * Action functions for weapons. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include "doomdef.h" #include "d_event.h" +#include "doomdef.h" #include "deh_misc.h" #include "m_random.h" #include "p_local.h" + +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* State. */ -// State. #include "doomstat.h" -// Data. -#include "sounds.h" +/* Data. */ #include "p_pspr.h" -#define LOWERSPEED FRACUNIT*6 -#define RAISESPEED FRACUNIT*6 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LOWERSPEED FRACUNIT * 6 +#define RAISESPEED FRACUNIT * 6 + +#define WEAPONBOTTOM 128 * FRACUNIT +#define WEAPONTOP 32 * FRACUNIT -#define WEAPONBOTTOM 128*FRACUNIT -#define WEAPONTOP 32*FRACUNIT +/**************************************************************************** + * Public Data + ****************************************************************************/ +fixed_t swingx; +fixed_t swingy; +fixed_t bulletslope; -// -// P_SetPsprite -// -void -P_SetPsprite -( player_t* player, - int position, - statenum_t stnum ) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void p_set_psprite(player_t *player, int position, statenum_t stnum) { - pspdef_t* psp; - state_t* state; - - psp = &player->psprites[position]; - - do + pspdef_t *psp; + state_t *state; + + psp = &player->psprites[position]; + + do { - if (!stnum) - { - // object removed itself - psp->state = NULL; - break; - } - - state = &states[stnum]; - psp->state = state; - psp->tics = state->tics; // could be 0 - - if (state->misc1) - { - // coordinate set - psp->sx = state->misc1 << FRACBITS; - psp->sy = state->misc2 << FRACBITS; - } - - // Call action routine. - // Modified handling. - if (state->action.acp2) - { - state->action.acp2(player, psp); - if (!psp->state) - break; - } - - stnum = psp->state->nextstate; - - } while (!psp->tics); - // an initial state of 0 could cycle through -} + if (!stnum) + { + /* object removed itself */ + + psp->state = NULL; + break; + } + + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; /* could be 0 */ + +#if 0 /* Unused as far as I can tell */ + if (state->misc1) + { + /* coordinate set */ + + psp->sx = state->misc1 << FRACBITS; + psp->sy = state->misc2 << FRACBITS; + } +#endif + /* Call action routine. + * Modified handling. + */ + if (state->action.acp2) + { + state->action.acp2(player, psp); + if (!psp->state) break; + } -// -// P_CalcSwing -// -fixed_t swingx; -fixed_t swingy; + stnum = psp->state->nextstate; + } + while (!psp->tics); + + /* an initial state of 0 could cycle through */ +} -void P_CalcSwing (player_t* player) +static void p_calc_swing(player_t *player) { - fixed_t swing; - int angle; - - // OPTIMIZE: tablify this. - // A LUT would allow for different modes, - // and add flexibility. + fixed_t swing; + int angle; - swing = player->bob; + /* OPTIMIZE: tablify this. + * A LUT would allow for different modes, and add flexibility. + */ - angle = (FINEANGLES/70*leveltime)&FINEMASK; - swingx = FixedMul ( swing, finesine[angle]); + swing = player->bob; - angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; - swingy = -FixedMul ( swingx, finesine[angle]); + angle = (FINEANGLES / 70 * leveltime) & FINEMASK; + swingx = fixed_mul(swing, finesine[angle]); + + angle = (FINEANGLES / 70 * leveltime + FINEANGLES / 2) & FINEMASK; + swingy = -fixed_mul(swingx, finesine[angle]); } +/* p_bringup_weapon + * Starts bringing the pending weapon up from the bottom of the screen. Uses + * player + */ +static void p_bringup_weapon(player_t *player) +{ + statenum_t newstate; -// -// P_BringUpWeapon -// Starts bringing the pending weapon up -// from the bottom of the screen. -// Uses player -// -void P_BringUpWeapon (player_t* player) + if (player->pendingweapon == wp_nochange) + player->pendingweapon = player->readyweapon; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (player->pendingweapon == wp_chainsaw) + s_start_sound(player->mo, SFX_SAWUP); +#endif + + newstate = weaponinfo[player->pendingweapon].upstate; + + player->pendingweapon = wp_nochange; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + + p_set_psprite(player, ps_weapon, newstate); +} + +/* Doom does not check the bounds of the ammo array. As a result, + * it is possible to use an ammo type > 4 that overflows into the + * maxammo array and affects that instead. Through dehacked, for + * example, it is possible to make a weapon that decreases the max + * number of ammo for another weapon. Emulate this. + */ + +static void decrease_ammo(player_t *player, int ammonum, int amount) { - statenum_t newstate; - - if (player->pendingweapon == wp_nochange) - player->pendingweapon = player->readyweapon; - - if (player->pendingweapon == wp_chainsaw) - S_StartSound (player->mo, sfx_sawup); - - newstate = weaponinfo[player->pendingweapon].upstate; - - player->pendingweapon = wp_nochange; - player->psprites[ps_weapon].sy = WEAPONBOTTOM; - - P_SetPsprite (player, ps_weapon, newstate); + if (ammonum < NUMAMMO) + { + player->ammo[ammonum] -= amount; + } + else + { + player->maxammo[ammonum - NUMAMMO] -= amount; + } } -// -// P_CheckAmmo -// Returns true if there is enough ammo to shoot. -// If not, selects the next weapon to use. -// -boolean P_CheckAmmo (player_t* player) +/* p_bullet_slope + * Sets a slope so a near miss is at approximately + * the height of the intended target + */ + +static void p_bullet_slope(mobj_t *mo) { - ammotype_t ammo; - int count; - - ammo = weaponinfo[player->readyweapon].ammo; - - // Minimal amount for one shot varies. - if (player->readyweapon == wp_bfg) - count = deh_bfg_cells_per_shot; - else if (player->readyweapon == wp_supershotgun) - count = 2; // Double barrel. - else - count = 1; // Regular. - - // Some do not need ammunition anyway. - // Return if current ammunition sufficient. - if (ammo == am_noammo || player->ammo[ammo] >= count) - return true; - - // Out of ammo, pick a weapon to change to. - // Preferences are set here. - do + angle_t an; + + /* see which target is to be aimed at */ + + an = mo->angle; + bulletslope = p_aim_line_attack(mo, an, 16 * 64 * FRACUNIT); + + if (!linetarget) { - if (player->weaponowned[wp_plasma] - && player->ammo[am_cell] - && (gamemode != shareware) ) - { - player->pendingweapon = wp_plasma; - } - else if (player->weaponowned[wp_supershotgun] - && player->ammo[am_shell]>2 - && (gamemode == commercial) ) - { - player->pendingweapon = wp_supershotgun; - } - else if (player->weaponowned[wp_chaingun] - && player->ammo[am_clip]) - { - player->pendingweapon = wp_chaingun; - } - else if (player->weaponowned[wp_shotgun] - && player->ammo[am_shell]) - { - player->pendingweapon = wp_shotgun; - } - else if (player->ammo[am_clip]) - { - player->pendingweapon = wp_pistol; - } - else if (player->weaponowned[wp_chainsaw]) - { - player->pendingweapon = wp_chainsaw; - } - else if (player->weaponowned[wp_missile] - && player->ammo[am_misl]) - { - player->pendingweapon = wp_missile; - } - else if (player->weaponowned[wp_bfg] - && player->ammo[am_cell]>40 - && (gamemode != shareware) ) - { - player->pendingweapon = wp_bfg; - } - else - { - // If everything fails. - player->pendingweapon = wp_fist; - } - - } while (player->pendingweapon == wp_nochange); - - // Now set appropriate weapon overlay. - P_SetPsprite (player, - ps_weapon, - weaponinfo[player->readyweapon].downstate); - - return false; + an += 1 << 26; + bulletslope = p_aim_line_attack(mo, an, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + bulletslope = p_aim_line_attack(mo, an, 16 * 64 * FRACUNIT); + } + } } +static void p_gunshot(mobj_t *mo, boolean accurate) +{ + angle_t angle; + int damage; -// -// P_FireWeapon. -// -void P_FireWeapon (player_t* player) + damage = 5 * (p_random() % 3 + 1); + angle = mo->angle; + + if (!accurate) angle += p_sub_random() << 18; + + p_line_attack(mo, angle, MISSILERANGE, bulletslope, damage); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* p_check_ammo + * Returns true if there is enough ammo to shoot. + * If not, selects the next weapon to use. + */ + +boolean p_check_ammo(player_t *player) { - statenum_t newstate; - - if (!P_CheckAmmo (player)) - return; - - P_SetMobjState (player->mo, S_PLAY_ATK1); - newstate = weaponinfo[player->readyweapon].atkstate; - P_SetPsprite (player, ps_weapon, newstate); - P_NoiseAlert (player->mo, player->mo); + ammotype_t ammo; + int count; + + ammo = weaponinfo[player->readyweapon].ammo; + + /* Minimal amount for one shot varies. */ + + if (player->readyweapon == wp_bfg) + count = deh_bfg_cells_per_shot; + else if (player->readyweapon == wp_supershotgun) + count = 2; /* Double barrel. */ + else + count = 1; /* Regular. */ + + /* Some do not need ammunition anyway. + * Return if current ammunition sufficient. + */ + + if (ammo == am_noammo || player->ammo[ammo] >= count) return true; + + /* Out of ammo, pick a weapon to change to. + * Preferences are set here. + */ + + do + { + if (player->weaponowned[wp_plasma] && player->ammo[am_cell] && + (gamemode != shareware)) + { + player->pendingweapon = wp_plasma; + } + else if (player->weaponowned[wp_supershotgun] && + player->ammo[am_shell] > 2 && (gamemode == commercial)) + { + player->pendingweapon = wp_supershotgun; + } + else if (player->weaponowned[wp_chaingun] && player->ammo[am_clip]) + { + player->pendingweapon = wp_chaingun; + } + else if (player->weaponowned[wp_shotgun] && player->ammo[am_shell]) + { + player->pendingweapon = wp_shotgun; + } + else if (player->ammo[am_clip]) + { + player->pendingweapon = wp_pistol; + } + else if (player->weaponowned[wp_chainsaw]) + { + player->pendingweapon = wp_chainsaw; + } + else if (player->weaponowned[wp_missile] && player->ammo[am_misl]) + { + player->pendingweapon = wp_missile; + } + else if (player->weaponowned[wp_bfg] && player->ammo[am_cell] > 40 && + (gamemode != shareware)) + { + player->pendingweapon = wp_bfg; + } + else + { + /* If everything fails. */ + + player->pendingweapon = wp_fist; + } + } + while (player->pendingweapon == wp_nochange); + + /* Now set appropriate weapon overlay. */ + + p_set_psprite(player, ps_weapon, + weaponinfo[player->readyweapon].downstate); + return false; } +static void p_fire_weapon(player_t *player) +{ + statenum_t newstate; + + if (!p_check_ammo(player)) return; + p_set_mobj_state(player->mo, S_PLAY_ATK1); + newstate = weaponinfo[player->readyweapon].atkstate; + p_set_psprite(player, ps_weapon, newstate); + p_noise_alert(player->mo, player->mo); +} + +/* p_drop_weapon + * Player died, so put the weapon away. + */ -// -// P_DropWeapon -// Player died, so put the weapon away. -// -void P_DropWeapon (player_t* player) +void p_drop_weapon(player_t *player) { - P_SetPsprite (player, - ps_weapon, - weaponinfo[player->readyweapon].downstate); + p_set_psprite(player, ps_weapon, + weaponinfo[player->readyweapon].downstate); } +/* a_weapon_ready + * The player can fire the weapon or change to another weapon at this time. + * Follows after getting weapon up, or after previous attack/fire sequence. + */ +void a_weapon_ready(player_t *player, pspdef_t *psp) +{ + statenum_t newstate; + int angle; -// -// A_WeaponReady -// The player can fire the weapon -// or change to another weapon at this time. -// Follows after getting weapon up, -// or after previous attack/fire sequence. -// -void -A_WeaponReady -( player_t* player, - pspdef_t* psp ) -{ - statenum_t newstate; - int angle; - - // get out of attack state - if (player->mo->state == &states[S_PLAY_ATK1] - || player->mo->state == &states[S_PLAY_ATK2] ) + /* get out of attack state */ + + if (player->mo->state == &states[S_PLAY_ATK1] || + player->mo->state == &states[S_PLAY_ATK2]) { - P_SetMobjState (player->mo, S_PLAY); + p_set_mobj_state(player->mo, S_PLAY); } - - if (player->readyweapon == wp_chainsaw - && psp->state == &states[S_SAW]) + + if (player->readyweapon == wp_chainsaw && psp->state == &states[S_SAW]) { - S_StartSound (player->mo, sfx_sawidl); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_SAWIDL); +#endif } - - // check for change - // if player is dead, put the weapon away - if (player->pendingweapon != wp_nochange || !player->health) + + /* check for change if player is dead, put the weapon away */ + + if (player->pendingweapon != wp_nochange || !player->health) { - // change weapon - // (pending weapon should allready be validated) - newstate = weaponinfo[player->readyweapon].downstate; - P_SetPsprite (player, ps_weapon, newstate); - return; + /* change weapon (pending weapon should already be validated) */ + + newstate = weaponinfo[player->readyweapon].downstate; + p_set_psprite(player, ps_weapon, newstate); + return; } - - // check for fire - // the missile launcher and bfg do not auto fire - if (player->cmd.buttons & BT_ATTACK) + + /* check for fire the missile launcher and bfg do not auto fire */ + + if (player->cmd.buttons & BT_ATTACK) { - if ( !player->attackdown - || (player->readyweapon != wp_missile - && player->readyweapon != wp_bfg) ) - { - player->attackdown = true; - P_FireWeapon (player); - return; - } + if (!player->attackdown || (player->readyweapon != wp_missile && + player->readyweapon != wp_bfg)) + { + player->attackdown = true; + p_fire_weapon(player); + return; + } } - else - player->attackdown = false; - - // bob the weapon based on movement speed - angle = (128*leveltime)&FINEMASK; - psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); - angle &= FINEANGLES/2-1; - psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); -} + else + player->attackdown = false; + /* bob the weapon based on movement speed */ + angle = (128 * leveltime) & FINEMASK; + psp->sx = FRACUNIT + fixed_mul(player->bob, finecosine[angle]); + angle &= FINEANGLES / 2 - 1; + psp->sy = WEAPONTOP + fixed_mul(player->bob, finesine[angle]); +} -// -// A_ReFire -// The player can re-fire the weapon -// without lowering it entirely. -// -void A_ReFire -( player_t* player, - pspdef_t* psp ) +/* a_refire + * The player can re-fire the weapon without lowering it entirely. + */ + +void a_refire(player_t *player, pspdef_t *psp) { - - // check for fire - // (if a weaponchange is pending, let it go through instead) - if ( (player->cmd.buttons & BT_ATTACK) - && player->pendingweapon == wp_nochange - && player->health) + /* check for fire (if a weaponchange is pending, let it go through instead) + */ + + if ((player->cmd.buttons & BT_ATTACK) && + player->pendingweapon == wp_nochange && player->health) { - player->refire++; - P_FireWeapon (player); + player->refire++; + p_fire_weapon(player); } - else + else { - player->refire = 0; - P_CheckAmmo (player); + player->refire = 0; + p_check_ammo(player); } } - -void -A_CheckReload -( player_t* player, - pspdef_t* psp ) +void a_check_reload(player_t *player, pspdef_t *psp) { - P_CheckAmmo (player); + p_check_ammo(player); #if 0 - if (player->ammo[am_shell]<2) - P_SetPsprite (player, ps_weapon, S_DSNR1); + if (player->ammo[am_shell] < 2) + { + p_set_psprite(player, ps_weapon, S_DSNR1); + } #endif } +/* a_lower + * Lowers current weapon, and changes weapon at bottom. + */ +void a_lower(player_t *player, pspdef_t *psp) +{ + psp->sy += LOWERSPEED; -// -// A_Lower -// Lowers current weapon, -// and changes weapon at bottom. -// -void -A_Lower -( player_t* player, - pspdef_t* psp ) -{ - psp->sy += LOWERSPEED; + /* Is already down. */ - // Is already down. - if (psp->sy < WEAPONBOTTOM ) - return; + if (psp->sy < WEAPONBOTTOM) return; - // Player is dead. - if (player->playerstate == PST_DEAD) + /* Player is dead. */ + + if (player->playerstate == PST_DEAD) { - psp->sy = WEAPONBOTTOM; + psp->sy = WEAPONBOTTOM; + + /* don't bring weapon back up */ - // don't bring weapon back up - return; + return; } - - // The old weapon has been lowered off the screen, - // so change the weapon and start raising it - if (!player->health) + + /* The old weapon has been lowered off the screen, so change the weapon and + * start raising it + */ + + if (!player->health) { - // Player is dead, so keep the weapon off screen. - P_SetPsprite (player, ps_weapon, S_NULL); - return; + /* Player is dead, so keep the weapon off screen. */ + + p_set_psprite(player, ps_weapon, S_NULL); + return; } - - player->readyweapon = player->pendingweapon; - P_BringUpWeapon (player); -} + player->readyweapon = player->pendingweapon; + p_bringup_weapon(player); +} -// -// A_Raise -// -void -A_Raise -( player_t* player, - pspdef_t* psp ) +void a_raise(player_t *player, pspdef_t *psp) { - statenum_t newstate; - - psp->sy -= RAISESPEED; - - if (psp->sy > WEAPONTOP ) - return; - - psp->sy = WEAPONTOP; - - // The weapon has been raised all the way, - // so change to the ready state. - newstate = weaponinfo[player->readyweapon].readystate; - - P_SetPsprite (player, ps_weapon, newstate); -} + statenum_t newstate; + + psp->sy -= RAISESPEED; + + if (psp->sy > WEAPONTOP) return; + psp->sy = WEAPONTOP; + /* The weapon has been raised all the way, so change to the ready state. */ -// -// A_GunFlash -// -void -A_GunFlash -( player_t* player, - pspdef_t* psp ) + newstate = weaponinfo[player->readyweapon].readystate; + + p_set_psprite(player, ps_weapon, newstate); +} + +void a_gun_flash(player_t *player, pspdef_t *psp) { - P_SetMobjState (player->mo, S_PLAY_ATK2); - P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); + p_set_mobj_state(player->mo, S_PLAY_ATK2); + p_set_psprite(player, ps_flash, + weaponinfo[player->readyweapon].flashstate); } +/* WEAPON ATTACKS */ +void a_punch(player_t *player, pspdef_t *psp) +{ + angle_t angle; + int damage; + int slope; -// -// WEAPON ATTACKS -// + damage = (p_random() % 10 + 1) << 1; + if (player->powers[pw_strength]) damage *= 10; -// -// A_Punch -// -void -A_Punch -( player_t* player, - pspdef_t* psp ) -{ - angle_t angle; - int damage; - int slope; - - damage = (P_Random ()%10+1)<<1; - - if (player->powers[pw_strength]) - damage *= 10; - - angle = player->mo->angle; - angle += P_SubRandom() << 18; - slope = P_AimLineAttack (player->mo, angle, MELEERANGE); - P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); - - // turn to face target - if (linetarget) + angle = player->mo->angle; + angle += p_sub_random() << 18; + slope = p_aim_line_attack(player->mo, angle, MELEERANGE); + p_line_attack(player->mo, angle, MELEERANGE, slope, damage); + + /* turn to face target */ + + if (linetarget) { - S_StartSound (player->mo, sfx_punch); - player->mo->angle = R_PointToAngle2 (player->mo->x, - player->mo->y, - linetarget->x, - linetarget->y); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_PUNCH); +#endif + player->mo->angle = r_point_to_angle2(player->mo->x, player->mo->y, + linetarget->x, linetarget->y); } } - -// -// A_Saw -// -void -A_Saw -( player_t* player, - pspdef_t* psp ) +void a_saw(player_t *player, pspdef_t *psp) { - angle_t angle; - int damage; - int slope; - - damage = 2*(P_Random ()%10+1); - angle = player->mo->angle; - angle += P_SubRandom() << 18; - - // use meleerange + 1 se the puff doesn't skip the flash - slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1); - P_LineAttack (player->mo, angle, MELEERANGE+1, slope, damage); - - if (!linetarget) - { - S_StartSound (player->mo, sfx_sawful); - return; - } - S_StartSound (player->mo, sfx_sawhit); - - // turn to face target - angle = R_PointToAngle2 (player->mo->x, player->mo->y, - linetarget->x, linetarget->y); - if (angle - player->mo->angle > ANG180) - { - if ((signed int) (angle - player->mo->angle) < -ANG90/20) - player->mo->angle = angle + ANG90/21; - else - player->mo->angle -= ANG90/20; - } - else + angle_t angle; + int damage; + int slope; + + damage = 2 * (p_random() % 10 + 1); + angle = player->mo->angle; + angle += p_sub_random() << 18; + + /* use meleerange + 1 se the puff doesn't skip the flash */ + + slope = p_aim_line_attack(player->mo, angle, MELEERANGE + 1); + p_line_attack(player->mo, angle, MELEERANGE + 1, slope, damage); + + if (!linetarget) { - if (angle - player->mo->angle > ANG90/20) - player->mo->angle = angle - ANG90/21; - else - player->mo->angle += ANG90/20; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_SAWFUL); +#endif + return; } - player->mo->flags |= MF_JUSTATTACKED; -} -// Doom does not check the bounds of the ammo array. As a result, -// it is possible to use an ammo type > 4 that overflows into the -// maxammo array and affects that instead. Through dehacked, for -// example, it is possible to make a weapon that decreases the max -// number of ammo for another weapon. Emulate this. +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_SAWHIT); +#endif -static void DecreaseAmmo(player_t *player, int ammonum, int amount) -{ - if (ammonum < NUMAMMO) + /* turn to face target */ + + angle = r_point_to_angle2(player->mo->x, player->mo->y, linetarget->x, + linetarget->y); + if (angle - player->mo->angle > ANG180) { - player->ammo[ammonum] -= amount; + if ((signed int)(angle - player->mo->angle) < -ANG90 / 20) + player->mo->angle = angle + ANG90 / 21; + else + player->mo->angle -= ANG90 / 20; } - else + else { - player->maxammo[ammonum - NUMAMMO] -= amount; + if (angle - player->mo->angle > ANG90 / 20) + player->mo->angle = angle - ANG90 / 21; + else + player->mo->angle += ANG90 / 20; } -} + player->mo->flags |= MF_JUSTATTACKED; +} -// -// A_FireMissile -// -void -A_FireMissile -( player_t* player, - pspdef_t* psp ) +void a_fire_missile(player_t *player, pspdef_t *psp) { - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); - P_SpawnPlayerMissile (player->mo, MT_ROCKET); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, 1); + p_spawn_player_missile(player->mo, MT_ROCKET); } - -// -// A_FireBFG -// -void -A_FireBFG -( player_t* player, - pspdef_t* psp ) +void a_fire_bfg(player_t *player, pspdef_t *psp) { - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, - deh_bfg_cells_per_shot); - P_SpawnPlayerMissile (player->mo, MT_BFG); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, + deh_bfg_cells_per_shot); + p_spawn_player_missile(player->mo, MT_BFG); } - - -// -// A_FirePlasma -// -void -A_FirePlasma -( player_t* player, - pspdef_t* psp ) +void a_fire_plasma(player_t *player, pspdef_t *psp) { - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, 1); - P_SetPsprite (player, - ps_flash, - weaponinfo[player->readyweapon].flashstate+(P_Random ()&1) ); + p_set_psprite(player, ps_flash, + weaponinfo[player->readyweapon].flashstate + + (p_random() & 1)); - P_SpawnPlayerMissile (player->mo, MT_PLASMA); + p_spawn_player_missile(player->mo, MT_PLASMA); } +void a_fire_pistol(player_t *player, pspdef_t *psp) +{ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_PISTOL); +#endif + p_set_mobj_state(player->mo, S_PLAY_ATK2); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, 1); -// -// P_BulletSlope -// Sets a slope so a near miss is at aproximately -// the height of the intended target -// -fixed_t bulletslope; + p_set_psprite(player, ps_flash, + weaponinfo[player->readyweapon].flashstate); + p_bullet_slope(player->mo); + p_gunshot(player->mo, !player->refire); +} -void P_BulletSlope (mobj_t* mo) +void a_fire_shotgun(player_t *player, pspdef_t *psp) { - angle_t an; - - // see which target is to be aimed at - an = mo->angle; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); + int i; - if (!linetarget) - { - an += 1<<26; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - if (!linetarget) - { - an -= 2<<26; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - } - } -} +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_SHOTGN); +#endif + p_set_mobj_state(player->mo, S_PLAY_ATK2); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, 1); -// -// P_GunShot -// -void -P_GunShot -( mobj_t* mo, - boolean accurate ) -{ - angle_t angle; - int damage; - - damage = 5*(P_Random ()%3+1); - angle = mo->angle; + p_set_psprite(player, ps_flash, + weaponinfo[player->readyweapon].flashstate); - if (!accurate) - angle += P_SubRandom() << 18; + p_bullet_slope(player->mo); - P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage); + for (i = 0; i < 7; i++) + p_gunshot(player->mo, false); } - -// -// A_FirePistol -// -void -A_FirePistol -( player_t* player, - pspdef_t* psp ) +void a_fire_shotgun2(player_t *player, pspdef_t *psp) { - S_StartSound (player->mo, sfx_pistol); + int i; + angle_t angle; + int damage; - P_SetMobjState (player->mo, S_PLAY_ATK2); - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_DSHTGN); +#endif + p_set_mobj_state(player->mo, S_PLAY_ATK2); - P_SetPsprite (player, - ps_flash, - weaponinfo[player->readyweapon].flashstate); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, 2); - P_BulletSlope (player->mo); - P_GunShot (player->mo, !player->refire); -} + p_set_psprite(player, ps_flash, + weaponinfo[player->readyweapon].flashstate); + p_bullet_slope(player->mo); -// -// A_FireShotgun -// -void -A_FireShotgun -( player_t* player, - pspdef_t* psp ) -{ - int i; - - S_StartSound (player->mo, sfx_shotgn); - P_SetMobjState (player->mo, S_PLAY_ATK2); + for (i = 0; i < 20; i++) + { + damage = 5 * (p_random() % 3 + 1); + angle = player->mo->angle; + angle += p_sub_random() << ANGLETOFINESHIFT; + p_line_attack(player->mo, angle, MISSILERANGE, + bulletslope + (p_sub_random() << 5), damage); + } +} - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); +void a_fire_cgun(player_t *player, pspdef_t *psp) +{ +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_PISTOL); +#endif - P_SetPsprite (player, - ps_flash, - weaponinfo[player->readyweapon].flashstate); + if (!player->ammo[weaponinfo[player->readyweapon].ammo]) return; - P_BulletSlope (player->mo); - - for (i=0 ; i<7 ; i++) - P_GunShot (player->mo, false); -} + p_set_mobj_state(player->mo, S_PLAY_ATK2); + decrease_ammo(player, weaponinfo[player->readyweapon].ammo, 1); + p_set_psprite(player, ps_flash, + weaponinfo[player->readyweapon].flashstate + psp->state - + &states[S_CHAIN1]); + p_bullet_slope(player->mo); -// -// A_FireShotgun2 -// -void -A_FireShotgun2 -( player_t* player, - pspdef_t* psp ) -{ - int i; - angle_t angle; - int damage; - - - S_StartSound (player->mo, sfx_dshtgn); - P_SetMobjState (player->mo, S_PLAY_ATK2); - - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 2); - - P_SetPsprite (player, - ps_flash, - weaponinfo[player->readyweapon].flashstate); - - P_BulletSlope (player->mo); - - for (i=0 ; i<20 ; i++) - { - damage = 5*(P_Random ()%3+1); - angle = player->mo->angle; - angle += P_SubRandom() << ANGLETOFINESHIFT; - P_LineAttack (player->mo, - angle, - MISSILERANGE, - bulletslope + (P_SubRandom() << 5), damage); - } + p_gunshot(player->mo, !player->refire); } +/* ? */ -// -// A_FireCGun -// -void -A_FireCGun -( player_t* player, - pspdef_t* psp ) +void a_light0(player_t *player, pspdef_t *psp) { - S_StartSound (player->mo, sfx_pistol); - - if (!player->ammo[weaponinfo[player->readyweapon].ammo]) - return; - - P_SetMobjState (player->mo, S_PLAY_ATK2); - DecreaseAmmo(player, weaponinfo[player->readyweapon].ammo, 1); - - P_SetPsprite (player, - ps_flash, - weaponinfo[player->readyweapon].flashstate - + psp->state - - &states[S_CHAIN1] ); - - P_BulletSlope (player->mo); - - P_GunShot (player->mo, !player->refire); + player->extralight = 0; } - - -// -// ? -// -void A_Light0 (player_t *player, pspdef_t *psp) +void a_light1(player_t *player, pspdef_t *psp) { - player->extralight = 0; + player->extralight = 1; } -void A_Light1 (player_t *player, pspdef_t *psp) +void a_light2(player_t *player, pspdef_t *psp) { - player->extralight = 1; + player->extralight = 2; } -void A_Light2 (player_t *player, pspdef_t *psp) +/* a_bfg_spray + * Spawn a BFG explosion on every monster in view + */ + +void a_bfg_spray(mobj_t *mo) { - player->extralight = 2; -} + int i; + int j; + int damage; + angle_t an; + /* offset angles from its attack angle */ -// -// A_BFGSpray -// Spawn a BFG explosion on every monster in view -// -void A_BFGSpray (mobj_t* mo) -{ - int i; - int j; - int damage; - angle_t an; - - // offset angles from its attack angle - for (i=0 ; i<40 ; i++) + for (i = 0; i < 40; i++) { - an = mo->angle - ANG90/2 + ANG90/40*i; + an = mo->angle - ANG90 / 2 + ANG90 / 40 * i; + + /* mo->target is the originator (player) of the missile */ + + p_aim_line_attack(mo->target, an, 16 * 64 * FRACUNIT); - // mo->target is the originator (player) - // of the missile - P_AimLineAttack (mo->target, an, 16*64*FRACUNIT); + if (!linetarget) continue; - if (!linetarget) - continue; + p_spawn_mobj(linetarget->x, linetarget->y, + linetarget->z + (linetarget->height >> 2), MT_EXTRABFG); - P_SpawnMobj (linetarget->x, - linetarget->y, - linetarget->z + (linetarget->height>>2), - MT_EXTRABFG); - - damage = 0; - for (j=0;j<15;j++) - damage += (P_Random()&7) + 1; + damage = 0; + for (j = 0; j < 15; j++) + damage += (p_random() & 7) + 1; - P_DamageMobj (linetarget, mo->target,mo->target, damage); + p_damage_mobj(linetarget, mo->target, mo->target, damage); } } +/* a_bfg_sound */ -// -// A_BFGsound -// -void -A_BFGsound -( player_t* player, - pspdef_t* psp ) +void a_bfg_sound(player_t *player, pspdef_t *psp) { - S_StartSound (player->mo, sfx_bfg); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(player->mo, SFX_BFG); +#endif } +/* p_setup_psprites + * Called at start of level for each player. + */ - -// -// P_SetupPsprites -// Called at start of level for each player. -// -void P_SetupPsprites (player_t* player) +void p_setup_psprites(player_t *player) { - int i; - - // remove all psprites - for (i=0 ; ipsprites[i].state = NULL; - - // spawn the gun - player->pendingweapon = player->readyweapon; - P_BringUpWeapon (player); -} + int i; + + /* remove all psprites */ + for (i = 0; i < NUMPSPRITES; i++) + player->psprites[i].state = NULL; + /* spawn the gun */ + + player->pendingweapon = player->readyweapon; + p_bringup_weapon(player); +} +/* p_move_psprites + * Called every tic by player thinking routine. + */ -// -// P_MovePsprites -// Called every tic by player thinking routine. -// -void P_MovePsprites (player_t* player) +void p_move_psprites(player_t *player) { - int i; - pspdef_t* psp; - - psp = &player->psprites[0]; - for (i=0 ; ipsprites[0]; + for (i = 0; i < NUMPSPRITES; i++, psp++) { - // a null state means not active - if (psp->state) - { - // drop tic count and possibly change state - - // a -1 tic count never changes - if (psp->tics != -1) - { - psp->tics--; - if (!psp->tics) - P_SetPsprite (player, i, psp->state->nextstate); - } - } + /* a null state means not active */ + + if (psp->state) + { + /* drop tic count and possibly change state */ + + /* a -1 tic count never changes */ + + if (psp->tics != -1) + { + psp->tics--; + if (!psp->tics) + { + p_set_psprite(player, i, psp->state->nextstate); + } + } + } } - - player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; - player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; -} - + player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; + player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; +} diff --git a/games/NXDoom/src/doom/p_pspr.h b/games/NXDoom/src/doom/p_pspr.h index 2616bd4760d..83ab57f6a01 100644 --- a/games/NXDoom/src/doom/p_pspr.h +++ b/games/NXDoom/src/doom/p_pspr.h @@ -1,75 +1,88 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Sprite animation. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_pspr.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Sprite animation. + * + ****************************************************************************/ #ifndef __P_PSPR__ #define __P_PSPR__ -// Basic data types. -// Needs fixed point, and BAM angles. +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Basic data types. + * Needs fixed point, and BAM angles. + */ + #include "m_fixed.h" #include "tables.h" +/* Needs to include the precompiled sprite animation tables. + * + * Header generated by multigen utility. + * + * This includes all the data for thing animation, + * i.e. the Thing Attributes table and the Frame Sequence table. + */ -// -// Needs to include the precompiled -// sprite animation tables. -// Header generated by multigen utility. -// This includes all the data for thing animation, -// i.e. the Thing Atrributes table -// and the Frame Sequence table. #include "info.h" +/* Frame flags: + * handles maximum brightness (torches, muzzle flare, light sources) + */ +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// -// Frame flags: -// handles maximum brightness (torches, muzzle flare, light sources) -// -#define FF_FULLBRIGHT 0x8000 // flag in thing->frame -#define FF_FRAMEMASK 0x7fff +#define FF_FULLBRIGHT 0x8000 /* flag in thing->frame */ +#define FF_FRAMEMASK 0x7fff +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* Overlay psprites are scaled shapes drawn directly on the view screen, + * coordinates are given for a 320*200 view screen. + */ -// -// Overlay psprites are scaled shapes -// drawn directly on the view screen, -// coordinates are given for a 320*200 view screen. -// typedef enum { - ps_weapon, - ps_flash, - NUMPSPRITES - + ps_weapon, + ps_flash, + NUMPSPRITES } psprnum_t; typedef struct { - state_t* state; // a NULL state means not active - int tics; - fixed_t sx; - fixed_t sy; - + state_t *state; /* a NULL state means not active */ + int tics; + fixed_t sx; + fixed_t sy; } pspdef_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ extern fixed_t bulletslope; - -#endif +#endif /* __P_PSPR__ */ diff --git a/games/NXDoom/src/doom/p_saveg.c b/games/NXDoom/src/doom/p_saveg.c index 1192bff90bb..5c5439cb97b 100644 --- a/games/NXDoom/src/doom/p_saveg.c +++ b/games/NXDoom/src/doom/p_saveg.c @@ -1,1888 +1,2129 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Archiving: SaveGame I/O. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_saveg.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Archiving: SaveGame I/O. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include -#include "dstrings.h" #include "deh_main.h" +#include "dstrings.h" #include "i_system.h" -#include "z_zone.h" #include "p_local.h" #include "p_saveg.h" +#include "z_zone.h" + +/* State. */ -// State. #include "doomstat.h" #include "g_game.h" #include "m_misc.h" #include "r_state.h" -FILE *save_stream; -int savegamelength; -boolean savegame_error; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Get the filename of a temporary file to write the savegame to. After -// the file has been successfully saved, it will be renamed to the -// real file. +/* Enum values are 32-bit integers. */ -char *P_TempSaveGameFile(void) -{ - static char *filename = NULL; +#define saveg_read_enum saveg_read32 +#define saveg_write_enum saveg_write32 - if (filename == NULL) - { - filename = M_StringJoin(savegamedir, "temp.dsg", NULL); - } +/* think_t + * This is just an actionf_t. + */ - return filename; -} +#define saveg_read_think_t saveg_read_actionf_t +#define saveg_write_think_t saveg_write_actionf_t -// Get the filename of the save game file to use for the specified slot. +/**************************************************************************** + * Private Types + ****************************************************************************/ -char *P_SaveGameFile(int slot) +enum { - static char *filename = NULL; - static size_t filename_size = 0; - char basename[32]; + tc_ceiling, + tc_door, + tc_floor, + tc_plat, + tc_flash, + tc_strobe, + tc_glow, + tc_endspecials +} specials_e; + +/* Thinkers */ - if (filename == NULL) - { - filename_size = strlen(savegamedir) + 32; - filename = malloc(filename_size); - } +typedef enum +{ + tc_end, + tc_mobj +} thinkerclass_t; - DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot); - M_snprintf(filename, filename_size, "%s%s", savegamedir, basename); +/**************************************************************************** + * Public Data + ****************************************************************************/ - return filename; -} +FILE *save_stream; +int savegamelength; +boolean savegame_error; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// Endian-safe integer read/write functions +/* Endian-safe integer read/write functions */ static byte saveg_read8(void) { - byte result = -1; + byte result = -1; - if (fread(&result, 1, 1, save_stream) < 1) + if (fread(&result, 1, 1, save_stream) < 1) { - if (!savegame_error) + if (!savegame_error) { - fprintf(stderr, "saveg_read8: Unexpected end of file while " - "reading save game\n"); + fprintf(stderr, "saveg_read8: Unexpected end of file while " + "reading save game\n"); - savegame_error = true; + savegame_error = true; } } - return result; + return result; } static void saveg_write8(byte value) { - if (fwrite(&value, 1, 1, save_stream) < 1) + if (fwrite(&value, 1, 1, save_stream) < 1) { - if (!savegame_error) + if (!savegame_error) { - fprintf(stderr, "saveg_write8: Error while writing save game\n"); + fprintf(stderr, "saveg_write8: Error while writing save game\n"); - savegame_error = true; + savegame_error = true; } } } static short saveg_read16(void) { - int result; + int result; - result = saveg_read8(); - result |= saveg_read8() << 8; + result = saveg_read8(); + result |= saveg_read8() << 8; - return result; + return result; } static void saveg_write16(short value) { - saveg_write8(value & 0xff); - saveg_write8((value >> 8) & 0xff); + saveg_write8(value & 0xff); + saveg_write8((value >> 8) & 0xff); } static int saveg_read32(void) { - int result; + int result; - result = saveg_read8(); - result |= saveg_read8() << 8; - result |= saveg_read8() << 16; - result |= saveg_read8() << 24; + result = saveg_read8(); + result |= saveg_read8() << 8; + result |= saveg_read8() << 16; + result |= saveg_read8() << 24; - return result; + return result; } static void saveg_write32(int value) { - saveg_write8(value & 0xff); - saveg_write8((value >> 8) & 0xff); - saveg_write8((value >> 16) & 0xff); - saveg_write8((value >> 24) & 0xff); + saveg_write8(value & 0xff); + saveg_write8((value >> 8) & 0xff); + saveg_write8((value >> 16) & 0xff); + saveg_write8((value >> 24) & 0xff); } -// Pad to 4-byte boundaries +/* Pad to 4-byte boundaries */ static void saveg_read_pad(void) { - unsigned long pos; - int padding; - int i; + unsigned long pos; + int padding; + int i; - pos = ftell(save_stream); + pos = ftell(save_stream); - padding = (4 - (pos & 3)) & 3; + padding = (4 - (pos & 3)) & 3; - for (i=0; ix = saveg_read16(); + /* short x; */ + + str->x = saveg_read16(); + + /* short y; */ - // short y; - str->y = saveg_read16(); + str->y = saveg_read16(); - // short angle; - str->angle = saveg_read16(); + /* short angle; */ - // short type; - str->type = saveg_read16(); + str->angle = saveg_read16(); - // short options; - str->options = saveg_read16(); + /* short type; */ + + str->type = saveg_read16(); + + /* short options; */ + + str->options = saveg_read16(); } static void saveg_write_mapthing_t(mapthing_t *str) { - // short x; - saveg_write16(str->x); + /* short x; */ + + saveg_write16(str->x); + + /* short y; */ + + saveg_write16(str->y); + + /* short angle; */ - // short y; - saveg_write16(str->y); + saveg_write16(str->angle); - // short angle; - saveg_write16(str->angle); + /* short type; */ - // short type; - saveg_write16(str->type); + saveg_write16(str->type); - // short options; - saveg_write16(str->options); + /* short options; */ + + saveg_write16(str->options); } -// -// actionf_t -// +/* actionf_t */ static void saveg_read_actionf_t(actionf_t *str) { - // actionf_p1 acp1; - str->acp1 = saveg_readp(); + /* actionf_p1 acp1; */ + + str->acp1 = saveg_readp(); } static void saveg_write_actionf_t(actionf_t *str) { - // actionf_p1 acp1; - saveg_writep(str->acp1); -} - -// -// think_t -// -// This is just an actionf_t. -// + /* actionf_p1 acp1; */ -#define saveg_read_think_t saveg_read_actionf_t -#define saveg_write_think_t saveg_write_actionf_t + saveg_writep(str->acp1); +} -// -// thinker_t -// +/* thinker_t */ static void saveg_read_thinker_t(thinker_t *str) { - // struct thinker_s* prev; - str->prev = saveg_readp(); + /* struct thinker_s* prev; */ - // struct thinker_s* next; - str->next = saveg_readp(); + str->prev = saveg_readp(); - // think_t function; - saveg_read_think_t(&str->function); + /* struct thinker_s* next; */ + + str->next = saveg_readp(); + + /* think_t function; */ + + saveg_read_think_t(&str->function); } static void saveg_write_thinker_t(thinker_t *str) { - // struct thinker_s* prev; - saveg_writep(str->prev); + /* struct thinker_s* prev; */ + + saveg_writep(str->prev); + + /* struct thinker_s* next; */ + + saveg_writep(str->next); - // struct thinker_s* next; - saveg_writep(str->next); + /* think_t function; */ - // think_t function; - saveg_write_think_t(&str->function); + saveg_write_think_t(&str->function); } -// -// mobj_t -// +/* mobj_t */ static void saveg_read_mobj_t(mobj_t *str) { - int pl; + int pl; - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + /* thinker_t thinker; */ - // fixed_t x; - str->x = saveg_read32(); + saveg_read_thinker_t(&str->thinker); - // fixed_t y; - str->y = saveg_read32(); + /* fixed_t x; */ - // fixed_t z; - str->z = saveg_read32(); + str->x = saveg_read32(); - // struct mobj_s* snext; - str->snext = saveg_readp(); + /* fixed_t y; */ - // struct mobj_s* sprev; - str->sprev = saveg_readp(); + str->y = saveg_read32(); - // angle_t angle; - str->angle = saveg_read32(); + /* fixed_t z; */ - // spritenum_t sprite; - str->sprite = saveg_read_enum(); + str->z = saveg_read32(); - // int frame; - str->frame = saveg_read32(); + /* struct mobj_s* snext; */ - // struct mobj_s* bnext; - str->bnext = saveg_readp(); + str->snext = saveg_readp(); - // struct mobj_s* bprev; - str->bprev = saveg_readp(); + /* struct mobj_s* sprev; */ - // struct subsector_s* subsector; - str->subsector = saveg_readp(); + str->sprev = saveg_readp(); - // fixed_t floorz; - str->floorz = saveg_read32(); + /* angle_t angle; */ - // fixed_t ceilingz; - str->ceilingz = saveg_read32(); + str->angle = saveg_read32(); - // fixed_t radius; - str->radius = saveg_read32(); + /* spritenum_t sprite; */ - // fixed_t height; - str->height = saveg_read32(); + str->sprite = saveg_read_enum(); - // fixed_t momx; - str->momx = saveg_read32(); + /* int frame; */ - // fixed_t momy; - str->momy = saveg_read32(); + str->frame = saveg_read32(); - // fixed_t momz; - str->momz = saveg_read32(); + /* struct mobj_s* bnext; */ - // int validcount; - str->validcount = saveg_read32(); + str->bnext = saveg_readp(); - // mobjtype_t type; - str->type = saveg_read_enum(); + /* struct mobj_s* bprev; */ - // mobjinfo_t* info; - str->info = saveg_readp(); + str->bprev = saveg_readp(); - // int tics; - str->tics = saveg_read32(); + /* struct subsector_s* subsector; */ - // state_t* state; - str->state = &states[saveg_read32()]; + str->subsector = saveg_readp(); - // int flags; - str->flags = saveg_read32(); + /* fixed_t floorz; */ - // int health; - str->health = saveg_read32(); + str->floorz = saveg_read32(); - // int movedir; - str->movedir = saveg_read32(); + /* fixed_t ceilingz; */ - // int movecount; - str->movecount = saveg_read32(); + str->ceilingz = saveg_read32(); - // struct mobj_s* target; - str->target = saveg_readp(); + /* fixed_t radius; */ - // int reactiontime; - str->reactiontime = saveg_read32(); + str->radius = saveg_read32(); - // int threshold; - str->threshold = saveg_read32(); + /* fixed_t height; */ - // struct player_s* player; - pl = saveg_read32(); + str->height = saveg_read32(); - if (pl > 0) + /* fixed_t momx; */ + + str->momx = saveg_read32(); + + /* fixed_t momy; */ + + str->momy = saveg_read32(); + + /* fixed_t momz; */ + + str->momz = saveg_read32(); + + /* int validcount; */ + + str->validcount = saveg_read32(); + + /* mobjtype_t type; */ + + str->type = saveg_read_enum(); + + /* mobjinfo_t* info; */ + + str->info = saveg_readp(); + + /* int tics; */ + + str->tics = saveg_read32(); + + /* state_t* state; */ + + str->state = &states[saveg_read32()]; + + /* int flags; */ + + str->flags = saveg_read32(); + + /* int health; */ + + str->health = saveg_read32(); + + /* int movedir; */ + + str->movedir = saveg_read32(); + + /* int movecount; */ + + str->movecount = saveg_read32(); + + /* struct mobj_s* target; */ + + str->target = saveg_readp(); + + /* int reactiontime; */ + + str->reactiontime = saveg_read32(); + + /* int threshold; */ + + str->threshold = saveg_read32(); + + /* struct player_s* player; */ + + pl = saveg_read32(); + + if (pl > 0) { - str->player = &players[pl - 1]; - str->player->mo = str; + str->player = &players[pl - 1]; + str->player->mo = str; } - else + else { - str->player = NULL; + str->player = NULL; } - // int lastlook; - str->lastlook = saveg_read32(); + /* int lastlook; */ + + str->lastlook = saveg_read32(); + + /* mapthing_t spawnpoint; */ + + saveg_read_mapthing_t(&str->spawnpoint); - // mapthing_t spawnpoint; - saveg_read_mapthing_t(&str->spawnpoint); + /* struct mobj_s* tracer; */ - // struct mobj_s* tracer; - str->tracer = saveg_readp(); + str->tracer = saveg_readp(); } static void saveg_write_mobj_t(mobj_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* fixed_t x; */ + + saveg_write32(str->x); + + /* fixed_t y; */ + + saveg_write32(str->y); + + /* fixed_t z; */ + + saveg_write32(str->z); + + /* struct mobj_s* snext; */ + + saveg_writep(str->snext); + + /* struct mobj_s* sprev; */ + + saveg_writep(str->sprev); + + /* angle_t angle; */ + + saveg_write32(str->angle); + + /* spritenum_t sprite; */ + + saveg_write_enum(str->sprite); + + /* int frame; */ + + saveg_write32(str->frame); + + /* struct mobj_s* bnext; */ + + saveg_writep(str->bnext); + + /* struct mobj_s* bprev; */ - // fixed_t x; - saveg_write32(str->x); + saveg_writep(str->bprev); - // fixed_t y; - saveg_write32(str->y); + /* struct subsector_s* subsector; */ - // fixed_t z; - saveg_write32(str->z); + saveg_writep(str->subsector); - // struct mobj_s* snext; - saveg_writep(str->snext); + /* fixed_t floorz; */ - // struct mobj_s* sprev; - saveg_writep(str->sprev); + saveg_write32(str->floorz); - // angle_t angle; - saveg_write32(str->angle); + /* fixed_t ceilingz; */ - // spritenum_t sprite; - saveg_write_enum(str->sprite); + saveg_write32(str->ceilingz); - // int frame; - saveg_write32(str->frame); + /* fixed_t radius; */ - // struct mobj_s* bnext; - saveg_writep(str->bnext); + saveg_write32(str->radius); - // struct mobj_s* bprev; - saveg_writep(str->bprev); + /* fixed_t height; */ - // struct subsector_s* subsector; - saveg_writep(str->subsector); + saveg_write32(str->height); - // fixed_t floorz; - saveg_write32(str->floorz); + /* fixed_t momx; */ - // fixed_t ceilingz; - saveg_write32(str->ceilingz); + saveg_write32(str->momx); - // fixed_t radius; - saveg_write32(str->radius); + /* fixed_t momy; */ - // fixed_t height; - saveg_write32(str->height); + saveg_write32(str->momy); - // fixed_t momx; - saveg_write32(str->momx); + /* fixed_t momz; */ - // fixed_t momy; - saveg_write32(str->momy); + saveg_write32(str->momz); - // fixed_t momz; - saveg_write32(str->momz); + /* int validcount; */ - // int validcount; - saveg_write32(str->validcount); + saveg_write32(str->validcount); - // mobjtype_t type; - saveg_write_enum(str->type); + /* mobjtype_t type; */ - // mobjinfo_t* info; - saveg_writep(str->info); + saveg_write_enum(str->type); - // int tics; - saveg_write32(str->tics); + /* mobjinfo_t* info; */ - // state_t* state; - saveg_write32(str->state - states); + saveg_writep(str->info); - // int flags; - saveg_write32(str->flags); + /* int tics; */ - // int health; - saveg_write32(str->health); + saveg_write32(str->tics); - // int movedir; - saveg_write32(str->movedir); + /* state_t* state; */ - // int movecount; - saveg_write32(str->movecount); + saveg_write32(str->state - states); - // struct mobj_s* target; - saveg_writep(str->target); + /* int flags; */ - // int reactiontime; - saveg_write32(str->reactiontime); + saveg_write32(str->flags); - // int threshold; - saveg_write32(str->threshold); + /* int health; */ - // struct player_s* player; - if (str->player) + saveg_write32(str->health); + + /* int movedir; */ + + saveg_write32(str->movedir); + + /* int movecount; */ + + saveg_write32(str->movecount); + + /* struct mobj_s* target; */ + + saveg_writep(str->target); + + /* int reactiontime; */ + + saveg_write32(str->reactiontime); + + /* int threshold; */ + + saveg_write32(str->threshold); + + /* struct player_s* player; */ + + if (str->player) { - saveg_write32(str->player - players + 1); + saveg_write32(str->player - players + 1); } - else + else { - saveg_write32(0); + saveg_write32(0); } - // int lastlook; - saveg_write32(str->lastlook); + /* int lastlook; */ - // mapthing_t spawnpoint; - saveg_write_mapthing_t(&str->spawnpoint); + saveg_write32(str->lastlook); - // struct mobj_s* tracer; - saveg_writep(str->tracer); -} + /* mapthing_t spawnpoint; */ + + saveg_write_mapthing_t(&str->spawnpoint); + /* struct mobj_s* tracer; */ -// -// ticcmd_t -// + saveg_writep(str->tracer); +} + +/* ticcmd_t */ static void saveg_read_ticcmd_t(ticcmd_t *str) { + /* signed char forwardmove; */ + + str->forwardmove = saveg_read8(); + + /* signed char sidemove; */ + + str->sidemove = saveg_read8(); + + /* short angleturn; */ + + str->angleturn = saveg_read16(); - // signed char forwardmove; - str->forwardmove = saveg_read8(); + /* short consistency; */ - // signed char sidemove; - str->sidemove = saveg_read8(); + str->consistency = saveg_read16(); - // short angleturn; - str->angleturn = saveg_read16(); + /* byte chatchar; */ - // short consistancy; - str->consistancy = saveg_read16(); + str->chatchar = saveg_read8(); - // byte chatchar; - str->chatchar = saveg_read8(); + /* byte buttons; */ - // byte buttons; - str->buttons = saveg_read8(); + str->buttons = saveg_read8(); } static void saveg_write_ticcmd_t(ticcmd_t *str) { + /* signed char forwardmove; */ - // signed char forwardmove; - saveg_write8(str->forwardmove); + saveg_write8(str->forwardmove); - // signed char sidemove; - saveg_write8(str->sidemove); + /* signed char sidemove; */ - // short angleturn; - saveg_write16(str->angleturn); + saveg_write8(str->sidemove); - // short consistancy; - saveg_write16(str->consistancy); + /* short angleturn; */ - // byte chatchar; - saveg_write8(str->chatchar); + saveg_write16(str->angleturn); - // byte buttons; - saveg_write8(str->buttons); + /* short consistency; */ + + saveg_write16(str->consistency); + + /* byte chatchar; */ + + saveg_write8(str->chatchar); + + /* byte buttons; */ + + saveg_write8(str->buttons); } -// -// pspdef_t -// +/* pspdef_t */ static void saveg_read_pspdef_t(pspdef_t *str) { - int state; + int state; + + /* state_t* state; */ - // state_t* state; - state = saveg_read32(); + state = saveg_read32(); - if (state > 0) + if (state > 0) { - str->state = &states[state]; + str->state = &states[state]; } - else + else { - str->state = NULL; + str->state = NULL; } - // int tics; - str->tics = saveg_read32(); + /* int tics; */ + + str->tics = saveg_read32(); - // fixed_t sx; - str->sx = saveg_read32(); + /* fixed_t sx; */ - // fixed_t sy; - str->sy = saveg_read32(); + str->sx = saveg_read32(); + + /* fixed_t sy; */ + + str->sy = saveg_read32(); } static void saveg_write_pspdef_t(pspdef_t *str) { - // state_t* state; - if (str->state) + /* state_t* state; */ + + if (str->state) { - saveg_write32(str->state - states); + saveg_write32(str->state - states); } - else + else { - saveg_write32(0); + saveg_write32(0); } - // int tics; - saveg_write32(str->tics); + /* int tics; */ + + saveg_write32(str->tics); - // fixed_t sx; - saveg_write32(str->sx); + /* fixed_t sx; */ - // fixed_t sy; - saveg_write32(str->sy); + saveg_write32(str->sx); + + /* fixed_t sy; */ + + saveg_write32(str->sy); } -// -// player_t -// +/* player_t */ static void saveg_read_player_t(player_t *str) { - int i; + int i; + + /* mobj_t* mo; */ + + str->mo = saveg_readp(); + + /* playerstate_t playerstate; */ + + str->playerstate = saveg_read_enum(); + + /* ticcmd_t cmd; */ + + saveg_read_ticcmd_t(&str->cmd); + + /* fixed_t viewz; */ + + str->viewz = saveg_read32(); - // mobj_t* mo; - str->mo = saveg_readp(); + /* fixed_t viewheight; */ - // playerstate_t playerstate; - str->playerstate = saveg_read_enum(); + str->viewheight = saveg_read32(); - // ticcmd_t cmd; - saveg_read_ticcmd_t(&str->cmd); + /* fixed_t deltaviewheight; */ - // fixed_t viewz; - str->viewz = saveg_read32(); + str->deltaviewheight = saveg_read32(); - // fixed_t viewheight; - str->viewheight = saveg_read32(); + /* fixed_t bob; */ - // fixed_t deltaviewheight; - str->deltaviewheight = saveg_read32(); + str->bob = saveg_read32(); - // fixed_t bob; - str->bob = saveg_read32(); + /* int health; */ - // int health; - str->health = saveg_read32(); + str->health = saveg_read32(); - // int armorpoints; - str->armorpoints = saveg_read32(); + /* int armorpoints; */ - // int armortype; - str->armortype = saveg_read32(); + str->armorpoints = saveg_read32(); - // int powers[NUMPOWERS]; - for (i=0; iarmortype = saveg_read32(); + + /* int powers[NUMPOWERS]; */ + + for (i = 0; i < NUMPOWERS; ++i) { - str->powers[i] = saveg_read32(); + str->powers[i] = saveg_read32(); } - // boolean cards[NUMCARDS]; - for (i=0; icards[i] = saveg_read32(); + str->cards[i] = saveg_read32(); } - // boolean backpack; - str->backpack = saveg_read32(); + /* boolean backpack; */ - // int frags[MAXPLAYERS]; - for (i=0; ibackpack = saveg_read32(); + + /* int frags[MAXPLAYERS]; */ + + for (i = 0; i < MAXPLAYERS; ++i) { - str->frags[i] = saveg_read32(); + str->frags[i] = saveg_read32(); } - // weapontype_t readyweapon; - str->readyweapon = saveg_read_enum(); + /* weapontype_t readyweapon; */ + + str->readyweapon = saveg_read_enum(); - // weapontype_t pendingweapon; - str->pendingweapon = saveg_read_enum(); + /* weapontype_t pendingweapon; */ - // boolean weaponowned[NUMWEAPONS]; - for (i=0; ipendingweapon = saveg_read_enum(); + + /* boolean weaponowned[NUMWEAPONS]; */ + + for (i = 0; i < NUMWEAPONS; ++i) { - str->weaponowned[i] = saveg_read32(); + str->weaponowned[i] = saveg_read32(); } - // int ammo[NUMAMMO]; - for (i=0; iammo[i] = saveg_read32(); + str->ammo[i] = saveg_read32(); } - // int maxammo[NUMAMMO]; - for (i=0; imaxammo[i] = saveg_read32(); + str->maxammo[i] = saveg_read32(); } - // int attackdown; - str->attackdown = saveg_read32(); + /* int attackdown; */ + + str->attackdown = saveg_read32(); + + /* int usedown; */ - // int usedown; - str->usedown = saveg_read32(); + str->usedown = saveg_read32(); - // int cheats; - str->cheats = saveg_read32(); + /* int cheats; */ - // int refire; - str->refire = saveg_read32(); + str->cheats = saveg_read32(); - // int killcount; - str->killcount = saveg_read32(); + /* int refire; */ - // int itemcount; - str->itemcount = saveg_read32(); + str->refire = saveg_read32(); - // int secretcount; - str->secretcount = saveg_read32(); + /* int killcount; */ - // char* message; - str->message = saveg_readp(); + str->killcount = saveg_read32(); - // int damagecount; - str->damagecount = saveg_read32(); + /* int itemcount; */ - // int bonuscount; - str->bonuscount = saveg_read32(); + str->itemcount = saveg_read32(); - // mobj_t* attacker; - str->attacker = saveg_readp(); + /* int secretcount; */ - // int extralight; - str->extralight = saveg_read32(); + str->secretcount = saveg_read32(); - // int fixedcolormap; - str->fixedcolormap = saveg_read32(); + /* char* message; */ - // int colormap; - str->colormap = saveg_read32(); + str->message = saveg_readp(); - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; idamagecount = saveg_read32(); + + /* int bonuscount; */ + + str->bonuscount = saveg_read32(); + + /* mobj_t* attacker; */ + + str->attacker = saveg_readp(); + + /* int extralight; */ + + str->extralight = saveg_read32(); + + /* int fixedcolormap; */ + + str->fixedcolormap = saveg_read32(); + + /* int colormap; */ + + str->colormap = saveg_read32(); + + /* pspdef_t psprites[NUMPSPRITES]; */ + + for (i = 0; i < NUMPSPRITES; ++i) { - saveg_read_pspdef_t(&str->psprites[i]); + saveg_read_pspdef_t(&str->psprites[i]); } - // boolean didsecret; - str->didsecret = saveg_read32(); + /* boolean didsecret; */ + + str->didsecret = saveg_read32(); } static void saveg_write_player_t(player_t *str) { - int i; + int i; - // mobj_t* mo; - saveg_writep(str->mo); + /* mobj_t* mo; */ - // playerstate_t playerstate; - saveg_write_enum(str->playerstate); + saveg_writep(str->mo); - // ticcmd_t cmd; - saveg_write_ticcmd_t(&str->cmd); + /* playerstate_t playerstate; */ - // fixed_t viewz; - saveg_write32(str->viewz); + saveg_write_enum(str->playerstate); - // fixed_t viewheight; - saveg_write32(str->viewheight); + /* ticcmd_t cmd; */ - // fixed_t deltaviewheight; - saveg_write32(str->deltaviewheight); + saveg_write_ticcmd_t(&str->cmd); - // fixed_t bob; - saveg_write32(str->bob); + /* fixed_t viewz; */ - // int health; - saveg_write32(str->health); + saveg_write32(str->viewz); - // int armorpoints; - saveg_write32(str->armorpoints); + /* fixed_t viewheight; */ - // int armortype; - saveg_write32(str->armortype); + saveg_write32(str->viewheight); - // int powers[NUMPOWERS]; - for (i=0; ideltaviewheight); + + /* fixed_t bob; */ + + saveg_write32(str->bob); + + /* int health; */ + + saveg_write32(str->health); + + /* int armorpoints; */ + + saveg_write32(str->armorpoints); + + /* int armortype; */ + + saveg_write32(str->armortype); + + /* int powers[NUMPOWERS]; */ + + for (i = 0; i < NUMPOWERS; ++i) { - saveg_write32(str->powers[i]); + saveg_write32(str->powers[i]); } - // boolean cards[NUMCARDS]; - for (i=0; icards[i]); + saveg_write32(str->cards[i]); } - // boolean backpack; - saveg_write32(str->backpack); + /* boolean backpack; */ + + saveg_write32(str->backpack); + + /* int frags[MAXPLAYERS]; */ - // int frags[MAXPLAYERS]; - for (i=0; ifrags[i]); + saveg_write32(str->frags[i]); } - // weapontype_t readyweapon; - saveg_write_enum(str->readyweapon); + /* weapontype_t readyweapon; */ - // weapontype_t pendingweapon; - saveg_write_enum(str->pendingweapon); + saveg_write_enum(str->readyweapon); - // boolean weaponowned[NUMWEAPONS]; - for (i=0; ipendingweapon); + + /* boolean weaponowned[NUMWEAPONS]; */ + + for (i = 0; i < NUMWEAPONS; ++i) { - saveg_write32(str->weaponowned[i]); + saveg_write32(str->weaponowned[i]); } - // int ammo[NUMAMMO]; - for (i=0; iammo[i]); + saveg_write32(str->ammo[i]); } - // int maxammo[NUMAMMO]; - for (i=0; imaxammo[i]); + saveg_write32(str->maxammo[i]); } - // int attackdown; - saveg_write32(str->attackdown); + /* int attackdown; */ + + saveg_write32(str->attackdown); + + /* int usedown; */ + + saveg_write32(str->usedown); + + /* int cheats; */ + + saveg_write32(str->cheats); + + /* int refire; */ + + saveg_write32(str->refire); + + /* int killcount; */ + + saveg_write32(str->killcount); - // int usedown; - saveg_write32(str->usedown); + /* int itemcount; */ - // int cheats; - saveg_write32(str->cheats); + saveg_write32(str->itemcount); - // int refire; - saveg_write32(str->refire); + /* int secretcount; */ - // int killcount; - saveg_write32(str->killcount); + saveg_write32(str->secretcount); - // int itemcount; - saveg_write32(str->itemcount); + /* char* message; */ - // int secretcount; - saveg_write32(str->secretcount); + saveg_writep(str->message); - // char* message; - saveg_writep(str->message); + /* int damagecount; */ - // int damagecount; - saveg_write32(str->damagecount); + saveg_write32(str->damagecount); - // int bonuscount; - saveg_write32(str->bonuscount); + /* int bonuscount; */ - // mobj_t* attacker; - saveg_writep(str->attacker); + saveg_write32(str->bonuscount); - // int extralight; - saveg_write32(str->extralight); + /* mobj_t* attacker; */ - // int fixedcolormap; - saveg_write32(str->fixedcolormap); + saveg_writep(str->attacker); - // int colormap; - saveg_write32(str->colormap); + /* int extralight; */ - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; iextralight); + + /* int fixedcolormap; */ + + saveg_write32(str->fixedcolormap); + + /* int colormap; */ + + saveg_write32(str->colormap); + + /* pspdef_t psprites[NUMPSPRITES]; */ + + for (i = 0; i < NUMPSPRITES; ++i) { - saveg_write_pspdef_t(&str->psprites[i]); + saveg_write_pspdef_t(&str->psprites[i]); } - // boolean didsecret; - saveg_write32(str->didsecret); -} + /* boolean didsecret; */ + saveg_write32(str->didsecret); +} -// -// ceiling_t -// +/* ceiling_t */ static void saveg_read_ceiling_t(ceiling_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* ceiling_e type; */ + + str->type = saveg_read_enum(); + + /* sector_t* sector; */ - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + sector = saveg_read32(); + str->sector = §ors[sector]; - // ceiling_e type; - str->type = saveg_read_enum(); + /* fixed_t bottomheight; */ - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + str->bottomheight = saveg_read32(); - // fixed_t bottomheight; - str->bottomheight = saveg_read32(); + /* fixed_t topheight; */ - // fixed_t topheight; - str->topheight = saveg_read32(); + str->topheight = saveg_read32(); - // fixed_t speed; - str->speed = saveg_read32(); + /* fixed_t speed; */ - // boolean crush; - str->crush = saveg_read32(); + str->speed = saveg_read32(); - // int direction; - str->direction = saveg_read32(); + /* boolean crush; */ - // int tag; - str->tag = saveg_read32(); + str->crush = saveg_read32(); - // int olddirection; - str->olddirection = saveg_read32(); + /* int direction; */ + + str->direction = saveg_read32(); + + /* int tag; */ + + str->tag = saveg_read32(); + + /* int olddirection; */ + + str->olddirection = saveg_read32(); } static void saveg_write_ceiling_t(ceiling_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* ceiling_e type; */ + + saveg_write_enum(str->type); + + /* sector_t* sector; */ + + saveg_write32(str->sector - sectors); + + /* fixed_t bottomheight; */ + + saveg_write32(str->bottomheight); + + /* fixed_t topheight; */ + + saveg_write32(str->topheight); - // ceiling_e type; - saveg_write_enum(str->type); + /* fixed_t speed; */ - // sector_t* sector; - saveg_write32(str->sector - sectors); + saveg_write32(str->speed); - // fixed_t bottomheight; - saveg_write32(str->bottomheight); + /* boolean crush; */ - // fixed_t topheight; - saveg_write32(str->topheight); + saveg_write32(str->crush); - // fixed_t speed; - saveg_write32(str->speed); + /* int direction; */ - // boolean crush; - saveg_write32(str->crush); + saveg_write32(str->direction); - // int direction; - saveg_write32(str->direction); + /* int tag; */ - // int tag; - saveg_write32(str->tag); + saveg_write32(str->tag); - // int olddirection; - saveg_write32(str->olddirection); + /* int olddirection; */ + + saveg_write32(str->olddirection); } -// -// vldoor_t -// +/* vldoor_t */ static void saveg_read_vldoor_t(vldoor_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* vldoor_e type; */ + + str->type = saveg_read_enum(); + + /* sector_t* sector; */ + + sector = saveg_read32(); + str->sector = §ors[sector]; - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + /* fixed_t topheight; */ - // vldoor_e type; - str->type = saveg_read_enum(); + str->topheight = saveg_read32(); - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + /* fixed_t speed; */ - // fixed_t topheight; - str->topheight = saveg_read32(); + str->speed = saveg_read32(); - // fixed_t speed; - str->speed = saveg_read32(); + /* int direction; */ - // int direction; - str->direction = saveg_read32(); + str->direction = saveg_read32(); - // int topwait; - str->topwait = saveg_read32(); + /* int topwait; */ - // int topcountdown; - str->topcountdown = saveg_read32(); + str->topwait = saveg_read32(); + + /* int topcountdown; */ + + str->topcountdown = saveg_read32(); } static void saveg_write_vldoor_t(vldoor_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* vldoor_e type; */ + + saveg_write_enum(str->type); + + /* sector_t* sector; */ + + saveg_write32(str->sector - sectors); - // vldoor_e type; - saveg_write_enum(str->type); + /* fixed_t topheight; */ - // sector_t* sector; - saveg_write32(str->sector - sectors); + saveg_write32(str->topheight); - // fixed_t topheight; - saveg_write32(str->topheight); + /* fixed_t speed; */ - // fixed_t speed; - saveg_write32(str->speed); + saveg_write32(str->speed); - // int direction; - saveg_write32(str->direction); + /* int direction; */ - // int topwait; - saveg_write32(str->topwait); + saveg_write32(str->direction); - // int topcountdown; - saveg_write32(str->topcountdown); + /* int topwait; */ + + saveg_write32(str->topwait); + + /* int topcountdown; */ + + saveg_write32(str->topcountdown); } -// -// floormove_t -// +/* floormove_t */ static void saveg_read_floormove_t(floormove_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* floor_e type; */ + + str->type = saveg_read_enum(); - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + /* boolean crush; */ - // floor_e type; - str->type = saveg_read_enum(); + str->crush = saveg_read32(); - // boolean crush; - str->crush = saveg_read32(); + /* sector_t* sector; */ - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + sector = saveg_read32(); + str->sector = §ors[sector]; - // int direction; - str->direction = saveg_read32(); + /* int direction; */ - // int newspecial; - str->newspecial = saveg_read32(); + str->direction = saveg_read32(); - // short texture; - str->texture = saveg_read16(); + /* int newspecial; */ - // fixed_t floordestheight; - str->floordestheight = saveg_read32(); + str->newspecial = saveg_read32(); - // fixed_t speed; - str->speed = saveg_read32(); + /* short texture; */ + + str->texture = saveg_read16(); + + /* fixed_t floordestheight; */ + + str->floordestheight = saveg_read32(); + + /* fixed_t speed; */ + + str->speed = saveg_read32(); } static void saveg_write_floormove_t(floormove_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* floor_e type; */ - // floor_e type; - saveg_write_enum(str->type); + saveg_write_enum(str->type); - // boolean crush; - saveg_write32(str->crush); + /* boolean crush; */ - // sector_t* sector; - saveg_write32(str->sector - sectors); + saveg_write32(str->crush); - // int direction; - saveg_write32(str->direction); + /* sector_t* sector; */ - // int newspecial; - saveg_write32(str->newspecial); + saveg_write32(str->sector - sectors); - // short texture; - saveg_write16(str->texture); + /* int direction; */ - // fixed_t floordestheight; - saveg_write32(str->floordestheight); + saveg_write32(str->direction); - // fixed_t speed; - saveg_write32(str->speed); + /* int newspecial; */ + + saveg_write32(str->newspecial); + + /* short texture; */ + + saveg_write16(str->texture); + + /* fixed_t floordestheight; */ + + saveg_write32(str->floordestheight); + + /* fixed_t speed; */ + + saveg_write32(str->speed); } -// -// plat_t -// +/* plat_t */ static void saveg_read_plat_t(plat_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* sector_t* sector; */ + + sector = saveg_read32(); + str->sector = §ors[sector]; + + /* fixed_t speed; */ + + str->speed = saveg_read32(); - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + /* fixed_t low; */ - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + str->low = saveg_read32(); - // fixed_t speed; - str->speed = saveg_read32(); + /* fixed_t high; */ - // fixed_t low; - str->low = saveg_read32(); + str->high = saveg_read32(); - // fixed_t high; - str->high = saveg_read32(); + /* int wait; */ - // int wait; - str->wait = saveg_read32(); + str->wait = saveg_read32(); - // int count; - str->count = saveg_read32(); + /* int count; */ - // plat_e status; - str->status = saveg_read_enum(); + str->count = saveg_read32(); - // plat_e oldstatus; - str->oldstatus = saveg_read_enum(); + /* plat_e status; */ - // boolean crush; - str->crush = saveg_read32(); + str->status = saveg_read_enum(); - // int tag; - str->tag = saveg_read32(); + /* plat_e oldstatus; */ - // plattype_e type; - str->type = saveg_read_enum(); + str->oldstatus = saveg_read_enum(); + + /* boolean crush; */ + + str->crush = saveg_read32(); + + /* int tag; */ + + str->tag = saveg_read32(); + + /* plattype_e type; */ + + str->type = saveg_read_enum(); } static void saveg_write_plat_t(plat_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* sector_t* sector; */ + + saveg_write32(str->sector - sectors); + + /* fixed_t speed; */ + + saveg_write32(str->speed); + + /* fixed_t low; */ + + saveg_write32(str->low); + + /* fixed_t high; */ - // sector_t* sector; - saveg_write32(str->sector - sectors); + saveg_write32(str->high); - // fixed_t speed; - saveg_write32(str->speed); + /* int wait; */ - // fixed_t low; - saveg_write32(str->low); + saveg_write32(str->wait); - // fixed_t high; - saveg_write32(str->high); + /* int count; */ - // int wait; - saveg_write32(str->wait); + saveg_write32(str->count); - // int count; - saveg_write32(str->count); + /* plat_e status; */ - // plat_e status; - saveg_write_enum(str->status); + saveg_write_enum(str->status); - // plat_e oldstatus; - saveg_write_enum(str->oldstatus); + /* plat_e oldstatus; */ - // boolean crush; - saveg_write32(str->crush); + saveg_write_enum(str->oldstatus); - // int tag; - saveg_write32(str->tag); + /* boolean crush; */ - // plattype_e type; - saveg_write_enum(str->type); + saveg_write32(str->crush); + + /* int tag; */ + + saveg_write32(str->tag); + + /* plattype_e type; */ + + saveg_write_enum(str->type); } -// -// lightflash_t -// +/* lightflash_t */ static void saveg_read_lightflash_t(lightflash_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* sector_t* sector; */ - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + sector = saveg_read32(); + str->sector = §ors[sector]; - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + /* int count; */ - // int count; - str->count = saveg_read32(); + str->count = saveg_read32(); - // int maxlight; - str->maxlight = saveg_read32(); + /* int maxlight; */ - // int minlight; - str->minlight = saveg_read32(); + str->maxlight = saveg_read32(); - // int maxtime; - str->maxtime = saveg_read32(); + /* int minlight; */ - // int mintime; - str->mintime = saveg_read32(); + str->minlight = saveg_read32(); + + /* int maxtime; */ + + str->maxtime = saveg_read32(); + + /* int mintime; */ + + str->mintime = saveg_read32(); } static void saveg_write_lightflash_t(lightflash_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* sector_t* sector; */ + + saveg_write32(str->sector - sectors); - // sector_t* sector; - saveg_write32(str->sector - sectors); + /* int count; */ - // int count; - saveg_write32(str->count); + saveg_write32(str->count); - // int maxlight; - saveg_write32(str->maxlight); + /* int maxlight; */ - // int minlight; - saveg_write32(str->minlight); + saveg_write32(str->maxlight); - // int maxtime; - saveg_write32(str->maxtime); + /* int minlight; */ - // int mintime; - saveg_write32(str->mintime); + saveg_write32(str->minlight); + + /* int maxtime; */ + + saveg_write32(str->maxtime); + + /* int mintime; */ + + saveg_write32(str->mintime); } -// -// strobe_t -// +/* strobe_t */ static void saveg_read_strobe_t(strobe_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* sector_t* sector; */ - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + sector = saveg_read32(); + str->sector = §ors[sector]; - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + /* int count; */ - // int count; - str->count = saveg_read32(); + str->count = saveg_read32(); - // int minlight; - str->minlight = saveg_read32(); + /* int minlight; */ - // int maxlight; - str->maxlight = saveg_read32(); + str->minlight = saveg_read32(); - // int darktime; - str->darktime = saveg_read32(); + /* int maxlight; */ - // int brighttime; - str->brighttime = saveg_read32(); + str->maxlight = saveg_read32(); + + /* int darktime; */ + + str->darktime = saveg_read32(); + + /* int brighttime; */ + + str->brighttime = saveg_read32(); } static void saveg_write_strobe_t(strobe_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* sector_t* sector; */ + + saveg_write32(str->sector - sectors); - // sector_t* sector; - saveg_write32(str->sector - sectors); + /* int count; */ - // int count; - saveg_write32(str->count); + saveg_write32(str->count); - // int minlight; - saveg_write32(str->minlight); + /* int minlight; */ - // int maxlight; - saveg_write32(str->maxlight); + saveg_write32(str->minlight); - // int darktime; - saveg_write32(str->darktime); + /* int maxlight; */ - // int brighttime; - saveg_write32(str->brighttime); + saveg_write32(str->maxlight); + + /* int darktime; */ + + saveg_write32(str->darktime); + + /* int brighttime; */ + + saveg_write32(str->brighttime); } -// -// glow_t -// +/* glow_t */ static void saveg_read_glow_t(glow_t *str) { - int sector; + int sector; + + /* thinker_t thinker; */ + + saveg_read_thinker_t(&str->thinker); + + /* sector_t* sector; */ - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); + sector = saveg_read32(); + str->sector = §ors[sector]; - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; + /* int minlight; */ - // int minlight; - str->minlight = saveg_read32(); + str->minlight = saveg_read32(); - // int maxlight; - str->maxlight = saveg_read32(); + /* int maxlight; */ - // int direction; - str->direction = saveg_read32(); + str->maxlight = saveg_read32(); + + /* int direction; */ + + str->direction = saveg_read32(); } static void saveg_write_glow_t(glow_t *str) { - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); + /* thinker_t thinker; */ + + saveg_write_thinker_t(&str->thinker); + + /* sector_t* sector; */ + + saveg_write32(str->sector - sectors); + + /* int minlight; */ - // sector_t* sector; - saveg_write32(str->sector - sectors); + saveg_write32(str->minlight); - // int minlight; - saveg_write32(str->minlight); + /* int maxlight; */ - // int maxlight; - saveg_write32(str->maxlight); + saveg_write32(str->maxlight); - // int direction; - saveg_write32(str->direction); + /* int direction; */ + + saveg_write32(str->direction); } -// -// Write the header for a savegame -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Write the header for a savegame */ -void P_WriteSaveGameHeader(char *description) +void p_write_save_game_header(char *description) { - char name[VERSIONSIZE]; - int i; - - for (i=0; description[i] != '\0'; ++i) - saveg_write8(description[i]); - for (; i> 16) & 0xff); - saveg_write8((leveltime >> 8) & 0xff); - saveg_write8(leveltime & 0xff); + char name[VERSIONSIZE]; + int i; + + for (i = 0; description[i] != '\0'; ++i) + saveg_write8(description[i]); + for (; i < SAVESTRINGSIZE; ++i) + saveg_write8(0); + + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name), "version %i", g_vanilla_version_code()); + + for (i = 0; i < VERSIONSIZE; ++i) + saveg_write8(name[i]); + + saveg_write8(gameskill); + saveg_write8(gameepisode); + saveg_write8(gamemap); + + for (i = 0; i < MAXPLAYERS; i++) + saveg_write8(playeringame[i]); + + saveg_write8((leveltime >> 16) & 0xff); + saveg_write8((leveltime >> 8) & 0xff); + saveg_write8(leveltime & 0xff); } -// -// Read the header for a savegame -// +/* Get the filename of a temporary file to write the savegame to. After + * the file has been successfully saved, it will be renamed to the + * real file. + */ -boolean P_ReadSaveGameHeader(void) +char *p_temp_save_game_file(void) { - int i; - byte a, b, c; - char vcheck[VERSIONSIZE]; - char read_vcheck[VERSIONSIZE]; - - // skip the description field - - for (i=0; ifloorheight >> FRACBITS); - saveg_write16(sec->ceilingheight >> FRACBITS); - saveg_write16(sec->floorpic); - saveg_write16(sec->ceilingpic); - saveg_write16(sec->lightlevel); - saveg_write16(sec->special); // needed? - saveg_write16(sec->tag); // needed? - } + int i; - - // do lines - for (i=0, li = lines ; iflags); - saveg_write16(li->special); - saveg_write16(li->tag); - for (j=0 ; j<2 ; j++) - { - if (li->sidenum[j] == -1) - continue; - - si = &sides[li->sidenum[j]]; - - saveg_write16(si->textureoffset >> FRACBITS); - saveg_write16(si->rowoffset >> FRACBITS); - saveg_write16(si->toptexture); - saveg_write16(si->bottomtexture); - saveg_write16(si->midtexture); - } + if (!playeringame[i]) continue; + + saveg_read_pad(); + + saveg_read_player_t(&players[i]); + + /* will be set when unarc thinker */ + + players[i].mo = NULL; + players[i].message = NULL; + players[i].attacker = NULL; } } +void p_archive_world(void) +{ + int i; + int j; + sector_t *sec; + line_t *li; + side_t *si; + /* do sectors */ -// -// P_UnArchiveWorld -// -void P_UnArchiveWorld (void) -{ - int i; - int j; - sector_t* sec; - line_t* li; - side_t* si; - - // do sectors - for (i=0, sec = sectors ; ifloorheight = saveg_read16() << FRACBITS; - sec->ceilingheight = saveg_read16() << FRACBITS; - sec->floorpic = saveg_read16(); - sec->ceilingpic = saveg_read16(); - sec->lightlevel = saveg_read16(); - sec->special = saveg_read16(); // needed? - sec->tag = saveg_read16(); // needed? - sec->specialdata = 0; - sec->soundtarget = 0; + saveg_write16(sec->floorheight >> FRACBITS); + saveg_write16(sec->ceilingheight >> FRACBITS); + saveg_write16(sec->floorpic); + saveg_write16(sec->ceilingpic); + saveg_write16(sec->lightlevel); + saveg_write16(sec->special); /* needed? */ + + saveg_write16(sec->tag); /* needed? */ } - - // do lines - for (i=0, li = lines ; iflags = saveg_read16(); - li->special = saveg_read16(); - li->tag = saveg_read16(); - for (j=0 ; j<2 ; j++) - { - if (li->sidenum[j] == -1) - continue; - si = &sides[li->sidenum[j]]; - si->textureoffset = saveg_read16() << FRACBITS; - si->rowoffset = saveg_read16() << FRACBITS; - si->toptexture = saveg_read16(); - si->bottomtexture = saveg_read16(); - si->midtexture = saveg_read16(); - } + saveg_write16(li->flags); + saveg_write16(li->special); + saveg_write16(li->tag); + for (j = 0; j < 2; j++) + { + if (li->sidenum[j] == -1) continue; + + si = &sides[li->sidenum[j]]; + + saveg_write16(si->textureoffset >> FRACBITS); + saveg_write16(si->rowoffset >> FRACBITS); + saveg_write16(si->toptexture); + saveg_write16(si->bottomtexture); + saveg_write16(si->midtexture); + } } } +void p_unarchive_world(void) +{ + int i; + int j; + sector_t *sec; + line_t *li; + side_t *si; + /* do sectors */ + for (i = 0, sec = sectors; i < numsectors; i++, sec++) + { + sec->floorheight = saveg_read16() << FRACBITS; + sec->ceilingheight = saveg_read16() << FRACBITS; + sec->floorpic = saveg_read16(); + sec->ceilingpic = saveg_read16(); + sec->lightlevel = saveg_read16(); + sec->special = saveg_read16(); /* needed? */ + sec->tag = saveg_read16(); /* needed? */ -// -// Thinkers -// -typedef enum -{ - tc_end, - tc_mobj + sec->specialdata = 0; + sec->soundtarget = 0; + } -} thinkerclass_t; + /* do lines */ + for (i = 0, li = lines; i < numlines; i++, li++) + { + li->flags = saveg_read16(); + li->special = saveg_read16(); + li->tag = saveg_read16(); + for (j = 0; j < 2; j++) + { + if (li->sidenum[j] == -1) continue; + si = &sides[li->sidenum[j]]; + si->textureoffset = saveg_read16() << FRACBITS; + si->rowoffset = saveg_read16() << FRACBITS; + si->toptexture = saveg_read16(); + si->bottomtexture = saveg_read16(); + si->midtexture = saveg_read16(); + } + } +} -// -// P_ArchiveThinkers -// -void P_ArchiveThinkers (void) +void p_archive_thinkers(void) { - thinker_t* th; + thinker_t *th; - // save off the current thinkers - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + /* save off the current thinkers */ + + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - saveg_write8(tc_mobj); - saveg_write_pad(); - saveg_write_mobj_t((mobj_t *) th); - - continue; - } - - // I_Error ("P_ArchiveThinkers: Unknown thinker function"); + if (th->function.acp1 == (actionf_p1)p_mobj_thinker) + { + saveg_write8(tc_mobj); + saveg_write_pad(); + saveg_write_mobj_t((mobj_t *)th); + + continue; + } } - // add a terminating marker - saveg_write8(tc_end); + /* add a terminating marker */ + + saveg_write8(tc_end); } +void p_unarchive_thinkers(void) +{ + byte tclass; + thinker_t *currentthinker; + thinker_t *next; + mobj_t *mobj; + /* remove all the current thinkers */ -// -// P_UnArchiveThinkers -// -void P_UnArchiveThinkers (void) -{ - byte tclass; - thinker_t* currentthinker; - thinker_t* next; - mobj_t* mobj; - - // remove all the current thinkers - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) { - next = currentthinker->next; - - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - P_RemoveMobj ((mobj_t *)currentthinker); - else - Z_Free (currentthinker); - - currentthinker = next; + next = currentthinker->next; + + if (currentthinker->function.acp1 == (actionf_p1)p_mobj_thinker) + p_remove_mobj((mobj_t *)currentthinker); + else + z_free(currentthinker); + + currentthinker = next; } - P_InitThinkers (); - - // read in saved thinkers - while (1) + + p_init_thinkers(); + + /* read in saved thinkers */ + + while (1) { - tclass = saveg_read8(); - switch (tclass) - { - case tc_end: - return; // end of list - - case tc_mobj: - saveg_read_pad(); - mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); - saveg_read_mobj_t(mobj); - - mobj->target = NULL; - mobj->tracer = NULL; - P_SetThingPosition (mobj); - mobj->info = &mobjinfo[mobj->type]; - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; - P_AddThinker (&mobj->thinker); - break; - - default: - I_Error ("Unknown tclass %i in savegame",tclass); - } - + tclass = saveg_read8(); + switch (tclass) + { + case tc_end: + return; /* end of list */ + + case tc_mobj: + saveg_read_pad(); + mobj = z_malloc(sizeof(*mobj), PU_LEVEL, NULL); + saveg_read_mobj_t(mobj); + + mobj->target = NULL; + mobj->tracer = NULL; + p_set_thing_position(mobj); + mobj->info = &mobjinfo[mobj->type]; + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + mobj->thinker.function.acp1 = (actionf_p1)p_mobj_thinker; + p_add_thinker(&mobj->thinker); + break; + + default: + i_error("Unknown tclass %i in savegame", tclass); + } } - } - -// -// P_ArchiveSpecials -// -enum +/* Things to handle: + * + * t_move_ceiling, (ceiling_t: sector_t * swizzle), - active list + * t_vertical_door, (vldoor_t: sector_t * swizzle), + * t_move_floor, (floormove_t: sector_t * swizzle), + * t_light_flash, (lightflash_t: sector_t * swizzle), + * t_strobe_flash, (strobe_t: sector_t *), + * t_glow, (glow_t: sector_t *), + * t_plat_raise, (plat_t: sector_t *), - active list + */ + +void p_archive_specials(void) { - tc_ceiling, - tc_door, - tc_floor, - tc_plat, - tc_flash, - tc_strobe, - tc_glow, - tc_endspecials - -} specials_e; - - - -// -// Things to handle: -// -// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list -// T_VerticalDoor, (vldoor_t: sector_t * swizzle), -// T_MoveFloor, (floormove_t: sector_t * swizzle), -// T_LightFlash, (lightflash_t: sector_t * swizzle), -// T_StrobeFlash, (strobe_t: sector_t *), -// T_Glow, (glow_t: sector_t *), -// T_PlatRaise, (plat_t: sector_t *), - active list -// -void P_ArchiveSpecials (void) -{ - thinker_t* th; - int i; - - // save off the current thinkers - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + thinker_t *th; + int i; + + /* save off the current thinkers */ + + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - if (th->function.acv == (actionf_v)NULL) - { - for (i = 0; i < MAXCEILINGS;i++) - if (activeceilings[i] == (ceiling_t *)th) - break; - - if (ifunction.acp1 == (actionf_p1)T_MoveCeiling) - { - saveg_write8(tc_ceiling); - saveg_write_pad(); - saveg_write_ceiling_t((ceiling_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_VerticalDoor) - { - saveg_write8(tc_door); - saveg_write_pad(); - saveg_write_vldoor_t((vldoor_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_MoveFloor) - { - saveg_write8(tc_floor); - saveg_write_pad(); - saveg_write_floormove_t((floormove_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_PlatRaise) - { - saveg_write8(tc_plat); - saveg_write_pad(); - saveg_write_plat_t((plat_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_LightFlash) - { - saveg_write8(tc_flash); - saveg_write_pad(); - saveg_write_lightflash_t((lightflash_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_StrobeFlash) - { - saveg_write8(tc_strobe); - saveg_write_pad(); - saveg_write_strobe_t((strobe_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_Glow) - { - saveg_write8(tc_glow); - saveg_write_pad(); - saveg_write_glow_t((glow_t *) th); - continue; - } + if (th->function.acv == (actionf_v)NULL) + { + for (i = 0; i < MAXCEILINGS; i++) + { + if (activeceilings[i] == (ceiling_t *)th) break; + } + + if (i < MAXCEILINGS) + { + saveg_write8(tc_ceiling); + saveg_write_pad(); + saveg_write_ceiling_t((ceiling_t *)th); + } + + continue; + } + + if (th->function.acp1 == (actionf_p1)t_move_ceiling) + { + saveg_write8(tc_ceiling); + saveg_write_pad(); + saveg_write_ceiling_t((ceiling_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)t_vertical_door) + { + saveg_write8(tc_door); + saveg_write_pad(); + saveg_write_vldoor_t((vldoor_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)t_move_floor) + { + saveg_write8(tc_floor); + saveg_write_pad(); + saveg_write_floormove_t((floormove_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)t_plat_raise) + { + saveg_write8(tc_plat); + saveg_write_pad(); + saveg_write_plat_t((plat_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)t_light_flash) + { + saveg_write8(tc_flash); + saveg_write_pad(); + saveg_write_lightflash_t((lightflash_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)t_strobe_flash) + { + saveg_write8(tc_strobe); + saveg_write_pad(); + saveg_write_strobe_t((strobe_t *)th); + continue; + } + + if (th->function.acp1 == (actionf_p1)t_glow) + { + saveg_write8(tc_glow); + saveg_write_pad(); + saveg_write_glow_t((glow_t *)th); + continue; + } } - - // add a terminating marker - saveg_write8(tc_endspecials); -} + /* add a terminating marker */ + saveg_write8(tc_endspecials); +} -// -// P_UnArchiveSpecials -// -void P_UnArchiveSpecials (void) +void p_unarchive_specials(void) { - byte tclass; - ceiling_t* ceiling; - vldoor_t* door; - floormove_t* floor; - plat_t* plat; - lightflash_t* flash; - strobe_t* strobe; - glow_t* glow; - - - // read in saved thinkers - while (1) + byte tclass; + ceiling_t *ceiling; + vldoor_t *door; + floormove_t *floor; + plat_t *plat; + lightflash_t *flash; + strobe_t *strobe; + glow_t *glow; + + /* read in saved thinkers */ + + while (1) { - tclass = saveg_read8(); - - switch (tclass) - { - case tc_endspecials: - return; // end of list - - case tc_ceiling: - saveg_read_pad(); - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL); - saveg_read_ceiling_t(ceiling); - ceiling->sector->specialdata = ceiling; - - if (ceiling->thinker.function.acp1) - ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; - - P_AddThinker (&ceiling->thinker); - P_AddActiveCeiling(ceiling); - break; - - case tc_door: - saveg_read_pad(); - door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL); - saveg_read_vldoor_t(door); - door->sector->specialdata = door; - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - P_AddThinker (&door->thinker); - break; - - case tc_floor: - saveg_read_pad(); - floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); - saveg_read_floormove_t(floor); - floor->sector->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; - P_AddThinker (&floor->thinker); - break; - - case tc_plat: - saveg_read_pad(); - plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); - saveg_read_plat_t(plat); - plat->sector->specialdata = plat; - - if (plat->thinker.function.acp1) - plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise; - - P_AddThinker (&plat->thinker); - P_AddActivePlat(plat); - break; - - case tc_flash: - saveg_read_pad(); - flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); - saveg_read_lightflash_t(flash); - flash->thinker.function.acp1 = (actionf_p1)T_LightFlash; - P_AddThinker (&flash->thinker); - break; - - case tc_strobe: - saveg_read_pad(); - strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); - saveg_read_strobe_t(strobe); - strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; - P_AddThinker (&strobe->thinker); - break; - - case tc_glow: - saveg_read_pad(); - glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); - saveg_read_glow_t(glow); - glow->thinker.function.acp1 = (actionf_p1)T_Glow; - P_AddThinker (&glow->thinker); - break; - - default: - I_Error ("P_UnarchiveSpecials:Unknown tclass %i " - "in savegame",tclass); - } - - } + tclass = saveg_read8(); + switch (tclass) + { + case tc_endspecials: + return; /* end of list */ + + case tc_ceiling: + saveg_read_pad(); + ceiling = z_malloc(sizeof(*ceiling), PU_LEVEL, NULL); + saveg_read_ceiling_t(ceiling); + ceiling->sector->specialdata = ceiling; + + if (ceiling->thinker.function.acp1) + ceiling->thinker.function.acp1 = (actionf_p1)t_move_ceiling; + + p_add_thinker(&ceiling->thinker); + p_add_active_ceiling(ceiling); + break; + + case tc_door: + saveg_read_pad(); + door = z_malloc(sizeof(*door), PU_LEVEL, NULL); + saveg_read_vldoor_t(door); + door->sector->specialdata = door; + door->thinker.function.acp1 = (actionf_p1)t_vertical_door; + p_add_thinker(&door->thinker); + break; + + case tc_floor: + saveg_read_pad(); + floor = z_malloc(sizeof(*floor), PU_LEVEL, NULL); + saveg_read_floormove_t(floor); + floor->sector->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)t_move_floor; + p_add_thinker(&floor->thinker); + break; + + case tc_plat: + saveg_read_pad(); + plat = z_malloc(sizeof(*plat), PU_LEVEL, NULL); + saveg_read_plat_t(plat); + plat->sector->specialdata = plat; + + if (plat->thinker.function.acp1) + plat->thinker.function.acp1 = (actionf_p1)t_plat_raise; + + p_add_thinker(&plat->thinker); + p_add_active_plat(plat); + break; + + case tc_flash: + saveg_read_pad(); + flash = z_malloc(sizeof(*flash), PU_LEVEL, NULL); + saveg_read_lightflash_t(flash); + flash->thinker.function.acp1 = (actionf_p1)t_light_flash; + p_add_thinker(&flash->thinker); + break; + + case tc_strobe: + saveg_read_pad(); + strobe = z_malloc(sizeof(*strobe), PU_LEVEL, NULL); + saveg_read_strobe_t(strobe); + strobe->thinker.function.acp1 = (actionf_p1)t_strobe_flash; + p_add_thinker(&strobe->thinker); + break; + + case tc_glow: + saveg_read_pad(); + glow = z_malloc(sizeof(*glow), PU_LEVEL, NULL); + saveg_read_glow_t(glow); + glow->thinker.function.acp1 = (actionf_p1)t_glow; + p_add_thinker(&glow->thinker); + break; + + default: + i_error("P_UnarchiveSpecials:Unknown tclass %i " + "in savegame", + tclass); + } + } } - diff --git a/games/NXDoom/src/doom/p_saveg.h b/games/NXDoom/src/doom/p_saveg.h index 518a5b70658..8c27b6dc745 100644 --- a/games/NXDoom/src/doom/p_saveg.h +++ b/games/NXDoom/src/doom/p_saveg.h @@ -1,65 +1,86 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Savegame I/O, archiving, persistence. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_saveg.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Savegame I/O, archiving, persistence. + * + ****************************************************************************/ #ifndef __P_SAVEG__ #define __P_SAVEG__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define SAVEGAME_EOF 0x1d #define VERSIONSIZE 16 -// maximum size of a savegame description +/* maximum size of a savegame description */ #define SAVESTRINGSIZE 24 -// temporary filename to use while saving. +/**************************************************************************** + * Public Data + ****************************************************************************/ -char *P_TempSaveGameFile(void); +extern FILE *save_stream; +extern boolean savegame_error; -// filename to use for a savegame slot +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -char *P_SaveGameFile(int slot); +/* temporary filename to use while saving. */ -// Savegame file header read/write functions +char *p_temp_save_game_file(void); -boolean P_ReadSaveGameHeader(void); -void P_WriteSaveGameHeader(char *description); +/* filename to use for a savegame slot */ -// Savegame end-of-file read/write functions +char *p_save_game_file(int slot); -boolean P_ReadSaveGameEOF(void); -void P_WriteSaveGameEOF(void); +/* Savegame file header read/write functions */ -// Persistent storage/archiving. -// These are the load / save game routines. -void P_ArchivePlayers (void); -void P_UnArchivePlayers (void); -void P_ArchiveWorld (void); -void P_UnArchiveWorld (void); -void P_ArchiveThinkers (void); -void P_UnArchiveThinkers (void); -void P_ArchiveSpecials (void); -void P_UnArchiveSpecials (void); +boolean p_read_save_game_header(void); +void p_write_save_game_header(char *description); -extern FILE *save_stream; -extern boolean savegame_error; +/* Savegame end-of-file read/write functions */ + +boolean p_read_save_game_eof(void); +void p_write_save_game_eof(void); + +/* Persistent storage/archiving. + * These are the load / save game routines. + */ +void p_archive_players(void); +void p_unarchive_players(void); +void p_archive_world(void); +void p_unarchive_world(void); +void p_archive_thinkers(void); +void p_unarchive_thinkers(void); +void p_archive_specials(void); +void p_unarchive_specials(void); -#endif +#endif /* __P_SAVEG__ */ diff --git a/games/NXDoom/src/doom/p_setup.c b/games/NXDoom/src/doom/p_setup.c index fbb1a180d53..3dc608abf23 100644 --- a/games/NXDoom/src/doom/p_setup.c +++ b/games/NXDoom/src/doom/p_setup.c @@ -1,23 +1,30 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Do all the WAD I/O, get map description, -// set up initial state and misc. LUTs. -// - - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_setup.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Do all the WAD I/O, get map description, set up initial state and misc. + * LUTs. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -38,796 +45,790 @@ #include "p_local.h" #include "p_rejectpad.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#endif #include "doomstat.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Maintain single and multi player starting spots. */ + +#define MAX_DEATHMATCH_STARTS 10 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void p_spawn_map_thing(mapthing_t *mthing); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int totallines; -void P_SpawnMapThing (mapthing_t* mthing); +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* MAP related Lookup tables. + * Store VERTICES, LINEDEFS, SIDEDEFS, etc. + */ -// -// MAP related Lookup tables. -// Store VERTEXES, LINEDEFS, SIDEDEFS, etc. -// -int numvertexes; -vertex_t* vertexes; +int numvertices; +vertex_t *vertices; -int numsegs; -seg_t* segs; +int numsegs; +seg_t *segs; -int numsectors; -sector_t* sectors; +int numsectors; +sector_t *sectors; -int numsubsectors; -subsector_t* subsectors; +int numsubsectors; +subsector_t *subsectors; -int numnodes; -node_t* nodes; +int numnodes; +node_t *nodes; -int numlines; -line_t* lines; +int numlines; +line_t *lines; -int numsides; -side_t* sides; +int numsides; +side_t *sides; -static int totallines; +/* BLOCKMAP + * Created from axis aligned bounding box + * of the map, a rectangular array of + * blocks of size ... + * Used to speed up collision detection + * by spatial subdivision in 2D. + */ -// BLOCKMAP -// Created from axis aligned bounding box -// of the map, a rectangular array of -// blocks of size ... -// Used to speed up collision detection -// by spatial subdivision in 2D. -// -// Blockmap size. -int bmapwidth; -int bmapheight; // size in mapblocks -short* blockmap; // int for larger maps -// offsets in blockmap are from here -short* blockmaplump; -// origin of block map -fixed_t bmaporgx; -fixed_t bmaporgy; -// for thing chains -mobj_t** blocklinks; +/* Blockmap size. */ +int bmapwidth; +int bmapheight; /* size in mapblocks */ +short *blockmap; /* int for larger maps */ -// REJECT -// For fast sight rejection. -// Speeds up enemy AI by skipping detailed -// LineOf Sight calculation. -// Without special effect, this could be -// used as a PVS lookup as well. -// -byte* rejectmatrix; +/* offsets in blockmap are from here */ +short *blockmaplump; -// Maintain single and multi player starting spots. -#define MAX_DEATHMATCH_STARTS 10 +/* origin of block map */ -mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS]; -mapthing_t* deathmatch_p; -mapthing_t playerstarts[MAXPLAYERS]; -boolean playerstartsingame[MAXPLAYERS]; +fixed_t bmaporgx; +fixed_t bmaporgy; +/* for thing chains */ +mobj_t **blocklinks; +/* REJECT + * For fast sight rejection. + * Speeds up enemy AI by skipping detailed LineOf Sight calculation. + * Without special effect, this could be used as a PVS lookup as well. + */ +byte *rejectmatrix; -// -// P_LoadVertexes -// -void P_LoadVertexes (int lump) +mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS]; +mapthing_t *deathmatch_p; +mapthing_t playerstarts[MAXPLAYERS]; +boolean playerstartsingame[MAXPLAYERS]; + +/* pointer to the current map lump info struct */ + +lumpinfo_t *maplumpinfo; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void p_load_vertices(int lump) { - byte* data; - int i; - mapvertex_t* ml; - vertex_t* li; - - // Determine number of lumps: - // total lump length / vertex record length. - numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t); - - // Allocate zone memory for buffer. - vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0); - - // Load data into cache. - data = W_CacheLumpNum (lump, PU_STATIC); - - ml = (mapvertex_t *)data; - li = vertexes; - - // Copy and convert vertex coordinates, - // internal representation as fixed. - for (i=0 ; ix = SHORT(ml->x)<y = SHORT(ml->y)<x = SHORT(ml->x) << FRACBITS; + li->y = SHORT(ml->y) << FRACBITS; } - // Free buffer memory. - W_ReleaseLumpNum(lump); + /* Free buffer memory. */ + + w_release_lump_num(lump); } -// -// GetSectorAtNullAddress -// -sector_t* GetSectorAtNullAddress(void) +static sector_t *get_sector_at_null_address(void) { - static boolean null_sector_is_initialized = false; - static sector_t null_sector; + static boolean null_sector_is_initialized = false; + static sector_t null_sector; - if (!null_sector_is_initialized) + if (!null_sector_is_initialized) { - memset(&null_sector, 0, sizeof(null_sector)); - I_GetMemoryValue(0, &null_sector.floorheight, 4); - I_GetMemoryValue(4, &null_sector.ceilingheight, 4); - null_sector_is_initialized = true; + memset(&null_sector, 0, sizeof(null_sector)); + i_get_memory_value(0, &null_sector.floorheight, 4); + i_get_memory_value(4, &null_sector.ceilingheight, 4); + null_sector_is_initialized = true; } - return &null_sector; + return &null_sector; } -// -// P_LoadSegs -// -void P_LoadSegs (int lump) +static void p_load_segs(int lump) { - byte* data; - int i; - mapseg_t* ml; - seg_t* li; - line_t* ldef; - int linedef; - int side; - int sidenum; - - numsegs = W_LumpLength (lump) / sizeof(mapseg_t); - segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0); - memset (segs, 0, numsegs*sizeof(seg_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - ml = (mapseg_t *)data; - li = segs; - for (i=0 ; iv1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; - - li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - side = SHORT(ml->side); - - // e6y: check for wrong indexes - if ((unsigned)ldef->sidenum[side] >= (unsigned)numsides) + li->v1 = &vertices[SHORT(ml->v1)]; + li->v2 = &vertices[SHORT(ml->v2)]; + + li->angle = (SHORT(ml->angle)) << FRACBITS; + li->offset = (SHORT(ml->offset)) << FRACBITS; + linedef_int = SHORT(ml->linedef); + ldef = &lines[linedef_int]; + li->linedef = ldef; + side = SHORT(ml->side); + + /* e6y: check for wrong indexes */ + + if ((unsigned)ldef->sidenum[side] >= (unsigned)numsides) { - I_Error("P_LoadSegs: linedef %d for seg %d references a non-existent sidedef %d", - linedef, i, (unsigned)ldef->sidenum[side]); + i_error("p_load_segs: linedef %d for seg %d references a " + "non-existent sidedef %d", + linedef_int, i, (unsigned)ldef->sidenum[side]); } - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef-> flags & ML_TWOSIDED) + if (ldef->flags & ML_TWOSIDED) { - sidenum = ldef->sidenum[side ^ 1]; + sidenum = ldef->sidenum[side ^ 1]; - // If the sidenum is out of range, this may be a "glass hack" - // impassible window. Point at side #0 (this may not be - // the correct Vanilla behavior; however, it seems to work for - // OTTAWAU.WAD, which is the one place I've seen this trick - // used). + /* If the sidenum is out of range, this may be a "glass hack" + * impassable window. Point at side #0 (this may not be + * the correct Vanilla behavior; however, it seems to work for + * OTTAWAU.WAD, which is the one place I've seen this trick + * used). + */ - if (sidenum < 0 || sidenum >= numsides) + if (sidenum < 0 || sidenum >= numsides) { - li->backsector = GetSectorAtNullAddress(); + li->backsector = get_sector_at_null_address(); } - else + else { - li->backsector = sides[sidenum].sector; + li->backsector = sides[sidenum].sector; } } - else + else { - li->backsector = 0; + li->backsector = 0; } } - - W_ReleaseLumpNum(lump); -} + w_release_lump_num(lump); +} -// -// P_LoadSubsectors -// -void P_LoadSubsectors (int lump) +static void p_load_subsectors(int lump) { - byte* data; - int i; - mapsubsector_t* ms; - subsector_t* ss; - - numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t); - subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0); - data = W_CacheLumpNum (lump,PU_STATIC); - - ms = (mapsubsector_t *)data; - memset (subsectors,0, numsubsectors*sizeof(subsector_t)); - ss = subsectors; - - for (i=0 ; inumlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); + ss->numlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); } - - W_ReleaseLumpNum(lump); -} - + w_release_lump_num(lump); +} -// -// P_LoadSectors -// -void P_LoadSectors (int lump) +static void p_load_sectors(int lump) { - byte* data; - int i; - mapsector_t* ms; - sector_t* ss; - - numsectors = W_LumpLength (lump) / sizeof(mapsector_t); - sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0); - memset (sectors, 0, numsectors*sizeof(sector_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - ms = (mapsector_t *)data; - ss = sectors; - for (i=0 ; ifloorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = R_FlatNumForName(ms->floorpic); - ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); - ss->lightlevel = SHORT(ms->lightlevel); - ss->special = SHORT(ms->special); - ss->tag = SHORT(ms->tag); - ss->thinglist = NULL; + ss->floorheight = SHORT(ms->floorheight) << FRACBITS; + ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS; + ss->floorpic = r_flat_num_for_name(ms->floorpic); + ss->ceilingpic = r_flat_num_for_name(ms->ceilingpic); + ss->lightlevel = SHORT(ms->lightlevel); + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + ss->thinglist = NULL; } - - W_ReleaseLumpNum(lump); -} + w_release_lump_num(lump); +} -// -// P_LoadNodes -// -void P_LoadNodes (int lump) +static void p_load_nodes(int lump) { - byte* data; - int i; - int j; - int k; - mapnode_t* mn; - node_t* no; - - numnodes = W_LumpLength (lump) / sizeof(mapnode_t); - nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0); - data = W_CacheLumpNum (lump,PU_STATIC); - - mn = (mapnode_t *)data; - no = nodes; - - for (i=0 ; ix = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); - for (k=0 ; k<4 ; k++) - no->bbox[j][k] = SHORT(mn->bbox[j][k])<x = SHORT(mn->x) << FRACBITS; + no->y = SHORT(mn->y) << FRACBITS; + no->dx = SHORT(mn->dx) << FRACBITS; + no->dy = SHORT(mn->dy) << FRACBITS; + for (j = 0; j < 2; j++) + { + no->children[j] = SHORT(mn->children[j]); + for (k = 0; k < 4; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; + } } - - W_ReleaseLumpNum(lump); -} + w_release_lump_num(lump); +} -// -// P_LoadThings -// -void P_LoadThings (int lump) +static void p_load_things(int lump) { - byte *data; - int i; - mapthing_t *mt; - mapthing_t spawnthing; - int numthings; - boolean spawn; - - data = W_CacheLumpNum (lump,PU_STATIC); - numthings = W_LumpLength (lump) / sizeof(mapthing_t); - - mt = (mapthing_t *)data; - for (i=0 ; itype)) - { - case 68: // Arachnotron - case 64: // Archvile - case 88: // Boss Brain - case 89: // Boss Shooter - case 69: // Hell Knight - case 67: // Mancubus - case 71: // Pain Elemental - case 65: // Former Human Commando - case 66: // Revenant - case 84: // Wolf SS - spawn = false; - break; - } - } - if (spawn == false) - break; - - // Do spawn all other stuff. - spawnthing.x = SHORT(mt->x); - spawnthing.y = SHORT(mt->y); - spawnthing.angle = SHORT(mt->angle); - spawnthing.type = SHORT(mt->type); - spawnthing.options = SHORT(mt->options); - - P_SpawnMapThing(&spawnthing); + spawn = true; + + /* Do not spawn cool, new monsters if !commercial */ + + if (gamemode != commercial) + { + switch (SHORT(mt->type)) + { + case 68: /* Arachnotron */ + case 64: /* Archvile */ + case 88: /* Boss Brain */ + case 89: /* Boss Shooter */ + case 69: /* Hell Knight */ + case 67: /* Mancubus */ + case 71: /* Pain Elemental */ + case 65: /* Former Human Commando */ + case 66: /* Revenant */ + case 84: /* Wolf SS */ + spawn = false; + break; + } + } + + if (spawn == false) break; + + /* Do spawn all other stuff. */ + + spawnthing.x = SHORT(mt->x); + spawnthing.y = SHORT(mt->y); + spawnthing.angle = SHORT(mt->angle); + spawnthing.type = SHORT(mt->type); + spawnthing.options = SHORT(mt->options); + + p_spawn_map_thing(&spawnthing); } - if (!deathmatch) + if (!deathmatch) { - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !playerstartsingame[i]) + if (playeringame[i] && !playerstartsingame[i]) { - I_Error("P_LoadThings: Player %d start missing (vanilla crashes here)", i + 1); + i_error("p_load_things: Player %d start missing (vanilla " + "crashes here)", + i + 1); } - playerstartsingame[i] = false; + + playerstartsingame[i] = false; } } - W_ReleaseLumpNum(lump); + w_release_lump_num(lump); } +/* p_load_linedefs + * Also counts secret lines for intermissions. + */ -// -// P_LoadLineDefs -// Also counts secret lines for intermissions. -// -void P_LoadLineDefs (int lump) +static void p_load_linedefs(int lump) { - byte* data; - int i; - maplinedef_t* mld; - line_t* ld; - vertex_t* v1; - vertex_t* v2; - - numlines = W_LumpLength (lump) / sizeof(maplinedef_t); - lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0); - memset (lines, 0, numlines*sizeof(line_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - mld = (maplinedef_t *)data; - ld = lines; - for (i=0 ; iflags = SHORT(mld->flags); - ld->special = SHORT(mld->special); - ld->tag = SHORT(mld->tag); - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else - { - if (FixedDiv (ld->dy , ld->dx) > 0) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - } - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - - if (ld->sidenum[0] != -1) - ld->frontsector = sides[ld->sidenum[0]].sector; - else - ld->frontsector = 0; - - if (ld->sidenum[1] != -1) - ld->backsector = sides[ld->sidenum[1]].sector; - else - ld->backsector = 0; + ld->flags = SHORT(mld->flags); + ld->special = SHORT(mld->special); + ld->tag = SHORT(mld->tag); + v1 = ld->v1 = &vertices[SHORT(mld->v1)]; + v2 = ld->v2 = &vertices[SHORT(mld->v2)]; + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else + { + if (fixed_div(ld->dy, ld->dx) > 0) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + } + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + + if (ld->sidenum[0] != -1) + ld->frontsector = sides[ld->sidenum[0]].sector; + else + ld->frontsector = 0; + + if (ld->sidenum[1] != -1) + ld->backsector = sides[ld->sidenum[1]].sector; + else + ld->backsector = 0; } - W_ReleaseLumpNum(lump); + w_release_lump_num(lump); } - -// -// P_LoadSideDefs -// -void P_LoadSideDefs (int lump) +static void p_load_side_defs(int lump) { - byte* data; - int i; - mapsidedef_t* msd; - side_t* sd; - - numsides = W_LumpLength (lump) / sizeof(mapsidedef_t); - sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0); - memset (sides, 0, numsides*sizeof(side_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - msd = (mapsidedef_t *)data; - sd = sides; - for (i=0 ; itextureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<toptexture = R_TextureNumForName(msd->toptexture); - sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); - sd->midtexture = R_TextureNumForName(msd->midtexture); - sd->sector = §ors[SHORT(msd->sector)]; + sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS; + sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS; + sd->toptexture = r_texture_num_for_name(msd->toptexture); + sd->bottomtexture = r_texture_num_for_name(msd->bottomtexture); + sd->midtexture = r_texture_num_for_name(msd->midtexture); + sd->sector = §ors[SHORT(msd->sector)]; } - W_ReleaseLumpNum(lump); + w_release_lump_num(lump); } - -// -// P_LoadBlockMap -// -void P_LoadBlockMap (int lump) +static void p_load_block_map(int lump) { - int i; - int count; - int lumplen; - - lumplen = W_LumpLength(lump); - count = lumplen / 2; - - blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); - W_ReadLump(lump, blockmaplump); - blockmap = blockmaplump + 4; - - // Swap all short integers to native byte ordering. - - for (i=0; ifirstline]; - ss->sector = seg->sidedef->sector; + seg = &segs[ss->firstline]; + ss->sector = seg->sidedef->sector; } - // count number of lines in each sector - li = lines; - totallines = 0; - for (i=0 ; ifrontsector->linecount++; - - if (li->backsector && li->backsector != li->frontsector) - { - li->backsector->linecount++; - totallines++; - } + totallines++; + li->frontsector->linecount++; + + if (li->backsector && li->backsector != li->frontsector) + { + li->backsector->linecount++; + totallines++; + } } - // build line tables for each sector - linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0); + /* build line tables for each sector */ + + linebuffer = z_malloc(totallines * sizeof(line_t *), PU_LEVEL, 0); - for (i=0; ifrontsector != NULL) + if (li->frontsector != NULL) { - sector = li->frontsector; + sector = li->frontsector; - sector->lines[sector->linecount] = li; - ++sector->linecount; + sector->lines[sector->linecount] = li; + ++sector->linecount; } - if (li->backsector != NULL && li->frontsector != li->backsector) + if (li->backsector != NULL && li->frontsector != li->backsector) { - sector = li->backsector; + sector = li->backsector; - sector->lines[sector->linecount] = li; - ++sector->linecount; + sector->lines[sector->linecount] = li; + ++sector->linecount; } } - - // Generate bounding boxes for sectors - - sector = sectors; - for (i=0 ; ilinecount; j++) - { - li = sector->lines[j]; - - M_AddToBox (bbox, li->v1->x, li->v1->y); - M_AddToBox (bbox, li->v2->x, li->v2->y); - } - - // set the degenmobj_t to the middle of the bounding box - sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2; - sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2; - - // adjust bounding box to map blocks - block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; - block = block >= bmapheight ? bmapheight-1 : block; - sector->blockbox[BOXTOP]=block; - - block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXBOTTOM]=block; - - block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; - block = block >= bmapwidth ? bmapwidth-1 : block; - sector->blockbox[BOXRIGHT]=block; - - block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXLEFT]=block; + m_clear_box(bbox); + + for (j = 0; j < sector->linecount; j++) + { + li = sector->lines[j]; + + m_add_to_box(bbox, li->v1->x, li->v1->y); + m_add_to_box(bbox, li->v2->x, li->v2->y); + } + + /* set the degenmobj_t to the middle of the bounding box */ + + sector->soundorg.x = (bbox[BOXRIGHT] + bbox[BOXLEFT]) / 2; + sector->soundorg.y = (bbox[BOXTOP] + bbox[BOXBOTTOM]) / 2; + + /* adjust bounding box to map blocks */ + + block = (bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + block = block >= bmapheight ? bmapheight - 1 : block; + sector->blockbox[BOXTOP] = block; + + block = (bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXBOTTOM] = block; + + block = (bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; + block = block >= bmapwidth ? bmapwidth - 1 : block; + sector->blockbox[BOXRIGHT] = block; + + block = (bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; + block = block < 0 ? 0 : block; + sector->blockbox[BOXLEFT] = block; } - } - -static void P_LoadReject(int lumpnum) +static void p_load_reject(int lumpnum) { - int minlength; - int lumplen; + int minlength; + int lumplen; - // Calculate the size that the REJECT lump *should* be. + /* Calculate the size that the REJECT lump *should* be. */ - minlength = (numsectors * numsectors + 7) / 8; + minlength = (numsectors * numsectors + 7) / 8; - // If the lump meets the minimum length, it can be loaded directly. - // Otherwise, we need to allocate a buffer of the correct size - // and pad it with appropriate data. + /* If the lump meets the minimum length, it can be loaded directly. + * Otherwise, we need to allocate a buffer of the correct size + * and pad it with appropriate data. + */ - lumplen = W_LumpLength(lumpnum); + lumplen = w_lump_length(lumpnum); - if (lumplen >= minlength) + if (lumplen >= minlength) { - rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); + rejectmatrix = w_cache_lump_num(lumpnum, PU_LEVEL); } - else + else { - rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); - W_ReadLump(lumpnum, rejectmatrix); + rejectmatrix = z_malloc(minlength, PU_LEVEL, &rejectmatrix); + w_read_lump(lumpnum, rejectmatrix); - PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); + pad_reject_array(rejectmatrix + lumplen, minlength - lumplen, + totallines); } } -// pointer to the current map lump info struct -lumpinfo_t *maplumpinfo; +/* p_setup_level */ -// -// P_SetupLevel -// -void -P_SetupLevel -( int episode, - int map, - int playermask, - skill_t skill) +void p_setup_level(int episode, int map, int playermask, skill_t skill) { - int i; - char lumpname[9]; - int lumpnum; - - totalkills = totalitems = totalsecret = wminfo.maxfrags = 0; - wminfo.partime = 180; - for (i=0 ; id.line; - li = in->d.line; + /* crosses a two sided line */ - // - // crosses a two sided line - // - P_LineOpening(li); + p_line_opening(li); - if (openbottom >= opentop) // quick test for totally closed doors - return false; // stop + /* quick test for totally closed doors */ - if (li->frontsector->floorheight != li->backsector->floorheight) + if (openbottom >= opentop) { - slope = FixedDiv(openbottom - sightzstart, in->frac); - if (slope > bottomslope) - bottomslope = slope; + return false; /* stop */ } - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + if (li->frontsector->floorheight != li->backsector->floorheight) { - slope = FixedDiv(opentop - sightzstart, in->frac); - if (slope < topslope) - topslope = slope; + slope = fixed_div(openbottom - sightzstart, in->frac); + if (slope > bottomslope) bottomslope = slope; } - if (topslope <= bottomslope) - return false; // stop + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = fixed_div(opentop - sightzstart, in->frac); + if (slope < topslope) topslope = slope; + } + + if (topslope <= bottomslope) return false; /* stop */ - return true; // keep going + return true; /* keep going */ } +/* p_divline_side + * Returns side 0 (front), 1 (back), or 2 (on). + */ -// -// P_DivlineSide -// Returns side 0 (front), 1 (back), or 2 (on). -// -int -P_DivlineSide -( fixed_t x, - fixed_t y, - divline_t* node ) +static int p_divline_side(fixed_t x, fixed_t y, divline_t *node) { - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; - if (!node->dx) + if (!node->dx) { - if (x==node->x) - return 2; - - if (x <= node->x) - return node->dy > 0; + if (x == node->x) return 2; - return node->dy < 0; + if (x <= node->x) return node->dy > 0; + + return node->dy < 0; } - - if (!node->dy) + + if (!node->dy) { - if (x==node->y) - return 2; + if (x == node->y) return 2; - if (y <= node->y) - return node->dx < 0; + if (y <= node->y) return node->dx < 0; - return node->dx > 0; + return node->dx > 0; } - - dx = (x - node->x); - dy = (y - node->y); - - left = (node->dy>>FRACBITS) * (dx>>FRACBITS); - right = (dy>>FRACBITS) * (node->dx>>FRACBITS); - - if (right < left) - return 0; // front side - - if (left == right) - return 2; - return 1; // back side + + dx = (x - node->x); + dy = (y - node->y); + + left = (node->dy >> FRACBITS) * (dx >> FRACBITS); + right = (dy >> FRACBITS) * (node->dx >> FRACBITS); + + if (right < left) return 0; /* front side */ + + if (left == right) return 2; + return 1; /* back side */ } +/* p_intercept_vector2 + * Returns the fractional intercept point along the first divline. + * This is only called by the addthings and addlines traversers. + */ -// -// P_InterceptVector2 -// Returns the fractional intercept point -// along the first divline. -// This is only called by the addthings and addlines traversers. -// -fixed_t -P_InterceptVector2 -( divline_t* v2, - divline_t* v1 ) +static fixed_t p_intercept_vector2(divline_t *v2, divline_t *v1) { - fixed_t frac; - fixed_t num; - fixed_t den; - - den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); - - if (den == 0) - return 0; - // I_Error ("P_InterceptVector: parallel"); - - num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + - FixedMul ( (v2->y - v1->y)>>8 , v1->dx); - frac = FixedDiv (num , den); - - return frac; + fixed_t frac; + fixed_t num; + fixed_t den; + + den = fixed_mul(v1->dy >> 8, v2->dx) - fixed_mul(v1->dx >> 8, v2->dy); + + if (den == 0) return 0; + + num = fixed_mul((v1->x - v2->x) >> 8, v1->dy) + + fixed_mul((v2->y - v1->y) >> 8, v1->dx); + frac = fixed_div(num, den); + + return frac; } -// -// P_CrossSubsector -// Returns true -// if strace crosses the given subsector successfully. -// -boolean P_CrossSubsector (int num) +/* p_cross_subsector + * Returns true if strace crosses the given subsector successfully. + */ + +static boolean p_cross_subsector(int num) { - seg_t* seg; - line_t* line; - int s1; - int s2; - int count; - subsector_t* sub; - sector_t* front; - sector_t* back; - fixed_t opentop; - fixed_t openbottom; - divline_t divl; - vertex_t* v1; - vertex_t* v2; - fixed_t frac; - fixed_t slope; - -#ifdef RANGECHECK - if (num>=numsubsectors) - I_Error ("P_CrossSubsector: ss %i with numss = %i", - num, - numsubsectors); + seg_t *seg; + line_t *line; + int s1; + int s2; + int count; + subsector_t *sub; + sector_t *front; + sector_t *back; + fixed_t l_opentop; + fixed_t l_openbottom; + divline_t divl; + vertex_t *v1; + vertex_t *v2; + fixed_t frac; + fixed_t slope; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (num >= numsubsectors) + i_error("p_cross_subsector: ss %i with numss = %i", num, numsubsectors); #endif - sub = &subsectors[num]; - - // check lines - count = sub->numlines; - seg = &segs[sub->firstline]; + sub = &subsectors[num]; + + /* check lines */ - for ( ; count ; seg++, count--) + count = sub->numlines; + seg = &segs[sub->firstline]; + + for (; count; seg++, count--) { - line = seg->linedef; - - // allready checked other side? - if (line->validcount == validcount) - continue; - - line->validcount = validcount; - - v1 = line->v1; - v2 = line->v2; - s1 = P_DivlineSide (v1->x,v1->y, &strace); - s2 = P_DivlineSide (v2->x, v2->y, &strace); - - // line isn't crossed? - if (s1 == s2) - continue; - - divl.x = v1->x; - divl.y = v1->y; - divl.dx = v2->x - v1->x; - divl.dy = v2->y - v1->y; - s1 = P_DivlineSide (strace.x, strace.y, &divl); - s2 = P_DivlineSide (t2x, t2y, &divl); - - // line isn't crossed? - if (s1 == s2) - continue; - - // Backsector may be NULL if this is an "impassible - // glass" hack line. - - if (line->backsector == NULL) + line = seg->linedef; + + /* already checked other side? */ + + if (line->validcount == validcount) continue; + + line->validcount = validcount; + + v1 = line->v1; + v2 = line->v2; + s1 = p_divline_side(v1->x, v1->y, &strace); + s2 = p_divline_side(v2->x, v2->y, &strace); + + /* line isn't crossed? */ + + if (s1 == s2) continue; + + divl.x = v1->x; + divl.y = v1->y; + divl.dx = v2->x - v1->x; + divl.dy = v2->y - v1->y; + s1 = p_divline_side(strace.x, strace.y, &divl); + s2 = p_divline_side(t2x, t2y, &divl); + + /* line isn't crossed? */ + + if (s1 == s2) continue; + + /* Backsector may be NULL if this is an "impassable + * glass" hack line. + */ + + if (line->backsector == NULL) { - return false; + return false; } - // stop because it is not two sided anyway - // might do this after updating validcount? - if ( !(line->flags & ML_TWOSIDED) ) - return false; - - // crosses a two sided line - front = seg->frontsector; - back = seg->backsector; - - // no wall to block sight with? - if (front->floorheight == back->floorheight - && front->ceilingheight == back->ceilingheight) - continue; - - // possible occluder - // because of ceiling height differences - if (front->ceilingheight < back->ceilingheight) - opentop = front->ceilingheight; - else - opentop = back->ceilingheight; - - // because of ceiling height differences - if (front->floorheight > back->floorheight) - openbottom = front->floorheight; - else - openbottom = back->floorheight; - - // quick test for totally closed doors - if (openbottom >= opentop) - return false; // stop - - frac = P_InterceptVector2 (&strace, &divl); - - if (front->floorheight != back->floorheight) - { - slope = FixedDiv (openbottom - sightzstart , frac); - if (slope > bottomslope) - bottomslope = slope; - } - - if (front->ceilingheight != back->ceilingheight) - { - slope = FixedDiv (opentop - sightzstart , frac); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop + /* stop because it is not two sided anyway + * might do this after updating validcount? + */ + + if (!(line->flags & ML_TWOSIDED)) return false; + + /* crosses a two sided line */ + + front = seg->frontsector; + back = seg->backsector; + + /* no wall to block sight with? */ + + if (front->floorheight == back->floorheight && + front->ceilingheight == back->ceilingheight) + continue; + + /* possible occluder + * because of ceiling height differences + */ + + if (front->ceilingheight < back->ceilingheight) + l_opentop = front->ceilingheight; + else + l_opentop = back->ceilingheight; + + /* because of ceiling height differences */ + + if (front->floorheight > back->floorheight) + l_openbottom = front->floorheight; + else + l_openbottom = back->floorheight; + + /* quick test for totally closed doors */ + + if (l_openbottom >= l_opentop) return false; /* stop */ + + frac = p_intercept_vector2(&strace, &divl); + + if (front->floorheight != back->floorheight) + { + slope = fixed_div(l_openbottom - sightzstart, frac); + if (slope > bottomslope) bottomslope = slope; + } + + if (front->ceilingheight != back->ceilingheight) + { + slope = fixed_div(l_opentop - sightzstart, frac); + if (slope < topslope) topslope = slope; + } + + if (topslope <= bottomslope) return false; /* stop */ } - // passed the subsector ok - return true; -} + /* passed the subsector ok */ + return true; +} + +/* p_cross_bsp_node + * Returns true if strace crosses the given node successfully. + */ -// -// P_CrossBSPNode -// Returns true -// if strace crosses the given node successfully. -// -boolean P_CrossBSPNode (int bspnum) +static boolean p_cross_bsp_node(int bspnum) { - node_t* bsp; - int side; + node_t *bsp; + int side; - if (bspnum & NF_SUBSECTOR) + if (bspnum & NF_SUBSECTOR) { - if (bspnum == -1) - return P_CrossSubsector (0); - else - return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); + if (bspnum == -1) + { + return p_cross_subsector(0); + } + else + { + return p_cross_subsector(bspnum & (~NF_SUBSECTOR)); + } } - - bsp = &nodes[bspnum]; - - // decide which side the start point is on - side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp); - if (side == 2) - side = 0; // an "on" should cross both sides - - // cross the starting side - if (!P_CrossBSPNode (bsp->children[side]) ) - return false; - - // the partition plane is crossed here - if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp)) + + bsp = &nodes[bspnum]; + + /* decide which side the start point is on */ + + side = p_divline_side(strace.x, strace.y, (divline_t *)bsp); + if (side == 2) side = 0; /* an "on" should cross both sides */ + + /* cross the starting side */ + + if (!p_cross_bsp_node(bsp->children[side])) return false; + + /* the partition plane is crossed here */ + + if (side == p_divline_side(t2x, t2y, (divline_t *)bsp)) { - // the line doesn't touch the other side - return true; + /* the line doesn't touch the other side */ + + return true; } - - // cross the ending side - return P_CrossBSPNode (bsp->children[side^1]); + + /* cross the ending side */ + + return p_cross_bsp_node(bsp->children[side ^ 1]); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* p_check_sight + * Returns true if a straight line between t1 and t2 is unobstructed. + * Uses REJECT. + */ -// -// P_CheckSight -// Returns true -// if a straight line between t1 and t2 is unobstructed. -// Uses REJECT. -// -boolean -P_CheckSight -( mobj_t* t1, - mobj_t* t2 ) +boolean p_check_sight(mobj_t *t1, mobj_t *t2) { - int s1; - int s2; - int pnum; - int bytenum; - int bitnum; - - // First check for trivial rejection. - - // Determine subsector entries in REJECT table. - s1 = (t1->subsector->sector - sectors); - s2 = (t2->subsector->sector - sectors); - pnum = s1*numsectors + s2; - bytenum = pnum>>3; - bitnum = 1 << (pnum&7); - - // Check in REJECT table. - if (rejectmatrix[bytenum]&bitnum) + int s1; + int s2; + int pnum; + int bytenum; + int bitnum; + + /* First check for trivial rejection. */ + + /* Determine subsector entries in REJECT table. */ + + s1 = (t1->subsector->sector - sectors); + s2 = (t2->subsector->sector - sectors); + pnum = s1 * numsectors + s2; + bytenum = pnum >> 3; + bitnum = 1 << (pnum & 7); + + /* Check in REJECT table. */ + + if (rejectmatrix[bytenum] & bitnum) { - sightcounts[0]++; + sightcounts[0]++; + + /* can't possibly be connected */ - // can't possibly be connected - return false; + return false; } - // An unobstructed LOS is possible. - // Now look from eyes of t1 to any part of t2. - sightcounts[1]++; - - validcount++; - - sightzstart = t1->z + t1->height - (t1->height>>2); - topslope = (t2->z+t2->height) - sightzstart; - bottomslope = (t2->z) - sightzstart; - - if (gameversion <= exe_doom_1_2) + /* An unobstructed LOS is possible. + * Now look from eyes of t1 to any part of t2. + */ + + sightcounts[1]++; + + validcount++; + + sightzstart = t1->z + t1->height - (t1->height >> 2); + topslope = (t2->z + t2->height) - sightzstart; + bottomslope = (t2->z) - sightzstart; + + if (gameversion <= exe_doom_1_2) { - return P_PathTraverse(t1->x, t1->y, t2->x, t2->y, - PT_EARLYOUT | PT_ADDLINES, PTR_SightTraverse); + return p_path_traverse(t1->x, t1->y, t2->x, t2->y, + PT_EARLYOUT | PT_ADDLINES, + ptr_sight_traverse); } - strace.x = t1->x; - strace.y = t1->y; - t2x = t2->x; - t2y = t2->y; - strace.dx = t2->x - t1->x; - strace.dy = t2->y - t1->y; - - // the head node is the last node output - return P_CrossBSPNode (numnodes-1); -} + strace.x = t1->x; + strace.y = t1->y; + t2x = t2->x; + t2y = t2->y; + strace.dx = t2->x - t1->x; + strace.dy = t2->y - t1->y; + /* the head node is the last node output */ + return p_cross_bsp_node(numnodes - 1); +} diff --git a/games/NXDoom/src/doom/p_spec.c b/games/NXDoom/src/doom/p_spec.c index 8d890ce2e64..2b095210d11 100644 --- a/games/NXDoom/src/doom/p_spec.c +++ b/games/NXDoom/src/doom/p_spec.c @@ -1,25 +1,32 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Implements special effects: -// Texture animation, height or lighting changes -// according to adjacent sectors, respective -// utility functions, etc. -// Line Tag handling. Line and Sector triggers. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_spec.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Implements special effects: + * Texture animation, height or lighting changes according to adjacent + * sectors, respective utility functions, etc. + * Line Tag handling. Line and Sector triggers. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -28,1492 +35,1342 @@ #include "deh_main.h" #include "i_system.h" -#include "z_zone.h" #include "m_argv.h" #include "m_misc.h" #include "m_random.h" #include "w_wad.h" +#include "z_zone.h" -#include "r_local.h" #include "p_local.h" +#include "r_local.h" #include "g_game.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* State. */ -// State. #include "r_state.h" -// Data. -#include "sounds.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAXANIMS 32 + +/* Animating line specials */ + +#define MAXLINEANIMS 64 + +/* version <= 1.2 did not have a limit and could handle up to 66 scrolling + * linedefs before displaying adverse effects. All other versions have a + * limit of 64. + */ + +#define MAXLINEANIMS1_2 66 + +/* Thanks to entryway for the Vanilla overflow emulation. + * 20 adjoining sectors max! + */ +#define MAX_ADJOINING_SECTORS 20 + +/* Donut overrun emulation + * + * Derived from the code from PrBoom+. Thanks go to Andrey Budko (entryway) + * as usual :-) + */ + +#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000 +#define DONUT_FLOORPIC_DEFAULT 0x16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Animating textures and planes + * There is another anim_t used in wi_stuff, unrelated. + */ -// -// Animating textures and planes -// There is another anim_t used in wi_stuff, unrelated. -// typedef struct { - boolean istexture; - int picnum; - int basepic; - int numpics; - int speed; - + boolean istexture; + int picnum; + int basepic; + int numpics; + int speed; } anim_t; -// -// source animation definition -// +/* source animation definition */ + typedef struct { - int istexture; // if false, it is a flat - char endname[9]; - char startname[9]; - int speed; + int istexture; /* if false, it is a flat */ + char endname[9]; + char startname[9]; + int speed; } animdef_t; +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* p_init_pic_anims */ -#define MAXANIMS 32 +/* Floor/ceiling animation sequences, defined by first and last frame, i.e. + * the flat (64x64 tile) name to be used. + * + * The full animation sequence is given using all the flats between the start + * and end entry, in the order found in the WAD file. + */ +static animdef_t g_animdefs[] = +{ + {false, "NUKAGE3", "NUKAGE1", 8}, + {false, "FWATER4", "FWATER1", 8}, + {false, "SWATER4", "SWATER1", 8}, + {false, "LAVA4", "LAVA1", 8}, + {false, "BLOOD3", "BLOOD1", 8}, + {false, "RROCK08", "RROCK05", 8}, /* DOOM II flat animations. */ + {false, "SLIME04", "SLIME01", 8}, + {false, "SLIME08", "SLIME05", 8}, + {false, "SLIME12", "SLIME09", 8}, + {true, "BLODGR4", "BLODGR1", 8}, + {true, "SLADRIP3", "SLADRIP1", 8}, + {true, "BLODRIP4", "BLODRIP1", 8}, + {true, "FIREWALL", "FIREWALA", 8}, + {true, "GSTFONT3", "GSTFONT1", 8}, + {true, "FIRELAVA", "FIRELAV3", 8}, + {true, "FIREMAG3", "FIREMAG1", 8}, + {true, "FIREBLU2", "FIREBLU1", 8}, + {true, "ROCKRED3", "ROCKRED1", 8}, + {true, "BFALL4", "BFALL1", 8}, + {true, "SFALL4", "SFALL1", 8}, + {true, "WFALL4", "WFALL1", 8}, + {true, "DBRAIN4", "DBRAIN1", 8}, + { -1, "", "", 0}, +}; + +static anim_t g_anims[MAXANIMS]; +static anim_t *g_lastanim; + +static short g_numlinespecials; +static line_t *g_linespeciallist[MAXLINEANIMS1_2]; -// -// P_InitPicAnims -// +/* p_update_specials + * Animate planes, scroll walls, etc. + */ -// Floor/ceiling animation sequences, -// defined by first and last frame, -// i.e. the flat (64x64 tile) name to -// be used. -// The full animation sequence is given -// using all the flats between the start -// and end entry, in the order found in -// the WAD file. -// -animdef_t animdefs[] = +static boolean g_level_timer; +static int g_level_time_count; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void donut_overrun(fixed_t *s3_floorheight, short *s3_floorpic, + line_t *line, sector_t *pillar_sector) { - {false, "NUKAGE3", "NUKAGE1", 8}, - {false, "FWATER4", "FWATER1", 8}, - {false, "SWATER4", "SWATER1", 8}, - {false, "LAVA4", "LAVA1", 8}, - {false, "BLOOD3", "BLOOD1", 8}, - - // DOOM II flat animations. - {false, "RROCK08", "RROCK05", 8}, - {false, "SLIME04", "SLIME01", 8}, - {false, "SLIME08", "SLIME05", 8}, - {false, "SLIME12", "SLIME09", 8}, - - {true, "BLODGR4", "BLODGR1", 8}, - {true, "SLADRIP3", "SLADRIP1", 8}, - - {true, "BLODRIP4", "BLODRIP1", 8}, - {true, "FIREWALL", "FIREWALA", 8}, - {true, "GSTFONT3", "GSTFONT1", 8}, - {true, "FIRELAVA", "FIRELAV3", 8}, - {true, "FIREMAG3", "FIREMAG1", 8}, - {true, "FIREBLU2", "FIREBLU1", 8}, - {true, "ROCKRED3", "ROCKRED1", 8}, - - {true, "BFALL4", "BFALL1", 8}, - {true, "SFALL4", "SFALL1", 8}, - {true, "WFALL4", "WFALL1", 8}, - {true, "DBRAIN4", "DBRAIN1", 8}, - - {-1, "", "", 0}, -}; + static int first = 1; + static int tmp_s3_floorheight; + static int tmp_s3_floorpic; -anim_t anims[MAXANIMS]; -anim_t* lastanim; + if (first) + { + int p; + + /* This is the first time we have had an overrun. */ + + first = 0; + + /* Default values */ + tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT; + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; -// -// Animating line specials -// -#define MAXLINEANIMS 64 -// version <= 1.2 did not have a limit and could handle up to 66 scrolling -// linedefs before displaying adverse effects. All other versions have a limit -// of 64. -#define MAXLINEANIMS1_2 66 + /* @category compat + * @arg + * + * Use the specified magic values when emulating behavior caused + * by memory overruns from improperly constructed donuts. + * In Vanilla Doom this can differ depending on the operating + * system. The default (if this option is not specified) is to + * emulate the behavior when running under Windows 98. + */ -short numlinespecials; -line_t *linespeciallist[MAXLINEANIMS1_2]; + p = m_check_parm_with_args("-donut", 2); + + if (p > 0) + { + /* Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008 + * + * C:\>debug + * -d 0:0 + * + * DOS 6.22: + * 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) + * DOS 7.1: + * 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) + * Win98: + * 0000:0000 (00 00 00 00) 65 04 70 00-(16 00) + * DOSBox under XP: + * 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + */ + + m_str_to_int(myargv[p + 1], &tmp_s3_floorheight); + m_str_to_int(myargv[p + 2], &tmp_s3_floorpic); + + if (tmp_s3_floorpic >= numflats) + { + fprintf(stderr, + "DonutOverrun: The second parameter for \"-donut\" " + "switch should be greater than 0 and less than number " + "of flats (%d). Using default value (%d) instead. \n", + numflats, DONUT_FLOORPIC_DEFAULT); + tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + } + } + } + *s3_floorheight = (fixed_t)tmp_s3_floorheight; + *s3_floorpic = (short)tmp_s3_floorpic; +} +/* p_spawn_specials + * After the map has been loaded, scan for specials that spawn thinkers + */ -void P_InitPicAnims (void) +static unsigned int num_scrollers(void) { - int i; + unsigned int i; + unsigned int scrollers = 0; - - // Init animation - lastanim = anims; - for (i=0 ; animdefs[i].istexture != -1 ; i++) + for (i = 0; i < numlines; i++) { - const char *startname, *endname; - - startname = DEH_String(animdefs[i].startname); - endname = DEH_String(animdefs[i].endname); - - if (animdefs[i].istexture) - { - // different episode ? - if (R_CheckTextureNumForName(startname) == -1) - continue; - - lastanim->picnum = R_TextureNumForName(endname); - lastanim->basepic = R_TextureNumForName(startname); - } - else - { - if (W_CheckNumForName(startname) == -1) - continue; - - lastanim->picnum = R_FlatNumForName(endname); - lastanim->basepic = R_FlatNumForName(startname); - } - - lastanim->istexture = animdefs[i].istexture; - lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; - - if (lastanim->numpics < 2) - I_Error ("P_InitPicAnims: bad cycle from %s to %s", - startname, endname); - - lastanim->speed = animdefs[i].speed; - lastanim++; + if (48 == lines[i].special) + { + scrollers++; + } } - + + return scrollers; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ +void p_init_pic_anims(void) +{ + int i; -// -// UTILITIES -// + /* Init animation */ + g_lastanim = g_anims; + for (i = 0; g_animdefs[i].istexture != -1; i++) + { + const char *startname; + const char *endname; + startname = (g_animdefs[i].startname); + endname = (g_animdefs[i].endname); -// -// getSide() -// Will return a side_t* -// given the number of the current sector, -// the line number, and the side (0/1) that you want. -// -side_t* -getSide -( int currentSector, - int line, - int side ) -{ - return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; + if (g_animdefs[i].istexture) + { + /* different episode ? */ + + if (r_check_texture_num_for_name(startname) == -1) continue; + + g_lastanim->picnum = r_texture_num_for_name(endname); + g_lastanim->basepic = r_texture_num_for_name(startname); + } + else + { + if (w_check_num_for_name(startname) == -1) continue; + + g_lastanim->picnum = r_flat_num_for_name(endname); + g_lastanim->basepic = r_flat_num_for_name(startname); + } + + g_lastanim->istexture = g_animdefs[i].istexture; + g_lastanim->numpics = g_lastanim->picnum - g_lastanim->basepic + 1; + + if (g_lastanim->numpics < 2) + i_error("p_init_pic_anims: bad cycle from %s to %s", startname, + endname); + + g_lastanim->speed = g_animdefs[i].speed; + g_lastanim++; + } } +/* UTILITIES */ + +/* get_side() + * Will return a side_t* given the number of the current sector, the line + * number, and the side (0/1) that you want. + */ -// -// getSector() -// Will return a sector_t* -// given the number of the current sector, -// the line number and the side (0/1) that you want. -// -sector_t* -getSector -( int currentSector, - int line, - int side ) +side_t *get_side(int current_sector, int line, int side) { - return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; + return &sides[(sectors[current_sector].lines[line])->sidenum[side]]; } +/* get_sector() + * Will return a sector_t* given the number of the current sector, the line + * number and the side (0/1) that you want. + */ -// -// twoSided() -// Given the sector number and the line number, -// it will tell you whether the line is two-sided or not. -// -int -twoSided -( int sector, - int line ) +sector_t *get_sector(int current_sector, int line, int side) { - return (sectors[sector].lines[line])->flags & ML_TWOSIDED; + return sides[(sectors[current_sector].lines[line])->sidenum[side]].sector; } +/* two_sided() + * Given the sector number and the line number, it will tell you whether the + * line is two-sided or not. + */ +int two_sided(int sector, int line) +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} +/* get_next_sector() + * Return sector_t * of sector next to current. NULL if not two-sided line + */ -// -// getNextSector() -// Return sector_t * of sector next to current. -// NULL if not two-sided line -// -sector_t* -getNextSector -( line_t* line, - sector_t* sec ) +sector_t *get_next_sector(line_t *line, sector_t *sec) { - if (!(line->flags & ML_TWOSIDED)) - return NULL; - - if (line->frontsector == sec) - return line->backsector; - - return line->frontsector; -} + if (!(line->flags & ML_TWOSIDED)) return NULL; + + if (line->frontsector == sec) return line->backsector; + return line->frontsector; +} +/* p_find_lowest_floor_surrounding() + * FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS + */ -// -// P_FindLowestFloorSurrounding() -// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -fixed_t P_FindLowestFloorSurrounding(sector_t* sec) +fixed_t p_find_lowest_floor_surrounding(sector_t *sec) { - int i; - line_t* check; - sector_t* other; - fixed_t floor = sec->floorheight; - - for (i=0 ;i < sec->linecount ; i++) + int i; + line_t *check; + sector_t *other; + fixed_t floor = sec->floorheight; + + for (i = 0; i < sec->linecount; i++) { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->floorheight < floor) - floor = other->floorheight; + check = sec->lines[i]; + other = get_next_sector(check, sec); + + if (!other) continue; + + if (other->floorheight < floor) floor = other->floorheight; } - return floor; -} + return floor; +} +/* p_find_highest_floor_surrounding() + * FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS + */ -// -// P_FindHighestFloorSurrounding() -// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -fixed_t P_FindHighestFloorSurrounding(sector_t *sec) +fixed_t p_find_highest_floor_surrounding(sector_t *sec) { - int i; - line_t* check; - sector_t* other; - fixed_t floor = -500*FRACUNIT; - - for (i=0 ;i < sec->linecount ; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->floorheight > floor) - floor = other->floorheight; - } - return floor; -} + int i; + line_t *check; + sector_t *other; + fixed_t floor = -500 * FRACUNIT; + for (i = 0; i < sec->linecount; i++) + { + check = sec->lines[i]; + other = get_next_sector(check, sec); + if (!other) continue; -// -// P_FindNextHighestFloor -// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS -// Note: this should be doable w/o a fixed array. + if (other->floorheight > floor) floor = other->floorheight; + } -// Thanks to entryway for the Vanilla overflow emulation. + return floor; +} -// 20 adjoining sectors max! -#define MAX_ADJOINING_SECTORS 20 +/* p_find_next_highest_floor + * FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS + * Note: this should be doable w/o a fixed array. + */ -fixed_t -P_FindNextHighestFloor -( sector_t* sec, - int currentheight ) +fixed_t p_find_next_highest_floor(sector_t *sec, int currentheight) { - int i; - int h; - int min; - line_t* check; - sector_t* other; - fixed_t height = currentheight; - fixed_t heightlist[MAX_ADJOINING_SECTORS + 2]; - - for (i=0, h=0; i < sec->linecount; i++) + int i; + int h; + int min; + line_t *check; + sector_t *other; + fixed_t height = currentheight; + fixed_t heightlist[MAX_ADJOINING_SECTORS + 2]; + + for (i = 0, h = 0; i < sec->linecount; i++) { - check = sec->lines[i]; - other = getNextSector(check,sec); + check = sec->lines[i]; + other = get_next_sector(check, sec); - if (!other) - continue; - - if (other->floorheight > height) + if (!other) continue; + + if (other->floorheight > height) { - // Emulation of memory (stack) overflow - if (h == MAX_ADJOINING_SECTORS + 1) + /* Emulation of memory (stack) overflow */ + + if (h == MAX_ADJOINING_SECTORS + 1) { - height = other->floorheight; + height = other->floorheight; } - else if (h == MAX_ADJOINING_SECTORS + 2) + else if (h == MAX_ADJOINING_SECTORS + 2) { - // Fatal overflow: game crashes at 22 sectors - I_Error("Sector with more than 22 adjoining sectors. " - "Vanilla will crash here"); + /* Fatal overflow: game crashes at 22 sectors */ + + i_error("Sector with more than 22 adjoining sectors. " + "Vanilla will crash here"); } - heightlist[h++] = other->floorheight; + heightlist[h++] = other->floorheight; } } - - // Find lowest height in list - if (!h) + + /* Find lowest height in list */ + + if (!h) { - return currentheight; + return currentheight; } - - min = heightlist[0]; - - // Range checking? - for (i = 1; i < h; i++) + + min = heightlist[0]; + + /* Range checking? */ + + for (i = 1; i < h; i++) { - if (heightlist[i] < min) + if (heightlist[i] < min) { - min = heightlist[i]; + min = heightlist[i]; } } - return min; + return min; } -// -// FIND LOWEST CEILING IN THE SURROUNDING SECTORS -// -fixed_t -P_FindLowestCeilingSurrounding(sector_t* sec) +/* FIND LOWEST CEILING IN THE SURROUNDING SECTORS */ + +fixed_t p_find_lowest_ceiling_surrounding(sector_t *sec) { - int i; - line_t* check; - sector_t* other; - fixed_t height = INT_MAX; - - for (i=0 ;i < sec->linecount ; i++) + int i; + line_t *check; + sector_t *other; + fixed_t height = INT_MAX; + + for (i = 0; i < sec->linecount; i++) { - check = sec->lines[i]; - other = getNextSector(check,sec); + check = sec->lines[i]; + other = get_next_sector(check, sec); - if (!other) - continue; + if (!other) continue; - if (other->ceilingheight < height) - height = other->ceilingheight; + if (other->ceilingheight < height) height = other->ceilingheight; } - return height; + + return height; } +/* FIND HIGHEST CEILING IN THE SURROUNDING SECTORS */ -// -// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS -// -fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) +fixed_t p_find_heighest_ceiling_surrounding(sector_t *sec) { - int i; - line_t* check; - sector_t* other; - fixed_t height = 0; - - for (i=0 ;i < sec->linecount ; i++) + int i; + line_t *check; + sector_t *other; + fixed_t height = 0; + + for (i = 0; i < sec->linecount; i++) { - check = sec->lines[i]; - other = getNextSector(check,sec); + check = sec->lines[i]; + other = get_next_sector(check, sec); - if (!other) - continue; + if (!other) continue; - if (other->ceilingheight > height) - height = other->ceilingheight; + if (other->ceilingheight > height) height = other->ceilingheight; } - return height; -} + return height; +} +/* RETURN NEXT SECTOR # THAT LINE TAG REFERS TO */ -// -// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO -// -int -P_FindSectorFromLineTag -( line_t* line, - int start ) +int p_find_sector_from_line_tag(line_t *line, int start) { - int i; - - for (i=start+1;itag) - return i; - - return -1; -} + int i; + for (i = start + 1; i < numsectors; i++) + { + if (sectors[i].tag == line->tag) + { + return i; + } + } + return -1; +} +/* Find minimum light from an adjacent sector */ -// -// Find minimum light from an adjacent sector -// -int -P_FindMinSurroundingLight -( sector_t* sector, - int max ) +int p_find_min_surrounding(sector_t *sector, int max) { - int i; - int min; - line_t* line; - sector_t* check; - - min = max; - for (i=0 ; i < sector->linecount ; i++) + int i; + int min; + line_t *line; + sector_t *check; + + min = max; + for (i = 0; i < sector->linecount; i++) { - line = sector->lines[i]; - check = getNextSector(line,sector); + line = sector->lines[i]; + check = get_next_sector(line, sector); - if (!check) - continue; + if (!check) continue; - if (check->lightlevel < min) - min = check->lightlevel; + if (check->lightlevel < min) min = check->lightlevel; } - return min; -} + return min; +} +/* EVENTS + * Events are operations triggered by using, crossing, + * or shooting special lines, or by timed thinkers. + */ -// -// EVENTS -// Events are operations triggered by using, crossing, -// or shooting special lines, or by timed thinkers. -// +/* p_cross_special_line - TRIGGER + * Called every time a thing origin is about to cross a line with a non 0 + * special. + */ -// -// P_CrossSpecialLine - TRIGGER -// Called every time a thing origin is about -// to cross a line with a non 0 special. -// -void -P_CrossSpecialLine -( int linenum, - int side, - mobj_t* thing ) +void p_cross_special_line(int linenum, int side, mobj_t *thing) { - line_t* line; - int ok; + line_t *line; + int is_ok; - line = &lines[linenum]; - - if (gameversion <= exe_doom_1_2) + line = &lines[linenum]; + + if (gameversion <= exe_doom_1_2) { - if (line->special > 98 && line->special != 104) + if (line->special > 98 && line->special != 104) { - return; + return; } } - else + else { - // Triggers that other things can activate - if (!thing->player) + /* Triggers that other things can activate */ + + if (!thing->player) { - // Things that should NOT trigger specials... - switch(thing->type) + /* Things that should NOT trigger specials... */ + + switch (thing->type) { - case MT_ROCKET: - case MT_PLASMA: - case MT_BFG: - case MT_TROOPSHOT: - case MT_HEADSHOT: - case MT_BRUISERSHOT: - return; - - default: break; + case MT_ROCKET: + case MT_PLASMA: + case MT_BFG: + case MT_TROOPSHOT: + case MT_HEADSHOT: + case MT_BRUISERSHOT: + return; + + default: + break; } } } - if (!thing->player) + if (!thing->player) { - ok = 0; - switch(line->special) - { - case 39: // TELEPORT TRIGGER - case 97: // TELEPORT RETRIGGER - case 125: // TELEPORT MONSTERONLY TRIGGER - case 126: // TELEPORT MONSTERONLY RETRIGGER - case 4: // RAISE DOOR - case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER - case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER - ok = 1; - break; - } - if (!ok) - return; + is_ok = 0; + switch (line->special) + { + case 39: /* TELEPORT TRIGGER */ + case 97: /* TELEPORT RETRIGGER */ + case 125: /* TELEPORT MONSTERONLY TRIGGER */ + case 126: /* TELEPORT MONSTERONLY RETRIGGER */ + case 4: /* RAISE DOOR */ + case 10: /* PLAT DOWN-WAIT-UP-STAY TRIGGER */ + case 88: /* PLAT DOWN-WAIT-UP-STAY RETRIGGER */ + is_ok = 1; + break; + } + + if (!is_ok) return; } - - // Note: could use some const's here. - switch (line->special) + /* Note: could use some const's here. */ + + switch (line->special) { - // TRIGGERS. - // All from here to RETRIGGERS. - case 2: - // Open Door - EV_DoDoor(line,vld_open); - line->special = 0; - break; - - case 3: - // Close Door - EV_DoDoor(line,vld_close); - line->special = 0; - break; - - case 4: - // Raise Door - EV_DoDoor(line,vld_normal); - line->special = 0; - break; - - case 5: - // Raise Floor - EV_DoFloor(line,raiseFloor); - line->special = 0; - break; - - case 6: - // Fast Ceiling Crush & Raise - EV_DoCeiling(line,fastCrushAndRaise); - line->special = 0; - break; - - case 8: - // Build Stairs - EV_BuildStairs(line,build8); - line->special = 0; - break; - - case 10: - // PlatDownWaitUp - EV_DoPlat(line,downWaitUpStay,0); - line->special = 0; - break; - - case 12: - // Light Turn On - brightest near - EV_LightTurnOn(line,0); - line->special = 0; - break; - - case 13: - // Light Turn On 255 - EV_LightTurnOn(line,255); - line->special = 0; - break; - - case 16: - // Close Door 30 - EV_DoDoor(line,vld_close30ThenOpen); - line->special = 0; - break; - - case 17: - // Start Light Strobing - EV_StartLightStrobing(line); - line->special = 0; - break; - - case 19: - // Lower Floor - EV_DoFloor(line,lowerFloor); - line->special = 0; - break; - - case 22: - // Raise floor to nearest height and change texture - EV_DoPlat(line,raiseToNearestAndChange,0); - line->special = 0; - break; - - case 25: - // Ceiling Crush and Raise - EV_DoCeiling(line,crushAndRaise); - line->special = 0; - break; - - case 30: - // Raise floor to shortest texture height - // on either side of lines. - EV_DoFloor(line,raiseToTexture); - line->special = 0; - break; - - case 35: - // Lights Very Dark - EV_LightTurnOn(line,35); - line->special = 0; - break; - - case 36: - // Lower Floor (TURBO) - EV_DoFloor(line,turboLower); - line->special = 0; - break; - - case 37: - // LowerAndChange - EV_DoFloor(line,lowerAndChange); - line->special = 0; - break; - - case 38: - // Lower Floor To Lowest - EV_DoFloor( line, lowerFloorToLowest ); - line->special = 0; - break; - - case 39: - // TELEPORT! - EV_Teleport( line, side, thing ); - line->special = 0; - break; - - case 40: - // RaiseCeilingLowerFloor - EV_DoCeiling( line, raiseToHighest ); - EV_DoFloor( line, lowerFloorToLowest ); - line->special = 0; - break; - - case 44: - // Ceiling Crush - EV_DoCeiling( line, lowerAndCrush ); - line->special = 0; - break; - - case 52: - // EXIT! - G_ExitLevel (); - break; - - case 53: - // Perpetual Platform Raise - EV_DoPlat(line,perpetualRaise,0); - line->special = 0; - break; - - case 54: - // Platform Stop - EV_StopPlat(line); - line->special = 0; - break; - - case 56: - // Raise Floor Crush - EV_DoFloor(line,raiseFloorCrush); - line->special = 0; - break; - - case 57: - // Ceiling Crush Stop - EV_CeilingCrushStop(line); - line->special = 0; - break; - - case 58: - // Raise Floor 24 - EV_DoFloor(line,raiseFloor24); - line->special = 0; - break; - - case 59: - // Raise Floor 24 And Change - EV_DoFloor(line,raiseFloor24AndChange); - line->special = 0; - break; - - case 104: - // Turn lights off in sector(tag) - EV_TurnTagLightsOff(line); - line->special = 0; - break; - - case 108: - // Blazing Door Raise (faster than TURBO!) - EV_DoDoor (line,vld_blazeRaise); - line->special = 0; - break; - - case 109: - // Blazing Door Open (faster than TURBO!) - EV_DoDoor (line,vld_blazeOpen); - line->special = 0; - break; - - case 100: - // Build Stairs Turbo 16 - EV_BuildStairs(line,turbo16); - line->special = 0; - break; - - case 110: - // Blazing Door Close (faster than TURBO!) - EV_DoDoor (line,vld_blazeClose); - line->special = 0; - break; - - case 119: - // Raise floor to nearest surr. floor - EV_DoFloor(line,raiseFloorToNearest); - line->special = 0; - break; - - case 121: - // Blazing PlatDownWaitUpStay - EV_DoPlat(line,blazeDWUS,0); - line->special = 0; - break; - - case 124: - // Secret EXIT - G_SecretExitLevel (); - break; - - case 125: - // TELEPORT MonsterONLY - if (!thing->player) - { - EV_Teleport( line, side, thing ); - line->special = 0; - } - break; - - case 130: - // Raise Floor Turbo - EV_DoFloor(line,raiseFloorTurbo); - line->special = 0; - break; - - case 141: - // Silent Ceiling Crush & Raise - EV_DoCeiling(line,silentCrushAndRaise); - line->special = 0; - break; - - // RETRIGGERS. All from here till end. - case 72: - // Ceiling Crush - EV_DoCeiling( line, lowerAndCrush ); - break; - - case 73: - // Ceiling Crush and Raise - EV_DoCeiling(line,crushAndRaise); - break; - - case 74: - // Ceiling Crush Stop - EV_CeilingCrushStop(line); - break; - - case 75: - // Close Door - EV_DoDoor(line,vld_close); - break; - - case 76: - // Close Door 30 - EV_DoDoor(line,vld_close30ThenOpen); - break; - - case 77: - // Fast Ceiling Crush & Raise - EV_DoCeiling(line,fastCrushAndRaise); - break; - - case 79: - // Lights Very Dark - EV_LightTurnOn(line,35); - break; - - case 80: - // Light Turn On - brightest near - EV_LightTurnOn(line,0); - break; - - case 81: - // Light Turn On 255 - EV_LightTurnOn(line,255); - break; - - case 82: - // Lower Floor To Lowest - EV_DoFloor( line, lowerFloorToLowest ); - break; - - case 83: - // Lower Floor - EV_DoFloor(line,lowerFloor); - break; - - case 84: - // LowerAndChange - EV_DoFloor(line,lowerAndChange); - break; - - case 86: - // Open Door - EV_DoDoor(line,vld_open); - break; - - case 87: - // Perpetual Platform Raise - EV_DoPlat(line,perpetualRaise,0); - break; - - case 88: - // PlatDownWaitUp - EV_DoPlat(line,downWaitUpStay,0); - break; - - case 89: - // Platform Stop - EV_StopPlat(line); - break; - - case 90: - // Raise Door - EV_DoDoor(line,vld_normal); - break; - - case 91: - // Raise Floor - EV_DoFloor(line,raiseFloor); - break; - - case 92: - // Raise Floor 24 - EV_DoFloor(line,raiseFloor24); - break; - - case 93: - // Raise Floor 24 And Change - EV_DoFloor(line,raiseFloor24AndChange); - break; - - case 94: - // Raise Floor Crush - EV_DoFloor(line,raiseFloorCrush); - break; - - case 95: - // Raise floor to nearest height - // and change texture. - EV_DoPlat(line,raiseToNearestAndChange,0); - break; - - case 96: - // Raise floor to shortest texture height - // on either side of lines. - EV_DoFloor(line,raiseToTexture); - break; - - case 97: - // TELEPORT! - EV_Teleport( line, side, thing ); - break; - - case 98: - // Lower Floor (TURBO) - EV_DoFloor(line,turboLower); - break; - - case 105: - // Blazing Door Raise (faster than TURBO!) - EV_DoDoor (line,vld_blazeRaise); - break; - - case 106: - // Blazing Door Open (faster than TURBO!) - EV_DoDoor (line,vld_blazeOpen); - break; - - case 107: - // Blazing Door Close (faster than TURBO!) - EV_DoDoor (line,vld_blazeClose); - break; - - case 120: - // Blazing PlatDownWaitUpStay. - EV_DoPlat(line,blazeDWUS,0); - break; - - case 126: - // TELEPORT MonsterONLY. - if (!thing->player) - EV_Teleport( line, side, thing ); - break; - - case 128: - // Raise To Nearest Floor - EV_DoFloor(line,raiseFloorToNearest); - break; - - case 129: - // Raise Floor Turbo - EV_DoFloor(line,raiseFloorTurbo); - break; + /* TRIGGERS. + * All from here to RETRIGGERS. + */ + + case 2: /* Open Door */ + ev_do_door(line, VLD_OPEN); + line->special = 0; + break; + + case 3: /* Close Door */ + ev_do_door(line, VLD_CLOSE); + line->special = 0; + break; + + case 4: /* Raise Door */ + ev_do_door(line, VLD_NORMAL); + line->special = 0; + break; + + case 5: /* Raise Floor */ + ev_do_floor(line, FLOOR_RAISEFLOOR); + line->special = 0; + break; + + case 6: /* Fast Ceiling Crush & Raise */ + ev_do_ceiling(line, CEIL_FASTCRUSHANDRAISE); + line->special = 0; + break; + + case 8: /* Build Stairs */ + ev_build_stairs(line, STAIR_BUILD8); + line->special = 0; + break; + + case 10: /* PlatDownWaitUp */ + ev_do_plat(line, PLAT_DOWNWAITUPSTAY, 0); + line->special = 0; + break; + + case 12: /* Light Turn On - brightest near */ + ev_light_turn_on(line, 0); + line->special = 0; + break; + + case 13: /* Light Turn On 255 */ + ev_light_turn_on(line, 255); + line->special = 0; + break; + + case 16: /* Close Door 30 */ + ev_do_door(line, VLD_CLOSE30THENOPEN); + line->special = 0; + break; + + case 17: /* Start Light Strobing */ + ev_start_light_strobing(line); + line->special = 0; + break; + + case 19: /* Lower Floor */ + ev_do_floor(line, FLOOR_LOWERFLOOR); + line->special = 0; + break; + + case 22: /* Raise floor to nearest height and change texture */ + ev_do_plat(line, PLAT_RAISETONEARESTANDCHANGE, 0); + line->special = 0; + break; + + case 25: /* Ceiling Crush and Raise */ + ev_do_ceiling(line, CEIL_CRUSHANDRAISE); + line->special = 0; + break; + + case 30: + + /* Raise floor to shortest texture height on either side of lines. */ + + ev_do_floor(line, FLOOR_RAISETOTEXTURE); + line->special = 0; + break; + + case 35: /* Lights Very Dark */ + ev_light_turn_on(line, 35); + line->special = 0; + break; + + case 36: /* Lower Floor (TURBO) */ + ev_do_floor(line, FLOOR_TURBOLOWER); + line->special = 0; + break; + + case 37: /* LowerAndChange */ + ev_do_floor(line, FLOOR_LOWERANDCHANGE); + line->special = 0; + break; + + case 38: /* Lower Floor To Lowest */ + ev_do_floor(line, FLOOR_LOWERFLOORTOLOWEST); + line->special = 0; + break; + + case 39: /* TELEPORT! */ + ev_teleport(line, side, thing); + line->special = 0; + break; + + case 40: /* RaiseCeilingLowerFloor */ + ev_do_ceiling(line, CEIL_RAISETOHIGHEST); + ev_do_floor(line, FLOOR_LOWERFLOORTOLOWEST); + line->special = 0; + break; + + case 44: /* Ceiling Crush */ + ev_do_ceiling(line, CEIL_LOWERANDCRUSH); + line->special = 0; + break; + + case 52: /* EXIT! */ + g_exit_level(); + break; + + case 53: /* Perpetual Platform Raise */ + ev_do_plat(line, PLAT_PERPETUALRAISE, 0); + line->special = 0; + break; + + case 54: /* Platform Stop */ + ev_stop_plat(line); + line->special = 0; + break; + + case 56: /* Raise Floor Crush */ + ev_do_floor(line, FLOOR_RAISEFLOORCRUSH); + line->special = 0; + break; + + case 57: /* Ceiling Crush Stop */ + ev_ceiling_crush_stop(line); + line->special = 0; + break; + + case 58: /* Raise Floor 24 */ + ev_do_floor(line, FLOOR_RAISEFLOOR24); + line->special = 0; + break; + + case 59: /* Raise Floor 24 And Change */ + ev_do_floor(line, FLOOR_RAISEFLOOR24ANDCHANGE); + line->special = 0; + break; + + case 104: /* Turn lights off in sector(tag) */ + ev_turn_tag_lights_off(line); + line->special = 0; + break; + + case 108: /* Blazing Door Raise (faster than TURBO!) */ + ev_do_door(line, VLD_BLAZERAISE); + line->special = 0; + break; + + case 109: /* Blazing Door Open (faster than TURBO!) */ + ev_do_door(line, VLD_BLAZEOPEN); + line->special = 0; + break; + + case 100: /* Build Stairs Turbo 16 */ + ev_build_stairs(line, STAIR_TURBO16); + line->special = 0; + break; + + case 110: /* Blazing Door Close (faster than TURBO!) */ + ev_do_door(line, VLD_BLAZECLOSE); + line->special = 0; + break; + + case 119: /* Raise floor to nearest surr. floor */ + ev_do_floor(line, FLOOR_RAISEFLOORTONEAREST); + line->special = 0; + break; + + case 121: /* Blazing PlatDownWaitUpStay */ + ev_do_plat(line, PLAT_BLAZEDWUS, 0); + line->special = 0; + break; + + case 124: /* Secret EXIT */ + g_secret_exit_level(); + break; + + case 125: /* TELEPORT MonsterONLY */ + if (!thing->player) + { + ev_teleport(line, side, thing); + line->special = 0; + } + break; + + case 130: /* Raise Floor Turbo */ + ev_do_floor(line, FLOOR_RAISEFLOORTURBO); + line->special = 0; + break; + + case 141: /* Silent Ceiling Crush & Raise */ + ev_do_ceiling(line, CEIL_SILENTCRUSHANDRAISE); + line->special = 0; + break; + + /* RETRIGGERS. All from here till end. */ + + case 72: /* Ceiling Crush */ + ev_do_ceiling(line, CEIL_LOWERANDCRUSH); + break; + + case 73: /* Ceiling Crush and Raise */ + ev_do_ceiling(line, CEIL_CRUSHANDRAISE); + break; + + case 74: /* Ceiling Crush Stop */ + ev_ceiling_crush_stop(line); + break; + + case 75: /* Close Door */ + ev_do_door(line, VLD_CLOSE); + break; + + case 76: /* Close Door 30 */ + ev_do_door(line, VLD_CLOSE30THENOPEN); + break; + + case 77: /* Fast Ceiling Crush & Raise */ + ev_do_ceiling(line, CEIL_FASTCRUSHANDRAISE); + break; + + case 79: /* Lights Very Dark */ + ev_light_turn_on(line, 35); + break; + + case 80: /* Light Turn On - brightest near */ + ev_light_turn_on(line, 0); + break; + + case 81: /* Light Turn On 255 */ + ev_light_turn_on(line, 255); + break; + + case 82: /* Lower Floor To Lowest */ + ev_do_floor(line, FLOOR_LOWERFLOORTOLOWEST); + break; + + case 83: /* Lower Floor */ + ev_do_floor(line, FLOOR_LOWERFLOOR); + break; + + case 84: /* LowerAndChange */ + ev_do_floor(line, FLOOR_LOWERANDCHANGE); + break; + + case 86: /* Open Door */ + ev_do_door(line, VLD_OPEN); + break; + + case 87: /* Perpetual Platform Raise */ + ev_do_plat(line, PLAT_PERPETUALRAISE, 0); + break; + + case 88: /* PlatDownWaitUp */ + ev_do_plat(line, PLAT_DOWNWAITUPSTAY, 0); + break; + + case 89: /* Platform Stop */ + ev_stop_plat(line); + break; + + case 90: /* Raise Door */ + ev_do_door(line, VLD_NORMAL); + break; + + case 91: /* Raise Floor */ + ev_do_floor(line, FLOOR_RAISEFLOOR); + break; + + case 92: /* Raise Floor 24 */ + ev_do_floor(line, FLOOR_RAISEFLOOR24); + break; + + case 93: /* Raise Floor 24 And Change */ + ev_do_floor(line, FLOOR_RAISEFLOOR24ANDCHANGE); + break; + + case 94: /* Raise Floor Crush */ + ev_do_floor(line, FLOOR_RAISEFLOORCRUSH); + break; + + case 95: /* Raise floor to nearest height and change texture. */ + ev_do_plat(line, PLAT_RAISETONEARESTANDCHANGE, 0); + break; + + case 96: + + /* Raise floor to shortest texture height on either side of lines. */ + + ev_do_floor(line, FLOOR_RAISETOTEXTURE); + break; + + case 97: /* TELEPORT! */ + ev_teleport(line, side, thing); + break; + + case 98: /* Lower Floor (TURBO) */ + ev_do_floor(line, FLOOR_TURBOLOWER); + break; + + case 105: /* Blazing Door Raise (faster than TURBO!) */ + ev_do_door(line, VLD_BLAZERAISE); + break; + + case 106: /* Blazing Door Open (faster than TURBO!) */ + ev_do_door(line, VLD_BLAZEOPEN); + break; + + case 107: /* Blazing Door Close (faster than TURBO!) */ + ev_do_door(line, VLD_BLAZECLOSE); + break; + + case 120: /* Blazing PlatDownWaitUpStay. */ + ev_do_plat(line, PLAT_BLAZEDWUS, 0); + break; + + case 126: /* TELEPORT MonsterONLY. */ + if (!thing->player) ev_teleport(line, side, thing); + break; + + case 128: /* Raise To Nearest Floor */ + ev_do_floor(line, FLOOR_RAISEFLOORTONEAREST); + break; + + case 129: /* Raise Floor Turbo */ + ev_do_floor(line, FLOOR_RAISEFLOORTURBO); + break; } } +/* p_shoot_special_line - IMPACT SPECIALS + * Called when a thing shoots a special line. + */ - -// -// P_ShootSpecialLine - IMPACT SPECIALS -// Called when a thing shoots a special line. -// -void -P_ShootSpecialLine -( mobj_t* thing, - line_t* line ) +void p_shoot_special_line(mobj_t *thing, line_t *line) { - int ok; - - // Impacts that other things can activate. - if (!thing->player) + int is_ok; + + /* Impacts that other things can activate. */ + + if (!thing->player) { - ok = 0; - switch(line->special) - { - case 46: - // OPEN DOOR IMPACT - ok = 1; - break; - } - if (!ok) - return; + is_ok = 0; + switch (line->special) + { + case 46: /* OPEN DOOR IMPACT */ + is_ok = 1; + break; + } + + if (!is_ok) return; } - switch(line->special) + switch (line->special) { - case 24: - // RAISE FLOOR - EV_DoFloor(line,raiseFloor); - P_ChangeSwitchTexture(line,0); - break; - - case 46: - // OPEN DOOR - EV_DoDoor(line,vld_open); - P_ChangeSwitchTexture(line,1); - break; - - case 47: - // RAISE FLOOR NEAR AND CHANGE - EV_DoPlat(line,raiseToNearestAndChange,0); - P_ChangeSwitchTexture(line,0); - break; + case 24: /* RAISE FLOOR */ + ev_do_floor(line, FLOOR_RAISEFLOOR); + p_change_switch_texture(line, 0); + break; + + case 46: /* OPEN DOOR */ + ev_do_door(line, VLD_OPEN); + p_change_switch_texture(line, 1); + break; + + case 47: /* RAISE FLOOR NEAR AND CHANGE */ + ev_do_plat(line, PLAT_RAISETONEARESTANDCHANGE, 0); + p_change_switch_texture(line, 0); + break; } } +/* p_player_in_special_sector + * Called every tic frame that the player origin is in a special sector + */ - -// -// P_PlayerInSpecialSector -// Called every tic frame -// that the player origin is in a special sector -// -void P_PlayerInSpecialSector (player_t* player) +void p_player_in_special_sector(player_t *player) { - sector_t* sector; - - sector = player->mo->subsector->sector; + sector_t *sector; + + sector = player->mo->subsector->sector; + + /* Falling, not all the way down yet? */ - // Falling, not all the way down yet? - if (player->mo->z != sector->floorheight) - return; + if (player->mo->z != sector->floorheight) return; - // Has hitten ground. - switch (sector->special) + /* Has hitten ground. */ + + switch (sector->special) { - case 5: - // HELLSLIME DAMAGE - if (!player->powers[pw_ironfeet]) - if (!(leveltime&0x1f)) - P_DamageMobj (player->mo, NULL, NULL, 10); - break; - - case 7: - // NUKAGE DAMAGE - if (!player->powers[pw_ironfeet]) - if (!(leveltime&0x1f)) - P_DamageMobj (player->mo, NULL, NULL, 5); - break; - - case 16: - // SUPER HELLSLIME DAMAGE - case 4: - // STROBE HURT - if (!player->powers[pw_ironfeet] - || (P_Random()<5) ) - { - if (!(leveltime&0x1f)) - P_DamageMobj (player->mo, NULL, NULL, 20); - } - break; - - case 9: - // SECRET SECTOR - player->secretcount++; - sector->special = 0; - break; - - case 11: - // EXIT SUPER DAMAGE! (for E1M8 finale) - player->cheats &= ~CF_GODMODE; - - if (!(leveltime&0x1f)) - P_DamageMobj (player->mo, NULL, NULL, 20); - - if (player->health <= 10) - G_ExitLevel(); - break; - - default: - I_Error ("P_PlayerInSpecialSector: " - "unknown special %i", - sector->special); - break; - }; -} + case 5: /* HELLSLIME DAMAGE */ + if (!player->powers[pw_ironfeet]) + { + if (!(leveltime & 0x1f)) p_damage_mobj(player->mo, NULL, NULL, 10); + } + break; + case 7: /* NUKAGE DAMAGE */ + if (!player->powers[pw_ironfeet]) + { + if (!(leveltime & 0x1f)) p_damage_mobj(player->mo, NULL, NULL, 5); + } + break; -// -// P_UpdateSpecials -// Animate planes, scroll walls, etc. -// -boolean levelTimer; -int levelTimeCount; + case 16: /* SUPER HELLSLIME DAMAGE */ + case 4: /* STROBE HURT */ + if (!player->powers[pw_ironfeet] || (p_random() < 5)) + { + if (!(leveltime & 0x1f)) p_damage_mobj(player->mo, NULL, NULL, 20); + } -void P_UpdateSpecials (void) -{ - anim_t* anim; - int pic; - int i; - line_t* line; - - - // LEVEL TIMER - if (levelTimer == true) - { - levelTimeCount--; - if (!levelTimeCount) - G_ExitLevel(); - } - - // ANIMATE FLATS AND TEXTURES GLOBALLY - for (anim = anims ; anim < lastanim ; anim++) - { - for (i=anim->basepic ; ibasepic+anim->numpics ; i++) - { - pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); - if (anim->istexture) - texturetranslation[i] = pic; - else - flattranslation[i] = pic; - } - } + break; - - // ANIMATE LINE SPECIALS - for (i = 0; i < numlinespecials; i++) - { - line = linespeciallist[i]; - switch(line->special) - { - case 48: - // EFFECT FIRSTCOL SCROLL + - sides[line->sidenum[0]].textureoffset += FRACUNIT; - break; - } - } + case 9: /* SECRET SECTOR */ + player->secretcount++; + sector->special = 0; + break; - - // DO BUTTONS - for (i = 0; i < MAXBUTTONS; i++) - if (buttonlist[i].btimer) - { - buttonlist[i].btimer--; - if (!buttonlist[i].btimer) - { - switch(buttonlist[i].where) - { - case top: - sides[buttonlist[i].line->sidenum[0]].toptexture = - buttonlist[i].btexture; - break; - - case middle: - sides[buttonlist[i].line->sidenum[0]].midtexture = - buttonlist[i].btexture; - break; - - case bottom: - sides[buttonlist[i].line->sidenum[0]].bottomtexture = - buttonlist[i].btexture; - break; - } - S_StartSound(&buttonlist[i].soundorg,sfx_swtchn); - memset(&buttonlist[i],0,sizeof(button_t)); - } - } -} + case 11: /* EXIT SUPER DAMAGE! (for E1M8 finale) */ + player->cheats &= ~CF_GODMODE; + if (!(leveltime & 0x1f)) p_damage_mobj(player->mo, NULL, NULL, 20); -// -// Donut overrun emulation -// -// Derived from the code from PrBoom+. Thanks go to Andrey Budko (entryway) -// as usual :-) -// + if (player->health <= 10) g_exit_level(); + break; -#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000 -#define DONUT_FLOORPIC_DEFAULT 0x16 + default: + i_error("p_player_in_special_sector: " + "unknown special %i", + sector->special); + break; + }; +} -static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic, - line_t *line, sector_t *pillar_sector) +void p_update_specials(void) { - static int first = 1; - static int tmp_s3_floorheight; - static int tmp_s3_floorpic; + anim_t *anim; + int pic; + int i; + line_t *line; + + /* LEVEL TIMER */ - if (first) + if (g_level_timer == true) { - int p; + g_level_time_count--; + if (!g_level_time_count) g_exit_level(); + } - // This is the first time we have had an overrun. - first = 0; + /* ANIMATE FLATS AND TEXTURES GLOBALLY */ - // Default values - tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT; - tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; + for (anim = g_anims; anim < g_lastanim; anim++) + { + for (i = anim->basepic; i < anim->basepic + anim->numpics; i++) + { + pic = anim->basepic + + ((leveltime / anim->speed + i) % anim->numpics); - //! - // @category compat - // @arg - // - // Use the specified magic values when emulating behavior caused - // by memory overruns from improperly constructed donuts. - // In Vanilla Doom this can differ depending on the operating - // system. The default (if this option is not specified) is to - // emulate the behavior when running under Windows 98. + if (anim->istexture) + texturetranslation[i] = pic; + else + flattranslation[i] = pic; + } + } - p = M_CheckParmWithArgs("-donut", 2); + /* ANIMATE LINE SPECIALS */ - if (p > 0) + for (i = 0; i < g_numlinespecials; i++) + { + line = g_linespeciallist[i]; + switch (line->special) { - // Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008 - // - // C:\>debug - // -d 0:0 - // - // DOS 6.22: - // 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) - // DOS 7.1: - // 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) - // Win98: - // 0000:0000 (00 00 00 00) 65 04 70 00-(16 00) - // DOSBox under XP: - // 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) - - M_StrToInt(myargv[p + 1], &tmp_s3_floorheight); - M_StrToInt(myargv[p + 2], &tmp_s3_floorpic); - - if (tmp_s3_floorpic >= numflats) - { - fprintf(stderr, - "DonutOverrun: The second parameter for \"-donut\" " - "switch should be greater than 0 and less than number " - "of flats (%d). Using default value (%d) instead. \n", - numflats, DONUT_FLOORPIC_DEFAULT); - tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; - } + case 48: /* EFFECT FIRSTCOL SCROLL + */ + sides[line->sidenum[0]].textureoffset += FRACUNIT; + break; } } - /* - fprintf(stderr, - "Linedef: %d; Sector: %d; " - "New floor height: %d; New floor pic: %d\n", - line->iLineID, pillar_sector->iSectorID, - tmp_s3_floorheight >> 16, tmp_s3_floorpic); - */ - - *s3_floorheight = (fixed_t) tmp_s3_floorheight; - *s3_floorpic = (short) tmp_s3_floorpic; + /* DO BUTTONS */ + + for (i = 0; i < MAXBUTTONS; i++) + if (buttonlist[i].btimer) + { + buttonlist[i].btimer--; + if (!buttonlist[i].btimer) + { + switch (buttonlist[i].where) + { + case top: + sides[buttonlist[i].line->sidenum[0]].toptexture = + buttonlist[i].btexture; + break; + + case middle: + sides[buttonlist[i].line->sidenum[0]].midtexture = + buttonlist[i].btexture; + break; + + case bottom: + sides[buttonlist[i].line->sidenum[0]].bottomtexture = + buttonlist[i].btexture; + break; + } + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(&buttonlist[i].soundorg, SFX_SWTCHN); +#endif + memset(&buttonlist[i], 0, sizeof(button_t)); + } + } } +/* Special Stuff that can not be categorized */ -// -// Special Stuff that can not be categorized -// -int EV_DoDonut(line_t* line) +int ev_do_donut(line_t *line) { - sector_t* s1; - sector_t* s2; - sector_t* s3; - int secnum; - int rtn; - int i; - floormove_t* floor; - fixed_t s3_floorheight; - short s3_floorpic; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + sector_t *s1; + sector_t *s2; + sector_t *s3; + int secnum; + int rtn; + int i; + floormove_t *floor; + fixed_t s3_floorheight; + short s3_floorpic; + + secnum = -1; + rtn = 0; + while ((secnum = p_find_sector_from_line_tag(line, secnum)) >= 0) { - s1 = §ors[secnum]; + s1 = §ors[secnum]; - // ALREADY MOVING? IF SO, KEEP GOING... - if (s1->specialdata) - continue; + /* ALREADY MOVING? IF SO, KEEP GOING... */ - rtn = 1; - s2 = getNextSector(s1->lines[0],s1); + if (s1->specialdata) continue; - // Vanilla Doom does not check if the linedef is one sided. The - // game does not crash, but reads invalid memory and causes the - // sector floor to move "down" to some unknown height. - // DOSbox prints a warning about an invalid memory access. - // - // I'm not sure exactly what invalid memory is being read. This - // isn't something that should be done, anyway. - // Just print a warning and return. + rtn = 1; + s2 = get_next_sector(s1->lines[0], s1); - if (s2 == NULL) + /* Vanilla Doom does not check if the linedef is one sided. The + * game does not crash, but reads invalid memory and causes the + * sector floor to move "down" to some unknown height. + * DOSbox prints a warning about an invalid memory access. + * + * I'm not sure exactly what invalid memory is being read. This + * isn't something that should be done, anyway. + * Just print a warning and return. + */ + + if (s2 == NULL) { - fprintf(stderr, - "EV_DoDonut: linedef had no second sidedef! " - "Unexpected behavior may occur in Vanilla Doom. \n"); - break; + fprintf(stderr, + "ev_do_donut: linedef had no second sidedef! " + "Unexpected behavior may occur in Vanilla Doom. \n"); + break; } - for (i = 0; i < s2->linecount; i++) - { - s3 = s2->lines[i]->backsector; + for (i = 0; i < s2->linecount; i++) + { + s3 = s2->lines[i]->backsector; - if (s3 == s1) - continue; + if (s3 == s1) continue; - if (s3 == NULL) + if (s3 == NULL) { - // e6y - // s3 is NULL, so - // s3->floorheight is an int at 0000:0000 - // s3->floorpic is a short at 0000:0008 - // Trying to emulate - - fprintf(stderr, - "EV_DoDonut: WARNING: emulating buffer overrun due to " - "NULL back sector. " - "Unexpected behavior may occur in Vanilla Doom.\n"); - - DonutOverrun(&s3_floorheight, &s3_floorpic, line, s1); + /* e6y + * s3 is NULL, so + * s3->floorheight is an int at 0000:0000 + * s3->floorpic is a short at 0000:0008 + * Trying to emulate + */ + + fprintf(stderr, "ev_do_donut: WARNING: emulating buffer " + "overrun due to NULL back sector. Unexpected " + "behavior may occur in Vanilla Doom.\n"); + + donut_overrun(&s3_floorheight, &s3_floorpic, line, s1); } - else + else { - s3_floorheight = s3->floorheight; - s3_floorpic = s3->floorpic; + s3_floorheight = s3->floorheight; + s3_floorpic = s3->floorpic; } - // Spawn rising slime - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - s2->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->type = donutRaise; - floor->crush = false; - floor->direction = 1; - floor->sector = s2; - floor->speed = FLOORSPEED / 2; - floor->texture = s3_floorpic; - floor->newspecial = 0; - floor->floordestheight = s3_floorheight; - - // Spawn lowering donut-hole - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - s1->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->type = lowerFloor; - floor->crush = false; - floor->direction = -1; - floor->sector = s1; - floor->speed = FLOORSPEED / 2; - floor->floordestheight = s3_floorheight; - break; - } + /* Spawn rising slime */ + + floor = z_malloc(sizeof(*floor), PU_LEVSPEC, 0); + p_add_thinker(&floor->thinker); + s2->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)t_move_floor; + floor->type = FLOOR_DONUTRAISE; + floor->crush = false; + floor->direction = 1; + floor->sector = s2; + floor->speed = FLOORSPEED / 2; + floor->texture = s3_floorpic; + floor->newspecial = 0; + floor->floordestheight = s3_floorheight; + + /* Spawn lowering donut-hole */ + + floor = z_malloc(sizeof(*floor), PU_LEVSPEC, 0); + p_add_thinker(&floor->thinker); + s1->specialdata = floor; + floor->thinker.function.acp1 = (actionf_p1)t_move_floor; + floor->type = FLOOR_LOWERFLOOR; + floor->crush = false; + floor->direction = -1; + floor->sector = s1; + floor->speed = FLOORSPEED / 2; + floor->floordestheight = s3_floorheight; + break; + } } - return rtn; -} - - -// -// SPECIAL SPAWNING -// - -// -// P_SpawnSpecials -// After the map has been loaded, scan for specials -// that spawn thinkers -// + return rtn; +} -static unsigned int NumScrollers() -{ - unsigned int i, scrollers = 0; +/* SPECIAL SPAWNING */ - for (i = 0; i < numlines; i++) - { - if (48 == lines[i].special) - { - scrollers++; - } - } - return scrollers; -} +/* Parses command line parameters. */ -// Parses command line parameters. -void P_SpawnSpecials (void) +void p_spawn_specials(void) { - sector_t* sector; - int i; - short maxlineanims = (gameversion <= exe_doom_1_2) ? MAXLINEANIMS1_2 - : MAXLINEANIMS; + sector_t *sector; + int i; + short maxlineanims = + (gameversion <= exe_doom_1_2) ? MAXLINEANIMS1_2 : MAXLINEANIMS; - // See if -TIMER was specified. + /* See if -TIMER was specified. */ - if (timelimit > 0 && deathmatch) + if (timelimit > 0 && deathmatch) { - levelTimer = true; - levelTimeCount = timelimit * 60 * TICRATE; + g_level_timer = true; + g_level_time_count = timelimit * 60 * TICRATE; } - else + else { - levelTimer = false; + g_level_timer = false; } - // Init special SECTORs. - sector = sectors; - for (i=0 ; ispecial) - continue; - - switch (sector->special) - { - case 1: - // FLICKERING LIGHTS - P_SpawnLightFlash (sector); - break; - - case 2: - // STROBE FAST - P_SpawnStrobeFlash(sector,FASTDARK,0); - break; - - case 3: - // STROBE SLOW - P_SpawnStrobeFlash(sector,SLOWDARK,0); - break; - - case 4: - // STROBE FAST/DEATH SLIME - P_SpawnStrobeFlash(sector,FASTDARK,0); - sector->special = 4; - break; - - case 8: - // GLOWING LIGHT - P_SpawnGlowingLight(sector); - break; - case 9: - // SECRET SECTOR - totalsecret++; - break; - - case 10: - // DOOR CLOSE IN 30 SECONDS - P_SpawnDoorCloseIn30 (sector); - break; - - case 12: - // SYNC STROBE SLOW - P_SpawnStrobeFlash (sector, SLOWDARK, 1); - break; - - case 13: - // SYNC STROBE FAST - P_SpawnStrobeFlash (sector, FASTDARK, 1); - break; - - case 14: - // DOOR RAISE IN 5 MINUTES - P_SpawnDoorRaiseIn5Mins (sector, i); - break; - - case 17: - // first introduced in official v1.4 beta - if (gameversion > exe_doom_1_2) + if (!sector->special) continue; + + switch (sector->special) + { + case 1: /* FLICKERING LIGHTS */ + p_spawn_light_flash(sector); + break; + + case 2: /* STROBE FAST */ + p_spawn_strobe_flash(sector, FASTDARK, 0); + break; + + case 3: /* STROBE SLOW */ + p_spawn_strobe_flash(sector, SLOWDARK, 0); + break; + + case 4: /* STROBE FAST/DEATH SLIME */ + p_spawn_strobe_flash(sector, FASTDARK, 0); + sector->special = 4; + break; + + case 8: /* GLOWING LIGHT */ + p_spawn_glowing_light(sector); + break; + + case 9: /* SECRET SECTOR */ + totalsecret++; + break; + + case 10: /* DOOR CLOSE IN 30 SECONDS */ + p_spawn_door_close_in30(sector); + break; + + case 12: /* SYNC STROBE SLOW */ + p_spawn_strobe_flash(sector, SLOWDARK, 1); + break; + + case 13: /* SYNC STROBE FAST */ + p_spawn_strobe_flash(sector, FASTDARK, 1); + break; + + case 14: /* DOOR RAISE IN 5 MINUTES */ + p_spawn_door_raise_in_5min(sector, i); + break; + + case 17: /* first introduced in official v1.4 beta */ + if (gameversion > exe_doom_1_2) { - P_SpawnFireFlicker(sector); + p_spawn_fire_flicker(sector); } - break; - } + break; + } } - - // Init line EFFECTs - numlinespecials = 0; - for (i = 0;i < numlines; i++) + /* Init line EFFECTs */ + + g_numlinespecials = 0; + + for (i = 0; i < numlines; i++) { - switch(lines[i].special) - { - case 48: - if (numlinespecials >= maxlineanims) + switch (lines[i].special) + { + case 48: + if (g_numlinespecials >= maxlineanims) { - I_Error("P_SpawnSpecials: Too many scrolling wall linedefs " - "(%d)! (Vanilla limit is %d)", NumScrollers(), - maxlineanims); + i_error("p_spawn_specials: Too many scrolling wall linedefs " + "(%d)! (Vanilla limit is %d)", + num_scrollers(), maxlineanims); } - // EFFECT FIRSTCOL SCROLL+ - linespeciallist[numlinespecials] = &lines[i]; - numlinespecials++; - break; - } + + /* EFFECT FIRSTCOL SCROLL+ */ + + g_linespeciallist[g_numlinespecials] = &lines[i]; + g_numlinespecials++; + break; + } } - - // Init other misc stuff - for (i = 0;i < MAXCEILINGS;i++) - activeceilings[i] = NULL; + /* Init other misc stuff */ + + for (i = 0; i < MAXCEILINGS; i++) + activeceilings[i] = NULL; + + for (i = 0; i < MAXPLATS; i++) + activeplats[i] = NULL; - for (i = 0;i < MAXPLATS;i++) - activeplats[i] = NULL; - - for (i = 0;i < MAXBUTTONS;i++) - memset(&buttonlist[i],0,sizeof(button_t)); + for (i = 0; i < MAXBUTTONS; i++) + memset(&buttonlist[i], 0, sizeof(button_t)); - // UNUSED: no horizonal sliders. - // P_InitSlidingDoorFrames(); + /* UNUSED: no horizontal sliders. + * p_init_sliding_door_frames(); + */ } diff --git a/games/NXDoom/src/doom/p_spec.h b/games/NXDoom/src/doom/p_spec.h index a1343bfa398..f69c818b4c6 100644 --- a/games/NXDoom/src/doom/p_spec.h +++ b/games/NXDoom/src/doom/p_spec.h @@ -1,637 +1,503 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// Implements special effects: -// Texture animation, height or lighting changes -// according to adjacent sectors, respective -// utility functions, etc. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_spec.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: none + * Implements special effects: + * Texture animation, height or lighting changes according to adjacent + * sectors, respective utility functions, etc. + * + ****************************************************************************/ #ifndef __P_SPEC__ #define __P_SPEC__ +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// -// End-level timer (-TIMER option) -// -extern boolean levelTimer; -extern int levelTimeCount; - - -// Define values for map objects -#define MO_TELEPORTMAN 14 - +/* Define values for map objects */ -// at game start -void P_InitPicAnims (void); +#define MO_TELEPORTMAN 14 -// at map load -void P_SpawnSpecials (void); +#define GLOWSPEED 8 +#define STROBEBRIGHT 5 +#define FASTDARK 15 +#define SLOWDARK 35 -// every tic -void P_UpdateSpecials (void); +/* max # of wall switches in a level */ -// when needed -boolean -P_UseSpecialLine -( mobj_t* thing, - line_t* line, - int side ); +#define MAXSWITCHES 50 -void -P_ShootSpecialLine -( mobj_t* thing, - line_t* line ); +/* 4 players, 4 buttons each at once, max. */ -void -P_CrossSpecialLine -( int linenum, - int side, - mobj_t* thing ); +#define MAXBUTTONS 16 -void P_PlayerInSpecialSector (player_t* player); +/* 1 second, in ticks. */ -int -twoSided -( int sector, - int line ); +#define BUTTONTIME 35 -sector_t* -getSector -( int currentSector, - int line, - int side ); +#define PLATWAIT 3 +#define PLATSPEED FRACUNIT +#define MAXPLATS 30 -side_t* -getSide -( int currentSector, - int line, - int side ); +#define FLOORSPEED FRACUNIT -fixed_t P_FindLowestFloorSurrounding(sector_t* sec); -fixed_t P_FindHighestFloorSurrounding(sector_t* sec); +#define VDOORSPEED FRACUNIT * 2 +#define VDOORWAIT 150 -fixed_t -P_FindNextHighestFloor -( sector_t* sec, - int currentheight ); +#define CEILSPEED FRACUNIT +#define CEILWAIT 150 +#define MAXCEILINGS 30 -fixed_t P_FindLowestCeilingSurrounding(sector_t* sec); -fixed_t P_FindHighestCeilingSurrounding(sector_t* sec); +#if 0 /* UNUSED */ -int -P_FindSectorFromLineTag -( line_t* line, - int start ); +/* how many frames of animation */ -int -P_FindMinSurroundingLight -( sector_t* sector, - int max ); +#define SNUMFRAMES 4 -sector_t* -getNextSector -( line_t* line, - sector_t* sec ); +#define SDOORWAIT 35 * 3 +#define SWAITTICS 4 +/* how many diff. types of anims */ -// -// SPECIAL -// -int EV_DoDonut(line_t* line); +#define MAXSLIDEDOORS 5 +#endif +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* P_LIGHTS */ -// -// P_LIGHTS -// typedef struct { - thinker_t thinker; - sector_t* sector; - int count; - int maxlight; - int minlight; - + thinker_t thinker; + sector_t *sector; + int count; + int maxlight; + int minlight; } fireflicker_t; - - typedef struct { - thinker_t thinker; - sector_t* sector; - int count; - int maxlight; - int minlight; - int maxtime; - int mintime; - + thinker_t thinker; + sector_t *sector; + int count; + int maxlight; + int minlight; + int maxtime; + int mintime; } lightflash_t; - - typedef struct { - thinker_t thinker; - sector_t* sector; - int count; - int minlight; - int maxlight; - int darktime; - int brighttime; - + thinker_t thinker; + sector_t *sector; + int count; + int minlight; + int maxlight; + int darktime; + int brighttime; } strobe_t; - - - typedef struct { - thinker_t thinker; - sector_t* sector; - int minlight; - int maxlight; - int direction; - + thinker_t thinker; + sector_t *sector; + int minlight; + int maxlight; + int direction; } glow_t; +/* P_SWITCH */ -#define GLOWSPEED 8 -#define STROBEBRIGHT 5 -#define FASTDARK 15 -#define SLOWDARK 35 - -void P_SpawnFireFlicker (sector_t* sector); -void T_LightFlash (lightflash_t* flash); -void P_SpawnLightFlash (sector_t* sector); -void T_StrobeFlash (strobe_t* flash); - -void -P_SpawnStrobeFlash -( sector_t* sector, - int fastOrSlow, - int inSync ); - -void EV_StartLightStrobing(line_t* line); -void EV_TurnTagLightsOff(line_t* line); +typedef struct +{ + char name1[9]; + char name2[9]; + short episode; +} switchlist_t; -void -EV_LightTurnOn -( line_t* line, - int bright ); +typedef enum +{ + top, + middle, + bottom +} bwhere_e; -void T_Glow(glow_t* g); -void P_SpawnGlowingLight(sector_t* sector); +typedef struct +{ + line_t *line; + bwhere_e where; + int btexture; + int btimer; + degenmobj_t *soundorg; +} button_t; +/* P_PLATS */ +typedef enum +{ + up, + down, + waiting, + in_stasis +} plat_e; +typedef enum +{ + PLAT_PERPETUALRAISE, + PLAT_DOWNWAITUPSTAY, + PLAT_RAISEANDCHANGE, + PLAT_RAISETONEARESTANDCHANGE, + PLAT_BLAZEDWUS +} plattype_e; -// -// P_SWITCH -// typedef struct { - char name1[9]; - char name2[9]; - short episode; - -} switchlist_t; + thinker_t thinker; + sector_t *sector; + fixed_t speed; + fixed_t low; + fixed_t high; + int wait; + int count; + plat_e status; + plat_e oldstatus; + boolean crush; + int tag; + plattype_e type; +} plat_t; +/* P_FLOOR */ typedef enum { - top, - middle, - bottom + /* lower floor to highest surrounding floor */ -} bwhere_e; + FLOOR_LOWERFLOOR, + /* lower floor to lowest surrounding floor */ -typedef struct -{ - line_t* line; - bwhere_e where; - int btexture; - int btimer; - degenmobj_t *soundorg; + FLOOR_LOWERFLOORTOLOWEST, -} button_t; + /* lower floor to highest surrounding floor VERY FAST */ + FLOOR_TURBOLOWER, + /* raise floor to lowest surrounding CEILING */ + FLOOR_RAISEFLOOR, - // max # of wall switches in a level -#define MAXSWITCHES 50 + /* raise floor to next highest surrounding floor */ - // 4 players, 4 buttons each at once, max. -#define MAXBUTTONS 16 + FLOOR_RAISEFLOORTONEAREST, - // 1 second, in ticks. -#define BUTTONTIME 35 + /* raise floor to shortest height texture around it */ -extern button_t buttonlist[MAXBUTTONS]; + FLOOR_RAISETOTEXTURE, -void -P_ChangeSwitchTexture -( line_t* line, - int useAgain ); + /* lower floor to lowest surrounding floor and change floorpic */ -void P_InitSwitchList(void); + FLOOR_LOWERANDCHANGE, + FLOOR_RAISEFLOOR24, + FLOOR_RAISEFLOOR24ANDCHANGE, + FLOOR_RAISEFLOORCRUSH, -// -// P_PLATS -// -typedef enum -{ - up, - down, - waiting, - in_stasis - -} plat_e; - + /* raise to next highest floor, turbo-speed */ + FLOOR_RAISEFLOORTURBO, + FLOOR_DONUTRAISE, + FLOOR_RAISEFLOOR512 +} floor_e; typedef enum { - perpetualRaise, - downWaitUpStay, - raiseAndChange, - raiseToNearestAndChange, - blazeDWUS + STAIR_BUILD8, /* slowly build by 8 */ + STAIR_TURBO16 /* quickly build by 16 */ +} stair_e; -} plattype_e; +typedef struct +{ + thinker_t thinker; + floor_e type; + boolean crush; + sector_t *sector; + int direction; + int newspecial; + short texture; + fixed_t floordestheight; + fixed_t speed; +} floormove_t; +typedef enum +{ + ok, + crushed, + pastdest +} result_e; +typedef enum +{ + VLD_NORMAL, + VLD_CLOSE30THENOPEN, + VLD_CLOSE, + VLD_OPEN, + VLD_RAISEIN5MINS, + VLD_BLAZERAISE, + VLD_BLAZEOPEN, + VLD_BLAZECLOSE +} vldoor_e; typedef struct { - thinker_t thinker; - sector_t* sector; - fixed_t speed; - fixed_t low; - fixed_t high; - int wait; - int count; - plat_e status; - plat_e oldstatus; - boolean crush; - int tag; - plattype_e type; - -} plat_t; + thinker_t thinker; + vldoor_e type; + sector_t *sector; + fixed_t topheight; + fixed_t speed; + /* 1 = up, 0 = waiting at top, -1 = down */ + int direction; -#define PLATWAIT 3 -#define PLATSPEED FRACUNIT -#define MAXPLATS 30 + /* tics to wait at the top */ + int topwait; -extern plat_t* activeplats[MAXPLATS]; + /* (keep in case a door going down is reset) + * when it reaches 0, start going down + */ -void T_PlatRaise(plat_t* plat); - -int -EV_DoPlat -( line_t* line, - plattype_e type, - int amount ); - -void P_AddActivePlat(plat_t* plat); -void P_RemoveActivePlat(plat_t* plat); -void EV_StopPlat(line_t* line); -void P_ActivateInStasis(int tag); + int topcountdown; +} vldoor_t; +/* P_CEILNG */ -// -// P_DOORS -// typedef enum { - vld_normal, - vld_close30ThenOpen, - vld_close, - vld_open, - vld_raiseIn5Mins, - vld_blazeRaise, - vld_blazeOpen, - vld_blazeClose - -} vldoor_e; - - + CEIL_LOWERTOFLOOR, + CEIL_RAISETOHIGHEST, + CEIL_LOWERANDCRUSH, + CEIL_CRUSHANDRAISE, + CEIL_FASTCRUSHANDRAISE, + CEIL_SILENTCRUSHANDRAISE +} ceiling_e; typedef struct { - thinker_t thinker; - vldoor_e type; - sector_t* sector; - fixed_t topheight; - fixed_t speed; - - // 1 = up, 0 = waiting at top, -1 = down - int direction; - - // tics to wait at the top - int topwait; - // (keep in case a door going down is reset) - // when it reaches 0, start going down - int topcountdown; - -} vldoor_t; + thinker_t thinker; + ceiling_e type; + sector_t *sector; + fixed_t bottomheight; + fixed_t topheight; + fixed_t speed; + boolean crush; + /* 1 = up, 0 = waiting, -1 = down */ + int direction; -#define VDOORSPEED FRACUNIT*2 -#define VDOORWAIT 150 + /* ID */ -void -EV_VerticalDoor -( line_t* line, - mobj_t* thing ); + int tag; + int olddirection; +} ceiling_t; -int -EV_DoDoor -( line_t* line, - vldoor_e type ); +#if 0 /* UNUSED */ -int -EV_DoLockedDoor -( line_t* line, - vldoor_e type, - mobj_t* thing ); +/* Sliding doors... */ -void T_VerticalDoor (vldoor_t* door); -void P_SpawnDoorCloseIn30 (sector_t* sec); +typedef enum +{ + sd_opening, + sd_waiting, + sd_closing +} sd_e; -void -P_SpawnDoorRaiseIn5Mins -( sector_t* sec, - int secnum ); +typedef enum +{ + SDT_OPENONLY, + SDT_CLOSEONLY, + SDT_OPENANDCLOSE +} sdt_e; +typedef struct +{ + thinker_t thinker; + sdt_e type; + line_t *line; + int frame; + int which_door_index; + int timer; + sector_t *frontsector; + sector_t *backsector; + sd_e status; +} slidedoor_t; +typedef struct +{ + char front_frame1[9]; + char front_frame2[9]; + char front_frame3[9]; + char front_frame4[9]; + char back_frame1[9]; + char back_frame2[9]; + char back_frame3[9]; + char back_frame4[9]; +} slidename_t; -#if 0 // UNUSED -// -// Sliding doors... -// -typedef enum +typedef struct { - sd_opening, - sd_waiting, - sd_closing + int front_frames[4]; + int back_frames[4]; +} slideframe_t; +#endif -} sd_e; +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* End-level timer (-TIMER option) */ +extern button_t buttonlist[MAXBUTTONS]; -typedef enum -{ - sdt_openOnly, - sdt_closeOnly, - sdt_openAndClose +extern plat_t *activeplats[MAXPLATS]; -} sdt_e; +extern ceiling_t *activeceilings[MAXCEILINGS]; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/* at game start */ +void p_init_pic_anims(void); -typedef struct -{ - thinker_t thinker; - sdt_e type; - line_t* line; - int frame; - int whichDoorIndex; - int timer; - sector_t* frontsector; - sector_t* backsector; - sd_e status; +/* at map load */ -} slidedoor_t; +void p_spawn_specials(void); +/* every tic */ +void p_update_specials(void); -typedef struct -{ - char frontFrame1[9]; - char frontFrame2[9]; - char frontFrame3[9]; - char frontFrame4[9]; - char backFrame1[9]; - char backFrame2[9]; - char backFrame3[9]; - char backFrame4[9]; - -} slidename_t; +/* when needed */ +boolean p_use_special_line(mobj_t *thing, line_t *line, int side); +void p_shoot_special_line(mobj_t *thing, line_t *line); -typedef struct -{ - int frontFrames[4]; - int backFrames[4]; - -} slideframe_t; +void p_cross_special_line(int linenum, int side, mobj_t *thing); +void p_player_in_special_sector(player_t *player); +int two_sided(int sector, int line); -// how many frames of animation -#define SNUMFRAMES 4 +sector_t *get_sector(int current_sector, int line, int side); -#define SDOORWAIT 35*3 -#define SWAITTICS 4 +side_t *get_side(int current_sector, int line, int side); -// how many diff. types of anims -#define MAXSLIDEDOORS 5 +fixed_t p_find_lowest_floor_surrounding(sector_t *sec); +fixed_t p_find_highest_floor_surrounding(sector_t *sec); -void P_InitSlidingDoorFrames(void); +fixed_t p_find_next_highest_floor(sector_t *sec, int currentheight); -void -EV_SlidingDoor -( line_t* line, - mobj_t* thing ); -#endif +fixed_t p_find_lowest_ceiling_surrounding(sector_t *sec); +fixed_t p_find_heighest_ceiling_surrounding(sector_t *sec); +int p_find_sector_from_line_tag(line_t *line, int start); +int p_find_min_surrounding(sector_t *sector, int max); -// -// P_CEILNG -// -typedef enum -{ - lowerToFloor, - raiseToHighest, - lowerAndCrush, - crushAndRaise, - fastCrushAndRaise, - silentCrushAndRaise +sector_t *get_next_sector(line_t *line, sector_t *sec); -} ceiling_e; +/* SPECIAL */ +int ev_do_donut(line_t *line); +void p_spawn_fire_flicker(sector_t *sector); +void t_light_flash(lightflash_t *flash); +void p_spawn_light_flash(sector_t *sector); +void t_strobe_flash(strobe_t *flash); -typedef struct -{ - thinker_t thinker; - ceiling_e type; - sector_t* sector; - fixed_t bottomheight; - fixed_t topheight; - fixed_t speed; - boolean crush; - - // 1 = up, 0 = waiting, -1 = down - int direction; - - // ID - int tag; - int olddirection; - -} ceiling_t; +void p_spawn_strobe_flash(sector_t *sector, int fast_or_slow, int in_sync); +void ev_start_light_strobing(line_t *line); +void ev_turn_tag_lights_off(line_t *line); +void ev_light_turn_on(line_t *line, int bright); +void t_glow(glow_t *g); +void p_spawn_glowing_light(sector_t *sector); +void p_change_switch_texture(line_t *line, int use_again); -#define CEILSPEED FRACUNIT -#define CEILWAIT 150 -#define MAXCEILINGS 30 +void p_init_switch_list(void); -extern ceiling_t* activeceilings[MAXCEILINGS]; +void t_plat_raise(plat_t *plat); -int -EV_DoCeiling -( line_t* line, - ceiling_e type ); +int ev_do_plat(line_t *line, plattype_e type, int amount); -void T_MoveCeiling (ceiling_t* ceiling); -void P_AddActiveCeiling(ceiling_t* c); -void P_RemoveActiveCeiling(ceiling_t* c); -int EV_CeilingCrushStop(line_t* line); -void P_ActivateInStasisCeiling(line_t* line); +void p_add_active_plat(plat_t *plat); +void p_remove_active_plat(plat_t *plat); +void ev_stop_plat(line_t *line); +void p_activate_in_stasis(int tag); +/* P_DOORS */ -// -// P_FLOOR -// -typedef enum -{ - // lower floor to highest surrounding floor - lowerFloor, - - // lower floor to lowest surrounding floor - lowerFloorToLowest, - - // lower floor to highest surrounding floor VERY FAST - turboLower, - - // raise floor to lowest surrounding CEILING - raiseFloor, - - // raise floor to next highest surrounding floor - raiseFloorToNearest, - - // raise floor to shortest height texture around it - raiseToTexture, - - // lower floor to lowest surrounding floor - // and change floorpic - lowerAndChange, - - raiseFloor24, - raiseFloor24AndChange, - raiseFloorCrush, - - // raise to next highest floor, turbo-speed - raiseFloorTurbo, - donutRaise, - raiseFloor512 - -} floor_e; +void ev_vertical_door(line_t *line, mobj_t *thing); +int ev_do_door(line_t *line, vldoor_e type); +int ev_do_locked_door(line_t *line, vldoor_e type, mobj_t *thing); +void t_vertical_door(vldoor_t *door); +void p_spawn_door_close_in30(sector_t *sec); -typedef enum -{ - build8, // slowly build by 8 - turbo16 // quickly build by 16 - -} stair_e; +void p_spawn_door_raise_in_5min(sector_t *sec, int secnum); +int ev_do_ceiling(line_t *line, ceiling_e type); +void t_move_ceiling(ceiling_t *ceiling); +void p_add_active_ceiling(ceiling_t *c); +void p_remove_active_ceiling(ceiling_t *c); +int ev_ceiling_crush_stop(line_t *line); +void p_activate_in_stasis_ceiling(line_t *line); -typedef struct -{ - thinker_t thinker; - floor_e type; - boolean crush; - sector_t* sector; - int direction; - int newspecial; - short texture; - fixed_t floordestheight; - fixed_t speed; +result_e t_move_plane(sector_t *sector, fixed_t speed, fixed_t dest, + boolean crush, int floor_or_ceiling, int direction); -} floormove_t; +int ev_build_stairs(line_t *line, stair_e type); +int ev_do_floor(line_t *line, floor_e floortype); +void t_move_floor(floormove_t *floor); -#define FLOORSPEED FRACUNIT +/* P_TELEPT */ -typedef enum -{ - ok, - crushed, - pastdest - -} result_e; +int ev_teleport(line_t *line, int side, mobj_t *thing); -result_e -T_MovePlane -( sector_t* sector, - fixed_t speed, - fixed_t dest, - boolean crush, - int floorOrCeiling, - int direction ); - -int -EV_BuildStairs -( line_t* line, - stair_e type ); - -int -EV_DoFloor -( line_t* line, - floor_e floortype ); - -void T_MoveFloor( floormove_t* floor); - -// -// P_TELEPT -// -int -EV_Teleport -( line_t* line, - int side, - mobj_t* thing ); +#if 0 /* UNUSED */ +void p_init_sliding_door_frames(void); +void ev_sliding_door(line_t *line, mobj_t *thing); #endif + +#endif /* __P_SPEC__ */ diff --git a/games/NXDoom/src/doom/p_switch.c b/games/NXDoom/src/doom/p_switch.c index b9ef2195aad..27640d5ec21 100644 --- a/games/NXDoom/src/doom/p_switch.c +++ b/games/NXDoom/src/doom/p_switch.c @@ -1,641 +1,596 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: -// Switches, buttons. Two-state animation. Exits. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_switch.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * + * DESCRIPTION: + * Switches, buttons. Two-state animation. Exits. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include -#include "i_system.h" #include "deh_main.h" #include "doomdef.h" +#include "i_system.h" #include "p_local.h" #include "g_game.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" - -// Data. #include "sounds.h" +#endif + +/* State. */ -// State. #include "doomstat.h" #include "r_state.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE */ -// -// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE -// -switchlist_t alphSwitchList[] = +static switchlist_t g_alph_switch_list[] = { - // Doom shareware episode 1 switches - {"SW1BRCOM", "SW2BRCOM", 1}, - {"SW1BRN1", "SW2BRN1", 1}, - {"SW1BRN2", "SW2BRN2", 1}, - {"SW1BRNGN", "SW2BRNGN", 1}, - {"SW1BROWN", "SW2BROWN", 1}, - {"SW1COMM", "SW2COMM", 1}, - {"SW1COMP", "SW2COMP", 1}, - {"SW1DIRT", "SW2DIRT", 1}, - {"SW1EXIT", "SW2EXIT", 1}, - {"SW1GRAY", "SW2GRAY", 1}, - {"SW1GRAY1", "SW2GRAY1", 1}, - {"SW1METAL", "SW2METAL", 1}, - {"SW1PIPE", "SW2PIPE", 1}, - {"SW1SLAD", "SW2SLAD", 1}, - {"SW1STARG", "SW2STARG", 1}, - {"SW1STON1", "SW2STON1", 1}, - {"SW1STON2", "SW2STON2", 1}, - {"SW1STONE", "SW2STONE", 1}, - {"SW1STRTN", "SW2STRTN", 1}, - - // Doom registered episodes 2&3 switches - {"SW1BLUE", "SW2BLUE", 2}, - {"SW1CMT", "SW2CMT", 2}, - {"SW1GARG", "SW2GARG", 2}, - {"SW1GSTON", "SW2GSTON", 2}, - {"SW1HOT", "SW2HOT", 2}, - {"SW1LION", "SW2LION", 2}, - {"SW1SATYR", "SW2SATYR", 2}, - {"SW1SKIN", "SW2SKIN", 2}, - {"SW1VINE", "SW2VINE", 2}, - {"SW1WOOD", "SW2WOOD", 2}, - - // Doom II switches - {"SW1PANEL", "SW2PANEL", 3}, - {"SW1ROCK", "SW2ROCK", 3}, - {"SW1MET2", "SW2MET2", 3}, - {"SW1WDMET", "SW2WDMET", 3}, - {"SW1BRIK", "SW2BRIK", 3}, - {"SW1MOD1", "SW2MOD1", 3}, - {"SW1ZIM", "SW2ZIM", 3}, - {"SW1STON6", "SW2STON6", 3}, - {"SW1TEK", "SW2TEK", 3}, - {"SW1MARB", "SW2MARB", 3}, - {"SW1SKULL", "SW2SKULL", 3}, + {"SW1BRCOM", "SW2BRCOM", 1}, /* Doom shareware episode 1 switches */ + {"SW1BRN1", "SW2BRN1", 1}, + {"SW1BRN2", "SW2BRN2", 1}, + {"SW1BRNGN", "SW2BRNGN", 1}, + {"SW1BROWN", "SW2BROWN", 1}, + {"SW1COMM", "SW2COMM", 1}, + {"SW1COMP", "SW2COMP", 1}, + {"SW1DIRT", "SW2DIRT", 1}, + {"SW1EXIT", "SW2EXIT", 1}, + {"SW1GRAY", "SW2GRAY", 1}, + {"SW1GRAY1", "SW2GRAY1", 1}, + {"SW1METAL", "SW2METAL", 1}, + {"SW1PIPE", "SW2PIPE", 1}, + {"SW1SLAD", "SW2SLAD", 1}, + {"SW1STARG", "SW2STARG", 1}, + {"SW1STON1", "SW2STON1", 1}, + {"SW1STON2", "SW2STON2", 1}, + {"SW1STONE", "SW2STONE", 1}, + {"SW1STRTN", "SW2STRTN", 1}, + {"SW1BLUE", "SW2BLUE", 2}, /* Doom registered episodes 2 & 3 switches */ + {"SW1CMT", "SW2CMT", 2}, + {"SW1GARG", "SW2GARG", 2}, + {"SW1GSTON", "SW2GSTON", 2}, + {"SW1HOT", "SW2HOT", 2}, + {"SW1LION", "SW2LION", 2}, + {"SW1SATYR", "SW2SATYR", 2}, + {"SW1SKIN", "SW2SKIN", 2}, + {"SW1VINE", "SW2VINE", 2}, + {"SW1WOOD", "SW2WOOD", 2}, + {"SW1PANEL", "SW2PANEL", 3}, /* Doom II switches */ + {"SW1ROCK", "SW2ROCK", 3}, + {"SW1MET2", "SW2MET2", 3}, + {"SW1WDMET", "SW2WDMET", 3}, + {"SW1BRIK", "SW2BRIK", 3}, + {"SW1MOD1", "SW2MOD1", 3}, + {"SW1ZIM", "SW2ZIM", 3}, + {"SW1STON6", "SW2STON6", 3}, + {"SW1TEK", "SW2TEK", 3}, + {"SW1MARB", "SW2MARB", 3}, + {"SW1SKULL", "SW2SKULL", 3}, }; -int switchlist[MAXSWITCHES * 2]; -int numswitches; -button_t buttonlist[MAXBUTTONS]; +static int g_numswitches; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +int switchlist[MAXSWITCHES * 2]; +button_t buttonlist[MAXBUTTONS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Start a button counting down till it turns off. */ -// -// P_InitSwitchList -// Only called at game initialization. -// -void P_InitSwitchList(void) +static void p_start_button(line_t *line, bwhere_e w, int texture, int time) { - int i, slindex, episode; + int i; - // Note that this is called "episode" here but it's actually something - // quite different. As we progress from Shareware->Registered->Doom II - // we support more switch textures. - switch (gamemode) + /* See if button is already pressed */ + + for (i = 0; i < MAXBUTTONS; i++) { - case registered: - case retail: - episode = 2; - break; - case commercial: - episode = 3; - break; - default: - episode = 1; - break; + if (buttonlist[i].btimer && buttonlist[i].line == line) + { + return; + } } - slindex = 0; - - for (i = 0; i < arrlen(alphSwitchList); i++) + for (i = 0; i < MAXBUTTONS; i++) { - if (alphSwitchList[i].episode <= episode) - { - switchlist[slindex++] = - R_TextureNumForName(DEH_String(alphSwitchList[i].name1)); - switchlist[slindex++] = - R_TextureNumForName(DEH_String(alphSwitchList[i].name2)); - } + if (!buttonlist[i].btimer) + { + buttonlist[i].line = line; + buttonlist[i].where = w; + buttonlist[i].btexture = texture; + buttonlist[i].btimer = time; + buttonlist[i].soundorg = &line->frontsector->soundorg; + return; + } } - numswitches = slindex / 2; - switchlist[slindex] = -1; + i_error("P_StartButton: no button slots left!"); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -// Start a button counting down till it turns off. -// -void -P_StartButton -( line_t* line, - bwhere_e w, - int texture, - int time ) +/* p_init_switch_list + * Only called at game initialization. + */ + +void p_init_switch_list(void) { - int i; - - // See if button is already pressed - for (i = 0;i < MAXBUTTONS;i++) + int i; + int slindex; + int episode; + + /* Note that this is called "episode" here but it's actually something + * quite different. As we progress from Shareware->Registered->Doom II + * we support more switch textures. + */ + + switch (gamemode) { - if (buttonlist[i].btimer - && buttonlist[i].line == line) - { - - return; - } + case registered: + case retail: + episode = 2; + break; + case commercial: + episode = 3; + break; + default: + episode = 1; + break; } - - - for (i = 0;i < MAXBUTTONS;i++) + slindex = 0; + + for (i = 0; i < arrlen(g_alph_switch_list); i++) { - if (!buttonlist[i].btimer) - { - buttonlist[i].line = line; - buttonlist[i].where = w; - buttonlist[i].btexture = texture; - buttonlist[i].btimer = time; - buttonlist[i].soundorg = &line->frontsector->soundorg; - return; - } + if (g_alph_switch_list[i].episode <= episode) + { + switchlist[slindex++] = + r_texture_num_for_name((g_alph_switch_list[i].name1)); + switchlist[slindex++] = + r_texture_num_for_name((g_alph_switch_list[i].name2)); + } } - - I_Error("P_StartButton: no button slots left!"); + + g_numswitches = slindex / 2; + switchlist[slindex] = -1; } +/* Function that changes wall texture. + * Tell it if switch is ok to use again (1=yes, it's a button). + */ +void p_change_switch_texture(line_t *line, int use_again) +{ + int tex_top; + int tex_mid; + int tex_bot; + int i; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + int sound; +#endif + if (!use_again) line->special = 0; + tex_top = sides[line->sidenum[0]].toptexture; + tex_mid = sides[line->sidenum[0]].midtexture; + tex_bot = sides[line->sidenum[0]].bottomtexture; -// -// Function that changes wall texture. -// Tell it if switch is ok to use again (1=yes, it's a button). -// -void -P_ChangeSwitchTexture -( line_t* line, - int useAgain ) -{ - int texTop; - int texMid; - int texBot; - int i; - int sound; - - if (!useAgain) - line->special = 0; - - texTop = sides[line->sidenum[0]].toptexture; - texMid = sides[line->sidenum[0]].midtexture; - texBot = sides[line->sidenum[0]].bottomtexture; - - sound = sfx_swtchn; - - // EXIT SWITCH? - if (line->special == 11) - sound = sfx_swtchx; - - for (i = 0;i < numswitches*2;i++) +#ifdef CONFIG_GAMES_NXDOOM_SOUND + sound = SFX_SWTCHN; + + /* EXIT SWITCH? */ + + if (line->special == 11) sound = SFX_SWTCHX; +#endif + + for (i = 0; i < g_numswitches * 2; i++) { - if (switchlist[i] == texTop) - { - S_StartSound(buttonlist->soundorg,sound); - sides[line->sidenum[0]].toptexture = switchlist[i^1]; - - if (useAgain) - P_StartButton(line,top,switchlist[i],BUTTONTIME); - - return; - } - else - { - if (switchlist[i] == texMid) - { - S_StartSound(buttonlist->soundorg,sound); - sides[line->sidenum[0]].midtexture = switchlist[i^1]; - - if (useAgain) - P_StartButton(line, middle,switchlist[i],BUTTONTIME); - - return; - } - else - { - if (switchlist[i] == texBot) - { - S_StartSound(buttonlist->soundorg,sound); - sides[line->sidenum[0]].bottomtexture = switchlist[i^1]; - - if (useAgain) - P_StartButton(line, bottom,switchlist[i],BUTTONTIME); - - return; - } - } - } + if (switchlist[i] == tex_top) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(buttonlist->soundorg, sound); +#endif + sides[line->sidenum[0]].toptexture = switchlist[i ^ 1]; + + if (use_again) + { + p_start_button(line, top, switchlist[i], BUTTONTIME); + } + + return; + } + else + { + if (switchlist[i] == tex_mid) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(buttonlist->soundorg, sound); +#endif + sides[line->sidenum[0]].midtexture = switchlist[i ^ 1]; + + if (use_again) + p_start_button(line, middle, switchlist[i], BUTTONTIME); + + return; + } + else + { + if (switchlist[i] == tex_bot) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(buttonlist->soundorg, sound); +#endif + sides[line->sidenum[0]].bottomtexture = switchlist[i ^ 1]; + + if (use_again) + p_start_button(line, bottom, switchlist[i], BUTTONTIME); + + return; + } + } + } } } +/* p_use_special_line + * Called when a thing uses a special line. + * Only the front sides of lines are usable. + */ +boolean p_use_special_line(mobj_t *thing, line_t *line, int side) +{ + /* Err... + * Use the back sides of VERY SPECIAL lines... + */ + if (side) + { + switch (line->special) + { + case 124: + /* Sliding door open & close + * UNUSED? + */ + break; -// -// P_UseSpecialLine -// Called when a thing uses a special line. -// Only the front sides of lines are usable. -// -boolean -P_UseSpecialLine -( mobj_t* thing, - line_t* line, - int side ) -{ - - // Err... - // Use the back sides of VERY SPECIAL lines... - if (side) - { - switch(line->special) - { - case 124: - // Sliding door open&close - // UNUSED? - break; - - default: - return false; - break; - } + default: + return false; + break; + } } - - // Switches that other things can activate. - if (!thing->player) + /* Switches that other things can activate. */ + + if (!thing->player) { - // never open secret doors - if (line->flags & ML_SECRET) - return false; - - switch(line->special) - { - case 1: // MANUAL DOOR RAISE - case 32: // MANUAL BLUE - case 33: // MANUAL RED - case 34: // MANUAL YELLOW - break; - - default: - return false; - break; - } + /* never open secret doors */ + + if (line->flags & ML_SECRET) return false; + + switch (line->special) + { + case 1: /* MANUAL DOOR RAISE */ + case 32: /* MANUAL BLUE */ + case 33: /* MANUAL RED */ + case 34: /* MANUAL YELLOW */ + break; + + default: + return false; + break; + } } - - // do something - switch (line->special) + /* do something */ + + switch (line->special) { - // MANUALS - case 1: // Vertical Door - case 26: // Blue Door/Locked - case 27: // Yellow Door /Locked - case 28: // Red Door /Locked - - case 31: // Manual door open - case 32: // Blue locked door open - case 33: // Red locked door open - case 34: // Yellow locked door open - - case 117: // Blazing door raise - case 118: // Blazing door open - EV_VerticalDoor (line, thing); - break; - - //UNUSED - Door Slide Open&Close - // case 124: - // EV_SlidingDoor (line, thing); - // break; - - // SWITCHES - case 7: - // Build Stairs - if (EV_BuildStairs(line,build8)) - P_ChangeSwitchTexture(line,0); - break; - - case 9: - // Change Donut - if (EV_DoDonut(line)) - P_ChangeSwitchTexture(line,0); - break; - - case 11: - // Exit level - P_ChangeSwitchTexture(line,0); - G_ExitLevel (); - break; - - case 14: - // Raise Floor 32 and change texture - if (EV_DoPlat(line,raiseAndChange,32)) - P_ChangeSwitchTexture(line,0); - break; - - case 15: - // Raise Floor 24 and change texture - if (EV_DoPlat(line,raiseAndChange,24)) - P_ChangeSwitchTexture(line,0); - break; - - case 18: - // Raise Floor to next highest floor - if (EV_DoFloor(line, raiseFloorToNearest)) - P_ChangeSwitchTexture(line,0); - break; - - case 20: - // Raise Plat next highest floor and change texture - if (EV_DoPlat(line,raiseToNearestAndChange,0)) - P_ChangeSwitchTexture(line,0); - break; - - case 21: - // PlatDownWaitUpStay - if (EV_DoPlat(line,downWaitUpStay,0)) - P_ChangeSwitchTexture(line,0); - break; - - case 23: - // Lower Floor to Lowest - if (EV_DoFloor(line,lowerFloorToLowest)) - P_ChangeSwitchTexture(line,0); - break; - - case 29: - // Raise Door - if (EV_DoDoor(line,vld_normal)) - P_ChangeSwitchTexture(line,0); - break; - - case 41: - // Lower Ceiling to Floor - if (EV_DoCeiling(line,lowerToFloor)) - P_ChangeSwitchTexture(line,0); - break; - - case 71: - // Turbo Lower Floor - if (EV_DoFloor(line,turboLower)) - P_ChangeSwitchTexture(line,0); - break; - - case 49: - // Ceiling Crush And Raise - if (EV_DoCeiling(line,crushAndRaise)) - P_ChangeSwitchTexture(line,0); - break; - - case 50: - // Close Door - if (EV_DoDoor(line,vld_close)) - P_ChangeSwitchTexture(line,0); - break; - - case 51: - // Secret EXIT - P_ChangeSwitchTexture(line,0); - G_SecretExitLevel (); - break; - - case 55: - // Raise Floor Crush - if (EV_DoFloor(line,raiseFloorCrush)) - P_ChangeSwitchTexture(line,0); - break; - - case 101: - // Raise Floor - if (EV_DoFloor(line,raiseFloor)) - P_ChangeSwitchTexture(line,0); - break; - - case 102: - // Lower Floor to Surrounding floor height - if (EV_DoFloor(line,lowerFloor)) - P_ChangeSwitchTexture(line,0); - break; - - case 103: - // Open Door - if (EV_DoDoor(line,vld_open)) - P_ChangeSwitchTexture(line,0); - break; - - case 111: - // Blazing Door Raise (faster than TURBO!) - if (EV_DoDoor (line,vld_blazeRaise)) - P_ChangeSwitchTexture(line,0); - break; - - case 112: - // Blazing Door Open (faster than TURBO!) - if (EV_DoDoor (line,vld_blazeOpen)) - P_ChangeSwitchTexture(line,0); - break; - - case 113: - // Blazing Door Close (faster than TURBO!) - if (EV_DoDoor (line,vld_blazeClose)) - P_ChangeSwitchTexture(line,0); - break; - - case 122: - // Blazing PlatDownWaitUpStay - if (EV_DoPlat(line,blazeDWUS,0)) - P_ChangeSwitchTexture(line,0); - break; - - case 127: - // Build Stairs Turbo 16 - if (EV_BuildStairs(line,turbo16)) - P_ChangeSwitchTexture(line,0); - break; - - case 131: - // Raise Floor Turbo - if (EV_DoFloor(line,raiseFloorTurbo)) - P_ChangeSwitchTexture(line,0); - break; - - case 133: - // BlzOpenDoor BLUE - case 135: - // BlzOpenDoor RED - case 137: - // BlzOpenDoor YELLOW - if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) - P_ChangeSwitchTexture(line,0); - break; - - case 140: - // Raise Floor 512 - if (EV_DoFloor(line,raiseFloor512)) - P_ChangeSwitchTexture(line,0); - break; - - // BUTTONS - case 42: - // Close Door - if (EV_DoDoor(line,vld_close)) - P_ChangeSwitchTexture(line,1); - break; - - case 43: - // Lower Ceiling to Floor - if (EV_DoCeiling(line,lowerToFloor)) - P_ChangeSwitchTexture(line,1); - break; - - case 45: - // Lower Floor to Surrounding floor height - if (EV_DoFloor(line,lowerFloor)) - P_ChangeSwitchTexture(line,1); - break; - - case 60: - // Lower Floor to Lowest - if (EV_DoFloor(line,lowerFloorToLowest)) - P_ChangeSwitchTexture(line,1); - break; - - case 61: - // Open Door - if (EV_DoDoor(line,vld_open)) - P_ChangeSwitchTexture(line,1); - break; - - case 62: - // PlatDownWaitUpStay - if (EV_DoPlat(line,downWaitUpStay,1)) - P_ChangeSwitchTexture(line,1); - break; - - case 63: - // Raise Door - if (EV_DoDoor(line,vld_normal)) - P_ChangeSwitchTexture(line,1); - break; - - case 64: - // Raise Floor to ceiling - if (EV_DoFloor(line,raiseFloor)) - P_ChangeSwitchTexture(line,1); - break; - - case 66: - // Raise Floor 24 and change texture - if (EV_DoPlat(line,raiseAndChange,24)) - P_ChangeSwitchTexture(line,1); - break; - - case 67: - // Raise Floor 32 and change texture - if (EV_DoPlat(line,raiseAndChange,32)) - P_ChangeSwitchTexture(line,1); - break; - - case 65: - // Raise Floor Crush - if (EV_DoFloor(line,raiseFloorCrush)) - P_ChangeSwitchTexture(line,1); - break; - - case 68: - // Raise Plat to next highest floor and change texture - if (EV_DoPlat(line,raiseToNearestAndChange,0)) - P_ChangeSwitchTexture(line,1); - break; - - case 69: - // Raise Floor to next highest floor - if (EV_DoFloor(line, raiseFloorToNearest)) - P_ChangeSwitchTexture(line,1); - break; - - case 70: - // Turbo Lower Floor - if (EV_DoFloor(line,turboLower)) - P_ChangeSwitchTexture(line,1); - break; - - case 114: - // Blazing Door Raise (faster than TURBO!) - if (EV_DoDoor (line,vld_blazeRaise)) - P_ChangeSwitchTexture(line,1); - break; - - case 115: - // Blazing Door Open (faster than TURBO!) - if (EV_DoDoor (line,vld_blazeOpen)) - P_ChangeSwitchTexture(line,1); - break; - - case 116: - // Blazing Door Close (faster than TURBO!) - if (EV_DoDoor (line,vld_blazeClose)) - P_ChangeSwitchTexture(line,1); - break; - - case 123: - // Blazing PlatDownWaitUpStay - if (EV_DoPlat(line,blazeDWUS,0)) - P_ChangeSwitchTexture(line,1); - break; - - case 132: - // Raise Floor Turbo - if (EV_DoFloor(line,raiseFloorTurbo)) - P_ChangeSwitchTexture(line,1); - break; - - case 99: - // BlzOpenDoor BLUE - case 134: - // BlzOpenDoor RED - case 136: - // BlzOpenDoor YELLOW - if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) - P_ChangeSwitchTexture(line,1); - break; - - case 138: - // Light Turn On - EV_LightTurnOn(line,255); - P_ChangeSwitchTexture(line,1); - break; - - case 139: - // Light Turn Off - EV_LightTurnOn(line,35); - P_ChangeSwitchTexture(line,1); - break; - + /* MANUALS */ + + case 1: /* Vertical Door */ + case 26: /* Blue Door/Locked */ + case 27: /* Yellow Door /Locked */ + case 28: /* Red Door /Locked */ + + case 31: /* Manual door open */ + case 32: /* Blue locked door open */ + case 33: /* Red locked door open */ + case 34: /* Yellow locked door open */ + + case 117: /* Blazing door raise */ + case 118: /* Blazing door open */ + ev_vertical_door(line, thing); + break; + + /* UNUSED - Door Slide Open&Close + * case 124: + * ev_sliding_door (line, thing); + * break; + */ + + /* SWITCHES */ + + case 7: /* Build Stairs */ + if (ev_build_stairs(line, STAIR_BUILD8)) + p_change_switch_texture(line, 0); + break; + + case 9: /* Change Donut */ + if (ev_do_donut(line)) p_change_switch_texture(line, 0); + break; + + case 11: /* Exit level */ + p_change_switch_texture(line, 0); + g_exit_level(); + break; + + case 14: /* Raise Floor 32 and change texture */ + if (ev_do_plat(line, PLAT_RAISEANDCHANGE, 32)) + p_change_switch_texture(line, 0); + break; + + case 15: /* Raise Floor 24 and change texture */ + if (ev_do_plat(line, PLAT_RAISEANDCHANGE, 24)) + p_change_switch_texture(line, 0); + break; + + case 18: /* Raise Floor to next highest floor */ + if (ev_do_floor(line, FLOOR_RAISEFLOORTONEAREST)) + p_change_switch_texture(line, 0); + break; + + case 20: /* Raise Plat next highest floor and change texture */ + if (ev_do_plat(line, PLAT_RAISETONEARESTANDCHANGE, 0)) + p_change_switch_texture(line, 0); + break; + + case 21: /* PlatDownWaitUpStay */ + if (ev_do_plat(line, PLAT_DOWNWAITUPSTAY, 0)) + p_change_switch_texture(line, 0); + break; + + case 23: /* Lower Floor to Lowest */ + if (ev_do_floor(line, FLOOR_LOWERFLOORTOLOWEST)) + p_change_switch_texture(line, 0); + break; + + case 29: /* Raise Door */ + if (ev_do_door(line, VLD_NORMAL)) p_change_switch_texture(line, 0); + break; + + case 41: /* Lower Ceiling to Floor */ + if (ev_do_ceiling(line, CEIL_LOWERTOFLOOR)) + p_change_switch_texture(line, 0); + break; + + case 71: /* Turbo Lower Floor */ + if (ev_do_floor(line, FLOOR_TURBOLOWER)) + p_change_switch_texture(line, 0); + break; + + case 49: /* Ceiling Crush And Raise */ + if (ev_do_ceiling(line, CEIL_CRUSHANDRAISE)) + p_change_switch_texture(line, 0); + break; + + case 50: /* Close Door */ + if (ev_do_door(line, VLD_CLOSE)) p_change_switch_texture(line, 0); + break; + + case 51: /* Secret EXIT */ + p_change_switch_texture(line, 0); + g_secret_exit_level(); + break; + + case 55: /* Raise Floor Crush */ + if (ev_do_floor(line, FLOOR_RAISEFLOORCRUSH)) + p_change_switch_texture(line, 0); + break; + + case 101: /* Raise Floor */ + if (ev_do_floor(line, FLOOR_RAISEFLOOR)) + p_change_switch_texture(line, 0); + break; + + case 102: /* Lower Floor to Surrounding floor height */ + if (ev_do_floor(line, FLOOR_LOWERFLOOR)) + p_change_switch_texture(line, 0); + break; + + case 103: /* Open Door */ + if (ev_do_door(line, VLD_OPEN)) p_change_switch_texture(line, 0); + break; + + case 111: /* Blazing Door Raise (faster than TURBO!) */ + if (ev_do_door(line, VLD_BLAZERAISE)) p_change_switch_texture(line, 0); + break; + + case 112: /* Blazing Door Open (faster than TURBO!) */ + if (ev_do_door(line, VLD_BLAZEOPEN)) p_change_switch_texture(line, 0); + break; + + case 113: /* Blazing Door Close (faster than TURBO!) */ + if (ev_do_door(line, VLD_BLAZECLOSE)) p_change_switch_texture(line, 0); + break; + + case 122: /* Blazing PlatDownWaitUpStay */ + if (ev_do_plat(line, PLAT_BLAZEDWUS, 0)) + p_change_switch_texture(line, 0); + break; + + case 127: /* Build Stairs Turbo 16 */ + if (ev_build_stairs(line, STAIR_TURBO16)) + p_change_switch_texture(line, 0); + break; + + case 131: /* Raise Floor Turbo */ + if (ev_do_floor(line, FLOOR_RAISEFLOORTURBO)) + p_change_switch_texture(line, 0); + break; + + case 133: /* BlzOpenDoor BLUE */ + case 135: /* BlzOpenDoor RED */ + case 137: /* BlzOpenDoor YELLOW */ + if (ev_do_locked_door(line, VLD_BLAZEOPEN, thing)) + p_change_switch_texture(line, 0); + break; + + case 140: /* Raise Floor 512 */ + if (ev_do_floor(line, FLOOR_RAISEFLOOR512)) + p_change_switch_texture(line, 0); + break; + + /* BUTTONS */ + + case 42: /* Close Door */ + if (ev_do_door(line, VLD_CLOSE)) p_change_switch_texture(line, 1); + break; + + case 43: /* Lower Ceiling to Floor */ + if (ev_do_ceiling(line, CEIL_LOWERTOFLOOR)) + p_change_switch_texture(line, 1); + break; + + case 45: /* Lower Floor to Surrounding floor height */ + if (ev_do_floor(line, FLOOR_LOWERFLOOR)) + p_change_switch_texture(line, 1); + break; + + case 60: /* Lower Floor to Lowest */ + if (ev_do_floor(line, FLOOR_LOWERFLOORTOLOWEST)) + p_change_switch_texture(line, 1); + break; + + case 61: /* Open Door */ + if (ev_do_door(line, VLD_OPEN)) p_change_switch_texture(line, 1); + break; + + case 62: /* PlatDownWaitUpStay */ + if (ev_do_plat(line, PLAT_DOWNWAITUPSTAY, 1)) + p_change_switch_texture(line, 1); + break; + + case 63: /* Raise Door */ + if (ev_do_door(line, VLD_NORMAL)) p_change_switch_texture(line, 1); + break; + + case 64: /* Raise Floor to ceiling */ + if (ev_do_floor(line, FLOOR_RAISEFLOOR)) + p_change_switch_texture(line, 1); + break; + + case 66: /* Raise Floor 24 and change texture */ + if (ev_do_plat(line, PLAT_RAISEANDCHANGE, 24)) + p_change_switch_texture(line, 1); + break; + + case 67: /* Raise Floor 32 and change texture */ + if (ev_do_plat(line, PLAT_RAISEANDCHANGE, 32)) + p_change_switch_texture(line, 1); + break; + + case 65: /* Raise Floor Crush */ + if (ev_do_floor(line, FLOOR_RAISEFLOORCRUSH)) + p_change_switch_texture(line, 1); + break; + + case 68: /* Raise Plat to next highest floor and change texture */ + if (ev_do_plat(line, PLAT_RAISETONEARESTANDCHANGE, 0)) + p_change_switch_texture(line, 1); + break; + + case 69: /* Raise Floor to next highest floor */ + if (ev_do_floor(line, FLOOR_RAISEFLOORTONEAREST)) + p_change_switch_texture(line, 1); + break; + + case 70: /* Turbo Lower Floor */ + if (ev_do_floor(line, FLOOR_TURBOLOWER)) + p_change_switch_texture(line, 1); + break; + + case 114: /* Blazing Door Raise (faster than TURBO!) */ + if (ev_do_door(line, VLD_BLAZERAISE)) p_change_switch_texture(line, 1); + break; + + case 115: /* Blazing Door Open (faster than TURBO!) */ + if (ev_do_door(line, VLD_BLAZEOPEN)) p_change_switch_texture(line, 1); + break; + + case 116: /* Blazing Door Close (faster than TURBO!) */ + if (ev_do_door(line, VLD_BLAZECLOSE)) p_change_switch_texture(line, 1); + break; + + case 123: /* Blazing PlatDownWaitUpStay */ + if (ev_do_plat(line, PLAT_BLAZEDWUS, 0)) + p_change_switch_texture(line, 1); + break; + + case 132: /* Raise Floor Turbo */ + if (ev_do_floor(line, FLOOR_RAISEFLOORTURBO)) + p_change_switch_texture(line, 1); + break; + + case 99: /* BlzOpenDoor BLUE */ + case 134: /* BlzOpenDoor RED */ + case 136: /* BlzOpenDoor YELLOW */ + if (ev_do_locked_door(line, VLD_BLAZEOPEN, thing)) + p_change_switch_texture(line, 1); + break; + + case 138: + + /* Light Turn On */ + + ev_light_turn_on(line, 255); + p_change_switch_texture(line, 1); + break; + + case 139: + + /* Light Turn Off */ + + ev_light_turn_on(line, 35); + p_change_switch_texture(line, 1); + break; } - - return true; -} + return true; +} diff --git a/games/NXDoom/src/doom/p_telept.c b/games/NXDoom/src/doom/p_telept.c index 8e2d5e16c98..3986a0543d6 100644 --- a/games/NXDoom/src/doom/p_telept.c +++ b/games/NXDoom/src/doom/p_telept.c @@ -1,132 +1,141 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Teleportation. -// - - - +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_telept.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Teleportation. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "doomdef.h" #include "doomstat.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "p_local.h" +/* State. */ -// Data. -#include "sounds.h" - -// State. #include "r_state.h" +/**************************************************************************** + * Public Functions + ****************************************************************************/ - -// -// TELEPORTATION -// -int -EV_Teleport -( line_t* line, - int side, - mobj_t* thing ) +int ev_teleport(line_t *line, int side, mobj_t *thing) { - int i; - int tag; - mobj_t* m; - mobj_t* fog; - unsigned an; - thinker_t* thinker; - sector_t* sector; - fixed_t oldx; - fixed_t oldy; - fixed_t oldz; - - // don't teleport missiles - if (thing->flags & MF_MISSILE) - return 0; - - // Don't teleport if hit back of line, - // so you can get out of teleporter. - if (side == 1) - return 0; - - - tag = line->tag; - for (i = 0; i < numsectors; i++) + int i; + int tag; + mobj_t *m; + mobj_t *fog; + unsigned an; + thinker_t *thinker; + sector_t *sector; + fixed_t oldx; + fixed_t oldy; + fixed_t oldz; + + /* don't teleport missiles */ + + if (thing->flags & MF_MISSILE) return 0; + + /* Don't teleport if hit back of line, so you can get out of teleporter. */ + + if (side == 1) return 0; + + tag = line->tag; + for (i = 0; i < numsectors; i++) { - if (sectors[ i ].tag == tag ) - { - for (thinker = thinkercap.next; - thinker != &thinkercap; - thinker = thinker->next) - { - // not a mobj - if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - m = (mobj_t *)thinker; - - // not a teleportman - if (m->type != MT_TELEPORTMAN ) - continue; - - sector = m->subsector->sector; - // wrong sector - if (sector-sectors != i ) - continue; - - oldx = thing->x; - oldy = thing->y; - oldz = thing->z; - - if (!P_TeleportMove (thing, m->x, m->y)) - return 0; - - // The first Final Doom executable does not set thing->z - // when teleporting. This quirk is unique to this - // particular version; the later version included in - // some versions of the Id Anthology fixed this. - - if (gameversion != exe_final) - thing->z = thing->floorz; - - if (thing->player) - thing->player->viewz = thing->z+thing->player->viewheight; - - // spawn teleport fog at source and destination - fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); - S_StartSound (fog, sfx_telept); - an = m->angle >> ANGLETOFINESHIFT; - fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] - , thing->z, MT_TFOG); - - // emit sound, where? - S_StartSound (fog, sfx_telept); - - // don't move for a bit - if (thing->player) - thing->reactiontime = 18; - - thing->angle = m->angle; - thing->momx = thing->momy = thing->momz = 0; - return 1; - } - } + if (sectors[i].tag == tag) + { + for (thinker = thinkercap.next; thinker != &thinkercap; + thinker = thinker->next) + { + /* not a mobj */ + + if (thinker->function.acp1 != (actionf_p1)p_mobj_thinker) + continue; + + m = (mobj_t *)thinker; + + /* not a teleportman */ + + if (m->type != MT_TELEPORTMAN) continue; + + sector = m->subsector->sector; + + /* wrong sector */ + + if (sector - sectors != i) continue; + + oldx = thing->x; + oldy = thing->y; + oldz = thing->z; + + if (!p_teleport_move(thing, m->x, m->y)) return 0; + + /* The first Final Doom executable does not set thing->z + * when teleporting. This quirk is unique to this + * particular version; the later version included in + * some versions of the Id Anthology fixed this. + */ + + if (gameversion != exe_final) thing->z = thing->floorz; + + if (thing->player) + thing->player->viewz = thing->z + thing->player->viewheight; + + /* spawn teleport fog at source and destination */ + + fog = p_spawn_mobj(oldx, oldy, oldz, MT_TFOG); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(fog, SFX_TELEPT); +#endif + an = m->angle >> ANGLETOFINESHIFT; + fog = p_spawn_mobj(m->x + 20 * finecosine[an], + m->y + 20 * finesine[an], + thing->z, MT_TFOG); + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + + /* emit sound, where? */ + + s_start_sound(fog, SFX_TELEPT); +#else + UNUSED(fog); +#endif + + /* don't move for a bit */ + + if (thing->player) thing->reactiontime = 18; + + thing->angle = m->angle; + thing->momx = thing->momy = thing->momz = 0; + return 1; + } + } } - return 0; -} + return 0; +} diff --git a/games/NXDoom/src/doom/p_tick.c b/games/NXDoom/src/doom/p_tick.c index 5a93b80f13b..d2655dd18b4 100644 --- a/games/NXDoom/src/doom/p_tick.c +++ b/games/NXDoom/src/doom/p_tick.c @@ -1,153 +1,145 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Archiving: SaveGame I/O. -// Thinker, Ticker. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/p_tick.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Archiving: SaveGame I/O. + * Thinker, Ticker. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include "z_zone.h" #include "p_local.h" +#include "z_zone.h" #include "doomstat.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ -int leveltime; +int leveltime; -// -// THINKERS -// All thinkers should be allocated by Z_Malloc -// so they can be operated on uniformly. -// The actual structures will vary in size, -// but the first element must be thinker_t. -// +/* THINKERS + * All thinkers should be allocated by z_malloc + * so they can be operated on uniformly. + * The actual structures will vary in size, + * but the first element must be thinker_t. + */ +/* Both the head and tail of the thinker list. */ +thinker_t thinkercap; -// Both the head and tail of the thinker list. -thinker_t thinkercap; +/**************************************************************************** + * Private Functions + ****************************************************************************/ - -// -// P_InitThinkers -// -void P_InitThinkers (void) +static void p_run_thinkers(void) { - thinkercap.prev = thinkercap.next = &thinkercap; + thinker_t *currentthinker, *nextthinker; + + currentthinker = thinkercap.next; + while (currentthinker != &thinkercap) + { + if (currentthinker->function.acv == (actionf_v)(-1)) + { + /* time to remove it */ + + nextthinker = currentthinker->next; + currentthinker->next->prev = currentthinker->prev; + currentthinker->prev->next = currentthinker->next; + z_free(currentthinker); + } + else + { + if (currentthinker->function.acp1) + currentthinker->function.acp1(currentthinker); + nextthinker = currentthinker->next; + } + + currentthinker = nextthinker; + } } +/**************************************************************************** + * Public Functions + ****************************************************************************/ +void p_init_thinkers(void) +{ + thinkercap.prev = thinkercap.next = &thinkercap; +} +/* p_add_thinker + * Adds a new thinker at the end of the list. + */ -// -// P_AddThinker -// Adds a new thinker at the end of the list. -// -void P_AddThinker (thinker_t* thinker) +void p_add_thinker(thinker_t *thinker) { - thinkercap.prev->next = thinker; - thinker->next = &thinkercap; - thinker->prev = thinkercap.prev; - thinkercap.prev = thinker; + thinkercap.prev->next = thinker; + thinker->next = &thinkercap; + thinker->prev = thinkercap.prev; + thinkercap.prev = thinker; } +/* p_remove_thinker Deallocation is lazy -- it will not actually be freed + * until its thinking turn comes up. + */ - -// -// P_RemoveThinker -// Deallocation is lazy -- it will not actually be freed -// until its thinking turn comes up. -// -void P_RemoveThinker (thinker_t* thinker) +void p_remove_thinker(thinker_t *thinker) { - // FIXME: NOP. + /* FIXME: NOP. */ + thinker->function.acv = (actionf_v)(-1); } - - -// -// P_AllocateThinker -// Allocates memory and adds a new thinker at the end of the list. -// -void P_AllocateThinker (thinker_t* thinker) +void p_ticker(void) { -} + int i; + /* run the tic */ + if (paused) return; -// -// P_RunThinkers -// -void P_RunThinkers (void) -{ - thinker_t *currentthinker, *nextthinker; + /* pause if in menu and at least one tic has been run */ - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) + if (!netgame && g_menuactive && !demoplayback && + players[consoleplayer].viewz != 1) { - if ( currentthinker->function.acv == (actionf_v)(-1) ) - { - // time to remove it - nextthinker = currentthinker->next; - currentthinker->next->prev = currentthinker->prev; - currentthinker->prev->next = currentthinker->next; - Z_Free(currentthinker); - } - else - { - if (currentthinker->function.acp1) - currentthinker->function.acp1 (currentthinker); - nextthinker = currentthinker->next; - } - currentthinker = nextthinker; + return; } -} + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + p_player_think(&players[i]); + } + } + p_run_thinkers(); + p_update_specials(); + p_respawn_specials(); -// -// P_Ticker -// + /* for par times */ -void P_Ticker (void) -{ - int i; - - // run the tic - if (paused) - return; - - // pause if in menu and at least one tic has been run - if ( !netgame - && menuactive - && !demoplayback - && players[consoleplayer].viewz != 1) - { - return; - } - - - for (i=0 ; i>= ANGLETOFINESHIFT; - - player->mo->momx += FixedMul(move,finecosine[angle]); - player->mo->momy += FixedMul(move,finesine[angle]); + angle >>= ANGLETOFINESHIFT; + + player->mo->momx += fixed_mul(move, finecosine[angle]); + player->mo->momy += fixed_mul(move, finesine[angle]); } +/* Calculate the walking / running height adjustment */ +static void p_calc_height(player_t *player) +{ + int angle; + fixed_t bob; + /* Regular movement bobbing + * (needs to be calculated for gun swing + * even if not on ground) + * OPTIMIZE: tablify angle + * Note: a LUT allows for effects + * like a ramp with low health. + */ -// -// P_CalcHeight -// Calculate the walking / running height adjustment -// -void P_CalcHeight (player_t* player) -{ - int angle; - fixed_t bob; - - // Regular movement bobbing - // (needs to be calculated for gun swing - // even if not on ground) - // OPTIMIZE: tablify angle - // Note: a LUT allows for effects - // like a ramp with low health. - player->bob = - FixedMul (player->mo->momx, player->mo->momx) - + FixedMul (player->mo->momy,player->mo->momy); - - player->bob >>= 2; - - if (player->bob>MAXBOB) - player->bob = MAXBOB; - - if ((player->cheats & CF_NOMOMENTUM) || !onground) + player->bob = fixed_mul(player->mo->momx, player->mo->momx) + + fixed_mul(player->mo->momy, player->mo->momy); + + player->bob >>= 2; + + if (player->bob > MAXBOB) player->bob = MAXBOB; + + if ((player->cheats & CF_NOMOMENTUM) || !onground) { - player->viewz = player->mo->z + VIEWHEIGHT; + player->viewz = player->mo->z + VIEWHEIGHT; - if (player->viewz > player->mo->ceilingz-4*FRACUNIT) - player->viewz = player->mo->ceilingz-4*FRACUNIT; + if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) + player->viewz = player->mo->ceilingz - 4 * FRACUNIT; - player->viewz = player->mo->z + player->viewheight; - return; + player->viewz = player->mo->z + player->viewheight; + return; } - - angle = (FINEANGLES/20*leveltime)&FINEMASK; - bob = FixedMul ( player->bob/2, finesine[angle]); - - // move viewheight - if (player->playerstate == PST_LIVE) + angle = (FINEANGLES / 20 * leveltime) & FINEMASK; + bob = fixed_mul(player->bob / 2, finesine[angle]); + + /* move viewheight */ + + if (player->playerstate == PST_LIVE) { - player->viewheight += player->deltaviewheight; - - if (player->viewheight > VIEWHEIGHT) - { - player->viewheight = VIEWHEIGHT; - player->deltaviewheight = 0; - } - - if (player->viewheight < VIEWHEIGHT/2) - { - player->viewheight = VIEWHEIGHT/2; - if (player->deltaviewheight <= 0) - player->deltaviewheight = 1; - } - - if (player->deltaviewheight) - { - player->deltaviewheight += FRACUNIT/4; - if (!player->deltaviewheight) - player->deltaviewheight = 1; - } + player->viewheight += player->deltaviewheight; + + if (player->viewheight > VIEWHEIGHT) + { + player->viewheight = VIEWHEIGHT; + player->deltaviewheight = 0; + } + + if (player->viewheight < VIEWHEIGHT / 2) + { + player->viewheight = VIEWHEIGHT / 2; + if (player->deltaviewheight <= 0) player->deltaviewheight = 1; + } + + if (player->deltaviewheight) + { + player->deltaviewheight += FRACUNIT / 4; + if (!player->deltaviewheight) player->deltaviewheight = 1; + } } - player->viewz = player->mo->z + player->viewheight + bob; - if (player->viewz > player->mo->ceilingz-4*FRACUNIT) - player->viewz = player->mo->ceilingz-4*FRACUNIT; + player->viewz = player->mo->z + player->viewheight + bob; + + if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) + player->viewz = player->mo->ceilingz - 4 * FRACUNIT; } +static void p_move_player(player_t *player) +{ + ticcmd_t *cmd; + cmd = &player->cmd; -// -// P_MovePlayer -// -void P_MovePlayer (player_t* player) -{ - ticcmd_t* cmd; - - cmd = &player->cmd; - - player->mo->angle += (cmd->angleturn<mo->z <= player->mo->floorz); - - if (cmd->forwardmove && onground) - P_Thrust (player, player->mo->angle, cmd->forwardmove*2048); - - if (cmd->sidemove && onground) - P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048); - - if ( (cmd->forwardmove || cmd->sidemove) - && player->mo->state == &states[S_PLAY] ) + player->mo->angle += (cmd->angleturn << FRACBITS); + + /* Do not let the player control movement if not onground. */ + + onground = (player->mo->z <= player->mo->floorz); + + if (cmd->forwardmove && onground) + p_thrust(player, player->mo->angle, cmd->forwardmove * 2048); + + if (cmd->sidemove && onground) + p_thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2048); + + if ((cmd->forwardmove || cmd->sidemove) && + player->mo->state == &states[S_PLAY]) { - P_SetMobjState (player->mo, S_PLAY_RUN1); + p_set_mobj_state(player->mo, S_PLAY_RUN1); } -} +} +/* P_DeathThink + * Fall on your face when dying. + * Decrease POV height to floor height. + */ +static void p_death_think(player_t *player) +{ + angle_t angle; + angle_t delta; -// -// P_DeathThink -// Fall on your face when dying. -// Decrease POV height to floor height. -// -#define ANG5 (ANG90/18) + p_move_psprites(player); -void P_DeathThink (player_t* player) -{ - angle_t angle; - angle_t delta; - - P_MovePsprites (player); - - // fall to the ground - if (player->viewheight > 6*FRACUNIT) - player->viewheight -= FRACUNIT; - - if (player->viewheight < 6*FRACUNIT) - player->viewheight = 6*FRACUNIT; - - player->deltaviewheight = 0; - onground = (player->mo->z <= player->mo->floorz); - P_CalcHeight (player); - - if (player->attacker && player->attacker != player->mo) + /* fall to the ground */ + + if (player->viewheight > 6 * FRACUNIT) player->viewheight -= FRACUNIT; + + if (player->viewheight < 6 * FRACUNIT) player->viewheight = 6 * FRACUNIT; + + player->deltaviewheight = 0; + onground = (player->mo->z <= player->mo->floorz); + p_calc_height(player); + + if (player->attacker && player->attacker != player->mo) { - angle = R_PointToAngle2 (player->mo->x, - player->mo->y, - player->attacker->x, - player->attacker->y); - - delta = angle - player->mo->angle; - - if (delta < ANG5 || delta > (unsigned)-ANG5) - { - // Looking at killer, - // so fade damage flash down. - player->mo->angle = angle; - - if (player->damagecount) - player->damagecount--; - } - else if (delta < ANG180) - player->mo->angle += ANG5; - else - player->mo->angle -= ANG5; + angle = r_point_to_angle2(player->mo->x, player->mo->y, + player->attacker->x, player->attacker->y); + + delta = angle - player->mo->angle; + + if (delta < ANG5 || delta > (unsigned)-ANG5) + { + /* Looking at killer, so fade damage flash down. */ + + player->mo->angle = angle; + + if (player->damagecount) player->damagecount--; + } + else if (delta < ANG180) + player->mo->angle += ANG5; + else + player->mo->angle -= ANG5; } - else if (player->damagecount) - player->damagecount--; - + else if (player->damagecount) + player->damagecount--; - if (player->cmd.buttons & BT_USE) - player->playerstate = PST_REBORN; + if (player->cmd.buttons & BT_USE) player->playerstate = PST_REBORN; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ - -// -// P_PlayerThink -// -void P_PlayerThink (player_t* player) +void p_player_think(player_t *player) { - ticcmd_t* cmd; - weapontype_t newweapon; - - // fixme: do this in the cheat code - if (player->cheats & CF_NOCLIP) - player->mo->flags |= MF_NOCLIP; - else - player->mo->flags &= ~MF_NOCLIP; - - // chain saw run forward - cmd = &player->cmd; - if (player->mo->flags & MF_JUSTATTACKED) + ticcmd_t *cmd; + weapontype_t newweapon; + + /* fixme: do this in the cheat code */ + + if (player->cheats & CF_NOCLIP) + player->mo->flags |= MF_NOCLIP; + else + player->mo->flags &= ~MF_NOCLIP; + + /* chain saw run forward */ + + cmd = &player->cmd; + if (player->mo->flags & MF_JUSTATTACKED) { - cmd->angleturn = 0; - cmd->forwardmove = 0xc800/512; - cmd->sidemove = 0; - player->mo->flags &= ~MF_JUSTATTACKED; + cmd->angleturn = 0; + cmd->forwardmove = 0xc800 / 512; + cmd->sidemove = 0; + player->mo->flags &= ~MF_JUSTATTACKED; } - - - if (player->playerstate == PST_DEAD) + + if (player->playerstate == PST_DEAD) { - P_DeathThink (player); - return; + p_death_think(player); + return; } - - // Move around. - // Reactiontime is used to prevent movement - // for a bit after a teleport. - if (player->mo->reactiontime) - player->mo->reactiontime--; - else - P_MovePlayer (player); - - P_CalcHeight (player); - - if (player->mo->subsector->sector->special) - P_PlayerInSpecialSector (player); - - // Check for weapon change. - - // A special event has no other buttons. - if (cmd->buttons & BT_SPECIAL) - cmd->buttons = 0; - - if (cmd->buttons & BT_CHANGE) + + /* Move around. + * Reactiontime is used to prevent movement for a bit after a teleport. + */ + + if (player->mo->reactiontime) + player->mo->reactiontime--; + else + p_move_player(player); + + p_calc_height(player); + + if (player->mo->subsector->sector->special) { - // The actual changing of the weapon is done - // when the weapon psprite can do it - // (read: not in the middle of an attack). - newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT; - - if (newweapon == wp_fist - && player->weaponowned[wp_chainsaw] - && !(player->readyweapon == wp_chainsaw - && player->powers[pw_strength])) - { - newweapon = wp_chainsaw; - } - - if ( (gamemode == commercial) - && newweapon == wp_shotgun - && player->weaponowned[wp_supershotgun] - && player->readyweapon != wp_supershotgun) - { - newweapon = wp_supershotgun; - } - - - if (player->weaponowned[newweapon] - && newweapon != player->readyweapon) - { - // Do not go to plasma or BFG in shareware, - // even if cheated. - if ((newweapon != wp_plasma - && newweapon != wp_bfg) - || (gamemode != shareware) ) - { - player->pendingweapon = newweapon; - } - } + p_player_in_special_sector(player); } - - // check for use - if (cmd->buttons & BT_USE) + + /* Check for weapon change. */ + + /* A special event has no other buttons. */ + + if (cmd->buttons & BT_SPECIAL) cmd->buttons = 0; + + if (cmd->buttons & BT_CHANGE) { - if (!player->usedown) - { - P_UseLines (player); - player->usedown = true; - } + /* The actual changing of the weapon is done + * when the weapon psprite can do it + * (read: not in the middle of an attack). + */ + + newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; + + if (newweapon == wp_fist && player->weaponowned[wp_chainsaw] && + !(player->readyweapon == wp_chainsaw && + player->powers[pw_strength])) + { + newweapon = wp_chainsaw; + } + + if ((gamemode == commercial) && newweapon == wp_shotgun && + player->weaponowned[wp_supershotgun] && + player->readyweapon != wp_supershotgun) + { + newweapon = wp_supershotgun; + } + + if (player->weaponowned[newweapon] && newweapon != player->readyweapon) + { + /* Do not go to plasma or BFG in shareware, even if cheated. */ + + if ((newweapon != wp_plasma && newweapon != wp_bfg) || + (gamemode != shareware)) + { + player->pendingweapon = newweapon; + } + } } - else - player->usedown = false; - - // cycle psprites - P_MovePsprites (player); - - // Counters, time dependend power ups. - - // Strength counts up to diminish fade. - if (player->powers[pw_strength]) - player->powers[pw_strength]++; - - if (player->powers[pw_invulnerability]) - player->powers[pw_invulnerability]--; - - if (player->powers[pw_invisibility]) - if (! --player->powers[pw_invisibility] ) - player->mo->flags &= ~MF_SHADOW; - - if (player->powers[pw_infrared]) - player->powers[pw_infrared]--; - - if (player->powers[pw_ironfeet]) - player->powers[pw_ironfeet]--; - - if (player->damagecount) - player->damagecount--; - - if (player->bonuscount) - player->bonuscount--; - - - // Handling colormaps. - if (player->powers[pw_invulnerability]) + + /* check for use */ + + if (cmd->buttons & BT_USE) { - if (player->powers[pw_invulnerability] > 4*32 - || (player->powers[pw_invulnerability]&8) ) - player->fixedcolormap = INVERSECOLORMAP; - else - player->fixedcolormap = 0; + if (!player->usedown) + { + p_use_lines(player); + player->usedown = true; + } } - else if (player->powers[pw_infrared]) + else + player->usedown = false; + + /* cycle psprites */ + + p_move_psprites(player); + + /* Counters, time dependent power ups. */ + + /* Strength counts up to diminish fade. */ + + if (player->powers[pw_strength]) player->powers[pw_strength]++; + + if (player->powers[pw_invulnerability]) + player->powers[pw_invulnerability]--; + + if (player->powers[pw_invisibility]) { - if (player->powers[pw_infrared] > 4*32 - || (player->powers[pw_infrared]&8) ) - { - // almost full bright - player->fixedcolormap = 1; - } - else - player->fixedcolormap = 0; + if (!--player->powers[pw_invisibility]) + { + player->mo->flags &= ~MF_SHADOW; + } } - else - player->fixedcolormap = 0; -} + if (player->powers[pw_infrared]) player->powers[pw_infrared]--; + + if (player->powers[pw_ironfeet]) player->powers[pw_ironfeet]--; + if (player->damagecount) player->damagecount--; + + if (player->bonuscount) player->bonuscount--; + + /* Handling colormaps. */ + + if (player->powers[pw_invulnerability]) + { + if (player->powers[pw_invulnerability] > 4 * 32 || + (player->powers[pw_invulnerability] & 8)) + player->fixedcolormap = INVERSECOLORMAP; + else + player->fixedcolormap = 0; + } + else if (player->powers[pw_infrared]) + { + if (player->powers[pw_infrared] > 4 * 32 || + (player->powers[pw_infrared] & 8)) + { + /* almost full bright */ + + player->fixedcolormap = 1; + } + else + player->fixedcolormap = 0; + } + else + player->fixedcolormap = 0; +} diff --git a/games/NXDoom/src/doom/r_bsp.c b/games/NXDoom/src/doom/r_bsp.c index 755d2eefc67..605b21beaa8 100644 --- a/games/NXDoom/src/doom/r_bsp.c +++ b/games/NXDoom/src/doom/r_bsp.c @@ -1,23 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// BSP traversal, handling of LineSegs for rendering. -// - - - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_bsp.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * BSP traversal, handling of LineSegs for rendering. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "doomdef.h" @@ -29,555 +35,650 @@ #include "r_plane.h" #include "r_things.h" -// State. #include "doomstat.h" #include "r_state.h" -//#include "r_local.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* We must expand MAXSEGS to the theoretical limit of the number of solidsegs + * that can be generated in a scene by the DOOM engine. This was determined + * by Lee Killough during BOOM development to be a function of the + * screensize. The simplest thing we can do, other than fix this bug, is to + * let the game render overage and then bomb out by detecting the overflow + * after the fact. -haleyjd + */ +/* #define MAXSEGS 32 */ -seg_t* curline; -side_t* sidedef; -line_t* linedef; -sector_t* frontsector; -sector_t* backsector; +#define MAXSEGS (SCREENWIDTH / 2 + 1) -drawseg_t drawsegs[MAXDRAWSEGS]; -drawseg_t* ds_p; +/**************************************************************************** + * Private Types + ****************************************************************************/ +/* ClipWallSegment + * Clips the given range of columns and includes it in the new clip list. + */ -void -R_StoreWallRange -( int start, - int stop ); +typedef struct +{ + int first; + int last; +} cliprange_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ +seg_t *curline; +side_t *sidedef; +line_t *linedef; +sector_t *frontsector; +sector_t *backsector; +drawseg_t drawsegs[CONFIG_GAMES_NXDOOM_MAXDRAWSEGS]; +drawseg_t *ds_p; -// -// R_ClearDrawSegs -// -void R_ClearDrawSegs (void) -{ - ds_p = drawsegs; -} +/* newend is one past the last valid seg */ +cliprange_t *newend; +cliprange_t solidsegs[MAXSEGS]; +int checkcoord[12][4] = +{ + { + 3, + 0, + 2, + 1, + }, + { + 3, + 0, + 2, + 0, + }, + { + 3, + 1, + 2, + 0, + }, + { + 0, + }, + { + 2, + 0, + 2, + 1, + }, + { + 0, + 0, + 0, + 0, + }, + { + 3, + 1, + 3, + 0, + }, + { + 0, + }, + { + 2, + 0, + 3, + 1, + }, + { + 2, + 1, + 3, + 1, + }, + { + 2, + 1, + 3, + 0, + }, +}; -// -// ClipWallSegment -// Clips the given range of columns -// and includes it in the new clip list. -// -typedef struct +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void r_store_wall_range(int start, int stop); +void r_clip_solid_wall_segment(int first, int last); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: r_clip_pass_wall_segment + * + * Description: + * Clips the given range of columns, + * but does not includes it in the clip list. + * Does handle windows, + * e.g. LineDefs with upper and lower texture. + * + ****************************************************************************/ + +static void r_clip_pass_wall_segment(int first, int last) { - int first; - int last; - -} cliprange_t; + cliprange_t *start; -// We must expand MAXSEGS to the theoretical limit of the number of solidsegs -// that can be generated in a scene by the DOOM engine. This was determined by -// Lee Killough during BOOM development to be a function of the screensize. -// The simplest thing we can do, other than fix this bug, is to let the game -// render overage and then bomb out by detecting the overflow after the -// fact. -haleyjd -//#define MAXSEGS 32 -#define MAXSEGS (SCREENWIDTH / 2 + 1) + /* Find the first range that touches the range + * (adjacent pixels are touching). + */ -// newend is one past the last valid seg -cliprange_t* newend; -cliprange_t solidsegs[MAXSEGS]; + start = solidsegs; + while (start->last < first - 1) + start++; + if (first < start->first) + { + if (last < start->first - 1) + { + /* Post is entirely visible (above start). */ + r_store_wall_range(first, last); + return; + } + /* There is a fragment above *start. */ -// -// R_ClipSolidWallSegment -// Does handle solid walls, -// e.g. single sided LineDefs (middle texture) -// that entirely block the view. -// -void -R_ClipSolidWallSegment -( int first, - int last ) -{ - cliprange_t* next; - cliprange_t* start; + r_store_wall_range(first, start->first - 1); + } + + /* Bottom contained in start? */ - // Find the first range that touches the range - // (adjacent pixels are touching). - start = solidsegs; - while (start->last < first-1) - start++; + if (last <= start->last) return; - if (first < start->first) + while (last >= (start + 1)->first - 1) { - if (last < start->first-1) - { - // Post is entirely visible (above start), - // so insert a new clippost. - R_StoreWallRange (first, last); - next = newend; - newend++; - - while (next != start) - { - *next = *(next-1); - next--; - } - next->first = first; - next->last = last; - return; - } - - // There is a fragment above *start. - R_StoreWallRange (first, start->first - 1); - // Now adjust the clip size. - start->first = first; + /* There is a fragment between two posts. */ + + r_store_wall_range(start->last + 1, (start + 1)->first - 1); + start++; + + if (last <= start->last) return; } - // Bottom contained in start? - if (last <= start->last) - return; - - next = start; - while (last >= (next+1)->first-1) + /* There is a fragment after *next. */ + + r_store_wall_range(start->last + 1, last); +} + +/* r_check_b_box + * Checks BSP node/subtree bounding box. + * Returns true if some part of the bbox might be visible. + */ + +static boolean r_check_b_box(fixed_t *bspcoord) +{ + int boxx; + int boxy; + int boxpos; + + fixed_t x1; + fixed_t y1; + fixed_t x2; + fixed_t y2; + + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + cliprange_t *start; + + int sx1; + int sx2; + + /* Find the corners of the box + * that define the edges from current viewpoint. + */ + + if (viewx <= bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx < bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy >= bspcoord[BOXTOP]) + boxy = 0; + else if (viewy > bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy << 2) + boxx; + if (boxpos == 5) return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + /* check clip list for an open space */ + + angle1 = r_point_to_angle(x1, y1) - viewangle; + angle2 = r_point_to_angle(x2, y2) - viewangle; + + span = angle1 - angle2; + + /* Sitting on a line? */ + + if (span >= ANG180) return true; + + tspan = angle1 + clipangle; + + if (tspan > 2 * clipangle) { - // There is a fragment between two posts. - R_StoreWallRange (next->last + 1, (next+1)->first - 1); - next++; - - if (last <= next->last) - { - // Bottom is contained in next. - // Adjust the clip size. - start->last = next->last; - goto crunch; - } + tspan -= 2 * clipangle; + + /* Totally off the left edge? */ + + if (tspan >= span) return false; + + angle1 = clipangle; } - - // There is a fragment after *next. - R_StoreWallRange (next->last + 1, last); - // Adjust the clip size. - start->last = last; - - // Remove start+1 to next from the clip list, - // because start now covers their area. - crunch: - if (next == start) + + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) { - // Post just extended past the bottom of one post. - return; + tspan -= 2 * clipangle; + + /* Totally off the left edge? */ + + if (tspan >= span) return false; + + angle2 = -clipangle; } - - while (next++ != newend) + /* Find the first clippost + * that touches the source post + * (adjacent pixels are touching). + */ + + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + sx1 = viewangletox[angle1]; + sx2 = viewangletox[angle2]; + + /* Does not cross a pixel. */ + + if (sx1 == sx2) return false; + sx2--; + + start = solidsegs; + while (start->last < sx2) + start++; + + if (sx1 >= start->first && sx2 <= start->last) { - // Remove a post. - *++start = *next; + /* The clippost contains the new span. */ + + return false; } - newend = start+1; + return true; } +/**************************************************************************** + * Name: r_add_line + * + * Description: + * Clips the given segment + * and adds any visible pieces to the line list. + * + ****************************************************************************/ - -// -// R_ClipPassWallSegment -// Clips the given range of columns, -// but does not includes it in the clip list. -// Does handle windows, -// e.g. LineDefs with upper and lower texture. -// -void -R_ClipPassWallSegment -( int first, - int last ) +static void r_add_line(seg_t *line) { - cliprange_t* start; + int x1; + int x2; + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + + curline = line; + + /* OPTIMIZE: quickly reject orthogonal back sides. */ + + angle1 = r_point_to_angle(line->v1->x, line->v1->y); + angle2 = r_point_to_angle(line->v2->x, line->v2->y); + + /* Clip to view edges. + * OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). + */ + + span = angle1 - angle2; + + /* Back side? I.e. backface culling? */ + + if (span >= ANG180) return; - // Find the first range that touches the range - // (adjacent pixels are touching). - start = solidsegs; - while (start->last < first-1) - start++; + /* Global angle needed by segcalc. */ - if (first < start->first) + rw_angle1 = angle1; + angle1 -= viewangle; + angle2 -= viewangle; + + tspan = angle1 + clipangle; + if (tspan > 2 * clipangle) { - if (last < start->first-1) - { - // Post is entirely visible (above start). - R_StoreWallRange (first, last); - return; - } - - // There is a fragment above *start. - R_StoreWallRange (first, start->first - 1); + tspan -= 2 * clipangle; + + /* Totally off the left edge? */ + + if (tspan >= span) return; + + angle1 = clipangle; } - // Bottom contained in start? - if (last <= start->last) - return; - - while (last >= (start+1)->first-1) + tspan = clipangle - angle2; + if (tspan > 2 * clipangle) { - // There is a fragment between two posts. - R_StoreWallRange (start->last + 1, (start+1)->first - 1); - start++; - - if (last <= start->last) - return; + tspan -= 2 * clipangle; + + /* Totally off the left edge? */ + + if (tspan >= span) return; + angle2 = -clipangle; } - - // There is a fragment after *next. - R_StoreWallRange (start->last + 1, last); -} + /* The seg is in the view range, but not necessarily visible. */ + angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; + angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; + x1 = viewangletox[angle1]; + x2 = viewangletox[angle2]; -// -// R_ClearClipSegs -// -void R_ClearClipSegs (void) -{ - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = -1; - solidsegs[1].first = viewwidth; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs+2; + /* Does not cross a pixel? */ + + if (x1 == x2) return; + + backsector = line->backsector; + + /* Single sided line? */ + + if (!backsector) goto clipsolid; + + /* Closed door. */ + + if (backsector->ceilingheight <= frontsector->floorheight || + backsector->floorheight >= frontsector->ceilingheight) + { + goto clipsolid; + } + + /* Window. */ + + if (backsector->ceilingheight != frontsector->ceilingheight || + backsector->floorheight != frontsector->floorheight) + { + goto clippass; + } + + /* Reject empty lines used for triggers + * and special events. + * Identical floor and ceiling on both sides, + * identical light levels on both sides, + * and no middle texture. + */ + + if (backsector->ceilingpic == frontsector->ceilingpic && + backsector->floorpic == frontsector->floorpic && + backsector->lightlevel == frontsector->lightlevel && + curline->sidedef->midtexture == 0) + { + return; + } + +clippass: + r_clip_pass_wall_segment(x1, x2 - 1); + return; + +clipsolid: + r_clip_solid_wall_segment(x1, x2 - 1); } -// -// R_AddLine -// Clips the given segment -// and adds any visible pieces to the line list. -// -void R_AddLine (seg_t* line) +/* r_subsector + * Determine floor/ceiling planes. + * Add sprites of things in sector. + * Draw one or more line segments. + */ + +static void r_subsector(int num) { - int x1; - int x2; - angle_t angle1; - angle_t angle2; - angle_t span; - angle_t tspan; - - curline = line; - - // OPTIMIZE: quickly reject orthogonal back sides. - angle1 = R_PointToAngle (line->v1->x, line->v1->y); - angle2 = R_PointToAngle (line->v2->x, line->v2->y); - - // Clip to view edges. - // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). - span = angle1 - angle2; - - // Back side? I.e. backface culling? - if (span >= ANG180) - return; - - // Global angle needed by segcalc. - rw_angle1 = angle1; - angle1 -= viewangle; - angle2 -= viewangle; - - tspan = angle1 + clipangle; - if (tspan > 2*clipangle) - { - tspan -= 2*clipangle; + int count; + seg_t *line; + subsector_t *sub; - // Totally off the left edge? - if (tspan >= span) - return; - - angle1 = clipangle; +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (num >= numsubsectors) + i_error("R_Subsector: ss %i with numss = %i", num, numsubsectors); +#endif + + sscount++; + sub = &subsectors[num]; + frontsector = sub->sector; + count = sub->numlines; + line = &segs[sub->firstline]; + + if (frontsector->floorheight < viewz) + { + floorplane = + r_find_plane(frontsector->floorheight, frontsector->floorpic, + frontsector->lightlevel); } - tspan = clipangle - angle2; - if (tspan > 2*clipangle) + else + floorplane = NULL; + + if (frontsector->ceilingheight > viewz || + frontsector->ceilingpic == skyflatnum) { - tspan -= 2*clipangle; + ceilingplane = + r_find_plane(frontsector->ceilingheight, frontsector->ceilingpic, + frontsector->lightlevel); + } + else + ceilingplane = NULL; - // Totally off the left edge? - if (tspan >= span) - return; - angle2 = -clipangle; + r_add_sprites(frontsector); + + while (count--) + { + r_add_line(line); + line++; } - - // The seg is in the view range, - // but not necessarily visible. - angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; - angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; - - // Does not cross a pixel? - if (x1 == x2) - return; - - backsector = line->backsector; - - // Single sided line? - if (!backsector) - goto clipsolid; - - // Closed door. - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - goto clipsolid; - - // Window. - if (backsector->ceilingheight != frontsector->ceilingheight - || backsector->floorheight != frontsector->floorheight) - goto clippass; - - // Reject empty lines used for triggers - // and special events. - // Identical floor and ceiling on both sides, - // identical light levels on both sides, - // and no middle texture. - if (backsector->ceilingpic == frontsector->ceilingpic - && backsector->floorpic == frontsector->floorpic - && backsector->lightlevel == frontsector->lightlevel - && curline->sidedef->midtexture == 0) + + /* check for solidsegs overflow - extremely unsatisfactory! */ + + if (newend > &solidsegs[32]) { - return; + i_error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); } - - - clippass: - R_ClipPassWallSegment (x1, x2-1); - return; - - clipsolid: - R_ClipSolidWallSegment (x1, x2-1); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: r_clear_draw_segs + ****************************************************************************/ -// -// R_CheckBBox -// Checks BSP node/subtree bounding box. -// Returns true -// if some part of the bbox might be visible. -// -int checkcoord[12][4] = +void r_clear_draw_segs(void) { - {3,0,2,1}, - {3,0,2,0}, - {3,1,2,0}, - {0}, - {2,0,2,1}, - {0,0,0,0}, - {3,1,3,0}, - {0}, - {2,0,3,1}, - {2,1,3,1}, - {2,1,3,0} -}; + ds_p = drawsegs; +} +/**************************************************************************** + * Name: r_clip_solid_wall_segment + * + * Description: + * Does handle solid walls, e.g. single sided LineDefs (middle texture) + * that entirely block the view. + * + ****************************************************************************/ -boolean R_CheckBBox (fixed_t* bspcoord) +void r_clip_solid_wall_segment(int first, int last) { - int boxx; - int boxy; - int boxpos; - - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - angle_t angle1; - angle_t angle2; - angle_t span; - angle_t tspan; - - cliprange_t* start; - - int sx1; - int sx2; - - // Find the corners of the box - // that define the edges from current viewpoint. - if (viewx <= bspcoord[BOXLEFT]) - boxx = 0; - else if (viewx < bspcoord[BOXRIGHT]) - boxx = 1; - else - boxx = 2; - - if (viewy >= bspcoord[BOXTOP]) - boxy = 0; - else if (viewy > bspcoord[BOXBOTTOM]) - boxy = 1; - else - boxy = 2; - - boxpos = (boxy<<2)+boxx; - if (boxpos == 5) - return true; - - x1 = bspcoord[checkcoord[boxpos][0]]; - y1 = bspcoord[checkcoord[boxpos][1]]; - x2 = bspcoord[checkcoord[boxpos][2]]; - y2 = bspcoord[checkcoord[boxpos][3]]; - - // check clip list for an open space - angle1 = R_PointToAngle (x1, y1) - viewangle; - angle2 = R_PointToAngle (x2, y2) - viewangle; - - span = angle1 - angle2; - - // Sitting on a line? - if (span >= ANG180) - return true; - - tspan = angle1 + clipangle; - - if (tspan > 2*clipangle) - { - tspan -= 2*clipangle; + cliprange_t *next; + cliprange_t *start; - // Totally off the left edge? - if (tspan >= span) - return false; + /* Find the first range that touches the range + * (adjacent pixels are touching). + */ - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2*clipangle) + start = solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) { - tspan -= 2*clipangle; + if (last < start->first - 1) + { + /* Post is entirely visible (above start), + * so insert a new clippost. + */ + + r_store_wall_range(first, last); + next = newend; + newend++; - // Totally off the left edge? - if (tspan >= span) - return false; - - angle2 = -clipangle; + while (next != start) + { + *next = *(next - 1); + next--; + } + + next->first = first; + next->last = last; + return; + } + + /* There is a fragment above *start. */ + + r_store_wall_range(first, start->first - 1); + + /* Now adjust the clip size. */ + + start->first = first; } + /* Bottom contained in start? */ - // Find the first clippost - // that touches the source post - // (adjacent pixels are touching). - angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; - angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; - sx1 = viewangletox[angle1]; - sx2 = viewangletox[angle2]; - - // Does not cross a pixel. - if (sx1 == sx2) - return false; - sx2--; - - start = solidsegs; - while (start->last < sx2) - start++; - - if (sx1 >= start->first - && sx2 <= start->last) + if (last <= start->last) return; + + next = start; + while (last >= (next + 1)->first - 1) { - // The clippost contains the new span. - return false; + /* There is a fragment between two posts. */ + + r_store_wall_range(next->last + 1, (next + 1)->first - 1); + next++; + + if (last <= next->last) + { + /* Bottom is contained in next. + * Adjust the clip size. + */ + + start->last = next->last; + goto crunch; + } } - return true; -} + /* There is a fragment after *next. */ + r_store_wall_range(next->last + 1, last); + /* Adjust the clip size. */ -// -// R_Subsector -// Determine floor/ceiling planes. -// Add sprites of things in sector. -// Draw one or more line segments. -// -void R_Subsector (int num) -{ - int count; - seg_t* line; - subsector_t* sub; - -#ifdef RANGECHECK - if (num>=numsubsectors) - I_Error ("R_Subsector: ss %i with numss = %i", - num, - numsubsectors); -#endif + start->last = last; - sscount++; - sub = &subsectors[num]; - frontsector = sub->sector; - count = sub->numlines; - line = &segs[sub->firstline]; + /* Remove start+1 to next from the clip list, + * because start now covers their area. + */ - if (frontsector->floorheight < viewz) - { - floorplane = R_FindPlane (frontsector->floorheight, - frontsector->floorpic, - frontsector->lightlevel); - } - else - floorplane = NULL; - - if (frontsector->ceilingheight > viewz - || frontsector->ceilingpic == skyflatnum) +crunch: + if (next == start) { - ceilingplane = R_FindPlane (frontsector->ceilingheight, - frontsector->ceilingpic, - frontsector->lightlevel); + /* Post just extended past the bottom of one post. */ + + return; } - else - ceilingplane = NULL; - - R_AddSprites (frontsector); - while (count--) + while (next++ != newend) { - R_AddLine (line); - line++; + /* Remove a post. */ + + *++start = *next; } - // check for solidsegs overflow - extremely unsatisfactory! - if(newend > &solidsegs[32]) - I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); + newend = start + 1; } +/**************************************************************************** + * Name: r_clear_clip_segs + ****************************************************************************/ +void r_clear_clip_segs(void) +{ + solidsegs[0].first = -0x7fffffff; + solidsegs[0].last = -1; + solidsegs[1].first = viewwidth; + solidsegs[1].last = 0x7fffffff; + newend = solidsegs + 2; +} +/* RenderBSPNode + * Renders all subsectors below a given node, traversing subtree recursively. + * Just call with BSP root. + */ -// -// RenderBSPNode -// Renders all subsectors below a given node, -// traversing subtree recursively. -// Just call with BSP root. -void R_RenderBSPNode (int bspnum) +void r_render_bsp_node(int bspnum) { - node_t* bsp; - int side; + node_t *bsp; + int side; - // Found a subsector? - if (bspnum & NF_SUBSECTOR) + /* Found a subsector? */ + + if (bspnum & NF_SUBSECTOR) { - if (bspnum == -1) - R_Subsector (0); - else - R_Subsector (bspnum&(~NF_SUBSECTOR)); - return; + if (bspnum == -1) + r_subsector(0); + else + r_subsector(bspnum & (~NF_SUBSECTOR)); + return; } - - bsp = &nodes[bspnum]; - - // Decide which side the view point is on. - side = R_PointOnSide (viewx, viewy, bsp); - - // Recursively divide front space. - R_RenderBSPNode (bsp->children[side]); - - // Possibly divide back space. - if (R_CheckBBox (bsp->bbox[side^1])) - R_RenderBSPNode (bsp->children[side^1]); -} + bsp = &nodes[bspnum]; + + /* Decide which side the view point is on. */ + + side = r_point_on_side(viewx, viewy, bsp); + /* Recursively divide front space. */ + + r_render_bsp_node(bsp->children[side]); + + /* Possibly divide back space. */ + + if (r_check_b_box(bsp->bbox[side ^ 1])) + r_render_bsp_node(bsp->children[side ^ 1]); +} diff --git a/games/NXDoom/src/doom/r_bsp.h b/games/NXDoom/src/doom/r_bsp.h index 1723e686147..66c6d611fff 100644 --- a/games/NXDoom/src/doom/r_bsp.h +++ b/games/NXDoom/src/doom/r_bsp.h @@ -1,61 +1,73 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh module, BSP traversal and handling. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_bsp.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh module, BSP traversal and handling. + * + ****************************************************************************/ #ifndef __R_BSP__ #define __R_BSP__ +/**************************************************************************** + * Public Types + ****************************************************************************/ +typedef void (*drawfunc_t)(int start, int stop); -extern seg_t* curline; -extern side_t* sidedef; -extern line_t* linedef; -extern sector_t* frontsector; -extern sector_t* backsector; - -extern int rw_x; -extern int rw_stopx; +/**************************************************************************** + * Public Data + ****************************************************************************/ -extern boolean segtextured; +extern seg_t *curline; +extern side_t *sidedef; +extern line_t *linedef; +extern sector_t *frontsector; +extern sector_t *backsector; -// false if the back side is the same plane -extern boolean markfloor; -extern boolean markceiling; +extern int rw_x; +extern int rw_stopx; -extern boolean skymap; +extern boolean segtextured; -extern drawseg_t drawsegs[MAXDRAWSEGS]; -extern drawseg_t* ds_p; +/* false if the back side is the same plane */ -extern lighttable_t** hscalelight; -extern lighttable_t** vscalelight; -extern lighttable_t** dscalelight; +extern boolean markfloor; +extern boolean markceiling; +extern boolean skymap; -typedef void (*drawfunc_t) (int start, int stop); +extern drawseg_t drawsegs[CONFIG_GAMES_NXDOOM_MAXDRAWSEGS]; +extern drawseg_t *ds_p; +extern lighttable_t **hscalelight; +extern lighttable_t **vscalelight; +extern lighttable_t **dscalelight; -// BSP? -void R_ClearClipSegs (void); -void R_ClearDrawSegs (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/* BSP? */ -void R_RenderBSPNode (int bspnum); +void r_clear_clip_segs(void); +void r_clear_draw_segs(void); +void r_render_bsp_node(int bspnum); -#endif +#endif /* __R_BSP__ */ diff --git a/games/NXDoom/src/doom/r_data.c b/games/NXDoom/src/doom/r_data.c index 7f1bbbe00ae..2a35c2eda99 100644 --- a/games/NXDoom/src/doom/r_data.c +++ b/games/NXDoom/src/doom/r_data.c @@ -1,21 +1,30 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Preparation of data for rendering, -// generation of lookups, caching, retrieval by name. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_data.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Preparation of data for rendering, + * generation of lookups, caching, retrieval by name. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -24,881 +33,912 @@ #include "i_system.h" #include "z_zone.h" - #include "w_wad.h" #include "doomdef.h" #include "m_misc.h" -#include "r_local.h" #include "p_local.h" +#include "r_local.h" #include "doomstat.h" #include "r_sky.h" - #include "r_data.h" -// -// Graphics. -// DOOM graphics for walls and sprites -// is stored in vertical runs of opaque pixels (posts). -// A column is composed of zero or more posts, -// a patch or sprite is composed of zero or more columns. -// - - - -// -// Texture definition. -// Each texture is composed of one or more patches, -// with patches being lumps stored in the WAD. -// The lumps are referenced by number, and patched -// into the rectangular texture space using origin -// and possibly other attributes. -// -typedef PACKED_STRUCT ( +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Graphics. + * DOOM graphics for walls and sprites + * is stored in vertical runs of opaque pixels (posts). + * A column is composed of zero or more posts, + * a patch or sprite is composed of zero or more columns. + */ + +/* Texture definition. + * Each texture is composed of one or more patches, + * with patches being lumps stored in the WAD. + * The lumps are referenced by number, and patched + * into the rectangular texture space using origin + * and possibly other attributes. + */ + +begin_packed_struct struct mappatch_t { - short originx; - short originy; - short patch; - short stepdir; - short colormap; -}) mappatch_t; - - -// -// Texture definition. -// A DOOM wall texture is a list of patches -// which are to be combined in a predefined order. -// -typedef PACKED_STRUCT ( + short originx; + short originy; + short patch; + short stepdir; + short colormap; +} end_packed_struct; + +typedef struct mappatch_t mappatch_t; + +/* Texture definition. + * A DOOM wall texture is a list of patches + * which are to be combined in a predefined order. + */ + +begin_packed_struct struct maptexture_t { - char name[8]; - int masked; - short width; - short height; - int obsolete; - short patchcount; - mappatch_t patches[1]; -}) maptexture_t; - - -// A single patch from a texture definition, -// basically a rectangular area within -// the texture rectangle. + char name[8]; + int masked; + short width; + short height; + int obsolete; + short patchcount; + mappatch_t patches[1]; +} end_packed_struct; + +typedef struct maptexture_t maptexture_t; + +/* A single patch from a texture definition, basically a rectangular area + * within the texture rectangle. + */ + typedef struct { - // Block origin (allways UL), - // which has allready accounted - // for the internal origin of the patch. - short originx; - short originy; - int patch; -} texpatch_t; + /* Block origin (always UL), which has already accounted for the internal + * origin of the patch. + */ + short originx; + short originy; + int patch; +} texpatch_t; -// A maptexturedef_t describes a rectangular texture, -// which is composed of one or more mappatch_t structures -// that arrange graphic patches. +/* A maptexturedef_t describes a rectangular texture, which is composed of + * one or more mappatch_t structures that arrange graphic patches. + */ typedef struct texture_s texture_t; struct texture_s { - // Keep name for switch changing, etc. - char name[8]; - short width; - short height; + /* Keep name for switch changing, etc. */ + + char name[8]; + short width; + short height; + + /* Index in textures list */ + + int index; - // Index in textures list + /* Next in hash table chain */ - int index; + texture_t *next; - // Next in hash table chain + /* All the patches[patchcount] are drawn back to front into the cached + * texture. + */ - texture_t *next; - - // All the patches[patchcount] - // are drawn back to front into the cached texture. - short patchcount; - texpatch_t patches[1]; + short patchcount; + texpatch_t patches[1]; }; +/**************************************************************************** + * Public Data + ****************************************************************************/ +int firstflat; +int lastflat; +int numflats; -int firstflat; -int lastflat; -int numflats; +int firstpatch; +int lastpatch; +int numpatches; -int firstpatch; -int lastpatch; -int numpatches; +int firstspritelump; +int lastspritelump; +int numspritelumps; -int firstspritelump; -int lastspritelump; -int numspritelumps; +int numtextures; +texture_t **textures; +texture_t **textures_hashtable; -int numtextures; -texture_t** textures; -texture_t** textures_hashtable; +int *texturewidthmask; +/* needed for texture pegging */ -int* texturewidthmask; -// needed for texture pegging -fixed_t* textureheight; -int* texturecompositesize; -short** texturecolumnlump; -unsigned short** texturecolumnofs; -byte** texturecomposite; +fixed_t *textureheight; +int *texturecompositesize; +short **texturecolumnlump; +unsigned short **texturecolumnofs; +byte **texturecomposite; -// for global animation -int* flattranslation; -int* texturetranslation; +/* for global animation */ -// needed for pre rendering -fixed_t* spritewidth; -fixed_t* spriteoffset; -fixed_t* spritetopoffset; +int *flattranslation; +int *texturetranslation; -lighttable_t *colormaps; +/* needed for pre rendering */ +fixed_t *spritewidth; +fixed_t *spriteoffset; +fixed_t *spritetopoffset; -// -// MAPTEXTURE_T CACHING -// When a texture is first needed, -// it counts the number of composite columns -// required in the texture and allocates space -// for a column directory and any new columns. -// The directory will simply point inside other patches -// if there is only one patch in a given column, -// but any columns with multiple patches -// will have new column_ts generated. -// +lighttable_t *colormaps; +int flatmemory; +int texturememory; +int spritememory; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// -// R_DrawColumnInCache -// Clip and draw a column -// from a patch into a cached post. -// -void -R_DrawColumnInCache -( column_t* patch, - byte* cache, - int originy, - int cacheheight ) +static void generate_texture_hashtable(void) { - int count; - int position; - byte* source; + texture_t **rover; + int i; + int key; - while (patch->topdelta != 0xff) - { - source = (byte *)patch + 3; - count = patch->length; - position = originy + patch->topdelta; - - if (position < 0) - { - count += position; - position = 0; - } - - if (position + count > cacheheight) - count = cacheheight - position; - - if (count > 0) - memcpy (cache + position, source, count); - - patch = (column_t *)( (byte *)patch + patch->length + 4); - } -} + textures_hashtable = + z_malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); + memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); + /* Add all textures to hash table */ -// -// R_GenerateComposite -// Using the texture definition, -// the composite texture is created from the patches, -// and each column is cached. -// -void R_GenerateComposite (int texnum) -{ - byte* block; - texture_t* texture; - texpatch_t* patch; - patch_t* realpatch; - int x; - int x1; - int x2; - int i; - column_t* patchcol; - short* collump; - unsigned short* colofs; - - texture = textures[texnum]; - - block = Z_Malloc (texturecompositesize[texnum], - PU_STATIC, - &texturecomposite[texnum]); - - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - - // Composite the columns together. - for (i=0 , patch = texture->patches; - ipatchcount; - i++, patch++) + for (i = 0; i < numtextures; ++i) { - realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1<0) - x = 0; - else - x = x1; - - if (x2 > texture->width) - x2 = texture->width; - - for ( ; x= 0) - continue; - - patchcol = (column_t *)((byte *)realpatch - + LONG(realpatch->columnofs[x-x1])); - R_DrawColumnInCache (patchcol, - block + colofs[x], - patch->originy, - texture->height); - } - - } + /* Store index */ - // Now that the texture has been built in column cache, - // it is purgable from zone memory. - Z_ChangeTag (block, PU_CACHE); -} + textures[i]->index = i; + + /* Vanilla Doom does a linear search of the textures array + * and stops at the first entry it finds. If there are two + * entries with the same name, the first one in the array + * wins. The new entry must therefore be added at the end + * of the hash chain, so that earlier entries win. + */ + + key = w_lump_name_hash(textures[i]->name) % numtextures; + + rover = &textures_hashtable[key]; + + while (*rover != NULL) + { + rover = &(*rover)->next; + } + + /* Hook into hash table */ + textures[i]->next = NULL; + *rover = textures[i]; + } +} +/**************************************************************************** + * Name: r_generate_lookup + ****************************************************************************/ -// -// R_GenerateLookup -// -void R_GenerateLookup (int texnum) +static void r_generate_lookup(int texnum) { - texture_t* texture; - byte* patchcount; // patchcount[texture->width] - texpatch_t* patch; - patch_t* realpatch; - int x; - int x1; - int x2; - int i; - short* collump; - unsigned short* colofs; - - texture = textures[texnum]; - - // Composited texture not created yet. - texturecomposite[texnum] = 0; - - texturecompositesize[texnum] = 0; - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - - // Now count the number of columns - // that are covered by more than one patch. - // Fill in the lump / offset, so columns - // with only a single patch are all done. - patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); - memset (patchcount, 0, texture->width); - - for (i=0 , patch = texture->patches; - ipatchcount; - i++, patch++) + texture_t *texture; + byte *patchcount; /* patchcount[texture->width] */ + texpatch_t *patch; + patch_t *realpatch; + int x; + int x1; + int x2; + int i; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + + /* Composited texture not created yet. */ + + texturecomposite[texnum] = 0; + + texturecompositesize[texnum] = 0; + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + + /* Now count the number of columns that are covered by more than one patch. + * + * Fill in the lump / offset, so columns with only a single patch are all + * done. + */ + + patchcount = (byte *)z_malloc(texture->width, PU_STATIC, &patchcount); + memset(patchcount, 0, texture->width); + + for (i = 0, patch = texture->patches; + i < texture->patchcount; + i++, patch++) { - realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1 < 0) - x = 0; - else - x = x1; - - if (x2 > texture->width) - x2 = texture->width; - for ( ; xpatch; - colofs[x] = LONG(realpatch->columnofs[x-x1])+3; - } + realpatch = w_cache_lump_num(patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1 < 0) + x = 0; + else + x = x1; + + if (x2 > texture->width) x2 = texture->width; + for (; x < x2; x++) + { + patchcount[x]++; + collump[x] = patch->patch; + colofs[x] = LONG(realpatch->columnofs[x - x1]) + 3; + } } - - for (x=0 ; xwidth ; x++) + + for (x = 0; x < texture->width; x++) { - if (!patchcount[x]) - { - printf ("R_GenerateLookup: column without a patch (%s)\n", - texture->name); - return; - } - // I_Error ("R_GenerateLookup: column without a patch"); - - if (patchcount[x] > 1) - { - // Use the cached block. - collump[x] = -1; - colofs[x] = texturecompositesize[texnum]; - - if (texturecompositesize[texnum] > 0x10000-texture->height) - { - I_Error ("R_GenerateLookup: texture %i is >64k", - texnum); - } - - texturecompositesize[texnum] += texture->height; - } - } + if (!patchcount[x]) + { + printf("r_generate_lookup: column without a patch (%s)\n", + texture->name); + return; + } - Z_Free(patchcount); -} + if (patchcount[x] > 1) + { + /* Use the cached block. */ + collump[x] = -1; + colofs[x] = texturecompositesize[texnum]; + if (texturecompositesize[texnum] > 0x10000 - texture->height) + { + i_error("r_generate_lookup: texture %i is >64k", texnum); + } + texturecompositesize[texnum] += texture->height; + } + } -// -// R_GetColumn -// -byte* -R_GetColumn -( int tex, - int col ) -{ - int lump; - int ofs; - - col &= texturewidthmask[tex]; - lump = texturecolumnlump[tex][col]; - ofs = texturecolumnofs[tex][col]; - - if (lump > 0) - return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs; - - if (!texturecomposite[tex]) - R_GenerateComposite (tex); - - return texturecomposite[tex] + ofs; + z_free(patchcount); } - -static void GenerateTextureHashTable(void) +/* MAPTEXTURE_T CACHING + * + * When a texture is first needed, it counts the number of composite columns + * required in the texture and allocates space for a column directory and any + * new columns. + * + * The directory will simply point inside other patches if there is only one + * patch in a given column, but any columns with multiple patches will have + * new column_ts generated. + */ + +/**************************************************************************** + * Name: r_init_textures + * + * Description: + * Initializes the texture list + * with the textures from the world map. + * + ****************************************************************************/ + +static void r_init_textures(void) { - texture_t **rover; - int i; - int key; - - textures_hashtable - = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); + maptexture_t *mtexture; + texture_t *texture; + mappatch_t *mpatch; + texpatch_t *patch; - memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); + int i; + int j; - // Add all textures to hash table + int *maptex; + int *maptex2; + int *maptex1; - for (i=0; iindex = i; + int *patchlookup; - // Vanilla Doom does a linear search of the texures array - // and stops at the first entry it finds. If there are two - // entries with the same name, the first one in the array - // wins. The new entry must therefore be added at the end - // of the hash chain, so that earlier entries win. + int nummappatches; + int offset; + int maxoff; + int maxoff2; + int numtextures1; + int numtextures2; - key = W_LumpNameHash(textures[i]->name) % numtextures; + int *directory; - rover = &textures_hashtable[key]; + int temp1; + int temp2; + int temp3; - while (*rover != NULL) - { - rover = &(*rover)->next; - } + /* Load the patch names from pnames.lmp. */ - // Hook into hash table + name[8] = 0; + names = w_cache_lump_name(("PNAMES"), PU_STATIC); + nummappatches = LONG(*((int *)names)); + name_p = names + 4; + patchlookup = + z_malloc(nummappatches * sizeof(*patchlookup), PU_STATIC, NULL); - textures[i]->next = NULL; - *rover = textures[i]; + for (i = 0; i < nummappatches; i++) + { + m_str_copy(name, name_p + i * 8, sizeof(name)); + patchlookup[i] = w_check_num_for_name(name); } -} + w_release_lump_name(("PNAMES")); -// -// R_InitTextures -// Initializes the texture list -// with the textures from the world map. -// -void R_InitTextures (void) -{ - maptexture_t* mtexture; - texture_t* texture; - mappatch_t* mpatch; - texpatch_t* patch; - - int i; - int j; - - int* maptex; - int* maptex2; - int* maptex1; - - char name[9]; - char* names; - char* name_p; - - int* patchlookup; - - int nummappatches; - int offset; - int maxoff; - int maxoff2; - int numtextures1; - int numtextures2; - - int* directory; - - int temp1; - int temp2; - int temp3; - - - // Load the patch names from pnames.lmp. - name[8] = 0; - names = W_CacheLumpName (DEH_String("PNAMES"), PU_STATIC); - nummappatches = LONG ( *((int *)names) ); - name_p = names + 4; - patchlookup = Z_Malloc(nummappatches*sizeof(*patchlookup), PU_STATIC, NULL); - - for (i = 0; i < nummappatches; i++) - { - M_StringCopy(name, name_p + i * 8, sizeof(name)); - patchlookup[i] = W_CheckNumForName(name); - } - W_ReleaseLumpName(DEH_String("PNAMES")); - - // Load the map texture definitions from textures.lmp. - // The data is contained in one or two lumps, - // TEXTURE1 for shareware, plus TEXTURE2 for commercial. - maptex = maptex1 = W_CacheLumpName (DEH_String("TEXTURE1"), PU_STATIC); - numtextures1 = LONG(*maptex); - maxoff = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE1"))); - directory = maptex+1; - - if (W_CheckNumForName (DEH_String("TEXTURE2")) != -1) + /* Load the map texture definitions from textures.lmp. + * The data is contained in one or two lumps, + * TEXTURE1 for shareware, plus TEXTURE2 for commercial. + */ + + maptex = maptex1 = w_cache_lump_name(("TEXTURE1"), PU_STATIC); + numtextures1 = LONG(*maptex); + maxoff = w_lump_length(w_get_num_for_name(("TEXTURE1"))); + directory = maptex + 1; + + if (w_check_num_for_name(("TEXTURE2")) != -1) { - maptex2 = W_CacheLumpName (DEH_String("TEXTURE2"), PU_STATIC); - numtextures2 = LONG(*maptex2); - maxoff2 = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE2"))); + maptex2 = w_cache_lump_name(("TEXTURE2"), PU_STATIC); + numtextures2 = LONG(*maptex2); + maxoff2 = w_lump_length(w_get_num_for_name(("TEXTURE2"))); } - else + else { - maptex2 = NULL; - numtextures2 = 0; - maxoff2 = 0; + maptex2 = NULL; + numtextures2 = 0; + maxoff2 = 0; } - numtextures = numtextures1 + numtextures2; - - textures = Z_Malloc (numtextures * sizeof(*textures), PU_STATIC, 0); - texturecolumnlump = Z_Malloc (numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0); - texturecolumnofs = Z_Malloc (numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0); - texturecomposite = Z_Malloc (numtextures * sizeof(*texturecomposite), PU_STATIC, 0); - texturecompositesize = Z_Malloc (numtextures * sizeof(*texturecompositesize), PU_STATIC, 0); - texturewidthmask = Z_Malloc (numtextures * sizeof(*texturewidthmask), PU_STATIC, 0); - textureheight = Z_Malloc (numtextures * sizeof(*textureheight), PU_STATIC, 0); - - // Really complex printing shit... - temp1 = W_GetNumForName (DEH_String("S_START")); // P_??????? - temp2 = W_GetNumForName (DEH_String("S_END")) - 1; - temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64); - - // If stdout is a real console, use the classic vanilla "filling - // up the box" effect, which uses backspace to "step back" inside - // the box. If stdout is a file, don't draw the box. - - if (I_ConsoleStdout()) + + numtextures = numtextures1 + numtextures2; + + textures = z_malloc(numtextures * sizeof(*textures), PU_STATIC, 0); + texturecolumnlump = + z_malloc(numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0); + texturecolumnofs = + z_malloc(numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0); + texturecomposite = + z_malloc(numtextures * sizeof(*texturecomposite), PU_STATIC, 0); + texturecompositesize = + z_malloc(numtextures * sizeof(*texturecompositesize), PU_STATIC, 0); + texturewidthmask = + z_malloc(numtextures * sizeof(*texturewidthmask), PU_STATIC, 0); + textureheight = + z_malloc(numtextures * sizeof(*textureheight), PU_STATIC, 0); + + /* Really complex printing shit... */ + + temp1 = w_get_num_for_name(("S_START")); /* P_??????? */ + temp2 = w_get_num_for_name(("S_END")) - 1; + temp3 = ((temp2 - temp1 + 63) / 64) + ((numtextures + 63) / 64); + + /* If stdout is a real console, use the classic vanilla "filling + * up the box" effect, which uses backspace to "step back" inside + * the box. If stdout is a file, don't draw the box. + */ + + if (i_console_stdout()) { - printf("["); - for (i = 0; i < temp3 + 9; i++) - printf(" "); - printf("]"); - for (i = 0; i < temp3 + 10; i++) - printf("\b"); + printf("["); + for (i = 0; i < temp3 + 9; i++) + printf(" "); + printf("]"); + for (i = 0; i < temp3 + 10; i++) + printf("\b"); } - - for (i=0 ; i maxoff) - I_Error ("R_InitTextures: bad texture directory"); - - mtexture = (maptexture_t *) ( (byte *)maptex + offset); - - texture = textures[i] = - Z_Malloc (sizeof(texture_t) - + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), - PU_STATIC, 0); - - texture->width = SHORT(mtexture->width); - texture->height = SHORT(mtexture->height); - texture->patchcount = SHORT(mtexture->patchcount); - - memcpy (texture->name, mtexture->name, sizeof(texture->name)); - mpatch = &mtexture->patches[0]; - patch = &texture->patches[0]; - - for (j=0 ; jpatchcount ; j++, mpatch++, patch++) - { - patch->originx = SHORT(mpatch->originx); - patch->originy = SHORT(mpatch->originy); - patch->patch = patchlookup[SHORT(mpatch->patch)]; - if (patch->patch == -1) - { - I_Error ("R_InitTextures: Missing patch in texture %s", - texture->name); - } - } - texturecolumnlump[i] = Z_Malloc (texture->width*sizeof(**texturecolumnlump), PU_STATIC,0); - texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(**texturecolumnofs), PU_STATIC,0); - - j = 1; - while (j*2 <= texture->width) - j<<=1; - - texturewidthmask[i] = j-1; - textureheight[i] = texture->height< maxoff) i_error("r_init_textures: bad texture directory"); + + mtexture = (maptexture_t *)((byte *)maptex + offset); + + texture = textures[i] = + z_malloc(sizeof(texture_t) + + sizeof(texpatch_t) * (SHORT(mtexture->patchcount) - 1), + PU_STATIC, 0); + + texture->width = SHORT(mtexture->width); + texture->height = SHORT(mtexture->height); + texture->patchcount = SHORT(mtexture->patchcount); + + memcpy(texture->name, mtexture->name, sizeof(texture->name)); + mpatch = &mtexture->patches[0]; + patch = &texture->patches[0]; + + for (j = 0; j < texture->patchcount; j++, mpatch++, patch++) + { + patch->originx = SHORT(mpatch->originx); + patch->originy = SHORT(mpatch->originy); + patch->patch = patchlookup[SHORT(mpatch->patch)]; + if (patch->patch == -1) + { + i_error("r_init_textures: Missing patch in texture %s", + texture->name); + } + } + + texturecolumnlump[i] = z_malloc( + texture->width * sizeof(**texturecolumnlump), PU_STATIC, 0); + texturecolumnofs[i] = + z_malloc(texture->width * sizeof(**texturecolumnofs), + PU_STATIC, 0); + + j = 1; + while (j * 2 <= texture->width) + j <<= 1; + + texturewidthmask[i] = j - 1; + textureheight[i] = texture->height << FRACBITS; } - Z_Free(patchlookup); + z_free(patchlookup); + + w_release_lump_name(("TEXTURE1")); + if (maptex2) w_release_lump_name(("TEXTURE2")); + + /* Precalculate whatever possible. */ - W_ReleaseLumpName(DEH_String("TEXTURE1")); - if (maptex2) - W_ReleaseLumpName(DEH_String("TEXTURE2")); - - // Precalculate whatever possible. + for (i = 0; i < numtextures; i++) + r_generate_lookup(i); - for (i=0 ; iwidth) << FRACBITS; + spriteoffset[i] = SHORT(patch->leftoffset) << FRACBITS; + spritetopoffset[i] = SHORT(patch->topoffset) << FRACBITS; + } +} + +/**************************************************************************** + * Name: r_init_colourmaps + ****************************************************************************/ + +static void r_init_colourmaps(void) { - int i; - - firstflat = W_GetNumForName (DEH_String("F_START")) + 1; - lastflat = W_GetNumForName (DEH_String("F_END")) - 1; - numflats = lastflat - firstflat + 1; - - // Create translation table for global animation. - flattranslation = Z_Malloc ((numflats+1)*sizeof(*flattranslation), PU_STATIC, 0); - - for (i=0 ; itopdelta != 0xff) { - if (!(i&63)) - printf ("."); + source = (byte *)patch + 3; + count = patch->length; + position = originy + patch->topdelta; + + if (position < 0) + { + count += position; + position = 0; + } - patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE); - spritewidth[i] = SHORT(patch->width)<leftoffset)<topoffset)< cacheheight) count = cacheheight - position; + + if (count > 0) memcpy(cache + position, source, count); + + patch = (column_t *)((byte *)patch + patch->length + 4); } } +/**************************************************************************** + * Name: r_generate_composite + * + * Description: + * Using the texture definition, the composite texture is created from the + * patches, and each column is cached. + * + ****************************************************************************/ - -// -// R_InitColormaps -// -void R_InitColormaps (void) +static void r_generate_composite(int texnum) { - int lump; + byte *block; + texture_t *texture; + texpatch_t *patch; + patch_t *realpatch; + int x; + int x1; + int x2; + int i; + column_t *patchcol; + short *collump; + unsigned short *colofs; + + texture = textures[texnum]; + + block = z_malloc(texturecompositesize[texnum], PU_STATIC, + &texturecomposite[texnum]); + + collump = texturecolumnlump[texnum]; + colofs = texturecolumnofs[texnum]; + + /* Composite the columns together. */ + + for (i = 0, patch = texture->patches; + i < texture->patchcount; + i++, patch++) + { + realpatch = w_cache_lump_num(patch->patch, PU_CACHE); + x1 = patch->originx; + x2 = x1 + SHORT(realpatch->width); + + if (x1 < 0) + x = 0; + else + x = x1; - // Load in the light tables, - // 256 byte align tables. - lump = W_GetNumForName(DEH_String("COLORMAP")); - colormaps = W_CacheLumpNum(lump, PU_STATIC); + if (x2 > texture->width) x2 = texture->width; + + for (; x < x2; x++) + { + /* Column does not have multiple patches? */ + + if (collump[x] >= 0) continue; + + patchcol = (column_t *)((byte *)realpatch + + LONG(realpatch->columnofs[x - x1])); + r_draw_column_in_cache(patchcol, block + colofs[x], + patch->originy, texture->height); + } + } + + /* Now that the texture has been built in column cache, + * it is purgeable from zone memory. + */ + + z_change_tag(block, PU_CACHE); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: r_get_column + ****************************************************************************/ -// -// R_InitData -// Locates all the lumps -// that will be used by all views -// Must be called after W_Init. -// -void R_InitData (void) +byte *r_get_column(int tex, int col) { - R_InitTextures (); - printf ("."); - R_InitFlats (); - printf ("."); - R_InitSpriteLumps (); - printf ("."); - R_InitColormaps (); + int lump; + int ofs; + + col &= texturewidthmask[tex]; + lump = texturecolumnlump[tex][col]; + ofs = texturecolumnofs[tex][col]; + + if (lump > 0) return (byte *)w_cache_lump_num(lump, PU_CACHE) + ofs; + + if (!texturecomposite[tex]) r_generate_composite(tex); + + return texturecomposite[tex] + ofs; } +/**************************************************************************** + * Name: r_init_data + * + * Description: + * Locates all the lumps that will be used by all views + * Must be called after W_Init. + * + ****************************************************************************/ + +void r_init_data(void) +{ + r_init_textures(); + printf("."); + r_init_flats(); + printf("."); + r_init_sprite_lumps(); + printf("."); + r_init_colourmaps(); +} +/**************************************************************************** + * Name: r_flat_num_for_name + * + * Description: + * Retrieval, get a flat number for a flat name. + * + ****************************************************************************/ -// -// R_FlatNumForName -// Retrieval, get a flat number for a flat name. -// -int R_FlatNumForName(const char *name) +int r_flat_num_for_name(const char *name) { - int i; - char namet[9]; + int i; + char namet[9]; - i = W_CheckNumForName (name); + i = w_check_num_for_name(name); - if (i == -1) + if (i == -1) { - namet[8] = 0; - memcpy (namet, name,8); - I_Error ("R_FlatNumForName: %s not found",namet); + namet[8] = 0; + memcpy(namet, name, 8); + i_error("r_flat_num_for_name: %s not found", namet); } - return i - firstflat; + + return i - firstflat; } +/**************************************************************************** + * Name: r_check_texture_num_for_name + * + * Description: + * Check whether texture is available. + * Filter out NoTexture indicator. + * + ****************************************************************************/ +int r_check_texture_num_for_name(const char *name) +{ + texture_t *texture; + int key; + /* "NoTexture" marker. */ -// -// R_CheckTextureNumForName -// Check whether texture is available. -// Filter out NoTexture indicator. -// -int R_CheckTextureNumForName(const char *name) -{ - texture_t *texture; - int key; - - // "NoTexture" marker. - if (name[0] == '-') - return 0; - - key = W_LumpNameHash(name) % numtextures; - - texture=textures_hashtable[key]; - - while (texture != NULL) + if (name[0] == '-') return 0; + + key = w_lump_name_hash(name) % numtextures; + + texture = textures_hashtable[key]; + + while (texture != NULL) { - if (!strncasecmp (texture->name, name, 8) ) - return texture->index; + if (!strncasecmp(texture->name, name, 8)) return texture->index; - texture = texture->next; + texture = texture->next; } - - return -1; -} + return -1; +} +/**************************************************************************** + * Name: r_texture_num_for_name + * + * Description: + * Calls r_check_texture_num_for_name, aborts with error message. + * + ****************************************************************************/ -// -// R_TextureNumForName -// Calls R_CheckTextureNumForName, -// aborts with error message. -// -int R_TextureNumForName(const char *name) +int r_texture_num_for_name(const char *name) { - int i; - - i = R_CheckTextureNumForName (name); + int i; + + i = r_check_texture_num_for_name(name); - if (i==-1) + if (i == -1) { - I_Error ("R_TextureNumForName: %s not found", - name); + i_error("r_texture_num_for_name: %s not found", name); } - return i; + + return i; } +/**************************************************************************** + * Name: r_precache_level + * + * Description: + * Preloads all relevant graphics for the level. + * + ****************************************************************************/ +void r_precache_level(void) +{ + char *flatpresent; + char *texturepresent; + char *spritepresent; + int i; + int j; + int k; + int lump; -// -// R_PrecacheLevel -// Preloads all relevant graphics for the level. -// -int flatmemory; -int texturememory; -int spritememory; + texture_t *texture; + thinker_t *th; + spriteframe_t *sf; -void R_PrecacheLevel (void) -{ - char* flatpresent; - char* texturepresent; - char* spritepresent; - - int i; - int j; - int k; - int lump; - - texture_t* texture; - thinker_t* th; - spriteframe_t* sf; - - if (demoplayback) - return; - - // Precache flats. - flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); - memset (flatpresent,0,numflats); - - for (i=0 ; isize; - W_CacheLumpNum(lump, PU_CACHE); - } + if (flatpresent[i]) + { + lump = firstflat + i; + flatmemory += lumpinfo[lump]->size; + w_cache_lump_num(lump, PU_CACHE); + } } - Z_Free(flatpresent); - - // Precache textures. - texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); - memset (texturepresent,0, numtextures); - - for (i=0 ; ipatchcount ; j++) - { - lump = texture->patches[j].patch; - texturememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump , PU_CACHE); - } + if (!texturepresent[i]) continue; + + texture = textures[i]; + + for (j = 0; j < texture->patchcount; j++) + { + lump = texture->patches[j].patch; + texturememory += lumpinfo[lump]->size; + w_cache_lump_num(lump, PU_CACHE); + } } - Z_Free(texturepresent); - - // Precache sprites. - spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); - memset (spritepresent,0, numsprites); - - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) + z_free(texturepresent); + + /* Precache sprites. */ + + spritepresent = z_malloc(numsprites, PU_STATIC, NULL); + memset(spritepresent, 0, numsprites); + + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - spritepresent[((mobj_t *)th)->sprite] = 1; + if (th->function.acp1 == (actionf_p1)p_mobj_thinker) + spritepresent[((mobj_t *)th)->sprite] = 1; } - - spritememory = 0; - for (i=0 ; ilump[k]; - spritememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump , PU_CACHE); - } - } + if (!spritepresent[i]) continue; + + for (j = 0; j < sprites[i].numframes; j++) + { + sf = &sprites[i].spriteframes[j]; + for (k = 0; k < 8; k++) + { + lump = firstspritelump + sf->lump[k]; + spritememory += lumpinfo[lump]->size; + w_cache_lump_num(lump, PU_CACHE); + } + } } - Z_Free(spritepresent); + z_free(spritepresent); } - - - - diff --git a/games/NXDoom/src/doom/r_data.h b/games/NXDoom/src/doom/r_data.h index 1b273088d50..f320ed0f7bb 100644 --- a/games/NXDoom/src/doom/r_data.h +++ b/games/NXDoom/src/doom/r_data.h @@ -1,55 +1,68 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh module, data I/O, caching, retrieval of graphics -// by name. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_data.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh module, data I/O, caching, retrieval of graphics + * by name. + * + ****************************************************************************/ #ifndef __R_DATA__ #define __R_DATA__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "r_defs.h" #include "r_state.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Retrieve column data for span blitting. -byte* -R_GetColumn -( int tex, - int col ); +extern int numflats; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// I/O, setting up the stuff. -void R_InitData (void); -void R_PrecacheLevel (void); +/* Retrieve column data for span blitting. */ +byte *r_get_column(int tex, int col); -// Retrieval. -// Floor/ceiling opaque texture tiles, -// lookup by name. For animation? -int R_FlatNumForName(const char *name); +/* I/O, setting up the stuff. */ +void r_init_data(void); +void r_precache_level(void); -// Called by P_Ticker for switches and animations, -// returns the texture number for the texture name. -int R_TextureNumForName(const char *name); -int R_CheckTextureNumForName(const char *name); +/* Retrieval. + * Floor/ceiling opaque texture tiles, + * lookup by name. For animation? + */ +int r_flat_num_for_name(const char *name); -extern int numflats; +/* Called by p_ticker for switches and animations, + * returns the texture number for the texture name. + */ +int r_texture_num_for_name(const char *name); +int r_check_texture_num_for_name(const char *name); -#endif +#endif /* __R_DATA__ */ diff --git a/games/NXDoom/src/doom/r_defs.h b/games/NXDoom/src/doom/r_defs.h index d87ca38a9f6..ae84ae63e88 100644 --- a/games/NXDoom/src/doom/r_defs.h +++ b/games/NXDoom/src/doom/r_defs.h @@ -1,448 +1,444 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh/rendering module, shared data struct definitions. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_defs.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh/rendering module, shared data struct definitions. + * + ****************************************************************************/ #ifndef __R_DEFS__ #define __R_DEFS__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Screenwidth. */ -// Screenwidth. #include "doomdef.h" -// Some more or less basic data types -// we depend on. +/* Some more or less basic data types we depend on. */ + #include "m_fixed.h" -// We rely on the thinker data struct -// to handle sound origins in sectors. +/* We rely on the thinker data struct to handle sound origins in sectors. */ + #include "d_think.h" -// SECTORS do store MObjs anyway. + +/* SECTORS do store MObjs anyway. */ + #include "p_mobj.h" #include "i_video.h" #include "v_patch.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Silhouette, needed for clipping Segs (mainly) and sprites representing + * things. + */ +#define SIL_NONE 0 +#define SIL_BOTTOM 1 +#define SIL_TOP 2 +#define SIL_BOTH 3 -// Silhouette, needed for clipping Segs (mainly) -// and sprites representing things. -#define SIL_NONE 0 -#define SIL_BOTTOM 1 -#define SIL_TOP 2 -#define SIL_BOTH 3 +/**************************************************************************** + * Public Types + ****************************************************************************/ -#define MAXDRAWSEGS 256 +/* INTERNAL MAP TYPES used by play and refresh */ +/* Your plain vanilla vertex. + * + * Note: transformed values not buffered locally, like some DOOM-alikes + * ("wt", "WebView") did. + */ - - - -// -// INTERNAL MAP TYPES -// used by play and refresh -// - -// -// Your plain vanilla vertex. -// Note: transformed values not buffered locally, -// like some DOOM-alikes ("wt", "WebView") did. -// typedef struct { - fixed_t x; - fixed_t y; - + fixed_t x; + fixed_t y; } vertex_t; +/* Forward of LineDefs, for Sectors. */ -// Forward of LineDefs, for Sectors. struct line_s; -// Each sector has a degenmobj_t in its center -// for sound origin purposes. -// I suppose this does not handle sound from -// moving objects (doppler), because -// position is prolly just buffered, not -// updated. +/* Each sector has a degenmobj_t in its center for sound origin purposes. + * + * I suppose this does not handle sound from moving objects (doppler), + * because position is prolly just buffered, not updated. + */ + typedef struct { - thinker_t thinker; // not used for anything - fixed_t x; - fixed_t y; - fixed_t z; - + thinker_t thinker; /* not used for anything */ + fixed_t x; + fixed_t y; + fixed_t z; } degenmobj_t; -// -// The SECTORS record, at runtime. -// Stores things/mobjs. -// -typedef struct +/* The SECTORS record, at runtime. Stores things/mobjs. */ + +typedef struct { - fixed_t floorheight; - fixed_t ceilingheight; - short floorpic; - short ceilingpic; - short lightlevel; - short special; - short tag; + fixed_t floorheight; + fixed_t ceilingheight; + short floorpic; + short ceilingpic; + short lightlevel; + short special; + short tag; - // 0 = untraversed, 1,2 = sndlines -1 - int soundtraversed; + /* 0 = untraversed, 1,2 = sndlines -1 */ - // thing that made a sound (or null) - mobj_t* soundtarget; + int soundtraversed; - // mapblock bounding box for height changes - int blockbox[4]; + /* thing that made a sound (or null) */ - // origin for any sounds played by the sector - degenmobj_t soundorg; + mobj_t *soundtarget; - // if == validcount, already checked - int validcount; + /* mapblock bounding box for height changes */ - // list of mobjs in sector - mobj_t* thinglist; + int blockbox[4]; - // thinker_t for reversable actions - void* specialdata; + /* origin for any sounds played by the sector */ - int linecount; - struct line_s** lines; // [linecount] size - -} sector_t; + degenmobj_t soundorg; + + /* if == validcount, already checked */ + int validcount; + /* list of mobjs in sector */ + mobj_t *thinglist; -// -// The SideDef. -// + /* thinker_t for reversible actions */ + + void *specialdata; + + int linecount; + struct line_s **lines; /* [linecount] size */ +} sector_t; + +/* The SideDef. */ typedef struct { - // add this to the calculated texture column - fixed_t textureoffset; - - // add this to the calculated texture top - fixed_t rowoffset; - - // Texture indices. - // We do not maintain names here. - short toptexture; - short bottomtexture; - short midtexture; - - // Sector the SideDef is facing. - sector_t* sector; - -} side_t; + /* add this to the calculated texture column */ + fixed_t textureoffset; + /* add this to the calculated texture top */ -// -// Move clipping aid for LineDefs. -// -typedef enum -{ - ST_HORIZONTAL, - ST_VERTICAL, - ST_POSITIVE, - ST_NEGATIVE + fixed_t rowoffset; -} slopetype_t; + /* Texture indices. We do not maintain names here. */ + short toptexture; + short bottomtexture; + short midtexture; + + /* Sector the SideDef is facing. */ + + sector_t *sector; +} side_t; +/* Move clipping aid for LineDefs. */ + +typedef enum +{ + ST_HORIZONTAL, + ST_VERTICAL, + ST_POSITIVE, + ST_NEGATIVE +} slopetype_t; typedef struct line_s { - // Vertices, from v1 to v2. - vertex_t* v1; - vertex_t* v2; + /* Vertices, from v1 to v2. */ - // Precalculated v2 - v1 for side checking. - fixed_t dx; - fixed_t dy; + vertex_t *v1; + vertex_t *v2; - // Animation related. - short flags; - short special; - short tag; + /* Precalculated v2 - v1 for side checking. */ - // Visual appearance: SideDefs. - // sidenum[1] will be -1 if one sided - short sidenum[2]; + fixed_t dx; + fixed_t dy; - // Neat. Another bounding box, for the extent - // of the LineDef. - fixed_t bbox[4]; + /* Animation related. */ - // To aid move clipping. - slopetype_t slopetype; + short flags; + short special; + short tag; - // Front and back sector. - // Note: redundant? Can be retrieved from SideDefs. - sector_t* frontsector; - sector_t* backsector; + /* Visual appearance: SideDefs. sidenum[1] will be -1 if one sided */ - // if == validcount, already checked - int validcount; + short sidenum[2]; - // thinker_t for reversable actions - void* specialdata; -} line_t; + /* Neat. Another bounding box, for the extent of the LineDef. */ + fixed_t bbox[4]; + /* To aid move clipping. */ + slopetype_t slopetype; + + /* Front and back sector. + * Note: redundant? Can be retrieved from SideDefs. + */ + + sector_t *frontsector; + sector_t *backsector; + + /* if == validcount, already checked */ + + int validcount; + + /* thinker_t for reversible actions */ + + void *specialdata; +} line_t; + +/* A SubSector. + * References a Sector. + * + * Basically, this is a list of LineSegs, indicating the visible walls that + * define (all or some) sides of a convex BSP leaf. + */ -// -// A SubSector. -// References a Sector. -// Basically, this is a list of LineSegs, -// indicating the visible walls that define -// (all or some) sides of a convex BSP leaf. -// typedef struct subsector_s { - sector_t* sector; - short numlines; - short firstline; - + sector_t *sector; + short numlines; + short firstline; } subsector_t; +/* The LineSeg. */ - -// -// The LineSeg. -// typedef struct { - vertex_t* v1; - vertex_t* v2; - - fixed_t offset; - - angle_t angle; - - side_t* sidedef; - line_t* linedef; - - // Sector references. - // Could be retrieved from linedef, too. - // backsector is NULL for one sided lines - sector_t* frontsector; - sector_t* backsector; - -} seg_t; + vertex_t *v1; + vertex_t *v2; + fixed_t offset; + angle_t angle; + + side_t *sidedef; + line_t *linedef; + + /* Sector references. + * Could be retrieved from linedef, too. + * backsector is NULL for one sided lines + */ + + sector_t *frontsector; + sector_t *backsector; +} seg_t; + +/* BSP node. */ -// -// BSP node. -// typedef struct { - // Partition line. - fixed_t x; - fixed_t y; - fixed_t dx; - fixed_t dy; - - // Bounding box for each child. - fixed_t bbox[2][4]; - - // If NF_SUBSECTOR its a subsector. - unsigned short children[2]; - + /* Partition line. */ + + fixed_t x; + fixed_t y; + fixed_t dx; + fixed_t dy; + + /* Bounding box for each child. */ + + fixed_t bbox[2][4]; + + /* If NF_SUBSECTOR its a subsector. */ + + unsigned short children[2]; } node_t; +/* PC direct to screen pointers + * B UNUSED - keep till detailshift in r_draw.c resolved + * extern byte* destview; + * extern byte* destscreen; + */ +/* OTHER TYPES */ +/* This could be wider for >8 bit display. + * + * Indeed, true color support is possible precalculating 24bpp + * lightmap/colormap LUT. from darkening PLAYPAL to all black. Could even + * use more than 32 levels. + */ -// PC direct to screen pointers -//B UNUSED - keep till detailshift in r_draw.c resolved -//extern byte* destview; -//extern byte* destscreen; +typedef pixel_t lighttable_t; +/* ? */ +typedef struct drawseg_s +{ + seg_t *curline; + int x1; + int x2; + fixed_t scale1; + fixed_t scale2; + fixed_t scalestep; + /* 0=none, 1=bottom, 2=top, 3=both */ -// -// OTHER TYPES -// + int silhouette; -// This could be wider for >8 bit display. -// Indeed, true color support is posibble -// precalculating 24bpp lightmap/colormap LUT. -// from darkening PLAYPAL to all black. -// Could even us emore than 32 levels. -typedef pixel_t lighttable_t; + /* do not clip sprites above this */ + fixed_t bsilheight; + /* do not clip sprites below this */ + fixed_t tsilheight; -// -// ? -// -typedef struct drawseg_s -{ - seg_t* curline; - int x1; - int x2; - - fixed_t scale1; - fixed_t scale2; - fixed_t scalestep; - - // 0=none, 1=bottom, 2=top, 3=both - int silhouette; - - // do not clip sprites above this - fixed_t bsilheight; - - // do not clip sprites below this - fixed_t tsilheight; - - // Pointers to lists for sprite clipping, - // all three adjusted so [x1] is first value. - short* sprtopclip; - short* sprbottomclip; - short* maskedtexturecol; - -} drawseg_t; + /* Pointers to lists for sprite clipping, all three adjusted so [x1] is + * first value. + */ + short *sprtopclip; + short *sprbottomclip; + short *maskedtexturecol; +} drawseg_t; +/* A vissprite_t is a thing that will be drawn during a refresh. + * + * I.e. a sprite object that is partly visible. + */ -// A vissprite_t is a thing -// that will be drawn during a refresh. -// I.e. a sprite object that is partly visible. typedef struct vissprite_s { - // Doubly linked list. - struct vissprite_s* prev; - struct vissprite_s* next; - - int x1; - int x2; - - // for line side calculation - fixed_t gx; - fixed_t gy; - - // global bottom / top for silhouette clipping - fixed_t gz; - fixed_t gzt; - - // horizontal position of x1 - fixed_t startfrac; - - fixed_t scale; - - // negative if flipped - fixed_t xiscale; - - fixed_t texturemid; - int patch; - - // for color translation and shadow draw, - // maxbright frames as well - lighttable_t* colormap; - - int mobjflags; - + /* Doubly linked list. */ + + struct vissprite_s *prev; + struct vissprite_s *next; + + int x1; + int x2; + + /* for line side calculation */ + + fixed_t gx; + fixed_t gy; + + /* global bottom / top for silhouette clipping */ + + fixed_t gz; + fixed_t gzt; + + /* horizontal position of x1 */ + + fixed_t startfrac; + + fixed_t scale; + + /* negative if flipped */ + + fixed_t xiscale; + + fixed_t texturemid; + int patch; + + /* for color translation and shadow draw, maxbright frames as well */ + + lighttable_t *colormap; + + int mobjflags; } vissprite_t; +/* Sprites are patches with a special naming convention so they can be + * recognized by r_init_sprites. + * + * The base name is NNNNFx or NNNNFxFx, with x indicating the rotation, + * x = 0, 1-7. + * + * The sprite and frame specified by a thing_t is range checked at run time. + * + * A sprite is a patch_t that is assumed to represent a three dimensional + * object and may have multiple rotations pre drawn. + * + * Horizontal flipping is used to save space, thus NNNNF2F5 defines a + * mirrored patch. + * + * Some sprites will only have one picture used for all views: NNNNF0 + */ -// -// Sprites are patches with a special naming convention -// so they can be recognized by R_InitSprites. -// The base name is NNNNFx or NNNNFxFx, with -// x indicating the rotation, x = 0, 1-7. -// The sprite and frame specified by a thing_t -// is range checked at run time. -// A sprite is a patch_t that is assumed to represent -// a three dimensional object and may have multiple -// rotations pre drawn. -// Horizontal flipping is used to save space, -// thus NNNNF2F5 defines a mirrored patch. -// Some sprites will only have one picture used -// for all views: NNNNF0 -// typedef struct { - // If false use 0 for any position. - // Note: as eight entries are available, - // we might as well insert the same name eight times. - boolean rotate; + /* If false use 0 for any position. + * Note: as eight entries are available, we might as well insert the same + * name eight times. + */ - // Lump to use for view angles 0-7. - short lump[8]; + boolean rotate; - // Flip bit (1 = flip) to use for view angles 0-7. - byte flip[8]; - -} spriteframe_t; + /* Lump to use for view angles 0-7. */ + + short lump[8]; + /* Flip bit (1 = flip) to use for view angles 0-7. */ + byte flip[8]; +} spriteframe_t; + +/* A sprite definition: a number of animation frames. */ -// -// A sprite definition: -// a number of animation frames. -// typedef struct { - int numframes; - spriteframe_t* spriteframes; - + int numframes; + spriteframe_t *spriteframes; } spritedef_t; +/* Now what is a visplane, anyway? */ - -// -// Now what is a visplane, anyway? -// typedef struct { - fixed_t height; - int picnum; - int lightlevel; - int minx; - int maxx; - - // leave pads for [minx-1]/[maxx+1] - - byte pad1; - // Here lies the rub for all - // dynamic resize/change of resolution. - byte top[SCREENWIDTH]; - byte pad2; - byte pad3; - // See above. - byte bottom[SCREENWIDTH]; - byte pad4; + fixed_t height; + int picnum; + int lightlevel; + int minx; + int maxx; -} visplane_t; + /* leave pads for [minx-1]/[maxx+1] */ + + byte pad1; + /* Here lies the rub for all dynamic resize/change of resolution. */ + byte top[SCREENWIDTH]; + byte pad2; + byte pad3; + /* See above. */ + + byte bottom[SCREENWIDTH]; + byte pad4; +} visplane_t; -#endif +#endif /* __R_DEFS__ */ diff --git a/games/NXDoom/src/doom/r_draw.c b/games/NXDoom/src/doom/r_draw.c index 4fc41b5d51e..ff243912aed 100644 --- a/games/NXDoom/src/doom/r_draw.c +++ b/games/NXDoom/src/doom/r_draw.c @@ -1,959 +1,965 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The actual span/column drawing functions. -// Here find the main potential for optimization, -// e.g. inline assembly, different algorithms. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_draw.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * The actual span/column drawing functions. + * Here find the main potential for optimization, e.g. inline assembly, + * different algorithms. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - - -#include "doomdef.h" #include "deh_main.h" +#include "doomdef.h" #include "i_system.h" -#include "z_zone.h" #include "w_wad.h" +#include "z_zone.h" #include "r_local.h" -// Needs access to LFB (guess what). +/* Needs access to LFB (guess what). */ + #include "v_video.h" -// State. +/* State. */ + #include "doomstat.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ? */ + +#define MAXWIDTH 1120 +#define MAXHEIGHT 832 + +/* status bar height at bottom of screen */ + +#define SBARHEIGHT 32 + +/* Spectre/Invisibility. */ + +#define FUZZTABLE 50 +#define FUZZOFF (SCREENWIDTH) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* All drawing to the view buffer is accomplished in this file. + * + * The other refresh files only know about coordinates, not the architecture + * of the frame buffer. + * + * Conveniently, the frame buffer is a linear one, and we need only the base + * address, and the total size == width*height*depth/8., + */ + +byte *viewimage; +int viewwidth; +int scaledviewwidth; +int viewheight; +int viewwindowx; +int viewwindowy; +pixel_t *ylookup[MAXHEIGHT]; +int columnofs[MAXWIDTH]; + +/* Color tables for different players, translate a limited part to another + * (color ramps used for suit colors). + */ + +byte translations[3][256]; + +lighttable_t *dc_colormap; +int dc_x; +int dc_yl; +int dc_yh; +fixed_t dc_iscale; +fixed_t dc_texturemid; + +/* first pixel in a column (possibly virtual) */ + +byte *dc_source; + +int fuzzoffset[FUZZTABLE] = +{ + FUZZOFF, -FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, + FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, + FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, + FUZZOFF, -FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, FUZZOFF, FUZZOFF, + -FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, -FUZZOFF, + FUZZOFF, FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, FUZZOFF, + FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, + FUZZOFF, +}; + +int fuzzpos = 0; + +byte *dc_translation; +byte *translationtables; + +int ds_y; +int ds_x1; +int ds_x2; + +lighttable_t *ds_colormap; -// ? -#define MAXWIDTH 1120 -#define MAXHEIGHT 832 - -// status bar height at bottom of screen -#define SBARHEIGHT 32 - -// -// All drawing to the view buffer is accomplished in this file. -// The other refresh files only know about ccordinates, -// not the architecture of the frame buffer. -// Conveniently, the frame buffer is a linear one, -// and we need only the base address, -// and the total size == width*height*depth/8., -// - - -byte* viewimage; -int viewwidth; -int scaledviewwidth; -int viewheight; -int viewwindowx; -int viewwindowy; -pixel_t* ylookup[MAXHEIGHT]; -int columnofs[MAXWIDTH]; - -// Color tables for different players, -// translate a limited part to another -// (color ramps used for suit colors). -// -byte translations[3][256]; - -// Backing buffer containing the bezel drawn around the screen and -// surrounding background. +fixed_t ds_xfrac; +fixed_t ds_yfrac; +fixed_t ds_xstep; +fixed_t ds_ystep; + +/* start of a 64*64 tile image */ + +byte *ds_source; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Backing buffer containing the bezel drawn around the screen and + * surrounding background. + */ static pixel_t *background_buffer = NULL; +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Source is the top of the column to scale. + * + * A column is a vertical slice/span from a wall texture that, given the DOOM + * style restrictions on the view orientation, will always have constant z + * depth. + * + * Thus a special case loop for very fast rendering can be used. It has also + * been used with Wolfenstein 3D. + */ + +void r_draw_column(void) +{ + int count; + pixel_t *dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + /* Zero length, column does not exceed a pixel. */ + + if (count < 0) return; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + i_error("r_draw_column: %i to %i at %i", dc_yl, dc_yh, dc_x); +#endif + + /* Framebuffer destination address. + * Use ylookup LUT to avoid multiply with ScreenWidth. + * Use columnofs LUT for subwindows? + */ + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + /* Determine scaling, which is the only mapping to be done. */ + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + /* Inner loop that does the actual texture mapping, + * e.g. a DDA-lile scaling. + * This is as fast as it gets. + */ -// -// R_DrawColumn -// Source is the top of the column to scale. -// -lighttable_t* dc_colormap; -int dc_x; -int dc_yl; -int dc_yh; -fixed_t dc_iscale; -fixed_t dc_texturemid; - -// first pixel in a column (possibly virtual) -byte* dc_source; - -// just for profiling -int dccount; - -// -// A column is a vertical slice/span from a wall texture that, -// given the DOOM style restrictions on the view orientation, -// will always have constant z depth. -// Thus a special case loop for very fast rendering can -// be used. It has also been used with Wolfenstein 3D. -// -void R_DrawColumn (void) -{ - int count; - pixel_t* dest; - fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - - // Zero length, column does not exceed a pixel. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) - I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - dest = ylookup[dc_yl] + columnofs[dc_x]; - - // Determine scaling, - // which is the only mapping to be done. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - // Inner loop that does the actual texture mapping, - // e.g. a DDA-lile scaling. - // This is as fast as it gets. - do + do { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; - - dest += SCREENWIDTH; - frac += fracstep; - - } while (count--); -} + /* Re-map color indices from wall texture column + * using a lighting/special effects LUT. + */ + *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + frac += fracstep; + } + while (count--); +} + +/* UNUSED. Loop unrolled. */ -// UNUSED. -// Loop unrolled. #if 0 -void R_DrawColumn (void) -{ - int count; - byte* source; - byte* dest; - byte* colormap; - - unsigned frac; - unsigned fracstep; - unsigned fracstep2; - unsigned fracstep3; - unsigned fracstep4; - - count = dc_yh - dc_yl + 1; - - source = dc_source; - colormap = dc_colormap; - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale<<9; - frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; - - fracstep2 = fracstep+fracstep; - fracstep3 = fracstep2+fracstep; - fracstep4 = fracstep3+fracstep; - - while (count >= 8) - { - dest[0] = colormap[source[frac>>25]]; - dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; - dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; - dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]]; - - frac += fracstep4; - - dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; - dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; - dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; - dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; - - frac += fracstep4; - dest += SCREENWIDTH*8; - count -= 8; - } - - while (count > 0) - { - *dest = colormap[source[frac>>25]]; - dest += SCREENWIDTH; - frac += fracstep; - count--; - } +void r_draw_column(void) +{ + int count; + byte *source; + byte *dest; + byte *colormap; + + unsigned frac; + unsigned fracstep; + unsigned fracstep2; + unsigned fracstep3; + unsigned fracstep4; + + count = dc_yh - dc_yl + 1; + + source = dc_source; + colormap = dc_colormap; + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale << 9; + frac = (dc_texturemid + (dc_yl - centery) * dc_iscale) << 9; + + fracstep2 = fracstep + fracstep; + fracstep3 = fracstep2 + fracstep; + fracstep4 = fracstep3 + fracstep; + + while (count >= 8) + { + dest[0] = colormap[source[frac >> 25]]; + dest[SCREENWIDTH] = colormap[source[(frac + fracstep) >> 25]]; + dest[SCREENWIDTH * 2] = colormap[source[(frac + fracstep2) >> 25]]; + dest[SCREENWIDTH * 3] = colormap[source[(frac + fracstep3) >> 25]]; + + frac += fracstep4; + + dest[SCREENWIDTH * 4] = colormap[source[frac >> 25]]; + dest[SCREENWIDTH * 5] = colormap[source[(frac + fracstep) >> 25]]; + dest[SCREENWIDTH * 6] = colormap[source[(frac + fracstep2) >> 25]]; + dest[SCREENWIDTH * 7] = colormap[source[(frac + fracstep3) >> 25]]; + + frac += fracstep4; + dest += SCREENWIDTH * 8; + count -= 8; + } + + while (count > 0) + { + *dest = colormap[source[frac >> 25]]; + dest += SCREENWIDTH; + frac += fracstep; + count--; + } } #endif +void r_draw_column_low(void) +{ + int count; + pixel_t *dest; + pixel_t *dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + count = dc_yh - dc_yl; + + /* Zero length. */ + + if (count < 0) return; -void R_DrawColumnLow (void) -{ - int count; - pixel_t* dest; - pixel_t* dest2; - fixed_t frac; - fixed_t fracstep; - int x; - - count = dc_yh - dc_yl; - - // Zero length. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { - - I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + i_error("r_draw_column: %i to %i at %i", dc_yl, dc_yh, dc_x); } - // dccount++; -#endif - // Blocky mode, need to multiply by 2. - x = dc_x << 1; - - dest = ylookup[dc_yl] + columnofs[x]; - dest2 = ylookup[dc_yl] + columnofs[x+1]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - do +#endif + + /* Blocky mode, need to multiply by 2. */ + + x = dc_x << 1; + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x + 1]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do { - // Hack. Does not work corretly. - *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; - dest += SCREENWIDTH; - dest2 += SCREENWIDTH; - frac += fracstep; + /* Hack. Does not work correctly. */ - } while (count--); + *dest2 = *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + frac += fracstep; + } + while (count--); } +/* Framebuffer postprocessing. + * + * Creates a fuzzy image by copying pixels from adjacent ones to left and + * right. + * + * Used with an all black colormap, this could create the SHADOW effect, i.e. + * spectres and invisible players. + */ -// -// Spectre/Invisibility. -// -#define FUZZTABLE 50 -#define FUZZOFF (SCREENWIDTH) +void r_draw_fuzz_column(void) +{ + int count; + pixel_t *dest; + /* Adjust borders. Low... */ -int fuzzoffset[FUZZTABLE] = -{ - FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, - FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, - FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF, - FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF, - FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF, - FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF, - FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF -}; - -int fuzzpos = 0; - - -// -// Framebuffer postprocessing. -// Creates a fuzzy image by copying pixels -// from adjacent ones to left and right. -// Used with an all black colormap, this -// could create the SHADOW effect, -// i.e. spectres and invisible players. -// -void R_DrawFuzzColumn (void) -{ - int count; - pixel_t* dest; - - // Adjust borders. Low... - if (!dc_yl) - dc_yl = 1; - - // .. and high. - if (dc_yh == viewheight-1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - - // Zero length. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + if (!dc_yl) dc_yl = 1; + + /* .. and high. */ + + if (dc_yh == viewheight - 1) dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + /* Zero length. */ + + if (count < 0) return; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { - I_Error ("R_DrawFuzzColumn: %i to %i at %i", - dc_yl, dc_yh, dc_x); + i_error("r_draw_fuzz_column: %i to %i at %i", dc_yl, dc_yh, dc_x); } #endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - // Looks like an attempt at dithering, - // using the colormap #6 (of 0-31, a bit - // brighter than average). - do + dest = ylookup[dc_yl] + columnofs[dc_x]; + + /* Looks like an attempt at dithering, + * using the colormap #6 (of 0-31, a bit + * brighter than average). + */ + + do { - // Lookup framebuffer, and retrieve - // a pixel that is either one column - // left or right of the current one. - // Add index from colormap to index. - *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; - - // Clamp table lookup index. - if (++fuzzpos == FUZZTABLE) - fuzzpos = 0; - - dest += SCREENWIDTH; - } while (count--); -} - -// low detail mode version - -void R_DrawFuzzColumnLow (void) -{ - int count; - pixel_t* dest; - pixel_t* dest2; - int x; - - // Adjust borders. Low... - if (!dc_yl) - dc_yl = 1; - - // .. and high. - if (dc_yh == viewheight-1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - - // Zero length. - if (count < 0) - return; - - // low detail mode, need to multiply by 2 - - x = dc_x << 1; - -#ifdef RANGECHECK - if ((unsigned)x >= SCREENWIDTH - || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + /* Lookup framebuffer, and retrieve a pixel that is either one column + * left or right of the current one. Add index from colormap to index. + */ + + *dest = colormaps[6 * 256 + dest[fuzzoffset[fuzzpos]]]; + + /* Clamp table lookup index. */ + + if (++fuzzpos == FUZZTABLE) fuzzpos = 0; + + dest += SCREENWIDTH; + } + while (count--); +} + +/* low detail mode version */ + +void r_draw_fuzz_column_low(void) +{ + int count; + pixel_t *dest; + pixel_t *dest2; + int x; + + /* Adjust borders. Low... */ + + if (!dc_yl) dc_yl = 1; + + /* .. and high. */ + + if (dc_yh == viewheight - 1) dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + /* Zero length. */ + + if (count < 0) return; + + /* low detail mode, need to multiply by 2 */ + + x = dc_x << 1; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { - I_Error ("R_DrawFuzzColumn: %i to %i at %i", - dc_yl, dc_yh, dc_x); + i_error("r_draw_fuzz_column: %i to %i at %i", dc_yl, dc_yh, dc_x); } #endif - - dest = ylookup[dc_yl] + columnofs[x]; - dest2 = ylookup[dc_yl] + columnofs[x+1]; - - // Looks like an attempt at dithering, - // using the colormap #6 (of 0-31, a bit - // brighter than average). - do - { - // Lookup framebuffer, and retrieve - // a pixel that is either one column - // left or right of the current one. - // Add index from colormap to index. - *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; - *dest2 = colormaps[6*256+dest2[fuzzoffset[fuzzpos]]]; - - // Clamp table lookup index. - if (++fuzzpos == FUZZTABLE) - fuzzpos = 0; - - dest += SCREENWIDTH; - dest2 += SCREENWIDTH; - } while (count--); -} - - - - - -// -// R_DrawTranslatedColumn -// Used to draw player sprites -// with the green colorramp mapped to others. -// Could be used with different translation -// tables, e.g. the lighter colored version -// of the BaronOfHell, the HellKnight, uses -// identical sprites, kinda brightened up. -// -byte* dc_translation; -byte* translationtables; - -void R_DrawTranslatedColumn (void) -{ - int count; - pixel_t* dest; - fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x + 1]; + + /* Looks like an attempt at dithering, using the colormap #6 + * (of 0-31, a bit brighter than average). + */ + + do { - I_Error ( "R_DrawColumn: %i to %i at %i", - dc_yl, dc_yh, dc_x); + /* Lookup framebuffer, and retrieve a pixel that is either one column + * left or right of the current one. Add index from colormap to index. + */ + + *dest = colormaps[6 * 256 + dest[fuzzoffset[fuzzpos]]]; + *dest2 = colormaps[6 * 256 + dest2[fuzzoffset[fuzzpos]]]; + + /* Clamp table lookup index. */ + + if (++fuzzpos == FUZZTABLE) fuzzpos = 0; + + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; } - -#endif + while (count--); +} +/* r_draw_translated_column + * + * Used to draw player sprites with the green colorramp mapped to others. + * + * Could be used with different translation tables, e.g. the lighter colored + * version of the BaronOfHell, the HellKnight, uses identical sprites, kinda + * brightened up. + */ - dest = ylookup[dc_yl] + columnofs[dc_x]; +void r_draw_translated_column(void) +{ + int count; + pixel_t *dest; + fixed_t frac; + fixed_t fracstep; - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; + count = dc_yh - dc_yl; + if (count < 0) return; - // Here we do an additional index re-mapping. - do - { - // Translation tables are used - // to map certain colorramps to other ones, - // used with PLAY sprites. - // Thus the "green" ramp of the player 0 sprite - // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; - dest += SCREENWIDTH; - - frac += fracstep; - } while (count--); -} - -void R_DrawTranslatedColumnLow (void) -{ - int count; - pixel_t* dest; - pixel_t* dest2; - fixed_t frac; - fixed_t fracstep; - int x; - - count = dc_yh - dc_yl; - if (count < 0) - return; - - // low detail, need to scale by 2 - x = dc_x << 1; - -#ifdef RANGECHECK - if ((unsigned)x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { - I_Error ( "R_DrawColumn: %i to %i at %i", - dc_yl, dc_yh, x); + i_error("r_draw_column: %i to %i at %i", dc_yl, dc_yh, dc_x); } - -#endif +#endif + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + /* Looks familiar. */ - dest = ylookup[dc_yl] + columnofs[x]; - dest2 = ylookup[dc_yl] + columnofs[x+1]; + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; + /* Here we do an additional index re-mapping. */ - // Here we do an additional index re-mapping. - do + do { - // Translation tables are used - // to map certain colorramps to other ones, - // used with PLAY sprites. - // Thus the "green" ramp of the player 0 sprite - // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; - *dest2 = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; - dest += SCREENWIDTH; - dest2 += SCREENWIDTH; - - frac += fracstep; - } while (count--); -} - - - - -// -// R_InitTranslationTables -// Creates the translation tables to map -// the green color ramp to gray, brown, red. -// Assumes a given structure of the PLAYPAL. -// Could be read from a lump instead. -// -void R_InitTranslationTables (void) + /* Translation tables are used to map certain colorramps to other ones, + * used with PLAY sprites. + * + * Thus the "green" ramp of the player 0 sprite is mapped to gray, red, + * black/indigo. + */ + + *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + dest += SCREENWIDTH; + + frac += fracstep; + } + while (count--); +} + +void r_draw_translated_column_low(void) { - int i; - - translationtables = Z_Malloc (256*3, PU_STATIC, 0); - - // translate just the 16 green colors - for (i=0 ; i<256 ; i++) + int count; + pixel_t *dest; + pixel_t *dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + count = dc_yh - dc_yl; + if (count < 0) return; + + /* low detail, need to scale by 2 */ + + x = dc_x << 1; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { - if (i >= 0x70 && i<= 0x7f) - { - // map green ramp to gray, brown, red - translationtables[i] = 0x60 + (i&0xf); - translationtables [i+256] = 0x40 + (i&0xf); - translationtables [i+512] = 0x20 + (i&0xf); - } - else - { - // Keep all other colors as is. - translationtables[i] = translationtables[i+256] - = translationtables[i+512] = i; - } + i_error("r_draw_column: %i to %i at %i", dc_yl, dc_yh, x); } + +#endif + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x + 1]; + + /* Looks familiar. */ + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + /* Here we do an additional index re-mapping. */ + + do + { + /* Translation tables are used to map certain colorramps to other ones, + * used with PLAY sprites. + * + * Thus the "green" ramp of the player 0 sprite is mapped to gray, red, + * black/indigo. + */ + + *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + *dest2 = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + + frac += fracstep; + } + while (count--); } +/* r_init_translation_table + * + * Creates the translation tables to map the green color ramp to gray, brown, + * red. + * + * Assumes a given structure of the PLAYPAL. Could be read from a lump + * instead. + */ + +void r_init_translation_table(void) +{ + int i; + + translationtables = z_malloc(256 * 3, PU_STATIC, 0); + + /* translate just the 16 green colors */ + for (i = 0; i < 256; i++) + { + if (i >= 0x70 && i <= 0x7f) + { + /* map green ramp to gray, brown, red */ + translationtables[i] = 0x60 + (i & 0xf); + translationtables[i + 256] = 0x40 + (i & 0xf); + translationtables[i + 512] = 0x20 + (i & 0xf); + } + else + { + /* Keep all other colors as is. */ + + translationtables[i] = translationtables[i + 256] = + translationtables[i + 512] = i; + } + } +} -// -// R_DrawSpan -// With DOOM style restrictions on view orientation, -// the floors and ceilings consist of horizontal slices -// or spans with constant z depth. -// However, rotation around the world z axis is possible, -// thus this mapping, while simpler and faster than -// perspective correct texture mapping, has to traverse -// the texture at an angle in all but a few cases. -// In consequence, flats are not stored by column (like walls), -// and the inner loop has to step in texture space u and v. -// -int ds_y; -int ds_x1; -int ds_x2; - -lighttable_t* ds_colormap; - -fixed_t ds_xfrac; -fixed_t ds_yfrac; -fixed_t ds_xstep; -fixed_t ds_ystep; - -// start of a 64*64 tile image -byte* ds_source; - -// just for profiling -int dscount; - - -// -// Draws the actual span. -void R_DrawSpan (void) -{ - unsigned int position, step; - pixel_t *dest; - int count; - int spot; - unsigned int xtemp, ytemp; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 - || ds_x1<0 - || ds_x2>=SCREENWIDTH - || (unsigned)ds_y>SCREENHEIGHT) +/* r_draw_span + * + * With DOOM style restrictions on view orientation, the floors and ceilings + * consist of horizontal slices or spans with constant z depth. + * + * However, rotation around the world z axis is possible, thus this mapping, + * while simpler and faster than perspective correct texture mapping, has to + * traverse the texture at an angle in all but a few cases. + * + * In consequence, flats are not stored by column (like walls), and the inner + * loop has to step in texture space u and v. + * + * Draws the actual span. + */ + +void r_draw_span(void) +{ + unsigned int position; + unsigned int step; + pixel_t *dest; + int count; + int spot; + unsigned int xtemp; + unsigned int ytemp; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH || + (unsigned)ds_y > SCREENHEIGHT) { - I_Error( "R_DrawSpan: %i to %i at %i", - ds_x1,ds_x2,ds_y); + i_error("r_draw_span: %i to %i at %i", ds_x1, ds_x2, ds_y); } -// dscount++; #endif - // Pack position and step variables into a single 32-bit integer, - // with x in the top 16 bits and y in the bottom 16 bits. For - // each 16-bit part, the top 6 bits are the integer part and the - // bottom 10 bits are the fractional part of the pixel position. + /* Pack position and step variables into a single 32-bit integer, + * with x in the top 16 bits and y in the bottom 16 bits. For + * each 16-bit part, the top 6 bits are the integer part and the + * bottom 10 bits are the fractional part of the pixel position. + */ - position = ((ds_xfrac << 10) & 0xffff0000) - | ((ds_yfrac >> 6) & 0x0000ffff); - step = ((ds_xstep << 10) & 0xffff0000) - | ((ds_ystep >> 6) & 0x0000ffff); + position = ((ds_xfrac << 10) & 0xffff0000) | + ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0x0000ffff); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = ylookup[ds_y] + columnofs[ds_x1]; - // We do not check for zero spans here? - count = ds_x2 - ds_x1; + /* We do not check for zero spans here? */ - do + count = ds_x2 - ds_x1; + + do { - // Calculate current texture index in u,v. - ytemp = (position >> 4) & 0x0fc0; - xtemp = (position >> 26); - spot = xtemp | ytemp; + /* Calculate current texture index in u,v. */ - // Lookup pixel from flat texture tile, - // re-index using light/colormap. - *dest++ = ds_colormap[ds_source[spot]]; + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; - position += step; + /* Lookup pixel from flat texture tile, re-index using light/colormap. + */ - } while (count--); -} + *dest++ = ds_colormap[ds_source[spot]]; + position += step; + } + while (count--); +} +/* UNUSED. Loop unrolled by 4. */ -// UNUSED. -// Loop unrolled by 4. #if 0 -void R_DrawSpan (void) -{ - unsigned position, step; - - byte* source; - byte* colormap; - pixel_t* dest; - - unsigned count; - usingned spot; - unsigned value; - unsigned temp; - unsigned xtemp; - unsigned ytemp; - - position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff); - step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff); - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - - while (count >= 4) - { - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[0] = colormap[source[spot]]; - - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[1] = colormap[source[spot]]; - - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[2] = colormap[source[spot]]; - - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[3] = colormap[source[spot]]; - - count -= 4; - dest += 4; - } - while (count > 0) - { - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - *dest++ = colormap[source[spot]]; - count--; - } -} +void r_draw_span(void) +{ + unsigned position; + unsigned step; + + byte *source; + byte *colormap; + pixel_t *dest; + + unsigned count; + usingned spot; + unsigned value; + unsigned temp; + unsigned xtemp; + unsigned ytemp; + + position = ((ds_xfrac << 10) & 0xffff0000) | ((ds_yfrac >> 6) & 0xffff); + step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0xffff); + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; + + while (count >= 4) + { + ytemp = position >> 4; + ytemp = ytemp & 4032; + xtemp = position >> 26; + spot = xtemp | ytemp; + position += step; + dest[0] = colormap[source[spot]]; + + ytemp = position >> 4; + ytemp = ytemp & 4032; + xtemp = position >> 26; + spot = xtemp | ytemp; + position += step; + dest[1] = colormap[source[spot]]; + + ytemp = position >> 4; + ytemp = ytemp & 4032; + xtemp = position >> 26; + spot = xtemp | ytemp; + position += step; + dest[2] = colormap[source[spot]]; + + ytemp = position >> 4; + ytemp = ytemp & 4032; + xtemp = position >> 26; + spot = xtemp | ytemp; + position += step; + dest[3] = colormap[source[spot]]; + + count -= 4; + dest += 4; + } + while (count > 0) + { + ytemp = position >> 4; + ytemp = ytemp & 4032; + xtemp = position >> 26; + spot = xtemp | ytemp; + position += step; + *dest++ = colormap[source[spot]]; + count--; + } +} #endif +/* Again.. */ -// -// Again.. -// -void R_DrawSpanLow (void) +void r_draw_span_low(void) { - unsigned int position, step; - unsigned int xtemp, ytemp; - pixel_t *dest; - int count; - int spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 - || ds_x1<0 - || ds_x2>=SCREENWIDTH - || (unsigned)ds_y>SCREENHEIGHT) + unsigned int position; + unsigned int step; + unsigned int xtemp; + unsigned int ytemp; + pixel_t *dest; + int count; + int spot; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH || + (unsigned)ds_y > SCREENHEIGHT) { - I_Error( "R_DrawSpan: %i to %i at %i", - ds_x1,ds_x2,ds_y); + i_error("r_draw_span: %i to %i at %i", ds_x1, ds_x2, ds_y); } -// dscount++; #endif - position = ((ds_xfrac << 10) & 0xffff0000) - | ((ds_yfrac >> 6) & 0x0000ffff); - step = ((ds_xstep << 10) & 0xffff0000) - | ((ds_ystep >> 6) & 0x0000ffff); + position = ((ds_xfrac << 10) & 0xffff0000) | + ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0x0000ffff); - count = (ds_x2 - ds_x1); + count = (ds_x2 - ds_x1); - // Blocky mode, need to multiply by 2. - ds_x1 <<= 1; - ds_x2 <<= 1; + /* Blocky mode, need to multiply by 2. */ - dest = ylookup[ds_y] + columnofs[ds_x1]; + ds_x1 <<= 1; + ds_x2 <<= 1; - do + dest = ylookup[ds_y] + columnofs[ds_x1]; + + do { - // Calculate current texture index in u,v. - ytemp = (position >> 4) & 0x0fc0; - xtemp = (position >> 26); - spot = xtemp | ytemp; + /* Calculate current texture index in u,v. */ + + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + /* Lowres/blocky mode does it twice, while scale is adjusted + * appropriately. + */ + + *dest++ = ds_colormap[ds_source[spot]]; + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + } + while (count--); +} + +/* r_init_buffer + * + * Creates lookup tables that avoid multiplies and other hazzles for getting + * the framebuffer address of a pixel to draw. + */ + +void r_init_buffer(int width, int height) +{ + int i; + + /* Handle resize, + * e.g. smaller view windows + * with border and/or status bar. + */ + + viewwindowx = (SCREENWIDTH - width) >> 1; - // Lowres/blocky mode does it twice, - // while scale is adjusted appropriately. - *dest++ = ds_colormap[ds_source[spot]]; - *dest++ = ds_colormap[ds_source[spot]]; + /* Column offset. For windows. */ - position += step; + for (i = 0; i < width; i++) + columnofs[i] = viewwindowx + i; - } while (count--); + /* Samw with base row offset. */ + + if (width == SCREENWIDTH) + viewwindowy = 0; + else + viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1; + + /* Preclaculate all row offsets. */ + + for (i = 0; i < height; i++) + ylookup[i] = i_video_buffer + (i + viewwindowy) * SCREENWIDTH; } -// -// R_InitBuffer -// Creats lookup tables that avoid -// multiplies and other hazzles -// for getting the framebuffer address -// of a pixel to draw. -// -void -R_InitBuffer -( int width, - int height ) -{ - int i; - - // Handle resize, - // e.g. smaller view windows - // with border and/or status bar. - viewwindowx = (SCREENWIDTH-width) >> 1; - - // Column offset. For windows. - for (i=0 ; i> 1; - - // Preclaculate all row offsets. - for (i=0 ; i #include +#include - -#include "doomdef.h" #include "d_loop.h" +#include "doomdef.h" #include "m_bbox.h" #include "m_menu.h" @@ -35,856 +38,844 @@ #include "r_local.h" #include "r_sky.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Fineangles in the SCREENWIDTH wide window. */ +#define FIELDOFVIEW 2048 +#define DISTMAP 2 -// Fineangles in the SCREENWIDTH wide window. -#define FIELDOFVIEW 2048 +/**************************************************************************** + * Public Data + ****************************************************************************/ +int viewangleoffset; +/* increment every time a check is made */ -int viewangleoffset; +int validcount = 1; -// increment every time a check is made -int validcount = 1; +lighttable_t *fixedcolormap; +int centerx; +int centery; -lighttable_t* fixedcolormap; +fixed_t centerxfrac; +fixed_t centeryfrac; +fixed_t projection; -int centerx; -int centery; +/* just for profiling purposes */ -fixed_t centerxfrac; -fixed_t centeryfrac; -fixed_t projection; +int framecount; -// just for profiling purposes -int framecount; +int sscount; +int linecount; +int loopcount; -int sscount; -int linecount; -int loopcount; +fixed_t viewx; +fixed_t viewy; +fixed_t viewz; -fixed_t viewx; -fixed_t viewy; -fixed_t viewz; +angle_t viewangle; -angle_t viewangle; +fixed_t viewcos; +fixed_t viewsin; -fixed_t viewcos; -fixed_t viewsin; +player_t *viewplayer; -player_t* viewplayer; +/* 0 = high, 1 = low */ -// 0 = high, 1 = low -int detailshift; +int detailshift; -// -// precalculated math tables -// -angle_t clipangle; +/* precalculated math tables */ -// The viewangletox[viewangle + FINEANGLES/4] lookup -// maps the visible view angles to screen X coordinates, -// flattening the arc to a flat projection plane. -// There will be many angles mapped to the same X. -int viewangletox[FINEANGLES/2]; +angle_t clipangle; -// The xtoviewangleangle[] table maps a screen pixel -// to the lowest viewangle that maps back to x ranges -// from clipangle to -clipangle. -angle_t xtoviewangle[SCREENWIDTH+1]; +/* The viewangletox[viewangle + FINEANGLES/4] lookup + * maps the visible view angles to screen X coordinates, + * flattening the arc to a flat projection plane. + * There will be many angles mapped to the same X. + */ -lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; -lighttable_t* scalelightfixed[MAXLIGHTSCALE]; -lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ]; +int viewangletox[FINEANGLES / 2]; -// bumped light from gun blasts -int extralight; +/* The xtoviewangleangle[] table maps a screen pixel + * to the lowest viewangle that maps back to x ranges + * from clipangle to -clipangle. + */ +angle_t xtoviewangle[SCREENWIDTH + 1]; +lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; +lighttable_t *scalelightfixed[MAXLIGHTSCALE]; +lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; -void (*colfunc) (void); -void (*basecolfunc) (void); -void (*fuzzcolfunc) (void); -void (*transcolfunc) (void); -void (*spanfunc) (void); +/* bumped light from gun blasts */ +int extralight; +void (*colfunc)(void); +void (*basecolfunc)(void); +void (*fuzzcolfunc)(void); +void (*transcolfunc)(void); +void (*spanfunc)(void); -// -// R_AddPointToBox -// Expand a given bbox -// so that it encloses a given point. -// -void -R_AddPointToBox -( int x, - int y, - fixed_t* box ) +boolean setsizeneeded; +int setblocks; +int setdetail; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: r_add_point_to_box + * + * Description: + * Expand a given bbox so that it encloses a given point. + * + ****************************************************************************/ + +static void r_add_point_to_box(int x, int y, fixed_t *box) { - if (x< box[BOXLEFT]) - box[BOXLEFT] = x; - if (x> box[BOXRIGHT]) - box[BOXRIGHT] = x; - if (y< box[BOXBOTTOM]) - box[BOXBOTTOM] = y; - if (y> box[BOXTOP]) - box[BOXTOP] = y; + if (x < box[BOXLEFT]) box[BOXLEFT] = x; + if (x > box[BOXRIGHT]) box[BOXRIGHT] = x; + if (y < box[BOXBOTTOM]) box[BOXBOTTOM] = y; + if (y > box[BOXTOP]) box[BOXTOP] = y; } +/**************************************************************************** + * Name: r_setup_frame + ****************************************************************************/ -// -// R_PointOnSide -// Traverse BSP (sub) tree, -// check point against partition plane. -// Returns side 0 (front) or 1 (back). -// -int -R_PointOnSide -( fixed_t x, - fixed_t y, - node_t* node ) +static void r_setup_frame(player_t *player) { - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - if (!node->dx) - { - if (x <= node->x) - return node->dy > 0; - - return node->dy < 0; - } - if (!node->dy) - { - if (y <= node->y) - return node->dx < 0; - - return node->dx > 0; - } - - dx = (x - node->x); - dy = (y - node->y); - - // Try to quickly decide by looking at sign bits. - if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 ) - { - if ( (node->dy ^ dx) & 0x80000000 ) - { - // (left is negative) - return 1; - } - return 0; - } + int i; - left = FixedMul ( node->dy>>FRACBITS , dx ); - right = FixedMul ( dy , node->dx>>FRACBITS ); - - if (right < left) + viewplayer = player; + viewx = player->mo->x; + viewy = player->mo->y; + viewangle = player->mo->angle + viewangleoffset; + extralight = player->extralight; + + viewz = player->viewz; + + viewsin = finesine[viewangle >> ANGLETOFINESHIFT]; + viewcos = finecosine[viewangle >> ANGLETOFINESHIFT]; + + sscount = 0; + + if (player->fixedcolormap) { - // front side - return 0; + fixedcolormap = colormaps + player->fixedcolormap * 256; + + walllights = scalelightfixed; + + for (i = 0; i < MAXLIGHTSCALE; i++) + scalelightfixed[i] = fixedcolormap; } - // back side - return 1; + else + fixedcolormap = 0; + + framecount++; + validcount++; } +/**************************************************************************** + * Name: r_init_light_tables + * + * Description: + * Only inits the zlight table, because the scalelight table changes with + * view size. + * + ****************************************************************************/ -int -R_PointOnSegSide -( fixed_t x, - fixed_t y, - seg_t* line ) +static void r_init_light_tables(void) { - fixed_t lx; - fixed_t ly; - fixed_t ldx; - fixed_t ldy; - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - lx = line->v1->x; - ly = line->v1->y; - - ldx = line->v2->x - lx; - ldy = line->v2->y - ly; - - if (!ldx) - { - if (x <= lx) - return ldy > 0; - - return ldy < 0; - } - if (!ldy) + int i; + int j; + int level; + int startmap; + int scale; + + /* Calculate the light levels to use for each level / distance combination. + */ + + for (i = 0; i < LIGHTLEVELS; i++) { - if (y <= ly) - return ldx < 0; - - return ldx > 0; + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTZ; j++) + { + scale = fixed_div((SCREENWIDTH / 2 * FRACUNIT), + (j + 1) << LIGHTZSHIFT); + scale >>= LIGHTSCALESHIFT; + level = startmap - scale / DISTMAP; + + if (level < 0) level = 0; + + if (level >= NUMCOLORMAPS) level = NUMCOLORMAPS - 1; + + zlight[i][j] = colormaps + level * 256; + } } - - dx = (x - lx); - dy = (y - ly); - - // Try to quickly decide by looking at sign bits. - if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 ) +} + +/**************************************************************************** + * Name: r_init_tables + ****************************************************************************/ + +static void r_init_tables(void) +{ +#if 0 /* UNUSED: now getting from tables.c */ + int i; + float a; + float fv; + int t; + + /* viewangle tangent table */ + + for (i = 0; i < FINEANGLES / 2; i++) { - if ( (ldy ^ dx) & 0x80000000 ) - { - // (left is negative) - return 1; - } - return 0; + a = (i - FINEANGLES / 4 + 0.5) * PI * 2 / FINEANGLES; + fv = FRACUNIT * tan(a); + t = fv; + finetangent[i] = t; } - left = FixedMul ( ldy>>FRACBITS , dx ); - right = FixedMul ( dy , ldx>>FRACBITS ); - - if (right < left) + /* finesine table */ + + for (i = 0; i < 5 * FINEANGLES / 4; i++) { - // front side - return 0; + /* OPTIMIZE: mirror... */ + + a = (i + 0.5) * PI * 2 / FINEANGLES; + t = FRACUNIT * sin(a); + finesine[i] = t; } - // back side - return 1; +#endif } +/**************************************************************************** + * Name: r_init_point_to_angle + ****************************************************************************/ -// -// R_PointToAngle -// To get a global angle from cartesian coordinates, -// the coordinates are flipped until they are in -// the first octant of the coordinate system, then -// the y (<=x) is scaled and divided by x to get a -// tangent (slope) value which is looked up in the -// tantoangle[] table. +static void r_init_point_to_angle(void) +{ +#if 0 /* UNUSED - now getting from tables.c */ + int i; + long t; + float f; -// + /* slope (tangent) to angle lookup */ + for (i = 0; i <= SLOPERANGE; i++) + { + f = atan((float)i / SLOPERANGE) / (3.141592657 * 2); + t = 0xffffffff * f; + tantoangle[i] = t; + } +#endif +} +/**************************************************************************** + * Name: r_init_texture_mapping + ****************************************************************************/ +static void r_init_texture_mapping(void) +{ + int i; + int x; + int t; + fixed_t focallength; + + /* Use tangent table to generate viewangletox: + * viewangletox will give the next greatest x + * after the view angle. + * + * Calc focallength + * so FIELDOFVIEW angles covers SCREENWIDTH. + */ + + focallength = + fixed_div(centerxfrac, finetangent[FINEANGLES / 4 + FIELDOFVIEW / 2]); + + for (i = 0; i < FINEANGLES / 2; i++) + { + if (finetangent[i] > FRACUNIT * 2) + t = -1; + else if (finetangent[i] < -FRACUNIT * 2) + t = viewwidth + 1; + else + { + t = fixed_mul(finetangent[i], focallength); + t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS; + + if (t < -1) + t = -1; + else if (t > viewwidth + 1) + t = viewwidth + 1; + } + + viewangletox[i] = t; + } -angle_t -R_PointToAngle -( fixed_t x, - fixed_t y ) -{ - x -= viewx; - y -= viewy; - - if ( (!x) && (!y) ) - return 0; + /* Scan viewangletox[] to generate xtoviewangle[]: + * xtoviewangle will give the smallest view angle + * that maps to x. + */ - if (x>= 0) + for (x = 0; x <= viewwidth; x++) { - // x >=0 - if (y>= 0) - { - // y>= 0 - - if (x>y) - { - // octant 0 - return tantoangle[ SlopeDiv(y,x)]; - } - else - { - // octant 1 - return ANG90-1-tantoangle[ SlopeDiv(x,y)]; - } - } - else - { - // y<0 - y = -y; - - if (x>y) - { - // octant 8 - return -tantoangle[SlopeDiv(y,x)]; - } - else - { - // octant 7 - return ANG270+tantoangle[ SlopeDiv(x,y)]; - } - } + i = 0; + while (viewangletox[i] > x) + i++; + xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90; } - else + + /* Take out the fencepost cases from viewangletox. */ + + for (i = 0; i < FINEANGLES / 2; i++) { - // x<0 - x = -x; - - if (y>= 0) - { - // y>= 0 - if (x>y) - { - // octant 3 - return ANG180-1-tantoangle[ SlopeDiv(y,x)]; - } - else - { - // octant 2 - return ANG90+ tantoangle[ SlopeDiv(x,y)]; - } - } - else - { - // y<0 - y = -y; - - if (x>y) - { - // octant 4 - return ANG180+tantoangle[ SlopeDiv(y,x)]; - } - else - { - // octant 5 - return ANG270-1-tantoangle[ SlopeDiv(x,y)]; - } - } + t = fixed_mul(finetangent[i], focallength); + t = centerx - t; + + if (viewangletox[i] == -1) + viewangletox[i] = 0; + else if (viewangletox[i] == viewwidth + 1) + viewangletox[i] = viewwidth; } - return 0; + + clipangle = xtoviewangle[0]; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: r_point_on_side + * + * Description: + * Traverse BSP (sub) tree, check point against partition plane. + * + * Returns: + * Side 0 (front) or 1 (back). + ****************************************************************************/ + +int r_point_on_side(fixed_t x, fixed_t y, node_t *node) +{ + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; -angle_t -R_PointToAngle2 -( fixed_t x1, - fixed_t y1, - fixed_t x2, - fixed_t y2 ) -{ - viewx = x1; - viewy = y1; - - return R_PointToAngle (x2, y2); -} + if (!node->dx) + { + if (x <= node->x) return node->dy > 0; + return node->dy < 0; + } -fixed_t -R_PointToDist -( fixed_t x, - fixed_t y ) -{ - int angle; - fixed_t dx; - fixed_t dy; - fixed_t temp; - fixed_t dist; - fixed_t frac; - - dx = abs(x - viewx); - dy = abs(y - viewy); - - if (dy>dx) + if (!node->dy) { - temp = dx; - dx = dy; - dy = temp; + if (y <= node->y) return node->dx < 0; + + return node->dx > 0; } - // Fix crashes in udm1.wad + dx = (x - node->x); + dy = (y - node->y); - if (dx != 0) + /* Try to quickly decide by looking at sign bits. */ + + if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) { - frac = FixedDiv(dy, dx); + if ((node->dy ^ dx) & 0x80000000) + { + return 1; /* (left is negative) */ + } + + return 0; } - else + + left = fixed_mul(node->dy >> FRACBITS, dx); + right = fixed_mul(dy, node->dx >> FRACBITS); + + if (right < left) { - frac = 0; + return 0; /* front side */ } - - angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT; - // use as cosine - dist = FixedDiv (dx, finesine[angle] ); - - return dist; + return 1; /* back side */ } +/**************************************************************************** + * Name: r_point_on_seg_side + ****************************************************************************/ - - -// -// R_InitPointToAngle -// -void R_InitPointToAngle (void) +int r_point_on_seg_side(fixed_t x, fixed_t y, seg_t *line) { - // UNUSED - now getting from tables.c -#if 0 - int i; - long t; - float f; -// -// slope (tangent) to angle lookup -// - for (i=0 ; i<=SLOPERANGE ; i++) + fixed_t lx; + fixed_t ly; + fixed_t ldx; + fixed_t ldy; + fixed_t dx; + fixed_t dy; + fixed_t left; + fixed_t right; + + lx = line->v1->x; + ly = line->v1->y; + + ldx = line->v2->x - lx; + ldy = line->v2->y - ly; + + if (!ldx) { - f = atan( (float)i/SLOPERANGE )/(3.141592657*2); - t = 0xffffffff*f; - tantoangle[i] = t; + if (x <= lx) return ldy > 0; + + return ldy < 0; } -#endif -} + if (!ldy) + { + if (y <= ly) return ldx < 0; -// -// R_ScaleFromGlobalAngle -// Returns the texture mapping scale -// for the current line (horizontal span) -// at the given angle. -// rw_distance must be calculated first. -// -fixed_t R_ScaleFromGlobalAngle (angle_t visangle) -{ - fixed_t scale; - angle_t anglea; - angle_t angleb; - int sinea; - int sineb; - fixed_t num; - int den; - - // UNUSED -#if 0 -{ - fixed_t dist; - fixed_t z; - fixed_t sinv; - fixed_t cosv; - - sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; - dist = FixedDiv (rw_distance, sinv); - cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; - z = abs(FixedMul (dist, cosv)); - scale = FixedDiv(projection, z); - return scale; -} -#endif + return ldx > 0; + } - anglea = ANG90 + (visangle-viewangle); - angleb = ANG90 + (visangle-rw_normalangle); + dx = (x - lx); + dy = (y - ly); - // both sines are allways positive - sinea = finesine[anglea>>ANGLETOFINESHIFT]; - sineb = finesine[angleb>>ANGLETOFINESHIFT]; - num = FixedMul(projection,sineb)< num>>FRACBITS) + if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) { - scale = FixedDiv (num, den); + if ((ldy ^ dx) & 0x80000000) + { + return 1; /* (left is negative) */ + } - if (scale > 64*FRACUNIT) - scale = 64*FRACUNIT; - else if (scale < 256) - scale = 256; + return 0; } - else - scale = 64*FRACUNIT; - - return scale; -} + left = fixed_mul(ldy >> FRACBITS, dx); + right = fixed_mul(dy, ldx >> FRACBITS); + + if (right < left) + { + return 0; /* front side */ + } + return 1; /* back side */ +} -// -// R_InitTables -// -void R_InitTables (void) +/**************************************************************************** + * Name: r_point_to_angle + * + * Description: + * To get a global angle from cartesian coordinates, the coordinates are + * flipped until they are in the first octant of the coordinate system, then + * the y (<=x) is scaled and divided by x to get a tangent (slope) value + * which is looked up in the tantoangle[] table. + * + ****************************************************************************/ + +angle_t r_point_to_angle(fixed_t x, fixed_t y) { - // UNUSED: now getting from tables.c -#if 0 - int i; - float a; - float fv; - int t; - - // viewangle tangent table - for (i=0 ; i= 0) { - a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES; - fv = FRACUNIT*tan (a); - t = fv; - finetangent[i] = t; + /* x >=0 */ + + if (y >= 0) + { + /* y>= 0 */ + + if (x > y) + { + return tantoangle[slope_div(y, x)]; /* octant 0 */ + } + else + { + return ANG90 - 1 - tantoangle[slope_div(x, y)]; /* octant 1 */ + } + } + else + { + /* y<0 */ + + y = -y; + + if (x > y) + { + return -tantoangle[slope_div(y, x)]; /* octant 8 */ + } + else + { + return ANG270 + tantoangle[slope_div(x, y)]; /* octant 7 */ + } + } } - - // finesine table - for (i=0 ; i<5*FINEANGLES/4 ; i++) + else { - // OPTIMIZE: mirror... - a = (i+0.5)*PI*2/FINEANGLES; - t = FRACUNIT*sin (a); - finesine[i] = t; + /* x<0 */ + + x = -x; + + if (y >= 0) + { + /* y>= 0 */ + + if (x > y) + { + return ANG180 - 1 - tantoangle[slope_div(y, x)]; /* octant 3 */ + } + else + { + return ANG90 + tantoangle[slope_div(x, y)]; /* octant 2 */ + } + } + else + { + y = -y; /* y<0 */ + + if (x > y) + { + return ANG180 + tantoangle[slope_div(y, x)]; /* octant 4 */ + } + else + { + return ANG270 - 1 - tantoangle[slope_div(x, y)]; /* octant 5 */ + } + } } -#endif + return 0; } +/**************************************************************************** + * Name: r_point_to_angle2 + ****************************************************************************/ +angle_t r_point_to_angle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) +{ + viewx = x1; + viewy = y1; -// -// R_InitTextureMapping -// -void R_InitTextureMapping (void) + return r_point_to_angle(x2, y2); +} + +/**************************************************************************** + * Name: r_point_to_dist + ****************************************************************************/ + +fixed_t r_point_to_dist(fixed_t x, fixed_t y) { - int i; - int x; - int t; - fixed_t focallength; - - // Use tangent table to generate viewangletox: - // viewangletox will give the next greatest x - // after the view angle. - // - // Calc focallength - // so FIELDOFVIEW angles covers SCREENWIDTH. - focallength = FixedDiv (centerxfrac, - finetangent[FINEANGLES/4+FIELDOFVIEW/2] ); - - for (i=0 ; i dx) { - if (finetangent[i] > FRACUNIT*2) - t = -1; - else if (finetangent[i] < -FRACUNIT*2) - t = viewwidth+1; - else - { - t = FixedMul (finetangent[i], focallength); - t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS; - - if (t < -1) - t = -1; - else if (t>viewwidth+1) - t = viewwidth+1; - } - viewangletox[i] = t; + temp = dx; + dx = dy; + dy = temp; } - - // Scan viewangletox[] to generate xtoviewangle[]: - // xtoviewangle will give the smallest view angle - // that maps to x. - for (x=0;x<=viewwidth;x++) + + /* Fix crashes in udm1.wad */ + + if (dx != 0) { - i = 0; - while (viewangletox[i]>x) - i++; - xtoviewangle[x] = (i<> DBITS] + ANG90) >> ANGLETOFINESHIFT; + dist = fixed_div(dx, finesine[angle]); /* use as cosine */ -// -// R_InitLightTables -// Only inits the zlight table, -// because the scalelight table changes with view size. -// -#define DISTMAP 2 + return dist; +} -void R_InitLightTables (void) +/**************************************************************************** + * Name: r_scale_from_global_angle + * + * Description: + * Returns the texture mapping scale for the current line (horizontal span) + * at the given angle. rw_distance must be calculated first. + * + ****************************************************************************/ + +fixed_t r_scale_from_global_angle(angle_t visangle) { - int i; - int j; - int level; - int startmap; - int scale; - - // Calculate the light levels to use - // for each level / distance combination. - for (i=0 ; i< LIGHTLEVELS ; i++) - { - startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; - for (j=0 ; j>= LIGHTSCALESHIFT; - level = startmap - scale/DISTMAP; - - if (level < 0) - level = 0; - - if (level >= NUMCOLORMAPS) - level = NUMCOLORMAPS-1; - - zlight[i][j] = colormaps + level*256; - } - } -} + fixed_t scale; + angle_t anglea; + angle_t angleb; + int sinea; + int sineb; + fixed_t num; + int den; + +#if 0 /* UNUSED */ + fixed_t dist; + fixed_t z; + fixed_t sinv; + fixed_t cosv; + + sinv = finesine[(visangle - rw_normalangle) >> ANGLETOFINESHIFT]; + dist = fixed_div(rw_distance, sinv); + cosv = finecosine[(viewangle - visangle) >> ANGLETOFINESHIFT]; + z = abs(fixed_mul(dist, cosv)); + scale = fixed_div(projection, z); + return scale; +#endif + + anglea = ANG90 + (visangle - viewangle); + angleb = ANG90 + (visangle - rw_normalangle); + + /* both sines are always positive */ + + sinea = finesine[anglea >> ANGLETOFINESHIFT]; + sineb = finesine[angleb >> ANGLETOFINESHIFT]; + num = fixed_mul(projection, sineb) << detailshift; + den = fixed_mul(rw_distance, sinea); + if (den > num >> FRACBITS) + { + scale = fixed_div(num, den); + if (scale > 64 * FRACUNIT) + scale = 64 * FRACUNIT; + else if (scale < 256) + scale = 256; + } + else + scale = 64 * FRACUNIT; -// -// R_SetViewSize -// Do not really change anything here, -// because it might be in the middle of a refresh. -// The change will take effect next refresh. -// -boolean setsizeneeded; -int setblocks; -int setdetail; + return scale; +} +/**************************************************************************** + * Name: r_set_view_size + * + * Description: + * Do not really change anything here, because it might be in the middle + * of a refresh. The change will take effect next refresh. + * + ****************************************************************************/ -void -R_SetViewSize -( int blocks, - int detail ) +void r_set_view_size(int blocks, int detail) { - setsizeneeded = true; - setblocks = blocks; - setdetail = detail; + setsizeneeded = true; + setblocks = blocks; + setdetail = detail; } +/**************************************************************************** + * Name: r_execute_set_view_size + ****************************************************************************/ -// -// R_ExecuteSetViewSize -// -void R_ExecuteSetViewSize (void) +void r_execute_set_view_size(void) { - fixed_t cosadj; - fixed_t dy; - int i; - int j; - int level; - int startmap; + fixed_t cosadj; + fixed_t dy; + int i; + int j; + int level; + int startmap; - setsizeneeded = false; + setsizeneeded = false; - if (setblocks == 11) + if (setblocks == 11) { - scaledviewwidth = SCREENWIDTH; - viewheight = SCREENHEIGHT; + scaledviewwidth = SCREENWIDTH; + viewheight = SCREENHEIGHT; } - else + else { - scaledviewwidth = setblocks*32; - viewheight = (setblocks*168/10)&~7; + scaledviewwidth = setblocks * 32; + viewheight = (setblocks * 168 / 10) & ~7; } - - detailshift = setdetail; - viewwidth = scaledviewwidth>>detailshift; - - centery = viewheight/2; - centerx = viewwidth/2; - centerxfrac = centerx<> detailshift; + + centery = viewheight / 2; + centerx = viewwidth / 2; + centerxfrac = centerx << FRACBITS; + centeryfrac = centery << FRACBITS; + projection = centerxfrac; + + if (!detailshift) { - colfunc = basecolfunc = R_DrawColumn; - fuzzcolfunc = R_DrawFuzzColumn; - transcolfunc = R_DrawTranslatedColumn; - spanfunc = R_DrawSpan; + colfunc = basecolfunc = r_draw_column; + fuzzcolfunc = r_draw_fuzz_column; + transcolfunc = r_draw_translated_column; + spanfunc = r_draw_span; } - else + else { - colfunc = basecolfunc = R_DrawColumnLow; - fuzzcolfunc = R_DrawFuzzColumnLow; - transcolfunc = R_DrawTranslatedColumnLow; - spanfunc = R_DrawSpanLow; + colfunc = basecolfunc = r_draw_column_low; + fuzzcolfunc = r_draw_fuzz_column_low; + transcolfunc = r_draw_translated_column_low; + spanfunc = r_draw_span_low; } - R_InitBuffer (scaledviewwidth, viewheight); - - R_InitTextureMapping (); - - // psprite scales - pspritescale = FRACUNIT*viewwidth/SCREENWIDTH; - pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth; - - // thing clipping - for (i=0 ; i>ANGLETOFINESHIFT]); - distscale[i] = FixedDiv (FRACUNIT,cosadj); + dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; + dy = abs(dy); + yslope[i] = fixed_div((viewwidth << detailshift) / 2 * FRACUNIT, dy); } - - // Calculate the light levels to use - // for each level / scale combination. - for (i=0 ; i< LIGHTLEVELS ; i++) + + for (i = 0; i < viewwidth; i++) { - startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; - for (j=0 ; j= NUMCOLORMAPS) - level = NUMCOLORMAPS-1; - - scalelight[i][j] = colormaps + level*256; - } + cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); + distscale[i] = fixed_div(FRACUNIT, cosadj); } -} + /* Calculate the light levels to use for each level / scale combination. */ + for (i = 0; i < LIGHTLEVELS; i++) + { + startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; + for (j = 0; j < MAXLIGHTSCALE; j++) + { + level = startmap - + j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP; + + if (level < 0) level = 0; -// -// R_Init -// + if (level >= NUMCOLORMAPS) level = NUMCOLORMAPS - 1; + scalelight[i][j] = colormaps + level * 256; + } + } +} +/**************************************************************************** + * Name: r_init + ****************************************************************************/ -void R_Init (void) +void r_init(void) { - R_InitData (); - printf ("."); - R_InitPointToAngle (); - printf ("."); - R_InitTables (); - // viewwidth / viewheight / detailLevel are set by the defaults - printf ("."); - - R_SetViewSize (screenblocks, detailLevel); - R_InitPlanes (); - printf ("."); - R_InitLightTables (); - printf ("."); - R_InitSkyMap (); - R_InitTranslationTables (); - printf ("."); - - framecount = 0; + r_init_data(); + printf("."); + r_init_point_to_angle(); + printf("."); + r_init_tables(); + + /* viewwidth / viewheight / g_detail_level are set by the defaults */ + + printf("."); + + r_set_view_size(screenblocks, g_detail_level); + r_init_planes(); + printf("."); + r_init_light_tables(); + printf("."); + r_init_sky_map(); + r_init_translation_table(); + printf("."); + + framecount = 0; } +/**************************************************************************** + * Name: r_point_in_subsector + ****************************************************************************/ -// -// R_PointInSubsector -// -subsector_t* -R_PointInSubsector -( fixed_t x, - fixed_t y ) +subsector_t *r_point_in_subsector(fixed_t x, fixed_t y) { - node_t* node; - int side; - int nodenum; + node_t *node; + int side; + int nodenum; - // single subsector is a special case - if (!numnodes) - return subsectors; - - nodenum = numnodes-1; + /* single subsector is a special case */ - while (! (nodenum & NF_SUBSECTOR) ) + if (!numnodes) return subsectors; + + nodenum = numnodes - 1; + + while (!(nodenum & NF_SUBSECTOR)) { - node = &nodes[nodenum]; - side = R_PointOnSide (x, y, node); - nodenum = node->children[side]; + node = &nodes[nodenum]; + side = r_point_on_side(x, y, node); + nodenum = node->children[side]; } - - return &subsectors[nodenum & ~NF_SUBSECTOR]; + + return &subsectors[nodenum & ~NF_SUBSECTOR]; } +/**************************************************************************** + * Name: r_render_player_view + ****************************************************************************/ +void r_render_player_view(player_t *player) +{ + r_setup_frame(player); -// -// R_SetupFrame -// -void R_SetupFrame (player_t* player) -{ - int i; - - viewplayer = player; - viewx = player->mo->x; - viewy = player->mo->y; - viewangle = player->mo->angle + viewangleoffset; - extralight = player->extralight; - - viewz = player->viewz; - - viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; - viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; - - sscount = 0; - - if (player->fixedcolormap) - { - fixedcolormap = - colormaps - + player->fixedcolormap*256; - - walllights = scalelightfixed; - - for (i=0 ; i #include #include "i_system.h" -#include "z_zone.h" #include "w_wad.h" +#include "z_zone.h" #include "doomdef.h" #include "doomstat.h" @@ -32,418 +40,378 @@ #include "r_local.h" #include "r_sky.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define MAXOPENINGS (SCREENWIDTH * CONFIG_GAMES_NXDOOM_MAXOPENINGS) -planefunction_t floorfunc; -planefunction_t ceilingfunc; +/**************************************************************************** + * Public Data + ****************************************************************************/ -// -// opening -// +planefunction_t floorfunc; +planefunction_t ceilingfunc; -// Here comes the obnoxious "visplane". -#define MAXVISPLANES 128 -visplane_t visplanes[MAXVISPLANES]; -visplane_t* lastvisplane; -visplane_t* floorplane; -visplane_t* ceilingplane; +/* opening */ -// ? -#define MAXOPENINGS SCREENWIDTH*64 -short openings[MAXOPENINGS]; -short* lastopening; +/* Here comes the obnoxious "visplane". */ +visplane_t visplanes[CONFIG_GAMES_NXDOOM_MAXVISPLANES]; +visplane_t *lastvisplane; +visplane_t *floorplane; +visplane_t *ceilingplane; -// -// Clip values are the solid pixel bounding the range. -// floorclip starts out SCREENHEIGHT -// ceilingclip starts out -1 -// -short floorclip[SCREENWIDTH]; -short ceilingclip[SCREENWIDTH]; +short openings[MAXOPENINGS]; +short *lastopening; -// -// spanstart holds the start of a plane span -// initialized to 0 at start -// -int spanstart[SCREENHEIGHT]; -int spanstop[SCREENHEIGHT]; +/* Clip values are the solid pixel bounding the range. floorclip starts out + * SCREENHEIGHT ceilingclip starts out -1 + */ -// -// texture mapping -// -lighttable_t** planezlight; -fixed_t planeheight; +short floorclip[SCREENWIDTH]; +short ceilingclip[SCREENWIDTH]; -fixed_t yslope[SCREENHEIGHT]; -fixed_t distscale[SCREENWIDTH]; -fixed_t basexscale; -fixed_t baseyscale; +/* spanstart holds the start of a plane span initialized to 0 at start */ -fixed_t cachedheight[SCREENHEIGHT]; -fixed_t cacheddistance[SCREENHEIGHT]; -fixed_t cachedxstep[SCREENHEIGHT]; -fixed_t cachedystep[SCREENHEIGHT]; +int spanstart[SCREENHEIGHT]; +int spanstop[SCREENHEIGHT]; +/* texture mapping */ +lighttable_t **planezlight; +fixed_t planeheight; -// -// R_InitPlanes -// Only at game startup. -// -void R_InitPlanes (void) -{ - // Doh! -} +fixed_t yslope[SCREENHEIGHT]; +fixed_t distscale[SCREENWIDTH]; +fixed_t basexscale; +fixed_t baseyscale; +fixed_t cachedheight[SCREENHEIGHT]; +fixed_t cacheddistance[SCREENHEIGHT]; +fixed_t cachedxstep[SCREENHEIGHT]; +fixed_t cachedystep[SCREENHEIGHT]; -// -// R_MapPlane -// -// Uses global vars: -// planeheight -// ds_source -// basexscale -// baseyscale -// viewx -// viewy -// -// BASIC PRIMITIVE -// -void -R_MapPlane -( int y, - int x1, - int x2 ) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Uses global vars: + * planeheight + * ds_source + * basexscale + * baseyscale + * viewx + * viewy + * + * BASIC PRIMITIVE + */ + +static void r_map_plane(int y, int x1, int x2) { - angle_t angle; - fixed_t distance; - fixed_t length; - unsigned index; - -#ifdef RANGECHECK - if (x2 < x1 - || x1 < 0 - || x2 >= viewwidth - || y > viewheight) + angle_t angle; + fixed_t distance; + fixed_t length; + unsigned index; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) { - I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); + i_error("R_MapPlane: %i, %i at %i", x1, x2, y); } #endif - if (planeheight != cachedheight[y]) + if (planeheight != cachedheight[y]) { - cachedheight[y] = planeheight; - distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]); - ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale); - ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale); + cachedheight[y] = planeheight; + distance = cacheddistance[y] = fixed_mul(planeheight, yslope[y]); + ds_xstep = cachedxstep[y] = fixed_mul(distance, basexscale); + ds_ystep = cachedystep[y] = fixed_mul(distance, baseyscale); } - else + else { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; } - - length = FixedMul (distance,distscale[x1]); - angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; - ds_xfrac = viewx + FixedMul(finecosine[angle], length); - ds_yfrac = -viewy - FixedMul(finesine[angle], length); - - if (fixedcolormap) - ds_colormap = fixedcolormap; - else + + length = fixed_mul(distance, distscale[x1]); + angle = (viewangle + xtoviewangle[x1]) >> ANGLETOFINESHIFT; + ds_xfrac = viewx + fixed_mul(finecosine[angle], length); + ds_yfrac = -viewy - fixed_mul(finesine[angle], length); + + if (fixedcolormap) + ds_colormap = fixedcolormap; + else { - index = distance >> LIGHTZSHIFT; - - if (index >= MAXLIGHTZ ) - index = MAXLIGHTZ-1; + index = distance >> LIGHTZSHIFT; - ds_colormap = planezlight[index]; + if (index >= MAXLIGHTZ) index = MAXLIGHTZ - 1; + + ds_colormap = planezlight[index]; } - - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; - // high or low detail - spanfunc (); -} + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + /* high or low detail */ -// -// R_ClearPlanes -// At begining of frame. -// -void R_ClearPlanes (void) + spanfunc(); +} + +static void r_make_spans(int x, int t1, int b1, int t2, int b2) { - int i; - angle_t angle; - - // opening / clipping determination - for (i=0 ; i b2 && b1 >= t1) { - floorclip[i] = viewheight; - ceilingclip[i] = -1; + r_map_plane(b1, spanstart[b1], x - 1); + b1--; } - lastvisplane = visplanes; - lastopening = openings; - - // texture calculation - memset (cachedheight, 0, sizeof(cachedheight)); - - // left to right mapping - angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; - - // scale will be unit scale at SCREENWIDTH/2 distance - basexscale = FixedDiv (finecosine[angle],centerxfrac); - baseyscale = -FixedDiv (finesine[angle],centerxfrac); + while (t2 < t1 && t2 <= b2) + { + spanstart[t2] = x; + t2++; + } + while (b2 > b1 && b2 >= t2) + { + spanstart[b2] = x; + b2--; + } } +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/* r_init_planes + * Only at game startup. + */ - -// -// R_FindPlane -// -visplane_t* -R_FindPlane -( fixed_t height, - int picnum, - int lightlevel ) +void r_init_planes(void) { - visplane_t* check; - - if (picnum == skyflatnum) - { - height = 0; // all skys map together - lightlevel = 0; - } - - for (check=visplanes; checkheight - && picnum == check->picnum - && lightlevel == check->lightlevel) - { - break; - } - } - - - if (check < lastvisplane) - return check; - - if (lastvisplane - visplanes == MAXVISPLANES) - I_Error ("R_FindPlane: no more visplanes"); - - lastvisplane++; - - check->height = height; - check->picnum = picnum; - check->lightlevel = lightlevel; - check->minx = SCREENWIDTH; - check->maxx = -1; - - memset (check->top,0xff,sizeof(check->top)); - - return check; + /* Doh! */ } +/* r_clear_planes + * At beginning of frame. + */ -// -// R_CheckPlane -// -visplane_t* -R_CheckPlane -( visplane_t* pl, - int start, - int stop ) +void r_clear_planes(void) { - int intrl; - int intrh; - int unionl; - int unionh; - int x; - - if (start < pl->minx) - { - intrl = pl->minx; - unionl = start; - } - else + int i; + angle_t angle; + + /* opening / clipping determination */ + + for (i = 0; i < viewwidth; i++) { - unionl = pl->minx; - intrl = start; + floorclip[i] = viewheight; + ceilingclip[i] = -1; } - - if (stop > pl->maxx) + + lastvisplane = visplanes; + lastopening = openings; + + /* texture calculation */ + + memset(cachedheight, 0, sizeof(cachedheight)); + + /* left to right mapping */ + + angle = (viewangle - ANG90) >> ANGLETOFINESHIFT; + + /* scale will be unit scale at SCREENWIDTH/2 distance */ + + basexscale = fixed_div(finecosine[angle], centerxfrac); + baseyscale = -fixed_div(finesine[angle], centerxfrac); +} + +visplane_t *r_find_plane(fixed_t height, int picnum, int lightlevel) +{ + visplane_t *check; + + if (picnum == skyflatnum) { - intrh = pl->maxx; - unionh = stop; + height = 0; /* all skys map together */ + lightlevel = 0; } - else + + for (check = visplanes; check < lastvisplane; check++) { - unionh = pl->maxx; - intrh = stop; + if (height == check->height && picnum == check->picnum && + lightlevel == check->lightlevel) + { + break; + } } - for (x=intrl ; x<= intrh ; x++) - if (pl->top[x] != 0xff) - break; + if (check < lastvisplane) return check; - if (x > intrh) - { - pl->minx = unionl; - pl->maxx = unionh; + if (lastvisplane - visplanes == CONFIG_GAMES_NXDOOM_MAXVISPLANES) + i_error("r_find_plane: no more visplanes"); - // use the same one - return pl; - } - - // make a new visplane - lastvisplane->height = pl->height; - lastvisplane->picnum = pl->picnum; - lastvisplane->lightlevel = pl->lightlevel; - - if (lastvisplane - visplanes == MAXVISPLANES) - I_Error ("R_CheckPlane: no more visplanes"); - - pl = lastvisplane++; - pl->minx = start; - pl->maxx = stop; - - memset (pl->top,0xff,sizeof(pl->top)); - - return pl; -} + lastvisplane++; + + check->height = height; + check->picnum = picnum; + check->lightlevel = lightlevel; + check->minx = SCREENWIDTH; + check->maxx = -1; + memset(check->top, 0xff, sizeof(check->top)); -// -// R_MakeSpans -// -void -R_MakeSpans -( int x, - int t1, - int b1, - int t2, - int b2 ) + return check; +} + +visplane_t *r_check_plane(visplane_t *pl, int start, int stop) { - while (t1 < t2 && t1<=b1) + int intrl; + int intrh; + int unionl; + int unionh; + int x; + + if (start < pl->minx) { - R_MapPlane (t1,spanstart[t1],x-1); - t1++; + intrl = pl->minx; + unionl = start; } - while (b1 > b2 && b1>=t1) + else { - R_MapPlane (b1,spanstart[b1],x-1); - b1--; + unionl = pl->minx; + intrl = start; } - - while (t2 < t1 && t2<=b2) + + if (stop > pl->maxx) { - spanstart[t2] = x; - t2++; + intrh = pl->maxx; + unionh = stop; } - while (b2 > b1 && b2>=t2) + else { - spanstart[b2] = x; - b2--; + unionh = pl->maxx; + intrh = stop; } -} + for (x = intrl; x <= intrh; x++) + { + if (pl->top[x] != 0xff) break; + } + + if (x > intrh) + { + pl->minx = unionl; + pl->maxx = unionh; + + return pl; /* use the same one */ + } + + /* make a new visplane */ + + lastvisplane->height = pl->height; + lastvisplane->picnum = pl->picnum; + lastvisplane->lightlevel = pl->lightlevel; + + if (lastvisplane - visplanes == CONFIG_GAMES_NXDOOM_MAXVISPLANES) + i_error("r_check_plane: no more visplanes"); + + pl = lastvisplane++; + pl->minx = start; + pl->maxx = stop; + memset(pl->top, 0xff, sizeof(pl->top)); -// -// R_DrawPlanes -// At the end of each frame. -// -void R_DrawPlanes (void) + return pl; +} + +/* At the end of each frame. */ + +void r_draw_planes(void) { - visplane_t* pl; - int light; - int x; - int stop; - int angle; - int lumpnum; - -#ifdef RANGECHECK - if (ds_p - drawsegs > MAXDRAWSEGS) - I_Error ("R_DrawPlanes: drawsegs overflow (%td)", - ds_p - drawsegs); - - if (lastvisplane - visplanes > MAXVISPLANES) - I_Error ("R_DrawPlanes: visplane overflow (%td)", - lastvisplane - visplanes); - - if (lastopening - openings > MAXOPENINGS) - I_Error ("R_DrawPlanes: opening overflow (%td)", - lastopening - openings); + visplane_t *pl; + int light; + int x; + int stop; + int angle; + int lumpnum; + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (ds_p - drawsegs > CONFIG_GAMES_NXDOOM_MAXDRAWSEGS) + i_error("r_draw_planes: drawsegs overflow (%td)", ds_p - drawsegs); + + if (lastvisplane - visplanes > CONFIG_GAMES_NXDOOM_MAXVISPLANES) + i_error("r_draw_planes: visplane overflow (%td)", + lastvisplane - visplanes); + + if (lastopening - openings > MAXOPENINGS) + i_error("r_draw_planes: opening overflow (%td)", lastopening - openings); #endif - for (pl = visplanes ; pl < lastvisplane ; pl++) + for (pl = visplanes; pl < lastvisplane; pl++) { - if (pl->minx > pl->maxx) - continue; - - - // sky flat - if (pl->picnum == skyflatnum) - { - dc_iscale = pspriteiscale>>detailshift; - - // Sky is allways drawn full bright, - // i.e. colormaps[0] is used. - // Because of this hack, sky is not affected - // by INVUL inverse mapping. - dc_colormap = colormaps; - dc_texturemid = skytexturemid; - for (x=pl->minx ; x <= pl->maxx ; x++) - { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; - - if (dc_yl <= dc_yh) - { - angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; - dc_x = x; - dc_source = R_GetColumn(skytexture, angle); - colfunc (); - } - } - continue; - } - - // regular flat - lumpnum = firstflat + flattranslation[pl->picnum]; - ds_source = W_CacheLumpNum(lumpnum, PU_STATIC); - - planeheight = abs(pl->height-viewz); - light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (light >= LIGHTLEVELS) - light = LIGHTLEVELS-1; - - if (light < 0) - light = 0; - - planezlight = zlight[light]; - - pl->top[pl->maxx+1] = 0xff; - pl->top[pl->minx-1] = 0xff; - - stop = pl->maxx + 1; - - for (x=pl->minx ; x<= stop ; x++) - { - R_MakeSpans(x,pl->top[x-1], - pl->bottom[x-1], - pl->top[x], - pl->bottom[x]); - } - - W_ReleaseLumpNum(lumpnum); + if (pl->minx > pl->maxx) continue; + + /* sky flat */ + + if (pl->picnum == skyflatnum) + { + dc_iscale = pspriteiscale >> detailshift; + + /* Sky is always drawn full bright, i.e. colormaps[0] is used. + * Because of this hack, sky is not affected by INVUL inverse + * mapping. + */ + + dc_colormap = colormaps; + dc_texturemid = skytexturemid; + for (x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + + if (dc_yl <= dc_yh) + { + angle = (viewangle + xtoviewangle[x]) >> ANGLETOSKYSHIFT; + dc_x = x; + dc_source = r_get_column(skytexture, angle); + colfunc(); + } + } + + continue; + } + + /* regular flat */ + + lumpnum = firstflat + flattranslation[pl->picnum]; + ds_source = w_cache_lump_num(lumpnum, PU_STATIC); + + planeheight = abs(pl->height - viewz); + light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; + + if (light >= LIGHTLEVELS) light = LIGHTLEVELS - 1; + + if (light < 0) light = 0; + + planezlight = zlight[light]; + + pl->top[pl->maxx + 1] = 0xff; + pl->top[pl->minx - 1] = 0xff; + + stop = pl->maxx + 1; + + for (x = pl->minx; x <= stop; x++) + { + r_make_spans(x, pl->top[x - 1], pl->bottom[x - 1], pl->top[x], + pl->bottom[x]); + } + + w_release_lump_num(lumpnum); } } diff --git a/games/NXDoom/src/doom/r_plane.h b/games/NXDoom/src/doom/r_plane.h index 57b50e5bc5e..1ae3b79254b 100644 --- a/games/NXDoom/src/doom/r_plane.h +++ b/games/NXDoom/src/doom/r_plane.h @@ -1,76 +1,69 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh, visplane stuff (floor, ceilings). -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_plane.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh, visplane stuff (floor, ceilings). + * + ****************************************************************************/ #ifndef __R_PLANE__ #define __R_PLANE__ +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "r_data.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ +typedef void (*planefunction_t)(int top, int bottom); -// Visplane related. -extern short* lastopening; - - -typedef void (*planefunction_t) (int top, int bottom); - -extern planefunction_t floorfunc; -extern planefunction_t ceilingfunc_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ -extern short floorclip[SCREENWIDTH]; -extern short ceilingclip[SCREENWIDTH]; +/* Visplane related. */ -extern fixed_t yslope[SCREENHEIGHT]; -extern fixed_t distscale[SCREENWIDTH]; +extern short *lastopening; -void R_InitPlanes (void); -void R_ClearPlanes (void); +extern planefunction_t floorfunc; +extern planefunction_t ceilingfunc_t; -void -R_MapPlane -( int y, - int x1, - int x2 ); +extern short floorclip[SCREENWIDTH]; +extern short ceilingclip[SCREENWIDTH]; -void -R_MakeSpans -( int x, - int t1, - int b1, - int t2, - int b2 ); +extern fixed_t yslope[SCREENHEIGHT]; +extern fixed_t distscale[SCREENWIDTH]; -void R_DrawPlanes (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -visplane_t* -R_FindPlane -( fixed_t height, - int picnum, - int lightlevel ); +void r_init_planes(void); +void r_clear_planes(void); -visplane_t* -R_CheckPlane -( visplane_t* pl, - int start, - int stop ); +void r_draw_planes(void); +visplane_t *r_find_plane(fixed_t height, int picnum, int lightlevel); +visplane_t *r_check_plane(visplane_t *pl, int start, int stop); -#endif +#endif /* __R_PLANE__ */ diff --git a/games/NXDoom/src/doom/r_segs.c b/games/NXDoom/src/doom/r_segs.c index 06881a52072..83d9b026f45 100644 --- a/games/NXDoom/src/doom/r_segs.c +++ b/games/NXDoom/src/doom/r_segs.c @@ -1,25 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// All the clipping: columns, horizontal spans, sky columns. -// - - - - - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_segs.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * All the clipping: columns, horizontal spans, sky columns. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -32,712 +36,752 @@ #include "r_local.h" #include "r_sky.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define HEIGHTBITS 12 +#define HEIGHTUNIT (1 << HEIGHTBITS) + +/**************************************************************************** + * Public Data + ****************************************************************************/ -// OPTIMIZE: closed two sided lines as single sided +/* OPTIMIZE: closed two sided lines as single sided */ -// True if any of the segs textures might be visible. -boolean segtextured; +/* True if any of the segs textures might be visible. */ -// False if the back side is the same plane. -boolean markfloor; -boolean markceiling; +boolean segtextured; -boolean maskedtexture; -int toptexture; -int bottomtexture; -int midtexture; +/* False if the back side is the same plane. */ +boolean markfloor; +boolean markceiling; -angle_t rw_normalangle; -// angle to line origin -int rw_angle1; +boolean maskedtexture; +int toptexture; +int bottomtexture; +int midtexture; -// -// regular wall -// -int rw_x; -int rw_stopx; -angle_t rw_centerangle; -fixed_t rw_offset; -fixed_t rw_distance; -fixed_t rw_scale; -fixed_t rw_scalestep; -fixed_t rw_midtexturemid; -fixed_t rw_toptexturemid; -fixed_t rw_bottomtexturemid; +angle_t rw_normalangle; -int worldtop; -int worldbottom; -int worldhigh; -int worldlow; +/* angle to line origin */ -fixed_t pixhigh; -fixed_t pixlow; -fixed_t pixhighstep; -fixed_t pixlowstep; +int rw_angle1; -fixed_t topfrac; -fixed_t topstep; +/* regular wall */ -fixed_t bottomfrac; -fixed_t bottomstep; +int rw_x; +int rw_stopx; +angle_t rw_centerangle; +fixed_t rw_offset; +fixed_t rw_distance; +fixed_t rw_scale; +fixed_t rw_scalestep; +fixed_t rw_midtexturemid; +fixed_t rw_toptexturemid; +fixed_t rw_bottomtexturemid; +int worldtop; +int worldbottom; +int worldhigh; +int worldlow; -lighttable_t** walllights; +fixed_t pixhigh; +fixed_t pixlow; +fixed_t pixhighstep; +fixed_t pixlowstep; -short* maskedtexturecol; +fixed_t topfrac; +fixed_t topstep; +fixed_t bottomfrac; +fixed_t bottomstep; +lighttable_t **walllights; -// -// R_RenderMaskedSegRange -// -void -R_RenderMaskedSegRange -( drawseg_t* ds, - int x1, - int x2 ) +short *maskedtexturecol; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Draws zero, one, or two textures (and possibly a masked texture) for + * walls. + * + * Can draw or mark the starting pixel of floor and ceiling textures. + * CALLED: CORE LOOPING ROUTINE. + */ + +static void r_render_seg_loop(void) { - unsigned index; - column_t* col; - int lightnum; - int texnum; - - // Calculate light table. - // Use different light tables - // for horizontal / vertical / diagonal. Diagonal? - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; - frontsector = curline->frontsector; - backsector = curline->backsector; - texnum = texturetranslation[curline->sidedef->midtexture]; - - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS-1]; - else - walllights = scalelight[lightnum]; - - maskedtexturecol = ds->maskedtexturecol; - - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; - - // find positioning - if (curline->linedef->flags & ML_DONTPEGBOTTOM) + angle_t angle; + unsigned index; + int yl; + int yh; + int mid; + fixed_t texturecolumn; + int top; + int bottom; + + for (; rw_x < rw_stopx; rw_x++) { - dc_texturemid = frontsector->floorheight > backsector->floorheight - ? frontsector->floorheight : backsector->floorheight; - dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; + /* mark floor / ceiling areas */ + + yl = (topfrac + HEIGHTUNIT - 1) >> HEIGHTBITS; + + /* no space above wall? */ + + if (yl < ceilingclip[rw_x] + 1) yl = ceilingclip[rw_x] + 1; + + if (markceiling) + { + top = ceilingclip[rw_x] + 1; + bottom = yl - 1; + + if (bottom >= floorclip[rw_x]) bottom = floorclip[rw_x] - 1; + + if (top <= bottom) + { + ceilingplane->top[rw_x] = top; + ceilingplane->bottom[rw_x] = bottom; + } + } + + yh = bottomfrac >> HEIGHTBITS; + + if (yh >= floorclip[rw_x]) yh = floorclip[rw_x] - 1; + + if (markfloor) + { + top = yh + 1; + bottom = floorclip[rw_x] - 1; + if (top <= ceilingclip[rw_x]) top = ceilingclip[rw_x] + 1; + if (top <= bottom) + { + floorplane->top[rw_x] = top; + floorplane->bottom[rw_x] = bottom; + } + } + + /* texturecolumn and lighting are independent of wall tiers */ + + if (segtextured) + { + /* calculate texture offset */ + + angle = (rw_centerangle + xtoviewangle[rw_x]) >> ANGLETOFINESHIFT; + texturecolumn = + rw_offset - fixed_mul(finetangent[angle], rw_distance); + texturecolumn >>= FRACBITS; + + /* calculate lighting */ + + index = rw_scale >> LIGHTSCALESHIFT; + + if (index >= MAXLIGHTSCALE) index = MAXLIGHTSCALE - 1; + + dc_colormap = walllights[index]; + dc_x = rw_x; + dc_iscale = 0xffffffffu / (unsigned)rw_scale; + } + else + { + /* purely to shut up the compiler */ + + texturecolumn = 0; + } + + /* draw the wall tiers */ + + if (midtexture) + { + /* single sided line */ + + dc_yl = yl; + dc_yh = yh; + dc_texturemid = rw_midtexturemid; + dc_source = r_get_column(midtexture, texturecolumn); + colfunc(); + ceilingclip[rw_x] = viewheight; + floorclip[rw_x] = -1; + } + else + { + /* two sided line */ + + if (toptexture) + { + /* top wall */ + + mid = pixhigh >> HEIGHTBITS; + pixhigh += pixhighstep; + + if (mid >= floorclip[rw_x]) mid = floorclip[rw_x] - 1; + + if (mid >= yl) + { + dc_yl = yl; + dc_yh = mid; + dc_texturemid = rw_toptexturemid; + dc_source = r_get_column(toptexture, texturecolumn); + colfunc(); + ceilingclip[rw_x] = mid; + } + else + ceilingclip[rw_x] = yl - 1; + } + else + { + /* no top wall */ + + if (markceiling) ceilingclip[rw_x] = yl - 1; + } + + if (bottomtexture) + { + /* bottom wall */ + + mid = (pixlow + HEIGHTUNIT - 1) >> HEIGHTBITS; + pixlow += pixlowstep; + + /* no space above wall? */ + + if (mid <= ceilingclip[rw_x]) mid = ceilingclip[rw_x] + 1; + + if (mid <= yh) + { + dc_yl = mid; + dc_yh = yh; + dc_texturemid = rw_bottomtexturemid; + dc_source = r_get_column(bottomtexture, texturecolumn); + colfunc(); + floorclip[rw_x] = mid; + } + else + floorclip[rw_x] = yh + 1; + } + else + { + /* no bottom wall */ + + if (markfloor) floorclip[rw_x] = yh + 1; + } + + if (maskedtexture) + { + /* save texturecol + * for backdrawing of masked mid texture + */ + + maskedtexturecol[rw_x] = texturecolumn; + } + } + + rw_scale += rw_scalestep; + topfrac += topstep; + bottomfrac += bottomstep; } - else +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void r_render_masked_seg_range(drawseg_t *ds, int x1, int x2) +{ + unsigned index; + column_t *col; + int lightnum; + int texnum; + + /* Calculate light table. + * Use different light tables for horizontal / vertical / diagonal. + * Diagonal? OPTIMIZE: get rid of LIGHTSEGSHIFT globally + */ + + curline = ds->curline; + frontsector = curline->frontsector; + backsector = curline->backsector; + texnum = texturetranslation[curline->sidedef->midtexture]; + + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; + + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + + maskedtexturecol = ds->maskedtexturecol; + + rw_scalestep = ds->scalestep; + spryscale = ds->scale1 + (x1 - ds->x1) * rw_scalestep; + mfloorclip = ds->sprbottomclip; + mceilingclip = ds->sprtopclip; + + /* find positioning */ + + if (curline->linedef->flags & ML_DONTPEGBOTTOM) { - dc_texturemid =frontsector->ceilingheightceilingheight - ? frontsector->ceilingheight : backsector->ceilingheight; - dc_texturemid = dc_texturemid - viewz; + dc_texturemid = frontsector->floorheight > backsector->floorheight + ? frontsector->floorheight + : backsector->floorheight; + dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; } - dc_texturemid += curline->sidedef->rowoffset; - - if (fixedcolormap) - dc_colormap = fixedcolormap; - - // draw the columns - for (dc_x = x1 ; dc_x <= x2 ; dc_x++) + else { - // calculate lighting - if (maskedtexturecol[dc_x] != SHRT_MAX) - { - if (!fixedcolormap) - { - index = spryscale>>LIGHTSCALESHIFT; - - if (index >= MAXLIGHTSCALE ) - index = MAXLIGHTSCALE-1; - - dc_colormap = walllights[index]; - } - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)( - (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3); - - R_DrawMaskedColumn (col); - maskedtexturecol[dc_x] = SHRT_MAX; - } - spryscale += rw_scalestep; + dc_texturemid = frontsector->ceilingheight < backsector->ceilingheight + ? frontsector->ceilingheight + : backsector->ceilingheight; + dc_texturemid = dc_texturemid - viewz; } - -} - + dc_texturemid += curline->sidedef->rowoffset; + if (fixedcolormap) dc_colormap = fixedcolormap; -// -// R_RenderSegLoop -// Draws zero, one, or two textures (and possibly a masked -// texture) for walls. -// Can draw or mark the starting pixel of floor and ceiling -// textures. -// CALLED: CORE LOOPING ROUTINE. -// -#define HEIGHTBITS 12 -#define HEIGHTUNIT (1<>HEIGHTBITS; - - // no space above wall? - if (yl < ceilingclip[rw_x]+1) - yl = ceilingclip[rw_x]+1; - - if (markceiling) - { - top = ceilingclip[rw_x]+1; - bottom = yl-1; - - if (bottom >= floorclip[rw_x]) - bottom = floorclip[rw_x]-1; - - if (top <= bottom) - { - ceilingplane->top[rw_x] = top; - ceilingplane->bottom[rw_x] = bottom; - } - } - - yh = bottomfrac>>HEIGHTBITS; - - if (yh >= floorclip[rw_x]) - yh = floorclip[rw_x]-1; - - if (markfloor) - { - top = yh+1; - bottom = floorclip[rw_x]-1; - if (top <= ceilingclip[rw_x]) - top = ceilingclip[rw_x]+1; - if (top <= bottom) - { - floorplane->top[rw_x] = top; - floorplane->bottom[rw_x] = bottom; - } - } - - // texturecolumn and lighting are independent of wall tiers - if (segtextured) - { - // calculate texture offset - angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; - texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance); - texturecolumn >>= FRACBITS; - // calculate lighting - index = rw_scale>>LIGHTSCALESHIFT; - - if (index >= MAXLIGHTSCALE ) - index = MAXLIGHTSCALE-1; - - dc_colormap = walllights[index]; - dc_x = rw_x; - dc_iscale = 0xffffffffu / (unsigned)rw_scale; - } - else + /* calculate lighting */ + + if (maskedtexturecol[dc_x] != SHRT_MAX) { - // purely to shut up the compiler + if (!fixedcolormap) + { + index = spryscale >> LIGHTSCALESHIFT; + + if (index >= MAXLIGHTSCALE) index = MAXLIGHTSCALE - 1; + + dc_colormap = walllights[index]; + } + + sprtopscreen = centeryfrac - fixed_mul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + /* draw the texture */ - texturecolumn = 0; + col = (column_t *)((byte *)r_get_column(texnum, + maskedtexturecol[dc_x]) - + 3); + + r_draw_masked_column(col); + maskedtexturecol[dc_x] = SHRT_MAX; } - - // draw the wall tiers - if (midtexture) - { - // single sided line - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn); - colfunc (); - ceilingclip[rw_x] = viewheight; - floorclip[rw_x] = -1; - } - else - { - // two sided line - if (toptexture) - { - // top wall - mid = pixhigh>>HEIGHTBITS; - pixhigh += pixhighstep; - - if (mid >= floorclip[rw_x]) - mid = floorclip[rw_x]-1; - - if (mid >= yl) - { - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn); - colfunc (); - ceilingclip[rw_x] = mid; - } - else - ceilingclip[rw_x] = yl-1; - } - else - { - // no top wall - if (markceiling) - ceilingclip[rw_x] = yl-1; - } - - if (bottomtexture) - { - // bottom wall - mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; - pixlow += pixlowstep; - - // no space above wall? - if (mid <= ceilingclip[rw_x]) - mid = ceilingclip[rw_x]+1; - - if (mid <= yh) - { - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn); - colfunc (); - floorclip[rw_x] = mid; - } - else - floorclip[rw_x] = yh+1; - } - else - { - // no bottom wall - if (markfloor) - floorclip[rw_x] = yh+1; - } - - if (maskedtexture) - { - // save texturecol - // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = texturecolumn; - } - } - - rw_scale += rw_scalestep; - topfrac += topstep; - bottomfrac += bottomstep; + + spryscale += rw_scalestep; } } +/* r_store_wall_range + * A wall segment will be drawn between start and stop pixels (inclusive). + */ + +void r_store_wall_range(int start, int stop) +{ + fixed_t hyp; + fixed_t sineval; + angle_t distangle, offsetangle; + fixed_t vtop; + int lightnum; + /* don't overflow and crash */ + if (ds_p == &drawsegs[CONFIG_GAMES_NXDOOM_MAXDRAWSEGS]) return; -// -// R_StoreWallRange -// A wall segment will be drawn -// between start and stop pixels (inclusive). -// -void -R_StoreWallRange -( int start, - int stop ) -{ - fixed_t hyp; - fixed_t sineval; - angle_t distangle, offsetangle; - fixed_t vtop; - int lightnum; - - // don't overflow and crash - if (ds_p == &drawsegs[MAXDRAWSEGS]) - return; - -#ifdef RANGECHECK - if (start >=viewwidth || start > stop) - I_Error ("Bad R_RenderWallRange: %i to %i", start , stop); +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (start >= viewwidth || start > stop) + i_error("Bad R_RenderWallRange: %i to %i", start, stop); #endif - - sidedef = curline->sidedef; - linedef = curline->linedef; - - // mark the segment as visible for auto map - linedef->flags |= ML_MAPPED; - - // calculate rw_distance for scale calculation - rw_normalangle = curline->angle + ANG90; - offsetangle = abs((int)rw_normalangle-(int)rw_angle1); - - if (offsetangle > ANG90) - offsetangle = ANG90; - - distangle = ANG90 - offsetangle; - hyp = R_PointToDist (curline->v1->x, curline->v1->y); - sineval = finesine[distangle>>ANGLETOFINESHIFT]; - rw_distance = FixedMul (hyp, sineval); - - - ds_p->x1 = rw_x = start; - ds_p->x2 = stop; - ds_p->curline = curline; - rw_stopx = stop+1; - - // calculate scale at both ends and step - ds_p->scale1 = rw_scale = - R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]); - - if (stop > start ) + + sidedef = curline->sidedef; + linedef = curline->linedef; + + /* mark the segment as visible for auto map */ + + linedef->flags |= ML_MAPPED; + + /* calculate rw_distance for scale calculation */ + + rw_normalangle = curline->angle + ANG90; + offsetangle = abs((int)rw_normalangle - (int)rw_angle1); + + if (offsetangle > ANG90) offsetangle = ANG90; + + distangle = ANG90 - offsetangle; + hyp = r_point_to_dist(curline->v1->x, curline->v1->y); + sineval = finesine[distangle >> ANGLETOFINESHIFT]; + rw_distance = fixed_mul(hyp, sineval); + + ds_p->x1 = rw_x = start; + ds_p->x2 = stop; + ds_p->curline = curline; + rw_stopx = stop + 1; + + /* calculate scale at both ends and step */ + + ds_p->scale1 = rw_scale = + r_scale_from_global_angle(viewangle + xtoviewangle[start]); + + if (stop > start) { - ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]); - ds_p->scalestep = rw_scalestep = - (ds_p->scale2 - rw_scale) / (stop-start); + ds_p->scale2 = + r_scale_from_global_angle(viewangle + xtoviewangle[stop]); + ds_p->scalestep = rw_scalestep = + (ds_p->scale2 - rw_scale) / (stop - start); } - else + else { - // UNUSED: try to fix the stretched line bug -#if 0 - if (rw_distance < FRACUNIT/2) - { - fixed_t trx,try; - fixed_t gxt,gyt; - - trx = curline->v1->x - viewx; - try = curline->v1->y - viewy; - - gxt = FixedMul(trx,viewcos); - gyt = -FixedMul(try,viewsin); - ds_p->scale1 = FixedDiv(projection, gxt-gyt)<v1->x - viewx; + try = curline->v1->y - viewy; + + gxt = fixed_mul(trx, viewcos); + gyt = -fixed_mul(try, viewsin); + ds_p->scale1 = fixed_div(projection, gxt - gyt) << detailshift; + } + #endif - ds_p->scale2 = ds_p->scale1; + ds_p->scale2 = ds_p->scale1; + } + + /* calculate texture boundaries and decide if floor / ceiling marks are + * needed + */ + + worldtop = frontsector->ceilingheight - viewz; + worldbottom = frontsector->floorheight - viewz; + + midtexture = toptexture = bottomtexture = maskedtexture = 0; + ds_p->maskedtexturecol = NULL; + + if (!backsector) + { + /* single sided line */ + + midtexture = texturetranslation[sidedef->midtexture]; + + /* a single sided line is terminal, so it must mark ends */ + + markfloor = markceiling = true; + if (linedef->flags & ML_DONTPEGBOTTOM) + { + vtop = + frontsector->floorheight + textureheight[sidedef->midtexture]; + + /* bottom of texture at bottom */ + + rw_midtexturemid = vtop - viewz; + } + else + { + /* top of texture at top */ + + rw_midtexturemid = worldtop; + } + + rw_midtexturemid += sidedef->rowoffset; + + ds_p->silhouette = SIL_BOTH; + ds_p->sprtopclip = screenheightarray; + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->tsilheight = INT_MIN; + } + else + { + /* two sided line */ + + ds_p->sprtopclip = ds_p->sprbottomclip = NULL; + ds_p->silhouette = 0; + + if (frontsector->floorheight > backsector->floorheight) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = frontsector->floorheight; + } + else if (backsector->floorheight > viewz) + { + ds_p->silhouette = SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; + + /* ds_p->sprbottomclip = negonearray; */ + } + + if (frontsector->ceilingheight < backsector->ceilingheight) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = frontsector->ceilingheight; + } + else if (backsector->ceilingheight < viewz) + { + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; + + /* ds_p->sprtopclip = screenheightarray; */ + } + + if (backsector->ceilingheight <= frontsector->floorheight) + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } + + if (backsector->floorheight >= frontsector->ceilingheight) + { + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT_MIN; + ds_p->silhouette |= SIL_TOP; + } + + worldhigh = backsector->ceilingheight - viewz; + worldlow = backsector->floorheight - viewz; + + /* hack to allow height changes in outdoor areas */ + + if (frontsector->ceilingpic == skyflatnum && + backsector->ceilingpic == skyflatnum) + { + worldtop = worldhigh; + } + + if (worldlow != worldbottom || + backsector->floorpic != frontsector->floorpic || + backsector->lightlevel != frontsector->lightlevel) + { + markfloor = true; + } + else + { + /* same plane on both sides */ + + markfloor = false; + } + + if (worldhigh != worldtop || + backsector->ceilingpic != frontsector->ceilingpic || + backsector->lightlevel != frontsector->lightlevel) + { + markceiling = true; + } + else + { + /* same plane on both sides */ + + markceiling = false; + } + + if (backsector->ceilingheight <= frontsector->floorheight || + backsector->floorheight >= frontsector->ceilingheight) + { + /* closed door */ + + markceiling = markfloor = true; + } + + if (worldhigh < worldtop) + { + /* top texture */ + + toptexture = texturetranslation[sidedef->toptexture]; + if (linedef->flags & ML_DONTPEGTOP) + { + /* top of texture at top */ + + rw_toptexturemid = worldtop; + } + else + { + vtop = backsector->ceilingheight + + textureheight[sidedef->toptexture]; + + /* bottom of texture */ + + rw_toptexturemid = vtop - viewz; + } + } + + if (worldlow > worldbottom) + { + /* bottom texture */ + + bottomtexture = texturetranslation[sidedef->bottomtexture]; + + if (linedef->flags & ML_DONTPEGBOTTOM) + { + /* bottom of texture at bottom top of texture at top */ + + rw_bottomtexturemid = worldtop; + } + else /* top of texture at top */ + rw_bottomtexturemid = worldlow; + } + + rw_toptexturemid += sidedef->rowoffset; + rw_bottomtexturemid += sidedef->rowoffset; + + /* allocate space for masked texture tables */ + + if (sidedef->midtexture) + { + /* masked midtexture */ + + maskedtexture = true; + ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; + lastopening += rw_stopx - rw_x; + } } - - // calculate texture boundaries - // and decide if floor / ceiling marks are needed - worldtop = frontsector->ceilingheight - viewz; - worldbottom = frontsector->floorheight - viewz; - - midtexture = toptexture = bottomtexture = maskedtexture = 0; - ds_p->maskedtexturecol = NULL; - - if (!backsector) + + /* calculate rw_offset (only needed for textured lines) */ + + segtextured = midtexture | toptexture | bottomtexture | maskedtexture; + + if (segtextured) { - // single sided line - midtexture = texturetranslation[sidedef->midtexture]; - // a single sided line is terminal, so it must mark ends - markfloor = markceiling = true; - if (linedef->flags & ML_DONTPEGBOTTOM) - { - vtop = frontsector->floorheight + - textureheight[sidedef->midtexture]; - // bottom of texture at bottom - rw_midtexturemid = vtop - viewz; - } - else - { - // top of texture at top - rw_midtexturemid = worldtop; - } - rw_midtexturemid += sidedef->rowoffset; - - ds_p->silhouette = SIL_BOTH; - ds_p->sprtopclip = screenheightarray; - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->tsilheight = INT_MIN; + offsetangle = rw_normalangle - rw_angle1; + + if (offsetangle > ANG180) offsetangle = -offsetangle; + + if (offsetangle > ANG90) offsetangle = ANG90; + + sineval = finesine[offsetangle >> ANGLETOFINESHIFT]; + rw_offset = fixed_mul(hyp, sineval); + + if (rw_normalangle - rw_angle1 < ANG180) rw_offset = -rw_offset; + + rw_offset += sidedef->textureoffset + curline->offset; + rw_centerangle = ANG90 + viewangle - rw_normalangle; + + /* calculate light table use different light tables for horizontal / + * vertical / diagonal + * + * OPTIMIZE: get rid of LIGHTSEGSHIFT globally + */ + + if (!fixedcolormap) + { + lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; + + if (curline->v1->y == curline->v2->y) + lightnum--; + else if (curline->v1->x == curline->v2->x) + lightnum++; + + if (lightnum < 0) + walllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + walllights = scalelight[LIGHTLEVELS - 1]; + else + walllights = scalelight[lightnum]; + } } - else + + /* if a floor / ceiling plane is on the wrong side of the view plane, it is + * definitely invisible and doesn't need to be marked. + */ + + if (frontsector->floorheight >= viewz) { - // two sided line - ds_p->sprtopclip = ds_p->sprbottomclip = NULL; - ds_p->silhouette = 0; - - if (frontsector->floorheight > backsector->floorheight) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = frontsector->floorheight; - } - else if (backsector->floorheight > viewz) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; - // ds_p->sprbottomclip = negonearray; - } - - if (frontsector->ceilingheight < backsector->ceilingheight) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = frontsector->ceilingheight; - } - else if (backsector->ceilingheight < viewz) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; - // ds_p->sprtopclip = screenheightarray; - } - - if (backsector->ceilingheight <= frontsector->floorheight) - { - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->silhouette |= SIL_BOTTOM; - } - - if (backsector->floorheight >= frontsector->ceilingheight) - { - ds_p->sprtopclip = screenheightarray; - ds_p->tsilheight = INT_MIN; - ds_p->silhouette |= SIL_TOP; - } - - worldhigh = backsector->ceilingheight - viewz; - worldlow = backsector->floorheight - viewz; - - // hack to allow height changes in outdoor areas - if (frontsector->ceilingpic == skyflatnum - && backsector->ceilingpic == skyflatnum) - { - worldtop = worldhigh; - } - - - if (worldlow != worldbottom - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel) - { - markfloor = true; - } - else - { - // same plane on both sides - markfloor = false; - } - - - if (worldhigh != worldtop - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel) - { - markceiling = true; - } - else - { - // same plane on both sides - markceiling = false; - } - - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - { - // closed door - markceiling = markfloor = true; - } - - - if (worldhigh < worldtop) - { - // top texture - toptexture = texturetranslation[sidedef->toptexture]; - if (linedef->flags & ML_DONTPEGTOP) - { - // top of texture at top - rw_toptexturemid = worldtop; - } - else - { - vtop = - backsector->ceilingheight - + textureheight[sidedef->toptexture]; - - // bottom of texture - rw_toptexturemid = vtop - viewz; - } - } - if (worldlow > worldbottom) - { - // bottom texture - bottomtexture = texturetranslation[sidedef->bottomtexture]; - - if (linedef->flags & ML_DONTPEGBOTTOM ) - { - // bottom of texture at bottom - // top of texture at top - rw_bottomtexturemid = worldtop; - } - else // top of texture at top - rw_bottomtexturemid = worldlow; - } - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; - - // allocate space for masked texture tables - if (sidedef->midtexture) - { - // masked midtexture - maskedtexture = true; - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; - } + /* above view plane */ + + markfloor = false; } - - // calculate rw_offset (only needed for textured lines) - segtextured = midtexture | toptexture | bottomtexture | maskedtexture; - if (segtextured) + if (frontsector->ceilingheight <= viewz && + frontsector->ceilingpic != skyflatnum) { - offsetangle = rw_normalangle-rw_angle1; - - if (offsetangle > ANG180) - offsetangle = -offsetangle; - - if (offsetangle > ANG90) - offsetangle = ANG90; - - sineval = finesine[offsetangle >>ANGLETOFINESHIFT]; - rw_offset = FixedMul (hyp, sineval); - - if (rw_normalangle-rw_angle1 < ANG180) - rw_offset = -rw_offset; - - rw_offset += sidedef->textureoffset + curline->offset; - rw_centerangle = ANG90 + viewangle - rw_normalangle; - - // calculate light table - // use different light tables - // for horizontal / vertical / diagonal - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - if (!fixedcolormap) - { - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS-1]; - else - walllights = scalelight[lightnum]; - } + /* below view plane */ + + markceiling = false; } - - // if a floor / ceiling plane is on the wrong side - // of the view plane, it is definitely invisible - // and doesn't need to be marked. - - - if (frontsector->floorheight >= viewz) + + /* calculate incremental stepping values for texture edges */ + + worldtop >>= 4; + worldbottom >>= 4; + + topstep = -fixed_mul(rw_scalestep, worldtop); + topfrac = (centeryfrac >> 4) - fixed_mul(worldtop, rw_scale); + + bottomstep = -fixed_mul(rw_scalestep, worldbottom); + bottomfrac = (centeryfrac >> 4) - fixed_mul(worldbottom, rw_scale); + + if (backsector) { - // above view plane - markfloor = false; + worldhigh >>= 4; + worldlow >>= 4; + + if (worldhigh < worldtop) + { + pixhigh = (centeryfrac >> 4) - fixed_mul(worldhigh, rw_scale); + pixhighstep = -fixed_mul(rw_scalestep, worldhigh); + } + + if (worldlow > worldbottom) + { + pixlow = (centeryfrac >> 4) - fixed_mul(worldlow, rw_scale); + pixlowstep = -fixed_mul(rw_scalestep, worldlow); + } } - - if (frontsector->ceilingheight <= viewz - && frontsector->ceilingpic != skyflatnum) + + /* render it */ + + if (markceiling) { - // below view plane - markceiling = false; + ceilingplane = r_check_plane(ceilingplane, rw_x, rw_stopx - 1); } - - // calculate incremental stepping values for texture edges - worldtop >>= 4; - worldbottom >>= 4; - - topstep = -FixedMul (rw_scalestep, worldtop); - topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); - - bottomstep = -FixedMul (rw_scalestep,worldbottom); - bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); - - if (backsector) - { - worldhigh >>= 4; - worldlow >>= 4; - - if (worldhigh < worldtop) - { - pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); - pixhighstep = -FixedMul (rw_scalestep,worldhigh); - } - - if (worldlow > worldbottom) - { - pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); - pixlowstep = -FixedMul (rw_scalestep,worldlow); - } + if (markfloor) + { + floorplane = r_check_plane(floorplane, rw_x, rw_stopx - 1); } - - // render it - if (markceiling) - ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); - - if (markfloor) - floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); - - R_RenderSegLoop (); - - - // save sprite clipping info - if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) - && !ds_p->sprtopclip) + + r_render_seg_loop(); + + /* save sprite clipping info */ + + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) { - memcpy (lastopening, ceilingclip+start, sizeof(*lastopening)*(rw_stopx-start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; + memcpy(lastopening, ceilingclip + start, + sizeof(*lastopening) * (rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; } - - if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) - && !ds_p->sprbottomclip) + + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && + !ds_p->sprbottomclip) { - memcpy (lastopening, floorclip+start, sizeof(*lastopening)*(rw_stopx-start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; + memcpy(lastopening, floorclip + start, + sizeof(*lastopening) * (rw_stopx - start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; } - if (maskedtexture && !(ds_p->silhouette&SIL_TOP)) + if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; + ds_p->silhouette |= SIL_TOP; + ds_p->tsilheight = INT_MIN; } - if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM)) + + if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; + ds_p->silhouette |= SIL_BOTTOM; + ds_p->bsilheight = INT_MAX; } - ds_p++; -} + ds_p++; +} diff --git a/games/NXDoom/src/doom/r_segs.h b/games/NXDoom/src/doom/r_segs.h index 8e6a768f454..8bd13275f31 100644 --- a/games/NXDoom/src/doom/r_segs.h +++ b/games/NXDoom/src/doom/r_segs.h @@ -1,34 +1,39 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh module, drawing LineSegs from BSP. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_segs.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh module, drawing LineSegs from BSP. + * + ****************************************************************************/ #ifndef __R_SEGS__ #define __R_SEGS__ +/**************************************************************************** + * Public Data + ****************************************************************************/ extern lighttable_t **walllights; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void -R_RenderMaskedSegRange -( drawseg_t* ds, - int x1, - int x2 ); - +void r_render_masked_seg_range(drawseg_t *ds, int x1, int x2); -#endif +#endif /* __R_SEGS__ */ diff --git a/games/NXDoom/src/doom/r_sky.c b/games/NXDoom/src/doom/r_sky.c index bcd5a75bb50..d84e6729bd1 100644 --- a/games/NXDoom/src/doom/r_sky.c +++ b/games/NXDoom/src/doom/r_sky.c @@ -1,52 +1,68 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Sky rendering. The DOOM sky is a texture map like any -// wall, wrapping around. A 1024 columns equal 360 degrees. -// The default sky map is 256 columns and repeats 4 times -// on a 320 screen? -// -// - - - -// Needed for FRACUNIT. +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_sky.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Sky rendering. The DOOM sky is a texture map like any + * wall, wrapping around. A 1024 columns equal 360 degrees. + * The default sky map is 256 columns and repeats 4 times + * on a 320 screen? + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Needed for FRACUNIT. */ + #include "m_fixed.h" -// Needed for Flat retrieval. -#include "r_data.h" +/* Needed for Flat retrieval. */ +#include "r_data.h" #include "r_sky.h" -// -// sky mapping -// -int skyflatnum; -int skytexture; -int skytexturemid; +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* sky mapping */ +int skyflatnum; +int skytexture; +int skytexturemid; -// -// R_InitSkyMap -// Called whenever the view size changes. -// -void R_InitSkyMap (void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: r_init_sky_map + * + * Description: + * Called whenever the view size changes. + * + ****************************************************************************/ + +void r_init_sky_map(void) { - // skyflatnum = R_FlatNumForName ( SKYFLATNAME ); - skytexturemid = SCREENHEIGHT/2*FRACUNIT; -} + /* skyflatnum = r_flat_num_for_name ( SKYFLATNAME ); */ + skytexturemid = SCREENHEIGHT / 2 * FRACUNIT; +} diff --git a/games/NXDoom/src/doom/r_sky.h b/games/NXDoom/src/doom/r_sky.h index 8ad6680aa5f..e9455b72e8a 100644 --- a/games/NXDoom/src/doom/r_sky.h +++ b/games/NXDoom/src/doom/r_sky.h @@ -1,37 +1,54 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Sky rendering. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_sky.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Sky rendering. + * + ****************************************************************************/ #ifndef __R_SKY__ #define __R_SKY__ +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SKY, store the number for name. */ + +#define SKYFLATNAME "F_SKY1" + +/* The sky map is 256*128*4 maps. */ + +#define ANGLETOSKYSHIFT 22 +/**************************************************************************** + * Public Data + ****************************************************************************/ -// SKY, store the number for name. -#define SKYFLATNAME "F_SKY1" +extern int skytexture; +extern int skytexturemid; -// The sky map is 256*128*4 maps. -#define ANGLETOSKYSHIFT 22 +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -extern int skytexture; -extern int skytexturemid; +/* Called whenever the view size changes. */ -// Called whenever the view size changes. -void R_InitSkyMap (void); +void r_init_sky_map(void); #endif diff --git a/games/NXDoom/src/doom/r_state.h b/games/NXDoom/src/doom/r_state.h index 2a60e2fe8e1..cab81830dea 100644 --- a/games/NXDoom/src/doom/r_state.h +++ b/games/NXDoom/src/doom/r_state.h @@ -1,127 +1,130 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh/render internal state variables (global). -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_state.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh/render internal state variables (global). + * + ****************************************************************************/ #ifndef __R_STATE__ #define __R_STATE__ -// Need data structure definitions. -#include "d_player.h" -#include "r_data.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ +/* Need data structure definitions. */ +#include "d_player.h" +#include "r_data.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* Refresh internal data structures, for rendering. */ +/* needed for texture pegging */ -// -// Refresh internal data structures, -// for rendering. -// +extern fixed_t *textureheight; -// needed for texture pegging -extern fixed_t* textureheight; +/* needed for pre rendering (fracs) */ -// needed for pre rendering (fracs) -extern fixed_t* spritewidth; +extern fixed_t *spritewidth; -extern fixed_t* spriteoffset; -extern fixed_t* spritetopoffset; +extern fixed_t *spriteoffset; +extern fixed_t *spritetopoffset; -extern lighttable_t* colormaps; +extern lighttable_t *colormaps; -extern int viewwidth; -extern int scaledviewwidth; -extern int viewheight; +extern int viewwidth; +extern int scaledviewwidth; +extern int viewheight; -extern int firstflat; +extern int firstflat; -// for global animation -extern int* flattranslation; -extern int* texturetranslation; +/* for global animation */ +extern int *flattranslation; +extern int *texturetranslation; -// Sprite.... -extern int firstspritelump; -extern int lastspritelump; -extern int numspritelumps; +/* Sprite.... */ +extern int firstspritelump; +extern int lastspritelump; +extern int numspritelumps; +/* Lookup tables for map data. */ -// -// Lookup tables for map data. -// -extern int numsprites; -extern spritedef_t* sprites; +extern int numsprites; +extern spritedef_t *sprites; -extern int numvertexes; -extern vertex_t* vertexes; +extern int numvertices; +extern vertex_t *vertices; -extern int numsegs; -extern seg_t* segs; +extern int numsegs; +extern seg_t *segs; -extern int numsectors; -extern sector_t* sectors; +extern int numsectors; +extern sector_t *sectors; -extern int numsubsectors; -extern subsector_t* subsectors; +extern int numsubsectors; +extern subsector_t *subsectors; -extern int numnodes; -extern node_t* nodes; +extern int numnodes; +extern node_t *nodes; -extern int numlines; -extern line_t* lines; +extern int numlines; +extern line_t *lines; -extern int numsides; -extern side_t* sides; +extern int numsides; +extern side_t *sides; +/* POV data. */ -// -// POV data. -// -extern fixed_t viewx; -extern fixed_t viewy; -extern fixed_t viewz; +extern fixed_t viewx; +extern fixed_t viewy; +extern fixed_t viewz; -extern angle_t viewangle; -extern player_t* viewplayer; +extern angle_t viewangle; +extern player_t *viewplayer; +/* ? */ -// ? -extern angle_t clipangle; +extern angle_t clipangle; -extern int viewangletox[FINEANGLES/2]; -extern angle_t xtoviewangle[SCREENWIDTH+1]; -//extern fixed_t finetangent[FINEANGLES/2]; +extern int viewangletox[FINEANGLES / 2]; +extern angle_t xtoviewangle[SCREENWIDTH + 1]; -extern fixed_t rw_distance; -extern angle_t rw_normalangle; +/* extern fixed_t finetangent[FINEANGLES/2]; */ +extern fixed_t rw_distance; +extern angle_t rw_normalangle; +/* angle to line origin */ -// angle to line origin -extern int rw_angle1; +extern int rw_angle1; -// Segs count? -extern int sscount; +/* Segs count? */ -extern visplane_t* floorplane; -extern visplane_t* ceilingplane; +extern int sscount; +extern visplane_t *floorplane; +extern visplane_t *ceilingplane; -#endif +#endif /* __R_STATE__ */ diff --git a/games/NXDoom/src/doom/r_things.c b/games/NXDoom/src/doom/r_things.c index 5533fd9bf48..019d83a7048 100644 --- a/games/NXDoom/src/doom/r_things.c +++ b/games/NXDoom/src/doom/r_things.c @@ -1,982 +1,974 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh of things, i.e. objects represented by sprites. -// - - - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_things.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh of things, i.e. objects represented by sprites. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include - #include "deh_main.h" #include "doomdef.h" #include "i_swap.h" #include "i_system.h" -#include "z_zone.h" #include "w_wad.h" +#include "z_zone.h" #include "r_local.h" #include "doomstat.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define MINZ (FRACUNIT * 4) +#define BASEYCENTER (SCREENHEIGHT / 2) -#define MINZ (FRACUNIT*4) -#define BASEYCENTER (SCREENHEIGHT/2) - -//void R_DrawColumn (void); -//void R_DrawFuzzColumn (void); - - +/**************************************************************************** + * Private Types + ****************************************************************************/ typedef struct { - int x1; - int x2; - - int column; - int topclip; - int bottomclip; + int x1; + int x2; + int column; + int topclip; + int bottomclip; } maskdraw_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ +/* Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn + * CLOCKWISE around the axis. + * + * This is not the same as the angle, which increases counter clockwise + * (protractor). There was a lot of stuff grabbed wrong, so I changed it... + */ -// -// Sprite rotation 0 is facing the viewer, -// rotation 1 is one angle turn CLOCKWISE around the axis. -// This is not the same as the angle, -// which increases counter clockwise (protractor). -// There was a lot of stuff grabbed wrong, so I changed it... -// -fixed_t pspritescale; -fixed_t pspriteiscale; +fixed_t pspritescale; +fixed_t pspriteiscale; -lighttable_t** spritelights; +lighttable_t **spritelights; -// constant arrays -// used for psprite clipping and initializing clipping -short negonearray[SCREENWIDTH]; -short screenheightarray[SCREENWIDTH]; +/* constant arrays used for psprite clipping and initializing clipping */ +short negonearray[SCREENWIDTH]; +short screenheightarray[SCREENWIDTH]; -// -// INITIALIZATION FUNCTIONS -// +/* INITIALIZATION FUNCTIONS */ -// variables used to look up -// and range check thing_t sprites patches -spritedef_t* sprites; -int numsprites; +/* variables used to look up and range check thing_t sprites patches */ -spriteframe_t sprtemp[29]; -int maxframe; -const char *spritename; +spritedef_t *sprites; +int numsprites; +spriteframe_t sprtemp[29]; +int maxframe; +const char *spritename; +vissprite_t vissprites[CONFIG_GAMES_NXDOOM_MAXVISSPRITES]; +vissprite_t *vissprite_p; +int newvissprite; +vissprite_t overflowsprite; -// -// R_InstallSpriteLump -// Local function for R_InitSprites. -// -void -R_InstallSpriteLump -( int lump, - unsigned frame, - unsigned rotation, - boolean flipped ) -{ - int r; - - if (frame >= 29 || rotation > 8) - I_Error("R_InstallSpriteLump: " - "Bad frame characters in lump %i", lump); - - if ((int)frame > maxframe) - maxframe = frame; - - if (rotation == 0) - { - // the lump should be used for all rotations - if (sprtemp[frame].rotate == false) - I_Error ("R_InitSprites: Sprite %s frame %c has " - "multip rot=0 lump", spritename, 'A'+frame); - - if (sprtemp[frame].rotate == true) - I_Error ("R_InitSprites: Sprite %s frame %c has rotations " - "and a rot=0 lump", spritename, 'A'+frame); - - sprtemp[frame].rotate = false; - for (r=0 ; r<8 ; r++) - { - sprtemp[frame].lump[r] = lump - firstspritelump; - sprtemp[frame].flip[r] = (byte)flipped; - } - return; - } - - // the lump is only used for one rotation - if (sprtemp[frame].rotate == false) - I_Error ("R_InitSprites: Sprite %s frame %c has rotations " - "and a rot=0 lump", spritename, 'A'+frame); - - sprtemp[frame].rotate = true; - - // make 0 based - rotation--; - if (sprtemp[frame].lump[rotation] != -1) - I_Error ("R_InitSprites: Sprite %s : %c : %c " - "has two lumps mapped to it", - spritename, 'A'+frame, '1'+rotation); - - sprtemp[frame].lump[rotation] = lump - firstspritelump; - sprtemp[frame].flip[rotation] = (byte)flipped; -} +short *mfloorclip; +short *mceilingclip; +fixed_t spryscale; +fixed_t sprtopscreen; +vissprite_t vsprsortedhead; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// -// R_InitSpriteDefs -// Pass a null terminated list of sprite names -// (4 chars exactly) to be used. -// Builds the sprite rotation matrixes to account -// for horizontally flipped sprites. -// Will report an error if the lumps are inconsistant. -// Only called at startup. -// -// Sprite lump names are 4 characters for the actor, -// a letter for the frame, and a number for the rotation. -// A sprite that is flippable will have an additional -// letter/number appended. -// The rotation character can be 0 to signify no rotations. -// -void R_InitSpriteDefs(const char **namelist) -{ - const char **check; - int i; - int l; - int frame; - int rotation; - int start; - int end; - int patched; - - // count the number of sprite names - check = namelist; - while (*check != NULL) - check++; - - numsprites = check-namelist; - - if (!numsprites) - return; - - sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); - - start = firstspritelump-1; - end = lastspritelump+1; - - // scan all the lump names for each of the names, - // noting the highest frame letter. - // Just compare 4 characters as ints - for (i=0 ; iname, spritename, 4)) - { - frame = lumpinfo[l]->name[4] - 'A'; - rotation = lumpinfo[l]->name[5] - '0'; - - if (modifiedgame) - patched = W_GetNumForName (lumpinfo[l]->name); - else - patched = l; - - R_InstallSpriteLump (patched, frame, rotation, false); - - if (lumpinfo[l]->name[6]) - { - frame = lumpinfo[l]->name[6] - 'A'; - rotation = lumpinfo[l]->name[7] - '0'; - R_InstallSpriteLump (l, frame, rotation, true); - } - } - } - - // check the frames that were found for completeness - if (maxframe == -1) - { - sprites[i].numframes = 0; - continue; - } - - maxframe++; - - for (frame = 0 ; frame < maxframe ; frame++) - { - switch ((int)sprtemp[frame].rotate) - { - case -1: - // no rotations were found for that frame at all - I_Error ("R_InitSprites: No patches found " - "for %s frame %c", spritename, frame+'A'); - break; - - case 0: - // only the first rotation is needed - break; - - case 1: - // must have all 8 frames - for (rotation=0 ; rotation<8 ; rotation++) - if (sprtemp[frame].lump[rotation] == -1) - I_Error ("R_InitSprites: Sprite %s frame %c " - "is missing rotations", - spritename, frame+'A'); - break; - } - } - - // allocate space for the frames present and copy sprtemp to it - sprites[i].numframes = maxframe; - sprites[i].spriteframes = - Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); - memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); +/* R_InstallSpriteLump + * Local function for r_init_sprites. + */ + +static void r_install_sprite_lump(int lump, unsigned frame, + unsigned rotation, boolean flipped) +{ + int r; + + if (frame >= 29 || rotation > 8) + i_error("R_InstallSpriteLump: " + "Bad frame characters in lump %i", + lump); + + if ((int)frame > maxframe) maxframe = frame; + + if (rotation == 0) + { + /* the lump should be used for all rotations */ + + if (sprtemp[frame].rotate == false) + i_error("r_init_sprites: Sprite %s frame %c has " + "multip rot=0 lump", + spritename, 'A' + frame); + + if (sprtemp[frame].rotate == true) + i_error("r_init_sprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = false; + for (r = 0; r < 8; r++) + { + sprtemp[frame].lump[r] = lump - firstspritelump; + sprtemp[frame].flip[r] = (byte)flipped; + } + + return; } + /* the lump is only used for one rotation */ + + if (sprtemp[frame].rotate == false) + i_error("r_init_sprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = true; + + /* make 0 based */ + + rotation--; + if (sprtemp[frame].lump[rotation] != -1) + i_error("r_init_sprites: Sprite %s : %c : %c " + "has two lumps mapped to it", + spritename, 'A' + frame, '1' + rotation); + + sprtemp[frame].lump[rotation] = lump - firstspritelump; + sprtemp[frame].flip[rotation] = (byte)flipped; } +/* r_init_sprite_defs + * + * Pass a null terminated list of sprite names (4 chars exactly) to be used. + * + * Builds the sprite rotation matrixes to account for horizontally flipped + * sprites. + * + * Will report an error if the lumps are inconsistent. Only called at + * startup. + * + * Sprite lump names are 4 characters for the actor, a letter for the frame, + * and a number for the rotation. + * + * A sprite that is flippable will have an additional letter/number appended. + * + * The rotation character can be 0 to signify no rotations. + */ + +static void r_init_sprite_defs(const char **namelist) +{ + const char **check; + int i; + int l; + int frame; + int rotation; + int start; + int end; + int patched; + /* count the number of sprite names */ + check = namelist; + while (*check != NULL) + check++; -// -// GAME FUNCTIONS -// -vissprite_t vissprites[MAXVISSPRITES]; -vissprite_t* vissprite_p; -int newvissprite; + numsprites = check - namelist; + if (!numsprites) return; + sprites = z_malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); -// -// R_InitSprites -// Called at program start. -// -void R_InitSprites(const char **namelist) -{ - int i; - - for (i=0 ; iname, spritename, 4)) + { + frame = lumpinfo[l]->name[4] - 'A'; + rotation = lumpinfo[l]->name[5] - '0'; + + if (modifiedgame) + patched = w_get_num_for_name(lumpinfo[l]->name); + else + patched = l; + + r_install_sprite_lump(patched, frame, rotation, false); + + if (lumpinfo[l]->name[6]) + { + frame = lumpinfo[l]->name[6] - 'A'; + rotation = lumpinfo[l]->name[7] - '0'; + r_install_sprite_lump(l, frame, rotation, true); + } + } + } + + /* check the frames that were found for completeness */ + + if (maxframe == -1) + { + sprites[i].numframes = 0; + continue; + } + + maxframe++; + + for (frame = 0; frame < maxframe; frame++) + { + switch ((int)sprtemp[frame].rotate) + { + case -1: + + /* no rotations were found for that frame at all */ + + i_error("r_init_sprites: No patches found " + "for %s frame %c", + spritename, frame + 'A'); + break; + + case 0: + break; /* only the first rotation is needed */ + + case 1: + + /* must have all 8 frames */ + + for (rotation = 0; rotation < 8; rotation++) + if (sprtemp[frame].lump[rotation] == -1) + i_error("r_init_sprites: Sprite %s frame %c " + "is missing rotations", + spritename, frame + 'A'); + break; + } + } + + /* allocate space for the frames present and copy sprtemp to it */ + + sprites[i].numframes = maxframe; + sprites[i].spriteframes = + z_malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + memcpy(sprites[i].spriteframes, sprtemp, + maxframe * sizeof(spriteframe_t)); } - - R_InitSpriteDefs (namelist); } - - -// -// R_ClearSprites -// Called at frame start. -// -void R_ClearSprites (void) +static vissprite_t *r_new_vis_sprite(void) { - vissprite_p = vissprites; -} + if (vissprite_p == &vissprites[CONFIG_GAMES_NXDOOM_MAXVISSPRITES]) + { + return &overflowsprite; + } + vissprite_p++; + return vissprite_p - 1; +} -// -// R_NewVisSprite -// -vissprite_t overflowsprite; +/* R_DrawVisSprite + * mfloorclip and mceilingclip should also be set. + */ -vissprite_t* R_NewVisSprite (void) +static void r_draw_vis_sprite(vissprite_t *vis, int x1, int x2) { - if (vissprite_p == &vissprites[MAXVISSPRITES]) - return &overflowsprite; - - vissprite_p++; - return vissprite_p-1; -} + column_t *column; + int texturecolumn; + fixed_t frac; + patch_t *patch; + patch = w_cache_lump_num(vis->patch + firstspritelump, PU_CACHE); + dc_colormap = vis->colormap; -// -// R_DrawMaskedColumn -// Used for sprites and masked mid textures. -// Masked means: partly transparent, i.e. stored -// in posts/runs of opaque pixels. -// -short* mfloorclip; -short* mceilingclip; + if (!dc_colormap) + { + /* NULL colormap = shadow draw */ -fixed_t spryscale; -fixed_t sprtopscreen; + colfunc = fuzzcolfunc; + } + else if (vis->mobjflags & MF_TRANSLATION) + { + colfunc = transcolfunc; + dc_translation = + translationtables - 256 + + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); + } -void R_DrawMaskedColumn (column_t* column) -{ - int topscreen; - int bottomscreen; - fixed_t basetexturemid; - - basetexturemid = dc_texturemid; - - for ( ; column->topdelta != 0xff ; ) - { - // calculate unclipped screen coordinates - // for post - topscreen = sprtopscreen + spryscale*column->topdelta; - bottomscreen = topscreen + spryscale*column->length; - - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; - - if (dc_yh >= mfloorclip[dc_x]) - dc_yh = mfloorclip[dc_x]-1; - if (dc_yl <= mceilingclip[dc_x]) - dc_yl = mceilingclip[dc_x]+1; - - if (dc_yl <= dc_yh) - { - dc_source = (byte *)column + 3; - dc_texturemid = basetexturemid - (column->topdelta<topdelta; - - // Drawn by either R_DrawColumn - // or (SHADOW) R_DrawFuzzColumn. - colfunc (); - } - column = (column_t *)( (byte *)column + column->length + 4); - } - - dc_texturemid = basetexturemid; -} + dc_iscale = abs(vis->xiscale) >> detailshift; + dc_texturemid = vis->texturemid; + frac = vis->startfrac; + spryscale = vis->scale; + sprtopscreen = centeryfrac - fixed_mul(dc_texturemid, spryscale); + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + { + texturecolumn = frac >> FRACBITS; +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + { + i_error("R_DrawSpriteRange: bad texturecolumn"); + } -// -// R_DrawVisSprite -// mfloorclip and mceilingclip should also be set. -// -void -R_DrawVisSprite -( vissprite_t* vis, - int x1, - int x2 ) -{ - column_t* column; - int texturecolumn; - fixed_t frac; - patch_t* patch; - - - patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); - - dc_colormap = vis->colormap; - - if (!dc_colormap) - { - // NULL colormap = shadow draw - colfunc = fuzzcolfunc; - } - else if (vis->mobjflags & MF_TRANSLATION) - { - colfunc = transcolfunc; - dc_translation = translationtables - 256 + - ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) ); - } - - dc_iscale = abs(vis->xiscale)>>detailshift; - dc_texturemid = vis->texturemid; - frac = vis->startfrac; - spryscale = vis->scale; - sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); - - for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) - { - texturecolumn = frac>>FRACBITS; -#ifdef RANGECHECK - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - I_Error ("R_DrawSpriteRange: bad texturecolumn"); #endif - column = (column_t *) ((byte *)patch + - LONG(patch->columnofs[texturecolumn])); - R_DrawMaskedColumn (column); + + column = (column_t *)((byte *)patch + + LONG(patch->columnofs[texturecolumn])); + r_draw_masked_column(column); } - colfunc = basecolfunc; + colfunc = basecolfunc; } +/* R_ProjectSprite + * Generates a vissprite for a thing if it might be visible. + */ - -// -// R_ProjectSprite -// Generates a vissprite for a thing -// if it might be visible. -// -void R_ProjectSprite (mobj_t* thing) +static void r_project_sprite(mobj_t *thing) { - fixed_t tr_x; - fixed_t tr_y; - - fixed_t gxt; - fixed_t gyt; - - fixed_t tx; - fixed_t tz; - - fixed_t xscale; - - int x1; - int x2; - - spritedef_t* sprdef; - spriteframe_t* sprframe; - int lump; - - unsigned rot; - boolean flip; - - int index; - - vissprite_t* vis; - - angle_t ang; - fixed_t iscale; - - // transform the origin point - tr_x = thing->x - viewx; - tr_y = thing->y - viewy; - - gxt = FixedMul(tr_x,viewcos); - gyt = -FixedMul(tr_y,viewsin); - - tz = gxt-gyt; - - // thing is behind view plane? - if (tz < MINZ) - return; - - xscale = FixedDiv(projection, tz); - - gxt = -FixedMul(tr_x,viewsin); - gyt = FixedMul(tr_y,viewcos); - tx = -(gyt+gxt); - - // too far off the side? - if (abs(tx)>(tz<<2)) - return; - - // decide which patch to use for sprite relative to player -#ifdef RANGECHECK - if ((unsigned int) thing->sprite >= (unsigned int) numsprites) - I_Error ("R_ProjectSprite: invalid sprite number %i ", - thing->sprite); + fixed_t tr_x; + fixed_t tr_y; + + fixed_t gxt; + fixed_t gyt; + + fixed_t tx; + fixed_t tz; + + fixed_t xscale; + + int x1; + int x2; + + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + + unsigned rot; + boolean flip; + + int index; + + vissprite_t *vis; + + angle_t ang; + fixed_t iscale; + + /* transform the origin point */ + + tr_x = thing->x - viewx; + tr_y = thing->y - viewy; + + gxt = fixed_mul(tr_x, viewcos); + gyt = -fixed_mul(tr_y, viewsin); + + tz = gxt - gyt; + + /* thing is behind view plane? */ + + if (tz < MINZ) return; + + xscale = fixed_div(projection, tz); + + gxt = -fixed_mul(tr_x, viewsin); + gyt = fixed_mul(tr_y, viewcos); + tx = -(gyt + gxt); + + /* too far off the side? */ + + if (abs(tx) > (tz << 2)) return; + + /* decide which patch to use for sprite relative to player */ + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned int)thing->sprite >= (unsigned int)numsprites) + i_error("R_ProjectSprite: invalid sprite number %i ", thing->sprite); #endif - sprdef = &sprites[thing->sprite]; -#ifdef RANGECHECK - if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) - I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", - thing->sprite, thing->frame); + sprdef = &sprites[thing->sprite]; +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((thing->frame & FF_FRAMEMASK) >= sprdef->numframes) + i_error("R_ProjectSprite: invalid sprite frame %i : %i ", thing->sprite, + thing->frame); #endif - sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; - if (sprframe->rotate) + if (sprframe->rotate) { - // choose a different rotation based on player view - ang = R_PointToAngle (thing->x, thing->y); - rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; - lump = sprframe->lump[rot]; - flip = (boolean)sprframe->flip[rot]; + /* choose a different rotation based on player view */ + + ang = r_point_to_angle(thing->x, thing->y); + rot = (ang - thing->angle + (unsigned)(ANG45 / 2) * 9) >> 29; + lump = sprframe->lump[rot]; + flip = (boolean)sprframe->flip[rot]; } - else + else { - // use single rotation for all views - lump = sprframe->lump[0]; - flip = (boolean)sprframe->flip[0]; + /* use single rotation for all views */ + + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; } - - // calculate edges of the shape - tx -= spriteoffset[lump]; - x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; - // off the right side? - if (x1 > viewwidth) - return; - - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; + /* calculate edges of the shape */ + + tx -= spriteoffset[lump]; + x1 = (centerxfrac + fixed_mul(tx, xscale)) >> FRACBITS; + + /* off the right side? */ + + if (x1 > viewwidth) return; - // off the left side - if (x2 < 0) - return; - - // store information in a vissprite - vis = R_NewVisSprite (); - vis->mobjflags = thing->flags; - vis->scale = xscale<gx = thing->x; - vis->gy = thing->y; - vis->gz = thing->z; - vis->gzt = thing->z + spritetopoffset[lump]; - vis->texturemid = vis->gzt - viewz; - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - iscale = FixedDiv (FRACUNIT, xscale); + tx += spritewidth[lump]; + x2 = ((centerxfrac + fixed_mul(tx, xscale)) >> FRACBITS) - 1; - if (flip) + /* off the left side */ + + if (x2 < 0) return; + + /* store information in a vissprite */ + + vis = r_new_vis_sprite(); + vis->mobjflags = thing->flags; + vis->scale = xscale << detailshift; + vis->gx = thing->x; + vis->gy = thing->y; + vis->gz = thing->z; + vis->gzt = thing->z + spritetopoffset[lump]; + vis->texturemid = vis->gzt - viewz; + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + iscale = fixed_div(FRACUNIT, xscale); + + if (flip) { - vis->startfrac = spritewidth[lump]-1; - vis->xiscale = -iscale; + vis->startfrac = spritewidth[lump] - 1; + vis->xiscale = -iscale; } - else + else { - vis->startfrac = 0; - vis->xiscale = iscale; + vis->startfrac = 0; + vis->xiscale = iscale; } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale*(vis->x1-x1); - vis->patch = lump; - - // get light level - if (thing->flags & MF_SHADOW) + if (vis->x1 > x1) vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->patch = lump; + + /* get light level */ + + if (thing->flags & MF_SHADOW) { - // shadow draw - vis->colormap = NULL; + /* shadow draw */ + + vis->colormap = NULL; } - else if (fixedcolormap) + else if (fixedcolormap) { - // fixed map - vis->colormap = fixedcolormap; + /* fixed map */ + + vis->colormap = fixedcolormap; } - else if (thing->frame & FF_FULLBRIGHT) + else if (thing->frame & FF_FULLBRIGHT) { - // full bright - vis->colormap = colormaps; + /* full bright */ + + vis->colormap = colormaps; } - - else + + else { - // diminished light - index = xscale>>(LIGHTSCALESHIFT-detailshift); + /* diminished light */ - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE-1; + index = xscale >> (LIGHTSCALESHIFT - detailshift); - vis->colormap = spritelights[index]; - } + if (index >= MAXLIGHTSCALE) index = MAXLIGHTSCALE - 1; + + vis->colormap = spritelights[index]; + } } +/* R_DrawPSprite */ +static void r_draw_psprite(pspdef_t *psp) +{ + fixed_t tx; + int x1; + int x2; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + boolean flip; + vissprite_t *vis; + vissprite_t avis; + + /* decide which patch to use */ + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((unsigned)psp->state->sprite >= (unsigned int)numsprites) + { + i_error("R_ProjectSprite: invalid sprite number %i ", + psp->state->sprite); + } +#endif -// -// R_AddSprites -// During BSP traversal, this adds sprites by sector. -// -void R_AddSprites (sector_t* sec) -{ - mobj_t* thing; - int lightnum; - - // BSP is traversed by subsector. - // A sector might have been split into several - // subsectors during BSP building. - // Thus we check whether its already added. - if (sec->validcount == validcount) - return; - - // Well, now it will be done. - sec->validcount = validcount; - - lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; - else - spritelights = scalelight[lightnum]; - - // Handle all things in sector. - for (thing = sec->thinglist ; thing ; thing = thing->snext) - R_ProjectSprite (thing); -} + sprdef = &sprites[psp->state->sprite]; +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if ((psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) + { + i_error("R_ProjectSprite: invalid sprite frame %i : %i ", + psp->state->sprite, psp->state->frame); + } -// -// R_DrawPSprite -// -void R_DrawPSprite (pspdef_t* psp) -{ - fixed_t tx; - int x1; - int x2; - spritedef_t* sprdef; - spriteframe_t* sprframe; - int lump; - boolean flip; - vissprite_t* vis; - vissprite_t avis; - - // decide which patch to use -#ifdef RANGECHECK - if ( (unsigned)psp->state->sprite >= (unsigned int) numsprites) - I_Error ("R_ProjectSprite: invalid sprite number %i ", - psp->state->sprite); #endif - sprdef = &sprites[psp->state->sprite]; -#ifdef RANGECHECK - if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) - I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", - psp->state->sprite, psp->state->frame); -#endif - sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; + sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; + + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + + /* calculate edges of the shape */ + + tx = psp->sx - (SCREENWIDTH / 2) * FRACUNIT; + + tx -= spriteoffset[lump]; + x1 = (centerxfrac + fixed_mul(tx, pspritescale)) >> FRACBITS; - lump = sprframe->lump[0]; - flip = (boolean)sprframe->flip[0]; - - // calculate edges of the shape - tx = psp->sx-(SCREENWIDTH/2)*FRACUNIT; - - tx -= spriteoffset[lump]; - x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; + /* off the right side */ - // off the right side - if (x1 > viewwidth) - return; + if (x1 > viewwidth) return; - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; + tx += spritewidth[lump]; + x2 = ((centerxfrac + fixed_mul(tx, pspritescale)) >> FRACBITS) - 1; - // off the left side - if (x2 < 0) - return; - - // store information in a vissprite - vis = &avis; - vis->mobjflags = 0; - vis->texturemid = (BASEYCENTER<sy-spritetopoffset[lump]); - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - vis->scale = pspritescale<mobjflags = 0; + vis->texturemid = (BASEYCENTER << FRACBITS) + FRACUNIT / 2 - + (psp->sy - spritetopoffset[lump]); + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + vis->scale = pspritescale << detailshift; + + if (flip) { - vis->xiscale = -pspriteiscale; - vis->startfrac = spritewidth[lump]-1; + vis->xiscale = -pspriteiscale; + vis->startfrac = spritewidth[lump] - 1; } - else + else { - vis->xiscale = pspriteiscale; - vis->startfrac = 0; + vis->xiscale = pspriteiscale; + vis->startfrac = 0; } - - if (vis->x1 > x1) - vis->startfrac += vis->xiscale*(vis->x1-x1); - vis->patch = lump; + if (vis->x1 > x1) vis->startfrac += vis->xiscale * (vis->x1 - x1); + + vis->patch = lump; - if (viewplayer->powers[pw_invisibility] > 4*32 - || viewplayer->powers[pw_invisibility] & 8) + if (viewplayer->powers[pw_invisibility] > 4 * 32 || + viewplayer->powers[pw_invisibility] & 8) { - // shadow draw - vis->colormap = NULL; + vis->colormap = NULL; /* shadow draw */ } - else if (fixedcolormap) + else if (fixedcolormap) { - // fixed color - vis->colormap = fixedcolormap; + vis->colormap = fixedcolormap; /* fixed color */ } - else if (psp->state->frame & FF_FULLBRIGHT) + else if (psp->state->frame & FF_FULLBRIGHT) { - // full bright - vis->colormap = colormaps; + vis->colormap = colormaps; /* full bright */ } - else + else { - // local light - vis->colormap = spritelights[MAXLIGHTSCALE-1]; + vis->colormap = spritelights[MAXLIGHTSCALE - 1]; /* local light */ } - - R_DrawVisSprite (vis, vis->x1, vis->x2); + + r_draw_vis_sprite(vis, vis->x1, vis->x2); } +static void r_draw_player_sprites(void) +{ + int i; + int lightnum; + pspdef_t *psp; + /* get light level */ -// -// R_DrawPlayerSprites -// -void R_DrawPlayerSprites (void) -{ - int i; - int lightnum; - pspdef_t* psp; - - // get light level - lightnum = - (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) - +extralight; - - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; - else - spritelights = scalelight[lightnum]; - - // clip to screen bounds - mfloorclip = screenheightarray; - mceilingclip = negonearray; - - // add all active psprites - for (i=0, psp=viewplayer->psprites; - istate) - R_DrawPSprite (psp); + lightnum = + (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + + extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; + + /* clip to screen bounds */ + + mfloorclip = screenheightarray; + mceilingclip = negonearray; + + /* add all active psprites */ + + for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; i++, psp++) + { + if (psp->state) r_draw_psprite(psp); } } +static void r_sort_vis_sprites(void) +{ + int i; + int count; + vissprite_t *ds; + vissprite_t *best; + static vissprite_t unsorted; + fixed_t bestscale; + count = vissprite_p - vissprites; + unsorted.next = unsorted.prev = &unsorted; -// -// R_SortVisSprites -// -vissprite_t vsprsortedhead; + if (!count) return; + for (ds = vissprites; ds < vissprite_p; ds++) + { + ds->next = ds + 1; + ds->prev = ds - 1; + } + + vissprites[0].prev = &unsorted; + unsorted.next = &vissprites[0]; + (vissprite_p - 1)->next = &unsorted; + unsorted.prev = vissprite_p - 1; + + /* pull the vissprites out by scale */ -void R_SortVisSprites (void) + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i = 0; i < count; i++) + { + bestscale = INT_MAX; + best = unsorted.next; + + for (ds = unsorted.next; ds != &unsorted; ds = ds->next) + { + if (ds->scale < bestscale) + { + bestscale = ds->scale; + best = ds; + } + } + + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; + } +} + +static void r_draw_sprite(vissprite_t *spr) { - int i; - int count; - vissprite_t* ds; - vissprite_t* best; - static vissprite_t unsorted; - fixed_t bestscale; - - count = vissprite_p - vissprites; - - unsorted.next = unsorted.prev = &unsorted; - - if (!count) - return; - - for (ds=vissprites ; dsnext = ds+1; - ds->prev = ds-1; - } - - vissprites[0].prev = &unsorted; - unsorted.next = &vissprites[0]; - (vissprite_p-1)->next = &unsorted; - unsorted.prev = vissprite_p-1; - - // pull the vissprites out by scale - - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i=0 ; inext) - { - if (ds->scale < bestscale) - { - bestscale = ds->scale; - best = ds; - } - } - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; + drawseg_t *ds; + short clipbot[SCREENWIDTH]; + short cliptop[SCREENWIDTH]; + int x; + int r1; + int r2; + fixed_t scale; + fixed_t lowscale; + int silhouette; + + for (x = spr->x1; x <= spr->x2; x++) + clipbot[x] = cliptop[x] = -2; + + /* Scan drawsegs from end to start for obscuring segs. + * The first drawseg that has a greater scale is the clip seg. + */ + + for (ds = ds_p - 1; ds >= drawsegs; ds--) + { + /* determine if the drawseg obscures the sprite */ + + if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || + (!ds->silhouette && !ds->maskedtexturecol)) + { + continue; /* does not cover sprite */ + } + + r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; + r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->scale || + (lowscale < spr->scale && + !r_point_on_seg_side(spr->gx, spr->gy, ds->curline))) + { + /* masked mid texture? */ + + if (ds->maskedtexturecol) r_render_masked_seg_range(ds, r1, r2); + continue; /* seg is behind sprite */ + } + + /* clip this piece of the sprite */ + + silhouette = ds->silhouette; + + if (spr->gz >= ds->bsilheight) silhouette &= ~SIL_BOTTOM; + + if (spr->gzt <= ds->tsilheight) silhouette &= ~SIL_TOP; + + if (silhouette == 1) + { + /* bottom sil */ + + for (x = r1; x <= r2; x++) + { + if (clipbot[x] == -2) clipbot[x] = ds->sprbottomclip[x]; + } + } + else if (silhouette == 2) + { + /* top sil */ + + for (x = r1; x <= r2; x++) + { + if (cliptop[x] == -2) cliptop[x] = ds->sprtopclip[x]; + } + } + else if (silhouette == 3) + { + /* both */ + + for (x = r1; x <= r2; x++) + { + if (clipbot[x] == -2) clipbot[x] = ds->sprbottomclip[x]; + if (cliptop[x] == -2) cliptop[x] = ds->sprtopclip[x]; + } + } + } + + /* all clipping has been performed, so draw the sprite */ + + /* check for unclipped columns */ + + for (x = spr->x1; x <= spr->x2; x++) + { + if (clipbot[x] == -2) clipbot[x] = viewheight; + + if (cliptop[x] == -2) cliptop[x] = -1; } + + mfloorclip = clipbot; + mceilingclip = cliptop; + r_draw_vis_sprite(spr, spr->x1, spr->x2); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/* r_init_sprites + * Called at program start. + */ -// -// R_DrawSprite -// -void R_DrawSprite (vissprite_t* spr) +void r_init_sprites(const char **namelist) { - drawseg_t* ds; - short clipbot[SCREENWIDTH]; - short cliptop[SCREENWIDTH]; - int x; - int r1; - int r2; - fixed_t scale; - fixed_t lowscale; - int silhouette; - - for (x = spr->x1 ; x<=spr->x2 ; x++) - clipbot[x] = cliptop[x] = -2; - - // Scan drawsegs from end to start for obscuring segs. - // The first drawseg that has a greater scale - // is the clip seg. - for (ds=ds_p-1 ; ds >= drawsegs ; ds--) - { - // determine if the drawseg obscures the sprite - if (ds->x1 > spr->x2 - || ds->x2 < spr->x1 - || (!ds->silhouette - && !ds->maskedtexturecol) ) - { - // does not cover sprite - continue; - } - - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->scale - || ( lowscale < spr->scale - && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) - { - // masked mid texture? - if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2); - // seg is behind sprite - continue; - } - - - // clip this piece of the sprite - silhouette = ds->silhouette; - - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; - - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; - - if (silhouette == 1) - { - // bottom sil - for (x=r1 ; x<=r2 ; x++) - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == 2) - { - // top sil - for (x=r1 ; x<=r2 ; x++) - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == 3) - { - // both - for (x=r1 ; x<=r2 ; x++) - { - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - } - - } - - // all clipping has been performed, so draw the sprite - - // check for unclipped columns - for (x = spr->x1 ; x<=spr->x2 ; x++) - { - if (clipbot[x] == -2) - clipbot[x] = viewheight; - - if (cliptop[x] == -2) - cliptop[x] = -1; - } - - mfloorclip = clipbot; - mceilingclip = cliptop; - R_DrawVisSprite (spr, spr->x1, spr->x2); + int i; + + for (i = 0; i < SCREENWIDTH; i++) + { + negonearray[i] = -1; + } + + r_init_sprite_defs(namelist); } +/* Called at frame start. */ + +void r_clear_sprites(void) +{ + vissprite_p = vissprites; +} + +/* r_draw_masked_column + * Used for sprites and masked mid textures. + * Masked means: partly transparent, i.e. stored in posts/runs of opaque + * pixels. + */ + +void r_draw_masked_column(column_t *column) +{ + int topscreen; + int bottomscreen; + fixed_t basetexturemid; + + basetexturemid = dc_texturemid; + + for (; column->topdelta != 0xff; ) + { + /* calculate unclipped screen coordinates for post */ + + topscreen = sprtopscreen + spryscale * column->topdelta; + bottomscreen = topscreen + spryscale * column->length; + + dc_yl = (topscreen + FRACUNIT - 1) >> FRACBITS; + dc_yh = (bottomscreen - 1) >> FRACBITS; + + if (dc_yh >= mfloorclip[dc_x]) dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yl <= dc_yh) + { + dc_source = (byte *)column + 3; + dc_texturemid = basetexturemid - (column->topdelta << FRACBITS); + + /* Drawn by either r_draw_column or (SHADOW) r_draw_fuzz_column. + */ + + colfunc(); + } + + column = (column_t *)((byte *)column + column->length + 4); + } + dc_texturemid = basetexturemid; +} +/* r_add_sprites + * During BSP traversal, this adds sprites by sector. + */ -// -// R_DrawMasked -// -void R_DrawMasked (void) +void r_add_sprites(sector_t *sec) { - vissprite_t* spr; - drawseg_t* ds; - - R_SortVisSprites (); - - if (vissprite_p > vissprites) - { - // draw all vissprites back to front - for (spr = vsprsortedhead.next ; - spr != &vsprsortedhead ; - spr=spr->next) - { - - R_DrawSprite (spr); - } - } - - // render any remaining masked mid textures - for (ds=ds_p-1 ; ds >= drawsegs ; ds--) - if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, ds->x1, ds->x2); - - // draw the psprites on top of everything - // but does not draw on side views - if (!viewangleoffset) - R_DrawPlayerSprites (); + mobj_t *thing; + int lightnum; + + /* BSP is traversed by subsector. + * A sector might have been split into several subsectors during BSP + * building. Thus we check whether its already added. + */ + + if (sec->validcount == validcount) return; + + /* Well, now it will be done. */ + + sec->validcount = validcount; + + lightnum = (sec->lightlevel >> LIGHTSEGSHIFT) + extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; + + /* Handle all things in sector. */ + + for (thing = sec->thinglist; thing; thing = thing->snext) + r_project_sprite(thing); } +void r_draw_masked(void) +{ + vissprite_t *spr; + drawseg_t *ds; + r_sort_vis_sprites(); + if (vissprite_p > vissprites) + { + /* draw all vissprites back to front */ + + for (spr = vsprsortedhead.next; + spr != &vsprsortedhead; + spr = spr->next) + { + r_draw_sprite(spr); + } + } + + /* render any remaining masked mid textures */ + + for (ds = ds_p - 1; ds >= drawsegs; ds--) + { + if (ds->maskedtexturecol) + { + r_render_masked_seg_range(ds, ds->x1, ds->x2); + } + } + + /* draw the psprites on top of everything but does not draw on side views + */ + + if (!viewangleoffset) + { + r_draw_player_sprites(); + } +} diff --git a/games/NXDoom/src/doom/r_things.h b/games/NXDoom/src/doom/r_things.h index fc51c34a4eb..cdd29948368 100644 --- a/games/NXDoom/src/doom/r_things.h +++ b/games/NXDoom/src/doom/r_things.h @@ -1,65 +1,61 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Rendering of moving objects, sprites. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/r_things.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Rendering of moving objects, sprites. + * + ****************************************************************************/ #ifndef __R_THINGS__ #define __R_THINGS__ +/**************************************************************************** + * Public Data + ****************************************************************************/ +extern vissprite_t vissprites[CONFIG_GAMES_NXDOOM_MAXVISSPRITES]; +extern vissprite_t *vissprite_p; +extern vissprite_t vsprsortedhead; -#define MAXVISSPRITES 128 - -extern vissprite_t vissprites[MAXVISSPRITES]; -extern vissprite_t* vissprite_p; -extern vissprite_t vsprsortedhead; - -// Constant arrays used for psprite clipping -// and initializing clipping. -extern short negonearray[SCREENWIDTH]; -extern short screenheightarray[SCREENWIDTH]; - -// vars for R_DrawMaskedColumn -extern short* mfloorclip; -extern short* mceilingclip; -extern fixed_t spryscale; -extern fixed_t sprtopscreen; - -extern fixed_t pspritescale; -extern fixed_t pspriteiscale; +/* Constant arrays used for psprite clipping and initializing clipping. */ +extern short negonearray[SCREENWIDTH]; +extern short screenheightarray[SCREENWIDTH]; -void R_DrawMaskedColumn (column_t* column); +/* vars for r_draw_masked_column */ +extern short *mfloorclip; +extern short *mceilingclip; +extern fixed_t spryscale; +extern fixed_t sprtopscreen; -void R_SortVisSprites (void); +extern fixed_t pspritescale; +extern fixed_t pspriteiscale; -void R_AddSprites (sector_t* sec); -void R_AddPSprites (void); -void R_DrawSprites (void); -void R_InitSprites(const char **namelist); -void R_ClearSprites (void); -void R_DrawMasked (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void -R_ClipVisSprite -( vissprite_t* vis, - int xl, - int xh ); +void r_draw_masked_column(column_t *column); +void r_add_sprites(sector_t *sec); +void r_init_sprites(const char **namelist); +void r_clear_sprites(void); +void r_draw_masked(void); -#endif +#endif /* __R_THINGS__ */ diff --git a/games/NXDoom/src/doom/s_sound.c b/games/NXDoom/src/doom/s_sound.c index 76748892ab9..dbca08a5748 100644 --- a/games/NXDoom/src/doom/s_sound.c +++ b/games/NXDoom/src/doom/s_sound.c @@ -1,19 +1,28 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/s_sound.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: none + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -26,699 +35,737 @@ #include "doomstat.h" #include "doomtype.h" -#include "sounds.h" #include "s_sound.h" +#include "sounds.h" +#include "m_argv.h" #include "m_misc.h" #include "m_random.h" -#include "m_argv.h" #include "p_local.h" #include "w_wad.h" #include "z_zone.h" -// when to clip out sounds -// Does not fit the large outdoor areas. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* when to clip out sounds + * Does not fit the large outdoor areas. + */ #define S_CLIPPING_DIST (1200 * FRACUNIT) -// Distance tp origin when sounds should be maxed out. -// This should relate to movement clipping resolution -// (see BLOCKMAP handling). -// In the source code release: (160*FRACUNIT). Changed back to the -// Vanilla value of 200 (why was this changed?) +/* Distance tp origin when sounds should be maxed out. + * This should relate to movement clipping resolution + * (see BLOCKMAP handling). + * In the source code release: (160*FRACUNIT). Changed back to the + * Vanilla value of 200 (why was this changed?) + */ #define S_CLOSE_DIST (200 * FRACUNIT) -// The range over which sound attenuates +/* The range over which sound attenuates */ #define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS) -// Stereo separation +/* Stereo separation */ #define S_STEREO_SWING (96 * FRACUNIT) #define NORM_PRIORITY 64 #define NORM_SEP 128 +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef struct { - // sound information (if null, channel avail.) - sfxinfo_t *sfxinfo; + /* sound information (if null, channel avail.) */ + + sfxinfo_t *sfxinfo; + + /* origin of sound */ - // origin of sound - mobj_t *origin; + mobj_t *origin; - // handle of the sound being played - int handle; + /* handle of the sound being played */ - int pitch; + int handle; + int pitch; } channel_t; -// The set of channels available +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The set of channels available */ static channel_t *channels; -// Maximum volume of a sound effect. -// Internal default is max out of 0-15. +/* Internal volume level, ranging from 0-127 */ -int sfxVolume = 8; +static int g_snd_sfx_volume; -// Maximum volume of music. +/* Whether songs are mus_paused */ -int musicVolume = 8; +static boolean mus_paused; -// Internal volume level, ranging from 0-127 +/* Music currently being played */ -static int snd_SfxVolume; +static musicinfo_t *mus_playing = NULL; -// Whether songs are mus_paused +/**************************************************************************** + * Public Data + ****************************************************************************/ -static boolean mus_paused; +/* Maximum volume of a sound effect. + * Internal default is max out of 0-15. + */ -// Music currently being played +int g_sfx_volume = 8; -static musicinfo_t *mus_playing = NULL; +/* Maximum volume of music. */ -// Number of channels to use +int g_music_volume = 8; + +/* Number of channels to use */ int snd_channels = 8; -// -// Initializes sound stuff, including volume -// Sets channels, SFX and music volume, -// allocates channel buffer, sets S_sfx lookup. -// +/**************************************************************************** + * Private Functions + ****************************************************************************/ -void S_Init(int sfxVolume, int musicVolume) +static void s_stop_channel(int cnum) { - int i; + int i; + channel_t *c; + + c = &channels[cnum]; - if (gameversion == exe_doom_1_666) + if (c->sfxinfo) { - if (logical_gamemission == doom) + /* stop the sound playing */ + + if (i_sound_playing(c->handle)) { - I_SetOPLDriverVer(opl_doom1_1_666); + i_stop_sound(c->handle); } - else + + /* check to see if other channels are playing the sound */ + + for (i = 0; i < snd_channels; i++) { - I_SetOPLDriverVer(opl_doom2_1_666); + if (cnum != i && c->sfxinfo == channels[i].sfxinfo) + { + break; + } } + + /* degrade usefulness of sound data */ + + c->sfxinfo->usefulness--; + c->sfxinfo = NULL; + c->origin = NULL; } - else - { - I_SetOPLDriverVer(opl_doom_1_9); - } +} - I_PrecacheSounds(S_sfx, NUMSFX); +/* S_GetChannel: If none available, return -1. Otherwise channel #. */ - S_SetSfxVolume(sfxVolume); - S_SetMusicVolume(musicVolume); +static int s_get_channel(mobj_t *origin, sfxinfo_t *sfxinfo) +{ + /* channel number to use */ - // Allocating the internal channels for mixing - // (the maximum numer of sounds rendered - // simultaneously) within zone memory. - channels = Z_Malloc(snd_channels*sizeof(channel_t), PU_STATIC, 0); + int cnum; - // Free all channels for use - for (i=0 ; ipriority >= sfxinfo->priority) + { + break; + } + } + + if (cnum == snd_channels) + { + /* FUCK! No lower priority. Sorry, Charlie. */ + + return -1; + } + else + { + /* Otherwise, kick out lower priority. */ + + s_stop_channel(cnum); + } } - I_AtExit(S_Shutdown, true); -} + c = &channels[cnum]; -void S_Shutdown(void) -{ - I_ShutdownSound(); - I_ShutdownMusic(); + /* channel is decided to be cnum. */ + + c->sfxinfo = sfxinfo; + c->origin = origin; + + return cnum; } -static void S_StopChannel(int cnum) +/* Changes volume and stereo-separation variables from the norm of a sound + * effect to be played. If the sound is not audible, returns a 0. Otherwise, + * modifies parameters and returns 1. + */ + +static int s_adjust_sound_params(mobj_t *listener, mobj_t *source, int *vol, + int *sep) { - int i; - channel_t *c; + fixed_t approx_dist; + fixed_t adx; + fixed_t ady; + angle_t angle; - c = &channels[cnum]; + /* calculate the distance to sound origin and clip it if necessary */ - if (c->sfxinfo) - { - // stop the sound playing + adx = abs(listener->x - source->x); + ady = abs(listener->y - source->y); - if (I_SoundIsPlaying(c->handle)) - { - I_StopSound(c->handle); - } + /* From _GG1_ p.428. Appox. Euclidean distance fast. */ - // check to see if other channels are playing the sound + approx_dist = adx + ady - ((adx < ady ? adx : ady) >> 1); - for (i=0; isfxinfo == channels[i].sfxinfo) - { - break; - } - } + if (gamemap != 8 && approx_dist > S_CLIPPING_DIST) + { + return 0; + } - // degrade usefulness of sound data + /* angle of source to listener */ - c->sfxinfo->usefulness--; - c->sfxinfo = NULL; - c->origin = NULL; + angle = r_point_to_angle2(listener->x, listener->y, source->x, source->y); + + if (angle > listener->angle) + { + angle = angle - listener->angle; + } + else + { + angle = angle + (0xffffffff - listener->angle); } -} -// -// Per level startup code. -// Kills playing sounds at start of level, -// determines music if any, changes music. -// + angle >>= ANGLETOFINESHIFT; -void S_Start(void) -{ - int cnum; - int mnum; + /* stereo separation */ - // kill all playing sounds at start of level - // (trust me - a good idea) - for (cnum=0 ; cnum> FRACBITS); + + /* volume calculation */ + + if (approx_dist < S_CLOSE_DIST) { - if (channels[cnum].sfxinfo) + *vol = g_snd_sfx_volume; + } + else if (gamemap == 8) + { + if (approx_dist > S_CLIPPING_DIST) { - S_StopChannel(cnum); + approx_dist = S_CLIPPING_DIST; } + + *vol = 15 + ((g_snd_sfx_volume - 15) * + ((S_CLIPPING_DIST - approx_dist) >> FRACBITS)) / + S_ATTENUATOR; + } + else + { + /* distance effect */ + + *vol = (g_snd_sfx_volume * + ((S_CLIPPING_DIST - approx_dist) >> FRACBITS) + ) / S_ATTENUATOR; } - // start new music for the level - mus_paused = 0; + return (*vol > 0); +} - if (gamemode == commercial) +/* clamp supplied integer to the range 0 <= x <= 255. */ + +static int clamp(int x) +{ + if (x < 0) { - mnum = mus_runnin + gamemap - 1; + return 0; } - else + else if (x > 255) { - int spmus[]= - { - // Song - Who? - Where? - - mus_e3m4, // American e4m1 - mus_e3m2, // Romero e4m2 - mus_e3m3, // Shawn e4m3 - mus_e1m5, // American e4m4 - mus_e2m7, // Tim e4m5 - mus_e2m4, // Romero e4m6 - mus_e2m6, // J.Anderson e4m7 CHIRON.WAD - mus_e2m5, // Shawn e4m8 - mus_e1m9, // Tim e4m9 - }; - - if (gameepisode < 4) - { - mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1; - } - else - { - mnum = spmus[gamemap-1]; - } + return 255; } - S_ChangeMusic(mnum, true); + return x; } -void S_StopSound(mobj_t *origin) +static void s_shutdown(void) { - int cnum; + i_shutdown_sound(); + i_shutdown_music(); +} - for (cnum=0 ; cnumhandle); + w_release_lump_num(mus_playing->lumpnum); + mus_playing->data = NULL; + mus_playing = NULL; } } -// -// S_GetChannel : -// If none available, return -1. Otherwise channel #. -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ -static int S_GetChannel(mobj_t *origin, sfxinfo_t *sfxinfo) -{ - // channel number to use - int cnum; +/* Initializes sound stuff, including volume + * + * Sets channels, SFX and music volume, allocates channel buffer, sets s_sfx + * lookup. + */ - channel_t* c; +void s_init(int sfxvolume, int musicvolume) +{ + int i; - // Find an open channel - for (cnum=0 ; cnumpriority >= sfxinfo->priority) - { - break; - } - } - - if (cnum == snd_channels) - { - // FUCK! No lower priority. Sorry, Charlie. - return -1; - } - else - { - // Otherwise, kick out lower priority. - S_StopChannel(cnum); - } + i_set_opl_driver_ver(opl_doom_1_9); } +#endif - c = &channels[cnum]; + i_precache_sounds(s_sfx, SFX_NUMSFX); - // channel is decided to be cnum. - c->sfxinfo = sfxinfo; - c->origin = origin; + s_set_sfx_volume(sfxvolume); + s_set_music_volume(musicvolume); - return cnum; -} + /* Allocating the internal channels for mixing + * (the maximum number of sounds rendered + * simultaneously) within zone memory. + */ -// -// Changes volume and stereo-separation variables -// from the norm of a sound effect to be played. -// If the sound is not audible, returns a 0. -// Otherwise, modifies parameters and returns 1. -// + channels = z_malloc(snd_channels * sizeof(channel_t), PU_STATIC, 0); -static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, - int *vol, int *sep) -{ - fixed_t approx_dist; - fixed_t adx; - fixed_t ady; - angle_t angle; + /* Free all channels for use */ + + for (i = 0; i < snd_channels; i++) + { + channels[i].sfxinfo = 0; + } + + /* no sounds are playing, and they are not mus_paused */ - // calculate the distance to sound origin - // and clip it if necessary - adx = abs(listener->x - source->x); - ady = abs(listener->y - source->y); + mus_paused = 0; - // From _GG1_ p.428. Appox. eucledian distance fast. - approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1); + /* Note that sounds have not been cached (yet). */ - if (gamemap != 8 && approx_dist > S_CLIPPING_DIST) + for (i = 1; i < SFX_NUMSFX; i++) { - return 0; + s_sfx[i].lumpnum = s_sfx[i].usefulness = -1; } - // angle of source to listener - angle = R_PointToAngle2(listener->x, - listener->y, - source->x, - source->y); + /* Doom defaults to pitch-shifting off. */ - if (angle > listener->angle) + if (snd_pitchshift == -1) { - angle = angle - listener->angle; + snd_pitchshift = 0; } - else + + i_at_exit(s_shutdown, true); +} + +/* Per level startup code. + * Kills playing sounds at start of level, determines music if any, changes + * music. + */ + +void s_start(void) +{ + int cnum; + int mnum; + + /* kill all playing sounds at start of level (trust me - a good idea) + */ + + for (cnum = 0; cnum < snd_channels; cnum++) { - angle = angle + (0xffffffff - listener->angle); + if (channels[cnum].sfxinfo) + { + s_stop_channel(cnum); + } } - angle >>= ANGLETOFINESHIFT; + /* start new music for the level */ - // stereo separation - *sep = 128 - (FixedMul(S_STEREO_SWING, finesine[angle]) >> FRACBITS); + mus_paused = 0; - // volume calculation - if (approx_dist < S_CLOSE_DIST) + if (gamemode == commercial) { - *vol = snd_SfxVolume; + mnum = MUS_RUNNIN + gamemap - 1; } - else if (gamemap == 8) + else { - if (approx_dist > S_CLIPPING_DIST) + int spmus[] = { + /* Song - Who? - Where? */ + + MUS_E3M4, /* American e4m1 */ + MUS_E3M2, /* Romero e4m2 */ + MUS_E3M3, /* Shawn e4m3 */ + MUS_E1M5, /* American e4m4 */ + MUS_E2M7, /* Tim e4m5 */ + MUS_E2M4, /* Romero e4m6 */ + MUS_E2M6, /* J.Anderson e4m7 CHIRON.WAD */ + MUS_E2M5, /* Shawn e4m8 */ + MUS_E1M9, /* Tim e4m9 */ + }; + + if (gameepisode < 4) { - approx_dist = S_CLIPPING_DIST; + mnum = MUS_E1M1 + (gameepisode - 1) * 9 + gamemap - 1; + } + else + { + mnum = spmus[gamemap - 1]; } - - *vol = 15+ ((snd_SfxVolume-15) - *((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) - / S_ATTENUATOR; - } - else - { - // distance effect - *vol = (snd_SfxVolume - * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) - / S_ATTENUATOR; } - return (*vol > 0); + s_change_music(mnum, true); } -// clamp supplied integer to the range 0 <= x <= 255. - -static int Clamp(int x) +void s_stop_sound(mobj_t *origin) { - if (x < 0) - { - return 0; - } - else if (x > 255) + int cnum; + + for (cnum = 0; cnum < snd_channels; cnum++) { - return 255; + if (channels[cnum].sfxinfo && channels[cnum].origin == origin) + { + s_stop_channel(cnum); + break; + } } - return x; } -void S_StartSound(void *origin_p, int sfx_id) +void s_start_sound(void *origin_p, int sfx_id) { - sfxinfo_t *sfx; - mobj_t *origin; - int rc; - int sep; - int pitch; - int cnum; - int volume; + sfxinfo_t *sfx; + mobj_t *origin; + int rc; + int sep; + int pitch; + int cnum; + int volume; + + origin = (mobj_t *)origin_p; + volume = g_snd_sfx_volume; - origin = (mobj_t *) origin_p; - volume = snd_SfxVolume; + /* check for bogus sound # */ - // check for bogus sound # - if (sfx_id < 1 || sfx_id > NUMSFX) + if (sfx_id < 1 || sfx_id > SFX_NUMSFX) { - I_Error("Bad sfx #: %d", sfx_id); + i_error("Bad sfx #: %d", sfx_id); } - sfx = &S_sfx[sfx_id]; + sfx = &s_sfx[sfx_id]; - // Initialize sound parameters - pitch = NORM_PITCH; - if (sfx->link) + /* Initialize sound parameters */ + + pitch = NORM_PITCH; + if (sfx->link) { - volume += sfx->volume; - pitch = sfx->pitch; + volume += sfx->volume; + pitch = sfx->pitch; - if (volume < 1) + if (volume < 1) { - return; + return; } - if (volume > snd_SfxVolume) + if (volume > g_snd_sfx_volume) { - volume = snd_SfxVolume; + volume = g_snd_sfx_volume; } } + /* Check to see if it is audible, and if not, modify the params */ - // Check to see if it is audible, - // and if not, modify the params - if (origin && origin != players[consoleplayer].mo) + if (origin && origin != players[consoleplayer].mo) { - rc = S_AdjustSoundParams(players[consoleplayer].mo, - origin, - &volume, + rc = s_adjust_sound_params(players[consoleplayer].mo, origin, &volume, &sep); - if (origin->x == players[consoleplayer].mo->x - && origin->y == players[consoleplayer].mo->y) + if (origin->x == players[consoleplayer].mo->x && + origin->y == players[consoleplayer].mo->y) { - sep = NORM_SEP; + sep = NORM_SEP; } - if (!rc) + if (!rc) { - return; + return; } } - else + else { - sep = NORM_SEP; + sep = NORM_SEP; } - // hacks to vary the sfx pitches - if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit) + /* hacks to vary the sfx pitches */ + + if (sfx_id >= SFX_SAWUP && sfx_id <= SFX_SAWHIT) { - pitch += 8 - (M_Random()&15); + pitch += 8 - (m_random() & 15); } - else if (sfx_id != sfx_itemup && sfx_id != sfx_tink) + else if (sfx_id != SFX_ITEMUP && sfx_id != SFX_TINK) { - pitch += 16 - (M_Random()&31); + pitch += 16 - (m_random() & 31); } - pitch = Clamp(pitch); - // kill old sound - S_StopSound(origin); + pitch = clamp(pitch); + + s_stop_sound(origin); /* kill old sound */ + + /* try to find a channel */ - // try to find a channel - cnum = S_GetChannel(origin, sfx); + cnum = s_get_channel(origin, sfx); - if (cnum < 0) + if (cnum < 0) { - return; + return; } - // increase the usefulness - if (sfx->usefulness++ < 0) + /* increase the usefulness */ + + if (sfx->usefulness++ < 0) { - sfx->usefulness = 1; + sfx->usefulness = 1; } - if (sfx->lumpnum < 0) + if (sfx->lumpnum < 0) { - sfx->lumpnum = I_GetSfxLumpNum(sfx); + sfx->lumpnum = i_get_sfx_lumpnum(sfx); } - channels[cnum].pitch = pitch; - channels[cnum].handle = I_StartSound(sfx, cnum, volume, sep, channels[cnum].pitch); + channels[cnum].pitch = pitch; + channels[cnum].handle = + i_start_sound(sfx, cnum, volume, sep, channels[cnum].pitch); } -// -// Stop and resume music, during game PAUSE. -// +/* Stop and resume music, during game PAUSE. */ -void S_PauseSound(void) +void s_pause_sound(void) { - if (mus_playing && !mus_paused) + if (mus_playing && !mus_paused) { - I_PauseSong(); - mus_paused = true; + i_pause_song(); + mus_paused = true; } } -void S_ResumeSound(void) +void s_resume_sound(void) { - if (mus_playing && mus_paused) + if (mus_playing && mus_paused) { - I_ResumeSong(); - mus_paused = false; + i_resume_song(); + mus_paused = false; } } -// -// Updates music & sounds -// +/* Updates music & sounds */ -void S_UpdateSounds(mobj_t *listener) +void s_update_sounds(mobj_t *listener) { - int audible; - int cnum; - int volume; - int sep; - sfxinfo_t* sfx; - channel_t* c; + int audible; + int cnum; + int volume; + int sep; + sfxinfo_t *sfx; + channel_t *c; - I_UpdateSound(); + i_update_sound(); - for (cnum=0; cnumsfxinfo; + c = &channels[cnum]; + sfx = c->sfxinfo; - if (c->sfxinfo) + if (c->sfxinfo) { - if (I_SoundIsPlaying(c->handle)) + if (i_sound_playing(c->handle)) { - // initialize parameters - volume = snd_SfxVolume; - sep = NORM_SEP; + /* initialize parameters */ + + volume = g_snd_sfx_volume; + sep = NORM_SEP; - if (sfx->link) + if (sfx->link) { - volume += sfx->volume; - if (volume < 1) + volume += sfx->volume; + if (volume < 1) { - S_StopChannel(cnum); - continue; + s_stop_channel(cnum); + continue; } - else if (volume > snd_SfxVolume) + else if (volume > g_snd_sfx_volume) { - volume = snd_SfxVolume; + volume = g_snd_sfx_volume; } } - // check non-local sounds for distance clipping - // or modify their params - if (c->origin && listener != c->origin) + /* check non-local sounds for distance clipping or modify their + * params + */ + + if (c->origin && listener != c->origin) { - audible = S_AdjustSoundParams(listener, - c->origin, - &volume, - &sep); + audible = s_adjust_sound_params(listener, c->origin, + &volume, &sep); - if (!audible) + if (!audible) { - S_StopChannel(cnum); + s_stop_channel(cnum); } - else + else { - I_UpdateSoundParams(c->handle, volume, sep); + i_update_sound_params(c->handle, volume, sep); } } } - else + else { - // if channel is allocated but sound has stopped, - // free it - S_StopChannel(cnum); + /* if channel is allocated but sound has stopped, free it + */ + + s_stop_channel(cnum); } } } } -void S_SetMusicVolume(int volume) +void s_set_music_volume(int volume) { - if (volume < 0 || volume > 127) + if (volume < 0 || volume > 127) { - I_Error("Attempt to set music volume at %d", - volume); + i_error("Attempt to set music volume at %d", volume); } - I_SetMusicVolume(volume); + i_set_music_volume(volume); } -void S_SetSfxVolume(int volume) +void s_set_sfx_volume(int volume) { - if (volume < 0 || volume > 127) + if (volume < 0 || volume > 127) { - I_Error("Attempt to set sfx volume at %d", volume); + i_error("Attempt to set sfx volume at %d", volume); } - snd_SfxVolume = volume; + g_snd_sfx_volume = volume; } -// -// Starts some music with the music id found in sounds.h. -// +/* Starts some music with the music id found in sounds.h. */ -void S_StartMusic(int m_id) +void s_start_music(int m_id) { - S_ChangeMusic(m_id, false); + s_change_music(m_id, false); } -void S_ChangeMusic(int musicnum, int looping) +void s_change_music(int musicnum, int looping) { - musicinfo_t *music = NULL; - char namebuf[9]; - void *handle; + musicinfo_t *music = NULL; + char namebuf[9]; + void *handle; - // The Doom IWAD file has two versions of the intro music: d_intro - // and d_introa. The latter is used for OPL playback. + /* The Doom IWAD file has two versions of the intro music: d_intro + * and d_introa. The latter is used for OPL playback. + */ - if (musicnum == mus_intro && (snd_musicdevice == SNDDEVICE_ADLIB - || snd_musicdevice == SNDDEVICE_SB) - && W_CheckNumForName("D_INTROA") >= 0) + if (musicnum == MUS_INTRO && + (snd_musicdevice == SNDDEVICE_ADLIB || + snd_musicdevice == SNDDEVICE_SB) && + w_check_num_for_name("D_INTROA") >= 0) { - musicnum = mus_introa; + musicnum = MUS_INTROA; } - if (musicnum <= mus_None || musicnum >= NUMMUSIC) + if (musicnum <= MUS_NONE || musicnum >= MUS_NUMMUSIC) { - I_Error("Bad music number %d", musicnum); + i_error("Bad music number %d", musicnum); } - else + else { - music = &S_music[musicnum]; + music = &s_music[musicnum]; } - if (mus_playing == music) + if (mus_playing == music) { - return; + return; } - // shutdown old music - S_StopMusic(); + /* shutdown old music */ - // get lumpnum if neccessary - if (!music->lumpnum) - { - M_snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name)); - music->lumpnum = W_GetNumForName(namebuf); - } - - music->data = W_CacheLumpNum(music->lumpnum, PU_STATIC); + s_stop_music(); - handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum)); - music->handle = handle; - I_PlaySong(handle, looping); + /* get lumpnum if necessary */ - mus_playing = music; -} + if (!music->lumpnum) + { + snprintf(namebuf, sizeof(namebuf), "d_%s", (music->name)); + music->lumpnum = w_get_num_for_name(namebuf); + } -boolean S_MusicPlaying(void) -{ - return I_MusicIsPlaying(); -} + music->data = w_cache_lump_num(music->lumpnum, PU_STATIC); -void S_StopMusic(void) -{ - if (mus_playing) - { - if (mus_paused) - { - I_ResumeSong(); - } + handle = i_register_song(music->data, w_lump_length(music->lumpnum)); + music->handle = handle; + i_play_song(handle, looping); - I_StopSong(); - I_UnRegisterSong(mus_playing->handle); - W_ReleaseLumpNum(mus_playing->lumpnum); - mus_playing->data = NULL; - mus_playing = NULL; - } + mus_playing = music; } - diff --git a/games/NXDoom/src/doom/s_sound.h b/games/NXDoom/src/doom/s_sound.h index bbd100a0c35..21f569d9b2b 100644 --- a/games/NXDoom/src/doom/s_sound.h +++ b/games/NXDoom/src/doom/s_sound.h @@ -1,89 +1,86 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The not so system specific sound interface. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/s_sound.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * The not so system specific sound interface. + * + ****************************************************************************/ #ifndef __S_SOUND__ #define __S_SOUND__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "p_mobj.h" #include "sounds.h" -// -// Initializes sound stuff, including volume -// Sets channels, SFX and music volume, -// allocates channel buffer, sets S_sfx lookup. -// - -void S_Init(int sfxVolume, int musicVolume); - +/**************************************************************************** + * Public Data + ****************************************************************************/ -// Shut down sound - -void S_Shutdown(void); +extern int snd_channels; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/* Initializes sound stuff, including volume + * Sets channels, SFX and music volume, allocates channel buffer, sets s_sfx + * lookup. + */ -// -// Per level startup code. -// Kills playing sounds at start of level, -// determines music if any, changes music. -// +void s_init(int sfxvolume, int musicvolume); -void S_Start(void); +/* Per level startup code. + * Kills playing sounds at start of level, determines music if any, changes + * music. + */ -// -// Start sound for thing at -// using from sounds.h -// +void s_start(void); -void S_StartSound(void *origin, int sound_id); +/* Start sound for thing at using from sounds.h */ -// Stop sound for thing at -void S_StopSound(mobj_t *origin); +void s_start_sound(void *origin, int sound_id); +/* Stop sound for thing at */ -// Start music using from sounds.h -void S_StartMusic(int music_id); +void s_stop_sound(mobj_t *origin); -// Start music using from sounds.h, -// and set whether looping -void S_ChangeMusic(int music_id, int looping); +/* Start music using from sounds.h */ -// query if music is playing -boolean S_MusicPlaying(void); +void s_start_music(int music_id); -// Stops the music fer sure. -void S_StopMusic(void); +/* Start music using from sounds.h, and set whether looping */ -// Stop and resume music, during game PAUSE. -void S_PauseSound(void); -void S_ResumeSound(void); +void s_change_music(int music_id, int looping); +/* Stop and resume music, during game PAUSE. */ -// -// Updates music & sounds -// -void S_UpdateSounds(mobj_t *listener); +void s_pause_sound(void); +void s_resume_sound(void); -void S_SetMusicVolume(int volume); -void S_SetSfxVolume(int volume); +/* Updates music & sounds */ -extern int snd_channels; +void s_update_sounds(mobj_t *listener); -#endif +void s_set_music_volume(int volume); +void s_set_sfx_volume(int volume); +#endif /* __S_SOUND__ */ diff --git a/games/NXDoom/src/doom/sounds.c b/games/NXDoom/src/doom/sounds.c index e976bc84480..b1282cdb28f 100644 --- a/games/NXDoom/src/doom/sounds.c +++ b/games/NXDoom/src/doom/sounds.c @@ -1,132 +1,89 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Created by a sound utility. -// Kept as a sample, DOOM2 sounds. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/sounds.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Created by a sound utility. + * Kept as a sample, DOOM2 sounds. + * + ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ #include - #include "doomtype.h" #include "sounds.h" -// -// Information about all the music -// +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#define MUSIC(name) \ - { name, 0, NULL, NULL } +/* Information about all the music */ -musicinfo_t S_music[] = -{ - MUSIC(NULL), - MUSIC("e1m1"), - MUSIC("e1m2"), - MUSIC("e1m3"), - MUSIC("e1m4"), - MUSIC("e1m5"), - MUSIC("e1m6"), - MUSIC("e1m7"), - MUSIC("e1m8"), - MUSIC("e1m9"), - MUSIC("e2m1"), - MUSIC("e2m2"), - MUSIC("e2m3"), - MUSIC("e2m4"), - MUSIC("e2m5"), - MUSIC("e2m6"), - MUSIC("e2m7"), - MUSIC("e2m8"), - MUSIC("e2m9"), - MUSIC("e3m1"), - MUSIC("e3m2"), - MUSIC("e3m3"), - MUSIC("e3m4"), - MUSIC("e3m5"), - MUSIC("e3m6"), - MUSIC("e3m7"), - MUSIC("e3m8"), - MUSIC("e3m9"), - MUSIC("inter"), - MUSIC("intro"), - MUSIC("bunny"), - MUSIC("victor"), - MUSIC("introa"), - MUSIC("runnin"), - MUSIC("stalks"), - MUSIC("countd"), - MUSIC("betwee"), - MUSIC("doom"), - MUSIC("the_da"), - MUSIC("shawn"), - MUSIC("ddtblu"), - MUSIC("in_cit"), - MUSIC("dead"), - MUSIC("stlks2"), - MUSIC("theda2"), - MUSIC("doom2"), - MUSIC("ddtbl2"), - MUSIC("runni2"), - MUSIC("dead2"), - MUSIC("stlks3"), - MUSIC("romero"), - MUSIC("shawn2"), - MUSIC("messag"), - MUSIC("count2"), - MUSIC("ddtbl3"), - MUSIC("ampie"), - MUSIC("theda3"), - MUSIC("adrian"), - MUSIC("messg2"), - MUSIC("romer2"), - MUSIC("tense"), - MUSIC("shawn3"), - MUSIC("openin"), - MUSIC("evil"), - MUSIC("ultima"), - MUSIC("read_m"), - MUSIC("dm2ttl"), - MUSIC("dm2int") -}; +#define MUSIC(name) {name, 0, NULL, NULL} +/* Information about all the sfx */ -// -// Information about all the sfx -// +#define SOUND(name, priority) \ + {NULL, name, priority, NULL, -1, -1, 0, 0, -1, NULL} +#define SOUND_LINK(name, priority, link_id, pitch, volume) \ + {NULL, name, priority, &s_sfx[link_id], pitch, volume, 0, 0, -1, NULL} -#define SOUND(name, priority) \ - { NULL, name, priority, NULL, -1, -1, 0, 0, -1, NULL } -#define SOUND_LINK(name, priority, link_id, pitch, volume) \ - { NULL, name, priority, &S_sfx[link_id], pitch, volume, 0, 0, -1, NULL } +/**************************************************************************** + * Public Data + ****************************************************************************/ + +musicinfo_t s_music[] = +{ + MUSIC(NULL), MUSIC("e1m1"), MUSIC("e1m2"), MUSIC("e1m3"), + MUSIC("e1m4"), MUSIC("e1m5"), MUSIC("e1m6"), MUSIC("e1m7"), + MUSIC("e1m8"), MUSIC("e1m9"), MUSIC("e2m1"), MUSIC("e2m2"), + MUSIC("e2m3"), MUSIC("e2m4"), MUSIC("e2m5"), MUSIC("e2m6"), + MUSIC("e2m7"), MUSIC("e2m8"), MUSIC("e2m9"), MUSIC("e3m1"), + MUSIC("e3m2"), MUSIC("e3m3"), MUSIC("e3m4"), MUSIC("e3m5"), + MUSIC("e3m6"), MUSIC("e3m7"), MUSIC("e3m8"), MUSIC("e3m9"), + MUSIC("inter"), MUSIC("intro"), MUSIC("bunny"), MUSIC("victor"), + MUSIC("introa"), MUSIC("runnin"), MUSIC("stalks"), MUSIC("countd"), + MUSIC("betwee"), MUSIC("doom"), MUSIC("the_da"), MUSIC("shawn"), + MUSIC("ddtblu"), MUSIC("in_cit"), MUSIC("dead"), MUSIC("stlks2"), + MUSIC("theda2"), MUSIC("doom2"), MUSIC("ddtbl2"), MUSIC("runni2"), + MUSIC("dead2"), MUSIC("stlks3"), MUSIC("romero"), MUSIC("shawn2"), + MUSIC("messag"), MUSIC("count2"), MUSIC("ddtbl3"), MUSIC("ampie"), + MUSIC("theda3"), MUSIC("adrian"), MUSIC("messg2"), MUSIC("romer2"), + MUSIC("tense"), MUSIC("shawn3"), MUSIC("openin"), MUSIC("evil"), + MUSIC("ultima"), MUSIC("read_m"), MUSIC("dm2ttl"), MUSIC("dm2int"), +}; -sfxinfo_t S_sfx[] = +sfxinfo_t s_sfx[] = { - // S_sfx[0] needs to be a dummy for odd reasons. - SOUND("none", 0), + SOUND("none", 0), /* s_sfx[0] needs to be a dummy for odd reasons. */ SOUND("pistol", 64), SOUND("shotgn", 64), SOUND("sgcock", 64), SOUND("dshtgn", 64), - SOUND("dbopn", 64), - SOUND("dbcls", 64), + SOUND("dbopn", 64), + SOUND("dbcls", 64), SOUND("dbload", 64), SOUND("plasma", 64), - SOUND("bfg", 64), - SOUND("sawup", 64), + SOUND("bfg", 64), + SOUND("sawup", 64), SOUND("sawidl", 118), SOUND("sawful", 64), SOUND("sawhit", 64), @@ -135,7 +92,7 @@ sfxinfo_t S_sfx[] = SOUND("firsht", 70), SOUND("firxpl", 70), SOUND("pstart", 100), - SOUND("pstop", 100), + SOUND("pstop", 100), SOUND("doropn", 100), SOUND("dorcls", 100), SOUND("stnmov", 119), @@ -147,10 +104,10 @@ sfxinfo_t S_sfx[] = SOUND("vipain", 96), SOUND("mnpain", 96), SOUND("pepain", 96), - SOUND("slop", 78), + SOUND("slop", 78), SOUND("itemup", 78), - SOUND("wpnup", 78), - SOUND("oof", 96), + SOUND("wpnup", 78), + SOUND("oof", 96), SOUND("telept", 32), SOUND("posit1", 98), SOUND("posit2", 98), @@ -166,12 +123,12 @@ sfxinfo_t S_sfx[] = SOUND("kntsit", 90), SOUND("vilsit", 90), SOUND("mansit", 90), - SOUND("pesit", 90), + SOUND("pesit", 90), SOUND("sklatk", 70), SOUND("sgtatk", 70), SOUND("skepch", 70), SOUND("vilatk", 70), - SOUND("claw", 70), + SOUND("claw", 70), SOUND("skeswg", 70), SOUND("pldeth", 32), SOUND("pdiehi", 32), @@ -189,41 +146,44 @@ sfxinfo_t S_sfx[] = SOUND("bspdth", 32), SOUND("vildth", 32), SOUND("kntdth", 32), - SOUND("pedth", 32), + SOUND("pedth", 32), SOUND("skedth", 32), SOUND("posact", 120), - SOUND("bgact", 120), - SOUND("dmact", 120), + SOUND("bgact", 120), + SOUND("dmact", 120), SOUND("bspact", 100), SOUND("bspwlk", 100), SOUND("vilact", 100), - SOUND("noway", 78), + SOUND("noway", 78), SOUND("barexp", 60), - SOUND("punch", 64), - SOUND("hoof", 70), - SOUND("metal", 70), - SOUND_LINK("chgun", 64, sfx_pistol, 150, 0), - SOUND("tink", 60), - SOUND("bdopn", 100), - SOUND("bdcls", 100), - SOUND("itmbk", 100), - SOUND("flame", 32), + SOUND("punch", 64), + SOUND("hoof", 70), + SOUND("metal", 70), + SOUND_LINK("chgun", 64, SFX_PISTOL, 150, 0), + SOUND("tink", 60), + SOUND("bdopn", 100), + SOUND("bdcls", 100), + SOUND("itmbk", 100), + SOUND("flame", 32), SOUND("flamst", 32), SOUND("getpow", 60), SOUND("bospit", 70), SOUND("boscub", 70), SOUND("bossit", 70), - SOUND("bospn", 70), + SOUND("bospn", 70), SOUND("bosdth", 70), SOUND("manatk", 70), SOUND("mandth", 70), - SOUND("sssit", 70), - SOUND("ssdth", 70), + SOUND("sssit", 70), + SOUND("ssdth", 70), SOUND("keenpn", 70), SOUND("keendt", 70), SOUND("skeact", 70), SOUND("skesit", 70), SOUND("skeatk", 70), - SOUND("radio", 60), + SOUND("radio", 60), }; +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/doom/sounds.h b/games/NXDoom/src/doom/sounds.h index 1e8afc4051c..a2d9b371fe0 100644 --- a/games/NXDoom/src/doom/sounds.h +++ b/games/NXDoom/src/doom/sounds.h @@ -1,227 +1,241 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Created by the sound utility written by Dave Taylor. -// Kept as a sample, DOOM2 sounds. Frozen. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/sounds.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Created by the sound utility written by Dave Taylor. + * Kept as a sample, DOOM2 sounds. Frozen. + * + ****************************************************************************/ #ifndef __SOUNDS__ #define __SOUNDS__ -#include "i_sound.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ -// the complete set of sound effects -extern sfxinfo_t S_sfx[]; +#include "i_sound.h" -// the complete set of music -extern musicinfo_t S_music[]; +/**************************************************************************** + * Public Types + ****************************************************************************/ -// -// Identifiers for all music in game. -// +/* Identifiers for all music in game. */ typedef enum { - mus_None, - mus_e1m1, - mus_e1m2, - mus_e1m3, - mus_e1m4, - mus_e1m5, - mus_e1m6, - mus_e1m7, - mus_e1m8, - mus_e1m9, - mus_e2m1, - mus_e2m2, - mus_e2m3, - mus_e2m4, - mus_e2m5, - mus_e2m6, - mus_e2m7, - mus_e2m8, - mus_e2m9, - mus_e3m1, - mus_e3m2, - mus_e3m3, - mus_e3m4, - mus_e3m5, - mus_e3m6, - mus_e3m7, - mus_e3m8, - mus_e3m9, - mus_inter, - mus_intro, - mus_bunny, - mus_victor, - mus_introa, - mus_runnin, - mus_stalks, - mus_countd, - mus_betwee, - mus_doom, - mus_the_da, - mus_shawn, - mus_ddtblu, - mus_in_cit, - mus_dead, - mus_stlks2, - mus_theda2, - mus_doom2, - mus_ddtbl2, - mus_runni2, - mus_dead2, - mus_stlks3, - mus_romero, - mus_shawn2, - mus_messag, - mus_count2, - mus_ddtbl3, - mus_ampie, - mus_theda3, - mus_adrian, - mus_messg2, - mus_romer2, - mus_tense, - mus_shawn3, - mus_openin, - mus_evil, - mus_ultima, - mus_read_m, - mus_dm2ttl, - mus_dm2int, - NUMMUSIC + MUS_NONE, + MUS_E1M1, + MUS_E1M2, + MUS_E1M3, + MUS_E1M4, + MUS_E1M5, + MUS_E1M6, + MUS_E1M7, + MUS_E1M8, + MUS_E1M9, + MUS_E2M1, + MUS_E2M2, + MUS_E2M3, + MUS_E2M4, + MUS_E2M5, + MUS_E2M6, + MUS_E2M7, + MUS_E2M8, + MUS_E2M9, + MUS_E3M1, + MUS_E3M2, + MUS_E3M3, + MUS_E3M4, + MUS_E3M5, + MUS_E3M6, + MUS_E3M7, + MUS_E3M8, + MUS_E3M9, + MUS_INTER, + MUS_INTRO, + MUS_BUNNY, + MUS_VICTOR, + MUS_INTROA, + MUS_RUNNIN, + MUS_STALKS, + MUS_COUNTD, + MUS_BETWEE, + MUS_DOOM, + MUS_THE_DA, + MUS_SHAWN, + MUS_DDTBLU, + MUS_IN_CIT, + MUS_DEAD, + MUS_STLKS2, + MUS_THEDA2, + MUS_DOOM2, + MUS_DDTBL2, + MUS_RUNNI2, + MUS_DEAD2, + MUS_STLKS3, + MUS_ROMERO, + MUS_SHAWN2, + MUS_MESSAG, + MUS_COUNT2, + MUS_DDTBL3, + MUS_AMPIE, + MUS_THEDA3, + MUS_ADRIAN, + MUS_MESSG2, + MUS_ROMER2, + MUS_TENSE, + MUS_SHAWN3, + MUS_OPENIN, + MUS_EVIL, + MUS_ULTIMA, + MUS_READ_M, + MUS_DM2TTL, + MUS_DM2INT, + MUS_NUMMUSIC } musicenum_t; - -// -// Identifiers for all sfx in game. -// +/* Identifiers for all sfx in game. */ typedef enum { - sfx_None, - sfx_pistol, - sfx_shotgn, - sfx_sgcock, - sfx_dshtgn, - sfx_dbopn, - sfx_dbcls, - sfx_dbload, - sfx_plasma, - sfx_bfg, - sfx_sawup, - sfx_sawidl, - sfx_sawful, - sfx_sawhit, - sfx_rlaunc, - sfx_rxplod, - sfx_firsht, - sfx_firxpl, - sfx_pstart, - sfx_pstop, - sfx_doropn, - sfx_dorcls, - sfx_stnmov, - sfx_swtchn, - sfx_swtchx, - sfx_plpain, - sfx_dmpain, - sfx_popain, - sfx_vipain, - sfx_mnpain, - sfx_pepain, - sfx_slop, - sfx_itemup, - sfx_wpnup, - sfx_oof, - sfx_telept, - sfx_posit1, - sfx_posit2, - sfx_posit3, - sfx_bgsit1, - sfx_bgsit2, - sfx_sgtsit, - sfx_cacsit, - sfx_brssit, - sfx_cybsit, - sfx_spisit, - sfx_bspsit, - sfx_kntsit, - sfx_vilsit, - sfx_mansit, - sfx_pesit, - sfx_sklatk, - sfx_sgtatk, - sfx_skepch, - sfx_vilatk, - sfx_claw, - sfx_skeswg, - sfx_pldeth, - sfx_pdiehi, - sfx_podth1, - sfx_podth2, - sfx_podth3, - sfx_bgdth1, - sfx_bgdth2, - sfx_sgtdth, - sfx_cacdth, - sfx_skldth, - sfx_brsdth, - sfx_cybdth, - sfx_spidth, - sfx_bspdth, - sfx_vildth, - sfx_kntdth, - sfx_pedth, - sfx_skedth, - sfx_posact, - sfx_bgact, - sfx_dmact, - sfx_bspact, - sfx_bspwlk, - sfx_vilact, - sfx_noway, - sfx_barexp, - sfx_punch, - sfx_hoof, - sfx_metal, - sfx_chgun, - sfx_tink, - sfx_bdopn, - sfx_bdcls, - sfx_itmbk, - sfx_flame, - sfx_flamst, - sfx_getpow, - sfx_bospit, - sfx_boscub, - sfx_bossit, - sfx_bospn, - sfx_bosdth, - sfx_manatk, - sfx_mandth, - sfx_sssit, - sfx_ssdth, - sfx_keenpn, - sfx_keendt, - sfx_skeact, - sfx_skesit, - sfx_skeatk, - sfx_radio, - NUMSFX + SFX_NONE, + SFX_PISTOL, + SFX_SHOTGN, + SFX_SGCOCK, + SFX_DSHTGN, + SFX_DBOPN, + SFX_DBCLS, + SFX_DBLOAD, + SFX_PLASMA, + SFX_BFG, + SFX_SAWUP, + SFX_SAWIDL, + SFX_SAWFUL, + SFX_SAWHIT, + SFX_RLAUNC, + SFX_RXPLOD, + SFX_FIRSHT, + SFX_FIRXPL, + SFX_PSTART, + SFX_PSTOP, + SFX_DOROPN, + SFX_DORCLS, + SFX_STNMOV, + SFX_SWTCHN, + SFX_SWTCHX, + SFX_PLPAIN, + SFX_DMPAIN, + SFX_POPAIN, + SFX_VIPAIN, + SFX_MNPAIN, + SFX_PEPAIN, + SFX_SLOP, + SFX_ITEMUP, + SFX_WPNUP, + SFX_OOF, + SFX_TELEPT, + SFX_POSIT1, + SFX_POSIT2, + SFX_POSIT3, + SFX_BGSIT1, + SFX_BGSIT2, + SFX_SGTSIT, + SFX_CACSIT, + SFX_BRSSIT, + SFX_CYBSIT, + SFX_SPISIT, + SFX_BSPSIT, + SFX_KNTSIT, + SFX_VILSIT, + SFX_MANSIT, + SFX_PESIT, + SFX_SKLATK, + SFX_SGTATK, + SFX_SKEPCH, + SFX_VILATK, + SFX_CLAW, + SFX_SKESWG, + SFX_PLDETH, + SFX_PDIEHI, + SFX_PODTH1, + SFX_PODTH2, + SFX_PODTH3, + SFX_BGDTH1, + SFX_BGDTH2, + SFX_SGTDTH, + SFX_CACDTH, + SFX_SKLDTH, + SFX_BRSDTH, + SFX_CYBDTH, + SFX_SPIDTH, + SFX_BSPDTH, + SFX_VILDTH, + SFX_KNTDTH, + SFX_PEDTH, + SFX_SKEDTH, + SFX_POSACT, + SFX_BGACT, + SFX_DMACT, + SFX_BSPACT, + SFX_BSPWLK, + SFX_VILACT, + SFX_NOWAY, + SFX_BAREXP, + SFX_PUNCH, + SFX_HOOF, + SFX_METAL, + SFX_CHGUN, + SFX_TINK, + SFX_BDOPN, + SFX_BDCLS, + SFX_ITMBK, + SFX_FLAME, + SFX_FLAMST, + SFX_GETPOW, + SFX_BOSPIT, + SFX_BOSCUB, + SFX_BOSSIT, + SFX_BOSPN, + SFX_BOSDTH, + SFX_MANATK, + SFX_MANDTH, + SFX_SSSIT, + SFX_SSDTH, + SFX_KEENPN, + SFX_KEENDT, + SFX_SKEACT, + SFX_SKESIT, + SFX_SKEATK, + SFX_RADIO, + SFX_NUMSFX } sfxenum_t; -#endif +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* the complete set of sound effects */ + +extern sfxinfo_t s_sfx[]; + +/* the complete set of music */ + +extern musicinfo_t s_music[]; + +#endif /* __SOUNDS__ */ diff --git a/games/NXDoom/src/doom/st_lib.c b/games/NXDoom/src/doom/st_lib.c index 832bb66d387..d8aeda710a4 100644 --- a/games/NXDoom/src/doom/st_lib.c +++ b/games/NXDoom/src/doom/st_lib.c @@ -1,283 +1,238 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The status bar widget code. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/st_lib.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * The status bar widget code. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include #include +#include #include "deh_main.h" #include "doomdef.h" -#include "z_zone.h" #include "v_video.h" +#include "z_zone.h" #include "i_swap.h" #include "i_system.h" #include "w_wad.h" -#include "st_stuff.h" -#include "st_lib.h" #include "r_local.h" +#include "st_lib.h" +#include "st_stuff.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ -// -// Hack display negative frags. -// Loads and store the stminus lump. -// -patch_t* sttminus; +/* Hack display negative frags. Loads and store the stminus lump. */ -void STlib_init(void) -{ - if (W_CheckNumForName(DEH_String("STTMINUS")) >= 0) - sttminus = (patch_t *) W_CacheLumpName(DEH_String("STTMINUS"), PU_STATIC); - else - sttminus = NULL; -} +patch_t *sttminus; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// ? -void -STlib_initNum -( st_number_t* n, - int x, - int y, - patch_t** pl, - int* num, - boolean* on, - int width ) -{ - n->x = x; - n->y = y; - n->oldnum = 0; - n->width = width; - n->num = num; - n->on = on; - n->p = pl; -} +/**************************************************************************** + * Name: stlib_draw_num + * + * Description: + * A fairly efficient way to draw a number based on differences from the old + * number. Note: worth the trouble? + * + ****************************************************************************/ - -// -// A fairly efficient way to draw a number -// based on differences from the old number. -// Note: worth the trouble? -// -void -STlib_drawNum -( st_number_t* n, - boolean refresh ) +static void stlib_draw_num(st_number_t *n, boolean refresh) { + int numdigits = n->width; + int num = *n->num; + + int w = SHORT(n->p[0]->width); + int h = SHORT(n->p[0]->height); + int x = n->x; - int numdigits = n->width; - int num = *n->num; - - int w = SHORT(n->p[0]->width); - int h = SHORT(n->p[0]->height); - int x = n->x; - - int neg; + int neg; - n->oldnum = *n->num; + n->oldnum = *n->num; - neg = num < 0; + neg = num < 0; - if (neg) + if (neg) { - if (numdigits == 2 && num < -9) - num = -9; - else if (numdigits == 3 && num < -99) - num = -99; - - num = -num; + if (numdigits == 2 && num < -9) + num = -9; + else if (numdigits == 3 && num < -99) + num = -99; + + num = -num; } - // clear the area - x = n->x - numdigits*w; + /* clear the area */ + + x = n->x - numdigits * w; + + if (n->y - ST_Y < 0) i_error("drawNum: n->y - ST_Y < 0"); + + v_copy_rect(x, n->y - ST_Y, st_backing_screen, w * numdigits, h, x, n->y); - if (n->y - ST_Y < 0) - I_Error("drawNum: n->y - ST_Y < 0"); + if (num == 1994) return; /* if non-number, do not draw it */ - V_CopyRect(x, n->y - ST_Y, st_backing_screen, w*numdigits, h, x, n->y); + x = n->x; - // if non-number, do not draw it - if (num == 1994) - return; + /* in the special case of 0, you draw 0 */ - x = n->x; + if (!num) v_draw_patch(x - w, n->y, n->p[0]); - // in the special case of 0, you draw 0 - if (!num) - V_DrawPatch(x - w, n->y, n->p[ 0 ]); + /* draw the new number */ - // draw the new number - while (num && numdigits--) + while (num && numdigits--) { - x -= w; - V_DrawPatch(x, n->y, n->p[ num % 10 ]); - num /= 10; + x -= w; + v_draw_patch(x, n->y, n->p[num % 10]); + num /= 10; } - // draw a minus sign if necessary - if (neg && sttminus) - V_DrawPatch(x - 8, n->y, sttminus); + /* draw a minus sign if necessary */ + + if (neg && sttminus) v_draw_patch(x - 8, n->y, sttminus); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -void -STlib_updateNum -( st_number_t* n, - boolean refresh ) +void stlib_init(void) { - if (*n->on) STlib_drawNum(n, refresh); + if (w_check_num_for_name(("STTMINUS")) >= 0) + sttminus = (patch_t *)w_cache_lump_name(("STTMINUS"), PU_STATIC); + else + sttminus = NULL; } +/* ? */ -// -void -STlib_initPercent -( st_percent_t* p, - int x, - int y, - patch_t** pl, - int* num, - boolean* on, - patch_t* percent ) +void stlib_init_num(st_number_t *n, int x, int y, patch_t **pl, int *num, + boolean *on, int width) { - STlib_initNum(&p->n, x, y, pl, num, on, 3); - p->p = percent; + n->x = x; + n->y = y; + n->oldnum = 0; + n->width = width; + n->num = num; + n->on = on; + n->p = pl; } +void stlib_update_num(st_number_t *n, boolean refresh) +{ + if (*n->on) stlib_draw_num(n, refresh); +} - - -void -STlib_updatePercent -( st_percent_t* per, - int refresh ) +void stlib_init_percent(st_percent_t *p, int x, int y, patch_t **pl, + int *num, boolean *on, patch_t *percent) { - if (refresh && *per->n.on) - V_DrawPatch(per->n.x, per->n.y, per->p); - - STlib_updateNum(&per->n, refresh); + stlib_init_num(&p->n, x, y, pl, num, on, 3); + p->p = percent; } +void stlib_update_percent(st_percent_t *per, int refresh) +{ + if (refresh && *per->n.on) v_draw_patch(per->n.x, per->n.y, per->p); + stlib_update_num(&per->n, refresh); +} -void -STlib_initMultIcon -( st_multicon_t* i, - int x, - int y, - patch_t** il, - int* inum, - boolean* on ) +void stlib_init_mutl_icon(st_multicon_t *i, int x, int y, patch_t **il, + int *inum, boolean *on) { - i->x = x; - i->y = y; - i->oldinum = -1; - i->inum = inum; - i->on = on; - i->p = il; + i->x = x; + i->y = y; + i->oldinum = -1; + i->inum = inum; + i->on = on; + i->p = il; } - - -void -STlib_updateMultIcon -( st_multicon_t* mi, - boolean refresh ) +void stlib_update_mult_icon(st_multicon_t *mi, boolean refresh) { - int w; - int h; - int x; - int y; - - if (*mi->on - && (mi->oldinum != *mi->inum || refresh) - && (*mi->inum!=-1)) + int w; + int h; + int x; + int y; + + if (*mi->on && (mi->oldinum != *mi->inum || refresh) && (*mi->inum != -1)) { - if (mi->oldinum != -1) - { - x = mi->x - SHORT(mi->p[mi->oldinum]->leftoffset); - y = mi->y - SHORT(mi->p[mi->oldinum]->topoffset); - w = SHORT(mi->p[mi->oldinum]->width); - h = SHORT(mi->p[mi->oldinum]->height); - - if (y - ST_Y < 0) - I_Error("updateMultIcon: y - ST_Y < 0"); - - V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); - } - V_DrawPatch(mi->x, mi->y, mi->p[*mi->inum]); - mi->oldinum = *mi->inum; - } -} + if (mi->oldinum != -1) + { + x = mi->x - SHORT(mi->p[mi->oldinum]->leftoffset); + y = mi->y - SHORT(mi->p[mi->oldinum]->topoffset); + w = SHORT(mi->p[mi->oldinum]->width); + h = SHORT(mi->p[mi->oldinum]->height); + if (y - ST_Y < 0) i_error("updateMultIcon: y - ST_Y < 0"); + v_copy_rect(x, y - ST_Y, st_backing_screen, w, h, x, y); + } -void -STlib_initBinIcon -( st_binicon_t* b, - int x, - int y, - patch_t* i, - boolean* val, - boolean* on ) -{ - b->x = x; - b->y = y; - b->oldval = false; - b->val = val; - b->on = on; - b->p = i; + v_draw_patch(mi->x, mi->y, mi->p[*mi->inum]); + mi->oldinum = *mi->inum; + } } +void stlib_init_bin_icon(st_binicon_t *b, int x, int y, patch_t *i, + boolean *val, boolean *on) +{ + b->x = x; + b->y = y; + b->oldval = false; + b->val = val; + b->on = on; + b->p = i; +} - -void -STlib_updateBinIcon -( st_binicon_t* bi, - boolean refresh ) +void stlib_update_bin_icon(st_binicon_t *bi, boolean refresh) { - int x; - int y; - int w; - int h; + int x; + int y; + int w; + int h; - if (*bi->on - && (bi->oldval != *bi->val || refresh)) + if (*bi->on && (bi->oldval != *bi->val || refresh)) { - x = bi->x - SHORT(bi->p->leftoffset); - y = bi->y - SHORT(bi->p->topoffset); - w = SHORT(bi->p->width); - h = SHORT(bi->p->height); + x = bi->x - SHORT(bi->p->leftoffset); + y = bi->y - SHORT(bi->p->topoffset); + w = SHORT(bi->p->width); + h = SHORT(bi->p->height); - if (y - ST_Y < 0) - I_Error("updateBinIcon: y - ST_Y < 0"); + if (y - ST_Y < 0) i_error("updateBinIcon: y - ST_Y < 0"); - if (*bi->val) - V_DrawPatch(bi->x, bi->y, bi->p); - else - V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); + if (*bi->val) + v_draw_patch(bi->x, bi->y, bi->p); + else + v_copy_rect(x, y - ST_Y, st_backing_screen, w, h, x, y); - bi->oldval = *bi->val; + bi->oldval = *bi->val; } - } - diff --git a/games/NXDoom/src/doom/st_lib.h b/games/NXDoom/src/doom/st_lib.h index 3a8f5212512..b1fa3867bd0 100644 --- a/games/NXDoom/src/doom/st_lib.h +++ b/games/NXDoom/src/doom/st_lib.h @@ -1,209 +1,187 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The status bar widget code. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/st_lib.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * The status bar widget code. + * + ****************************************************************************/ #ifndef __STLIB__ #define __STLIB__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* We are referring to patches. */ -// We are referring to patches. #include "r_defs.h" -// -// Typedefs of widgets -// +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Typedefs of widgets */ -// Number widget +/* Number widget */ typedef struct { - // upper right-hand corner - // of the number (right-justified) - int x; - int y; - - // max # of digits in number - int width; - - // last number value - int oldnum; - - // pointer to current value - int* num; - - // pointer to boolean stating - // whether to update number - boolean* on; - - // list of patches for 0-9 - patch_t** p; - - // user data - int data; - -} st_number_t; + /* upper right-hand corner of the number (right-justified) + */ + + int x; + int y; + + /* max # of digits in number */ + + int width; + + /* last number value */ + + int oldnum; + /* pointer to current value */ + + int *num; + + /* pointer to boolean stating whether to update number */ + + boolean *on; + + /* list of patches for 0-9 */ + + patch_t **p; + + /* user data */ + + int data; +} st_number_t; +/* Percent widget ("child" of number widget, or, more precisely, contains a + * number widget.) + */ -// Percent widget ("child" of number widget, -// or, more precisely, contains a number widget.) typedef struct { - // number information - st_number_t n; + /* number information */ - // percent sign graphic - patch_t* p; - -} st_percent_t; + st_number_t n; + + /* percent sign graphic */ + patch_t *p; +} st_percent_t; +/* Multiple Icon widget */ -// Multiple Icon widget typedef struct { - // center-justified location of icons - int x; - int y; - - // last icon number - int oldinum; - - // pointer to current icon - int* inum; - - // pointer to boolean stating - // whether to update icon - boolean* on; - - // list of icons - patch_t** p; - - // user data - int data; - -} st_multicon_t; + /* center-justified location of icons */ + + int x; + int y; + + /* last icon number */ + + int oldinum; + + /* pointer to current icon */ + int *inum; + /* pointer to boolean stating whether to update icon */ + boolean *on; -// Binary Icon widget + /* list of icons */ + + patch_t **p; + + /* user data */ + + int data; +} st_multicon_t; + +/* Binary Icon widget */ typedef struct { - // center-justified location of icon - int x; - int y; + /* center-justified location of icon */ - // last icon value - boolean oldval; + int x; + int y; - // pointer to current icon status - boolean* val; + /* last icon value */ - // pointer to boolean - // stating whether to update icon - boolean* on; + boolean oldval; + /* pointer to current icon status */ - patch_t* p; // icon - int data; // user data - -} st_binicon_t; + boolean *val; + /* pointer to boolean stating whether to update icon */ + boolean *on; -// -// Widget creation, access, and update routines -// + patch_t *p; /* icon */ + int data; /* user data */ +} st_binicon_t; -// Initializes widget library. -// More precisely, initialize STMINUS, -// everything else is done somewhere else. -// -void STlib_init(void); +/* Widget creation, access, and update routines */ +/* Initializes widget library. + * More precisely, initialize STMINUS, + * everything else is done somewhere else. + */ +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Number widget routines -void -STlib_initNum -( st_number_t* n, - int x, - int y, - patch_t** pl, - int* num, - boolean* on, - int width ); +void stlib_init(void); -void -STlib_updateNum -( st_number_t* n, - boolean refresh ); +/* Number widget routines */ +void stlib_init_num(st_number_t *n, int x, int y, patch_t **pl, int *num, + boolean *on, int width); -// Percent widget routines -void -STlib_initPercent -( st_percent_t* p, - int x, - int y, - patch_t** pl, - int* num, - boolean* on, - patch_t* percent ); +void stlib_update_num(st_number_t *n, boolean refresh); +/* Percent widget routines */ -void -STlib_updatePercent -( st_percent_t* per, - int refresh ); +void stlib_init_percent(st_percent_t *p, int x, int y, patch_t **pl, + int *num, boolean *on, patch_t *percent); +void stlib_update_percent(st_percent_t *per, int refresh); -// Multiple Icon widget routines -void -STlib_initMultIcon -( st_multicon_t* mi, - int x, - int y, - patch_t** il, - int* inum, - boolean* on ); +/* Multiple Icon widget routines */ +void stlib_init_mutl_icon(st_multicon_t *mi, int x, int y, patch_t **il, + int *inum, boolean *on); -void -STlib_updateMultIcon -( st_multicon_t* mi, - boolean refresh ); +void stlib_update_mult_icon(st_multicon_t *mi, boolean refresh); -// Binary Icon widget routines +/* Binary Icon widget routines */ -void -STlib_initBinIcon -( st_binicon_t* b, - int x, - int y, - patch_t* i, - boolean* val, - boolean* on ); +void stlib_init_bin_icon(st_binicon_t *b, int x, int y, patch_t *i, + boolean *val, boolean *on); -void -STlib_updateBinIcon -( st_binicon_t* bi, - boolean refresh ); +void stlib_update_bin_icon(st_binicon_t *bi, boolean refresh); -#endif +#endif /* __STLIB__ */ diff --git a/games/NXDoom/src/doom/st_stuff.c b/games/NXDoom/src/doom/st_stuff.c index da9b8bcf8c3..7a133b33ca5 100644 --- a/games/NXDoom/src/doom/st_stuff.c +++ b/games/NXDoom/src/doom/st_stuff.c @@ -1,34 +1,41 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Status bar code. -// Does the face/direction indicator animatin. -// Does palette indicators as well (red pain/berserk, bright pickup) -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/st_stuff.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Status bar code. + * Does the face/direction indicator animating. + * Does palette indicators as well (red pain/berserk, bright pickup) + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - -#include #include +#include #include "i_system.h" #include "i_video.h" -#include "z_zone.h" #include "m_misc.h" #include "m_random.h" #include "w_wad.h" +#include "z_zone.h" #include "deh_main.h" #include "deh_misc.h" @@ -37,280 +44,354 @@ #include "g_game.h" -#include "st_stuff.h" -#include "st_lib.h" #include "r_local.h" +#include "st_lib.h" +#include "st_stuff.h" -#include "p_local.h" #include "p_inter.h" +#include "p_local.h" #include "am_map.h" #include "m_cheat.h" +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif + +/* Needs access to LFB. */ -// Needs access to LFB. #include "v_video.h" -// State. +/* State. */ + #include "doomstat.h" -// Data. +/* Data. */ + #include "dstrings.h" -#include "sounds.h" -// -// STATUS BAR DATA -// - - -// Palette indices. -// For damage/bonus red-/gold-shifts -#define STARTREDPALS 1 -#define STARTBONUSPALS 9 -#define NUMREDPALS 8 -#define NUMBONUSPALS 4 -// Radiation suit, green shift. -#define RADIATIONPAL 13 - -// Location of status bar -#define ST_X 0 -#define ST_X2 104 - -#define ST_FX 143 -#define ST_FY 169 - -// Number of status faces. -#define ST_NUMPAINFACES 5 -#define ST_NUMSTRAIGHTFACES 3 -#define ST_NUMTURNFACES 2 -#define ST_NUMSPECIALFACES 3 - -#define ST_FACESTRIDE \ - (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES) - -#define ST_NUMEXTRAFACES 2 - -#define ST_NUMFACES \ - (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES) - -#define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES) -#define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES) -#define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1) -#define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1) -#define ST_GODFACE (ST_NUMPAINFACES*ST_FACESTRIDE) -#define ST_DEADFACE (ST_GODFACE+1) - -#define ST_FACESX 143 -#define ST_FACESY 168 - -#define ST_EVILGRINCOUNT (2*TICRATE) -#define ST_STRAIGHTFACECOUNT (TICRATE/2) -#define ST_TURNCOUNT (1*TICRATE) -#define ST_OUCHCOUNT (1*TICRATE) -#define ST_RAMPAGEDELAY (2*TICRATE) - -#define ST_MUCHPAIN 20 - - -// Location and size of statistics, -// justified according to widget type. -// Problem is, within which space? STbar? Screen? -// Note: this could be read in by a lump. -// Problem is, is the stuff rendered -// into a buffer, -// or into the frame buffer? - -// AMMO number pos. -#define ST_AMMOWIDTH 3 -#define ST_AMMOX 44 -#define ST_AMMOY 171 - -// HEALTH number pos. -#define ST_HEALTHWIDTH 3 -#define ST_HEALTHX 90 -#define ST_HEALTHY 171 - -// Weapon pos. -#define ST_ARMSX 111 -#define ST_ARMSY 172 -#define ST_ARMSBGX 104 -#define ST_ARMSBGY 168 -#define ST_ARMSXSPACE 12 -#define ST_ARMSYSPACE 10 - -// Frags pos. -#define ST_FRAGSX 138 -#define ST_FRAGSY 171 -#define ST_FRAGSWIDTH 2 - -// ARMOR number pos. -#define ST_ARMORWIDTH 3 -#define ST_ARMORX 221 -#define ST_ARMORY 171 - -// Key icon positions. -#define ST_KEY0WIDTH 8 -#define ST_KEY0HEIGHT 5 -#define ST_KEY0X 239 -#define ST_KEY0Y 171 -#define ST_KEY1WIDTH ST_KEY0WIDTH -#define ST_KEY1X 239 -#define ST_KEY1Y 181 -#define ST_KEY2WIDTH ST_KEY0WIDTH -#define ST_KEY2X 239 -#define ST_KEY2Y 191 - -// Ammunition counter. -#define ST_AMMO0WIDTH 3 -#define ST_AMMO0HEIGHT 6 -#define ST_AMMO0X 288 -#define ST_AMMO0Y 173 -#define ST_AMMO1WIDTH ST_AMMO0WIDTH -#define ST_AMMO1X 288 -#define ST_AMMO1Y 179 -#define ST_AMMO2WIDTH ST_AMMO0WIDTH -#define ST_AMMO2X 288 -#define ST_AMMO2Y 191 -#define ST_AMMO3WIDTH ST_AMMO0WIDTH -#define ST_AMMO3X 288 -#define ST_AMMO3Y 185 - -// Indicate maximum ammunition. -// Only needed because backpack exists. -#define ST_MAXAMMO0WIDTH 3 -#define ST_MAXAMMO0HEIGHT 5 -#define ST_MAXAMMO0X 314 -#define ST_MAXAMMO0Y 173 -#define ST_MAXAMMO1WIDTH ST_MAXAMMO0WIDTH -#define ST_MAXAMMO1X 314 -#define ST_MAXAMMO1Y 179 -#define ST_MAXAMMO2WIDTH ST_MAXAMMO0WIDTH -#define ST_MAXAMMO2X 314 -#define ST_MAXAMMO2Y 191 -#define ST_MAXAMMO3WIDTH ST_MAXAMMO0WIDTH -#define ST_MAXAMMO3X 314 -#define ST_MAXAMMO3Y 185 - -// Dimensions given in characters. -#define ST_MSGWIDTH 52 - -// graphics are drawn to a backing screen and blitted to the real screen -pixel_t *st_backing_screen; - -// main player in game -static player_t* plyr; +/* STATUS BAR DATA */ + +/* Palette indices. + * For damage/bonus red-/gold-shifts + */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STARTREDPALS 1 +#define STARTBONUSPALS 9 +#define NUMREDPALS 8 +#define NUMBONUSPALS 4 + +/* Radiation suit, green shift. */ + +#define RADIATIONPAL 13 + +/* Location of status bar */ + +#define ST_X 0 +#define ST_X2 104 + +#define ST_FX 143 +#define ST_FY 169 + +/* Number of status faces. */ + +#define ST_NUMPAINFACES 5 +#define ST_NUMSTRAIGHTFACES 3 +#define ST_NUMTURNFACES 2 +#define ST_NUMSPECIALFACES 3 + +#define ST_FACESTRIDE \ + (ST_NUMSTRAIGHTFACES + ST_NUMTURNFACES + ST_NUMSPECIALFACES) + +#define ST_NUMEXTRAFACES 2 + +#define ST_NUMFACES (ST_FACESTRIDE * ST_NUMPAINFACES + ST_NUMEXTRAFACES) + +#define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES) +#define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES) +#define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1) +#define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1) +#define ST_GODFACE (ST_NUMPAINFACES * ST_FACESTRIDE) +#define ST_DEADFACE (ST_GODFACE + 1) + +#define ST_FACESX 143 +#define ST_FACESY 168 + +#define ST_EVILGRINCOUNT (2 * TICRATE) +#define ST_STRAIGHTFACECOUNT (TICRATE / 2) +#define ST_TURNCOUNT (1 * TICRATE) +#define ST_OUCHCOUNT (1 * TICRATE) +#define ST_RAMPAGEDELAY (2 * TICRATE) + +#define ST_MUCHPAIN 20 + +/* Location and size of statistics, + * justified according to widget type. + * Problem is, within which space? STbar? Screen? + * Note: this could be read in by a lump. + * Problem is, is the stuff rendered + * into a buffer, + * or into the frame buffer? + */ + +/* AMMO number pos. */ + +#define ST_AMMOWIDTH 3 +#define ST_AMMOX 44 +#define ST_AMMOY 171 + +/* HEALTH number pos. */ + +#define ST_HEALTHWIDTH 3 +#define ST_HEALTHX 90 +#define ST_HEALTHY 171 + +/* Weapon pos. */ + +#define ST_ARMSX 111 +#define ST_ARMSY 172 +#define ST_ARMSBGX 104 +#define ST_ARMSBGY 168 +#define ST_ARMSXSPACE 12 +#define ST_ARMSYSPACE 10 + +/* Frags pos. */ + +#define ST_FRAGSX 138 +#define ST_FRAGSY 171 +#define ST_FRAGSWIDTH 2 + +/* ARMOR number pos. */ + +#define ST_ARMORWIDTH 3 +#define ST_ARMORX 221 +#define ST_ARMORY 171 + +/* Key icon positions. */ + +#define ST_KEY0WIDTH 8 +#define ST_KEY0HEIGHT 5 +#define ST_KEY0X 239 +#define ST_KEY0Y 171 +#define ST_KEY1WIDTH ST_KEY0WIDTH +#define ST_KEY1X 239 +#define ST_KEY1Y 181 +#define ST_KEY2WIDTH ST_KEY0WIDTH +#define ST_KEY2X 239 +#define ST_KEY2Y 191 + +/* Ammunition counter. */ + +#define ST_AMMO0WIDTH 3 +#define ST_AMMO0HEIGHT 6 +#define ST_AMMO0X 288 +#define ST_AMMO0Y 173 +#define ST_AMMO1WIDTH ST_AMMO0WIDTH +#define ST_AMMO1X 288 +#define ST_AMMO1Y 179 +#define ST_AMMO2WIDTH ST_AMMO0WIDTH +#define ST_AMMO2X 288 +#define ST_AMMO2Y 191 +#define ST_AMMO3WIDTH ST_AMMO0WIDTH +#define ST_AMMO3X 288 +#define ST_AMMO3Y 185 + +/* Indicate maximum ammunition. + * Only needed because backpack exists. + */ + +#define ST_MAXAMMO0WIDTH 3 +#define ST_MAXAMMO0HEIGHT 5 +#define ST_MAXAMMO0X 314 +#define ST_MAXAMMO0Y 173 +#define ST_MAXAMMO1WIDTH ST_MAXAMMO0WIDTH +#define ST_MAXAMMO1X 314 +#define ST_MAXAMMO1Y 179 +#define ST_MAXAMMO2WIDTH ST_MAXAMMO0WIDTH +#define ST_MAXAMMO2X 314 +#define ST_MAXAMMO2Y 191 +#define ST_MAXAMMO3WIDTH ST_MAXAMMO0WIDTH +#define ST_MAXAMMO3X 314 +#define ST_MAXAMMO3Y 185 + +/* Dimensions given in characters. */ + +#define ST_MSGWIDTH 52 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* main player in game */ + +static player_t *plyr; + +/* st_start() has just been called */ + +static boolean st_firsttime; + +/* lump number for PLAYPAL */ + +static int lu_palette; + +/* used for making messages go away */ + +static int st_msgcounter = 0; + +/* whether left-side main status bar is active */ + +static boolean st_statusbaron; + +/* whether status bar chat is active */ + +static boolean st_chat; + +/* value of st_chat before message popped up */ + +static boolean st_oldchat; + +/* !deathmatch */ + +static boolean st_notdeathmatch; + +/* !deathmatch && st_statusbaron */ + +static boolean st_armson; + +/* !deathmatch */ + +static boolean st_fragson; + +/* main bar left */ + +static patch_t *sbar; + +/* main bar right, for doom 1.0 */ + +static patch_t *sbarr; + +/* 0-9, tall numbers */ + +static patch_t *tallnum[10]; + +/* tall % sign */ + +static patch_t *tallpercent; -// ST_Start() has just been called -static boolean st_firsttime; +/* 0-9, short, yellow (,different!) numbers */ -// lump number for PLAYPAL -static int lu_palette; +static patch_t *shortnum[10]; -// used for making messages go away -static int st_msgcounter=0; +/* 3 key-cards, 3 skulls */ -// whether left-side main status bar is active -static boolean st_statusbaron; +static patch_t *keys[NUMCARDS]; -// whether status bar chat is active -static boolean st_chat; +/* face status patches */ -// value of st_chat before message popped up -static boolean st_oldchat; +static patch_t *faces[ST_NUMFACES]; -// !deathmatch -static boolean st_notdeathmatch; +/* face background */ -// !deathmatch && st_statusbaron -static boolean st_armson; +static patch_t *faceback; -// !deathmatch -static boolean st_fragson; +/* main bar right */ -// main bar left -static patch_t* sbar; +static patch_t *armsbg; -// main bar right, for doom 1.0 -static patch_t* sbarr; +/* weapon ownership patches */ -// 0-9, tall numbers -static patch_t* tallnum[10]; +static patch_t *arms[6][2]; -// tall % sign -static patch_t* tallpercent; +/* ready-weapon widget */ -// 0-9, short, yellow (,different!) numbers -static patch_t* shortnum[10]; +static st_number_t w_ready; -// 3 key-cards, 3 skulls -static patch_t* keys[NUMCARDS]; +/* in deathmatch only, summary of frags stats */ -// face status patches -static patch_t* faces[ST_NUMFACES]; +static st_number_t w_frags; -// face background -static patch_t* faceback; +/* health widget */ - // main bar right -static patch_t* armsbg; +static st_percent_t w_health; -// weapon ownership patches -static patch_t* arms[6][2]; +/* arms background */ -// ready-weapon widget -static st_number_t w_ready; +static st_binicon_t w_armsbg; - // in deathmatch only, summary of frags stats -static st_number_t w_frags; +/* weapon ownership widgets */ -// health widget -static st_percent_t w_health; +static st_multicon_t w_arms[6]; -// arms background -static st_binicon_t w_armsbg; +/* face status widget */ +static st_multicon_t w_faces; -// weapon ownership widgets -static st_multicon_t w_arms[6]; +/* keycard widgets */ -// face status widget -static st_multicon_t w_faces; +static st_multicon_t w_keyboxes[3]; -// keycard widgets -static st_multicon_t w_keyboxes[3]; +/* armor widget */ -// armor widget -static st_percent_t w_armor; +static st_percent_t w_armor; -// ammo widgets -static st_number_t w_ammo[4]; +/* ammo widgets */ -// max ammo widgets -static st_number_t w_maxammo[4]; +static st_number_t w_ammo[4]; +/* max ammo widgets */ +static st_number_t w_maxammo[4]; - // number of frags so far in deathmatch -static int st_fragscount; +/* number of frags so far in deathmatch */ -// used to use appopriately pained face -static int st_oldhealth = -1; +static int st_fragscount; -// used for evil grin -static boolean oldweaponsowned[NUMWEAPONS]; +/* used to use appropriately pained face */ - // count until face changes -static int st_facecount = 0; +static int st_oldhealth = -1; -// current face index, used by w_faces -static int st_faceindex = 0; +/* used for evil grin */ -// holds key-type for each key box on bar -static int keyboxes[3]; +static boolean oldweaponsowned[NUMWEAPONS]; -// a random number per tick -static int st_randomnumber; +/* count until face changes */ + +static int st_facecount = 0; + +/* current face index, used by w_faces */ + +static int st_faceindex = 0; + +/* holds key-type for each key box on bar */ + +static int keyboxes[3]; + +/* a random number per tick */ + +static int st_randomnumber; + +static int st_palette = 0; + +static boolean st_stopped = true; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* graphics are drawn to a backing screen and blitted to the real screen */ + +pixel_t *st_backing_screen; cheatseq_t cheat_mus = CHEAT("idmus", 2); cheatseq_t cheat_god = CHEAT("iddqd", 0); @@ -319,1049 +400,1017 @@ cheatseq_t cheat_ammonokey = CHEAT("idfa", 0); cheatseq_t cheat_noclip = CHEAT("idspispopd", 0); cheatseq_t cheat_commercial_noclip = CHEAT("idclip", 0); -cheatseq_t cheat_powerup[7] = +cheatseq_t cheat_powerup[7] = { - CHEAT("idbeholdv", 0), - CHEAT("idbeholds", 0), - CHEAT("idbeholdi", 0), - CHEAT("idbeholdr", 0), - CHEAT("idbeholda", 0), - CHEAT("idbeholdl", 0), - CHEAT("idbehold", 0), + CHEAT("idbeholdv", 0), CHEAT("idbeholds", 0), CHEAT("idbeholdi", 0), + CHEAT("idbeholdr", 0), CHEAT("idbeholda", 0), CHEAT("idbeholdl", 0), + CHEAT("idbehold", 0), }; cheatseq_t cheat_choppers = CHEAT("idchoppers", 0); cheatseq_t cheat_clev = CHEAT("idclev", 2); cheatseq_t cheat_mypos = CHEAT("idmypos", 0); +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// -// STATUS BAR CODE -// -void ST_Stop(void); - -void ST_refreshBackground(void) +static void st_stop(void) { + if (st_stopped) return; - if (st_statusbaron) + i_set_palette(w_cache_lump_num(lu_palette, PU_CACHE)); + st_stopped = true; +} + +static void st_refresh_background(void) +{ + if (st_statusbaron) { - V_UseBuffer(st_backing_screen); + v_use_buffer(st_backing_screen); - V_DrawPatch(ST_X, 0, sbar); + v_draw_patch(ST_X, 0, sbar); - // draw right side of bar if needed (Doom 1.0) - if (sbarr) - V_DrawPatch(ST_ARMSBGX, 0, sbarr); + /* draw right side of bar if needed (Doom 1.0) */ - if (netgame) - V_DrawPatch(ST_FX, 0, faceback); + if (sbarr) v_draw_patch(ST_ARMSBGX, 0, sbarr); - V_RestoreBuffer(); + if (netgame) v_draw_patch(ST_FX, 0, faceback); - V_CopyRect(ST_X, 0, st_backing_screen, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y); - } + v_restore_buffer(); + v_copy_rect(ST_X, 0, st_backing_screen, ST_WIDTH, ST_HEIGHT, ST_X, + ST_Y); + } } - -// Respond to keyboard input events, -// intercept cheats. -boolean -ST_Responder (event_t* ev) +static int st_calc_paint_offset(void) { - int i; - - // Filter automap on/off. - if (ev->type == ev_keyup - && ((ev->data1 & 0xffff0000) == AM_MSGHEADER)) - { - switch(ev->data1) + int health; + static int lastcalc; + static int oldhealth = -1; + + health = plyr->health > 100 ? 100 : plyr->health; + + if (health != oldhealth) { - case AM_MSGENTERED: - st_firsttime = true; - break; - - case AM_MSGEXITED: - // fprintf(stderr, "AM exited\n"); - break; + lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101); + oldhealth = health; } - } - // if a user keypress... - else if (ev->type == ev_keydown) - { - if (!netgame && gameskill != sk_nightmare) + return lastcalc; +} + +/* This is a not-very-pretty routine which handles the face states and their + * timing. the precedence of expressions is: dead > evil grin > turned head > + * straight ahead + */ + +static void st_update_face_widget(void) +{ + int i; + angle_t badguyangle; + angle_t diffang; + static int lastattackdown = -1; + static int priority = 0; + boolean doevilgrin; + + if (priority < 10) { - // 'dqd' cheat for toggleable god mode - if (cht_CheckCheat(&cheat_god, ev->data2)) - { - plyr->cheats ^= CF_GODMODE; - if (plyr->cheats & CF_GODMODE) - { - if (plyr->mo) - plyr->mo->health = deh_god_mode_health; - - plyr->health = deh_god_mode_health; - plyr->message = DEH_String(STSTR_DQDON); - } - else - plyr->message = DEH_String(STSTR_DQDOFF); - } - // 'fa' cheat for killer fucking arsenal - else if (cht_CheckCheat(&cheat_ammonokey, ev->data2)) - { - plyr->armorpoints = deh_idfa_armor; - plyr->armortype = deh_idfa_armor_class; - - for (i=0;iweaponowned[i] = true; - - for (i=0;iammo[i] = plyr->maxammo[i]; - - plyr->message = DEH_String(STSTR_FAADDED); - } - // 'kfa' cheat for key full ammo - else if (cht_CheckCheat(&cheat_ammo, ev->data2)) - { - plyr->armorpoints = deh_idkfa_armor; - plyr->armortype = deh_idkfa_armor_class; - - for (i=0;iweaponowned[i] = true; - - for (i=0;iammo[i] = plyr->maxammo[i]; - - for (i=0;icards[i] = true; - - plyr->message = DEH_String(STSTR_KFAADDED); - } - // 'mus' cheat for changing music - else if (cht_CheckCheat(&cheat_mus, ev->data2)) - { - - char buf[3]; - int musnum; - - plyr->message = DEH_String(STSTR_MUS); - cht_GetParam(&cheat_mus, buf); - - // Note: The original v1.9 had a bug that tried to play back - // the Doom II music regardless of gamemode. This was fixed - // in the Ultimate Doom executable so that it would work for - // the Doom 1 music as well. - - if (gamemode == commercial || gameversion < exe_ultimate) - { - musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1; - - if (((buf[0]-'0')*10 + buf[1]-'0') > 35 - && gameversion >= exe_doom_1_8) - plyr->message = DEH_String(STSTR_NOMUS); - else - S_ChangeMusic(musnum, 1); - } - else - { - musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1'); - - if (((buf[0]-'1')*9 + buf[1]-'1') > 31) - plyr->message = DEH_String(STSTR_NOMUS); - else - S_ChangeMusic(musnum, 1); - } - } - else if ( (logical_gamemission == doom - && cht_CheckCheat(&cheat_noclip, ev->data2)) - || (logical_gamemission != doom - && cht_CheckCheat(&cheat_commercial_noclip,ev->data2))) - { - // Noclip cheat. - // For Doom 1, use the idspipsopd cheat; for all others, use - // idclip - - plyr->cheats ^= CF_NOCLIP; - - if (plyr->cheats & CF_NOCLIP) - plyr->message = DEH_String(STSTR_NCON); - else - plyr->message = DEH_String(STSTR_NCOFF); - } - // 'behold?' power-up cheats - for (i=0;i<6;i++) - { - if (cht_CheckCheat(&cheat_powerup[i], ev->data2)) - { - if (!plyr->powers[i]) - P_GivePower( plyr, i); - else if (i!=pw_strength) - plyr->powers[i] = 1; - else - plyr->powers[i] = 0; - - plyr->message = DEH_String(STSTR_BEHOLDX); - } - } - - // 'behold' power-up menu - if (cht_CheckCheat(&cheat_powerup[6], ev->data2)) - { - plyr->message = DEH_String(STSTR_BEHOLD); - } - // 'choppers' invulnerability & chainsaw - else if (cht_CheckCheat(&cheat_choppers, ev->data2)) - { - plyr->weaponowned[wp_chainsaw] = true; - plyr->powers[pw_invulnerability] = true; - plyr->message = DEH_String(STSTR_CHOPPERS); - } - // 'mypos' for player position - else if (cht_CheckCheat(&cheat_mypos, ev->data2)) - { - static char buf[ST_MSGWIDTH]; - M_snprintf(buf, sizeof(buf), "ang=0x%x;x,y=(0x%x,0x%x)", - players[consoleplayer].mo->angle, - players[consoleplayer].mo->x, - players[consoleplayer].mo->y); - plyr->message = buf; - } + /* dead */ + + if (!plyr->health) + { + priority = 9; + st_faceindex = ST_DEADFACE; + st_facecount = 1; + } } - - // 'clev' change-level cheat - if (!netgame && cht_CheckCheat(&cheat_clev, ev->data2)) + + if (priority < 9) { - char buf[3]; - int epsd; - int map; - - cht_GetParam(&cheat_clev, buf); - - if (gamemode == commercial) - { - epsd = 0; - map = (buf[0] - '0')*10 + buf[1] - '0'; - } - else - { - epsd = buf[0] - '0'; - map = buf[1] - '0'; + if (plyr->bonuscount) + { + /* picking up bonus */ - // Chex.exe always warps to episode 1. + doevilgrin = false; - if (gameversion == exe_chex) - { - if (epsd > 1) + for (i = 0; i < NUMWEAPONS; i++) { - epsd = 1; + if (oldweaponsowned[i] != plyr->weaponowned[i]) + { + doevilgrin = true; + oldweaponsowned[i] = plyr->weaponowned[i]; + } } - if (map > 5) + + if (doevilgrin) { - map = 5; + /* evil grin if just picked up weapon */ + + priority = 8; + st_facecount = ST_EVILGRINCOUNT; + st_faceindex = st_calc_paint_offset() + ST_EVILGRINOFFSET; } } - } - - // Catch invalid maps. - if (gamemode != commercial) - { - if (epsd < 1) - { - return false; - } - if (epsd > 4) - { - return false; - } - if (epsd == 4 && gameversion < exe_ultimate) - { - return false; - } - if (map < 1) - { - return false; - } - if (map > 9) - { - return false; - } - } - else - { - if (map < 1) - { - return false; - } - if (map > 40) - { - return false; - } - } - - // So be it. - plyr->message = DEH_String(STSTR_CLEV); - G_DeferedInitNew(gameskill, epsd, map); } - } - return false; -} - - - -int ST_calcPainOffset(void) -{ - int health; - static int lastcalc; - static int oldhealth = -1; - - health = plyr->health > 100 ? 100 : plyr->health; - if (health != oldhealth) + if (priority < 8) { - lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101); - oldhealth = health; - } - return lastcalc; -} + if (plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo) + { + /* being attacked */ + priority = 7; -// -// This is a not-very-pretty routine which handles -// the face states and their timing. -// the precedence of expressions is: -// dead > evil grin > turned head > straight ahead -// -void ST_updateFaceWidget(void) -{ - int i; - angle_t badguyangle; - angle_t diffang; - static int lastattackdown = -1; - static int priority = 0; - boolean doevilgrin; - - if (priority < 10) - { - // dead - if (!plyr->health) - { - priority = 9; - st_faceindex = ST_DEADFACE; - st_facecount = 1; - } + if (plyr->health - st_oldhealth > ST_MUCHPAIN) + { + st_facecount = ST_TURNCOUNT; + st_faceindex = st_calc_paint_offset() + ST_OUCHOFFSET; + } + else + { + badguyangle = + r_point_to_angle2(plyr->mo->x, plyr->mo->y, + plyr->attacker->x, plyr->attacker->y); + + if (badguyangle > plyr->mo->angle) + { + /* whether right or left */ + + diffang = badguyangle - plyr->mo->angle; + i = diffang > ANG180; + } + else + { + /* whether left or right */ + + diffang = plyr->mo->angle - badguyangle; + i = diffang <= ANG180; + } + + /* confusing, aint it? */ + + st_facecount = ST_TURNCOUNT; + st_faceindex = st_calc_paint_offset(); + + if (diffang < ANG45) + { + /* head-on */ + + st_faceindex += ST_RAMPAGEOFFSET; + } + else if (i) + { + /* turn face right */ + + st_faceindex += ST_TURNOFFSET; + } + else + { + /* turn face left */ + + st_faceindex += ST_TURNOFFSET + 1; + } + } + } } - if (priority < 9) + if (priority < 7) { - if (plyr->bonuscount) - { - // picking up bonus - doevilgrin = false; - - for (i=0;iweaponowned[i]) - { - doevilgrin = true; - oldweaponsowned[i] = plyr->weaponowned[i]; - } - } - if (doevilgrin) - { - // evil grin if just picked up weapon - priority = 8; - st_facecount = ST_EVILGRINCOUNT; - st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET; - } - } + /* getting hurt because of your own damn stupidity */ + if (plyr->damagecount) + { + if (plyr->health - st_oldhealth > ST_MUCHPAIN) + { + priority = 7; + st_facecount = ST_TURNCOUNT; + st_faceindex = st_calc_paint_offset() + ST_OUCHOFFSET; + } + else + { + priority = 6; + st_facecount = ST_TURNCOUNT; + st_faceindex = st_calc_paint_offset() + ST_RAMPAGEOFFSET; + } + } } - - if (priority < 8) - { - if (plyr->damagecount - && plyr->attacker - && plyr->attacker != plyr->mo) - { - // being attacked - priority = 7; - - if (plyr->health - st_oldhealth > ST_MUCHPAIN) - { - st_facecount = ST_TURNCOUNT; - st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; - } - else - { - badguyangle = R_PointToAngle2(plyr->mo->x, - plyr->mo->y, - plyr->attacker->x, - plyr->attacker->y); - - if (badguyangle > plyr->mo->angle) - { - // whether right or left - diffang = badguyangle - plyr->mo->angle; - i = diffang > ANG180; - } - else - { - // whether left or right - diffang = plyr->mo->angle - badguyangle; - i = diffang <= ANG180; - } // confusing, aint it? - - - st_facecount = ST_TURNCOUNT; - st_faceindex = ST_calcPainOffset(); - - if (diffang < ANG45) - { - // head-on - st_faceindex += ST_RAMPAGEOFFSET; - } - else if (i) - { - // turn face right - st_faceindex += ST_TURNOFFSET; - } - else - { - // turn face left - st_faceindex += ST_TURNOFFSET+1; - } - } - } - } - - if (priority < 7) - { - // getting hurt because of your own damn stupidity - if (plyr->damagecount) - { - if (plyr->health - st_oldhealth > ST_MUCHPAIN) - { - priority = 7; - st_facecount = ST_TURNCOUNT; - st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET; - } - else - { - priority = 6; - st_facecount = ST_TURNCOUNT; - st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; - } - - } - } - - if (priority < 6) + if (priority < 6) { - // rapid firing - if (plyr->attackdown) - { - if (lastattackdown==-1) - lastattackdown = ST_RAMPAGEDELAY; - else if (!--lastattackdown) - { - priority = 5; - st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET; - st_facecount = 1; - lastattackdown = 1; - } - } - else - lastattackdown = -1; + /* rapid firing */ + if (plyr->attackdown) + { + if (lastattackdown == -1) + lastattackdown = ST_RAMPAGEDELAY; + else if (!--lastattackdown) + { + priority = 5; + st_faceindex = st_calc_paint_offset() + ST_RAMPAGEOFFSET; + st_facecount = 1; + lastattackdown = 1; + } + } + else + lastattackdown = -1; } - - if (priority < 5) - { - // invulnerability - if ((plyr->cheats & CF_GODMODE) - || plyr->powers[pw_invulnerability]) - { - priority = 4; - st_faceindex = ST_GODFACE; - st_facecount = 1; + if (priority < 5) + { + /* invulnerability */ - } + if ((plyr->cheats & CF_GODMODE) || plyr->powers[pw_invulnerability]) + { + priority = 4; + st_faceindex = ST_GODFACE; + st_facecount = 1; + } } - // look left or look right if the facecount has timed out - if (!st_facecount) + /* look left or look right if the facecount has timed out */ + + if (!st_facecount) { - st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3); - st_facecount = ST_STRAIGHTFACECOUNT; - priority = 0; + st_faceindex = st_calc_paint_offset() + (st_randomnumber % 3); + st_facecount = ST_STRAIGHTFACECOUNT; + priority = 0; } - st_facecount--; - + st_facecount--; } -void ST_updateWidgets(void) +static void st_update_widgets(void) { - static int largeammo = 1994; // means "n/a" - int i; - - // must redirect the pointer if the ready weapon has changed. - // if (w_ready.data != plyr->readyweapon) - // { - if (weaponinfo[plyr->readyweapon].ammo == am_noammo) - w_ready.num = &largeammo; - else - w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo]; - //{ - // static int tic=0; - // static int dir=-1; - // if (!(tic&15)) - // plyr->ammo[weaponinfo[plyr->readyweapon].ammo]+=dir; - // if (plyr->ammo[weaponinfo[plyr->readyweapon].ammo] == -100) - // dir = 1; - // tic++; - // } - w_ready.data = plyr->readyweapon; - - // if (*w_ready.on) - // STlib_updateNum(&w_ready, true); - // refresh weapon change - // } - - // update keycard multiple widgets - for (i=0;i<3;i++) + static int largeammo = 1994; /* means "n/a" */ + int i; + + /* must redirect the pointer if the ready weapon has changed. + * if (w_ready.data != plyr->readyweapon) + * { + */ + + if (weaponinfo[plyr->readyweapon].ammo == am_noammo) + w_ready.num = &largeammo; + else + w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo]; + + /* { + * static int tic=0; + * static int dir=-1; + * if (!(tic&15)) + * plyr->ammo[weaponinfo[plyr->readyweapon].ammo]+=dir; + * if (plyr->ammo[weaponinfo[plyr->readyweapon].ammo] == -100) + * dir = 1; + * tic++; + * } + */ + + w_ready.data = plyr->readyweapon; + + /* if (*w_ready.on) + * stlib_update_num(&w_ready, true); + * refresh weapon change + * } + */ + + /* update keycard multiple widgets */ + + for (i = 0; i < 3; i++) { - keyboxes[i] = plyr->cards[i] ? i : -1; + keyboxes[i] = plyr->cards[i] ? i : -1; - if (plyr->cards[i+3]) - keyboxes[i] = i+3; + if (plyr->cards[i + 3]) keyboxes[i] = i + 3; } - // refresh everything if this is him coming back to life - ST_updateFaceWidget(); + /* refresh everything if this is him coming back to life */ - // used by the w_armsbg widget - st_notdeathmatch = !deathmatch; - - // used by w_arms[] widgets - st_armson = st_statusbaron && !deathmatch; + st_update_face_widget(); - // used by w_frags widget - st_fragson = deathmatch && st_statusbaron; - st_fragscount = 0; + /* used by the w_armsbg widget */ - for (i=0 ; ifrags[i]; - else - st_fragscount -= plyr->frags[i]; - } + st_notdeathmatch = !deathmatch; - // get rid of chat window if up because of message - if (!--st_msgcounter) - st_chat = st_oldchat; + /* used by w_arms[] widgets */ -} + st_armson = st_statusbaron && !deathmatch; -void ST_Ticker (void) -{ + /* used by w_frags widget */ - st_randomnumber = M_Random(); - ST_updateWidgets(); - st_oldhealth = plyr->health; + st_fragson = deathmatch && st_statusbaron; + st_fragscount = 0; -} + for (i = 0; i < MAXPLAYERS; i++) + { + if (i != consoleplayer) + st_fragscount += plyr->frags[i]; + else + st_fragscount -= plyr->frags[i]; + } -static int st_palette = 0; + /* get rid of chat window if up because of message */ -void ST_doPaletteStuff(void) -{ + if (!--st_msgcounter) st_chat = st_oldchat; +} - int palette; - byte* pal; - int cnt; - int bzc; +static void st_do_palette_stuff(void) +{ + int palette; + byte *pal; + int cnt; + int bzc; - cnt = plyr->damagecount; + cnt = plyr->damagecount; - if (plyr->powers[pw_strength]) + if (plyr->powers[pw_strength]) { - // slowly fade the berzerk out - bzc = 12 - (plyr->powers[pw_strength]>>6); + /* slowly fade the berzerk out */ + + bzc = 12 - (plyr->powers[pw_strength] >> 6); - if (bzc > cnt) - cnt = bzc; + if (bzc > cnt) cnt = bzc; } - - if (cnt) + + if (cnt) { - palette = (cnt+7)>>3; - - if (palette >= NUMREDPALS) - palette = NUMREDPALS-1; + palette = (cnt + 7) >> 3; + + if (palette >= NUMREDPALS) palette = NUMREDPALS - 1; - palette += STARTREDPALS; + palette += STARTREDPALS; } - else if (plyr->bonuscount) + else if (plyr->bonuscount) { - palette = (plyr->bonuscount+7)>>3; + palette = (plyr->bonuscount + 7) >> 3; - if (palette >= NUMBONUSPALS) - palette = NUMBONUSPALS-1; + if (palette >= NUMBONUSPALS) palette = NUMBONUSPALS - 1; - palette += STARTBONUSPALS; + palette += STARTBONUSPALS; } - else if ( plyr->powers[pw_ironfeet] > 4*32 - || plyr->powers[pw_ironfeet]&8) - palette = RADIATIONPAL; - else - palette = 0; + else if (plyr->powers[pw_ironfeet] > 4 * 32 || + plyr->powers[pw_ironfeet] & 8) + palette = RADIATIONPAL; + else + palette = 0; - // In Chex Quest, the player never sees red. Instead, the - // radiation suit palette is used to tint the screen green, - // as though the player is being covered in goo by an - // attacking flemoid. + /* In Chex Quest, the player never sees red. Instead, the + * radiation suit palette is used to tint the screen green, + * as though the player is being covered in goo by an + * attacking flemoid. + */ - if (gameversion == exe_chex - && palette >= STARTREDPALS && palette < STARTREDPALS + NUMREDPALS) + if (gameversion == exe_chex && palette >= STARTREDPALS && + palette < STARTREDPALS + NUMREDPALS) { - palette = RADIATIONPAL; + palette = RADIATIONPAL; } - if (palette != st_palette) + if (palette != st_palette) { - st_palette = palette; - pal = (byte *) W_CacheLumpNum (lu_palette, PU_CACHE)+palette*768; - I_SetPalette (pal); + st_palette = palette; + pal = (byte *)w_cache_lump_num(lu_palette, PU_CACHE) + palette * 768; + i_set_palette(pal); } - } -void ST_drawWidgets(boolean refresh) +static void st_draw_widgets(boolean refresh) { - int i; + int i; + + /* used by w_arms[] widgets */ - // used by w_arms[] widgets - st_armson = st_statusbaron && !deathmatch; + st_armson = st_statusbaron && !deathmatch; - // used by w_frags widget - st_fragson = deathmatch && st_statusbaron; + /* used by w_frags widget */ - STlib_updateNum(&w_ready, refresh); + st_fragson = deathmatch && st_statusbaron; - for (i=0;i<4;i++) + stlib_update_num(&w_ready, refresh); + + for (i = 0; i < 4; i++) { - STlib_updateNum(&w_ammo[i], refresh); - STlib_updateNum(&w_maxammo[i], refresh); + stlib_update_num(&w_ammo[i], refresh); + stlib_update_num(&w_maxammo[i], refresh); } - STlib_updatePercent(&w_health, refresh); - STlib_updatePercent(&w_armor, refresh); - - STlib_updateBinIcon(&w_armsbg, refresh); + stlib_update_percent(&w_health, refresh); + stlib_update_percent(&w_armor, refresh); - for (i=0;i<6;i++) - STlib_updateMultIcon(&w_arms[i], refresh); + stlib_update_bin_icon(&w_armsbg, refresh); - STlib_updateMultIcon(&w_faces, refresh); + for (i = 0; i < 6; i++) + stlib_update_mult_icon(&w_arms[i], refresh); - for (i=0;i<3;i++) - STlib_updateMultIcon(&w_keyboxes[i], refresh); + stlib_update_mult_icon(&w_faces, refresh); - STlib_updateNum(&w_frags, refresh); + for (i = 0; i < 3; i++) + stlib_update_mult_icon(&w_keyboxes[i], refresh); + stlib_update_num(&w_frags, refresh); } -void ST_doRefresh(void) +static void st_do_refresh(void) { + st_firsttime = false; - st_firsttime = false; + /* draw status bar background to off-screen buff */ - // draw status bar background to off-screen buff - ST_refreshBackground(); + st_refresh_background(); - // and refresh all widgets - ST_drawWidgets(true); + /* and refresh all widgets */ + st_draw_widgets(true); } -void ST_diffDraw(void) +static void st_diff_draw(void) { - // update all widgets - ST_drawWidgets(false); + /* update all widgets */ + + st_draw_widgets(false); } -void ST_Drawer (boolean fullscreen, boolean refresh) +/* Iterates through all graphics to be loaded or unloaded, along with + * the variable they use, invoking the specified callback function. + */ + +static void st_load_unload_graphics(load_callback_t callback) { - - st_statusbaron = (!fullscreen) || automapactive; - st_firsttime = st_firsttime || refresh; + int i; + int j; + int facenum; - // Do red-/gold-shifts from damage/items - ST_doPaletteStuff(); + char namebuf[9]; - // If just after ST_Start(), refresh all - if (st_firsttime) ST_doRefresh(); - // Otherwise, update as little as possible - else ST_diffDraw(); + /* Load the numbers, tall and short */ -} + for (i = 0; i < 10; i++) + { + snprintf(namebuf, 9, "STTNUM%d", i); + callback(namebuf, &tallnum[i]); -typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + snprintf(namebuf, 9, "STYSNUM%d", i); + callback(namebuf, &shortnum[i]); + } -// Iterates through all graphics to be loaded or unloaded, along with -// the variable they use, invoking the specified callback function. + /* Load percent key. + * Note: why not load STMINUS here, too? + */ -static void ST_loadUnloadGraphics(load_callback_t callback) -{ + callback(("STTPRCNT"), &tallpercent); - int i; - int j; - int facenum; - - char namebuf[9]; + /* key cards */ - // Load the numbers, tall and short - for (i=0;i<10;i++) + for (i = 0; i < NUMCARDS; i++) { - DEH_snprintf(namebuf, 9, "STTNUM%d", i); - callback(namebuf, &tallnum[i]); - - DEH_snprintf(namebuf, 9, "STYSNUM%d", i); - callback(namebuf, &shortnum[i]); + snprintf(namebuf, 9, "STKEYS%d", i); + callback(namebuf, &keys[i]); } - // Load percent key. - //Note: why not load STMINUS here, too? + /* arms background */ + + callback(("STARMS"), &armsbg); - callback(DEH_String("STTPRCNT"), &tallpercent); + /* arms ownership widgets */ - // key cards - for (i=0;i= 0) + /* status bar background bits */ + + if (w_check_num_for_name("STBAR") >= 0) { - callback(DEH_String("STBAR"), &sbar); - sbarr = NULL; + callback(("STBAR"), &sbar); + sbarr = NULL; } - else + else { - callback(DEH_String("STMBARL"), &sbar); - callback(DEH_String("STMBARR"), &sbarr); + callback(("STMBARL"), &sbar); + callback(("STMBARR"), &sbarr); } - // face states - facenum = 0; - for (i=0; iweaponowned[i]; + + for (i = 0; i < 3; i++) + keyboxes[i] = -1; + + stlib_init(); } -void ST_initData(void) +static void st_create_widgets(void) { + int i; + + /* ready weapon ammo */ + + stlib_init_num(&w_ready, ST_AMMOX, ST_AMMOY, tallnum, + &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], + &st_statusbaron, ST_AMMOWIDTH); + + /* the last weapon type */ + + w_ready.data = plyr->readyweapon; + + /* health percentage */ + + stlib_init_percent(&w_health, ST_HEALTHX, ST_HEALTHY, tallnum, + &plyr->health, &st_statusbaron, tallpercent); + + /* arms background */ + + stlib_init_bin_icon(&w_armsbg, ST_ARMSBGX, ST_ARMSBGY, armsbg, + &st_notdeathmatch, &st_statusbaron); + + /* weapons owned */ + + for (i = 0; i < 6; i++) + { + stlib_init_mutl_icon(&w_arms[i], ST_ARMSX + (i % 3) * ST_ARMSXSPACE, + ST_ARMSY + (i / 3) * ST_ARMSYSPACE, arms[i], + &plyr->weaponowned[i + 1], &st_armson); + } + + /* frags sum */ - int i; + stlib_init_num(&w_frags, ST_FRAGSX, ST_FRAGSY, tallnum, &st_fragscount, + &st_fragson, ST_FRAGSWIDTH); - st_firsttime = true; - plyr = &players[consoleplayer]; + /* faces */ - st_statusbaron = true; - st_oldchat = st_chat = false; + stlib_init_mutl_icon(&w_faces, ST_FACESX, ST_FACESY, faces, &st_faceindex, + &st_statusbaron); - st_faceindex = 0; - st_palette = -1; + /* armor percentage - should be colored later */ - st_oldhealth = -1; + stlib_init_percent(&w_armor, ST_ARMORX, ST_ARMORY, tallnum, + &plyr->armorpoints, &st_statusbaron, tallpercent); - for (i=0;iweaponowned[i]; + /* keyboxes 0-2 */ - for (i=0;i<3;i++) - keyboxes[i] = -1; + stlib_init_mutl_icon(&w_keyboxes[0], ST_KEY0X, ST_KEY0Y, keys, + &keyboxes[0], &st_statusbaron); - STlib_init(); + stlib_init_mutl_icon(&w_keyboxes[1], ST_KEY1X, ST_KEY1Y, keys, + &keyboxes[1], &st_statusbaron); + stlib_init_mutl_icon(&w_keyboxes[2], ST_KEY2X, ST_KEY2Y, keys, + &keyboxes[2], &st_statusbaron); + + /* ammo count (all four kinds) */ + + stlib_init_num(&w_ammo[0], ST_AMMO0X, ST_AMMO0Y, shortnum, &plyr->ammo[0], + &st_statusbaron, ST_AMMO0WIDTH); + + stlib_init_num(&w_ammo[1], ST_AMMO1X, ST_AMMO1Y, shortnum, &plyr->ammo[1], + &st_statusbaron, ST_AMMO1WIDTH); + + stlib_init_num(&w_ammo[2], ST_AMMO2X, ST_AMMO2Y, shortnum, &plyr->ammo[2], + &st_statusbaron, ST_AMMO2WIDTH); + + stlib_init_num(&w_ammo[3], ST_AMMO3X, ST_AMMO3Y, shortnum, &plyr->ammo[3], + &st_statusbaron, ST_AMMO3WIDTH); + + /* max ammo count (all four kinds) */ + + stlib_init_num(&w_maxammo[0], ST_MAXAMMO0X, ST_MAXAMMO0Y, shortnum, + &plyr->maxammo[0], &st_statusbaron, ST_MAXAMMO0WIDTH); + + stlib_init_num(&w_maxammo[1], ST_MAXAMMO1X, ST_MAXAMMO1Y, shortnum, + &plyr->maxammo[1], &st_statusbaron, ST_MAXAMMO1WIDTH); + + stlib_init_num(&w_maxammo[2], ST_MAXAMMO2X, ST_MAXAMMO2Y, shortnum, + &plyr->maxammo[2], &st_statusbaron, ST_MAXAMMO2WIDTH); + + stlib_init_num(&w_maxammo[3], ST_MAXAMMO3X, ST_MAXAMMO3Y, shortnum, + &plyr->maxammo[3], &st_statusbaron, ST_MAXAMMO3WIDTH); } +/**************************************************************************** + * Public Function + ****************************************************************************/ +/* Respond to keyboard input events, intercept cheats. */ -void ST_createWidgets(void) +boolean st_responder(event_t *ev) { + int i; + + /* Filter automap on/off. */ - int i; - - // ready weapon ammo - STlib_initNum(&w_ready, - ST_AMMOX, - ST_AMMOY, - tallnum, - &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], - &st_statusbaron, - ST_AMMOWIDTH ); - - // the last weapon type - w_ready.data = plyr->readyweapon; - - // health percentage - STlib_initPercent(&w_health, - ST_HEALTHX, - ST_HEALTHY, - tallnum, - &plyr->health, - &st_statusbaron, - tallpercent); - - // arms background - STlib_initBinIcon(&w_armsbg, - ST_ARMSBGX, - ST_ARMSBGY, - armsbg, - &st_notdeathmatch, - &st_statusbaron); - - // weapons owned - for(i=0;i<6;i++) + if (ev->type == ev_keyup && ((ev->data1 & 0xffff0000) == AM_MSGHEADER)) { - STlib_initMultIcon(&w_arms[i], - ST_ARMSX+(i%3)*ST_ARMSXSPACE, - ST_ARMSY+(i/3)*ST_ARMSYSPACE, - arms[i], - &plyr->weaponowned[i+1], - &st_armson); + switch (ev->data1) + { + case AM_MSGENTERED: + st_firsttime = true; + break; + + case AM_MSGEXITED: + break; + } } - // frags sum - STlib_initNum(&w_frags, - ST_FRAGSX, - ST_FRAGSY, - tallnum, - &st_fragscount, - &st_fragson, - ST_FRAGSWIDTH); - - // faces - STlib_initMultIcon(&w_faces, - ST_FACESX, - ST_FACESY, - faces, - &st_faceindex, - &st_statusbaron); - - // armor percentage - should be colored later - STlib_initPercent(&w_armor, - ST_ARMORX, - ST_ARMORY, - tallnum, - &plyr->armorpoints, - &st_statusbaron, tallpercent); - - // keyboxes 0-2 - STlib_initMultIcon(&w_keyboxes[0], - ST_KEY0X, - ST_KEY0Y, - keys, - &keyboxes[0], - &st_statusbaron); - - STlib_initMultIcon(&w_keyboxes[1], - ST_KEY1X, - ST_KEY1Y, - keys, - &keyboxes[1], - &st_statusbaron); - - STlib_initMultIcon(&w_keyboxes[2], - ST_KEY2X, - ST_KEY2Y, - keys, - &keyboxes[2], - &st_statusbaron); - - // ammo count (all four kinds) - STlib_initNum(&w_ammo[0], - ST_AMMO0X, - ST_AMMO0Y, - shortnum, - &plyr->ammo[0], - &st_statusbaron, - ST_AMMO0WIDTH); - - STlib_initNum(&w_ammo[1], - ST_AMMO1X, - ST_AMMO1Y, - shortnum, - &plyr->ammo[1], - &st_statusbaron, - ST_AMMO1WIDTH); - - STlib_initNum(&w_ammo[2], - ST_AMMO2X, - ST_AMMO2Y, - shortnum, - &plyr->ammo[2], - &st_statusbaron, - ST_AMMO2WIDTH); - - STlib_initNum(&w_ammo[3], - ST_AMMO3X, - ST_AMMO3Y, - shortnum, - &plyr->ammo[3], - &st_statusbaron, - ST_AMMO3WIDTH); - - // max ammo count (all four kinds) - STlib_initNum(&w_maxammo[0], - ST_MAXAMMO0X, - ST_MAXAMMO0Y, - shortnum, - &plyr->maxammo[0], - &st_statusbaron, - ST_MAXAMMO0WIDTH); - - STlib_initNum(&w_maxammo[1], - ST_MAXAMMO1X, - ST_MAXAMMO1Y, - shortnum, - &plyr->maxammo[1], - &st_statusbaron, - ST_MAXAMMO1WIDTH); - - STlib_initNum(&w_maxammo[2], - ST_MAXAMMO2X, - ST_MAXAMMO2Y, - shortnum, - &plyr->maxammo[2], - &st_statusbaron, - ST_MAXAMMO2WIDTH); - - STlib_initNum(&w_maxammo[3], - ST_MAXAMMO3X, - ST_MAXAMMO3Y, - shortnum, - &plyr->maxammo[3], - &st_statusbaron, - ST_MAXAMMO3WIDTH); + /* if a user keypress... */ -} + else if (ev->type == ev_keydown) + { + if (!netgame && gameskill != sk_nightmare) + { + /* 'dqd' cheat for toggleable god mode */ -static boolean st_stopped = true; + if (cht_check_cheat(&cheat_god, ev->data2)) + { + plyr->cheats ^= CF_GODMODE; + if (plyr->cheats & CF_GODMODE) + { + if (plyr->mo) plyr->mo->health = deh_god_mode_health; + + plyr->health = deh_god_mode_health; + plyr->message = (STSTR_DQDON); + } + else + plyr->message = (STSTR_DQDOFF); + } + /* 'fa' cheat for killer fucking arsenal */ -void ST_Start (void) -{ + else if (cht_check_cheat(&cheat_ammonokey, ev->data2)) + { + plyr->armorpoints = deh_idfa_armor; + plyr->armortype = deh_idfa_armor_class; + + for (i = 0; i < NUMWEAPONS; i++) + plyr->weaponowned[i] = true; + + for (i = 0; i < NUMAMMO; i++) + plyr->ammo[i] = plyr->maxammo[i]; + + plyr->message = (STSTR_FAADDED); + } + + /* 'kfa' cheat for key full ammo */ + + else if (cht_check_cheat(&cheat_ammo, ev->data2)) + { + plyr->armorpoints = deh_idkfa_armor; + plyr->armortype = deh_idkfa_armor_class; + + for (i = 0; i < NUMWEAPONS; i++) + plyr->weaponowned[i] = true; + + for (i = 0; i < NUMAMMO; i++) + plyr->ammo[i] = plyr->maxammo[i]; + + for (i = 0; i < NUMCARDS; i++) + plyr->cards[i] = true; + + plyr->message = (STSTR_KFAADDED); + } + + /* 'mus' cheat for changing music */ + + else if (cht_check_cheat(&cheat_mus, ev->data2)) + { + char buf[3]; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + int musnum; +#endif + + plyr->message = (STSTR_MUS); + ch_get_param(&cheat_mus, buf); + + /* Note: The original v1.9 had a bug that tried to play back + * the Doom II music regardless of gamemode. This was fixed + * in the Ultimate Doom executable so that it would work for + * the Doom 1 music as well. + */ + + if (gamemode == commercial || gameversion < exe_ultimate) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + musnum = + MUS_RUNNIN + (buf[0] - '0') * 10 + buf[1] - '0' - 1; +#endif + + if (((buf[0] - '0') * 10 + buf[1] - '0') > 35 && + gameversion >= exe_doom_1_8) + plyr->message = (STSTR_NOMUS); + else + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_change_music(musnum, 1); +#endif + } + } + else + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + musnum = MUS_E1M1 + (buf[0] - '1') * 9 + (buf[1] - '1'); +#endif + + if (((buf[0] - '1') * 9 + buf[1] - '1') > 31) + plyr->message = (STSTR_NOMUS); + else + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_change_music(musnum, 1); +#endif + } + } + } + else if ((logical_gamemission == doom && + cht_check_cheat(&cheat_noclip, ev->data2)) || + (logical_gamemission != doom && + cht_check_cheat(&cheat_commercial_noclip, ev->data2))) + { + /* Noclip cheat. + * For Doom 1, use the idspipsopd cheat; for all others, use + * idclip + */ + + plyr->cheats ^= CF_NOCLIP; + + if (plyr->cheats & CF_NOCLIP) + plyr->message = (STSTR_NCON); + else + plyr->message = (STSTR_NCOFF); + } + + /* 'behold?' power-up cheats */ + + for (i = 0; i < 6; i++) + { + if (cht_check_cheat(&cheat_powerup[i], ev->data2)) + { + if (!plyr->powers[i]) + p_give_power(plyr, i); + else if (i != pw_strength) + plyr->powers[i] = 1; + else + plyr->powers[i] = 0; + + plyr->message = (STSTR_BEHOLDX); + } + } + + /* 'behold' power-up menu */ + + if (cht_check_cheat(&cheat_powerup[6], ev->data2)) + { + plyr->message = (STSTR_BEHOLD); + } + + /* 'choppers' invulnerability & chainsaw */ + + else if (cht_check_cheat(&cheat_choppers, ev->data2)) + { + plyr->weaponowned[wp_chainsaw] = true; + plyr->powers[pw_invulnerability] = true; + plyr->message = (STSTR_CHOPPERS); + } + + /* 'mypos' for player position */ - if (!st_stopped) - ST_Stop(); + else if (cht_check_cheat(&cheat_mypos, ev->data2)) + { + static char buf[ST_MSGWIDTH]; + snprintf(buf, sizeof(buf), "ang=0x%x;x,y=(0x%x,0x%x)", + players[consoleplayer].mo->angle, + players[consoleplayer].mo->x, + players[consoleplayer].mo->y); + plyr->message = buf; + } + } + + /* 'clev' change-level cheat */ + + if (!netgame && cht_check_cheat(&cheat_clev, ev->data2)) + { + char buf[3]; + int epsd; + int map; - ST_initData(); - ST_createWidgets(); - st_stopped = false; + ch_get_param(&cheat_clev, buf); + if (gamemode == commercial) + { + epsd = 0; + map = (buf[0] - '0') * 10 + buf[1] - '0'; + } + else + { + epsd = buf[0] - '0'; + map = buf[1] - '0'; + + /* Chex.exe always warps to episode 1. */ + + if (gameversion == exe_chex) + { + if (epsd > 1) + { + epsd = 1; + } + + if (map > 5) + { + map = 5; + } + } + } + + /* Catch invalid maps. */ + + if (gamemode != commercial) + { + if (epsd < 1) + { + return false; + } + + if (epsd > 4) + { + return false; + } + + if (epsd == 4 && gameversion < exe_ultimate) + { + return false; + } + + if (map < 1) + { + return false; + } + + if (map > 9) + { + return false; + } + } + else + { + if (map < 1) + { + return false; + } + + if (map > 40) + { + return false; + } + } + + /* So be it. */ + + plyr->message = (STSTR_CLEV); + g_deferred_init_new(gameskill, epsd, map); + } + } + + return false; } -void ST_Stop (void) +void st_ticker(void) { - if (st_stopped) - return; + st_randomnumber = m_random(); + st_update_widgets(); + st_oldhealth = plyr->health; +} + +void st_drawer(boolean p_fullscreen, boolean refresh) +{ + st_statusbaron = (!p_fullscreen) || automapactive; + st_firsttime = st_firsttime || refresh; + + /* Do red-/gold-shifts from damage/items */ + + st_do_palette_stuff(); + + /* If just after st_start(), refresh all */ - I_SetPalette (W_CacheLumpNum (lu_palette, PU_CACHE)); + if (st_firsttime) + { + st_do_refresh(); + } + else + { + /* Otherwise, update as little as possible */ - st_stopped = true; + st_diff_draw(); + } } -void ST_Init (void) +void st_start(void) { - ST_loadData(); - st_backing_screen = (pixel_t *) Z_Malloc(ST_WIDTH * ST_HEIGHT * sizeof(*st_backing_screen), PU_STATIC, 0); + if (!st_stopped) + { + st_stop(); + } + + st_init_data(); + st_create_widgets(); + st_stopped = false; } +void st_init(void) +{ + st_load_data(); + st_backing_screen = (pixel_t *)z_malloc( + ST_WIDTH * ST_HEIGHT * sizeof(*st_backing_screen), PU_STATIC, 0); +} diff --git a/games/NXDoom/src/doom/st_stuff.h b/games/NXDoom/src/doom/st_stuff.h index 0cf28bb631e..f68279e663d 100644 --- a/games/NXDoom/src/doom/st_stuff.h +++ b/games/NXDoom/src/doom/st_stuff.h @@ -1,57 +1,54 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Status bar code. -// Does the face/direction indicator animatin. -// Does palette indicators as well (red pain/berserk, bright pickup) -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/st_stuff.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Status bar code. + * Does the face/direction indicator animating. + * Does palette indicators as well (red pain/berserk, bright pickup) + * + ****************************************************************************/ #ifndef __STSTUFF_H__ #define __STSTUFF_H__ -#include "doomtype.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_event.h" +#include "doomtype.h" #include "m_cheat.h" -// Size of statusbar. -// Now sensitive for scaling. -#define ST_HEIGHT 32 -#define ST_WIDTH SCREENWIDTH -#define ST_Y (SCREENHEIGHT - ST_HEIGHT) - - -// -// STATUS BAR -// +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Called by main loop. -boolean ST_Responder (event_t* ev); - -// Called by main loop. -void ST_Ticker (void); - -// Called by main loop. -void ST_Drawer (boolean fullscreen, boolean refresh); - -// Called when the console player is spawned on each level. -void ST_Start (void); - -// Called by startup code. -void ST_Init (void); +/* Size of statusbar. + * Now sensitive for scaling. + */ +#define ST_HEIGHT 32 +#define ST_WIDTH SCREENWIDTH +#define ST_Y (SCREENHEIGHT - ST_HEIGHT) +/**************************************************************************** + * Public Data + ****************************************************************************/ extern pixel_t *st_backing_screen; extern cheatseq_t cheat_mus; @@ -65,5 +62,30 @@ extern cheatseq_t cheat_choppers; extern cheatseq_t cheat_clev; extern cheatseq_t cheat_mypos; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* STATUS BAR */ + +/* Called by main loop. */ + +boolean st_responder(event_t *ev); + +/* Called by main loop. */ + +void st_ticker(void); + +/* Called by main loop. */ + +void st_drawer(boolean fullscreen, boolean refresh); + +/* Called when the console player is spawned on each level. */ + +void st_start(void); + +/* Called by startup code. */ + +void st_init(void); -#endif +#endif /* __STSTUFF_H__ */ diff --git a/games/NXDoom/src/doom/statdump.c b/games/NXDoom/src/doom/statdump.c index ae6814a31f7..1db5657ab6c 100644 --- a/games/NXDoom/src/doom/statdump.c +++ b/games/NXDoom/src/doom/statdump.c @@ -1,357 +1,388 @@ - /* - - Copyright(C) 2005-2014 Simon Howard - - 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. - - -- - - Functions for presenting the information captured from the statistics - buffer to a file. - - */ +/**************************************************************************** + * apps/games/NXDoom/src/doom/statdump.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Functions for presenting the information captured from the statistics + * buffer to a file. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include #include -#include "d_player.h" #include "d_mode.h" +#include "d_player.h" #include "m_argv.h" #include "m_misc.h" #include "statdump.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_CAPTURES 32 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + /* Par times for E1M1-E1M9. */ + static const int doom1_par_times[] = { - 30, 75, 120, 90, 165, 180, 180, 30, 165, + 30, 75, 120, 90, 165, 180, 180, 30, 165, }; /* Par times for MAP01-MAP09. */ + static const int doom2_par_times[] = { - 30, 90, 120, 120, 90, 150, 120, 120, 270, + 30, 90, 120, 120, 90, 150, 120, 120, 270, }; /* Player colors. */ + static const char *player_colors[] = { - "Green", "Indigo", "Brown", "Red" + "Green", + "Indigo", + "Brown", + "Red", }; -// Array of end-of-level statistics that have been captured. +/* Array of end-of-level statistics that have been captured. */ -#define MAX_CAPTURES 32 static wbstartstruct_t captured_stats[MAX_CAPTURES]; static int num_captured_stats = 0; -static GameMission_t discovered_gamemission = none; +static gamemission_t discovered_gamemission = none; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ /* Try to work out whether this is a Doom 1 or Doom 2 game, by looking * at the episode and map, and the par times. This is used to decide * how to format the level name. Unfortunately, in some cases it is - * impossible to determine whether this is Doom 1 or Doom 2. */ + * impossible to determine whether this is Doom 1 or Doom 2. + */ -static void DiscoverGamemode(const wbstartstruct_t *stats, int num_stats) +static void discover_game_mode(const wbstartstruct_t *stats, int num_stats) { - int partime; - int level; - int i; + int partime; + int level; + int i; - if (discovered_gamemission != none) + if (discovered_gamemission != none) { - return; + return; } - for (i=0; i 0) + if (stats[i].epsd > 0) { - discovered_gamemission = doom; - return; + discovered_gamemission = doom; + return; } - /* This is episode 1. If this is level 10 or higher, - it must be Doom 2. */ + /* This is episode 1. If this is level 10 or higher, it must be + * Doom 2. + */ - if (level >= 9) + if (level >= 9) { - discovered_gamemission = doom2; - return; + discovered_gamemission = doom2; + return; } - /* Try to work out if this is Doom 1 or Doom 2 by looking - at the par time. */ + /* Try to work out if this is Doom 1 or Doom 2 by looking at the par + * time. + */ - partime = stats[i].partime; + partime = stats[i].partime; - if (partime == doom1_par_times[level] * TICRATE - && partime != doom2_par_times[level] * TICRATE) + if (partime == doom1_par_times[level] * TICRATE && + partime != doom2_par_times[level] * TICRATE) { - discovered_gamemission = doom; - return; + discovered_gamemission = doom; + return; } - if (partime != doom1_par_times[level] * TICRATE - && partime == doom2_par_times[level] * TICRATE) + if (partime != doom1_par_times[level] * TICRATE && + partime == doom2_par_times[level] * TICRATE) { - discovered_gamemission = doom2; - return; + discovered_gamemission = doom2; + return; } } } /* Returns the number of players active in the given stats buffer. */ -static int GetNumPlayers(const wbstartstruct_t *stats) +static int get_num_players(const wbstartstruct_t *stats) { - int i; - int num_players = 0; + int i; + int num_players = 0; - for (i=0; iplyr[i].in) + if (stats->plyr[i].in) { - ++num_players; + ++num_players; } } - return num_players; + return num_players; } -static void PrintBanner(FILE *stream) +static void print_banner(FILE *stream) { - fprintf(stream, "===========================================\n"); + fprintf(stream, "===========================================\n"); } -static void PrintPercentage(FILE *stream, int amount, int total) +static void print_percentage(FILE *stream, int amount, int total) { - if (total == 0) + if (total == 0) { - fprintf(stream, "0"); + fprintf(stream, "0"); } - else + else { - fprintf(stream, "%i / %i", amount, total); + fprintf(stream, "%i / %i", amount, total); - // statdump.exe is a 16-bit program, so very occasionally an - // integer overflow can occur when doing this calculation with - // a large value. Therefore, cast to short to give the same - // output. + /* statdump.exe is a 16-bit program, so very occasionally an + * integer overflow can occur when doing this calculation with + * a large value. Therefore, cast to short to give the same + * output. + */ - fprintf(stream, " (%i%%)", (short) (amount * 100) / total); + fprintf(stream, " (%i%%)", (short)(amount * 100) / total); } } /* Display statistics for a single player. */ -static void PrintPlayerStats(FILE *stream, const wbstartstruct_t *stats, - int player_num) +static void print_player_stats(FILE *stream, const wbstartstruct_t *stats, + int player_num) { - const wbplayerstruct_t *player = &stats->plyr[player_num]; + const wbplayerstruct_t *player = &stats->plyr[player_num]; - fprintf(stream, "Player %i (%s):\n", player_num + 1, - player_colors[player_num]); + fprintf(stream, "Player %i (%s):\n", player_num + 1, + player_colors[player_num]); - /* Kills percentage */ + /* Kills percentage */ - fprintf(stream, "\tKills: "); - PrintPercentage(stream, player->skills, stats->maxkills); - fprintf(stream, "\n"); + fprintf(stream, "\tKills: "); + print_percentage(stream, player->skills, stats->maxkills); + fprintf(stream, "\n"); - /* Items percentage */ + /* Items percentage */ - fprintf(stream, "\tItems: "); - PrintPercentage(stream, player->sitems, stats->maxitems); - fprintf(stream, "\n"); + fprintf(stream, "\tItems: "); + print_percentage(stream, player->sitems, stats->maxitems); + fprintf(stream, "\n"); - /* Secrets percentage */ + /* Secrets percentage */ - fprintf(stream, "\tSecrets: "); - PrintPercentage(stream, player->ssecret, stats->maxsecret); - fprintf(stream, "\n"); + fprintf(stream, "\tSecrets: "); + print_percentage(stream, player->ssecret, stats->maxsecret); + fprintf(stream, "\n"); } /* Frags table for multiplayer games. */ -static void PrintFragsTable(FILE *stream, const wbstartstruct_t *stats) +static void print_frags_table(FILE *stream, const wbstartstruct_t *stats) { - int x, y; + int x; + int y; - fprintf(stream, "Frags:\n"); + fprintf(stream, "Frags:\n"); - /* Print header */ + /* Print header */ - fprintf(stream, "\t\t"); + fprintf(stream, "\t\t"); - for (x=0; xplyr[x].in) + if (!stats->plyr[x].in) { - continue; + continue; } - fprintf(stream, "%s\t", player_colors[x]); + fprintf(stream, "%s\t", player_colors[x]); } - fprintf(stream, "\n"); + fprintf(stream, "\n"); - fprintf(stream, "\t\t-------------------------------- VICTIMS\n"); + fprintf(stream, "\t\t-------------------------------- VICTIMS\n"); - /* Print table */ + /* Print table */ - for (y=0; yplyr[y].in) + if (!stats->plyr[y].in) { - continue; + continue; } - fprintf(stream, "\t%s\t|", player_colors[y]); + fprintf(stream, "\t%s\t|", player_colors[y]); - for (x=0; xplyr[x].in) + if (!stats->plyr[x].in) { - continue; + continue; } - fprintf(stream, "%i\t", stats->plyr[y].frags[x]); + fprintf(stream, "%i\t", stats->plyr[y].frags[x]); } - fprintf(stream, "\n"); + fprintf(stream, "\n"); } - fprintf(stream, "\t\t|\n"); - fprintf(stream, "\t KILLERS\n"); + fprintf(stream, "\t\t|\n"); + fprintf(stream, "\t KILLERS\n"); } /* Displays the level name: MAPxy or ExMy, depending on game mode. */ -static void PrintLevelName(FILE *stream, int episode, int level) +static void print_level_name(FILE *stream, int episode, int level) { - PrintBanner(stream); + print_banner(stream); - switch (discovered_gamemission) + switch (discovered_gamemission) { - - case doom: - fprintf(stream, "E%iM%i\n", episode + 1, level + 1); - break; - case doom2: - fprintf(stream, "MAP%02i\n", level + 1); - break; - default: - case none: - fprintf(stream, "E%iM%i / MAP%02i\n", - episode + 1, level + 1, level + 1); - break; + case doom: + fprintf(stream, "E%iM%i\n", episode + 1, level + 1); + break; + case doom2: + fprintf(stream, "MAP%02i\n", level + 1); + break; + default: + case none: + fprintf(stream, "E%iM%i / MAP%02i\n", episode + 1, level + 1, + level + 1); + break; } - PrintBanner(stream); + print_banner(stream); } /* Print details of a statistics buffer to the given file. */ -static void PrintStats(FILE *stream, const wbstartstruct_t *stats) +static void print_stats(FILE *stream, const wbstartstruct_t *stats) { - short leveltime, partime; - int i; + short leveltime; + short partime; + int i; - PrintLevelName(stream, stats->epsd, stats->last); - fprintf(stream, "\n"); + print_level_name(stream, stats->epsd, stats->last); + fprintf(stream, "\n"); - leveltime = stats->plyr[0].stime / TICRATE; - partime = stats->partime / TICRATE; - fprintf(stream, "Time: %i:%02i", leveltime / 60, leveltime % 60); - fprintf(stream, " (par: %i:%02i)\n", partime / 60, partime % 60); - fprintf(stream, "\n"); + leveltime = stats->plyr[0].stime / TICRATE; + partime = stats->partime / TICRATE; + fprintf(stream, "Time: %i:%02i", leveltime / 60, leveltime % 60); + fprintf(stream, " (par: %i:%02i)\n", partime / 60, partime % 60); + fprintf(stream, "\n"); - for (i=0; iplyr[i].in) + if (stats->plyr[i].in) { - PrintPlayerStats(stream, stats, i); + print_player_stats(stream, stats, i); } } - if (GetNumPlayers(stats) >= 2) + if (get_num_players(stats) >= 2) { - PrintFragsTable(stream, stats); + print_frags_table(stream, stats); } - fprintf(stream, "\n"); + fprintf(stream, "\n"); } -void StatCopy(const wbstartstruct_t *stats) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void stat_copy(const wbstartstruct_t *stats) { - if (M_ParmExists("-statdump") && num_captured_stats < MAX_CAPTURES) + if (m_parm_exists("-statdump") && num_captured_stats < MAX_CAPTURES) { - memcpy(&captured_stats[num_captured_stats], stats, - sizeof(wbstartstruct_t)); - ++num_captured_stats; + memcpy(&captured_stats[num_captured_stats], stats, + sizeof(wbstartstruct_t)); + ++num_captured_stats; } } -void StatDump(void) +void stat_dump(void) { - FILE *dumpfile; - int i; + FILE *dumpfile; + int i; - //! - // @category compat - // @arg - // - // Dump statistics information to the specified file on the levels - // that were played. The output from this option matches the output - // from statdump.exe (see ctrlapi.zip in the /idgames archive). - // + /* @category compat + * @arg + * + * Dump statistics information to the specified file on the levels + * that were played. The output from this option matches the output + * from statdump.exe (see ctrlapi.zip in the /idgames archive). + */ - i = M_CheckParmWithArgs("-statdump", 1); + i = m_check_parm_with_args("-statdump", 1); - if (i > 0) + if (i > 0) { - printf("Statistics captured for %i level(s)\n", num_captured_stats); + printf("Statistics captured for %i level(s)\n", num_captured_stats); - // We actually know what the real gamemission is, but this has - // to match the output from statdump.exe. + /* We actually know what the real gamemission is, but this has + * to match the output from statdump.exe. + */ - DiscoverGamemode(captured_stats, num_captured_stats); + discover_game_mode(captured_stats, num_captured_stats); - // Allow "-" as output file, for stdout. + /* Allow "-" as output file, for stdout. */ - if (strcmp(myargv[i + 1], "-") != 0) + if (strcmp(myargv[i + 1], "-") != 0) { - dumpfile = M_fopen(myargv[i + 1], "w"); + dumpfile = fopen(myargv[i + 1], "w"); } - else + else { - dumpfile = stdout; + dumpfile = stdout; } - for (i = 0; i < num_captured_stats; ++i) + for (i = 0; i < num_captured_stats; ++i) { - PrintStats(dumpfile, &captured_stats[i]); + print_stats(dumpfile, &captured_stats[i]); } - if (dumpfile != stdout) + if (dumpfile != stdout) { - fclose(dumpfile); + fclose(dumpfile); } } } - diff --git a/games/NXDoom/src/doom/statdump.h b/games/NXDoom/src/doom/statdump.h index f4f11efe666..57073aa0892 100644 --- a/games/NXDoom/src/doom/statdump.h +++ b/games/NXDoom/src/doom/statdump.h @@ -1,23 +1,30 @@ - /* - - Copyright(C) 2005-2014 Simon Howard - - 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. - - */ +/**************************************************************************** + * apps/games/NXDoom/src/doom/statdump.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ #ifndef DOOM_STATDUMP_H #define DOOM_STATDUMP_H -void StatCopy(const wbstartstruct_t *stats); -void StatDump(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void stat_copy(const wbstartstruct_t *stats); +void stat_dump(void); -#endif /* #ifndef DOOM_STATDUMP_H */ +#endif /* DOOM_STATDUMP_H */ diff --git a/games/NXDoom/src/doom/wi_stuff.c b/games/NXDoom/src/doom/wi_stuff.c index 965cc557169..724aa33203b 100644 --- a/games/NXDoom/src/doom/wi_stuff.c +++ b/games/NXDoom/src/doom/wi_stuff.c @@ -1,21 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Intermission screens. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doom/wi_stuff.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Intermission screens. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -33,232 +41,279 @@ #include "g_game.h" #include "r_local.h" + +#ifdef CONFIG_GAMES_NXDOOM_SOUND #include "s_sound.h" +#include "sounds.h" +#endif #include "doomstat.h" -// Data. -#include "sounds.h" +/* Needs access to LFB. */ -// Needs access to LFB. #include "v_video.h" #include "wi_stuff.h" -// -// Data needed to add patches to full screen intermission pics. -// Patches are statistics messages, and animations. -// Loads of by-pixel layout and placement, offsets etc. -// +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Data needed to add patches to full screen intermission pics. + * Patches are statistics messages, and animations. + * Loads of by-pixel layout and placement, offsets etc. + */ + +/* Different between registered DOOM (1994) and + * Ultimate DOOM - Final edition (retail, 1995?). + * This is supposedly ignored for commercial + * release (aka DOOM II), which had 34 maps + * in one episode. So there. + */ + +#define NUMEPISODES 4 +#define NUMMAPS 9 + +/* in tics + * U #define PAUSELEN (TICRATE*2) + * U #define SCORESTEP 100 + * U #define ANIMPERIOD 32 + * pixel distance from "(YOU)" to "PLAYER N" + * U #define STARDIST 10 + * U #define WK 1 + */ + +/* GLOBAL LOCATIONS */ + +#define WI_TITLEY 2 +#define WI_SPACINGY 33 +/* SINGLE-PLAYER STUFF */ -// -// Different vetween registered DOOM (1994) and -// Ultimate DOOM - Final edition (retail, 1995?). -// This is supposedly ignored for commercial -// release (aka DOOM II), which had 34 maps -// in one episode. So there. -#define NUMEPISODES 4 -#define NUMMAPS 9 +#define SP_STATSX 50 +#define SP_STATSY 50 +#define SP_TIMEX 16 +#define SP_TIMEY (SCREENHEIGHT - 32) -// in tics -//U #define PAUSELEN (TICRATE*2) -//U #define SCORESTEP 100 -//U #define ANIMPERIOD 32 -// pixel distance from "(YOU)" to "PLAYER N" -//U #define STARDIST 10 -//U #define WK 1 +/* NET GAME STUFF */ +#define NG_STATSY 50 +#define NG_STATSX (32 + SHORT(star->width) / 2 + 32 * !dofrags) -// GLOBAL LOCATIONS -#define WI_TITLEY 2 -#define WI_SPACINGY 33 +#define NG_SPACINGX 64 -// SINGPLE-PLAYER STUFF -#define SP_STATSX 50 -#define SP_STATSY 50 +/* DEATHMATCH STUFF */ -#define SP_TIMEX 16 -#define SP_TIMEY (SCREENHEIGHT-32) +#define DM_MATRIXX 42 +#define DM_MATRIXY 68 +#define DM_SPACINGX 40 -// NET GAME STUFF -#define NG_STATSY 50 -#define NG_STATSX (32 + SHORT(star->width)/2 + 32*!dofrags) +#define DM_TOTALSX 269 -#define NG_SPACINGX 64 +#define DM_KILLERSX 10 +#define DM_KILLERSY 100 +#define DM_VICTIMSX 5 +#define DM_VICTIMSY 50 +/* Animation locations for episode 0 (1). + * Using patches saves a lot of space, + * as they replace 320x200 full screen frames. + */ -// DEATHMATCH STUFF -#define DM_MATRIXX 42 -#define DM_MATRIXY 68 +#define ANIM(type, period, nanims, x, y, nexttic) \ + {(type), (period), (nanims), {(x), (y)}, (nexttic), 0, {NULL, NULL, NULL}, \ + 0, 0, 0, 0} -#define DM_SPACINGX 40 +/* GENERAL DATA */ -#define DM_TOTALSX 269 +/* Locally used stuff. */ -#define DM_KILLERSX 10 -#define DM_KILLERSY 100 -#define DM_VICTIMSX 5 -#define DM_VICTIMSY 50 +/* States for single-player */ +#define SP_KILLS 0 +#define SP_ITEMS 2 +#define SP_SECRET 4 +#define SP_FRAGS 6 +#define SP_TIME 8 +#define SP_PAR ST_TIME +#define SP_PAUSE 1 +/* in seconds */ + +#define SHOWNEXTLOCDELAY 4 + +/**************************************************************************** + * Private Types + ****************************************************************************/ typedef enum { - ANIM_ALWAYS, - ANIM_RANDOM, - ANIM_LEVEL - + ANIM_ALWAYS, + ANIM_RANDOM, + ANIM_LEVEL } animenum_t; +/* States for the intermission */ + +typedef enum +{ + NO_STATE = -1, + STAT_COUNT, + SHOW_NEXT_LOC, +} stateenum_t; + typedef struct { - int x; - int y; - + int x; + int y; } point_t; +/* Animation. + * There is another anim_t used in p_spec. + */ -// -// Animation. -// There is another anim_t used in p_spec. -// typedef struct { - animenum_t type; + animenum_t type; + + /* period in tics between animations */ + + int period; + + /* number of animation frames */ + + int nanims; - // period in tics between animations - int period; + /* location of animation */ - // number of animation frames - int nanims; + point_t loc; - // location of animation - point_t loc; + /* ALWAYS: n/a, + * RANDOM: period deviation (<256), + * LEVEL: level + */ - // ALWAYS: n/a, - // RANDOM: period deviation (<256), - // LEVEL: level - int data1; + int data1; - // ALWAYS: n/a, - // RANDOM: random base period, - // LEVEL: n/a - int data2; + /* ALWAYS: n/a, + * RANDOM: random base period, + * LEVEL: n/a + */ - // actual graphics for frames of animations - patch_t* p[3]; + int data2; - // following must be initialized to zero before use! + /* actual graphics for frames of animations */ - // next value of bcnt (used in conjunction with period) - int nexttic; + patch_t *p[3]; - // last drawn animation frame - int lastdrawn; + /* following must be initialized to zero before use! */ - // next frame number to animate - int ctr; - - // used by RANDOM and LEVEL when animating - int state; + /* next value of bcnt (used in conjunction with period) */ + int nexttic; + + /* last drawn animation frame */ + + int lastdrawn; + + /* next frame number to animate */ + + int ctr; + + /* used by RANDOM and LEVEL when animating */ + + int state; } anim_t; +typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ static point_t lnodes[NUMEPISODES][NUMMAPS] = { - // Episode 0 World Map + /* Episode 0 World Map */ + { - { 185, 164 }, // location of level 0 (CJ) - { 148, 143 }, // location of level 1 (CJ) - { 69, 122 }, // location of level 2 (CJ) - { 209, 102 }, // location of level 3 (CJ) - { 116, 89 }, // location of level 4 (CJ) - { 166, 55 }, // location of level 5 (CJ) - { 71, 56 }, // location of level 6 (CJ) - { 135, 29 }, // location of level 7 (CJ) - { 71, 24 } // location of level 8 (CJ) + {185, 164}, /* location of level 0 (CJ) */ + {148, 143}, /* location of level 1 (CJ) */ + {69, 122}, /* location of level 2 (CJ) */ + {209, 102}, /* location of level 3 (CJ) */ + {116, 89}, /* location of level 4 (CJ) */ + {166, 55}, /* location of level 5 (CJ) */ + {71, 56}, /* location of level 6 (CJ) */ + {135, 29}, /* location of level 7 (CJ) */ + {71, 24}, /* location of level 8 (CJ) */ }, - // Episode 1 World Map should go here + /* Episode 1 World Map should go here */ + { - { 254, 25 }, // location of level 0 (CJ) - { 97, 50 }, // location of level 1 (CJ) - { 188, 64 }, // location of level 2 (CJ) - { 128, 78 }, // location of level 3 (CJ) - { 214, 92 }, // location of level 4 (CJ) - { 133, 130 }, // location of level 5 (CJ) - { 208, 136 }, // location of level 6 (CJ) - { 148, 140 }, // location of level 7 (CJ) - { 235, 158 } // location of level 8 (CJ) + {254, 25}, /* location of level 0 (CJ) */ + {97, 50}, /* location of level 1 (CJ) */ + {188, 64}, /* location of level 2 (CJ) */ + {128, 78}, /* location of level 3 (CJ) */ + {214, 92}, /* location of level 4 (CJ) */ + {133, 130}, /* location of level 5 (CJ) */ + {208, 136}, /* location of level 6 (CJ) */ + {148, 140}, /* location of level 7 (CJ) */ + {235, 158}, /* location of level 8 (CJ) */ }, - // Episode 2 World Map should go here - { - { 156, 168 }, // location of level 0 (CJ) - { 48, 154 }, // location of level 1 (CJ) - { 174, 95 }, // location of level 2 (CJ) - { 265, 75 }, // location of level 3 (CJ) - { 130, 48 }, // location of level 4 (CJ) - { 279, 23 }, // location of level 5 (CJ) - { 198, 48 }, // location of level 6 (CJ) - { 140, 25 }, // location of level 7 (CJ) - { 281, 136 } // location of level 8 (CJ) - } + /* Episode 2 World Map should go here */ + { + {156, 168}, /* location of level 0 (CJ) */ + {48, 154}, /* location of level 1 (CJ) */ + {174, 95}, /* location of level 2 (CJ) */ + {265, 75}, /* location of level 3 (CJ) */ + {130, 48}, /* location of level 4 (CJ) */ + {279, 23}, /* location of level 5 (CJ) */ + {198, 48}, /* location of level 6 (CJ) */ + {140, 25}, /* location of level 7 (CJ) */ + {281, 136}, /* location of level 8 (CJ) */ + }, }; - -// -// Animation locations for episode 0 (1). -// Using patches saves a lot of space, -// as they replace 320x200 full screen frames. -// - -#define ANIM(type, period, nanims, x, y, nexttic) \ - { (type), (period), (nanims), { (x), (y) }, (nexttic), \ - 0, { NULL, NULL, NULL }, 0, 0, 0, 0 } - - static anim_t epsd0animinfo[] = { - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 224, 104, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 184, 160, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 112, 136, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 72, 112, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 88, 96, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 64, 48, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 192, 40, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 136, 16, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 80, 16, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 64, 24, 0), }; static anim_t epsd1animinfo[] = { - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7), - ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 1), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 2), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 3), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 4), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 5), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 6), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 7), + ANIM(ANIM_LEVEL, TICRATE / 3, 3, 192, 144, 8), + ANIM(ANIM_LEVEL, TICRATE / 3, 1, 128, 136, 8), }; static anim_t epsd2animinfo[] = { - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0), - ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 104, 168, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 40, 136, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 160, 96, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 104, 80, 0), + ANIM(ANIM_ALWAYS, TICRATE / 3, 3, 120, 32, 0), + ANIM(ANIM_ALWAYS, TICRATE / 4, 3, 40, 0, 0), }; static int NUMANIMS[NUMEPISODES] = @@ -272,1562 +327,1567 @@ static anim_t *anims[NUMEPISODES] = { epsd0animinfo, epsd1animinfo, - epsd2animinfo + epsd2animinfo, }; +/* used to accelerate or skip a stage */ + +static int acceleratestage; + +/* wbs->pnum */ + +static int me; + +/* specifies current state */ -// -// GENERAL DATA -// +static stateenum_t state; -// -// Locally used stuff. -// +/* contains information passed into intermission */ -// States for single-player -#define SP_KILLS 0 -#define SP_ITEMS 2 -#define SP_SECRET 4 -#define SP_FRAGS 6 -#define SP_TIME 8 -#define SP_PAR ST_TIME +static wbstartstruct_t *wbs; -#define SP_PAUSE 1 +static wbplayerstruct_t *plrs; /* wbs->plyr[] */ -// in seconds -#define SHOWNEXTLOCDELAY 4 -//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY +/* used for general timing */ +static int cnt; -// used to accelerate or skip a stage -static int acceleratestage; +/* used for timing of background animation */ -// wbs->pnum -static int me; +static int bcnt; - // specifies current state -static stateenum_t state; +/* signals to refresh everything for one frame */ -// contains information passed into intermission -static wbstartstruct_t* wbs; +static int firstrefresh; -static wbplayerstruct_t* plrs; // wbs->plyr[] +static int cnt_kills[MAXPLAYERS]; +static int cnt_items[MAXPLAYERS]; +static int cnt_secret[MAXPLAYERS]; +static int cnt_time; +static int cnt_par; +static int cnt_pause; -// used for general timing -static int cnt; +/* # of commercial levels */ -// used for timing of background animation -static int bcnt; +static int NUMCMAPS; -// signals to refresh everything for one frame -static int firstrefresh; +/* GRAPHICS */ -static int cnt_kills[MAXPLAYERS]; -static int cnt_items[MAXPLAYERS]; -static int cnt_secret[MAXPLAYERS]; -static int cnt_time; -static int cnt_par; -static int cnt_pause; +/* You Are Here graphic */ -// # of commercial levels -static int NUMCMAPS; +static patch_t *yah[3] = +{ + NULL, + NULL, + NULL, +}; + +/* splat */ + +static patch_t *splat[2] = +{ + NULL, + NULL, +}; + +/* %, : graphics */ + +static patch_t *percent; +static patch_t *colon; + +/* 0-9 graphic */ + +static patch_t *num[10]; + +/* minus sign */ +static patch_t *wiminus; -// -// GRAPHICS -// +/* "Finished!" graphics */ -// You Are Here graphic -static patch_t* yah[3] = { NULL, NULL, NULL }; +static patch_t *finished; -// splat -static patch_t* splat[2] = { NULL, NULL }; +/* "Entering" graphic */ -// %, : graphics -static patch_t* percent; -static patch_t* colon; +static patch_t *entering; -// 0-9 graphic -static patch_t* num[10]; +/* "secret" */ -// minus sign -static patch_t* wiminus; +static patch_t *sp_secret; -// "Finished!" graphics -static patch_t* finished; +/* "Kills", "Scrt", "Items", "Frags" */ -// "Entering" graphic -static patch_t* entering; +static patch_t *kills; +static patch_t *secret; +static patch_t *items; +static patch_t *frags; -// "secret" -static patch_t* sp_secret; +/* Time sucks. */ - // "Kills", "Scrt", "Items", "Frags" -static patch_t* kills; -static patch_t* secret; -static patch_t* items; -static patch_t* frags; +static patch_t *timepatch; +static patch_t *par; +static patch_t *sucks; -// Time sucks. -static patch_t* timepatch; -static patch_t* par; -static patch_t* sucks; +/* "killers", "victims" */ -// "killers", "victims" -static patch_t* killers; -static patch_t* victims; +static patch_t *killers; +static patch_t *victims; -// "Total", your face, your dead face -static patch_t* total; -static patch_t* star; -static patch_t* bstar; +/* "Total", your face, your dead face */ -// "red P[1..MAXPLAYERS]" -static patch_t* p[MAXPLAYERS]; +static patch_t *total; +static patch_t *star; +static patch_t *bstar; -// "gray P[1..MAXPLAYERS]" -static patch_t* bp[MAXPLAYERS]; +/* "red P[1..MAXPLAYERS]" */ - // Name graphics of each level (centered) -static patch_t** lnames; +static patch_t *p[MAXPLAYERS]; + +/* "gray P[1..MAXPLAYERS]" */ + +static patch_t *bp[MAXPLAYERS]; + +/* Name graphics of each level (centered) */ + +static patch_t **lnames; + +/* Buffer storing the backdrop */ -// Buffer storing the backdrop static patch_t *background; -// -// CODE -// +static int dm_state; +static int dm_frags[MAXPLAYERS][MAXPLAYERS]; +static int dm_totals[MAXPLAYERS]; -// slam background -void WI_slamBackground(void) -{ - V_DrawPatch(0, 0, background); -} +static int cnt_frags[MAXPLAYERS]; +static int dofrags; +static int ng_state; -// The ticker is used to detect keys -// because of timing issues in netgames. -boolean WI_Responder(event_t* ev) -{ - return false; -} +static int sp_state; +static boolean snl_pointeron = false; -// Draws " Finished!" -void WI_drawLF(void) -{ - int y = WI_TITLEY; +/**************************************************************************** + * Private Functions + ****************************************************************************/ - if (gamemode != commercial || wbs->last < NUMCMAPS) - { - // draw - V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2, - y, lnames[wbs->last]); +/* Common load/unload function. Iterates over all the graphics + * lumps to be loaded/unloaded into memory. + */ - // draw "Finished!" - y += (5*SHORT(lnames[wbs->last]->height))/4; +static void wi_load_unload_data(load_callback_t callback) +{ + int8_t i; + int8_t j; + char name[9]; + anim_t *a; - V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); - } - else if (wbs->last == NUMCMAPS) + if (gamemode == commercial) { - // MAP33 - draw "Finished!" only - V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); + for (i = 0; i < NUMCMAPS; i++) + { + snprintf(name, sizeof(name), "CWILV%2.2d", i); + callback(name, &lnames[i]); + } } - else if (wbs->last > NUMCMAPS) + else { - // > MAP33. Doom bombs out here with a Bad V_DrawPatch error. - // I'm pretty sure that doom2.exe is just reading into random - // bits of memory at this point, but let's try to be accurate - // anyway. This deliberately triggers a V_DrawPatch error. + for (i = 0; i < NUMMAPS; i++) + { + snprintf(name, sizeof(name), "WILV%d%d", wbs->epsd, i); + callback(name, &lnames[i]); + } + + /* you are here */ + + callback(("WIURH0"), &yah[0]); + + /* you are here (alt.) */ + + callback(("WIURH1"), &yah[1]); + + /* splat */ + + callback(("WISPLAT"), &splat[0]); + + if (wbs->epsd < 3) + { + for (j = 0; j < NUMANIMS[wbs->epsd]; j++) + { + a = &anims[wbs->epsd][j]; + for (i = 0; i < a->nanims; i++) + { + /* MONDO HACK! */ + + if (wbs->epsd != 1 || j != 8) + { + /* animations */ + + snprintf(name, sizeof(name), "WIA%d%.2d%.2d", + wbs->epsd, j, i); + callback(name, &a->p[i]); + } + else + { + /* HACK ALERT! */ + + a->p[i] = anims[1][4].p[i]; + } + } + } + } + } - patch_t tmp = { SCREENWIDTH, SCREENHEIGHT, 1, 1, - { 0, 0, 0, 0, 0, 0, 0, 0 } }; + /* More hacks on minus sign. */ + + if (w_check_num_for_name(("WIMINUS")) > 0) + callback(("WIMINUS"), &wiminus); + else + wiminus = NULL; + + for (i = 0; i < 10; i++) + { + /* numbers 0-9 */ - V_DrawPatch(0, y, &tmp); + snprintf(name, sizeof(name), "WINUM%d", i); + callback(name, &num[i]); } -} + /* percent sign */ + callback(("WIPCNT"), &percent); -// Draws "Entering " -void WI_drawEL(void) -{ - int y = WI_TITLEY; + /* "finished" */ - // draw "Entering" - V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2, - y, - entering); + callback(("WIF"), &finished); - // draw level - y += (5*SHORT(lnames[wbs->next]->height))/4; + /* "entering" */ - V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2, - y, - lnames[wbs->next]); + callback(("WIENTER"), &entering); -} + /* "kills" */ -void -WI_drawOnLnode -( int n, - patch_t* c[] ) -{ + callback(("WIOSTK"), &kills); - int i; - int left; - int top; - int right; - int bottom; - boolean fits = false; + /* "scrt" */ - i = 0; - do - { - left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset); - top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset); - right = left + SHORT(c[i]->width); - bottom = top + SHORT(c[i]->height); - - if (left >= 0 - && right < SCREENWIDTH - && top >= 0 - && bottom < SCREENHEIGHT) - { - fits = true; - } - else - { - i++; - } - } while (!fits && i!=2 && c[i] != NULL); - - if (fits && i<2) + callback(("WIOSTS"), &secret); + + /* "secret" */ + + callback(("WISCRT2"), &sp_secret); + + /* french wad uses WIOBJ (?) */ + + if (w_check_num_for_name(("WIOBJ")) >= 0) { - V_DrawPatch(lnodes[wbs->epsd][n].x, - lnodes[wbs->epsd][n].y, - c[i]); + /* "items" */ + + if (netgame && !deathmatch) + callback(("WIOBJ"), &items); + else + callback(("WIOSTI"), &items); } - else + else { - // DEBUG - printf("Could not place patch on level %d", n+1); + callback(("WIOSTI"), &items); } -} + /* "frgs" */ + callback(("WIFRGS"), &frags); -void WI_initAnimatedBack(void) -{ - int i; - anim_t* a; + /* ":" */ - if (gamemode == commercial) - return; + callback(("WICOLON"), &colon); - if (wbs->epsd > 2) - return; + /* "time" */ - for (i=0;iepsd];i++) - { - a = &anims[wbs->epsd][i]; - - // init variables - a->ctr = -1; - - // specify the next time to draw it - if (a->type == ANIM_ALWAYS) - a->nexttic = bcnt + 1 + (M_Random()%a->period); - else if (a->type == ANIM_RANDOM) - a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1); - else if (a->type == ANIM_LEVEL) - a->nexttic = bcnt + 1; - } + callback(("WITIME"), &timepatch); -} + /* "sucks" */ -void WI_updateAnimatedBack(void) -{ - int i; - anim_t* a; + callback(("WISUCKS"), &sucks); - if (gamemode == commercial) - return; + /* "par" */ - if (wbs->epsd > 2) - return; + callback(("WIPAR"), &par); - for (i=0;iepsd];i++) - { - a = &anims[wbs->epsd][i]; - - if (bcnt == a->nexttic) - { - switch (a->type) - { - case ANIM_ALWAYS: - if (++a->ctr >= a->nanims) a->ctr = 0; - a->nexttic = bcnt + a->period; - break; - - case ANIM_RANDOM: - a->ctr++; - if (a->ctr == a->nanims) - { - a->ctr = -1; - a->nexttic = bcnt+a->data2+(M_Random()%a->data1); - } - else a->nexttic = bcnt + a->period; - break; - - case ANIM_LEVEL: - // gawd-awful hack for level anims - if (!(state == StatCount && i == 7) - && wbs->next == a->data1) - { - a->ctr++; - if (a->ctr == a->nanims) a->ctr--; - a->nexttic = bcnt + a->period; - } - break; - } - } + /* "killers" (vertical) */ - } + callback(("WIKILRS"), &killers); -} + /* "victims" (horiz) */ -void WI_drawAnimatedBack(void) -{ - int i; - anim_t* a; + callback(("WIVCTMS"), &victims); - if (gamemode == commercial) - return; + /* "total" */ - if (wbs->epsd > 2) - return; + callback(("WIMSTT"), &total); - for (i=0 ; iepsd] ; i++) + for (i = 0; i < MAXPLAYERS; i++) { - a = &anims[wbs->epsd][i]; + /* "1,2,3,4" */ + + snprintf(name, sizeof(name), "STPB%d", i); + callback(name, &p[i]); - if (a->ctr >= 0) - V_DrawPatch(a->loc.x, a->loc.y, a->p[a->ctr]); + /* "1,2,3,4" */ + + snprintf(name, sizeof(name), "WIBP%d", i + 1); + callback(name, &bp[i]); + } + + /* Background image */ + + if (gamemode == commercial) + { + m_str_copy(name, ("INTERPIC"), sizeof(name)); } + else if (gameversion >= exe_ultimate && wbs->epsd == 3) + { + m_str_copy(name, ("INTERPIC"), sizeof(name)); + } + else + { + snprintf(name, sizeof(name), "WIMAP%d", wbs->epsd); + } + + /* Draw backdrop and save to a temporary buffer */ + callback(name, &background); } -// -// Draws a number. -// If digits > 0, then use that many digits minimum, -// otherwise only use as many as necessary. -// Returns new x position. -// - -int -WI_drawNum -( int x, - int y, - int n, - int digits ) +static void wi_load_callback(const char *name, patch_t **variable) { + *variable = w_cache_lump_name(name, PU_STATIC); +} - int fontwidth = SHORT(num[0]->width); - int neg; - int temp; +static void wi_unload_callback(const char *name, patch_t **variable) +{ + w_release_lump_name(name); + *variable = NULL; +} - if (digits < 0) +static void wi_load_data(void) +{ + if (gamemode == commercial) + { + NUMCMAPS = 32; + lnames = (patch_t **)z_malloc(sizeof(patch_t *) * NUMCMAPS, + PU_STATIC, NULL); + } + else { - if (!n) - { - // make variable-length zeros 1 digit long - digits = 1; - } - else - { - // figure out # of digits in # - digits = 0; - temp = n; - - while (temp) - { - temp /= 10; - digits++; - } - } + lnames = + (patch_t **)z_malloc(sizeof(patch_t *) * NUMMAPS, PU_STATIC, NULL); } - neg = n < 0; - if (neg) - n = -n; + wi_load_unload_data(wi_load_callback); - // if non-number, do not draw it - if (n == 1994) - return 0; + /* These two graphics are special cased because we're sharing them with the + * status bar code + */ - // draw the new number - while (digits--) - { - x -= fontwidth; - V_DrawPatch(x, y, num[ n % 10 ]); - n /= 10; - } + /* your face */ - // draw a minus sign if necessary - if (neg && wiminus) - V_DrawPatch(x-=8, y, wiminus); + star = w_cache_lump_name(("STFST01"), PU_STATIC); - return x; + /* dead face */ + bstar = w_cache_lump_name(("STFDEAD0"), PU_STATIC); } -void -WI_drawPercent -( int x, - int y, - int p ) +static void wi_unload_data(void) { - if (p < 0) - return; + wi_load_unload_data(wi_unload_callback); + + /* We do not free these lumps as they are shared with the status + * bar code. + */ - V_DrawPatch(x, y, percent); - WI_drawNum(x, y, p, -1); + /* w_release_lump_name("STFST01"); + * w_release_lump_name("STFDEAD0"); + */ } +/* slam background */ + +static void wi_slam_background(void) +{ + v_draw_patch(0, 0, background); +} +/* Draws " Finished!" */ -// -// Display level completion time and par, -// or "sucks" message if overflow. -// -void -WI_drawTime -( int x, - int y, - int t ) +static void wi_draw_lf(void) { + int y = WI_TITLEY; - int div; - int n; + if (gamemode != commercial || wbs->last < NUMCMAPS) + { + /* draw */ + + v_draw_patch((SCREENWIDTH - SHORT(lnames[wbs->last]->width)) / 2, y, + lnames[wbs->last]); + + /* draw "Finished!" */ - if (t<0) - return; + y += (5 * SHORT(lnames[wbs->last]->height)) / 4; - if (t <= 61*59) + v_draw_patch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); + } + else if (wbs->last == NUMCMAPS) { - div = 1; - - do - { - n = (t / div) % 60; - x = WI_drawNum(x, y, n, 2) - SHORT(colon->width); - div *= 60; - - // draw - if (div==60 || t / div) - V_DrawPatch(x, y, colon); - - } while (t / div); + /* MAP33 - draw "Finished!" only */ + + v_draw_patch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); } - else + else if (wbs->last > NUMCMAPS) { - // "sucks" - V_DrawPatch(x - SHORT(sucks->width), y, sucks); + /* > MAP33. Doom bombs out here with a Bad v_draw_patch error. + * I'm pretty sure that doom2.exe is just reading into random + * bits of memory at this point, but let's try to be accurate + * anyway. This deliberately triggers a v_draw_patch error. + */ + + patch_t tmp = + { + SCREENWIDTH, + SCREENHEIGHT, + 1, + 1, + { + 0, 0, 0, 0, 0, 0, 0, 0 + }, + }; + + v_draw_patch(0, y, &tmp); } } +/* Draws "Entering " */ -void WI_End(void) +static void wi_draw_e(void) { - void WI_unloadData(void); - WI_unloadData(); -} + int y = WI_TITLEY; -void WI_initNoState(void) -{ - state = NoState; - acceleratestage = 0; - cnt = 10; -} + /* draw "Entering" */ -void WI_updateNoState(void) { + v_draw_patch((SCREENWIDTH - SHORT(entering->width)) / 2, y, entering); - WI_updateAnimatedBack(); + /* draw level */ + + y += (5 * SHORT(lnames[wbs->next]->height)) / 4; + + v_draw_patch((SCREENWIDTH - SHORT(lnames[wbs->next]->width)) / 2, y, + lnames[wbs->next]); +} - if (!--cnt) +static void wi_draw_on_lnode(int n, patch_t *c[]) +{ + int i; + int left; + int top; + int right; + int bottom; + boolean fits = false; + + i = 0; + do { - // Don't call WI_End yet. G_WorldDone doesnt immediately - // change gamestate, so WI_Drawer is still going to get - // run until that happens. If we do that after WI_End - // (which unloads all the graphics), we're in trouble. - //WI_End(); - G_WorldDone(); + left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset); + top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset); + right = left + SHORT(c[i]->width); + bottom = top + SHORT(c[i]->height); + + if (left >= 0 && right < SCREENWIDTH && top >= 0 && + bottom < SCREENHEIGHT) + { + fits = true; + } + else + { + i++; + } } + while (!fits && i != 2 && c[i] != NULL); + if (fits && i < 2) + { + v_draw_patch(lnodes[wbs->epsd][n].x, lnodes[wbs->epsd][n].y, c[i]); + } + else + { + printf("Could not place patch on level %d", n + 1); /* DEBUG */ + } } -static boolean snl_pointeron = false; +static void wi_init_animate_back(void) +{ + int i; + anim_t *a; + if (gamemode == commercial) return; -void WI_initShowNextLoc(void) -{ - state = ShowNextLoc; - acceleratestage = 0; - cnt = SHOWNEXTLOCDELAY * TICRATE; + if (wbs->epsd > 2) return; - WI_initAnimatedBack(); -} + for (i = 0; i < NUMANIMS[wbs->epsd]; i++) + { + a = &anims[wbs->epsd][i]; -void WI_updateShowNextLoc(void) -{ - WI_updateAnimatedBack(); + /* init variables */ - if (!--cnt || acceleratestage) - WI_initNoState(); - else - snl_pointeron = (cnt & 31) < 20; + a->ctr = -1; + + /* specify the next time to draw it */ + + if (a->type == ANIM_ALWAYS) + a->nexttic = bcnt + 1 + (m_random() % a->period); + else if (a->type == ANIM_RANDOM) + a->nexttic = bcnt + 1 + a->data2 + (m_random() % a->data1); + else if (a->type == ANIM_LEVEL) + a->nexttic = bcnt + 1; + } } -void WI_drawShowNextLoc(void) +static void wi_update_animated_block(void) { + int i; + anim_t *a; - int i; - int last; + if (gamemode == commercial) return; - WI_slamBackground(); + if (wbs->epsd > 2) return; - // draw animated background - WI_drawAnimatedBack(); - - if ( gamemode != commercial) + for (i = 0; i < NUMANIMS[wbs->epsd]; i++) { - if (wbs->epsd > 2) - { - WI_drawEL(); - return; - } - - last = (wbs->last == 8) ? wbs->next - 1 : wbs->last; - - // draw a splat on taken cities. - for (i=0 ; i<=last ; i++) - WI_drawOnLnode(i, splat); - - // splat the secret level? - if (wbs->didsecret) - WI_drawOnLnode(8, splat); - - // draw flashing ptr - if (snl_pointeron) - WI_drawOnLnode(wbs->next, yah); + a = &anims[wbs->epsd][i]; + + if (bcnt == a->nexttic) + { + switch (a->type) + { + case ANIM_ALWAYS: + if (++a->ctr >= a->nanims) a->ctr = 0; + a->nexttic = bcnt + a->period; + break; + + case ANIM_RANDOM: + a->ctr++; + if (a->ctr == a->nanims) + { + a->ctr = -1; + a->nexttic = bcnt + a->data2 + (m_random() % a->data1); + } + else + a->nexttic = bcnt + a->period; + break; + + case ANIM_LEVEL: + + /* gawd-awful hack for level anims */ + + if (!(state == STAT_COUNT && i == 7) && wbs->next == a->data1) + { + a->ctr++; + if (a->ctr == a->nanims) a->ctr--; + a->nexttic = bcnt + a->period; + } + break; + } + } } - - // draws which level you are entering.. - if ( (gamemode != commercial) - || wbs->next != 30) - WI_drawEL(); - } -void WI_drawNoState(void) +static void wi_draw_animated_back(void) { - snl_pointeron = true; - WI_drawShowNextLoc(); -} + int i; + anim_t *a; -int WI_fragSum(int playernum) -{ - int i; - int frags = 0; - - for (i=0 ; iepsd > 2) return; - return frags; -} + for (i = 0; i < NUMANIMS[wbs->epsd]; i++) + { + a = &anims[wbs->epsd][i]; + if (a->ctr >= 0) v_draw_patch(a->loc.x, a->loc.y, a->p[a->ctr]); + } +} +/* Draws a number. + * If digits > 0, then use that many digits minimum, otherwise only use as + * many as necessary. Returns new x position. + */ -static int dm_state; -static int dm_frags[MAXPLAYERS][MAXPLAYERS]; -static int dm_totals[MAXPLAYERS]; +static int wi_draw_num(int x, int y, int n, int digits) +{ + int fontwidth = SHORT(num[0]->width); + int neg; + int temp; + if (digits < 0) + { + if (!n) + { + /* make variable-length zeros 1 digit long */ + digits = 1; + } + else + { + /* figure out # of digits in # */ + + digits = 0; + temp = n; + + while (temp) + { + temp /= 10; + digits++; + } + } + } -void WI_initDeathmatchStats(void) -{ + neg = n < 0; + if (neg) n = -n; - int i; - int j; + /* if non-number, do not draw it */ - state = StatCount; - acceleratestage = 0; - dm_state = 1; + if (n == 1994) return 0; - cnt_pause = TICRATE; + /* draw the new number */ - for (i=0 ; i 99) - dm_frags[i][j] = 99; - - if (dm_frags[i][j] < -99) - dm_frags[i][j] = -99; - - stillticking = true; - } - } - dm_totals[i] = WI_fragSum(i); - - if (dm_totals[i] > 99) - dm_totals[i] = 99; - - if (dm_totals[i] < -99) - dm_totals[i] = -99; - } - - } - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - dm_state++; - } + if (t < 0) return; - } - else if (dm_state == 4) + if (t <= 61 * 59) { - if (acceleratestage) - { - S_StartSound(0, sfx_slop); - - if ( gamemode == commercial) - WI_initNoState(); - else - WI_initShowNextLoc(); - } + div = 1; + + do + { + n = (t / div) % 60; + x = wi_draw_num(x, y, n, 2) - SHORT(colon->width); + div *= 60; + + /* draw */ + + if (div == 60 || t / div) v_draw_patch(x, y, colon); + } + while (t / div); } - else if (dm_state & 1) + else { - if (!--cnt_pause) - { - dm_state++; - cnt_pause = TICRATE; - } + /* "sucks" */ + + v_draw_patch(x - SHORT(sucks->width), y, sucks); } } +static void wi_init_nostate(void) +{ + state = NO_STATE; + acceleratestage = 0; + cnt = 10; +} - -void WI_drawDeathmatchStats(void) +static void wi_update_no_state(void) { + wi_update_animated_block(); - int i; - int j; - int x; - int y; - int w; - - WI_slamBackground(); - - // draw animated background - WI_drawAnimatedBack(); - WI_drawLF(); - - // draw stat titles (top line) - V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2, - DM_MATRIXY-WI_SPACINGY+10, - total); - - V_DrawPatch(DM_KILLERSX, DM_KILLERSY, killers); - V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, victims); - - // draw P? - x = DM_MATRIXX + DM_SPACINGX; - y = DM_MATRIXY; - - for (i=0 ; iwidth)/2, - DM_MATRIXY - WI_SPACINGY, - p[i]); - - V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, - y, - p[i]); - - if (i == me) - { - V_DrawPatch(x-SHORT(p[i]->width)/2, - DM_MATRIXY - WI_SPACINGY, - bstar); - - V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, - y, - star); - } - } - else - { - // V_DrawPatch(x-SHORT(bp[i]->width)/2, - // DM_MATRIXY - WI_SPACINGY, bp[i]); - // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2, - // y, bp[i]); - } - x += DM_SPACINGX; - y += WI_SPACINGY; + /* Don't call wi_end yet. g_world_done doesn't immediately + * change gamestate, so wi_drawer is still going to get + * run until that happens. If we do that after wi_end + * (which unloads all the graphics), we're in trouble. + * wi_end(); + */ + + g_world_done(); } +} - // draw stats - y = DM_MATRIXY+10; - w = SHORT(num[0]->width); +static void wi_init_show_next_loc(void) +{ + state = SHOW_NEXT_LOC; + acceleratestage = 0; + cnt = SHOWNEXTLOCDELAY * TICRATE; - for (i=0 ; iepsd > 2) + { + wi_draw_e(); + return; + } + + last = (wbs->last == 8) ? wbs->next - 1 : wbs->last; + + /* draw a splat on taken cities. */ + + for (i = 0; i <= last; i++) + wi_draw_on_lnode(i, splat); + + /* splat the secret level? */ + + if (wbs->didsecret) wi_draw_on_lnode(8, splat); - cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0; + /* draw flashing ptr */ - dofrags += WI_fragSum(i); + if (snl_pointeron) wi_draw_on_lnode(wbs->next, yah); } - dofrags = !!dofrags; + /* draws which level you are entering.. */ - WI_initAnimatedBack(); + if ((gamemode != commercial) || wbs->next != 30) wi_draw_e(); } +static void wi_draw_no_state(void) +{ + snl_pointeron = true; + wi_draw_show_next_loc(); +} + +static int wi_frag_sum(int playernum) +{ + int i; + int l_frags = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && i != playernum) + { + l_frags += plrs[playernum].frags[i]; + } + } + + /* JDC hack - negative frags. */ + + l_frags -= plrs[playernum].frags[playernum]; + + /* UNUSED if (frags < 0) + * frags = 0; + */ + + return l_frags; +} -void WI_updateNetgameStats(void) +static void wi_init_deathmatch_stats(void) { + int i; + int j; - int i; - int fsum; - - boolean stillticking; + state = STAT_COUNT; + acceleratestage = 0; + dm_state = 1; - WI_updateAnimatedBack(); + cnt_pause = TICRATE; - if (acceleratestage && ng_state != 10) + for (i = 0; i < MAXPLAYERS; i++) { - acceleratestage = 0; - - for (i=0 ; imaxkills; - cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; - cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; - - if (dofrags) - cnt_frags[i] = WI_fragSum(i); - } - S_StartSound(0, sfx_barexp); - ng_state = 10; + if (playeringame[i]) + { + for (j = 0; j < MAXPLAYERS; j++) + { + if (playeringame[j]) dm_frags[i][j] = 0; + } + + dm_totals[i] = 0; + } } - if (ng_state == 2) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (plrs[i].skills * 100) / wbs->maxkills) - cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; - else - stillticking = true; - } - - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - ng_state++; - } - } - else if (ng_state == 4) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (plrs[i].sitems * 100) / wbs->maxitems) - cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; - else - stillticking = true; - } - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - ng_state++; - } - } - else if (ng_state == 6) + wi_init_animate_back(); +} + +static void wi_update_deathmatch_stats(void) +{ + int i; + int j; + + boolean stillticking; + + wi_update_animated_block(); + + if (acceleratestage && dm_state != 4) { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (plrs[i].ssecret * 100) / wbs->maxsecret) - cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; - else - stillticking = true; - } - - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - ng_state += 1 + 2*!dofrags; - } + acceleratestage = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + for (j = 0; j < MAXPLAYERS; j++) + { + if (playeringame[j]) dm_frags[i][j] = plrs[i].frags[j]; + } + + dm_totals[i] = wi_frag_sum(i); + } + } + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + dm_state = 4; } - else if (ng_state == 8) + + if (dm_state == 2) { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (fsum = WI_fragSum(i))) - cnt_frags[i] = fsum; - else - stillticking = true; - } - - if (!stillticking) - { - S_StartSound(0, sfx_pldeth); - ng_state++; - } +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif + + stillticking = false; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + for (j = 0; j < MAXPLAYERS; j++) + { + if (playeringame[j] && dm_frags[i][j] != plrs[i].frags[j]) + { + if (plrs[i].frags[j] < 0) + dm_frags[i][j]--; + else + dm_frags[i][j]++; + + if (dm_frags[i][j] > 99) dm_frags[i][j] = 99; + + if (dm_frags[i][j] < -99) dm_frags[i][j] = -99; + + stillticking = true; + } + } + + dm_totals[i] = wi_frag_sum(i); + + if (dm_totals[i] > 99) dm_totals[i] = 99; + + if (dm_totals[i] < -99) dm_totals[i] = -99; + } + } + + if (!stillticking) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + dm_state++; + } } - else if (ng_state == 10) + else if (dm_state == 4) { - if (acceleratestage) - { - S_StartSound(0, sfx_sgcock); - if ( gamemode == commercial ) - WI_initNoState(); - else - WI_initShowNextLoc(); - } + if (acceleratestage) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_SLOP); +#endif + + if (gamemode == commercial) + wi_init_nostate(); + else + wi_init_show_next_loc(); + } } - else if (ng_state & 1) + else if (dm_state & 1) { - if (!--cnt_pause) - { - ng_state++; - cnt_pause = TICRATE; - } + if (!--cnt_pause) + { + dm_state++; + cnt_pause = TICRATE; + } } } +static void wi_draw_deathmatch_stats(void) +{ + int i; + int j; + int x; + int y; + int w; + wi_slam_background(); -void WI_drawNetgameStats(void) -{ - int i; - int x; - int y; - int pwidth = SHORT(percent->width); + /* draw animated background */ - WI_slamBackground(); - - // draw animated background - WI_drawAnimatedBack(); + wi_draw_animated_back(); + wi_draw_lf(); - WI_drawLF(); + /* draw stat titles (top line) */ - // draw stat titles (top line) - V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width), - NG_STATSY, kills); + v_draw_patch(DM_TOTALSX - SHORT(total->width) / 2, + DM_MATRIXY - WI_SPACINGY + 10, total); - V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width), - NG_STATSY, items); + v_draw_patch(DM_KILLERSX, DM_KILLERSY, killers); + v_draw_patch(DM_VICTIMSX, DM_VICTIMSY, victims); - V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width), - NG_STATSY, secret); - - if (dofrags) - V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width), - NG_STATSY, frags); + /* draw P? */ - // draw stats - y = NG_STATSY + SHORT(kills->height); + x = DM_MATRIXX + DM_SPACINGX; + y = DM_MATRIXY; - for (i=0 ; iwidth) / 2, DM_MATRIXY - WI_SPACINGY, + p[i]); - x = NG_STATSX; - V_DrawPatch(x-SHORT(p[i]->width), y, p[i]); + v_draw_patch(DM_MATRIXX - SHORT(p[i]->width) / 2, y, p[i]); - if (i == me) - V_DrawPatch(x-SHORT(p[i]->width), y, star); + if (i == me) + { + v_draw_patch(x - SHORT(p[i]->width) / 2, + DM_MATRIXY - WI_SPACINGY, bstar); - x += NG_SPACINGX; - WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX; - WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX; - WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX; + v_draw_patch(DM_MATRIXX - SHORT(p[i]->width) / 2, y, star); + } + } + else + { + /* v_draw_patch(x-SHORT(bp[i]->width)/2, + * DM_MATRIXY - WI_SPACINGY, bp[i]); + * v_draw_patch(DM_MATRIXX-SHORT(bp[i]->width)/2, + * y, bp[i]); + */ + } + + x += DM_SPACINGX; + y += WI_SPACINGY; + } - if (dofrags) - WI_drawNum(x, y+10, cnt_frags[i], -1); + /* draw stats */ - y += WI_SPACINGY; - } + y = DM_MATRIXY + 10; + w = SHORT(num[0]->width); -} + for (i = 0; i < MAXPLAYERS; i++) + { + x = DM_MATRIXX + DM_SPACINGX; -static int sp_state; + if (playeringame[i]) + { + for (j = 0; j < MAXPLAYERS; j++) + { + if (playeringame[j]) wi_draw_num(x + w, y, dm_frags[i][j], 2); -void WI_initStats(void) -{ - state = StatCount; - acceleratestage = 0; - sp_state = 1; - cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1; - cnt_time = cnt_par = -1; - cnt_pause = TICRATE; - - WI_initAnimatedBack(); + x += DM_SPACINGX; + } + + wi_draw_num(DM_TOTALSX + w, y, dm_totals[i], 2); + } + + y += WI_SPACINGY; + } } -void WI_updateStats(void) +static void wi_init_netgame_stats(void) { + int i; - WI_updateAnimatedBack(); + state = STAT_COUNT; + acceleratestage = 0; + ng_state = 1; - if (acceleratestage && sp_state != 10) - { - acceleratestage = 0; - cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; - cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; - cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; - cnt_time = plrs[me].stime / TICRATE; - cnt_par = wbs->partime / TICRATE; - S_StartSound(0, sfx_barexp); - sp_state = 10; - } + cnt_pause = TICRATE; - if (sp_state == 2) + for (i = 0; i < MAXPLAYERS; i++) { - cnt_kills[0] += 2; + if (!playeringame[i]) continue; - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); + cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0; - if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills) - { - cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; - S_StartSound(0, sfx_barexp); - sp_state++; - } + dofrags += wi_frag_sum(i); } - else if (sp_state == 4) - { - cnt_items[0] += 2; - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); + dofrags = !!dofrags; - if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems) - { - cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; - S_StartSound(0, sfx_barexp); - sp_state++; - } - } - else if (sp_state == 6) + wi_init_animate_back(); +} + +static void wi_update_netgame_stats(void) +{ + int i; + int fsum; + + boolean stillticking; + + wi_update_animated_block(); + + if (acceleratestage && ng_state != 10) { - cnt_secret[0] += 2; + acceleratestage = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); + cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; + cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; + cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; - if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret) - { - cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; - S_StartSound(0, sfx_barexp); - sp_state++; - } + if (dofrags) cnt_frags[i] = wi_frag_sum(i); + } + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + ng_state = 10; } - else if (sp_state == 8) + if (ng_state == 2) { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif - cnt_time += 3; + stillticking = false; - if (cnt_time >= plrs[me].stime / TICRATE) - cnt_time = plrs[me].stime / TICRATE; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; - cnt_par += 3; + cnt_kills[i] += 2; - if (cnt_par >= wbs->partime / TICRATE) - { - cnt_par = wbs->partime / TICRATE; + if (cnt_kills[i] >= (plrs[i].skills * 100) / wbs->maxkills) + cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; + else + stillticking = true; + } - if (cnt_time >= plrs[me].stime / TICRATE) - { - S_StartSound(0, sfx_barexp); - sp_state++; - } - } + if (!stillticking) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + ng_state++; + } } - else if (sp_state == 10) + else if (ng_state == 4) { - if (acceleratestage) - { - S_StartSound(0, sfx_sgcock); - - if (gamemode == commercial) - WI_initNoState(); - else - WI_initShowNextLoc(); - } +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif + + stillticking = false; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; + + cnt_items[i] += 2; + if (cnt_items[i] >= (plrs[i].sitems * 100) / wbs->maxitems) + cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; + else + stillticking = true; + } + + if (!stillticking) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + ng_state++; + } } - else if (sp_state & 1) + else if (ng_state == 6) { - if (!--cnt_pause) - { - sp_state++; - cnt_pause = TICRATE; - } - } +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif -} + stillticking = false; -void WI_drawStats(void) -{ - // line height - int lh; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; - lh = (3*SHORT(num[0]->height))/2; + cnt_secret[i] += 2; - WI_slamBackground(); + if (cnt_secret[i] >= (plrs[i].ssecret * 100) / wbs->maxsecret) + cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; + else + stillticking = true; + } - // draw animated background - WI_drawAnimatedBack(); - - WI_drawLF(); + if (!stillticking) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + ng_state += 1 + 2 * !dofrags; + } + } + else if (ng_state == 8) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif - V_DrawPatch(SP_STATSX, SP_STATSY, kills); - WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]); + stillticking = false; - V_DrawPatch(SP_STATSX, SP_STATSY+lh, items); - WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; - V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, sp_secret); - WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]); + cnt_frags[i] += 1; - V_DrawPatch(SP_TIMEX, SP_TIMEY, timepatch); - WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time); + if (cnt_frags[i] >= (fsum = wi_frag_sum(i))) + cnt_frags[i] = fsum; + else + stillticking = true; + } - if (wbs->epsd < 3) + if (!stillticking) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_PLDETH); +#endif + ng_state++; + } + } + else if (ng_state == 10) + { + if (acceleratestage) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_SGCOCK); +#endif + if (gamemode == commercial) + wi_init_nostate(); + else + wi_init_show_next_loc(); + } + } + else if (ng_state & 1) { - V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par); - WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par); + if (!--cnt_pause) + { + ng_state++; + cnt_pause = TICRATE; + } } +} +static void wi_init_stats(void) +{ + state = STAT_COUNT; + acceleratestage = 0; + sp_state = 1; + cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1; + cnt_time = cnt_par = -1; + cnt_pause = TICRATE; + + wi_init_animate_back(); } -void WI_checkForAccelerate(void) +static void wi_update_stats(void) { - int i; - player_t *player; + wi_update_animated_block(); - // check for button presses to skip delays - for (i=0, player = players ; icmd.buttons & BT_ATTACK) - { - if (!player->attackdown) - acceleratestage = 1; - player->attackdown = true; - } - else - player->attackdown = false; - if (player->cmd.buttons & BT_USE) - { - if (!player->usedown) - acceleratestage = 1; - player->usedown = true; - } - else - player->usedown = false; - } + acceleratestage = 0; + cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; + cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; + cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; + cnt_time = plrs[me].stime / TICRATE; + cnt_par = wbs->partime / TICRATE; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + sp_state = 10; } -} - + if (sp_state == 2) + { + cnt_kills[0] += 2; -// Updates stuff each tick -void WI_Ticker(void) -{ - // counter for general background animation - bcnt++; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif - if (bcnt == 1) - { - // intermission music - if ( gamemode == commercial ) - S_ChangeMusic(mus_dm2int, true); - else - S_ChangeMusic(mus_inter, true); + if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills) + { + cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + sp_state++; + } } + else if (sp_state == 4) + { + cnt_items[0] += 2; - WI_checkForAccelerate(); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif - switch (state) + if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems) + { + cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + sp_state++; + } + } + else if (sp_state == 6) { - case StatCount: - if (deathmatch) WI_updateDeathmatchStats(); - else if (netgame) WI_updateNetgameStats(); - else WI_updateStats(); - break; - - case ShowNextLoc: - WI_updateShowNextLoc(); - break; - - case NoState: - WI_updateNoState(); - break; + cnt_secret[0] += 2; + +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif + + if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret) + { + cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + sp_state++; + } } -} + else if (sp_state == 8) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + if (!(bcnt & 3)) s_start_sound(0, SFX_PISTOL); +#endif -typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); + cnt_time += 3; -// Common load/unload function. Iterates over all the graphics -// lumps to be loaded/unloaded into memory. + if (cnt_time >= plrs[me].stime / TICRATE) + cnt_time = plrs[me].stime / TICRATE; -static void WI_loadUnloadData(load_callback_t callback) -{ - int i, j; - char name[9]; - anim_t *a; + cnt_par += 3; + + if (cnt_par >= wbs->partime / TICRATE) + { + cnt_par = wbs->partime / TICRATE; - if (gamemode == commercial) + if (cnt_time >= plrs[me].stime / TICRATE) + { +#ifdef CONFIG_GAMES_NXDOOM_SOUND + s_start_sound(0, SFX_BAREXP); +#endif + sp_state++; + } + } + } + else if (sp_state == 10) { - for (i=0 ; iepsd, i); - callback(name, &lnames[i]); - } - - // you are here - callback(DEH_String("WIURH0"), &yah[0]); - - // you are here (alt.) - callback(DEH_String("WIURH1"), &yah[1]); - - // splat - callback(DEH_String("WISPLAT"), &splat[0]); - - if (wbs->epsd < 3) - { - for (j=0;jepsd];j++) - { - a = &anims[wbs->epsd][j]; - for (i=0;inanims;i++) - { - // MONDO HACK! - if (wbs->epsd != 1 || j != 8) - { - // animations - DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i); - callback(name, &a->p[i]); - } - else - { - // HACK ALERT! - a->p[i] = anims[1][4].p[i]; - } - } - } - } + if (!--cnt_pause) + { + sp_state++; + cnt_pause = TICRATE; + } } +} - // More hacks on minus sign. - if (W_CheckNumForName(DEH_String("WIMINUS")) > 0) - callback(DEH_String("WIMINUS"), &wiminus); - else - wiminus = NULL; +static void wi_draw_netgame_stats(void) +{ + int i; + int x; + int y; + int pwidth = SHORT(percent->width); - for (i=0;i<10;i++) - { - // numbers 0-9 - DEH_snprintf(name, 9, "WINUM%d", i); - callback(name, &num[i]); - } + wi_slam_background(); - // percent sign - callback(DEH_String("WIPCNT"), &percent); + /* draw animated background */ - // "finished" - callback(DEH_String("WIF"), &finished); + wi_draw_animated_back(); - // "entering" - callback(DEH_String("WIENTER"), &entering); + wi_draw_lf(); - // "kills" - callback(DEH_String("WIOSTK"), &kills); + /* draw stat titles (top line) */ - // "scrt" - callback(DEH_String("WIOSTS"), &secret); + v_draw_patch(NG_STATSX + NG_SPACINGX - SHORT(kills->width), NG_STATSY, + kills); - // "secret" - callback(DEH_String("WISCRT2"), &sp_secret); + v_draw_patch(NG_STATSX + 2 * NG_SPACINGX - SHORT(items->width), NG_STATSY, + items); - // french wad uses WIOBJ (?) - if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0) + v_draw_patch(NG_STATSX + 3 * NG_SPACINGX - SHORT(secret->width), NG_STATSY, + secret); + + if (dofrags) { - // "items" - if (netgame && !deathmatch) - callback(DEH_String("WIOBJ"), &items); - else - callback(DEH_String("WIOSTI"), &items); - } else { - callback(DEH_String("WIOSTI"), &items); + v_draw_patch(NG_STATSX + 4 * NG_SPACINGX - SHORT(frags->width), + NG_STATSY, frags); } - // "frgs" - callback(DEH_String("WIFRGS"), &frags); - - // ":" - callback(DEH_String("WICOLON"), &colon); - - // "time" - callback(DEH_String("WITIME"), &timepatch); + /* draw stats */ - // "sucks" - callback(DEH_String("WISUCKS"), &sucks); + y = NG_STATSY + SHORT(kills->height); - // "par" - callback(DEH_String("WIPAR"), &par); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; - // "killers" (vertical) - callback(DEH_String("WIKILRS"), &killers); + x = NG_STATSX; + v_draw_patch(x - SHORT(p[i]->width), y, p[i]); - // "victims" (horiz) - callback(DEH_String("WIVCTMS"), &victims); + if (i == me) v_draw_patch(x - SHORT(p[i]->width), y, star); - // "total" - callback(DEH_String("WIMSTT"), &total); + x += NG_SPACINGX; + wi_draw_percent(x - pwidth, y + 10, cnt_kills[i]); + x += NG_SPACINGX; + wi_draw_percent(x - pwidth, y + 10, cnt_items[i]); + x += NG_SPACINGX; + wi_draw_percent(x - pwidth, y + 10, cnt_secret[i]); + x += NG_SPACINGX; - for (i=0 ; i= exe_ultimate && wbs->epsd == 3) - { - M_StringCopy(name, DEH_String("INTERPIC"), sizeof(name)); - } - else - { - DEH_snprintf(name, sizeof(name), "WIMAP%d", wbs->epsd); - } + lh = (3 * SHORT(num[0]->height)) / 2; - // Draw backdrop and save to a temporary buffer + wi_slam_background(); - callback(name, &background); -} + /* draw animated background */ -static void WI_loadCallback(const char *name, patch_t **variable) -{ - *variable = W_CacheLumpName(name, PU_STATIC); -} + wi_draw_animated_back(); -void WI_loadData(void) -{ - if (gamemode == commercial) - { - NUMCMAPS = 32; - lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS, - PU_STATIC, NULL); - } - else - { - lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS, - PU_STATIC, NULL); - } + wi_draw_lf(); - WI_loadUnloadData(WI_loadCallback); + v_draw_patch(SP_STATSX, SP_STATSY, kills); + wi_draw_percent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]); - // These two graphics are special cased because we're sharing - // them with the status bar code + v_draw_patch(SP_STATSX, SP_STATSY + lh, items); + wi_draw_percent(SCREENWIDTH - SP_STATSX, SP_STATSY + lh, cnt_items[0]); - // your face - star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC); + v_draw_patch(SP_STATSX, SP_STATSY + 2 * lh, sp_secret); + wi_draw_percent(SCREENWIDTH - SP_STATSX, SP_STATSY + 2 * lh, + cnt_secret[0]); - // dead face - bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC); -} + v_draw_patch(SP_TIMEX, SP_TIMEY, timepatch); + wi_draw_time(SCREENWIDTH / 2 - SP_TIMEX, SP_TIMEY, cnt_time); -static void WI_unloadCallback(const char *name, patch_t **variable) -{ - W_ReleaseLumpName(name); - *variable = NULL; + if (wbs->epsd < 3) + { + v_draw_patch(SCREENWIDTH / 2 + SP_TIMEX, SP_TIMEY, par); + wi_draw_time(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par); + } } -void WI_unloadData(void) +static void wi_check_for_accelerate(void) { - WI_loadUnloadData(WI_unloadCallback); + int i; + player_t *player; - // We do not free these lumps as they are shared with the status - // bar code. - - // W_ReleaseLumpName("STFST01"); - // W_ReleaseLumpName("STFDEAD0"); + /* check for button presses to skip delays */ + + for (i = 0, player = players; i < MAXPLAYERS; i++, player++) + { + if (playeringame[i]) + { + if (player->cmd.buttons & BT_ATTACK) + { + if (!player->attackdown) acceleratestage = 1; + player->attackdown = true; + } + else + player->attackdown = false; + if (player->cmd.buttons & BT_USE) + { + if (!player->usedown) acceleratestage = 1; + player->usedown = true; + } + else + player->usedown = false; + } + } } -void WI_Drawer (void) +static void wi_init_variables(wbstartstruct_t *wbstartstruct) { - switch (state) + wbs = wbstartstruct; + + acceleratestage = 0; + cnt = bcnt = 0; + firstrefresh = 1; + me = wbs->pnum; + plrs = wbs->plyr; + + if (!wbs->maxkills) wbs->maxkills = 1; + + if (!wbs->maxitems) wbs->maxitems = 1; + + if (!wbs->maxsecret) wbs->maxsecret = 1; + + if (gameversion < exe_ultimate) { - case StatCount: - if (deathmatch) - WI_drawDeathmatchStats(); - else if (netgame) - WI_drawNetgameStats(); - else - WI_drawStats(); - break; - - case ShowNextLoc: - WI_drawShowNextLoc(); - break; - - case NoState: - WI_drawNoState(); - break; + if (wbs->epsd > 2) wbs->epsd -= 3; } } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void WI_initVariables(wbstartstruct_t* wbstartstruct) +void wi_end(void) { + wi_unload_data(); +} + +/* Updates stuff each tick */ - wbs = wbstartstruct; +void wi_ticker(void) +{ + /* counter for general background animation */ -#ifdef RANGECHECKING - if (gamemode != commercial) + bcnt++; + + if (bcnt == 1) { - if (gameversion >= exe_ultimate) - RNGCHECK(wbs->epsd, 0, 3); +#ifdef CONFIG_GAMES_NXDOOM_SOUND + /* intermission music */ + + if (gamemode == commercial) + s_change_music(MUS_DM2INT, true); else - RNGCHECK(wbs->epsd, 0, 2); + s_change_music(MUS_INTER, true); +#endif } - else + + wi_check_for_accelerate(); + + switch (state) { - RNGCHECK(wbs->last, 0, 8); - RNGCHECK(wbs->next, 0, 8); - } - RNGCHECK(wbs->pnum, 0, MAXPLAYERS); - RNGCHECK(wbs->pnum, 0, MAXPLAYERS); -#endif + case STAT_COUNT: + if (deathmatch) + wi_update_deathmatch_stats(); + else if (netgame) + wi_update_netgame_stats(); + else + wi_update_stats(); + break; - acceleratestage = 0; - cnt = bcnt = 0; - firstrefresh = 1; - me = wbs->pnum; - plrs = wbs->plyr; + case SHOW_NEXT_LOC: + wi_update_show_next_loc(); + break; - if (!wbs->maxkills) - wbs->maxkills = 1; + case NO_STATE: + wi_update_no_state(); + break; + } +} - if (!wbs->maxitems) - wbs->maxitems = 1; +void wi_drawer(void) +{ + switch (state) + { + case STAT_COUNT: + if (deathmatch) + wi_draw_deathmatch_stats(); + else if (netgame) + wi_draw_netgame_stats(); + else + wi_draw_stats(); + break; - if (!wbs->maxsecret) - wbs->maxsecret = 1; + case SHOW_NEXT_LOC: + wi_draw_show_next_loc(); + break; - if ( gameversion < exe_ultimate ) - if (wbs->epsd > 2) - wbs->epsd -= 3; + case NO_STATE: + wi_draw_no_state(); + break; + } } -void WI_Start(wbstartstruct_t* wbstartstruct) +void wi_start(wbstartstruct_t *wbstartstruct) { - WI_initVariables(wbstartstruct); - WI_loadData(); - - if (deathmatch) - WI_initDeathmatchStats(); - else if (netgame) - WI_initNetgameStats(); - else - WI_initStats(); + wi_init_variables(wbstartstruct); + wi_load_data(); + + if (deathmatch) + wi_init_deathmatch_stats(); + else if (netgame) + wi_init_netgame_stats(); + else + wi_init_stats(); } diff --git a/games/NXDoom/src/doom/wi_stuff.h b/games/NXDoom/src/doom/wi_stuff.h index 296571f73a8..78c689d78fc 100644 --- a/games/NXDoom/src/doom/wi_stuff.h +++ b/games/NXDoom/src/doom/wi_stuff.h @@ -1,48 +1,78 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Intermission. -// +/**************************************************************************** + * apps/games/NXDoom/src/doom/wi_stuff.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Intermission. + * + ****************************************************************************/ #ifndef __WI_STUFF__ #define __WI_STUFF__ -//#include "v_video.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "doomdef.h" -// States for the intermission +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -typedef enum -{ - NoState = -1, - StatCount, - ShowNextLoc, -} stateenum_t; +/**************************************************************************** + * Name: wi_ticker + * + * Description: + * Called by main loop, animate the intermission. + * + ****************************************************************************/ -// Called by main loop, animate the intermission. -void WI_Ticker (void); +void wi_ticker(void); -// Called by main loop, -// draws the intermission directly into the screen buffer. -void WI_Drawer (void); +/**************************************************************************** + * Name: wi_drawer + * + * Description: + * Called by main loop, draws the intermission directly into the screen + * buffer. + * + ****************************************************************************/ -// Setup for an intermission screen. -void WI_Start(wbstartstruct_t* wbstartstruct); +void wi_drawer(void); -// Shut down the intermission screen -void WI_End(void); +/**************************************************************************** + * Name: wi_start + * + * Description: + * Setup for an intermission screen. + * + ****************************************************************************/ -#endif +void wi_start(wbstartstruct_t *wbstartstruct); + +/**************************************************************************** + * Name: wi_end + * + * Description: + * Shut down the intermission screen + * + ****************************************************************************/ + +void wi_end(void); + +#endif /* __WI_STUFF__ */ diff --git a/games/NXDoom/src/doomkeys.h b/games/NXDoom/src/doomkeys.h index 1098c719dee..f29a2b78221 100644 --- a/games/NXDoom/src/doomkeys.h +++ b/games/NXDoom/src/doomkeys.h @@ -1,156 +1,302 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Key definitions -// +/**************************************************************************** + * apps/games/NXDoom/src/doomkeys.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Key definitions + * + * + ****************************************************************************/ #ifndef __DOOMKEYS__ #define __DOOMKEYS__ -// -// DOOM keyboard definition. -// This is the stuff configured by Setup.Exe. -// Most key data are simple ascii (uppercased). -// -#define KEY_RIGHTARROW 0xae -#define KEY_LEFTARROW 0xac -#define KEY_UPARROW 0xad -#define KEY_DOWNARROW 0xaf -#define KEY_ESCAPE 27 -#define KEY_ENTER 13 -#define KEY_TAB 9 -#define KEY_F1 (0x80+0x3b) -#define KEY_F2 (0x80+0x3c) -#define KEY_F3 (0x80+0x3d) -#define KEY_F4 (0x80+0x3e) -#define KEY_F5 (0x80+0x3f) -#define KEY_F6 (0x80+0x40) -#define KEY_F7 (0x80+0x41) -#define KEY_F8 (0x80+0x42) -#define KEY_F9 (0x80+0x43) -#define KEY_F10 (0x80+0x44) -#define KEY_F11 (0x80+0x57) -#define KEY_F12 (0x80+0x58) - -#define KEY_BACKSPACE 0x7f -#define KEY_PAUSE 0xff - -#define KEY_EQUALS 0x3d -#define KEY_MINUS 0x2d - -#define KEY_RSHIFT (0x80+0x36) -#define KEY_RCTRL (0x80+0x1d) -#define KEY_RALT (0x80+0x38) - -#define KEY_LALT KEY_RALT - -// new keys: - -#define KEY_CAPSLOCK (0x80+0x3a) -#define KEY_NUMLOCK (0x80+0x45) -#define KEY_SCRLCK (0x80+0x46) -#define KEY_PRTSCR (0x80+0x59) - -#define KEY_HOME (0x80+0x47) -#define KEY_END (0x80+0x4f) -#define KEY_PGUP (0x80+0x49) -#define KEY_PGDN (0x80+0x51) -#define KEY_INS (0x80+0x52) -#define KEY_DEL (0x80+0x53) - -#define KEYP_0 KEY_INS -#define KEYP_1 KEY_END -#define KEYP_2 KEY_DOWNARROW -#define KEYP_3 KEY_PGDN -#define KEYP_4 KEY_LEFTARROW -#define KEYP_5 (0x80+0x4c) -#define KEYP_6 KEY_RIGHTARROW -#define KEYP_7 KEY_HOME -#define KEYP_8 KEY_UPARROW -#define KEYP_9 KEY_PGUP - -#define KEYP_DIVIDE '/' -#define KEYP_PLUS '+' -#define KEYP_MINUS '-' -#define KEYP_MULTIPLY '*' -#define KEYP_PERIOD 0 -#define KEYP_EQUALS KEY_EQUALS -#define KEYP_ENTER KEY_ENTER +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* DOOM keyboard definition. + * This is the stuff configured by Setup.Exe. + * Most key data are simple ascii (uppercased). + */ + +#define KEY_RIGHTARROW 0xae +#define KEY_LEFTARROW 0xac +#define KEY_UPARROW 0xad +#define KEY_DOWNARROW 0xaf +#define KEY_ESCAPE 27 +#define KEY_ENTER 13 +#define KEY_TAB 9 +#define KEY_F1 (0x80 + 0x3b) +#define KEY_F2 (0x80 + 0x3c) +#define KEY_F3 (0x80 + 0x3d) +#define KEY_F4 (0x80 + 0x3e) +#define KEY_F5 (0x80 + 0x3f) +#define KEY_F6 (0x80 + 0x40) +#define KEY_F7 (0x80 + 0x41) +#define KEY_F8 (0x80 + 0x42) +#define KEY_F9 (0x80 + 0x43) +#define KEY_F10 (0x80 + 0x44) +#define KEY_F11 (0x80 + 0x57) +#define KEY_F12 (0x80 + 0x58) + +#define KEY_BACKSPACE 0x7f +#define KEY_PAUSE 0xff + +#define KEY_EQUALS 0x3d +#define KEY_MINUS 0x2d + +#define KEY_RSHIFT (0x80 + 0x36) +#define KEY_RCTRL (0x80 + 0x1d) +#define KEY_RALT (0x80 + 0x38) + +#define KEY_LALT KEY_RALT + +/* new keys: */ + +#define KEY_CAPSLOCK (0x80 + 0x3a) +#define KEY_NUMLOCK (0x80 + 0x45) +#define KEY_SCRLCK (0x80 + 0x46) +#define KEY_PRTSCR (0x80 + 0x59) + +#define KEY_HOME (0x80 + 0x47) +#define KEY_END (0x80 + 0x4f) +#define KEY_PGUP (0x80 + 0x49) +#define KEY_PGDN (0x80 + 0x51) +#define KEY_INS (0x80 + 0x52) +#define KEY_DEL (0x80 + 0x53) + +#define KEYP_0 KEY_INS +#define KEYP_1 KEY_END +#define KEYP_2 KEY_DOWNARROW +#define KEYP_3 KEY_PGDN +#define KEYP_4 KEY_LEFTARROW +#define KEYP_5 (0x80 + 0x4c) +#define KEYP_6 KEY_RIGHTARROW +#define KEYP_7 KEY_HOME +#define KEYP_8 KEY_UPARROW +#define KEYP_9 KEY_PGUP + +#define KEYP_DIVIDE '/' +#define KEYP_PLUS '+' +#define KEYP_MINUS '-' +#define KEYP_MULTIPLY '*' +#define KEYP_PERIOD 0 +#define KEYP_EQUALS KEY_EQUALS +#define KEYP_ENTER KEY_ENTER #define KEY_NONUSBACKSLASH '\\' -#define SCANCODE_TO_KEYS_ARRAY { \ - 0, 0, 0, 0, 'a', /* 0-9 */ \ - 'b', 'c', 'd', 'e', 'f', \ - 'g', 'h', 'i', 'j', 'k', /* 10-19 */ \ - 'l', 'm', 'n', 'o', 'p', \ - 'q', 'r', 's', 't', 'u', /* 20-29 */ \ - 'v', 'w', 'x', 'y', 'z', \ - '1', '2', '3', '4', '5', /* 30-39 */ \ - '6', '7', '8', '9', '0', \ - KEY_ENTER, KEY_ESCAPE, KEY_BACKSPACE, KEY_TAB, ' ', /* 40-49 */ \ - KEY_MINUS, KEY_EQUALS, '[', ']', '\\', \ - 0, ';', '\'', '`', ',', /* 50-59 */ \ - '.', '/', KEY_CAPSLOCK, KEY_F1, KEY_F2, \ - KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* 60-69 */ \ - KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, \ - KEY_PRTSCR, KEY_SCRLCK, KEY_PAUSE, KEY_INS, KEY_HOME, /* 70-79 */ \ - KEY_PGUP, KEY_DEL, KEY_END, KEY_PGDN, KEY_RIGHTARROW, \ - KEY_LEFTARROW, KEY_DOWNARROW, KEY_UPARROW, /* 80-89 */ \ - KEY_NUMLOCK, KEYP_DIVIDE, \ - KEYP_MULTIPLY, KEYP_MINUS, KEYP_PLUS, KEYP_ENTER, KEYP_1, \ - KEYP_2, KEYP_3, KEYP_4, KEYP_5, KEYP_6, /* 90-99 */ \ - KEYP_7, KEYP_8, KEYP_9, KEYP_0, KEYP_PERIOD, \ - KEY_NONUSBACKSLASH, 0, 0, KEYP_EQUALS, /* 100-103 */ \ -} - -// Default names for keys, to use in English or as fallback. -#define KEY_NAMES_ARRAY { \ - { KEY_BACKSPACE, "BACKSP" }, { KEY_TAB, "TAB" }, \ - { KEY_INS, "INS" }, { KEY_DEL, "DEL" }, \ - { KEY_PGUP, "PGUP" }, { KEY_PGDN, "PGDN" }, \ - { KEY_ENTER, "ENTER" }, { KEY_ESCAPE, "ESC" }, \ - { KEY_F1, "F1" }, { KEY_F2, "F2" }, \ - { KEY_F3, "F3" }, { KEY_F4, "F4" }, \ - { KEY_F5, "F5" }, { KEY_F6, "F6" }, \ - { KEY_F7, "F7" }, { KEY_F8, "F8" }, \ - { KEY_F9, "F9" }, { KEY_F10, "F10" }, \ - { KEY_F11, "F11" }, { KEY_F12, "F12" }, \ - { KEY_HOME, "HOME" }, { KEY_END, "END" }, \ - { KEY_MINUS, "-" }, { KEY_EQUALS, "=" }, \ - { KEY_NUMLOCK, "NUMLCK" }, { KEY_SCRLCK, "SCRLCK" }, \ - { KEY_PAUSE, "PAUSE" }, { KEY_PRTSCR, "PRTSC" }, \ - { KEY_UPARROW, "UP" }, { KEY_DOWNARROW, "DOWN" }, \ - { KEY_LEFTARROW, "LEFT" }, { KEY_RIGHTARROW, "RIGHT" }, \ - { KEY_RALT, "ALT" }, { KEY_LALT, "ALT" }, \ - { KEY_RSHIFT, "SHIFT" }, { KEY_CAPSLOCK, "CAPS" }, \ - { KEY_RCTRL, "CTRL" }, { KEYP_5, "NUM5" }, \ - { ' ', "SPACE" }, \ - { 'a', "A" }, { 'b', "B" }, { 'c', "C" }, { 'd', "D" }, \ - { 'e', "E" }, { 'f', "F" }, { 'g', "G" }, { 'h', "H" }, \ - { 'i', "I" }, { 'j', "J" }, { 'k', "K" }, { 'l', "L" }, \ - { 'm', "M" }, { 'n', "N" }, { 'o', "O" }, { 'p', "P" }, \ - { 'q', "Q" }, { 'r', "R" }, { 's', "S" }, { 't', "T" }, \ - { 'u', "U" }, { 'v', "V" }, { 'w', "W" }, { 'x', "X" }, \ - { 'y', "Y" }, { 'z', "Z" }, { '0', "0" }, { '1', "1" }, \ - { '2', "2" }, { '3', "3" }, { '4', "4" }, { '5', "5" }, \ - { '6', "6" }, { '7', "7" }, { '8', "8" }, { '9', "9" }, \ - { '[', "[" }, { ']', "]" }, { ';', ";" }, { '`', "`" }, \ - { ',', "," }, { '.', "." }, { '/', "/" }, { '\\', "\\" }, \ - { '\'', "\'" }, \ -} - -#endif // __DOOMKEYS__ +#define SCANCODE_TO_KEYS_ARRAY \ + { \ + 0, \ + 0, \ + 0, \ + 0, \ + 'a', /* 0-9 */ \ + 'b', \ + 'c', \ + 'd', \ + 'e', \ + 'f', \ + 'g', \ + 'h', \ + 'i', \ + 'j', \ + 'k', /* 10-19 */ \ + 'l', \ + 'm', \ + 'n', \ + 'o', \ + 'p', \ + 'q', \ + 'r', \ + 's', \ + 't', \ + 'u', /* 20-29 */ \ + 'v', \ + 'w', \ + 'x', \ + 'y', \ + 'z', \ + '1', \ + '2', \ + '3', \ + '4', \ + '5', /* 30-39 */ \ + '6', \ + '7', \ + '8', \ + '9', \ + '0', \ + KEY_ENTER, \ + KEY_ESCAPE, \ + KEY_BACKSPACE, \ + KEY_TAB, \ + ' ', /* 40-49 */ \ + KEY_MINUS, \ + KEY_EQUALS, \ + '[', \ + ']', \ + '\\', \ + 0, \ + ';', \ + '\'', \ + '`', \ + ',', /* 50-59 */ \ + '.', \ + '/', \ + KEY_CAPSLOCK, \ + KEY_F1, \ + KEY_F2, \ + KEY_F3, \ + KEY_F4, \ + KEY_F5, \ + KEY_F6, \ + KEY_F7, /* 60-69 */ \ + KEY_F8, \ + KEY_F9, \ + KEY_F10, \ + KEY_F11, \ + KEY_F12, \ + KEY_PRTSCR, \ + KEY_SCRLCK, \ + KEY_PAUSE, \ + KEY_INS, \ + KEY_HOME, /* 70-79 */ \ + KEY_PGUP, \ + KEY_DEL, \ + KEY_END, \ + KEY_PGDN, \ + KEY_RIGHTARROW, \ + KEY_LEFTARROW, \ + KEY_DOWNARROW, \ + KEY_UPARROW, /* 80-89 */ \ + KEY_NUMLOCK, \ + KEYP_DIVIDE, \ + KEYP_MULTIPLY, \ + KEYP_MINUS, \ + KEYP_PLUS, \ + KEYP_ENTER, \ + KEYP_1, \ + KEYP_2, \ + KEYP_3, \ + KEYP_4, \ + KEYP_5, \ + KEYP_6, /* 90-99 */ \ + KEYP_7, \ + KEYP_8, \ + KEYP_9, \ + KEYP_0, \ + KEYP_PERIOD, \ + KEY_NONUSBACKSLASH, \ + 0, \ + 0, \ + KEYP_EQUALS, /* 100-103 */ \ + } + +/* Default names for keys, to use in English or as fallback. */ + +#define KEY_NAMES_ARRAY \ + { \ + {KEY_BACKSPACE, "BACKSP"}, \ + {KEY_TAB, "TAB"}, \ + {KEY_INS, "INS"}, \ + {KEY_DEL, "DEL"}, \ + {KEY_PGUP, "PGUP"}, \ + {KEY_PGDN, "PGDN"}, \ + {KEY_ENTER, "ENTER"}, \ + {KEY_ESCAPE, "ESC"}, \ + {KEY_F1, "F1"}, \ + {KEY_F2, "F2"}, \ + {KEY_F3, "F3"}, \ + {KEY_F4, "F4"}, \ + {KEY_F5, "F5"}, \ + {KEY_F6, "F6"}, \ + {KEY_F7, "F7"}, \ + {KEY_F8, "F8"}, \ + {KEY_F9, "F9"}, \ + {KEY_F10, "F10"}, \ + {KEY_F11, "F11"}, \ + {KEY_F12, "F12"}, \ + {KEY_HOME, "HOME"}, \ + {KEY_END, "END"}, \ + {KEY_MINUS, "-"}, \ + {KEY_EQUALS, "="}, \ + {KEY_NUMLOCK, "NUMLCK"}, \ + {KEY_SCRLCK, "SCRLCK"}, \ + {KEY_PAUSE, "PAUSE"}, \ + {KEY_PRTSCR, "PRTSC"}, \ + {KEY_UPARROW, "UP"}, \ + {KEY_DOWNARROW, "DOWN"}, \ + {KEY_LEFTARROW, "LEFT"}, \ + {KEY_RIGHTARROW, "RIGHT"}, \ + {KEY_RALT, "ALT"}, \ + {KEY_LALT, "ALT"}, \ + {KEY_RSHIFT, "SHIFT"}, \ + {KEY_CAPSLOCK, "CAPS"}, \ + {KEY_RCTRL, "CTRL"}, \ + {KEYP_5, "NUM5"}, \ + {' ', "SPACE"}, \ + {'a', "A"}, \ + {'b', "B"}, \ + {'c', "C"}, \ + {'d', "D"}, \ + {'e', "E"}, \ + {'f', "F"}, \ + {'g', "G"}, \ + {'h', "H"}, \ + {'i', "I"}, \ + {'j', "J"}, \ + {'k', "K"}, \ + {'l', "L"}, \ + {'m', "M"}, \ + {'n', "N"}, \ + {'o', "O"}, \ + {'p', "P"}, \ + {'q', "Q"}, \ + {'r', "R"}, \ + {'s', "S"}, \ + {'t', "T"}, \ + {'u', "U"}, \ + {'v', "V"}, \ + {'w', "W"}, \ + {'x', "X"}, \ + {'y', "Y"}, \ + {'z', "Z"}, \ + {'0', "0"}, \ + {'1', "1"}, \ + {'2', "2"}, \ + {'3', "3"}, \ + {'4', "4"}, \ + {'5', "5"}, \ + {'6', "6"}, \ + {'7', "7"}, \ + {'8', "8"}, \ + {'9', "9"}, \ + {'[', "["}, \ + {']', "]"}, \ + {';', ";"}, \ + {'`', "`"}, \ + {',', ","}, \ + {'.', "."}, \ + {'/', "/"}, \ + {'\\', "\\"}, \ + {'\'', "\'"}, \ + } +#endif /* __DOOMKEYS__ */ diff --git a/games/NXDoom/src/doomtype.h b/games/NXDoom/src/doomtype.h index d90cfec970b..2029723ad3f 100644 --- a/games/NXDoom/src/doomtype.h +++ b/games/NXDoom/src/doomtype.h @@ -1,69 +1,72 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Simple basic typedefs, isolated here to make it easier -// separating modules. -// - +/**************************************************************************** + * apps/games/NXDoom/src/doomtype.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Simple basic typedefs, isolated here to make it easier + * separating modules. + * + ****************************************************************************/ #ifndef __DOOMTYPE__ #define __DOOMTYPE__ -#include "config.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ -#if defined(_MSC_VER) && !defined(__cplusplus) -#define inline __inline -#endif +#include -// #define macros to provide functions missing in Windows. -// Outside Windows, we use strings.h for str[n]casecmp. +#include +/* What is really wanted here is stdint.h; however, some old versions + * of Solaris don't have stdint.h and only have inttypes.h (the + * pre-standardisation version). inttypes.h is also in the C99 + * standard and defined to include stdint.h, so include this. + */ -#if !HAVE_DECL_STRCASECMP || !HAVE_DECL_STRNCASECMP +#include +#include -#include -#if !HAVE_DECL_STRCASECMP -#define strcasecmp stricmp -#endif -#if !HAVE_DECL_STRNCASECMP -#define strncasecmp strnicmp -#endif +#include -#else +#include "config.h" -#include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#endif +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_S "/" +#define PATH_SEPARATOR ':' +#define arrlen(array) (sizeof(array) / sizeof(*array)) -// -// The packed attribute forces structures to be packed into the minimum -// space necessary. If this is not done, the compiler may align structure -// fields differently to optimize memory access, inflating the overall -// structure size. It is important to use the packed attribute on certain -// structures where alignment is important, particularly data read/written -// to disk. -// +/* The packed attribute forces structures to be packed into the minimum + * space necessary. If this is not done, the compiler may align structure + * fields differently to optimize memory access, inflating the overall + * structure size. It is important to use the packed attribute on certain + * structures where alignment is important, particularly data read/written + * to disk. + */ #ifdef __GNUC__ -#if defined(_WIN32) && !defined(__clang__) -#define PACKEDATTR __attribute__((packed,gcc_struct)) -#else #define PACKEDATTR __attribute__((packed)) -#endif #define PRINTF_ATTR(fmt, first) __attribute__((format(printf, fmt, first))) #define PRINTF_ARG_ATTR(x) __attribute__((format_arg(x))) @@ -78,43 +81,33 @@ #define PRINTF_ATTR(fmt, first) #define PRINTF_ARG_ATTR(x) #define NORETURN -#endif +#endif /* __GNUC__ */ -#ifdef __WATCOMC__ -#define PACKEDPREFIX _Packed -#elif defined(_MSC_VER) -#define PACKEDPREFIX __pragma(pack(push,1)) -#else #define PACKEDPREFIX -#endif - -#define PACKED_STRUCT(...) PACKEDPREFIX struct __VA_ARGS__ PACKEDATTR - -// C99 integer types; with gcc we just use this. Other compilers -// should add conditional statements that define the C99 types. -// What is really wanted here is stdint.h; however, some old versions -// of Solaris don't have stdint.h and only have inttypes.h (the -// pre-standardisation version). inttypes.h is also in the C99 -// standard and defined to include stdint.h, so include this. +/**************************************************************************** + * Public Types + ****************************************************************************/ -#include -#include +/* C99 integer types; with gcc we just use this. Other compilers + * should add conditional statements that define the C99 types. + */ #if defined(__cplusplus) || defined(__bool_true_false_are_defined) -// The C++/C99 bool type (or _Bool that is) can only have two values: -// 0 or 1. However, the Doom source code assumes any non-zero value -// to evaluate to true, so we have to use an int type here. +/* The C++/C99 bool type (or _Bool that is) can only have two values: + * 0 or 1. However, the Doom source code assumes any non-zero value + * to evaluate to true, so we have to use an int type here. + */ typedef int boolean; #else -typedef enum +typedef enum { - false, - true + false, + true } boolean; #endif @@ -123,23 +116,4 @@ typedef uint8_t byte; typedef uint8_t pixel_t; typedef int16_t dpixel_t; -#include - -#ifdef _WIN32 - -#define DIR_SEPARATOR '\\' -#define DIR_SEPARATOR_S "\\" -#define PATH_SEPARATOR ';' - -#else - -#define DIR_SEPARATOR '/' -#define DIR_SEPARATOR_S "/" -#define PATH_SEPARATOR ':' - -#endif - -#define arrlen(array) (sizeof(array) / sizeof(*array)) - -#endif - +#endif /* __DOOMTYPE__ */ diff --git a/games/NXDoom/src/gusconf.c b/games/NXDoom/src/gusconf.c index 5cd1d62a970..01f6606c5e0 100644 --- a/games/NXDoom/src/gusconf.c +++ b/games/NXDoom/src/gusconf.c @@ -1,301 +1,337 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// GUS emulation code. -// -// Actually emulating a GUS is far too much work; fortunately -// GUS "emulation" already exists in the form of Timidity, which -// supports GUS patch files. This code therefore converts Doom's -// DMXGUS lump into an equivalent Timidity configuration file. -// - +/**************************************************************************** + * apps/games/NXDoom/src/gusconf.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * GUS emulation code. + * + * Actually emulating a GUS is far too much work; fortunately + * GUS "emulation" already exists in the form of Timidity, which + * supports GUS patch files. This code therefore converts Doom's + * DMXGUS lump into an equivalent Timidity configuration file. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include #include "m_misc.h" #include "w_wad.h" #include "z_zone.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define MAX_INSTRUMENTS 256 +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef struct { - char *patch_names[MAX_INSTRUMENTS]; - int used[MAX_INSTRUMENTS]; - int mapping[MAX_INSTRUMENTS]; - unsigned int count; + char *patch_names[MAX_INSTRUMENTS]; + int used[MAX_INSTRUMENTS]; + int mapping[MAX_INSTRUMENTS]; + unsigned int count; } gus_config_t; +/**************************************************************************** + * Public Data + ****************************************************************************/ + char *gus_patch_path = ""; int gus_ram_kb = 1024; -static unsigned int MappingIndex(void) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static unsigned int mapping_index(void) { - unsigned int result = gus_ram_kb / 256; + unsigned int result = gus_ram_kb / 256; - if (result < 1) + if (result < 1) { - return 1; + return 1; } - else if (result > 4) + else if (result > 4) { - return 4; + return 4; } - else + else { - return result; + return result; } } -static int SplitLine(char *line, char **fields, unsigned int max_fields) +static int split_line(char *line, char **fields, unsigned int max_fields) { - unsigned int num_fields; - char *p; + unsigned int num_fields; + char *p; - fields[0] = line; - num_fields = 1; + fields[0] = line; + num_fields = 1; - for (p = line; *p != '\0'; ++p) + for (p = line; *p != '\0'; ++p) { - if (*p == ',') + if (*p == ',') { - *p = '\0'; + *p = '\0'; + + /* Skip spaces following the comma. */ - // Skip spaces following the comma. - do + do { - ++p; - } while (*p != '\0' && isspace(*p)); + ++p; + } + while (*p != '\0' && isspace(*p)); - fields[num_fields] = p; - ++num_fields; - --p; + fields[num_fields] = p; + ++num_fields; + --p; - if (num_fields >= max_fields) + if (num_fields >= max_fields) { - break; + break; } } - else if (*p == '#') + else if (*p == '#') { - *p = '\0'; - break; + *p = '\0'; + break; } } - // Strip off trailing whitespace from the end of the line. - p = fields[num_fields - 1] + strlen(fields[num_fields - 1]); - while (p > fields[num_fields - 1] && isspace(*(p - 1))) + /* Strip off trailing whitespace from the end of the line. */ + + p = fields[num_fields - 1] + strlen(fields[num_fields - 1]); + while (p > fields[num_fields - 1] && isspace(*(p - 1))) { - --p; - *p = '\0'; + --p; + *p = '\0'; } - return num_fields; + return num_fields; } -static void ParseLine(gus_config_t *config, char *line) +static void parse_line(gus_config_t *config, char *line) { - char *fields[6]; - unsigned int i; - unsigned int num_fields; - unsigned int instr_id, mapped_id; + char *fields[6]; + unsigned int i; + unsigned int num_fields; + unsigned int instr_id; + unsigned int mapped_id; - num_fields = SplitLine(line, fields, 6); + num_fields = split_line(line, fields, 6); - if (num_fields < 6) + if (num_fields < 6) { - return; + return; } - instr_id = atoi(fields[0]); + instr_id = atoi(fields[0]); - // Skip non GM percussions. - if ((instr_id >= 128 && instr_id < 128 + 35) || instr_id > 128 + 81) + /* Skip non GM percussions. */ + + if ((instr_id >= 128 && instr_id < 128 + 35) || instr_id > 128 + 81) { - return; + return; } - mapped_id = atoi(fields[MappingIndex()]); + mapped_id = atoi(fields[mapping_index()]); - for (i = 0; i < config->count; i++) + for (i = 0; i < config->count; i++) { - if (config->used[i] == mapped_id) + if (config->used[i] == mapped_id) { - break; + break; } } - - if (i == config->count) + + if (i == config->count) { - // DMX uses wrong patch name (we should use name of 'mapped_id' - // instrument, but DMX uses name of 'instr_id' instead). - free(config->patch_names[i]); - config->patch_names[i] = M_StringDuplicate(fields[5]); - config->used[i] = mapped_id; - config->count++; + /* DMX uses wrong patch name (we should use name of 'mapped_id' + * instrument, but DMX uses name of 'instr_id' instead). + */ + + free(config->patch_names[i]); + config->patch_names[i] = m_string_duplicate(fields[5]); + config->used[i] = mapped_id; + config->count++; } - config->mapping[instr_id] = i; + + config->mapping[instr_id] = i; } -static void ParseDMXConfig(char *dmxconf, gus_config_t *config) +static void parse_dmx_config(char *dmxconf, gus_config_t *config) { - char *p, *newline; - unsigned int i; + char *p; + char *newline; + unsigned int i; - memset(config, 0, sizeof(gus_config_t)); + memset(config, 0, sizeof(gus_config_t)); - for (i = 0; i < MAX_INSTRUMENTS; ++i) + for (i = 0; i < MAX_INSTRUMENTS; ++i) { - config->mapping[i] = -1; - config->used[i] = -1; + config->mapping[i] = -1; + config->used[i] = -1; } - config->count = 0; + config->count = 0; - p = dmxconf; + p = dmxconf; - for (;;) + for (; ; ) { - newline = strchr(p, '\n'); + newline = strchr(p, '\n'); - if (newline != NULL) + if (newline != NULL) { - *newline = '\0'; + *newline = '\0'; } - ParseLine(config, p); + parse_line(config, p); - if (newline == NULL) + if (newline == NULL) { - break; + break; } - else + else { - p = newline + 1; + p = newline + 1; } } } -static void FreeDMXConfig(gus_config_t *config) +static void free_dmx_config(gus_config_t *config) { - unsigned int i; + unsigned int i; - for (i = 0; i < MAX_INSTRUMENTS; ++i) + for (i = 0; i < MAX_INSTRUMENTS; ++i) { - free(config->patch_names[i]); + free(config->patch_names[i]); } } -static char *ReadDMXConfig(void) +static char *read_dmx_config(void) { - int lumpnum; - unsigned int len; - char *data; + int lumpnum; + unsigned int len; + char *data; - // TODO: This should be chosen based on gamemode == commercial: + /* TODO: This should be chosen based on gamemode == commercial: */ - lumpnum = W_CheckNumForName("DMXGUS"); + lumpnum = w_check_num_for_name("DMXGUS"); - if (lumpnum < 0) + if (lumpnum < 0) { - lumpnum = W_GetNumForName("DMXGUSC"); + lumpnum = w_get_num_for_name("DMXGUSC"); } - len = W_LumpLength(lumpnum); - data = Z_Malloc(len + 1, PU_STATIC, NULL); - W_ReadLump(lumpnum, data); + len = w_lump_length(lumpnum); + data = z_malloc(len + 1, PU_STATIC, NULL); + w_read_lump(lumpnum, data); - data[len] = '\0'; - return data; + data[len] = '\0'; + return data; } -static boolean WriteTimidityConfig(char *path, gus_config_t *config) +static boolean write_timidity_config(char *path, gus_config_t *config) { - FILE *fstream; - unsigned int i; + FILE *fstream; + unsigned int i; - fstream = M_fopen(path, "w"); + fstream = fopen(path, "w"); - if (fstream == NULL) + if (fstream == NULL) { - return false; + return false; } - fprintf(fstream, "# Autogenerated Timidity config.\n\n"); + fprintf(fstream, "# Autogenerated Timidity config.\n\n"); - fprintf(fstream, "dir \"%s\"\n", gus_patch_path); + fprintf(fstream, "dir \"%s\"\n", gus_patch_path); - fprintf(fstream, "\nbank 0\n\n"); + fprintf(fstream, "\nbank 0\n\n"); - for (i = 0; i < 128; ++i) + for (i = 0; i < 128; ++i) { - if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS - && config->patch_names[config->mapping[i]] != NULL) + if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS && + config->patch_names[config->mapping[i]] != NULL) { - fprintf(fstream, "%u %s\n", - i, config->patch_names[config->mapping[i]]); + fprintf(fstream, "%u %s\n", i, + config->patch_names[config->mapping[i]]); } } - fprintf(fstream, "\ndrumset 0\n\n"); - - for (i = 128 + 35; i <= 128 + 81; ++i) + fprintf(fstream, "\ndrumset 0\n\n"); + + for (i = 128 + 35; i <= 128 + 81; ++i) { - if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS - && config->patch_names[config->mapping[i]] != NULL) + if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS && + config->patch_names[config->mapping[i]] != NULL) { - fprintf(fstream, "%u %s\n", - i - 128, config->patch_names[config->mapping[i]]); + fprintf(fstream, "%u %s\n", i - 128, + config->patch_names[config->mapping[i]]); } } - fprintf(fstream, "\n"); + fprintf(fstream, "\n"); - fclose(fstream); + fclose(fstream); - return true; + return true; } -boolean GUS_WriteConfig(char *path) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +boolean gus_write_config(char *path) { - boolean result; - char *dmxconf; - gus_config_t config; + boolean result; + char *dmxconf; + gus_config_t config; - if (!strcmp(gus_patch_path, "")) + if (!strcmp(gus_patch_path, "")) { - printf("You haven't configured gus_patch_path.\n"); - printf("gus_patch_path needs to point to the location of " - "your GUS patch set.\n" - "To get a copy of the \"standard\" GUS patches, " - "download a copy of dgguspat.zip.\n"); + printf("You haven't configured gus_patch_path.\n"); + printf("gus_patch_path needs to point to the location of " + "your GUS patch set.\n" + "To get a copy of the \"standard\" GUS patches, " + "download a copy of dgguspat.zip.\n"); - return false; + return false; } - dmxconf = ReadDMXConfig(); - ParseDMXConfig(dmxconf, &config); + dmxconf = read_dmx_config(); + parse_dmx_config(dmxconf, &config); - result = WriteTimidityConfig(path, &config); + result = write_timidity_config(path, &config); - FreeDMXConfig(&config); - Z_Free(dmxconf); + free_dmx_config(&config); + z_free(dmxconf); - return result; + return result; } - diff --git a/games/NXDoom/src/gusconf.h b/games/NXDoom/src/gusconf.h index 4efbe99524b..aef259d5e15 100644 --- a/games/NXDoom/src/gusconf.h +++ b/games/NXDoom/src/gusconf.h @@ -1,29 +1,45 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// GUS emulation code. -// +/**************************************************************************** + * apps/games/NXDoom/src/gusconf.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * GUS emulation code. + * + ****************************************************************************/ #ifndef __GUSCONF_H__ #define __GUSCONF_H__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ + extern char *gus_patch_path; extern int gus_ram_kb; -boolean GUS_WriteConfig(char *path); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef __GUSCONF_H__ */ +boolean gus_write_config(char *path); +#endif /* __GUSCONF_H__ */ diff --git a/games/NXDoom/src/heretic-res.rc.in b/games/NXDoom/src/heretic-res.rc.in deleted file mode 100644 index 0cf43446d9e..00000000000 --- a/games/NXDoom/src/heretic-res.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -1 ICON "@top_srcdir@/data/heretic.ico" - -#include - -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" - -1 VERSIONINFO -PRODUCTVERSION @WINDOWS_RC_VERSION@ -FILEVERSION @WINDOWS_RC_VERSION@ -FILETYPE 1 -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "@PACKAGE_VERSION@.0" - VALUE "FileDescription", "@PACKAGE_STRING@" - VALUE "InternalName", "@PACKAGE_TARNAME@" - VALUE "CompanyName", "@PACKAGE_BUGREPORT@" - VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" - VALUE "ProductName", "@PACKAGE_NAME@" - VALUE "ProductVersion", "@PACKAGE_VERSION@" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - diff --git a/games/NXDoom/src/heretic/.gitignore b/games/NXDoom/src/heretic/.gitignore deleted file mode 100644 index 76092240c0b..00000000000 --- a/games/NXDoom/src/heretic/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -Makefile -Makefile.in -.deps -tags -TAGS - diff --git a/games/NXDoom/src/heretic/CMakeLists.txt b/games/NXDoom/src/heretic/CMakeLists.txt deleted file mode 100644 index ac6d2fbaf90..00000000000 --- a/games/NXDoom/src/heretic/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -add_library(heretic STATIC - am_data.h - am_map.c am_map.h - ct_chat.c ct_chat.h - deh_ammo.c - deh_frame.c - deh_htext.c - deh_htic.c deh_htic.h - deh_sound.c - deh_thing.c - deh_weapon.c - d_main.c - d_net.c - doomdata.h - doomdef.h - dstrings.h - f_finale.c - g_game.c - info.c info.h - in_lude.c - m_random.c m_random.h - mn_menu.c - p_action.h - p_ceilng.c - p_doors.c - p_enemy.c - p_floor.c - p_inter.c - p_lights.c - p_local.h - p_map.c - p_maputl.c - p_mobj.c - p_plats.c - p_pspr.c - p_saveg.c - p_setup.c - p_sight.c - p_spec.c p_spec.h - p_switch.c - p_telept.c - p_tick.c - p_user.c - r_bsp.c - r_data.c - r_draw.c - r_local.h - r_main.c - r_plane.c - r_segs.c - r_things.c - sb_bar.c - sounds.c sounds.h - s_sound.c s_sound.h) - -target_include_directories(heretic PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") - -if (DEFINED EMSCRIPTEN) - set(SDL_FLAGS "-s USE_SDL=2") - if(ENABLE_SDL2_MIXER) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") - endif() - if(ENABLE_SDL2_NET) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") - endif() -else() - set(SDL_LINK_LIBS SDL2::SDL2) - if(ENABLE_SDL2_MIXER) - list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) - endif() - if(ENABLE_SDL2_NET) - list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) - endif() -endif() -target_link_libraries(heretic textscreen ${SDL_LINK_LIBS}) -set_target_properties(heretic PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") -set_target_properties(heretic PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/heretic/Makefile.am b/games/NXDoom/src/heretic/Makefile.am deleted file mode 100644 index ac849d5e5fe..00000000000 --- a/games/NXDoom/src/heretic/Makefile.am +++ /dev/null @@ -1,72 +0,0 @@ - -AM_CFLAGS=-I$(top_srcdir)/src \ - -I$(top_srcdir)/textscreen \ - @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ - -EXTRA_DIST = \ - CMakeLists.txt \ - heretic_icon.c - -noinst_LIBRARIES=libheretic.a - -libheretic_a_SOURCES = \ - am_data.h \ -am_map.c am_map.h \ -ct_chat.c ct_chat.h \ -deh_ammo.c \ -deh_frame.c \ -deh_htext.c \ -deh_htic.c deh_htic.h \ -deh_sound.c \ -deh_thing.c \ -deh_weapon.c \ -d_main.c \ -d_net.c \ - doomdata.h \ - doomdef.h \ - dstrings.h \ -f_finale.c \ -g_game.c \ -info.c info.h \ -in_lude.c \ -m_random.c m_random.h \ -mn_menu.c \ - p_action.h \ -p_ceilng.c \ -p_doors.c \ -p_enemy.c \ -p_floor.c \ -p_inter.c \ -p_lights.c \ -p_local.h \ -p_map.c \ -p_maputl.c \ -p_mobj.c \ -p_plats.c \ -p_pspr.c \ -p_saveg.c \ -p_setup.c \ -p_sight.c \ -p_spec.c p_spec.h \ -p_switch.c \ -p_telept.c \ -p_tick.c \ -p_user.c \ -r_bsp.c \ -r_data.c \ -r_draw.c \ - r_local.h \ -r_main.c \ -r_plane.c \ -r_segs.c \ -r_things.c \ -sb_bar.c \ -sounds.c sounds.h \ -s_sound.c s_sound.h - -if HAVE_ICONS - -heretic_icon.c : $(top_builddir)/data/heretic.png - $(top_builddir)/data/convert-icon $(top_builddir)/data/heretic.png $@ - -endif diff --git a/games/NXDoom/src/heretic/am_data.h b/games/NXDoom/src/heretic/am_data.h deleted file mode 100644 index c5efb0894a9..00000000000 --- a/games/NXDoom/src/heretic/am_data.h +++ /dev/null @@ -1,103 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// AM_data.h : The vector graphics for the automap - -#ifndef __AMDATA_H__ -#define __AMDATA_H__ - -// a line drawing of the player pointing right, starting from the middle. - -#define R ((8*PLAYERRADIUS)/7) - -mline_t player_arrow[] = { - { { -R+R/4, 0 }, { 0, 0} }, // center line. - { { -R+R/4, R/8 }, { R, 0} }, // blade - { { -R+R/4, -R/8 }, { R, 0 } }, - { { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece - { { -R+R/8, -R/4 }, { -R+R/8, R/4 } }, - { { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors - { { -R+R/8, R/4 }, { -R+R/4, R/4} }, - { { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel - { { -R-R/4, R/8 }, { -R+R/8, R/8 } }, - { { -R-R/4, -R/8}, { -R+R/8, -R/8 } } - }; - -mline_t keysquare[] = { - { { 0, 0 }, { R/4, -R/2 } }, - { { R/4, -R/2 }, { R/2, -R/2 } }, - { { R/2, -R/2 }, { R/2, R/2 } }, - { { R/2, R/2 }, { R/4, R/2 } }, - { { R/4, R/2 }, { 0, 0 } }, // handle part type thing - { { 0, 0 }, { -R, 0 } }, // stem - { { -R, 0 }, { -R, -R/2 } }, // end lockpick part - { { -3*R/4, 0 }, { -3*R/4, -R/4 } } - }; - -/*mline_t player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/4 } }, // -----> - { { R, 0 }, { R-R/2, -R/4 } }, - { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> - { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> - { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } - }; -*/ -#undef R -#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) -#define NUMKEYSQUARELINES (sizeof(keysquare)/sizeof(mline_t)) - -#define R ((8*PLAYERRADIUS)/7) -mline_t cheat_player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/6 } }, // -----> - { { R, 0 }, { R-R/2, -R/6 } }, - { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> - { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> - { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, - { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> - { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, - { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, - { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> - { { -R/6, -R/6 }, { 0, -R/6 } }, - { { 0, -R/6 }, { 0, R/4 } }, - { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> - { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, - { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } - }; -#undef R -#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) - -#define R (FRACUNIT) -mline_t triangle_guy[] = { - { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } }, - { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } }, - { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } } - }; -#undef R -#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t)) - -#define R (FRACUNIT) -mline_t thintriangle_guy[] = { - { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, - { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, - { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } - }; -#undef R -#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) - -#endif diff --git a/games/NXDoom/src/heretic/am_map.c b/games/NXDoom/src/heretic/am_map.c deleted file mode 100644 index afc0c4222d1..00000000000 --- a/games/NXDoom/src/heretic/am_map.c +++ /dev/null @@ -1,1535 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// AM_map.c - -#include - -#include "doomdef.h" -#include "deh_str.h" -#include "i_timer.h" -#include "i_video.h" -#include "m_controls.h" -#include "p_local.h" -#include "am_map.h" -#include "am_data.h" - -#include "doomkeys.h" -#include "v_video.h" - -vertex_t KeyPoints[NUM_KEY_TYPES]; - -#define NUMALIAS 3 // Number of antialiased lines. - -const char *LevelNames[] = { - // EPISODE 1 - THE CITY OF THE DAMNED - "E1M1: THE DOCKS", - "E1M2: THE DUNGEONS", - "E1M3: THE GATEHOUSE", - "E1M4: THE GUARD TOWER", - "E1M5: THE CITADEL", - "E1M6: THE CATHEDRAL", - "E1M7: THE CRYPTS", - "E1M8: HELL'S MAW", - "E1M9: THE GRAVEYARD", - // EPISODE 2 - HELL'S MAW - "E2M1: THE CRATER", - "E2M2: THE LAVA PITS", - "E2M3: THE RIVER OF FIRE", - "E2M4: THE ICE GROTTO", - "E2M5: THE CATACOMBS", - "E2M6: THE LABYRINTH", - "E2M7: THE GREAT HALL", - "E2M8: THE PORTALS OF CHAOS", - "E2M9: THE GLACIER", - // EPISODE 3 - THE DOME OF D'SPARIL - "E3M1: THE STOREHOUSE", - "E3M2: THE CESSPOOL", - "E3M3: THE CONFLUENCE", - "E3M4: THE AZURE FORTRESS", - "E3M5: THE OPHIDIAN LAIR", - "E3M6: THE HALLS OF FEAR", - "E3M7: THE CHASM", - "E3M8: D'SPARIL'S KEEP", - "E3M9: THE AQUIFER", - // EPISODE 4: THE OSSUARY - "E4M1: CATAFALQUE", - "E4M2: BLOCKHOUSE", - "E4M3: AMBULATORY", - "E4M4: SEPULCHER", - "E4M5: GREAT STAIR", - "E4M6: HALLS OF THE APOSTATE", - "E4M7: RAMPARTS OF PERDITION", - "E4M8: SHATTERED BRIDGE", - "E4M9: MAUSOLEUM", - // EPISODE 5: THE STAGNANT DEMESNE - "E5M1: OCHRE CLIFFS", - "E5M2: RAPIDS", - "E5M3: QUAY", - "E5M4: COURTYARD", - "E5M5: HYDRATYR", - "E5M6: COLONNADE", - "E5M7: FOETID MANSE", - "E5M8: FIELD OF JUDGEMENT", - "E5M9: SKEIN OF D'SPARIL", - // EPISODE 6: unnamed - "E6M1: ", - "E6M2: ", - "E6M3: ", -}; - -static int cheating = 0; -static int grid = 0; - -boolean automapactive = false; -static int finit_width = SCREENWIDTH; -static int finit_height = SCREENHEIGHT - 42; -static int f_x, f_y; // location of window on screen -static int f_w, f_h; // size of window on screen -static int lightlev; // used for funky strobing effect -static byte *fb; // pseudo-frame buffer -static int amclock; - -static mpoint_t m_paninc; // how far the window pans each tic (map coords) -static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) -static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) - -static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) -static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) - -// width/height of window on map (map coords) -static fixed_t m_w, m_h; -static fixed_t min_x, min_y; // based on level size -static fixed_t max_x, max_y; // based on level size -static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y -static fixed_t min_w, min_h; // based on player size -static fixed_t min_scale_mtof; // used to tell when to stop zooming out -static fixed_t max_scale_mtof; // used to tell when to stop zooming in - -// old stuff for recovery later -static fixed_t old_m_w, old_m_h; -static fixed_t old_m_x, old_m_y; - -// old location used by the Follower routine -static mpoint_t f_oldloc; - -// used by MTOF to scale from map-to-frame-buffer coords -static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; -// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) -static fixed_t scale_ftom; - -static player_t *plr; // the player represented by an arrow -static vertex_t oldplr; - -//static patch_t *marknums[10]; // numbers used for marking by the automap -//static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are -//static int markpointnum = 0; // next point to be assigned - -static int followplayer = 1; // specifies whether to follow the player around - -static char cheat_amap[] = { 'r', 'a', 'v', 'm', 'a', 'p' }; - -static byte cheatcount = 0; - -static byte antialias[NUMALIAS][8] = { - {96, 97, 98, 99, 100, 101, 102, 103}, - {110, 109, 108, 107, 106, 105, 104, 103}, - {75, 76, 77, 78, 79, 80, 81, 103} -}; - -/* -static byte *aliasmax[NUMALIAS] = { - &antialias[0][7], &antialias[1][7], &antialias[2][7] -};*/ - -static byte *maplump; // pointer to the raw data for the automap background. -static short mapystart = 0; // y-value for the start of the map bitmap...used in the paralax stuff. -static short mapxstart = 0; //x-value for the bitmap. - -//byte screens[][SCREENWIDTH*SCREENHEIGHT]; -//void V_MarkRect (int x, int y, int width, int height); - -// Functions - -void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, - int NumLevels, unsigned short IntensityBits); - -// Calculates the slope and slope according to the x-axis of a line -// segment in map coordinates (with the upright y-axis n' all) so -// that it can be used with the brain-dead drawing stuff. - -// Ripped out for Heretic -/* -void AM_getIslope(mline_t *ml, islope_t *is) -{ - int dx, dy; - - dy = ml->a.y - ml->b.y; - dx = ml->b.x - ml->a.x; - if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); - else is->islp = FixedDiv(dx, dy); - if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); - else is->slp = FixedDiv(dy, dx); -} -*/ - -void AM_activateNewScale(void) -{ - m_x += m_w / 2; - m_y += m_h / 2; - m_w = FTOM(f_w); - m_h = FTOM(f_h); - m_x -= m_w / 2; - m_y -= m_h / 2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; -} - -void AM_saveScaleAndLoc(void) -{ - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; -} - -void AM_restoreScaleAndLoc(void) -{ - - m_w = old_m_w; - m_h = old_m_h; - if (!followplayer) - { - m_x = old_m_x; - m_y = old_m_y; - } - else - { - m_x = plr->mo->x - m_w / 2; - m_y = plr->mo->y - m_h / 2; - } - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - - // Change the scaling multipliers - scale_mtof = FixedDiv(f_w << FRACBITS, m_w); - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); -} - -// adds a marker at the current location - -/* -void AM_addMark(void) -{ - markpoints[markpointnum].x = m_x + m_w/2; - markpoints[markpointnum].y = m_y + m_h/2; - markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; - -} -*/ -void AM_findMinMaxBoundaries(void) -{ - int i; - fixed_t a, b; - - min_x = min_y = INT_MAX; - max_x = max_y = -INT_MAX; - for (i = 0; i < numvertexes; i++) - { - if (vertexes[i].x < min_x) - min_x = vertexes[i].x; - else if (vertexes[i].x > max_x) - max_x = vertexes[i].x; - if (vertexes[i].y < min_y) - min_y = vertexes[i].y; - else if (vertexes[i].y > max_y) - max_y = vertexes[i].y; - } - max_w = max_x - min_x; - max_h = max_y - min_y; - min_w = 2 * PLAYERRADIUS; - min_h = 2 * PLAYERRADIUS; - - a = FixedDiv(f_w << FRACBITS, max_w); - b = FixedDiv(f_h << FRACBITS, max_h); - min_scale_mtof = a < b ? a : b; - - max_scale_mtof = FixedDiv(f_h << FRACBITS, 2 * PLAYERRADIUS); - -} - -void AM_changeWindowLoc(void) -{ - if (m_paninc.x || m_paninc.y) - { - followplayer = 0; - f_oldloc.x = INT_MAX; - } - - m_x += m_paninc.x; - m_y += m_paninc.y; - - if (m_x + m_w / 2 > max_x) - { - m_x = max_x - m_w / 2; - m_paninc.x = 0; - } - else if (m_x + m_w / 2 < min_x) - { - m_x = min_x - m_w / 2; - m_paninc.x = 0; - } - if (m_y + m_h / 2 > max_y) - { - m_y = max_y - m_h / 2; - m_paninc.y = 0; - } - else if (m_y + m_h / 2 < min_y) - { - m_y = min_y - m_h / 2; - m_paninc.y = 0; - } - - // The following code was commented out in the released Heretic source, - // but I believe we need to do this here to stop the background moving - // when we reach the map boundaries. (In the released source it's done - // in AM_clearFB). - mapxstart += MTOF(m_paninc.x+FRACUNIT/2); - mapystart -= MTOF(m_paninc.y+FRACUNIT/2); - if(mapxstart >= finit_width) - mapxstart -= finit_width; - if(mapxstart < 0) - mapxstart += finit_width; - if(mapystart >= finit_height) - mapystart -= finit_height; - if(mapystart < 0) - mapystart += finit_height; - // - end of code that was commented-out - - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; -} - -void AM_initVariables(void) -{ - int pnum; - thinker_t *think; - mobj_t *mo; - - //static event_t st_notify = { ev_keyup, AM_MSGENTERED }; - - automapactive = true; - fb = I_VideoBuffer; - - f_oldloc.x = INT_MAX; - amclock = 0; - lightlev = 0; - - m_paninc.x = m_paninc.y = 0; - ftom_zoommul = FRACUNIT; - mtof_zoommul = FRACUNIT; - - m_w = FTOM(f_w); - m_h = FTOM(f_h); - - // find player to center on initially - if (!playeringame[pnum = consoleplayer]) - for (pnum = 0; pnum < MAXPLAYERS; pnum++) - if (playeringame[pnum]) - break; - plr = &players[pnum]; - oldplr.x = plr->mo->x; - oldplr.y = plr->mo->y; - m_x = plr->mo->x - m_w / 2; - m_y = plr->mo->y - m_h / 2; - AM_changeWindowLoc(); - - // for saving & restoring - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; - - // load in the location of keys, if in baby mode - - memset(KeyPoints, 0, sizeof(vertex_t) * 3); - if (gameskill == sk_baby) - { - for (think = thinkercap.next; think != &thinkercap; - think = think->next) - { - if (think->function != P_MobjThinker) - { //not a mobj - continue; - } - mo = (mobj_t *) think; - if (mo->type == MT_CKEY) - { - KeyPoints[0].x = mo->x; - KeyPoints[0].y = mo->y; - } - else if (mo->type == MT_AKYY) - { - KeyPoints[1].x = mo->x; - KeyPoints[1].y = mo->y; - } - else if (mo->type == MT_BKYY) - { - KeyPoints[2].x = mo->x; - KeyPoints[2].y = mo->y; - } - } - } - - // inform the status bar of the change -//c ST_Responder(&st_notify); -} - -void AM_loadPics(void) -{ - //int i; - //char namebuf[9]; -/* for (i=0;i<10;i++) - { - M_snprintf(namebuf, sizeof(namebuf), "AMMNUM%d", i); - marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); - }*/ - maplump = W_CacheLumpName(DEH_String("AUTOPAGE"), PU_STATIC); -} - -/*void AM_unloadPics(void) -{ - int i; - for (i=0;i<10;i++) Z_ChangeTag(marknums[i], PU_CACHE); - -}*/ - -/* -void AM_clearMarks(void) -{ - int i; - for (i=0;i max_scale_mtof) - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); -} - -static boolean stopped = true; - -void AM_Stop(void) -{ - //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; - -// AM_unloadPics(); - automapactive = false; -// ST_Responder(&st_notify); - stopped = true; - BorderNeedRefresh = true; -} - -void AM_Start(void) -{ - static int lastlevel = -1, lastepisode = -1; - - if (!stopped) - AM_Stop(); - stopped = false; - if (gamestate != GS_LEVEL) - { - return; // don't show automap if we aren't in a game! - } - if (lastlevel != gamemap || lastepisode != gameepisode) - { - AM_LevelInit(); - lastlevel = gamemap; - lastepisode = gameepisode; - } - AM_initVariables(); - AM_loadPics(); -} - -// set the window scale to the maximum size - -void AM_minOutWindowScale(void) -{ - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); -} - -// set the window scale to the minimum size - -void AM_maxOutWindowScale(void) -{ - scale_mtof = max_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); -} - -boolean AM_Responder(event_t * ev) -{ - int rc; - int key; - static int bigstate = 0; - static int joywait = 0; - - key = ev->data1; - rc = false; - - if (ev->type == ev_joystick && joybautomap >= 0 - && (ev->data1 & (1 << joybautomap)) != 0 && joywait < I_GetTime()) - { - joywait = I_GetTime() + 5; - - if (!automapactive) - { - AM_Start (); - viewactive = false; - } - else - { - bigstate = 0; - viewactive = true; - AM_Stop (); - } - } - - if (!automapactive) - { - - if (ev->type == ev_keydown && key == key_map_toggle - && gamestate == GS_LEVEL) - { - AM_Start(); - viewactive = false; - // viewactive = true; - rc = true; - } - } - else if (ev->type == ev_keydown) - { - rc = true; - - if (key == key_map_east) // pan right - { - if (!followplayer) - m_paninc.x = FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_west) // pan left - { - if (!followplayer) - m_paninc.x = -FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_north) // pan up - { - if (!followplayer) - m_paninc.y = FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_south) // pan down - { - if (!followplayer) - m_paninc.y = -FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_zoomout) // zoom out - { - mtof_zoommul = M_ZOOMOUT; - ftom_zoommul = M_ZOOMIN; - } - else if (key == key_map_zoomin) // zoom in - { - mtof_zoommul = M_ZOOMIN; - ftom_zoommul = M_ZOOMOUT; - } - else if (key == key_map_toggle) // toggle map (tab) - { - bigstate = 0; - viewactive = true; - AM_Stop(); - } - else if (key == key_map_maxzoom) - { - bigstate = !bigstate; - if (bigstate) - { - AM_saveScaleAndLoc(); - AM_minOutWindowScale(); - } - else - AM_restoreScaleAndLoc(); - } - else if (key == key_map_follow) - { - followplayer = !followplayer; - f_oldloc.x = INT_MAX; - P_SetMessage(plr, - followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, - true); - } - /* - else if (key == key_map_grid) - { - grid = !grid; - plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF; - } - else if (key == key_map_mark) - { - M_snprintf(buffer, sizeof(buffer), "%s %d", - AMSTR_MARKEDSPOT, markpointnum); - plr->message = buffer; - AM_addMark(); - } - else if (key == key_map_clearmark) - { - AM_clearMarks(); - plr->message = AMSTR_MARKSCLEARED; - } - */ - else - { - rc = false; - } - - if (cheat_amap[cheatcount] == ev->data1 && !netgame) - cheatcount++; - else - cheatcount = 0; - if (cheatcount == 6) - { - cheatcount = 0; - rc = false; - cheating = (cheating + 1) % 3; - } - } - - else if (ev->type == ev_keyup) - { - rc = false; - - if (key == key_map_east) - { - if (!followplayer) - m_paninc.x = 0; - } - else if (key == key_map_west) - { - if (!followplayer) - m_paninc.x = 0; - } - else if (key == key_map_north) - { - if (!followplayer) - m_paninc.y = 0; - } - else if (key == key_map_south) - { - if (!followplayer) - m_paninc.y = 0; - } - else if (key == key_map_zoomout || key == key_map_zoomin) - { - mtof_zoommul = FRACUNIT; - ftom_zoommul = FRACUNIT; - } - } - - return rc; - -} - -void AM_changeWindowScale(void) -{ - - // Change the scaling multipliers - scale_mtof = FixedMul(scale_mtof, mtof_zoommul); - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - - if (scale_mtof < min_scale_mtof) - AM_minOutWindowScale(); - else if (scale_mtof > max_scale_mtof) - AM_maxOutWindowScale(); - else - AM_activateNewScale(); -} - -void AM_doFollowPlayer(void) -{ - if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) - { -// m_x = FTOM(MTOF(plr->mo->x - m_w/2)); -// m_y = FTOM(MTOF(plr->mo->y - m_h/2)); -// m_x = plr->mo->x - m_w/2; -// m_y = plr->mo->y - m_h/2; - m_x = FTOM(MTOF(plr->mo->x)) - m_w / 2; - m_y = FTOM(MTOF(plr->mo->y)) - m_h / 2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - - // do the parallax parchment scrolling. -/* - dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point - dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y)); - - if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first - dmapx=0; //goes into the automap. - mapxstart += dmapx; - mapystart += dmapy; - - while(mapxstart >= finit_width) - mapxstart -= finit_width; - while(mapxstart < 0) - mapxstart += finit_width; - while(mapystart >= finit_height) - mapystart -= finit_height; - while(mapystart < 0) - mapystart += finit_height; -*/ - f_oldloc.x = plr->mo->x; - f_oldloc.y = plr->mo->y; - } -} - -// Ripped out for Heretic -/* -void AM_updateLightLev(void) -{ - static nexttic = 0; -//static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; - static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; - static int litelevelscnt = 0; - - // Change light level - if (amclock>nexttic) - { - lightlev = litelevels[litelevelscnt++]; - if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; - nexttic = amclock + 6 - (amclock % 6); - } -} -*/ - -void AM_Ticker(void) -{ - - if (!automapactive) - return; - - amclock++; - - if (followplayer) - AM_doFollowPlayer(); - - // Change the zoom if necessary - if (ftom_zoommul != FRACUNIT) - AM_changeWindowScale(); - - // Change x,y location - if (m_paninc.x || m_paninc.y) - AM_changeWindowLoc(); - // Update light level -// AM_updateLightLev(); - -} - -void AM_clearFB(int color) -{ - int i, j; - int dmapx; - int dmapy; - - if (followplayer) - { - dmapx = (MTOF(plr->mo->x) - MTOF(oldplr.x)); //fixed point - dmapy = (MTOF(oldplr.y) - MTOF(plr->mo->y)); - - oldplr.x = plr->mo->x; - oldplr.y = plr->mo->y; -// if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first -// dmapx=0; //goes into the automap. - mapxstart += dmapx >> 1; - mapystart += dmapy >> 1; - - while (mapxstart >= finit_width) - mapxstart -= finit_width; - while (mapxstart < 0) - mapxstart += finit_width; - while (mapystart >= finit_height) - mapystart -= finit_height; - while (mapystart < 0) - mapystart += finit_height; - } - else - { - // The released Heretic source does this here, but this causes a bug - // where the map background keeps moving when we reach the map - // boundaries. This is instead done in AM_changeWindowLoc. - /* - mapxstart += (MTOF(m_paninc.x) >> 1); - mapystart -= (MTOF(m_paninc.y) >> 1); - - if (mapxstart >= finit_width) - mapxstart -= finit_width; - if (mapxstart < 0) - mapxstart += finit_width; - if (mapystart >= finit_height) - mapystart -= finit_height; - if (mapystart < 0) - mapystart += finit_height; - */ - } - - //blit the automap background to the screen. - j = mapystart * finit_width; - for (i = 0; i < finit_height; i++) - { - memcpy(I_VideoBuffer + i * finit_width, maplump + j + mapxstart, - finit_width - mapxstart); - memcpy(I_VideoBuffer + i * finit_width + finit_width - mapxstart, - maplump + j, mapxstart); - j += finit_width; - if (j >= finit_height * finit_width) - j = 0; - } - -// memcpy(I_VideoBuffer, maplump, finit_width*finit_height); -// memset(fb, color, f_w*f_h); -} - -// Based on Cohen-Sutherland clipping algorithm but with a slightly -// faster reject and precalculated slopes. If I need the speed, will -// hash algorithm to the common cases. - -boolean AM_clipMline(mline_t * ml, fline_t * fl) -{ - enum - { LEFT = 1, RIGHT = 2, BOTTOM = 4, TOP = 8 }; - int outcode1 = 0, outcode2 = 0, outside; - fpoint_t tmp = { 0, 0 }; - int dx, dy; - -#define DOOUTCODE(oc, mx, my) \ - (oc) = 0; \ - if ((my) < 0) (oc) |= TOP; \ - else if ((my) >= f_h) (oc) |= BOTTOM; \ - if ((mx) < 0) (oc) |= LEFT; \ - else if ((mx) >= f_w) (oc) |= RIGHT - - // do trivial rejects and outcodes - if (ml->a.y > m_y2) - outcode1 = TOP; - else if (ml->a.y < m_y) - outcode1 = BOTTOM; - if (ml->b.y > m_y2) - outcode2 = TOP; - else if (ml->b.y < m_y) - outcode2 = BOTTOM; - if (outcode1 & outcode2) - return false; // trivially outside - - if (ml->a.x < m_x) - outcode1 |= LEFT; - else if (ml->a.x > m_x2) - outcode1 |= RIGHT; - if (ml->b.x < m_x) - outcode2 |= LEFT; - else if (ml->b.x > m_x2) - outcode2 |= RIGHT; - if (outcode1 & outcode2) - return false; // trivially outside - - // transform to frame-buffer coordinates. - fl->a.x = CXMTOF(ml->a.x); - fl->a.y = CYMTOF(ml->a.y); - fl->b.x = CXMTOF(ml->b.x); - fl->b.y = CYMTOF(ml->b.y); - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - if (outcode1 & outcode2) - return false; - - while (outcode1 | outcode2) - { - // may be partially inside box - // find an outside point - if (outcode1) - outside = outcode1; - else - outside = outcode2; - // clip to each side - if (outside & TOP) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx * (fl->a.y)) / dy; - tmp.y = 0; - } - else if (outside & BOTTOM) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx * (fl->a.y - f_h)) / dy; - tmp.y = f_h - 1; - } - else if (outside & RIGHT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy * (f_w - 1 - fl->a.x)) / dx; - tmp.x = f_w - 1; - } - else if (outside & LEFT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy * (-fl->a.x)) / dx; - tmp.x = 0; - } - if (outside == outcode1) - { - fl->a = tmp; - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - } - else - { - fl->b = tmp; - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - } - if (outcode1 & outcode2) - return false; // trivially outside - } - - return true; -} - -#undef DOOUTCODE - -// Classic Bresenham w/ whatever optimizations I need for speed - -void AM_drawFline(fline_t * fl, int color) -{ - - register int x, y, dx, dy, sx, sy, ax, ay, d; - static int fuck = 0; - - switch (color) - { - case WALLCOLORS: - DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[0][0], - 8, 3); - break; - case FDWALLCOLORS: - DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[1][0], - 8, 3); - break; - case CDWALLCOLORS: - DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[2][0], - 8, 3); - break; - default: - { - // For debugging only - if (fl->a.x < 0 || fl->a.x >= f_w - || fl->a.y < 0 || fl->a.y >= f_h - || fl->b.x < 0 || fl->b.x >= f_w - || fl->b.y < 0 || fl->b.y >= f_h) - { - fprintf(stderr, "fuck %d \r", fuck++); - return; - } - -#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO! - - dx = fl->b.x - fl->a.x; - ax = 2 * (dx < 0 ? -dx : dx); - sx = dx < 0 ? -1 : 1; - - dy = fl->b.y - fl->a.y; - ay = 2 * (dy < 0 ? -dy : dy); - sy = dy < 0 ? -1 : 1; - - x = fl->a.x; - y = fl->a.y; - - if (ax > ay) - { - d = ay - ax / 2; - while (1) - { - DOT(x, y, color); - if (x == fl->b.x) - return; - if (d >= 0) - { - y += sy; - d -= ax; - } - x += sx; - d += ay; - } - } - else - { - d = ax - ay / 2; - while (1) - { - DOT(x, y, color); - if (y == fl->b.y) - return; - if (d >= 0) - { - x += sx; - d -= ay; - } - y += sy; - d += ax; - } - } - } - } -} - -/* Wu antialiased line drawer. - * (X0,Y0),(X1,Y1) = line to draw - * BaseColor = color # of first color in block used for antialiasing, the - * 100% intensity version of the drawing color - * NumLevels = size of color block, with BaseColor+NumLevels-1 being the - * 0% intensity version of the drawing color - * IntensityBits = log base 2 of NumLevels; the # of bits used to describe - * the intensity of the drawing color. 2**IntensityBits==NumLevels - */ -void PUTDOT(short xx, short yy, byte * cc, byte * cm) -{ - static int oldyy; - static int oldyyshifted; - byte *oldcc = cc; - - if (xx < 32) - cc += 7 - (xx >> 2); - else if (xx > (finit_width - 32)) - cc += 7 - ((finit_width - xx) >> 2); -// if(cc==oldcc) //make sure that we don't double fade the corners. -// { - if (yy < 32) - cc += 7 - (yy >> 2); - else if (yy > (finit_height - 32)) - cc += 7 - ((finit_height - yy) >> 2); -// } - if (cc > cm && cm != NULL) - { - cc = cm; - } - else if (cc > oldcc + 6) // don't let the color escape from the fade table... - { - cc = oldcc + 6; - } - if (yy == oldyy + 1) - { - oldyy++; - oldyyshifted += 320; - } - else if (yy == oldyy - 1) - { - oldyy--; - oldyyshifted -= 320; - } - else if (yy != oldyy) - { - oldyy = yy; - oldyyshifted = yy * 320; - } - fb[oldyyshifted + xx] = *(cc); -// fb[(yy)*f_w+(xx)]=*(cc); -} - -void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, - int NumLevels, unsigned short IntensityBits) -{ - unsigned short IntensityShift, ErrorAdj, ErrorAcc; - unsigned short ErrorAccTemp, Weighting, WeightingComplementMask; - short DeltaX, DeltaY, Temp, XDir; - - /* Make sure the line runs top to bottom */ - if (Y0 > Y1) - { - Temp = Y0; - Y0 = Y1; - Y1 = Temp; - Temp = X0; - X0 = X1; - X1 = Temp; - } - /* Draw the initial pixel, which is always exactly intersected by - the line and so needs no weighting */ - PUTDOT(X0, Y0, &BaseColor[0], NULL); - - if ((DeltaX = X1 - X0) >= 0) - { - XDir = 1; - } - else - { - XDir = -1; - DeltaX = -DeltaX; /* make DeltaX positive */ - } - /* Special-case horizontal, vertical, and diagonal lines, which - require no weighting because they go right through the center of - every pixel */ - if ((DeltaY = Y1 - Y0) == 0) - { - /* Horizontal line */ - while (DeltaX-- != 0) - { - X0 += XDir; - PUTDOT(X0, Y0, &BaseColor[0], NULL); - } - return; - } - if (DeltaX == 0) - { - /* Vertical line */ - do - { - Y0++; - PUTDOT(X0, Y0, &BaseColor[0], NULL); - } - while (--DeltaY != 0); - return; - } - //diagonal line. - if (DeltaX == DeltaY) - { - do - { - X0 += XDir; - Y0++; - PUTDOT(X0, Y0, &BaseColor[0], NULL); - } - while (--DeltaY != 0); - return; - } - /* Line is not horizontal, diagonal, or vertical */ - ErrorAcc = 0; /* initialize the line error accumulator to 0 */ - /* # of bits by which to shift ErrorAcc to get intensity level */ - IntensityShift = 16 - IntensityBits; - /* Mask used to flip all bits in an intensity weighting, producing the - result (1 - intensity weighting) */ - WeightingComplementMask = NumLevels - 1; - /* Is this an X-major or Y-major line? */ - if (DeltaY > DeltaX) - { - /* Y-major line; calculate 16-bit fixed-point fractional part of a - pixel that X advances each time Y advances 1 pixel, truncating the - result so that we won't overrun the endpoint along the X axis */ - ErrorAdj = ((unsigned int) DeltaX << 16) / (unsigned int) DeltaY; - /* Draw all pixels other than the first and last */ - while (--DeltaY) - { - ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ - ErrorAcc += ErrorAdj; /* calculate error for next pixel */ - if (ErrorAcc <= ErrorAccTemp) - { - /* The error accumulator turned over, so advance the X coord */ - X0 += XDir; - } - Y0++; /* Y-major, so always advance Y */ - /* The IntensityBits most significant bits of ErrorAcc give us the - intensity weighting for this pixel, and the complement of the - weighting for the paired pixel */ - Weighting = ErrorAcc >> IntensityShift; - PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); - PUTDOT(X0 + XDir, Y0, - &BaseColor[(Weighting ^ WeightingComplementMask)], - &BaseColor[7]); - } - /* Draw the final pixel, which is always exactly intersected by the line - and so needs no weighting */ - PUTDOT(X1, Y1, &BaseColor[0], NULL); - return; - } - /* It's an X-major line; calculate 16-bit fixed-point fractional part of a - pixel that Y advances each time X advances 1 pixel, truncating the - result to avoid overrunning the endpoint along the X axis */ - ErrorAdj = ((unsigned int) DeltaY << 16) / (unsigned int) DeltaX; - /* Draw all pixels other than the first and last */ - while (--DeltaX) - { - ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ - ErrorAcc += ErrorAdj; /* calculate error for next pixel */ - if (ErrorAcc <= ErrorAccTemp) - { - /* The error accumulator turned over, so advance the Y coord */ - Y0++; - } - X0 += XDir; /* X-major, so always advance X */ - /* The IntensityBits most significant bits of ErrorAcc give us the - intensity weighting for this pixel, and the complement of the - weighting for the paired pixel */ - Weighting = ErrorAcc >> IntensityShift; - PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); - PUTDOT(X0, Y0 + 1, - &BaseColor[(Weighting ^ WeightingComplementMask)], - &BaseColor[7]); - - } - /* Draw the final pixel, which is always exactly intersected by the line - and so needs no weighting */ - PUTDOT(X1, Y1, &BaseColor[0], NULL); -} - -void AM_drawMline(mline_t * ml, int color) -{ - static fline_t fl; - - if (AM_clipMline(ml, &fl)) - AM_drawFline(&fl, color); // draws it on frame buffer using fb coords - -} - -void AM_drawGrid(int color) -{ - fixed_t x, y; - fixed_t start, end; - mline_t ml; - - // Figure out start of vertical gridlines - start = m_x; - if ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)) - start += (MAPBLOCKUNITS << FRACBITS) - - ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)); - end = m_x + m_w; - - // draw vertical gridlines - ml.a.y = m_y; - ml.b.y = m_y + m_h; - for (x = start; x < end; x += (MAPBLOCKUNITS << FRACBITS)) - { - ml.a.x = x; - ml.b.x = x; - AM_drawMline(&ml, color); - } - - // Figure out start of horizontal gridlines - start = m_y; - if ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)) - start += (MAPBLOCKUNITS << FRACBITS) - - ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)); - end = m_y + m_h; - - // draw horizontal gridlines - ml.a.x = m_x; - ml.b.x = m_x + m_w; - for (y = start; y < end; y += (MAPBLOCKUNITS << FRACBITS)) - { - ml.a.y = y; - ml.b.y = y; - AM_drawMline(&ml, color); - } -} - -void AM_drawWalls(void) -{ - int i; - static mline_t l; - - for (i = 0; i < numlines; i++) - { - l.a.x = lines[i].v1->x; - l.a.y = lines[i].v1->y; - l.b.x = lines[i].v2->x; - l.b.y = lines[i].v2->y; - if (cheating || (lines[i].flags & ML_MAPPED)) - { - if ((lines[i].flags & LINE_NEVERSEE) && !cheating) - continue; - if (!lines[i].backsector) - { - AM_drawMline(&l, WALLCOLORS + lightlev); - } - else - { - if (lines[i].special == 39) - { // teleporters - AM_drawMline(&l, WALLCOLORS + WALLRANGE / 2); - } - else if (lines[i].flags & ML_SECRET) // secret door - { - if (cheating) - AM_drawMline(&l, 0); - else - AM_drawMline(&l, WALLCOLORS + lightlev); - } - else if (lines[i].special > 25 && lines[i].special < 35) - { - switch (lines[i].special) - { - case 26: - case 32: - AM_drawMline(&l, BLUEKEY); - break; - case 27: - case 34: - AM_drawMline(&l, YELLOWKEY); - break; - case 28: - case 33: - AM_drawMline(&l, GREENKEY); - break; - default: - break; - } - } - else if (lines[i].backsector->floorheight - != lines[i].frontsector->floorheight) - { - AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change - } - else if (lines[i].backsector->ceilingheight - != lines[i].frontsector->ceilingheight) - { - AM_drawMline(&l, CDWALLCOLORS + lightlev); // ceiling level change - } - else if (cheating) - { - AM_drawMline(&l, TSWALLCOLORS + lightlev); - } - } - } - else if (plr->powers[pw_allmap]) - { - if (!(lines[i].flags & LINE_NEVERSEE)) - AM_drawMline(&l, GRAYS + 3); - } - } - -} - -void AM_rotate(fixed_t * x, fixed_t * y, angle_t a) -{ - fixed_t tmpx; - - tmpx = FixedMul(*x, finecosine[a >> ANGLETOFINESHIFT]) - - FixedMul(*y, finesine[a >> ANGLETOFINESHIFT]); - *y = FixedMul(*x, finesine[a >> ANGLETOFINESHIFT]) - + FixedMul(*y, finecosine[a >> ANGLETOFINESHIFT]); - *x = tmpx; -} - -void AM_drawLineCharacter(mline_t * lineguy, int lineguylines, fixed_t scale, - angle_t angle, int color, fixed_t x, fixed_t y) -{ - int i; - mline_t l; - - for (i = 0; i < lineguylines; i++) - { - l.a.x = lineguy[i].a.x; - l.a.y = lineguy[i].a.y; - if (scale) - { - l.a.x = FixedMul(scale, l.a.x); - l.a.y = FixedMul(scale, l.a.y); - } - if (angle) - AM_rotate(&l.a.x, &l.a.y, angle); - l.a.x += x; - l.a.y += y; - - l.b.x = lineguy[i].b.x; - l.b.y = lineguy[i].b.y; - if (scale) - { - l.b.x = FixedMul(scale, l.b.x); - l.b.y = FixedMul(scale, l.b.y); - } - if (angle) - AM_rotate(&l.b.x, &l.b.y, angle); - l.b.x += x; - l.b.y += y; - - AM_drawMline(&l, color); - } - -} - -void AM_drawPlayers(void) -{ - - int i; - player_t *p; - static int their_colors[] = { GREENKEY, YELLOWKEY, BLOODRED, BLUEKEY }; - int their_color = -1; - int color; - - if (!netgame) - { - /* - if (cheating) AM_drawLineCharacter(cheat_player_arrow, NUMCHEATPLYRLINES, 0, - plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); - *///cheat key player pointer is the same as non-cheat pointer.. - - AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, - WHITE, plr->mo->x, plr->mo->y); - return; - } - - for (i = 0; i < MAXPLAYERS; i++) - { - their_color++; - p = &players[i]; - if (deathmatch && !singledemo && p != plr) - { - continue; - } - if (!playeringame[i]) - continue; - if (p->powers[pw_invisibility]) - color = 102; // *close* to the automap color - else - color = their_colors[their_color]; - AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, - color, p->mo->x, p->mo->y); - } -} - -void AM_drawThings(int colors, int colorrange) -{ - int i; - mobj_t *t; - - for (i = 0; i < numsectors; i++) - { - t = sectors[i].thinglist; - while (t) - { - AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, - 16 << FRACBITS, t->angle, colors + lightlev, - t->x, t->y); - t = t->snext; - } - } -} - -/* -void AM_drawMarks(void) -{ - int i, fx, fy, w, h; - - for (i=0;iwidth); - h = SHORT(marknums[i]->height); - fx = CXMTOF(markpoints[i].x); - fy = CYMTOF(markpoints[i].y); - if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) - V_DrawPatch(fx, fy, marknums[i]); - } - } -} -*/ - -void AM_drawkeys(void) -{ - if (KeyPoints[0].x != 0 || KeyPoints[0].y != 0) - { - AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY, - KeyPoints[0].x, KeyPoints[0].y); - } - if (KeyPoints[1].x != 0 || KeyPoints[1].y != 0) - { - AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY, - KeyPoints[1].x, KeyPoints[1].y); - } - if (KeyPoints[2].x != 0 || KeyPoints[2].y != 0) - { - AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY, - KeyPoints[2].x, KeyPoints[2].y); - } -} - -void AM_drawCrosshair(int color) -{ - fb[(f_w * (f_h + 1)) / 2] = color; // single point for now -} - -void AM_Drawer(void) -{ - const char *level_name; - int numepisodes; - - if (!automapactive) - return; - - UpdateState |= I_FULLSCRN; - AM_clearFB(BACKGROUND); - if (grid) - AM_drawGrid(GRIDCOLORS); - AM_drawWalls(); - AM_drawPlayers(); - if (cheating == 2) - AM_drawThings(THINGCOLORS, THINGRANGE); -// AM_drawCrosshair(XHAIRCOLORS); - -// AM_drawMarks(); - if (gameskill == sk_baby) - { - AM_drawkeys(); - } - - if (gamemode == retail) - { - numepisodes = 5; - } - else - { - numepisodes = 3; - } - - if (gameepisode <= numepisodes && gamemap < 10) - { - level_name = LevelNames[(gameepisode - 1) * 9 + gamemap - 1]; - MN_DrTextA(DEH_String(level_name), 20, 145); - } -// I_Update(); -// V_MarkRect(f_x, f_y, f_w, f_h); -} diff --git a/games/NXDoom/src/heretic/am_map.h b/games/NXDoom/src/heretic/am_map.h deleted file mode 100644 index aa535cc3007..00000000000 --- a/games/NXDoom/src/heretic/am_map.h +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -#ifndef __AMMAP_H__ -#define __AMMAP_H__ - - -#include "r_local.h" - - -// For use if I do walls with outsides/insides -#define REDS 12*8 -#define REDRANGE 1 //16 -#define BLUES (256-4*16+8) -#define BLUERANGE 1 //8 -#define GREENS (33*8) -#define GREENRANGE 1 //16 -#define GRAYS (5*8) -#define GRAYSRANGE 1 //16 -#define BROWNS (14*8) -#define BROWNRANGE 1 //16 -#define YELLOWS 10*8 -#define YELLOWRANGE 1 -#define BLACK 0 -#define WHITE 4*8 -#define PARCH 13*8-1 -#define BLOODRED 150 -#define BLUEKEY 197 -#define YELLOWKEY 144 -#define GREENKEY 220 - -// Automap colors -#define BACKGROUND PARCH -#define YOURCOLORS WHITE -#define YOURRANGE 0 -#define WALLCOLORS REDS -#define WALLRANGE REDRANGE -#define TSWALLCOLORS GRAYS -#define TSWALLRANGE GRAYSRANGE -#define FDWALLCOLORS BROWNS -#define FDWALLRANGE BROWNRANGE -#define CDWALLCOLORS YELLOWS -#define CDWALLRANGE YELLOWRANGE -#define THINGCOLORS GREENS -#define THINGRANGE GREENRANGE -#define SECRETWALLCOLORS WALLCOLORS -#define SECRETWALLRANGE WALLRANGE -#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) -#define GRIDRANGE 0 -#define XHAIRCOLORS GRAYS - -// drawing stuff -#define FB 0 - -#define AM_NUMMARKPOINTS 10 - -#define AM_MSGHEADER (('a'<<24)+('m'<<16)) -#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) -#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) - -#define INITSCALEMTOF (.2*FRACUNIT) // scale on entry -// how much the automap moves window per tic in frame-buffer coordinates -#define F_PANINC 4 // moves 140 pixels in 1 second -// how much zoom-in per tic -#define M_ZOOMIN ((int) (1.02*FRACUNIT)) // goes to 2x in 1 second -// how much zoom-out per tic -#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) // pulls out to 0.5x in 1 second - -// translates between frame-buffer and map distances -#define FTOM(x) FixedMul(((x)<<16),scale_ftom) -#define MTOF(x) (FixedMul((x),scale_mtof)>>16) -// translates between frame-buffer and map coordinates -#define CXMTOF(x) (f_x + MTOF((x)-m_x)) -#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) - -// the following is crap -#define LINE_NEVERSEE ML_DONTDRAW - -typedef struct -{ - int x, y; -} fpoint_t; - -typedef struct -{ - fpoint_t a, b; -} fline_t; - -typedef vertex_t mpoint_t; - -typedef struct -{ - mpoint_t a, b; -} mline_t; - -typedef struct -{ - fixed_t slp, islp; -} islope_t; - -// extern int f_x, f_y, f_w, f_h; - - -extern boolean automapactive; -extern vertex_t KeyPoints[]; -extern const char *LevelNames[]; - - -void AM_Stop(void); - - -#endif diff --git a/games/NXDoom/src/heretic/ct_chat.c b/games/NXDoom/src/heretic/ct_chat.c deleted file mode 100644 index f0f8e5ff6bf..00000000000 --- a/games/NXDoom/src/heretic/ct_chat.c +++ /dev/null @@ -1,477 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Chat mode -// - -#include -#include - -#include "doomdef.h" -#include "doomkeys.h" - -#include "deh_str.h" -#include "i_input.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -#define QUEUESIZE 128 -#define MESSAGESIZE 128 -#define MESSAGELEN 265 - -#define CT_PLR_GREEN 1 -#define CT_PLR_YELLOW 2 -#define CT_PLR_RED 3 -#define CT_PLR_BLUE 4 -#define CT_PLR_ALL 5 - -#define CT_ESCAPE 6 - -// Public data - - -boolean chatmodeon; - -// Private data - -void CT_queueChatChar(char ch); -void CT_ClearChatMessage(int player); -void CT_AddChar(int player, char c); -void CT_BackSpace(int player); - -int head; -int tail; -byte ChatQueue[QUEUESIZE]; -int chat_dest[MAXPLAYERS]; -char chat_msg[MAXPLAYERS][MESSAGESIZE]; -char plr_lastmsg[MAXPLAYERS][MESSAGESIZE + 9]; // add in the length of the pre-string -int msgptr[MAXPLAYERS]; -int msglen[MAXPLAYERS]; - -boolean cheated; - -static int FontABaseLump; - -const char *CT_FromPlrText[MAXPLAYERS] = { - "GREEN: ", - "YELLOW: ", - "RED: ", - "BLUE: " -}; - -char *chat_macros[10]; - -boolean altdown; -boolean shiftdown; - - -//=========================================================================== -// -// CT_Init -// -// Initialize chat mode data -//=========================================================================== - -void CT_Init(void) -{ - int i; - - head = 0; //initialize the queue index - tail = 0; - chatmodeon = false; - memset(ChatQueue, 0, QUEUESIZE); - for (i = 0; i < MAXPLAYERS; i++) - { - chat_dest[i] = 0; - msgptr[i] = 0; - memset(plr_lastmsg[i], 0, MESSAGESIZE); - memset(chat_msg[i], 0, MESSAGESIZE); - } - FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; - return; -} - -//=========================================================================== -// -// CT_Stop -// -//=========================================================================== - -void CT_Stop(void) -{ - chatmodeon = false; - I_StopTextInput(); - return; -} - -// These keys are allowed by Vanilla Heretic: - -static boolean ValidChatChar(char c) -{ - return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '!' || c == '?' - || c == ' ' || c == '\'' - || c == ',' || c == '.' - || c == '-' || c == '='; -} - -//=========================================================================== -// -// CT_Responder -// -//=========================================================================== - -boolean CT_Responder(event_t * ev) -{ - char *macro; - - int sendto; - - if (!netgame) - { - return false; - } - if (ev->data1 == KEY_LALT || ev->data2 == KEY_RALT) - { - altdown = (ev->type == ev_keydown); - return false; - } - if (ev->data1 == KEY_RSHIFT) - { - shiftdown = (ev->type == ev_keydown); - return false; - } - if (ev->type != ev_keydown) - { - return false; - } - if (!chatmodeon) - { - sendto = 0; - if (ev->data1 == key_multi_msg) - { - sendto = CT_PLR_ALL; - } - else if (ev->data1 == key_multi_msgplayer[0]) - { - sendto = CT_PLR_GREEN; - } - else if (ev->data1 == key_multi_msgplayer[1]) - { - sendto = CT_PLR_YELLOW; - } - else if (ev->data1 == key_multi_msgplayer[2]) - { - sendto = CT_PLR_RED; - } - else if (ev->data1 == key_multi_msgplayer[3]) - { - sendto = CT_PLR_BLUE; - } - if (sendto == 0 || (sendto != CT_PLR_ALL && !playeringame[sendto - 1]) - || sendto == consoleplayer + 1) - { - return false; - } - CT_queueChatChar(sendto); - chatmodeon = true; - I_StartTextInput(25, 10, SCREENWIDTH, 18); - return true; - } - else - { - if (altdown) - { - if (ev->data1 >= '0' && ev->data1 <= '9') - { - if (ev->data1 == '0') - { // macro 0 comes after macro 9 - ev->data1 = '9' + 1; - } - macro = chat_macros[ev->data1 - '1']; - CT_queueChatChar(KEY_ENTER); //send old message - CT_queueChatChar(chat_dest[consoleplayer]); // chose the dest. - while (*macro) - { - CT_queueChatChar(toupper(*macro++)); - } - CT_queueChatChar(KEY_ENTER); //send it off... - CT_Stop(); - return true; - } - } - if (ev->data1 == KEY_ENTER) - { - CT_queueChatChar(KEY_ENTER); - CT_Stop(); - return true; - } - else if (ev->data1 == KEY_ESCAPE) - { - CT_queueChatChar(CT_ESCAPE); - CT_Stop(); - return true; - } - else if (ev->data1 == KEY_BACKSPACE) - { - CT_queueChatChar(KEY_BACKSPACE); - return true; - } - else if (ValidChatChar(ev->data3)) - { - CT_queueChatChar(toupper(ev->data3)); - return true; - } - } - return false; -} - -//=========================================================================== -// -// CT_Ticker -// -//=========================================================================== - -void CT_Ticker(void) -{ - int i; - int j; - char c; - int numplayers; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - { - continue; - } - if ((c = players[i].cmd.chatchar) != 0) - { - if (c <= 5) - { - chat_dest[i] = c; - continue; - } - else if (c == CT_ESCAPE) - { - CT_ClearChatMessage(i); - } - else if (c == KEY_ENTER) - { - numplayers = 0; - for (j = 0; j < MAXPLAYERS; j++) - { - numplayers += playeringame[j]; - } - CT_AddChar(i, 0); // set the end of message character - if (numplayers > 2) - { - M_StringCopy(plr_lastmsg[i], DEH_String(CT_FromPlrText[i]), - sizeof(plr_lastmsg[i])); - M_StringConcat(plr_lastmsg[i], chat_msg[i], - sizeof(plr_lastmsg[i])); - } - else - { - M_StringCopy(plr_lastmsg[i], chat_msg[i], - sizeof(plr_lastmsg[i])); - } - if (i != consoleplayer && (chat_dest[i] == consoleplayer + 1 - || chat_dest[i] == CT_PLR_ALL) - && *chat_msg[i]) - { - P_SetMessage(&players[consoleplayer], plr_lastmsg[i], - true); - S_StartSound(NULL, sfx_chat); - } - else if (i == consoleplayer && (*chat_msg[i])) - { - if (numplayers > 1) - { - P_SetMessage(&players[consoleplayer], - DEH_String("-MESSAGE SENT-"), true); - S_StartSound(NULL, sfx_chat); - } - else - { - P_SetMessage(&players[consoleplayer], - DEH_String("THERE ARE NO OTHER PLAYERS IN THE GAME!"), - true); - S_StartSound(NULL, sfx_chat); - } - } - CT_ClearChatMessage(i); - } - else if (c == KEY_BACKSPACE) - { - CT_BackSpace(i); - } - else - { - CT_AddChar(i, c); - } - } - } - return; -} - -//=========================================================================== -// -// CT_Drawer -// -//=========================================================================== - -void CT_Drawer(void) -{ - int i; - int x; - patch_t *patch; - - if (chatmodeon) - { - x = 25; - for (i = 0; i < msgptr[consoleplayer]; i++) - { - if (chat_msg[consoleplayer][i] < 33) - { - x += 6; - } - else - { - patch = W_CacheLumpNum(FontABaseLump + - chat_msg[consoleplayer][i] - 33, - PU_CACHE); - V_DrawPatch(x, 10, patch); - x += patch->width; - } - } - V_DrawPatch(x, 10, W_CacheLumpName(DEH_String("FONTA59"), PU_CACHE)); - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } -} - -//=========================================================================== -// -// CT_queueChatChar -// -//=========================================================================== - -void CT_queueChatChar(char ch) -{ - if (((tail + 1) & (QUEUESIZE - 1)) == head) - { // the queue is full - return; - } - ChatQueue[tail] = ch; - tail = (tail + 1) & (QUEUESIZE - 1); -} - -//=========================================================================== -// -// CT_dequeueChatChar -// -//=========================================================================== - -char CT_dequeueChatChar(void) -{ - byte temp; - - if (head == tail) - { // queue is empty - return 0; - } - temp = ChatQueue[head]; - head = (head + 1) & (QUEUESIZE - 1); - return temp; -} - -//=========================================================================== -// -// CT_AddChar -// -//=========================================================================== - -void CT_AddChar(int player, char c) -{ - patch_t *patch; - - if (msgptr[player] + 1 >= MESSAGESIZE || msglen[player] >= MESSAGELEN) - { // full. - return; - } - chat_msg[player][msgptr[player]] = c; - msgptr[player]++; - if (c < 33) - { - msglen[player] += 6; - } - else - { - patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - msglen[player] += patch->width; - } -} - -//=========================================================================== -// -// CT_BackSpace -// -// Backs up a space, when the user hits (obviously) backspace -//=========================================================================== - -void CT_BackSpace(int player) -{ - patch_t *patch; - char c; - - if (msgptr[player] == 0) - { // message is already blank - return; - } - msgptr[player]--; - c = chat_msg[player][msgptr[player]]; - if (c < 33) - { - msglen[player] -= 6; - } - else - { - patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - msglen[player] -= patch->width; - } - chat_msg[player][msgptr[player]] = 0; -} - -//=========================================================================== -// -// CT_ClearChatMessage -// -// Clears out the data for the chat message, but the player's message -// is still saved in plrmsg. -//=========================================================================== - -void CT_ClearChatMessage(int player) -{ - memset(chat_msg[player], 0, MESSAGESIZE); - msgptr[player] = 0; - msglen[player] = 0; -} diff --git a/games/NXDoom/src/heretic/ct_chat.h b/games/NXDoom/src/heretic/ct_chat.h deleted file mode 100644 index 75aaab2706b..00000000000 --- a/games/NXDoom/src/heretic/ct_chat.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Chat mode stuff -// - -#ifndef HERETIC_CT_CHAT_H -#define HERETIC_CT_CHAT_H - -#define CT_PLR_GREEN 1 -#define CT_PLR_YELLOW 2 -#define CT_PLR_RED 3 -#define CT_PLR_BLUE 4 -#define CT_PLR_ALL 5 - -#define CT_KEY_GREEN 'g' -#define CT_KEY_YELLOW 'y' -#define CT_KEY_RED 'r' -#define CT_KEY_BLUE 'b' -#define CT_KEY_ALL 't' - -extern char *chat_macros[10]; - -#endif /* #ifndef HERETIC_CT_CHAT_H */ - diff --git a/games/NXDoom/src/heretic/d_main.c b/games/NXDoom/src/heretic/d_main.c deleted file mode 100644 index 9090df83af1..00000000000 --- a/games/NXDoom/src/heretic/d_main.c +++ /dev/null @@ -1,1171 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// D_main.c - -#include -#include - -#include "txt_main.h" -#include "txt_io.h" - -#include "net_client.h" - -#include "config.h" -#include "ct_chat.h" -#include "doomdef.h" -#include "deh_main.h" -#include "d_iwad.h" -#include "i_endoom.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_sound.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "m_argv.h" -#include "m_config.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "s_sound.h" -#include "w_main.h" -#include "v_video.h" -#include "am_map.h" - -#include "heretic_icon.c" - -#define CT_KEY_GREEN 'g' -#define CT_KEY_YELLOW 'y' -#define CT_KEY_RED 'r' -#define CT_KEY_BLUE 'b' - -#define STARTUP_WINDOW_X 17 -#define STARTUP_WINDOW_Y 7 - -GameMode_t gamemode = indetermined; -const char *gamedescription = "unknown"; - -boolean nomonsters; // checkparm of -nomonsters -boolean respawnparm; // checkparm of -respawn -boolean debugmode; // checkparm of -debug -boolean ravpic; // checkparm of -ravpic -boolean cdrom; // true if cd-rom mode active -boolean noartiskip; // whether shift-enter skips an artifact - -skill_t startskill; -int startepisode; -int startmap; -int UpdateState; -static int graphical_startup = 1; -static boolean using_graphical_startup; -static boolean main_loop_started = false; -boolean autostart; - -boolean advancedemo; - -FILE *debugfile; - -static int show_endoom = 1; - -void D_ConnectNetGame(void); -void D_CheckNetGame(void); -void D_PageDrawer(void); -void D_AdvanceDemo(void); -boolean F_Responder(event_t * ev); - -//--------------------------------------------------------------------------- -// -// PROC D_ProcessEvents -// -// Send all the events of the given timestamp down the responder chain. -// -//--------------------------------------------------------------------------- - -void D_ProcessEvents(void) -{ - event_t *ev; - - while ((ev = D_PopEvent()) != NULL) - { - if (F_Responder(ev)) - { - continue; - } - if (MN_Responder(ev)) - { - continue; - } - G_Responder(ev); - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawMessage -// -//--------------------------------------------------------------------------- - -void DrawMessage(void) -{ - player_t *player; - - player = &players[consoleplayer]; - if (player->messageTics <= 0 || !player->message) - { // No message - return; - } - MN_DrTextA(player->message, 160 - MN_TextAWidth(player->message) / 2, 1); -} - -//--------------------------------------------------------------------------- -// -// PROC D_Display -// -// Draw current display, possibly wiping it from the previous. -// -//--------------------------------------------------------------------------- - - -void D_Display(void) -{ - // Change the view size if needed - if (setsizeneeded) - { - R_ExecuteSetViewSize(); - } - -// -// do buffered drawing -// - switch (gamestate) - { - case GS_LEVEL: - if (!gametic) - break; - if (automapactive) - AM_Drawer(); - else - R_RenderPlayerView(&players[displayplayer]); - CT_Drawer(); - UpdateState |= I_FULLVIEW; - SB_Drawer(); - break; - case GS_INTERMISSION: - IN_Drawer(); - break; - case GS_FINALE: - F_Drawer(); - break; - case GS_DEMOSCREEN: - D_PageDrawer(); - break; - } - - if (testcontrols) - { - V_DrawMouseSpeedBox(testcontrols_mousespeed); - } - - if (paused && !MenuActive && !askforquit) - { - if (!netgame) - { - V_DrawPatch(160, viewwindowy + 5, W_CacheLumpName(DEH_String("PAUSED"), - PU_CACHE)); - } - else - { - V_DrawPatch(160, 70, W_CacheLumpName(DEH_String("PAUSED"), PU_CACHE)); - } - } - // Handle player messages - DrawMessage(); - - // Menu drawing - MN_Drawer(); - - // Send out any new accumulation - NetUpdate(); - - // Flush buffered stuff to screen - I_FinishUpdate(); -} - -// -// D_GrabMouseCallback -// -// Called to determine whether to grab the mouse pointer -// - -boolean D_GrabMouseCallback(void) -{ - // when menu is active or game is paused, release the mouse - - if (MenuActive || paused) - return false; - - // only grab mouse when playing levels (but not demos) - - return (gamestate == GS_LEVEL) && !demoplayback && !advancedemo; -} - -//--------------------------------------------------------------------------- -// -// PROC D_DoomLoop -// -//--------------------------------------------------------------------------- - -void D_DoomLoop(void) -{ - if (M_CheckParm("-debugfile")) - { - char filename[20]; - M_snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer); - debugfile = M_fopen(filename, "w"); - } - I_GraphicsCheckCommandLine(); - I_SetGrabMouseCallback(D_GrabMouseCallback); - I_RegisterWindowIcon(heretic_icon_data, heretic_icon_w, heretic_icon_h); - I_InitGraphics(); - - main_loop_started = true; - - while (1) - { - // Frame syncronous IO operations - I_StartFrame(); - - // Process one or more tics - // Will run at least one tic - TryRunTics(); - - // Move positional sounds - S_UpdateSounds(players[consoleplayer].mo); - D_Display(); - } -} - -/* -=============================================================================== - - DEMO LOOP - -=============================================================================== -*/ - -static int demosequence; -static int pagetic; -static const char *pagename; - - -/* -================ -= -= D_PageTicker -= -= Handles timing for warped projection -= -================ -*/ - -void D_PageTicker(void) -{ - if (--pagetic < 0) - D_AdvanceDemo(); -} - - -/* -================ -= -= D_PageDrawer -= -================ -*/ - -void D_PageDrawer(void) -{ - V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE)); - if (demosequence == 1) - { - V_DrawPatch(4, 160, W_CacheLumpName(DEH_String("ADVISOR"), PU_CACHE)); - } - UpdateState |= I_FULLSCRN; -} - -/* -================= -= -= D_AdvanceDemo -= -= Called after each demo or intro demosequence finishes -================= -*/ - -void D_AdvanceDemo(void) -{ - advancedemo = true; -} - -void D_DoAdvanceDemo(void) -{ - players[consoleplayer].playerstate = PST_LIVE; // don't reborn - advancedemo = false; - usergame = false; // can't save / end game here - paused = false; - gameaction = ga_nothing; - demosequence = (demosequence + 1) % 7; - switch (demosequence) - { - case 0: - pagetic = 210; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("TITLE"); - S_StartSong(mus_titl, false); - break; - case 1: - pagetic = 140; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("TITLE"); - break; - case 2: - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - G_DeferedPlayDemo(DEH_String("demo1")); - break; - case 3: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("CREDIT"); - break; - case 4: - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - G_DeferedPlayDemo(DEH_String("demo2")); - break; - case 5: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - if (gamemode == shareware) - { - pagename = DEH_String("ORDER"); - } - else - { - pagename = DEH_String("CREDIT"); - } - break; - case 6: - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - G_DeferedPlayDemo(DEH_String("demo3")); - break; - } -} - - -/* -================= -= -= D_StartTitle -= -================= -*/ - -void D_StartTitle(void) -{ - gameaction = ga_nothing; - demosequence = -1; - D_AdvanceDemo(); -} - - -/* -============== -= -= D_CheckRecordFrom -= -= -recordfrom -============== -*/ - -void D_CheckRecordFrom(void) -{ - int p; - char *filename; - - //! - // @vanilla - // @category demo - // @arg - // - // Load a game from the given savegame slot and record a demo from - // it. Equivalent to -loadgame -record . - - p = M_CheckParmWithArgs("-recordfrom", 2); - if (!p) - return; - - filename = SV_Filename(myargv[p + 1][0] - '0'); - G_LoadGame(filename); - G_DoLoadGame(); // load the gameskill etc info from savegame - - G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p + 2]); - D_DoomLoop(); // never returns - free(filename); -} - -/* -=============== -= -= D_AddFile -= -=============== -*/ - -// MAPDIR should be defined as the directory that holds development maps -// for the -wart # # command - -#define MAPDIR "\\data\\" - -#define SHAREWAREWADNAME "heretic1.wad" - -char *iwadfile; - - -void wadprintf(void) -{ - if (debugmode) - { - return; - } -} - -boolean D_AddFile(char *file) -{ - wad_file_t *handle; - - printf(" adding %s\n", file); - - handle = W_AddFile(file); - - return handle != NULL; -} - -//========================================================== -// -// Startup Thermo code -// -//========================================================== -#define MSG_Y 9 -#define THERM_X 14 -#define THERM_Y 14 - -int thermMax; -int thermCurrent; -char smsg[80]; // status bar line - -// -// Heretic startup screen shit -// - -static int startup_line = STARTUP_WINDOW_Y; - -void hprintf(const char *string) -{ - if (using_graphical_startup) - { - TXT_BGColor(TXT_COLOR_CYAN, 0); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_GotoXY(STARTUP_WINDOW_X, startup_line); - ++startup_line; - TXT_Puts(string); - - TXT_UpdateScreen(); - } - - // haleyjd: shouldn't be WATCOMC-only - if (debugmode) - puts(string); -} - -void drawstatus(void) -{ - int i; - - TXT_GotoXY(1, 24); - TXT_BGColor(TXT_COLOR_BLUE, 0); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - for (i=0; smsg[i] != '\0'; ++i) - { - TXT_PutChar(smsg[i]); - } -} - -static void status(const char *string) -{ - if (using_graphical_startup) - { - M_StringConcat(smsg, string, sizeof(smsg)); - drawstatus(); - } -} - -void DrawThermo(void) -{ - static int last_progress = -1; - int progress; - int i; - - if (!using_graphical_startup) - { - return; - } - - // No progress? Don't update the screen. - - progress = (50 * thermCurrent) / thermMax + 2; - - if (last_progress == progress) - { - return; - } - - last_progress = progress; - - TXT_GotoXY(THERM_X, THERM_Y); - - TXT_FGColor(TXT_COLOR_BRIGHT_GREEN); - TXT_BGColor(TXT_COLOR_GREEN, 0); - - for (i = 0; i < progress; i++) - { - TXT_PutChar(0xdb); - } - - TXT_UpdateScreen(); -} - -void initStartup(void) -{ - byte *textScreen; - byte *loading; - - if (!graphical_startup || debugmode || testcontrols) - { - using_graphical_startup = false; - return; - } - - if (!TXT_Init()) - { - using_graphical_startup = false; - return; - } - - I_InitWindowTitle(); - I_InitWindowIcon(); - - // Blit main screen - textScreen = TXT_GetScreenData(); - loading = W_CacheLumpName(DEH_String("LOADING"), PU_CACHE); - memcpy(textScreen, loading, 4000); - - // Print version string - - TXT_BGColor(TXT_COLOR_RED, 0); - TXT_FGColor(TXT_COLOR_YELLOW); - TXT_GotoXY(46, 2); - TXT_Puts(HERETIC_VERSION_TEXT); - - TXT_UpdateScreen(); - - using_graphical_startup = true; -} - -static void finishStartup(void) -{ - if (using_graphical_startup) - { - TXT_Shutdown(); - } -} - -char tmsg[300]; -void tprintf(const char *msg, int initflag) -{ - printf("%s", msg); -} - -// haleyjd: moved up, removed WATCOMC code -void CleanExit(void) -{ - DEH_printf("Exited from HERETIC.\n"); - exit(1); -} - -void CheckAbortStartup(void) -{ - // haleyjd: removed WATCOMC - // haleyjd FIXME: this should actually work in text mode too, but how to - // get input before SDL video init? - if(using_graphical_startup) - { - if(TXT_GetChar() == 27) - CleanExit(); - } -} - -void IncThermo(void) -{ - thermCurrent++; - DrawThermo(); - CheckAbortStartup(); -} - -void InitThermo(int max) -{ - thermMax = max; - thermCurrent = 0; -} - -// -// Add configuration file variable bindings. -// - -void D_BindVariables(void) -{ - int i; - - M_ApplyPlatformDefaults(); - - I_BindInputVariables(); - I_BindVideoVariables(); - I_BindJoystickVariables(); - I_BindSoundVariables(); - - M_BindBaseControls(); - M_BindHereticControls(); - M_BindWeaponControls(); - M_BindChatControls(MAXPLAYERS); - - key_multi_msgplayer[0] = CT_KEY_GREEN; - key_multi_msgplayer[1] = CT_KEY_YELLOW; - key_multi_msgplayer[2] = CT_KEY_RED; - key_multi_msgplayer[3] = CT_KEY_BLUE; - - M_BindMenuControls(); - M_BindMapControls(); - - NET_BindVariables(); - - M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); - M_BindIntVariable("sfx_volume", &snd_MaxVolume); - M_BindIntVariable("music_volume", &snd_MusicVolume); - M_BindIntVariable("screenblocks", &screenblocks); - M_BindIntVariable("snd_channels", &snd_Channels); - M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); - M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); - M_BindIntVariable("show_endoom", &show_endoom); - M_BindIntVariable("graphical_startup", &graphical_startup); - - for (i=0; i<10; ++i) - { - char buf[12]; - - M_snprintf(buf, sizeof(buf), "chatmacro%i", i); - M_BindStringVariable(buf, &chat_macros[i]); - } -} - -// -// Called at exit to display the ENDOOM screen (ENDTEXT in Heretic) -// - -static void D_Endoom(void) -{ - byte *endoom_data; - - // Disable ENDOOM? - - if (!show_endoom || testcontrols || !main_loop_started) - { - return; - } - - endoom_data = W_CacheLumpName(DEH_String("ENDTEXT"), PU_STATIC); - - I_Endoom(endoom_data); -} - -//--------------------------------------------------------------------------- -// -// PROC D_DoomMain -// -//--------------------------------------------------------------------------- - -void D_DoomMain(void) -{ - GameMission_t gamemission; - int p; - char file[256]; - char demolumpname[9]; - - I_PrintBanner(PACKAGE_STRING); - - I_AtExit(D_Endoom, false); - - //! - // @category game - // @vanilla - // - // Disable monsters. - // - - nomonsters = M_ParmExists("-nomonsters"); - - //! - // @category game - // @vanilla - // - // Monsters respawn after being killed. - // - - respawnparm = M_ParmExists("-respawn"); - - //! - // @vanilla - // - // Take screenshots when F1 is pressed. - // - - ravpic = M_ParmExists("-ravpic"); - - //! - // @category obscure - // @vanilla - // - // Allow artifacts to be used when the run key is held down. - // - - noartiskip = M_ParmExists("-noartiskip"); - - debugmode = M_ParmExists("-debug"); - startskill = sk_medium; - startepisode = 1; - startmap = 1; - autostart = false; - -// -// get skill / episode / map from parms -// - - //! - // @vanilla - // @category net - // - // Start a deathmatch game. - // - - if (M_ParmExists("-deathmatch")) - { - deathmatch = true; - } - - //! - // @category game - // @arg - // @vanilla - // - // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of - // 0 disables all monsters. - // - - p = M_CheckParmWithArgs("-skill", 1); - if (p) - { - startskill = myargv[p + 1][0] - '1'; - autostart = true; - } - - //! - // @category game - // @arg - // @vanilla - // - // Start playing episode n (1-4). - // - - p = M_CheckParmWithArgs("-episode", 1); - if (p) - { - startepisode = myargv[p + 1][0] - '0'; - startmap = 1; - autostart = true; - } - - //! - // @category game - // @arg - // @vanilla - // - // Start a game immediately, warping to level ExMy. - // - - p = M_CheckParmWithArgs("-warp", 2); - if (p && p < myargc - 2) - { - startepisode = myargv[p + 1][0] - '0'; - startmap = myargv[p + 2][0] - '0'; - autostart = true; - } - -// -// init subsystems -// - DEH_printf("V_Init: allocate screens.\n"); - V_Init(); - - // Check for -CDROM - - cdrom = false; - -#ifdef _WIN32 - - //! - // @category obscure - // @platform windows - // @vanilla - // - // Save configuration data and savegames in c:\heretic.cd, - // allowing play from CD. - // - - if (M_CheckParm("-cdrom")) - { - cdrom = true; - } -#endif - - if (cdrom) - { - M_SetConfigDir(DEH_String("c:\\heretic.cd")); - } - else - { - M_SetConfigDir(NULL); - } - - // Load defaults before initing other systems - DEH_printf("M_LoadDefaults: Load system defaults.\n"); - D_BindVariables(); - M_SetConfigFilenames("heretic.cfg", PROGRAM_PREFIX "heretic.cfg"); - M_LoadDefaults(); - - I_AtExit(M_SaveDefaults, false); - - DEH_printf("Z_Init: Init zone memory allocation daemon.\n"); - Z_Init(); - - DEH_printf("W_Init: Init WADfiles.\n"); - - iwadfile = D_FindIWAD(IWAD_MASK_HERETIC, &gamemission); - - if (iwadfile == NULL) - { - I_Error("Game mode indeterminate. No IWAD was found. Try specifying\n" - "one with the '-iwad' command line parameter."); - } - - D_AddFile(iwadfile); - W_CheckCorrectIWAD(heretic); - - //! - // @category mod - // - // Disable auto-loading of .wad files. - // - if (!M_ParmExists("-noautoload")) - { - char *autoload_dir; - autoload_dir = M_GetAutoloadDir("heretic.wad"); - if (autoload_dir != NULL) - { - DEH_AutoLoadPatches(autoload_dir); - W_AutoLoadWADs(autoload_dir); - free(autoload_dir); - } - } - - // Load dehacked patches specified on the command line. - DEH_ParseCommandLine(); - - // Load PWAD files. - W_ParseCommandLine(); - - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp. - // - - p = M_CheckParmWithArgs("-playdemo", 1); - if (!p) - { - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp, determining the framerate - // of the screen. - // - - p = M_CheckParmWithArgs("-timedemo", 1); - } - - if (p) - { - char *uc_filename = strdup(myargv[p + 1]); - M_ForceUppercase(uc_filename); - - // In Vanilla, the filename must be specified without .lmp, - // but make that optional. - if (M_StringEndsWith(uc_filename, ".LMP")) - { - M_StringCopy(file, myargv[p + 1], sizeof(file)); - } - else - { - DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p + 1]); - } - - free(uc_filename); - - if (D_AddFile(file)) - { - M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, - sizeof(demolumpname)); - } - else - { - // The file failed to load, but copy the original arg as a - // demo name to make tricks like -playdemo demo1 possible. - M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); - } - - printf("Playing demo %s.\n", file); - } - - // Generate the WAD hash table. Speed things up a bit. - W_GenerateHashTable(); - - //! - // @category demo - // - // Record or playback a demo without automatically quitting - // after either level exit or player respawn. - // - - demoextend = M_ParmExists("-demoextend"); - - if (W_CheckNumForName(DEH_String("E2M1")) == -1) - { - gamemode = shareware; - gamedescription = "Heretic (shareware)"; - } - else if (W_CheckNumForName("EXTENDED") != -1) - { - // Presence of the EXTENDED lump indicates the retail version - - gamemode = retail; - gamedescription = "Heretic: Shadow of the Serpent Riders"; - } - else - { - gamemode = registered; - gamedescription = "Heretic (registered)"; - } - - I_SetWindowTitle(gamedescription); - - savegamedir = M_GetSaveGameDir("heretic.wad"); - - I_PrintStartupBanner(gamedescription); - - if (M_ParmExists("-testcontrols")) - { - startepisode = 1; - startmap = 1; - autostart = true; - testcontrols = true; - } - - I_InitTimer(); - I_InitSound(heretic); - I_InitMusic(); - - tprintf("NET_Init: Init network subsystem.\n", 1); - NET_Init (); - - D_ConnectNetGame(); - - // haleyjd: removed WATCOMC - initStartup(); - - // - // Build status bar line! - // - smsg[0] = 0; - if (deathmatch) - status(DEH_String("DeathMatch...")); - if (nomonsters) - status(DEH_String("No Monsters...")); - if (respawnparm) - status(DEH_String("Respawning...")); - if (autostart) - { - char temp[64]; - DEH_snprintf(temp, sizeof(temp), - "Warp to Episode %d, Map %d, Skill %d ", - startepisode, startmap, startskill + 1); - status(temp); - } - wadprintf(); // print the added wadfiles - - tprintf(DEH_String("MN_Init: Init menu system.\n"), 1); - MN_Init(); - - CT_Init(); - - tprintf(DEH_String("R_Init: Init Heretic refresh daemon."), 1); - hprintf(DEH_String("Loading graphics")); - R_Init(); - tprintf("\n", 0); - - tprintf(DEH_String("P_Init: Init Playloop state.\n"), 1); - hprintf(DEH_String("Init game engine.")); - P_Init(); - IncThermo(); - - tprintf(DEH_String("I_Init: Setting up machine state.\n"), 1); - I_CheckIsScreensaver(); - I_InitJoystick(); - IncThermo(); - - tprintf(DEH_String("S_Init: Setting up sound.\n"), 1); - S_Init(); - //IO_StartupTimer(); - S_Start(); - - tprintf(DEH_String("D_CheckNetGame: Checking network game status.\n"), 1); - hprintf(DEH_String("Checking network game status.")); - D_CheckNetGame(); - IncThermo(); - - // haleyjd: removed WATCOMC - - tprintf(DEH_String("SB_Init: Loading patches.\n"), 1); - SB_Init(); - IncThermo(); - -// -// start the appropriate game based on params -// - - D_CheckRecordFrom(); - - //! - // @arg - // @category demo - // @vanilla - // - // Record a demo named x.lmp. - // - - p = M_CheckParmWithArgs("-record", 1); - if (p) - { - G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p + 1]); - D_DoomLoop(); // Never returns - } - - p = M_CheckParmWithArgs("-playdemo", 1); - if (p) - { - singledemo = true; // Quit after one demo - G_DeferedPlayDemo(demolumpname); - D_DoomLoop(); // Never returns - } - - p = M_CheckParmWithArgs("-timedemo", 1); - if (p) - { - G_TimeDemo(demolumpname); - D_DoomLoop(); // Never returns - } - - //! - // @category game - // @arg - // @vanilla - // - // Load the game in savegame slot s. - // - - p = M_CheckParmWithArgs("-loadgame", 1); - if (p && p < myargc - 1) - { - char *filename; - - filename = SV_Filename(myargv[p + 1][0] - '0'); - G_LoadGame(filename); - free(filename); - } - - // Check valid episode and map - if (autostart || netgame) - { - if (!D_ValidEpisodeMap(heretic, gamemode, startepisode, startmap)) - { - startepisode = 1; - startmap = 1; - } - } - - if (gameaction != ga_loadgame) - { - UpdateState |= I_FULLSCRN; - BorderNeedRefresh = true; - if (autostart || netgame) - { - G_InitNew(startskill, startepisode, startmap); - } - else - { - D_StartTitle(); - } - } - - finishStartup(); - - D_DoomLoop(); // Never returns -} diff --git a/games/NXDoom/src/heretic/d_net.c b/games/NXDoom/src/heretic/d_net.c deleted file mode 100644 index 8aef319fed5..00000000000 --- a/games/NXDoom/src/heretic/d_net.c +++ /dev/null @@ -1,218 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM Network game communication and protocol, -// all OS independend parts. -// - -#include - -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "doomdef.h" -#include "m_argv.h" -#include "m_misc.h" -#include "w_checksum.h" - -#include "deh_main.h" - -#include "d_loop.h" - -ticcmd_t *netcmds; - - -// Called when a player leaves the game - -static void PlayerQuitGame(player_t *player) -{ - static char exitmsg[80]; - unsigned int player_num; - - player_num = player - players; - - // Note: - // The Heretic source code does this, which doesn't actually work. - // As a result, the exit message is never seen. - - M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg)); - exitmsg[7] += player_num; - players[consoleplayer].message = exitmsg; - - playeringame[player_num] = false; - players[consoleplayer].message = exitmsg; - - // TODO: check if it is sensible to do this: - - if (demorecording) - { - G_CheckDemoStatus (); - } -} - -static void RunTic(ticcmd_t *cmds, boolean *ingame) -{ - unsigned int i; - - // Check for player quits. - - for (i = 0; i < MAXPLAYERS; ++i) - { - if (!demoplayback && playeringame[i] && !ingame[i]) - { - PlayerQuitGame(&players[i]); - } - } - - netcmds = cmds; - - // check that there are players in the game. if not, we cannot - // run a tic. - - if (advancedemo) - D_DoAdvanceDemo (); - - G_Ticker (); -} - -static loop_interface_t doom_loop_interface = { - D_ProcessEvents, - G_BuildTiccmd, - RunTic, - MN_Ticker -}; - - -// Load game settings from the specified structure and -// set global variables. - -static void LoadGameSettings(net_gamesettings_t *settings) -{ - unsigned int i; - - deathmatch = settings->deathmatch; - ticdup = settings->ticdup; - startepisode = settings->episode; - startmap = settings->map; - startskill = settings->skill; - // TODO startloadgame = settings->loadgame; - lowres_turn = settings->lowres_turn; - nomonsters = settings->nomonsters; - respawnparm = settings->respawn_monsters; - consoleplayer = settings->consoleplayer; - - if (lowres_turn) - { - printf("NOTE: Turning resolution is reduced; this is probably " - "because there is a client recording a Vanilla demo.\n"); - } - - for (i = 0; i < MAXPLAYERS; ++i) - { - playeringame[i] = i < settings->num_players; - } -} - -// Save the game settings from global variables to the specified -// game settings structure. - -static void SaveGameSettings(net_gamesettings_t *settings) -{ - // Fill in game settings structure with appropriate parameters - // for the new game - - settings->deathmatch = deathmatch; - settings->episode = startepisode; - settings->map = startmap; - settings->skill = startskill; - // TODO settings->loadgame = startloadgame; - settings->gameversion = exe_heretic_1_3; - settings->nomonsters = nomonsters; - settings->respawn_monsters = respawnparm; - settings->timelimit = 0; - - settings->lowres_turn = M_ParmExists("-record") - && !M_ParmExists("-longtics"); -} - -static void InitConnectData(net_connect_data_t *connect_data) -{ - connect_data->drone = false; - connect_data->max_players = MAXPLAYERS; - - // - // Connect data - // - - // Game type fields: - - connect_data->gamemode = gamemode; - connect_data->gamemission = heretic; - - // Are we recording a demo? Possibly set lowres turn mode - - connect_data->lowres_turn = M_ParmExists("-record") - && !M_ParmExists("-longtics"); - - // Read checksums of our WAD directory and dehacked information - - W_Checksum(connect_data->wad_sha1sum); - DEH_Checksum(connect_data->deh_sha1sum); - - connect_data->is_freedoom = 0; -} - -void D_ConnectNetGame(void) -{ - net_connect_data_t connect_data; - - InitConnectData(&connect_data); - netgame = D_InitNetGame(&connect_data); - - //! - // @category net - // - // Start the game playing as though in a netgame with a single - // player. This can also be used to play back single player netgame - // demos. - // - - if (M_CheckParm("-solo-net") > 0) - { - netgame = true; - } -} - -// -// D_CheckNetGame -// Works out player numbers among the net participants -// - -void D_CheckNetGame (void) -{ - net_gamesettings_t settings; - - D_RegisterLoopCallbacks(&doom_loop_interface); - - if (netgame) - { - autostart = true; - } - - SaveGameSettings(&settings); - D_StartNetGame(&settings, NULL); - LoadGameSettings(&settings); -} - diff --git a/games/NXDoom/src/heretic/deh_ammo.c b/games/NXDoom/src/heretic/deh_ammo.c deleted file mode 100644 index 39384d75d59..00000000000 --- a/games/NXDoom/src/heretic/deh_ammo.c +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Ammo" sections in dehacked files -// - -#include -#include -#include - -#include "doomdef.h" -#include "doomtype.h" -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" -#include "p_local.h" - -static void *DEH_AmmoStart(deh_context_t *context, char *line) -{ - int ammo_number = 0; - - if (sscanf(line, "Ammo %i", &ammo_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (ammo_number < 0 || ammo_number >= NUMAMMO) - { - DEH_Warning(context, "Invalid ammo number: %i", ammo_number); - return NULL; - } - - return &maxammo[ammo_number]; -} - -static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) -{ - char *variable_name, *value; - int ivalue; - int ammo_number; - - if (tag == NULL) - return; - - ammo_number = ((int *) tag) - maxammo; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - ivalue = atoi(value); - - if (!strcasecmp(variable_name, "Per ammo")) - { - // Heretic doesn't have a "per clip" ammo array, instead - // it is per weapon. However, the weapon number lines - // up with the ammo number if we add one. - - GetWeaponAmmo[ammo_number + 1] = ivalue; - } - else if (!strcasecmp(variable_name, "Max ammo")) - { - maxammo[ammo_number] = ivalue; - } - else - { - DEH_Warning(context, "Field named '%s' not found", variable_name); - } -} - -static void DEH_AmmoSHA1Hash(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include - -#include "doomtype.h" -#include "info.h" - -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" -#include "deh_mapping.h" -#include "deh_htic.h" - -#include "p_action.h" - -typedef struct -{ - int offsets[deh_hhe_num_versions]; - void (*func)(struct mobj_s *, struct player_s *, struct pspdef_s *); -} hhe_action_pointer_t; - -// Offsets of action pointers within the Heretic executables. -// Different versions have different offsets. -// (Seriously Greg, was this really necessary? What was wrong with the -// "copying action pointer from another frame" technique used in dehacked?) - -// Offset Action function -// v1.0 v1.2 v1.3 - -static const hhe_action_pointer_t action_pointers[] = -{ - { { 77680, 80144, 80208 }, A_AccTeleGlitter }, - { { 78608, 81104, 81168 }, A_AddPlayerCorpse }, - { { 115808, 118000, 118240 }, A_AddPlayerRain }, - { { 112272, 114480, 114720 }, A_BeakAttackPL1 }, - { { 112448, 114656, 114896 }, A_BeakAttackPL2 }, - { { 111856, 114176, 114416 }, A_BeakRaise }, - { { 111568, 113888, 114128 }, A_BeakReady }, - { { 74640, 77120, 77184 }, A_BeastAttack }, - { { 70480, 72992, 73056 }, A_BeastPuff }, - { { 73120, 75600, 75664 }, A_BlueSpark }, - { { 115456, 117648, 117888 }, A_BoltSpark }, - { { 77344, 79808, 79872 }, A_BossDeath }, - { { 69328, 71856, 71920 }, A_Chase }, - { { 0, 80976, 81040 }, A_CheckBurnGone }, - { { 78480, 80944, 81008 }, A_CheckSkullDone }, - { { 78448, 80912, 80976 }, A_CheckSkullFloor }, - { { 71376, 73888, 73952 }, A_ChicAttack }, - { { 71488, 74000, 74064 }, A_ChicChase }, - { { 71456, 73968, 74032 }, A_ChicLook }, - { { 71520, 74032, 74096 }, A_ChicPain }, - { { 75792, 78208, 78272 }, A_ClinkAttack }, - { { 108432, 110816, 111056 }, A_ContMobjSound }, - { { 114752, 116944, 117184 }, A_DeathBallImpact }, - { { 70016, 72528, 72592 }, A_DripBlood }, - { { 77472, 79936, 80000 }, A_ESound }, - { { 76784, 79248, 79312 }, A_Explode }, - { { 69872, 72400, 72464 }, A_FaceTarget }, - { { 71568, 74080, 74144 }, A_Feathers }, - { { 112928, 115136, 115376 }, A_FireBlasterPL1 }, - { { 113072, 115280, 115520 }, A_FireBlasterPL2 }, - { { 115232, 117424, 117664 }, A_FireCrossbowPL1 }, - { { 115312, 117504, 117744 }, A_FireCrossbowPL2 }, - { { 113152, 115360, 115600 }, A_FireGoldWandPL1 }, - { { 113296, 115504, 115744 }, A_FireGoldWandPL2 }, - { { 113760, 115968, 116208 }, A_FireMacePL1 }, - { { 114624, 116816, 117056 }, A_FireMacePL2 }, - { { 116368, 118544, 118784 }, A_FirePhoenixPL1 }, - { { 116736, 118896, 119136 }, A_FirePhoenixPL2 }, - { { 115568, 117760, 118000 }, A_FireSkullRodPL1 }, - { { 115648, 117840, 118080 }, A_FireSkullRodPL2 }, - { { 117120, 119280, 119520 }, A_FlameEnd }, - { { 78704, 81200, 81264 }, A_FlameSnd }, - { { 117152, 119312, 119552 }, A_FloatPuff }, - { { 78512, 81008, 81072 }, A_FreeTargMobj }, - { { 117184, 119344, 119584 }, A_GauntletAttack }, - { { 73232, 75712, 75776 }, A_GenWizard }, - { { 75872, 78304, 78368 }, A_GhostOff }, - { { 74752, 77232, 77296 }, A_HeadAttack }, - { { 75488, 77984, 78048 }, A_HeadFireGrow }, - { { 75328, 77824, 77888 }, A_HeadIceImpact }, - { { 116336, 118512, 118752 }, A_HideInCeiling }, - { { 78736, 81232, 81296 }, A_HideThing }, - { { 70976, 73488, 73552 }, A_ImpDeath }, - { { 70304, 72816, 72880 }, A_ImpExplode }, - { { 70592, 73104, 73168 }, A_ImpMeAttack }, - { { 70672, 73184, 73248 }, A_ImpMsAttack }, - { { 70880, 73392, 73456 }, A_ImpMsAttack2 }, - { { 71024, 73536, 73600 }, A_ImpXDeath1 }, - { { 71072, 73584, 73648 }, A_ImpXDeath2 }, - { { 77728, 80192, 80256 }, A_InitKeyGizmo }, - { { 116720, 118880, 119120 }, A_InitPhoenixPL2 }, - { { 70160, 72672, 72736 }, A_KnightAttack }, - { { 117648, 119824, 120064 }, A_Light0 }, - { { 69200, 71728, 71792 }, A_Look }, - { { 111760, 114080, 114320 }, A_Lower }, - { { 114032, 116224, 116464 }, A_MaceBallImpact }, - { { 114192, 116384, 116624 }, A_MaceBallImpact2 }, - { { 113904, 116112, 116352 }, A_MacePL1Check }, - { { 77104, 79568, 79632 }, A_MakePod }, - { { 73648, 76128, 76192 }, A_MinotaurAtk1 }, - { { 74112, 76592, 76656 }, A_MinotaurAtk2 }, - { { 74352, 76832, 76896 }, A_MinotaurAtk3 }, - { { 74032, 76512, 76576 }, A_MinotaurCharge }, - { { 73760, 76240, 76304 }, A_MinotaurDecide }, - { { 74528, 77008, 77072 }, A_MntrFloorFire }, - { { 71808, 74288, 74352 }, A_MummyAttack }, - { { 71920, 74400, 74464 }, A_MummyAttack2 }, - { { 72016, 74496, 74560 }, A_MummyFX1Seek }, - { { 72048, 74528, 74592 }, A_MummySoul }, - { { 76400, 78832, 78896 }, A_NoBlocking }, - { { 69984, 72496, 72560 }, A_Pain }, - { { 116496, 118656, 118896 }, A_PhoenixPuff }, - { { 76896, 79360, 79424 }, A_PodPain }, - { { 116272, 118448, 118688 }, A_RainImpact }, - { { 111920, 114240, 114480 }, A_Raise }, - { { 111696, 114016, 114256 }, A_ReFire }, - { { 77056, 79520, 79584 }, A_RemovePod }, - { { 116480, 0, 0 }, A_RemovedPhoenixFunc }, - { { 81952, 84464, 84528 }, A_RestoreArtifact }, - { { 82048, 84544, 84608 }, A_RestoreSpecialThing1 }, - { { 82128, 84592, 84656 }, A_RestoreSpecialThing2 }, - { { 76144, 78576, 78640 }, A_Scream }, - { { 117104, 119264, 119504 }, A_ShutdownPhoenixPL2 }, - { { 78288, 80752, 80816 }, A_SkullPop }, - { { 115776, 117968, 118208 }, A_SkullRodPL2Seek }, - { { 115984, 118176, 118416 }, A_SkullRodStorm }, - { { 75632, 78048, 78112 }, A_SnakeAttack }, - { { 75712, 78128, 78192 }, A_SnakeAttack2 }, - { { 72144, 74624, 74688 }, A_Sor1Chase }, - { { 72096, 74576, 74640 }, A_Sor1Pain }, - { { 73392, 75872, 75936 }, A_Sor2DthInit }, - { { 73424, 75904, 75968 }, A_Sor2DthLoop }, - { { 73584, 76064, 76128 }, A_SorDBon }, - { { 73552, 76032, 76096 }, A_SorDExp }, - { { 73520, 76000, 76064 }, A_SorDSph }, - { { 73488, 75968, 76032 }, A_SorRise }, - { { 73616, 76096, 76160 }, A_SorSightSnd }, - { { 73456, 75936, 76000 }, A_SorZap }, - { { 72480, 74960, 75024 }, A_SorcererRise }, - { { 115088, 117280, 117520 }, A_SpawnRippers }, - { { 77520, 79984, 80048 }, A_SpawnTeleGlitter }, - { { 77600, 80064, 80128 }, A_SpawnTeleGlitter2 }, - { { 72192, 74672, 74736 }, A_Srcr1Attack }, - { { 72896, 75376, 75440 }, A_Srcr2Attack }, - { { 72816, 75296, 75360 }, A_Srcr2Decide }, - { { 112640, 114848, 115088 }, A_StaffAttackPL1 }, - { { 112784, 114992, 115232 }, A_StaffAttackPL2 }, - { { 78752, 81248, 81312 }, A_UnHideThing }, - { { 78080, 80544, 80608 }, A_VolcBallImpact }, - { { 77856, 80320, 80384 }, A_VolcanoBlast }, - { { 77824, 80288, 80352 }, A_VolcanoSet }, - { { 111168, 113488, 113728 }, A_WeaponReady }, - { { 75168, 77664, 77728 }, A_WhirlwindSeek }, - { { 75888, 78320, 78384 }, A_WizAtk1 }, - { { 75920, 78352, 78416 }, A_WizAtk2 }, - { { 75952, 78384, 78448 }, A_WizAtk3 }, -}; - -DEH_BEGIN_MAPPING(state_mapping, state_t) - DEH_MAPPING("Sprite number", sprite) - DEH_MAPPING("Sprite subnumber", frame) - DEH_MAPPING("Duration", tics) - DEH_MAPPING("Next frame", nextstate) - DEH_MAPPING("Unknown 1", misc1) - DEH_MAPPING("Unknown 2", misc2) -DEH_END_MAPPING - -static void DEH_FrameInit(void) -{ - // Bit of a hack here: - DEH_HereticInit(); -} - -static void *DEH_FrameStart(deh_context_t *context, char *line) -{ - int frame_number = 0; - int mapped_frame_number; - state_t *state; - - if (sscanf(line, "Frame %i", &frame_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - // Map the HHE frame number (which assumes a Heretic 1.0 state table) - // to the internal frame number (which is is the Heretic 1.3 state table): - - mapped_frame_number = DEH_MapHereticFrameNumber(frame_number); - - if (mapped_frame_number < 0 || mapped_frame_number >= DEH_HERETIC_NUMSTATES) - { - DEH_Warning(context, "Invalid frame number: %i", frame_number); - return NULL; - } - - state = &states[mapped_frame_number]; - - return state; -} - -static boolean GetActionPointerForOffset(int offset, void (**result)(struct mobj_s *, struct player_s *, struct pspdef_s *)) -{ - int i; - - // Special case. - - if (offset == 0) - { - *result = NULL; - return true; - } - - for (i=0; iaction = func; - } - else - { - // "Next frame" numbers need to undergo mapping. - - if (!strcasecmp(variable_name, "Next frame")) - { - ivalue = DEH_MapHereticFrameNumber(ivalue); - } - - DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); - } -} - -static void DEH_FrameSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include -#include - -#include "doomtype.h" -#include "dstrings.h" - -#include "z_zone.h" - -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_htic.h" -#include "deh_main.h" - -// -// Ok, Greg, the action pointers thing was bad enough, but this really -// takes the biscuit. Why does HHE's text replacement address strings -// by offset??!! The dehacked way was much nicer, why change it? -// - -typedef struct -{ - unsigned int offsets[deh_hhe_num_versions]; - const char *string; -} hhe_string_t; - -// Offsets String -// v1.0 v1.2 v1.3 - -static const hhe_string_t strings[] = -{ - { { 228, 228, 228 }, "PLAYPAL" }, - { { 1240, 1252, 1252 }, "E1M1: THE DOCKS" }, - { { 1260, 1272, 1272 }, "E1M2: THE DUNGEONS" }, - { { 1280, 1292, 1292 }, "E1M3: THE GATEHOUSE" }, - { { 1304, 1316, 1316 }, "E1M4: THE GUARD TOWER" }, - { { 1328, 1340, 1340 }, "E1M5: THE CITADEL" }, - { { 1348, 1360, 1360 }, "E1M6: THE CATHEDRAL" }, - { { 1372, 1384, 1384 }, "E1M7: THE CRYPTS" }, - { { 1392, 1404, 1404 }, "E1M8: HELL'S MAW" }, - { { 1412, 1424, 1424 }, "E1M9: THE GRAVEYARD" }, - { { 1436, 1448, 1448 }, "E2M1: THE CRATER" }, - { { 1456, 1468, 1468 }, "E2M2: THE LAVA PITS" }, - { { 1480, 1492, 1492 }, "E2M3: THE RIVER OF FIRE" }, - { { 1508, 1520, 1520 }, "E2M4: THE ICE GROTTO" }, - { { 1532, 1544, 1544 }, "E2M5: THE CATACOMBS" }, - { { 1556, 1568, 1568 }, "E2M6: THE LABYRINTH" }, - { { 1580, 1592, 1592 }, "E2M7: THE GREAT HALL" }, - { { 1604, 1616, 1616 }, "E2M8: THE PORTALS OF CHAOS" }, - { { 1632, 1644, 1644 }, "E2M9: THE GLACIER" }, - { { 1652, 1664, 1664 }, "E3M1: THE STOREHOUSE" }, - { { 1676, 1688, 1688 }, "E3M2: THE CESSPOOL" }, - { { 1696, 1708, 1708 }, "E3M3: THE CONFLUENCE" }, - { { 1720, 1732, 1732 }, "E3M4: THE AZURE FORTRESS" }, - { { 1748, 1760, 1760 }, "E3M5: THE OPHIDIAN LAIR" }, - { { 1776, 1788, 1788 }, "E3M6: THE HALLS OF FEAR" }, - { { 1804, 1816, 1816 }, "E3M7: THE CHASM" }, - { { 1824, 1836, 1836 }, "E3M8: D'SPARIL'S KEEP" }, - { { 1848, 1860, 1860 }, "E3M9: THE AQUIFER" }, - { { 0, 1880, 1880 }, "E4M1: CATAFALQUE" }, - { { 0, 1900, 1900 }, "E4M2: BLOCKHOUSE" }, - { { 0, 1920, 1920 }, "E4M3: AMBULATORY" }, - { { 0, 1940, 1940 }, "E4M4: SEPULCHER" }, - { { 0, 1960, 1960 }, "E4M5: GREAT STAIR" }, - { { 0, 1980, 1980 }, "E4M6: HALLS OF THE APOSTATE" }, - { { 0, 2012, 2012 }, "E4M7: RAMPARTS OF PERDITION" }, - { { 0, 2044, 2044 }, "E4M8: SHATTERED BRIDGE" }, - { { 0, 2068, 2068 }, "E4M9: MAUSOLEUM" }, - { { 0, 2088, 2088 }, "E5M1: OCHRE CLIFFS" }, - { { 0, 2108, 2108 }, "E5M2: RAPIDS" }, - { { 0, 2124, 2124 }, "E5M3: QUAY" }, - { { 0, 2136, 2136 }, "E5M4: COURTYARD" }, - { { 0, 2156, 2156 }, "E5M5: HYDRATYR" }, - { { 0, 2172, 2172 }, "E5M6: COLONNADE" }, - { { 0, 2192, 2192 }, "E5M7: FOETID MANSE" }, - { { 0, 2212, 2212 }, "E5M8: FIELD OF JUDGEMENT" }, - { { 0, 2240, 2240 }, "E5M9: SKEIN OF D'SPARIL" }, - { { 1868, 2268, 2268 }, "AUTOPAGE" }, - { { 1880, 2280, 2280 }, "FOLLOW MODE ON" }, - { { 1896, 2296, 2296 }, "FOLLOW MODE OFF" }, - { { 1924, 2324, 2324 }, "GREEN: " }, - { { 1936, 2336, 2336 }, "YELLOW: " }, - { { 1948, 2348, 2348 }, "RED: " }, - { { 1956, 2356, 2356 }, "BLUE: " }, - { { 1964, 2364, 2364 }, "FONTA_S" }, - { { 1972, 2372, 2372 }, "-MESSAGE SENT-" }, - { { 1988, 2388, 2388 }, "THERE ARE NO OTHER PLAYERS IN THE GAME!" }, - { { 2028, 2428, 2428 }, "FONTA59" }, - { { 2036, 2504, 2504 }, "PAUSED" }, - { { 2072, 2540, 2540 }, "ADVISOR" }, - { { 2080, 2548, 2548 }, "TITLE" }, - { { 2088, 2556, 2556 }, "demo1" }, - { { 2096, 2564, 2564 }, "CREDIT" }, - { { 2104, 2572, 2572 }, "demo2" }, - { { 2112, 2580, 2580 }, "ORDER" }, - { { 2120, 2588, 2588 }, "demo3" }, - { { 2304, 2696, 2696 }, "Exited from HERETIC.\n" }, - { { 2412, 2800, 2800 }, "c:\\heretic.cd" }, - { { 2528, 2916, 2916 }, "Playing demo %s.lmp.\n" }, - { { 2592, 2980, 2980 }, "V_Init: allocate screens.\n" }, - { { 2620, 3008, 3008 }, "M_LoadDefaults: Load system defaults.\n" }, - { { 2660, 3048, 3048 }, "Z_Init: Init zone memory allocation daemon.\n" }, - { { 2708, 3096, 3096 }, "W_Init: Init WADfiles.\n" }, - { { 2732, 3120, 3120 }, "E2M1" }, - { { 0, 3128, 3128 }, "EXTENDED" }, - { { 2740, 3140, 3140 }, "LOADING" }, - { { 2748, 3148, 3148 }, "DeathMatch..." }, - { { 2764, 3164, 3164 }, "No Monsters..." }, - { { 2780, 3180, 3180 }, "Respawning..." }, - { { 2796, 3196, 3196 }, "Warp to Episode %d, Map %d, Skill %d " }, - { { 2836, 3236, 3236 }, "MN_Init: Init menu system.\n" }, - { { 2864, 3264, 3264 }, "R_Init: Init Heretic refresh daemon." }, - { { 2904, 3304, 3304 }, "Loading graphics" }, - { { 2924, 3324, 3324 }, "P_Init: Init Playloop state." }, - { { 2956, 3356, 3356 }, "Init game engine." }, - { { 2976, 3376, 3376 }, "I_Init: Setting up machine state.\n" }, - { { 3012, 3412, 3412 }, "D_CheckNetGame: Checking network game status.\n" }, - { { 3060, 3460, 3460 }, "Checking network game status." }, - { { 3092, 3492, 3492 }, "SB_Init: Loading patches.\n" }, - { { 0, 3752, 3752 }, "PLAYER 1 LEFT THE GAME" }, - { { 3508, 3932, 3932 }, "Network game synchronization aborted." }, - { { 0, 3972, 3972 }, "Different DOOM versions cannot play a net game!" }, - { { 3908, 4132, 4132 }, "SKY1" }, - { { 3916, 4140, 4140 }, "SKY2" }, - { { 3924, 4148, 4148 }, "SKY3" }, - { { 3736, 4196, 4196 }, "NET GAME" }, - { { 3748, 4208, 4208 }, "SAVE GAME" }, - { { 3760, 4220, 4220 }, "Only %i deathmatch spots, 4 required" }, - { { 3800, 4260, 4260 }, "version %i" }, - { { 3828, 4372, 4372 }, "c:\\heretic.cd\\hticsav%d.hsg" }, - { { 3856, 4400, 4400 }, "hticsav%d.hsg" }, - { { 3896, 4416, 4416 }, "GAME SAVED" }, - { { 4016, 4456, 4456 }, E1TEXT }, - { { 4536, 4976, 4976 }, E2TEXT }, - { { 5068, 5508, 5508 }, E3TEXT }, - { { 0, 6072, 6072 }, E4TEXT }, - { { 0, 6780, 6780 }, E5TEXT }, - { { 5632, 7468, 7468 }, "FLOOR25" }, - { { 5640, 7476, 7476 }, "FLATHUH1" }, - { { 5652, 7488, 7488 }, "FLTWAWA2" }, - { { 0, 7500, 7500 }, "FLOOR28" }, - { { 0, 7508, 7508 }, "FLOOR08" }, - { { 5664, 7516, 7516 }, "FONTA_S" }, - { { 5704, 7524, 7524 }, "PLAYPAL" }, - { { 5672, 7532, 7532 }, "FINAL1" }, - { { 5680, 7540, 7540 }, "FINAL2" }, - { { 5688, 7548, 7548 }, "E2PAL" }, - { { 5696, 7556, 7556 }, "E2END" }, - { { 7884, 7564, 7564 }, "TITLE" }, - { { 5712, 7572, 7572 }, "ORDER" }, - { { 0, 7580, 7580 }, "CREDIT" }, - { { 5720, 7588, 7588 }, "IMPX" }, - { { 5728, 7596, 7596 }, "ACLO" }, - { { 5736, 7604, 7604 }, "PTN1" }, - { { 5744, 7612, 7612 }, "SHLD" }, - { { 5752, 7620, 7620 }, "SHD2" }, - { { 5760, 7628, 7628 }, "BAGH" }, - { { 5768, 7636, 7636 }, "SPMP" }, - { { 5776, 7644, 7644 }, "INVS" }, - { { 5784, 7652, 7652 }, "PTN2" }, - { { 5792, 7660, 7660 }, "SOAR" }, - { { 5800, 7668, 7668 }, "INVU" }, - { { 5808, 7676, 7676 }, "PWBK" }, - { { 5816, 7684, 7684 }, "EGGC" }, - { { 5824, 7692, 7692 }, "EGGM" }, - { { 5832, 7700, 7700 }, "FX01" }, - { { 5840, 7708, 7708 }, "SPHL" }, - { { 5848, 7716, 7716 }, "TRCH" }, - { { 5856, 7724, 7724 }, "FBMB" }, - { { 5864, 7732, 7732 }, "XPL1" }, - { { 5872, 7740, 7740 }, "ATLP" }, - { { 5880, 7748, 7748 }, "PPOD" }, - { { 5888, 7756, 7756 }, "AMG1" }, - { { 5896, 7764, 7764 }, "SPSH" }, - { { 5904, 7772, 7772 }, "LVAS" }, - { { 5912, 7780, 7780 }, "SLDG" }, - { { 5920, 7788, 7788 }, "SKH1" }, - { { 5928, 7796, 7796 }, "SKH2" }, - { { 5936, 7804, 7804 }, "SKH3" }, - { { 5944, 7812, 7812 }, "SKH4" }, - { { 5952, 7820, 7820 }, "CHDL" }, - { { 5960, 7828, 7828 }, "SRTC" }, - { { 5968, 7836, 7836 }, "SMPL" }, - { { 5976, 7844, 7844 }, "STGS" }, - { { 5984, 7852, 7852 }, "STGL" }, - { { 5992, 7860, 7860 }, "STCS" }, - { { 6000, 7868, 7868 }, "STCL" }, - { { 6008, 7876, 7876 }, "KFR1" }, - { { 6016, 7884, 7884 }, "BARL" }, - { { 6024, 7892, 7892 }, "BRPL" }, - { { 6032, 7900, 7900 }, "MOS1" }, - { { 6040, 7908, 7908 }, "MOS2" }, - { { 6048, 7916, 7916 }, "WTRH" }, - { { 6056, 7924, 7924 }, "HCOR" }, - { { 6064, 7932, 7932 }, "KGZ1" }, - { { 6072, 7940, 7940 }, "KGZB" }, - { { 6080, 7948, 7948 }, "KGZG" }, - { { 6088, 7956, 7956 }, "KGZY" }, - { { 6096, 7964, 7964 }, "VLCO" }, - { { 6104, 7972, 7972 }, "VFBL" }, - { { 6112, 7980, 7980 }, "VTFB" }, - { { 6120, 7988, 7988 }, "SFFI" }, - { { 6128, 7996, 7996 }, "TGLT" }, - { { 6136, 8004, 8004 }, "TELE" }, - { { 6144, 8012, 8012 }, "STFF" }, - { { 6152, 8020, 8020 }, "PUF3" }, - { { 6160, 8028, 8028 }, "PUF4" }, - { { 6168, 8036, 8036 }, "BEAK" }, - { { 6176, 8044, 8044 }, "WGNT" }, - { { 6184, 8052, 8052 }, "GAUN" }, - { { 6192, 8060, 8060 }, "PUF1" }, - { { 6200, 8068, 8068 }, "WBLS" }, - { { 6208, 8076, 8076 }, "BLSR" }, - { { 6216, 8084, 8084 }, "FX18" }, - { { 6224, 8092, 8092 }, "FX17" }, - { { 6232, 8100, 8100 }, "WMCE" }, - { { 6240, 8108, 8108 }, "MACE" }, - { { 6248, 8116, 8116 }, "FX02" }, - { { 6256, 8124, 8124 }, "WSKL" }, - { { 6264, 8132, 8132 }, "HROD" }, - { { 6272, 8140, 8140 }, "FX00" }, - { { 6280, 8148, 8148 }, "FX20" }, - { { 6288, 8156, 8156 }, "FX21" }, - { { 6296, 8164, 8164 }, "FX22" }, - { { 6304, 8172, 8172 }, "FX23" }, - { { 6312, 8180, 8180 }, "GWND" }, - { { 6320, 8188, 8188 }, "PUF2" }, - { { 6328, 8196, 8196 }, "WPHX" }, - { { 6336, 8204, 8204 }, "PHNX" }, - { { 6344, 8212, 8212 }, "FX04" }, - { { 6352, 8220, 8220 }, "FX08" }, - { { 6360, 8228, 8228 }, "FX09" }, - { { 6368, 8236, 8236 }, "WBOW" }, - { { 6376, 8244, 8244 }, "CRBW" }, - { { 6384, 8252, 8252 }, "FX03" }, - { { 6392, 8260, 8260 }, "BLOD" }, - { { 6400, 8268, 8268 }, "PLAY" }, - { { 6408, 8276, 8276 }, "FDTH" }, - { { 6416, 8284, 8284 }, "BSKL" }, - { { 6424, 8292, 8292 }, "CHKN" }, - { { 6432, 8300, 8300 }, "MUMM" }, - { { 6440, 8308, 8308 }, "FX15" }, - { { 6448, 8316, 8316 }, "BEAS" }, - { { 6456, 8324, 8324 }, "FRB1" }, - { { 6464, 8332, 8332 }, "SNKE" }, - { { 6472, 8340, 8340 }, "SNFX" }, - { { 6480, 8348, 8348 }, "HEAD" }, - { { 6488, 8356, 8356 }, "FX05" }, - { { 6496, 8364, 8364 }, "FX06" }, - { { 6504, 8372, 8372 }, "FX07" }, - { { 6512, 8380, 8380 }, "CLNK" }, - { { 6520, 8388, 8388 }, "WZRD" }, - { { 6528, 8396, 8396 }, "FX11" }, - { { 6536, 8404, 8404 }, "FX10" }, - { { 6544, 8412, 8412 }, "KNIG" }, - { { 6552, 8420, 8420 }, "SPAX" }, - { { 6560, 8428, 8428 }, "RAXE" }, - { { 6568, 8436, 8436 }, "SRCR" }, - { { 6576, 8444, 8444 }, "FX14" }, - { { 6584, 8452, 8452 }, "SOR2" }, - { { 6592, 8460, 8460 }, "SDTH" }, - { { 6600, 8468, 8468 }, "FX16" }, - { { 6608, 8476, 8476 }, "MNTR" }, - { { 6616, 8484, 8484 }, "FX12" }, - { { 6624, 8492, 8492 }, "FX13" }, - { { 6632, 8500, 8500 }, "AKYY" }, - { { 6640, 8508, 8508 }, "BKYY" }, - { { 6648, 8516, 8516 }, "CKYY" }, - { { 6656, 8524, 8524 }, "AMG2" }, - { { 6664, 8532, 8532 }, "AMM1" }, - { { 6672, 8540, 8540 }, "AMM2" }, - { { 6680, 8548, 8548 }, "AMC1" }, - { { 6688, 8556, 8556 }, "AMC2" }, - { { 6696, 8564, 8564 }, "AMS1" }, - { { 6704, 8572, 8572 }, "AMS2" }, - { { 6712, 8580, 8580 }, "AMP1" }, - { { 6720, 8588, 8588 }, "AMP2" }, - { { 6728, 8596, 8596 }, "AMB1" }, - { { 6736, 8604, 8604 }, "AMB2" }, - { { 6744, 8612, 8612 }, "K" }, - { { 6748, 8616, 8616 }, "I" }, - { { 6752, 8620, 8620 }, "L" }, - { { 6756, 8624, 8624 }, "E" }, - { { 6760, 8628, 8628 }, "R" }, - { { 6764, 8632, 8632 }, "S" }, - { { 6768, 8636, 8636 }, "PLAYPAL" }, - { { 6776, 8644, 8644 }, "MAPE1" }, - { { 6784, 8652, 8652 }, "MAPE2" }, - { { 6792, 8660, 8660 }, "MAPE3" }, - { { 6800, 8668, 8668 }, "IN_X" }, - { { 6808, 8676, 8676 }, "IN_YAH" }, - { { 6816, 8684, 8684 }, "FONTB16" }, - { { 6824, 8692, 8692 }, "FONTB_S" }, - { { 6832, 8700, 8700 }, "FONTB13" }, - { { 6840, 8708, 8708 }, "FONTB15" }, - { { 6848, 8716, 8716 }, "FONTB05" }, - { { 6856, 8724, 8724 }, "FACEA0" }, - { { 6864, 8732, 8732 }, "FACEB0" }, - { { 6940, 8808, 8808 }, "FLOOR16" }, - { { 6948, 8816, 8816 }, "FINISHED" }, - { { 6960, 8828, 8828 }, "NOW ENTERING:" }, - { { 6976, 8844, 8844 }, "KILLS" }, - { { 6984, 8852, 8852 }, "ITEMS" }, - { { 6992, 8860, 8860 }, "SECRETS" }, - { { 7000, 8868, 8868 }, "TIME" }, - { { 7008, 8876, 8876 }, "BONUS" }, - { { 7016, 8884, 8884 }, "SECRET" }, - { { 7024, 8892, 8892 }, "TOTAL" }, - { { 7032, 8900, 8900 }, "VICTIMS" }, - { { 7040, 8908, 8908 }, ":" }, - { { 7044, 8912, 8912 }, "NEW GAME" }, - { { 7056, 8924, 8924 }, "OPTIONS" }, - { { 7064, 8932, 8932 }, "GAME FILES" }, - { { 7076, 8944, 8944 }, "INFO" }, - { { 7084, 8952, 8952 }, "QUIT GAME" }, - { { 7096, 8964, 8964 }, "CITY OF THE DAMNED" }, - { { 7116, 8984, 8984 }, "HELL'S MAW" }, - { { 7128, 8996, 8996 }, "THE DOME OF D'SPARIL" }, - { { 0, 9020, 9020 }, "THE OSSUARY" }, - { { 0, 9032, 9032 }, "THE STAGNANT DEMESNE" }, - { { 7152, 9056, 9056 }, "LOAD GAME" }, - { { 7164, 9068, 9068 }, "SAVE GAME" }, - { { 7176, 9080, 9080 }, "THOU NEEDETH A WET-NURSE" }, - { { 7204, 9108, 9108 }, "YELLOWBELLIES-R-US" }, - { { 7224, 9128, 9128 }, "BRINGEST THEM ONETH" }, - { { 7244, 9148, 9148 }, "THOU ART A SMITE-MEISTER" }, - { { 7272, 9176, 9176 }, "BLACK PLAGUE POSSESSES THEE" }, - { { 7300, 9204, 9204 }, "END GAME" }, - { { 7312, 9216, 9216 }, "MESSAGES : " }, - { { 7324, 9228, 9228 }, "MOUSE SENSITIVITY" }, - { { 7344, 9248, 9248 }, "MORE..." }, - { { 7352, 9256, 9256 }, "SCREEN SIZE" }, - { { 7364, 9268, 9268 }, "SFX VOLUME" }, - { { 7376, 9280, 9280 }, "MUSIC VOLUME" }, - { { 7416, 9296, 9296 }, "ARE YOU SURE YOU WANT TO QUIT?" }, - { { 7448, 9328, 9328 }, "ARE YOU SURE YOU WANT TO END THE GAME?" }, - { { 7488, 9368, 9368 }, "DO YOU WANT TO QUICKSAVE THE GAME NAMED" }, - { { 7528, 9408, 9408 }, "DO YOU WANT TO QUICKLOAD THE GAME NAMED" }, - { { 7392, 9448, 9448 }, "M_SKL00" }, - { { 7400, 9456, 9456 }, "FONTA_S" }, - { { 7408, 9464, 9464 }, "FONTB_S" }, - { { 7568, 9472, 9472 }, "?" }, - { { 7572, 9476, 9476 }, "M_SLCTR1" }, - { { 7584, 9488, 9488 }, "M_SLCTR2" }, - { { 7596, 9500, 9500 }, "M_HTIC" }, - { { 7604, 9508, 9508 }, "c:\\heretic.cd\\hticsav%d.hsg" }, - { { 7632, 9536, 9536 }, "hticsav%d.hsg" }, - { { 7652, 9556, 9556 }, "M_FSLOT" }, - { { 7660, 9564, 9564 }, "ON" }, - { { 7664, 9568, 9568 }, "OFF" }, - { { 0, 9572, 9572 }, "YOU CAN'T START A NEW GAME IN NETPLAY!" }, - { { 0, 9612, 9612 }, "YOU CAN'T LOAD A GAME IN NETPLAY!" }, - { { 7668, 9648, 9648 }, "MESSAGES ON" }, - { { 7680, 9660, 9660 }, "MESSAGES OFF" }, - { { 7748, 9676, 9676 }, "ONLY AVAILABLE IN THE REGISTERED VERSION" }, - { { 7792, 9720, 9720 }, "PLAYPAL" }, - { { 7800, 9728, 9728 }, "QUICKSAVING...." }, - { { 7816, 9744, 9744 }, "QUICKLOADING...." }, - { { 7836, 9764, 9764 }, "CHOOSE A QUICKSAVE SLOT" }, - { { 7860, 9788, 9788 }, "CHOOSE A QUICKLOAD SLOT" }, - { { 0, 9812, 9812 }, "TITLE" }, - { { 7892, 9820, 9820 }, "M_SLDLT" }, - { { 7900, 9828, 9828 }, "M_SLDMD1" }, - { { 7912, 9840, 9840 }, "M_SLDMD2" }, - { { 7924, 9852, 9852 }, "M_SLDRT" }, - { { 7932, 9860, 9860 }, "M_SLDKB" }, - { { 9016, 10944, 10944 }, "SCREEN SHOT" }, - { { 9028, 10956, 10956 }, "YOU NEED A BLUE KEY TO OPEN THIS DOOR" }, - { { 9068, 10996, 10996 }, "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" }, - { { 9108, 11036, 11036 }, "YOU NEED A GREEN KEY TO OPEN THIS DOOR" }, - { { 9244, 11172, 11172 }, "CRYSTAL VIAL" }, - { { 9260, 11188, 11188 }, "SILVER SHIELD" }, - { { 9276, 11204, 11204 }, "ENCHANTED SHIELD" }, - { { 9296, 11224, 11224 }, "BAG OF HOLDING" }, - { { 9312, 11240, 11240 }, "MAP SCROLL" }, - { { 9324, 11252, 11252 }, "BLUE KEY" }, - { { 9336, 11264, 11264 }, "YELLOW KEY" }, - { { 9348, 11276, 11276 }, "GREEN KEY" }, - { { 9360, 11288, 11288 }, "QUARTZ FLASK" }, - { { 9376, 11304, 11304 }, "WINGS OF WRATH" }, - { { 9392, 11320, 11320 }, "RING OF INVINCIBILITY" }, - { { 9416, 11344, 11344 }, "TOME OF POWER" }, - { { 9432, 11360, 11360 }, "SHADOWSPHERE" }, - { { 9448, 11376, 11376 }, "MORPH OVUM" }, - { { 9460, 11388, 11388 }, "MYSTIC URN" }, - { { 9472, 11400, 11400 }, "TORCH" }, - { { 9480, 11408, 11408 }, "TIME BOMB OF THE ANCIENTS" }, - { { 9508, 11436, 11436 }, "CHAOS DEVICE" }, - { { 9524, 11452, 11452 }, "WAND CRYSTAL" }, - { { 9540, 11468, 11468 }, "CRYSTAL GEODE" }, - { { 9556, 11484, 11484 }, "MACE SPHERES" }, - { { 9572, 11500, 11500 }, "PILE OF MACE SPHERES" }, - { { 9596, 11524, 11524 }, "ETHEREAL ARROWS" }, - { { 9612, 11540, 11540 }, "QUIVER OF ETHEREAL ARROWS" }, - { { 9640, 11568, 11568 }, "CLAW ORB" }, - { { 9652, 11580, 11580 }, "ENERGY ORB" }, - { { 9664, 11592, 11592 }, "LESSER RUNES" }, - { { 9680, 11608, 11608 }, "GREATER RUNES" }, - { { 9696, 11624, 11624 }, "FLAME ORB" }, - { { 9708, 11636, 11636 }, "INFERNO ORB" }, - { { 9720, 11648, 11648 }, "FIREMACE" }, - { { 9732, 11660, 11660 }, "ETHEREAL CROSSBOW" }, - { { 9752, 11680, 11680 }, "DRAGON CLAW" }, - { { 9764, 11692, 11692 }, "HELLSTAFF" }, - { { 9776, 11704, 11704 }, "PHOENIX ROD" }, - { { 9788, 11716, 11716 }, "GAUNTLETS OF THE NECROMANCER" }, - { { 10088, 12016, 12016 }, "FLTWAWA1" }, - { { 10100, 12028, 12028 }, "FLTFLWW1" }, - { { 10112, 12040, 12040 }, "FLTLAVA1" }, - { { 10124, 12052, 12052 }, "FLATHUH1" }, - { { 10136, 12064, 12064 }, "FLTSLUD1" }, - { { 10148, 12076, 12076 }, "END" }, - { { 10236, 12164, 12164 }, "texture2" }, - { { 10444, 12372, 12372 }, "PLAYPAL" }, - { { 10596, 12488, 12488 }, "PNAMES" }, - { { 10604, 12496, 12496 }, "TEXTURE1" }, - { { 10616, 12508, 12508 }, "TEXTURE2" }, - { { 10628, 12520, 12520 }, "S_END" }, - { { 10636, 12528, 12528 }, "S_START" }, - { { 10728, 12620, 12620 }, "F_START" }, - { { 10736, 12628, 12628 }, "F_END" }, - { { 10744, 12636, 12636 }, "COLORMAP" }, - { { 10756, 12648, 12648 }, "\nR_InitTextures " }, - { { 10776, 12668, 12668 }, "R_InitFlats\n" }, - { { 10792, 12684, 12684 }, "R_InitSpriteLumps " }, - { { 10948, 12772, 12772 }, "TINTTAB" }, - { { 10984, 12780, 12780 }, "FLOOR04" }, - { { 10992, 12788, 12788 }, "FLAT513" }, - { { 11000, 12796, 12796 }, "bordt" }, - { { 11008, 12804, 12804 }, "bordb" }, - { { 11016, 12812, 12812 }, "bordl" }, - { { 11024, 12820, 12820 }, "bordr" }, - { { 11032, 12828, 12828 }, "bordtl" }, - { { 11040, 12836, 12836 }, "bordtr" }, - { { 11048, 12844, 12844 }, "bordbr" }, - { { 11056, 12852, 12852 }, "bordbl" }, - { { 11064, 12860, 12860 }, "R_InitData " }, - { { 11076, 12872, 12872 }, "R_InitPointToAngle\n" }, - { { 11096, 12892, 12892 }, "R_InitTables " }, - { { 11112, 12908, 12908 }, "R_InitPlanes\n" }, - { { 11128, 12924, 12924 }, "R_InitLightTables " }, - { { 11148, 12944, 12944 }, "R_InitSkyMap\n" }, - { { 11164, 12960, 12960 }, "F_SKY1" }, - { { 12120, 13484, 13484 }, "LTFACE" }, - { { 12128, 13492, 13492 }, "RTFACE" }, - { { 12136, 13500, 13500 }, "BARBACK" }, - { { 12144, 13508, 13508 }, "INVBAR" }, - { { 12152, 13516, 13516 }, "CHAIN" }, - { { 12160, 13524, 13524 }, "STATBAR" }, - { { 12168, 13532, 13532 }, "LIFEBAR" }, - { { 12176, 13540, 13540 }, "LIFEGEM2" }, - { { 12188, 13552, 13552 }, "LIFEGEM0" }, - { { 12200, 13564, 13564 }, "LTFCTOP" }, - { { 12208, 13572, 13572 }, "RTFCTOP" }, - { { 12224, 13580, 13580 }, "SELECTBOX" }, - { { 12236, 13592, 13592 }, "INVGEML1" }, - { { 12248, 13604, 13604 }, "INVGEML2" }, - { { 12260, 13616, 13616 }, "INVGEMR1" }, - { { 12272, 13628, 13628 }, "INVGEMR2" }, - { { 12284, 13640, 13640 }, "BLACKSQ" }, - { { 12292, 13648, 13648 }, "ARMCLEAR" }, - { { 12304, 13660, 13660 }, "CHAINBACK" }, - { { 12316, 13672, 13672 }, "IN0" }, - { { 12320, 13676, 13676 }, "NEGNUM" }, - { { 12328, 13684, 13684 }, "FONTB16" }, - { { 12336, 13692, 13692 }, "SMALLIN0" }, - { { 12348, 13704, 13704 }, "PLAYPAL" }, - { { 12356, 13712, 13712 }, "SPINBK0" }, - { { 12364, 13720, 13720 }, "SPFLY0" }, - { { 12372, 13728, 13728 }, "LAME" }, - { { 12380, 13736, 13736 }, "*** SOUND DEBUG INFO ***" }, - { { 12408, 13764, 13764 }, "NAME" }, - { { 12416, 13772, 13772 }, "MO.T" }, - { { 12424, 13780, 13780 }, "MO.X" }, - { { 12432, 13788, 13788 }, "MO.Y" }, - { { 12440, 13796, 13796 }, "ID" }, - { { 12444, 13800, 13800 }, "PRI" }, - { { 12448, 13804, 13804 }, "DIST" }, - { { 12456, 13812, 13812 }, "------" }, - { { 12464, 13820, 13820 }, "%s" }, - { { 12468, 13824, 13824 }, "%d" }, - { { 12472, 13828, 13828 }, "GOD1" }, - { { 12480, 13836, 13836 }, "GOD2" }, - { { 12488, 13844, 13844 }, "useartia" }, - { { 12500, 13856, 13856 }, "ykeyicon" }, - { { 12512, 13868, 13868 }, "gkeyicon" }, - { { 12524, 13880, 13880 }, "bkeyicon" }, - { { 12216, 13892, 13892 }, "ARTIBOX" }, - { { 12536, 13900, 13900 }, "GOD MODE ON" }, - { { 12548, 13912, 13912 }, "GOD MODE OFF" }, - { { 12564, 13928, 13928 }, "NO CLIPPING ON" }, - { { 12580, 13944, 13944 }, "NO CLIPPING OFF" }, - { { 12596, 13960, 13960 }, "ALL WEAPONS" }, - { { 12608, 13972, 13972 }, "POWER OFF" }, - { { 12620, 13984, 13984 }, "POWER ON" }, - { { 12632, 13996, 13996 }, "FULL HEALTH" }, - { { 12644, 14008, 14008 }, "ALL KEYS" }, - { { 12656, 14020, 14020 }, "SOUND DEBUG ON" }, - { { 12672, 14036, 14036 }, "SOUND DEBUG OFF" }, - { { 12688, 14052, 14052 }, "TICKER ON" }, - { { 12700, 14064, 14064 }, "TICKER OFF" }, - { { 12712, 14076, 14076 }, "CHOOSE AN ARTIFACT ( A - J )" }, - { { 12744, 14108, 14108 }, "HOW MANY ( 1 - 9 )" }, - { { 12764, 14128, 14128 }, "YOU GOT IT" }, - { { 12776, 14140, 14140 }, "BAD INPUT" }, - { { 12788, 14152, 14152 }, "LEVEL WARP" }, - { { 12800, 14164, 14164 }, "CHICKEN OFF" }, - { { 12812, 14176, 14176 }, "CHICKEN ON" }, - { { 12824, 14188, 14188 }, "MASSACRE" }, - { { 12836, 14200, 14200 }, "CHEATER - YOU DON'T DESERVE WEAPONS" }, - { { 12872, 14236, 14236 }, "TRYING TO CHEAT, EH? NOW YOU DIE!" }, -}; - -// String offsets that are valid but we don't support. - -static const int unsupported_strings_1_0[] = -{ - 0, 4, 64, 104, 160, 200, 220, 236, - 244, 252, 272, 288, 296, 316, 332, 372, - 436, 500, 504, 536, 544, 560, 576, 584, - 592, 612, 640, 664, 708, 712, 744, 764, - 808, 820, 828, 840, 876, 884, 908, 952, - 992, 1028, 1036, 1048, 1088, 1128, 1160, 1192, - 1212, 1912, 2044, 2056, 2068, 2128, 2140, 2168, - 2184, 2196, 2212, 2228, 2240, 2252, 2260, 2264, - 2284, 2292, 2296, 2300, 2328, 2340, 2352, 2364, - 2372, 2384, 2388, 2404, 2428, 2436, 2444, 2464, - 2496, 2508, 2520, 2552, 2564, 2572, 2584, 3120, - 3128, 3140, 3184, 3220, 3248, 3252, 3256, 3280, - 3304, 3320, 3352, 3380, 3400, 3432, 3464, 3548, - 3600, 3624, 3664, 3696, 3812, 3872, 3932, 3940, - 3976, 3996, 6872, 6896, 7648, 7696, 7940, 7964, - 7968, 7992, 8020, 8028, 8052, 8056, 8076, 8088, - 8104, 8116, 8128, 8136, 8148, 8164, 8180, 8192, - 8204, 8220, 8232, 8248, 8264, 8276, 8292, 8308, - 8320, 8328, 8340, 8352, 8364, 8376, 8392, 8408, - 8424, 8436, 8448, 8460, 8472, 8488, 8504, 8520, - 8536, 8548, 8560, 8572, 8584, 8596, 8608, 8612, - 8624, 8648, 8660, 8668, 8680, 8708, 8720, 8728, - 8740, 8752, 8764, 8788, 8800, 8812, 8824, 8848, - 8860, 8864, 8868, 8876, 8888, 8896, 8916, 8944, - 8948, 8960, 8964, 8968, 8980, 9148, 9172, 9212, - 9216, 9220, 9820, 9860, 9892, 9940, 9972, 10012, - 10036, 10040, 10052, 10080, 10152, 10192, 10248, 10284, - 10320, 10360, 10392, 10452, 10488, 10508, 10556, 10644, - 10684, 10812, 10844, 10880, 10912, 10956, 11172, 11200, - 11232, 11272, 11312, 11348, 11380, 11404, 11436, 11492, - 11548, 11616, 11684, 11748, 11792, 11840, 11896, 11936, - 11980, 12028, 12072, 12908, 12924, 12956, 12960, 12968, - 12976, 13020, 13048, 13076, 13104, 13136, 13168, 13196, - 13240, 13272, 13292, 13296, 13308, 13312, 13320, 13324, - 13364, 13408, 13460, 13492, 13516, 13560, 13612, 13664, - 13700, 13744, 13796, 13848, 13884, 13940, 13996, 14040, - 14084, 14140, 14148, 14156, 14164, 14184, 14192, 14204, - 14208, 14212, 14256, 14272, 14284, 14296, 14300, 14312, - 14320, 14324, 14348, 14356, 14360, 14372, 14380, 14392, - 14432, 14440, 14444, 14472, 14496, 14516, 14536, 14548, - 14560, 14572, 14580, 14588, 14596, 14604, 14612, 14620, - 14636, 14660, 14704, 14740, 14748, 14756, 14760, 14768, - -1, -}; - -static const int unsupported_strings_1_2[] = -{ - 0, 4, 64, 104, 160, 200, 220, 236, - 244, 252, 272, 288, 296, 316, 332, 372, - 436, 500, 504, 536, 544, 560, 576, 584, - 592, 612, 640, 664, 708, 712, 744, 756, - 776, 820, 832, 840, 852, 888, 896, 920, - 964, 1004, 1040, 1048, 1060, 1100, 1140, 1172, - 1204, 1224, 2312, 2436, 2448, 2464, 2480, 2492, - 2512, 2524, 2536, 2596, 2608, 2636, 2652, 2656, - 2676, 2684, 2688, 2720, 2732, 2744, 2752, 2764, - 2772, 2776, 2792, 2816, 2824, 2832, 2852, 2884, - 2896, 2908, 2940, 2952, 2960, 2972, 3520, 3528, - 3540, 3584, 3620, 3648, 3652, 3656, 3680, 3704, - 3720, 3776, 3804, 3824, 3856, 3888, 4020, 4044, - 4084, 4116, 4156, 4272, 4288, 4296, 4332, 4352, - 4428, 4432, 8740, 8764, 9552, 9868, 9888, 9900, - 9916, 9928, 9940, 9948, 9960, 9976, 9992, 10004, - 10016, 10032, 10044, 10060, 10076, 10088, 10104, 10120, - 10132, 10140, 10152, 10164, 10176, 10188, 10204, 10220, - 10236, 10248, 10260, 10272, 10284, 10300, 10316, 10332, - 10348, 10360, 10372, 10384, 10396, 10408, 10420, 10424, - 10436, 10460, 10472, 10480, 10492, 10520, 10532, 10540, - 10552, 10564, 10576, 10600, 10612, 10624, 10636, 10660, - 10672, 10676, 10700, 10704, 10728, 10756, 10764, 10788, - 10792, 10796, 10804, 10816, 10824, 10844, 10872, 10876, - 10888, 10892, 10896, 10908, 11076, 11100, 11140, 11144, - 11148, 11748, 11788, 11820, 11868, 11900, 11940, 11964, - 11968, 11980, 12008, 12080, 12120, 12176, 12212, 12248, - 12288, 12320, 12380, 12400, 12448, 12536, 12576, 12704, - 12736, 12968, 13000, 13024, 13080, 13136, 13204, 13272, - 13336, 13380, 13428, 14272, 14288, 14320, 14324, 14332, - 14340, 14384, 14412, 14440, 14468, 14500, 14532, 14560, - 14604, 14636, 14656, 14696, 14740, 14792, 14824, 14848, - 14892, 14944, 14996, 15032, 15076, 15128, 15180, 15216, - 15272, 15328, 15372, 15416, 15472, 15480, 15488, 15496, - 15516, 15524, 15536, 15540, 15544, 15588, 15604, 15616, - 15628, 15632, 15644, 15652, 15656, 15680, 15688, 15692, - 15704, 15712, 15724, 15764, 15772, 15776, 15804, 15828, - 15848, 15868, 15880, 15892, 15904, 15912, 15920, 15928, - 15936, -1, -}; - -static const int unsupported_strings_1_3[] = -{ - 0, 4, 64, 104, 160, 200, 220, 236, - 244, 252, 272, 288, 296, 316, 332, 372, - 436, 500, 504, 536, 544, 560, 576, 584, - 592, 612, 640, 664, 708, 712, 744, 756, - 776, 820, 832, 840, 852, 888, 896, 920, - 964, 1004, 1040, 1048, 1060, 1100, 1140, 1172, - 1204, 1224, 2312, 2436, 2448, 2464, 2480, 2492, - 2512, 2524, 2536, 2596, 2608, 2636, 2652, 2656, - 2676, 2684, 2688, 2720, 2732, 2744, 2752, 2764, - 2772, 2776, 2792, 2816, 2824, 2832, 2852, 2884, - 2896, 2908, 2940, 2952, 2960, 2972, 3520, 3528, - 3540, 3584, 3620, 3648, 3652, 3656, 3680, 3704, - 3720, 3776, 3804, 3824, 3856, 3888, 4020, 4044, - 4084, 4116, 4156, 4272, 4288, 4296, 4332, 4352, - 4428, 4432, 8740, 8764, 9552, 9868, 9888, 9900, - 9916, 9928, 9940, 9948, 9960, 9976, 9992, 10004, - 10016, 10032, 10044, 10060, 10076, 10088, 10104, 10120, - 10132, 10140, 10152, 10164, 10176, 10188, 10204, 10220, - 10236, 10248, 10260, 10272, 10284, 10300, 10316, 10332, - 10348, 10360, 10372, 10384, 10396, 10408, 10420, 10424, - 10436, 10460, 10472, 10480, 10492, 10520, 10532, 10540, - 10552, 10564, 10576, 10600, 10612, 10624, 10636, 10660, - 10672, 10676, 10700, 10704, 10728, 10756, 10764, 10788, - 10792, 10796, 10804, 10816, 10824, 10844, 10872, 10876, - 10888, 10892, 10896, 10908, 11076, 11100, 11140, 11144, - 11148, 11748, 11788, 11820, 11868, 11900, 11940, 11964, - 11968, 11980, 12008, 12080, 12120, 12176, 12212, 12248, - 12288, 12320, 12380, 12400, 12448, 12536, 12576, 12704, - 12736, 12968, 13000, 13024, 13080, 13136, 13204, 13272, - 13336, 13380, 13428, 14272, 14288, 14320, 14324, 14332, - 14340, 14384, 14412, 14440, 14468, 14500, 14532, 14560, - 14604, 14636, 14656, 14696, 14740, 14792, 14824, 14848, - 14892, 14944, 14996, 15032, 15076, 15128, 15180, 15216, - 15272, 15328, 15372, 15416, 15472, 15480, 15488, 15496, - 15516, 15524, 15536, 15540, 15544, 15588, 15604, 15616, - 15628, 15632, 15644, 15652, 15656, 15680, 15688, 15692, - 15704, 15712, 15724, 15764, 15772, 15776, 15804, 15828, - 15848, 15868, 15880, 15892, 15904, 15912, 15920, 15928, - 15936, -1, -}; - -static const int *unsupported_strings[] = -{ - unsupported_strings_1_0, - unsupported_strings_1_2, - unsupported_strings_1_3, -}; - -static boolean StringIsUnsupported(unsigned int offset) -{ - const int *string_list; - int i; - - string_list = unsupported_strings[deh_hhe_version]; - - for (i=0; string_list[i] >= 0; ++i) - { - if ((unsigned int) string_list[i] == offset) - { - return true; - } - } - - return false; -} - -static boolean GetStringByOffset(unsigned int offset, const char **result) -{ - int i; - - for (i=0; i= 0; ++i) - { - if (string_list[i] == offset) - { - DEH_SuggestHereticVersion(v); - } - } - } -} - -static void *DEH_TextStart(deh_context_t *context, char *line) -{ - char *repl_text; - const char *orig_text; - int orig_offset, repl_len; - int i; - - if (sscanf(line, "Text %i %i", &orig_offset, &repl_len) != 2) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - repl_text = malloc(repl_len + 1); - - // read in the "to" text - - for (i=0; i MaxStringLength(strlen(orig_text))) - { - DEH_Error(context, "Replacement string is longer than the maximum " - "possible in heretic.exe"); - } - else - { - // Success. - - DEH_AddStringReplacement(orig_text, repl_text); - } - - // We must always free the replacement text. - free(repl_text); - - return NULL; -} - -static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag) -{ - // not used -} - -deh_section_t deh_section_heretic_text = -{ - "Text", - NULL, - DEH_TextStart, - DEH_TextParseLine, - NULL, - NULL, -}; - diff --git a/games/NXDoom/src/heretic/deh_htic.c b/games/NXDoom/src/heretic/deh_htic.c deleted file mode 100644 index 94fb935ceca..00000000000 --- a/games/NXDoom/src/heretic/deh_htic.c +++ /dev/null @@ -1,182 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Top-level dehacked definitions for Heretic dehacked (HHE). -// - -#include -#include -#include - -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_htic.h" -#include "info.h" -#include "m_argv.h" - -const char *deh_signatures[] = -{ - "Patch File for HHE v1.0", - "Patch File for HHE v1.1", - NULL -}; - -static const char *hhe_versions[] = -{ - "1.0", "1.2", "1.3" -}; - -// Version number for patches. - -deh_hhe_version_t deh_hhe_version = deh_hhe_1_0; - - -// -// List of section types: -// - -deh_section_t *deh_section_types[] = -{ - &deh_section_ammo, - &deh_section_frame, -// &deh_section_pointer, TODO - &deh_section_sound, - &deh_section_heretic_text, - &deh_section_thing, - &deh_section_weapon, - NULL -}; - -static void SetHHEVersionByName(const char *name) -{ - int i; - - for (i=0; i - // @category mod - // - // Select the Heretic version number that was used to generate the - // HHE patch to be loaded. Patches for each of the Vanilla - // Heretic versions (1.0, 1.2, 1.3) can be loaded, but the correct - // version number must be specified. - - i = M_CheckParm("-hhever"); - - if (i > 0) - { - SetHHEVersionByName(myargv[i + 1]); - } - - // For v1.0 patches, we must apply a slight change to the states[] - // table. The table was changed between 1.0 and 1.3 to add two extra - // frames to the player "burning death" animation. - // - // If we are using a v1.0 patch, we must change the table to cut - // these out again. - - if (deh_hhe_version < deh_hhe_1_2) - { - states[S_PLAY_FDTH18].nextstate = S_NULL; - } -} - -int DEH_MapHereticThingType(int type) -{ - // Heretic 1.0 had an extra entry in the mobjinfo table that was removed - // in later versions. This has been added back into the table for - // compatibility. However, it also means that if we're loading a patch - // for a later version, we need to translate to the index used internally. - - if (deh_hhe_version > deh_hhe_1_0) - { - if (type >= MT_PHOENIXFX_REMOVED) - { - ++type; - } - } - - return type; -} - -int DEH_MapHereticFrameNumber(int frame) -{ - if (deh_hhe_version < deh_hhe_1_2) - { - // Between Heretic 1.0 and 1.2, two new frames - // were added to the "states" table, to extend the "flame death" - // animation displayed when the player is killed by fire. Therefore, - // we must map Heretic 1.0 frame numbers to corresponding indexes - // for our state table. - - if (frame >= S_PLAY_FDTH19) - { - frame = (frame - S_PLAY_FDTH19) + S_BLOODYSKULL1; - } - } - else - { - // After Heretic 1.2, three unused frames were removed from the - // states table, unused phoenix rod frames. Our state table includes - // these missing states for backwards compatibility. We must therefore - // adjust frame numbers for v1.2/v1.3 to corresponding indexes for - // our state table. - - if (frame >= S_PHOENIXFXIX_1) - { - frame = (frame - S_PHOENIXFXIX_1) + S_PHOENIXPUFF1; - } - } - - return frame; -} - -void DEH_SuggestHereticVersion(deh_hhe_version_t version) -{ - fprintf(stderr, - "\n" - "This patch may be for version %s. You are currently running in\n" - "Heretic %s mode. For %s mode, add this to your command line:\n" - "\n" - "\t-hhever %s\n" - "\n", - hhe_versions[version], - hhe_versions[deh_hhe_version], - hhe_versions[version], - hhe_versions[version]); -} - diff --git a/games/NXDoom/src/heretic/deh_htic.h b/games/NXDoom/src/heretic/deh_htic.h deleted file mode 100644 index 978d9381567..00000000000 --- a/games/NXDoom/src/heretic/deh_htic.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Common header for Heretic dehacked (HHE) support. -// - -#ifndef DEH_HTIC_H -#define DEH_HTIC_H - -#include "info.h" - -// HHE executable version. Loading HHE patches is (unfortunately) -// dependent on the version of the Heretic executable used to make them. - -typedef enum -{ - deh_hhe_1_0, - deh_hhe_1_2, - deh_hhe_1_3, - deh_hhe_num_versions -} deh_hhe_version_t; - -// HHE doesn't know about the last two states in the state table, so -// these are considered invalid. - -#define DEH_HERETIC_NUMSTATES (NUMSTATES - 2) - -// It also doesn't know about the last two things in the mobjinfo table -// (which correspond to the states above) - -#define DEH_HERETIC_NUMMOBJTYPES (NUMMOBJTYPES - 2) - -void DEH_HereticInit(void); -int DEH_MapHereticThingType(int type); -int DEH_MapHereticFrameNumber(int frame); -void DEH_SuggestHereticVersion(deh_hhe_version_t version); - -extern deh_hhe_version_t deh_hhe_version; - -// deh_htext.c: -extern deh_section_t deh_section_heretic_text; - - -#endif /* #ifndef DEH_HTIC_H */ - diff --git a/games/NXDoom/src/heretic/deh_sound.c b/games/NXDoom/src/heretic/deh_sound.c deleted file mode 100644 index c889cd66308..00000000000 --- a/games/NXDoom/src/heretic/deh_sound.c +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Sound" sections in dehacked files -// - -#include -#include - -#include "doomtype.h" -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_mapping.h" - -#include "doomdef.h" -#include "i_sound.h" - -#include "sounds.h" - -DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t) - DEH_MAPPING_STRING("Name", name) - DEH_UNSUPPORTED_MAPPING("Special") - DEH_MAPPING("Value", priority) - DEH_MAPPING("Unknown 1", usefulness) - DEH_UNSUPPORTED_MAPPING("Unknown 2") - DEH_UNSUPPORTED_MAPPING("Unknown 3") - DEH_MAPPING("One/Two", numchannels) -DEH_END_MAPPING - -static void *DEH_SoundStart(deh_context_t *context, char *line) -{ - int sound_number = 0; - - if (sscanf(line, "Sound %i", &sound_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (sound_number < 0 || sound_number >= NUMSFX) - { - DEH_Warning(context, "Invalid sound number: %i", sound_number); - return NULL; - } - - if (sound_number >= DEH_VANILLA_NUMSFX) - { - DEH_Warning(context, "Attempt to modify SFX %i. This will cause " - "problems in Vanilla dehacked.", sound_number); - } - - return &S_sfx[sound_number]; -} - -static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag) -{ - sfxinfo_t *sfx; - char *variable_name, *value; - - if (tag == NULL) - return; - - sfx = (sfxinfo_t *) tag; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - // Set the field value: - - if (!strcasecmp(variable_name, "Name")) - { - DEH_SetStringMapping(context, &sound_mapping, sfx, - variable_name, value); - } - else - { - DEH_SetMapping(context, &sound_mapping, sfx, - variable_name, atoi(value)); - } -} - -deh_section_t deh_section_sound = -{ - "Sound", - NULL, - DEH_SoundStart, - DEH_SoundParseLine, - NULL, - NULL, -}; - diff --git a/games/NXDoom/src/heretic/deh_thing.c b/games/NXDoom/src/heretic/deh_thing.c deleted file mode 100644 index e9984fbdef7..00000000000 --- a/games/NXDoom/src/heretic/deh_thing.c +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Thing" sections in dehacked files -// - -#include -#include - -#include "doomtype.h" -#include "m_misc.h" - -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_mapping.h" -#include "deh_htic.h" - -#include "info.h" - -DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t) - DEH_MAPPING("ID #", doomednum) - DEH_MAPPING("Initial frame", spawnstate) - DEH_MAPPING("Hit points", spawnhealth) - DEH_MAPPING("First moving frame", seestate) - DEH_MAPPING("Alert sound", seesound) - DEH_MAPPING("Reaction time", reactiontime) - DEH_MAPPING("Attack sound", attacksound) - DEH_MAPPING("Injury frame", painstate) - DEH_MAPPING("Pain chance", painchance) - DEH_MAPPING("Pain sound", painsound) - DEH_MAPPING("Close attack frame", meleestate) - DEH_MAPPING("Far attack frame", missilestate) - DEH_MAPPING("Burning frame", crashstate) - DEH_MAPPING("Death frame", deathstate) - DEH_MAPPING("Exploding frame", xdeathstate) - DEH_MAPPING("Death sound", deathsound) - DEH_MAPPING("Speed", speed) - DEH_MAPPING("Width", radius) - DEH_MAPPING("Height", height) - DEH_MAPPING("Mass", mass) - DEH_MAPPING("Missile damage", damage) - DEH_MAPPING("Action sound", activesound) - DEH_MAPPING("Bits 1", flags) - DEH_MAPPING("Bits 2", flags2) -DEH_END_MAPPING - -static void *DEH_ThingStart(deh_context_t *context, char *line) -{ - int orig_thing_number = 0, thing_number = 0; - mobjinfo_t *mobj; - - if (sscanf(line, "Thing %i", &orig_thing_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - // Translate to the correct thing number based on the exe version this - // patch was made for. Subtract one because HHE thing numbers are - // indexed from 1. - - thing_number = DEH_MapHereticThingType(orig_thing_number - 1); - - if (thing_number < 0 || thing_number >= DEH_HERETIC_NUMMOBJTYPES) - { - DEH_Warning(context, "Invalid thing number: %i", orig_thing_number); - return NULL; - } - - mobj = &mobjinfo[thing_number]; - - return mobj; -} - -static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) -{ - mobjinfo_t *mobj; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; - - mobj = (mobjinfo_t *) tag; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - // all values are integers - - ivalue = atoi(value); - - // If the value to be set is a frame, the frame number must - // undergo transformation from a Heretic 1.0 index to a - // Heretic 1.3 index. - - if (M_StrCaseStr(variable_name, "frame") != NULL) - { - ivalue = DEH_MapHereticFrameNumber(ivalue); - } - - // Set the field value - - DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); -} - -static void DEH_ThingSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include -#include - -#include "doomtype.h" -#include "m_misc.h" - -#include "doomdef.h" - -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_mapping.h" -#include "deh_htic.h" - -DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t) - DEH_MAPPING("Ammo type", ammo) - DEH_MAPPING("Deselect frame", upstate) - DEH_MAPPING("Select frame", downstate) - DEH_MAPPING("Bobbing frame", readystate) - DEH_MAPPING("Shooting frame", atkstate) - DEH_MAPPING("Firing frame", holdatkstate) - DEH_MAPPING("Unknown frame", flashstate) -DEH_END_MAPPING - -static void *DEH_WeaponStart(deh_context_t *context, char *line) -{ - int weapon_number = 0; - - if (sscanf(line, "Weapon %i", &weapon_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (weapon_number < 0 || weapon_number >= NUMWEAPONS * 2) - { - DEH_Warning(context, "Invalid weapon number: %i", weapon_number); - return NULL; - } - - // Because of the tome of power, we have two levels of weapons: - - if (weapon_number < NUMWEAPONS) - { - return &wpnlev1info[weapon_number]; - } - else - { - return &wpnlev2info[weapon_number - NUMWEAPONS]; - } -} - -static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) -{ - char *variable_name, *value; - weaponinfo_t *weapon; - int ivalue; - - if (tag == NULL) - return; - - weapon = (weaponinfo_t *) tag; - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - ivalue = atoi(value); - - // If this is a frame field, we need to map from Heretic 1.0 frame - // numbers to Heretic 1.3 frame numbers. - - if (M_StrCaseStr(variable_name, "frame") != NULL) - { - ivalue = DEH_MapHereticFrameNumber(ivalue); - } - - DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); -} - -static void DEH_WeaponSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include -//haleyjd: removed WATCOMC -#include - -#define HERETIC_VERSION 130 -#define HERETIC_VERSION_TEXT "v1.3" - -// if rangecheck is undefined, most parameter validation debugging code -// will not be compiled -//#define RANGECHECK - -// all external data is defined here -#include "doomdata.h" - -// all important printed strings -#include "dstrings.h" - -// header generated by multigen utility -#include "info.h" - -// WAD file access -#include "w_wad.h" - -// fixed_t -#include "m_fixed.h" - -// angle_t -#include "tables.h" - -// events -#include "d_event.h" - -// gamemode/mission -#include "d_mode.h" - -// ticcmd_t -#include "d_ticcmd.h" - -#include "d_loop.h" - -#define SAVEGAMENAME "hticsav" - -/* -=============================================================================== - - GLOBAL TYPES - -=============================================================================== -*/ - -#define NUMARTIFCTS 28 -#define MAXPLAYERS 4 - -#define BT_ATTACK 1 -#define BT_USE 2 -#define BT_CHANGE 4 // if true, the next 3 bits hold weapon num -#define BT_WEAPONMASK (8+16+32) -#define BT_WEAPONSHIFT 3 - -#define BT_SPECIAL 128 // game events, not really buttons -#define BTS_SAVEMASK (4+8+16) -#define BTS_SAVESHIFT 2 -#define BT_SPECIALMASK 3 -#define BTS_PAUSE 1 // pause the game -#define BTS_SAVEGAME 2 // save the game at each console -// savegame slot numbers occupy the second byte of buttons - -typedef enum -{ - GS_LEVEL, - GS_INTERMISSION, - GS_FINALE, - GS_DEMOSCREEN -} gamestate_t; - -typedef enum -{ - ga_nothing, - ga_loadlevel, - ga_newgame, - ga_loadgame, - ga_savegame, - ga_playdemo, - ga_completed, - ga_victory, - ga_worlddone, - ga_screenshot -} gameaction_t; - -typedef enum -{ - wipe_0, - wipe_1, - wipe_2, - wipe_3, - wipe_4, - NUMWIPES, - wipe_random -} wipe_t; - -/* -=============================================================================== - - MAPOBJ DATA - -=============================================================================== -*/ - - -struct thinker_s; - -// think_t is a function pointer to a routine to handle an actor -typedef void (*think_t) (struct thinker_s *); - -typedef struct thinker_s -{ - struct thinker_s *prev, *next; - think_t function; -} thinker_t; - -typedef union -{ - int i; - struct mobj_s *m; -} specialval_t; - -struct player_s; - -typedef struct mobj_s -{ - thinker_t thinker; // thinker links - -// info for drawing - fixed_t x, y, z; - struct mobj_s *snext, *sprev; // links in sector (if needed) - angle_t angle; - spritenum_t sprite; // used to find patch_t and flip value - int frame; // might be ord with FF_FULLBRIGHT - -// interaction info - struct mobj_s *bnext, *bprev; // links in blocks (if needed) - struct subsector_s *subsector; - fixed_t floorz, ceilingz; // closest together of contacted secs - fixed_t radius, height; // for movement checking - fixed_t momx, momy, momz; // momentums - - int validcount; // if == validcount, already checked - - mobjtype_t type; - mobjinfo_t *info; // &mobjinfo[mobj->type] - int tics; // state tic counter - state_t *state; - int damage; // For missiles - int flags; - int flags2; // Heretic flags - specialval_t special1; // Special info - specialval_t special2; // Special info - int health; - int movedir; // 0-7 - int movecount; // when 0, select a new dir - struct mobj_s *target; // thing being chased/attacked (or NULL) - // also the originator for missiles - int reactiontime; // if non 0, don't attack yet - // used by player to freeze a bit after - // teleporting - int threshold; // if >0, the target will be chased - // no matter what (even if shot) - struct player_s *player; // only valid if type == MT_PLAYER - int lastlook; // player number last looked for - - mapthing_t spawnpoint; // for nightmare respawn -} mobj_t; - -// each sector has a degenmobj_t in it's center for sound origin purposes -typedef struct -{ - thinker_t thinker; // not used for anything - fixed_t x, y, z; -} degenmobj_t; - -// -// frame flags -// -#define FF_FULLBRIGHT 0x8000 // flag in thing->frame -#define FF_FRAMEMASK 0x7fff - -// --- mobj.flags --- - -#define MF_SPECIAL 1 // call P_SpecialThing when touched -#define MF_SOLID 2 -#define MF_SHOOTABLE 4 -#define MF_NOSECTOR 8 // don't use the sector links - // (invisible but touchable) -#define MF_NOBLOCKMAP 16 // don't use the blocklinks - // (inert but displayable) -#define MF_AMBUSH 32 -#define MF_JUSTHIT 64 // try to attack right back -#define MF_JUSTATTACKED 128 // take at least one step before attacking -#define MF_SPAWNCEILING 256 // hang from ceiling instead of floor -#define MF_NOGRAVITY 512 // don't apply gravity every tic - -// movement flags -#define MF_DROPOFF 0x400 // allow jumps from high places -#define MF_PICKUP 0x800 // for players to pick up items -#define MF_NOCLIP 0x1000 // player cheat -#define MF_SLIDE 0x2000 // keep info about sliding along walls -#define MF_FLOAT 0x4000 // allow moves to any height, no gravity -#define MF_TELEPORT 0x8000 // don't cross lines or look at heights -#define MF_MISSILE 0x10000 // don't hit same species, explode on block - -#define MF_DROPPED 0x20000 // dropped by a demon, not level spawned -#define MF_SHADOW 0x40000 // use translucent draw (shadow demons / invis) -#define MF_NOBLOOD 0x80000 // don't bleed when shot (use puff) -#define MF_CORPSE 0x100000 // don't stop moving halfway off a step -#define MF_INFLOAT 0x200000 // floating to a height for a move, don't - // auto float to target's height - -#define MF_COUNTKILL 0x400000 // count towards intermission kill total -#define MF_COUNTITEM 0x800000 // count towards intermission item total - -#define MF_SKULLFLY 0x1000000 // skull in flight -#define MF_NOTDMATCH 0x2000000 // don't spawn in death match (key cards) - -#define MF_TRANSLATION 0xc000000 // if 0x4 0x8 or 0xc, use a translation -#define MF_TRANSSHIFT 26 // table for player colormaps - -// --- mobj.flags2 --- - -#define MF2_LOGRAV 0x00000001 // alternate gravity setting -#define MF2_WINDTHRUST 0x00000002 // gets pushed around by the wind - // specials -#define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor -#define MF2_THRUGHOST 0x00000008 // missile will pass through ghosts -#define MF2_FLY 0x00000010 // fly mode is active -#define MF2_FOOTCLIP 0x00000020 // if feet are allowed to be clipped -#define MF2_SPAWNFLOAT 0x00000040 // spawn random float z -#define MF2_NOTELEPORT 0x00000080 // does not teleport -#define MF2_RIP 0x00000100 // missile rips through solid - // targets -#define MF2_PUSHABLE 0x00000200 // can be pushed by other moving - // mobjs -#define MF2_SLIDE 0x00000400 // slides against walls -#define MF2_ONMOBJ 0x00000800 // mobj is resting on top of another - // mobj -#define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, - // this flag will allow the mobj to - // pass over/under other mobjs. -#define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs -#define MF2_FEETARECLIPPED 0x00004000 // a mobj's feet are now being cut -#define MF2_BOSS 0x00008000 // mobj is a major boss -#define MF2_FIREDAMAGE 0x00010000 // does fire damage -#define MF2_NODMGTHRUST 0x00020000 // does not thrust target when - // damaging -#define MF2_TELESTOMP 0x00040000 // mobj can stomp another -#define MF2_FLOATBOB 0x00080000 // use float bobbing z movement -#define MF2_DONTDRAW 0X00100000 // don't generate a vissprite - -//============================================================================= -typedef enum -{ - PST_LIVE, // playing - PST_DEAD, // dead on the ground - PST_REBORN // ready to restart -} playerstate_t; - -// psprites are scaled shapes directly on the view screen -// coordinates are given for a 320*200 view screen -typedef enum -{ - ps_weapon, - ps_flash, - NUMPSPRITES -} psprnum_t; - -typedef struct pspdef_s -{ - state_t *state; // a NULL state means not active - int tics; - fixed_t sx, sy; -} pspdef_t; - -typedef enum -{ - key_yellow, - key_green, - key_blue, - NUM_KEY_TYPES -} keytype_t; - -typedef enum -{ - wp_staff, - wp_goldwand, - wp_crossbow, - wp_blaster, - wp_skullrod, - wp_phoenixrod, - wp_mace, - wp_gauntlets, - wp_beak, - NUMWEAPONS, - wp_nochange -} weapontype_t; - -#define AMMO_GWND_WIMPY 10 -#define AMMO_GWND_HEFTY 50 -#define AMMO_CBOW_WIMPY 5 -#define AMMO_CBOW_HEFTY 20 -#define AMMO_BLSR_WIMPY 10 -#define AMMO_BLSR_HEFTY 25 -#define AMMO_SKRD_WIMPY 20 -#define AMMO_SKRD_HEFTY 100 -#define AMMO_PHRD_WIMPY 1 -#define AMMO_PHRD_HEFTY 10 -#define AMMO_MACE_WIMPY 20 -#define AMMO_MACE_HEFTY 100 - -typedef enum -{ - am_goldwand, - am_crossbow, - am_blaster, - am_skullrod, - am_phoenixrod, - am_mace, - NUMAMMO, - am_noammo // staff, gauntlets -} ammotype_t; - -typedef struct -{ - ammotype_t ammo; - int upstate; - int downstate; - int readystate; - int atkstate; - int holdatkstate; - int flashstate; -} weaponinfo_t; - -extern weaponinfo_t wpnlev1info[NUMWEAPONS]; -extern weaponinfo_t wpnlev2info[NUMWEAPONS]; - -typedef enum -{ - arti_none, - arti_invulnerability, - arti_invisibility, - arti_health, - arti_superhealth, - arti_tomeofpower, - arti_torch, - arti_firebomb, - arti_egg, - arti_fly, - arti_teleport, - NUMARTIFACTS -} artitype_t; - -typedef enum -{ - pw_None, - pw_invulnerability, - pw_invisibility, - pw_allmap, - pw_infrared, - pw_weaponlevel2, - pw_flight, - pw_shield, - pw_health2, - NUMPOWERS -} powertype_t; - -#define INVULNTICS (30*35) -#define INVISTICS (60*35) -#define INFRATICS (120*35) -#define IRONTICS (60*35) -#define WPNLEV2TICS (40*35) -#define FLIGHTTICS (60*35) - -#define CHICKENTICS (40*35) - -#define MESSAGETICS (4*35) -#define BLINKTHRESHOLD (4*32) - -#define NUMINVENTORYSLOTS 14 -typedef struct -{ - int type; - int count; -} inventory_t; - -/* -================ -= -= player_t -= -================ -*/ - -typedef struct player_s -{ - mobj_t *mo; - playerstate_t playerstate; - ticcmd_t cmd; - - fixed_t viewz; // focal origin above r.z - fixed_t viewheight; // base height above floor for viewz - fixed_t deltaviewheight; // squat speed - fixed_t bob; // bounded/scaled total momentum - - int flyheight; - int lookdir; - boolean centering; - int health; // only used between levels, mo->health - // is used during levels - int armorpoints, armortype; // armor type is 0-2 - - inventory_t inventory[NUMINVENTORYSLOTS]; - artitype_t readyArtifact; - int artifactCount; - int inventorySlotNum; - int powers[NUMPOWERS]; - boolean keys[NUM_KEY_TYPES]; - boolean backpack; - signed int frags[MAXPLAYERS]; // kills of other players - weapontype_t readyweapon; - weapontype_t pendingweapon; // wp_nochange if not changing - boolean weaponowned[NUMWEAPONS]; - int ammo[NUMAMMO]; - int maxammo[NUMAMMO]; - int attackdown, usedown; // true if button down last tic - int cheats; // bit flags - - int refire; // refired shots are less accurate - - int killcount, itemcount, secretcount; // for intermission - const char *message; // hint messages - int messageTics; // counter for showing messages - int damagecount, bonuscount; // for screen flashing - int flamecount; // for flame thrower duration - mobj_t *attacker; // who did damage (NULL for floors) - int extralight; // so gun flashes light up areas - int fixedcolormap; // can be set to REDCOLORMAP, etc - int colormap; // 0-3 for which color to draw player - pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) - boolean didsecret; // true if secret level has been done - int chickenTics; // player is a chicken if > 0 - int chickenPeck; // chicken peck countdown - mobj_t *rain1; // active rain maker 1 - mobj_t *rain2; // active rain maker 2 -} player_t; - -#define CF_NOCLIP 1 -#define CF_GODMODE 2 -#define CF_NOMOMENTUM 4 // not really a cheat, just a debug aid - -#define SBARHEIGHT 42 // status bar height at bottom of screen - - -/* -=============================================================================== - - GLOBAL VARIABLES - -=============================================================================== -*/ - -#define TELEFOGHEIGHT (32*FRACUNIT) - -extern gameaction_t gameaction; - -extern boolean paused; - -extern GameMode_t gamemode; - -extern boolean ExtendedWAD; // true if main WAD is the extended version - -extern boolean nomonsters; // checkparm of -nomonsters - -extern boolean respawnparm; // checkparm of -respawn - -extern boolean debugmode; // checkparm of -debug - -extern boolean usergame; // ok to save / end game - -extern boolean ravpic; // checkparm of -ravpic - -extern boolean altpal; // checkparm to use an alternate palette routine - -extern boolean cdrom; // true if cd-rom mode active ("-cdrom") - -extern boolean noartiskip; // whether shift-enter skips an artifact - -extern boolean viewactive; - -extern boolean deathmatch; // only if started as net death - -extern boolean netgame; // only true if >1 player - -extern boolean playeringame[MAXPLAYERS]; - -extern int consoleplayer; // player taking events and displaying - -extern int displayplayer; - -extern int viewangleoffset; // ANG90 = left side, ANG270 = right - -extern player_t players[MAXPLAYERS]; - -extern boolean DebugSound; // debug flag for displaying sound info - -extern int GetWeaponAmmo[NUMWEAPONS]; - -extern boolean demorecording; -extern boolean demoplayback; -extern boolean demoextend; // allow demos to persist through exit/respawn -extern int skytexture; - -// Truncate angleturn in ticcmds to nearest 256. -// Used when recording Vanilla demos in netgames. -extern boolean lowres_turn; - -extern gamestate_t gamestate; -extern skill_t gameskill; -extern boolean respawnmonsters; -extern int gameepisode; -extern int gamemap; -extern int prevmap; -extern int totalkills, totalitems, totalsecret; // for intermission -extern int levelstarttic; // gametic at level start -extern int leveltime; // tics in game play for par - -extern ticcmd_t *netcmds; - -#define SAVEGAMESIZE 0x30000 -#define SAVESTRINGSIZE 24 - -extern mapthing_t *deathmatch_p; -extern mapthing_t deathmatchstarts[10]; -extern mapthing_t playerstarts[MAXPLAYERS]; -extern boolean playerstartsingame[MAXPLAYERS]; - -extern int mouseSensitivity; - -extern boolean precache; // if true, load all graphics at level load - -extern boolean singledemo; // quit after playing a demo from cmdline - -extern int bodyqueslot; -extern skill_t startskill; -extern int startepisode; -extern int startmap; -extern boolean autostart; -extern boolean advancedemo; - -extern boolean testcontrols; -extern int testcontrols_mousespeed; - -extern int vanilla_savegame_limit; -extern int vanilla_demo_limit; - -/* -=============================================================================== - - GLOBAL FUNCTIONS - -=============================================================================== -*/ - -#include "z_zone.h" - -//---------- -//BASE LEVEL -//---------- -void D_DoomMain(void); -void CheckAbortStartup(void); -void IncThermo(void); -void InitThermo(int max); -void tprintf(const char *string, int initflag); -// not a globally visible function, just included for source reference -// calls all startup code -// parses command line options -// if not overrided, calls N_AdvanceDemo - -void D_DoomLoop(void); -// not a globally visible function, just included for source reference -// called by D_DoomMain, never exits -// manages timing and IO -// calls all ?_Responder, ?_Ticker, and ?_Drawer functions -// calls I_GetTime, I_StartFrame, and I_StartTic - -void D_StartTitle(void); - - -//--------- -//SYSTEM IO -//--------- -byte *I_AllocLow(int length); -// allocates from low memory under dos, just mallocs under unix - -// haleyjd: was WATCOMC, preserved for historical interest. -// This is similar to the -control structure in DOOM v1.4 and Strife. -#if 0 -extern boolean useexterndriver; - -#define EBT_FIRE 1 -#define EBT_OPENDOOR 2 -#define EBT_SPEED 4 -#define EBT_STRAFE 8 -#define EBT_MAP 0x10 -#define EBT_INVENTORYLEFT 0x20 -#define EBT_INVENTORYRIGHT 0x40 -#define EBT_USEARTIFACT 0x80 -#define EBT_FLYDROP 0x100 -#define EBT_CENTERVIEW 0x200 -#define EBT_PAUSE 0x400 -#define EBT_WEAPONCYCLE 0x800 - -typedef struct -{ - short vector; // Interrupt vector - - signed char moveForward; // forward/backward (maxes at 50) - signed char moveSideways; // strafe (maxes at 24) - short angleTurn; // turning speed (640 [slow] 1280 [fast]) - short angleHead; // head angle (+2080 [left] : 0 [center] : -2048 [right]) - signed char pitch; // look up/down (-110 : +90) - signed char flyDirection; // flyheight (+1/-1) - unsigned short buttons; // EBT_* flags -} externdata_t; -#endif - -//---- -//GAME -//---- - -void G_DeathMatchSpawnPlayer(int playernum); - -void G_InitNew(skill_t skill, int episode, int map); - -void G_DeferedInitNew(skill_t skill, int episode, int map); -// can be called by the startup code or M_Responder -// a normal game starts at map 1, but a warp test can start elsewhere - -void G_DeferedPlayDemo(const char *demo); - -void G_LoadGame(char *name); -// can be called by the startup code or M_Responder -// calls P_SetupLevel or W_EnterWorld -void G_DoLoadGame(void); - -void G_SaveGame(int slot, char *description); -// called by M_Responder - -#define SAVE_GAME_TERMINATOR 0x1d -// Support routines for saving games -char *SV_Filename(int slot); -void SV_Open(char *fileName); -void SV_OpenRead(char *fileName); -void SV_WriteSaveGameEOF(void); -void SV_Close(void); -void SV_Write(void *buffer, int size); -void SV_WriteByte(byte val); -void SV_WriteWord(unsigned short val); -void SV_WriteLong(unsigned int val); -void SV_Read(void *buffer, int size); -byte SV_ReadByte(void); -uint16_t SV_ReadWord(void); -uint32_t SV_ReadLong(void); - -extern char *savegamedir; - -void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, - const char *name); -// only called by startup code - -void G_PlayDemo(char *name); -void G_TimeDemo(char *name); -boolean G_CheckDemoStatus(void); -void D_DoAdvanceDemo(void); - -void G_ExitLevel(void); -void G_SecretExitLevel(void); - -void D_ProcessEvents(void); - -void G_WorldDone(void); - -void G_BuildTiccmd(ticcmd_t *cmd, int maketic); - -void G_Ticker(void); -boolean G_Responder(event_t * ev); - -void G_ScreenShot(void); - -//----- -//PLAY -//----- - -extern lumpinfo_t *maplumpinfo; - -void P_Ticker(void); -// called by C_Ticker -// can call G_PlayerExited -// carries out all thinking of monsters and players - -void P_SetupLevel(int episode, int map, int playermask, skill_t skill); -// called by W_Ticker - -void P_Init(void); -// called by startup code - -void P_ArchivePlayers(void); -void P_UnArchivePlayers(void); -void P_ArchiveWorld(void); -void P_UnArchiveWorld(void); -void P_ArchiveThinkers(void); -void P_UnArchiveThinkers(void); -void P_ArchiveSpecials(void); -void P_UnArchiveSpecials(void); -// load / save game routines - - -//------- -//REFRESH -//------- - -extern boolean setsizeneeded; - -extern boolean BorderNeedRefresh; -extern boolean BorderTopRefresh; - -extern int UpdateState; -// define the different areas for the dirty map -#define I_NOUPDATE 0 -#define I_FULLVIEW 1 -#define I_STATBAR 2 -#define I_MESSAGES 4 -#define I_FULLSCRN 8 - -void R_RenderPlayerView(player_t * player); -// called by G_Drawer - -void R_Init(void); -// called by startup code - -void R_DrawViewBorder(void); -void R_DrawTopBorder(void); -// if the view size is not full screen, draws a border around it - -void R_SetViewSize(int blocks, int detail); -// called by M_Responder - -int R_FlatNumForName(const char *name); - -int R_TextureNumForName(const char *name); -int R_CheckTextureNumForName(const char *name); -// called by P_Ticker for switches and animations -// returns the texture number for the texture name - - -//---- -//MISC -//---- -// returns the position of the given parameter in the arg list (0 if not found) - -int M_DrawText(int x, int y, boolean direct, char *string); - -//---------------------- -// Interlude (IN_lude.c) -//---------------------- - -extern boolean intermission; - -void IN_Start(void); -void IN_Ticker(void); -void IN_Drawer(void); - -//---------------------- -// Chat mode (CT_chat.c) -//---------------------- - -void CT_Init(void); -void CT_Drawer(void); -boolean CT_Responder(event_t * ev); -void CT_Ticker(void); -char CT_dequeueChatChar(void); - -extern boolean chatmodeon; -extern boolean ultimatemsg; - -//-------------------- -// Finale (F_finale.c) -//-------------------- - -void F_Drawer(void); -void F_Ticker(void); -void F_StartFinale(void); - -//---------------------- -// STATUS BAR (SB_bar.c) -//---------------------- - - -extern boolean inventory; -extern int curpos; -extern int inv_ptr; -extern int playerkeys; - - -void SB_Init(void); -boolean SB_Responder(event_t * event); -void SB_Ticker(void); -void SB_Drawer(void); - -//----------------- -// MENU (MN_menu.c) -//----------------- - -extern boolean askforquit; -extern boolean MenuActive; - -void MN_Init(void); -void MN_ActivateMenu(void); -void MN_DeactivateMenu(void); -boolean MN_Responder(event_t * event); -void MN_Ticker(void); -void MN_Drawer(void); -void MN_DrTextA(const char *text, int x, int y); -int MN_TextAWidth(const char *text); -void MN_DrTextB(const char *text, int x, int y); -int MN_TextBWidth(const char *text); - -#include "sounds.h" - -#endif // __DOOMDEF__ diff --git a/games/NXDoom/src/heretic/dstrings.h b/games/NXDoom/src/heretic/dstrings.h deleted file mode 100644 index 54bb97607c0..00000000000 --- a/games/NXDoom/src/heretic/dstrings.h +++ /dev/null @@ -1,244 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// DStrings.h - -//--------------------------------------------------------------------------- -// -// P_inter.c -// -//--------------------------------------------------------------------------- - -// Keys - -#define TXT_GOTBLUEKEY "BLUE KEY" -#define TXT_GOTYELLOWKEY "YELLOW KEY" -#define TXT_GOTGREENKEY "GREEN KEY" - -// Artifacts - -#define TXT_ARTIHEALTH "QUARTZ FLASK" -#define TXT_ARTIFLY "WINGS OF WRATH" -#define TXT_ARTIINVULNERABILITY "RING OF INVINCIBILITY" -#define TXT_ARTITOMEOFPOWER "TOME OF POWER" -#define TXT_ARTIINVISIBILITY "SHADOWSPHERE" -#define TXT_ARTIEGG "MORPH OVUM" -#define TXT_ARTISUPERHEALTH "MYSTIC URN" -#define TXT_ARTITORCH "TORCH" -#define TXT_ARTIFIREBOMB "TIME BOMB OF THE ANCIENTS" -#define TXT_ARTITELEPORT "CHAOS DEVICE" - -// Items - -#define TXT_ITEMHEALTH "CRYSTAL VIAL" -#define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING" -#define TXT_ITEMSHIELD1 "SILVER SHIELD" -#define TXT_ITEMSHIELD2 "ENCHANTED SHIELD" -#define TXT_ITEMSUPERMAP "MAP SCROLL" - -// Ammo - -#define TXT_AMMOGOLDWAND1 "WAND CRYSTAL" -#define TXT_AMMOGOLDWAND2 "CRYSTAL GEODE" -#define TXT_AMMOMACE1 "MACE SPHERES" -#define TXT_AMMOMACE2 "PILE OF MACE SPHERES" -#define TXT_AMMOCROSSBOW1 "ETHEREAL ARROWS" -#define TXT_AMMOCROSSBOW2 "QUIVER OF ETHEREAL ARROWS" -#define TXT_AMMOBLASTER1 "CLAW ORB" -#define TXT_AMMOBLASTER2 "ENERGY ORB" -#define TXT_AMMOSKULLROD1 "LESSER RUNES" -#define TXT_AMMOSKULLROD2 "GREATER RUNES" -#define TXT_AMMOPHOENIXROD1 "FLAME ORB" -#define TXT_AMMOPHOENIXROD2 "INFERNO ORB" - -// Weapons - -#define TXT_WPNMACE "FIREMACE" -#define TXT_WPNCROSSBOW "ETHEREAL CROSSBOW" -#define TXT_WPNBLASTER "DRAGON CLAW" -#define TXT_WPNSKULLROD "HELLSTAFF" -#define TXT_WPNPHOENIXROD "PHOENIX ROD" -#define TXT_WPNGAUNTLETS "GAUNTLETS OF THE NECROMANCER" - -//--------------------------------------------------------------------------- -// -// SB_bar.c -// -//--------------------------------------------------------------------------- - -#define TXT_CHEATGODON "GOD MODE ON" -#define TXT_CHEATGODOFF "GOD MODE OFF" -#define TXT_CHEATNOCLIPON "NO CLIPPING ON" -#define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF" -#define TXT_CHEATWEAPONS "ALL WEAPONS" -#define TXT_CHEATFLIGHTON "FLIGHT ON" -#define TXT_CHEATFLIGHTOFF "FLIGHT OFF" -#define TXT_CHEATPOWERON "POWER ON" -#define TXT_CHEATPOWEROFF "POWER OFF" -#define TXT_CHEATHEALTH "FULL HEALTH" -#define TXT_CHEATKEYS "ALL KEYS" -#define TXT_CHEATSOUNDON "SOUND DEBUG ON" -#define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF" -#define TXT_CHEATTICKERON "TICKER ON" -#define TXT_CHEATTICKEROFF "TICKER OFF" -#define TXT_CHEATARTIFACTS1 "CHOOSE AN ARTIFACT ( A - J )" -#define TXT_CHEATARTIFACTS2 "HOW MANY ( 1 - 9 )" -#define TXT_CHEATARTIFACTS3 "YOU GOT IT" -#define TXT_CHEATARTIFACTSFAIL "BAD INPUT" -#define TXT_CHEATWARP "LEVEL WARP" -#define TXT_CHEATSCREENSHOT "SCREENSHOT" -#define TXT_CHEATCHICKENON "CHICKEN ON" -#define TXT_CHEATCHICKENOFF "CHICKEN OFF" -#define TXT_CHEATMASSACRE "MASSACRE" -#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!" -#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS" - -//--------------------------------------------------------------------------- -// -// P_doors.c -// -//--------------------------------------------------------------------------- - -#define TXT_NEEDBLUEKEY "YOU NEED A BLUE KEY TO OPEN THIS DOOR" -#define TXT_NEEDGREENKEY "YOU NEED A GREEN KEY TO OPEN THIS DOOR" -#define TXT_NEEDYELLOWKEY "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" - -//--------------------------------------------------------------------------- -// -// G_game.c -// -//--------------------------------------------------------------------------- - -#define TXT_GAMESAVED "GAME SAVED" - -//--------------------------------------------------------------------------- -// -// AM_map.c -// -//--------------------------------------------------------------------------- - -#define AMSTR_FOLLOWON "FOLLOW MODE ON" -#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF" - -#define AMSTR_GRIDON "Grid ON" -#define AMSTR_GRIDOFF "Grid OFF" - -#define AMSTR_MARKEDSPOT "Marked Spot" -#define AMSTR_MARKSCLEARED "All Marks Cleared" - -//--------------------------------------------------------------------------- -// -// F_finale.c -// -//--------------------------------------------------------------------------- - -#define E1TEXT "with the destruction of the iron\n"\ - "liches and their minions, the last\n"\ - "of the undead are cleared from this\n"\ - "plane of existence.\n\n"\ - "those creatures had to come from\n"\ - "somewhere, though, and you have the\n"\ - "sneaky suspicion that the fiery\n"\ - "portal of hell's maw opens onto\n"\ - "their home dimension.\n\n"\ - "to make sure that more undead\n"\ - "(or even worse things) don't come\n"\ - "through, you'll have to seal hell's\n"\ - "maw from the other side. of course\n"\ - "this means you may get stuck in a\n"\ - "very unfriendly world, but no one\n"\ - "ever said being a Heretic was easy!" - -#define E2TEXT "the mighty maulotaurs have proved\n"\ - "to be no match for you, and as\n"\ - "their steaming corpses slide to the\n"\ - "ground you feel a sense of grim\n"\ - "satisfaction that they have been\n"\ - "destroyed.\n\n"\ - "the gateways which they guarded\n"\ - "have opened, revealing what you\n"\ - "hope is the way home. but as you\n"\ - "step through, mocking laughter\n"\ - "rings in your ears.\n\n"\ - "was some other force controlling\n"\ - "the maulotaurs? could there be even\n"\ - "more horrific beings through this\n"\ - "gate? the sweep of a crystal dome\n"\ - "overhead where the sky should be is\n"\ - "certainly not a good sign...." - -#define E3TEXT "the death of d'sparil has loosed\n"\ - "the magical bonds holding his\n"\ - "creatures on this plane, their\n"\ - "dying screams overwhelming his own\n"\ - "cries of agony.\n\n"\ - "your oath of vengeance fulfilled,\n"\ - "you enter the portal to your own\n"\ - "world, mere moments before the dome\n"\ - "shatters into a million pieces.\n\n"\ - "but if d'sparil's power is broken\n"\ - "forever, why don't you feel safe?\n"\ - "was it that last shout just before\n"\ - "his death, the one that sounded\n"\ - "like a curse? or a summoning? you\n"\ - "can't really be sure, but it might\n"\ - "just have been a scream.\n\n"\ - "then again, what about the other\n"\ - "serpent riders?" - -#define E4TEXT "you thought you would return to your\n"\ - "own world after d'sparil died, but\n"\ - "his final act banished you to his\n"\ - "own plane. here you entered the\n"\ - "shattered remnants of lands\n"\ - "conquered by d'sparil. you defeated\n"\ - "the last guardians of these lands,\n"\ - "but now you stand before the gates\n"\ - "to d'sparil's stronghold. until this\n"\ - "moment you had no doubts about your\n"\ - "ability to face anything you might\n"\ - "encounter, but beyond this portal\n"\ - "lies the very heart of the evil\n"\ - "which invaded your world. d'sparil\n"\ - "might be dead, but the pit where he\n"\ - "was spawned remains. now you must\n"\ - "enter that pit in the hopes of\n"\ - "finding a way out. and somewhere,\n"\ - "in the darkest corner of d'sparil's\n"\ - "demesne, his personal bodyguards\n"\ - "await your arrival ..." - -#define E5TEXT "as the final maulotaur bellows his\n"\ - "death-agony, you realize that you\n"\ - "have never come so close to your own\n"\ - "destruction. not even the fight with\n"\ - "d'sparil and his disciples had been\n"\ - "this desperate. grimly you stare at\n"\ - "the gates which open before you,\n"\ - "wondering if they lead home, or if\n"\ - "they open onto some undreamed-of\n"\ - "horror. you find yourself wondering\n"\ - "if you have the strength to go on,\n"\ - "if nothing but death and pain await\n"\ - "you. but what else can you do, if\n"\ - "the will to fight is gone? can you\n"\ - "force yourself to continue in the\n"\ - "face of such despair? do you have\n"\ - "the courage? you find, in the end,\n"\ - "that it is not within you to\n"\ - "surrender without a fight. eyes\n"\ - "wide, you go to meet your fate." - diff --git a/games/NXDoom/src/heretic/f_finale.c b/games/NXDoom/src/heretic/f_finale.c deleted file mode 100644 index 4508bd3a3c8..00000000000 --- a/games/NXDoom/src/heretic/f_finale.c +++ /dev/null @@ -1,436 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// F_finale.c - -#include - -#include "doomdef.h" -#include "deh_str.h" -#include "i_swap.h" -#include "i_video.h" -#include "s_sound.h" -#include "v_video.h" -#include "am_map.h" - -static int finalestage; // 0 = text, 1 = art screen -static int finalecount; - -#define TEXTSPEED 3 -#define TEXTWAIT 250 - -static const char *finaletext; -static const char *finaleflat; - -static int FontABaseLump; - - -/* -======================= -= -= F_StartFinale -= -======================= -*/ - -void F_StartFinale(void) -{ - gameaction = ga_nothing; - gamestate = GS_FINALE; - viewactive = false; - automapactive = false; - players[consoleplayer].messageTics = 1; - players[consoleplayer].message = NULL; - - switch (gameepisode) - { - case 1: - finaleflat = DEH_String("FLOOR25"); - finaletext = DEH_String(E1TEXT); - break; - case 2: - finaleflat = DEH_String("FLATHUH1"); - finaletext = DEH_String(E2TEXT); - break; - case 3: - finaleflat = DEH_String("FLTWAWA2"); - finaletext = DEH_String(E3TEXT); - break; - case 4: - finaleflat = DEH_String("FLOOR28"); - finaletext = DEH_String(E4TEXT); - break; - case 5: - finaleflat = DEH_String("FLOOR08"); - finaletext = DEH_String(E5TEXT); - break; - } - - finalestage = 0; - finalecount = 0; - FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; - -// S_ChangeMusic(mus_victor, true); - S_StartSong(mus_cptd, true); -} - - - -boolean F_Responder(event_t * event) -{ - if (event->type != ev_keydown) - { - return false; - } - if (finalestage == 1 && gameepisode == 2) - { // we're showing the water pic, make any key kick to demo mode - finalestage++; - /* - memset((byte *) 0xa0000, 0, SCREENWIDTH * SCREENHEIGHT); - memset(I_VideoBuffer, 0, SCREENWIDTH * SCREENHEIGHT); - I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); - */ - return true; - } - return false; -} - - -/* -======================= -= -= F_Ticker -= -======================= -*/ - -void F_Ticker(void) -{ - finalecount++; - if (!finalestage - && finalecount > strlen(finaletext) * TEXTSPEED + TEXTWAIT) - { - finalecount = 0; - if (!finalestage) - { - finalestage = 1; - } - -// wipegamestate = -1; // force a wipe -/* - if (gameepisode == 3) - S_StartMusic (mus_bunny); -*/ - } -} - - -/* -======================= -= -= F_TextWrite -= -======================= -*/ - - -void F_TextWrite(void) -{ - byte *src, *dest; - int x, y; - int count; - const char *ch; - int c; - int cx, cy; - patch_t *w; - -// -// erase the entire screen to a tiled background -// - src = W_CacheLumpName(finaleflat, PU_CACHE); - dest = I_VideoBuffer; - for (y = 0; y < SCREENHEIGHT; y++) - { - for (x = 0; x < SCREENWIDTH / 64; x++) - { - memcpy(dest, src + ((y & 63) << 6), 64); - dest += 64; - } - if (SCREENWIDTH & 63) - { - memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); - dest += (SCREENWIDTH & 63); - } - } - -// V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); - -// -// draw some of the text onto the screen -// - cx = 20; - cy = 5; - ch = finaletext; - - count = (finalecount - 10) / TEXTSPEED; - if (count < 0) - count = 0; - for (; count; count--) - { - c = *ch++; - if (!c) - break; - if (c == '\n') - { - cx = 20; - cy += 9; - continue; - } - - c = toupper(c); - if (c < 33) - { - cx += 5; - continue; - } - - w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - if (cx + SHORT(w->width) > SCREENWIDTH) - break; - V_DrawPatch(cx, cy, w); - cx += SHORT(w->width); - } - -} - - -void F_DrawPatchCol(int x, patch_t * patch, int col) -{ - column_t *column; - byte *source, *dest, *desttop; - int count; - - column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); - desttop = I_VideoBuffer + x; - -// step through the posts in a column - - while (column->topdelta != 0xff) - { - source = (byte *) column + 3; - dest = desttop + column->topdelta * SCREENWIDTH; - count = column->length; - - while (count--) - { - *dest = *source++; - dest += SCREENWIDTH; - } - column = (column_t *) ((byte *) column + column->length + 4); - } -} - -/* -================== -= -= F_DemonScroll -= -================== -*/ - -void F_DemonScroll(void) -{ - byte *p1, *p2; - static int yval = 0; - static int nextscroll = 0; - - if (finalecount < nextscroll) - { - return; - } - p1 = W_CacheLumpName(DEH_String("FINAL1"), PU_LEVEL); - p2 = W_CacheLumpName(DEH_String("FINAL2"), PU_LEVEL); - if (finalecount < 70) - { - memcpy(I_VideoBuffer, p1, SCREENHEIGHT * SCREENWIDTH); - nextscroll = finalecount; - return; - } - if (yval < 64000) - { - memcpy(I_VideoBuffer, p2 + SCREENHEIGHT * SCREENWIDTH - yval, yval); - memcpy(I_VideoBuffer + yval, p1, SCREENHEIGHT * SCREENWIDTH - yval); - yval += SCREENWIDTH; - nextscroll = finalecount + 3; - } - else - { //else, we'll just sit here and wait, for now - memcpy(I_VideoBuffer, p2, SCREENWIDTH * SCREENHEIGHT); - } -} - -/* -================== -= -= F_DrawUnderwater -= -================== -*/ - -void F_DrawUnderwater(void) -{ - static boolean underwawa = false; - const char *lumpname; - byte *palette; - - // The underwater screen has its own palette, which is rather annoying. - // The palette doesn't correspond to the normal palette. Because of - // this, we must regenerate the lookup tables used in the video scaling - // code. - - switch (finalestage) - { - case 1: - if (!underwawa) - { - underwawa = true; - V_DrawFilledBox(0, 0, SCREENWIDTH, SCREENHEIGHT, 0); - lumpname = DEH_String("E2PAL"); - palette = W_CacheLumpName(lumpname, PU_STATIC); - I_SetPalette(palette); - W_ReleaseLumpName(lumpname); - V_DrawRawScreen(W_CacheLumpName(DEH_String("E2END"), PU_CACHE)); - } - paused = false; - MenuActive = false; - askforquit = false; - - break; - case 2: - if (underwawa) - { - lumpname = DEH_String("PLAYPAL"); - palette = W_CacheLumpName(lumpname, PU_STATIC); - I_SetPalette(palette); - W_ReleaseLumpName(lumpname); - underwawa = false; - } - V_DrawRawScreen(W_CacheLumpName(DEH_String("TITLE"), PU_CACHE)); - //D_StartTitle(); // go to intro/demo mode. - } -} - - -#if 0 -/* -================== -= -= F_BunnyScroll -= -================== -*/ - -void F_BunnyScroll(void) -{ - int scrolled, x; - patch_t *p1, *p2; - char name[10]; - int stage; - static int laststage; - - p1 = W_CacheLumpName("PFUB2", PU_LEVEL); - p2 = W_CacheLumpName("PFUB1", PU_LEVEL); - - V_MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT); - - scrolled = 320 - (finalecount - 230) / 2; - if (scrolled > 320) - scrolled = 320; - if (scrolled < 0) - scrolled = 0; - - for (x = 0; x < SCREENWIDTH; x++) - { - if (x + scrolled < 320) - F_DrawPatchCol(x, p1, x + scrolled); - else - F_DrawPatchCol(x, p2, x + scrolled - 320); - } - - if (finalecount < 1130) - return; - if (finalecount < 1180) - { - V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, 0, - W_CacheLumpName("END0", PU_CACHE)); - laststage = 0; - return; - } - - stage = (finalecount - 1180) / 5; - if (stage > 6) - stage = 6; - if (stage > laststage) - { - S_StartSound(NULL, sfx_pistol); - laststage = stage; - } - - M_snprintf(name, sizeof(name), "END%i", stage); - V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2, - W_CacheLumpName(name, PU_CACHE)); -} -#endif - -/* -======================= -= -= F_Drawer -= -======================= -*/ - -void F_Drawer(void) -{ - UpdateState |= I_FULLSCRN; - if (!finalestage) - F_TextWrite(); - else - { - switch (gameepisode) - { - case 1: - if (gamemode == shareware) - { - V_DrawRawScreen(W_CacheLumpName("ORDER", PU_CACHE)); - } - else - { - V_DrawRawScreen(W_CacheLumpName("CREDIT", PU_CACHE)); - } - break; - case 2: - F_DrawUnderwater(); - break; - case 3: - F_DemonScroll(); - break; - case 4: // Just show credits screen for extended episodes - case 5: - V_DrawRawScreen(W_CacheLumpName("CREDIT", PU_CACHE)); - break; - } - } -} diff --git a/games/NXDoom/src/heretic/g_game.c b/games/NXDoom/src/heretic/g_game.c deleted file mode 100644 index 01bcc4aebae..00000000000 --- a/games/NXDoom/src/heretic/g_game.c +++ /dev/null @@ -1,2284 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// G_game.c - -#include -#include -#include -#include "doomdef.h" -#include "doomkeys.h" -#include "deh_str.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_timer.h" -#include "i_system.h" -#include "m_argv.h" -#include "m_controls.h" -#include "m_misc.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -// Macros - -#define AM_STARTKEY 9 - -// Functions - -void G_ReadDemoTiccmd(ticcmd_t * cmd); -void G_WriteDemoTiccmd(ticcmd_t * cmd); -void G_PlayerReborn(int player); - -void G_DoReborn(int playernum); - -void G_DoLoadLevel(void); -void G_DoNewGame(void); -void G_DoPlayDemo(void); -void G_DoCompleted(void); -void G_DoVictory(void); -void G_DoWorldDone(void); -void G_DoSaveGame(void); - -void D_PageTicker(void); -void D_AdvanceDemo(void); - -static boolean InventoryMoveLeft(); -static boolean InventoryMoveRight(); - -struct -{ - int type; // mobjtype_t - int speed[2]; -} MonsterMissileInfo[] = { - { MT_IMPBALL, { 10, 20 } }, - { MT_MUMMYFX1, { 9, 18 } }, - { MT_KNIGHTAXE, { 9, 18 } }, - { MT_REDAXE, { 9, 18 } }, - { MT_BEASTBALL, { 12, 20 } }, - { MT_WIZFX1, { 18, 24 } }, - { MT_SNAKEPRO_A, { 14, 20 } }, - { MT_SNAKEPRO_B, { 14, 20 } }, - { MT_HEADFX1, { 13, 20 } }, - { MT_HEADFX3, { 10, 18 } }, - { MT_MNTRFX1, { 20, 26 } }, - { MT_MNTRFX2, { 14, 20 } }, - { MT_SRCRFX1, { 20, 28 } }, - { MT_SOR2FX1, { 20, 28 } }, - { -1, { -1, -1 } } // Terminator -}; - -gameaction_t gameaction; -gamestate_t gamestate; -skill_t gameskill; -boolean respawnmonsters; -int gameepisode; -int gamemap; -int prevmap; - -boolean paused; -boolean sendpause; // send a pause event next tic -boolean sendsave; // send a save event next tic -boolean usergame; // ok to save / end game - -boolean timingdemo; // if true, exit with report on completion -int starttime; // for comparative timing purposes - -boolean viewactive; - -boolean deathmatch; // only if started as net death -boolean netgame; // only true if packets are broadcast -boolean playeringame[MAXPLAYERS]; -player_t players[MAXPLAYERS]; - -int consoleplayer; // player taking events and displaying -int displayplayer; // view being displayed -int levelstarttic; // gametic at level start -int totalkills, totalitems, totalsecret; // for intermission - -int mouseSensitivity; - -char *demoname; -boolean demorecording; -boolean longtics; // specify high resolution turning in demos -boolean lowres_turn; -boolean shortticfix; // calculate lowres turning like doom -boolean demoplayback; -boolean netdemo; -boolean demoextend; -byte *demobuffer, *demo_p, *demoend; -boolean singledemo; // quit after playing a demo from cmdline - -boolean precache = true; // if true, load all graphics at start - -// TODO: Heretic uses 16-bit shorts for consistency? -byte consistancy[MAXPLAYERS][BACKUPTICS]; -char *savegamedir; - -boolean testcontrols = false; -int testcontrols_mousespeed; - - -// -// controls (have defaults) -// - - - -#define MAXPLMOVE 0x32 - -fixed_t forwardmove[2] = { 0x19, 0x32 }; -fixed_t sidemove[2] = { 0x18, 0x28 }; -fixed_t angleturn[3] = { 640, 1280, 320 }; // + slow turn - -static int *weapon_keys[] = -{ - &key_weapon1, - &key_weapon2, - &key_weapon3, - &key_weapon4, - &key_weapon5, - &key_weapon6, - &key_weapon7 -}; - -// Set to -1 or +1 to switch to the previous or next weapon. - -static int next_weapon = 0; - -// Used for prev/next weapon keys. - -static const struct -{ - weapontype_t weapon; - weapontype_t weapon_num; -} weapon_order_table[] = { - { wp_staff, wp_staff }, - { wp_gauntlets, wp_staff }, - { wp_goldwand, wp_goldwand }, - { wp_crossbow, wp_crossbow }, - { wp_blaster, wp_blaster }, - { wp_skullrod, wp_skullrod }, - { wp_phoenixrod, wp_phoenixrod }, - { wp_mace, wp_mace }, - { wp_beak, wp_beak }, -}; - -#define SLOWTURNTICS 6 - -#define NUMKEYS 256 -boolean gamekeydown[NUMKEYS]; -int turnheld; // for accelerative turning -int lookheld; - - -boolean mousearray[MAX_MOUSE_BUTTONS + 1]; -boolean *mousebuttons = &mousearray[1]; - // allow [-1] -int mousex, mousey; // mouse values are used once -int dclicktime, dclickstate, dclicks; -int dclicktime2, dclickstate2, dclicks2; - -#define MAX_JOY_BUTTONS 20 - -int joyxmove, joyymove; // joystick values are repeated -int joystrafemove; -int joylook; -boolean joyarray[MAX_JOY_BUTTONS + 1]; -boolean *joybuttons = &joyarray[1]; // allow [-1] - -int savegameslot; -char savedescription[32]; - -int vanilla_demo_limit = 1; - -int inventoryTics; - -// haleyjd: removed WATCOMC - -//============================================================================= -// Not used - ripped out for Heretic -/* -int G_CmdChecksum(ticcmd_t *cmd) -{ - int i; - int sum; - - sum = 0; - for(i = 0; i < sizeof(*cmd)/4-1; i++) - { - sum += ((int *)cmd)[i]; - } - return(sum); -} -*/ - -static boolean WeaponSelectable(weapontype_t weapon) -{ - if (weapon == wp_beak) - { - return false; - } - - return players[consoleplayer].weaponowned[weapon]; -} - -static int G_NextWeapon(int direction) -{ - weapontype_t weapon; - int start_i, i; - - // Find index in the table. - - if (players[consoleplayer].pendingweapon == wp_nochange) - { - weapon = players[consoleplayer].readyweapon; - } - else - { - weapon = players[consoleplayer].pendingweapon; - } - - for (i=0; i= arrlen(weapon_order_table)) { - I_Error("Internal error: weapon %d not present in weapon_order_table", weapon); - } - - // Switch weapon. Don't loop forever. - start_i = i; - do - { - i += direction; - i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); - } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon)); - - return weapon_order_table[i].weapon_num; -} - -/* -==================== -= -= G_BuildTiccmd -= -= Builds a ticcmd from all of the available inputs or reads it from the -= demo buffer. -= If recording a demo, write it out -==================== -*/ - - -boolean usearti = true; - -void G_BuildTiccmd(ticcmd_t *cmd, int maketic) -{ - int i; - boolean strafe, bstrafe; - int speed, tspeed, lspeed; - int forward, side; - int look, arti; - int flyheight; - - // haleyjd: removed externdriver crap - - memset(cmd, 0, sizeof(*cmd)); - //cmd->consistancy = - // consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS]; - cmd->consistancy = consistancy[consoleplayer][maketic % BACKUPTICS]; - -//printf ("cons: %i\n",cmd->consistancy); - - strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] - || joybuttons[joybstrafe]; - speed = joybspeed >= MAX_JOY_BUTTONS - || gamekeydown[key_speed] - || joybuttons[joybspeed] - || mousebuttons[mousebspeed]; - - // haleyjd: removed externdriver crap - - forward = side = look = arti = flyheight = 0; - -// -// use two stage accelerative turning on the keyboard and joystick -// - if (joyxmove < 0 || joyxmove > 0 - || gamekeydown[key_right] || gamekeydown[key_left] - || mousebuttons[mousebturnright] || mousebuttons[mousebturnleft]) - turnheld += ticdup; - else - turnheld = 0; - if (turnheld < SLOWTURNTICS) - tspeed = 2; // slow turn - else - tspeed = speed; - - if (gamekeydown[key_lookdown] || gamekeydown[key_lookup]) - { - lookheld += ticdup; - } - else - { - lookheld = 0; - } - if (lookheld < SLOWTURNTICS) - { - lspeed = 1; - } - else - { - lspeed = 2; - } - -// -// let movement keys cancel each other out -// - if (strafe) - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - side += sidemove[speed]; - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - side -= sidemove[speed]; - if (use_analog && joyxmove) - { - joyxmove = joyxmove * joystick_move_sensitivity / 10; - joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; - joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; - side += FixedMul(sidemove[speed], joyxmove); - } - else if (joystick_move_sensitivity) - { - if (joyxmove > 0) - side += sidemove[speed]; - if (joyxmove < 0) - side -= sidemove[speed]; - } - } - else - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - cmd->angleturn -= angleturn[tspeed]; - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - cmd->angleturn += angleturn[tspeed]; - if (use_analog && joyxmove) - { - // Cubic response curve allows for finer control when stick - // deflection is small. - joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); - joyxmove = joyxmove * joystick_turn_sensitivity / 10; - cmd->angleturn -= FixedMul(angleturn[1], joyxmove); - } - else if (joystick_turn_sensitivity) - { - if (joyxmove > 0) - cmd->angleturn -= angleturn[tspeed]; - if (joyxmove < 0) - cmd->angleturn += angleturn[tspeed]; - } - } - - if (gamekeydown[key_up]) - forward += forwardmove[speed]; - if (gamekeydown[key_down]) - forward -= forwardmove[speed]; - if (use_analog && joyymove) - { - joyymove = joyymove * joystick_move_sensitivity / 10; - joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; - joyymove = (joyymove < -FRACUNIT) ? FRACUNIT : joyymove; - forward -= FixedMul(forwardmove[speed], joyymove); - } - else if (joystick_move_sensitivity) - { - if (joyymove < 0) - forward += forwardmove[speed]; - if (joyymove > 0) - forward -= forwardmove[speed]; - } - if (gamekeydown[key_straferight] || mousebuttons[mousebstraferight] - || joybuttons[joybstraferight]) - side += sidemove[speed]; - if (gamekeydown[key_strafeleft] || mousebuttons[mousebstrafeleft] - || joybuttons[joybstrafeleft]) - side -= sidemove[speed]; - - if (use_analog && joystrafemove) - { - joystrafemove = joystrafemove * joystick_move_sensitivity / 10; - joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; - joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; - side += FixedMul(sidemove[speed], joystrafemove); - } - else if (joystick_move_sensitivity) - { - if (joystrafemove < 0) - side -= sidemove[speed]; - if (joystrafemove > 0) - side += sidemove[speed]; - } - // Look up/down/center keys - if (gamekeydown[key_lookup]) - { - look = lspeed; - } - if (gamekeydown[key_lookdown]) - { - look = -lspeed; - } - if (use_analog && joylook) - { - joylook = joylook * joystick_look_sensitivity / 10; - joylook = (joylook > FRACUNIT) ? FRACUNIT : joylook; - joylook = (joylook < -FRACUNIT) ? -FRACUNIT : joylook; - look = -FixedMul(2, joylook); - } - else if (joystick_look_sensitivity) - { - if (joylook < 0) - { - look = lspeed; - } - - if (joylook > 0) - { - look = -lspeed; - } - } - // haleyjd: removed externdriver crap - if (gamekeydown[key_lookcenter]) - { - look = TOCENTER; - } - - // haleyjd: removed externdriver crap - - // Fly up/down/drop keys - if (gamekeydown[key_flyup] || joybuttons[joybflyup]) - { - flyheight = 5; // note that the actual flyheight will be twice this - } - if (gamekeydown[key_flydown] || joybuttons[joybflydown]) - { - flyheight = -5; - } - if (gamekeydown[key_flycenter] || joybuttons[joybflycenter]) - { - flyheight = TOCENTER; - // haleyjd: removed externdriver crap - look = TOCENTER; - } - - // Use artifact key - if (gamekeydown[key_useartifact] || mousebuttons[mousebuseartifact] - || joybuttons[joybuseartifact]) - { - if (gamekeydown[key_speed] && !noartiskip) - { - if (players[consoleplayer].inventory[inv_ptr].type != arti_none) - { - gamekeydown[key_useartifact] = false; - mousebuttons[mousebuseartifact] = false; - cmd->arti = 0xff; // skip artifact code - } - } - else - { - if (inventory) - { - players[consoleplayer].readyArtifact = - players[consoleplayer].inventory[inv_ptr].type; - inventory = false; - cmd->arti = 0; - usearti = false; - } - else if (usearti) - { - cmd->arti = players[consoleplayer].inventory[inv_ptr].type; - usearti = false; - } - } - } - if (gamekeydown[key_arti_tome] && !cmd->arti - && !players[consoleplayer].powers[pw_weaponlevel2]) - { - gamekeydown[key_arti_tome] = false; - cmd->arti = arti_tomeofpower; - } - else if (gamekeydown[key_arti_quartz] && !cmd->arti - && (players[consoleplayer].mo->health < MAXHEALTH)) - { - gamekeydown[key_arti_quartz] = false; - cmd->arti = arti_health; - } - else if (gamekeydown[key_arti_urn] && !cmd->arti) - { - gamekeydown[key_arti_urn] = false; - cmd->arti = arti_superhealth; - } - else if (gamekeydown[key_arti_bomb] && !cmd->arti) - { - gamekeydown[key_arti_bomb] = false; - cmd->arti = arti_firebomb; - } - else if (gamekeydown[key_arti_ring] && !cmd->arti) - { - gamekeydown[key_arti_ring] = false; - cmd->arti = arti_invulnerability; - } - else if (gamekeydown[key_arti_chaosdevice] && !cmd->arti) - { - gamekeydown[key_arti_chaosdevice] = false; - cmd->arti = arti_teleport; - } - else if (gamekeydown[key_arti_shadowsphere] && !cmd->arti) - { - gamekeydown[key_arti_shadowsphere] = false; - cmd->arti = arti_invisibility; - } - else if (gamekeydown[key_arti_wings] && !cmd->arti) - { - gamekeydown[key_arti_wings] = false; - cmd->arti = arti_fly; - } - else if (gamekeydown[key_arti_torch] && !cmd->arti) - { - gamekeydown[key_arti_torch] = false; - cmd->arti = arti_torch; - } - else if (gamekeydown[key_arti_morph] && !cmd->arti) - { - gamekeydown[key_arti_morph] = false; - cmd->arti = arti_egg; - } - -// -// buttons -// - cmd->chatchar = CT_dequeueChatChar(); - - if (gamekeydown[key_fire] || mousebuttons[mousebfire] - || joybuttons[joybfire]) - cmd->buttons |= BT_ATTACK; - - if (gamekeydown[key_use] || joybuttons[joybuse] || mousebuttons[mousebuse]) - { - cmd->buttons |= BT_USE; - dclicks = 0; // clear double clicks if hit use button - } - - // If the previous or next weapon button is pressed, the - // next_weapon variable is set to change weapons when - // we generate a ticcmd. Choose a new weapon. - // (Can't weapon cycle when the player is a chicken) - - if (gamestate == GS_LEVEL - && players[consoleplayer].chickenTics == 0 && next_weapon != 0) - { - i = G_NextWeapon(next_weapon); - cmd->buttons |= BT_CHANGE; - cmd->buttons |= i << BT_WEAPONSHIFT; - } - else - { - for (i=0; ibuttons |= BT_CHANGE; - cmd->buttons |= i< 1) - { - dclickstate = mousebuttons[mousebforward]; - if (dclickstate) - dclicks++; - if (dclicks == 2) - { - cmd->buttons |= BT_USE; - dclicks = 0; - } - else - dclicktime = 0; - } - else - { - dclicktime += ticdup; - if (dclicktime > 20) - { - dclicks = 0; - dclickstate = 0; - } - } - - // - // strafe double click - // - - bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; - if (bstrafe != dclickstate2 && dclicktime2 > 1) - { - dclickstate2 = bstrafe; - if (dclickstate2) - dclicks2++; - if (dclicks2 == 2) - { - cmd->buttons |= BT_USE; - dclicks2 = 0; - } - else - dclicktime2 = 0; - } - else - { - dclicktime2 += ticdup; - if (dclicktime2 > 20) - { - dclicks2 = 0; - dclickstate2 = 0; - } - } - } - - if (strafe) - { - side += mousex * 2; - } - else - { - cmd->angleturn -= mousex * 0x8; - } - - // No mouse movement in previous frame? - - if (mousex == 0) - { - testcontrols_mousespeed = 0; - } - - forward += mousey; - mousex = mousey = 0; - - if (forward > MAXPLMOVE) - forward = MAXPLMOVE; - else if (forward < -MAXPLMOVE) - forward = -MAXPLMOVE; - if (side > MAXPLMOVE) - side = MAXPLMOVE; - else if (side < -MAXPLMOVE) - side = -MAXPLMOVE; - - cmd->forwardmove += forward; - cmd->sidemove += side; - if (players[consoleplayer].playerstate == PST_LIVE) - { - if (look < 0) - { - look += 16; - } - cmd->lookfly = look; - } - if (flyheight < 0) - { - flyheight += 16; - } - cmd->lookfly |= flyheight << 4; - -// -// special buttons -// - if (sendpause) - { - sendpause = false; - cmd->buttons = BT_SPECIAL | BTS_PAUSE; - } - - if (sendsave) - { - sendsave = false; - cmd->buttons = - BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT); - } - - if (lowres_turn) - { - if (shortticfix) - { - static signed short carry = 0; - signed short desired_angleturn; - - desired_angleturn = cmd->angleturn + carry; - - // round angleturn to the nearest 256 unit boundary - // for recording demos with single byte values for turn - - cmd->angleturn = (desired_angleturn + 128) & 0xff00; - - // Carry forward the error from the reduced resolution to the - // next tic, so that successive small movements can accumulate. - - carry = desired_angleturn - cmd->angleturn; - } - else - { - // truncate angleturn to the nearest 256 boundary - // for recording demos with single byte values for turn - cmd->angleturn &= 0xff00; - } - } -} - - -/* -============== -= -= G_DoLoadLevel -= -============== -*/ - -void G_DoLoadLevel(void) -{ - int i; - - levelstarttic = gametic; // for time calculation - gamestate = GS_LEVEL; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].playerstate == PST_DEAD) - players[i].playerstate = PST_REBORN; - memset(players[i].frags, 0, sizeof(players[i].frags)); - } - - P_SetupLevel(gameepisode, gamemap, 0, gameskill); - displayplayer = consoleplayer; // view the guy you are playing - gameaction = ga_nothing; - Z_CheckHeap(); - -// -// clear cmd building stuff -// - - memset(gamekeydown, 0, sizeof(gamekeydown)); - joyxmove = joyymove = joystrafemove = joylook = 0; - mousex = mousey = 0; - sendpause = sendsave = paused = false; - memset(mousearray, 0, sizeof(mousearray)); - memset(joyarray, 0, sizeof(joyarray)); - - if (testcontrols) - { - P_SetMessage(&players[consoleplayer], "PRESS ESCAPE TO QUIT.", false); - } -} - -static void SetJoyButtons(unsigned int buttons_mask) -{ - int i; - player_t* plr; - - plr = &players[consoleplayer]; - - for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; - } - usearti = true; - } - } - - joybuttons[i] = button_on; - } -} - -// If an InventoryMove*() function is called when the inventory is not active, -// it will instead activate the inventory without attempting to change the -// selected item. This action is indicated by a return value of false. -// Otherwise, it attempts to change items and will return a value of true. - -static boolean InventoryMoveLeft() -{ - inventoryTics = 5 * 35; - if (!inventory) - { - inventory = true; - return false; - } - inv_ptr--; - if (inv_ptr < 0) - { - inv_ptr = 0; - } - else - { - curpos--; - if (curpos < 0) - { - curpos = 0; - } - } - return true; -} - -static boolean InventoryMoveRight() -{ - player_t *plr; - - plr = &players[consoleplayer]; - inventoryTics = 5 * 35; - if (!inventory) - { - inventory = true; - return false; - } - inv_ptr++; - if (inv_ptr >= plr->inventorySlotNum) - { - inv_ptr--; - if (inv_ptr < 0) - inv_ptr = 0; - } - else - { - curpos++; - if (curpos > 6) - { - curpos = 6; - } - } - return true; -} - -static void SetMouseButtons(unsigned int buttons_mask) -{ - int i; - player_t *plr; - - plr = &players[consoleplayer]; - - for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; - } - usearti = true; - } - } - - mousebuttons[i] = button_on; - } -} - -/* -=============================================================================== -= -= G_Responder -= -= get info needed to make ticcmd_ts for the players -= -=============================================================================== -*/ - -boolean G_Responder(event_t * ev) -{ - player_t *plr; - - plr = &players[consoleplayer]; - if (ev->type == ev_keyup && ev->data1 == key_useartifact) - { // flag to denote that it's okay to use an artifact - if (!inventory) - { - plr->readyArtifact = plr->inventory[inv_ptr].type; - } - usearti = true; - } - - // Check for spy mode player cycle - if (gamestate == GS_LEVEL && ev->type == ev_keydown - && ev->data1 == KEY_F12 && !deathmatch) - { // Cycle the display player - do - { - displayplayer++; - if (displayplayer == MAXPLAYERS) - { - displayplayer = 0; - } - } - while (!playeringame[displayplayer] - && displayplayer != consoleplayer); - return (true); - } - - if (gamestate == GS_LEVEL) - { - if (CT_Responder(ev)) - { // Chat ate the event - return (true); - } - if (SB_Responder(ev)) - { // Status bar ate the event - return (true); - } - if (AM_Responder(ev)) - { // Automap ate the event - return (true); - } - } - - if (ev->type == ev_mouse) - { - testcontrols_mousespeed = abs(ev->data2); - } - - if (ev->type == ev_keydown && ev->data1 == key_prevweapon) - { - next_weapon = -1; - } - else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) - { - next_weapon = 1; - } - - switch (ev->type) - { - case ev_keydown: - if (ev->data1 == key_invleft) - { - if (InventoryMoveLeft()) - { - return (true); - } - break; - } - if (ev->data1 == key_invright) - { - if (InventoryMoveRight()) - { - return (true); - } - break; - } - if (ev->data1 == key_pause && !MenuActive) - { - sendpause = true; - return (true); - } - if (ev->data1 < NUMKEYS) - { - gamekeydown[ev->data1] = true; - } - return (true); // eat key down events - - case ev_keyup: - if (ev->data1 < NUMKEYS) - { - gamekeydown[ev->data1] = false; - } - return (false); // always let key up events filter down - - case ev_mouse: - SetMouseButtons(ev->data1); - mousex = ev->data2 * (mouseSensitivity + 5) / 10; - mousey = ev->data3 * (mouseSensitivity + 5) / 10; - return (true); // eat events - - case ev_joystick: - SetJoyButtons(ev->data1); - joyxmove = ev->data2; - joyymove = ev->data3; - joystrafemove = ev->data4; - joylook = ev->data5; - return (true); // eat events - - default: - break; - } - return (false); -} - -/* -=============================================================================== -= -= G_Ticker -= -=============================================================================== -*/ - -void G_Ticker(void) -{ - int i, buf; - ticcmd_t *cmd = NULL; - -// -// do player reborns if needed -// - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].playerstate == PST_REBORN) - G_DoReborn(i); - -// -// do things to change the game state -// - while (gameaction != ga_nothing) - { - switch (gameaction) - { - case ga_loadlevel: - G_DoLoadLevel(); - break; - case ga_newgame: - G_DoNewGame(); - break; - case ga_loadgame: - G_DoLoadGame(); - break; - case ga_savegame: - G_DoSaveGame(); - break; - case ga_playdemo: - G_DoPlayDemo(); - break; - case ga_screenshot: - V_ScreenShot("HTIC%02i.%s"); - gameaction = ga_nothing; - break; - case ga_completed: - G_DoCompleted(); - break; - case ga_worlddone: - G_DoWorldDone(); - break; - case ga_victory: - F_StartFinale(); - break; - default: - break; - } - } - - -// -// get commands, check consistancy, and build new consistancy check -// - //buf = gametic%BACKUPTICS; - buf = (gametic / ticdup) % BACKUPTICS; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - cmd = &players[i].cmd; - - memcpy(cmd, &netcmds[i], sizeof(ticcmd_t)); - - if (demoplayback) - G_ReadDemoTiccmd(cmd); - if (demorecording) - G_WriteDemoTiccmd(cmd); - - if (netgame && !netdemo && !(gametic % ticdup)) - { - if (gametic > BACKUPTICS - && consistancy[i][buf] != cmd->consistancy) - { - I_Error("consistency failure (%i should be %i)", - cmd->consistancy, consistancy[i][buf]); - } - if (players[i].mo) - consistancy[i][buf] = players[i].mo->x; - else - consistancy[i][buf] = rndindex; - } - } - -// -// check for special buttons -// - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - if (players[i].cmd.buttons & BT_SPECIAL) - { - switch (players[i].cmd.buttons & BT_SPECIALMASK) - { - case BTS_PAUSE: - paused ^= 1; - if (paused) - { - S_PauseSound(); - } - else - { - S_ResumeSound(); - } - break; - - case BTS_SAVEGAME: - if (!savedescription[0]) - { - if (netgame) - { - M_StringCopy(savedescription, - DEH_String("NET GAME"), - sizeof(savedescription)); - } - else - { - M_StringCopy(savedescription, - DEH_String("SAVE GAME"), - sizeof(savedescription)); - } - } - savegameslot = - (players[i].cmd. - buttons & BTS_SAVEMASK) >> BTS_SAVESHIFT; - gameaction = ga_savegame; - break; - } - } - } - // turn inventory off after a certain amount of time - if (inventory && !(--inventoryTics)) - { - players[consoleplayer].readyArtifact = - players[consoleplayer].inventory[inv_ptr].type; - inventory = false; - cmd->arti = 0; - } -// -// do main actions -// -// -// do main actions -// - switch (gamestate) - { - case GS_LEVEL: - P_Ticker(); - SB_Ticker(); - AM_Ticker(); - CT_Ticker(); - break; - case GS_INTERMISSION: - IN_Ticker(); - break; - case GS_FINALE: - F_Ticker(); - break; - case GS_DEMOSCREEN: - D_PageTicker(); - break; - } -} - - -/* -============================================================================== - - PLAYER STRUCTURE FUNCTIONS - -also see P_SpawnPlayer in P_Things -============================================================================== -*/ - -/* -==================== -= -= G_InitPlayer -= -= Called at the start -= Called by the game initialization functions -==================== -*/ - -void G_InitPlayer(int player) -{ - // clear everything else to defaults - G_PlayerReborn(player); -} - - -/* -==================== -= -= G_PlayerFinishLevel -= -= Can when a player completes a level -==================== -*/ - -void G_PlayerFinishLevel(int player) -{ - player_t *p; - int i; - -/* // BIG HACK - inv_ptr = 0; - curpos = 0; -*/ - // END HACK - p = &players[player]; - for (i = 0; i < p->inventorySlotNum; i++) - { - p->inventory[i].count = 1; - } - p->artifactCount = p->inventorySlotNum; - - if (!deathmatch) - { - for (i = 0; i < 16; i++) - { - P_PlayerUseArtifact(p, arti_fly); - } - } - memset(p->powers, 0, sizeof(p->powers)); - memset(p->keys, 0, sizeof(p->keys)); - playerkeys = 0; -// memset(p->inventory, 0, sizeof(p->inventory)); - if (p->chickenTics) - { - p->readyweapon = p->mo->special1.i; // Restore weapon - p->chickenTics = 0; - } - p->messageTics = 0; - p->lookdir = 0; - p->mo->flags &= ~MF_SHADOW; // Remove invisibility - p->extralight = 0; // Remove weapon flashes - p->fixedcolormap = 0; // Remove torch - p->damagecount = 0; // No palette changes - p->bonuscount = 0; - p->rain1 = NULL; - p->rain2 = NULL; - if (p == &players[consoleplayer]) - { - SB_state = -1; // refresh the status bar - } -} - -/* -==================== -= -= G_PlayerReborn -= -= Called after a player dies -= almost everything is cleared and initialized -==================== -*/ - -void G_PlayerReborn(int player) -{ - player_t *p; - int i; - int frags[MAXPLAYERS]; - int killcount, itemcount, secretcount; - boolean secret; - - secret = false; - memcpy(frags, players[player].frags, sizeof(frags)); - killcount = players[player].killcount; - itemcount = players[player].itemcount; - secretcount = players[player].secretcount; - - p = &players[player]; - if (p->didsecret) - { - secret = true; - } - memset(p, 0, sizeof(*p)); - - memcpy(players[player].frags, frags, sizeof(players[player].frags)); - players[player].killcount = killcount; - players[player].itemcount = itemcount; - players[player].secretcount = secretcount; - - p->usedown = p->attackdown = true; // don't do anything immediately - p->playerstate = PST_LIVE; - p->health = MAXHEALTH; - p->readyweapon = p->pendingweapon = wp_goldwand; - p->weaponowned[wp_staff] = true; - p->weaponowned[wp_goldwand] = true; - p->messageTics = 0; - p->lookdir = 0; - p->ammo[am_goldwand] = 50; - for (i = 0; i < NUMAMMO; i++) - { - p->maxammo[i] = maxammo[i]; - } - if (gamemap == 9 || secret) - { - p->didsecret = true; - } - if (p == &players[consoleplayer]) - { - SB_state = -1; // refresh the status bar - inv_ptr = 0; // reset the inventory pointer - curpos = 0; - } -} - -/* -==================== -= -= G_CheckSpot -= -= Returns false if the player cannot be respawned at the given mapthing_t spot -= because something is occupying it -==================== -*/ - -void P_SpawnPlayer(mapthing_t * mthing); - -boolean G_CheckSpot(int playernum, mapthing_t * mthing) -{ - fixed_t x, y; - subsector_t *ss; - unsigned an; - mobj_t *mo; - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - players[playernum].mo->flags2 &= ~MF2_PASSMOBJ; - if (!P_CheckPosition(players[playernum].mo, x, y)) - { - players[playernum].mo->flags2 |= MF2_PASSMOBJ; - return false; - } - players[playernum].mo->flags2 |= MF2_PASSMOBJ; - -// spawn a teleport fog - ss = R_PointInSubsector(x, y); - an = ((unsigned) ANG45 * (mthing->angle / 45)) >> ANGLETOFINESHIFT; - - mo = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an], - ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); - - if (players[consoleplayer].viewz != 1) - S_StartSound(mo, sfx_telept); // don't start sound on first frame - - return true; -} - -/* -==================== -= -= G_DeathMatchSpawnPlayer -= -= Spawns a player at one of the random death match spots -= called at level load and each death -==================== -*/ - -void G_DeathMatchSpawnPlayer(int playernum) -{ - int i, j; - int selections; - - selections = deathmatch_p - deathmatchstarts; - if (selections < 4) - I_Error("Only %i deathmatch spots, 4 required", selections); - - for (j = 0; j < 20; j++) - { - i = P_Random() % selections; - if (G_CheckSpot(playernum, &deathmatchstarts[i])) - { - deathmatchstarts[i].type = playernum + 1; - P_SpawnPlayer(&deathmatchstarts[i]); - return; - } - } - -// no good spot, so the player will probably get stuck - P_SpawnPlayer(&playerstarts[playernum]); -} - -/* -==================== -= -= G_DoReborn -= -==================== -*/ - -void G_DoReborn(int playernum) -{ - int i; - - // quit demo unless -demoextend - if (!demoextend && G_CheckDemoStatus()) - return; - if (!netgame) - gameaction = ga_loadlevel; // reload the level from scratch - else - { // respawn at the start - players[playernum].mo->player = NULL; // dissasociate the corpse - - // spawn at random spot if in death match - if (deathmatch) - { - G_DeathMatchSpawnPlayer(playernum); - return; - } - - if (G_CheckSpot(playernum, &playerstarts[playernum])) - { - P_SpawnPlayer(&playerstarts[playernum]); - return; - } - // try to spawn at one of the other players spots - for (i = 0; i < MAXPLAYERS; i++) - if (G_CheckSpot(playernum, &playerstarts[i])) - { - playerstarts[i].type = playernum + 1; // fake as other player - P_SpawnPlayer(&playerstarts[i]); - playerstarts[i].type = i + 1; // restore - return; - } - // he's going to be inside something. Too bad. - P_SpawnPlayer(&playerstarts[playernum]); - } -} - - -void G_ScreenShot(void) -{ - gameaction = ga_screenshot; -} - - -/* -==================== -= -= G_DoCompleted -= -==================== -*/ - -boolean secretexit; - -void G_ExitLevel(void) -{ - secretexit = false; - gameaction = ga_completed; -} - -void G_SecretExitLevel(void) -{ - secretexit = true; - gameaction = ga_completed; -} - -void G_DoCompleted(void) -{ - int i; - static int afterSecret[5] = { 7, 5, 5, 5, 4 }; - - gameaction = ga_nothing; - - // quit demo unless -demoextend - if (!demoextend && G_CheckDemoStatus()) - { - return; - } - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - G_PlayerFinishLevel(i); - } - } - prevmap = gamemap; - if (secretexit == true) - { - gamemap = 9; - } - else if (gamemap == 9) - { // Finished secret level - gamemap = afterSecret[gameepisode - 1]; - } - else if (gamemap == 8) - { - gameaction = ga_victory; - return; - } - else - { - gamemap++; - } - gamestate = GS_INTERMISSION; - IN_Start(); -} - -//============================================================================ -// -// G_WorldDone -// -//============================================================================ - -void G_WorldDone(void) -{ - gameaction = ga_worlddone; -} - -//============================================================================ -// -// G_DoWorldDone -// -//============================================================================ - -void G_DoWorldDone(void) -{ - gamestate = GS_LEVEL; - G_DoLoadLevel(); - gameaction = ga_nothing; - viewactive = true; -} - -//--------------------------------------------------------------------------- -// -// PROC G_LoadGame -// -// Can be called by the startup code or the menu task. -// -//--------------------------------------------------------------------------- - -static char *savename = NULL; - -void G_LoadGame(char *name) -{ - savename = M_StringDuplicate(name); - gameaction = ga_loadgame; -} - -//--------------------------------------------------------------------------- -// -// PROC G_DoLoadGame -// -// Called by G_Ticker based on gameaction. -// -//--------------------------------------------------------------------------- - -#define VERSIONSIZE 16 - -void G_DoLoadGame(void) -{ - int i; - int a, b, c; - char savestr[SAVESTRINGSIZE]; - char vcheck[VERSIONSIZE], readversion[VERSIONSIZE]; - - gameaction = ga_nothing; - - SV_OpenRead(savename); - - free(savename); - savename = NULL; - - // Skip the description field - SV_Read(savestr, SAVESTRINGSIZE); - - memset(vcheck, 0, sizeof(vcheck)); - DEH_snprintf(vcheck, VERSIONSIZE, "version %i", HERETIC_VERSION); - SV_Read(readversion, VERSIONSIZE); - - if (strncmp(readversion, vcheck, VERSIONSIZE) != 0) - { // Bad version - return; - } - gameskill = SV_ReadByte(); - gameepisode = SV_ReadByte(); - gamemap = SV_ReadByte(); - for (i = 0; i < MAXPLAYERS; i++) - { - playeringame[i] = SV_ReadByte(); - } - // Load a base level - G_InitNew(gameskill, gameepisode, gamemap); - - // Create leveltime - a = SV_ReadByte(); - b = SV_ReadByte(); - c = SV_ReadByte(); - leveltime = (a << 16) + (b << 8) + c; - - // De-archive all the modifications - P_UnArchivePlayers(); - P_UnArchiveWorld(); - P_UnArchiveThinkers(); - P_UnArchiveSpecials(); - - if (SV_ReadByte() != SAVE_GAME_TERMINATOR) - { // Missing savegame termination marker - I_Error("Bad savegame"); - } - - SV_Close(); -} - - -/* -==================== -= -= G_InitNew -= -= Can be called by the startup code or the menu task -= consoleplayer, displayplayer, playeringame[] should be set -==================== -*/ - -skill_t d_skill; -int d_episode; -int d_map; - -void G_DeferedInitNew(skill_t skill, int episode, int map) -{ - d_skill = skill; - d_episode = episode; - d_map = map; - gameaction = ga_newgame; -} - -void G_DoNewGame(void) -{ - G_InitNew(d_skill, d_episode, d_map); - gameaction = ga_nothing; -} - -void G_InitNew(skill_t skill, int episode, int map) -{ - int i; - int speed; - static const char *skyLumpNames[5] = { - "SKY1", "SKY2", "SKY3", "SKY1", "SKY3" - }; - - if (paused) - { - paused = false; - S_ResumeSound(); - } - if (skill < sk_baby) - skill = sk_baby; - if (skill > sk_nightmare) - skill = sk_nightmare; - if (episode < 1) - episode = 1; - // Up to 9 episodes for testing - if (episode > 9) - episode = 9; - if (map < 1) - map = 1; - if (map > 9) - map = 9; - M_ClearRandom(); - if (respawnparm) - { - respawnmonsters = true; - } - else - { - respawnmonsters = false; - } - // Set monster missile speeds - speed = skill == sk_nightmare; - for (i = 0; MonsterMissileInfo[i].type != -1; i++) - { - mobjinfo[MonsterMissileInfo[i].type].speed - = MonsterMissileInfo[i].speed[speed] << FRACBITS; - } - // Force players to be initialized upon first level load - for (i = 0; i < MAXPLAYERS; i++) - { - players[i].playerstate = PST_REBORN; - players[i].didsecret = false; - } - // Set up a bunch of globals - usergame = true; // will be set false if a demo - paused = false; - demorecording = false; - demoplayback = false; - netdemo = false; - viewactive = true; - gameepisode = episode; - gamemap = map; - gameskill = skill; - BorderNeedRefresh = true; - - // Set the sky map - if (episode > 5) - { - skytexture = R_TextureNumForName(DEH_String("SKY1")); - } - else - { - skytexture = R_TextureNumForName(DEH_String(skyLumpNames[episode - 1])); - } - -// -// give one null ticcmd_t -// -#if 0 - gametic = 0; - maketic = 1; - for (i = 0; i < MAXPLAYERS; i++) - nettics[i] = 1; // one null event for this gametic - memset(localcmds, 0, sizeof(localcmds)); - memset(netcmds, 0, sizeof(netcmds)); -#endif - G_DoLoadLevel(); -} - - -/* -=============================================================================== - - DEMO RECORDING - -=============================================================================== -*/ - -#define DEMOMARKER 0x80 -#define DEMOHEADER_RESPAWN 0x20 -#define DEMOHEADER_LONGTICS 0x10 -#define DEMOHEADER_NOMONSTERS 0x02 - -void G_ReadDemoTiccmd(ticcmd_t * cmd) -{ - if (*demo_p == DEMOMARKER) - { // end of demo data stream - G_CheckDemoStatus(); - return; - } - cmd->forwardmove = ((signed char) *demo_p++); - cmd->sidemove = ((signed char) *demo_p++); - - // If this is a longtics demo, read back in higher resolution - - if (longtics) - { - cmd->angleturn = *demo_p++; - cmd->angleturn |= (*demo_p++) << 8; - } - else - { - cmd->angleturn = ((unsigned char) *demo_p++) << 8; - } - - cmd->buttons = (unsigned char) *demo_p++; - cmd->lookfly = (unsigned char) *demo_p++; - cmd->arti = (unsigned char) *demo_p++; -} - -// Increase the size of the demo buffer to allow unlimited demos - -static void IncreaseDemoBuffer(void) -{ - int current_length; - byte *new_demobuffer; - byte *new_demop; - int new_length; - - // Find the current size - - current_length = demoend - demobuffer; - - // Generate a new buffer twice the size - new_length = current_length * 2; - - new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); - new_demop = new_demobuffer + (demo_p - demobuffer); - - // Copy over the old data - - memcpy(new_demobuffer, demobuffer, current_length); - - // Free the old buffer and point the demo pointers at the new buffer. - - Z_Free(demobuffer); - - demobuffer = new_demobuffer; - demo_p = new_demop; - demoend = demobuffer + new_length; -} - -void G_WriteDemoTiccmd(ticcmd_t * cmd) -{ - byte *demo_start; - - if (gamekeydown[key_demo_quit]) // press to end demo recording - G_CheckDemoStatus(); - - demo_start = demo_p; - - *demo_p++ = cmd->forwardmove; - *demo_p++ = cmd->sidemove; - - // If this is a longtics demo, record in higher resolution - - if (longtics) - { - *demo_p++ = (cmd->angleturn & 0xff); - *demo_p++ = (cmd->angleturn >> 8) & 0xff; - } - else - { - *demo_p++ = cmd->angleturn >> 8; - } - - *demo_p++ = cmd->buttons; - *demo_p++ = cmd->lookfly; - *demo_p++ = cmd->arti; - - // reset demo pointer back - demo_p = demo_start; - - if (demo_p > demoend - 16) - { - if (vanilla_demo_limit) - { - // no more space - G_CheckDemoStatus(); - return; - } - else - { - // Vanilla demo limit disabled: unlimited - // demo lengths! - - IncreaseDemoBuffer(); - } - } - - G_ReadDemoTiccmd(cmd); // make SURE it is exactly the same -} - - - -/* -=================== -= -= G_RecordDemo -= -=================== -*/ - -void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, - const char *name) -{ - size_t demoname_size; - int i; - int maxsize; - - //! - // @category demo - // - // Record or playback a demo with high resolution turning. - // - - longtics = D_NonVanillaRecord(M_ParmExists("-longtics"), - "vvHeretic longtics demo"); - - // If not recording a longtics demo, record in low res - - lowres_turn = !longtics; - - //! - // @category demo - // - // Smooth out low resolution turning when recording a demo. - // - - shortticfix = M_ParmExists("-shortticfix"); - - G_InitNew(skill, episode, map); - usergame = false; - demoname_size = strlen(name) + 5; - demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); - M_snprintf(demoname, demoname_size, "%s.lmp", name); - maxsize = 0x20000; - - //! - // @arg - // @category demo - // @vanilla - // - // Specify the demo buffer size (KiB) - // - - i = M_CheckParmWithArgs("-maxdemo", 1); - if (i) - maxsize = atoi(myargv[i + 1]) * 1024; - demobuffer = Z_Malloc(maxsize, PU_STATIC, NULL); - demoend = demobuffer + maxsize; - - demo_p = demobuffer; - *demo_p++ = skill; - *demo_p++ = episode; - *demo_p++ = map; - - // Write special parameter bits onto player one byte. - // This aligns with vvHeretic demo usage: - // 0x20 = -respawn - // 0x10 = -longtics - // 0x02 = -nomonsters - - *demo_p = 1; // assume player one exists - if (D_NonVanillaRecord(respawnparm, "vvHeretic -respawn header flag")) - { - *demo_p |= DEMOHEADER_RESPAWN; - } - if (longtics) - { - *demo_p |= DEMOHEADER_LONGTICS; - } - if (D_NonVanillaRecord(nomonsters, "vvHeretic -nomonsters header flag")) - { - *demo_p |= DEMOHEADER_NOMONSTERS; - } - demo_p++; - - for (i = 1; i < MAXPLAYERS; i++) - *demo_p++ = playeringame[i]; - - demorecording = true; -} - - -/* -=================== -= -= G_PlayDemo -= -=================== -*/ - -static const char *defdemoname; - -void G_DeferedPlayDemo(const char *name) -{ - defdemoname = name; - gameaction = ga_playdemo; -} - -void G_DoPlayDemo(void) -{ - skill_t skill; - int i, lumpnum, episode, map; - - gameaction = ga_nothing; - lumpnum = W_GetNumForName(defdemoname); - demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC); - demo_p = demobuffer; - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - - // vvHeretic allows extra options to be stored in the upper bits of - // the player 1 present byte. However, this is a non-vanilla extension. - if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_LONGTICS) != 0, - lumpnum, "vvHeretic longtics demo")) - { - longtics = true; - } - if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_RESPAWN) != 0, - lumpnum, "vvHeretic -respawn header flag")) - { - respawnparm = true; - } - if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_NOMONSTERS) != 0, - lumpnum, "vvHeretic -nomonsters header flag")) - { - nomonsters = true; - } - - for (i = 0; i < MAXPLAYERS; i++) - playeringame[i] = (*demo_p++) != 0; - - if (playeringame[1] || M_CheckParm("-solo-net") > 0 - || M_CheckParm("-netdemo") > 0) - { - netgame = true; - } - - precache = false; // don't spend a lot of time in loadlevel - G_InitNew(skill, episode, map); - precache = true; - usergame = false; - demoplayback = true; - - if (netgame == true) - { - netdemo = true; - } -} - - -/* -=================== -= -= G_TimeDemo -= -=================== -*/ - -void G_TimeDemo(char *name) -{ - skill_t skill; - int episode, map, i; - - demobuffer = demo_p = W_CacheLumpName(name, PU_STATIC); - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - - // Read special parameter bits: see G_RecordDemo() for details. - longtics = (*demo_p & DEMOHEADER_LONGTICS) != 0; - - // don't overwrite arguments from the command line - respawnparm |= (*demo_p & DEMOHEADER_RESPAWN) != 0; - nomonsters |= (*demo_p & DEMOHEADER_NOMONSTERS) != 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - playeringame[i] = (*demo_p++) != 0; - } - - if (playeringame[1] || M_CheckParm("-solo-net") > 0 - || M_CheckParm("-netdemo") > 0) - { - netgame = true; - } - - G_InitNew(skill, episode, map); - starttime = I_GetTime(); - - usergame = false; - demoplayback = true; - timingdemo = true; - singletics = true; - - if (netgame == true) - { - netdemo = true; - } -} - - -/* -=================== -= -= G_CheckDemoStatus -= -= Called after a death or level completion to allow demos to be cleaned up -= Returns true if a new demo loop action will take place -=================== -*/ - -boolean G_CheckDemoStatus(void) -{ - int endtime, realtics; - - if (timingdemo) - { - float fps; - endtime = I_GetTime(); - realtics = endtime - starttime; - fps = ((float) gametic * TICRATE) / realtics; - I_Error("timed %i gametics in %i realtics (%f fps)", - gametic, realtics, fps); - } - - if (demoplayback) - { - if (singledemo) - I_Quit(); - - W_ReleaseLumpName(defdemoname); - demoplayback = false; - netdemo = false; - netgame = false; - D_AdvanceDemo(); - return true; - } - - if (demorecording) - { - *demo_p++ = DEMOMARKER; - M_WriteFile(demoname, demobuffer, demo_p - demobuffer); - Z_Free(demobuffer); - demorecording = false; - I_Error("Demo %s recorded", demoname); - } - - return false; -} - -/**************************************************************************/ -/**************************************************************************/ - -//========================================================================== -// -// G_SaveGame -// -// Called by the menu task. is a 24 byte text string. -// -//========================================================================== - -void G_SaveGame(int slot, char *description) -{ - savegameslot = slot; - M_StringCopy(savedescription, description, sizeof(savedescription)); - sendsave = true; -} - -//========================================================================== -// -// G_DoSaveGame -// -// Called by G_Ticker based on gameaction. -// -//========================================================================== - -void G_DoSaveGame(void) -{ - int i; - char *filename; - char verString[VERSIONSIZE]; - char *description; - - filename = SV_Filename(savegameslot); - - description = savedescription; - - SV_Open(filename); - SV_Write(description, SAVESTRINGSIZE); - memset(verString, 0, sizeof(verString)); - DEH_snprintf(verString, VERSIONSIZE, "version %i", HERETIC_VERSION); - SV_Write(verString, VERSIONSIZE); - SV_WriteByte(gameskill); - SV_WriteByte(gameepisode); - SV_WriteByte(gamemap); - for (i = 0; i < MAXPLAYERS; i++) - { - SV_WriteByte(playeringame[i]); - } - SV_WriteByte(leveltime >> 16); - SV_WriteByte(leveltime >> 8); - SV_WriteByte(leveltime); - P_ArchivePlayers(); - P_ArchiveWorld(); - P_ArchiveThinkers(); - P_ArchiveSpecials(); - SV_WriteSaveGameEOF(); - SV_Close(); - - gameaction = ga_nothing; - savedescription[0] = 0; - P_SetMessage(&players[consoleplayer], DEH_String(TXT_GAMESAVED), true); - - free(filename); -} - diff --git a/games/NXDoom/src/heretic/heretic_icon.c b/games/NXDoom/src/heretic/heretic_icon.c deleted file mode 100644 index ab8b641c856..00000000000 --- a/games/NXDoom/src/heretic/heretic_icon.c +++ /dev/null @@ -1,2736 +0,0 @@ -static int heretic_icon_w = 128; -static int heretic_icon_h = 128; - -static const unsigned int heretic_icon_data[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, - 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, - 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, - 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, - 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, - 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, - 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, - 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, - 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, - 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, - 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, - 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, - 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, - 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, - 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, - 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, - 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, - 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, - 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, - 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, - 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, - 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, - 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, - 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, - 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, - 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, - 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, - 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, - 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, - 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, - 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, - 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, - 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, - 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, - 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, - 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, - 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, - 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, - 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, - 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, - 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, - 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, - 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, - 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, - 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, - 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, - 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, - 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x93756aff, 0x91756aff, 0x968078ff, 0x99867fff, - 0x99867fff, 0x99867fff, 0x99867fff, 0x99867fff, 0x99867fff, 0xa2918bff, - 0xb5aaa6ff, 0xb5a9a5ff, 0xb5a9a5ff, 0xb4a8a4ff, 0xb4a8a4ff, 0xb3a7a3ff, - 0xb2a6a2ff, 0xb2a6a2ff, 0xb0a5a1ff, 0xa2928cff, 0x98857eff, 0x98847eff, - 0x98847eff, 0x98847eff, 0x97837dff, 0x95817bff, 0x937f79ff, 0x907d76ff, - 0x907e77ff, 0x9e908cff, 0xa09491ff, 0x9f938fff, 0x9d928eff, 0x9b8f8bff, - 0x998d89ff, 0x978c88ff, 0x968a86ff, 0x948884ff, 0x8f827eff, 0x7a6660ff, - 0x78645eff, 0x76625dff, 0x74605bff, 0x725e59ff, 0x705c57ff, 0x6e5b55ff, - 0x6c5953ff, 0x6a5751ff, 0x73625eff, 0x7f7370ff, 0x7d716eff, 0x7b6f6cff, - 0x796d6aff, 0x786c69ff, 0x766a67ff, 0x746865ff, 0x716563ff, 0x716562ff, - 0x5d4b47ff, 0x54403bff, 0x523d3aff, 0x55413fff, 0x574445ff, 0x59464aff, - 0x5b494fff, 0x5d4950ff, 0x5f464cff, 0x674e55ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, - 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, - 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, - 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, - 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, - 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, - 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, - 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, - 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, - 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, - 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, - 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, - 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, - 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, - 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, - 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, - 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, - 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, - 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, - 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, - 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, - 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xb9b8b8ff, 0xbdbdbdff, - 0xbbbbbcff, 0xbbbbbbff, 0xbab9baff, 0xb9b9baff, 0xb8b8b9ff, 0xb8b8b8ff, - 0xb7b6b7ff, 0xb0afb0ff, 0x9f9ea0ff, 0x9e9ea0ff, 0x9e9da0ff, 0x9e9d9fff, - 0x9d9c9fff, 0x9d9c9eff, 0x9c9b9eff, 0x9c9a9eff, 0x9c9a9eff, 0xa6a5a7ff, - 0xadacafff, 0xacaaadff, 0xacaaadff, 0xaaa9acff, 0xa8a7aaff, 0xa6a5a8ff, - 0xa5a3a7ff, 0xa3a2a5ff, 0xa1a0a3ff, 0x8f8d93ff, 0x8c8a90ff, 0x8a888dff, - 0x88868cff, 0x868389ff, 0x848288ff, 0x828086ff, 0x817e85ff, 0x7e7b82ff, - 0x807e84ff, 0x8c8b8fff, 0x8b898eff, 0x89878cff, 0x87858bff, 0x858488ff, - 0x848287ff, 0x827f85ff, 0x807e83ff, 0x7e7c82ff, 0x737178ff, 0x67636cff, - 0x64616aff, 0x635f68ff, 0x605d66ff, 0x5f5b65ff, 0x5d5963ff, 0x5b5761ff, - 0x58555fff, 0x57535dff, 0x646168ff, 0x68656cff, 0x66636bff, 0x67656dff, - 0x676570ff, 0x676672ff, 0x696775ff, 0x696877ff, 0x6a6a7aff, 0x6b6b7bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x757473ff, 0x747475ff, 0x747374ff, 0x737274ff, 0x727273ff, 0x727173ff, - 0x717072ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, - 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, - 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, - 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, - 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, - 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, - 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, - 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, - 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, - 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, - 0x4a4655ff, 0x4b4653ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x747373ff, 0x747374ff, 0x737274ff, 0x727273ff, - 0x727173ff, 0x717072ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, - 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, - 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, - 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, - 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, - 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, - 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, - 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, - 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, - 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, - 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x4a4652ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x747272ff, 0x737274ff, - 0x727273ff, 0x727173ff, 0x717072ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, - 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, - 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, - 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, - 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, - 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, - 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, - 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, - 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, - 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, - 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x4a4652ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x737172ff, 0x727273ff, 0x727173ff, 0x717072ff, 0x706f72ff, 0x706f71ff, - 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, - 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, - 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, - 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, - 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, - 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, - 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, - 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, - 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, - 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, - 0x494654ff, 0x494552ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x727171ff, 0x727173ff, 0x717072ff, 0x706f72ff, - 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, - 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, - 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, - 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, - 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, - 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, - 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, - 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, - 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, - 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, - 0x494654ff, 0x494654ff, 0x484554ff, 0x494551ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x727071ff, 0x717072ff, - 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, - 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, - 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, - 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, - 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, - 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, - 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, - 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, - 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, - 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, - 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x484551ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x716f70ff, 0x706f72ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, 0x6e6c70ff, - 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, - 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, - 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, - 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, - 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, - 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, - 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, - 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, - 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, - 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, - 0x474553ff, 0x484551ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x706e70ff, 0x706f71ff, 0x6f6e71ff, 0x6e6d70ff, - 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, - 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, - 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, - 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, - 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, - 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, - 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, - 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, - 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, - 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, - 0x484553ff, 0x474553ff, 0x474553ff, 0x474550ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x706e6fff, 0x6f6e71ff, - 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, - 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, - 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, - 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, - 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, - 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, - 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, - 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, - 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, - 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, - 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x474450ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6f6d6fff, 0x6e6d70ff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, 0x6c6a6eff, - 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, - 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, - 0x636068ff, 0x727361ff, 0xc3d93eff, 0xceea38ff, 0xcae938ff, 0xc6e838ff, - 0xc3e738ff, 0xbfe639ff, 0xbbe539ff, 0xb7e439ff, 0xb4e339ff, 0xb0e23aff, - 0xace13aff, 0x96bf43ff, 0x5d5b5fff, 0x595560ff, 0x585460ff, 0x5b595dff, - 0x88bb44ff, 0x93d93bff, 0x8fd83bff, 0x8bd73cff, 0x88d53cff, 0x84d43cff, - 0x80d33dff, 0x7cd23dff, 0x78d13dff, 0x74d03eff, 0x70d03eff, 0x69bd41ff, - 0x535c55ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, - 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, - 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, - 0x464452ff, 0x46444fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x6e6c6eff, 0x6e6c70ff, 0x6d6c6fff, 0x6c6b6fff, - 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, - 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, - 0x646168ff, 0x636068ff, 0x625f67ff, 0xa0ac4dff, 0xd6f434ff, 0xd2f335ff, - 0xcef235ff, 0xcaf135ff, 0xc6f036ff, 0xc2ef36ff, 0xbeee36ff, 0xbaed36ff, - 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0x728453ff, 0x585460ff, - 0x58535fff, 0x6d8153ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, - 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, - 0x6fd83cff, 0x6bd73dff, 0x568d46ff, 0x4d4757ff, 0x4d4857ff, 0x4d4757ff, - 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, - 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, - 0x464552ff, 0x464452ff, 0x454451ff, 0x46444fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6e6b6eff, 0x6d6c6fff, - 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, 0x69676cff, - 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, - 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x828858ff, - 0xd1f135ff, 0xcef235ff, 0xcaf135ff, 0xc6f036ff, 0xc2ef36ff, 0xbeee36ff, - 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa3df3aff, - 0x62675bff, 0x58535fff, 0x57525fff, 0x5f6459ff, 0x90da3bff, 0x8fe13aff, - 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, - 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d43dff, 0x4b684aff, 0x423f50ff, - 0x4c4656ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, - 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, - 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x45444fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6d6b6dff, 0x6c6b6fff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, 0x6a686dff, - 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, - 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, - 0x615e66ff, 0x605d66ff, 0x70725eff, 0xc5ea37ff, 0xc6f036ff, 0xc2ef36ff, - 0xbeee36ff, 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, - 0x98cc3fff, 0x5f615cff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, - 0x5a5d59ff, 0x81c441ff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, - 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x66ce3eff, 0x46534dff, - 0x413e4eff, 0x413d4eff, 0x413e50ff, 0x4b4655ff, 0x4b4756ff, 0x4b4756ff, - 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, - 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, - 0x444451ff, 0x44444eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x6c6a6dff, 0x6c6a6eff, 0x6b696eff, 0x6a686dff, - 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, - 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, - 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0xbadf3bff, - 0xc2ef36ff, 0xbeee36ff, 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, - 0xaae838ff, 0xa6e738ff, 0x8bb945ff, 0x58535fff, 0x57525fff, 0x56525eff, - 0x56515eff, 0x55505dff, 0x544f5dff, 0x78b244ff, 0x83dd3bff, 0x7fdc3bff, - 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, - 0x5fc23fff, 0x413e4eff, 0x413d4eff, 0x403d4eff, 0x403d4dff, 0x413e4fff, - 0x4a4655ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, - 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, - 0x454451ff, 0x444451ff, 0x434450ff, 0x44434eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6c696cff, 0x6b696eff, - 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, 0x67656bff, - 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, - 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, - 0x5e5b64ff, 0xb1d63eff, 0xbeee36ff, 0xbaed36ff, 0xb6ec37ff, 0xb2eb37ff, - 0xaee937ff, 0xaae838ff, 0xa6e738ff, 0xa2e638ff, 0x84b047ff, 0x57525fff, - 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x72a947ff, - 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, - 0x67d63dff, 0x63d43dff, 0x59b940ff, 0x413d4eff, 0x403d4eff, 0x403d4dff, - 0x3f3d4dff, 0x3f3d4dff, 0x403e4eff, 0x494554ff, 0x494654ff, 0x494654ff, - 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, - 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x43434eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6b686cff, 0x6a686dff, 0x6a686dff, 0x69676cff, 0x68666cff, 0x68656bff, - 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, - 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, - 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0xa8cc41ff, 0xbaed36ff, 0xb6ec37ff, - 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, - 0x7ea649ff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, - 0x534e5cff, 0x6ca048ff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, - 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x55af41ff, 0x403d4eff, - 0x403d4dff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, 0x3f3e4eff, - 0x484553ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, - 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, - 0x424350ff, 0x43434dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x6a676bff, 0x6a686dff, 0x69676cff, 0x68666cff, - 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, - 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, - 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x9fc243ff, - 0xb6ec37ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa6e738ff, 0xa2e638ff, - 0x9fe539ff, 0x9be439ff, 0x779e4bff, 0x56515eff, 0x55505dff, 0x544f5dff, - 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x68974aff, 0x77da3cff, 0x73d93cff, - 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, - 0x51a643ff, 0x403d4dff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, - 0x3e3c4cff, 0x3e3d4cff, 0x3f3c4dff, 0x474452ff, 0x474553ff, 0x474553ff, - 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, - 0x434350ff, 0x424350ff, 0x42434fff, 0x42434dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a676bff, 0x69676cff, - 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, 0x656269ff, - 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, - 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, - 0x6e755bff, 0xaddc3bff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, 0xa6e738ff, - 0xa2e638ff, 0x9fe539ff, 0x9be439ff, 0x97e339ff, 0x8fd83bff, 0x87ce3eff, - 0x83cc3eff, 0x80ca3eff, 0x7dca3fff, 0x79c93fff, 0x76c83fff, 0x75d03eff, - 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, - 0x5cd23eff, 0x58d13eff, 0x52bf40ff, 0x41564bff, 0x3f3d4dff, 0x3e3c4dff, - 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3e3d4dff, - 0x464452ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, - 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x42424cff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x69666aff, 0x68666cff, 0x68656bff, 0x67656bff, 0x66646aff, 0x66636aff, - 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, - 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, - 0x5d5963ff, 0x5c5863ff, 0x9bc044ff, 0xb2eb37ff, 0xaee937ff, 0xaae838ff, - 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, 0x9be439ff, 0x97e339ff, 0x93e239ff, - 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, - 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, - 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x48a243ff, - 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, - 0x3d3c4bff, 0x3d3c4cff, 0x3e3d4cff, 0x454351ff, 0x454451ff, 0x454451ff, - 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, - 0x41424eff, 0x41424cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x68656aff, 0x68656bff, 0x67656bff, 0x66646aff, - 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, - 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, - 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x89a54bff, 0xaee937ff, - 0xaae838ff, 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, 0x9be439ff, 0x97e339ff, - 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, - 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, - 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, - 0x4cce3fff, 0x438846ff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, - 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3d3d4cff, - 0x444350ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, - 0x41434fff, 0x41424eff, 0x40424eff, 0x41424cff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x686469ff, 0x67656bff, - 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, 0x636068ff, - 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, - 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, - 0x5b5861ff, 0x8aad49ff, 0xa6e738ff, 0xa2e638ff, 0x9fe539ff, 0x9be439ff, - 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x83ce3cff, 0x638747ff, 0x5d8049ff, - 0x71b940ff, 0x7bdb3bff, 0x77da3cff, 0x68b641ff, 0x547c48ff, 0x548347ff, - 0x63c63fff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, - 0x50cf3fff, 0x4cce3fff, 0x449345ff, 0x3f3e4dff, 0x3e3c4cff, 0x3e3d4cff, - 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, - 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4cff, 0x42434fff, 0x434350ff, 0x424350ff, - 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x40424bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x676469ff, 0x66646aff, 0x66636aff, 0x656269ff, 0x646269ff, 0x646168ff, - 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, - 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, - 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x7a944fff, 0xa2e638ff, 0x9fe539ff, - 0x9be439ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, 0x586c4cff, - 0x454252ff, 0x444251ff, 0x66a144ff, 0x77da3cff, 0x73d93cff, 0x5e9d44ff, - 0x423f50ff, 0x413e4fff, 0x4b684aff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, - 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x407947ff, 0x3e3c4cff, - 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, - 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3c3c4bff, - 0x41424fff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, - 0x3f424dff, 0x40424bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x666368ff, 0x66636aff, 0x656269ff, 0x646269ff, - 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, - 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, - 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x738b51ff, - 0x9fe539ff, 0x9be439ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, - 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, - 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, - 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, - 0x3f7148ff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, - 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3c3c4aff, 0x40424eff, 0x41424eff, 0x40424eff, - 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3f414bff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x666268ff, 0x656269ff, - 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, - 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, - 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, - 0x585460ff, 0x6e8153ff, 0x9be439ff, 0x97e339ff, 0x93e239ff, 0x8fe13aff, - 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, - 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, - 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, - 0x44cc40ff, 0x40cb40ff, 0x3e6848ff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, - 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, - 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3b3b49ff, - 0x3f414dff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3f414bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x656167ff, 0x646269ff, 0x646168ff, 0x636068ff, 0x625f67ff, 0x625f67ff, - 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, - 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, - 0x595560ff, 0x585460ff, 0x58535fff, 0x697756ff, 0x97e339ff, 0x93e239ff, - 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, - 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, - 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, - 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x3c5e4aff, 0x3e3b4cff, - 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, - 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, - 0x3a3b48ff, 0x393b49ff, 0x3b3b49ff, 0x3f414cff, 0x3f424dff, 0x3e414dff, - 0x3e414cff, 0x3e414bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x646167ff, 0x646168ff, 0x636068ff, 0x625f67ff, - 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, - 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, - 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x636f57ff, - 0x93e239ff, 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, - 0x7bdb3bff, 0x5a8247ff, 0x50694bff, 0x4f684bff, 0x5fad42ff, 0x67d63dff, - 0x63d43dff, 0x56a942ff, 0x49654aff, 0x46654aff, 0x497d46ff, 0x50cf3fff, - 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, - 0x3c564aff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, - 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393c48ff, - 0x3e404cff, 0x3e414cff, 0x3d414cff, 0x3e414aff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x646066ff, 0x636068ff, - 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, - 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, - 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, - 0x56525eff, 0x5f6659ff, 0x8fe13aff, 0x8bdf3aff, 0x87de3aff, 0x83dd3bff, - 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x68b341ff, 0x4c5e4cff, 0x47544dff, - 0x5aa443ff, 0x63d43dff, 0x5fd33dff, 0x53a043ff, 0x43514cff, 0x445b4aff, - 0x4cac42ff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, - 0x38c841ff, 0x34c741ff, 0x3b5049ff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, - 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, - 0x393b48ff, 0x393a48ff, 0x393c48ff, 0x3d414cff, 0x3d414bff, 0x3d414aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x635f66ff, 0x625f67ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, 0x605c65ff, - 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, - 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, - 0x57525fff, 0x56525eff, 0x56515eff, 0x5a5c5aff, 0x8bdf3aff, 0x87de3aff, - 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, - 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, - 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, - 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x3b464bff, 0x3c3c4bff, - 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, - 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x393b48ff, - 0x3c414bff, 0x3d404aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x625e65ff, 0x625f67ff, 0x615e66ff, 0x605d66ff, - 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, - 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, - 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x56535cff, - 0x87de3aff, 0x83dd3bff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, 0x73d93cff, - 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, - 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, - 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x2cc541ff, - 0x3c404bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, - 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, - 0x383b47ff, 0x383b47ff, 0x383a47ff, 0x3c4049ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x625e65ff, 0x615e66ff, - 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, - 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, - 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, - 0x544f5dff, 0x544e5cff, 0x81d93cff, 0x7fdc3bff, 0x7bdb3bff, 0x77da3cff, - 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, - 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, - 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, - 0x2cc541ff, 0x29c042ff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, - 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, - 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, - 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x393b46ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x615d64ff, 0x605d66ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, 0x5e5a64ff, - 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, - 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, - 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x7bcf3eff, 0x7bdb3bff, - 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, - 0x5fd33dff, 0x57ba41ff, 0x497448ff, 0x43524bff, 0x41514bff, 0x447348ff, - 0x47b641ff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x34c741ff, - 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x26b643ff, 0x3c3b4aff, 0x3c3b4bff, - 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, - 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, - 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, - 0x373a47ff, 0x373a45ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x605c64ff, 0x605c65ff, 0x5f5b65ff, 0x5e5b64ff, - 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, - 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, - 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, - 0x75c63fff, 0x77da3cff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, 0x67d63dff, - 0x63d43dff, 0x5fd33dff, 0x54aa42ff, 0x40434dff, 0x403d4dff, 0x3f3d4dff, - 0x3f3d4dff, 0x3e3c4dff, 0x3f424dff, 0x40a543ff, 0x3cc940ff, 0x38c841ff, - 0x34c741ff, 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, 0x24af43ff, - 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, - 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, - 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x373a44ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x605b63ff, 0x5f5b65ff, - 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, - 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, - 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, - 0x524d5bff, 0x524c5bff, 0x70bd42ff, 0x73d93cff, 0x6fd83cff, 0x6bd73dff, - 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5bcb3fff, 0x424a4cff, 0x403d4dff, - 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, 0x3d494bff, - 0x38c242ff, 0x34c741ff, 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, - 0x20c242ff, 0x22a644ff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, - 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, - 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a45ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5f5a63ff, 0x5e5b64ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, 0x5c5862ff, - 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, - 0x57525fff, 0x56525eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, - 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x6ab443ff, 0x6fd83cff, - 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, 0x509e44ff, - 0x403d4dff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, - 0x3e3d4cff, 0x3d3b4dff, 0x379745ff, 0x30c641ff, 0x2cc541ff, 0x28c442ff, - 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x239e45ff, 0x3b3c4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, - 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, - 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, - 0x363a46ff, 0x373a44ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x5e5a62ff, 0x5e5a64ff, 0x5d5963ff, 0x5c5863ff, - 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, - 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, - 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, - 0x65ab45ff, 0x6bd73dff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, 0x5cd23eff, - 0x58d13eff, 0x4a8645ff, 0x3f3d4dff, 0x3f3d4dff, 0x3e3c4dff, 0x3e3c4dff, - 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x378046ff, 0x2cc541ff, - 0x28c442ff, 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, 0x219546ff, - 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, - 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, - 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, - 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x363a44ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5e5962ff, 0x5d5963ff, - 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, - 0x585460ff, 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, - 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, - 0x504b5aff, 0x504a59ff, 0x60a247ff, 0x67d63dff, 0x63d43dff, 0x5fd33dff, - 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x477c46ff, 0x3f3d4dff, 0x3e3c4dff, - 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, - 0x357948ff, 0x28c442ff, 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, - 0x15be43ff, 0x218c46ff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, - 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, - 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, - 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x363a44ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5d5861ff, 0x5c5863ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, 0x5a5561ff, - 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, 0x56515eff, - 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, - 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x5d9949ff, 0x63d43dff, - 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, 0x447448ff, - 0x3e3c4dff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, - 0x3d3c4bff, 0x3d3c4cff, 0x347047ff, 0x24c342ff, 0x20c242ff, 0x1cc143ff, - 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x218446ff, 0x3b3b4aff, 0x3a3b4aff, - 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, - 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, - 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, - 0x353a45ff, 0x353943ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x5c5761ff, 0x5c5862ff, 0x5b5762ff, 0x5a5661ff, - 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56525eff, - 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, - 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, - 0x59904aff, 0x5fd33dff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, 0x50cf3fff, - 0x4cce3fff, 0x416a49ff, 0x3e3c4dff, 0x3e3c4cff, 0x3e3d4cff, 0x3d3b4dff, - 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x356749ff, 0x20c242ff, - 0x1cc143ff, 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, 0x237c47ff, - 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, - 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, - 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, - 0x353a45ff, 0x353a45ff, 0x343944ff, 0x353943ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5c5760ff, 0x5b5762ff, - 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, 0x57525fff, - 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, - 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, - 0x4e4858ff, 0x4e4858ff, 0x56884bff, 0x5cd23eff, 0x58d13eff, 0x54d03eff, - 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x40624aff, 0x3e3c4cff, 0x3e3d4cff, - 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, - 0x355f48ff, 0x1cc143ff, 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, - 0x0cbb44ff, 0x257547ff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, - 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, - 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, - 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x343944ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5b5660ff, 0x5a5661ff, 0x5a5561ff, 0x595560ff, 0x585460ff, 0x58535fff, - 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, - 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, - 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x537f4dff, 0x58d13eff, - 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, 0x3e594aff, - 0x3e3d4cff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, - 0x3c3b4cff, 0x3c3b4aff, 0x365749ff, 0x19c043ff, 0x15be43ff, 0x11bd44ff, - 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x286d46ff, 0x393b49ff, 0x393b49ff, - 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, - 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, - 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, - 0x333944ff, 0x343a43ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x5a555fff, 0x5a5561ff, 0x595560ff, 0x585460ff, - 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, - 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, - 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, - 0x50764eff, 0x54d03eff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, 0x44cc40ff, - 0x40cb40ff, 0x3e514aff, 0x3d3b4dff, 0x3e3b4cff, 0x3d3c4bff, 0x3d3c4cff, - 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x37504aff, 0x15be43ff, - 0x11bd44ff, 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, 0x2a6548ff, - 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, - 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, - 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, - 0x343944ff, 0x333944ff, 0x333a44ff, 0x343942ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5a545fff, 0x595560ff, - 0x585460ff, 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, 0x55505dff, - 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, - 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, - 0x4d4757ff, 0x4c4757ff, 0x4e6f4fff, 0x50cf3fff, 0x4cce3fff, 0x48cd3fff, - 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x3c484cff, 0x3e3b4cff, 0x3d3c4bff, - 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, - 0x374849ff, 0x11bd44ff, 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, - 0x0cb846ff, 0x2c5e48ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, - 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, - 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, - 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x343942ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x59545eff, 0x585460ff, 0x58535fff, 0x57525fff, 0x56515eff, 0x56515eff, - 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, - 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, - 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4c6650ff, 0x4cce3fff, - 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, 0x3e3f4cff, - 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, - 0x3c3c4bff, 0x3b3c4aff, 0x3a4049ff, 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, - 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x2f5548ff, 0x393b48ff, 0x393a48ff, - 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, - 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, - 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, - 0x333943ff, 0x333942ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x58535eff, 0x58535fff, 0x57525fff, 0x56515eff, - 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, - 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, - 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, - 0x4b5e52ff, 0x48cd3fff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, 0x38c841ff, - 0x34c341ff, 0x3d3c4bff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, 0x3c3b4aff, - 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x0db844ff, - 0x0cba45ff, 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x0cb547ff, 0x324f48ff, - 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, - 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, - 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, - 0x333943ff, 0x333943ff, 0x323943ff, 0x333a42ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x58525dff, 0x57525fff, - 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, 0x534e5cff, - 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, - 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, - 0x4b4756ff, 0x4b4756ff, 0x4a5552ff, 0x44cc40ff, 0x40cb40ff, 0x3cc940ff, - 0x38c841ff, 0x34c741ff, 0x31bb42ff, 0x3d3c4cff, 0x3c3c4bff, 0x3c3b4cff, - 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x0fb046ff, 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x0cb547ff, - 0x0cb447ff, 0x344848ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, - 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, - 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, - 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x333941ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x57515dff, 0x56515eff, 0x56515eff, 0x55505dff, 0x544f5dff, 0x544e5cff, - 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, - 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, - 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4d54ff, 0x40cb40ff, - 0x3cc940ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x2eb242ff, 0x3c3c4bff, - 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x12a846ff, 0x0cb846ff, 0x0cb746ff, - 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x374047ff, 0x383b48ff, 0x383b47ff, - 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, - 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, - 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, - 0x323942ff, 0x333841ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x56505cff, 0x56515eff, 0x55505dff, 0x544f5dff, - 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, - 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, - 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, - 0x494754ff, 0x3dc840ff, 0x38c841ff, 0x34c741ff, 0x30c641ff, 0x2cc541ff, - 0x2caa44ff, 0x3c3b4cff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, 0x3b3c4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x15a047ff, - 0x0cb746ff, 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x0cb148ff, 0x383c48ff, - 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, - 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, - 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, - 0x333a43ff, 0x323942ff, 0x323841ff, 0x313941ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x56505cff, 0x55505dff, - 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, 0x514b5aff, - 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, - 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, - 0x4a4655ff, 0x494654ff, 0x494654ff, 0x39c142ff, 0x34c741ff, 0x30c641ff, - 0x2cc541ff, 0x28c442ff, 0x2aa144ff, 0x3c3b4aff, 0x3c3b4bff, 0x3c3c4bff, - 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, - 0x393b49ff, 0x179947ff, 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x0cb248ff, - 0x0daa48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, - 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, - 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, - 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x313940ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x554f5bff, 0x544f5dff, 0x544e5cff, 0x534e5cff, 0x524d5bff, 0x524c5bff, - 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, - 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, - 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x36b843ff, - 0x30c641ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, 0x299845ff, 0x3c3b4bff, - 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, - 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x199047ff, 0x0cb447ff, 0x0cb348ff, - 0x0cb248ff, 0x0bb148ff, 0x11a248ff, 0x383b47ff, 0x373947ff, 0x363a46ff, - 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, - 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, - 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, - 0x303941ff, 0x313941ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x544e5bff, 0x544e5cff, 0x534e5cff, 0x524d5bff, - 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, - 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, - 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, - 0x484553ff, 0x34b044ff, 0x2cc541ff, 0x28c442ff, 0x24c342ff, 0x20c242ff, - 0x289046ff, 0x3c3c4bff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x1d8847ff, - 0x0cb348ff, 0x0cb248ff, 0x0bb148ff, 0x0bb049ff, 0x139a49ff, 0x373947ff, - 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, - 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, - 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, - 0x303842ff, 0x303941ff, 0x303941ff, 0x313941ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x544d5aff, 0x534e5cff, - 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, - 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, - 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, - 0x484554ff, 0x484553ff, 0x474553ff, 0x32a845ff, 0x28c442ff, 0x24c342ff, - 0x20c242ff, 0x1cc143ff, 0x278847ff, 0x3b3c4aff, 0x3b3b4aff, 0x3b3b4aff, - 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, - 0x393b48ff, 0x1f8048ff, 0x0cb248ff, 0x0bb148ff, 0x0bb049ff, 0x0baf49ff, - 0x159349ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, - 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, - 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, - 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x303940ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x534d5aff, 0x524d5bff, 0x524c5bff, 0x514b5aff, 0x504b5aff, 0x504a59ff, - 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, - 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, - 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x31a046ff, - 0x24c342ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, 0x277f47ff, 0x3b3b4aff, - 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, - 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x217948ff, 0x0bb148ff, 0x0bb049ff, - 0x0baf49ff, 0x0bae4aff, 0x188c49ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, - 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, - 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, - 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, - 0x2f3841ff, 0x30393fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x524c59ff, 0x524c5bff, 0x514b5aff, 0x504b5aff, - 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, - 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, - 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, - 0x464552ff, 0x309747ff, 0x20c242ff, 0x1cc143ff, 0x19c043ff, 0x15be43ff, - 0x287747ff, 0x3b3b4aff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, 0x393b49ff, - 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x237248ff, - 0x0bb049ff, 0x0baf49ff, 0x0bae4aff, 0x0bad4aff, 0x1a834aff, 0x363a46ff, - 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, - 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, - 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, - 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x30393fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x524c59ff, 0x514b5aff, - 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, - 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, - 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, - 0x474553ff, 0x464552ff, 0x464452ff, 0x2f8f48ff, 0x1cc143ff, 0x19c043ff, - 0x15be43ff, 0x11bd44ff, 0x286f47ff, 0x3b3b4aff, 0x3a3b4aff, 0x3a3b48ff, - 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, - 0x383b48ff, 0x256b48ff, 0x0baf49ff, 0x0bae4aff, 0x0bad4aff, 0x0bab4bff, - 0x1d7c49ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, - 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, - 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, - 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x30393fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x514b58ff, 0x504b5aff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, 0x4e4858ff, - 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, - 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, - 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x2f8749ff, - 0x19c043ff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, 0x2a6748ff, 0x3a3b4aff, - 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, - 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x286448ff, 0x0bae4aff, 0x0bad4aff, - 0x0bab4bff, 0x0baa4bff, 0x1f7649ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, - 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, - 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, - 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, - 0x2f3940ff, 0x2e383fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x504b58ff, 0x504a59ff, 0x4f4959ff, 0x4e4858ff, - 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, - 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, - 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, - 0x454451ff, 0x2f804bff, 0x15be43ff, 0x11bd44ff, 0x0dbc44ff, 0x0cbb44ff, - 0x2c6049ff, 0x3a3b48ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, 0x393b48ff, - 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x2a5b48ff, - 0x0bad4aff, 0x0bab4bff, 0x0baa4bff, 0x0ba94cff, 0x216f49ff, 0x363a45ff, - 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, - 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, - 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, - 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2e393fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x504a57ff, 0x4f4959ff, - 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, - 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, - 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, - 0x454451ff, 0x454451ff, 0x444451ff, 0x2f784bff, 0x11bd44ff, 0x0dbc44ff, - 0x0cbb44ff, 0x0cba45ff, 0x305847ff, 0x393b49ff, 0x393b49ff, 0x393a48ff, - 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, - 0x373947ff, 0x2c5547ff, 0x0bab4bff, 0x0baa4bff, 0x0ba94cff, 0x0ba84cff, - 0x246848ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, - 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, - 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, - 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2d393fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f4957ff, 0x4e4858ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, 0x4c4757ff, - 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, - 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, - 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x30704bff, - 0x0dbc44ff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, 0x315148ff, 0x393b49ff, - 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, - 0x383b47ff, 0x373947ff, 0x363a46ff, 0x2f4f48ff, 0x0baa4bff, 0x0ba94cff, - 0x0ba84cff, 0x0ba74cff, 0x256248ff, 0x353a45ff, 0x343944ff, 0x343944ff, - 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, - 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, - 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, - 0x2c393fff, 0x2d393eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4e4856ff, 0x4e4858ff, 0x4d4857ff, 0x4d4757ff, - 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, - 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, - 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, - 0x434350ff, 0x31694cff, 0x0cbb44ff, 0x0cba45ff, 0x0cb945ff, 0x0cb846ff, - 0x334a48ff, 0x393a48ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, 0x383b48ff, - 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x304846ff, - 0x0ba94cff, 0x0ba84cff, 0x0ba74cff, 0x0ba64dff, 0x285b48ff, 0x343944ff, - 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, - 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, - 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, - 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2d383dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4e4856ff, 0x4d4857ff, - 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, - 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, - 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, - 0x434450ff, 0x434350ff, 0x424350ff, 0x34624cff, 0x0cba45ff, 0x0cb945ff, - 0x0cb846ff, 0x0cb746ff, 0x374248ff, 0x393b48ff, 0x393a48ff, 0x393a47ff, - 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, - 0x363a46ff, 0x344146ff, 0x0ba84cff, 0x0ba74cff, 0x0ba64dff, 0x0ba54dff, - 0x2a5447ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, - 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, - 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, - 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2c383eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4d4855ff, 0x4d4757ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, 0x4b4756ff, - 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, - 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, - 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x365b4dff, - 0x0cb945ff, 0x0cb846ff, 0x0cb746ff, 0x0cb447ff, 0x383c48ff, 0x393a48ff, - 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, - 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x353b46ff, 0x0ba64cff, 0x0ba64dff, - 0x0ba54dff, 0x0ba44eff, 0x2c4e46ff, 0x333944ff, 0x333a44ff, 0x333943ff, - 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, - 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, - 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, - 0x2b373eff, 0x2c383dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4d4755ff, 0x4c4757ff, 0x4c4756ff, 0x4b4756ff, - 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, - 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, - 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, - 0x41434fff, 0x3a534dff, 0x0cb846ff, 0x0cb746ff, 0x0cb547ff, 0x0eae47ff, - 0x393a48ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, 0x373947ff, - 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, - 0x0ca14cff, 0x0ba54dff, 0x0ba44eff, 0x0ba24eff, 0x2e4746ff, 0x333a44ff, - 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, - 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, - 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, - 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2b383dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d4755ff, 0x4c4756ff, - 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, 0x494654ff, - 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, - 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, - 0x42434fff, 0x41434fff, 0x41424eff, 0x3b4c4dff, 0x0cb746ff, 0x0cb547ff, - 0x0cb447ff, 0x11a548ff, 0x393a47ff, 0x383b48ff, 0x383b47ff, 0x383b47ff, - 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, - 0x363a45ff, 0x353a45ff, 0x109a4cff, 0x0ba44eff, 0x0ba24eff, 0x0ba14fff, - 0x304245ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, - 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, - 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, - 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2b383dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4d4754ff, 0x4b4756ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, 0x494654ff, - 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, - 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, - 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x3e454eff, - 0x0cb547ff, 0x0cb447ff, 0x0cb348ff, 0x139f48ff, 0x383b48ff, 0x383b47ff, - 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, - 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x11934cff, 0x0ba24eff, - 0x0ba14fff, 0x0ba04fff, 0x323b43ff, 0x333943ff, 0x323943ff, 0x333a43ff, - 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, - 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, - 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, - 0x2a383eff, 0x2a383cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4c4754ff, 0x4b4756ff, 0x4a4655ff, 0x4a4655ff, - 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, - 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, - 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, - 0x40424eff, 0x3f424dff, 0x0eb147ff, 0x0cb348ff, 0x0cb248ff, 0x169648ff, - 0x383b47ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, 0x363a46ff, - 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, - 0x148b4cff, 0x0ba14fff, 0x0ba04fff, 0x0d9c4fff, 0x333943ff, 0x323943ff, - 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, - 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, - 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, - 0x2a383eff, 0x2a383eff, 0x29383dff, 0x2a383cff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4c4754ff, 0x4a4655ff, - 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, 0x474553ff, - 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, - 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, - 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x10aa49ff, 0x0cb248ff, - 0x0bb148ff, 0x188f48ff, 0x383b47ff, 0x373947ff, 0x363a46ff, 0x373a47ff, - 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, - 0x343944ff, 0x343944ff, 0x16844cff, 0x0ba04fff, 0x0b9f50ff, 0x0f954fff, - 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, - 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, - 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, - 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x29383cff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4b4653ff, 0x4a4655ff, 0x494654ff, 0x494654ff, 0x484554ff, 0x484553ff, - 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, - 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, - 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, - 0x13a249ff, 0x0bb148ff, 0x0bb049ff, 0x1a8848ff, 0x373947ff, 0x363a46ff, - 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, - 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x187e4cff, 0x0b9f50ff, - 0x0b9e50ff, 0x108e4eff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, - 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, - 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, - 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, - 0x28383dff, 0x29383bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4b4653ff, 0x494654ff, 0x494654ff, 0x484554ff, - 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, - 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, - 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, - 0x3e414dff, 0x3e414cff, 0x159b49ff, 0x0bb049ff, 0x0baf49ff, 0x1d8049ff, - 0x363a46ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, - 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, - 0x1b774bff, 0x0b9e50ff, 0x0b9d50ff, 0x12884eff, 0x323942ff, 0x323841ff, - 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, - 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, - 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, - 0x29383dff, 0x28383dff, 0x28383cff, 0x28383bff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4a4652ff, 0x494654ff, - 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, 0x464452ff, - 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, - 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, - 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x189349ff, 0x0baf49ff, - 0x0bae4aff, 0x1e7949ff, 0x373a47ff, 0x363a46ff, 0x363a45ff, 0x363a46ff, - 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, - 0x333a44ff, 0x333943ff, 0x1d714aff, 0x0b9d50ff, 0x0a9c51ff, 0x14824dff, - 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, - 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, - 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, - 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x28373aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4a4652ff, 0x484554ff, 0x484553ff, 0x474553ff, 0x474553ff, 0x464552ff, - 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, - 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, - 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, - 0x207f49ff, 0x0bae4aff, 0x0bad4aff, 0x276449ff, 0x363a46ff, 0x363a45ff, - 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, 0x343944ff, - 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x235e48ff, 0x0a9c51ff, - 0x0a9b51ff, 0x1c6e4bff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, - 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, - 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, - 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, - 0x27373bff, 0x27373aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x494552ff, 0x484553ff, 0x474553ff, 0x474553ff, - 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, - 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, - 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, - 0x3d414bff, 0x3c414bff, 0x3a454aff, 0x237048ff, 0x256749ff, 0x363b46ff, - 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, 0x343944ff, - 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, - 0x333b43ff, 0x225f48ff, 0x206549ff, 0x2e3d43ff, 0x303941ff, 0x303941ff, - 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, - 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, - 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, - 0x27383cff, 0x27373bff, 0x26373bff, 0x27373aff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x494551ff, 0x474553ff, - 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, 0x444451ff, - 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, - 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, - 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b3f49ff, - 0x373b47ff, 0x363a45ff, 0x363a46ff, 0x363a45ff, 0x353a45ff, 0x353a45ff, - 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, 0x333943ff, - 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, - 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, - 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, - 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, - 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, 0x263739ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x484551ff, 0x474553ff, 0x464552ff, 0x464452ff, 0x454451ff, 0x454451ff, - 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, - 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, - 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, - 0x3b404aff, 0x3a404aff, 0x3a3f48ff, 0x363b47ff, 0x363a45ff, 0x353a45ff, - 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, 0x333943ff, - 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, - 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, - 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, - 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, - 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, - 0x25373aff, 0x263739ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x484551ff, 0x464552ff, 0x464452ff, 0x454451ff, - 0x444451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, - 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, - 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, - 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f47ff, - 0x363b45ff, 0x353a45ff, 0x343944ff, 0x343944ff, 0x333944ff, 0x333a44ff, - 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, 0x323841ff, - 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, - 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, - 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, - 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, - 0x26373bff, 0x25373aff, 0x25373aff, 0x253639ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x474550ff, 0x464452ff, - 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, 0x424350ff, - 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, - 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, - 0x3c404bff, 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, - 0x393f48ff, 0x383f48ff, 0x383f48ff, 0x353b45ff, 0x343944ff, 0x333944ff, - 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, 0x323942ff, - 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, - 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, - 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, - 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, - 0x26373bff, 0x26373bff, 0x25373aff, 0x25373aff, 0x24363aff, 0x253638ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x474450ff, 0x454451ff, 0x454451ff, 0x444451ff, 0x434450ff, 0x434350ff, - 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, - 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, - 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, - 0x393f49ff, 0x393f48ff, 0x383f48ff, 0x383f48ff, 0x373e47ff, 0x373e47ff, - 0x353b45ff, 0x333a44ff, 0x333943ff, 0x333943ff, 0x323943ff, 0x333a43ff, - 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, 0x303941ff, - 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, - 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, - 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, - 0x27373bff, 0x26373bff, 0x26373bff, 0x25373aff, 0x25373aff, 0x24363aff, - 0x243639ff, 0x243638ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46444fff, 0x454451ff, 0x444451ff, 0x434450ff, - 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, 0x40424eff, - 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, 0x3d414cff, - 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b404aff, 0x3a404aff, - 0x3a3f49ff, 0x393f49ff, 0x393f48ff, 0x383f48ff, 0x383f48ff, 0x373e47ff, - 0x373e47ff, 0x363e47ff, 0x363e46ff, 0x333944ff, 0x333943ff, 0x323943ff, - 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, 0x303941ff, - 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, 0x2d3840ff, - 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, 0x2b383eff, - 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, 0x28383cff, - 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, 0x25373aff, 0x25373aff, - 0x24363aff, 0x243639ff, 0x233639ff, 0x243637ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46404aff, 0x444451ff, - 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, 0x41424eff, - 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, 0x3e414cff, - 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, 0x3b404aff, - 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f48ff, 0x383f48ff, 0x383f48ff, - 0x373e47ff, 0x373e47ff, 0x363e47ff, 0x363e46ff, 0x353d46ff, 0x353d45ff, - 0x323a43ff, 0x333a43ff, 0x323942ff, 0x323841ff, 0x303842ff, 0x303941ff, - 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, 0x2f3940ff, - 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, 0x2b373eff, - 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, 0x28383dff, - 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, 0x25373aff, - 0x25373aff, 0x24363aff, 0x243639ff, 0x233639ff, 0x233638ff, 0x293333ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x553c3aea, 0x434450ff, 0x434350ff, 0x424350ff, 0x42434fff, 0x41434fff, - 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, 0x3e414dff, - 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, 0x3b404aff, - 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f48ff, 0x383f48ff, - 0x383f48ff, 0x373e47ff, 0x373e47ff, 0x363e47ff, 0x363e46ff, 0x353d46ff, - 0x353d45ff, 0x343d45ff, 0x343d45ff, 0x323a42ff, 0x323841ff, 0x303842ff, - 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, 0x2e393fff, - 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, 0x2c383eff, - 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, 0x29383dff, - 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, 0x26373bff, - 0x25373aff, 0x25373aff, 0x24363aff, 0x243639ff, 0x233639ff, 0x233638ff, - 0x223538ff, 0x41332be9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x713c3522, 0x4e3c3df7, 0x424350ff, 0x42434fff, - 0x41434fff, 0x41424eff, 0x40424eff, 0x40424eff, 0x3f424dff, 0x3f424dff, - 0x3e414dff, 0x3e414cff, 0x3d414cff, 0x3d414bff, 0x3c414bff, 0x3c404bff, - 0x3b404aff, 0x3b404aff, 0x3a404aff, 0x3a3f49ff, 0x393f49ff, 0x393f48ff, - 0x383f48ff, 0x383f48ff, 0x373e47ff, 0x373e47ff, 0x363e47ff, 0x363e46ff, - 0x353d46ff, 0x353d45ff, 0x343d45ff, 0x343d45ff, 0x333d44ff, 0x333c44ff, - 0x313943ff, 0x303941ff, 0x303941ff, 0x303941ff, 0x2f3841ff, 0x2f3940ff, - 0x2e393fff, 0x2f3940ff, 0x2d3840ff, 0x2d383fff, 0x2c393fff, 0x2b393fff, - 0x2c383eff, 0x2b373eff, 0x2b383eff, 0x2a383eff, 0x2a383eff, 0x29383dff, - 0x29383dff, 0x28383dff, 0x28383cff, 0x27383cff, 0x27373bff, 0x26373bff, - 0x26373bff, 0x25373aff, 0x25373aff, 0x24363aff, 0x243639ff, 0x233639ff, - 0x233638ff, 0x223538ff, 0x38332ef6, 0x60382820, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6d3d2c4b, 0x673d2f97, 0x633d309b, 0x633d309b, 0x633d309b, 0x633d309b, - 0x633d309b, 0x633b309b, 0x633b2e9b, 0x613b2e9b, 0x613b2e9b, 0x613b2e9b, - 0x613b2e9b, 0x613b2e9b, 0x613b2e9b, 0x5f3b2e9b, 0x5f3b2c9b, 0x5f3b2c9b, - 0x5f3b2c9b, 0x5f3b2c9b, 0x5f3b2c9b, 0x5f3b2c9b, 0x5f3b2c9b, 0x5e3b2c9b, - 0x5e3b2c9b, 0x5e3a2c9b, 0x5e3a2b9b, 0x5e3a2b9b, 0x5e3a2b9b, 0x5e3a2b9b, - 0x5e3a2b9b, 0x5c3a2b9b, 0x5c3a2b9b, 0x5b372a9d, 0x5b372a9d, 0x5b372c9d, - 0x5b372c9d, 0x5b372a9d, 0x5c392b9c, 0x58382b9c, 0x58382b9c, 0x58382b9c, - 0x5a38299c, 0x5a38299c, 0x5838299c, 0x5838299c, 0x5938299b, 0x5938299b, - 0x5938279b, 0x5938279b, 0x5938279b, 0x5938279b, 0x5738279b, 0x5738279b, - 0x5738279b, 0x5738279b, 0x5738269b, 0x5738269b, 0x5736269b, 0x5736269b, - 0x5636269b, 0x5636269b, 0x5a382597, 0x633a224b, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; diff --git a/games/NXDoom/src/heretic/in_lude.c b/games/NXDoom/src/heretic/in_lude.c deleted file mode 100644 index a8ac4255dcf..00000000000 --- a/games/NXDoom/src/heretic/in_lude.c +++ /dev/null @@ -1,1075 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -/* -======================== -= -= IN_lude.c -= -======================== -*/ - -#include "doomdef.h" -#include "deh_str.h" -#include "p_local.h" -#include "s_sound.h" -#include "i_swap.h" -#include "i_system.h" -#include "i_video.h" -#include "v_video.h" -#include "am_map.h" - - -typedef enum -{ - SINGLE, - COOPERATIVE, - DEATHMATCH -} gametype_t; - -// Public functions - - -boolean intermission; - -// Private functions - -static void IN_WaitStop(void); -static void IN_Stop(void); -static void IN_LoadPics(void); -static void IN_UnloadPics(void); -static void IN_CheckForSkip(void); -static void IN_InitStats(void); -static void IN_DrawOldLevel(void); -static void IN_DrawYAH(void); -static void IN_DrawStatBack(void); -static void IN_DrawSingleStats(void); -static void IN_DrawCoopStats(void); -static void IN_DrawDMStats(void); -static void IN_DrawNumber(int val, int x, int y, int digits); -static void IN_DrawTime(int x, int y, int h, int m, int s); -static void IN_DrTextB(const char *text, int x, int y); - -static boolean skipintermission; -static int interstate = 0; -static int intertime = -1; -static int oldintertime = 0; -static gametype_t gametype; - -static int cnt; - -static int hours; -static int minutes; -static int seconds; - -static int slaughterboy; // in DM, the player with the most kills - -static int killPercent[MAXPLAYERS]; -static int bonusPercent[MAXPLAYERS]; -static int secretPercent[MAXPLAYERS]; - -static patch_t *patchINTERPIC; -static patch_t *patchBEENTHERE; -static patch_t *patchGOINGTHERE; -static patch_t *FontBNumbers[10]; -static patch_t *FontBNegative; -static patch_t *FontBSlash; -static patch_t *FontBPercent; - -static int FontBLump; -static int FontBLumpBase; -static int patchFaceOkayBase; -static int patchFaceDeadBase; - -static signed int totalFrags[MAXPLAYERS]; -static fixed_t dSlideX[MAXPLAYERS]; -static fixed_t dSlideY[MAXPLAYERS]; - -static const char *KillersText[] = { "K", "I", "L", "L", "E", "R", "S" }; - - -typedef struct -{ - int x; - int y; -} yahpt_t; - -static yahpt_t YAHspot[3][9] = { - { - {172, 78}, - {86, 90}, - {73, 66}, - {159, 95}, - {148, 126}, - {132, 54}, - {131, 74}, - {208, 138}, - {52, 101} - }, - { - {218, 57}, - {137, 81}, - {155, 124}, - {171, 68}, - {250, 86}, - {136, 98}, - {203, 90}, - {220, 140}, - {279, 106} - }, - { - {86, 99}, - {124, 103}, - {154, 79}, - {202, 83}, - {178, 59}, - {142, 58}, - {219, 66}, - {247, 57}, - {107, 80} - } -}; - -static const char *NameForMap(int map) -{ - const char *name = LevelNames[(gameepisode - 1) * 9 + map - 1]; - name = DEH_String(name); - if (strlen(name) < 7) - { - return ""; - } - return name + 7; -} - -//======================================================================== -// -// IN_Start -// -//======================================================================== - - -void IN_Start(void) -{ - I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE)); - IN_LoadPics(); - IN_InitStats(); - intermission = true; - interstate = -1; - skipintermission = false; - intertime = 0; - oldintertime = 0; - AM_Stop(); - S_StartSong(mus_intr, true); -} - -//======================================================================== -// -// IN_WaitStop -// -//======================================================================== - -void IN_WaitStop(void) -{ - if (!--cnt) - { - IN_Stop(); - G_WorldDone(); - } -} - -//======================================================================== -// -// IN_Stop -// -//======================================================================== - -void IN_Stop(void) -{ - intermission = false; - IN_UnloadPics(); - SB_state = -1; - BorderNeedRefresh = true; -} - -//======================================================================== -// -// IN_InitStats -// -// Initializes the stats for single player mode -//======================================================================== - -void IN_InitStats(void) -{ - int i; - int j; - signed int slaughterfrags; - int posnum; - int slaughtercount; - int playercount; - int count; - - if (!netgame) - { - gametype = SINGLE; - count = leveltime / 35; - hours = count / 3600; - count -= hours * 3600; - minutes = count / 60; - count -= minutes * 60; - seconds = count; - } - else if (netgame && !deathmatch) - { - gametype = COOPERATIVE; - memset(killPercent, 0, MAXPLAYERS * sizeof(int)); - memset(bonusPercent, 0, MAXPLAYERS * sizeof(int)); - memset(secretPercent, 0, MAXPLAYERS * sizeof(int)); - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - if (totalkills) - { - killPercent[i] = players[i].killcount * 100 / totalkills; - } - if (totalitems) - { - bonusPercent[i] = players[i].itemcount * 100 / totalitems; - } - if (totalsecret) - { - secretPercent[i] = - players[i].secretcount * 100 / totalsecret; - } - } - } - } - else - { - gametype = DEATHMATCH; - slaughterboy = 0; - slaughterfrags = -9999; - posnum = 0; - playercount = 0; - slaughtercount = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - totalFrags[i] = 0; - if (playeringame[i]) - { - playercount++; - for (j = 0; j < MAXPLAYERS; j++) - { - if (playeringame[j]) - { - totalFrags[i] += players[i].frags[j]; - } - } - dSlideX[i] = (43 * posnum * FRACUNIT) / 20; - dSlideY[i] = (36 * posnum * FRACUNIT) / 20; - posnum++; - } - if (totalFrags[i] > slaughterfrags) - { - slaughterboy = 1 << i; - slaughterfrags = totalFrags[i]; - slaughtercount = 1; - } - else if (totalFrags[i] == slaughterfrags) - { - slaughterboy |= 1 << i; - slaughtercount++; - } - } - if (playercount == slaughtercount) - { // don't do the slaughter stuff if everyone is equal - slaughterboy = 0; - } - } -} - -static void IN_LoadUnloadPics(void (*callback)(const char *lumpname, - int lumpnum, - patch_t **ptr)) -{ - int i; - - switch (gameepisode) - { - case 1: - callback(DEH_String("MAPE1"), 0, &patchINTERPIC); - break; - case 2: - callback(DEH_String("MAPE2"), 0, &patchINTERPIC); - break; - case 3: - callback(DEH_String("MAPE3"), 0, &patchINTERPIC); - break; - default: - break; - } - - callback(DEH_String("IN_X"), 0, &patchBEENTHERE); - callback(DEH_String("IN_YAH"), 0, &patchGOINGTHERE); - callback(DEH_String("FONTB13"), 0, &FontBNegative); - - callback(DEH_String("FONTB15"), 0, &FontBSlash); - callback(DEH_String("FONTB05"), 0, &FontBPercent); - - FontBLumpBase = W_GetNumForName(DEH_String("FONTB16")); - - for (i = 0; i < 10; i++) - { - callback(NULL, FontBLumpBase + i, &FontBNumbers[i]); - } -} - -//======================================================================== -// -// IN_LoadPics -// -//======================================================================== - -static void LoadLumpCallback(const char *lumpname, int lumpnum, patch_t **ptr) -{ - if (lumpname != NULL) - { - lumpnum = W_GetNumForName(lumpname); - } - - // Cache the lump - - *ptr = W_CacheLumpNum(lumpnum, PU_STATIC); -} - -void IN_LoadPics(void) -{ - FontBLump = W_GetNumForName(DEH_String("FONTB_S")) + 1; - patchFaceOkayBase = W_GetNumForName(DEH_String("FACEA0")); - patchFaceDeadBase = W_GetNumForName(DEH_String("FACEB0")); - - IN_LoadUnloadPics(LoadLumpCallback); -} - -//======================================================================== -// -// IN_UnloadPics -// -//======================================================================== - -static void UnloadLumpCallback(const char *lumpname, int lumpnum, patch_t **ptr) -{ - if (lumpname != NULL) - { - W_ReleaseLumpName(lumpname); - } - else - { - W_ReleaseLumpNum(lumpnum); - } -} - -void IN_UnloadPics(void) -{ - IN_LoadUnloadPics(UnloadLumpCallback); -} - -//======================================================================== -// -// IN_Ticker -// -//======================================================================== - -void IN_Ticker(void) -{ - if (!intermission) - { - return; - } - if (interstate == 3) - { - IN_WaitStop(); - return; - } - IN_CheckForSkip(); - intertime++; - if (oldintertime < intertime) - { - interstate++; - if (gameepisode > 3 && interstate >= 1) - { // Extended Wad levels: skip directly to the next level - interstate = 3; - } - switch (interstate) - { - case 0: - oldintertime = intertime + 300; - if (gameepisode > 3) - { - oldintertime = intertime + 1200; - } - break; - case 1: - oldintertime = intertime + 200; - break; - case 2: - oldintertime = INT_MAX; - break; - case 3: - cnt = 10; - break; - default: - break; - } - } - if (skipintermission) - { - if (interstate == 0 && intertime < 150) - { - intertime = 150; - skipintermission = false; - return; - } - else if (interstate < 2 && gameepisode < 4) - { - interstate = 2; - skipintermission = false; - S_StartSound(NULL, sfx_dorcls); - return; - } - interstate = 3; - cnt = 10; - skipintermission = false; - S_StartSound(NULL, sfx_dorcls); - } -} - -//======================================================================== -// -// IN_CheckForSkip -// -// Check to see if any player hit a key -//======================================================================== - -void IN_CheckForSkip(void) -{ - int i; - player_t *player; - - for (i = 0, player = players; i < MAXPLAYERS; i++, player++) - { - if (playeringame[i]) - { - if (player->cmd.buttons & BT_ATTACK) - { - if (!player->attackdown) - { - skipintermission = 1; - } - player->attackdown = true; - } - else - { - player->attackdown = false; - } - if (player->cmd.buttons & BT_USE) - { - if (!player->usedown) - { - skipintermission = 1; - } - player->usedown = true; - } - else - { - player->usedown = false; - } - } - } -} - -//======================================================================== -// -// IN_Drawer -// -//======================================================================== - -void IN_Drawer(void) -{ - static int oldinterstate; - - if (!intermission) - { - return; - } - if (interstate == 3) - { - return; - } - UpdateState |= I_FULLSCRN; - if (oldinterstate != 2 && interstate == 2) - { - S_StartSound(NULL, sfx_pstop); - } - oldinterstate = interstate; - switch (interstate) - { - case 0: // draw stats - IN_DrawStatBack(); - switch (gametype) - { - case SINGLE: - IN_DrawSingleStats(); - break; - case COOPERATIVE: - IN_DrawCoopStats(); - break; - case DEATHMATCH: - IN_DrawDMStats(); - break; - } - break; - case 1: // leaving old level - if (gameepisode < 4) - { - V_DrawPatch(0, 0, patchINTERPIC); - IN_DrawOldLevel(); - } - break; - case 2: // going to the next level - if (gameepisode < 4) - { - V_DrawPatch(0, 0, patchINTERPIC); - IN_DrawYAH(); - } - break; - case 3: // waiting before going to the next level - if (gameepisode < 4) - { - V_DrawPatch(0, 0, patchINTERPIC); - } - break; - default: - I_Error("IN_lude: Intermission state out of range.\n"); - break; - } -} - -//======================================================================== -// -// IN_DrawStatBack -// -//======================================================================== - -void IN_DrawStatBack(void) -{ - int x; - int y; - - byte *src; - byte *dest; - - src = W_CacheLumpName(DEH_String("FLOOR16"), PU_CACHE); - dest = I_VideoBuffer; - - for (y = 0; y < SCREENHEIGHT; y++) - { - for (x = 0; x < SCREENWIDTH / 64; x++) - { - memcpy(dest, src + ((y & 63) << 6), 64); - dest += 64; - } - if (SCREENWIDTH & 63) - { - memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); - dest += (SCREENWIDTH & 63); - } - } -} - -//======================================================================== -// -// IN_DrawOldLevel -// -//======================================================================== - -void IN_DrawOldLevel(void) -{ - const char *level_name = NameForMap(prevmap); - int i; - int x; - - x = 160 - MN_TextBWidth(level_name) / 2; - IN_DrTextB(level_name, x, 3); - x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2; - MN_DrTextA(DEH_String("FINISHED"), x, 25); - - if (prevmap == 9) - { - for (i = 0; i < gamemap - 1; i++) - { - V_DrawPatch(YAHspot[gameepisode - 1][i].x, - YAHspot[gameepisode - 1][i].y, patchBEENTHERE); - } - if (!(intertime & 16)) - { - V_DrawPatch(YAHspot[gameepisode - 1][8].x, - YAHspot[gameepisode - 1][8].y, patchBEENTHERE); - } - } - else - { - for (i = 0; i < prevmap - 1; i++) - { - V_DrawPatch(YAHspot[gameepisode - 1][i].x, - YAHspot[gameepisode - 1][i].y, patchBEENTHERE); - } - if (players[consoleplayer].didsecret) - { - V_DrawPatch(YAHspot[gameepisode - 1][8].x, - YAHspot[gameepisode - 1][8].y, patchBEENTHERE); - } - if (!(intertime & 16)) - { - V_DrawPatch(YAHspot[gameepisode - 1][prevmap - 1].x, - YAHspot[gameepisode - 1][prevmap - 1].y, - patchBEENTHERE); - } - } -} - -//======================================================================== -// -// IN_DrawYAH -// -//======================================================================== - -void IN_DrawYAH(void) -{ - const char *level_name = NameForMap(gamemap); - int i; - int x; - - x = 160 - MN_TextAWidth(DEH_String("NOW ENTERING:")) / 2; - MN_DrTextA(DEH_String("NOW ENTERING:"), x, 10); - x = 160 - MN_TextBWidth(level_name) / 2; - IN_DrTextB(level_name, x, 20); - - if (prevmap == 9) - { - prevmap = gamemap - 1; - } - for (i = 0; i < prevmap; i++) - { - V_DrawPatch(YAHspot[gameepisode - 1][i].x, - YAHspot[gameepisode - 1][i].y, patchBEENTHERE); - } - if (players[consoleplayer].didsecret) - { - V_DrawPatch(YAHspot[gameepisode - 1][8].x, - YAHspot[gameepisode - 1][8].y, patchBEENTHERE); - } - if (!(intertime & 16) || interstate == 3) - { // draw the destination 'X' - V_DrawPatch(YAHspot[gameepisode - 1][gamemap - 1].x, - YAHspot[gameepisode - 1][gamemap - 1].y, patchGOINGTHERE); - } -} - -//======================================================================== -// -// IN_DrawSingleStats -// -//======================================================================== - -void IN_DrawSingleStats(void) -{ - const char *prev_level_name = NameForMap(prevmap); - const char *next_level_name = NameForMap(gamemap); - int x; - static int sounds; - - IN_DrTextB(DEH_String("KILLS"), 50, 65); - IN_DrTextB(DEH_String("ITEMS"), 50, 90); - IN_DrTextB(DEH_String("SECRETS"), 50, 115); - - x = 160 - MN_TextBWidth(prev_level_name) / 2; - IN_DrTextB(prev_level_name, x, 3); - x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2; - MN_DrTextA(DEH_String("FINISHED"), x, 25); - - if (intertime < 30) - { - sounds = 0; - return; - } - if (sounds < 1 && intertime >= 30) - { - S_StartSound(NULL, sfx_dorcls); - sounds++; - } - IN_DrawNumber(players[consoleplayer].killcount, 200, 65, 3); - V_DrawShadowedPatch(237, 65, FontBSlash); - IN_DrawNumber(totalkills, 248, 65, 3); - if (intertime < 60) - { - return; - } - if (sounds < 2 && intertime >= 60) - { - S_StartSound(NULL, sfx_dorcls); - sounds++; - } - IN_DrawNumber(players[consoleplayer].itemcount, 200, 90, 3); - V_DrawShadowedPatch(237, 90, FontBSlash); - IN_DrawNumber(totalitems, 248, 90, 3); - if (intertime < 90) - { - return; - } - if (sounds < 3 && intertime >= 90) - { - S_StartSound(NULL, sfx_dorcls); - sounds++; - } - IN_DrawNumber(players[consoleplayer].secretcount, 200, 115, 3); - V_DrawShadowedPatch(237, 115, FontBSlash); - IN_DrawNumber(totalsecret, 248, 115, 3); - if (intertime < 150) - { - return; - } - if (sounds < 4 && intertime >= 150) - { - S_StartSound(NULL, sfx_dorcls); - sounds++; - } - - if (gamemode != retail || gameepisode <= 3) - { - IN_DrTextB(DEH_String("TIME"), 85, 160); - IN_DrawTime(155, 160, hours, minutes, seconds); - } - else - { - x = 160 - MN_TextAWidth(DEH_String("NOW ENTERING:")) / 2; - MN_DrTextA(DEH_String("NOW ENTERING:"), x, 160); - x = 160 - MN_TextBWidth(next_level_name) / 2; - IN_DrTextB(next_level_name, x, 170); - skipintermission = false; - } -} - -//======================================================================== -// -// IN_DrawCoopStats -// -//======================================================================== - -void IN_DrawCoopStats(void) -{ - const char *level_name = NameForMap(prevmap); - int i; - int x; - int ypos; - - static int sounds; - - IN_DrTextB(DEH_String("KILLS"), 95, 35); - IN_DrTextB(DEH_String("BONUS"), 155, 35); - IN_DrTextB(DEH_String("SECRET"), 232, 35); - x = 160 - MN_TextBWidth(level_name) / 2; - IN_DrTextB(level_name, x, 3); - x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2; - MN_DrTextA(DEH_String("FINISHED"), x, 25); - - ypos = 50; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - V_DrawShadowedPatch(25, ypos, - W_CacheLumpNum(patchFaceOkayBase + i, - PU_CACHE)); - if (intertime < 40) - { - sounds = 0; - ypos += 37; - continue; - } - else if (intertime >= 40 && sounds < 1) - { - S_StartSound(NULL, sfx_dorcls); - sounds++; - } - IN_DrawNumber(killPercent[i], 85, ypos + 10, 3); - V_DrawShadowedPatch(121, ypos + 10, FontBPercent); - IN_DrawNumber(bonusPercent[i], 160, ypos + 10, 3); - V_DrawShadowedPatch(196, ypos + 10, FontBPercent); - IN_DrawNumber(secretPercent[i], 237, ypos + 10, 3); - V_DrawShadowedPatch(273, ypos + 10, FontBPercent); - ypos += 37; - } - } -} - -//======================================================================== -// -// IN_DrawDMStats -// -//======================================================================== - -void IN_DrawDMStats(void) -{ - int i; - int j; - int ypos; - int xpos; - int kpos; - - static int sounds; - - xpos = 90; - ypos = 55; - - IN_DrTextB(DEH_String("TOTAL"), 265, 30); - MN_DrTextA(DEH_String("VICTIMS"), 140, 8); - for (i = 0; i < 7; i++) - { - MN_DrTextA(DEH_String(KillersText[i]), 10, 80 + 9 * i); - } - if (intertime < 20) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - V_DrawShadowedPatch(40, - ((ypos << FRACBITS) + - dSlideY[i] * intertime) >> FRACBITS, - W_CacheLumpNum(patchFaceOkayBase + i, - PU_CACHE)); - V_DrawShadowedPatch(((xpos << FRACBITS) + - dSlideX[i] * intertime) >> FRACBITS, 18, - W_CacheLumpNum(patchFaceDeadBase + i, - PU_CACHE)); - } - } - sounds = 0; - return; - } - if (intertime >= 20 && sounds < 1) - { - S_StartSound(NULL, sfx_dorcls); - sounds++; - } - if (intertime >= 100 && slaughterboy && sounds < 2) - { - S_StartSound(NULL, sfx_wpnup); - sounds++; - } - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - if (intertime < 100 || i == consoleplayer) - { - V_DrawShadowedPatch(40, ypos, - W_CacheLumpNum(patchFaceOkayBase + i, - PU_CACHE)); - V_DrawShadowedPatch(xpos, 18, - W_CacheLumpNum(patchFaceDeadBase + i, - PU_CACHE)); - } - else - { - V_DrawAltTLPatch(40, ypos, - W_CacheLumpNum(patchFaceOkayBase + i, - PU_CACHE)); - V_DrawAltTLPatch(xpos, 18, - W_CacheLumpNum(patchFaceDeadBase + i, - PU_CACHE)); - } - kpos = 86; - for (j = 0; j < MAXPLAYERS; j++) - { - if (playeringame[j]) - { - IN_DrawNumber(players[i].frags[j], kpos, ypos + 10, 3); - kpos += 43; - } - } - if (slaughterboy & (1 << i)) - { - if (!(intertime & 16)) - { - IN_DrawNumber(totalFrags[i], 263, ypos + 10, 3); - } - } - else - { - IN_DrawNumber(totalFrags[i], 263, ypos + 10, 3); - } - ypos += 36; - xpos += 43; - } - } -} - -//======================================================================== -// -// IN_DrawTime -// -//======================================================================== - -void IN_DrawTime(int x, int y, int h, int m, int s) -{ - if (h) - { - IN_DrawNumber(h, x, y, 2); - IN_DrTextB(DEH_String(":"), x + 26, y); - } - x += 34; - if (m || h) - { - IN_DrawNumber(m, x, y, 2); - } - x += 34; - if (s) - { - IN_DrTextB(DEH_String(":"), x - 8, y); - IN_DrawNumber(s, x, y, 2); - } -} - -//======================================================================== -// -// IN_DrawNumber -// -//======================================================================== - -void IN_DrawNumber(int val, int x, int y, int digits) -{ - patch_t *patch; - int xpos; - int oldval; - int realdigits; - boolean neg; - - oldval = val; - xpos = x; - neg = false; - realdigits = 1; - - if (val < 0) - { //...this should reflect negative frags - val = -val; - neg = true; - if (val > 99) - { - val = 99; - } - } - if (val > 9) - { - realdigits++; - if (digits < realdigits) - { - realdigits = digits; - val = 9; - } - } - if (val > 99) - { - realdigits++; - if (digits < realdigits) - { - realdigits = digits; - val = 99; - } - } - if (val > 999) - { - realdigits++; - if (digits < realdigits) - { - realdigits = digits; - val = 999; - } - } - if (digits == 4) - { - patch = FontBNumbers[val / 1000]; - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2 - 12, y, patch); - } - if (digits > 2) - { - if (realdigits > 2) - { - patch = FontBNumbers[val / 100]; - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - } - xpos += 12; - } - val = val % 100; - if (digits > 1) - { - if (val > 9) - { - patch = FontBNumbers[val / 10]; - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - } - else if (digits == 2 || oldval > 99) - { - V_DrawShadowedPatch(xpos, y, FontBNumbers[0]); - } - xpos += 12; - } - val = val % 10; - patch = FontBNumbers[val]; - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - if (neg) - { - patch = FontBNegative; - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2 - 12 * (realdigits), - y, patch); - } -} - -//======================================================================== -// -// IN_DrTextB -// -//======================================================================== - -void IN_DrTextB(const char *text, int x, int y) -{ - char c; - patch_t *p; - - while ((c = *text++) != 0) - { - if (c < 33) - { - x += 8; - } - else - { - p = W_CacheLumpNum(FontBLump + c - 33, PU_CACHE); - V_DrawShadowedPatch(x, y, p); - x += SHORT(p->width) - 1; - } - } -} diff --git a/games/NXDoom/src/heretic/info.c b/games/NXDoom/src/heretic/info.c deleted file mode 100644 index d736325b761..00000000000 --- a/games/NXDoom/src/heretic/info.c +++ /dev/null @@ -1,5600 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -#include "doomdef.h" -#include "p_action.h" - -const char *sprnames[] = { - "IMPX","ACLO","PTN1","SHLD","SHD2","BAGH","SPMP","INVS","PTN2","SOAR", - "INVU","PWBK","EGGC","EGGM","FX01","SPHL","TRCH","FBMB","XPL1","ATLP", - "PPOD","AMG1","SPSH","LVAS","SLDG","SKH1","SKH2","SKH3","SKH4","CHDL", - "SRTC","SMPL","STGS","STGL","STCS","STCL","KFR1","BARL","BRPL","MOS1", - "MOS2","WTRH","HCOR","KGZ1","KGZB","KGZG","KGZY","VLCO","VFBL","VTFB", - "SFFI","TGLT","TELE","STFF","PUF3","PUF4","BEAK","WGNT","GAUN","PUF1", - "WBLS","BLSR","FX18","FX17","WMCE","MACE","FX02","WSKL","HROD","FX00", - "FX20","FX21","FX22","FX23","GWND","PUF2","WPHX","PHNX","FX04","FX08", - "FX09","WBOW","CRBW","FX03","BLOD","PLAY","FDTH","BSKL","CHKN","MUMM", - "FX15","BEAS","FRB1","SNKE","SNFX","HEAD","FX05","FX06","FX07","CLNK", - "WZRD","FX11","FX10","KNIG","SPAX","RAXE","SRCR","FX14","SOR2","SDTH", - "FX16","MNTR","FX12","FX13","AKYY","BKYY","CKYY","AMG2","AMM1","AMM2", - "AMC1","AMC2","AMS1","AMS2","AMP1","AMP2","AMB1","AMB2", - NULL -}; - -state_t states[NUMSTATES] = { - {SPR_IMPX, 0, -1, NULL, S_NULL, 0, 0}, // S_NULL - {SPR_ACLO, 4, 1050, A_FreeTargMobj, S_NULL, 0, 0}, // S_FREETARGMOBJ - {SPR_PTN1, 0, 3, NULL, S_ITEM_PTN1_2, 0, 0}, // S_ITEM_PTN1_1 - {SPR_PTN1, 1, 3, NULL, S_ITEM_PTN1_3, 0, 0}, // S_ITEM_PTN1_2 - {SPR_PTN1, 2, 3, NULL, S_ITEM_PTN1_1, 0, 0}, // S_ITEM_PTN1_3 - {SPR_SHLD, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_SHLD1 - {SPR_SHD2, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_SHD2_1 - {SPR_BAGH, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_BAGH1 - {SPR_SPMP, 0, -1, NULL, S_NULL, 0, 0}, // S_ITEM_SPMP1 - {SPR_ACLO, 4, 1400, NULL, S_HIDESPECIAL2, 0, 0}, // S_HIDESPECIAL1 - {SPR_ACLO, 0, 4, A_RestoreSpecialThing1, S_HIDESPECIAL3, 0, 0}, // S_HIDESPECIAL2 - {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL4, 0, 0}, // S_HIDESPECIAL3 - {SPR_ACLO, 0, 4, NULL, S_HIDESPECIAL5, 0, 0}, // S_HIDESPECIAL4 - {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL6, 0, 0}, // S_HIDESPECIAL5 - {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL7, 0, 0}, // S_HIDESPECIAL6 - {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL8, 0, 0}, // S_HIDESPECIAL7 - {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL9, 0, 0}, // S_HIDESPECIAL8 - {SPR_ACLO, 3, 4, NULL, S_HIDESPECIAL10, 0, 0}, // S_HIDESPECIAL9 - {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL11, 0, 0}, // S_HIDESPECIAL10 - {SPR_ACLO, 3, 4, A_RestoreSpecialThing2, S_NULL, 0, 0}, // S_HIDESPECIAL11 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2, 0, 0}, // S_DORMANTARTI1 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3, 0, 0}, // S_DORMANTARTI2 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI4, 0, 0}, // S_DORMANTARTI3 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI5, 0, 0}, // S_DORMANTARTI4 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI6, 0, 0}, // S_DORMANTARTI5 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI7, 0, 0}, // S_DORMANTARTI6 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI8, 0, 0}, // S_DORMANTARTI7 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI9, 0, 0}, // S_DORMANTARTI8 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI10, 0, 0}, // S_DORMANTARTI9 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI11, 0, 0}, // S_DORMANTARTI10 - {SPR_ACLO, 0, 1400, A_HideThing, S_DORMANTARTI12, 0, 0}, // S_DORMANTARTI11 - {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI13, 0, 0}, // S_DORMANTARTI12 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI14, 0, 0}, // S_DORMANTARTI13 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI15, 0, 0}, // S_DORMANTARTI14 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI16, 0, 0}, // S_DORMANTARTI15 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI17, 0, 0}, // S_DORMANTARTI16 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI18, 0, 0}, // S_DORMANTARTI17 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI19, 0, 0}, // S_DORMANTARTI18 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI20, 0, 0}, // S_DORMANTARTI19 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI21, 0, 0}, // S_DORMANTARTI20 - {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI21 - {SPR_ACLO, 3, 3, NULL, S_DEADARTI2, 0, 0}, // S_DEADARTI1 - {SPR_ACLO, 2, 3, NULL, S_DEADARTI3, 0, 0}, // S_DEADARTI2 - {SPR_ACLO, 3, 3, NULL, S_DEADARTI4, 0, 0}, // S_DEADARTI3 - {SPR_ACLO, 2, 3, NULL, S_DEADARTI5, 0, 0}, // S_DEADARTI4 - {SPR_ACLO, 1, 3, NULL, S_DEADARTI6, 0, 0}, // S_DEADARTI5 - {SPR_ACLO, 2, 3, NULL, S_DEADARTI7, 0, 0}, // S_DEADARTI6 - {SPR_ACLO, 1, 3, NULL, S_DEADARTI8, 0, 0}, // S_DEADARTI7 - {SPR_ACLO, 0, 3, NULL, S_DEADARTI9, 0, 0}, // S_DEADARTI8 - {SPR_ACLO, 1, 3, NULL, S_DEADARTI10, 0, 0}, // S_DEADARTI9 - {SPR_ACLO, 0, 3, NULL, S_NULL, 0, 0}, // S_DEADARTI10 - {SPR_INVS, 32768, 350, NULL, S_ARTI_INVS1, 0, 0}, // S_ARTI_INVS1 - {SPR_PTN2, 0, 4, NULL, S_ARTI_PTN2_2, 0, 0}, // S_ARTI_PTN2_1 - {SPR_PTN2, 1, 4, NULL, S_ARTI_PTN2_3, 0, 0}, // S_ARTI_PTN2_2 - {SPR_PTN2, 2, 4, NULL, S_ARTI_PTN2_1, 0, 0}, // S_ARTI_PTN2_3 - {SPR_SOAR, 0, 5, NULL, S_ARTI_SOAR2, 0, 0}, // S_ARTI_SOAR1 - {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR3, 0, 0}, // S_ARTI_SOAR2 - {SPR_SOAR, 2, 5, NULL, S_ARTI_SOAR4, 0, 0}, // S_ARTI_SOAR3 - {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR1, 0, 0}, // S_ARTI_SOAR4 - {SPR_INVU, 0, 3, NULL, S_ARTI_INVU2, 0, 0}, // S_ARTI_INVU1 - {SPR_INVU, 1, 3, NULL, S_ARTI_INVU3, 0, 0}, // S_ARTI_INVU2 - {SPR_INVU, 2, 3, NULL, S_ARTI_INVU4, 0, 0}, // S_ARTI_INVU3 - {SPR_INVU, 3, 3, NULL, S_ARTI_INVU1, 0, 0}, // S_ARTI_INVU4 - {SPR_PWBK, 0, 350, NULL, S_ARTI_PWBK1, 0, 0}, // S_ARTI_PWBK1 - {SPR_EGGC, 0, 6, NULL, S_ARTI_EGGC2, 0, 0}, // S_ARTI_EGGC1 - {SPR_EGGC, 1, 6, NULL, S_ARTI_EGGC3, 0, 0}, // S_ARTI_EGGC2 - {SPR_EGGC, 2, 6, NULL, S_ARTI_EGGC4, 0, 0}, // S_ARTI_EGGC3 - {SPR_EGGC, 1, 6, NULL, S_ARTI_EGGC1, 0, 0}, // S_ARTI_EGGC4 - {SPR_EGGM, 0, 4, NULL, S_EGGFX2, 0, 0}, // S_EGGFX1 - {SPR_EGGM, 1, 4, NULL, S_EGGFX3, 0, 0}, // S_EGGFX2 - {SPR_EGGM, 2, 4, NULL, S_EGGFX4, 0, 0}, // S_EGGFX3 - {SPR_EGGM, 3, 4, NULL, S_EGGFX5, 0, 0}, // S_EGGFX4 - {SPR_EGGM, 4, 4, NULL, S_EGGFX1, 0, 0}, // S_EGGFX5 - {SPR_FX01, 32772, 3, NULL, S_EGGFXI1_2, 0, 0}, // S_EGGFXI1_1 - {SPR_FX01, 32773, 3, NULL, S_EGGFXI1_3, 0, 0}, // S_EGGFXI1_2 - {SPR_FX01, 32774, 3, NULL, S_EGGFXI1_4, 0, 0}, // S_EGGFXI1_3 - {SPR_FX01, 32775, 3, NULL, S_NULL, 0, 0}, // S_EGGFXI1_4 - {SPR_SPHL, 0, 350, NULL, S_ARTI_SPHL1, 0, 0}, // S_ARTI_SPHL1 - {SPR_TRCH, 32768, 3, NULL, S_ARTI_TRCH2, 0, 0}, // S_ARTI_TRCH1 - {SPR_TRCH, 32769, 3, NULL, S_ARTI_TRCH3, 0, 0}, // S_ARTI_TRCH2 - {SPR_TRCH, 32770, 3, NULL, S_ARTI_TRCH1, 0, 0}, // S_ARTI_TRCH3 - {SPR_FBMB, 4, 350, NULL, S_ARTI_FBMB1, 0, 0}, // S_ARTI_FBMB1 - {SPR_FBMB, 0, 10, NULL, S_FIREBOMB2, 0, 0}, // S_FIREBOMB1 - {SPR_FBMB, 1, 10, NULL, S_FIREBOMB3, 0, 0}, // S_FIREBOMB2 - {SPR_FBMB, 2, 10, NULL, S_FIREBOMB4, 0, 0}, // S_FIREBOMB3 - {SPR_FBMB, 3, 10, NULL, S_FIREBOMB5, 0, 0}, // S_FIREBOMB4 - {SPR_FBMB, 4, 6, A_Scream, S_FIREBOMB6, 0, 0}, // S_FIREBOMB5 - {SPR_XPL1, 32768, 4, A_Explode, S_FIREBOMB7, 0, 0}, // S_FIREBOMB6 - {SPR_XPL1, 32769, 4, NULL, S_FIREBOMB8, 0, 0}, // S_FIREBOMB7 - {SPR_XPL1, 32770, 4, NULL, S_FIREBOMB9, 0, 0}, // S_FIREBOMB8 - {SPR_XPL1, 32771, 4, NULL, S_FIREBOMB10, 0, 0}, // S_FIREBOMB9 - {SPR_XPL1, 32772, 4, NULL, S_FIREBOMB11, 0, 0}, // S_FIREBOMB10 - {SPR_XPL1, 32773, 4, NULL, S_NULL, 0, 0}, // S_FIREBOMB11 - {SPR_ATLP, 0, 4, NULL, S_ARTI_ATLP2, 0, 0}, // S_ARTI_ATLP1 - {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP3, 0, 0}, // S_ARTI_ATLP2 - {SPR_ATLP, 2, 4, NULL, S_ARTI_ATLP4, 0, 0}, // S_ARTI_ATLP3 - {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP1, 0, 0}, // S_ARTI_ATLP4 - {SPR_PPOD, 0, 10, NULL, S_POD_WAIT1, 0, 0}, // S_POD_WAIT1 - {SPR_PPOD, 1, 14, A_PodPain, S_POD_WAIT1, 0, 0}, // S_POD_PAIN1 - {SPR_PPOD, 32770, 5, A_RemovePod, S_POD_DIE2, 0, 0}, // S_POD_DIE1 - {SPR_PPOD, 32771, 5, A_Scream, S_POD_DIE3, 0, 0}, // S_POD_DIE2 - {SPR_PPOD, 32772, 5, A_Explode, S_POD_DIE4, 0, 0}, // S_POD_DIE3 - {SPR_PPOD, 32773, 10, NULL, S_FREETARGMOBJ, 0, 0}, // S_POD_DIE4 - {SPR_PPOD, 8, 3, NULL, S_POD_GROW2, 0, 0}, // S_POD_GROW1 - {SPR_PPOD, 9, 3, NULL, S_POD_GROW3, 0, 0}, // S_POD_GROW2 - {SPR_PPOD, 10, 3, NULL, S_POD_GROW4, 0, 0}, // S_POD_GROW3 - {SPR_PPOD, 11, 3, NULL, S_POD_GROW5, 0, 0}, // S_POD_GROW4 - {SPR_PPOD, 12, 3, NULL, S_POD_GROW6, 0, 0}, // S_POD_GROW5 - {SPR_PPOD, 13, 3, NULL, S_POD_GROW7, 0, 0}, // S_POD_GROW6 - {SPR_PPOD, 14, 3, NULL, S_POD_GROW8, 0, 0}, // S_POD_GROW7 - {SPR_PPOD, 15, 3, NULL, S_POD_WAIT1, 0, 0}, // S_POD_GROW8 - {SPR_PPOD, 6, 8, NULL, S_PODGOO2, 0, 0}, // S_PODGOO1 - {SPR_PPOD, 7, 8, NULL, S_PODGOO1, 0, 0}, // S_PODGOO2 - {SPR_PPOD, 6, 10, NULL, S_NULL, 0, 0}, // S_PODGOOX - {SPR_AMG1, 0, 35, A_MakePod, S_PODGENERATOR, 0, 0}, // S_PODGENERATOR - {SPR_SPSH, 0, 8, NULL, S_SPLASH2, 0, 0}, // S_SPLASH1 - {SPR_SPSH, 1, 8, NULL, S_SPLASH3, 0, 0}, // S_SPLASH2 - {SPR_SPSH, 2, 8, NULL, S_SPLASH4, 0, 0}, // S_SPLASH3 - {SPR_SPSH, 3, 16, NULL, S_NULL, 0, 0}, // S_SPLASH4 - {SPR_SPSH, 3, 10, NULL, S_NULL, 0, 0}, // S_SPLASHX - {SPR_SPSH, 4, 5, NULL, S_SPLASHBASE2, 0, 0}, // S_SPLASHBASE1 - {SPR_SPSH, 5, 5, NULL, S_SPLASHBASE3, 0, 0}, // S_SPLASHBASE2 - {SPR_SPSH, 6, 5, NULL, S_SPLASHBASE4, 0, 0}, // S_SPLASHBASE3 - {SPR_SPSH, 7, 5, NULL, S_SPLASHBASE5, 0, 0}, // S_SPLASHBASE4 - {SPR_SPSH, 8, 5, NULL, S_SPLASHBASE6, 0, 0}, // S_SPLASHBASE5 - {SPR_SPSH, 9, 5, NULL, S_SPLASHBASE7, 0, 0}, // S_SPLASHBASE6 - {SPR_SPSH, 10, 5, NULL, S_NULL, 0, 0}, // S_SPLASHBASE7 - {SPR_LVAS, 32768, 5, NULL, S_LAVASPLASH2, 0, 0}, // S_LAVASPLASH1 - {SPR_LVAS, 32769, 5, NULL, S_LAVASPLASH3, 0, 0}, // S_LAVASPLASH2 - {SPR_LVAS, 32770, 5, NULL, S_LAVASPLASH4, 0, 0}, // S_LAVASPLASH3 - {SPR_LVAS, 32771, 5, NULL, S_LAVASPLASH5, 0, 0}, // S_LAVASPLASH4 - {SPR_LVAS, 32772, 5, NULL, S_LAVASPLASH6, 0, 0}, // S_LAVASPLASH5 - {SPR_LVAS, 32773, 5, NULL, S_NULL, 0, 0}, // S_LAVASPLASH6 - {SPR_LVAS, 32774, 5, NULL, S_LAVASMOKE2, 0, 0}, // S_LAVASMOKE1 - {SPR_LVAS, 32775, 5, NULL, S_LAVASMOKE3, 0, 0}, // S_LAVASMOKE2 - {SPR_LVAS, 32776, 5, NULL, S_LAVASMOKE4, 0, 0}, // S_LAVASMOKE3 - {SPR_LVAS, 32777, 5, NULL, S_LAVASMOKE5, 0, 0}, // S_LAVASMOKE4 - {SPR_LVAS, 32778, 5, NULL, S_NULL, 0, 0}, // S_LAVASMOKE5 - {SPR_SLDG, 0, 8, NULL, S_SLUDGECHUNK2, 0, 0}, // S_SLUDGECHUNK1 - {SPR_SLDG, 1, 8, NULL, S_SLUDGECHUNK3, 0, 0}, // S_SLUDGECHUNK2 - {SPR_SLDG, 2, 8, NULL, S_SLUDGECHUNK4, 0, 0}, // S_SLUDGECHUNK3 - {SPR_SLDG, 3, 8, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNK4 - {SPR_SLDG, 3, 6, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNKX - {SPR_SLDG, 4, 5, NULL, S_SLUDGESPLASH2, 0, 0}, // S_SLUDGESPLASH1 - {SPR_SLDG, 5, 5, NULL, S_SLUDGESPLASH3, 0, 0}, // S_SLUDGESPLASH2 - {SPR_SLDG, 6, 5, NULL, S_SLUDGESPLASH4, 0, 0}, // S_SLUDGESPLASH3 - {SPR_SLDG, 7, 5, NULL, S_NULL, 0, 0}, // S_SLUDGESPLASH4 - {SPR_SKH1, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG70_1 - {SPR_SKH2, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG60_1 - {SPR_SKH3, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG45_1 - {SPR_SKH4, 0, -1, NULL, S_NULL, 0, 0}, // S_SKULLHANG35_1 - {SPR_CHDL, 0, 4, NULL, S_CHANDELIER2, 0, 0}, // S_CHANDELIER1 - {SPR_CHDL, 1, 4, NULL, S_CHANDELIER3, 0, 0}, // S_CHANDELIER2 - {SPR_CHDL, 2, 4, NULL, S_CHANDELIER1, 0, 0}, // S_CHANDELIER3 - {SPR_SRTC, 0, 4, NULL, S_SERPTORCH2, 0, 0}, // S_SERPTORCH1 - {SPR_SRTC, 1, 4, NULL, S_SERPTORCH3, 0, 0}, // S_SERPTORCH2 - {SPR_SRTC, 2, 4, NULL, S_SERPTORCH1, 0, 0}, // S_SERPTORCH3 - {SPR_SMPL, 0, -1, NULL, S_NULL, 0, 0}, // S_SMALLPILLAR - {SPR_STGS, 0, -1, NULL, S_NULL, 0, 0}, // S_STALAGMITESMALL - {SPR_STGL, 0, -1, NULL, S_NULL, 0, 0}, // S_STALAGMITELARGE - {SPR_STCS, 0, -1, NULL, S_NULL, 0, 0}, // S_STALACTITESMALL - {SPR_STCL, 0, -1, NULL, S_NULL, 0, 0}, // S_STALACTITELARGE - {SPR_KFR1, 32768, 3, NULL, S_FIREBRAZIER2, 0, 0}, // S_FIREBRAZIER1 - {SPR_KFR1, 32769, 3, NULL, S_FIREBRAZIER3, 0, 0}, // S_FIREBRAZIER2 - {SPR_KFR1, 32770, 3, NULL, S_FIREBRAZIER4, 0, 0}, // S_FIREBRAZIER3 - {SPR_KFR1, 32771, 3, NULL, S_FIREBRAZIER5, 0, 0}, // S_FIREBRAZIER4 - {SPR_KFR1, 32772, 3, NULL, S_FIREBRAZIER6, 0, 0}, // S_FIREBRAZIER5 - {SPR_KFR1, 32773, 3, NULL, S_FIREBRAZIER7, 0, 0}, // S_FIREBRAZIER6 - {SPR_KFR1, 32774, 3, NULL, S_FIREBRAZIER8, 0, 0}, // S_FIREBRAZIER7 - {SPR_KFR1, 32775, 3, NULL, S_FIREBRAZIER1, 0, 0}, // S_FIREBRAZIER8 - {SPR_BARL, 0, -1, NULL, S_NULL, 0, 0}, // S_BARREL - {SPR_BRPL, 0, -1, NULL, S_NULL, 0, 0}, // S_BRPILLAR - {SPR_MOS1, 0, -1, NULL, S_NULL, 0, 0}, // S_MOSS1 - {SPR_MOS2, 0, -1, NULL, S_NULL, 0, 0}, // S_MOSS2 - {SPR_WTRH, 32768, 6, NULL, S_WALLTORCH2, 0, 0}, // S_WALLTORCH1 - {SPR_WTRH, 32769, 6, NULL, S_WALLTORCH3, 0, 0}, // S_WALLTORCH2 - {SPR_WTRH, 32770, 6, NULL, S_WALLTORCH1, 0, 0}, // S_WALLTORCH3 - {SPR_HCOR, 0, -1, NULL, S_NULL, 0, 0}, // S_HANGINGCORPSE - {SPR_KGZ1, 0, 1, NULL, S_KEYGIZMO2, 0, 0}, // S_KEYGIZMO1 - {SPR_KGZ1, 0, 1, A_InitKeyGizmo, S_KEYGIZMO3, 0, 0}, // S_KEYGIZMO2 - {SPR_KGZ1, 0, -1, NULL, S_NULL, 0, 0}, // S_KEYGIZMO3 - {SPR_KGZB, 0, 1, NULL, S_KGZ_START, 0, 0}, // S_KGZ_START - {SPR_KGZB, 32768, -1, NULL, S_NULL, 0, 0}, // S_KGZ_BLUEFLOAT1 - {SPR_KGZG, 32768, -1, NULL, S_NULL, 0, 0}, // S_KGZ_GREENFLOAT1 - {SPR_KGZY, 32768, -1, NULL, S_NULL, 0, 0}, // S_KGZ_YELLOWFLOAT1 - {SPR_VLCO, 0, 350, NULL, S_VOLCANO2, 0, 0}, // S_VOLCANO1 - {SPR_VLCO, 0, 35, A_VolcanoSet, S_VOLCANO3, 0, 0}, // S_VOLCANO2 - {SPR_VLCO, 1, 3, NULL, S_VOLCANO4, 0, 0}, // S_VOLCANO3 - {SPR_VLCO, 2, 3, NULL, S_VOLCANO5, 0, 0}, // S_VOLCANO4 - {SPR_VLCO, 3, 3, NULL, S_VOLCANO6, 0, 0}, // S_VOLCANO5 - {SPR_VLCO, 1, 3, NULL, S_VOLCANO7, 0, 0}, // S_VOLCANO6 - {SPR_VLCO, 2, 3, NULL, S_VOLCANO8, 0, 0}, // S_VOLCANO7 - {SPR_VLCO, 3, 3, NULL, S_VOLCANO9, 0, 0}, // S_VOLCANO8 - {SPR_VLCO, 4, 10, A_VolcanoBlast, S_VOLCANO2, 0, 0}, // S_VOLCANO9 - {SPR_VFBL, 0, 4, A_BeastPuff, S_VOLCANOBALL2, 0, 0}, // S_VOLCANOBALL1 - {SPR_VFBL, 1, 4, A_BeastPuff, S_VOLCANOBALL1, 0, 0}, // S_VOLCANOBALL2 - {SPR_XPL1, 0, 4, A_VolcBallImpact, S_VOLCANOBALLX2, 0, 0}, // S_VOLCANOBALLX1 - {SPR_XPL1, 1, 4, NULL, S_VOLCANOBALLX3, 0, 0}, // S_VOLCANOBALLX2 - {SPR_XPL1, 2, 4, NULL, S_VOLCANOBALLX4, 0, 0}, // S_VOLCANOBALLX3 - {SPR_XPL1, 3, 4, NULL, S_VOLCANOBALLX5, 0, 0}, // S_VOLCANOBALLX4 - {SPR_XPL1, 4, 4, NULL, S_VOLCANOBALLX6, 0, 0}, // S_VOLCANOBALLX5 - {SPR_XPL1, 5, 4, NULL, S_NULL, 0, 0}, // S_VOLCANOBALLX6 - {SPR_VTFB, 0, 4, NULL, S_VOLCANOTBALL2, 0, 0}, // S_VOLCANOTBALL1 - {SPR_VTFB, 1, 4, NULL, S_VOLCANOTBALL1, 0, 0}, // S_VOLCANOTBALL2 - {SPR_SFFI, 2, 4, NULL, S_VOLCANOTBALLX2, 0, 0}, // S_VOLCANOTBALLX1 - {SPR_SFFI, 1, 4, NULL, S_VOLCANOTBALLX3, 0, 0}, // S_VOLCANOTBALLX2 - {SPR_SFFI, 0, 4, NULL, S_VOLCANOTBALLX4, 0, 0}, // S_VOLCANOTBALLX3 - {SPR_SFFI, 1, 4, NULL, S_VOLCANOTBALLX5, 0, 0}, // S_VOLCANOTBALLX4 - {SPR_SFFI, 2, 4, NULL, S_VOLCANOTBALLX6, 0, 0}, // S_VOLCANOTBALLX5 - {SPR_SFFI, 3, 4, NULL, S_VOLCANOTBALLX7, 0, 0}, // S_VOLCANOTBALLX6 - {SPR_SFFI, 4, 4, NULL, S_NULL, 0, 0}, // S_VOLCANOTBALLX7 - {SPR_TGLT, 0, 8, A_SpawnTeleGlitter, S_TELEGLITGEN1, 0, 0}, // S_TELEGLITGEN1 - {SPR_TGLT, 5, 8, A_SpawnTeleGlitter2, S_TELEGLITGEN2, 0, 0}, // S_TELEGLITGEN2 - {SPR_TGLT, 32768, 2, NULL, S_TELEGLITTER1_2, 0, 0}, // S_TELEGLITTER1_1 - {SPR_TGLT, 32769, 2, A_AccTeleGlitter, S_TELEGLITTER1_3, 0, 0}, // S_TELEGLITTER1_2 - {SPR_TGLT, 32770, 2, NULL, S_TELEGLITTER1_4, 0, 0}, // S_TELEGLITTER1_3 - {SPR_TGLT, 32771, 2, A_AccTeleGlitter, S_TELEGLITTER1_5, 0, 0}, // S_TELEGLITTER1_4 - {SPR_TGLT, 32772, 2, NULL, S_TELEGLITTER1_1, 0, 0}, // S_TELEGLITTER1_5 - {SPR_TGLT, 32773, 2, NULL, S_TELEGLITTER2_2, 0, 0}, // S_TELEGLITTER2_1 - {SPR_TGLT, 32774, 2, A_AccTeleGlitter, S_TELEGLITTER2_3, 0, 0}, // S_TELEGLITTER2_2 - {SPR_TGLT, 32775, 2, NULL, S_TELEGLITTER2_4, 0, 0}, // S_TELEGLITTER2_3 - {SPR_TGLT, 32776, 2, A_AccTeleGlitter, S_TELEGLITTER2_5, 0, 0}, // S_TELEGLITTER2_4 - {SPR_TGLT, 32777, 2, NULL, S_TELEGLITTER2_1, 0, 0}, // S_TELEGLITTER2_5 - {SPR_TELE, 32768, 6, NULL, S_TFOG2, 0, 0}, // S_TFOG1 - {SPR_TELE, 32769, 6, NULL, S_TFOG3, 0, 0}, // S_TFOG2 - {SPR_TELE, 32770, 6, NULL, S_TFOG4, 0, 0}, // S_TFOG3 - {SPR_TELE, 32771, 6, NULL, S_TFOG5, 0, 0}, // S_TFOG4 - {SPR_TELE, 32772, 6, NULL, S_TFOG6, 0, 0}, // S_TFOG5 - {SPR_TELE, 32773, 6, NULL, S_TFOG7, 0, 0}, // S_TFOG6 - {SPR_TELE, 32774, 6, NULL, S_TFOG8, 0, 0}, // S_TFOG7 - {SPR_TELE, 32775, 6, NULL, S_TFOG9, 0, 0}, // S_TFOG8 - {SPR_TELE, 32774, 6, NULL, S_TFOG10, 0, 0}, // S_TFOG9 - {SPR_TELE, 32773, 6, NULL, S_TFOG11, 0, 0}, // S_TFOG10 - {SPR_TELE, 32772, 6, NULL, S_TFOG12, 0, 0}, // S_TFOG11 - {SPR_TELE, 32771, 6, NULL, S_TFOG13, 0, 0}, // S_TFOG12 - {SPR_TELE, 32770, 6, NULL, S_NULL, 0, 0}, // S_TFOG13 - {SPR_STFF, 0, 0, A_Light0, S_NULL, 0, 0}, // S_LIGHTDONE - {SPR_STFF, 0, 1, A_WeaponReady, S_STAFFREADY, 0, 0}, // S_STAFFREADY - {SPR_STFF, 0, 1, A_Lower, S_STAFFDOWN, 0, 0}, // S_STAFFDOWN - {SPR_STFF, 0, 1, A_Raise, S_STAFFUP, 0, 0}, // S_STAFFUP - {SPR_STFF, 3, 4, A_WeaponReady, S_STAFFREADY2_2, 0, 0}, // S_STAFFREADY2_1 - {SPR_STFF, 4, 4, A_WeaponReady, S_STAFFREADY2_3, 0, 0}, // S_STAFFREADY2_2 - {SPR_STFF, 5, 4, A_WeaponReady, S_STAFFREADY2_1, 0, 0}, // S_STAFFREADY2_3 - {SPR_STFF, 3, 1, A_Lower, S_STAFFDOWN2, 0, 0}, // S_STAFFDOWN2 - {SPR_STFF, 3, 1, A_Raise, S_STAFFUP2, 0, 0}, // S_STAFFUP2 - {SPR_STFF, 1, 6, NULL, S_STAFFATK1_2, 0, 0}, // S_STAFFATK1_1 - {SPR_STFF, 2, 8, A_StaffAttackPL1, S_STAFFATK1_3, 0, 0}, // S_STAFFATK1_2 - {SPR_STFF, 1, 8, A_ReFire, S_STAFFREADY, 0, 0}, // S_STAFFATK1_3 - {SPR_STFF, 6, 6, NULL, S_STAFFATK2_2, 0, 0}, // S_STAFFATK2_1 - {SPR_STFF, 7, 8, A_StaffAttackPL2, S_STAFFATK2_3, 0, 0}, // S_STAFFATK2_2 - {SPR_STFF, 6, 8, A_ReFire, S_STAFFREADY2_1, 0, 0}, // S_STAFFATK2_3 - {SPR_PUF3, 32768, 4, NULL, S_STAFFPUFF2, 0, 0}, // S_STAFFPUFF1 - {SPR_PUF3, 1, 4, NULL, S_STAFFPUFF3, 0, 0}, // S_STAFFPUFF2 - {SPR_PUF3, 2, 4, NULL, S_STAFFPUFF4, 0, 0}, // S_STAFFPUFF3 - {SPR_PUF3, 3, 4, NULL, S_NULL, 0, 0}, // S_STAFFPUFF4 - {SPR_PUF4, 32768, 4, NULL, S_STAFFPUFF2_2, 0, 0}, // S_STAFFPUFF2_1 - {SPR_PUF4, 32769, 4, NULL, S_STAFFPUFF2_3, 0, 0}, // S_STAFFPUFF2_2 - {SPR_PUF4, 32770, 4, NULL, S_STAFFPUFF2_4, 0, 0}, // S_STAFFPUFF2_3 - {SPR_PUF4, 32771, 4, NULL, S_STAFFPUFF2_5, 0, 0}, // S_STAFFPUFF2_4 - {SPR_PUF4, 32772, 4, NULL, S_STAFFPUFF2_6, 0, 0}, // S_STAFFPUFF2_5 - {SPR_PUF4, 32773, 4, NULL, S_NULL, 0, 0}, // S_STAFFPUFF2_6 - {SPR_BEAK, 0, 1, A_BeakReady, S_BEAKREADY, 0, 0}, // S_BEAKREADY - {SPR_BEAK, 0, 1, A_Lower, S_BEAKDOWN, 0, 0}, // S_BEAKDOWN - {SPR_BEAK, 0, 1, A_BeakRaise, S_BEAKUP, 0, 0}, // S_BEAKUP - {SPR_BEAK, 0, 18, A_BeakAttackPL1, S_BEAKREADY, 0, 0}, // S_BEAKATK1_1 - {SPR_BEAK, 0, 12, A_BeakAttackPL2, S_BEAKREADY, 0, 0}, // S_BEAKATK2_1 - {SPR_WGNT, 0, -1, NULL, S_NULL, 0, 0}, // S_WGNT - {SPR_GAUN, 0, 1, A_WeaponReady, S_GAUNTLETREADY, 0, 0}, // S_GAUNTLETREADY - {SPR_GAUN, 0, 1, A_Lower, S_GAUNTLETDOWN, 0, 0}, // S_GAUNTLETDOWN - {SPR_GAUN, 0, 1, A_Raise, S_GAUNTLETUP, 0, 0}, // S_GAUNTLETUP - {SPR_GAUN, 6, 4, A_WeaponReady, S_GAUNTLETREADY2_2, 0, 0}, // S_GAUNTLETREADY2_1 - {SPR_GAUN, 7, 4, A_WeaponReady, S_GAUNTLETREADY2_3, 0, 0}, // S_GAUNTLETREADY2_2 - {SPR_GAUN, 8, 4, A_WeaponReady, S_GAUNTLETREADY2_1, 0, 0}, // S_GAUNTLETREADY2_3 - {SPR_GAUN, 6, 1, A_Lower, S_GAUNTLETDOWN2, 0, 0}, // S_GAUNTLETDOWN2 - {SPR_GAUN, 6, 1, A_Raise, S_GAUNTLETUP2, 0, 0}, // S_GAUNTLETUP2 - {SPR_GAUN, 1, 4, NULL, S_GAUNTLETATK1_2, 0, 0}, // S_GAUNTLETATK1_1 - {SPR_GAUN, 2, 4, NULL, S_GAUNTLETATK1_3, 0, 0}, // S_GAUNTLETATK1_2 - {SPR_GAUN, 32771, 4, A_GauntletAttack, S_GAUNTLETATK1_4, 0, 0}, // S_GAUNTLETATK1_3 - {SPR_GAUN, 32772, 4, A_GauntletAttack, S_GAUNTLETATK1_5, 0, 0}, // S_GAUNTLETATK1_4 - {SPR_GAUN, 32773, 4, A_GauntletAttack, S_GAUNTLETATK1_6, 0, 0}, // S_GAUNTLETATK1_5 - {SPR_GAUN, 2, 4, A_ReFire, S_GAUNTLETATK1_7, 0, 0}, // S_GAUNTLETATK1_6 - {SPR_GAUN, 1, 4, A_Light0, S_GAUNTLETREADY, 0, 0}, // S_GAUNTLETATK1_7 - {SPR_GAUN, 9, 4, NULL, S_GAUNTLETATK2_2, 0, 0}, // S_GAUNTLETATK2_1 - {SPR_GAUN, 10, 4, NULL, S_GAUNTLETATK2_3, 0, 0}, // S_GAUNTLETATK2_2 - {SPR_GAUN, 32779, 4, A_GauntletAttack, S_GAUNTLETATK2_4, 0, 0}, // S_GAUNTLETATK2_3 - {SPR_GAUN, 32780, 4, A_GauntletAttack, S_GAUNTLETATK2_5, 0, 0}, // S_GAUNTLETATK2_4 - {SPR_GAUN, 32781, 4, A_GauntletAttack, S_GAUNTLETATK2_6, 0, 0}, // S_GAUNTLETATK2_5 - {SPR_GAUN, 10, 4, A_ReFire, S_GAUNTLETATK2_7, 0, 0}, // S_GAUNTLETATK2_6 - {SPR_GAUN, 9, 4, A_Light0, S_GAUNTLETREADY2_1, 0, 0}, // S_GAUNTLETATK2_7 - {SPR_PUF1, 32768, 4, NULL, S_GAUNTLETPUFF1_2, 0, 0}, // S_GAUNTLETPUFF1_1 - {SPR_PUF1, 32769, 4, NULL, S_GAUNTLETPUFF1_3, 0, 0}, // S_GAUNTLETPUFF1_2 - {SPR_PUF1, 32770, 4, NULL, S_GAUNTLETPUFF1_4, 0, 0}, // S_GAUNTLETPUFF1_3 - {SPR_PUF1, 32771, 4, NULL, S_NULL, 0, 0}, // S_GAUNTLETPUFF1_4 - {SPR_PUF1, 32772, 4, NULL, S_GAUNTLETPUFF2_2, 0, 0}, // S_GAUNTLETPUFF2_1 - {SPR_PUF1, 32773, 4, NULL, S_GAUNTLETPUFF2_3, 0, 0}, // S_GAUNTLETPUFF2_2 - {SPR_PUF1, 32774, 4, NULL, S_GAUNTLETPUFF2_4, 0, 0}, // S_GAUNTLETPUFF2_3 - {SPR_PUF1, 32775, 4, NULL, S_NULL, 0, 0}, // S_GAUNTLETPUFF2_4 - {SPR_WBLS, 0, -1, NULL, S_NULL, 0, 0}, // S_BLSR - {SPR_BLSR, 0, 1, A_WeaponReady, S_BLASTERREADY, 0, 0}, // S_BLASTERREADY - {SPR_BLSR, 0, 1, A_Lower, S_BLASTERDOWN, 0, 0}, // S_BLASTERDOWN - {SPR_BLSR, 0, 1, A_Raise, S_BLASTERUP, 0, 0}, // S_BLASTERUP - {SPR_BLSR, 1, 3, NULL, S_BLASTERATK1_2, 0, 0}, // S_BLASTERATK1_1 - {SPR_BLSR, 2, 3, NULL, S_BLASTERATK1_3, 0, 0}, // S_BLASTERATK1_2 - {SPR_BLSR, 3, 2, A_FireBlasterPL1, S_BLASTERATK1_4, 0, 0}, // S_BLASTERATK1_3 - {SPR_BLSR, 2, 2, NULL, S_BLASTERATK1_5, 0, 0}, // S_BLASTERATK1_4 - {SPR_BLSR, 1, 2, NULL, S_BLASTERATK1_6, 0, 0}, // S_BLASTERATK1_5 - {SPR_BLSR, 0, 0, A_ReFire, S_BLASTERREADY, 0, 0}, // S_BLASTERATK1_6 - {SPR_BLSR, 1, 0, NULL, S_BLASTERATK2_2, 0, 0}, // S_BLASTERATK2_1 - {SPR_BLSR, 2, 0, NULL, S_BLASTERATK2_3, 0, 0}, // S_BLASTERATK2_2 - {SPR_BLSR, 3, 3, A_FireBlasterPL2, S_BLASTERATK2_4, 0, 0}, // S_BLASTERATK2_3 - {SPR_BLSR, 2, 4, NULL, S_BLASTERATK2_5, 0, 0}, // S_BLASTERATK2_4 - {SPR_BLSR, 1, 4, NULL, S_BLASTERATK2_6, 0, 0}, // S_BLASTERATK2_5 - {SPR_BLSR, 0, 0, A_ReFire, S_BLASTERREADY, 0, 0}, // S_BLASTERATK2_6 - {SPR_ACLO, 4, 200, NULL, S_BLASTERFX1_1, 0, 0}, // S_BLASTERFX1_1 - {SPR_FX18, 32768, 3, A_SpawnRippers, S_BLASTERFXI1_2, 0, 0}, // S_BLASTERFXI1_1 - {SPR_FX18, 32769, 3, NULL, S_BLASTERFXI1_3, 0, 0}, // S_BLASTERFXI1_2 - {SPR_FX18, 32770, 4, NULL, S_BLASTERFXI1_4, 0, 0}, // S_BLASTERFXI1_3 - {SPR_FX18, 32771, 4, NULL, S_BLASTERFXI1_5, 0, 0}, // S_BLASTERFXI1_4 - {SPR_FX18, 32772, 4, NULL, S_BLASTERFXI1_6, 0, 0}, // S_BLASTERFXI1_5 - {SPR_FX18, 32773, 4, NULL, S_BLASTERFXI1_7, 0, 0}, // S_BLASTERFXI1_6 - {SPR_FX18, 32774, 4, NULL, S_NULL, 0, 0}, // S_BLASTERFXI1_7 - {SPR_FX18, 7, 4, NULL, S_BLASTERSMOKE2, 0, 0}, // S_BLASTERSMOKE1 - {SPR_FX18, 8, 4, NULL, S_BLASTERSMOKE3, 0, 0}, // S_BLASTERSMOKE2 - {SPR_FX18, 9, 4, NULL, S_BLASTERSMOKE4, 0, 0}, // S_BLASTERSMOKE3 - {SPR_FX18, 10, 4, NULL, S_BLASTERSMOKE5, 0, 0}, // S_BLASTERSMOKE4 - {SPR_FX18, 11, 4, NULL, S_NULL, 0, 0}, // S_BLASTERSMOKE5 - {SPR_FX18, 12, 4, NULL, S_RIPPER2, 0, 0}, // S_RIPPER1 - {SPR_FX18, 13, 5, NULL, S_RIPPER1, 0, 0}, // S_RIPPER2 - {SPR_FX18, 32782, 4, NULL, S_RIPPERX2, 0, 0}, // S_RIPPERX1 - {SPR_FX18, 32783, 4, NULL, S_RIPPERX3, 0, 0}, // S_RIPPERX2 - {SPR_FX18, 32784, 4, NULL, S_RIPPERX4, 0, 0}, // S_RIPPERX3 - {SPR_FX18, 32785, 4, NULL, S_RIPPERX5, 0, 0}, // S_RIPPERX4 - {SPR_FX18, 32786, 4, NULL, S_NULL, 0, 0}, // S_RIPPERX5 - {SPR_FX17, 32768, 4, NULL, S_BLASTERPUFF1_2, 0, 0}, // S_BLASTERPUFF1_1 - {SPR_FX17, 32769, 4, NULL, S_BLASTERPUFF1_3, 0, 0}, // S_BLASTERPUFF1_2 - {SPR_FX17, 32770, 4, NULL, S_BLASTERPUFF1_4, 0, 0}, // S_BLASTERPUFF1_3 - {SPR_FX17, 32771, 4, NULL, S_BLASTERPUFF1_5, 0, 0}, // S_BLASTERPUFF1_4 - {SPR_FX17, 32772, 4, NULL, S_NULL, 0, 0}, // S_BLASTERPUFF1_5 - {SPR_FX17, 32773, 3, NULL, S_BLASTERPUFF2_2, 0, 0}, // S_BLASTERPUFF2_1 - {SPR_FX17, 32774, 3, NULL, S_BLASTERPUFF2_3, 0, 0}, // S_BLASTERPUFF2_2 - {SPR_FX17, 32775, 4, NULL, S_BLASTERPUFF2_4, 0, 0}, // S_BLASTERPUFF2_3 - {SPR_FX17, 32776, 4, NULL, S_BLASTERPUFF2_5, 0, 0}, // S_BLASTERPUFF2_4 - {SPR_FX17, 32777, 4, NULL, S_BLASTERPUFF2_6, 0, 0}, // S_BLASTERPUFF2_5 - {SPR_FX17, 32778, 4, NULL, S_BLASTERPUFF2_7, 0, 0}, // S_BLASTERPUFF2_6 - {SPR_FX17, 32779, 4, NULL, S_NULL, 0, 0}, // S_BLASTERPUFF2_7 - {SPR_WMCE, 0, -1, NULL, S_NULL, 0, 0}, // S_WMCE - {SPR_MACE, 0, 1, A_WeaponReady, S_MACEREADY, 0, 0}, // S_MACEREADY - {SPR_MACE, 0, 1, A_Lower, S_MACEDOWN, 0, 0}, // S_MACEDOWN - {SPR_MACE, 0, 1, A_Raise, S_MACEUP, 0, 0}, // S_MACEUP - {SPR_MACE, 1, 4, NULL, S_MACEATK1_2, 0, 0}, // S_MACEATK1_1 - {SPR_MACE, 2, 3, A_FireMacePL1, S_MACEATK1_3, 0, 0}, // S_MACEATK1_2 - {SPR_MACE, 3, 3, A_FireMacePL1, S_MACEATK1_4, 0, 0}, // S_MACEATK1_3 - {SPR_MACE, 4, 3, A_FireMacePL1, S_MACEATK1_5, 0, 0}, // S_MACEATK1_4 - {SPR_MACE, 5, 3, A_FireMacePL1, S_MACEATK1_6, 0, 0}, // S_MACEATK1_5 - {SPR_MACE, 2, 4, A_ReFire, S_MACEATK1_7, 0, 0}, // S_MACEATK1_6 - {SPR_MACE, 3, 4, NULL, S_MACEATK1_8, 0, 0}, // S_MACEATK1_7 - {SPR_MACE, 4, 4, NULL, S_MACEATK1_9, 0, 0}, // S_MACEATK1_8 - {SPR_MACE, 5, 4, NULL, S_MACEATK1_10, 0, 0}, // S_MACEATK1_9 - {SPR_MACE, 1, 4, NULL, S_MACEREADY, 0, 0}, // S_MACEATK1_10 - {SPR_MACE, 1, 4, NULL, S_MACEATK2_2, 0, 0}, // S_MACEATK2_1 - {SPR_MACE, 3, 4, A_FireMacePL2, S_MACEATK2_3, 0, 0}, // S_MACEATK2_2 - {SPR_MACE, 1, 4, NULL, S_MACEATK2_4, 0, 0}, // S_MACEATK2_3 - {SPR_MACE, 0, 8, A_ReFire, S_MACEREADY, 0, 0}, // S_MACEATK2_4 - {SPR_FX02, 0, 4, A_MacePL1Check, S_MACEFX1_2, 0, 0}, // S_MACEFX1_1 - {SPR_FX02, 1, 4, A_MacePL1Check, S_MACEFX1_1, 0, 0}, // S_MACEFX1_2 - {SPR_FX02, 32773, 4, A_MaceBallImpact, S_MACEFXI1_2, 0, 0}, // S_MACEFXI1_1 - {SPR_FX02, 32774, 4, NULL, S_MACEFXI1_3, 0, 0}, // S_MACEFXI1_2 - {SPR_FX02, 32775, 4, NULL, S_MACEFXI1_4, 0, 0}, // S_MACEFXI1_3 - {SPR_FX02, 32776, 4, NULL, S_MACEFXI1_5, 0, 0}, // S_MACEFXI1_4 - {SPR_FX02, 32777, 4, NULL, S_NULL, 0, 0}, // S_MACEFXI1_5 - {SPR_FX02, 2, 4, NULL, S_MACEFX2_2, 0, 0}, // S_MACEFX2_1 - {SPR_FX02, 3, 4, NULL, S_MACEFX2_1, 0, 0}, // S_MACEFX2_2 - {SPR_FX02, 32773, 4, A_MaceBallImpact2, S_MACEFXI1_2, 0, 0}, // S_MACEFXI2_1 - {SPR_FX02, 0, 4, NULL, S_MACEFX3_2, 0, 0}, // S_MACEFX3_1 - {SPR_FX02, 1, 4, NULL, S_MACEFX3_1, 0, 0}, // S_MACEFX3_2 - {SPR_FX02, 4, 99, NULL, S_MACEFX4_1, 0, 0}, // S_MACEFX4_1 - {SPR_FX02, 32770, 4, A_DeathBallImpact, S_MACEFXI1_2, 0, 0}, // S_MACEFXI4_1 - {SPR_WSKL, 0, -1, NULL, S_NULL, 0, 0}, // S_WSKL - {SPR_HROD, 0, 1, A_WeaponReady, S_HORNRODREADY, 0, 0}, // S_HORNRODREADY - {SPR_HROD, 0, 1, A_Lower, S_HORNRODDOWN, 0, 0}, // S_HORNRODDOWN - {SPR_HROD, 0, 1, A_Raise, S_HORNRODUP, 0, 0}, // S_HORNRODUP - {SPR_HROD, 0, 4, A_FireSkullRodPL1, S_HORNRODATK1_2, 0, 0}, // S_HORNRODATK1_1 - {SPR_HROD, 1, 4, A_FireSkullRodPL1, S_HORNRODATK1_3, 0, 0}, // S_HORNRODATK1_2 - {SPR_HROD, 1, 0, A_ReFire, S_HORNRODREADY, 0, 0}, // S_HORNRODATK1_3 - {SPR_HROD, 2, 2, NULL, S_HORNRODATK2_2, 0, 0}, // S_HORNRODATK2_1 - {SPR_HROD, 3, 3, NULL, S_HORNRODATK2_3, 0, 0}, // S_HORNRODATK2_2 - {SPR_HROD, 4, 2, NULL, S_HORNRODATK2_4, 0, 0}, // S_HORNRODATK2_3 - {SPR_HROD, 5, 3, NULL, S_HORNRODATK2_5, 0, 0}, // S_HORNRODATK2_4 - {SPR_HROD, 6, 4, A_FireSkullRodPL2, S_HORNRODATK2_6, 0, 0}, // S_HORNRODATK2_5 - {SPR_HROD, 5, 2, NULL, S_HORNRODATK2_7, 0, 0}, // S_HORNRODATK2_6 - {SPR_HROD, 4, 3, NULL, S_HORNRODATK2_8, 0, 0}, // S_HORNRODATK2_7 - {SPR_HROD, 3, 2, NULL, S_HORNRODATK2_9, 0, 0}, // S_HORNRODATK2_8 - {SPR_HROD, 2, 2, A_ReFire, S_HORNRODREADY, 0, 0}, // S_HORNRODATK2_9 - {SPR_FX00, 32768, 6, NULL, S_HRODFX1_2, 0, 0}, // S_HRODFX1_1 - {SPR_FX00, 32769, 6, NULL, S_HRODFX1_1, 0, 0}, // S_HRODFX1_2 - {SPR_FX00, 32775, 5, NULL, S_HRODFXI1_2, 0, 0}, // S_HRODFXI1_1 - {SPR_FX00, 32776, 5, NULL, S_HRODFXI1_3, 0, 0}, // S_HRODFXI1_2 - {SPR_FX00, 32777, 4, NULL, S_HRODFXI1_4, 0, 0}, // S_HRODFXI1_3 - {SPR_FX00, 32778, 4, NULL, S_HRODFXI1_5, 0, 0}, // S_HRODFXI1_4 - {SPR_FX00, 32779, 3, NULL, S_HRODFXI1_6, 0, 0}, // S_HRODFXI1_5 - {SPR_FX00, 32780, 3, NULL, S_NULL, 0, 0}, // S_HRODFXI1_6 - {SPR_FX00, 32770, 3, NULL, S_HRODFX2_2, 0, 0}, // S_HRODFX2_1 - {SPR_FX00, 32771, 3, A_SkullRodPL2Seek, S_HRODFX2_3, 0, 0}, // S_HRODFX2_2 - {SPR_FX00, 32772, 3, NULL, S_HRODFX2_4, 0, 0}, // S_HRODFX2_3 - {SPR_FX00, 32773, 3, A_SkullRodPL2Seek, S_HRODFX2_1, 0, 0}, // S_HRODFX2_4 - {SPR_FX00, 32775, 5, A_AddPlayerRain, S_HRODFXI2_2, 0, 0}, // S_HRODFXI2_1 - {SPR_FX00, 32776, 5, NULL, S_HRODFXI2_3, 0, 0}, // S_HRODFXI2_2 - {SPR_FX00, 32777, 4, NULL, S_HRODFXI2_4, 0, 0}, // S_HRODFXI2_3 - {SPR_FX00, 32778, 3, NULL, S_HRODFXI2_5, 0, 0}, // S_HRODFXI2_4 - {SPR_FX00, 32779, 3, NULL, S_HRODFXI2_6, 0, 0}, // S_HRODFXI2_5 - {SPR_FX00, 32780, 3, NULL, S_HRODFXI2_7, 0, 0}, // S_HRODFXI2_6 - {SPR_FX00, 6, 1, A_HideInCeiling, S_HRODFXI2_8, 0, 0}, // S_HRODFXI2_7 - {SPR_FX00, 6, 1, A_SkullRodStorm, S_HRODFXI2_8, 0, 0}, // S_HRODFXI2_8 - {SPR_FX20, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR1_1 - {SPR_FX21, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR2_1 - {SPR_FX22, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR3_1 - {SPR_FX23, 32768, -1, NULL, S_NULL, 0, 0}, // S_RAINPLR4_1 - {SPR_FX20, 32769, 4, A_RainImpact, S_RAINPLR1X_2, 0, 0}, // S_RAINPLR1X_1 - {SPR_FX20, 32770, 4, NULL, S_RAINPLR1X_3, 0, 0}, // S_RAINPLR1X_2 - {SPR_FX20, 32771, 4, NULL, S_RAINPLR1X_4, 0, 0}, // S_RAINPLR1X_3 - {SPR_FX20, 32772, 4, NULL, S_RAINPLR1X_5, 0, 0}, // S_RAINPLR1X_4 - {SPR_FX20, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR1X_5 - {SPR_FX21, 32769, 4, A_RainImpact, S_RAINPLR2X_2, 0, 0}, // S_RAINPLR2X_1 - {SPR_FX21, 32770, 4, NULL, S_RAINPLR2X_3, 0, 0}, // S_RAINPLR2X_2 - {SPR_FX21, 32771, 4, NULL, S_RAINPLR2X_4, 0, 0}, // S_RAINPLR2X_3 - {SPR_FX21, 32772, 4, NULL, S_RAINPLR2X_5, 0, 0}, // S_RAINPLR2X_4 - {SPR_FX21, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR2X_5 - {SPR_FX22, 32769, 4, A_RainImpact, S_RAINPLR3X_2, 0, 0}, // S_RAINPLR3X_1 - {SPR_FX22, 32770, 4, NULL, S_RAINPLR3X_3, 0, 0}, // S_RAINPLR3X_2 - {SPR_FX22, 32771, 4, NULL, S_RAINPLR3X_4, 0, 0}, // S_RAINPLR3X_3 - {SPR_FX22, 32772, 4, NULL, S_RAINPLR3X_5, 0, 0}, // S_RAINPLR3X_4 - {SPR_FX22, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR3X_5 - {SPR_FX23, 32769, 4, A_RainImpact, S_RAINPLR4X_2, 0, 0}, // S_RAINPLR4X_1 - {SPR_FX23, 32770, 4, NULL, S_RAINPLR4X_3, 0, 0}, // S_RAINPLR4X_2 - {SPR_FX23, 32771, 4, NULL, S_RAINPLR4X_4, 0, 0}, // S_RAINPLR4X_3 - {SPR_FX23, 32772, 4, NULL, S_RAINPLR4X_5, 0, 0}, // S_RAINPLR4X_4 - {SPR_FX23, 32773, 4, NULL, S_NULL, 0, 0}, // S_RAINPLR4X_5 - {SPR_FX20, 32774, 4, NULL, S_RAINAIRXPLR1_2, 0, 0}, // S_RAINAIRXPLR1_1 - {SPR_FX21, 32774, 4, NULL, S_RAINAIRXPLR2_2, 0, 0}, // S_RAINAIRXPLR2_1 - {SPR_FX22, 32774, 4, NULL, S_RAINAIRXPLR3_2, 0, 0}, // S_RAINAIRXPLR3_1 - {SPR_FX23, 32774, 4, NULL, S_RAINAIRXPLR4_2, 0, 0}, // S_RAINAIRXPLR4_1 - {SPR_FX20, 32775, 4, NULL, S_RAINAIRXPLR1_3, 0, 0}, // S_RAINAIRXPLR1_2 - {SPR_FX21, 32775, 4, NULL, S_RAINAIRXPLR2_3, 0, 0}, // S_RAINAIRXPLR2_2 - {SPR_FX22, 32775, 4, NULL, S_RAINAIRXPLR3_3, 0, 0}, // S_RAINAIRXPLR3_2 - {SPR_FX23, 32775, 4, NULL, S_RAINAIRXPLR4_3, 0, 0}, // S_RAINAIRXPLR4_2 - {SPR_FX20, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR1_3 - {SPR_FX21, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR2_3 - {SPR_FX22, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR3_3 - {SPR_FX23, 32776, 4, NULL, S_NULL, 0, 0}, // S_RAINAIRXPLR4_3 - {SPR_GWND, 0, 1, A_WeaponReady, S_GOLDWANDREADY, 0, 0}, // S_GOLDWANDREADY - {SPR_GWND, 0, 1, A_Lower, S_GOLDWANDDOWN, 0, 0}, // S_GOLDWANDDOWN - {SPR_GWND, 0, 1, A_Raise, S_GOLDWANDUP, 0, 0}, // S_GOLDWANDUP - {SPR_GWND, 1, 3, NULL, S_GOLDWANDATK1_2, 0, 0}, // S_GOLDWANDATK1_1 - {SPR_GWND, 2, 5, A_FireGoldWandPL1, S_GOLDWANDATK1_3, 0, 0}, // S_GOLDWANDATK1_2 - {SPR_GWND, 3, 3, NULL, S_GOLDWANDATK1_4, 0, 0}, // S_GOLDWANDATK1_3 - {SPR_GWND, 3, 0, A_ReFire, S_GOLDWANDREADY, 0, 0}, // S_GOLDWANDATK1_4 - {SPR_GWND, 1, 3, NULL, S_GOLDWANDATK2_2, 0, 0}, // S_GOLDWANDATK2_1 - {SPR_GWND, 2, 4, A_FireGoldWandPL2, S_GOLDWANDATK2_3, 0, 0}, // S_GOLDWANDATK2_2 - {SPR_GWND, 3, 3, NULL, S_GOLDWANDATK2_4, 0, 0}, // S_GOLDWANDATK2_3 - {SPR_GWND, 3, 0, A_ReFire, S_GOLDWANDREADY, 0, 0}, // S_GOLDWANDATK2_4 - {SPR_FX01, 32768, 6, NULL, S_GWANDFX1_2, 0, 0}, // S_GWANDFX1_1 - {SPR_FX01, 32769, 6, NULL, S_GWANDFX1_1, 0, 0}, // S_GWANDFX1_2 - {SPR_FX01, 32772, 3, NULL, S_GWANDFXI1_2, 0, 0}, // S_GWANDFXI1_1 - {SPR_FX01, 32773, 3, NULL, S_GWANDFXI1_3, 0, 0}, // S_GWANDFXI1_2 - {SPR_FX01, 32774, 3, NULL, S_GWANDFXI1_4, 0, 0}, // S_GWANDFXI1_3 - {SPR_FX01, 32775, 3, NULL, S_NULL, 0, 0}, // S_GWANDFXI1_4 - {SPR_FX01, 32770, 6, NULL, S_GWANDFX2_2, 0, 0}, // S_GWANDFX2_1 - {SPR_FX01, 32771, 6, NULL, S_GWANDFX2_1, 0, 0}, // S_GWANDFX2_2 - {SPR_PUF2, 32768, 3, NULL, S_GWANDPUFF1_2, 0, 0}, // S_GWANDPUFF1_1 - {SPR_PUF2, 32769, 3, NULL, S_GWANDPUFF1_3, 0, 0}, // S_GWANDPUFF1_2 - {SPR_PUF2, 32770, 3, NULL, S_GWANDPUFF1_4, 0, 0}, // S_GWANDPUFF1_3 - {SPR_PUF2, 32771, 3, NULL, S_GWANDPUFF1_5, 0, 0}, // S_GWANDPUFF1_4 - {SPR_PUF2, 32772, 3, NULL, S_NULL, 0, 0}, // S_GWANDPUFF1_5 - {SPR_WPHX, 0, -1, NULL, S_NULL, 0, 0}, // S_WPHX - {SPR_PHNX, 0, 1, A_WeaponReady, S_PHOENIXREADY, 0, 0}, // S_PHOENIXREADY - {SPR_PHNX, 0, 1, A_Lower, S_PHOENIXDOWN, 0, 0}, // S_PHOENIXDOWN - {SPR_PHNX, 0, 1, A_Raise, S_PHOENIXUP, 0, 0}, // S_PHOENIXUP - {SPR_PHNX, 1, 5, NULL, S_PHOENIXATK1_2, 0, 0}, // S_PHOENIXATK1_1 - {SPR_PHNX, 2, 7, A_FirePhoenixPL1, S_PHOENIXATK1_3, 0, 0}, // S_PHOENIXATK1_2 - {SPR_PHNX, 3, 4, NULL, S_PHOENIXATK1_4, 0, 0}, // S_PHOENIXATK1_3 - {SPR_PHNX, 1, 4, NULL, S_PHOENIXATK1_5, 0, 0}, // S_PHOENIXATK1_4 - {SPR_PHNX, 1, 0, A_ReFire, S_PHOENIXREADY, 0, 0}, // S_PHOENIXATK1_5 - {SPR_PHNX, 1, 3, A_InitPhoenixPL2, S_PHOENIXATK2_2, 0, 0}, // S_PHOENIXATK2_1 - {SPR_PHNX, 32770, 1, A_FirePhoenixPL2, S_PHOENIXATK2_3, 0, 0}, // S_PHOENIXATK2_2 - {SPR_PHNX, 1, 4, A_ReFire, S_PHOENIXATK2_4, 0, 0}, // S_PHOENIXATK2_3 - {SPR_PHNX, 1, 4, A_ShutdownPhoenixPL2, S_PHOENIXREADY, 0, 0}, // S_PHOENIXATK2_4 - {SPR_FX04, 32768, 4, A_PhoenixPuff, S_PHOENIXFX1_1, 0, 0}, // S_PHOENIXFX1_1 - {SPR_FX08, 32768, 6, A_Explode, S_PHOENIXFXI1_2, 0, 0}, // S_PHOENIXFXI1_1 - {SPR_FX08, 32769, 5, NULL, S_PHOENIXFXI1_3, 0, 0}, // S_PHOENIXFXI1_2 - {SPR_FX08, 32770, 5, NULL, S_PHOENIXFXI1_4, 0, 0}, // S_PHOENIXFXI1_3 - {SPR_FX08, 32771, 4, NULL, S_PHOENIXFXI1_5, 0, 0}, // S_PHOENIXFXI1_4 - {SPR_FX08, 32772, 4, NULL, S_PHOENIXFXI1_6, 0, 0}, // S_PHOENIXFXI1_5 - {SPR_FX08, 32773, 4, NULL, S_PHOENIXFXI1_7, 0, 0}, // S_PHOENIXFXI1_6 - {SPR_FX08, 32774, 4, NULL, S_PHOENIXFXI1_8, 0, 0}, // S_PHOENIXFXI1_7 - {SPR_FX08, 32775, 4, NULL, S_NULL, 0, 0}, // S_PHOENIXFXI1_8 - {SPR_FX08, 32776, 8, NULL, S_PHOENIXFXIX_1, 0, 0 }, // S_PHOENIXFXIX_1 - {SPR_FX08, 32777, 8, A_RemovedPhoenixFunc, S_PHOENIXFXIX_2, 0, 0 }, // S_PHOENIXFXIX_2 - {SPR_FX08, 32778, 8, NULL, S_NULL, 0, 0 }, // S_PHOENIXFXIX_3 - {SPR_FX04, 1, 4, NULL, S_PHOENIXPUFF2, 0, 0}, // S_PHOENIXPUFF1 - {SPR_FX04, 2, 4, NULL, S_PHOENIXPUFF3, 0, 0}, // S_PHOENIXPUFF2 - {SPR_FX04, 3, 4, NULL, S_PHOENIXPUFF4, 0, 0}, // S_PHOENIXPUFF3 - {SPR_FX04, 4, 4, NULL, S_PHOENIXPUFF5, 0, 0}, // S_PHOENIXPUFF4 - {SPR_FX04, 5, 4, NULL, S_NULL, 0, 0}, // S_PHOENIXPUFF5 - {SPR_FX09, 32768, 2, NULL, S_PHOENIXFX2_2, 0, 0}, // S_PHOENIXFX2_1 - {SPR_FX09, 32769, 2, NULL, S_PHOENIXFX2_3, 0, 0}, // S_PHOENIXFX2_2 - {SPR_FX09, 32768, 2, NULL, S_PHOENIXFX2_4, 0, 0}, // S_PHOENIXFX2_3 - {SPR_FX09, 32769, 2, NULL, S_PHOENIXFX2_5, 0, 0}, // S_PHOENIXFX2_4 - {SPR_FX09, 32768, 2, NULL, S_PHOENIXFX2_6, 0, 0}, // S_PHOENIXFX2_5 - {SPR_FX09, 32769, 2, A_FlameEnd, S_PHOENIXFX2_7, 0, 0}, // S_PHOENIXFX2_6 - {SPR_FX09, 32770, 2, NULL, S_PHOENIXFX2_8, 0, 0}, // S_PHOENIXFX2_7 - {SPR_FX09, 32771, 2, NULL, S_PHOENIXFX2_9, 0, 0}, // S_PHOENIXFX2_8 - {SPR_FX09, 32772, 2, NULL, S_PHOENIXFX2_10, 0, 0}, // S_PHOENIXFX2_9 - {SPR_FX09, 32773, 2, NULL, S_NULL, 0, 0}, // S_PHOENIXFX2_10 - {SPR_FX09, 32774, 3, NULL, S_PHOENIXFXI2_2, 0, 0}, // S_PHOENIXFXI2_1 - {SPR_FX09, 32775, 3, A_FloatPuff, S_PHOENIXFXI2_3, 0, 0}, // S_PHOENIXFXI2_2 - {SPR_FX09, 32776, 4, NULL, S_PHOENIXFXI2_4, 0, 0}, // S_PHOENIXFXI2_3 - {SPR_FX09, 32777, 5, NULL, S_PHOENIXFXI2_5, 0, 0}, // S_PHOENIXFXI2_4 - {SPR_FX09, 32778, 5, NULL, S_NULL, 0, 0}, // S_PHOENIXFXI2_5 - {SPR_WBOW, 0, -1, NULL, S_NULL, 0, 0}, // S_WBOW - {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW2, 0, 0}, // S_CRBOW1 - {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW3, 0, 0}, // S_CRBOW2 - {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW4, 0, 0}, // S_CRBOW3 - {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW5, 0, 0}, // S_CRBOW4 - {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW6, 0, 0}, // S_CRBOW5 - {SPR_CRBW, 0, 1, A_WeaponReady, S_CRBOW7, 0, 0}, // S_CRBOW6 - {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW8, 0, 0}, // S_CRBOW7 - {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW9, 0, 0}, // S_CRBOW8 - {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW10, 0, 0}, // S_CRBOW9 - {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW11, 0, 0}, // S_CRBOW10 - {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW12, 0, 0}, // S_CRBOW11 - {SPR_CRBW, 1, 1, A_WeaponReady, S_CRBOW13, 0, 0}, // S_CRBOW12 - {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW14, 0, 0}, // S_CRBOW13 - {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW15, 0, 0}, // S_CRBOW14 - {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW16, 0, 0}, // S_CRBOW15 - {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW17, 0, 0}, // S_CRBOW16 - {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW18, 0, 0}, // S_CRBOW17 - {SPR_CRBW, 2, 1, A_WeaponReady, S_CRBOW1, 0, 0}, // S_CRBOW18 - {SPR_CRBW, 0, 1, A_Lower, S_CRBOWDOWN, 0, 0}, // S_CRBOWDOWN - {SPR_CRBW, 0, 1, A_Raise, S_CRBOWUP, 0, 0}, // S_CRBOWUP - {SPR_CRBW, 3, 6, A_FireCrossbowPL1, S_CRBOWATK1_2, 0, 0}, // S_CRBOWATK1_1 - {SPR_CRBW, 4, 3, NULL, S_CRBOWATK1_3, 0, 0}, // S_CRBOWATK1_2 - {SPR_CRBW, 5, 3, NULL, S_CRBOWATK1_4, 0, 0}, // S_CRBOWATK1_3 - {SPR_CRBW, 6, 3, NULL, S_CRBOWATK1_5, 0, 0}, // S_CRBOWATK1_4 - {SPR_CRBW, 7, 3, NULL, S_CRBOWATK1_6, 0, 0}, // S_CRBOWATK1_5 - {SPR_CRBW, 0, 4, NULL, S_CRBOWATK1_7, 0, 0}, // S_CRBOWATK1_6 - {SPR_CRBW, 1, 4, NULL, S_CRBOWATK1_8, 0, 0}, // S_CRBOWATK1_7 - {SPR_CRBW, 2, 5, A_ReFire, S_CRBOW1, 0, 0}, // S_CRBOWATK1_8 - {SPR_CRBW, 3, 5, A_FireCrossbowPL2, S_CRBOWATK2_2, 0, 0}, // S_CRBOWATK2_1 - {SPR_CRBW, 4, 3, NULL, S_CRBOWATK2_3, 0, 0}, // S_CRBOWATK2_2 - {SPR_CRBW, 5, 2, NULL, S_CRBOWATK2_4, 0, 0}, // S_CRBOWATK2_3 - {SPR_CRBW, 6, 3, NULL, S_CRBOWATK2_5, 0, 0}, // S_CRBOWATK2_4 - {SPR_CRBW, 7, 2, NULL, S_CRBOWATK2_6, 0, 0}, // S_CRBOWATK2_5 - {SPR_CRBW, 0, 3, NULL, S_CRBOWATK2_7, 0, 0}, // S_CRBOWATK2_6 - {SPR_CRBW, 1, 3, NULL, S_CRBOWATK2_8, 0, 0}, // S_CRBOWATK2_7 - {SPR_CRBW, 2, 4, A_ReFire, S_CRBOW1, 0, 0}, // S_CRBOWATK2_8 - {SPR_FX03, 32769, 1, NULL, S_CRBOWFX1, 0, 0}, // S_CRBOWFX1 - {SPR_FX03, 32775, 8, NULL, S_CRBOWFXI1_2, 0, 0}, // S_CRBOWFXI1_1 - {SPR_FX03, 32776, 8, NULL, S_CRBOWFXI1_3, 0, 0}, // S_CRBOWFXI1_2 - {SPR_FX03, 32777, 8, NULL, S_NULL, 0, 0}, // S_CRBOWFXI1_3 - {SPR_FX03, 32769, 1, A_BoltSpark, S_CRBOWFX2, 0, 0}, // S_CRBOWFX2 - {SPR_FX03, 32768, 1, NULL, S_CRBOWFX3, 0, 0}, // S_CRBOWFX3 - {SPR_FX03, 32770, 8, NULL, S_CRBOWFXI3_2, 0, 0}, // S_CRBOWFXI3_1 - {SPR_FX03, 32771, 8, NULL, S_CRBOWFXI3_3, 0, 0}, // S_CRBOWFXI3_2 - {SPR_FX03, 32772, 8, NULL, S_NULL, 0, 0}, // S_CRBOWFXI3_3 - {SPR_FX03, 32773, 8, NULL, S_CRBOWFX4_2, 0, 0}, // S_CRBOWFX4_1 - {SPR_FX03, 32774, 8, NULL, S_NULL, 0, 0}, // S_CRBOWFX4_2 - {SPR_BLOD, 2, 8, NULL, S_BLOOD2, 0, 0}, // S_BLOOD1 - {SPR_BLOD, 1, 8, NULL, S_BLOOD3, 0, 0}, // S_BLOOD2 - {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOOD3 - {SPR_BLOD, 2, 8, NULL, S_BLOODSPLATTER2, 0, 0}, // S_BLOODSPLATTER1 - {SPR_BLOD, 1, 8, NULL, S_BLOODSPLATTER3, 0, 0}, // S_BLOODSPLATTER2 - {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTER3 - {SPR_BLOD, 0, 6, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTERX - {SPR_PLAY, 0, -1, NULL, S_NULL, 0, 0}, // S_PLAY - {SPR_PLAY, 0, 4, NULL, S_PLAY_RUN2, 0, 0}, // S_PLAY_RUN1 - {SPR_PLAY, 1, 4, NULL, S_PLAY_RUN3, 0, 0}, // S_PLAY_RUN2 - {SPR_PLAY, 2, 4, NULL, S_PLAY_RUN4, 0, 0}, // S_PLAY_RUN3 - {SPR_PLAY, 3, 4, NULL, S_PLAY_RUN1, 0, 0}, // S_PLAY_RUN4 - {SPR_PLAY, 4, 12, NULL, S_PLAY, 0, 0}, // S_PLAY_ATK1 - {SPR_PLAY, 32773, 6, NULL, S_PLAY_ATK1, 0, 0}, // S_PLAY_ATK2 - {SPR_PLAY, 6, 4, NULL, S_PLAY_PAIN2, 0, 0}, // S_PLAY_PAIN - {SPR_PLAY, 6, 4, A_Pain, S_PLAY, 0, 0}, // S_PLAY_PAIN2 - {SPR_PLAY, 7, 6, NULL, S_PLAY_DIE2, 0, 0}, // S_PLAY_DIE1 - {SPR_PLAY, 8, 6, A_Scream, S_PLAY_DIE3, 0, 0}, // S_PLAY_DIE2 - {SPR_PLAY, 9, 6, NULL, S_PLAY_DIE4, 0, 0}, // S_PLAY_DIE3 - {SPR_PLAY, 10, 6, NULL, S_PLAY_DIE5, 0, 0}, // S_PLAY_DIE4 - {SPR_PLAY, 11, 6, A_NoBlocking, S_PLAY_DIE6, 0, 0}, // S_PLAY_DIE5 - {SPR_PLAY, 12, 6, NULL, S_PLAY_DIE7, 0, 0}, // S_PLAY_DIE6 - {SPR_PLAY, 13, 6, NULL, S_PLAY_DIE8, 0, 0}, // S_PLAY_DIE7 - {SPR_PLAY, 14, 6, NULL, S_PLAY_DIE9, 0, 0}, // S_PLAY_DIE8 - {SPR_PLAY, 15, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_PLAY_DIE9 - {SPR_PLAY, 16, 5, A_Scream, S_PLAY_XDIE2, 0, 0}, // S_PLAY_XDIE1 - {SPR_PLAY, 17, 5, A_SkullPop, S_PLAY_XDIE3, 0, 0}, // S_PLAY_XDIE2 - {SPR_PLAY, 18, 5, A_NoBlocking, S_PLAY_XDIE4, 0, 0}, // S_PLAY_XDIE3 - {SPR_PLAY, 19, 5, NULL, S_PLAY_XDIE5, 0, 0}, // S_PLAY_XDIE4 - {SPR_PLAY, 20, 5, NULL, S_PLAY_XDIE6, 0, 0}, // S_PLAY_XDIE5 - {SPR_PLAY, 21, 5, NULL, S_PLAY_XDIE7, 0, 0}, // S_PLAY_XDIE6 - {SPR_PLAY, 22, 5, NULL, S_PLAY_XDIE8, 0, 0}, // S_PLAY_XDIE7 - {SPR_PLAY, 23, 5, NULL, S_PLAY_XDIE9, 0, 0}, // S_PLAY_XDIE8 - {SPR_PLAY, 24, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_PLAY_XDIE9 - {SPR_FDTH, 32768, 5, A_FlameSnd, S_PLAY_FDTH2, 0, 0}, // S_PLAY_FDTH1 - {SPR_FDTH, 32769, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_FDTH2 - {SPR_FDTH, 32770, 5, NULL, S_PLAY_FDTH4, 0, 0}, // S_PLAY_FDTH3 - {SPR_FDTH, 32771, 4, A_Scream, S_PLAY_FDTH5, 0, 0}, // S_PLAY_FDTH4 - {SPR_FDTH, 32772, 5, NULL, S_PLAY_FDTH6, 0, 0}, // S_PLAY_FDTH5 - {SPR_FDTH, 32773, 4, NULL, S_PLAY_FDTH7, 0, 0}, // S_PLAY_FDTH6 - {SPR_FDTH, 32774, 5, A_FlameSnd, S_PLAY_FDTH8, 0, 0}, // S_PLAY_FDTH7 - {SPR_FDTH, 32775, 4, NULL, S_PLAY_FDTH9, 0, 0}, // S_PLAY_FDTH8 - {SPR_FDTH, 32776, 5, NULL, S_PLAY_FDTH10, 0, 0}, // S_PLAY_FDTH9 - {SPR_FDTH, 32777, 4, NULL, S_PLAY_FDTH11, 0, 0}, // S_PLAY_FDTH10 - {SPR_FDTH, 32778, 5, NULL, S_PLAY_FDTH12, 0, 0}, // S_PLAY_FDTH11 - {SPR_FDTH, 32779, 4, NULL, S_PLAY_FDTH13, 0, 0}, // S_PLAY_FDTH12 - {SPR_FDTH, 32780, 5, NULL, S_PLAY_FDTH14, 0, 0}, // S_PLAY_FDTH13 - {SPR_FDTH, 32781, 4, NULL, S_PLAY_FDTH15, 0, 0}, // S_PLAY_FDTH14 - {SPR_FDTH, 32782, 5, A_NoBlocking, S_PLAY_FDTH16, 0, 0}, // S_PLAY_FDTH15 - {SPR_FDTH, 32783, 4, NULL, S_PLAY_FDTH17, 0, 0}, // S_PLAY_FDTH16 - {SPR_FDTH, 32784, 5, NULL, S_PLAY_FDTH18, 0, 0}, // S_PLAY_FDTH17 - {SPR_FDTH, 32785, 4, NULL, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH18 - {SPR_ACLO, 4, 35, A_CheckBurnGone, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH19 - {SPR_ACLO, 4, 8, NULL, S_NULL, 0, 0}, // S_PLAY_FDTH20 - {SPR_BSKL, 0, 5, A_CheckSkullFloor, S_BLOODYSKULL2, 0, 0}, // S_BLOODYSKULL1 - {SPR_BSKL, 1, 5, A_CheckSkullFloor, S_BLOODYSKULL3, 0, 0}, // S_BLOODYSKULL2 - {SPR_BSKL, 2, 5, A_CheckSkullFloor, S_BLOODYSKULL4, 0, 0}, // S_BLOODYSKULL3 - {SPR_BSKL, 3, 5, A_CheckSkullFloor, S_BLOODYSKULL5, 0, 0}, // S_BLOODYSKULL4 - {SPR_BSKL, 4, 5, A_CheckSkullFloor, S_BLOODYSKULL1, 0, 0}, // S_BLOODYSKULL5 - {SPR_BSKL, 5, 16, A_CheckSkullDone, S_BLOODYSKULLX1, 0, 0}, // S_BLOODYSKULLX1 - {SPR_BSKL, 5, 1050, NULL, S_NULL, 0, 0}, // S_BLOODYSKULLX2 - {SPR_CHKN, 0, -1, NULL, S_NULL, 0, 0}, // S_CHICPLAY - {SPR_CHKN, 0, 3, NULL, S_CHICPLAY_RUN2, 0, 0}, // S_CHICPLAY_RUN1 - {SPR_CHKN, 1, 3, NULL, S_CHICPLAY_RUN3, 0, 0}, // S_CHICPLAY_RUN2 - {SPR_CHKN, 0, 3, NULL, S_CHICPLAY_RUN4, 0, 0}, // S_CHICPLAY_RUN3 - {SPR_CHKN, 1, 3, NULL, S_CHICPLAY_RUN1, 0, 0}, // S_CHICPLAY_RUN4 - {SPR_CHKN, 2, 12, NULL, S_CHICPLAY, 0, 0}, // S_CHICPLAY_ATK1 - {SPR_CHKN, 3, 4, A_Feathers, S_CHICPLAY_PAIN2, 0, 0}, // S_CHICPLAY_PAIN - {SPR_CHKN, 2, 4, A_Pain, S_CHICPLAY, 0, 0}, // S_CHICPLAY_PAIN2 - {SPR_CHKN, 0, 10, A_ChicLook, S_CHICKEN_LOOK2, 0, 0}, // S_CHICKEN_LOOK1 - {SPR_CHKN, 1, 10, A_ChicLook, S_CHICKEN_LOOK1, 0, 0}, // S_CHICKEN_LOOK2 - {SPR_CHKN, 0, 3, A_ChicChase, S_CHICKEN_WALK2, 0, 0}, // S_CHICKEN_WALK1 - {SPR_CHKN, 1, 3, A_ChicChase, S_CHICKEN_WALK1, 0, 0}, // S_CHICKEN_WALK2 - {SPR_CHKN, 3, 5, A_Feathers, S_CHICKEN_PAIN2, 0, 0}, // S_CHICKEN_PAIN1 - {SPR_CHKN, 2, 5, A_ChicPain, S_CHICKEN_WALK1, 0, 0}, // S_CHICKEN_PAIN2 - {SPR_CHKN, 0, 8, A_FaceTarget, S_CHICKEN_ATK2, 0, 0}, // S_CHICKEN_ATK1 - {SPR_CHKN, 2, 10, A_ChicAttack, S_CHICKEN_WALK1, 0, 0}, // S_CHICKEN_ATK2 - {SPR_CHKN, 4, 6, A_Scream, S_CHICKEN_DIE2, 0, 0}, // S_CHICKEN_DIE1 - {SPR_CHKN, 5, 6, A_Feathers, S_CHICKEN_DIE3, 0, 0}, // S_CHICKEN_DIE2 - {SPR_CHKN, 6, 6, NULL, S_CHICKEN_DIE4, 0, 0}, // S_CHICKEN_DIE3 - {SPR_CHKN, 7, 6, A_NoBlocking, S_CHICKEN_DIE5, 0, 0}, // S_CHICKEN_DIE4 - {SPR_CHKN, 8, 6, NULL, S_CHICKEN_DIE6, 0, 0}, // S_CHICKEN_DIE5 - {SPR_CHKN, 9, 6, NULL, S_CHICKEN_DIE7, 0, 0}, // S_CHICKEN_DIE6 - {SPR_CHKN, 10, 6, NULL, S_CHICKEN_DIE8, 0, 0}, // S_CHICKEN_DIE7 - {SPR_CHKN, 11, -1, NULL, S_NULL, 0, 0}, // S_CHICKEN_DIE8 - {SPR_CHKN, 12, 3, NULL, S_FEATHER2, 0, 0}, // S_FEATHER1 - {SPR_CHKN, 13, 3, NULL, S_FEATHER3, 0, 0}, // S_FEATHER2 - {SPR_CHKN, 14, 3, NULL, S_FEATHER4, 0, 0}, // S_FEATHER3 - {SPR_CHKN, 15, 3, NULL, S_FEATHER5, 0, 0}, // S_FEATHER4 - {SPR_CHKN, 16, 3, NULL, S_FEATHER6, 0, 0}, // S_FEATHER5 - {SPR_CHKN, 15, 3, NULL, S_FEATHER7, 0, 0}, // S_FEATHER6 - {SPR_CHKN, 14, 3, NULL, S_FEATHER8, 0, 0}, // S_FEATHER7 - {SPR_CHKN, 13, 3, NULL, S_FEATHER1, 0, 0}, // S_FEATHER8 - {SPR_CHKN, 13, 6, NULL, S_NULL, 0, 0}, // S_FEATHERX - {SPR_MUMM, 0, 10, A_Look, S_MUMMY_LOOK2, 0, 0}, // S_MUMMY_LOOK1 - {SPR_MUMM, 1, 10, A_Look, S_MUMMY_LOOK1, 0, 0}, // S_MUMMY_LOOK2 - {SPR_MUMM, 0, 4, A_Chase, S_MUMMY_WALK2, 0, 0}, // S_MUMMY_WALK1 - {SPR_MUMM, 1, 4, A_Chase, S_MUMMY_WALK3, 0, 0}, // S_MUMMY_WALK2 - {SPR_MUMM, 2, 4, A_Chase, S_MUMMY_WALK4, 0, 0}, // S_MUMMY_WALK3 - {SPR_MUMM, 3, 4, A_Chase, S_MUMMY_WALK1, 0, 0}, // S_MUMMY_WALK4 - {SPR_MUMM, 4, 6, A_FaceTarget, S_MUMMY_ATK2, 0, 0}, // S_MUMMY_ATK1 - {SPR_MUMM, 5, 6, A_MummyAttack, S_MUMMY_ATK3, 0, 0}, // S_MUMMY_ATK2 - {SPR_MUMM, 6, 6, A_FaceTarget, S_MUMMY_WALK1, 0, 0}, // S_MUMMY_ATK3 - {SPR_MUMM, 23, 5, A_FaceTarget, S_MUMMYL_ATK2, 0, 0}, // S_MUMMYL_ATK1 - {SPR_MUMM, 32792, 5, A_FaceTarget, S_MUMMYL_ATK3, 0, 0}, // S_MUMMYL_ATK2 - {SPR_MUMM, 23, 5, A_FaceTarget, S_MUMMYL_ATK4, 0, 0}, // S_MUMMYL_ATK3 - {SPR_MUMM, 32792, 5, A_FaceTarget, S_MUMMYL_ATK5, 0, 0}, // S_MUMMYL_ATK4 - {SPR_MUMM, 23, 5, A_FaceTarget, S_MUMMYL_ATK6, 0, 0}, // S_MUMMYL_ATK5 - {SPR_MUMM, 32792, 15, A_MummyAttack2, S_MUMMY_WALK1, 0, 0}, // S_MUMMYL_ATK6 - {SPR_MUMM, 7, 4, NULL, S_MUMMY_PAIN2, 0, 0}, // S_MUMMY_PAIN1 - {SPR_MUMM, 7, 4, A_Pain, S_MUMMY_WALK1, 0, 0}, // S_MUMMY_PAIN2 - {SPR_MUMM, 8, 5, NULL, S_MUMMY_DIE2, 0, 0}, // S_MUMMY_DIE1 - {SPR_MUMM, 9, 5, A_Scream, S_MUMMY_DIE3, 0, 0}, // S_MUMMY_DIE2 - {SPR_MUMM, 10, 5, A_MummySoul, S_MUMMY_DIE4, 0, 0}, // S_MUMMY_DIE3 - {SPR_MUMM, 11, 5, NULL, S_MUMMY_DIE5, 0, 0}, // S_MUMMY_DIE4 - {SPR_MUMM, 12, 5, A_NoBlocking, S_MUMMY_DIE6, 0, 0}, // S_MUMMY_DIE5 - {SPR_MUMM, 13, 5, NULL, S_MUMMY_DIE7, 0, 0}, // S_MUMMY_DIE6 - {SPR_MUMM, 14, 5, NULL, S_MUMMY_DIE8, 0, 0}, // S_MUMMY_DIE7 - {SPR_MUMM, 15, -1, NULL, S_NULL, 0, 0}, // S_MUMMY_DIE8 - {SPR_MUMM, 16, 5, NULL, S_MUMMY_SOUL2, 0, 0}, // S_MUMMY_SOUL1 - {SPR_MUMM, 17, 5, NULL, S_MUMMY_SOUL3, 0, 0}, // S_MUMMY_SOUL2 - {SPR_MUMM, 18, 5, NULL, S_MUMMY_SOUL4, 0, 0}, // S_MUMMY_SOUL3 - {SPR_MUMM, 19, 9, NULL, S_MUMMY_SOUL5, 0, 0}, // S_MUMMY_SOUL4 - {SPR_MUMM, 20, 5, NULL, S_MUMMY_SOUL6, 0, 0}, // S_MUMMY_SOUL5 - {SPR_MUMM, 21, 5, NULL, S_MUMMY_SOUL7, 0, 0}, // S_MUMMY_SOUL6 - {SPR_MUMM, 22, 5, NULL, S_NULL, 0, 0}, // S_MUMMY_SOUL7 - {SPR_FX15, 32768, 5, A_ContMobjSound, S_MUMMYFX1_2, 0, 0}, // S_MUMMYFX1_1 - {SPR_FX15, 32769, 5, A_MummyFX1Seek, S_MUMMYFX1_3, 0, 0}, // S_MUMMYFX1_2 - {SPR_FX15, 32770, 5, NULL, S_MUMMYFX1_4, 0, 0}, // S_MUMMYFX1_3 - {SPR_FX15, 32769, 5, A_MummyFX1Seek, S_MUMMYFX1_1, 0, 0}, // S_MUMMYFX1_4 - {SPR_FX15, 32771, 5, NULL, S_MUMMYFXI1_2, 0, 0}, // S_MUMMYFXI1_1 - {SPR_FX15, 32772, 5, NULL, S_MUMMYFXI1_3, 0, 0}, // S_MUMMYFXI1_2 - {SPR_FX15, 32773, 5, NULL, S_MUMMYFXI1_4, 0, 0}, // S_MUMMYFXI1_3 - {SPR_FX15, 32774, 5, NULL, S_NULL, 0, 0}, // S_MUMMYFXI1_4 - {SPR_BEAS, 0, 10, A_Look, S_BEAST_LOOK2, 0, 0}, // S_BEAST_LOOK1 - {SPR_BEAS, 1, 10, A_Look, S_BEAST_LOOK1, 0, 0}, // S_BEAST_LOOK2 - {SPR_BEAS, 0, 3, A_Chase, S_BEAST_WALK2, 0, 0}, // S_BEAST_WALK1 - {SPR_BEAS, 1, 3, A_Chase, S_BEAST_WALK3, 0, 0}, // S_BEAST_WALK2 - {SPR_BEAS, 2, 3, A_Chase, S_BEAST_WALK4, 0, 0}, // S_BEAST_WALK3 - {SPR_BEAS, 3, 3, A_Chase, S_BEAST_WALK5, 0, 0}, // S_BEAST_WALK4 - {SPR_BEAS, 4, 3, A_Chase, S_BEAST_WALK6, 0, 0}, // S_BEAST_WALK5 - {SPR_BEAS, 5, 3, A_Chase, S_BEAST_WALK1, 0, 0}, // S_BEAST_WALK6 - {SPR_BEAS, 7, 10, A_FaceTarget, S_BEAST_ATK2, 0, 0}, // S_BEAST_ATK1 - {SPR_BEAS, 8, 10, A_BeastAttack, S_BEAST_WALK1, 0, 0}, // S_BEAST_ATK2 - {SPR_BEAS, 6, 3, NULL, S_BEAST_PAIN2, 0, 0}, // S_BEAST_PAIN1 - {SPR_BEAS, 6, 3, A_Pain, S_BEAST_WALK1, 0, 0}, // S_BEAST_PAIN2 - {SPR_BEAS, 17, 6, NULL, S_BEAST_DIE2, 0, 0}, // S_BEAST_DIE1 - {SPR_BEAS, 18, 6, A_Scream, S_BEAST_DIE3, 0, 0}, // S_BEAST_DIE2 - {SPR_BEAS, 19, 6, NULL, S_BEAST_DIE4, 0, 0}, // S_BEAST_DIE3 - {SPR_BEAS, 20, 6, NULL, S_BEAST_DIE5, 0, 0}, // S_BEAST_DIE4 - {SPR_BEAS, 21, 6, NULL, S_BEAST_DIE6, 0, 0}, // S_BEAST_DIE5 - {SPR_BEAS, 22, 6, A_NoBlocking, S_BEAST_DIE7, 0, 0}, // S_BEAST_DIE6 - {SPR_BEAS, 23, 6, NULL, S_BEAST_DIE8, 0, 0}, // S_BEAST_DIE7 - {SPR_BEAS, 24, 6, NULL, S_BEAST_DIE9, 0, 0}, // S_BEAST_DIE8 - {SPR_BEAS, 25, -1, NULL, S_NULL, 0, 0}, // S_BEAST_DIE9 - {SPR_BEAS, 9, 5, NULL, S_BEAST_XDIE2, 0, 0}, // S_BEAST_XDIE1 - {SPR_BEAS, 10, 6, A_Scream, S_BEAST_XDIE3, 0, 0}, // S_BEAST_XDIE2 - {SPR_BEAS, 11, 5, NULL, S_BEAST_XDIE4, 0, 0}, // S_BEAST_XDIE3 - {SPR_BEAS, 12, 6, NULL, S_BEAST_XDIE5, 0, 0}, // S_BEAST_XDIE4 - {SPR_BEAS, 13, 5, NULL, S_BEAST_XDIE6, 0, 0}, // S_BEAST_XDIE5 - {SPR_BEAS, 14, 6, A_NoBlocking, S_BEAST_XDIE7, 0, 0}, // S_BEAST_XDIE6 - {SPR_BEAS, 15, 5, NULL, S_BEAST_XDIE8, 0, 0}, // S_BEAST_XDIE7 - {SPR_BEAS, 16, -1, NULL, S_NULL, 0, 0}, // S_BEAST_XDIE8 - {SPR_FRB1, 0, 2, A_BeastPuff, S_BEASTBALL2, 0, 0}, // S_BEASTBALL1 - {SPR_FRB1, 0, 2, A_BeastPuff, S_BEASTBALL3, 0, 0}, // S_BEASTBALL2 - {SPR_FRB1, 1, 2, A_BeastPuff, S_BEASTBALL4, 0, 0}, // S_BEASTBALL3 - {SPR_FRB1, 1, 2, A_BeastPuff, S_BEASTBALL5, 0, 0}, // S_BEASTBALL4 - {SPR_FRB1, 2, 2, A_BeastPuff, S_BEASTBALL6, 0, 0}, // S_BEASTBALL5 - {SPR_FRB1, 2, 2, A_BeastPuff, S_BEASTBALL1, 0, 0}, // S_BEASTBALL6 - {SPR_FRB1, 3, 4, NULL, S_BEASTBALLX2, 0, 0}, // S_BEASTBALLX1 - {SPR_FRB1, 4, 4, NULL, S_BEASTBALLX3, 0, 0}, // S_BEASTBALLX2 - {SPR_FRB1, 5, 4, NULL, S_BEASTBALLX4, 0, 0}, // S_BEASTBALLX3 - {SPR_FRB1, 6, 4, NULL, S_BEASTBALLX5, 0, 0}, // S_BEASTBALLX4 - {SPR_FRB1, 7, 4, NULL, S_NULL, 0, 0}, // S_BEASTBALLX5 - {SPR_FRB1, 0, 4, NULL, S_BURNBALL2, 0, 0}, // S_BURNBALL1 - {SPR_FRB1, 1, 4, NULL, S_BURNBALL3, 0, 0}, // S_BURNBALL2 - {SPR_FRB1, 2, 4, NULL, S_BURNBALL4, 0, 0}, // S_BURNBALL3 - {SPR_FRB1, 3, 4, NULL, S_BURNBALL5, 0, 0}, // S_BURNBALL4 - {SPR_FRB1, 4, 4, NULL, S_BURNBALL6, 0, 0}, // S_BURNBALL5 - {SPR_FRB1, 5, 4, NULL, S_BURNBALL7, 0, 0}, // S_BURNBALL6 - {SPR_FRB1, 6, 4, NULL, S_BURNBALL8, 0, 0}, // S_BURNBALL7 - {SPR_FRB1, 7, 4, NULL, S_NULL, 0, 0}, // S_BURNBALL8 - {SPR_FRB1, 32768, 4, NULL, S_BURNBALLFB2, 0, 0}, // S_BURNBALLFB1 - {SPR_FRB1, 32769, 4, NULL, S_BURNBALLFB3, 0, 0}, // S_BURNBALLFB2 - {SPR_FRB1, 32770, 4, NULL, S_BURNBALLFB4, 0, 0}, // S_BURNBALLFB3 - {SPR_FRB1, 32771, 4, NULL, S_BURNBALLFB5, 0, 0}, // S_BURNBALLFB4 - {SPR_FRB1, 32772, 4, NULL, S_BURNBALLFB6, 0, 0}, // S_BURNBALLFB5 - {SPR_FRB1, 32773, 4, NULL, S_BURNBALLFB7, 0, 0}, // S_BURNBALLFB6 - {SPR_FRB1, 32774, 4, NULL, S_BURNBALLFB8, 0, 0}, // S_BURNBALLFB7 - {SPR_FRB1, 32775, 4, NULL, S_NULL, 0, 0}, // S_BURNBALLFB8 - {SPR_FRB1, 3, 4, NULL, S_PUFFY2, 0, 0}, // S_PUFFY1 - {SPR_FRB1, 4, 4, NULL, S_PUFFY3, 0, 0}, // S_PUFFY2 - {SPR_FRB1, 5, 4, NULL, S_PUFFY4, 0, 0}, // S_PUFFY3 - {SPR_FRB1, 6, 4, NULL, S_PUFFY5, 0, 0}, // S_PUFFY4 - {SPR_FRB1, 7, 4, NULL, S_NULL, 0, 0}, // S_PUFFY5 - {SPR_SNKE, 0, 10, A_Look, S_SNAKE_LOOK2, 0, 0}, // S_SNAKE_LOOK1 - {SPR_SNKE, 1, 10, A_Look, S_SNAKE_LOOK1, 0, 0}, // S_SNAKE_LOOK2 - {SPR_SNKE, 0, 4, A_Chase, S_SNAKE_WALK2, 0, 0}, // S_SNAKE_WALK1 - {SPR_SNKE, 1, 4, A_Chase, S_SNAKE_WALK3, 0, 0}, // S_SNAKE_WALK2 - {SPR_SNKE, 2, 4, A_Chase, S_SNAKE_WALK4, 0, 0}, // S_SNAKE_WALK3 - {SPR_SNKE, 3, 4, A_Chase, S_SNAKE_WALK1, 0, 0}, // S_SNAKE_WALK4 - {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK2, 0, 0}, // S_SNAKE_ATK1 - {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK3, 0, 0}, // S_SNAKE_ATK2 - {SPR_SNKE, 5, 4, A_SnakeAttack, S_SNAKE_ATK4, 0, 0}, // S_SNAKE_ATK3 - {SPR_SNKE, 5, 4, A_SnakeAttack, S_SNAKE_ATK5, 0, 0}, // S_SNAKE_ATK4 - {SPR_SNKE, 5, 4, A_SnakeAttack, S_SNAKE_ATK6, 0, 0}, // S_SNAKE_ATK5 - {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK7, 0, 0}, // S_SNAKE_ATK6 - {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK8, 0, 0}, // S_SNAKE_ATK7 - {SPR_SNKE, 5, 5, A_FaceTarget, S_SNAKE_ATK9, 0, 0}, // S_SNAKE_ATK8 - {SPR_SNKE, 5, 4, A_SnakeAttack2, S_SNAKE_WALK1, 0, 0}, // S_SNAKE_ATK9 - {SPR_SNKE, 4, 3, NULL, S_SNAKE_PAIN2, 0, 0}, // S_SNAKE_PAIN1 - {SPR_SNKE, 4, 3, A_Pain, S_SNAKE_WALK1, 0, 0}, // S_SNAKE_PAIN2 - {SPR_SNKE, 6, 5, NULL, S_SNAKE_DIE2, 0, 0}, // S_SNAKE_DIE1 - {SPR_SNKE, 7, 5, A_Scream, S_SNAKE_DIE3, 0, 0}, // S_SNAKE_DIE2 - {SPR_SNKE, 8, 5, NULL, S_SNAKE_DIE4, 0, 0}, // S_SNAKE_DIE3 - {SPR_SNKE, 9, 5, NULL, S_SNAKE_DIE5, 0, 0}, // S_SNAKE_DIE4 - {SPR_SNKE, 10, 5, NULL, S_SNAKE_DIE6, 0, 0}, // S_SNAKE_DIE5 - {SPR_SNKE, 11, 5, NULL, S_SNAKE_DIE7, 0, 0}, // S_SNAKE_DIE6 - {SPR_SNKE, 12, 5, A_NoBlocking, S_SNAKE_DIE8, 0, 0}, // S_SNAKE_DIE7 - {SPR_SNKE, 13, 5, NULL, S_SNAKE_DIE9, 0, 0}, // S_SNAKE_DIE8 - {SPR_SNKE, 14, 5, NULL, S_SNAKE_DIE10, 0, 0}, // S_SNAKE_DIE9 - {SPR_SNKE, 15, -1, NULL, S_NULL, 0, 0}, // S_SNAKE_DIE10 - {SPR_SNFX, 32768, 5, NULL, S_SNAKEPRO_A2, 0, 0}, // S_SNAKEPRO_A1 - {SPR_SNFX, 32769, 5, NULL, S_SNAKEPRO_A3, 0, 0}, // S_SNAKEPRO_A2 - {SPR_SNFX, 32770, 5, NULL, S_SNAKEPRO_A4, 0, 0}, // S_SNAKEPRO_A3 - {SPR_SNFX, 32771, 5, NULL, S_SNAKEPRO_A1, 0, 0}, // S_SNAKEPRO_A4 - {SPR_SNFX, 32772, 5, NULL, S_SNAKEPRO_AX2, 0, 0}, // S_SNAKEPRO_AX1 - {SPR_SNFX, 32773, 5, NULL, S_SNAKEPRO_AX3, 0, 0}, // S_SNAKEPRO_AX2 - {SPR_SNFX, 32774, 4, NULL, S_SNAKEPRO_AX4, 0, 0}, // S_SNAKEPRO_AX3 - {SPR_SNFX, 32775, 3, NULL, S_SNAKEPRO_AX5, 0, 0}, // S_SNAKEPRO_AX4 - {SPR_SNFX, 32776, 3, NULL, S_NULL, 0, 0}, // S_SNAKEPRO_AX5 - {SPR_SNFX, 32777, 6, NULL, S_SNAKEPRO_B2, 0, 0}, // S_SNAKEPRO_B1 - {SPR_SNFX, 32778, 6, NULL, S_SNAKEPRO_B1, 0, 0}, // S_SNAKEPRO_B2 - {SPR_SNFX, 32779, 5, NULL, S_SNAKEPRO_BX2, 0, 0}, // S_SNAKEPRO_BX1 - {SPR_SNFX, 32780, 5, NULL, S_SNAKEPRO_BX3, 0, 0}, // S_SNAKEPRO_BX2 - {SPR_SNFX, 32781, 4, NULL, S_SNAKEPRO_BX4, 0, 0}, // S_SNAKEPRO_BX3 - {SPR_SNFX, 32782, 3, NULL, S_NULL, 0, 0}, // S_SNAKEPRO_BX4 - {SPR_HEAD, 0, 10, A_Look, S_HEAD_LOOK, 0, 0}, // S_HEAD_LOOK - {SPR_HEAD, 0, 4, A_Chase, S_HEAD_FLOAT, 0, 0}, // S_HEAD_FLOAT - {SPR_HEAD, 0, 5, A_FaceTarget, S_HEAD_ATK2, 0, 0}, // S_HEAD_ATK1 - {SPR_HEAD, 1, 20, A_HeadAttack, S_HEAD_FLOAT, 0, 0}, // S_HEAD_ATK2 - {SPR_HEAD, 0, 4, NULL, S_HEAD_PAIN2, 0, 0}, // S_HEAD_PAIN1 - {SPR_HEAD, 0, 4, A_Pain, S_HEAD_FLOAT, 0, 0}, // S_HEAD_PAIN2 - {SPR_HEAD, 2, 7, NULL, S_HEAD_DIE2, 0, 0}, // S_HEAD_DIE1 - {SPR_HEAD, 3, 7, A_Scream, S_HEAD_DIE3, 0, 0}, // S_HEAD_DIE2 - {SPR_HEAD, 4, 7, NULL, S_HEAD_DIE4, 0, 0}, // S_HEAD_DIE3 - {SPR_HEAD, 5, 7, NULL, S_HEAD_DIE5, 0, 0}, // S_HEAD_DIE4 - {SPR_HEAD, 6, 7, A_NoBlocking, S_HEAD_DIE6, 0, 0}, // S_HEAD_DIE5 - {SPR_HEAD, 7, 7, NULL, S_HEAD_DIE7, 0, 0}, // S_HEAD_DIE6 - {SPR_HEAD, 8, -1, A_BossDeath, S_NULL, 0, 0}, // S_HEAD_DIE7 - {SPR_FX05, 0, 6, NULL, S_HEADFX1_2, 0, 0}, // S_HEADFX1_1 - {SPR_FX05, 1, 6, NULL, S_HEADFX1_3, 0, 0}, // S_HEADFX1_2 - {SPR_FX05, 2, 6, NULL, S_HEADFX1_1, 0, 0}, // S_HEADFX1_3 - {SPR_FX05, 3, 5, A_HeadIceImpact, S_HEADFXI1_2, 0, 0}, // S_HEADFXI1_1 - {SPR_FX05, 4, 5, NULL, S_HEADFXI1_3, 0, 0}, // S_HEADFXI1_2 - {SPR_FX05, 5, 5, NULL, S_HEADFXI1_4, 0, 0}, // S_HEADFXI1_3 - {SPR_FX05, 6, 5, NULL, S_NULL, 0, 0}, // S_HEADFXI1_4 - {SPR_FX05, 7, 6, NULL, S_HEADFX2_2, 0, 0}, // S_HEADFX2_1 - {SPR_FX05, 8, 6, NULL, S_HEADFX2_3, 0, 0}, // S_HEADFX2_2 - {SPR_FX05, 9, 6, NULL, S_HEADFX2_1, 0, 0}, // S_HEADFX2_3 - {SPR_FX05, 3, 5, NULL, S_HEADFXI2_2, 0, 0}, // S_HEADFXI2_1 - {SPR_FX05, 4, 5, NULL, S_HEADFXI2_3, 0, 0}, // S_HEADFXI2_2 - {SPR_FX05, 5, 5, NULL, S_HEADFXI2_4, 0, 0}, // S_HEADFXI2_3 - {SPR_FX05, 6, 5, NULL, S_NULL, 0, 0}, // S_HEADFXI2_4 - {SPR_FX06, 0, 4, A_HeadFireGrow, S_HEADFX3_2, 0, 0}, // S_HEADFX3_1 - {SPR_FX06, 1, 4, A_HeadFireGrow, S_HEADFX3_3, 0, 0}, // S_HEADFX3_2 - {SPR_FX06, 2, 4, A_HeadFireGrow, S_HEADFX3_1, 0, 0}, // S_HEADFX3_3 - {SPR_FX06, 0, 5, NULL, S_HEADFX3_5, 0, 0}, // S_HEADFX3_4 - {SPR_FX06, 1, 5, NULL, S_HEADFX3_6, 0, 0}, // S_HEADFX3_5 - {SPR_FX06, 2, 5, NULL, S_HEADFX3_4, 0, 0}, // S_HEADFX3_6 - {SPR_FX06, 3, 5, NULL, S_HEADFXI3_2, 0, 0}, // S_HEADFXI3_1 - {SPR_FX06, 4, 5, NULL, S_HEADFXI3_3, 0, 0}, // S_HEADFXI3_2 - {SPR_FX06, 5, 5, NULL, S_HEADFXI3_4, 0, 0}, // S_HEADFXI3_3 - {SPR_FX06, 6, 5, NULL, S_NULL, 0, 0}, // S_HEADFXI3_4 - {SPR_FX07, 3, 3, NULL, S_HEADFX4_2, 0, 0}, // S_HEADFX4_1 - {SPR_FX07, 4, 3, NULL, S_HEADFX4_3, 0, 0}, // S_HEADFX4_2 - {SPR_FX07, 5, 3, NULL, S_HEADFX4_4, 0, 0}, // S_HEADFX4_3 - {SPR_FX07, 6, 3, NULL, S_HEADFX4_5, 0, 0}, // S_HEADFX4_4 - {SPR_FX07, 0, 3, A_WhirlwindSeek, S_HEADFX4_6, 0, 0}, // S_HEADFX4_5 - {SPR_FX07, 1, 3, A_WhirlwindSeek, S_HEADFX4_7, 0, 0}, // S_HEADFX4_6 - {SPR_FX07, 2, 3, A_WhirlwindSeek, S_HEADFX4_5, 0, 0}, // S_HEADFX4_7 - {SPR_FX07, 6, 4, NULL, S_HEADFXI4_2, 0, 0}, // S_HEADFXI4_1 - {SPR_FX07, 5, 4, NULL, S_HEADFXI4_3, 0, 0}, // S_HEADFXI4_2 - {SPR_FX07, 4, 4, NULL, S_HEADFXI4_4, 0, 0}, // S_HEADFXI4_3 - {SPR_FX07, 3, 4, NULL, S_NULL, 0, 0}, // S_HEADFXI4_4 - {SPR_CLNK, 0, 10, A_Look, S_CLINK_LOOK2, 0, 0}, // S_CLINK_LOOK1 - {SPR_CLNK, 1, 10, A_Look, S_CLINK_LOOK1, 0, 0}, // S_CLINK_LOOK2 - {SPR_CLNK, 0, 3, A_Chase, S_CLINK_WALK2, 0, 0}, // S_CLINK_WALK1 - {SPR_CLNK, 1, 3, A_Chase, S_CLINK_WALK3, 0, 0}, // S_CLINK_WALK2 - {SPR_CLNK, 2, 3, A_Chase, S_CLINK_WALK4, 0, 0}, // S_CLINK_WALK3 - {SPR_CLNK, 3, 3, A_Chase, S_CLINK_WALK1, 0, 0}, // S_CLINK_WALK4 - {SPR_CLNK, 4, 5, A_FaceTarget, S_CLINK_ATK2, 0, 0}, // S_CLINK_ATK1 - {SPR_CLNK, 5, 4, A_FaceTarget, S_CLINK_ATK3, 0, 0}, // S_CLINK_ATK2 - {SPR_CLNK, 6, 7, A_ClinkAttack, S_CLINK_WALK1, 0, 0}, // S_CLINK_ATK3 - {SPR_CLNK, 7, 3, NULL, S_CLINK_PAIN2, 0, 0}, // S_CLINK_PAIN1 - {SPR_CLNK, 7, 3, A_Pain, S_CLINK_WALK1, 0, 0}, // S_CLINK_PAIN2 - {SPR_CLNK, 8, 6, NULL, S_CLINK_DIE2, 0, 0}, // S_CLINK_DIE1 - {SPR_CLNK, 9, 6, NULL, S_CLINK_DIE3, 0, 0}, // S_CLINK_DIE2 - {SPR_CLNK, 10, 5, A_Scream, S_CLINK_DIE4, 0, 0}, // S_CLINK_DIE3 - {SPR_CLNK, 11, 5, A_NoBlocking, S_CLINK_DIE5, 0, 0}, // S_CLINK_DIE4 - {SPR_CLNK, 12, 5, NULL, S_CLINK_DIE6, 0, 0}, // S_CLINK_DIE5 - {SPR_CLNK, 13, 5, NULL, S_CLINK_DIE7, 0, 0}, // S_CLINK_DIE6 - {SPR_CLNK, 14, -1, NULL, S_NULL, 0, 0}, // S_CLINK_DIE7 - {SPR_WZRD, 0, 10, A_Look, S_WIZARD_LOOK2, 0, 0}, // S_WIZARD_LOOK1 - {SPR_WZRD, 1, 10, A_Look, S_WIZARD_LOOK1, 0, 0}, // S_WIZARD_LOOK2 - {SPR_WZRD, 0, 3, A_Chase, S_WIZARD_WALK2, 0, 0}, // S_WIZARD_WALK1 - {SPR_WZRD, 0, 4, A_Chase, S_WIZARD_WALK3, 0, 0}, // S_WIZARD_WALK2 - {SPR_WZRD, 0, 3, A_Chase, S_WIZARD_WALK4, 0, 0}, // S_WIZARD_WALK3 - {SPR_WZRD, 0, 4, A_Chase, S_WIZARD_WALK5, 0, 0}, // S_WIZARD_WALK4 - {SPR_WZRD, 1, 3, A_Chase, S_WIZARD_WALK6, 0, 0}, // S_WIZARD_WALK5 - {SPR_WZRD, 1, 4, A_Chase, S_WIZARD_WALK7, 0, 0}, // S_WIZARD_WALK6 - {SPR_WZRD, 1, 3, A_Chase, S_WIZARD_WALK8, 0, 0}, // S_WIZARD_WALK7 - {SPR_WZRD, 1, 4, A_Chase, S_WIZARD_WALK1, 0, 0}, // S_WIZARD_WALK8 - {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK2, 0, 0}, // S_WIZARD_ATK1 - {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK3, 0, 0}, // S_WIZARD_ATK2 - {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK4, 0, 0}, // S_WIZARD_ATK3 - {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK5, 0, 0}, // S_WIZARD_ATK4 - {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK6, 0, 0}, // S_WIZARD_ATK5 - {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK7, 0, 0}, // S_WIZARD_ATK6 - {SPR_WZRD, 2, 4, A_WizAtk1, S_WIZARD_ATK8, 0, 0}, // S_WIZARD_ATK7 - {SPR_WZRD, 2, 4, A_WizAtk2, S_WIZARD_ATK9, 0, 0}, // S_WIZARD_ATK8 - {SPR_WZRD, 3, 12, A_WizAtk3, S_WIZARD_WALK1, 0, 0}, // S_WIZARD_ATK9 - {SPR_WZRD, 4, 3, A_GhostOff, S_WIZARD_PAIN2, 0, 0}, // S_WIZARD_PAIN1 - {SPR_WZRD, 4, 3, A_Pain, S_WIZARD_WALK1, 0, 0}, // S_WIZARD_PAIN2 - {SPR_WZRD, 5, 6, A_GhostOff, S_WIZARD_DIE2, 0, 0}, // S_WIZARD_DIE1 - {SPR_WZRD, 6, 6, A_Scream, S_WIZARD_DIE3, 0, 0}, // S_WIZARD_DIE2 - {SPR_WZRD, 7, 6, NULL, S_WIZARD_DIE4, 0, 0}, // S_WIZARD_DIE3 - {SPR_WZRD, 8, 6, NULL, S_WIZARD_DIE5, 0, 0}, // S_WIZARD_DIE4 - {SPR_WZRD, 9, 6, A_NoBlocking, S_WIZARD_DIE6, 0, 0}, // S_WIZARD_DIE5 - {SPR_WZRD, 10, 6, NULL, S_WIZARD_DIE7, 0, 0}, // S_WIZARD_DIE6 - {SPR_WZRD, 11, 6, NULL, S_WIZARD_DIE8, 0, 0}, // S_WIZARD_DIE7 - {SPR_WZRD, 12, -1, NULL, S_NULL, 0, 0}, // S_WIZARD_DIE8 - {SPR_FX11, 32768, 6, NULL, S_WIZFX1_2, 0, 0}, // S_WIZFX1_1 - {SPR_FX11, 32769, 6, NULL, S_WIZFX1_1, 0, 0}, // S_WIZFX1_2 - {SPR_FX11, 32770, 5, NULL, S_WIZFXI1_2, 0, 0}, // S_WIZFXI1_1 - {SPR_FX11, 32771, 5, NULL, S_WIZFXI1_3, 0, 0}, // S_WIZFXI1_2 - {SPR_FX11, 32772, 5, NULL, S_WIZFXI1_4, 0, 0}, // S_WIZFXI1_3 - {SPR_FX11, 32773, 5, NULL, S_WIZFXI1_5, 0, 0}, // S_WIZFXI1_4 - {SPR_FX11, 32774, 5, NULL, S_NULL, 0, 0}, // S_WIZFXI1_5 - {SPR_IMPX, 0, 10, A_Look, S_IMP_LOOK2, 0, 0}, // S_IMP_LOOK1 - {SPR_IMPX, 1, 10, A_Look, S_IMP_LOOK3, 0, 0}, // S_IMP_LOOK2 - {SPR_IMPX, 2, 10, A_Look, S_IMP_LOOK4, 0, 0}, // S_IMP_LOOK3 - {SPR_IMPX, 1, 10, A_Look, S_IMP_LOOK1, 0, 0}, // S_IMP_LOOK4 - {SPR_IMPX, 0, 3, A_Chase, S_IMP_FLY2, 0, 0}, // S_IMP_FLY1 - {SPR_IMPX, 0, 3, A_Chase, S_IMP_FLY3, 0, 0}, // S_IMP_FLY2 - {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY4, 0, 0}, // S_IMP_FLY3 - {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY5, 0, 0}, // S_IMP_FLY4 - {SPR_IMPX, 2, 3, A_Chase, S_IMP_FLY6, 0, 0}, // S_IMP_FLY5 - {SPR_IMPX, 2, 3, A_Chase, S_IMP_FLY7, 0, 0}, // S_IMP_FLY6 - {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY8, 0, 0}, // S_IMP_FLY7 - {SPR_IMPX, 1, 3, A_Chase, S_IMP_FLY1, 0, 0}, // S_IMP_FLY8 - {SPR_IMPX, 3, 6, A_FaceTarget, S_IMP_MEATK2, 0, 0}, // S_IMP_MEATK1 - {SPR_IMPX, 4, 6, A_FaceTarget, S_IMP_MEATK3, 0, 0}, // S_IMP_MEATK2 - {SPR_IMPX, 5, 6, A_ImpMeAttack, S_IMP_FLY1, 0, 0}, // S_IMP_MEATK3 - {SPR_IMPX, 0, 10, A_FaceTarget, S_IMP_MSATK1_2, 0, 0}, // S_IMP_MSATK1_1 - {SPR_IMPX, 1, 6, A_ImpMsAttack, S_IMP_MSATK1_3, 0, 0}, // S_IMP_MSATK1_2 - {SPR_IMPX, 2, 6, NULL, S_IMP_MSATK1_4, 0, 0}, // S_IMP_MSATK1_3 - {SPR_IMPX, 1, 6, NULL, S_IMP_MSATK1_5, 0, 0}, // S_IMP_MSATK1_4 - {SPR_IMPX, 0, 6, NULL, S_IMP_MSATK1_6, 0, 0}, // S_IMP_MSATK1_5 - {SPR_IMPX, 1, 6, NULL, S_IMP_MSATK1_3, 0, 0}, // S_IMP_MSATK1_6 - {SPR_IMPX, 3, 6, A_FaceTarget, S_IMP_MSATK2_2, 0, 0}, // S_IMP_MSATK2_1 - {SPR_IMPX, 4, 6, A_FaceTarget, S_IMP_MSATK2_3, 0, 0}, // S_IMP_MSATK2_2 - {SPR_IMPX, 5, 6, A_ImpMsAttack2, S_IMP_FLY1, 0, 0}, // S_IMP_MSATK2_3 - {SPR_IMPX, 6, 3, NULL, S_IMP_PAIN2, 0, 0}, // S_IMP_PAIN1 - {SPR_IMPX, 6, 3, A_Pain, S_IMP_FLY1, 0, 0}, // S_IMP_PAIN2 - {SPR_IMPX, 6, 4, A_ImpDeath, S_IMP_DIE2, 0, 0}, // S_IMP_DIE1 - {SPR_IMPX, 7, 5, NULL, S_IMP_DIE2, 0, 0}, // S_IMP_DIE2 - {SPR_IMPX, 18, 5, A_ImpXDeath1, S_IMP_XDIE2, 0, 0}, // S_IMP_XDIE1 - {SPR_IMPX, 19, 5, NULL, S_IMP_XDIE3, 0, 0}, // S_IMP_XDIE2 - {SPR_IMPX, 20, 5, NULL, S_IMP_XDIE4, 0, 0}, // S_IMP_XDIE3 - {SPR_IMPX, 21, 5, A_ImpXDeath2, S_IMP_XDIE5, 0, 0}, // S_IMP_XDIE4 - {SPR_IMPX, 22, 5, NULL, S_IMP_XDIE5, 0, 0}, // S_IMP_XDIE5 - {SPR_IMPX, 8, 7, A_ImpExplode, S_IMP_CRASH2, 0, 0}, // S_IMP_CRASH1 - {SPR_IMPX, 9, 7, A_Scream, S_IMP_CRASH3, 0, 0}, // S_IMP_CRASH2 - {SPR_IMPX, 10, 7, NULL, S_IMP_CRASH4, 0, 0}, // S_IMP_CRASH3 - {SPR_IMPX, 11, -1, NULL, S_NULL, 0, 0}, // S_IMP_CRASH4 - {SPR_IMPX, 23, 7, NULL, S_IMP_XCRASH2, 0, 0}, // S_IMP_XCRASH1 - {SPR_IMPX, 24, 7, NULL, S_IMP_XCRASH3, 0, 0}, // S_IMP_XCRASH2 - {SPR_IMPX, 25, -1, NULL, S_NULL, 0, 0}, // S_IMP_XCRASH3 - {SPR_IMPX, 12, 5, NULL, S_IMP_CHUNKA2, 0, 0}, // S_IMP_CHUNKA1 - {SPR_IMPX, 13, 700, NULL, S_IMP_CHUNKA3, 0, 0}, // S_IMP_CHUNKA2 - {SPR_IMPX, 14, 700, NULL, S_NULL, 0, 0}, // S_IMP_CHUNKA3 - {SPR_IMPX, 15, 5, NULL, S_IMP_CHUNKB2, 0, 0}, // S_IMP_CHUNKB1 - {SPR_IMPX, 16, 700, NULL, S_IMP_CHUNKB3, 0, 0}, // S_IMP_CHUNKB2 - {SPR_IMPX, 17, 700, NULL, S_NULL, 0, 0}, // S_IMP_CHUNKB3 - {SPR_FX10, 32768, 6, NULL, S_IMPFX2, 0, 0}, // S_IMPFX1 - {SPR_FX10, 32769, 6, NULL, S_IMPFX3, 0, 0}, // S_IMPFX2 - {SPR_FX10, 32770, 6, NULL, S_IMPFX1, 0, 0}, // S_IMPFX3 - {SPR_FX10, 32771, 5, NULL, S_IMPFXI2, 0, 0}, // S_IMPFXI1 - {SPR_FX10, 32772, 5, NULL, S_IMPFXI3, 0, 0}, // S_IMPFXI2 - {SPR_FX10, 32773, 5, NULL, S_IMPFXI4, 0, 0}, // S_IMPFXI3 - {SPR_FX10, 32774, 5, NULL, S_NULL, 0, 0}, // S_IMPFXI4 - {SPR_KNIG, 0, 10, A_Look, S_KNIGHT_STND2, 0, 0}, // S_KNIGHT_STND1 - {SPR_KNIG, 1, 10, A_Look, S_KNIGHT_STND1, 0, 0}, // S_KNIGHT_STND2 - {SPR_KNIG, 0, 4, A_Chase, S_KNIGHT_WALK2, 0, 0}, // S_KNIGHT_WALK1 - {SPR_KNIG, 1, 4, A_Chase, S_KNIGHT_WALK3, 0, 0}, // S_KNIGHT_WALK2 - {SPR_KNIG, 2, 4, A_Chase, S_KNIGHT_WALK4, 0, 0}, // S_KNIGHT_WALK3 - {SPR_KNIG, 3, 4, A_Chase, S_KNIGHT_WALK1, 0, 0}, // S_KNIGHT_WALK4 - {SPR_KNIG, 4, 10, A_FaceTarget, S_KNIGHT_ATK2, 0, 0}, // S_KNIGHT_ATK1 - {SPR_KNIG, 5, 8, A_FaceTarget, S_KNIGHT_ATK3, 0, 0}, // S_KNIGHT_ATK2 - {SPR_KNIG, 6, 8, A_KnightAttack, S_KNIGHT_ATK4, 0, 0}, // S_KNIGHT_ATK3 - {SPR_KNIG, 4, 10, A_FaceTarget, S_KNIGHT_ATK5, 0, 0}, // S_KNIGHT_ATK4 - {SPR_KNIG, 5, 8, A_FaceTarget, S_KNIGHT_ATK6, 0, 0}, // S_KNIGHT_ATK5 - {SPR_KNIG, 6, 8, A_KnightAttack, S_KNIGHT_WALK1, 0, 0}, // S_KNIGHT_ATK6 - {SPR_KNIG, 7, 3, NULL, S_KNIGHT_PAIN2, 0, 0}, // S_KNIGHT_PAIN1 - {SPR_KNIG, 7, 3, A_Pain, S_KNIGHT_WALK1, 0, 0}, // S_KNIGHT_PAIN2 - {SPR_KNIG, 8, 6, NULL, S_KNIGHT_DIE2, 0, 0}, // S_KNIGHT_DIE1 - {SPR_KNIG, 9, 6, A_Scream, S_KNIGHT_DIE3, 0, 0}, // S_KNIGHT_DIE2 - {SPR_KNIG, 10, 6, NULL, S_KNIGHT_DIE4, 0, 0}, // S_KNIGHT_DIE3 - {SPR_KNIG, 11, 6, A_NoBlocking, S_KNIGHT_DIE5, 0, 0}, // S_KNIGHT_DIE4 - {SPR_KNIG, 12, 6, NULL, S_KNIGHT_DIE6, 0, 0}, // S_KNIGHT_DIE5 - {SPR_KNIG, 13, 6, NULL, S_KNIGHT_DIE7, 0, 0}, // S_KNIGHT_DIE6 - {SPR_KNIG, 14, -1, NULL, S_NULL, 0, 0}, // S_KNIGHT_DIE7 - {SPR_SPAX, 32768, 3, A_ContMobjSound, S_SPINAXE2, 0, 0}, // S_SPINAXE1 - {SPR_SPAX, 32769, 3, NULL, S_SPINAXE3, 0, 0}, // S_SPINAXE2 - {SPR_SPAX, 32770, 3, NULL, S_SPINAXE1, 0, 0}, // S_SPINAXE3 - {SPR_SPAX, 32771, 6, NULL, S_SPINAXEX2, 0, 0}, // S_SPINAXEX1 - {SPR_SPAX, 32772, 6, NULL, S_SPINAXEX3, 0, 0}, // S_SPINAXEX2 - {SPR_SPAX, 32773, 6, NULL, S_NULL, 0, 0}, // S_SPINAXEX3 - {SPR_RAXE, 32768, 5, A_DripBlood, S_REDAXE2, 0, 0}, // S_REDAXE1 - {SPR_RAXE, 32769, 5, A_DripBlood, S_REDAXE1, 0, 0}, // S_REDAXE2 - {SPR_RAXE, 32770, 6, NULL, S_REDAXEX2, 0, 0}, // S_REDAXEX1 - {SPR_RAXE, 32771, 6, NULL, S_REDAXEX3, 0, 0}, // S_REDAXEX2 - {SPR_RAXE, 32772, 6, NULL, S_NULL, 0, 0}, // S_REDAXEX3 - {SPR_SRCR, 0, 10, A_Look, S_SRCR1_LOOK2, 0, 0}, // S_SRCR1_LOOK1 - {SPR_SRCR, 1, 10, A_Look, S_SRCR1_LOOK1, 0, 0}, // S_SRCR1_LOOK2 - {SPR_SRCR, 0, 5, A_Sor1Chase, S_SRCR1_WALK2, 0, 0}, // S_SRCR1_WALK1 - {SPR_SRCR, 1, 5, A_Sor1Chase, S_SRCR1_WALK3, 0, 0}, // S_SRCR1_WALK2 - {SPR_SRCR, 2, 5, A_Sor1Chase, S_SRCR1_WALK4, 0, 0}, // S_SRCR1_WALK3 - {SPR_SRCR, 3, 5, A_Sor1Chase, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_WALK4 - {SPR_SRCR, 16, 6, A_Sor1Pain, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_PAIN1 - {SPR_SRCR, 16, 7, A_FaceTarget, S_SRCR1_ATK2, 0, 0}, // S_SRCR1_ATK1 - {SPR_SRCR, 17, 6, A_FaceTarget, S_SRCR1_ATK3, 0, 0}, // S_SRCR1_ATK2 - {SPR_SRCR, 18, 10, A_Srcr1Attack, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_ATK3 - {SPR_SRCR, 18, 10, A_FaceTarget, S_SRCR1_ATK5, 0, 0}, // S_SRCR1_ATK4 - {SPR_SRCR, 16, 7, A_FaceTarget, S_SRCR1_ATK6, 0, 0}, // S_SRCR1_ATK5 - {SPR_SRCR, 17, 6, A_FaceTarget, S_SRCR1_ATK7, 0, 0}, // S_SRCR1_ATK6 - {SPR_SRCR, 18, 10, A_Srcr1Attack, S_SRCR1_WALK1, 0, 0}, // S_SRCR1_ATK7 - {SPR_SRCR, 4, 7, NULL, S_SRCR1_DIE2, 0, 0}, // S_SRCR1_DIE1 - {SPR_SRCR, 5, 7, A_Scream, S_SRCR1_DIE3, 0, 0}, // S_SRCR1_DIE2 - {SPR_SRCR, 6, 7, NULL, S_SRCR1_DIE4, 0, 0}, // S_SRCR1_DIE3 - {SPR_SRCR, 7, 6, NULL, S_SRCR1_DIE5, 0, 0}, // S_SRCR1_DIE4 - {SPR_SRCR, 8, 6, NULL, S_SRCR1_DIE6, 0, 0}, // S_SRCR1_DIE5 - {SPR_SRCR, 9, 6, NULL, S_SRCR1_DIE7, 0, 0}, // S_SRCR1_DIE6 - {SPR_SRCR, 10, 6, NULL, S_SRCR1_DIE8, 0, 0}, // S_SRCR1_DIE7 - {SPR_SRCR, 11, 25, A_SorZap, S_SRCR1_DIE9, 0, 0}, // S_SRCR1_DIE8 - {SPR_SRCR, 12, 5, NULL, S_SRCR1_DIE10, 0, 0}, // S_SRCR1_DIE9 - {SPR_SRCR, 13, 5, NULL, S_SRCR1_DIE11, 0, 0}, // S_SRCR1_DIE10 - {SPR_SRCR, 14, 4, NULL, S_SRCR1_DIE12, 0, 0}, // S_SRCR1_DIE11 - {SPR_SRCR, 11, 20, A_SorZap, S_SRCR1_DIE13, 0, 0}, // S_SRCR1_DIE12 - {SPR_SRCR, 12, 5, NULL, S_SRCR1_DIE14, 0, 0}, // S_SRCR1_DIE13 - {SPR_SRCR, 13, 5, NULL, S_SRCR1_DIE15, 0, 0}, // S_SRCR1_DIE14 - {SPR_SRCR, 14, 4, NULL, S_SRCR1_DIE16, 0, 0}, // S_SRCR1_DIE15 - {SPR_SRCR, 11, 12, NULL, S_SRCR1_DIE17, 0, 0}, // S_SRCR1_DIE16 - {SPR_SRCR, 15, -1, A_SorcererRise, S_NULL, 0, 0}, // S_SRCR1_DIE17 - {SPR_FX14, 32768, 6, NULL, S_SRCRFX1_2, 0, 0}, // S_SRCRFX1_1 - {SPR_FX14, 32769, 6, NULL, S_SRCRFX1_3, 0, 0}, // S_SRCRFX1_2 - {SPR_FX14, 32770, 6, NULL, S_SRCRFX1_1, 0, 0}, // S_SRCRFX1_3 - {SPR_FX14, 32771, 5, NULL, S_SRCRFXI1_2, 0, 0}, // S_SRCRFXI1_1 - {SPR_FX14, 32772, 5, NULL, S_SRCRFXI1_3, 0, 0}, // S_SRCRFXI1_2 - {SPR_FX14, 32773, 5, NULL, S_SRCRFXI1_4, 0, 0}, // S_SRCRFXI1_3 - {SPR_FX14, 32774, 5, NULL, S_SRCRFXI1_5, 0, 0}, // S_SRCRFXI1_4 - {SPR_FX14, 32775, 5, NULL, S_NULL, 0, 0}, // S_SRCRFXI1_5 - {SPR_SOR2, 0, 4, NULL, S_SOR2_RISE2, 0, 0}, // S_SOR2_RISE1 - {SPR_SOR2, 1, 4, NULL, S_SOR2_RISE3, 0, 0}, // S_SOR2_RISE2 - {SPR_SOR2, 2, 4, A_SorRise, S_SOR2_RISE4, 0, 0}, // S_SOR2_RISE3 - {SPR_SOR2, 3, 4, NULL, S_SOR2_RISE5, 0, 0}, // S_SOR2_RISE4 - {SPR_SOR2, 4, 4, NULL, S_SOR2_RISE6, 0, 0}, // S_SOR2_RISE5 - {SPR_SOR2, 5, 4, NULL, S_SOR2_RISE7, 0, 0}, // S_SOR2_RISE6 - {SPR_SOR2, 6, 12, A_SorSightSnd, S_SOR2_WALK1, 0, 0}, // S_SOR2_RISE7 - {SPR_SOR2, 12, 10, A_Look, S_SOR2_LOOK2, 0, 0}, // S_SOR2_LOOK1 - {SPR_SOR2, 13, 10, A_Look, S_SOR2_LOOK1, 0, 0}, // S_SOR2_LOOK2 - {SPR_SOR2, 12, 4, A_Chase, S_SOR2_WALK2, 0, 0}, // S_SOR2_WALK1 - {SPR_SOR2, 13, 4, A_Chase, S_SOR2_WALK3, 0, 0}, // S_SOR2_WALK2 - {SPR_SOR2, 14, 4, A_Chase, S_SOR2_WALK4, 0, 0}, // S_SOR2_WALK3 - {SPR_SOR2, 15, 4, A_Chase, S_SOR2_WALK1, 0, 0}, // S_SOR2_WALK4 - {SPR_SOR2, 16, 3, NULL, S_SOR2_PAIN2, 0, 0}, // S_SOR2_PAIN1 - {SPR_SOR2, 16, 6, A_Pain, S_SOR2_WALK1, 0, 0}, // S_SOR2_PAIN2 - {SPR_SOR2, 17, 9, A_Srcr2Decide, S_SOR2_ATK2, 0, 0}, // S_SOR2_ATK1 - {SPR_SOR2, 18, 9, A_FaceTarget, S_SOR2_ATK3, 0, 0}, // S_SOR2_ATK2 - {SPR_SOR2, 19, 20, A_Srcr2Attack, S_SOR2_WALK1, 0, 0}, // S_SOR2_ATK3 - {SPR_SOR2, 11, 6, NULL, S_SOR2_TELE2, 0, 0}, // S_SOR2_TELE1 - {SPR_SOR2, 10, 6, NULL, S_SOR2_TELE3, 0, 0}, // S_SOR2_TELE2 - {SPR_SOR2, 9, 6, NULL, S_SOR2_TELE4, 0, 0}, // S_SOR2_TELE3 - {SPR_SOR2, 8, 6, NULL, S_SOR2_TELE5, 0, 0}, // S_SOR2_TELE4 - {SPR_SOR2, 7, 6, NULL, S_SOR2_TELE6, 0, 0}, // S_SOR2_TELE5 - {SPR_SOR2, 6, 6, NULL, S_SOR2_WALK1, 0, 0}, // S_SOR2_TELE6 - {SPR_SDTH, 0, 8, A_Sor2DthInit, S_SOR2_DIE2, 0, 0}, // S_SOR2_DIE1 - {SPR_SDTH, 1, 8, NULL, S_SOR2_DIE3, 0, 0}, // S_SOR2_DIE2 - {SPR_SDTH, 2, 8, A_SorDSph, S_SOR2_DIE4, 0, 0}, // S_SOR2_DIE3 - {SPR_SDTH, 3, 7, NULL, S_SOR2_DIE5, 0, 0}, // S_SOR2_DIE4 - {SPR_SDTH, 4, 7, NULL, S_SOR2_DIE6, 0, 0}, // S_SOR2_DIE5 - {SPR_SDTH, 5, 7, A_Sor2DthLoop, S_SOR2_DIE7, 0, 0}, // S_SOR2_DIE6 - {SPR_SDTH, 6, 6, A_SorDExp, S_SOR2_DIE8, 0, 0}, // S_SOR2_DIE7 - {SPR_SDTH, 7, 6, NULL, S_SOR2_DIE9, 0, 0}, // S_SOR2_DIE8 - {SPR_SDTH, 8, 18, NULL, S_SOR2_DIE10, 0, 0}, // S_SOR2_DIE9 - {SPR_SDTH, 9, 6, A_NoBlocking, S_SOR2_DIE11, 0, 0}, // S_SOR2_DIE10 - {SPR_SDTH, 10, 6, A_SorDBon, S_SOR2_DIE12, 0, 0}, // S_SOR2_DIE11 - {SPR_SDTH, 11, 6, NULL, S_SOR2_DIE13, 0, 0}, // S_SOR2_DIE12 - {SPR_SDTH, 12, 6, NULL, S_SOR2_DIE14, 0, 0}, // S_SOR2_DIE13 - {SPR_SDTH, 13, 6, NULL, S_SOR2_DIE15, 0, 0}, // S_SOR2_DIE14 - {SPR_SDTH, 14, -1, A_BossDeath, S_NULL, 0, 0}, // S_SOR2_DIE15 - {SPR_FX16, 32768, 3, A_BlueSpark, S_SOR2FX1_2, 0, 0}, // S_SOR2FX1_1 - {SPR_FX16, 32769, 3, A_BlueSpark, S_SOR2FX1_3, 0, 0}, // S_SOR2FX1_2 - {SPR_FX16, 32770, 3, A_BlueSpark, S_SOR2FX1_1, 0, 0}, // S_SOR2FX1_3 - {SPR_FX16, 32774, 5, A_Explode, S_SOR2FXI1_2, 0, 0}, // S_SOR2FXI1_1 - {SPR_FX16, 32775, 5, NULL, S_SOR2FXI1_3, 0, 0}, // S_SOR2FXI1_2 - {SPR_FX16, 32776, 5, NULL, S_SOR2FXI1_4, 0, 0}, // S_SOR2FXI1_3 - {SPR_FX16, 32777, 5, NULL, S_SOR2FXI1_5, 0, 0}, // S_SOR2FXI1_4 - {SPR_FX16, 32778, 5, NULL, S_SOR2FXI1_6, 0, 0}, // S_SOR2FXI1_5 - {SPR_FX16, 32779, 5, NULL, S_NULL, 0, 0}, // S_SOR2FXI1_6 - {SPR_FX16, 32771, 12, NULL, S_SOR2FXSPARK2, 0, 0}, // S_SOR2FXSPARK1 - {SPR_FX16, 32772, 12, NULL, S_SOR2FXSPARK3, 0, 0}, // S_SOR2FXSPARK2 - {SPR_FX16, 32773, 12, NULL, S_NULL, 0, 0}, // S_SOR2FXSPARK3 - {SPR_FX11, 32768, 35, NULL, S_SOR2FX2_2, 0, 0}, // S_SOR2FX2_1 - {SPR_FX11, 32768, 5, A_GenWizard, S_SOR2FX2_3, 0, 0}, // S_SOR2FX2_2 - {SPR_FX11, 32769, 5, NULL, S_SOR2FX2_2, 0, 0}, // S_SOR2FX2_3 - {SPR_FX11, 32770, 5, NULL, S_SOR2FXI2_2, 0, 0}, // S_SOR2FXI2_1 - {SPR_FX11, 32771, 5, NULL, S_SOR2FXI2_3, 0, 0}, // S_SOR2FXI2_2 - {SPR_FX11, 32772, 5, NULL, S_SOR2FXI2_4, 0, 0}, // S_SOR2FXI2_3 - {SPR_FX11, 32773, 5, NULL, S_SOR2FXI2_5, 0, 0}, // S_SOR2FXI2_4 - {SPR_FX11, 32774, 5, NULL, S_NULL, 0, 0}, // S_SOR2FXI2_5 - {SPR_SOR2, 6, 8, NULL, S_SOR2TELEFADE2, 0, 0}, // S_SOR2TELEFADE1 - {SPR_SOR2, 7, 6, NULL, S_SOR2TELEFADE3, 0, 0}, // S_SOR2TELEFADE2 - {SPR_SOR2, 8, 6, NULL, S_SOR2TELEFADE4, 0, 0}, // S_SOR2TELEFADE3 - {SPR_SOR2, 9, 6, NULL, S_SOR2TELEFADE5, 0, 0}, // S_SOR2TELEFADE4 - {SPR_SOR2, 10, 6, NULL, S_SOR2TELEFADE6, 0, 0}, // S_SOR2TELEFADE5 - {SPR_SOR2, 11, 6, NULL, S_NULL, 0, 0}, // S_SOR2TELEFADE6 - {SPR_MNTR, 0, 10, A_Look, S_MNTR_LOOK2, 0, 0}, // S_MNTR_LOOK1 - {SPR_MNTR, 1, 10, A_Look, S_MNTR_LOOK1, 0, 0}, // S_MNTR_LOOK2 - {SPR_MNTR, 0, 5, A_Chase, S_MNTR_WALK2, 0, 0}, // S_MNTR_WALK1 - {SPR_MNTR, 1, 5, A_Chase, S_MNTR_WALK3, 0, 0}, // S_MNTR_WALK2 - {SPR_MNTR, 2, 5, A_Chase, S_MNTR_WALK4, 0, 0}, // S_MNTR_WALK3 - {SPR_MNTR, 3, 5, A_Chase, S_MNTR_WALK1, 0, 0}, // S_MNTR_WALK4 - {SPR_MNTR, 21, 10, A_FaceTarget, S_MNTR_ATK1_2, 0, 0}, // S_MNTR_ATK1_1 - {SPR_MNTR, 22, 7, A_FaceTarget, S_MNTR_ATK1_3, 0, 0}, // S_MNTR_ATK1_2 - {SPR_MNTR, 23, 12, A_MinotaurAtk1, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK1_3 - {SPR_MNTR, 21, 10, A_MinotaurDecide, S_MNTR_ATK2_2, 0, 0}, // S_MNTR_ATK2_1 - {SPR_MNTR, 24, 4, A_FaceTarget, S_MNTR_ATK2_3, 0, 0}, // S_MNTR_ATK2_2 - {SPR_MNTR, 25, 9, A_MinotaurAtk2, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK2_3 - {SPR_MNTR, 21, 10, A_FaceTarget, S_MNTR_ATK3_2, 0, 0}, // S_MNTR_ATK3_1 - {SPR_MNTR, 22, 7, A_FaceTarget, S_MNTR_ATK3_3, 0, 0}, // S_MNTR_ATK3_2 - {SPR_MNTR, 23, 12, A_MinotaurAtk3, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK3_3 - {SPR_MNTR, 23, 12, NULL, S_MNTR_ATK3_1, 0, 0}, // S_MNTR_ATK3_4 - {SPR_MNTR, 20, 2, A_MinotaurCharge, S_MNTR_ATK4_1, 0, 0}, // S_MNTR_ATK4_1 - {SPR_MNTR, 4, 3, NULL, S_MNTR_PAIN2, 0, 0}, // S_MNTR_PAIN1 - {SPR_MNTR, 4, 6, A_Pain, S_MNTR_WALK1, 0, 0}, // S_MNTR_PAIN2 - {SPR_MNTR, 5, 6, NULL, S_MNTR_DIE2, 0, 0}, // S_MNTR_DIE1 - {SPR_MNTR, 6, 5, NULL, S_MNTR_DIE3, 0, 0}, // S_MNTR_DIE2 - {SPR_MNTR, 7, 6, A_Scream, S_MNTR_DIE4, 0, 0}, // S_MNTR_DIE3 - {SPR_MNTR, 8, 5, NULL, S_MNTR_DIE5, 0, 0}, // S_MNTR_DIE4 - {SPR_MNTR, 9, 6, NULL, S_MNTR_DIE6, 0, 0}, // S_MNTR_DIE5 - {SPR_MNTR, 10, 5, NULL, S_MNTR_DIE7, 0, 0}, // S_MNTR_DIE6 - {SPR_MNTR, 11, 6, NULL, S_MNTR_DIE8, 0, 0}, // S_MNTR_DIE7 - {SPR_MNTR, 12, 5, A_NoBlocking, S_MNTR_DIE9, 0, 0}, // S_MNTR_DIE8 - {SPR_MNTR, 13, 6, NULL, S_MNTR_DIE10, 0, 0}, // S_MNTR_DIE9 - {SPR_MNTR, 14, 5, NULL, S_MNTR_DIE11, 0, 0}, // S_MNTR_DIE10 - {SPR_MNTR, 15, 6, NULL, S_MNTR_DIE12, 0, 0}, // S_MNTR_DIE11 - {SPR_MNTR, 16, 5, NULL, S_MNTR_DIE13, 0, 0}, // S_MNTR_DIE12 - {SPR_MNTR, 17, 6, NULL, S_MNTR_DIE14, 0, 0}, // S_MNTR_DIE13 - {SPR_MNTR, 18, 5, NULL, S_MNTR_DIE15, 0, 0}, // S_MNTR_DIE14 - {SPR_MNTR, 19, -1, A_BossDeath, S_NULL, 0, 0}, // S_MNTR_DIE15 - {SPR_FX12, 32768, 6, NULL, S_MNTRFX1_2, 0, 0}, // S_MNTRFX1_1 - {SPR_FX12, 32769, 6, NULL, S_MNTRFX1_1, 0, 0}, // S_MNTRFX1_2 - {SPR_FX12, 32770, 5, NULL, S_MNTRFXI1_2, 0, 0}, // S_MNTRFXI1_1 - {SPR_FX12, 32771, 5, NULL, S_MNTRFXI1_3, 0, 0}, // S_MNTRFXI1_2 - {SPR_FX12, 32772, 5, NULL, S_MNTRFXI1_4, 0, 0}, // S_MNTRFXI1_3 - {SPR_FX12, 32773, 5, NULL, S_MNTRFXI1_5, 0, 0}, // S_MNTRFXI1_4 - {SPR_FX12, 32774, 5, NULL, S_MNTRFXI1_6, 0, 0}, // S_MNTRFXI1_5 - {SPR_FX12, 32775, 5, NULL, S_NULL, 0, 0}, // S_MNTRFXI1_6 - {SPR_FX13, 0, 2, A_MntrFloorFire, S_MNTRFX2_1, 0, 0}, // S_MNTRFX2_1 - {SPR_FX13, 32776, 4, A_Explode, S_MNTRFXI2_2, 0, 0}, // S_MNTRFXI2_1 - {SPR_FX13, 32777, 4, NULL, S_MNTRFXI2_3, 0, 0}, // S_MNTRFXI2_2 - {SPR_FX13, 32778, 4, NULL, S_MNTRFXI2_4, 0, 0}, // S_MNTRFXI2_3 - {SPR_FX13, 32779, 4, NULL, S_MNTRFXI2_5, 0, 0}, // S_MNTRFXI2_4 - {SPR_FX13, 32780, 4, NULL, S_NULL, 0, 0}, // S_MNTRFXI2_5 - {SPR_FX13, 32771, 4, NULL, S_MNTRFX3_2, 0, 0}, // S_MNTRFX3_1 - {SPR_FX13, 32770, 4, NULL, S_MNTRFX3_3, 0, 0}, // S_MNTRFX3_2 - {SPR_FX13, 32769, 5, NULL, S_MNTRFX3_4, 0, 0}, // S_MNTRFX3_3 - {SPR_FX13, 32770, 5, NULL, S_MNTRFX3_5, 0, 0}, // S_MNTRFX3_4 - {SPR_FX13, 32771, 5, NULL, S_MNTRFX3_6, 0, 0}, // S_MNTRFX3_5 - {SPR_FX13, 32772, 5, NULL, S_MNTRFX3_7, 0, 0}, // S_MNTRFX3_6 - {SPR_FX13, 32773, 4, NULL, S_MNTRFX3_8, 0, 0}, // S_MNTRFX3_7 - {SPR_FX13, 32774, 4, NULL, S_MNTRFX3_9, 0, 0}, // S_MNTRFX3_8 - {SPR_FX13, 32775, 4, NULL, S_NULL, 0, 0}, // S_MNTRFX3_9 - {SPR_AKYY, 32768, 3, NULL, S_AKYY2, 0, 0}, // S_AKYY1 - {SPR_AKYY, 32769, 3, NULL, S_AKYY3, 0, 0}, // S_AKYY2 - {SPR_AKYY, 32770, 3, NULL, S_AKYY4, 0, 0}, // S_AKYY3 - {SPR_AKYY, 32771, 3, NULL, S_AKYY5, 0, 0}, // S_AKYY4 - {SPR_AKYY, 32772, 3, NULL, S_AKYY6, 0, 0}, // S_AKYY5 - {SPR_AKYY, 32773, 3, NULL, S_AKYY7, 0, 0}, // S_AKYY6 - {SPR_AKYY, 32774, 3, NULL, S_AKYY8, 0, 0}, // S_AKYY7 - {SPR_AKYY, 32775, 3, NULL, S_AKYY9, 0, 0}, // S_AKYY8 - {SPR_AKYY, 32776, 3, NULL, S_AKYY10, 0, 0}, // S_AKYY9 - {SPR_AKYY, 32777, 3, NULL, S_AKYY1, 0, 0}, // S_AKYY10 - {SPR_BKYY, 32768, 3, NULL, S_BKYY2, 0, 0}, // S_BKYY1 - {SPR_BKYY, 32769, 3, NULL, S_BKYY3, 0, 0}, // S_BKYY2 - {SPR_BKYY, 32770, 3, NULL, S_BKYY4, 0, 0}, // S_BKYY3 - {SPR_BKYY, 32771, 3, NULL, S_BKYY5, 0, 0}, // S_BKYY4 - {SPR_BKYY, 32772, 3, NULL, S_BKYY6, 0, 0}, // S_BKYY5 - {SPR_BKYY, 32773, 3, NULL, S_BKYY7, 0, 0}, // S_BKYY6 - {SPR_BKYY, 32774, 3, NULL, S_BKYY8, 0, 0}, // S_BKYY7 - {SPR_BKYY, 32775, 3, NULL, S_BKYY9, 0, 0}, // S_BKYY8 - {SPR_BKYY, 32776, 3, NULL, S_BKYY10, 0, 0}, // S_BKYY9 - {SPR_BKYY, 32777, 3, NULL, S_BKYY1, 0, 0}, // S_BKYY10 - {SPR_CKYY, 32768, 3, NULL, S_CKYY2, 0, 0}, // S_CKYY1 - {SPR_CKYY, 32769, 3, NULL, S_CKYY3, 0, 0}, // S_CKYY2 - {SPR_CKYY, 32770, 3, NULL, S_CKYY4, 0, 0}, // S_CKYY3 - {SPR_CKYY, 32771, 3, NULL, S_CKYY5, 0, 0}, // S_CKYY4 - {SPR_CKYY, 32772, 3, NULL, S_CKYY6, 0, 0}, // S_CKYY5 - {SPR_CKYY, 32773, 3, NULL, S_CKYY7, 0, 0}, // S_CKYY6 - {SPR_CKYY, 32774, 3, NULL, S_CKYY8, 0, 0}, // S_CKYY7 - {SPR_CKYY, 32775, 3, NULL, S_CKYY9, 0, 0}, // S_CKYY8 - {SPR_CKYY, 32776, 3, NULL, S_CKYY1, 0, 0}, // S_CKYY9 - {SPR_AMG1, 0, -1, NULL, S_NULL, 0, 0}, // S_AMG1 - {SPR_AMG2, 0, 4, NULL, S_AMG2_2, 0, 0}, // S_AMG2_1 - {SPR_AMG2, 1, 4, NULL, S_AMG2_3, 0, 0}, // S_AMG2_2 - {SPR_AMG2, 2, 4, NULL, S_AMG2_1, 0, 0}, // S_AMG2_3 - {SPR_AMM1, 0, -1, NULL, S_NULL, 0, 0}, // S_AMM1 - {SPR_AMM2, 0, -1, NULL, S_NULL, 0, 0}, // S_AMM2 - {SPR_AMC1, 0, -1, NULL, S_NULL, 0, 0}, // S_AMC1 - {SPR_AMC2, 0, 5, NULL, S_AMC2_2, 0, 0}, // S_AMC2_1 - {SPR_AMC2, 1, 5, NULL, S_AMC2_3, 0, 0}, // S_AMC2_2 - {SPR_AMC2, 2, 5, NULL, S_AMC2_1, 0, 0}, // S_AMC2_3 - {SPR_AMS1, 0, 5, NULL, S_AMS1_2, 0, 0}, // S_AMS1_1 - {SPR_AMS1, 1, 5, NULL, S_AMS1_1, 0, 0}, // S_AMS1_2 - {SPR_AMS2, 0, 5, NULL, S_AMS2_2, 0, 0}, // S_AMS2_1 - {SPR_AMS2, 1, 5, NULL, S_AMS2_1, 0, 0}, // S_AMS2_2 - {SPR_AMP1, 0, 4, NULL, S_AMP1_2, 0, 0}, // S_AMP1_1 - {SPR_AMP1, 1, 4, NULL, S_AMP1_3, 0, 0}, // S_AMP1_2 - {SPR_AMP1, 2, 4, NULL, S_AMP1_1, 0, 0}, // S_AMP1_3 - {SPR_AMP2, 0, 4, NULL, S_AMP2_2, 0, 0}, // S_AMP2_1 - {SPR_AMP2, 1, 4, NULL, S_AMP2_3, 0, 0}, // S_AMP2_2 - {SPR_AMP2, 2, 4, NULL, S_AMP2_1, 0, 0}, // S_AMP2_3 - {SPR_AMB1, 0, 4, NULL, S_AMB1_2, 0, 0}, // S_AMB1_1 - {SPR_AMB1, 1, 4, NULL, S_AMB1_3, 0, 0}, // S_AMB1_2 - {SPR_AMB1, 2, 4, NULL, S_AMB1_1, 0, 0}, // S_AMB1_3 - {SPR_AMB2, 0, 4, NULL, S_AMB2_2, 0, 0}, // S_AMB2_1 - {SPR_AMB2, 1, 4, NULL, S_AMB2_3, 0, 0}, // S_AMB2_2 - {SPR_AMB2, 2, 4, NULL, S_AMB2_1, 0, 0}, // S_AMB2_3 - {SPR_AMG1, 0, 100, A_ESound, S_SND_WIND, 0, 0}, // S_SND_WIND - {SPR_AMG1, 0, 85, A_ESound, S_SND_WATERFALL, 0, 0} // S_SND_WATERFALL -}; - - -mobjinfo_t mobjinfo[NUMMOBJTYPES] = { - - { // MT_MISC0 - 81, // doomednum - S_ITEM_PTN1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ITEMSHIELD1 - 85, // doomednum - S_ITEM_SHLD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ITEMSHIELD2 - 31, // doomednum - S_ITEM_SHD2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MISC1 - 8, // doomednum - S_ITEM_BAGH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MISC2 - 35, // doomednum - S_ITEM_SPMP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIINVISIBILITY - 75, // doomednum - S_ARTI_INVS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_SHADOW | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MISC3 - 82, // doomednum - S_ARTI_PTN2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIFLY - 83, // doomednum - S_ARTI_SOAR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIINVULNERABILITY - 84, // doomednum - S_ARTI_INVU1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTITOMEOFPOWER - 86, // doomednum - S_ARTI_PWBK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIEGG - 30, // doomednum - S_ARTI_EGGC1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_EGGFX - -1, // doomednum - S_EGGFX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_EGGFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 18 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ARTISUPERHEAL - 32, // doomednum - S_ARTI_SPHL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MISC4 - 33, // doomednum - S_ARTI_TRCH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MISC5 - 34, // doomednum - S_ARTI_FBMB1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_FIREBOMB - -1, // doomednum - S_FIREBOMB1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_phohit, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_ARTITELEPORT - 36, // doomednum - S_ARTI_ATLP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_COUNTITEM, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_POD - 2035, // doomednum - S_POD_WAIT1, // spawnstate - 45, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_POD_PAIN1, // painstate - 255, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_POD_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_podexp, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 54 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_NOBLOOD | MF_SHOOTABLE | MF_DROPOFF, // flags - MF2_WINDTHRUST | MF2_PUSHABLE | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP // flags2 - }, - - { // MT_PODGOO - -1, // doomednum - S_PODGOO1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_PODGOOX, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_PODGENERATOR - 43, // doomednum - S_PODGENERATOR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_SPLASH - -1, // doomednum - S_SPLASH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SPLASHX, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_SPLASHBASE - -1, // doomednum - S_SPLASHBASE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_LAVASPLASH - -1, // doomednum - S_LAVASPLASH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_LAVASMOKE - -1, // doomednum - S_LAVASMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_SLUDGECHUNK - -1, // doomednum - S_SLUDGECHUNK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SLUDGECHUNKX, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_SLUDGESPLASH - -1, // doomednum - S_SLUDGESPLASH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_SKULLHANG70 - 17, // doomednum - S_SKULLHANG70_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 70 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_SKULLHANG60 - 24, // doomednum - S_SKULLHANG60_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 60 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_SKULLHANG45 - 25, // doomednum - S_SKULLHANG45_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 45 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_SKULLHANG35 - 26, // doomednum - S_SKULLHANG35_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 35 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_CHANDELIER - 28, // doomednum - S_CHANDELIER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 60 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_SERPTORCH - 27, // doomednum - S_SERPTORCH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 54 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_SMALLPILLAR - 29, // doomednum - S_SMALLPILLAR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 34 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_STALAGMITESMALL - 37, // doomednum - S_STALAGMITESMALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_STALAGMITELARGE - 38, // doomednum - S_STALAGMITELARGE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_STALACTITESMALL - 39, // doomednum - S_STALACTITESMALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 36 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_STALACTITELARGE - 40, // doomednum - S_STALACTITELARGE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 68 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC6 - 76, // doomednum - S_FIREBRAZIER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 44 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_BARREL - 44, // doomednum - S_BARREL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC7 - 47, // doomednum - S_BRPILLAR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 128 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC8 - 48, // doomednum - S_MOSS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 23 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC9 - 49, // doomednum - S_MOSS2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 27 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC10 - 50, // doomednum - S_WALLTORCH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC11 - 51, // doomednum - S_HANGINGCORPSE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 104 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_KEYGIZMOBLUE - 94, // doomednum - S_KEYGIZMO1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_KEYGIZMOGREEN - 95, // doomednum - S_KEYGIZMO1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_KEYGIZMOYELLOW - 96, // doomednum - S_KEYGIZMO1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_KEYGIZMOFLOAT - -1, // doomednum - S_KGZ_START, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC12 - 87, // doomednum - S_VOLCANO1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_VOLCANOBLAST - -1, // doomednum - S_VOLCANOBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_VOLCANOBALLX1, // deathstate - S_NULL, // xdeathstate - sfx_volhit, // deathsound - 2 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_VOLCANOTBLAST - -1, // doomednum - S_VOLCANOTBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_VOLCANOTBALLX1, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 2 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_TELEGLITGEN - 74, // doomednum - S_TELEGLITGEN1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_TELEGLITGEN2 - 52, // doomednum - S_TELEGLITGEN2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_TELEGLITTER - -1, // doomednum - S_TELEGLITTER1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - 0 // flags2 - }, - - { // MT_TELEGLITTER2 - -1, // doomednum - S_TELEGLITTER2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - 0 // flags2 - }, - - { // MT_TFOG - -1, // doomednum - S_TFOG1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_TELEPORTMAN - 14, // doomednum - S_NULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_STAFFPUFF - -1, // doomednum - S_STAFFPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_stfhit, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_STAFFPUFF2 - -1, // doomednum - S_STAFFPUFF2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_stfpow, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_BEAKPUFF - -1, // doomednum - S_STAFFPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_chicatk, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC13 - 2005, // doomednum - S_WGNT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_GAUNTLETPUFF1 - -1, // doomednum - S_GAUNTLETPUFF1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_GAUNTLETPUFF2 - -1, // doomednum - S_GAUNTLETPUFF2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_MISC14 - 53, // doomednum - S_BLSR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_BLASTERFX1 - -1, // doomednum - S_BLASTERFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BLASTERFXI1_1, // deathstate - S_NULL, // xdeathstate - sfx_blshit, // deathsound - 184 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_BLASTERSMOKE - -1, // doomednum - S_BLASTERSMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 - }, - - { // MT_RIPPER - -1, // doomednum - S_RIPPER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_RIPPERX1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 14 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_RIP // flags2 - }, - - { // MT_BLASTERPUFF1 - -1, // doomednum - S_BLASTERPUFF1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_BLASTERPUFF2 - -1, // doomednum - S_BLASTERPUFF2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_WMACE - 2002, // doomednum - S_WMCE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_MACEFX1 - -1, // doomednum - S_MACEFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_lobsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MACEFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 20 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 - }, - - { // MT_MACEFX2 - -1, // doomednum - S_MACEFX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MACEFXI2_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 6, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 - }, - - { // MT_MACEFX3 - -1, // doomednum - S_MACEFX3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MACEFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 7 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 4, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 - }, - - { // MT_MACEFX4 - -1, // doomednum - S_MACEFX4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MACEFXI4_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 7 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 18, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_FLOORBOUNCE | MF2_THRUGHOST | MF2_TELESTOMP // flags2 - }, - - { // MT_WSKULLROD - 2004, // doomednum - S_WSKL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_HORNRODFX1 - -1, // doomednum - S_HRODFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_hrnsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HRODFXI1_1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 22 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 - }, - - { // MT_HORNRODFX2 - -1, // doomednum - S_HRODFX2_1, // spawnstate - 4 * 35, // spawnhealth - S_NULL, // seestate - sfx_hrnsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HRODFXI2_1, // deathstate - S_NULL, // xdeathstate - sfx_ramphit, // deathsound - 22 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 10, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_RAINPLR1 - -1, // doomednum - S_RAINPLR1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_RAINPLR1X_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 12 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_RAINPLR2 - -1, // doomednum - S_RAINPLR2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_RAINPLR2X_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 12 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_RAINPLR3 - -1, // doomednum - S_RAINPLR3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_RAINPLR3X_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 12 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_RAINPLR4 - -1, // doomednum - S_RAINPLR4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_RAINPLR4X_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 12 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_GOLDWANDFX1 - -1, // doomednum - S_GWANDFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_GWANDFXI1_1, // deathstate - S_NULL, // xdeathstate - sfx_gldhit, // deathsound - 22 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_GOLDWANDFX2 - -1, // doomednum - S_GWANDFX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_GWANDFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 18 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_GOLDWANDPUFF1 - -1, // doomednum - S_GWANDPUFF1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_GOLDWANDPUFF2 - -1, // doomednum - S_GWANDFXI1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_WPHOENIXROD - 2003, // doomednum - S_WPHX, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_PHOENIXFX1 - -1, // doomednum - S_PHOENIXFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_phosht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_PHOENIXFXI1_1, // deathstate - S_NULL, // xdeathstate - sfx_phohit, // deathsound - 20 * FRACUNIT, // speed - 11 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 20, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_THRUGHOST | MF2_NOTELEPORT // flags2 - }, - - // The following thing is present in the mobjinfo table from Heretic 1.0, - // but not in Heretic 1.3 (ie. it was removed). It has been re-inserted - // here to support HHE patches. - - { // MT_PHOENIXFX_REMOVED - -1, // doomednum - S_PHOENIXFXIX_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_PHOENIXFXIX_3, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_PHOENIXPUFF - -1, // doomednum - S_PHOENIXPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 - }, - - { // MT_PHOENIXFX2 - -1, // doomednum - S_PHOENIXFX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_PHOENIXFXI2_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 6 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_MISC15 - 2001, // doomednum - S_WBOW, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_CRBOWFX1 - -1, // doomednum - S_CRBOWFX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_bowsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CRBOWFXI1_1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 30 * FRACUNIT, // speed - 11 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 10, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_CRBOWFX2 - -1, // doomednum - S_CRBOWFX2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_bowsht, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CRBOWFXI1_1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 32 * FRACUNIT, // speed - 11 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 6, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_CRBOWFX3 - -1, // doomednum - S_CRBOWFX3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CRBOWFXI3_1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 20 * FRACUNIT, // speed - 11 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_THRUGHOST | MF2_NOTELEPORT // flags2 - }, - - { // MT_CRBOWFX4 - -1, // doomednum - S_CRBOWFX4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - MF2_LOGRAV // flags2 - }, - - { // MT_BLOOD - -1, // doomednum - S_BLOOD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_BLOODSPLATTER - -1, // doomednum - S_BLOODSPLATTER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BLOODSPLATTERX, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 - }, - - { // MT_PLAYER - -1, // doomednum - S_PLAY, // spawnstate - 100, // spawnhealth - S_PLAY_RUN1, // seestate - sfx_None, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_PLAY_PAIN, // painstate - 255, // painchance - sfx_plrpai, // painsound - S_NULL, // meleestate - S_PLAY_ATK1, // missilestate - S_NULL, // crashstate - S_PLAY_DIE1, // deathstate - S_PLAY_XDIE1, // xdeathstate - sfx_plrdth, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 56 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags - MF2_WINDTHRUST | MF2_FOOTCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP // flags2 - }, - - { // MT_BLOODYSKULL - -1, // doomednum - S_BLOODYSKULL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_CHICPLAYER - -1, // doomednum - S_CHICPLAY, // spawnstate - 100, // spawnhealth - S_CHICPLAY_RUN1, // seestate - sfx_None, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_CHICPLAY_PAIN, // painstate - 255, // painchance - sfx_chicpai, // painsound - S_NULL, // meleestate - S_CHICPLAY_ATK1, // missilestate - S_NULL, // crashstate - S_CHICKEN_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_chicdth, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 24 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_NOTDMATCH, // flags - MF2_WINDTHRUST | MF2_SLIDE | MF2_PASSMOBJ | MF2_FOOTCLIP | MF2_LOGRAV | MF2_TELESTOMP // flags2 - }, - - { // MT_CHICKEN - -1, // doomednum - S_CHICKEN_LOOK1, // spawnstate - 10, // spawnhealth - S_CHICKEN_WALK1, // seestate - sfx_chicpai, // seesound - 8, // reactiontime - sfx_chicatk, // attacksound - S_CHICKEN_PAIN1, // painstate - 200, // painchance - sfx_chicpai, // painsound - S_CHICKEN_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_CHICKEN_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_chicdth, // deathsound - 4, // speed - 9 * FRACUNIT, // radius - 22 * FRACUNIT, // height - 40, // mass - 0, // damage - sfx_chicact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF, // flags - MF2_WINDTHRUST | MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_FEATHER - -1, // doomednum - S_FEATHER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FEATHERX, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH | MF2_WINDTHRUST // flags2 - }, - - { // MT_MUMMY - 68, // doomednum - S_MUMMY_LOOK1, // spawnstate - 80, // spawnhealth - S_MUMMY_WALK1, // seestate - sfx_mumsit, // seesound - 8, // reactiontime - sfx_mumat1, // attacksound - S_MUMMY_PAIN1, // painstate - 128, // painchance - sfx_mumpai, // painsound - S_MUMMY_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_MUMMY_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_mumdth, // deathsound - 12, // speed - 22 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 75, // mass - 0, // damage - sfx_mumact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_MUMMYLEADER - 45, // doomednum - S_MUMMY_LOOK1, // spawnstate - 100, // spawnhealth - S_MUMMY_WALK1, // seestate - sfx_mumsit, // seesound - 8, // reactiontime - sfx_mumat1, // attacksound - S_MUMMY_PAIN1, // painstate - 64, // painchance - sfx_mumpai, // painsound - S_MUMMY_ATK1, // meleestate - S_MUMMYL_ATK1, // missilestate - S_NULL, // crashstate - S_MUMMY_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_mumdth, // deathsound - 12, // speed - 22 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 75, // mass - 0, // damage - sfx_mumact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_MUMMYGHOST - 69, // doomednum - S_MUMMY_LOOK1, // spawnstate - 80, // spawnhealth - S_MUMMY_WALK1, // seestate - sfx_mumsit, // seesound - 8, // reactiontime - sfx_mumat1, // attacksound - S_MUMMY_PAIN1, // painstate - 128, // painchance - sfx_mumpai, // painsound - S_MUMMY_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_MUMMY_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_mumdth, // deathsound - 12, // speed - 22 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 75, // mass - 0, // damage - sfx_mumact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_MUMMYLEADERGHOST - 46, // doomednum - S_MUMMY_LOOK1, // spawnstate - 100, // spawnhealth - S_MUMMY_WALK1, // seestate - sfx_mumsit, // seesound - 8, // reactiontime - sfx_mumat1, // attacksound - S_MUMMY_PAIN1, // painstate - 64, // painchance - sfx_mumpai, // painsound - S_MUMMY_ATK1, // meleestate - S_MUMMYL_ATK1, // missilestate - S_NULL, // crashstate - S_MUMMY_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_mumdth, // deathsound - 12, // speed - 22 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 75, // mass - 0, // damage - sfx_mumact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_MUMMYSOUL - -1, // doomednum - S_MUMMY_SOUL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MUMMYFX1 - -1, // doomednum - S_MUMMYFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MUMMYFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 9 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 14 * FRACUNIT, // height - 100, // mass - 4, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_BEAST - 70, // doomednum - S_BEAST_LOOK1, // spawnstate - 220, // spawnhealth - S_BEAST_WALK1, // seestate - sfx_bstsit, // seesound - 8, // reactiontime - sfx_bstatk, // attacksound - S_BEAST_PAIN1, // painstate - 100, // painchance - sfx_bstpai, // painsound - 0, // meleestate - S_BEAST_ATK1, // missilestate - S_NULL, // crashstate - S_BEAST_DIE1, // deathstate - S_BEAST_XDIE1, // xdeathstate - sfx_bstdth, // deathsound - 14, // speed - 32 * FRACUNIT, // radius - 74 * FRACUNIT, // height - 200, // mass - 0, // damage - sfx_bstact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_BEASTBALL - -1, // doomednum - S_BEASTBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BEASTBALLX1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 12 * FRACUNIT, // speed - 9 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 4, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 - }, - - { // MT_BURNBALL - -1, // doomednum - S_BURNBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BEASTBALLX1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 6 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_BURNBALLFB - -1, // doomednum - S_BURNBALLFB1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BEASTBALLX1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 6 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_PUFFY - -1, // doomednum - S_PUFFY1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_PUFFY1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 6 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SNAKE - 92, // doomednum - S_SNAKE_LOOK1, // spawnstate - 280, // spawnhealth - S_SNAKE_WALK1, // seestate - sfx_snksit, // seesound - 8, // reactiontime - sfx_snkatk, // attacksound - S_SNAKE_PAIN1, // painstate - 48, // painchance - sfx_snkpai, // painsound - 0, // meleestate - S_SNAKE_ATK1, // missilestate - S_NULL, // crashstate - S_SNAKE_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_snkdth, // deathsound - 10, // speed - 22 * FRACUNIT, // radius - 70 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_snkact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_SNAKEPRO_A - -1, // doomednum - S_SNAKEPRO_A1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SNAKEPRO_AX1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 14 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 - }, - - { // MT_SNAKEPRO_B - -1, // doomednum - S_SNAKEPRO_B1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SNAKEPRO_BX1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 14 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_HEAD - 6, // doomednum - S_HEAD_LOOK, // spawnstate - 700, // spawnhealth - S_HEAD_FLOAT, // seestate - sfx_hedsit, // seesound - 8, // reactiontime - sfx_hedat1, // attacksound - S_HEAD_PAIN1, // painstate - 32, // painchance - sfx_hedpai, // painsound - 0, // meleestate - S_HEAD_ATK1, // missilestate - S_NULL, // crashstate - S_HEAD_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_heddth, // deathsound - 6, // speed - 40 * FRACUNIT, // radius - 72 * FRACUNIT, // height - 325, // mass - 0, // damage - sfx_hedact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags - MF2_PASSMOBJ // flags2 - }, - - { // MT_HEADFX1 - -1, // doomednum - S_HEADFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HEADFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 13 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_THRUGHOST // flags2 - }, - - { // MT_HEADFX2 - -1, // doomednum - S_HEADFX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HEADFXI2_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 8 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_HEADFX3 - -1, // doomednum - S_HEADFX3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HEADFXI3_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 14 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 5, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 - }, - - { // MT_WHIRLWIND - -1, // doomednum - S_HEADFX4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HEADFXI4_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 74 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_SHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_CLINK - 90, // doomednum - S_CLINK_LOOK1, // spawnstate - 150, // spawnhealth - S_CLINK_WALK1, // seestate - sfx_clksit, // seesound - 8, // reactiontime - sfx_clkatk, // attacksound - S_CLINK_PAIN1, // painstate - 32, // painchance - sfx_clkpai, // painsound - S_CLINK_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_CLINK_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_clkdth, // deathsound - 14, // speed - 20 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 75, // mass - 0, // damage - sfx_clkact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_WIZARD - 15, // doomednum - S_WIZARD_LOOK1, // spawnstate - 180, // spawnhealth - S_WIZARD_WALK1, // seestate - sfx_wizsit, // seesound - 8, // reactiontime - sfx_wizatk, // attacksound - S_WIZARD_PAIN1, // painstate - 64, // painchance - sfx_wizpai, // painsound - 0, // meleestate - S_WIZARD_ATK1, // missilestate - S_NULL, // crashstate - S_WIZARD_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_wizdth, // deathsound - 12, // speed - 16 * FRACUNIT, // radius - 68 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_wizact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_FLOAT | MF_NOGRAVITY, // flags - MF2_PASSMOBJ // flags2 - }, - - { // MT_WIZFX1 - -1, // doomednum - S_WIZFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_WIZFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 18 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_IMP - 66, // doomednum - S_IMP_LOOK1, // spawnstate - 40, // spawnhealth - S_IMP_FLY1, // seestate - sfx_impsit, // seesound - 8, // reactiontime - sfx_impat1, // attacksound - S_IMP_PAIN1, // painstate - 200, // painchance - sfx_imppai, // painsound - S_IMP_MEATK1, // meleestate - S_IMP_MSATK1_1, // missilestate - S_IMP_CRASH1, // crashstate - S_IMP_DIE1, // deathstate - S_IMP_XDIE1, // xdeathstate - sfx_impdth, // deathsound - 10, // speed - 16 * FRACUNIT, // radius - 36 * FRACUNIT, // height - 50, // mass - 0, // damage - sfx_impact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_FLOAT | MF_NOGRAVITY | MF_COUNTKILL, // flags - MF2_SPAWNFLOAT | MF2_PASSMOBJ // flags2 - }, - - { // MT_IMPLEADER - 5, // doomednum - S_IMP_LOOK1, // spawnstate - 80, // spawnhealth - S_IMP_FLY1, // seestate - sfx_impsit, // seesound - 8, // reactiontime - sfx_impat2, // attacksound - S_IMP_PAIN1, // painstate - 200, // painchance - sfx_imppai, // painsound - 0, // meleestate - S_IMP_MSATK2_1, // missilestate - S_IMP_CRASH1, // crashstate - S_IMP_DIE1, // deathstate - S_IMP_XDIE1, // xdeathstate - sfx_impdth, // deathsound - 10, // speed - 16 * FRACUNIT, // radius - 36 * FRACUNIT, // height - 50, // mass - 0, // damage - sfx_impact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_FLOAT | MF_NOGRAVITY | MF_COUNTKILL, // flags - MF2_SPAWNFLOAT | MF2_PASSMOBJ // flags2 - }, - - { // MT_IMPCHUNK1 - -1, // doomednum - S_IMP_CHUNKA1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_IMPCHUNK2 - -1, // doomednum - S_IMP_CHUNKB1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_IMPBALL - -1, // doomednum - S_IMPFX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_IMPFXI1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 10 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_NOTELEPORT // flags2 - }, - - { // MT_KNIGHT - 64, // doomednum - S_KNIGHT_STND1, // spawnstate - 200, // spawnhealth - S_KNIGHT_WALK1, // seestate - sfx_kgtsit, // seesound - 8, // reactiontime - sfx_kgtatk, // attacksound - S_KNIGHT_PAIN1, // painstate - 100, // painchance - sfx_kgtpai, // painsound - S_KNIGHT_ATK1, // meleestate - S_KNIGHT_ATK1, // missilestate - S_NULL, // crashstate - S_KNIGHT_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_kgtdth, // deathsound - 12, // speed - 24 * FRACUNIT, // radius - 78 * FRACUNIT, // height - 150, // mass - 0, // damage - sfx_kgtact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_KNIGHTGHOST - 65, // doomednum - S_KNIGHT_STND1, // spawnstate - 200, // spawnhealth - S_KNIGHT_WALK1, // seestate - sfx_kgtsit, // seesound - 8, // reactiontime - sfx_kgtatk, // attacksound - S_KNIGHT_PAIN1, // painstate - 100, // painchance - sfx_kgtpai, // painsound - S_KNIGHT_ATK1, // meleestate - S_KNIGHT_ATK1, // missilestate - S_NULL, // crashstate - S_KNIGHT_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_kgtdth, // deathsound - 12, // speed - 24 * FRACUNIT, // radius - 78 * FRACUNIT, // height - 150, // mass - 0, // damage - sfx_kgtact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ // flags2 - }, - - { // MT_KNIGHTAXE - -1, // doomednum - S_SPINAXE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SPINAXEX1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 9 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_WINDTHRUST | MF2_NOTELEPORT | MF2_THRUGHOST // flags2 - }, - - { // MT_REDAXE - -1, // doomednum - S_REDAXE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_REDAXEX1, // deathstate - S_NULL, // xdeathstate - sfx_hrnhit, // deathsound - 9 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 7, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_THRUGHOST // flags2 - }, - - { // MT_SORCERER1 - 7, // doomednum - S_SRCR1_LOOK1, // spawnstate - 2000, // spawnhealth - S_SRCR1_WALK1, // seestate - sfx_sbtsit, // seesound - 8, // reactiontime - sfx_sbtatk, // attacksound - S_SRCR1_PAIN1, // painstate - 56, // painchance - sfx_sbtpai, // painsound - 0, // meleestate - S_SRCR1_ATK1, // missilestate - S_NULL, // crashstate - S_SRCR1_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_sbtdth, // deathsound - 16, // speed - 28 * FRACUNIT, // radius - 100 * FRACUNIT, // height - 800, // mass - 0, // damage - sfx_sbtact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ | MF2_BOSS // flags2 - }, - - { // MT_SRCRFX1 - -1, // doomednum - S_SRCRFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SRCRFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 20 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 10, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_SORCERER2 - -1, // doomednum - S_SOR2_LOOK1, // spawnstate - 3500, // spawnhealth - S_SOR2_WALK1, // seestate - sfx_sorsit, // seesound - 8, // reactiontime - sfx_soratk, // attacksound - S_SOR2_PAIN1, // painstate - 32, // painchance - sfx_sorpai, // painsound - 0, // meleestate - S_SOR2_ATK1, // missilestate - S_NULL, // crashstate - S_SOR2_DIE1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 14, // speed - 16 * FRACUNIT, // radius - 70 * FRACUNIT, // height - 300, // mass - 0, // damage - sfx_soract, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ | MF2_BOSS // flags2 - }, - - { // MT_SOR2FX1 - -1, // doomednum - S_SOR2FX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SOR2FXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 20 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SOR2FXSPARK - -1, // doomednum - S_SOR2FXSPARK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 - }, - - { // MT_SOR2FX2 - -1, // doomednum - S_SOR2FX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SOR2FXI2_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 6 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 10, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SOR2TELEFADE - -1, // doomednum - S_SOR2TELEFADE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_MINOTAUR - 9, // doomednum - S_MNTR_LOOK1, // spawnstate - 3000, // spawnhealth - S_MNTR_WALK1, // seestate - sfx_minsit, // seesound - 8, // reactiontime - sfx_minat1, // attacksound - S_MNTR_PAIN1, // painstate - 25, // painchance - sfx_minpai, // painsound - S_MNTR_ATK1_1, // meleestate - S_MNTR_ATK2_1, // missilestate - S_NULL, // crashstate - S_MNTR_DIE1, // deathstate - S_NULL, // xdeathstate - sfx_mindth, // deathsound - 16, // speed - 28 * FRACUNIT, // radius - 100 * FRACUNIT, // height - 800, // mass - 7, // damage - sfx_minact, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF, // flags - MF2_FOOTCLIP | MF2_PASSMOBJ | MF2_BOSS // flags2 - }, - - { // MT_MNTRFX1 - -1, // doomednum - S_MNTRFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MNTRFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 20 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 3, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_MNTRFX2 - -1, // doomednum - S_MNTRFX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MNTRFXI2_1, // deathstate - S_NULL, // xdeathstate - sfx_phohit, // deathsound - 14 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 4, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_MNTRFX3 - -1, // doomednum - S_MNTRFX3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MNTRFXI2_1, // deathstate - S_NULL, // xdeathstate - sfx_phohit, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 4, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_AKYY - 73, // doomednum - S_AKYY1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_NOTDMATCH, // flags - 0 // flags2 - }, - - { // MT_BKYY - 79, // doomednum - S_BKYY1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_NOTDMATCH, // flags - 0 // flags2 - }, - - { // MT_CKEY - 80, // doomednum - S_CKYY1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL | MF_NOTDMATCH, // flags - 0 // flags2 - }, - - { // MT_AMGWNDWIMPY - 10, // doomednum - S_AMG1, // spawnstate - AMMO_GWND_WIMPY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMGWNDHEFTY - 12, // doomednum - S_AMG2_1, // spawnstate - AMMO_GWND_HEFTY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMMACEWIMPY - 13, // doomednum - S_AMM1, // spawnstate - AMMO_MACE_WIMPY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMMACEHEFTY - 16, // doomednum - S_AMM2, // spawnstate - AMMO_MACE_HEFTY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMCBOWWIMPY - 18, // doomednum - S_AMC1, // spawnstate - AMMO_CBOW_WIMPY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMCBOWHEFTY - 19, // doomednum - S_AMC2_1, // spawnstate - AMMO_CBOW_HEFTY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMSKRDWIMPY - 20, // doomednum - S_AMS1_1, // spawnstate - AMMO_SKRD_WIMPY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMSKRDHEFTY - 21, // doomednum - S_AMS2_1, // spawnstate - AMMO_SKRD_HEFTY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMPHRDWIMPY - 22, // doomednum - S_AMP1_1, // spawnstate - AMMO_PHRD_WIMPY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMPHRDHEFTY - 23, // doomednum - S_AMP2_1, // spawnstate - AMMO_PHRD_HEFTY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMBLSRWIMPY - 54, // doomednum - S_AMB1_1, // spawnstate - AMMO_BLSR_WIMPY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AMBLSRHEFTY - 55, // doomednum - S_AMB2_1, // spawnstate - AMMO_BLSR_HEFTY, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_SOUNDWIND - 42, // doomednum - S_SND_WIND, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_SOUNDWATERFALL - 41, // doomednum - S_SND_WATERFALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - } -}; diff --git a/games/NXDoom/src/heretic/info.h b/games/NXDoom/src/heretic/info.h deleted file mode 100644 index 2247b658ab5..00000000000 --- a/games/NXDoom/src/heretic/info.h +++ /dev/null @@ -1,1584 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef HERETIC_INFO_H -#define HERETIC_INFO_H - -typedef enum -{ - SPR_IMPX, - SPR_ACLO, - SPR_PTN1, - SPR_SHLD, - SPR_SHD2, - SPR_BAGH, - SPR_SPMP, - SPR_INVS, - SPR_PTN2, - SPR_SOAR, - SPR_INVU, - SPR_PWBK, - SPR_EGGC, - SPR_EGGM, - SPR_FX01, - SPR_SPHL, - SPR_TRCH, - SPR_FBMB, - SPR_XPL1, - SPR_ATLP, - SPR_PPOD, - SPR_AMG1, - SPR_SPSH, - SPR_LVAS, - SPR_SLDG, - SPR_SKH1, - SPR_SKH2, - SPR_SKH3, - SPR_SKH4, - SPR_CHDL, - SPR_SRTC, - SPR_SMPL, - SPR_STGS, - SPR_STGL, - SPR_STCS, - SPR_STCL, - SPR_KFR1, - SPR_BARL, - SPR_BRPL, - SPR_MOS1, - SPR_MOS2, - SPR_WTRH, - SPR_HCOR, - SPR_KGZ1, - SPR_KGZB, - SPR_KGZG, - SPR_KGZY, - SPR_VLCO, - SPR_VFBL, - SPR_VTFB, - SPR_SFFI, - SPR_TGLT, - SPR_TELE, - SPR_STFF, - SPR_PUF3, - SPR_PUF4, - SPR_BEAK, - SPR_WGNT, - SPR_GAUN, - SPR_PUF1, - SPR_WBLS, - SPR_BLSR, - SPR_FX18, - SPR_FX17, - SPR_WMCE, - SPR_MACE, - SPR_FX02, - SPR_WSKL, - SPR_HROD, - SPR_FX00, - SPR_FX20, - SPR_FX21, - SPR_FX22, - SPR_FX23, - SPR_GWND, - SPR_PUF2, - SPR_WPHX, - SPR_PHNX, - SPR_FX04, - SPR_FX08, - SPR_FX09, - SPR_WBOW, - SPR_CRBW, - SPR_FX03, - SPR_BLOD, - SPR_PLAY, - SPR_FDTH, - SPR_BSKL, - SPR_CHKN, - SPR_MUMM, - SPR_FX15, - SPR_BEAS, - SPR_FRB1, - SPR_SNKE, - SPR_SNFX, - SPR_HEAD, - SPR_FX05, - SPR_FX06, - SPR_FX07, - SPR_CLNK, - SPR_WZRD, - SPR_FX11, - SPR_FX10, - SPR_KNIG, - SPR_SPAX, - SPR_RAXE, - SPR_SRCR, - SPR_FX14, - SPR_SOR2, - SPR_SDTH, - SPR_FX16, - SPR_MNTR, - SPR_FX12, - SPR_FX13, - SPR_AKYY, - SPR_BKYY, - SPR_CKYY, - SPR_AMG2, - SPR_AMM1, - SPR_AMM2, - SPR_AMC1, - SPR_AMC2, - SPR_AMS1, - SPR_AMS2, - SPR_AMP1, - SPR_AMP2, - SPR_AMB1, - SPR_AMB2, - NUMSPRITES -} spritenum_t; - -typedef enum -{ - S_NULL, - S_FREETARGMOBJ, - S_ITEM_PTN1_1, - S_ITEM_PTN1_2, - S_ITEM_PTN1_3, - S_ITEM_SHLD1, - S_ITEM_SHD2_1, - S_ITEM_BAGH1, - S_ITEM_SPMP1, - S_HIDESPECIAL1, - S_HIDESPECIAL2, - S_HIDESPECIAL3, - S_HIDESPECIAL4, - S_HIDESPECIAL5, - S_HIDESPECIAL6, - S_HIDESPECIAL7, - S_HIDESPECIAL8, - S_HIDESPECIAL9, - S_HIDESPECIAL10, - S_HIDESPECIAL11, - S_DORMANTARTI1, - S_DORMANTARTI2, - S_DORMANTARTI3, - S_DORMANTARTI4, - S_DORMANTARTI5, - S_DORMANTARTI6, - S_DORMANTARTI7, - S_DORMANTARTI8, - S_DORMANTARTI9, - S_DORMANTARTI10, - S_DORMANTARTI11, - S_DORMANTARTI12, - S_DORMANTARTI13, - S_DORMANTARTI14, - S_DORMANTARTI15, - S_DORMANTARTI16, - S_DORMANTARTI17, - S_DORMANTARTI18, - S_DORMANTARTI19, - S_DORMANTARTI20, - S_DORMANTARTI21, - S_DEADARTI1, - S_DEADARTI2, - S_DEADARTI3, - S_DEADARTI4, - S_DEADARTI5, - S_DEADARTI6, - S_DEADARTI7, - S_DEADARTI8, - S_DEADARTI9, - S_DEADARTI10, - S_ARTI_INVS1, - S_ARTI_PTN2_1, - S_ARTI_PTN2_2, - S_ARTI_PTN2_3, - S_ARTI_SOAR1, - S_ARTI_SOAR2, - S_ARTI_SOAR3, - S_ARTI_SOAR4, - S_ARTI_INVU1, - S_ARTI_INVU2, - S_ARTI_INVU3, - S_ARTI_INVU4, - S_ARTI_PWBK1, - S_ARTI_EGGC1, - S_ARTI_EGGC2, - S_ARTI_EGGC3, - S_ARTI_EGGC4, - S_EGGFX1, - S_EGGFX2, - S_EGGFX3, - S_EGGFX4, - S_EGGFX5, - S_EGGFXI1_1, - S_EGGFXI1_2, - S_EGGFXI1_3, - S_EGGFXI1_4, - S_ARTI_SPHL1, - S_ARTI_TRCH1, - S_ARTI_TRCH2, - S_ARTI_TRCH3, - S_ARTI_FBMB1, - S_FIREBOMB1, - S_FIREBOMB2, - S_FIREBOMB3, - S_FIREBOMB4, - S_FIREBOMB5, - S_FIREBOMB6, - S_FIREBOMB7, - S_FIREBOMB8, - S_FIREBOMB9, - S_FIREBOMB10, - S_FIREBOMB11, - S_ARTI_ATLP1, - S_ARTI_ATLP2, - S_ARTI_ATLP3, - S_ARTI_ATLP4, - S_POD_WAIT1, - S_POD_PAIN1, - S_POD_DIE1, - S_POD_DIE2, - S_POD_DIE3, - S_POD_DIE4, - S_POD_GROW1, - S_POD_GROW2, - S_POD_GROW3, - S_POD_GROW4, - S_POD_GROW5, - S_POD_GROW6, - S_POD_GROW7, - S_POD_GROW8, - S_PODGOO1, - S_PODGOO2, - S_PODGOOX, - S_PODGENERATOR, - S_SPLASH1, - S_SPLASH2, - S_SPLASH3, - S_SPLASH4, - S_SPLASHX, - S_SPLASHBASE1, - S_SPLASHBASE2, - S_SPLASHBASE3, - S_SPLASHBASE4, - S_SPLASHBASE5, - S_SPLASHBASE6, - S_SPLASHBASE7, - S_LAVASPLASH1, - S_LAVASPLASH2, - S_LAVASPLASH3, - S_LAVASPLASH4, - S_LAVASPLASH5, - S_LAVASPLASH6, - S_LAVASMOKE1, - S_LAVASMOKE2, - S_LAVASMOKE3, - S_LAVASMOKE4, - S_LAVASMOKE5, - S_SLUDGECHUNK1, - S_SLUDGECHUNK2, - S_SLUDGECHUNK3, - S_SLUDGECHUNK4, - S_SLUDGECHUNKX, - S_SLUDGESPLASH1, - S_SLUDGESPLASH2, - S_SLUDGESPLASH3, - S_SLUDGESPLASH4, - S_SKULLHANG70_1, - S_SKULLHANG60_1, - S_SKULLHANG45_1, - S_SKULLHANG35_1, - S_CHANDELIER1, - S_CHANDELIER2, - S_CHANDELIER3, - S_SERPTORCH1, - S_SERPTORCH2, - S_SERPTORCH3, - S_SMALLPILLAR, - S_STALAGMITESMALL, - S_STALAGMITELARGE, - S_STALACTITESMALL, - S_STALACTITELARGE, - S_FIREBRAZIER1, - S_FIREBRAZIER2, - S_FIREBRAZIER3, - S_FIREBRAZIER4, - S_FIREBRAZIER5, - S_FIREBRAZIER6, - S_FIREBRAZIER7, - S_FIREBRAZIER8, - S_BARREL, - S_BRPILLAR, - S_MOSS1, - S_MOSS2, - S_WALLTORCH1, - S_WALLTORCH2, - S_WALLTORCH3, - S_HANGINGCORPSE, - S_KEYGIZMO1, - S_KEYGIZMO2, - S_KEYGIZMO3, - S_KGZ_START, - S_KGZ_BLUEFLOAT1, - S_KGZ_GREENFLOAT1, - S_KGZ_YELLOWFLOAT1, - S_VOLCANO1, - S_VOLCANO2, - S_VOLCANO3, - S_VOLCANO4, - S_VOLCANO5, - S_VOLCANO6, - S_VOLCANO7, - S_VOLCANO8, - S_VOLCANO9, - S_VOLCANOBALL1, - S_VOLCANOBALL2, - S_VOLCANOBALLX1, - S_VOLCANOBALLX2, - S_VOLCANOBALLX3, - S_VOLCANOBALLX4, - S_VOLCANOBALLX5, - S_VOLCANOBALLX6, - S_VOLCANOTBALL1, - S_VOLCANOTBALL2, - S_VOLCANOTBALLX1, - S_VOLCANOTBALLX2, - S_VOLCANOTBALLX3, - S_VOLCANOTBALLX4, - S_VOLCANOTBALLX5, - S_VOLCANOTBALLX6, - S_VOLCANOTBALLX7, - S_TELEGLITGEN1, - S_TELEGLITGEN2, - S_TELEGLITTER1_1, - S_TELEGLITTER1_2, - S_TELEGLITTER1_3, - S_TELEGLITTER1_4, - S_TELEGLITTER1_5, - S_TELEGLITTER2_1, - S_TELEGLITTER2_2, - S_TELEGLITTER2_3, - S_TELEGLITTER2_4, - S_TELEGLITTER2_5, - S_TFOG1, - S_TFOG2, - S_TFOG3, - S_TFOG4, - S_TFOG5, - S_TFOG6, - S_TFOG7, - S_TFOG8, - S_TFOG9, - S_TFOG10, - S_TFOG11, - S_TFOG12, - S_TFOG13, - S_LIGHTDONE, - S_STAFFREADY, - S_STAFFDOWN, - S_STAFFUP, - S_STAFFREADY2_1, - S_STAFFREADY2_2, - S_STAFFREADY2_3, - S_STAFFDOWN2, - S_STAFFUP2, - S_STAFFATK1_1, - S_STAFFATK1_2, - S_STAFFATK1_3, - S_STAFFATK2_1, - S_STAFFATK2_2, - S_STAFFATK2_3, - S_STAFFPUFF1, - S_STAFFPUFF2, - S_STAFFPUFF3, - S_STAFFPUFF4, - S_STAFFPUFF2_1, - S_STAFFPUFF2_2, - S_STAFFPUFF2_3, - S_STAFFPUFF2_4, - S_STAFFPUFF2_5, - S_STAFFPUFF2_6, - S_BEAKREADY, - S_BEAKDOWN, - S_BEAKUP, - S_BEAKATK1_1, - S_BEAKATK2_1, - S_WGNT, - S_GAUNTLETREADY, - S_GAUNTLETDOWN, - S_GAUNTLETUP, - S_GAUNTLETREADY2_1, - S_GAUNTLETREADY2_2, - S_GAUNTLETREADY2_3, - S_GAUNTLETDOWN2, - S_GAUNTLETUP2, - S_GAUNTLETATK1_1, - S_GAUNTLETATK1_2, - S_GAUNTLETATK1_3, - S_GAUNTLETATK1_4, - S_GAUNTLETATK1_5, - S_GAUNTLETATK1_6, - S_GAUNTLETATK1_7, - S_GAUNTLETATK2_1, - S_GAUNTLETATK2_2, - S_GAUNTLETATK2_3, - S_GAUNTLETATK2_4, - S_GAUNTLETATK2_5, - S_GAUNTLETATK2_6, - S_GAUNTLETATK2_7, - S_GAUNTLETPUFF1_1, - S_GAUNTLETPUFF1_2, - S_GAUNTLETPUFF1_3, - S_GAUNTLETPUFF1_4, - S_GAUNTLETPUFF2_1, - S_GAUNTLETPUFF2_2, - S_GAUNTLETPUFF2_3, - S_GAUNTLETPUFF2_4, - S_BLSR, - S_BLASTERREADY, - S_BLASTERDOWN, - S_BLASTERUP, - S_BLASTERATK1_1, - S_BLASTERATK1_2, - S_BLASTERATK1_3, - S_BLASTERATK1_4, - S_BLASTERATK1_5, - S_BLASTERATK1_6, - S_BLASTERATK2_1, - S_BLASTERATK2_2, - S_BLASTERATK2_3, - S_BLASTERATK2_4, - S_BLASTERATK2_5, - S_BLASTERATK2_6, - S_BLASTERFX1_1, - S_BLASTERFXI1_1, - S_BLASTERFXI1_2, - S_BLASTERFXI1_3, - S_BLASTERFXI1_4, - S_BLASTERFXI1_5, - S_BLASTERFXI1_6, - S_BLASTERFXI1_7, - S_BLASTERSMOKE1, - S_BLASTERSMOKE2, - S_BLASTERSMOKE3, - S_BLASTERSMOKE4, - S_BLASTERSMOKE5, - S_RIPPER1, - S_RIPPER2, - S_RIPPERX1, - S_RIPPERX2, - S_RIPPERX3, - S_RIPPERX4, - S_RIPPERX5, - S_BLASTERPUFF1_1, - S_BLASTERPUFF1_2, - S_BLASTERPUFF1_3, - S_BLASTERPUFF1_4, - S_BLASTERPUFF1_5, - S_BLASTERPUFF2_1, - S_BLASTERPUFF2_2, - S_BLASTERPUFF2_3, - S_BLASTERPUFF2_4, - S_BLASTERPUFF2_5, - S_BLASTERPUFF2_6, - S_BLASTERPUFF2_7, - S_WMCE, - S_MACEREADY, - S_MACEDOWN, - S_MACEUP, - S_MACEATK1_1, - S_MACEATK1_2, - S_MACEATK1_3, - S_MACEATK1_4, - S_MACEATK1_5, - S_MACEATK1_6, - S_MACEATK1_7, - S_MACEATK1_8, - S_MACEATK1_9, - S_MACEATK1_10, - S_MACEATK2_1, - S_MACEATK2_2, - S_MACEATK2_3, - S_MACEATK2_4, - S_MACEFX1_1, - S_MACEFX1_2, - S_MACEFXI1_1, - S_MACEFXI1_2, - S_MACEFXI1_3, - S_MACEFXI1_4, - S_MACEFXI1_5, - S_MACEFX2_1, - S_MACEFX2_2, - S_MACEFXI2_1, - S_MACEFX3_1, - S_MACEFX3_2, - S_MACEFX4_1, - S_MACEFXI4_1, - S_WSKL, - S_HORNRODREADY, - S_HORNRODDOWN, - S_HORNRODUP, - S_HORNRODATK1_1, - S_HORNRODATK1_2, - S_HORNRODATK1_3, - S_HORNRODATK2_1, - S_HORNRODATK2_2, - S_HORNRODATK2_3, - S_HORNRODATK2_4, - S_HORNRODATK2_5, - S_HORNRODATK2_6, - S_HORNRODATK2_7, - S_HORNRODATK2_8, - S_HORNRODATK2_9, - S_HRODFX1_1, - S_HRODFX1_2, - S_HRODFXI1_1, - S_HRODFXI1_2, - S_HRODFXI1_3, - S_HRODFXI1_4, - S_HRODFXI1_5, - S_HRODFXI1_6, - S_HRODFX2_1, - S_HRODFX2_2, - S_HRODFX2_3, - S_HRODFX2_4, - S_HRODFXI2_1, - S_HRODFXI2_2, - S_HRODFXI2_3, - S_HRODFXI2_4, - S_HRODFXI2_5, - S_HRODFXI2_6, - S_HRODFXI2_7, - S_HRODFXI2_8, - S_RAINPLR1_1, - S_RAINPLR2_1, - S_RAINPLR3_1, - S_RAINPLR4_1, - S_RAINPLR1X_1, - S_RAINPLR1X_2, - S_RAINPLR1X_3, - S_RAINPLR1X_4, - S_RAINPLR1X_5, - S_RAINPLR2X_1, - S_RAINPLR2X_2, - S_RAINPLR2X_3, - S_RAINPLR2X_4, - S_RAINPLR2X_5, - S_RAINPLR3X_1, - S_RAINPLR3X_2, - S_RAINPLR3X_3, - S_RAINPLR3X_4, - S_RAINPLR3X_5, - S_RAINPLR4X_1, - S_RAINPLR4X_2, - S_RAINPLR4X_3, - S_RAINPLR4X_4, - S_RAINPLR4X_5, - S_RAINAIRXPLR1_1, - S_RAINAIRXPLR2_1, - S_RAINAIRXPLR3_1, - S_RAINAIRXPLR4_1, - S_RAINAIRXPLR1_2, - S_RAINAIRXPLR2_2, - S_RAINAIRXPLR3_2, - S_RAINAIRXPLR4_2, - S_RAINAIRXPLR1_3, - S_RAINAIRXPLR2_3, - S_RAINAIRXPLR3_3, - S_RAINAIRXPLR4_3, - S_GOLDWANDREADY, - S_GOLDWANDDOWN, - S_GOLDWANDUP, - S_GOLDWANDATK1_1, - S_GOLDWANDATK1_2, - S_GOLDWANDATK1_3, - S_GOLDWANDATK1_4, - S_GOLDWANDATK2_1, - S_GOLDWANDATK2_2, - S_GOLDWANDATK2_3, - S_GOLDWANDATK2_4, - S_GWANDFX1_1, - S_GWANDFX1_2, - S_GWANDFXI1_1, - S_GWANDFXI1_2, - S_GWANDFXI1_3, - S_GWANDFXI1_4, - S_GWANDFX2_1, - S_GWANDFX2_2, - S_GWANDPUFF1_1, - S_GWANDPUFF1_2, - S_GWANDPUFF1_3, - S_GWANDPUFF1_4, - S_GWANDPUFF1_5, - S_WPHX, - S_PHOENIXREADY, - S_PHOENIXDOWN, - S_PHOENIXUP, - S_PHOENIXATK1_1, - S_PHOENIXATK1_2, - S_PHOENIXATK1_3, - S_PHOENIXATK1_4, - S_PHOENIXATK1_5, - S_PHOENIXATK2_1, - S_PHOENIXATK2_2, - S_PHOENIXATK2_3, - S_PHOENIXATK2_4, - S_PHOENIXFX1_1, - S_PHOENIXFXI1_1, - S_PHOENIXFXI1_2, - S_PHOENIXFXI1_3, - S_PHOENIXFXI1_4, - S_PHOENIXFXI1_5, - S_PHOENIXFXI1_6, - S_PHOENIXFXI1_7, - S_PHOENIXFXI1_8, - S_PHOENIXFXIX_1, // [ States in Heretic 1.0 that were removed - S_PHOENIXFXIX_2, - S_PHOENIXFXIX_3, // ] - S_PHOENIXPUFF1, - S_PHOENIXPUFF2, - S_PHOENIXPUFF3, - S_PHOENIXPUFF4, - S_PHOENIXPUFF5, - S_PHOENIXFX2_1, - S_PHOENIXFX2_2, - S_PHOENIXFX2_3, - S_PHOENIXFX2_4, - S_PHOENIXFX2_5, - S_PHOENIXFX2_6, - S_PHOENIXFX2_7, - S_PHOENIXFX2_8, - S_PHOENIXFX2_9, - S_PHOENIXFX2_10, - S_PHOENIXFXI2_1, - S_PHOENIXFXI2_2, - S_PHOENIXFXI2_3, - S_PHOENIXFXI2_4, - S_PHOENIXFXI2_5, - S_WBOW, - S_CRBOW1, - S_CRBOW2, - S_CRBOW3, - S_CRBOW4, - S_CRBOW5, - S_CRBOW6, - S_CRBOW7, - S_CRBOW8, - S_CRBOW9, - S_CRBOW10, - S_CRBOW11, - S_CRBOW12, - S_CRBOW13, - S_CRBOW14, - S_CRBOW15, - S_CRBOW16, - S_CRBOW17, - S_CRBOW18, - S_CRBOWDOWN, - S_CRBOWUP, - S_CRBOWATK1_1, - S_CRBOWATK1_2, - S_CRBOWATK1_3, - S_CRBOWATK1_4, - S_CRBOWATK1_5, - S_CRBOWATK1_6, - S_CRBOWATK1_7, - S_CRBOWATK1_8, - S_CRBOWATK2_1, - S_CRBOWATK2_2, - S_CRBOWATK2_3, - S_CRBOWATK2_4, - S_CRBOWATK2_5, - S_CRBOWATK2_6, - S_CRBOWATK2_7, - S_CRBOWATK2_8, - S_CRBOWFX1, - S_CRBOWFXI1_1, - S_CRBOWFXI1_2, - S_CRBOWFXI1_3, - S_CRBOWFX2, - S_CRBOWFX3, - S_CRBOWFXI3_1, - S_CRBOWFXI3_2, - S_CRBOWFXI3_3, - S_CRBOWFX4_1, - S_CRBOWFX4_2, - S_BLOOD1, - S_BLOOD2, - S_BLOOD3, - S_BLOODSPLATTER1, - S_BLOODSPLATTER2, - S_BLOODSPLATTER3, - S_BLOODSPLATTERX, - S_PLAY, - S_PLAY_RUN1, - S_PLAY_RUN2, - S_PLAY_RUN3, - S_PLAY_RUN4, - S_PLAY_ATK1, - S_PLAY_ATK2, - S_PLAY_PAIN, - S_PLAY_PAIN2, - S_PLAY_DIE1, - S_PLAY_DIE2, - S_PLAY_DIE3, - S_PLAY_DIE4, - S_PLAY_DIE5, - S_PLAY_DIE6, - S_PLAY_DIE7, - S_PLAY_DIE8, - S_PLAY_DIE9, - S_PLAY_XDIE1, - S_PLAY_XDIE2, - S_PLAY_XDIE3, - S_PLAY_XDIE4, - S_PLAY_XDIE5, - S_PLAY_XDIE6, - S_PLAY_XDIE7, - S_PLAY_XDIE8, - S_PLAY_XDIE9, - S_PLAY_FDTH1, - S_PLAY_FDTH2, - S_PLAY_FDTH3, - S_PLAY_FDTH4, - S_PLAY_FDTH5, - S_PLAY_FDTH6, - S_PLAY_FDTH7, - S_PLAY_FDTH8, - S_PLAY_FDTH9, - S_PLAY_FDTH10, - S_PLAY_FDTH11, - S_PLAY_FDTH12, - S_PLAY_FDTH13, - S_PLAY_FDTH14, - S_PLAY_FDTH15, - S_PLAY_FDTH16, - S_PLAY_FDTH17, - S_PLAY_FDTH18, - S_PLAY_FDTH19, // < These two frames were not present in the Heretic - S_PLAY_FDTH20, // < 1.0 executable (fire death animation was extended) - S_BLOODYSKULL1, - S_BLOODYSKULL2, - S_BLOODYSKULL3, - S_BLOODYSKULL4, - S_BLOODYSKULL5, - S_BLOODYSKULLX1, - S_BLOODYSKULLX2, - S_CHICPLAY, - S_CHICPLAY_RUN1, - S_CHICPLAY_RUN2, - S_CHICPLAY_RUN3, - S_CHICPLAY_RUN4, - S_CHICPLAY_ATK1, - S_CHICPLAY_PAIN, - S_CHICPLAY_PAIN2, - S_CHICKEN_LOOK1, - S_CHICKEN_LOOK2, - S_CHICKEN_WALK1, - S_CHICKEN_WALK2, - S_CHICKEN_PAIN1, - S_CHICKEN_PAIN2, - S_CHICKEN_ATK1, - S_CHICKEN_ATK2, - S_CHICKEN_DIE1, - S_CHICKEN_DIE2, - S_CHICKEN_DIE3, - S_CHICKEN_DIE4, - S_CHICKEN_DIE5, - S_CHICKEN_DIE6, - S_CHICKEN_DIE7, - S_CHICKEN_DIE8, - S_FEATHER1, - S_FEATHER2, - S_FEATHER3, - S_FEATHER4, - S_FEATHER5, - S_FEATHER6, - S_FEATHER7, - S_FEATHER8, - S_FEATHERX, - S_MUMMY_LOOK1, - S_MUMMY_LOOK2, - S_MUMMY_WALK1, - S_MUMMY_WALK2, - S_MUMMY_WALK3, - S_MUMMY_WALK4, - S_MUMMY_ATK1, - S_MUMMY_ATK2, - S_MUMMY_ATK3, - S_MUMMYL_ATK1, - S_MUMMYL_ATK2, - S_MUMMYL_ATK3, - S_MUMMYL_ATK4, - S_MUMMYL_ATK5, - S_MUMMYL_ATK6, - S_MUMMY_PAIN1, - S_MUMMY_PAIN2, - S_MUMMY_DIE1, - S_MUMMY_DIE2, - S_MUMMY_DIE3, - S_MUMMY_DIE4, - S_MUMMY_DIE5, - S_MUMMY_DIE6, - S_MUMMY_DIE7, - S_MUMMY_DIE8, - S_MUMMY_SOUL1, - S_MUMMY_SOUL2, - S_MUMMY_SOUL3, - S_MUMMY_SOUL4, - S_MUMMY_SOUL5, - S_MUMMY_SOUL6, - S_MUMMY_SOUL7, - S_MUMMYFX1_1, - S_MUMMYFX1_2, - S_MUMMYFX1_3, - S_MUMMYFX1_4, - S_MUMMYFXI1_1, - S_MUMMYFXI1_2, - S_MUMMYFXI1_3, - S_MUMMYFXI1_4, - S_BEAST_LOOK1, - S_BEAST_LOOK2, - S_BEAST_WALK1, - S_BEAST_WALK2, - S_BEAST_WALK3, - S_BEAST_WALK4, - S_BEAST_WALK5, - S_BEAST_WALK6, - S_BEAST_ATK1, - S_BEAST_ATK2, - S_BEAST_PAIN1, - S_BEAST_PAIN2, - S_BEAST_DIE1, - S_BEAST_DIE2, - S_BEAST_DIE3, - S_BEAST_DIE4, - S_BEAST_DIE5, - S_BEAST_DIE6, - S_BEAST_DIE7, - S_BEAST_DIE8, - S_BEAST_DIE9, - S_BEAST_XDIE1, - S_BEAST_XDIE2, - S_BEAST_XDIE3, - S_BEAST_XDIE4, - S_BEAST_XDIE5, - S_BEAST_XDIE6, - S_BEAST_XDIE7, - S_BEAST_XDIE8, - S_BEASTBALL1, - S_BEASTBALL2, - S_BEASTBALL3, - S_BEASTBALL4, - S_BEASTBALL5, - S_BEASTBALL6, - S_BEASTBALLX1, - S_BEASTBALLX2, - S_BEASTBALLX3, - S_BEASTBALLX4, - S_BEASTBALLX5, - S_BURNBALL1, - S_BURNBALL2, - S_BURNBALL3, - S_BURNBALL4, - S_BURNBALL5, - S_BURNBALL6, - S_BURNBALL7, - S_BURNBALL8, - S_BURNBALLFB1, - S_BURNBALLFB2, - S_BURNBALLFB3, - S_BURNBALLFB4, - S_BURNBALLFB5, - S_BURNBALLFB6, - S_BURNBALLFB7, - S_BURNBALLFB8, - S_PUFFY1, - S_PUFFY2, - S_PUFFY3, - S_PUFFY4, - S_PUFFY5, - S_SNAKE_LOOK1, - S_SNAKE_LOOK2, - S_SNAKE_WALK1, - S_SNAKE_WALK2, - S_SNAKE_WALK3, - S_SNAKE_WALK4, - S_SNAKE_ATK1, - S_SNAKE_ATK2, - S_SNAKE_ATK3, - S_SNAKE_ATK4, - S_SNAKE_ATK5, - S_SNAKE_ATK6, - S_SNAKE_ATK7, - S_SNAKE_ATK8, - S_SNAKE_ATK9, - S_SNAKE_PAIN1, - S_SNAKE_PAIN2, - S_SNAKE_DIE1, - S_SNAKE_DIE2, - S_SNAKE_DIE3, - S_SNAKE_DIE4, - S_SNAKE_DIE5, - S_SNAKE_DIE6, - S_SNAKE_DIE7, - S_SNAKE_DIE8, - S_SNAKE_DIE9, - S_SNAKE_DIE10, - S_SNAKEPRO_A1, - S_SNAKEPRO_A2, - S_SNAKEPRO_A3, - S_SNAKEPRO_A4, - S_SNAKEPRO_AX1, - S_SNAKEPRO_AX2, - S_SNAKEPRO_AX3, - S_SNAKEPRO_AX4, - S_SNAKEPRO_AX5, - S_SNAKEPRO_B1, - S_SNAKEPRO_B2, - S_SNAKEPRO_BX1, - S_SNAKEPRO_BX2, - S_SNAKEPRO_BX3, - S_SNAKEPRO_BX4, - S_HEAD_LOOK, - S_HEAD_FLOAT, - S_HEAD_ATK1, - S_HEAD_ATK2, - S_HEAD_PAIN1, - S_HEAD_PAIN2, - S_HEAD_DIE1, - S_HEAD_DIE2, - S_HEAD_DIE3, - S_HEAD_DIE4, - S_HEAD_DIE5, - S_HEAD_DIE6, - S_HEAD_DIE7, - S_HEADFX1_1, - S_HEADFX1_2, - S_HEADFX1_3, - S_HEADFXI1_1, - S_HEADFXI1_2, - S_HEADFXI1_3, - S_HEADFXI1_4, - S_HEADFX2_1, - S_HEADFX2_2, - S_HEADFX2_3, - S_HEADFXI2_1, - S_HEADFXI2_2, - S_HEADFXI2_3, - S_HEADFXI2_4, - S_HEADFX3_1, - S_HEADFX3_2, - S_HEADFX3_3, - S_HEADFX3_4, - S_HEADFX3_5, - S_HEADFX3_6, - S_HEADFXI3_1, - S_HEADFXI3_2, - S_HEADFXI3_3, - S_HEADFXI3_4, - S_HEADFX4_1, - S_HEADFX4_2, - S_HEADFX4_3, - S_HEADFX4_4, - S_HEADFX4_5, - S_HEADFX4_6, - S_HEADFX4_7, - S_HEADFXI4_1, - S_HEADFXI4_2, - S_HEADFXI4_3, - S_HEADFXI4_4, - S_CLINK_LOOK1, - S_CLINK_LOOK2, - S_CLINK_WALK1, - S_CLINK_WALK2, - S_CLINK_WALK3, - S_CLINK_WALK4, - S_CLINK_ATK1, - S_CLINK_ATK2, - S_CLINK_ATK3, - S_CLINK_PAIN1, - S_CLINK_PAIN2, - S_CLINK_DIE1, - S_CLINK_DIE2, - S_CLINK_DIE3, - S_CLINK_DIE4, - S_CLINK_DIE5, - S_CLINK_DIE6, - S_CLINK_DIE7, - S_WIZARD_LOOK1, - S_WIZARD_LOOK2, - S_WIZARD_WALK1, - S_WIZARD_WALK2, - S_WIZARD_WALK3, - S_WIZARD_WALK4, - S_WIZARD_WALK5, - S_WIZARD_WALK6, - S_WIZARD_WALK7, - S_WIZARD_WALK8, - S_WIZARD_ATK1, - S_WIZARD_ATK2, - S_WIZARD_ATK3, - S_WIZARD_ATK4, - S_WIZARD_ATK5, - S_WIZARD_ATK6, - S_WIZARD_ATK7, - S_WIZARD_ATK8, - S_WIZARD_ATK9, - S_WIZARD_PAIN1, - S_WIZARD_PAIN2, - S_WIZARD_DIE1, - S_WIZARD_DIE2, - S_WIZARD_DIE3, - S_WIZARD_DIE4, - S_WIZARD_DIE5, - S_WIZARD_DIE6, - S_WIZARD_DIE7, - S_WIZARD_DIE8, - S_WIZFX1_1, - S_WIZFX1_2, - S_WIZFXI1_1, - S_WIZFXI1_2, - S_WIZFXI1_3, - S_WIZFXI1_4, - S_WIZFXI1_5, - S_IMP_LOOK1, - S_IMP_LOOK2, - S_IMP_LOOK3, - S_IMP_LOOK4, - S_IMP_FLY1, - S_IMP_FLY2, - S_IMP_FLY3, - S_IMP_FLY4, - S_IMP_FLY5, - S_IMP_FLY6, - S_IMP_FLY7, - S_IMP_FLY8, - S_IMP_MEATK1, - S_IMP_MEATK2, - S_IMP_MEATK3, - S_IMP_MSATK1_1, - S_IMP_MSATK1_2, - S_IMP_MSATK1_3, - S_IMP_MSATK1_4, - S_IMP_MSATK1_5, - S_IMP_MSATK1_6, - S_IMP_MSATK2_1, - S_IMP_MSATK2_2, - S_IMP_MSATK2_3, - S_IMP_PAIN1, - S_IMP_PAIN2, - S_IMP_DIE1, - S_IMP_DIE2, - S_IMP_XDIE1, - S_IMP_XDIE2, - S_IMP_XDIE3, - S_IMP_XDIE4, - S_IMP_XDIE5, - S_IMP_CRASH1, - S_IMP_CRASH2, - S_IMP_CRASH3, - S_IMP_CRASH4, - S_IMP_XCRASH1, - S_IMP_XCRASH2, - S_IMP_XCRASH3, - S_IMP_CHUNKA1, - S_IMP_CHUNKA2, - S_IMP_CHUNKA3, - S_IMP_CHUNKB1, - S_IMP_CHUNKB2, - S_IMP_CHUNKB3, - S_IMPFX1, - S_IMPFX2, - S_IMPFX3, - S_IMPFXI1, - S_IMPFXI2, - S_IMPFXI3, - S_IMPFXI4, - S_KNIGHT_STND1, - S_KNIGHT_STND2, - S_KNIGHT_WALK1, - S_KNIGHT_WALK2, - S_KNIGHT_WALK3, - S_KNIGHT_WALK4, - S_KNIGHT_ATK1, - S_KNIGHT_ATK2, - S_KNIGHT_ATK3, - S_KNIGHT_ATK4, - S_KNIGHT_ATK5, - S_KNIGHT_ATK6, - S_KNIGHT_PAIN1, - S_KNIGHT_PAIN2, - S_KNIGHT_DIE1, - S_KNIGHT_DIE2, - S_KNIGHT_DIE3, - S_KNIGHT_DIE4, - S_KNIGHT_DIE5, - S_KNIGHT_DIE6, - S_KNIGHT_DIE7, - S_SPINAXE1, - S_SPINAXE2, - S_SPINAXE3, - S_SPINAXEX1, - S_SPINAXEX2, - S_SPINAXEX3, - S_REDAXE1, - S_REDAXE2, - S_REDAXEX1, - S_REDAXEX2, - S_REDAXEX3, - S_SRCR1_LOOK1, - S_SRCR1_LOOK2, - S_SRCR1_WALK1, - S_SRCR1_WALK2, - S_SRCR1_WALK3, - S_SRCR1_WALK4, - S_SRCR1_PAIN1, - S_SRCR1_ATK1, - S_SRCR1_ATK2, - S_SRCR1_ATK3, - S_SRCR1_ATK4, - S_SRCR1_ATK5, - S_SRCR1_ATK6, - S_SRCR1_ATK7, - S_SRCR1_DIE1, - S_SRCR1_DIE2, - S_SRCR1_DIE3, - S_SRCR1_DIE4, - S_SRCR1_DIE5, - S_SRCR1_DIE6, - S_SRCR1_DIE7, - S_SRCR1_DIE8, - S_SRCR1_DIE9, - S_SRCR1_DIE10, - S_SRCR1_DIE11, - S_SRCR1_DIE12, - S_SRCR1_DIE13, - S_SRCR1_DIE14, - S_SRCR1_DIE15, - S_SRCR1_DIE16, - S_SRCR1_DIE17, - S_SRCRFX1_1, - S_SRCRFX1_2, - S_SRCRFX1_3, - S_SRCRFXI1_1, - S_SRCRFXI1_2, - S_SRCRFXI1_3, - S_SRCRFXI1_4, - S_SRCRFXI1_5, - S_SOR2_RISE1, - S_SOR2_RISE2, - S_SOR2_RISE3, - S_SOR2_RISE4, - S_SOR2_RISE5, - S_SOR2_RISE6, - S_SOR2_RISE7, - S_SOR2_LOOK1, - S_SOR2_LOOK2, - S_SOR2_WALK1, - S_SOR2_WALK2, - S_SOR2_WALK3, - S_SOR2_WALK4, - S_SOR2_PAIN1, - S_SOR2_PAIN2, - S_SOR2_ATK1, - S_SOR2_ATK2, - S_SOR2_ATK3, - S_SOR2_TELE1, - S_SOR2_TELE2, - S_SOR2_TELE3, - S_SOR2_TELE4, - S_SOR2_TELE5, - S_SOR2_TELE6, - S_SOR2_DIE1, - S_SOR2_DIE2, - S_SOR2_DIE3, - S_SOR2_DIE4, - S_SOR2_DIE5, - S_SOR2_DIE6, - S_SOR2_DIE7, - S_SOR2_DIE8, - S_SOR2_DIE9, - S_SOR2_DIE10, - S_SOR2_DIE11, - S_SOR2_DIE12, - S_SOR2_DIE13, - S_SOR2_DIE14, - S_SOR2_DIE15, - S_SOR2FX1_1, - S_SOR2FX1_2, - S_SOR2FX1_3, - S_SOR2FXI1_1, - S_SOR2FXI1_2, - S_SOR2FXI1_3, - S_SOR2FXI1_4, - S_SOR2FXI1_5, - S_SOR2FXI1_6, - S_SOR2FXSPARK1, - S_SOR2FXSPARK2, - S_SOR2FXSPARK3, - S_SOR2FX2_1, - S_SOR2FX2_2, - S_SOR2FX2_3, - S_SOR2FXI2_1, - S_SOR2FXI2_2, - S_SOR2FXI2_3, - S_SOR2FXI2_4, - S_SOR2FXI2_5, - S_SOR2TELEFADE1, - S_SOR2TELEFADE2, - S_SOR2TELEFADE3, - S_SOR2TELEFADE4, - S_SOR2TELEFADE5, - S_SOR2TELEFADE6, - S_MNTR_LOOK1, - S_MNTR_LOOK2, - S_MNTR_WALK1, - S_MNTR_WALK2, - S_MNTR_WALK3, - S_MNTR_WALK4, - S_MNTR_ATK1_1, - S_MNTR_ATK1_2, - S_MNTR_ATK1_3, - S_MNTR_ATK2_1, - S_MNTR_ATK2_2, - S_MNTR_ATK2_3, - S_MNTR_ATK3_1, - S_MNTR_ATK3_2, - S_MNTR_ATK3_3, - S_MNTR_ATK3_4, - S_MNTR_ATK4_1, - S_MNTR_PAIN1, - S_MNTR_PAIN2, - S_MNTR_DIE1, - S_MNTR_DIE2, - S_MNTR_DIE3, - S_MNTR_DIE4, - S_MNTR_DIE5, - S_MNTR_DIE6, - S_MNTR_DIE7, - S_MNTR_DIE8, - S_MNTR_DIE9, - S_MNTR_DIE10, - S_MNTR_DIE11, - S_MNTR_DIE12, - S_MNTR_DIE13, - S_MNTR_DIE14, - S_MNTR_DIE15, - S_MNTRFX1_1, - S_MNTRFX1_2, - S_MNTRFXI1_1, - S_MNTRFXI1_2, - S_MNTRFXI1_3, - S_MNTRFXI1_4, - S_MNTRFXI1_5, - S_MNTRFXI1_6, - S_MNTRFX2_1, - S_MNTRFXI2_1, - S_MNTRFXI2_2, - S_MNTRFXI2_3, - S_MNTRFXI2_4, - S_MNTRFXI2_5, - S_MNTRFX3_1, - S_MNTRFX3_2, - S_MNTRFX3_3, - S_MNTRFX3_4, - S_MNTRFX3_5, - S_MNTRFX3_6, - S_MNTRFX3_7, - S_MNTRFX3_8, - S_MNTRFX3_9, - S_AKYY1, - S_AKYY2, - S_AKYY3, - S_AKYY4, - S_AKYY5, - S_AKYY6, - S_AKYY7, - S_AKYY8, - S_AKYY9, - S_AKYY10, - S_BKYY1, - S_BKYY2, - S_BKYY3, - S_BKYY4, - S_BKYY5, - S_BKYY6, - S_BKYY7, - S_BKYY8, - S_BKYY9, - S_BKYY10, - S_CKYY1, - S_CKYY2, - S_CKYY3, - S_CKYY4, - S_CKYY5, - S_CKYY6, - S_CKYY7, - S_CKYY8, - S_CKYY9, - S_AMG1, - S_AMG2_1, - S_AMG2_2, - S_AMG2_3, - S_AMM1, - S_AMM2, - S_AMC1, - S_AMC2_1, - S_AMC2_2, - S_AMC2_3, - S_AMS1_1, - S_AMS1_2, - S_AMS2_1, - S_AMS2_2, - S_AMP1_1, - S_AMP1_2, - S_AMP1_3, - S_AMP2_1, - S_AMP2_2, - S_AMP2_3, - S_AMB1_1, - S_AMB1_2, - S_AMB1_3, - S_AMB2_1, - S_AMB2_2, - S_AMB2_3, - S_SND_WIND, - S_SND_WATERFALL, - NUMSTATES -} statenum_t; - - -struct mobj_s; -struct player_s; -struct pspdef_s; - - -typedef struct -{ - spritenum_t sprite; - int frame; - int tics; - void (*action) (struct mobj_s *, struct player_s *, struct pspdef_s *); - statenum_t nextstate; - int misc1, misc2; -} state_t; - -extern state_t states[NUMSTATES]; -extern const char *sprnames[]; - - - -typedef enum -{ - MT_MISC0, - MT_ITEMSHIELD1, - MT_ITEMSHIELD2, - MT_MISC1, - MT_MISC2, - MT_ARTIINVISIBILITY, - MT_MISC3, - MT_ARTIFLY, - MT_ARTIINVULNERABILITY, - MT_ARTITOMEOFPOWER, - MT_ARTIEGG, - MT_EGGFX, - MT_ARTISUPERHEAL, - MT_MISC4, - MT_MISC5, - MT_FIREBOMB, - MT_ARTITELEPORT, - MT_POD, - MT_PODGOO, - MT_PODGENERATOR, - MT_SPLASH, - MT_SPLASHBASE, - MT_LAVASPLASH, - MT_LAVASMOKE, - MT_SLUDGECHUNK, - MT_SLUDGESPLASH, - MT_SKULLHANG70, - MT_SKULLHANG60, - MT_SKULLHANG45, - MT_SKULLHANG35, - MT_CHANDELIER, - MT_SERPTORCH, - MT_SMALLPILLAR, - MT_STALAGMITESMALL, - MT_STALAGMITELARGE, - MT_STALACTITESMALL, - MT_STALACTITELARGE, - MT_MISC6, - MT_BARREL, - MT_MISC7, - MT_MISC8, - MT_MISC9, - MT_MISC10, - MT_MISC11, - MT_KEYGIZMOBLUE, - MT_KEYGIZMOGREEN, - MT_KEYGIZMOYELLOW, - MT_KEYGIZMOFLOAT, - MT_MISC12, - MT_VOLCANOBLAST, - MT_VOLCANOTBLAST, - MT_TELEGLITGEN, - MT_TELEGLITGEN2, - MT_TELEGLITTER, - MT_TELEGLITTER2, - MT_TFOG, - MT_TELEPORTMAN, - MT_STAFFPUFF, - MT_STAFFPUFF2, - MT_BEAKPUFF, - MT_MISC13, - MT_GAUNTLETPUFF1, - MT_GAUNTLETPUFF2, - MT_MISC14, - MT_BLASTERFX1, - MT_BLASTERSMOKE, - MT_RIPPER, - MT_BLASTERPUFF1, - MT_BLASTERPUFF2, - MT_WMACE, - MT_MACEFX1, - MT_MACEFX2, - MT_MACEFX3, - MT_MACEFX4, - MT_WSKULLROD, - MT_HORNRODFX1, - MT_HORNRODFX2, - MT_RAINPLR1, - MT_RAINPLR2, - MT_RAINPLR3, - MT_RAINPLR4, - MT_GOLDWANDFX1, - MT_GOLDWANDFX2, - MT_GOLDWANDPUFF1, - MT_GOLDWANDPUFF2, - MT_WPHOENIXROD, - MT_PHOENIXFX1, - MT_PHOENIXFX_REMOVED, // In Heretic 1.0, but removed. - MT_PHOENIXPUFF, - MT_PHOENIXFX2, - MT_MISC15, - MT_CRBOWFX1, - MT_CRBOWFX2, - MT_CRBOWFX3, - MT_CRBOWFX4, - MT_BLOOD, - MT_BLOODSPLATTER, - MT_PLAYER, - MT_BLOODYSKULL, - MT_CHICPLAYER, - MT_CHICKEN, - MT_FEATHER, - MT_MUMMY, - MT_MUMMYLEADER, - MT_MUMMYGHOST, - MT_MUMMYLEADERGHOST, - MT_MUMMYSOUL, - MT_MUMMYFX1, - MT_BEAST, - MT_BEASTBALL, - MT_BURNBALL, - MT_BURNBALLFB, - MT_PUFFY, - MT_SNAKE, - MT_SNAKEPRO_A, - MT_SNAKEPRO_B, - MT_HEAD, - MT_HEADFX1, - MT_HEADFX2, - MT_HEADFX3, - MT_WHIRLWIND, - MT_CLINK, - MT_WIZARD, - MT_WIZFX1, - MT_IMP, - MT_IMPLEADER, - MT_IMPCHUNK1, - MT_IMPCHUNK2, - MT_IMPBALL, - MT_KNIGHT, - MT_KNIGHTGHOST, - MT_KNIGHTAXE, - MT_REDAXE, - MT_SORCERER1, - MT_SRCRFX1, - MT_SORCERER2, - MT_SOR2FX1, - MT_SOR2FXSPARK, - MT_SOR2FX2, - MT_SOR2TELEFADE, - MT_MINOTAUR, - MT_MNTRFX1, - MT_MNTRFX2, - MT_MNTRFX3, - MT_AKYY, - MT_BKYY, - MT_CKEY, - MT_AMGWNDWIMPY, - MT_AMGWNDHEFTY, - MT_AMMACEWIMPY, - MT_AMMACEHEFTY, - MT_AMCBOWWIMPY, - MT_AMCBOWHEFTY, - MT_AMSKRDWIMPY, - MT_AMSKRDHEFTY, - MT_AMPHRDWIMPY, - MT_AMPHRDHEFTY, - MT_AMBLSRWIMPY, - MT_AMBLSRHEFTY, - MT_SOUNDWIND, - MT_SOUNDWATERFALL, - NUMMOBJTYPES -} mobjtype_t; - -typedef struct -{ - int doomednum; - int spawnstate; - int spawnhealth; - int seestate; - int seesound; - int reactiontime; - int attacksound; - int painstate; - int painchance; - int painsound; - int meleestate; - int missilestate; - int crashstate; - int deathstate; - int xdeathstate; - int deathsound; - int speed; - int radius; - int height; - int mass; - int damage; - int activesound; - int flags; - int flags2; -} mobjinfo_t; - -extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; - -#endif /* #ifndef HERETIC_INFO_H */ - diff --git a/games/NXDoom/src/heretic/m_random.c b/games/NXDoom/src/heretic/m_random.c deleted file mode 100644 index 7d535b84852..00000000000 --- a/games/NXDoom/src/heretic/m_random.c +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include "m_random.h" - -/* -=============== -= -= M_Random -= -= Returns a 0-255 number -= -=============== -*/ - -const unsigned int rndtable[256] = { - 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, - 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36, - 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, - 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, - 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242, - 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0, - 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, - 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113, - 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75, - 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, - 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113, - 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241, - 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, - 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, - 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226, - 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, - 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, - 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136, - 120, 163, 236, 249 -}; - -int rndindex = 0; -int prndindex = 0; - -int P_Random(void) -{ - prndindex = (prndindex + 1) & 0xff; - return rndtable[prndindex]; -} - -int M_Random(void) -{ - rndindex = (rndindex + 1) & 0xff; - return rndtable[rndindex]; -} - -void M_ClearRandom(void) -{ - rndindex = prndindex = 0; -} - -// inspired by the same routine in Eternity, thanks haleyjd -int P_SubRandom (void) -{ - int r = P_Random(); - return r - P_Random(); -} diff --git a/games/NXDoom/src/heretic/m_random.h b/games/NXDoom/src/heretic/m_random.h deleted file mode 100644 index d7ec2d18790..00000000000 --- a/games/NXDoom/src/heretic/m_random.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef HERETIC_M_RANDOM_H -#define HERETIC_M_RANDOM_H - -// Most damage defined using HITDICE -#define HITDICE(a) ((1+(P_Random()&7))*a) - -int M_Random(void); -// returns a number from 0 to 255 -int P_Random(void); -// as M_Random, but used only by the play simulation - -void M_ClearRandom(void); -// fix randoms for demos - -extern int rndindex; - -// Defined version of P_Random() - P_Random() -int P_SubRandom (void); - -#endif // HERETIC_M_RANDOM_H - diff --git a/games/NXDoom/src/heretic/mn_menu.c b/games/NXDoom/src/heretic/mn_menu.c deleted file mode 100644 index 95cb62ce5c1..00000000000 --- a/games/NXDoom/src/heretic/mn_menu.c +++ /dev/null @@ -1,1824 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// MN_menu.c - -#include -#include - -#include "deh_str.h" -#include "doomdef.h" -#include "doomkeys.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_swap.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "r_local.h" -#include "s_sound.h" -#include "v_video.h" -#include "am_map.h" - -// Macros - -#define LEFT_DIR 0 -#define RIGHT_DIR 1 -#define ITEM_HEIGHT 20 -#define SELECTOR_XOFFSET (-28) -#define SELECTOR_YOFFSET (-1) -#define SLOTTEXTLEN 16 -#define ASCII_CURSOR '[' - -// Types - -typedef enum -{ - ITT_EMPTY, - ITT_EFUNC, - ITT_LRFUNC, - ITT_SETMENU, - ITT_INERT -} ItemType_t; - -typedef enum -{ - MENU_MAIN, - MENU_EPISODE, - MENU_SKILL, - MENU_OPTIONS, - MENU_OPTIONS2, - MENU_FILES, - MENU_LOAD, - MENU_SAVE, - MENU_NONE -} MenuType_t; - -typedef struct -{ - ItemType_t type; - const char *text; - boolean(*func) (int option); - int option; - MenuType_t menu; -} MenuItem_t; - -typedef struct -{ - int x; - int y; - void (*drawFunc) (void); - int itemCount; - MenuItem_t *items; - int oldItPos; - MenuType_t prevMenu; -} Menu_t; - -// Private Functions - -static void InitFonts(void); -static void SetMenu(MenuType_t menu); -static boolean SCNetCheck(int option); -static boolean SCQuitGame(int option); -static boolean SCEpisode(int option); -static boolean SCSkill(int option); -static boolean SCMouseSensi(int option); -static boolean SCSfxVolume(int option); -static boolean SCMusicVolume(int option); -static boolean SCScreenSize(int option); -static boolean SCLoadGame(int option); -static boolean SCSaveGame(int option); -static boolean SCMessages(int option); -static boolean SCEndGame(int option); -static boolean SCInfo(int option); -static void DrawMainMenu(void); -static void DrawEpisodeMenu(void); -static void DrawSkillMenu(void); -static void DrawOptionsMenu(void); -static void DrawOptions2Menu(void); -static void DrawFileSlots(Menu_t * menu); -static void DrawFilesMenu(void); -static void MN_DrawInfo(void); -static void DrawLoadMenu(void); -static void DrawSaveMenu(void); -static void DrawSlider(Menu_t * menu, int item, int width, int slot); -void MN_LoadSlotText(void); - - -// Public Data - -boolean MenuActive; -int InfoType; -boolean messageson; - -// Private Data - -static int FontABaseLump; -static int FontBBaseLump; -static int SkullBaseLump; -static Menu_t *CurrentMenu; -static int CurrentItPos; -static int MenuEpisode; -static int MenuTime; -static boolean soundchanged; - -boolean askforquit; -static int typeofask; -static boolean FileMenuKeySteal; -static boolean slottextloaded; -static boolean joypadsave; -static char SlotText[6][SLOTTEXTLEN + 2]; -static char oldSlotText[SLOTTEXTLEN + 2]; -static int SlotStatus[6]; -static int slotptr; -static int currentSlot; -static int quicksave; -static int quickload; - -static MenuItem_t MainItems[] = { - {ITT_EFUNC, "NEW GAME", SCNetCheck, 1, MENU_EPISODE}, - {ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS}, - {ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES}, - {ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE}, - {ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE} -}; - -static Menu_t MainMenu = { - 110, 56, - DrawMainMenu, - 5, MainItems, - 0, - MENU_NONE -}; - -static MenuItem_t EpisodeItems[] = { - {ITT_EFUNC, "CITY OF THE DAMNED", SCEpisode, 1, MENU_NONE}, - {ITT_EFUNC, "HELL'S MAW", SCEpisode, 2, MENU_NONE}, - {ITT_EFUNC, "THE DOME OF D'SPARIL", SCEpisode, 3, MENU_NONE}, - {ITT_EFUNC, "THE OSSUARY", SCEpisode, 4, MENU_NONE}, - {ITT_EFUNC, "THE STAGNANT DEMESNE", SCEpisode, 5, MENU_NONE} -}; - -static Menu_t EpisodeMenu = { - 80, 50, - DrawEpisodeMenu, - 3, EpisodeItems, - 0, - MENU_MAIN -}; - -static MenuItem_t FilesItems[] = { - {ITT_EFUNC, "LOAD GAME", SCNetCheck, 2, MENU_LOAD}, - {ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE} -}; - -static Menu_t FilesMenu = { - 110, 60, - DrawFilesMenu, - 2, FilesItems, - 0, - MENU_MAIN -}; - -static MenuItem_t LoadItems[] = { - {ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE} -}; - -static Menu_t LoadMenu = { - 70, 30, - DrawLoadMenu, - 6, LoadItems, - 0, - MENU_FILES -}; - -static MenuItem_t SaveItems[] = { - {ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE} -}; - -static Menu_t SaveMenu = { - 70, 30, - DrawSaveMenu, - 6, SaveItems, - 0, - MENU_FILES -}; - -static MenuItem_t SkillItems[] = { - {ITT_EFUNC, "THOU NEEDETH A WET-NURSE", SCSkill, sk_baby, MENU_NONE}, - {ITT_EFUNC, "YELLOWBELLIES-R-US", SCSkill, sk_easy, MENU_NONE}, - {ITT_EFUNC, "BRINGEST THEM ONETH", SCSkill, sk_medium, MENU_NONE}, - {ITT_EFUNC, "THOU ART A SMITE-MEISTER", SCSkill, sk_hard, MENU_NONE}, - {ITT_EFUNC, "BLACK PLAGUE POSSESSES THEE", - SCSkill, sk_nightmare, MENU_NONE} -}; - -static Menu_t SkillMenu = { - 38, 30, - DrawSkillMenu, - 5, SkillItems, - 2, - MENU_EPISODE -}; - -static MenuItem_t OptionsItems[] = { - {ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE}, - {ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE}, - {ITT_LRFUNC, "MOUSE SENSITIVITY", SCMouseSensi, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2} -}; - -static Menu_t OptionsMenu = { - 88, 30, - DrawOptionsMenu, - 5, OptionsItems, - 0, - MENU_MAIN -}; - -static MenuItem_t Options2Items[] = { - {ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE} -}; - -static Menu_t Options2Menu = { - 90, 20, - DrawOptions2Menu, - 6, Options2Items, - 0, - MENU_OPTIONS -}; - -static Menu_t *Menus[] = { - &MainMenu, - &EpisodeMenu, - &SkillMenu, - &OptionsMenu, - &Options2Menu, - &FilesMenu, - &LoadMenu, - &SaveMenu -}; - -//--------------------------------------------------------------------------- -// -// PROC MN_Init -// -//--------------------------------------------------------------------------- - -void MN_Init(void) -{ - InitFonts(); - MenuActive = false; - messageson = true; - SkullBaseLump = W_GetNumForName(DEH_String("M_SKL00")); - - if (gamemode == retail) - { // Add episodes 4 and 5 to the menu - EpisodeMenu.itemCount = 5; - EpisodeMenu.y -= ITEM_HEIGHT; - } -} - -//--------------------------------------------------------------------------- -// -// PROC InitFonts -// -//--------------------------------------------------------------------------- - -static void InitFonts(void) -{ - FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1; - FontBBaseLump = W_GetNumForName(DEH_String("FONTB_S")) + 1; -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DrTextA -// -// Draw text using font A. -// -//--------------------------------------------------------------------------- - -void MN_DrTextA(const char *text, int x, int y) -{ - char c; - patch_t *p; - - while ((c = *text++) != 0) - { - if (c < 33) - { - x += 5; - } - else - { - p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - V_DrawPatch(x, y, p); - x += SHORT(p->width) - 1; - } - } -} - -//--------------------------------------------------------------------------- -// -// FUNC MN_TextAWidth -// -// Returns the pixel width of a string using font A. -// -//--------------------------------------------------------------------------- - -int MN_TextAWidth(const char *text) -{ - char c; - int width; - patch_t *p; - - width = 0; - while ((c = *text++) != 0) - { - if (c < 33) - { - width += 5; - } - else - { - p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - width += SHORT(p->width) - 1; - } - } - return (width); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DrTextB -// -// Draw text using font B. -// -//--------------------------------------------------------------------------- - -void MN_DrTextB(const char *text, int x, int y) -{ - char c; - patch_t *p; - - while ((c = *text++) != 0) - { - if (c < 33) - { - x += 8; - } - else - { - p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); - V_DrawPatch(x, y, p); - x += SHORT(p->width) - 1; - } - } -} - -//--------------------------------------------------------------------------- -// -// FUNC MN_TextBWidth -// -// Returns the pixel width of a string using font B. -// -//--------------------------------------------------------------------------- - -int MN_TextBWidth(const char *text) -{ - char c; - int width; - patch_t *p; - - width = 0; - while ((c = *text++) != 0) - { - if (c < 33) - { - width += 5; - } - else - { - p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); - width += SHORT(p->width) - 1; - } - } - return (width); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_Ticker -// -//--------------------------------------------------------------------------- - -void MN_Ticker(void) -{ - if (MenuActive == false) - { - return; - } - MenuTime++; -} - -//--------------------------------------------------------------------------- -// -// PROC MN_Drawer -// -//--------------------------------------------------------------------------- - -const char *QuitEndMsg[] = { - "ARE YOU SURE YOU WANT TO QUIT?", - "ARE YOU SURE YOU WANT TO END THE GAME?", - "DO YOU WANT TO QUICKSAVE THE GAME NAMED", - "DO YOU WANT TO QUICKLOAD THE GAME NAMED" -}; - -void MN_Drawer(void) -{ - int i; - int x; - int y; - MenuItem_t *item; - const char *message; - const char *selName; - - if (MenuActive == false) - { - if (askforquit) - { - message = DEH_String(QuitEndMsg[typeofask - 1]); - - MN_DrTextA(message, 160 - MN_TextAWidth(message) / 2, 80); - if (typeofask == 3) - { - MN_DrTextA(SlotText[quicksave - 1], 160 - - MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); - MN_DrTextA(DEH_String("?"), 160 + - MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); - } - if (typeofask == 4) - { - MN_DrTextA(SlotText[quickload - 1], 160 - - MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); - MN_DrTextA(DEH_String("?"), 160 + - MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); - } - UpdateState |= I_FULLSCRN; - } - return; - } - else - { - UpdateState |= I_FULLSCRN; - if (InfoType) - { - MN_DrawInfo(); - return; - } - if (screenblocks < 10) - { - BorderNeedRefresh = true; - } - if (CurrentMenu->drawFunc != NULL) - { - CurrentMenu->drawFunc(); - } - x = CurrentMenu->x; - y = CurrentMenu->y; - item = CurrentMenu->items; - for (i = 0; i < CurrentMenu->itemCount; i++) - { - if (item->type != ITT_EMPTY && item->text) - { - MN_DrTextB(DEH_String(item->text), x, y); - } - y += ITEM_HEIGHT; - item++; - } - y = CurrentMenu->y + (CurrentItPos * ITEM_HEIGHT) + SELECTOR_YOFFSET; - selName = DEH_String(MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2"); - V_DrawPatch(x + SELECTOR_XOFFSET, y, - W_CacheLumpName(selName, PU_CACHE)); - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawMainMenu -// -//--------------------------------------------------------------------------- - -static void DrawMainMenu(void) -{ - int frame; - - frame = (MenuTime / 3) % 18; - V_DrawPatch(88, 0, W_CacheLumpName(DEH_String("M_HTIC"), PU_CACHE)); - V_DrawPatch(40, 10, W_CacheLumpNum(SkullBaseLump + (17 - frame), - PU_CACHE)); - V_DrawPatch(232, 10, W_CacheLumpNum(SkullBaseLump + frame, PU_CACHE)); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawEpisodeMenu -// -//--------------------------------------------------------------------------- - -static void DrawEpisodeMenu(void) -{ -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSkillMenu -// -//--------------------------------------------------------------------------- - -static void DrawSkillMenu(void) -{ -} - -//--------------------------------------------------------------------------- -// -// PROC DrawFilesMenu -// -//--------------------------------------------------------------------------- - -static void DrawFilesMenu(void) -{ -// clear out the quicksave/quickload stuff - quicksave = 0; - quickload = 0; - players[consoleplayer].message = NULL; - players[consoleplayer].messageTics = 1; -} - -//--------------------------------------------------------------------------- -// -// PROC DrawLoadMenu -// -//--------------------------------------------------------------------------- - -static void DrawLoadMenu(void) -{ - const char *title; - - title = DEH_String("LOAD GAME"); - - MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10); - if (!slottextloaded) - { - MN_LoadSlotText(); - } - DrawFileSlots(&LoadMenu); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSaveMenu -// -//--------------------------------------------------------------------------- - -static void DrawSaveMenu(void) -{ - const char *title; - - title = DEH_String("SAVE GAME"); - - MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10); - if (!slottextloaded) - { - MN_LoadSlotText(); - } - DrawFileSlots(&SaveMenu); -} - -//=========================================================================== -// -// MN_LoadSlotText -// -// Loads in the text message for each slot -//=========================================================================== - -void MN_LoadSlotText(void) -{ - FILE *fp; - int i; - char *filename; - - for (i = 0; i < 6; i++) - { - int retval; - filename = SV_Filename(i); - fp = M_fopen(filename, "rb+"); - free(filename); - - if (!fp) - { - SlotText[i][0] = 0; // empty the string - SlotStatus[i] = 0; - continue; - } - retval = fread(&SlotText[i], 1, SLOTTEXTLEN, fp); - fclose(fp); - SlotStatus[i] = retval == SLOTTEXTLEN; - } - slottextloaded = true; -} - -//--------------------------------------------------------------------------- -// -// PROC DrawFileSlots -// -//--------------------------------------------------------------------------- - -static void DrawFileSlots(Menu_t * menu) -{ - int i; - int x; - int y; - - x = menu->x; - y = menu->y; - for (i = 0; i < 6; i++) - { - V_DrawPatch(x, y, W_CacheLumpName(DEH_String("M_FSLOT"), PU_CACHE)); - if (SlotStatus[i]) - { - MN_DrTextA(SlotText[i], x + 5, y + 5); - } - y += ITEM_HEIGHT; - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawOptionsMenu -// -//--------------------------------------------------------------------------- - -static void DrawOptionsMenu(void) -{ - if (messageson) - { - MN_DrTextB(DEH_String("ON"), 196, 50); - } - else - { - MN_DrTextB(DEH_String("OFF"), 196, 50); - } - DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawOptions2Menu -// -//--------------------------------------------------------------------------- - -static void DrawOptions2Menu(void) -{ - DrawSlider(&Options2Menu, 1, 9, screenblocks - 3); - DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume); - DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume); -} - -//--------------------------------------------------------------------------- -// -// PROC SCNetCheck -// -//--------------------------------------------------------------------------- - -static boolean SCNetCheck(int option) -{ - if (!netgame) - { // okay to go into the menu - return true; - } - switch (option) - { - case 1: - P_SetMessage(&players[consoleplayer], - "YOU CAN'T START A NEW GAME IN NETPLAY!", true); - break; - case 2: - P_SetMessage(&players[consoleplayer], - "YOU CAN'T LOAD A GAME IN NETPLAY!", true); - break; - default: - break; - } - MenuActive = false; - return false; -} - -//--------------------------------------------------------------------------- -// -// PROC SCQuitGame -// -//--------------------------------------------------------------------------- - -static boolean SCQuitGame(int option) -{ - MenuActive = false; - askforquit = true; - typeofask = 1; //quit game - if (!netgame && !demoplayback) - { - paused = true; - } - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCEndGame -// -//--------------------------------------------------------------------------- - -static boolean SCEndGame(int option) -{ - if (demoplayback || netgame) - { - return false; - } - MenuActive = false; - askforquit = true; - typeofask = 2; //endgame - if (!netgame && !demoplayback) - { - paused = true; - } - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCMessages -// -//--------------------------------------------------------------------------- - -static boolean SCMessages(int option) -{ - messageson ^= 1; - if (messageson) - { - P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES ON"), true); - } - else - { - P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES OFF"), true); - } - S_StartSound(NULL, sfx_chat); - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCLoadGame -// -//--------------------------------------------------------------------------- - -static boolean SCLoadGame(int option) -{ - char *filename; - - if (!SlotStatus[option]) - { // slot's empty...don't try and load - return false; - } - - filename = SV_Filename(option); - G_LoadGame(filename); - free(filename); - - MN_DeactivateMenu(); - BorderNeedRefresh = true; - if (quickload == -1) - { - quickload = option + 1; - players[consoleplayer].message = NULL; - players[consoleplayer].messageTics = 1; - } - return true; -} - -// -// Generate a default save slot name when the user saves to -// an empty slot via the joypad. -// -static void SetDefaultSaveName(int slot) -{ - // map from IWAD or PWAD? - if (W_IsIWADLump(maplumpinfo) && strcmp(savegamedir, "")) - { - M_snprintf(SlotText[slot], SLOTTEXTLEN, - "%s", maplumpinfo->name); - } - else - { - char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo)); - char *ext = strrchr(wadname, '.'); - - if (ext != NULL) - { - *ext = '\0'; - } - - M_snprintf(SlotText[slot], SLOTTEXTLEN, - "%s (%s)", maplumpinfo->name, - wadname); - free(wadname); - } - M_ForceUppercase(SlotText[slot]); - joypadsave = false; -} - -//--------------------------------------------------------------------------- -// -// PROC SCSaveGame -// -//--------------------------------------------------------------------------- - -static boolean SCSaveGame(int option) -{ - char *ptr; - - if (!FileMenuKeySteal) - { - int x, y; - - FileMenuKeySteal = true; - // We need to activate the text input interface to type the save - // game name: - x = SaveMenu.x + 1; - y = SaveMenu.y + 1 + option * ITEM_HEIGHT; - I_StartTextInput(x, y, x + 190, y + ITEM_HEIGHT - 2); - - M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText)); - ptr = SlotText[option]; - - if (!strcmp(ptr, "") && joypadsave) - { - SetDefaultSaveName(option); - } - - while (*ptr) - { - ptr++; - } - *ptr = '['; - *(ptr + 1) = 0; - SlotStatus[option]++; - currentSlot = option; - slotptr = ptr - SlotText[option]; - return false; - } - else - { - G_SaveGame(option, SlotText[option]); - FileMenuKeySteal = false; - I_StopTextInput(); - MN_DeactivateMenu(); - } - BorderNeedRefresh = true; - if (quicksave == -1) - { - quicksave = option + 1; - players[consoleplayer].message = NULL; - players[consoleplayer].messageTics = 1; - } - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCEpisode -// -//--------------------------------------------------------------------------- - -static boolean SCEpisode(int option) -{ - if (gamemode == shareware && option > 1) - { - P_SetMessage(&players[consoleplayer], - "ONLY AVAILABLE IN THE REGISTERED VERSION", true); - } - else - { - MenuEpisode = option; - SetMenu(MENU_SKILL); - } - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCSkill -// -//--------------------------------------------------------------------------- - -static boolean SCSkill(int option) -{ - G_DeferedInitNew(option, MenuEpisode, 1); - MN_DeactivateMenu(); - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCMouseSensi -// -//--------------------------------------------------------------------------- - -static boolean SCMouseSensi(int option) -{ - if (option == RIGHT_DIR) - { - if (mouseSensitivity < 9) - { - mouseSensitivity++; - } - } - else if (mouseSensitivity) - { - mouseSensitivity--; - } - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCSfxVolume -// -//--------------------------------------------------------------------------- - -static boolean SCSfxVolume(int option) -{ - if (option == RIGHT_DIR) - { - if (snd_MaxVolume < 15) - { - snd_MaxVolume++; - } - } - else if (snd_MaxVolume) - { - snd_MaxVolume--; - } - S_SetMaxVolume(false); // don't recalc the sound curve, yet - soundchanged = true; // we'll set it when we leave the menu - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCMusicVolume -// -//--------------------------------------------------------------------------- - -static boolean SCMusicVolume(int option) -{ - if (option == RIGHT_DIR) - { - if (snd_MusicVolume < 15) - { - snd_MusicVolume++; - } - } - else if (snd_MusicVolume) - { - snd_MusicVolume--; - } - S_SetMusicVolume(); - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCScreenSize -// -//--------------------------------------------------------------------------- - -static boolean SCScreenSize(int option) -{ - if (option == RIGHT_DIR) - { - if (screenblocks < 11) - { - screenblocks++; - } - } - else if (screenblocks > 3) - { - screenblocks--; - } - R_SetViewSize(screenblocks, detailLevel); - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC SCInfo -// -//--------------------------------------------------------------------------- - -static boolean SCInfo(int option) -{ - InfoType = 1; - S_StartSound(NULL, sfx_dorcls); - if (!netgame && !demoplayback) - { - paused = true; - } - return true; -} - -//--------------------------------------------------------------------------- -// -// FUNC MN_Responder -// -//--------------------------------------------------------------------------- - -boolean MN_Responder(event_t * event) -{ - int charTyped; - int key; - int i; - MenuItem_t *item; - char *textBuffer; - int dir; - - // In testcontrols mode, none of the function keys should do anything - // - the only key is escape to quit. - - if (testcontrols) - { - if (event->type == ev_quit - || (event->type == ev_keydown - && (event->data1 == key_menu_activate - || event->data1 == key_menu_quit))) - { - I_Quit(); - return true; - } - - return false; - } - - // "close" button pressed on window? - if (event->type == ev_quit) - { - // First click on close = bring up quit confirm message. - // Second click = confirm quit. - - if (!MenuActive && askforquit && typeofask == 1) - { - G_CheckDemoStatus(); - I_Quit(); - } - else - { - SCQuitGame(0); - S_StartSound(NULL, sfx_chat); - } - return true; - } - - charTyped = 0; - key = -1; - - if (event->type == ev_joystick) - { - // Simulate key presses from joystick events to interact with the menu. - - if (MenuActive) - { - if (JOY_GET_DPAD(event->data6) != JOY_DIR_NONE) - { - dir = JOY_GET_DPAD(event->data6); - } - else if (JOY_GET_LSTICK(event->data6) != JOY_DIR_NONE) - { - dir = JOY_GET_LSTICK(event->data6); - } - else - { - dir = JOY_GET_RSTICK(event->data6); - } - - if (dir & JOY_DIR_UP) - { - key = key_menu_up; - joywait = I_GetTime() + 5; - } - else if (dir & JOY_DIR_DOWN) - { - key = key_menu_down; - joywait = I_GetTime() + 5; - } - if (dir & JOY_DIR_LEFT) - { - key = key_menu_left; - joywait = I_GetTime() + 5; - } - else if (dir & JOY_DIR_RIGHT) - { - key = key_menu_right; - joywait = I_GetTime() + 5; - } - -#define JOY_BUTTON_MAPPED(x) ((x) >= 0) -#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (event->data1 & (1 << (x))) != 0) - - if (JOY_BUTTON_PRESSED(joybfire)) - { - // Simulate pressing "Enter" when we are supplying a save slot name - if (FileMenuKeySteal) - { - key = KEY_ENTER; - } - else - { - // if selecting a save slot via joypad, set a flag - if (CurrentMenu == &SaveMenu) - { - joypadsave = true; - } - key = key_menu_forward; - } - joywait = I_GetTime() + 5; - } - if (JOY_BUTTON_PRESSED(joybuse)) - { - // If user was entering a save name, back out - if (FileMenuKeySteal) - { - key = KEY_ESCAPE; - } - else - { - key = key_menu_back; - } - joywait = I_GetTime() + 5; - } - } - else if (askforquit) - { - if (JOY_BUTTON_PRESSED(joybfire)) - { - // Simulate a 'Y' keypress - key = key_menu_confirm; - joywait = I_GetTime() + 5; - } - if (JOY_BUTTON_PRESSED(joybuse)) - { - // Simulate a 'N' keypress - key = key_menu_abort; - joywait = I_GetTime() + 5; - } - } - if (JOY_BUTTON_PRESSED(joybmenu)) - { - MN_ActivateMenu(); - joywait = I_GetTime() + 5; - return true; - } - } - - if (event->type != ev_keydown && key == -1) - { - return false; - } - - if (event->type == ev_keydown) - { - key = event->data1; - charTyped = event->data2; - } - - if (InfoType) - { - if (gamemode == shareware) - { - InfoType = (InfoType + 1) % 5; - } - else - { - InfoType = (InfoType + 1) % 4; - } - if (key == KEY_ESCAPE) - { - InfoType = 0; - } - if (!InfoType) - { - paused = false; - MN_DeactivateMenu(); - SB_state = -1; //refresh the statbar - BorderNeedRefresh = true; - } - S_StartSound(NULL, sfx_dorcls); - return (true); //make the info screen eat the keypress - } - - if ((ravpic && key == KEY_F1) || - (key != 0 && key == key_menu_screenshot)) - { - G_ScreenShot(); - return (true); - } - - if (askforquit) - { - if (key == key_menu_confirm) - { - switch (typeofask) - { - case 1: - G_CheckDemoStatus(); - I_Quit(); - return false; - - case 2: - players[consoleplayer].messageTics = 0; - //set the msg to be cleared - players[consoleplayer].message = NULL; - paused = false; - I_SetPalette(W_CacheLumpName - ("PLAYPAL", PU_CACHE)); - D_StartTitle(); // go to intro/demo mode. - break; - - case 3: - P_SetMessage(&players[consoleplayer], - "QUICKSAVING....", false); - FileMenuKeySteal = true; - SCSaveGame(quicksave - 1); - BorderNeedRefresh = true; - break; - - case 4: - P_SetMessage(&players[consoleplayer], - "QUICKLOADING....", false); - SCLoadGame(quickload - 1); - BorderNeedRefresh = true; - break; - - default: - break; - } - - askforquit = false; - typeofask = 0; - - return true; - } - else if (key == key_menu_abort || key == KEY_ESCAPE) - { - players[consoleplayer].messageTics = 1; //set the msg to be cleared - askforquit = false; - typeofask = 0; - paused = false; - UpdateState |= I_FULLSCRN; - BorderNeedRefresh = true; - return true; - } - - return false; // don't let the keys filter thru - } - - if (!MenuActive && !chatmodeon) - { - if (key == key_menu_decscreen) - { - if (automapactive) - { // Don't screen size in automap - return (false); - } - SCScreenSize(LEFT_DIR); - S_StartSound(NULL, sfx_keyup); - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - return (true); - } - else if (key == key_menu_incscreen) - { - if (automapactive) - { // Don't screen size in automap - return (false); - } - SCScreenSize(RIGHT_DIR); - S_StartSound(NULL, sfx_keyup); - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - return (true); - } - else if (key == key_menu_help) // F1 - { - SCInfo(0); // start up info screens - MenuActive = true; - return (true); - } - else if (key == key_menu_save) // F2 (save game) - { - if (gamestate == GS_LEVEL && !demoplayback) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &SaveMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_dorcls); - slottextloaded = false; //reload the slot text, when needed - } - return true; - } - else if (key == key_menu_load) // F3 (load game) - { - if (SCNetCheck(2)) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &LoadMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_dorcls); - slottextloaded = false; //reload the slot text, when needed - } - return true; - } - else if (key == key_menu_volume) // F4 (volume) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &Options2Menu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_dorcls); - slottextloaded = false; //reload the slot text, when needed - return true; - } - else if (key == key_menu_detail) // F5 (detail) - { - // F5 isn't used in Heretic. (detail level) - return true; - } - else if (key == key_menu_qsave) // F6 (quicksave) - { - if (gamestate == GS_LEVEL && !demoplayback) - { - if (!quicksave || quicksave == -1) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &SaveMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_dorcls); - slottextloaded = false; //reload the slot text, when needed - quicksave = -1; - P_SetMessage(&players[consoleplayer], - "CHOOSE A QUICKSAVE SLOT", true); - } - else - { - askforquit = true; - typeofask = 3; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_chat); - } - } - return true; - } - else if (key == key_menu_endgame) // F7 (end game) - { - if (gamestate == GS_LEVEL && !demoplayback) - { - S_StartSound(NULL, sfx_chat); - SCEndGame(0); - } - return true; - } - else if (key == key_menu_messages) // F8 (toggle messages) - { - SCMessages(0); - return true; - } - else if (key == key_menu_qload) // F9 (quickload) - { - if (!quickload || quickload == -1) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &LoadMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_dorcls); - slottextloaded = false; //reload the slot text, when needed - quickload = -1; - P_SetMessage(&players[consoleplayer], - "CHOOSE A QUICKLOAD SLOT", true); - } - else - { - askforquit = true; - if (!netgame && !demoplayback) - { - paused = true; - } - typeofask = 4; - S_StartSound(NULL, sfx_chat); - } - return true; - } - else if (key == key_menu_quit) // F10 (quit) - { - if (gamestate == GS_LEVEL) - { - SCQuitGame(0); - S_StartSound(NULL, sfx_chat); - } - return true; - } - else if (key == key_menu_gamma) // F11 (gamma correction) - { - usegamma++; - if (usegamma > 4) - { - usegamma = 0; - } - I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE)); - return true; - } - - } - - if (!MenuActive) - { - if (key == key_menu_activate || gamestate == GS_DEMOSCREEN || demoplayback) - { - MN_ActivateMenu(); - return (true); - } - return (false); - } - if (!FileMenuKeySteal) - { - item = &CurrentMenu->items[CurrentItPos]; - - if (key == key_menu_down) // Next menu item - { - do - { - if (CurrentItPos + 1 > CurrentMenu->itemCount - 1) - { - CurrentItPos = 0; - } - else - { - CurrentItPos++; - } - } - while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); - S_StartSound(NULL, sfx_switch); - return (true); - } - else if (key == key_menu_up) // Previous menu item - { - do - { - if (CurrentItPos == 0) - { - CurrentItPos = CurrentMenu->itemCount - 1; - } - else - { - CurrentItPos--; - } - } - while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); - S_StartSound(NULL, sfx_switch); - return (true); - } - else if (key == key_menu_left) // Slider left - { - if (item->type == ITT_LRFUNC && item->func != NULL) - { - item->func(LEFT_DIR); - S_StartSound(NULL, sfx_keyup); - } - return (true); - } - else if (key == key_menu_right) // Slider right - { - if (item->type == ITT_LRFUNC && item->func != NULL) - { - item->func(RIGHT_DIR); - S_StartSound(NULL, sfx_keyup); - } - return (true); - } - else if (key == key_menu_forward) // Activate item (enter) - { - if (item->type == ITT_SETMENU) - { - SetMenu(item->menu); - } - else if (item->func != NULL) - { - CurrentMenu->oldItPos = CurrentItPos; - if (item->type == ITT_LRFUNC) - { - item->func(RIGHT_DIR); - } - else if (item->type == ITT_EFUNC) - { - if (item->func(item->option)) - { - if (item->menu != MENU_NONE) - { - SetMenu(item->menu); - } - } - } - } - S_StartSound(NULL, sfx_dorcls); - return (true); - } - else if (key == key_menu_activate) // Toggle menu - { - MN_DeactivateMenu(); - return (true); - } - else if (key == key_menu_back) // Go back to previous menu - { - S_StartSound(NULL, sfx_switch); - if (CurrentMenu->prevMenu == MENU_NONE) - { - MN_DeactivateMenu(); - } - else - { - SetMenu(CurrentMenu->prevMenu); - } - return (true); - } - else if (charTyped != 0) - { - // Jump to menu item based on first letter: - - for (i = 0; i < CurrentMenu->itemCount; i++) - { - if (CurrentMenu->items[i].text) - { - if (toupper(charTyped) - == toupper(DEH_String(CurrentMenu->items[i].text)[0])) - { - CurrentItPos = i; - return (true); - } - } - } - } - - return (false); - } - else - { - // Editing file names - // When typing a savegame name, we use the fully shifted and - // translated input value from event->data3. - charTyped = event->data3; - - textBuffer = &SlotText[currentSlot][slotptr]; - if (key == KEY_BACKSPACE) - { - if (slotptr) - { - *textBuffer = 0; - slotptr--; - textBuffer = &SlotText[currentSlot][slotptr]; - *textBuffer = ASCII_CURSOR; - } - return (true); - } - if (key == KEY_ESCAPE) - { - memset(SlotText[currentSlot], 0, SLOTTEXTLEN + 2); - M_StringCopy(SlotText[currentSlot], oldSlotText, - sizeof(SlotText[currentSlot])); - SlotStatus[currentSlot]--; - MN_DeactivateMenu(); - return (true); - } - if (key == KEY_ENTER) - { - SlotText[currentSlot][slotptr] = 0; // clear the cursor - item = &CurrentMenu->items[CurrentItPos]; - CurrentMenu->oldItPos = CurrentItPos; - if (item->type == ITT_EFUNC) - { - item->func(item->option); - if (item->menu != MENU_NONE) - { - SetMenu(item->menu); - } - } - return (true); - } - if (slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE) - { - if (isalpha(charTyped)) - { - *textBuffer++ = toupper(charTyped); - *textBuffer = ASCII_CURSOR; - slotptr++; - return (true); - } - if (isdigit(charTyped) || charTyped == ' ' - || charTyped == ',' || charTyped == '.' || charTyped == '-' - || charTyped == '!') - { - *textBuffer++ = charTyped; - *textBuffer = ASCII_CURSOR; - slotptr++; - return (true); - } - } - return (true); - } - return (false); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_ActivateMenu -// -//--------------------------------------------------------------------------- - -void MN_ActivateMenu(void) -{ - if (MenuActive) - { - return; - } - if (paused) - { - S_ResumeSound(); - } - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &MainMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, sfx_dorcls); - slottextloaded = false; //reload the slot text, when needed -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DeactivateMenu -// -//--------------------------------------------------------------------------- - -void MN_DeactivateMenu(void) -{ - if (CurrentMenu != NULL) - { - CurrentMenu->oldItPos = CurrentItPos; - } - MenuActive = false; - if (FileMenuKeySteal) - { - I_StopTextInput(); - } - if (!netgame) - { - paused = false; - } - S_StartSound(NULL, sfx_dorcls); - if (soundchanged) - { - S_SetMaxVolume(true); //recalc the sound curve - soundchanged = false; - } - players[consoleplayer].message = NULL; - players[consoleplayer].messageTics = 1; -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DrawInfo -// -//--------------------------------------------------------------------------- - -void MN_DrawInfo(void) -{ - I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); - V_DrawRawScreen(W_CacheLumpNum(W_GetNumForName("TITLE") + InfoType, - PU_CACHE)); -// V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType, -// PU_CACHE)); -} - - -//--------------------------------------------------------------------------- -// -// PROC SetMenu -// -//--------------------------------------------------------------------------- - -static void SetMenu(MenuType_t menu) -{ - CurrentMenu->oldItPos = CurrentItPos; - CurrentMenu = Menus[menu]; - CurrentItPos = CurrentMenu->oldItPos; -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSlider -// -//--------------------------------------------------------------------------- - -static void DrawSlider(Menu_t * menu, int item, int width, int slot) -{ - int x; - int y; - int x2; - int count; - - x = menu->x + 24; - y = menu->y + 2 + (item * ITEM_HEIGHT); - V_DrawPatch(x - 32, y, W_CacheLumpName(DEH_String("M_SLDLT"), PU_CACHE)); - for (x2 = x, count = width; count--; x2 += 8) - { - V_DrawPatch(x2, y, W_CacheLumpName(DEH_String(count & 1 ? "M_SLDMD1" - : "M_SLDMD2"), PU_CACHE)); - } - V_DrawPatch(x2, y, W_CacheLumpName(DEH_String("M_SLDRT"), PU_CACHE)); - V_DrawPatch(x + 4 + slot * 8, y + 7, - W_CacheLumpName(DEH_String("M_SLDKB"), PU_CACHE)); -} diff --git a/games/NXDoom/src/heretic/p_action.h b/games/NXDoom/src/heretic/p_action.h deleted file mode 100644 index 8bb87071ca2..00000000000 --- a/games/NXDoom/src/heretic/p_action.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// External definitions for action pointer functions. -// - -#ifndef HERETIC_P_ACTION_H -#define HERETIC_P_ACTION_H - -void A_FreeTargMobj(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_RestoreSpecialThing1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_RestoreSpecialThing2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_HideThing(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_UnHideThing(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_RestoreArtifact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Scream(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Explode(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_PodPain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_RemovePod(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MakePod(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_InitKeyGizmo(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_VolcanoSet(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_VolcanoBlast(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BeastPuff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_VolcBallImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SpawnTeleGlitter(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SpawnTeleGlitter2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_AccTeleGlitter(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Light0(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_WeaponReady(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Lower(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Raise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_StaffAttackPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ReFire(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_StaffAttackPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BeakReady(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BeakRaise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BeakAttackPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BeakAttackPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_GauntletAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireBlasterPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireBlasterPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SpawnRippers(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireMacePL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireMacePL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MacePL1Check(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MaceBallImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MaceBallImpact2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_DeathBallImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireSkullRodPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireSkullRodPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SkullRodPL2Seek(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_AddPlayerRain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_HideInCeiling(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SkullRodStorm(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_RainImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireGoldWandPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireGoldWandPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FirePhoenixPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_InitPhoenixPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FirePhoenixPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ShutdownPhoenixPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_PhoenixPuff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_RemovedPhoenixFunc(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FlameEnd(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FloatPuff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireCrossbowPL1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FireCrossbowPL2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BoltSpark(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Pain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_NoBlocking(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_AddPlayerCorpse(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SkullPop(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FlameSnd(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_CheckBurnGone(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_CheckSkullFloor(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_CheckSkullDone(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Feathers(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ChicLook(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ChicChase(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ChicPain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_FaceTarget(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ChicAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Look(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Chase(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MummyAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MummyAttack2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MummySoul(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ContMobjSound(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MummyFX1Seek(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BeastAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SnakeAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SnakeAttack2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_HeadAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BossDeath(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_HeadIceImpact(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_HeadFireGrow(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_WhirlwindSeek(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ClinkAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_WizAtk1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_WizAtk2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_WizAtk3(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_GhostOff(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpMeAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpMsAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpMsAttack2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpDeath(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpXDeath1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpXDeath2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ImpExplode(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_KnightAttack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_DripBlood(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Sor1Chase(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Sor1Pain(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Srcr1Attack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorZap(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorcererRise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorRise(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorSightSnd(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Srcr2Decide(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Srcr2Attack(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Sor2DthInit(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorDSph(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_Sor2DthLoop(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorDExp(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_SorDBon(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_BlueSpark(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_GenWizard(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MinotaurAtk1(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MinotaurDecide(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MinotaurAtk2(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MinotaurAtk3(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MinotaurCharge(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_MntrFloorFire(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); -void A_ESound(struct mobj_s *actor, struct player_s *player, struct pspdef_s *psp); - -#endif /* #ifndef HERETIC_P_ACTION_H */ - diff --git a/games/NXDoom/src/heretic/p_ceilng.c b/games/NXDoom/src/heretic/p_ceilng.c deleted file mode 100644 index c37d3973275..00000000000 --- a/games/NXDoom/src/heretic/p_ceilng.c +++ /dev/null @@ -1,256 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include "doomdef.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -//================================================================== -//================================================================== -// -// CEILINGS -// -//================================================================== -//================================================================== - -ceiling_t *activeceilings[MAXCEILINGS]; - -//================================================================== -// -// T_MoveCeiling -// -//================================================================== -void T_MoveCeiling(thinker_t *thinker) -{ - ceiling_t *ceiling = (ceiling_t *) thinker; - result_e res; - - switch (ceiling->direction) - { - case 0: // IN STASIS - break; - case 1: // UP - res = T_MovePlane(ceiling->sector, ceiling->speed, - ceiling->topheight, false, 1, - ceiling->direction); - if (!(leveltime & 7)) - S_StartSound(&ceiling->sector->soundorg, - sfx_dormov); - if (res == pastdest) - switch (ceiling->type) - { - case raiseToHighest: - P_RemoveActiveCeiling(ceiling); - break; - case fastCrushAndRaise: - case crushAndRaise: - ceiling->direction = -1; - break; - default: - break; - } - break; - case -1: // DOWN - res = T_MovePlane(ceiling->sector, ceiling->speed, - ceiling->bottomheight, ceiling->crush, 1, - ceiling->direction); - if (!(leveltime & 7)) - S_StartSound(&ceiling->sector->soundorg, - sfx_dormov); - if (res == pastdest) - switch (ceiling->type) - { - case crushAndRaise: - ceiling->speed = CEILSPEED; - case fastCrushAndRaise: - ceiling->direction = 1; - break; - case lowerAndCrush: - case lowerToFloor: - P_RemoveActiveCeiling(ceiling); - break; - default: - break; - } - else if (res == crushed) - switch (ceiling->type) - { - case crushAndRaise: - case lowerAndCrush: - ceiling->speed = CEILSPEED / 8; - break; - default: - break; - } - break; - } -} - -//================================================================== -// -// EV_DoCeiling -// Move a ceiling up/down and all around! -// -//================================================================== -int EV_DoCeiling(line_t * line, ceiling_e type) -{ - int secnum, rtn; - sector_t *sec; - ceiling_t *ceiling; - - secnum = -1; - rtn = 0; - - // - // Reactivate in-stasis ceilings...for certain types. - // - switch (type) - { - case fastCrushAndRaise: - case crushAndRaise: - P_ActivateInStasisCeiling(line); - default: - break; - } - - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - // - // new door thinker - // - rtn = 1; - ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0); - P_AddThinker(&ceiling->thinker); - sec->specialdata = ceiling; - ceiling->thinker.function = T_MoveCeiling; - ceiling->sector = sec; - ceiling->crush = false; - switch (type) - { - case fastCrushAndRaise: - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT); - ceiling->direction = -1; - ceiling->speed = CEILSPEED * 2; - break; - case crushAndRaise: - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - case lowerAndCrush: - case lowerToFloor: - ceiling->bottomheight = sec->floorheight; - if (type != lowerToFloor) - ceiling->bottomheight += 8 * FRACUNIT; - ceiling->direction = -1; - ceiling->speed = CEILSPEED; - break; - case raiseToHighest: - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - ceiling->speed = CEILSPEED; - break; - } - - ceiling->tag = sec->tag; - ceiling->type = type; - P_AddActiveCeiling(ceiling); - } - return rtn; -} - -//================================================================== -// -// Add an active ceiling -// -//================================================================== -void P_AddActiveCeiling(ceiling_t * c) -{ - int i; - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] == NULL) - { - activeceilings[i] = c; - return; - } -} - -//================================================================== -// -// Remove a ceiling's thinker -// -//================================================================== -void P_RemoveActiveCeiling(ceiling_t * c) -{ - int i; - - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] == c) - { - activeceilings[i]->sector->specialdata = NULL; - P_RemoveThinker(&activeceilings[i]->thinker); - activeceilings[i] = NULL; - break; - } -} - -//================================================================== -// -// Restart a ceiling that's in-stasis -// -//================================================================== -void P_ActivateInStasisCeiling(line_t * line) -{ - int i; - - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && - (activeceilings[i]->direction == 0)) - { - activeceilings[i]->direction = activeceilings[i]->olddirection; - activeceilings[i]->thinker.function = T_MoveCeiling; - } -} - -//================================================================== -// -// EV_CeilingCrushStop -// Stop a ceiling from crushing! -// -//================================================================== -int EV_CeilingCrushStop(line_t * line) -{ - int i; - int rtn; - - rtn = 0; - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && - (activeceilings[i]->direction != 0)) - { - activeceilings[i]->olddirection = activeceilings[i]->direction; - activeceilings[i]->thinker.function = NULL; - activeceilings[i]->direction = 0; // in-stasis - rtn = 1; - } - - return rtn; -} diff --git a/games/NXDoom/src/heretic/p_doors.c b/games/NXDoom/src/heretic/p_doors.c deleted file mode 100644 index 3cd40373538..00000000000 --- a/games/NXDoom/src/heretic/p_doors.c +++ /dev/null @@ -1,380 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_doors.c - -#include "doomdef.h" -#include "deh_str.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -//================================================================== -//================================================================== -// -// VERTICAL DOORS -// -//================================================================== -//================================================================== - -//================================================================== -// -// T_VerticalDoor -// -//================================================================== -void T_VerticalDoor(thinker_t *thinker) -{ - vldoor_t *door = (vldoor_t *) thinker; - result_e res; - - switch (door->direction) - { - case 0: // WAITING - if (!--door->topcountdown) - switch (door->type) - { - case vld_normal: - door->direction = -1; // time to go back down - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - case vld_close30ThenOpen: - door->direction = 1; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - default: - break; - } - break; - case 2: // INITIAL WAIT - if (!--door->topcountdown) - { - switch (door->type) - { - case vld_raiseIn5Mins: - door->direction = 1; - door->type = vld_normal; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - default: - break; - } - } - break; - case -1: // DOWN - res = T_MovePlane(door->sector, door->speed, - door->sector->floorheight, false, 1, - door->direction); - if (res == pastdest) - { - switch (door->type) - { - case vld_normal: - case vld_close: - door->sector->specialdata = NULL; - P_RemoveThinker(&door->thinker); // unlink and free - S_StartSound(&door->sector->soundorg, sfx_dorcls); - break; - case vld_close30ThenOpen: - door->direction = 0; - door->topcountdown = 35 * 30; - break; - default: - break; - } - } - else if (res == crushed) - { - switch (door->type) - { - case vld_close: // DON'T GO BACK UP! - break; - default: - door->direction = 1; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - } - } - break; - case 1: // UP - res = T_MovePlane(door->sector, door->speed, - door->topheight, false, 1, door->direction); - if (res == pastdest) - { - switch (door->type) - { - case vld_normal: - door->direction = 0; // wait at top - door->topcountdown = door->topwait; - break; - case vld_close30ThenOpen: - case vld_open: - door->sector->specialdata = NULL; - P_RemoveThinker(&door->thinker); // unlink and free - S_StopSound(&door->sector->soundorg); - break; - default: - break; - } - } - break; - } -} - -//---------------------------------------------------------------------------- -// -// EV_DoDoor -// -// Move a door up/down -// -//---------------------------------------------------------------------------- - -int EV_DoDoor(line_t * line, vldoor_e type, fixed_t speed) -{ - int secnum; - int retcode; - sector_t *sec; - vldoor_t *door; - - secnum = -1; - retcode = 0; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - { - continue; - } - // Add new door thinker - retcode = 1; - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - switch (type) - { - case vld_close: - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; - door->direction = -1; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - case vld_close30ThenOpen: - door->topheight = sec->ceilingheight; - door->direction = -1; - S_StartSound(&door->sector->soundorg, sfx_doropn); - break; - case vld_normal: - case vld_open: - door->direction = 1; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; - if (door->topheight != sec->ceilingheight) - { - S_StartSound(&door->sector->soundorg, - sfx_doropn); - } - break; - default: - break; - } - door->type = type; - door->speed = speed; - door->topwait = VDOORWAIT; - } - return (retcode); -} - -//================================================================== -// -// EV_VerticalDoor : open a door manually, no tag value -// -//================================================================== -void EV_VerticalDoor(line_t * line, mobj_t * thing) -{ - player_t *player; - sector_t *sec; - vldoor_t *door; - int side; - - side = 0; // only front sides can be used -// -// Check for locks -// - player = thing->player; - switch (line->special) - { - case 26: // Blue Lock - case 32: - if (!player) - { - return; - } - if (!player->keys[key_blue]) - { - P_SetMessage(player, DEH_String(TXT_NEEDBLUEKEY), false); - S_StartSound(NULL, sfx_plroof); - return; - } - break; - case 27: // Yellow Lock - case 34: - if (!player) - { - return; - } - if (!player->keys[key_yellow]) - { - P_SetMessage(player, DEH_String(TXT_NEEDYELLOWKEY), false); - S_StartSound(NULL, sfx_plroof); - return; - } - break; - case 28: // Green Lock - case 33: - if (!player) - { - return; - } - if (!player->keys[key_green]) - { - P_SetMessage(player, DEH_String(TXT_NEEDGREENKEY), false); - S_StartSound(NULL, sfx_plroof); - return; - } - break; - } - - // if the sector has an active thinker, use it - sec = sides[line->sidenum[side ^ 1]].sector; - if (sec->specialdata) - { - door = sec->specialdata; - switch (line->special) - { - case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s - case 26: - case 27: - case 28: - if (door->direction == -1) - { - door->direction = 1; // go back up - } - else - { - if (!thing->player) - { // Monsters don't close doors - return; - } - door->direction = -1; // start going down immediately - } - return; - } - } - - // for proper sound - switch (line->special) - { - case 1: // NORMAL DOOR SOUND - case 31: - S_StartSound(&sec->soundorg, sfx_doropn); - //S_StartSound(&sec->soundorg, sfx_dormov); - break; - default: // LOCKED DOOR SOUND - S_StartSound(&sec->soundorg, sfx_doropn); - //S_StartSound(&sec->soundorg, sfx_dormov); - break; - } - - // - // new door thinker - // - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - door->direction = 1; - switch (line->special) - { - case 1: - case 26: - case 27: - case 28: - door->type = vld_normal; - break; - case 31: - case 32: - case 33: - case 34: - door->type = vld_open; - line->special = 0; - break; - } - door->speed = VDOORSPEED; - door->topwait = VDOORWAIT; - - // - // find the top and bottom of the movement range - // - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; -} - -//================================================================== -// -// Spawn a door that closes after 30 seconds -// -//================================================================== -void P_SpawnDoorCloseIn30(sector_t * sec) -{ - vldoor_t *door; - - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - sec->special = 0; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - door->direction = 0; - door->type = vld_normal; - door->speed = VDOORSPEED; - door->topcountdown = 30 * 35; -} - -//================================================================== -// -// Spawn a door that opens after 5 minutes -// -//================================================================== -void P_SpawnDoorRaiseIn5Mins(sector_t * sec, int secnum) -{ - vldoor_t *door; - - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - sec->special = 0; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - door->direction = 2; - door->type = vld_raiseIn5Mins; - door->speed = VDOORSPEED; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; - door->topwait = VDOORWAIT; - door->topcountdown = 5 * 60 * 35; -} diff --git a/games/NXDoom/src/heretic/p_enemy.c b/games/NXDoom/src/heretic/p_enemy.c deleted file mode 100644 index 3ade41ae963..00000000000 --- a/games/NXDoom/src/heretic/p_enemy.c +++ /dev/null @@ -1,2711 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_enemy.c - -#include -#include "doomdef.h" -#include "i_system.h" -#include "i_timer.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -// Macros - -#define MAX_BOSS_SPOTS 8 - -// Types - -typedef struct -{ - fixed_t x; - fixed_t y; - angle_t angle; -} BossSpot_t; - -// Private Data - -static int BossSpotCount; -static BossSpot_t BossSpots[MAX_BOSS_SPOTS]; - -//---------------------------------------------------------------------------- -// -// PROC P_InitMonsters -// -// Called at level load. -// -//---------------------------------------------------------------------------- - -void P_InitMonsters(void) -{ - BossSpotCount = 0; -} - -//---------------------------------------------------------------------------- -// -// PROC P_AddBossSpot -// -//---------------------------------------------------------------------------- - -void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle) -{ - if (BossSpotCount == MAX_BOSS_SPOTS) - { - I_Error("Too many boss spots."); - } - BossSpots[BossSpotCount].x = x; - BossSpots[BossSpotCount].y = y; - BossSpots[BossSpotCount].angle = angle; - BossSpotCount++; -} - -//---------------------------------------------------------------------------- -// -// PROC P_RecursiveSound -// -//---------------------------------------------------------------------------- - -mobj_t *soundtarget; - -void P_RecursiveSound(sector_t * sec, int soundblocks) -{ - int i; - line_t *check; - sector_t *other; - - // Wake up all monsters in this sector - if (sec->validcount == validcount - && sec->soundtraversed <= soundblocks + 1) - { // Already flooded - return; - } - sec->validcount = validcount; - sec->soundtraversed = soundblocks + 1; - sec->soundtarget = soundtarget; - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - if (!(check->flags & ML_TWOSIDED)) - { - continue; - } - P_LineOpening(check); - if (openrange <= 0) - { // Closed door - continue; - } - if (sides[check->sidenum[0]].sector == sec) - { - other = sides[check->sidenum[1]].sector; - } - else - { - other = sides[check->sidenum[0]].sector; - } - if (check->flags & ML_SOUNDBLOCK) - { - if (!soundblocks) - { - P_RecursiveSound(other, 1); - } - } - else - { - P_RecursiveSound(other, soundblocks); - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_NoiseAlert -// -// If a monster yells at a player, it will alert other monsters to the -// player. -// -//---------------------------------------------------------------------------- - -void P_NoiseAlert(mobj_t * target, mobj_t * emmiter) -{ - soundtarget = target; - validcount++; - P_RecursiveSound(emmiter->subsector->sector, 0); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_CheckMeleeRange -// -//---------------------------------------------------------------------------- - -boolean P_CheckMeleeRange(mobj_t * actor) -{ - mobj_t *mo; - fixed_t dist; - - if (!actor->target) - { - return (false); - } - mo = actor->target; - dist = P_AproxDistance(mo->x - actor->x, mo->y - actor->y); - if (dist >= MELEERANGE) - { - return (false); - } - if (!P_CheckSight(actor, mo)) - { - return (false); - } - if (mo->z > actor->z + actor->height) - { // Target is higher than the attacker - return (false); - } - else if (actor->z > mo->z + mo->height) - { // Attacker is higher - return (false); - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_CheckMissileRange -// -//---------------------------------------------------------------------------- - -boolean P_CheckMissileRange(mobj_t * actor) -{ - fixed_t dist; - - if (!P_CheckSight(actor, actor->target)) - { - return (false); - } - if (actor->flags & MF_JUSTHIT) - { // The target just hit the enemy, so fight back! - actor->flags &= ~MF_JUSTHIT; - return (true); - } - if (actor->reactiontime) - { // Don't attack yet - return (false); - } - dist = (P_AproxDistance(actor->x - actor->target->x, - actor->y - actor->target->y) >> FRACBITS) - 64; - if (!actor->info->meleestate) - { // No melee attack, so fire more frequently - dist -= 128; - } - if (actor->type == MT_IMP) - { // Imp's fly attack from far away - dist >>= 1; - } - if (dist > 200) - { - dist = 200; - } - if (P_Random() < dist) - { - return (false); - } - return (true); -} - -/* -================ -= -= P_Move -= -= Move in the current direction -= returns false if the move is blocked -================ -*/ - -fixed_t xspeed[8] = - { FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000, 0, 47000 }; -fixed_t yspeed[8] = - { 0, 47000, FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000 }; - - -boolean P_Move(mobj_t * actor) -{ - fixed_t tryx, tryy; - line_t *ld; - boolean good; - - if (actor->movedir == DI_NODIR) - { - return (false); - } - tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; - tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; - if (!P_TryMove(actor, tryx, tryy)) - { // open any specials - if (actor->flags & MF_FLOAT && floatok) - { // must adjust height - if (actor->z < tmfloorz) - { - actor->z += FLOATSPEED; - } - else - { - actor->z -= FLOATSPEED; - } - actor->flags |= MF_INFLOAT; - return (true); - } - if (!numspechit) - { - return false; - } - actor->movedir = DI_NODIR; - good = false; - while (numspechit--) - { - ld = spechit[numspechit]; - // if the special isn't a door that can be opened, return false - if (P_UseSpecialLine(actor, ld)) - { - good = true; - } - } - return (good); - } - else - { - actor->flags &= ~MF_INFLOAT; - } - if (!(actor->flags & MF_FLOAT)) - { - if (actor->z > actor->floorz) - { - P_HitFloor(actor); - } - actor->z = actor->floorz; - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_TryWalk -// -// Attempts to move actor in its current (ob->moveangle) direction. -// If blocked by either a wall or an actor returns FALSE. -// If move is either clear of block only by a door, returns TRUE and sets. -// If a door is in the way, an OpenDoor call is made to start it opening. -// -//---------------------------------------------------------------------------- - -boolean P_TryWalk(mobj_t * actor) -{ - if (!P_Move(actor)) - { - return (false); - } - actor->movecount = P_Random() & 15; - return (true); -} - -/* -================ -= -= P_NewChaseDir -= -================ -*/ - -dirtype_t opposite[] = - { DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, - DI_NORTH, DI_NORTHWEST, DI_NODIR -}; - -dirtype_t diags[] = - { DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST }; - -void P_NewChaseDir(mobj_t * actor) -{ - fixed_t deltax, deltay; - dirtype_t d[3]; - dirtype_t tdir, olddir, turnaround; - - if (!actor->target) - I_Error("P_NewChaseDir: called with no target"); - - olddir = actor->movedir; - turnaround = opposite[olddir]; - - deltax = actor->target->x - actor->x; - deltay = actor->target->y - actor->y; - if (deltax > 10 * FRACUNIT) - d[1] = DI_EAST; - else if (deltax < -10 * FRACUNIT) - d[1] = DI_WEST; - else - d[1] = DI_NODIR; - if (deltay < -10 * FRACUNIT) - d[2] = DI_SOUTH; - else if (deltay > 10 * FRACUNIT) - d[2] = DI_NORTH; - else - d[2] = DI_NODIR; - -// try direct route - if (d[1] != DI_NODIR && d[2] != DI_NODIR) - { - actor->movedir = diags[((deltay < 0) << 1) + (deltax > 0)]; - if (actor->movedir != turnaround && P_TryWalk(actor)) - return; - } - -// try other directions - if (P_Random() > 200 || abs(deltay) > abs(deltax)) - { - tdir = d[1]; - d[1] = d[2]; - d[2] = tdir; - } - - if (d[1] == turnaround) - d[1] = DI_NODIR; - if (d[2] == turnaround) - d[2] = DI_NODIR; - - if (d[1] != DI_NODIR) - { - actor->movedir = d[1]; - if (P_TryWalk(actor)) - return; /*either moved forward or attacked */ - } - - if (d[2] != DI_NODIR) - { - actor->movedir = d[2]; - if (P_TryWalk(actor)) - return; - } - -/* there is no direct path to the player, so pick another direction */ - - if (olddir != DI_NODIR) - { - actor->movedir = olddir; - if (P_TryWalk(actor)) - return; - } - - if (P_Random() & 1) /*randomly determine direction of search */ - { - for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) - { - if (tdir != turnaround) - { - actor->movedir = tdir; - if (P_TryWalk(actor)) - return; - } - } - } - else - { - // Iterate over all movedirs. - tdir = DI_SOUTHEAST; - - for (;;) - { - if (tdir != turnaround) - { - actor->movedir = tdir; - if (P_TryWalk(actor)) - return; - } - - if (tdir == DI_EAST) - { - break; - } - - --tdir; - } - } - - if (turnaround != DI_NODIR) - { - actor->movedir = turnaround; - if (P_TryWalk(actor)) - return; - } - - actor->movedir = DI_NODIR; // can't move -} - -//--------------------------------------------------------------------------- -// -// FUNC P_LookForMonsters -// -//--------------------------------------------------------------------------- - -#define MONS_LOOK_RANGE (20*64*FRACUNIT) -#define MONS_LOOK_LIMIT 64 - -boolean P_LookForMonsters(mobj_t * actor) -{ - int count; - mobj_t *mo; - thinker_t *think; - - if (!P_CheckSight(players[0].mo, actor)) - { // Player can't see monster - return (false); - } - count = 0; - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - if (!(mo->flags & MF_COUNTKILL) || (mo == actor) || (mo->health <= 0)) - { // Not a valid monster - continue; - } - if (P_AproxDistance(actor->x - mo->x, actor->y - mo->y) - > MONS_LOOK_RANGE) - { // Out of range - continue; - } - if (P_Random() < 16) - { // Skip - continue; - } - if (count++ > MONS_LOOK_LIMIT) - { // Stop searching - return (false); - } - if (!P_CheckSight(actor, mo)) - { // Out of sight - continue; - } - // Found a target monster - actor->target = mo; - return (true); - } - return (false); -} - -/* -================ -= -= P_LookForPlayers -= -= If allaround is false, only look 180 degrees in front -= returns true if a player is targeted -================ -*/ - -boolean P_LookForPlayers(mobj_t * actor, boolean allaround) -{ - int c; - int stop; - player_t *player; - angle_t an; - fixed_t dist; - - if (!netgame && players[0].health <= 0) - { // Single player game and player is dead, look for monsters - return (P_LookForMonsters(actor)); - } - c = 0; - stop = (actor->lastlook - 1) & 3; - for (;; actor->lastlook = (actor->lastlook + 1) & 3) - { - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2 || actor->lastlook == stop) - return false; // done looking - - player = &players[actor->lastlook]; - if (player->health <= 0) - continue; // dead - if (!P_CheckSight(actor, player->mo)) - continue; // out of sight - - if (!allaround) - { - an = R_PointToAngle2(actor->x, actor->y, - player->mo->x, player->mo->y) - actor->angle; - if (an > ANG90 && an < ANG270) - { - dist = P_AproxDistance(player->mo->x - actor->x, - player->mo->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - if (player->mo->flags & MF_SHADOW) - { // Player is invisible - if ((P_AproxDistance(player->mo->x - actor->x, - player->mo->y - actor->y) > 2 * MELEERANGE) - && P_AproxDistance(player->mo->momx, player->mo->momy) - < 5 * FRACUNIT) - { // Player is sneaking - can't detect - return (false); - } - if (P_Random() < 225) - { // Player isn't sneaking, but still didn't detect - return (false); - } - } - actor->target = player->mo; - return (true); - } - return (false); -} - -/* -=============================================================================== - - ACTION ROUTINES - -=============================================================================== -*/ - -/* -============== -= -= A_Look -= -= Stay in state until a player is sighted -= -============== -*/ - -void A_Look(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *targ; - - actor->threshold = 0; // any shot will wake up - targ = actor->subsector->sector->soundtarget; - if (targ && (targ->flags & MF_SHOOTABLE)) - { - actor->target = targ; - if (actor->flags & MF_AMBUSH) - { - if (P_CheckSight(actor, actor->target)) - goto seeyou; - } - else - goto seeyou; - } - - - if (!P_LookForPlayers(actor, false)) - return; - -// go into chase state - seeyou: - if (actor->info->seesound) - { - int sound; - -/* - switch (actor->info->seesound) - { - case sfx_posit1: - case sfx_posit2: - case sfx_posit3: - sound = sfx_posit1+P_Random()%3; - break; - case sfx_bgsit1: - case sfx_bgsit2: - sound = sfx_bgsit1+P_Random()%2; - break; - default: - sound = actor->info->seesound; - break; - } -*/ - sound = actor->info->seesound; - if (actor->flags2 & MF2_BOSS) - { // Full volume - S_StartSound(NULL, sound); - } - else - { - S_StartSound(actor, sound); - } - } - P_SetMobjState(actor, actor->info->seestate); -} - - -/* -============== -= -= A_Chase -= -= Actor has a melee attack, so it tries to close as fast as possible -= -============== -*/ - -void A_Chase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int delta; - - if (actor->reactiontime) - { - actor->reactiontime--; - } - - // Modify target threshold - if (actor->threshold) - { - actor->threshold--; - } - - if (gameskill == sk_nightmare) - { // Monsters move faster in nightmare mode - actor->tics -= actor->tics / 2; - if (actor->tics < 3) - { - actor->tics = 3; - } - } - -// -// turn towards movement direction if not there yet -// - if (actor->movedir < 8) - { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - if (delta > 0) - { - actor->angle -= ANG90 / 2; - } - else if (delta < 0) - { - actor->angle += ANG90 / 2; - } - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { // look for a new target - if (P_LookForPlayers(actor, true)) - { // got a new target - return; - } - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - -// -// don't attack twice in a row -// - if (actor->flags & MF_JUSTATTACKED) - { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare) - P_NewChaseDir(actor); - return; - } - -// -// check for melee attack -// - if (actor->info->meleestate && P_CheckMeleeRange(actor)) - { - if (actor->info->attacksound) - S_StartSound(actor, actor->info->attacksound); - P_SetMobjState(actor, actor->info->meleestate); - return; - } - -// -// check for missile attack -// - if (actor->info->missilestate) - { - if (gameskill < sk_nightmare && actor->movecount) - goto nomissile; - if (!P_CheckMissileRange(actor)) - goto nomissile; - P_SetMobjState(actor, actor->info->missilestate); - actor->flags |= MF_JUSTATTACKED; - return; - } - nomissile: - -// -// possibly choose another target -// - if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) - { - if (P_LookForPlayers(actor, true)) - return; // got a new target - } - -// -// chase towards player -// - if (--actor->movecount < 0 || !P_Move(actor)) - { - P_NewChaseDir(actor); - } - -// -// make active sound -// - if (actor->info->activesound && P_Random() < 3) - { - if (actor->type == MT_WIZARD && P_Random() < 128) - { - S_StartSound(actor, actor->info->seesound); - } - else if (actor->type == MT_SORCERER2) - { - S_StartSound(NULL, actor->info->activesound); - } - else - { - S_StartSound(actor, actor->info->activesound); - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FaceTarget -// -//---------------------------------------------------------------------------- - -void A_FaceTarget(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - actor->flags &= ~MF_AMBUSH; - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, - actor->target->y); - if (actor->target->flags & MF_SHADOW) - { // Target is a ghost - actor->angle += P_SubRandom() << 21; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Pain -// -//---------------------------------------------------------------------------- - -void A_Pain(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->info->painsound) - { - S_StartSound(actor, actor->info->painsound); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_DripBlood -// -//---------------------------------------------------------------------------- - -void A_DripBlood(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1,r2; - - r1 = P_SubRandom(); - r2 = P_SubRandom(); - - mo = P_SpawnMobj(actor->x + (r2 << 11), - actor->y + (r1 << 11), actor->z, - MT_BLOOD); - mo->momx = P_SubRandom() << 10; - mo->momy = P_SubRandom() << 10; - mo->flags2 |= MF2_LOGRAV; -} - -//---------------------------------------------------------------------------- -// -// PROC A_KnightAttack -// -//---------------------------------------------------------------------------- - -void A_KnightAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(3)); - S_StartSound(actor, sfx_kgtat2); - return; - } - // Throw axe - S_StartSound(actor, actor->info->attacksound); - if (actor->type == MT_KNIGHTGHOST || P_Random() < 40) - { // Red axe - P_SpawnMissile(actor, actor->target, MT_REDAXE); - return; - } - // Green axe - P_SpawnMissile(actor, actor->target, MT_KNIGHTAXE); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpExplode -// -//---------------------------------------------------------------------------- - -void A_ImpExplode(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK1); - mo->momx = P_SubRandom() << 10; - mo->momy = P_SubRandom() << 10; - mo->momz = 9 * FRACUNIT; - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK2); - mo->momx = P_SubRandom() << 10; - mo->momy = P_SubRandom() << 10; - mo->momz = 9 * FRACUNIT; - if (actor->special1.i == 666) - { // Extreme death crash - P_SetMobjState(actor, S_IMP_XCRASH1); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_BeastPuff -// -//---------------------------------------------------------------------------- - -void A_BeastPuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_Random() > 64) - { - int r1,r2,r3; - r1 = P_SubRandom(); - r2 = P_SubRandom(); - r3 = P_SubRandom(); - P_SpawnMobj(actor->x + (r3 << 10), - actor->y + (r2 << 10), - actor->z + (r1 << 10), MT_PUFFY); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpMeAttack -// -//---------------------------------------------------------------------------- - -void A_ImpMeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, 5 + (P_Random() & 7)); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpMsAttack -// -//---------------------------------------------------------------------------- - -void A_ImpMsAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *dest; - angle_t an; - int dist; - - if (!actor->target || P_Random() > 64) - { - P_SetMobjState(actor, actor->info->seestate); - return; - } - dest = actor->target; - actor->flags |= MF_SKULLFLY; - S_StartSound(actor, actor->info->attacksound); - A_FaceTarget(actor, player, psp); - an = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(12 * FRACUNIT, finecosine[an]); - actor->momy = FixedMul(12 * FRACUNIT, finesine[an]); - dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); - dist = dist / (12 * FRACUNIT); - if (dist < 1) - { - dist = 1; - } - actor->momz = (dest->z + (dest->height >> 1) - actor->z) / dist; -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpMsAttack2 -// -// Fireball attack of the imp leader. -// -//---------------------------------------------------------------------------- - -void A_ImpMsAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, 5 + (P_Random() & 7)); - return; - } - P_SpawnMissile(actor, actor->target, MT_IMPBALL); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpDeath -// -//---------------------------------------------------------------------------- - -void A_ImpDeath(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SOLID; - actor->flags2 |= MF2_FOOTCLIP; - if (actor->z <= actor->floorz) - { - P_SetMobjState(actor, S_IMP_CRASH1); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpXDeath1 -// -//---------------------------------------------------------------------------- - -void A_ImpXDeath1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SOLID; - actor->flags |= MF_NOGRAVITY; - actor->flags2 |= MF2_FOOTCLIP; - actor->special1.i = 666; // Flag the crash routine -} - -//---------------------------------------------------------------------------- -// -// PROC A_ImpXDeath2 -// -//---------------------------------------------------------------------------- - -void A_ImpXDeath2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_NOGRAVITY; - if (actor->z <= actor->floorz) - { - P_SetMobjState(actor, S_IMP_CRASH1); - } -} - -//---------------------------------------------------------------------------- -// -// FUNC P_UpdateChicken -// -// Returns true if the chicken morphs. -// -//---------------------------------------------------------------------------- - -boolean P_UpdateChicken(mobj_t * actor, int tics) -{ - mobj_t *fog; - fixed_t x; - fixed_t y; - fixed_t z; - mobjtype_t moType; - mobj_t *mo; - mobj_t oldChicken; - - actor->special1.i -= tics; - if (actor->special1.i > 0) - { - return (false); - } - moType = actor->special2.i; - x = actor->x; - y = actor->y; - z = actor->z; - oldChicken = *actor; - P_SetMobjState(actor, S_FREETARGMOBJ); - mo = P_SpawnMobj(x, y, z, moType); - if (P_TestMobjLocation(mo) == false) - { // Didn't fit - P_RemoveMobj(mo); - mo = P_SpawnMobj(x, y, z, MT_CHICKEN); - mo->angle = oldChicken.angle; - mo->flags = oldChicken.flags; - mo->health = oldChicken.health; - mo->target = oldChicken.target; - mo->special1.i = 5 * 35; // Next try in 5 seconds - mo->special2.i = moType; - return (false); - } - mo->angle = oldChicken.angle; - mo->target = oldChicken.target; - fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, sfx_telept); - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ChicAttack -// -//---------------------------------------------------------------------------- - -void A_ChicAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateChicken(actor, 18)) - { - return; - } - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, 1 + (P_Random() & 1)); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_ChicLook -// -//---------------------------------------------------------------------------- - -void A_ChicLook(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateChicken(actor, 10)) - { - return; - } - A_Look(actor, player, psp); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ChicChase -// -//---------------------------------------------------------------------------- - -void A_ChicChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateChicken(actor, 3)) - { - return; - } - A_Chase(actor, player, psp); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ChicPain -// -//---------------------------------------------------------------------------- - -void A_ChicPain(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateChicken(actor, 10)) - { - return; - } - S_StartSound(actor, actor->info->painsound); -} - -//---------------------------------------------------------------------------- -// -// PROC A_Feathers -// -//---------------------------------------------------------------------------- - -void A_Feathers(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - int count; - mobj_t *mo; - - if (actor->health > 0) - { // Pain - count = P_Random() < 32 ? 2 : 1; - } - else - { // Death - count = 5 + (P_Random() & 3); - } - for (i = 0; i < count; i++) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 20 * FRACUNIT, - MT_FEATHER); - mo->target = actor; - mo->momx = P_SubRandom() << 8; - mo->momy = P_SubRandom() << 8; - mo->momz = FRACUNIT + (P_Random() << 9); - P_SetMobjState(mo, S_FEATHER1 + (P_Random() & 7)); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MummyAttack -// -//---------------------------------------------------------------------------- - -void A_MummyAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(2)); - S_StartSound(actor, sfx_mumat2); - return; - } - S_StartSound(actor, sfx_mumat1); -} - -//---------------------------------------------------------------------------- -// -// PROC A_MummyAttack2 -// -// Mummy leader missile attack. -// -//---------------------------------------------------------------------------- - -void A_MummyAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - if (!actor->target) - { - return; - } - //S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(2)); - return; - } - mo = P_SpawnMissile(actor, actor->target, MT_MUMMYFX1); - //mo = P_SpawnMissile(actor, actor->target, MT_EGGFX); - if (mo != NULL) - { - mo->special1.m = actor->target; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MummyFX1Seek -// -//---------------------------------------------------------------------------- - -void A_MummyFX1Seek(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SeekerMissile(actor, ANG1_X * 10, ANG1_X * 20); -} - -//---------------------------------------------------------------------------- -// -// PROC A_MummySoul -// -//---------------------------------------------------------------------------- - -void A_MummySoul(mobj_t * mummy, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(mummy->x, mummy->y, mummy->z + 10 * FRACUNIT, - MT_MUMMYSOUL); - mo->momz = FRACUNIT; -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor1Pain -// -//---------------------------------------------------------------------------- - -void A_Sor1Pain(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->special1.i = 20; // Number of steps to walk fast - A_Pain(actor, player, psp); -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor1Chase -// -//---------------------------------------------------------------------------- - -void A_Sor1Chase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special1.i) - { - actor->special1.i--; - actor->tics -= 3; - } - A_Chase(actor, player, psp); -} - -//---------------------------------------------------------------------------- -// -// PROC A_Srcr1Attack -// -// Sorcerer demon attack. -// -//---------------------------------------------------------------------------- - -void A_Srcr1Attack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - fixed_t momz; - angle_t angle; - - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(8)); - return; - } - if (actor->health > (actor->info->spawnhealth / 3) * 2) - { // Spit one fireball - P_SpawnMissile(actor, actor->target, MT_SRCRFX1); - } - else - { // Spit three fireballs - mo = P_SpawnMissile(actor, actor->target, MT_SRCRFX1); - if (mo) - { - momz = mo->momz; - angle = mo->angle; - P_SpawnMissileAngle(actor, MT_SRCRFX1, angle - ANG1_X * 3, momz); - P_SpawnMissileAngle(actor, MT_SRCRFX1, angle + ANG1_X * 3, momz); - } - if (actor->health < actor->info->spawnhealth / 3) - { // Maybe attack again - if (actor->special1.i) - { // Just attacked, so don't attack again - actor->special1.i = 0; - } - else - { // Set state to attack again - actor->special1.i = 1; - P_SetMobjState(actor, S_SRCR1_ATK4); - } - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_SorcererRise -// -//---------------------------------------------------------------------------- - -void A_SorcererRise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - actor->flags &= ~MF_SOLID; - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCERER2); - P_SetMobjState(mo, S_SOR2_RISE1); - mo->angle = actor->angle; - mo->target = actor->target; -} - -//---------------------------------------------------------------------------- -// -// PROC P_DSparilTeleport -// -//---------------------------------------------------------------------------- - -void P_DSparilTeleport(mobj_t *actor) -{ - int i; - fixed_t x; - fixed_t y; - fixed_t prevX; - fixed_t prevY; - fixed_t prevZ; - mobj_t *mo; - - if (!BossSpotCount) - { // No spots - return; - } - i = P_Random(); - do - { - i++; - x = BossSpots[i % BossSpotCount].x; - y = BossSpots[i % BossSpotCount].y; - } - while (P_AproxDistance(actor->x - x, actor->y - y) < 128 * FRACUNIT); - prevX = actor->x; - prevY = actor->y; - prevZ = actor->z; - if (P_TeleportMove(actor, x, y)) - { - mo = P_SpawnMobj(prevX, prevY, prevZ, MT_SOR2TELEFADE); - S_StartSound(mo, sfx_telept); - P_SetMobjState(actor, S_SOR2_TELE1); - S_StartSound(actor, sfx_telept); - actor->z = actor->floorz; - actor->angle = BossSpots[i % BossSpotCount].angle; - actor->momx = actor->momy = actor->momz = 0; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Srcr2Decide -// -//---------------------------------------------------------------------------- - -void A_Srcr2Decide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - static int chance[] = { - 192, 120, 120, 120, 64, 64, 32, 16, 0 - }; - - if (!BossSpotCount) - { // No spots - return; - } - if (P_Random() < chance[actor->health / (actor->info->spawnhealth / 8)]) - { - P_DSparilTeleport(actor); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Srcr2Attack -// -//---------------------------------------------------------------------------- - -void A_Srcr2Attack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int chance; - - if (!actor->target) - { - return; - } - S_StartSound(NULL, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(20)); - return; - } - chance = actor->health < actor->info->spawnhealth / 2 ? 96 : 48; - if (P_Random() < chance) - { // Wizard spawners - P_SpawnMissileAngle(actor, MT_SOR2FX2, - actor->angle - ANG45, FRACUNIT / 2); - P_SpawnMissileAngle(actor, MT_SOR2FX2, - actor->angle + ANG45, FRACUNIT / 2); - } - else - { // Blue bolt - P_SpawnMissile(actor, actor->target, MT_SOR2FX1); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_BlueSpark -// -//---------------------------------------------------------------------------- - -void A_BlueSpark(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - mobj_t *mo; - - for (i = 0; i < 2; i++) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SOR2FXSPARK); - mo->momx = P_SubRandom() << 9; - mo->momy = P_SubRandom() << 9; - mo->momz = FRACUNIT + (P_Random() << 8); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_GenWizard -// -//---------------------------------------------------------------------------- - -void A_GenWizard(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - mobj_t *fog; - - mo = P_SpawnMobj(actor->x, actor->y, - actor->z - mobjinfo[MT_WIZARD].height / 2, MT_WIZARD); - if (P_TestMobjLocation(mo) == false) - { // Didn't fit - P_RemoveMobj(mo); - return; - } - actor->momx = actor->momy = actor->momz = 0; - P_SetMobjState(actor, mobjinfo[actor->type].deathstate); - actor->flags &= ~MF_MISSILE; - fog = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TFOG); - S_StartSound(fog, sfx_telept); -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor2DthInit -// -//---------------------------------------------------------------------------- - -void A_Sor2DthInit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->special1.i = 7; // Animation loop counter - P_Massacre(); // Kill monsters early -} - -//---------------------------------------------------------------------------- -// -// PROC A_Sor2DthLoop -// -//---------------------------------------------------------------------------- - -void A_Sor2DthLoop(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (--actor->special1.i) - { // Need to loop - P_SetMobjState(actor, S_SOR2_DIE4); - } -} - -//---------------------------------------------------------------------------- -// -// D'Sparil Sound Routines -// -//---------------------------------------------------------------------------- - -void A_SorZap(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, sfx_sorzap); -} - -void A_SorRise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, sfx_sorrise); -} - -void A_SorDSph(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, sfx_sordsph); -} - -void A_SorDExp(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, sfx_sordexp); -} - -void A_SorDBon(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, sfx_sordbon); -} - -void A_SorSightSnd(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, sfx_sorsit); -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk1 -// -// Melee attack. -// -//---------------------------------------------------------------------------- - -void A_MinotaurAtk1(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - player_t *player; - - if (!actor->target) - { - return; - } - S_StartSound(actor, sfx_stfpow); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(4)); - if ((player = actor->target->player) != NULL) - { // Squish the player - player->deltaviewheight = -16 * FRACUNIT; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurDecide -// -// Choose a missile attack. -// -//---------------------------------------------------------------------------- - -#define MNTR_CHARGE_SPEED (13*FRACUNIT) - -void A_MinotaurDecide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - mobj_t *target; - int dist; - - target = actor->target; - if (!target) - { - return; - } - S_StartSound(actor, sfx_minsit); - dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); - if (target->z + target->height > actor->z - && target->z + target->height < actor->z + actor->height - && dist < 8 * 64 * FRACUNIT - && dist > 1 * 64 * FRACUNIT && P_Random() < 150) - { // Charge attack - // Don't call the state function right away - P_SetMobjStateNF(actor, S_MNTR_ATK4_1); - actor->flags |= MF_SKULLFLY; - A_FaceTarget(actor, player, psp); - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(MNTR_CHARGE_SPEED, finecosine[angle]); - actor->momy = FixedMul(MNTR_CHARGE_SPEED, finesine[angle]); - actor->special1.i = 35 / 2; // Charge duration - } - else if (target->z == target->floorz - && dist < 9 * 64 * FRACUNIT && P_Random() < 220) - { // Floor fire attack - P_SetMobjState(actor, S_MNTR_ATK3_1); - actor->special2.i = 0; - } - else - { // Swing attack - A_FaceTarget(actor, player, psp); - // Don't need to call P_SetMobjState because the current state - // falls through to the swing attack - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurCharge -// -//---------------------------------------------------------------------------- - -void A_MinotaurCharge(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *puff; - - if (actor->special1.i) - { - puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF); - puff->momz = 2 * FRACUNIT; - actor->special1.i--; - } - else - { - actor->flags &= ~MF_SKULLFLY; - P_SetMobjState(actor, actor->info->seestate); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk2 -// -// Swing attack. -// -//---------------------------------------------------------------------------- - -void A_MinotaurAtk2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - fixed_t momz; - - if (!actor->target) - { - return; - } - S_StartSound(actor, sfx_minat2); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(5)); - return; - } - mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX1); - if (mo) - { - S_StartSound(mo, sfx_minat2); - momz = mo->momz; - angle = mo->angle; - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 8), momz); - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 8), momz); - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 16), momz); - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 16), momz); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk3 -// -// Floor fire attack. -// -//---------------------------------------------------------------------------- - -void A_MinotaurAtk3(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - mobj_t *mo; - player_t *player; - - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(5)); - if ((player = actor->target->player) != NULL) - { // Squish the player - player->deltaviewheight = -16 * FRACUNIT; - } - } - else - { - mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX2); - if (mo != NULL) - { - S_StartSound(mo, sfx_minat1); - } - } - if (P_Random() < 192 && actor->special2.i == 0) - { - P_SetMobjState(actor, S_MNTR_ATK3_4); - actor->special2.i = 1; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MntrFloorFire -// -//---------------------------------------------------------------------------- - -void A_MntrFloorFire(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1, r2; - - r1 = P_SubRandom(); - r2 = P_SubRandom(); - - actor->z = actor->floorz; - mo = P_SpawnMobj(actor->x + (r2 << 10), - actor->y + (r1 << 10), ONFLOORZ, - MT_MNTRFX3); - mo->target = actor->target; - mo->momx = 1; // Force block checking - P_CheckMissileSpawn(mo); -} - -//---------------------------------------------------------------------------- -// -// PROC A_BeastAttack -// -//---------------------------------------------------------------------------- - -void A_BeastAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(3)); - return; - } - P_SpawnMissile(actor, actor->target, MT_BEASTBALL); -} - -//---------------------------------------------------------------------------- -// -// PROC A_HeadAttack -// -//---------------------------------------------------------------------------- - -void A_HeadAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - mobj_t *fire; - mobj_t *baseFire; - mobj_t *mo; - mobj_t *target; - int randAttack; - static int atkResolve1[] = { 50, 150 }; - static int atkResolve2[] = { 150, 200 }; - int dist; - - // Ice ball (close 20% : far 60%) - // Fire column (close 40% : far 20%) - // Whirlwind (close 40% : far 20%) - // Distance threshold = 8 cells - - target = actor->target; - if (target == NULL) - { - return; - } - A_FaceTarget(actor, player, psp); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(target, actor, actor, HITDICE(6)); - return; - } - dist = P_AproxDistance(actor->x - target->x, actor->y - target->y) - > 8 * 64 * FRACUNIT; - randAttack = P_Random(); - if (randAttack < atkResolve1[dist]) - { // Ice ball - P_SpawnMissile(actor, target, MT_HEADFX1); - S_StartSound(actor, sfx_hedat2); - } - else if (randAttack < atkResolve2[dist]) - { // Fire column - baseFire = P_SpawnMissile(actor, target, MT_HEADFX3); - if (baseFire != NULL) - { - P_SetMobjState(baseFire, S_HEADFX3_4); // Don't grow - for (i = 0; i < 5; i++) - { - fire = P_SpawnMobj(baseFire->x, baseFire->y, - baseFire->z, MT_HEADFX3); - if (i == 0) - { - S_StartSound(actor, sfx_hedat1); - } - fire->target = baseFire->target; - fire->angle = baseFire->angle; - fire->momx = baseFire->momx; - fire->momy = baseFire->momy; - fire->momz = baseFire->momz; - fire->damage = 0; - fire->health = (i + 1) * 2; - P_CheckMissileSpawn(fire); - } - } - } - else - { // Whirlwind - mo = P_SpawnMissile(actor, target, MT_WHIRLWIND); - if (mo != NULL) - { - mo->z -= 32 * FRACUNIT; - mo->special1.m = target; - mo->special2.i = 50; // Timer for active sound - mo->health = 20 * TICRATE; // Duration - S_StartSound(actor, sfx_hedat3); - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_WhirlwindSeek -// -//---------------------------------------------------------------------------- - -void A_WhirlwindSeek(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->health -= 3; - if (actor->health < 0) - { - actor->momx = actor->momy = actor->momz = 0; - P_SetMobjState(actor, mobjinfo[actor->type].deathstate); - actor->flags &= ~MF_MISSILE; - return; - } - if ((actor->special2.i -= 3) < 0) - { - actor->special2.i = 58 + (P_Random() & 31); - S_StartSound(actor, sfx_hedat3); - } - if (actor->special1.m - && (((mobj_t *) (actor->special1.m))->flags & MF_SHADOW)) - { - return; - } - P_SeekerMissile(actor, ANG1_X * 10, ANG1_X * 30); -} - -//---------------------------------------------------------------------------- -// -// PROC A_HeadIceImpact -// -//---------------------------------------------------------------------------- - -void A_HeadIceImpact(mobj_t * ice, player_t *player, pspdef_t *psp) -{ - unsigned int i; - angle_t angle; - mobj_t *shard; - - for (i = 0; i < 8; i++) - { - shard = P_SpawnMobj(ice->x, ice->y, ice->z, MT_HEADFX2); - angle = i * ANG45; - shard->target = ice->target; - shard->angle = angle; - angle >>= ANGLETOFINESHIFT; - shard->momx = FixedMul(shard->info->speed, finecosine[angle]); - shard->momy = FixedMul(shard->info->speed, finesine[angle]); - shard->momz = (fixed_t)(-.6 * FRACUNIT); - P_CheckMissileSpawn(shard); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_HeadFireGrow -// -//---------------------------------------------------------------------------- - -void A_HeadFireGrow(mobj_t * fire, player_t *player, pspdef_t *psp) -{ - fire->health--; - fire->z += 9 * FRACUNIT; - if (fire->health == 0) - { - fire->damage = fire->info->damage; - P_SetMobjState(fire, S_HEADFX3_4); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_SnakeAttack -// -//---------------------------------------------------------------------------- - -void A_SnakeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - P_SetMobjState(actor, S_SNAKE_WALK1); - return; - } - S_StartSound(actor, actor->info->attacksound); - A_FaceTarget(actor, player, psp); - P_SpawnMissile(actor, actor->target, MT_SNAKEPRO_A); -} - -//---------------------------------------------------------------------------- -// -// PROC A_SnakeAttack2 -// -//---------------------------------------------------------------------------- - -void A_SnakeAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - P_SetMobjState(actor, S_SNAKE_WALK1); - return; - } - S_StartSound(actor, actor->info->attacksound); - A_FaceTarget(actor, player, psp); - P_SpawnMissile(actor, actor->target, MT_SNAKEPRO_B); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ClinkAttack -// -//---------------------------------------------------------------------------- - -void A_ClinkAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int damage; - - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - damage = ((P_Random() % 7) + 3); - P_DamageMobj(actor->target, actor, actor, damage); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_GhostOff -// -//---------------------------------------------------------------------------- - -void A_GhostOff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SHADOW; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk1 -// -//---------------------------------------------------------------------------- - -void A_WizAtk1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_FaceTarget(actor, player, psp); - actor->flags &= ~MF_SHADOW; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk2 -// -//---------------------------------------------------------------------------- - -void A_WizAtk2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_FaceTarget(actor, player, psp); - actor->flags |= MF_SHADOW; -} - -//---------------------------------------------------------------------------- -// -// PROC A_WizAtk3 -// -//---------------------------------------------------------------------------- - -void A_WizAtk3(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - fixed_t momz; - - actor->flags &= ~MF_SHADOW; - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(4)); - return; - } - mo = P_SpawnMissile(actor, actor->target, MT_WIZFX1); - if (mo) - { - momz = mo->momz; - angle = mo->angle; - P_SpawnMissileAngle(actor, MT_WIZFX1, angle - (ANG45 / 8), momz); - P_SpawnMissileAngle(actor, MT_WIZFX1, angle + (ANG45 / 8), momz); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Scream -// -//---------------------------------------------------------------------------- - -void A_Scream(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - switch (actor->type) - { - case MT_CHICPLAYER: - case MT_SORCERER1: - case MT_MINOTAUR: - // Make boss death sounds full volume - S_StartSound(NULL, actor->info->deathsound); - break; - case MT_PLAYER: - // Handle the different player death screams - if (actor->special1.i < 10) - { // Wimpy death sound - S_StartSound(actor, sfx_plrwdth); - } - else if (actor->health > -50) - { // Normal death sound - S_StartSound(actor, actor->info->deathsound); - } - else if (actor->health > -100) - { // Crazy death sound - S_StartSound(actor, sfx_plrcdth); - } - else - { // Extreme death sound - S_StartSound(actor, sfx_gibdth); - } - break; - default: - S_StartSound(actor, actor->info->deathsound); - break; - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_DropItem -// -//--------------------------------------------------------------------------- - -void P_DropItem(mobj_t * source, mobjtype_t type, int special, int chance) -{ - mobj_t *mo; - - if (P_Random() > chance) - { - return; - } - mo = P_SpawnMobj(source->x, source->y, - source->z + (source->height >> 1), type); - mo->momx = P_SubRandom() << 8; - mo->momy = P_SubRandom() << 8; - mo->momz = FRACUNIT * 5 + (P_Random() << 10); - mo->flags |= MF_DROPPED; - mo->health = special; -} - -//---------------------------------------------------------------------------- -// -// PROC A_NoBlocking -// -//---------------------------------------------------------------------------- - -void A_NoBlocking(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SOLID; - // Check for monsters dropping things - switch (actor->type) - { - case MT_MUMMY: - case MT_MUMMYLEADER: - case MT_MUMMYGHOST: - case MT_MUMMYLEADERGHOST: - P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84); - break; - case MT_KNIGHT: - case MT_KNIGHTGHOST: - P_DropItem(actor, MT_AMCBOWWIMPY, 5, 84); - break; - case MT_WIZARD: - P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84); - P_DropItem(actor, MT_ARTITOMEOFPOWER, 0, 4); - break; - case MT_HEAD: - P_DropItem(actor, MT_AMBLSRWIMPY, 10, 84); - P_DropItem(actor, MT_ARTIEGG, 0, 51); - break; - case MT_BEAST: - P_DropItem(actor, MT_AMCBOWWIMPY, 10, 84); - break; - case MT_CLINK: - P_DropItem(actor, MT_AMSKRDWIMPY, 20, 84); - break; - case MT_SNAKE: - P_DropItem(actor, MT_AMPHRDWIMPY, 5, 84); - break; - case MT_MINOTAUR: - P_DropItem(actor, MT_ARTISUPERHEAL, 0, 51); - P_DropItem(actor, MT_AMPHRDWIMPY, 10, 84); - break; - default: - break; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Explode -// -// Handles a bunch of exploding things. -// -//---------------------------------------------------------------------------- - -void A_Explode(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - int damage; - - damage = 128; - switch (actor->type) - { - case MT_FIREBOMB: // Time Bombs - actor->z += 32 * FRACUNIT; - actor->flags &= ~MF_SHADOW; - break; - case MT_MNTRFX2: // Minotaur floor fire - damage = 24; - break; - case MT_SOR2FX1: // D'Sparil missile - damage = 80 + (P_Random() & 31); - break; - default: - break; - } - P_RadiusAttack(actor, actor->target, damage); - P_HitFloor(actor); -} - -//---------------------------------------------------------------------------- -// -// PROC A_PodPain -// -//---------------------------------------------------------------------------- - -void A_PodPain(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - int i; - int count; - int chance; - mobj_t *goo; - - chance = P_Random(); - if (chance < 128) - { - return; - } - count = chance > 240 ? 2 : 1; - for (i = 0; i < count; i++) - { - goo = P_SpawnMobj(actor->x, actor->y, - actor->z + 48 * FRACUNIT, MT_PODGOO); - goo->target = actor; - goo->momx = P_SubRandom() << 9; - goo->momy = P_SubRandom() << 9; - goo->momz = FRACUNIT / 2 + (P_Random() << 9); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_RemovePod -// -//---------------------------------------------------------------------------- - -void A_RemovePod(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - if (actor->special2.m) - { - mo = (mobj_t *) actor->special2.m; - if (mo->special1.i > 0) - { - mo->special1.i--; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MakePod -// -//---------------------------------------------------------------------------- - -#define MAX_GEN_PODS 16 - -void A_MakePod(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - fixed_t x; - fixed_t y; - - if (actor->special1.i == MAX_GEN_PODS) - { // Too many generated pods - return; - } - x = actor->x; - y = actor->y; - mo = P_SpawnMobj(x, y, ONFLOORZ, MT_POD); - if (P_CheckPosition(mo, x, y) == false) - { // Didn't fit - P_RemoveMobj(mo); - return; - } - P_SetMobjState(mo, S_POD_GROW1); - P_ThrustMobj(mo, P_Random() << 24, (fixed_t) (4.5 * FRACUNIT)); - S_StartSound(mo, sfx_newpod); - actor->special1.i++; // Increment generated pod count - mo->special2.m = actor; // Link the generator to the pod - return; -} - -//---------------------------------------------------------------------------- -// -// PROC P_Massacre -// -// Kills all monsters. -// -//---------------------------------------------------------------------------- - -void P_Massacre(void) -{ - mobj_t *mo; - thinker_t *think; - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - if ((mo->flags & MF_COUNTKILL) && (mo->health > 0)) - { - P_DamageMobj(mo, NULL, NULL, 10000); - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_BossDeath -// -// Trigger special effects if all bosses are dead. -// -//---------------------------------------------------------------------------- - -void A_BossDeath(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - thinker_t *think; - line_t dummyLine; - static mobjtype_t bossType[6] = { - MT_HEAD, - MT_MINOTAUR, - MT_SORCERER2, - MT_HEAD, - MT_MINOTAUR, - -1 - }; - - if (gamemap != 8) - { // Not a boss level - return; - } - if (actor->type != bossType[gameepisode - 1]) - { // Not considered a boss in this episode - return; - } - // Make sure all bosses are dead - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - if ((mo != actor) && (mo->type == actor->type) && (mo->health > 0)) - { // Found a living boss - return; - } - } - if (gameepisode > 1) - { // Kill any remaining monsters - P_Massacre(); - } - dummyLine.tag = 666; - EV_DoFloor(&dummyLine, lowerFloor); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ESound -// -//---------------------------------------------------------------------------- - -void A_ESound(mobj_t *mo, player_t *player, pspdef_t *psp) -{ - int sound = sfx_None; - - switch (mo->type) - { - case MT_SOUNDWATERFALL: - sound = sfx_waterfl; - break; - case MT_SOUNDWIND: - sound = sfx_wind; - break; - default: - break; - } - S_StartSound(mo, sound); -} - -//---------------------------------------------------------------------------- -// -// PROC A_SpawnTeleGlitter -// -//---------------------------------------------------------------------------- - -void A_SpawnTeleGlitter(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1, r2; - - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r2 & 31) - 16) * FRACUNIT, - actor->y + ((r1 & 31) - 16) * FRACUNIT, - actor->subsector->sector->floorheight, MT_TELEGLITTER); - mo->momz = FRACUNIT / 4; -} - -//---------------------------------------------------------------------------- -// -// PROC A_SpawnTeleGlitter2 -// -//---------------------------------------------------------------------------- - -void A_SpawnTeleGlitter2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1, r2; - - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r2 & 31) - 16) * FRACUNIT, - actor->y + ((r1 & 31) - 16) * FRACUNIT, - actor->subsector->sector->floorheight, MT_TELEGLITTER2); - mo->momz = FRACUNIT / 4; -} - -//---------------------------------------------------------------------------- -// -// PROC A_AccTeleGlitter -// -//---------------------------------------------------------------------------- - -void A_AccTeleGlitter(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (++actor->health > 35) - { - actor->momz += actor->momz / 2; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_InitKeyGizmo -// -//---------------------------------------------------------------------------- - -void A_InitKeyGizmo(mobj_t * gizmo, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - statenum_t state = S_NULL; - - switch (gizmo->type) - { - case MT_KEYGIZMOBLUE: - state = S_KGZ_BLUEFLOAT1; - break; - case MT_KEYGIZMOGREEN: - state = S_KGZ_GREENFLOAT1; - break; - case MT_KEYGIZMOYELLOW: - state = S_KGZ_YELLOWFLOAT1; - break; - default: - break; - } - mo = P_SpawnMobj(gizmo->x, gizmo->y, gizmo->z + 60 * FRACUNIT, - MT_KEYGIZMOFLOAT); - P_SetMobjState(mo, state); -} - -//---------------------------------------------------------------------------- -// -// PROC A_VolcanoSet -// -//---------------------------------------------------------------------------- - -void A_VolcanoSet(mobj_t * volcano, player_t *player, pspdef_t *psp) -{ - volcano->tics = 105 + (P_Random() & 127); -} - -//---------------------------------------------------------------------------- -// -// PROC A_VolcanoBlast -// -//---------------------------------------------------------------------------- - -void A_VolcanoBlast(mobj_t * volcano, player_t *player, pspdef_t *psp) -{ - int i; - int count; - mobj_t *blast; - angle_t angle; - - count = 1 + (P_Random() % 3); - for (i = 0; i < count; i++) - { - blast = P_SpawnMobj(volcano->x, volcano->y, volcano->z + 44 * FRACUNIT, MT_VOLCANOBLAST); // MT_VOLCANOBLAST - blast->target = volcano; - angle = P_Random() << 24; - blast->angle = angle; - angle >>= ANGLETOFINESHIFT; - blast->momx = FixedMul(1 * FRACUNIT, finecosine[angle]); - blast->momy = FixedMul(1 * FRACUNIT, finesine[angle]); - blast->momz = (fixed_t)(2.5 * FRACUNIT) + (P_Random() << 10); - S_StartSound(blast, sfx_volsht); - P_CheckMissileSpawn(blast); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_VolcBallImpact -// -//---------------------------------------------------------------------------- - -void A_VolcBallImpact(mobj_t * ball, player_t *player, pspdef_t *psp) -{ - unsigned int i; - mobj_t *tiny; - angle_t angle; - - if (ball->z <= ball->floorz) - { - ball->flags |= MF_NOGRAVITY; - ball->flags2 &= ~MF2_LOGRAV; - ball->z += 28 * FRACUNIT; - //ball->momz = 3*FRACUNIT; - } - P_RadiusAttack(ball, ball->target, 25); - for (i = 0; i < 4; i++) - { - tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_VOLCANOTBLAST); - tiny->target = ball; - angle = i * ANG90; - tiny->angle = angle; - angle >>= ANGLETOFINESHIFT; - tiny->momx = FixedMul((fixed_t)(FRACUNIT * .7), finecosine[angle]); - tiny->momy = FixedMul((fixed_t)(FRACUNIT * .7), finesine[angle]); - tiny->momz = FRACUNIT + (P_Random() << 9); - P_CheckMissileSpawn(tiny); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_SkullPop -// -//---------------------------------------------------------------------------- - -void A_SkullPop(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - mobj_t *mo; - player_t *player; - - actor->flags &= ~MF_SOLID; - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 48 * FRACUNIT, - MT_BLOODYSKULL); - //mo->target = actor; - mo->momx = P_SubRandom() << 9; - mo->momy = P_SubRandom() << 9; - mo->momz = FRACUNIT * 2 + (P_Random() << 6); - // Attach player mobj to bloody skull - player = actor->player; - actor->player = NULL; - mo->player = player; - mo->health = actor->health; - mo->angle = actor->angle; - - // fraggle: This check wasn't originally here in the Vanilla Heretic - // source, causing crashes if the player respawns before this - // function is called. - - if (player != NULL) - { - player->mo = mo; - player->lookdir = 0; - player->damagecount = 32; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_CheckSkullFloor -// -//---------------------------------------------------------------------------- - -void A_CheckSkullFloor(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->z <= actor->floorz) - { - P_SetMobjState(actor, S_BLOODYSKULLX1); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_CheckSkullDone -// -//---------------------------------------------------------------------------- - -void A_CheckSkullDone(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special2.i == 666) - { - P_SetMobjState(actor, S_BLOODYSKULLX2); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_CheckBurnGone -// -//---------------------------------------------------------------------------- - -void A_CheckBurnGone(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special2.i == 666) - { - P_SetMobjState(actor, S_PLAY_FDTH20); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FreeTargMobj -// -//---------------------------------------------------------------------------- - -void A_FreeTargMobj(mobj_t * mo, player_t *player, pspdef_t *psp) -{ - mo->momx = mo->momy = mo->momz = 0; - mo->z = mo->ceilingz + 4 * FRACUNIT; - mo->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_SOLID); - mo->flags |= MF_CORPSE | MF_DROPOFF | MF_NOGRAVITY; - mo->flags2 &= ~(MF2_PASSMOBJ | MF2_LOGRAV); - mo->player = NULL; -} - -//---------------------------------------------------------------------------- -// -// PROC A_AddPlayerCorpse -// -//---------------------------------------------------------------------------- - -#define BODYQUESIZE 32 -mobj_t *bodyque[BODYQUESIZE]; -int bodyqueslot; - -void A_AddPlayerCorpse(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (bodyqueslot >= BODYQUESIZE) - { // Too many player corpses - remove an old one - P_RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]); - } - bodyque[bodyqueslot % BODYQUESIZE] = actor; - bodyqueslot++; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FlameSnd -// -//---------------------------------------------------------------------------- - -void A_FlameSnd(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(actor, sfx_hedat1); // Burn sound -} - -//---------------------------------------------------------------------------- -// -// PROC A_HideThing -// -//---------------------------------------------------------------------------- - -void A_HideThing(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - //P_UnsetThingPosition(actor); - actor->flags2 |= MF2_DONTDRAW; -} - -//---------------------------------------------------------------------------- -// -// PROC A_UnHideThing -// -//---------------------------------------------------------------------------- - -void A_UnHideThing(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - //P_SetThingPosition(actor); - actor->flags2 &= ~MF2_DONTDRAW; -} diff --git a/games/NXDoom/src/heretic/p_floor.c b/games/NXDoom/src/heretic/p_floor.c deleted file mode 100644 index d95a157aa49..00000000000 --- a/games/NXDoom/src/heretic/p_floor.c +++ /dev/null @@ -1,461 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -#include "doomdef.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -//================================================================== -//================================================================== -// -// FLOORS -// -//================================================================== -//================================================================== - - - -//================================================================== -// -// Move a plane (floor or ceiling) and check for crushing -// -//================================================================== -result_e T_MovePlane(sector_t * sector, fixed_t speed, - fixed_t dest, boolean crush, int floorOrCeiling, - int direction) -{ - boolean flag; - fixed_t lastpos; - - switch (floorOrCeiling) - { - case 0: // FLOOR - switch (direction) - { - case -1: // DOWN - if (sector->floorheight - speed < dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - //return crushed; - } - return pastdest; - } - else - { - lastpos = sector->floorheight; - sector->floorheight -= speed; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - return crushed; - } - } - break; - - case 1: // UP - if (sector->floorheight + speed > dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - //return crushed; - } - return pastdest; - } - else // COULD GET CRUSHED - { - lastpos = sector->floorheight; - sector->floorheight += speed; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - if (crush == true) - return crushed; - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - return crushed; - } - } - break; - } - break; - - case 1: // CEILING - switch (direction) - { - case -1: // DOWN - if (sector->ceilingheight - speed < dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - //return crushed; - } - return pastdest; - } - else // COULD GET CRUSHED - { - lastpos = sector->ceilingheight; - sector->ceilingheight -= speed; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - if (crush == true) - return crushed; - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - return crushed; - } - } - break; - - case 1: // UP - if (sector->ceilingheight + speed > dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - //return crushed; - } - return pastdest; - } - else - { - lastpos = sector->ceilingheight; - sector->ceilingheight += speed; - flag = P_ChangeSector(sector, crush); -#if 0 - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - return crushed; - } -#endif - } - break; - } - break; - - } - return ok; -} - -//================================================================== -// -// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) -// -//================================================================== -void T_MoveFloor(thinker_t *thinker) -{ - floormove_t *floor = (floormove_t *) thinker; - result_e res; - - res = T_MovePlane(floor->sector, floor->speed, - floor->floordestheight, floor->crush, 0, - floor->direction); - if (!(leveltime & 7)) - { - S_StartSound(&floor->sector->soundorg, sfx_dormov); - } - - if (res == pastdest) - { - floor->sector->specialdata = NULL; - if (floor->type == raiseBuildStep) - { - S_StartSound(&floor->sector->soundorg, sfx_pstop); - } - if (floor->direction == 1) - switch (floor->type) - { - case donutRaise: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - else if (floor->direction == -1) - switch (floor->type) - { - case lowerAndChange: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - P_RemoveThinker(&floor->thinker); - } - -} - -//================================================================== -// -// HANDLE FLOOR TYPES -// -//================================================================== -int EV_DoFloor(line_t * line, floor_e floortype) -{ - int secnum; - int rtn; - int i; - sector_t *sec; - floormove_t *floor; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // - // new floor thinker - // - rtn = 1; - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker(&floor->thinker); - sec->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = floortype; - floor->crush = false; - switch (floortype) - { - case lowerFloor: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = P_FindHighestFloorSurrounding(sec); - break; - case lowerFloorToLowest: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = P_FindLowestFloorSurrounding(sec); - break; - case turboLower: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED * 4; - floor->floordestheight = (8 * FRACUNIT) + - P_FindHighestFloorSurrounding(sec); - break; - case raiseFloorCrush: - floor->crush = true; - case raiseFloor: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = P_FindLowestCeilingSurrounding(sec); - if (floor->floordestheight > sec->ceilingheight) - floor->floordestheight = sec->ceilingheight; - floor->floordestheight -= (8 * FRACUNIT) * - (floortype == raiseFloorCrush); - break; - case raiseFloorToNearest: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindNextHighestFloor(sec, sec->floorheight); - break; - case raiseFloor24: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 24 * FRACUNIT; - break; - case raiseFloor24AndChange: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 24 * FRACUNIT; - sec->floorpic = line->frontsector->floorpic; - sec->special = line->frontsector->special; - break; - case raiseToTexture: - { - int minsize = INT_MAX; - side_t *side; - - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - for (i = 0; i < sec->linecount; i++) - if (twoSided(secnum, i)) - { - side = getSide(secnum, i, 0); - if (side->bottomtexture >= 0) - if (textureheight[side->bottomtexture] < - minsize) - minsize = - textureheight[side->bottomtexture]; - side = getSide(secnum, i, 1); - if (side->bottomtexture >= 0) - if (textureheight[side->bottomtexture] < - minsize) - minsize = - textureheight[side->bottomtexture]; - } - floor->floordestheight = floor->sector->floorheight + - minsize; - } - break; - case lowerAndChange: - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = P_FindLowestFloorSurrounding(sec); - floor->texture = sec->floorpic; - for (i = 0; i < sec->linecount; i++) - if (twoSided(secnum, i)) - { - if (getSide(secnum, i, 0)->sector - sectors == secnum) - { - sec = getSector(secnum, i, 1); - floor->texture = sec->floorpic; - floor->newspecial = sec->special; - break; - } - else - { - sec = getSector(secnum, i, 0); - floor->texture = sec->floorpic; - floor->newspecial = sec->special; - break; - } - } - default: - break; - } - } - return rtn; -} - -//================================================================== -// -// BUILD A STAIRCASE! -// -//================================================================== -int EV_BuildStairs(line_t * line, fixed_t stepDelta) -{ - int secnum; - int height; - int i; - int newsecnum; - int texture; - int ok; - int rtn; - sector_t *sec, *tsec; - floormove_t *floor; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // - // new floor thinker - // - rtn = 1; - height = sec->floorheight + stepDelta; - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker(&floor->thinker); - sec->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = raiseBuildStep; - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = height; - - texture = sec->floorpic; - - // - // Find next sector to raise - // 1. Find 2-sided line with same sector side[0] - // 2. Other side is the next sector to raise - // - do - { - ok = 0; - for (i = 0; i < sec->linecount; i++) - { - if (!((sec->lines[i])->flags & ML_TWOSIDED)) - continue; - - tsec = (sec->lines[i])->frontsector; - newsecnum = tsec - sectors; - if (secnum != newsecnum) - continue; - tsec = (sec->lines[i])->backsector; - newsecnum = tsec - sectors; - if (tsec->floorpic != texture) - continue; - - height += stepDelta; - if (tsec->specialdata) - continue; - - sec = tsec; - secnum = newsecnum; - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker(&floor->thinker); - sec->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = raiseBuildStep; - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = height; - ok = 1; - break; - } - } - while (ok); - } - return (rtn); -} diff --git a/games/NXDoom/src/heretic/p_inter.c b/games/NXDoom/src/heretic/p_inter.c deleted file mode 100644 index cf75a7dbf35..00000000000 --- a/games/NXDoom/src/heretic/p_inter.c +++ /dev/null @@ -1,1488 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_inter.c - -#include "doomdef.h" -#include "deh_str.h" -#include "i_system.h" -#include "i_timer.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "am_map.h" - - -#define BONUSADD 6 - -int WeaponValue[] = { - 1, // staff - 3, // goldwand - 4, // crossbow - 5, // blaster - 6, // skullrod - 7, // phoenixrod - 8, // mace - 2, // gauntlets - 0 // beak -}; - -int maxammo[NUMAMMO] = { - 100, // gold wand - 50, // crossbow - 200, // blaster - 200, // skull rod - 20, // phoenix rod - 150 // mace -}; - -int GetWeaponAmmo[NUMWEAPONS] = { - 0, // staff - 25, // gold wand - 10, // crossbow - 30, // blaster - 50, // skull rod - 2, // phoenix rod - 50, // mace - 0, // gauntlets - 0 // beak -}; - -static weapontype_t GetAmmoChange[] = { - wp_goldwand, - wp_crossbow, - wp_blaster, - wp_skullrod, - wp_phoenixrod, - wp_mace -}; - -/* -static boolean GetAmmoChangePL1[NUMWEAPONS][NUMAMMO] = -{ - // staff - {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace}, - // gold wand - {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace}, - // crossbow - {-1, -1, wp_blaster, wp_skullrod, -1, -1}, - // blaster - {-1, -1, -1, -1, -1, -1}, - // skull rod - {-1, -1, -1, -1, -1, -1}, - // phoenix rod - {-1, -1, -1, -1, -1, -1}, - // mace - {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1}, - // gauntlets - {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace} -}; -*/ - -/* -static boolean GetAmmoChangePL2[NUMWEAPONS][NUMAMMO] = -{ - // staff - {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod, - wp_mace}, - // gold wand - {-1, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod, wp_mace}, - // crossbow - {-1, -1, wp_blaster, wp_skullrod, wp_phoenixrod, -1}, - // blaster - {-1, -1, -1, wp_skullrod, wp_phoenixrod, -1}, - // skull rod - {-1, -1, -1, -1, -1, -1}, - // phoenix rod - {-1, -1, -1, -1, -1, -1}, - // mace - {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1}, - // gauntlets - {-1, -1, -1, wp_skullrod, wp_phoenixrod, wp_mace} -}; -*/ - -//-------------------------------------------------------------------------- -// -// PROC P_SetMessage -// -//-------------------------------------------------------------------------- - -boolean ultimatemsg; - -void P_SetMessage(player_t * player, const char *message, boolean ultmsg) -{ - if ((ultimatemsg || !messageson) && !ultmsg) - { - return; - } - player->message = message; - player->messageTics = MESSAGETICS; - BorderTopRefresh = true; - if (ultmsg) - { - ultimatemsg = true; - } -} - -//-------------------------------------------------------------------------- -// -// FUNC P_GiveAmmo -// -// Returns true if the player accepted the ammo, false if it was -// refused (player has maxammo[ammo]). -// -//-------------------------------------------------------------------------- - -boolean P_GiveAmmo(player_t * player, ammotype_t ammo, int count) -{ - int prevAmmo; - //weapontype_t changeWeapon; - - if (ammo == am_noammo) - { - return (false); - } - if ((unsigned int) ammo >= NUMAMMO) - { - I_Error("P_GiveAmmo: bad type %i", ammo); - } - if (player->ammo[ammo] == player->maxammo[ammo]) - { - return (false); - } - if (gameskill == sk_baby || gameskill == sk_nightmare) - { // extra ammo in baby mode and nightmare mode - count += count >> 1; - } - prevAmmo = player->ammo[ammo]; - - player->ammo[ammo] += count; - if (player->ammo[ammo] > player->maxammo[ammo]) - { - player->ammo[ammo] = player->maxammo[ammo]; - } - if (prevAmmo) - { - // Don't attempt to change weapons if the player already had - // ammo of the type just given - return (true); - } - if (player->readyweapon == wp_staff - || player->readyweapon == wp_gauntlets) - { - if (player->weaponowned[GetAmmoChange[ammo]]) - { - player->pendingweapon = GetAmmoChange[ammo]; - } - } -/* - if(player->powers[pw_weaponlevel2]) - { - changeWeapon = GetAmmoChangePL2[player->readyweapon][ammo]; - } - else - { - changeWeapon = GetAmmoChangePL1[player->readyweapon][ammo]; - } - if(changeWeapon != -1) - { - if(player->weaponowned[changeWeapon]) - { - player->pendingweapon = changeWeapon; - } - } -*/ - return (true); -} - -//-------------------------------------------------------------------------- -// -// FUNC P_GiveWeapon -// -// Returns true if the weapon or its ammo was accepted. -// -//-------------------------------------------------------------------------- - -boolean P_GiveWeapon(player_t * player, weapontype_t weapon) -{ - boolean gaveAmmo; - boolean gaveWeapon; - - if (netgame && !deathmatch) - { // Cooperative net-game - if (player->weaponowned[weapon]) - { - return (false); - } - player->bonuscount += BONUSADD; - player->weaponowned[weapon] = true; - P_GiveAmmo(player, wpnlev1info[weapon].ammo, GetWeaponAmmo[weapon]); - player->pendingweapon = weapon; - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, sfx_wpnup); - } - return (false); - } - gaveAmmo = P_GiveAmmo(player, wpnlev1info[weapon].ammo, - GetWeaponAmmo[weapon]); - if (player->weaponowned[weapon]) - { - gaveWeapon = false; - } - else - { - gaveWeapon = true; - player->weaponowned[weapon] = true; - if (WeaponValue[weapon] > WeaponValue[player->readyweapon]) - { // Only switch to more powerful weapons - player->pendingweapon = weapon; - } - } - return (gaveWeapon || gaveAmmo); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GiveBody -// -// Returns false if the body isn't needed at all. -// -//--------------------------------------------------------------------------- - -boolean P_GiveBody(player_t * player, int num) -{ - int max; - - max = MAXHEALTH; - if (player->chickenTics) - { - max = MAXCHICKENHEALTH; - } - if (player->health >= max) - { - return (false); - } - player->health += num; - if (player->health > max) - { - player->health = max; - } - player->mo->health = player->health; - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GiveArmor -// -// Returns false if the armor is worse than the current armor. -// -//--------------------------------------------------------------------------- - -boolean P_GiveArmor(player_t * player, int armortype) -{ - int hits; - - hits = armortype * 100; - if (player->armorpoints >= hits) - { - return (false); - } - player->armortype = armortype; - player->armorpoints = hits; - return (true); -} - -//--------------------------------------------------------------------------- -// -// PROC P_GiveKey -// -//--------------------------------------------------------------------------- - -void P_GiveKey(player_t * player, keytype_t key) -{ - - if (player->keys[key]) - { - return; - } - if (player == &players[consoleplayer]) - { - playerkeys |= 1 << key; - KeyPoints[key].x = 0; - KeyPoints[key].y = 0; - } - player->bonuscount = BONUSADD; - player->keys[key] = true; -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GivePower -// -// Returns true if power accepted. -// -//--------------------------------------------------------------------------- - -boolean P_GivePower(player_t * player, powertype_t power) -{ - if (power == pw_invulnerability) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = INVULNTICS; - return (true); - } - if (power == pw_weaponlevel2) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = WPNLEV2TICS; - return (true); - } - if (power == pw_invisibility) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = INVISTICS; - player->mo->flags |= MF_SHADOW; - return (true); - } - if (power == pw_flight) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = FLIGHTTICS; - player->mo->flags2 |= MF2_FLY; - player->mo->flags |= MF_NOGRAVITY; - if (player->mo->z <= player->mo->floorz) - { - player->flyheight = 10; // thrust the player in the air a bit - } - return (true); - } - if (power == pw_infrared) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = INFRATICS; - return (true); - } -/* - if(power == pw_ironfeet) - { - player->powers[power] = IRONTICS; - return(true); - } - if(power == pw_strength) - { - P_GiveBody(player, 100); - player->powers[power] = 1; - return(true); - } -*/ - if (player->powers[power]) - { - return (false); // already got it - } - player->powers[power] = 1; - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GiveArtifact -// -// Returns true if artifact accepted. -// -//--------------------------------------------------------------------------- - -boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo) -{ - int i; - - i = 0; - while (player->inventory[i].type != arti && i < player->inventorySlotNum) - { - i++; - } - if (i == player->inventorySlotNum) - { - player->inventory[i].count = 1; - player->inventory[i].type = arti; - player->inventorySlotNum++; - } - else - { - if (player->inventory[i].count >= 16) - { // Player already has 16 of this item - return (false); - } - player->inventory[i].count++; - } - if (player->artifactCount == 0) - { - player->readyArtifact = arti; - } - player->artifactCount++; - if (mo && (mo->flags & MF_COUNTITEM)) - { - player->itemcount++; - } - return (true); -} - -//--------------------------------------------------------------------------- -// -// PROC P_SetDormantArtifact -// -// Removes the MF_SPECIAL flag, and initiates the artifact pickup -// animation. -// -//--------------------------------------------------------------------------- - -void P_SetDormantArtifact(mobj_t * arti) -{ - arti->flags &= ~MF_SPECIAL; - if (deathmatch && (arti->type != MT_ARTIINVULNERABILITY) - && (arti->type != MT_ARTIINVISIBILITY)) - { - P_SetMobjState(arti, S_DORMANTARTI1); - } - else - { // Don't respawn - P_SetMobjState(arti, S_DEADARTI1); - } - S_StartSound(arti, sfx_artiup); -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreArtifact -// -//--------------------------------------------------------------------------- - -void A_RestoreArtifact(mobj_t * arti, player_t *player, pspdef_t *psp) -{ - arti->flags |= MF_SPECIAL; - P_SetMobjState(arti, arti->info->spawnstate); - S_StartSound(arti, sfx_respawn); -} - -//---------------------------------------------------------------------------- -// -// PROC P_HideSpecialThing -// -//---------------------------------------------------------------------------- - -void P_HideSpecialThing(mobj_t * thing) -{ - thing->flags &= ~MF_SPECIAL; - thing->flags2 |= MF2_DONTDRAW; - P_SetMobjState(thing, S_HIDESPECIAL1); -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialThing1 -// -// Make a special thing visible again. -// -//--------------------------------------------------------------------------- - -void A_RestoreSpecialThing1(mobj_t * thing, player_t *player, pspdef_t *psp) -{ - if (thing->type == MT_WMACE) - { // Do random mace placement - P_RepositionMace(thing); - } - thing->flags2 &= ~MF2_DONTDRAW; - S_StartSound(thing, sfx_respawn); -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialThing2 -// -//--------------------------------------------------------------------------- - -void A_RestoreSpecialThing2(mobj_t * thing, player_t *player, pspdef_t *psp) -{ - thing->flags |= MF_SPECIAL; - P_SetMobjState(thing, thing->info->spawnstate); -} - -//--------------------------------------------------------------------------- -// -// PROC P_TouchSpecialThing -// -//--------------------------------------------------------------------------- - -void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher) -{ - int i; - player_t *player; - fixed_t delta; - int sound; - boolean respawn; - - delta = special->z - toucher->z; - if (delta > toucher->height || delta < -32 * FRACUNIT) - { // Out of reach - return; - } - if (toucher->health <= 0) - { // Toucher is dead - return; - } - sound = sfx_itemup; - player = toucher->player; - respawn = true; - switch (special->sprite) - { - // Items - case SPR_PTN1: // Item_HealingPotion - if (!P_GiveBody(player, 10)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_ITEMHEALTH), false); - break; - case SPR_SHLD: // Item_Shield1 - if (!P_GiveArmor(player, 1)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_ITEMSHIELD1), false); - break; - case SPR_SHD2: // Item_Shield2 - if (!P_GiveArmor(player, 2)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_ITEMSHIELD2), false); - break; - case SPR_BAGH: // Item_BagOfHolding - if (!player->backpack) - { - for (i = 0; i < NUMAMMO; i++) - { - player->maxammo[i] *= 2; - } - player->backpack = true; - } - P_GiveAmmo(player, am_goldwand, AMMO_GWND_WIMPY); - P_GiveAmmo(player, am_blaster, AMMO_BLSR_WIMPY); - P_GiveAmmo(player, am_crossbow, AMMO_CBOW_WIMPY); - P_GiveAmmo(player, am_skullrod, AMMO_SKRD_WIMPY); - P_GiveAmmo(player, am_phoenixrod, AMMO_PHRD_WIMPY); - P_SetMessage(player, DEH_String(TXT_ITEMBAGOFHOLDING), false); - break; - case SPR_SPMP: // Item_SuperMap - if (!P_GivePower(player, pw_allmap)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_ITEMSUPERMAP), false); - break; - - // Keys - case SPR_BKYY: // Key_Blue - if (!player->keys[key_blue]) - { - P_SetMessage(player, DEH_String(TXT_GOTBLUEKEY), false); - } - P_GiveKey(player, key_blue); - sound = sfx_keyup; - if (!netgame) - { - break; - } - return; - case SPR_CKYY: // Key_Yellow - if (!player->keys[key_yellow]) - { - P_SetMessage(player, DEH_String(TXT_GOTYELLOWKEY), false); - } - sound = sfx_keyup; - P_GiveKey(player, key_yellow); - if (!netgame) - { - break; - } - return; - case SPR_AKYY: // Key_Green - if (!player->keys[key_green]) - { - P_SetMessage(player, DEH_String(TXT_GOTGREENKEY), false); - } - sound = sfx_keyup; - P_GiveKey(player, key_green); - if (!netgame) - { - break; - } - return; - - // Artifacts - case SPR_PTN2: // Arti_HealingPotion - if (P_GiveArtifact(player, arti_health, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTIHEALTH), false); - P_SetDormantArtifact(special); - } - return; - case SPR_SOAR: // Arti_Fly - if (P_GiveArtifact(player, arti_fly, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTIFLY), false); - P_SetDormantArtifact(special); - } - return; - case SPR_INVU: // Arti_Invulnerability - if (P_GiveArtifact(player, arti_invulnerability, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTIINVULNERABILITY), false); - P_SetDormantArtifact(special); - } - return; - case SPR_PWBK: // Arti_TomeOfPower - if (P_GiveArtifact(player, arti_tomeofpower, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTITOMEOFPOWER), false); - P_SetDormantArtifact(special); - } - return; - case SPR_INVS: // Arti_Invisibility - if (P_GiveArtifact(player, arti_invisibility, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTIINVISIBILITY), false); - P_SetDormantArtifact(special); - } - return; - case SPR_EGGC: // Arti_Egg - if (P_GiveArtifact(player, arti_egg, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTIEGG), false); - P_SetDormantArtifact(special); - } - return; - case SPR_SPHL: // Arti_SuperHealth - if (P_GiveArtifact(player, arti_superhealth, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTISUPERHEALTH), false); - P_SetDormantArtifact(special); - } - return; - case SPR_TRCH: // Arti_Torch - if (P_GiveArtifact(player, arti_torch, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTITORCH), false); - P_SetDormantArtifact(special); - } - return; - case SPR_FBMB: // Arti_FireBomb - if (P_GiveArtifact(player, arti_firebomb, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTIFIREBOMB), false); - P_SetDormantArtifact(special); - } - return; - case SPR_ATLP: // Arti_Teleport - if (P_GiveArtifact(player, arti_teleport, special)) - { - P_SetMessage(player, DEH_String(TXT_ARTITELEPORT), false); - P_SetDormantArtifact(special); - } - return; - - // Ammo - case SPR_AMG1: // Ammo_GoldWandWimpy - if (!P_GiveAmmo(player, am_goldwand, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOGOLDWAND1), false); - break; - case SPR_AMG2: // Ammo_GoldWandHefty - if (!P_GiveAmmo(player, am_goldwand, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOGOLDWAND2), false); - break; - case SPR_AMM1: // Ammo_MaceWimpy - if (!P_GiveAmmo(player, am_mace, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOMACE1), false); - break; - case SPR_AMM2: // Ammo_MaceHefty - if (!P_GiveAmmo(player, am_mace, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOMACE2), false); - break; - case SPR_AMC1: // Ammo_CrossbowWimpy - if (!P_GiveAmmo(player, am_crossbow, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOCROSSBOW1), false); - break; - case SPR_AMC2: // Ammo_CrossbowHefty - if (!P_GiveAmmo(player, am_crossbow, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOCROSSBOW2), false); - break; - case SPR_AMB1: // Ammo_BlasterWimpy - if (!P_GiveAmmo(player, am_blaster, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOBLASTER1), false); - break; - case SPR_AMB2: // Ammo_BlasterHefty - if (!P_GiveAmmo(player, am_blaster, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOBLASTER2), false); - break; - case SPR_AMS1: // Ammo_SkullRodWimpy - if (!P_GiveAmmo(player, am_skullrod, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOSKULLROD1), false); - break; - case SPR_AMS2: // Ammo_SkullRodHefty - if (!P_GiveAmmo(player, am_skullrod, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOSKULLROD2), false); - break; - case SPR_AMP1: // Ammo_PhoenixRodWimpy - if (!P_GiveAmmo(player, am_phoenixrod, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOPHOENIXROD1), false); - break; - case SPR_AMP2: // Ammo_PhoenixRodHefty - if (!P_GiveAmmo(player, am_phoenixrod, special->health)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_AMMOPHOENIXROD2), false); - break; - - // Weapons - case SPR_WMCE: // Weapon_Mace - if (!P_GiveWeapon(player, wp_mace)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_WPNMACE), false); - sound = sfx_wpnup; - break; - case SPR_WBOW: // Weapon_Crossbow - if (!P_GiveWeapon(player, wp_crossbow)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_WPNCROSSBOW), false); - sound = sfx_wpnup; - break; - case SPR_WBLS: // Weapon_Blaster - if (!P_GiveWeapon(player, wp_blaster)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_WPNBLASTER), false); - sound = sfx_wpnup; - break; - case SPR_WSKL: // Weapon_SkullRod - if (!P_GiveWeapon(player, wp_skullrod)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_WPNSKULLROD), false); - sound = sfx_wpnup; - break; - case SPR_WPHX: // Weapon_PhoenixRod - if (!P_GiveWeapon(player, wp_phoenixrod)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_WPNPHOENIXROD), false); - sound = sfx_wpnup; - break; - case SPR_WGNT: // Weapon_Gauntlets - if (!P_GiveWeapon(player, wp_gauntlets)) - { - return; - } - P_SetMessage(player, DEH_String(TXT_WPNGAUNTLETS), false); - sound = sfx_wpnup; - break; - default: - I_Error("P_SpecialThing: Unknown gettable thing"); - } - if (special->flags & MF_COUNTITEM) - { - player->itemcount++; - } - if (deathmatch && respawn && !(special->flags & MF_DROPPED)) - { - P_HideSpecialThing(special); - } - else - { - P_RemoveMobj(special); - } - player->bonuscount += BONUSADD; - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, sound); - SB_PaletteFlash(); - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_KillMobj -// -//--------------------------------------------------------------------------- - -void P_KillMobj(mobj_t * source, mobj_t * target) -{ - target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_NOGRAVITY); - target->flags |= MF_CORPSE | MF_DROPOFF; - target->flags2 &= ~MF2_PASSMOBJ; - target->height >>= 2; - if (source && source->player) - { - if (target->flags & MF_COUNTKILL) - { // Count for intermission - source->player->killcount++; - } - if (target->player) - { // Frag stuff - if (target == source) - { // Self-frag - target->player->frags[target->player - players]--; - } - else - { - source->player->frags[target->player - players]++; - if (source->player == &players[consoleplayer]) - { - S_StartSound(NULL, sfx_gfrag); - } - if (source->player->chickenTics) - { // Make a super chicken - P_GivePower(source->player, pw_weaponlevel2); - } - } - } - } - else if (!netgame && (target->flags & MF_COUNTKILL)) - { // Count all monster deaths - players[0].killcount++; - } - if (target->player) - { - if (!source) - { // Self-frag - target->player->frags[target->player - players]--; - } - target->flags &= ~MF_SOLID; - target->flags2 &= ~MF2_FLY; - target->player->powers[pw_flight] = 0; - target->player->powers[pw_weaponlevel2] = 0; - target->player->playerstate = PST_DEAD; - P_DropWeapon(target->player); - if (target->flags2 & MF2_FIREDAMAGE) - { // Player flame death - P_SetMobjState(target, S_PLAY_FDTH1); - //S_StartSound(target, sfx_hedat1); // Burn sound - return; - } - } - if (target->health < -(target->info->spawnhealth >> 1) - && target->info->xdeathstate) - { // Extreme death - P_SetMobjState(target, target->info->xdeathstate); - } - else - { // Normal death - P_SetMobjState(target, target->info->deathstate); - } - target->tics -= P_Random() & 3; -// I_StartSound(&actor->r, actor->info->deathsound); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_MinotaurSlam -// -//--------------------------------------------------------------------------- - -void P_MinotaurSlam(mobj_t * source, mobj_t * target) -{ - angle_t angle; - fixed_t thrust; - - angle = R_PointToAngle2(source->x, source->y, target->x, target->y); - angle >>= ANGLETOFINESHIFT; - thrust = 16 * FRACUNIT + (P_Random() << 10); - target->momx += FixedMul(thrust, finecosine[angle]); - target->momy += FixedMul(thrust, finesine[angle]); - P_DamageMobj(target, NULL, NULL, HITDICE(6)); - if (target->player) - { - target->reactiontime = 14 + (P_Random() & 7); - } -} - -//--------------------------------------------------------------------------- -// -// FUNC P_TouchWhirlwind -// -//--------------------------------------------------------------------------- - -void P_TouchWhirlwind(mobj_t * target) -{ - int randVal; - - target->angle += P_SubRandom() << 20; - target->momx += P_SubRandom() << 10; - target->momy += P_SubRandom() << 10; - if (leveltime & 16 && !(target->flags2 & MF2_BOSS)) - { - randVal = P_Random(); - if (randVal > 160) - { - randVal = 160; - } - target->momz += randVal << 10; - if (target->momz > 12 * FRACUNIT) - { - target->momz = 12 * FRACUNIT; - } - } - if (!(leveltime & 7)) - { - P_DamageMobj(target, NULL, NULL, 3); - } -} - -//--------------------------------------------------------------------------- -// -// FUNC P_ChickenMorphPlayer -// -// Returns true if the player gets turned into a chicken. -// -//--------------------------------------------------------------------------- - -boolean P_ChickenMorphPlayer(player_t * player) -{ - mobj_t *pmo; - mobj_t *fog; - mobj_t *chicken; - fixed_t x; - fixed_t y; - fixed_t z; - angle_t angle; - int oldFlags2; - - if (player->chickenTics) - { - if ((player->chickenTics < CHICKENTICS - TICRATE) - && !player->powers[pw_weaponlevel2]) - { // Make a super chicken - P_GivePower(player, pw_weaponlevel2); - } - return (false); - } - if (player->powers[pw_invulnerability]) - { // Immune when invulnerable - return (false); - } - pmo = player->mo; - x = pmo->x; - y = pmo->y; - z = pmo->z; - angle = pmo->angle; - oldFlags2 = pmo->flags2; - P_SetMobjState(pmo, S_FREETARGMOBJ); - fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, sfx_telept); - chicken = P_SpawnMobj(x, y, z, MT_CHICPLAYER); - chicken->special1.i = player->readyweapon; - chicken->angle = angle; - chicken->player = player; - player->health = chicken->health = MAXCHICKENHEALTH; - player->mo = chicken; - player->armorpoints = player->armortype = 0; - player->powers[pw_invisibility] = 0; - player->powers[pw_weaponlevel2] = 0; - if (oldFlags2 & MF2_FLY) - { - chicken->flags2 |= MF2_FLY; - } - player->chickenTics = CHICKENTICS; - P_ActivateBeak(player); - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_ChickenMorph -// -//--------------------------------------------------------------------------- - -boolean P_ChickenMorph(mobj_t * actor) -{ - mobj_t *fog; - mobj_t *chicken; - mobj_t *target; - mobjtype_t moType; - fixed_t x; - fixed_t y; - fixed_t z; - angle_t angle; - int ghost; - - if (actor->player) - { - return (false); - } - moType = actor->type; - switch (moType) - { - case MT_POD: - case MT_CHICKEN: - case MT_HEAD: - case MT_MINOTAUR: - case MT_SORCERER1: - case MT_SORCERER2: - return (false); - default: - break; - } - x = actor->x; - y = actor->y; - z = actor->z; - angle = actor->angle; - ghost = actor->flags & MF_SHADOW; - target = actor->target; - P_SetMobjState(actor, S_FREETARGMOBJ); - fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, sfx_telept); - chicken = P_SpawnMobj(x, y, z, MT_CHICKEN); - chicken->special2.i = moType; - chicken->special1.i = CHICKENTICS + P_Random(); - chicken->flags |= ghost; - chicken->target = target; - chicken->angle = angle; - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_AutoUseChaosDevice -// -//--------------------------------------------------------------------------- - -boolean P_AutoUseChaosDevice(player_t * player) -{ - int i; - - for (i = 0; i < player->inventorySlotNum; i++) - { - if (player->inventory[i].type == arti_teleport) - { - P_PlayerUseArtifact(player, arti_teleport); - player->health = player->mo->health = (player->health + 1) / 2; - return (true); - } - } - return (false); -} - -//--------------------------------------------------------------------------- -// -// PROC P_AutoUseHealth -// -//--------------------------------------------------------------------------- - -void P_AutoUseHealth(player_t * player, int saveHealth) -{ - int i; - int count; - int normalCount; - int normalSlot; - int superCount; - int superSlot; - - normalCount = 0; - superCount = 0; - normalSlot = 0; - superSlot = 0; - - for (i = 0; i < player->inventorySlotNum; i++) - { - if (player->inventory[i].type == arti_health) - { - normalSlot = i; - normalCount = player->inventory[i].count; - } - else if (player->inventory[i].type == arti_superhealth) - { - superSlot = i; - superCount = player->inventory[i].count; - } - } - if ((gameskill == sk_baby) && (normalCount * 25 >= saveHealth)) - { // Use quartz flasks - count = (saveHealth + 24) / 25; - for (i = 0; i < count; i++) - { - player->health += 25; - P_PlayerRemoveArtifact(player, normalSlot); - } - } - else if (superCount * 100 >= saveHealth) - { // Use mystic urns - count = (saveHealth + 99) / 100; - for (i = 0; i < count; i++) - { - player->health += 100; - P_PlayerRemoveArtifact(player, superSlot); - } - } - else if ((gameskill == sk_baby) - && (superCount * 100 + normalCount * 25 >= saveHealth)) - { // Use mystic urns and quartz flasks - count = (saveHealth + 24) / 25; - saveHealth -= count * 25; - for (i = 0; i < count; i++) - { - player->health += 25; - P_PlayerRemoveArtifact(player, normalSlot); - } - count = (saveHealth + 99) / 100; - for (i = 0; i < count; i++) - { - player->health += 100; - P_PlayerRemoveArtifact(player, normalSlot); - } - } - player->mo->health = player->health; -} - -/* -================= -= -= P_DamageMobj -= -= Damages both enemies and players -= inflictor is the thing that caused the damage -= creature or missile, can be NULL (slime, etc) -= source is the thing to target after taking damage -= creature or NULL -= Source and inflictor are the same for melee attacks -= source can be null for barrel explosions and other environmental stuff -================== -*/ - -void P_DamageMobj - (mobj_t * target, mobj_t * inflictor, mobj_t * source, int damage) -{ - unsigned ang; - int saved; - player_t *player; - fixed_t thrust; - int temp; - - if (!(target->flags & MF_SHOOTABLE)) - { - // Shouldn't happen - return; - } - if (target->health <= 0) - { - return; - } - if (target->flags & MF_SKULLFLY) - { - if (target->type == MT_MINOTAUR) - { // Minotaur is invulnerable during charge attack - return; - } - target->momx = target->momy = target->momz = 0; - } - player = target->player; - if (player && gameskill == sk_baby) - { - // Take half damage in trainer mode - damage >>= 1; - } - // Special damage types - if (inflictor) - { - switch (inflictor->type) - { - case MT_EGGFX: - if (player) - { - P_ChickenMorphPlayer(player); - } - else - { - P_ChickenMorph(target); - } - return; // Always return - case MT_WHIRLWIND: - P_TouchWhirlwind(target); - return; - case MT_MINOTAUR: - if (inflictor->flags & MF_SKULLFLY) - { // Slam only when in charge mode - P_MinotaurSlam(inflictor, target); - return; - } - break; - case MT_MACEFX4: // Death ball - if ((target->flags2 & MF2_BOSS) || target->type == MT_HEAD) - { // Don't allow cheap boss kills - break; - } - else if (target->player) - { // Player specific checks - if (target->player->powers[pw_invulnerability]) - { // Can't hurt invulnerable players - break; - } - if (P_AutoUseChaosDevice(target->player)) - { // Player was saved using chaos device - return; - } - } - damage = 10000; // Something's gonna die - break; - case MT_PHOENIXFX2: // Flame thrower - if (target->player && P_Random() < 128) - { // Freeze player for a bit - target->reactiontime += 4; - } - break; - case MT_RAINPLR1: // Rain missiles - case MT_RAINPLR2: - case MT_RAINPLR3: - case MT_RAINPLR4: - if (target->flags2 & MF2_BOSS) - { // Decrease damage for bosses - damage = (P_Random() & 7) + 1; - } - break; - case MT_HORNRODFX2: - case MT_PHOENIXFX1: - if (target->type == MT_SORCERER2 && P_Random() < 96) - { // D'Sparil teleports away - P_DSparilTeleport(target); - return; - } - break; - case MT_BLASTERFX1: - case MT_RIPPER: - if (target->type == MT_HEAD) - { // Less damage to Ironlich bosses - damage = P_Random() & 1; - if (!damage) - { - return; - } - } - break; - default: - break; - } - } - // Push the target unless source is using the gauntlets - if (inflictor && (!source || !source->player - || source->player->readyweapon != wp_gauntlets) - && !(inflictor->flags2 & MF2_NODMGTHRUST)) - { - ang = R_PointToAngle2(inflictor->x, inflictor->y, - target->x, target->y); - //thrust = damage*(FRACUNIT>>3)*100/target->info->mass; - // We do this multiplication in unsigned because it might overflow - // and signed overflow is undefined behavior - // but then we must cast it back to signed for the division - // to match original behavior - // unsigned to signed cast is implementation defined behavior at worst - thrust = ((int) (damage * (FRACUNIT >> 3) * 150u)) / target->info->mass; - // make fall forwards sometimes - if ((damage < 40) && (damage > target->health) - && (target->z - inflictor->z > 64 * FRACUNIT) && (P_Random() & 1)) - { - ang += ANG180; - thrust *= 4; - } - ang >>= ANGLETOFINESHIFT; - if (source && source->player && (source == inflictor) - && source->player->powers[pw_weaponlevel2] - && source->player->readyweapon == wp_staff) - { - // Staff power level 2 - target->momx += FixedMul(10 * FRACUNIT, finecosine[ang]); - target->momy += FixedMul(10 * FRACUNIT, finesine[ang]); - if (!(target->flags & MF_NOGRAVITY)) - { - target->momz += 5 * FRACUNIT; - } - } - else - { - target->momx += FixedMul(thrust, finecosine[ang]); - target->momy += FixedMul(thrust, finesine[ang]); - } - } - - // - // player specific - // - if (player) - { - // end of game hell hack - //if(target->subsector->sector->special == 11 - // && damage >= target->health) - //{ - // damage = target->health - 1; - //} - - if (damage < 1000 && ((player->cheats & CF_GODMODE) - || player->powers[pw_invulnerability])) - { - return; - } - if (player->armortype) - { - if (player->armortype == 1) - { - saved = damage >> 1; - } - else - { - saved = (damage >> 1) + (damage >> 2); - } - if (player->armorpoints <= saved) - { - // armor is used up - saved = player->armorpoints; - player->armortype = 0; - } - player->armorpoints -= saved; - damage -= saved; - } - if (damage >= player->health - && ((gameskill == sk_baby) || deathmatch) && !player->chickenTics) - { // Try to use some inventory health - P_AutoUseHealth(player, damage - player->health + 1); - } - player->health -= damage; // mirror mobj health here for Dave - if (player->health < 0) - { - player->health = 0; - } - player->attacker = source; - player->damagecount += damage; // add damage after armor / invuln - if (player->damagecount > 100) - { - player->damagecount = 100; // teleport stomp does 10k points... - } - temp = damage < 100 ? damage : 100; - if (player == &players[consoleplayer]) - { - I_Tactile(40, 10, 40 + temp * 2); - SB_PaletteFlash(); - } - } - - // - // do the damage - // - target->health -= damage; - if (target->health <= 0) - { // Death - target->special1.i = damage; - if (target->type == MT_POD && source && source->type != MT_POD) - { // Make sure players get frags for chain-reaction kills - target->target = source; - } - if (player && inflictor && !player->chickenTics) - { // Check for flame death - if ((inflictor->flags2 & MF2_FIREDAMAGE) - || ((inflictor->type == MT_PHOENIXFX1) - && (target->health > -50) && (damage > 25))) - { - target->flags2 |= MF2_FIREDAMAGE; - } - } - P_KillMobj(source, target); - return; - } - if ((P_Random() < target->info->painchance) - && !(target->flags & MF_SKULLFLY)) - { - target->flags |= MF_JUSTHIT; // fight back! - P_SetMobjState(target, target->info->painstate); - } - target->reactiontime = 0; // we're awake now... - if (!target->threshold && source && !(source->flags2 & MF2_BOSS) - && !(target->type == MT_SORCERER2 && source->type == MT_WIZARD)) - { - // Target actor is not intent on another actor, - // so make him chase after source - target->target = source; - target->threshold = BASETHRESHOLD; - if (target->state == &states[target->info->spawnstate] - && target->info->seestate != S_NULL) - { - P_SetMobjState(target, target->info->seestate); - } - } -} diff --git a/games/NXDoom/src/heretic/p_lights.c b/games/NXDoom/src/heretic/p_lights.c deleted file mode 100644 index 407041b3c05..00000000000 --- a/games/NXDoom/src/heretic/p_lights.c +++ /dev/null @@ -1,280 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -#include "doomdef.h" -#include "m_random.h" -#include "p_local.h" -#include "v_video.h" - -//================================================================== -//================================================================== -// -// BROKEN LIGHT FLASHING -// -//================================================================== -//================================================================== - -//================================================================== -// -// T_LightFlash -// -// After the map has been loaded, scan each sector for specials -// that spawn thinkers -// -//================================================================== -void T_LightFlash(thinker_t *thinker) -{ - lightflash_t *flash = (lightflash_t *) thinker; - - if (--flash->count) - return; - - if (flash->sector->lightlevel == flash->maxlight) - { - flash->sector->lightlevel = flash->minlight; - flash->count = (P_Random() & flash->mintime) + 1; - } - else - { - flash->sector->lightlevel = flash->maxlight; - flash->count = (P_Random() & flash->maxtime) + 1; - } - -} - - -//================================================================== -// -// P_SpawnLightFlash -// -// After the map has been loaded, scan each sector for specials that spawn thinkers -// -//================================================================== -void P_SpawnLightFlash(sector_t * sector) -{ - lightflash_t *flash; - - sector->special = 0; // nothing special about it during gameplay - - flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0); - P_AddThinker(&flash->thinker); - flash->thinker.function = T_LightFlash; - flash->sector = sector; - flash->maxlight = sector->lightlevel; - - flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); - flash->maxtime = 64; - flash->mintime = 7; - flash->count = (P_Random() & flash->maxtime) + 1; -} - -//================================================================== -// -// STROBE LIGHT FLASHING -// -//================================================================== - -//================================================================== -// -// T_StrobeFlash -// -// After the map has been loaded, scan each sector for specials that spawn thinkers -// -//================================================================== -void T_StrobeFlash(thinker_t *thinker) -{ - strobe_t *flash = (strobe_t *) thinker; - - if (--flash->count) - return; - - if (flash->sector->lightlevel == flash->minlight) - { - flash->sector->lightlevel = flash->maxlight; - flash->count = flash->brighttime; - } - else - { - flash->sector->lightlevel = flash->minlight; - flash->count = flash->darktime; - } - -} - -//================================================================== -// -// P_SpawnLightFlash -// -// After the map has been loaded, scan each sector for specials that spawn thinkers -// -//================================================================== -void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync) -{ - strobe_t *flash; - - flash = Z_Malloc(sizeof(*flash), PU_LEVSPEC, 0); - P_AddThinker(&flash->thinker); - flash->sector = sector; - flash->darktime = fastOrSlow; - flash->brighttime = STROBEBRIGHT; - flash->thinker.function = T_StrobeFlash; - flash->maxlight = sector->lightlevel; - flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); - - if (flash->minlight == flash->maxlight) - flash->minlight = 0; - sector->special = 0; // nothing special about it during gameplay - - if (!inSync) - flash->count = (P_Random() & 7) + 1; - else - flash->count = 1; -} - -//================================================================== -// -// Start strobing lights (usually from a trigger) -// -//================================================================== -void EV_StartLightStrobing(line_t * line) -{ - int secnum; - sector_t *sec; - - secnum = -1; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - P_SpawnStrobeFlash(sec, SLOWDARK, 0); - } -} - -//================================================================== -// -// TURN LINE'S TAG LIGHTS OFF -// -//================================================================== -void EV_TurnTagLightsOff(line_t * line) -{ - int i; - int j; - int min; - sector_t *sector; - sector_t *tsec; - line_t *templine; - - sector = sectors; - for (j = 0; j < numsectors; j++, sector++) - if (sector->tag == line->tag) - { - min = sector->lightlevel; - for (i = 0; i < sector->linecount; i++) - { - templine = sector->lines[i]; - tsec = getNextSector(templine, sector); - if (!tsec) - continue; - if (tsec->lightlevel < min) - min = tsec->lightlevel; - } - sector->lightlevel = min; - } -} - -//================================================================== -// -// TURN LINE'S TAG LIGHTS ON -// -//================================================================== -void EV_LightTurnOn(line_t * line, int bright) -{ - int i; - int j; - sector_t *sector; - sector_t *temp; - line_t *templine; - - sector = sectors; - - for (i = 0; i < numsectors; i++, sector++) - if (sector->tag == line->tag) - { - // - // bright = 0 means to search for highest - // light level surrounding sector - // - if (!bright) - { - for (j = 0; j < sector->linecount; j++) - { - templine = sector->lines[j]; - temp = getNextSector(templine, sector); - if (!temp) - continue; - if (temp->lightlevel > bright) - bright = temp->lightlevel; - } - } - sector->lightlevel = bright; - } -} - -//================================================================== -// -// Spawn glowing light -// -//================================================================== -void T_Glow(thinker_t *thinker) -{ - glow_t *g = (glow_t *) thinker; - - switch (g->direction) - { - case -1: // DOWN - g->sector->lightlevel -= GLOWSPEED; - if (g->sector->lightlevel <= g->minlight) - { - g->sector->lightlevel += GLOWSPEED; - g->direction = 1; - } - break; - case 1: // UP - g->sector->lightlevel += GLOWSPEED; - if (g->sector->lightlevel >= g->maxlight) - { - g->sector->lightlevel -= GLOWSPEED; - g->direction = -1; - } - break; - } -} - -void P_SpawnGlowingLight(sector_t * sector) -{ - glow_t *g; - - g = Z_Malloc(sizeof(*g), PU_LEVSPEC, 0); - P_AddThinker(&g->thinker); - g->sector = sector; - g->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); - g->maxlight = sector->lightlevel; - g->thinker.function = T_Glow; - g->direction = -1; - - sector->special = 0; -} diff --git a/games/NXDoom/src/heretic/p_local.h b/games/NXDoom/src/heretic/p_local.h deleted file mode 100644 index 6137d3d0d67..00000000000 --- a/games/NXDoom/src/heretic/p_local.h +++ /dev/null @@ -1,292 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_local.h - -#ifndef __P_LOCAL__ -#define __P_LOCAL__ - -#ifndef __R_LOCAL__ -#include "r_local.h" -#endif - -#define STARTREDPALS 1 -#define STARTBONUSPALS 9 -#define NUMREDPALS 8 -#define NUMBONUSPALS 4 - -#define FOOTCLIPSIZE 10*FRACUNIT - -#define TOCENTER -8 -#define FLOATSPEED (FRACUNIT*4) - -#define MAXHEALTH 100 -#define MAXCHICKENHEALTH 30 -#define VIEWHEIGHT (41*FRACUNIT) - -// mapblocks are used to check movement against lines and things -#define MAPBLOCKUNITS 128 -#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) -#define MAPBLOCKSHIFT (FRACBITS+7) -#define MAPBMASK (MAPBLOCKSIZE-1) -#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) - -// player radius for movement checking -#define PLAYERRADIUS 16*FRACUNIT - -// MAXRADIUS is for precalculated sector block boxes -// the spider demon is larger, but we don't have any moving sectors -// nearby -#define MAXRADIUS 32*FRACUNIT - -#define GRAVITY FRACUNIT -#define MAXMOVE (30*FRACUNIT) - -#define USERANGE (64*FRACUNIT) -#define MELEERANGE (64*FRACUNIT) -#define MISSILERANGE (32*64*FRACUNIT) - -typedef enum -{ - DI_EAST, - DI_NORTHEAST, - DI_NORTH, - DI_NORTHWEST, - DI_WEST, - DI_SOUTHWEST, - DI_SOUTH, - DI_SOUTHEAST, - DI_NODIR, - NUMDIRS -} dirtype_t; - -#define BASETHRESHOLD 100 // follow a player exlusively for 3 seconds - -// ***** P_TICK ***** - -extern thinker_t thinkercap; // both the head and tail of the thinker list -extern int TimerGame; // tic countdown for deathmatch - -void P_InitThinkers(void); -void P_AddThinker(thinker_t * thinker); -void P_RemoveThinker(thinker_t * thinker); - -// ***** P_PSPR ***** - -#define USE_GWND_AMMO_1 1 -#define USE_GWND_AMMO_2 1 -#define USE_CBOW_AMMO_1 1 -#define USE_CBOW_AMMO_2 1 -#define USE_BLSR_AMMO_1 1 -#define USE_BLSR_AMMO_2 5 -#define USE_SKRD_AMMO_1 1 -#define USE_SKRD_AMMO_2 5 -#define USE_PHRD_AMMO_1 1 -#define USE_PHRD_AMMO_2 1 -#define USE_MACE_AMMO_1 1 -#define USE_MACE_AMMO_2 5 - -void P_OpenWeapons(void); -void P_CloseWeapons(void); -void P_AddMaceSpot(mapthing_t * mthing); -void P_RepositionMace(mobj_t * mo); -void P_SetPsprite(player_t * player, int position, statenum_t stnum); -void P_SetupPsprites(player_t * curplayer); -void P_MovePsprites(player_t * curplayer); -void P_DropWeapon(player_t * player); -void P_ActivateBeak(player_t * player); -void P_PostChickenWeapon(player_t * player, weapontype_t weapon); -void P_UpdateBeak(player_t * player, pspdef_t * psp); - -// ***** P_USER ***** - -void P_PlayerThink(player_t * player); -void P_Thrust(player_t * player, angle_t angle, fixed_t move); -void P_PlayerRemoveArtifact(player_t * player, int slot); -void P_PlayerUseArtifact(player_t * player, artitype_t arti); -boolean P_UseArtifact(player_t * player, artitype_t arti); -int P_GetPlayerNum(player_t * player); -boolean P_UndoPlayerChicken(player_t *player); - - -// ***** P_MOBJ ***** - -#define FLOOR_SOLID 0 -#define FLOOR_WATER 1 -#define FLOOR_LAVA 2 -#define FLOOR_SLUDGE 3 - -#define ONFLOORZ INT_MIN -#define ONCEILINGZ INT_MAX -#define FLOATRANDZ (INT_MAX-1) - -extern mobjtype_t PuffType; -extern mobj_t *MissileMobj; - -mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); -void P_RemoveMobj(mobj_t * th); -boolean P_SetMobjState(mobj_t * mobj, statenum_t state); -boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state); -void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move); -int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta); -boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax); -void P_MobjThinker(thinker_t *thinker); -void P_BlasterMobjThinker(thinker_t *thinker); -void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z); -void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage); -void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator); -void P_RipperBlood(mobj_t * mo); -int P_GetThingFloorType(mobj_t * thing); -int P_HitFloor(mobj_t * thing); -boolean P_CheckMissileSpawn(mobj_t * missile); -mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type); -mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, - angle_t angle, fixed_t momz); -mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type); -mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle); - -// ***** P_ENEMY ***** - -void P_NoiseAlert(mobj_t * target, mobj_t * emmiter); -void P_InitMonsters(void); -void P_AddBossSpot(fixed_t x, fixed_t y, angle_t angle); -void P_Massacre(void); -void P_DSparilTeleport(mobj_t * actor); - -// ***** P_MAPUTL ***** - -typedef struct -{ - fixed_t x, y, dx, dy; -} divline_t; - -typedef struct -{ - fixed_t frac; // along trace line - boolean isaline; - union - { - mobj_t *thing; - line_t *line; - } d; -} intercept_t; - -#define MAXINTERCEPTS 128 -extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p; -typedef boolean(*traverser_t) (intercept_t * in); - - -fixed_t P_AproxDistance(fixed_t dx, fixed_t dy); -int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line); -int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line); -void P_MakeDivline(line_t * li, divline_t * dl); -fixed_t P_InterceptVector(divline_t * v2, divline_t * v1); -int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld); - -extern fixed_t opentop, openbottom, openrange; -extern fixed_t lowfloor; -void P_LineOpening(line_t * linedef); - -boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)); -boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)); - -#define PT_ADDLINES 1 -#define PT_ADDTHINGS 2 -#define PT_EARLYOUT 4 - -extern divline_t trace; -boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, - int flags, boolean(*trav) (intercept_t *)); - -void P_UnsetThingPosition(mobj_t * thing); -void P_SetThingPosition(mobj_t * thing); - -// ***** P_MAP ***** - -extern boolean floatok; // if true, move would be ok if -extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz - -extern line_t *ceilingline; -boolean P_TestMobjLocation(mobj_t * mobj); -boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y); -mobj_t *P_CheckOnmobj(mobj_t * thing); -void P_FakeZMovement(mobj_t * mo); -boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y); -boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y); -void P_SlideMove(mobj_t * mo); - -extern fixed_t topslope, bottomslope; // slopes to top and bottom of target - -boolean P_CheckSight(mobj_t * t1, mobj_t * t2); -void P_UseLines(player_t * player); - -boolean P_ChangeSector(sector_t * sector, boolean crunch); - -extern mobj_t *linetarget; // who got hit (or NULL) -fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance); - -void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, - int damage); - -void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage); - -#define MAXSPECIALCROSS 8 -extern line_t *spechit[MAXSPECIALCROSS]; -extern int numspechit; - - -// ***** P_SETUP ***** - -extern byte *rejectmatrix; // for fast sight rejection -extern short *blockmaplump; // offsets in blockmap are from here -extern short *blockmap; -extern int bmapwidth, bmapheight; // in mapblocks -extern fixed_t bmaporgx, bmaporgy; // origin of block map -extern mobj_t **blocklinks; // for thing chains - -// ***** P_INTER ***** - -extern int maxammo[NUMAMMO]; -extern int clipammo[NUMAMMO]; - -extern boolean messageson; - - -void P_SetMessage(player_t * player, const char *message, boolean ultmsg); -void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher); -void P_DamageMobj(mobj_t * target, mobj_t * inflictor, mobj_t * source, - int damage); -boolean P_GiveAmmo(player_t * player, ammotype_t ammo, int count); -boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo); -boolean P_GiveBody(player_t * player, int num); -boolean P_GivePower(player_t * player, powertype_t power); -boolean P_ChickenMorphPlayer(player_t * player); - -// ***** AM_MAP ***** - -boolean AM_Responder(event_t * ev); -void AM_Ticker(void); -void AM_Drawer(void); - -// ***** SB_BAR ***** - -extern int SB_state; -extern int ArtifactFlash; -void SB_PaletteFlash(void); - -#include "p_spec.h" - -#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/heretic/p_map.c b/games/NXDoom/src/heretic/p_map.c deleted file mode 100644 index ba56697707b..00000000000 --- a/games/NXDoom/src/heretic/p_map.c +++ /dev/null @@ -1,1696 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// P_map.c - -#include - -#include "doomdef.h" -#include "i_system.h" -#include "m_bbox.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" - -/* -=============================================================================== - -NOTES: - - -=============================================================================== -*/ - -/* -=============================================================================== - -mobj_t NOTES - -mobj_ts are used to tell the refresh where to draw an image, tell the world -simulation when objects are contacted, and tell the sound driver how to -position a sound. - -The refresh uses the next and prev links to follow lists of things in sectors -as they are being drawn. The sprite, frame, and angle elements determine which -patch_t is used to draw the sprite if it is visible. The sprite and frame -values are allmost allways set from state_t structures. The statescr.exe -utility generates the states.h and states.c files that contain the sprite/frame -numbers from the statescr.txt source file. The xyz origin point represents a -point at the bottom middle of the sprite (between the feet of a biped). This -is the default origin position for patch_ts grabbed with lumpy.exe. A walking -creature will have its z equal to the floor it is standing on. - -The sound code uses the x,y, and subsector fields to do stereo positioning of -any sound effited by the mobj_t. - -The play simulation uses the blocklinks, x,y,z, radius, height to determine -when mobj_ts are touching each other, touching lines in the map, or hit by -trace lines (gunshots, lines of sight, etc). The mobj_t->flags element has -various bit flags used by the simulation. - - -Every mobj_t is linked into a single sector based on it's origin coordinates. -The subsector_t is found with R_PointInSubsector(x,y), and the sector_t can be -found with subsector->sector. The sector links are only used by the rendering -code, the play simulation does not care about them at all. - -Any mobj_t that needs to be acted upon be something else in the play world -(block movement, be shot, etc) will also need to be linked into the blockmap. -If the thing has the MF_NOBLOCK flag set, it will not use the block links. It -can still interact with other things, but only as the instigator (missiles will -run into other things, but nothing can run into a missile). Each block in -the grid is 128*128 units, and knows about every line_t that it contains a -piece of, and every interactable mobj_t that has it's origin contained. - -A valid mobj_t is a mobj_t that has the proper subsector_t filled in for it's -xy coordinates and is linked into the subsector's sector or has the MF_NOSECTOR -flag set (the subsector_t needs to be valid even if MF_NOSECTOR is set), and is -linked into a blockmap block or has the MF_NOBLOCKMAP flag set. Links should -only be modified by the P_[Un]SetThingPosition () functions. Do not change -the MF_NO? flags while a thing is valid. - - -=============================================================================== -*/ - -fixed_t tmbbox[4]; -mobj_t *tmthing; -int tmflags; -fixed_t tmx, tmy; - -boolean floatok; // if true, move would be ok if - // within tmfloorz - tmceilingz - -fixed_t tmfloorz, tmceilingz, tmdropoffz; - -// keep track of the line that lowers the ceiling, so missiles don't explode -// against sky hack walls -line_t *ceilingline; - -// keep track of special lines as they are hit, but don't process them -// until the move is proven valid -#define MAXSPECIALCROSS 8 -line_t *spechit[MAXSPECIALCROSS]; -int numspechit; - -mobj_t *onmobj; //generic global onmobj...used for landing on pods/players - -/* -=============================================================================== - - TELEPORT MOVE - -=============================================================================== -*/ - -/* -================== -= -= PIT_StompThing -= -================== -*/ - -boolean PIT_StompThing(mobj_t * thing) -{ - fixed_t blockdist; - - if (!(thing->flags & MF_SHOOTABLE)) - return true; - - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - return true; // didn't hit it - - if (thing == tmthing) - return true; // don't clip against self - - if (!(tmthing->flags2 & MF2_TELESTOMP)) - { // Not allowed to stomp things - return (false); - } - - P_DamageMobj(thing, tmthing, tmthing, 10000); - - return true; -} - - -/* -=================== -= -= P_TeleportMove -= -=================== -*/ - -boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y) -{ - int xl, xh, yl, yh, bx, by; - subsector_t *newsubsec; - -// -// kill anything occupying the position -// - - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; - -// -// the base floor / ceiling is from the subsector that contains the -// point. Any contacted lines the step closer together will adjust them -// - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - -// -// stomp on any things contacted -// - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_StompThing)) - return false; - -// -// the move is ok, so link the thing into its new position -// - P_UnsetThingPosition(thing); - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - - P_SetThingPosition(thing); - - return true; -} - -/* -=============================================================================== - - MOVEMENT ITERATOR FUNCTIONS - -=============================================================================== -*/ - -/* -================== -= -= PIT_CheckLine -= -= Adjusts tmfloorz and tmceilingz as lines are contacted -================== -*/ - -boolean PIT_CheckLine(line_t * ld) -{ - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - { - return (true); - } - if (P_BoxOnLineSide(tmbbox, ld) != -1) - { - return (true); - } - -// a line has been hit -/* -= -= The moving thing's destination position will cross the given line. -= If this should not be allowed, return false. -= If the line is special, keep track of it to process later if the move -= is proven ok. NOTE: specials are NOT sorted by order, so two special lines -= that are only 8 pixels apart could be crossed in either order. -*/ - - if (!ld->backsector) - { // One sided line - if (tmthing->flags & MF_MISSILE) - { // Missiles can trigger impact specials - if (ld->special) - { - spechit[numspechit] = ld; - numspechit++; - } - } - return false; - } - if (!(tmthing->flags & MF_MISSILE)) - { - if (ld->flags & ML_BLOCKING) - { // Explicitly blocking everything - return (false); - } - if (!tmthing->player && ld->flags & ML_BLOCKMONSTERS - && tmthing->type != MT_POD) - { // Block monsters only - return (false); - } - } - P_LineOpening(ld); // set openrange, opentop, openbottom - // adjust floor / ceiling heights - if (opentop < tmceilingz) - { - tmceilingz = opentop; - ceilingline = ld; - } - if (openbottom > tmfloorz) - { - tmfloorz = openbottom; - } - if (lowfloor < tmdropoffz) - { - tmdropoffz = lowfloor; - } - if (ld->special) - { // Contacted a special line, add it to the list - spechit[numspechit] = ld; - numspechit++; - } - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC PIT_CheckThing -// -//--------------------------------------------------------------------------- - -boolean PIT_CheckThing(mobj_t * thing) -{ - fixed_t blockdist; - boolean solid; - int damage; - - if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) - { // Can't hit thing - return (true); - } - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - { // Didn't hit thing - return (true); - } - if (thing == tmthing) - { // Don't clip against self - return (true); - } - if (tmthing->flags2 & MF2_PASSMOBJ) - { // check if a mobj passed over/under another object - if ((tmthing->type == MT_IMP || tmthing->type == MT_WIZARD) - && (thing->type == MT_IMP || thing->type == MT_WIZARD)) - { // don't let imps/wizards fly over other imps/wizards - return false; - } - if (tmthing->z > thing->z + thing->height - && !(thing->flags & MF_SPECIAL)) - { - return (true); - } - else if (tmthing->z + tmthing->height < thing->z - && !(thing->flags & MF_SPECIAL)) - { // under thing - return (true); - } - } - // Check for skulls slamming into things - if (tmthing->flags & MF_SKULLFLY) - { - damage = ((P_Random() % 8) + 1) * tmthing->damage; - P_DamageMobj(thing, tmthing, tmthing, damage); - tmthing->flags &= ~MF_SKULLFLY; - tmthing->momx = tmthing->momy = tmthing->momz = 0; - P_SetMobjState(tmthing, tmthing->info->seestate); - return (false); - } - // Check for missile - if (tmthing->flags & MF_MISSILE) - { - // Check for passing through a ghost - if ((thing->flags & MF_SHADOW) && (tmthing->flags2 & MF2_THRUGHOST)) - { - return (true); - } - // Check if it went over / under - if (tmthing->z > thing->z + thing->height) - { // Over thing - return (true); - } - if (tmthing->z + tmthing->height < thing->z) - { // Under thing - return (true); - } - if (tmthing->target && tmthing->target->type == thing->type) - { // Don't hit same species as originator - if (thing == tmthing->target) - { // Don't missile self - return (true); - } - if (thing->type != MT_PLAYER) - { // Hit same species as originator, explode, no damage - return (false); - } - } - if (!(thing->flags & MF_SHOOTABLE)) - { // Didn't do any damage - return !(thing->flags & MF_SOLID); - } - if (tmthing->flags2 & MF2_RIP) - { - if (!(thing->flags & MF_NOBLOOD)) - { // Ok to spawn some blood - P_RipperBlood(tmthing); - } - S_StartSound(tmthing, sfx_ripslop); - damage = ((P_Random() & 3) + 2) * tmthing->damage; - P_DamageMobj(thing, tmthing, tmthing->target, damage); - if (thing->flags2 & MF2_PUSHABLE - && !(tmthing->flags2 & MF2_CANNOTPUSH)) - { // Push thing - thing->momx += tmthing->momx >> 2; - thing->momy += tmthing->momy >> 2; - } - numspechit = 0; - return (true); - } - // Do damage - damage = ((P_Random() % 8) + 1) * tmthing->damage; - if (damage) - { - if (!(thing->flags & MF_NOBLOOD) && P_Random() < 192) - { - P_BloodSplatter(tmthing->x, tmthing->y, tmthing->z, thing); - } - P_DamageMobj(thing, tmthing, tmthing->target, damage); - } - return (false); - } - if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH)) - { // Push thing - thing->momx += tmthing->momx >> 2; - thing->momy += tmthing->momy >> 2; - } - // Check for special thing - if (thing->flags & MF_SPECIAL) - { - solid = (thing->flags & MF_SOLID) != 0; - if (tmflags & MF_PICKUP) - { // Can be picked up by tmthing - P_TouchSpecialThing(thing, tmthing); // Can remove thing - } - return (!solid); - } - return (!(thing->flags & MF_SOLID)); -} - -//--------------------------------------------------------------------------- -// -// PIT_CheckOnmobjZ -// -//--------------------------------------------------------------------------- - -boolean PIT_CheckOnmobjZ(mobj_t * thing) -{ - fixed_t blockdist; - - if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) - { // Can't hit thing - return (true); - } - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - { // Didn't hit thing - return (true); - } - if (thing == tmthing) - { // Don't clip against self - return (true); - } - if (tmthing->z > thing->z + thing->height) - { - return (true); - } - else if (tmthing->z + tmthing->height < thing->z) - { // under thing - return (true); - } - if (thing->flags & MF_SOLID) - { - onmobj = thing; - } - return (!(thing->flags & MF_SOLID)); -} - -/* -=============================================================================== - - MOVEMENT CLIPPING - -=============================================================================== -*/ - -//---------------------------------------------------------------------------- -// -// FUNC P_TestMobjLocation -// -// Returns true if the mobj is not blocked by anything at its current -// location, otherwise returns false. -// -//---------------------------------------------------------------------------- - -boolean P_TestMobjLocation(mobj_t * mobj) -{ - int flags; - - flags = mobj->flags; - mobj->flags &= ~MF_PICKUP; - if (P_CheckPosition(mobj, mobj->x, mobj->y)) - { // XY is ok, now check Z - mobj->flags = flags; - if ((mobj->z < mobj->floorz) - || (mobj->z + mobj->height > mobj->ceilingz)) - { // Bad Z - return (false); - } - return (true); - } - mobj->flags = flags; - return (false); -} - -/* -================== -= -= P_CheckPosition -= -= This is purely informative, nothing is modified (except things picked up) - -in: -a mobj_t (can be valid or invalid) -a position to be checked (doesn't need to be related to the mobj_t->x,y) - -during: -special things are touched if MF_PICKUP -early out on solid lines? - -out: -newsubsec -floorz -ceilingz -tmdropoffz the lowest point contacted (monsters won't move to a dropoff) -speciallines[] -numspeciallines - -================== -*/ - -boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y) -{ - int xl, xh, yl, yh, bx, by; - subsector_t *newsubsec; - - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; - -// -// the base floor / ceiling is from the subsector that contains the -// point. Any contacted lines the step closer together will adjust them -// - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - - if (tmflags & MF_NOCLIP) - return true; - -// -// check things first, possibly picking things up -// the bounding box is extended by MAXRADIUS because mobj_ts are grouped -// into mapblocks based on their origin point, and can overlap into adjacent -// blocks by up to MAXRADIUS units -// - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) - return false; -// -// check lines -// - xl = (tmbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockLinesIterator(bx, by, PIT_CheckLine)) - return false; - - return true; -} - -//============================================================================= -// -// P_CheckOnmobj(mobj_t *thing) -// -// Checks if the new Z position is legal -//============================================================================= - -mobj_t *P_CheckOnmobj(mobj_t * thing) -{ - int xl, xh, yl, yh, bx, by; - subsector_t *newsubsec; - fixed_t x; - fixed_t y; - mobj_t oldmo; - - x = thing->x; - y = thing->y; - tmthing = thing; - tmflags = thing->flags; - oldmo = *thing; // save the old mobj before the fake zmovement - P_FakeZMovement(tmthing); - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; - -// -// the base floor / ceiling is from the subsector that contains the -// point. Any contacted lines the step closer together will adjust them -// - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - - if (tmflags & MF_NOCLIP) - return NULL; - -// -// check things first, possibly picking things up -// the bounding box is extended by MAXRADIUS because mobj_ts are grouped -// into mapblocks based on their origin point, and can overlap into adjacent -// blocks by up to MAXRADIUS units -// - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_CheckOnmobjZ)) - { - *tmthing = oldmo; - return onmobj; - } - *tmthing = oldmo; - return NULL; -} - -//============================================================================= -// -// P_FakeZMovement -// -// Fake the zmovement so that we can check if a move is legal -//============================================================================= - -void P_FakeZMovement(mobj_t * mo) -{ - int dist; - int delta; -// -// adjust height -// - mo->z += mo->momz; - if (mo->flags & MF_FLOAT && mo->target) - { // float down towards target if too close - if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) - { - dist = - P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); - delta = (mo->target->z + (mo->height >> 1)) - mo->z; - if (delta < 0 && dist < -(delta * 3)) - mo->z -= FLOATSPEED; - else if (delta > 0 && dist < (delta * 3)) - mo->z += FLOATSPEED; - } - } - if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) - && leveltime & 2) - { - mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; - } - -// -// clip movement -// - if (mo->z <= mo->floorz) - { // Hit the floor - mo->z = mo->floorz; - if (mo->momz < 0) - { - mo->momz = 0; - } - if (mo->flags & MF_SKULLFLY) - { // The skull slammed into something - mo->momz = -mo->momz; - } - if (mo->info->crashstate && (mo->flags & MF_CORPSE)) - { - return; - } - } - else if (mo->flags2 & MF2_LOGRAV) - { - if (mo->momz == 0) - mo->momz = -(GRAVITY >> 3) * 2; - else - mo->momz -= GRAVITY >> 3; - } - else if (!(mo->flags & MF_NOGRAVITY)) - { - if (mo->momz == 0) - mo->momz = -GRAVITY * 2; - else - mo->momz -= GRAVITY; - } - - if (mo->z + mo->height > mo->ceilingz) - { // hit the ceiling - if (mo->momz > 0) - mo->momz = 0; - mo->z = mo->ceilingz - mo->height; - if (mo->flags & MF_SKULLFLY) - { // the skull slammed into something - mo->momz = -mo->momz; - } - } -} - -//========================================================================== -// -// CheckMissileImpact -// -//========================================================================== - -void CheckMissileImpact(mobj_t * mobj) -{ - int i; - - if (!numspechit || !(mobj->flags & MF_MISSILE) || !mobj->target) - { - return; - } - if (!mobj->target->player) - { - return; - } - for (i = numspechit - 1; i >= 0; i--) - { - P_ShootSpecialLine(mobj->target, spechit[i]); - } -} - -/* -=================== -= -= P_TryMove -= -= Attempt to move to a new position, crossing special lines unless MF_TELEPORT -= is set -= -=================== -*/ - -boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y) -{ - fixed_t oldx, oldy; - int side, oldside; - line_t *ld; - - floatok = false; - if (!P_CheckPosition(thing, x, y)) - { // Solid wall or thing - CheckMissileImpact(thing); - return false; - } - if (!(thing->flags & MF_NOCLIP)) - { - if (tmceilingz - tmfloorz < thing->height) - { // Doesn't fit - CheckMissileImpact(thing); - return false; - } - floatok = true; - if (!(thing->flags & MF_TELEPORT) - && tmceilingz - thing->z < thing->height - && !(thing->flags2 & MF2_FLY)) - { // mobj must lower itself to fit - CheckMissileImpact(thing); - return false; - } - if (thing->flags2 & MF2_FLY) - { - if (thing->z + thing->height > tmceilingz) - { - thing->momz = -8 * FRACUNIT; - return false; - } - else if (thing->z < tmfloorz - && tmfloorz - tmdropoffz > 24 * FRACUNIT) - { - thing->momz = 8 * FRACUNIT; - return false; - } - } - if (!(thing->flags & MF_TELEPORT) - // The Minotaur floor fire (MT_MNTRFX2) can step up any amount - && thing->type != MT_MNTRFX2 - && tmfloorz - thing->z > 24 * FRACUNIT) - { // Too big a step up - CheckMissileImpact(thing); - return false; - } - if ((thing->flags & MF_MISSILE) && tmfloorz > thing->z) - { - CheckMissileImpact(thing); - } - if (!(thing->flags & (MF_DROPOFF | MF_FLOAT)) - && tmfloorz - tmdropoffz > 24 * FRACUNIT) - { // Can't move over a dropoff - return false; - } - } - -// -// the move is ok, so link the thing into its new position -// - P_UnsetThingPosition(thing); - - oldx = thing->x; - oldy = thing->y; - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - - P_SetThingPosition(thing); - - if (thing->flags2 & MF2_FOOTCLIP - && P_GetThingFloorType(thing) != FLOOR_SOLID) - { - thing->flags2 |= MF2_FEETARECLIPPED; - } - else if (thing->flags2 & MF2_FEETARECLIPPED) - { - thing->flags2 &= ~MF2_FEETARECLIPPED; - } - -// -// if any special lines were hit, do the effect -// - if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) - while (numspechit--) - { - // see if the line was crossed - ld = spechit[numspechit]; - side = P_PointOnLineSide(thing->x, thing->y, ld); - oldside = P_PointOnLineSide(oldx, oldy, ld); - if (side != oldside) - { - if (ld->special) - P_CrossSpecialLine(ld - lines, oldside, thing); - } - } - - return true; -} - -/* -================== -= -= P_ThingHeightClip -= -= Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, -= anf possibly thing->z -= -= This is called for all nearby monsters whenever a sector changes height -= -= If the thing doesn't fit, the z will be set to the lowest value and -= false will be returned -================== -*/ - -boolean P_ThingHeightClip(mobj_t * thing) -{ - boolean onfloor; - - onfloor = (thing->z == thing->floorz); - - P_CheckPosition(thing, thing->x, thing->y); - // what about stranding a monster partially off an edge? - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - - if (onfloor) - // walking monsters rise and fall with the floor - thing->z = thing->floorz; - else - { // don't adjust a floating monster unless forced to - if (thing->z + thing->height > thing->ceilingz) - thing->z = thing->ceilingz - thing->height; - } - - if (thing->ceilingz - thing->floorz < thing->height) - return false; - - return true; -} - - -/* -============================================================================== - - SLIDE MOVE - -Allows the player to slide along any angled walls - -============================================================================== -*/ - -fixed_t bestslidefrac, secondslidefrac; -line_t *bestslideline, *secondslideline; -mobj_t *slidemo; - -fixed_t tmxmove, tmymove; - -/* -================== -= -= P_HitSlideLine -= -= Adjusts the xmove / ymove so that the next move will slide along the wall -================== -*/ - -void P_HitSlideLine(line_t * ld) -{ - int side; - angle_t lineangle, moveangle, deltaangle; - fixed_t movelen, newlen; - - - if (ld->slopetype == ST_HORIZONTAL) - { - tmymove = 0; - return; - } - if (ld->slopetype == ST_VERTICAL) - { - tmxmove = 0; - return; - } - - side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - - lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); - if (side == 1) - lineangle += ANG180; - moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); - deltaangle = moveangle - lineangle; - if (deltaangle > ANG180) - deltaangle += ANG180; -// I_Error ("SlideLine: ang>ANG180"); - - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance(tmxmove, tmymove); - newlen = FixedMul(movelen, finecosine[deltaangle]); - tmxmove = FixedMul(newlen, finecosine[lineangle]); - tmymove = FixedMul(newlen, finesine[lineangle]); -} - -/* -============== -= -= PTR_SlideTraverse -= -============== -*/ - -boolean PTR_SlideTraverse(intercept_t * in) -{ - line_t *li; - - if (!in->isaline) - I_Error("PTR_SlideTraverse: not a line?"); - - li = in->d.line; - if (!(li->flags & ML_TWOSIDED)) - { - if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) - return true; // don't hit the back side - goto isblocking; - } - - P_LineOpening(li); // set openrange, opentop, openbottom - if (openrange < slidemo->height) - goto isblocking; // doesn't fit - - if (opentop - slidemo->z < slidemo->height) - goto isblocking; // mobj is too high - - if (openbottom - slidemo->z > 24 * FRACUNIT) - goto isblocking; // too big a step up - - return true; // this line doesn't block movement - -// the line does block movement, see if it is closer than best so far - isblocking: - if (in->frac < bestslidefrac) - { - secondslidefrac = bestslidefrac; - secondslideline = bestslideline; - bestslidefrac = in->frac; - bestslideline = li; - } - - return false; // stop -} - - -/* -================== -= -= P_SlideMove -= -= The momx / momy move is bad, so try to slide along a wall -= -= Find the first line hit, move flush to it, and slide along it -= -= This is a kludgy mess. -================== -*/ - -void P_SlideMove(mobj_t * mo) -{ - fixed_t leadx, leady; - fixed_t trailx, traily; - fixed_t newx, newy; - int hitcount; - - slidemo = mo; - hitcount = 0; - retry: - if (++hitcount == 3) - goto stairstep; // don't loop forever - -// -// trace along the three leading corners -// - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; - - P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - -// -// move up to the wall -// - if (bestslidefrac == FRACUNIT + 1) - { // the move most have hit the middle, so stairstep - stairstep: - if (!P_TryMove(mo, mo->x, mo->y + mo->momy)) - P_TryMove(mo, mo->x + mo->momx, mo->y); - return; - } - - bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit - if (bestslidefrac > 0) - { - newx = FixedMul(mo->momx, bestslidefrac); - newy = FixedMul(mo->momy, bestslidefrac); - if (!P_TryMove(mo, mo->x + newx, mo->y + newy)) - goto stairstep; - } - -// -// now continue along the wall -// - bestslidefrac = FRACUNIT - (bestslidefrac + 0x800); // remainder - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - if (bestslidefrac <= 0) - return; - - tmxmove = FixedMul(mo->momx, bestslidefrac); - tmymove = FixedMul(mo->momy, bestslidefrac); - - P_HitSlideLine(bestslideline); // clip the moves - - mo->momx = tmxmove; - mo->momy = tmymove; - - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove)) - { - goto retry; - } -} - - - -/* -============================================================================== - - P_LineAttack - -============================================================================== -*/ - - -mobj_t *linetarget; // who got hit (or NULL) -mobj_t *shootthing; -fixed_t shootz; // height if not aiming up or down - // ???: use slope for monsters? -int la_damage; -fixed_t attackrange; - -fixed_t aimslope; - - -/* -=============================================================================== -= -= PTR_AimTraverse -= -= Sets linetaget and aimslope when a target is aimed at -=============================================================================== -*/ - -boolean PTR_AimTraverse(intercept_t * in) -{ - line_t *li; - mobj_t *th; - fixed_t slope, thingtopslope, thingbottomslope; - fixed_t dist; - - if (in->isaline) - { - li = in->d.line; - if (!(li->flags & ML_TWOSIDED)) - return false; // stop -// -// crosses a two sided line -// a two sided line will restrict the possible target ranges - P_LineOpening(li); - - if (openbottom >= opentop) - return false; // stop - - dist = FixedMul(attackrange, in->frac); - - // Added checks if there is no backsector to prevent crashing. - // Crashes didn't happen in the DOS version of Heretic - // because reading NULL pointer produces unpredictable but - // deterministic values instead of crashing. - // See https://github.com/chocolate-doom/chocolate-doom/issues/1665 - if (li->backsector == NULL - || li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv(openbottom - shootz, dist); - if (slope > bottomslope) - bottomslope = slope; - } - - if (li->backsector == NULL - || li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv(opentop - shootz, dist); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - - return true; // shot continues - } - -// -// shoot a thing -// - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - if (!(th->flags & MF_SHOOTABLE)) - return true; // corpse or something - if (th->type == MT_POD) - { // Can't auto-aim at pods - return (true); - } - -// check angles to see if the thing can be aimed at - - dist = FixedMul(attackrange, in->frac); - thingtopslope = FixedDiv(th->z + th->height - shootz, dist); - if (thingtopslope < bottomslope) - return true; // shot over the thing - thingbottomslope = FixedDiv(th->z - shootz, dist); - if (thingbottomslope > topslope) - return true; // shot under the thing - -// -// this thing can be hit! -// - if (thingtopslope > topslope) - thingtopslope = topslope; - if (thingbottomslope < bottomslope) - thingbottomslope = bottomslope; - - aimslope = (thingtopslope + thingbottomslope) / 2; - linetarget = th; - - return false; // don't go any farther -} - - -/* -============================================================================== -= -= PTR_ShootTraverse -= -============================================================================== -*/ - -boolean PTR_ShootTraverse(intercept_t * in) -{ - fixed_t x, y, z; - fixed_t frac; - line_t *li; - mobj_t *th; - fixed_t slope; - fixed_t dist; - fixed_t thingtopslope, thingbottomslope; - mobj_t *mo; - - if (in->isaline) - { - li = in->d.line; - if (li->special) - P_ShootSpecialLine(shootthing, li); - if (!(li->flags & ML_TWOSIDED)) - goto hitline; - -// -// crosses a two sided line -// - P_LineOpening(li); - - dist = FixedMul(attackrange, in->frac); - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv(openbottom - shootz, dist); - if (slope > aimslope) - goto hitline; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv(opentop - shootz, dist); - if (slope < aimslope) - goto hitline; - } - - return true; // shot continues -// -// hit line -// - hitline: - // position a bit closer - frac = in->frac - FixedDiv(4 * FRACUNIT, attackrange); - x = trace.x + FixedMul(trace.dx, frac); - y = trace.y + FixedMul(trace.dy, frac); - z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); - - if (li->frontsector->ceilingpic == skyflatnum) - { - if (z > li->frontsector->ceilingheight) - return false; // don't shoot the sky! - if (li->backsector && li->backsector->ceilingpic == skyflatnum) - return false; // it's a sky hack wall - } - - P_SpawnPuff(x, y, z); - return false; // don't go any farther - } - -// -// shoot a thing -// - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - if (!(th->flags & MF_SHOOTABLE)) - return true; // corpse or something - -// -// check for physical attacks on a ghost -// - if (th->flags & MF_SHADOW && shootthing->player->readyweapon == wp_staff) - { - return (true); - } - -// check angles to see if the thing can be aimed at - dist = FixedMul(attackrange, in->frac); - thingtopslope = FixedDiv(th->z + th->height - shootz, dist); - if (thingtopslope < aimslope) - return true; // shot over the thing - thingbottomslope = FixedDiv(th->z - shootz, dist); - if (thingbottomslope > aimslope) - return true; // shot under the thing - -// -// hit thing -// - // position a bit closer - frac = in->frac - FixedDiv(10 * FRACUNIT, attackrange); - x = trace.x + FixedMul(trace.dx, frac); - y = trace.y + FixedMul(trace.dy, frac); - z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); - if (PuffType == MT_BLASTERPUFF1) - { // Make blaster big puff - mo = P_SpawnMobj(x, y, z, MT_BLASTERPUFF2); - S_StartSound(mo, sfx_blshit); - } - else - { - P_SpawnPuff(x, y, z); - } - if (la_damage) - { - if (!(in->d.thing->flags & MF_NOBLOOD) && P_Random() < 192) - { - P_BloodSplatter(x, y, z, in->d.thing); - } - P_DamageMobj(th, shootthing, shootthing, la_damage); - } - return (false); // don't go any farther -} - -/* -================= -= -= P_AimLineAttack -= -================= -*/ - -fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance) -{ - fixed_t x2, y2; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; - y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; - shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; - topslope = 100 * FRACUNIT / 160; // can't shoot outside view angles - bottomslope = -100 * FRACUNIT / 160; - attackrange = distance; - linetarget = NULL; - - P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, - PTR_AimTraverse); - - if (linetarget) - return aimslope; - return 0; -} - - - -/* -================= -= -= P_LineAttack -= -= if damage == 0, it is just a test trace that will leave linetarget set -= -================= -*/ - -void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, - int damage) -{ - fixed_t x2, y2; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - la_damage = damage; - x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; - y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; - shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; - if (t1->flags2 & MF2_FEETARECLIPPED) - { - shootz -= FOOTCLIPSIZE; - } - attackrange = distance; - aimslope = slope; - - P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, - PTR_ShootTraverse); -} - - - -/* -============================================================================== - - USE LINES - -============================================================================== -*/ - -mobj_t *usething; - -boolean PTR_UseTraverse(intercept_t * in) -{ - if (!in->d.line->special) - { - P_LineOpening(in->d.line); - if (openrange <= 0) - { - //S_StartSound (usething, sfx_noway); - return false; // can't use through a wall - } - return true; // not a special line, but keep checking - } - - if (P_PointOnLineSide(usething->x, usething->y, in->d.line) == 1) - return false; // don't use back sides - - P_UseSpecialLine(usething, in->d.line); - - return false; // can't use for than one special line in a row -} - - -/* -================ -= -= P_UseLines -= -= Looks for special lines in front of the player to activate -================ -*/ - -void P_UseLines(player_t * player) -{ - int angle; - fixed_t x1, y1, x2, y2; - - usething = player->mo; - - angle = player->mo->angle >> ANGLETOFINESHIFT; - x1 = player->mo->x; - y1 = player->mo->y; - x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; - y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; - - P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse); -} - - - -/* -============================================================================== - - RADIUS ATTACK - -============================================================================== -*/ - -mobj_t *bombsource; -mobj_t *bombspot; -int bombdamage; - -/* -================= -= -= PIT_RadiusAttack -= -= Source is the creature that casued the explosion at spot -================= -*/ - -boolean PIT_RadiusAttack(mobj_t * thing) -{ - fixed_t dx, dy, dist; - - if (!(thing->flags & MF_SHOOTABLE)) - { - return true; - } - if (thing->type == MT_MINOTAUR || thing->type == MT_SORCERER1 - || thing->type == MT_SORCERER2) - { // Episode 2 and 3 bosses take no damage from PIT_RadiusAttack - return (true); - } - dx = abs(thing->x - bombspot->x); - dy = abs(thing->y - bombspot->y); - dist = dx > dy ? dx : dy; - dist = (dist - thing->radius) >> FRACBITS; - if (dist < 0) - { - dist = 0; - } - if (dist >= bombdamage) - { // Out of range - return true; - } - if (P_CheckSight(thing, bombspot)) - { // OK to damage, target is in direct path - P_DamageMobj(thing, bombspot, bombsource, bombdamage - dist); - } - return (true); -} - -/* -================= -= -= P_RadiusAttack -= -= Source is the creature that casued the explosion at spot -================= -*/ - -void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage) -{ - int x, y, xl, xh, yl, yh; - fixed_t dist; - - dist = (damage + MAXRADIUS) << FRACBITS; - yh = (spot->y + dist - bmaporgy) >> MAPBLOCKSHIFT; - yl = (spot->y - dist - bmaporgy) >> MAPBLOCKSHIFT; - xh = (spot->x + dist - bmaporgx) >> MAPBLOCKSHIFT; - xl = (spot->x - dist - bmaporgx) >> MAPBLOCKSHIFT; - bombspot = spot; - if (spot->type == MT_POD && spot->target) - { - bombsource = spot->target; - } - else - { - bombsource = source; - } - bombdamage = damage; - for (y = yl; y <= yh; y++) - for (x = xl; x <= xh; x++) - P_BlockThingsIterator(x, y, PIT_RadiusAttack); -} - - -/* -============================================================================== - - SECTOR HEIGHT CHANGING - -= After modifying a sectors floor or ceiling height, call this -= routine to adjust the positions of all things that touch the -= sector. -= -= If anything doesn't fit anymore, true will be returned. -= If crunch is true, they will take damage as they are being crushed -= If Crunch is false, you should set the sector height back the way it -= was and call P_ChangeSector again to undo the changes -============================================================================== -*/ - -boolean crushchange; -boolean nofit; - -/* -=============== -= -= PIT_ChangeSector -= -=============== -*/ - -boolean PIT_ChangeSector(mobj_t * thing) -{ - mobj_t *mo; - - if (P_ThingHeightClip(thing)) - return true; // keep checking - - // crunch bodies to giblets - if (thing->health <= 0) - { - //P_SetMobjState (thing, S_GIBS); - thing->height = 0; - thing->radius = 0; - return true; // keep checking - } - - // crunch dropped items - if (thing->flags & MF_DROPPED) - { - P_RemoveMobj(thing); - return true; // keep checking - } - - if (!(thing->flags & MF_SHOOTABLE)) - return true; // assume it is bloody gibs or something - - nofit = true; - if (crushchange && !(leveltime & 3)) - { - P_DamageMobj(thing, NULL, NULL, 10); - // spray blood in a random direction - mo = P_SpawnMobj(thing->x, thing->y, thing->z + thing->height / 2, - MT_BLOOD); - mo->momx = P_SubRandom() << 12; - mo->momy = P_SubRandom() << 12; - } - - return true; // keep checking (crush other things) -} - -/* -=============== -= -= P_ChangeSector -= -=============== -*/ - -boolean P_ChangeSector(sector_t * sector, boolean crunch) -{ - int x, y; - - nofit = false; - crushchange = crunch; - -// recheck heights for all things near the moving sector - - for (x = sector->blockbox[BOXLEFT]; x <= sector->blockbox[BOXRIGHT]; x++) - for (y = sector->blockbox[BOXBOTTOM]; y <= sector->blockbox[BOXTOP]; - y++) - P_BlockThingsIterator(x, y, PIT_ChangeSector); - - - return nofit; -} diff --git a/games/NXDoom/src/heretic/p_maputl.c b/games/NXDoom/src/heretic/p_maputl.c deleted file mode 100644 index 5150aaeef88..00000000000 --- a/games/NXDoom/src/heretic/p_maputl.c +++ /dev/null @@ -1,779 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_maputl.c - -#include - -#include "doomdef.h" -#include "m_bbox.h" -#include "m_misc.h" -#include "p_local.h" - - -/* -=================== -= -= P_AproxDistance -= -= Gives an estimation of distance (not exact) -= -=================== -*/ - -fixed_t P_AproxDistance(fixed_t dx, fixed_t dy) -{ - dx = abs(dx); - dy = abs(dy); - if (dx < dy) - return dx + dy - (dx >> 1); - return dx + dy - (dy >> 1); -} - - -/* -================== -= -= P_PointOnLineSide -= -= Returns 0 or 1 -================== -*/ - -int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line) -{ - fixed_t dx, dy; - fixed_t left, right; - - if (!line->dx) - { - if (x <= line->v1->x) - return line->dy > 0; - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->v1->y) - return line->dx < 0; - return line->dx > 0; - } - - dx = (x - line->v1->x); - dy = (y - line->v1->y); - - left = FixedMul(line->dy >> FRACBITS, dx); - right = FixedMul(dy, line->dx >> FRACBITS); - - if (right < left) - return 0; // front side - return 1; // back side -} - - -/* -================= -= -= P_BoxOnLineSide -= -= Considers the line to be infinite -= Returns side 0 or 1, -1 if box crosses the line -================= -*/ - -int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld) -{ - int p1 = 0, p2 = 0; - - switch (ld->slopetype) - { - case ST_HORIZONTAL: - p1 = tmbox[BOXTOP] > ld->v1->y; - p2 = tmbox[BOXBOTTOM] > ld->v1->y; - if (ld->dx < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - case ST_VERTICAL: - p1 = tmbox[BOXRIGHT] < ld->v1->x; - p2 = tmbox[BOXLEFT] < ld->v1->x; - if (ld->dy < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - case ST_POSITIVE: - p1 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); - break; - case ST_NEGATIVE: - p1 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); - break; - } - - if (p1 == p2) - return p1; - return -1; -} - -/* -================== -= -= P_PointOnDivlineSide -= -= Returns 0 or 1 -================== -*/ - -int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line) -{ - fixed_t dx, dy; - fixed_t left, right; - - if (!line->dx) - { - if (x <= line->x) - return line->dy > 0; - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->y) - return line->dx < 0; - return line->dx > 0; - } - - dx = (x - line->x); - dy = (y - line->y); - -// try to quickly decide by looking at sign bits - if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000) - { - if ((line->dy ^ dx) & 0x80000000) - return 1; // (left is negative) - return 0; - } - - left = FixedMul(line->dy >> 8, dx >> 8); - right = FixedMul(dy >> 8, line->dx >> 8); - - if (right < left) - return 0; // front side - return 1; // back side -} - - - -/* -============== -= -= P_MakeDivline -= -============== -*/ - -void P_MakeDivline(line_t * li, divline_t * dl) -{ - dl->x = li->v1->x; - dl->y = li->v1->y; - dl->dx = li->dx; - dl->dy = li->dy; -} - - -/* -=============== -= -= P_InterceptVector -= -= Returns the fractional intercept point along the first divline -= -= This is only called by the addthings and addlines traversers -=============== -*/ - -fixed_t P_InterceptVector(divline_t * v2, divline_t * v1) -{ -#if 1 - fixed_t frac, num, den; - - den = FixedMul(v1->dy >> 8, v2->dx) - FixedMul(v1->dx >> 8, v2->dy); - if (den == 0) - return 0; -// I_Error ("P_InterceptVector: parallel"); - num = FixedMul((v1->x - v2->x) >> 8, v1->dy) + - FixedMul((v2->y - v1->y) >> 8, v1->dx); - frac = FixedDiv(num, den); - - return frac; -#else - float frac, num, den, v1x, v1y, v1dx, v1dy, v2x, v2y, v2dx, v2dy; - - v1x = (float) v1->x / FRACUNIT; - v1y = (float) v1->y / FRACUNIT; - v1dx = (float) v1->dx / FRACUNIT; - v1dy = (float) v1->dy / FRACUNIT; - v2x = (float) v2->x / FRACUNIT; - v2y = (float) v2->y / FRACUNIT; - v2dx = (float) v2->dx / FRACUNIT; - v2dy = (float) v2->dy / FRACUNIT; - - den = v1dy * v2dx - v1dx * v2dy; - if (den == 0) - return 0; // parallel - num = (v1x - v2x) * v1dy + (v2y - v1y) * v1dx; - frac = num / den; - - return frac * FRACUNIT; -#endif -} - -/* -================== -= -= P_LineOpening -= -= Sets opentop and openbottom to the window through a two sided line -= OPTIMIZE: keep this precalculated -================== -*/ - -fixed_t opentop, openbottom, openrange; -fixed_t lowfloor; - -void P_LineOpening(line_t * linedef) -{ - sector_t *front, *back; - - if (linedef->sidenum[1] == -1) - { // single sided line - openrange = 0; - return; - } - - front = linedef->frontsector; - back = linedef->backsector; - - if (front->ceilingheight < back->ceilingheight) - opentop = front->ceilingheight; - else - opentop = back->ceilingheight; - if (front->floorheight > back->floorheight) - { - openbottom = front->floorheight; - lowfloor = back->floorheight; - } - else - { - openbottom = back->floorheight; - lowfloor = front->floorheight; - } - - openrange = opentop - openbottom; -} - -/* -=============================================================================== - - THING POSITION SETTING - -=============================================================================== -*/ - -/* -=================== -= -= P_UnsetThingPosition -= -= Unlinks a thing from block map and sectors -= -=================== -*/ - -void P_UnsetThingPosition(mobj_t * thing) -{ - int blockx, blocky; - - if (!(thing->flags & MF_NOSECTOR)) - { // inert things don't need to be in blockmap -// unlink from subsector - if (thing->snext) - thing->snext->sprev = thing->sprev; - if (thing->sprev) - thing->sprev->snext = thing->snext; - else - thing->subsector->sector->thinglist = thing->snext; - } - - if (!(thing->flags & MF_NOBLOCKMAP)) - { // inert things don't need to be in blockmap -// unlink from block map - if (thing->bnext) - thing->bnext->bprev = thing->bprev; - if (thing->bprev) - thing->bprev->bnext = thing->bnext; - else - { - blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; - if (blockx >= 0 && blockx < bmapwidth - && blocky >= 0 && blocky < bmapheight) - blocklinks[blocky * bmapwidth + blockx] = thing->bnext; - } - } -} - - -/* -=================== -= -= P_SetThingPosition -= -= Links a thing into both a block and a subsector based on it's x y -= Sets thing->subsector properly -= -=================== -*/ - -void P_SetThingPosition(mobj_t * thing) -{ - subsector_t *ss; - sector_t *sec; - int blockx, blocky; - mobj_t **link; - -// -// link into subsector -// - ss = R_PointInSubsector(thing->x, thing->y); - thing->subsector = ss; - if (!(thing->flags & MF_NOSECTOR)) - { // invisible things don't go into the sector links - sec = ss->sector; - - thing->sprev = NULL; - thing->snext = sec->thinglist; - if (sec->thinglist) - sec->thinglist->sprev = thing; - sec->thinglist = thing; - } - -// -// link into blockmap -// - if (!(thing->flags & MF_NOBLOCKMAP)) - { // inert things don't need to be in blockmap - blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; - if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 - && blocky < bmapheight) - { - link = &blocklinks[blocky * bmapwidth + blockx]; - thing->bprev = NULL; - thing->bnext = *link; - if (*link) - (*link)->bprev = thing; - *link = thing; - } - else - { // thing is off the map - thing->bnext = thing->bprev = NULL; - } - } -} - - - -/* -=============================================================================== - - BLOCK MAP ITERATORS - -For each line/thing in the given mapblock, call the passed function. -If the function returns false, exit with false without checking anything else. - -=============================================================================== -*/ - -/* -================== -= -= P_BlockLinesIterator -= -= The validcount flags are used to avoid checking lines -= that are marked in multiple mapblocks, so increment validcount before -= the first call to P_BlockLinesIterator, then make one or more calls to it -=================== -*/ - -boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)) -{ - int offset; - short *list; - line_t *ld; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - return true; - offset = y * bmapwidth + x; - - offset = *(blockmap + offset); - - for (list = blockmaplump + offset; *list != -1; list++) - { - ld = &lines[*list]; - if (ld->validcount == validcount) - continue; // line has already been checked - ld->validcount = validcount; - - if (!func(ld)) - return false; - } - - return true; // everything was checked -} - - -/* -================== -= -= P_BlockThingsIterator -= -================== -*/ - -boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)) -{ - mobj_t *mobj; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - return true; - - LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); - - for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext) - if (!func(mobj)) - return false; - - return true; -} - -/* -=============================================================================== - - INTERCEPT ROUTINES - -=============================================================================== -*/ - -intercept_t intercepts[MAXINTERCEPTS], *intercept_p; - -divline_t trace; -boolean earlyout; -int ptflags; - -/* -================== -= -= PIT_AddLineIntercepts -= -= Looks for lines in the given block that intercept the given trace -= to add to the intercepts list -= A line is crossed if its endpoints are on opposite sides of the trace -= Returns true if earlyout and a solid line hit -================== -*/ - -boolean PIT_AddLineIntercepts(line_t * ld) -{ - int s1, s2; - fixed_t frac; - divline_t dl; - -// avoid precision problems with two routines - if (trace.dx > FRACUNIT * 16 || trace.dy > FRACUNIT * 16 - || trace.dx < -FRACUNIT * 16 || trace.dy < -FRACUNIT * 16) - { - s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); - } - else - { - s1 = P_PointOnLineSide(trace.x, trace.y, ld); - s2 = P_PointOnLineSide(trace.x + trace.dx, trace.y + trace.dy, ld); - } - if (s1 == s2) - return true; // line isn't crossed - -// -// hit the line -// - P_MakeDivline(ld, &dl); - frac = P_InterceptVector(&trace, &dl); - if (frac < 0) - return true; // behind source - -// try to early out the check - if (earlyout && frac < FRACUNIT && !ld->backsector) - return false; // stop checking - - intercept_p->frac = frac; - intercept_p->isaline = true; - intercept_p->d.line = ld; - intercept_p++; - - return true; // continue -} - - - -/* -================== -= -= PIT_AddThingIntercepts -= -================== -*/ - -boolean PIT_AddThingIntercepts(mobj_t * thing) -{ - fixed_t x1, y1, x2, y2; - int s1, s2; - boolean tracepositive; - divline_t dl; - fixed_t frac; - - tracepositive = (trace.dx ^ trace.dy) > 0; - - // check a corner to corner crossection for hit - - if (tracepositive) - { - x1 = thing->x - thing->radius; - y1 = thing->y + thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y - thing->radius; - } - else - { - x1 = thing->x - thing->radius; - y1 = thing->y - thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y + thing->radius; - } - s1 = P_PointOnDivlineSide(x1, y1, &trace); - s2 = P_PointOnDivlineSide(x2, y2, &trace); - if (s1 == s2) - return true; // line isn't crossed - - dl.x = x1; - dl.y = y1; - dl.dx = x2 - x1; - dl.dy = y2 - y1; - frac = P_InterceptVector(&trace, &dl); - if (frac < 0) - return true; // behind source - intercept_p->frac = frac; - intercept_p->isaline = false; - intercept_p->d.thing = thing; - intercept_p++; - - return true; // keep going -} - - -/* -==================== -= -= P_TraverseIntercepts -= -= Returns true if the traverser function returns true for all lines -==================== -*/ - -boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) -{ - int count; - fixed_t dist; - intercept_t *scan, *in; - - count = intercept_p - intercepts; - in = 0; // shut up compiler warning - - while (count--) - { - dist = INT_MAX; - for (scan = intercepts; scan < intercept_p; scan++) - if (scan->frac < dist) - { - dist = scan->frac; - in = scan; - } - - if (dist > maxfrac) - return true; // checked everything in range -#if 0 - { // don't check these yet, ther may be others inserted - in = scan = intercepts; - for (scan = intercepts; scan < intercept_p; scan++) - if (scan->frac > maxfrac) - *in++ = *scan; - intercept_p = in; - return false; - } -#endif - - if (!func(in)) - return false; // don't bother going farther - in->frac = INT_MAX; - } - - return true; // everything was traversed -} - - - -/* -================== -= -= P_PathTraverse -= -= Traces a line from x1,y1 to x2,y2, calling the traverser function for each -= Returns true if the traverser function returns true for all lines -================== -*/ - -boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, - int flags, boolean(*trav) (intercept_t *)) -{ - fixed_t xt1, yt1, xt2, yt2; - fixed_t xstep, ystep; - fixed_t partial; - fixed_t xintercept, yintercept; - int mapx, mapy, mapxstep, mapystep; - int count; - - earlyout = (flags & PT_EARLYOUT) != 0; - - validcount++; - intercept_p = intercepts; - - if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) - x1 += FRACUNIT; // don't side exactly on a line - if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) - y1 += FRACUNIT; // don't side exactly on a line - trace.x = x1; - trace.y = y1; - trace.dx = x2 - x1; - trace.dy = y2 - y1; - - x1 -= bmaporgx; - y1 -= bmaporgy; - xt1 = x1 >> MAPBLOCKSHIFT; - yt1 = y1 >> MAPBLOCKSHIFT; - - x2 -= bmaporgx; - y2 -= bmaporgy; - xt2 = x2 >> MAPBLOCKSHIFT; - yt2 = y2 >> MAPBLOCKSHIFT; - - if (xt2 > xt1) - { - mapxstep = 1; - partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else if (xt2 < xt1) - { - mapxstep = -1; - partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else - { - mapxstep = 0; - partial = FRACUNIT; - ystep = 256 * FRACUNIT; - } - yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); - - - if (yt2 > yt1) - { - mapystep = 1; - partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else - { - mapystep = 0; - partial = FRACUNIT; - xstep = 256 * FRACUNIT; - } - xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); - - -// -// step through map blocks -// Count is present to prevent a round off error from skipping the break - mapx = xt1; - mapy = yt1; - - for (count = 0; count < 64; count++) - { - if (flags & PT_ADDLINES) - { - if (!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts)) - return false; // early out - } - if (flags & PT_ADDTHINGS) - { - if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts)) - return false; // early out - } - - if (mapx == xt2 && mapy == yt2) - break; - - if ((yintercept >> FRACBITS) == mapy) - { - yintercept += ystep; - mapx += mapxstep; - } - else if ((xintercept >> FRACBITS) == mapx) - { - xintercept += xstep; - mapy += mapystep; - } - - } - - -// -// go through the sorted list -// - return P_TraverseIntercepts(trav, FRACUNIT); -} diff --git a/games/NXDoom/src/heretic/p_mobj.c b/games/NXDoom/src/heretic/p_mobj.c deleted file mode 100644 index 363dabe4a60..00000000000 --- a/games/NXDoom/src/heretic/p_mobj.c +++ /dev/null @@ -1,1626 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_mobj.c - -#include "doomdef.h" -#include "i_system.h" -#include "m_random.h" -#include "p_local.h" -#include "sounds.h" -#include "s_sound.h" - -void G_PlayerReborn(int player); -void P_SpawnMapThing(mapthing_t * mthing); - -mobjtype_t PuffType; -mobj_t *MissileMobj; - -static fixed_t FloatBobOffsets[64] = { - 0, 51389, 102283, 152192, - 200636, 247147, 291278, 332604, - 370727, 405280, 435929, 462380, - 484378, 501712, 514213, 521763, - 524287, 521763, 514213, 501712, - 484378, 462380, 435929, 405280, - 370727, 332604, 291278, 247147, - 200636, 152192, 102283, 51389, - -1, -51390, -102284, -152193, - -200637, -247148, -291279, -332605, - -370728, -405281, -435930, -462381, - -484380, -501713, -514215, -521764, - -524288, -521764, -514214, -501713, - -484379, -462381, -435930, -405280, - -370728, -332605, -291279, -247148, - -200637, -152193, -102284, -51389 -}; - -//---------------------------------------------------------------------------- -// -// FUNC P_SetMobjState -// -// Returns true if the mobj is still present. -// -//---------------------------------------------------------------------------- - -boolean P_SetMobjState(mobj_t * mobj, statenum_t state) -{ - state_t *st; - - if (state == S_NULL) - { // Remove mobj - mobj->state = (state_t *) S_NULL; - P_RemoveMobj(mobj); - return (false); - } - st = &states[state]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - if (st->action) - { // Call action function - st->action(mobj, NULL, NULL); - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_SetMobjStateNF -// -// Same as P_SetMobjState, but does not call the state function. -// -//---------------------------------------------------------------------------- - -boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state) -{ - state_t *st; - - if (state == S_NULL) - { // Remove mobj - mobj->state = (state_t *) S_NULL; - P_RemoveMobj(mobj); - return (false); - } - st = &states[state]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC P_ExplodeMissile -// -//---------------------------------------------------------------------------- - -void P_ExplodeMissile(mobj_t * mo) -{ - if (mo->type == MT_WHIRLWIND) - { - if (++mo->special2.i < 60) - { - return; - } - } - mo->momx = mo->momy = mo->momz = 0; - P_SetMobjState(mo, mobjinfo[mo->type].deathstate); - //mo->tics -= P_Random()&3; - mo->flags &= ~MF_MISSILE; - if (mo->info->deathsound) - { - S_StartSound(mo, mo->info->deathsound); - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_FloorBounceMissile -// -//---------------------------------------------------------------------------- - -void P_FloorBounceMissile(mobj_t * mo) -{ - mo->momz = -mo->momz; - P_SetMobjState(mo, mobjinfo[mo->type].deathstate); -} - -//---------------------------------------------------------------------------- -// -// PROC P_ThrustMobj -// -//---------------------------------------------------------------------------- - -void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move) -{ - angle >>= ANGLETOFINESHIFT; - mo->momx += FixedMul(move, finecosine[angle]); - mo->momy += FixedMul(move, finesine[angle]); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_FaceMobj -// -// Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs -// to turn counter clockwise. 'delta' is set to the amount 'source' -// needs to turn. -// -//---------------------------------------------------------------------------- - -int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta) -{ - angle_t diff; - angle_t angle1; - angle_t angle2; - - angle1 = source->angle; - angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y); - if (angle2 > angle1) - { - diff = angle2 - angle1; - if (diff > ANG180) - { - *delta = ANG_MAX - diff; - return (0); - } - else - { - *delta = diff; - return (1); - } - } - else - { - diff = angle1 - angle2; - if (diff > ANG180) - { - *delta = ANG_MAX - diff; - return (1); - } - else - { - *delta = diff; - return (0); - } - } -} - -//---------------------------------------------------------------------------- -// -// FUNC P_SeekerMissile -// -// The missile special1 field must be mobj_t *target. Returns true if -// target was tracked, false if not. -// -//---------------------------------------------------------------------------- - -boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax) -{ - int dir; - int dist; - angle_t delta; - angle_t angle; - mobj_t *target; - - target = (mobj_t *) actor->special1.m; - if (target == NULL) - { - return (false); - } - if (!(target->flags & MF_SHOOTABLE)) - { // Target died - actor->special1.m = NULL; - return (false); - } - dir = P_FaceMobj(actor, target, &delta); - if (delta > thresh) - { - delta >>= 1; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->angle += delta; - } - else - { // Turn counter clockwise - actor->angle -= delta; - } - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(actor->info->speed, finecosine[angle]); - actor->momy = FixedMul(actor->info->speed, finesine[angle]); - if (actor->z + actor->height < target->z || - target->z + target->height < actor->z) - { // Need to seek vertically - dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); - dist = dist / actor->info->speed; - if (dist < 1) - { - dist = 1; - } - actor->momz = (target->z - actor->z) / dist; - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC P_XYMovement -// -//---------------------------------------------------------------------------- - -#define STOPSPEED 0x1000 -#define FRICTION_NORMAL 0xe800 -#define FRICTION_LOW 0xf900 -#define FRICTION_FLY 0xeb00 - -void P_XYMovement(mobj_t * mo) -{ - fixed_t ptryx, ptryy; - player_t *player; - fixed_t xmove, ymove; - int special; - static int windTab[3] = { 2048 * 5, 2048 * 10, 2048 * 25 }; - - if (!mo->momx && !mo->momy) - { - if (mo->flags & MF_SKULLFLY) - { // A flying mobj slammed into something - mo->flags &= ~MF_SKULLFLY; - mo->momx = mo->momy = mo->momz = 0; - P_SetMobjState(mo, mo->info->seestate); - } - return; - } - special = mo->subsector->sector->special; - if (mo->flags2 & MF2_WINDTHRUST) - { - switch (special) - { - case 40: - case 41: - case 42: // Wind_East - P_ThrustMobj(mo, 0, windTab[special - 40]); - break; - case 43: - case 44: - case 45: // Wind_North - P_ThrustMobj(mo, ANG90, windTab[special - 43]); - break; - case 46: - case 47: - case 48: // Wind_South - P_ThrustMobj(mo, ANG270, windTab[special - 46]); - break; - case 49: - case 50: - case 51: // Wind_West - P_ThrustMobj(mo, ANG180, windTab[special - 49]); - break; - } - } - player = mo->player; - if (mo->momx > MAXMOVE) - { - mo->momx = MAXMOVE; - } - else if (mo->momx < -MAXMOVE) - { - mo->momx = -MAXMOVE; - } - if (mo->momy > MAXMOVE) - { - mo->momy = MAXMOVE; - } - else if (mo->momy < -MAXMOVE) - { - mo->momy = -MAXMOVE; - } - xmove = mo->momx; - ymove = mo->momy; - do - { - if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2) - { - ptryx = mo->x + xmove / 2; - ptryy = mo->y + ymove / 2; - xmove >>= 1; - ymove >>= 1; - } - else - { - ptryx = mo->x + xmove; - ptryy = mo->y + ymove; - xmove = ymove = 0; - } - if (!P_TryMove(mo, ptryx, ptryy)) - { // Blocked move - if (mo->flags2 & MF2_SLIDE) - { // Try to slide along it - P_SlideMove(mo); - } - else if (mo->flags & MF_MISSILE) - { // Explode a missile - if (ceilingline && ceilingline->backsector - && ceilingline->backsector->ceilingpic == skyflatnum) - { // Hack to prevent missiles exploding against the sky - if (mo->type == MT_BLOODYSKULL) - { - mo->momx = mo->momy = 0; - mo->momz = -FRACUNIT; - } - else - { - P_RemoveMobj(mo); - } - return; - } - P_ExplodeMissile(mo); - } - //else if(mo->info->crashstate) - //{ - // mo->momx = mo->momy = 0; - // P_SetMobjState(mo, mo->info->crashstate); - // return; - //} - else - { - mo->momx = mo->momy = 0; - } - } - } - while (xmove || ymove); - - // Friction - - if (player && player->cheats & CF_NOMOMENTUM) - { // Debug option for no sliding at all - mo->momx = mo->momy = 0; - return; - } - if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) - { // No friction for missiles - return; - } - if (mo->z > mo->floorz && !(mo->flags2 & MF2_FLY) - && !(mo->flags2 & MF2_ONMOBJ)) - { // No friction when falling - return; - } - if (mo->flags & MF_CORPSE) - { // Don't stop sliding if halfway off a step with some momentum - if (mo->momx > FRACUNIT / 4 || mo->momx < -FRACUNIT / 4 - || mo->momy > FRACUNIT / 4 || mo->momy < -FRACUNIT / 4) - { - if (mo->floorz != mo->subsector->sector->floorheight) - { - return; - } - } - } - if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED - && mo->momy > -STOPSPEED && mo->momy < STOPSPEED - && (!player || (player->cmd.forwardmove == 0 - && player->cmd.sidemove == 0))) - { // If in a walking frame, stop moving - if (player) - { - if (player->chickenTics) - { - if ((unsigned) ((player->mo->state - states) - - S_CHICPLAY_RUN1) < 4) - { - P_SetMobjState(player->mo, S_CHICPLAY); - } - } - else - { - if ((unsigned) ((player->mo->state - states) - - S_PLAY_RUN1) < 4) - { - P_SetMobjState(player->mo, S_PLAY); - } - } - } - mo->momx = 0; - mo->momy = 0; - } - else - { - if (mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) - && !(mo->flags2 & MF2_ONMOBJ)) - { - mo->momx = FixedMul(mo->momx, FRICTION_FLY); - mo->momy = FixedMul(mo->momy, FRICTION_FLY); - } - else if (special == 15) // Friction_Low - { - mo->momx = FixedMul(mo->momx, FRICTION_LOW); - mo->momy = FixedMul(mo->momy, FRICTION_LOW); - } - else - { - mo->momx = FixedMul(mo->momx, FRICTION_NORMAL); - mo->momy = FixedMul(mo->momy, FRICTION_NORMAL); - } - } -} - - -/* -=============== -= -= P_ZMovement -= -=============== -*/ - -void P_ZMovement(mobj_t * mo) -{ - int dist; - int delta; -// -// check for smooth step up -// - if (mo->player && mo->z < mo->floorz) - { - mo->player->viewheight -= mo->floorz - mo->z; - mo->player->deltaviewheight = - (VIEWHEIGHT - mo->player->viewheight) >> 3; - } -// -// adjust height -// - mo->z += mo->momz; - if (mo->flags & MF_FLOAT && mo->target) - { // float down towards target if too close - if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) - { - dist = - P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); - delta = (mo->target->z + (mo->height >> 1)) - mo->z; - if (delta < 0 && dist < -(delta * 3)) - mo->z -= FLOATSPEED; - else if (delta > 0 && dist < (delta * 3)) - mo->z += FLOATSPEED; - } - } - if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) - && leveltime & 2) - { - mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; - } - -// -// clip movement -// - if (mo->z <= mo->floorz) - { // Hit the floor - if (mo->flags & MF_MISSILE) - { - mo->z = mo->floorz; - if (mo->flags2 & MF2_FLOORBOUNCE) - { - P_FloorBounceMissile(mo); - return; - } - else if (mo->type == MT_MNTRFX2) - { // Minotaur floor fire can go up steps - return; - } - else - { - P_ExplodeMissile(mo); - return; - } - } - if (mo->z - mo->momz > mo->floorz) - { // Spawn splashes, etc. - P_HitFloor(mo); - } - mo->z = mo->floorz; - if (mo->momz < 0) - { - if (mo->player && mo->momz < -GRAVITY * 8 && !(mo->flags2 & MF2_FLY)) // squat down - { - mo->player->deltaviewheight = mo->momz >> 3; - S_StartSound(mo, sfx_plroof); - // haleyjd: removed externdriver crap - mo->player->centering = true; - } - mo->momz = 0; - } - if (mo->flags & MF_SKULLFLY) - { // The skull slammed into something - mo->momz = -mo->momz; - } - if (mo->info->crashstate && (mo->flags & MF_CORPSE)) - { - P_SetMobjState(mo, mo->info->crashstate); - return; - } - } - else if (mo->flags2 & MF2_LOGRAV) - { - if (mo->momz == 0) - mo->momz = -(GRAVITY >> 3) * 2; - else - mo->momz -= GRAVITY >> 3; - } - else if (!(mo->flags & MF_NOGRAVITY)) - { - if (mo->momz == 0) - mo->momz = -GRAVITY * 2; - else - mo->momz -= GRAVITY; - } - - if (mo->z + mo->height > mo->ceilingz) - { // hit the ceiling - if (mo->momz > 0) - mo->momz = 0; - mo->z = mo->ceilingz - mo->height; - if (mo->flags & MF_SKULLFLY) - { // the skull slammed into something - mo->momz = -mo->momz; - } - if (mo->flags & MF_MISSILE) - { - if (mo->subsector->sector->ceilingpic == skyflatnum) - { - if (mo->type == MT_BLOODYSKULL) - { - mo->momx = mo->momy = 0; - mo->momz = -FRACUNIT; - } - else - { - P_RemoveMobj(mo); - } - return; - } - P_ExplodeMissile(mo); - return; - } - } -} - - -/* -================ -= -= P_NightmareRespawn -= -================ -*/ - -void P_NightmareRespawn(mobj_t * mobj) -{ - fixed_t x, y, z; - subsector_t *ss; - mobj_t *mo; - mapthing_t *mthing; - - x = mobj->spawnpoint.x << FRACBITS; - y = mobj->spawnpoint.y << FRACBITS; - - if (!P_CheckPosition(mobj, x, y)) - return; // somthing is occupying it's position - - -// spawn a teleport fog at old spot - - mo = P_SpawnMobj(mobj->x, mobj->y, - mobj->subsector->sector->floorheight + TELEFOGHEIGHT, - MT_TFOG); - S_StartSound(mo, sfx_telept); - -// spawn a teleport fog at the new spot - ss = R_PointInSubsector(x, y); - mo = P_SpawnMobj(x, y, ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(mo, sfx_telept); - -// spawn the new monster - mthing = &mobj->spawnpoint; - -// spawn it - if (mobj->info->flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; - mo = P_SpawnMobj(x, y, z, mobj->type); - mo->spawnpoint = mobj->spawnpoint; - mo->angle = ANG45 * (mthing->angle / 45); - if (mthing->options & MTF_AMBUSH) - mo->flags |= MF_AMBUSH; - - mo->reactiontime = 18; - -// remove the old monster - P_RemoveMobj(mobj); -} - -//---------------------------------------------------------------------------- -// -// PROC P_BlasterMobjThinker -// -// Thinker for the ultra-fast blaster PL2 ripper-spawning missile. -// -//---------------------------------------------------------------------------- - -void P_BlasterMobjThinker(thinker_t *thinker) -{ - mobj_t *mobj = (mobj_t *) thinker; - int i; - fixed_t xfrac; - fixed_t yfrac; - fixed_t zfrac; - fixed_t z; - boolean changexy; - - // Handle movement - if (mobj->momx || mobj->momy || (mobj->z != mobj->floorz) || mobj->momz) - { - xfrac = mobj->momx >> 3; - yfrac = mobj->momy >> 3; - zfrac = mobj->momz >> 3; - changexy = xfrac || yfrac; - for (i = 0; i < 8; i++) - { - if (changexy) - { - if (!P_TryMove(mobj, mobj->x + xfrac, mobj->y + yfrac)) - { // Blocked move - P_ExplodeMissile(mobj); - return; - } - } - mobj->z += zfrac; - if (mobj->z <= mobj->floorz) - { // Hit the floor - mobj->z = mobj->floorz; - P_HitFloor(mobj); - P_ExplodeMissile(mobj); - return; - } - if (mobj->z + mobj->height > mobj->ceilingz) - { // Hit the ceiling - mobj->z = mobj->ceilingz - mobj->height; - P_ExplodeMissile(mobj); - return; - } - if (changexy && (P_Random() < 64)) - { - z = mobj->z - 8 * FRACUNIT; - if (z < mobj->floorz) - { - z = mobj->floorz; - } - P_SpawnMobj(mobj->x, mobj->y, z, MT_BLASTERSMOKE); - } - } - } - // Advance the state - if (mobj->tics != -1) - { - mobj->tics--; - while (!mobj->tics) - { - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - { // mobj was removed - return; - } - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_MobjThinker -// -//---------------------------------------------------------------------------- - -void P_MobjThinker(thinker_t *thinker) -{ - mobj_t *mobj = (mobj_t *) thinker; - mobj_t *onmo; - - // Handle X and Y momentums - if (mobj->momx || mobj->momy || (mobj->flags & MF_SKULLFLY)) - { - P_XYMovement(mobj); - if (mobj->thinker.function == (think_t) - 1) - { // mobj was removed - return; - } - } - if (mobj->flags2 & MF2_FLOATBOB) - { // Floating item bobbing motion - mobj->z = mobj->floorz + FloatBobOffsets[(mobj->health++) & 63]; - } - else if ((mobj->z != mobj->floorz) || mobj->momz) - { // Handle Z momentum and gravity - if (mobj->flags2 & MF2_PASSMOBJ) - { - if (!(onmo = P_CheckOnmobj(mobj))) - { - P_ZMovement(mobj); - } - else - { - if (mobj->player && mobj->momz < 0) - { - mobj->flags2 |= MF2_ONMOBJ; - mobj->momz = 0; - } - if (mobj->player && (onmo->player || onmo->type == MT_POD)) - { - mobj->momx = onmo->momx; - mobj->momy = onmo->momy; - if (onmo->z < onmo->floorz) - { - mobj->z += onmo->floorz - onmo->z; - if (onmo->player) - { - onmo->player->viewheight -= - onmo->floorz - onmo->z; - onmo->player->deltaviewheight = - (VIEWHEIGHT - onmo->player->viewheight) >> 3; - } - onmo->z = onmo->floorz; - } - } - } - } - else - { - P_ZMovement(mobj); - } - if (mobj->thinker.function == (think_t) - 1) - { // mobj was removed - return; - } - } - -// -// cycle through states, calling action functions at transitions -// - if (mobj->tics != -1) - { - mobj->tics--; - // you can cycle through multiple states in a tic - while (!mobj->tics) - { - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - { // mobj was removed - return; - } - } - } - else - { // Check for monster respawn - if (!(mobj->flags & MF_COUNTKILL)) - { - return; - } - if (!respawnmonsters) - { - return; - } - mobj->movecount++; - if (mobj->movecount < 12 * 35) - { - return; - } - if (leveltime & 31) - { - return; - } - if (P_Random() > 4) - { - return; - } - P_NightmareRespawn(mobj); - } -} - -/* -=============== -= -= P_SpawnMobj -= -=============== -*/ - -mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) -{ - mobj_t *mobj; - state_t *st; - mobjinfo_t *info; - fixed_t space; - - mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); - memset(mobj, 0, sizeof(*mobj)); - info = &mobjinfo[type]; - mobj->type = type; - mobj->info = info; - mobj->x = x; - mobj->y = y; - mobj->radius = info->radius; - mobj->height = info->height; - mobj->flags = info->flags; - mobj->flags2 = info->flags2; - mobj->damage = info->damage; - mobj->health = info->spawnhealth; - if (gameskill != sk_nightmare) - { - mobj->reactiontime = info->reactiontime; - } - mobj->lastlook = P_Random() % MAXPLAYERS; - - // Set the state, but do not use P_SetMobjState, because action - // routines can't be called yet. If the spawnstate has an action - // routine, it will not be called. - st = &states[info->spawnstate]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - - // Set subsector and/or block links. - P_SetThingPosition(mobj); - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - if (z == ONFLOORZ) - { - mobj->z = mobj->floorz; - } - else if (z == ONCEILINGZ) - { - mobj->z = mobj->ceilingz - mobj->info->height; - } - else if (z == FLOATRANDZ) - { - space = ((mobj->ceilingz) - (mobj->info->height)) - mobj->floorz; - if (space > 48 * FRACUNIT) - { - space -= 40 * FRACUNIT; - mobj->z = - ((space * P_Random()) >> 8) + mobj->floorz + 40 * FRACUNIT; - } - else - { - mobj->z = mobj->floorz; - } - } - else - { - mobj->z = z; - } - if (mobj->flags2 & MF2_FOOTCLIP - && P_GetThingFloorType(mobj) != FLOOR_SOLID - && mobj->floorz == mobj->subsector->sector->floorheight) - { - mobj->flags2 |= MF2_FEETARECLIPPED; - } - else - { - mobj->flags2 &= ~MF2_FEETARECLIPPED; - } - - mobj->thinker.function = P_MobjThinker; - P_AddThinker(&mobj->thinker); - return (mobj); -} - -/* -=============== -= -= P_RemoveMobj -= -=============== -*/ - -void P_RemoveMobj(mobj_t * mobj) -{ -// unlink from sector and block lists - P_UnsetThingPosition(mobj); -// stop any playing sound - S_StopSound(mobj); -// free block - P_RemoveThinker((thinker_t *) mobj); -} - -//============================================================================= - - -/* -============ -= -= P_SpawnPlayer -= -= Called when a player is spawned on the level -= Most of the player structure stays unchanged between levels -============ -*/ - -void P_SpawnPlayer(mapthing_t * mthing) -{ - player_t *p; - fixed_t x, y, z; - mobj_t *mobj; - int i; - - if (!playeringame[mthing->type - 1]) - return; // not playing - - p = &players[mthing->type - 1]; - - if (p->playerstate == PST_REBORN) - G_PlayerReborn(mthing->type - 1); - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - z = ONFLOORZ; - mobj = P_SpawnMobj(x, y, z, MT_PLAYER); - if (mthing->type > 1) // set color translations for player sprites - mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT; - - mobj->angle = ANG45 * (mthing->angle / 45); - mobj->player = p; - mobj->health = p->health; - p->mo = mobj; - p->playerstate = PST_LIVE; - p->refire = 0; - p->message = NULL; - p->damagecount = 0; - p->bonuscount = 0; - p->chickenTics = 0; - p->rain1 = NULL; - p->rain2 = NULL; - p->extralight = 0; - p->fixedcolormap = 0; - p->viewheight = VIEWHEIGHT; - P_SetupPsprites(p); // setup gun psprite - if (deathmatch) - { // Give all keys in death match mode - for (i = 0; i < NUM_KEY_TYPES; i++) - { - p->keys[i] = true; - if (p == &players[consoleplayer]) - { - playerkeys = 7; - UpdateState |= I_STATBAR; - } - } - } - else if (p == &players[consoleplayer]) - { - playerkeys = 0; - UpdateState |= I_STATBAR; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_SpawnMapThing -// -// The fields of the mapthing should already be in host byte order. -// -//---------------------------------------------------------------------------- - -void P_SpawnMapThing(mapthing_t * mthing) -{ - int i; - int bit; - mobj_t *mobj; - fixed_t x, y, z; - -// count deathmatch start positions - if (mthing->type == 11) - { - if (deathmatch_p < &deathmatchstarts[10]) - { - memcpy(deathmatch_p, mthing, sizeof(*mthing)); - deathmatch_p++; - } - return; - } - -// check for players specially - if (mthing->type <= 4) - { - // save spots for respawning in network games - playerstarts[mthing->type - 1] = *mthing; - playerstartsingame[mthing->type - 1] = true; - if (!deathmatch) - { - P_SpawnPlayer(mthing); - } - return; - } - - // Ambient sound sequences - if (mthing->type >= 1200 && mthing->type < 1300) - { - P_AddAmbientSfx(mthing->type - 1200); - return; - } - - // Check for boss spots - if (mthing->type == 56) // Monster_BossSpot - { - P_AddBossSpot(mthing->x << FRACBITS, mthing->y << FRACBITS, - ANG45 * (mthing->angle / 45)); - return; - } - -// check for appropriate skill level - if (!netgame && (mthing->options & 16)) - return; - - if (gameskill == sk_baby) - bit = 1; - else if (gameskill == sk_nightmare) - bit = 4; - else - bit = 1 << (gameskill - 1); - if (!(mthing->options & bit)) - return; - -// find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) - I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)", mthing->type, - mthing->x, mthing->y); - -// don't spawn keys and players in deathmatch - if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) - return; - -// don't spawn any monsters if -nomonsters - if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) - return; - -// spawn it - switch (i) - { // Special stuff - case MT_WSKULLROD: - case MT_WPHOENIXROD: - case MT_AMSKRDWIMPY: - case MT_AMSKRDHEFTY: - case MT_AMPHRDWIMPY: - case MT_AMPHRDHEFTY: - case MT_AMMACEWIMPY: - case MT_AMMACEHEFTY: - case MT_ARTISUPERHEAL: - case MT_ARTITELEPORT: - case MT_ITEMSHIELD2: - if (gamemode == shareware) - { // Don't place on map in shareware version - return; - } - break; - case MT_WMACE: - if (gamemode != shareware) - { // Put in the mace spot list - P_AddMaceSpot(mthing); - return; - } - return; - default: - break; - } - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - if (mobjinfo[i].flags & MF_SPAWNCEILING) - { - z = ONCEILINGZ; - } - else if (mobjinfo[i].flags2 & MF2_SPAWNFLOAT) - { - z = FLOATRANDZ; - } - else - { - z = ONFLOORZ; - } - mobj = P_SpawnMobj(x, y, z, i); - if (mobj->flags2 & MF2_FLOATBOB) - { // Seed random starting index for bobbing motion - mobj->health = P_Random(); - } - if (mobj->tics > 0) - { - mobj->tics = 1 + (P_Random() % mobj->tics); - } - if (mobj->flags & MF_COUNTKILL) - { - totalkills++; - mobj->spawnpoint = *mthing; - } - if (mobj->flags & MF_COUNTITEM) - { - totalitems++; - } - mobj->angle = ANG45 * (mthing->angle / 45); - if (mthing->options & MTF_AMBUSH) - { - mobj->flags |= MF_AMBUSH; - } -} - -/* -=============================================================================== - - GAME SPAWN FUNCTIONS - -=============================================================================== -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_SpawnPuff -// -//--------------------------------------------------------------------------- - - -void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z) -{ - mobj_t *puff; - - z += (P_SubRandom() << 10); - puff = P_SpawnMobj(x, y, z, PuffType); - if (puff->info->attacksound) - { - S_StartSound(puff, puff->info->attacksound); - } - switch (PuffType) - { - case MT_BEAKPUFF: - case MT_STAFFPUFF: - puff->momz = FRACUNIT; - break; - case MT_GAUNTLETPUFF1: - case MT_GAUNTLETPUFF2: - puff->momz = (fixed_t)(.8 * FRACUNIT); - default: - break; - } -} - -/* -================ -= -= P_SpawnBlood -= -================ -*/ - -/* -void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) -{ - mobj_t *th; - - z += (P_SubRandom()<<10); - th = P_SpawnMobj (x,y,z, MT_BLOOD); - th->momz = FRACUNIT*2; - th->tics -= P_Random()&3; - - if (damage <= 12 && damage >= 9) - P_SetMobjState (th,S_BLOOD2); - else if (damage < 9) - P_SetMobjState (th,S_BLOOD3); -} -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_BloodSplatter -// -//--------------------------------------------------------------------------- - -void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator) -{ - mobj_t *mo; - - mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER); - mo->target = originator; - mo->momx = P_SubRandom() << 9; - mo->momy = P_SubRandom() << 9; - mo->momz = FRACUNIT * 2; -} - -//--------------------------------------------------------------------------- -// -// PROC P_RipperBlood -// -//--------------------------------------------------------------------------- - -void P_RipperBlood(mobj_t * mo) -{ - mobj_t *th; - fixed_t x, y, z; - - x = mo->x + (P_SubRandom() << 12); - y = mo->y + (P_SubRandom() << 12); - z = mo->z + (P_SubRandom() << 12); - th = P_SpawnMobj(x, y, z, MT_BLOOD); - th->flags |= MF_NOGRAVITY; - th->momx = mo->momx >> 1; - th->momy = mo->momy >> 1; - th->tics += P_Random() & 3; -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GetThingFloorType -// -//--------------------------------------------------------------------------- - -int P_GetThingFloorType(mobj_t * thing) -{ - return (TerrainTypes[thing->subsector->sector->floorpic]); -/* - if(thing->subsector->sector->floorpic - == W_GetNumForName("FLTWAWA1")-firstflat) - { - return(FLOOR_WATER); - } - else - { - return(FLOOR_SOLID); - } -*/ -} - -//--------------------------------------------------------------------------- -// -// FUNC P_HitFloor -// -//--------------------------------------------------------------------------- - -int P_HitFloor(mobj_t * thing) -{ - mobj_t *mo; - - if (thing->floorz != thing->subsector->sector->floorheight) - { // don't splash if landing on the edge above water/lava/etc.... - return (FLOOR_SOLID); - } - switch (P_GetThingFloorType(thing)) - { - case FLOOR_WATER: - P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE); - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH); - mo->target = thing; - mo->momx = P_SubRandom() << 8; - mo->momy = P_SubRandom() << 8; - mo->momz = 2 * FRACUNIT + (P_Random() << 8); - S_StartSound(mo, sfx_gloop); - return (FLOOR_WATER); - case FLOOR_LAVA: - P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH); - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE); - mo->momz = FRACUNIT + (P_Random() << 7); - S_StartSound(mo, sfx_burn); - return (FLOOR_LAVA); - case FLOOR_SLUDGE: - P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGESPLASH); - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK); - mo->target = thing; - mo->momx = P_SubRandom() << 8; - mo->momy = P_SubRandom() << 8; - mo->momz = FRACUNIT + (P_Random() << 8); - return (FLOOR_SLUDGE); - } - return (FLOOR_SOLID); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_CheckMissileSpawn -// -// Returns true if the missile is at a valid spawn point, otherwise -// explodes it and returns false. -// -//--------------------------------------------------------------------------- - -boolean P_CheckMissileSpawn(mobj_t * missile) -{ - //missile->tics -= P_Random()&3; - - // move a little forward so an angle can be computed if it - // immediately explodes - missile->x += (missile->momx >> 1); - missile->y += (missile->momy >> 1); - missile->z += (missile->momz >> 1); - if (!P_TryMove(missile, missile->x, missile->y)) - { - P_ExplodeMissile(missile); - return (false); - } - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_SpawnMissile -// -// Returns NULL if the missile exploded immediately, otherwise returns -// a mobj_t pointer to the missile. -// -//--------------------------------------------------------------------------- - -mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type) -{ - fixed_t z; - mobj_t *th; - angle_t an; - int dist; - - switch (type) - { - case MT_MNTRFX1: // Minotaur swing attack missile - z = source->z + 40 * FRACUNIT; - break; - case MT_MNTRFX2: // Minotaur floor fire missile - z = ONFLOORZ; - break; - case MT_SRCRFX1: // Sorcerer Demon fireball - z = source->z + 48 * FRACUNIT; - break; - case MT_KNIGHTAXE: // Knight normal axe - case MT_REDAXE: // Knight red power axe - z = source->z + 36 * FRACUNIT; - break; - default: - z = source->z + 32 * FRACUNIT; - break; - } - if (source->flags2 & MF2_FEETARECLIPPED) - { - z -= FOOTCLIPSIZE; - } - th = P_SpawnMobj(source->x, source->y, z, type); - if (th->info->seesound) - { - S_StartSound(th, th->info->seesound); - } - th->target = source; // Originator - an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); - if (dest->flags & MF_SHADOW) - { // Invisible target - an += P_SubRandom() << 21; - } - th->angle = an; - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul(th->info->speed, finecosine[an]); - th->momy = FixedMul(th->info->speed, finesine[an]); - dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); - dist = dist / th->info->speed; - if (dist < 1) - { - dist = 1; - } - th->momz = (dest->z - source->z) / dist; - return (P_CheckMissileSpawn(th) ? th : NULL); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_SpawnMissileAngle -// -// Returns NULL if the missile exploded immediately, otherwise returns -// a mobj_t pointer to the missile. -// -//--------------------------------------------------------------------------- - -mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, - angle_t angle, fixed_t momz) -{ - fixed_t z; - mobj_t *mo; - - switch (type) - { - case MT_MNTRFX1: // Minotaur swing attack missile - z = source->z + 40 * FRACUNIT; - break; - case MT_MNTRFX2: // Minotaur floor fire missile - z = ONFLOORZ; - break; - case MT_SRCRFX1: // Sorcerer Demon fireball - z = source->z + 48 * FRACUNIT; - break; - default: - z = source->z + 32 * FRACUNIT; - break; - } - if (source->flags2 & MF2_FEETARECLIPPED) - { - z -= FOOTCLIPSIZE; - } - mo = P_SpawnMobj(source->x, source->y, z, type); - if (mo->info->seesound) - { - S_StartSound(mo, mo->info->seesound); - } - mo->target = source; // Originator - mo->angle = angle; - angle >>= ANGLETOFINESHIFT; - mo->momx = FixedMul(mo->info->speed, finecosine[angle]); - mo->momy = FixedMul(mo->info->speed, finesine[angle]); - mo->momz = momz; - return (P_CheckMissileSpawn(mo) ? mo : NULL); -} - -/* -================ -= -= P_SpawnPlayerMissile -= -= Tries to aim at a nearby monster -================ -*/ - -mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type) -{ - angle_t an; - fixed_t x, y, z, slope; - - // Try to find a target - an = source->angle; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an += 1 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an -= 2 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - } - if (!linetarget) - { - an = source->angle; - slope = ((source->player->lookdir) << FRACBITS) / 173; - } - } - x = source->x; - y = source->y; - z = source->z + 4 * 8 * FRACUNIT + - ((source->player->lookdir) << FRACBITS) / 173; - if (source->flags2 & MF2_FEETARECLIPPED) - { - z -= FOOTCLIPSIZE; - } - MissileMobj = P_SpawnMobj(x, y, z, type); - if (MissileMobj->info->seesound) - { - S_StartSound(MissileMobj, MissileMobj->info->seesound); - } - MissileMobj->target = source; - MissileMobj->angle = an; - MissileMobj->momx = FixedMul(MissileMobj->info->speed, - finecosine[an >> ANGLETOFINESHIFT]); - MissileMobj->momy = FixedMul(MissileMobj->info->speed, - finesine[an >> ANGLETOFINESHIFT]); - MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope); - if (MissileMobj->type == MT_BLASTERFX1) - { // Ultra-fast ripper spawning missile - MissileMobj->x += (MissileMobj->momx >> 3); - MissileMobj->y += (MissileMobj->momy >> 3); - MissileMobj->z += (MissileMobj->momz >> 3); - } - else - { // Normal missile - MissileMobj->x += (MissileMobj->momx >> 1); - MissileMobj->y += (MissileMobj->momy >> 1); - MissileMobj->z += (MissileMobj->momz >> 1); - } - if (!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y)) - { // Exploded immediately - P_ExplodeMissile(MissileMobj); - return (NULL); - } - return (MissileMobj); -} - -//--------------------------------------------------------------------------- -// -// PROC P_SPMAngle -// -//--------------------------------------------------------------------------- - -mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle) -{ - mobj_t *th; - angle_t an; - fixed_t x, y, z, slope; - -// -// see which target is to be aimed at -// - an = angle; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an += 1 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an -= 2 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - } - if (!linetarget) - { - an = angle; - slope = ((source->player->lookdir) << FRACBITS) / 173; - } - } - x = source->x; - y = source->y; - z = source->z + 4 * 8 * FRACUNIT + - ((source->player->lookdir) << FRACBITS) / 173; - if (source->flags2 & MF2_FEETARECLIPPED) - { - z -= FOOTCLIPSIZE; - } - th = P_SpawnMobj(x, y, z, type); - if (th->info->seesound) - { - S_StartSound(th, th->info->seesound); - } - th->target = source; - th->angle = an; - th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); - th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); - th->momz = FixedMul(th->info->speed, slope); - return (P_CheckMissileSpawn(th) ? th : NULL); -} - -//--------------------------------------------------------------------------- -// -// PROC A_ContMobjSound -// -//--------------------------------------------------------------------------- - -void A_ContMobjSound(mobj_t * actor, player_t *player, pspdef_t *psp) -{ - switch (actor->type) - { - case MT_KNIGHTAXE: - S_StartSound(actor, sfx_kgtatk); - break; - case MT_MUMMYFX1: - S_StartSound(actor, sfx_mumhed); - break; - default: - break; - } -} diff --git a/games/NXDoom/src/heretic/p_plats.c b/games/NXDoom/src/heretic/p_plats.c deleted file mode 100644 index 861a9a51a31..00000000000 --- a/games/NXDoom/src/heretic/p_plats.c +++ /dev/null @@ -1,259 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_plats.c - -#include "doomdef.h" -#include "i_system.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -plat_t *activeplats[MAXPLATS]; - -//================================================================== -// -// Move a plat up and down -// -//================================================================== -void T_PlatRaise(thinker_t *thinker) -{ - plat_t *plat = (plat_t *) thinker; - result_e res; - - switch (plat->status) - { - case up: - res = T_MovePlane(plat->sector, plat->speed, - plat->high, plat->crush, 0, 1); - if (!(leveltime & 31)) - { - S_StartSound(&plat->sector->soundorg, sfx_stnmov); - } - if (plat->type == raiseAndChange - || plat->type == raiseToNearestAndChange) - { - if (!(leveltime & 7)) - { - S_StartSound(&plat->sector->soundorg, - sfx_stnmov); - } - } - if (res == crushed && (!plat->crush)) - { - plat->count = plat->wait; - plat->status = down; - S_StartSound(&plat->sector->soundorg, sfx_pstart); - } - else if (res == pastdest) - { - plat->count = plat->wait; - plat->status = waiting; - S_StartSound(&plat->sector->soundorg, sfx_pstop); - switch (plat->type) - { - case downWaitUpStay: - P_RemoveActivePlat(plat); - break; - case raiseAndChange: - P_RemoveActivePlat(plat); - break; - default: - break; - } - } - break; - case down: - res = - T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, - -1); - if (res == pastdest) - { - plat->count = plat->wait; - plat->status = waiting; - S_StartSound(&plat->sector->soundorg, sfx_pstop); - } - else - { - if (!(leveltime & 31)) - { - S_StartSound(&plat->sector->soundorg, - sfx_stnmov); - } - } - break; - case waiting: - if (!--plat->count) - { - if (plat->sector->floorheight == plat->low) - plat->status = up; - else - plat->status = down; - S_StartSound(&plat->sector->soundorg, sfx_pstart); - } - case in_stasis: - break; - } -} - -//================================================================== -// -// Do Platforms -// "amount" is only used for SOME platforms. -// -//================================================================== -int EV_DoPlat(line_t * line, plattype_e type, int amount) -{ - plat_t *plat; - int secnum; - int rtn; - sector_t *sec; - - secnum = -1; - rtn = 0; - - // - // Activate all plats that are in_stasis - // - switch (type) - { - case perpetualRaise: - P_ActivateInStasis(line->tag); - break; - default: - break; - } - - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - // - // Find lowest & highest floors around sector - // - rtn = 1; - plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, 0); - P_AddThinker(&plat->thinker); - - plat->type = type; - plat->sector = sec; - plat->sector->specialdata = plat; - plat->thinker.function = T_PlatRaise; - plat->crush = false; - plat->tag = line->tag; - switch (type) - { - case raiseToNearestAndChange: - plat->speed = PLATSPEED / 2; - sec->floorpic = sides[line->sidenum[0]].sector->floorpic; - plat->high = P_FindNextHighestFloor(sec, sec->floorheight); - plat->wait = 0; - plat->status = up; - sec->special = 0; // NO MORE DAMAGE, IF APPLICABLE - S_StartSound(&sec->soundorg, sfx_stnmov); - break; - case raiseAndChange: - plat->speed = PLATSPEED / 2; - sec->floorpic = sides[line->sidenum[0]].sector->floorpic; - plat->high = sec->floorheight + amount * FRACUNIT; - plat->wait = 0; - plat->status = up; - S_StartSound(&sec->soundorg, sfx_stnmov); - break; - case downWaitUpStay: - plat->speed = PLATSPEED * 4; - plat->low = P_FindLowestFloorSurrounding(sec); - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - plat->high = sec->floorheight; - plat->wait = 35 * PLATWAIT; - plat->status = down; - S_StartSound(&sec->soundorg, sfx_pstart); - break; - case perpetualRaise: - plat->speed = PLATSPEED; - plat->low = P_FindLowestFloorSurrounding(sec); - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - plat->high = P_FindHighestFloorSurrounding(sec); - if (plat->high < sec->floorheight) - plat->high = sec->floorheight; - plat->wait = 35 * PLATWAIT; - plat->status = P_Random() & 1; - S_StartSound(&sec->soundorg, sfx_pstart); - break; - } - P_AddActivePlat(plat); - } - return rtn; -} - -void P_ActivateInStasis(int tag) -{ - int i; - - for (i = 0; i < MAXPLATS; i++) - if (activeplats[i] && - (activeplats[i])->tag == tag && - (activeplats[i])->status == in_stasis) - { - (activeplats[i])->status = (activeplats[i])->oldstatus; - (activeplats[i])->thinker.function = T_PlatRaise; - } -} - -void EV_StopPlat(line_t * line) -{ - int j; - - for (j = 0; j < MAXPLATS; j++) - if (activeplats[j] && ((activeplats[j])->status != in_stasis) && - ((activeplats[j])->tag == line->tag)) - { - (activeplats[j])->oldstatus = (activeplats[j])->status; - (activeplats[j])->status = in_stasis; - (activeplats[j])->thinker.function = NULL; - } -} - -void P_AddActivePlat(plat_t * plat) -{ - int i; - for (i = 0; i < MAXPLATS; i++) - if (activeplats[i] == NULL) - { - activeplats[i] = plat; - return; - } - I_Error("P_AddActivePlat: no more plats!"); -} - -void P_RemoveActivePlat(plat_t * plat) -{ - int i; - for (i = 0; i < MAXPLATS; i++) - if (plat == activeplats[i]) - { - (activeplats[i])->sector->specialdata = NULL; - P_RemoveThinker(&(activeplats[i])->thinker); - activeplats[i] = NULL; - return; - } - I_Error("P_RemoveActivePlat: can't find plat!"); -} diff --git a/games/NXDoom/src/heretic/p_pspr.c b/games/NXDoom/src/heretic/p_pspr.c deleted file mode 100644 index 10e967dd6c9..00000000000 --- a/games/NXDoom/src/heretic/p_pspr.c +++ /dev/null @@ -1,1907 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_pspr.c - -#include "doomdef.h" -#include "i_system.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" - -// Macros - -#define LOWERSPEED FRACUNIT*6 -#define RAISESPEED FRACUNIT*6 -#define WEAPONBOTTOM 128*FRACUNIT -#define WEAPONTOP 32*FRACUNIT -#define FLAME_THROWER_TICS 10*35 -#define MAGIC_JUNK 1234 -#define MAX_MACE_SPOTS 8 - -static int MaceSpotCount; -static struct -{ - fixed_t x; - fixed_t y; -} MaceSpots[MAX_MACE_SPOTS]; - -fixed_t bulletslope; - -static int WeaponAmmoUsePL1[NUMWEAPONS] = { - 0, // staff - USE_GWND_AMMO_1, // gold wand - USE_CBOW_AMMO_1, // crossbow - USE_BLSR_AMMO_1, // blaster - USE_SKRD_AMMO_1, // skull rod - USE_PHRD_AMMO_1, // phoenix rod - USE_MACE_AMMO_1, // mace - 0, // gauntlets - 0 // beak -}; - -static int WeaponAmmoUsePL2[NUMWEAPONS] = { - 0, // staff - USE_GWND_AMMO_2, // gold wand - USE_CBOW_AMMO_2, // crossbow - USE_BLSR_AMMO_2, // blaster - USE_SKRD_AMMO_2, // skull rod - USE_PHRD_AMMO_2, // phoenix rod - USE_MACE_AMMO_2, // mace - 0, // gauntlets - 0 // beak -}; - -weaponinfo_t wpnlev1info[NUMWEAPONS] = { - { // Staff - am_noammo, // ammo - S_STAFFUP, // upstate - S_STAFFDOWN, // downstate - S_STAFFREADY, // readystate - S_STAFFATK1_1, // atkstate - S_STAFFATK1_1, // holdatkstate - S_NULL // flashstate - }, - { // Gold wand - am_goldwand, // ammo - S_GOLDWANDUP, // upstate - S_GOLDWANDDOWN, // downstate - S_GOLDWANDREADY, // readystate - S_GOLDWANDATK1_1, // atkstate - S_GOLDWANDATK1_1, // holdatkstate - S_NULL // flashstate - }, - { // Crossbow - am_crossbow, // ammo - S_CRBOWUP, // upstate - S_CRBOWDOWN, // downstate - S_CRBOW1, // readystate - S_CRBOWATK1_1, // atkstate - S_CRBOWATK1_1, // holdatkstate - S_NULL // flashstate - }, - { // Blaster - am_blaster, // ammo - S_BLASTERUP, // upstate - S_BLASTERDOWN, // downstate - S_BLASTERREADY, // readystate - S_BLASTERATK1_1, // atkstate - S_BLASTERATK1_3, // holdatkstate - S_NULL // flashstate - }, - { // Skull rod - am_skullrod, // ammo - S_HORNRODUP, // upstate - S_HORNRODDOWN, // downstate - S_HORNRODREADY, // readystae - S_HORNRODATK1_1, // atkstate - S_HORNRODATK1_1, // holdatkstate - S_NULL // flashstate - }, - { // Phoenix rod - am_phoenixrod, // ammo - S_PHOENIXUP, // upstate - S_PHOENIXDOWN, // downstate - S_PHOENIXREADY, // readystate - S_PHOENIXATK1_1, // atkstate - S_PHOENIXATK1_1, // holdatkstate - S_NULL // flashstate - }, - { // Mace - am_mace, // ammo - S_MACEUP, // upstate - S_MACEDOWN, // downstate - S_MACEREADY, // readystate - S_MACEATK1_1, // atkstate - S_MACEATK1_2, // holdatkstate - S_NULL // flashstate - }, - { // Gauntlets - am_noammo, // ammo - S_GAUNTLETUP, // upstate - S_GAUNTLETDOWN, // downstate - S_GAUNTLETREADY, // readystate - S_GAUNTLETATK1_1, // atkstate - S_GAUNTLETATK1_3, // holdatkstate - S_NULL // flashstate - }, - { // Beak - am_noammo, // ammo - S_BEAKUP, // upstate - S_BEAKDOWN, // downstate - S_BEAKREADY, // readystate - S_BEAKATK1_1, // atkstate - S_BEAKATK1_1, // holdatkstate - S_NULL // flashstate - } -}; - -weaponinfo_t wpnlev2info[NUMWEAPONS] = { - { // Staff - am_noammo, // ammo - S_STAFFUP2, // upstate - S_STAFFDOWN2, // downstate - S_STAFFREADY2_1, // readystate - S_STAFFATK2_1, // atkstate - S_STAFFATK2_1, // holdatkstate - S_NULL // flashstate - }, - { // Gold wand - am_goldwand, // ammo - S_GOLDWANDUP, // upstate - S_GOLDWANDDOWN, // downstate - S_GOLDWANDREADY, // readystate - S_GOLDWANDATK2_1, // atkstate - S_GOLDWANDATK2_1, // holdatkstate - S_NULL // flashstate - }, - { // Crossbow - am_crossbow, // ammo - S_CRBOWUP, // upstate - S_CRBOWDOWN, // downstate - S_CRBOW1, // readystate - S_CRBOWATK2_1, // atkstate - S_CRBOWATK2_1, // holdatkstate - S_NULL // flashstate - }, - { // Blaster - am_blaster, // ammo - S_BLASTERUP, // upstate - S_BLASTERDOWN, // downstate - S_BLASTERREADY, // readystate - S_BLASTERATK2_1, // atkstate - S_BLASTERATK2_3, // holdatkstate - S_NULL // flashstate - }, - { // Skull rod - am_skullrod, // ammo - S_HORNRODUP, // upstate - S_HORNRODDOWN, // downstate - S_HORNRODREADY, // readystae - S_HORNRODATK2_1, // atkstate - S_HORNRODATK2_1, // holdatkstate - S_NULL // flashstate - }, - { // Phoenix rod - am_phoenixrod, // ammo - S_PHOENIXUP, // upstate - S_PHOENIXDOWN, // downstate - S_PHOENIXREADY, // readystate - S_PHOENIXATK2_1, // atkstate - S_PHOENIXATK2_2, // holdatkstate - S_NULL // flashstate - }, - { // Mace - am_mace, // ammo - S_MACEUP, // upstate - S_MACEDOWN, // downstate - S_MACEREADY, // readystate - S_MACEATK2_1, // atkstate - S_MACEATK2_1, // holdatkstate - S_NULL // flashstate - }, - { // Gauntlets - am_noammo, // ammo - S_GAUNTLETUP2, // upstate - S_GAUNTLETDOWN2, // downstate - S_GAUNTLETREADY2_1, // readystate - S_GAUNTLETATK2_1, // atkstate - S_GAUNTLETATK2_3, // holdatkstate - S_NULL // flashstate - }, - { // Beak - am_noammo, // ammo - S_BEAKUP, // upstate - S_BEAKDOWN, // downstate - S_BEAKREADY, // readystate - S_BEAKATK2_1, // atkstate - S_BEAKATK2_1, // holdatkstate - S_NULL // flashstate - } -}; - -//--------------------------------------------------------------------------- -// -// PROC P_OpenWeapons -// -// Called at level load before things are loaded. -// -//--------------------------------------------------------------------------- - -void P_OpenWeapons(void) -{ - MaceSpotCount = 0; -} - -//--------------------------------------------------------------------------- -// -// PROC P_AddMaceSpot -// -//--------------------------------------------------------------------------- - -void P_AddMaceSpot(mapthing_t * mthing) -{ - if (MaceSpotCount == MAX_MACE_SPOTS) - { - I_Error("Too many mace spots."); - } - MaceSpots[MaceSpotCount].x = mthing->x << FRACBITS; - MaceSpots[MaceSpotCount].y = mthing->y << FRACBITS; - MaceSpotCount++; -} - -//--------------------------------------------------------------------------- -// -// PROC P_RepositionMace -// -// Chooses the next spot to place the mace. -// -//--------------------------------------------------------------------------- - -void P_RepositionMace(mobj_t * mo) -{ - int spot; - subsector_t *ss; - - P_UnsetThingPosition(mo); - spot = P_Random() % MaceSpotCount; - mo->x = MaceSpots[spot].x; - mo->y = MaceSpots[spot].y; - ss = R_PointInSubsector(mo->x, mo->y); - mo->z = mo->floorz = ss->sector->floorheight; - mo->ceilingz = ss->sector->ceilingheight; - P_SetThingPosition(mo); -} - -//--------------------------------------------------------------------------- -// -// PROC P_CloseWeapons -// -// Called at level load after things are loaded. -// -//--------------------------------------------------------------------------- - -void P_CloseWeapons(void) -{ - int spot; - - if (!MaceSpotCount) - { // No maces placed - return; - } - if (!deathmatch && P_Random() < 64) - { // Sometimes doesn't show up if not in deathmatch - return; - } - spot = P_Random() % MaceSpotCount; - P_SpawnMobj(MaceSpots[spot].x, MaceSpots[spot].y, ONFLOORZ, MT_WMACE); -} - -//--------------------------------------------------------------------------- -// -// PROC P_SetPsprite -// -//--------------------------------------------------------------------------- - -void P_SetPsprite(player_t * player, int position, statenum_t stnum) -{ - pspdef_t *psp; - state_t *state; - - psp = &player->psprites[position]; - do - { - if (!stnum) - { // Object removed itself. - psp->state = NULL; - break; - } - state = &states[stnum]; - psp->state = state; - psp->tics = state->tics; // could be 0 - if (state->misc1) - { // Set coordinates. - psp->sx = state->misc1 << FRACBITS; - psp->sy = state->misc2 << FRACBITS; - } - if (state->action) - { // Call action routine. - state->action(NULL, player, psp); - if (!psp->state) - { - break; - } - } - stnum = psp->state->nextstate; - } - while (!psp->tics); // An initial state of 0 could cycle through. -} - -/* -================= -= -= P_CalcSwing -= -================= -*/ - -/* -fixed_t swingx, swingy; -void P_CalcSwing (player_t *player) -{ - fixed_t swing; - int angle; - -// OPTIMIZE: tablify this - - swing = player->bob; - - angle = (FINEANGLES/70*leveltime)&FINEMASK; - swingx = FixedMul ( swing, finesine[angle]); - - angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; - swingy = -FixedMul ( swingx, finesine[angle]); -} -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_ActivateBeak -// -//--------------------------------------------------------------------------- - -void P_ActivateBeak(player_t * player) -{ - player->pendingweapon = wp_nochange; - player->readyweapon = wp_beak; - player->psprites[ps_weapon].sy = WEAPONTOP; - P_SetPsprite(player, ps_weapon, S_BEAKREADY); -} - -//--------------------------------------------------------------------------- -// -// PROC P_PostChickenWeapon -// -//--------------------------------------------------------------------------- - -void P_PostChickenWeapon(player_t * player, weapontype_t weapon) -{ - if (weapon == wp_beak) - { // Should never happen - weapon = wp_staff; - } - player->pendingweapon = wp_nochange; - player->readyweapon = weapon; - player->psprites[ps_weapon].sy = WEAPONBOTTOM; - P_SetPsprite(player, ps_weapon, wpnlev1info[weapon].upstate); -} - -//--------------------------------------------------------------------------- -// -// PROC P_BringUpWeapon -// -// Starts bringing the pending weapon up from the bottom of the screen. -// -//--------------------------------------------------------------------------- - -void P_BringUpWeapon(player_t * player) -{ - statenum_t new; - - if (player->pendingweapon == wp_nochange) - { - player->pendingweapon = player->readyweapon; - } - if (player->pendingweapon == wp_gauntlets) - { - S_StartSound(player->mo, sfx_gntact); - } - if (player->powers[pw_weaponlevel2]) - { - new = wpnlev2info[player->pendingweapon].upstate; - } - else - { - new = wpnlev1info[player->pendingweapon].upstate; - } - player->pendingweapon = wp_nochange; - player->psprites[ps_weapon].sy = WEAPONBOTTOM; - P_SetPsprite(player, ps_weapon, new); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_CheckAmmo -// -// Returns true if there is enough ammo to shoot. If not, selects the -// next weapon to use. -// -//--------------------------------------------------------------------------- - -boolean P_CheckAmmo(player_t * player) -{ - ammotype_t ammo; - int *ammoUse; - int count; - - ammo = wpnlev1info[player->readyweapon].ammo; - if (player->powers[pw_weaponlevel2] && !deathmatch) - { - ammoUse = WeaponAmmoUsePL2; - } - else - { - ammoUse = WeaponAmmoUsePL1; - } - count = ammoUse[player->readyweapon]; - if (ammo == am_noammo || player->ammo[ammo] >= count) - { - return (true); - } - // out of ammo, pick a weapon to change to - do - { - if (player->weaponowned[wp_skullrod] - && player->ammo[am_skullrod] > ammoUse[wp_skullrod]) - { - player->pendingweapon = wp_skullrod; - } - else if (player->weaponowned[wp_blaster] - && player->ammo[am_blaster] > ammoUse[wp_blaster]) - { - player->pendingweapon = wp_blaster; - } - else if (player->weaponowned[wp_crossbow] - && player->ammo[am_crossbow] > ammoUse[wp_crossbow]) - { - player->pendingweapon = wp_crossbow; - } - else if (player->weaponowned[wp_mace] - && player->ammo[am_mace] > ammoUse[wp_mace]) - { - player->pendingweapon = wp_mace; - } - else if (player->ammo[am_goldwand] > ammoUse[wp_goldwand]) - { - player->pendingweapon = wp_goldwand; - } - else if (player->weaponowned[wp_gauntlets]) - { - player->pendingweapon = wp_gauntlets; - } - else if (player->weaponowned[wp_phoenixrod] - && player->ammo[am_phoenixrod] > ammoUse[wp_phoenixrod]) - { - player->pendingweapon = wp_phoenixrod; - } - else - { - player->pendingweapon = wp_staff; - } - } - while (player->pendingweapon == wp_nochange); - if (player->powers[pw_weaponlevel2]) - { - P_SetPsprite(player, ps_weapon, - wpnlev2info[player->readyweapon].downstate); - } - else - { - P_SetPsprite(player, ps_weapon, - wpnlev1info[player->readyweapon].downstate); - } - return (false); -} - -//--------------------------------------------------------------------------- -// -// PROC P_FireWeapon -// -//--------------------------------------------------------------------------- - -void P_FireWeapon(player_t * player) -{ - weaponinfo_t *wpinfo; - statenum_t attackState; - - if (!P_CheckAmmo(player)) - { - return; - } - P_SetMobjState(player->mo, S_PLAY_ATK2); - wpinfo = player->powers[pw_weaponlevel2] ? &wpnlev2info[0] - : &wpnlev1info[0]; - attackState = player->refire ? wpinfo[player->readyweapon].holdatkstate - : wpinfo[player->readyweapon].atkstate; - P_SetPsprite(player, ps_weapon, attackState); - P_NoiseAlert(player->mo, player->mo); - if (player->readyweapon == wp_gauntlets && !player->refire) - { // Play the sound for the initial gauntlet attack - S_StartSound(player->mo, sfx_gntuse); - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_DropWeapon -// -// The player died, so put the weapon away. -// -//--------------------------------------------------------------------------- - -void P_DropWeapon(player_t * player) -{ - if (player->powers[pw_weaponlevel2]) - { - P_SetPsprite(player, ps_weapon, - wpnlev2info[player->readyweapon].downstate); - } - else - { - P_SetPsprite(player, ps_weapon, - wpnlev1info[player->readyweapon].downstate); - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_WeaponReady -// -// The player can fire the weapon or change to another weapon at this time. -// -//--------------------------------------------------------------------------- - -void A_WeaponReady(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int angle; - - if (player->chickenTics) - { // Change to the chicken beak - P_ActivateBeak(player); - return; - } - // Change player from attack state - if (player->mo->state == &states[S_PLAY_ATK1] - || player->mo->state == &states[S_PLAY_ATK2]) - { - P_SetMobjState(player->mo, S_PLAY); - } - // Check for staff PL2 active sound - if ((player->readyweapon == wp_staff) - && (psp->state == &states[S_STAFFREADY2_1]) && P_Random() < 128) - { - S_StartSound(player->mo, sfx_stfcrk); - } - // Put the weapon away if the player has a pending weapon or has - // died. - if (player->pendingweapon != wp_nochange || !player->health) - { - if (player->powers[pw_weaponlevel2]) - { - P_SetPsprite(player, ps_weapon, - wpnlev2info[player->readyweapon].downstate); - } - else - { - P_SetPsprite(player, ps_weapon, - wpnlev1info[player->readyweapon].downstate); - } - return; - } - - // Check for fire. The phoenix rod does not auto fire. - if (player->cmd.buttons & BT_ATTACK) - { - if (!player->attackdown || (player->readyweapon != wp_phoenixrod)) - { - player->attackdown = true; - P_FireWeapon(player); - return; - } - } - else - { - player->attackdown = false; - } - - // Bob the weapon based on movement speed. - angle = (128 * leveltime) & FINEMASK; - psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]); - angle &= FINEANGLES / 2 - 1; - psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]); -} - -//--------------------------------------------------------------------------- -// -// PROC P_UpdateBeak -// -//--------------------------------------------------------------------------- - -void P_UpdateBeak(player_t * player, pspdef_t * psp) -{ - psp->sy = WEAPONTOP + (player->chickenPeck << (FRACBITS - 1)); -} - -//--------------------------------------------------------------------------- -// -// PROC A_BeakReady -// -//--------------------------------------------------------------------------- - -void A_BeakReady(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (player->cmd.buttons & BT_ATTACK) - { // Chicken beak attack - player->attackdown = true; - P_SetMobjState(player->mo, S_CHICPLAY_ATK1); - if (player->powers[pw_weaponlevel2]) - { - P_SetPsprite(player, ps_weapon, S_BEAKATK2_1); - } - else - { - P_SetPsprite(player, ps_weapon, S_BEAKATK1_1); - } - P_NoiseAlert(player->mo, player->mo); - } - else - { - if (player->mo->state == &states[S_CHICPLAY_ATK1]) - { // Take out of attack state - P_SetMobjState(player->mo, S_CHICPLAY); - } - player->attackdown = false; - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_ReFire -// -// The player can re fire the weapon without lowering it entirely. -// -//--------------------------------------------------------------------------- - -void A_ReFire(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if ((player->cmd.buttons & BT_ATTACK) - && player->pendingweapon == wp_nochange && player->health) - { - player->refire++; - P_FireWeapon(player); - } - else - { - player->refire = 0; - P_CheckAmmo(player); - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_Lower -// -//--------------------------------------------------------------------------- - -void A_Lower(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (player->chickenTics) - { - psp->sy = WEAPONBOTTOM; - } - else - { - psp->sy += LOWERSPEED; - } - if (psp->sy < WEAPONBOTTOM) - { // Not lowered all the way yet - return; - } - if (player->playerstate == PST_DEAD) - { // Player is dead, so don't bring up a pending weapon - psp->sy = WEAPONBOTTOM; - return; - } - if (!player->health) - { // Player is dead, so keep the weapon off screen - P_SetPsprite(player, ps_weapon, S_NULL); - return; - } - player->readyweapon = player->pendingweapon; - P_BringUpWeapon(player); -} - -//--------------------------------------------------------------------------- -// -// PROC A_BeakRaise -// -//--------------------------------------------------------------------------- - -void A_BeakRaise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - psp->sy = WEAPONTOP; - P_SetPsprite(player, ps_weapon, - wpnlev1info[player->readyweapon].readystate); -} - -//--------------------------------------------------------------------------- -// -// PROC A_Raise -// -//--------------------------------------------------------------------------- - -void A_Raise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - psp->sy -= RAISESPEED; - if (psp->sy > WEAPONTOP) - { // Not raised all the way yet - return; - } - psp->sy = WEAPONTOP; - if (player->powers[pw_weaponlevel2]) - { - P_SetPsprite(player, ps_weapon, - wpnlev2info[player->readyweapon].readystate); - } - else - { - P_SetPsprite(player, ps_weapon, - wpnlev1info[player->readyweapon].readystate); - } -} - -/* -=============== -= -= P_BulletSlope -= -= Sets a slope so a near miss is at aproximately the height of the -= intended target -= -=============== -*/ - -void P_BulletSlope(mobj_t * mo) -{ - angle_t an; - -// -// see which target is to be aimed at -// - an = mo->angle; - bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an += 1 << 26; - bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an -= 2 << 26; - bulletslope = P_AimLineAttack(mo, an, 16 * 64 * FRACUNIT); - } - if (!linetarget) - { - an += 2 << 26; - bulletslope = (mo->player->lookdir << FRACBITS) / 173; - } - } -} - -//**************************************************************************** -// -// WEAPON ATTACKS -// -//**************************************************************************** - -//---------------------------------------------------------------------------- -// -// PROC A_BeakAttackPL1 -// -//---------------------------------------------------------------------------- - -void A_BeakAttackPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - - damage = 1 + (P_Random() & 3); - angle = player->mo->angle; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - PuffType = MT_BEAKPUFF; - P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); - if (linetarget) - { - player->mo->angle = R_PointToAngle2(player->mo->x, - player->mo->y, linetarget->x, - linetarget->y); - } - S_StartSound(player->mo, sfx_chicpk1 + (P_Random() % 3)); - player->chickenPeck = 12; - psp->tics -= P_Random() & 7; -} - -//---------------------------------------------------------------------------- -// -// PROC A_BeakAttackPL2 -// -//---------------------------------------------------------------------------- - -void A_BeakAttackPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - - damage = HITDICE(4); - angle = player->mo->angle; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - PuffType = MT_BEAKPUFF; - P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); - if (linetarget) - { - player->mo->angle = R_PointToAngle2(player->mo->x, - player->mo->y, linetarget->x, - linetarget->y); - } - S_StartSound(player->mo, sfx_chicpk1 + (P_Random() % 3)); - player->chickenPeck = 12; - psp->tics -= P_Random() & 3; -} - -//---------------------------------------------------------------------------- -// -// PROC A_StaffAttackPL1 -// -//---------------------------------------------------------------------------- - -void A_StaffAttackPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - - damage = 5 + (P_Random() & 15); - angle = player->mo->angle; - angle += P_SubRandom() << 18; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - PuffType = MT_STAFFPUFF; - P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); - if (linetarget) - { - //S_StartSound(player->mo, sfx_stfhit); - // turn to face target - player->mo->angle = R_PointToAngle2(player->mo->x, - player->mo->y, linetarget->x, - linetarget->y); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_StaffAttackPL2 -// -//---------------------------------------------------------------------------- - -void A_StaffAttackPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - - // P_inter.c:P_DamageMobj() handles target momentums - damage = 18 + (P_Random() & 63); - angle = player->mo->angle; - angle += P_SubRandom() << 18; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - PuffType = MT_STAFFPUFF2; - P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); - if (linetarget) - { - //S_StartSound(player->mo, sfx_stfpow); - // turn to face target - player->mo->angle = R_PointToAngle2(player->mo->x, - player->mo->y, linetarget->x, - linetarget->y); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireBlasterPL1 -// -//---------------------------------------------------------------------------- - -void A_FireBlasterPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - int damage; - - mo = player->mo; - S_StartSound(mo, sfx_gldhit); - player->ammo[am_blaster] -= USE_BLSR_AMMO_1; - P_BulletSlope(mo); - damage = HITDICE(4); - angle = mo->angle; - if (player->refire) - { - angle += P_SubRandom() << 18; - } - PuffType = MT_BLASTERPUFF1; - P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); - S_StartSound(player->mo, sfx_blssht); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireBlasterPL2 -// -//---------------------------------------------------------------------------- - -void A_FireBlasterPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - player->ammo[am_blaster] -= - deathmatch ? USE_BLSR_AMMO_1 : USE_BLSR_AMMO_2; - mo = P_SpawnPlayerMissile(player->mo, MT_BLASTERFX1); - if (mo) - { - mo->thinker.function = P_BlasterMobjThinker; - } - S_StartSound(player->mo, sfx_blssht); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireGoldWandPL1 -// -//---------------------------------------------------------------------------- - -void A_FireGoldWandPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - int damage; - - mo = player->mo; - player->ammo[am_goldwand] -= USE_GWND_AMMO_1; - P_BulletSlope(mo); - damage = 7 + (P_Random() & 7); - angle = mo->angle; - if (player->refire) - { - angle += P_SubRandom() << 18; - } - PuffType = MT_GOLDWANDPUFF1; - P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); - S_StartSound(player->mo, sfx_gldhit); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireGoldWandPL2 -// -//---------------------------------------------------------------------------- - -void A_FireGoldWandPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - mobj_t *mo; - angle_t angle; - int damage; - fixed_t momz; - - mo = player->mo; - player->ammo[am_goldwand] -= - deathmatch ? USE_GWND_AMMO_1 : USE_GWND_AMMO_2; - PuffType = MT_GOLDWANDPUFF2; - P_BulletSlope(mo); - momz = FixedMul(mobjinfo[MT_GOLDWANDFX2].speed, bulletslope); - P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle - (ANG45 / 8), momz); - P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle + (ANG45 / 8), momz); - angle = mo->angle - (ANG45 / 8); - for (i = 0; i < 5; i++) - { - damage = 1 + (P_Random() & 7); - P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage); - angle += ((ANG45 / 8) * 2) / 4; - } - S_StartSound(player->mo, sfx_gldhit); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireMacePL1B -// -//---------------------------------------------------------------------------- - -void A_FireMacePL1B(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *pmo; - mobj_t *ball; - angle_t angle; - - if (player->ammo[am_mace] < USE_MACE_AMMO_1) - { - return; - } - player->ammo[am_mace] -= USE_MACE_AMMO_1; - pmo = player->mo; - - // Vanilla bug here: - // Original code here looks like: - // (pmo->flags2 & MF2_FEETARECLIPPED != 0) - // C's operator precedence interprets this as: - // (pmo->flags2 & (MF2_FEETARECLIPPED != 0)) - // Which simplifies to: - // (pmo->flags2 & 1) - ball = P_SpawnMobj(pmo->x, pmo->y, pmo->z + 28 * FRACUNIT - - FOOTCLIPSIZE * (pmo->flags2 & 1), MT_MACEFX2); - - ball->momz = 2 * FRACUNIT + ((player->lookdir) << (FRACBITS - 5)); - angle = pmo->angle; - ball->target = pmo; - ball->angle = angle; - ball->z += (player->lookdir) << (FRACBITS - 4); - angle >>= ANGLETOFINESHIFT; - ball->momx = (pmo->momx >> 1) - + FixedMul(ball->info->speed, finecosine[angle]); - ball->momy = (pmo->momy >> 1) - + FixedMul(ball->info->speed, finesine[angle]); - S_StartSound(ball, sfx_lobsht); - P_CheckMissileSpawn(ball); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireMacePL1 -// -//---------------------------------------------------------------------------- - -void A_FireMacePL1(mobj_t *mobj, player_t * player, pspdef_t * psp) -{ - mobj_t *ball; - - if (P_Random() < 28) - { - A_FireMacePL1B(mobj, player, psp); - return; - } - if (player->ammo[am_mace] < USE_MACE_AMMO_1) - { - return; - } - player->ammo[am_mace] -= USE_MACE_AMMO_1; - psp->sx = ((P_Random() & 3) - 2) * FRACUNIT; - psp->sy = WEAPONTOP + (P_Random() & 3) * FRACUNIT; - ball = P_SPMAngle(player->mo, MT_MACEFX1, player->mo->angle - + (((P_Random() & 7) - 4) << 24)); - if (ball) - { - ball->special1.i = 16; // tics till dropoff - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MacePL1Check -// -//---------------------------------------------------------------------------- - -void A_MacePL1Check(mobj_t * ball, player_t *player, pspdef_t *psp) -{ - angle_t angle; - - if (ball->special1.i == 0) - { - return; - } - ball->special1.i -= 4; - if (ball->special1.i > 0) - { - return; - } - ball->special1.i = 0; - ball->flags2 |= MF2_LOGRAV; - angle = ball->angle >> ANGLETOFINESHIFT; - ball->momx = FixedMul(7 * FRACUNIT, finecosine[angle]); - ball->momy = FixedMul(7 * FRACUNIT, finesine[angle]); - ball->momz -= ball->momz >> 1; -} - -//---------------------------------------------------------------------------- -// -// PROC A_MaceBallImpact -// -//---------------------------------------------------------------------------- - -void A_MaceBallImpact(mobj_t * ball, player_t *player, pspdef_t *psp) -{ - if ((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID)) - { // Landed in some sort of liquid - P_RemoveMobj(ball); - return; - } - if ((ball->health != MAGIC_JUNK) && (ball->z <= ball->floorz) - && ball->momz) - { // Bounce - ball->health = MAGIC_JUNK; - ball->momz = (ball->momz * 192) >> 8; - ball->flags2 &= ~MF2_FLOORBOUNCE; - P_SetMobjState(ball, ball->info->spawnstate); - S_StartSound(ball, sfx_bounce); - } - else - { // Explode - ball->flags |= MF_NOGRAVITY; - ball->flags2 &= ~MF2_LOGRAV; - S_StartSound(ball, sfx_lobhit); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MaceBallImpact2 -// -//---------------------------------------------------------------------------- - -void A_MaceBallImpact2(mobj_t * ball, player_t *player, pspdef_t *psp) -{ - mobj_t *tiny; - angle_t angle; - - if ((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID)) - { // Landed in some sort of liquid - P_RemoveMobj(ball); - return; - } - if ((ball->z != ball->floorz) || (ball->momz < 2 * FRACUNIT)) - { // Explode - ball->momx = ball->momy = ball->momz = 0; - ball->flags |= MF_NOGRAVITY; - ball->flags2 &= ~(MF2_LOGRAV | MF2_FLOORBOUNCE); - } - else - { // Bounce - ball->momz = (ball->momz * 192) >> 8; - P_SetMobjState(ball, ball->info->spawnstate); - - tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3); - angle = ball->angle + ANG90; - tiny->target = ball->target; - tiny->angle = angle; - angle >>= ANGLETOFINESHIFT; - tiny->momx = (ball->momx >> 1) + FixedMul(ball->momz - FRACUNIT, - finecosine[angle]); - tiny->momy = (ball->momy >> 1) + FixedMul(ball->momz - FRACUNIT, - finesine[angle]); - tiny->momz = ball->momz; - P_CheckMissileSpawn(tiny); - - tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3); - angle = ball->angle - ANG90; - tiny->target = ball->target; - tiny->angle = angle; - angle >>= ANGLETOFINESHIFT; - tiny->momx = (ball->momx >> 1) + FixedMul(ball->momz - FRACUNIT, - finecosine[angle]); - tiny->momy = (ball->momy >> 1) + FixedMul(ball->momz - FRACUNIT, - finesine[angle]); - tiny->momz = ball->momz; - P_CheckMissileSpawn(tiny); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireMacePL2 -// -//---------------------------------------------------------------------------- - -void A_FireMacePL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - player->ammo[am_mace] -= deathmatch ? USE_MACE_AMMO_1 : USE_MACE_AMMO_2; - mo = P_SpawnPlayerMissile(player->mo, MT_MACEFX4); - if (mo) - { - mo->momx += player->mo->momx; - mo->momy += player->mo->momy; - mo->momz = 2 * FRACUNIT + ((player->lookdir) << (FRACBITS - 5)); - if (linetarget) - { - mo->special1.m = linetarget; - } - } - S_StartSound(player->mo, sfx_lobsht); -} - -//---------------------------------------------------------------------------- -// -// PROC A_DeathBallImpact -// -//---------------------------------------------------------------------------- - -void A_DeathBallImpact(mobj_t * ball, player_t *player, pspdef_t *psp) -{ - int i; - mobj_t *target; - angle_t angle; - boolean newAngle; - - if ((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID)) - { // Landed in some sort of liquid - P_RemoveMobj(ball); - return; - } - if ((ball->z <= ball->floorz) && ball->momz) - { // Bounce - newAngle = false; - target = (mobj_t *) ball->special1.m; - if (target) - { - if (!(target->flags & MF_SHOOTABLE)) - { // Target died - ball->special1.m = NULL; - } - else - { // Seek - angle = R_PointToAngle2(ball->x, ball->y, - target->x, target->y); - newAngle = true; - } - } - else - { // Find new target - angle = 0; - for (i = 0; i < 16; i++) - { - P_AimLineAttack(ball, angle, 10 * 64 * FRACUNIT); - if (linetarget && ball->target != linetarget) - { - ball->special1.m = linetarget; - angle = R_PointToAngle2(ball->x, ball->y, - linetarget->x, linetarget->y); - newAngle = true; - break; - } - angle += ANG45 / 2; - } - } - if (newAngle) - { - ball->angle = angle; - angle >>= ANGLETOFINESHIFT; - ball->momx = FixedMul(ball->info->speed, finecosine[angle]); - ball->momy = FixedMul(ball->info->speed, finesine[angle]); - } - P_SetMobjState(ball, ball->info->spawnstate); - S_StartSound(ball, sfx_pstop); - } - else - { // Explode - ball->flags |= MF_NOGRAVITY; - ball->flags2 &= ~MF2_LOGRAV; - S_StartSound(ball, sfx_phohit); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_SpawnRippers -// -//---------------------------------------------------------------------------- - -void A_SpawnRippers(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - unsigned int i; - angle_t angle; - mobj_t *ripper; - - for (i = 0; i < 8; i++) - { - ripper = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RIPPER); - angle = i * ANG45; - ripper->target = actor->target; - ripper->angle = angle; - angle >>= ANGLETOFINESHIFT; - ripper->momx = FixedMul(ripper->info->speed, finecosine[angle]); - ripper->momy = FixedMul(ripper->info->speed, finesine[angle]); - P_CheckMissileSpawn(ripper); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireCrossbowPL1 -// -//---------------------------------------------------------------------------- - -void A_FireCrossbowPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *pmo; - - pmo = player->mo; - player->ammo[am_crossbow] -= USE_CBOW_AMMO_1; - P_SpawnPlayerMissile(pmo, MT_CRBOWFX1); - P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle - (ANG45 / 10)); - P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle + (ANG45 / 10)); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireCrossbowPL2 -// -//---------------------------------------------------------------------------- - -void A_FireCrossbowPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *pmo; - - pmo = player->mo; - player->ammo[am_crossbow] -= - deathmatch ? USE_CBOW_AMMO_1 : USE_CBOW_AMMO_2; - P_SpawnPlayerMissile(pmo, MT_CRBOWFX2); - P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle - (ANG45 / 10)); - P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle + (ANG45 / 10)); - P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle - (ANG45 / 5)); - P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle + (ANG45 / 5)); -} - -//---------------------------------------------------------------------------- -// -// PROC A_BoltSpark -// -//---------------------------------------------------------------------------- - -void A_BoltSpark(mobj_t * bolt, player_t *player, pspdef_t *psp) -{ - mobj_t *spark; - - if (P_Random() > 50) - { - spark = P_SpawnMobj(bolt->x, bolt->y, bolt->z, MT_CRBOWFX4); - spark->x += P_SubRandom() << 10; - spark->y += P_SubRandom() << 10; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireSkullRodPL1 -// -//---------------------------------------------------------------------------- - -void A_FireSkullRodPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - if (player->ammo[am_skullrod] < USE_SKRD_AMMO_1) - { - return; - } - player->ammo[am_skullrod] -= USE_SKRD_AMMO_1; - mo = P_SpawnPlayerMissile(player->mo, MT_HORNRODFX1); - // Randomize the first frame - if (mo && P_Random() > 128) - { - P_SetMobjState(mo, S_HRODFX1_2); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireSkullRodPL2 -// -// The special2 field holds the player number that shot the rain missile. -// The special1 field is used for the seeking routines, then as a counter -// for the sound looping. -// -//---------------------------------------------------------------------------- - -void A_FireSkullRodPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->ammo[am_skullrod] -= - deathmatch ? USE_SKRD_AMMO_1 : USE_SKRD_AMMO_2; - P_SpawnPlayerMissile(player->mo, MT_HORNRODFX2); - // Use MissileMobj instead of the return value from - // P_SpawnPlayerMissile because we need to give info to the mobj - // even if it exploded immediately. - if (netgame) - { // Multi-player game - MissileMobj->special2.i = P_GetPlayerNum(player); - } - else - { // Always use red missiles in single player games - MissileMobj->special2.i = 2; - } - if (linetarget) - { - MissileMobj->special1.m = linetarget; - } - S_StartSound(MissileMobj, sfx_hrnpow); -} - -//---------------------------------------------------------------------------- -// -// PROC A_SkullRodPL2Seek -// -//---------------------------------------------------------------------------- - -void A_SkullRodPL2Seek(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SeekerMissile(actor, ANG1_X * 10, ANG1_X * 30); -} - -//---------------------------------------------------------------------------- -// -// PROC A_AddPlayerRain -// -//---------------------------------------------------------------------------- - -void A_AddPlayerRain(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - int playerNum; - player_t *player; - - playerNum = netgame ? actor->special2.i : 0; - if (!playeringame[playerNum]) - { // Player left the game - return; - } - player = &players[playerNum]; - if (player->health <= 0) - { // Player is dead - return; - } - if (player->rain1 && player->rain2) - { // Terminate an active rain - if (player->rain1->health < player->rain2->health) - { - if (player->rain1->health > 16) - { - player->rain1->health = 16; - } - player->rain1 = NULL; - } - else - { - if (player->rain2->health > 16) - { - player->rain2->health = 16; - } - player->rain2 = NULL; - } - } - // Add rain mobj to list - if (player->rain1) - { - player->rain2 = actor; - } - else - { - player->rain1 = actor; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_SkullRodStorm -// -//---------------------------------------------------------------------------- - -void A_SkullRodStorm(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - fixed_t x; - fixed_t y; - mobj_t *mo; - int playerNum; - player_t *player; - - if (actor->health-- == 0) - { - P_SetMobjState(actor, S_NULL); - playerNum = netgame ? actor->special2.i : 0; - if (!playeringame[playerNum]) - { // Player left the game - return; - } - player = &players[playerNum]; - if (player->health <= 0) - { // Player is dead - return; - } - if (player->rain1 == actor) - { - player->rain1 = NULL; - } - else if (player->rain2 == actor) - { - player->rain2 = NULL; - } - return; - } - if (P_Random() < 25) - { // Fudge rain frequency - return; - } - x = actor->x + ((P_Random() & 127) - 64) * FRACUNIT; - y = actor->y + ((P_Random() & 127) - 64) * FRACUNIT; - mo = P_SpawnMobj(x, y, ONCEILINGZ, MT_RAINPLR1 + actor->special2.i); - mo->target = actor->target; - mo->momx = 1; // Force collision detection - mo->momz = -mo->info->speed; - mo->special2.i = actor->special2.i; // Transfer player number - P_CheckMissileSpawn(mo); - if (!(actor->special1.i & 31)) - { - S_StartSound(actor, sfx_ramrain); - } - actor->special1.i++; -} - -//---------------------------------------------------------------------------- -// -// PROC A_RainImpact -// -//---------------------------------------------------------------------------- - -void A_RainImpact(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->z > actor->floorz) - { - P_SetMobjState(actor, S_RAINAIRXPLR1_1 + actor->special2.i); - } - else if (P_Random() < 40) - { - P_HitFloor(actor); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_HideInCeiling -// -//---------------------------------------------------------------------------- - -void A_HideInCeiling(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->z = actor->ceilingz + 4 * FRACUNIT; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FirePhoenixPL1 -// -//---------------------------------------------------------------------------- - -void A_FirePhoenixPL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - - player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_1; - P_SpawnPlayerMissile(player->mo, MT_PHOENIXFX1); - //P_SpawnPlayerMissile(player->mo, MT_MNTRFX2); - angle = player->mo->angle + ANG180; - angle >>= ANGLETOFINESHIFT; - player->mo->momx += FixedMul(4 * FRACUNIT, finecosine[angle]); - player->mo->momy += FixedMul(4 * FRACUNIT, finesine[angle]); -} - -//---------------------------------------------------------------------------- -// -// PROC A_PhoenixPuff -// -//---------------------------------------------------------------------------- - -void A_PhoenixPuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *puff; - angle_t angle; - - P_SeekerMissile(actor, ANG1_X * 5, ANG1_X * 10); - puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF); - angle = actor->angle + ANG90; - angle >>= ANGLETOFINESHIFT; - puff->momx = FixedMul((fixed_t)(FRACUNIT * 1.3), finecosine[angle]); - puff->momy = FixedMul((fixed_t)(FRACUNIT * 1.3), finesine[angle]); - puff->momz = 0; - puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF); - angle = actor->angle - ANG90; - angle >>= ANGLETOFINESHIFT; - puff->momx = FixedMul((fixed_t)(FRACUNIT * 1.3), finecosine[angle]); - puff->momy = FixedMul((fixed_t)(FRACUNIT * 1.3), finesine[angle]); - puff->momz = 0; -} - -// -// This function was present in the Heretic 1.0 executable for the -// removed "secondary phoenix flash" object (MT_PHOENIXFX_REMOVED). -// The purpose of this object is unknown, as is this function. -// - -void A_RemovedPhoenixFunc(mobj_t *actor, player_t * player, pspdef_t * psp) -{ - I_Error("Action function invoked for removed Phoenix action!"); -} - -//---------------------------------------------------------------------------- -// -// PROC A_InitPhoenixPL2 -// -//---------------------------------------------------------------------------- - -void A_InitPhoenixPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->flamecount = FLAME_THROWER_TICS; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FirePhoenixPL2 -// -// Flame thrower effect. -// -//---------------------------------------------------------------------------- - -void A_FirePhoenixPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - mobj_t *pmo; - angle_t angle; - fixed_t x, y, z; - fixed_t slope; - - if (--player->flamecount == 0) - { // Out of flame - P_SetPsprite(player, ps_weapon, S_PHOENIXATK2_4); - player->refire = 0; - return; - } - pmo = player->mo; - angle = pmo->angle; - x = pmo->x + (P_SubRandom() << 9); - y = pmo->y + (P_SubRandom() << 9); - z = pmo->z + 26 * FRACUNIT + ((player->lookdir) << FRACBITS) / 173; - if (pmo->flags2 & MF2_FEETARECLIPPED) - { - z -= FOOTCLIPSIZE; - } - slope = ((player->lookdir) << FRACBITS) / 173 + (FRACUNIT / 10); - mo = P_SpawnMobj(x, y, z, MT_PHOENIXFX2); - mo->target = pmo; - mo->angle = angle; - mo->momx = pmo->momx + FixedMul(mo->info->speed, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = pmo->momy + FixedMul(mo->info->speed, - finesine[angle >> ANGLETOFINESHIFT]); - mo->momz = FixedMul(mo->info->speed, slope); - if (!player->refire || !(leveltime % 38)) - { - S_StartSound(player->mo, sfx_phopow); - } - P_CheckMissileSpawn(mo); -} - -//---------------------------------------------------------------------------- -// -// PROC A_ShutdownPhoenixPL2 -// -//---------------------------------------------------------------------------- - -void A_ShutdownPhoenixPL2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2; -} - -//---------------------------------------------------------------------------- -// -// PROC A_FlameEnd -// -//---------------------------------------------------------------------------- - -void A_FlameEnd(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->momz += (fixed_t)(1.5 * FRACUNIT); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FloatPuff -// -//---------------------------------------------------------------------------- - -void A_FloatPuff(mobj_t * puff, player_t *player, pspdef_t *psp) -{ - puff->momz += (fixed_t)(1.8 * FRACUNIT); -} - -//--------------------------------------------------------------------------- -// -// PROC A_GauntletAttack -// -//--------------------------------------------------------------------------- - -void A_GauntletAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - int randVal; - fixed_t dist; - - psp->sx = ((P_Random() & 3) - 2) * FRACUNIT; - psp->sy = WEAPONTOP + (P_Random() & 3) * FRACUNIT; - angle = player->mo->angle; - if (player->powers[pw_weaponlevel2]) - { - damage = HITDICE(2); - dist = 4 * MELEERANGE; - angle += P_SubRandom() << 17; - PuffType = MT_GAUNTLETPUFF2; - } - else - { - damage = HITDICE(2); - dist = MELEERANGE + 1; - angle += P_SubRandom() << 18; - PuffType = MT_GAUNTLETPUFF1; - } - slope = P_AimLineAttack(player->mo, angle, dist); - P_LineAttack(player->mo, angle, dist, slope, damage); - if (!linetarget) - { - if (P_Random() > 64) - { - player->extralight = !player->extralight; - } - S_StartSound(player->mo, sfx_gntful); - return; - } - randVal = P_Random(); - if (randVal < 64) - { - player->extralight = 0; - } - else if (randVal < 160) - { - player->extralight = 1; - } - else - { - player->extralight = 2; - } - if (player->powers[pw_weaponlevel2]) - { - P_GiveBody(player, damage >> 1); - S_StartSound(player->mo, sfx_gntpow); - } - else - { - S_StartSound(player->mo, sfx_gnthit); - } - // turn to face target - angle = R_PointToAngle2(player->mo->x, player->mo->y, - linetarget->x, linetarget->y); - if (angle - player->mo->angle > ANG180) - { - if ((signed int) (angle - player->mo->angle) < -ANG90 / 20) - player->mo->angle = angle + ANG90 / 21; - else - player->mo->angle -= ANG90 / 20; - } - else - { - if (angle - player->mo->angle > ANG90 / 20) - player->mo->angle = angle - ANG90 / 21; - else - player->mo->angle += ANG90 / 20; - } - player->mo->flags |= MF_JUSTATTACKED; -} - -void A_Light0(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->extralight = 0; -} - -void A_Light1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->extralight = 1; -} - -void A_Light2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->extralight = 2; -} - -//------------------------------------------------------------------------ -// -// PROC P_SetupPsprites -// -// Called at start of level for each player -// -//------------------------------------------------------------------------ - -void P_SetupPsprites(player_t * player) -{ - int i; - - // Remove all psprites - for (i = 0; i < NUMPSPRITES; i++) - { - player->psprites[i].state = NULL; - } - // Spawn the ready weapon - player->pendingweapon = player->readyweapon; - P_BringUpWeapon(player); -} - -//------------------------------------------------------------------------ -// -// PROC P_MovePsprites -// -// Called every tic by player thinking routine -// -//------------------------------------------------------------------------ - -void P_MovePsprites(player_t * player) -{ - int i; - pspdef_t *psp; - - psp = &player->psprites[0]; - for (i = 0; i < NUMPSPRITES; i++, psp++) - { - if (psp->state != 0) // a null state means not active - { - // drop tic count and possibly change state - if (psp->tics != -1) // a -1 tic count never changes - { - psp->tics--; - if (!psp->tics) - { - P_SetPsprite(player, i, psp->state->nextstate); - } - } - } - } - player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; - player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; -} diff --git a/games/NXDoom/src/heretic/p_saveg.c b/games/NXDoom/src/heretic/p_saveg.c deleted file mode 100644 index c4a2f131df6..00000000000 --- a/games/NXDoom/src/heretic/p_saveg.c +++ /dev/null @@ -1,1925 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_tick.c - -#include - -#include "doomdef.h" -#include "i_swap.h" -#include "i_system.h" -#include "m_misc.h" -#include "p_local.h" -#include "v_video.h" - -static FILE *SaveGameFP; - -int vanilla_savegame_limit = 1; - - -//========================================================================== -// -// SV_Filename -// -// Generate the filename to use for a particular savegame slot. -// Returns a malloc()'d buffer that must be freed by the caller. -// -//========================================================================== - -char *SV_Filename(int slot) -{ - char *filename; - size_t filename_len; - - filename_len = strlen(savegamedir) + strlen(SAVEGAMENAME) + 8; - filename = malloc(filename_len); - M_snprintf(filename, filename_len, - "%s" SAVEGAMENAME "%d.hsg", savegamedir, slot); - - return filename; -} - -//========================================================================== -// -// SV_Open -// -//========================================================================== - -void SV_Open(char *fileName) -{ - SaveGameFP = M_fopen(fileName, "wb"); -} - -void SV_OpenRead(char *filename) -{ - SaveGameFP = M_fopen(filename, "rb"); - - if (SaveGameFP == NULL) - { - I_Error("Could not load savegame %s", filename); - } -} - -//========================================================================== -// -// SV_WriteSaveGameEOF -// -//========================================================================== - -void SV_WriteSaveGameEOF(void) -{ - SV_WriteByte(SAVE_GAME_TERMINATOR); - - // Enforce the same savegame size limit as in Vanilla Heretic - - if (vanilla_savegame_limit && ftell(SaveGameFP) > SAVEGAMESIZE) - { - I_Error("Savegame buffer overrun"); - } -} - -//========================================================================== -// -// SV_Close -// -//========================================================================== - -void SV_Close(void) -{ - if (SaveGameFP) - { - fclose(SaveGameFP); - SaveGameFP = NULL; - } -} - -//========================================================================== -// -// SV_Write -// -//========================================================================== - -void SV_Write(void *buffer, int size) -{ - fwrite(buffer, size, 1, SaveGameFP); -} - -void SV_WriteByte(byte val) -{ - SV_Write(&val, sizeof(byte)); -} - -void SV_WriteWord(unsigned short val) -{ - val = SHORT(val); - SV_Write(&val, sizeof(unsigned short)); -} - -void SV_WriteLong(unsigned int val) -{ - val = LONG(val); - SV_Write(&val, sizeof(int)); -} - -void SV_WritePtr(const void *ptr) -{ - long val = (long)(intptr_t) ptr; - - SV_WriteLong(val & 0xffffffff); -} - -//========================================================================== -// -// SV_Read -// -//========================================================================== - -void SV_Read(void *buffer, int size) -{ - int retval = fread(buffer, 1, size, SaveGameFP); - if (retval != size) - { - I_Error("Incomplete read in SV_Read: Expected %d, got %d bytes", - size, retval); - } -} - -byte SV_ReadByte(void) -{ - byte result; - SV_Read(&result, sizeof(byte)); - return result; -} - -uint16_t SV_ReadWord(void) -{ - uint16_t result; - SV_Read(&result, sizeof(unsigned short)); - return SHORT(result); -} - -uint32_t SV_ReadLong(void) -{ - uint32_t result; - SV_Read(&result, sizeof(int)); - return LONG(result); -} - -// -// ticcmd_t -// - -static void saveg_read_ticcmd_t(ticcmd_t *str) -{ - // char forwardmove; - str->forwardmove = SV_ReadByte(); - - // char sidemove; - str->sidemove = SV_ReadByte(); - - // short angleturn; - str->angleturn = SV_ReadWord(); - - // short consistancy; - str->consistancy = SV_ReadWord(); - - // byte chatchar; - str->chatchar = SV_ReadByte(); - - // byte buttons; - str->buttons = SV_ReadByte(); - - // byte lookfly; - str->lookfly = SV_ReadByte(); - - // byte arti; - str->arti = SV_ReadByte(); -} - -static void saveg_write_ticcmd_t(ticcmd_t *str) -{ - // char forwardmove; - SV_WriteByte(str->forwardmove); - - // char sidemove; - SV_WriteByte(str->sidemove); - - // short angleturn; - SV_WriteWord(str->angleturn); - - // short consistancy; - SV_WriteWord(str->consistancy); - - // byte chatchar; - SV_WriteByte(str->chatchar); - - // byte buttons; - SV_WriteByte(str->buttons); - - // byte lookfly; - SV_WriteByte(str->lookfly); - - // byte arti; - SV_WriteByte(str->arti); -} - -// -// inventory_t -// - -static void saveg_read_inventory_t(inventory_t *str) -{ - // int type; - str->type = SV_ReadLong(); - - // int count; - str->count = SV_ReadLong(); -} - -static void saveg_write_inventory_t(inventory_t *str) -{ - // int type; - SV_WriteLong(str->type); - - // int count; - SV_WriteLong(str->count); -} - - -// -// state_t * -// - -static void saveg_read_state_ptr(state_t **state) -{ - int statenum; - - statenum = SV_ReadLong(); - - // We have read a state number, but it is indexed according to the state - // table in Vanilla Heretic v1.3. To support v1.0 HHE patches we have - // three extra states, so map the state number to our internal state - // number. - - if (statenum >= S_PHOENIXFXIX_1) - { - statenum = (statenum - S_PHOENIXFXIX_1) + S_PHOENIXPUFF1; - } - - if (statenum == 0) - { - *state = NULL; - } - else - { - *state = &states[statenum]; - } -} - -static void saveg_write_state_ptr(state_t *state) -{ - int statenum; - - // NULL states are just written as zero. - - if (state == NULL) - { - SV_WriteLong(0); - return; - } - - statenum = state - states; - - // Our internal state table has three extra states than Vanilla, so map - // to the state numbers used by Vanilla Heretic v1.3 for savegame - // compatibility. - - if (statenum >= S_PHOENIXPUFF1) - { - statenum = (statenum - S_PHOENIXPUFF1) + S_PHOENIXFXIX_1; - } - else if (statenum >= S_PHOENIXFXIX_1) - { - // Now we're really in trouble. This state doesn't exist in Vanilla - // Heretic v1.3 (but does in v1.0). Map to a frame that might be - // vaguely sensible. - - statenum = S_PHOENIXFXI1_8; - } - - SV_WriteLong(statenum); -} - - -// -// pspdef_t -// - -static void saveg_read_pspdef_t(pspdef_t *str) -{ - // state_t *state; - saveg_read_state_ptr(&str->state); - - // int tics; - str->tics = SV_ReadLong(); - - // fixed_t sx, sy; - str->sx = SV_ReadLong(); - str->sy = SV_ReadLong(); -} - -static void saveg_write_pspdef_t(pspdef_t *str) -{ - // state_t *state; - saveg_write_state_ptr(str->state); - - // int tics; - SV_WriteLong(str->tics); - - // fixed_t sx, sy; - SV_WriteLong(str->sx); - SV_WriteLong(str->sy); -} - - -// -// player_t -// - -static void saveg_read_player_t(player_t *str) -{ - int i; - - // mobj_t *mo; - SV_ReadLong(); - str->mo = NULL; - - // playerstate_t playerstate; - str->playerstate = SV_ReadLong(); - - // ticcmd_t cmd; - saveg_read_ticcmd_t(&str->cmd); - - // fixed_t viewz; - str->viewz = SV_ReadLong(); - - // fixed_t viewheight; - str->viewheight = SV_ReadLong(); - - // fixed_t deltaviewheight; - str->deltaviewheight = SV_ReadLong(); - - // fixed_t bob; - str->bob = SV_ReadLong(); - - // int flyheight; - str->flyheight = SV_ReadLong(); - - // int lookdir; - str->lookdir = SV_ReadLong(); - - // boolean centering; - str->centering = SV_ReadLong(); - - // int health; - str->health = SV_ReadLong(); - - // int armorpoints, armortype; - str->armorpoints = SV_ReadLong(); - str->armortype = SV_ReadLong(); - - // inventory_t inventory[NUMINVENTORYSLOTS]; - for (i=0; iinventory[i]); - } - - // artitype_t readyArtifact; - str->readyArtifact = SV_ReadLong(); - - // int artifactCount; - str->artifactCount = SV_ReadLong(); - - // int inventorySlotNum; - str->inventorySlotNum = SV_ReadLong(); - - // int powers[NUMPOWERS]; - for (i=0; ipowers[i] = SV_ReadLong(); - } - - // boolean keys[NUM_KEY_TYPES]; - for (i = 0; i < NUM_KEY_TYPES; ++i) - { - str->keys[i] = SV_ReadLong(); - } - - // boolean backpack; - str->backpack = SV_ReadLong(); - - // signed int frags[MAXPLAYERS]; - for (i=0; ifrags[i] = SV_ReadLong(); - } - - // weapontype_t readyweapon; - str->readyweapon = SV_ReadLong(); - - // weapontype_t pendingweapon; - str->pendingweapon = SV_ReadLong(); - - // boolean weaponowned[NUMWEAPONS]; - for (i=0; iweaponowned[i] = SV_ReadLong(); - } - - // int ammo[NUMAMMO]; - for (i=0; iammo[i] = SV_ReadLong(); - } - - // int maxammo[NUMAMMO]; - for (i=0; imaxammo[i] = SV_ReadLong(); - } - - // int attackdown, usedown; - str->attackdown = SV_ReadLong(); - str->usedown = SV_ReadLong(); - - // int cheats; - str->cheats = SV_ReadLong(); - - // int refire; - str->refire = SV_ReadLong(); - - // int killcount, itemcount, secretcount; - str->killcount = SV_ReadLong(); - str->itemcount = SV_ReadLong(); - str->secretcount = SV_ReadLong(); - - // char *message; - SV_ReadLong(); - str->message = NULL; - - // int messageTics; - str->messageTics = SV_ReadLong(); - - // int damagecount, bonuscount; - str->damagecount = SV_ReadLong(); - str->bonuscount = SV_ReadLong(); - - // int flamecount; - str->flamecount = SV_ReadLong(); - - // mobj_t *attacker; - SV_ReadLong(); - str->attacker = NULL; - - // int extralight; - str->extralight = SV_ReadLong(); - - // int fixedcolormap; - str->fixedcolormap = SV_ReadLong(); - - // int colormap; - str->colormap = SV_ReadLong(); - - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; ipsprites[i]); - } - - // boolean didsecret; - str->didsecret = SV_ReadLong(); - - // int chickenTics; - str->chickenTics = SV_ReadLong(); - - // int chickenPeck; - str->chickenPeck = SV_ReadLong(); - - // mobj_t *rain1; - SV_ReadLong(); - str->rain1 = NULL; - - // mobj_t *rain2; - SV_ReadLong(); - str->rain2 = NULL; -} - -static void saveg_write_player_t(player_t *str) -{ - int i; - - // mobj_t *mo; - // pointer will be trashed, but it gets restored on load as - // the player number reference is stored in the mo. - SV_WritePtr(str->mo); - - // playerstate_t playerstate; - SV_WriteLong(str->playerstate); - - // ticcmd_t cmd; - saveg_write_ticcmd_t(&str->cmd); - - // fixed_t viewz; - SV_WriteLong(str->viewz); - - // fixed_t viewheight; - SV_WriteLong(str->viewheight); - - // fixed_t deltaviewheight; - SV_WriteLong(str->deltaviewheight); - - // fixed_t bob; - SV_WriteLong(str->bob); - - // int flyheight; - SV_WriteLong(str->flyheight); - - // int lookdir; - SV_WriteLong(str->lookdir); - - // boolean centering; - SV_WriteLong(str->centering); - - // int health; - SV_WriteLong(str->health); - - // int armorpoints, armortype; - SV_WriteLong(str->armorpoints); - SV_WriteLong(str->armortype); - - // inventory_t inventory[NUMINVENTORYSLOTS]; - for (i=0; iinventory[i]); - } - - // artitype_t readyArtifact; - SV_WriteLong(str->readyArtifact); - - // int artifactCount; - SV_WriteLong(str->artifactCount); - - // int inventorySlotNum; - SV_WriteLong(str->inventorySlotNum); - - // int powers[NUMPOWERS]; - for (i=0; ipowers[i]); - } - - // boolean keys[NUMKEYS]; - for (i = 0; i < NUM_KEY_TYPES; ++i) - { - SV_WriteLong(str->keys[i]); - } - - // boolean backpack; - SV_WriteLong(str->backpack); - - // signed int frags[MAXPLAYERS]; - for (i=0; ifrags[i]); - } - - // weapontype_t readyweapon; - SV_WriteLong(str->readyweapon); - - // weapontype_t pendingweapon; - SV_WriteLong(str->pendingweapon); - - // boolean weaponowned[NUMWEAPONS]; - for (i=0; iweaponowned[i]); - } - - // int ammo[NUMAMMO]; - for (i=0; iammo[i]); - } - - // int maxammo[NUMAMMO]; - for (i=0; imaxammo[i]); - } - - // int attackdown, usedown; - SV_WriteLong(str->attackdown); - SV_WriteLong(str->usedown); - - // int cheats; - SV_WriteLong(str->cheats); - - // int refire; - SV_WriteLong(str->refire); - - // int killcount, itemcount, secretcount; - SV_WriteLong(str->killcount); - SV_WriteLong(str->itemcount); - SV_WriteLong(str->secretcount); - - // char *message; - SV_WritePtr(str->message); - - // int messageTics; - SV_WriteLong(str->messageTics); - - // int damagecount, bonuscount; - SV_WriteLong(str->damagecount); - SV_WriteLong(str->bonuscount); - - // int flamecount; - SV_WriteLong(str->flamecount); - - // mobj_t *attacker; - SV_WritePtr(str->attacker); - - // int extralight; - SV_WriteLong(str->extralight); - - // int fixedcolormap; - SV_WriteLong(str->fixedcolormap); - - // int colormap; - SV_WriteLong(str->colormap); - - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; ipsprites[i]); - } - - // boolean didsecret; - SV_WriteLong(str->didsecret); - - // int chickenTics; - SV_WriteLong(str->chickenTics); - - // int chickenPeck; - SV_WriteLong(str->chickenPeck); - - // mobj_t *rain1; - SV_WritePtr(str->rain1); - - // mobj_t *rain2; - SV_WritePtr(str->rain2); -} - - -// -// mapthing_t -// - -static void saveg_read_mapthing_t(mapthing_t *str) -{ - // short x, y; - str->x = SV_ReadWord(); - str->y = SV_ReadWord(); - - // short angle; - str->angle = SV_ReadWord(); - - // short type; - str->type = SV_ReadWord(); - - // short options; - str->options = SV_ReadWord(); -} - -static void saveg_write_mapthing_t(mapthing_t *str) -{ - // short x, y; - SV_WriteWord(str->x); - SV_WriteWord(str->y); - - // short angle; - SV_WriteWord(str->angle); - - // short type; - SV_WriteWord(str->type); - - // short options; - SV_WriteWord(str->options); -} - - -// -// thinker_t -// - -static void saveg_read_thinker_t(thinker_t *str) -{ - // struct thinker_s *prev, *next; - SV_ReadLong(); - str->prev = NULL; - SV_ReadLong(); - str->next = NULL; - - // think_t function; - SV_ReadLong(); - str->function = NULL; -} - -static void saveg_write_thinker_t(thinker_t *str) -{ - // struct thinker_s *prev, *next; - SV_WritePtr(str->prev); - SV_WritePtr(str->next); - - // think_t function; - SV_WritePtr(str->function); -} - - -// -// specialval_t -// - -static void saveg_read_specialval_t(specialval_t *str) -{ - // This can also be a mobj_t ptr, but we just assume it's - // an int. This is probably a really bad assumption that's - // likely to end in tears. - - // int i; - str->i = SV_ReadLong(); -} - -static void saveg_write_specialval_t(specialval_t *str) -{ - // int i; - SV_WriteLong(str->i); -} - - -// -// mobj_t -// - -static void saveg_read_mobj_t(mobj_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // fixed_t x, y, z; - str->x = SV_ReadLong(); - str->y = SV_ReadLong(); - str->z = SV_ReadLong(); - - // struct mobj_s *snext, *sprev; - SV_ReadLong(); - str->snext = NULL; - SV_ReadLong(); - str->sprev = NULL; - - // angle_t angle; - str->angle = SV_ReadLong(); - - // spritenum_t sprite; - str->sprite = SV_ReadLong(); - - // int frame; - str->frame = SV_ReadLong(); - - // struct mobj_s *bnext, *bprev; - SV_ReadLong(); - str->bnext = NULL; - SV_ReadLong(); - str->bprev = NULL; - - // struct subsector_s *subsector; - SV_ReadLong(); - str->subsector = NULL; - - // fixed_t floorz, ceilingz; - str->floorz = SV_ReadLong(); - str->ceilingz = SV_ReadLong(); - - // fixed_t radius, height; - str->radius = SV_ReadLong(); - str->height = SV_ReadLong(); - - // fixed_t momx, momy, momz; - str->momx = SV_ReadLong(); - str->momy = SV_ReadLong(); - str->momz = SV_ReadLong(); - - // int validcount; - str->validcount = SV_ReadLong(); - - // mobjtype_t type; - str->type = SV_ReadLong(); - - // An extra thing type was added for v1.0 HHE compatibility. - // Map from the v1.3 thing type index to the internal one. - if (str->type >= MT_PHOENIXFX_REMOVED) - { - ++str->type; - } - - // mobjinfo_t *info; - SV_ReadLong(); - str->info = NULL; - - // int tics; - str->tics = SV_ReadLong(); - - // state_t *state; - saveg_read_state_ptr(&str->state); - - // int damage; - str->damage = SV_ReadLong(); - - // int flags; - str->flags = SV_ReadLong(); - - // int flags2; - str->flags2 = SV_ReadLong(); - - // specialval_t special1; - saveg_read_specialval_t(&str->special1); - - // specialval_t special2; - saveg_read_specialval_t(&str->special2); - - // Now we have a bunch of hacks to try to NULL out special values - // where special[12] contained a mobj_t pointer that isn't valid - // any more. This isn't in Vanilla but at least it stops the game - // from crashing. - - switch (str->type) - { - // Gas pods use special2.m to point to the pod generator - // that made it. - case MT_POD: - str->special2.m = NULL; - break; - - // Several thing types use special1.m to mean 'target': - case MT_MACEFX4: // A_DeathBallImpact - case MT_WHIRLWIND: // A_WhirlwindSeek - case MT_MUMMYFX1: // A_MummyFX1Seek - case MT_HORNRODFX2: // A_SkullRodPL2Seek - case MT_PHOENIXFX1: // A_PhoenixPuff - str->special1.m = NULL; - break; - - default: - break; - } - - // int health; - str->health = SV_ReadLong(); - - // int movedir; - str->movedir = SV_ReadLong(); - - // int movecount; - str->movecount = SV_ReadLong(); - - // struct mobj_s *target; - SV_ReadLong(); - str->target = NULL; - - // int reactiontime; - str->reactiontime = SV_ReadLong(); - - // int threshold; - str->threshold = SV_ReadLong(); - - // struct player_s *player; - i = SV_ReadLong(); - if (i != 0) - { - str->player = &players[i - 1]; - str->player->mo = str; - } - else - { - str->player = NULL; - } - - // int lastlook; - str->lastlook = SV_ReadLong(); - - // mapthing_t spawnpoint; - saveg_read_mapthing_t(&str->spawnpoint); -} - -static void saveg_write_mobj_t(mobj_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // fixed_t x, y, z; - SV_WriteLong(str->x); - SV_WriteLong(str->y); - SV_WriteLong(str->z); - - // struct mobj_s *snext, *sprev; - SV_WritePtr(str->snext); - SV_WritePtr(str->sprev); - - // angle_t angle; - SV_WriteLong(str->angle); - - // spritenum_t sprite; - SV_WriteLong(str->sprite); - - // int frame; - SV_WriteLong(str->frame); - - // struct mobj_s *bnext, *bprev; - SV_WritePtr(str->bnext); - SV_WritePtr(str->bprev); - - // struct subsector_s *subsector; - SV_WritePtr(str->subsector); - - // fixed_t floorz, ceilingz; - SV_WriteLong(str->floorz); - SV_WriteLong(str->ceilingz); - - // fixed_t radius, height; - SV_WriteLong(str->radius); - SV_WriteLong(str->height); - - // fixed_t momx, momy, momz; - SV_WriteLong(str->momx); - SV_WriteLong(str->momy); - SV_WriteLong(str->momz); - - // int validcount; - SV_WriteLong(str->validcount); - - // mobjtype_t type; - // Our mobjinfo table has an extra entry, for compatibility with v1.0 - // HHE patches. So translate the internal thing type index to the - // equivalent for Vanilla Heretic v1.3, for savegame compatibility. - - if (str->type > MT_PHOENIXFX_REMOVED) - { - SV_WriteLong(str->type - 1); - } - else if (str->type == MT_PHOENIXFX_REMOVED) - { - // This should never happen, but just in case, do something - // vaguely sensible ... ? - SV_WriteLong(MT_PHOENIXFX1); - } - else - { - SV_WriteLong(str->type); - } - - // mobjinfo_t *info; - SV_WritePtr(str->info); - - // int tics; - SV_WriteLong(str->tics); - - // state_t *state; - saveg_write_state_ptr(str->state); - - // int damage; - SV_WriteLong(str->damage); - - // int flags; - SV_WriteLong(str->flags); - - // int flags2; - SV_WriteLong(str->flags2); - - // specialval_t special1; - saveg_write_specialval_t(&str->special1); - - // specialval_t special2; - saveg_write_specialval_t(&str->special2); - - // int health; - SV_WriteLong(str->health); - - // int movedir; - SV_WriteLong(str->movedir); - - // int movecount; - SV_WriteLong(str->movecount); - - // struct mobj_s *target; - SV_WritePtr(str->target); - - // int reactiontime; - SV_WriteLong(str->reactiontime); - - // int threshold; - SV_WriteLong(str->threshold); - - // struct player_s *player; - if (str->player != NULL) - { - SV_WriteLong(str->player - players + 1); - } - else - { - SV_WriteLong(0); - } - - // int lastlook; - SV_WriteLong(str->lastlook); - - // mapthing_t spawnpoint; - saveg_write_mapthing_t(&str->spawnpoint); -} - - -// -// ceiling_t -// - -static void saveg_read_ceiling_t(ceiling_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // ceiling_e type; - str->type = SV_ReadLong(); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // fixed_t bottomheight, topheight; - str->bottomheight = SV_ReadLong(); - str->topheight = SV_ReadLong(); - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // boolean crush; - str->crush = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // int tag; - str->tag = SV_ReadLong(); - - // int olddirection; - str->olddirection = SV_ReadLong(); -} - -static void saveg_write_ceiling_t(ceiling_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // ceiling_e type; - SV_WriteLong(str->type); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // fixed_t bottomheight, topheight; - SV_WriteLong(str->bottomheight); - SV_WriteLong(str->topheight); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // boolean crush; - SV_WriteLong(str->crush); - - // int direction; - SV_WriteLong(str->direction); - - // int tag; - SV_WriteLong(str->tag); - - // int olddirection; - SV_WriteLong(str->olddirection); -} - - -// -// vldoor_t -// - -static void saveg_read_vldoor_t(vldoor_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // vldoor_e type; - str->type = SV_ReadLong(); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // fixed_t topheight; - str->topheight = SV_ReadLong(); - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // int topwait; - str->topwait = SV_ReadLong(); - - // int topcountdown; - str->topcountdown = SV_ReadLong(); -} - -static void saveg_write_vldoor_t(vldoor_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // vldoor_e type; - SV_WriteLong(str->type); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // fixed_t topheight; - SV_WriteLong(str->topheight); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // int direction; - SV_WriteLong(str->direction); - - // int topwait; - SV_WriteLong(str->topwait); - - // int topcountdown; - SV_WriteLong(str->topcountdown); -} - - -// -// floormove_t -// - -static void saveg_read_floormove_t(floormove_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // floor_e type; - str->type = SV_ReadLong(); - - // boolean crush; - str->crush = SV_ReadLong(); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // int direction; - str->direction = SV_ReadLong(); - - // int newspecial; - str->newspecial = SV_ReadLong(); - - // short texture; - str->texture = SV_ReadWord(); - - // fixed_t floordestheight; - str->floordestheight = SV_ReadLong(); - - // fixed_t speed; - str->speed = SV_ReadLong(); -} - -static void saveg_write_floormove_t(floormove_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // floor_e type; - SV_WriteLong(str->type); - - // boolean crush; - SV_WriteLong(str->crush); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // int direction; - SV_WriteLong(str->direction); - - // int newspecial; - SV_WriteLong(str->newspecial); - - // short texture; - SV_WriteWord(str->texture); - - // fixed_t floordestheight; - SV_WriteLong(str->floordestheight); - - // fixed_t speed; - SV_WriteLong(str->speed); -} - - -// -// plat_t -// - -static void saveg_read_plat_t(plat_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // fixed_t low; - str->low = SV_ReadLong(); - - // fixed_t high; - str->high = SV_ReadLong(); - - // int wait; - str->wait = SV_ReadLong(); - - // int count; - str->count = SV_ReadLong(); - - // plat_e status; - str->status = SV_ReadLong(); - - // plat_e oldstatus; - str->oldstatus = SV_ReadLong(); - - // boolean crush; - str->crush = SV_ReadLong(); - - // int tag; - str->tag = SV_ReadLong(); - - // plattype_e type; - str->type = SV_ReadLong(); -} - -static void saveg_write_plat_t(plat_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // fixed_t low; - SV_WriteLong(str->low); - - // fixed_t high; - SV_WriteLong(str->high); - - // int wait; - SV_WriteLong(str->wait); - - // int count; - SV_WriteLong(str->count); - - // plat_e status; - SV_WriteLong(str->status); - - // plat_e oldstatus; - SV_WriteLong(str->oldstatus); - - // boolean crush; - SV_WriteLong(str->crush); - - // int tag; - SV_WriteLong(str->tag); - - // plattype_e type; - SV_WriteLong(str->type); -} - - -// -// lightflash_t -// - -static void saveg_read_lightflash_t(lightflash_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // int count; - str->count = SV_ReadLong(); - - // int maxlight; - str->maxlight = SV_ReadLong(); - - // int minlight; - str->minlight = SV_ReadLong(); - - // int maxtime; - str->maxtime = SV_ReadLong(); - - // int mintime; - str->mintime = SV_ReadLong(); -} - -static void saveg_write_lightflash_t(lightflash_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // int count; - SV_WriteLong(str->count); - - // int maxlight; - SV_WriteLong(str->maxlight); - - // int minlight; - SV_WriteLong(str->minlight); - - // int maxtime; - SV_WriteLong(str->maxtime); - - // int mintime; - SV_WriteLong(str->mintime); -} - - -// -// strobe_t -// - -static void saveg_read_strobe_t(strobe_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // int count; - str->count = SV_ReadLong(); - - // int minlight; - str->minlight = SV_ReadLong(); - - // int maxlight; - str->maxlight = SV_ReadLong(); - - // int darktime; - str->darktime = SV_ReadLong(); - - // int brighttime; - str->brighttime = SV_ReadLong(); -} - -static void saveg_write_strobe_t(strobe_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // int count; - SV_WriteLong(str->count); - - // int minlight; - SV_WriteLong(str->minlight); - - // int maxlight; - SV_WriteLong(str->maxlight); - - // int darktime; - SV_WriteLong(str->darktime); - - // int brighttime; - SV_WriteLong(str->brighttime); -} - - -// -// glow_t -// - -static void saveg_read_glow_t(glow_t *str) -{ - int i; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // int minlight; - str->minlight = SV_ReadLong(); - - // int maxlight; - str->maxlight = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); -} - -static void saveg_write_glow_t(glow_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // int minlight; - SV_WriteLong(str->minlight); - - // int maxlight; - SV_WriteLong(str->maxlight); - - // int direction; - SV_WriteLong(str->direction); -} - - -/* -==================== -= -= P_ArchivePlayers -= -==================== -*/ - -void P_ArchivePlayers(void) -{ - int i; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - { - continue; - } - saveg_write_player_t(&players[i]); - } -} - -/* -==================== -= -= P_UnArchivePlayers -= -==================== -*/ - -void P_UnArchivePlayers(void) -{ - int i; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - saveg_read_player_t(&players[i]); - players[i].mo = NULL; // will be set when unarc thinker - players[i].message = NULL; - players[i].attacker = NULL; - } -} - -//============================================================================= - - -/* -==================== -= -= P_ArchiveWorld -= -==================== -*/ - -void P_ArchiveWorld(void) -{ - int i, j; - sector_t *sec; - line_t *li; - side_t *si; - - // Sectors - for (i = 0, sec = sectors; i < numsectors; i++, sec++) - { - SV_WriteWord(sec->floorheight >> FRACBITS); - SV_WriteWord(sec->ceilingheight >> FRACBITS); - SV_WriteWord(sec->floorpic); - SV_WriteWord(sec->ceilingpic); - SV_WriteWord(sec->lightlevel); - SV_WriteWord(sec->special); // needed? - SV_WriteWord(sec->tag); // needed? - } - - // Lines - for (i = 0, li = lines; i < numlines; i++, li++) - { - SV_WriteWord(li->flags); - SV_WriteWord(li->special); - SV_WriteWord(li->tag); - for (j = 0; j < 2; j++) - { - if (li->sidenum[j] == -1) - { - continue; - } - si = &sides[li->sidenum[j]]; - SV_WriteWord(si->textureoffset >> FRACBITS); - SV_WriteWord(si->rowoffset >> FRACBITS); - SV_WriteWord(si->toptexture); - SV_WriteWord(si->bottomtexture); - SV_WriteWord(si->midtexture); - } - } -} - -/* -==================== -= -= P_UnArchiveWorld -= -==================== -*/ - -void P_UnArchiveWorld(void) -{ - int i, j; - sector_t *sec; - line_t *li; - side_t *si; - -// -// do sectors -// - for (i = 0, sec = sectors; i < numsectors; i++, sec++) - { - sec->floorheight = SV_ReadWord() << FRACBITS; - sec->ceilingheight = SV_ReadWord() << FRACBITS; - sec->floorpic = SV_ReadWord(); - sec->ceilingpic = SV_ReadWord(); - sec->lightlevel = SV_ReadWord(); - sec->special = SV_ReadWord(); // needed? - sec->tag = SV_ReadWord(); // needed? - sec->specialdata = 0; - sec->soundtarget = 0; - } - -// -// do lines -// - for (i = 0, li = lines; i < numlines; i++, li++) - { - li->flags = SV_ReadWord(); - li->special = SV_ReadWord(); - li->tag = SV_ReadWord(); - for (j = 0; j < 2; j++) - { - if (li->sidenum[j] == -1) - continue; - si = &sides[li->sidenum[j]]; - si->textureoffset = SV_ReadWord() << FRACBITS; - si->rowoffset = SV_ReadWord() << FRACBITS; - si->toptexture = SV_ReadWord(); - si->bottomtexture = SV_ReadWord(); - si->midtexture = SV_ReadWord(); - } - } -} - -//============================================================================= - -typedef enum -{ - tc_end, - tc_mobj -} thinkerclass_t; - -/* -==================== -= -= P_ArchiveThinkers -= -==================== -*/ - -void P_ArchiveThinkers(void) -{ - thinker_t *th; - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function == P_MobjThinker) - { - SV_WriteByte(tc_mobj); - saveg_write_mobj_t((mobj_t *) th); - } - //I_Error("P_ArchiveThinkers: Unknown thinker function"); - } - - // Add a terminating marker - SV_WriteByte(tc_end); -} - -/* -==================== -= -= P_UnArchiveThinkers -= -==================== -*/ - -void P_UnArchiveThinkers(void) -{ - byte tclass; - thinker_t *currentthinker, *next; - mobj_t *mobj; - - // - // remove all the current thinkers - // - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) - { - next = currentthinker->next; - if (currentthinker->function == P_MobjThinker) - P_RemoveMobj((mobj_t *) currentthinker); - else - Z_Free(currentthinker); - currentthinker = next; - } - P_InitThinkers(); - - // read in saved thinkers - while (1) - { - tclass = SV_ReadByte(); - switch (tclass) - { - case tc_end: - return; // end of list - - case tc_mobj: - mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); - saveg_read_mobj_t(mobj); - mobj->target = NULL; - P_SetThingPosition(mobj); - mobj->info = &mobjinfo[mobj->type]; - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - mobj->thinker.function = P_MobjThinker; - P_AddThinker(&mobj->thinker); - break; - - default: - I_Error("Unknown tclass %i in savegame", tclass); - } - - } - -} - -//============================================================================= - - -/* -==================== -= -= P_ArchiveSpecials -= -==================== -*/ -enum -{ - tc_ceiling, - tc_door, - tc_floor, - tc_plat, - tc_flash, - tc_strobe, - tc_glow, - tc_endspecials -} specials_e; - -void P_ArchiveSpecials(void) -{ - /* - T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list - T_VerticalDoor, (vldoor_t: sector_t * swizzle), - T_MoveFloor, (floormove_t: sector_t * swizzle), - T_LightFlash, (lightflash_t: sector_t * swizzle), - T_StrobeFlash, (strobe_t: sector_t *), - T_Glow, (glow_t: sector_t *), - T_PlatRaise, (plat_t: sector_t *), - active list - */ - - thinker_t *th; - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function == T_MoveCeiling) - { - SV_WriteByte(tc_ceiling); - saveg_write_ceiling_t((ceiling_t *) th); - } - else if (th->function == T_VerticalDoor) - { - SV_WriteByte(tc_door); - saveg_write_vldoor_t((vldoor_t *) th); - } - else if (th->function == T_MoveFloor) - { - SV_WriteByte(tc_floor); - saveg_write_floormove_t((floormove_t *) th); - } - else if (th->function == T_PlatRaise) - { - SV_WriteByte(tc_plat); - saveg_write_plat_t((plat_t *) th); - } - else if (th->function == T_LightFlash) - { - SV_WriteByte(tc_flash); - saveg_write_lightflash_t((lightflash_t *) th); - } - else if (th->function == T_StrobeFlash) - { - SV_WriteByte(tc_strobe); - saveg_write_strobe_t((strobe_t *) th); - } - else if (th->function == T_Glow) - { - SV_WriteByte(tc_glow); - saveg_write_glow_t((glow_t *) th); - } - } - // Add a terminating marker - SV_WriteByte(tc_endspecials); -} - -/* -==================== -= -= P_UnArchiveSpecials -= -==================== -*/ - -void P_UnArchiveSpecials(void) -{ - byte tclass; - ceiling_t *ceiling; - vldoor_t *door; - floormove_t *floor; - plat_t *plat; - lightflash_t *flash; - strobe_t *strobe; - glow_t *glow; - - - // read in saved thinkers - while (1) - { - tclass = SV_ReadByte(); - switch (tclass) - { - case tc_endspecials: - return; // end of list - - case tc_ceiling: - ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVEL, NULL); - saveg_read_ceiling_t(ceiling); - ceiling->sector->specialdata = T_MoveCeiling; // ??? - ceiling->thinker.function = T_MoveCeiling; - P_AddThinker(&ceiling->thinker); - P_AddActiveCeiling(ceiling); - break; - - case tc_door: - door = Z_Malloc(sizeof(*door), PU_LEVEL, NULL); - saveg_read_vldoor_t(door); - door->sector->specialdata = door; - door->thinker.function = T_VerticalDoor; - P_AddThinker(&door->thinker); - break; - - case tc_floor: - floor = Z_Malloc(sizeof(*floor), PU_LEVEL, NULL); - saveg_read_floormove_t(floor); - floor->sector->specialdata = T_MoveFloor; - floor->thinker.function = T_MoveFloor; - P_AddThinker(&floor->thinker); - break; - - case tc_plat: - plat = Z_Malloc(sizeof(*plat), PU_LEVEL, NULL); - saveg_read_plat_t(plat); - plat->sector->specialdata = T_PlatRaise; - // In the original Heretic code this was a conditional "fix" - // of the thinker function, but the save code (above) decides - // whether to save a T_PlatRaise based on thinker function - // anyway, so it can't be NULL. Having the conditional causes - // a bug, as our saveg_read_thinker_t sets these to NULL. - // if (plat->thinker.function) - plat->thinker.function = T_PlatRaise; - P_AddThinker(&plat->thinker); - P_AddActivePlat(plat); - break; - - case tc_flash: - flash = Z_Malloc(sizeof(*flash), PU_LEVEL, NULL); - saveg_read_lightflash_t(flash); - flash->thinker.function = T_LightFlash; - P_AddThinker(&flash->thinker); - break; - - case tc_strobe: - strobe = Z_Malloc(sizeof(*strobe), PU_LEVEL, NULL); - saveg_read_strobe_t(strobe); - strobe->thinker.function = T_StrobeFlash; - P_AddThinker(&strobe->thinker); - break; - - case tc_glow: - glow = Z_Malloc(sizeof(*glow), PU_LEVEL, NULL); - saveg_read_glow_t(glow); - glow->thinker.function = T_Glow; - P_AddThinker(&glow->thinker); - break; - - default: - I_Error("P_UnarchiveSpecials:Unknown tclass %i " - "in savegame", tclass); - } - - } - -} - - diff --git a/games/NXDoom/src/heretic/p_setup.c b/games/NXDoom/src/heretic/p_setup.c deleted file mode 100644 index 645175552ec..00000000000 --- a/games/NXDoom/src/heretic/p_setup.c +++ /dev/null @@ -1,709 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_main.c - -#include -#include - -#include "doomdef.h" -#include "i_swap.h" -#include "i_system.h" -#include "m_argv.h" -#include "m_bbox.h" -#include "p_local.h" -#include "p_rejectpad.h" -#include "s_sound.h" - -void P_SpawnMapThing(mapthing_t * mthing); - -int numvertexes; -vertex_t *vertexes; - -int numsegs; -seg_t *segs; - -int numsectors; -sector_t *sectors; - -int numsubsectors; -subsector_t *subsectors; - -int numnodes; -node_t *nodes; - -int numlines; -line_t *lines; - -int numsides; -side_t *sides; - -static int totallines; - -short *blockmaplump; // offsets in blockmap are from here -short *blockmap; -int bmapwidth, bmapheight; // in mapblocks -fixed_t bmaporgx, bmaporgy; // origin of block map -mobj_t **blocklinks; // for thing chains - -byte *rejectmatrix; // for fast sight rejection - -mapthing_t deathmatchstarts[10], *deathmatch_p; -mapthing_t playerstarts[MAXPLAYERS]; -boolean playerstartsingame[MAXPLAYERS]; - -/* -================= -= -= P_LoadVertexes -= -================= -*/ - -void P_LoadVertexes(int lump) -{ - byte *data; - int i; - mapvertex_t *ml; - vertex_t *li; - - numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t); - vertexes = Z_Malloc(numvertexes * sizeof(vertex_t), PU_LEVEL, 0); - data = W_CacheLumpNum(lump, PU_STATIC); - - ml = (mapvertex_t *) data; - li = vertexes; - for (i = 0; i < numvertexes; i++, li++, ml++) - { - li->x = SHORT(ml->x) << FRACBITS; - li->y = SHORT(ml->y) << FRACBITS; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSegs -= -================= -*/ - -void P_LoadSegs(int lump) -{ - byte *data; - int i; - mapseg_t *ml; - seg_t *li; - line_t *ldef; - int linedef, side; - - numsegs = W_LumpLength(lump) / sizeof(mapseg_t); - segs = Z_Malloc(numsegs * sizeof(seg_t), PU_LEVEL, 0); - memset(segs, 0, numsegs * sizeof(seg_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - ml = (mapseg_t *) data; - li = segs; - for (i = 0; i < numsegs; i++, li++, ml++) - { - li->v1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; - - li->angle = (SHORT(ml->angle)) << 16; - li->offset = (SHORT(ml->offset)) << 16; - linedef = SHORT(ml->linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - side = SHORT(ml->side); - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef->flags & ML_TWOSIDED) - li->backsector = sides[ldef->sidenum[side ^ 1]].sector; - else - li->backsector = 0; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSubsectors -= -================= -*/ - -void P_LoadSubsectors(int lump) -{ - byte *data; - int i; - mapsubsector_t *ms; - subsector_t *ss; - - numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t); - subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0); - data = W_CacheLumpNum(lump, PU_STATIC); - - ms = (mapsubsector_t *) data; - memset(subsectors, 0, numsubsectors * sizeof(subsector_t)); - ss = subsectors; - for (i = 0; i < numsubsectors; i++, ss++, ms++) - { - ss->numlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSectors -= -================= -*/ - -void P_LoadSectors(int lump) -{ - byte *data; - int i; - mapsector_t *ms; - sector_t *ss; - - numsectors = W_LumpLength(lump) / sizeof(mapsector_t); - sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0); - memset(sectors, 0, numsectors * sizeof(sector_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - ms = (mapsector_t *) data; - ss = sectors; - for (i = 0; i < numsectors; i++, ss++, ms++) - { - ss->floorheight = SHORT(ms->floorheight) << FRACBITS; - ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS; - ss->floorpic = R_FlatNumForName(ms->floorpic); - ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); - ss->lightlevel = SHORT(ms->lightlevel); - ss->special = SHORT(ms->special); - ss->tag = SHORT(ms->tag); - ss->thinglist = NULL; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadNodes -= -================= -*/ - -void P_LoadNodes(int lump) -{ - byte *data; - int i, j, k; - mapnode_t *mn; - node_t *no; - - numnodes = W_LumpLength(lump) / sizeof(mapnode_t); - nodes = Z_Malloc(numnodes * sizeof(node_t), PU_LEVEL, 0); - data = W_CacheLumpNum(lump, PU_STATIC); - - mn = (mapnode_t *) data; - no = nodes; - for (i = 0; i < numnodes; i++, no++, mn++) - { - no->x = SHORT(mn->x) << FRACBITS; - no->y = SHORT(mn->y) << FRACBITS; - no->dx = SHORT(mn->dx) << FRACBITS; - no->dy = SHORT(mn->dy) << FRACBITS; - for (j = 0; j < 2; j++) - { - no->children[j] = SHORT(mn->children[j]); - for (k = 0; k < 4; k++) - no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; - } - } - - W_ReleaseLumpNum(lump); -} - - - -/* -================= -= -= P_LoadThings -= -================= -*/ - -void P_LoadThings(int lump) -{ - byte *data; - int i; - mapthing_t spawnthing; - mapthing_t *mt; - int numthings; - - data = W_CacheLumpNum(lump, PU_STATIC); - numthings = W_LumpLength(lump) / sizeof(mapthing_t); - - mt = (mapthing_t *) data; - for (i = 0; i < numthings; i++, mt++) - { - spawnthing.x = SHORT(mt->x); - spawnthing.y = SHORT(mt->y); - spawnthing.angle = SHORT(mt->angle); - spawnthing.type = SHORT(mt->type); - spawnthing.options = SHORT(mt->options); - P_SpawnMapThing(&spawnthing); - } - - if (!deathmatch) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !playerstartsingame[i]) - { - I_Error("P_LoadThings: Player %d start missing (vanilla crashes here)", i + 1); - } - playerstartsingame[i] = false; - } - } - - W_ReleaseLumpNum(lump); -} - - - -/* -================= -= -= P_LoadLineDefs -= -= Also counts secret lines for intermissions -================= -*/ - -void P_LoadLineDefs(int lump) -{ - byte *data; - int i; - maplinedef_t *mld; - line_t *ld; - vertex_t *v1, *v2; - - numlines = W_LumpLength(lump) / sizeof(maplinedef_t); - lines = Z_Malloc(numlines * sizeof(line_t), PU_LEVEL, 0); - memset(lines, 0, numlines * sizeof(line_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - mld = (maplinedef_t *) data; - ld = lines; - for (i = 0; i < numlines; i++, mld++, ld++) - { - ld->flags = SHORT(mld->flags); - ld->special = SHORT(mld->special); - ld->tag = SHORT(mld->tag); - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else - { - if (FixedDiv(ld->dy, ld->dx) > 0) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - } - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - if (ld->sidenum[0] != -1) - ld->frontsector = sides[ld->sidenum[0]].sector; - else - ld->frontsector = 0; - if (ld->sidenum[1] != -1) - ld->backsector = sides[ld->sidenum[1]].sector; - else - ld->backsector = 0; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSideDefs -= -================= -*/ - -void P_LoadSideDefs(int lump) -{ - byte *data; - int i; - mapsidedef_t *msd; - side_t *sd; - - numsides = W_LumpLength(lump) / sizeof(mapsidedef_t); - sides = Z_Malloc(numsides * sizeof(side_t), PU_LEVEL, 0); - memset(sides, 0, numsides * sizeof(side_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - msd = (mapsidedef_t *) data; - sd = sides; - for (i = 0; i < numsides; i++, msd++, sd++) - { - sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS; - sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS; - sd->toptexture = R_TextureNumForName(msd->toptexture); - sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); - sd->midtexture = R_TextureNumForName(msd->midtexture); - sd->sector = §ors[SHORT(msd->sector)]; - } - - W_ReleaseLumpNum(lump); -} - - - -/* -================= -= -= P_LoadBlockMap -= -================= -*/ - -void P_LoadBlockMap(int lump) -{ - int i, count; - int lumplen; - - lumplen = W_LumpLength(lump); - - blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); - W_ReadLump(lump, blockmaplump); - blockmap = blockmaplump + 4; - - // Swap all short integers to native byte ordering: - - count = lumplen / 2; - for (i = 0; i < count; i++) - blockmaplump[i] = SHORT(blockmaplump[i]); - - bmaporgx = blockmaplump[0] << FRACBITS; - bmaporgy = blockmaplump[1] << FRACBITS; - bmapwidth = blockmaplump[2]; - bmapheight = blockmaplump[3]; - -// clear out mobj chains - count = sizeof(*blocklinks) * bmapwidth * bmapheight; - blocklinks = Z_Malloc(count, PU_LEVEL, 0); - memset(blocklinks, 0, count); -} - - - - -/* -================= -= -= P_GroupLines -= -= Builds sector line lists and subsector sector numbers -= Finds block bounding boxes for sectors -================= -*/ - -void P_GroupLines(void) -{ - line_t **linebuffer; - int i, j; - line_t *li; - sector_t *sector; - subsector_t *ss; - seg_t *seg; - fixed_t bbox[4]; - int block; - -// look up sector number for each subsector - ss = subsectors; - for (i = 0; i < numsubsectors; i++, ss++) - { - seg = &segs[ss->firstline]; - ss->sector = seg->sidedef->sector; - } - -// count number of lines in each sector - li = lines; - totallines = 0; - for (i = 0; i < numlines; i++, li++) - { - totallines++; - li->frontsector->linecount++; - if (li->backsector && li->backsector != li->frontsector) - { - li->backsector->linecount++; - totallines++; - } - } - -// build line tables for each sector - linebuffer = Z_Malloc(totallines * sizeof(line_t *), PU_LEVEL, 0); - sector = sectors; - for (i = 0; i < numsectors; i++, sector++) - { - M_ClearBox(bbox); - sector->lines = linebuffer; - li = lines; - for (j = 0; j < numlines; j++, li++) - { - if (li->frontsector == sector || li->backsector == sector) - { - *linebuffer++ = li; - M_AddToBox(bbox, li->v1->x, li->v1->y); - M_AddToBox(bbox, li->v2->x, li->v2->y); - } - } - if (linebuffer - sector->lines != sector->linecount) - I_Error("P_GroupLines: miscounted"); - - // set the degenmobj_t to the middle of the bounding box - sector->soundorg.x = (bbox[BOXRIGHT] + bbox[BOXLEFT]) / 2; - sector->soundorg.y = (bbox[BOXTOP] + bbox[BOXBOTTOM]) / 2; - - // adjust bounding box to map blocks - block = (bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - block = block >= bmapheight ? bmapheight - 1 : block; - sector->blockbox[BOXTOP] = block; - - block = (bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXBOTTOM] = block; - - block = (bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - block = block >= bmapwidth ? bmapwidth - 1 : block; - sector->blockbox[BOXRIGHT] = block; - - block = (bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXLEFT] = block; - } - -} - - -static void P_LoadReject(int lumpnum) -{ - int minlength; - int lumplen; - - // Calculate the size that the REJECT lump *should* be. - - minlength = (numsectors * numsectors + 7) / 8; - - // If the lump meets the minimum length, it can be loaded directly. - // Otherwise, we need to allocate a buffer of the correct size - // and pad it with appropriate data. - - lumplen = W_LumpLength(lumpnum); - - if (lumplen >= minlength) - { - rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); - } - else - { - rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); - W_ReadLump(lumpnum, rejectmatrix); - - PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); - } -} - -//============================================================================= - -lumpinfo_t *maplumpinfo; - -/* -================= -= -= P_SetupLevel -= -================= -*/ - -void P_SetupLevel(int episode, int map, int playermask, skill_t skill) -{ - int i; - int parm; - char lumpname[9]; - int lumpnum; - mobj_t *mobj; - - totalkills = totalitems = totalsecret = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - players[i].killcount = players[i].secretcount - = players[i].itemcount = 0; - } - players[consoleplayer].viewz = 1; // will be set by player think - - S_Start(); // make sure all sounds are stopped before Z_FreeTags - - Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); - - P_InitThinkers(); - -// -// look for a regular (development) map first -// - lumpname[0] = 'E'; - lumpname[1] = '0' + episode; - lumpname[2] = 'M'; - lumpname[3] = '0' + map; - lumpname[4] = 0; - leveltime = 0; - - lumpnum = W_GetNumForName(lumpname); - - maplumpinfo = lumpinfo[lumpnum]; - -// note: most of this ordering is important - P_LoadBlockMap(lumpnum + ML_BLOCKMAP); - P_LoadVertexes(lumpnum + ML_VERTEXES); - P_LoadSectors(lumpnum + ML_SECTORS); - P_LoadSideDefs(lumpnum + ML_SIDEDEFS); - - P_LoadLineDefs(lumpnum + ML_LINEDEFS); - P_LoadSubsectors(lumpnum + ML_SSECTORS); - P_LoadNodes(lumpnum + ML_NODES); - P_LoadSegs(lumpnum + ML_SEGS); - - P_GroupLines(); - P_LoadReject(lumpnum + ML_REJECT); - - bodyqueslot = 0; - deathmatch_p = deathmatchstarts; - P_InitAmbientSound(); - P_InitMonsters(); - P_OpenWeapons(); - P_LoadThings(lumpnum + ML_THINGS); - P_CloseWeapons(); - -// -// if deathmatch, randomly spawn the active players -// - TimerGame = 0; - if (deathmatch) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { // must give a player spot before deathmatchspawn - mobj = P_SpawnMobj(playerstarts[i].x << 16, - playerstarts[i].y << 16, 0, MT_PLAYER); - players[i].mo = mobj; - G_DeathMatchSpawnPlayer(i); - P_RemoveMobj(mobj); - } - } - - //! - // @arg - // @category net - // @vanilla - // - // For multiplayer games: exit each level after n minutes. - // - - parm = M_CheckParmWithArgs("-timer", 1); - if (parm) - { - TimerGame = atoi(myargv[parm + 1]) * 35 * 60; - } - } - -// set up world state - P_SpawnSpecials(); - -// build subsector connect matrix -// P_ConnectSubsectors (); - -// preload graphics - if (precache) - R_PrecacheLevel(); - -//printf ("free memory: 0x%x\n", Z_FreeMemory()); - -} - - -/* -================= -= -= P_Init -= -================= -*/ - -void P_Init(void) -{ - P_InitSwitchList(); - P_InitPicAnims(); - P_InitTerrainTypes(); - P_InitLava(); - R_InitSprites(sprnames); -} diff --git a/games/NXDoom/src/heretic/p_sight.c b/games/NXDoom/src/heretic/p_sight.c deleted file mode 100644 index 3a442daefa6..00000000000 --- a/games/NXDoom/src/heretic/p_sight.c +++ /dev/null @@ -1,355 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// P_sight.c - -#include - -#include "doomdef.h" -#include "p_local.h" - -/* -============================================================================== - - P_CheckSight - -This uses specialized forms of the maputils routines for optimized performance - -============================================================================== -*/ - -fixed_t sightzstart; // eye z of looker -fixed_t topslope, bottomslope; // slopes to top and bottom of target - -int sightcounts[3]; - -/* -============== -= -= PTR_SightTraverse -= -============== -*/ - -boolean PTR_SightTraverse(intercept_t * in) -{ - line_t *li; - fixed_t slope; - - li = in->d.line; - -// -// crosses a two sided line -// - P_LineOpening(li); - - if (openbottom >= opentop) // quick test for totally closed doors - return false; // stop - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv(openbottom - sightzstart, in->frac); - if (slope > bottomslope) - bottomslope = slope; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv(opentop - sightzstart, in->frac); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - - return true; // keep going -} - - - -/* -================== -= -= P_SightBlockLinesIterator -= -=================== -*/ - -boolean P_SightBlockLinesIterator(int x, int y) -{ - int offset; - short *list; - line_t *ld; - int s1, s2; - divline_t dl; - - offset = y * bmapwidth + x; - - offset = *(blockmap + offset); - - for (list = blockmaplump + offset; *list != -1; list++) - { - ld = &lines[*list]; - if (ld->validcount == validcount) - continue; // line has already been checked - ld->validcount = validcount; - - s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); - if (s1 == s2) - continue; // line isn't crossed - P_MakeDivline(ld, &dl); - s1 = P_PointOnDivlineSide(trace.x, trace.y, &dl); - s2 = P_PointOnDivlineSide(trace.x + trace.dx, trace.y + trace.dy, - &dl); - if (s1 == s2) - continue; // line isn't crossed - - // try to early out the check - if (!ld->backsector) - return false; // stop checking - - // store the line for later intersection testing - intercept_p->d.line = ld; - intercept_p++; - - } - - return true; // everything was checked -} - -/* -==================== -= -= P_SightTraverseIntercepts -= -= Returns true if the traverser function returns true for all lines -==================== -*/ - -boolean P_SightTraverseIntercepts(void) -{ - int count; - fixed_t dist; - intercept_t *scan, *in; - divline_t dl; - - count = intercept_p - intercepts; -// -// calculate intercept distance -// - for (scan = intercepts; scan < intercept_p; scan++) - { - P_MakeDivline(scan->d.line, &dl); - scan->frac = P_InterceptVector(&trace, &dl); - } - -// -// go through in order -// - in = 0; // shut up compiler warning - - while (count--) - { - dist = INT_MAX; - for (scan = intercepts; scan < intercept_p; scan++) - if (scan->frac < dist) - { - dist = scan->frac; - in = scan; - } - - if (!PTR_SightTraverse(in)) - return false; // don't bother going farther - in->frac = INT_MAX; - } - - return true; // everything was traversed -} - - - -/* -================== -= -= P_SightPathTraverse -= -= Traces a line from x1,y1 to x2,y2, calling the traverser function for each -= Returns true if the traverser function returns true for all lines -================== -*/ - -boolean P_SightPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) -{ - fixed_t xt1, yt1, xt2, yt2; - fixed_t xstep, ystep; - fixed_t partial; - fixed_t xintercept, yintercept; - int mapx, mapy, mapxstep, mapystep; - int count; - - validcount++; - intercept_p = intercepts; - - if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) - x1 += FRACUNIT; // don't side exactly on a line - if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) - y1 += FRACUNIT; // don't side exactly on a line - trace.x = x1; - trace.y = y1; - trace.dx = x2 - x1; - trace.dy = y2 - y1; - - x1 -= bmaporgx; - y1 -= bmaporgy; - xt1 = x1 >> MAPBLOCKSHIFT; - yt1 = y1 >> MAPBLOCKSHIFT; - - x2 -= bmaporgx; - y2 -= bmaporgy; - xt2 = x2 >> MAPBLOCKSHIFT; - yt2 = y2 >> MAPBLOCKSHIFT; - -// points should never be out of bounds, but check once instead of -// each block - if (xt1 < 0 || yt1 < 0 || xt1 >= bmapwidth || yt1 >= bmapheight - || xt2 < 0 || yt2 < 0 || xt2 >= bmapwidth || yt2 >= bmapheight) - return false; - - if (xt2 > xt1) - { - mapxstep = 1; - partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else if (xt2 < xt1) - { - mapxstep = -1; - partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else - { - mapxstep = 0; - partial = FRACUNIT; - ystep = 256 * FRACUNIT; - } - yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); - - - if (yt2 > yt1) - { - mapystep = 1; - partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else - { - mapystep = 0; - partial = FRACUNIT; - xstep = 256 * FRACUNIT; - } - xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); - - -// -// step through map blocks -// Count is present to prevent a round off error from skipping the break - mapx = xt1; - mapy = yt1; - - - for (count = 0; count < 64; count++) - { - if (!P_SightBlockLinesIterator(mapx, mapy)) - { - sightcounts[1]++; - return false; // early out - } - - if (mapx == xt2 && mapy == yt2) - break; - - if ((yintercept >> FRACBITS) == mapy) - { - yintercept += ystep; - mapx += mapxstep; - } - else if ((xintercept >> FRACBITS) == mapx) - { - xintercept += xstep; - mapy += mapystep; - } - - } - - -// -// couldn't early out, so go through the sorted list -// - sightcounts[2]++; - - return P_SightTraverseIntercepts(); -} - - - -/* -===================== -= -= P_CheckSight -= -= Returns true if a straight line between t1 and t2 is unobstructed -= look from eyes of t1 to any part of t2 -= -===================== -*/ - -boolean P_CheckSight(mobj_t * t1, mobj_t * t2) -{ - int s1, s2; - int pnum, bytenum, bitnum; - -// -// check for trivial rejection -// - s1 = (t1->subsector->sector - sectors); - s2 = (t2->subsector->sector - sectors); - pnum = s1 * numsectors + s2; - bytenum = pnum >> 3; - bitnum = 1 << (pnum & 7); - - if (rejectmatrix[bytenum] & bitnum) - { - sightcounts[0]++; - return false; // can't possibly be connected - } - -// -// check precisely -// - sightzstart = t1->z + t1->height - (t1->height >> 2); - topslope = (t2->z + t2->height) - sightzstart; - bottomslope = (t2->z) - sightzstart; - - return P_SightPathTraverse(t1->x, t1->y, t2->x, t2->y); -} diff --git a/games/NXDoom/src/heretic/p_spec.c b/games/NXDoom/src/heretic/p_spec.c deleted file mode 100644 index cb89bac2115..00000000000 --- a/games/NXDoom/src/heretic/p_spec.c +++ /dev/null @@ -1,1306 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_Spec.c - -#include "doomdef.h" -#include "deh_str.h" -#include "i_system.h" -#include "i_timer.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -// Macros - -#define MAX_AMBIENT_SFX 8 // Per level - -// Types - -typedef enum -{ - afxcmd_play, // (sound) - afxcmd_playabsvol, // (sound, volume) - afxcmd_playrelvol, // (sound, volume) - afxcmd_delay, // (ticks) - afxcmd_delayrand, // (andbits) - afxcmd_end // () -} afxcmd_t; - -// Data - -int *LevelAmbientSfx[MAX_AMBIENT_SFX]; -int *AmbSfxPtr; -int AmbSfxCount; -int AmbSfxTics; -int AmbSfxVolume; - -int AmbSndSeqInit[] = { // Startup - afxcmd_end -}; -int AmbSndSeq1[] = { // Scream - afxcmd_play, sfx_amb1, - afxcmd_end -}; -int AmbSndSeq2[] = { // Squish - afxcmd_play, sfx_amb2, - afxcmd_end -}; -int AmbSndSeq3[] = { // Drops - afxcmd_play, sfx_amb3, - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, sfx_amb7, - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, sfx_amb3, - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, sfx_amb7, - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, sfx_amb3, - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, sfx_amb7, - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_end -}; -int AmbSndSeq4[] = { // SlowFootSteps - afxcmd_play, sfx_amb4, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb4, -3, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb4, -3, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb4, -3, - afxcmd_delay, 15, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_end -}; -int AmbSndSeq5[] = { // Heartbeat - afxcmd_play, sfx_amb5, - afxcmd_delay, 35, - afxcmd_play, sfx_amb5, - afxcmd_delay, 35, - afxcmd_play, sfx_amb5, - afxcmd_delay, 35, - afxcmd_play, sfx_amb5, - afxcmd_end -}; -int AmbSndSeq6[] = { // Bells - afxcmd_play, sfx_amb6, - afxcmd_delay, 17, - afxcmd_playrelvol, sfx_amb6, -8, - afxcmd_delay, 17, - afxcmd_playrelvol, sfx_amb6, -8, - afxcmd_delay, 17, - afxcmd_playrelvol, sfx_amb6, -8, - afxcmd_end -}; -int AmbSndSeq7[] = { // Growl - afxcmd_play, sfx_bstsit, - afxcmd_end -}; -int AmbSndSeq8[] = { // Magic - afxcmd_play, sfx_amb8, - afxcmd_end -}; -int AmbSndSeq9[] = { // Laughter - afxcmd_play, sfx_amb9, - afxcmd_delay, 16, - afxcmd_playrelvol, sfx_amb9, -4, - afxcmd_delay, 16, - afxcmd_playrelvol, sfx_amb9, -4, - afxcmd_delay, 16, - afxcmd_playrelvol, sfx_amb10, -4, - afxcmd_delay, 16, - afxcmd_playrelvol, sfx_amb10, -4, - afxcmd_delay, 16, - afxcmd_playrelvol, sfx_amb10, -4, - afxcmd_end -}; -int AmbSndSeq10[] = { // FastFootsteps - afxcmd_play, sfx_amb4, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb4, -3, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb4, -3, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb4, -3, - afxcmd_delay, 8, - afxcmd_playrelvol, sfx_amb11, -3, - afxcmd_end -}; - -int *AmbientSfx[] = { - AmbSndSeq1, // Scream - AmbSndSeq2, // Squish - AmbSndSeq3, // Drops - AmbSndSeq4, // SlowFootsteps - AmbSndSeq5, // Heartbeat - AmbSndSeq6, // Bells - AmbSndSeq7, // Growl - AmbSndSeq8, // Magic - AmbSndSeq9, // Laughter - AmbSndSeq10 // FastFootsteps -}; - -animdef_t animdefs[] = { - // false = flat - // true = texture - {false, "FLTWAWA3", "FLTWAWA1", 8}, // Water - {false, "FLTSLUD3", "FLTSLUD1", 8}, // Sludge - {false, "FLTTELE4", "FLTTELE1", 6}, // Teleport - {false, "FLTFLWW3", "FLTFLWW1", 9}, // River - West - {false, "FLTLAVA4", "FLTLAVA1", 8}, // Lava - {false, "FLATHUH4", "FLATHUH1", 8}, // Super Lava - {true, "LAVAFL3", "LAVAFL1", 6}, // Texture: Lavaflow - {true, "WATRWAL3", "WATRWAL1", 4}, // Texture: Waterfall - {-1} -}; - -anim_t anims[MAXANIMS]; -anim_t *lastanim; - -int *TerrainTypes; -struct -{ - const char *name; - int type; -} TerrainTypeDefs[] = -{ - { "FLTWAWA1", FLOOR_WATER }, - { "FLTFLWW1", FLOOR_WATER }, - { "FLTLAVA1", FLOOR_LAVA }, - { "FLATHUH1", FLOOR_LAVA }, - { "FLTSLUD1", FLOOR_SLUDGE }, - { "END", -1 } -}; - -mobj_t LavaInflictor; - -//---------------------------------------------------------------------------- -// -// PROC P_InitLava -// -//---------------------------------------------------------------------------- - -void P_InitLava(void) -{ - memset(&LavaInflictor, 0, sizeof(mobj_t)); - LavaInflictor.type = MT_PHOENIXFX2; - LavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST; -} - -//---------------------------------------------------------------------------- -// -// PROC P_InitTerrainTypes -// -//---------------------------------------------------------------------------- - -void P_InitTerrainTypes(void) -{ - int i; - int lump; - int size; - - size = (numflats + 1) * sizeof(int); - TerrainTypes = Z_Malloc(size, PU_STATIC, 0); - memset(TerrainTypes, 0, size); - for (i = 0; TerrainTypeDefs[i].type != -1; i++) - { - lump = W_CheckNumForName(TerrainTypeDefs[i].name); - if (lump != -1) - { - TerrainTypes[lump - firstflat] = TerrainTypeDefs[i].type; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_InitPicAnims -// -//---------------------------------------------------------------------------- - -void P_InitPicAnims(void) -{ - const char *startname; - const char *endname; - int i; - - lastanim = anims; - for (i = 0; animdefs[i].istexture != -1; i++) - { - startname = DEH_String(animdefs[i].startname); - endname = DEH_String(animdefs[i].endname); - - if (animdefs[i].istexture) - { // Texture animation - if (R_CheckTextureNumForName(startname) == -1) - { // Texture doesn't exist - continue; - } - lastanim->picnum = R_TextureNumForName(endname); - lastanim->basepic = R_TextureNumForName(startname); - } - else - { // Flat animation - if (W_CheckNumForName(startname) == -1) - { // Flat doesn't exist - continue; - } - lastanim->picnum = R_FlatNumForName(endname); - lastanim->basepic = R_FlatNumForName(startname); - } - lastanim->istexture = animdefs[i].istexture; - lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; - if (lastanim->numpics < 2) - { - I_Error("P_InitPicAnims: bad cycle from %s to %s", - startname, endname); - } - lastanim->speed = animdefs[i].speed; - lastanim++; - } -} - -/* -============================================================================== - - UTILITIES - -============================================================================== -*/ - -// -// Will return a side_t* given the number of the current sector, -// the line number, and the side (0/1) that you want. -// -side_t *getSide(int currentSector, int line, int side) -{ - return &sides[(sectors[currentSector].lines[line])->sidenum[side]]; -} - -// -// Will return a sector_t* given the number of the current sector, -// the line number and the side (0/1) that you want. -// -sector_t *getSector(int currentSector, int line, int side) -{ - return sides[(sectors[currentSector].lines[line])->sidenum[side]].sector; -} - -// -// Given the sector number and the line number, will tell you whether -// the line is two-sided or not. -// -int twoSided(int sector, int line) -{ - return (sectors[sector].lines[line])->flags & ML_TWOSIDED; -} - -//================================================================== -// -// Return sector_t * of sector next to current. NULL if not two-sided line -// -//================================================================== -sector_t *getNextSector(line_t * line, sector_t * sec) -{ - if (!(line->flags & ML_TWOSIDED)) - return NULL; - - if (line->frontsector == sec) - return line->backsector; - - return line->frontsector; -} - -//================================================================== -// -// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindLowestFloorSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t floor = sec->floorheight; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->floorheight < floor) - floor = other->floorheight; - } - return floor; -} - -//================================================================== -// -// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindHighestFloorSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t floor = -500 * FRACUNIT; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->floorheight > floor) - floor = other->floorheight; - } - return floor; -} - -//================================================================== -// -// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight) -{ - int i; - int h; - fixed_t min; - line_t *check; - sector_t *other; - fixed_t height = currentheight; - - min = INT_MAX; - - for (i = 0, h = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - - if (other != NULL && other->floorheight > height) - { - if (other->floorheight < min) - { - min = other->floorheight; - } - - ++h; - } - } - - // Don't return INT_MAX if no higher floor is found. - - if (!h) - { - return height; - } - - // Compatibility note, in case of demo desyncs. - - if (h > 20) - { - fprintf(stderr, "P_FindNextHighestFloor: exceeded Vanilla limit\n"); - } - - return min; -} - -//================================================================== -// -// FIND LOWEST CEILING IN THE SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindLowestCeilingSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t height = INT_MAX; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->ceilingheight < height) - height = other->ceilingheight; - } - return height; -} - -//================================================================== -// -// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindHighestCeilingSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t height = 0; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->ceilingheight > height) - height = other->ceilingheight; - } - return height; -} - -//================================================================== -// -// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO -// -//================================================================== -int P_FindSectorFromLineTag(line_t * line, int start) -{ - int i; - - for (i = start + 1; i < numsectors; i++) - if (sectors[i].tag == line->tag) - return i; - return -1; -} - -//================================================================== -// -// Find minimum light from an adjacent sector -// -//================================================================== -int P_FindMinSurroundingLight(sector_t * sector, int max) -{ - int i; - int min; - line_t *line; - sector_t *check; - - min = max; - for (i = 0; i < sector->linecount; i++) - { - line = sector->lines[i]; - check = getNextSector(line, sector); - if (!check) - continue; - if (check->lightlevel < min) - min = check->lightlevel; - } - return min; -} - -/* -============================================================================== - - EVENTS - -Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers - -============================================================================== -*/ - - - -/* -=============================================================================== -= -= P_CrossSpecialLine - TRIGGER -= -= Called every time a thing origin is about to cross -= a line with a non 0 special -= -=============================================================================== -*/ - -void P_CrossSpecialLine(int linenum, int side, mobj_t * thing) -{ - line_t *line; - - line = &lines[linenum]; - if (!thing->player) - { // Check if trigger allowed by non-player mobj - switch (line->special) - { - case 39: // Trigger_TELEPORT - case 97: // Retrigger_TELEPORT - case 4: // Trigger_Raise_Door - //case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER - //case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER - break; - default: - return; - break; - } - } - switch (line->special) - { - //==================================================== - // TRIGGERS - //==================================================== - case 2: // Open Door - EV_DoDoor(line, vld_open, VDOORSPEED); - line->special = 0; - break; - case 3: // Close Door - EV_DoDoor(line, vld_close, VDOORSPEED); - line->special = 0; - break; - case 4: // Raise Door - EV_DoDoor(line, vld_normal, VDOORSPEED); - line->special = 0; - break; - case 5: // Raise Floor - EV_DoFloor(line, raiseFloor); - line->special = 0; - break; - case 6: // Fast Ceiling Crush & Raise - EV_DoCeiling(line, fastCrushAndRaise); - line->special = 0; - break; - case 8: // Trigger_Build_Stairs (8 pixel steps) - EV_BuildStairs(line, 8 * FRACUNIT); - line->special = 0; - break; - case 106: // Trigger_Build_Stairs_16 (16 pixel steps) - EV_BuildStairs(line, 16 * FRACUNIT); - line->special = 0; - break; - case 10: // PlatDownWaitUp - EV_DoPlat(line, downWaitUpStay, 0); - line->special = 0; - break; - case 12: // Light Turn On - brightest near - EV_LightTurnOn(line, 0); - line->special = 0; - break; - case 13: // Light Turn On 255 - EV_LightTurnOn(line, 255); - line->special = 0; - break; - case 16: // Close Door 30 - EV_DoDoor(line, vld_close30ThenOpen, VDOORSPEED); - line->special = 0; - break; - case 17: // Start Light Strobing - EV_StartLightStrobing(line); - line->special = 0; - break; - case 19: // Lower Floor - EV_DoFloor(line, lowerFloor); - line->special = 0; - break; - case 22: // Raise floor to nearest height and change texture - EV_DoPlat(line, raiseToNearestAndChange, 0); - line->special = 0; - break; - case 25: // Ceiling Crush and Raise - EV_DoCeiling(line, crushAndRaise); - line->special = 0; - break; - case 30: // Raise floor to shortest texture height - // on either side of lines - EV_DoFloor(line, raiseToTexture); - line->special = 0; - break; - case 35: // Lights Very Dark - EV_LightTurnOn(line, 35); - line->special = 0; - break; - case 36: // Lower Floor (TURBO) - EV_DoFloor(line, turboLower); - line->special = 0; - break; - case 37: // LowerAndChange - EV_DoFloor(line, lowerAndChange); - line->special = 0; - break; - case 38: // Lower Floor To Lowest - EV_DoFloor(line, lowerFloorToLowest); - line->special = 0; - break; - case 39: // TELEPORT! - EV_Teleport(line, side, thing); - line->special = 0; - break; - case 40: // RaiseCeilingLowerFloor - EV_DoCeiling(line, raiseToHighest); - EV_DoFloor(line, lowerFloorToLowest); - line->special = 0; - break; - case 44: // Ceiling Crush - EV_DoCeiling(line, lowerAndCrush); - line->special = 0; - break; - case 52: // EXIT! - G_ExitLevel(); - line->special = 0; - break; - case 53: // Perpetual Platform Raise - EV_DoPlat(line, perpetualRaise, 0); - line->special = 0; - break; - case 54: // Platform Stop - EV_StopPlat(line); - line->special = 0; - break; - case 56: // Raise Floor Crush - EV_DoFloor(line, raiseFloorCrush); - line->special = 0; - break; - case 57: // Ceiling Crush Stop - EV_CeilingCrushStop(line); - line->special = 0; - break; - case 58: // Raise Floor 24 - EV_DoFloor(line, raiseFloor24); - line->special = 0; - break; - case 59: // Raise Floor 24 And Change - EV_DoFloor(line, raiseFloor24AndChange); - line->special = 0; - break; - case 104: // Turn lights off in sector(tag) - EV_TurnTagLightsOff(line); - line->special = 0; - break; - case 105: // Trigger_SecretExit - G_SecretExitLevel(); - line->special = 0; - break; - - //==================================================== - // RE-DOABLE TRIGGERS - //==================================================== - - case 72: // Ceiling Crush - EV_DoCeiling(line, lowerAndCrush); - break; - case 73: // Ceiling Crush and Raise - EV_DoCeiling(line, crushAndRaise); - break; - case 74: // Ceiling Crush Stop - EV_CeilingCrushStop(line); - break; - case 75: // Close Door - EV_DoDoor(line, vld_close, VDOORSPEED); - break; - case 76: // Close Door 30 - EV_DoDoor(line, vld_close30ThenOpen, VDOORSPEED); - break; - case 77: // Fast Ceiling Crush & Raise - EV_DoCeiling(line, fastCrushAndRaise); - break; - case 79: // Lights Very Dark - EV_LightTurnOn(line, 35); - break; - case 80: // Light Turn On - brightest near - EV_LightTurnOn(line, 0); - break; - case 81: // Light Turn On 255 - EV_LightTurnOn(line, 255); - break; - case 82: // Lower Floor To Lowest - EV_DoFloor(line, lowerFloorToLowest); - break; - case 83: // Lower Floor - EV_DoFloor(line, lowerFloor); - break; - case 84: // LowerAndChange - EV_DoFloor(line, lowerAndChange); - break; - case 86: // Open Door - EV_DoDoor(line, vld_open, VDOORSPEED); - break; - case 87: // Perpetual Platform Raise - EV_DoPlat(line, perpetualRaise, 0); - break; - case 88: // PlatDownWaitUp - EV_DoPlat(line, downWaitUpStay, 0); - break; - case 89: // Platform Stop - EV_StopPlat(line); - break; - case 90: // Raise Door - EV_DoDoor(line, vld_normal, VDOORSPEED); - break; - case 100: // Retrigger_Raise_Door_Turbo - EV_DoDoor(line, vld_normal, VDOORSPEED * 3); - break; - case 91: // Raise Floor - EV_DoFloor(line, raiseFloor); - break; - case 92: // Raise Floor 24 - EV_DoFloor(line, raiseFloor24); - break; - case 93: // Raise Floor 24 And Change - EV_DoFloor(line, raiseFloor24AndChange); - break; - case 94: // Raise Floor Crush - EV_DoFloor(line, raiseFloorCrush); - break; - case 95: // Raise floor to nearest height and change texture - EV_DoPlat(line, raiseToNearestAndChange, 0); - break; - case 96: // Raise floor to shortest texture height - // on either side of lines - EV_DoFloor(line, raiseToTexture); - break; - case 97: // TELEPORT! - EV_Teleport(line, side, thing); - break; - case 98: // Lower Floor (TURBO) - EV_DoFloor(line, turboLower); - break; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_ShootSpecialLine -// -// Called when a thing shoots a special line. -// -//---------------------------------------------------------------------------- - -void P_ShootSpecialLine(mobj_t * thing, line_t * line) -{ - if (!thing->player) - { // Check if trigger allowed by non-player mobj - switch (line->special) - { - case 46: // Impact_OpenDoor - break; - default: - return; - break; - } - } - switch (line->special) - { - case 24: // Impact_RaiseFloor - EV_DoFloor(line, raiseFloor); - P_ChangeSwitchTexture(line, 0); - break; - case 46: // Impact_OpenDoor - EV_DoDoor(line, vld_open, VDOORSPEED); - P_ChangeSwitchTexture(line, 1); - break; - case 47: // Impact_RaiseFloorNear&Change - EV_DoPlat(line, raiseToNearestAndChange, 0); - P_ChangeSwitchTexture(line, 0); - break; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerInSpecialSector -// -// Called every tic frame that the player origin is in a special sector. -// -//---------------------------------------------------------------------------- - -void P_PlayerInSpecialSector(player_t * player) -{ - sector_t *sector; - static int pushTab[5] = { - 2048 * 5, - 2048 * 10, - 2048 * 25, - 2048 * 30, - 2048 * 35 - }; - - sector = player->mo->subsector->sector; - if (player->mo->z != sector->floorheight) - { // Player is not touching the floor - return; - } - switch (sector->special) - { - case 7: // Damage_Sludge - if (!(leveltime & 31)) - { - P_DamageMobj(player->mo, NULL, NULL, 4); - } - break; - case 5: // Damage_LavaWimpy - if (!(leveltime & 15)) - { - P_DamageMobj(player->mo, &LavaInflictor, NULL, 5); - P_HitFloor(player->mo); - } - break; - case 16: // Damage_LavaHefty - if (!(leveltime & 15)) - { - P_DamageMobj(player->mo, &LavaInflictor, NULL, 8); - P_HitFloor(player->mo); - } - break; - case 4: // Scroll_EastLavaDamage - P_Thrust(player, 0, 2048 * 28); - if (!(leveltime & 15)) - { - P_DamageMobj(player->mo, &LavaInflictor, NULL, 5); - P_HitFloor(player->mo); - } - break; - case 9: // SecretArea - player->secretcount++; - sector->special = 0; - break; - case 11: // Exit_SuperDamage (DOOM E1M8 finale) - /* - player->cheats &= ~CF_GODMODE; - if(!(leveltime&0x1f)) - { - P_DamageMobj(player->mo, NULL, NULL, 20); - } - if(player->health <= 10) - { - G_ExitLevel(); - } - */ - break; - - case 25: - case 26: - case 27: - case 28: - case 29: // Scroll_North - P_Thrust(player, ANG90, pushTab[sector->special - 25]); - break; - case 20: - case 21: - case 22: - case 23: - case 24: // Scroll_East - P_Thrust(player, 0, pushTab[sector->special - 20]); - break; - case 30: - case 31: - case 32: - case 33: - case 34: // Scroll_South - P_Thrust(player, ANG270, pushTab[sector->special - 30]); - break; - case 35: - case 36: - case 37: - case 38: - case 39: // Scroll_West - P_Thrust(player, ANG180, pushTab[sector->special - 35]); - break; - - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - case 48: - case 49: - case 50: - case 51: - // Wind specials are handled in (P_mobj):P_XYMovement - break; - - case 15: // Friction_Low - // Only used in (P_mobj):P_XYMovement and (P_user):P_Thrust - break; - - default: - I_Error("P_PlayerInSpecialSector: " - "unknown special %i", sector->special); - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_UpdateSpecials -// -// Animate planes, scroll walls, etc. -// -//---------------------------------------------------------------------------- - -void P_UpdateSpecials(void) -{ - int i; - int pic; - anim_t *anim; - line_t *line; - - // Animate flats and textures - for (anim = anims; anim < lastanim; anim++) - { - for (i = anim->basepic; i < anim->basepic + anim->numpics; i++) - { - pic = - anim->basepic + - ((leveltime / anim->speed + i) % anim->numpics); - if (anim->istexture) - { - texturetranslation[i] = pic; - } - else - { - flattranslation[i] = pic; - } - } - } - // Update scrolling texture offsets - for (i = 0; i < numlinespecials; i++) - { - line = linespeciallist[i]; - switch (line->special) - { - case 48: // Effect_Scroll_Left - sides[line->sidenum[0]].textureoffset += FRACUNIT; - break; - case 99: // Effect_Scroll_Right - sides[line->sidenum[0]].textureoffset -= FRACUNIT; - break; - } - } - // Handle buttons - for (i = 0; i < MAXBUTTONS; i++) - { - if (buttonlist[i].btimer) - { - buttonlist[i].btimer--; - if (!buttonlist[i].btimer) - { - switch (buttonlist[i].where) - { - case top: - sides[buttonlist[i].line->sidenum[0]].toptexture = - buttonlist[i].btexture; - break; - case middle: - sides[buttonlist[i].line->sidenum[0]].midtexture = - buttonlist[i].btexture; - break; - case bottom: - sides[buttonlist[i].line->sidenum[0]].bottomtexture = - buttonlist[i].btexture; - break; - } - S_StartSound(buttonlist[i].soundorg, sfx_switch); - memset(&buttonlist[i], 0, sizeof(button_t)); - } - } - } -} - -//============================================================ -// -// Special Stuff that can't be categorized -// -//============================================================ -int EV_DoDonut(line_t * line) -{ - sector_t *s1; - sector_t *s2; - sector_t *s3; - int secnum; - int rtn; - int i; - floormove_t *floor; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) - { - s1 = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (s1->specialdata) - continue; - - rtn = 1; - s2 = getNextSector(s1->lines[0], s1); - for (i = 0; i < s2->linecount; i++) - { - // Note: This was originally part of the following test: - // (!s2->lines[i]->flags & ML_TWOSIDED) || - // Due to the apparent mistaken formatting, this can never be - // true. - - if (s2->lines[i]->backsector == s1) - continue; - s3 = s2->lines[i]->backsector; - - // - // Spawn rising slime - // - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker(&floor->thinker); - s2->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = donutRaise; - floor->crush = false; - floor->direction = 1; - floor->sector = s2; - floor->speed = FLOORSPEED / 2; - floor->texture = s3->floorpic; - floor->newspecial = 0; - floor->floordestheight = s3->floorheight; - - // - // Spawn lowering donut-hole - // - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker(&floor->thinker); - s1->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = lowerFloor; - floor->crush = false; - floor->direction = -1; - floor->sector = s1; - floor->speed = FLOORSPEED / 2; - floor->floordestheight = s3->floorheight; - break; - } - } - return rtn; -} - -/* -============================================================================== - - SPECIAL SPAWNING - -============================================================================== -*/ -/* -================================================================================ -= P_SpawnSpecials -= -= After the map has been loaded, scan for specials that -= spawn thinkers -= -=============================================================================== -*/ - -short numlinespecials; -line_t *linespeciallist[MAXLINEANIMS]; - -void P_SpawnSpecials(void) -{ - sector_t *sector; - int i; - - // - // Init special SECTORs - // - sector = sectors; - for (i = 0; i < numsectors; i++, sector++) - { - if (!sector->special) - continue; - switch (sector->special) - { - case 1: // FLICKERING LIGHTS - P_SpawnLightFlash(sector); - break; - case 2: // STROBE FAST - P_SpawnStrobeFlash(sector, FASTDARK, 0); - break; - case 3: // STROBE SLOW - P_SpawnStrobeFlash(sector, SLOWDARK, 0); - break; - case 4: // STROBE FAST/DEATH SLIME - P_SpawnStrobeFlash(sector, FASTDARK, 0); - sector->special = 4; - break; - case 8: // GLOWING LIGHT - P_SpawnGlowingLight(sector); - break; - case 9: // SECRET SECTOR - totalsecret++; - break; - case 10: // DOOR CLOSE IN 30 SECONDS - P_SpawnDoorCloseIn30(sector); - break; - case 12: // SYNC STROBE SLOW - P_SpawnStrobeFlash(sector, SLOWDARK, 1); - break; - case 13: // SYNC STROBE FAST - P_SpawnStrobeFlash(sector, FASTDARK, 1); - break; - case 14: // DOOR RAISE IN 5 MINUTES - P_SpawnDoorRaiseIn5Mins(sector, i); - break; - } - } - - - // - // Init line EFFECTs - // - numlinespecials = 0; - for (i = 0; i < numlines; i++) - switch (lines[i].special) - { - case 48: // Effect_Scroll_Left - case 99: // Effect_Scroll_Right - linespeciallist[numlinespecials] = &lines[i]; - numlinespecials++; - break; - } - - // - // Init other misc stuff - // - for (i = 0; i < MAXCEILINGS; i++) - activeceilings[i] = NULL; - for (i = 0; i < MAXPLATS; i++) - activeplats[i] = NULL; - for (i = 0; i < MAXBUTTONS; i++) - memset(&buttonlist[i], 0, sizeof(button_t)); -} - -//---------------------------------------------------------------------------- -// -// PROC P_InitAmbientSound -// -//---------------------------------------------------------------------------- - -void P_InitAmbientSound(void) -{ - AmbSfxCount = 0; - AmbSfxVolume = 0; - AmbSfxTics = 10 * TICRATE; - AmbSfxPtr = AmbSndSeqInit; -} - -//---------------------------------------------------------------------------- -// -// PROC P_AddAmbientSfx -// -// Called by (P_mobj):P_SpawnMapThing during (P_setup):P_SetupLevel. -// -//---------------------------------------------------------------------------- - -void P_AddAmbientSfx(int sequence) -{ - if (AmbSfxCount == MAX_AMBIENT_SFX) - { - I_Error("Too many ambient sound sequences"); - } - LevelAmbientSfx[AmbSfxCount++] = AmbientSfx[sequence]; -} - -//---------------------------------------------------------------------------- -// -// PROC P_AmbientSound -// -// Called every tic by (P_tick):P_Ticker. -// -//---------------------------------------------------------------------------- - -void P_AmbientSound(void) -{ - afxcmd_t cmd; - int sound; - boolean done; - - if (!AmbSfxCount) - { // No ambient sound sequences on current level - return; - } - if (--AmbSfxTics) - { - return; - } - done = false; - do - { - cmd = *AmbSfxPtr++; - switch (cmd) - { - case afxcmd_play: - AmbSfxVolume = P_Random() >> 2; - S_StartSoundAtVolume(NULL, *AmbSfxPtr++, AmbSfxVolume); - break; - case afxcmd_playabsvol: - sound = *AmbSfxPtr++; - AmbSfxVolume = *AmbSfxPtr++; - S_StartSoundAtVolume(NULL, sound, AmbSfxVolume); - break; - case afxcmd_playrelvol: - sound = *AmbSfxPtr++; - AmbSfxVolume += *AmbSfxPtr++; - if (AmbSfxVolume < 0) - { - AmbSfxVolume = 0; - } - else if (AmbSfxVolume > 127) - { - AmbSfxVolume = 127; - } - S_StartSoundAtVolume(NULL, sound, AmbSfxVolume); - break; - case afxcmd_delay: - AmbSfxTics = *AmbSfxPtr++; - done = true; - break; - case afxcmd_delayrand: - AmbSfxTics = P_Random() & (*AmbSfxPtr++); - done = true; - break; - case afxcmd_end: - AmbSfxTics = 6 * TICRATE + P_Random(); - AmbSfxPtr = LevelAmbientSfx[P_Random() % AmbSfxCount]; - done = true; - break; - default: - I_Error("P_AmbientSound: Unknown afxcmd %d", cmd); - break; - } - } - while (done == false); -} diff --git a/games/NXDoom/src/heretic/p_spec.h b/games/NXDoom/src/heretic/p_spec.h deleted file mode 100644 index 7d78e4d2cf6..00000000000 --- a/games/NXDoom/src/heretic/p_spec.h +++ /dev/null @@ -1,390 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_spec.h - -/* -=============================================================================== - - P_SPEC - -=============================================================================== -*/ - -// -// Animating textures and planes -// -typedef struct -{ - boolean istexture; - int picnum; - int basepic; - int numpics; - int speed; -} anim_t; - -// -// source animation definition -// -typedef struct -{ - int istexture; // if false, it's a flat - char endname[9]; - char startname[9]; - int speed; -} animdef_t; - -#define MAXANIMS 32 - -extern anim_t anims[MAXANIMS], *lastanim; -extern int *TerrainTypes; - -// -// Animating line specials -// -#define MAXLINEANIMS 64 -extern short numlinespecials; -extern line_t *linespeciallist[MAXLINEANIMS]; - -// Define values for map objects -#define MO_TELEPORTMAN 14 - -// at game start -void P_InitPicAnims(void); -void P_InitTerrainTypes(void); -void P_InitLava(void); - -// at map load -void P_SpawnSpecials(void); -void P_InitAmbientSound(void); -void P_AddAmbientSfx(int sequence); - -// every tic -void P_UpdateSpecials(void); -void P_AmbientSound(void); - -// when needed -boolean P_UseSpecialLine(mobj_t * thing, line_t * line); -void P_ShootSpecialLine(mobj_t * thing, line_t * line); -void P_CrossSpecialLine(int linenum, int side, mobj_t * thing); - -void P_PlayerInSpecialSector(player_t * player); - -int twoSided(int sector, int line); -sector_t *getSector(int currentSector, int line, int side); -side_t *getSide(int currentSector, int line, int side); -fixed_t P_FindLowestFloorSurrounding(sector_t * sec); -fixed_t P_FindHighestFloorSurrounding(sector_t * sec); -fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight); -fixed_t P_FindLowestCeilingSurrounding(sector_t * sec); -fixed_t P_FindHighestCeilingSurrounding(sector_t * sec); -int P_FindSectorFromLineTag(line_t * line, int start); -int P_FindMinSurroundingLight(sector_t * sector, int max); -sector_t *getNextSector(line_t * line, sector_t * sec); - -// -// SPECIAL -// -int EV_DoDonut(line_t * line); - -/* -=============================================================================== - - P_LIGHTS - -=============================================================================== -*/ -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int count; - int maxlight; - int minlight; - int maxtime; - int mintime; -} lightflash_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int count; - int minlight; - int maxlight; - int darktime; - int brighttime; -} strobe_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int minlight; - int maxlight; - int direction; -} glow_t; - -#define GLOWSPEED 8 -#define STROBEBRIGHT 5 -#define FASTDARK 15 -#define SLOWDARK 35 - -void T_LightFlash(thinker_t *thinker); -void P_SpawnLightFlash(sector_t * sector); -void T_StrobeFlash(thinker_t *thinker); -void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync); -void EV_StartLightStrobing(line_t * line); -void EV_TurnTagLightsOff(line_t * line); -void EV_LightTurnOn(line_t * line, int bright); -void T_Glow(thinker_t *thinker); -void P_SpawnGlowingLight(sector_t * sector); - -/* -=============================================================================== - - P_SWITCH - -=============================================================================== -*/ -typedef struct -{ - char name1[9]; - char name2[9]; - short episode; -} switchlist_t; - -typedef enum -{ - top, - middle, - bottom -} bwhere_e; - -typedef struct -{ - line_t *line; - bwhere_e where; - int btexture; - int btimer; - void *soundorg; -} button_t; - -#define MAXSWITCHES 50 // max # of wall switches in a level -#define MAXBUTTONS 16 // 4 players, 4 buttons each at once, max. -#define BUTTONTIME 35 // 1 second - -extern button_t buttonlist[MAXBUTTONS]; - -void P_ChangeSwitchTexture(line_t * line, int useAgain); -void P_InitSwitchList(void); - -/* -=============================================================================== - - P_PLATS - -=============================================================================== -*/ -typedef enum -{ - up, - down, - waiting, - in_stasis -} plat_e; - -typedef enum -{ - perpetualRaise, - downWaitUpStay, - raiseAndChange, - raiseToNearestAndChange -} plattype_e; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - fixed_t speed; - fixed_t low; - fixed_t high; - int wait; - int count; - plat_e status; - plat_e oldstatus; - boolean crush; - int tag; - plattype_e type; -} plat_t; - -#define PLATWAIT 3 -#define PLATSPEED FRACUNIT -#define MAXPLATS 30 - -extern plat_t *activeplats[MAXPLATS]; - -void T_PlatRaise(thinker_t *thinker); -int EV_DoPlat(line_t * line, plattype_e type, int amount); -void P_AddActivePlat(plat_t * plat); -void P_RemoveActivePlat(plat_t * plat); -void EV_StopPlat(line_t * line); -void P_ActivateInStasis(int tag); - -/* -=============================================================================== - - P_DOORS - -=============================================================================== -*/ -typedef enum -{ - vld_normal, - vld_close30ThenOpen, - vld_close, - vld_open, - vld_raiseIn5Mins -} vldoor_e; - -typedef struct -{ - thinker_t thinker; - vldoor_e type; - sector_t *sector; - fixed_t topheight; - fixed_t speed; - int direction; // 1 = up, 0 = waiting at top, -1 = down - int topwait; // tics to wait at the top - // (keep in case a door going down is reset) - int topcountdown; // when it reaches 0, start going down -} vldoor_t; - -#define VDOORSPEED FRACUNIT*2 -#define VDOORWAIT 150 - -void EV_VerticalDoor(line_t * line, mobj_t * thing); -int EV_DoDoor(line_t * line, vldoor_e type, fixed_t speed); -void T_VerticalDoor(thinker_t *thinker); -void P_SpawnDoorCloseIn30(sector_t * sec); -void P_SpawnDoorRaiseIn5Mins(sector_t * sec, int secnum); - -/* -=============================================================================== - - P_CEILNG - -=============================================================================== -*/ -typedef enum -{ - lowerToFloor, - raiseToHighest, - lowerAndCrush, - crushAndRaise, - fastCrushAndRaise -} ceiling_e; - -typedef struct -{ - thinker_t thinker; - ceiling_e type; - sector_t *sector; - fixed_t bottomheight, topheight; - fixed_t speed; - boolean crush; - int direction; // 1 = up, 0 = waiting, -1 = down - int tag; // ID - int olddirection; -} ceiling_t; - -#define CEILSPEED FRACUNIT -#define CEILWAIT 150 -#define MAXCEILINGS 30 - -extern ceiling_t *activeceilings[MAXCEILINGS]; - -int EV_DoCeiling(line_t * line, ceiling_e type); -void T_MoveCeiling(thinker_t *thinker); -void P_AddActiveCeiling(ceiling_t * c); -void P_RemoveActiveCeiling(ceiling_t * c); -int EV_CeilingCrushStop(line_t * line); -void P_ActivateInStasisCeiling(line_t * line); - -/* -=============================================================================== - - P_FLOOR - -=============================================================================== -*/ -typedef enum -{ - lowerFloor, // lower floor to highest surrounding floor - lowerFloorToLowest, // lower floor to lowest surrounding floor - turboLower, // lower floor to highest surrounding floor VERY FAST - raiseFloor, // raise floor to lowest surrounding CEILING - raiseFloorToNearest, // raise floor to next highest surrounding floor - raiseToTexture, // raise floor to shortest height texture around it - lowerAndChange, // lower floor to lowest surrounding floor and change - // floorpic - raiseFloor24, - raiseFloor24AndChange, - raiseFloorCrush, - donutRaise, - raiseBuildStep // One step of a staircase -} floor_e; - -typedef struct -{ - thinker_t thinker; - floor_e type; - boolean crush; - sector_t *sector; - int direction; - int newspecial; - short texture; - fixed_t floordestheight; - fixed_t speed; -} floormove_t; - -#define FLOORSPEED FRACUNIT - -typedef enum -{ - ok, - crushed, - pastdest -} result_e; - -result_e T_MovePlane(sector_t * sector, fixed_t speed, - fixed_t dest, boolean crush, int floorOrCeiling, - int direction); - -int EV_BuildStairs(line_t * line, fixed_t stepDelta); -int EV_DoFloor(line_t * line, floor_e floortype); -void T_MoveFloor(thinker_t *thinker); - -/* -=============================================================================== - - P_TELEPT - -=============================================================================== -*/ - -boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle); -boolean EV_Teleport(line_t * line, int side, mobj_t * thing); diff --git a/games/NXDoom/src/heretic/p_switch.c b/games/NXDoom/src/heretic/p_switch.c deleted file mode 100644 index 885d67326db..00000000000 --- a/games/NXDoom/src/heretic/p_switch.c +++ /dev/null @@ -1,409 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include "doomdef.h" -#include "deh_str.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -//================================================================== -// -// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE -// -//================================================================== -switchlist_t alphSwitchList[] = { - {"SW1OFF", "SW1ON", 1}, - {"SW2OFF", "SW2ON", 1}, - -/* - {"SW1CTY", "SW2CTY", 1}, - {"SW1ORGRY", "SW2ORGRY", 1}, - {"SW1GRSTN", "SW2GRSTN", 1}, - {"SW1SNDP", "SW2SNDP", 1}, - {"SW1SPINE", "SW2SPINE", 1}, - {"SW1SQPEB", "SW2SQPEB", 1}, - {"SW1TRST1", "SW2TRST1", 1}, - {"SW1CSTL", "SW2CSTL", 1}, - {"SW1MOSS", "SW2MOSS", 1}, - {"SW1SNDSQ", "SW2SNDSQ", 1}, - {"SW1RED", "SW2RED", 1}, - {"SW1WOOD", "SW2WOOD", 1}, - {"SW1BROWN", "SW2BROWN", 1}, - - {"SW1TRST2", "SW2TRST2", 2}, - {"SW1MSC", "SW2MSC", 2}, - {"SW1MSC2", "SW2MSC2", 2}, - {"SW1GRDMD", "SW2GRDMD", 2}, -*/ - -#if 0 - {"SW1BRCOM", "SW2BRCOM", 1}, - {"SW1BRN1", "SW2BRN1", 1}, - {"SW1BRN2", "SW2BRN2", 1}, - {"SW1BRNGN", "SW2BRNGN", 1}, - {"SW1BROWN", "SW2BROWN", 1}, - {"SW1COMM", "SW2COMM", 1}, - {"SW1COMP", "SW2COMP", 1}, - {"SW1DIRT", "SW2DIRT", 1}, - {"SW1EXIT", "SW2EXIT", 1}, - {"SW1GRAY", "SW2GRAY", 1}, - {"SW1GRAY1", "SW2GRAY1", 1}, - {"SW1METAL", "SW2METAL", 1}, - {"SW1PIPE", "SW2PIPE", 1}, - {"SW1SLAD", "SW2SLAD", 1}, - {"SW1STARG", "SW2STARG", 1}, - {"SW1STON1", "SW2STON1", 1}, - {"SW1STON2", "SW2STON2", 1}, - {"SW1STONE", "SW2STONE", 1}, - {"SW1STRTN", "SW2STRTN", 1}, - - {"SW1BLUE", "SW2BLUE", 2}, - {"SW1CMT", "SW2CMT", 2}, - {"SW1GARG", "SW2GARG", 2}, - {"SW1GSTON", "SW2GSTON", 2}, - {"SW1HOT", "SW2HOT", 2}, - {"SW1LION", "SW2LION", 2}, - {"SW1SATYR", "SW2SATYR", 2}, - {"SW1SKIN", "SW2SKIN", 2}, - {"SW1VINE", "SW2VINE", 2}, - {"SW1WOOD", "SW2WOOD", 2}, -#endif -}; - -int switchlist[MAXSWITCHES * 2]; -int numswitches; -button_t buttonlist[MAXBUTTONS]; - -/* -=============== -= -= P_InitSwitchList -= -= Only called at game initialization -= -=============== -*/ - -void P_InitSwitchList(void) -{ - int i, slindex, episode; - - // Note that this is called "episode" here but it's actually something - // quite different. As we progress from Shareware->Registered->Doom II - // we support more switch textures. - if (gamemode == shareware) - { - episode = 1; - } - else - { - episode = 2; - } - - slindex = 0; - - for (i = 0; i < arrlen(alphSwitchList); i++) - { - if (alphSwitchList[i].episode <= episode) - { - switchlist[slindex++] = - R_TextureNumForName(DEH_String(alphSwitchList[i].name1)); - switchlist[slindex++] = - R_TextureNumForName(DEH_String(alphSwitchList[i].name2)); - } - } - - numswitches = slindex / 2; - switchlist[slindex] = -1; -} - -//================================================================== -// -// Start a button counting down till it turns off. -// -//================================================================== -void P_StartButton(line_t * line, bwhere_e w, int texture, int time) -{ - int i; - - for (i = 0; i < MAXBUTTONS; i++) - if (!buttonlist[i].btimer) - { - buttonlist[i].line = line; - buttonlist[i].where = w; - buttonlist[i].btexture = texture; - buttonlist[i].btimer = time; - buttonlist[i].soundorg = &line->frontsector->soundorg; - return; - } - - I_Error("P_StartButton: no button slots left!"); -} - -//================================================================== -// -// Function that changes wall texture. -// Tell it if switch is ok to use again (1=yes, it's a button). -// -//================================================================== -void P_ChangeSwitchTexture(line_t * line, int useAgain) -{ - int texTop; - int texMid; - int texBot; - int i; - int sound; - - if (!useAgain) - line->special = 0; - - texTop = sides[line->sidenum[0]].toptexture; - texMid = sides[line->sidenum[0]].midtexture; - texBot = sides[line->sidenum[0]].bottomtexture; - - sound = sfx_switch; - //if (line->special == 11) // EXIT SWITCH? - // sound = sfx_swtchx; - - for (i = 0; i < numswitches * 2; i++) - if (switchlist[i] == texTop) - { - S_StartSound(buttonlist->soundorg, sound); - sides[line->sidenum[0]].toptexture = switchlist[i ^ 1]; - if (useAgain) - P_StartButton(line, top, switchlist[i], BUTTONTIME); - return; - } - else if (switchlist[i] == texMid) - { - S_StartSound(buttonlist->soundorg, sound); - sides[line->sidenum[0]].midtexture = switchlist[i ^ 1]; - if (useAgain) - P_StartButton(line, middle, switchlist[i], BUTTONTIME); - return; - } - else if (switchlist[i] == texBot) - { - S_StartSound(buttonlist->soundorg, sound); - sides[line->sidenum[0]].bottomtexture = switchlist[i ^ 1]; - if (useAgain) - P_StartButton(line, bottom, switchlist[i], BUTTONTIME); - return; - } -} - -/* -============================================================================== -= -= P_UseSpecialLine -= -= Called when a thing uses a special line -= Only the front sides of lines are usable -=============================================================================== -*/ - -boolean P_UseSpecialLine(mobj_t * thing, line_t * line) -{ - // - // Switches that other things can activate - // - if (!thing->player) - { - if (line->flags & ML_SECRET) - return false; // never open secret doors - switch (line->special) - { - case 1: // MANUAL DOOR RAISE - case 32: // MANUAL BLUE - case 33: // MANUAL RED - case 34: // MANUAL YELLOW - break; - default: - return false; - } - } - - // - // do something - // - switch (line->special) - { - //=============================================== - // MANUALS - //=============================================== - case 1: // Vertical Door - case 26: // Blue Door/Locked - case 27: // Yellow Door /Locked - case 28: // Red Door /Locked - - case 31: // Manual door open - case 32: // Blue locked door open - case 33: // Red locked door open - case 34: // Yellow locked door open - EV_VerticalDoor(line, thing); - break; - //=============================================== - // SWITCHES - //=============================================== - case 7: // Switch_Build_Stairs (8 pixel steps) - if (EV_BuildStairs(line, 8 * FRACUNIT)) - { - P_ChangeSwitchTexture(line, 0); - } - break; - case 107: // Switch_Build_Stairs_16 (16 pixel steps) - if (EV_BuildStairs(line, 16 * FRACUNIT)) - { - P_ChangeSwitchTexture(line, 0); - } - break; - case 9: // Change Donut - if (EV_DoDonut(line)) - P_ChangeSwitchTexture(line, 0); - break; - case 11: // Exit level - G_ExitLevel(); - P_ChangeSwitchTexture(line, 0); - break; - case 14: // Raise Floor 32 and change texture - if (EV_DoPlat(line, raiseAndChange, 32)) - P_ChangeSwitchTexture(line, 0); - break; - case 15: // Raise Floor 24 and change texture - if (EV_DoPlat(line, raiseAndChange, 24)) - P_ChangeSwitchTexture(line, 0); - break; - case 18: // Raise Floor to next highest floor - if (EV_DoFloor(line, raiseFloorToNearest)) - P_ChangeSwitchTexture(line, 0); - break; - case 20: // Raise Plat next highest floor and change texture - if (EV_DoPlat(line, raiseToNearestAndChange, 0)) - P_ChangeSwitchTexture(line, 0); - break; - case 21: // PlatDownWaitUpStay - if (EV_DoPlat(line, downWaitUpStay, 0)) - P_ChangeSwitchTexture(line, 0); - break; - case 23: // Lower Floor to Lowest - if (EV_DoFloor(line, lowerFloorToLowest)) - P_ChangeSwitchTexture(line, 0); - break; - case 29: // Raise Door - if (EV_DoDoor(line, vld_normal, VDOORSPEED)) - P_ChangeSwitchTexture(line, 0); - break; - case 41: // Lower Ceiling to Floor - if (EV_DoCeiling(line, lowerToFloor)) - P_ChangeSwitchTexture(line, 0); - break; - case 71: // Turbo Lower Floor - if (EV_DoFloor(line, turboLower)) - P_ChangeSwitchTexture(line, 0); - break; - case 49: // Lower Ceiling And Crush - if (EV_DoCeiling(line, lowerAndCrush)) - P_ChangeSwitchTexture(line, 0); - break; - case 50: // Close Door - if (EV_DoDoor(line, vld_close, VDOORSPEED)) - P_ChangeSwitchTexture(line, 0); - break; - case 51: // Secret EXIT - G_SecretExitLevel(); - P_ChangeSwitchTexture(line, 0); - break; - case 55: // Raise Floor Crush - if (EV_DoFloor(line, raiseFloorCrush)) - P_ChangeSwitchTexture(line, 0); - break; - case 101: // Raise Floor - if (EV_DoFloor(line, raiseFloor)) - P_ChangeSwitchTexture(line, 0); - break; - case 102: // Lower Floor to Surrounding floor height - if (EV_DoFloor(line, lowerFloor)) - P_ChangeSwitchTexture(line, 0); - break; - case 103: // Open Door - if (EV_DoDoor(line, vld_open, VDOORSPEED)) - P_ChangeSwitchTexture(line, 0); - break; - //=============================================== - // BUTTONS - //=============================================== - case 42: // Close Door - if (EV_DoDoor(line, vld_close, VDOORSPEED)) - P_ChangeSwitchTexture(line, 1); - break; - case 43: // Lower Ceiling to Floor - if (EV_DoCeiling(line, lowerToFloor)) - P_ChangeSwitchTexture(line, 1); - break; - case 45: // Lower Floor to Surrounding floor height - if (EV_DoFloor(line, lowerFloor)) - P_ChangeSwitchTexture(line, 1); - break; - case 60: // Lower Floor to Lowest - if (EV_DoFloor(line, lowerFloorToLowest)) - P_ChangeSwitchTexture(line, 1); - break; - case 61: // Open Door - if (EV_DoDoor(line, vld_open, VDOORSPEED)) - P_ChangeSwitchTexture(line, 1); - break; - case 62: // PlatDownWaitUpStay - if (EV_DoPlat(line, downWaitUpStay, 1)) - P_ChangeSwitchTexture(line, 1); - break; - case 63: // Raise Door - if (EV_DoDoor(line, vld_normal, VDOORSPEED)) - P_ChangeSwitchTexture(line, 1); - break; - case 64: // Raise Floor to ceiling - if (EV_DoFloor(line, raiseFloor)) - P_ChangeSwitchTexture(line, 1); - break; - case 66: // Raise Floor 24 and change texture - if (EV_DoPlat(line, raiseAndChange, 24)) - P_ChangeSwitchTexture(line, 1); - break; - case 67: // Raise Floor 32 and change texture - if (EV_DoPlat(line, raiseAndChange, 32)) - P_ChangeSwitchTexture(line, 1); - break; - case 65: // Raise Floor Crush - if (EV_DoFloor(line, raiseFloorCrush)) - P_ChangeSwitchTexture(line, 1); - break; - case 68: // Raise Plat to next highest floor and change texture - if (EV_DoPlat(line, raiseToNearestAndChange, 0)) - P_ChangeSwitchTexture(line, 1); - break; - case 69: // Raise Floor to next highest floor - if (EV_DoFloor(line, raiseFloorToNearest)) - P_ChangeSwitchTexture(line, 1); - break; - case 70: // Turbo Lower Floor - if (EV_DoFloor(line, turboLower)) - P_ChangeSwitchTexture(line, 1); - break; - } - - return true; -} diff --git a/games/NXDoom/src/heretic/p_telept.c b/games/NXDoom/src/heretic/p_telept.c deleted file mode 100644 index a922f7cf871..00000000000 --- a/games/NXDoom/src/heretic/p_telept.c +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_telept.c - -#include "doomdef.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" - -//---------------------------------------------------------------------------- -// -// FUNC P_Teleport -// -//---------------------------------------------------------------------------- - -boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle) -{ - fixed_t oldx; - fixed_t oldy; - fixed_t oldz; - fixed_t aboveFloor; - fixed_t fogDelta; - player_t *player; - unsigned an; - mobj_t *fog; - - oldx = thing->x; - oldy = thing->y; - oldz = thing->z; - aboveFloor = thing->z - thing->floorz; - if (!P_TeleportMove(thing, x, y)) - { - return (false); - } - if (thing->player) - { - player = thing->player; - if (player->powers[pw_flight] && aboveFloor) - { - thing->z = thing->floorz + aboveFloor; - if (thing->z + thing->height > thing->ceilingz) - { - thing->z = thing->ceilingz - thing->height; - } - player->viewz = thing->z + player->viewheight; - } - else - { - thing->z = thing->floorz; - player->viewz = thing->z + player->viewheight; - player->lookdir = 0; - } - } - else if (thing->flags & MF_MISSILE) - { - thing->z = thing->floorz + aboveFloor; - if (thing->z + thing->height > thing->ceilingz) - { - thing->z = thing->ceilingz - thing->height; - } - } - else - { - thing->z = thing->floorz; - } - // Spawn teleport fog at source and destination - fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; - fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG); - S_StartSound(fog, sfx_telept); - an = angle >> ANGLETOFINESHIFT; - fog = P_SpawnMobj(x + 20 * finecosine[an], - y + 20 * finesine[an], thing->z + fogDelta, MT_TFOG); - S_StartSound(fog, sfx_telept); - if (thing->player && !thing->player->powers[pw_weaponlevel2]) - { // Freeze player for about .5 sec - thing->reactiontime = 18; - } - thing->angle = angle; - if (thing->flags2 & MF2_FOOTCLIP - && P_GetThingFloorType(thing) != FLOOR_SOLID) - { - thing->flags2 |= MF2_FEETARECLIPPED; - } - else if (thing->flags2 & MF2_FEETARECLIPPED) - { - thing->flags2 &= ~MF2_FEETARECLIPPED; - } - if (thing->flags & MF_MISSILE) - { - angle >>= ANGLETOFINESHIFT; - thing->momx = FixedMul(thing->info->speed, finecosine[angle]); - thing->momy = FixedMul(thing->info->speed, finesine[angle]); - } - else - { - thing->momx = thing->momy = thing->momz = 0; - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC EV_Teleport -// -//---------------------------------------------------------------------------- - -boolean EV_Teleport(line_t * line, int side, mobj_t * thing) -{ - int i; - int tag; - mobj_t *m; - thinker_t *thinker; - sector_t *sector; - - if (thing->flags2 & MF2_NOTELEPORT) - { - return (false); - } - if (side == 1) - { // Don't teleport when crossing back side - return (false); - } - tag = line->tag; - for (i = 0; i < numsectors; i++) - { - if (sectors[i].tag == tag) - { - for (thinker = thinkercap.next; thinker != &thinkercap; - thinker = thinker->next) - { - if (thinker->function != P_MobjThinker) - { // Not a mobj - continue; - } - m = (mobj_t *) thinker; - if (m->type != MT_TELEPORTMAN) - { // Not a teleportman - continue; - } - sector = m->subsector->sector; - if (sector - sectors != i) - { // Wrong sector - continue; - } - return (P_Teleport(thing, m->x, m->y, m->angle)); - } - } - } - return (false); -} diff --git a/games/NXDoom/src/heretic/p_tick.c b/games/NXDoom/src/heretic/p_tick.c deleted file mode 100644 index ac1c9429966..00000000000 --- a/games/NXDoom/src/heretic/p_tick.c +++ /dev/null @@ -1,167 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_tick.c - -#include "doomdef.h" -#include "i_system.h" -#include "p_local.h" -#include "v_video.h" - -int leveltime; -int TimerGame; - -/* -=============================================================================== - - THINKERS - -All thinkers should be allocated by Z_Malloc so they can be operated on uniformly. The actual -structures will vary in size, but the first element must be thinker_t. - -=============================================================================== -*/ - -thinker_t thinkercap; // both the head and tail of the thinker list - -/* -=============== -= -= P_InitThinkers -= -=============== -*/ - -void P_InitThinkers(void) -{ - thinkercap.prev = thinkercap.next = &thinkercap; -} - - -/* -=============== -= -= P_AddThinker -= -= Adds a new thinker at the end of the list -= -=============== -*/ - -void P_AddThinker(thinker_t * thinker) -{ - thinkercap.prev->next = thinker; - thinker->next = &thinkercap; - thinker->prev = thinkercap.prev; - thinkercap.prev = thinker; -} - -/* -=============== -= -= P_RemoveThinker -= -= Deallocation is lazy -- it will not actually be freed until its -= thinking turn comes up -= -=============== -*/ - -void P_RemoveThinker(thinker_t * thinker) -{ - thinker->function = (think_t) - 1; -} - -/* -=============== -= -= P_AllocateThinker -= -= Allocates memory and adds a new thinker at the end of the list -= -=============== -*/ - -void P_AllocateThinker(thinker_t * thinker) -{ -} - - -/* -=============== -= -= P_RunThinkers -= -=============== -*/ - -void P_RunThinkers(void) -{ - thinker_t *currentthinker, *nextthinker; - - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) - { - if (currentthinker->function == (think_t) - 1) - { // time to remove it - nextthinker = currentthinker->next; - currentthinker->next->prev = currentthinker->prev; - currentthinker->prev->next = currentthinker->next; - Z_Free(currentthinker); - } - else - { - if (currentthinker->function) - currentthinker->function(currentthinker); - nextthinker = currentthinker->next; - } - currentthinker = nextthinker; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_Ticker -// -//---------------------------------------------------------------------------- - -void P_Ticker(void) -{ - int i; - - if (paused) - { - return; - } - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - P_PlayerThink(&players[i]); - } - } - if (TimerGame) - { - if (!--TimerGame) - { - G_ExitLevel(); - } - } - P_RunThinkers(); - P_UpdateSpecials(); - P_AmbientSound(); - leveltime++; -} diff --git a/games/NXDoom/src/heretic/p_user.c b/games/NXDoom/src/heretic/p_user.c deleted file mode 100644 index b24029ca707..00000000000 --- a/games/NXDoom/src/heretic/p_user.c +++ /dev/null @@ -1,1017 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// P_user.c - -#include - -#include "doomdef.h" -#include "deh_str.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" - -void P_PlayerNextArtifact(player_t * player); - -// Macros - -#define MAXBOB 0x100000 // 16 pixels of bob - -// Data - -boolean onground; -int newtorch; // used in the torch flicker effect. -int newtorchdelta; - -boolean WeaponInShareware[] = { - true, // Staff - true, // Gold wand - true, // Crossbow - true, // Blaster - false, // Skull rod - false, // Phoenix rod - false, // Mace - true, // Gauntlets - true // Beak -}; - -/* -================== -= -= P_Thrust -= -= moves the given origin along a given angle -= -================== -*/ - -void P_Thrust(player_t * player, angle_t angle, fixed_t move) -{ - angle >>= ANGLETOFINESHIFT; - if (player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz)) - { - player->mo->momx += FixedMul(move, finecosine[angle]); - player->mo->momy += FixedMul(move, finesine[angle]); - } - else if (player->mo->subsector->sector->special == 15) // Friction_Low - { - player->mo->momx += FixedMul(move >> 2, finecosine[angle]); - player->mo->momy += FixedMul(move >> 2, finesine[angle]); - } - else - { - player->mo->momx += FixedMul(move, finecosine[angle]); - player->mo->momy += FixedMul(move, finesine[angle]); - } -} - - -/* -================== -= -= P_CalcHeight -= -=Calculate the walking / running height adjustment -= -================== -*/ - -void P_CalcHeight(player_t * player) -{ - int angle; - fixed_t bob; - -// -// regular movement bobbing (needs to be calculated for gun swing even -// if not on ground) -// OPTIMIZE: tablify angle - - player->bob = FixedMul(player->mo->momx, player->mo->momx) + - FixedMul(player->mo->momy, player->mo->momy); - player->bob >>= 2; - if (player->bob > MAXBOB) - player->bob = MAXBOB; - if (player->mo->flags2 & MF2_FLY && !onground) - { - player->bob = FRACUNIT / 2; - } - - if ((player->cheats & CF_NOMOMENTUM)) - { - player->viewz = player->mo->z + VIEWHEIGHT; - if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) - player->viewz = player->mo->ceilingz - 4 * FRACUNIT; - player->viewz = player->mo->z + player->viewheight; - return; - } - - angle = (FINEANGLES / 20 * leveltime) & FINEMASK; - bob = FixedMul(player->bob / 2, finesine[angle]); - -// -// move viewheight -// - if (player->playerstate == PST_LIVE) - { - player->viewheight += player->deltaviewheight; - if (player->viewheight > VIEWHEIGHT) - { - player->viewheight = VIEWHEIGHT; - player->deltaviewheight = 0; - } - if (player->viewheight < VIEWHEIGHT / 2) - { - player->viewheight = VIEWHEIGHT / 2; - if (player->deltaviewheight <= 0) - player->deltaviewheight = 1; - } - - if (player->deltaviewheight) - { - player->deltaviewheight += FRACUNIT / 4; - if (!player->deltaviewheight) - player->deltaviewheight = 1; - } - } - - if (player->chickenTics) - { - player->viewz = player->mo->z + player->viewheight - (20 * FRACUNIT); - } - else - { - player->viewz = player->mo->z + player->viewheight + bob; - } - if (player->mo->flags2 & MF2_FEETARECLIPPED - && player->playerstate != PST_DEAD - && player->mo->z <= player->mo->floorz) - { - player->viewz -= FOOTCLIPSIZE; - } - if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) - { - player->viewz = player->mo->ceilingz - 4 * FRACUNIT; - } - if (player->viewz < player->mo->floorz + 4 * FRACUNIT) - { - player->viewz = player->mo->floorz + 4 * FRACUNIT; - } -} - -/* -================= -= -= P_MovePlayer -= -================= -*/ - -void P_MovePlayer(player_t * player) -{ - int look; - int fly; - ticcmd_t *cmd; - - cmd = &player->cmd; - player->mo->angle += (cmd->angleturn << 16); - - onground = (player->mo->z <= player->mo->floorz - || (player->mo->flags2 & MF2_ONMOBJ)); - - if (player->chickenTics) - { // Chicken speed - if (cmd->forwardmove && (onground || player->mo->flags2 & MF2_FLY)) - P_Thrust(player, player->mo->angle, cmd->forwardmove * 2500); - if (cmd->sidemove && (onground || player->mo->flags2 & MF2_FLY)) - P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2500); - } - else - { // Normal speed - if (cmd->forwardmove && (onground || player->mo->flags2 & MF2_FLY)) - P_Thrust(player, player->mo->angle, cmd->forwardmove * 2048); - if (cmd->sidemove && (onground || player->mo->flags2 & MF2_FLY)) - P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2048); - } - - if (cmd->forwardmove || cmd->sidemove) - { - if (player->chickenTics) - { - if (player->mo->state == &states[S_CHICPLAY]) - { - P_SetMobjState(player->mo, S_CHICPLAY_RUN1); - } - } - else - { - if (player->mo->state == &states[S_PLAY]) - { - P_SetMobjState(player->mo, S_PLAY_RUN1); - } - } - } - - look = cmd->lookfly & 15; - if (look > 7) - { - look -= 16; - } - if (look) - { - if (look == TOCENTER) - { - player->centering = true; - } - else - { - player->lookdir += 5 * look; - if (player->lookdir > 90 || player->lookdir < -110) - { - player->lookdir -= 5 * look; - } - } - } - if (player->centering) - { - if (player->lookdir > 0) - { - player->lookdir -= 8; - } - else if (player->lookdir < 0) - { - player->lookdir += 8; - } - if (abs(player->lookdir) < 8) - { - player->lookdir = 0; - player->centering = false; - } - } - fly = cmd->lookfly >> 4; - if (fly > 7) - { - fly -= 16; - } - if (fly && player->powers[pw_flight]) - { - if (fly != TOCENTER) - { - player->flyheight = fly * 2; - if (!(player->mo->flags2 & MF2_FLY)) - { - player->mo->flags2 |= MF2_FLY; - player->mo->flags |= MF_NOGRAVITY; - } - } - else - { - player->mo->flags2 &= ~MF2_FLY; - player->mo->flags &= ~MF_NOGRAVITY; - } - } - else if (fly > 0) - { - P_PlayerUseArtifact(player, arti_fly); - } - if (player->mo->flags2 & MF2_FLY) - { - player->mo->momz = player->flyheight * FRACUNIT; - if (player->flyheight) - { - player->flyheight /= 2; - } - } -} - -/* -================= -= -= P_DeathThink -= -================= -*/ - -#define ANG5 (ANG90/18) - -void P_DeathThink(player_t * player) -{ - angle_t angle, delta; - int lookDelta; - - P_MovePsprites(player); - - onground = (player->mo->z <= player->mo->floorz); - if (player->mo->type == MT_BLOODYSKULL) - { // Flying bloody skull - player->viewheight = 6 * FRACUNIT; - player->deltaviewheight = 0; - //player->damagecount = 20; - if (onground) - { - if (player->lookdir < 60) - { - lookDelta = (60 - player->lookdir) / 8; - if (lookDelta < 1 && (leveltime & 1)) - { - lookDelta = 1; - } - else if (lookDelta > 6) - { - lookDelta = 6; - } - player->lookdir += lookDelta; - } - } - } - else - { // Fall to ground - player->deltaviewheight = 0; - if (player->viewheight > 6 * FRACUNIT) - player->viewheight -= FRACUNIT; - if (player->viewheight < 6 * FRACUNIT) - player->viewheight = 6 * FRACUNIT; - if (player->lookdir > 0) - { - player->lookdir -= 6; - } - else if (player->lookdir < 0) - { - player->lookdir += 6; - } - if (abs(player->lookdir) < 6) - { - player->lookdir = 0; - } - } - P_CalcHeight(player); - - if (player->attacker && player->attacker != player->mo) - { - angle = R_PointToAngle2(player->mo->x, player->mo->y, - player->attacker->x, player->attacker->y); - delta = angle - player->mo->angle; - if (delta < ANG5 || delta > (unsigned) -ANG5) - { // Looking at killer, so fade damage flash down - player->mo->angle = angle; - if (player->damagecount) - { - player->damagecount--; - } - } - else if (delta < ANG180) - player->mo->angle += ANG5; - else - player->mo->angle -= ANG5; - } - else if (player->damagecount) - { - player->damagecount--; - } - - if (player->cmd.buttons & BT_USE) - { - if (player == &players[consoleplayer]) - { - I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE)); - inv_ptr = 0; - curpos = 0; - newtorch = 0; - newtorchdelta = 0; - } - player->playerstate = PST_REBORN; - // Let the mobj know the player has entered the reborn state. Some - // mobjs need to know when it's ok to remove themselves. - player->mo->special2.i = 666; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_ChickenPlayerThink -// -//---------------------------------------------------------------------------- - -void P_ChickenPlayerThink(player_t * player) -{ - mobj_t *pmo; - - if (player->health > 0) - { // Handle beak movement - P_UpdateBeak(player, &player->psprites[ps_weapon]); - } - if (player->chickenTics & 15) - { - return; - } - pmo = player->mo; - if (!(pmo->momx + pmo->momy) && P_Random() < 160) - { // Twitch view angle - pmo->angle += P_SubRandom() << 19; - } - if ((pmo->z <= pmo->floorz) && (P_Random() < 32)) - { // Jump and noise - pmo->momz += FRACUNIT; - P_SetMobjState(pmo, S_CHICPLAY_PAIN); - return; - } - if (P_Random() < 48) - { // Just noise - S_StartSound(pmo, sfx_chicact); - } -} - -//---------------------------------------------------------------------------- -// -// FUNC P_GetPlayerNum -// -//---------------------------------------------------------------------------- - -int P_GetPlayerNum(player_t * player) -{ - int i; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (player == &players[i]) - { - return (i); - } - } - return (0); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_UndoPlayerChicken -// -//---------------------------------------------------------------------------- - -boolean P_UndoPlayerChicken(player_t * player) -{ - mobj_t *fog; - mobj_t *mo; - mobj_t *pmo; - fixed_t x; - fixed_t y; - fixed_t z; - angle_t angle; - int playerNum; - weapontype_t weapon; - int oldFlags; - int oldFlags2; - - pmo = player->mo; - x = pmo->x; - y = pmo->y; - z = pmo->z; - angle = pmo->angle; - weapon = pmo->special1.i; - oldFlags = pmo->flags; - oldFlags2 = pmo->flags2; - P_SetMobjState(pmo, S_FREETARGMOBJ); - mo = P_SpawnMobj(x, y, z, MT_PLAYER); - if (P_TestMobjLocation(mo) == false) - { // Didn't fit - P_RemoveMobj(mo); - mo = P_SpawnMobj(x, y, z, MT_CHICPLAYER); - mo->angle = angle; - mo->health = player->health; - mo->special1.i = weapon; - mo->player = player; - mo->flags = oldFlags; - mo->flags2 = oldFlags2; - player->mo = mo; - player->chickenTics = 2 * 35; - return (false); - } - playerNum = P_GetPlayerNum(player); - if (playerNum != 0) - { // Set color translation - mo->flags |= playerNum << MF_TRANSSHIFT; - } - mo->angle = angle; - mo->player = player; - mo->reactiontime = 18; - if (oldFlags2 & MF2_FLY) - { - mo->flags2 |= MF2_FLY; - mo->flags |= MF_NOGRAVITY; - } - player->chickenTics = 0; - player->powers[pw_weaponlevel2] = 0; - player->health = mo->health = MAXHEALTH; - player->mo = mo; - angle >>= ANGLETOFINESHIFT; - fog = P_SpawnMobj(x + 20 * finecosine[angle], - y + 20 * finesine[angle], z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, sfx_telept); - P_PostChickenWeapon(player, weapon); - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerThink -// -//---------------------------------------------------------------------------- - -void P_PlayerThink(player_t * player) -{ - ticcmd_t *cmd; - weapontype_t newweapon; - - // No-clip cheat - if (player->cheats & CF_NOCLIP) - { - player->mo->flags |= MF_NOCLIP; - } - else - { - player->mo->flags &= ~MF_NOCLIP; - } - cmd = &player->cmd; - if (player->mo->flags & MF_JUSTATTACKED) - { // Gauntlets attack auto forward motion - cmd->angleturn = 0; - cmd->forwardmove = 0xc800 / 512; - cmd->sidemove = 0; - player->mo->flags &= ~MF_JUSTATTACKED; - } -// messageTics is above the rest of the counters so that messages will -// go away, even in death. - player->messageTics--; // Can go negative - if (!player->messageTics) - { // Refresh the screen when a message goes away - ultimatemsg = false; // clear out any chat messages. - BorderTopRefresh = true; - } - if (player->playerstate == PST_DEAD) - { - P_DeathThink(player); - return; - } - if (player->chickenTics) - { - P_ChickenPlayerThink(player); - } - // Handle movement - if (player->mo->reactiontime) - { // Player is frozen - player->mo->reactiontime--; - } - else - { - P_MovePlayer(player); - } - P_CalcHeight(player); - if (player->mo->subsector->sector->special) - { - P_PlayerInSpecialSector(player); - } - if (cmd->arti) - { // Use an artifact - if (cmd->arti == 0xff) - { - P_PlayerNextArtifact(player); - } - else - { - P_PlayerUseArtifact(player, cmd->arti); - } - } - // Check for weapon change - if (cmd->buttons & BT_SPECIAL) - { // A special event has no other buttons - cmd->buttons = 0; - } - if (cmd->buttons & BT_CHANGE) - { - // The actual changing of the weapon is done when the weapon - // psprite can do it (A_WeaponReady), so it doesn't happen in - // the middle of an attack. - newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; - if (newweapon == wp_staff && player->weaponowned[wp_gauntlets] - && !(player->readyweapon == wp_gauntlets)) - { - newweapon = wp_gauntlets; - } - if (player->weaponowned[newweapon] - && newweapon != player->readyweapon) - { - if (WeaponInShareware[newweapon] || gamemode != shareware) - { - player->pendingweapon = newweapon; - } - } - } - // Check for use - if (cmd->buttons & BT_USE) - { - if (!player->usedown) - { - P_UseLines(player); - player->usedown = true; - } - } - else - { - player->usedown = false; - } - // Chicken counter - if (player->chickenTics) - { - if (player->chickenPeck) - { // Chicken attack counter - player->chickenPeck -= 3; - } - if (!--player->chickenTics) - { // Attempt to undo the chicken - P_UndoPlayerChicken(player); - } - } - // Cycle psprites - P_MovePsprites(player); - // Other Counters - if (player->powers[pw_invulnerability]) - { - player->powers[pw_invulnerability]--; - } - if (player->powers[pw_invisibility]) - { - if (!--player->powers[pw_invisibility]) - { - player->mo->flags &= ~MF_SHADOW; - } - } - if (player->powers[pw_infrared]) - { - player->powers[pw_infrared]--; - } - if (player->powers[pw_flight]) - { - if (!--player->powers[pw_flight]) - { - // haleyjd: removed externdriver crap - if (player->mo->z != player->mo->floorz) - { - player->centering = true; - } - - player->mo->flags2 &= ~MF2_FLY; - player->mo->flags &= ~MF_NOGRAVITY; - BorderTopRefresh = true; //make sure the sprite's cleared out - } - } - if (player->powers[pw_weaponlevel2]) - { - if (!--player->powers[pw_weaponlevel2]) - { - if ((player->readyweapon == wp_phoenixrod) - && (player->psprites[ps_weapon].state - != &states[S_PHOENIXREADY]) - && (player->psprites[ps_weapon].state - != &states[S_PHOENIXUP])) - { - P_SetPsprite(player, ps_weapon, S_PHOENIXREADY); - player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2; - player->refire = 0; - } - else if ((player->readyweapon == wp_gauntlets) - || (player->readyweapon == wp_staff)) - { - player->pendingweapon = player->readyweapon; - } - BorderTopRefresh = true; - } - } - if (player->damagecount) - { - player->damagecount--; - } - if (player->bonuscount) - { - player->bonuscount--; - } - // Colormaps - if (player->powers[pw_invulnerability]) - { - if (player->powers[pw_invulnerability] > BLINKTHRESHOLD - || (player->powers[pw_invulnerability] & 8)) - { - player->fixedcolormap = INVERSECOLORMAP; - } - else - { - player->fixedcolormap = 0; - } - } - else if (player->powers[pw_infrared]) - { - if (player->powers[pw_infrared] <= BLINKTHRESHOLD) - { - if (player->powers[pw_infrared] & 8) - { - player->fixedcolormap = 0; - } - else - { - player->fixedcolormap = 1; - } - } - else if (!(leveltime & 16) && player == &players[consoleplayer]) - { - if (newtorch) - { - if (player->fixedcolormap + newtorchdelta > 7 - || player->fixedcolormap + newtorchdelta < 1 - || newtorch == player->fixedcolormap) - { - newtorch = 0; - } - else - { - player->fixedcolormap += newtorchdelta; - } - } - else - { - newtorch = (M_Random() & 7) + 1; - newtorchdelta = (newtorch == player->fixedcolormap) ? - 0 : ((newtorch > player->fixedcolormap) ? 1 : -1); - } - } - } - else - { - player->fixedcolormap = 0; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_ArtiTele -// -//---------------------------------------------------------------------------- - -void P_ArtiTele(player_t * player) -{ - int i; - int selections; - fixed_t destX; - fixed_t destY; - angle_t destAngle; - - if (deathmatch) - { - selections = deathmatch_p - deathmatchstarts; - i = P_Random() % selections; - destX = deathmatchstarts[i].x << FRACBITS; - destY = deathmatchstarts[i].y << FRACBITS; - destAngle = ANG45 * (deathmatchstarts[i].angle / 45); - } - else - { - destX = playerstarts[0].x << FRACBITS; - destY = playerstarts[0].y << FRACBITS; - destAngle = ANG45 * (playerstarts[0].angle / 45); - } - P_Teleport(player->mo, destX, destY, destAngle); - S_StartSound(NULL, sfx_wpnup); // Full volume laugh -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerNextArtifact -// -//---------------------------------------------------------------------------- - -void P_PlayerNextArtifact(player_t * player) -{ - if (player == &players[consoleplayer]) - { - inv_ptr--; - if (inv_ptr < 6) - { - curpos--; - if (curpos < 0) - { - curpos = 0; - } - } - if (inv_ptr < 0) - { - inv_ptr = player->inventorySlotNum - 1; - if (inv_ptr < 6) - { - curpos = inv_ptr; - } - else - { - curpos = 6; - } - } - player->readyArtifact = player->inventory[inv_ptr].type; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerRemoveArtifact -// -//---------------------------------------------------------------------------- - -void P_PlayerRemoveArtifact(player_t * player, int slot) -{ - int i; - player->artifactCount--; - if (!(--player->inventory[slot].count)) - { // Used last of a type - compact the artifact list - player->readyArtifact = arti_none; - player->inventory[slot].type = arti_none; - for (i = slot + 1; i < player->inventorySlotNum; i++) - { - player->inventory[i - 1] = player->inventory[i]; - } - player->inventorySlotNum--; - if (player == &players[consoleplayer]) - { // Set position markers and get next readyArtifact - inv_ptr--; - if (inv_ptr < 6) - { - curpos--; - if (curpos < 0) - { - curpos = 0; - } - } - if (inv_ptr >= player->inventorySlotNum) - { - inv_ptr = player->inventorySlotNum - 1; - } - if (inv_ptr < 0) - { - inv_ptr = 0; - } - player->readyArtifact = player->inventory[inv_ptr].type; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerUseArtifact -// -//---------------------------------------------------------------------------- - -void P_PlayerUseArtifact(player_t * player, artitype_t arti) -{ - int i; - - for (i = 0; i < player->inventorySlotNum; i++) - { - if (player->inventory[i].type == arti) - { // Found match - try to use - if (P_UseArtifact(player, arti)) - { // Artifact was used - remove it from inventory - P_PlayerRemoveArtifact(player, i); - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, sfx_artiuse); - ArtifactFlash = 4; - } - } - else - { // Unable to use artifact, advance pointer - P_PlayerNextArtifact(player); - } - break; - } - } -} - -//---------------------------------------------------------------------------- -// -// FUNC P_UseArtifact -// -// Returns true if artifact was used. -// -//---------------------------------------------------------------------------- - -boolean P_UseArtifact(player_t * player, artitype_t arti) -{ - mobj_t *mo; - angle_t angle; - - switch (arti) - { - case arti_invulnerability: - if (!P_GivePower(player, pw_invulnerability)) - { - return (false); - } - break; - case arti_invisibility: - if (!P_GivePower(player, pw_invisibility)) - { - return (false); - } - break; - case arti_health: - if (!P_GiveBody(player, 25)) - { - return (false); - } - break; - case arti_superhealth: - if (!P_GiveBody(player, 100)) - { - return (false); - } - break; - case arti_tomeofpower: - if (player->chickenTics) - { // Attempt to undo chicken - if (P_UndoPlayerChicken(player) == false) - { // Failed - P_DamageMobj(player->mo, NULL, NULL, 10000); - } - else - { // Succeeded - player->chickenTics = 0; - S_StartSound(player->mo, sfx_wpnup); - } - } - else - { - if (!P_GivePower(player, pw_weaponlevel2)) - { - return (false); - } - if (player->readyweapon == wp_staff) - { - P_SetPsprite(player, ps_weapon, S_STAFFREADY2_1); - } - else if (player->readyweapon == wp_gauntlets) - { - P_SetPsprite(player, ps_weapon, S_GAUNTLETREADY2_1); - } - } - break; - case arti_torch: - if (!P_GivePower(player, pw_infrared)) - { - return (false); - } - break; - case arti_firebomb: - angle = player->mo->angle >> ANGLETOFINESHIFT; - - // Vanilla bug here: - // Original code here looks like: - // (player->mo->flags2 & MF2_FEETARECLIPPED != 0), - // Which under C's operator precedence is: - // (player->mo->flags2 & (MF2_FEETARECLIPPED != 0)), - // Which simplifies to: - // (player->mo->flags2 & 1), - mo = P_SpawnMobj(player->mo->x + 24 * finecosine[angle], - player->mo->y + 24 * finesine[angle], - player->mo->z - - 15 * FRACUNIT * (player->mo->flags2 & 1), - MT_FIREBOMB); - mo->target = player->mo; - break; - case arti_egg: - mo = player->mo; - P_SpawnPlayerMissile(mo, MT_EGGFX); - P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 6)); - P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 6)); - P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 3)); - P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 3)); - break; - case arti_fly: - if (!P_GivePower(player, pw_flight)) - { - return (false); - } - break; - case arti_teleport: - P_ArtiTele(player); - break; - default: - return (false); - } - return (true); -} diff --git a/games/NXDoom/src/heretic/r_bsp.c b/games/NXDoom/src/heretic/r_bsp.c deleted file mode 100644 index 1e9d3be7a01..00000000000 --- a/games/NXDoom/src/heretic/r_bsp.c +++ /dev/null @@ -1,489 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// R_bsp.c - -#include "doomdef.h" -#include "i_system.h" -#include "m_bbox.h" -#include "i_system.h" -#include "r_local.h" - -seg_t *curline; -side_t *sidedef; -line_t *linedef; -sector_t *frontsector, *backsector; - -drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; - -void R_StoreWallRange(int start, int stop); - -/* -==================== -= -= R_ClearDrawSegs -= -==================== -*/ - -void R_ClearDrawSegs(void) -{ - ds_p = drawsegs; -} - -//============================================================================= - - -/* -=============================================================================== -= -= ClipWallSegment -= -= Clips the given range of columns and includes it in the new clip list -=============================================================================== -*/ - -typedef struct -{ - int first, last; -} cliprange_t; - -// We must expand MAXSEGS to the theoretical limit of the number of solidsegs -// that can be generated in a scene by the DOOM engine. This was determined by -// Lee Killough during BOOM development to be a function of the screensize. -// The simplest thing we can do, other than fix this bug, is to let the game -// render overage and then bomb out by detecting the overflow after the -// fact. -haleyjd -//#define MAXSEGS 32 -#define MAXSEGS (SCREENWIDTH / 2 + 1) - -cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg - - -void R_ClipSolidWallSegment(int first, int last) -{ - cliprange_t *next, *start; - -// find the first range that touches the range (adjacent pixels are touching) - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first - 1) - { // post is entirely visible (above start), so insert a new clippost - R_StoreWallRange(first, last); - next = newend; - newend++; - while (next != start) - { - *next = *(next - 1); - next--; - } - next->first = first; - next->last = last; - return; - } - - // there is a fragment above *start - R_StoreWallRange(first, start->first - 1); - start->first = first; // adjust the clip size - } - - if (last <= start->last) - return; // bottom contained in start - - next = start; - while (last >= (next + 1)->first - 1) - { - // there is a fragment between two posts - R_StoreWallRange(next->last + 1, (next + 1)->first - 1); - next++; - if (last <= next->last) - { // bottom is contained in next - start->last = next->last; // adjust the clip size - goto crunch; - } - } - - // there is a fragment after *next - R_StoreWallRange(next->last + 1, last); - start->last = last; // adjust the clip size - - -// remove start+1 to next from the clip list, -// because start now covers their area - crunch: - if (next == start) - return; // post just extended past the bottom of one post - - while (next++ != newend) // remove a post - *++start = *next; - newend = start + 1; -} - -/* -=============================================================================== -= -= R_ClipPassWallSegment -= -= Clips the given range of columns, but does not includes it in the clip list -=============================================================================== -*/ - -void R_ClipPassWallSegment(int first, int last) -{ - cliprange_t *start; - -// find the first range that touches the range (adjacent pixels are touching) - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first - 1) - { // post is entirely visible (above start) - R_StoreWallRange(first, last); - return; - } - - // there is a fragment above *start - R_StoreWallRange(first, start->first - 1); - } - - if (last <= start->last) - return; // bottom contained in start - - while (last >= (start + 1)->first - 1) - { - // there is a fragment between two posts - R_StoreWallRange(start->last + 1, (start + 1)->first - 1); - start++; - if (last <= start->last) - return; - } - - // there is a fragment after *next - R_StoreWallRange(start->last + 1, last); -} - - - -/* -==================== -= -= R_ClearClipSegs -= -==================== -*/ - -void R_ClearClipSegs(void) -{ - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = -1; - solidsegs[1].first = viewwidth; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs + 2; -} - - -//============================================================================= - -/* -====================== -= -= R_AddLine -= -= Clips the given segment and adds any visible pieces to the line list -= -====================== -*/ - -void R_AddLine(seg_t * line) -{ - int x1, x2; - angle_t angle1, angle2, span, tspan; - - curline = line; - -// OPTIMIZE: quickly reject orthogonal back sides - - angle1 = R_PointToAngle(line->v1->x, line->v1->y); - angle2 = R_PointToAngle(line->v2->x, line->v2->y); - -// -// clip to view edges -// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW) - span = angle1 - angle2; - if (span >= ANG180) - return; // back side - - rw_angle1 = angle1; // global angle needed by segcalc - angle1 -= viewangle; - angle2 -= viewangle; - - tspan = angle1 + clipangle; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return; // totally off the left edge - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return; // totally off the left edge - angle2 = -clipangle; - } - -// -// the seg is in the view range, but not necessarily visible -// - angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; - angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; - if (x1 == x2) - return; // does not cross a pixel - - backsector = line->backsector; - - if (!backsector) - goto clipsolid; // single sided line - - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - goto clipsolid; // closed door - - if (backsector->ceilingheight != frontsector->ceilingheight - || backsector->floorheight != frontsector->floorheight) - goto clippass; // window - -// reject empty lines used for triggers and special events - if (backsector->ceilingpic == frontsector->ceilingpic - && backsector->floorpic == frontsector->floorpic - && backsector->lightlevel == frontsector->lightlevel - && curline->sidedef->midtexture == 0) - return; - - clippass: - R_ClipPassWallSegment(x1, x2 - 1); - return; - - clipsolid: - R_ClipSolidWallSegment(x1, x2 - 1); -} - -//============================================================================ - - -/* -=============================================================================== -= -= R_CheckBBox -= -= Returns true if some part of the bbox might be visible -= -=============================================================================== -*/ - -int checkcoord[12][4] = { - {3, 0, 2, 1}, - {3, 0, 2, 0}, - {3, 1, 2, 0}, - {0}, - {2, 0, 2, 1}, - {0, 0, 0, 0}, - {3, 1, 3, 0}, - {0}, - {2, 0, 3, 1}, - {2, 1, 3, 1}, - {2, 1, 3, 0} -}; - - -boolean R_CheckBBox(fixed_t * bspcoord) -{ - int boxx, boxy, boxpos; - fixed_t x1, y1, x2, y2; - angle_t angle1, angle2, span, tspan; - cliprange_t *start; - int sx1, sx2; - -// find the corners of the box that define the edges from current viewpoint - if (viewx <= bspcoord[BOXLEFT]) - boxx = 0; - else if (viewx < bspcoord[BOXRIGHT]) - boxx = 1; - else - boxx = 2; - - if (viewy >= bspcoord[BOXTOP]) - boxy = 0; - else if (viewy > bspcoord[BOXBOTTOM]) - boxy = 1; - else - boxy = 2; - - boxpos = (boxy << 2) + boxx; - if (boxpos == 5) - return true; - - x1 = bspcoord[checkcoord[boxpos][0]]; - y1 = bspcoord[checkcoord[boxpos][1]]; - x2 = bspcoord[checkcoord[boxpos][2]]; - y2 = bspcoord[checkcoord[boxpos][3]]; - - -// -// check clip list for an open space -// - angle1 = R_PointToAngle(x1, y1) - viewangle; - angle2 = R_PointToAngle(x2, y2) - viewangle; - - span = angle1 - angle2; - if (span >= ANG180) - return true; // sitting on a line - tspan = angle1 + clipangle; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return false; // totally off the left edge - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return false; // totally off the left edge - angle2 = -clipangle; - } - - -// find the first clippost that touches the source post (adjacent pixels are touching) - angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; - angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; - sx1 = viewangletox[angle1]; - sx2 = viewangletox[angle2]; - if (sx1 == sx2) - return false; // does not cross a pixel - sx2--; - - start = solidsegs; - while (start->last < sx2) - start++; - if (sx1 >= start->first && sx2 <= start->last) - return false; // the clippost contains the new span - - return true; -} - - -/* -================ -= -= R_Subsector -= -= Draw one or more segments -================ -*/ - -void R_Subsector(int num) -{ - int count; - seg_t *line; - subsector_t *sub; - -#ifdef RANGECHECK - if (num >= numsubsectors) - I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); -#endif - - sscount++; - sub = &subsectors[num]; - frontsector = sub->sector; - count = sub->numlines; - line = &segs[sub->firstline]; - - if (frontsector->floorheight < viewz) - floorplane = R_FindPlane(frontsector->floorheight, - frontsector->floorpic, - frontsector->lightlevel, - frontsector->special); - else - floorplane = NULL; - if (frontsector->ceilingheight > viewz - || frontsector->ceilingpic == skyflatnum) - ceilingplane = R_FindPlane(frontsector->ceilingheight, - frontsector->ceilingpic, - frontsector->lightlevel, 0); - else - ceilingplane = NULL; - - R_AddSprites(frontsector); - - while (count--) - { - R_AddLine(line); - line++; - } - - // check for solidsegs overflow - extremely unsatisfactory! - if(newend > &solidsegs[32]) - I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); -} - - -/* -=============================================================================== -= -= RenderBSPNode -= -=============================================================================== -*/ - -void R_RenderBSPNode(int bspnum) -{ - node_t *bsp; - int side; - - if (bspnum & NF_SUBSECTOR) - { - if (bspnum == -1) - R_Subsector(0); - else - R_Subsector(bspnum & (~NF_SUBSECTOR)); - return; - } - - bsp = &nodes[bspnum]; - -// -// decide which side the view point is on -// - side = R_PointOnSide(viewx, viewy, bsp); - - R_RenderBSPNode(bsp->children[side]); // recursively divide front space - - if (R_CheckBBox(bsp->bbox[side ^ 1])) // possibly divide back space - R_RenderBSPNode(bsp->children[side ^ 1]); -} diff --git a/games/NXDoom/src/heretic/r_data.c b/games/NXDoom/src/heretic/r_data.c deleted file mode 100644 index 04bdecc8669..00000000000 --- a/games/NXDoom/src/heretic/r_data.c +++ /dev/null @@ -1,732 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// R_data.c - -#include "doomdef.h" -#include "deh_str.h" - -#include "i_swap.h" -#include "i_system.h" -#include "m_misc.h" -#include "r_local.h" -#include "p_local.h" - - -typedef struct -{ - int originx; // block origin (allways UL), which has allready - int originy; // accounted for the patch's internal origin - int patch; -} texpatch_t; - -// a maptexturedef_t describes a rectangular texture, which is composed of one -// or more mappatch_t structures that arrange graphic patches -typedef struct -{ - char name[8]; // for switch changing, etc - short width; - short height; - short patchcount; - texpatch_t patches[1]; // [patchcount] drawn back to front - // into the cached texture -} texture_t; - - - -int firstflat, lastflat, numflats; -int firstpatch, lastpatch, numpatches; -int firstspritelump, lastspritelump, numspritelumps; - -int numtextures; -texture_t **textures; -int *texturewidthmask; -fixed_t *textureheight; // needed for texture pegging -int *texturecompositesize; -short **texturecolumnlump; -unsigned short **texturecolumnofs; -byte **texturecomposite; - -int *flattranslation; // for global animation -int *texturetranslation; // for global animation - -fixed_t *spritewidth; // needed for pre rendering -fixed_t *spriteoffset; -fixed_t *spritetopoffset; - -lighttable_t *colormaps; - - -/* -============================================================================== - - MAPTEXTURE_T CACHING - -when a texture is first needed, it counts the number of composite columns -required in the texture and allocates space for a column directory and any -new columns. The directory will simply point inside other patches if there -is only one patch in a given column, but any columns with multiple patches -will have new column_ts generated. - -============================================================================== -*/ - -/* -=================== -= -= R_DrawColumnInCache -= -= Clip and draw a column from a patch into a cached post -= -=================== -*/ - -void R_DrawColumnInCache(column_t * patch, byte * cache, int originy, - int cacheheight) -{ - int count, position; - byte *source; - - while (patch->topdelta != 0xff) - { - source = (byte *) patch + 3; - count = patch->length; - position = originy + patch->topdelta; - if (position < 0) - { - count += position; - position = 0; - } - if (position + count > cacheheight) - count = cacheheight - position; - if (count > 0) - memcpy(cache + position, source, count); - - patch = (column_t *) ((byte *) patch + patch->length + 4); - } -} - - -/* -=================== -= -= R_GenerateComposite -= -=================== -*/ - -void R_GenerateComposite(int texnum) -{ - byte *block; - texture_t *texture; - texpatch_t *patch; - patch_t *realpatch; - int x, x1, x2; - int i; - column_t *patchcol; - short *collump; - unsigned short *colofs; - - texture = textures[texnum]; - block = Z_Malloc(texturecompositesize[texnum], PU_STATIC, - &texturecomposite[texnum]); - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - -// -// composite the columns together -// - for (i = 0, patch = texture->patches; i < texture->patchcount; - i++, patch++) - { - realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1 < 0) - x = 0; - else - x = x1; - if (x2 > texture->width) - x2 = texture->width; - - for (; x < x2; x++) - { - if (collump[x] >= 0) - continue; // column does not have multiple patches - patchcol = (column_t *) ((byte *) realpatch + - LONG(realpatch->columnofs[x - x1])); - R_DrawColumnInCache(patchcol, block + colofs[x], patch->originy, - texture->height); - } - - } - -// now that the texture has been built, it is purgable - Z_ChangeTag(block, PU_CACHE); -} - - -/* -=================== -= -= R_GenerateLookup -= -=================== -*/ - -void R_GenerateLookup(int texnum) -{ - texture_t *texture; - byte *patchcount; // [texture->width] - texpatch_t *patch; - patch_t *realpatch; - int x, x1, x2; - int i; - short *collump; - unsigned short *colofs; - - texture = textures[texnum]; - - texturecomposite[texnum] = 0; // composited not created yet - texturecompositesize[texnum] = 0; - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - -// -// count the number of columns that are covered by more than one patch -// fill in the lump / offset, so columns with only a single patch are -// all done -// - patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); - memset(patchcount, 0, texture->width); - - for (i = 0, patch = texture->patches; i < texture->patchcount; - i++, patch++) - { - realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - if (x1 < 0) - x = 0; - else - x = x1; - if (x2 > texture->width) - x2 = texture->width; - for (; x < x2; x++) - { - patchcount[x]++; - collump[x] = patch->patch; - colofs[x] = LONG(realpatch->columnofs[x - x1]) + 3; - } - } - - for (x = 0; x < texture->width; x++) - { - if (!patchcount[x]) - { - printf("R_GenerateLookup: column without a patch (%s)\n", - texture->name); - return; - } -// I_Error ("R_GenerateLookup: column without a patch"); - if (patchcount[x] > 1) - { - collump[x] = -1; // use the cached block - colofs[x] = texturecompositesize[texnum]; - if (texturecompositesize[texnum] > 0x10000 - texture->height) - I_Error("R_GenerateLookup: texture %i is >64k", texnum); - texturecompositesize[texnum] += texture->height; - } - } - - Z_Free(patchcount); -} - - -/* -================ -= -= R_GetColumn -= -================ -*/ - -byte *R_GetColumn(int tex, int col) -{ - int lump, ofs; - - col &= texturewidthmask[tex]; - lump = texturecolumnlump[tex][col]; - ofs = texturecolumnofs[tex][col]; - if (lump > 0) - return (byte *) W_CacheLumpNum(lump, PU_CACHE) + ofs; - if (!texturecomposite[tex]) - R_GenerateComposite(tex); - return texturecomposite[tex] + ofs; -} - - -/* -================== -= -= R_InitTextures -= -= Initializes the texture list with the textures from the world map -= -================== -*/ - -void R_InitTextures(void) -{ - maptexture_t *mtexture; - texture_t *texture; - mappatch_t *mpatch; - texpatch_t *patch; - int i, j; - int *maptex, *maptex2, *maptex1; - char name[9], *names, *name_p; - int *patchlookup; - int nummappatches; - int offset, maxoff, maxoff2; - int numtextures1, numtextures2; - int *directory; - const char *texture1, *texture2, *pnames; - - texture1 = DEH_String("TEXTURE1"); - texture2 = DEH_String("TEXTURE2"); - pnames = DEH_String("PNAMES"); - -// -// load the patch names from pnames.lmp -// - names = W_CacheLumpName(pnames, PU_STATIC); - nummappatches = LONG(*((int *) names)); - name_p = names + 4; - patchlookup = Z_Malloc(nummappatches * sizeof(*patchlookup), PU_STATIC, NULL); - for (i = 0; i < nummappatches; i++) - { - M_StringCopy(name, name_p + i * 8, sizeof(name)); - patchlookup[i] = W_CheckNumForName(name); - } - W_ReleaseLumpName(pnames); - -// -// load the map texture definitions from textures.lmp -// - maptex = maptex1 = W_CacheLumpName(texture1, PU_STATIC); - numtextures1 = LONG(*maptex); - maxoff = W_LumpLength(W_GetNumForName(texture1)); - directory = maptex + 1; - - if (W_CheckNumForName(texture2) != -1) - { - maptex2 = W_CacheLumpName(texture2, PU_STATIC); - numtextures2 = LONG(*maptex2); - maxoff2 = W_LumpLength(W_GetNumForName(texture2)); - } - else - { - maptex2 = NULL; - numtextures2 = 0; - maxoff2 = 0; - } - numtextures = numtextures1 + numtextures2; - - // - // Init the startup thermometer at this point... - // - { - int start, end; - int spramount; - start = W_GetNumForName(DEH_String("S_START")); - end = W_GetNumForName(DEH_String("S_END")); - spramount = end - start + 1; - InitThermo(spramount + numtextures + 6); - } - - textures = Z_Malloc(numtextures * sizeof(texture_t *), PU_STATIC, 0); - texturecolumnlump = Z_Malloc(numtextures * sizeof(short *), PU_STATIC, 0); - texturecolumnofs = Z_Malloc(numtextures * sizeof(unsigned short *), PU_STATIC, 0); - texturecomposite = Z_Malloc(numtextures * sizeof(byte *), PU_STATIC, 0); - texturecompositesize = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); - texturewidthmask = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); - textureheight = Z_Malloc(numtextures * sizeof(fixed_t), PU_STATIC, 0); - - for (i = 0; i < numtextures; i++, directory++) - { -#ifdef __NEXT__ - if (!(i & 63)) - printf("."); -#else - IncThermo(); -#endif - if (i == numtextures1) - { // start looking in second texture file - maptex = maptex2; - maxoff = maxoff2; - directory = maptex + 1; - } - - offset = LONG(*directory); - if (offset > maxoff) - I_Error("R_InitTextures: bad texture directory"); - mtexture = (maptexture_t *) ((byte *) maptex + offset); - texture = textures[i] = Z_Malloc(sizeof(texture_t) - + - sizeof(texpatch_t) * - (SHORT(mtexture->patchcount) - 1), - PU_STATIC, 0); - texture->width = SHORT(mtexture->width); - texture->height = SHORT(mtexture->height); - texture->patchcount = SHORT(mtexture->patchcount); - memcpy(texture->name, mtexture->name, sizeof(texture->name)); - mpatch = &mtexture->patches[0]; - patch = &texture->patches[0]; - for (j = 0; j < texture->patchcount; j++, mpatch++, patch++) - { - patch->originx = SHORT(mpatch->originx); - patch->originy = SHORT(mpatch->originy); - patch->patch = patchlookup[SHORT(mpatch->patch)]; - if (patch->patch == -1) - I_Error("R_InitTextures: Missing patch in texture %s", - texture->name); - } - texturecolumnlump[i] = Z_Malloc(texture->width * sizeof(short), - PU_STATIC, 0); - texturecolumnofs[i] = Z_Malloc(texture->width * sizeof(short), - PU_STATIC, 0); - j = 1; - while (j * 2 <= texture->width) - j <<= 1; - texturewidthmask[i] = j - 1; - textureheight[i] = texture->height << FRACBITS; - } - - Z_Free(patchlookup); - - W_ReleaseLumpName(texture1); - if (maptex2) - { - W_ReleaseLumpName(texture2); - } - -// -// precalculate whatever possible -// - for (i = 0; i < numtextures; i++) - { - R_GenerateLookup(i); - CheckAbortStartup(); - } - -// -// translation table for global animation -// - texturetranslation = Z_Malloc((numtextures + 1) * sizeof(int), PU_STATIC, 0); - for (i = 0; i < numtextures; i++) - texturetranslation[i] = i; -} - - -/* -================ -= -= R_InitFlats -= -================= -*/ - -void R_InitFlats(void) -{ - int i; - - firstflat = W_GetNumForName(DEH_String("F_START")) + 1; - lastflat = W_GetNumForName(DEH_String("F_END")) - 1; - numflats = lastflat - firstflat + 1; - -// translation table for global animation - flattranslation = Z_Malloc((numflats + 1) * sizeof(int), PU_STATIC, 0); - for (i = 0; i < numflats; i++) - flattranslation[i] = i; -} - - -/* -================ -= -= R_InitSpriteLumps -= -= Finds the width and hoffset of all sprites in the wad, so the sprite doesn't -= need to be cached just for the header during rendering -================= -*/ - -void R_InitSpriteLumps(void) -{ - int i; - patch_t *patch; - - firstspritelump = W_GetNumForName(DEH_String("S_START")) + 1; - lastspritelump = W_GetNumForName(DEH_String("S_END")) - 1; - numspritelumps = lastspritelump - firstspritelump + 1; - spritewidth = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); - spriteoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); - spritetopoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); - - for (i = 0; i < numspritelumps; i++) - { -#ifdef __NEXT__ - if (!(i & 63)) - printf("."); -#else - IncThermo(); -#endif - patch = W_CacheLumpNum(firstspritelump + i, PU_CACHE); - spritewidth[i] = SHORT(patch->width) << FRACBITS; - spriteoffset[i] = SHORT(patch->leftoffset) << FRACBITS; - spritetopoffset[i] = SHORT(patch->topoffset) << FRACBITS; - } -} - - -/* -================ -= -= R_InitColormaps -= -================= -*/ - -void R_InitColormaps(void) -{ - int lump, length; -// -// load in the light tables -// 256 byte align tables -// - lump = W_GetNumForName(DEH_String("COLORMAP")); - length = W_LumpLength(lump); - colormaps = Z_Malloc(length, PU_STATIC, 0); - W_ReadLump(lump, colormaps); -} - - -/* -================ -= -= R_InitData -= -= Locates all the lumps that will be used by all views -= Must be called after W_Init -================= -*/ - -void R_InitData(void) -{ - //tprintf("\nR_InitTextures ", 0); - R_InitTextures(); - printf ("."); - //tprintf("R_InitFlats\n", 0); - R_InitFlats(); - IncThermo(); - printf ("."); - //tprintf("R_InitSpriteLumps ", 0); - R_InitSpriteLumps(); - IncThermo(); - printf ("."); - R_InitColormaps(); -} - - -//============================================================================= - -/* -================ -= -= R_FlatNumForName -= -================ -*/ - -int R_FlatNumForName(const char *name) -{ - int i; - char namet[9]; - - i = W_CheckNumForName(name); - if (i == -1) - { - namet[8] = 0; - memcpy(namet, name, 8); - I_Error("R_FlatNumForName: %s not found", namet); - } - return i - firstflat; -} - - -/* -================ -= -= R_CheckTextureNumForName -= -================ -*/ - -int R_CheckTextureNumForName(const char *name) -{ - int i; - - if (name[0] == '-') // no texture marker - return 0; - - for (i = 0; i < numtextures; i++) - if (!strncasecmp(textures[i]->name, name, 8)) - return i; - - return -1; -} - - -/* -================ -= -= R_TextureNumForName -= -================ -*/ - -int R_TextureNumForName(const char *name) -{ - int i; - //char namet[9]; - - i = R_CheckTextureNumForName(name); - if (i == -1) - I_Error("R_TextureNumForName: %s not found", name); - - return i; -} - - -/* -================= -= -= R_PrecacheLevel -= -= Preloads all relevent graphics for the level -================= -*/ - -int flatmemory, texturememory, spritememory; - -void R_PrecacheLevel(void) -{ - char *flatpresent; - char *texturepresent; - char *spritepresent; - int i, j, k, lump; - texture_t *texture; - thinker_t *th; - spriteframe_t *sf; - - if (demoplayback) - return; - -// -// precache flats -// - flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); - memset(flatpresent, 0, numflats); - for (i = 0; i < numsectors; i++) - { - flatpresent[sectors[i].floorpic] = 1; - flatpresent[sectors[i].ceilingpic] = 1; - } - - flatmemory = 0; - for (i = 0; i < numflats; i++) - if (flatpresent[i]) - { - lump = firstflat + i; - flatmemory += lumpinfo[lump]->size; - W_CacheLumpNum(lump, PU_CACHE); - } - - Z_Free(flatpresent); - -// -// precache textures -// - texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); - memset(texturepresent, 0, numtextures); - - for (i = 0; i < numsides; i++) - { - texturepresent[sides[i].toptexture] = 1; - texturepresent[sides[i].midtexture] = 1; - texturepresent[sides[i].bottomtexture] = 1; - } - - texturepresent[skytexture] = 1; - - texturememory = 0; - for (i = 0; i < numtextures; i++) - { - if (!texturepresent[i]) - continue; - texture = textures[i]; - for (j = 0; j < texture->patchcount; j++) - { - lump = texture->patches[j].patch; - texturememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump, PU_CACHE); - } - } - - Z_Free(texturepresent); - -// -// precache sprites -// - spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); - memset(spritepresent, 0, numsprites); - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function == P_MobjThinker) - spritepresent[((mobj_t *) th)->sprite] = 1; - } - - spritememory = 0; - for (i = 0; i < numsprites; i++) - { - if (!spritepresent[i]) - continue; - for (j = 0; j < sprites[i].numframes; j++) - { - sf = &sprites[i].spriteframes[j]; - for (k = 0; k < 8; k++) - { - lump = firstspritelump + sf->lump[k]; - spritememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump, PU_CACHE); - } - } - } - - Z_Free(spritepresent); -} diff --git a/games/NXDoom/src/heretic/r_draw.c b/games/NXDoom/src/heretic/r_draw.c deleted file mode 100644 index 4760cd59aca..00000000000 --- a/games/NXDoom/src/heretic/r_draw.c +++ /dev/null @@ -1,490 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// R_draw.c - -#include "doomdef.h" -#include "deh_str.h" -#include "r_local.h" -#include "i_video.h" -#include "v_video.h" - -/* - -All drawing to the view buffer is accomplished in this file. The other refresh -files only know about ccordinates, not the architecture of the frame buffer. - -*/ - -byte *viewimage; -int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; -byte *ylookup[MAXHEIGHT]; -int columnofs[MAXWIDTH]; -byte translations[3][256]; // color tables for different players - -/* -================== -= -= R_DrawColumn -= -= Source is the top of the column to scale -= -================== -*/ - -lighttable_t *dc_colormap; -int dc_x; -int dc_yl; -int dc_yh; -fixed_t dc_iscale; -fixed_t dc_texturemid; -byte *dc_source; // first pixel in a column (possibly virtual) - -int dccount; // just for profiling - -void R_DrawColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -void R_DrawColumnLow(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -// dccount++; -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -// Translucent column draw - blended with background using tinttable. - -void R_DrawTLColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - if (!dc_yl) - dc_yl = 1; - if (dc_yh == viewheight - 1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = - tinttable[((*dest) << 8) + - dc_colormap[dc_source[(frac >> FRACBITS) & 127]]]; - - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -/* -======================== -= -= R_DrawTranslatedColumn -= -======================== -*/ - -byte *dc_translation; -byte *translationtables; - -void R_DrawTranslatedColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -void R_DrawTranslatedTLColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = tinttable[((*dest) << 8) - + - dc_colormap[dc_translation - [dc_source[frac >> FRACBITS]]]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -//-------------------------------------------------------------------------- -// -// PROC R_InitTranslationTables -// -//-------------------------------------------------------------------------- - -void R_InitTranslationTables(void) -{ - int i; - - V_LoadTintTable(); - - // Allocate translation tables - translationtables = Z_Malloc(256 * 3, PU_STATIC, 0); - - // Fill out the translation tables - for (i = 0; i < 256; i++) - { - if (i >= 225 && i <= 240) - { - translationtables[i] = 114 + (i - 225); // yellow - translationtables[i + 256] = 145 + (i - 225); // red - translationtables[i + 512] = 190 + (i - 225); // blue - } - else - { - translationtables[i] = translationtables[i + 256] - = translationtables[i + 512] = i; - } - } -} - -/* -================ -= -= R_DrawSpan -= -================ -*/ - -int ds_y; -int ds_x1; -int ds_x2; -lighttable_t *ds_colormap; -fixed_t ds_xfrac; -fixed_t ds_yfrac; -fixed_t ds_xstep; -fixed_t ds_ystep; -byte *ds_source; // start of a 64*64 tile image - -int dscount; // just for profiling - -void R_DrawSpan(void) -{ - fixed_t xfrac, yfrac; - byte *dest; - int count, spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH - || (unsigned) ds_y > SCREENHEIGHT) - I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); -// dscount++; -#endif - - xfrac = ds_xfrac; - yfrac = ds_yfrac; - - dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1; - do - { - spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); - *dest++ = ds_colormap[ds_source[spot]]; - xfrac += ds_xstep; - yfrac += ds_ystep; - } - while (count--); -} - -void R_DrawSpanLow(void) -{ - fixed_t xfrac, yfrac; - byte *dest; - int count, spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH - || (unsigned) ds_y > SCREENHEIGHT) - I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); -// dscount++; -#endif - - xfrac = ds_xfrac; - yfrac = ds_yfrac; - - dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1; - do - { - spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); - *dest++ = ds_colormap[ds_source[spot]]; - xfrac += ds_xstep; - yfrac += ds_ystep; - } - while (count--); -} - - - -/* -================ -= -= R_InitBuffer -= -================= -*/ - -void R_InitBuffer(int width, int height) -{ - int i; - - viewwindowx = (SCREENWIDTH - width) >> 1; - for (i = 0; i < width; i++) - columnofs[i] = viewwindowx + i; - if (width == SCREENWIDTH) - viewwindowy = 0; - else - viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1; - for (i = 0; i < height; i++) - ylookup[i] = I_VideoBuffer + (i + viewwindowy) * SCREENWIDTH; -} - - -/* -================== -= -= R_DrawViewBorder -= -= Draws the border around the view for different size windows -================== -*/ - -boolean BorderNeedRefresh; - -void R_DrawViewBorder(void) -{ - byte *src, *dest; - int x, y; - - if (scaledviewwidth == SCREENWIDTH) - return; - - if (gamemode == shareware) - { - src = W_CacheLumpName(DEH_String("FLOOR04"), PU_CACHE); - } - else - { - src = W_CacheLumpName(DEH_String("FLAT513"), PU_CACHE); - } - dest = I_VideoBuffer; - - for (y = 0; y < SCREENHEIGHT - SBARHEIGHT; y++) - { - for (x = 0; x < SCREENWIDTH / 64; x++) - { - memcpy(dest, src + ((y & 63) << 6), 64); - dest += 64; - } - if (SCREENWIDTH & 63) - { - memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); - dest += (SCREENWIDTH & 63); - } - } - for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) - { - V_DrawPatch(x, viewwindowy - 4, - W_CacheLumpName(DEH_String("bordt"), PU_CACHE)); - V_DrawPatch(x, viewwindowy + viewheight, - W_CacheLumpName(DEH_String("bordb"), PU_CACHE)); - } - for (y = viewwindowy; y < viewwindowy + viewheight; y += 16) - { - V_DrawPatch(viewwindowx - 4, y, - W_CacheLumpName(DEH_String("bordl"), PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, y, - W_CacheLumpName(DEH_String("bordr"), PU_CACHE)); - } - V_DrawPatch(viewwindowx - 4, viewwindowy - 4, - W_CacheLumpName(DEH_String("bordtl"), PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, - W_CacheLumpName(DEH_String("bordtr"), PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy + viewheight, - W_CacheLumpName(DEH_String("bordbr"), PU_CACHE)); - V_DrawPatch(viewwindowx - 4, viewwindowy + viewheight, - W_CacheLumpName(DEH_String("bordbl"), PU_CACHE)); -} - -/* -================== -= -= R_DrawTopBorder -= -= Draws the top border around the view for different size windows -================== -*/ - -boolean BorderTopRefresh; - -void R_DrawTopBorder(void) -{ - byte *src, *dest; - int x, y; - - if (scaledviewwidth == SCREENWIDTH) - return; - - if (gamemode == shareware) - { - src = W_CacheLumpName(DEH_String("FLOOR04"), PU_CACHE); - } - else - { - src = W_CacheLumpName(DEH_String("FLAT513"), PU_CACHE); - } - dest = I_VideoBuffer; - - for (y = 0; y < 30; y++) - { - for (x = 0; x < SCREENWIDTH / 64; x++) - { - memcpy(dest, src + ((y & 63) << 6), 64); - dest += 64; - } - if (SCREENWIDTH & 63) - { - memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); - dest += (SCREENWIDTH & 63); - } - } - if (viewwindowy < 25) - { - for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) - { - V_DrawPatch(x, viewwindowy - 4, - W_CacheLumpName(DEH_String("bordt"), PU_CACHE)); - } - V_DrawPatch(viewwindowx - 4, viewwindowy, - W_CacheLumpName(DEH_String("bordl"), PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy, - W_CacheLumpName(DEH_String("bordr"), PU_CACHE)); - V_DrawPatch(viewwindowx - 4, viewwindowy + 16, - W_CacheLumpName(DEH_String("bordl"), PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy + 16, - W_CacheLumpName(DEH_String("bordr"), PU_CACHE)); - - V_DrawPatch(viewwindowx - 4, viewwindowy - 4, - W_CacheLumpName(DEH_String("bordtl"), PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, - W_CacheLumpName(DEH_String("bordtr"), PU_CACHE)); - } -} diff --git a/games/NXDoom/src/heretic/r_local.h b/games/NXDoom/src/heretic/r_local.h deleted file mode 100644 index cf58ed18522..00000000000 --- a/games/NXDoom/src/heretic/r_local.h +++ /dev/null @@ -1,487 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// R_local.h - -#ifndef __R_LOCAL__ -#define __R_LOCAL__ - -#include "i_video.h" -#include "v_patch.h" - -#define ANGLETOSKYSHIFT 22 // sky map is 256*128*4 maps - -#define BASEYCENTER 100 - -#define MAXWIDTH 1120 -#define MAXHEIGHT 832 - -#define PI 3.141592657 - -#define CENTERY (SCREENHEIGHT/2) - -#define MINZ (FRACUNIT*4) - -#define FIELDOFVIEW 2048 // fineangles in the SCREENWIDTH wide window - -// -// lighting constants -// -#define LIGHTLEVELS 16 -#define LIGHTSEGSHIFT 4 -#define MAXLIGHTSCALE 48 -#define LIGHTSCALESHIFT 12 -#define MAXLIGHTZ 128 -#define LIGHTZSHIFT 20 -#define NUMCOLORMAPS 32 // number of diminishing -#define INVERSECOLORMAP 32 - -/* -============================================================================== - - INTERNAL MAP TYPES - -============================================================================== -*/ - -//================ used by play and refresh - -typedef struct -{ - fixed_t x, y; -} vertex_t; - -struct line_s; - -typedef struct -{ - fixed_t floorheight, ceilingheight; - short floorpic, ceilingpic; - short lightlevel; - short special, tag; - - int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 - mobj_t *soundtarget; // thing that made a sound (or null) - - int blockbox[4]; // mapblock bounding box for height changes - degenmobj_t soundorg; // for any sounds played by the sector - - int validcount; // if == validcount, already checked - mobj_t *thinglist; // list of mobjs in sector - void *specialdata; // thinker_t for reversable actions - int linecount; - struct line_s **lines; // [linecount] size -} sector_t; - -typedef struct -{ - fixed_t textureoffset; // add this to the calculated texture col - fixed_t rowoffset; // add this to the calculated texture top - short toptexture, bottomtexture, midtexture; - sector_t *sector; -} side_t; - -typedef enum -{ ST_HORIZONTAL, ST_VERTICAL, ST_POSITIVE, ST_NEGATIVE } slopetype_t; - -typedef struct line_s -{ - vertex_t *v1, *v2; - fixed_t dx, dy; // v2 - v1 for side checking - short flags; - short special, tag; - short sidenum[2]; // sidenum[1] will be -1 if one sided - fixed_t bbox[4]; - slopetype_t slopetype; // to aid move clipping - sector_t *frontsector, *backsector; - int validcount; // if == validcount, already checked - void *specialdata; // thinker_t for reversable actions -} line_t; - - -typedef struct subsector_s -{ - sector_t *sector; - short numlines; - short firstline; -} subsector_t; - -typedef struct -{ - vertex_t *v1, *v2; - fixed_t offset; - angle_t angle; - side_t *sidedef; - line_t *linedef; - sector_t *frontsector; - sector_t *backsector; // NULL for one sided lines -} seg_t; - -typedef struct -{ - fixed_t x, y, dx, dy; // partition line - fixed_t bbox[2][4]; // bounding box for each child - unsigned short children[2]; // if NF_SUBSECTOR its a subsector -} node_t; - - -/* -============================================================================== - - OTHER TYPES - -============================================================================== -*/ - -typedef byte lighttable_t; // this could be wider for >8 bit display - -#define MAXVISPLANES 128 -#define MAXOPENINGS SCREENWIDTH*64 - -typedef struct -{ - fixed_t height; - int picnum; - int lightlevel; - int special; - int minx, maxx; - byte pad1; // leave pads for [minx-1]/[maxx+1] - byte top[SCREENWIDTH]; - byte pad2; - byte pad3; - byte bottom[SCREENWIDTH]; - byte pad4; -} visplane_t; - -typedef struct drawseg_s -{ - seg_t *curline; - int x1, x2; - fixed_t scale1, scale2, scalestep; - int silhouette; // 0=none, 1=bottom, 2=top, 3=both - fixed_t bsilheight; // don't clip sprites above this - fixed_t tsilheight; // don't clip sprites below this -// pointers to lists for sprite clipping - short *sprtopclip; // adjusted so [x1] is first value - short *sprbottomclip; // adjusted so [x1] is first value - short *maskedtexturecol; // adjusted so [x1] is first value -} drawseg_t; - -#define SIL_NONE 0 -#define SIL_BOTTOM 1 -#define SIL_TOP 2 -#define SIL_BOTH 3 - -#define MAXDRAWSEGS 256 - -// A vissprite_t is a thing that will be drawn during a refresh -typedef struct vissprite_s -{ - struct vissprite_s *prev, *next; - int x1, x2; - fixed_t gx, gy; // for line side calculation - fixed_t gz, gzt; // global bottom / top for silhouette clipping - fixed_t startfrac; // horizontal position of x1 - fixed_t scale; - fixed_t xiscale; // negative if flipped - fixed_t texturemid; - int patch; - lighttable_t *colormap; - int mobjflags; // for color translation and shadow draw - boolean psprite; // true if psprite - fixed_t footclip; // foot clipping -} vissprite_t; - - -extern visplane_t *floorplane, *ceilingplane; - -// Sprites are patches with a special naming convention so they can be -// recognized by R_InitSprites. The sprite and frame specified by a -// thing_t is range checked at run time. -// a sprite is a patch_t that is assumed to represent a three dimensional -// object and may have multiple rotations pre drawn. Horizontal flipping -// is used to save space. Some sprites will only have one picture used -// for all views. - -typedef struct -{ - boolean rotate; // if false use 0 for any position - short lump[8]; // lump to use for view angles 0-7 - byte flip[8]; // flip (1 = flip) to use for view angles 0-7 -} spriteframe_t; - -typedef struct -{ - int numframes; - spriteframe_t *spriteframes; -} spritedef_t; - -extern spritedef_t *sprites; -extern int numsprites; - -//============================================================================= - -extern int numvertexes; -extern vertex_t *vertexes; - -extern int numsegs; -extern seg_t *segs; - -extern int numsectors; -extern sector_t *sectors; - -extern int numsubsectors; -extern subsector_t *subsectors; - -extern int numnodes; -extern node_t *nodes; - -extern int numlines; -extern line_t *lines; - -extern int numsides; -extern side_t *sides; - - - -extern fixed_t viewx, viewy, viewz; -extern angle_t viewangle; -extern player_t *viewplayer; - - -extern angle_t clipangle; - -extern int viewangletox[FINEANGLES / 2]; -extern angle_t xtoviewangle[SCREENWIDTH + 1]; - -extern fixed_t rw_distance; -extern angle_t rw_normalangle; - -// -// R_main.c -// -extern int viewwidth, viewheight, viewwindowx, viewwindowy; -extern int scaledviewwidth; -extern int centerx, centery; -extern int flyheight; -extern fixed_t centerxfrac; -extern fixed_t centeryfrac; -extern fixed_t projection; - -extern int validcount; - -extern int sscount, linecount, loopcount; -extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; -extern lighttable_t *scalelightfixed[MAXLIGHTSCALE]; -extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; - -extern int extralight; -extern lighttable_t *fixedcolormap; - -extern fixed_t viewcos, viewsin; - -extern int detailshift; // 0 = high, 1 = low - -extern int detailLevel; -extern int screenblocks; - -extern void (*colfunc) (void); -extern void (*basecolfunc) (void); -extern void (*tlcolfunc) (void); -extern void (*spanfunc) (void); - -int R_PointOnSide(fixed_t x, fixed_t y, node_t * node); -int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line); -angle_t R_PointToAngle(fixed_t x, fixed_t y); -angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); -fixed_t R_PointToDist(fixed_t x, fixed_t y); -fixed_t R_ScaleFromGlobalAngle(angle_t visangle); -subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); -void R_AddPointToBox(int x, int y, fixed_t * box); -void R_ExecuteSetViewSize(void); - - -// -// R_bsp.c -// -extern seg_t *curline; -extern side_t *sidedef; -extern line_t *linedef; -extern sector_t *frontsector, *backsector; - -extern int rw_x; -extern int rw_stopx; - -extern boolean segtextured; -extern boolean markfloor; // false if the back side is the same plane -extern boolean markceiling; -extern boolean skymap; - -extern drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; - -extern lighttable_t **hscalelight, **vscalelight, **dscalelight; - -typedef void (*drawfunc_t) (int start, int stop); -void R_ClearClipSegs(void); - -void R_ClearDrawSegs(void); -void R_InitSkyMap(void); -void R_RenderBSPNode(int bspnum); - -// -// R_segs.c -// -extern int rw_angle1; // angle to line origin -extern lighttable_t **walllights; - - -void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2); - - -// -// R_plane.c -// -typedef void (*planefunction_t) (int top, int bottom); -extern planefunction_t floorfunc, ceilingfunc; - -extern int skyflatnum; - -extern short openings[MAXOPENINGS], *lastopening; - -extern short floorclip[SCREENWIDTH]; -extern short ceilingclip[SCREENWIDTH]; - -extern fixed_t yslope[SCREENHEIGHT]; -extern fixed_t distscale[SCREENWIDTH]; - -void R_InitPlanes(void); -void R_ClearPlanes(void); -void R_MapPlane(int y, int x1, int x2); -void R_MakeSpans(int x, int t1, int b1, int t2, int b2); -void R_DrawPlanes(void); - -visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel, - int special); -visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop); - - -// -// R_debug.m -// -extern int drawbsp; - -// -// R_data.c -// -extern fixed_t *textureheight; // needed for texture pegging -extern fixed_t *spritewidth; // needed for pre rendering (fracs) -extern fixed_t *spriteoffset; -extern fixed_t *spritetopoffset; -extern lighttable_t *colormaps; -extern int firstflat; -extern int numflats; - -extern int *flattranslation; // for global animation -extern int *texturetranslation; // for global animation - -extern int firstspritelump, lastspritelump, numspritelumps; - -extern int columnofs[MAXWIDTH]; - - -byte *R_GetColumn(int tex, int col); -void R_InitData(void); -void R_PrecacheLevel(void); - - -// -// R_things.c -// -#define MAXVISSPRITES 128 - -extern vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; -extern vissprite_t vsprsortedhead; - -// constant arrays used for psprite clipping and initializing clipping -extern short negonearray[SCREENWIDTH]; -extern short screenheightarray[SCREENWIDTH]; - -// vars for R_DrawMaskedColumn -extern short *mfloorclip; -extern short *mceilingclip; -extern fixed_t spryscale; -extern fixed_t sprtopscreen; -extern fixed_t sprbotscreen; - -extern fixed_t pspritescale, pspriteiscale; - - -void R_DrawMaskedColumn(column_t * column, signed int baseclip); - - -void R_SortVisSprites(void); - -void R_AddSprites(sector_t * sec); -void R_AddPSprites(void); -void R_DrawSprites(void); -void R_InitSprites(const char **namelist); -void R_ClearSprites(void); -void R_DrawMasked(void); -void R_ClipVisSprite(vissprite_t * vis, int xl, int xh); - -//============================================================================= -// -// R_draw.c -// -//============================================================================= - -extern lighttable_t *dc_colormap; -extern int dc_x; -extern int dc_yl; -extern int dc_yh; -extern fixed_t dc_iscale; -extern fixed_t dc_texturemid; -extern byte *dc_source; // first pixel in a column -extern byte *ylookup[MAXHEIGHT]; - - -void R_DrawColumn(void); -void R_DrawColumnLow(void); -void R_DrawTLColumn(void); -void R_DrawTLColumnLow(void); -void R_DrawTranslatedColumn(void); -void R_DrawTranslatedTLColumn(void); -void R_DrawTranslatedColumnLow(void); - -extern int ds_y; -extern int ds_x1; -extern int ds_x2; -extern lighttable_t *ds_colormap; -extern fixed_t ds_xfrac; -extern fixed_t ds_yfrac; -extern fixed_t ds_xstep; -extern fixed_t ds_ystep; -extern byte *ds_source; // start of a 64*64 tile image - -extern byte *translationtables; -extern byte *dc_translation; - -void R_DrawSpan(void); -void R_DrawSpanLow(void); - -void R_InitBuffer(int width, int height); -void R_InitTranslationTables(void); - -#endif // __R_LOCAL__ diff --git a/games/NXDoom/src/heretic/r_main.c b/games/NXDoom/src/heretic/r_main.c deleted file mode 100644 index 1ff6a68d882..00000000000 --- a/games/NXDoom/src/heretic/r_main.c +++ /dev/null @@ -1,818 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// R_main.c - -#include -#include -#include "doomdef.h" -#include "m_bbox.h" -#include "r_local.h" -#include "tables.h" - -int viewangleoffset; - -// haleyjd: removed WATCOMC - -int validcount = 1; // increment every time a check is made - -lighttable_t *fixedcolormap; - -int centerx, centery; -fixed_t centerxfrac, centeryfrac; -fixed_t projection; - -int framecount; // just for profiling purposes - -int sscount, linecount, loopcount; - -fixed_t viewx, viewy, viewz; -angle_t viewangle; -fixed_t viewcos, viewsin; -player_t *viewplayer; - -int detailshift; // 0 = high, 1 = low - -// -// precalculated math tables -// -angle_t clipangle; - -// The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view -// angles to screen X coordinates, flattening the arc to a flat projection -// plane. There will be many angles mapped to the same X. -int viewangletox[FINEANGLES / 2]; - -// The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle -// that maps back to x ranges from clipangle to -clipangle -angle_t xtoviewangle[SCREENWIDTH + 1]; - -lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; -lighttable_t *scalelightfixed[MAXLIGHTSCALE]; -lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; - -int extralight; // bumped light from gun blasts - -void (*colfunc) (void); -void (*basecolfunc) (void); -void (*tlcolfunc) (void); -void (*transcolfunc) (void); -void (*spanfunc) (void); - -/* -=================== -= -= R_AddPointToBox -= -=================== -*/ - -void R_AddPointToBox(int x, int y, fixed_t * box) -{ - if (x < box[BOXLEFT]) - box[BOXLEFT] = x; - if (x > box[BOXRIGHT]) - box[BOXRIGHT] = x; - if (y < box[BOXBOTTOM]) - box[BOXBOTTOM] = y; - if (y > box[BOXTOP]) - box[BOXTOP] = y; -} - - - -/* -=============================================================================== -= -= R_PointOnSide -= -= Returns side 0 (front) or 1 (back) -=============================================================================== -*/ - -int R_PointOnSide(fixed_t x, fixed_t y, node_t * node) -{ - fixed_t dx, dy; - fixed_t left, right; - - if (!node->dx) - { - if (x <= node->x) - return node->dy > 0; - return node->dy < 0; - } - if (!node->dy) - { - if (y <= node->y) - return node->dx < 0; - return node->dx > 0; - } - - dx = (x - node->x); - dy = (y - node->y); - -// try to quickly decide by looking at sign bits - if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) - { - if ((node->dy ^ dx) & 0x80000000) - return 1; // (left is negative) - return 0; - } - - left = FixedMul(node->dy >> FRACBITS, dx); - right = FixedMul(dy, node->dx >> FRACBITS); - - if (right < left) - return 0; // front side - return 1; // back side -} - - -int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line) -{ - fixed_t lx, ly; - fixed_t ldx, ldy; - fixed_t dx, dy; - fixed_t left, right; - - lx = line->v1->x; - ly = line->v1->y; - - ldx = line->v2->x - lx; - ldy = line->v2->y - ly; - - if (!ldx) - { - if (x <= lx) - return ldy > 0; - return ldy < 0; - } - if (!ldy) - { - if (y <= ly) - return ldx < 0; - return ldx > 0; - } - - dx = (x - lx); - dy = (y - ly); - -// try to quickly decide by looking at sign bits - if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) - { - if ((ldy ^ dx) & 0x80000000) - return 1; // (left is negative) - return 0; - } - - left = FixedMul(ldy >> FRACBITS, dx); - right = FixedMul(dy, ldx >> FRACBITS); - - if (right < left) - return 0; // front side - return 1; // back side -} - - -/* -=============================================================================== -= -= R_PointToAngle -= -=============================================================================== -*/ - -angle_t R_PointToAngle(fixed_t x, fixed_t y) -{ - x -= viewx; - y -= viewy; - if ((!x) && (!y)) - return 0; - if (x >= 0) - { // x >=0 - if (y >= 0) - { // y>= 0 - if (x > y) - return tantoangle[SlopeDiv(y, x)]; // octant 0 - else - return ANG90 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 1 - } - else - { // y<0 - y = -y; - if (x > y) - return -tantoangle[SlopeDiv(y, x)]; // octant 8 - else - return ANG270 + tantoangle[SlopeDiv(x, y)]; // octant 7 - } - } - else - { // x<0 - x = -x; - if (y >= 0) - { // y>= 0 - if (x > y) - return ANG180 - 1 - tantoangle[SlopeDiv(y, x)]; // octant 3 - else - return ANG90 + tantoangle[SlopeDiv(x, y)]; // octant 2 - } - else - { // y<0 - y = -y; - if (x > y) - return ANG180 + tantoangle[SlopeDiv(y, x)]; // octant 4 - else - return ANG270 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 5 - } - } - - return 0; -} - - -angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) -{ - viewx = x1; - viewy = y1; - return R_PointToAngle(x2, y2); -} - - -fixed_t R_PointToDist(fixed_t x, fixed_t y) -{ - int angle; - fixed_t dx, dy, temp; - fixed_t dist; - - dx = abs(x - viewx); - dy = abs(y - viewy); - - if (dy > dx) - { - temp = dx; - dx = dy; - dy = temp; - } - - angle = - (tantoangle[FixedDiv(dy, dx) >> DBITS] + ANG90) >> ANGLETOFINESHIFT; - - dist = FixedDiv(dx, finesine[angle]); // use as cosine - - return dist; -} - - - -/* -================= -= -= R_InitPointToAngle -= -================= -*/ - -void R_InitPointToAngle(void) -{ -// now getting from tables.c -#if 0 - int i; - long t; - float f; -// -// slope (tangent) to angle lookup -// - for (i = 0; i <= SLOPERANGE; i++) - { - f = atan((float) i / SLOPERANGE) / (3.141592657 * 2); - t = 0xffffffff * f; - tantoangle[i] = t; - } -#endif -} - -//============================================================================= - -/* -================ -= -= R_ScaleFromGlobalAngle -= -= Returns the texture mapping scale for the current line at the given angle -= rw_distance must be calculated first -================ -*/ - -fixed_t R_ScaleFromGlobalAngle(angle_t visangle) -{ - fixed_t scale; - int anglea, angleb; - int sinea, sineb; - fixed_t num, den; - -#if 0 - { - fixed_t dist, z; - fixed_t sinv, cosv; - - sinv = finesine[(visangle - rw_normalangle) >> ANGLETOFINESHIFT]; - dist = FixedDiv(rw_distance, sinv); - cosv = finecosine[(viewangle - visangle) >> ANGLETOFINESHIFT]; - z = abs(FixedMul(dist, cosv)); - scale = FixedDiv(projection, z); - return scale; - } -#endif - - anglea = ANG90 + (visangle - viewangle); - angleb = ANG90 + (visangle - rw_normalangle); -// bothe sines are allways positive - sinea = finesine[anglea >> ANGLETOFINESHIFT]; - sineb = finesine[angleb >> ANGLETOFINESHIFT]; - num = FixedMul(projection, sineb) << detailshift; - den = FixedMul(rw_distance, sinea); - if (den > num >> 16) - { - scale = FixedDiv(num, den); - if (scale > 64 * FRACUNIT) - scale = 64 * FRACUNIT; - else if (scale < 256) - scale = 256; - } - else - scale = 64 * FRACUNIT; - - return scale; -} - - - -/* -================= -= -= R_InitTables -= -================= -*/ - -void R_InitTables(void) -{ -// now getting from tables.c -#if 0 - int i; - float a, fv; - int t; - -// -// viewangle tangent table -// - for (i = 0; i < FINEANGLES / 2; i++) - { - a = (i - FINEANGLES / 4 + 0.5) * PI * 2 / FINEANGLES; - fv = FRACUNIT * tan(a); - t = fv; - finetangent[i] = t; - } - -// -// finesine table -// - for (i = 0; i < 5 * FINEANGLES / 4; i++) - { -// OPTIMIZE: mirror... - a = (i + 0.5) * PI * 2 / FINEANGLES; - t = FRACUNIT * sin(a); - finesine[i] = t; - } -#endif - -} - - -/* -================= -= -= R_InitTextureMapping -= -================= -*/ - -void R_InitTextureMapping(void) -{ - int i; - int x; - int t; - fixed_t focallength; - - -// -// use tangent table to generate viewangletox -// viewangletox will give the next greatest x after the view angle -// - // calc focallength so FIELDOFVIEW angles covers SCREENWIDTH - focallength = - FixedDiv(centerxfrac, finetangent[FINEANGLES / 4 + FIELDOFVIEW / 2]); - - for (i = 0; i < FINEANGLES / 2; i++) - { - if (finetangent[i] > FRACUNIT * 2) - t = -1; - else if (finetangent[i] < -FRACUNIT * 2) - t = viewwidth + 1; - else - { - t = FixedMul(finetangent[i], focallength); - t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS; - if (t < -1) - t = -1; - else if (t > viewwidth + 1) - t = viewwidth + 1; - } - viewangletox[i] = t; - } - -// -// scan viewangletox[] to generate xtoviewangleangle[] -// -// xtoviewangle will give the smallest view angle that maps to x - for (x = 0; x <= viewwidth; x++) - { - i = 0; - while (viewangletox[i] > x) - i++; - xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90; - } - -// -// take out the fencepost cases from viewangletox -// - for (i = 0; i < FINEANGLES / 2; i++) - { - t = FixedMul(finetangent[i], focallength); - t = centerx - t; - if (viewangletox[i] == -1) - viewangletox[i] = 0; - else if (viewangletox[i] == viewwidth + 1) - viewangletox[i] = viewwidth; - } - - clipangle = xtoviewangle[0]; -} - -//============================================================================= - -/* -==================== -= -= R_InitLightTables -= -= Only inits the zlight table, because the scalelight table changes -= with view size -= -==================== -*/ - -#define DISTMAP 2 - -void R_InitLightTables(void) -{ - int i, j, level, startmap; - int scale; - -// -// Calculate the light levels to use for each level / distance combination -// - for (i = 0; i < LIGHTLEVELS; i++) - { - startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; - for (j = 0; j < MAXLIGHTZ; j++) - { - scale = - FixedDiv((SCREENWIDTH / 2 * FRACUNIT), - (j + 1) << LIGHTZSHIFT); - scale >>= LIGHTSCALESHIFT; - level = startmap - scale / DISTMAP; - if (level < 0) - level = 0; - if (level >= NUMCOLORMAPS) - level = NUMCOLORMAPS - 1; - zlight[i][j] = colormaps + level * 256; - } - } -} - - -/* -============== -= -= R_SetViewSize -= -= Don't really change anything here, because i might be in the middle of -= a refresh. The change will take effect next refresh. -= -============== -*/ - -boolean setsizeneeded; -int setblocks, setdetail; - -void R_SetViewSize(int blocks, int detail) -{ - setsizeneeded = true; - setblocks = blocks; - setdetail = detail; -} - -/* -============== -= -= R_ExecuteSetViewSize -= -============== -*/ - -void R_ExecuteSetViewSize(void) -{ - fixed_t cosadj, dy; - int i, j, level, startmap; - - setsizeneeded = false; - - if (setblocks == 11) - { - scaledviewwidth = SCREENWIDTH; - viewheight = SCREENHEIGHT; - } - else - { - scaledviewwidth = setblocks * 32; - viewheight = (setblocks * 158 / 10); - } - - detailshift = setdetail; - viewwidth = scaledviewwidth >> detailshift; - - centery = viewheight / 2; - centerx = viewwidth / 2; - centerxfrac = centerx << FRACBITS; - centeryfrac = centery << FRACBITS; - projection = centerxfrac; - - if (!detailshift) - { - colfunc = basecolfunc = R_DrawColumn; - tlcolfunc = R_DrawTLColumn; - transcolfunc = R_DrawTranslatedColumn; - spanfunc = R_DrawSpan; - } - else - { - colfunc = basecolfunc = R_DrawColumnLow; - tlcolfunc = R_DrawTLColumn; - transcolfunc = R_DrawTranslatedColumn; - spanfunc = R_DrawSpanLow; - } - - R_InitBuffer(scaledviewwidth, viewheight); - - R_InitTextureMapping(); - -// -// psprite scales -// - pspritescale = FRACUNIT * viewwidth / SCREENWIDTH; - pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth; - -// -// thing clipping -// - for (i = 0; i < viewwidth; i++) - screenheightarray[i] = viewheight; - -// -// planes -// - for (i = 0; i < viewheight; i++) - { - dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; - dy = abs(dy); - yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, dy); - } - - for (i = 0; i < viewwidth; i++) - { - cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); - distscale[i] = FixedDiv(FRACUNIT, cosadj); - } - -// -// Calculate the light levels to use for each level / scale combination -// - for (i = 0; i < LIGHTLEVELS; i++) - { - startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; - for (j = 0; j < MAXLIGHTSCALE; j++) - { - level = - startmap - - j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP; - if (level < 0) - level = 0; - if (level >= NUMCOLORMAPS) - level = NUMCOLORMAPS - 1; - scalelight[i][j] = colormaps + level * 256; - } - } - -// -// draw the border -// - R_DrawViewBorder(); // erase old menu stuff -} - - -/* -============== -= -= R_Init -= -============== -*/ - -int detailLevel; -int screenblocks = 10; - -void R_Init(void) -{ - //tprintf("R_InitData ", 1); - R_InitData(); - printf ("."); - //tprintf("R_InitPointToAngle\n", 0); - R_InitPointToAngle(); - printf ("."); - //tprintf("R_InitTables ", 0); - R_InitTables(); - // viewwidth / viewheight / detailLevel are set by the defaults - printf ("."); - R_SetViewSize(screenblocks, detailLevel); - //tprintf("R_InitPlanes\n", 0); - R_InitPlanes(); - printf ("."); - //tprintf("R_InitLightTables ", 0); - R_InitLightTables(); - printf ("."); - //tprintf("R_InitSkyMap\n", 0); - R_InitSkyMap(); - printf ("."); - R_InitTranslationTables(); - framecount = 0; -} - - -/* -============== -= -= R_PointInSubsector -= -============== -*/ - -subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) -{ - node_t *node; - int side, nodenum; - - if (!numnodes) // single subsector is a special case - return subsectors; - - nodenum = numnodes - 1; - - while (!(nodenum & NF_SUBSECTOR)) - { - node = &nodes[nodenum]; - side = R_PointOnSide(x, y, node); - nodenum = node->children[side]; - } - - return &subsectors[nodenum & ~NF_SUBSECTOR]; - -} - -//---------------------------------------------------------------------------- -// -// PROC R_SetupFrame -// -//---------------------------------------------------------------------------- - -void R_SetupFrame(player_t * player) -{ - int i; - int tableAngle; - int tempCentery; - - //drawbsp = 1; - viewplayer = player; - // haleyjd: removed WATCOMC - // haleyjd FIXME: viewangleoffset handling? - viewangle = player->mo->angle + viewangleoffset; - tableAngle = viewangle >> ANGLETOFINESHIFT; - if (player->chickenTics && player->chickenPeck) - { // Set chicken attack view position - viewx = player->mo->x + player->chickenPeck * finecosine[tableAngle]; - viewy = player->mo->y + player->chickenPeck * finesine[tableAngle]; - } - else - { // Normal view position - viewx = player->mo->x; - viewy = player->mo->y; - } - extralight = player->extralight; - viewz = player->viewz; - - tempCentery = viewheight / 2 + (player->lookdir) * screenblocks / 10; - if (centery != tempCentery) - { - centery = tempCentery; - centeryfrac = centery << FRACBITS; - for (i = 0; i < viewheight; i++) - { - yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, - abs(((i - centery) << FRACBITS) + - FRACUNIT / 2)); - } - } - viewsin = finesine[tableAngle]; - viewcos = finecosine[tableAngle]; - sscount = 0; - if (player->fixedcolormap) - { - fixedcolormap = colormaps + player->fixedcolormap - * 256 * sizeof(lighttable_t); - walllights = scalelightfixed; - for (i = 0; i < MAXLIGHTSCALE; i++) - { - scalelightfixed[i] = fixedcolormap; - } - } - else - { - fixedcolormap = 0; - } - framecount++; - validcount++; - if (BorderNeedRefresh) - { - if (setblocks < 10) - { - R_DrawViewBorder(); - } - BorderNeedRefresh = false; - BorderTopRefresh = false; - UpdateState |= I_FULLSCRN; - } - if (BorderTopRefresh) - { - if (setblocks < 10) - { - R_DrawTopBorder(); - } - BorderTopRefresh = false; - UpdateState |= I_MESSAGES; - } -} - -/* -============== -= -= R_RenderView -= -============== -*/ - -void R_RenderPlayerView(player_t * player) -{ - R_SetupFrame(player); - R_ClearClipSegs(); - R_ClearDrawSegs(); - R_ClearPlanes(); - R_ClearSprites(); - NetUpdate(); // check for new console commands - R_RenderBSPNode(numnodes - 1); // the head node is the last node output - NetUpdate(); // check for new console commands - R_DrawPlanes(); - NetUpdate(); // check for new console commands - R_DrawMasked(); - NetUpdate(); // check for new console commands -} diff --git a/games/NXDoom/src/heretic/r_plane.c b/games/NXDoom/src/heretic/r_plane.c deleted file mode 100644 index e9ed70c760e..00000000000 --- a/games/NXDoom/src/heretic/r_plane.c +++ /dev/null @@ -1,511 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// R_planes.c - -#include -#include "doomdef.h" -#include "deh_str.h" -#include "i_system.h" -#include "r_local.h" - -planefunction_t floorfunc, ceilingfunc; - -// -// sky mapping -// -int skyflatnum; -int skytexture; -int skytexturemid; -fixed_t skyiscale; - -// -// opening -// - -visplane_t visplanes[MAXVISPLANES], *lastvisplane; -visplane_t *floorplane, *ceilingplane; - -short openings[MAXOPENINGS], *lastopening; - -// -// clip values are the solid pixel bounding the range -// floorclip starts out SCREENHEIGHT -// ceilingclip starts out -1 -// -short floorclip[SCREENWIDTH]; -short ceilingclip[SCREENWIDTH]; - -// -// spanstart holds the start of a plane span -// initialized to 0 at start -// -int spanstart[SCREENHEIGHT]; -int spanstop[SCREENHEIGHT]; - -// -// texture mapping -// -lighttable_t **planezlight; -fixed_t planeheight; - -fixed_t yslope[SCREENHEIGHT]; -fixed_t distscale[SCREENWIDTH]; -fixed_t basexscale, baseyscale; - -fixed_t cachedheight[SCREENHEIGHT]; -fixed_t cacheddistance[SCREENHEIGHT]; -fixed_t cachedxstep[SCREENHEIGHT]; -fixed_t cachedystep[SCREENHEIGHT]; - - -/* -================ -= -= R_InitSkyMap -= -= Called whenever the view size changes -= -================ -*/ - -void R_InitSkyMap(void) -{ - skyflatnum = R_FlatNumForName(DEH_String("F_SKY1")); - skytexturemid = 200 * FRACUNIT; - skyiscale = FRACUNIT; -} - - -/* -==================== -= -= R_InitPlanes -= -= Only at game startup -==================== -*/ - -void R_InitPlanes(void) -{ -} - - -/* -================ -= -= R_MapPlane -= -global vars: - -planeheight -ds_source -basexscale -baseyscale -viewx -viewy - -BASIC PRIMITIVE -================ -*/ - -void R_MapPlane(int y, int x1, int x2) -{ - angle_t angle; - fixed_t distance, length; - unsigned index; - -#ifdef RANGECHECK - if (x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned) y > viewheight) - I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); -#endif - - if (planeheight != cachedheight[y]) - { - cachedheight[y] = planeheight; - distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); - - ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); - ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); - } - else - { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; - } - - length = FixedMul(distance, distscale[x1]); - angle = (viewangle + xtoviewangle[x1]) >> ANGLETOFINESHIFT; - ds_xfrac = viewx + FixedMul(finecosine[angle], length); - ds_yfrac = -viewy - FixedMul(finesine[angle], length); - - if (fixedcolormap) - ds_colormap = fixedcolormap; - else - { - index = distance >> LIGHTZSHIFT; - if (index >= MAXLIGHTZ) - index = MAXLIGHTZ - 1; - ds_colormap = planezlight[index]; - } - - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; - - spanfunc(); // high or low detail -} - -//============================================================================= - -/* -==================== -= -= R_ClearPlanes -= -= At begining of frame -==================== -*/ - -void R_ClearPlanes(void) -{ - int i; - angle_t angle; - -// -// opening / clipping determination -// - for (i = 0; i < viewwidth; i++) - { - floorclip[i] = viewheight; - ceilingclip[i] = -1; - } - - lastvisplane = visplanes; - lastopening = openings; - -// -// texture calculation -// - memset(cachedheight, 0, sizeof(cachedheight)); - angle = (viewangle - ANG90) >> ANGLETOFINESHIFT; // left to right mapping - - // scale will be unit scale at SCREENWIDTH/2 distance - basexscale = FixedDiv(finecosine[angle], centerxfrac); - baseyscale = -FixedDiv(finesine[angle], centerxfrac); -} - - - -/* -=============== -= -= R_FindPlane -= -=============== -*/ - -visplane_t *R_FindPlane(fixed_t height, int picnum, - int lightlevel, int special) -{ - visplane_t *check; - - if (picnum == skyflatnum) - { - // all skies map together - height = 0; - lightlevel = 0; - } - - for (check = visplanes; check < lastvisplane; check++) - { - if (height == check->height - && picnum == check->picnum - && lightlevel == check->lightlevel && special == check->special) - break; - } - - if (check < lastvisplane) - { - return (check); - } - - if (lastvisplane - visplanes == MAXVISPLANES) - { - I_Error("R_FindPlane: no more visplanes"); - } - - lastvisplane++; - check->height = height; - check->picnum = picnum; - check->lightlevel = lightlevel; - check->special = special; - check->minx = SCREENWIDTH; - check->maxx = -1; - memset(check->top, 0xff, sizeof(check->top)); - return (check); -} - -/* -=============== -= -= R_CheckPlane -= -=============== -*/ - -visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop) -{ - int intrl, intrh; - int unionl, unionh; - int x; - - if (start < pl->minx) - { - intrl = pl->minx; - unionl = start; - } - else - { - unionl = pl->minx; - intrl = start; - } - - if (stop > pl->maxx) - { - intrh = pl->maxx; - unionh = stop; - } - else - { - unionh = pl->maxx; - intrh = stop; - } - - for (x = intrl; x <= intrh; x++) - if (pl->top[x] != 0xff) - break; - - if (x > intrh) - { - pl->minx = unionl; - pl->maxx = unionh; - return pl; // use the same one - } - -// make a new visplane - - lastvisplane->height = pl->height; - lastvisplane->picnum = pl->picnum; - lastvisplane->lightlevel = pl->lightlevel; - lastvisplane->special = pl->special; - pl = lastvisplane++; - pl->minx = start; - pl->maxx = stop; - memset(pl->top, 0xff, sizeof(pl->top)); - - return pl; -} - - - -//============================================================================= - -/* -================ -= -= R_MakeSpans -= -================ -*/ - -void R_MakeSpans(int x, int t1, int b1, int t2, int b2) -{ - while (t1 < t2 && t1 <= b1) - { - R_MapPlane(t1, spanstart[t1], x - 1); - t1++; - } - while (b1 > b2 && b1 >= t1) - { - R_MapPlane(b1, spanstart[b1], x - 1); - b1--; - } - - while (t2 < t1 && t2 <= b2) - { - spanstart[t2] = x; - t2++; - } - while (b2 > b1 && b2 >= t2) - { - spanstart[b2] = x; - b2--; - } -} - - - -/* -================ -= -= R_DrawPlanes -= -= At the end of each frame -================ -*/ - -void R_DrawPlanes(void) -{ - visplane_t *pl; - int light; - int x, stop; - int lumpnum; - int angle; - byte *tempSource; - - byte *dest; - int count; - fixed_t frac, fracstep; - -#ifdef RANGECHECK - if (ds_p - drawsegs > MAXDRAWSEGS) - I_Error("R_DrawPlanes: drawsegs overflow (%td)", - ds_p - drawsegs); - if (lastvisplane - visplanes > MAXVISPLANES) - I_Error("R_DrawPlanes: visplane overflow (%td)", - lastvisplane - visplanes); - if (lastopening - openings > MAXOPENINGS) - I_Error("R_DrawPlanes: opening overflow (%td)", - lastopening - openings); -#endif - - for (pl = visplanes; pl < lastvisplane; pl++) - { - if (pl->minx > pl->maxx) - continue; - // - // sky flat - // - if (pl->picnum == skyflatnum) - { - dc_iscale = skyiscale; - dc_colormap = colormaps; // sky is allways drawn full bright - dc_texturemid = skytexturemid; - for (x = pl->minx; x <= pl->maxx; x++) - { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; - if (dc_yl <= dc_yh) - { - angle = (viewangle + xtoviewangle[x]) >> ANGLETOSKYSHIFT; - dc_x = x; - dc_source = R_GetColumn(skytexture, angle); - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, - dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = 1; - frac = (dc_texturemid >> FRACBITS) + (dc_yl - centery); - do - { - *dest = dc_source[frac]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); - -// colfunc (); - } - } - continue; - } - - // - // regular flat - // - lumpnum = firstflat + flattranslation[pl->picnum]; - - tempSource = W_CacheLumpNum(lumpnum, PU_STATIC); - - switch (pl->special) - { - case 25: - case 26: - case 27: - case 28: - case 29: // Scroll_North - ds_source = tempSource; - break; - case 20: - case 21: - case 22: - case 23: - case 24: // Scroll_East - ds_source = tempSource + ((63 - ((leveltime >> 1) & 63)) << - (pl->special - 20) & 63); - //ds_source = tempSource+((leveltime>>1)&63); - break; - case 30: - case 31: - case 32: - case 33: - case 34: // Scroll_South - ds_source = tempSource; - break; - case 35: - case 36: - case 37: - case 38: - case 39: // Scroll_West - ds_source = tempSource; - break; - case 4: // Scroll_EastLavaDamage - ds_source = - tempSource + (((63 - ((leveltime >> 1) & 63)) << 3) & 63); - break; - default: - ds_source = tempSource; - } - planeheight = abs(pl->height - viewz); - light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (light >= LIGHTLEVELS) - light = LIGHTLEVELS - 1; - if (light < 0) - light = 0; - planezlight = zlight[light]; - - pl->top[pl->maxx + 1] = 0xff; - pl->top[pl->minx - 1] = 0xff; - - stop = pl->maxx + 1; - for (x = pl->minx; x <= stop; x++) - R_MakeSpans(x, pl->top[x - 1], pl->bottom[x - 1], pl->top[x], - pl->bottom[x]); - - W_ReleaseLumpNum(lumpnum); - } -} diff --git a/games/NXDoom/src/heretic/r_segs.c b/games/NXDoom/src/heretic/r_segs.c deleted file mode 100644 index b37c94d6c6d..00000000000 --- a/games/NXDoom/src/heretic/r_segs.c +++ /dev/null @@ -1,661 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -//************************************************************************** -//** -//** R_SEGS.C -//** -//** This version has the tall-sector-crossing-precision-bug fixed. -//** -//************************************************************************** - -#include - -#include "doomdef.h" -#include "r_local.h" - -// OPTIMIZE: closed two sided lines as single sided - -boolean segtextured; // true if any of the segs textures might be vis -boolean markfloor; // false if the back side is the same plane -boolean markceiling; -boolean maskedtexture; -int toptexture, bottomtexture, midtexture; - - -angle_t rw_normalangle; -int rw_angle1; // angle to line origin - -// -// wall -// -int rw_x; -int rw_stopx; -angle_t rw_centerangle; -fixed_t rw_offset; -fixed_t rw_distance; -fixed_t rw_scale; -fixed_t rw_scalestep; -fixed_t rw_midtexturemid; -fixed_t rw_toptexturemid; -fixed_t rw_bottomtexturemid; - -int worldtop, worldbottom, worldhigh, worldlow; - -fixed_t pixhigh, pixlow; -fixed_t pixhighstep, pixlowstep; -fixed_t topfrac, topstep; -fixed_t bottomfrac, bottomstep; - - -lighttable_t **walllights; - -short *maskedtexturecol; - -/* -================ -= -= R_RenderMaskedSegRange -= -================ -*/ - -void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2) -{ - unsigned index; - column_t *col; - int lightnum; - int texnum; - -// -// calculate light table -// use different light tables for horizontal / vertical / diagonal -// OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; - frontsector = curline->frontsector; - backsector = curline->backsector; - texnum = texturetranslation[curline->sidedef->midtexture]; - - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS - 1]; - else - walllights = scalelight[lightnum]; - - maskedtexturecol = ds->maskedtexturecol; - - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1) * rw_scalestep; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; - -// -// find positioning -// - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - { - dc_texturemid = frontsector->floorheight > backsector->floorheight - ? frontsector->floorheight : backsector->floorheight; - dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; - } - else - { - dc_texturemid = frontsector->ceilingheight < backsector->ceilingheight - ? frontsector->ceilingheight : backsector->ceilingheight; - dc_texturemid = dc_texturemid - viewz; - } - dc_texturemid += curline->sidedef->rowoffset; - - if (fixedcolormap) - dc_colormap = fixedcolormap; -// -// draw the columns -// - for (dc_x = x1; dc_x <= x2; dc_x++) - { - // calculate lighting - if (maskedtexturecol[dc_x] != SHRT_MAX) - { - if (!fixedcolormap) - { - index = spryscale >> LIGHTSCALESHIFT; - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE - 1; - dc_colormap = walllights[index]; - } - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned) spryscale; - - // - // draw the texture - // - col = (column_t *) ((byte *) - R_GetColumn(texnum, - maskedtexturecol[dc_x]) - 3); - - R_DrawMaskedColumn(col, -1); - maskedtexturecol[dc_x] = SHRT_MAX; - } - spryscale += rw_scalestep; - } - -} - -/* -================ -= -= R_RenderSegLoop -= -= Draws zero, one, or two textures (and possibly a masked texture) for walls -= Can draw or mark the starting pixel of floor and ceiling textures -= -= CALLED: CORE LOOPING ROUTINE -================ -*/ - -#define HEIGHTBITS 12 -#define HEIGHTUNIT (1<> HEIGHTBITS; - if (yl < ceilingclip[rw_x] + 1) - yl = ceilingclip[rw_x] + 1; // no space above wall - if (markceiling) - { - top = ceilingclip[rw_x] + 1; - bottom = yl - 1; - if (bottom >= floorclip[rw_x]) - bottom = floorclip[rw_x] - 1; - if (top <= bottom) - { - ceilingplane->top[rw_x] = top; - ceilingplane->bottom[rw_x] = bottom; - } - } - - yh = bottomfrac >> HEIGHTBITS; - if (yh >= floorclip[rw_x]) - yh = floorclip[rw_x] - 1; - if (markfloor) - { - top = yh + 1; - bottom = floorclip[rw_x] - 1; - if (top <= ceilingclip[rw_x]) - top = ceilingclip[rw_x] + 1; - if (top <= bottom) - { - floorplane->top[rw_x] = top; - floorplane->bottom[rw_x] = bottom; - } - } - -// -// texturecolumn and lighting are independent of wall tiers -// - if (segtextured) - { - // calculate texture offset - angle = (rw_centerangle + xtoviewangle[rw_x]) >> ANGLETOFINESHIFT; - texturecolumn = - rw_offset - FixedMul(finetangent[angle], rw_distance); - texturecolumn >>= FRACBITS; - // calculate lighting - index = rw_scale >> LIGHTSCALESHIFT; - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE - 1; - dc_colormap = walllights[index]; - dc_x = rw_x; - dc_iscale = 0xffffffffu / (unsigned) rw_scale; - } - -// -// draw the wall tiers -// - if (midtexture) - { // single sided line - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture, texturecolumn); - colfunc(); - ceilingclip[rw_x] = viewheight; - floorclip[rw_x] = -1; - } - else - { // two sided line - if (toptexture) - { // top wall - mid = pixhigh >> HEIGHTBITS; - pixhigh += pixhighstep; - if (mid >= floorclip[rw_x]) - mid = floorclip[rw_x] - 1; - if (mid >= yl) - { - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture, texturecolumn); - colfunc(); - ceilingclip[rw_x] = mid; - } - else - ceilingclip[rw_x] = yl - 1; - } - else - { // no top wall - if (markceiling) - ceilingclip[rw_x] = yl - 1; - } - - if (bottomtexture) - { // bottom wall - mid = (pixlow + HEIGHTUNIT - 1) >> HEIGHTBITS; - pixlow += pixlowstep; - if (mid <= ceilingclip[rw_x]) - mid = ceilingclip[rw_x] + 1; // no space above wall - if (mid <= yh) - { - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, texturecolumn); - colfunc(); - floorclip[rw_x] = mid; - } - else - floorclip[rw_x] = yh + 1; - } - else - { // no bottom wall - if (markfloor) - floorclip[rw_x] = yh + 1; - } - - if (maskedtexture) - { // save texturecol for backdrawing of masked mid texture - maskedtexturecol[rw_x] = texturecolumn; - } - } - - rw_scale += rw_scalestep; - topfrac += topstep; - bottomfrac += bottomstep; - } - -} - - - -/* -===================== -= -= R_StoreWallRange -= -= A wall segment will be drawn between start and stop pixels (inclusive) -= -====================== -*/ - -void R_StoreWallRange(int start, int stop) -{ - fixed_t hyp; - fixed_t sineval; - angle_t distangle, offsetangle; - fixed_t vtop; - int lightnum; - - if (ds_p == &drawsegs[MAXDRAWSEGS]) - return; // don't overflow and crash - -#ifdef RANGECHECK - if (start >= viewwidth || start > stop) - I_Error("Bad R_RenderWallRange: %i to %i", start, stop); -#endif - - sidedef = curline->sidedef; - linedef = curline->linedef; - -// mark the segment as visible for auto map - linedef->flags |= ML_MAPPED; - -// -// calculate rw_distance for scale calculation -// - rw_normalangle = curline->angle + ANG90; - offsetangle = abs((int) rw_normalangle - (int) rw_angle1); - if (offsetangle > ANG90) - offsetangle = ANG90; - distangle = ANG90 - offsetangle; - hyp = R_PointToDist(curline->v1->x, curline->v1->y); - sineval = finesine[distangle >> ANGLETOFINESHIFT]; - rw_distance = FixedMul(hyp, sineval); - - - ds_p->x1 = rw_x = start; - ds_p->x2 = stop; - ds_p->curline = curline; - rw_stopx = stop + 1; - -// -// calculate scale at both ends and step -// - ds_p->scale1 = rw_scale = - R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); - if (stop > start) - { - ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); - ds_p->scalestep = rw_scalestep = - (ds_p->scale2 - rw_scale) / (stop - start); - } - else - { - // - // try to fix the stretched line bug - // -#if 0 - if (rw_distance < FRACUNIT / 2) - { - fixed_t trx, try; - fixed_t gxt, gyt; - - trx = curline->v1->x - viewx; - try = curline->v1->y - viewy; - - gxt = FixedMul(trx, viewcos); - gyt = -FixedMul(try, viewsin); - ds_p->scale1 = FixedDiv(projection, gxt - gyt); - } -#endif - ds_p->scale2 = ds_p->scale1; - } - - -// -// calculate texture boundaries and decide if floor / ceiling marks -// are needed -// - worldtop = frontsector->ceilingheight - viewz; - worldbottom = frontsector->floorheight - viewz; - - midtexture = toptexture = bottomtexture = maskedtexture = 0; - ds_p->maskedtexturecol = NULL; - - if (!backsector) - { -// -// single sided line -// - midtexture = texturetranslation[sidedef->midtexture]; - // a single sided line is terminal, so it must mark ends - markfloor = markceiling = true; - if (linedef->flags & ML_DONTPEGBOTTOM) - { - vtop = frontsector->floorheight + - textureheight[sidedef->midtexture]; - rw_midtexturemid = vtop - viewz; // bottom of texture at bottom - } - else - rw_midtexturemid = worldtop; // top of texture at top - rw_midtexturemid += sidedef->rowoffset; - ds_p->silhouette = SIL_BOTH; - ds_p->sprtopclip = screenheightarray; - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->tsilheight = INT_MIN; - } - else - { -// -// two sided line -// - ds_p->sprtopclip = ds_p->sprbottomclip = NULL; - ds_p->silhouette = 0; - if (frontsector->floorheight > backsector->floorheight) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = frontsector->floorheight; - } - else if (backsector->floorheight > viewz) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; -// ds_p->sprbottomclip = negonearray; - } - if (frontsector->ceilingheight < backsector->ceilingheight) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = frontsector->ceilingheight; - } - else if (backsector->ceilingheight < viewz) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; -// ds_p->sprtopclip = screenheightarray; - } - - if (backsector->ceilingheight <= frontsector->floorheight) - { - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->silhouette |= SIL_BOTTOM; - } - if (backsector->floorheight >= frontsector->ceilingheight) - { - ds_p->sprtopclip = screenheightarray; - ds_p->tsilheight = INT_MIN; - ds_p->silhouette |= SIL_TOP; - } - worldhigh = backsector->ceilingheight - viewz; - worldlow = backsector->floorheight - viewz; - - // hack to allow height changes in outdoor areas - if (frontsector->ceilingpic == skyflatnum - && backsector->ceilingpic == skyflatnum) - worldtop = worldhigh; - - if (worldlow != worldbottom - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel) - markfloor = true; - else - markfloor = false; // same plane on both sides - - if (worldhigh != worldtop - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel) - markceiling = true; - else - markceiling = false; // same plane on both sides - - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - markceiling = markfloor = true; // closed door - - if (worldhigh < worldtop) - { // top texture - toptexture = texturetranslation[sidedef->toptexture]; - if (linedef->flags & ML_DONTPEGTOP) - rw_toptexturemid = worldtop; // top of texture at top - else - { - vtop = backsector->ceilingheight + - textureheight[sidedef->toptexture]; - rw_toptexturemid = vtop - viewz; // bottom of texture - } - } - if (worldlow > worldbottom) - { // bottom texture - bottomtexture = texturetranslation[sidedef->bottomtexture]; - if (linedef->flags & ML_DONTPEGBOTTOM) - { // bottom of texture at bottom - rw_bottomtexturemid = worldtop; // top of texture at top - } - else // top of texture at top - rw_bottomtexturemid = worldlow; - } - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; - - // - // allocate space for masked texture tables - // - if (sidedef->midtexture) - { // masked midtexture - maskedtexture = true; - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; - } - } - -// -// calculate rw_offset (only needed for textured lines) -// - segtextured = midtexture | toptexture | bottomtexture | maskedtexture; - - if (segtextured) - { - offsetangle = rw_normalangle - rw_angle1; - if (offsetangle > ANG180) - offsetangle = -offsetangle; - if (offsetangle > ANG90) - offsetangle = ANG90; - sineval = finesine[offsetangle >> ANGLETOFINESHIFT]; - rw_offset = FixedMul(hyp, sineval); - if (rw_normalangle - rw_angle1 < ANG180) - rw_offset = -rw_offset; - rw_offset += sidedef->textureoffset + curline->offset; - rw_centerangle = ANG90 + viewangle - rw_normalangle; - - // - // calculate light table - // use different light tables for horizontal / vertical / diagonal - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - if (!fixedcolormap) - { - lightnum = - (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS - 1]; - else - walllights = scalelight[lightnum]; - } - } - - -// -// if a floor / ceiling plane is on the wrong side of the view plane -// it is definately invisible and doesn't need to be marked -// - if (frontsector->floorheight >= viewz) - markfloor = false; // above view plane - if (frontsector->ceilingheight <= viewz - && frontsector->ceilingpic != skyflatnum) - markceiling = false; // below view plane - -// -// calculate incremental stepping values for texture edges -// - worldtop >>= 4; - worldbottom >>= 4; - - topstep = -FixedMul(rw_scalestep, worldtop); - topfrac = (centeryfrac >> 4) - FixedMul(worldtop, rw_scale); - - bottomstep = -FixedMul(rw_scalestep, worldbottom); - bottomfrac = (centeryfrac >> 4) - FixedMul(worldbottom, rw_scale); - - if (backsector) - { - worldhigh >>= 4; - worldlow >>= 4; - - if (worldhigh < worldtop) - { - pixhigh = (centeryfrac >> 4) - FixedMul(worldhigh, rw_scale); - pixhighstep = -FixedMul(rw_scalestep, worldhigh); - } - if (worldlow > worldbottom) - { - pixlow = (centeryfrac >> 4) - FixedMul(worldlow, rw_scale); - pixlowstep = -FixedMul(rw_scalestep, worldlow); - } - } - -// -// render it -// - if (markceiling) - ceilingplane = R_CheckPlane(ceilingplane, rw_x, rw_stopx - 1); - if (markfloor) - floorplane = R_CheckPlane(floorplane, rw_x, rw_stopx - 1); - - R_RenderSegLoop(); - -// -// save sprite clipping info -// - if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) - { - memcpy(lastopening, ceilingclip + start, 2 * (rw_stopx - start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } - if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) - && !ds_p->sprbottomclip) - { - memcpy(lastopening, floorclip + start, 2 * (rw_stopx - start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; - } - if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; - } - if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) - { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; - } - ds_p++; -} diff --git a/games/NXDoom/src/heretic/r_things.c b/games/NXDoom/src/heretic/r_things.c deleted file mode 100644 index 88e35b9bc1b..00000000000 --- a/games/NXDoom/src/heretic/r_things.c +++ /dev/null @@ -1,1017 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// R_things.c -#include -#include -#include "doomdef.h" -#include "deh_str.h" -#include "i_swap.h" -#include "i_system.h" -#include "r_local.h" - -typedef struct -{ - int x1, x2; - - int column; - int topclip; - int bottomclip; -} maskdraw_t; - -/* - -Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis. -This is not the same as the angle, which increases counter clockwise -(protractor). There was a lot of stuff grabbed wrong, so I changed it... - -*/ - - -fixed_t pspritescale, pspriteiscale; - -lighttable_t **spritelights; - -// constant arrays used for psprite clipping and initializing clipping -short negonearray[SCREENWIDTH]; -short screenheightarray[SCREENWIDTH]; - -/* -=============================================================================== - - INITIALIZATION FUNCTIONS - -=============================================================================== -*/ - -// variables used to look up and range check thing_t sprites patches -spritedef_t *sprites; -int numsprites; - -spriteframe_t sprtemp[26]; -int maxframe; -const char *spritename; - - - -/* -================= -= -= R_InstallSpriteLump -= -= Local function for R_InitSprites -================= -*/ - -void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, - boolean flipped) -{ - int r; - - if (frame >= 26 || rotation > 8) - I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); - - if ((int) frame > maxframe) - maxframe = frame; - - if (rotation == 0) - { -// the lump should be used for all rotations - if (sprtemp[frame].rotate == false) - I_Error("R_InitSprites: Sprite %s frame %c has multip rot=0 lump", - spritename, 'A' + frame); - if (sprtemp[frame].rotate == true) - I_Error - ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", - spritename, 'A' + frame); - - sprtemp[frame].rotate = false; - for (r = 0; r < 8; r++) - { - sprtemp[frame].lump[r] = lump - firstspritelump; - sprtemp[frame].flip[r] = (byte) flipped; - } - return; - } - -// the lump is only used for one rotation - if (sprtemp[frame].rotate == false) - I_Error - ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", - spritename, 'A' + frame); - - sprtemp[frame].rotate = true; - - rotation--; // make 0 based - if (sprtemp[frame].lump[rotation] != -1) - I_Error - ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it", - spritename, 'A' + frame, '1' + rotation); - - sprtemp[frame].lump[rotation] = lump - firstspritelump; - sprtemp[frame].flip[rotation] = (byte) flipped; -} - -/* -================= -= -= R_InitSpriteDefs -= -= Pass a null terminated list of sprite names (4 chars exactly) to be used -= Builds the sprite rotation matrixes to account for horizontally flipped -= sprites. Will report an error if the lumps are inconsistant -=Only called at startup -= -= Sprite lump names are 4 characters for the actor, a letter for the frame, -= and a number for the rotation, A sprite that is flippable will have an -= additional letter/number appended. The rotation character can be 0 to -= signify no rotations -================= -*/ - -void R_InitSpriteDefs(const char **namelist) -{ - const char **check; - int i, l, frame, rotation; - int start, end; - -// count the number of sprite names - check = namelist; - while (*check != NULL) - check++; - numsprites = check - namelist; - - if (!numsprites) - return; - - sprites = Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); - - start = firstspritelump - 1; - end = lastspritelump + 1; - -// scan all the lump names for each of the names, noting the highest -// frame letter -// Just compare 4 characters as ints - for (i = 0; i < numsprites; i++) - { - spritename = DEH_String(namelist[i]); - memset(sprtemp, -1, sizeof(sprtemp)); - - maxframe = -1; - - // - // scan the lumps, filling in the frames for whatever is found - // - for (l = start + 1; l < end; l++) - if (!strncasecmp(lumpinfo[l]->name, spritename, 4)) - { - frame = lumpinfo[l]->name[4] - 'A'; - rotation = lumpinfo[l]->name[5] - '0'; - R_InstallSpriteLump(l, frame, rotation, false); - if (lumpinfo[l]->name[6]) - { - frame = lumpinfo[l]->name[6] - 'A'; - rotation = lumpinfo[l]->name[7] - '0'; - R_InstallSpriteLump(l, frame, rotation, true); - } - } - - // - // check the frames that were found for completeness - // - if (maxframe == -1) - { - //continue; - sprites[i].numframes = 0; - if (gamemode == shareware) - continue; - I_Error("R_InitSprites: No lumps found for sprite %s", - spritename); - } - - maxframe++; - for (frame = 0; frame < maxframe; frame++) - { - switch ((int) sprtemp[frame].rotate) - { - case -1: // no rotations were found for that frame at all - I_Error("R_InitSprites: No patches found for %s frame %c", - spritename, frame + 'A'); - case 0: // only the first rotation is needed - break; - - case 1: // must have all 8 frames - for (rotation = 0; rotation < 8; rotation++) - if (sprtemp[frame].lump[rotation] == -1) - I_Error - ("R_InitSprites: Sprite %s frame %c is missing rotations", - spritename, frame + 'A'); - } - } - - // - // allocate space for the frames present and copy sprtemp to it - // - sprites[i].numframes = maxframe; - sprites[i].spriteframes = - Z_Malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); - memcpy(sprites[i].spriteframes, sprtemp, - maxframe * sizeof(spriteframe_t)); - } - -} - - -/* -=============================================================================== - - GAME FUNCTIONS - -=============================================================================== -*/ - -vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; -int newvissprite; - - -/* -=================== -= -= R_InitSprites -= -= Called at program start -=================== -*/ - -void R_InitSprites(const char **namelist) -{ - int i; - - for (i = 0; i < SCREENWIDTH; i++) - { - negonearray[i] = -1; - } - - R_InitSpriteDefs(namelist); -} - - -/* -=================== -= -= R_ClearSprites -= -= Called at frame start -=================== -*/ - -void R_ClearSprites(void) -{ - vissprite_p = vissprites; -} - - -/* -=================== -= -= R_NewVisSprite -= -=================== -*/ - -vissprite_t overflowsprite; - -vissprite_t *R_NewVisSprite(void) -{ - if (vissprite_p == &vissprites[MAXVISSPRITES]) - return &overflowsprite; - vissprite_p++; - return vissprite_p - 1; -} - - -/* -================ -= -= R_DrawMaskedColumn -= -= Used for sprites and masked mid textures -================ -*/ - -short *mfloorclip; -short *mceilingclip; -fixed_t spryscale; -fixed_t sprtopscreen; -fixed_t sprbotscreen; - -void R_DrawMaskedColumn(column_t * column, signed int baseclip) -{ - int topscreen, bottomscreen; - fixed_t basetexturemid; - - basetexturemid = dc_texturemid; - - for (; column->topdelta != 0xff;) - { -// calculate unclipped screen coordinates for post - topscreen = sprtopscreen + spryscale * column->topdelta; - bottomscreen = topscreen + spryscale * column->length; - dc_yl = (topscreen + FRACUNIT - 1) >> FRACBITS; - dc_yh = (bottomscreen - 1) >> FRACBITS; - - if (dc_yh >= mfloorclip[dc_x]) - dc_yh = mfloorclip[dc_x] - 1; - if (dc_yl <= mceilingclip[dc_x]) - dc_yl = mceilingclip[dc_x] + 1; - - if (dc_yh >= baseclip && baseclip != -1) - dc_yh = baseclip; - - if (dc_yl <= dc_yh) - { - dc_source = (byte *) column + 3; - dc_texturemid = basetexturemid - (column->topdelta << FRACBITS); -// dc_source = (byte *)column + 3 - column->topdelta; - colfunc(); // either R_DrawColumn or R_DrawTLColumn - } - column = (column_t *) ((byte *) column + column->length + 4); - } - - dc_texturemid = basetexturemid; -} - - -/* -================ -= -= R_DrawVisSprite -= -= mfloorclip and mceilingclip should also be set -================ -*/ - -void R_DrawVisSprite(vissprite_t * vis, int x1, int x2) -{ - column_t *column; - int texturecolumn; - fixed_t frac; - patch_t *patch; - fixed_t baseclip; - - - patch = W_CacheLumpNum(vis->patch + firstspritelump, PU_CACHE); - - dc_colormap = vis->colormap; - -// if(!dc_colormap) -// colfunc = tlcolfunc; // NULL colormap = shadow draw - - if (vis->mobjflags & MF_SHADOW) - { - if (vis->mobjflags & MF_TRANSLATION) - { - colfunc = R_DrawTranslatedTLColumn; - dc_translation = translationtables - 256 + - ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); - } - else - { // Draw using shadow column function - colfunc = tlcolfunc; - } - } - else if (vis->mobjflags & MF_TRANSLATION) - { - // Draw using translated column function - colfunc = R_DrawTranslatedColumn; - dc_translation = translationtables - 256 + - ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); - } - - dc_iscale = abs(vis->xiscale) >> detailshift; - dc_texturemid = vis->texturemid; - frac = vis->startfrac; - spryscale = vis->scale; - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - -// check to see if weapon is a vissprite - if (vis->psprite) - { - dc_texturemid += FixedMul(((centery - viewheight / 2) << FRACBITS), - vis->xiscale); - sprtopscreen += (viewheight / 2 - centery) << FRACBITS; - } - - if (vis->footclip && !vis->psprite) - { - sprbotscreen = sprtopscreen + FixedMul(SHORT(patch->height) << FRACBITS, - spryscale); - baseclip = (sprbotscreen - FixedMul(vis->footclip << FRACBITS, - spryscale)) >> FRACBITS; - } - else - { - baseclip = -1; - } - - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) - { - texturecolumn = frac >> FRACBITS; -#ifdef RANGECHECK - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - I_Error("R_DrawSpriteRange: bad texturecolumn"); -#endif - column = (column_t *) ((byte *) patch + - LONG(patch->columnofs[texturecolumn])); - R_DrawMaskedColumn(column, baseclip); - } - - colfunc = basecolfunc; -} - - - -/* -=================== -= -= R_ProjectSprite -= -= Generates a vissprite for a thing if it might be visible -= -=================== -*/ - -void R_ProjectSprite(mobj_t * thing) -{ - fixed_t trx, try; - fixed_t gxt, gyt; - fixed_t tx, tz; - fixed_t xscale; - int x1, x2; - spritedef_t *sprdef; - spriteframe_t *sprframe; - int lump; - unsigned rot; - boolean flip; - int index; - vissprite_t *vis; - angle_t ang; - fixed_t iscale; - - if (thing->flags2 & MF2_DONTDRAW) - { // Never make a vissprite when MF2_DONTDRAW is flagged. - return; - } - -// -// transform the origin point -// - trx = thing->x - viewx; - try = thing->y - viewy; - - gxt = FixedMul(trx, viewcos); - gyt = -FixedMul(try, viewsin); - tz = gxt - gyt; - - if (tz < MINZ) - return; // thing is behind view plane - xscale = FixedDiv(projection, tz); - - gxt = -FixedMul(trx, viewsin); - gyt = FixedMul(try, viewcos); - tx = -(gyt + gxt); - - if (abs(tx) > (tz << 2)) - return; // too far off the side - -// -// decide which patch to use for sprite reletive to player -// -#ifdef RANGECHECK - if ((unsigned) thing->sprite >= numsprites) - I_Error("R_ProjectSprite: invalid sprite number %i ", thing->sprite); -#endif - sprdef = &sprites[thing->sprite]; -#ifdef RANGECHECK - if ((thing->frame & FF_FRAMEMASK) >= sprdef->numframes) - I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", - thing->sprite, thing->frame); -#endif - sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; - - if (sprframe->rotate) - { // choose a different rotation based on player view - ang = R_PointToAngle(thing->x, thing->y); - rot = (ang - thing->angle + (unsigned) (ANG45 / 2) * 9) >> 29; - lump = sprframe->lump[rot]; - flip = (boolean) sprframe->flip[rot]; - } - else - { // use single rotation for all views - lump = sprframe->lump[0]; - flip = (boolean) sprframe->flip[0]; - } - -// -// calculate edges of the shape -// - tx -= spriteoffset[lump]; - x1 = (centerxfrac + FixedMul(tx, xscale)) >> FRACBITS; - if (x1 > viewwidth) - return; // off the right side - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul(tx, xscale)) >> FRACBITS) - 1; - if (x2 < 0) - return; // off the left side - - -// -// store information in a vissprite -// - vis = R_NewVisSprite(); - vis->mobjflags = thing->flags; - vis->psprite = false; - vis->scale = xscale << detailshift; - vis->gx = thing->x; - vis->gy = thing->y; - vis->gz = thing->z; - vis->gzt = thing->z + spritetopoffset[lump]; - - // foot clipping - if (thing->flags2 & MF2_FEETARECLIPPED - && thing->z <= thing->subsector->sector->floorheight) - { - vis->footclip = 10; - } - else - vis->footclip = 0; - vis->texturemid = vis->gzt - viewz - (vis->footclip << FRACBITS); - - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; - iscale = FixedDiv(FRACUNIT, xscale); - if (flip) - { - vis->startfrac = spritewidth[lump] - 1; - vis->xiscale = -iscale; - } - else - { - vis->startfrac = 0; - vis->xiscale = iscale; - } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale * (vis->x1 - x1); - vis->patch = lump; -// -// get light level -// - -// if (thing->flags & MF_SHADOW) -// vis->colormap = NULL; // shadow draw -// else ... - - if (fixedcolormap) - vis->colormap = fixedcolormap; // fixed map - else if (thing->frame & FF_FULLBRIGHT) - vis->colormap = colormaps; // full bright - else - { // diminished light - index = xscale >> (LIGHTSCALESHIFT - detailshift); - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE - 1; - vis->colormap = spritelights[index]; - } -} - - - - -/* -======================== -= -= R_AddSprites -= -======================== -*/ - -void R_AddSprites(sector_t * sec) -{ - mobj_t *thing; - int lightnum; - - if (sec->validcount == validcount) - return; // already added - - sec->validcount = validcount; - - lightnum = (sec->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS - 1]; - else - spritelights = scalelight[lightnum]; - - - for (thing = sec->thinglist; thing; thing = thing->snext) - R_ProjectSprite(thing); -} - - -/* -======================== -= -= R_DrawPSprite -= -======================== -*/ - -int PSpriteSY[NUMWEAPONS] = { - 0, // staff - 5 * FRACUNIT, // goldwand - 15 * FRACUNIT, // crossbow - 15 * FRACUNIT, // blaster - 15 * FRACUNIT, // skullrod - 15 * FRACUNIT, // phoenix rod - 15 * FRACUNIT, // mace - 15 * FRACUNIT, // gauntlets - 15 * FRACUNIT // beak -}; - -void R_DrawPSprite(pspdef_t * psp) -{ - fixed_t tx; - int x1, x2; - spritedef_t *sprdef; - spriteframe_t *sprframe; - int lump; - boolean flip; - vissprite_t *vis, avis; - - int tempangle; - -// -// decide which patch to use -// -#ifdef RANGECHECK - if ((unsigned) psp->state->sprite >= numsprites) - I_Error("R_ProjectSprite: invalid sprite number %i ", - psp->state->sprite); -#endif - sprdef = &sprites[psp->state->sprite]; -#ifdef RANGECHECK - if ((psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) - I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", - psp->state->sprite, psp->state->frame); -#endif - sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; - - lump = sprframe->lump[0]; - flip = (boolean) sprframe->flip[0]; - -// -// calculate edges of the shape -// - tx = psp->sx - 160 * FRACUNIT; - - tx -= spriteoffset[lump]; - if (viewangleoffset) - { - tempangle = - ((centerxfrac / 1024) * (viewangleoffset >> ANGLETOFINESHIFT)); - } - else - { - tempangle = 0; - } - x1 = (centerxfrac + FixedMul(tx, pspritescale) + tempangle) >> FRACBITS; - if (x1 > viewwidth) - return; // off the right side - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul(tx, pspritescale) + - tempangle) >> FRACBITS) - 1; - if (x2 < 0) - return; // off the left side - -// -// store information in a vissprite -// - vis = &avis; - vis->mobjflags = 0; - vis->psprite = true; - vis->footclip = 0; - vis->texturemid = - (BASEYCENTER << FRACBITS) + FRACUNIT / 2 - (psp->sy - - spritetopoffset[lump]); - if (viewheight == SCREENHEIGHT) - { - vis->texturemid -= PSpriteSY[players[consoleplayer].readyweapon]; - } - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; - vis->scale = pspritescale << detailshift; - if (flip) - { - vis->xiscale = -pspriteiscale; - vis->startfrac = spritewidth[lump] - 1; - } - else - { - vis->xiscale = pspriteiscale; - vis->startfrac = 0; - } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale * (vis->x1 - x1); - vis->patch = lump; - - if (viewplayer->powers[pw_invisibility] > 4 * 32 || - viewplayer->powers[pw_invisibility] & 8) - { - // Invisibility - vis->colormap = spritelights[MAXLIGHTSCALE - 1]; - vis->mobjflags |= MF_SHADOW; - } - else if (fixedcolormap) - { - // Fixed color - vis->colormap = fixedcolormap; - } - else if (psp->state->frame & FF_FULLBRIGHT) - { - // Full bright - vis->colormap = colormaps; - } - else - { - // local light - vis->colormap = spritelights[MAXLIGHTSCALE - 1]; - } - R_DrawVisSprite(vis, vis->x1, vis->x2); -} - -/* -======================== -= -= R_DrawPlayerSprites -= -======================== -*/ - -void R_DrawPlayerSprites(void) -{ - int i, lightnum; - pspdef_t *psp; - -// -// get light level -// - lightnum = - (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + - extralight; - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS - 1]; - else - spritelights = scalelight[lightnum]; -// -// clip to screen bounds -// - mfloorclip = screenheightarray; - mceilingclip = negonearray; - -// -// add all active psprites -// - for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; i++, psp++) - if (psp->state) - R_DrawPSprite(psp); - -} - - -/* -======================== -= -= R_SortVisSprites -= -======================== -*/ - -vissprite_t vsprsortedhead; - -void R_SortVisSprites(void) -{ - int i, count; - vissprite_t *ds, *best; - static vissprite_t unsorted; - fixed_t bestscale; - - count = vissprite_p - vissprites; - - unsorted.next = unsorted.prev = &unsorted; - if (!count) - return; - - for (ds = vissprites; ds < vissprite_p; ds++) - { - ds->next = ds + 1; - ds->prev = ds - 1; - } - vissprites[0].prev = &unsorted; - unsorted.next = &vissprites[0]; - (vissprite_p - 1)->next = &unsorted; - unsorted.prev = vissprite_p - 1; - -// -// pull the vissprites out by scale -// - best = 0; // shut up the compiler warning - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i = 0; i < count; i++) - { - bestscale = INT_MAX; - for (ds = unsorted.next; ds != &unsorted; ds = ds->next) - { - if (ds->scale < bestscale) - { - bestscale = ds->scale; - best = ds; - } - } - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; - } -} - - - -/* -======================== -= -= R_DrawSprite -= -======================== -*/ - -void R_DrawSprite(vissprite_t * spr) -{ - drawseg_t *ds; - short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH]; - int x, r1, r2; - fixed_t scale, lowscale; - int silhouette; - - for (x = spr->x1; x <= spr->x2; x++) - clipbot[x] = cliptop[x] = -2; - -// -// scan drawsegs from end to start for obscuring segs -// the first drawseg that has a greater scale is the clip seg -// - for (ds = ds_p - 1; ds >= drawsegs; ds--) - { - // - // determine if the drawseg obscures the sprite - // - if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || - (!ds->silhouette && !ds->maskedtexturecol)) - continue; // doesn't cover sprite - - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->scale || (lowscale < spr->scale - && !R_PointOnSegSide(spr->gx, spr->gy, - ds->curline))) - { - if (ds->maskedtexturecol) // masked mid texture - R_RenderMaskedSegRange(ds, r1, r2); - continue; // seg is behind sprite - } - -// -// clip this piece of the sprite -// - silhouette = ds->silhouette; - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; - - if (silhouette == 1) - { // bottom sil - for (x = r1; x <= r2; x++) - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == 2) - { // top sil - for (x = r1; x <= r2; x++) - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == 3) - { // both - for (x = r1; x <= r2; x++) - { - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - } - - } - -// -// all clipping has been performed, so draw the sprite -// - -// check for unclipped columns - for (x = spr->x1; x <= spr->x2; x++) - { - if (clipbot[x] == -2) - clipbot[x] = viewheight; - if (cliptop[x] == -2) - cliptop[x] = -1; - } - - mfloorclip = clipbot; - mceilingclip = cliptop; - R_DrawVisSprite(spr, spr->x1, spr->x2); -} - - -/* -======================== -= -= R_DrawMasked -= -======================== -*/ - -void R_DrawMasked(void) -{ - vissprite_t *spr; - drawseg_t *ds; - - R_SortVisSprites(); - - if (vissprite_p > vissprites) - { - // draw all vissprites back to front - - for (spr = vsprsortedhead.next; spr != &vsprsortedhead; - spr = spr->next) - R_DrawSprite(spr); - } - -// -// render any remaining masked mid textures -// - for (ds = ds_p - 1; ds >= drawsegs; ds--) - if (ds->maskedtexturecol) - R_RenderMaskedSegRange(ds, ds->x1, ds->x2); - -// -// draw the psprites on top of everything -// -// Added for the sideviewing with an external device - if (viewangleoffset <= 1024 << ANGLETOFINESHIFT || viewangleoffset >= - -(1024 << ANGLETOFINESHIFT)) - { // don't draw on side views - R_DrawPlayerSprites(); - } - -// if (!viewangleoffset) // don't draw on side views -// R_DrawPlayerSprites (); -} diff --git a/games/NXDoom/src/heretic/s_sound.c b/games/NXDoom/src/heretic/s_sound.c deleted file mode 100644 index 829278918e0..00000000000 --- a/games/NXDoom/src/heretic/s_sound.c +++ /dev/null @@ -1,607 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include - -#include "doomdef.h" -#include "i_system.h" -#include "m_random.h" -#include "sounds.h" -#include "s_sound.h" -#include "i_sound.h" -#include "r_local.h" -#include "p_local.h" - -#include "sounds.h" - -#include "w_wad.h" -#include "z_zone.h" - -/* -=============================================================================== - - MUSIC & SFX API - -=============================================================================== -*/ - -void S_ShutDown(void); -boolean S_StopSoundID(int sound_id, int priority); - -static channel_t channel[MAX_CHANNELS]; - -static void *rs; // Handle for the registered song -int mus_song = -1; -int mus_lumpnum; -void *mus_sndptr; -byte *soundCurve; - -int snd_MaxVolume = 10; -int snd_MusicVolume = 10; -int snd_Channels = 16; - -int AmbChan; - -void S_Start(void) -{ - int i; - - S_StartSong((gameepisode - 1) * 9 + gamemap - 1, true); - - //stop all sounds - for (i = 0; i < snd_Channels; i++) - { - if (channel[i].handle) - { - S_StopSound(channel[i].mo); - } - } - memset(channel, 0, 8 * sizeof(channel_t)); -} - -void S_StartSong(int song, boolean loop) -{ - int mus_len; - - if (song == mus_song) - { // don't replay an old song - return; - } - - if (rs != NULL) - { - I_StopSong(); - I_UnRegisterSong(rs); - } - - if (song < mus_e1m1 || song > NUMMUSIC) - { - return; - } - mus_lumpnum = W_GetNumForName(S_music[song].name); - mus_sndptr = W_CacheLumpNum(mus_lumpnum, PU_MUSIC); - mus_len = W_LumpLength(mus_lumpnum); - rs = I_RegisterSong(mus_sndptr, mus_len); - I_PlaySong(rs, loop); //'true' denotes endless looping. - mus_song = song; -} - -static mobj_t *GetSoundListener(void) -{ - static degenmobj_t dummy_listener; - - // If we are at the title screen, the console player doesn't have an - // object yet, so return a pointer to a static dummy listener instead. - - if (players[consoleplayer].mo != NULL) - { - return players[consoleplayer].mo; - } - else - { - dummy_listener.x = 0; - dummy_listener.y = 0; - dummy_listener.z = 0; - - return (mobj_t *) &dummy_listener; - } -} - -void S_StartSound(void *_origin, int sound_id) -{ - mobj_t *origin = _origin; - mobj_t *listener; - int dist, vol; - int i; - int priority; - int sep; - int angle; - int absx; - int absy; - - static int sndcount = 0; - int chan; - - listener = GetSoundListener(); - - if (sound_id == 0 || snd_MaxVolume == 0) - return; - if (origin == NULL) - { - origin = listener; - } - -// calculate the distance before other stuff so that we can throw out -// sounds that are beyond the hearing range. - absx = abs(origin->x - listener->x); - absy = abs(origin->y - listener->y); - dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); - dist >>= FRACBITS; -// dist = P_AproxDistance(origin->x-viewx, origin->y-viewy)>>FRACBITS; - - if (dist >= MAX_SND_DIST) - { -// dist = MAX_SND_DIST - 1; - return; //sound is beyond the hearing range... - } - if (dist < 0) - { - dist = 0; - } - priority = S_sfx[sound_id].priority; - priority *= (10 - (dist / 160)); - if (!S_StopSoundID(sound_id, priority)) - { - return; // other sounds have greater priority - } - for (i = 0; i < snd_Channels; i++) - { - if (origin->player) - { - i = snd_Channels; - break; // let the player have more than one sound. - } - if (origin == channel[i].mo) - { // only allow other mobjs one sound - S_StopSound(channel[i].mo); - break; - } - } - if (i >= snd_Channels) - { - if (sound_id >= sfx_wind) - { - if (AmbChan != -1 && S_sfx[sound_id].priority <= - S_sfx[channel[AmbChan].sound_id].priority) - { - return; //ambient channel already in use - } - else - { - AmbChan = -1; - } - } - for (i = 0; i < snd_Channels; i++) - { - if (channel[i].mo == NULL) - { - break; - } - } - if (i >= snd_Channels) - { - //look for a lower priority sound to replace. - sndcount++; - if (sndcount >= snd_Channels) - { - sndcount = 0; - } - for (chan = 0; chan < snd_Channels; chan++) - { - i = (sndcount + chan) % snd_Channels; - if (priority >= channel[i].priority) - { - chan = -1; //denote that sound should be replaced. - break; - } - } - if (chan != -1) - { - return; //no free channels. - } - else //replace the lower priority sound. - { - if (channel[i].handle) - { - if (I_SoundIsPlaying(channel[i].handle)) - { - I_StopSound(channel[i].handle); - } - if (S_sfx[channel[i].sound_id].usefulness > 0) - { - S_sfx[channel[i].sound_id].usefulness--; - } - - if (AmbChan == i) - { - AmbChan = -1; - } - } - } - } - } - if (S_sfx[sound_id].lumpnum == 0) - { - S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]); - } - - // calculate the volume based upon the distance from the sound origin. -// vol = (snd_MaxVolume*16 + dist*(-snd_MaxVolume*16)/MAX_SND_DIST)>>9; - vol = soundCurve[dist]; - - if (origin == listener) - { - sep = 128; - } - else - { - angle = R_PointToAngle2(listener->x, listener->y, - origin->x, origin->y); - angle = (angle - viewangle) >> 24; - sep = angle * 2 - 128; - if (sep < 64) - sep = -sep; - if (sep > 192) - sep = 512 - sep; - } - - channel[i].pitch = (byte) (NORM_PITCH + (M_Random() & 7) - (M_Random() & 7)); - channel[i].handle = I_StartSound(&S_sfx[sound_id], i, vol, sep, channel[i].pitch); - channel[i].mo = origin; - channel[i].sound_id = sound_id; - channel[i].priority = priority; - if (sound_id >= sfx_wind) - { - AmbChan = i; - } - if (S_sfx[sound_id].usefulness == -1) - { - S_sfx[sound_id].usefulness = 1; - } - else - { - S_sfx[sound_id].usefulness++; - } -} - -void S_StartSoundAtVolume(void *_origin, int sound_id, int volume) -{ - mobj_t *origin = _origin; - mobj_t *listener; - int i; - - listener = GetSoundListener(); - - if (sound_id == 0 || snd_MaxVolume == 0) - return; - if (origin == NULL) - { - origin = listener; - } - - if (volume == 0) - { - return; - } - volume = (volume * (snd_MaxVolume + 1) * 8) >> 7; - -// no priority checking, as ambient sounds would be the LOWEST. - for (i = 0; i < snd_Channels; i++) - { - if (channel[i].mo == NULL) - { - break; - } - } - if (i >= snd_Channels) - { - return; - } - if (S_sfx[sound_id].lumpnum == 0) - { - S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]); - } - - channel[i].pitch = (byte) (NORM_PITCH - (M_Random() & 3) + (M_Random() & 3)); - channel[i].handle = I_StartSound(&S_sfx[sound_id], i, volume, 128, channel[i].pitch); - channel[i].mo = origin; - channel[i].sound_id = sound_id; - channel[i].priority = 1; //super low priority. - if (S_sfx[sound_id].usefulness == -1) - { - S_sfx[sound_id].usefulness = 1; - } - else - { - S_sfx[sound_id].usefulness++; - } -} - -boolean S_StopSoundID(int sound_id, int priority) -{ - int i; - int lp; //least priority - int found; - - if (S_sfx[sound_id].numchannels == -1) - { - return (true); - } - lp = -1; //denote the argument sound_id - found = 0; - for (i = 0; i < snd_Channels; i++) - { - if (channel[i].sound_id == sound_id && channel[i].mo) - { - found++; //found one. Now, should we replace it?? - if (priority >= channel[i].priority) - { // if we're gonna kill one, then this'll be it - lp = i; - priority = channel[i].priority; - } - } - } - if (found < S_sfx[sound_id].numchannels) - { - return (true); - } - else if (lp == -1) - { - return (false); // don't replace any sounds - } - if (channel[lp].handle) - { - if (I_SoundIsPlaying(channel[lp].handle)) - { - I_StopSound(channel[lp].handle); - } - if (S_sfx[channel[i].sound_id].usefulness > 0) - { - S_sfx[channel[i].sound_id].usefulness--; - } - channel[lp].mo = NULL; - } - return (true); -} - -void S_StopSound(void *_origin) -{ - mobj_t *origin = _origin; - int i; - - for (i = 0; i < snd_Channels; i++) - { - if (channel[i].mo == origin) - { - I_StopSound(channel[i].handle); - if (S_sfx[channel[i].sound_id].usefulness > 0) - { - S_sfx[channel[i].sound_id].usefulness--; - } - channel[i].handle = 0; - channel[i].mo = NULL; - if (AmbChan == i) - { - AmbChan = -1; - } - } - } -} - -void S_SoundLink(mobj_t * oldactor, mobj_t * newactor) -{ - int i; - - for (i = 0; i < snd_Channels; i++) - { - if (channel[i].mo == oldactor) - channel[i].mo = newactor; - } -} - -void S_PauseSound(void) -{ - I_PauseSong(); -} - -void S_ResumeSound(void) -{ - I_ResumeSong(); -} - -void S_UpdateSounds(mobj_t * listener) -{ - int i, dist, vol; - int angle; - int sep; - int priority; - int absx; - int absy; - - I_UpdateSound(); - - listener = GetSoundListener(); - if (snd_MaxVolume == 0) - { - return; - } - - for (i = 0; i < snd_Channels; i++) - { - if (!channel[i].handle || S_sfx[channel[i].sound_id].usefulness == -1) - { - continue; - } - if (!I_SoundIsPlaying(channel[i].handle)) - { - if (S_sfx[channel[i].sound_id].usefulness > 0) - { - S_sfx[channel[i].sound_id].usefulness--; - } - channel[i].handle = 0; - channel[i].mo = NULL; - channel[i].sound_id = 0; - if (AmbChan == i) - { - AmbChan = -1; - } - } - if (channel[i].mo == NULL || channel[i].sound_id == 0 - || channel[i].mo == listener || listener == NULL) - { - continue; - } - else - { - absx = abs(channel[i].mo->x - listener->x); - absy = abs(channel[i].mo->y - listener->y); - dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); - dist >>= FRACBITS; -// dist = P_AproxDistance(channel[i].mo->x-listener->x, channel[i].mo->y-listener->y)>>FRACBITS; - - if (dist >= MAX_SND_DIST) - { - S_StopSound(channel[i].mo); - continue; - } - if (dist < 0) - dist = 0; - -// calculate the volume based upon the distance from the sound origin. -// vol = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE)+dist)*(snd_MaxVolume*8))>>7; - vol = soundCurve[dist]; - - angle = R_PointToAngle2(listener->x, listener->y, - channel[i].mo->x, channel[i].mo->y); - angle = (angle - viewangle) >> 24; - sep = angle * 2 - 128; - if (sep < 64) - sep = -sep; - if (sep > 192) - sep = 512 - sep; - // TODO: Pitch shifting. - I_UpdateSoundParams(channel[i].handle, vol, sep); - priority = S_sfx[channel[i].sound_id].priority; - priority *= (10 - (dist >> 8)); - channel[i].priority = priority; - } - } -} - -void S_Init(void) -{ - I_SetOPLDriverVer(opl_doom2_1_666); - soundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL); - if (snd_Channels > 8) - { - snd_Channels = 8; - } - I_SetMusicVolume(snd_MusicVolume * 8); - S_SetMaxVolume(true); - - I_AtExit(S_ShutDown, true); - - // Heretic defaults to pitch-shifting on - if (snd_pitchshift == -1) - { - snd_pitchshift = 1; - } - - I_PrecacheSounds(S_sfx, NUMSFX); -} - -void S_GetChannelInfo(SoundInfo_t * s) -{ - int i; - ChanInfo_t *c; - - s->channelCount = snd_Channels; - s->musicVolume = snd_MusicVolume; - s->soundVolume = snd_MaxVolume; - for (i = 0; i < snd_Channels; i++) - { - c = &s->chan[i]; - c->id = channel[i].sound_id; - c->priority = channel[i].priority; - c->name = S_sfx[c->id].name; - c->mo = channel[i].mo; - - if (c->mo != NULL) - { - c->distance = P_AproxDistance(c->mo->x - viewx, c->mo->y - viewy) - >> FRACBITS; - } - else - { - c->distance = 0; - } - } -} - -void S_SetMaxVolume(boolean fullprocess) -{ - int i; - - if (!fullprocess) - { - soundCurve[0] = - (*((byte *) W_CacheLumpName("SNDCURVE", PU_CACHE)) * - (snd_MaxVolume * 8)) >> 7; - } - else - { - for (i = 0; i < MAX_SND_DIST; i++) - { - soundCurve[i] = - (*((byte *) W_CacheLumpName("SNDCURVE", PU_CACHE) + i) * - (snd_MaxVolume * 8)) >> 7; - } - } -} - -static boolean musicPaused; -void S_SetMusicVolume(void) -{ - I_SetMusicVolume(snd_MusicVolume * 8); - if (snd_MusicVolume == 0) - { - I_PauseSong(); - musicPaused = true; - } - else if (musicPaused) - { - musicPaused = false; - I_ResumeSong(); - } -} - -void S_ShutDown(void) -{ - I_StopSong(); - I_UnRegisterSong(rs); - I_ShutdownSound(); -} - diff --git a/games/NXDoom/src/heretic/s_sound.h b/games/NXDoom/src/heretic/s_sound.h deleted file mode 100644 index 796be73ee2d..00000000000 --- a/games/NXDoom/src/heretic/s_sound.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// soundst.h - -#ifndef __SOUNDSTH__ -#define __SOUNDSTH__ - -extern int snd_MaxVolume; -extern int snd_MusicVolume; -extern int snd_Channels; - - -void S_Start(void); -void S_StartSound(void *origin, int sound_id); -void S_StartSoundAtVolume(void *origin, int sound_id, int volume); -void S_StopSound(void *origin); -void S_PauseSound(void); -void S_ResumeSound(void); -void S_UpdateSounds(mobj_t * listener); -void S_StartSong(int song, boolean loop); -void S_Init(void); -void S_GetChannelInfo(SoundInfo_t * s); -void S_SetMaxVolume(boolean fullprocess); -void S_SetMusicVolume(void); - -#endif diff --git a/games/NXDoom/src/heretic/sb_bar.c b/games/NXDoom/src/heretic/sb_bar.c deleted file mode 100644 index bcc5d765a91..00000000000 --- a/games/NXDoom/src/heretic/sb_bar.c +++ /dev/null @@ -1,1283 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// SB_bar.c - -#include "doomdef.h" -#include "deh_str.h" -#include "i_video.h" -#include "i_swap.h" -#include "m_cheat.h" -#include "m_misc.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" -#include "am_map.h" - -// Types - -typedef struct Cheat_s -{ - void (*func) (player_t * player, struct Cheat_s * cheat); - cheatseq_t *seq; -} Cheat_t; - -// Private Functions - -static void DrawSoundInfo(void); -static void ShadeLine(int x, int y, int height, int shade); -static void ShadeChain(void); -static void DrINumber(signed int val, int x, int y); -static void DrBNumber(signed int val, int x, int y); -static void DrawCommonBar(void); -static void DrawMainBar(void); -static void DrawInventoryBar(void); -static void DrawFullScreenStuff(void); -static boolean HandleCheats(byte key); -static void CheatGodFunc(player_t * player, Cheat_t * cheat); -static void CheatNoClipFunc(player_t * player, Cheat_t * cheat); -static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat); -static void CheatPowerFunc(player_t * player, Cheat_t * cheat); -static void CheatHealthFunc(player_t * player, Cheat_t * cheat); -static void CheatKeysFunc(player_t * player, Cheat_t * cheat); -static void CheatSoundFunc(player_t * player, Cheat_t * cheat); -static void CheatTickerFunc(player_t * player, Cheat_t * cheat); -static void CheatArtifact1Func(player_t * player, Cheat_t * cheat); -static void CheatArtifact2Func(player_t * player, Cheat_t * cheat); -static void CheatArtifact3Func(player_t * player, Cheat_t * cheat); -static void CheatWarpFunc(player_t * player, Cheat_t * cheat); -static void CheatChickenFunc(player_t * player, Cheat_t * cheat); -static void CheatMassacreFunc(player_t * player, Cheat_t * cheat); -static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat); -static void CheatIDDQDFunc(player_t * player, Cheat_t * cheat); - -// Public Data - -boolean DebugSound; // debug flag for displaying sound info - -boolean inventory; -int curpos; -int inv_ptr; -int ArtifactFlash; - -static int DisplayTicker = 0; - -// Private Data - -static int HealthMarker; -static int ChainWiggle; -static player_t *CPlayer; -int playpalette; - -patch_t *PatchLTFACE; -patch_t *PatchRTFACE; -patch_t *PatchBARBACK; -patch_t *PatchCHAIN; -patch_t *PatchSTATBAR; -patch_t *PatchLIFEGEM; -//patch_t *PatchEMPWEAP; -//patch_t *PatchLIL4BOX; -patch_t *PatchLTFCTOP; -patch_t *PatchRTFCTOP; -//patch_t *PatchARMORBOX; -//patch_t *PatchARTIBOX; -patch_t *PatchSELECTBOX; -//patch_t *PatchKILLSPIC; -//patch_t *PatchMANAPIC; -//patch_t *PatchPOWERICN; -patch_t *PatchINVLFGEM1; -patch_t *PatchINVLFGEM2; -patch_t *PatchINVRTGEM1; -patch_t *PatchINVRTGEM2; -patch_t *PatchINumbers[10]; -patch_t *PatchNEGATIVE; -patch_t *PatchSmNumbers[10]; -patch_t *PatchBLACKSQ; -patch_t *PatchINVBAR; -patch_t *PatchARMCLEAR; -patch_t *PatchCHAINBACK; -//byte *ShadeTables; -int FontBNumBase; -int spinbooklump; -int spinflylump; - -// Toggle god mode -cheatseq_t CheatGodSeq = CHEAT("quicken", 0); - -// Toggle no clipping mode -cheatseq_t CheatNoClipSeq = CHEAT("kitty", 0); - -// Get all weapons and ammo -cheatseq_t CheatWeaponsSeq = CHEAT("rambo", 0); - -// Toggle tome of power -cheatseq_t CheatPowerSeq = CHEAT("shazam", 0); - -// Get full health -cheatseq_t CheatHealthSeq = CHEAT("ponce", 0); - -// Get all keys -cheatseq_t CheatKeysSeq = CHEAT("skel", 0); - -// Toggle sound debug info -cheatseq_t CheatSoundSeq = CHEAT("noise", 0); - -// Toggle ticker -cheatseq_t CheatTickerSeq = CHEAT("ticker", 0); - -// Get an artifact 1st stage (ask for type) -cheatseq_t CheatArtifact1Seq = CHEAT("gimme", 0); - -// Get an artifact 2nd stage (ask for count) -cheatseq_t CheatArtifact2Seq = CHEAT("gimme", 1); - -// Get an artifact final stage -cheatseq_t CheatArtifact3Seq = CHEAT("gimme", 2); - -// Warp to new level -cheatseq_t CheatWarpSeq = CHEAT("engage", 2); - -// Save a screenshot -cheatseq_t CheatChickenSeq = CHEAT("cockadoodledoo", 0); - -// Kill all monsters -cheatseq_t CheatMassacreSeq = CHEAT("massacre", 0); - -cheatseq_t CheatIDKFASeq = CHEAT("idkfa", 0); -cheatseq_t CheatIDDQDSeq = CHEAT("iddqd", 0); - -static Cheat_t Cheats[] = { - {CheatGodFunc, &CheatGodSeq}, - {CheatNoClipFunc, &CheatNoClipSeq}, - {CheatWeaponsFunc, &CheatWeaponsSeq}, - {CheatPowerFunc, &CheatPowerSeq}, - {CheatHealthFunc, &CheatHealthSeq}, - {CheatKeysFunc, &CheatKeysSeq}, - {CheatSoundFunc, &CheatSoundSeq}, - {CheatTickerFunc, &CheatTickerSeq}, - {CheatArtifact1Func, &CheatArtifact1Seq}, - {CheatArtifact2Func, &CheatArtifact2Seq}, - {CheatArtifact3Func, &CheatArtifact3Seq}, - {CheatWarpFunc, &CheatWarpSeq}, - {CheatChickenFunc, &CheatChickenSeq}, - {CheatMassacreFunc, &CheatMassacreSeq}, - {CheatIDKFAFunc, &CheatIDKFASeq}, - {CheatIDDQDFunc, &CheatIDDQDSeq}, - {NULL, NULL} -}; - -//--------------------------------------------------------------------------- -// -// PROC SB_Init -// -//--------------------------------------------------------------------------- - -void SB_Init(void) -{ - int i; - int startLump; - - PatchLTFACE = W_CacheLumpName(DEH_String("LTFACE"), PU_STATIC); - PatchRTFACE = W_CacheLumpName(DEH_String("RTFACE"), PU_STATIC); - PatchBARBACK = W_CacheLumpName(DEH_String("BARBACK"), PU_STATIC); - PatchINVBAR = W_CacheLumpName(DEH_String("INVBAR"), PU_STATIC); - PatchCHAIN = W_CacheLumpName(DEH_String("CHAIN"), PU_STATIC); - if (deathmatch) - { - PatchSTATBAR = W_CacheLumpName(DEH_String("STATBAR"), PU_STATIC); - } - else - { - PatchSTATBAR = W_CacheLumpName(DEH_String("LIFEBAR"), PU_STATIC); - } - if (!netgame) - { // single player game uses red life gem - PatchLIFEGEM = W_CacheLumpName(DEH_String("LIFEGEM2"), PU_STATIC); - } - else - { - PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName(DEH_String("LIFEGEM0")) - + consoleplayer, PU_STATIC); - } - PatchLTFCTOP = W_CacheLumpName(DEH_String("LTFCTOP"), PU_STATIC); - PatchRTFCTOP = W_CacheLumpName(DEH_String("RTFCTOP"), PU_STATIC); - PatchSELECTBOX = W_CacheLumpName(DEH_String("SELECTBOX"), PU_STATIC); - PatchINVLFGEM1 = W_CacheLumpName(DEH_String("INVGEML1"), PU_STATIC); - PatchINVLFGEM2 = W_CacheLumpName(DEH_String("INVGEML2"), PU_STATIC); - PatchINVRTGEM1 = W_CacheLumpName(DEH_String("INVGEMR1"), PU_STATIC); - PatchINVRTGEM2 = W_CacheLumpName(DEH_String("INVGEMR2"), PU_STATIC); - PatchBLACKSQ = W_CacheLumpName(DEH_String("BLACKSQ"), PU_STATIC); - PatchARMCLEAR = W_CacheLumpName(DEH_String("ARMCLEAR"), PU_STATIC); - PatchCHAINBACK = W_CacheLumpName(DEH_String("CHAINBACK"), PU_STATIC); - startLump = W_GetNumForName(DEH_String("IN0")); - for (i = 0; i < 10; i++) - { - PatchINumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); - } - PatchNEGATIVE = W_CacheLumpName(DEH_String("NEGNUM"), PU_STATIC); - FontBNumBase = W_GetNumForName(DEH_String("FONTB16")); - startLump = W_GetNumForName(DEH_String("SMALLIN0")); - for (i = 0; i < 10; i++) - { - PatchSmNumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); - } - playpalette = W_GetNumForName(DEH_String("PLAYPAL")); - spinbooklump = W_GetNumForName(DEH_String("SPINBK0")); - spinflylump = W_GetNumForName(DEH_String("SPFLY0")); -} - -//--------------------------------------------------------------------------- -// -// PROC SB_Ticker -// -//--------------------------------------------------------------------------- - -void SB_Ticker(void) -{ - int delta; - int curHealth; - - if (leveltime & 1) - { - ChainWiggle = P_Random() & 1; - } - curHealth = players[consoleplayer].mo->health; - if (curHealth < 0) - { - curHealth = 0; - } - if (curHealth < HealthMarker) - { - delta = (HealthMarker - curHealth) >> 2; - if (delta < 1) - { - delta = 1; - } - else if (delta > 8) - { - delta = 8; - } - HealthMarker -= delta; - } - else if (curHealth > HealthMarker) - { - delta = (curHealth - HealthMarker) >> 2; - if (delta < 1) - { - delta = 1; - } - else if (delta > 8) - { - delta = 8; - } - HealthMarker += delta; - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrINumber -// -// Draws a three digit number. -// -//--------------------------------------------------------------------------- - -static void DrINumber(signed int val, int x, int y) -{ - patch_t *patch; - int oldval; - - oldval = val; - if (val < 0) - { - if (val < -9) - { - V_DrawPatch(x + 1, y + 1, W_CacheLumpName(DEH_String("LAME"), PU_CACHE)); - } - else - { - val = -val; - V_DrawPatch(x + 18, y, PatchINumbers[val]); - V_DrawPatch(x + 9, y, PatchNEGATIVE); - } - return; - } - if (val > 99) - { - patch = PatchINumbers[val / 100]; - V_DrawPatch(x, y, patch); - } - val = val % 100; - if (val > 9 || oldval > 99) - { - patch = PatchINumbers[val / 10]; - V_DrawPatch(x + 9, y, patch); - } - val = val % 10; - patch = PatchINumbers[val]; - V_DrawPatch(x + 18, y, patch); -} - -//--------------------------------------------------------------------------- -// -// PROC DrBNumber -// -// Draws a three digit number using FontB -// -//--------------------------------------------------------------------------- - -static void DrBNumber(signed int val, int x, int y) -{ - patch_t *patch; - int xpos; - int oldval; - - oldval = val; - xpos = x; - if (val < 0) - { - val = 0; - } - if (val > 99) - { - patch = W_CacheLumpNum(FontBNumBase + val / 100, PU_CACHE); - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - } - val = val % 100; - xpos += 12; - if (val > 9 || oldval > 99) - { - patch = W_CacheLumpNum(FontBNumBase + val / 10, PU_CACHE); - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - } - val = val % 10; - xpos += 12; - patch = W_CacheLumpNum(FontBNumBase + val, PU_CACHE); - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); -} - -//--------------------------------------------------------------------------- -// -// PROC DrSmallNumber -// -// Draws a small two digit number. -// -//--------------------------------------------------------------------------- - -static void DrSmallNumber(int val, int x, int y) -{ - patch_t *patch; - - if (val == 1) - { - return; - } - if (val > 9) - { - patch = PatchSmNumbers[val / 10]; - V_DrawPatch(x, y, patch); - } - val = val % 10; - patch = PatchSmNumbers[val]; - V_DrawPatch(x + 4, y, patch); -} - -//--------------------------------------------------------------------------- -// -// PROC ShadeLine -// -//--------------------------------------------------------------------------- - -static void ShadeLine(int x, int y, int height, int shade) -{ - byte *dest; - byte *shades; - - shades = colormaps + 9 * 256 + shade * 2 * 256; - dest = I_VideoBuffer + y * SCREENWIDTH + x; - while (height--) - { - *(dest) = *(shades + *dest); - dest += SCREENWIDTH; - } -} - -//--------------------------------------------------------------------------- -// -// PROC ShadeChain -// -//--------------------------------------------------------------------------- - -static void ShadeChain(void) -{ - int i; - - for (i = 0; i < 16; i++) - { - ShadeLine(277 + i, 190, 10, i / 2); - ShadeLine(19 + i, 190, 10, 7 - (i / 2)); - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSoundInfo -// -// Displays sound debugging information. -// -//--------------------------------------------------------------------------- - -static void DrawSoundInfo(void) -{ - int i; - SoundInfo_t s; - ChanInfo_t *c; - char text[32]; - int x; - int y; - int xPos[7] = { 1, 75, 112, 156, 200, 230, 260 }; - - if (leveltime & 16) - { - MN_DrTextA(DEH_String("*** SOUND DEBUG INFO ***"), xPos[0], 20); - } - S_GetChannelInfo(&s); - if (s.channelCount == 0) - { - return; - } - x = 0; - MN_DrTextA(DEH_String("NAME"), xPos[x++], 30); - MN_DrTextA(DEH_String("MO.T"), xPos[x++], 30); - MN_DrTextA(DEH_String("MO.X"), xPos[x++], 30); - MN_DrTextA(DEH_String("MO.Y"), xPos[x++], 30); - MN_DrTextA(DEH_String("ID"), xPos[x++], 30); - MN_DrTextA(DEH_String("PRI"), xPos[x++], 30); - MN_DrTextA(DEH_String("DIST"), xPos[x++], 30); - for (i = 0; i < s.channelCount; i++) - { - c = &s.chan[i]; - x = 0; - y = 40 + i * 10; - if (c->mo == NULL) - { // Channel is unused - MN_DrTextA(DEH_String("------"), xPos[0], y); - continue; - } - M_snprintf(text, sizeof(text), "%s", c->name); - M_ForceUppercase(text); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->mo->type); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->id); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->priority); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->distance); - MN_DrTextA(text, xPos[x++], y); - } - UpdateState |= I_FULLSCRN; - BorderNeedRefresh = true; -} - -//--------------------------------------------------------------------------- -// -// PROC SB_Drawer -// -//--------------------------------------------------------------------------- - -char patcharti[][10] = { - {"ARTIBOX"}, // none - {"ARTIINVU"}, // invulnerability - {"ARTIINVS"}, // invisibility - {"ARTIPTN2"}, // health - {"ARTISPHL"}, // superhealth - {"ARTIPWBK"}, // tomeofpower - {"ARTITRCH"}, // torch - {"ARTIFBMB"}, // firebomb - {"ARTIEGGC"}, // egg - {"ARTISOAR"}, // fly - {"ARTIATLP"} // teleport -}; - -char ammopic[][10] = { - {"INAMGLD"}, - {"INAMBOW"}, - {"INAMBST"}, - {"INAMRAM"}, - {"INAMPNX"}, - {"INAMLOB"} -}; - -int SB_state = -1; -static int oldarti = 0; -static int oldartiCount = 0; -static int oldfrags = -9999; -static int oldammo = -1; -static int oldarmor = -1; -static int oldweapon = -1; -static int oldhealth = -1; -static int oldlife = -1; -static int oldkeys = -1; - -int playerkeys = 0; - - -void SB_Drawer(void) -{ - int frame; - static boolean hitCenterFrame; - - // Sound info debug stuff - if (DebugSound == true) - { - DrawSoundInfo(); - } - CPlayer = &players[consoleplayer]; - if (viewheight == SCREENHEIGHT && !automapactive) - { - DrawFullScreenStuff(); - SB_state = -1; - } - else - { - if (SB_state == -1) - { - V_DrawPatch(0, 158, PatchBARBACK); - if (players[consoleplayer].cheats & CF_GODMODE) - { - V_DrawPatch(16, 167, - W_CacheLumpName(DEH_String("GOD1"), PU_CACHE)); - V_DrawPatch(287, 167, - W_CacheLumpName(DEH_String("GOD2"), PU_CACHE)); - } - oldhealth = -1; - } - DrawCommonBar(); - if (!inventory) - { - if (SB_state != 0) - { - // Main interface - V_DrawPatch(34, 160, PatchSTATBAR); - oldarti = 0; - oldammo = -1; - oldarmor = -1; - oldweapon = -1; - oldfrags = -9999; //can't use -1, 'cuz of negative frags - oldlife = -1; - oldkeys = -1; - } - DrawMainBar(); - SB_state = 0; - } - else - { - if (SB_state != 1) - { - V_DrawPatch(34, 160, PatchINVBAR); - } - DrawInventoryBar(); - SB_state = 1; - } - } - SB_PaletteFlash(); - - // Flight icons - if (CPlayer->powers[pw_flight]) - { - if (CPlayer->powers[pw_flight] > BLINKTHRESHOLD - || !(CPlayer->powers[pw_flight] & 16)) - { - frame = (leveltime / 3) & 15; - if (CPlayer->mo->flags2 & MF2_FLY) - { - if (hitCenterFrame && (frame != 15 && frame != 0)) - { - V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + 15, - PU_CACHE)); - } - else - { - V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + frame, - PU_CACHE)); - hitCenterFrame = false; - } - } - else - { - if (!hitCenterFrame && (frame != 15 && frame != 0)) - { - V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + frame, - PU_CACHE)); - hitCenterFrame = false; - } - else - { - V_DrawPatch(20, 17, W_CacheLumpNum(spinflylump + 15, - PU_CACHE)); - hitCenterFrame = true; - } - } - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - else - { - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - } - - if (CPlayer->powers[pw_weaponlevel2] && !CPlayer->chickenTics) - { - if (CPlayer->powers[pw_weaponlevel2] > BLINKTHRESHOLD - || !(CPlayer->powers[pw_weaponlevel2] & 16)) - { - frame = (leveltime / 3) & 15; - V_DrawPatch(300, 17, - W_CacheLumpNum(spinbooklump + frame, PU_CACHE)); - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - else - { - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - } -/* - if(CPlayer->powers[pw_weaponlevel2] > BLINKTHRESHOLD - || (CPlayer->powers[pw_weaponlevel2]&8)) - { - V_DrawPatch(291, 0, W_CacheLumpName("ARTIPWBK", PU_CACHE)); - } - else - { - BorderTopRefresh = true; - } - } -*/ -} - -// sets the new palette based upon current values of player->damagecount -// and player->bonuscount -void SB_PaletteFlash(void) -{ - static int sb_palette = 0; - int palette; - byte *pal; - - CPlayer = &players[consoleplayer]; - - if (CPlayer->damagecount) - { - palette = (CPlayer->damagecount + 7) >> 3; - if (palette >= NUMREDPALS) - { - palette = NUMREDPALS - 1; - } - palette += STARTREDPALS; - } - else if (CPlayer->bonuscount) - { - palette = (CPlayer->bonuscount + 7) >> 3; - if (palette >= NUMBONUSPALS) - { - palette = NUMBONUSPALS - 1; - } - palette += STARTBONUSPALS; - } - else - { - palette = 0; - } - if (palette != sb_palette) - { - sb_palette = palette; - pal = (byte *) W_CacheLumpNum(playpalette, PU_CACHE) + palette * 768; - I_SetPalette(pal); - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawCommonBar -// -//--------------------------------------------------------------------------- - -void DrawCommonBar(void) -{ - int chainY; - int healthPos; - - V_DrawPatch(0, 148, PatchLTFCTOP); - V_DrawPatch(290, 148, PatchRTFCTOP); - - if (oldhealth != HealthMarker) - { - oldhealth = HealthMarker; - healthPos = HealthMarker; - if (healthPos < 0) - { - healthPos = 0; - } - if (healthPos > 100) - { - healthPos = 100; - } - healthPos = (healthPos * 256) / 100; - chainY = - (HealthMarker == CPlayer->mo->health) ? 191 : 191 + ChainWiggle; - V_DrawPatch(0, 190, PatchCHAINBACK); - V_DrawPatch(2 + (healthPos % 17), chainY, PatchCHAIN); - V_DrawPatch(17 + healthPos, chainY, PatchLIFEGEM); - V_DrawPatch(0, 190, PatchLTFACE); - V_DrawPatch(276, 190, PatchRTFACE); - ShadeChain(); - UpdateState |= I_STATBAR; - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawMainBar -// -//--------------------------------------------------------------------------- - -void DrawMainBar(void) -{ - int i; - int temp; - - // Ready artifact - if (ArtifactFlash) - { - V_DrawPatch(180, 161, PatchBLACKSQ); - - temp = W_GetNumForName(DEH_String("useartia")) + ArtifactFlash - 1; - - V_DrawPatch(182, 161, W_CacheLumpNum(temp, PU_CACHE)); - ArtifactFlash--; - oldarti = -1; // so that the correct artifact fills in after the flash - UpdateState |= I_STATBAR; - } - else if (oldarti != CPlayer->readyArtifact - || oldartiCount != CPlayer->inventory[inv_ptr].count) - { - V_DrawPatch(180, 161, PatchBLACKSQ); - if (CPlayer->readyArtifact > 0) - { - V_DrawPatch(179, 160, - W_CacheLumpName(DEH_String(patcharti[CPlayer->readyArtifact]), - PU_CACHE)); - DrSmallNumber(CPlayer->inventory[inv_ptr].count, 201, 182); - } - oldarti = CPlayer->readyArtifact; - oldartiCount = CPlayer->inventory[inv_ptr].count; - UpdateState |= I_STATBAR; - } - - // Frags - if (deathmatch) - { - temp = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - temp += CPlayer->frags[i]; - } - if (temp != oldfrags) - { - V_DrawPatch(57, 171, PatchARMCLEAR); - DrINumber(temp, 61, 170); - oldfrags = temp; - UpdateState |= I_STATBAR; - } - } - else - { - temp = HealthMarker; - if (temp < 0) - { - temp = 0; - } - else if (temp > 100) - { - temp = 100; - } - if (oldlife != temp) - { - oldlife = temp; - V_DrawPatch(57, 171, PatchARMCLEAR); - DrINumber(temp, 61, 170); - UpdateState |= I_STATBAR; - } - } - - // Keys - if (oldkeys != playerkeys) - { - if (CPlayer->keys[key_yellow]) - { - V_DrawPatch(153, 164, W_CacheLumpName(DEH_String("ykeyicon"), PU_CACHE)); - } - if (CPlayer->keys[key_green]) - { - V_DrawPatch(153, 172, W_CacheLumpName(DEH_String("gkeyicon"), PU_CACHE)); - } - if (CPlayer->keys[key_blue]) - { - V_DrawPatch(153, 180, W_CacheLumpName(DEH_String("bkeyicon"), PU_CACHE)); - } - oldkeys = playerkeys; - UpdateState |= I_STATBAR; - } - // Ammo - temp = CPlayer->ammo[wpnlev1info[CPlayer->readyweapon].ammo]; - if (oldammo != temp || oldweapon != CPlayer->readyweapon) - { - V_DrawPatch(108, 161, PatchBLACKSQ); - if (temp && CPlayer->readyweapon > 0 && CPlayer->readyweapon < 7) - { - DrINumber(temp, 109, 162); - V_DrawPatch(111, 172, - W_CacheLumpName(DEH_String(ammopic[CPlayer->readyweapon - 1]), - PU_CACHE)); - } - oldammo = temp; - oldweapon = CPlayer->readyweapon; - UpdateState |= I_STATBAR; - } - - // Armor - if (oldarmor != CPlayer->armorpoints) - { - V_DrawPatch(224, 171, PatchARMCLEAR); - DrINumber(CPlayer->armorpoints, 228, 170); - oldarmor = CPlayer->armorpoints; - UpdateState |= I_STATBAR; - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawInventoryBar -// -//--------------------------------------------------------------------------- - -void DrawInventoryBar(void) -{ - const char *patch; - int i; - int x; - - x = inv_ptr - curpos; - UpdateState |= I_STATBAR; - V_DrawPatch(34, 160, PatchINVBAR); - for (i = 0; i < 7; i++) - { - //V_DrawPatch(50+i*31, 160, W_CacheLumpName("ARTIBOX", PU_CACHE)); - if (CPlayer->inventorySlotNum > x + i - && CPlayer->inventory[x + i].type != arti_none) - { - patch = DEH_String(patcharti[CPlayer->inventory[x + i].type]); - - V_DrawPatch(50 + i * 31, 160, W_CacheLumpName(patch, PU_CACHE)); - DrSmallNumber(CPlayer->inventory[x + i].count, 69 + i * 31, 182); - } - } - V_DrawPatch(50 + curpos * 31, 189, PatchSELECTBOX); - if (x != 0) - { - V_DrawPatch(38, 159, !(leveltime & 4) ? PatchINVLFGEM1 : - PatchINVLFGEM2); - } - if (CPlayer->inventorySlotNum - x > 7) - { - V_DrawPatch(269, 159, !(leveltime & 4) ? - PatchINVRTGEM1 : PatchINVRTGEM2); - } -} - -void DrawFullScreenStuff(void) -{ - const char *patch; - int i; - int x; - int temp; - - UpdateState |= I_FULLSCRN; - if (CPlayer->mo->health > 0) - { - DrBNumber(CPlayer->mo->health, 5, 180); - } - else - { - DrBNumber(0, 5, 180); - } - if (deathmatch) - { - temp = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - temp += CPlayer->frags[i]; - } - } - DrINumber(temp, 45, 185); - } - if (!inventory) - { - if (CPlayer->readyArtifact > 0) - { - patch = DEH_String(patcharti[CPlayer->readyArtifact]); - V_DrawAltTLPatch(286, 170, W_CacheLumpName(DEH_String("ARTIBOX"), PU_CACHE)); - V_DrawPatch(286, 170, W_CacheLumpName(patch, PU_CACHE)); - DrSmallNumber(CPlayer->inventory[inv_ptr].count, 307, 192); - } - } - else - { - x = inv_ptr - curpos; - for (i = 0; i < 7; i++) - { - V_DrawAltTLPatch(50 + i * 31, 168, - W_CacheLumpName(DEH_String("ARTIBOX"), PU_CACHE)); - if (CPlayer->inventorySlotNum > x + i - && CPlayer->inventory[x + i].type != arti_none) - { - patch = DEH_String(patcharti[CPlayer->inventory[x + i].type]); - V_DrawPatch(50 + i * 31, 168, - W_CacheLumpName(patch, PU_CACHE)); - DrSmallNumber(CPlayer->inventory[x + i].count, 69 + i * 31, - 190); - } - } - V_DrawPatch(50 + curpos * 31, 197, PatchSELECTBOX); - if (x != 0) - { - V_DrawPatch(38, 167, !(leveltime & 4) ? PatchINVLFGEM1 : - PatchINVLFGEM2); - } - if (CPlayer->inventorySlotNum - x > 7) - { - V_DrawPatch(269, 167, !(leveltime & 4) ? - PatchINVRTGEM1 : PatchINVRTGEM2); - } - } -} - -//-------------------------------------------------------------------------- -// -// FUNC SB_Responder -// -//-------------------------------------------------------------------------- - -boolean SB_Responder(event_t * event) -{ - if (event->type == ev_keydown) - { - if (HandleCheats(event->data1)) - { // Need to eat the key - return (true); - } - } - return (false); -} - -//-------------------------------------------------------------------------- -// -// FUNC HandleCheats -// -// Returns true if the caller should eat the key. -// -//-------------------------------------------------------------------------- - -static boolean HandleCheats(byte key) -{ - int i; - boolean eat; - - if (netgame || gameskill == sk_nightmare) - { // Can't cheat in a net-game, or in nightmare mode - return (false); - } - if (players[consoleplayer].health <= 0) - { // Dead players can't cheat - return (false); - } - eat = false; - for (i = 0; Cheats[i].func != NULL; i++) - { - if (cht_CheckCheat(Cheats[i].seq, key)) - { - Cheats[i].func(&players[consoleplayer], &Cheats[i]); - S_StartSound(NULL, sfx_dorcls); - } - } - return (eat); -} - -//-------------------------------------------------------------------------- -// -// CHEAT FUNCTIONS -// -//-------------------------------------------------------------------------- - -static void CheatGodFunc(player_t * player, Cheat_t * cheat) -{ - player->cheats ^= CF_GODMODE; - if (player->cheats & CF_GODMODE) - { - P_SetMessage(player, DEH_String(TXT_CHEATGODON), false); - } - else - { - P_SetMessage(player, DEH_String(TXT_CHEATGODOFF), false); - } - SB_state = -1; -} - -static void CheatNoClipFunc(player_t * player, Cheat_t * cheat) -{ - player->cheats ^= CF_NOCLIP; - if (player->cheats & CF_NOCLIP) - { - P_SetMessage(player, DEH_String(TXT_CHEATNOCLIPON), false); - } - else - { - P_SetMessage(player, DEH_String(TXT_CHEATNOCLIPOFF), false); - } -} - -static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat) -{ - int i; - - player->armorpoints = 200; - player->armortype = 2; - if (!player->backpack) - { - for (i = 0; i < NUMAMMO; i++) - { - player->maxammo[i] *= 2; - } - player->backpack = true; - } - for (i = 0; i < NUMWEAPONS - 1; i++) - { - player->weaponowned[i] = true; - } - if (gamemode == shareware) - { - player->weaponowned[wp_skullrod] = false; - player->weaponowned[wp_phoenixrod] = false; - player->weaponowned[wp_mace] = false; - } - for (i = 0; i < NUMAMMO; i++) - { - player->ammo[i] = player->maxammo[i]; - } - P_SetMessage(player, DEH_String(TXT_CHEATWEAPONS), false); -} - -static void CheatPowerFunc(player_t * player, Cheat_t * cheat) -{ - if (player->powers[pw_weaponlevel2]) - { - player->powers[pw_weaponlevel2] = 0; - P_SetMessage(player, DEH_String(TXT_CHEATPOWEROFF), false); - } - else - { - P_UseArtifact(player, arti_tomeofpower); - P_SetMessage(player, DEH_String(TXT_CHEATPOWERON), false); - } -} - -static void CheatHealthFunc(player_t * player, Cheat_t * cheat) -{ - if (player->chickenTics) - { - player->health = player->mo->health = MAXCHICKENHEALTH; - } - else - { - player->health = player->mo->health = MAXHEALTH; - } - P_SetMessage(player, DEH_String(TXT_CHEATHEALTH), false); -} - -static void CheatKeysFunc(player_t * player, Cheat_t * cheat) -{ - player->keys[key_yellow] = true; - player->keys[key_green] = true; - player->keys[key_blue] = true; - playerkeys = 7; // Key refresh flags - P_SetMessage(player, DEH_String(TXT_CHEATKEYS), false); -} - -static void CheatSoundFunc(player_t * player, Cheat_t * cheat) -{ - DebugSound = !DebugSound; - if (DebugSound) - { - P_SetMessage(player, DEH_String(TXT_CHEATSOUNDON), false); - } - else - { - P_SetMessage(player, DEH_String(TXT_CHEATSOUNDOFF), false); - } -} - -static void CheatTickerFunc(player_t * player, Cheat_t * cheat) -{ - DisplayTicker = !DisplayTicker; - if (DisplayTicker) - { - P_SetMessage(player, DEH_String(TXT_CHEATTICKERON), false); - } - else - { - P_SetMessage(player, DEH_String(TXT_CHEATTICKEROFF), false); - } - - I_DisplayFPSDots(DisplayTicker); -} - -static void CheatArtifact1Func(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS1), false); -} - -static void CheatArtifact2Func(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS2), false); -} - -static void CheatArtifact3Func(player_t * player, Cheat_t * cheat) -{ - char args[2]; - int i; - int j; - int type; - int count; - - cht_GetParam(cheat->seq, args); - type = args[0] - 'a' + 1; - count = args[1] - '0'; - if (type == 26 && count == 0) - { // All artifacts - for (i = arti_none + 1; i < NUMARTIFACTS; i++) - { - if (gamemode == shareware - && (i == arti_superhealth || i == arti_teleport)) - { - continue; - } - for (j = 0; j < 16; j++) - { - P_GiveArtifact(player, i, NULL); - } - } - P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS3), false); - } - else if (type > arti_none && type < NUMARTIFACTS - && count > 0 && count < 10) - { - if (gamemode == shareware - && (type == arti_superhealth || type == arti_teleport)) - { - P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTSFAIL), false); - return; - } - for (i = 0; i < count; i++) - { - P_GiveArtifact(player, type, NULL); - } - P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS3), false); - } - else - { // Bad input - P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTSFAIL), false); - } -} - -static void CheatWarpFunc(player_t * player, Cheat_t * cheat) -{ - char args[2]; - int episode; - int map; - - cht_GetParam(cheat->seq, args); - - episode = args[0] - '0'; - map = args[1] - '0'; - if (D_ValidEpisodeMap(heretic, gamemode, episode, map)) - { - G_DeferedInitNew(gameskill, episode, map); - P_SetMessage(player, DEH_String(TXT_CHEATWARP), false); - } -} - -static void CheatChickenFunc(player_t * player, Cheat_t * cheat) -{ - if (player->chickenTics) - { - if (P_UndoPlayerChicken(player)) - { - P_SetMessage(player, DEH_String(TXT_CHEATCHICKENOFF), false); - } - } - else if (P_ChickenMorphPlayer(player)) - { - P_SetMessage(player, DEH_String(TXT_CHEATCHICKENON), false); - } -} - -static void CheatMassacreFunc(player_t * player, Cheat_t * cheat) -{ - P_Massacre(); - P_SetMessage(player, DEH_String(TXT_CHEATMASSACRE), false); -} - -static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat) -{ - int i; - if (player->chickenTics) - { - return; - } - for (i = 1; i < 8; i++) - { - player->weaponowned[i] = false; - } - player->pendingweapon = wp_staff; - P_SetMessage(player, DEH_String(TXT_CHEATIDKFA), true); -} - -static void CheatIDDQDFunc(player_t * player, Cheat_t * cheat) -{ - P_DamageMobj(player->mo, NULL, player->mo, 10000); - P_SetMessage(player, DEH_String(TXT_CHEATIDDQD), true); -} diff --git a/games/NXDoom/src/heretic/sounds.c b/games/NXDoom/src/heretic/sounds.c deleted file mode 100644 index 3e1dda157ad..00000000000 --- a/games/NXDoom/src/heretic/sounds.c +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// sounds.c - -#include "doomdef.h" -#include "i_sound.h" -#include "sounds.h" - -// Music info - -#define MUSIC(name) \ - { name, 0, NULL, NULL } - -musicinfo_t S_music[] = { - MUSIC("MUS_E1M1"), // 1-1 - MUSIC("MUS_E1M2"), - MUSIC("MUS_E1M3"), - MUSIC("MUS_E1M4"), - MUSIC("MUS_E1M5"), - MUSIC("MUS_E1M6"), - MUSIC("MUS_E1M7"), - MUSIC("MUS_E1M8"), - MUSIC("MUS_E1M9"), - - MUSIC("MUS_E2M1"), // 2-1 - MUSIC("MUS_E2M2"), - MUSIC("MUS_E2M3"), - MUSIC("MUS_E2M4"), - MUSIC("MUS_E1M4"), - MUSIC("MUS_E2M6"), - MUSIC("MUS_E2M7"), - MUSIC("MUS_E2M8"), - MUSIC("MUS_E2M9"), - - MUSIC("MUS_E1M1"), // 3-1 - MUSIC("MUS_E3M2"), - MUSIC("MUS_E3M3"), - MUSIC("MUS_E1M6"), - MUSIC("MUS_E1M3"), - MUSIC("MUS_E1M2"), - MUSIC("MUS_E1M5"), - MUSIC("MUS_E1M9"), - MUSIC("MUS_E2M6"), - - MUSIC("MUS_E1M6"), // 4-1 - MUSIC("MUS_E1M2"), - MUSIC("MUS_E1M3"), - MUSIC("MUS_E1M4"), - MUSIC("MUS_E1M5"), - MUSIC("MUS_E1M1"), - MUSIC("MUS_E1M7"), - MUSIC("MUS_E1M8"), - MUSIC("MUS_E1M9"), - - MUSIC("MUS_E2M1"), // 5-1 - MUSIC("MUS_E2M2"), - MUSIC("MUS_E2M3"), - MUSIC("MUS_E2M4"), - MUSIC("MUS_E1M4"), - MUSIC("MUS_E2M6"), - MUSIC("MUS_E2M7"), - MUSIC("MUS_E2M8"), - MUSIC("MUS_E2M9"), - - MUSIC("MUS_E3M2"), // 6-1 - MUSIC("MUS_E3M3"), // 6-2 - MUSIC("MUS_E1M6"), // 6-3 - - MUSIC("MUS_TITL"), - MUSIC("MUS_INTR"), - MUSIC("MUS_CPTD") -}; - -// Sound info - - /* Macro for original heretic sfxinfo_t -#define SOUND(name, priority, numchannels) \ - { name, NULL, priority, -1, NULL, 0, numchannels } -#define SOUND_LINK(name, link_id, priority, numchannels) \ - { name, &S_sfx[link_id], priority, -1, NULL, 0, numchannels } - */ - -#define SOUND(name, priority, numchannels) \ - { NULL, name, priority, NULL, -1, -1, -1, 0, numchannels, NULL } -#define SOUND_LINK(name, link_id, priority, numchannels) \ - { NULL, name, priority, &S_sfx[link_id], 0, 0, -1, 0, numchannels, NULL } - -sfxinfo_t S_sfx[] = { - SOUND("", 0, 0), - SOUND("gldhit", 32, 2), - SOUND("gntful", 32, -1), - SOUND("gnthit", 32, -1), - SOUND("gntpow", 32, -1), - SOUND("gntact", 32, -1), - SOUND("gntuse", 32, -1), - SOUND("phosht", 32, 2), - SOUND("phohit", 32, -1), - SOUND_LINK("-phopow", sfx_hedat1, 32, 1), - SOUND("lobsht", 20, 2), - SOUND("lobhit", 20, 2), - SOUND("lobpow", 20, 2), - SOUND("hrnsht", 32, 2), - SOUND("hrnhit", 32, 2), - SOUND("hrnpow", 32, 2), - SOUND("ramphit", 32, 2), - SOUND("ramrain", 10, 2), - SOUND("bowsht", 32, 2), - SOUND("stfhit", 32, 2), - SOUND("stfpow", 32, 2), - SOUND("stfcrk", 32, 2), - SOUND("impsit", 32, 2), - SOUND("impat1", 32, 2), - SOUND("impat2", 32, 2), - SOUND("impdth", 80, 2), - SOUND_LINK("-impact", sfx_impsit, 20, 2), - SOUND("imppai", 32, 2), - SOUND("mumsit", 32, 2), - SOUND("mumat1", 32, 2), - SOUND("mumat2", 32, 2), - SOUND("mumdth", 80, 2), - SOUND_LINK("-mumact", sfx_mumsit, 20, 2), - SOUND("mumpai", 32, 2), - SOUND("mumhed", 32, 2), - SOUND("bstsit", 32, 2), - SOUND("bstatk", 32, 2), - SOUND("bstdth", 80, 2), - SOUND("bstact", 20, 2), - SOUND("bstpai", 32, 2), - SOUND("clksit", 32, 2), - SOUND("clkatk", 32, 2), - SOUND("clkdth", 80, 2), - SOUND("clkact", 20, 2), - SOUND("clkpai", 32, 2), - SOUND("snksit", 32, 2), - SOUND("snkatk", 32, 2), - SOUND("snkdth", 80, 2), - SOUND("snkact", 20, 2), - SOUND("snkpai", 32, 2), - SOUND("kgtsit", 32, 2), - SOUND("kgtatk", 32, 2), - SOUND("kgtat2", 32, 2), - SOUND("kgtdth", 80, 2), - SOUND_LINK("-kgtact", sfx_kgtsit, 20, 2), - SOUND("kgtpai", 32, 2), - SOUND("wizsit", 32, 2), - SOUND("wizatk", 32, 2), - SOUND("wizdth", 80, 2), - SOUND("wizact", 20, 2), - SOUND("wizpai", 32, 2), - SOUND("minsit", 32, 2), - SOUND("minat1", 32, 2), - SOUND("minat2", 32, 2), - SOUND("minat3", 32, 2), - SOUND("mindth", 80, 2), - SOUND("minact", 20, 2), - SOUND("minpai", 32, 2), - SOUND("hedsit", 32, 2), - SOUND("hedat1", 32, 2), - SOUND("hedat2", 32, 2), - SOUND("hedat3", 32, 2), - SOUND("heddth", 80, 2), - SOUND("hedact", 20, 2), - SOUND("hedpai", 32, 2), - SOUND("sorzap", 32, 2), - SOUND("sorrise", 32, 2), - SOUND("sorsit", 200, 2), - SOUND("soratk", 32, 2), - SOUND("soract", 200, 2), - SOUND("sorpai", 200, 2), - SOUND("sordsph", 200, 2), - SOUND("sordexp", 200, 2), - SOUND("sordbon", 200, 2), - SOUND_LINK("-sbtsit", sfx_bstsit, 32, 2), - SOUND_LINK("-sbtatk", sfx_bstatk, 32, 2), - SOUND("sbtdth", 80, 2), - SOUND("sbtact", 20, 2), - SOUND("sbtpai", 32, 2), - SOUND("plroof", 32, 2), - SOUND("plrpai", 32, 2), - SOUND("plrdth", 80, 2), - SOUND("gibdth", 100, 2), - SOUND("plrwdth", 80, 2), - SOUND("plrcdth", 100, 2), - SOUND("itemup", 32, 2), - SOUND("wpnup", 32, 2), - SOUND("telept", 50, 2), - SOUND("doropn", 40, 2), - SOUND("dorcls", 40, 2), - SOUND("dormov", 40, 2), - SOUND("artiup", 32, 2), - SOUND("switch", 40, 2), - SOUND("pstart", 40, 2), - SOUND("pstop", 40, 2), - SOUND("stnmov", 40, 2), - SOUND("chicpai", 32, 2), - SOUND("chicatk", 32, 2), - SOUND("chicdth", 40, 2), - SOUND("chicact", 32, 2), - SOUND("chicpk1", 32, 2), - SOUND("chicpk2", 32, 2), - SOUND("chicpk3", 32, 2), - SOUND("keyup", 50, 2), - SOUND("ripslop", 16, 2), - SOUND("newpod", 16, -1), - SOUND("podexp", 40, -1), - SOUND("bounce", 16, 2), - SOUND_LINK("-volsht", sfx_bstatk, 16, 2), - SOUND_LINK("-volhit", sfx_lobhit, 16, 2), - SOUND("burn", 10, 2), - SOUND("splash", 10, 1), - SOUND("gloop", 10, 2), - SOUND("respawn", 10, 1), - SOUND("blssht", 32, 2), - SOUND("blshit", 32, 2), - SOUND("chat", 100, 1), - SOUND("artiuse", 32, 1), - SOUND("gfrag", 100, 1), - SOUND("waterfl", 16, 2), - - // Monophonic sounds - - SOUND("wind", 16, 1), - SOUND("amb1", 1, 1), - SOUND("amb2", 1, 1), - SOUND("amb3", 1, 1), - SOUND("amb4", 1, 1), - SOUND("amb5", 1, 1), - SOUND("amb6", 1, 1), - SOUND("amb7", 1, 1), - SOUND("amb8", 1, 1), - SOUND("amb9", 1, 1), - SOUND("amb10", 1, 1), - SOUND("amb11", 1, 0) -}; diff --git a/games/NXDoom/src/heretic/sounds.h b/games/NXDoom/src/heretic/sounds.h deleted file mode 100644 index f49b0279843..00000000000 --- a/games/NXDoom/src/heretic/sounds.h +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// sounds.h - -#ifndef __SOUNDSH__ -#define __SOUNDSH__ - -#include "i_sound.h" - -#define MAX_SND_DIST 1600 -#define MAX_CHANNELS 16 - -// Music identifiers - -typedef enum -{ - mus_e1m1, - mus_e1m2, - mus_e1m3, - mus_e1m4, - mus_e1m5, - mus_e1m6, - mus_e1m7, - mus_e1m8, - mus_e1m9, - - mus_e2m1, - mus_e2m2, - mus_e2m3, - mus_e2m4, - mus_e2m5, - mus_e2m6, - mus_e2m7, - mus_e2m8, - mus_e2m9, - - mus_e3m1, - mus_e3m2, - mus_e3m3, - mus_e3m4, - mus_e3m5, - mus_e3m6, - mus_e3m7, - mus_e3m8, - mus_e3m9, - - mus_e4m1, - mus_e4m2, - mus_e4m3, - mus_e4m4, - mus_e4m5, - mus_e4m6, - mus_e4m7, - mus_e4m8, - mus_e4m9, - - mus_e5m1, - mus_e5m2, - mus_e5m3, - mus_e5m4, - mus_e5m5, - mus_e5m6, - mus_e5m7, - mus_e5m8, - mus_e5m9, - - mus_e6m1, - mus_e6m2, - mus_e6m3, - - mus_titl, - mus_intr, - mus_cptd, - NUMMUSIC -} musicenum_t; - -#if 0 -typedef struct -{ - char name[8]; -} musicinfo_t; - -typedef struct sfxinfo_s -{ - char name[8]; - struct sfxinfo_s *link; // Make alias for another sound - unsigned short priority; // Higher priority takes precendence - int usefulness; // Determines when a sound should be cached out - void *snd_ptr; - int lumpnum; - int numchannels; // total number of channels a sound type may occupy -} sfxinfo_t; - -#endif - -typedef struct -{ - mobj_t *mo; - int sound_id; - int handle; - int pitch; - int priority; -} channel_t; - -typedef struct -{ - int id; - unsigned short priority; - char *name; - mobj_t *mo; - int distance; -} ChanInfo_t; - -typedef struct -{ - int channelCount; - int musicVolume; - int soundVolume; - ChanInfo_t chan[8]; -} SoundInfo_t; - -// Sound identifiers - -typedef enum -{ - sfx_None, - sfx_gldhit, - sfx_gntful, - sfx_gnthit, - sfx_gntpow, - sfx_gntact, - sfx_gntuse, - sfx_phosht, - sfx_phohit, - sfx_phopow, - sfx_lobsht, - sfx_lobhit, - sfx_lobpow, - sfx_hrnsht, - sfx_hrnhit, - sfx_hrnpow, - sfx_ramphit, - sfx_ramrain, - sfx_bowsht, - sfx_stfhit, - sfx_stfpow, - sfx_stfcrk, - sfx_impsit, - sfx_impat1, - sfx_impat2, - sfx_impdth, - sfx_impact, - sfx_imppai, - sfx_mumsit, - sfx_mumat1, - sfx_mumat2, - sfx_mumdth, - sfx_mumact, - sfx_mumpai, - sfx_mumhed, - sfx_bstsit, - sfx_bstatk, - sfx_bstdth, - sfx_bstact, - sfx_bstpai, - sfx_clksit, - sfx_clkatk, - sfx_clkdth, - sfx_clkact, - sfx_clkpai, - sfx_snksit, - sfx_snkatk, - sfx_snkdth, - sfx_snkact, - sfx_snkpai, - sfx_kgtsit, - sfx_kgtatk, - sfx_kgtat2, - sfx_kgtdth, - sfx_kgtact, - sfx_kgtpai, - sfx_wizsit, - sfx_wizatk, - sfx_wizdth, - sfx_wizact, - sfx_wizpai, - sfx_minsit, - sfx_minat1, - sfx_minat2, - sfx_minat3, - sfx_mindth, - sfx_minact, - sfx_minpai, - sfx_hedsit, - sfx_hedat1, - sfx_hedat2, - sfx_hedat3, - sfx_heddth, - sfx_hedact, - sfx_hedpai, - sfx_sorzap, - sfx_sorrise, - sfx_sorsit, - sfx_soratk, - sfx_soract, - sfx_sorpai, - sfx_sordsph, - sfx_sordexp, - sfx_sordbon, - sfx_sbtsit, - sfx_sbtatk, - sfx_sbtdth, - sfx_sbtact, - sfx_sbtpai, - sfx_plroof, - sfx_plrpai, - sfx_plrdth, // Normal - sfx_gibdth, // Extreme - sfx_plrwdth, // Wimpy - sfx_plrcdth, // Crazy - sfx_itemup, - sfx_wpnup, - sfx_telept, - sfx_doropn, - sfx_dorcls, - sfx_dormov, - sfx_artiup, - sfx_switch, - sfx_pstart, - sfx_pstop, - sfx_stnmov, - sfx_chicpai, - sfx_chicatk, - sfx_chicdth, - sfx_chicact, - sfx_chicpk1, - sfx_chicpk2, - sfx_chicpk3, - sfx_keyup, - sfx_ripslop, - sfx_newpod, - sfx_podexp, - sfx_bounce, - sfx_volsht, - sfx_volhit, - sfx_burn, - sfx_splash, - sfx_gloop, - sfx_respawn, - sfx_blssht, - sfx_blshit, - sfx_chat, - sfx_artiuse, - sfx_gfrag, - sfx_waterfl, - - // Monophonic sounds - - sfx_wind, - sfx_amb1, - sfx_amb2, - sfx_amb3, - sfx_amb4, - sfx_amb5, - sfx_amb6, - sfx_amb7, - sfx_amb8, - sfx_amb9, - sfx_amb10, - sfx_amb11, - NUMSFX -} sfxenum_t; - -extern sfxinfo_t S_sfx[]; -extern musicinfo_t S_music[]; - -#endif diff --git a/games/NXDoom/src/hexen-res.rc.in b/games/NXDoom/src/hexen-res.rc.in deleted file mode 100644 index b2b811b6027..00000000000 --- a/games/NXDoom/src/hexen-res.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -1 ICON "@top_srcdir@/data/hexen.ico" - -#include - -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" - -1 VERSIONINFO -PRODUCTVERSION @WINDOWS_RC_VERSION@ -FILEVERSION @WINDOWS_RC_VERSION@ -FILETYPE 1 -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "@PACKAGE_VERSION@.0" - VALUE "FileDescription", "@PACKAGE_STRING@" - VALUE "InternalName", "@PACKAGE_TARNAME@" - VALUE "CompanyName", "@PACKAGE_BUGREPORT@" - VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" - VALUE "ProductName", "@PACKAGE_NAME@" - VALUE "ProductVersion", "@PACKAGE_VERSION@" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - diff --git a/games/NXDoom/src/hexen/.gitignore b/games/NXDoom/src/hexen/.gitignore deleted file mode 100644 index d4e88e5a219..00000000000 --- a/games/NXDoom/src/hexen/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -Makefile -Makefile.in -.deps -tags -TAGS diff --git a/games/NXDoom/src/hexen/CMakeLists.txt b/games/NXDoom/src/hexen/CMakeLists.txt deleted file mode 100644 index 3eba5d07305..00000000000 --- a/games/NXDoom/src/hexen/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ -add_library(hexen STATIC - a_action.c - am_data.h - am_map.c am_map.h - ct_chat.c - ct_chat.h - d_net.c - f_finale.c - g_game.c - h2def.h - h2_main.c - info.c info.h - in_lude.c - m_random.c m_random.h - mn_menu.c - p_acs.c - p_action.h - p_anim.c - p_ceilng.c - p_doors.c - p_enemy.c - p_floor.c - p_inter.c - p_lights.c - p_local.h - p_map.c - p_maputl.c - p_mobj.c - po_man.c - p_plats.c - p_pspr.c - p_setup.c - p_sight.c - p_spec.c p_spec.h - p_switch.c - p_telept.c - p_things.c - p_tick.c - p_user.c - r_bsp.c - r_data.c - r_draw.c - r_local.h - r_main.c - r_plane.c - r_segs.c - r_things.c - s_sound.c s_sound.h - sb_bar.c - sc_man.c - sn_sonix.c - sounds.c sounds.h - st_start.c st_start.h - sv_save.c - textdefs.h - xddefs.h) - -target_include_directories(hexen PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") -if (DEFINED EMSCRIPTEN) - set(SDL_FLAGS "-s USE_SDL=2") - if(ENABLE_SDL2_MIXER) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") - endif() - if(ENABLE_SDL2_NET) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") - endif() -else() - set(SDL_LINK_LIBS SDL2::SDL2) - if(ENABLE_SDL2_MIXER) - list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) - endif() - if(ENABLE_SDL2_NET) - list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) - endif() -endif() -target_link_libraries(hexen ${SDL_LINK_LIBS}) -set_target_properties(hexen PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") -set_target_properties(hexen PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/hexen/Makefile.am b/games/NXDoom/src/hexen/Makefile.am deleted file mode 100644 index c974ba3c80b..00000000000 --- a/games/NXDoom/src/hexen/Makefile.am +++ /dev/null @@ -1,71 +0,0 @@ -AM_CFLAGS=-I$(top_srcdir)/src @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ - -EXTRA_DIST = \ - CMakeLists.txt \ - hexen_icon.c - -noinst_LIBRARIES=libhexen.a - -libhexen_a_SOURCES = \ -a_action.c \ - am_data.h \ -am_map.c am_map.h \ -ct_chat.c \ - ct_chat.h \ -d_net.c \ -f_finale.c \ -g_game.c \ - h2def.h \ -h2_main.c \ -info.c info.h \ -in_lude.c \ -m_random.c m_random.h \ -mn_menu.c \ -p_acs.c \ - p_action.h \ -p_anim.c \ -p_ceilng.c \ -p_doors.c \ -p_enemy.c \ -p_floor.c \ -p_inter.c \ -p_lights.c \ - p_local.h \ -p_map.c \ -p_maputl.c \ -p_mobj.c \ -po_man.c \ -p_plats.c \ -p_pspr.c \ -p_setup.c \ -p_sight.c \ -p_spec.c p_spec.h \ -p_switch.c \ -p_telept.c \ -p_things.c \ -p_tick.c \ -p_user.c \ -r_bsp.c \ -r_data.c \ -r_draw.c \ - r_local.h \ -r_main.c \ -r_plane.c \ -r_segs.c \ -r_things.c \ -s_sound.c s_sound.h \ -sb_bar.c \ -sc_man.c \ -sn_sonix.c \ -sounds.c sounds.h \ -st_start.c st_start.h \ -sv_save.c \ - textdefs.h \ - xddefs.h - -if HAVE_ICONS - -hexen_icon.c : $(top_builddir)/data/hexen.png - $(top_builddir)/data/convert-icon $(top_builddir)/data/hexen.png $@ - -endif diff --git a/games/NXDoom/src/hexen/a_action.c b/games/NXDoom/src/hexen/a_action.c deleted file mode 100644 index 7842f556a34..00000000000 --- a/games/NXDoom/src/hexen/a_action.c +++ /dev/null @@ -1,1341 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- -int orbitTableX[256] = { - 983025, 982725, 981825, 980340, 978255, 975600, 972330, 968490, - 964065, 959070, 953475, 947325, 940590, 933300, 925440, 917025, - 908055, 898545, 888495, 877905, 866775, 855135, 842985, 830310, - 817155, 803490, 789360, 774735, 759660, 744120, 728130, 711690, - 694845, 677565, 659880, 641805, 623340, 604500, 585285, 565725, - 545820, 525600, 505050, 484200, 463065, 441645, 419955, 398010, - 375840, 353430, 330810, 307995, 285000, 261825, 238485, 215010, - 191400, 167685, 143865, 119955, 95970, 71940, 47850, 23745, - -375, -24495, -48600, -72690, -96720, -120705, -144600, -168420, - -192150, -215745, -239220, -262545, -285720, -308715, -331530, -354135, - -376530, -398700, -420630, -442320, -463725, -484860, -505695, -526230, - -546450, -566340, -585885, -605085, -623925, -642375, -660435, -678105, - -695370, -712215, -728625, -744600, -760125, -775200, -789795, -803925, - -817575, -830715, -843375, -855510, -867135, -878235, -888810, -898845, - -908340, -917295, -925695, -933540, -940815, -947520, -953670, -959235, - -964215, -968625, -972450, -975690, -978330, -980400, -981870, -982740, - -983025, -982725, -981825, -980340, -978255, -975600, -972330, -968490, - -964065, -959070, -953475, -947325, -940590, -933300, -925440, -917025, - -908055, -898545, -888495, -877905, -866775, -855135, -842985, -830310, - -817155, -803490, -789360, -774735, -759660, -744120, -728130, -711690, - -694845, -677565, -659880, -641805, -623340, -604485, -585285, -565725, - -545820, -525600, -505050, -484200, -463065, -441645, -419955, -398010, - -375840, -353430, -330810, -307995, -285000, -261825, -238485, -215010, - -191400, -167685, -143865, -119955, -95970, -71940, -47850, -23745, - 375, 24495, 48600, 72690, 96720, 120705, 144600, 168420, - 192150, 215745, 239220, 262545, 285720, 308715, 331530, 354135, - 376530, 398700, 420630, 442320, 463725, 484860, 505695, 526230, - 546450, 566340, 585885, 605085, 623925, 642375, 660435, 678105, - 695370, 712215, 728625, 744600, 760125, 775200, 789795, 803925, - 817575, 830715, 843375, 855510, 867135, 878235, 888810, 898845, - 908340, 917295, 925695, 933540, 940815, 947520, 953670, 959235, - 964215, 968625, 972450, 975690, 978330, 980400, 981870, 982740 -}; - -int orbitTableY[256] = { - 375, 24495, 48600, 72690, 96720, 120705, 144600, 168420, - 192150, 215745, 239220, 262545, 285720, 308715, 331530, 354135, - 376530, 398700, 420630, 442320, 463725, 484860, 505695, 526230, - 546450, 566340, 585885, 605085, 623925, 642375, 660435, 678105, - 695370, 712215, 728625, 744600, 760125, 775200, 789795, 803925, - 817575, 830715, 843375, 855510, 867135, 878235, 888810, 898845, - 908340, 917295, 925695, 933540, 940815, 947520, 953670, 959235, - 964215, 968625, 972450, 975690, 978330, 980400, 981870, 982740, - 983025, 982725, 981825, 980340, 978255, 975600, 972330, 968490, - 964065, 959070, 953475, 947325, 940590, 933300, 925440, 917025, - 908055, 898545, 888495, 877905, 866775, 855135, 842985, 830310, - 817155, 803490, 789360, 774735, 759660, 744120, 728130, 711690, - 694845, 677565, 659880, 641805, 623340, 604500, 585285, 565725, - 545820, 525600, 505050, 484200, 463065, 441645, 419955, 398010, - 375840, 353430, 330810, 307995, 285000, 261825, 238485, 215010, - 191400, 167685, 143865, 119955, 95970, 71940, 47850, 23745, - -375, -24495, -48600, -72690, -96720, -120705, -144600, -168420, - -192150, -215745, -239220, -262545, -285720, -308715, -331530, -354135, - -376530, -398700, -420630, -442320, -463725, -484860, -505695, -526230, - -546450, -566340, -585885, -605085, -623925, -642375, -660435, -678105, - -695370, -712215, -728625, -744600, -760125, -775200, -789795, -803925, - -817575, -830715, -843375, -855510, -867135, -878235, -888810, -898845, - -908340, -917295, -925695, -933540, -940815, -947520, -953670, -959235, - -964215, -968625, -972450, -975690, -978330, -980400, -981870, -982740, - -983025, -982725, -981825, -980340, -978255, -975600, -972330, -968490, - -964065, -959070, -953475, -947325, -940590, -933300, -925440, -917025, - -908055, -898545, -888495, -877905, -866775, -855135, -842985, -830310, - -817155, -803490, -789360, -774735, -759660, -744120, -728130, -711690, - -694845, -677565, -659880, -641805, -623340, -604485, -585285, -565725, - -545820, -525600, -505050, -484200, -463065, -441645, -419955, -398010, - -375840, -353430, -330810, -307995, -285000, -261825, -238485, -215010, - -191400, -167685, -143865, -119955, -95970, -71940, -47850, -23745 -}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -// CODE -------------------------------------------------------------------- - -//-------------------------------------------------------------------------- -// -// Environmental Action routines -// -//-------------------------------------------------------------------------- - -//========================================================================== -// -// A_DripBlood -// -//========================================================================== - -/* -void A_DripBlood(mobj_t *actor) -{ - mobj_t *mo; - int r; - - r = P_SubRandom(); - - mo = P_SpawnMobj(actor->x+(r<<11), - actor->y+(P_SubRandom()<<11), actor->z, MT_BLOOD); - mo->momx = P_SubRandom()<<10; - mo->momy = P_SubRandom()<<10; - mo->flags2 |= MF2_LOGRAV; -} -*/ - -//============================================================================ -// -// A_PotteryExplode -// -//============================================================================ - -void A_PotteryExplode(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo = NULL; - int i; - - for (i = (P_Random() & 3) + 3; i; i--) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_POTTERYBIT1); - P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 5)); - mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4); - mo->momx = P_SubRandom() << (FRACBITS - 6); - mo->momy = P_SubRandom() << (FRACBITS - 6); - } - S_StartSound(mo, SFX_POTTERY_EXPLODE); - if (actor->args[0]) - { // Spawn an item - if (!nomonsters - || !(mobjinfo[TranslateThingType[actor->args[0]]]. - flags & MF_COUNTKILL)) - { // Only spawn monsters if not -nomonsters - P_SpawnMobj(actor->x, actor->y, actor->z, - TranslateThingType[actor->args[0]]); - } - } - P_RemoveMobj(actor); -} - -//============================================================================ -// -// A_PotteryChooseBit -// -//============================================================================ - -void A_PotteryChooseBit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SetMobjState(actor, actor->info->deathstate + (P_Random() % 5) + 1); - actor->tics = 256 + (P_Random() << 1); -} - -//============================================================================ -// -// A_PotteryCheck -// -//============================================================================ - -void A_PotteryCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - mobj_t *pmo; - - if (!netgame) - { - pmo = players[consoleplayer].mo; - if (P_CheckSight(actor, pmo) - && (abs((int)R_PointToAngle2(pmo->x, pmo->y, actor->x, actor->y) - - (int)pmo->angle) <= ANG45)) - { // Previous state (pottery bit waiting state) - P_SetMobjState(actor, actor->state - &states[0] - 1); - } - else - { - return; - } - } - else - { - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - { - continue; - } - pmo = players[i].mo; - if (P_CheckSight(actor, pmo) - && (abs((int)R_PointToAngle2(pmo->x, pmo->y, actor->x, actor->y) - - (int)pmo->angle) <= ANG45)) - { // Previous state (pottery bit waiting state) - P_SetMobjState(actor, actor->state - &states[0] - 1); - return; - } - } - } -} - -//============================================================================ -// -// A_CorpseBloodDrip -// -//============================================================================ - -void A_CorpseBloodDrip(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_Random() > 128) - { - return; - } - P_SpawnMobj(actor->x, actor->y, actor->z + actor->height / 2, - MT_CORPSEBLOODDRIP); -} - -//============================================================================ -// -// A_CorpseExplode -// -//============================================================================ - -void A_CorpseExplode(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int i; - - for (i = (P_Random() & 3) + 3; i; i--) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT); - P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3)); - mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4); - mo->momx = P_SubRandom() << (FRACBITS - 6); - mo->momy = P_SubRandom() << (FRACBITS - 6); - } - // Spawn a skull - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_CORPSEBIT); - P_SetMobjState(mo, S_CORPSEBIT_4); - if (mo) - { - mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4); - mo->momx = P_SubRandom() << (FRACBITS - 6); - mo->momy = P_SubRandom() << (FRACBITS - 6); - S_StartSound(mo, SFX_FIRED_DEATH); - } - P_RemoveMobj(actor); -} - -//============================================================================ -// -// A_LeafSpawn -// -//============================================================================ - -void A_LeafSpawn(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int i; - - for (i = (P_Random() & 3) + 1; i; i--) - { - // Official release of Hexen's source code relies on unspecified behavior - // the in order of function's argument evaluation, - // see ISO-IEC 9899-1999, [6.5.2.2.10] - mobjtype_t type = MT_LEAF1 + (P_Random() & 1); - fixed_t z = actor->z + (P_Random() << 14); - fixed_t y = actor->y + (P_SubRandom() << 14); - fixed_t x = actor->x + (P_SubRandom() << 14); - - mo = P_SpawnMobj(x, y, z, type); - if (mo) - { - P_ThrustMobj(mo, actor->angle, (P_Random() << 9) + 3 * FRACUNIT); - mo->target = actor; - mo->special1.i = 0; - } - } -} - -//============================================================================ -// -// A_LeafThrust -// -//============================================================================ - -void A_LeafThrust(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_Random() > 96) - { - return; - } - actor->momz += (P_Random() << 9) + FRACUNIT; -} - -//============================================================================ -// -// A_LeafCheck -// -//============================================================================ - -void A_LeafCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->special1.i++; - if (actor->special1.i >= 20) - { - P_SetMobjState(actor, S_NULL); - return; - } - if (P_Random() > 64) - { - if (!actor->momx && !actor->momy) - { - P_ThrustMobj(actor, actor->target->angle, - (P_Random() << 9) + FRACUNIT); - } - return; - } - P_SetMobjState(actor, S_LEAF1_8); - actor->momz = (P_Random() << 9) + FRACUNIT; - P_ThrustMobj(actor, actor->target->angle, - (P_Random() << 9) + 2 * FRACUNIT); - actor->flags |= MF_MISSILE; -} - -/* -#define ORBIT_RADIUS (15*FRACUNIT) -void GenerateOrbitTable(void) -{ - int angle; - - for (angle=0; angle<256; angle++) - { - orbitTableX[angle] = FixedMul(ORBIT_RADIUS, finecosine[angle<<5]); - orbitTableY[angle] = FixedMul(ORBIT_RADIUS, finesine[angle<<5]); - } - - printf("int orbitTableX[256]=\n{\n"); - for (angle=0; angle<256; angle+=8) - { - printf("%d, %d, %d, %d, %d, %d, %d, %d,\n", - orbitTableX[angle], - orbitTableX[angle+1], - orbitTableX[angle+2], - orbitTableX[angle+3], - orbitTableX[angle+4], - orbitTableX[angle+5], - orbitTableX[angle+6], - orbitTableX[angle+7]); - } - printf("};\n\n"); - - printf("int orbitTableY[256]=\n{\n"); - for (angle=0; angle<256; angle+=8) - { - printf("%d, %d, %d, %d, %d, %d, %d, %d,\n", - orbitTableY[angle], - orbitTableY[angle+1], - orbitTableY[angle+2], - orbitTableY[angle+3], - orbitTableY[angle+4], - orbitTableY[angle+5], - orbitTableY[angle+6], - orbitTableY[angle+7]); - } - printf("};\n"); -} -*/ - -// New bridge stuff -// Parent -// special1 true == removing from world -// -// Child -// target pointer to center mobj -// args[0] angle of ball - -void A_BridgeOrbit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->target->special1.i) - { - P_SetMobjState(actor, S_NULL); - } - actor->args[0] += 3; - actor->x = actor->target->x + orbitTableX[actor->args[0]]; - actor->y = actor->target->y + orbitTableY[actor->args[0]]; - actor->z = actor->target->z; -} - - -void A_BridgeInit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - byte startangle; - mobj_t *ball1, *ball2, *ball3; - fixed_t cx, cy, cz; - -// GenerateOrbitTable(); - - cx = actor->x; - cy = actor->y; - cz = actor->z; - startangle = P_Random(); - actor->special1.i = 0; - - // Spawn triad into world - ball1 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL); - ball1->args[0] = startangle; - ball1->target = actor; - - ball2 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL); - ball2->args[0] = (startangle + 85) & 255; - ball2->target = actor; - - ball3 = P_SpawnMobj(cx, cy, cz, MT_BRIDGEBALL); - ball3->args[0] = (startangle + 170) & 255; - ball3->target = actor; - - A_BridgeOrbit(ball1, NULL, NULL); - A_BridgeOrbit(ball2, NULL, NULL); - A_BridgeOrbit(ball3, NULL, NULL); -} - -void A_BridgeRemove(mobj_t * actor) -{ - actor->special1.i = true; // Removing the bridge - actor->flags &= ~MF_SOLID; - P_SetMobjState(actor, S_FREE_BRIDGE1); -} - - -//========================================================================== -// -// A_GhostOn -// -//========================================================================== - -/* -void A_GhostOn(mobj_t *actor) -{ - actor->flags |= MF_SHADOW; -} -*/ - -//========================================================================== -// -// A_GhostOff -// -//========================================================================== - -/* -void A_GhostOff(mobj_t *actor) -{ - actor->flags &= ~MF_SHADOW; -} -*/ - -//========================================================================== -// -// A_HideThing -// -//========================================================================== - -void A_HideThing(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 |= MF2_DONTDRAW; -} - -//========================================================================== -// -// A_UnHideThing -// -//========================================================================== - -void A_UnHideThing(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 &= ~MF2_DONTDRAW; -} - -//========================================================================== -// -// A_SetShootable -// -//========================================================================== - -void A_SetShootable(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 &= ~MF2_NONSHOOTABLE; - actor->flags |= MF_SHOOTABLE; -} - -//========================================================================== -// -// A_UnSetShootable -// -//========================================================================== - -void A_UnSetShootable(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 |= MF2_NONSHOOTABLE; - actor->flags &= ~MF_SHOOTABLE; -} - -//========================================================================== -// -// A_SetAltShadow -// -//========================================================================== - -void A_SetAltShadow(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SHADOW; - actor->flags |= MF_ALTSHADOW; -} - -//========================================================================== -// -// A_UnSetAltShadow -// -//========================================================================== - -/* -void A_UnSetAltShadow(mobj_t *actor) -{ - actor->flags &= ~MF_ALTSHADOW; -} -*/ - -//-------------------------------------------------------------------------- -// -// Sound Action Routines -// -//-------------------------------------------------------------------------- - -//========================================================================== -// -// A_ContMobjSound -// -//========================================================================== - -void A_ContMobjSound(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - switch (actor->type) - { - case MT_SERPENTFX: - S_StartSound(actor, SFX_SERPENTFX_CONTINUOUS); - break; - case MT_HAMMER_MISSILE: - S_StartSound(actor, SFX_FIGHTER_HAMMER_CONTINUOUS); - break; - case MT_QUAKE_FOCUS: - S_StartSound(actor, SFX_EARTHQUAKE); - break; - default: - break; - } -} - -//========================================================================== -// -// PROC A_ESound -// -//========================================================================== - -void A_ESound(mobj_t *mo, player_t *player, pspdef_t *psp) -{ - int sound; - - switch (mo->type) - { - case MT_SOUNDWIND: - sound = SFX_WIND; - break; - default: - sound = SFX_NONE; - break; - } - S_StartSound(mo, sound); -} - - - -//========================================================================== -// Summon Minotaur -- see p_enemy for variable descriptions -//========================================================================== - - -void A_Summon(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - mobj_t *master; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINOTAUR); - if (mo) - { - if (P_TestMobjLocation(mo) == false || !actor->special1.m) - { // Didn't fit - change back to artifact - P_SetMobjState(mo, S_NULL); - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SUMMONMAULATOR); - if (mo) - mo->flags2 |= MF2_DROPPED; - return; - } - - // Store leveltime into mo->args. This must be stored in little- - // endian format for Vanilla savegame compatibility. - mo->args[0] = leveltime & 0xff; - mo->args[1] = (leveltime >> 8) & 0xff; - mo->args[2] = (leveltime >> 16) & 0xff; - mo->args[3] = (leveltime >> 24) & 0xff; - master = actor->special1.m; - if (master->flags & MF_CORPSE) - { // Master dead - mo->special1.m = NULL; // No master - } - else - { - mo->special1.m = actor->special1.m; // Pointer to master (mobj_t *) - P_GivePower(master->player, pw_minotaur); - } - - // Make smoke puff - P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE); - S_StartSound(actor, SFX_MAULATOR_ACTIVE); - } -} - - - -//========================================================================== -// Fog Variables: -// -// args[0] Speed (0..10) of fog -// args[1] Angle of spread (0..128) -// args[2] Frequency of spawn (1..10) -// args[3] Lifetime countdown -// args[4] Boolean: fog moving? -// special1 Internal: Counter for spawn frequency -// special2 Internal: Index into floatbob table -// -//========================================================================== - -void A_FogSpawn(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo = NULL; - angle_t delta; - - if (actor->special1.i-- > 0) - return; - - actor->special1.i = actor->args[2]; // Reset frequency count - - switch (P_Random() % 3) - { - case 0: - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHS); - break; - case 1: - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHM); - break; - case 2: - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FOGPATCHL); - break; - } - - if (mo) - { - delta = actor->args[1]; - if (delta == 0) - delta = 1; - mo->angle = - actor->angle + (((P_Random() % delta) - (delta >> 1)) << 24); - mo->target = actor; - if (actor->args[0] < 1) - actor->args[0] = 1; - mo->args[0] = (P_Random() % (actor->args[0])) + 1; // Random speed - mo->args[3] = actor->args[3]; // Set lifetime - mo->args[4] = 1; // Set to moving - mo->special2.i = P_Random() & 63; - } -} - - -void A_FogMove(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int speed = actor->args[0] << FRACBITS; - angle_t angle; - int weaveindex; - - if (!(actor->args[4])) - return; - - if (actor->args[3]-- <= 0) - { - P_SetMobjStateNF(actor, actor->info->deathstate); - return; - } - - if ((actor->args[3] % 4) == 0) - { - weaveindex = actor->special2.i; - actor->z += FloatBobOffsets[weaveindex] >> 1; - actor->special2.i = (weaveindex + 1) & 63; - } - - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(speed, finecosine[angle]); - actor->momy = FixedMul(speed, finesine[angle]); -} - -//=========================================================================== -// -// A_PoisonBagInit -// -//=========================================================================== - -void A_PoisonBagInit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 28 * FRACUNIT, - MT_POISONCLOUD); - if (!mo) - { - return; - } - mo->momx = 1; // missile objects must move to impact other objects - mo->special1.i = 24 + (P_Random() & 7); - mo->special2.i = 0; - mo->target = actor->target; - mo->radius = 20 * FRACUNIT; - mo->height = 30 * FRACUNIT; - mo->flags &= ~MF_NOCLIP; -} - -//=========================================================================== -// -// A_PoisonBagCheck -// -//=========================================================================== - -void A_PoisonBagCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!--actor->special1.i) - { - P_SetMobjState(actor, S_POISONCLOUD_X1); - } - else - { - return; - } -} - -//=========================================================================== -// -// A_PoisonBagDamage -// -//=========================================================================== - -void A_PoisonBagDamage(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int bobIndex; - - A_Explode(actor, player, psp); - - bobIndex = actor->special2.i; - actor->z += FloatBobOffsets[bobIndex] >> 4; - actor->special2.i = (bobIndex + 1) & 63; -} - -//=========================================================================== -// -// A_PoisonShroom -// -//=========================================================================== - -void A_PoisonShroom(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->tics = 128 + (P_Random() << 1); -} - -//=========================================================================== -// -// A_CheckThrowBomb -// -//=========================================================================== - -void A_CheckThrowBomb(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (abs(actor->momx) < 1.5 * FRACUNIT && abs(actor->momy) < 1.5 * FRACUNIT - && actor->momz < 2 * FRACUNIT - && actor->state == &states[S_THROWINGBOMB6]) - { - P_SetMobjState(actor, S_THROWINGBOMB7); - actor->z = actor->floorz; - actor->momz = 0; - actor->flags2 &= ~MF2_FLOORBOUNCE; - actor->flags &= ~MF_MISSILE; - } - if (!--actor->health) - { - P_SetMobjState(actor, actor->info->deathstate); - } -} - -//=========================================================================== -// Quake variables -// -// args[0] Intensity on richter scale (2..9) -// args[1] Duration in tics -// args[2] Radius for damage -// args[3] Radius for tremor -// args[4] TID of map thing for focus of quake -// -//=========================================================================== - -//=========================================================================== -// -// A_LocalQuake -// -//=========================================================================== - -boolean A_LocalQuake(byte * args, mobj_t * actor) -{ - mobj_t *focus, *target; - int lastfound = 0; - int success = false; - - // Find all quake foci - do - { - target = P_FindMobjFromTID(args[4], &lastfound); - if (target) - { - focus = P_SpawnMobj(target->x, - target->y, target->z, MT_QUAKE_FOCUS); - if (focus) - { - focus->args[0] = args[0]; - focus->args[1] = args[1] >> 1; // decremented every 2 tics - focus->args[2] = args[2]; - focus->args[3] = args[3]; - focus->args[4] = args[4]; - success = true; - } - } - } - while (target != NULL); - - return (success); -} - - -//=========================================================================== -// -// A_Quake -// -//=========================================================================== -int localQuakeHappening[MAXPLAYERS]; - -void A_Quake(mobj_t *actor, player_t *player_param, pspdef_t *psp) -{ - angle_t an; - player_t *player; - mobj_t *victim; - int richters = actor->args[0]; - int playnum; - fixed_t dist; - - if (actor->args[1]-- > 0) - { - for (playnum = 0; playnum < maxplayers; playnum++) - { - player = &players[playnum]; - if (!playeringame[playnum]) - continue; - - victim = player->mo; - dist = P_AproxDistance(actor->x - victim->x, - actor->y - victim->y) >> (FRACBITS + 6); - // Tested in tile units (64 pixels) - if (dist < actor->args[3]) // In tremor radius - { - localQuakeHappening[playnum] = richters; - } - // Check if in damage radius - if ((dist < actor->args[2]) && (victim->z <= victim->floorz)) - { - if (P_Random() < 50) - { - P_DamageMobj(victim, NULL, NULL, HITDICE(1)); - } - // Thrust player around - an = victim->angle + ANG1 * P_Random(); - P_ThrustMobj(victim, an, richters << (FRACBITS - 1)); - } - } - } - else - { - for (playnum = 0; playnum < maxplayers; playnum++) - { - localQuakeHappening[playnum] = false; - } - P_SetMobjState(actor, S_NULL); - } -} - - - - -//=========================================================================== -// -// Teleport other stuff -// -//=========================================================================== - -#define TELEPORT_LIFE 1 - -void A_TeloSpawnA(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX2); - if (mo) - { - mo->special1.i = TELEPORT_LIFE; // Lifetime countdown - mo->angle = actor->angle; - mo->target = actor->target; - mo->momx = actor->momx >> 1; - mo->momy = actor->momy >> 1; - mo->momz = actor->momz >> 1; - } -} - -void A_TeloSpawnB(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX3); - if (mo) - { - mo->special1.i = TELEPORT_LIFE; // Lifetime countdown - mo->angle = actor->angle; - mo->target = actor->target; - mo->momx = actor->momx >> 1; - mo->momy = actor->momy >> 1; - mo->momz = actor->momz >> 1; - } -} - -void A_TeloSpawnC(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX4); - if (mo) - { - mo->special1.i = TELEPORT_LIFE; // Lifetime countdown - mo->angle = actor->angle; - mo->target = actor->target; - mo->momx = actor->momx >> 1; - mo->momy = actor->momy >> 1; - mo->momz = actor->momz >> 1; - } -} - -void A_TeloSpawnD(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_TELOTHER_FX5); - if (mo) - { - mo->special1.i = TELEPORT_LIFE; // Lifetime countdown - mo->angle = actor->angle; - mo->target = actor->target; - mo->momx = actor->momx >> 1; - mo->momy = actor->momy >> 1; - mo->momz = actor->momz >> 1; - } -} - -void A_CheckTeleRing(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special1.i-- <= 0) - { - P_SetMobjState(actor, actor->info->deathstate); - } -} - - - - -// Dirt stuff - -void P_SpawnDirt(mobj_t * actor, fixed_t radius) -{ - fixed_t x, y, z; - int dtype = 0; - mobj_t *mo; - angle_t angle; - - angle = P_Random() << 5; // <<24 >>19 - x = actor->x + FixedMul(radius, finecosine[angle]); - y = actor->y + FixedMul(radius, finesine[angle]); -// x = actor->x + (P_SubRandom()%radius)<y + ((P_SubRandom()<z + (P_Random() << 9) + FRACUNIT; - switch (P_Random() % 6) - { - case 0: - dtype = MT_DIRT1; - break; - case 1: - dtype = MT_DIRT2; - break; - case 2: - dtype = MT_DIRT3; - break; - case 3: - dtype = MT_DIRT4; - break; - case 4: - dtype = MT_DIRT5; - break; - case 5: - dtype = MT_DIRT6; - break; - } - mo = P_SpawnMobj(x, y, z, dtype); - if (mo) - { - mo->momz = P_Random() << 10; - } -} - - - - -//=========================================================================== -// -// Thrust floor stuff -// -// Thrust Spike Variables -// special1 pointer to dirt clump mobj -// special2 speed of raise -// args[0] 0 = lowered, 1 = raised -// args[1] 0 = normal, 1 = bloody -//=========================================================================== - -void A_ThrustInitUp(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->special2.i = 5; // Raise speed - actor->args[0] = 1; // Mark as up - actor->floorclip = 0; - actor->flags = MF_SOLID; - actor->flags2 = MF2_NOTELEPORT | MF2_FLOORCLIP; - actor->special1.m = NULL; -} - -void A_ThrustInitDn(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - actor->special2.i = 5; // Raise speed - actor->args[0] = 0; // Mark as down - actor->floorclip = actor->info->height; - actor->flags = 0; - actor->flags2 = MF2_NOTELEPORT | MF2_FLOORCLIP | MF2_DONTDRAW; - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_DIRTCLUMP); - actor->special1.m = mo; -} - - -void A_ThrustRaise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (A_RaiseMobj(actor)) - { // Reached it's target height - actor->args[0] = 1; - if (actor->args[1]) - P_SetMobjStateNF(actor, S_BTHRUSTINIT2_1); - else - P_SetMobjStateNF(actor, S_THRUSTINIT2_1); - } - - // Lose the dirt clump - if ((actor->floorclip < actor->height) && actor->special1.m) - { - P_RemoveMobj(actor->special1.m); - actor->special1.m = NULL; - } - - // Spawn some dirt - if (P_Random() < 40) - P_SpawnDirt(actor, actor->radius); - actor->special2.i++; // Increase raise speed -} - -void A_ThrustLower(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (A_SinkMobj(actor)) - { - actor->args[0] = 0; - if (actor->args[1]) - P_SetMobjStateNF(actor, S_BTHRUSTINIT1_1); - else - P_SetMobjStateNF(actor, S_THRUSTINIT1_1); - } -} - -void A_ThrustBlock(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags |= MF_SOLID; -} - -void A_ThrustImpale(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - // Impale all shootables in radius - PIT_ThrustSpike(actor); -} - -//=========================================================================== -// -// A_SoAExplode - Suit of Armor Explode -// -//=========================================================================== - -void A_SoAExplode(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int i; - int r1,r2,r3; - - for (i = 0; i < 10; i++) - { - r1 = P_Random(); - r2 = P_Random(); - r3 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r3 - 128) << 12), - actor->y + ((r2 - 128) << 12), - actor->z + (r1 * actor->height / 256), - MT_ZARMORCHUNK); - P_SetMobjState(mo, mo->info->spawnstate + i); - mo->momz = ((P_Random() & 7) + 5) * FRACUNIT; - mo->momx = P_SubRandom() << (FRACBITS - 6); - mo->momy = P_SubRandom() << (FRACBITS - 6); - } - if (actor->args[0]) - { // Spawn an item - if ((gameversion != exe_hexen_1_1r2) || !nomonsters - || !(mobjinfo[TranslateThingType[actor->args[0]]]. - flags & MF_COUNTKILL)) - { // Only spawn monsters if not -nomonsters - P_SpawnMobj(actor->x, actor->y, actor->z, - TranslateThingType[actor->args[0]]); - } - } - S_StartSound(mo, SFX_SUITOFARMOR_BREAK); - P_RemoveMobj(actor); -} - -//=========================================================================== -// -// A_BellReset1 -// -//=========================================================================== - -void A_BellReset1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags |= MF_NOGRAVITY; - actor->height <<= 2; -} - -//=========================================================================== -// -// A_BellReset2 -// -//=========================================================================== - -void A_BellReset2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags |= MF_SHOOTABLE; - actor->flags &= ~MF_CORPSE; - actor->health = 5; -} - - -//=========================================================================== -// -// A_FlameCheck -// -//=========================================================================== - -void A_FlameCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->args[0]--) // Called every 8 tics - { - P_SetMobjState(actor, S_NULL); - } -} - - -//=========================================================================== -// Bat Spawner Variables -// special1 frequency counter -// special2 -// args[0] frequency of spawn (1=fastest, 10=slowest) -// args[1] spread angle (0..255) -// args[2] -// args[3] duration of bats (in octics) -// args[4] turn amount per move (in degrees) -// -// Bat Variables -// special2 lifetime counter -// args[4] turn amount per move (in degrees) -//=========================================================================== - -void A_BatSpawnInit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->special1.i = 0; // Frequency count -} - -void A_BatSpawn(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int delta; - angle_t angle; - - // Countdown until next spawn - if (actor->special1.i-- > 0) - return; - actor->special1.i = actor->args[0]; // Reset frequency count - - delta = actor->args[1]; - if (delta == 0) - delta = 1; - angle = actor->angle + (((P_Random() % delta) - (delta >> 1)) << 24); - mo = P_SpawnMissileAngle(actor, MT_BAT, angle, 0); - if (mo) - { - mo->args[0] = P_Random() & 63; // floatbob index - mo->args[4] = actor->args[4]; // turn degrees - mo->special2.i = actor->args[3] << 3; // Set lifetime - mo->target = actor; - } -} - - -void A_BatMove(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t newangle; - fixed_t speed; - - if (actor->special2.i < 0) - { - P_SetMobjState(actor, actor->info->deathstate); - } - actor->special2.i -= 2; // Called every 2 tics - - if (P_Random() < 128) - { - newangle = actor->angle + ANG1 * actor->args[4]; - } - else - { - newangle = actor->angle - ANG1 * actor->args[4]; - } - - // Adjust momentum vector to new direction - newangle >>= ANGLETOFINESHIFT; - speed = FixedMul(actor->info->speed, P_Random() << 10); - actor->momx = FixedMul(speed, finecosine[newangle]); - actor->momy = FixedMul(speed, finesine[newangle]); - - if (P_Random() < 15) - S_StartSound(actor, SFX_BAT_SCREAM); - - // Handle Z movement - actor->z = actor->target->z + 2 * FloatBobOffsets[actor->args[0]]; - actor->args[0] = (actor->args[0] + 3) & 63; -} - -//=========================================================================== -// -// A_TreeDeath -// -//=========================================================================== - -void A_TreeDeath(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!(actor->flags2 & MF2_FIREDAMAGE)) - { - actor->height <<= 2; - actor->flags |= MF_SHOOTABLE; - actor->flags &= ~(MF_CORPSE + MF_DROPOFF); - actor->health = 35; - return; - } - else - { - P_SetMobjState(actor, actor->info->meleestate); - } -} - -//=========================================================================== -// -// A_NoGravity -// -//=========================================================================== - -void A_NoGravity(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags |= MF_NOGRAVITY; -} diff --git a/games/NXDoom/src/hexen/am_data.h b/games/NXDoom/src/hexen/am_data.h deleted file mode 100644 index 26589a25cf1..00000000000 --- a/games/NXDoom/src/hexen/am_data.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef __AMDATA_H__ -#define __AMDATA_H__ - -// a line drawing of the player pointing right, starting from the middle. - -#define R ((8*PLAYERRADIUS)/7) - -mline_t player_arrow[] = { - { { -R+R/4, 0 }, { 0, 0} }, // center line. - { { -R+R/4, R/8 }, { R, 0} }, // blade - { { -R+R/4, -R/8 }, { R, 0 } }, - { { -R+R/4, -R/4 }, { -R+R/4, R/4 } }, // crosspiece - { { -R+R/8, -R/4 }, { -R+R/8, R/4 } }, - { { -R+R/8, -R/4 }, { -R+R/4, -R/4} }, //crosspiece connectors - { { -R+R/8, R/4 }, { -R+R/4, R/4} }, - { { -R-R/4, R/8 }, { -R-R/4, -R/8 } }, //pommel - { { -R-R/4, R/8 }, { -R+R/8, R/8 } }, - { { -R-R/4, -R/8}, { -R+R/8, -R/8 } } - }; - -/* -mline_t keysquare[] = { - { { 0, 0 }, { R/4, -R/2 } }, - { { R/4, -R/2 }, { R/2, -R/2 } }, - { { R/2, -R/2 }, { R/2, R/2 } }, - { { R/2, R/2 }, { R/4, R/2 } }, - { { R/4, R/2 }, { 0, 0 } }, // handle part type thing - { { 0, 0 }, { -R, 0 } }, // stem - { { -R, 0 }, { -R, -R/2 } }, // end lockpick part - { { -3*R/4, 0 }, { -3*R/4, -R/4 } } - }; -*/ - -/*mline_t player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/4 } }, // -----> - { { R, 0 }, { R-R/2, -R/4 } }, - { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> - { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> - { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } - }; -*/ -#undef R -#define NUMPLYRLINES (sizeof(player_arrow)/sizeof(mline_t)) -#define NUMKEYSQUARELINES (sizeof(keysquare)/sizeof(mline_t)) - -/* -#define R ((8*PLAYERRADIUS)/7) -mline_t cheat_player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/6 } }, // -----> - { { R, 0 }, { R-R/2, -R/6 } }, - { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> - { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> - { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, - { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> - { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, - { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, - { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> - { { -R/6, -R/6 }, { 0, -R/6 } }, - { { 0, -R/6 }, { 0, R/4 } }, - { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> - { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, - { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } - }; -#undef R -#define NUMCHEATPLYRLINES (sizeof(cheat_player_arrow)/sizeof(mline_t)) -*/ - - -/* -#define R (FRACUNIT) -mline_t triangle_guy[] = { - { { -.867*R, -.5*R }, { .867*R, -.5*R } }, - { { .867*R, -.5*R } , { 0, R } }, - { { 0, R }, { -.867*R, -.5*R } } - }; -#undef R -#define NUMTRIANGLEGUYLINES (sizeof(triangle_guy)/sizeof(mline_t)) -*/ - -#define R (FRACUNIT) -mline_t thintriangle_guy[] = { - { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, - { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, - { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } - }; -#undef R -#define NUMTHINTRIANGLEGUYLINES (sizeof(thintriangle_guy)/sizeof(mline_t)) - -#endif diff --git a/games/NXDoom/src/hexen/am_map.c b/games/NXDoom/src/hexen/am_map.c deleted file mode 100644 index 34985dc5d9f..00000000000 --- a/games/NXDoom/src/hexen/am_map.c +++ /dev/null @@ -1,1544 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include - -#include "h2def.h" -#include "doomkeys.h" -#include "i_video.h" -#include "i_swap.h" -#include "i_timer.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "am_map.h" -#include "am_data.h" -#include "v_video.h" - -#define NUMALIAS 3 // Number of antialiased lines. - -int cheating = 0; -static int grid = 0; - -boolean automapactive = false; -static int finit_width = SCREENWIDTH; -static int finit_height = SCREENHEIGHT - SBARHEIGHT - 3; -static int f_x, f_y; // location of window on screen -static int f_w, f_h; // size of window on screen -static int lightlev; // used for funky strobing effect -static byte *fb; // pseudo-frame buffer -static int amclock; - -static mpoint_t m_paninc; // how far the window pans each tic (map coords) -static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) -static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) - -static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) -static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) - -// width/height of window on map (map coords) -static fixed_t m_w, m_h; -static fixed_t min_x, min_y; // based on level size -static fixed_t max_x, max_y; // based on level size -static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y -static fixed_t min_w, min_h; // based on player size -static fixed_t min_scale_mtof; // used to tell when to stop zooming out -static fixed_t max_scale_mtof; // used to tell when to stop zooming in - -// old stuff for recovery later -static fixed_t old_m_w, old_m_h; -static fixed_t old_m_x, old_m_y; - -// old location used by the Follower routine -static mpoint_t f_oldloc; - -// used by MTOF to scale from map-to-frame-buffer coords -static fixed_t scale_mtof = INITSCALEMTOF; -// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) -static fixed_t scale_ftom; - -static player_t *plr; // the player represented by an arrow -static vertex_t oldplr; - -//static patch_t *marknums[10]; // numbers used for marking by the automap -//static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are -//static int markpointnum = 0; // next point to be assigned - -static int followplayer = 1; // specifies whether to follow the player around - -static char cheat_kills[] = { 'k', 'i', 'l', 'l', 's' }; -static boolean ShowKills = 0; -static unsigned ShowKillsCount = 0; - -static byte antialias[NUMALIAS][8] = { - {83, 84, 85, 86, 87, 88, 89, 90}, - {96, 96, 95, 94, 93, 92, 91, 90}, - {107, 108, 109, 110, 111, 112, 89, 90} -}; - -/* -static byte *aliasmax[NUMALIAS] = { - &antialias[0][7], &antialias[1][7], &antialias[2][7] -};*/ - -static byte *maplump; // pointer to the raw data for the automap background. -static short mapystart = 0; // y-value for the start of the map bitmap...used in - //the parallax stuff. -static short mapxstart = 0; //x-value for the bitmap. - -//byte screens[][SCREENWIDTH*SCREENHEIGHT]; -//void V_MarkRect (int x, int y, int width, int height); - -// Functions - -void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, - int NumLevels, unsigned short IntensityBits); - -void AM_DrawDeathmatchStats(void); -static void DrawWorldTimer(void); - -// Calculates the slope and slope according to the x-axis of a line -// segment in map coordinates (with the upright y-axis n' all) so -// that it can be used with the brain-dead drawing stuff. - -// Ripped out for Heretic -/* -void AM_getIslope(mline_t *ml, islope_t *is) -{ - int dx, dy; - - dy = ml->a.y - ml->b.y; - dx = ml->b.x - ml->a.x; - if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); - else is->islp = FixedDiv(dx, dy); - if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); - else is->slp = FixedDiv(dy, dx); -} -*/ - -void AM_activateNewScale(void) -{ - m_x += m_w / 2; - m_y += m_h / 2; - m_w = FTOM(f_w); - m_h = FTOM(f_h); - m_x -= m_w / 2; - m_y -= m_h / 2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; -} - -void AM_saveScaleAndLoc(void) -{ - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; -} - -void AM_restoreScaleAndLoc(void) -{ - - m_w = old_m_w; - m_h = old_m_h; - if (!followplayer) - { - m_x = old_m_x; - m_y = old_m_y; - } - else - { - m_x = plr->mo->x - m_w / 2; - m_y = plr->mo->y - m_h / 2; - } - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - - // Change the scaling multipliers - scale_mtof = FixedDiv(f_w << FRACBITS, m_w); - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); -} - -// adds a marker at the current location - -/* -void AM_addMark(void) -{ - markpoints[markpointnum].x = m_x + m_w/2; - markpoints[markpointnum].y = m_y + m_h/2; - markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; - -} -*/ -void AM_findMinMaxBoundaries(void) -{ - int i; - fixed_t a, b; - - min_x = min_y = INT_MAX; - max_x = max_y = -INT_MAX; - for (i = 0; i < numvertexes; i++) - { - if (vertexes[i].x < min_x) - min_x = vertexes[i].x; - else if (vertexes[i].x > max_x) - max_x = vertexes[i].x; - if (vertexes[i].y < min_y) - min_y = vertexes[i].y; - else if (vertexes[i].y > max_y) - max_y = vertexes[i].y; - } - max_w = max_x - min_x; - max_h = max_y - min_y; - min_w = 2 * PLAYERRADIUS; - min_h = 2 * PLAYERRADIUS; - - a = FixedDiv(f_w << FRACBITS, max_w); - b = FixedDiv(f_h << FRACBITS, max_h); - min_scale_mtof = a < b ? a : b; - - max_scale_mtof = FixedDiv(f_h << FRACBITS, 2 * PLAYERRADIUS); - -} - -void AM_changeWindowLoc(void) -{ - if (m_paninc.x || m_paninc.y) - { - followplayer = 0; - f_oldloc.x = INT_MAX; - } - - m_x += m_paninc.x; - m_y += m_paninc.y; - - if (m_x + m_w / 2 > max_x) - { - m_x = max_x - m_w / 2; - m_paninc.x = 0; - } - else if (m_x + m_w / 2 < min_x) - { - m_x = min_x - m_w / 2; - m_paninc.x = 0; - } - if (m_y + m_h / 2 > max_y) - { - m_y = max_y - m_h / 2; - m_paninc.y = 0; - } - else if (m_y + m_h / 2 < min_y) - { - m_y = min_y - m_h / 2; - m_paninc.y = 0; - } - - // The following code was commented out in the released Hexen source, - // but I believe we need to do this here to stop the background moving - // when we reach the map boundaries. (In the released source it's done - // in AM_clearFB). - mapxstart += MTOF(m_paninc.x+FRACUNIT/2); - mapystart -= MTOF(m_paninc.y+FRACUNIT/2); - if(mapxstart >= finit_width) - mapxstart -= finit_width; - if(mapxstart < 0) - mapxstart += finit_width; - if(mapystart >= finit_height) - mapystart -= finit_height; - if(mapystart < 0) - mapystart += finit_height; - // - end of code that was commented-out - - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; -} - -void AM_initVariables(void) -{ - int pnum; - thinker_t *think; - - //static event_t st_notify = { ev_keyup, AM_MSGENTERED }; - - automapactive = true; - fb = I_VideoBuffer; - - f_oldloc.x = INT_MAX; - amclock = 0; - lightlev = 0; - - m_paninc.x = m_paninc.y = 0; - ftom_zoommul = FRACUNIT; - mtof_zoommul = FRACUNIT; - - m_w = FTOM(f_w); - m_h = FTOM(f_h); - - // find player to center on initially - if (!playeringame[pnum = consoleplayer]) - for (pnum = 0; pnum < maxplayers; pnum++) - if (playeringame[pnum]) - break; - plr = &players[pnum]; - oldplr.x = plr->mo->x; - oldplr.y = plr->mo->y; - m_x = plr->mo->x - m_w / 2; - m_y = plr->mo->y - m_h / 2; - AM_changeWindowLoc(); - - // for saving & restoring - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; - - // load in the location of keys, if in baby mode - -// memset(KeyPoints, 0, sizeof(vertex_t)*3); - if (gameskill == sk_baby) - { - for (think = thinkercap.next; think != &thinkercap; - think = think->next) - { - if (think->function != P_MobjThinker) - { //not a mobj - continue; - } - } - } - - // inform the status bar of the change -//c ST_Responder(&st_notify); -} - -void AM_loadPics(void) -{ - maplump = W_CacheLumpName("AUTOPAGE", PU_STATIC); -} - - -/* -void AM_clearMarks(void) -{ - int i; - for (i=0;i max_scale_mtof) - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); -} - -static boolean stopped = true; - -void AM_Stop(void) -{ - //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED }; - -// AM_unloadPics(); - automapactive = false; -// ST_Responder(&st_notify); - stopped = true; - BorderNeedRefresh = true; -} - -void AM_Start(void) -{ - static int lastlevel = -1, lastepisode = -1; - - if (!stopped) - AM_Stop(); - stopped = false; - if (gamestate != GS_LEVEL) - { - return; // don't show automap if we aren't in a game! - } - if (lastlevel != gamemap || lastepisode != gameepisode) - { - AM_LevelInit(); - lastlevel = gamemap; - lastepisode = gameepisode; - } - AM_initVariables(); - AM_loadPics(); -} - -// set the window scale to the maximum size - -void AM_minOutWindowScale(void) -{ - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); -} - -// set the window scale to the minimum size - -void AM_maxOutWindowScale(void) -{ - scale_mtof = max_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); -} - -boolean AM_Responder(event_t * ev) -{ - int rc; - int key; - static int bigstate = 0; - static int joywait = 0; - - key = ev->data1; - - if (ev->type == ev_joystick && joybautomap >= 0 - && (ev->data1 & (1 << joybautomap)) != 0 && joywait < I_GetTime()) - { - joywait = I_GetTime() + 5; - - if (!automapactive) - { - AM_Start (); - SB_state = -1; - viewactive = false; - } - else - { - bigstate = 0; - viewactive = true; - AM_Stop (); - SB_state = -1; - } - - return true; - } - - - rc = false; - if (!automapactive) - { - if (ev->type == ev_keydown && key == key_map_toggle - && gamestate == GS_LEVEL) - { - AM_Start(); - SB_state = -1; - viewactive = false; - rc = true; - } - } - else if (ev->type == ev_keydown) - { - rc = true; - - if (key == key_map_east) // pan right - { - if (!followplayer) - m_paninc.x = FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_west) // pan left - { - if (!followplayer) - m_paninc.x = -FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_north) // pan up - { - if (!followplayer) - m_paninc.y = FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_south) // pan down - { - if (!followplayer) - m_paninc.y = -FTOM(F_PANINC); - else - rc = false; - } - else if (key == key_map_zoomout) // zoom out - { - mtof_zoommul = M_ZOOMOUT; - ftom_zoommul = M_ZOOMIN; - } - else if (key == key_map_zoomin) // zoom in - { - mtof_zoommul = M_ZOOMIN; - ftom_zoommul = M_ZOOMOUT; - } - else if (key == key_map_toggle) - { - bigstate = 0; - viewactive = true; - AM_Stop(); - SB_state = -1; - } - else if (key == key_map_maxzoom) - { - bigstate = !bigstate; - if (bigstate) - { - AM_saveScaleAndLoc(); - AM_minOutWindowScale(); - } - else - AM_restoreScaleAndLoc(); - } - else if (key == key_map_follow) - { - followplayer = !followplayer; - f_oldloc.x = INT_MAX; - P_SetMessage(plr, - followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, - true); - } - else - { - rc = false; - } - - if (cheat_kills[ShowKillsCount] == ev->data1 && netgame && deathmatch) - { - ShowKillsCount++; - if (ShowKillsCount == 5) - { - ShowKillsCount = 0; - rc = false; - ShowKills ^= 1; - } - } - else - { - ShowKillsCount = 0; - } - } - else if (ev->type == ev_keyup) - { - rc = false; - - if (key == key_map_east) - { - if (!followplayer) - m_paninc.x = 0; - } - else if (key == key_map_west) - { - if (!followplayer) - m_paninc.x = 0; - } - else if (key == key_map_north) - { - if (!followplayer) - m_paninc.y = 0; - } - else if (key == key_map_south) - { - if (!followplayer) - m_paninc.y = 0; - } - else if (key == key_map_zoomin || key == key_map_zoomout) - { - mtof_zoommul = FRACUNIT; - ftom_zoommul = FRACUNIT; - } - } - return rc; -} - -void AM_changeWindowScale(void) -{ - - // Change the scaling multipliers - scale_mtof = FixedMul(scale_mtof, mtof_zoommul); - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - - if (scale_mtof < min_scale_mtof) - AM_minOutWindowScale(); - else if (scale_mtof > max_scale_mtof) - AM_maxOutWindowScale(); - else - AM_activateNewScale(); -} - -void AM_doFollowPlayer(void) -{ - if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) - { -// m_x = FTOM(MTOF(plr->mo->x - m_w/2)); -// m_y = FTOM(MTOF(plr->mo->y - m_h/2)); -// m_x = plr->mo->x - m_w/2; -// m_y = plr->mo->y - m_h/2; - m_x = FTOM(MTOF(plr->mo->x)) - m_w / 2; - m_y = FTOM(MTOF(plr->mo->y)) - m_h / 2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - - // do the parallax parchment scrolling. -/* - dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point - dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y)); - - if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first - dmapx=0; //goes into the automap. - mapxstart += dmapx; - mapystart += dmapy; - - while(mapxstart >= finit_width) - mapxstart -= finit_width; - while(mapxstart < 0) - mapxstart += finit_width; - while(mapystart >= finit_height) - mapystart -= finit_height; - while(mapystart < 0) - mapystart += finit_height; -*/ - f_oldloc.x = plr->mo->x; - f_oldloc.y = plr->mo->y; - } -} - -// Ripped out for Heretic -/* -void AM_updateLightLev(void) -{ - static nexttic = 0; -//static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; - static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; - static int litelevelscnt = 0; - - // Change light level - if (amclock>nexttic) - { - lightlev = litelevels[litelevelscnt++]; - if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; - nexttic = amclock + 6 - (amclock % 6); - } -} -*/ - -void AM_Ticker(void) -{ - - if (!automapactive) - return; - - amclock++; - - if (followplayer) - AM_doFollowPlayer(); - - // Change the zoom if necessary - if (ftom_zoommul != FRACUNIT) - AM_changeWindowScale(); - - // Change x,y location - if (m_paninc.x || m_paninc.y) - AM_changeWindowLoc(); - // Update light level -// AM_updateLightLev(); - -} - -void AM_clearFB(int color) -{ - int i, j; - int dmapx; - int dmapy; - - if (followplayer) - { - dmapx = (MTOF(plr->mo->x) - MTOF(oldplr.x)); //fixed point - dmapy = (MTOF(oldplr.y) - MTOF(plr->mo->y)); - - oldplr.x = plr->mo->x; - oldplr.y = plr->mo->y; -// if(f_oldloc.x == INT_MAX) //to eliminate an error when the user first -// dmapx=0; //goes into the automap. - mapxstart += dmapx >> 1; - mapystart += dmapy >> 1; - - while (mapxstart >= finit_width) - mapxstart -= finit_width; - while (mapxstart < 0) - mapxstart += finit_width; - while (mapystart >= finit_height) - mapystart -= finit_height; - while (mapystart < 0) - mapystart += finit_height; - } - else - { - // The released Hexen source does this here, but this causes a bug - // where the map background keeps moving when we reach the map - // boundaries. This is instead done in AM_changeWindowLoc. - /* - mapxstart += (MTOF(m_paninc.x) >> 1); - mapystart -= (MTOF(m_paninc.y) >> 1); - if (mapxstart >= finit_width) - mapxstart -= finit_width; - if (mapxstart < 0) - mapxstart += finit_width; - if (mapystart >= finit_height) - mapystart -= finit_height; - if (mapystart < 0) - mapystart += finit_height; - */ - } - - //blit the automap background to the screen. - j = mapystart * finit_width; - for (i = 0; i < SCREENHEIGHT - SBARHEIGHT; i++) - { - memcpy(I_VideoBuffer + i * finit_width, maplump + j + mapxstart, - finit_width - mapxstart); - memcpy(I_VideoBuffer + i * finit_width + finit_width - mapxstart, - maplump + j, mapxstart); - j += finit_width; - if (j >= finit_height * finit_width) - j = 0; - } - -// memcpy(I_VideoBuffer, maplump, finit_width*finit_height); -// memset(fb, color, f_w*f_h); -} - -// Based on Cohen-Sutherland clipping algorithm but with a slightly -// faster reject and precalculated slopes. If I need the speed, will -// hash algorithm to the common cases. - -boolean AM_clipMline(mline_t * ml, fline_t * fl) -{ - enum - { LEFT = 1, RIGHT = 2, BOTTOM = 4, TOP = 8 }; - int outcode1 = 0, outcode2 = 0, outside; - fpoint_t tmp = { 0, 0 }; - int dx, dy; - -#define DOOUTCODE(oc, mx, my) \ - (oc) = 0; \ - if ((my) < 0) (oc) |= TOP; \ - else if ((my) >= f_h) (oc) |= BOTTOM; \ - if ((mx) < 0) (oc) |= LEFT; \ - else if ((mx) >= f_w) (oc) |= RIGHT - - // do trivial rejects and outcodes - if (ml->a.y > m_y2) - outcode1 = TOP; - else if (ml->a.y < m_y) - outcode1 = BOTTOM; - if (ml->b.y > m_y2) - outcode2 = TOP; - else if (ml->b.y < m_y) - outcode2 = BOTTOM; - if (outcode1 & outcode2) - return false; // trivially outside - - if (ml->a.x < m_x) - outcode1 |= LEFT; - else if (ml->a.x > m_x2) - outcode1 |= RIGHT; - if (ml->b.x < m_x) - outcode2 |= LEFT; - else if (ml->b.x > m_x2) - outcode2 |= RIGHT; - if (outcode1 & outcode2) - return false; // trivially outside - - // transform to frame-buffer coordinates. - fl->a.x = CXMTOF(ml->a.x); - fl->a.y = CYMTOF(ml->a.y); - fl->b.x = CXMTOF(ml->b.x); - fl->b.y = CYMTOF(ml->b.y); - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - if (outcode1 & outcode2) - return false; - - while (outcode1 | outcode2) - { - // may be partially inside box - // find an outside point - if (outcode1) - outside = outcode1; - else - outside = outcode2; - // clip to each side - if (outside & TOP) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx * (fl->a.y)) / dy; - tmp.y = 0; - } - else if (outside & BOTTOM) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx * (fl->a.y - f_h)) / dy; - tmp.y = f_h - 1; - } - else if (outside & RIGHT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy * (f_w - 1 - fl->a.x)) / dx; - tmp.x = f_w - 1; - } - else if (outside & LEFT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy * (-fl->a.x)) / dx; - tmp.x = 0; - } - if (outside == outcode1) - { - fl->a = tmp; - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - } - else - { - fl->b = tmp; - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - } - if (outcode1 & outcode2) - return false; // trivially outside - } - - return true; -} - -#undef DOOUTCODE - -// Classic Bresenham w/ whatever optimizations I need for speed - -void AM_drawFline(fline_t * fl, int color) -{ - register int x, y, dx, dy, sx, sy, ax, ay, d; - //static fuck = 0; - - switch (color) - { - case WALLCOLORS: - DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, - &antialias[0][0], 8, 3); - break; - case FDWALLCOLORS: - DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, - &antialias[1][0], 8, 3); - break; - case CDWALLCOLORS: - DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, - &antialias[2][0], 8, 3); - break; - default: - { - // For debugging only - if (fl->a.x < 0 || fl->a.x >= f_w - || fl->a.y < 0 || fl->a.y >= f_h - || fl->b.x < 0 || fl->b.x >= f_w - || fl->b.y < 0 || fl->b.y >= f_h) - { - //fprintf(stderr, "fuck %d \r", fuck++); - return; - } - -#define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO! - - dx = fl->b.x - fl->a.x; - ax = 2 * (dx < 0 ? -dx : dx); - sx = dx < 0 ? -1 : 1; - - dy = fl->b.y - fl->a.y; - ay = 2 * (dy < 0 ? -dy : dy); - sy = dy < 0 ? -1 : 1; - - x = fl->a.x; - y = fl->a.y; - - if (ax > ay) - { - d = ay - ax / 2; - while (1) - { - DOT(x, y, color); - if (x == fl->b.x) - return; - if (d >= 0) - { - y += sy; - d -= ax; - } - x += sx; - d += ay; - } - } - else - { - d = ax - ay / 2; - while (1) - { - DOT(x, y, color); - if (y == fl->b.y) - return; - if (d >= 0) - { - x += sx; - d -= ay; - } - y += sy; - d += ax; - } - } - } - } -} - -/* Wu antialiased line drawer. - * (X0,Y0),(X1,Y1) = line to draw - * BaseColor = color # of first color in block used for antialiasing, the - * 100% intensity version of the drawing color - * NumLevels = size of color block, with BaseColor+NumLevels-1 being the - * 0% intensity version of the drawing color - * IntensityBits = log base 2 of NumLevels; the # of bits used to describe - * the intensity of the drawing color. 2**IntensityBits==NumLevels - */ -void PUTDOT(short xx, short yy, byte * cc, byte * cm) -{ - static int oldyy; - static int oldyyshifted; - byte *oldcc = cc; - - if (xx < 32) - cc += 7 - (xx >> 2); - else if (xx > (finit_width - 32)) - cc += 7 - ((finit_width - xx) >> 2); -// if(cc==oldcc) //make sure that we don't double fade the corners. -// { - if (yy < 32) - cc += 7 - (yy >> 2); - else if (yy > (finit_height - 32)) - cc += 7 - ((finit_height - yy) >> 2); -// } - if (cc > cm && cm != NULL) - { - cc = cm; - } - else if (cc > oldcc + 6) // don't let the color escape from the fade table... - { - cc = oldcc + 6; - } - if (yy == oldyy + 1) - { - oldyy++; - oldyyshifted += 320; - } - else if (yy == oldyy - 1) - { - oldyy--; - oldyyshifted -= 320; - } - else if (yy != oldyy) - { - oldyy = yy; - oldyyshifted = yy * 320; - } - fb[oldyyshifted + xx] = *(cc); -// fb[(yy)*f_w+(xx)]=*(cc); -} - -void DrawWuLine(int X0, int Y0, int X1, int Y1, byte * BaseColor, - int NumLevels, unsigned short IntensityBits) -{ - unsigned short IntensityShift, ErrorAdj, ErrorAcc; - unsigned short ErrorAccTemp, Weighting, WeightingComplementMask; - short DeltaX, DeltaY, Temp, XDir; - - /* Make sure the line runs top to bottom */ - if (Y0 > Y1) - { - Temp = Y0; - Y0 = Y1; - Y1 = Temp; - Temp = X0; - X0 = X1; - X1 = Temp; - } - /* Draw the initial pixel, which is always exactly intersected by - the line and so needs no weighting */ - PUTDOT(X0, Y0, &BaseColor[0], NULL); - - if ((DeltaX = X1 - X0) >= 0) - { - XDir = 1; - } - else - { - XDir = -1; - DeltaX = -DeltaX; /* make DeltaX positive */ - } - /* Special-case horizontal, vertical, and diagonal lines, which - require no weighting because they go right through the center of - every pixel */ - if ((DeltaY = Y1 - Y0) == 0) - { - /* Horizontal line */ - while (DeltaX-- != 0) - { - X0 += XDir; - PUTDOT(X0, Y0, &BaseColor[0], NULL); - } - return; - } - if (DeltaX == 0) - { - /* Vertical line */ - do - { - Y0++; - PUTDOT(X0, Y0, &BaseColor[0], NULL); - } - while (--DeltaY != 0); - return; - } - //diagonal line. - if (DeltaX == DeltaY) - { - do - { - X0 += XDir; - Y0++; - PUTDOT(X0, Y0, &BaseColor[0], NULL); - } - while (--DeltaY != 0); - return; - } - /* Line is not horizontal, diagonal, or vertical */ - ErrorAcc = 0; /* initialize the line error accumulator to 0 */ - /* # of bits by which to shift ErrorAcc to get intensity level */ - IntensityShift = 16 - IntensityBits; - /* Mask used to flip all bits in an intensity weighting, producing the - result (1 - intensity weighting) */ - WeightingComplementMask = NumLevels - 1; - /* Is this an X-major or Y-major line? */ - if (DeltaY > DeltaX) - { - /* Y-major line; calculate 16-bit fixed-point fractional part of a - pixel that X advances each time Y advances 1 pixel, truncating the - result so that we won't overrun the endpoint along the X axis */ - ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY; - /* Draw all pixels other than the first and last */ - while (--DeltaY) - { - ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ - ErrorAcc += ErrorAdj; /* calculate error for next pixel */ - if (ErrorAcc <= ErrorAccTemp) - { - /* The error accumulator turned over, so advance the X coord */ - X0 += XDir; - } - Y0++; /* Y-major, so always advance Y */ - /* The IntensityBits most significant bits of ErrorAcc give us the - intensity weighting for this pixel, and the complement of the - weighting for the paired pixel */ - Weighting = ErrorAcc >> IntensityShift; - PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); - PUTDOT(X0 + XDir, Y0, - &BaseColor[(Weighting ^ WeightingComplementMask)], - &BaseColor[7]); - } - /* Draw the final pixel, which is always exactly intersected by the line - and so needs no weighting */ - PUTDOT(X1, Y1, &BaseColor[0], NULL); - return; - } - /* It's an X-major line; calculate 16-bit fixed-point fractional part of a - pixel that Y advances each time X advances 1 pixel, truncating the - result to avoid overrunning the endpoint along the X axis */ - ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX; - /* Draw all pixels other than the first and last */ - while (--DeltaX) - { - ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ - ErrorAcc += ErrorAdj; /* calculate error for next pixel */ - if (ErrorAcc <= ErrorAccTemp) - { - /* The error accumulator turned over, so advance the Y coord */ - Y0++; - } - X0 += XDir; /* X-major, so always advance X */ - /* The IntensityBits most significant bits of ErrorAcc give us the - intensity weighting for this pixel, and the complement of the - weighting for the paired pixel */ - Weighting = ErrorAcc >> IntensityShift; - PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]); - PUTDOT(X0, Y0 + 1, - &BaseColor[(Weighting ^ WeightingComplementMask)], - &BaseColor[7]); - - } - /* Draw the final pixel, which is always exactly intersected by the line - and so needs no weighting */ - PUTDOT(X1, Y1, &BaseColor[0], NULL); -} - -void AM_drawMline(mline_t * ml, int color) -{ - static fline_t fl; - - if (AM_clipMline(ml, &fl)) - AM_drawFline(&fl, color); // draws it on frame buffer using fb coords - -} - -void AM_drawGrid(int color) -{ - fixed_t x, y; - fixed_t start, end; - mline_t ml; - - // Figure out start of vertical gridlines - start = m_x; - if ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)) - start += (MAPBLOCKUNITS << FRACBITS) - - ((start - bmaporgx) % (MAPBLOCKUNITS << FRACBITS)); - end = m_x + m_w; - - // draw vertical gridlines - ml.a.y = m_y; - ml.b.y = m_y + m_h; - for (x = start; x < end; x += (MAPBLOCKUNITS << FRACBITS)) - { - ml.a.x = x; - ml.b.x = x; - AM_drawMline(&ml, color); - } - - // Figure out start of horizontal gridlines - start = m_y; - if ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)) - start += (MAPBLOCKUNITS << FRACBITS) - - ((start - bmaporgy) % (MAPBLOCKUNITS << FRACBITS)); - end = m_y + m_h; - - // draw horizontal gridlines - ml.a.x = m_x; - ml.b.x = m_x + m_w; - for (y = start; y < end; y += (MAPBLOCKUNITS << FRACBITS)) - { - ml.a.y = y; - ml.b.y = y; - AM_drawMline(&ml, color); - } -} - -void AM_drawWalls(void) -{ - int i; - static mline_t l; - - for (i = 0; i < numlines; i++) - { - l.a.x = lines[i].v1->x; - l.a.y = lines[i].v1->y; - l.b.x = lines[i].v2->x; - l.b.y = lines[i].v2->y; - if (cheating || (lines[i].flags & ML_MAPPED)) - { - if ((lines[i].flags & LINE_NEVERSEE) && !cheating) - continue; - if (!lines[i].backsector) - { - AM_drawMline(&l, WALLCOLORS + lightlev); - } - else - { - if (lines[i].flags & ML_SECRET) // secret door - { - if (cheating) - AM_drawMline(&l, 0); - else - AM_drawMline(&l, WALLCOLORS + lightlev); - } - else if (lines[i].special == 13 || lines[i].special == 83) - { // Locked door line -- all locked doors are greed - AM_drawMline(&l, GREENKEY); - } - else if (lines[i].special == 70 || lines[i].special == 71) - { // intra-level teleports are blue - AM_drawMline(&l, BLUEKEY); - } - else if (lines[i].special == 74 || lines[i].special == 75) - { // inter-level teleport/game-winning exit -- both are red - AM_drawMline(&l, BLOODRED); - } - else if (lines[i].backsector->floorheight - != lines[i].frontsector->floorheight) - { - AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change - } - else if (lines[i].backsector->ceilingheight - != lines[i].frontsector->ceilingheight) - { - AM_drawMline(&l, CDWALLCOLORS + lightlev); // ceiling level change - } - else if (cheating) - { - AM_drawMline(&l, TSWALLCOLORS + lightlev); - } - } - } - else if (plr->powers[pw_allmap]) - { - if (!(lines[i].flags & LINE_NEVERSEE)) - AM_drawMline(&l, GRAYS + 3); - } - } - -} - -void AM_rotate(fixed_t * x, fixed_t * y, angle_t a) -{ - fixed_t tmpx; - - tmpx = FixedMul(*x, finecosine[a >> ANGLETOFINESHIFT]) - - FixedMul(*y, finesine[a >> ANGLETOFINESHIFT]); - *y = FixedMul(*x, finesine[a >> ANGLETOFINESHIFT]) - + FixedMul(*y, finecosine[a >> ANGLETOFINESHIFT]); - *x = tmpx; -} - -void AM_drawLineCharacter(mline_t * lineguy, int lineguylines, fixed_t scale, - angle_t angle, int color, fixed_t x, fixed_t y) -{ - int i; - mline_t l; - - for (i = 0; i < lineguylines; i++) - { - l.a.x = lineguy[i].a.x; - l.a.y = lineguy[i].a.y; - if (scale) - { - l.a.x = FixedMul(scale, l.a.x); - l.a.y = FixedMul(scale, l.a.y); - } - if (angle) - AM_rotate(&l.a.x, &l.a.y, angle); - l.a.x += x; - l.a.y += y; - - l.b.x = lineguy[i].b.x; - l.b.y = lineguy[i].b.y; - if (scale) - { - l.b.x = FixedMul(scale, l.b.x); - l.b.y = FixedMul(scale, l.b.y); - } - if (angle) - AM_rotate(&l.b.x, &l.b.y, angle); - l.b.x += x; - l.b.y += y; - - AM_drawMline(&l, color); - } -} - -void AM_drawPlayers(void) -{ - int i; - player_t *p; - static int their_colors[] = { - AM_PLR1_COLOR, - AM_PLR2_COLOR, - AM_PLR3_COLOR, - AM_PLR4_COLOR, - AM_PLR5_COLOR, - AM_PLR6_COLOR, - AM_PLR7_COLOR, - AM_PLR8_COLOR - }; - int their_color = -1; - int color; - - if (!netgame) - { - AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, - WHITE, plr->mo->x, plr->mo->y); - return; - } - - for (i = 0; i < maxplayers; i++) - { - their_color++; - p = &players[i]; - if (deathmatch && !singledemo && p != plr) - { - continue; - } - if (!playeringame[i]) - continue; - color = their_colors[their_color]; - AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, - color, p->mo->x, p->mo->y); - } -} - -void AM_drawThings(int colors, int colorrange) -{ - int i; - mobj_t *t; - - for (i = 0; i < numsectors; i++) - { - t = sectors[i].thinglist; - while (t) - { - AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, - 16 << FRACBITS, t->angle, colors + lightlev, - t->x, t->y); - t = t->snext; - } - } -} - -/* -void AM_drawMarks(void) -{ - int i, fx, fy, w, h; - - for (i=0;iwidth); - h = SHORT(marknums[i]->height); - fx = CXMTOF(markpoints[i].x); - fy = CYMTOF(markpoints[i].y); - if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) - V_DrawPatch(fx, fy, marknums[i]); - } - } -} -*/ -/* -void AM_drawkeys(void) -{ - if(KeyPoints[0].x != 0 || KeyPoints[0].y != 0) - { - AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY, - KeyPoints[0].x, KeyPoints[0].y); - } - if(KeyPoints[1].x != 0 || KeyPoints[1].y != 0) - { - AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY, - KeyPoints[1].x, KeyPoints[1].y); - } - if(KeyPoints[2].x != 0 || KeyPoints[2].y != 0) - { - AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY, - KeyPoints[2].x, KeyPoints[2].y); - } -} -*/ - -/* -void AM_drawCrosshair(int color) -{ - fb[(f_w*(f_h+1))/2] = color; // single point for now -} -*/ - -void AM_Drawer(void) -{ - if (!automapactive) - return; - - UpdateState |= I_FULLSCRN; - AM_clearFB(BACKGROUND); - if (grid) - AM_drawGrid(GRIDCOLORS); - AM_drawWalls(); - AM_drawPlayers(); - DrawWorldTimer(); - - if (cheating == 2) - AM_drawThings(THINGCOLORS, THINGRANGE); - -// AM_drawCrosshair(XHAIRCOLORS); -// AM_drawMarks(); -// if(gameskill == sk_baby) AM_drawkeys(); - - MN_DrTextA(P_GetMapName(gamemap), 38, 144); - if (ShowKills && netgame && deathmatch) - { - AM_DrawDeathmatchStats(); - } -// I_Update(); -// V_MarkRect(f_x, f_y, f_w, f_h); - -} - -//=========================================================================== -// -// AM_DrawDeathmatchStats -// -//=========================================================================== - -// 8-player note: Proper player color names here, too - -const char *PlayerColorText[MAXPLAYERS] = { - "BLUE:", - "RED:", - "YELLOW:", - "GREEN:", - "JADE:", - "WHITE:", - "HAZEL:", - "PURPLE:" -}; - -void AM_DrawDeathmatchStats(void) -{ - int i, j, k, m; - int fragCount[MAXPLAYERS]; - int order[MAXPLAYERS]; - char textBuffer[80]; - int yPosition; - - for (i = 0; i < maxplayers; i++) - { - fragCount[i] = 0; - order[i] = -1; - } - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - { - continue; - } - else - { - for (j = 0; j < maxplayers; j++) - { - if (playeringame[j]) - { - fragCount[i] += players[i].frags[j]; - } - } - for (k = 0; k < maxplayers; k++) - { - if (order[k] == -1) - { - order[k] = i; - break; - } - else if (fragCount[i] > fragCount[order[k]]) - { - for (m = maxplayers - 1; m > k; m--) - { - order[m] = order[m - 1]; - } - order[k] = i; - break; - } - } - } - } - yPosition = 15; - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[order[i]]) - { - continue; - } - else - { - MN_DrTextA(PlayerColorText[order[i]], 8, yPosition); - M_snprintf(textBuffer, sizeof(textBuffer), - "%d", fragCount[order[i]]); - MN_DrTextA(textBuffer, 80, yPosition); - yPosition += 10; - } - } -} - -//=========================================================================== -// -// DrawWorldTimer -// -//=========================================================================== - -static void DrawWorldTimer(void) -{ - int days; - int hours; - int minutes; - int seconds; - int worldTimer; - char timeBuffer[15]; - char dayBuffer[20]; - - worldTimer = players[consoleplayer].worldTimer; - - worldTimer /= 35; - days = worldTimer / 86400; - worldTimer -= days * 86400; - hours = worldTimer / 3600; - worldTimer -= hours * 3600; - minutes = worldTimer / 60; - worldTimer -= minutes * 60; - seconds = worldTimer; - - M_snprintf(timeBuffer, sizeof(timeBuffer), - "%.2d : %.2d : %.2d", hours, minutes, seconds); - MN_DrTextA(timeBuffer, 240, 8); - - if (days) - { - if (days == 1) - { - M_snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAY", days); - } - else - { - M_snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAYS", days); - } - MN_DrTextA(dayBuffer, 240, 20); - if (days >= 5) - { - MN_DrTextA("YOU FREAK!!!", 230, 35); - } - } -} diff --git a/games/NXDoom/src/hexen/am_map.h b/games/NXDoom/src/hexen/am_map.h deleted file mode 100644 index f6081a448b0..00000000000 --- a/games/NXDoom/src/hexen/am_map.h +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __AMMAP_H__ -#define __AMMAP_H__ - -// For use if I do walls with outsides/insides -#define REDS 12*8 -#define REDRANGE 1 //16 -#define BLUES (256-4*16+8) -#define BLUERANGE 1 //8 -#define GREENS (33*8) -#define GREENRANGE 1 //16 -#define GRAYS (5*8) -#define GRAYSRANGE 1 //16 -#define BROWNS (14*8) -#define BROWNRANGE 1 //16 -#define YELLOWS 10*8 -#define YELLOWRANGE 1 -#define BLACK 0 -#define WHITE 4*8 -#define PARCH 13*8-1 -#define BLOODRED 177 -#define BLUEKEY 157 -#define YELLOWKEY 137 -#define GREENKEY 198 - -// Automap colors - -#define AM_PLR1_COLOR 157 // Blue -#define AM_PLR2_COLOR 177 // Red -#define AM_PLR3_COLOR 137 // Yellow -#define AM_PLR4_COLOR 198 // Green -#define AM_PLR5_COLOR 215 // Jade -#define AM_PLR6_COLOR 32 // White -#define AM_PLR7_COLOR 106 // Hazel -#define AM_PLR8_COLOR 234 // Purple - -#define BACKGROUND PARCH -#define YOURCOLORS WHITE -#define YOURRANGE 0 -#define WALLCOLORS REDS -#define WALLRANGE REDRANGE -#define TSWALLCOLORS GRAYS -#define TSWALLRANGE GRAYSRANGE -#define FDWALLCOLORS BROWNS -#define FDWALLRANGE BROWNRANGE -#define CDWALLCOLORS YELLOWS -#define CDWALLRANGE YELLOWRANGE -#define THINGCOLORS GREENS -#define THINGRANGE GREENRANGE -#define SECRETWALLCOLORS WALLCOLORS -#define SECRETWALLRANGE WALLRANGE -#define GRIDCOLORS (GRAYS + GRAYSRANGE/2) -#define GRIDRANGE 0 -#define XHAIRCOLORS GRAYS - -// drawing stuff - -#define AM_NUMMARKPOINTS 10 - -#define AM_MSGHEADER (('a'<<24)+('m'<<16)) -#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) -#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) - -#define INITSCALEMTOF (.2*FRACUNIT) // scale on entry -// how much the automap moves window per tic in frame-buffer coordinates -#define F_PANINC 4 // moves 140 pixels in 1 second -// how much zoom-in per tic -#define M_ZOOMIN ((int) (1.02*FRACUNIT)) // goes to 2x in 1 second -// how much zoom-out per tic -#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) // pulls out to 0.5x in 1 second - -// translates between frame-buffer and map distances -#define FTOM(x) FixedMul(((x)<<16),scale_ftom) -#define MTOF(x) (FixedMul((x),scale_mtof)>>16) -// translates between frame-buffer and map coordinates -#define CXMTOF(x) (f_x + MTOF((x)-m_x)) -#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) - -// the following is crap -#define LINE_NEVERSEE ML_DONTDRAW - -typedef struct -{ - int x, y; -} fpoint_t; - -typedef struct -{ - fpoint_t a, b; -} fline_t; - -typedef vertex_t mpoint_t; - -typedef struct -{ - mpoint_t a, b; -} mline_t; - -typedef struct -{ - fixed_t slp, islp; -} islope_t; - - -extern int cheating; -extern boolean automapactive; - - -void AM_Stop(void); - - -#endif diff --git a/games/NXDoom/src/hexen/ct_chat.c b/games/NXDoom/src/hexen/ct_chat.c deleted file mode 100644 index cba051dc09a..00000000000 --- a/games/NXDoom/src/hexen/ct_chat.c +++ /dev/null @@ -1,497 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include -#include -#include "h2def.h" -#include "i_input.h" -#include "s_sound.h" -#include "doomkeys.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "v_video.h" - -#define NUMKEYS 256 - -#define QUEUESIZE 128 -#define MESSAGESIZE 128 -#define MESSAGELEN 265 - -// 8-player note: Change this stuff (CT_PLR_*, and the key mappings) -enum -{ - CT_PLR_BLUE = 1, - CT_PLR_RED, - CT_PLR_YELLOW, - CT_PLR_GREEN, - CT_PLR_PLAYER5, - CT_PLR_PLAYER6, - CT_PLR_PLAYER7, - CT_PLR_PLAYER8, - CT_PLR_ALL -}; - -#define CT_ESCAPE 6 - -// Public data - - -boolean chatmodeon; - -// Private data - -void CT_queueChatChar(char ch); -void CT_ClearChatMessage(int player); -void CT_AddChar(int player, char c); -void CT_BackSpace(int player); - -int head; -int tail; -byte ChatQueue[QUEUESIZE]; -int chat_dest[MAXPLAYERS]; -char chat_msg[MAXPLAYERS][MESSAGESIZE]; -char plr_lastmsg[MAXPLAYERS][MESSAGESIZE + 9]; -int msgptr[MAXPLAYERS]; -int msglen[MAXPLAYERS]; - -boolean cheated; - -static int FontABaseLump; - -const char *CT_FromPlrText[MAXPLAYERS] = { - "BLUE: ", - "RED: ", - "YELLOW: ", - "GREEN: ", - "JADE: ", - "WHITE: ", - "HAZEL: ", - "PURPLE: " -}; - -char *chat_macros[10]; - -boolean altdown; -boolean shiftdown; - - -//=========================================================================== -// -// CT_Init -// -// Initialize chat mode data -//=========================================================================== - -void CT_Init(void) -{ - int i; - - head = 0; //initialize the queue index - tail = 0; - chatmodeon = false; - memset(ChatQueue, 0, QUEUESIZE); - for (i = 0; i < maxplayers; i++) - { - chat_dest[i] = 0; - msgptr[i] = 0; - memset(plr_lastmsg[i], 0, MESSAGESIZE); - memset(chat_msg[i], 0, MESSAGESIZE); - } - FontABaseLump = W_GetNumForName("FONTA_S") + 1; - return; -} - -//=========================================================================== -// -// CT_Stop -// -//=========================================================================== - -void CT_Stop(void) -{ - chatmodeon = false; - I_StopTextInput(); - return; -} - -// These keys are allowed by Vanilla Heretic: - -static boolean ValidChatChar(char c) -{ - return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '!' || c == '?' - || c == ' ' || c == '\'' - || c == ',' || c == '.' - || c == '-' || c == '='; -} - -//=========================================================================== -// -// CT_Responder -// -//=========================================================================== - -boolean CT_Responder(event_t * ev) -{ - char *macro; - - int sendto; - - if (!netgame) - { - return false; - } - if (ev->data1 == KEY_RALT) - { - altdown = (ev->type == ev_keydown); - return false; - } - if (ev->data1 == KEY_RSHIFT) - { - shiftdown = (ev->type == ev_keydown); - return false; - } - if (gamestate != GS_LEVEL || ev->type != ev_keydown) - { - return false; - } - if (!chatmodeon) - { - sendto = 0; - if (ev->data1 == key_multi_msg) - { - sendto = CT_PLR_ALL; - } - else if (ev->data1 == key_multi_msgplayer[0]) - { - sendto = CT_PLR_BLUE; - } - else if (ev->data1 == key_multi_msgplayer[1]) - { - sendto = CT_PLR_RED; - } - else if (ev->data1 == key_multi_msgplayer[2]) - { - sendto = CT_PLR_YELLOW; - } - else if (ev->data1 == key_multi_msgplayer[3]) - { - sendto = CT_PLR_GREEN; - } - else if (ev->data1 == key_multi_msgplayer[4]) - { - sendto = CT_PLR_PLAYER5; - } - else if (ev->data1 == key_multi_msgplayer[5]) - { - sendto = CT_PLR_PLAYER6; - } - else if (ev->data1 == key_multi_msgplayer[6]) - { - sendto = CT_PLR_PLAYER7; - } - else if (ev->data1 == key_multi_msgplayer[7]) - { - sendto = CT_PLR_PLAYER8; - } - if (sendto == 0 || (sendto != CT_PLR_ALL && !playeringame[sendto - 1]) - || sendto == consoleplayer + 1) - { - return false; - } - CT_queueChatChar(sendto); - chatmodeon = true; - I_StartTextInput(25, 10, SCREENWIDTH, 18); - return true; - } - else - { - if (altdown) - { - if (ev->data1 >= '0' && ev->data1 <= '9') - { - if (ev->data1 == '0') - { // macro 0 comes after macro 9 - ev->data1 = '9' + 1; - } - macro = chat_macros[ev->data1 - '1']; - CT_queueChatChar(KEY_ENTER); //send old message - CT_queueChatChar(chat_dest[consoleplayer]); // chose the dest. - while (*macro) - { - CT_queueChatChar(toupper(*macro++)); - } - CT_queueChatChar(KEY_ENTER); //send it off... - CT_Stop(); - return true; - } - } - if (ev->data1 == KEY_ENTER) - { - CT_queueChatChar(KEY_ENTER); - usearti = false; - CT_Stop(); - return true; - } - else if (ev->data1 == KEY_ESCAPE) - { - CT_queueChatChar(CT_ESCAPE); - CT_Stop(); - return true; - } - else if (ev->data1 == KEY_BACKSPACE) - { - CT_queueChatChar(KEY_BACKSPACE); - return true; - } - else if (ValidChatChar(ev->data3)) - { - CT_queueChatChar(toupper(ev->data3)); - return true; - } - } - return false; -} - -//=========================================================================== -// -// CT_Ticker -// -//=========================================================================== - -void CT_Ticker(void) -{ - int i; - int j; - char c; - int numplayers; - - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - { - continue; - } - if ((c = players[i].cmd.chatchar) != 0) - { - if (c <= CT_PLR_ALL) - { - chat_dest[i] = c; - continue; - } - else if (c == CT_ESCAPE) - { - CT_ClearChatMessage(i); - } - else if (c == KEY_ENTER) - { - numplayers = 0; - for (j = 0; j < maxplayers; j++) - { - numplayers += playeringame[j]; - } - CT_AddChar(i, 0); // set the end of message character - if (numplayers > 2) - { - M_StringCopy(plr_lastmsg[i], CT_FromPlrText[i], - sizeof(plr_lastmsg[i])); - M_StringConcat(plr_lastmsg[i], chat_msg[i], - sizeof(plr_lastmsg[i])); - } - else - { - M_StringCopy(plr_lastmsg[i], chat_msg[i], - sizeof(plr_lastmsg[i])); - } - if (i != consoleplayer && (chat_dest[i] == consoleplayer + 1 - || chat_dest[i] == CT_PLR_ALL) - && *chat_msg[i]) - { - P_SetMessage(&players[consoleplayer], plr_lastmsg[i], - true); - S_StartSound(NULL, SFX_CHAT); - } - else if (i == consoleplayer && (*chat_msg[i])) - { - if (numplayers <= 1) - { - P_SetMessage(&players[consoleplayer], - "THERE ARE NO OTHER PLAYERS IN THE GAME!", - true); - S_StartSound(NULL, SFX_CHAT); - } - } - CT_ClearChatMessage(i); - } - else if (c == KEY_BACKSPACE) - { - CT_BackSpace(i); - } - else - { - CT_AddChar(i, c); - } - } - } - return; -} - -//=========================================================================== -// -// CT_Drawer -// -//=========================================================================== - -void CT_Drawer(void) -{ - int i; - int x; - patch_t *patch; - - if (chatmodeon) - { - x = 25; - for (i = 0; i < msgptr[consoleplayer]; i++) - { - if (chat_msg[consoleplayer][i] < 33) - { - x += 6; - } - else - { - patch = W_CacheLumpNum(FontABaseLump + - chat_msg[consoleplayer][i] - 33, - PU_CACHE); - V_DrawPatch(x, 10, patch); - x += patch->width; - } - } - V_DrawPatch(x, 10, W_CacheLumpName("FONTA59", PU_CACHE)); - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } -} - -//=========================================================================== -// -// CT_queueChatChar -// -//=========================================================================== - -void CT_queueChatChar(char ch) -{ - if (((tail + 1) & (QUEUESIZE - 1)) == head) - { // the queue is full - return; - } - ChatQueue[tail] = ch; - tail = (tail + 1) & (QUEUESIZE - 1); -} - -//=========================================================================== -// -// CT_dequeueChatChar -// -//=========================================================================== - -char CT_dequeueChatChar(void) -{ - byte temp; - - if (head == tail) - { // queue is empty - return 0; - } - temp = ChatQueue[head]; - head = (head + 1) & (QUEUESIZE - 1); - return temp; -} - -//=========================================================================== -// -// CT_AddChar -// -//=========================================================================== - -void CT_AddChar(int player, char c) -{ - patch_t *patch; - - if (msgptr[player] + 1 >= MESSAGESIZE || msglen[player] >= MESSAGELEN) - { // full. - return; - } - chat_msg[player][msgptr[player]] = c; - msgptr[player]++; - if (c < 33) - { - msglen[player] += 6; - } - else - { - patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - msglen[player] += patch->width; - } -} - -//=========================================================================== -// -// CT_BackSpace -// -// Backs up a space, when the user hits (obviously) backspace -//=========================================================================== - -void CT_BackSpace(int player) -{ - patch_t *patch; - char c; - - if (msgptr[player] == 0) - { // message is already blank - return; - } - msgptr[player]--; - c = chat_msg[player][msgptr[player]]; - if (c < 33) - { - msglen[player] -= 6; - } - else - { - patch = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - msglen[player] -= patch->width; - } - chat_msg[player][msgptr[player]] = 0; -} - -//=========================================================================== -// -// CT_ClearChatMessage -// -// Clears out the data for the chat message, but the player's message -// is still saved in plrmsg. -//=========================================================================== - -void CT_ClearChatMessage(int player) -{ - memset(chat_msg[player], 0, MESSAGESIZE); - msgptr[player] = 0; - msglen[player] = 0; -} diff --git a/games/NXDoom/src/hexen/ct_chat.h b/games/NXDoom/src/hexen/ct_chat.h deleted file mode 100644 index c46fdfce8bf..00000000000 --- a/games/NXDoom/src/hexen/ct_chat.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Chat mode stuff -// - -#ifndef HEXEN_CT_CHAT_H -#define HEXEN_CT_CHAT_H - -#define CT_PLR_GREEN 1 -#define CT_PLR_YELLOW 2 -#define CT_PLR_RED 3 -#define CT_PLR_BLUE 4 -#define CT_PLR_ALL 5 - -#define CT_KEY_GREEN 'g' -#define CT_KEY_YELLOW 'y' -#define CT_KEY_RED 'r' -#define CT_KEY_BLUE 'b' -#define CT_KEY_ALL 't' - -extern char *chat_macros[10]; - -#endif - diff --git a/games/NXDoom/src/hexen/d_net.c b/games/NXDoom/src/hexen/d_net.c deleted file mode 100644 index 252914722cd..00000000000 --- a/games/NXDoom/src/hexen/d_net.c +++ /dev/null @@ -1,283 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM Network game communication and protocol, -// all OS independend parts. -// - -#include - -#include "m_argv.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "i_videohr.h" -#include "h2def.h" -#include "m_misc.h" -#include "p_local.h" -#include "s_sound.h" -#include "w_checksum.h" - -#include "deh_main.h" - -#include "d_loop.h" - -ticcmd_t *netcmds; - - -// Called when a player leaves the game - -static void PlayerQuitGame(player_t *player) -{ - static char exitmsg[80]; - unsigned int player_num; - - player_num = player - players; - - M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg)); - exitmsg[7] += player_num; - P_SetMessage(&players[consoleplayer], exitmsg, true); - S_StartSound(NULL, SFX_CHAT); - - playeringame[player_num] = false; - - // TODO: check if it is sensible to do this: - - if (demorecording) - { - G_CheckDemoStatus (); - } -} - -static void RunTic(ticcmd_t *cmds, boolean *ingame) -{ - unsigned int i; - - // Check for player quits. - - for (i = 0; i < maxplayers; ++i) - { - if (!demoplayback && playeringame[i] && !ingame[i]) - { - PlayerQuitGame(&players[i]); - } - } - - netcmds = cmds; - - // check that there are players in the game. if not, we cannot - // run a tic. - - if (advancedemo) - H2_DoAdvanceDemo (); - - G_Ticker (); -} - -static loop_interface_t hexen_loop_interface = { - H2_ProcessEvents, - G_BuildTiccmd, - RunTic, - MN_Ticker -}; - - -// Load game settings from the specified structure and -// set global variables. - -static void LoadGameSettings(net_gamesettings_t *settings) -{ - unsigned int i; - - deathmatch = settings->deathmatch; - ticdup = settings->ticdup; - startepisode = settings->episode; - startmap = settings->map; - startskill = settings->skill; - // TODO startloadgame = settings->loadgame; - lowres_turn = settings->lowres_turn; - nomonsters = settings->nomonsters; - respawnparm = settings->respawn_monsters; - consoleplayer = settings->consoleplayer; - - if (lowres_turn) - { - printf("NOTE: Turning resolution is reduced; this is probably " - "because there is a client recording a Vanilla demo.\n"); - } - - for (i=0; inum_players; - PlayerClass[i] = settings->player_classes[i]; - - if (PlayerClass[i] >= NUMCLASSES) - { - PlayerClass[i] = PCLASS_FIGHTER; - } - } -} - -// Save the game settings from global variables to the specified -// game settings structure. - -static void SaveGameSettings(net_gamesettings_t *settings) -{ - // jhaley 20120715: Some parts of the structure are being left - // uninitialized. If -class is not used on the command line, this - // can lead to a crash in SB_Init due to player class == 0xCCCCCCCC. - memset(settings, 0, sizeof(*settings)); - - // Fill in game settings structure with appropriate parameters - // for the new game - - settings->deathmatch = deathmatch; - settings->episode = startepisode; - settings->map = startmap; - settings->skill = startskill; - // TODO settings->loadgame = startloadgame; - settings->gameversion = exe_hexen_1_1; - settings->nomonsters = nomonsters; - settings->respawn_monsters = respawnparm; - settings->timelimit = 0; - - settings->lowres_turn = M_ParmExists("-record") - && !M_ParmExists("-longtics"); -} - -static void InitConnectData(net_connect_data_t *connect_data) -{ - int i; - - // - // Connect data - // - - // Game type fields: - - connect_data->gamemode = gamemode; - connect_data->gamemission = hexen; - - // Are we recording a demo? Possibly set lowres turn mode - - connect_data->lowres_turn = M_ParmExists("-record") - && !M_ParmExists("-longtics"); - - connect_data->drone = false; - connect_data->max_players = maxplayers; - - //! - // @category net - // @arg - // - // Specify player class: 0=fighter, 1=cleric, 2=mage, 3=pig. - // - - i = M_CheckParmWithArgs("-class", 1); - - if (i > 0) - { - connect_data->player_class = atoi(myargv[i + 1]); - } - else - { - connect_data->player_class = PCLASS_FIGHTER; - } - - // Read checksums of our WAD directory and dehacked information - - W_Checksum(connect_data->wad_sha1sum); - memset(connect_data->deh_sha1sum, 0, sizeof(sha1_digest_t)); - - connect_data->is_freedoom = 0; -} - -void D_ConnectNetGame(void) -{ - net_connect_data_t connect_data; - - InitConnectData(&connect_data); - netgame = D_InitNetGame(&connect_data); - - //! - // @category net - // - // Start the game playing as though in a netgame with a single - // player. This can also be used to play back single player netgame - // demos. - // - - if (M_CheckParm("-solo-net") > 0) - { - netgame = true; - } -} - -static boolean StartupProgress(int now_ready, int total) -{ - static int ready = 0; - - while (ready < now_ready) - { - ST_NetProgress(); - ++ready; - } - - ready = now_ready; - - // Allow the user to hit escape during netgame startup to abort. - return !I_CheckAbortHR(); -} - -// -// D_CheckNetGame -// Works out player numbers among the net participants -// - -void D_CheckNetGame(void) -{ - net_gamesettings_t settings; - - D_RegisterLoopCallbacks(&hexen_loop_interface); - - if (netgame) - { - autostart = true; - } - - SaveGameSettings(&settings); - D_StartNetGame(&settings, StartupProgress); - LoadGameSettings(&settings); - - // Finish netgame progress on startup screen. - - if (netgame) - { - StartupProgress(settings.num_players, settings.num_players); - ST_NetDone(); - } -} - -//========================================================================== -// -// NET_SendFrags -// -//========================================================================== - -void NET_SendFrags(player_t * player) -{ - // Not sure what this is intended for. Unused? -} - diff --git a/games/NXDoom/src/hexen/f_finale.c b/games/NXDoom/src/hexen/f_finale.c deleted file mode 100644 index 93af19e7a3b..00000000000 --- a/games/NXDoom/src/hexen/f_finale.c +++ /dev/null @@ -1,387 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "i_system.h" -#include "i_video.h" -#include "p_local.h" -#include "s_sound.h" -#include -#include "v_video.h" -#include "i_swap.h" -#include "am_map.h" - - -// MACROS ------------------------------------------------------------------ - -#define TEXTSPEED 3 -#define TEXTWAIT 250 - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void TextWrite(void); -static void DrawPic(void); -static void InitializeFade(boolean fadeIn); -static void DeInitializeFade(void); -static void FadePic(void); -static char *GetFinaleText(int sequence); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DECLARATIONS ------------------------------------------------ - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int FinaleStage; -static int FinaleCount; -static int FinaleEndCount; -static int FinaleLumpNum; -static int FontABaseLump; -static char *FinaleText; - -static fixed_t *Palette; -static fixed_t *PaletteDelta; -static byte *RealPalette; - -// CODE -------------------------------------------------------------------- - -//=========================================================================== -// -// F_StartFinale -// -//=========================================================================== - -void F_StartFinale(void) -{ - gameaction = ga_nothing; - gamestate = GS_FINALE; - viewactive = false; - automapactive = false; - P_ClearMessage(&players[consoleplayer]); - - FinaleStage = 0; - FinaleCount = 0; - FinaleText = GetFinaleText(0); - FinaleEndCount = 70; - FinaleLumpNum = W_GetNumForName("FINALE1"); - FontABaseLump = W_GetNumForName("FONTA_S") + 1; - InitializeFade(1); - -// S_ChangeMusic(mus_victor, true); - S_StartSongName("hall", false); // don't loop the song -} - -//=========================================================================== -// -// F_Responder -// -//=========================================================================== - -boolean F_Responder(event_t * event) -{ - return false; -} - -//=========================================================================== -// -// F_Ticker -// -//=========================================================================== - -void F_Ticker(void) -{ - FinaleCount++; - if (FinaleStage < 5 && FinaleCount >= FinaleEndCount) - { - FinaleCount = 0; - FinaleStage++; - switch (FinaleStage) - { - case 1: // Text 1 - FinaleEndCount = strlen(FinaleText) * TEXTSPEED + TEXTWAIT; - break; - case 2: // Pic 2, Text 2 - FinaleText = GetFinaleText(1); - FinaleEndCount = strlen(FinaleText) * TEXTSPEED + TEXTWAIT; - FinaleLumpNum = W_GetNumForName("FINALE2"); - S_StartSongName("orb", false); - break; - case 3: // Pic 2 -- Fade out - FinaleEndCount = 70; - DeInitializeFade(); - InitializeFade(0); - break; - case 4: // Pic 3 -- Fade in - FinaleLumpNum = W_GetNumForName("FINALE3"); - FinaleEndCount = 71; - DeInitializeFade(); - InitializeFade(1); - S_StartSongName("chess", true); - break; - case 5: // Pic 3 , Text 3 - FinaleText = GetFinaleText(2); - DeInitializeFade(); - break; - default: - break; - } - return; - } - if (FinaleStage == 0 || FinaleStage == 3 || FinaleStage == 4) - { - FadePic(); - } -} - -//=========================================================================== -// -// TextWrite -// -//=========================================================================== - -static void TextWrite(void) -{ - int count; - char *ch; - int c; - int cx, cy; - patch_t *w; - - memcpy(I_VideoBuffer, W_CacheLumpNum(FinaleLumpNum, PU_CACHE), - SCREENWIDTH * SCREENHEIGHT); - if (FinaleStage == 5) - { // Chess pic, draw the correct character graphic - if (netgame) - { - V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE)); - } - else if (PlayerClass[consoleplayer]) - { - V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc") - + PlayerClass[consoleplayer] - - 1, PU_CACHE)); - } - } - // Draw the actual text - if (FinaleStage == 5) - { - cy = 135; - } - else - { - cy = 5; - } - cx = 20; - ch = FinaleText; - count = (FinaleCount - 10) / TEXTSPEED; - if (count < 0) - { - count = 0; - } - for (; count; count--) - { - c = *ch++; - if (!c) - { - break; - } - if (c == '\n') - { - cx = 20; - cy += 9; - continue; - } - if (c < 32) - { - continue; - } - c = toupper(c); - if (c == 32) - { - cx += 5; - continue; - } - w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - if (cx + SHORT(w->width) > SCREENWIDTH) - { - break; - } - V_DrawPatch(cx, cy, w); - cx += SHORT(w->width); - } -} - -//=========================================================================== -// -// InitializeFade -// -//=========================================================================== - -static void InitializeFade(boolean fadeIn) -{ - unsigned i; - - Palette = Z_Malloc(768 * sizeof(fixed_t), PU_STATIC, 0); - PaletteDelta = Z_Malloc(768 * sizeof(fixed_t), PU_STATIC, 0); - RealPalette = Z_Malloc(768 * sizeof(byte), PU_STATIC, 0); - - if (fadeIn) - { - memset(RealPalette, 0, 768 * sizeof(byte)); - for (i = 0; i < 768; i++) - { - Palette[i] = 0; - PaletteDelta[i] = FixedDiv((*((byte *) W_CacheLumpName("playpal", - PU_CACHE) + - i)) << FRACBITS, 70 * FRACUNIT); - } - } - else - { - for (i = 0; i < 768; i++) - { - RealPalette[i] = - *((byte *) W_CacheLumpName("playpal", PU_CACHE) + i); - Palette[i] = RealPalette[i] << FRACBITS; - PaletteDelta[i] = FixedDiv(Palette[i], -70 * FRACUNIT); - } - } - I_SetPalette(RealPalette); -} - -//=========================================================================== -// -// DeInitializeFade -// -//=========================================================================== - -static void DeInitializeFade(void) -{ - Z_Free(Palette); - Z_Free(PaletteDelta); - Z_Free(RealPalette); -} - -//=========================================================================== -// -// FadePic -// -//=========================================================================== - -static void FadePic(void) -{ - unsigned i; - - for (i = 0; i < 768; i++) - { - Palette[i] += PaletteDelta[i]; - RealPalette[i] = Palette[i] >> FRACBITS; - } - I_SetPalette(RealPalette); -} - -//=========================================================================== -// -// DrawPic -// -//=========================================================================== - -static void DrawPic(void) -{ - memcpy(I_VideoBuffer, W_CacheLumpNum(FinaleLumpNum, PU_CACHE), - SCREENWIDTH * SCREENHEIGHT); - if (FinaleStage == 4 || FinaleStage == 5) - { // Chess pic, draw the correct character graphic - if (netgame) - { - V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE)); - } - else if (PlayerClass[consoleplayer]) - { - V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc") - + PlayerClass[consoleplayer] - - 1, PU_CACHE)); - } - } -} - -//=========================================================================== -// -// F_Drawer -// -//=========================================================================== - -void F_Drawer(void) -{ - switch (FinaleStage) - { - case 0: // Fade in initial finale screen - DrawPic(); - break; - case 1: - case 2: - TextWrite(); - break; - case 3: // Fade screen out - DrawPic(); - break; - case 4: // Fade in chess screen - DrawPic(); - break; - case 5: - TextWrite(); - break; - } - UpdateState |= I_FULLSCRN; -} - -//========================================================================== -// -// GetFinaleText -// -//========================================================================== - -static char *GetFinaleText(int sequence) -{ - const char *msgLumpName; - int msgSize; - int msgLump; - static const char *winMsgLumpNames[] = { - "win1msg", - "win2msg", - "win3msg" - }; - - msgLumpName = winMsgLumpNames[sequence]; - msgLump = W_GetNumForName(msgLumpName); - msgSize = W_LumpLength(msgLump); - if (msgSize >= MAX_INTRMSN_MESSAGE_SIZE) - { - I_Error("Finale message too long (%s)", msgLumpName); - } - W_ReadLump(msgLump, ClusterMessage); - ClusterMessage[msgSize] = 0; // Append terminator - return ClusterMessage; -} diff --git a/games/NXDoom/src/hexen/g_game.c b/games/NXDoom/src/hexen/g_game.c deleted file mode 100644 index ecfb3832767..00000000000 --- a/games/NXDoom/src/hexen/g_game.c +++ /dev/null @@ -1,2347 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include -#include "m_random.h" -#include "h2def.h" -#include "s_sound.h" -#include "doomkeys.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_video.h" -#include "i_system.h" -#include "i_timer.h" -#include "m_argv.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "v_video.h" - -#define AM_STARTKEY 9 - -// External functions - - -// Functions - -void G_ReadDemoTiccmd(ticcmd_t * cmd); -void G_WriteDemoTiccmd(ticcmd_t * cmd); - -void G_DoReborn(int playernum); - -void G_DoLoadLevel(void); -void G_DoInitNew(void); -void G_DoNewGame(void); -void G_DoPlayDemo(void); -void G_DoTeleportNewMap(void); -void G_DoCompleted(void); -void G_DoVictory(void); -void G_DoWorldDone(void); -void G_DoSaveGame(void); -void G_DoSingleReborn(void); - -void H2_PageTicker(void); -void H2_AdvanceDemo(void); - -static boolean InventoryMoveLeft(); -static boolean InventoryMoveRight(); - - -gameaction_t gameaction; -gamestate_t gamestate; -skill_t gameskill; -//boolean respawnmonsters; -int gameepisode; -int gamemap; -int prevmap; - -boolean paused; -boolean sendpause; // send a pause event next tic -boolean sendsave; // send a save event next tic -boolean usergame; // ok to save / end game - -boolean timingdemo; // if true, exit with report on completion -int starttime; // for comparative timing purposes - -boolean viewactive; - -boolean deathmatch; // only if started as net death -boolean netgame; // only true if packets are broadcast -boolean playeringame[MAXPLAYERS]; -player_t players[MAXPLAYERS]; -pclass_t PlayerClass[MAXPLAYERS]; - -// Position indicator for cooperative net-play reborn -int RebornPosition; - -int consoleplayer; // player taking events and displaying -int displayplayer; // view being displayed -int levelstarttic; // gametic at level start - -char *demoname; -boolean demorecording; -boolean longtics; // specify high resolution turning in demos -boolean lowres_turn; -boolean shortticfix; // calculate lowres turning like doom -boolean demoplayback; -boolean demoextend; -boolean netdemo; -byte *demobuffer, *demo_p, *demoend; -boolean singledemo; // quit after playing a demo from cmdline - -boolean precache = true; // if true, load all graphics at start - -// TODO: Hexen uses 16-bit shorts for consistancy? -byte consistancy[MAXPLAYERS][BACKUPTICS]; - -int mouseSensitivity = 5; - -int LeaveMap; -static int LeavePosition; - -//#define MAXPLMOVE 0x32 // Old Heretic Max move - -fixed_t MaxPlayerMove[NUMCLASSES] = { 0x3C, 0x32, 0x2D, 0x31 }; -fixed_t forwardmove[NUMCLASSES][2] = { - {0x1D, 0x3C}, - {0x19, 0x32}, - {0x16, 0x2E}, - {0x18, 0x31} -}; - -fixed_t sidemove[NUMCLASSES][2] = { - {0x1B, 0x3B}, - {0x18, 0x28}, - {0x15, 0x25}, - {0x17, 0x27} -}; - -fixed_t angleturn[3] = { 640, 1280, 320 }; // + slow turn - -static int *weapon_keys[] = -{ - &key_weapon1, - &key_weapon2, - &key_weapon3, - &key_weapon4, -}; - -static int next_weapon = 0; - -#define SLOWTURNTICS 6 - -boolean gamekeydown[NUMKEYS]; -int turnheld; // for accelerative turning -int lookheld; - - -boolean mousearray[MAX_MOUSE_BUTTONS + 1]; -boolean *mousebuttons = &mousearray[1]; - // allow [-1] -int mousex, mousey; // mouse values are used once -int dclicktime, dclickstate, dclicks; -int dclicktime2, dclickstate2, dclicks2; - -#define MAX_JOY_BUTTONS 20 - -int joyxmove, joyymove; // joystick values are repeated -int joystrafemove; -int joylook; -boolean joyarray[MAX_JOY_BUTTONS + 1]; -boolean *joybuttons = &joyarray[1]; // allow [-1] - -int savegameslot; -char savedescription[32]; - -int vanilla_demo_limit = 1; - -int inventoryTics; - -// haleyjd: removed externdriver crap - -static skill_t TempSkill; -static int TempEpisode; -static int TempMap; - -boolean testcontrols = false; -int testcontrols_mousespeed; - -//============================================================================= -/* -==================== -= -= G_BuildTiccmd -= -= Builds a ticcmd from all of the available inputs or reads it from the -= demo buffer. -= If recording a demo, write it out -==================== -*/ - -boolean usearti = true; - -void G_BuildTiccmd(ticcmd_t *cmd, int maketic) -{ - int i; - boolean strafe, bstrafe; - int speed, tspeed, lspeed; - int forward, side; - int look, arti; - int flyheight; - int pClass; - - // haleyjd: removed externdriver crap - - pClass = players[consoleplayer].class; - memset(cmd, 0, sizeof(*cmd)); - -// cmd->consistancy = -// consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS]; - - cmd->consistancy = consistancy[consoleplayer][maketic % BACKUPTICS]; - -//printf ("cons: %i\n",cmd->consistancy); - - strafe = gamekeydown[key_strafe] - || mousebuttons[mousebstrafe] - || joybuttons[joybstrafe]; - - // Allow joybspeed hack. - - speed = key_speed >= NUMKEYS - || joybspeed >= MAX_JOY_BUTTONS - || gamekeydown[key_speed] - || joybuttons[joybspeed] - || mousebuttons[mousebspeed]; - - // haleyjd: removed externdriver crap - - forward = side = look = arti = flyheight = 0; - -// -// use two stage accelerative turning on the keyboard and joystick -// - if (joyxmove < 0 || joyxmove > 0 - || gamekeydown[key_right] || gamekeydown[key_left] - || mousebuttons[mousebturnright] || mousebuttons[mousebturnleft]) - turnheld += ticdup; - else - turnheld = 0; - if (turnheld < SLOWTURNTICS) - tspeed = 2; // slow turn - else - tspeed = speed; - - if (gamekeydown[key_lookdown] || gamekeydown[key_lookup]) - { - lookheld += ticdup; - } - else - { - lookheld = 0; - } - if (lookheld < SLOWTURNTICS) - { - lspeed = 1; // 3; - } - else - { - lspeed = 2; // 5; - } - -// -// let movement keys cancel each other out -// - if (strafe) - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - { - side += sidemove[pClass][speed]; - } - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - { - side -= sidemove[pClass][speed]; - } - if (use_analog && joyxmove) - { - joyxmove = joyxmove * joystick_move_sensitivity / 10; - joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; - joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; - side += FixedMul(sidemove[pClass][speed], joyxmove); - } - else if (joystick_move_sensitivity) - { - if (joyxmove > 0) - { - side += sidemove[pClass][speed]; - } - if (joyxmove < 0) - { - side -= sidemove[pClass][speed]; - } - } - } - else - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - cmd->angleturn -= angleturn[tspeed]; - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - cmd->angleturn += angleturn[tspeed]; - if (use_analog && joyxmove) - { - // Cubic response curve allows for finer control when stick - // deflection is small. - joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); - joyxmove = joyxmove * joystick_turn_sensitivity / 10; - cmd->angleturn -= FixedMul(angleturn[1], joyxmove); - } - else if (joystick_turn_sensitivity) - { - if (joyxmove > 0) - cmd->angleturn -= angleturn[tspeed]; - if (joyxmove < 0) - cmd->angleturn += angleturn[tspeed]; - } - } - - if (gamekeydown[key_up]) - { - forward += forwardmove[pClass][speed]; - } - if (gamekeydown[key_down]) - { - forward -= forwardmove[pClass][speed]; - } - if (use_analog && joyymove) - { - joyymove = joyymove * joystick_move_sensitivity / 10; - joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; - joyymove = (joyymove < -FRACUNIT) ? FRACUNIT : joyymove; - forward -= FixedMul(forwardmove[pClass][speed], joyymove); - } - else if (joystick_move_sensitivity) - { - if (joyymove < 0) - { - forward += forwardmove[pClass][speed]; - } - if (joyymove > 0) - { - forward -= forwardmove[pClass][speed]; - } - } - if (gamekeydown[key_straferight] || mousebuttons[mousebstraferight] - || joybuttons[joybstraferight]) - { - side += sidemove[pClass][speed]; - } - if (gamekeydown[key_strafeleft] || mousebuttons[mousebstrafeleft] - || joybuttons[joybstrafeleft]) - { - side -= sidemove[pClass][speed]; - } - - if (use_analog && joystrafemove) - { - joystrafemove = joystrafemove * joystick_move_sensitivity / 10; - joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; - joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; - side += FixedMul(sidemove[pClass][speed], joystrafemove); - } - else if (joystick_move_sensitivity) - { - if (joystrafemove < 0) - side -= sidemove[pClass][speed]; - if (joystrafemove > 0) - side += sidemove[pClass][speed]; - } - - // Look up/down/center keys - if (gamekeydown[key_lookup]) - { - look = lspeed; - } - if (gamekeydown[key_lookdown]) - { - look = -lspeed; - } - if (use_analog && joylook) - { - joylook = joylook * joystick_look_sensitivity / 10; - joylook = (joylook > FRACUNIT) ? FRACUNIT : joylook; - joylook = (joylook < -FRACUNIT) ? -FRACUNIT : joylook; - look = -FixedMul(2, joylook); - } - else if (joystick_look_sensitivity) - { - if (joylook < 0) - { - look = lspeed; - } - - if (joylook > 0) - { - look = -lspeed; - } - } - // haleyjd: removed externdriver crap - if (gamekeydown[key_lookcenter]) - { - look = TOCENTER; - } - - // haleyjd: removed externdriver crap - - // Fly up/down/drop keys - if (gamekeydown[key_flyup] || joybuttons[joybflyup]) - { - flyheight = 5; // note that the actual flyheight will be twice this - } - if (gamekeydown[key_flydown] || joybuttons[joybflydown]) - { - flyheight = -5; - } - if (gamekeydown[key_flycenter] || joybuttons[joybflycenter]) - { - flyheight = TOCENTER; - // haleyjd: removed externdriver crap - look = TOCENTER; - } - // Use artifact key - if (gamekeydown[key_useartifact] || mousebuttons[mousebuseartifact] - || joybuttons[joybuseartifact]) - { - if (gamekeydown[key_speed] && artiskip) - { - if (players[consoleplayer].inventory[inv_ptr].type != arti_none) - { // Skip an artifact - gamekeydown[key_useartifact] = false; - mousebuttons[mousebuseartifact] = false; - joybuttons[joybuseartifact] = false; - P_PlayerNextArtifact(&players[consoleplayer]); - } - } - else - { - if (inventory) - { - players[consoleplayer].readyArtifact = - players[consoleplayer].inventory[inv_ptr].type; - inventory = false; - cmd->arti = 0; - usearti = false; - } - else if (usearti) - { - cmd->arti |= - players[consoleplayer].inventory[inv_ptr]. - type & AFLAG_MASK; - usearti = false; - } - } - } - if (gamekeydown[key_jump] || mousebuttons[mousebjump] - || joybuttons[joybjump]) - { - cmd->arti |= AFLAG_JUMP; - } - if (mn_SuicideConsole) - { - cmd->arti |= AFLAG_SUICIDE; - mn_SuicideConsole = false; - } - - // Artifact hot keys - if (gamekeydown[key_arti_all] && !cmd->arti) - { - gamekeydown[key_arti_all] = false; // Use one of each artifact - cmd->arti = NUMARTIFACTS; - } - else if (gamekeydown[key_arti_health] && !cmd->arti - && (players[consoleplayer].mo->health < MAXHEALTH)) - { - gamekeydown[key_arti_health] = false; - cmd->arti = arti_health; - } - else if (gamekeydown[key_arti_poisonbag] && !cmd->arti) - { - gamekeydown[key_arti_poisonbag] = false; - cmd->arti = arti_poisonbag; - } - else if (gamekeydown[key_arti_blastradius] && !cmd->arti) - { - gamekeydown[key_arti_blastradius] = false; - cmd->arti = arti_blastradius; - } - else if (gamekeydown[key_arti_teleport] && !cmd->arti) - { - gamekeydown[key_arti_teleport] = false; - cmd->arti = arti_teleport; - } - else if (gamekeydown[key_arti_teleportother] && !cmd->arti) - { - gamekeydown[key_arti_teleportother] = false; - cmd->arti = arti_teleportother; - } - else if (gamekeydown[key_arti_egg] && !cmd->arti) - { - gamekeydown[key_arti_egg] = false; - cmd->arti = arti_egg; - } - else if (gamekeydown[key_arti_invulnerability] && !cmd->arti - && !players[consoleplayer].powers[pw_invulnerability]) - { - gamekeydown[key_arti_invulnerability] = false; - cmd->arti = arti_invulnerability; - } - -// -// buttons -// - cmd->chatchar = CT_dequeueChatChar(); - - if (gamekeydown[key_fire] || mousebuttons[mousebfire] - || joybuttons[joybfire]) - cmd->buttons |= BT_ATTACK; - - if (gamekeydown[key_use] || joybuttons[joybuse] || mousebuttons[mousebuse]) - { - cmd->buttons |= BT_USE; - dclicks = 0; // clear double clicks if hit use button - } - - // Weapon cycling. Switch to previous or next weapon. - // (Disabled when player is a pig). - if (gamestate == GS_LEVEL - && players[consoleplayer].morphTics == 0 && next_weapon != 0) - { - int start_i; - - if (players[consoleplayer].pendingweapon == WP_NOCHANGE) - { - i = players[consoleplayer].readyweapon; - } - else - { - i = players[consoleplayer].pendingweapon; - } - - // Don't loop forever. - start_i = i; - do { - i = (i + next_weapon + NUMWEAPONS) % NUMWEAPONS; - } while (i != start_i && !players[consoleplayer].weaponowned[i]); - - cmd->buttons |= BT_CHANGE; - cmd->buttons |= i << BT_WEAPONSHIFT; - } - else - { - for (i=0; ibuttons |= BT_CHANGE; - cmd->buttons |= i< 1) - { - dclickstate = mousebuttons[mousebforward]; - if (dclickstate) - dclicks++; - if (dclicks == 2) - { - cmd->buttons |= BT_USE; - dclicks = 0; - } - else - dclicktime = 0; - } - else - { - dclicktime += ticdup; - if (dclicktime > 20) - { - dclicks = 0; - dclickstate = 0; - } - } - - // - // strafe double click - // - bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; - if (bstrafe != dclickstate2 && dclicktime2 > 1) - { - dclickstate2 = bstrafe; - if (dclickstate2) - dclicks2++; - if (dclicks2 == 2) - { - cmd->buttons |= BT_USE; - dclicks2 = 0; - } - else - dclicktime2 = 0; - } - else - { - dclicktime2 += ticdup; - if (dclicktime2 > 20) - { - dclicks2 = 0; - dclickstate2 = 0; - } - } - } - - if (strafe) - { - side += mousex * 2; - } - else - { - cmd->angleturn -= mousex * 0x8; - } - - if (mousex == 0) - { - testcontrols_mousespeed = 0; - } - - forward += mousey; - mousex = mousey = 0; - - if (forward > MaxPlayerMove[pClass]) - { - forward = MaxPlayerMove[pClass]; - } - else if (forward < -MaxPlayerMove[pClass]) - { - forward = -MaxPlayerMove[pClass]; - } - if (side > MaxPlayerMove[pClass]) - { - side = MaxPlayerMove[pClass]; - } - else if (side < -MaxPlayerMove[pClass]) - { - side = -MaxPlayerMove[pClass]; - } - if (players[consoleplayer].powers[pw_speed] - && !players[consoleplayer].morphTics) - { // Adjust for a player with a speed artifact - forward = (3 * forward) >> 1; - side = (3 * side) >> 1; - } - cmd->forwardmove += forward; - cmd->sidemove += side; - if (players[consoleplayer].playerstate == PST_LIVE) - { - if (look < 0) - { - look += 16; - } - cmd->lookfly = look; - } - if (flyheight < 0) - { - flyheight += 16; - } - cmd->lookfly |= flyheight << 4; - -// -// special buttons -// - if (sendpause) - { - sendpause = false; - cmd->buttons = BT_SPECIAL | BTS_PAUSE; - } - - if (sendsave) - { - sendsave = false; - cmd->buttons = - BT_SPECIAL | BTS_SAVEGAME | (savegameslot << BTS_SAVESHIFT); - } - - if (lowres_turn) - { - if (shortticfix) - { - static signed short carry = 0; - signed short desired_angleturn; - - desired_angleturn = cmd->angleturn + carry; - - // round angleturn to the nearest 256 unit boundary - // for recording demos with single byte values for turn - - cmd->angleturn = (desired_angleturn + 128) & 0xff00; - - // Carry forward the error from the reduced resolution to the - // next tic, so that successive small movements can accumulate. - - carry = desired_angleturn - cmd->angleturn; - } - else - { - // truncate angleturn to the nearest 256 boundary - // for recording demos with single byte values for turn - cmd->angleturn &= 0xff00; - } - } -} - - -/* -============== -= -= G_DoLoadLevel -= -============== -*/ - -void G_DoLoadLevel(void) -{ - int i; - - levelstarttic = gametic; // for time calculation - gamestate = GS_LEVEL; - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i] && players[i].playerstate == PST_DEAD) - players[i].playerstate = PST_REBORN; - memset(players[i].frags, 0, sizeof(players[i].frags)); - } - - SN_StopAllSequences(); - P_SetupLevel(gameepisode, gamemap, 0, gameskill); - displayplayer = consoleplayer; // view the guy you are playing - gameaction = ga_nothing; - Z_CheckHeap(); - -// -// clear cmd building stuff -// - - memset(gamekeydown, 0, sizeof(gamekeydown)); - joyxmove = joyymove = joystrafemove = joylook = 0; - mousex = mousey = 0; - sendpause = sendsave = paused = false; - memset(mousearray, 0, sizeof(mousearray)); - memset(joyarray, 0, sizeof(joyarray)); - - if (testcontrols) - { - P_SetMessage(&players[consoleplayer], "PRESS ESCAPE TO QUIT.", false); - } -} - -static void SetJoyButtons(unsigned int buttons_mask) -{ - int i; - player_t *plr; - - plr = &players[consoleplayer]; - - for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; - } - usearti = true; - } - } - - joybuttons[i] = button_on; - } -} - -// If an InventoryMove*() function is called when the inventory is not active, -// it will instead activate the inventory without attempting to change the -// selected item. This action is indicated by a return value of false. -// Otherwise, it attempts to change items and will return a value of true. - -static boolean InventoryMoveLeft() -{ - inventoryTics = 5 * 35; - if (!inventory) - { - inventory = true; - return false; - } - inv_ptr--; - if (inv_ptr < 0) - { - inv_ptr = 0; - } - else - { - curpos--; - if (curpos < 0) - { - curpos = 0; - } - } - return true; -} - -static boolean InventoryMoveRight() -{ - player_t *plr; - - plr = &players[consoleplayer]; - inventoryTics = 5 * 35; - if (!inventory) - { - inventory = true; - return false; - } - inv_ptr++; - if (inv_ptr >= plr->inventorySlotNum) - { - inv_ptr--; - if (inv_ptr < 0) - inv_ptr = 0; - } - else - { - curpos++; - if (curpos > 6) - { - curpos = 6; - } - } - return true; -} - -static void SetMouseButtons(unsigned int buttons_mask) -{ - int i; - player_t *plr; - - plr = &players[consoleplayer]; - - for (i=0; ireadyArtifact = plr->inventory[inv_ptr].type; - } - usearti = true; - } - } - - mousebuttons[i] = button_on; - } -} - -/* -=============================================================================== -= -= G_Responder -= -= get info needed to make ticcmd_ts for the players -= -=============================================================================== -*/ - -boolean G_Responder(event_t * ev) -{ - player_t *plr; - - plr = &players[consoleplayer]; - if (ev->type == ev_keyup && ev->data1 == key_useartifact) - { // flag to denote that it's okay to use an artifact - if (!inventory) - { - plr->readyArtifact = plr->inventory[inv_ptr].type; - } - usearti = true; - } - - // Check for spy mode player cycle - if (gamestate == GS_LEVEL && ev->type == ev_keydown - && ev->data1 == key_spy && !deathmatch) - { // Cycle the display player - do - { - displayplayer++; - if (displayplayer == maxplayers) - { - displayplayer = 0; - } - } - while (!playeringame[displayplayer] - && displayplayer != consoleplayer); - return (true); - } - - if (CT_Responder(ev)) - { // Chat ate the event - return (true); - } - if (gamestate == GS_LEVEL) - { - if (SB_Responder(ev)) - { // Status bar ate the event - return (true); - } - if (AM_Responder(ev)) - { // Automap ate the event - return (true); - } - } - - if (ev->type == ev_mouse) - { - testcontrols_mousespeed = abs(ev->data2); - } - - if (ev->type == ev_keydown && ev->data1 == key_prevweapon) - { - next_weapon = -1; - } - else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) - { - next_weapon = 1; - } - - switch (ev->type) - { - case ev_keydown: - if (ev->data1 == key_invleft) - { - if (InventoryMoveLeft()) - { - return (true); - } - break; - } - if (ev->data1 == key_invright) - { - if (InventoryMoveRight()) - { - return (true); - } - break; - } - if (ev->data1 == key_pause && !MenuActive) - { - sendpause = true; - return (true); - } - if (ev->data1 < NUMKEYS) - { - gamekeydown[ev->data1] = true; - } - return (true); // eat key down events - - case ev_keyup: - if (ev->data1 < NUMKEYS) - { - gamekeydown[ev->data1] = false; - } - return (false); // always let key up events filter down - - case ev_mouse: - SetMouseButtons(ev->data1); - mousex = ev->data2 * (mouseSensitivity + 5) / 10; - mousey = ev->data3 * (mouseSensitivity + 5) / 10; - return (true); // eat events - - case ev_joystick: - SetJoyButtons(ev->data1); - joyxmove = ev->data2; - joyymove = ev->data3; - joystrafemove = ev->data4; - joylook = ev->data5; - return (true); // eat events - - default: - break; - } - return (false); -} - - -//========================================================================== -// -// G_Ticker -// -//========================================================================== - -void G_Ticker(void) -{ - int i, buf; - ticcmd_t *cmd = NULL; - -// -// do player reborns if needed -// - for (i = 0; i < maxplayers; i++) - if (playeringame[i] && players[i].playerstate == PST_REBORN) - G_DoReborn(i); - -// -// do things to change the game state -// - while (gameaction != ga_nothing) - { - switch (gameaction) - { - case ga_loadlevel: - G_DoLoadLevel(); - break; - case ga_initnew: - G_DoInitNew(); - break; - case ga_newgame: - G_DoNewGame(); - break; - case ga_loadgame: - Draw_LoadIcon(); - G_DoLoadGame(); - break; - case ga_savegame: - Draw_SaveIcon(); - G_DoSaveGame(); - break; - case ga_singlereborn: - G_DoSingleReborn(); - break; - case ga_playdemo: - G_DoPlayDemo(); - break; - case ga_screenshot: - V_ScreenShot("HEXEN%02i.%s"); - P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false); - gameaction = ga_nothing; - break; - case ga_leavemap: - Draw_TeleportIcon(); - G_DoTeleportNewMap(); - break; - case ga_completed: - G_DoCompleted(); - break; - case ga_worlddone: - G_DoWorldDone(); - break; - case ga_victory: - F_StartFinale(); - break; - default: - break; - } - } - - -// -// get commands, check consistancy, and build new consistancy check -// - //buf = gametic%BACKUPTICS; - buf = (gametic / ticdup) % BACKUPTICS; - - for (i = 0; i < maxplayers; i++) - if (playeringame[i]) - { - cmd = &players[i].cmd; - - memcpy(cmd, &netcmds[i], sizeof(ticcmd_t)); - - if (demoplayback) - G_ReadDemoTiccmd(cmd); - if (demorecording) - G_WriteDemoTiccmd(cmd); - - if (netgame && !netdemo && !(gametic % ticdup)) - { - if (gametic > BACKUPTICS - && consistancy[i][buf] != cmd->consistancy) - { - I_Error("consistency failure (%i should be %i)", - cmd->consistancy, consistancy[i][buf]); - } - if (players[i].mo) - consistancy[i][buf] = players[i].mo->x; - else - consistancy[i][buf] = rndindex; - } - } - -// -// check for special buttons -// - for (i = 0; i < maxplayers; i++) - if (playeringame[i]) - { - if (players[i].cmd.buttons & BT_SPECIAL) - { - switch (players[i].cmd.buttons & BT_SPECIALMASK) - { - case BTS_PAUSE: - paused ^= 1; - if (paused) - { - S_PauseSound(); - } - else - { - S_ResumeSound(); - } - break; - - case BTS_SAVEGAME: - if (!savedescription[0]) - { - if (netgame) - { - M_StringCopy(savedescription, "NET GAME", - sizeof(savedescription)); - } - else - { - M_StringCopy(savedescription, "SAVE GAME", - sizeof(savedescription)); - } - } - savegameslot = - (players[i].cmd. - buttons & BTS_SAVEMASK) >> BTS_SAVESHIFT; - gameaction = ga_savegame; - break; - } - } - } - // turn inventory off after a certain amount of time - if (inventory && !(--inventoryTics)) - { - players[consoleplayer].readyArtifact = - players[consoleplayer].inventory[inv_ptr].type; - inventory = false; - cmd->arti = 0; - } -// -// do main actions -// -// -// do main actions -// - switch (gamestate) - { - case GS_LEVEL: - P_Ticker(); - SB_Ticker(); - AM_Ticker(); - CT_Ticker(); - break; - case GS_INTERMISSION: - IN_Ticker(); - break; - case GS_FINALE: - F_Ticker(); - break; - case GS_DEMOSCREEN: - H2_PageTicker(); - break; - } -} - - -/* -============================================================================== - - PLAYER STRUCTURE FUNCTIONS - -also see P_SpawnPlayer in P_Things -============================================================================== -*/ - -//========================================================================== -// -// G_PlayerExitMap -// -// Called when the player leaves a map. -// -//========================================================================== - -void G_PlayerExitMap(int playerNumber) -{ - int i; - player_t *player; - int flightPower; - - player = &players[playerNumber]; - -// if(deathmatch) -// { -// // Strip all but one of each type of artifact -// for(i = 0; i < player->inventorySlotNum; i++) -// { -// player->inventory[i].count = 1; -// } -// player->artifactCount = player->inventorySlotNum; -// } -// else - - // Strip all current powers (retain flight) - flightPower = player->powers[pw_flight]; - memset(player->powers, 0, sizeof(player->powers)); - player->powers[pw_flight] = flightPower; - - if (deathmatch) - { - player->powers[pw_flight] = 0; - } - else - { - if (P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap)) - { // Entering new cluster - // Strip all keys - player->keys = 0; - - // Strip flight artifact - for (i = 0; i < 25; i++) - { - player->powers[pw_flight] = 0; - P_PlayerUseArtifact(player, arti_fly); - } - player->powers[pw_flight] = 0; - } - } - - if (player->morphTics) - { - player->readyweapon = player->mo->special1.i; // Restore weapon - player->morphTics = 0; - } - player->messageTics = 0; - player->lookdir = 0; - player->mo->flags &= ~MF_SHADOW; // Remove invisibility - player->extralight = 0; // Remove weapon flashes - player->fixedcolormap = 0; // Remove torch - player->damagecount = 0; // No palette changes - player->bonuscount = 0; - player->poisoncount = 0; - if (player == &players[consoleplayer]) - { - SB_state = -1; // refresh the status bar - viewangleoffset = 0; - } -} - -//========================================================================== -// -// G_PlayerReborn -// -// Called after a player dies. Almost everything is cleared and -// initialized. -// -//========================================================================== - -void G_PlayerReborn(int player) -{ - player_t *p; - int frags[MAXPLAYERS]; - int killcount, itemcount, secretcount; - unsigned int worldTimer; - - memcpy(frags, players[player].frags, sizeof(frags)); - killcount = players[player].killcount; - itemcount = players[player].itemcount; - secretcount = players[player].secretcount; - worldTimer = players[player].worldTimer; - - p = &players[player]; - memset(p, 0, sizeof(*p)); - - memcpy(players[player].frags, frags, sizeof(players[player].frags)); - players[player].killcount = killcount; - players[player].itemcount = itemcount; - players[player].secretcount = secretcount; - players[player].worldTimer = worldTimer; - players[player].class = PlayerClass[player]; - - p->usedown = p->attackdown = true; // don't do anything immediately - p->playerstate = PST_LIVE; - p->health = MAXHEALTH; - p->readyweapon = p->pendingweapon = WP_FIRST; - p->weaponowned[WP_FIRST] = true; - p->messageTics = 0; - p->lookdir = 0; - localQuakeHappening[player] = false; - if (p == &players[consoleplayer]) - { - SB_state = -1; // refresh the status bar - inv_ptr = 0; // reset the inventory pointer - curpos = 0; - viewangleoffset = 0; - } -} - -/* -==================== -= -= G_CheckSpot -= -= Returns false if the player cannot be respawned at the given mapthing_t spot -= because something is occupying it -==================== -*/ - -void P_SpawnPlayer(mapthing_t * mthing); - -boolean G_CheckSpot(int playernum, mapthing_t * mthing) -{ - fixed_t x, y; - subsector_t *ss; - unsigned an; - mobj_t *mo; - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - players[playernum].mo->flags2 &= ~MF2_PASSMOBJ; - if (!P_CheckPosition(players[playernum].mo, x, y)) - { - players[playernum].mo->flags2 |= MF2_PASSMOBJ; - return false; - } - players[playernum].mo->flags2 |= MF2_PASSMOBJ; - -// spawn a teleport fog - ss = R_PointInSubsector(x, y); - an = ((unsigned) ANG45 * (mthing->angle / 45)) >> ANGLETOFINESHIFT; - - mo = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an], - ss->sector->floorheight + TELEFOGHEIGHT, MT_TFOG); - if (players[consoleplayer].viewz != 1) - S_StartSound(mo, SFX_TELEPORT); // don't start sound on first frame - - return true; -} - -/* -==================== -= -= G_DeathMatchSpawnPlayer -= -= Spawns a player at one of the random death match spots -= called at level load and each death -==================== -*/ - -void G_DeathMatchSpawnPlayer(int playernum) -{ - int i, j; - int selections; - - selections = deathmatch_p - deathmatchstarts; - - // This check has been moved to p_setup.c:P_LoadThings() - //if (selections < 8) - // I_Error ("Only %i deathmatch spots, 8 required", selections); - - for (j = 0; j < 20; j++) - { - i = P_Random() % selections; - if (G_CheckSpot(playernum, &deathmatchstarts[i])) - { - deathmatchstarts[i].type = playernum + 1; - P_SpawnPlayer(&deathmatchstarts[i]); - return; - } - } - -// no good spot, so the player will probably get stuck - P_SpawnPlayer(&playerstarts[0][playernum]); -} - -//========================================================================== -// -// G_DoReborn -// -//========================================================================== - -void G_DoReborn(int playernum) -{ - int i; - boolean oldWeaponowned[NUMWEAPONS]; - int oldKeys; - int oldPieces; - boolean foundSpot; - int bestWeapon; - - // quit demo unless -demoextend - if (!demoextend && G_CheckDemoStatus()) - { - return; - } - if (!netgame) - { - if (SV_RebornSlotAvailable()) - { // Use the reborn code if the slot is available - gameaction = ga_singlereborn; - } - else - { // Start a new game if there's no reborn info - gameaction = ga_newgame; - } - } - else - { // Net-game - players[playernum].mo->player = NULL; // Dissassociate the corpse - - if (deathmatch) - { // Spawn at random spot if in death match - G_DeathMatchSpawnPlayer(playernum); - return; - } - - // Cooperative net-play, retain keys and weapons - oldKeys = players[playernum].keys; - oldPieces = players[playernum].pieces; - for (i = 0; i < NUMWEAPONS; i++) - { - oldWeaponowned[i] = players[playernum].weaponowned[i]; - } - - foundSpot = false; - if (G_CheckSpot(playernum, &playerstarts[RebornPosition][playernum])) - { // Appropriate player start spot is open - P_SpawnPlayer(&playerstarts[RebornPosition][playernum]); - foundSpot = true; - } - else - { - // Try to spawn at one of the other player start spots - for (i = 0; i < maxplayers; i++) - { - if (G_CheckSpot(playernum, &playerstarts[RebornPosition][i])) - { // Found an open start spot - - // Fake as other player - playerstarts[RebornPosition][i].type = playernum + 1; - P_SpawnPlayer(&playerstarts[RebornPosition][i]); - - // Restore proper player type - playerstarts[RebornPosition][i].type = i + 1; - - foundSpot = true; - break; - } - } - } - - if (foundSpot == false) - { // Player's going to be inside something - P_SpawnPlayer(&playerstarts[RebornPosition][playernum]); - } - - // Restore keys and weapons - players[playernum].keys = oldKeys; - players[playernum].pieces = oldPieces; - for (bestWeapon = 0, i = 0; i < NUMWEAPONS; i++) - { - if (oldWeaponowned[i]) - { - bestWeapon = i; - players[playernum].weaponowned[i] = true; - } - } - players[playernum].mana[MANA_1] = 25; - players[playernum].mana[MANA_2] = 25; - if (bestWeapon) - { // Bring up the best weapon - players[playernum].pendingweapon = bestWeapon; - } - } -} - -void G_ScreenShot(void) -{ - gameaction = ga_screenshot; -} - -//========================================================================== -// -// G_StartNewInit -// -//========================================================================== - -void G_StartNewInit(void) -{ - SV_InitBaseSlot(); - SV_ClearRebornSlot(); - P_ACSInitNewGame(); - // Default the player start spot group to 0 - RebornPosition = 0; -} - -//========================================================================== -// -// G_StartNewGame -// -//========================================================================== - -void G_StartNewGame(skill_t skill) -{ - int realMap; - - G_StartNewInit(); - realMap = P_TranslateMap(1); - if (realMap == -1) - { - realMap = 1; - } - G_InitNew(TempSkill, 1, realMap); -} - -//========================================================================== -// -// G_TeleportNewMap -// -// Only called by the warp cheat code. Works just like normal map to map -// teleporting, but doesn't do any interlude stuff. -// -//========================================================================== - -void G_TeleportNewMap(int map, int position) -{ - gameaction = ga_leavemap; - LeaveMap = map; - LeavePosition = position; -} - -//========================================================================== -// -// G_DoTeleportNewMap -// -//========================================================================== - -void G_DoTeleportNewMap(void) -{ - SV_MapTeleport(LeaveMap, LeavePosition); - gamestate = GS_LEVEL; - gameaction = ga_nothing; - RebornPosition = LeavePosition; -} - -/* -boolean secretexit; -void G_ExitLevel (void) -{ - secretexit = false; - gameaction = ga_completed; -} -void G_SecretExitLevel (void) -{ - secretexit = true; - gameaction = ga_completed; -} -*/ - -//========================================================================== -// -// G_Completed -// -// Starts intermission routine, which is used only during hub exits, -// and DeathMatch games. -//========================================================================== - -void G_Completed(int map, int position) -{ - if (gamemode == shareware && map > 4) - { - P_SetMessage(&players[consoleplayer], "ACCESS DENIED -- DEMO", true); - S_StartSound(NULL, SFX_CHAT); - return; - } - - gameaction = ga_completed; - LeaveMap = map; - LeavePosition = position; -} - -void G_DoCompleted(void) -{ - int i; - - gameaction = ga_nothing; - - // quit demo unless -demoextend - if (!demoextend && G_CheckDemoStatus()) - { - return; - } - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - G_PlayerExitMap(i); - } - } - if (LeaveMap == -1 && LeavePosition == -1) - { - gameaction = ga_victory; - return; - } - else - { - gamestate = GS_INTERMISSION; - IN_Start(); - } - -/* - int i; - static int afterSecret[3] = { 7, 5, 5 }; - - gameaction = ga_nothing; - if(G_CheckDemoStatus()) - { - return; - } - for(i = 0; i < maxplayers; i++) - { - if(playeringame[i]) - { - G_PlayerFinishLevel(i); - } - } - prevmap = gamemap; - if(secretexit == true) - { - gamemap = 9; - } - else if(gamemap == 9) - { // Finished secret level - gamemap = afterSecret[gameepisode-1]; - } - else if(gamemap == 8) - { - gameaction = ga_victory; - return; - } - else - { - gamemap++; - } - gamestate = GS_INTERMISSION; - IN_Start(); -*/ -} - -//============================================================================ -// -// G_WorldDone -// -//============================================================================ - -void G_WorldDone(void) -{ - gameaction = ga_worlddone; -} - -//============================================================================ -// -// G_DoWorldDone -// -//============================================================================ - -void G_DoWorldDone(void) -{ - gamestate = GS_LEVEL; - G_DoLoadLevel(); - gameaction = ga_nothing; - viewactive = true; -} - -//========================================================================== -// -// G_DoSingleReborn -// -// Called by G_Ticker based on gameaction. Loads a game from the reborn -// save slot. -// -//========================================================================== - -void G_DoSingleReborn(void) -{ - gameaction = ga_nothing; - SV_LoadGame(SV_GetRebornSlot()); - SB_SetClassData(); -} - -//========================================================================== -// -// G_LoadGame -// -// Can be called by the startup code or the menu task. -// -//========================================================================== - -static int GameLoadSlot; - -void G_LoadGame(int slot) -{ - GameLoadSlot = slot; - gameaction = ga_loadgame; -} - -//========================================================================== -// -// G_DoLoadGame -// -// Called by G_Ticker based on gameaction. -// -//========================================================================== - -void G_DoLoadGame(void) -{ - gameaction = ga_nothing; - SV_LoadGame(GameLoadSlot); - if (!netgame) - { // Copy the base slot to the reborn slot - SV_UpdateRebornSlot(); - } - SB_SetClassData(); -} - -//========================================================================== -// -// G_SaveGame -// -// Called by the menu task. is a 24 byte text string. -// -//========================================================================== - -void G_SaveGame(int slot, char *description) -{ - savegameslot = slot; - M_StringCopy(savedescription, description, sizeof(savedescription)); - sendsave = true; -} - -//========================================================================== -// -// G_DoSaveGame -// -// Called by G_Ticker based on gameaction. -// -//========================================================================== - -void G_DoSaveGame(void) -{ - SV_SaveGame(savegameslot, savedescription); - gameaction = ga_nothing; - savedescription[0] = 0; - P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true); -} - -//========================================================================== -// -// G_DeferredNewGame -// -//========================================================================== - -void G_DeferredNewGame(skill_t skill) -{ - TempSkill = skill; - gameaction = ga_newgame; -} - -//========================================================================== -// -// G_DoNewGame -// -//========================================================================== - -void G_DoNewGame(void) -{ - G_StartNewGame(TempSkill); - gameaction = ga_nothing; -} - -/* -==================== -= -= G_InitNew -= -= Can be called by the startup code or the menu task -= consoleplayer, displayplayer, playeringame[] should be set -==================== -*/ - -void G_DeferedInitNew(skill_t skill, int episode, int map) -{ - TempSkill = skill; - TempEpisode = episode; - TempMap = map; - gameaction = ga_initnew; -} - -void G_DoInitNew(void) -{ - SV_InitBaseSlot(); - G_InitNew(TempSkill, TempEpisode, TempMap); - gameaction = ga_nothing; -} - -void G_InitNew(skill_t skill, int episode, int map) -{ - int i; - - if (paused) - { - paused = false; - S_ResumeSound(); - } - if (skill < sk_baby) - { - skill = sk_baby; - } - if (skill > sk_nightmare) - { - skill = sk_nightmare; - } - if (map < 1) - { - map = 1; - } - if (map > 99) - { - map = 99; - } - M_ClearRandom(); - // Force players to be initialized upon first level load - for (i = 0; i < maxplayers; i++) - { - players[i].playerstate = PST_REBORN; - players[i].worldTimer = 0; - } - - // Set up a bunch of globals - if (!demoextend) - { - // This prevents map-loading from interrupting a demo. - // demoextend is set back to false only if starting a new game or - // loading a saved one from the menu, and only during playback. - demorecording = false; - demoplayback = false; - netdemo = false; - usergame = true; // will be set false if a demo - } - paused = false; - viewactive = true; - gameepisode = episode; - gamemap = map; - gameskill = skill; - BorderNeedRefresh = true; - - // Initialize the sky - R_InitSky(map); - - // Give one null ticcmd_t - //gametic = 0; - //maketic = 1; - //for (i=0 ; iforwardmove = ((signed char) *demo_p++); - cmd->sidemove = ((signed char) *demo_p++); - - // If this is a longtics demo, read back in higher resolution - - if (longtics) - { - cmd->angleturn = *demo_p++; - cmd->angleturn |= (*demo_p++) << 8; - } - else - { - cmd->angleturn = ((unsigned char) *demo_p++) << 8; - } - - cmd->buttons = (unsigned char) *demo_p++; - cmd->lookfly = (unsigned char) *demo_p++; - cmd->arti = (unsigned char) *demo_p++; -} - -// Increase the size of the demo buffer to allow unlimited demos - -static void IncreaseDemoBuffer(void) -{ - int current_length; - byte *new_demobuffer; - byte *new_demop; - int new_length; - - // Find the current size - - current_length = demoend - demobuffer; - - // Generate a new buffer twice the size - new_length = current_length * 2; - - new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); - new_demop = new_demobuffer + (demo_p - demobuffer); - - // Copy over the old data - - memcpy(new_demobuffer, demobuffer, current_length); - - // Free the old buffer and point the demo pointers at the new buffer. - - Z_Free(demobuffer); - - demobuffer = new_demobuffer; - demo_p = new_demop; - demoend = demobuffer + new_length; -} - -void G_WriteDemoTiccmd(ticcmd_t * cmd) -{ - byte *demo_start; - - if (gamekeydown[key_demo_quit]) // press to end demo recording - G_CheckDemoStatus(); - - demo_start = demo_p; - - *demo_p++ = cmd->forwardmove; - *demo_p++ = cmd->sidemove; - - // If this is a longtics demo, record in higher resolution - - if (longtics) - { - *demo_p++ = (cmd->angleturn & 0xff); - *demo_p++ = (cmd->angleturn >> 8) & 0xff; - } - else - { - *demo_p++ = cmd->angleturn >> 8; - } - - *demo_p++ = cmd->buttons; - *demo_p++ = cmd->lookfly; - *demo_p++ = cmd->arti; - - // reset demo pointer back - demo_p = demo_start; - - if (demo_p > demoend - 16) - { - if (vanilla_demo_limit) - { - // no more space - G_CheckDemoStatus(); - return; - } - else - { - // Vanilla demo limit disabled: unlimited - // demo lengths! - - IncreaseDemoBuffer(); - } - } - - G_ReadDemoTiccmd(cmd); // make SURE it is exactly the same -} - - - -/* -=================== -= -= G_RecordDemo -= -=================== -*/ - -void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, - const char *name) -{ - size_t demoname_size; - int i; - int maxsize; - - //! - // @category demo - // - // Record or playback a demo with high resolution turning. - // - - longtics = D_NonVanillaRecord(M_ParmExists("-longtics"), - "vvHeretic longtics demo"); - - // If not recording a longtics demo, record in low res - - lowres_turn = !longtics; - - //! - // @category demo - // - // Smooth out low resolution turning when recording a demo. - // - - shortticfix = M_ParmExists("-shortticfix"); - - G_InitNew(skill, episode, map); - usergame = false; - demoname_size = strlen(name) + 5; - demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); - M_snprintf(demoname, demoname_size, "%s.lmp", name); - maxsize = 0x20000; - - //! - // @arg - // @category demo - // @vanilla - // - // Specify the demo buffer size (KiB) - // - - i = M_CheckParmWithArgs("-maxdemo", 1); - if (i) - maxsize = atoi(myargv[i + 1]) * 1024; - demobuffer = Z_Malloc(maxsize, PU_STATIC, NULL); - demoend = demobuffer + maxsize; - - demo_p = demobuffer; - *demo_p++ = skill; - *demo_p++ = episode; - *demo_p++ = map; - - // Write special parameter bits onto player one byte. - // This aligns with vvHeretic demo usage. Hexen demo support has no - // precedent here so consistency with another game is chosen: - // 0x20 = -respawn - // 0x10 = -longtics - // 0x02 = -nomonsters - - *demo_p = 1; // assume player one exists - if (D_NonVanillaRecord(respawnparm, "vvHeretic -respawn header flag")) - { - *demo_p |= DEMOHEADER_RESPAWN; - } - if (longtics) - { - *demo_p |= DEMOHEADER_LONGTICS; - } - if (D_NonVanillaRecord(nomonsters, "vvHeretic -nomonsters header flag")) - { - *demo_p |= DEMOHEADER_NOMONSTERS; - } - demo_p++; - *demo_p++ = PlayerClass[0]; - - for (i = 1; i < maxplayers; i++) - { - *demo_p++ = playeringame[i]; - *demo_p++ = PlayerClass[i]; - } - - demorecording = true; -} - - -/* -=================== -= -= G_PlayDemo -= -=================== -*/ - -static const char *defdemoname; - -void G_DeferedPlayDemo(const char *name) -{ - defdemoname = name; - gameaction = ga_playdemo; -} - -void G_DoPlayDemo(void) -{ - skill_t skill; - int i, lumpnum, episode, map; - - gameaction = ga_nothing; - lumpnum = W_GetNumForName(defdemoname); - demobuffer = W_CacheLumpNum(lumpnum, PU_STATIC); - demo_p = demobuffer; - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - - // When recording we store some extra options inside the upper bits - // of the player 1 present byte. However, this is a non-vanilla extension. - // Note references to vvHeretic here; these are the extensions used by - // vvHeretic, which we're just reusing for Hexen demos too. There is no - // vvHexen. - if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_LONGTICS) != 0, - lumpnum, "vvHeretic longtics demo")) - { - longtics = true; - } - if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_RESPAWN) != 0, - lumpnum, "vvHeretic -respawn header flag")) - { - respawnparm = true; - } - if (D_NonVanillaPlayback((*demo_p & DEMOHEADER_NOMONSTERS) != 0, - lumpnum, "vvHeretic -nomonsters header flag")) - { - nomonsters = true; - } - - for (i = 0; i < maxplayers; i++) - { - playeringame[i] = (*demo_p++) != 0; - PlayerClass[i] = *demo_p++; - } - - if (playeringame[1] || M_ParmExists("-solo-net") - || M_ParmExists("-netdemo")) - { - netgame = true; - } - - // Initialize world info, etc. - G_StartNewInit(); - - precache = false; // don't spend a lot of time in loadlevel - G_InitNew(skill, episode, map); - precache = true; - usergame = false; - demoplayback = true; - - if (netgame) - { - netdemo = true; - } -} - - -/* -=================== -= -= G_TimeDemo -= -=================== -*/ - -void G_TimeDemo(char *name) -{ - skill_t skill; - int episode, map, i; - - demobuffer = demo_p = W_CacheLumpName(name, PU_STATIC); - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - - // Read special parameter bits: see G_RecordDemo() for details. - longtics = (*demo_p & DEMOHEADER_LONGTICS) != 0; - - // don't overwrite arguments from the command line - respawnparm |= (*demo_p & DEMOHEADER_RESPAWN) != 0; - nomonsters |= (*demo_p & DEMOHEADER_NOMONSTERS) != 0; - - for (i = 0; i < maxplayers; i++) - { - playeringame[i] = (*demo_p++) != 0; - PlayerClass[i] = *demo_p++; - } - - if (playeringame[1] || M_ParmExists("-solo-net") - || M_ParmExists("-netdemo")) - { - netgame = true; - } - - G_InitNew(skill, episode, map); - starttime = I_GetTime(); - - usergame = false; - demoplayback = true; - timingdemo = true; - singletics = true; - - if (netgame) - { - netdemo = true; - } -} - - -/* -=================== -= -= G_CheckDemoStatus -= -= Called after a death or level completion to allow demos to be cleaned up -= Returns true if a new demo loop action will take place -=================== -*/ - -boolean G_CheckDemoStatus(void) -{ - int endtime, realtics; - - if (timingdemo) - { - float fps; - endtime = I_GetTime(); - realtics = endtime - starttime; - fps = ((float) gametic * TICRATE) / realtics; - I_Error("timed %i gametics in %i realtics (%f fps)", - gametic, realtics, fps); - } - - if (demoplayback) - { - if (singledemo) - I_Quit(); - - W_ReleaseLumpName(defdemoname); - demoplayback = false; - netdemo = false; - netgame = false; - H2_AdvanceDemo(); - return true; - } - - if (demorecording) - { - *demo_p++ = DEMOMARKER; - M_WriteFile(demoname, demobuffer, demo_p - demobuffer); - Z_Free(demobuffer); - demorecording = false; - I_Error("Demo %s recorded", demoname); - } - - return false; -} diff --git a/games/NXDoom/src/hexen/h2_main.c b/games/NXDoom/src/hexen/h2_main.c deleted file mode 100644 index 0a7bff85fe6..00000000000 --- a/games/NXDoom/src/hexen/h2_main.c +++ /dev/null @@ -1,1227 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -// haleyjd: removed WATCOMC -#include -#include -#include - -#include "config.h" - -#include "h2def.h" -#include "ct_chat.h" -#include "d_iwad.h" -#include "d_mode.h" -#include "m_misc.h" -#include "s_sound.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_system.h" -#include "i_timer.h" -#include "m_argv.h" -#include "m_config.h" -#include "m_controls.h" -#include "net_client.h" -#include "p_local.h" -#include "v_video.h" -#include "w_main.h" -#include "am_map.h" - -#include "hexen_icon.c" - -// MACROS ------------------------------------------------------------------ - -#define MAXWADFILES 20 -#define CT_KEY_BLUE 'b' -#define CT_KEY_RED 'r' -#define CT_KEY_YELLOW 'y' -#define CT_KEY_GREEN 'g' -#define CT_KEY_PLAYER5 'j' // Jade -#define CT_KEY_PLAYER6 'w' // White -#define CT_KEY_PLAYER7 'h' // Hazel -#define CT_KEY_PLAYER8 'p' // Purple -#define CT_KEY_ALL 't' - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -void R_ExecuteSetViewSize(void); -void D_ConnectNetGame(void); -void D_CheckNetGame(void); -boolean F_Responder(event_t * ev); -void I_StartupKeyboard(void); -void I_StartupJoystick(void); -void I_ShutdownKeyboard(void); -void S_InitScript(void); - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -void H2_AdvanceDemo(void); -void H2_PageTicker(void); - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void DrawMessage(void); -static void PageDrawer(void); -static void HandleArgs(void); -static void CheckRecordFrom(void); -static void DrawAndBlit(void); -static void CreateSavePath(void); -static void WarpCheck(void); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -GameMode_t gamemode; -GameVersion_t gameversion = exe_hexen_1_1; -static const char *gamedescription; -char *iwadfile; -static char demolumpname[9]; // Demo lump to start playing. -boolean nomonsters; // checkparm of -nomonsters -boolean respawnparm; // checkparm of -respawn -boolean randomclass; // checkparm of -randclass -boolean debugmode; // checkparm of -debug -boolean ravpic; // checkparm of -ravpic -boolean cdrom = false; // true if cd-rom mode active -boolean cmdfrag; // true if a CMD_FRAG packet should be sent out -boolean artiskip; // whether shift-enter skips an artifact -int maxzone = 0x800000; // Maximum allocated for zone heap (8meg default) -skill_t startskill; -int startepisode; -int startmap; -boolean autostart; -boolean advancedemo; -FILE *debugfile; -int UpdateState; -int maxplayers = MAXPLAYERS; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int WarpMap; -static int demosequence; -static int pagetic; -static const char *pagename; -static char *SavePathConfig; - -// CODE -------------------------------------------------------------------- - - -static const char * const chat_macro_defaults[10] = -{ - HUSTR_CHATMACRO0, - HUSTR_CHATMACRO1, - HUSTR_CHATMACRO2, - HUSTR_CHATMACRO3, - HUSTR_CHATMACRO4, - HUSTR_CHATMACRO5, - HUSTR_CHATMACRO6, - HUSTR_CHATMACRO7, - HUSTR_CHATMACRO8, - HUSTR_CHATMACRO9, -}; - - -void D_BindVariables(void) -{ - int i; - - M_ApplyPlatformDefaults(); - - I_BindInputVariables(); - I_BindVideoVariables(); - I_BindJoystickVariables(); - I_BindSoundVariables(); - - M_BindBaseControls(); - M_BindMapControls(); - M_BindMenuControls(); - M_BindWeaponControls(); - M_BindChatControls(MAXPLAYERS); - M_BindHereticControls(); - M_BindHexenControls(); - - key_multi_msgplayer[0] = CT_KEY_BLUE; - key_multi_msgplayer[1] = CT_KEY_RED; - key_multi_msgplayer[2] = CT_KEY_YELLOW; - key_multi_msgplayer[3] = CT_KEY_GREEN; - key_multi_msgplayer[4] = CT_KEY_PLAYER5; - key_multi_msgplayer[5] = CT_KEY_PLAYER6; - key_multi_msgplayer[6] = CT_KEY_PLAYER7; - key_multi_msgplayer[7] = CT_KEY_PLAYER8; - - NET_BindVariables(); - - M_BindIntVariable("graphical_startup", &graphical_startup); - M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); - M_BindIntVariable("sfx_volume", &snd_MaxVolume); - M_BindIntVariable("music_volume", &snd_MusicVolume); - M_BindIntVariable("messageson", &messageson); - M_BindIntVariable("screenblocks", &screenblocks); - M_BindIntVariable("snd_channels", &snd_Channels); - M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); - M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); - - M_BindStringVariable("savedir", &SavePathConfig); - - // Multiplayer chat macros - - for (i=0; i<10; ++i) - { - char buf[12]; - - chat_macros[i] = M_StringDuplicate(chat_macro_defaults[i]); - M_snprintf(buf, sizeof(buf), "chatmacro%i", i); - M_BindStringVariable(buf, &chat_macros[i]); - } -} - -// Set the default directory where hub savegames are saved. - -static void D_SetDefaultSavePath(void) -{ - SavePath = M_GetSaveGameDir("hexen.wad"); - - if (!strcmp(SavePath, "")) - { - // only get hexen.cfg path if one is not already found - - if (SavePathConfig == NULL || !strcmp(SavePathConfig, "")) - { - // If we are not using a savegame path (probably because we are on - // Windows and not using a config dir), behave like Vanilla Hexen - // and use hexndata/: - - SavePath = malloc(10); - M_snprintf(SavePath, 10, "hexndata%c", DIR_SEPARATOR); - } - else - { - SavePath = M_StringDuplicate(SavePathConfig); - } - } - - // only set hexen.cfg path if using default handling - - if (!M_ParmExists("-savedir") && !M_ParmExists("-cdrom")) - { - SavePathConfig = SavePath; - } -} - -// The Mac version of the Hexen IWAD is different to the "normal" DOS -// version - it doesn't include lumps used by the DOS DMX library. -// This means that we can't do GUS or OPL emulation and need to apply -// a workaround. -static void AdjustForMacIWAD(void) -{ - boolean adjust_music = false; - - switch (snd_musicdevice) - { - case SNDDEVICE_ADLIB: - case SNDDEVICE_SB: - adjust_music = W_CheckNumForName("GENMIDI") < 0; - break; - - case SNDDEVICE_GUS: - adjust_music = W_CheckNumForName("DMXGUS") < 0; - break; - - default: - break; - } - - if (adjust_music) - { - printf("** Note: You appear to be using the Mac version of the Hexen\n" - "** IWAD file. This is missing the lumps required for OPL or\n" - "** GUS emulation. Your music configuration is being adjusted\n" - "** to a different setting that won't cause the game to " - "crash.\n"); - snd_musicdevice = SNDDEVICE_GENMIDI; - } -} - -// -// D_GrabMouseCallback -// -// Called to determine whether to grab the mouse pointer -// - -static boolean D_GrabMouseCallback(void) -{ - // when menu is active or game is paused, release the mouse - - if (MenuActive || paused) - return false; - - // only grab mouse when playing levels (but not demos) - - return (gamestate == GS_LEVEL) && !advancedemo && !demoplayback; -} - -// Message displayed when quitting Hexen - -static void D_HexenQuitMessage(void) -{ - printf("\nHexen: Beyond Heretic\n"); -} - -static void D_AddFile(char *filename) -{ - printf(" adding %s\n", filename); - - W_AddFile(filename); -} - -// Find out what version of Hexen is playing. - -void D_IdentifyVersion(void) -{ - // The Hexen Shareware, ne 4 Level Demo Version, is missing the SKY1 lump - // and uses the SKY2 lump instead. Let's use this fact and the missing - // levels from MAP05 onward to identify it and set gamemode accordingly. - - if (W_CheckNumForName("SKY1") == -1 && - W_CheckNumForName("MAP05") == -1 ) - { - gamemode = shareware; - maxplayers = 4; - } - - // The v1.0 IWAD file is missing a bunch of lumps that can cause the game - // to crash, so we exit with an error if the user tries to play with it. - // But we provide an override command line flag if they really want to - // do it. - - //! - // If provided, the check for the v1.0 IWAD file is disabled, even though - // it will almost certainly cause the game to crash. - // - // @category compat - // - - if (!M_ParmExists("-v10override") - && gamemode != shareware && W_CheckNumForName("CLUS1MSG") < 0) - { - I_Error( - "You are trying to use the Hexen v1.0 IWAD. This isn't\n" - "supported by " PACKAGE_NAME ". Please upgrade to the v1.1\n" - "IWAD file. See here for more information:\n" - " https://www.doomworld.com/classicdoom/info/patches.php"); - } -} - -// Set the gamedescription string. - -void D_SetGameDescription(void) -{ -/* - NB: The 4 Level Demo Version actually prints a four-lined banner - (and indeed waits for a keypress): - - Hexen: Beyond Heretic - - 4 Level Demo Version - Press any key to continue. -*/ - - if (gamemode == shareware) - { - gamedescription = "Hexen: 4 Level Demo Version"; - } - else - { - gamedescription = "Hexen"; - } -} - -static const struct -{ - const char *description; - const char *cmdline; - GameVersion_t version; -} gameversions[] = { - {"Hexen 1.1", "1.1", exe_hexen_1_1}, - {"Hexen 1.1 (alt)", "1.1r2", exe_hexen_1_1r2}, - { NULL, NULL, 0}, -}; - -// Initialize the game version - -static void InitGameVersion(void) -{ - int p; - - //! - // @arg - // @category compat - // - // Emulate a specific version of Hexen. - // Valid values are "1.1" and "1.1r2". - // - - p = M_CheckParmWithArgs("-gameversion", 1); - - if (p) - { - int i; - for (i=0; gameversions[i].description != NULL; ++i) - { - if (!strcmp(myargv[p+1], gameversions[i].cmdline)) - { - gameversion = gameversions[i].version; - break; - } - } - - if (gameversions[i].description == NULL) - { - printf("Supported game versions:\n"); - - for (i=0; gameversions[i].description != NULL; ++i) - { - printf("\t%s (%s)\n", gameversions[i].cmdline, - gameversions[i].description); - } - - I_Error("Unknown game version '%s'", myargv[p+1]); - } - } - else - { - // Determine automatically - - gameversion = exe_hexen_1_1; - } -} - -void PrintGameVersion(void) -{ - int i; - - for (i=0; gameversions[i].description != NULL; ++i) - { - if (gameversions[i].version == gameversion) - { - printf("Emulating the behavior of the " - "'%s' executable.\n", gameversions[i].description); - break; - } - } -} - -//========================================================================== -// -// H2_Main -// -//========================================================================== -void InitMapMusicInfo(void); - -void D_DoomMain(void) -{ - GameMission_t gamemission; - int p; - - I_AtExit(D_HexenQuitMessage, false); - startepisode = 1; - autostart = false; - startskill = sk_medium; - startmap = 1; - gamemode = commercial; - - I_PrintBanner(PACKAGE_STRING); - - // Initialize subsystems - - ST_Message("V_Init: allocate screens.\n"); - V_Init(); - - // Load defaults before initing other systems - ST_Message("M_LoadDefaults: Load system defaults.\n"); - D_BindVariables(); - -#ifdef _WIN32 - - //! - // @category obscure - // @platform windows - // @vanilla - // - // Save configuration data and savegames in c:\hexndata, - // allowing play from CD. - // - - cdrom = M_ParmExists("-cdrom"); -#endif - - if (cdrom) - { - M_SetConfigDir("c:\\hexndata\\"); - } - else - { - M_SetConfigDir(NULL); - } - - M_SetConfigFilenames("hexen.cfg", PROGRAM_PREFIX "hexen.cfg"); - M_LoadDefaults(); - - D_SetDefaultSavePath(); - - I_AtExit(M_SaveDefaults, false); - - // Now that the savedir is loaded, make sure it exists - CreateSavePath(); - - ST_Message("Z_Init: Init zone memory allocation daemon.\n"); - Z_Init(); - - // haleyjd: removed WATCOMC - - ST_Message("W_Init: Init WADfiles.\n"); - - iwadfile = D_FindIWAD(IWAD_MASK_HEXEN, &gamemission); - - if (iwadfile == NULL) - { - I_Error("Game mode indeterminate. No IWAD was found. Try specifying\n" - "one with the '-iwad' command line parameter."); - } - - D_AddFile(iwadfile); - W_CheckCorrectIWAD(hexen); - D_IdentifyVersion(); - InitGameVersion(); - D_SetGameDescription(); - AdjustForMacIWAD(); - - //! - // @category mod - // - // Disable auto-loading of .wad files. - // - if (!M_ParmExists("-noautoload")) - { - char *autoload_dir; - autoload_dir = M_GetAutoloadDir("hexen.wad"); - if (autoload_dir != NULL) - { - // TODO? DEH_AutoLoadPatches(autoload_dir); - W_AutoLoadWADs(autoload_dir); - free(autoload_dir); - } - } - - HandleArgs(); - - // Generate the WAD hash table. Speed things up a bit. - W_GenerateHashTable(); - - I_PrintStartupBanner(gamedescription); - - ST_Message("MN_Init: Init menu system.\n"); - MN_Init(); - - ST_Message("CT_Init: Init chat mode data.\n"); - CT_Init(); - - InitMapMusicInfo(); // Init music fields in mapinfo - - ST_Message("S_InitScript\n"); - S_InitScript(); - - ST_Message("SN_InitSequenceScript: Registering sound sequences.\n"); - SN_InitSequenceScript(); - ST_Message("I_Init: Setting up machine state.\n"); - I_CheckIsScreensaver(); - I_InitTimer(); - I_InitJoystick(); - I_InitSound(hexen); - I_InitMusic(); - - ST_Message("NET_Init: Init networking subsystem.\n"); - NET_Init(); - D_ConnectNetGame(); - - S_Init(); - S_Start(); - - ST_Message("ST_Init: Init startup screen.\n"); - ST_Init(); - - // Show version message now, so it's visible during R_Init() - ST_Message("R_Init: Init Hexen refresh daemon"); - R_Init(); - ST_Message("\n"); - - //if (M_CheckParm("-net")) - // ST_NetProgress(); // Console player found - - ST_Message("P_Init: Init Playloop state.\n"); - P_Init(); - - // Check for command line warping. Follows P_Init() because the - // MAPINFO.TXT script must be already processed. - WarpCheck(); - - ST_Message("D_CheckNetGame: Checking network game status.\n"); - D_CheckNetGame(); - - PrintGameVersion(); - - ST_Message("SB_Init: Loading patches.\n"); - SB_Init(); - - ST_Done(); - - if (autostart) - { - ST_Message("Warp to Map %d (\"%s\":%d), Skill %d\n", - WarpMap, P_GetMapName(startmap), startmap, startskill + 1); - } - - CheckRecordFrom(); - - //! - // @arg - // @category demo - // @vanilla - // - // Record a demo named x.lmp. - // - - p = M_CheckParm("-record"); - if (p && p < myargc - 1) - { - G_RecordDemo(startskill, 1, startepisode, startmap, myargv[p + 1]); - H2_GameLoop(); // Never returns - } - - p = M_CheckParmWithArgs("-playdemo", 1); - if (p) - { - singledemo = true; // Quit after one demo - G_DeferedPlayDemo(demolumpname); - H2_GameLoop(); // Never returns - } - - p = M_CheckParmWithArgs("-timedemo", 1); - if (p) - { - G_TimeDemo(demolumpname); - H2_GameLoop(); // Never returns - } - - //! - // @category game - // @arg - // @vanilla - // - // Load the game in savegame slot s. - // - - p = M_CheckParmWithArgs("-loadgame", 1); - if (p) - { - G_LoadGame(atoi(myargv[p + 1])); - } - - if (gameaction != ga_loadgame) - { - UpdateState |= I_FULLSCRN; - BorderNeedRefresh = true; - if (autostart || netgame) - { - G_StartNewInit(); - G_InitNew(startskill, startepisode, startmap); - } - else - { - H2_StartTitle(); - } - } - H2_GameLoop(); // Never returns -} - -//========================================================================== -// -// HandleArgs -// -//========================================================================== - -static void HandleArgs(void) -{ - int p; - - //! - // @category game - // @vanilla - // - // Disable monsters. - // - - nomonsters = M_ParmExists("-nomonsters"); - - //! - // @category game - // @vanilla - // - // Monsters respawn after being killed. - // - - respawnparm = M_ParmExists("-respawn"); - - //! - // @vanilla - // @category net - // - // In deathmatch mode, change a player's class each time the - // player respawns. - // - - randomclass = M_ParmExists("-randclass"); - - //! - // @vanilla - // - // Take screenshots when F1 is pressed. - // - - ravpic = M_ParmExists("-ravpic"); - - //! - // @category obscure - // @vanilla - // - // Don't allow artifacts to be used when the run key is held down. - // - - artiskip = M_ParmExists("-artiskip"); - - debugmode = M_ParmExists("-debug"); - - //! - // @vanilla - // @category net - // - // Start a deathmatch game. - // - - deathmatch = M_ParmExists("-deathmatch"); - - // currently broken or unused: - cmdfrag = M_ParmExists("-cmdfrag"); - - // Check WAD file command line options - W_ParseCommandLine(); - - //! - // @category obscure - // @vanilla - // @arg - // - // Development option to specify path to level scripts. - // - - p = M_CheckParmWithArgs("-scripts", 1); - - if (p) - { - sc_FileScripts = true; - sc_ScriptsDir = myargv[p+1]; - } - - //! - // @category game - // @arg - // @vanilla - // - // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of - // 0 disables all monsters. - // - - p = M_CheckParmWithArgs("-skill", 1); - - if (p) - { - startskill = myargv[p+1][0] - '1'; - autostart = true; - } - - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp. - // - - p = M_CheckParmWithArgs("-playdemo", 1); - - if (!p) - { - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp, determining the framerate - // of the screen. - // - - p = M_CheckParmWithArgs("-timedemo", 1); - } - - if (p) - { - char *uc_filename; - char file[256]; - - M_StringCopy(file, myargv[p+1], sizeof(file)); - - // With Vanilla Hexen you have to specify the file without - // extension, but make that optional. - uc_filename = strdup(myargv[p + 1]); - M_ForceUppercase(uc_filename); - - if (!M_StringEndsWith(uc_filename, ".LMP")) - { - M_StringConcat(file, ".lmp", sizeof(file)); - } - - free(uc_filename); - - if (W_AddFile(file) != NULL) - { - M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, - sizeof(demolumpname)); - } - else - { - // The file failed to load, but copy the original arg as a - // demo name to make tricks like -playdemo demo1 possible. - M_StringCopy(demolumpname, myargv[p+1], sizeof(demolumpname)); - } - - ST_Message("Playing demo %s.\n", myargv[p+1]); - } - - //! - // @category demo - // - // Record or playback a demo without automatically quitting - // after either level exit or player respawn. - // - - demoextend = M_ParmExists("-demoextend"); - - if (M_ParmExists("-testcontrols")) - { - autostart = true; - testcontrols = true; - } -} - -//========================================================================== -// -// WarpCheck -// -//========================================================================== - -static void WarpCheck(void) -{ - int p; - int map; - - //! - // @category game - // @arg x - // @vanilla - // - // Start a game immediately, warping to MAPx. - // - - p = M_CheckParm("-warp"); - if (p && p < myargc - 1) - { - WarpMap = atoi(myargv[p + 1]); - map = P_TranslateMap(WarpMap); - if (map == -1) - { // Couldn't find real map number - startmap = 1; - ST_Message("-WARP: Invalid map number.\n"); - } - else - { // Found a valid startmap - startmap = map; - autostart = true; - } - } - else - { - WarpMap = 1; - startmap = P_TranslateMap(1); - if (startmap == -1) - { - startmap = 1; - } - } -} - -//========================================================================== -// -// H2_GameLoop -// -//========================================================================== - -void H2_GameLoop(void) -{ - if (M_CheckParm("-debugfile")) - { - char filename[20]; - M_snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer); - debugfile = M_fopen(filename, "w"); - } - I_SetWindowTitle(gamedescription); - I_GraphicsCheckCommandLine(); - I_SetGrabMouseCallback(D_GrabMouseCallback); - I_RegisterWindowIcon(hexen_icon_data, hexen_icon_w, hexen_icon_h); - I_InitGraphics(); - - while (1) - { - // Frame syncronous IO operations - I_StartFrame(); - - // Process one or more tics - // Will run at least one tic - TryRunTics(); - - // Move positional sounds - S_UpdateSounds(players[displayplayer].mo); - - DrawAndBlit(); - } -} - -//========================================================================== -// -// H2_ProcessEvents -// -// Send all the events of the given timestamp down the responder chain. -// -//========================================================================== - -void H2_ProcessEvents(void) -{ - event_t *ev; - - for (;;) - { - ev = D_PopEvent(); - - if (ev == NULL) - { - break; - } - - if (F_Responder(ev)) - { - continue; - } - if (MN_Responder(ev)) - { - continue; - } - G_Responder(ev); - } -} - -//========================================================================== -// -// DrawAndBlit -// -//========================================================================== - -static void DrawAndBlit(void) -{ - // Change the view size if needed - if (setsizeneeded) - { - R_ExecuteSetViewSize(); - } - - // Do buffered drawing - switch (gamestate) - { - case GS_LEVEL: - if (!gametic) - { - break; - } - if (automapactive) - { - AM_Drawer(); - } - else - { - R_RenderPlayerView(&players[displayplayer]); - } - CT_Drawer(); - UpdateState |= I_FULLVIEW; - SB_Drawer(); - break; - case GS_INTERMISSION: - IN_Drawer(); - break; - case GS_FINALE: - F_Drawer(); - break; - case GS_DEMOSCREEN: - PageDrawer(); - break; - } - - if (testcontrols) - { - V_DrawMouseSpeedBox(testcontrols_mousespeed); - } - - if (paused && !MenuActive && !askforquit) - { - if (!netgame) - { - V_DrawPatch(160, viewwindowy + 5, W_CacheLumpName("PAUSED", - PU_CACHE)); - } - else - { - V_DrawPatch(160, 70, W_CacheLumpName("PAUSED", PU_CACHE)); - } - } - - // Draw current message - DrawMessage(); - - // Draw Menu - MN_Drawer(); - - // Send out any new accumulation - NetUpdate(); - - // Flush buffered stuff to screen - I_FinishUpdate(); -} - -//========================================================================== -// -// DrawMessage -// -//========================================================================== - -static void DrawMessage(void) -{ - player_t *player; - - player = &players[consoleplayer]; - if (player->messageTics <= 0) - { // No message - return; - } - if (player->yellowMessage) - { - MN_DrTextAYellow(player->message, - 160 - MN_TextAWidth(player->message) / 2, 1); - } - else - { - MN_DrTextA(player->message, 160 - MN_TextAWidth(player->message) / 2, - 1); - } -} - -//========================================================================== -// -// H2_PageTicker -// -//========================================================================== - -void H2_PageTicker(void) -{ - if (--pagetic < 0) - { - H2_AdvanceDemo(); - } -} - -//========================================================================== -// -// PageDrawer -// -//========================================================================== - -static void PageDrawer(void) -{ - V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE)); - if (demosequence == 1) - { - V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE)); - } - UpdateState |= I_FULLSCRN; -} - -//========================================================================== -// -// H2_AdvanceDemo -// -// Called after each demo or intro demosequence finishes. -// -//========================================================================== - -void H2_AdvanceDemo(void) -{ - advancedemo = true; -} - -//========================================================================== -// -// H2_DoAdvanceDemo -// -//========================================================================== - -void H2_DoAdvanceDemo(void) -{ - players[consoleplayer].playerstate = PST_LIVE; // don't reborn - advancedemo = false; - usergame = false; // can't save/end game here - paused = false; - gameaction = ga_nothing; - demosequence = (demosequence + 1) % 7; - switch (demosequence) - { - case 0: - pagetic = 280; - gamestate = GS_DEMOSCREEN; - pagename = "TITLE"; - S_StartSongName("hexen", true); - break; - case 1: - pagetic = 210; - gamestate = GS_DEMOSCREEN; - pagename = "TITLE"; - break; - case 2: - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - G_DeferedPlayDemo("demo1"); - break; - case 3: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - pagename = "CREDIT"; - break; - case 4: - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - G_DeferedPlayDemo("demo2"); - break; - case 5: - pagetic = 200; - gamestate = GS_DEMOSCREEN; - pagename = "CREDIT"; - break; - case 6: - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - G_DeferedPlayDemo("demo3"); - break; - } -} - -//========================================================================== -// -// H2_StartTitle -// -//========================================================================== - -void H2_StartTitle(void) -{ - gameaction = ga_nothing; - demosequence = -1; - H2_AdvanceDemo(); -} - -//========================================================================== -// -// CheckRecordFrom -// -// -recordfrom -// -//========================================================================== - -static void CheckRecordFrom(void) -{ - int p; - - //! - // @vanilla - // @category demo - // @arg - // - // Load a game from the given savegame slot and record a demo from - // it. Equivalent to -loadgame -record . - // - p = M_CheckParm("-recordfrom"); - if (!p || p > myargc - 2) - { // Bad args - return; - } - G_LoadGame(atoi(myargv[p + 1])); - G_DoLoadGame(); // Load the gameskill etc info from savegame - G_RecordDemo(gameskill, 1, gameepisode, gamemap, myargv[p + 2]); - - H2_GameLoop(); // Never returns -} - -// haleyjd: removed WATCOMC -/* -void CleanExit(void) -{ - union REGS regs; - - I_ShutdownKeyboard(); - regs.x.eax = 0x3; - int386(0x10, ®s, ®s); - printf("Exited from HEXEN: Beyond Heretic.\n"); - exit(1); -} -*/ - -//========================================================================== -// -// CreateSavePath -// -//========================================================================== - -static void CreateSavePath(void) -{ - M_MakeDirectory(SavePath); -} diff --git a/games/NXDoom/src/hexen/h2def.h b/games/NXDoom/src/hexen/h2def.h deleted file mode 100644 index 2bfdfb513c4..00000000000 --- a/games/NXDoom/src/hexen/h2def.h +++ /dev/null @@ -1,1121 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __H2DEF__ -#define __H2DEF__ -#include -#include -#include -//#include - -#include "st_start.h" -// haleyjd: removed WATCOMC - -// ticcmd: - -#include "d_ticcmd.h" - -// events - -#include "d_event.h" - -// gamemode/mission - -#include "d_mode.h" - -// for fixed_t: - -#include "m_fixed.h" - -// angle definitions: - -#include "tables.h" - -#include "d_loop.h" -#include "net_defs.h" - -#define HEXEN_VERSION 110 -#define HEXEN_VERSION_TEXT "v1.1" - -// if rangecheck is undefined, most parameter validation debugging code -// will not be compiled -#ifndef NORANGECHECKING -#define RANGECHECK -#endif - -// Past distributions -//#ifndef VER_ID -//#define VER_ID "DVL" -//#endif -//#define HEXEN_VERSIONTEXT "ID V1.2" -//#define HEXEN_VERSIONTEXT "RETAIL STORE BETA" // 9/26/95 -//#define HEXEN_VERSIONTEXT "DVL BETA 10 05 95" // Used for GT for testing -//#define HEXEN_VERSIONTEXT "DVL BETA 10 07 95" // Just an update for Romero -//#define HEXEN_VERSIONTEXT "FINAL 1.0 (10 13 95)" // Just an update for Romero -//#ifdef RANGECHECK -//#define HEXEN_VERSIONTEXT "Version 1.1 +R "__DATE__" ("VER_ID")" -//#else -//#define HEXEN_VERSIONTEXT "Version 1.1 "__DATE__" ("VER_ID")" -//#endif -#define HEXEN_VERSIONTEXT ((gamemode == shareware) ? \ - "DEMO 10 16 95" : \ - (gameversion != exe_hexen_1_1r2) ? \ - "VERSION 1.1 MAR 12 1996 (CBI)" : \ - "VERSION 1.1 MAR 22 1996 (BCP)") - -// all exterior data is defined here -#include "xddefs.h" - -// all important printed strings -#include "textdefs.h" - -// header generated by multigen utility -#include "info.h" - -/* -=============================================================================== - - GLOBAL TYPES - -=============================================================================== -*/ - -//#define NUMARTIFCTS 28 -#define MAXPLAYERS 8 - -#define BT_ATTACK 1 -#define BT_USE 2 -#define BT_CHANGE 4 // if true, the next 3 bits hold weapon num -#define BT_WEAPONMASK (8+16+32) -#define BT_WEAPONSHIFT 3 - -#define BT_SPECIAL 128 // game events, not really buttons -#define BTS_SAVEMASK (4+8+16) -#define BTS_SAVESHIFT 2 -#define BT_SPECIALMASK 3 -#define BTS_PAUSE 1 // pause the game -#define BTS_SAVEGAME 2 // save the game at each console -// savegame slot numbers occupy the second byte of buttons - -// The top 3 bits of the artifact field in the ticcmd_t struct are used -// as additional flags -#define AFLAG_MASK 0x3F -#define AFLAG_SUICIDE 0x40 -#define AFLAG_JUMP 0x80 - -typedef enum -{ - GS_LEVEL, - GS_INTERMISSION, - GS_FINALE, - GS_DEMOSCREEN -} gamestate_t; - -typedef enum -{ - ga_nothing, - ga_loadlevel, - ga_initnew, - ga_newgame, - ga_loadgame, - ga_savegame, - ga_playdemo, - ga_completed, - ga_leavemap, - ga_singlereborn, - ga_victory, - ga_worlddone, - ga_screenshot -} gameaction_t; - -typedef enum -{ - wipe_0, - wipe_1, - wipe_2, - wipe_3, - wipe_4, - NUMWIPES, - wipe_random -} wipe_t; - -/* -=============================================================================== - - MAPOBJ DATA - -=============================================================================== -*/ - - -struct thinker_s; - - -// think_t is a function pointer to a routine to handle an actor -typedef void (*think_t)(struct thinker_s *); - -typedef struct thinker_s -{ - struct thinker_s *prev, *next; - think_t function; -} thinker_t; - -struct player_s; - -typedef union -{ - intptr_t i; - struct mobj_s *m; - struct player_s *p; -} specialval_t; - -typedef struct mobj_s -{ - thinker_t thinker; // thinker node - -// info for drawing - fixed_t x, y, z; - struct mobj_s *snext, *sprev; // links in sector (if needed) - angle_t angle; - spritenum_t sprite; // used to find patch_t and flip value - int frame; // might be ord with FF_FULLBRIGHT - -// interaction info - struct mobj_s *bnext, *bprev; // links in blocks (if needed) - struct subsector_s *subsector; - fixed_t floorz, ceilingz; // closest together of contacted secs - fixed_t floorpic; // contacted sec floorpic - fixed_t radius, height; // for movement checking - fixed_t momx, momy, momz; // momentums - int validcount; // if == validcount, already checked - mobjtype_t type; - mobjinfo_t *info; // &mobjinfo[mobj->type] - int tics; // state tic counter - state_t *state; - int damage; // For missiles - int flags; - int flags2; // Heretic flags - specialval_t special1; // Special info - specialval_t special2; // Special info - int health; - int movedir; // 0-7 - int movecount; // when 0, select a new dir - struct mobj_s *target; // thing being chased/attacked (or NULL) - // also the originator for missiles - int reactiontime; // if non 0, don't attack yet - // used by player to freeze a bit after - // teleporting - int threshold; // if > 0, the target will be chased - // no matter what (even if shot) - struct player_s *player; // only valid if type == MT_PLAYER - int lastlook; // player number last looked for - fixed_t floorclip; // value to use for floor clipping - int archiveNum; // Identity during archive - short tid; // thing identifier - byte special; // special - byte args[5]; // special arguments -} mobj_t; - -// each sector has a degenmobj_t in it's center for sound origin purposes -typedef struct -{ - thinker_t thinker; // not used for anything - fixed_t x, y, z; -} degenmobj_t; - -// -// frame flags -// -#define FF_FULLBRIGHT 0x8000 // flag in thing->frame -#define FF_FRAMEMASK 0x7fff - -// --- mobj.flags --- - -#define MF_SPECIAL 1 // call P_SpecialThing when touched -#define MF_SOLID 2 -#define MF_SHOOTABLE 4 -#define MF_NOSECTOR 8 // don't use the sector links - // (invisible but touchable) -#define MF_NOBLOCKMAP 16 // don't use the blocklinks - // (inert but displayable) -#define MF_AMBUSH 32 -#define MF_JUSTHIT 64 // try to attack right back -#define MF_JUSTATTACKED 128 // take at least one step before attacking -#define MF_SPAWNCEILING 256 // hang from ceiling instead of floor -#define MF_NOGRAVITY 512 // don't apply gravity every tic - -// movement flags -#define MF_DROPOFF 0x400 // allow jumps from high places -#define MF_PICKUP 0x800 // for players to pick up items -#define MF_NOCLIP 0x1000 // player cheat -#define MF_SLIDE 0x2000 // keep info about sliding along walls -#define MF_FLOAT 0x4000 // allow moves to any height, no gravity -#define MF_TELEPORT 0x8000 // don't cross lines or look at heights -#define MF_MISSILE 0x10000 // don't hit same species, explode on block - -#define MF_ALTSHADOW 0x20000 // alternate translucent draw -#define MF_SHADOW 0x40000 // use translucent draw (shadow demons / invis) -#define MF_NOBLOOD 0x80000 // don't bleed when shot (use puff) -#define MF_CORPSE 0x100000 // don't stop moving halfway off a step -#define MF_INFLOAT 0x200000 // floating to a height for a move, don't - // auto float to target's height - -#define MF_COUNTKILL 0x400000 // count towards intermission kill total -#define MF_ICECORPSE 0x800000 // a frozen corpse (for blasting) - -#define MF_SKULLFLY 0x1000000 // skull in flight -#define MF_NOTDMATCH 0x2000000 // don't spawn in death match (key cards) - -//#define MF_TRANSLATION 0xc000000 // if 0x4 0x8 or 0xc, use a translation -#define MF_TRANSLATION 0x1c000000 // use a translation table (>>MF_TRANSHIFT) -#define MF_TRANSSHIFT 26 // table for player colormaps - - -// --- mobj.flags2 --- - -#define MF2_LOGRAV 0x00000001 // alternate gravity setting -#define MF2_WINDTHRUST 0x00000002 // gets pushed around by the wind - // specials -#define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor -#define MF2_BLASTED 0x00000008 // missile will pass through ghosts -#define MF2_FLY 0x00000010 // fly mode is active -#define MF2_FLOORCLIP 0x00000020 // if feet are allowed to be clipped -#define MF2_SPAWNFLOAT 0x00000040 // spawn random float z -#define MF2_NOTELEPORT 0x00000080 // does not teleport -#define MF2_RIP 0x00000100 // missile rips through solid - // targets -#define MF2_PUSHABLE 0x00000200 // can be pushed by other moving - // mobjs -#define MF2_SLIDE 0x00000400 // slides against walls -#define MF2_ONMOBJ 0x00000800 // mobj is resting on top of another - // mobj -#define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, - // this flag will allow the mobj to - // pass over/under other mobjs. -#define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs -#define MF2_DROPPED 0x00004000 // dropped by a demon -#define MF2_BOSS 0x00008000 // mobj is a major boss -#define MF2_FIREDAMAGE 0x00010000 // does fire damage -#define MF2_NODMGTHRUST 0x00020000 // does not thrust target when - // damaging -#define MF2_TELESTOMP 0x00040000 // mobj can stomp another -#define MF2_FLOATBOB 0x00080000 // use float bobbing z movement -#define MF2_DONTDRAW 0x00100000 // don't generate a vissprite -#define MF2_IMPACT 0x00200000 // an MF_MISSILE mobj can activate - // SPAC_IMPACT -#define MF2_PUSHWALL 0x00400000 // mobj can push walls -#define MF2_MCROSS 0x00800000 // can activate monster cross lines -#define MF2_PCROSS 0x01000000 // can activate projectile cross lines -#define MF2_CANTLEAVEFLOORPIC 0x02000000 // stay within a certain floor type -#define MF2_NONSHOOTABLE 0x04000000 // mobj is totally non-shootable, - // but still considered solid -#define MF2_INVULNERABLE 0x08000000 // mobj is invulnerable -#define MF2_DORMANT 0x10000000 // thing is dormant -#define MF2_ICEDAMAGE 0x20000000 // does ice damage -#define MF2_SEEKERMISSILE 0x40000000 // is a seeker (for reflection) -#define MF2_REFLECTIVE 0x80000000 // reflects missiles - -//============================================================================= - -// ===== Player Class Types ===== -typedef enum -{ - PCLASS_FIGHTER, - PCLASS_CLERIC, - PCLASS_MAGE, - PCLASS_PIG, - NUMCLASSES -} pclass_t; - -typedef enum -{ - PST_LIVE, // playing - PST_DEAD, // dead on the ground - PST_REBORN // ready to restart -} playerstate_t; - -// psprites are scaled shapes directly on the view screen -// coordinates are given for a 320*200 view screen -typedef enum -{ - ps_weapon, - ps_flash, - NUMPSPRITES -} psprnum_t; - -typedef struct pspdef_s -{ - state_t *state; // a NULL state means not active - int tics; - fixed_t sx, sy; -} pspdef_t; - -/* Old Heretic key type -typedef enum -{ - key_yellow, - key_green, - key_blue, - NUM_KEY_TYPES -} keytype_t; -*/ - -typedef enum -{ - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_A, - KEY_B, - NUM_KEY_TYPES -} keytype_t; - -typedef enum -{ - ARMOR_ARMOR, - ARMOR_SHIELD, - ARMOR_HELMET, - ARMOR_AMULET, - NUMARMOR -} armortype_t; - -typedef enum -{ - WP_FIRST, - WP_SECOND, - WP_THIRD, - WP_FOURTH, - NUMWEAPONS, - WP_NOCHANGE -} weapontype_t; - -typedef enum -{ - MANA_1, - MANA_2, - NUMMANA, - MANA_BOTH, - MANA_NONE -} manatype_t; - -#define MAX_MANA 200 - -#define WPIECE1 1 -#define WPIECE2 2 -#define WPIECE3 4 - -typedef struct -{ - manatype_t mana; - int upstate; - int downstate; - int readystate; - int atkstate; - int holdatkstate; - int flashstate; -} weaponinfo_t; - -extern weaponinfo_t WeaponInfo[NUMWEAPONS][NUMCLASSES]; - -typedef enum -{ - arti_none, - arti_invulnerability, - arti_health, - arti_superhealth, - arti_healingradius, - arti_summon, - arti_torch, - arti_egg, - arti_fly, - arti_blastradius, - arti_poisonbag, - arti_teleportother, - arti_speed, - arti_boostmana, - arti_boostarmor, - arti_teleport, - // Puzzle artifacts - arti_firstpuzzitem, - arti_puzzskull = arti_firstpuzzitem, - arti_puzzgembig, - arti_puzzgemred, - arti_puzzgemgreen1, - arti_puzzgemgreen2, - arti_puzzgemblue1, - arti_puzzgemblue2, - arti_puzzbook1, - arti_puzzbook2, - arti_puzzskull2, - arti_puzzfweapon, - arti_puzzcweapon, - arti_puzzmweapon, - arti_puzzgear1, - arti_puzzgear2, - arti_puzzgear3, - arti_puzzgear4, - NUMARTIFACTS -} artitype_t; - -typedef enum -{ - pw_None, - pw_invulnerability, - pw_allmap, - pw_infrared, - pw_flight, - pw_shield, - pw_health2, - pw_speed, - pw_minotaur, - NUMPOWERS -} powertype_t; - -#define INVULNTICS (30*35) -#define INVISTICS (60*35) -#define INFRATICS (120*35) -#define IRONTICS (60*35) -#define WPNLEV2TICS (40*35) -#define FLIGHTTICS (60*35) -#define SPEEDTICS (45*35) -#define MORPHTICS (40*35) -#define MAULATORTICS (25*35) - -#define MESSAGETICS (4*35) -#define BLINKTHRESHOLD (4*35) - -#define NUMINVENTORYSLOTS NUMARTIFACTS - -typedef struct -{ - int type; - int count; -} inventory_t; - -/* -================ -= -= player_t -= -================ -*/ - -typedef struct player_s -{ - mobj_t *mo; - playerstate_t playerstate; - ticcmd_t cmd; - - pclass_t class; // player class type - - fixed_t viewz; // focal origin above r.z - fixed_t viewheight; // base height above floor for viewz - fixed_t deltaviewheight; // squat speed - fixed_t bob; // bounded/scaled total momentum - - int flyheight; - int lookdir; - boolean centering; - int health; // only used between levels, mo->health - // is used during levels - int armorpoints[NUMARMOR]; - - inventory_t inventory[NUMINVENTORYSLOTS]; - artitype_t readyArtifact; - int artifactCount; - int inventorySlotNum; - int powers[NUMPOWERS]; - int keys; - int pieces; // Fourth Weapon pieces - signed int frags[MAXPLAYERS]; // kills of other players - weapontype_t readyweapon; - weapontype_t pendingweapon; // wp_nochange if not changing - boolean weaponowned[NUMWEAPONS]; - int mana[NUMMANA]; - int attackdown, usedown; // true if button down last tic - int cheats; // bit flags - - int refire; // refired shots are less accurate - - int killcount, itemcount, secretcount; // for intermission - char message[80]; // hint messages - int messageTics; // counter for showing messages - short ultimateMessage; - short yellowMessage; - int damagecount, bonuscount; // for screen flashing - int poisoncount; // screen flash for poison damage - mobj_t *poisoner; // NULL for non-player mobjs - mobj_t *attacker; // who did damage (NULL for floors) - int extralight; // so gun flashes light up areas - int fixedcolormap; // can be set to REDCOLORMAP, etc - int colormap; // 0-3 for which color to draw player - pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) - int morphTics; // player is a pig if > 0 - unsigned int jumpTics; // delay the next jump for a moment - unsigned int worldTimer; // total time the player's been playing -} player_t; - -#define CF_NOCLIP 1 -#define CF_GODMODE 2 -#define CF_NOMOMENTUM 4 // not really a cheat, just a debug aid - -#define SBARHEIGHT 39 // status bar height at bottom of screen - -void NET_SendFrags(player_t * player); - -/* -=============================================================================== - - GLOBAL VARIABLES - -=============================================================================== -*/ - -#define TELEFOGHEIGHT (32*FRACUNIT) - -extern GameMode_t gamemode; -extern GameVersion_t gameversion; - -extern gameaction_t gameaction; - -extern boolean paused; - -extern boolean DevMaps; // true = map development mode -extern char *DevMapsDir; // development maps directory - -extern boolean nomonsters; // checkparm of -nomonsters - -extern boolean respawnparm; // checkparm of -respawn - -extern boolean randomclass; // checkparm of -randclass - -extern boolean debugmode; // checkparm of -debug - -extern boolean usergame; // ok to save / end game - -extern boolean ravpic; // checkparm of -ravpic - -extern boolean altpal; // checkparm to use an alternate palette routine - -extern boolean cdrom; // true if cd-rom mode active ("-cdrom") - -extern boolean viewactive; - -extern boolean deathmatch; // only if started as net death - -extern boolean netgame; // only true if >1 player - -extern boolean cmdfrag; // true if a CMD_FRAG packet should be sent out every - // kill - -extern boolean playeringame[MAXPLAYERS]; -extern pclass_t PlayerClass[MAXPLAYERS]; - -extern int consoleplayer; // player taking events and displaying - -extern int displayplayer; - -extern int viewangleoffset; // ANG90 = left side, ANG270 = right - -extern player_t players[MAXPLAYERS]; - -extern boolean DebugSound; // debug flag for displaying sound info - -extern boolean demorecording; -extern boolean demoplayback; -extern boolean demoextend; // allow demos to persist through exit/respawn -extern int maxzone; // Maximum chunk allocated for zone heap - -// Truncate angleturn in ticcmds to nearest 256. -// Used when recording Vanilla demos in netgames. -extern boolean lowres_turn; - -extern int Sky1Texture; -extern int Sky2Texture; - -extern gamestate_t gamestate; -extern skill_t gameskill; -//extern boolean respawnmonsters; -extern int gameepisode; -extern int gamemap; -extern int prevmap; -extern int levelstarttic; // gametic at level start -extern int leveltime; // tics in game play for par - -extern ticcmd_t *netcmds; - -#define MAXDEATHMATCHSTARTS 16 -extern mapthing_t *deathmatch_p; -extern mapthing_t deathmatchstarts[MAXDEATHMATCHSTARTS]; - -// Position indicator for cooperative net-play reborn -extern int RebornPosition; - -#define MAX_PLAYER_STARTS 8 -extern mapthing_t playerstarts[MAX_PLAYER_STARTS][MAXPLAYERS]; -extern int maxplayers; - -extern int mouseSensitivity; - -extern boolean precache; // if true, load all graphics at level load - -extern byte *screen; // off screen work buffer, from V_video.c - -extern boolean singledemo; // quit after playing a demo from cmdline - -extern int bodyqueslot; -extern skill_t startskill; -extern int startepisode; -extern int startmap; -extern boolean autostart; -extern boolean advancedemo; - -extern boolean testcontrols; -extern int testcontrols_mousespeed; - -extern int vanilla_savegame_limit; -extern int vanilla_demo_limit; - -extern boolean usearti; - - -/* -=============================================================================== - - GLOBAL FUNCTIONS - -=============================================================================== -*/ - -#include "w_wad.h" -#include "z_zone.h" - -//---------- -//BASE LEVEL -//---------- -void H2_Main(void); -// not a globally visible function, just included for source reference -// calls all startup code -// parses command line options -// if not overrided, calls N_AdvanceDemo - -void H2_GameLoop(void); -// not a globally visible function, just included for source reference -// called by H2_Main, never exits -// manages timing and IO -// calls all ?_Responder, ?_Ticker, and ?_Drawer functions -// calls I_GetTime, I_StartFrame, and I_StartTic - -void H2_StartTitle(void); - - -extern boolean artiskip; - - -//--------- -//SYSTEM IO -//--------- -byte *I_AllocLow(int length); -// allocates from low memory under dos, just mallocs under unix - -// haleyjd: was WATCOMC, again preserved for historical interest as in Heretic -#if 0 -extern boolean useexterndriver; - -#define EBT_FIRE 1 -#define EBT_OPENDOOR 2 -#define EBT_SPEED 4 -#define EBT_STRAFE 8 -#define EBT_MAP 0x10 -#define EBT_INVENTORYLEFT 0x20 -#define EBT_INVENTORYRIGHT 0x40 -#define EBT_USEARTIFACT 0x80 -#define EBT_FLYDROP 0x100 -#define EBT_CENTERVIEW 0x200 -#define EBT_PAUSE 0x400 -#define EBT_WEAPONCYCLE 0x800 -#define EBT_JUMP 0x1000 - -typedef struct -{ - short vector; // Interrupt vector - - signed char moveForward; // forward/backward (maxes at 50) - signed char moveSideways; // strafe (maxes at 24) - short angleTurn; // turning speed (640 [slow] 1280 [fast]) - short angleHead; // head angle (+2080 [left] : 0 [center] : -2048 [right]) - signed char pitch; // look up/down (-110 : +90) - signed char flyDirection; // flyheight (+1/-1) - unsigned short buttons; // EBT_* flags -} externdata_t; -#endif - -//---- -//GAME -//---- - - -#define NUMKEYS 256 - - -void G_DeathMatchSpawnPlayer(int playernum); - -void G_InitNew(skill_t skill, int episode, int map); - -void G_DeferedInitNew(skill_t skill, int episode, int map); -// can be called by the startup code or M_Responder -// a normal game starts at map 1, but a warp test can start elsewhere - -void G_DeferredNewGame(skill_t skill); - -void G_DeferedPlayDemo(const char *demo); - -void G_LoadGame(int slot); -// can be called by the startup code or M_Responder -// calls P_SetupLevel or W_EnterWorld -void G_DoLoadGame(void); - -void G_SaveGame(int slot, char *description); -// called by M_Responder - -void H2_ProcessEvents(void); - -void H2_DoAdvanceDemo(void); - -boolean G_CheckDemoStatus(void); - -void G_RecordDemo(skill_t skill, int numplayers, int episode, int map, - const char *name); -// only called by startup code - -void G_PlayDemo(char *name); -void G_TimeDemo(char *name); - -void G_TeleportNewMap(int map, int position); - -void G_Completed(int map, int position); -//void G_ExitLevel (void); -//void G_SecretExitLevel (void); - -void G_StartNewGame(skill_t skill); -void G_StartNewInit(void); - -void G_WorldDone(void); - -void G_BuildTiccmd(ticcmd_t *cmd, int maketic); -void G_Ticker(void); -boolean G_Responder(event_t * ev); - -void G_ScreenShot(void); - - -extern int LeaveMap; -extern boolean gamekeydown[NUMKEYS]; - - -//------- -//SV_SAVE -//------- - -#define HXS_VERSION_TEXT "HXS Ver 2.37" -#define HXS_VERSION_TEXT_LENGTH 16 -#define HXS_DESCRIPTION_LENGTH 24 - -extern char *SavePath; - -void SV_SaveGame(int slot, const char *description); -void SV_SaveMap(boolean savePlayers); -void SV_LoadGame(int slot); -void SV_MapTeleport(int map, int position); -void SV_LoadMap(void); -void SV_InitBaseSlot(void); -void SV_UpdateRebornSlot(void); -void SV_ClearRebornSlot(void); -boolean SV_RebornSlotAvailable(void); -int SV_GetRebornSlot(void); - -//----- -//PLAY -//----- - -extern lumpinfo_t *maplumpinfo; - -void P_Ticker(void); -// called by C_Ticker -// can call G_PlayerExited -// carries out all thinking of monsters and players - -void P_SetupLevel(int episode, int map, int playermask, skill_t skill); -// called by W_Ticker - -void P_Init(void); -// called by startup code - -int P_GetMapCluster(int map); -int P_TranslateMap(int map); -int P_GetMapCDTrack(int map); -int P_GetMapWarpTrans(int map); -int P_GetMapNextMap(int map); -int P_GetMapSky1Texture(int map); -int P_GetMapSky2Texture(int map); -char *P_GetMapName(int map); -fixed_t P_GetMapSky1ScrollDelta(int map); -fixed_t P_GetMapSky2ScrollDelta(int map); -boolean P_GetMapDoubleSky(int map); -boolean P_GetMapLightning(int map); -boolean P_GetMapFadeTable(int map); -char *P_GetMapSongLump(int map); -void P_PutMapSongLump(int map, char *lumpName); -int P_GetCDStartTrack(void); -int P_GetCDEnd1Track(void); -int P_GetCDEnd2Track(void); -int P_GetCDEnd3Track(void); -int P_GetCDIntermissionTrack(void); -int P_GetCDTitleTrack(void); - -//------- -//REFRESH -//------- - -extern boolean setsizeneeded; - -extern boolean BorderNeedRefresh; -extern boolean BorderTopRefresh; - -extern int UpdateState; -// define the different areas for the dirty map -#define I_NOUPDATE 0 -#define I_FULLVIEW 1 -#define I_STATBAR 2 -#define I_MESSAGES 4 -#define I_FULLSCRN 8 - -void R_RenderPlayerView(player_t * player); -// called by G_Drawer - -void R_Init(void); -// called by startup code - -void R_DrawViewBorder(void); -void R_DrawTopBorder(void); -// if the view size is not full screen, draws a border around it - -void R_SetViewSize(int blocks, int detail); -// called by M_Responder - -int R_FlatNumForName(const char *name); - -int R_TextureNumForName(const char *name); -int R_CheckTextureNumForName(const char *name); -// called by P_Ticker for switches and animations -// returns the texture number for the texture name - - -//---- -//MISC -//---- -extern int localQuakeHappening[MAXPLAYERS]; - -int M_DrawText(int x, int y, boolean direct, char *string); - -//------------------------------ -// SC_man.c -//------------------------------ - -void SC_Open(const char *name); -void SC_OpenLump(const char *name); -void SC_OpenFile(const char *name); -void SC_Close(void); -boolean SC_GetString(void); -void SC_MustGetString(void); -void SC_MustGetStringName(char *name); -boolean SC_GetNumber(void); -void SC_MustGetNumber(void); -void SC_UnGet(void); -//boolean SC_Check(void); -boolean SC_Compare(const char *text); -int SC_MatchString(const char **strings); -int SC_MustMatchString(const char **strings); -void SC_ScriptError(const char *message); - -extern char *sc_String; -extern int sc_Number; -extern int sc_Line; -extern boolean sc_End; -extern boolean sc_Crossed; -extern boolean sc_FileScripts; -extern const char *sc_ScriptsDir; - -//------------------------------ -// SN_sonix.c -//------------------------------ - -enum -{ - SEQ_PLATFORM, - SEQ_PLATFORM_HEAVY, // same script as a normal platform - SEQ_PLATFORM_METAL, - SEQ_PLATFORM_CREAK, // same script as a normal platform - SEQ_PLATFORM_SILENCE, - SEQ_PLATFORM_LAVA, - SEQ_PLATFORM_WATER, - SEQ_PLATFORM_ICE, - SEQ_PLATFORM_EARTH, - SEQ_PLATFORM_METAL2, - SEQ_DOOR_STONE, - SEQ_DOOR_HEAVY, - SEQ_DOOR_METAL, - SEQ_DOOR_CREAK, - SEQ_DOOR_SILENCE, - SEQ_DOOR_LAVA, - SEQ_DOOR_WATER, - SEQ_DOOR_ICE, - SEQ_DOOR_EARTH, - SEQ_DOOR_METAL2, - SEQ_ESOUND_WIND, - SEQ_NUMSEQ -}; - -typedef enum -{ - SEQTYPE_STONE, - SEQTYPE_HEAVY, - SEQTYPE_METAL, - SEQTYPE_CREAK, - SEQTYPE_SILENCE, - SEQTYPE_LAVA, - SEQTYPE_WATER, - SEQTYPE_ICE, - SEQTYPE_EARTH, - SEQTYPE_METAL2, - SEQTYPE_NUMSEQ -} seqtype_t; - -void SN_InitSequenceScript(void); -void SN_StartSequence(mobj_t * mobj, int sequence); -void SN_StartSequenceName(mobj_t * mobj, char *name); -void SN_StopSequence(mobj_t * mobj); -void SN_UpdateActiveSequences(void); -void SN_StopAllSequences(void); -int SN_GetSequenceOffset(int sequence, int *sequencePtr); -void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume, - int currentSoundID); - - -typedef struct seqnode_s seqnode_t; -struct seqnode_s -{ - int *sequencePtr; - int sequence; - mobj_t *mobj; - int currentSoundID; - int delayTics; - int volume; - int stopSound; - seqnode_t *prev; - seqnode_t *next; -}; - -extern int ActiveSequences; -extern seqnode_t *SequenceListHead; - -//---------------------- -// Interlude (IN_lude.c) -//---------------------- - -#define MAX_INTRMSN_MESSAGE_SIZE 1024 - -extern boolean intermission; -extern char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE]; - -void IN_Start(void); -void IN_Ticker(void); -void IN_Drawer(void); - -//---------------------- -// Chat mode (CT_chat.c) -//---------------------- - -void CT_Init(void); -void CT_Drawer(void); -boolean CT_Responder(event_t * ev); -void CT_Ticker(void); -char CT_dequeueChatChar(void); - -extern boolean chatmodeon; - -//-------------------- -// Finale (F_finale.c) -//-------------------- - -void F_Drawer(void); -void F_Ticker(void); -void F_StartFinale(void); - -//---------------------- -// STATUS BAR (SB_bar.c) -//---------------------- - -extern int inv_ptr; -extern int curpos; -extern boolean inventory; - - -void SB_Init(void); -void SB_SetClassData(void); -boolean SB_Responder(event_t * event); -void SB_Ticker(void); -void SB_Drawer(void); -void Draw_TeleportIcon(void); -void Draw_SaveIcon(void); -void Draw_LoadIcon(void); - -//----------------- -// MENU (MN_menu.c) -//----------------- - -void MN_Init(void); -void MN_ActivateMenu(void); -void MN_DeactivateMenu(void); -boolean MN_Responder(event_t * event); -void MN_Ticker(void); -void MN_Drawer(void); -void MN_DrTextA(const char *text, int x, int y); -void MN_DrTextAYellow(const char *text, int x, int y); -int MN_TextAWidth(const char *text); -void MN_DrTextB(const char *text, int x, int y); -int MN_TextBWidth(const char *text); - -extern int messageson; -extern boolean MenuActive; -extern boolean askforquit; -extern boolean mn_SuicideConsole; -extern int detailLevel; - - -#include "sounds.h" - -#include "p_action.h" - - -#endif // __H2DEF__ diff --git a/games/NXDoom/src/hexen/hexen_icon.c b/games/NXDoom/src/hexen/hexen_icon.c deleted file mode 100644 index ae1082596a0..00000000000 --- a/games/NXDoom/src/hexen/hexen_icon.c +++ /dev/null @@ -1,2736 +0,0 @@ -static int hexen_icon_w = 128; -static int hexen_icon_h = 128; - -static const unsigned int hexen_icon_data[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, - 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, - 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, - 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, - 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, - 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, - 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, - 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, - 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, - 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, - 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, - 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, - 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, - 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, - 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, - 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, - 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, - 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, - 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, - 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, - 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, - 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, - 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, - 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, - 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, - 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, - 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, - 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, - 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, - 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, - 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, - 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, - 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, - 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, - 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, - 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, - 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, - 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, - 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, - 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, - 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, - 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, - 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, - 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, - 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, - 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, - 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, - 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x93756aff, 0x917469ff, 0x99796eff, 0xa07b70ff, - 0xa07b70ff, 0xa07b70ff, 0xa07b70ff, 0xa07b70ff, 0xa07b70ff, 0xa8887eff, - 0xb9a39dff, 0xb8a39cff, 0xb8a39cff, 0xb7a29bff, 0xb7a29bff, 0xb6a19aff, - 0xb5a099ff, 0xb5a099ff, 0xb49f98ff, 0xa78980ff, 0x9e7a6eff, 0x9d7a6eff, - 0x9d7a6eff, 0x9d7a6eff, 0x9b796dff, 0x99776bff, 0x977469ff, 0x957267ff, - 0x957368ff, 0xa18982ff, 0xa38e88ff, 0xa18d86ff, 0xa08c85ff, 0x9e8983ff, - 0x9c8781ff, 0x9a867fff, 0x99847dff, 0x97827bff, 0x917c74ff, 0x7e5d51ff, - 0x7c5b4fff, 0x7b594eff, 0x78574cff, 0x76554aff, 0x745348ff, 0x735246ff, - 0x715044ff, 0x6f4e42ff, 0x775c52ff, 0x816e67ff, 0x7f6c65ff, 0x7e6b63ff, - 0x7c6861ff, 0x7a6760ff, 0x79665eff, 0x76635cff, 0x74615aff, 0x736059ff, - 0x61443bff, 0x57382dff, 0x55362cff, 0x583a30ff, 0x5a3d36ff, 0x5d3f3cff, - 0x5f4141ff, 0x5f4447ff, 0x5f454bff, 0x674e55ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, - 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, - 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, - 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, - 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, - 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, - 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, - 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, - 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, - 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, - 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, - 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, - 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, - 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, - 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, - 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, - 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, - 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, - 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, - 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, - 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, - 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc69e94ff, 0xc9a49bff, - 0xc8a39aff, 0xc7a39aff, 0xc6a198ff, 0xc5a198ff, 0xc4a097ff, 0xc4a096ff, - 0xc29f95ff, 0xbd948aff, 0xb07c6eff, 0xb07b6eff, 0xaf7b6dff, 0xae7b6dff, - 0xae7a6dff, 0xad7a6cff, 0xad7a6cff, 0xac7a6cff, 0xac7a6cff, 0xb38a80ff, - 0xb7978eff, 0xb6958cff, 0xb6958cff, 0xb5948bff, 0xb29289ff, 0xb19188ff, - 0xaf8f86ff, 0xad8d85ff, 0xab8c83ff, 0x9e7164ff, 0x9a6c5fff, 0x986a5dff, - 0x97695bff, 0x946759ff, 0x926558ff, 0x906356ff, 0x8e6155ff, 0x8b5f52ff, - 0x8d6458ff, 0x96786fff, 0x94776eff, 0x91756cff, 0x90736bff, 0x8e7269ff, - 0x8c7068ff, 0x8a6e66ff, 0x896d64ff, 0x866b62ff, 0x7d5d52ff, 0x734a3dff, - 0x70483bff, 0x6e473aff, 0x6c4438ff, 0x6b4337ff, 0x684134ff, 0x664033ff, - 0x643e31ff, 0x623c2fff, 0x6b4f45ff, 0x6f564eff, 0x6d544cff, 0x6e564fff, - 0x6e5652ff, 0x6e5753ff, 0x6f5857ff, 0x6f5958ff, 0x705a5cff, 0x705b5eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x903d27ff, 0x903d28ff, 0x8f3d28ff, 0x8e3c27ff, 0x8d3c27ff, 0x8c3b27ff, - 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, - 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, - 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, - 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, - 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, - 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, - 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, - 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, - 0x572311ff, 0x572310ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8f3d27ff, 0x8f3d28ff, 0x8e3c27ff, 0x8d3c27ff, - 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, - 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, - 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, - 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, - 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, - 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, - 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, - 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, - 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e3d27ff, 0x8e3c27ff, - 0x8d3c27ff, 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, - 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, - 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, - 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, - 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, - 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, - 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, - 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, - 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, - 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8d3c26ff, 0x8d3c27ff, 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, 0x8a3a26ff, - 0x893a25ff, 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, - 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, - 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, - 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, - 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, - 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, - 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, - 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, - 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, - 0x552210ff, 0x54220fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x8c3c26ff, 0x8c3b27ff, 0x8b3b26ff, 0x8a3b26ff, - 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, - 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, - 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, - 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, - 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, - 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, - 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, - 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, - 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, - 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8b3b26ff, 0x8b3b26ff, - 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, 0x863924ff, - 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, - 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, - 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, - 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, - 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, - 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, - 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, - 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, - 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8a3b25ff, 0x8a3b26ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, 0x873924ff, - 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, - 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, 0x7d3420ff, - 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, - 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, - 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, - 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, - 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, - 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, - 0x52210fff, 0x51200eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x893b25ff, 0x8a3a26ff, 0x893a25ff, 0x883925ff, - 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, - 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7e3521ff, - 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, - 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, - 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, - 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, - 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, - 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, - 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x893a25ff, 0x893a25ff, - 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, 0x843723ff, - 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, - 0x7e3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, - 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, - 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, - 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, - 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, - 0x5e2614ff, 0x5e2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, - 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, - 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x883a24ff, 0x883925ff, 0x873924ff, 0x863924ff, 0x853824ff, 0x843823ff, - 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x97361fff, - 0xe93819ff, 0xe53619ff, 0x92341fff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, - 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, - 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, - 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, - 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, - 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x852112ff, 0xd31710ff, 0xea1310ff, - 0xcc150fff, 0x752110ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, - 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, - 0x50200eff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x873924ff, 0x873924ff, 0x863924ff, 0x853824ff, - 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, - 0x7f3521ff, 0xcc371cff, 0xfe3718ff, 0xfe3617ff, 0xf23518ff, 0x91341eff, - 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, - 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, - 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, - 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, - 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xee0f0eff, 0x641e10ff, 0x572310ff, - 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, - 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x863923ff, 0x863924ff, - 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, 0x813622ff, - 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0xae361eff, 0xfe3617ff, 0xfe3517ff, - 0xfe3417ff, 0xf23318ff, 0x8f331eff, 0x78321eff, 0x77321eff, 0x77311eff, - 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, - 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, - 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, - 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, - 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0x9d1310ff, 0x501f10ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, - 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x853923ff, 0x853824ff, 0x843823ff, 0x843723ff, 0x833723ff, 0x823722ff, - 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, - 0xbd351cff, 0xfe3417ff, 0xfe3317ff, 0xfe3217ff, 0xf23217ff, 0x8d321dff, - 0xa8311bff, 0xd02f19ff, 0x9a311bff, 0x74301dff, 0x73301cff, 0x722f1cff, - 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, - 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, - 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0xf70e11ff, 0xaf1211ff, 0x40190fff, 0x4e1f0fff, 0x53210fff, - 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, - 0x4d1e0cff, 0x4d1e0cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x843823ff, 0x843823ff, 0x843723ff, 0x833723ff, - 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, - 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0xbc331bff, 0xfe3217ff, 0xfe3216ff, - 0xfd3116ff, 0xf23016ff, 0xfc2f16ff, 0xfd2e15ff, 0xfb2d15ff, 0xa02e1aff, - 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, - 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, - 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0x811411ff, 0x3f180eff, - 0x40180fff, 0x4d1e0fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, - 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4d1e0cff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x833822ff, 0x843723ff, - 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, - 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, - 0xbb321aff, 0xfd3116ff, 0xfd3016ff, 0xfd2f16ff, 0xfd2e15ff, 0xfd2d15ff, - 0xfd2c15ff, 0xfb2b15ff, 0x9f2d19ff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, - 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, - 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, - 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc41013ff, - 0x41180eff, 0x3f180eff, 0x3e180eff, 0x3f180eff, 0x4c1e0eff, 0x50200eff, - 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1d0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x833722ff, 0x833723ff, 0x823722ff, 0x813622ff, 0x803622ff, 0x7f3521ff, - 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7c331fff, - 0xaa321cff, 0xa4321bff, 0x78321eff, 0xba301aff, 0xfd2f16ff, 0xfd2e15ff, - 0xfd2d15ff, 0xfd2c15ff, 0xfd2b15ff, 0xfd2a15ff, 0xfa2914ff, 0x9e2c19ff, - 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, - 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, - 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, - 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, - 0x3f180eff, 0x4a1d0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4b1d0dff, 0x4c1d0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x823722ff, 0x823722ff, 0x813622ff, 0x803622ff, - 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, - 0x7a331fff, 0xb9331bff, 0xfe3216ff, 0xfd3116ff, 0x9c2b18ff, 0x76311dff, - 0xb92f19ff, 0xfd2d15ff, 0xfd2c15ff, 0xfd2b15ff, 0xfd2a15ff, 0xfc2914ff, - 0xfc2814ff, 0xf72713ff, 0x742717ff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, - 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, - 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, - 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, - 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3f180eff, 0x491c0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4b1d0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x813721ff, 0x813622ff, - 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, - 0x7b331fff, 0x7a331fff, 0x79331fff, 0xc5321aff, 0xfd3116ff, 0xfd3016ff, - 0xa02615ff, 0x5c2617ff, 0x74301dff, 0xb82e19ff, 0xfd2b15ff, 0xfd2a15ff, - 0xfc2914ff, 0xfc2814ff, 0xfc2714ff, 0xfc2614ff, 0x691d12ff, 0x602717ff, - 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, - 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, - 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, - 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3e180dff, 0x481c0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4b1c0eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x803621ff, 0x803622ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, 0x7d3420ff, - 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x84321dff, - 0xc12b16ff, 0xb72914ff, 0x531f13ff, 0x491d13ff, 0x5b2517ff, 0x722f1cff, - 0xb72c18ff, 0xfc2914ff, 0xfc2814ff, 0xfc2714ff, 0xfc2614ff, 0xb32112ff, - 0x441c11ff, 0x441b11ff, 0x5e2617ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, - 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, - 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x481b0dff, 0x4a1d0dff, - 0x4a1c0eff, 0x4a1c0eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x7f3621ff, 0x7f3521ff, 0x7e3521ff, 0x7d3521ff, - 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, - 0x77321eff, 0x77311eff, 0x712f1cff, 0x512115ff, 0x491d13ff, 0x481d13ff, - 0x481d13ff, 0x592416ff, 0x712f1bff, 0xb62b17ff, 0xfc2714ff, 0xfc2614ff, - 0xfc2513ff, 0xec2312ff, 0x621c11ff, 0x431b11ff, 0x431b10ff, 0x5c2516ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, - 0x5e2613ff, 0x932011ff, 0xf7120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xca1113ff, 0x47180eff, - 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d180eff, 0x471a0eff, 0x491c0eff, 0x4a1c0eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7f3520ff, 0x7e3521ff, - 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, 0x79331fff, - 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x6f2e1cff, - 0x502114ff, 0x481d13ff, 0x591e12ff, 0xa92313ff, 0x9c2515ff, 0x702e1aff, - 0xb52a17ff, 0xfc2513ff, 0xfc2413ff, 0xfc2313ff, 0xeb2113ff, 0x611c10ff, - 0x421a10ff, 0x421b10ff, 0x5a2415ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, - 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, - 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, - 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3e170fff, 0x461a0eff, 0x491b0fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x7e3520ff, 0x7d3521ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, 0x7a331fff, - 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, - 0x74301dff, 0x73301cff, 0x6e2d1bff, 0x4e2014ff, 0xc22514ff, 0xfc2814ff, - 0xfc2714ff, 0xb82615ff, 0x6e2d1aff, 0xb42816ff, 0xfc2313ff, 0xfc2213ff, - 0xfb2112ff, 0xea1f11ff, 0x601b10ff, 0x411a10ff, 0x411a10ff, 0x582414ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, - 0x5f2714ff, 0x5e2614ff, 0x5e2613ff, 0x971f12ff, 0xf8120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, - 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, - 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3e1710ff, 0x461a0fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x7d3520ff, 0x7d3420ff, 0x7c3420ff, 0x7b331fff, - 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, - 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x6c2d1aff, - 0xc32514ff, 0xfc2714ff, 0xfc2614ff, 0xfc2513ff, 0xb82313ff, 0x6c2c19ff, - 0xb32716ff, 0xfb2112ff, 0xfb2012ff, 0xfb1f12ff, 0xea1d11ff, 0x5e1b10ff, - 0x401a0fff, 0x401a0fff, 0x592414ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x612714ff, 0xa02013ff, 0xe41711ff, 0xf9140fff, 0xfa130fff, 0xf9120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, - 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, - 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, - 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x401710ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7d341fff, 0x7c3420ff, - 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, 0x77311eff, - 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, - 0x712f1bff, 0x702e1bff, 0x7b2b18ff, 0xe42514ff, 0xfc2513ff, 0xfc2413ff, - 0xfc2313ff, 0xb72213ff, 0x6b2c18ff, 0xb22515ff, 0xfb1f12ff, 0xfb1e12ff, - 0xfb1d12ff, 0xea1b10ff, 0x5e1910ff, 0x3f190fff, 0x3f190fff, 0x562213ff, - 0x612815ff, 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, - 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, 0x3e180eff, - 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3e170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3f1611ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x7c341fff, 0x7b331fff, 0x7a331fff, 0x79331fff, 0x78321eff, 0x77321eff, - 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, - 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x7a2a18ff, - 0xe42312ff, 0xfc2313ff, 0xfc2213ff, 0xfb2112ff, 0x9b2113ff, 0x682b18ff, - 0xb12414ff, 0xfb1d12ff, 0xfb1c11ff, 0xfb1b11ff, 0xea1a10ff, 0x5e190fff, - 0x3e190eff, 0x3e190fff, 0x552112ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, - 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, 0x3f180eff, - 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3e170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3f1611ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x7b331eff, 0x7a331fff, 0x79331fff, 0x78321eff, - 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, - 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, - 0x6d2d1aff, 0x6c2d19ff, 0x782917ff, 0xe42112ff, 0xfb2112ff, 0xfb2012ff, - 0xb11d11ff, 0x522013ff, 0x662a17ff, 0xb02314ff, 0xfb1b11ff, 0xfb1a11ff, - 0xfa1911ff, 0xeb1810ff, 0xc71810ff, 0xc81610ff, 0xd41610ff, 0xfa1410ff, - 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, 0x47180eff, - 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3f1711ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x7a331eff, 0x79331fff, - 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, 0x74301dff, - 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, - 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x772916ff, - 0xc61f12ff, 0xcb1e11ff, 0x591b10ff, 0x441a10ff, 0x5f1f11ff, 0x642916ff, - 0xb02114ff, 0xfa1911ff, 0xfa1810ff, 0xfa1710ff, 0xfa1610ff, 0xfa1510ff, - 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xc81013ff, - 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, - 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3f1712ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x79331eff, 0x78321eff, 0x77321eff, 0x77311eff, 0x76311dff, 0x75311dff, - 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, - 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, - 0x6a2c18ff, 0x692b18ff, 0x642917ff, 0x471c11ff, 0x4d1a10ff, 0xe21c11ff, - 0xfb1b11ff, 0xb11d12ff, 0x642815ff, 0xba1f12ff, 0xfa1710ff, 0xfa1610ff, - 0xfa1510ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, - 0xda0f13ff, 0x47180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, - 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3e170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3f1712ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x78321dff, 0x77321eff, 0x77311eff, 0x76311dff, - 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, - 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, - 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x622816ff, - 0x791c10ff, 0xfb1b11ff, 0xfb1a11ff, 0xfa1911ff, 0xbf1b10ff, 0xd41b11ff, - 0xfa1610ff, 0xfa1510ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, - 0xf60e12ff, 0xf50e14ff, 0xf20e15ff, 0x681510ff, 0x3e180eff, 0x3e180eff, - 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, - 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3f1712ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x77321dff, 0x77311eff, - 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, 0x712f1bff, - 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, - 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x692615ff, 0xe21a11ff, 0xfa1911ff, 0xfa1810ff, - 0xfa1710ff, 0xfa1610ff, 0xfa1510ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, - 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xa91214ff, - 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3f1613ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x77311dff, 0x76311dff, 0x75311dff, 0x74301dff, 0x73301cff, 0x722f1cff, - 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, - 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x702514ff, - 0xe21910ff, 0xfa1710ff, 0xfa1610ff, 0xfa1510ff, 0xfa1410ff, 0xfa140fff, - 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, - 0xf20e18ff, 0xaf1215ff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1513ff, 0x3e1613ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x76311cff, 0x75311dff, 0x74301dff, 0x73301cff, - 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, - 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x6e2514ff, 0xe21710ff, 0xfa1510ff, 0xfa1410ff, - 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, - 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, 0x781511ff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3e1714ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x75311cff, 0x74301dff, - 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, - 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, - 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xc11b11ff, - 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, - 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, 0xae1215ff, 0x3e180eff, - 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3e1615ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x74301cff, 0x73301cff, 0x722f1cff, 0x712f1bff, 0x712f1bff, 0x702e1bff, - 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, - 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, - 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, - 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, 0xb31116ff, - 0x41180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3f1614ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x73301bff, 0x722f1cff, 0x712f1bff, 0x712f1bff, - 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, - 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, - 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xf70e11ff, - 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xf10e19ff, - 0xb31116ff, 0x41180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, - 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3e1615ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x722f1bff, 0x712f1bff, - 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, - 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, - 0x612815ff, 0x612714ff, 0xbc1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, - 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, - 0xf10e19ff, 0xec0e19ff, 0x5d1611ff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, - 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3f1515ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x712f1aff, 0x712f1bff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, 0x6d2d1aff, - 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, - 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0xf70e11ff, 0xf60e12ff, 0xf50e14ff, 0xf40e15ff, 0xf30e16ff, - 0xf20e18ff, 0xf10e19ff, 0xf00e1aff, 0xef0e1cff, 0xde0f1bff, 0x5c1610ff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, - 0x3d1415ff, 0x3e1615ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x712f1aff, 0x702e1bff, 0x6f2e1aff, 0x6e2e1aff, - 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xbc1d12ff, 0xfa1410ff, - 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0xc01110ff, 0xec0e12ff, 0xf50e14ff, 0xf40e15ff, - 0xf30e16ff, 0xf20e18ff, 0xd90f18ff, 0xa31315ff, 0xef0e1cff, 0xee0e1dff, - 0xed0d1eff, 0xdd0e1eff, 0x5a1510ff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, - 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3e1616ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x702e1aff, 0x6f2e1aff, - 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, - 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xbc1d12ff, - 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x40180fff, 0xcb1012ff, - 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xd90f18ff, 0x54170fff, 0x3e180eff, - 0x961215ff, 0xed0d1eff, 0xec0d20ff, 0xeb0d21ff, 0xdb0e20ff, 0x591512ff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, - 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3d1516ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6f2e19ff, 0x6e2e1aff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, - 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, - 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, - 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, - 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x8f1216ff, 0xeb0d21ff, 0xea0d22ff, - 0xe90d24ff, 0xd90e23ff, 0x5a1513ff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, - 0x3c1416ff, 0x3d1515ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x6e2e19ff, 0x6d2d1aff, 0x6c2d19ff, 0x6b2c19ff, - 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, - 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, - 0x40180fff, 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, - 0x56170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, - 0x8e1217ff, 0xe90d24ff, 0xe80d25ff, 0xe70d26ff, 0xd70e26ff, 0x5a1513ff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, - 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3d1516ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6d2d19ff, 0x6c2d19ff, - 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, - 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, - 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0xa11210ff, 0x40180fff, 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, - 0xdc0f18ff, 0x56170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x8d1218ff, 0xe70d26ff, 0xe60d28ff, - 0xe50d29ff, 0xd50e27ff, 0x591415ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, - 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, - 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3d1416ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6c2d19ff, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, 0x682b18ff, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, 0xfa140fff, - 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0xa11210ff, 0x40180fff, 0xa91212ff, 0xf40e15ff, 0xf30e16ff, - 0xf20e18ff, 0xdc0f18ff, 0x56170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x8c121bff, 0xe50d29ff, 0xe40d2aff, 0xe30d2cff, 0xd40e2aff, 0x5a1515ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, - 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, - 0x3c1316ff, 0x3d1417ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x6b2c19ff, 0x6a2c19ff, 0x6a2c18ff, 0x692b18ff, - 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, 0xfa1410ff, - 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, 0xa91212ff, 0xf40e15ff, - 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x8b121cff, 0xe30d2cff, 0xe20d2dff, - 0xe10d2eff, 0xd20e2dff, 0x591416ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, - 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, - 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3d1418ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a2c19ff, 0x6a2c18ff, - 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, 0xb91c11ff, - 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, 0xa91212ff, - 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, 0x3e180eff, - 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x8a121eff, 0xe10d2eff, 0xe00d30ff, 0xdf0d31ff, 0xd00e30ff, 0x591418ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, - 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, - 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3d1318ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6a2c18ff, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, 0x652a16ff, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x612714ff, - 0xb91c11ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0xa11210ff, 0x40180fff, - 0xa91212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xdc0f18ff, 0x56170fff, - 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x8a121fff, 0xdf0d31ff, 0xde0d33ff, - 0xdd0d34ff, 0xce0e32ff, 0x591418ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, - 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, - 0x3c1218ff, 0x3c1318ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x692b18ff, 0x682b18ff, 0x672a17ff, 0x662a17ff, - 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, - 0x3f180fff, 0xab1212ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, 0xd90f18ff, - 0x54170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, - 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x8e1222ff, 0xdd0d34ff, 0xdc0d35ff, 0xdb0d37ff, 0xcc0e35ff, 0x571419ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, - 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, - 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3c1319ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x682b18ff, 0x672a17ff, - 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, - 0x612815ff, 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, 0xfa130fff, - 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0x9b1310ff, 0x3f180fff, 0x691511ff, 0xf40e15ff, 0xf30e16ff, 0xf20e18ff, - 0xd90f18ff, 0x54170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x8d1224ff, 0xdb0d37ff, 0xda0d38ff, - 0xd90d39ff, 0xcb0e38ff, 0x56141cff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, - 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, - 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3c1218ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x672a17ff, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, 0x632815ff, - 0x622815ff, 0x612815ff, 0x612714ff, 0xbb1d12ff, 0xfa1410ff, 0xfa140fff, - 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, 0x5d1610ff, 0xf10e16ff, - 0xf20e18ff, 0xd90f18ff, 0x54170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x8c1125ff, 0xd90d39ff, 0xd80d3bff, 0xd70d3cff, 0xc90e39ff, 0x56141cff, - 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, - 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, - 0x3b1118ff, 0x3c1218ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x662a17ff, 0x652a16ff, 0x642916ff, 0x642916ff, - 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x9b2012ff, 0xfa1410ff, - 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x40180fff, 0x7b1511ff, 0x801411ff, - 0x41180eff, 0x6e1610ff, 0x911313ff, 0x4e170fff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x8a1228ff, 0xd70d3cff, 0xd60d3dff, - 0xd50d3fff, 0xc70d3cff, 0x56141dff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, - 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, - 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3c1319ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x652a16ff, 0x642916ff, - 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, - 0xd81810ff, 0xfa140fff, 0xfa130fff, 0xf9120fff, 0xf9110fff, 0xf9100eff, - 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x851411ff, - 0xf40e15ff, 0xf30e16ff, 0x941412ff, 0x3e180eff, 0x3f180eff, 0x3e180eff, - 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, - 0x8a1129ff, 0xd50d3fff, 0xd40c40ff, 0xd30c41ff, 0xc50d3fff, 0x54131dff, - 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, - 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3b121aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x642916ff, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, 0x602714ff, - 0x5f2714ff, 0x5e2614ff, 0xe41610ff, 0xfa130fff, 0xf9120fff, 0xf9110fff, - 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, - 0x3f180fff, 0x971311ff, 0xf30e16ff, 0xf20e18ff, 0xa51214ff, 0x3f180eff, - 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x88102aff, 0xd30c41ff, 0xd20c43ff, - 0xd10c44ff, 0xc20d41ff, 0x51131dff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, - 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, - 0x3a111aff, 0x3a1219ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x642916ff, 0x632815ff, 0x622815ff, 0x612815ff, - 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, 0xb61b11ff, 0xf9120fff, - 0xf9110fff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, - 0x3f180fff, 0x5c1610ff, 0x4d170fff, 0x49180eff, 0xac1214ff, 0xb01215ff, - 0x50170fff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, - 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, - 0x87102dff, 0xd10c44ff, 0xd00c45ff, 0xcf0c47ff, 0x940f34ff, 0x3c1317ff, - 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, - 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3b1219ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x632815ff, 0x622815ff, - 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, - 0x652413ff, 0xd81510ff, 0xf9100eff, 0xf90f0eff, 0xf90e0eff, 0xf80e10ff, - 0x9b1310ff, 0x3f180fff, 0x961412ff, 0xf40e15ff, 0xea0e16ff, 0x591610ff, - 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, - 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, - 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x86102dff, 0xcf0c47ff, 0xce0c48ff, - 0x7a102cff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, - 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x3a1119ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x622815ff, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, - 0x5d2613ff, 0x5c2513ff, 0x742211ff, 0xeb120fff, 0xf90f0eff, 0xf90e0eff, - 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, 0xc81113ff, 0xf30e16ff, - 0xf20e18ff, 0x811412ff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, - 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, - 0x5d1221ff, 0x621124ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, - 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, - 0x39101aff, 0x3a1119ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x612815ff, 0x602714ff, 0x5f2714ff, 0x5e2614ff, - 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0xd4140fff, 0xf90f0eff, - 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, 0x3f180eff, - 0x761511ff, 0xe40f17ff, 0xc91016ff, 0x4b170fff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, - 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, - 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, - 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, - 0x3a111aff, 0x39101aff, 0x39101aff, 0x39111aff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x602714ff, 0x5f2714ff, - 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, - 0xd4140fff, 0xf90e0eff, 0xf80e10ff, 0x9b1310ff, 0x3f180fff, 0x3f180fff, - 0x3f180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, 0x3e180eff, - 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, - 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, - 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, - 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, - 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x39101aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5f2714ff, 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, - 0x5a2412ff, 0x592411ff, 0x6b1f10ff, 0xa71310ff, 0x801510ff, 0x3f180fff, - 0x3f180fff, 0x3f180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, 0x3f180eff, - 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, - 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, - 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, - 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, - 0x380f1bff, 0x39101aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x5e2614ff, 0x5d2613ff, 0x5d2613ff, 0x5c2513ff, - 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x54210fff, - 0x41190eff, 0x3f180fff, 0x3f180eff, 0x3f180eff, 0x3e180eff, 0x3e180eff, - 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, 0x3d170dff, - 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, - 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, - 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, - 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, - 0x38101bff, 0x380f1bff, 0x380f1bff, 0x38101bff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5d2613ff, 0x5d2613ff, - 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, - 0x572310ff, 0x562210ff, 0x52200fff, 0x40190fff, 0x3f180eff, 0x3e180eff, - 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, 0x3e170dff, - 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, - 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, - 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, - 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, - 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, - 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x380f1bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5d2613ff, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, 0x582411ff, - 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x501f0fff, - 0x40190fff, 0x3e180eff, 0x3f180eff, 0x3e180eff, 0x3e170dff, 0x3e180dff, - 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, - 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, - 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, - 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, - 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, - 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, - 0x370e1cff, 0x370f1cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x5c2513ff, 0x5b2512ff, 0x5a2412ff, 0x592411ff, - 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, - 0x53210fff, 0x52210fff, 0x4f1f0eff, 0x40190eff, 0x3e180eff, 0x3e170dff, - 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, 0x3d170eff, - 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, - 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, - 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, - 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, - 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, - 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x370f1cff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5b2512ff, 0x5a2412ff, - 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, - 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x4e1f0eff, - 0x3f180eff, 0x3e180dff, 0x3e170dff, 0x3d170dff, 0x3d170dff, 0x3d170eff, - 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, - 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, - 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, - 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, - 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, - 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, - 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x360e1cff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5a2412ff, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, 0x562210ff, - 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, - 0x50200eff, 0x4f1f0dff, 0x4c1e0dff, 0x3f180dff, 0x3d170dff, 0x3d170dff, - 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, 0x3e170fff, - 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, - 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, - 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, - 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, - 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, - 0x350d1dff, 0x360e1dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x592411ff, 0x582411ff, 0x572311ff, 0x572310ff, - 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, - 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4a1d0dff, - 0x3f180dff, 0x3d170eff, 0x3d170eff, 0x3d170eff, 0x3d170fff, 0x3d170fff, - 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, - 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, - 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, - 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, - 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, - 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, - 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x350e1dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x582411ff, 0x572311ff, - 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, - 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x491c0eff, 0x3f180eff, 0x3d170eff, 0x3d170fff, - 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, 0x3e1611ff, - 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, - 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, - 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, - 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, - 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, - 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, - 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x350d1dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x572311ff, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, 0x53210fff, - 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, - 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x481c0eff, - 0x3f170fff, 0x3d170fff, 0x3e170fff, 0x3d1610ff, 0x3e1710ff, 0x3e1710ff, - 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, - 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, - 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, - 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, - 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, - 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, - 0x340c1eff, 0x340d1eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x572310ff, 0x562210ff, 0x552210ff, 0x54220fff, - 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, - 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, - 0x4a1d0dff, 0x4a1c0eff, 0x471b0fff, 0x3f180fff, 0x3d1610ff, 0x3e1710ff, - 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, - 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, - 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, - 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, - 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, - 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, - 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x340d1eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x562210ff, 0x552210ff, - 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, - 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, - 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x471a10ff, - 0x3f1710ff, 0x3e1710ff, 0x3e1611ff, 0x3e1611ff, 0x3e1711ff, 0x3e1612ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, - 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, - 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, - 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, - 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, - 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, - 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x340c1eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x552210ff, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, 0x51200eff, - 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, - 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x3f1711ff, 0x3e1611ff, 0x3e1711ff, - 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, 0x3d1614ff, - 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, - 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, - 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, - 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, - 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, - 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, - 0x330b1fff, 0x330c1fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x54220fff, 0x53210fff, 0x52210fff, 0x51200eff, - 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, - 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x461911ff, - 0x3f1711ff, 0x3e1612ff, 0x3e1612ff, 0x3e1612ff, 0x3e1513ff, 0x3d1613ff, - 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, - 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, - 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, - 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, - 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, - 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, - 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x330c1fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x53210fff, 0x52210fff, - 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, - 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, - 0x471a10ff, 0x461a10ff, 0x441812ff, 0x3e1613ff, 0x3e1612ff, 0x3e1513ff, - 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, - 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, - 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, - 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, - 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, - 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, - 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x320b1fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x52210fff, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, - 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, - 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, - 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, 0x431811ff, - 0x3e1613ff, 0x3d1613ff, 0x3d1614ff, 0x3d1515ff, 0x3e1514ff, 0x3d1515ff, - 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, - 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, - 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, - 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, - 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, - 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, - 0x310a20ff, 0x320b20ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x51200eff, 0x51200eff, 0x50200eff, 0x4f1f0dff, - 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, - 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, - 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, - 0x451911ff, 0x441812ff, 0x421712ff, 0x3e1613ff, 0x3d1515ff, 0x3e1514ff, - 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, 0x3c1415ff, - 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, - 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, - 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, - 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, - 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, - 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x310b20ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x51200eff, 0x50200eff, - 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, - 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, - 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, - 0x451911ff, 0x451911ff, 0x441812ff, 0x441812ff, 0x431812ff, 0x421713ff, - 0x3e1514ff, 0x3d1515ff, 0x3d1415ff, 0x3d1515ff, 0x3d1516ff, 0x3c1416ff, - 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, - 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, - 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, - 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, - 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, - 0x320b20ff, 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x300a21ff, 0x310a20ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50200eff, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, - 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, - 0x461911ff, 0x451911ff, 0x451911ff, 0x441812ff, 0x441812ff, 0x431812ff, - 0x431713ff, 0x431713ff, 0x411714ff, 0x3d1515ff, 0x3d1515ff, 0x3d1516ff, - 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, 0x3c1318ff, - 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, - 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, - 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, - 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, - 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x300a21ff, - 0x300921ff, 0x300a21ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4e1f0dff, 0x4d1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, - 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, 0x471a10ff, - 0x461a10ff, 0x461911ff, 0x451911ff, 0x451911ff, 0x441812ff, 0x441812ff, - 0x431812ff, 0x431713ff, 0x431713ff, 0x421714ff, 0x421614ff, 0x401614ff, - 0x3d1515ff, 0x3c1416ff, 0x3c1415ff, 0x3c1416ff, 0x3c1316ff, 0x3c1317ff, - 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, - 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, 0x39101aff, - 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, 0x360e1dff, - 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, 0x330c1fff, - 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x310a20ff, 0x310a21ff, - 0x300a21ff, 0x300921ff, 0x2f0922ff, 0x300a21ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0eff, 0x4d1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, 0x4a1c0eff, - 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, 0x471a10ff, - 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, 0x451911ff, 0x441812ff, - 0x441812ff, 0x431812ff, 0x431713ff, 0x431713ff, 0x421714ff, 0x421614ff, - 0x411614ff, 0x411615ff, 0x3f1515ff, 0x3d1415ff, 0x3c1416ff, 0x3c1316ff, - 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, 0x3b1118ff, - 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, 0x39101aff, - 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, 0x370e1cff, - 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, 0x340c1eff, - 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, 0x310a20ff, - 0x310a21ff, 0x300a21ff, 0x300921ff, 0x2f0922ff, 0x2f0922ff, 0x330b20ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5a250fea, 0x4c1e0cff, 0x4c1e0cff, 0x4b1d0dff, 0x4b1d0dff, 0x4a1d0dff, - 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, 0x481b0fff, - 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, 0x451911ff, - 0x441812ff, 0x441812ff, 0x431812ff, 0x431713ff, 0x431713ff, 0x421714ff, - 0x421614ff, 0x411614ff, 0x411615ff, 0x401515ff, 0x401515ff, 0x3e1516ff, - 0x3d1317ff, 0x3c1317ff, 0x3c1318ff, 0x3c1218ff, 0x3b1218ff, 0x3b1219ff, - 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, 0x3a111aff, - 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, 0x370f1cff, - 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, 0x340d1eff, - 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, 0x320b20ff, - 0x310a20ff, 0x310a21ff, 0x300a21ff, 0x300921ff, 0x2f0922ff, 0x2f0922ff, - 0x2e0822ff, 0x48171fe9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x782d1e22, 0x56220df7, 0x4b1d0dff, 0x4b1d0dff, - 0x4a1d0dff, 0x4a1c0eff, 0x491c0eff, 0x491c0eff, 0x481b0fff, 0x481b0fff, - 0x481b0fff, 0x471a10ff, 0x471a10ff, 0x461a10ff, 0x461911ff, 0x451911ff, - 0x451911ff, 0x441812ff, 0x441812ff, 0x431812ff, 0x431713ff, 0x431713ff, - 0x421714ff, 0x421614ff, 0x411614ff, 0x411615ff, 0x401515ff, 0x401515ff, - 0x3f1516ff, 0x3f1416ff, 0x3d1416ff, 0x3d1318ff, 0x3c1218ff, 0x3b1218ff, - 0x3b1219ff, 0x3b1118ff, 0x3b1118ff, 0x3b1219ff, 0x3a111aff, 0x391119ff, - 0x3a111aff, 0x39101aff, 0x39101aff, 0x38101bff, 0x380f1bff, 0x380f1bff, - 0x370f1cff, 0x370e1cff, 0x360e1dff, 0x360e1dff, 0x350d1dff, 0x350d1eff, - 0x340d1eff, 0x340c1eff, 0x330c1fff, 0x330c1fff, 0x330b1fff, 0x320b20ff, - 0x320b20ff, 0x310a20ff, 0x310a21ff, 0x300a21ff, 0x300921ff, 0x2f0922ff, - 0x2f0922ff, 0x2e0822ff, 0x40131ff6, 0x68282820, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x7030114b, 0x6a2e1397, 0x682b149b, 0x662b149b, 0x662b149b, 0x662b149b, - 0x662b149b, 0x662b149b, 0x662b149b, 0x662b149b, 0x662b149b, 0x662b159b, - 0x642b159b, 0x642b159b, 0x6429159b, 0x6429159b, 0x6429159b, 0x6429159b, - 0x6429159b, 0x6429159b, 0x6429159b, 0x6329159b, 0x6329179b, 0x6329179b, - 0x6329179b, 0x6329179b, 0x6327179b, 0x6327179b, 0x6327179b, 0x6027179c, - 0x5f27179c, 0x5f27179c, 0x6027179c, 0x6027179c, 0x6027199c, 0x6127199b, - 0x5f27199b, 0x5f27199b, 0x5f26199b, 0x5f26199b, 0x5f26199b, 0x5f26199b, - 0x5f26199b, 0x5f26199b, 0x5f26199b, 0x5e261a9b, 0x5e261a9b, 0x5e241a9b, - 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, 0x5e241a9b, - 0x5c241c9b, 0x5c241c9b, 0x5c241c9b, 0x5c241c9b, 0x5c241c9b, 0x5c231c9b, - 0x5c231c9b, 0x5c231c9b, 0x5f231d97, 0x66291b4b, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; diff --git a/games/NXDoom/src/hexen/in_lude.c b/games/NXDoom/src/hexen/in_lude.c deleted file mode 100644 index 573dce5c8d6..00000000000 --- a/games/NXDoom/src/hexen/in_lude.c +++ /dev/null @@ -1,607 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include - -#include "h2def.h" -#include "s_sound.h" -#include "i_system.h" -#include "i_video.h" -#include "m_misc.h" -#include "p_local.h" -#include "v_video.h" -#include "i_swap.h" -#include "am_map.h" - - -// MACROS ------------------------------------------------------------------ - -#define TEXTSPEED 3 -#define TEXTWAIT 140 - -// TYPES ------------------------------------------------------------------- - -typedef enum -{ - SINGLE, - COOPERATIVE, - DEATHMATCH -} gametype_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void WaitStop(void); -static void Stop(void); -static void LoadPics(void); -static void UnloadPics(void); -static void CheckForSkip(void); -static void InitStats(void); -static void DrDeathTally(void); -static void DrNumber(int val, int x, int y, int wrapThresh); -static void DrNumberBold(int val, int x, int y, int wrapThresh); -static void DrawHubText(void); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DECLARATIONS ------------------------------------------------ - -boolean intermission; -char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE]; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static boolean skipintermission; -static int interstate = 0; -static int intertime = -1; -static gametype_t gametype; -static int cnt; -static int slaughterboy; // in DM, the player with the most kills -static patch_t *patchINTERPIC; -static patch_t *FontBNumbers[10]; -static patch_t *FontBNegative; -static patch_t *FontBSlash; -static patch_t *FontBPercent; -static int FontABaseLump; -static int FontBLump; -static int FontBLumpBase; - -static signed int totalFrags[MAXPLAYERS]; - -static int HubCount; -static char *HubText; - -// CODE -------------------------------------------------------------------- - -//======================================================================== -// -// IN_Start -// -//======================================================================== - - -void IN_Start(void) -{ - int i; - I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); - InitStats(); - LoadPics(); - intermission = true; - interstate = 0; - skipintermission = false; - intertime = 0; - AM_Stop(); - for (i = 0; i < maxplayers; i++) - { - players[i].messageTics = 0; - players[i].message[0] = 0; - } - SN_StopAllSequences(); -} - -//======================================================================== -// -// WaitStop -// -//======================================================================== - -void WaitStop(void) -{ - if (!--cnt) - { - Stop(); -// gamestate = GS_LEVEL; -// G_DoLoadLevel(); - gameaction = ga_leavemap; -// G_WorldDone(); - } -} - -//======================================================================== -// -// Stop -// -//======================================================================== - -static void Stop(void) -{ - intermission = false; - UnloadPics(); - SB_state = -1; - BorderNeedRefresh = true; -} - -//======================================================================== -// -// InitStats -// -// Initializes the stats for single player mode -//======================================================================== - -static const char *ClusMsgLumpNames[] = { - "clus1msg", - "clus2msg", - "clus3msg", - "clus4msg", - "clus5msg" -}; - -static void InitStats(void) -{ - int i; - int j; - int oldCluster; - signed int slaughterfrags; - int slaughtercount; - int playercount; - const char *msgLumpName; - int msgSize; - int msgLump; - - if (!deathmatch) - { - gametype = SINGLE; - HubCount = 0; - oldCluster = P_GetMapCluster(gamemap); - if (oldCluster != P_GetMapCluster(LeaveMap)) - { - if (oldCluster >= 1 && oldCluster <= 5) - { - msgLumpName = ClusMsgLumpNames[oldCluster - 1]; - msgLump = W_GetNumForName(msgLumpName); - msgSize = W_LumpLength(msgLump); - if (msgSize >= MAX_INTRMSN_MESSAGE_SIZE) - { - I_Error("Cluster message too long (%s)", msgLumpName); - } - W_ReadLump(msgLump, ClusterMessage); - ClusterMessage[msgSize] = 0; // Append terminator - HubText = ClusterMessage; - HubCount = strlen(HubText) * TEXTSPEED + TEXTWAIT; - S_StartSongName("hub", true); - } - } - } - else - { - gametype = DEATHMATCH; - slaughterboy = 0; - slaughterfrags = -9999; - playercount = 0; - slaughtercount = 0; - for (i = 0; i < maxplayers; i++) - { - totalFrags[i] = 0; - if (playeringame[i]) - { - playercount++; - for (j = 0; j < maxplayers; j++) - { - if (playeringame[j]) - { - totalFrags[i] += players[i].frags[j]; - } - } - } - if (totalFrags[i] > slaughterfrags) - { - slaughterboy = 1 << i; - slaughterfrags = totalFrags[i]; - slaughtercount = 1; - } - else if (totalFrags[i] == slaughterfrags) - { - slaughterboy |= 1 << i; - slaughtercount++; - } - } - if (playercount == slaughtercount) - { // don't do the slaughter stuff if everyone is equal - slaughterboy = 0; - } - S_StartSongName("hub", true); - } -} - -//======================================================================== -// -// LoadPics -// -//======================================================================== - -static void LoadPics(void) -{ - int i; - - if (HubCount || gametype == DEATHMATCH) - { - patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC); - FontBLumpBase = W_GetNumForName("FONTB16"); - for (i = 0; i < 10; i++) - { - FontBNumbers[i] = W_CacheLumpNum(FontBLumpBase + i, PU_STATIC); - } - FontBLump = W_GetNumForName("FONTB_S") + 1; - FontBNegative = W_CacheLumpName("FONTB13", PU_STATIC); - FontABaseLump = W_GetNumForName("FONTA_S") + 1; - - FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC); - FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC); - } -} - -//======================================================================== -// -// UnloadPics -// -//======================================================================== - -static void UnloadPics(void) -{ - int i; - - if (HubCount || gametype == DEATHMATCH) - { - W_ReleaseLumpName("INTERPIC"); - - patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC); - FontBLumpBase = W_GetNumForName("FONTB16"); - for (i = 0; i < 10; i++) - { - W_ReleaseLumpNum(FontBLumpBase + i); - } - W_ReleaseLumpName("FONTB13"); - W_ReleaseLumpName("FONTB15"); - W_ReleaseLumpName("FONTB05"); - } -} - -//======================================================================== -// -// IN_Ticker -// -//======================================================================== - -void IN_Ticker(void) -{ - if (!intermission) - { - return; - } - if (interstate) - { - WaitStop(); - return; - } - skipintermission = false; - CheckForSkip(); - intertime++; - if (skipintermission || (gametype == SINGLE && !HubCount)) - { - interstate = 1; - cnt = 10; - skipintermission = false; - //S_StartSound(NULL, sfx_dorcls); - } -} - -//======================================================================== -// -// CheckForSkip -// -// Check to see if any player hit a key -//======================================================================== - -static void CheckForSkip(void) -{ - int i; - player_t *player; - static boolean triedToSkip; - - for (i = 0, player = players; i < maxplayers; i++, player++) - { - if (playeringame[i]) - { - if (player->cmd.buttons & BT_ATTACK) - { - if (!player->attackdown) - { - skipintermission = 1; - } - player->attackdown = true; - } - else - { - player->attackdown = false; - } - if (player->cmd.buttons & BT_USE) - { - if (!player->usedown) - { - skipintermission = 1; - } - player->usedown = true; - } - else - { - player->usedown = false; - } - } - } - if (deathmatch && intertime < 140) - { // wait for 4 seconds before allowing a skip - if (skipintermission == 1) - { - triedToSkip = true; - skipintermission = 0; - } - } - else - { - if (triedToSkip) - { - skipintermission = 1; - triedToSkip = false; - } - } -} - -//======================================================================== -// -// IN_Drawer -// -//======================================================================== - -void IN_Drawer(void) -{ - if (!intermission) - { - return; - } - if (interstate) - { - return; - } - UpdateState |= I_FULLSCRN; - memcpy(I_VideoBuffer, (byte *) patchINTERPIC, SCREENWIDTH * SCREENHEIGHT); - - if (gametype == SINGLE) - { - if (HubCount) - { - DrawHubText(); - } - } - else - { - DrDeathTally(); - } -} - -//======================================================================== -// -// DrDeathTally -// -//======================================================================== - -#define TALLY_EFFECT_TICKS 20 -#define TALLY_FINAL_X_DELTA (23*FRACUNIT) -#define TALLY_FINAL_Y_DELTA (13*FRACUNIT) -#define TALLY_START_XPOS (178*FRACUNIT) -#define TALLY_STOP_XPOS (90*FRACUNIT) -#define TALLY_START_YPOS (132*FRACUNIT) -#define TALLY_STOP_YPOS (83*FRACUNIT) -#define TALLY_TOP_X 85 -#define TALLY_TOP_Y 9 -#define TALLY_LEFT_X 7 -#define TALLY_LEFT_Y 71 -#define TALLY_TOTALS_X 291 - -static void DrDeathTally(void) -{ - int i, j; - fixed_t xPos, yPos; - fixed_t xDelta, yDelta; - fixed_t xStart, scale; - int x, y; - boolean bold; - static boolean showTotals; - int temp; - - V_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y, - W_CacheLumpName("tallytop", PU_CACHE)); - V_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y, - W_CacheLumpName("tallylft", PU_CACHE)); - if (intertime < TALLY_EFFECT_TICKS) - { - showTotals = false; - scale = (intertime * FRACUNIT) / TALLY_EFFECT_TICKS; - xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA); - yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA); - xStart = TALLY_START_XPOS - FixedMul(scale, - TALLY_START_XPOS - - TALLY_STOP_XPOS); - yPos = - TALLY_START_YPOS - FixedMul(scale, - TALLY_START_YPOS - TALLY_STOP_YPOS); - } - else - { - xDelta = TALLY_FINAL_X_DELTA; - yDelta = TALLY_FINAL_Y_DELTA; - xStart = TALLY_STOP_XPOS; - yPos = TALLY_STOP_YPOS; - } - if (intertime >= TALLY_EFFECT_TICKS && showTotals == false) - { - showTotals = true; - S_StartSound(NULL, SFX_PLATFORM_STOP); - } - y = yPos >> FRACBITS; - for (i = 0; i < maxplayers; i++) - { - xPos = xStart; - for (j = 0; j < maxplayers; j++, xPos += xDelta) - { - x = xPos >> FRACBITS; - bold = (i == consoleplayer || j == consoleplayer); - if (playeringame[i] && playeringame[j]) - { - if (bold) - { - DrNumberBold(players[i].frags[j], x, y, 100); - } - else - { - DrNumber(players[i].frags[j], x, y, 100); - } - } - else - { - temp = MN_TextAWidth("--") / 2; - if (bold) - { - MN_DrTextAYellow("--", x - temp, y); - } - else - { - MN_DrTextA("--", x - temp, y); - } - } - } - if (showTotals && playeringame[i] - && !((slaughterboy & (1 << i)) && !(intertime & 16))) - { - DrNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000); - } - yPos += yDelta; - y = yPos >> FRACBITS; - } -} - -//========================================================================== -// -// DrNumber -// -//========================================================================== - -static void DrNumber(int val, int x, int y, int wrapThresh) -{ - char buff[8] = "XX"; - - if (!(val < -9 && wrapThresh < 1000)) - { - M_snprintf(buff, sizeof(buff), "%d", - val >= wrapThresh ? val % wrapThresh : val); - } - MN_DrTextA(buff, x - MN_TextAWidth(buff) / 2, y); -} - -//========================================================================== -// -// DrNumberBold -// -//========================================================================== - -static void DrNumberBold(int val, int x, int y, int wrapThresh) -{ - char buff[8] = "XX"; - - if (!(val < -9 && wrapThresh < 1000)) - { - M_snprintf(buff, sizeof(buff), "%d", - val >= wrapThresh ? val % wrapThresh : val); - } - MN_DrTextAYellow(buff, x - MN_TextAWidth(buff) / 2, y); -} - -//=========================================================================== -// -// DrawHubText -// -//=========================================================================== - -static void DrawHubText(void) -{ - int count; - char *ch; - int c; - int cx, cy; - patch_t *w; - - cy = 5; - cx = 10; - ch = HubText; - count = (intertime - 10) / TEXTSPEED; - if (count < 0) - { - count = 0; - } - for (; count; count--) - { - c = *ch++; - if (!c) - { - break; - } - if (c == '\n') - { - cx = 10; - cy += 9; - continue; - } - if (c < 32) - { - continue; - } - c = toupper(c); - if (c == 32) - { - cx += 5; - continue; - } - w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - if (cx + SHORT(w->width) > SCREENWIDTH) - { - break; - } - V_DrawPatch(cx, cy, w); - cx += SHORT(w->width); - } -} diff --git a/games/NXDoom/src/hexen/info.c b/games/NXDoom/src/hexen/info.c deleted file mode 100644 index ad579b629a5..00000000000 --- a/games/NXDoom/src/hexen/info.c +++ /dev/null @@ -1,13654 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -#include "h2def.h" -#include "i_swap.h" -#include "p_local.h" - -// generated by stateco - -const char *sprnames[] = { - "MAN1","ACLO","TLGL","FBL1","XPL1","ARRW","DART","RIPP","CFCF","BLAD", - "SHRD","FFSM","FFLG","PTN1","PTN2","SOAR","INVU","SUMN","TSPK","TELO", - "TRNG","ROCK","FOGS","FOGM","FOGL","SGSA","SGSB","PORK","EGGM","FHFX", - "SPHL","STWN","GMPD","ASKU","ABGM","AGMR","AGMG","AGG2","AGMB","AGB2", - "ABK1","ABK2","ASK2","AFWP","ACWP","AMWP","AGER","AGR2","AGR3","AGR4", - "TRCH","PSBG","ATLP","THRW","SPED","BMAN","BRAC","BLST","HRAD","SPSH", - "LVAS","SLDG","STTW","RCK1","RCK2","RCK3","RCK4","CDLR","TRE1","TRDT", - "TRE2","TRE3","STM1","STM2","STM3","STM4","MSH1","MSH2","MSH3","MSH4", - "MSH5","MSH6","MSH7","MSH8","SGMP","SGM1","SGM2","SGM3","SLC1","SLC2", - "SLC3","MSS1","MSS2","SWMV","CPS1","CPS2","TMS1","TMS2","TMS3","TMS4", - "TMS5","TMS6","TMS7","CPS3","STT2","STT3","STT4","STT5","GAR1","GAR2", - "GAR3","GAR4","GAR5","GAR6","GAR7","GAR8","GAR9","BNR1","TRE4","TRE5", - "TRE6","TRE7","LOGG","ICT1","ICT2","ICT3","ICT4","ICM1","ICM2","ICM3", - "ICM4","RKBL","RKBS","RKBK","RBL1","RBL2","RBL3","VASE","POT1","POT2", - "POT3","PBIT","CPS4","CPS5","CPS6","CPB1","CPB2","CPB3","CPB4","BDRP", - "BDSH","BDPL","CNDL","LEF1","LEF3","LEF2","TWTR","WLTR","BARL","SHB1", - "SHB2","BCKT","SHRM","FBUL","FSKL","BRTR","SUIT","BBLL","CAND","IRON", - "XMAS","CDRN","CHNS","TST1","TST2","TST3","TST4","TST5","TST6","TST7", - "TST8","TST9","TST0","TELE","TSMK","FPCH","WFAX","FAXE","WFHM","FHMR", - "FSRD","FSFX","CMCE","WCSS","CSSF","WCFM","CFLM","CFFX","CHLY","SPIR", - "MWND","WMLG","MLNG","MLFX","MLF2","MSTF","MSP1","MSP2","WFR1","WFR2", - "WFR3","WCH1","WCH2","WCH3","WMS1","WMS2","WMS3","WPIG","WMCS","CONE", - "SHEX","BLOD","GIBS","PLAY","FDTH","BSKL","ICEC","CLER","MAGE","PIGY", - "CENT","CTXD","CTFX","CTDP","DEMN","DEMA","DEMB","DEMC","DEMD","DEME", - "DMFX","DEM2","DMBA","DMBB","DMBC","DMBD","DMBE","D2FX","WRTH","WRT2", - "WRBL","MNTR","FX12","FX13","MNSM","SSPT","SSDV","SSXD","SSFX","BISH", - "BPFX","DRAG","DRFX","ARM1","ARM2","ARM3","ARM4","MAN2","MAN3","KEY1", - "KEY2","KEY3","KEY4","KEY5","KEY6","KEY7","KEY8","KEY9","KEYA","KEYB", - "ETTN","ETTB","FDMN","FDMB","ICEY","ICPR","ICWS","SORC","SBMP","SBS4", - "SBMB","SBS3","SBMG","SBS1","SBS2","SBFX","RADE","WATR","KORX","ABAT", - NULL -}; - - -state_t states[NUMSTATES] = { - {SPR_MAN1, 0, -1, NULL, S_NULL, 0, 0}, // S_NULL - {SPR_ACLO, 4, 1050, A_FreeTargMobj, S_NULL, 0, 0}, // S_FREETARGMOBJ - {SPR_TLGL, 0, -1, NULL, S_NULL, 0, 0}, // S_MAPSPOT - {SPR_FBL1, 32768, 4, NULL, S_FIREBALL1_2, 0, 0}, // S_FIREBALL1_1 - {SPR_FBL1, 32769, 4, NULL, S_FIREBALL1_1, 0, 0}, // S_FIREBALL1_2 - {SPR_XPL1, 32768, 4, NULL, S_FIREBALL1_X2, 0, 0}, // S_FIREBALL1_X1 - {SPR_XPL1, 32769, 4, NULL, S_FIREBALL1_X3, 0, 0}, // S_FIREBALL1_X2 - {SPR_XPL1, 32770, 4, NULL, S_FIREBALL1_X4, 0, 0}, // S_FIREBALL1_X3 - {SPR_XPL1, 32771, 4, NULL, S_FIREBALL1_X5, 0, 0}, // S_FIREBALL1_X4 - {SPR_XPL1, 32772, 4, NULL, S_FIREBALL1_X6, 0, 0}, // S_FIREBALL1_X5 - {SPR_XPL1, 32773, 4, NULL, S_NULL, 0, 0}, // S_FIREBALL1_X6 - {SPR_ARRW, 0, -1, NULL, S_NULL, 0, 0}, // S_ARROW_1 - {SPR_ARRW, 0, 1, NULL, S_NULL, 0, 0}, // S_ARROW_X1 - {SPR_DART, 0, -1, NULL, S_NULL, 0, 0}, // S_DART_1 - {SPR_DART, 0, 1, NULL, S_NULL, 0, 0}, // S_DART_X1 - {SPR_DART, 0, -1, NULL, S_NULL, 0, 0}, // S_POISONDART_1 - {SPR_DART, 0, 1, NULL, S_NULL, 0, 0}, // S_POISONDART_X1 - {SPR_RIPP, 0, 3, NULL, S_RIPPERBALL_2, 0, 0}, // S_RIPPERBALL_1 - {SPR_RIPP, 1, 3, NULL, S_RIPPERBALL_3, 0, 0}, // S_RIPPERBALL_2 - {SPR_RIPP, 2, 3, NULL, S_RIPPERBALL_1, 0, 0}, // S_RIPPERBALL_3 - {SPR_CFCF, 32784, 4, NULL, S_RIPPERBALL_X2, 0, 0}, // S_RIPPERBALL_X1 - {SPR_CFCF, 32785, 3, NULL, S_RIPPERBALL_X3, 0, 0}, // S_RIPPERBALL_X2 - {SPR_CFCF, 32786, 4, NULL, S_RIPPERBALL_X4, 0, 0}, // S_RIPPERBALL_X3 - {SPR_CFCF, 32787, 3, NULL, S_RIPPERBALL_X5, 0, 0}, // S_RIPPERBALL_X4 - {SPR_CFCF, 32788, 4, NULL, S_RIPPERBALL_X6, 0, 0}, // S_RIPPERBALL_X5 - {SPR_CFCF, 32789, 3, NULL, S_RIPPERBALL_X7, 0, 0}, // S_RIPPERBALL_X6 - {SPR_CFCF, 32790, 4, NULL, S_RIPPERBALL_X8, 0, 0}, // S_RIPPERBALL_X7 - {SPR_CFCF, 32791, 3, NULL, S_RIPPERBALL_X9, 0, 0}, // S_RIPPERBALL_X8 - {SPR_CFCF, 32792, 4, NULL, S_RIPPERBALL_X10, 0, 0}, // S_RIPPERBALL_X9 - {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_RIPPERBALL_X10 - {SPR_BLAD, 0, -1, NULL, S_NULL, 0, 0}, // S_PRJ_BLADE1 - {SPR_BLAD, 0, 1, NULL, S_NULL, 0, 0}, // S_PRJ_BLADE_X1 - {SPR_SHRD, 32768, 3, NULL, S_ICESHARD2, 0, 0}, // S_ICESHARD1 - {SPR_SHRD, 32769, 3, NULL, S_ICESHARD3, 0, 0}, // S_ICESHARD2 - {SPR_SHRD, 32770, 3, NULL, S_ICESHARD1, 0, 0}, // S_ICESHARD3 - {SPR_FFSM, 32768, 3, NULL, S_FLAME_TSMALL2, 0, 0}, // S_FLAME_TSMALL1 - {SPR_FFSM, 32769, 3, NULL, S_FLAME_TSMALL3, 0, 0}, // S_FLAME_TSMALL2 - {SPR_FFSM, 32770, 2, A_FlameCheck, S_FLAME_TSMALL4, 0, 0}, // S_FLAME_TSMALL3 - {SPR_FFSM, 32770, 2, NULL, S_FLAME_TSMALL5, 0, 0}, // S_FLAME_TSMALL4 - {SPR_FFSM, 32771, 3, NULL, S_FLAME_TSMALL6, 0, 0}, // S_FLAME_TSMALL5 - {SPR_FFSM, 32772, 3, A_FlameCheck, S_FLAME_TSMALL1, 0, 0}, // S_FLAME_TSMALL6 - {SPR_FFLG, 32768, 4, NULL, S_FLAME_TLARGE2, 0, 0}, // S_FLAME_TLARGE1 - {SPR_FFLG, 32769, 4, A_FlameCheck, S_FLAME_TLARGE3, 0, 0}, // S_FLAME_TLARGE2 - {SPR_FFLG, 32770, 4, NULL, S_FLAME_TLARGE4, 0, 0}, // S_FLAME_TLARGE3 - {SPR_FFLG, 32771, 4, A_FlameCheck, S_FLAME_TLARGE5, 0, 0}, // S_FLAME_TLARGE4 - {SPR_FFLG, 32772, 4, NULL, S_FLAME_TLARGE6, 0, 0}, // S_FLAME_TLARGE5 - {SPR_FFLG, 32773, 4, A_FlameCheck, S_FLAME_TLARGE7, 0, 0}, // S_FLAME_TLARGE6 - {SPR_FFLG, 32774, 4, NULL, S_FLAME_TLARGE8, 0, 0}, // S_FLAME_TLARGE7 - {SPR_FFLG, 32775, 4, A_FlameCheck, S_FLAME_TLARGE9, 0, 0}, // S_FLAME_TLARGE8 - {SPR_FFLG, 32776, 4, NULL, S_FLAME_TLARGE10, 0, 0}, // S_FLAME_TLARGE9 - {SPR_FFLG, 32777, 4, A_FlameCheck, S_FLAME_TLARGE11, 0, 0}, // S_FLAME_TLARGE10 - {SPR_FFLG, 32778, 4, NULL, S_FLAME_TLARGE12, 0, 0}, // S_FLAME_TLARGE11 - {SPR_FFLG, 32779, 4, A_FlameCheck, S_FLAME_TLARGE13, 0, 0}, // S_FLAME_TLARGE12 - {SPR_FFLG, 32780, 4, NULL, S_FLAME_TLARGE14, 0, 0}, // S_FLAME_TLARGE13 - {SPR_FFLG, 32781, 4, A_FlameCheck, S_FLAME_TLARGE15, 0, 0}, // S_FLAME_TLARGE14 - {SPR_FFLG, 32782, 4, NULL, S_FLAME_TLARGE16, 0, 0}, // S_FLAME_TLARGE15 - {SPR_FFLG, 32783, 4, A_FlameCheck, S_FLAME_TLARGE5, 0, 0}, // S_FLAME_TLARGE16 - {SPR_FFSM, 0, 2, NULL, S_FLAME_SDORM2, 0, 0}, // S_FLAME_SDORM1 - {SPR_FFSM, 1, 2, A_HideThing, S_FLAME_SDORM3, 0, 0}, // S_FLAME_SDORM2 - {SPR_FFSM, 2, 200, NULL, S_FLAME_SDORM3, 0, 0}, // S_FLAME_SDORM3 - {SPR_FFSM, 32768, 3, NULL, S_FLAME_SMALL2, 0, 0}, // S_FLAME_SMALL1 - {SPR_FFSM, 32768, 3, A_UnHideThing, S_FLAME_SMALL3, 0, 0}, // S_FLAME_SMALL2 - {SPR_FFSM, 32768, 3, NULL, S_FLAME_SMALL4, 0, 0}, // S_FLAME_SMALL3 - {SPR_FFSM, 32769, 3, NULL, S_FLAME_SMALL5, 0, 0}, // S_FLAME_SMALL4 - {SPR_FFSM, 32770, 3, NULL, S_FLAME_SMALL6, 0, 0}, // S_FLAME_SMALL5 - {SPR_FFSM, 32771, 3, NULL, S_FLAME_SMALL7, 0, 0}, // S_FLAME_SMALL6 - {SPR_FFSM, 32772, 3, NULL, S_FLAME_SMALL3, 0, 0}, // S_FLAME_SMALL7 - {SPR_FFLG, 3, 2, NULL, S_FLAME_LDORM2, 0, 0}, // S_FLAME_LDORM1 - {SPR_FFLG, 2, 2, NULL, S_FLAME_LDORM3, 0, 0}, // S_FLAME_LDORM2 - {SPR_FFLG, 1, 2, NULL, S_FLAME_LDORM4, 0, 0}, // S_FLAME_LDORM3 - {SPR_FFLG, 0, 2, A_HideThing, S_FLAME_LDORM5, 0, 0}, // S_FLAME_LDORM4 - {SPR_FFLG, 0, 200, NULL, S_FLAME_LDORM5, 0, 0}, // S_FLAME_LDORM5 - {SPR_FFLG, 32768, 2, NULL, S_FLAME_LARGE2, 0, 0}, // S_FLAME_LARGE1 - {SPR_FFLG, 32768, 2, A_UnHideThing, S_FLAME_LARGE3, 0, 0}, // S_FLAME_LARGE2 - {SPR_FFLG, 32768, 4, NULL, S_FLAME_LARGE4, 0, 0}, // S_FLAME_LARGE3 - {SPR_FFLG, 32769, 4, NULL, S_FLAME_LARGE5, 0, 0}, // S_FLAME_LARGE4 - {SPR_FFLG, 32770, 4, NULL, S_FLAME_LARGE6, 0, 0}, // S_FLAME_LARGE5 - {SPR_FFLG, 32771, 4, NULL, S_FLAME_LARGE7, 0, 0}, // S_FLAME_LARGE6 - {SPR_FFLG, 32772, 4, NULL, S_FLAME_LARGE8, 0, 0}, // S_FLAME_LARGE7 - {SPR_FFLG, 32773, 4, NULL, S_FLAME_LARGE9, 0, 0}, // S_FLAME_LARGE8 - {SPR_FFLG, 32774, 4, NULL, S_FLAME_LARGE10, 0, 0}, // S_FLAME_LARGE9 - {SPR_FFLG, 32775, 4, NULL, S_FLAME_LARGE11, 0, 0}, // S_FLAME_LARGE10 - {SPR_FFLG, 32776, 4, NULL, S_FLAME_LARGE12, 0, 0}, // S_FLAME_LARGE11 - {SPR_FFLG, 32777, 4, NULL, S_FLAME_LARGE13, 0, 0}, // S_FLAME_LARGE12 - {SPR_FFLG, 32778, 4, NULL, S_FLAME_LARGE14, 0, 0}, // S_FLAME_LARGE13 - {SPR_FFLG, 32779, 4, NULL, S_FLAME_LARGE15, 0, 0}, // S_FLAME_LARGE14 - {SPR_FFLG, 32780, 4, NULL, S_FLAME_LARGE16, 0, 0}, // S_FLAME_LARGE15 - {SPR_FFLG, 32781, 4, NULL, S_FLAME_LARGE17, 0, 0}, // S_FLAME_LARGE16 - {SPR_FFLG, 32782, 4, NULL, S_FLAME_LARGE18, 0, 0}, // S_FLAME_LARGE17 - {SPR_FFLG, 32783, 4, NULL, S_FLAME_LARGE7, 0, 0}, // S_FLAME_LARGE18 - {SPR_PTN1, 0, 3, NULL, S_ITEM_PTN1_2, 0, 0}, // S_ITEM_PTN1_1 - {SPR_PTN1, 1, 3, NULL, S_ITEM_PTN1_3, 0, 0}, // S_ITEM_PTN1_2 - {SPR_PTN1, 2, 3, NULL, S_ITEM_PTN1_1, 0, 0}, // S_ITEM_PTN1_3 - {SPR_ACLO, 4, 1400, NULL, S_HIDESPECIAL2, 0, 0}, // S_HIDESPECIAL1 - {SPR_ACLO, 0, 4, A_RestoreSpecialThing1, S_HIDESPECIAL3, 0, 0}, // S_HIDESPECIAL2 - {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL4, 0, 0}, // S_HIDESPECIAL3 - {SPR_ACLO, 0, 4, NULL, S_HIDESPECIAL5, 0, 0}, // S_HIDESPECIAL4 - {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL6, 0, 0}, // S_HIDESPECIAL5 - {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL7, 0, 0}, // S_HIDESPECIAL6 - {SPR_ACLO, 1, 4, NULL, S_HIDESPECIAL8, 0, 0}, // S_HIDESPECIAL7 - {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL9, 0, 0}, // S_HIDESPECIAL8 - {SPR_ACLO, 3, 4, NULL, S_HIDESPECIAL10, 0, 0}, // S_HIDESPECIAL9 - {SPR_ACLO, 2, 4, NULL, S_HIDESPECIAL11, 0, 0}, // S_HIDESPECIAL10 - {SPR_ACLO, 3, 4, A_RestoreSpecialThing2, S_NULL, 0, 0}, // S_HIDESPECIAL11 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI1_2, 0, 0}, // S_DORMANTARTI1_1 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_3, 0, 0}, // S_DORMANTARTI1_2 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI1_4, 0, 0}, // S_DORMANTARTI1_3 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_5, 0, 0}, // S_DORMANTARTI1_4 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_6, 0, 0}, // S_DORMANTARTI1_5 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_7, 0, 0}, // S_DORMANTARTI1_6 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_8, 0, 0}, // S_DORMANTARTI1_7 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI1_9, 0, 0}, // S_DORMANTARTI1_8 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_10, 0, 0}, // S_DORMANTARTI1_9 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI1_11, 0, 0}, // S_DORMANTARTI1_10 - {SPR_ACLO, 0, 1400, A_HideThing, S_DORMANTARTI1_12, 0, 0}, // S_DORMANTARTI1_11 - {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI1_13, 0, 0}, // S_DORMANTARTI1_12 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_14, 0, 0}, // S_DORMANTARTI1_13 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI1_15, 0, 0}, // S_DORMANTARTI1_14 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_16, 0, 0}, // S_DORMANTARTI1_15 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_17, 0, 0}, // S_DORMANTARTI1_16 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI1_18, 0, 0}, // S_DORMANTARTI1_17 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_19, 0, 0}, // S_DORMANTARTI1_18 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI1_20, 0, 0}, // S_DORMANTARTI1_19 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI1_21, 0, 0}, // S_DORMANTARTI1_20 - {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI1_21 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2_2, 0, 0}, // S_DORMANTARTI2_1 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_3, 0, 0}, // S_DORMANTARTI2_2 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2_4, 0, 0}, // S_DORMANTARTI2_3 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_5, 0, 0}, // S_DORMANTARTI2_4 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_6, 0, 0}, // S_DORMANTARTI2_5 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_7, 0, 0}, // S_DORMANTARTI2_6 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_8, 0, 0}, // S_DORMANTARTI2_7 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI2_9, 0, 0}, // S_DORMANTARTI2_8 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_10, 0, 0}, // S_DORMANTARTI2_9 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI2_11, 0, 0}, // S_DORMANTARTI2_10 - {SPR_ACLO, 0, 4200, A_HideThing, S_DORMANTARTI2_12, 0, 0}, // S_DORMANTARTI2_11 - {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI2_13, 0, 0}, // S_DORMANTARTI2_12 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_14, 0, 0}, // S_DORMANTARTI2_13 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI2_15, 0, 0}, // S_DORMANTARTI2_14 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_16, 0, 0}, // S_DORMANTARTI2_15 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_17, 0, 0}, // S_DORMANTARTI2_16 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI2_18, 0, 0}, // S_DORMANTARTI2_17 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_19, 0, 0}, // S_DORMANTARTI2_18 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI2_20, 0, 0}, // S_DORMANTARTI2_19 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI2_21, 0, 0}, // S_DORMANTARTI2_20 - {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI2_21 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI3_2, 0, 0}, // S_DORMANTARTI3_1 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_3, 0, 0}, // S_DORMANTARTI3_2 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI3_4, 0, 0}, // S_DORMANTARTI3_3 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_5, 0, 0}, // S_DORMANTARTI3_4 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_6, 0, 0}, // S_DORMANTARTI3_5 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_7, 0, 0}, // S_DORMANTARTI3_6 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_8, 0, 0}, // S_DORMANTARTI3_7 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI3_9, 0, 0}, // S_DORMANTARTI3_8 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_10, 0, 0}, // S_DORMANTARTI3_9 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI3_11, 0, 0}, // S_DORMANTARTI3_10 - {SPR_ACLO, 0, 21000, A_HideThing, S_DORMANTARTI3_12, 0, 0}, // S_DORMANTARTI3_11 - {SPR_ACLO, 0, 3, A_UnHideThing, S_DORMANTARTI3_13, 0, 0}, // S_DORMANTARTI3_12 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_14, 0, 0}, // S_DORMANTARTI3_13 - {SPR_ACLO, 0, 3, NULL, S_DORMANTARTI3_15, 0, 0}, // S_DORMANTARTI3_14 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_16, 0, 0}, // S_DORMANTARTI3_15 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_17, 0, 0}, // S_DORMANTARTI3_16 - {SPR_ACLO, 1, 3, NULL, S_DORMANTARTI3_18, 0, 0}, // S_DORMANTARTI3_17 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_19, 0, 0}, // S_DORMANTARTI3_18 - {SPR_ACLO, 3, 3, NULL, S_DORMANTARTI3_20, 0, 0}, // S_DORMANTARTI3_19 - {SPR_ACLO, 2, 3, NULL, S_DORMANTARTI3_21, 0, 0}, // S_DORMANTARTI3_20 - {SPR_ACLO, 3, 3, A_RestoreArtifact, S_NULL, 0, 0}, // S_DORMANTARTI3_21 - {SPR_ACLO, 3, 3, NULL, S_DEADARTI2, 0, 0}, // S_DEADARTI1 - {SPR_ACLO, 2, 3, NULL, S_DEADARTI3, 0, 0}, // S_DEADARTI2 - {SPR_ACLO, 3, 3, NULL, S_DEADARTI4, 0, 0}, // S_DEADARTI3 - {SPR_ACLO, 2, 3, NULL, S_DEADARTI5, 0, 0}, // S_DEADARTI4 - {SPR_ACLO, 1, 3, NULL, S_DEADARTI6, 0, 0}, // S_DEADARTI5 - {SPR_ACLO, 2, 3, NULL, S_DEADARTI7, 0, 0}, // S_DEADARTI6 - {SPR_ACLO, 1, 3, NULL, S_DEADARTI8, 0, 0}, // S_DEADARTI7 - {SPR_ACLO, 0, 3, NULL, S_DEADARTI9, 0, 0}, // S_DEADARTI8 - {SPR_ACLO, 1, 3, NULL, S_DEADARTI10, 0, 0}, // S_DEADARTI9 - {SPR_ACLO, 0, 3, NULL, S_NULL, 0, 0}, // S_DEADARTI10 - {SPR_PTN2, 0, 4, NULL, S_ARTI_PTN2_2, 0, 0}, // S_ARTI_PTN2_1 - {SPR_PTN2, 1, 4, NULL, S_ARTI_PTN2_3, 0, 0}, // S_ARTI_PTN2_2 - {SPR_PTN2, 2, 4, NULL, S_ARTI_PTN2_1, 0, 0}, // S_ARTI_PTN2_3 - {SPR_SOAR, 0, 5, NULL, S_ARTI_SOAR2, 0, 0}, // S_ARTI_SOAR1 - {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR3, 0, 0}, // S_ARTI_SOAR2 - {SPR_SOAR, 2, 5, NULL, S_ARTI_SOAR4, 0, 0}, // S_ARTI_SOAR3 - {SPR_SOAR, 1, 5, NULL, S_ARTI_SOAR1, 0, 0}, // S_ARTI_SOAR4 - {SPR_INVU, 0, 3, NULL, S_ARTI_INVU2, 0, 0}, // S_ARTI_INVU1 - {SPR_INVU, 1, 3, NULL, S_ARTI_INVU3, 0, 0}, // S_ARTI_INVU2 - {SPR_INVU, 2, 3, NULL, S_ARTI_INVU4, 0, 0}, // S_ARTI_INVU3 - {SPR_INVU, 3, 3, NULL, S_ARTI_INVU1, 0, 0}, // S_ARTI_INVU4 - {SPR_SUMN, 0, 350, NULL, S_ARTI_SUMMON, 0, 0}, // S_ARTI_SUMMON - {SPR_SUMN, 0, 4, NULL, S_SUMMON_FX1_1, 0, 0}, // S_SUMMON_FX1_1 - {SPR_SUMN, 0, 4, NULL, S_SUMMON_FX2_2, 0, 0}, // S_SUMMON_FX2_1 - {SPR_SUMN, 0, 4, NULL, S_SUMMON_FX2_3, 0, 0}, // S_SUMMON_FX2_2 - {SPR_SUMN, 0, 4, A_Summon, S_NULL, 0, 0}, // S_SUMMON_FX2_3 - {SPR_TSPK, 0, 3, NULL, S_THRUSTINIT2_2, 0, 0}, // S_THRUSTINIT2_1 - {SPR_TSPK, 0, 4, A_ThrustInitUp, S_THRUSTBLOCK, 0, 0}, // S_THRUSTINIT2_2 - {SPR_TSPK, 1, 3, NULL, S_BTHRUSTINIT2_2, 0, 0}, // S_BTHRUSTINIT2_1 - {SPR_TSPK, 1, 4, A_ThrustInitUp, S_BTHRUSTBLOCK, 0, 0}, // S_BTHRUSTINIT2_2 - {SPR_TSPK, 0, 3, NULL, S_THRUSTINIT1_2, 0, 0}, // S_THRUSTINIT1_1 - {SPR_TSPK, 0, 4, A_ThrustInitDn, S_THRUSTSTAY, 0, 0}, // S_THRUSTINIT1_2 - {SPR_TSPK, 1, 3, NULL, S_BTHRUSTINIT1_2, 0, 0}, // S_BTHRUSTINIT1_1 - {SPR_TSPK, 1, 4, A_ThrustInitDn, S_BTHRUSTSTAY, 0, 0}, // S_BTHRUSTINIT1_2 - {SPR_TSPK, 0, 8, A_ThrustRaise, S_THRUSTRAISE2, 0, 0}, // S_THRUSTRAISE1 - {SPR_TSPK, 0, 6, A_ThrustRaise, S_THRUSTRAISE3, 0, 0}, // S_THRUSTRAISE2 - {SPR_TSPK, 0, 4, A_ThrustRaise, S_THRUSTRAISE4, 0, 0}, // S_THRUSTRAISE3 - {SPR_TSPK, 0, 3, A_ThrustBlock, S_THRUSTIMPALE, 0, 0}, // S_THRUSTRAISE4 - {SPR_TSPK, 1, 8, A_ThrustRaise, S_BTHRUSTRAISE2, 0, 0}, // S_BTHRUSTRAISE1 - {SPR_TSPK, 1, 6, A_ThrustRaise, S_BTHRUSTRAISE3, 0, 0}, // S_BTHRUSTRAISE2 - {SPR_TSPK, 1, 4, A_ThrustRaise, S_BTHRUSTRAISE4, 0, 0}, // S_BTHRUSTRAISE3 - {SPR_TSPK, 1, 3, A_ThrustBlock, S_BTHRUSTIMPALE, 0, 0}, // S_BTHRUSTRAISE4 - {SPR_TSPK, 0, 2, A_ThrustImpale, S_THRUSTRAISE, 0, 0}, // S_THRUSTIMPALE - {SPR_TSPK, 1, 2, A_ThrustImpale, S_BTHRUSTRAISE, 0, 0}, // S_BTHRUSTIMPALE - {SPR_TSPK, 0, 2, A_ThrustRaise, S_THRUSTRAISE, 0, 0}, // S_THRUSTRAISE - {SPR_TSPK, 1, 2, A_ThrustRaise, S_BTHRUSTRAISE, 0, 0}, // S_BTHRUSTRAISE - {SPR_TSPK, 0, 10, NULL, S_THRUSTBLOCK, 0, 0}, // S_THRUSTBLOCK - {SPR_TSPK, 1, 10, NULL, S_BTHRUSTBLOCK, 0, 0}, // S_BTHRUSTBLOCK - {SPR_TSPK, 0, 2, A_ThrustLower, S_THRUSTLOWER, 0, 0}, // S_THRUSTLOWER - {SPR_TSPK, 1, 2, A_ThrustLower, S_BTHRUSTLOWER, 0, 0}, // S_BTHRUSTLOWER - {SPR_TSPK, 0, -1, NULL, S_THRUSTSTAY, 0, 0}, // S_THRUSTSTAY - {SPR_TSPK, 1, -1, NULL, S_BTHRUSTSTAY, 0, 0}, // S_BTHRUSTSTAY - {SPR_TELO, 0, 5, NULL, S_ARTI_TELOTHER2, 0, 0}, // S_ARTI_TELOTHER1 - {SPR_TELO, 1, 5, NULL, S_ARTI_TELOTHER3, 0, 0}, // S_ARTI_TELOTHER2 - {SPR_TELO, 2, 5, NULL, S_ARTI_TELOTHER4, 0, 0}, // S_ARTI_TELOTHER3 - {SPR_TELO, 3, 5, NULL, S_ARTI_TELOTHER1, 0, 0}, // S_ARTI_TELOTHER4 - {SPR_TRNG, 32772, 5, NULL, S_TELO_FX2, 0, 0}, // S_TELO_FX1 - {SPR_TRNG, 32771, 4, NULL, S_TELO_FX3, 0, 0}, // S_TELO_FX2 - {SPR_TRNG, 32770, 3, A_TeloSpawnC, S_TELO_FX4, 0, 0}, // S_TELO_FX3 - {SPR_TRNG, 32769, 3, A_TeloSpawnB, S_TELO_FX5, 0, 0}, // S_TELO_FX4 - {SPR_TRNG, 32768, 3, A_TeloSpawnA, S_TELO_FX6, 0, 0}, // S_TELO_FX5 - {SPR_TRNG, 32769, 3, A_TeloSpawnB, S_TELO_FX7, 0, 0}, // S_TELO_FX6 - {SPR_TRNG, 32770, 3, A_TeloSpawnC, S_TELO_FX8, 0, 0}, // S_TELO_FX7 - {SPR_TRNG, 32771, 3, A_TeloSpawnD, S_TELO_FX3, 0, 0}, // S_TELO_FX8 - {SPR_TRNG, 32772, 3, NULL, S_NULL, 0, 0}, // S_TELO_FX9 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX2_2, 0, 0}, // S_TELO_FX2_1 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX2_3, 0, 0}, // S_TELO_FX2_2 - {SPR_TRNG, 32771, 4, NULL, S_TELO_FX2_4, 0, 0}, // S_TELO_FX2_3 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX2_5, 0, 0}, // S_TELO_FX2_4 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX2_6, 0, 0}, // S_TELO_FX2_5 - {SPR_TRNG, 32768, 4, A_CheckTeleRing, S_TELO_FX2_1, 0, 0}, // S_TELO_FX2_6 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX3_2, 0, 0}, // S_TELO_FX3_1 - {SPR_TRNG, 32771, 4, NULL, S_TELO_FX3_3, 0, 0}, // S_TELO_FX3_2 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX3_4, 0, 0}, // S_TELO_FX3_3 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX3_5, 0, 0}, // S_TELO_FX3_4 - {SPR_TRNG, 32768, 4, NULL, S_TELO_FX3_6, 0, 0}, // S_TELO_FX3_5 - {SPR_TRNG, 32769, 4, A_CheckTeleRing, S_TELO_FX3_1, 0, 0}, // S_TELO_FX3_6 - {SPR_TRNG, 32771, 4, NULL, S_TELO_FX4_2, 0, 0}, // S_TELO_FX4_1 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX4_3, 0, 0}, // S_TELO_FX4_2 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX4_4, 0, 0}, // S_TELO_FX4_3 - {SPR_TRNG, 32768, 4, NULL, S_TELO_FX4_5, 0, 0}, // S_TELO_FX4_4 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX4_6, 0, 0}, // S_TELO_FX4_5 - {SPR_TRNG, 32770, 4, A_CheckTeleRing, S_TELO_FX4_1, 0, 0}, // S_TELO_FX4_6 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX5_2, 0, 0}, // S_TELO_FX5_1 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX5_3, 0, 0}, // S_TELO_FX5_2 - {SPR_TRNG, 32768, 4, NULL, S_TELO_FX5_4, 0, 0}, // S_TELO_FX5_3 - {SPR_TRNG, 32769, 4, NULL, S_TELO_FX5_5, 0, 0}, // S_TELO_FX5_4 - {SPR_TRNG, 32770, 4, NULL, S_TELO_FX5_6, 0, 0}, // S_TELO_FX5_5 - {SPR_TRNG, 32771, 4, A_CheckTeleRing, S_TELO_FX5_1, 0, 0}, // S_TELO_FX5_6 - {SPR_ROCK, 3, 20, NULL, S_DIRT1_1, 0, 0}, // S_DIRT1_1 - {SPR_ROCK, 3, 10, NULL, S_NULL, 0, 0}, // S_DIRT1_D - {SPR_ROCK, 4, 20, NULL, S_DIRT2_1, 0, 0}, // S_DIRT2_1 - {SPR_ROCK, 4, 10, NULL, S_NULL, 0, 0}, // S_DIRT2_D - {SPR_ROCK, 5, 20, NULL, S_DIRT3_1, 0, 0}, // S_DIRT3_1 - {SPR_ROCK, 5, 10, NULL, S_NULL, 0, 0}, // S_DIRT3_D - {SPR_ROCK, 6, 20, NULL, S_DIRT4_1, 0, 0}, // S_DIRT4_1 - {SPR_ROCK, 6, 10, NULL, S_NULL, 0, 0}, // S_DIRT4_D - {SPR_ROCK, 7, 20, NULL, S_DIRT5_1, 0, 0}, // S_DIRT5_1 - {SPR_ROCK, 7, 10, NULL, S_NULL, 0, 0}, // S_DIRT5_D - {SPR_ROCK, 8, 20, NULL, S_DIRT6_1, 0, 0}, // S_DIRT6_1 - {SPR_ROCK, 8, 10, NULL, S_NULL, 0, 0}, // S_DIRT6_D - {SPR_TSPK, 2, 20, NULL, S_DIRTCLUMP1, 0, 0}, // S_DIRTCLUMP1 - {SPR_ROCK, 0, 20, NULL, S_ROCK1_1, 0, 0}, // S_ROCK1_1 - {SPR_ROCK, 0, 10, NULL, S_NULL, 0, 0}, // S_ROCK1_D - {SPR_ROCK, 1, 20, NULL, S_ROCK2_1, 0, 0}, // S_ROCK2_1 - {SPR_ROCK, 1, 10, NULL, S_NULL, 0, 0}, // S_ROCK2_D - {SPR_ROCK, 2, 20, NULL, S_ROCK3_1, 0, 0}, // S_ROCK3_1 - {SPR_ROCK, 2, 10, NULL, S_NULL, 0, 0}, // S_ROCK3_D - {SPR_MAN1, 0, 20, A_FogSpawn, S_SPAWNFOG1, 0, 0}, // S_SPAWNFOG1 - {SPR_FOGS, 0, 7, A_FogMove, S_FOGPATCHS2, 0, 0}, // S_FOGPATCHS1 - {SPR_FOGS, 1, 7, A_FogMove, S_FOGPATCHS3, 0, 0}, // S_FOGPATCHS2 - {SPR_FOGS, 2, 7, A_FogMove, S_FOGPATCHS4, 0, 0}, // S_FOGPATCHS3 - {SPR_FOGS, 3, 7, A_FogMove, S_FOGPATCHS5, 0, 0}, // S_FOGPATCHS4 - {SPR_FOGS, 4, 7, A_FogMove, S_FOGPATCHS1, 0, 0}, // S_FOGPATCHS5 - {SPR_FOGS, 4, 5, NULL, S_NULL, 0, 0}, // S_FOGPATCHS0 - {SPR_FOGM, 0, 7, A_FogMove, S_FOGPATCHM2, 0, 0}, // S_FOGPATCHM1 - {SPR_FOGM, 1, 7, A_FogMove, S_FOGPATCHM3, 0, 0}, // S_FOGPATCHM2 - {SPR_FOGM, 2, 7, A_FogMove, S_FOGPATCHM4, 0, 0}, // S_FOGPATCHM3 - {SPR_FOGM, 3, 7, A_FogMove, S_FOGPATCHM5, 0, 0}, // S_FOGPATCHM4 - {SPR_FOGM, 4, 7, A_FogMove, S_FOGPATCHM1, 0, 0}, // S_FOGPATCHM5 - {SPR_FOGS, 0, 5, NULL, S_FOGPATCHMA, 0, 0}, // S_FOGPATCHM0 - {SPR_FOGS, 1, 5, NULL, S_FOGPATCHMB, 0, 0}, // S_FOGPATCHMA - {SPR_FOGS, 2, 5, NULL, S_FOGPATCHMC, 0, 0}, // S_FOGPATCHMB - {SPR_FOGS, 3, 5, NULL, S_FOGPATCHMD, 0, 0}, // S_FOGPATCHMC - {SPR_FOGS, 4, 5, NULL, S_FOGPATCHS0, 0, 0}, // S_FOGPATCHMD - {SPR_FOGL, 0, 7, A_FogMove, S_FOGPATCHL2, 0, 0}, // S_FOGPATCHL1 - {SPR_FOGL, 1, 7, A_FogMove, S_FOGPATCHL3, 0, 0}, // S_FOGPATCHL2 - {SPR_FOGL, 2, 7, A_FogMove, S_FOGPATCHL4, 0, 0}, // S_FOGPATCHL3 - {SPR_FOGL, 3, 7, A_FogMove, S_FOGPATCHL5, 0, 0}, // S_FOGPATCHL4 - {SPR_FOGL, 4, 7, A_FogMove, S_FOGPATCHL1, 0, 0}, // S_FOGPATCHL5 - {SPR_FOGM, 0, 4, NULL, S_FOGPATCHLA, 0, 0}, // S_FOGPATCHL0 - {SPR_FOGM, 1, 4, NULL, S_FOGPATCHLB, 0, 0}, // S_FOGPATCHLA - {SPR_FOGM, 2, 4, NULL, S_FOGPATCHLC, 0, 0}, // S_FOGPATCHLB - {SPR_FOGM, 3, 4, NULL, S_FOGPATCHLD, 0, 0}, // S_FOGPATCHLC - {SPR_FOGM, 4, 4, NULL, S_FOGPATCHM0, 0, 0}, // S_FOGPATCHLD - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE2, 0, 0}, // S_QUAKE_ACTIVE1 - {SPR_MAN1, 0, 1, A_ContMobjSound, S_QUAKE_ACTIVE3, 0, 0}, // S_QUAKE_ACTIVE2 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE4, 0, 0}, // S_QUAKE_ACTIVE3 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE5, 0, 0}, // S_QUAKE_ACTIVE4 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE6, 0, 0}, // S_QUAKE_ACTIVE5 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE7, 0, 0}, // S_QUAKE_ACTIVE6 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE8, 0, 0}, // S_QUAKE_ACTIVE7 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE9, 0, 0}, // S_QUAKE_ACTIVE8 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE0, 0, 0}, // S_QUAKE_ACTIVE9 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEA, 0, 0}, // S_QUAKE_ACTIVE0 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEB, 0, 0}, // S_QUAKE_ACTIVEA - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEC, 0, 0}, // S_QUAKE_ACTIVEB - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVED, 0, 0}, // S_QUAKE_ACTIVEC - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEE, 0, 0}, // S_QUAKE_ACTIVED - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEF, 0, 0}, // S_QUAKE_ACTIVEE - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEG, 0, 0}, // S_QUAKE_ACTIVEF - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEH, 0, 0}, // S_QUAKE_ACTIVEG - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEI, 0, 0}, // S_QUAKE_ACTIVEH - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEJ, 0, 0}, // S_QUAKE_ACTIVEI - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEK, 0, 0}, // S_QUAKE_ACTIVEJ - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEL, 0, 0}, // S_QUAKE_ACTIVEK - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEM, 0, 0}, // S_QUAKE_ACTIVEL - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEN, 0, 0}, // S_QUAKE_ACTIVEM - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEO, 0, 0}, // S_QUAKE_ACTIVEN - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEP, 0, 0}, // S_QUAKE_ACTIVEO - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEQ, 0, 0}, // S_QUAKE_ACTIVEP - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVER, 0, 0}, // S_QUAKE_ACTIVEQ - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVES, 0, 0}, // S_QUAKE_ACTIVER - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVET, 0, 0}, // S_QUAKE_ACTIVES - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEU, 0, 0}, // S_QUAKE_ACTIVET - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEV, 0, 0}, // S_QUAKE_ACTIVEU - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEW, 0, 0}, // S_QUAKE_ACTIVEV - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEX, 0, 0}, // S_QUAKE_ACTIVEW - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEY, 0, 0}, // S_QUAKE_ACTIVEX - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVEZ, 0, 0}, // S_QUAKE_ACTIVEY - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT1, 0, 0}, // S_QUAKE_ACTIVEZ - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT2, 0, 0}, // S_QUAKE_ACT1 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT3, 0, 0}, // S_QUAKE_ACT2 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT4, 0, 0}, // S_QUAKE_ACT3 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT5, 0, 0}, // S_QUAKE_ACT4 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT6, 0, 0}, // S_QUAKE_ACT5 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT7, 0, 0}, // S_QUAKE_ACT6 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT8, 0, 0}, // S_QUAKE_ACT7 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT9, 0, 0}, // S_QUAKE_ACT8 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACT0, 0, 0}, // S_QUAKE_ACT9 - {SPR_MAN1, 0, 2, A_Quake, S_QUAKE_ACTIVE1, 0, 0}, // S_QUAKE_ACT0 - {SPR_SGSA, 0, 4, NULL, S_SGSHARD1_2, 0, 0}, // S_SGSHARD1_1 - {SPR_SGSA, 1, 4, NULL, S_SGSHARD1_3, 0, 0}, // S_SGSHARD1_2 - {SPR_SGSA, 2, 4, NULL, S_SGSHARD1_4, 0, 0}, // S_SGSHARD1_3 - {SPR_SGSA, 3, 4, NULL, S_SGSHARD1_5, 0, 0}, // S_SGSHARD1_4 - {SPR_SGSA, 4, 4, NULL, S_SGSHARD1_1, 0, 0}, // S_SGSHARD1_5 - {SPR_SGSA, 4, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD1_D - {SPR_SGSA, 5, 4, NULL, S_SGSHARD2_2, 0, 0}, // S_SGSHARD2_1 - {SPR_SGSA, 6, 4, NULL, S_SGSHARD2_3, 0, 0}, // S_SGSHARD2_2 - {SPR_SGSA, 7, 4, NULL, S_SGSHARD2_4, 0, 0}, // S_SGSHARD2_3 - {SPR_SGSA, 8, 4, NULL, S_SGSHARD2_5, 0, 0}, // S_SGSHARD2_4 - {SPR_SGSA, 9, 4, NULL, S_SGSHARD2_1, 0, 0}, // S_SGSHARD2_5 - {SPR_SGSA, 9, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD2_D - {SPR_SGSA, 10, 4, NULL, S_SGSHARD3_2, 0, 0}, // S_SGSHARD3_1 - {SPR_SGSA, 11, 4, NULL, S_SGSHARD3_3, 0, 0}, // S_SGSHARD3_2 - {SPR_SGSA, 12, 4, NULL, S_SGSHARD3_4, 0, 0}, // S_SGSHARD3_3 - {SPR_SGSA, 13, 4, NULL, S_SGSHARD3_5, 0, 0}, // S_SGSHARD3_4 - {SPR_SGSA, 14, 4, NULL, S_SGSHARD3_1, 0, 0}, // S_SGSHARD3_5 - {SPR_SGSA, 14, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD3_D - {SPR_SGSA, 15, 4, NULL, S_SGSHARD4_2, 0, 0}, // S_SGSHARD4_1 - {SPR_SGSA, 16, 4, NULL, S_SGSHARD4_3, 0, 0}, // S_SGSHARD4_2 - {SPR_SGSA, 17, 4, NULL, S_SGSHARD4_4, 0, 0}, // S_SGSHARD4_3 - {SPR_SGSA, 18, 4, NULL, S_SGSHARD4_5, 0, 0}, // S_SGSHARD4_4 - {SPR_SGSA, 19, 4, NULL, S_SGSHARD4_1, 0, 0}, // S_SGSHARD4_5 - {SPR_SGSA, 19, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD4_D - {SPR_SGSA, 20, 4, NULL, S_SGSHARD5_2, 0, 0}, // S_SGSHARD5_1 - {SPR_SGSA, 21, 4, NULL, S_SGSHARD5_3, 0, 0}, // S_SGSHARD5_2 - {SPR_SGSA, 22, 4, NULL, S_SGSHARD5_4, 0, 0}, // S_SGSHARD5_3 - {SPR_SGSA, 23, 4, NULL, S_SGSHARD5_5, 0, 0}, // S_SGSHARD5_4 - {SPR_SGSA, 24, 4, NULL, S_SGSHARD5_1, 0, 0}, // S_SGSHARD5_5 - {SPR_SGSA, 24, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD5_D - {SPR_SGSB, 0, 4, NULL, S_SGSHARD6_1, 0, 0}, // S_SGSHARD6_1 - {SPR_SGSB, 0, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD6_D - {SPR_SGSB, 1, 4, NULL, S_SGSHARD7_1, 0, 0}, // S_SGSHARD7_1 - {SPR_SGSB, 1, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD7_D - {SPR_SGSB, 2, 4, NULL, S_SGSHARD8_1, 0, 0}, // S_SGSHARD8_1 - {SPR_SGSB, 2, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD8_D - {SPR_SGSB, 3, 4, NULL, S_SGSHARD9_1, 0, 0}, // S_SGSHARD9_1 - {SPR_SGSB, 3, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD9_D - {SPR_SGSB, 4, 4, NULL, S_SGSHARD0_1, 0, 0}, // S_SGSHARD0_1 - {SPR_SGSB, 4, 30, NULL, S_NULL, 0, 0}, // S_SGSHARD0_D - {SPR_PORK, 0, 5, NULL, S_ARTI_EGGC2, 0, 0}, // S_ARTI_EGGC1 - {SPR_PORK, 1, 5, NULL, S_ARTI_EGGC3, 0, 0}, // S_ARTI_EGGC2 - {SPR_PORK, 2, 5, NULL, S_ARTI_EGGC4, 0, 0}, // S_ARTI_EGGC3 - {SPR_PORK, 3, 5, NULL, S_ARTI_EGGC5, 0, 0}, // S_ARTI_EGGC4 - {SPR_PORK, 4, 5, NULL, S_ARTI_EGGC6, 0, 0}, // S_ARTI_EGGC5 - {SPR_PORK, 5, 5, NULL, S_ARTI_EGGC7, 0, 0}, // S_ARTI_EGGC6 - {SPR_PORK, 6, 5, NULL, S_ARTI_EGGC8, 0, 0}, // S_ARTI_EGGC7 - {SPR_PORK, 7, 5, NULL, S_ARTI_EGGC1, 0, 0}, // S_ARTI_EGGC8 - {SPR_EGGM, 0, 4, NULL, S_EGGFX2, 0, 0}, // S_EGGFX1 - {SPR_EGGM, 1, 4, NULL, S_EGGFX3, 0, 0}, // S_EGGFX2 - {SPR_EGGM, 2, 4, NULL, S_EGGFX4, 0, 0}, // S_EGGFX3 - {SPR_EGGM, 3, 4, NULL, S_EGGFX5, 0, 0}, // S_EGGFX4 - {SPR_EGGM, 4, 4, NULL, S_EGGFX1, 0, 0}, // S_EGGFX5 - {SPR_FHFX, 32776, 3, NULL, S_EGGFXI1_2, 0, 0}, // S_EGGFXI1_1 - {SPR_FHFX, 32777, 3, NULL, S_EGGFXI1_3, 0, 0}, // S_EGGFXI1_2 - {SPR_FHFX, 32778, 3, NULL, S_EGGFXI1_4, 0, 0}, // S_EGGFXI1_3 - {SPR_FHFX, 32779, 3, NULL, S_NULL, 0, 0}, // S_EGGFXI1_4 - {SPR_SPHL, 0, 350, NULL, S_ARTI_SPHL1, 0, 0}, // S_ARTI_SPHL1 - {SPR_STWN, 0, -1, NULL, S_NULL, 0, 0}, // S_ZWINGEDSTATUENOSKULL - {SPR_STWN, 1, -1, NULL, S_NULL, 0, 0}, // S_ZWINGEDSTATUENOSKULL2 - {SPR_GMPD, 0, -1, NULL, S_NULL, 0, 0}, // S_ZGEMPEDESTAL1 - {SPR_GMPD, 1, -1, NULL, S_NULL, 0, 0}, // S_ZGEMPEDESTAL2 - {SPR_ASKU, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZSKULL - {SPR_ABGM, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMBIG - {SPR_AGMR, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMRED - {SPR_AGMG, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMGREEN1 - {SPR_AGG2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMGREEN2 - {SPR_AGMB, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMBLUE1 - {SPR_AGB2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZGEMBLUE2 - {SPR_ABK1, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZBOOK1 - {SPR_ABK2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZBOOK2 - {SPR_ASK2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZSKULL2 - {SPR_AFWP, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZFWEAPON - {SPR_ACWP, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZCWEAPON - {SPR_AMWP, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTIPUZZMWEAPON - {SPR_AGER, 32768, 4, NULL, S_ARTIPUZZGEAR_2, 0, 0}, // S_ARTIPUZZGEAR_1 - {SPR_AGER, 32769, 4, NULL, S_ARTIPUZZGEAR_3, 0, 0}, // S_ARTIPUZZGEAR_2 - {SPR_AGER, 32770, 4, NULL, S_ARTIPUZZGEAR_4, 0, 0}, // S_ARTIPUZZGEAR_3 - {SPR_AGER, 32771, 4, NULL, S_ARTIPUZZGEAR_5, 0, 0}, // S_ARTIPUZZGEAR_4 - {SPR_AGER, 32772, 4, NULL, S_ARTIPUZZGEAR_6, 0, 0}, // S_ARTIPUZZGEAR_5 - {SPR_AGER, 32773, 4, NULL, S_ARTIPUZZGEAR_7, 0, 0}, // S_ARTIPUZZGEAR_6 - {SPR_AGER, 32774, 4, NULL, S_ARTIPUZZGEAR_8, 0, 0}, // S_ARTIPUZZGEAR_7 - {SPR_AGER, 32775, 4, NULL, S_ARTIPUZZGEAR_1, 0, 0}, // S_ARTIPUZZGEAR_8 - {SPR_AGR2, 32768, 4, NULL, S_ARTIPUZZGEAR2_2, 0, 0}, // S_ARTIPUZZGEAR2_1 - {SPR_AGR2, 32769, 4, NULL, S_ARTIPUZZGEAR2_3, 0, 0}, // S_ARTIPUZZGEAR2_2 - {SPR_AGR2, 32770, 4, NULL, S_ARTIPUZZGEAR2_4, 0, 0}, // S_ARTIPUZZGEAR2_3 - {SPR_AGR2, 32771, 4, NULL, S_ARTIPUZZGEAR2_5, 0, 0}, // S_ARTIPUZZGEAR2_4 - {SPR_AGR2, 32772, 4, NULL, S_ARTIPUZZGEAR2_6, 0, 0}, // S_ARTIPUZZGEAR2_5 - {SPR_AGR2, 32773, 4, NULL, S_ARTIPUZZGEAR2_7, 0, 0}, // S_ARTIPUZZGEAR2_6 - {SPR_AGR2, 32774, 4, NULL, S_ARTIPUZZGEAR2_8, 0, 0}, // S_ARTIPUZZGEAR2_7 - {SPR_AGR2, 32775, 4, NULL, S_ARTIPUZZGEAR2_1, 0, 0}, // S_ARTIPUZZGEAR2_8 - {SPR_AGR3, 32768, 4, NULL, S_ARTIPUZZGEAR3_2, 0, 0}, // S_ARTIPUZZGEAR3_1 - {SPR_AGR3, 32769, 4, NULL, S_ARTIPUZZGEAR3_3, 0, 0}, // S_ARTIPUZZGEAR3_2 - {SPR_AGR3, 32770, 4, NULL, S_ARTIPUZZGEAR3_4, 0, 0}, // S_ARTIPUZZGEAR3_3 - {SPR_AGR3, 32771, 4, NULL, S_ARTIPUZZGEAR3_5, 0, 0}, // S_ARTIPUZZGEAR3_4 - {SPR_AGR3, 32772, 4, NULL, S_ARTIPUZZGEAR3_6, 0, 0}, // S_ARTIPUZZGEAR3_5 - {SPR_AGR3, 32773, 4, NULL, S_ARTIPUZZGEAR3_7, 0, 0}, // S_ARTIPUZZGEAR3_6 - {SPR_AGR3, 32774, 4, NULL, S_ARTIPUZZGEAR3_8, 0, 0}, // S_ARTIPUZZGEAR3_7 - {SPR_AGR3, 32775, 4, NULL, S_ARTIPUZZGEAR3_1, 0, 0}, // S_ARTIPUZZGEAR3_8 - {SPR_AGR4, 32768, 4, NULL, S_ARTIPUZZGEAR4_2, 0, 0}, // S_ARTIPUZZGEAR4_1 - {SPR_AGR4, 32769, 4, NULL, S_ARTIPUZZGEAR4_3, 0, 0}, // S_ARTIPUZZGEAR4_2 - {SPR_AGR4, 32770, 4, NULL, S_ARTIPUZZGEAR4_4, 0, 0}, // S_ARTIPUZZGEAR4_3 - {SPR_AGR4, 32771, 4, NULL, S_ARTIPUZZGEAR4_5, 0, 0}, // S_ARTIPUZZGEAR4_4 - {SPR_AGR4, 32772, 4, NULL, S_ARTIPUZZGEAR4_6, 0, 0}, // S_ARTIPUZZGEAR4_5 - {SPR_AGR4, 32773, 4, NULL, S_ARTIPUZZGEAR4_7, 0, 0}, // S_ARTIPUZZGEAR4_6 - {SPR_AGR4, 32774, 4, NULL, S_ARTIPUZZGEAR4_8, 0, 0}, // S_ARTIPUZZGEAR4_7 - {SPR_AGR4, 32775, 4, NULL, S_ARTIPUZZGEAR4_1, 0, 0}, // S_ARTIPUZZGEAR4_8 - {SPR_TRCH, 32768, 3, NULL, S_ARTI_TRCH2, 0, 0}, // S_ARTI_TRCH1 - {SPR_TRCH, 32769, 3, NULL, S_ARTI_TRCH3, 0, 0}, // S_ARTI_TRCH2 - {SPR_TRCH, 32770, 3, NULL, S_ARTI_TRCH1, 0, 0}, // S_ARTI_TRCH3 - {SPR_PSBG, 0, 20, NULL, S_FIREBOMB2, 0, 0}, // S_FIREBOMB1 - {SPR_PSBG, 0, 10, NULL, S_FIREBOMB3, 0, 0}, // S_FIREBOMB2 - {SPR_PSBG, 0, 10, NULL, S_FIREBOMB4, 0, 0}, // S_FIREBOMB3 - {SPR_PSBG, 1, 4, NULL, S_FIREBOMB5, 0, 0}, // S_FIREBOMB4 - {SPR_PSBG, 2, 4, A_Scream, S_FIREBOMB6, 0, 0}, // S_FIREBOMB5 - {SPR_XPL1, 32768, 4, A_Explode, S_FIREBOMB7, 0, 0}, // S_FIREBOMB6 - {SPR_XPL1, 32769, 4, NULL, S_FIREBOMB8, 0, 0}, // S_FIREBOMB7 - {SPR_XPL1, 32770, 4, NULL, S_FIREBOMB9, 0, 0}, // S_FIREBOMB8 - {SPR_XPL1, 32771, 4, NULL, S_FIREBOMB10, 0, 0}, // S_FIREBOMB9 - {SPR_XPL1, 32772, 4, NULL, S_FIREBOMB11, 0, 0}, // S_FIREBOMB10 - {SPR_XPL1, 32773, 4, NULL, S_NULL, 0, 0}, // S_FIREBOMB11 - {SPR_ATLP, 0, 4, NULL, S_ARTI_ATLP2, 0, 0}, // S_ARTI_ATLP1 - {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP3, 0, 0}, // S_ARTI_ATLP2 - {SPR_ATLP, 2, 4, NULL, S_ARTI_ATLP4, 0, 0}, // S_ARTI_ATLP3 - {SPR_ATLP, 1, 4, NULL, S_ARTI_ATLP1, 0, 0}, // S_ARTI_ATLP4 - {SPR_PSBG, 0, -1, NULL, S_NULL, 0, 0}, // S_ARTI_PSBG1 - {SPR_PSBG, 32768, 18, NULL, S_POISONBAG2, 0, 0}, // S_POISONBAG1 - {SPR_PSBG, 32769, 4, NULL, S_POISONBAG3, 0, 0}, // S_POISONBAG2 - {SPR_PSBG, 2, 3, NULL, S_POISONBAG4, 0, 0}, // S_POISONBAG3 - {SPR_PSBG, 2, 1, A_PoisonBagInit, S_NULL, 0, 0}, // S_POISONBAG4 - {SPR_PSBG, 3, 1, NULL, S_POISONCLOUD2, 0, 0}, // S_POISONCLOUD1 - {SPR_PSBG, 3, 1, A_Scream, S_POISONCLOUD3, 0, 0}, // S_POISONCLOUD2 - {SPR_PSBG, 3, 2, A_PoisonBagDamage, S_POISONCLOUD4, 0, 0}, // S_POISONCLOUD3 - {SPR_PSBG, 4, 2, A_PoisonBagDamage, S_POISONCLOUD5, 0, 0}, // S_POISONCLOUD4 - {SPR_PSBG, 4, 2, A_PoisonBagDamage, S_POISONCLOUD6, 0, 0}, // S_POISONCLOUD5 - {SPR_PSBG, 4, 2, A_PoisonBagDamage, S_POISONCLOUD7, 0, 0}, // S_POISONCLOUD6 - {SPR_PSBG, 5, 2, A_PoisonBagDamage, S_POISONCLOUD8, 0, 0}, // S_POISONCLOUD7 - {SPR_PSBG, 5, 2, A_PoisonBagDamage, S_POISONCLOUD9, 0, 0}, // S_POISONCLOUD8 - {SPR_PSBG, 5, 2, A_PoisonBagDamage, S_POISONCLOUD10, 0, 0}, // S_POISONCLOUD9 - {SPR_PSBG, 6, 2, A_PoisonBagDamage, S_POISONCLOUD11, 0, 0}, // S_POISONCLOUD10 - {SPR_PSBG, 6, 2, A_PoisonBagDamage, S_POISONCLOUD12, 0, 0}, // S_POISONCLOUD11 - {SPR_PSBG, 6, 2, A_PoisonBagDamage, S_POISONCLOUD13, 0, 0}, // S_POISONCLOUD12 - {SPR_PSBG, 7, 2, A_PoisonBagDamage, S_POISONCLOUD14, 0, 0}, // S_POISONCLOUD13 - {SPR_PSBG, 7, 2, A_PoisonBagDamage, S_POISONCLOUD15, 0, 0}, // S_POISONCLOUD14 - {SPR_PSBG, 7, 2, A_PoisonBagDamage, S_POISONCLOUD16, 0, 0}, // S_POISONCLOUD15 - {SPR_PSBG, 8, 2, A_PoisonBagDamage, S_POISONCLOUD17, 0, 0}, // S_POISONCLOUD16 - {SPR_PSBG, 8, 1, A_PoisonBagDamage, S_POISONCLOUD18, 0, 0}, // S_POISONCLOUD17 - {SPR_PSBG, 8, 1, A_PoisonBagCheck, S_POISONCLOUD4, 0, 0}, // S_POISONCLOUD18 - {SPR_PSBG, 7, 7, NULL, S_POISONCLOUD_X2, 0, 0}, // S_POISONCLOUD_X1 - {SPR_PSBG, 6, 7, NULL, S_POISONCLOUD_X3, 0, 0}, // S_POISONCLOUD_X2 - {SPR_PSBG, 5, 6, NULL, S_POISONCLOUD_X4, 0, 0}, // S_POISONCLOUD_X3 - {SPR_PSBG, 3, 6, NULL, S_NULL, 0, 0}, // S_POISONCLOUD_X4 - {SPR_THRW, 0, 4, A_CheckThrowBomb, S_THROWINGBOMB2, 0, 0}, // S_THROWINGBOMB1 - {SPR_THRW, 1, 3, A_CheckThrowBomb, S_THROWINGBOMB3, 0, 0}, // S_THROWINGBOMB2 - {SPR_THRW, 2, 3, A_CheckThrowBomb, S_THROWINGBOMB4, 0, 0}, // S_THROWINGBOMB3 - {SPR_THRW, 3, 3, A_CheckThrowBomb, S_THROWINGBOMB5, 0, 0}, // S_THROWINGBOMB4 - {SPR_THRW, 4, 3, A_CheckThrowBomb, S_THROWINGBOMB6, 0, 0}, // S_THROWINGBOMB5 - {SPR_THRW, 5, 3, A_CheckThrowBomb, S_THROWINGBOMB1, 0, 0}, // S_THROWINGBOMB6 - {SPR_THRW, 6, 6, A_CheckThrowBomb, S_THROWINGBOMB8, 0, 0}, // S_THROWINGBOMB7 - {SPR_THRW, 5, 4, A_CheckThrowBomb, S_THROWINGBOMB9, 0, 0}, // S_THROWINGBOMB8 - {SPR_THRW, 7, 6, A_CheckThrowBomb, S_THROWINGBOMB10, 0, 0}, // S_THROWINGBOMB9 - {SPR_THRW, 5, 4, A_CheckThrowBomb, S_THROWINGBOMB11, 0, 0}, // S_THROWINGBOMB10 - {SPR_THRW, 6, 6, A_CheckThrowBomb, S_THROWINGBOMB12, 0, 0}, // S_THROWINGBOMB11 - {SPR_THRW, 5, 3, A_CheckThrowBomb, S_THROWINGBOMB12, 0, 0}, // S_THROWINGBOMB12 - {SPR_CFCF, 32784, 4, A_NoGravity, S_THROWINGBOMB_X2, 0, 0}, // S_THROWINGBOMB_X1 - {SPR_CFCF, 32785, 3, A_Scream, S_THROWINGBOMB_X3, 0, 0}, // S_THROWINGBOMB_X2 - {SPR_CFCF, 32786, 4, A_Explode, S_THROWINGBOMB_X4, 0, 0}, // S_THROWINGBOMB_X3 - {SPR_CFCF, 32787, 3, NULL, S_THROWINGBOMB_X5, 0, 0}, // S_THROWINGBOMB_X4 - {SPR_CFCF, 32788, 4, NULL, S_THROWINGBOMB_X6, 0, 0}, // S_THROWINGBOMB_X5 - {SPR_CFCF, 32790, 3, NULL, S_THROWINGBOMB_X7, 0, 0}, // S_THROWINGBOMB_X6 - {SPR_CFCF, 32791, 4, NULL, S_THROWINGBOMB_X8, 0, 0}, // S_THROWINGBOMB_X7 - {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_THROWINGBOMB_X8 - {SPR_SPED, 32768, 3, NULL, S_ARTI_BOOTS2, 0, 0}, // S_ARTI_BOOTS1 - {SPR_SPED, 32769, 3, NULL, S_ARTI_BOOTS3, 0, 0}, // S_ARTI_BOOTS2 - {SPR_SPED, 32770, 3, NULL, S_ARTI_BOOTS4, 0, 0}, // S_ARTI_BOOTS3 - {SPR_SPED, 32771, 3, NULL, S_ARTI_BOOTS5, 0, 0}, // S_ARTI_BOOTS4 - {SPR_SPED, 32772, 3, NULL, S_ARTI_BOOTS6, 0, 0}, // S_ARTI_BOOTS5 - {SPR_SPED, 32773, 3, NULL, S_ARTI_BOOTS7, 0, 0}, // S_ARTI_BOOTS6 - {SPR_SPED, 32774, 3, NULL, S_ARTI_BOOTS8, 0, 0}, // S_ARTI_BOOTS7 - {SPR_SPED, 32775, 3, NULL, S_ARTI_BOOTS1, 0, 0}, // S_ARTI_BOOTS8 - {SPR_BMAN, 32768, -1, NULL, S_NULL, 0, 0}, // S_ARTI_MANA - {SPR_BRAC, 32768, 4, NULL, S_ARTI_ARMOR2, 0, 0}, // S_ARTI_ARMOR1 - {SPR_BRAC, 32769, 4, NULL, S_ARTI_ARMOR3, 0, 0}, // S_ARTI_ARMOR2 - {SPR_BRAC, 32770, 4, NULL, S_ARTI_ARMOR4, 0, 0}, // S_ARTI_ARMOR3 - {SPR_BRAC, 32771, 4, NULL, S_ARTI_ARMOR5, 0, 0}, // S_ARTI_ARMOR4 - {SPR_BRAC, 32772, 4, NULL, S_ARTI_ARMOR6, 0, 0}, // S_ARTI_ARMOR5 - {SPR_BRAC, 32773, 4, NULL, S_ARTI_ARMOR7, 0, 0}, // S_ARTI_ARMOR6 - {SPR_BRAC, 32774, 4, NULL, S_ARTI_ARMOR8, 0, 0}, // S_ARTI_ARMOR7 - {SPR_BRAC, 32775, 4, NULL, S_ARTI_ARMOR1, 0, 0}, // S_ARTI_ARMOR8 - {SPR_BLST, 32768, 4, NULL, S_ARTI_BLAST2, 0, 0}, // S_ARTI_BLAST1 - {SPR_BLST, 32769, 4, NULL, S_ARTI_BLAST3, 0, 0}, // S_ARTI_BLAST2 - {SPR_BLST, 32770, 4, NULL, S_ARTI_BLAST4, 0, 0}, // S_ARTI_BLAST3 - {SPR_BLST, 32771, 4, NULL, S_ARTI_BLAST5, 0, 0}, // S_ARTI_BLAST4 - {SPR_BLST, 32772, 4, NULL, S_ARTI_BLAST6, 0, 0}, // S_ARTI_BLAST5 - {SPR_BLST, 32773, 4, NULL, S_ARTI_BLAST7, 0, 0}, // S_ARTI_BLAST6 - {SPR_BLST, 32774, 4, NULL, S_ARTI_BLAST8, 0, 0}, // S_ARTI_BLAST7 - {SPR_BLST, 32775, 4, NULL, S_ARTI_BLAST1, 0, 0}, // S_ARTI_BLAST8 - {SPR_HRAD, 32768, 4, NULL, S_ARTI_HEALRAD2, 0, 0}, // S_ARTI_HEALRAD1 - {SPR_HRAD, 32769, 4, NULL, S_ARTI_HEALRAD3, 0, 0}, // S_ARTI_HEALRAD2 - {SPR_HRAD, 32770, 4, NULL, S_ARTI_HEALRAD4, 0, 0}, // S_ARTI_HEALRAD3 - {SPR_HRAD, 32771, 4, NULL, S_ARTI_HEALRAD5, 0, 0}, // S_ARTI_HEALRAD4 - {SPR_HRAD, 32772, 4, NULL, S_ARTI_HEALRAD6, 0, 0}, // S_ARTI_HEALRAD5 - {SPR_HRAD, 32773, 4, NULL, S_ARTI_HEALRAD7, 0, 0}, // S_ARTI_HEALRAD6 - {SPR_HRAD, 32774, 4, NULL, S_ARTI_HEALRAD8, 0, 0}, // S_ARTI_HEALRAD7 - {SPR_HRAD, 32775, 4, NULL, S_ARTI_HEALRAD9, 0, 0}, // S_ARTI_HEALRAD8 - {SPR_HRAD, 32776, 4, NULL, S_ARTI_HEALRAD0, 0, 0}, // S_ARTI_HEALRAD9 - {SPR_HRAD, 32777, 4, NULL, S_ARTI_HEALRADA, 0, 0}, // S_ARTI_HEALRAD0 - {SPR_HRAD, 32778, 4, NULL, S_ARTI_HEALRADB, 0, 0}, // S_ARTI_HEALRADA - {SPR_HRAD, 32779, 4, NULL, S_ARTI_HEALRADC, 0, 0}, // S_ARTI_HEALRADB - {SPR_HRAD, 32780, 4, NULL, S_ARTI_HEALRADD, 0, 0}, // S_ARTI_HEALRADC - {SPR_HRAD, 32781, 4, NULL, S_ARTI_HEALRADE, 0, 0}, // S_ARTI_HEALRADD - {SPR_HRAD, 32782, 4, NULL, S_ARTI_HEALRADF, 0, 0}, // S_ARTI_HEALRADE - {SPR_HRAD, 32783, 4, NULL, S_ARTI_HEALRAD1, 0, 0}, // S_ARTI_HEALRADF - {SPR_SPSH, 0, 8, NULL, S_SPLASH2, 0, 0}, // S_SPLASH1 - {SPR_SPSH, 1, 8, NULL, S_SPLASH3, 0, 0}, // S_SPLASH2 - {SPR_SPSH, 2, 8, NULL, S_SPLASH4, 0, 0}, // S_SPLASH3 - {SPR_SPSH, 3, 16, NULL, S_NULL, 0, 0}, // S_SPLASH4 - {SPR_SPSH, 3, 10, NULL, S_NULL, 0, 0}, // S_SPLASHX - {SPR_SPSH, 4, 5, NULL, S_SPLASHBASE2, 0, 0}, // S_SPLASHBASE1 - {SPR_SPSH, 5, 5, NULL, S_SPLASHBASE3, 0, 0}, // S_SPLASHBASE2 - {SPR_SPSH, 6, 5, NULL, S_SPLASHBASE4, 0, 0}, // S_SPLASHBASE3 - {SPR_SPSH, 7, 5, NULL, S_SPLASHBASE5, 0, 0}, // S_SPLASHBASE4 - {SPR_SPSH, 8, 5, NULL, S_SPLASHBASE6, 0, 0}, // S_SPLASHBASE5 - {SPR_SPSH, 9, 5, NULL, S_SPLASHBASE7, 0, 0}, // S_SPLASHBASE6 - {SPR_SPSH, 10, 5, NULL, S_NULL, 0, 0}, // S_SPLASHBASE7 - {SPR_LVAS, 32768, 5, NULL, S_LAVASPLASH2, 0, 0}, // S_LAVASPLASH1 - {SPR_LVAS, 32769, 5, NULL, S_LAVASPLASH3, 0, 0}, // S_LAVASPLASH2 - {SPR_LVAS, 32770, 5, NULL, S_LAVASPLASH4, 0, 0}, // S_LAVASPLASH3 - {SPR_LVAS, 32771, 5, NULL, S_LAVASPLASH5, 0, 0}, // S_LAVASPLASH4 - {SPR_LVAS, 32772, 5, NULL, S_LAVASPLASH6, 0, 0}, // S_LAVASPLASH5 - {SPR_LVAS, 32773, 5, NULL, S_NULL, 0, 0}, // S_LAVASPLASH6 - {SPR_LVAS, 32774, 5, NULL, S_LAVASMOKE2, 0, 0}, // S_LAVASMOKE1 - {SPR_LVAS, 32775, 5, NULL, S_LAVASMOKE3, 0, 0}, // S_LAVASMOKE2 - {SPR_LVAS, 32776, 5, NULL, S_LAVASMOKE4, 0, 0}, // S_LAVASMOKE3 - {SPR_LVAS, 32777, 5, NULL, S_LAVASMOKE5, 0, 0}, // S_LAVASMOKE4 - {SPR_LVAS, 32778, 5, NULL, S_NULL, 0, 0}, // S_LAVASMOKE5 - {SPR_SLDG, 0, 8, NULL, S_SLUDGECHUNK2, 0, 0}, // S_SLUDGECHUNK1 - {SPR_SLDG, 1, 8, NULL, S_SLUDGECHUNK3, 0, 0}, // S_SLUDGECHUNK2 - {SPR_SLDG, 2, 8, NULL, S_SLUDGECHUNK4, 0, 0}, // S_SLUDGECHUNK3 - {SPR_SLDG, 3, 8, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNK4 - {SPR_SLDG, 3, 6, NULL, S_NULL, 0, 0}, // S_SLUDGECHUNKX - {SPR_SLDG, 4, 6, NULL, S_SLUDGESPLASH2, 0, 0}, // S_SLUDGESPLASH1 - {SPR_SLDG, 5, 6, NULL, S_SLUDGESPLASH3, 0, 0}, // S_SLUDGESPLASH2 - {SPR_SLDG, 6, 6, NULL, S_SLUDGESPLASH4, 0, 0}, // S_SLUDGESPLASH3 - {SPR_SLDG, 7, 6, NULL, S_NULL, 0, 0}, // S_SLUDGESPLASH4 - {SPR_STTW, 0, -1, NULL, S_NULL, 0, 0}, // S_ZWINGEDSTATUE1 - {SPR_RCK1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK1_1 - {SPR_RCK2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK2_1 - {SPR_RCK3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK3_1 - {SPR_RCK4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCK4_1 - {SPR_CDLR, 0, 4, NULL, S_ZCHANDELIER2, 0, 0}, // S_ZCHANDELIER1 - {SPR_CDLR, 1, 4, NULL, S_ZCHANDELIER3, 0, 0}, // S_ZCHANDELIER2 - {SPR_CDLR, 2, 4, NULL, S_ZCHANDELIER1, 0, 0}, // S_ZCHANDELIER3 - {SPR_CDLR, 3, -1, NULL, S_NULL, 0, 0}, // S_ZCHANDELIER_U - {SPR_TRE1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDEAD1 - {SPR_TRE1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREE - {SPR_TRDT, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDESTRUCTIBLE1 - {SPR_TRDT, 1, 5, NULL, S_ZTREEDES_D2, 0, 0}, // S_ZTREEDES_D1 - {SPR_TRDT, 2, 5, A_Scream, S_ZTREEDES_D3, 0, 0}, // S_ZTREEDES_D2 - {SPR_TRDT, 3, 5, NULL, S_ZTREEDES_D4, 0, 0}, // S_ZTREEDES_D3 - {SPR_TRDT, 4, 5, NULL, S_ZTREEDES_D5, 0, 0}, // S_ZTREEDES_D4 - {SPR_TRDT, 5, 5, NULL, S_ZTREEDES_D6, 0, 0}, // S_ZTREEDES_D5 - {SPR_TRDT, 6, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDES_D6 - {SPR_TRDT, 32775, 5, NULL, S_ZTREEDES_X2, 0, 0}, // S_ZTREEDES_X1 - {SPR_TRDT, 32776, 5, NULL, S_ZTREEDES_X3, 0, 0}, // S_ZTREEDES_X2 - {SPR_TRDT, 32777, 5, NULL, S_ZTREEDES_X4, 0, 0}, // S_ZTREEDES_X3 - {SPR_TRDT, 32778, 5, NULL, S_ZTREEDES_X5, 0, 0}, // S_ZTREEDES_X4 - {SPR_TRDT, 32779, 5, NULL, S_ZTREEDES_X6, 0, 0}, // S_ZTREEDES_X5 - {SPR_TRDT, 32780, 5, A_Explode, S_ZTREEDES_X7, 0, 0}, // S_ZTREEDES_X6 - {SPR_TRDT, 32781, 5, NULL, S_ZTREEDES_X8, 0, 0}, // S_ZTREEDES_X7 - {SPR_TRDT, 14, 5, NULL, S_ZTREEDES_X9, 0, 0}, // S_ZTREEDES_X8 - {SPR_TRDT, 15, 5, NULL, S_ZTREEDES_X10, 0, 0}, // S_ZTREEDES_X9 - {SPR_TRDT, 16, -1, NULL, S_NULL, 0, 0}, // S_ZTREEDES_X10 - {SPR_TRE2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREESWAMP182_1 - {SPR_TRE3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREESWAMP172_1 - {SPR_STM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPBURNED1 - {SPR_STM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPBARE1 - {SPR_STM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPSWAMP1_1 - {SPR_STM4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTUMPSWAMP2_1 - {SPR_MSH1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMLARGE1_1 - {SPR_MSH2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMLARGE2_1 - {SPR_MSH3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMLARGE3_1 - {SPR_MSH4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL1_1 - {SPR_MSH5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL2_1 - {SPR_MSH6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL3_1 - {SPR_MSH7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL4_1 - {SPR_MSH8, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHROOMSMALL5_1 - {SPR_SGMP, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEPILLAR1 - {SPR_SGM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITELARGE1 - {SPR_SGM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEMEDIUM1 - {SPR_SGM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITESMALL1 - {SPR_SLC1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITELARGE1 - {SPR_SLC2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEMEDIUM1 - {SPR_SLC3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITESMALL1 - {SPR_MSS1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZMOSSCEILING1_1 - {SPR_MSS2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZMOSSCEILING2_1 - {SPR_SWMV, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSWAMPVINE1 - {SPR_CPS1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSEKABOB1 - {SPR_CPS2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSESLEEPING1 - {SPR_TMS1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONERIP1 - {SPR_TMS2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONESHANE1 - {SPR_TMS3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONEBIGCROSS1 - {SPR_TMS4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONEBRIANR1 - {SPR_TMS5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONECROSSCIRCLE1 - {SPR_TMS6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONESMALLCROSS1 - {SPR_TMS7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTOMBSTONEBRIANP1 - {SPR_CPS3, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEHANGING_1 - {SPR_STT2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEGREENTALL_1 - {SPR_STT3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEBLUETALL_1 - {SPR_STT4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEGREENSHORT_1 - {SPR_STT5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEBLUESHORT_1 - {SPR_GAR1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLESTRIPETALL_1 - {SPR_GAR2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEDARKREDTALL_1 - {SPR_GAR3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEREDTALL_1 - {SPR_GAR4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLETANTALL_1 - {SPR_GAR5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLERUSTTALL_1 - {SPR_GAR6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEDARKREDSHORT_1 - {SPR_GAR7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLEREDSHORT_1 - {SPR_GAR8, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLETANSHORT_1 - {SPR_GAR9, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTATUEGARGOYLERUSTSHORT_1 - {SPR_BNR1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZBANNERTATTERED_1 - {SPR_TRE4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREELARGE1 - {SPR_TRE5, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREELARGE2 - {SPR_TRE6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEGNARLED1 - {SPR_TRE7, 0, -1, NULL, S_NULL, 0, 0}, // S_ZTREEGNARLED2 - {SPR_LOGG, 0, -1, NULL, S_NULL, 0, 0}, // S_ZLOG - {SPR_ICT1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICELARGE - {SPR_ICT2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICEMEDIUM - {SPR_ICT3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICESMALL - {SPR_ICT4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALACTITEICETINY - {SPR_ICM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICELARGE - {SPR_ICM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICEMEDIUM - {SPR_ICM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICESMALL - {SPR_ICM4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSTALAGMITEICETINY - {SPR_RKBL, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCKBROWN1 - {SPR_RKBS, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCKBROWN2 - {SPR_RKBK, 0, -1, NULL, S_NULL, 0, 0}, // S_ZROCKBLACK - {SPR_RBL1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZRUBBLE1 - {SPR_RBL2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZRUBBLE2 - {SPR_RBL3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZRUBBLE3 - {SPR_VASE, 0, -1, NULL, S_NULL, 0, 0}, // S_ZVASEPILLAR - {SPR_POT1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZPOTTERY1 - {SPR_POT2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZPOTTERY2 - {SPR_POT3, 0, -1, NULL, S_NULL, 0, 0}, // S_ZPOTTERY3 - {SPR_POT1, 0, 0, A_PotteryExplode, S_NULL, 0, 0}, // S_ZPOTTERY_EXPLODE - {SPR_PBIT, 0, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_1 - {SPR_PBIT, 1, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_2 - {SPR_PBIT, 2, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_3 - {SPR_PBIT, 3, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_4 - {SPR_PBIT, 4, -1, NULL, S_NULL, 0, 0}, // S_POTTERYBIT_5 - {SPR_PBIT, 5, 0, A_PotteryChooseBit, S_NULL, 0, 0}, // S_POTTERYBIT_EX0 - {SPR_PBIT, 5, 140, NULL, S_POTTERYBIT_EX1_2, 0, 0}, // S_POTTERYBIT_EX1 - {SPR_PBIT, 5, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX1_2 - {SPR_PBIT, 6, 140, NULL, S_POTTERYBIT_EX2_2, 0, 0}, // S_POTTERYBIT_EX2 - {SPR_PBIT, 6, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX2_2 - {SPR_PBIT, 7, 140, NULL, S_POTTERYBIT_EX3_2, 0, 0}, // S_POTTERYBIT_EX3 - {SPR_PBIT, 7, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX3_2 - {SPR_PBIT, 8, 140, NULL, S_POTTERYBIT_EX4_2, 0, 0}, // S_POTTERYBIT_EX4 - {SPR_PBIT, 8, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX4_2 - {SPR_PBIT, 9, 140, NULL, S_POTTERYBIT_EX5_2, 0, 0}, // S_POTTERYBIT_EX5 - {SPR_PBIT, 9, 1, A_PotteryCheck, S_NULL, 0, 0}, // S_POTTERYBIT_EX5_2 - {SPR_CPS4, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSELYNCHED1 - {SPR_CPS5, 0, 140, A_CorpseBloodDrip, S_ZCORPSELYNCHED2, 0, 0}, // S_ZCORPSELYNCHED2 - {SPR_CPS6, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCORPSESITTING - {SPR_CPS6, 0, 1, A_CorpseExplode, S_NULL, 0, 0}, // S_ZCORPSESITTING_X - {SPR_CPB1, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_1 - {SPR_CPB2, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_2 - {SPR_CPB3, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_3 - {SPR_CPB4, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBIT_4 - {SPR_BDRP, 0, -1, NULL, S_NULL, 0, 0}, // S_CORPSEBLOODDRIP - {SPR_BDSH, 0, 3, NULL, S_CORPSEBLOODDRIP_X2, 0, 0}, // S_CORPSEBLOODDRIP_X1 - {SPR_BDSH, 1, 3, NULL, S_CORPSEBLOODDRIP_X3, 0, 0}, // S_CORPSEBLOODDRIP_X2 - {SPR_BDSH, 2, 2, NULL, S_CORPSEBLOODDRIP_X4, 0, 0}, // S_CORPSEBLOODDRIP_X3 - {SPR_BDSH, 3, 2, NULL, S_NULL, 0, 0}, // S_CORPSEBLOODDRIP_X4 - {SPR_BDPL, 0, -1, NULL, S_NULL, 0, 0}, // S_BLOODPOOL - {SPR_CNDL, 32768, 4, NULL, S_ZCANDLE2, 0, 0}, // S_ZCANDLE1 - {SPR_CNDL, 32769, 4, NULL, S_ZCANDLE3, 0, 0}, // S_ZCANDLE2 - {SPR_CNDL, 32770, 4, NULL, S_ZCANDLE1, 0, 0}, // S_ZCANDLE3 - {SPR_MAN1, 0, 20, A_LeafSpawn, S_ZLEAFSPAWNER, 0, 0}, // S_ZLEAFSPAWNER - {SPR_LEF1, 0, 4, NULL, S_LEAF1_2, 0, 0}, // S_LEAF1_1 - {SPR_LEF1, 1, 4, NULL, S_LEAF1_3, 0, 0}, // S_LEAF1_2 - {SPR_LEF1, 2, 4, NULL, S_LEAF1_4, 0, 0}, // S_LEAF1_3 - {SPR_LEF1, 3, 4, A_LeafThrust, S_LEAF1_5, 0, 0}, // S_LEAF1_4 - {SPR_LEF1, 4, 4, NULL, S_LEAF1_6, 0, 0}, // S_LEAF1_5 - {SPR_LEF1, 5, 4, NULL, S_LEAF1_7, 0, 0}, // S_LEAF1_6 - {SPR_LEF1, 6, 4, NULL, S_LEAF1_8, 0, 0}, // S_LEAF1_7 - {SPR_LEF1, 7, 4, A_LeafThrust, S_LEAF1_9, 0, 0}, // S_LEAF1_8 - {SPR_LEF1, 8, 4, NULL, S_LEAF1_10, 0, 0}, // S_LEAF1_9 - {SPR_LEF1, 0, 4, NULL, S_LEAF1_11, 0, 0}, // S_LEAF1_10 - {SPR_LEF1, 1, 4, NULL, S_LEAF1_12, 0, 0}, // S_LEAF1_11 - {SPR_LEF1, 2, 4, A_LeafThrust, S_LEAF1_13, 0, 0}, // S_LEAF1_12 - {SPR_LEF1, 3, 4, NULL, S_LEAF1_14, 0, 0}, // S_LEAF1_13 - {SPR_LEF1, 4, 4, NULL, S_LEAF1_15, 0, 0}, // S_LEAF1_14 - {SPR_LEF1, 5, 4, NULL, S_LEAF1_16, 0, 0}, // S_LEAF1_15 - {SPR_LEF1, 6, 4, A_LeafThrust, S_LEAF1_17, 0, 0}, // S_LEAF1_16 - {SPR_LEF1, 7, 4, NULL, S_LEAF1_18, 0, 0}, // S_LEAF1_17 - {SPR_LEF1, 8, 4, NULL, S_NULL, 0, 0}, // S_LEAF1_18 - {SPR_LEF3, 3, 10, A_LeafCheck, S_LEAF_X1, 0, 0}, // S_LEAF_X1 - {SPR_LEF2, 0, 4, NULL, S_LEAF2_2, 0, 0}, // S_LEAF2_1 - {SPR_LEF2, 1, 4, NULL, S_LEAF2_3, 0, 0}, // S_LEAF2_2 - {SPR_LEF2, 2, 4, NULL, S_LEAF2_4, 0, 0}, // S_LEAF2_3 - {SPR_LEF2, 3, 4, A_LeafThrust, S_LEAF2_5, 0, 0}, // S_LEAF2_4 - {SPR_LEF2, 4, 4, NULL, S_LEAF2_6, 0, 0}, // S_LEAF2_5 - {SPR_LEF2, 5, 4, NULL, S_LEAF2_7, 0, 0}, // S_LEAF2_6 - {SPR_LEF2, 6, 4, NULL, S_LEAF2_8, 0, 0}, // S_LEAF2_7 - {SPR_LEF2, 7, 4, A_LeafThrust, S_LEAF2_9, 0, 0}, // S_LEAF2_8 - {SPR_LEF2, 8, 4, NULL, S_LEAF2_10, 0, 0}, // S_LEAF2_9 - {SPR_LEF2, 0, 4, NULL, S_LEAF2_11, 0, 0}, // S_LEAF2_10 - {SPR_LEF2, 1, 4, NULL, S_LEAF2_12, 0, 0}, // S_LEAF2_11 - {SPR_LEF2, 2, 4, A_LeafThrust, S_LEAF2_13, 0, 0}, // S_LEAF2_12 - {SPR_LEF2, 3, 4, NULL, S_LEAF2_14, 0, 0}, // S_LEAF2_13 - {SPR_LEF2, 4, 4, NULL, S_LEAF2_15, 0, 0}, // S_LEAF2_14 - {SPR_LEF2, 5, 4, NULL, S_LEAF2_16, 0, 0}, // S_LEAF2_15 - {SPR_LEF2, 6, 4, A_LeafThrust, S_LEAF2_17, 0, 0}, // S_LEAF2_16 - {SPR_LEF2, 7, 4, NULL, S_LEAF2_18, 0, 0}, // S_LEAF2_17 - {SPR_LEF2, 8, 4, NULL, S_NULL, 0, 0}, // S_LEAF2_18 - {SPR_TWTR, 32768, 4, NULL, S_ZTWINEDTORCH_2, 0, 0}, // S_ZTWINEDTORCH_1 - {SPR_TWTR, 32769, 4, NULL, S_ZTWINEDTORCH_3, 0, 0}, // S_ZTWINEDTORCH_2 - {SPR_TWTR, 32770, 4, NULL, S_ZTWINEDTORCH_4, 0, 0}, // S_ZTWINEDTORCH_3 - {SPR_TWTR, 32771, 4, NULL, S_ZTWINEDTORCH_5, 0, 0}, // S_ZTWINEDTORCH_4 - {SPR_TWTR, 32772, 4, NULL, S_ZTWINEDTORCH_6, 0, 0}, // S_ZTWINEDTORCH_5 - {SPR_TWTR, 32773, 4, NULL, S_ZTWINEDTORCH_7, 0, 0}, // S_ZTWINEDTORCH_6 - {SPR_TWTR, 32774, 4, NULL, S_ZTWINEDTORCH_8, 0, 0}, // S_ZTWINEDTORCH_7 - {SPR_TWTR, 32775, 4, NULL, S_ZTWINEDTORCH_1, 0, 0}, // S_ZTWINEDTORCH_8 - {SPR_TWTR, 8, -1, NULL, S_NULL, 0, 0}, // S_ZTWINEDTORCH_UNLIT - {SPR_TLGL, 0, 2, NULL, S_BRIDGE2, 0, 0}, // S_BRIDGE1 - {SPR_TLGL, 0, 2, A_BridgeInit, S_BRIDGE3, 0, 0}, // S_BRIDGE2 - {SPR_TLGL, 0, -1, NULL, S_NULL, 0, 0}, // S_BRIDGE3 - {SPR_TLGL, 0, 2, NULL, S_FREE_BRIDGE2, 0, 0}, // S_FREE_BRIDGE1 - {SPR_TLGL, 0, 300, NULL, S_NULL, 0, 0}, // S_FREE_BRIDGE2 - {SPR_TLGL, 0, 2, NULL, S_BBALL2, 0, 0}, // S_BBALL1 - {SPR_TLGL, 0, 5, A_BridgeOrbit, S_BBALL2, 0, 0}, // S_BBALL2 - {SPR_WLTR, 32768, 5, NULL, S_ZWALLTORCH2, 0, 0}, // S_ZWALLTORCH1 - {SPR_WLTR, 32769, 5, NULL, S_ZWALLTORCH3, 0, 0}, // S_ZWALLTORCH2 - {SPR_WLTR, 32770, 5, NULL, S_ZWALLTORCH4, 0, 0}, // S_ZWALLTORCH3 - {SPR_WLTR, 32771, 5, NULL, S_ZWALLTORCH5, 0, 0}, // S_ZWALLTORCH4 - {SPR_WLTR, 32772, 5, NULL, S_ZWALLTORCH6, 0, 0}, // S_ZWALLTORCH5 - {SPR_WLTR, 32773, 5, NULL, S_ZWALLTORCH7, 0, 0}, // S_ZWALLTORCH6 - {SPR_WLTR, 32774, 5, NULL, S_ZWALLTORCH8, 0, 0}, // S_ZWALLTORCH7 - {SPR_WLTR, 32775, 5, NULL, S_ZWALLTORCH1, 0, 0}, // S_ZWALLTORCH8 - {SPR_WLTR, 8, -1, NULL, S_NULL, 0, 0}, // S_ZWALLTORCH_U - {SPR_BARL, 0, -1, NULL, S_NULL, 0, 0}, // S_ZBARREL1 - {SPR_SHB1, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHRUB1 - {SPR_SHB1, 0, 1, A_TreeDeath, S_ZSHRUB1, 0, 0}, // S_ZSHRUB1_DIE - {SPR_SHB1, 32769, 7, NULL, S_ZSHRUB1_X2, 0, 0}, // S_ZSHRUB1_X1 - {SPR_SHB1, 32770, 6, A_Scream, S_ZSHRUB1_X3, 0, 0}, // S_ZSHRUB1_X2 - {SPR_SHB1, 32771, 5, NULL, S_NULL, 0, 0}, // S_ZSHRUB1_X3 - {SPR_SHB2, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSHRUB2 - {SPR_SHB2, 0, 1, A_TreeDeath, S_ZSHRUB2, 0, 0}, // S_ZSHRUB2_DIE - {SPR_SHB2, 32769, 7, NULL, S_ZSHRUB2_X2, 0, 0}, // S_ZSHRUB2_X1 - {SPR_SHB2, 32770, 6, A_Scream, S_ZSHRUB2_X3, 0, 0}, // S_ZSHRUB2_X2 - {SPR_SHB2, 32771, 5, A_Explode, S_ZSHRUB2_X4, 0, 0}, // S_ZSHRUB2_X3 - {SPR_SHB2, 32772, 5, NULL, S_NULL, 0, 0}, // S_ZSHRUB2_X4 - {SPR_BCKT, 0, -1, NULL, S_NULL, 0, 0}, // S_ZBUCKET1 - {SPR_SHRM, 0, 5, A_PoisonShroom, S_ZPOISONSHROOM_P2, 0, 0}, // S_ZPOISONSHROOM1 - {SPR_SHRM, 0, 6, NULL, S_ZPOISONSHROOM_P2, 0, 0}, // S_ZPOISONSHROOM_P1 - {SPR_SHRM, 1, 8, A_Pain, S_ZPOISONSHROOM1, 0, 0}, // S_ZPOISONSHROOM_P2 - {SPR_SHRM, 2, 5, NULL, S_ZPOISONSHROOM_X2, 0, 0}, // S_ZPOISONSHROOM_X1 - {SPR_SHRM, 3, 5, NULL, S_ZPOISONSHROOM_X3, 0, 0}, // S_ZPOISONSHROOM_X2 - {SPR_SHRM, 4, 5, A_PoisonBagInit, S_ZPOISONSHROOM_X4, 0, 0}, // S_ZPOISONSHROOM_X3 - {SPR_SHRM, 5, -1, NULL, S_NULL, 0, 0}, // S_ZPOISONSHROOM_X4 - {SPR_FBUL, 32768, 4, NULL, S_ZFIREBULL2, 0, 0}, // S_ZFIREBULL1 - {SPR_FBUL, 32769, 4, NULL, S_ZFIREBULL3, 0, 0}, // S_ZFIREBULL2 - {SPR_FBUL, 32770, 4, NULL, S_ZFIREBULL4, 0, 0}, // S_ZFIREBULL3 - {SPR_FBUL, 32771, 4, NULL, S_ZFIREBULL5, 0, 0}, // S_ZFIREBULL4 - {SPR_FBUL, 32772, 4, NULL, S_ZFIREBULL6, 0, 0}, // S_ZFIREBULL5 - {SPR_FBUL, 32773, 4, NULL, S_ZFIREBULL7, 0, 0}, // S_ZFIREBULL6 - {SPR_FBUL, 32774, 4, NULL, S_ZFIREBULL1, 0, 0}, // S_ZFIREBULL7 - {SPR_FBUL, 32777, 4, NULL, S_ZFIREBULL_DEATH2, 0, 0}, // S_ZFIREBULL_DEATH - {SPR_FBUL, 32776, 4, NULL, S_ZFIREBULL_U, 0, 0}, // S_ZFIREBULL_DEATH2 - {SPR_FBUL, 7, -1, NULL, S_NULL, 0, 0}, // S_ZFIREBULL_U - {SPR_FBUL, 32776, 4, NULL, S_ZFIREBULL_BIRTH2, 0, 0}, // S_ZFIREBULL_BIRTH - {SPR_FBUL, 32777, 4, NULL, S_ZFIREBULL1, 0, 0}, // S_ZFIREBULL_BIRTH2 - {SPR_FSKL, 32768, 4, NULL, S_ZFIRETHING2, 0, 0}, // S_ZFIRETHING1 - {SPR_FSKL, 32769, 3, NULL, S_ZFIRETHING3, 0, 0}, // S_ZFIRETHING2 - {SPR_FSKL, 32770, 4, NULL, S_ZFIRETHING4, 0, 0}, // S_ZFIRETHING3 - {SPR_FSKL, 32771, 3, NULL, S_ZFIRETHING5, 0, 0}, // S_ZFIRETHING4 - {SPR_FSKL, 32772, 4, NULL, S_ZFIRETHING6, 0, 0}, // S_ZFIRETHING5 - {SPR_FSKL, 32773, 3, NULL, S_ZFIRETHING7, 0, 0}, // S_ZFIRETHING6 - {SPR_FSKL, 32774, 4, NULL, S_ZFIRETHING8, 0, 0}, // S_ZFIRETHING7 - {SPR_FSKL, 32775, 3, NULL, S_ZFIRETHING9, 0, 0}, // S_ZFIRETHING8 - {SPR_FSKL, 32776, 4, NULL, S_ZFIRETHING1, 0, 0}, // S_ZFIRETHING9 - {SPR_BRTR, 32768, 4, NULL, S_ZBRASSTORCH2, 0, 0}, // S_ZBRASSTORCH1 - {SPR_BRTR, 32769, 4, NULL, S_ZBRASSTORCH3, 0, 0}, // S_ZBRASSTORCH2 - {SPR_BRTR, 32770, 4, NULL, S_ZBRASSTORCH4, 0, 0}, // S_ZBRASSTORCH3 - {SPR_BRTR, 32771, 4, NULL, S_ZBRASSTORCH5, 0, 0}, // S_ZBRASSTORCH4 - {SPR_BRTR, 32772, 4, NULL, S_ZBRASSTORCH6, 0, 0}, // S_ZBRASSTORCH5 - {SPR_BRTR, 32773, 4, NULL, S_ZBRASSTORCH7, 0, 0}, // S_ZBRASSTORCH6 - {SPR_BRTR, 32774, 4, NULL, S_ZBRASSTORCH8, 0, 0}, // S_ZBRASSTORCH7 - {SPR_BRTR, 32775, 4, NULL, S_ZBRASSTORCH9, 0, 0}, // S_ZBRASSTORCH8 - {SPR_BRTR, 32776, 4, NULL, S_ZBRASSTORCH10, 0, 0}, // S_ZBRASSTORCH9 - {SPR_BRTR, 32777, 4, NULL, S_ZBRASSTORCH11, 0, 0}, // S_ZBRASSTORCH10 - {SPR_BRTR, 32778, 4, NULL, S_ZBRASSTORCH12, 0, 0}, // S_ZBRASSTORCH11 - {SPR_BRTR, 32779, 4, NULL, S_ZBRASSTORCH13, 0, 0}, // S_ZBRASSTORCH12 - {SPR_BRTR, 32780, 4, NULL, S_ZBRASSTORCH1, 0, 0}, // S_ZBRASSTORCH13 - {SPR_SUIT, 0, -1, NULL, S_NULL, 0, 0}, // S_ZSUITOFARMOR - {SPR_SUIT, 0, 1, A_SoAExplode, S_NULL, 0, 0}, // S_ZSUITOFARMOR_X1 - {SPR_SUIT, 1, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK1 - {SPR_SUIT, 2, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK2 - {SPR_SUIT, 3, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK3 - {SPR_SUIT, 4, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK4 - {SPR_SUIT, 5, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK5 - {SPR_SUIT, 6, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK6 - {SPR_SUIT, 7, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK7 - {SPR_SUIT, 8, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK8 - {SPR_SUIT, 9, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK9 - {SPR_SUIT, 10, -1, NULL, S_NULL, 0, 0}, // S_ZARMORCHUNK10 - {SPR_BBLL, 5, -1, NULL, S_NULL, 0, 0}, // S_ZBELL - {SPR_BBLL, 0, 4, A_BellReset1, S_ZBELL_X2, 0, 0}, // S_ZBELL_X1 - {SPR_BBLL, 1, 4, NULL, S_ZBELL_X3, 0, 0}, // S_ZBELL_X2 - {SPR_BBLL, 2, 4, NULL, S_ZBELL_X4, 0, 0}, // S_ZBELL_X3 - {SPR_BBLL, 3, 5, A_Scream, S_ZBELL_X5, 0, 0}, // S_ZBELL_X4 - {SPR_BBLL, 2, 4, NULL, S_ZBELL_X6, 0, 0}, // S_ZBELL_X5 - {SPR_BBLL, 1, 4, NULL, S_ZBELL_X7, 0, 0}, // S_ZBELL_X6 - {SPR_BBLL, 0, 3, NULL, S_ZBELL_X8, 0, 0}, // S_ZBELL_X7 - {SPR_BBLL, 4, 4, NULL, S_ZBELL_X9, 0, 0}, // S_ZBELL_X8 - {SPR_BBLL, 5, 5, NULL, S_ZBELL_X10, 0, 0}, // S_ZBELL_X9 - {SPR_BBLL, 6, 6, A_Scream, S_ZBELL_X11, 0, 0}, // S_ZBELL_X10 - {SPR_BBLL, 5, 5, NULL, S_ZBELL_X12, 0, 0}, // S_ZBELL_X11 - {SPR_BBLL, 4, 4, NULL, S_ZBELL_X13, 0, 0}, // S_ZBELL_X12 - {SPR_BBLL, 0, 4, NULL, S_ZBELL_X14, 0, 0}, // S_ZBELL_X13 - {SPR_BBLL, 1, 5, NULL, S_ZBELL_X15, 0, 0}, // S_ZBELL_X14 - {SPR_BBLL, 2, 5, NULL, S_ZBELL_X16, 0, 0}, // S_ZBELL_X15 - {SPR_BBLL, 3, 6, A_Scream, S_ZBELL_X17, 0, 0}, // S_ZBELL_X16 - {SPR_BBLL, 2, 5, NULL, S_ZBELL_X18, 0, 0}, // S_ZBELL_X17 - {SPR_BBLL, 1, 5, NULL, S_ZBELL_X19, 0, 0}, // S_ZBELL_X18 - {SPR_BBLL, 0, 4, NULL, S_ZBELL_X20, 0, 0}, // S_ZBELL_X19 - {SPR_BBLL, 4, 5, NULL, S_ZBELL_X21, 0, 0}, // S_ZBELL_X20 - {SPR_BBLL, 5, 5, NULL, S_ZBELL_X22, 0, 0}, // S_ZBELL_X21 - {SPR_BBLL, 6, 7, A_Scream, S_ZBELL_X23, 0, 0}, // S_ZBELL_X22 - {SPR_BBLL, 5, 5, NULL, S_ZBELL_X24, 0, 0}, // S_ZBELL_X23 - {SPR_BBLL, 4, 5, NULL, S_ZBELL_X25, 0, 0}, // S_ZBELL_X24 - {SPR_BBLL, 0, 5, NULL, S_ZBELL_X26, 0, 0}, // S_ZBELL_X25 - {SPR_BBLL, 1, 6, NULL, S_ZBELL_X27, 0, 0}, // S_ZBELL_X26 - {SPR_BBLL, 2, 6, NULL, S_ZBELL_X28, 0, 0}, // S_ZBELL_X27 - {SPR_BBLL, 3, 7, A_Scream, S_ZBELL_X29, 0, 0}, // S_ZBELL_X28 - {SPR_BBLL, 2, 6, NULL, S_ZBELL_X30, 0, 0}, // S_ZBELL_X29 - {SPR_BBLL, 1, 6, NULL, S_ZBELL_X31, 0, 0}, // S_ZBELL_X30 - {SPR_BBLL, 0, 5, NULL, S_ZBELL_X32, 0, 0}, // S_ZBELL_X31 - {SPR_BBLL, 4, 6, NULL, S_ZBELL_X33, 0, 0}, // S_ZBELL_X32 - {SPR_BBLL, 5, 6, NULL, S_ZBELL_X34, 0, 0}, // S_ZBELL_X33 - {SPR_BBLL, 6, 7, A_Scream, S_ZBELL_X35, 0, 0}, // S_ZBELL_X34 - {SPR_BBLL, 5, 6, NULL, S_ZBELL_X36, 0, 0}, // S_ZBELL_X35 - {SPR_BBLL, 4, 6, NULL, S_ZBELL_X37, 0, 0}, // S_ZBELL_X36 - {SPR_BBLL, 0, 6, NULL, S_ZBELL_X38, 0, 0}, // S_ZBELL_X37 - {SPR_BBLL, 1, 6, NULL, S_ZBELL_X39, 0, 0}, // S_ZBELL_X38 - {SPR_BBLL, 2, 6, NULL, S_ZBELL_X40, 0, 0}, // S_ZBELL_X39 - {SPR_BBLL, 1, 7, NULL, S_ZBELL_X41, 0, 0}, // S_ZBELL_X40 - {SPR_BBLL, 0, 8, NULL, S_ZBELL_X42, 0, 0}, // S_ZBELL_X41 - {SPR_BBLL, 4, 12, NULL, S_ZBELL_X43, 0, 0}, // S_ZBELL_X42 - {SPR_BBLL, 0, 10, NULL, S_ZBELL_X44, 0, 0}, // S_ZBELL_X43 - {SPR_BBLL, 1, 12, NULL, S_ZBELL_X45, 0, 0}, // S_ZBELL_X44 - {SPR_BBLL, 0, 12, NULL, S_ZBELL_X46, 0, 0}, // S_ZBELL_X45 - {SPR_BBLL, 4, 14, NULL, S_ZBELL_X47, 0, 0}, // S_ZBELL_X46 - {SPR_BBLL, 0, 1, A_BellReset2, S_ZBELL, 0, 0}, // S_ZBELL_X47 - {SPR_CAND, 32768, 5, NULL, S_ZBLUE_CANDLE2, 0, 0}, // S_ZBLUE_CANDLE1 - {SPR_CAND, 32769, 5, NULL, S_ZBLUE_CANDLE3, 0, 0}, // S_ZBLUE_CANDLE2 - {SPR_CAND, 32770, 5, NULL, S_ZBLUE_CANDLE4, 0, 0}, // S_ZBLUE_CANDLE3 - {SPR_CAND, 32771, 5, NULL, S_ZBLUE_CANDLE5, 0, 0}, // S_ZBLUE_CANDLE4 - {SPR_CAND, 32772, 5, NULL, S_ZBLUE_CANDLE1, 0, 0}, // S_ZBLUE_CANDLE5 - {SPR_IRON, 0, -1, NULL, S_NULL, 0, 0}, // S_ZIRON_MAIDEN - {SPR_XMAS, 0, -1, NULL, S_NULL, 0, 0}, // S_ZXMAS_TREE - {SPR_XMAS, 0, 4, A_TreeDeath, S_ZXMAS_TREE, 0, 0}, // S_ZXMAS_TREE_DIE - {SPR_XMAS, 32769, 6, NULL, S_ZXMAS_TREE_X2, 0, 0}, // S_ZXMAS_TREE_X1 - {SPR_XMAS, 32770, 6, A_Scream, S_ZXMAS_TREE_X3, 0, 0}, // S_ZXMAS_TREE_X2 - {SPR_XMAS, 32771, 5, NULL, S_ZXMAS_TREE_X4, 0, 0}, // S_ZXMAS_TREE_X3 - {SPR_XMAS, 32772, 5, A_Explode, S_ZXMAS_TREE_X5, 0, 0}, // S_ZXMAS_TREE_X4 - {SPR_XMAS, 32773, 5, NULL, S_ZXMAS_TREE_X6, 0, 0}, // S_ZXMAS_TREE_X5 - {SPR_XMAS, 32774, 4, NULL, S_ZXMAS_TREE_X7, 0, 0}, // S_ZXMAS_TREE_X6 - {SPR_XMAS, 7, 5, NULL, S_ZXMAS_TREE_X8, 0, 0}, // S_ZXMAS_TREE_X7 - {SPR_XMAS, 8, 4, A_NoBlocking, S_ZXMAS_TREE_X9, 0, 0}, // S_ZXMAS_TREE_X8 - {SPR_XMAS, 9, 4, NULL, S_ZXMAS_TREE_X10, 0, 0}, // S_ZXMAS_TREE_X9 - {SPR_XMAS, 10, -1, NULL, S_NULL, 0, 0}, // S_ZXMAS_TREE_X10 - {SPR_CDRN, 32769, 4, NULL, S_ZCAULDRON2, 0, 0}, // S_ZCAULDRON1 - {SPR_CDRN, 32770, 4, NULL, S_ZCAULDRON3, 0, 0}, // S_ZCAULDRON2 - {SPR_CDRN, 32771, 4, NULL, S_ZCAULDRON4, 0, 0}, // S_ZCAULDRON3 - {SPR_CDRN, 32772, 4, NULL, S_ZCAULDRON5, 0, 0}, // S_ZCAULDRON4 - {SPR_CDRN, 32773, 4, NULL, S_ZCAULDRON6, 0, 0}, // S_ZCAULDRON5 - {SPR_CDRN, 32774, 4, NULL, S_ZCAULDRON7, 0, 0}, // S_ZCAULDRON6 - {SPR_CDRN, 32775, 4, NULL, S_ZCAULDRON1, 0, 0}, // S_ZCAULDRON7 - {SPR_CDRN, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCAULDRON_U - {SPR_CHNS, 0, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINBIT32 - {SPR_CHNS, 1, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINBIT64 - {SPR_CHNS, 2, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_HEART - {SPR_CHNS, 3, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_HOOK1 - {SPR_CHNS, 4, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_HOOK2 - {SPR_CHNS, 5, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_SPIKE - {SPR_CHNS, 6, -1, NULL, S_NULL, 0, 0}, // S_ZCHAINEND_SKULL - {SPR_TST1, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT1 - {SPR_TST2, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT2 - {SPR_TST3, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT3 - {SPR_TST4, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT4 - {SPR_TST5, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT5 - {SPR_TST6, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT6 - {SPR_TST7, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT7 - {SPR_TST8, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT8 - {SPR_TST9, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT9 - {SPR_TST0, 0, -1, NULL, S_NULL, 0, 0}, // S_TABLE_SHIT10 - {SPR_TELE, 32768, 6, NULL, S_TFOG2, 0, 0}, // S_TFOG1 - {SPR_TELE, 32769, 6, NULL, S_TFOG3, 0, 0}, // S_TFOG2 - {SPR_TELE, 32770, 6, NULL, S_TFOG4, 0, 0}, // S_TFOG3 - {SPR_TELE, 32771, 6, NULL, S_TFOG5, 0, 0}, // S_TFOG4 - {SPR_TELE, 32772, 6, NULL, S_TFOG6, 0, 0}, // S_TFOG5 - {SPR_TELE, 32773, 6, NULL, S_TFOG7, 0, 0}, // S_TFOG6 - {SPR_TELE, 32774, 6, NULL, S_TFOG8, 0, 0}, // S_TFOG7 - {SPR_TELE, 32775, 6, NULL, S_TFOG9, 0, 0}, // S_TFOG8 - {SPR_TELE, 32774, 6, NULL, S_TFOG10, 0, 0}, // S_TFOG9 - {SPR_TELE, 32773, 6, NULL, S_TFOG11, 0, 0}, // S_TFOG10 - {SPR_TELE, 32772, 6, NULL, S_TFOG12, 0, 0}, // S_TFOG11 - {SPR_TELE, 32771, 6, NULL, S_TFOG13, 0, 0}, // S_TFOG12 - {SPR_TELE, 32770, 6, NULL, S_NULL, 0, 0}, // S_TFOG13 - {SPR_TSMK, 0, 4, NULL, S_TELESMOKE2, 0, 0}, // S_TELESMOKE1 - {SPR_TSMK, 1, 3, NULL, S_TELESMOKE3, 0, 0}, // S_TELESMOKE2 - {SPR_TSMK, 2, 4, NULL, S_TELESMOKE4, 0, 0}, // S_TELESMOKE3 - {SPR_TSMK, 3, 3, NULL, S_TELESMOKE5, 0, 0}, // S_TELESMOKE4 - {SPR_TSMK, 4, 4, NULL, S_TELESMOKE6, 0, 0}, // S_TELESMOKE5 - {SPR_TSMK, 5, 3, NULL, S_TELESMOKE7, 0, 0}, // S_TELESMOKE6 - {SPR_TSMK, 6, 4, NULL, S_TELESMOKE8, 0, 0}, // S_TELESMOKE7 - {SPR_TSMK, 7, 3, NULL, S_TELESMOKE9, 0, 0}, // S_TELESMOKE8 - {SPR_TSMK, 8, 4, NULL, S_TELESMOKE10, 0, 0}, // S_TELESMOKE9 - {SPR_TSMK, 9, 3, NULL, S_TELESMOKE11, 0, 0}, // S_TELESMOKE10 - {SPR_TSMK, 10, 4, NULL, S_TELESMOKE12, 0, 0}, // S_TELESMOKE11 - {SPR_TSMK, 11, 3, NULL, S_TELESMOKE13, 0, 0}, // S_TELESMOKE12 - {SPR_TSMK, 12, 4, NULL, S_TELESMOKE14, 0, 0}, // S_TELESMOKE13 - {SPR_TSMK, 13, 3, NULL, S_TELESMOKE15, 0, 0}, // S_TELESMOKE14 - {SPR_TSMK, 14, 4, NULL, S_TELESMOKE16, 0, 0}, // S_TELESMOKE15 - {SPR_TSMK, 15, 3, NULL, S_TELESMOKE17, 0, 0}, // S_TELESMOKE16 - {SPR_TSMK, 16, 4, NULL, S_TELESMOKE18, 0, 0}, // S_TELESMOKE17 - {SPR_TSMK, 17, 3, NULL, S_TELESMOKE19, 0, 0}, // S_TELESMOKE18 - {SPR_TSMK, 18, 4, NULL, S_TELESMOKE20, 0, 0}, // S_TELESMOKE19 - {SPR_TSMK, 19, 3, NULL, S_TELESMOKE21, 0, 0}, // S_TELESMOKE20 - {SPR_TSMK, 20, 4, NULL, S_TELESMOKE22, 0, 0}, // S_TELESMOKE21 - {SPR_TSMK, 21, 3, NULL, S_TELESMOKE23, 0, 0}, // S_TELESMOKE22 - {SPR_TSMK, 22, 4, NULL, S_TELESMOKE24, 0, 0}, // S_TELESMOKE23 - {SPR_TSMK, 23, 3, NULL, S_TELESMOKE25, 0, 0}, // S_TELESMOKE24 - {SPR_TSMK, 24, 4, NULL, S_TELESMOKE26, 0, 0}, // S_TELESMOKE25 - {SPR_TSMK, 25, 3, NULL, S_TELESMOKE1, 0, 0}, // S_TELESMOKE26 - {SPR_FPCH, 0, 0, A_Light0, S_NULL, 0, 0}, // S_LIGHTDONE - {SPR_FPCH, 0, 1, A_WeaponReady, S_PUNCHREADY, 0, 0}, // S_PUNCHREADY - {SPR_FPCH, 0, 1, A_Lower, S_PUNCHDOWN, 0, 0}, // S_PUNCHDOWN - {SPR_FPCH, 0, 1, A_Raise, S_PUNCHUP, 0, 0}, // S_PUNCHUP - {SPR_FPCH, 1, 5, NULL, S_PUNCHATK1_2, 5, 40}, // S_PUNCHATK1_1 - {SPR_FPCH, 2, 4, NULL, S_PUNCHATK1_3, 5, 40}, // S_PUNCHATK1_2 - {SPR_FPCH, 3, 4, A_FPunchAttack, S_PUNCHATK1_4, 5, 40}, // S_PUNCHATK1_3 - {SPR_FPCH, 2, 4, NULL, S_PUNCHATK1_5, 5, 40}, // S_PUNCHATK1_4 - {SPR_FPCH, 1, 5, A_ReFire, S_PUNCHREADY, 5, 40}, // S_PUNCHATK1_5 - {SPR_FPCH, 3, 4, NULL, S_PUNCHATK2_2, 5, 40}, // S_PUNCHATK2_1 - {SPR_FPCH, 4, 4, NULL, S_PUNCHATK2_3, 5, 40}, // S_PUNCHATK2_2 - {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_4, 15, 50}, // S_PUNCHATK2_3 - {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_5, 25, 60}, // S_PUNCHATK2_4 - {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_6, 35, 70}, // S_PUNCHATK2_5 - {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_7, 45, 80}, // S_PUNCHATK2_6 - {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_8, 55, 90}, // S_PUNCHATK2_7 - {SPR_FPCH, 4, 1, NULL, S_PUNCHATK2_9, 65, 100}, // S_PUNCHATK2_8 - {SPR_FPCH, 4, 10, NULL, S_PUNCHREADY, 0, 150}, // S_PUNCHATK2_9 - {SPR_FHFX, 18, 4, NULL, S_PUNCHPUFF2, 0, 0}, // S_PUNCHPUFF1 - {SPR_FHFX, 19, 4, NULL, S_PUNCHPUFF3, 0, 0}, // S_PUNCHPUFF2 - {SPR_FHFX, 20, 4, NULL, S_PUNCHPUFF4, 0, 0}, // S_PUNCHPUFF3 - {SPR_FHFX, 21, 4, NULL, S_PUNCHPUFF5, 0, 0}, // S_PUNCHPUFF4 - {SPR_FHFX, 22, 4, NULL, S_NULL, 0, 0}, // S_PUNCHPUFF5 - {SPR_WFAX, 0, -1, NULL, S_NULL, 0, 0}, // S_AXE - {SPR_FAXE, 0, 1, A_WeaponReady, S_FAXEREADY, 0, 0}, // S_FAXEREADY - {SPR_FAXE, 0, 1, A_Lower, S_FAXEDOWN, 0, 0}, // S_FAXEDOWN - {SPR_FAXE, 0, 1, A_Raise, S_FAXEUP, 0, 0}, // S_FAXEUP - {SPR_FAXE, 1, 4, NULL, S_FAXEATK_2, 15, 32}, // S_FAXEATK_1 - {SPR_FAXE, 2, 3, NULL, S_FAXEATK_3, 15, 32}, // S_FAXEATK_2 - {SPR_FAXE, 3, 2, NULL, S_FAXEATK_4, 15, 32}, // S_FAXEATK_3 - {SPR_FAXE, 3, 1, A_FAxeAttack, S_FAXEATK_5, -5, 70}, // S_FAXEATK_4 - {SPR_FAXE, 3, 2, NULL, S_FAXEATK_6, -25, 90}, // S_FAXEATK_5 - {SPR_FAXE, 4, 1, NULL, S_FAXEATK_7, 15, 32}, // S_FAXEATK_6 - {SPR_FAXE, 4, 2, NULL, S_FAXEATK_8, 10, 54}, // S_FAXEATK_7 - {SPR_FAXE, 4, 7, NULL, S_FAXEATK_9, 10, 150}, // S_FAXEATK_8 - {SPR_FAXE, 0, 1, A_ReFire, S_FAXEATK_10, 0, 60}, // S_FAXEATK_9 - {SPR_FAXE, 0, 1, NULL, S_FAXEATK_11, 0, 52}, // S_FAXEATK_10 - {SPR_FAXE, 0, 1, NULL, S_FAXEATK_12, 0, 44}, // S_FAXEATK_11 - {SPR_FAXE, 0, 1, NULL, S_FAXEATK_13, 0, 36}, // S_FAXEATK_12 - {SPR_FAXE, 0, 1, NULL, S_FAXEREADY, 0, 0}, // S_FAXEATK_13 - {SPR_FAXE, 11, 1, A_WeaponReady, S_FAXEREADY_G1, 0, 0}, // S_FAXEREADY_G - {SPR_FAXE, 11, 1, A_WeaponReady, S_FAXEREADY_G2, 0, 0}, // S_FAXEREADY_G1 - {SPR_FAXE, 11, 1, A_WeaponReady, S_FAXEREADY_G3, 0, 0}, // S_FAXEREADY_G2 - {SPR_FAXE, 12, 1, A_WeaponReady, S_FAXEREADY_G4, 0, 0}, // S_FAXEREADY_G3 - {SPR_FAXE, 12, 1, A_WeaponReady, S_FAXEREADY_G5, 0, 0}, // S_FAXEREADY_G4 - {SPR_FAXE, 12, 1, A_WeaponReady, S_FAXEREADY_G, 0, 0}, // S_FAXEREADY_G5 - {SPR_FAXE, 11, 1, A_Lower, S_FAXEDOWN_G, 0, 0}, // S_FAXEDOWN_G - {SPR_FAXE, 11, 1, A_Raise, S_FAXEUP_G, 0, 0}, // S_FAXEUP_G - {SPR_FAXE, 13, 4, NULL, S_FAXEATK_G2, 15, 32}, // S_FAXEATK_G1 - {SPR_FAXE, 14, 3, NULL, S_FAXEATK_G3, 15, 32}, // S_FAXEATK_G2 - {SPR_FAXE, 15, 2, NULL, S_FAXEATK_G4, 15, 32}, // S_FAXEATK_G3 - {SPR_FAXE, 15, 1, A_FAxeAttack, S_FAXEATK_G5, -5, 70}, // S_FAXEATK_G4 - {SPR_FAXE, 15, 2, NULL, S_FAXEATK_G6, -25, 90}, // S_FAXEATK_G5 - {SPR_FAXE, 16, 1, NULL, S_FAXEATK_G7, 15, 32}, // S_FAXEATK_G6 - {SPR_FAXE, 16, 2, NULL, S_FAXEATK_G8, 10, 54}, // S_FAXEATK_G7 - {SPR_FAXE, 16, 7, NULL, S_FAXEATK_G9, 10, 150}, // S_FAXEATK_G8 - {SPR_FAXE, 0, 1, A_ReFire, S_FAXEATK_G10, 0, 60}, // S_FAXEATK_G9 - {SPR_FAXE, 0, 1, NULL, S_FAXEATK_G11, 0, 52}, // S_FAXEATK_G10 - {SPR_FAXE, 0, 1, NULL, S_FAXEATK_G12, 0, 44}, // S_FAXEATK_G11 - {SPR_FAXE, 0, 1, NULL, S_FAXEATK_G13, 0, 36}, // S_FAXEATK_G12 - {SPR_FAXE, 0, 1, NULL, S_FAXEREADY_G, 0, 0}, // S_FAXEATK_G13 - {SPR_FAXE, 32785, 4, NULL, S_AXEPUFF_GLOW2, 0, 0}, // S_AXEPUFF_GLOW1 - {SPR_FAXE, 32786, 4, NULL, S_AXEPUFF_GLOW3, 0, 0}, // S_AXEPUFF_GLOW2 - {SPR_FAXE, 32787, 4, NULL, S_AXEPUFF_GLOW4, 0, 0}, // S_AXEPUFF_GLOW3 - {SPR_FAXE, 32788, 4, NULL, S_AXEPUFF_GLOW5, 0, 0}, // S_AXEPUFF_GLOW4 - {SPR_FAXE, 32789, 4, NULL, S_AXEPUFF_GLOW6, 0, 0}, // S_AXEPUFF_GLOW5 - {SPR_FAXE, 32790, 4, NULL, S_AXEPUFF_GLOW7, 0, 0}, // S_AXEPUFF_GLOW6 - {SPR_FAXE, 32791, 4, NULL, S_NULL, 0, 0}, // S_AXEPUFF_GLOW7 - {SPR_FAXE, 5, 3, NULL, S_AXEBLOOD2, 0, 0}, // S_AXEBLOOD1 - {SPR_FAXE, 6, 3, NULL, S_AXEBLOOD3, 0, 0}, // S_AXEBLOOD2 - {SPR_FAXE, 7, 3, NULL, S_AXEBLOOD4, 0, 0}, // S_AXEBLOOD3 - {SPR_FAXE, 8, 3, NULL, S_AXEBLOOD5, 0, 0}, // S_AXEBLOOD4 - {SPR_FAXE, 9, 3, NULL, S_AXEBLOOD6, 0, 0}, // S_AXEBLOOD5 - {SPR_FAXE, 10, 3, NULL, S_NULL, 0, 0}, // S_AXEBLOOD6 - {SPR_WFHM, 0, -1, NULL, S_NULL, 0, 0}, // S_HAMM - {SPR_FHMR, 0, 1, A_WeaponReady, S_FHAMMERREADY, 0, 0}, // S_FHAMMERREADY - {SPR_FHMR, 0, 1, A_Lower, S_FHAMMERDOWN, 0, 0}, // S_FHAMMERDOWN - {SPR_FHMR, 0, 1, A_Raise, S_FHAMMERUP, 0, 0}, // S_FHAMMERUP - {SPR_FHMR, 1, 6, NULL, S_FHAMMERATK_2, 5, 0}, // S_FHAMMERATK_1 - {SPR_FHMR, 2, 3, A_FHammerAttack, S_FHAMMERATK_3, 5, 0}, // S_FHAMMERATK_2 - {SPR_FHMR, 3, 3, NULL, S_FHAMMERATK_4, 5, 0}, // S_FHAMMERATK_3 - {SPR_FHMR, 4, 2, NULL, S_FHAMMERATK_5, 5, 0}, // S_FHAMMERATK_4 - {SPR_FHMR, 4, 10, A_FHammerThrow, S_FHAMMERATK_6, 5, 150}, // S_FHAMMERATK_5 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_7, 0, 60}, // S_FHAMMERATK_6 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_8, 0, 55}, // S_FHAMMERATK_7 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_9, 0, 50}, // S_FHAMMERATK_8 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_10, 0, 45}, // S_FHAMMERATK_9 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_11, 0, 40}, // S_FHAMMERATK_10 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERATK_12, 0, 35}, // S_FHAMMERATK_11 - {SPR_FHMR, 0, 1, NULL, S_FHAMMERREADY, 0, 0}, // S_FHAMMERATK_12 - {SPR_FHFX, 32768, 2, NULL, S_HAMMER_MISSILE_2, 0, 0}, // S_HAMMER_MISSILE_1 - {SPR_FHFX, 32769, 2, A_ContMobjSound, S_HAMMER_MISSILE_3, 0, 0}, // S_HAMMER_MISSILE_2 - {SPR_FHFX, 32770, 2, NULL, S_HAMMER_MISSILE_4, 0, 0}, // S_HAMMER_MISSILE_3 - {SPR_FHFX, 32771, 2, NULL, S_HAMMER_MISSILE_5, 0, 0}, // S_HAMMER_MISSILE_4 - {SPR_FHFX, 32772, 2, NULL, S_HAMMER_MISSILE_6, 0, 0}, // S_HAMMER_MISSILE_5 - {SPR_FHFX, 32773, 2, NULL, S_HAMMER_MISSILE_7, 0, 0}, // S_HAMMER_MISSILE_6 - {SPR_FHFX, 32774, 2, NULL, S_HAMMER_MISSILE_8, 0, 0}, // S_HAMMER_MISSILE_7 - {SPR_FHFX, 32775, 2, NULL, S_HAMMER_MISSILE_1, 0, 0}, // S_HAMMER_MISSILE_8 - {SPR_FHFX, 32776, 3, NULL, S_HAMMER_MISSILE_X2, 0, 0}, // S_HAMMER_MISSILE_X1 - {SPR_FHFX, 32777, 3, NULL, S_HAMMER_MISSILE_X3, 0, 0}, // S_HAMMER_MISSILE_X2 - {SPR_FHFX, 32778, 3, A_Explode, S_HAMMER_MISSILE_X4, 0, 0}, // S_HAMMER_MISSILE_X3 - {SPR_FHFX, 32779, 3, NULL, S_HAMMER_MISSILE_X5, 0, 0}, // S_HAMMER_MISSILE_X4 - {SPR_FHFX, 32780, 3, NULL, S_HAMMER_MISSILE_X6, 0, 0}, // S_HAMMER_MISSILE_X5 - {SPR_FHFX, 13, 3, NULL, S_HAMMER_MISSILE_X7, 0, 0}, // S_HAMMER_MISSILE_X6 - {SPR_FHFX, 32782, 3, NULL, S_HAMMER_MISSILE_X8, 0, 0}, // S_HAMMER_MISSILE_X7 - {SPR_FHFX, 32783, 3, NULL, S_HAMMER_MISSILE_X9, 0, 0}, // S_HAMMER_MISSILE_X8 - {SPR_FHFX, 32784, 3, NULL, S_HAMMER_MISSILE_X10, 0, 0}, // S_HAMMER_MISSILE_X9 - {SPR_FHFX, 32785, 3, NULL, S_NULL, 0, 0}, // S_HAMMER_MISSILE_X10 - {SPR_FHFX, 18, 4, NULL, S_HAMMERPUFF2, 0, 0}, // S_HAMMERPUFF1 - {SPR_FHFX, 19, 4, NULL, S_HAMMERPUFF3, 0, 0}, // S_HAMMERPUFF2 - {SPR_FHFX, 20, 4, NULL, S_HAMMERPUFF4, 0, 0}, // S_HAMMERPUFF3 - {SPR_FHFX, 21, 4, NULL, S_HAMMERPUFF5, 0, 0}, // S_HAMMERPUFF4 - {SPR_FHFX, 22, 4, NULL, S_NULL, 0, 0}, // S_HAMMERPUFF5 - {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY1, 0, 0}, // S_FSWORDREADY - {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY2, 0, 0}, // S_FSWORDREADY1 - {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY3, 0, 0}, // S_FSWORDREADY2 - {SPR_FSRD, 32768, 1, A_WeaponReady, S_FSWORDREADY4, 0, 0}, // S_FSWORDREADY3 - {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY5, 0, 0}, // S_FSWORDREADY4 - {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY6, 0, 0}, // S_FSWORDREADY5 - {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY7, 0, 0}, // S_FSWORDREADY6 - {SPR_FSRD, 32769, 1, A_WeaponReady, S_FSWORDREADY8, 0, 0}, // S_FSWORDREADY7 - {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY9, 0, 0}, // S_FSWORDREADY8 - {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY10, 0, 0}, // S_FSWORDREADY9 - {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY11, 0, 0}, // S_FSWORDREADY10 - {SPR_FSRD, 32770, 1, A_WeaponReady, S_FSWORDREADY, 0, 0}, // S_FSWORDREADY11 - {SPR_FSRD, 32768, 1, A_Lower, S_FSWORDDOWN, 0, 0}, // S_FSWORDDOWN - {SPR_FSRD, 32768, 1, A_Raise, S_FSWORDUP, 0, 0}, // S_FSWORDUP - {SPR_FSRD, 32771, 3, NULL, S_FSWORDATK_2, 5, 36}, // S_FSWORDATK_1 - {SPR_FSRD, 32772, 3, NULL, S_FSWORDATK_3, 5, 36}, // S_FSWORDATK_2 - {SPR_FSRD, 32773, 2, NULL, S_FSWORDATK_4, 5, 36}, // S_FSWORDATK_3 - {SPR_FSRD, 32774, 3, A_FSwordAttack, S_FSWORDATK_5, 5, 36}, // S_FSWORDATK_4 - {SPR_FSRD, 32775, 2, NULL, S_FSWORDATK_6, 5, 36}, // S_FSWORDATK_5 - {SPR_FSRD, 32776, 2, NULL, S_FSWORDATK_7, 5, 36}, // S_FSWORDATK_6 - {SPR_FSRD, 32776, 10, NULL, S_FSWORDATK_8, 5, 150}, // S_FSWORDATK_7 - {SPR_FSRD, 32768, 1, NULL, S_FSWORDATK_9, 5, 60}, // S_FSWORDATK_8 - {SPR_FSRD, 32769, 1, NULL, S_FSWORDATK_10, 5, 55}, // S_FSWORDATK_9 - {SPR_FSRD, 32770, 1, NULL, S_FSWORDATK_11, 5, 50}, // S_FSWORDATK_10 - {SPR_FSRD, 32768, 1, NULL, S_FSWORDATK_12, 5, 45}, // S_FSWORDATK_11 - {SPR_FSRD, 32769, 1, NULL, S_FSWORDREADY, 5, 40}, // S_FSWORDATK_12 - {SPR_FSFX, 32768, 3, NULL, S_FSWORD_MISSILE2, 0, 0}, // S_FSWORD_MISSILE1 - {SPR_FSFX, 32769, 3, NULL, S_FSWORD_MISSILE3, 0, 0}, // S_FSWORD_MISSILE2 - {SPR_FSFX, 32770, 3, NULL, S_FSWORD_MISSILE1, 0, 0}, // S_FSWORD_MISSILE3 - {SPR_FSFX, 32771, 4, NULL, S_FSWORD_MISSILE_X2, 0, 0}, // S_FSWORD_MISSILE_X1 - {SPR_FSFX, 32772, 3, A_FSwordFlames, S_FSWORD_MISSILE_X3, 0, 0}, // S_FSWORD_MISSILE_X2 - {SPR_FSFX, 32773, 4, A_Explode, S_FSWORD_MISSILE_X4, 0, 0}, // S_FSWORD_MISSILE_X3 - {SPR_FSFX, 32774, 3, NULL, S_FSWORD_MISSILE_X5, 0, 0}, // S_FSWORD_MISSILE_X4 - {SPR_FSFX, 32775, 4, NULL, S_FSWORD_MISSILE_X6, 0, 0}, // S_FSWORD_MISSILE_X5 - {SPR_FSFX, 32776, 3, NULL, S_FSWORD_MISSILE_X7, 0, 0}, // S_FSWORD_MISSILE_X6 - {SPR_FSFX, 32777, 4, NULL, S_FSWORD_MISSILE_X8, 0, 0}, // S_FSWORD_MISSILE_X7 - {SPR_FSFX, 32778, 3, NULL, S_FSWORD_MISSILE_X9, 0, 0}, // S_FSWORD_MISSILE_X8 - {SPR_FSFX, 32779, 3, NULL, S_FSWORD_MISSILE_X10, 0, 0}, // S_FSWORD_MISSILE_X9 - {SPR_FSFX, 32780, 3, NULL, S_NULL, 0, 0}, // S_FSWORD_MISSILE_X10 - {SPR_FSFX, 32781, 3, NULL, S_FSWORD_FLAME2, 0, 0}, // S_FSWORD_FLAME1 - {SPR_FSFX, 32782, 3, NULL, S_FSWORD_FLAME3, 0, 0}, // S_FSWORD_FLAME2 - {SPR_FSFX, 32783, 3, NULL, S_FSWORD_FLAME4, 0, 0}, // S_FSWORD_FLAME3 - {SPR_FSFX, 32784, 3, NULL, S_FSWORD_FLAME5, 0, 0}, // S_FSWORD_FLAME4 - {SPR_FSFX, 32785, 3, NULL, S_FSWORD_FLAME6, 0, 0}, // S_FSWORD_FLAME5 - {SPR_FSFX, 32786, 3, NULL, S_FSWORD_FLAME7, 0, 0}, // S_FSWORD_FLAME6 - {SPR_FSFX, 32787, 3, NULL, S_FSWORD_FLAME8, 0, 0}, // S_FSWORD_FLAME7 - {SPR_FSFX, 32788, 3, NULL, S_FSWORD_FLAME9, 0, 0}, // S_FSWORD_FLAME8 - {SPR_FSFX, 32789, 3, NULL, S_FSWORD_FLAME10, 0, 0}, // S_FSWORD_FLAME9 - {SPR_FSFX, 32790, 3, NULL, S_NULL, 0, 0}, // S_FSWORD_FLAME10 - {SPR_CMCE, 0, 1, A_WeaponReady, S_CMACEREADY, 0, 0}, // S_CMACEREADY - {SPR_CMCE, 0, 1, A_Lower, S_CMACEDOWN, 0, 0}, // S_CMACEDOWN - {SPR_CMCE, 0, 1, A_Raise, S_CMACEUP, 0, 0}, // S_CMACEUP - {SPR_CMCE, 1, 2, NULL, S_CMACEATK_2, 60, 20}, // S_CMACEATK_1 - {SPR_CMCE, 1, 1, NULL, S_CMACEATK_3, 30, 33}, // S_CMACEATK_2 - {SPR_CMCE, 1, 2, NULL, S_CMACEATK_4, 8, 45}, // S_CMACEATK_3 - {SPR_CMCE, 2, 1, NULL, S_CMACEATK_5, 8, 45}, // S_CMACEATK_4 - {SPR_CMCE, 3, 1, NULL, S_CMACEATK_6, 8, 45}, // S_CMACEATK_5 - {SPR_CMCE, 4, 1, NULL, S_CMACEATK_7, 8, 45}, // S_CMACEATK_6 - {SPR_CMCE, 4, 1, A_CMaceAttack, S_CMACEATK_8, -11, 58}, // S_CMACEATK_7 - {SPR_CMCE, 5, 1, NULL, S_CMACEATK_9, 8, 45}, // S_CMACEATK_8 - {SPR_CMCE, 5, 2, NULL, S_CMACEATK_10, -8, 74}, // S_CMACEATK_9 - {SPR_CMCE, 5, 1, NULL, S_CMACEATK_11, -20, 96}, // S_CMACEATK_10 - {SPR_CMCE, 5, 8, NULL, S_CMACEATK_12, -33, 160}, // S_CMACEATK_11 - {SPR_CMCE, 0, 2, A_ReFire, S_CMACEATK_13, 8, 75}, // S_CMACEATK_12 - {SPR_CMCE, 0, 1, NULL, S_CMACEATK_14, 8, 65}, // S_CMACEATK_13 - {SPR_CMCE, 0, 2, NULL, S_CMACEATK_15, 8, 60}, // S_CMACEATK_14 - {SPR_CMCE, 0, 1, NULL, S_CMACEATK_16, 8, 55}, // S_CMACEATK_15 - {SPR_CMCE, 0, 2, NULL, S_CMACEATK_17, 8, 50}, // S_CMACEATK_16 - {SPR_CMCE, 0, 1, NULL, S_CMACEREADY, 8, 45}, // S_CMACEATK_17 - {SPR_WCSS, 0, -1, NULL, S_NULL, 0, 0}, // S_CSTAFF - {SPR_CSSF, 2, 4, NULL, S_CSTAFFREADY1, 0, 0}, // S_CSTAFFREADY - {SPR_CSSF, 1, 3, A_CStaffInitBlink, S_CSTAFFREADY2, 0, 0}, // S_CSTAFFREADY1 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY3, 0, 0}, // S_CSTAFFREADY2 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY4, 0, 0}, // S_CSTAFFREADY3 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY5, 0, 0}, // S_CSTAFFREADY4 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY6, 0, 0}, // S_CSTAFFREADY5 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY7, 0, 0}, // S_CSTAFFREADY6 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY8, 0, 0}, // S_CSTAFFREADY7 - {SPR_CSSF, 0, 1, A_WeaponReady, S_CSTAFFREADY9, 0, 0}, // S_CSTAFFREADY8 - {SPR_CSSF, 0, 1, A_CStaffCheckBlink, S_CSTAFFREADY2, 0, 0}, // S_CSTAFFREADY9 - {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK2, 0, 0}, // S_CSTAFFBLINK1 - {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK3, 0, 0}, // S_CSTAFFBLINK2 - {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK4, 0, 0}, // S_CSTAFFBLINK3 - {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK5, 0, 0}, // S_CSTAFFBLINK4 - {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK6, 0, 0}, // S_CSTAFFBLINK5 - {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK7, 0, 0}, // S_CSTAFFBLINK6 - {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK8, 0, 0}, // S_CSTAFFBLINK7 - {SPR_CSSF, 2, 1, A_WeaponReady, S_CSTAFFBLINK9, 0, 0}, // S_CSTAFFBLINK8 - {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK10, 0, 0}, // S_CSTAFFBLINK9 - {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFBLINK11, 0, 0}, // S_CSTAFFBLINK10 - {SPR_CSSF, 1, 1, A_WeaponReady, S_CSTAFFREADY2, 0, 0}, // S_CSTAFFBLINK11 - {SPR_CSSF, 1, 3, NULL, S_CSTAFFDOWN2, 0, 0}, // S_CSTAFFDOWN - {SPR_CSSF, 2, 4, NULL, S_CSTAFFDOWN3, 0, 0}, // S_CSTAFFDOWN2 - {SPR_CSSF, 2, 1, A_Lower, S_CSTAFFDOWN3, 0, 0}, // S_CSTAFFDOWN3 - {SPR_CSSF, 2, 1, A_Raise, S_CSTAFFUP, 0, 0}, // S_CSTAFFUP - {SPR_CSSF, 0, 1, A_CStaffCheck, S_CSTAFFATK_2, 0, 45}, // S_CSTAFFATK_1 - {SPR_CSSF, 9, 1, A_CStaffAttack, S_CSTAFFATK_3, 0, 50}, // S_CSTAFFATK_2 - {SPR_CSSF, 9, 2, NULL, S_CSTAFFATK_4, 0, 50}, // S_CSTAFFATK_3 - {SPR_CSSF, 9, 2, NULL, S_CSTAFFATK_5, 0, 45}, // S_CSTAFFATK_4 - {SPR_CSSF, 0, 2, NULL, S_CSTAFFATK_6, 0, 40}, // S_CSTAFFATK_5 - {SPR_CSSF, 0, 2, NULL, S_CSTAFFREADY2, 0, 36}, // S_CSTAFFATK_6 - {SPR_CSSF, 10, 10, NULL, S_CSTAFFREADY2, 0, 36}, // S_CSTAFFATK2_1 - {SPR_CSSF, 32771, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE2, 0, 0}, // S_CSTAFF_MISSILE1 - {SPR_CSSF, 32771, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE3, 0, 0}, // S_CSTAFF_MISSILE2 - {SPR_CSSF, 32772, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE4, 0, 0}, // S_CSTAFF_MISSILE3 - {SPR_CSSF, 32772, 1, A_CStaffMissileSlither, S_CSTAFF_MISSILE1, 0, 0}, // S_CSTAFF_MISSILE4 - {SPR_CSSF, 32773, 4, NULL, S_CSTAFF_MISSILE_X2, 0, 0}, // S_CSTAFF_MISSILE_X1 - {SPR_CSSF, 32774, 4, NULL, S_CSTAFF_MISSILE_X3, 0, 0}, // S_CSTAFF_MISSILE_X2 - {SPR_CSSF, 32775, 3, NULL, S_CSTAFF_MISSILE_X4, 0, 0}, // S_CSTAFF_MISSILE_X3 - {SPR_CSSF, 32776, 3, NULL, S_NULL, 0, 0}, // S_CSTAFF_MISSILE_X4 - {SPR_FHFX, 18, 4, NULL, S_CSTAFFPUFF2, 0, 0}, // S_CSTAFFPUFF1 - {SPR_FHFX, 19, 4, NULL, S_CSTAFFPUFF3, 0, 0}, // S_CSTAFFPUFF2 - {SPR_FHFX, 20, 4, NULL, S_CSTAFFPUFF4, 0, 0}, // S_CSTAFFPUFF3 - {SPR_FHFX, 21, 4, NULL, S_CSTAFFPUFF5, 0, 0}, // S_CSTAFFPUFF4 - {SPR_FHFX, 22, 4, NULL, S_NULL, 0, 0}, // S_CSTAFFPUFF5 - {SPR_WCFM, 32768, 4, NULL, S_CFLAME2, 0, 0}, // S_CFLAME1 - {SPR_WCFM, 32769, 4, NULL, S_CFLAME3, 0, 0}, // S_CFLAME2 - {SPR_WCFM, 32770, 4, NULL, S_CFLAME4, 0, 0}, // S_CFLAME3 - {SPR_WCFM, 32771, 4, NULL, S_CFLAME5, 0, 0}, // S_CFLAME4 - {SPR_WCFM, 32772, 4, NULL, S_CFLAME6, 0, 0}, // S_CFLAME5 - {SPR_WCFM, 32773, 4, NULL, S_CFLAME7, 0, 0}, // S_CFLAME6 - {SPR_WCFM, 32774, 4, NULL, S_CFLAME8, 0, 0}, // S_CFLAME7 - {SPR_WCFM, 32775, 4, NULL, S_CFLAME1, 0, 0}, // S_CFLAME8 - {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY2, 0, 0}, // S_CFLAMEREADY1 - {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY3, 0, 0}, // S_CFLAMEREADY2 - {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY4, 0, 0}, // S_CFLAMEREADY3 - {SPR_CFLM, 0, 1, A_WeaponReady, S_CFLAMEREADY5, 0, 0}, // S_CFLAMEREADY4 - {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY6, 0, 0}, // S_CFLAMEREADY5 - {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY7, 0, 0}, // S_CFLAMEREADY6 - {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY8, 0, 0}, // S_CFLAMEREADY7 - {SPR_CFLM, 1, 1, A_WeaponReady, S_CFLAMEREADY9, 0, 0}, // S_CFLAMEREADY8 - {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY10, 0, 0}, // S_CFLAMEREADY9 - {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY11, 0, 0}, // S_CFLAMEREADY10 - {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY12, 0, 0}, // S_CFLAMEREADY11 - {SPR_CFLM, 2, 1, A_WeaponReady, S_CFLAMEREADY1, 0, 0}, // S_CFLAMEREADY12 - {SPR_CFLM, 0, 1, A_Lower, S_CFLAMEDOWN, 0, 0}, // S_CFLAMEDOWN - {SPR_CFLM, 0, 1, A_Raise, S_CFLAMEUP, 0, 0}, // S_CFLAMEUP - {SPR_CFLM, 0, 2, NULL, S_CFLAMEATK_2, 0, 40}, // S_CFLAMEATK_1 - {SPR_CFLM, 3, 2, NULL, S_CFLAMEATK_3, 0, 50}, // S_CFLAMEATK_2 - {SPR_CFLM, 3, 2, NULL, S_CFLAMEATK_4, 0, 36}, // S_CFLAMEATK_3 - {SPR_CFLM, 32772, 4, NULL, S_CFLAMEATK_5, 0, 0}, // S_CFLAMEATK_4 - {SPR_CFLM, 32773, 4, A_CFlameAttack, S_CFLAMEATK_6, 0, 0}, // S_CFLAMEATK_5 - {SPR_CFLM, 32772, 4, NULL, S_CFLAMEATK_7, 0, 0}, // S_CFLAMEATK_6 - {SPR_CFLM, 6, 2, NULL, S_CFLAMEATK_8, 0, 40}, // S_CFLAMEATK_7 - {SPR_CFLM, 6, 2, NULL, S_CFLAMEREADY1, 0, 0}, // S_CFLAMEATK_8 - {SPR_CFFX, 32781, 5, NULL, S_CFLAMEFLOOR2, 0, 0}, // S_CFLAMEFLOOR1 - {SPR_CFFX, 32782, 4, NULL, S_CFLAMEFLOOR3, 0, 0}, // S_CFLAMEFLOOR2 - {SPR_CFFX, 32783, 3, NULL, S_NULL, 0, 0}, // S_CFLAMEFLOOR3 - {SPR_CFFX, 32768, 3, NULL, S_FLAMEPUFF2, 0, 0}, // S_FLAMEPUFF1 - {SPR_CFFX, 32769, 3, NULL, S_FLAMEPUFF3, 0, 0}, // S_FLAMEPUFF2 - {SPR_CFFX, 32770, 3, NULL, S_FLAMEPUFF4, 0, 0}, // S_FLAMEPUFF3 - {SPR_CFFX, 32771, 4, NULL, S_FLAMEPUFF5, 0, 0}, // S_FLAMEPUFF4 - {SPR_CFFX, 32772, 3, NULL, S_FLAMEPUFF6, 0, 0}, // S_FLAMEPUFF5 - {SPR_CFFX, 32773, 4, NULL, S_FLAMEPUFF7, 0, 0}, // S_FLAMEPUFF6 - {SPR_CFFX, 32774, 3, NULL, S_FLAMEPUFF8, 0, 0}, // S_FLAMEPUFF7 - {SPR_CFFX, 32775, 4, NULL, S_FLAMEPUFF9, 0, 0}, // S_FLAMEPUFF8 - {SPR_CFFX, 32776, 3, NULL, S_FLAMEPUFF10, 0, 0}, // S_FLAMEPUFF9 - {SPR_CFFX, 32777, 4, NULL, S_FLAMEPUFF11, 0, 0}, // S_FLAMEPUFF10 - {SPR_CFFX, 32778, 3, NULL, S_FLAMEPUFF12, 0, 0}, // S_FLAMEPUFF11 - {SPR_CFFX, 32779, 4, NULL, S_FLAMEPUFF13, 0, 0}, // S_FLAMEPUFF12 - {SPR_CFFX, 32780, 3, NULL, S_NULL, 0, 0}, // S_FLAMEPUFF13 - {SPR_CFFX, 32768, 3, NULL, S_FLAMEPUFF2_2, 0, 0}, // S_FLAMEPUFF2_1 - {SPR_CFFX, 32769, 3, NULL, S_FLAMEPUFF2_3, 0, 0}, // S_FLAMEPUFF2_2 - {SPR_CFFX, 32770, 3, NULL, S_FLAMEPUFF2_4, 0, 0}, // S_FLAMEPUFF2_3 - {SPR_CFFX, 32771, 4, NULL, S_FLAMEPUFF2_5, 0, 0}, // S_FLAMEPUFF2_4 - {SPR_CFFX, 32772, 3, NULL, S_FLAMEPUFF2_6, 0, 0}, // S_FLAMEPUFF2_5 - {SPR_CFFX, 32773, 4, NULL, S_FLAMEPUFF2_7, 0, 0}, // S_FLAMEPUFF2_6 - {SPR_CFFX, 32774, 3, NULL, S_FLAMEPUFF2_8, 0, 0}, // S_FLAMEPUFF2_7 - {SPR_CFFX, 32775, 4, NULL, S_FLAMEPUFF2_9, 0, 0}, // S_FLAMEPUFF2_8 - {SPR_CFFX, 32776, 3, NULL, S_FLAMEPUFF2_10, 0, 0}, // S_FLAMEPUFF2_9 - {SPR_CFFX, 32770, 3, NULL, S_FLAMEPUFF2_11, 0, 0}, // S_FLAMEPUFF2_10 - {SPR_CFFX, 32771, 4, NULL, S_FLAMEPUFF2_12, 0, 0}, // S_FLAMEPUFF2_11 - {SPR_CFFX, 32772, 3, NULL, S_FLAMEPUFF2_13, 0, 0}, // S_FLAMEPUFF2_12 - {SPR_CFFX, 32773, 4, NULL, S_FLAMEPUFF2_14, 0, 0}, // S_FLAMEPUFF2_13 - {SPR_CFFX, 32774, 3, NULL, S_FLAMEPUFF2_15, 0, 0}, // S_FLAMEPUFF2_14 - {SPR_CFFX, 32775, 4, NULL, S_FLAMEPUFF2_16, 0, 0}, // S_FLAMEPUFF2_15 - {SPR_CFFX, 32776, 3, NULL, S_FLAMEPUFF2_17, 0, 0}, // S_FLAMEPUFF2_16 - {SPR_CFFX, 32777, 4, NULL, S_FLAMEPUFF2_18, 0, 0}, // S_FLAMEPUFF2_17 - {SPR_CFFX, 32778, 3, NULL, S_FLAMEPUFF2_19, 0, 0}, // S_FLAMEPUFF2_18 - {SPR_CFFX, 32779, 4, NULL, S_FLAMEPUFF2_20, 0, 0}, // S_FLAMEPUFF2_19 - {SPR_CFFX, 32780, 3, NULL, S_NULL, 0, 0}, // S_FLAMEPUFF2_20 - {SPR_CFCF, 32768, 4, NULL, S_CIRCLE_FLAME2, 0, 0}, // S_CIRCLE_FLAME1 - {SPR_CFCF, 32769, 2, A_CFlameRotate, S_CIRCLE_FLAME3, 0, 0}, // S_CIRCLE_FLAME2 - {SPR_CFCF, 32770, 2, NULL, S_CIRCLE_FLAME4, 0, 0}, // S_CIRCLE_FLAME3 - {SPR_CFCF, 32771, 1, NULL, S_CIRCLE_FLAME5, 0, 0}, // S_CIRCLE_FLAME4 - {SPR_CFCF, 32772, 2, NULL, S_CIRCLE_FLAME6, 0, 0}, // S_CIRCLE_FLAME5 - {SPR_CFCF, 32773, 2, A_CFlameRotate, S_CIRCLE_FLAME7, 0, 0}, // S_CIRCLE_FLAME6 - {SPR_CFCF, 32774, 1, NULL, S_CIRCLE_FLAME8, 0, 0}, // S_CIRCLE_FLAME7 - {SPR_CFCF, 32775, 2, NULL, S_CIRCLE_FLAME9, 0, 0}, // S_CIRCLE_FLAME8 - {SPR_CFCF, 32776, 2, NULL, S_CIRCLE_FLAME10, 0, 0}, // S_CIRCLE_FLAME9 - {SPR_CFCF, 32777, 1, A_CFlameRotate, S_CIRCLE_FLAME11, 0, 0}, // S_CIRCLE_FLAME10 - {SPR_CFCF, 32778, 2, NULL, S_CIRCLE_FLAME12, 0, 0}, // S_CIRCLE_FLAME11 - {SPR_CFCF, 32779, 3, NULL, S_CIRCLE_FLAME13, 0, 0}, // S_CIRCLE_FLAME12 - {SPR_CFCF, 32780, 3, NULL, S_CIRCLE_FLAME14, 0, 0}, // S_CIRCLE_FLAME13 - {SPR_CFCF, 32781, 2, A_CFlameRotate, S_CIRCLE_FLAME15, 0, 0}, // S_CIRCLE_FLAME14 - {SPR_CFCF, 32782, 3, NULL, S_CIRCLE_FLAME16, 0, 0}, // S_CIRCLE_FLAME15 - {SPR_CFCF, 32783, 2, NULL, S_NULL, 0, 0}, // S_CIRCLE_FLAME16 - {SPR_CFCF, 32784, 3, NULL, S_CIRCLE_FLAME_X2, 0, 0}, // S_CIRCLE_FLAME_X1 - {SPR_CFCF, 32785, 3, NULL, S_CIRCLE_FLAME_X3, 0, 0}, // S_CIRCLE_FLAME_X2 - {SPR_CFCF, 32786, 3, A_Explode, S_CIRCLE_FLAME_X4, 0, 0}, // S_CIRCLE_FLAME_X3 - {SPR_CFCF, 32787, 3, NULL, S_CIRCLE_FLAME_X5, 0, 0}, // S_CIRCLE_FLAME_X4 - {SPR_CFCF, 32788, 3, NULL, S_CIRCLE_FLAME_X6, 0, 0}, // S_CIRCLE_FLAME_X5 - {SPR_CFCF, 32789, 3, NULL, S_CIRCLE_FLAME_X7, 0, 0}, // S_CIRCLE_FLAME_X6 - {SPR_CFCF, 32790, 3, NULL, S_CIRCLE_FLAME_X8, 0, 0}, // S_CIRCLE_FLAME_X7 - {SPR_CFCF, 32791, 3, NULL, S_CIRCLE_FLAME_X9, 0, 0}, // S_CIRCLE_FLAME_X8 - {SPR_CFCF, 32792, 3, NULL, S_CIRCLE_FLAME_X10, 0, 0}, // S_CIRCLE_FLAME_X9 - {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_CIRCLE_FLAME_X10 - {SPR_CFFX, 32768, 4, NULL, S_CFLAME_MISSILE2, 0, 0}, // S_CFLAME_MISSILE1 - {SPR_CFFX, 0, 1, A_CFlamePuff, S_FLAMEPUFF1, 0, 0}, // S_CFLAME_MISSILE2 - {SPR_CFFX, 32768, 1, A_CFlameMissile, S_FLAMEPUFF1, 0, 0}, // S_CFLAME_MISSILE_X - {SPR_CHLY, 0, 1, A_WeaponReady, S_CHOLYREADY, 0, 0}, // S_CHOLYREADY - {SPR_CHLY, 0, 1, A_Lower, S_CHOLYDOWN, 0, 0}, // S_CHOLYDOWN - {SPR_CHLY, 0, 1, A_Raise, S_CHOLYUP, 0, 0}, // S_CHOLYUP - {SPR_CHLY, 32768, 1, NULL, S_CHOLYATK_2, 0, 40}, // S_CHOLYATK_1 - {SPR_CHLY, 32769, 1, NULL, S_CHOLYATK_3, 0, 40}, // S_CHOLYATK_2 - {SPR_CHLY, 32770, 2, NULL, S_CHOLYATK_4, 0, 43}, // S_CHOLYATK_3 - {SPR_CHLY, 32771, 2, NULL, S_CHOLYATK_5, 0, 43}, // S_CHOLYATK_4 - {SPR_CHLY, 32772, 2, NULL, S_CHOLYATK_6, 0, 45}, // S_CHOLYATK_5 - {SPR_CHLY, 32773, 6, A_CHolyAttack, S_CHOLYATK_7, 0, 48}, // S_CHOLYATK_6 - {SPR_CHLY, 32774, 2, A_CHolyPalette, S_CHOLYATK_8, 0, 40}, // S_CHOLYATK_7 - {SPR_CHLY, 32774, 2, A_CHolyPalette, S_CHOLYATK_9, 0, 40}, // S_CHOLYATK_8 - {SPR_CHLY, 32774, 2, A_CHolyPalette, S_CHOLYREADY, 0, 36}, // S_CHOLYATK_9 - {SPR_SPIR, 0, 2, A_CHolySeek, S_HOLY_FX2, 0, 0}, // S_HOLY_FX1 - {SPR_SPIR, 0, 2, A_CHolySeek, S_HOLY_FX3, 0, 0}, // S_HOLY_FX2 - {SPR_SPIR, 1, 2, A_CHolySeek, S_HOLY_FX4, 0, 0}, // S_HOLY_FX3 - {SPR_SPIR, 1, 2, A_CHolyCheckScream, S_HOLY_FX1, 0, 0}, // S_HOLY_FX4 - {SPR_SPIR, 3, 4, NULL, S_HOLY_FX_X2, 0, 0}, // S_HOLY_FX_X1 - {SPR_SPIR, 4, 4, A_Scream, S_HOLY_FX_X3, 0, 0}, // S_HOLY_FX_X2 - {SPR_SPIR, 5, 4, NULL, S_HOLY_FX_X4, 0, 0}, // S_HOLY_FX_X3 - {SPR_SPIR, 6, 4, NULL, S_HOLY_FX_X5, 0, 0}, // S_HOLY_FX_X4 - {SPR_SPIR, 7, 4, NULL, S_HOLY_FX_X6, 0, 0}, // S_HOLY_FX_X5 - {SPR_SPIR, 8, 4, NULL, S_NULL, 0, 0}, // S_HOLY_FX_X6 - {SPR_SPIR, 2, 1, A_CHolyTail, S_HOLY_TAIL1, 0, 0}, // S_HOLY_TAIL1 - {SPR_SPIR, 3, -1, NULL, S_NULL, 0, 0}, // S_HOLY_TAIL2 - {SPR_SPIR, 10, 3, NULL, S_HOLY_PUFF2, 0, 0}, // S_HOLY_PUFF1 - {SPR_SPIR, 11, 3, NULL, S_HOLY_PUFF3, 0, 0}, // S_HOLY_PUFF2 - {SPR_SPIR, 12, 3, NULL, S_HOLY_PUFF4, 0, 0}, // S_HOLY_PUFF3 - {SPR_SPIR, 13, 3, NULL, S_HOLY_PUFF5, 0, 0}, // S_HOLY_PUFF4 - {SPR_SPIR, 14, 3, NULL, S_NULL, 0, 0}, // S_HOLY_PUFF5 - {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE2, 0, 0}, // S_HOLY_MISSILE1 - {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE3, 0, 0}, // S_HOLY_MISSILE2 - {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE4, 0, 0}, // S_HOLY_MISSILE3 - {SPR_SPIR, 32783, 3, A_CHolySpawnPuff, S_HOLY_MISSILE_X, 0, 0}, // S_HOLY_MISSILE4 - {SPR_SPIR, 32783, 1, A_CHolyAttack2, S_NULL, 0, 0}, // S_HOLY_MISSILE_X - {SPR_SPIR, 16, 3, NULL, S_HOLY_MISSILE_P2, 0, 0}, // S_HOLY_MISSILE_P1 - {SPR_SPIR, 17, 3, NULL, S_HOLY_MISSILE_P3, 0, 0}, // S_HOLY_MISSILE_P2 - {SPR_SPIR, 18, 3, NULL, S_HOLY_MISSILE_P4, 0, 0}, // S_HOLY_MISSILE_P3 - {SPR_SPIR, 19, 3, NULL, S_HOLY_MISSILE_P5, 0, 0}, // S_HOLY_MISSILE_P4 - {SPR_SPIR, 20, 3, NULL, S_NULL, 0, 0}, // S_HOLY_MISSILE_P5 - {SPR_MWND, 0, 1, A_WeaponReady, S_MWANDREADY, 0, 0}, // S_MWANDREADY - {SPR_MWND, 0, 1, A_Lower, S_MWANDDOWN, 0, 0}, // S_MWANDDOWN - {SPR_MWND, 0, 1, A_Raise, S_MWANDUP, 0, 0}, // S_MWANDUP - {SPR_MWND, 0, 6, NULL, S_MWANDATK_2, 0, 0}, // S_MWANDATK_1 - {SPR_MWND, 32769, 6, A_MWandAttack, S_MWANDATK_3, 0, 48}, // S_MWANDATK_2 - {SPR_MWND, 0, 3, NULL, S_MWANDATK_4, 0, 40}, // S_MWANDATK_3 - {SPR_MWND, 0, 3, A_ReFire, S_MWANDREADY, 0, 36}, // S_MWANDATK_4 - {SPR_MWND, 32772, 4, NULL, S_MWANDPUFF2, 0, 0}, // S_MWANDPUFF1 - {SPR_MWND, 32773, 3, NULL, S_MWANDPUFF3, 0, 0}, // S_MWANDPUFF2 - {SPR_MWND, 32774, 4, NULL, S_MWANDPUFF4, 0, 0}, // S_MWANDPUFF3 - {SPR_MWND, 32775, 3, NULL, S_MWANDPUFF5, 0, 0}, // S_MWANDPUFF4 - {SPR_MWND, 32776, 4, NULL, S_NULL, 0, 0}, // S_MWANDPUFF5 - {SPR_MWND, 2, 4, NULL, S_MWANDSMOKE2, 0, 0}, // S_MWANDSMOKE1 - {SPR_MWND, 3, 4, NULL, S_MWANDSMOKE3, 0, 0}, // S_MWANDSMOKE2 - {SPR_MWND, 2, 4, NULL, S_MWANDSMOKE4, 0, 0}, // S_MWANDSMOKE3 - {SPR_MWND, 3, 4, NULL, S_NULL, 0, 0}, // S_MWANDSMOKE4 - {SPR_MWND, 32770, 4, NULL, S_MWAND_MISSILE2, 0, 0}, // S_MWAND_MISSILE1 - {SPR_MWND, 32771, 4, NULL, S_MWAND_MISSILE1, 0, 0}, // S_MWAND_MISSILE2 - {SPR_WMLG, 32768, 4, NULL, S_MW_LIGHTNING2, 0, 0}, // S_MW_LIGHTNING1 - {SPR_WMLG, 32769, 4, NULL, S_MW_LIGHTNING3, 0, 0}, // S_MW_LIGHTNING2 - {SPR_WMLG, 32770, 4, NULL, S_MW_LIGHTNING4, 0, 0}, // S_MW_LIGHTNING3 - {SPR_WMLG, 32771, 4, NULL, S_MW_LIGHTNING5, 0, 0}, // S_MW_LIGHTNING4 - {SPR_WMLG, 32772, 4, NULL, S_MW_LIGHTNING6, 0, 0}, // S_MW_LIGHTNING5 - {SPR_WMLG, 32773, 4, NULL, S_MW_LIGHTNING7, 0, 0}, // S_MW_LIGHTNING6 - {SPR_WMLG, 32774, 4, NULL, S_MW_LIGHTNING8, 0, 0}, // S_MW_LIGHTNING7 - {SPR_WMLG, 32775, 4, NULL, S_MW_LIGHTNING1, 0, 0}, // S_MW_LIGHTNING8 - {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY2, 0, 0}, // S_MLIGHTNINGREADY - {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY3, 0, 0}, // S_MLIGHTNINGREADY2 - {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY4, 0, 0}, // S_MLIGHTNINGREADY3 - {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY5, 0, 0}, // S_MLIGHTNINGREADY4 - {SPR_MLNG, 32768, 1, A_WeaponReady, S_MLIGHTNINGREADY6, 0, 0}, // S_MLIGHTNINGREADY5 - {SPR_MLNG, 32768, 1, A_LightningReady, S_MLIGHTNINGREADY7, 0, 0}, // S_MLIGHTNINGREADY6 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY8, 0, 0}, // S_MLIGHTNINGREADY7 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY9, 0, 0}, // S_MLIGHTNINGREADY8 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY10, 0, 0}, // S_MLIGHTNINGREADY9 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY11, 0, 0}, // S_MLIGHTNINGREADY10 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY12, 0, 0}, // S_MLIGHTNINGREADY11 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY13, 0, 0}, // S_MLIGHTNINGREADY12 - {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY14, 0, 0}, // S_MLIGHTNINGREADY13 - {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY15, 0, 0}, // S_MLIGHTNINGREADY14 - {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY16, 0, 0}, // S_MLIGHTNINGREADY15 - {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY17, 0, 0}, // S_MLIGHTNINGREADY16 - {SPR_MLNG, 32770, 1, A_WeaponReady, S_MLIGHTNINGREADY18, 0, 0}, // S_MLIGHTNINGREADY17 - {SPR_MLNG, 32770, 1, A_LightningReady, S_MLIGHTNINGREADY19, 0, 0}, // S_MLIGHTNINGREADY18 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY20, 0, 0}, // S_MLIGHTNINGREADY19 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY21, 0, 0}, // S_MLIGHTNINGREADY20 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY22, 0, 0}, // S_MLIGHTNINGREADY21 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY23, 0, 0}, // S_MLIGHTNINGREADY22 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY24, 0, 0}, // S_MLIGHTNINGREADY23 - {SPR_MLNG, 32769, 1, A_WeaponReady, S_MLIGHTNINGREADY, 0, 0}, // S_MLIGHTNINGREADY24 - {SPR_MLNG, 32768, 1, A_Lower, S_MLIGHTNINGDOWN, 0, 0}, // S_MLIGHTNINGDOWN - {SPR_MLNG, 32768, 1, A_Raise, S_MLIGHTNINGUP, 0, 0}, // S_MLIGHTNINGUP - {SPR_MLNG, 32771, 3, NULL, S_MLIGHTNINGATK_2, 0, 0}, // S_MLIGHTNINGATK_1 - {SPR_MLNG, 32772, 3, NULL, S_MLIGHTNINGATK_3, 0, 0}, // S_MLIGHTNINGATK_2 - {SPR_MLNG, 32773, 4, A_MLightningAttack, S_MLIGHTNINGATK_4, 0, 0}, // S_MLIGHTNINGATK_3 - {SPR_MLNG, 32774, 4, NULL, S_MLIGHTNINGATK_5, 0, 0}, // S_MLIGHTNINGATK_4 - {SPR_MLNG, 32775, 3, NULL, S_MLIGHTNINGATK_6, 0, 0}, // S_MLIGHTNINGATK_5 - {SPR_MLNG, 32776, 3, NULL, S_MLIGHTNINGATK_7, 0, 0}, // S_MLIGHTNINGATK_6 - {SPR_MLNG, 32776, 6, NULL, S_MLIGHTNINGATK_8, 0, 199}, // S_MLIGHTNINGATK_7 - {SPR_MLNG, 32770, 2, NULL, S_MLIGHTNINGATK_9, 0, 55}, // S_MLIGHTNINGATK_8 - {SPR_MLNG, 32769, 2, NULL, S_MLIGHTNINGATK_10, 0, 50}, // S_MLIGHTNINGATK_9 - {SPR_MLNG, 32769, 2, NULL, S_MLIGHTNINGATK_11, 0, 45}, // S_MLIGHTNINGATK_10 - {SPR_MLNG, 32769, 2, NULL, S_MLIGHTNINGREADY, 0, 40}, // S_MLIGHTNINGATK_11 - {SPR_MLFX, 32768, 2, A_LightningZap, S_LIGHTNING_CEILING2, 0, 0}, // S_LIGHTNING_CEILING1 - {SPR_MLFX, 32769, 2, A_LightningClip, S_LIGHTNING_CEILING3, 0, 0}, // S_LIGHTNING_CEILING2 - {SPR_MLFX, 32770, 2, A_LightningClip, S_LIGHTNING_CEILING4, 0, 0}, // S_LIGHTNING_CEILING3 - {SPR_MLFX, 32771, 2, A_LightningClip, S_LIGHTNING_CEILING1, 0, 0}, // S_LIGHTNING_CEILING4 - {SPR_MLF2, 32768, 2, A_LightningRemove, S_LIGHTNING_C_X2, 0, 0}, // S_LIGHTNING_C_X1 - {SPR_MLF2, 32769, 3, NULL, S_LIGHTNING_C_X3, 0, 0}, // S_LIGHTNING_C_X2 - {SPR_MLF2, 32770, 3, NULL, S_LIGHTNING_C_X4, 0, 0}, // S_LIGHTNING_C_X3 - {SPR_MLF2, 32771, 3, NULL, S_LIGHTNING_C_X5, 0, 0}, // S_LIGHTNING_C_X4 - {SPR_MLF2, 32772, 3, NULL, S_LIGHTNING_C_X6, 0, 0}, // S_LIGHTNING_C_X5 - {SPR_MLF2, 32778, 3, NULL, S_LIGHTNING_C_X7, 0, 0}, // S_LIGHTNING_C_X6 - {SPR_MLF2, 32779, 3, NULL, S_LIGHTNING_C_X8, 0, 0}, // S_LIGHTNING_C_X7 - {SPR_MLF2, 32780, 3, NULL, S_LIGHTNING_C_X9, 0, 0}, // S_LIGHTNING_C_X8 - {SPR_ACLO, 4, 35, NULL, S_LIGHTNING_C_X10, 0, 0}, // S_LIGHTNING_C_X9 - {SPR_MLF2, 32781, 3, NULL, S_LIGHTNING_C_X11, 0, 0}, // S_LIGHTNING_C_X10 - {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_C_X12, 0, 0}, // S_LIGHTNING_C_X11 - {SPR_MLF2, 32783, 4, NULL, S_LIGHTNING_C_X13, 0, 0}, // S_LIGHTNING_C_X12 - {SPR_MLF2, 32784, 3, NULL, S_LIGHTNING_C_X14, 0, 0}, // S_LIGHTNING_C_X13 - {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_C_X15, 0, 0}, // S_LIGHTNING_C_X14 - {SPR_MLF2, 32784, 4, NULL, S_LIGHTNING_C_X16, 0, 0}, // S_LIGHTNING_C_X15 - {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_C_X17, 0, 0}, // S_LIGHTNING_C_X16 - {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_C_X18, 0, 0}, // S_LIGHTNING_C_X17 - {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_C_X19, 0, 0}, // S_LIGHTNING_C_X18 - {SPR_MLF2, 32783, 1, A_HideThing, S_FREETARGMOBJ, 0, 0}, // S_LIGHTNING_C_X19 - {SPR_MLFX, 32772, 2, A_LightningZap, S_LIGHTNING_FLOOR2, 0, 0}, // S_LIGHTNING_FLOOR1 - {SPR_MLFX, 32773, 2, A_LightningClip, S_LIGHTNING_FLOOR3, 0, 0}, // S_LIGHTNING_FLOOR2 - {SPR_MLFX, 32774, 2, A_LightningClip, S_LIGHTNING_FLOOR4, 0, 0}, // S_LIGHTNING_FLOOR3 - {SPR_MLFX, 32775, 2, A_LightningClip, S_LIGHTNING_FLOOR1, 0, 0}, // S_LIGHTNING_FLOOR4 - {SPR_MLF2, 32773, 2, A_LightningRemove, S_LIGHTNING_F_X2, 0, 0}, // S_LIGHTNING_F_X1 - {SPR_MLF2, 32774, 3, NULL, S_LIGHTNING_F_X3, 0, 0}, // S_LIGHTNING_F_X2 - {SPR_MLF2, 32775, 3, NULL, S_LIGHTNING_F_X4, 0, 0}, // S_LIGHTNING_F_X3 - {SPR_MLF2, 32776, 3, NULL, S_LIGHTNING_F_X5, 0, 0}, // S_LIGHTNING_F_X4 - {SPR_MLF2, 32777, 3, NULL, S_LIGHTNING_F_X6, 0, 0}, // S_LIGHTNING_F_X5 - {SPR_MLF2, 32778, 3, NULL, S_LIGHTNING_F_X7, 0, 0}, // S_LIGHTNING_F_X6 - {SPR_MLF2, 32779, 3, NULL, S_LIGHTNING_F_X8, 0, 0}, // S_LIGHTNING_F_X7 - {SPR_MLF2, 32780, 3, NULL, S_LIGHTNING_F_X9, 0, 0}, // S_LIGHTNING_F_X8 - {SPR_ACLO, 4, 20, NULL, S_LIGHTNING_F_X10, 0, 0}, // S_LIGHTNING_F_X9 - {SPR_MLF2, 32781, 3, NULL, S_LIGHTNING_F_X11, 0, 0}, // S_LIGHTNING_F_X10 - {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_F_X12, 0, 0}, // S_LIGHTNING_F_X11 - {SPR_MLF2, 32783, 4, NULL, S_LIGHTNING_F_X13, 0, 0}, // S_LIGHTNING_F_X12 - {SPR_MLF2, 32784, 3, NULL, S_LIGHTNING_F_X14, 0, 0}, // S_LIGHTNING_F_X13 - {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_F_X15, 0, 0}, // S_LIGHTNING_F_X14 - {SPR_MLF2, 32784, 4, A_LastZap, S_LIGHTNING_F_X16, 0, 0}, // S_LIGHTNING_F_X15 - {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_F_X17, 0, 0}, // S_LIGHTNING_F_X16 - {SPR_MLF2, 32782, 3, NULL, S_LIGHTNING_F_X18, 0, 0}, // S_LIGHTNING_F_X17 - {SPR_MLF2, 32783, 3, NULL, S_LIGHTNING_F_X19, 0, 0}, // S_LIGHTNING_F_X18 - {SPR_MLF2, 32783, 1, A_HideThing, S_FREETARGMOBJ, 0, 0}, // S_LIGHTNING_F_X19 - {SPR_MLFX, 32776, 2, A_ZapMimic, S_LIGHTNING_ZAP2, 0, 0}, // S_LIGHTNING_ZAP1 - {SPR_MLFX, 32777, 2, A_ZapMimic, S_LIGHTNING_ZAP3, 0, 0}, // S_LIGHTNING_ZAP2 - {SPR_MLFX, 32778, 2, A_ZapMimic, S_LIGHTNING_ZAP4, 0, 0}, // S_LIGHTNING_ZAP3 - {SPR_MLFX, 32779, 2, A_ZapMimic, S_LIGHTNING_ZAP5, 0, 0}, // S_LIGHTNING_ZAP4 - {SPR_MLFX, 32780, 2, A_ZapMimic, S_LIGHTNING_ZAP1, 0, 0}, // S_LIGHTNING_ZAP5 - {SPR_MLFX, 32781, 2, NULL, S_LIGHTNING_ZAP_X2, 0, 0}, // S_LIGHTNING_ZAP_X1 - {SPR_MLFX, 32782, 2, NULL, S_LIGHTNING_ZAP_X3, 0, 0}, // S_LIGHTNING_ZAP_X2 - {SPR_MLFX, 32783, 2, NULL, S_LIGHTNING_ZAP_X4, 0, 0}, // S_LIGHTNING_ZAP_X3 - {SPR_MLFX, 32784, 2, NULL, S_LIGHTNING_ZAP_X5, 0, 0}, // S_LIGHTNING_ZAP_X4 - {SPR_MLFX, 32785, 2, NULL, S_LIGHTNING_ZAP_X6, 0, 0}, // S_LIGHTNING_ZAP_X5 - {SPR_MLFX, 32786, 2, NULL, S_LIGHTNING_ZAP_X7, 0, 0}, // S_LIGHTNING_ZAP_X6 - {SPR_MLFX, 32787, 2, NULL, S_LIGHTNING_ZAP_X8, 0, 0}, // S_LIGHTNING_ZAP_X7 - {SPR_MLFX, 32788, 2, NULL, S_NULL, 0, 0}, // S_LIGHTNING_ZAP_X8 - {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY2, 0, 0}, // S_MSTAFFREADY - {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY3, 0, 0}, // S_MSTAFFREADY2 - {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY4, 0, 0}, // S_MSTAFFREADY3 - {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY5, 0, 0}, // S_MSTAFFREADY4 - {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY6, 0, 0}, // S_MSTAFFREADY5 - {SPR_MSTF, 0, 1, A_WeaponReady, S_MSTAFFREADY7, 0, 0}, // S_MSTAFFREADY6 - {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY8, 0, 0}, // S_MSTAFFREADY7 - {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY9, 0, 0}, // S_MSTAFFREADY8 - {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY10, 0, 0}, // S_MSTAFFREADY9 - {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY11, 0, 0}, // S_MSTAFFREADY10 - {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY12, 0, 0}, // S_MSTAFFREADY11 - {SPR_MSTF, 1, 1, A_WeaponReady, S_MSTAFFREADY13, 0, 0}, // S_MSTAFFREADY12 - {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY14, 0, 0}, // S_MSTAFFREADY13 - {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY15, 0, 0}, // S_MSTAFFREADY14 - {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY16, 0, 0}, // S_MSTAFFREADY15 - {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY17, 0, 0}, // S_MSTAFFREADY16 - {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY18, 0, 0}, // S_MSTAFFREADY17 - {SPR_MSTF, 2, 1, A_WeaponReady, S_MSTAFFREADY19, 0, 0}, // S_MSTAFFREADY18 - {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY20, 0, 0}, // S_MSTAFFREADY19 - {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY21, 0, 0}, // S_MSTAFFREADY20 - {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY22, 0, 0}, // S_MSTAFFREADY21 - {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY23, 0, 0}, // S_MSTAFFREADY22 - {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY24, 0, 0}, // S_MSTAFFREADY23 - {SPR_MSTF, 3, 1, A_WeaponReady, S_MSTAFFREADY25, 0, 0}, // S_MSTAFFREADY24 - {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY26, 0, 0}, // S_MSTAFFREADY25 - {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY27, 0, 0}, // S_MSTAFFREADY26 - {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY28, 0, 0}, // S_MSTAFFREADY27 - {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY29, 0, 0}, // S_MSTAFFREADY28 - {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY30, 0, 0}, // S_MSTAFFREADY29 - {SPR_MSTF, 4, 1, A_WeaponReady, S_MSTAFFREADY31, 0, 0}, // S_MSTAFFREADY30 - {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY32, 0, 0}, // S_MSTAFFREADY31 - {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY33, 0, 0}, // S_MSTAFFREADY32 - {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY34, 0, 0}, // S_MSTAFFREADY33 - {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY35, 0, 0}, // S_MSTAFFREADY34 - {SPR_MSTF, 5, 1, A_WeaponReady, S_MSTAFFREADY, 0, 0}, // S_MSTAFFREADY35 - {SPR_MSTF, 0, 1, A_Lower, S_MSTAFFDOWN, 0, 0}, // S_MSTAFFDOWN - {SPR_MSTF, 0, 1, A_Raise, S_MSTAFFUP, 0, 0}, // S_MSTAFFUP - {SPR_MSTF, 6, 4, NULL, S_MSTAFFATK_2, 0, 40}, // S_MSTAFFATK_1 - {SPR_MSTF, 32775, 4, A_MStaffAttack, S_MSTAFFATK_3, 0, 48}, // S_MSTAFFATK_2 - {SPR_MSTF, 32775, 2, A_MStaffPalette, S_MSTAFFATK_4, 0, 48}, // S_MSTAFFATK_3 - {SPR_MSTF, 8, 2, A_MStaffPalette, S_MSTAFFATK_5, 0, 48}, // S_MSTAFFATK_4 - {SPR_MSTF, 8, 2, A_MStaffPalette, S_MSTAFFATK_6, 0, 48}, // S_MSTAFFATK_5 - {SPR_MSTF, 8, 1, NULL, S_MSTAFFATK_7, 0, 40}, // S_MSTAFFATK_6 - {SPR_MSTF, 9, 5, NULL, S_MSTAFFREADY, 0, 36}, // S_MSTAFFATK_7 - {SPR_MSP1, 32768, 3, A_MStaffWeave, S_MSTAFF_FX1_2, 0, 0}, // S_MSTAFF_FX1_1 - {SPR_MSP1, 32769, 3, A_MStaffWeave, S_MSTAFF_FX1_3, 0, 0}, // S_MSTAFF_FX1_2 - {SPR_MSP1, 32770, 3, A_MStaffWeave, S_MSTAFF_FX1_4, 0, 0}, // S_MSTAFF_FX1_3 - {SPR_MSP1, 32771, 3, A_MStaffWeave, S_MSTAFF_FX1_5, 0, 0}, // S_MSTAFF_FX1_4 - {SPR_MSP1, 32772, 3, A_MStaffWeave, S_MSTAFF_FX1_6, 0, 0}, // S_MSTAFF_FX1_5 - {SPR_MSP1, 32773, 3, A_MStaffWeave, S_MSTAFF_FX1_1, 0, 0}, // S_MSTAFF_FX1_6 - {SPR_MSP1, 32774, 4, NULL, S_MSTAFF_FX_X2, 0, 0}, // S_MSTAFF_FX_X1 - {SPR_MSP1, 32775, 5, A_Explode, S_MSTAFF_FX_X3, 0, 0}, // S_MSTAFF_FX_X2 - {SPR_MSP1, 32776, 4, NULL, S_MSTAFF_FX_X4, 0, 0}, // S_MSTAFF_FX_X3 - {SPR_MSP1, 32777, 5, NULL, S_MSTAFF_FX_X5, 0, 0}, // S_MSTAFF_FX_X4 - {SPR_MSP1, 32778, 4, NULL, S_MSTAFF_FX_X6, 0, 0}, // S_MSTAFF_FX_X5 - {SPR_MSP1, 32779, 5, NULL, S_MSTAFF_FX_X7, 0, 0}, // S_MSTAFF_FX_X6 - {SPR_MSP1, 32780, 4, NULL, S_MSTAFF_FX_X8, 0, 0}, // S_MSTAFF_FX_X7 - {SPR_MSP1, 32781, 5, NULL, S_MSTAFF_FX_X9, 0, 0}, // S_MSTAFF_FX_X8 - {SPR_MSP1, 32782, 4, NULL, S_MSTAFF_FX_X10, 0, 0}, // S_MSTAFF_FX_X9 - {SPR_MSP1, 32783, 4, NULL, S_NULL, 0, 0}, // S_MSTAFF_FX_X10 - {SPR_MSP2, 32768, 2, A_MStaffTrack, S_MSTAFF_FX2_2, 0, 0}, // S_MSTAFF_FX2_1 - {SPR_MSP2, 32769, 2, A_MStaffTrack, S_MSTAFF_FX2_3, 0, 0}, // S_MSTAFF_FX2_2 - {SPR_MSP2, 32770, 2, A_MStaffTrack, S_MSTAFF_FX2_4, 0, 0}, // S_MSTAFF_FX2_3 - {SPR_MSP2, 32771, 2, A_MStaffTrack, S_MSTAFF_FX2_1, 0, 0}, // S_MSTAFF_FX2_4 - {SPR_MSP2, 32772, 4, NULL, S_MSTAFF_FX2_X2, 0, 0}, // S_MSTAFF_FX2_X1 - {SPR_MSP2, 32773, 5, A_Explode, S_MSTAFF_FX2_X3, 0, 0}, // S_MSTAFF_FX2_X2 - {SPR_MSP2, 32774, 5, NULL, S_MSTAFF_FX2_X4, 0, 0}, // S_MSTAFF_FX2_X3 - {SPR_MSP2, 32775, 5, NULL, S_MSTAFF_FX2_X5, 0, 0}, // S_MSTAFF_FX2_X4 - {SPR_MSP2, 32776, 4, NULL, S_NULL, 0, 0}, // S_MSTAFF_FX2_X5 - {SPR_WFR1, 32768, -1, NULL, S_NULL, 0, 0}, // S_FSWORD1 - {SPR_WFR2, 32768, -1, NULL, S_NULL, 0, 0}, // S_FSWORD2 - {SPR_WFR3, 32768, -1, NULL, S_NULL, 0, 0}, // S_FSWORD3 - {SPR_WCH1, 32768, -1, NULL, S_NULL, 0, 0}, // S_CHOLY1 - {SPR_WCH2, 32768, -1, NULL, S_NULL, 0, 0}, // S_CHOLY2 - {SPR_WCH3, 32768, -1, NULL, S_NULL, 0, 0}, // S_CHOLY3 - {SPR_WMS1, 32768, -1, NULL, S_NULL, 0, 0}, // S_MSTAFF1 - {SPR_WMS2, 32768, -1, NULL, S_NULL, 0, 0}, // S_MSTAFF2 - {SPR_WMS3, 32768, -1, NULL, S_NULL, 0, 0}, // S_MSTAFF3 - {SPR_WPIG, 0, 1, A_WeaponReady, S_SNOUTREADY, 0, 0}, // S_SNOUTREADY - {SPR_WPIG, 0, 1, A_Lower, S_SNOUTDOWN, 0, 0}, // S_SNOUTDOWN - {SPR_WPIG, 0, 1, A_Raise, S_SNOUTUP, 0, 0}, // S_SNOUTUP - {SPR_WPIG, 0, 4, A_SnoutAttack, S_SNOUTATK2, 0, 0}, // S_SNOUTATK1 - {SPR_WPIG, 1, 8, A_SnoutAttack, S_SNOUTREADY, 0, 0}, // S_SNOUTATK2 - {SPR_WMCS, 32768, 8, NULL, S_COS2, 0, 0}, // S_COS1 - {SPR_WMCS, 32769, 8, NULL, S_COS3, 0, 0}, // S_COS2 - {SPR_WMCS, 32770, 8, NULL, S_COS1, 0, 0}, // S_COS3 - {SPR_CONE, 0, 1, A_WeaponReady, S_CONEREADY, 0, 0}, // S_CONEREADY - {SPR_CONE, 0, 1, A_Lower, S_CONEDOWN, 0, 0}, // S_CONEDOWN - {SPR_CONE, 0, 1, A_Raise, S_CONEUP, 0, 0}, // S_CONEUP - {SPR_CONE, 1, 3, NULL, S_CONEATK1_2, 0, 0}, // S_CONEATK1_1 - {SPR_CONE, 2, 4, NULL, S_CONEATK1_3, 0, 0}, // S_CONEATK1_2 - {SPR_CONE, 3, 3, NULL, S_CONEATK1_4, 0, 0}, // S_CONEATK1_3 - {SPR_CONE, 4, 5, NULL, S_CONEATK1_5, 0, 0}, // S_CONEATK1_4 - {SPR_CONE, 5, 3, A_FireConePL1, S_CONEATK1_6, 0, 0}, // S_CONEATK1_5 - {SPR_CONE, 6, 3, NULL, S_CONEATK1_7, 0, 0}, // S_CONEATK1_6 - {SPR_CONE, 0, 9, NULL, S_CONEATK1_8, 0, 0}, // S_CONEATK1_7 - {SPR_CONE, 0, 10, A_ReFire, S_CONEREADY, 0, 0}, // S_CONEATK1_8 - {SPR_SHRD, 32768, 2, NULL, S_SHARDFX1_2, 0, 0}, // S_SHARDFX1_1 - {SPR_SHRD, 32768, 3, A_ShedShard, S_SHARDFX1_3, 0, 0}, // S_SHARDFX1_2 - {SPR_SHRD, 32769, 3, NULL, S_SHARDFX1_4, 0, 0}, // S_SHARDFX1_3 - {SPR_SHRD, 32770, 3, NULL, S_SHARDFX1_1, 0, 0}, // S_SHARDFX1_4 - {SPR_SHEX, 32768, 5, NULL, S_SHARDFXE1_2, 0, 0}, // S_SHARDFXE1_1 - {SPR_SHEX, 32769, 5, NULL, S_SHARDFXE1_3, 0, 0}, // S_SHARDFXE1_2 - {SPR_SHEX, 32770, 5, NULL, S_SHARDFXE1_4, 0, 0}, // S_SHARDFXE1_3 - {SPR_SHEX, 32771, 5, NULL, S_SHARDFXE1_5, 0, 0}, // S_SHARDFXE1_4 - {SPR_SHEX, 32772, 5, NULL, S_NULL, 0, 0}, // S_SHARDFXE1_5 - {SPR_BLOD, 2, 8, NULL, S_BLOOD2, 0, 0}, // S_BLOOD1 - {SPR_BLOD, 1, 8, NULL, S_BLOOD3, 0, 0}, // S_BLOOD2 - {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOOD3 - {SPR_BLOD, 2, 8, NULL, S_BLOODSPLATTER2, 0, 0}, // S_BLOODSPLATTER1 - {SPR_BLOD, 1, 8, NULL, S_BLOODSPLATTER3, 0, 0}, // S_BLOODSPLATTER2 - {SPR_BLOD, 0, 8, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTER3 - {SPR_BLOD, 0, 6, NULL, S_NULL, 0, 0}, // S_BLOODSPLATTERX - {SPR_GIBS, 0, -1, NULL, S_NULL, 0, 0}, // S_GIBS1 - {SPR_PLAY, 0, -1, NULL, S_NULL, 0, 0}, // S_FPLAY - {SPR_PLAY, 0, 4, NULL, S_FPLAY_RUN2, 0, 0}, // S_FPLAY_RUN1 - {SPR_PLAY, 1, 4, NULL, S_FPLAY_RUN3, 0, 0}, // S_FPLAY_RUN2 - {SPR_PLAY, 2, 4, NULL, S_FPLAY_RUN4, 0, 0}, // S_FPLAY_RUN3 - {SPR_PLAY, 3, 4, NULL, S_FPLAY_RUN1, 0, 0}, // S_FPLAY_RUN4 - {SPR_PLAY, 4, 8, NULL, S_FPLAY_ATK2, 0, 0}, // S_FPLAY_ATK1 - {SPR_PLAY, 5, 8, NULL, S_FPLAY, 0, 0}, // S_FPLAY_ATK2 - {SPR_PLAY, 6, 4, NULL, S_FPLAY_PAIN2, 0, 0}, // S_FPLAY_PAIN - {SPR_PLAY, 6, 4, A_Pain, S_FPLAY, 0, 0}, // S_FPLAY_PAIN2 - {SPR_PLAY, 7, 6, NULL, S_FPLAY_DIE2, 0, 0}, // S_FPLAY_DIE1 - {SPR_PLAY, 8, 6, A_Scream, S_FPLAY_DIE3, 0, 0}, // S_FPLAY_DIE2 - {SPR_PLAY, 9, 6, NULL, S_FPLAY_DIE4, 0, 0}, // S_FPLAY_DIE3 - {SPR_PLAY, 10, 6, NULL, S_FPLAY_DIE5, 0, 0}, // S_FPLAY_DIE4 - {SPR_PLAY, 11, 6, A_NoBlocking, S_FPLAY_DIE6, 0, 0}, // S_FPLAY_DIE5 - {SPR_PLAY, 12, 6, NULL, S_FPLAY_DIE7, 0, 0}, // S_FPLAY_DIE6 - {SPR_PLAY, 13, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_FPLAY_DIE7 - {SPR_PLAY, 14, 5, A_Scream, S_FPLAY_XDIE2, 0, 0}, // S_FPLAY_XDIE1 - {SPR_PLAY, 15, 5, A_SkullPop, S_FPLAY_XDIE3, 0, 0}, // S_FPLAY_XDIE2 - {SPR_PLAY, 17, 5, A_NoBlocking, S_FPLAY_XDIE4, 0, 0}, // S_FPLAY_XDIE3 - {SPR_PLAY, 18, 5, NULL, S_FPLAY_XDIE5, 0, 0}, // S_FPLAY_XDIE4 - {SPR_PLAY, 19, 5, NULL, S_FPLAY_XDIE6, 0, 0}, // S_FPLAY_XDIE5 - {SPR_PLAY, 20, 5, NULL, S_FPLAY_XDIE7, 0, 0}, // S_FPLAY_XDIE6 - {SPR_PLAY, 21, 5, NULL, S_FPLAY_XDIE8, 0, 0}, // S_FPLAY_XDIE7 - {SPR_PLAY, 22, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_FPLAY_XDIE8 - {SPR_PLAY, 23, 5, A_FreezeDeath, S_FPLAY_ICE2, 0, 0}, // S_FPLAY_ICE - {SPR_PLAY, 23, 1, A_FreezeDeathChunks, S_FPLAY_ICE2, 0, 0}, // S_FPLAY_ICE2 - {SPR_FDTH, 32768, 5, NULL, S_PLAY_F_FDTH2, 0, 0}, // S_PLAY_F_FDTH1 - {SPR_FDTH, 32769, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_F_FDTH2 - {SPR_FDTH, 32770, 5, NULL, S_PLAY_C_FDTH2, 0, 0}, // S_PLAY_C_FDTH1 - {SPR_FDTH, 32771, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_C_FDTH2 - {SPR_FDTH, 32772, 5, NULL, S_PLAY_M_FDTH2, 0, 0}, // S_PLAY_M_FDTH1 - {SPR_FDTH, 32773, 4, NULL, S_PLAY_FDTH3, 0, 0}, // S_PLAY_M_FDTH2 - {SPR_FDTH, 32774, 5, NULL, S_PLAY_FDTH4, 0, 0}, // S_PLAY_FDTH3 - {SPR_FDTH, 32775, 4, A_Scream, S_PLAY_FDTH5, 0, 0}, // S_PLAY_FDTH4 - {SPR_FDTH, 32776, 5, NULL, S_PLAY_FDTH6, 0, 0}, // S_PLAY_FDTH5 - {SPR_FDTH, 32777, 4, NULL, S_PLAY_FDTH7, 0, 0}, // S_PLAY_FDTH6 - {SPR_FDTH, 32778, 5, NULL, S_PLAY_FDTH8, 0, 0}, // S_PLAY_FDTH7 - {SPR_FDTH, 32779, 4, NULL, S_PLAY_FDTH9, 0, 0}, // S_PLAY_FDTH8 - {SPR_FDTH, 32780, 5, NULL, S_PLAY_FDTH10, 0, 0}, // S_PLAY_FDTH9 - {SPR_FDTH, 32781, 4, NULL, S_PLAY_FDTH11, 0, 0}, // S_PLAY_FDTH10 - {SPR_FDTH, 32782, 5, NULL, S_PLAY_FDTH12, 0, 0}, // S_PLAY_FDTH11 - {SPR_FDTH, 32783, 4, NULL, S_PLAY_FDTH13, 0, 0}, // S_PLAY_FDTH12 - {SPR_FDTH, 32784, 5, NULL, S_PLAY_FDTH14, 0, 0}, // S_PLAY_FDTH13 - {SPR_FDTH, 32785, 4, NULL, S_PLAY_FDTH15, 0, 0}, // S_PLAY_FDTH14 - {SPR_FDTH, 32786, 5, A_NoBlocking, S_PLAY_FDTH16, 0, 0}, // S_PLAY_FDTH15 - {SPR_FDTH, 32787, 4, NULL, S_PLAY_FDTH17, 0, 0}, // S_PLAY_FDTH16 - {SPR_FDTH, 32788, 5, NULL, S_PLAY_FDTH18, 0, 0}, // S_PLAY_FDTH17 - {SPR_FDTH, 32789, 4, NULL, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH18 - {SPR_ACLO, 4, 35, A_CheckBurnGone, S_PLAY_FDTH19, 0, 0}, // S_PLAY_FDTH19 - {SPR_ACLO, 4, 8, NULL, S_NULL, 0, 0}, // S_PLAY_FDTH20 - {SPR_BSKL, 0, 5, A_CheckSkullFloor, S_BLOODYSKULL2, 0, 0}, // S_BLOODYSKULL1 - {SPR_BSKL, 1, 5, A_CheckSkullFloor, S_BLOODYSKULL3, 0, 0}, // S_BLOODYSKULL2 - {SPR_BSKL, 2, 5, A_CheckSkullFloor, S_BLOODYSKULL4, 0, 0}, // S_BLOODYSKULL3 - {SPR_BSKL, 3, 5, A_CheckSkullFloor, S_BLOODYSKULL5, 0, 0}, // S_BLOODYSKULL4 - {SPR_BSKL, 5, 5, A_CheckSkullFloor, S_BLOODYSKULL6, 0, 0}, // S_BLOODYSKULL5 - {SPR_BSKL, 6, 5, A_CheckSkullFloor, S_BLOODYSKULL7, 0, 0}, // S_BLOODYSKULL6 - {SPR_BSKL, 7, 5, A_CheckSkullFloor, S_BLOODYSKULL1, 0, 0}, // S_BLOODYSKULL7 - {SPR_BSKL, 8, 16, A_CheckSkullDone, S_BLOODYSKULLX1, 0, 0}, // S_BLOODYSKULLX1 - {SPR_BSKL, 8, 1050, NULL, S_NULL, 0, 0}, // S_BLOODYSKULLX2 - {SPR_PLAY, 0, 5, NULL, S_PLAYER_SPEED2, 0, 0}, // S_PLAYER_SPEED1 - {SPR_PLAY, 0, 3, A_SpeedFade, S_NULL, 0, 0}, // S_PLAYER_SPEED2 - {SPR_ICEC, 0, 10, NULL, S_ICECHUNK2, 0, 0}, // S_ICECHUNK1 - {SPR_ICEC, 1, 10, A_IceSetTics, S_ICECHUNK3, 0, 0}, // S_ICECHUNK2 - {SPR_ICEC, 2, 10, A_IceSetTics, S_ICECHUNK4, 0, 0}, // S_ICECHUNK3 - {SPR_ICEC, 3, 10, A_IceSetTics, S_NULL, 0, 0}, // S_ICECHUNK4 - {SPR_ICEC, 0, 10, A_IceCheckHeadDone, S_ICECHUNK_HEAD, 0, 0}, // S_ICECHUNK_HEAD - {SPR_ICEC, 0, 1050, NULL, S_NULL, 0, 0}, // S_ICECHUNK_HEAD2 - {SPR_CLER, 0, -1, NULL, S_NULL, 0, 0}, // S_CPLAY - {SPR_CLER, 0, 4, NULL, S_CPLAY_RUN2, 0, 0}, // S_CPLAY_RUN1 - {SPR_CLER, 1, 4, NULL, S_CPLAY_RUN3, 0, 0}, // S_CPLAY_RUN2 - {SPR_CLER, 2, 4, NULL, S_CPLAY_RUN4, 0, 0}, // S_CPLAY_RUN3 - {SPR_CLER, 3, 4, NULL, S_CPLAY_RUN1, 0, 0}, // S_CPLAY_RUN4 - {SPR_CLER, 4, 6, NULL, S_CPLAY_ATK2, 0, 0}, // S_CPLAY_ATK1 - {SPR_CLER, 5, 6, NULL, S_CPLAY_ATK3, 0, 0}, // S_CPLAY_ATK2 - {SPR_CLER, 6, 6, NULL, S_CPLAY, 0, 0}, // S_CPLAY_ATK3 - {SPR_CLER, 7, 4, NULL, S_CPLAY_PAIN2, 0, 0}, // S_CPLAY_PAIN - {SPR_CLER, 7, 4, A_Pain, S_CPLAY, 0, 0}, // S_CPLAY_PAIN2 - {SPR_CLER, 8, 6, NULL, S_CPLAY_DIE2, 0, 0}, // S_CPLAY_DIE1 - {SPR_CLER, 10, 6, A_Scream, S_CPLAY_DIE3, 0, 0}, // S_CPLAY_DIE2 - {SPR_CLER, 11, 6, NULL, S_CPLAY_DIE4, 0, 0}, // S_CPLAY_DIE3 - {SPR_CLER, 11, 6, NULL, S_CPLAY_DIE5, 0, 0}, // S_CPLAY_DIE4 - {SPR_CLER, 12, 6, A_NoBlocking, S_CPLAY_DIE6, 0, 0}, // S_CPLAY_DIE5 - {SPR_CLER, 13, 6, NULL, S_CPLAY_DIE7, 0, 0}, // S_CPLAY_DIE6 - {SPR_CLER, 14, 6, NULL, S_CPLAY_DIE8, 0, 0}, // S_CPLAY_DIE7 - {SPR_CLER, 15, 6, NULL, S_CPLAY_DIE9, 0, 0}, // S_CPLAY_DIE8 - {SPR_CLER, 16, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_CPLAY_DIE9 - {SPR_CLER, 17, 5, A_Scream, S_CPLAY_XDIE2, 0, 0}, // S_CPLAY_XDIE1 - {SPR_CLER, 18, 5, NULL, S_CPLAY_XDIE3, 0, 0}, // S_CPLAY_XDIE2 - {SPR_CLER, 19, 5, A_NoBlocking, S_CPLAY_XDIE4, 0, 0}, // S_CPLAY_XDIE3 - {SPR_CLER, 20, 5, NULL, S_CPLAY_XDIE5, 0, 0}, // S_CPLAY_XDIE4 - {SPR_CLER, 21, 5, NULL, S_CPLAY_XDIE6, 0, 0}, // S_CPLAY_XDIE5 - {SPR_CLER, 22, 5, NULL, S_CPLAY_XDIE7, 0, 0}, // S_CPLAY_XDIE6 - {SPR_CLER, 23, 5, NULL, S_CPLAY_XDIE8, 0, 0}, // S_CPLAY_XDIE7 - {SPR_CLER, 24, 5, NULL, S_CPLAY_XDIE9, 0, 0}, // S_CPLAY_XDIE8 - {SPR_CLER, 25, 5, NULL, S_CPLAY_XDIE10, 0, 0}, // S_CPLAY_XDIE9 - {SPR_CLER, 26, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_CPLAY_XDIE10 - {SPR_CLER, 27, 5, A_FreezeDeath, S_CPLAY_ICE2, 0, 0}, // S_CPLAY_ICE - {SPR_CLER, 27, 1, A_FreezeDeathChunks, S_CPLAY_ICE2, 0, 0}, // S_CPLAY_ICE2 - {SPR_MAGE, 0, -1, NULL, S_NULL, 0, 0}, // S_MPLAY - {SPR_MAGE, 0, 4, NULL, S_MPLAY_RUN2, 0, 0}, // S_MPLAY_RUN1 - {SPR_MAGE, 1, 4, NULL, S_MPLAY_RUN3, 0, 0}, // S_MPLAY_RUN2 - {SPR_MAGE, 2, 4, NULL, S_MPLAY_RUN4, 0, 0}, // S_MPLAY_RUN3 - {SPR_MAGE, 3, 4, NULL, S_MPLAY_RUN1, 0, 0}, // S_MPLAY_RUN4 - {SPR_MAGE, 4, 8, NULL, S_MPLAY_ATK2, 0, 0}, // S_MPLAY_ATK1 - {SPR_MAGE, 32773, 8, NULL, S_MPLAY, 0, 0}, // S_MPLAY_ATK2 - {SPR_MAGE, 6, 4, NULL, S_MPLAY_PAIN2, 0, 0}, // S_MPLAY_PAIN - {SPR_MAGE, 6, 4, A_Pain, S_MPLAY, 0, 0}, // S_MPLAY_PAIN2 - {SPR_MAGE, 7, 6, NULL, S_MPLAY_DIE2, 0, 0}, // S_MPLAY_DIE1 - {SPR_MAGE, 8, 6, A_Scream, S_MPLAY_DIE3, 0, 0}, // S_MPLAY_DIE2 - {SPR_MAGE, 9, 6, NULL, S_MPLAY_DIE4, 0, 0}, // S_MPLAY_DIE3 - {SPR_MAGE, 10, 6, NULL, S_MPLAY_DIE5, 0, 0}, // S_MPLAY_DIE4 - {SPR_MAGE, 11, 6, A_NoBlocking, S_MPLAY_DIE6, 0, 0}, // S_MPLAY_DIE5 - {SPR_MAGE, 12, 6, NULL, S_MPLAY_DIE7, 0, 0}, // S_MPLAY_DIE6 - {SPR_MAGE, 13, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_MPLAY_DIE7 - {SPR_MAGE, 14, 5, A_Scream, S_MPLAY_XDIE2, 0, 0}, // S_MPLAY_XDIE1 - {SPR_MAGE, 15, 5, NULL, S_MPLAY_XDIE3, 0, 0}, // S_MPLAY_XDIE2 - {SPR_MAGE, 17, 5, A_NoBlocking, S_MPLAY_XDIE4, 0, 0}, // S_MPLAY_XDIE3 - {SPR_MAGE, 18, 5, NULL, S_MPLAY_XDIE5, 0, 0}, // S_MPLAY_XDIE4 - {SPR_MAGE, 19, 5, NULL, S_MPLAY_XDIE6, 0, 0}, // S_MPLAY_XDIE5 - {SPR_MAGE, 20, 5, NULL, S_MPLAY_XDIE7, 0, 0}, // S_MPLAY_XDIE6 - {SPR_MAGE, 21, 5, NULL, S_MPLAY_XDIE8, 0, 0}, // S_MPLAY_XDIE7 - {SPR_MAGE, 22, 5, NULL, S_MPLAY_XDIE9, 0, 0}, // S_MPLAY_XDIE8 - {SPR_MAGE, 23, -1, A_AddPlayerCorpse, S_NULL, 0, 0}, // S_MPLAY_XDIE9 - {SPR_MAGE, 24, 5, A_FreezeDeath, S_MPLAY_ICE2, 0, 0}, // S_MPLAY_ICE - {SPR_MAGE, 24, 1, A_FreezeDeathChunks, S_MPLAY_ICE2, 0, 0}, // S_MPLAY_ICE2 - {SPR_PIGY, 0, -1, NULL, S_NULL, 0, 0}, // S_PIGPLAY - {SPR_PIGY, 0, 3, NULL, S_PIGPLAY_RUN2, 0, 0}, // S_PIGPLAY_RUN1 - {SPR_PIGY, 1, 3, NULL, S_PIGPLAY_RUN3, 0, 0}, // S_PIGPLAY_RUN2 - {SPR_PIGY, 2, 3, NULL, S_PIGPLAY_RUN4, 0, 0}, // S_PIGPLAY_RUN3 - {SPR_PIGY, 3, 3, NULL, S_PIGPLAY_RUN1, 0, 0}, // S_PIGPLAY_RUN4 - {SPR_PIGY, 0, 12, NULL, S_PIGPLAY, 0, 0}, // S_PIGPLAY_ATK1 - {SPR_PIGY, 3, 4, A_PigPain, S_PIGPLAY, 0, 0}, // S_PIGPLAY_PAIN - {SPR_PIGY, 1, 10, A_PigLook, S_PIG_LOOK1, 0, 0}, // S_PIG_LOOK1 - {SPR_PIGY, 0, 3, A_PigChase, S_PIG_WALK2, 0, 0}, // S_PIG_WALK1 - {SPR_PIGY, 1, 3, A_PigChase, S_PIG_WALK3, 0, 0}, // S_PIG_WALK2 - {SPR_PIGY, 2, 3, A_PigChase, S_PIG_WALK4, 0, 0}, // S_PIG_WALK3 - {SPR_PIGY, 3, 3, A_PigChase, S_PIG_WALK1, 0, 0}, // S_PIG_WALK4 - {SPR_PIGY, 3, 4, A_PigPain, S_PIG_WALK1, 0, 0}, // S_PIG_PAIN - {SPR_PIGY, 0, 5, A_FaceTarget, S_PIG_ATK2, 0, 0}, // S_PIG_ATK1 - {SPR_PIGY, 0, 10, A_PigAttack, S_PIG_WALK1, 0, 0}, // S_PIG_ATK2 - {SPR_PIGY, 4, 4, A_Scream, S_PIG_DIE2, 0, 0}, // S_PIG_DIE1 - {SPR_PIGY, 5, 3, A_NoBlocking, S_PIG_DIE3, 0, 0}, // S_PIG_DIE2 - {SPR_PIGY, 6, 4, A_QueueCorpse, S_PIG_DIE4, 0, 0}, // S_PIG_DIE3 - {SPR_PIGY, 7, 3, NULL, S_PIG_DIE5, 0, 0}, // S_PIG_DIE4 - {SPR_PIGY, 8, 4, NULL, S_PIG_DIE6, 0, 0}, // S_PIG_DIE5 - {SPR_PIGY, 9, 4, NULL, S_PIG_DIE7, 0, 0}, // S_PIG_DIE6 - {SPR_PIGY, 10, 4, NULL, S_PIG_DIE8, 0, 0}, // S_PIG_DIE7 - {SPR_PIGY, 11, -1, NULL, S_NULL, 0, 0}, // S_PIG_DIE8 - {SPR_PIGY, 12, 5, A_FreezeDeath, S_PIG_ICE2, 0, 0}, // S_PIG_ICE - {SPR_PIGY, 12, 1, A_FreezeDeathChunks, S_PIG_ICE2, 0, 0}, // S_PIG_ICE2 - {SPR_CENT, 0, 10, A_Look, S_CENTAUR_LOOK2, 0, 0}, // S_CENTAUR_LOOK1 - {SPR_CENT, 1, 10, A_Look, S_CENTAUR_LOOK1, 0, 0}, // S_CENTAUR_LOOK2 - {SPR_CENT, 0, 4, A_Chase, S_CENTAUR_WALK2, 0, 0}, // S_CENTAUR_WALK1 - {SPR_CENT, 1, 4, A_Chase, S_CENTAUR_WALK3, 0, 0}, // S_CENTAUR_WALK2 - {SPR_CENT, 2, 4, A_Chase, S_CENTAUR_WALK4, 0, 0}, // S_CENTAUR_WALK3 - {SPR_CENT, 3, 4, A_Chase, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_WALK4 - {SPR_CENT, 7, 5, A_FaceTarget, S_CENTAUR_ATK2, 0, 0}, // S_CENTAUR_ATK1 - {SPR_CENT, 8, 4, A_FaceTarget, S_CENTAUR_ATK3, 0, 0}, // S_CENTAUR_ATK2 - {SPR_CENT, 9, 7, A_CentaurAttack, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_ATK3 - {SPR_CENT, 4, 10, A_FaceTarget, S_CENTAUR_MISSILE2, 0, 0}, // S_CENTAUR_MISSILE1 - {SPR_CENT, 32773, 8, A_CentaurAttack2, S_CENTAUR_MISSILE3, 0, 0}, // S_CENTAUR_MISSILE2 - {SPR_CENT, 4, 10, A_FaceTarget, S_CENTAUR_MISSILE4, 0, 0}, // S_CENTAUR_MISSILE3 - {SPR_CENT, 32773, 8, A_CentaurAttack2, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_MISSILE4 - {SPR_CENT, 6, 6, A_Pain, S_CENTAUR_PAIN2, 0, 0}, // S_CENTAUR_PAIN1 - {SPR_CENT, 6, 6, A_SetReflective, S_CENTAUR_PAIN3, 0, 0}, // S_CENTAUR_PAIN2 - {SPR_CENT, 4, 15, A_CentaurDefend, S_CENTAUR_PAIN4, 0, 0}, // S_CENTAUR_PAIN3 - {SPR_CENT, 4, 15, A_CentaurDefend, S_CENTAUR_PAIN5, 0, 0}, // S_CENTAUR_PAIN4 - {SPR_CENT, 4, 15, A_CentaurDefend, S_CENTAUR_PAIN6, 0, 0}, // S_CENTAUR_PAIN5 - {SPR_CENT, 4, 1, A_UnSetReflective, S_CENTAUR_WALK1, 0, 0}, // S_CENTAUR_PAIN6 - {SPR_CENT, 10, 4, NULL, S_CENTAUR_DEATH2, 0, 0}, // S_CENTAUR_DEATH1 - {SPR_CENT, 11, 4, A_Scream, S_CENTAUR_DEATH3, 0, 0}, // S_CENTAUR_DEATH2 - {SPR_CENT, 12, 4, NULL, S_CENTAUR_DEATH4, 0, 0}, // S_CENTAUR_DEATH3 - {SPR_CENT, 13, 4, NULL, S_CENTAUR_DEATH5, 0, 0}, // S_CENTAUR_DEATH4 - {SPR_CENT, 14, 4, A_NoBlocking, S_CENTAUR_DEATH6, 0, 0}, // S_CENTAUR_DEATH5 - {SPR_CENT, 15, 4, NULL, S_CENTAUR_DEATH7, 0, 0}, // S_CENTAUR_DEATH6 - {SPR_CENT, 16, 4, NULL, S_CENTAUR_DEATH8, 0, 0}, // S_CENTAUR_DEATH7 - {SPR_CENT, 17, 4, A_QueueCorpse, S_CENTAUR_DEATH9, 0, 0}, // S_CENTAUR_DEATH8 - {SPR_CENT, 18, 4, NULL, S_CENTAUR_DEATH0, 0, 0}, // S_CENTAUR_DEATH9 - {SPR_CENT, 19, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_DEATH0 - {SPR_CTXD, 0, 4, NULL, S_CENTAUR_DEATH_X2, 0, 0}, // S_CENTAUR_DEATH_X1 - {SPR_CTXD, 1, 4, A_NoBlocking, S_CENTAUR_DEATH_X3, 0, 0}, // S_CENTAUR_DEATH_X2 - {SPR_CTXD, 2, 4, A_CentaurDropStuff, S_CENTAUR_DEATH_X4, 0, 0}, // S_CENTAUR_DEATH_X3 - {SPR_CTXD, 3, 3, A_Scream, S_CENTAUR_DEATH_X5, 0, 0}, // S_CENTAUR_DEATH_X4 - {SPR_CTXD, 4, 4, A_QueueCorpse, S_CENTAUR_DEATH_X6, 0, 0}, // S_CENTAUR_DEATH_X5 - {SPR_CTXD, 5, 3, NULL, S_CENTAUR_DEATH_X7, 0, 0}, // S_CENTAUR_DEATH_X6 - {SPR_CTXD, 6, 4, NULL, S_CENTAUR_DEATH_X8, 0, 0}, // S_CENTAUR_DEATH_X7 - {SPR_CTXD, 7, 3, NULL, S_CENTAUR_DEATH_X9, 0, 0}, // S_CENTAUR_DEATH_X8 - {SPR_CTXD, 8, 4, NULL, S_CENTAUR_DEATH_X10, 0, 0}, // S_CENTAUR_DEATH_X9 - {SPR_CTXD, 9, 3, NULL, S_CENTAUR_DEATH_X11, 0, 0}, // S_CENTAUR_DEATH_X10 - {SPR_CTXD, 10, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_DEATH_X11 - {SPR_CENT, 20, 5, A_FreezeDeath, S_CENTAUR_ICE2, 0, 0}, // S_CENTAUR_ICE - {SPR_CENT, 20, 1, A_FreezeDeathChunks, S_CENTAUR_ICE2, 0, 0}, // S_CENTAUR_ICE2 - {SPR_CTFX, 32768, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_FX1 - {SPR_CTFX, 32769, 4, NULL, S_CENTAUR_FX_X2, 0, 0}, // S_CENTAUR_FX_X1 - {SPR_CTFX, 32770, 3, NULL, S_CENTAUR_FX_X3, 0, 0}, // S_CENTAUR_FX_X2 - {SPR_CTFX, 32771, 4, NULL, S_CENTAUR_FX_X4, 0, 0}, // S_CENTAUR_FX_X3 - {SPR_CTFX, 32772, 3, NULL, S_CENTAUR_FX_X5, 0, 0}, // S_CENTAUR_FX_X4 - {SPR_CTFX, 32773, 2, NULL, S_NULL, 0, 0}, // S_CENTAUR_FX_X5 - {SPR_CTDP, 0, 3, A_CheckFloor, S_CENTAUR_SHIELD2, 0, 0}, // S_CENTAUR_SHIELD1 - {SPR_CTDP, 1, 3, A_CheckFloor, S_CENTAUR_SHIELD3, 0, 0}, // S_CENTAUR_SHIELD2 - {SPR_CTDP, 2, 3, A_CheckFloor, S_CENTAUR_SHIELD4, 0, 0}, // S_CENTAUR_SHIELD3 - {SPR_CTDP, 3, 3, A_CheckFloor, S_CENTAUR_SHIELD5, 0, 0}, // S_CENTAUR_SHIELD4 - {SPR_CTDP, 4, 3, A_CheckFloor, S_CENTAUR_SHIELD6, 0, 0}, // S_CENTAUR_SHIELD5 - {SPR_CTDP, 5, 3, A_CheckFloor, S_CENTAUR_SHIELD3, 0, 0}, // S_CENTAUR_SHIELD6 - {SPR_CTDP, 6, 4, NULL, S_CENTAUR_SHIELD_X2, 0, 0}, // S_CENTAUR_SHIELD_X1 - {SPR_CTDP, 7, 4, A_QueueCorpse, S_CENTAUR_SHIELD_X3, 0, 0}, // S_CENTAUR_SHIELD_X2 - {SPR_CTDP, 8, 4, NULL, S_CENTAUR_SHIELD_X4, 0, 0}, // S_CENTAUR_SHIELD_X3 - {SPR_CTDP, 9, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_SHIELD_X4 - {SPR_CTDP, 10, 3, A_CheckFloor, S_CENTAUR_SWORD2, 0, 0}, // S_CENTAUR_SWORD1 - {SPR_CTDP, 11, 3, A_CheckFloor, S_CENTAUR_SWORD3, 0, 0}, // S_CENTAUR_SWORD2 - {SPR_CTDP, 12, 3, A_CheckFloor, S_CENTAUR_SWORD4, 0, 0}, // S_CENTAUR_SWORD3 - {SPR_CTDP, 13, 3, A_CheckFloor, S_CENTAUR_SWORD5, 0, 0}, // S_CENTAUR_SWORD4 - {SPR_CTDP, 14, 3, A_CheckFloor, S_CENTAUR_SWORD6, 0, 0}, // S_CENTAUR_SWORD5 - {SPR_CTDP, 15, 3, A_CheckFloor, S_CENTAUR_SWORD7, 0, 0}, // S_CENTAUR_SWORD6 - {SPR_CTDP, 16, 3, A_CheckFloor, S_CENTAUR_SWORD3, 0, 0}, // S_CENTAUR_SWORD7 - {SPR_CTDP, 17, 4, NULL, S_CENTAUR_SWORD_X2, 0, 0}, // S_CENTAUR_SWORD_X1 - {SPR_CTDP, 18, 4, A_QueueCorpse, S_CENTAUR_SWORD_X3, 0, 0}, // S_CENTAUR_SWORD_X2 - {SPR_CTDP, 19, -1, NULL, S_NULL, 0, 0}, // S_CENTAUR_SWORD_X3 - {SPR_DEMN, 0, 10, A_Look, S_DEMN_LOOK2, 0, 0}, // S_DEMN_LOOK1 - {SPR_DEMN, 0, 10, A_Look, S_DEMN_LOOK1, 0, 0}, // S_DEMN_LOOK2 - {SPR_DEMN, 0, 4, A_Chase, S_DEMN_CHASE2, 0, 0}, // S_DEMN_CHASE1 - {SPR_DEMN, 1, 4, A_Chase, S_DEMN_CHASE3, 0, 0}, // S_DEMN_CHASE2 - {SPR_DEMN, 2, 4, A_Chase, S_DEMN_CHASE4, 0, 0}, // S_DEMN_CHASE3 - {SPR_DEMN, 3, 4, A_Chase, S_DEMN_CHASE1, 0, 0}, // S_DEMN_CHASE4 - {SPR_DEMN, 4, 6, A_FaceTarget, S_DEMN_ATK1_2, 0, 0}, // S_DEMN_ATK1_1 - {SPR_DEMN, 5, 8, A_FaceTarget, S_DEMN_ATK1_3, 0, 0}, // S_DEMN_ATK1_2 - {SPR_DEMN, 6, 6, A_DemonAttack1, S_DEMN_CHASE1, 0, 0}, // S_DEMN_ATK1_3 - {SPR_DEMN, 4, 5, A_FaceTarget, S_DEMN_ATK2_2, 0, 0}, // S_DEMN_ATK2_1 - {SPR_DEMN, 5, 6, A_FaceTarget, S_DEMN_ATK2_3, 0, 0}, // S_DEMN_ATK2_2 - {SPR_DEMN, 6, 5, A_DemonAttack2, S_DEMN_CHASE1, 0, 0}, // S_DEMN_ATK2_3 - {SPR_DEMN, 4, 4, NULL, S_DEMN_PAIN2, 0, 0}, // S_DEMN_PAIN1 - {SPR_DEMN, 4, 4, A_Pain, S_DEMN_CHASE1, 0, 0}, // S_DEMN_PAIN2 - {SPR_DEMN, 7, 6, NULL, S_DEMN_DEATH2, 0, 0}, // S_DEMN_DEATH1 - {SPR_DEMN, 8, 6, NULL, S_DEMN_DEATH3, 0, 0}, // S_DEMN_DEATH2 - {SPR_DEMN, 9, 6, A_Scream, S_DEMN_DEATH4, 0, 0}, // S_DEMN_DEATH3 - {SPR_DEMN, 10, 6, A_NoBlocking, S_DEMN_DEATH5, 0, 0}, // S_DEMN_DEATH4 - {SPR_DEMN, 11, 6, A_QueueCorpse, S_DEMN_DEATH6, 0, 0}, // S_DEMN_DEATH5 - {SPR_DEMN, 12, 6, NULL, S_DEMN_DEATH7, 0, 0}, // S_DEMN_DEATH6 - {SPR_DEMN, 13, 6, NULL, S_DEMN_DEATH8, 0, 0}, // S_DEMN_DEATH7 - {SPR_DEMN, 14, 6, NULL, S_DEMN_DEATH9, 0, 0}, // S_DEMN_DEATH8 - {SPR_DEMN, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN_DEATH9 - {SPR_DEMN, 7, 6, NULL, S_DEMN_XDEATH2, 0, 0}, // S_DEMN_XDEATH1 - {SPR_DEMN, 8, 6, A_DemonDeath, S_DEMN_XDEATH3, 0, 0}, // S_DEMN_XDEATH2 - {SPR_DEMN, 9, 6, A_Scream, S_DEMN_XDEATH4, 0, 0}, // S_DEMN_XDEATH3 - {SPR_DEMN, 10, 6, A_NoBlocking, S_DEMN_XDEATH5, 0, 0}, // S_DEMN_XDEATH4 - {SPR_DEMN, 11, 6, A_QueueCorpse, S_DEMN_XDEATH6, 0, 0}, // S_DEMN_XDEATH5 - {SPR_DEMN, 12, 6, NULL, S_DEMN_XDEATH7, 0, 0}, // S_DEMN_XDEATH6 - {SPR_DEMN, 13, 6, NULL, S_DEMN_XDEATH8, 0, 0}, // S_DEMN_XDEATH7 - {SPR_DEMN, 14, 6, NULL, S_DEMN_XDEATH9, 0, 0}, // S_DEMN_XDEATH8 - {SPR_DEMN, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN_XDEATH9 - {SPR_DEMN, 16, 5, A_FreezeDeath, S_DEMON_ICE2, 0, 0}, // S_DEMON_ICE - {SPR_DEMN, 16, 1, A_FreezeDeathChunks, S_DEMON_ICE2, 0, 0}, // S_DEMON_ICE2 - {SPR_DEMA, 0, 4, NULL, S_DEMONCHUNK1_2, 0, 0}, // S_DEMONCHUNK1_1 - {SPR_DEMA, 0, 10, A_QueueCorpse, S_DEMONCHUNK1_3, 0, 0}, // S_DEMONCHUNK1_2 - {SPR_DEMA, 0, 20, NULL, S_DEMONCHUNK1_3, 0, 0}, // S_DEMONCHUNK1_3 - {SPR_DEMA, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK1_4 - {SPR_DEMB, 0, 4, NULL, S_DEMONCHUNK2_2, 0, 0}, // S_DEMONCHUNK2_1 - {SPR_DEMB, 0, 10, A_QueueCorpse, S_DEMONCHUNK2_3, 0, 0}, // S_DEMONCHUNK2_2 - {SPR_DEMB, 0, 20, NULL, S_DEMONCHUNK2_3, 0, 0}, // S_DEMONCHUNK2_3 - {SPR_DEMB, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK2_4 - {SPR_DEMC, 0, 4, NULL, S_DEMONCHUNK3_2, 0, 0}, // S_DEMONCHUNK3_1 - {SPR_DEMC, 0, 10, A_QueueCorpse, S_DEMONCHUNK3_3, 0, 0}, // S_DEMONCHUNK3_2 - {SPR_DEMC, 0, 20, NULL, S_DEMONCHUNK3_3, 0, 0}, // S_DEMONCHUNK3_3 - {SPR_DEMC, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK3_4 - {SPR_DEMD, 0, 4, NULL, S_DEMONCHUNK4_2, 0, 0}, // S_DEMONCHUNK4_1 - {SPR_DEMD, 0, 10, A_QueueCorpse, S_DEMONCHUNK4_3, 0, 0}, // S_DEMONCHUNK4_2 - {SPR_DEMD, 0, 20, NULL, S_DEMONCHUNK4_3, 0, 0}, // S_DEMONCHUNK4_3 - {SPR_DEMD, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK4_4 - {SPR_DEME, 0, 4, NULL, S_DEMONCHUNK5_2, 0, 0}, // S_DEMONCHUNK5_1 - {SPR_DEME, 0, 10, A_QueueCorpse, S_DEMONCHUNK5_3, 0, 0}, // S_DEMONCHUNK5_2 - {SPR_DEME, 0, 20, NULL, S_DEMONCHUNK5_3, 0, 0}, // S_DEMONCHUNK5_3 - {SPR_DEME, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMONCHUNK5_4 - {SPR_DMFX, 32768, 4, NULL, S_DEMONFX_MOVE2, 0, 0}, // S_DEMONFX_MOVE1 - {SPR_DMFX, 32769, 4, NULL, S_DEMONFX_MOVE3, 0, 0}, // S_DEMONFX_MOVE2 - {SPR_DMFX, 32770, 4, NULL, S_DEMONFX_MOVE1, 0, 0}, // S_DEMONFX_MOVE3 - {SPR_DMFX, 32771, 4, NULL, S_DEMONFX_BOOM2, 0, 0}, // S_DEMONFX_BOOM1 - {SPR_DMFX, 32772, 4, NULL, S_DEMONFX_BOOM3, 0, 0}, // S_DEMONFX_BOOM2 - {SPR_DMFX, 32773, 3, NULL, S_DEMONFX_BOOM4, 0, 0}, // S_DEMONFX_BOOM3 - {SPR_DMFX, 32774, 3, NULL, S_DEMONFX_BOOM5, 0, 0}, // S_DEMONFX_BOOM4 - {SPR_DMFX, 32775, 3, NULL, S_NULL, 0, 0}, // S_DEMONFX_BOOM5 - {SPR_DEM2, 0, 10, A_Look, S_DEMN2_LOOK2, 0, 0}, // S_DEMN2_LOOK1 - {SPR_DEM2, 0, 10, A_Look, S_DEMN2_LOOK1, 0, 0}, // S_DEMN2_LOOK2 - {SPR_DEM2, 0, 4, A_Chase, S_DEMN2_CHASE2, 0, 0}, // S_DEMN2_CHASE1 - {SPR_DEM2, 1, 4, A_Chase, S_DEMN2_CHASE3, 0, 0}, // S_DEMN2_CHASE2 - {SPR_DEM2, 2, 4, A_Chase, S_DEMN2_CHASE4, 0, 0}, // S_DEMN2_CHASE3 - {SPR_DEM2, 3, 4, A_Chase, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_CHASE4 - {SPR_DEM2, 4, 6, A_FaceTarget, S_DEMN2_ATK1_2, 0, 0}, // S_DEMN2_ATK1_1 - {SPR_DEM2, 5, 8, A_FaceTarget, S_DEMN2_ATK1_3, 0, 0}, // S_DEMN2_ATK1_2 - {SPR_DEM2, 6, 6, A_DemonAttack1, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_ATK1_3 - {SPR_DEM2, 4, 5, A_FaceTarget, S_DEMN2_ATK2_2, 0, 0}, // S_DEMN2_ATK2_1 - {SPR_DEM2, 5, 6, A_FaceTarget, S_DEMN2_ATK2_3, 0, 0}, // S_DEMN2_ATK2_2 - {SPR_DEM2, 6, 5, A_DemonAttack2, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_ATK2_3 - {SPR_DEM2, 4, 4, NULL, S_DEMN2_PAIN2, 0, 0}, // S_DEMN2_PAIN1 - {SPR_DEM2, 4, 4, A_Pain, S_DEMN2_CHASE1, 0, 0}, // S_DEMN2_PAIN2 - {SPR_DEM2, 7, 6, NULL, S_DEMN2_DEATH2, 0, 0}, // S_DEMN2_DEATH1 - {SPR_DEM2, 8, 6, NULL, S_DEMN2_DEATH3, 0, 0}, // S_DEMN2_DEATH2 - {SPR_DEM2, 9, 6, A_Scream, S_DEMN2_DEATH4, 0, 0}, // S_DEMN2_DEATH3 - {SPR_DEM2, 10, 6, A_NoBlocking, S_DEMN2_DEATH5, 0, 0}, // S_DEMN2_DEATH4 - {SPR_DEM2, 11, 6, A_QueueCorpse, S_DEMN2_DEATH6, 0, 0}, // S_DEMN2_DEATH5 - {SPR_DEM2, 12, 6, NULL, S_DEMN2_DEATH7, 0, 0}, // S_DEMN2_DEATH6 - {SPR_DEM2, 13, 6, NULL, S_DEMN2_DEATH8, 0, 0}, // S_DEMN2_DEATH7 - {SPR_DEM2, 14, 6, NULL, S_DEMN2_DEATH9, 0, 0}, // S_DEMN2_DEATH8 - {SPR_DEM2, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN2_DEATH9 - {SPR_DEM2, 7, 6, NULL, S_DEMN2_XDEATH2, 0, 0}, // S_DEMN2_XDEATH1 - {SPR_DEM2, 8, 6, A_Demon2Death, S_DEMN2_XDEATH3, 0, 0}, // S_DEMN2_XDEATH2 - {SPR_DEM2, 9, 6, A_Scream, S_DEMN2_XDEATH4, 0, 0}, // S_DEMN2_XDEATH3 - {SPR_DEM2, 10, 6, A_NoBlocking, S_DEMN2_XDEATH5, 0, 0}, // S_DEMN2_XDEATH4 - {SPR_DEM2, 11, 6, A_QueueCorpse, S_DEMN2_XDEATH6, 0, 0}, // S_DEMN2_XDEATH5 - {SPR_DEM2, 12, 6, NULL, S_DEMN2_XDEATH7, 0, 0}, // S_DEMN2_XDEATH6 - {SPR_DEM2, 13, 6, NULL, S_DEMN2_XDEATH8, 0, 0}, // S_DEMN2_XDEATH7 - {SPR_DEM2, 14, 6, NULL, S_DEMN2_XDEATH9, 0, 0}, // S_DEMN2_XDEATH8 - {SPR_DEM2, 15, -1, NULL, S_NULL, 0, 0}, // S_DEMN2_XDEATH9 - {SPR_DMBA, 0, 4, NULL, S_DEMON2CHUNK1_2, 0, 0}, // S_DEMON2CHUNK1_1 - {SPR_DMBA, 0, 10, A_QueueCorpse, S_DEMON2CHUNK1_3, 0, 0}, // S_DEMON2CHUNK1_2 - {SPR_DMBA, 0, 20, NULL, S_DEMON2CHUNK1_3, 0, 0}, // S_DEMON2CHUNK1_3 - {SPR_DMBA, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK1_4 - {SPR_DMBB, 0, 4, NULL, S_DEMON2CHUNK2_2, 0, 0}, // S_DEMON2CHUNK2_1 - {SPR_DMBB, 0, 10, A_QueueCorpse, S_DEMON2CHUNK2_3, 0, 0}, // S_DEMON2CHUNK2_2 - {SPR_DMBB, 0, 20, NULL, S_DEMON2CHUNK2_3, 0, 0}, // S_DEMON2CHUNK2_3 - {SPR_DMBB, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK2_4 - {SPR_DMBC, 0, 4, NULL, S_DEMON2CHUNK3_2, 0, 0}, // S_DEMON2CHUNK3_1 - {SPR_DMBC, 0, 10, A_QueueCorpse, S_DEMON2CHUNK3_3, 0, 0}, // S_DEMON2CHUNK3_2 - {SPR_DMBC, 0, 20, NULL, S_DEMON2CHUNK3_3, 0, 0}, // S_DEMON2CHUNK3_3 - {SPR_DMBC, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK3_4 - {SPR_DMBD, 0, 4, NULL, S_DEMON2CHUNK4_2, 0, 0}, // S_DEMON2CHUNK4_1 - {SPR_DMBD, 0, 10, A_QueueCorpse, S_DEMON2CHUNK4_3, 0, 0}, // S_DEMON2CHUNK4_2 - {SPR_DMBD, 0, 20, NULL, S_DEMON2CHUNK4_3, 0, 0}, // S_DEMON2CHUNK4_3 - {SPR_DMBD, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK4_4 - {SPR_DMBE, 0, 4, NULL, S_DEMON2CHUNK5_2, 0, 0}, // S_DEMON2CHUNK5_1 - {SPR_DMBE, 0, 10, NULL, S_DEMON2CHUNK5_3, 0, 0}, // S_DEMON2CHUNK5_2 - {SPR_DMBE, 0, 20, NULL, S_DEMON2CHUNK5_3, 0, 0}, // S_DEMON2CHUNK5_3 - {SPR_DMBE, 0, -1, NULL, S_NULL, 0, 0}, // S_DEMON2CHUNK5_4 - {SPR_D2FX, 32768, 4, NULL, S_DEMON2FX_MOVE2, 0, 0}, // S_DEMON2FX_MOVE1 - {SPR_D2FX, 32769, 4, NULL, S_DEMON2FX_MOVE3, 0, 0}, // S_DEMON2FX_MOVE2 - {SPR_D2FX, 32770, 4, NULL, S_DEMON2FX_MOVE4, 0, 0}, // S_DEMON2FX_MOVE3 - {SPR_D2FX, 32771, 4, NULL, S_DEMON2FX_MOVE5, 0, 0}, // S_DEMON2FX_MOVE4 - {SPR_D2FX, 32772, 4, NULL, S_DEMON2FX_MOVE6, 0, 0}, // S_DEMON2FX_MOVE5 - {SPR_D2FX, 32773, 4, NULL, S_DEMON2FX_MOVE1, 0, 0}, // S_DEMON2FX_MOVE6 - {SPR_D2FX, 32774, 4, NULL, S_DEMON2FX_BOOM2, 0, 0}, // S_DEMON2FX_BOOM1 - {SPR_D2FX, 32775, 4, NULL, S_DEMON2FX_BOOM3, 0, 0}, // S_DEMON2FX_BOOM2 - {SPR_D2FX, 32776, 4, NULL, S_DEMON2FX_BOOM4, 0, 0}, // S_DEMON2FX_BOOM3 - {SPR_D2FX, 32777, 4, NULL, S_DEMON2FX_BOOM5, 0, 0}, // S_DEMON2FX_BOOM4 - {SPR_D2FX, 32778, 3, NULL, S_DEMON2FX_BOOM6, 0, 0}, // S_DEMON2FX_BOOM5 - {SPR_D2FX, 32779, 3, NULL, S_NULL, 0, 0}, // S_DEMON2FX_BOOM6 - {SPR_WRTH, 0, 2, A_WraithRaiseInit, S_WRAITH_RAISE2, 0, 0}, // S_WRAITH_RAISE1 - {SPR_WRTH, 0, 2, A_WraithRaise, S_WRAITH_RAISE3, 0, 0}, // S_WRAITH_RAISE2 - {SPR_WRTH, 0, 2, A_FaceTarget, S_WRAITH_RAISE4, 0, 0}, // S_WRAITH_RAISE3 - {SPR_WRTH, 1, 2, A_WraithRaise, S_WRAITH_RAISE5, 0, 0}, // S_WRAITH_RAISE4 - {SPR_WRTH, 1, 2, A_WraithRaise, S_WRAITH_RAISE2, 0, 0}, // S_WRAITH_RAISE5 - {SPR_WRTH, 0, 10, NULL, S_WRAITH_INIT2, 0, 0}, // S_WRAITH_INIT1 - {SPR_WRTH, 1, 5, A_WraithInit, S_WRAITH_LOOK1, 0, 0}, // S_WRAITH_INIT2 - {SPR_WRTH, 0, 15, A_WraithLook, S_WRAITH_LOOK2, 0, 0}, // S_WRAITH_LOOK1 - {SPR_WRTH, 1, 15, A_WraithLook, S_WRAITH_LOOK1, 0, 0}, // S_WRAITH_LOOK2 - {SPR_WRTH, 0, 4, A_WraithChase, S_WRAITH_CHASE2, 0, 0}, // S_WRAITH_CHASE1 - {SPR_WRTH, 1, 4, A_WraithChase, S_WRAITH_CHASE3, 0, 0}, // S_WRAITH_CHASE2 - {SPR_WRTH, 2, 4, A_WraithChase, S_WRAITH_CHASE4, 0, 0}, // S_WRAITH_CHASE3 - {SPR_WRTH, 3, 4, A_WraithChase, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_CHASE4 - {SPR_WRTH, 4, 6, A_FaceTarget, S_WRAITH_ATK1_2, 0, 0}, // S_WRAITH_ATK1_1 - {SPR_WRTH, 5, 6, A_WraithFX3, S_WRAITH_ATK1_3, 0, 0}, // S_WRAITH_ATK1_2 - {SPR_WRTH, 6, 6, A_WraithMelee, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_ATK1_3 - {SPR_WRTH, 4, 6, A_FaceTarget, S_WRAITH_ATK2_2, 0, 0}, // S_WRAITH_ATK2_1 - {SPR_WRTH, 5, 6, NULL, S_WRAITH_ATK2_3, 0, 0}, // S_WRAITH_ATK2_2 - {SPR_WRTH, 6, 6, A_WraithMissile, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_ATK2_3 - {SPR_WRTH, 0, 2, NULL, S_WRAITH_PAIN2, 0, 0}, // S_WRAITH_PAIN1 - {SPR_WRTH, 7, 6, A_Pain, S_WRAITH_CHASE1, 0, 0}, // S_WRAITH_PAIN2 - {SPR_WRTH, 8, 4, NULL, S_WRAITH_DEATH1_2, 0, 0}, // S_WRAITH_DEATH1_1 - {SPR_WRTH, 9, 4, A_Scream, S_WRAITH_DEATH1_3, 0, 0}, // S_WRAITH_DEATH1_2 - {SPR_WRTH, 10, 4, NULL, S_WRAITH_DEATH1_4, 0, 0}, // S_WRAITH_DEATH1_3 - {SPR_WRTH, 11, 4, NULL, S_WRAITH_DEATH1_5, 0, 0}, // S_WRAITH_DEATH1_4 - {SPR_WRTH, 12, 4, A_NoBlocking, S_WRAITH_DEATH1_6, 0, 0}, // S_WRAITH_DEATH1_5 - {SPR_WRTH, 13, 4, A_QueueCorpse, S_WRAITH_DEATH1_7, 0, 0}, // S_WRAITH_DEATH1_6 - {SPR_WRTH, 14, 4, NULL, S_WRAITH_DEATH1_8, 0, 0}, // S_WRAITH_DEATH1_7 - {SPR_WRTH, 15, 5, NULL, S_WRAITH_DEATH1_9, 0, 0}, // S_WRAITH_DEATH1_8 - {SPR_WRTH, 16, 5, NULL, S_WRAITH_DEATH1_0, 0, 0}, // S_WRAITH_DEATH1_9 - {SPR_WRTH, 17, -1, NULL, S_NULL, 0, 0}, // S_WRAITH_DEATH1_0 - {SPR_WRT2, 0, 5, NULL, S_WRAITH_DEATH2_2, 0, 0}, // S_WRAITH_DEATH2_1 - {SPR_WRT2, 1, 5, A_Scream, S_WRAITH_DEATH2_3, 0, 0}, // S_WRAITH_DEATH2_2 - {SPR_WRT2, 2, 5, NULL, S_WRAITH_DEATH2_4, 0, 0}, // S_WRAITH_DEATH2_3 - {SPR_WRT2, 3, 5, NULL, S_WRAITH_DEATH2_5, 0, 0}, // S_WRAITH_DEATH2_4 - {SPR_WRT2, 4, 5, A_NoBlocking, S_WRAITH_DEATH2_6, 0, 0}, // S_WRAITH_DEATH2_5 - {SPR_WRT2, 5, 5, A_QueueCorpse, S_WRAITH_DEATH2_7, 0, 0}, // S_WRAITH_DEATH2_6 - {SPR_WRT2, 6, 5, NULL, S_WRAITH_DEATH2_8, 0, 0}, // S_WRAITH_DEATH2_7 - {SPR_WRT2, 7, -1, NULL, S_NULL, 0, 0}, // S_WRAITH_DEATH2_8 - {SPR_WRT2, 8, 5, A_FreezeDeath, S_WRAITH_ICE2, 0, 0}, // S_WRAITH_ICE - {SPR_WRT2, 8, 1, A_FreezeDeathChunks, S_WRAITH_ICE2, 0, 0}, // S_WRAITH_ICE2 - {SPR_WRBL, 32768, 3, NULL, S_WRTHFX_MOVE2, 0, 0}, // S_WRTHFX_MOVE1 - {SPR_WRBL, 32769, 3, A_WraithFX2, S_WRTHFX_MOVE3, 0, 0}, // S_WRTHFX_MOVE2 - {SPR_WRBL, 32770, 3, NULL, S_WRTHFX_MOVE1, 0, 0}, // S_WRTHFX_MOVE3 - {SPR_WRBL, 32771, 4, NULL, S_WRTHFX_BOOM2, 0, 0}, // S_WRTHFX_BOOM1 - {SPR_WRBL, 32772, 4, A_WraithFX2, S_WRTHFX_BOOM3, 0, 0}, // S_WRTHFX_BOOM2 - {SPR_WRBL, 32773, 4, NULL, S_WRTHFX_BOOM4, 0, 0}, // S_WRTHFX_BOOM3 - {SPR_WRBL, 32774, 3, A_WraithFX2, S_WRTHFX_BOOM5, 0, 0}, // S_WRTHFX_BOOM4 - {SPR_WRBL, 32775, 3, A_WraithFX2, S_WRTHFX_BOOM6, 0, 0}, // S_WRTHFX_BOOM5 - {SPR_WRBL, 32776, 3, NULL, S_NULL, 0, 0}, // S_WRTHFX_BOOM6 - {SPR_WRBL, 32777, 4, NULL, S_WRTHFX_SIZZLE2, 0, 0}, // S_WRTHFX_SIZZLE1 - {SPR_WRBL, 32778, 4, NULL, S_WRTHFX_SIZZLE3, 0, 0}, // S_WRTHFX_SIZZLE2 - {SPR_WRBL, 32779, 4, NULL, S_WRTHFX_SIZZLE4, 0, 0}, // S_WRTHFX_SIZZLE3 - {SPR_WRBL, 32780, 4, NULL, S_WRTHFX_SIZZLE5, 0, 0}, // S_WRTHFX_SIZZLE4 - {SPR_WRBL, 32781, 4, NULL, S_WRTHFX_SIZZLE6, 0, 0}, // S_WRTHFX_SIZZLE5 - {SPR_WRBL, 32782, 4, NULL, S_WRTHFX_SIZZLE7, 0, 0}, // S_WRTHFX_SIZZLE6 - {SPR_WRBL, 32783, 4, NULL, S_NULL, 0, 0}, // S_WRTHFX_SIZZLE7 - {SPR_WRBL, 32784, 4, NULL, S_WRTHFX_DROP2, 0, 0}, // S_WRTHFX_DROP1 - {SPR_WRBL, 32785, 4, NULL, S_WRTHFX_DROP3, 0, 0}, // S_WRTHFX_DROP2 - {SPR_WRBL, 32786, 4, NULL, S_WRTHFX_DROP1, 0, 0}, // S_WRTHFX_DROP3 - {SPR_WRBL, 32786, 4, NULL, S_NULL, 0, 0}, // S_WRTHFX_DEAD1 - {SPR_WRBL, 19, 4, NULL, S_WRTHFX_ADROP2, 0, 0}, // S_WRTHFX_ADROP1 - {SPR_WRBL, 20, 4, NULL, S_WRTHFX_ADROP3, 0, 0}, // S_WRTHFX_ADROP2 - {SPR_WRBL, 21, 4, NULL, S_WRTHFX_ADROP4, 0, 0}, // S_WRTHFX_ADROP3 - {SPR_WRBL, 22, 4, NULL, S_WRTHFX_ADROP1, 0, 0}, // S_WRTHFX_ADROP4 - {SPR_WRBL, 22, 10, NULL, S_NULL, 0, 0}, // S_WRTHFX_ADEAD1 - {SPR_WRBL, 23, 7, NULL, S_WRTHFX_BDROP2, 0, 0}, // S_WRTHFX_BDROP1 - {SPR_WRBL, 24, 7, NULL, S_WRTHFX_BDROP3, 0, 0}, // S_WRTHFX_BDROP2 - {SPR_WRBL, 25, 7, NULL, S_WRTHFX_BDROP1, 0, 0}, // S_WRTHFX_BDROP3 - {SPR_WRBL, 25, 35, NULL, S_NULL, 0, 0}, // S_WRTHFX_BDEAD1 - {SPR_MNTR, 0, 15, NULL, S_MNTR_SPAWN2, 0, 0}, // S_MNTR_SPAWN1 - {SPR_MNTR, 0, 15, A_MinotaurFade1, S_MNTR_SPAWN3, 0, 0}, // S_MNTR_SPAWN2 - {SPR_MNTR, 0, 3, A_MinotaurFade2, S_MNTR_LOOK1, 0, 0}, // S_MNTR_SPAWN3 - {SPR_MNTR, 0, 10, A_MinotaurLook, S_MNTR_LOOK2, 0, 0}, // S_MNTR_LOOK1 - {SPR_MNTR, 1, 10, A_MinotaurLook, S_MNTR_LOOK1, 0, 0}, // S_MNTR_LOOK2 - {SPR_MNTR, 0, 5, A_MinotaurChase, S_MNTR_WALK2, 0, 0}, // S_MNTR_WALK1 - {SPR_MNTR, 1, 5, A_MinotaurChase, S_MNTR_WALK3, 0, 0}, // S_MNTR_WALK2 - {SPR_MNTR, 2, 5, A_MinotaurChase, S_MNTR_WALK4, 0, 0}, // S_MNTR_WALK3 - {SPR_MNTR, 3, 5, A_MinotaurChase, S_MNTR_WALK1, 0, 0}, // S_MNTR_WALK4 - {SPR_MNTR, 0, 5, A_MinotaurRoam, S_MNTR_ROAM2, 0, 0}, // S_MNTR_ROAM1 - {SPR_MNTR, 1, 5, A_MinotaurRoam, S_MNTR_ROAM3, 0, 0}, // S_MNTR_ROAM2 - {SPR_MNTR, 2, 5, A_MinotaurRoam, S_MNTR_ROAM4, 0, 0}, // S_MNTR_ROAM3 - {SPR_MNTR, 3, 5, A_MinotaurRoam, S_MNTR_ROAM1, 0, 0}, // S_MNTR_ROAM4 - {SPR_MNTR, 6, 10, A_FaceTarget, S_MNTR_ATK1_2, 0, 0}, // S_MNTR_ATK1_1 - {SPR_MNTR, 7, 7, A_FaceTarget, S_MNTR_ATK1_3, 0, 0}, // S_MNTR_ATK1_2 - {SPR_MNTR, 8, 12, A_MinotaurAtk1, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK1_3 - {SPR_MNTR, 6, 10, A_MinotaurDecide, S_MNTR_ATK2_2, 0, 0}, // S_MNTR_ATK2_1 - {SPR_MNTR, 9, 4, A_FaceTarget, S_MNTR_ATK2_3, 0, 0}, // S_MNTR_ATK2_2 - {SPR_MNTR, 10, 9, A_MinotaurAtk2, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK2_3 - {SPR_MNTR, 6, 10, A_FaceTarget, S_MNTR_ATK3_2, 0, 0}, // S_MNTR_ATK3_1 - {SPR_MNTR, 7, 7, A_FaceTarget, S_MNTR_ATK3_3, 0, 0}, // S_MNTR_ATK3_2 - {SPR_MNTR, 8, 12, A_MinotaurAtk3, S_MNTR_WALK1, 0, 0}, // S_MNTR_ATK3_3 - {SPR_MNTR, 8, 12, NULL, S_MNTR_ATK3_1, 0, 0}, // S_MNTR_ATK3_4 - {SPR_MNTR, 5, 2, A_MinotaurCharge, S_MNTR_ATK4_1, 0, 0}, // S_MNTR_ATK4_1 - {SPR_MNTR, 4, 3, NULL, S_MNTR_PAIN2, 0, 0}, // S_MNTR_PAIN1 - {SPR_MNTR, 4, 6, A_Pain, S_MNTR_WALK1, 0, 0}, // S_MNTR_PAIN2 - {SPR_MNTR, 4, 6, NULL, S_MNTR_DIE2, 0, 0}, // S_MNTR_DIE1 - {SPR_MNTR, 4, 2, A_Scream, S_MNTR_DIE3, 0, 0}, // S_MNTR_DIE2 - {SPR_MNTR, 4, 5, A_SmokePuffExit, S_MNTR_DIE4, 0, 0}, // S_MNTR_DIE3 - {SPR_MNTR, 4, 5, NULL, S_MNTR_DIE5, 0, 0}, // S_MNTR_DIE4 - {SPR_MNTR, 4, 5, A_NoBlocking, S_MNTR_DIE6, 0, 0}, // S_MNTR_DIE5 - {SPR_MNTR, 4, 5, NULL, S_MNTR_DIE7, 0, 0}, // S_MNTR_DIE6 - {SPR_MNTR, 4, 5, A_MinotaurFade1, S_MNTR_DIE8, 0, 0}, // S_MNTR_DIE7 - {SPR_MNTR, 4, 5, A_MinotaurFade0, S_MNTR_DIE9, 0, 0}, // S_MNTR_DIE8 - {SPR_MNTR, 4, 10, NULL, S_NULL, 0, 0}, // S_MNTR_DIE9 - {SPR_FX12, 32768, 6, NULL, S_MNTRFX1_2, 0, 0}, // S_MNTRFX1_1 - {SPR_FX12, 32769, 6, NULL, S_MNTRFX1_1, 0, 0}, // S_MNTRFX1_2 - {SPR_FX12, 32770, 5, NULL, S_MNTRFXI1_2, 0, 0}, // S_MNTRFXI1_1 - {SPR_FX12, 32771, 5, NULL, S_MNTRFXI1_3, 0, 0}, // S_MNTRFXI1_2 - {SPR_FX12, 32772, 5, NULL, S_MNTRFXI1_4, 0, 0}, // S_MNTRFXI1_3 - {SPR_FX12, 32773, 5, NULL, S_MNTRFXI1_5, 0, 0}, // S_MNTRFXI1_4 - {SPR_FX12, 32774, 5, NULL, S_MNTRFXI1_6, 0, 0}, // S_MNTRFXI1_5 - {SPR_FX12, 32775, 5, NULL, S_NULL, 0, 0}, // S_MNTRFXI1_6 - {SPR_FX13, 0, 2, A_MntrFloorFire, S_MNTRFX2_1, 0, 0}, // S_MNTRFX2_1 - {SPR_FX13, 32776, 4, A_Explode, S_MNTRFXI2_2, 0, 0}, // S_MNTRFXI2_1 - {SPR_FX13, 32777, 4, NULL, S_MNTRFXI2_3, 0, 0}, // S_MNTRFXI2_2 - {SPR_FX13, 32778, 4, NULL, S_MNTRFXI2_4, 0, 0}, // S_MNTRFXI2_3 - {SPR_FX13, 32779, 4, NULL, S_MNTRFXI2_5, 0, 0}, // S_MNTRFXI2_4 - {SPR_FX13, 32780, 4, NULL, S_NULL, 0, 0}, // S_MNTRFXI2_5 - {SPR_FX13, 32771, 4, NULL, S_MNTRFX3_2, 0, 0}, // S_MNTRFX3_1 - {SPR_FX13, 32770, 4, NULL, S_MNTRFX3_3, 0, 0}, // S_MNTRFX3_2 - {SPR_FX13, 32769, 5, NULL, S_MNTRFX3_4, 0, 0}, // S_MNTRFX3_3 - {SPR_FX13, 32770, 5, NULL, S_MNTRFX3_5, 0, 0}, // S_MNTRFX3_4 - {SPR_FX13, 32771, 5, NULL, S_MNTRFX3_6, 0, 0}, // S_MNTRFX3_5 - {SPR_FX13, 32772, 5, NULL, S_MNTRFX3_7, 0, 0}, // S_MNTRFX3_6 - {SPR_FX13, 32773, 4, NULL, S_MNTRFX3_8, 0, 0}, // S_MNTRFX3_7 - {SPR_FX13, 32774, 4, NULL, S_MNTRFX3_9, 0, 0}, // S_MNTRFX3_8 - {SPR_FX13, 32775, 4, NULL, S_NULL, 0, 0}, // S_MNTRFX3_9 - {SPR_MNSM, 0, 3, NULL, S_MINOSMOKE2, 0, 0}, // S_MINOSMOKE1 - {SPR_MNSM, 1, 3, NULL, S_MINOSMOKE3, 0, 0}, // S_MINOSMOKE2 - {SPR_MNSM, 2, 3, NULL, S_MINOSMOKE4, 0, 0}, // S_MINOSMOKE3 - {SPR_MNSM, 3, 3, NULL, S_MINOSMOKE5, 0, 0}, // S_MINOSMOKE4 - {SPR_MNSM, 4, 3, NULL, S_MINOSMOKE6, 0, 0}, // S_MINOSMOKE5 - {SPR_MNSM, 5, 3, NULL, S_MINOSMOKE7, 0, 0}, // S_MINOSMOKE6 - {SPR_MNSM, 6, 3, NULL, S_MINOSMOKE8, 0, 0}, // S_MINOSMOKE7 - {SPR_MNSM, 7, 3, NULL, S_MINOSMOKE9, 0, 0}, // S_MINOSMOKE8 - {SPR_MNSM, 8, 3, NULL, S_MINOSMOKE0, 0, 0}, // S_MINOSMOKE9 - {SPR_MNSM, 9, 3, NULL, S_MINOSMOKEA, 0, 0}, // S_MINOSMOKE0 - {SPR_MNSM, 10, 3, NULL, S_MINOSMOKEB, 0, 0}, // S_MINOSMOKEA - {SPR_MNSM, 11, 3, NULL, S_MINOSMOKEC, 0, 0}, // S_MINOSMOKEB - {SPR_MNSM, 12, 3, NULL, S_MINOSMOKED, 0, 0}, // S_MINOSMOKEC - {SPR_MNSM, 13, 3, NULL, S_MINOSMOKEE, 0, 0}, // S_MINOSMOKED - {SPR_MNSM, 14, 3, NULL, S_MINOSMOKEF, 0, 0}, // S_MINOSMOKEE - {SPR_MNSM, 15, 3, NULL, S_MINOSMOKEG, 0, 0}, // S_MINOSMOKEF - {SPR_MNSM, 16, 3, NULL, S_NULL, 0, 0}, // S_MINOSMOKEG - {SPR_MNSM, 0, 3, NULL, S_MINOSMOKEX2, 0, 0}, // S_MINOSMOKEX1 - {SPR_MNSM, 1, 3, NULL, S_MINOSMOKEX3, 0, 0}, // S_MINOSMOKEX2 - {SPR_MNSM, 2, 3, NULL, S_MINOSMOKEX4, 0, 0}, // S_MINOSMOKEX3 - {SPR_MNSM, 3, 3, NULL, S_MINOSMOKEX5, 0, 0}, // S_MINOSMOKEX4 - {SPR_MNSM, 4, 3, NULL, S_MINOSMOKEX6, 0, 0}, // S_MINOSMOKEX5 - {SPR_MNSM, 5, 3, NULL, S_MINOSMOKEX7, 0, 0}, // S_MINOSMOKEX6 - {SPR_MNSM, 6, 3, NULL, S_MINOSMOKEX8, 0, 0}, // S_MINOSMOKEX7 - {SPR_MNSM, 7, 3, NULL, S_MINOSMOKEX9, 0, 0}, // S_MINOSMOKEX8 - {SPR_MNSM, 8, 3, NULL, S_MINOSMOKEX0, 0, 0}, // S_MINOSMOKEX9 - {SPR_MNSM, 9, 3, NULL, S_MINOSMOKEXA, 0, 0}, // S_MINOSMOKEX0 - {SPR_MNSM, 8, 3, NULL, S_MINOSMOKEXB, 0, 0}, // S_MINOSMOKEXA - {SPR_MNSM, 7, 3, NULL, S_MINOSMOKEXC, 0, 0}, // S_MINOSMOKEXB - {SPR_MNSM, 6, 3, NULL, S_MINOSMOKEXD, 0, 0}, // S_MINOSMOKEXC - {SPR_MNSM, 5, 3, NULL, S_MINOSMOKEXE, 0, 0}, // S_MINOSMOKEXD - {SPR_MNSM, 4, 3, NULL, S_MINOSMOKEXF, 0, 0}, // S_MINOSMOKEXE - {SPR_MNSM, 3, 3, NULL, S_MINOSMOKEXG, 0, 0}, // S_MINOSMOKEXF - {SPR_MNSM, 2, 3, NULL, S_MINOSMOKEXH, 0, 0}, // S_MINOSMOKEXG - {SPR_MNSM, 1, 3, NULL, S_MINOSMOKEXI, 0, 0}, // S_MINOSMOKEXH - {SPR_MNSM, 0, 3, NULL, S_NULL, 0, 0}, // S_MINOSMOKEXI - {SPR_SSPT, 7, 10, A_Look, S_SERPENT_LOOK1, 0, 0}, // S_SERPENT_LOOK1 - {SPR_SSPT, 7, 1, A_SerpentChase, S_SERPENT_SWIM2, 0, 0}, // S_SERPENT_SWIM1 - {SPR_SSPT, 7, 1, A_SerpentChase, S_SERPENT_SWIM3, 0, 0}, // S_SERPENT_SWIM2 - {SPR_SSPT, 7, 2, A_SerpentHumpDecide, S_SERPENT_SWIM1, 0, 0}, // S_SERPENT_SWIM3 - {SPR_SSPT, 7, 3, A_SerpentUnHide, S_SERPENT_HUMP2, 0, 0}, // S_SERPENT_HUMP1 - {SPR_SSPT, 4, 3, A_SerpentRaiseHump, S_SERPENT_HUMP3, 0, 0}, // S_SERPENT_HUMP2 - {SPR_SSPT, 5, 3, A_SerpentRaiseHump, S_SERPENT_HUMP4, 0, 0}, // S_SERPENT_HUMP3 - {SPR_SSPT, 6, 3, A_SerpentRaiseHump, S_SERPENT_HUMP5, 0, 0}, // S_SERPENT_HUMP4 - {SPR_SSPT, 4, 3, A_SerpentRaiseHump, S_SERPENT_HUMP6, 0, 0}, // S_SERPENT_HUMP5 - {SPR_SSPT, 5, 3, A_SerpentRaiseHump, S_SERPENT_HUMP7, 0, 0}, // S_SERPENT_HUMP6 - {SPR_SSPT, 6, 3, NULL, S_SERPENT_HUMP8, 0, 0}, // S_SERPENT_HUMP7 - {SPR_SSPT, 4, 3, NULL, S_SERPENT_HUMP9, 0, 0}, // S_SERPENT_HUMP8 - {SPR_SSPT, 5, 3, NULL, S_SERPENT_HUMP10, 0, 0}, // S_SERPENT_HUMP9 - {SPR_SSPT, 6, 3, A_SerpentLowerHump, S_SERPENT_HUMP11, 0, 0}, // S_SERPENT_HUMP10 - {SPR_SSPT, 4, 3, A_SerpentLowerHump, S_SERPENT_HUMP12, 0, 0}, // S_SERPENT_HUMP11 - {SPR_SSPT, 5, 3, A_SerpentLowerHump, S_SERPENT_HUMP13, 0, 0}, // S_SERPENT_HUMP12 - {SPR_SSPT, 6, 3, A_SerpentLowerHump, S_SERPENT_HUMP14, 0, 0}, // S_SERPENT_HUMP13 - {SPR_SSPT, 4, 3, A_SerpentLowerHump, S_SERPENT_HUMP15, 0, 0}, // S_SERPENT_HUMP14 - {SPR_SSPT, 5, 3, A_SerpentHide, S_SERPENT_SWIM1, 0, 0}, // S_SERPENT_HUMP15 - {SPR_SSPT, 0, 1, A_UnHideThing, S_SERPENT_SURFACE2, 0, 0}, // S_SERPENT_SURFACE1 - {SPR_SSPT, 0, 1, A_SerpentBirthScream, S_SERPENT_SURFACE3, 0, 0}, // S_SERPENT_SURFACE2 - {SPR_SSPT, 1, 3, A_SetShootable, S_SERPENT_SURFACE4, 0, 0}, // S_SERPENT_SURFACE3 - {SPR_SSPT, 2, 3, NULL, S_SERPENT_SURFACE5, 0, 0}, // S_SERPENT_SURFACE4 - {SPR_SSPT, 3, 4, A_SerpentCheckForAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_SURFACE5 - {SPR_SSDV, 0, 4, NULL, S_SERPENT_DIVE2, 0, 0}, // S_SERPENT_DIVE1 - {SPR_SSDV, 1, 4, NULL, S_SERPENT_DIVE3, 0, 0}, // S_SERPENT_DIVE2 - {SPR_SSDV, 2, 4, NULL, S_SERPENT_DIVE4, 0, 0}, // S_SERPENT_DIVE3 - {SPR_SSDV, 3, 4, A_UnSetShootable, S_SERPENT_DIVE5, 0, 0}, // S_SERPENT_DIVE4 - {SPR_SSDV, 4, 3, A_SerpentDiveSound, S_SERPENT_DIVE6, 0, 0}, // S_SERPENT_DIVE5 - {SPR_SSDV, 5, 3, NULL, S_SERPENT_DIVE7, 0, 0}, // S_SERPENT_DIVE6 - {SPR_SSDV, 6, 4, NULL, S_SERPENT_DIVE8, 0, 0}, // S_SERPENT_DIVE7 - {SPR_SSDV, 7, 4, NULL, S_SERPENT_DIVE9, 0, 0}, // S_SERPENT_DIVE8 - {SPR_SSDV, 8, 3, NULL, S_SERPENT_DIVE10, 0, 0}, // S_SERPENT_DIVE9 - {SPR_SSDV, 9, 3, A_SerpentHide, S_SERPENT_SWIM1, 0, 0}, // S_SERPENT_DIVE10 - {SPR_SSPT, 8, 5, A_SerpentWalk, S_SERPENT_WALK2, 0, 0}, // S_SERPENT_WALK1 - {SPR_SSPT, 9, 5, A_SerpentWalk, S_SERPENT_WALK3, 0, 0}, // S_SERPENT_WALK2 - {SPR_SSPT, 8, 5, A_SerpentWalk, S_SERPENT_WALK4, 0, 0}, // S_SERPENT_WALK3 - {SPR_SSPT, 9, 5, A_SerpentCheckForAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_WALK4 - {SPR_SSPT, 11, 5, NULL, S_SERPENT_PAIN2, 0, 0}, // S_SERPENT_PAIN1 - {SPR_SSPT, 11, 5, A_Pain, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_PAIN2 - {SPR_SSPT, 10, 6, A_FaceTarget, S_SERPENT_ATK2, 0, 0}, // S_SERPENT_ATK1 - {SPR_SSPT, 11, 5, A_SerpentChooseAttack, S_SERPENT_MELEE1, 0, 0}, // S_SERPENT_ATK2 - {SPR_SSPT, 13, 5, A_SerpentMeleeAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_MELEE1 - {SPR_SSPT, 13, 5, A_SerpentMissileAttack, S_SERPENT_DIVE1, 0, 0}, // S_SERPENT_MISSILE1 - {SPR_SSPT, 14, 4, NULL, S_SERPENT_DIE2, 0, 0}, // S_SERPENT_DIE1 - {SPR_SSPT, 15, 4, A_Scream, S_SERPENT_DIE3, 0, 0}, // S_SERPENT_DIE2 - {SPR_SSPT, 16, 4, A_NoBlocking, S_SERPENT_DIE4, 0, 0}, // S_SERPENT_DIE3 - {SPR_SSPT, 17, 4, NULL, S_SERPENT_DIE5, 0, 0}, // S_SERPENT_DIE4 - {SPR_SSPT, 18, 4, NULL, S_SERPENT_DIE6, 0, 0}, // S_SERPENT_DIE5 - {SPR_SSPT, 19, 4, NULL, S_SERPENT_DIE7, 0, 0}, // S_SERPENT_DIE6 - {SPR_SSPT, 20, 4, NULL, S_SERPENT_DIE8, 0, 0}, // S_SERPENT_DIE7 - {SPR_SSPT, 21, 4, NULL, S_SERPENT_DIE9, 0, 0}, // S_SERPENT_DIE8 - {SPR_SSPT, 22, 4, NULL, S_SERPENT_DIE10, 0, 0}, // S_SERPENT_DIE9 - {SPR_SSPT, 23, 4, NULL, S_SERPENT_DIE11, 0, 0}, // S_SERPENT_DIE10 - {SPR_SSPT, 24, 4, NULL, S_SERPENT_DIE12, 0, 0}, // S_SERPENT_DIE11 - {SPR_SSPT, 25, 4, NULL, S_NULL, 0, 0}, // S_SERPENT_DIE12 - {SPR_SSXD, 0, 4, NULL, S_SERPENT_XDIE2, 0, 0}, // S_SERPENT_XDIE1 - {SPR_SSXD, 1, 4, A_SerpentHeadPop, S_SERPENT_XDIE3, 0, 0}, // S_SERPENT_XDIE2 - {SPR_SSXD, 2, 4, A_NoBlocking, S_SERPENT_XDIE4, 0, 0}, // S_SERPENT_XDIE3 - {SPR_SSXD, 3, 4, NULL, S_SERPENT_XDIE5, 0, 0}, // S_SERPENT_XDIE4 - {SPR_SSXD, 4, 4, NULL, S_SERPENT_XDIE6, 0, 0}, // S_SERPENT_XDIE5 - {SPR_SSXD, 5, 3, NULL, S_SERPENT_XDIE7, 0, 0}, // S_SERPENT_XDIE6 - {SPR_SSXD, 6, 3, NULL, S_SERPENT_XDIE8, 0, 0}, // S_SERPENT_XDIE7 - {SPR_SSXD, 7, 3, A_SerpentSpawnGibs, S_NULL, 0, 0}, // S_SERPENT_XDIE8 - {SPR_SSPT, 26, 5, A_FreezeDeath, S_SERPENT_ICE2, 0, 0}, // S_SERPENT_ICE - {SPR_SSPT, 26, 1, A_FreezeDeathChunks, S_SERPENT_ICE2, 0, 0}, // S_SERPENT_ICE2 - {SPR_SSFX, 32768, 3, A_ContMobjSound, S_SERPENT_FX2, 0, 0}, // S_SERPENT_FX1 - {SPR_SSFX, 32769, 3, NULL, S_SERPENT_FX3, 0, 0}, // S_SERPENT_FX2 - {SPR_SSFX, 32768, 3, NULL, S_SERPENT_FX4, 0, 0}, // S_SERPENT_FX3 - {SPR_SSFX, 32769, 3, NULL, S_SERPENT_FX1, 0, 0}, // S_SERPENT_FX4 - {SPR_SSFX, 32770, 4, NULL, S_SERPENT_FX_X2, 0, 0}, // S_SERPENT_FX_X1 - {SPR_SSFX, 32771, 4, NULL, S_SERPENT_FX_X3, 0, 0}, // S_SERPENT_FX_X2 - {SPR_SSFX, 32772, 4, NULL, S_SERPENT_FX_X4, 0, 0}, // S_SERPENT_FX_X3 - {SPR_SSFX, 32773, 4, NULL, S_SERPENT_FX_X5, 0, 0}, // S_SERPENT_FX_X4 - {SPR_SSFX, 32774, 4, NULL, S_SERPENT_FX_X6, 0, 0}, // S_SERPENT_FX_X5 - {SPR_SSFX, 32775, 4, NULL, S_NULL, 0, 0}, // S_SERPENT_FX_X6 - {SPR_SSXD, 8, 4, A_SerpentHeadCheck, S_SERPENT_HEAD2, 0, 0}, // S_SERPENT_HEAD1 - {SPR_SSXD, 9, 4, A_SerpentHeadCheck, S_SERPENT_HEAD3, 0, 0}, // S_SERPENT_HEAD2 - {SPR_SSXD, 10, 4, A_SerpentHeadCheck, S_SERPENT_HEAD4, 0, 0}, // S_SERPENT_HEAD3 - {SPR_SSXD, 11, 4, A_SerpentHeadCheck, S_SERPENT_HEAD5, 0, 0}, // S_SERPENT_HEAD4 - {SPR_SSXD, 12, 4, A_SerpentHeadCheck, S_SERPENT_HEAD6, 0, 0}, // S_SERPENT_HEAD5 - {SPR_SSXD, 13, 4, A_SerpentHeadCheck, S_SERPENT_HEAD7, 0, 0}, // S_SERPENT_HEAD6 - {SPR_SSXD, 14, 4, A_SerpentHeadCheck, S_SERPENT_HEAD8, 0, 0}, // S_SERPENT_HEAD7 - {SPR_SSXD, 15, 4, A_SerpentHeadCheck, S_SERPENT_HEAD1, 0, 0}, // S_SERPENT_HEAD8 - {SPR_SSXD, 18, -1, NULL, S_SERPENT_HEAD_X1, 0, 0}, // S_SERPENT_HEAD_X1 - {SPR_SSXD, 16, 6, NULL, S_SERPENT_GIB1_2, 0, 0}, // S_SERPENT_GIB1_1 - {SPR_SSXD, 16, 6, A_FloatGib, S_SERPENT_GIB1_3, 0, 0}, // S_SERPENT_GIB1_2 - {SPR_SSXD, 16, 8, A_FloatGib, S_SERPENT_GIB1_4, 0, 0}, // S_SERPENT_GIB1_3 - {SPR_SSXD, 16, 8, A_FloatGib, S_SERPENT_GIB1_5, 0, 0}, // S_SERPENT_GIB1_4 - {SPR_SSXD, 16, 12, A_FloatGib, S_SERPENT_GIB1_6, 0, 0}, // S_SERPENT_GIB1_5 - {SPR_SSXD, 16, 12, A_FloatGib, S_SERPENT_GIB1_7, 0, 0}, // S_SERPENT_GIB1_6 - {SPR_SSXD, 16, 232, A_DelayGib, S_SERPENT_GIB1_8, 0, 0}, // S_SERPENT_GIB1_7 - {SPR_SSXD, 16, 12, A_SinkGib, S_SERPENT_GIB1_9, 0, 0}, // S_SERPENT_GIB1_8 - {SPR_SSXD, 16, 12, A_SinkGib, S_SERPENT_GIB1_10, 0, 0}, // S_SERPENT_GIB1_9 - {SPR_SSXD, 16, 8, A_SinkGib, S_SERPENT_GIB1_11, 0, 0}, // S_SERPENT_GIB1_10 - {SPR_SSXD, 16, 8, A_SinkGib, S_SERPENT_GIB1_12, 0, 0}, // S_SERPENT_GIB1_11 - {SPR_SSXD, 16, 8, A_SinkGib, S_NULL, 0, 0}, // S_SERPENT_GIB1_12 - {SPR_SSXD, 17, 6, NULL, S_SERPENT_GIB2_2, 0, 0}, // S_SERPENT_GIB2_1 - {SPR_SSXD, 17, 6, A_FloatGib, S_SERPENT_GIB2_3, 0, 0}, // S_SERPENT_GIB2_2 - {SPR_SSXD, 17, 8, A_FloatGib, S_SERPENT_GIB2_4, 0, 0}, // S_SERPENT_GIB2_3 - {SPR_SSXD, 17, 8, A_FloatGib, S_SERPENT_GIB2_5, 0, 0}, // S_SERPENT_GIB2_4 - {SPR_SSXD, 17, 12, A_FloatGib, S_SERPENT_GIB2_6, 0, 0}, // S_SERPENT_GIB2_5 - {SPR_SSXD, 17, 12, A_FloatGib, S_SERPENT_GIB2_7, 0, 0}, // S_SERPENT_GIB2_6 - {SPR_SSXD, 17, 232, A_DelayGib, S_SERPENT_GIB2_8, 0, 0}, // S_SERPENT_GIB2_7 - {SPR_SSXD, 17, 12, A_SinkGib, S_SERPENT_GIB2_9, 0, 0}, // S_SERPENT_GIB2_8 - {SPR_SSXD, 17, 12, A_SinkGib, S_SERPENT_GIB2_10, 0, 0}, // S_SERPENT_GIB2_9 - {SPR_SSXD, 17, 8, A_SinkGib, S_SERPENT_GIB2_11, 0, 0}, // S_SERPENT_GIB2_10 - {SPR_SSXD, 17, 8, A_SinkGib, S_SERPENT_GIB2_12, 0, 0}, // S_SERPENT_GIB2_11 - {SPR_SSXD, 17, 8, A_SinkGib, S_NULL, 0, 0}, // S_SERPENT_GIB2_12 - {SPR_SSXD, 19, 6, NULL, S_SERPENT_GIB3_2, 0, 0}, // S_SERPENT_GIB3_1 - {SPR_SSXD, 19, 6, A_FloatGib, S_SERPENT_GIB3_3, 0, 0}, // S_SERPENT_GIB3_2 - {SPR_SSXD, 19, 8, A_FloatGib, S_SERPENT_GIB3_4, 0, 0}, // S_SERPENT_GIB3_3 - {SPR_SSXD, 19, 8, A_FloatGib, S_SERPENT_GIB3_5, 0, 0}, // S_SERPENT_GIB3_4 - {SPR_SSXD, 19, 12, A_FloatGib, S_SERPENT_GIB3_6, 0, 0}, // S_SERPENT_GIB3_5 - {SPR_SSXD, 19, 12, A_FloatGib, S_SERPENT_GIB3_7, 0, 0}, // S_SERPENT_GIB3_6 - {SPR_SSXD, 19, 232, A_DelayGib, S_SERPENT_GIB3_8, 0, 0}, // S_SERPENT_GIB3_7 - {SPR_SSXD, 19, 12, A_SinkGib, S_SERPENT_GIB3_9, 0, 0}, // S_SERPENT_GIB3_8 - {SPR_SSXD, 19, 12, A_SinkGib, S_SERPENT_GIB3_10, 0, 0}, // S_SERPENT_GIB3_9 - {SPR_SSXD, 19, 8, A_SinkGib, S_SERPENT_GIB3_11, 0, 0}, // S_SERPENT_GIB3_10 - {SPR_SSXD, 19, 8, A_SinkGib, S_SERPENT_GIB3_12, 0, 0}, // S_SERPENT_GIB3_11 - {SPR_SSXD, 19, 8, A_SinkGib, S_NULL, 0, 0}, // S_SERPENT_GIB3_12 - {SPR_BISH, 0, 10, A_Look, S_BISHOP_LOOK1, 0, 0}, // S_BISHOP_LOOK1 - {SPR_BISH, 0, 1, A_BishopDecide, S_BISHOP_WALK1, 0, 0}, // S_BISHOP_DECIDE - {SPR_BISH, 0, 2, A_BishopDoBlur, S_BISHOP_BLUR2, 0, 0}, // S_BISHOP_BLUR1 - {SPR_BISH, 0, 4, A_BishopSpawnBlur, S_BISHOP_BLUR2, 0, 0}, // S_BISHOP_BLUR2 - {SPR_BISH, 0, 2, A_Chase, S_BISHOP_WALK2, 0, 0}, // S_BISHOP_WALK1 - {SPR_BISH, 0, 2, A_BishopChase, S_BISHOP_WALK3, 0, 0}, // S_BISHOP_WALK2 - {SPR_BISH, 0, 2, NULL, S_BISHOP_WALK4, 0, 0}, // S_BISHOP_WALK3 - {SPR_BISH, 1, 2, A_BishopChase, S_BISHOP_WALK5, 0, 0}, // S_BISHOP_WALK4 - {SPR_BISH, 1, 2, A_Chase, S_BISHOP_WALK6, 0, 0}, // S_BISHOP_WALK5 - {SPR_BISH, 1, 2, A_BishopChase, S_BISHOP_DECIDE, 0, 0}, // S_BISHOP_WALK6 - {SPR_BISH, 0, 3, A_FaceTarget, S_BISHOP_ATK2, 0, 0}, // S_BISHOP_ATK1 - {SPR_BISH, 32771, 3, A_FaceTarget, S_BISHOP_ATK3, 0, 0}, // S_BISHOP_ATK2 - {SPR_BISH, 32772, 3, A_FaceTarget, S_BISHOP_ATK4, 0, 0}, // S_BISHOP_ATK3 - {SPR_BISH, 32773, 3, A_BishopAttack, S_BISHOP_ATK5, 0, 0}, // S_BISHOP_ATK4 - {SPR_BISH, 32773, 5, A_BishopAttack2, S_BISHOP_ATK5, 0, 0}, // S_BISHOP_ATK5 - {SPR_BISH, 2, 6, A_Pain, S_BISHOP_PAIN2, 0, 0}, // S_BISHOP_PAIN1 - {SPR_BISH, 2, 6, A_BishopPainBlur, S_BISHOP_PAIN3, 0, 0}, // S_BISHOP_PAIN2 - {SPR_BISH, 2, 6, A_BishopPainBlur, S_BISHOP_PAIN4, 0, 0}, // S_BISHOP_PAIN3 - {SPR_BISH, 2, 6, A_BishopPainBlur, S_BISHOP_PAIN5, 0, 0}, // S_BISHOP_PAIN4 - {SPR_BISH, 2, 0, NULL, S_BISHOP_WALK1, 0, 0}, // S_BISHOP_PAIN5 - {SPR_BISH, 6, 6, NULL, S_BISHOP_DEATH2, 0, 0}, // S_BISHOP_DEATH1 - {SPR_BISH, 32775, 6, A_Scream, S_BISHOP_DEATH3, 0, 0}, // S_BISHOP_DEATH2 - {SPR_BISH, 32776, 5, A_NoBlocking, S_BISHOP_DEATH4, 0, 0}, // S_BISHOP_DEATH3 - {SPR_BISH, 32777, 5, A_Explode, S_BISHOP_DEATH5, 0, 0}, // S_BISHOP_DEATH4 - {SPR_BISH, 32778, 5, NULL, S_BISHOP_DEATH6, 0, 0}, // S_BISHOP_DEATH5 - {SPR_BISH, 32779, 4, NULL, S_BISHOP_DEATH7, 0, 0}, // S_BISHOP_DEATH6 - {SPR_BISH, 32780, 4, NULL, S_BISHOP_DEATH8, 0, 0}, // S_BISHOP_DEATH7 - {SPR_BISH, 13, 4, A_BishopPuff, S_BISHOP_DEATH9, 0, 0}, // S_BISHOP_DEATH8 - {SPR_BISH, 14, 4, A_QueueCorpse, S_BISHOP_DEATH10, 0, 0}, // S_BISHOP_DEATH9 - {SPR_BISH, 15, -1, NULL, S_NULL, 0, 0}, // S_BISHOP_DEATH10 - {SPR_BISH, 23, 5, A_FreezeDeath, S_BISHOP_ICE2, 0, 0}, // S_BISHOP_ICE - {SPR_BISH, 23, 1, A_FreezeDeathChunks, S_BISHOP_ICE2, 0, 0}, // S_BISHOP_ICE2 - {SPR_BISH, 16, 5, NULL, S_BISHOP_PUFF2, 0, 0}, // S_BISHOP_PUFF1 - {SPR_BISH, 17, 5, NULL, S_BISHOP_PUFF3, 0, 0}, // S_BISHOP_PUFF2 - {SPR_BISH, 18, 5, NULL, S_BISHOP_PUFF4, 0, 0}, // S_BISHOP_PUFF3 - {SPR_BISH, 19, 5, NULL, S_BISHOP_PUFF5, 0, 0}, // S_BISHOP_PUFF4 - {SPR_BISH, 20, 6, NULL, S_BISHOP_PUFF6, 0, 0}, // S_BISHOP_PUFF5 - {SPR_BISH, 21, 6, NULL, S_BISHOP_PUFF7, 0, 0}, // S_BISHOP_PUFF6 - {SPR_BISH, 22, 5, NULL, S_NULL, 0, 0}, // S_BISHOP_PUFF7 - {SPR_BISH, 0, 16, NULL, S_BISHOPBLUR2, 0, 0}, // S_BISHOPBLUR1 - {SPR_BISH, 0, 8, A_SetAltShadow, S_NULL, 0, 0}, // S_BISHOPBLUR2 - {SPR_BISH, 2, 8, NULL, S_NULL, 0, 0}, // S_BISHOPPAINBLUR1 - {SPR_BPFX, 32768, 1, A_BishopMissileWeave, S_BISHFX1_2, 0, 0}, // S_BISHFX1_1 - {SPR_BPFX, 32769, 1, A_BishopMissileWeave, S_BISHFX1_3, 0, 0}, // S_BISHFX1_2 - {SPR_BPFX, 32768, 1, A_BishopMissileWeave, S_BISHFX1_4, 0, 0}, // S_BISHFX1_3 - {SPR_BPFX, 32769, 1, A_BishopMissileWeave, S_BISHFX1_5, 0, 0}, // S_BISHFX1_4 - {SPR_BPFX, 32769, 0, A_BishopMissileSeek, S_BISHFX1_1, 0, 0}, // S_BISHFX1_5 - {SPR_BPFX, 32770, 4, NULL, S_BISHFXI1_2, 0, 0}, // S_BISHFXI1_1 - {SPR_BPFX, 32771, 4, NULL, S_BISHFXI1_3, 0, 0}, // S_BISHFXI1_2 - {SPR_BPFX, 32772, 4, NULL, S_BISHFXI1_4, 0, 0}, // S_BISHFXI1_3 - {SPR_BPFX, 32773, 4, NULL, S_BISHFXI1_5, 0, 0}, // S_BISHFXI1_4 - {SPR_BPFX, 32774, 3, NULL, S_BISHFXI1_6, 0, 0}, // S_BISHFXI1_5 - {SPR_BPFX, 32775, 3, NULL, S_NULL, 0, 0}, // S_BISHFXI1_6 - {SPR_DRAG, 3, 10, A_Look, S_DRAGON_LOOK1, 0, 0}, // S_DRAGON_LOOK1 - {SPR_DRAG, 2, 5, NULL, S_DRAGON_INIT2, 0, 0}, // S_DRAGON_INIT - {SPR_DRAG, 1, 5, NULL, S_DRAGON_INIT3, 0, 0}, // S_DRAGON_INIT2 - {SPR_DRAG, 0, 5, A_DragonInitFlight, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_INIT3 - {SPR_DRAG, 1, 3, A_DragonFlap, S_DRAGON_WALK2, 0, 0}, // S_DRAGON_WALK1 - {SPR_DRAG, 1, 3, A_DragonFlight, S_DRAGON_WALK3, 0, 0}, // S_DRAGON_WALK2 - {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK4, 0, 0}, // S_DRAGON_WALK3 - {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK5, 0, 0}, // S_DRAGON_WALK4 - {SPR_DRAG, 3, 3, A_DragonFlight, S_DRAGON_WALK6, 0, 0}, // S_DRAGON_WALK5 - {SPR_DRAG, 3, 3, A_DragonFlight, S_DRAGON_WALK7, 0, 0}, // S_DRAGON_WALK6 - {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK8, 0, 0}, // S_DRAGON_WALK7 - {SPR_DRAG, 2, 3, A_DragonFlight, S_DRAGON_WALK9, 0, 0}, // S_DRAGON_WALK8 - {SPR_DRAG, 1, 3, A_DragonFlight, S_DRAGON_WALK10, 0, 0}, // S_DRAGON_WALK9 - {SPR_DRAG, 1, 3, A_DragonFlight, S_DRAGON_WALK11, 0, 0}, // S_DRAGON_WALK10 - {SPR_DRAG, 0, 3, A_DragonFlight, S_DRAGON_WALK12, 0, 0}, // S_DRAGON_WALK11 - {SPR_DRAG, 0, 3, A_DragonFlight, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_WALK12 - {SPR_DRAG, 4, 8, A_DragonAttack, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_ATK1 - {SPR_DRAG, 5, 10, A_DragonPain, S_DRAGON_WALK1, 0, 0}, // S_DRAGON_PAIN1 - {SPR_DRAG, 6, 5, A_Scream, S_DRAGON_DEATH2, 0, 0}, // S_DRAGON_DEATH1 - {SPR_DRAG, 7, 4, A_NoBlocking, S_DRAGON_DEATH3, 0, 0}, // S_DRAGON_DEATH2 - {SPR_DRAG, 8, 4, NULL, S_DRAGON_DEATH4, 0, 0}, // S_DRAGON_DEATH3 - {SPR_DRAG, 9, 4, A_DragonCheckCrash, S_DRAGON_DEATH4, 0, 0}, // S_DRAGON_DEATH4 - {SPR_DRAG, 10, 5, NULL, S_DRAGON_CRASH2, 0, 0}, // S_DRAGON_CRASH1 - {SPR_DRAG, 11, 5, NULL, S_DRAGON_CRASH3, 0, 0}, // S_DRAGON_CRASH2 - {SPR_DRAG, 12, -1, NULL, S_NULL, 0, 0}, // S_DRAGON_CRASH3 - {SPR_DRFX, 32768, 4, NULL, S_DRAGON_FX1_2, 0, 0}, // S_DRAGON_FX1_1 - {SPR_DRFX, 32769, 4, NULL, S_DRAGON_FX1_3, 0, 0}, // S_DRAGON_FX1_2 - {SPR_DRFX, 32770, 4, NULL, S_DRAGON_FX1_4, 0, 0}, // S_DRAGON_FX1_3 - {SPR_DRFX, 32771, 4, NULL, S_DRAGON_FX1_5, 0, 0}, // S_DRAGON_FX1_4 - {SPR_DRFX, 32772, 4, NULL, S_DRAGON_FX1_6, 0, 0}, // S_DRAGON_FX1_5 - {SPR_DRFX, 32773, 4, NULL, S_DRAGON_FX1_1, 0, 0}, // S_DRAGON_FX1_6 - {SPR_DRFX, 32774, 4, NULL, S_DRAGON_FX1_X2, 0, 0}, // S_DRAGON_FX1_X1 - {SPR_DRFX, 32775, 4, NULL, S_DRAGON_FX1_X3, 0, 0}, // S_DRAGON_FX1_X2 - {SPR_DRFX, 32776, 4, NULL, S_DRAGON_FX1_X4, 0, 0}, // S_DRAGON_FX1_X3 - {SPR_DRFX, 32777, 4, A_DragonFX2, S_DRAGON_FX1_X5, 0, 0}, // S_DRAGON_FX1_X4 - {SPR_DRFX, 32778, 3, NULL, S_DRAGON_FX1_X6, 0, 0}, // S_DRAGON_FX1_X5 - {SPR_DRFX, 32779, 3, NULL, S_NULL, 0, 0}, // S_DRAGON_FX1_X6 - {SPR_CFCF, 32784, 1, NULL, S_DRAGON_FX2_2, 0, 0}, // S_DRAGON_FX2_1 - {SPR_CFCF, 32784, 4, A_UnHideThing, S_DRAGON_FX2_3, 0, 0}, // S_DRAGON_FX2_2 - {SPR_CFCF, 32785, 3, A_Scream, S_DRAGON_FX2_4, 0, 0}, // S_DRAGON_FX2_3 - {SPR_CFCF, 32786, 4, NULL, S_DRAGON_FX2_5, 0, 0}, // S_DRAGON_FX2_4 - {SPR_CFCF, 32787, 3, A_Explode, S_DRAGON_FX2_6, 0, 0}, // S_DRAGON_FX2_5 - {SPR_CFCF, 32788, 4, NULL, S_DRAGON_FX2_7, 0, 0}, // S_DRAGON_FX2_6 - {SPR_CFCF, 32789, 3, NULL, S_DRAGON_FX2_8, 0, 0}, // S_DRAGON_FX2_7 - {SPR_CFCF, 32790, 4, NULL, S_DRAGON_FX2_9, 0, 0}, // S_DRAGON_FX2_8 - {SPR_CFCF, 32791, 3, NULL, S_DRAGON_FX2_10, 0, 0}, // S_DRAGON_FX2_9 - {SPR_CFCF, 32792, 4, NULL, S_DRAGON_FX2_11, 0, 0}, // S_DRAGON_FX2_10 - {SPR_CFCF, 32793, 3, NULL, S_NULL, 0, 0}, // S_DRAGON_FX2_11 - {SPR_ARM1, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_1 - {SPR_ARM2, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_2 - {SPR_ARM3, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_3 - {SPR_ARM4, 0, -1, NULL, S_NULL, 0, 0}, // S_ARMOR_4 - {SPR_MAN1, 32768, 4, NULL, S_MANA1_2, 0, 0}, // S_MANA1_1 - {SPR_MAN1, 32769, 4, NULL, S_MANA1_3, 0, 0}, // S_MANA1_2 - {SPR_MAN1, 32770, 4, NULL, S_MANA1_4, 0, 0}, // S_MANA1_3 - {SPR_MAN1, 32771, 4, NULL, S_MANA1_5, 0, 0}, // S_MANA1_4 - {SPR_MAN1, 32772, 4, NULL, S_MANA1_6, 0, 0}, // S_MANA1_5 - {SPR_MAN1, 32773, 4, NULL, S_MANA1_7, 0, 0}, // S_MANA1_6 - {SPR_MAN1, 32774, 4, NULL, S_MANA1_8, 0, 0}, // S_MANA1_7 - {SPR_MAN1, 32775, 4, NULL, S_MANA1_9, 0, 0}, // S_MANA1_8 - {SPR_MAN1, 32776, 4, NULL, S_MANA1_1, 0, 0}, // S_MANA1_9 - {SPR_MAN2, 32768, 4, NULL, S_MANA2_2, 0, 0}, // S_MANA2_1 - {SPR_MAN2, 32769, 4, NULL, S_MANA2_3, 0, 0}, // S_MANA2_2 - {SPR_MAN2, 32770, 4, NULL, S_MANA2_4, 0, 0}, // S_MANA2_3 - {SPR_MAN2, 32771, 4, NULL, S_MANA2_5, 0, 0}, // S_MANA2_4 - {SPR_MAN2, 32772, 4, NULL, S_MANA2_6, 0, 0}, // S_MANA2_5 - {SPR_MAN2, 32773, 4, NULL, S_MANA2_7, 0, 0}, // S_MANA2_6 - {SPR_MAN2, 32774, 4, NULL, S_MANA2_8, 0, 0}, // S_MANA2_7 - {SPR_MAN2, 32775, 4, NULL, S_MANA2_9, 0, 0}, // S_MANA2_8 - {SPR_MAN2, 32776, 4, NULL, S_MANA2_10, 0, 0}, // S_MANA2_9 - {SPR_MAN2, 32777, 4, NULL, S_MANA2_11, 0, 0}, // S_MANA2_10 - {SPR_MAN2, 32778, 4, NULL, S_MANA2_12, 0, 0}, // S_MANA2_11 - {SPR_MAN2, 32779, 4, NULL, S_MANA2_13, 0, 0}, // S_MANA2_12 - {SPR_MAN2, 32780, 4, NULL, S_MANA2_14, 0, 0}, // S_MANA2_13 - {SPR_MAN2, 32781, 4, NULL, S_MANA2_15, 0, 0}, // S_MANA2_14 - {SPR_MAN2, 32782, 4, NULL, S_MANA2_16, 0, 0}, // S_MANA2_15 - {SPR_MAN2, 32783, 4, NULL, S_MANA2_1, 0, 0}, // S_MANA2_16 - {SPR_MAN3, 32768, 4, NULL, S_MANA3_2, 0, 0}, // S_MANA3_1 - {SPR_MAN3, 32769, 4, NULL, S_MANA3_3, 0, 0}, // S_MANA3_2 - {SPR_MAN3, 32770, 4, NULL, S_MANA3_4, 0, 0}, // S_MANA3_3 - {SPR_MAN3, 32771, 4, NULL, S_MANA3_5, 0, 0}, // S_MANA3_4 - {SPR_MAN3, 32772, 4, NULL, S_MANA3_6, 0, 0}, // S_MANA3_5 - {SPR_MAN3, 32773, 4, NULL, S_MANA3_7, 0, 0}, // S_MANA3_6 - {SPR_MAN3, 32774, 4, NULL, S_MANA3_8, 0, 0}, // S_MANA3_7 - {SPR_MAN3, 32775, 4, NULL, S_MANA3_9, 0, 0}, // S_MANA3_8 - {SPR_MAN3, 32776, 4, NULL, S_MANA3_10, 0, 0}, // S_MANA3_9 - {SPR_MAN3, 32777, 4, NULL, S_MANA3_11, 0, 0}, // S_MANA3_10 - {SPR_MAN3, 32778, 4, NULL, S_MANA3_12, 0, 0}, // S_MANA3_11 - {SPR_MAN3, 32779, 4, NULL, S_MANA3_13, 0, 0}, // S_MANA3_12 - {SPR_MAN3, 32780, 4, NULL, S_MANA3_14, 0, 0}, // S_MANA3_13 - {SPR_MAN3, 32781, 4, NULL, S_MANA3_15, 0, 0}, // S_MANA3_14 - {SPR_MAN3, 32782, 4, NULL, S_MANA3_16, 0, 0}, // S_MANA3_15 - {SPR_MAN3, 32783, 4, NULL, S_MANA3_1, 0, 0}, // S_MANA3_16 - {SPR_KEY1, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY1 - {SPR_KEY2, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY2 - {SPR_KEY3, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY3 - {SPR_KEY4, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY4 - {SPR_KEY5, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY5 - {SPR_KEY6, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY6 - {SPR_KEY7, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY7 - {SPR_KEY8, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY8 - {SPR_KEY9, 0, -1, NULL, S_NULL, 0, 0}, // S_KEY9 - {SPR_KEYA, 0, -1, NULL, S_NULL, 0, 0}, // S_KEYA - {SPR_KEYB, 0, -1, NULL, S_NULL, 0, 0}, // S_KEYB - {SPR_TLGL, 0, 1, NULL, S_SND_WIND2, 0, 0}, // S_SND_WIND1 - {SPR_TLGL, 0, 200, A_ESound, S_SND_WIND2, 0, 0}, // S_SND_WIND2 - {SPR_TLGL, 0, 85, A_ESound, S_SND_WATERFALL, 0, 0}, // S_SND_WATERFALL - {SPR_ETTN, 0, 10, A_Look, S_ETTIN_LOOK2, 0, 0}, // S_ETTIN_LOOK1 - {SPR_ETTN, 0, 10, A_Look, S_ETTIN_LOOK1, 0, 0}, // S_ETTIN_LOOK2 - {SPR_ETTN, 0, 5, A_Chase, S_ETTIN_CHASE2, 0, 0}, // S_ETTIN_CHASE1 - {SPR_ETTN, 1, 5, A_Chase, S_ETTIN_CHASE3, 0, 0}, // S_ETTIN_CHASE2 - {SPR_ETTN, 2, 5, A_Chase, S_ETTIN_CHASE4, 0, 0}, // S_ETTIN_CHASE3 - {SPR_ETTN, 3, 5, A_Chase, S_ETTIN_CHASE1, 0, 0}, // S_ETTIN_CHASE4 - {SPR_ETTN, 7, 7, A_Pain, S_ETTIN_CHASE1, 0, 0}, // S_ETTIN_PAIN1 - {SPR_ETTN, 4, 6, A_FaceTarget, S_ETTIN_ATK1_2, 0, 0}, // S_ETTIN_ATK1_1 - {SPR_ETTN, 5, 6, A_FaceTarget, S_ETTIN_ATK1_3, 0, 0}, // S_ETTIN_ATK1_2 - {SPR_ETTN, 6, 8, A_EttinAttack, S_ETTIN_CHASE1, 0, 0}, // S_ETTIN_ATK1_3 - {SPR_ETTN, 8, 4, NULL, S_ETTIN_DEATH1_2, 0, 0}, // S_ETTIN_DEATH1_1 - {SPR_ETTN, 9, 4, NULL, S_ETTIN_DEATH1_3, 0, 0}, // S_ETTIN_DEATH1_2 - {SPR_ETTN, 10, 4, A_Scream, S_ETTIN_DEATH1_4, 0, 0}, // S_ETTIN_DEATH1_3 - {SPR_ETTN, 11, 4, A_NoBlocking, S_ETTIN_DEATH1_5, 0, 0}, // S_ETTIN_DEATH1_4 - {SPR_ETTN, 12, 4, A_QueueCorpse, S_ETTIN_DEATH1_6, 0, 0}, // S_ETTIN_DEATH1_5 - {SPR_ETTN, 13, 4, NULL, S_ETTIN_DEATH1_7, 0, 0}, // S_ETTIN_DEATH1_6 - {SPR_ETTN, 14, 4, NULL, S_ETTIN_DEATH1_8, 0, 0}, // S_ETTIN_DEATH1_7 - {SPR_ETTN, 15, 4, NULL, S_ETTIN_DEATH1_9, 0, 0}, // S_ETTIN_DEATH1_8 - {SPR_ETTN, 16, -1, NULL, S_NULL, 0, 0}, // S_ETTIN_DEATH1_9 - {SPR_ETTB, 0, 4, NULL, S_ETTIN_DEATH2_2, 0, 0}, // S_ETTIN_DEATH2_1 - {SPR_ETTB, 1, 4, A_NoBlocking, S_ETTIN_DEATH2_3, 0, 0}, // S_ETTIN_DEATH2_2 - {SPR_ETTB, 2, 4, A_DropMace, S_ETTIN_DEATH2_4, 0, 0}, // S_ETTIN_DEATH2_3 - {SPR_ETTB, 3, 4, A_Scream, S_ETTIN_DEATH2_5, 0, 0}, // S_ETTIN_DEATH2_4 - {SPR_ETTB, 4, 4, A_QueueCorpse, S_ETTIN_DEATH2_6, 0, 0}, // S_ETTIN_DEATH2_5 - {SPR_ETTB, 5, 4, NULL, S_ETTIN_DEATH2_7, 0, 0}, // S_ETTIN_DEATH2_6 - {SPR_ETTB, 6, 4, NULL, S_ETTIN_DEATH2_8, 0, 0}, // S_ETTIN_DEATH2_7 - {SPR_ETTB, 7, 4, NULL, S_ETTIN_DEATH2_9, 0, 0}, // S_ETTIN_DEATH2_8 - {SPR_ETTB, 8, 4, NULL, S_ETTIN_DEATH2_0, 0, 0}, // S_ETTIN_DEATH2_9 - {SPR_ETTB, 9, 4, NULL, S_ETTIN_DEATH2_A, 0, 0}, // S_ETTIN_DEATH2_0 - {SPR_ETTB, 10, 4, NULL, S_ETTIN_DEATH2_B, 0, 0}, // S_ETTIN_DEATH2_A - {SPR_ETTB, 11, -1, NULL, S_NULL, 0, 0}, // S_ETTIN_DEATH2_B - {SPR_ETTN, 17, 5, A_FreezeDeath, S_ETTIN_ICE2, 0, 0}, // S_ETTIN_ICE1 - {SPR_ETTN, 17, 1, A_FreezeDeathChunks, S_ETTIN_ICE2, 0, 0}, // S_ETTIN_ICE2 - {SPR_ETTB, 12, 5, A_CheckFloor, S_ETTIN_MACE2, 0, 0}, // S_ETTIN_MACE1 - {SPR_ETTB, 13, 5, A_CheckFloor, S_ETTIN_MACE3, 0, 0}, // S_ETTIN_MACE2 - {SPR_ETTB, 14, 5, A_CheckFloor, S_ETTIN_MACE4, 0, 0}, // S_ETTIN_MACE3 - {SPR_ETTB, 15, 5, A_CheckFloor, S_ETTIN_MACE1, 0, 0}, // S_ETTIN_MACE4 - {SPR_ETTB, 16, 5, NULL, S_ETTIN_MACE6, 0, 0}, // S_ETTIN_MACE5 - {SPR_ETTB, 17, 5, A_QueueCorpse, S_ETTIN_MACE7, 0, 0}, // S_ETTIN_MACE6 - {SPR_ETTB, 18, -1, NULL, S_NULL, 0, 0}, // S_ETTIN_MACE7 - {SPR_FDMN, 32791, 5, NULL, S_FIRED_LOOK1, 0, 0}, // S_FIRED_SPAWN1 - {SPR_FDMN, 32772, 10, A_Look, S_FIRED_LOOK2, 0, 0}, // S_FIRED_LOOK1 - {SPR_FDMN, 32773, 10, A_Look, S_FIRED_LOOK3, 0, 0}, // S_FIRED_LOOK2 - {SPR_FDMN, 32774, 10, A_Look, S_FIRED_LOOK1, 0, 0}, // S_FIRED_LOOK3 - {SPR_FDMN, 32772, 8, NULL, S_FIRED_LOOK5, 0, 0}, // S_FIRED_LOOK4 - {SPR_FDMN, 32773, 6, NULL, S_FIRED_LOOK6, 0, 0}, // S_FIRED_LOOK5 - {SPR_FDMN, 32774, 5, NULL, S_FIRED_LOOK7, 0, 0}, // S_FIRED_LOOK6 - {SPR_FDMN, 32773, 8, NULL, S_FIRED_LOOK8, 0, 0}, // S_FIRED_LOOK7 - {SPR_FDMN, 32772, 6, NULL, S_FIRED_LOOK9, 0, 0}, // S_FIRED_LOOK8 - {SPR_FDMN, 32773, 7, A_FiredRocks, S_FIRED_LOOK0, 0, 0}, // S_FIRED_LOOK9 - {SPR_FDMN, 32775, 5, NULL, S_FIRED_LOOKA, 0, 0}, // S_FIRED_LOOK0 - {SPR_FDMN, 32776, 5, NULL, S_FIRED_LOOKB, 0, 0}, // S_FIRED_LOOKA - {SPR_FDMN, 32777, 5, A_UnSetInvulnerable, S_FIRED_WALK1, 0, 0}, // S_FIRED_LOOKB - {SPR_FDMN, 32768, 5, A_FiredChase, S_FIRED_WALK2, 0, 0}, // S_FIRED_WALK1 - {SPR_FDMN, 32769, 5, A_FiredChase, S_FIRED_WALK3, 0, 0}, // S_FIRED_WALK2 - {SPR_FDMN, 32770, 5, A_FiredChase, S_FIRED_WALK1, 0, 0}, // S_FIRED_WALK3 - {SPR_FDMN, 32771, 6, A_Pain, S_FIRED_WALK1, 0, 0}, // S_FIRED_PAIN1 - {SPR_FDMN, 32778, 3, A_FaceTarget, S_FIRED_ATTACK2, 0, 0}, // S_FIRED_ATTACK1 - {SPR_FDMN, 32778, 5, A_FiredAttack, S_FIRED_ATTACK3, 0, 0}, // S_FIRED_ATTACK2 - {SPR_FDMN, 32778, 5, A_FiredAttack, S_FIRED_ATTACK4, 0, 0}, // S_FIRED_ATTACK3 - {SPR_FDMN, 32778, 5, A_FiredAttack, S_FIRED_WALK1, 0, 0}, // S_FIRED_ATTACK4 - {SPR_FDMN, 32771, 4, A_FaceTarget, S_FIRED_DEATH2, 0, 0}, // S_FIRED_DEATH1 - {SPR_FDMN, 32779, 4, A_Scream, S_FIRED_DEATH3, 0, 0}, // S_FIRED_DEATH2 - {SPR_FDMN, 32779, 4, A_NoBlocking, S_FIRED_DEATH4, 0, 0}, // S_FIRED_DEATH3 - {SPR_FDMN, 32779, 200, NULL, S_NULL, 0, 0}, // S_FIRED_DEATH4 - {SPR_FDMN, 12, 5, A_FaceTarget, S_FIRED_XDEATH2, 0, 0}, // S_FIRED_XDEATH1 - {SPR_FDMN, 13, 5, A_NoBlocking, S_FIRED_XDEATH3, 0, 0}, // S_FIRED_XDEATH2 - {SPR_FDMN, 14, 5, A_FiredSplotch, S_NULL, 0, 0}, // S_FIRED_XDEATH3 - {SPR_FDMN, 17, 5, A_FreezeDeath, S_FIRED_ICE2, 0, 0}, // S_FIRED_ICE1 - {SPR_FDMN, 17, 1, A_FreezeDeathChunks, S_FIRED_ICE2, 0, 0}, // S_FIRED_ICE2 - {SPR_FDMN, 15, 3, NULL, S_FIRED_CORPSE2, 0, 0}, // S_FIRED_CORPSE1 - {SPR_FDMN, 15, 6, A_QueueCorpse, S_FIRED_CORPSE3, 0, 0}, // S_FIRED_CORPSE2 - {SPR_FDMN, 24, -1, NULL, S_NULL, 0, 0}, // S_FIRED_CORPSE3 - {SPR_FDMN, 16, 3, NULL, S_FIRED_CORPSE5, 0, 0}, // S_FIRED_CORPSE4 - {SPR_FDMN, 16, 6, A_QueueCorpse, S_FIRED_CORPSE6, 0, 0}, // S_FIRED_CORPSE5 - {SPR_FDMN, 25, -1, NULL, S_NULL, 0, 0}, // S_FIRED_CORPSE6 - {SPR_FDMN, 18, 4, NULL, S_FIRED_RDROP1, 0, 0}, // S_FIRED_RDROP1 - {SPR_FDMN, 18, 5, A_SmBounce, S_FIRED_RDEAD1_2, 0, 0}, // S_FIRED_RDEAD1_1 - {SPR_FDMN, 18, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD1_2 - {SPR_FDMN, 19, 4, NULL, S_FIRED_RDROP2, 0, 0}, // S_FIRED_RDROP2 - {SPR_FDMN, 19, 5, A_SmBounce, S_FIRED_RDEAD2_2, 0, 0}, // S_FIRED_RDEAD2_1 - {SPR_FDMN, 19, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD2_2 - {SPR_FDMN, 20, 4, NULL, S_FIRED_RDROP3, 0, 0}, // S_FIRED_RDROP3 - {SPR_FDMN, 20, 5, A_SmBounce, S_FIRED_RDEAD3_2, 0, 0}, // S_FIRED_RDEAD3_1 - {SPR_FDMN, 20, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD3_2 - {SPR_FDMN, 21, 4, NULL, S_FIRED_RDROP4, 0, 0}, // S_FIRED_RDROP4 - {SPR_FDMN, 21, 5, A_SmBounce, S_FIRED_RDEAD4_2, 0, 0}, // S_FIRED_RDEAD4_1 - {SPR_FDMN, 21, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD4_2 - {SPR_FDMN, 22, 4, NULL, S_FIRED_RDROP5, 0, 0}, // S_FIRED_RDROP5 - {SPR_FDMN, 22, 5, A_SmBounce, S_FIRED_RDEAD5_2, 0, 0}, // S_FIRED_RDEAD5_1 - {SPR_FDMN, 22, 200, NULL, S_NULL, 0, 0}, // S_FIRED_RDEAD5_2 - {SPR_FDMB, 32768, 5, NULL, S_FIRED_FX6_1, 0, 0}, // S_FIRED_FX6_1 - {SPR_FDMB, 32769, 5, NULL, S_FIRED_FX6_3, 0, 0}, // S_FIRED_FX6_2 - {SPR_FDMB, 32770, 5, NULL, S_FIRED_FX6_4, 0, 0}, // S_FIRED_FX6_3 - {SPR_FDMB, 32771, 5, NULL, S_FIRED_FX6_5, 0, 0}, // S_FIRED_FX6_4 - {SPR_FDMB, 32772, 5, NULL, S_NULL, 0, 0}, // S_FIRED_FX6_5 - {SPR_ICEY, 0, 10, A_IceGuyLook, S_ICEGUY_LOOK, 0, 0}, // S_ICEGUY_LOOK - {SPR_ICEY, 0, -1, NULL, S_ICEGUY_LOOK, 0, 0}, // S_ICEGUY_DORMANT - {SPR_ICEY, 0, 4, A_Chase, S_ICEGUY_WALK2, 0, 0}, // S_ICEGUY_WALK1 - {SPR_ICEY, 1, 4, A_IceGuyChase, S_ICEGUY_WALK3, 0, 0}, // S_ICEGUY_WALK2 - {SPR_ICEY, 2, 4, A_Chase, S_ICEGUY_WALK4, 0, 0}, // S_ICEGUY_WALK3 - {SPR_ICEY, 3, 4, A_Chase, S_ICEGUY_WALK1, 0, 0}, // S_ICEGUY_WALK4 - {SPR_ICEY, 4, 3, A_FaceTarget, S_ICEGUY_ATK2, 0, 0}, // S_ICEGUY_ATK1 - {SPR_ICEY, 5, 3, A_FaceTarget, S_ICEGUY_ATK3, 0, 0}, // S_ICEGUY_ATK2 - {SPR_ICEY, 32774, 8, A_IceGuyAttack, S_ICEGUY_ATK4, 0, 0}, // S_ICEGUY_ATK3 - {SPR_ICEY, 5, 4, A_FaceTarget, S_ICEGUY_WALK1, 0, 0}, // S_ICEGUY_ATK4 - {SPR_ICEY, 0, 1, A_Pain, S_ICEGUY_WALK1, 0, 0}, // S_ICEGUY_PAIN1 - {SPR_ICEY, 0, 1, A_IceGuyDie, S_NULL, 0, 0}, // S_ICEGUY_DEATH - {SPR_ICPR, 32768, 3, A_IceGuyMissilePuff, S_ICEGUY_FX2, 0, 0}, // S_ICEGUY_FX1 - {SPR_ICPR, 32769, 3, A_IceGuyMissilePuff, S_ICEGUY_FX3, 0, 0}, // S_ICEGUY_FX2 - {SPR_ICPR, 32770, 3, A_IceGuyMissilePuff, S_ICEGUY_FX1, 0, 0}, // S_ICEGUY_FX3 - {SPR_ICPR, 32771, 4, NULL, S_ICEGUY_FX_X2, 0, 0}, // S_ICEGUY_FX_X1 - {SPR_ICPR, 32772, 4, A_IceGuyMissileExplode, S_ICEGUY_FX_X3, 0, 0}, // S_ICEGUY_FX_X2 - {SPR_ICPR, 32773, 4, NULL, S_ICEGUY_FX_X4, 0, 0}, // S_ICEGUY_FX_X3 - {SPR_ICPR, 32774, 4, NULL, S_ICEGUY_FX_X5, 0, 0}, // S_ICEGUY_FX_X4 - {SPR_ICPR, 32775, 3, NULL, S_NULL, 0, 0}, // S_ICEGUY_FX_X5 - {SPR_ICPR, 8, 3, NULL, S_ICEFX_PUFF2, 0, 0}, // S_ICEFX_PUFF1 - {SPR_ICPR, 9, 3, NULL, S_ICEFX_PUFF3, 0, 0}, // S_ICEFX_PUFF2 - {SPR_ICPR, 10, 3, NULL, S_ICEFX_PUFF4, 0, 0}, // S_ICEFX_PUFF3 - {SPR_ICPR, 11, 2, NULL, S_ICEFX_PUFF5, 0, 0}, // S_ICEFX_PUFF4 - {SPR_ICPR, 12, 2, NULL, S_NULL, 0, 0}, // S_ICEFX_PUFF5 - {SPR_ICPR, 32781, 3, NULL, S_ICEGUY_FX2_2, 0, 0}, // S_ICEGUY_FX2_1 - {SPR_ICPR, 32782, 3, NULL, S_ICEGUY_FX2_3, 0, 0}, // S_ICEGUY_FX2_2 - {SPR_ICPR, 32783, 3, NULL, S_ICEGUY_FX2_1, 0, 0}, // S_ICEGUY_FX2_3 - {SPR_ICPR, 32784, 50, NULL, S_NULL, 0, 0}, // S_ICEGUY_BIT1 - {SPR_ICPR, 32785, 50, NULL, S_NULL, 0, 0}, // S_ICEGUY_BIT2 - {SPR_ICWS, 0, 2, NULL, S_ICEGUY_WISP1_2, 0, 0}, // S_ICEGUY_WISP1_1 - {SPR_ICWS, 1, 2, NULL, S_ICEGUY_WISP1_3, 0, 0}, // S_ICEGUY_WISP1_2 - {SPR_ICWS, 2, 2, NULL, S_ICEGUY_WISP1_4, 0, 0}, // S_ICEGUY_WISP1_3 - {SPR_ICWS, 3, 2, NULL, S_ICEGUY_WISP1_5, 0, 0}, // S_ICEGUY_WISP1_4 - {SPR_ICWS, 4, 2, NULL, S_ICEGUY_WISP1_6, 0, 0}, // S_ICEGUY_WISP1_5 - {SPR_ICWS, 5, 2, NULL, S_ICEGUY_WISP1_7, 0, 0}, // S_ICEGUY_WISP1_6 - {SPR_ICWS, 6, 2, NULL, S_ICEGUY_WISP1_8, 0, 0}, // S_ICEGUY_WISP1_7 - {SPR_ICWS, 7, 2, NULL, S_ICEGUY_WISP1_9, 0, 0}, // S_ICEGUY_WISP1_8 - {SPR_ICWS, 8, 2, NULL, S_NULL, 0, 0}, // S_ICEGUY_WISP1_9 - {SPR_ICWS, 9, 2, NULL, S_ICEGUY_WISP2_2, 0, 0}, // S_ICEGUY_WISP2_1 - {SPR_ICWS, 10, 2, NULL, S_ICEGUY_WISP2_3, 0, 0}, // S_ICEGUY_WISP2_2 - {SPR_ICWS, 11, 2, NULL, S_ICEGUY_WISP2_4, 0, 0}, // S_ICEGUY_WISP2_3 - {SPR_ICWS, 12, 2, NULL, S_ICEGUY_WISP2_5, 0, 0}, // S_ICEGUY_WISP2_4 - {SPR_ICWS, 13, 2, NULL, S_ICEGUY_WISP2_6, 0, 0}, // S_ICEGUY_WISP2_5 - {SPR_ICWS, 14, 2, NULL, S_ICEGUY_WISP2_7, 0, 0}, // S_ICEGUY_WISP2_6 - {SPR_ICWS, 15, 2, NULL, S_ICEGUY_WISP2_8, 0, 0}, // S_ICEGUY_WISP2_7 - {SPR_ICWS, 16, 2, NULL, S_ICEGUY_WISP2_9, 0, 0}, // S_ICEGUY_WISP2_8 - {SPR_ICWS, 17, 2, NULL, S_NULL, 0, 0}, // S_ICEGUY_WISP2_9 - {SPR_PLAY, 0, 2, NULL, S_FIGHTER2, 0, 0}, // S_FIGHTER - {SPR_PLAY, 0, 3, A_ClassBossHealth, S_FIGHTERLOOK, 0, 0}, // S_FIGHTER2 - {SPR_PLAY, 0, 5, A_Look, S_FIGHTERLOOK, 0, 0}, // S_FIGHTERLOOK - {SPR_PLAY, 0, 4, A_FastChase, S_FIGHTER_RUN2, 0, 0}, // S_FIGHTER_RUN1 - {SPR_PLAY, 1, 4, A_FastChase, S_FIGHTER_RUN3, 0, 0}, // S_FIGHTER_RUN2 - {SPR_PLAY, 2, 4, A_FastChase, S_FIGHTER_RUN4, 0, 0}, // S_FIGHTER_RUN3 - {SPR_PLAY, 3, 4, A_FastChase, S_FIGHTER_RUN1, 0, 0}, // S_FIGHTER_RUN4 - {SPR_PLAY, 4, 8, A_FaceTarget, S_FIGHTER_ATK2, 0, 0}, // S_FIGHTER_ATK1 - {SPR_PLAY, 5, 8, A_FighterAttack, S_FIGHTER_RUN1, 0, 0}, // S_FIGHTER_ATK2 - {SPR_PLAY, 6, 4, NULL, S_FIGHTER_PAIN2, 0, 0}, // S_FIGHTER_PAIN - {SPR_PLAY, 6, 4, A_Pain, S_FIGHTER_RUN1, 0, 0}, // S_FIGHTER_PAIN2 - {SPR_PLAY, 7, 6, NULL, S_FIGHTER_DIE2, 0, 0}, // S_FIGHTER_DIE1 - {SPR_PLAY, 8, 6, A_Scream, S_FIGHTER_DIE3, 0, 0}, // S_FIGHTER_DIE2 - {SPR_PLAY, 9, 6, NULL, S_FIGHTER_DIE4, 0, 0}, // S_FIGHTER_DIE3 - {SPR_PLAY, 10, 6, NULL, S_FIGHTER_DIE5, 0, 0}, // S_FIGHTER_DIE4 - {SPR_PLAY, 11, 6, A_NoBlocking, S_FIGHTER_DIE6, 0, 0}, // S_FIGHTER_DIE5 - {SPR_PLAY, 12, 6, NULL, S_FIGHTER_DIE7, 0, 0}, // S_FIGHTER_DIE6 - {SPR_PLAY, 13, -1, NULL, S_NULL, 0, 0}, // S_FIGHTER_DIE7 - {SPR_PLAY, 14, 5, A_Scream, S_FIGHTER_XDIE2, 0, 0}, // S_FIGHTER_XDIE1 - {SPR_PLAY, 15, 5, A_SkullPop, S_FIGHTER_XDIE3, 0, 0}, // S_FIGHTER_XDIE2 - {SPR_PLAY, 17, 5, A_NoBlocking, S_FIGHTER_XDIE4, 0, 0}, // S_FIGHTER_XDIE3 - {SPR_PLAY, 18, 5, NULL, S_FIGHTER_XDIE5, 0, 0}, // S_FIGHTER_XDIE4 - {SPR_PLAY, 19, 5, NULL, S_FIGHTER_XDIE6, 0, 0}, // S_FIGHTER_XDIE5 - {SPR_PLAY, 20, 5, NULL, S_FIGHTER_XDIE7, 0, 0}, // S_FIGHTER_XDIE6 - {SPR_PLAY, 21, 5, NULL, S_FIGHTER_XDIE8, 0, 0}, // S_FIGHTER_XDIE7 - {SPR_PLAY, 22, -1, NULL, S_NULL, 0, 0}, // S_FIGHTER_XDIE8 - {SPR_PLAY, 23, 5, A_FreezeDeath, S_FIGHTER_ICE2, 0, 0}, // S_FIGHTER_ICE - {SPR_PLAY, 23, 1, A_FreezeDeathChunks, S_FIGHTER_ICE2, 0, 0}, // S_FIGHTER_ICE2 - {SPR_CLER, 0, 2, NULL, S_CLERIC2, 0, 0}, // S_CLERIC - {SPR_CLER, 0, 3, A_ClassBossHealth, S_CLERICLOOK, 0, 0}, // S_CLERIC2 - {SPR_CLER, 0, 5, A_Look, S_CLERICLOOK, 0, 0}, // S_CLERICLOOK - {SPR_CLER, 0, 4, A_FastChase, S_CLERIC_RUN2, 0, 0}, // S_CLERIC_RUN1 - {SPR_CLER, 1, 4, A_FastChase, S_CLERIC_RUN3, 0, 0}, // S_CLERIC_RUN2 - {SPR_CLER, 2, 4, A_FastChase, S_CLERIC_RUN4, 0, 0}, // S_CLERIC_RUN3 - {SPR_CLER, 3, 4, A_FastChase, S_CLERIC_RUN1, 0, 0}, // S_CLERIC_RUN4 - {SPR_CLER, 4, 8, A_FaceTarget, S_CLERIC_ATK2, 0, 0}, // S_CLERIC_ATK1 - {SPR_CLER, 5, 8, A_FaceTarget, S_CLERIC_ATK3, 0, 0}, // S_CLERIC_ATK2 - {SPR_CLER, 6, 10, A_ClericAttack, S_CLERIC_RUN1, 0, 0}, // S_CLERIC_ATK3 - {SPR_CLER, 7, 4, NULL, S_CLERIC_PAIN2, 0, 0}, // S_CLERIC_PAIN - {SPR_CLER, 7, 4, A_Pain, S_CLERIC_RUN1, 0, 0}, // S_CLERIC_PAIN2 - {SPR_CLER, 8, 6, NULL, S_CLERIC_DIE2, 0, 0}, // S_CLERIC_DIE1 - {SPR_CLER, 10, 6, A_Scream, S_CLERIC_DIE3, 0, 0}, // S_CLERIC_DIE2 - {SPR_CLER, 11, 6, NULL, S_CLERIC_DIE4, 0, 0}, // S_CLERIC_DIE3 - {SPR_CLER, 11, 6, NULL, S_CLERIC_DIE5, 0, 0}, // S_CLERIC_DIE4 - {SPR_CLER, 12, 6, A_NoBlocking, S_CLERIC_DIE6, 0, 0}, // S_CLERIC_DIE5 - {SPR_CLER, 13, 6, NULL, S_CLERIC_DIE7, 0, 0}, // S_CLERIC_DIE6 - {SPR_CLER, 14, 6, NULL, S_CLERIC_DIE8, 0, 0}, // S_CLERIC_DIE7 - {SPR_CLER, 15, 6, NULL, S_CLERIC_DIE9, 0, 0}, // S_CLERIC_DIE8 - {SPR_CLER, 16, -1, NULL, S_NULL, 0, 0}, // S_CLERIC_DIE9 - {SPR_CLER, 17, 5, A_Scream, S_CLERIC_XDIE2, 0, 0}, // S_CLERIC_XDIE1 - {SPR_CLER, 18, 5, NULL, S_CLERIC_XDIE3, 0, 0}, // S_CLERIC_XDIE2 - {SPR_CLER, 19, 5, A_NoBlocking, S_CLERIC_XDIE4, 0, 0}, // S_CLERIC_XDIE3 - {SPR_CLER, 20, 5, NULL, S_CLERIC_XDIE5, 0, 0}, // S_CLERIC_XDIE4 - {SPR_CLER, 21, 5, NULL, S_CLERIC_XDIE6, 0, 0}, // S_CLERIC_XDIE5 - {SPR_CLER, 22, 5, NULL, S_CLERIC_XDIE7, 0, 0}, // S_CLERIC_XDIE6 - {SPR_CLER, 23, 5, NULL, S_CLERIC_XDIE8, 0, 0}, // S_CLERIC_XDIE7 - {SPR_CLER, 24, 5, NULL, S_CLERIC_XDIE9, 0, 0}, // S_CLERIC_XDIE8 - {SPR_CLER, 25, 5, NULL, S_CLERIC_XDIE10, 0, 0}, // S_CLERIC_XDIE9 - {SPR_CLER, 26, -1, NULL, S_NULL, 0, 0}, // S_CLERIC_XDIE10 - {SPR_CLER, 27, 5, A_FreezeDeath, S_CLERIC_ICE2, 0, 0}, // S_CLERIC_ICE - {SPR_CLER, 27, 1, A_FreezeDeathChunks, S_CLERIC_ICE2, 0, 0}, // S_CLERIC_ICE2 - {SPR_MAGE, 0, 2, NULL, S_MAGE2, 0, 0}, // S_MAGE - {SPR_MAGE, 0, 3, A_ClassBossHealth, S_MAGELOOK, 0, 0}, // S_MAGE2 - {SPR_MAGE, 0, 5, A_Look, S_MAGELOOK, 0, 0}, // S_MAGELOOK - {SPR_MAGE, 0, 4, A_FastChase, S_MAGE_RUN2, 0, 0}, // S_MAGE_RUN1 - {SPR_MAGE, 1, 4, A_FastChase, S_MAGE_RUN3, 0, 0}, // S_MAGE_RUN2 - {SPR_MAGE, 2, 4, A_FastChase, S_MAGE_RUN4, 0, 0}, // S_MAGE_RUN3 - {SPR_MAGE, 3, 4, A_FastChase, S_MAGE_RUN1, 0, 0}, // S_MAGE_RUN4 - {SPR_MAGE, 4, 8, A_FaceTarget, S_MAGE_ATK2, 0, 0}, // S_MAGE_ATK1 - {SPR_MAGE, 32773, 8, A_MageAttack, S_MAGE_RUN1, 0, 0}, // S_MAGE_ATK2 - {SPR_MAGE, 6, 4, NULL, S_MAGE_PAIN2, 0, 0}, // S_MAGE_PAIN - {SPR_MAGE, 6, 4, A_Pain, S_MAGE_RUN1, 0, 0}, // S_MAGE_PAIN2 - {SPR_MAGE, 7, 6, NULL, S_MAGE_DIE2, 0, 0}, // S_MAGE_DIE1 - {SPR_MAGE, 8, 6, A_Scream, S_MAGE_DIE3, 0, 0}, // S_MAGE_DIE2 - {SPR_MAGE, 9, 6, NULL, S_MAGE_DIE4, 0, 0}, // S_MAGE_DIE3 - {SPR_MAGE, 10, 6, NULL, S_MAGE_DIE5, 0, 0}, // S_MAGE_DIE4 - {SPR_MAGE, 11, 6, A_NoBlocking, S_MAGE_DIE6, 0, 0}, // S_MAGE_DIE5 - {SPR_MAGE, 12, 6, NULL, S_MAGE_DIE7, 0, 0}, // S_MAGE_DIE6 - {SPR_MAGE, 13, -1, NULL, S_NULL, 0, 0}, // S_MAGE_DIE7 - {SPR_MAGE, 14, 5, A_Scream, S_MAGE_XDIE2, 0, 0}, // S_MAGE_XDIE1 - {SPR_MAGE, 15, 5, NULL, S_MAGE_XDIE3, 0, 0}, // S_MAGE_XDIE2 - {SPR_MAGE, 17, 5, A_NoBlocking, S_MAGE_XDIE4, 0, 0}, // S_MAGE_XDIE3 - {SPR_MAGE, 18, 5, NULL, S_MAGE_XDIE5, 0, 0}, // S_MAGE_XDIE4 - {SPR_MAGE, 19, 5, NULL, S_MAGE_XDIE6, 0, 0}, // S_MAGE_XDIE5 - {SPR_MAGE, 20, 5, NULL, S_MAGE_XDIE7, 0, 0}, // S_MAGE_XDIE6 - {SPR_MAGE, 21, 5, NULL, S_MAGE_XDIE8, 0, 0}, // S_MAGE_XDIE7 - {SPR_MAGE, 22, 5, NULL, S_MAGE_XDIE9, 0, 0}, // S_MAGE_XDIE8 - {SPR_MAGE, 23, -1, NULL, S_NULL, 0, 0}, // S_MAGE_XDIE9 - {SPR_MAGE, 24, 5, A_FreezeDeath, S_MAGE_ICE2, 0, 0}, // S_MAGE_ICE - {SPR_MAGE, 24, 1, A_FreezeDeathChunks, S_MAGE_ICE2, 0, 0}, // S_MAGE_ICE2 - {SPR_SORC, 0, 3, NULL, S_SORC_SPAWN2, 0, 0}, // S_SORC_SPAWN1 - {SPR_SORC, 0, 2, A_SorcSpinBalls, S_SORC_LOOK1, 0, 0}, // S_SORC_SPAWN2 - {SPR_SORC, 0, 10, A_Look, S_SORC_LOOK1, 0, 0}, // S_SORC_LOOK1 - {SPR_SORC, 0, 5, A_Chase, S_SORC_WALK2, 0, 0}, // S_SORC_WALK1 - {SPR_SORC, 1, 5, A_Chase, S_SORC_WALK3, 0, 0}, // S_SORC_WALK2 - {SPR_SORC, 2, 5, A_Chase, S_SORC_WALK4, 0, 0}, // S_SORC_WALK3 - {SPR_SORC, 3, 5, A_Chase, S_SORC_WALK1, 0, 0}, // S_SORC_WALK4 - {SPR_SORC, 6, 8, NULL, S_SORC_PAIN2, 0, 0}, // S_SORC_PAIN1 - {SPR_SORC, 6, 8, A_Pain, S_SORC_WALK1, 0, 0}, // S_SORC_PAIN2 - {SPR_SORC, 32773, 6, A_FaceTarget, S_SORC_ATK2_2, 0, 0}, // S_SORC_ATK2_1 - {SPR_SORC, 32773, 6, A_SpeedBalls, S_SORC_ATK2_3, 0, 0}, // S_SORC_ATK2_2 - {SPR_SORC, 32773, 6, A_FaceTarget, S_SORC_ATK2_3, 0, 0}, // S_SORC_ATK2_3 - {SPR_SORC, 32772, 6, NULL, S_SORC_ATTACK2, 0, 0}, // S_SORC_ATTACK1 - {SPR_SORC, 32772, 6, A_SpawnFizzle, S_SORC_ATTACK3, 0, 0}, // S_SORC_ATTACK2 - {SPR_SORC, 32772, 5, A_FaceTarget, S_SORC_ATTACK2, 0, 0}, // S_SORC_ATTACK3 - {SPR_SORC, 32772, 2, NULL, S_SORC_ATTACK5, 0, 0}, // S_SORC_ATTACK4 - {SPR_SORC, 32772, 2, A_SorcBossAttack, S_SORC_WALK1, 0, 0}, // S_SORC_ATTACK5 - {SPR_SORC, 32775, 5, NULL, S_SORC_DIE2, 0, 0}, // S_SORC_DIE1 - {SPR_SORC, 32776, 5, A_FaceTarget, S_SORC_DIE3, 0, 0}, // S_SORC_DIE2 - {SPR_SORC, 32777, 5, A_Scream, S_SORC_DIE4, 0, 0}, // S_SORC_DIE3 - {SPR_SORC, 32778, 5, NULL, S_SORC_DIE5, 0, 0}, // S_SORC_DIE4 - {SPR_SORC, 32779, 5, NULL, S_SORC_DIE6, 0, 0}, // S_SORC_DIE5 - {SPR_SORC, 32780, 5, NULL, S_SORC_DIE7, 0, 0}, // S_SORC_DIE6 - {SPR_SORC, 32781, 5, NULL, S_SORC_DIE8, 0, 0}, // S_SORC_DIE7 - {SPR_SORC, 32782, 5, NULL, S_SORC_DIE9, 0, 0}, // S_SORC_DIE8 - {SPR_SORC, 32783, 5, NULL, S_SORC_DIE0, 0, 0}, // S_SORC_DIE9 - {SPR_SORC, 32784, 5, NULL, S_SORC_DIEA, 0, 0}, // S_SORC_DIE0 - {SPR_SORC, 32785, 5, NULL, S_SORC_DIEB, 0, 0}, // S_SORC_DIEA - {SPR_SORC, 32786, 5, NULL, S_SORC_DIEC, 0, 0}, // S_SORC_DIEB - {SPR_SORC, 32787, 5, NULL, S_SORC_DIED, 0, 0}, // S_SORC_DIEC - {SPR_SORC, 32788, 5, A_NoBlocking, S_SORC_DIEE, 0, 0}, // S_SORC_DIED - {SPR_SORC, 32789, 5, NULL, S_SORC_DIEF, 0, 0}, // S_SORC_DIEE - {SPR_SORC, 32790, 5, NULL, S_SORC_DIEG, 0, 0}, // S_SORC_DIEF - {SPR_SORC, 32791, 5, NULL, S_SORC_DIEH, 0, 0}, // S_SORC_DIEG - {SPR_SORC, 32792, 5, NULL, S_SORC_DIEI, 0, 0}, // S_SORC_DIEH - {SPR_SORC, 32793, -1, NULL, S_NULL, 0, 0}, // S_SORC_DIEI - {SPR_SBMP, 0, 2, A_SorcBallOrbit, S_SORCBALL1_2, 0, 0}, // S_SORCBALL1_1 - {SPR_SBMP, 1, 2, A_SorcBallOrbit, S_SORCBALL1_3, 0, 0}, // S_SORCBALL1_2 - {SPR_SBMP, 2, 2, A_SorcBallOrbit, S_SORCBALL1_4, 0, 0}, // S_SORCBALL1_3 - {SPR_SBMP, 3, 2, A_SorcBallOrbit, S_SORCBALL1_5, 0, 0}, // S_SORCBALL1_4 - {SPR_SBMP, 4, 2, A_SorcBallOrbit, S_SORCBALL1_6, 0, 0}, // S_SORCBALL1_5 - {SPR_SBMP, 5, 2, A_SorcBallOrbit, S_SORCBALL1_7, 0, 0}, // S_SORCBALL1_6 - {SPR_SBMP, 6, 2, A_SorcBallOrbit, S_SORCBALL1_8, 0, 0}, // S_SORCBALL1_7 - {SPR_SBMP, 7, 2, A_SorcBallOrbit, S_SORCBALL1_9, 0, 0}, // S_SORCBALL1_8 - {SPR_SBMP, 8, 2, A_SorcBallOrbit, S_SORCBALL1_0, 0, 0}, // S_SORCBALL1_9 - {SPR_SBMP, 9, 2, A_SorcBallOrbit, S_SORCBALL1_A, 0, 0}, // S_SORCBALL1_0 - {SPR_SBMP, 10, 2, A_SorcBallOrbit, S_SORCBALL1_B, 0, 0}, // S_SORCBALL1_A - {SPR_SBMP, 11, 2, A_SorcBallOrbit, S_SORCBALL1_C, 0, 0}, // S_SORCBALL1_B - {SPR_SBMP, 12, 2, A_SorcBallOrbit, S_SORCBALL1_D, 0, 0}, // S_SORCBALL1_C - {SPR_SBMP, 13, 2, A_SorcBallOrbit, S_SORCBALL1_E, 0, 0}, // S_SORCBALL1_D - {SPR_SBMP, 14, 2, A_SorcBallOrbit, S_SORCBALL1_F, 0, 0}, // S_SORCBALL1_E - {SPR_SBMP, 15, 2, A_SorcBallOrbit, S_SORCBALL1_1, 0, 0}, // S_SORCBALL1_F - {SPR_SBMP, 0, 5, A_SorcBallPop, S_SORCBALL1_D2, 0, 0}, // S_SORCBALL1_D1 - {SPR_SBMP, 1, 2, A_BounceCheck, S_SORCBALL1_D2, 0, 0}, // S_SORCBALL1_D2 - {SPR_SBS4, 3, 5, A_Explode, S_SORCBALL1_D6, 0, 0}, // S_SORCBALL1_D5 - {SPR_SBS4, 4, 5, NULL, S_SORCBALL1_D7, 0, 0}, // S_SORCBALL1_D6 - {SPR_SBS4, 5, 6, NULL, S_SORCBALL1_D8, 0, 0}, // S_SORCBALL1_D7 - {SPR_SBS4, 6, 6, NULL, S_SORCBALL1_D9, 0, 0}, // S_SORCBALL1_D8 - {SPR_SBS4, 7, 6, NULL, S_NULL, 0, 0}, // S_SORCBALL1_D9 - {SPR_SBMB, 0, 2, A_SorcBallOrbit, S_SORCBALL2_2, 0, 0}, // S_SORCBALL2_1 - {SPR_SBMB, 1, 2, A_SorcBallOrbit, S_SORCBALL2_3, 0, 0}, // S_SORCBALL2_2 - {SPR_SBMB, 2, 2, A_SorcBallOrbit, S_SORCBALL2_4, 0, 0}, // S_SORCBALL2_3 - {SPR_SBMB, 3, 2, A_SorcBallOrbit, S_SORCBALL2_5, 0, 0}, // S_SORCBALL2_4 - {SPR_SBMB, 4, 2, A_SorcBallOrbit, S_SORCBALL2_6, 0, 0}, // S_SORCBALL2_5 - {SPR_SBMB, 5, 2, A_SorcBallOrbit, S_SORCBALL2_7, 0, 0}, // S_SORCBALL2_6 - {SPR_SBMB, 6, 2, A_SorcBallOrbit, S_SORCBALL2_8, 0, 0}, // S_SORCBALL2_7 - {SPR_SBMB, 7, 2, A_SorcBallOrbit, S_SORCBALL2_9, 0, 0}, // S_SORCBALL2_8 - {SPR_SBMB, 8, 2, A_SorcBallOrbit, S_SORCBALL2_0, 0, 0}, // S_SORCBALL2_9 - {SPR_SBMB, 9, 2, A_SorcBallOrbit, S_SORCBALL2_A, 0, 0}, // S_SORCBALL2_0 - {SPR_SBMB, 10, 2, A_SorcBallOrbit, S_SORCBALL2_B, 0, 0}, // S_SORCBALL2_A - {SPR_SBMB, 11, 2, A_SorcBallOrbit, S_SORCBALL2_C, 0, 0}, // S_SORCBALL2_B - {SPR_SBMB, 12, 2, A_SorcBallOrbit, S_SORCBALL2_D, 0, 0}, // S_SORCBALL2_C - {SPR_SBMB, 13, 2, A_SorcBallOrbit, S_SORCBALL2_E, 0, 0}, // S_SORCBALL2_D - {SPR_SBMB, 14, 2, A_SorcBallOrbit, S_SORCBALL2_F, 0, 0}, // S_SORCBALL2_E - {SPR_SBMB, 15, 2, A_SorcBallOrbit, S_SORCBALL2_1, 0, 0}, // S_SORCBALL2_F - {SPR_SBMB, 0, 5, A_SorcBallPop, S_SORCBALL2_D2, 0, 0}, // S_SORCBALL2_D1 - {SPR_SBMB, 1, 2, A_BounceCheck, S_SORCBALL2_D2, 0, 0}, // S_SORCBALL2_D2 - {SPR_SBS3, 3, 5, A_Explode, S_SORCBALL2_D6, 0, 0}, // S_SORCBALL2_D5 - {SPR_SBS3, 4, 5, NULL, S_SORCBALL2_D7, 0, 0}, // S_SORCBALL2_D6 - {SPR_SBS3, 5, 6, NULL, S_SORCBALL2_D8, 0, 0}, // S_SORCBALL2_D7 - {SPR_SBS3, 6, 6, NULL, S_SORCBALL2_D9, 0, 0}, // S_SORCBALL2_D8 - {SPR_SBS3, 7, 6, NULL, S_NULL, 0, 0}, // S_SORCBALL2_D9 - {SPR_SBMG, 0, 2, A_SorcBallOrbit, S_SORCBALL3_2, 0, 0}, // S_SORCBALL3_1 - {SPR_SBMG, 1, 2, A_SorcBallOrbit, S_SORCBALL3_3, 0, 0}, // S_SORCBALL3_2 - {SPR_SBMG, 2, 2, A_SorcBallOrbit, S_SORCBALL3_4, 0, 0}, // S_SORCBALL3_3 - {SPR_SBMG, 3, 2, A_SorcBallOrbit, S_SORCBALL3_5, 0, 0}, // S_SORCBALL3_4 - {SPR_SBMG, 4, 2, A_SorcBallOrbit, S_SORCBALL3_6, 0, 0}, // S_SORCBALL3_5 - {SPR_SBMG, 5, 2, A_SorcBallOrbit, S_SORCBALL3_7, 0, 0}, // S_SORCBALL3_6 - {SPR_SBMG, 6, 2, A_SorcBallOrbit, S_SORCBALL3_8, 0, 0}, // S_SORCBALL3_7 - {SPR_SBMG, 7, 2, A_SorcBallOrbit, S_SORCBALL3_9, 0, 0}, // S_SORCBALL3_8 - {SPR_SBMG, 8, 2, A_SorcBallOrbit, S_SORCBALL3_0, 0, 0}, // S_SORCBALL3_9 - {SPR_SBMG, 9, 2, A_SorcBallOrbit, S_SORCBALL3_A, 0, 0}, // S_SORCBALL3_0 - {SPR_SBMG, 10, 2, A_SorcBallOrbit, S_SORCBALL3_B, 0, 0}, // S_SORCBALL3_A - {SPR_SBMG, 11, 2, A_SorcBallOrbit, S_SORCBALL3_C, 0, 0}, // S_SORCBALL3_B - {SPR_SBMG, 12, 2, A_SorcBallOrbit, S_SORCBALL3_D, 0, 0}, // S_SORCBALL3_C - {SPR_SBMG, 13, 2, A_SorcBallOrbit, S_SORCBALL3_E, 0, 0}, // S_SORCBALL3_D - {SPR_SBMG, 14, 2, A_SorcBallOrbit, S_SORCBALL3_F, 0, 0}, // S_SORCBALL3_E - {SPR_SBMG, 15, 2, A_SorcBallOrbit, S_SORCBALL3_1, 0, 0}, // S_SORCBALL3_F - {SPR_SBMG, 0, 5, A_SorcBallPop, S_SORCBALL3_D2, 0, 0}, // S_SORCBALL3_D1 - {SPR_SBMG, 1, 2, A_BounceCheck, S_SORCBALL3_D2, 0, 0}, // S_SORCBALL3_D2 - {SPR_SBS3, 3, 5, A_Explode, S_SORCBALL3_D6, 0, 0}, // S_SORCBALL3_D5 - {SPR_SBS3, 4, 5, NULL, S_SORCBALL3_D7, 0, 0}, // S_SORCBALL3_D6 - {SPR_SBS3, 5, 6, NULL, S_SORCBALL3_D8, 0, 0}, // S_SORCBALL3_D7 - {SPR_SBS3, 6, 6, NULL, S_SORCBALL3_D9, 0, 0}, // S_SORCBALL3_D8 - {SPR_SBS3, 7, 6, NULL, S_NULL, 0, 0}, // S_SORCBALL3_D9 - {SPR_SBS1, 32768, 2, NULL, S_SORCFX1_2, 0, 0}, // S_SORCFX1_1 - {SPR_SBS1, 32769, 3, A_SorcFX1Seek, S_SORCFX1_3, 0, 0}, // S_SORCFX1_2 - {SPR_SBS1, 32770, 3, A_SorcFX1Seek, S_SORCFX1_4, 0, 0}, // S_SORCFX1_3 - {SPR_SBS1, 32771, 3, A_SorcFX1Seek, S_SORCFX1_1, 0, 0}, // S_SORCFX1_4 - {SPR_FHFX, 32786, 2, A_Explode, S_SORCFX1_D2, 0, 0}, // S_SORCFX1_D1 - {SPR_FHFX, 32786, 6, NULL, S_SORCFX1_D3, 0, 0}, // S_SORCFX1_D2 - {SPR_FHFX, 32786, 6, NULL, S_NULL, 0, 0}, // S_SORCFX1_D3 - {SPR_SBS2, 32768, 3, A_SorcFX2Split, S_SORCFX2_SPLIT1, 0, 0}, // S_SORCFX2_SPLIT1 - {SPR_SBS2, 32768, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT2, 0, 0}, // S_SORCFX2_ORBIT1 - {SPR_SBS2, 32769, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT3, 0, 0}, // S_SORCFX2_ORBIT2 - {SPR_SBS2, 32770, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT4, 0, 0}, // S_SORCFX2_ORBIT3 - {SPR_SBS2, 32771, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT5, 0, 0}, // S_SORCFX2_ORBIT4 - {SPR_SBS2, 32772, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT6, 0, 0}, // S_SORCFX2_ORBIT5 - {SPR_SBS2, 32773, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT7, 0, 0}, // S_SORCFX2_ORBIT6 - {SPR_SBS2, 32774, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT8, 0, 0}, // S_SORCFX2_ORBIT7 - {SPR_SBS2, 32775, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT9, 0, 0}, // S_SORCFX2_ORBIT8 - {SPR_SBS2, 32776, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT0, 0, 0}, // S_SORCFX2_ORBIT9 - {SPR_SBS2, 32777, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITA, 0, 0}, // S_SORCFX2_ORBIT0 - {SPR_SBS2, 32778, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITB, 0, 0}, // S_SORCFX2_ORBITA - {SPR_SBS2, 32779, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITC, 0, 0}, // S_SORCFX2_ORBITB - {SPR_SBS2, 32780, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITD, 0, 0}, // S_SORCFX2_ORBITC - {SPR_SBS2, 32781, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITE, 0, 0}, // S_SORCFX2_ORBITD - {SPR_SBS2, 32782, 2, A_SorcFX2Orbit, S_SORCFX2_ORBITF, 0, 0}, // S_SORCFX2_ORBITE - {SPR_SBS2, 32783, 2, A_SorcFX2Orbit, S_SORCFX2_ORBIT1, 0, 0}, // S_SORCFX2_ORBITF - {SPR_SBS2, 0, 10, NULL, S_NULL, 0, 0}, // S_SORCFX2T1 - {SPR_SBS3, 32768, 2, NULL, S_SORCFX3_2, 0, 0}, // S_SORCFX3_1 - {SPR_SBS3, 32769, 2, NULL, S_SORCFX3_3, 0, 0}, // S_SORCFX3_2 - {SPR_SBS3, 32770, 2, NULL, S_SORCFX3_1, 0, 0}, // S_SORCFX3_3 - {SPR_SBS3, 32768, 4, NULL, S_BISHMORPHA, 0, 0}, // S_BISHMORPH1 - {SPR_BISH, 15, 4, A_SorcererBishopEntry, S_BISHMORPHB, 0, 0}, // S_BISHMORPHA - {SPR_BISH, 14, 4, NULL, S_BISHMORPHC, 0, 0}, // S_BISHMORPHB - {SPR_BISH, 13, 4, NULL, S_BISHMORPHD, 0, 0}, // S_BISHMORPHC - {SPR_BISH, 12, 3, NULL, S_BISHMORPHE, 0, 0}, // S_BISHMORPHD - {SPR_BISH, 11, 3, NULL, S_BISHMORPHF, 0, 0}, // S_BISHMORPHE - {SPR_BISH, 10, 3, NULL, S_BISHMORPHG, 0, 0}, // S_BISHMORPHF - {SPR_BISH, 9, 3, NULL, S_BISHMORPHH, 0, 0}, // S_BISHMORPHG - {SPR_BISH, 8, 3, NULL, S_BISHMORPHI, 0, 0}, // S_BISHMORPHH - {SPR_BISH, 7, 3, NULL, S_BISHMORPHJ, 0, 0}, // S_BISHMORPHI - {SPR_BISH, 6, 3, A_SpawnBishop, S_NULL, 0, 0}, // S_BISHMORPHJ - {SPR_SBS3, 3, 3, NULL, S_SORCFX3_EXP2, 0, 0}, // S_SORCFX3_EXP1 - {SPR_SBS3, 4, 3, NULL, S_SORCFX3_EXP3, 0, 0}, // S_SORCFX3_EXP2 - {SPR_SBS3, 5, 3, NULL, S_SORCFX3_EXP4, 0, 0}, // S_SORCFX3_EXP3 - {SPR_SBS3, 6, 3, NULL, S_SORCFX3_EXP5, 0, 0}, // S_SORCFX3_EXP4 - {SPR_SBS3, 7, 3, NULL, S_NULL, 0, 0}, // S_SORCFX3_EXP5 - {SPR_SBS4, 32768, 2, A_SorcFX4Check, S_SORCFX4_2, 0, 0}, // S_SORCFX4_1 - {SPR_SBS4, 32769, 2, A_SorcFX4Check, S_SORCFX4_3, 0, 0}, // S_SORCFX4_2 - {SPR_SBS4, 32770, 2, A_SorcFX4Check, S_SORCFX4_1, 0, 0}, // S_SORCFX4_3 - {SPR_SBS4, 32771, 2, NULL, S_SORCFX4_D2, 0, 0}, // S_SORCFX4_D1 - {SPR_SBS4, 32772, 2, A_Explode, S_SORCFX4_D3, 0, 0}, // S_SORCFX4_D2 - {SPR_SBS4, 32773, 2, NULL, S_SORCFX4_D4, 0, 0}, // S_SORCFX4_D3 - {SPR_SBS4, 32774, 2, NULL, S_SORCFX4_D5, 0, 0}, // S_SORCFX4_D4 - {SPR_SBS4, 32775, 2, NULL, S_NULL, 0, 0}, // S_SORCFX4_D5 - {SPR_SBFX, 32768, 4, NULL, S_SORCSPARK2, 0, 0}, // S_SORCSPARK1 - {SPR_SBFX, 32769, 4, NULL, S_SORCSPARK3, 0, 0}, // S_SORCSPARK2 - {SPR_SBFX, 32770, 4, NULL, S_SORCSPARK4, 0, 0}, // S_SORCSPARK3 - {SPR_SBFX, 32771, 4, NULL, S_SORCSPARK5, 0, 0}, // S_SORCSPARK4 - {SPR_SBFX, 32772, 4, NULL, S_SORCSPARK6, 0, 0}, // S_SORCSPARK5 - {SPR_SBFX, 32773, 4, NULL, S_SORCSPARK7, 0, 0}, // S_SORCSPARK6 - {SPR_SBFX, 32774, 4, NULL, S_NULL, 0, 0}, // S_SORCSPARK7 - {SPR_RADE, 0, 4, NULL, S_BLASTEFFECT2, 0, 0}, // S_BLASTEFFECT1 - {SPR_RADE, 1, 4, NULL, S_BLASTEFFECT3, 0, 0}, // S_BLASTEFFECT2 - {SPR_RADE, 2, 4, NULL, S_BLASTEFFECT4, 0, 0}, // S_BLASTEFFECT3 - {SPR_RADE, 3, 4, NULL, S_BLASTEFFECT5, 0, 0}, // S_BLASTEFFECT4 - {SPR_RADE, 4, 4, NULL, S_BLASTEFFECT6, 0, 0}, // S_BLASTEFFECT5 - {SPR_RADE, 5, 4, NULL, S_BLASTEFFECT7, 0, 0}, // S_BLASTEFFECT6 - {SPR_RADE, 6, 4, NULL, S_BLASTEFFECT8, 0, 0}, // S_BLASTEFFECT7 - {SPR_RADE, 7, 4, NULL, S_BLASTEFFECT9, 0, 0}, // S_BLASTEFFECT8 - {SPR_RADE, 8, 4, NULL, S_NULL, 0, 0}, // S_BLASTEFFECT9 - {SPR_WATR, 0, 5, NULL, S_WATERDRIP1, 0, 0}, // S_WATERDRIP1 - {SPR_KORX, 0, 5, A_Look, S_KORAX_LOOK1, 0, 0}, // S_KORAX_LOOK1 - {SPR_KORX, 0, 3, A_KoraxStep2, S_KORAX_CHASE2, 0, 0}, // S_KORAX_CHASE1 - {SPR_KORX, 0, 3, A_KoraxChase, S_KORAX_CHASE3, 0, 0}, // S_KORAX_CHASE2 - {SPR_KORX, 0, 3, A_KoraxChase, S_KORAX_CHASE4, 0, 0}, // S_KORAX_CHASE3 - {SPR_KORX, 0, 3, A_KoraxChase, S_KORAX_CHASE5, 0, 0}, // S_KORAX_CHASE4 - {SPR_KORX, 1, 3, A_KoraxStep, S_KORAX_CHASE6, 0, 0}, // S_KORAX_CHASE5 - {SPR_KORX, 1, 3, A_KoraxChase, S_KORAX_CHASE7, 0, 0}, // S_KORAX_CHASE6 - {SPR_KORX, 1, 3, A_KoraxChase, S_KORAX_CHASE8, 0, 0}, // S_KORAX_CHASE7 - {SPR_KORX, 1, 3, A_KoraxChase, S_KORAX_CHASE9, 0, 0}, // S_KORAX_CHASE8 - {SPR_KORX, 2, 3, A_KoraxStep2, S_KORAX_CHASE0, 0, 0}, // S_KORAX_CHASE9 - {SPR_KORX, 2, 3, A_KoraxChase, S_KORAX_CHASEA, 0, 0}, // S_KORAX_CHASE0 - {SPR_KORX, 2, 3, A_KoraxChase, S_KORAX_CHASEB, 0, 0}, // S_KORAX_CHASEA - {SPR_KORX, 2, 3, A_KoraxChase, S_KORAX_CHASEC, 0, 0}, // S_KORAX_CHASEB - {SPR_KORX, 3, 3, A_KoraxStep, S_KORAX_CHASED, 0, 0}, // S_KORAX_CHASEC - {SPR_KORX, 3, 3, A_KoraxChase, S_KORAX_CHASEE, 0, 0}, // S_KORAX_CHASED - {SPR_KORX, 3, 3, A_KoraxChase, S_KORAX_CHASEF, 0, 0}, // S_KORAX_CHASEE - {SPR_KORX, 3, 3, A_KoraxChase, S_KORAX_CHASE1, 0, 0}, // S_KORAX_CHASEF - {SPR_KORX, 7, 5, A_Pain, S_KORAX_PAIN2, 0, 0}, // S_KORAX_PAIN1 - {SPR_KORX, 7, 5, NULL, S_KORAX_CHASE2, 0, 0}, // S_KORAX_PAIN2 - {SPR_KORX, 32772, 2, A_FaceTarget, S_KORAX_ATTACK2, 0, 0}, // S_KORAX_ATTACK1 - {SPR_KORX, 32772, 5, A_KoraxDecide, S_KORAX_ATTACK2, 0, 0}, // S_KORAX_ATTACK2 - {SPR_KORX, 32772, 4, A_FaceTarget, S_KORAX_MISSILE2, 0, 0}, // S_KORAX_MISSILE1 - {SPR_KORX, 32773, 8, A_KoraxMissile, S_KORAX_MISSILE3, 0, 0}, // S_KORAX_MISSILE2 - {SPR_KORX, 32772, 8, NULL, S_KORAX_CHASE2, 0, 0}, // S_KORAX_MISSILE3 - {SPR_KORX, 32772, 5, A_FaceTarget, S_KORAX_COMMAND2, 0, 0}, // S_KORAX_COMMAND1 - {SPR_KORX, 32790, 10, A_FaceTarget, S_KORAX_COMMAND3, 0, 0}, // S_KORAX_COMMAND2 - {SPR_KORX, 32774, 15, A_KoraxCommand, S_KORAX_COMMAND4, 0, 0}, // S_KORAX_COMMAND3 - {SPR_KORX, 32790, 10, NULL, S_KORAX_COMMAND5, 0, 0}, // S_KORAX_COMMAND4 - {SPR_KORX, 32772, 5, NULL, S_KORAX_CHASE2, 0, 0}, // S_KORAX_COMMAND5 - {SPR_KORX, 8, 5, NULL, S_KORAX_DEATH2, 0, 0}, // S_KORAX_DEATH1 - {SPR_KORX, 9, 5, A_FaceTarget, S_KORAX_DEATH3, 0, 0}, // S_KORAX_DEATH2 - {SPR_KORX, 10, 5, A_Scream, S_KORAX_DEATH4, 0, 0}, // S_KORAX_DEATH3 - {SPR_KORX, 11, 5, NULL, S_KORAX_DEATH5, 0, 0}, // S_KORAX_DEATH4 - {SPR_KORX, 12, 5, NULL, S_KORAX_DEATH6, 0, 0}, // S_KORAX_DEATH5 - {SPR_KORX, 13, 5, NULL, S_KORAX_DEATH7, 0, 0}, // S_KORAX_DEATH6 - {SPR_KORX, 14, 5, NULL, S_KORAX_DEATH8, 0, 0}, // S_KORAX_DEATH7 - {SPR_KORX, 15, 5, NULL, S_KORAX_DEATH9, 0, 0}, // S_KORAX_DEATH8 - {SPR_KORX, 16, 10, NULL, S_KORAX_DEATH0, 0, 0}, // S_KORAX_DEATH9 - {SPR_KORX, 17, 5, A_KoraxBonePop, S_KORAX_DEATHA, 0, 0}, // S_KORAX_DEATH0 - {SPR_KORX, 18, 5, A_NoBlocking, S_KORAX_DEATHB, 0, 0}, // S_KORAX_DEATHA - {SPR_KORX, 19, 5, NULL, S_KORAX_DEATHC, 0, 0}, // S_KORAX_DEATHB - {SPR_KORX, 20, 5, NULL, S_KORAX_DEATHD, 0, 0}, // S_KORAX_DEATHC - {SPR_KORX, 21, -1, NULL, S_NULL, 0, 0}, // S_KORAX_DEATHD - {SPR_SPIR, 0, 5, A_KSpiritRoam, S_KSPIRIT_ROAM2, 0, 0}, // S_KSPIRIT_ROAM1 - {SPR_SPIR, 1, 5, A_KSpiritRoam, S_KSPIRIT_ROAM1, 0, 0}, // S_KSPIRIT_ROAM2 - {SPR_SPIR, 3, 5, NULL, S_KSPIRIT_DEATH2, 0, 0}, // S_KSPIRIT_DEATH1 - {SPR_SPIR, 4, 5, NULL, S_KSPIRIT_DEATH3, 0, 0}, // S_KSPIRIT_DEATH2 - {SPR_SPIR, 5, 5, NULL, S_KSPIRIT_DEATH4, 0, 0}, // S_KSPIRIT_DEATH3 - {SPR_SPIR, 6, 5, NULL, S_KSPIRIT_DEATH5, 0, 0}, // S_KSPIRIT_DEATH4 - {SPR_SPIR, 7, 5, NULL, S_KSPIRIT_DEATH6, 0, 0}, // S_KSPIRIT_DEATH5 - {SPR_SPIR, 8, 5, NULL, S_NULL, 0, 0}, // S_KSPIRIT_DEATH6 - {SPR_MLFX, 32776, 2, NULL, S_KBOLT2, 0, 0}, // S_KBOLT1 - {SPR_MLFX, 32777, 2, A_KBoltRaise, S_KBOLT3, 0, 0}, // S_KBOLT2 - {SPR_MLFX, 32776, 2, A_KBolt, S_KBOLT4, 0, 0}, // S_KBOLT3 - {SPR_MLFX, 32777, 2, A_KBolt, S_KBOLT5, 0, 0}, // S_KBOLT4 - {SPR_MLFX, 32778, 2, A_KBolt, S_KBOLT6, 0, 0}, // S_KBOLT5 - {SPR_MLFX, 32779, 2, A_KBolt, S_KBOLT7, 0, 0}, // S_KBOLT6 - {SPR_MLFX, 32780, 2, A_KBolt, S_KBOLT3, 0, 0}, // S_KBOLT7 - {SPR_MAN1, 0, 2, NULL, S_SPAWNBATS2, 0, 0}, // S_SPAWNBATS1 - {SPR_MAN1, 0, 2, A_BatSpawnInit, S_SPAWNBATS3, 0, 0}, // S_SPAWNBATS2 - {SPR_MAN1, 0, 2, A_BatSpawn, S_SPAWNBATS3, 0, 0}, // S_SPAWNBATS3 - {SPR_MAN1, 0, -1, NULL, S_NULL, 0, 0}, // S_SPAWNBATS_OFF - {SPR_ABAT, 0, 2, A_BatMove, S_BAT2, 0, 0}, // S_BAT1 - {SPR_ABAT, 1, 2, A_BatMove, S_BAT3, 0, 0}, // S_BAT2 - {SPR_ABAT, 2, 2, A_BatMove, S_BAT1, 0, 0}, // S_BAT3 - {SPR_ABAT, 0, 2, NULL, S_NULL, 0, 0} // S_BAT_DEATH -}; - - -mobjinfo_t mobjinfo[NUMMOBJTYPES] = { - - { // MT_MAPSPOT - 9001, // doomednum - S_MAPSPOT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MAPSPOTGRAVITY - 9013, // doomednum - S_MAPSPOT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - MF2_DONTDRAW // flags2 - }, - - { // MT_FIREBALL1 - -1, // doomednum - S_FIREBALL1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIREBALL1_X1, // deathstate - S_NULL, // xdeathstate - SFX_FIREBALL, // deathsound - 2 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_ARROW - -1, // doomednum - S_ARROW_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ARROW_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 6 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DART - -1, // doomednum - S_DART_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DART_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 6 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 2, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_POISONDART - -1, // doomednum - S_POISONDART_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_POISONDART_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 6 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 2, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_RIPPERBALL - -1, // doomednum - S_RIPPERBALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_RIPPERBALL_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 6 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 2, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_RIP // flags2 - }, - - { // MT_PROJECTILE_BLADE - -1, // doomednum - S_PRJ_BLADE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_PRJ_BLADE_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 6 * FRACUNIT, // speed - 6 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 3, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ICESHARD - -1, // doomednum - S_ICESHARD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SHARDFXE1_1, // deathstate - S_NULL, // xdeathstate - SFX_MAGE_SHARDS_EXPLODE, // deathsound - 25 * FRACUNIT, // speed - 13 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_ICEDAMAGE // flags2 - }, - - { // MT_FLAME_SMALL_TEMP - 10500, // doomednum - S_FLAME_TSMALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FLAME_LARGE_TEMP - 10502, // doomednum - S_FLAME_TLARGE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FLAME_SMALL - 10501, // doomednum - S_FLAME_SMALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - MF2_NOTELEPORT | MF2_DONTDRAW // flags2 - }, - - { // MT_FLAME_LARGE - 10503, // doomednum - S_FLAME_LARGE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - MF2_NOTELEPORT | MF2_DONTDRAW // flags2 - }, - - { // MT_HEALINGBOTTLE - 81, // doomednum - S_ITEM_PTN1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_HEALTHFLASK - 82, // doomednum - S_ARTI_PTN2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIFLY - 83, // doomednum - S_ARTI_SOAR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIINVULNERABILITY - 84, // doomednum - S_ARTI_INVU1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_SUMMONMAULATOR - 86, // doomednum - S_ARTI_SUMMON, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_SUMMON_FX - -1, // doomednum - S_SUMMON_FX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SUMMON_FX2_1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 20 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_DROPOFF | MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_THRUSTFLOOR_UP - 10091, // doomednum - S_THRUSTINIT2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 128 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_THRUSTFLOOR_DOWN - 10090, // doomednum - S_THRUSTINIT1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 128 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP | MF2_DONTDRAW // flags2 - }, - - { // MT_TELEPORTOTHER - 10040, // doomednum - S_ARTI_TELOTHER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_TELOTHER_FX1 - -1, // doomednum - S_TELO_FX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_TELO_FX9, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 20 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 10001, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_TELOTHER_FX2 - -1, // doomednum - S_TELO_FX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_TELO_FX9, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 16 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 10001, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_TELOTHER_FX3 - -1, // doomednum - S_TELO_FX3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_TELO_FX9, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 16 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 10001, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_TELOTHER_FX4 - -1, // doomednum - S_TELO_FX4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_TELO_FX9, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 16 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 10001, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_TELOTHER_FX5 - -1, // doomednum - S_TELO_FX5_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_TELO_FX9, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 16 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 10001, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY | MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DIRT1 - -1, // doomednum - S_DIRT1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DIRT1_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DIRT2 - -1, // doomednum - S_DIRT2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DIRT2_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DIRT3 - -1, // doomednum - S_DIRT3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DIRT3_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DIRT4 - -1, // doomednum - S_DIRT4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DIRT4_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_DIRT5 - -1, // doomednum - S_DIRT5_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DIRT5_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_DIRT6 - -1, // doomednum - S_DIRT6_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DIRT6_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_DIRTCLUMP - -1, // doomednum - S_DIRTCLUMP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ROCK1 - -1, // doomednum - S_ROCK1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ROCK1_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ROCK2 - -1, // doomednum - S_ROCK2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ROCK2_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ROCK3 - -1, // doomednum - S_ROCK3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ROCK3_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FOGSPAWNER - 10000, // doomednum - S_SPAWNFOG1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - MF2_DONTDRAW | MF2_FLOATBOB // flags2 - }, - - { // MT_FOGPATCHS - 10001, // doomednum - S_FOGPATCHS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FOGPATCHS0, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_FLOAT | MF_NOGRAVITY | MF_SHADOW | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FOGPATCHM - 10002, // doomednum - S_FOGPATCHM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FOGPATCHM0, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_FLOAT | MF_NOGRAVITY | MF_SHADOW | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FOGPATCHL - 10003, // doomednum - S_FOGPATCHL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FOGPATCHL0, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_FLOAT | MF_NOGRAVITY | MF_SHADOW | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_QUAKE_FOCUS - -1, // doomednum - S_QUAKE_ACTIVE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - MF2_DONTDRAW // flags2 - }, - - { // MT_SGSHARD1 - -1, // doomednum - S_SGSHARD1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD1_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD2 - -1, // doomednum - S_SGSHARD2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD2_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD3 - -1, // doomednum - S_SGSHARD3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD3_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD4 - -1, // doomednum - S_SGSHARD4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD4_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD5 - -1, // doomednum - S_SGSHARD5_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD5_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD6 - -1, // doomednum - S_SGSHARD6_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD6_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD7 - -1, // doomednum - S_SGSHARD7_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD7_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD8 - -1, // doomednum - S_SGSHARD8_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD8_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD9 - -1, // doomednum - S_SGSHARD9_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD9_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SGSHARD0 - -1, // doomednum - S_SGSHARD0_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SGSHARD0_D, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_ARTIEGG - 30, // doomednum - S_ARTI_EGGC1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_EGGFX - -1, // doomednum - S_EGGFX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_EGGFXI1_1, // deathstate - S_NULL, // xdeathstate - 0, // deathsound - 18 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ARTISUPERHEAL - 32, // doomednum - S_ARTI_SPHL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ZWINGEDSTATUENOSKULL - 9011, // doomednum - S_ZWINGEDSTATUENOSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZGEMPEDESTAL - 9012, // doomednum - S_ZGEMPEDESTAL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 40 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZSKULL - 9002, // doomednum - S_ARTIPUZZSKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEMBIG - 9003, // doomednum - S_ARTIPUZZGEMBIG, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEMRED - 9004, // doomednum - S_ARTIPUZZGEMRED, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEMGREEN1 - 9005, // doomednum - S_ARTIPUZZGEMGREEN1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEMGREEN2 - 9009, // doomednum - S_ARTIPUZZGEMGREEN2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEMBLUE1 - 9006, // doomednum - S_ARTIPUZZGEMBLUE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEMBLUE2 - 9010, // doomednum - S_ARTIPUZZGEMBLUE2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZBOOK1 - 9007, // doomednum - S_ARTIPUZZBOOK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZBOOK2 - 9008, // doomednum - S_ARTIPUZZBOOK2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZSKULL2 - 9014, // doomednum - S_ARTIPUZZSKULL2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZFWEAPON - 9015, // doomednum - S_ARTIPUZZFWEAPON, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZCWEAPON - 9016, // doomednum - S_ARTIPUZZCWEAPON, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZMWEAPON - 9017, // doomednum - S_ARTIPUZZMWEAPON, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEAR - 9018, // doomednum - S_ARTIPUZZGEAR_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEAR2 - 9019, // doomednum - S_ARTIPUZZGEAR2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEAR3 - 9020, // doomednum - S_ARTIPUZZGEAR3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTIPUZZGEAR4 - 9021, // doomednum - S_ARTIPUZZGEAR4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARTITORCH - 33, // doomednum - S_ARTI_TRCH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_FIREBOMB - -1, // doomednum - S_FIREBOMB1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_FLECHETTE_EXPLODE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOGRAVITY | MF_ALTSHADOW, // flags - MF2_FIREDAMAGE // flags2 - }, - - { // MT_ARTITELEPORT - 36, // doomednum - S_ARTI_ATLP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_ARTIPOISONBAG - 8000, // doomednum - S_ARTI_PSBG1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_POISONBAG - -1, // doomednum - S_POISONBAG1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOGRAVITY | MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_POISONCLOUD - -1, // doomednum - S_POISONCLOUD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_POISONSHROOM_DEATH, // deathsound - 0, // speed - 1, // radius - 1, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOGRAVITY | MF_NOBLOCKMAP | MF_SHADOW | MF_NOCLIP | MF_DROPOFF, // flags - MF2_NODMGTHRUST // flags2 - }, - - { // MT_THROWINGBOMB - -1, // doomednum - S_THROWINGBOMB1, // spawnstate - 48, // spawnhealth - S_NULL, // seestate - SFX_FLECHETTE_BOUNCE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_THROWINGBOMB_X1, // deathstate - S_NULL, // xdeathstate - SFX_FLECHETTE_EXPLODE, // deathsound - 12 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_FLOORBOUNCE | MF2_FIREDAMAGE // flags2 - }, - - { // MT_SPEEDBOOTS - 8002, // doomednum - S_ARTI_BOOTS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_BOOSTMANA - 8003, // doomednum - S_ARTI_MANA, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_BOOSTARMOR - 8041, // doomednum - S_ARTI_ARMOR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_BLASTRADIUS - 10110, // doomednum - S_ARTI_BLAST1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_HEALRADIUS - 10120, // doomednum - S_ARTI_HEALRAD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_SPLASH - -1, // doomednum - S_SPLASH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SPLASHX, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_SPLASHBASE - -1, // doomednum - S_SPLASHBASE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_LAVASPLASH - -1, // doomednum - S_LAVASPLASH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_LAVASMOKE - -1, // doomednum - S_LAVASMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_SLUDGECHUNK - -1, // doomednum - S_SLUDGECHUNK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SLUDGECHUNKX, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_SLUDGESPLASH - -1, // doomednum - S_SLUDGESPLASH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_MISC0 - 5, // doomednum - S_ZWINGEDSTATUE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC1 - 6, // doomednum - S_ZROCK1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC2 - 7, // doomednum - S_ZROCK2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC3 - 9, // doomednum - S_ZROCK3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC4 - 15, // doomednum - S_ZROCK4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC5 - 17, // doomednum - S_ZCHANDELIER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 60 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC6 - 8063, // doomednum - S_ZCHANDELIER_U, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 60 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC7 - 24, // doomednum - S_ZTREEDEAD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 96 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC8 - 25, // doomednum - S_ZTREE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 128 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_TREEDESTRUCTIBLE - 8062, // doomednum - S_ZTREEDESTRUCTIBLE1, // spawnstate - 70, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZTREEDES_D1, // deathstate - S_NULL, // xdeathstate - SFX_TREE_BREAK, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 180 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_MISC9 - 26, // doomednum - S_ZTREESWAMP182_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 150 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC10 - 27, // doomednum - S_ZTREESWAMP172_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 120 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC11 - 28, // doomednum - S_ZSTUMPBURNED1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC12 - 29, // doomednum - S_ZSTUMPBARE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC13 - 37, // doomednum - S_ZSTUMPSWAMP1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC14 - 38, // doomednum - S_ZSTUMPSWAMP2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC15 - 39, // doomednum - S_ZSHROOMLARGE1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC16 - 40, // doomednum - S_ZSHROOMLARGE2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC17 - 41, // doomednum - S_ZSHROOMLARGE3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC18 - 42, // doomednum - S_ZSHROOMSMALL1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC19 - 44, // doomednum - S_ZSHROOMSMALL2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC20 - 45, // doomednum - S_ZSHROOMSMALL3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC21 - 46, // doomednum - S_ZSHROOMSMALL4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC22 - 47, // doomednum - S_ZSHROOMSMALL5_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC23 - 48, // doomednum - S_ZSTALAGMITEPILLAR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 138 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC24 - 49, // doomednum - S_ZSTALAGMITELARGE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 48 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC25 - 50, // doomednum - S_ZSTALAGMITEMEDIUM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 6 * FRACUNIT, // radius - 40 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC26 - 51, // doomednum - S_ZSTALAGMITESMALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 36 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC27 - 52, // doomednum - S_ZSTALACTITELARGE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 66 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC28 - 56, // doomednum - S_ZSTALACTITEMEDIUM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 6 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC29 - 57, // doomednum - S_ZSTALACTITESMALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 40 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC30 - 58, // doomednum - S_ZMOSSCEILING1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC31 - 59, // doomednum - S_ZMOSSCEILING2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 24 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC32 - 60, // doomednum - S_ZSWAMPVINE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 52 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC33 - 61, // doomednum - S_ZCORPSEKABOB1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 92 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC34 - 62, // doomednum - S_ZCORPSESLEEPING1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC35 - 63, // doomednum - S_ZTOMBSTONERIP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 46 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC36 - 64, // doomednum - S_ZTOMBSTONESHANE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 46 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC37 - 65, // doomednum - S_ZTOMBSTONEBIGCROSS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 46 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC38 - 66, // doomednum - S_ZTOMBSTONEBRIANR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 52 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC39 - 67, // doomednum - S_ZTOMBSTONECROSSCIRCLE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 52 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC40 - 68, // doomednum - S_ZTOMBSTONESMALLCROSS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 46 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC41 - 69, // doomednum - S_ZTOMBSTONEBRIANP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 46 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC42 - 71, // doomednum - S_CORPSEHANGING_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 6 * FRACUNIT, // radius - 75 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC43 - 72, // doomednum - S_ZSTATUEGARGOYLEGREENTALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC44 - 73, // doomednum - S_ZSTATUEGARGOYLEBLUETALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC45 - 74, // doomednum - S_ZSTATUEGARGOYLEGREENSHORT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC46 - 76, // doomednum - S_ZSTATUEGARGOYLEBLUESHORT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC47 - 8044, // doomednum - S_ZSTATUEGARGOYLESTRIPETALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC48 - 8045, // doomednum - S_ZSTATUEGARGOYLEDARKREDTALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC49 - 8046, // doomednum - S_ZSTATUEGARGOYLEREDTALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC50 - 8047, // doomednum - S_ZSTATUEGARGOYLETANTALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC51 - 8048, // doomednum - S_ZSTATUEGARGOYLERUSTTALL_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 108 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC52 - 8049, // doomednum - S_ZSTATUEGARGOYLEDARKREDSHORT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC53 - 8050, // doomednum - S_ZSTATUEGARGOYLEREDSHORT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC54 - 8051, // doomednum - S_ZSTATUEGARGOYLETANSHORT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC55 - 8052, // doomednum - S_ZSTATUEGARGOYLERUSTSHORT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 14 * FRACUNIT, // radius - 62 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC56 - 77, // doomednum - S_ZBANNERTATTERED_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 120 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC57 - 78, // doomednum - S_ZTREELARGE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZTREELARGE1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 180 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC58 - 79, // doomednum - S_ZTREELARGE2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZTREELARGE2, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 180 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC59 - 80, // doomednum - S_ZTREEGNARLED1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 22 * FRACUNIT, // radius - 100 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC60 - 87, // doomednum - S_ZTREEGNARLED2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 22 * FRACUNIT, // radius - 100 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC61 - 88, // doomednum - S_ZLOG, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 25 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC62 - 89, // doomednum - S_ZSTALACTITEICELARGE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 66 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC63 - 90, // doomednum - S_ZSTALACTITEICEMEDIUM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC64 - 91, // doomednum - S_ZSTALACTITEICESMALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC65 - 92, // doomednum - S_ZSTALACTITEICETINY, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC66 - 93, // doomednum - S_ZSTALAGMITEICELARGE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 66 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC67 - 94, // doomednum - S_ZSTALAGMITEICEMEDIUM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC68 - 95, // doomednum - S_ZSTALAGMITEICESMALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC69 - 96, // doomednum - S_ZSTALAGMITEICETINY, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC70 - 97, // doomednum - S_ZROCKBROWN1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 17 * FRACUNIT, // radius - 72 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC71 - 98, // doomednum - S_ZROCKBROWN2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 50 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC72 - 99, // doomednum - S_ZROCKBLACK, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 40 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_MISC73 - 100, // doomednum - S_ZRUBBLE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC74 - 101, // doomednum - S_ZRUBBLE2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC75 - 102, // doomednum - S_ZRUBBLE3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_MISC76 - 103, // doomednum - S_ZVASEPILLAR, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 54 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_POTTERY1 - 104, // doomednum - S_ZPOTTERY1, // spawnstate - 15, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZPOTTERY_EXPLODE, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_DROPOFF, // flags - MF2_SLIDE | MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ // flags2 - }, - - { // MT_POTTERY2 - 105, // doomednum - S_ZPOTTERY2, // spawnstate - 15, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZPOTTERY_EXPLODE, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 25 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_DROPOFF, // flags - MF2_SLIDE | MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ // flags2 - }, - - { // MT_POTTERY3 - 106, // doomednum - S_ZPOTTERY3, // spawnstate - 15, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZPOTTERY_EXPLODE, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 25 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_DROPOFF, // flags - MF2_SLIDE | MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ // flags2 - }, - - { // MT_POTTERYBIT1 - -1, // doomednum - S_POTTERYBIT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_POTTERYBIT_EX0, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_MISC77 - 108, // doomednum - S_ZCORPSELYNCHED1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 11 * FRACUNIT, // radius - 95 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ZLYNCHED_NOHEART - 109, // doomednum - S_ZCORPSELYNCHED2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 100 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC78 - 110, // doomednum - S_ZCORPSESITTING, // spawnstate - 30, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZCORPSESITTING_X, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 35 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_CORPSEBIT - -1, // doomednum - S_CORPSEBIT_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - MF2_TELESTOMP // flags2 - }, - - { // MT_CORPSEBLOODDRIP - -1, // doomednum - S_CORPSEBLOODDRIP, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CORPSEBLOODDRIP_X1, // deathstate - S_NULL, // xdeathstate - SFX_DRIP, // deathsound - 0, // speed - FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_MISSILE, // flags - MF2_LOGRAV // flags2 - }, - - { // MT_BLOODPOOL - 111, // doomednum - S_BLOODPOOL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_MISC79 - 119, // doomednum - S_ZCANDLE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC80 - 113, // doomednum - S_ZLEAFSPAWNER, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - MF2_DONTDRAW // flags2 - }, - - { // MT_LEAF1 - -1, // doomednum - S_LEAF1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_LEAF_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_LEAF2 - -1, // doomednum - S_LEAF2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_LEAF_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_ZTWINEDTORCH - 116, // doomednum - S_ZTWINEDTORCH_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZTWINEDTORCH_UNLIT - 117, // doomednum - S_ZTWINEDTORCH_UNLIT, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 10 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_BRIDGE - 118, // doomednum - S_BRIDGE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 32 * FRACUNIT, // radius - 2 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_NOGRAVITY, // flags - MF2_DONTDRAW // flags2 - }, - - { // MT_BRIDGEBALL - -1, // doomednum - S_BBALL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ZWALLTORCH - 54, // doomednum - S_ZWALLTORCH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ZWALLTORCH_UNLIT - 55, // doomednum - S_ZWALLTORCH_U, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ZBARREL - 8100, // doomednum - S_ZBARREL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZSHRUB1 - 8101, // doomednum - S_ZSHRUB1, // spawnstate - 20, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_ZSHRUB1_X1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZSHRUB1_DIE, // deathstate - S_NULL, // xdeathstate - SFX_TREE_EXPLODE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 24 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_ZSHRUB2 - 8102, // doomednum - S_ZSHRUB2, // spawnstate - 10, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_ZSHRUB2_X1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZSHRUB2_DIE, // deathstate - S_NULL, // xdeathstate - SFX_TREE_EXPLODE, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 40 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_ZBUCKET - 8103, // doomednum - S_ZBUCKET1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 72 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SPAWNCEILING | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ZPOISONSHROOM - 8104, // doomednum - S_ZPOISONSHROOM1, // spawnstate - 30, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_ZPOISONSHROOM_P1, // painstate - 255, // painchance - SFX_POISONSHROOM_PAIN, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZPOISONSHROOM_X1, // deathstate - S_NULL, // xdeathstate - SFX_POISONSHROOM_DEATH, // deathsound - 0, // speed - 6 * FRACUNIT, // radius - 20 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SHOOTABLE | MF_SOLID | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_ZFIREBULL - 8042, // doomednum - S_ZFIREBULL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 80 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZFIREBULL_UNLIT - 8043, // doomednum - S_ZFIREBULL_U, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 80 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_FIRETHING - 8060, // doomednum - S_ZFIRETHING1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_BRASSTORCH - 8061, // doomednum - S_ZBRASSTORCH1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 6 * FRACUNIT, // radius - 35 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZSUITOFARMOR - 8064, // doomednum - S_ZSUITOFARMOR, // spawnstate - 60, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZSUITOFARMOR_X1, // deathstate - S_NULL, // xdeathstate - SFX_SUITOFARMOR_BREAK, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 72 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_ZARMORCHUNK - -1, // doomednum - S_ZARMORCHUNK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - 0, // flags - 0 // flags2 - }, - - { // MT_ZBELL - 8065, // doomednum - S_ZBELL, // spawnstate - 5, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZBELL_X1, // deathstate - S_NULL, // xdeathstate - SFX_BELLRING, // deathsound - 0, // speed - 56 * FRACUNIT, // radius - 120 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZBLUE_CANDLE - 8066, // doomednum - S_ZBLUE_CANDLE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_ZIRON_MAIDEN - 8067, // doomednum - S_ZIRON_MAIDEN, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 60 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZXMAS_TREE - 8068, // doomednum - S_ZXMAS_TREE, // spawnstate - 20, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_ZXMAS_TREE_X1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ZXMAS_TREE_DIE, // deathstate - S_NULL, // xdeathstate - SFX_TREE_EXPLODE, // deathsound - 0, // speed - 11 * FRACUNIT, // radius - 130 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD, // flags - 0 // flags2 - }, - - { // MT_ZCAULDRON - 8069, // doomednum - S_ZCAULDRON1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 26 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZCAULDRON_UNLIT - 8070, // doomednum - S_ZCAULDRON_U, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 12 * FRACUNIT, // radius - 26 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID, // flags - 0 // flags2 - }, - - { // MT_ZCHAINBIT32 - 8071, // doomednum - S_ZCHAINBIT32, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZCHAINBIT64 - 8072, // doomednum - S_ZCHAINBIT64, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZCHAINEND_HEART - 8073, // doomednum - S_ZCHAINEND_HEART, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZCHAINEND_HOOK1 - 8074, // doomednum - S_ZCHAINEND_HOOK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZCHAINEND_HOOK2 - 8075, // doomednum - S_ZCHAINEND_HOOK2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZCHAINEND_SPIKE - 8076, // doomednum - S_ZCHAINEND_SPIKE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_ZCHAINEND_SKULL - 8077, // doomednum - S_ZCHAINEND_SKULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 32 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SPAWNCEILING, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT1 - 8500, // doomednum - S_TABLE_SHIT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT2 - 8501, // doomednum - S_TABLE_SHIT2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT3 - 8502, // doomednum - S_TABLE_SHIT3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT4 - 8503, // doomednum - S_TABLE_SHIT4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT5 - 8504, // doomednum - S_TABLE_SHIT5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT6 - 8505, // doomednum - S_TABLE_SHIT6, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT7 - 8506, // doomednum - S_TABLE_SHIT7, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT8 - 8507, // doomednum - S_TABLE_SHIT8, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT9 - 8508, // doomednum - S_TABLE_SHIT9, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TABLE_SHIT10 - 8509, // doomednum - S_TABLE_SHIT10, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_TFOG - -1, // doomednum - S_TFOG1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MISC81 - 140, // doomednum - S_TELESMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_TELEPORTMAN - 14, // doomednum - S_NULL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_PUNCHPUFF - -1, // doomednum - S_PUNCHPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_FIGHTER_PUNCH_HITTHING, // seesound - 8, // reactiontime - SFX_FIGHTER_PUNCH_HITWALL, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_FW_AXE - 8010, // doomednum - S_AXE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_AXEPUFF - -1, // doomednum - S_HAMMERPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_FIGHTER_AXE_HITTHING, // seesound - 8, // reactiontime - SFX_FIGHTER_HAMMER_HITWALL, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_AXEPUFF_GLOW - -1, // doomednum - S_AXEPUFF_GLOW1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_FIGHTER_AXE_HITTHING, // seesound - 8, // reactiontime - SFX_FIGHTER_HAMMER_HITWALL, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_AXEBLOOD - -1, // doomednum - S_AXEBLOOD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_AXEBLOOD6, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 - }, - - { // MT_FW_HAMMER - 123, // doomednum - S_HAMM, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_HAMMER_MISSILE - -1, // doomednum - S_HAMMER_MISSILE_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HAMMER_MISSILE_X1, // deathstate - S_NULL, // xdeathstate - SFX_FIGHTER_HAMMER_EXPLODE, // deathsound - 25 * FRACUNIT, // speed - 14 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 10, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FIREDAMAGE // flags2 - }, - - { // MT_HAMMERPUFF - -1, // doomednum - S_HAMMERPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_FIGHTER_HAMMER_HITTHING, // seesound - 8, // reactiontime - SFX_FIGHTER_HAMMER_HITWALL, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_FSWORD_MISSILE - -1, // doomednum - S_FSWORD_MISSILE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FSWORD_MISSILE_X1, // deathstate - S_NULL, // xdeathstate - SFX_FIGHTER_SWORD_EXPLODE, // deathsound - 30 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 8, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_FSWORD_FLAME - -1, // doomednum - S_FSWORD_FLAME1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_CW_SERPSTAFF - 10, // doomednum - S_CSTAFF, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_CSTAFF_MISSILE - -1, // doomednum - S_CSTAFF_MISSILE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CSTAFF_MISSILE_X1, // deathstate - S_NULL, // xdeathstate - SFX_CLERIC_CSTAFF_EXPLODE, // deathsound - 22 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 5, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_CSTAFFPUFF - -1, // doomednum - S_CSTAFFPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_CLERIC_CSTAFF_HITTHING, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_CW_FLAME - 8009, // doomednum - S_CFLAME1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_CFLAMEFLOOR - -1, // doomednum - S_CFLAMEFLOOR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_FLAMEPUFF - -1, // doomednum - S_FLAMEPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_CLERIC_FLAME_EXPLODE, // seesound - 8, // reactiontime - SFX_CLERIC_FLAME_EXPLODE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - FRACUNIT, // radius - FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_FLAMEPUFF2 - -1, // doomednum - S_FLAMEPUFF2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_CLERIC_FLAME_EXPLODE, // seesound - 8, // reactiontime - SFX_CLERIC_FLAME_EXPLODE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - FRACUNIT, // radius - FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_CIRCLEFLAME - -1, // doomednum - S_CIRCLE_FLAME1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CIRCLE_FLAME_X1, // deathstate - S_NULL, // xdeathstate - SFX_CLERIC_FLAME_CIRCLE, // deathsound - 0, // speed - 6 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 2, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_CFLAME_MISSILE - -1, // doomednum - S_CFLAME_MISSILE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CFLAME_MISSILE_X, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 200 * FRACUNIT, // speed - 14 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 8, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_DONTDRAW | MF2_FIREDAMAGE // flags2 - }, - - { // MT_HOLY_FX - -1, // doomednum - S_HOLY_FX1, // spawnstate - 105, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HOLY_FX_X1, // deathstate - S_NULL, // xdeathstate - SFX_SPIRIT_DIE, // deathsound - 12 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 3, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_SEEKERMISSILE | MF2_RIP | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_HOLY_TAIL - -1, // doomednum - S_HOLY_TAIL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - FRACUNIT, // radius - FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_NOCLIP | MF_ALTSHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_HOLY_PUFF - -1, // doomednum - S_HOLY_PUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_HOLY_MISSILE - -1, // doomednum - S_HOLY_MISSILE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_HOLY_MISSILE_X, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 30 * FRACUNIT, // speed - 15 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_HOLY_MISSILE_PUFF - -1, // doomednum - S_HOLY_MISSILE_P1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_MWANDPUFF - -1, // doomednum - S_MWANDPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH | MF2_NODMGTHRUST // flags2 - }, - - { // MT_MWANDSMOKE - -1, // doomednum - S_MWANDSMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH | MF2_NODMGTHRUST // flags2 - }, - - { // MT_MWAND_MISSILE - -1, // doomednum - S_MWAND_MISSILE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MWANDPUFF1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 184 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 2, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_RIP | MF2_IMPACT | MF2_PCROSS | MF2_NODMGTHRUST | MF2_CANNOTPUSH // flags2 - }, - - { // MT_MW_LIGHTNING - 8040, // doomednum - S_MW_LIGHTNING1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_LIGHTNING_CEILING - -1, // doomednum - S_LIGHTNING_CEILING1, // spawnstate - 144, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_LIGHTNING_C_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 25 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 40 * FRACUNIT, // height - 100, // mass - 8, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_LIGHTNING_FLOOR - -1, // doomednum - S_LIGHTNING_FLOOR1, // spawnstate - 144, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_LIGHTNING_F_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 25 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 40 * FRACUNIT, // height - 100, // mass - 8, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_LIGHTNING_ZAP - -1, // doomednum - S_LIGHTNING_ZAP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_LIGHTNING_ZAP_X8, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 35 * FRACUNIT, // height - 100, // mass - 2, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags - 0 // flags2 - }, - - { // MT_MSTAFF_FX - -1, // doomednum - S_MSTAFF_FX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MSTAFF_FX_X1, // deathstate - S_NULL, // xdeathstate - SFX_MAGE_STAFF_EXPLODE, // deathsound - 20 * FRACUNIT, // speed - 16 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 6, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE | MF2_RIP | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_MSTAFF_FX2 - -1, // doomednum - S_MSTAFF_FX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MSTAFF_FX2_X1, // deathstate - S_NULL, // xdeathstate - SFX_MAGE_STAFF_EXPLODE, // deathsound - 17 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE | MF2_IMPACT | MF2_PCROSS | MF2_SEEKERMISSILE // flags2 - }, - - { // MT_FW_SWORD1 - 12, // doomednum - S_FSWORD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_FW_SWORD2 - 13, // doomednum - S_FSWORD2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_FW_SWORD3 - 16, // doomednum - S_FSWORD3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_CW_HOLY1 - 18, // doomednum - S_CHOLY1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_CW_HOLY2 - 19, // doomednum - S_CHOLY2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_CW_HOLY3 - 20, // doomednum - S_CHOLY3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MW_STAFF1 - 21, // doomednum - S_MSTAFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MW_STAFF2 - 22, // doomednum - S_MSTAFF2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MW_STAFF3 - 23, // doomednum - S_MSTAFF3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_SNOUTPUFF - -1, // doomednum - S_PUNCHPUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_MW_CONE - 53, // doomednum - S_COS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_SHARDFX1 - -1, // doomednum - S_SHARDFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SHARDFXE1_1, // deathstate - S_NULL, // xdeathstate - SFX_MAGE_SHARDS_EXPLODE, // deathsound - 25 * FRACUNIT, // speed - 13 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_ICEDAMAGE // flags2 - }, - - { // MT_BLOOD - -1, // doomednum - S_BLOOD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - 0 // flags2 - }, - - { // MT_BLOODSPLATTER - -1, // doomednum - S_BLOODSPLATTER1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BLOODSPLATTERX, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_CANNOTPUSH // flags2 - }, - - { // MT_GIBS - -1, // doomednum - S_GIBS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_PLAYER_FIGHTER - -1, // doomednum - S_FPLAY, // spawnstate - 100, // spawnhealth - S_FPLAY_RUN1, // seestate - SFX_NONE, // seesound - 0, // reactiontime - SFX_NONE, // attacksound - S_FPLAY_PAIN, // painstate - 255, // painchance - SFX_PLAYER_FIGHTER_PAIN, // painsound - S_NULL, // meleestate - S_FPLAY_ATK1, // missilestate - S_NULL, // crashstate - S_FPLAY_DIE1, // deathstate - S_FPLAY_XDIE1, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags - MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL // flags2 - }, - - { // MT_BLOODYSKULL - -1, // doomednum - S_BLOODYSKULL1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 4 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_CANNOTPUSH // flags2 - }, - - { // MT_PLAYER_SPEED - -1, // doomednum - S_PLAYER_SPEED1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_ALTSHADOW, // flags - 0 // flags2 - }, - - { // MT_ICECHUNK - -1, // doomednum - S_ICECHUNK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF, // flags - MF2_LOGRAV | MF2_CANNOTPUSH | MF2_FLOORCLIP // flags2 - }, - - { // MT_PLAYER_CLERIC - -1, // doomednum - S_CPLAY, // spawnstate - 100, // spawnhealth - S_CPLAY_RUN1, // seestate - SFX_NONE, // seesound - 0, // reactiontime - SFX_NONE, // attacksound - S_CPLAY_PAIN, // painstate - 255, // painchance - SFX_PLAYER_CLERIC_PAIN, // painsound - S_NULL, // meleestate - S_CPLAY_ATK1, // missilestate - S_NULL, // crashstate - S_CPLAY_DIE1, // deathstate - S_CPLAY_XDIE1, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags - MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL // flags2 - }, - - { // MT_PLAYER_MAGE - -1, // doomednum - S_MPLAY, // spawnstate - 100, // spawnhealth - S_MPLAY_RUN1, // seestate - SFX_NONE, // seesound - 0, // reactiontime - SFX_NONE, // attacksound - S_MPLAY_PAIN, // painstate - 255, // painchance - SFX_PLAYER_MAGE_PAIN, // painsound - S_NULL, // meleestate - S_MPLAY_ATK1, // missilestate - S_NULL, // crashstate - S_MPLAY_DIE1, // deathstate - S_MPLAY_XDIE1, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_PICKUP | MF_NOTDMATCH, // flags - MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_SLIDE | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL // flags2 - }, - - { // MT_PIGPLAYER - -1, // doomednum - S_PIGPLAY, // spawnstate - 100, // spawnhealth - S_PIGPLAY_RUN1, // seestate - SFX_NONE, // seesound - 0, // reactiontime - SFX_NONE, // attacksound - S_PIGPLAY_PAIN, // painstate - 255, // painchance - SFX_PIG_PAIN, // painsound - S_NULL, // meleestate - S_PIGPLAY_ATK1, // missilestate - S_NULL, // crashstate - S_PIG_DIE1, // deathstate - S_NULL, // xdeathstate - SFX_PIG_DEATH, // deathsound - 0, // speed - 16 * FRACUNIT, // radius - 24 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_DROPOFF | MF_NOTDMATCH, // flags - MF2_WINDTHRUST | MF2_SLIDE | MF2_PASSMOBJ | MF2_FLOORCLIP | MF2_TELESTOMP | MF2_PUSHWALL // flags2 - }, - - { // MT_PIG - -1, // doomednum - S_PIG_LOOK1, // spawnstate - 25, // spawnhealth - S_PIG_WALK1, // seestate - SFX_PIG_ACTIVE1, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_PIG_PAIN, // painstate - 128, // painchance - SFX_PIG_PAIN, // painsound - S_PIG_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_PIG_DIE1, // deathstate - S_NULL, // xdeathstate - SFX_PIG_DEATH, // deathsound - 10, // speed - 12 * FRACUNIT, // radius - 22 * FRACUNIT, // height - 60, // mass - 0, // damage - SFX_PIG_ACTIVE1, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_WINDTHRUST | MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 - }, - - { // MT_CENTAUR - 107, // doomednum - S_CENTAUR_LOOK1, // spawnstate - 200, // spawnhealth - S_CENTAUR_WALK1, // seestate - SFX_CENTAUR_SIGHT, // seesound - 8, // reactiontime - SFX_CENTAUR_ATTACK, // attacksound - S_CENTAUR_PAIN1, // painstate - 135, // painchance - SFX_CENTAUR_PAIN, // painsound - S_CENTAUR_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_CENTAUR_DEATH1, // deathstate - S_CENTAUR_DEATH_X1, // xdeathstate - SFX_CENTAUR_DEATH, // deathsound - 13, // speed - 20 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 120, // mass - 0, // damage - SFX_CENTAUR_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_CENTAURLEADER - 115, // doomednum - S_CENTAUR_LOOK1, // spawnstate - 250, // spawnhealth - S_CENTAUR_WALK1, // seestate - SFX_CENTAUR_SIGHT, // seesound - 8, // reactiontime - SFX_CENTAUR_ATTACK, // attacksound - S_CENTAUR_PAIN1, // painstate - 96, // painchance - SFX_CENTAUR_PAIN, // painsound - S_CENTAUR_ATK1, // meleestate - S_CENTAUR_MISSILE1, // missilestate - S_NULL, // crashstate - S_CENTAUR_DEATH1, // deathstate - S_CENTAUR_DEATH_X1, // xdeathstate - SFX_CENTAUR_DEATH, // deathsound - 10, // speed - 20 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 120, // mass - 0, // damage - SFX_CENTAUR_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_CENTAUR_FX - -1, // doomednum - S_CENTAUR_FX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CENTAUR_FX_X1, // deathstate - S_NULL, // xdeathstate - SFX_CENTAUR_MISSILE_EXPLODE, // deathsound - 20 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS // flags2 - }, - - { // MT_CENTAUR_SHIELD - -1, // doomednum - S_CENTAUR_SHIELD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CENTAUR_SHIELD_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_CENTAUR_SWORD - -1, // doomednum - S_CENTAUR_SWORD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_CENTAUR_SWORD_X1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DEMON - 31, // doomednum - S_DEMN_LOOK1, // spawnstate - 250, // spawnhealth - S_DEMN_CHASE1, // seestate - SFX_DEMON_SIGHT, // seesound - 8, // reactiontime - SFX_DEMON_ATTACK, // attacksound - S_DEMN_PAIN1, // painstate - 50, // painchance - SFX_DEMON_PAIN, // painsound - S_DEMN_ATK1_1, // meleestate - S_DEMN_ATK2_1, // missilestate - S_NULL, // crashstate - S_DEMN_DEATH1, // deathstate - S_DEMN_XDEATH1, // xdeathstate - SFX_DEMON_DEATH, // deathsound - 13, // speed - 32 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 220, // mass - 0, // damage - SFX_DEMON_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_DEMONCHUNK1 - -1, // doomednum - S_DEMONCHUNK1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMONCHUNK1_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMONCHUNK2 - -1, // doomednum - S_DEMONCHUNK2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMONCHUNK2_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMONCHUNK3 - -1, // doomednum - S_DEMONCHUNK3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMONCHUNK3_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMONCHUNK4 - -1, // doomednum - S_DEMONCHUNK4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMONCHUNK4_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMONCHUNK5 - -1, // doomednum - S_DEMONCHUNK5_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMONCHUNK5_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMONFX1 - -1, // doomednum - S_DEMONFX_MOVE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMONFX_BOOM1, // deathstate - S_NULL, // xdeathstate - SFX_DEMON_MISSILE_EXPLODE, // deathsound - 15 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 5, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FIREDAMAGE // flags2 - }, - - { // MT_DEMON2 - 8080, // doomednum - S_DEMN2_LOOK1, // spawnstate - 250, // spawnhealth - S_DEMN2_CHASE1, // seestate - SFX_DEMON_SIGHT, // seesound - 8, // reactiontime - SFX_DEMON_ATTACK, // attacksound - S_DEMN2_PAIN1, // painstate - 50, // painchance - SFX_DEMON_PAIN, // painsound - S_DEMN2_ATK1_1, // meleestate - S_DEMN2_ATK2_1, // missilestate - S_NULL, // crashstate - S_DEMN2_DEATH1, // deathstate - S_DEMN2_XDEATH1, // xdeathstate - SFX_DEMON_DEATH, // deathsound - 13, // speed - 32 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 220, // mass - 0, // damage - SFX_DEMON_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_DEMON2CHUNK1 - -1, // doomednum - S_DEMON2CHUNK1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMON2CHUNK1_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMON2CHUNK2 - -1, // doomednum - S_DEMON2CHUNK2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMON2CHUNK2_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMON2CHUNK3 - -1, // doomednum - S_DEMON2CHUNK3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMON2CHUNK3_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMON2CHUNK4 - -1, // doomednum - S_DEMON2CHUNK4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMON2CHUNK4_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMON2CHUNK5 - -1, // doomednum - S_DEMON2CHUNK5_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMON2CHUNK5_4, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_DEMON2FX1 - -1, // doomednum - S_DEMON2FX_MOVE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DEMON2FX_BOOM1, // deathstate - S_NULL, // xdeathstate - SFX_DEMON_MISSILE_EXPLODE, // deathsound - 15 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 5, // damage - SFX_NONE, // activesound - MF_MISSILE | MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FIREDAMAGE // flags2 - }, - - { // MT_WRAITHB - 10011, // doomednum - S_WRAITH_LOOK1, // spawnstate - 150, // spawnhealth - S_WRAITH_RAISE1, // seestate - SFX_WRAITH_SIGHT, // seesound - 8, // reactiontime - SFX_WRAITH_ATTACK, // attacksound - S_WRAITH_PAIN1, // painstate - 25, // painchance - SFX_WRAITH_PAIN, // painsound - S_WRAITH_ATK1_1, // meleestate - S_WRAITH_ATK2_1, // missilestate - S_NULL, // crashstate - S_WRAITH_DEATH1_1, // deathstate - S_WRAITH_DEATH2_1, // xdeathstate - SFX_WRAITH_DEATH, // deathsound - 11, // speed - 20 * FRACUNIT, // radius - 68 * FRACUNIT, // height - 75, // mass - 10, // damage - SFX_WRAITH_ACTIVE, // activesound - MF_DROPOFF | MF_NOGRAVITY | MF_FLOAT | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP | MF2_DONTDRAW // flags2 - }, - - { // MT_WRAITH - 34, // doomednum - S_WRAITH_INIT1, // spawnstate - 150, // spawnhealth - S_WRAITH_CHASE1, // seestate - SFX_WRAITH_SIGHT, // seesound - 8, // reactiontime - SFX_WRAITH_ATTACK, // attacksound - S_WRAITH_PAIN1, // painstate - 25, // painchance - SFX_WRAITH_PAIN, // painsound - S_WRAITH_ATK1_1, // meleestate - S_WRAITH_ATK2_1, // missilestate - S_NULL, // crashstate - S_WRAITH_DEATH1_1, // deathstate - S_WRAITH_DEATH2_1, // xdeathstate - SFX_WRAITH_DEATH, // deathsound - 11, // speed - 20 * FRACUNIT, // radius - 55 * FRACUNIT, // height - 75, // mass - 10, // damage - SFX_WRAITH_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF | MF_NOGRAVITY | MF_FLOAT, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 - }, - - { // MT_WRAITHFX1 - -1, // doomednum - S_WRTHFX_MOVE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_WRTHFX_BOOM1, // deathstate - S_NULL, // xdeathstate - SFX_WRAITH_MISSILE_EXPLODE, // deathsound - 14 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 5, // mass - 5, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FLOORCLIP | MF2_FIREDAMAGE // flags2 - }, - - { // MT_WRAITHFX2 - -1, // doomednum - S_WRTHFX_SIZZLE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_WRAITHFX3 - -1, // doomednum - S_WRTHFX_DROP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_WRTHFX_DEAD1, // deathstate - S_NULL, // xdeathstate - SFX_DRIP, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_WRAITHFX4 - -1, // doomednum - S_WRTHFX_ADROP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_WRTHFX_ADEAD1, // deathstate - S_NULL, // xdeathstate - SFX_DRIP, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_WRAITHFX5 - -1, // doomednum - S_WRTHFX_BDROP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_WRTHFX_BDEAD1, // deathstate - S_NULL, // xdeathstate - SFX_DRIP, // deathsound - 0, // speed - 2 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 5, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_MINOTAUR - 9, // doomednum - S_MNTR_SPAWN1, // spawnstate - 2500, // spawnhealth - S_MNTR_WALK1, // seestate - SFX_MAULATOR_SIGHT, // seesound - 8, // reactiontime - SFX_MAULATOR_HAMMER_SWING, // attacksound - S_MNTR_PAIN1, // painstate - 25, // painchance - SFX_MAULATOR_PAIN, // painsound - S_MNTR_ATK1_1, // meleestate - S_MNTR_ATK2_1, // missilestate - S_NULL, // crashstate - S_MNTR_DIE1, // deathstate - S_NULL, // xdeathstate - SFX_MAULATOR_DEATH, // deathsound - 16, // speed - 28 * FRACUNIT, // radius - 100 * FRACUNIT, // height - 800, // mass - 7, // damage - SFX_MAULATOR_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_SHADOW, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 - }, - - { // MT_MNTRFX1 - -1, // doomednum - S_MNTRFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MNTRFXI1_1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 20 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 3, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_MNTRFX2 - -1, // doomednum - S_MNTRFX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MNTRFXI2_1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 14 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 12 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_MNTRFX3 - -1, // doomednum - S_MNTRFX3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_MNTRFXI2_1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_MNTRSMOKE - -1, // doomednum - S_MINOSMOKE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_MNTRSMOKEEXIT - -1, // doomednum - S_MINOSMOKEX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SERPENT - 121, // doomednum - S_SERPENT_LOOK1, // spawnstate - 90, // spawnhealth - S_SERPENT_SWIM1, // seestate - SFX_SERPENT_SIGHT, // seesound - 8, // reactiontime - SFX_SERPENT_ATTACK, // attacksound - S_SERPENT_PAIN1, // painstate - 96, // painchance - SFX_SERPENT_PAIN, // painsound - S_SERPENT_SURFACE1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SERPENT_DIE1, // deathstate - S_SERPENT_XDIE1, // xdeathstate - SFX_SERPENT_DEATH, // deathsound - 12, // speed - 32 * FRACUNIT, // radius - 70 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_COUNTKILL | MF_NOBLOOD, // flags - MF2_PASSMOBJ | MF2_DONTDRAW | MF2_CANTLEAVEFLOORPIC | MF2_NONSHOOTABLE | MF2_MCROSS // flags2 - }, - - { // MT_SERPENTLEADER - 120, // doomednum - S_SERPENT_LOOK1, // spawnstate - 90, // spawnhealth - S_SERPENT_SWIM1, // seestate - SFX_SERPENT_SIGHT, // seesound - 8, // reactiontime - SFX_SERPENT_ATTACK, // attacksound - S_SERPENT_PAIN1, // painstate - 96, // painchance - SFX_SERPENT_PAIN, // painsound - S_SERPENT_SURFACE1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SERPENT_DIE1, // deathstate - S_SERPENT_XDIE1, // xdeathstate - SFX_SERPENT_DEATH, // deathsound - 12, // speed - 32 * FRACUNIT, // radius - 70 * FRACUNIT, // height - 200, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_COUNTKILL | MF_NOBLOOD, // flags - MF2_PASSMOBJ | MF2_DONTDRAW | MF2_CANTLEAVEFLOORPIC | MF2_NONSHOOTABLE | MF2_MCROSS // flags2 - }, - - { // MT_SERPENTFX - -1, // doomednum - S_SERPENT_FX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - 0, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SERPENT_FX_X1, // deathstate - S_NULL, // xdeathstate - SFX_SERPENTFX_HIT, // deathsound - 15 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 4, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SERPENT_HEAD - -1, // doomednum - S_SERPENT_HEAD1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - MF2_LOGRAV // flags2 - }, - - { // MT_SERPENT_GIB1 - -1, // doomednum - S_SERPENT_GIB1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 3 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_SERPENT_GIB2 - -1, // doomednum - S_SERPENT_GIB2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 3 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_SERPENT_GIB3 - -1, // doomednum - S_SERPENT_GIB3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 3 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_BISHOP - 114, // doomednum - S_BISHOP_LOOK1, // spawnstate - 130, // spawnhealth - S_BISHOP_WALK1, // seestate - SFX_BISHOP_SIGHT, // seesound - 8, // reactiontime - SFX_BISHOP_ATTACK, // attacksound - S_BISHOP_PAIN1, // painstate - 110, // painchance - SFX_BISHOP_PAIN, // painsound - 0, // meleestate - S_BISHOP_ATK1, // missilestate - S_NULL, // crashstate - S_BISHOP_DEATH1, // deathstate - S_NULL, // xdeathstate - SFX_BISHOP_DEATH, // deathsound - 10, // speed - 22 * FRACUNIT, // radius - 65 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_BISHOP_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_FLOAT | MF_NOGRAVITY | MF_NOBLOOD, // flags - MF2_PASSMOBJ | MF2_PUSHWALL | MF2_TELESTOMP // flags2 - }, - - { // MT_BISHOP_PUFF - -1, // doomednum - S_BISHOP_PUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SHADOW | MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_BISHOPBLUR - -1, // doomednum - S_BISHOPBLUR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_BISHOPPAINBLUR - -1, // doomednum - S_BISHOPPAINBLUR1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW, // flags - 0 // flags2 - }, - - { // MT_BISH_FX - -1, // doomednum - S_BISHFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BISHFXI1_1, // deathstate - S_NULL, // xdeathstate - SFX_BISHOP_MISSILE_EXPLODE, // deathsound - 10 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 100, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_SEEKERMISSILE // flags2 - }, - - { // MT_DRAGON - 254, // doomednum - S_DRAGON_LOOK1, // spawnstate - 640, // spawnhealth - S_DRAGON_INIT, // seestate - SFX_DRAGON_SIGHT, // seesound - 8, // reactiontime - SFX_DRAGON_ATTACK, // attacksound - S_DRAGON_PAIN1, // painstate - 128, // painchance - SFX_DRAGON_PAIN, // painsound - S_NULL, // meleestate - S_DRAGON_ATK1, // missilestate - S_NULL, // crashstate - S_DRAGON_DEATH1, // deathstate - S_NULL, // xdeathstate - SFX_DRAGON_DEATH, // deathsound - 10 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 65 * FRACUNIT, // height - INT_MAX, // mass - 0, // damage - SFX_DRAGON_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_FLOAT | MF_NOGRAVITY | MF_NOBLOOD, // flags - MF2_PASSMOBJ | MF2_BOSS // flags2 - }, - - { // MT_DRAGON_FX - -1, // doomednum - S_DRAGON_FX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_DRAGON_FX1_X1, // deathstate - S_NULL, // xdeathstate - SFX_DRAGON_FIREBALL_EXPLODE, // deathsound - 24 * FRACUNIT, // speed - 12 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 6, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE // flags2 - }, - - { // MT_DRAGON_FX2 - -1, // doomednum - S_DRAGON_FX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_DRAGON_FIREBALL_EXPLODE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP, // flags - MF2_NOTELEPORT | MF2_FIREDAMAGE | MF2_DONTDRAW // flags2 - }, - - { // MT_ARMOR_1 - 8005, // doomednum - S_ARMOR_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARMOR_2 - 8006, // doomednum - S_ARMOR_2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARMOR_3 - 8007, // doomednum - S_ARMOR_3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_ARMOR_4 - 8008, // doomednum - S_ARMOR_4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL | MF_NOGRAVITY, // flags - 0 // flags2 - }, - - { // MT_MANA1 - 122, // doomednum - S_MANA1_1, // spawnstate - 10, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MANA2 - 124, // doomednum - S_MANA2_1, // spawnstate - 10, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_MANA3 - 8004, // doomednum - S_MANA3_1, // spawnstate - 20, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 8 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - MF2_FLOATBOB // flags2 - }, - - { // MT_KEY1 - 8030, // doomednum - S_KEY1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY2 - 8031, // doomednum - S_KEY2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY3 - 8032, // doomednum - S_KEY3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY4 - 8033, // doomednum - S_KEY4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY5 - 8034, // doomednum - S_KEY5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY6 - 8035, // doomednum - S_KEY6, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY7 - 8036, // doomednum - S_KEY7, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY8 - 8037, // doomednum - S_KEY8, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEY9 - 8038, // doomednum - S_KEY9, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEYA - 8039, // doomednum - S_KEYA, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_KEYB - 8200, // doomednum - S_KEYB, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 8 * FRACUNIT, // radius - 20 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SPECIAL, // flags - 0 // flags2 - }, - - { // MT_SOUNDWIND - 1410, // doomednum - S_SND_WIND1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_SOUNDWATERFALL - 41, // doomednum - S_SND_WATERFALL, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR, // flags - 0 // flags2 - }, - - { // MT_ETTIN - 10030, // doomednum - S_ETTIN_LOOK1, // spawnstate - 175, // spawnhealth - S_ETTIN_CHASE1, // seestate - SFX_ETTIN_SIGHT, // seesound - 8, // reactiontime - SFX_ETTIN_ATTACK, // attacksound - S_ETTIN_PAIN1, // painstate - 60, // painchance - SFX_ETTIN_PAIN, // painsound - S_ETTIN_ATK1_1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ETTIN_DEATH1_1, // deathstate - S_ETTIN_DEATH2_1, // xdeathstate - SFX_ETTIN_DEATH, // deathsound - 13, // speed - 25 * FRACUNIT, // radius - 68 * FRACUNIT, // height - 175, // mass - 3, // damage - SFX_ETTIN_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_ETTIN_MACE - -1, // doomednum - S_ETTIN_MACE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ETTIN_MACE5, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_FIREDEMON - 10060, // doomednum - S_FIRED_SPAWN1, // spawnstate - 80, // spawnhealth - S_FIRED_LOOK4, // seestate - SFX_FIRED_SPAWN, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_FIRED_PAIN1, // painstate - 1, // painchance - SFX_FIRED_PAIN, // painsound - S_NULL, // meleestate - S_FIRED_ATTACK1, // missilestate - S_FIRED_XDEATH1, // crashstate - S_FIRED_DEATH1, // deathstate - S_FIRED_XDEATH1, // xdeathstate - SFX_FIRED_DEATH, // deathsound - 13, // speed - 20 * FRACUNIT, // radius - 68 * FRACUNIT, // height - 75, // mass - 1, // damage - SFX_FIRED_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_DROPOFF | MF_NOGRAVITY | MF_FLOAT, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_INVULNERABLE | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_FIREDEMON_SPLOTCH1 - -1, // doomednum - S_FIRED_CORPSE1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_FIREDEMON_SPLOTCH2 - -1, // doomednum - S_FIRED_CORPSE4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_DROPOFF | MF_CORPSE, // flags - MF2_NOTELEPORT | MF2_FLOORCLIP // flags2 - }, - - { // MT_FIREDEMON_FX1 - -1, // doomednum - S_FIRED_RDROP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIRED_RDEAD1_1, // deathstate - S_FIRED_RDEAD1_2, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 16, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FIREDEMON_FX2 - -1, // doomednum - S_FIRED_RDROP2, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIRED_RDEAD2_1, // deathstate - S_FIRED_RDEAD2_2, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 16, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FIREDEMON_FX3 - -1, // doomednum - S_FIRED_RDROP3, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIRED_RDEAD3_1, // deathstate - S_FIRED_RDEAD3_2, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 16, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FIREDEMON_FX4 - -1, // doomednum - S_FIRED_RDROP4, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIRED_RDEAD4_1, // deathstate - S_FIRED_RDEAD4_2, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 16, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FIREDEMON_FX5 - -1, // doomednum - S_FIRED_RDROP5, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIRED_RDEAD5_1, // deathstate - S_FIRED_RDEAD5_2, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 3 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 16, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FIREDEMON_FX6 - -1, // doomednum - S_FIRED_FX6_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_FIRED_FX6_2, // deathstate - S_NULL, // xdeathstate - SFX_FIRED_MISSILE_HIT, // deathsound - 10 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 6 * FRACUNIT, // height - 15, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_IMPACT | MF2_PCROSS | MF2_FLOORCLIP | MF2_FIREDAMAGE // flags2 - }, - - { // MT_ICEGUY - 8020, // doomednum - S_ICEGUY_LOOK, // spawnstate - 120, // spawnhealth - S_ICEGUY_WALK1, // seestate - SFX_ICEGUY_SIGHT, // seesound - 8, // reactiontime - SFX_ICEGUY_ATTACK, // attacksound - S_ICEGUY_PAIN1, // painstate - 144, // painchance - SFX_NONE, // painsound - 0, // meleestate - S_ICEGUY_ATK1, // missilestate - S_NULL, // crashstate - S_ICEGUY_DEATH, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 14, // speed - 22 * FRACUNIT, // radius - 75 * FRACUNIT, // height - 150, // mass - 0, // damage - SFX_ICEGUY_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags - MF2_PASSMOBJ | MF2_PUSHWALL | MF2_ICEDAMAGE | MF2_MCROSS | MF2_TELESTOMP // flags2 - }, - - { // MT_ICEGUY_FX - -1, // doomednum - S_ICEGUY_FX1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_ICEGUY_FX_X1, // deathstate - S_NULL, // xdeathstate - SFX_ICEGUY_FX_EXPLODE, // deathsound - 14 * FRACUNIT, // speed - 8 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags - MF2_NOTELEPORT | MF2_ICEDAMAGE // flags2 - }, - - { // MT_ICEFX_PUFF - -1, // doomednum - S_ICEFX_PUFF1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - FRACUNIT, // radius - FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_SHADOW | MF_DROPOFF, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ICEGUY_FX2 - -1, // doomednum - S_ICEGUY_FX2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 10 * FRACUNIT, // speed - 4 * FRACUNIT, // radius - 4 * FRACUNIT, // height - 100, // mass - 1, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_LOGRAV | MF2_ICEDAMAGE // flags2 - }, - - { // MT_ICEGUY_BIT - -1, // doomednum - S_ICEGUY_BIT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - FRACUNIT, // radius - FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_ICEGUY_WISP1 - -1, // doomednum - S_ICEGUY_WISP1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_ICEGUY_WISP2 - -1, // doomednum - S_ICEGUY_WISP2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_FIGHTER_BOSS - 10100, // doomednum - S_FIGHTER, // spawnstate - 800, // spawnhealth - S_FIGHTER_RUN1, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_FIGHTER_PAIN, // painstate - 50, // painchance - SFX_PLAYER_FIGHTER_PAIN, // painsound - S_FIGHTER_ATK1, // meleestate - S_FIGHTER_ATK1, // missilestate - S_NULL, // crashstate - S_FIGHTER_DIE1, // deathstate - S_FIGHTER_XDIE1, // xdeathstate - SFX_PLAYER_FIGHTER_CRAZY_DEATH, // deathsound - 25, // speed - 16 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL | MF2_MCROSS // flags2 - }, - - { // MT_CLERIC_BOSS - 10101, // doomednum - S_CLERIC, // spawnstate - 800, // spawnhealth - S_CLERIC_RUN1, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_CLERIC_PAIN, // painstate - 50, // painchance - SFX_PLAYER_CLERIC_PAIN, // painsound - S_CLERIC_ATK1, // meleestate - S_CLERIC_ATK1, // missilestate - S_NULL, // crashstate - S_CLERIC_DIE1, // deathstate - S_CLERIC_XDIE1, // xdeathstate - SFX_PLAYER_CLERIC_CRAZY_DEATH, // deathsound - 25, // speed - 16 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL | MF2_MCROSS // flags2 - }, - - { // MT_MAGE_BOSS - 10102, // doomednum - S_MAGE, // spawnstate - 800, // spawnhealth - S_MAGE_RUN1, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_MAGE_PAIN, // painstate - 50, // painchance - SFX_PLAYER_MAGE_PAIN, // painsound - S_MAGE_ATK1, // meleestate - S_MAGE_ATK1, // missilestate - S_NULL, // crashstate - S_MAGE_DIE1, // deathstate - S_MAGE_XDIE1, // xdeathstate - SFX_PLAYER_MAGE_CRAZY_DEATH, // deathsound - 25, // speed - 16 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_TELESTOMP | MF2_PUSHWALL | MF2_MCROSS // flags2 - }, - - { // MT_SORCBOSS - 10080, // doomednum - S_SORC_SPAWN1, // spawnstate - 5000, // spawnhealth - S_SORC_WALK1, // seestate - SFX_SORCERER_SIGHT, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_SORC_PAIN1, // painstate - 10, // painchance - SFX_SORCERER_PAIN, // painsound - S_NULL, // meleestate - S_SORC_ATK2_1, // missilestate - S_NULL, // crashstate - S_SORC_DIE1, // deathstate - S_NULL, // xdeathstate - SFX_SORCERER_DEATHSCREAM, // deathsound - 16, // speed - 40 * FRACUNIT, // radius - 110 * FRACUNIT, // height - 500, // mass - 9, // damage - SFX_SORCERER_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_NOBLOOD, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_PUSHWALL | MF2_BOSS | MF2_MCROSS // flags2 - }, - - { // MT_SORCBALL1 - -1, // doomednum - S_SORCBALL1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_SORCERER_BALLBOUNCE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_SORCBALL1_D1, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SORCBALL1_D5, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 10 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SORCBALL2 - -1, // doomednum - S_SORCBALL2_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_SORCERER_BALLBOUNCE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_SORCBALL2_D1, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SORCBALL2_D5, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 10 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SORCBALL3 - -1, // doomednum - S_SORCBALL3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_SORCERER_BALLBOUNCE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_SORCBALL3_D1, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SORCBALL3_D5, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 10 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SORCFX1 - -1, // doomednum - S_SORCFX1_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_SORCERER_BALLBOUNCE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SORCFX1_D1, // deathstate - S_SORCFX1_D1, // xdeathstate - SFX_NONE, // deathsound - 7 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE, // flags - MF2_NOTELEPORT | MF2_FLOORBOUNCE // flags2 - }, - - { // MT_SORCFX2 - -1, // doomednum - S_SORCFX2_SPLIT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SORCFX2T1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 15 * FRACUNIT, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SORCFX2_T1 - -1, // doomednum - S_SORCFX2T1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_ALTSHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SORCFX3 - -1, // doomednum - S_SORCFX3_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_SORCERER_BISHOPSPAWN, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BISHMORPH1, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 15 * FRACUNIT, // speed - 22 * FRACUNIT, // radius - 65 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SORCFX3_EXPLOSION - -1, // doomednum - S_SORCFX3_EXP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_ALTSHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SORCFX4 - -1, // doomednum - S_SORCFX4_1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_SORCFX4_D1, // deathstate - S_NULL, // xdeathstate - SFX_SORCERER_BALLEXPLODE, // deathsound - 12 * FRACUNIT, // speed - 10 * FRACUNIT, // radius - 10 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_MISSILE | MF_NOGRAVITY, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_SORCSPARK1 - -1, // doomednum - S_SORCSPARK1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 5 * FRACUNIT, // radius - 5 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF, // flags - MF2_NOTELEPORT | MF2_LOGRAV // flags2 - }, - - { // MT_BLASTEFFECT - -1, // doomednum - S_BLASTEFFECT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_NOCLIP | MF_ALTSHADOW, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_WATER_DRIP - -1, // doomednum - S_WATERDRIP1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_DRIP, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 1, // mass - 0, // damage - SFX_NONE, // activesound - MF_MISSILE, // flags - MF2_LOGRAV | MF2_NOTELEPORT // flags2 - }, - - { // MT_KORAX - 10200, // doomednum - S_KORAX_LOOK1, // spawnstate - 5000, // spawnhealth - S_KORAX_CHASE2, // seestate - SFX_KORAX_SIGHT, // seesound - 8, // reactiontime - SFX_KORAX_ATTACK, // attacksound - S_KORAX_PAIN1, // painstate - 20, // painchance - SFX_KORAX_PAIN, // painsound - S_NULL, // meleestate - S_KORAX_ATTACK1, // missilestate - S_NULL, // crashstate - S_KORAX_DEATH1, // deathstate - S_NULL, // xdeathstate - SFX_KORAX_DEATH, // deathsound - 10, // speed - 65 * FRACUNIT, // radius - 115 * FRACUNIT, // height - 2000, // mass - 15, // damage - SFX_KORAX_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL, // flags - MF2_FLOORCLIP | MF2_PUSHWALL | MF2_MCROSS | MF2_TELESTOMP | MF2_BOSS // flags2 - }, - - { // MT_KORAX_SPIRIT1 - -1, // doomednum - S_KSPIRIT_ROAM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 8 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_KORAX_SPIRIT2 - -1, // doomednum - S_KSPIRIT_ROAM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 8 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_KORAX_SPIRIT3 - -1, // doomednum - S_KSPIRIT_ROAM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 8 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_KORAX_SPIRIT4 - -1, // doomednum - S_KSPIRIT_ROAM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 8 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_KORAX_SPIRIT5 - -1, // doomednum - S_KSPIRIT_ROAM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 8 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_KORAX_SPIRIT6 - -1, // doomednum - S_KSPIRIT_ROAM1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 8 * FRACUNIT, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_DROPOFF | MF_NOGRAVITY | MF_ALTSHADOW | MF_MISSILE | MF_NOCLIP, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_DEMON_MASH - -1, // doomednum - S_DEMN_LOOK1, // spawnstate - 250, // spawnhealth - S_DEMN_CHASE1, // seestate - SFX_DEMON_SIGHT, // seesound - 8, // reactiontime - SFX_DEMON_ATTACK, // attacksound - S_DEMN_PAIN1, // painstate - 50, // painchance - SFX_DEMON_PAIN, // painsound - S_DEMN_ATK1_1, // meleestate - S_DEMN_ATK2_1, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_DEMON_DEATH, // deathsound - 13, // speed - 32 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 220, // mass - 0, // damage - SFX_DEMON_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 - }, - - { // MT_DEMON2_MASH - -1, // doomednum - S_DEMN2_LOOK1, // spawnstate - 250, // spawnhealth - S_DEMN2_CHASE1, // seestate - SFX_DEMON_SIGHT, // seesound - 8, // reactiontime - SFX_DEMON_ATTACK, // attacksound - S_DEMN2_PAIN1, // painstate - 50, // painchance - SFX_DEMON_PAIN, // painsound - S_DEMN2_ATK1_1, // meleestate - S_DEMN2_ATK2_1, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_DEMON_DEATH, // deathsound - 13, // speed - 32 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 220, // mass - 0, // damage - SFX_DEMON_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 - }, - - { // MT_ETTIN_MASH - -1, // doomednum - S_ETTIN_LOOK1, // spawnstate - 175, // spawnhealth - S_ETTIN_CHASE1, // seestate - SFX_ETTIN_SIGHT, // seesound - 8, // reactiontime - SFX_ETTIN_ATTACK, // attacksound - S_ETTIN_PAIN1, // painstate - 60, // painchance - SFX_ETTIN_PAIN, // painsound - S_ETTIN_ATK1_1, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_ETTIN_DEATH, // deathsound - 13, // speed - 25 * FRACUNIT, // radius - 68 * FRACUNIT, // height - 175, // mass - 3, // damage - SFX_ETTIN_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 - }, - - { // MT_CENTAUR_MASH - -1, // doomednum - S_CENTAUR_LOOK1, // spawnstate - 200, // spawnhealth - S_CENTAUR_WALK1, // seestate - SFX_CENTAUR_SIGHT, // seesound - 8, // reactiontime - SFX_CENTAUR_ATTACK, // attacksound - S_CENTAUR_PAIN1, // painstate - 135, // painchance - SFX_CENTAUR_PAIN, // painsound - S_CENTAUR_ATK1, // meleestate - 0, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_CENTAUR_DEATH, // deathsound - 13, // speed - 20 * FRACUNIT, // radius - 64 * FRACUNIT, // height - 120, // mass - 0, // damage - SFX_CENTAUR_ACTIVE, // activesound - MF_SOLID | MF_SHOOTABLE | MF_COUNTKILL | MF_ALTSHADOW | MF_NOBLOOD, // flags - MF2_FLOORCLIP | MF2_PASSMOBJ | MF2_MCROSS | MF2_PUSHWALL | MF2_BLASTED // flags2 - }, - - { // MT_KORAX_BOLT - -1, // doomednum - S_KBOLT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 15 * FRACUNIT, // radius - 35 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE | MF_DROPOFF, // flags - MF2_NOTELEPORT // flags2 - }, - - { // MT_BAT_SPAWNER - 10225, // doomednum - S_SPAWNBATS1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_NULL, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 0, // speed - 20 * FRACUNIT, // radius - 16 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOSECTOR | MF_NOGRAVITY, // flags - MF2_DONTDRAW // flags2 - }, - - { // MT_BAT - -1, // doomednum - S_BAT1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - SFX_NONE, // seesound - 8, // reactiontime - SFX_NONE, // attacksound - S_NULL, // painstate - 0, // painchance - SFX_NONE, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // crashstate - S_BAT_DEATH, // deathstate - S_NULL, // xdeathstate - SFX_NONE, // deathsound - 5 * FRACUNIT, // speed - 3 * FRACUNIT, // radius - 3 * FRACUNIT, // height - 100, // mass - 0, // damage - SFX_NONE, // activesound - MF_NOBLOCKMAP | MF_NOGRAVITY | MF_MISSILE, // flags - MF2_PASSMOBJ | MF2_NOTELEPORT // flags2 - } -}; diff --git a/games/NXDoom/src/hexen/info.h b/games/NXDoom/src/hexen/info.h deleted file mode 100644 index 18872fae987..00000000000 --- a/games/NXDoom/src/hexen/info.h +++ /dev/null @@ -1,3626 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// generated by stateco - -typedef enum -{ - SPR_MAN1, - SPR_ACLO, - SPR_TLGL, - SPR_FBL1, - SPR_XPL1, - SPR_ARRW, - SPR_DART, - SPR_RIPP, - SPR_CFCF, - SPR_BLAD, - SPR_SHRD, - SPR_FFSM, - SPR_FFLG, - SPR_PTN1, - SPR_PTN2, - SPR_SOAR, - SPR_INVU, - SPR_SUMN, - SPR_TSPK, - SPR_TELO, - SPR_TRNG, - SPR_ROCK, - SPR_FOGS, - SPR_FOGM, - SPR_FOGL, - SPR_SGSA, - SPR_SGSB, - SPR_PORK, - SPR_EGGM, - SPR_FHFX, - SPR_SPHL, - SPR_STWN, - SPR_GMPD, - SPR_ASKU, - SPR_ABGM, - SPR_AGMR, - SPR_AGMG, - SPR_AGG2, - SPR_AGMB, - SPR_AGB2, - SPR_ABK1, - SPR_ABK2, - SPR_ASK2, - SPR_AFWP, - SPR_ACWP, - SPR_AMWP, - SPR_AGER, - SPR_AGR2, - SPR_AGR3, - SPR_AGR4, - SPR_TRCH, - SPR_PSBG, - SPR_ATLP, - SPR_THRW, - SPR_SPED, - SPR_BMAN, - SPR_BRAC, - SPR_BLST, - SPR_HRAD, - SPR_SPSH, - SPR_LVAS, - SPR_SLDG, - SPR_STTW, - SPR_RCK1, - SPR_RCK2, - SPR_RCK3, - SPR_RCK4, - SPR_CDLR, - SPR_TRE1, - SPR_TRDT, - SPR_TRE2, - SPR_TRE3, - SPR_STM1, - SPR_STM2, - SPR_STM3, - SPR_STM4, - SPR_MSH1, - SPR_MSH2, - SPR_MSH3, - SPR_MSH4, - SPR_MSH5, - SPR_MSH6, - SPR_MSH7, - SPR_MSH8, - SPR_SGMP, - SPR_SGM1, - SPR_SGM2, - SPR_SGM3, - SPR_SLC1, - SPR_SLC2, - SPR_SLC3, - SPR_MSS1, - SPR_MSS2, - SPR_SWMV, - SPR_CPS1, - SPR_CPS2, - SPR_TMS1, - SPR_TMS2, - SPR_TMS3, - SPR_TMS4, - SPR_TMS5, - SPR_TMS6, - SPR_TMS7, - SPR_CPS3, - SPR_STT2, - SPR_STT3, - SPR_STT4, - SPR_STT5, - SPR_GAR1, - SPR_GAR2, - SPR_GAR3, - SPR_GAR4, - SPR_GAR5, - SPR_GAR6, - SPR_GAR7, - SPR_GAR8, - SPR_GAR9, - SPR_BNR1, - SPR_TRE4, - SPR_TRE5, - SPR_TRE6, - SPR_TRE7, - SPR_LOGG, - SPR_ICT1, - SPR_ICT2, - SPR_ICT3, - SPR_ICT4, - SPR_ICM1, - SPR_ICM2, - SPR_ICM3, - SPR_ICM4, - SPR_RKBL, - SPR_RKBS, - SPR_RKBK, - SPR_RBL1, - SPR_RBL2, - SPR_RBL3, - SPR_VASE, - SPR_POT1, - SPR_POT2, - SPR_POT3, - SPR_PBIT, - SPR_CPS4, - SPR_CPS5, - SPR_CPS6, - SPR_CPB1, - SPR_CPB2, - SPR_CPB3, - SPR_CPB4, - SPR_BDRP, - SPR_BDSH, - SPR_BDPL, - SPR_CNDL, - SPR_LEF1, - SPR_LEF3, - SPR_LEF2, - SPR_TWTR, - SPR_WLTR, - SPR_BARL, - SPR_SHB1, - SPR_SHB2, - SPR_BCKT, - SPR_SHRM, - SPR_FBUL, - SPR_FSKL, - SPR_BRTR, - SPR_SUIT, - SPR_BBLL, - SPR_CAND, - SPR_IRON, - SPR_XMAS, - SPR_CDRN, - SPR_CHNS, - SPR_TST1, - SPR_TST2, - SPR_TST3, - SPR_TST4, - SPR_TST5, - SPR_TST6, - SPR_TST7, - SPR_TST8, - SPR_TST9, - SPR_TST0, - SPR_TELE, - SPR_TSMK, - SPR_FPCH, - SPR_WFAX, - SPR_FAXE, - SPR_WFHM, - SPR_FHMR, - SPR_FSRD, - SPR_FSFX, - SPR_CMCE, - SPR_WCSS, - SPR_CSSF, - SPR_WCFM, - SPR_CFLM, - SPR_CFFX, - SPR_CHLY, - SPR_SPIR, - SPR_MWND, - SPR_WMLG, - SPR_MLNG, - SPR_MLFX, - SPR_MLF2, - SPR_MSTF, - SPR_MSP1, - SPR_MSP2, - SPR_WFR1, - SPR_WFR2, - SPR_WFR3, - SPR_WCH1, - SPR_WCH2, - SPR_WCH3, - SPR_WMS1, - SPR_WMS2, - SPR_WMS3, - SPR_WPIG, - SPR_WMCS, - SPR_CONE, - SPR_SHEX, - SPR_BLOD, - SPR_GIBS, - SPR_PLAY, - SPR_FDTH, - SPR_BSKL, - SPR_ICEC, - SPR_CLER, - SPR_MAGE, - SPR_PIGY, - SPR_CENT, - SPR_CTXD, - SPR_CTFX, - SPR_CTDP, - SPR_DEMN, - SPR_DEMA, - SPR_DEMB, - SPR_DEMC, - SPR_DEMD, - SPR_DEME, - SPR_DMFX, - SPR_DEM2, - SPR_DMBA, - SPR_DMBB, - SPR_DMBC, - SPR_DMBD, - SPR_DMBE, - SPR_D2FX, - SPR_WRTH, - SPR_WRT2, - SPR_WRBL, - SPR_MNTR, - SPR_FX12, - SPR_FX13, - SPR_MNSM, - SPR_SSPT, - SPR_SSDV, - SPR_SSXD, - SPR_SSFX, - SPR_BISH, - SPR_BPFX, - SPR_DRAG, - SPR_DRFX, - SPR_ARM1, - SPR_ARM2, - SPR_ARM3, - SPR_ARM4, - SPR_MAN2, - SPR_MAN3, - SPR_KEY1, - SPR_KEY2, - SPR_KEY3, - SPR_KEY4, - SPR_KEY5, - SPR_KEY6, - SPR_KEY7, - SPR_KEY8, - SPR_KEY9, - SPR_KEYA, - SPR_KEYB, - SPR_ETTN, - SPR_ETTB, - SPR_FDMN, - SPR_FDMB, - SPR_ICEY, - SPR_ICPR, - SPR_ICWS, - SPR_SORC, - SPR_SBMP, - SPR_SBS4, - SPR_SBMB, - SPR_SBS3, - SPR_SBMG, - SPR_SBS1, - SPR_SBS2, - SPR_SBFX, - SPR_RADE, - SPR_WATR, - SPR_KORX, - SPR_ABAT, - NUMSPRITES -} spritenum_t; - -typedef enum -{ - S_NULL, - S_FREETARGMOBJ, - S_MAPSPOT, - S_FIREBALL1_1, - S_FIREBALL1_2, - S_FIREBALL1_X1, - S_FIREBALL1_X2, - S_FIREBALL1_X3, - S_FIREBALL1_X4, - S_FIREBALL1_X5, - S_FIREBALL1_X6, - S_ARROW_1, - S_ARROW_X1, - S_DART_1, - S_DART_X1, - S_POISONDART_1, - S_POISONDART_X1, - S_RIPPERBALL_1, - S_RIPPERBALL_2, - S_RIPPERBALL_3, - S_RIPPERBALL_X1, - S_RIPPERBALL_X2, - S_RIPPERBALL_X3, - S_RIPPERBALL_X4, - S_RIPPERBALL_X5, - S_RIPPERBALL_X6, - S_RIPPERBALL_X7, - S_RIPPERBALL_X8, - S_RIPPERBALL_X9, - S_RIPPERBALL_X10, - S_PRJ_BLADE1, - S_PRJ_BLADE_X1, - S_ICESHARD1, - S_ICESHARD2, - S_ICESHARD3, - S_FLAME_TSMALL1, - S_FLAME_TSMALL2, - S_FLAME_TSMALL3, - S_FLAME_TSMALL4, - S_FLAME_TSMALL5, - S_FLAME_TSMALL6, - S_FLAME_TLARGE1, - S_FLAME_TLARGE2, - S_FLAME_TLARGE3, - S_FLAME_TLARGE4, - S_FLAME_TLARGE5, - S_FLAME_TLARGE6, - S_FLAME_TLARGE7, - S_FLAME_TLARGE8, - S_FLAME_TLARGE9, - S_FLAME_TLARGE10, - S_FLAME_TLARGE11, - S_FLAME_TLARGE12, - S_FLAME_TLARGE13, - S_FLAME_TLARGE14, - S_FLAME_TLARGE15, - S_FLAME_TLARGE16, - S_FLAME_SDORM1, - S_FLAME_SDORM2, - S_FLAME_SDORM3, - S_FLAME_SMALL1, - S_FLAME_SMALL2, - S_FLAME_SMALL3, - S_FLAME_SMALL4, - S_FLAME_SMALL5, - S_FLAME_SMALL6, - S_FLAME_SMALL7, - S_FLAME_LDORM1, - S_FLAME_LDORM2, - S_FLAME_LDORM3, - S_FLAME_LDORM4, - S_FLAME_LDORM5, - S_FLAME_LARGE1, - S_FLAME_LARGE2, - S_FLAME_LARGE3, - S_FLAME_LARGE4, - S_FLAME_LARGE5, - S_FLAME_LARGE6, - S_FLAME_LARGE7, - S_FLAME_LARGE8, - S_FLAME_LARGE9, - S_FLAME_LARGE10, - S_FLAME_LARGE11, - S_FLAME_LARGE12, - S_FLAME_LARGE13, - S_FLAME_LARGE14, - S_FLAME_LARGE15, - S_FLAME_LARGE16, - S_FLAME_LARGE17, - S_FLAME_LARGE18, - S_ITEM_PTN1_1, - S_ITEM_PTN1_2, - S_ITEM_PTN1_3, - S_HIDESPECIAL1, - S_HIDESPECIAL2, - S_HIDESPECIAL3, - S_HIDESPECIAL4, - S_HIDESPECIAL5, - S_HIDESPECIAL6, - S_HIDESPECIAL7, - S_HIDESPECIAL8, - S_HIDESPECIAL9, - S_HIDESPECIAL10, - S_HIDESPECIAL11, - S_DORMANTARTI1_1, - S_DORMANTARTI1_2, - S_DORMANTARTI1_3, - S_DORMANTARTI1_4, - S_DORMANTARTI1_5, - S_DORMANTARTI1_6, - S_DORMANTARTI1_7, - S_DORMANTARTI1_8, - S_DORMANTARTI1_9, - S_DORMANTARTI1_10, - S_DORMANTARTI1_11, - S_DORMANTARTI1_12, - S_DORMANTARTI1_13, - S_DORMANTARTI1_14, - S_DORMANTARTI1_15, - S_DORMANTARTI1_16, - S_DORMANTARTI1_17, - S_DORMANTARTI1_18, - S_DORMANTARTI1_19, - S_DORMANTARTI1_20, - S_DORMANTARTI1_21, - S_DORMANTARTI2_1, - S_DORMANTARTI2_2, - S_DORMANTARTI2_3, - S_DORMANTARTI2_4, - S_DORMANTARTI2_5, - S_DORMANTARTI2_6, - S_DORMANTARTI2_7, - S_DORMANTARTI2_8, - S_DORMANTARTI2_9, - S_DORMANTARTI2_10, - S_DORMANTARTI2_11, - S_DORMANTARTI2_12, - S_DORMANTARTI2_13, - S_DORMANTARTI2_14, - S_DORMANTARTI2_15, - S_DORMANTARTI2_16, - S_DORMANTARTI2_17, - S_DORMANTARTI2_18, - S_DORMANTARTI2_19, - S_DORMANTARTI2_20, - S_DORMANTARTI2_21, - S_DORMANTARTI3_1, - S_DORMANTARTI3_2, - S_DORMANTARTI3_3, - S_DORMANTARTI3_4, - S_DORMANTARTI3_5, - S_DORMANTARTI3_6, - S_DORMANTARTI3_7, - S_DORMANTARTI3_8, - S_DORMANTARTI3_9, - S_DORMANTARTI3_10, - S_DORMANTARTI3_11, - S_DORMANTARTI3_12, - S_DORMANTARTI3_13, - S_DORMANTARTI3_14, - S_DORMANTARTI3_15, - S_DORMANTARTI3_16, - S_DORMANTARTI3_17, - S_DORMANTARTI3_18, - S_DORMANTARTI3_19, - S_DORMANTARTI3_20, - S_DORMANTARTI3_21, - S_DEADARTI1, - S_DEADARTI2, - S_DEADARTI3, - S_DEADARTI4, - S_DEADARTI5, - S_DEADARTI6, - S_DEADARTI7, - S_DEADARTI8, - S_DEADARTI9, - S_DEADARTI10, - S_ARTI_PTN2_1, - S_ARTI_PTN2_2, - S_ARTI_PTN2_3, - S_ARTI_SOAR1, - S_ARTI_SOAR2, - S_ARTI_SOAR3, - S_ARTI_SOAR4, - S_ARTI_INVU1, - S_ARTI_INVU2, - S_ARTI_INVU3, - S_ARTI_INVU4, - S_ARTI_SUMMON, - S_SUMMON_FX1_1, - S_SUMMON_FX2_1, - S_SUMMON_FX2_2, - S_SUMMON_FX2_3, - S_THRUSTINIT2_1, - S_THRUSTINIT2_2, - S_BTHRUSTINIT2_1, - S_BTHRUSTINIT2_2, - S_THRUSTINIT1_1, - S_THRUSTINIT1_2, - S_BTHRUSTINIT1_1, - S_BTHRUSTINIT1_2, - S_THRUSTRAISE1, - S_THRUSTRAISE2, - S_THRUSTRAISE3, - S_THRUSTRAISE4, - S_BTHRUSTRAISE1, - S_BTHRUSTRAISE2, - S_BTHRUSTRAISE3, - S_BTHRUSTRAISE4, - S_THRUSTIMPALE, - S_BTHRUSTIMPALE, - S_THRUSTRAISE, - S_BTHRUSTRAISE, - S_THRUSTBLOCK, - S_BTHRUSTBLOCK, - S_THRUSTLOWER, - S_BTHRUSTLOWER, - S_THRUSTSTAY, - S_BTHRUSTSTAY, - S_ARTI_TELOTHER1, - S_ARTI_TELOTHER2, - S_ARTI_TELOTHER3, - S_ARTI_TELOTHER4, - S_TELO_FX1, - S_TELO_FX2, - S_TELO_FX3, - S_TELO_FX4, - S_TELO_FX5, - S_TELO_FX6, - S_TELO_FX7, - S_TELO_FX8, - S_TELO_FX9, - S_TELO_FX2_1, - S_TELO_FX2_2, - S_TELO_FX2_3, - S_TELO_FX2_4, - S_TELO_FX2_5, - S_TELO_FX2_6, - S_TELO_FX3_1, - S_TELO_FX3_2, - S_TELO_FX3_3, - S_TELO_FX3_4, - S_TELO_FX3_5, - S_TELO_FX3_6, - S_TELO_FX4_1, - S_TELO_FX4_2, - S_TELO_FX4_3, - S_TELO_FX4_4, - S_TELO_FX4_5, - S_TELO_FX4_6, - S_TELO_FX5_1, - S_TELO_FX5_2, - S_TELO_FX5_3, - S_TELO_FX5_4, - S_TELO_FX5_5, - S_TELO_FX5_6, - S_DIRT1_1, - S_DIRT1_D, - S_DIRT2_1, - S_DIRT2_D, - S_DIRT3_1, - S_DIRT3_D, - S_DIRT4_1, - S_DIRT4_D, - S_DIRT5_1, - S_DIRT5_D, - S_DIRT6_1, - S_DIRT6_D, - S_DIRTCLUMP1, - S_ROCK1_1, - S_ROCK1_D, - S_ROCK2_1, - S_ROCK2_D, - S_ROCK3_1, - S_ROCK3_D, - S_SPAWNFOG1, - S_FOGPATCHS1, - S_FOGPATCHS2, - S_FOGPATCHS3, - S_FOGPATCHS4, - S_FOGPATCHS5, - S_FOGPATCHS0, - S_FOGPATCHM1, - S_FOGPATCHM2, - S_FOGPATCHM3, - S_FOGPATCHM4, - S_FOGPATCHM5, - S_FOGPATCHM0, - S_FOGPATCHMA, - S_FOGPATCHMB, - S_FOGPATCHMC, - S_FOGPATCHMD, - S_FOGPATCHL1, - S_FOGPATCHL2, - S_FOGPATCHL3, - S_FOGPATCHL4, - S_FOGPATCHL5, - S_FOGPATCHL0, - S_FOGPATCHLA, - S_FOGPATCHLB, - S_FOGPATCHLC, - S_FOGPATCHLD, - S_QUAKE_ACTIVE1, - S_QUAKE_ACTIVE2, - S_QUAKE_ACTIVE3, - S_QUAKE_ACTIVE4, - S_QUAKE_ACTIVE5, - S_QUAKE_ACTIVE6, - S_QUAKE_ACTIVE7, - S_QUAKE_ACTIVE8, - S_QUAKE_ACTIVE9, - S_QUAKE_ACTIVE0, - S_QUAKE_ACTIVEA, - S_QUAKE_ACTIVEB, - S_QUAKE_ACTIVEC, - S_QUAKE_ACTIVED, - S_QUAKE_ACTIVEE, - S_QUAKE_ACTIVEF, - S_QUAKE_ACTIVEG, - S_QUAKE_ACTIVEH, - S_QUAKE_ACTIVEI, - S_QUAKE_ACTIVEJ, - S_QUAKE_ACTIVEK, - S_QUAKE_ACTIVEL, - S_QUAKE_ACTIVEM, - S_QUAKE_ACTIVEN, - S_QUAKE_ACTIVEO, - S_QUAKE_ACTIVEP, - S_QUAKE_ACTIVEQ, - S_QUAKE_ACTIVER, - S_QUAKE_ACTIVES, - S_QUAKE_ACTIVET, - S_QUAKE_ACTIVEU, - S_QUAKE_ACTIVEV, - S_QUAKE_ACTIVEW, - S_QUAKE_ACTIVEX, - S_QUAKE_ACTIVEY, - S_QUAKE_ACTIVEZ, - S_QUAKE_ACT1, - S_QUAKE_ACT2, - S_QUAKE_ACT3, - S_QUAKE_ACT4, - S_QUAKE_ACT5, - S_QUAKE_ACT6, - S_QUAKE_ACT7, - S_QUAKE_ACT8, - S_QUAKE_ACT9, - S_QUAKE_ACT0, - S_SGSHARD1_1, - S_SGSHARD1_2, - S_SGSHARD1_3, - S_SGSHARD1_4, - S_SGSHARD1_5, - S_SGSHARD1_D, - S_SGSHARD2_1, - S_SGSHARD2_2, - S_SGSHARD2_3, - S_SGSHARD2_4, - S_SGSHARD2_5, - S_SGSHARD2_D, - S_SGSHARD3_1, - S_SGSHARD3_2, - S_SGSHARD3_3, - S_SGSHARD3_4, - S_SGSHARD3_5, - S_SGSHARD3_D, - S_SGSHARD4_1, - S_SGSHARD4_2, - S_SGSHARD4_3, - S_SGSHARD4_4, - S_SGSHARD4_5, - S_SGSHARD4_D, - S_SGSHARD5_1, - S_SGSHARD5_2, - S_SGSHARD5_3, - S_SGSHARD5_4, - S_SGSHARD5_5, - S_SGSHARD5_D, - S_SGSHARD6_1, - S_SGSHARD6_D, - S_SGSHARD7_1, - S_SGSHARD7_D, - S_SGSHARD8_1, - S_SGSHARD8_D, - S_SGSHARD9_1, - S_SGSHARD9_D, - S_SGSHARD0_1, - S_SGSHARD0_D, - S_ARTI_EGGC1, - S_ARTI_EGGC2, - S_ARTI_EGGC3, - S_ARTI_EGGC4, - S_ARTI_EGGC5, - S_ARTI_EGGC6, - S_ARTI_EGGC7, - S_ARTI_EGGC8, - S_EGGFX1, - S_EGGFX2, - S_EGGFX3, - S_EGGFX4, - S_EGGFX5, - S_EGGFXI1_1, - S_EGGFXI1_2, - S_EGGFXI1_3, - S_EGGFXI1_4, - S_ARTI_SPHL1, - S_ZWINGEDSTATUENOSKULL, - S_ZWINGEDSTATUENOSKULL2, - S_ZGEMPEDESTAL1, - S_ZGEMPEDESTAL2, - S_ARTIPUZZSKULL, - S_ARTIPUZZGEMBIG, - S_ARTIPUZZGEMRED, - S_ARTIPUZZGEMGREEN1, - S_ARTIPUZZGEMGREEN2, - S_ARTIPUZZGEMBLUE1, - S_ARTIPUZZGEMBLUE2, - S_ARTIPUZZBOOK1, - S_ARTIPUZZBOOK2, - S_ARTIPUZZSKULL2, - S_ARTIPUZZFWEAPON, - S_ARTIPUZZCWEAPON, - S_ARTIPUZZMWEAPON, - S_ARTIPUZZGEAR_1, - S_ARTIPUZZGEAR_2, - S_ARTIPUZZGEAR_3, - S_ARTIPUZZGEAR_4, - S_ARTIPUZZGEAR_5, - S_ARTIPUZZGEAR_6, - S_ARTIPUZZGEAR_7, - S_ARTIPUZZGEAR_8, - S_ARTIPUZZGEAR2_1, - S_ARTIPUZZGEAR2_2, - S_ARTIPUZZGEAR2_3, - S_ARTIPUZZGEAR2_4, - S_ARTIPUZZGEAR2_5, - S_ARTIPUZZGEAR2_6, - S_ARTIPUZZGEAR2_7, - S_ARTIPUZZGEAR2_8, - S_ARTIPUZZGEAR3_1, - S_ARTIPUZZGEAR3_2, - S_ARTIPUZZGEAR3_3, - S_ARTIPUZZGEAR3_4, - S_ARTIPUZZGEAR3_5, - S_ARTIPUZZGEAR3_6, - S_ARTIPUZZGEAR3_7, - S_ARTIPUZZGEAR3_8, - S_ARTIPUZZGEAR4_1, - S_ARTIPUZZGEAR4_2, - S_ARTIPUZZGEAR4_3, - S_ARTIPUZZGEAR4_4, - S_ARTIPUZZGEAR4_5, - S_ARTIPUZZGEAR4_6, - S_ARTIPUZZGEAR4_7, - S_ARTIPUZZGEAR4_8, - S_ARTI_TRCH1, - S_ARTI_TRCH2, - S_ARTI_TRCH3, - S_FIREBOMB1, - S_FIREBOMB2, - S_FIREBOMB3, - S_FIREBOMB4, - S_FIREBOMB5, - S_FIREBOMB6, - S_FIREBOMB7, - S_FIREBOMB8, - S_FIREBOMB9, - S_FIREBOMB10, - S_FIREBOMB11, - S_ARTI_ATLP1, - S_ARTI_ATLP2, - S_ARTI_ATLP3, - S_ARTI_ATLP4, - S_ARTI_PSBG1, - S_POISONBAG1, - S_POISONBAG2, - S_POISONBAG3, - S_POISONBAG4, - S_POISONCLOUD1, - S_POISONCLOUD2, - S_POISONCLOUD3, - S_POISONCLOUD4, - S_POISONCLOUD5, - S_POISONCLOUD6, - S_POISONCLOUD7, - S_POISONCLOUD8, - S_POISONCLOUD9, - S_POISONCLOUD10, - S_POISONCLOUD11, - S_POISONCLOUD12, - S_POISONCLOUD13, - S_POISONCLOUD14, - S_POISONCLOUD15, - S_POISONCLOUD16, - S_POISONCLOUD17, - S_POISONCLOUD18, - S_POISONCLOUD_X1, - S_POISONCLOUD_X2, - S_POISONCLOUD_X3, - S_POISONCLOUD_X4, - S_THROWINGBOMB1, - S_THROWINGBOMB2, - S_THROWINGBOMB3, - S_THROWINGBOMB4, - S_THROWINGBOMB5, - S_THROWINGBOMB6, - S_THROWINGBOMB7, - S_THROWINGBOMB8, - S_THROWINGBOMB9, - S_THROWINGBOMB10, - S_THROWINGBOMB11, - S_THROWINGBOMB12, - S_THROWINGBOMB_X1, - S_THROWINGBOMB_X2, - S_THROWINGBOMB_X3, - S_THROWINGBOMB_X4, - S_THROWINGBOMB_X5, - S_THROWINGBOMB_X6, - S_THROWINGBOMB_X7, - S_THROWINGBOMB_X8, - S_ARTI_BOOTS1, - S_ARTI_BOOTS2, - S_ARTI_BOOTS3, - S_ARTI_BOOTS4, - S_ARTI_BOOTS5, - S_ARTI_BOOTS6, - S_ARTI_BOOTS7, - S_ARTI_BOOTS8, - S_ARTI_MANA, - S_ARTI_ARMOR1, - S_ARTI_ARMOR2, - S_ARTI_ARMOR3, - S_ARTI_ARMOR4, - S_ARTI_ARMOR5, - S_ARTI_ARMOR6, - S_ARTI_ARMOR7, - S_ARTI_ARMOR8, - S_ARTI_BLAST1, - S_ARTI_BLAST2, - S_ARTI_BLAST3, - S_ARTI_BLAST4, - S_ARTI_BLAST5, - S_ARTI_BLAST6, - S_ARTI_BLAST7, - S_ARTI_BLAST8, - S_ARTI_HEALRAD1, - S_ARTI_HEALRAD2, - S_ARTI_HEALRAD3, - S_ARTI_HEALRAD4, - S_ARTI_HEALRAD5, - S_ARTI_HEALRAD6, - S_ARTI_HEALRAD7, - S_ARTI_HEALRAD8, - S_ARTI_HEALRAD9, - S_ARTI_HEALRAD0, - S_ARTI_HEALRADA, - S_ARTI_HEALRADB, - S_ARTI_HEALRADC, - S_ARTI_HEALRADD, - S_ARTI_HEALRADE, - S_ARTI_HEALRADF, - S_SPLASH1, - S_SPLASH2, - S_SPLASH3, - S_SPLASH4, - S_SPLASHX, - S_SPLASHBASE1, - S_SPLASHBASE2, - S_SPLASHBASE3, - S_SPLASHBASE4, - S_SPLASHBASE5, - S_SPLASHBASE6, - S_SPLASHBASE7, - S_LAVASPLASH1, - S_LAVASPLASH2, - S_LAVASPLASH3, - S_LAVASPLASH4, - S_LAVASPLASH5, - S_LAVASPLASH6, - S_LAVASMOKE1, - S_LAVASMOKE2, - S_LAVASMOKE3, - S_LAVASMOKE4, - S_LAVASMOKE5, - S_SLUDGECHUNK1, - S_SLUDGECHUNK2, - S_SLUDGECHUNK3, - S_SLUDGECHUNK4, - S_SLUDGECHUNKX, - S_SLUDGESPLASH1, - S_SLUDGESPLASH2, - S_SLUDGESPLASH3, - S_SLUDGESPLASH4, - S_ZWINGEDSTATUE1, - S_ZROCK1_1, - S_ZROCK2_1, - S_ZROCK3_1, - S_ZROCK4_1, - S_ZCHANDELIER1, - S_ZCHANDELIER2, - S_ZCHANDELIER3, - S_ZCHANDELIER_U, - S_ZTREEDEAD1, - S_ZTREE, - S_ZTREEDESTRUCTIBLE1, - S_ZTREEDES_D1, - S_ZTREEDES_D2, - S_ZTREEDES_D3, - S_ZTREEDES_D4, - S_ZTREEDES_D5, - S_ZTREEDES_D6, - S_ZTREEDES_X1, - S_ZTREEDES_X2, - S_ZTREEDES_X3, - S_ZTREEDES_X4, - S_ZTREEDES_X5, - S_ZTREEDES_X6, - S_ZTREEDES_X7, - S_ZTREEDES_X8, - S_ZTREEDES_X9, - S_ZTREEDES_X10, - S_ZTREESWAMP182_1, - S_ZTREESWAMP172_1, - S_ZSTUMPBURNED1, - S_ZSTUMPBARE1, - S_ZSTUMPSWAMP1_1, - S_ZSTUMPSWAMP2_1, - S_ZSHROOMLARGE1_1, - S_ZSHROOMLARGE2_1, - S_ZSHROOMLARGE3_1, - S_ZSHROOMSMALL1_1, - S_ZSHROOMSMALL2_1, - S_ZSHROOMSMALL3_1, - S_ZSHROOMSMALL4_1, - S_ZSHROOMSMALL5_1, - S_ZSTALAGMITEPILLAR1, - S_ZSTALAGMITELARGE1, - S_ZSTALAGMITEMEDIUM1, - S_ZSTALAGMITESMALL1, - S_ZSTALACTITELARGE1, - S_ZSTALACTITEMEDIUM1, - S_ZSTALACTITESMALL1, - S_ZMOSSCEILING1_1, - S_ZMOSSCEILING2_1, - S_ZSWAMPVINE1, - S_ZCORPSEKABOB1, - S_ZCORPSESLEEPING1, - S_ZTOMBSTONERIP1, - S_ZTOMBSTONESHANE1, - S_ZTOMBSTONEBIGCROSS1, - S_ZTOMBSTONEBRIANR1, - S_ZTOMBSTONECROSSCIRCLE1, - S_ZTOMBSTONESMALLCROSS1, - S_ZTOMBSTONEBRIANP1, - S_CORPSEHANGING_1, - S_ZSTATUEGARGOYLEGREENTALL_1, - S_ZSTATUEGARGOYLEBLUETALL_1, - S_ZSTATUEGARGOYLEGREENSHORT_1, - S_ZSTATUEGARGOYLEBLUESHORT_1, - S_ZSTATUEGARGOYLESTRIPETALL_1, - S_ZSTATUEGARGOYLEDARKREDTALL_1, - S_ZSTATUEGARGOYLEREDTALL_1, - S_ZSTATUEGARGOYLETANTALL_1, - S_ZSTATUEGARGOYLERUSTTALL_1, - S_ZSTATUEGARGOYLEDARKREDSHORT_1, - S_ZSTATUEGARGOYLEREDSHORT_1, - S_ZSTATUEGARGOYLETANSHORT_1, - S_ZSTATUEGARGOYLERUSTSHORT_1, - S_ZBANNERTATTERED_1, - S_ZTREELARGE1, - S_ZTREELARGE2, - S_ZTREEGNARLED1, - S_ZTREEGNARLED2, - S_ZLOG, - S_ZSTALACTITEICELARGE, - S_ZSTALACTITEICEMEDIUM, - S_ZSTALACTITEICESMALL, - S_ZSTALACTITEICETINY, - S_ZSTALAGMITEICELARGE, - S_ZSTALAGMITEICEMEDIUM, - S_ZSTALAGMITEICESMALL, - S_ZSTALAGMITEICETINY, - S_ZROCKBROWN1, - S_ZROCKBROWN2, - S_ZROCKBLACK, - S_ZRUBBLE1, - S_ZRUBBLE2, - S_ZRUBBLE3, - S_ZVASEPILLAR, - S_ZPOTTERY1, - S_ZPOTTERY2, - S_ZPOTTERY3, - S_ZPOTTERY_EXPLODE, - S_POTTERYBIT_1, - S_POTTERYBIT_2, - S_POTTERYBIT_3, - S_POTTERYBIT_4, - S_POTTERYBIT_5, - S_POTTERYBIT_EX0, - S_POTTERYBIT_EX1, - S_POTTERYBIT_EX1_2, - S_POTTERYBIT_EX2, - S_POTTERYBIT_EX2_2, - S_POTTERYBIT_EX3, - S_POTTERYBIT_EX3_2, - S_POTTERYBIT_EX4, - S_POTTERYBIT_EX4_2, - S_POTTERYBIT_EX5, - S_POTTERYBIT_EX5_2, - S_ZCORPSELYNCHED1, - S_ZCORPSELYNCHED2, - S_ZCORPSESITTING, - S_ZCORPSESITTING_X, - S_CORPSEBIT_1, - S_CORPSEBIT_2, - S_CORPSEBIT_3, - S_CORPSEBIT_4, - S_CORPSEBLOODDRIP, - S_CORPSEBLOODDRIP_X1, - S_CORPSEBLOODDRIP_X2, - S_CORPSEBLOODDRIP_X3, - S_CORPSEBLOODDRIP_X4, - S_BLOODPOOL, - S_ZCANDLE1, - S_ZCANDLE2, - S_ZCANDLE3, - S_ZLEAFSPAWNER, - S_LEAF1_1, - S_LEAF1_2, - S_LEAF1_3, - S_LEAF1_4, - S_LEAF1_5, - S_LEAF1_6, - S_LEAF1_7, - S_LEAF1_8, - S_LEAF1_9, - S_LEAF1_10, - S_LEAF1_11, - S_LEAF1_12, - S_LEAF1_13, - S_LEAF1_14, - S_LEAF1_15, - S_LEAF1_16, - S_LEAF1_17, - S_LEAF1_18, - S_LEAF_X1, - S_LEAF2_1, - S_LEAF2_2, - S_LEAF2_3, - S_LEAF2_4, - S_LEAF2_5, - S_LEAF2_6, - S_LEAF2_7, - S_LEAF2_8, - S_LEAF2_9, - S_LEAF2_10, - S_LEAF2_11, - S_LEAF2_12, - S_LEAF2_13, - S_LEAF2_14, - S_LEAF2_15, - S_LEAF2_16, - S_LEAF2_17, - S_LEAF2_18, - S_ZTWINEDTORCH_1, - S_ZTWINEDTORCH_2, - S_ZTWINEDTORCH_3, - S_ZTWINEDTORCH_4, - S_ZTWINEDTORCH_5, - S_ZTWINEDTORCH_6, - S_ZTWINEDTORCH_7, - S_ZTWINEDTORCH_8, - S_ZTWINEDTORCH_UNLIT, - S_BRIDGE1, - S_BRIDGE2, - S_BRIDGE3, - S_FREE_BRIDGE1, - S_FREE_BRIDGE2, - S_BBALL1, - S_BBALL2, - S_ZWALLTORCH1, - S_ZWALLTORCH2, - S_ZWALLTORCH3, - S_ZWALLTORCH4, - S_ZWALLTORCH5, - S_ZWALLTORCH6, - S_ZWALLTORCH7, - S_ZWALLTORCH8, - S_ZWALLTORCH_U, - S_ZBARREL1, - S_ZSHRUB1, - S_ZSHRUB1_DIE, - S_ZSHRUB1_X1, - S_ZSHRUB1_X2, - S_ZSHRUB1_X3, - S_ZSHRUB2, - S_ZSHRUB2_DIE, - S_ZSHRUB2_X1, - S_ZSHRUB2_X2, - S_ZSHRUB2_X3, - S_ZSHRUB2_X4, - S_ZBUCKET1, - S_ZPOISONSHROOM1, - S_ZPOISONSHROOM_P1, - S_ZPOISONSHROOM_P2, - S_ZPOISONSHROOM_X1, - S_ZPOISONSHROOM_X2, - S_ZPOISONSHROOM_X3, - S_ZPOISONSHROOM_X4, - S_ZFIREBULL1, - S_ZFIREBULL2, - S_ZFIREBULL3, - S_ZFIREBULL4, - S_ZFIREBULL5, - S_ZFIREBULL6, - S_ZFIREBULL7, - S_ZFIREBULL_DEATH, - S_ZFIREBULL_DEATH2, - S_ZFIREBULL_U, - S_ZFIREBULL_BIRTH, - S_ZFIREBULL_BIRTH2, - S_ZFIRETHING1, - S_ZFIRETHING2, - S_ZFIRETHING3, - S_ZFIRETHING4, - S_ZFIRETHING5, - S_ZFIRETHING6, - S_ZFIRETHING7, - S_ZFIRETHING8, - S_ZFIRETHING9, - S_ZBRASSTORCH1, - S_ZBRASSTORCH2, - S_ZBRASSTORCH3, - S_ZBRASSTORCH4, - S_ZBRASSTORCH5, - S_ZBRASSTORCH6, - S_ZBRASSTORCH7, - S_ZBRASSTORCH8, - S_ZBRASSTORCH9, - S_ZBRASSTORCH10, - S_ZBRASSTORCH11, - S_ZBRASSTORCH12, - S_ZBRASSTORCH13, - S_ZSUITOFARMOR, - S_ZSUITOFARMOR_X1, - S_ZARMORCHUNK1, - S_ZARMORCHUNK2, - S_ZARMORCHUNK3, - S_ZARMORCHUNK4, - S_ZARMORCHUNK5, - S_ZARMORCHUNK6, - S_ZARMORCHUNK7, - S_ZARMORCHUNK8, - S_ZARMORCHUNK9, - S_ZARMORCHUNK10, - S_ZBELL, - S_ZBELL_X1, - S_ZBELL_X2, - S_ZBELL_X3, - S_ZBELL_X4, - S_ZBELL_X5, - S_ZBELL_X6, - S_ZBELL_X7, - S_ZBELL_X8, - S_ZBELL_X9, - S_ZBELL_X10, - S_ZBELL_X11, - S_ZBELL_X12, - S_ZBELL_X13, - S_ZBELL_X14, - S_ZBELL_X15, - S_ZBELL_X16, - S_ZBELL_X17, - S_ZBELL_X18, - S_ZBELL_X19, - S_ZBELL_X20, - S_ZBELL_X21, - S_ZBELL_X22, - S_ZBELL_X23, - S_ZBELL_X24, - S_ZBELL_X25, - S_ZBELL_X26, - S_ZBELL_X27, - S_ZBELL_X28, - S_ZBELL_X29, - S_ZBELL_X30, - S_ZBELL_X31, - S_ZBELL_X32, - S_ZBELL_X33, - S_ZBELL_X34, - S_ZBELL_X35, - S_ZBELL_X36, - S_ZBELL_X37, - S_ZBELL_X38, - S_ZBELL_X39, - S_ZBELL_X40, - S_ZBELL_X41, - S_ZBELL_X42, - S_ZBELL_X43, - S_ZBELL_X44, - S_ZBELL_X45, - S_ZBELL_X46, - S_ZBELL_X47, - S_ZBLUE_CANDLE1, - S_ZBLUE_CANDLE2, - S_ZBLUE_CANDLE3, - S_ZBLUE_CANDLE4, - S_ZBLUE_CANDLE5, - S_ZIRON_MAIDEN, - S_ZXMAS_TREE, - S_ZXMAS_TREE_DIE, - S_ZXMAS_TREE_X1, - S_ZXMAS_TREE_X2, - S_ZXMAS_TREE_X3, - S_ZXMAS_TREE_X4, - S_ZXMAS_TREE_X5, - S_ZXMAS_TREE_X6, - S_ZXMAS_TREE_X7, - S_ZXMAS_TREE_X8, - S_ZXMAS_TREE_X9, - S_ZXMAS_TREE_X10, - S_ZCAULDRON1, - S_ZCAULDRON2, - S_ZCAULDRON3, - S_ZCAULDRON4, - S_ZCAULDRON5, - S_ZCAULDRON6, - S_ZCAULDRON7, - S_ZCAULDRON_U, - S_ZCHAINBIT32, - S_ZCHAINBIT64, - S_ZCHAINEND_HEART, - S_ZCHAINEND_HOOK1, - S_ZCHAINEND_HOOK2, - S_ZCHAINEND_SPIKE, - S_ZCHAINEND_SKULL, - S_TABLE_SHIT1, - S_TABLE_SHIT2, - S_TABLE_SHIT3, - S_TABLE_SHIT4, - S_TABLE_SHIT5, - S_TABLE_SHIT6, - S_TABLE_SHIT7, - S_TABLE_SHIT8, - S_TABLE_SHIT9, - S_TABLE_SHIT10, - S_TFOG1, - S_TFOG2, - S_TFOG3, - S_TFOG4, - S_TFOG5, - S_TFOG6, - S_TFOG7, - S_TFOG8, - S_TFOG9, - S_TFOG10, - S_TFOG11, - S_TFOG12, - S_TFOG13, - S_TELESMOKE1, - S_TELESMOKE2, - S_TELESMOKE3, - S_TELESMOKE4, - S_TELESMOKE5, - S_TELESMOKE6, - S_TELESMOKE7, - S_TELESMOKE8, - S_TELESMOKE9, - S_TELESMOKE10, - S_TELESMOKE11, - S_TELESMOKE12, - S_TELESMOKE13, - S_TELESMOKE14, - S_TELESMOKE15, - S_TELESMOKE16, - S_TELESMOKE17, - S_TELESMOKE18, - S_TELESMOKE19, - S_TELESMOKE20, - S_TELESMOKE21, - S_TELESMOKE22, - S_TELESMOKE23, - S_TELESMOKE24, - S_TELESMOKE25, - S_TELESMOKE26, - S_LIGHTDONE, - S_PUNCHREADY, - S_PUNCHDOWN, - S_PUNCHUP, - S_PUNCHATK1_1, - S_PUNCHATK1_2, - S_PUNCHATK1_3, - S_PUNCHATK1_4, - S_PUNCHATK1_5, - S_PUNCHATK2_1, - S_PUNCHATK2_2, - S_PUNCHATK2_3, - S_PUNCHATK2_4, - S_PUNCHATK2_5, - S_PUNCHATK2_6, - S_PUNCHATK2_7, - S_PUNCHATK2_8, - S_PUNCHATK2_9, - S_PUNCHPUFF1, - S_PUNCHPUFF2, - S_PUNCHPUFF3, - S_PUNCHPUFF4, - S_PUNCHPUFF5, - S_AXE, - S_FAXEREADY, - S_FAXEDOWN, - S_FAXEUP, - S_FAXEATK_1, - S_FAXEATK_2, - S_FAXEATK_3, - S_FAXEATK_4, - S_FAXEATK_5, - S_FAXEATK_6, - S_FAXEATK_7, - S_FAXEATK_8, - S_FAXEATK_9, - S_FAXEATK_10, - S_FAXEATK_11, - S_FAXEATK_12, - S_FAXEATK_13, - S_FAXEREADY_G, - S_FAXEREADY_G1, - S_FAXEREADY_G2, - S_FAXEREADY_G3, - S_FAXEREADY_G4, - S_FAXEREADY_G5, - S_FAXEDOWN_G, - S_FAXEUP_G, - S_FAXEATK_G1, - S_FAXEATK_G2, - S_FAXEATK_G3, - S_FAXEATK_G4, - S_FAXEATK_G5, - S_FAXEATK_G6, - S_FAXEATK_G7, - S_FAXEATK_G8, - S_FAXEATK_G9, - S_FAXEATK_G10, - S_FAXEATK_G11, - S_FAXEATK_G12, - S_FAXEATK_G13, - S_AXEPUFF_GLOW1, - S_AXEPUFF_GLOW2, - S_AXEPUFF_GLOW3, - S_AXEPUFF_GLOW4, - S_AXEPUFF_GLOW5, - S_AXEPUFF_GLOW6, - S_AXEPUFF_GLOW7, - S_AXEBLOOD1, - S_AXEBLOOD2, - S_AXEBLOOD3, - S_AXEBLOOD4, - S_AXEBLOOD5, - S_AXEBLOOD6, - S_HAMM, - S_FHAMMERREADY, - S_FHAMMERDOWN, - S_FHAMMERUP, - S_FHAMMERATK_1, - S_FHAMMERATK_2, - S_FHAMMERATK_3, - S_FHAMMERATK_4, - S_FHAMMERATK_5, - S_FHAMMERATK_6, - S_FHAMMERATK_7, - S_FHAMMERATK_8, - S_FHAMMERATK_9, - S_FHAMMERATK_10, - S_FHAMMERATK_11, - S_FHAMMERATK_12, - S_HAMMER_MISSILE_1, - S_HAMMER_MISSILE_2, - S_HAMMER_MISSILE_3, - S_HAMMER_MISSILE_4, - S_HAMMER_MISSILE_5, - S_HAMMER_MISSILE_6, - S_HAMMER_MISSILE_7, - S_HAMMER_MISSILE_8, - S_HAMMER_MISSILE_X1, - S_HAMMER_MISSILE_X2, - S_HAMMER_MISSILE_X3, - S_HAMMER_MISSILE_X4, - S_HAMMER_MISSILE_X5, - S_HAMMER_MISSILE_X6, - S_HAMMER_MISSILE_X7, - S_HAMMER_MISSILE_X8, - S_HAMMER_MISSILE_X9, - S_HAMMER_MISSILE_X10, - S_HAMMERPUFF1, - S_HAMMERPUFF2, - S_HAMMERPUFF3, - S_HAMMERPUFF4, - S_HAMMERPUFF5, - S_FSWORDREADY, - S_FSWORDREADY1, - S_FSWORDREADY2, - S_FSWORDREADY3, - S_FSWORDREADY4, - S_FSWORDREADY5, - S_FSWORDREADY6, - S_FSWORDREADY7, - S_FSWORDREADY8, - S_FSWORDREADY9, - S_FSWORDREADY10, - S_FSWORDREADY11, - S_FSWORDDOWN, - S_FSWORDUP, - S_FSWORDATK_1, - S_FSWORDATK_2, - S_FSWORDATK_3, - S_FSWORDATK_4, - S_FSWORDATK_5, - S_FSWORDATK_6, - S_FSWORDATK_7, - S_FSWORDATK_8, - S_FSWORDATK_9, - S_FSWORDATK_10, - S_FSWORDATK_11, - S_FSWORDATK_12, - S_FSWORD_MISSILE1, - S_FSWORD_MISSILE2, - S_FSWORD_MISSILE3, - S_FSWORD_MISSILE_X1, - S_FSWORD_MISSILE_X2, - S_FSWORD_MISSILE_X3, - S_FSWORD_MISSILE_X4, - S_FSWORD_MISSILE_X5, - S_FSWORD_MISSILE_X6, - S_FSWORD_MISSILE_X7, - S_FSWORD_MISSILE_X8, - S_FSWORD_MISSILE_X9, - S_FSWORD_MISSILE_X10, - S_FSWORD_FLAME1, - S_FSWORD_FLAME2, - S_FSWORD_FLAME3, - S_FSWORD_FLAME4, - S_FSWORD_FLAME5, - S_FSWORD_FLAME6, - S_FSWORD_FLAME7, - S_FSWORD_FLAME8, - S_FSWORD_FLAME9, - S_FSWORD_FLAME10, - S_CMACEREADY, - S_CMACEDOWN, - S_CMACEUP, - S_CMACEATK_1, - S_CMACEATK_2, - S_CMACEATK_3, - S_CMACEATK_4, - S_CMACEATK_5, - S_CMACEATK_6, - S_CMACEATK_7, - S_CMACEATK_8, - S_CMACEATK_9, - S_CMACEATK_10, - S_CMACEATK_11, - S_CMACEATK_12, - S_CMACEATK_13, - S_CMACEATK_14, - S_CMACEATK_15, - S_CMACEATK_16, - S_CMACEATK_17, - S_CSTAFF, - S_CSTAFFREADY, - S_CSTAFFREADY1, - S_CSTAFFREADY2, - S_CSTAFFREADY3, - S_CSTAFFREADY4, - S_CSTAFFREADY5, - S_CSTAFFREADY6, - S_CSTAFFREADY7, - S_CSTAFFREADY8, - S_CSTAFFREADY9, - S_CSTAFFBLINK1, - S_CSTAFFBLINK2, - S_CSTAFFBLINK3, - S_CSTAFFBLINK4, - S_CSTAFFBLINK5, - S_CSTAFFBLINK6, - S_CSTAFFBLINK7, - S_CSTAFFBLINK8, - S_CSTAFFBLINK9, - S_CSTAFFBLINK10, - S_CSTAFFBLINK11, - S_CSTAFFDOWN, - S_CSTAFFDOWN2, - S_CSTAFFDOWN3, - S_CSTAFFUP, - S_CSTAFFATK_1, - S_CSTAFFATK_2, - S_CSTAFFATK_3, - S_CSTAFFATK_4, - S_CSTAFFATK_5, - S_CSTAFFATK_6, - S_CSTAFFATK2_1, - S_CSTAFF_MISSILE1, - S_CSTAFF_MISSILE2, - S_CSTAFF_MISSILE3, - S_CSTAFF_MISSILE4, - S_CSTAFF_MISSILE_X1, - S_CSTAFF_MISSILE_X2, - S_CSTAFF_MISSILE_X3, - S_CSTAFF_MISSILE_X4, - S_CSTAFFPUFF1, - S_CSTAFFPUFF2, - S_CSTAFFPUFF3, - S_CSTAFFPUFF4, - S_CSTAFFPUFF5, - S_CFLAME1, - S_CFLAME2, - S_CFLAME3, - S_CFLAME4, - S_CFLAME5, - S_CFLAME6, - S_CFLAME7, - S_CFLAME8, - S_CFLAMEREADY1, - S_CFLAMEREADY2, - S_CFLAMEREADY3, - S_CFLAMEREADY4, - S_CFLAMEREADY5, - S_CFLAMEREADY6, - S_CFLAMEREADY7, - S_CFLAMEREADY8, - S_CFLAMEREADY9, - S_CFLAMEREADY10, - S_CFLAMEREADY11, - S_CFLAMEREADY12, - S_CFLAMEDOWN, - S_CFLAMEUP, - S_CFLAMEATK_1, - S_CFLAMEATK_2, - S_CFLAMEATK_3, - S_CFLAMEATK_4, - S_CFLAMEATK_5, - S_CFLAMEATK_6, - S_CFLAMEATK_7, - S_CFLAMEATK_8, - S_CFLAMEFLOOR1, - S_CFLAMEFLOOR2, - S_CFLAMEFLOOR3, - S_FLAMEPUFF1, - S_FLAMEPUFF2, - S_FLAMEPUFF3, - S_FLAMEPUFF4, - S_FLAMEPUFF5, - S_FLAMEPUFF6, - S_FLAMEPUFF7, - S_FLAMEPUFF8, - S_FLAMEPUFF9, - S_FLAMEPUFF10, - S_FLAMEPUFF11, - S_FLAMEPUFF12, - S_FLAMEPUFF13, - S_FLAMEPUFF2_1, - S_FLAMEPUFF2_2, - S_FLAMEPUFF2_3, - S_FLAMEPUFF2_4, - S_FLAMEPUFF2_5, - S_FLAMEPUFF2_6, - S_FLAMEPUFF2_7, - S_FLAMEPUFF2_8, - S_FLAMEPUFF2_9, - S_FLAMEPUFF2_10, - S_FLAMEPUFF2_11, - S_FLAMEPUFF2_12, - S_FLAMEPUFF2_13, - S_FLAMEPUFF2_14, - S_FLAMEPUFF2_15, - S_FLAMEPUFF2_16, - S_FLAMEPUFF2_17, - S_FLAMEPUFF2_18, - S_FLAMEPUFF2_19, - S_FLAMEPUFF2_20, - S_CIRCLE_FLAME1, - S_CIRCLE_FLAME2, - S_CIRCLE_FLAME3, - S_CIRCLE_FLAME4, - S_CIRCLE_FLAME5, - S_CIRCLE_FLAME6, - S_CIRCLE_FLAME7, - S_CIRCLE_FLAME8, - S_CIRCLE_FLAME9, - S_CIRCLE_FLAME10, - S_CIRCLE_FLAME11, - S_CIRCLE_FLAME12, - S_CIRCLE_FLAME13, - S_CIRCLE_FLAME14, - S_CIRCLE_FLAME15, - S_CIRCLE_FLAME16, - S_CIRCLE_FLAME_X1, - S_CIRCLE_FLAME_X2, - S_CIRCLE_FLAME_X3, - S_CIRCLE_FLAME_X4, - S_CIRCLE_FLAME_X5, - S_CIRCLE_FLAME_X6, - S_CIRCLE_FLAME_X7, - S_CIRCLE_FLAME_X8, - S_CIRCLE_FLAME_X9, - S_CIRCLE_FLAME_X10, - S_CFLAME_MISSILE1, - S_CFLAME_MISSILE2, - S_CFLAME_MISSILE_X, - S_CHOLYREADY, - S_CHOLYDOWN, - S_CHOLYUP, - S_CHOLYATK_1, - S_CHOLYATK_2, - S_CHOLYATK_3, - S_CHOLYATK_4, - S_CHOLYATK_5, - S_CHOLYATK_6, - S_CHOLYATK_7, - S_CHOLYATK_8, - S_CHOLYATK_9, - S_HOLY_FX1, - S_HOLY_FX2, - S_HOLY_FX3, - S_HOLY_FX4, - S_HOLY_FX_X1, - S_HOLY_FX_X2, - S_HOLY_FX_X3, - S_HOLY_FX_X4, - S_HOLY_FX_X5, - S_HOLY_FX_X6, - S_HOLY_TAIL1, - S_HOLY_TAIL2, - S_HOLY_PUFF1, - S_HOLY_PUFF2, - S_HOLY_PUFF3, - S_HOLY_PUFF4, - S_HOLY_PUFF5, - S_HOLY_MISSILE1, - S_HOLY_MISSILE2, - S_HOLY_MISSILE3, - S_HOLY_MISSILE4, - S_HOLY_MISSILE_X, - S_HOLY_MISSILE_P1, - S_HOLY_MISSILE_P2, - S_HOLY_MISSILE_P3, - S_HOLY_MISSILE_P4, - S_HOLY_MISSILE_P5, - S_MWANDREADY, - S_MWANDDOWN, - S_MWANDUP, - S_MWANDATK_1, - S_MWANDATK_2, - S_MWANDATK_3, - S_MWANDATK_4, - S_MWANDPUFF1, - S_MWANDPUFF2, - S_MWANDPUFF3, - S_MWANDPUFF4, - S_MWANDPUFF5, - S_MWANDSMOKE1, - S_MWANDSMOKE2, - S_MWANDSMOKE3, - S_MWANDSMOKE4, - S_MWAND_MISSILE1, - S_MWAND_MISSILE2, - S_MW_LIGHTNING1, - S_MW_LIGHTNING2, - S_MW_LIGHTNING3, - S_MW_LIGHTNING4, - S_MW_LIGHTNING5, - S_MW_LIGHTNING6, - S_MW_LIGHTNING7, - S_MW_LIGHTNING8, - S_MLIGHTNINGREADY, - S_MLIGHTNINGREADY2, - S_MLIGHTNINGREADY3, - S_MLIGHTNINGREADY4, - S_MLIGHTNINGREADY5, - S_MLIGHTNINGREADY6, - S_MLIGHTNINGREADY7, - S_MLIGHTNINGREADY8, - S_MLIGHTNINGREADY9, - S_MLIGHTNINGREADY10, - S_MLIGHTNINGREADY11, - S_MLIGHTNINGREADY12, - S_MLIGHTNINGREADY13, - S_MLIGHTNINGREADY14, - S_MLIGHTNINGREADY15, - S_MLIGHTNINGREADY16, - S_MLIGHTNINGREADY17, - S_MLIGHTNINGREADY18, - S_MLIGHTNINGREADY19, - S_MLIGHTNINGREADY20, - S_MLIGHTNINGREADY21, - S_MLIGHTNINGREADY22, - S_MLIGHTNINGREADY23, - S_MLIGHTNINGREADY24, - S_MLIGHTNINGDOWN, - S_MLIGHTNINGUP, - S_MLIGHTNINGATK_1, - S_MLIGHTNINGATK_2, - S_MLIGHTNINGATK_3, - S_MLIGHTNINGATK_4, - S_MLIGHTNINGATK_5, - S_MLIGHTNINGATK_6, - S_MLIGHTNINGATK_7, - S_MLIGHTNINGATK_8, - S_MLIGHTNINGATK_9, - S_MLIGHTNINGATK_10, - S_MLIGHTNINGATK_11, - S_LIGHTNING_CEILING1, - S_LIGHTNING_CEILING2, - S_LIGHTNING_CEILING3, - S_LIGHTNING_CEILING4, - S_LIGHTNING_C_X1, - S_LIGHTNING_C_X2, - S_LIGHTNING_C_X3, - S_LIGHTNING_C_X4, - S_LIGHTNING_C_X5, - S_LIGHTNING_C_X6, - S_LIGHTNING_C_X7, - S_LIGHTNING_C_X8, - S_LIGHTNING_C_X9, - S_LIGHTNING_C_X10, - S_LIGHTNING_C_X11, - S_LIGHTNING_C_X12, - S_LIGHTNING_C_X13, - S_LIGHTNING_C_X14, - S_LIGHTNING_C_X15, - S_LIGHTNING_C_X16, - S_LIGHTNING_C_X17, - S_LIGHTNING_C_X18, - S_LIGHTNING_C_X19, - S_LIGHTNING_FLOOR1, - S_LIGHTNING_FLOOR2, - S_LIGHTNING_FLOOR3, - S_LIGHTNING_FLOOR4, - S_LIGHTNING_F_X1, - S_LIGHTNING_F_X2, - S_LIGHTNING_F_X3, - S_LIGHTNING_F_X4, - S_LIGHTNING_F_X5, - S_LIGHTNING_F_X6, - S_LIGHTNING_F_X7, - S_LIGHTNING_F_X8, - S_LIGHTNING_F_X9, - S_LIGHTNING_F_X10, - S_LIGHTNING_F_X11, - S_LIGHTNING_F_X12, - S_LIGHTNING_F_X13, - S_LIGHTNING_F_X14, - S_LIGHTNING_F_X15, - S_LIGHTNING_F_X16, - S_LIGHTNING_F_X17, - S_LIGHTNING_F_X18, - S_LIGHTNING_F_X19, - S_LIGHTNING_ZAP1, - S_LIGHTNING_ZAP2, - S_LIGHTNING_ZAP3, - S_LIGHTNING_ZAP4, - S_LIGHTNING_ZAP5, - S_LIGHTNING_ZAP_X1, - S_LIGHTNING_ZAP_X2, - S_LIGHTNING_ZAP_X3, - S_LIGHTNING_ZAP_X4, - S_LIGHTNING_ZAP_X5, - S_LIGHTNING_ZAP_X6, - S_LIGHTNING_ZAP_X7, - S_LIGHTNING_ZAP_X8, - S_MSTAFFREADY, - S_MSTAFFREADY2, - S_MSTAFFREADY3, - S_MSTAFFREADY4, - S_MSTAFFREADY5, - S_MSTAFFREADY6, - S_MSTAFFREADY7, - S_MSTAFFREADY8, - S_MSTAFFREADY9, - S_MSTAFFREADY10, - S_MSTAFFREADY11, - S_MSTAFFREADY12, - S_MSTAFFREADY13, - S_MSTAFFREADY14, - S_MSTAFFREADY15, - S_MSTAFFREADY16, - S_MSTAFFREADY17, - S_MSTAFFREADY18, - S_MSTAFFREADY19, - S_MSTAFFREADY20, - S_MSTAFFREADY21, - S_MSTAFFREADY22, - S_MSTAFFREADY23, - S_MSTAFFREADY24, - S_MSTAFFREADY25, - S_MSTAFFREADY26, - S_MSTAFFREADY27, - S_MSTAFFREADY28, - S_MSTAFFREADY29, - S_MSTAFFREADY30, - S_MSTAFFREADY31, - S_MSTAFFREADY32, - S_MSTAFFREADY33, - S_MSTAFFREADY34, - S_MSTAFFREADY35, - S_MSTAFFDOWN, - S_MSTAFFUP, - S_MSTAFFATK_1, - S_MSTAFFATK_2, - S_MSTAFFATK_3, - S_MSTAFFATK_4, - S_MSTAFFATK_5, - S_MSTAFFATK_6, - S_MSTAFFATK_7, - S_MSTAFF_FX1_1, - S_MSTAFF_FX1_2, - S_MSTAFF_FX1_3, - S_MSTAFF_FX1_4, - S_MSTAFF_FX1_5, - S_MSTAFF_FX1_6, - S_MSTAFF_FX_X1, - S_MSTAFF_FX_X2, - S_MSTAFF_FX_X3, - S_MSTAFF_FX_X4, - S_MSTAFF_FX_X5, - S_MSTAFF_FX_X6, - S_MSTAFF_FX_X7, - S_MSTAFF_FX_X8, - S_MSTAFF_FX_X9, - S_MSTAFF_FX_X10, - S_MSTAFF_FX2_1, - S_MSTAFF_FX2_2, - S_MSTAFF_FX2_3, - S_MSTAFF_FX2_4, - S_MSTAFF_FX2_X1, - S_MSTAFF_FX2_X2, - S_MSTAFF_FX2_X3, - S_MSTAFF_FX2_X4, - S_MSTAFF_FX2_X5, - S_FSWORD1, - S_FSWORD2, - S_FSWORD3, - S_CHOLY1, - S_CHOLY2, - S_CHOLY3, - S_MSTAFF1, - S_MSTAFF2, - S_MSTAFF3, - S_SNOUTREADY, - S_SNOUTDOWN, - S_SNOUTUP, - S_SNOUTATK1, - S_SNOUTATK2, - S_COS1, - S_COS2, - S_COS3, - S_CONEREADY, - S_CONEDOWN, - S_CONEUP, - S_CONEATK1_1, - S_CONEATK1_2, - S_CONEATK1_3, - S_CONEATK1_4, - S_CONEATK1_5, - S_CONEATK1_6, - S_CONEATK1_7, - S_CONEATK1_8, - S_SHARDFX1_1, - S_SHARDFX1_2, - S_SHARDFX1_3, - S_SHARDFX1_4, - S_SHARDFXE1_1, - S_SHARDFXE1_2, - S_SHARDFXE1_3, - S_SHARDFXE1_4, - S_SHARDFXE1_5, - S_BLOOD1, - S_BLOOD2, - S_BLOOD3, - S_BLOODSPLATTER1, - S_BLOODSPLATTER2, - S_BLOODSPLATTER3, - S_BLOODSPLATTERX, - S_GIBS1, - S_FPLAY, - S_FPLAY_RUN1, - S_FPLAY_RUN2, - S_FPLAY_RUN3, - S_FPLAY_RUN4, - S_FPLAY_ATK1, - S_FPLAY_ATK2, - S_FPLAY_PAIN, - S_FPLAY_PAIN2, - S_FPLAY_DIE1, - S_FPLAY_DIE2, - S_FPLAY_DIE3, - S_FPLAY_DIE4, - S_FPLAY_DIE5, - S_FPLAY_DIE6, - S_FPLAY_DIE7, - S_FPLAY_XDIE1, - S_FPLAY_XDIE2, - S_FPLAY_XDIE3, - S_FPLAY_XDIE4, - S_FPLAY_XDIE5, - S_FPLAY_XDIE6, - S_FPLAY_XDIE7, - S_FPLAY_XDIE8, - S_FPLAY_ICE, - S_FPLAY_ICE2, - S_PLAY_F_FDTH1, - S_PLAY_F_FDTH2, - S_PLAY_C_FDTH1, - S_PLAY_C_FDTH2, - S_PLAY_M_FDTH1, - S_PLAY_M_FDTH2, - S_PLAY_FDTH3, - S_PLAY_FDTH4, - S_PLAY_FDTH5, - S_PLAY_FDTH6, - S_PLAY_FDTH7, - S_PLAY_FDTH8, - S_PLAY_FDTH9, - S_PLAY_FDTH10, - S_PLAY_FDTH11, - S_PLAY_FDTH12, - S_PLAY_FDTH13, - S_PLAY_FDTH14, - S_PLAY_FDTH15, - S_PLAY_FDTH16, - S_PLAY_FDTH17, - S_PLAY_FDTH18, - S_PLAY_FDTH19, - S_PLAY_FDTH20, - S_BLOODYSKULL1, - S_BLOODYSKULL2, - S_BLOODYSKULL3, - S_BLOODYSKULL4, - S_BLOODYSKULL5, - S_BLOODYSKULL6, - S_BLOODYSKULL7, - S_BLOODYSKULLX1, - S_BLOODYSKULLX2, - S_PLAYER_SPEED1, - S_PLAYER_SPEED2, - S_ICECHUNK1, - S_ICECHUNK2, - S_ICECHUNK3, - S_ICECHUNK4, - S_ICECHUNK_HEAD, - S_ICECHUNK_HEAD2, - S_CPLAY, - S_CPLAY_RUN1, - S_CPLAY_RUN2, - S_CPLAY_RUN3, - S_CPLAY_RUN4, - S_CPLAY_ATK1, - S_CPLAY_ATK2, - S_CPLAY_ATK3, - S_CPLAY_PAIN, - S_CPLAY_PAIN2, - S_CPLAY_DIE1, - S_CPLAY_DIE2, - S_CPLAY_DIE3, - S_CPLAY_DIE4, - S_CPLAY_DIE5, - S_CPLAY_DIE6, - S_CPLAY_DIE7, - S_CPLAY_DIE8, - S_CPLAY_DIE9, - S_CPLAY_XDIE1, - S_CPLAY_XDIE2, - S_CPLAY_XDIE3, - S_CPLAY_XDIE4, - S_CPLAY_XDIE5, - S_CPLAY_XDIE6, - S_CPLAY_XDIE7, - S_CPLAY_XDIE8, - S_CPLAY_XDIE9, - S_CPLAY_XDIE10, - S_CPLAY_ICE, - S_CPLAY_ICE2, - S_MPLAY, - S_MPLAY_RUN1, - S_MPLAY_RUN2, - S_MPLAY_RUN3, - S_MPLAY_RUN4, - S_MPLAY_ATK1, - S_MPLAY_ATK2, - S_MPLAY_PAIN, - S_MPLAY_PAIN2, - S_MPLAY_DIE1, - S_MPLAY_DIE2, - S_MPLAY_DIE3, - S_MPLAY_DIE4, - S_MPLAY_DIE5, - S_MPLAY_DIE6, - S_MPLAY_DIE7, - S_MPLAY_XDIE1, - S_MPLAY_XDIE2, - S_MPLAY_XDIE3, - S_MPLAY_XDIE4, - S_MPLAY_XDIE5, - S_MPLAY_XDIE6, - S_MPLAY_XDIE7, - S_MPLAY_XDIE8, - S_MPLAY_XDIE9, - S_MPLAY_ICE, - S_MPLAY_ICE2, - S_PIGPLAY, - S_PIGPLAY_RUN1, - S_PIGPLAY_RUN2, - S_PIGPLAY_RUN3, - S_PIGPLAY_RUN4, - S_PIGPLAY_ATK1, - S_PIGPLAY_PAIN, - S_PIG_LOOK1, - S_PIG_WALK1, - S_PIG_WALK2, - S_PIG_WALK3, - S_PIG_WALK4, - S_PIG_PAIN, - S_PIG_ATK1, - S_PIG_ATK2, - S_PIG_DIE1, - S_PIG_DIE2, - S_PIG_DIE3, - S_PIG_DIE4, - S_PIG_DIE5, - S_PIG_DIE6, - S_PIG_DIE7, - S_PIG_DIE8, - S_PIG_ICE, - S_PIG_ICE2, - S_CENTAUR_LOOK1, - S_CENTAUR_LOOK2, - S_CENTAUR_WALK1, - S_CENTAUR_WALK2, - S_CENTAUR_WALK3, - S_CENTAUR_WALK4, - S_CENTAUR_ATK1, - S_CENTAUR_ATK2, - S_CENTAUR_ATK3, - S_CENTAUR_MISSILE1, - S_CENTAUR_MISSILE2, - S_CENTAUR_MISSILE3, - S_CENTAUR_MISSILE4, - S_CENTAUR_PAIN1, - S_CENTAUR_PAIN2, - S_CENTAUR_PAIN3, - S_CENTAUR_PAIN4, - S_CENTAUR_PAIN5, - S_CENTAUR_PAIN6, - S_CENTAUR_DEATH1, - S_CENTAUR_DEATH2, - S_CENTAUR_DEATH3, - S_CENTAUR_DEATH4, - S_CENTAUR_DEATH5, - S_CENTAUR_DEATH6, - S_CENTAUR_DEATH7, - S_CENTAUR_DEATH8, - S_CENTAUR_DEATH9, - S_CENTAUR_DEATH0, - S_CENTAUR_DEATH_X1, - S_CENTAUR_DEATH_X2, - S_CENTAUR_DEATH_X3, - S_CENTAUR_DEATH_X4, - S_CENTAUR_DEATH_X5, - S_CENTAUR_DEATH_X6, - S_CENTAUR_DEATH_X7, - S_CENTAUR_DEATH_X8, - S_CENTAUR_DEATH_X9, - S_CENTAUR_DEATH_X10, - S_CENTAUR_DEATH_X11, - S_CENTAUR_ICE, - S_CENTAUR_ICE2, - S_CENTAUR_FX1, - S_CENTAUR_FX_X1, - S_CENTAUR_FX_X2, - S_CENTAUR_FX_X3, - S_CENTAUR_FX_X4, - S_CENTAUR_FX_X5, - S_CENTAUR_SHIELD1, - S_CENTAUR_SHIELD2, - S_CENTAUR_SHIELD3, - S_CENTAUR_SHIELD4, - S_CENTAUR_SHIELD5, - S_CENTAUR_SHIELD6, - S_CENTAUR_SHIELD_X1, - S_CENTAUR_SHIELD_X2, - S_CENTAUR_SHIELD_X3, - S_CENTAUR_SHIELD_X4, - S_CENTAUR_SWORD1, - S_CENTAUR_SWORD2, - S_CENTAUR_SWORD3, - S_CENTAUR_SWORD4, - S_CENTAUR_SWORD5, - S_CENTAUR_SWORD6, - S_CENTAUR_SWORD7, - S_CENTAUR_SWORD_X1, - S_CENTAUR_SWORD_X2, - S_CENTAUR_SWORD_X3, - S_DEMN_LOOK1, - S_DEMN_LOOK2, - S_DEMN_CHASE1, - S_DEMN_CHASE2, - S_DEMN_CHASE3, - S_DEMN_CHASE4, - S_DEMN_ATK1_1, - S_DEMN_ATK1_2, - S_DEMN_ATK1_3, - S_DEMN_ATK2_1, - S_DEMN_ATK2_2, - S_DEMN_ATK2_3, - S_DEMN_PAIN1, - S_DEMN_PAIN2, - S_DEMN_DEATH1, - S_DEMN_DEATH2, - S_DEMN_DEATH3, - S_DEMN_DEATH4, - S_DEMN_DEATH5, - S_DEMN_DEATH6, - S_DEMN_DEATH7, - S_DEMN_DEATH8, - S_DEMN_DEATH9, - S_DEMN_XDEATH1, - S_DEMN_XDEATH2, - S_DEMN_XDEATH3, - S_DEMN_XDEATH4, - S_DEMN_XDEATH5, - S_DEMN_XDEATH6, - S_DEMN_XDEATH7, - S_DEMN_XDEATH8, - S_DEMN_XDEATH9, - S_DEMON_ICE, - S_DEMON_ICE2, - S_DEMONCHUNK1_1, - S_DEMONCHUNK1_2, - S_DEMONCHUNK1_3, - S_DEMONCHUNK1_4, - S_DEMONCHUNK2_1, - S_DEMONCHUNK2_2, - S_DEMONCHUNK2_3, - S_DEMONCHUNK2_4, - S_DEMONCHUNK3_1, - S_DEMONCHUNK3_2, - S_DEMONCHUNK3_3, - S_DEMONCHUNK3_4, - S_DEMONCHUNK4_1, - S_DEMONCHUNK4_2, - S_DEMONCHUNK4_3, - S_DEMONCHUNK4_4, - S_DEMONCHUNK5_1, - S_DEMONCHUNK5_2, - S_DEMONCHUNK5_3, - S_DEMONCHUNK5_4, - S_DEMONFX_MOVE1, - S_DEMONFX_MOVE2, - S_DEMONFX_MOVE3, - S_DEMONFX_BOOM1, - S_DEMONFX_BOOM2, - S_DEMONFX_BOOM3, - S_DEMONFX_BOOM4, - S_DEMONFX_BOOM5, - S_DEMN2_LOOK1, - S_DEMN2_LOOK2, - S_DEMN2_CHASE1, - S_DEMN2_CHASE2, - S_DEMN2_CHASE3, - S_DEMN2_CHASE4, - S_DEMN2_ATK1_1, - S_DEMN2_ATK1_2, - S_DEMN2_ATK1_3, - S_DEMN2_ATK2_1, - S_DEMN2_ATK2_2, - S_DEMN2_ATK2_3, - S_DEMN2_PAIN1, - S_DEMN2_PAIN2, - S_DEMN2_DEATH1, - S_DEMN2_DEATH2, - S_DEMN2_DEATH3, - S_DEMN2_DEATH4, - S_DEMN2_DEATH5, - S_DEMN2_DEATH6, - S_DEMN2_DEATH7, - S_DEMN2_DEATH8, - S_DEMN2_DEATH9, - S_DEMN2_XDEATH1, - S_DEMN2_XDEATH2, - S_DEMN2_XDEATH3, - S_DEMN2_XDEATH4, - S_DEMN2_XDEATH5, - S_DEMN2_XDEATH6, - S_DEMN2_XDEATH7, - S_DEMN2_XDEATH8, - S_DEMN2_XDEATH9, - S_DEMON2CHUNK1_1, - S_DEMON2CHUNK1_2, - S_DEMON2CHUNK1_3, - S_DEMON2CHUNK1_4, - S_DEMON2CHUNK2_1, - S_DEMON2CHUNK2_2, - S_DEMON2CHUNK2_3, - S_DEMON2CHUNK2_4, - S_DEMON2CHUNK3_1, - S_DEMON2CHUNK3_2, - S_DEMON2CHUNK3_3, - S_DEMON2CHUNK3_4, - S_DEMON2CHUNK4_1, - S_DEMON2CHUNK4_2, - S_DEMON2CHUNK4_3, - S_DEMON2CHUNK4_4, - S_DEMON2CHUNK5_1, - S_DEMON2CHUNK5_2, - S_DEMON2CHUNK5_3, - S_DEMON2CHUNK5_4, - S_DEMON2FX_MOVE1, - S_DEMON2FX_MOVE2, - S_DEMON2FX_MOVE3, - S_DEMON2FX_MOVE4, - S_DEMON2FX_MOVE5, - S_DEMON2FX_MOVE6, - S_DEMON2FX_BOOM1, - S_DEMON2FX_BOOM2, - S_DEMON2FX_BOOM3, - S_DEMON2FX_BOOM4, - S_DEMON2FX_BOOM5, - S_DEMON2FX_BOOM6, - S_WRAITH_RAISE1, - S_WRAITH_RAISE2, - S_WRAITH_RAISE3, - S_WRAITH_RAISE4, - S_WRAITH_RAISE5, - S_WRAITH_INIT1, - S_WRAITH_INIT2, - S_WRAITH_LOOK1, - S_WRAITH_LOOK2, - S_WRAITH_CHASE1, - S_WRAITH_CHASE2, - S_WRAITH_CHASE3, - S_WRAITH_CHASE4, - S_WRAITH_ATK1_1, - S_WRAITH_ATK1_2, - S_WRAITH_ATK1_3, - S_WRAITH_ATK2_1, - S_WRAITH_ATK2_2, - S_WRAITH_ATK2_3, - S_WRAITH_PAIN1, - S_WRAITH_PAIN2, - S_WRAITH_DEATH1_1, - S_WRAITH_DEATH1_2, - S_WRAITH_DEATH1_3, - S_WRAITH_DEATH1_4, - S_WRAITH_DEATH1_5, - S_WRAITH_DEATH1_6, - S_WRAITH_DEATH1_7, - S_WRAITH_DEATH1_8, - S_WRAITH_DEATH1_9, - S_WRAITH_DEATH1_0, - S_WRAITH_DEATH2_1, - S_WRAITH_DEATH2_2, - S_WRAITH_DEATH2_3, - S_WRAITH_DEATH2_4, - S_WRAITH_DEATH2_5, - S_WRAITH_DEATH2_6, - S_WRAITH_DEATH2_7, - S_WRAITH_DEATH2_8, - S_WRAITH_ICE, - S_WRAITH_ICE2, - S_WRTHFX_MOVE1, - S_WRTHFX_MOVE2, - S_WRTHFX_MOVE3, - S_WRTHFX_BOOM1, - S_WRTHFX_BOOM2, - S_WRTHFX_BOOM3, - S_WRTHFX_BOOM4, - S_WRTHFX_BOOM5, - S_WRTHFX_BOOM6, - S_WRTHFX_SIZZLE1, - S_WRTHFX_SIZZLE2, - S_WRTHFX_SIZZLE3, - S_WRTHFX_SIZZLE4, - S_WRTHFX_SIZZLE5, - S_WRTHFX_SIZZLE6, - S_WRTHFX_SIZZLE7, - S_WRTHFX_DROP1, - S_WRTHFX_DROP2, - S_WRTHFX_DROP3, - S_WRTHFX_DEAD1, - S_WRTHFX_ADROP1, - S_WRTHFX_ADROP2, - S_WRTHFX_ADROP3, - S_WRTHFX_ADROP4, - S_WRTHFX_ADEAD1, - S_WRTHFX_BDROP1, - S_WRTHFX_BDROP2, - S_WRTHFX_BDROP3, - S_WRTHFX_BDEAD1, - S_MNTR_SPAWN1, - S_MNTR_SPAWN2, - S_MNTR_SPAWN3, - S_MNTR_LOOK1, - S_MNTR_LOOK2, - S_MNTR_WALK1, - S_MNTR_WALK2, - S_MNTR_WALK3, - S_MNTR_WALK4, - S_MNTR_ROAM1, - S_MNTR_ROAM2, - S_MNTR_ROAM3, - S_MNTR_ROAM4, - S_MNTR_ATK1_1, - S_MNTR_ATK1_2, - S_MNTR_ATK1_3, - S_MNTR_ATK2_1, - S_MNTR_ATK2_2, - S_MNTR_ATK2_3, - S_MNTR_ATK3_1, - S_MNTR_ATK3_2, - S_MNTR_ATK3_3, - S_MNTR_ATK3_4, - S_MNTR_ATK4_1, - S_MNTR_PAIN1, - S_MNTR_PAIN2, - S_MNTR_DIE1, - S_MNTR_DIE2, - S_MNTR_DIE3, - S_MNTR_DIE4, - S_MNTR_DIE5, - S_MNTR_DIE6, - S_MNTR_DIE7, - S_MNTR_DIE8, - S_MNTR_DIE9, - S_MNTRFX1_1, - S_MNTRFX1_2, - S_MNTRFXI1_1, - S_MNTRFXI1_2, - S_MNTRFXI1_3, - S_MNTRFXI1_4, - S_MNTRFXI1_5, - S_MNTRFXI1_6, - S_MNTRFX2_1, - S_MNTRFXI2_1, - S_MNTRFXI2_2, - S_MNTRFXI2_3, - S_MNTRFXI2_4, - S_MNTRFXI2_5, - S_MNTRFX3_1, - S_MNTRFX3_2, - S_MNTRFX3_3, - S_MNTRFX3_4, - S_MNTRFX3_5, - S_MNTRFX3_6, - S_MNTRFX3_7, - S_MNTRFX3_8, - S_MNTRFX3_9, - S_MINOSMOKE1, - S_MINOSMOKE2, - S_MINOSMOKE3, - S_MINOSMOKE4, - S_MINOSMOKE5, - S_MINOSMOKE6, - S_MINOSMOKE7, - S_MINOSMOKE8, - S_MINOSMOKE9, - S_MINOSMOKE0, - S_MINOSMOKEA, - S_MINOSMOKEB, - S_MINOSMOKEC, - S_MINOSMOKED, - S_MINOSMOKEE, - S_MINOSMOKEF, - S_MINOSMOKEG, - S_MINOSMOKEX1, - S_MINOSMOKEX2, - S_MINOSMOKEX3, - S_MINOSMOKEX4, - S_MINOSMOKEX5, - S_MINOSMOKEX6, - S_MINOSMOKEX7, - S_MINOSMOKEX8, - S_MINOSMOKEX9, - S_MINOSMOKEX0, - S_MINOSMOKEXA, - S_MINOSMOKEXB, - S_MINOSMOKEXC, - S_MINOSMOKEXD, - S_MINOSMOKEXE, - S_MINOSMOKEXF, - S_MINOSMOKEXG, - S_MINOSMOKEXH, - S_MINOSMOKEXI, - S_SERPENT_LOOK1, - S_SERPENT_SWIM1, - S_SERPENT_SWIM2, - S_SERPENT_SWIM3, - S_SERPENT_HUMP1, - S_SERPENT_HUMP2, - S_SERPENT_HUMP3, - S_SERPENT_HUMP4, - S_SERPENT_HUMP5, - S_SERPENT_HUMP6, - S_SERPENT_HUMP7, - S_SERPENT_HUMP8, - S_SERPENT_HUMP9, - S_SERPENT_HUMP10, - S_SERPENT_HUMP11, - S_SERPENT_HUMP12, - S_SERPENT_HUMP13, - S_SERPENT_HUMP14, - S_SERPENT_HUMP15, - S_SERPENT_SURFACE1, - S_SERPENT_SURFACE2, - S_SERPENT_SURFACE3, - S_SERPENT_SURFACE4, - S_SERPENT_SURFACE5, - S_SERPENT_DIVE1, - S_SERPENT_DIVE2, - S_SERPENT_DIVE3, - S_SERPENT_DIVE4, - S_SERPENT_DIVE5, - S_SERPENT_DIVE6, - S_SERPENT_DIVE7, - S_SERPENT_DIVE8, - S_SERPENT_DIVE9, - S_SERPENT_DIVE10, - S_SERPENT_WALK1, - S_SERPENT_WALK2, - S_SERPENT_WALK3, - S_SERPENT_WALK4, - S_SERPENT_PAIN1, - S_SERPENT_PAIN2, - S_SERPENT_ATK1, - S_SERPENT_ATK2, - S_SERPENT_MELEE1, - S_SERPENT_MISSILE1, - S_SERPENT_DIE1, - S_SERPENT_DIE2, - S_SERPENT_DIE3, - S_SERPENT_DIE4, - S_SERPENT_DIE5, - S_SERPENT_DIE6, - S_SERPENT_DIE7, - S_SERPENT_DIE8, - S_SERPENT_DIE9, - S_SERPENT_DIE10, - S_SERPENT_DIE11, - S_SERPENT_DIE12, - S_SERPENT_XDIE1, - S_SERPENT_XDIE2, - S_SERPENT_XDIE3, - S_SERPENT_XDIE4, - S_SERPENT_XDIE5, - S_SERPENT_XDIE6, - S_SERPENT_XDIE7, - S_SERPENT_XDIE8, - S_SERPENT_ICE, - S_SERPENT_ICE2, - S_SERPENT_FX1, - S_SERPENT_FX2, - S_SERPENT_FX3, - S_SERPENT_FX4, - S_SERPENT_FX_X1, - S_SERPENT_FX_X2, - S_SERPENT_FX_X3, - S_SERPENT_FX_X4, - S_SERPENT_FX_X5, - S_SERPENT_FX_X6, - S_SERPENT_HEAD1, - S_SERPENT_HEAD2, - S_SERPENT_HEAD3, - S_SERPENT_HEAD4, - S_SERPENT_HEAD5, - S_SERPENT_HEAD6, - S_SERPENT_HEAD7, - S_SERPENT_HEAD8, - S_SERPENT_HEAD_X1, - S_SERPENT_GIB1_1, - S_SERPENT_GIB1_2, - S_SERPENT_GIB1_3, - S_SERPENT_GIB1_4, - S_SERPENT_GIB1_5, - S_SERPENT_GIB1_6, - S_SERPENT_GIB1_7, - S_SERPENT_GIB1_8, - S_SERPENT_GIB1_9, - S_SERPENT_GIB1_10, - S_SERPENT_GIB1_11, - S_SERPENT_GIB1_12, - S_SERPENT_GIB2_1, - S_SERPENT_GIB2_2, - S_SERPENT_GIB2_3, - S_SERPENT_GIB2_4, - S_SERPENT_GIB2_5, - S_SERPENT_GIB2_6, - S_SERPENT_GIB2_7, - S_SERPENT_GIB2_8, - S_SERPENT_GIB2_9, - S_SERPENT_GIB2_10, - S_SERPENT_GIB2_11, - S_SERPENT_GIB2_12, - S_SERPENT_GIB3_1, - S_SERPENT_GIB3_2, - S_SERPENT_GIB3_3, - S_SERPENT_GIB3_4, - S_SERPENT_GIB3_5, - S_SERPENT_GIB3_6, - S_SERPENT_GIB3_7, - S_SERPENT_GIB3_8, - S_SERPENT_GIB3_9, - S_SERPENT_GIB3_10, - S_SERPENT_GIB3_11, - S_SERPENT_GIB3_12, - S_BISHOP_LOOK1, - S_BISHOP_DECIDE, - S_BISHOP_BLUR1, - S_BISHOP_BLUR2, - S_BISHOP_WALK1, - S_BISHOP_WALK2, - S_BISHOP_WALK3, - S_BISHOP_WALK4, - S_BISHOP_WALK5, - S_BISHOP_WALK6, - S_BISHOP_ATK1, - S_BISHOP_ATK2, - S_BISHOP_ATK3, - S_BISHOP_ATK4, - S_BISHOP_ATK5, - S_BISHOP_PAIN1, - S_BISHOP_PAIN2, - S_BISHOP_PAIN3, - S_BISHOP_PAIN4, - S_BISHOP_PAIN5, - S_BISHOP_DEATH1, - S_BISHOP_DEATH2, - S_BISHOP_DEATH3, - S_BISHOP_DEATH4, - S_BISHOP_DEATH5, - S_BISHOP_DEATH6, - S_BISHOP_DEATH7, - S_BISHOP_DEATH8, - S_BISHOP_DEATH9, - S_BISHOP_DEATH10, - S_BISHOP_ICE, - S_BISHOP_ICE2, - S_BISHOP_PUFF1, - S_BISHOP_PUFF2, - S_BISHOP_PUFF3, - S_BISHOP_PUFF4, - S_BISHOP_PUFF5, - S_BISHOP_PUFF6, - S_BISHOP_PUFF7, - S_BISHOPBLUR1, - S_BISHOPBLUR2, - S_BISHOPPAINBLUR1, - S_BISHFX1_1, - S_BISHFX1_2, - S_BISHFX1_3, - S_BISHFX1_4, - S_BISHFX1_5, - S_BISHFXI1_1, - S_BISHFXI1_2, - S_BISHFXI1_3, - S_BISHFXI1_4, - S_BISHFXI1_5, - S_BISHFXI1_6, - S_DRAGON_LOOK1, - S_DRAGON_INIT, - S_DRAGON_INIT2, - S_DRAGON_INIT3, - S_DRAGON_WALK1, - S_DRAGON_WALK2, - S_DRAGON_WALK3, - S_DRAGON_WALK4, - S_DRAGON_WALK5, - S_DRAGON_WALK6, - S_DRAGON_WALK7, - S_DRAGON_WALK8, - S_DRAGON_WALK9, - S_DRAGON_WALK10, - S_DRAGON_WALK11, - S_DRAGON_WALK12, - S_DRAGON_ATK1, - S_DRAGON_PAIN1, - S_DRAGON_DEATH1, - S_DRAGON_DEATH2, - S_DRAGON_DEATH3, - S_DRAGON_DEATH4, - S_DRAGON_CRASH1, - S_DRAGON_CRASH2, - S_DRAGON_CRASH3, - S_DRAGON_FX1_1, - S_DRAGON_FX1_2, - S_DRAGON_FX1_3, - S_DRAGON_FX1_4, - S_DRAGON_FX1_5, - S_DRAGON_FX1_6, - S_DRAGON_FX1_X1, - S_DRAGON_FX1_X2, - S_DRAGON_FX1_X3, - S_DRAGON_FX1_X4, - S_DRAGON_FX1_X5, - S_DRAGON_FX1_X6, - S_DRAGON_FX2_1, - S_DRAGON_FX2_2, - S_DRAGON_FX2_3, - S_DRAGON_FX2_4, - S_DRAGON_FX2_5, - S_DRAGON_FX2_6, - S_DRAGON_FX2_7, - S_DRAGON_FX2_8, - S_DRAGON_FX2_9, - S_DRAGON_FX2_10, - S_DRAGON_FX2_11, - S_ARMOR_1, - S_ARMOR_2, - S_ARMOR_3, - S_ARMOR_4, - S_MANA1_1, - S_MANA1_2, - S_MANA1_3, - S_MANA1_4, - S_MANA1_5, - S_MANA1_6, - S_MANA1_7, - S_MANA1_8, - S_MANA1_9, - S_MANA2_1, - S_MANA2_2, - S_MANA2_3, - S_MANA2_4, - S_MANA2_5, - S_MANA2_6, - S_MANA2_7, - S_MANA2_8, - S_MANA2_9, - S_MANA2_10, - S_MANA2_11, - S_MANA2_12, - S_MANA2_13, - S_MANA2_14, - S_MANA2_15, - S_MANA2_16, - S_MANA3_1, - S_MANA3_2, - S_MANA3_3, - S_MANA3_4, - S_MANA3_5, - S_MANA3_6, - S_MANA3_7, - S_MANA3_8, - S_MANA3_9, - S_MANA3_10, - S_MANA3_11, - S_MANA3_12, - S_MANA3_13, - S_MANA3_14, - S_MANA3_15, - S_MANA3_16, - S_KEY1, - S_KEY2, - S_KEY3, - S_KEY4, - S_KEY5, - S_KEY6, - S_KEY7, - S_KEY8, - S_KEY9, - S_KEYA, - S_KEYB, - S_SND_WIND1, - S_SND_WIND2, - S_SND_WATERFALL, - S_ETTIN_LOOK1, - S_ETTIN_LOOK2, - S_ETTIN_CHASE1, - S_ETTIN_CHASE2, - S_ETTIN_CHASE3, - S_ETTIN_CHASE4, - S_ETTIN_PAIN1, - S_ETTIN_ATK1_1, - S_ETTIN_ATK1_2, - S_ETTIN_ATK1_3, - S_ETTIN_DEATH1_1, - S_ETTIN_DEATH1_2, - S_ETTIN_DEATH1_3, - S_ETTIN_DEATH1_4, - S_ETTIN_DEATH1_5, - S_ETTIN_DEATH1_6, - S_ETTIN_DEATH1_7, - S_ETTIN_DEATH1_8, - S_ETTIN_DEATH1_9, - S_ETTIN_DEATH2_1, - S_ETTIN_DEATH2_2, - S_ETTIN_DEATH2_3, - S_ETTIN_DEATH2_4, - S_ETTIN_DEATH2_5, - S_ETTIN_DEATH2_6, - S_ETTIN_DEATH2_7, - S_ETTIN_DEATH2_8, - S_ETTIN_DEATH2_9, - S_ETTIN_DEATH2_0, - S_ETTIN_DEATH2_A, - S_ETTIN_DEATH2_B, - S_ETTIN_ICE1, - S_ETTIN_ICE2, - S_ETTIN_MACE1, - S_ETTIN_MACE2, - S_ETTIN_MACE3, - S_ETTIN_MACE4, - S_ETTIN_MACE5, - S_ETTIN_MACE6, - S_ETTIN_MACE7, - S_FIRED_SPAWN1, - S_FIRED_LOOK1, - S_FIRED_LOOK2, - S_FIRED_LOOK3, - S_FIRED_LOOK4, - S_FIRED_LOOK5, - S_FIRED_LOOK6, - S_FIRED_LOOK7, - S_FIRED_LOOK8, - S_FIRED_LOOK9, - S_FIRED_LOOK0, - S_FIRED_LOOKA, - S_FIRED_LOOKB, - S_FIRED_WALK1, - S_FIRED_WALK2, - S_FIRED_WALK3, - S_FIRED_PAIN1, - S_FIRED_ATTACK1, - S_FIRED_ATTACK2, - S_FIRED_ATTACK3, - S_FIRED_ATTACK4, - S_FIRED_DEATH1, - S_FIRED_DEATH2, - S_FIRED_DEATH3, - S_FIRED_DEATH4, - S_FIRED_XDEATH1, - S_FIRED_XDEATH2, - S_FIRED_XDEATH3, - S_FIRED_ICE1, - S_FIRED_ICE2, - S_FIRED_CORPSE1, - S_FIRED_CORPSE2, - S_FIRED_CORPSE3, - S_FIRED_CORPSE4, - S_FIRED_CORPSE5, - S_FIRED_CORPSE6, - S_FIRED_RDROP1, - S_FIRED_RDEAD1_1, - S_FIRED_RDEAD1_2, - S_FIRED_RDROP2, - S_FIRED_RDEAD2_1, - S_FIRED_RDEAD2_2, - S_FIRED_RDROP3, - S_FIRED_RDEAD3_1, - S_FIRED_RDEAD3_2, - S_FIRED_RDROP4, - S_FIRED_RDEAD4_1, - S_FIRED_RDEAD4_2, - S_FIRED_RDROP5, - S_FIRED_RDEAD5_1, - S_FIRED_RDEAD5_2, - S_FIRED_FX6_1, - S_FIRED_FX6_2, - S_FIRED_FX6_3, - S_FIRED_FX6_4, - S_FIRED_FX6_5, - S_ICEGUY_LOOK, - S_ICEGUY_DORMANT, - S_ICEGUY_WALK1, - S_ICEGUY_WALK2, - S_ICEGUY_WALK3, - S_ICEGUY_WALK4, - S_ICEGUY_ATK1, - S_ICEGUY_ATK2, - S_ICEGUY_ATK3, - S_ICEGUY_ATK4, - S_ICEGUY_PAIN1, - S_ICEGUY_DEATH, - S_ICEGUY_FX1, - S_ICEGUY_FX2, - S_ICEGUY_FX3, - S_ICEGUY_FX_X1, - S_ICEGUY_FX_X2, - S_ICEGUY_FX_X3, - S_ICEGUY_FX_X4, - S_ICEGUY_FX_X5, - S_ICEFX_PUFF1, - S_ICEFX_PUFF2, - S_ICEFX_PUFF3, - S_ICEFX_PUFF4, - S_ICEFX_PUFF5, - S_ICEGUY_FX2_1, - S_ICEGUY_FX2_2, - S_ICEGUY_FX2_3, - S_ICEGUY_BIT1, - S_ICEGUY_BIT2, - S_ICEGUY_WISP1_1, - S_ICEGUY_WISP1_2, - S_ICEGUY_WISP1_3, - S_ICEGUY_WISP1_4, - S_ICEGUY_WISP1_5, - S_ICEGUY_WISP1_6, - S_ICEGUY_WISP1_7, - S_ICEGUY_WISP1_8, - S_ICEGUY_WISP1_9, - S_ICEGUY_WISP2_1, - S_ICEGUY_WISP2_2, - S_ICEGUY_WISP2_3, - S_ICEGUY_WISP2_4, - S_ICEGUY_WISP2_5, - S_ICEGUY_WISP2_6, - S_ICEGUY_WISP2_7, - S_ICEGUY_WISP2_8, - S_ICEGUY_WISP2_9, - S_FIGHTER, - S_FIGHTER2, - S_FIGHTERLOOK, - S_FIGHTER_RUN1, - S_FIGHTER_RUN2, - S_FIGHTER_RUN3, - S_FIGHTER_RUN4, - S_FIGHTER_ATK1, - S_FIGHTER_ATK2, - S_FIGHTER_PAIN, - S_FIGHTER_PAIN2, - S_FIGHTER_DIE1, - S_FIGHTER_DIE2, - S_FIGHTER_DIE3, - S_FIGHTER_DIE4, - S_FIGHTER_DIE5, - S_FIGHTER_DIE6, - S_FIGHTER_DIE7, - S_FIGHTER_XDIE1, - S_FIGHTER_XDIE2, - S_FIGHTER_XDIE3, - S_FIGHTER_XDIE4, - S_FIGHTER_XDIE5, - S_FIGHTER_XDIE6, - S_FIGHTER_XDIE7, - S_FIGHTER_XDIE8, - S_FIGHTER_ICE, - S_FIGHTER_ICE2, - S_CLERIC, - S_CLERIC2, - S_CLERICLOOK, - S_CLERIC_RUN1, - S_CLERIC_RUN2, - S_CLERIC_RUN3, - S_CLERIC_RUN4, - S_CLERIC_ATK1, - S_CLERIC_ATK2, - S_CLERIC_ATK3, - S_CLERIC_PAIN, - S_CLERIC_PAIN2, - S_CLERIC_DIE1, - S_CLERIC_DIE2, - S_CLERIC_DIE3, - S_CLERIC_DIE4, - S_CLERIC_DIE5, - S_CLERIC_DIE6, - S_CLERIC_DIE7, - S_CLERIC_DIE8, - S_CLERIC_DIE9, - S_CLERIC_XDIE1, - S_CLERIC_XDIE2, - S_CLERIC_XDIE3, - S_CLERIC_XDIE4, - S_CLERIC_XDIE5, - S_CLERIC_XDIE6, - S_CLERIC_XDIE7, - S_CLERIC_XDIE8, - S_CLERIC_XDIE9, - S_CLERIC_XDIE10, - S_CLERIC_ICE, - S_CLERIC_ICE2, - S_MAGE, - S_MAGE2, - S_MAGELOOK, - S_MAGE_RUN1, - S_MAGE_RUN2, - S_MAGE_RUN3, - S_MAGE_RUN4, - S_MAGE_ATK1, - S_MAGE_ATK2, - S_MAGE_PAIN, - S_MAGE_PAIN2, - S_MAGE_DIE1, - S_MAGE_DIE2, - S_MAGE_DIE3, - S_MAGE_DIE4, - S_MAGE_DIE5, - S_MAGE_DIE6, - S_MAGE_DIE7, - S_MAGE_XDIE1, - S_MAGE_XDIE2, - S_MAGE_XDIE3, - S_MAGE_XDIE4, - S_MAGE_XDIE5, - S_MAGE_XDIE6, - S_MAGE_XDIE7, - S_MAGE_XDIE8, - S_MAGE_XDIE9, - S_MAGE_ICE, - S_MAGE_ICE2, - S_SORC_SPAWN1, - S_SORC_SPAWN2, - S_SORC_LOOK1, - S_SORC_WALK1, - S_SORC_WALK2, - S_SORC_WALK3, - S_SORC_WALK4, - S_SORC_PAIN1, - S_SORC_PAIN2, - S_SORC_ATK2_1, - S_SORC_ATK2_2, - S_SORC_ATK2_3, - S_SORC_ATTACK1, - S_SORC_ATTACK2, - S_SORC_ATTACK3, - S_SORC_ATTACK4, - S_SORC_ATTACK5, - S_SORC_DIE1, - S_SORC_DIE2, - S_SORC_DIE3, - S_SORC_DIE4, - S_SORC_DIE5, - S_SORC_DIE6, - S_SORC_DIE7, - S_SORC_DIE8, - S_SORC_DIE9, - S_SORC_DIE0, - S_SORC_DIEA, - S_SORC_DIEB, - S_SORC_DIEC, - S_SORC_DIED, - S_SORC_DIEE, - S_SORC_DIEF, - S_SORC_DIEG, - S_SORC_DIEH, - S_SORC_DIEI, - S_SORCBALL1_1, - S_SORCBALL1_2, - S_SORCBALL1_3, - S_SORCBALL1_4, - S_SORCBALL1_5, - S_SORCBALL1_6, - S_SORCBALL1_7, - S_SORCBALL1_8, - S_SORCBALL1_9, - S_SORCBALL1_0, - S_SORCBALL1_A, - S_SORCBALL1_B, - S_SORCBALL1_C, - S_SORCBALL1_D, - S_SORCBALL1_E, - S_SORCBALL1_F, - S_SORCBALL1_D1, - S_SORCBALL1_D2, - S_SORCBALL1_D5, - S_SORCBALL1_D6, - S_SORCBALL1_D7, - S_SORCBALL1_D8, - S_SORCBALL1_D9, - S_SORCBALL2_1, - S_SORCBALL2_2, - S_SORCBALL2_3, - S_SORCBALL2_4, - S_SORCBALL2_5, - S_SORCBALL2_6, - S_SORCBALL2_7, - S_SORCBALL2_8, - S_SORCBALL2_9, - S_SORCBALL2_0, - S_SORCBALL2_A, - S_SORCBALL2_B, - S_SORCBALL2_C, - S_SORCBALL2_D, - S_SORCBALL2_E, - S_SORCBALL2_F, - S_SORCBALL2_D1, - S_SORCBALL2_D2, - S_SORCBALL2_D5, - S_SORCBALL2_D6, - S_SORCBALL2_D7, - S_SORCBALL2_D8, - S_SORCBALL2_D9, - S_SORCBALL3_1, - S_SORCBALL3_2, - S_SORCBALL3_3, - S_SORCBALL3_4, - S_SORCBALL3_5, - S_SORCBALL3_6, - S_SORCBALL3_7, - S_SORCBALL3_8, - S_SORCBALL3_9, - S_SORCBALL3_0, - S_SORCBALL3_A, - S_SORCBALL3_B, - S_SORCBALL3_C, - S_SORCBALL3_D, - S_SORCBALL3_E, - S_SORCBALL3_F, - S_SORCBALL3_D1, - S_SORCBALL3_D2, - S_SORCBALL3_D5, - S_SORCBALL3_D6, - S_SORCBALL3_D7, - S_SORCBALL3_D8, - S_SORCBALL3_D9, - S_SORCFX1_1, - S_SORCFX1_2, - S_SORCFX1_3, - S_SORCFX1_4, - S_SORCFX1_D1, - S_SORCFX1_D2, - S_SORCFX1_D3, - S_SORCFX2_SPLIT1, - S_SORCFX2_ORBIT1, - S_SORCFX2_ORBIT2, - S_SORCFX2_ORBIT3, - S_SORCFX2_ORBIT4, - S_SORCFX2_ORBIT5, - S_SORCFX2_ORBIT6, - S_SORCFX2_ORBIT7, - S_SORCFX2_ORBIT8, - S_SORCFX2_ORBIT9, - S_SORCFX2_ORBIT0, - S_SORCFX2_ORBITA, - S_SORCFX2_ORBITB, - S_SORCFX2_ORBITC, - S_SORCFX2_ORBITD, - S_SORCFX2_ORBITE, - S_SORCFX2_ORBITF, - S_SORCFX2T1, - S_SORCFX3_1, - S_SORCFX3_2, - S_SORCFX3_3, - S_BISHMORPH1, - S_BISHMORPHA, - S_BISHMORPHB, - S_BISHMORPHC, - S_BISHMORPHD, - S_BISHMORPHE, - S_BISHMORPHF, - S_BISHMORPHG, - S_BISHMORPHH, - S_BISHMORPHI, - S_BISHMORPHJ, - S_SORCFX3_EXP1, - S_SORCFX3_EXP2, - S_SORCFX3_EXP3, - S_SORCFX3_EXP4, - S_SORCFX3_EXP5, - S_SORCFX4_1, - S_SORCFX4_2, - S_SORCFX4_3, - S_SORCFX4_D1, - S_SORCFX4_D2, - S_SORCFX4_D3, - S_SORCFX4_D4, - S_SORCFX4_D5, - S_SORCSPARK1, - S_SORCSPARK2, - S_SORCSPARK3, - S_SORCSPARK4, - S_SORCSPARK5, - S_SORCSPARK6, - S_SORCSPARK7, - S_BLASTEFFECT1, - S_BLASTEFFECT2, - S_BLASTEFFECT3, - S_BLASTEFFECT4, - S_BLASTEFFECT5, - S_BLASTEFFECT6, - S_BLASTEFFECT7, - S_BLASTEFFECT8, - S_BLASTEFFECT9, - S_WATERDRIP1, - S_KORAX_LOOK1, - S_KORAX_CHASE1, - S_KORAX_CHASE2, - S_KORAX_CHASE3, - S_KORAX_CHASE4, - S_KORAX_CHASE5, - S_KORAX_CHASE6, - S_KORAX_CHASE7, - S_KORAX_CHASE8, - S_KORAX_CHASE9, - S_KORAX_CHASE0, - S_KORAX_CHASEA, - S_KORAX_CHASEB, - S_KORAX_CHASEC, - S_KORAX_CHASED, - S_KORAX_CHASEE, - S_KORAX_CHASEF, - S_KORAX_PAIN1, - S_KORAX_PAIN2, - S_KORAX_ATTACK1, - S_KORAX_ATTACK2, - S_KORAX_MISSILE1, - S_KORAX_MISSILE2, - S_KORAX_MISSILE3, - S_KORAX_COMMAND1, - S_KORAX_COMMAND2, - S_KORAX_COMMAND3, - S_KORAX_COMMAND4, - S_KORAX_COMMAND5, - S_KORAX_DEATH1, - S_KORAX_DEATH2, - S_KORAX_DEATH3, - S_KORAX_DEATH4, - S_KORAX_DEATH5, - S_KORAX_DEATH6, - S_KORAX_DEATH7, - S_KORAX_DEATH8, - S_KORAX_DEATH9, - S_KORAX_DEATH0, - S_KORAX_DEATHA, - S_KORAX_DEATHB, - S_KORAX_DEATHC, - S_KORAX_DEATHD, - S_KSPIRIT_ROAM1, - S_KSPIRIT_ROAM2, - S_KSPIRIT_DEATH1, - S_KSPIRIT_DEATH2, - S_KSPIRIT_DEATH3, - S_KSPIRIT_DEATH4, - S_KSPIRIT_DEATH5, - S_KSPIRIT_DEATH6, - S_KBOLT1, - S_KBOLT2, - S_KBOLT3, - S_KBOLT4, - S_KBOLT5, - S_KBOLT6, - S_KBOLT7, - S_SPAWNBATS1, - S_SPAWNBATS2, - S_SPAWNBATS3, - S_SPAWNBATS_OFF, - S_BAT1, - S_BAT2, - S_BAT3, - S_BAT_DEATH, - NUMSTATES -} statenum_t; - - -struct mobj_s; -struct player_s; -struct pspdef_s; - - -typedef struct -{ - spritenum_t sprite; - int frame; - int tics; - void (*action) (struct mobj_s *, struct player_s *, struct pspdef_s *); - statenum_t nextstate; - int misc1, misc2; -} state_t; - -extern state_t states[NUMSTATES]; -extern const char *sprnames[]; - - - -typedef enum -{ - MT_MAPSPOT, - MT_MAPSPOTGRAVITY, - MT_FIREBALL1, - MT_ARROW, - MT_DART, - MT_POISONDART, - MT_RIPPERBALL, - MT_PROJECTILE_BLADE, - MT_ICESHARD, - MT_FLAME_SMALL_TEMP, - MT_FLAME_LARGE_TEMP, - MT_FLAME_SMALL, - MT_FLAME_LARGE, - MT_HEALINGBOTTLE, - MT_HEALTHFLASK, - MT_ARTIFLY, - MT_ARTIINVULNERABILITY, - MT_SUMMONMAULATOR, - MT_SUMMON_FX, - MT_THRUSTFLOOR_UP, - MT_THRUSTFLOOR_DOWN, - MT_TELEPORTOTHER, - MT_TELOTHER_FX1, - MT_TELOTHER_FX2, - MT_TELOTHER_FX3, - MT_TELOTHER_FX4, - MT_TELOTHER_FX5, - MT_DIRT1, - MT_DIRT2, - MT_DIRT3, - MT_DIRT4, - MT_DIRT5, - MT_DIRT6, - MT_DIRTCLUMP, - MT_ROCK1, - MT_ROCK2, - MT_ROCK3, - MT_FOGSPAWNER, - MT_FOGPATCHS, - MT_FOGPATCHM, - MT_FOGPATCHL, - MT_QUAKE_FOCUS, - MT_SGSHARD1, - MT_SGSHARD2, - MT_SGSHARD3, - MT_SGSHARD4, - MT_SGSHARD5, - MT_SGSHARD6, - MT_SGSHARD7, - MT_SGSHARD8, - MT_SGSHARD9, - MT_SGSHARD0, - MT_ARTIEGG, - MT_EGGFX, - MT_ARTISUPERHEAL, - MT_ZWINGEDSTATUENOSKULL, - MT_ZGEMPEDESTAL, - MT_ARTIPUZZSKULL, - MT_ARTIPUZZGEMBIG, - MT_ARTIPUZZGEMRED, - MT_ARTIPUZZGEMGREEN1, - MT_ARTIPUZZGEMGREEN2, - MT_ARTIPUZZGEMBLUE1, - MT_ARTIPUZZGEMBLUE2, - MT_ARTIPUZZBOOK1, - MT_ARTIPUZZBOOK2, - MT_ARTIPUZZSKULL2, - MT_ARTIPUZZFWEAPON, - MT_ARTIPUZZCWEAPON, - MT_ARTIPUZZMWEAPON, - MT_ARTIPUZZGEAR, - MT_ARTIPUZZGEAR2, - MT_ARTIPUZZGEAR3, - MT_ARTIPUZZGEAR4, - MT_ARTITORCH, - MT_FIREBOMB, - MT_ARTITELEPORT, - MT_ARTIPOISONBAG, - MT_POISONBAG, - MT_POISONCLOUD, - MT_THROWINGBOMB, - MT_SPEEDBOOTS, - MT_BOOSTMANA, - MT_BOOSTARMOR, - MT_BLASTRADIUS, - MT_HEALRADIUS, - MT_SPLASH, - MT_SPLASHBASE, - MT_LAVASPLASH, - MT_LAVASMOKE, - MT_SLUDGECHUNK, - MT_SLUDGESPLASH, - MT_MISC0, - MT_MISC1, - MT_MISC2, - MT_MISC3, - MT_MISC4, - MT_MISC5, - MT_MISC6, - MT_MISC7, - MT_MISC8, - MT_TREEDESTRUCTIBLE, - MT_MISC9, - MT_MISC10, - MT_MISC11, - MT_MISC12, - MT_MISC13, - MT_MISC14, - MT_MISC15, - MT_MISC16, - MT_MISC17, - MT_MISC18, - MT_MISC19, - MT_MISC20, - MT_MISC21, - MT_MISC22, - MT_MISC23, - MT_MISC24, - MT_MISC25, - MT_MISC26, - MT_MISC27, - MT_MISC28, - MT_MISC29, - MT_MISC30, - MT_MISC31, - MT_MISC32, - MT_MISC33, - MT_MISC34, - MT_MISC35, - MT_MISC36, - MT_MISC37, - MT_MISC38, - MT_MISC39, - MT_MISC40, - MT_MISC41, - MT_MISC42, - MT_MISC43, - MT_MISC44, - MT_MISC45, - MT_MISC46, - MT_MISC47, - MT_MISC48, - MT_MISC49, - MT_MISC50, - MT_MISC51, - MT_MISC52, - MT_MISC53, - MT_MISC54, - MT_MISC55, - MT_MISC56, - MT_MISC57, - MT_MISC58, - MT_MISC59, - MT_MISC60, - MT_MISC61, - MT_MISC62, - MT_MISC63, - MT_MISC64, - MT_MISC65, - MT_MISC66, - MT_MISC67, - MT_MISC68, - MT_MISC69, - MT_MISC70, - MT_MISC71, - MT_MISC72, - MT_MISC73, - MT_MISC74, - MT_MISC75, - MT_MISC76, - MT_POTTERY1, - MT_POTTERY2, - MT_POTTERY3, - MT_POTTERYBIT1, - MT_MISC77, - MT_ZLYNCHED_NOHEART, - MT_MISC78, - MT_CORPSEBIT, - MT_CORPSEBLOODDRIP, - MT_BLOODPOOL, - MT_MISC79, - MT_MISC80, - MT_LEAF1, - MT_LEAF2, - MT_ZTWINEDTORCH, - MT_ZTWINEDTORCH_UNLIT, - MT_BRIDGE, - MT_BRIDGEBALL, - MT_ZWALLTORCH, - MT_ZWALLTORCH_UNLIT, - MT_ZBARREL, - MT_ZSHRUB1, - MT_ZSHRUB2, - MT_ZBUCKET, - MT_ZPOISONSHROOM, - MT_ZFIREBULL, - MT_ZFIREBULL_UNLIT, - MT_FIRETHING, - MT_BRASSTORCH, - MT_ZSUITOFARMOR, - MT_ZARMORCHUNK, - MT_ZBELL, - MT_ZBLUE_CANDLE, - MT_ZIRON_MAIDEN, - MT_ZXMAS_TREE, - MT_ZCAULDRON, - MT_ZCAULDRON_UNLIT, - MT_ZCHAINBIT32, - MT_ZCHAINBIT64, - MT_ZCHAINEND_HEART, - MT_ZCHAINEND_HOOK1, - MT_ZCHAINEND_HOOK2, - MT_ZCHAINEND_SPIKE, - MT_ZCHAINEND_SKULL, - MT_TABLE_SHIT1, - MT_TABLE_SHIT2, - MT_TABLE_SHIT3, - MT_TABLE_SHIT4, - MT_TABLE_SHIT5, - MT_TABLE_SHIT6, - MT_TABLE_SHIT7, - MT_TABLE_SHIT8, - MT_TABLE_SHIT9, - MT_TABLE_SHIT10, - MT_TFOG, - MT_MISC81, - MT_TELEPORTMAN, - MT_PUNCHPUFF, - MT_FW_AXE, - MT_AXEPUFF, - MT_AXEPUFF_GLOW, - MT_AXEBLOOD, - MT_FW_HAMMER, - MT_HAMMER_MISSILE, - MT_HAMMERPUFF, - MT_FSWORD_MISSILE, - MT_FSWORD_FLAME, - MT_CW_SERPSTAFF, - MT_CSTAFF_MISSILE, - MT_CSTAFFPUFF, - MT_CW_FLAME, - MT_CFLAMEFLOOR, - MT_FLAMEPUFF, - MT_FLAMEPUFF2, - MT_CIRCLEFLAME, - MT_CFLAME_MISSILE, - MT_HOLY_FX, - MT_HOLY_TAIL, - MT_HOLY_PUFF, - MT_HOLY_MISSILE, - MT_HOLY_MISSILE_PUFF, - MT_MWANDPUFF, - MT_MWANDSMOKE, - MT_MWAND_MISSILE, - MT_MW_LIGHTNING, - MT_LIGHTNING_CEILING, - MT_LIGHTNING_FLOOR, - MT_LIGHTNING_ZAP, - MT_MSTAFF_FX, - MT_MSTAFF_FX2, - MT_FW_SWORD1, - MT_FW_SWORD2, - MT_FW_SWORD3, - MT_CW_HOLY1, - MT_CW_HOLY2, - MT_CW_HOLY3, - MT_MW_STAFF1, - MT_MW_STAFF2, - MT_MW_STAFF3, - MT_SNOUTPUFF, - MT_MW_CONE, - MT_SHARDFX1, - MT_BLOOD, - MT_BLOODSPLATTER, - MT_GIBS, - MT_PLAYER_FIGHTER, - MT_BLOODYSKULL, - MT_PLAYER_SPEED, - MT_ICECHUNK, - MT_PLAYER_CLERIC, - MT_PLAYER_MAGE, - MT_PIGPLAYER, - MT_PIG, - MT_CENTAUR, - MT_CENTAURLEADER, - MT_CENTAUR_FX, - MT_CENTAUR_SHIELD, - MT_CENTAUR_SWORD, - MT_DEMON, - MT_DEMONCHUNK1, - MT_DEMONCHUNK2, - MT_DEMONCHUNK3, - MT_DEMONCHUNK4, - MT_DEMONCHUNK5, - MT_DEMONFX1, - MT_DEMON2, - MT_DEMON2CHUNK1, - MT_DEMON2CHUNK2, - MT_DEMON2CHUNK3, - MT_DEMON2CHUNK4, - MT_DEMON2CHUNK5, - MT_DEMON2FX1, - MT_WRAITHB, - MT_WRAITH, - MT_WRAITHFX1, - MT_WRAITHFX2, - MT_WRAITHFX3, - MT_WRAITHFX4, - MT_WRAITHFX5, - MT_MINOTAUR, - MT_MNTRFX1, - MT_MNTRFX2, - MT_MNTRFX3, - MT_MNTRSMOKE, - MT_MNTRSMOKEEXIT, - MT_SERPENT, - MT_SERPENTLEADER, - MT_SERPENTFX, - MT_SERPENT_HEAD, - MT_SERPENT_GIB1, - MT_SERPENT_GIB2, - MT_SERPENT_GIB3, - MT_BISHOP, - MT_BISHOP_PUFF, - MT_BISHOPBLUR, - MT_BISHOPPAINBLUR, - MT_BISH_FX, - MT_DRAGON, - MT_DRAGON_FX, - MT_DRAGON_FX2, - MT_ARMOR_1, - MT_ARMOR_2, - MT_ARMOR_3, - MT_ARMOR_4, - MT_MANA1, - MT_MANA2, - MT_MANA3, - MT_KEY1, - MT_KEY2, - MT_KEY3, - MT_KEY4, - MT_KEY5, - MT_KEY6, - MT_KEY7, - MT_KEY8, - MT_KEY9, - MT_KEYA, - MT_KEYB, - MT_SOUNDWIND, - MT_SOUNDWATERFALL, - MT_ETTIN, - MT_ETTIN_MACE, - MT_FIREDEMON, - MT_FIREDEMON_SPLOTCH1, - MT_FIREDEMON_SPLOTCH2, - MT_FIREDEMON_FX1, - MT_FIREDEMON_FX2, - MT_FIREDEMON_FX3, - MT_FIREDEMON_FX4, - MT_FIREDEMON_FX5, - MT_FIREDEMON_FX6, - MT_ICEGUY, - MT_ICEGUY_FX, - MT_ICEFX_PUFF, - MT_ICEGUY_FX2, - MT_ICEGUY_BIT, - MT_ICEGUY_WISP1, - MT_ICEGUY_WISP2, - MT_FIGHTER_BOSS, - MT_CLERIC_BOSS, - MT_MAGE_BOSS, - MT_SORCBOSS, - MT_SORCBALL1, - MT_SORCBALL2, - MT_SORCBALL3, - MT_SORCFX1, - MT_SORCFX2, - MT_SORCFX2_T1, - MT_SORCFX3, - MT_SORCFX3_EXPLOSION, - MT_SORCFX4, - MT_SORCSPARK1, - MT_BLASTEFFECT, - MT_WATER_DRIP, - MT_KORAX, - MT_KORAX_SPIRIT1, - MT_KORAX_SPIRIT2, - MT_KORAX_SPIRIT3, - MT_KORAX_SPIRIT4, - MT_KORAX_SPIRIT5, - MT_KORAX_SPIRIT6, - MT_DEMON_MASH, - MT_DEMON2_MASH, - MT_ETTIN_MASH, - MT_CENTAUR_MASH, - MT_KORAX_BOLT, - MT_BAT_SPAWNER, - MT_BAT, - NUMMOBJTYPES -} mobjtype_t; - -typedef struct -{ - int doomednum; - int spawnstate; - int spawnhealth; - int seestate; - int seesound; - int reactiontime; - int attacksound; - int painstate; - int painchance; - int painsound; - int meleestate; - int missilestate; - int crashstate; - int deathstate; - int xdeathstate; - int deathsound; - int speed; - int radius; - int height; - int mass; - int damage; - int activesound; - int flags; - int flags2; -} mobjinfo_t; - -extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; diff --git a/games/NXDoom/src/hexen/m_random.c b/games/NXDoom/src/hexen/m_random.c deleted file mode 100644 index 422b1a5d455..00000000000 --- a/games/NXDoom/src/hexen/m_random.c +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "m_random.h" - -// This is the new flat distribution table - -static const unsigned char rndtable[256] = { - 201, 1, 243, 19, 18, 42, 183, 203, 101, 123, 154, 137, 34, 118, 10, 216, - 135, 246, 0, 107, 133, 229, 35, 113, 177, 211, 110, 17, 139, 84, 251, 235, - 182, 166, 161, 230, 143, 91, 24, 81, 22, 94, 7, 51, 232, 104, 122, 248, - 175, 138, 127, 171, 222, 213, 44, 16, 9, 33, 88, 102, 170, 150, 136, 114, - 62, 3, 142, 237, 6, 252, 249, 56, 74, 30, 13, 21, 180, 199, 32, 132, - 187, 234, 78, 210, 46, 131, 197, 8, 206, 244, 73, 4, 236, 178, 195, 70, - 121, 97, 167, 217, 103, 40, 247, 186, 105, 39, 95, 163, 99, 149, 253, 29, - 119, 83, 254, 26, 202, 65, 130, 155, 60, 64, 184, 106, 221, 93, 164, 196, - 112, 108, 179, 141, 54, 109, 11, 126, 75, 165, 191, 227, 87, 225, 156, 15, - 98, 162, 116, 79, 169, 140, 190, 205, 168, 194, 41, 250, 27, 20, 14, 241, - 50, 214, 72, 192, 220, 233, 67, 148, 96, 185, 176, 181, 215, 207, 172, 85, - 89, 90, 209, 128, 124, 2, 55, 173, 66, 152, 47, 129, 59, 43, 159, 240, - 239, 12, 189, 212, 144, 28, 200, 77, 219, 198, 134, 228, 45, 92, 125, 151, - 5, 53, 255, 52, 68, 245, 160, 158, 61, 86, 58, 82, 117, 37, 242, 145, - 69, 188, 115, 76, 63, 100, 49, 111, 153, 80, 38, 57, 174, 224, 71, 231, - 23, 25, 48, 218, 120, 147, 208, 36, 226, 223, 193, 238, 157, 204, 146, 31 -}; - - -int rndindex = 0; -int prndindex = 0; - -/* -=============== -= -= M_Random -= -= Returns a 0-255 number -= -=============== -*/ - - -int P_Random(void) -{ - prndindex = (prndindex + 1) & 0xff; - return rndtable[prndindex]; -} - -int M_Random(void) -{ - rndindex = (rndindex + 1) & 0xff; - return rndtable[rndindex]; -} - -void M_ClearRandom(void) -{ - rndindex = prndindex = 0; -} - -// inspired by the same routine in Eternity, thanks haleyjd -int P_SubRandom (void) -{ - int r = P_Random(); - return r - P_Random(); -} diff --git a/games/NXDoom/src/hexen/m_random.h b/games/NXDoom/src/hexen/m_random.h deleted file mode 100644 index 2de7630012e..00000000000 --- a/games/NXDoom/src/hexen/m_random.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef HEXEN_M_RANDOM_H -#define HEXEN_M_RANDOM_H - -// Most damage defined using HITDICE -#define HITDICE(a) ((1+(P_Random()&7))*a) - -int M_Random(void); -// returns a number from 0 to 255 -int P_Random(void); -// as M_Random, but used only by the play simulation - -void M_ClearRandom(void); -// fix randoms for demos - -extern int rndindex; - -// Defined version of P_Random() - P_Random() -int P_SubRandom (void); - -#endif // HEXEN_M_RANDOM_H - diff --git a/games/NXDoom/src/hexen/mn_menu.c b/games/NXDoom/src/hexen/mn_menu.c deleted file mode 100644 index 57be51c9c6b..00000000000 --- a/games/NXDoom/src/hexen/mn_menu.c +++ /dev/null @@ -1,1952 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include -#include "h2def.h" -#include "doomkeys.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_swap.h" -#include "i_video.h" -#include "m_controls.h" -#include "m_misc.h" -#include "p_local.h" -#include "r_local.h" -#include "s_sound.h" -#include "v_video.h" -#include "am_map.h" - - -// MACROS ------------------------------------------------------------------ - -#define LEFT_DIR 0 -#define RIGHT_DIR 1 -#define ITEM_HEIGHT 20 -#define SELECTOR_XOFFSET (-28) -#define SELECTOR_YOFFSET (-1) -#define SLOTTEXTLEN 16 -#define ASCII_CURSOR '[' - -// TYPES ------------------------------------------------------------------- - -typedef enum -{ - ITT_EMPTY, - ITT_EFUNC, - ITT_LRFUNC, - ITT_SETMENU, - ITT_INERT -} ItemType_t; - -typedef enum -{ - MENU_MAIN, - MENU_CLASS, - MENU_SKILL, - MENU_OPTIONS, - MENU_OPTIONS2, - MENU_FILES, - MENU_LOAD, - MENU_SAVE, - MENU_NONE -} MenuType_t; - -typedef struct -{ - ItemType_t type; - const char *text; - void (*func) (int option); - int option; - MenuType_t menu; -} MenuItem_t; - -typedef struct -{ - int x; - int y; - void (*drawFunc) (void); - int itemCount; - MenuItem_t *items; - int oldItPos; - MenuType_t prevMenu; -} Menu_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void InitFonts(void); -static void SetMenu(MenuType_t menu); -static void SCQuitGame(int option); -static void SCClass(int option); -static void SCSkill(int option); -static void SCMouseSensi(int option); -static void SCSfxVolume(int option); -static void SCMusicVolume(int option); -static void SCScreenSize(int option); -static boolean SCNetCheck(int option); -static void SCNetCheck2(int option); -static void SCLoadGame(int option); -static void SCSaveGame(int option); -static void SCMessages(int option); -static void SCEndGame(int option); -static void SCInfo(int option); -static void DrawMainMenu(void); -static void DrawClassMenu(void); -static void DrawSkillMenu(void); -static void DrawOptionsMenu(void); -static void DrawOptions2Menu(void); -static void DrawFileSlots(Menu_t * menu); -static void DrawFilesMenu(void); -static void MN_DrawInfo(void); -static void DrawLoadMenu(void); -static void DrawSaveMenu(void); -static void DrawSlider(Menu_t * menu, int item, int width, int slot); -void MN_LoadSlotText(void); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -boolean MenuActive; -int InfoType; -int messageson = true; -boolean mn_SuicideConsole; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int FontABaseLump; -static int FontAYellowBaseLump; -static int FontBBaseLump; -static int MauloBaseLump; -static Menu_t *CurrentMenu; -static int CurrentItPos; -static int MenuPClass; -static int MenuTime; -static boolean soundchanged; - -boolean askforquit; -static int typeofask; -static boolean FileMenuKeySteal; -static boolean slottextloaded; -static boolean joypadsave; -static char SlotText[6][SLOTTEXTLEN + 2]; -static char oldSlotText[SLOTTEXTLEN + 2]; -static int SlotStatus[6]; -static int slotptr; -static int currentSlot; -static int quicksave; -static int quickload; - -static MenuItem_t MainItems[] = { - {ITT_SETMENU, "NEW GAME", SCNetCheck2, 1, MENU_CLASS}, - {ITT_SETMENU, "OPTIONS", NULL, 0, MENU_OPTIONS}, - {ITT_SETMENU, "GAME FILES", NULL, 0, MENU_FILES}, - {ITT_EFUNC, "INFO", SCInfo, 0, MENU_NONE}, - {ITT_EFUNC, "QUIT GAME", SCQuitGame, 0, MENU_NONE} -}; - -static Menu_t MainMenu = { - 110, 56, - DrawMainMenu, - 5, MainItems, - 0, - MENU_NONE -}; - -static MenuItem_t ClassItems[] = { - {ITT_EFUNC, "FIGHTER", SCClass, 0, MENU_NONE}, - {ITT_EFUNC, "CLERIC", SCClass, 1, MENU_NONE}, - {ITT_EFUNC, "MAGE", SCClass, 2, MENU_NONE} -}; - -static Menu_t ClassMenu = { - 66, 66, - DrawClassMenu, - 3, ClassItems, - 0, - MENU_MAIN -}; - -static MenuItem_t FilesItems[] = { - {ITT_SETMENU, "LOAD GAME", SCNetCheck2, 2, MENU_LOAD}, - {ITT_SETMENU, "SAVE GAME", NULL, 0, MENU_SAVE} -}; - -static Menu_t FilesMenu = { - 110, 60, - DrawFilesMenu, - 2, FilesItems, - 0, - MENU_MAIN -}; - -static MenuItem_t LoadItems[] = { - {ITT_EFUNC, NULL, SCLoadGame, 0, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 1, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 2, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 3, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 4, MENU_NONE}, - {ITT_EFUNC, NULL, SCLoadGame, 5, MENU_NONE} -}; - -static Menu_t LoadMenu = { - 70, 30, - DrawLoadMenu, - 6, LoadItems, - 0, - MENU_FILES -}; - -static MenuItem_t SaveItems[] = { - {ITT_EFUNC, NULL, SCSaveGame, 0, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 1, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 2, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 3, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 4, MENU_NONE}, - {ITT_EFUNC, NULL, SCSaveGame, 5, MENU_NONE} -}; - -static Menu_t SaveMenu = { - 70, 30, - DrawSaveMenu, - 6, SaveItems, - 0, - MENU_FILES -}; - -static MenuItem_t SkillItems[] = { - {ITT_EFUNC, NULL, SCSkill, sk_baby, MENU_NONE}, - {ITT_EFUNC, NULL, SCSkill, sk_easy, MENU_NONE}, - {ITT_EFUNC, NULL, SCSkill, sk_medium, MENU_NONE}, - {ITT_EFUNC, NULL, SCSkill, sk_hard, MENU_NONE}, - {ITT_EFUNC, NULL, SCSkill, sk_nightmare, MENU_NONE} -}; - -static Menu_t SkillMenu = { - 120, 44, - DrawSkillMenu, - 5, SkillItems, - 2, - MENU_CLASS -}; - -static MenuItem_t OptionsItems[] = { - {ITT_EFUNC, "END GAME", SCEndGame, 0, MENU_NONE}, - {ITT_EFUNC, "MESSAGES : ", SCMessages, 0, MENU_NONE}, - {ITT_LRFUNC, "MOUSE SENSITIVITY", SCMouseSensi, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_SETMENU, "MORE...", NULL, 0, MENU_OPTIONS2} -}; - -static Menu_t OptionsMenu = { - 88, 30, - DrawOptionsMenu, - 5, OptionsItems, - 0, - MENU_MAIN -}; - -static MenuItem_t Options2Items[] = { - {ITT_LRFUNC, "SCREEN SIZE", SCScreenSize, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_LRFUNC, "SFX VOLUME", SCSfxVolume, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE}, - {ITT_LRFUNC, "MUSIC VOLUME", SCMusicVolume, 0, MENU_NONE}, - {ITT_EMPTY, NULL, NULL, 0, MENU_NONE} -}; - -static Menu_t Options2Menu = { - 90, 20, - DrawOptions2Menu, - 6, Options2Items, - 0, - MENU_OPTIONS -}; - -static Menu_t *Menus[] = { - &MainMenu, - &ClassMenu, - &SkillMenu, - &OptionsMenu, - &Options2Menu, - &FilesMenu, - &LoadMenu, - &SaveMenu -}; - -static const char *GammaText[] = { - TXT_GAMMA_LEVEL_OFF, - TXT_GAMMA_LEVEL_1, - TXT_GAMMA_LEVEL_2, - TXT_GAMMA_LEVEL_3, - TXT_GAMMA_LEVEL_4 -}; - -// CODE -------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// -// PROC MN_Init -// -//--------------------------------------------------------------------------- - -void MN_Init(void) -{ - InitFonts(); - MenuActive = false; -// messageson = true; // Set by defaults in .CFG - MauloBaseLump = W_GetNumForName("FBULA0"); // ("M_SKL00"); -} - -//--------------------------------------------------------------------------- -// -// PROC InitFonts -// -//--------------------------------------------------------------------------- - -static void InitFonts(void) -{ - FontABaseLump = W_GetNumForName("FONTA_S") + 1; - FontAYellowBaseLump = W_GetNumForName("FONTAY_S") + 1; - FontBBaseLump = W_GetNumForName("FONTB_S") + 1; -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DrTextA -// -// Draw text using font A. -// -//--------------------------------------------------------------------------- - -void MN_DrTextA(const char *text, int x, int y) -{ - char c; - patch_t *p; - - while ((c = *text++) != 0) - { - if (c < 33) - { - x += 5; - } - else - { - p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - V_DrawPatch(x, y, p); - x += SHORT(p->width) - 1; - } - } -} - -//========================================================================== -// -// MN_DrTextAYellow -// -//========================================================================== - -void MN_DrTextAYellow(const char *text, int x, int y) -{ - char c; - patch_t *p; - - while ((c = *text++) != 0) - { - if (c < 33) - { - x += 5; - } - else - { - p = W_CacheLumpNum(FontAYellowBaseLump + c - 33, PU_CACHE); - V_DrawPatch(x, y, p); - x += SHORT(p->width) - 1; - } - } -} - -//--------------------------------------------------------------------------- -// -// FUNC MN_TextAWidth -// -// Returns the pixel width of a string using font A. -// -//--------------------------------------------------------------------------- - -int MN_TextAWidth(const char *text) -{ - char c; - int width; - patch_t *p; - - width = 0; - while ((c = *text++) != 0) - { - if (c < 33) - { - width += 5; - } - else - { - p = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); - width += SHORT(p->width) - 1; - } - } - return (width); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DrTextB -// -// Draw text using font B. -// -//--------------------------------------------------------------------------- - -void MN_DrTextB(const char *text, int x, int y) -{ - char c; - patch_t *p; - - while ((c = *text++) != 0) - { - if (c < 33) - { - x += 8; - } - else - { - p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); - V_DrawPatch(x, y, p); - x += SHORT(p->width) - 1; - } - } -} - -//--------------------------------------------------------------------------- -// -// FUNC MN_TextBWidth -// -// Returns the pixel width of a string using font B. -// -//--------------------------------------------------------------------------- - -int MN_TextBWidth(const char *text) -{ - char c; - int width; - patch_t *p; - - width = 0; - while ((c = *text++) != 0) - { - if (c < 33) - { - width += 5; - } - else - { - p = W_CacheLumpNum(FontBBaseLump + c - 33, PU_CACHE); - width += SHORT(p->width) - 1; - } - } - return (width); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_Ticker -// -//--------------------------------------------------------------------------- - -void MN_Ticker(void) -{ - if (MenuActive == false) - { - return; - } - MenuTime++; -} - -//--------------------------------------------------------------------------- -// -// PROC MN_Drawer -// -//--------------------------------------------------------------------------- - -const char *QuitEndMsg[] = { - "ARE YOU SURE YOU WANT TO QUIT?", - "ARE YOU SURE YOU WANT TO END THE GAME?", - "DO YOU WANT TO QUICKSAVE THE GAME NAMED", - "DO YOU WANT TO QUICKLOAD THE GAME NAMED", - "ARE YOU SURE YOU WANT TO SUICIDE?" -}; - -void MN_Drawer(void) -{ - int i; - int x; - int y; - MenuItem_t *item; - const char *selName; - - if (MenuActive == false) - { - if (askforquit) - { - MN_DrTextA(QuitEndMsg[typeofask - 1], 160 - - MN_TextAWidth(QuitEndMsg[typeofask - 1]) / 2, 80); - if (typeofask == 3) - { - MN_DrTextA(SlotText[quicksave - 1], 160 - - MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); - MN_DrTextA("?", 160 + - MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); - } - if (typeofask == 4) - { - MN_DrTextA(SlotText[quickload - 1], 160 - - MN_TextAWidth(SlotText[quickload - 1]) / 2, 90); - MN_DrTextA("?", 160 + - MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90); - } - UpdateState |= I_FULLSCRN; - } - return; - } - else - { - UpdateState |= I_FULLSCRN; - if (InfoType) - { - MN_DrawInfo(); - return; - } - if (screenblocks < 10) - { - BorderNeedRefresh = true; - } - if (CurrentMenu->drawFunc != NULL) - { - CurrentMenu->drawFunc(); - } - x = CurrentMenu->x; - y = CurrentMenu->y; - item = CurrentMenu->items; - for (i = 0; i < CurrentMenu->itemCount; i++) - { - if (item->type != ITT_EMPTY && item->text) - { - MN_DrTextB(item->text, x, y); - } - y += ITEM_HEIGHT; - item++; - } - y = CurrentMenu->y + (CurrentItPos * ITEM_HEIGHT) + SELECTOR_YOFFSET; - selName = MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2"; - V_DrawPatch(x + SELECTOR_XOFFSET, y, - W_CacheLumpName(selName, PU_CACHE)); - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawMainMenu -// -//--------------------------------------------------------------------------- - -static void DrawMainMenu(void) -{ - int frame; - - frame = (MenuTime / 5) % 7; - V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE)); -// Old Gold skull positions: (40, 10) and (232, 10) - V_DrawPatch(37, 80, W_CacheLumpNum(MauloBaseLump + (frame + 2) % 7, - PU_CACHE)); - V_DrawPatch(278, 80, W_CacheLumpNum(MauloBaseLump + frame, PU_CACHE)); -} - -//========================================================================== -// -// DrawClassMenu -// -//========================================================================== - -static void DrawClassMenu(void) -{ - pclass_t class; - static const char *boxLumpName[3] = { - "m_fbox", - "m_cbox", - "m_mbox" - }; - static const char *walkLumpName[3] = { - "m_fwalk1", - "m_cwalk1", - "m_mwalk1" - }; - - MN_DrTextB("CHOOSE CLASS:", 34, 24); - class = (pclass_t) CurrentMenu->items[CurrentItPos].option; - V_DrawPatch(174, 8, W_CacheLumpName(boxLumpName[class], PU_CACHE)); - V_DrawPatch(174 + 24, 8 + 12, - W_CacheLumpNum(W_GetNumForName(walkLumpName[class]) - + ((MenuTime >> 3) & 3), PU_CACHE)); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSkillMenu -// -//--------------------------------------------------------------------------- - -static void DrawSkillMenu(void) -{ - MN_DrTextB("CHOOSE SKILL LEVEL:", 74, 16); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawFilesMenu -// -//--------------------------------------------------------------------------- - -static void DrawFilesMenu(void) -{ -// clear out the quicksave/quickload stuff - quicksave = 0; - quickload = 0; - P_ClearMessage(&players[consoleplayer]); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawLoadMenu -// -//--------------------------------------------------------------------------- - -static void DrawLoadMenu(void) -{ - MN_DrTextB("LOAD GAME", 160 - MN_TextBWidth("LOAD GAME") / 2, 10); - if (!slottextloaded) - { - MN_LoadSlotText(); - } - DrawFileSlots(&LoadMenu); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSaveMenu -// -//--------------------------------------------------------------------------- - -static void DrawSaveMenu(void) -{ - MN_DrTextB("SAVE GAME", 160 - MN_TextBWidth("SAVE GAME") / 2, 10); - if (!slottextloaded) - { - MN_LoadSlotText(); - } - DrawFileSlots(&SaveMenu); -} - -static boolean ReadDescriptionForSlot(int slot, char *description) -{ - FILE *fp; - boolean found; - char name[100]; - char versionText[HXS_VERSION_TEXT_LENGTH]; - - M_snprintf(name, sizeof(name), "%shex%d.hxs", SavePath, slot); - - fp = M_fopen(name, "rb"); - - if (fp == NULL) - { - return false; - } - - found = fread(description, HXS_DESCRIPTION_LENGTH, 1, fp) == 1 - && fread(versionText, HXS_VERSION_TEXT_LENGTH, 1, fp) == 1; - - found = found && strcmp(versionText, HXS_VERSION_TEXT) == 0; - - fclose(fp); - - return found; -} - -//=========================================================================== -// -// MN_LoadSlotText -// -// For each slot, looks for save games and reads the description field. -// -//=========================================================================== - -void MN_LoadSlotText(void) -{ - char description[HXS_DESCRIPTION_LENGTH]; - int slot; - - for (slot = 0; slot < 6; slot++) - { - if (ReadDescriptionForSlot(slot, description)) - { - memcpy(SlotText[slot], description, SLOTTEXTLEN); - SlotStatus[slot] = 1; - } - else - { - memset(SlotText[slot], 0, SLOTTEXTLEN); - SlotStatus[slot] = 0; - } - } - slottextloaded = true; -} - -//--------------------------------------------------------------------------- -// -// PROC DrawFileSlots -// -//--------------------------------------------------------------------------- - -static void DrawFileSlots(Menu_t * menu) -{ - int i; - int x; - int y; - - x = menu->x; - y = menu->y; - for (i = 0; i < 6; i++) - { - V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE)); - if (SlotStatus[i]) - { - MN_DrTextA(SlotText[i], x + 5, y + 5); - } - y += ITEM_HEIGHT; - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawOptionsMenu -// -//--------------------------------------------------------------------------- - -static void DrawOptionsMenu(void) -{ - if (messageson) - { - MN_DrTextB("ON", 196, 50); - } - else - { - MN_DrTextB("OFF", 196, 50); - } - DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity); -} - -//--------------------------------------------------------------------------- -// -// PROC DrawOptions2Menu -// -//--------------------------------------------------------------------------- - -static void DrawOptions2Menu(void) -{ - DrawSlider(&Options2Menu, 1, 9, screenblocks - 3); - DrawSlider(&Options2Menu, 3, 16, snd_MaxVolume); - DrawSlider(&Options2Menu, 5, 16, snd_MusicVolume); -} - -//--------------------------------------------------------------------------- -// -// PROC SCQuitGame -// -//--------------------------------------------------------------------------- - -static void SCQuitGame(int option) -{ - MenuActive = false; - askforquit = true; - typeofask = 1; //quit game - if (!netgame && !demoplayback) - { - paused = true; - } -} - -//--------------------------------------------------------------------------- -// -// PROC SCEndGame -// -//--------------------------------------------------------------------------- - -static void SCEndGame(int option) -{ - if (demoplayback) - { - return; - } - if (SCNetCheck(3)) - { - MenuActive = false; - askforquit = true; - typeofask = 2; //endgame - if (!netgame && !demoplayback) - { - paused = true; - } - } -} - -//--------------------------------------------------------------------------- -// -// PROC SCMessages -// -//--------------------------------------------------------------------------- - -static void SCMessages(int option) -{ - messageson ^= 1; - if (messageson) - { - P_SetMessage(&players[consoleplayer], "MESSAGES ON", true); - } - else - { - P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true); - } - S_StartSound(NULL, SFX_CHAT); -} - -//=========================================================================== -// -// SCNetCheck -// -//=========================================================================== - -static boolean SCNetCheck(int option) -{ - if (!netgame) - { - return true; - } - switch (option) - { - case 1: // new game - P_SetMessage(&players[consoleplayer], - "YOU CAN'T START A NEW GAME IN NETPLAY!", true); - break; - case 2: // load game - P_SetMessage(&players[consoleplayer], - "YOU CAN'T LOAD A GAME IN NETPLAY!", true); - break; - case 3: // end game - P_SetMessage(&players[consoleplayer], - "YOU CAN'T END A GAME IN NETPLAY!", true); - break; - } - MenuActive = false; - S_StartSound(NULL, SFX_CHAT); - return false; -} - -//=========================================================================== -// -// SCNetCheck2 -// -//=========================================================================== - -static void SCNetCheck2(int option) -{ - SCNetCheck(option); - return; -} - -//--------------------------------------------------------------------------- -// -// PROC SCLoadGame -// -//--------------------------------------------------------------------------- - -static void SCLoadGame(int option) -{ - if (demoplayback) - { - // deactivate playback, return control to player - demoextend = false; - } - if (!SlotStatus[option]) - { // Don't try to load from an empty slot - return; - } - G_LoadGame(option); - MN_DeactivateMenu(); - BorderNeedRefresh = true; - if (quickload == -1) - { - quickload = option + 1; - P_ClearMessage(&players[consoleplayer]); - } -} - -// -// Generate a default save slot name when the user saves to -// an empty slot via the joypad. -// -static void SetDefaultSaveName(int slot) -{ - // map from IWAD or PWAD? - if (W_IsIWADLump(maplumpinfo) && strcmp(SavePath, "")) - { - M_snprintf(SlotText[slot], SLOTTEXTLEN, - "%s", maplumpinfo->name); - } - else - { - char *wadname = M_StringDuplicate(W_WadNameForLump(maplumpinfo)); - char *ext = strrchr(wadname, '.'); - - if (ext != NULL) - { - *ext = '\0'; - } - - M_snprintf(SlotText[slot], SLOTTEXTLEN, - "%s (%s)", maplumpinfo->name, - wadname); - free(wadname); - } - M_ForceUppercase(SlotText[slot]); - joypadsave = false; -} - -//--------------------------------------------------------------------------- -// -// PROC SCSaveGame -// -//--------------------------------------------------------------------------- - -static void SCSaveGame(int option) -{ - char *ptr; - - if (!FileMenuKeySteal) - { - int x, y; - - FileMenuKeySteal = true; - // We need to activate the text input interface to type the save - // game name: - x = SaveMenu.x + 1; - y = SaveMenu.y + 1 + option * ITEM_HEIGHT; - I_StartTextInput(x, y, x + 190, y + ITEM_HEIGHT - 2); - - M_StringCopy(oldSlotText, SlotText[option], sizeof(oldSlotText)); - ptr = SlotText[option]; - - if (!strcmp(ptr, "") && joypadsave) - { - SetDefaultSaveName(option); - } - - while (*ptr) - { - ptr++; - } - *ptr = '['; - *(ptr + 1) = 0; - SlotStatus[option]++; - currentSlot = option; - slotptr = ptr - SlotText[option]; - return; - } - else - { - G_SaveGame(option, SlotText[option]); - FileMenuKeySteal = false; - I_StopTextInput(); - MN_DeactivateMenu(); - } - BorderNeedRefresh = true; - if (quicksave == -1) - { - quicksave = option + 1; - P_ClearMessage(&players[consoleplayer]); - } -} - -//========================================================================== -// -// SCClass -// -//========================================================================== - -static void SCClass(int option) -{ - if (netgame) - { - P_SetMessage(&players[consoleplayer], - "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", - true); - return; - } - MenuPClass = option; - switch (MenuPClass) - { - case PCLASS_FIGHTER: - SkillMenu.x = 120; - SkillItems[0].text = "SQUIRE"; - SkillItems[1].text = "KNIGHT"; - SkillItems[2].text = "WARRIOR"; - SkillItems[3].text = "BERSERKER"; - SkillItems[4].text = "TITAN"; - break; - case PCLASS_CLERIC: - SkillMenu.x = 116; - SkillItems[0].text = "ALTAR BOY"; - SkillItems[1].text = "ACOLYTE"; - SkillItems[2].text = "PRIEST"; - SkillItems[3].text = "CARDINAL"; - SkillItems[4].text = "POPE"; - break; - case PCLASS_MAGE: - SkillMenu.x = 112; - SkillItems[0].text = "APPRENTICE"; - SkillItems[1].text = "ENCHANTER"; - SkillItems[2].text = "SORCERER"; - SkillItems[3].text = "WARLOCK"; - SkillItems[4].text = "ARCHIMAGE"; - break; - } - SetMenu(MENU_SKILL); -} - -//--------------------------------------------------------------------------- -// -// PROC SCSkill -// -//--------------------------------------------------------------------------- - -static void SCSkill(int option) -{ - if (demoplayback) - { - // deactivate playback, return control to player - demoextend = false; - } - - PlayerClass[consoleplayer] = MenuPClass; - G_DeferredNewGame(option); - SB_SetClassData(); - SB_state = -1; - MN_DeactivateMenu(); -} - -//--------------------------------------------------------------------------- -// -// PROC SCMouseSensi -// -//--------------------------------------------------------------------------- - -static void SCMouseSensi(int option) -{ - if (option == RIGHT_DIR) - { - if (mouseSensitivity < 9) - { - mouseSensitivity++; - } - } - else if (mouseSensitivity) - { - mouseSensitivity--; - } -} - -//--------------------------------------------------------------------------- -// -// PROC SCSfxVolume -// -//--------------------------------------------------------------------------- - -static void SCSfxVolume(int option) -{ - if (option == RIGHT_DIR) - { - if (snd_MaxVolume < 15) - { - snd_MaxVolume++; - } - } - else if (snd_MaxVolume) - { - snd_MaxVolume--; - } - soundchanged = true; // we'll set it when we leave the menu -} - -//--------------------------------------------------------------------------- -// -// PROC SCMusicVolume -// -//--------------------------------------------------------------------------- - -static void SCMusicVolume(int option) -{ - if (option == RIGHT_DIR) - { - if (snd_MusicVolume < 15) - { - snd_MusicVolume++; - } - } - else if (snd_MusicVolume) - { - snd_MusicVolume--; - } - S_SetMusicVolume(); -} - -//--------------------------------------------------------------------------- -// -// PROC SCScreenSize -// -//--------------------------------------------------------------------------- - -static void SCScreenSize(int option) -{ - if (option == RIGHT_DIR) - { - if (screenblocks < 11) - { - screenblocks++; - } - } - else if (screenblocks > 3) - { - screenblocks--; - } - R_SetViewSize(screenblocks, detailLevel); -} - -//--------------------------------------------------------------------------- -// -// PROC SCInfo -// -//--------------------------------------------------------------------------- - -static void SCInfo(int option) -{ - InfoType = 1; - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - if (!netgame && !demoplayback) - { - paused = true; - } -} - -//--------------------------------------------------------------------------- -// -// FUNC MN_Responder -// -//--------------------------------------------------------------------------- - -boolean MN_Responder(event_t * event) -{ - int key; - int charTyped; - int i; - MenuItem_t *item; - char *textBuffer; - int dir; - - // In testcontrols mode, none of the function keys should do anything - // - the only key is escape to quit. - - if (testcontrols) - { - if (event->type == ev_quit - || (event->type == ev_keydown - && (event->data1 == key_menu_activate - || event->data1 == key_menu_quit))) - { - I_Quit(); - return true; - } - - return false; - } - - // "close" button pressed on window? - if (event->type == ev_quit) - { - // First click on close = bring up quit confirm message. - // Second click = confirm quit. - - if (!MenuActive && askforquit && typeofask == 1) - { - G_CheckDemoStatus(); - I_Quit(); - } - else - { - SCQuitGame(0); - S_StartSound(NULL, SFX_CHAT); - } - - return true; - } - - charTyped = 0; - key = -1; - - if (event->type == ev_joystick) - { - // Simulate key presses from joystick events to interact with the menu. - - if (MenuActive) - { - if (JOY_GET_DPAD(event->data6) != JOY_DIR_NONE) - { - dir = JOY_GET_DPAD(event->data6); - } - else if (JOY_GET_LSTICK(event->data6) != JOY_DIR_NONE) - { - dir = JOY_GET_LSTICK(event->data6); - } - else - { - dir = JOY_GET_RSTICK(event->data6); - } - - if (dir & JOY_DIR_UP) - { - key = key_menu_up; - joywait = I_GetTime() + 5; - } - else if (dir & JOY_DIR_DOWN) - { - key = key_menu_down; - joywait = I_GetTime() + 5; - } - if (dir & JOY_DIR_LEFT) - { - key = key_menu_left; - joywait = I_GetTime() + 5; - } - else if (dir & JOY_DIR_RIGHT) - { - key = key_menu_right; - joywait = I_GetTime() + 5; - } - -#define JOY_BUTTON_MAPPED(x) ((x) >= 0) -#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (event->data1 & (1 << (x))) != 0) - - if (JOY_BUTTON_PRESSED(joybfire)) - { - // Simulate pressing "Enter" when we are supplying a save slot name - if (FileMenuKeySteal) - { - key = KEY_ENTER; - } - else - { - // if selecting a save slot via joypad, set a flag - if (CurrentMenu == &SaveMenu) - { - joypadsave = true; - } - key = key_menu_forward; - } - joywait = I_GetTime() + 5; - } - if (JOY_BUTTON_PRESSED(joybuse)) - { - // If user was entering a save name, back out - if (FileMenuKeySteal) - { - key = KEY_ESCAPE; - } - else - { - key = key_menu_back; - } - joywait = I_GetTime() + 5; - } - } - else if (askforquit) - { - if (JOY_BUTTON_PRESSED(joybfire)) - { - // Simulate a 'Y' keypress - key = key_menu_confirm; - joywait = I_GetTime() + 5; - } - if (JOY_BUTTON_PRESSED(joybuse)) - { - // Simulate a 'N' keypress - key = key_menu_abort; - joywait = I_GetTime() + 5; - } - } - if (JOY_BUTTON_PRESSED(joybmenu)) - { - MN_ActivateMenu(); - joywait = I_GetTime() + 5; - return true; - } - } - - if (event->type != ev_keydown && key == -1) - { - return false; - } - - if (event->type == ev_keydown) - { - key = event->data1; - charTyped = event->data2; - } - - if (InfoType) - { - /* The 4-Level Demo Version also has 3 Info pages - if (gamemode == shareware) - { - InfoType = (InfoType + 1) % 5; - } - else - */ - { - InfoType = (InfoType + 1) % 4; - } - if (key == KEY_ESCAPE) - { - InfoType = 0; - } - if (!InfoType) - { - if (!netgame && !demoplayback) - { - paused = false; - } - MN_DeactivateMenu(); - SB_state = -1; //refresh the statbar - BorderNeedRefresh = true; - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - return (true); //make the info screen eat the keypress - } - - if ((ravpic && key == KEY_F1) || - (key != 0 && key == key_menu_screenshot)) - { - G_ScreenShot(); - return (true); - } - - if (askforquit) - { - if (key == key_menu_confirm) - { - switch (typeofask) - { - case 1: - G_CheckDemoStatus(); - I_Quit(); - return false; - case 2: - P_ClearMessage(&players[consoleplayer]); - askforquit = false; - typeofask = 0; - paused = false; - I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); - H2_StartTitle(); // go to intro/demo mode. - return false; - case 3: - P_SetMessage(&players[consoleplayer], - "QUICKSAVING....", false); - FileMenuKeySteal = true; - SCSaveGame(quicksave - 1); - BorderNeedRefresh = true; - break; - case 4: - P_SetMessage(&players[consoleplayer], - "QUICKLOADING....", false); - SCLoadGame(quickload - 1); - BorderNeedRefresh = true; - break; - case 5: - BorderNeedRefresh = true; - mn_SuicideConsole = true; - break; - default: - break; - } - - askforquit = false; - typeofask = 0; - - return true; - } - else if (key == key_menu_abort || key == KEY_ESCAPE) - { - players[consoleplayer].messageTics = 0; - askforquit = false; - typeofask = 0; - paused = false; - UpdateState |= I_FULLSCRN; - BorderNeedRefresh = true; - return true; - } - - return false; // don't let the keys filter thru - } - if (!MenuActive && !chatmodeon) - { - if (key == key_menu_decscreen) - { - if (automapactive) - { // Don't screen size in automap - return (false); - } - SCScreenSize(LEFT_DIR); - S_StartSound(NULL, SFX_PICKUP_KEY); - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - return (true); - } - else if (key == key_menu_incscreen) - { - if (automapactive) - { // Don't screen size in automap - return (false); - } - SCScreenSize(RIGHT_DIR); - S_StartSound(NULL, SFX_PICKUP_KEY); - BorderNeedRefresh = true; - UpdateState |= I_FULLSCRN; - return (true); - } - else if (key == key_menu_help) // F1 (help screen) - { - SCInfo(0); // start up info screens - MenuActive = true; - return (true); - } - else if (key == key_menu_save) // F2 (save game) - { - if (gamestate == GS_LEVEL && !demoplayback) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &SaveMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - slottextloaded = false; //reload the slot text, when needed - } - return true; - } - else if (key == key_menu_load) // F3 (load game) - { - if (SCNetCheck(2)) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &LoadMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - slottextloaded = false; //reload the slot text, when needed - } - return true; - } - else if (key == key_menu_volume) // F4 (volume) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &Options2Menu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - slottextloaded = false; //reload the slot text, when needed - return true; - } - else if (key == key_menu_detail) // F5 (suicide) - { - MenuActive = false; - askforquit = true; - typeofask = 5; // suicide - return true; - } - else if (key == key_menu_qsave) // F6 (quicksave) - { - if (gamestate == GS_LEVEL && !demoplayback) - { - if (!quicksave || quicksave == -1) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &SaveMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - slottextloaded = false; //reload the slot text - quicksave = -1; - P_SetMessage(&players[consoleplayer], - "CHOOSE A QUICKSAVE SLOT", true); - } - else - { - askforquit = true; - typeofask = 3; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_CHAT); - } - } - return true; - } - else if (key == key_menu_endgame) // F7 (end game) - { - if (SCNetCheck(3)) - { - if (gamestate == GS_LEVEL && !demoplayback) - { - S_StartSound(NULL, SFX_CHAT); - SCEndGame(0); - } - } - return true; - } - else if (key == key_menu_messages) // F8 (toggle messages) - { - SCMessages(0); - return true; - } - else if (key == key_menu_qload) // F9 (quickload) - { - if (SCNetCheck(2)) - { - if (!quickload || quickload == -1) - { - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &LoadMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - slottextloaded = false; // reload the slot text - quickload = -1; - P_SetMessage(&players[consoleplayer], - "CHOOSE A QUICKLOAD SLOT", true); - } - else - { - askforquit = true; - if (!netgame && !demoplayback) - { - paused = true; - } - typeofask = 4; - S_StartSound(NULL, SFX_CHAT); - } - } - return true; - } - else if (key == key_menu_quit) // F10 (quit) - { - if (gamestate == GS_LEVEL || gamestate == GS_FINALE) - { - SCQuitGame(0); - S_StartSound(NULL, SFX_CHAT); - } - return true; - } - else if (key == key_menu_gamma) // F11 (gamma correction) - { - usegamma++; - if (usegamma > 4) - { - usegamma = 0; - } - SB_PaletteFlash(true); // force change - P_SetMessage(&players[consoleplayer], GammaText[usegamma], - false); - return true; - } - else if (key == KEY_F12) // F12 (???) - { - // F12 - reload current map (devmaps mode) - - if (netgame) - { - return false; - } - if (gamekeydown[key_speed]) - { // Monsters ON - nomonsters = false; - } - if (gamekeydown[key_strafe]) - { // Monsters OFF - nomonsters = true; - } - G_DeferedInitNew(gameskill, gameepisode, gamemap); - P_SetMessage(&players[consoleplayer], TXT_CHEATWARP, false); - return true; - } - } - - if (!MenuActive) - { - if (key == key_menu_activate || gamestate == GS_DEMOSCREEN || demoplayback) - { - MN_ActivateMenu(); - return (true); - } - return (false); - } - if (!FileMenuKeySteal) - { - item = &CurrentMenu->items[CurrentItPos]; - - if (key == key_menu_down) // Next menu item - { - do - { - if (CurrentItPos + 1 > CurrentMenu->itemCount - 1) - { - CurrentItPos = 0; - } - else - { - CurrentItPos++; - } - } - while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); - S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL); - return (true); - } - else if (key == key_menu_up) // Previous menu item - { - do - { - if (CurrentItPos == 0) - { - CurrentItPos = CurrentMenu->itemCount - 1; - } - else - { - CurrentItPos--; - } - } - while (CurrentMenu->items[CurrentItPos].type == ITT_EMPTY); - S_StartSound(NULL, SFX_FIGHTER_HAMMER_HITWALL); - return (true); - } - else if (key == key_menu_left) // Slider left - { - if (item->type == ITT_LRFUNC && item->func != NULL) - { - item->func(LEFT_DIR); - S_StartSound(NULL, SFX_PICKUP_KEY); - } - return (true); - } - else if (key == key_menu_right) // Slider right - { - if (item->type == ITT_LRFUNC && item->func != NULL) - { - item->func(RIGHT_DIR); - S_StartSound(NULL, SFX_PICKUP_KEY); - } - return (true); - } - else if (key == key_menu_forward) // Activate item (enter) - { - if (item->type == ITT_SETMENU) - { - if (item->func != NULL) - { - item->func(item->option); - } - SetMenu(item->menu); - } - else if (item->func != NULL) - { - CurrentMenu->oldItPos = CurrentItPos; - if (item->type == ITT_LRFUNC) - { - item->func(RIGHT_DIR); - } - else if (item->type == ITT_EFUNC) - { - item->func(item->option); - } - } - S_StartSound(NULL, SFX_DOOR_LIGHT_CLOSE); - return (true); - } - else if (key == key_menu_activate) - { - MN_DeactivateMenu(); - return (true); - } - else if (key == key_menu_back) - { - S_StartSound(NULL, SFX_PICKUP_KEY); - - if (CurrentMenu->prevMenu == MENU_NONE) - { - MN_DeactivateMenu(); - } - else - { - SetMenu(CurrentMenu->prevMenu); - } - return (true); - } - else if (charTyped != 0) - { - for (i = 0; i < CurrentMenu->itemCount; i++) - { - if (CurrentMenu->items[i].text) - { - if (toupper(charTyped) - == toupper(CurrentMenu->items[i].text[0])) - { - CurrentItPos = i; - return (true); - } - } - } - } - return (false); - } - else - { - // Editing file names - // When typing a savegame name, we use the fully shifted and - // translated input value from event->data3. - charTyped = event->data3; - textBuffer = &SlotText[currentSlot][slotptr]; - if (key == KEY_BACKSPACE) - { - if (slotptr) - { - *textBuffer = 0; - slotptr--; - textBuffer = &SlotText[currentSlot][slotptr]; - *textBuffer = ASCII_CURSOR; - } - return (true); - } - if (key == KEY_ESCAPE) - { - M_StringCopy(SlotText[currentSlot], oldSlotText, - sizeof(SlotText[currentSlot])); - SlotStatus[currentSlot]--; - MN_DeactivateMenu(); - return (true); - } - if (key == KEY_ENTER) - { - SlotText[currentSlot][slotptr] = 0; // clear the cursor - item = &CurrentMenu->items[CurrentItPos]; - CurrentMenu->oldItPos = CurrentItPos; - if (item->type == ITT_EFUNC) - { - item->func(item->option); - if (item->menu != MENU_NONE) - { - SetMenu(item->menu); - } - } - return (true); - } - if (slotptr < SLOTTEXTLEN && key != KEY_BACKSPACE) - { - if (isalpha(charTyped)) - { - *textBuffer++ = toupper(charTyped); - *textBuffer = ASCII_CURSOR; - slotptr++; - return (true); - } - if (isdigit(charTyped) || charTyped == ' ' - || charTyped == ',' || charTyped == '.' || charTyped == '-' - || charTyped == '!') - { - *textBuffer++ = charTyped; - *textBuffer = ASCII_CURSOR; - slotptr++; - return (true); - } - } - return (true); - } - return (false); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_ActivateMenu -// -//--------------------------------------------------------------------------- - -void MN_ActivateMenu(void) -{ - if (MenuActive) - { - return; - } - if (paused) - { - S_ResumeSound(); - } - MenuActive = true; - FileMenuKeySteal = false; - MenuTime = 0; - CurrentMenu = &MainMenu; - CurrentItPos = CurrentMenu->oldItPos; - if (!netgame && !demoplayback) - { - paused = true; - } - S_StartSound(NULL, SFX_PLATFORM_STOP); - slottextloaded = false; //reload the slot text, when needed -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DeactivateMenu -// -//--------------------------------------------------------------------------- - -void MN_DeactivateMenu(void) -{ - if (CurrentMenu != NULL) - { - CurrentMenu->oldItPos = CurrentItPos; - } - MenuActive = false; - if (FileMenuKeySteal) - { - I_StopTextInput(); - } - if (!netgame) - { - paused = false; - } - S_StartSound(NULL, SFX_PLATFORM_STOP); - P_ClearMessage(&players[consoleplayer]); -} - -//--------------------------------------------------------------------------- -// -// PROC MN_DrawInfo -// -//--------------------------------------------------------------------------- - -void MN_DrawInfo(void) -{ - I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); - memcpy(I_VideoBuffer, - (byte *) W_CacheLumpNum(W_GetNumForName("TITLE") + InfoType, - PU_CACHE), SCREENWIDTH * SCREENHEIGHT); -// V_DrawPatch(0, 0, W_CacheLumpNum(W_GetNumForName("TITLE")+InfoType, -// PU_CACHE)); -} - - -//--------------------------------------------------------------------------- -// -// PROC SetMenu -// -//--------------------------------------------------------------------------- - -static void SetMenu(MenuType_t menu) -{ - CurrentMenu->oldItPos = CurrentItPos; - CurrentMenu = Menus[menu]; - CurrentItPos = CurrentMenu->oldItPos; -} - -//--------------------------------------------------------------------------- -// -// PROC DrawSlider -// -//--------------------------------------------------------------------------- - -static void DrawSlider(Menu_t * menu, int item, int width, int slot) -{ - int x; - int y; - int x2; - int count; - - x = menu->x + 24; - y = menu->y + 2 + (item * ITEM_HEIGHT); - V_DrawPatch(x - 32, y, W_CacheLumpName("M_SLDLT", PU_CACHE)); - for (x2 = x, count = width; count--; x2 += 8) - { - V_DrawPatch(x2, y, W_CacheLumpName(count & 1 ? "M_SLDMD1" - : "M_SLDMD2", PU_CACHE)); - } - V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE)); - V_DrawPatch(x + 4 + slot * 8, y + 7, - W_CacheLumpName("M_SLDKB", PU_CACHE)); -} diff --git a/games/NXDoom/src/hexen/p_acs.c b/games/NXDoom/src/hexen/p_acs.c deleted file mode 100644 index 33d0480b6e7..00000000000 --- a/games/NXDoom/src/hexen/p_acs.c +++ /dev/null @@ -1,1996 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "m_misc.h" -#include "m_random.h" -#include "s_sound.h" -#include "i_swap.h" -#include "i_system.h" -#include "p_local.h" - -// MACROS ------------------------------------------------------------------ - -#define MAX_SCRIPT_ARGS 3 -#define SCRIPT_CONTINUE 0 -#define SCRIPT_STOP 1 -#define SCRIPT_TERMINATE 2 -#define OPEN_SCRIPTS_BASE 1000 -#define PRINT_BUFFER_SIZE 256 -#define GAME_SINGLE_PLAYER 0 -#define GAME_NET_COOPERATIVE 1 -#define GAME_NET_DEATHMATCH 2 -#define TEXTURE_TOP 0 -#define TEXTURE_MIDDLE 1 -#define TEXTURE_BOTTOM 2 - -// TYPES ------------------------------------------------------------------- - -typedef PACKED_STRUCT ( -{ - int marker; - int infoOffset; - int code; -}) acsHeader_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void StartOpenACS(int number, int infoIndex, int offset); -static void ScriptFinished(int number); -static boolean TagBusy(int tag); -static boolean AddToACSStore(int map, int number, byte * args); -static int GetACSIndex(int number); -static void Push(int value); -static int Pop(void); -static int Top(void); -static void Drop(void); - -static int CmdNOP(void); -static int CmdTerminate(void); -static int CmdSuspend(void); -static int CmdPushNumber(void); -static int CmdLSpec1(void); -static int CmdLSpec2(void); -static int CmdLSpec3(void); -static int CmdLSpec4(void); -static int CmdLSpec5(void); -static int CmdLSpec1Direct(void); -static int CmdLSpec2Direct(void); -static int CmdLSpec3Direct(void); -static int CmdLSpec4Direct(void); -static int CmdLSpec5Direct(void); -static int CmdAdd(void); -static int CmdSubtract(void); -static int CmdMultiply(void); -static int CmdDivide(void); -static int CmdModulus(void); -static int CmdEQ(void); -static int CmdNE(void); -static int CmdLT(void); -static int CmdGT(void); -static int CmdLE(void); -static int CmdGE(void); -static int CmdAssignScriptVar(void); -static int CmdAssignMapVar(void); -static int CmdAssignWorldVar(void); -static int CmdPushScriptVar(void); -static int CmdPushMapVar(void); -static int CmdPushWorldVar(void); -static int CmdAddScriptVar(void); -static int CmdAddMapVar(void); -static int CmdAddWorldVar(void); -static int CmdSubScriptVar(void); -static int CmdSubMapVar(void); -static int CmdSubWorldVar(void); -static int CmdMulScriptVar(void); -static int CmdMulMapVar(void); -static int CmdMulWorldVar(void); -static int CmdDivScriptVar(void); -static int CmdDivMapVar(void); -static int CmdDivWorldVar(void); -static int CmdModScriptVar(void); -static int CmdModMapVar(void); -static int CmdModWorldVar(void); -static int CmdIncScriptVar(void); -static int CmdIncMapVar(void); -static int CmdIncWorldVar(void); -static int CmdDecScriptVar(void); -static int CmdDecMapVar(void); -static int CmdDecWorldVar(void); -static int CmdGoto(void); -static int CmdIfGoto(void); -static int CmdDrop(void); -static int CmdDelay(void); -static int CmdDelayDirect(void); -static int CmdRandom(void); -static int CmdRandomDirect(void); -static int CmdThingCount(void); -static int CmdThingCountDirect(void); -static int CmdTagWait(void); -static int CmdTagWaitDirect(void); -static int CmdPolyWait(void); -static int CmdPolyWaitDirect(void); -static int CmdChangeFloor(void); -static int CmdChangeFloorDirect(void); -static int CmdChangeCeiling(void); -static int CmdChangeCeilingDirect(void); -static int CmdRestart(void); -static int CmdAndLogical(void); -static int CmdOrLogical(void); -static int CmdAndBitwise(void); -static int CmdOrBitwise(void); -static int CmdEorBitwise(void); -static int CmdNegateLogical(void); -static int CmdLShift(void); -static int CmdRShift(void); -static int CmdUnaryMinus(void); -static int CmdIfNotGoto(void); -static int CmdLineSide(void); -static int CmdScriptWait(void); -static int CmdScriptWaitDirect(void); -static int CmdClearLineSpecial(void); -static int CmdCaseGoto(void); -static int CmdBeginPrint(void); -static int CmdEndPrint(void); -static int CmdPrintString(void); -static int CmdPrintNumber(void); -static int CmdPrintCharacter(void); -static int CmdPlayerCount(void); -static int CmdGameType(void); -static int CmdGameSkill(void); -static int CmdTimer(void); -static int CmdSectorSound(void); -static int CmdAmbientSound(void); -static int CmdSoundSequence(void); -static int CmdSetLineTexture(void); -static int CmdSetLineBlocking(void); -static int CmdSetLineSpecial(void); -static int CmdThingSound(void); -static int CmdEndPrintBold(void); - -static void ThingCount(int type, int tid); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -int ACScriptCount; -byte *ActionCodeBase; -static int ActionCodeSize; -acsInfo_t *ACSInfo; -int MapVars[MAX_ACS_MAP_VARS]; -int WorldVars[MAX_ACS_WORLD_VARS]; -acsstore_t ACSStore[MAX_ACS_STORE + 1]; // +1 for termination marker - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static char EvalContext[64]; -static acs_t *ACScript; -static unsigned int PCodeOffset; -static byte SpecArgs[8]; -static int ACStringCount; -static char **ACStrings; -static char PrintBuffer[PRINT_BUFFER_SIZE]; -static acs_t *NewScript; - -static int (*PCodeCmds[]) (void) = -{ - CmdNOP, - CmdTerminate, - CmdSuspend, - CmdPushNumber, - CmdLSpec1, - CmdLSpec2, - CmdLSpec3, - CmdLSpec4, - CmdLSpec5, - CmdLSpec1Direct, - CmdLSpec2Direct, - CmdLSpec3Direct, - CmdLSpec4Direct, - CmdLSpec5Direct, - CmdAdd, - CmdSubtract, - CmdMultiply, - CmdDivide, - CmdModulus, - CmdEQ, - CmdNE, - CmdLT, - CmdGT, - CmdLE, - CmdGE, - CmdAssignScriptVar, - CmdAssignMapVar, - CmdAssignWorldVar, - CmdPushScriptVar, - CmdPushMapVar, - CmdPushWorldVar, - CmdAddScriptVar, - CmdAddMapVar, - CmdAddWorldVar, - CmdSubScriptVar, - CmdSubMapVar, - CmdSubWorldVar, - CmdMulScriptVar, - CmdMulMapVar, - CmdMulWorldVar, - CmdDivScriptVar, - CmdDivMapVar, - CmdDivWorldVar, - CmdModScriptVar, - CmdModMapVar, - CmdModWorldVar, - CmdIncScriptVar, - CmdIncMapVar, - CmdIncWorldVar, - CmdDecScriptVar, - CmdDecMapVar, - CmdDecWorldVar, - CmdGoto, - CmdIfGoto, - CmdDrop, - CmdDelay, - CmdDelayDirect, - CmdRandom, - CmdRandomDirect, - CmdThingCount, - CmdThingCountDirect, - CmdTagWait, - CmdTagWaitDirect, - CmdPolyWait, - CmdPolyWaitDirect, - CmdChangeFloor, - CmdChangeFloorDirect, - CmdChangeCeiling, - CmdChangeCeilingDirect, - CmdRestart, - CmdAndLogical, - CmdOrLogical, - CmdAndBitwise, - CmdOrBitwise, - CmdEorBitwise, - CmdNegateLogical, - CmdLShift, - CmdRShift, - CmdUnaryMinus, - CmdIfNotGoto, - CmdLineSide, - CmdScriptWait, - CmdScriptWaitDirect, - CmdClearLineSpecial, - CmdCaseGoto, - CmdBeginPrint, - CmdEndPrint, - CmdPrintString, - CmdPrintNumber, - CmdPrintCharacter, - CmdPlayerCount, - CmdGameType, - CmdGameSkill, - CmdTimer, - CmdSectorSound, - CmdAmbientSound, - CmdSoundSequence, - CmdSetLineTexture, - CmdSetLineBlocking, - CmdSetLineSpecial, - CmdThingSound, - CmdEndPrintBold, -}; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// ACSAssert -// -// Check that the given condition evaluates to true. If it does not, exit -// with an I_Error() printing the given message. -// -//========================================================================== - -static void ACSAssert(int condition, const char *fmt, ...) -{ - char buf[128]; - va_list args; - - if (condition) - { - return; - } - - va_start(args, fmt); - M_vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - I_Error("ACS assertion failure: in %s: %s", EvalContext, buf); -} - -//========================================================================== -// -// ReadCodeInt -// -// Read a 32-bit value from the loaded ACS lump at the location pointed to -// by PCodeOffset, advancing PCodeOffset to the next value in the process. -// -//========================================================================== - -static int ReadCodeInt(void) -{ - int result; - int *ptr; - - ACSAssert(PCodeOffset + 3 < ActionCodeSize, - "unexpectedly reached end of ACS lump"); - - ptr = (int *) (ActionCodeBase + PCodeOffset); - result = LONG(*ptr); - PCodeOffset += 4; - - return result; -} - -//========================================================================== -// -// ReadScriptVar -// -// Read a script variable index as an immediate value, validating the -// result is a valid script variable number. -// -//========================================================================== - -static int ReadScriptVar(void) -{ - int var = ReadCodeInt(); - ACSAssert(var >= 0, "negative script variable: %d < 0", var); - ACSAssert(var < MAX_ACS_SCRIPT_VARS, - "invalid script variable: %d >= %d", var, MAX_ACS_SCRIPT_VARS); - return var; -} - -//========================================================================== -// -// ReadMapVar -// -// Read a map variable index as an immediate value, validating the -// result is a valid map variable number. -// -//========================================================================== - -static int ReadMapVar(void) -{ - int var = ReadCodeInt(); - ACSAssert(var >= 0, "negative map variable: %d < 0", var); - ACSAssert(var < MAX_ACS_MAP_VARS, - "invalid map variable: %d >= %d", var, MAX_ACS_MAP_VARS); - return var; -} - -//========================================================================== -// -// ReadWorldVar -// -// Read a world variable index as an immediate value, validating the -// result is a valid world variable number. -// -//========================================================================== - -static int ReadWorldVar(void) -{ - int var = ReadCodeInt(); - ACSAssert(var >= 0, "negative world variable: %d < 0", var); - ACSAssert(var < MAX_ACS_WORLD_VARS, - "invalid world variable: %d >= %d", var, MAX_ACS_WORLD_VARS); - return var; -} - -//========================================================================== -// -// StringLookup -// -// Look up the given string in the strings table by index, validating that -// it is a valid string index. -// -//========================================================================== - -static char *StringLookup(int string_index) -{ - ACSAssert(string_index >= 0, - "negative string index: %d < 0", string_index); - ACSAssert(string_index < ACStringCount, - "invalid string index: %d >= %d", string_index, ACStringCount); - return ACStrings[string_index]; -} - -//========================================================================== -// -// ReadOffset -// -// Read a lump offset value, validating that it is an offset within the -// range of the lump. -// -//========================================================================== - -static int ReadOffset(void) -{ - int offset = ReadCodeInt(); - ACSAssert(offset >= 0, "negative lump offset %d", offset); - ACSAssert(offset < ActionCodeSize, "invalid lump offset: %d >= %d", - offset, ActionCodeSize); - return offset; -} - -//========================================================================== -// -// P_LoadACScripts -// -//========================================================================== - -void P_LoadACScripts(int lump) -{ - int i, offset; - acsHeader_t *header; - acsInfo_t *info; - - ActionCodeBase = W_CacheLumpNum(lump, PU_LEVEL); - ActionCodeSize = W_LumpLength(lump); - - M_snprintf(EvalContext, sizeof(EvalContext), - "header parsing of lump #%d", lump); - - header = (acsHeader_t *) ActionCodeBase; - PCodeOffset = LONG(header->infoOffset); - - ACScriptCount = ReadCodeInt(); - - if (ACScriptCount == 0) - { // Empty behavior lump - return; - } - - ACSInfo = Z_Malloc(ACScriptCount * sizeof(acsInfo_t), PU_LEVEL, 0); - memset(ACSInfo, 0, ACScriptCount * sizeof(acsInfo_t)); - for (i = 0, info = ACSInfo; i < ACScriptCount; i++, info++) - { - info->number = ReadCodeInt(); - info->offset = ReadOffset(); - info->argCount = ReadCodeInt(); - - if (info->argCount > MAX_SCRIPT_ARGS) - { - fprintf(stderr, "Warning: ACS script #%i has %i arguments, more " - "than the maximum of %i. Enforcing limit.\n" - "If you are seeing this message, please report " - "the name of the WAD where you saw it.\n", - i, info->argCount, MAX_SCRIPT_ARGS); - info->argCount = MAX_SCRIPT_ARGS; - } - - if (info->number >= OPEN_SCRIPTS_BASE) - { // Auto-activate - info->number -= OPEN_SCRIPTS_BASE; - StartOpenACS(info->number, i, info->offset); - info->state = ASTE_RUNNING; - } - else - { - info->state = ASTE_INACTIVE; - } - } - - ACStringCount = ReadCodeInt(); - ACSAssert(ACStringCount >= 0, "negative string count %d", ACStringCount); - ACStrings = Z_Malloc(ACStringCount * sizeof(char *), PU_LEVEL, NULL); - - for (i=0; inumber = number; - - // World objects are allotted 1 second for initialization - script->delayCount = 35; - - script->infoIndex = infoIndex; - script->ip = offset; - script->thinker.function = T_InterpretACS; - P_AddThinker(&script->thinker); -} - -//========================================================================== -// -// P_CheckACSStore -// -// Scans the ACS store and executes all scripts belonging to the current -// map. -// -//========================================================================== - -void P_CheckACSStore(void) -{ - acsstore_t *store; - - for (store = ACSStore; store->map != 0; store++) - { - if (store->map == gamemap) - { - P_StartACS(store->script, 0, store->args, NULL, NULL, 0); - if (NewScript) - { - NewScript->delayCount = 35; - } - store->map = -1; - } - } -} - -//========================================================================== -// -// P_StartACS -// -// Start an ACS script. The 'args' array should be at least MAX_SCRIPT_ARGS -// elements in length. -// -//========================================================================== - -static char ErrorMsg[128]; - -boolean P_StartACS(int number, int map, byte * args, mobj_t * activator, - line_t * line, int side) -{ - int i; - acs_t *script; - int infoIndex; - aste_t *statePtr; - - NewScript = NULL; - if (map && map != gamemap) - { // Add to the script store - return AddToACSStore(map, number, args); - } - infoIndex = GetACSIndex(number); - if (infoIndex == -1) - { // Script not found - //I_Error("P_StartACS: Unknown script number %d", number); - M_snprintf(ErrorMsg, sizeof(ErrorMsg), - "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number); - P_SetMessage(&players[consoleplayer], ErrorMsg, true); - } - statePtr = &ACSInfo[infoIndex].state; - if (*statePtr == ASTE_SUSPENDED) - { // Resume a suspended script - *statePtr = ASTE_RUNNING; - return true; - } - if (*statePtr != ASTE_INACTIVE) - { // Script is already executing - return false; - } - script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0); - memset(script, 0, sizeof(acs_t)); - script->number = number; - script->infoIndex = infoIndex; - script->activator = activator; - script->line = line; - script->side = side; - script->ip = ACSInfo[infoIndex].offset; - script->thinker.function = T_InterpretACS; - for (i = 0; i < MAX_SCRIPT_ARGS && i < ACSInfo[infoIndex].argCount; i++) - { - script->vars[i] = args[i]; - } - *statePtr = ASTE_RUNNING; - P_AddThinker(&script->thinker); - NewScript = script; - return true; -} - -//========================================================================== -// -// AddToACSStore -// -//========================================================================== - -static boolean AddToACSStore(int map, int number, byte * args) -{ - int i; - int index; - - index = -1; - for (i = 0; ACSStore[i].map != 0; i++) - { - if (ACSStore[i].script == number && ACSStore[i].map == map) - { // Don't allow duplicates - return false; - } - if (index == -1 && ACSStore[i].map == -1) - { // Remember first empty slot - index = i; - } - } - if (index == -1) - { // Append required - if (i == MAX_ACS_STORE) - { - I_Error("AddToACSStore: MAX_ACS_STORE (%d) exceeded.", - MAX_ACS_STORE); - } - index = i; - ACSStore[index + 1].map = 0; - } - ACSStore[index].map = map; - ACSStore[index].script = number; - memcpy(ACSStore[index].args, args, MAX_SCRIPT_ARGS); - return true; -} - -//========================================================================== -// -// P_StartLockedACS -// -//========================================================================== - - -boolean P_StartLockedACS(line_t * line, byte * args, mobj_t * mo, int side) -{ - int i; - int lock; - byte newArgs[5]; - char LockedBuffer[80]; - - lock = args[4]; - if (!mo->player) - { - return false; - } - if (lock) - { - if (!(mo->player->keys & (1 << (lock - 1)))) - { - M_snprintf(LockedBuffer, sizeof(LockedBuffer), - "YOU NEED THE %s\n", TextKeyMessages[lock - 1]); - P_SetMessage(mo->player, LockedBuffer, true); - S_StartSound(mo, SFX_DOOR_LOCKED); - return false; - } - } - for (i = 0; i < 4; i++) - { - newArgs[i] = args[i]; - } - newArgs[4] = 0; - return P_StartACS(newArgs[0], newArgs[1], &newArgs[2], mo, line, side); -} - -//========================================================================== -// -// P_TerminateACS -// -//========================================================================== - -boolean P_TerminateACS(int number, int map) -{ - int infoIndex; - - infoIndex = GetACSIndex(number); - if (infoIndex == -1) - { // Script not found - return false; - } - if (ACSInfo[infoIndex].state == ASTE_INACTIVE - || ACSInfo[infoIndex].state == ASTE_TERMINATING) - { // States that disallow termination - return false; - } - ACSInfo[infoIndex].state = ASTE_TERMINATING; - return true; -} - -//========================================================================== -// -// P_SuspendACS -// -//========================================================================== - -boolean P_SuspendACS(int number, int map) -{ - int infoIndex; - - infoIndex = GetACSIndex(number); - if (infoIndex == -1) - { // Script not found - return false; - } - if (ACSInfo[infoIndex].state == ASTE_INACTIVE - || ACSInfo[infoIndex].state == ASTE_SUSPENDED - || ACSInfo[infoIndex].state == ASTE_TERMINATING) - { // States that disallow suspension - return false; - } - ACSInfo[infoIndex].state = ASTE_SUSPENDED; - return true; -} - -//========================================================================== -// -// P_Init -// -//========================================================================== - -void P_ACSInitNewGame(void) -{ - memset(WorldVars, 0, sizeof(WorldVars)); - memset(ACSStore, 0, sizeof(ACSStore)); -} - -//========================================================================== -// -// T_InterpretACS -// -//========================================================================== - -void T_InterpretACS(thinker_t *thinker) -{ - acs_t *script = (acs_t *) thinker; - int cmd; - int action; - - if (ACSInfo[script->infoIndex].state == ASTE_TERMINATING) - { - ACSInfo[script->infoIndex].state = ASTE_INACTIVE; - ScriptFinished(ACScript->number); - P_RemoveThinker(&ACScript->thinker); - return; - } - if (ACSInfo[script->infoIndex].state != ASTE_RUNNING) - { - return; - } - if (script->delayCount) - { - script->delayCount--; - return; - } - ACScript = script; - PCodeOffset = ACScript->ip; - - do - { - M_snprintf(EvalContext, sizeof(EvalContext), "script %d @0x%x", - ACSInfo[script->infoIndex].number, PCodeOffset); - cmd = ReadCodeInt(); - M_snprintf(EvalContext, sizeof(EvalContext), "script %d @0x%x, cmd=%d", - ACSInfo[script->infoIndex].number, PCodeOffset, cmd); - ACSAssert(cmd >= 0, "negative ACS instruction %d", cmd); - ACSAssert(cmd < arrlen(PCodeCmds), - "invalid ACS instruction %d (maybe this WAD is designed " - "for an advanced source port and is not vanilla " - "compatible)", cmd); - action = PCodeCmds[cmd](); - } while (action == SCRIPT_CONTINUE); - - ACScript->ip = PCodeOffset; - - if (action == SCRIPT_TERMINATE) - { - ACSInfo[script->infoIndex].state = ASTE_INACTIVE; - ScriptFinished(ACScript->number); - P_RemoveThinker(&ACScript->thinker); - } -} - -//========================================================================== -// -// P_TagFinished -// -//========================================================================== - -void P_TagFinished(int tag) -{ - int i; - - if (TagBusy(tag) == true) - { - return; - } - for (i = 0; i < ACScriptCount; i++) - { - if (ACSInfo[i].state == ASTE_WAITINGFORTAG - && ACSInfo[i].waitValue == tag) - { - ACSInfo[i].state = ASTE_RUNNING; - } - } -} - -//========================================================================== -// -// P_PolyobjFinished -// -//========================================================================== - -void P_PolyobjFinished(int po) -{ - int i; - - if (PO_Busy(po) == true) - { - return; - } - for (i = 0; i < ACScriptCount; i++) - { - if (ACSInfo[i].state == ASTE_WAITINGFORPOLY - && ACSInfo[i].waitValue == po) - { - ACSInfo[i].state = ASTE_RUNNING; - } - } -} - -//========================================================================== -// -// ScriptFinished -// -//========================================================================== - -static void ScriptFinished(int number) -{ - int i; - - for (i = 0; i < ACScriptCount; i++) - { - if (ACSInfo[i].state == ASTE_WAITINGFORSCRIPT - && ACSInfo[i].waitValue == number) - { - ACSInfo[i].state = ASTE_RUNNING; - } - } -} - -//========================================================================== -// -// TagBusy -// -//========================================================================== - -static boolean TagBusy(int tag) -{ - int sectorIndex; - - sectorIndex = -1; - while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) - { - if (sectors[sectorIndex].specialdata) - { - return true; - } - } - return false; -} - -//========================================================================== -// -// GetACSIndex -// -// Returns the index of a script number. Returns -1 if the script number -// is not found. -// -//========================================================================== - -static int GetACSIndex(int number) -{ - int i; - - for (i = 0; i < ACScriptCount; i++) - { - if (ACSInfo[i].number == number) - { - return i; - } - } - return -1; -} - -//========================================================================== -// -// CheckACSPresent -// -// Placing Korax in a PWAD without extra steps will result in a crash in -// Vanilla because the relevant ACS scripts are not initialized -// -//========================================================================== - -void CheckACSPresent(int number) -{ - if (GetACSIndex(number) == -1) - { - I_Error("Required ACS script %d not initialized", number); - } -} - -//========================================================================== -// -// Push -// -//========================================================================== - -static void Push(int value) -{ - ACSAssert(ACScript->stackPtr < ACS_STACK_DEPTH, - "maximum stack depth exceeded: %d >= %d", - ACScript->stackPtr, ACS_STACK_DEPTH); - ACScript->stack[ACScript->stackPtr++] = value; -} - -//========================================================================== -// -// Pop -// -//========================================================================== - -static int Pop(void) -{ - ACSAssert(ACScript->stackPtr > 0, "pop of empty stack"); - return ACScript->stack[--ACScript->stackPtr]; -} - -//========================================================================== -// -// Top -// -//========================================================================== - -static int Top(void) -{ - ACSAssert(ACScript->stackPtr > 0, "read from top of empty stack"); - return ACScript->stack[ACScript->stackPtr - 1]; -} - -//========================================================================== -// -// Drop -// -//========================================================================== - -static void Drop(void) -{ - ACSAssert(ACScript->stackPtr > 0, "drop on empty stack"); - ACScript->stackPtr--; -} - -//========================================================================== -// -// P-Code Commands -// -//========================================================================== - -static int CmdNOP(void) -{ - return SCRIPT_CONTINUE; -} - -static int CmdTerminate(void) -{ - return SCRIPT_TERMINATE; -} - -static int CmdSuspend(void) -{ - ACSInfo[ACScript->infoIndex].state = ASTE_SUSPENDED; - return SCRIPT_STOP; -} - -static int CmdPushNumber(void) -{ - Push(ReadCodeInt()); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec1(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[0] = Pop(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec2(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[1] = Pop(); - SpecArgs[0] = Pop(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec3(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[2] = Pop(); - SpecArgs[1] = Pop(); - SpecArgs[0] = Pop(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec4(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[3] = Pop(); - SpecArgs[2] = Pop(); - SpecArgs[1] = Pop(); - SpecArgs[0] = Pop(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec5(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[4] = Pop(); - SpecArgs[3] = Pop(); - SpecArgs[2] = Pop(); - SpecArgs[1] = Pop(); - SpecArgs[0] = Pop(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec1Direct(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[0] = ReadCodeInt(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec2Direct(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[0] = ReadCodeInt(); - SpecArgs[1] = ReadCodeInt(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec3Direct(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[0] = ReadCodeInt(); - SpecArgs[1] = ReadCodeInt(); - SpecArgs[2] = ReadCodeInt(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec4Direct(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[0] = ReadCodeInt(); - SpecArgs[1] = ReadCodeInt(); - SpecArgs[2] = ReadCodeInt(); - SpecArgs[3] = ReadCodeInt(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdLSpec5Direct(void) -{ - int special; - - special = ReadCodeInt(); - SpecArgs[0] = ReadCodeInt(); - SpecArgs[1] = ReadCodeInt(); - SpecArgs[2] = ReadCodeInt(); - SpecArgs[3] = ReadCodeInt(); - SpecArgs[4] = ReadCodeInt(); - P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, - ACScript->side, ACScript->activator); - return SCRIPT_CONTINUE; -} - -static int CmdAdd(void) -{ - Push(Pop() + Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdSubtract(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() - operand2); - return SCRIPT_CONTINUE; -} - -static int CmdMultiply(void) -{ - Push(Pop() * Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdDivide(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() / operand2); - return SCRIPT_CONTINUE; -} - -static int CmdModulus(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() % operand2); - return SCRIPT_CONTINUE; -} - -static int CmdEQ(void) -{ - Push(Pop() == Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdNE(void) -{ - Push(Pop() != Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdLT(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() < operand2); - return SCRIPT_CONTINUE; -} - -static int CmdGT(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() > operand2); - return SCRIPT_CONTINUE; -} - -static int CmdLE(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() <= operand2); - return SCRIPT_CONTINUE; -} - -static int CmdGE(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() >= operand2); - return SCRIPT_CONTINUE; -} - -static int CmdAssignScriptVar(void) -{ - ACScript->vars[ReadScriptVar()] = Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdAssignMapVar(void) -{ - MapVars[ReadMapVar()] = Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdAssignWorldVar(void) -{ - WorldVars[ReadWorldVar()] = Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdPushScriptVar(void) -{ - Push(ACScript->vars[ReadScriptVar()]); - return SCRIPT_CONTINUE; -} - -static int CmdPushMapVar(void) -{ - Push(MapVars[ReadMapVar()]); - return SCRIPT_CONTINUE; -} - -static int CmdPushWorldVar(void) -{ - Push(WorldVars[ReadWorldVar()]); - return SCRIPT_CONTINUE; -} - -static int CmdAddScriptVar(void) -{ - ACScript->vars[ReadScriptVar()] += Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdAddMapVar(void) -{ - MapVars[ReadMapVar()] += Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdAddWorldVar(void) -{ - WorldVars[ReadWorldVar()] += Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdSubScriptVar(void) -{ - ACScript->vars[ReadScriptVar()] -= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdSubMapVar(void) -{ - MapVars[ReadMapVar()] -= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdSubWorldVar(void) -{ - WorldVars[ReadWorldVar()] -= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdMulScriptVar(void) -{ - ACScript->vars[ReadScriptVar()] *= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdMulMapVar(void) -{ - MapVars[ReadMapVar()] *= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdMulWorldVar(void) -{ - WorldVars[ReadWorldVar()] *= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdDivScriptVar(void) -{ - ACScript->vars[ReadScriptVar()] /= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdDivMapVar(void) -{ - MapVars[ReadMapVar()] /= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdDivWorldVar(void) -{ - WorldVars[ReadWorldVar()] /= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdModScriptVar(void) -{ - ACScript->vars[ReadScriptVar()] %= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdModMapVar(void) -{ - MapVars[ReadMapVar()] %= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdModWorldVar(void) -{ - WorldVars[ReadWorldVar()] %= Pop(); - return SCRIPT_CONTINUE; -} - -static int CmdIncScriptVar(void) -{ - ++ACScript->vars[ReadScriptVar()]; - return SCRIPT_CONTINUE; -} - -static int CmdIncMapVar(void) -{ - ++MapVars[ReadMapVar()]; - return SCRIPT_CONTINUE; -} - -static int CmdIncWorldVar(void) -{ - ++WorldVars[ReadWorldVar()]; - return SCRIPT_CONTINUE; -} - -static int CmdDecScriptVar(void) -{ - --ACScript->vars[ReadScriptVar()]; - return SCRIPT_CONTINUE; -} - -static int CmdDecMapVar(void) -{ - --MapVars[ReadMapVar()]; - return SCRIPT_CONTINUE; -} - -static int CmdDecWorldVar(void) -{ - --WorldVars[ReadWorldVar()]; - return SCRIPT_CONTINUE; -} - -static int CmdGoto(void) -{ - PCodeOffset = ReadOffset(); - return SCRIPT_CONTINUE; -} - -static int CmdIfGoto(void) -{ - int offset; - - offset = ReadOffset(); - - if (Pop() != 0) - { - PCodeOffset = offset; - } - return SCRIPT_CONTINUE; -} - -static int CmdDrop(void) -{ - Drop(); - return SCRIPT_CONTINUE; -} - -static int CmdDelay(void) -{ - ACScript->delayCount = Pop(); - return SCRIPT_STOP; -} - -static int CmdDelayDirect(void) -{ - ACScript->delayCount = ReadCodeInt(); - return SCRIPT_STOP; -} - -static int CmdRandom(void) -{ - int low; - int high; - - high = Pop(); - low = Pop(); - Push(low + (P_Random() % (high - low + 1))); - return SCRIPT_CONTINUE; -} - -static int CmdRandomDirect(void) -{ - int low; - int high; - - low = ReadCodeInt(); - high = ReadCodeInt(); - Push(low + (P_Random() % (high - low + 1))); - return SCRIPT_CONTINUE; -} - -static int CmdThingCount(void) -{ - int tid; - - tid = Pop(); - ThingCount(Pop(), tid); - return SCRIPT_CONTINUE; -} - -static int CmdThingCountDirect(void) -{ - int type; - - type = ReadCodeInt(); - ThingCount(type, ReadCodeInt()); - return SCRIPT_CONTINUE; -} - -static void ThingCount(int type, int tid) -{ - int count; - int searcher; - mobj_t *mobj; - mobjtype_t moType; - thinker_t *think; - - if (!(type + tid)) - { // Nothing to count - return; - } - moType = TranslateThingType[type]; - count = 0; - searcher = -1; - if (tid) - { // Count TID things - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - if (type == 0) - { // Just count TIDs - count++; - } - else if (moType == mobj->type) - { - if (mobj->flags & MF_COUNTKILL && mobj->health <= 0) - { // Don't count dead monsters - continue; - } - count++; - } - } - } - else - { // Count only types - for (think = thinkercap.next; think != &thinkercap; - think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mobj = (mobj_t *) think; - if (mobj->type != moType) - { // Doesn't match - continue; - } - if (mobj->flags & MF_COUNTKILL && mobj->health <= 0) - { // Don't count dead monsters - continue; - } - count++; - } - } - Push(count); -} - -static int CmdTagWait(void) -{ - ACSInfo[ACScript->infoIndex].waitValue = Pop(); - ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG; - return SCRIPT_STOP; -} - -static int CmdTagWaitDirect(void) -{ - ACSInfo[ACScript->infoIndex].waitValue = ReadCodeInt(); - ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG; - return SCRIPT_STOP; -} - -static int CmdPolyWait(void) -{ - ACSInfo[ACScript->infoIndex].waitValue = Pop(); - ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY; - return SCRIPT_STOP; -} - -static int CmdPolyWaitDirect(void) -{ - ACSInfo[ACScript->infoIndex].waitValue = ReadCodeInt(); - ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY; - return SCRIPT_STOP; -} - -static int CmdChangeFloor(void) -{ - int tag; - int flat; - int sectorIndex; - - flat = R_FlatNumForName(StringLookup(Pop())); - tag = Pop(); - sectorIndex = -1; - while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) - { - sectors[sectorIndex].floorpic = flat; - } - return SCRIPT_CONTINUE; -} - -static int CmdChangeFloorDirect(void) -{ - int tag; - int flat; - int sectorIndex; - - tag = ReadCodeInt(); - flat = R_FlatNumForName(StringLookup(ReadCodeInt())); - sectorIndex = -1; - while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) - { - sectors[sectorIndex].floorpic = flat; - } - return SCRIPT_CONTINUE; -} - -static int CmdChangeCeiling(void) -{ - int tag; - int flat; - int sectorIndex; - - flat = R_FlatNumForName(StringLookup(Pop())); - tag = Pop(); - sectorIndex = -1; - while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) - { - sectors[sectorIndex].ceilingpic = flat; - } - return SCRIPT_CONTINUE; -} - -static int CmdChangeCeilingDirect(void) -{ - int tag; - int flat; - int sectorIndex; - - tag = ReadCodeInt(); - flat = R_FlatNumForName(StringLookup(ReadCodeInt())); - sectorIndex = -1; - while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) - { - sectors[sectorIndex].ceilingpic = flat; - } - return SCRIPT_CONTINUE; -} - -static int CmdRestart(void) -{ - PCodeOffset = ACSInfo[ACScript->infoIndex].offset; - return SCRIPT_CONTINUE; -} - -static int CmdAndLogical(void) -{ - Push(Pop() && Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdOrLogical(void) -{ - Push(Pop() || Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdAndBitwise(void) -{ - Push(Pop() & Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdOrBitwise(void) -{ - Push(Pop() | Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdEorBitwise(void) -{ - Push(Pop() ^ Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdNegateLogical(void) -{ - Push(!Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdLShift(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() << operand2); - return SCRIPT_CONTINUE; -} - -static int CmdRShift(void) -{ - int operand2; - - operand2 = Pop(); - Push(Pop() >> operand2); - return SCRIPT_CONTINUE; -} - -static int CmdUnaryMinus(void) -{ - Push(-Pop()); - return SCRIPT_CONTINUE; -} - -static int CmdIfNotGoto(void) -{ - int offset; - - offset = ReadOffset(); - - if (Pop() == 0) - { - PCodeOffset = offset; - } - return SCRIPT_CONTINUE; -} - -static int CmdLineSide(void) -{ - Push(ACScript->side); - return SCRIPT_CONTINUE; -} - -static int CmdScriptWait(void) -{ - ACSInfo[ACScript->infoIndex].waitValue = Pop(); - ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT; - return SCRIPT_STOP; -} - -static int CmdScriptWaitDirect(void) -{ - ACSInfo[ACScript->infoIndex].waitValue = ReadCodeInt(); - ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT; - return SCRIPT_STOP; -} - -static int CmdClearLineSpecial(void) -{ - if (ACScript->line) - { - ACScript->line->special = 0; - } - return SCRIPT_CONTINUE; -} - -static int CmdCaseGoto(void) -{ - int value; - int offset; - - value = ReadCodeInt(); - offset = ReadOffset(); - - if (Top() == value) - { - PCodeOffset = offset; - Drop(); - } - - return SCRIPT_CONTINUE; -} - -static int CmdBeginPrint(void) -{ - *PrintBuffer = 0; - return SCRIPT_CONTINUE; -} - -static int CmdEndPrint(void) -{ - player_t *player; - - if (ACScript->activator && ACScript->activator->player) - { - player = ACScript->activator->player; - } - else - { - player = &players[consoleplayer]; - } - P_SetMessage(player, PrintBuffer, true); - return SCRIPT_CONTINUE; -} - -static int CmdEndPrintBold(void) -{ - int i; - - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - P_SetYellowMessage(&players[i], PrintBuffer, true); - } - } - return SCRIPT_CONTINUE; -} - -static int CmdPrintString(void) -{ - M_StringConcat(PrintBuffer, StringLookup(Pop()), sizeof(PrintBuffer)); - return SCRIPT_CONTINUE; -} - -static int CmdPrintNumber(void) -{ - char tempStr[16]; - - M_snprintf(tempStr, sizeof(tempStr), "%d", Pop()); - M_StringConcat(PrintBuffer, tempStr, sizeof(PrintBuffer)); - return SCRIPT_CONTINUE; -} - -static int CmdPrintCharacter(void) -{ - char tempStr[2]; - - tempStr[0] = Pop(); - tempStr[1] = '\0'; - M_StringConcat(PrintBuffer, tempStr, sizeof(PrintBuffer)); - - return SCRIPT_CONTINUE; -} - -static int CmdPlayerCount(void) -{ - int i; - int count; - - count = 0; - for (i = 0; i < maxplayers; i++) - { - count += playeringame[i]; - } - Push(count); - return SCRIPT_CONTINUE; -} - -static int CmdGameType(void) -{ - int gametype; - - if (netgame == false) - { - gametype = GAME_SINGLE_PLAYER; - } - else if (deathmatch) - { - gametype = GAME_NET_DEATHMATCH; - } - else - { - gametype = GAME_NET_COOPERATIVE; - } - Push(gametype); - return SCRIPT_CONTINUE; -} - -static int CmdGameSkill(void) -{ - Push(gameskill); - return SCRIPT_CONTINUE; -} - -static int CmdTimer(void) -{ - Push(leveltime); - return SCRIPT_CONTINUE; -} - -static int CmdSectorSound(void) -{ - int volume; - mobj_t *mobj; - - mobj = NULL; - if (ACScript->line) - { - mobj = (mobj_t *) & ACScript->line->frontsector->soundorg; - } - volume = Pop(); - S_StartSoundAtVolume(mobj, S_GetSoundID(StringLookup(Pop())), volume); - return SCRIPT_CONTINUE; -} - -static int CmdThingSound(void) -{ - int tid; - int sound; - int volume; - mobj_t *mobj; - int searcher; - - volume = Pop(); - sound = S_GetSoundID(StringLookup(Pop())); - tid = Pop(); - searcher = -1; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - S_StartSoundAtVolume(mobj, sound, volume); - } - return SCRIPT_CONTINUE; -} - -static int CmdAmbientSound(void) -{ - int volume; - - volume = Pop(); - S_StartSoundAtVolume(NULL, S_GetSoundID(StringLookup(Pop())), volume); - return SCRIPT_CONTINUE; -} - -static int CmdSoundSequence(void) -{ - mobj_t *mobj; - - mobj = NULL; - if (ACScript->line) - { - mobj = (mobj_t *) & ACScript->line->frontsector->soundorg; - } - SN_StartSequenceName(mobj, StringLookup(Pop())); - return SCRIPT_CONTINUE; -} - -static int CmdSetLineTexture(void) -{ - line_t *line; - int lineTag; - int side; - int position; - int texture; - int searcher; - - texture = R_TextureNumForName(StringLookup(Pop())); - position = Pop(); - side = Pop(); - lineTag = Pop(); - searcher = -1; - while ((line = P_FindLine(lineTag, &searcher)) != NULL) - { - if (position == TEXTURE_MIDDLE) - { - sides[line->sidenum[side]].midtexture = texture; - } - else if (position == TEXTURE_BOTTOM) - { - sides[line->sidenum[side]].bottomtexture = texture; - } - else - { // TEXTURE_TOP - sides[line->sidenum[side]].toptexture = texture; - } - } - return SCRIPT_CONTINUE; -} - -static int CmdSetLineBlocking(void) -{ - line_t *line; - int lineTag; - boolean blocking; - int searcher; - - blocking = Pop()? ML_BLOCKING : 0; - lineTag = Pop(); - searcher = -1; - while ((line = P_FindLine(lineTag, &searcher)) != NULL) - { - line->flags = (line->flags & ~ML_BLOCKING) | blocking; - } - return SCRIPT_CONTINUE; -} - -static int CmdSetLineSpecial(void) -{ - line_t *line; - int lineTag; - int special, arg1, arg2, arg3, arg4, arg5; - int searcher; - - arg5 = Pop(); - arg4 = Pop(); - arg3 = Pop(); - arg2 = Pop(); - arg1 = Pop(); - special = Pop(); - lineTag = Pop(); - searcher = -1; - while ((line = P_FindLine(lineTag, &searcher)) != NULL) - { - line->special = special; - line->arg1 = arg1; - line->arg2 = arg2; - line->arg3 = arg3; - line->arg4 = arg4; - line->arg5 = arg5; - } - return SCRIPT_CONTINUE; -} diff --git a/games/NXDoom/src/hexen/p_action.h b/games/NXDoom/src/hexen/p_action.h deleted file mode 100644 index 8336fbe582a..00000000000 --- a/games/NXDoom/src/hexen/p_action.h +++ /dev/null @@ -1,240 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// External definitions for action pointer functions. -// - -#ifndef HEXEN_P_ACTION_H -#define HEXEN_P_ACTION_H - - -void A_FreeTargMobj(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FlameCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_HideThing(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_RestoreSpecialThing1(mobj_t *thing, player_t *player, pspdef_t *psp); -void A_RestoreSpecialThing2(mobj_t *thing, player_t *player, pspdef_t *psp); -void A_RestoreArtifact(mobj_t *arti, player_t *player, pspdef_t *psp); -void A_Summon(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ThrustInitUp(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ThrustInitDn(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ThrustRaise(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ThrustBlock(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ThrustImpale(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ThrustLower(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_TeloSpawnC(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_TeloSpawnB(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_TeloSpawnA(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_TeloSpawnD(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CheckTeleRing(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FogSpawn(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FogMove(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Quake(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ContMobjSound(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Scream(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PoisonBagInit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PoisonBagDamage(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PoisonBagCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CheckThrowBomb(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_NoGravity(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PotteryExplode(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PotteryChooseBit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PotteryCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CorpseBloodDrip(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CorpseExplode(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LeafSpawn(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LeafThrust(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LeafCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BridgeInit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BridgeOrbit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_TreeDeath(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PoisonShroom(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Pain(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SoAExplode(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BellReset1(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BellReset2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Light0(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WeaponReady(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Lower(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Raise(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FPunchAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ReFire(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FAxeAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FHammerAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FHammerThrow(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FSwordAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FSwordFlames(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CMaceAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CStaffInitBlink(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CStaffCheckBlink(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CStaffCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CStaffMissileSlither(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CFlameAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CFlameRotate(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CFlamePuff(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CFlameMissile(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolyAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolyPalette(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolySeek(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolyCheckScream(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolyTail(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolySpawnPuff(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolyAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MWandAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LightningReady(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MLightningAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LightningZap(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LightningClip(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LightningRemove(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_LastZap(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ZapMimic(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MStaffPalette(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MStaffWeave(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MStaffTrack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SnoutAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FireConePL1(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ShedShard(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_AddPlayerCorpse(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SkullPop(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FreezeDeath(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CheckBurnGone(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CheckSkullFloor(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CheckSkullDone(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SpeedFade(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceSetTics(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceCheckHeadDone(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PigPain(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PigLook(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PigChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FaceTarget(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_PigAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_QueueCorpse(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Look(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Chase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CentaurAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CentaurAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SetReflective(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CentaurDefend(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_UnSetReflective(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CentaurDropStuff(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CheckFloor(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DemonAttack1(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DemonAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DemonDeath(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_Demon2Death(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithRaiseInit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithRaise(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithInit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithLook(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithFX3(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithMelee(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithMissile(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_WraithFX2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurFade1(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurFade2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurRoam(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurAtk1(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurDecide(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurAtk2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurAtk3(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurCharge(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SmokePuffExit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurFade0(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MntrFloorFire(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentHumpDecide(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentUnHide(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentRaiseHump(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentLowerHump(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentHide(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentBirthScream(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SetShootable(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentCheckForAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_UnSetShootable(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentDiveSound(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentWalk(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentChooseAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentMeleeAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentMissileAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentHeadPop(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentSpawnGibs(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SerpentHeadCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FloatGib(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DelayGib(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SinkGib(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopDecide(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopDoBlur(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopSpawnBlur(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopPainBlur(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopPuff(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SetAltShadow(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopMissileWeave(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BishopMissileSeek(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonInitFlight(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonFlap(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonFlight(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonPain(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonCheckCrash(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DragonFX2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ESound(mobj_t *mo, player_t *player, pspdef_t *psp); -void A_EttinAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DropMace(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FiredRocks(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_UnSetInvulnerable(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FiredChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FiredAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FiredSplotch(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SmBounce(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceGuyLook(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceGuyChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceGuyAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceGuyDie(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceGuyMissilePuff(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_IceGuyMissileExplode(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ClassBossHealth(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FastChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FighterAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_ClericAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MageAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcBallPop(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcFX2Split(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcFX2Orbit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcererBishopEntry(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SpawnBishop(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcFX4Check(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxStep2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxChase(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxStep(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxDecide(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxMissile(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxCommand(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KoraxBonePop(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KSpiritRoam(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KBoltRaise(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_KBolt(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BatSpawnInit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BatSpawn(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BatMove(mobj_t *actor, player_t *player, pspdef_t *psp); - - -#endif // HEXEN_P_ACTION_H diff --git a/games/NXDoom/src/hexen/p_anim.c b/games/NXDoom/src/hexen/p_anim.c deleted file mode 100644 index 12f90a5edd0..00000000000 --- a/games/NXDoom/src/hexen/p_anim.c +++ /dev/null @@ -1,477 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -#define ANIM_SCRIPT_NAME "ANIMDEFS" -#define MAX_ANIM_DEFS 20 -#define MAX_FRAME_DEFS 96 -#define ANIM_FLAT 0 -#define ANIM_TEXTURE 1 -#define SCI_FLAT "flat" -#define SCI_TEXTURE "texture" -#define SCI_PIC "pic" -#define SCI_TICS "tics" -#define SCI_RAND "rand" - -#define LIGHTNING_SPECIAL 198 -#define LIGHTNING_SPECIAL2 199 -#define SKYCHANGE_SPECIAL 200 - -// TYPES ------------------------------------------------------------------- - -typedef struct -{ - int index; - int tics; -} frameDef_t; - -typedef struct -{ - int type; - int index; - int tics; - int currentFrameDef; - int startFrameDef; - int endFrameDef; -} animDef_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void P_LightningFlash(void); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -fixed_t Sky1ScrollDelta; -fixed_t Sky2ScrollDelta; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static animDef_t AnimDefs[MAX_ANIM_DEFS]; -static frameDef_t FrameDefs[MAX_FRAME_DEFS]; -static int AnimDefCount; -static boolean LevelHasLightning; -static int NextLightningFlash; -static int LightningFlash; -static int *LightningLightLevels; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// P_AnimateSurfaces -// -//========================================================================== - -void P_AnimateSurfaces(void) -{ - int i; - animDef_t *ad; - line_t *line; - - // Animate flats and textures - for (i = 0; i < AnimDefCount; i++) - { - ad = &AnimDefs[i]; - ad->tics--; - if (ad->tics == 0) - { - if (ad->currentFrameDef == ad->endFrameDef) - { - ad->currentFrameDef = ad->startFrameDef; - } - else - { - ad->currentFrameDef++; - } - ad->tics = FrameDefs[ad->currentFrameDef].tics; - if (ad->tics > 255) - { // Random tics - ad->tics = (ad->tics >> 16) - + P_Random() % ((ad->tics & 0xff00) >> 8); - } - if (ad->type == ANIM_FLAT) - { - flattranslation[ad->index] = - FrameDefs[ad->currentFrameDef].index; - } - else - { // Texture - texturetranslation[ad->index] = - FrameDefs[ad->currentFrameDef].index; - } - } - } - - // Update scrolling textures - for (i = 0; i < numlinespecials; i++) - { - line = linespeciallist[i]; - switch (line->special) - { - case 100: // Scroll_Texture_Left - sides[line->sidenum[0]].textureoffset += line->arg1 << 10; - break; - case 101: // Scroll_Texture_Right - sides[line->sidenum[0]].textureoffset -= line->arg1 << 10; - break; - case 102: // Scroll_Texture_Up - sides[line->sidenum[0]].rowoffset += line->arg1 << 10; - break; - case 103: // Scroll_Texture_Down - sides[line->sidenum[0]].rowoffset -= line->arg1 << 10; - break; - } - } - - // Update sky column offsets - Sky1ColumnOffset += Sky1ScrollDelta; - Sky2ColumnOffset += Sky2ScrollDelta; - - if (LevelHasLightning) - { - if (!NextLightningFlash || LightningFlash) - { - P_LightningFlash(); - } - else - { - NextLightningFlash--; - } - } -} - -//========================================================================== -// -// P_LightningFlash -// -//========================================================================== - -static void P_LightningFlash(void) -{ - int i; - sector_t *tempSec; - int *tempLight; - boolean foundSec; - int flashLight; - - if (LightningFlash) - { - LightningFlash--; - if (LightningFlash) - { - tempLight = LightningLightLevels; - tempSec = sectors; - for (i = 0; i < numsectors; i++, tempSec++) - { - if (tempSec->ceilingpic == skyflatnum - || tempSec->special == LIGHTNING_SPECIAL - || tempSec->special == LIGHTNING_SPECIAL2) - { - if (*tempLight < tempSec->lightlevel - 4) - { - tempSec->lightlevel -= 4; - } - tempLight++; - } - } - } - else - { // remove the alternate lightning flash special - tempLight = LightningLightLevels; - tempSec = sectors; - for (i = 0; i < numsectors; i++, tempSec++) - { - if (tempSec->ceilingpic == skyflatnum - || tempSec->special == LIGHTNING_SPECIAL - || tempSec->special == LIGHTNING_SPECIAL2) - { - tempSec->lightlevel = *tempLight; - tempLight++; - } - } - Sky1Texture = P_GetMapSky1Texture(gamemap); - } - return; - } - LightningFlash = (P_Random() & 7) + 8; - flashLight = 200 + (P_Random() & 31); - tempSec = sectors; - tempLight = LightningLightLevels; - foundSec = false; - for (i = 0; i < numsectors; i++, tempSec++) - { - if (tempSec->ceilingpic == skyflatnum - || tempSec->special == LIGHTNING_SPECIAL - || tempSec->special == LIGHTNING_SPECIAL2) - { - *tempLight = tempSec->lightlevel; - if (tempSec->special == LIGHTNING_SPECIAL) - { - tempSec->lightlevel += 64; - if (tempSec->lightlevel > flashLight) - { - tempSec->lightlevel = flashLight; - } - } - else if (tempSec->special == LIGHTNING_SPECIAL2) - { - tempSec->lightlevel += 32; - if (tempSec->lightlevel > flashLight) - { - tempSec->lightlevel = flashLight; - } - } - else - { - tempSec->lightlevel = flashLight; - } - if (tempSec->lightlevel < *tempLight) - { - tempSec->lightlevel = *tempLight; - } - tempLight++; - foundSec = true; - } - } - if (foundSec) - { - Sky1Texture = P_GetMapSky2Texture(gamemap); // set alternate sky - S_StartSound(NULL, SFX_THUNDER_CRASH); - } - // Calculate the next lighting flash - if (!NextLightningFlash) - { - if (P_Random() < 50) - { // Immediate Quick flash - NextLightningFlash = (P_Random() & 15) + 16; - } - else - { - if (P_Random() < 128 && !(leveltime & 32)) - { - NextLightningFlash = ((P_Random() & 7) + 2) * 35; - } - else - { - NextLightningFlash = ((P_Random() & 15) + 5) * 35; - } - } - } -} - -//========================================================================== -// -// P_ForceLightning -// -//========================================================================== - -void P_ForceLightning(void) -{ - NextLightningFlash = 0; -} - -//========================================================================== -// -// P_InitLightning -// -//========================================================================== - -void P_InitLightning(void) -{ - int i; - int secCount; - - if (!P_GetMapLightning(gamemap)) - { - LevelHasLightning = false; - LightningFlash = 0; - return; - } - LightningFlash = 0; - secCount = 0; - for (i = 0; i < numsectors; i++) - { - if (sectors[i].ceilingpic == skyflatnum - || sectors[i].special == LIGHTNING_SPECIAL - || sectors[i].special == LIGHTNING_SPECIAL2) - { - secCount++; - } - } - if (secCount) - { - LevelHasLightning = true; - } - else - { - LevelHasLightning = false; - return; - } - LightningLightLevels = (int *) Z_Malloc(secCount * sizeof(int), PU_LEVEL, - NULL); - NextLightningFlash = ((P_Random() & 15) + 5) * 35; // don't flash at level start -} - -//========================================================================== -// -// P_InitFTAnims -// -// Initialize flat and texture animation lists. -// -//========================================================================== - -void P_InitFTAnims(void) -{ - int base; - int mod; - int fd; - animDef_t *ad; - boolean ignore; - boolean done; - - fd = 0; - ad = AnimDefs; - AnimDefCount = 0; - SC_Open(ANIM_SCRIPT_NAME); - while (SC_GetString()) - { - if (AnimDefCount == MAX_ANIM_DEFS) - { - I_Error("P_InitFTAnims: too many AnimDefs."); - } - if (SC_Compare(SCI_FLAT)) - { - ad->type = ANIM_FLAT; - } - else if (SC_Compare(SCI_TEXTURE)) - { - ad->type = ANIM_TEXTURE; - } - else - { - SC_ScriptError(NULL); - } - SC_MustGetString(); // Name - ignore = false; - if (ad->type == ANIM_FLAT) - { - if (W_CheckNumForName(sc_String) == -1) - { - ignore = true; - } - else - { - ad->index = R_FlatNumForName(sc_String); - } - } - else - { // Texture - if (R_CheckTextureNumForName(sc_String) == -1) - { - ignore = true; - } - else - { - ad->index = R_TextureNumForName(sc_String); - } - } - ad->startFrameDef = fd; - done = false; - while (done == false) - { - if (SC_GetString()) - { - if (SC_Compare(SCI_PIC)) - { - if (fd == MAX_FRAME_DEFS) - { - I_Error("P_InitFTAnims: too many FrameDefs."); - } - SC_MustGetNumber(); - if (ignore == false) - { - FrameDefs[fd].index = ad->index + sc_Number - 1; - } - SC_MustGetString(); - if (SC_Compare(SCI_TICS)) - { - SC_MustGetNumber(); - if (ignore == false) - { - FrameDefs[fd].tics = sc_Number; - fd++; - } - } - else if (SC_Compare(SCI_RAND)) - { - SC_MustGetNumber(); - base = sc_Number; - SC_MustGetNumber(); - if (ignore == false) - { - mod = sc_Number - base + 1; - FrameDefs[fd].tics = (base << 16) + (mod << 8); - fd++; - } - } - else - { - SC_ScriptError(NULL); - } - } - else - { - SC_UnGet(); - done = true; - } - } - else - { - done = true; - } - } - if ((ignore == false) && (fd - ad->startFrameDef < 2)) - { - I_Error("P_InitFTAnims: AnimDef has framecount < 2."); - } - if (ignore == false) - { - ad->endFrameDef = fd - 1; - ad->currentFrameDef = ad->endFrameDef; - ad->tics = 1; // Force 1st game tic to animate - AnimDefCount++; - ad++; - } - } - SC_Close(); -} diff --git a/games/NXDoom/src/hexen/p_ceilng.c b/games/NXDoom/src/hexen/p_ceilng.c deleted file mode 100644 index dfe0ba66f3f..00000000000 --- a/games/NXDoom/src/hexen/p_ceilng.c +++ /dev/null @@ -1,303 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "p_local.h" - -//================================================================== -//================================================================== -// -// CEILINGS -// -//================================================================== -//================================================================== - -ceiling_t *activeceilings[MAXCEILINGS]; - -//================================================================== -// -// T_MoveCeiling -// -//================================================================== -void T_MoveCeiling(thinker_t *thinker) -{ - ceiling_t *ceiling = (ceiling_t *) thinker; - result_e res; - - switch (ceiling->direction) - { -// case 0: // IN STASIS -// break; - case 1: // UP - res = T_MovePlane(ceiling->sector, ceiling->speed, - ceiling->topheight, false, 1, - ceiling->direction); - if (res == RES_PASTDEST) - { - SN_StopSequence((mobj_t *) & ceiling->sector->soundorg); - switch (ceiling->type) - { - case CLEV_CRUSHANDRAISE: - ceiling->direction = -1; - ceiling->speed = ceiling->speed * 2; - break; - default: - P_RemoveActiveCeiling(ceiling); - break; - } - } - break; - case -1: // DOWN - res = T_MovePlane(ceiling->sector, ceiling->speed, - ceiling->bottomheight, ceiling->crush, 1, - ceiling->direction); - if (res == RES_PASTDEST) - { - SN_StopSequence((mobj_t *) & ceiling->sector->soundorg); - switch (ceiling->type) - { - case CLEV_CRUSHANDRAISE: - case CLEV_CRUSHRAISEANDSTAY: - ceiling->direction = 1; - ceiling->speed = ceiling->speed / 2; - break; - default: - P_RemoveActiveCeiling(ceiling); - break; - } - } - else if (res == RES_CRUSHED) - { - switch (ceiling->type) - { - case CLEV_CRUSHANDRAISE: - case CLEV_LOWERANDCRUSH: - case CLEV_CRUSHRAISEANDSTAY: - //ceiling->speed = ceiling->speed/4; - break; - default: - break; - } - } - break; - } -} - -//================================================================== -// -// EV_DoCeiling -// Move a ceiling up/down and all around! -// -//================================================================== -int EV_DoCeiling(line_t * line, byte * arg, ceiling_e type) -{ - int secnum, rtn; - sector_t *sec; - ceiling_t *ceiling; - - secnum = -1; - rtn = 0; - -/* Old Ceiling stasis code - // - // Reactivate in-stasis ceilings...for certain types. - // - switch(type) - { - case CLEV_CRUSHANDRAISE: - P_ActivateInStasisCeiling(line); - default: - break; - } -*/ - while ((secnum = P_FindSectorFromTag(arg[0], secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - // - // new door thinker - // - rtn = 1; - ceiling = Z_Malloc(sizeof(*ceiling), PU_LEVSPEC, 0); - P_AddThinker(&ceiling->thinker); - sec->specialdata = ceiling; - ceiling->thinker.function = T_MoveCeiling; - ceiling->sector = sec; - ceiling->crush = 0; - ceiling->speed = arg[1] * (FRACUNIT / 8); - switch (type) - { - case CLEV_CRUSHRAISEANDSTAY: - ceiling->crush = arg[2]; // arg[2] = crushing value - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight + (8 * FRACUNIT); - ceiling->direction = -1; - break; - case CLEV_CRUSHANDRAISE: - ceiling->topheight = sec->ceilingheight; - case CLEV_LOWERANDCRUSH: - ceiling->crush = arg[2]; // arg[2] = crushing value - case CLEV_LOWERTOFLOOR: - ceiling->bottomheight = sec->floorheight; - if (type != CLEV_LOWERTOFLOOR) - { - ceiling->bottomheight += 8 * FRACUNIT; - } - ceiling->direction = -1; - break; - case CLEV_RAISETOHIGHEST: - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - break; - case CLEV_LOWERBYVALUE: - ceiling->bottomheight = - sec->ceilingheight - arg[2] * FRACUNIT; - ceiling->direction = -1; - break; - case CLEV_RAISEBYVALUE: - ceiling->topheight = sec->ceilingheight + arg[2] * FRACUNIT; - ceiling->direction = 1; - break; - case CLEV_MOVETOVALUETIMES8: - { - int destHeight = arg[2] * FRACUNIT * 8; - - if (arg[3]) - { - destHeight = -destHeight; - } - if (sec->ceilingheight <= destHeight) - { - ceiling->direction = 1; - ceiling->topheight = destHeight; - if (sec->ceilingheight == destHeight) - { - rtn = 0; - } - } - else if (sec->ceilingheight > destHeight) - { - ceiling->direction = -1; - ceiling->bottomheight = destHeight; - } - break; - } - default: - rtn = 0; - break; - } - ceiling->tag = sec->tag; - ceiling->type = type; - P_AddActiveCeiling(ceiling); - if (rtn) - { - SN_StartSequence((mobj_t *) & ceiling->sector->soundorg, - SEQ_PLATFORM + ceiling->sector->seqType); - } - } - return rtn; -} - -//================================================================== -// -// Add an active ceiling -// -//================================================================== -void P_AddActiveCeiling(ceiling_t * c) -{ - int i; - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] == NULL) - { - activeceilings[i] = c; - return; - } -} - -//================================================================== -// -// Remove a ceiling's thinker -// -//================================================================== -void P_RemoveActiveCeiling(ceiling_t * c) -{ - int i; - - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] == c) - { - activeceilings[i]->sector->specialdata = NULL; - P_RemoveThinker(&activeceilings[i]->thinker); - P_TagFinished(activeceilings[i]->sector->tag); - activeceilings[i] = NULL; - break; - } -} - -#if 0 -//================================================================== -// -// Restart a ceiling that's in-stasis -// -//================================================================== -void P_ActivateInStasisCeiling(line_t * line) -{ - int i; - - for (i = 0; i < MAXCEILINGS; i++) - if (activeceilings[i] && (activeceilings[i]->tag == line->arg1) && - (activeceilings[i]->direction == 0)) - { - activeceilings[i]->direction = activeceilings[i]->olddirection; - activeceilings[i]->thinker.function = T_MoveCeiling; - SN_StartSequence((mobj_t *) & activeceilings[i]->sector->soundorg, - SEQ_PLATFORM + - activeceilings[i]->sector->seqType); - } -} -#endif - -//================================================================== -// -// EV_CeilingCrushStop -// Stop a ceiling from crushing! -// -//================================================================== - -int EV_CeilingCrushStop(line_t * line, byte * args) -{ - int i; - int rtn; - - rtn = 0; - for (i = 0; i < MAXCEILINGS; i++) - { - if (activeceilings[i] && activeceilings[i]->tag == args[0]) - { - rtn = 1; - SN_StopSequence((mobj_t *) & activeceilings[i]->sector->soundorg); - activeceilings[i]->sector->specialdata = NULL; - P_RemoveThinker(&activeceilings[i]->thinker); - P_TagFinished(activeceilings[i]->sector->tag); - activeceilings[i] = NULL; - break; - } - } - return rtn; -} diff --git a/games/NXDoom/src/hexen/p_doors.c b/games/NXDoom/src/hexen/p_doors.c deleted file mode 100644 index eb526f2d541..00000000000 --- a/games/NXDoom/src/hexen/p_doors.c +++ /dev/null @@ -1,319 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "p_local.h" - -//================================================================== -//================================================================== -// -// VERTICAL DOORS -// -//================================================================== -//================================================================== - -//================================================================== -// -// T_VerticalDoor -// -//================================================================== -void T_VerticalDoor(thinker_t *thinker) -{ - vldoor_t *door = (vldoor_t *) thinker; - result_e res; - - switch (door->direction) - { - case 0: // WAITING - if (!--door->topcountdown) - switch (door->type) - { - case DREV_NORMAL: - door->direction = -1; // time to go back down - SN_StartSequence((mobj_t *) & door->sector->soundorg, - SEQ_DOOR_STONE + - door->sector->seqType); - break; - case DREV_CLOSE30THENOPEN: - door->direction = 1; - break; - default: - break; - } - break; - case 2: // INITIAL WAIT - if (!--door->topcountdown) - { - switch (door->type) - { - case DREV_RAISEIN5MINS: - door->direction = 1; - door->type = DREV_NORMAL; - break; - default: - break; - } - } - break; - case -1: // DOWN - res = T_MovePlane(door->sector, door->speed, - door->sector->floorheight, false, 1, - door->direction); - if (res == RES_PASTDEST) - { - SN_StopSequence((mobj_t *) & door->sector->soundorg); - switch (door->type) - { - case DREV_NORMAL: - case DREV_CLOSE: - door->sector->specialdata = NULL; - P_TagFinished(door->sector->tag); - P_RemoveThinker(&door->thinker); // unlink and free - break; - case DREV_CLOSE30THENOPEN: - door->direction = 0; - door->topcountdown = 35 * 30; - break; - default: - break; - } - } - else if (res == RES_CRUSHED) - { - switch (door->type) - { - case DREV_CLOSE: // DON'T GO BACK UP! - break; - default: - door->direction = 1; - break; - } - } - break; - case 1: // UP - res = T_MovePlane(door->sector, door->speed, - door->topheight, false, 1, door->direction); - if (res == RES_PASTDEST) - { - SN_StopSequence((mobj_t *) & door->sector->soundorg); - switch (door->type) - { - case DREV_NORMAL: - door->direction = 0; // wait at top - door->topcountdown = door->topwait; - break; - case DREV_CLOSE30THENOPEN: - case DREV_OPEN: - door->sector->specialdata = NULL; - P_TagFinished(door->sector->tag); - P_RemoveThinker(&door->thinker); // unlink and free - break; - default: - break; - } - } - break; - } -} - -//---------------------------------------------------------------------------- -// -// EV_DoDoor -// -// Move a door up/down -// -//---------------------------------------------------------------------------- - -int EV_DoDoor(line_t * line, byte * args, vldoor_e type) -{ - int secnum; - int retcode; - sector_t *sec; - vldoor_t *door; - fixed_t speed; - - speed = args[1] * FRACUNIT / 8; - secnum = -1; - retcode = 0; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - { - continue; - } - // Add new door thinker - retcode = 1; - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - switch (type) - { - case DREV_CLOSE: - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; - door->direction = -1; - break; - case DREV_CLOSE30THENOPEN: - door->topheight = sec->ceilingheight; - door->direction = -1; - break; - case DREV_NORMAL: - case DREV_OPEN: - door->direction = 1; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; - break; - default: - break; - } - door->type = type; - door->speed = speed; - door->topwait = args[2]; // line->arg3 - SN_StartSequence((mobj_t *) & door->sector->soundorg, - SEQ_DOOR_STONE + door->sector->seqType); - } - return (retcode); -} - -//================================================================== -// -// EV_VerticalDoor : open a door manually, no tag value -// -//================================================================== -boolean EV_VerticalDoor(line_t * line, mobj_t * thing) -{ - sector_t *sec; - vldoor_t *door; - int side; - - side = 0; // only front sides can be used - - // if the sector has an active thinker, use it - sec = sides[line->sidenum[side ^ 1]].sector; - if (sec->specialdata) - { - return false; -/* - door = sec->specialdata; - switch(line->special) - { // only for raise doors - case 12: - if(door->direction == -1) - { - door->direction = 1; // go back up - } - else - { - if(!thing->player) - { // Monsters don't close doors - return; - } - door->direction = -1; // start going down immediately - } - return; - } -*/ - } - // - // new door thinker - // - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - door->direction = 1; - switch (line->special) - { - case 11: - door->type = DREV_OPEN; - line->special = 0; - break; - case 12: - case 13: - door->type = DREV_NORMAL; - break; - default: - door->type = DREV_NORMAL; - break; - } - door->speed = line->arg2 * (FRACUNIT / 8); - door->topwait = line->arg3; - - // - // find the top and bottom of the movement range - // - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4 * FRACUNIT; - SN_StartSequence((mobj_t *) & door->sector->soundorg, - SEQ_DOOR_STONE + door->sector->seqType); - return true; -} - -//================================================================== -// -// Spawn a door that closes after 30 seconds -// -//================================================================== - -/* -void P_SpawnDoorCloseIn30(sector_t *sec) -{ - vldoor_t *door; - - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - sec->special = 0; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - door->direction = 0; - door->type = DREV_NORMAL; - door->speed = VDOORSPEED; - door->topcountdown = 30*35; -} -*/ - -//================================================================== -// -// Spawn a door that opens after 5 minutes -// -//================================================================== - -/* -void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum) -{ - vldoor_t *door; - - door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker(&door->thinker); - sec->specialdata = door; - sec->special = 0; - door->thinker.function = T_VerticalDoor; - door->sector = sec; - door->direction = 2; - door->type = DREV_RAISEIN5MINS; - door->speed = VDOORSPEED; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->topwait = VDOORWAIT; - door->topcountdown = 5*60*35; -} -*/ diff --git a/games/NXDoom/src/hexen/p_enemy.c b/games/NXDoom/src/hexen/p_enemy.c deleted file mode 100644 index fa8d094237e..00000000000 --- a/games/NXDoom/src/hexen/p_enemy.c +++ /dev/null @@ -1,5428 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "i_swap.h" -#include "p_local.h" -#include "s_sound.h" - -// Macros -// Types -// Private Data -// External Data - - -//---------------------------------------------------------------------------- -// -// PROC P_RecursiveSound -// -//---------------------------------------------------------------------------- - -mobj_t *soundtarget; - -void P_RecursiveSound(sector_t * sec, int soundblocks) -{ - int i; - line_t *check; - sector_t *other; - - // Wake up all monsters in this sector - if (sec->validcount == validcount - && sec->soundtraversed <= soundblocks + 1) - { // Already flooded - return; - } - sec->validcount = validcount; - sec->soundtraversed = soundblocks + 1; - sec->soundtarget = soundtarget; - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - if (!(check->flags & ML_TWOSIDED)) - { - continue; - } - P_LineOpening(check); - if (openrange <= 0) - { // Closed door - continue; - } - if (sides[check->sidenum[0]].sector == sec) - { - other = sides[check->sidenum[1]].sector; - } - else - { - other = sides[check->sidenum[0]].sector; - } - if (check->flags & ML_SOUNDBLOCK) - { - if (!soundblocks) - { - P_RecursiveSound(other, 1); - } - } - else - { - P_RecursiveSound(other, soundblocks); - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_NoiseAlert -// -// If a monster yells at a player, it will alert other monsters to the -// player. -// -//---------------------------------------------------------------------------- - -void P_NoiseAlert(mobj_t * target, mobj_t * emmiter) -{ - soundtarget = target; - validcount++; - P_RecursiveSound(emmiter->subsector->sector, 0); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_CheckMeleeRange -// -//---------------------------------------------------------------------------- - -boolean P_CheckMeleeRange(mobj_t * actor) -{ - mobj_t *mo; - fixed_t dist; - - if (!actor->target) - { - return (false); - } - mo = actor->target; - dist = P_AproxDistance(mo->x - actor->x, mo->y - actor->y); - if (dist >= MELEERANGE) - { - return (false); - } - if (!P_CheckSight(actor, mo)) - { - return (false); - } - if (mo->z > actor->z + actor->height) - { // Target is higher than the attacker - return (false); - } - else if (actor->z > mo->z + mo->height) - { // Attacker is higher - return (false); - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_CheckMeleeRange2 -// -//---------------------------------------------------------------------------- - -boolean P_CheckMeleeRange2(mobj_t * actor) -{ - mobj_t *mo; - fixed_t dist; - - if (!actor->target) - { - return (false); - } - mo = actor->target; - dist = P_AproxDistance(mo->x - actor->x, mo->y - actor->y); - if (dist >= MELEERANGE * 2 || dist < MELEERANGE) - { - return (false); - } - if (!P_CheckSight(actor, mo)) - { - return (false); - } - if (mo->z > actor->z + actor->height) - { // Target is higher than the attacker - return (false); - } - else if (actor->z > mo->z + mo->height) - { // Attacker is higher - return (false); - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_CheckMissileRange -// -//---------------------------------------------------------------------------- - -boolean P_CheckMissileRange(mobj_t * actor) -{ - fixed_t dist; - - if (!P_CheckSight(actor, actor->target)) - { - return (false); - } - if (actor->flags & MF_JUSTHIT) - { // The target just hit the enemy, so fight back! - actor->flags &= ~MF_JUSTHIT; - return (true); - } - if (actor->reactiontime) - { // Don't attack yet - return (false); - } - dist = (P_AproxDistance(actor->x - actor->target->x, - actor->y - actor->target->y) >> FRACBITS) - 64; - if (!actor->info->meleestate) - { // No melee attack, so fire more frequently - dist -= 128; - } - if (dist > 200) - { - dist = 200; - } - if (P_Random() < dist) - { - return (false); - } - return (true); -} - -/* -================ -= -= P_Move -= -= Move in the current direction -= returns false if the move is blocked -================ -*/ - -fixed_t xspeed[8] = - { FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000, 0, 47000 }; -fixed_t yspeed[8] = - { 0, 47000, FRACUNIT, 47000, 0, -47000, -FRACUNIT, -47000 }; - - -boolean P_Move(mobj_t * actor) -{ - fixed_t tryx, tryy; - line_t *ld; - boolean good; - - if (actor->flags2 & MF2_BLASTED) - return (true); - if (actor->movedir == DI_NODIR) - { - return (false); - } - tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; - tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; - if (!P_TryMove(actor, tryx, tryy)) - { // open any specials - if (actor->flags & MF_FLOAT && floatok) - { // must adjust height - if (actor->z < tmfloorz) - { - actor->z += FLOATSPEED; - } - else - { - actor->z -= FLOATSPEED; - } - actor->flags |= MF_INFLOAT; - return (true); - } - if (!numspechit) - { - return false; - } - actor->movedir = DI_NODIR; - good = false; - while (numspechit--) - { - ld = spechit[numspechit]; - // if the special isn't a door that can be opened, return false - if (P_ActivateLine(ld, actor, 0, SPAC_USE)) - { - good = true; - } -/* Old version before use/cross/impact specials were combined - if(P_UseSpecialLine(actor, ld)) - { - good = true; - } -*/ - } - return (good); - } - else - { - actor->flags &= ~MF_INFLOAT; - } - if (!(actor->flags & MF_FLOAT)) - { - if (actor->z > actor->floorz) - { - P_HitFloor(actor); - } - actor->z = actor->floorz; - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_TryWalk -// -// Attempts to move actor in its current (ob->moveangle) direction. -// If blocked by either a wall or an actor returns FALSE. -// If move is either clear of block only by a door, returns TRUE and sets. -// If a door is in the way, an OpenDoor call is made to start it opening. -// -//---------------------------------------------------------------------------- - -boolean P_TryWalk(mobj_t * actor) -{ - if (!P_Move(actor)) - { - return (false); - } - actor->movecount = P_Random() & 15; - return (true); -} - -/* -================ -= -= P_NewChaseDir -= -================ -*/ - -dirtype_t opposite[] = - { DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, - DI_NORTH, DI_NORTHWEST, DI_NODIR -}; - -dirtype_t diags[] = - { DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST }; - -void P_NewChaseDir(mobj_t * actor) -{ - fixed_t deltax, deltay; - dirtype_t d[3]; - dirtype_t tdir, olddir, turnaround; - - if (!actor->target) - I_Error("P_NewChaseDir: called with no target"); - - olddir = actor->movedir; - turnaround = opposite[olddir]; - - deltax = actor->target->x - actor->x; - deltay = actor->target->y - actor->y; - if (deltax > 10 * FRACUNIT) - d[1] = DI_EAST; - else if (deltax < -10 * FRACUNIT) - d[1] = DI_WEST; - else - d[1] = DI_NODIR; - if (deltay < -10 * FRACUNIT) - d[2] = DI_SOUTH; - else if (deltay > 10 * FRACUNIT) - d[2] = DI_NORTH; - else - d[2] = DI_NODIR; - -// try direct route - if (d[1] != DI_NODIR && d[2] != DI_NODIR) - { - actor->movedir = diags[((deltay < 0) << 1) + (deltax > 0)]; - if (actor->movedir != turnaround && P_TryWalk(actor)) - return; - } - -// try other directions - if (P_Random() > 200 || abs(deltay) > abs(deltax)) - { - tdir = d[1]; - d[1] = d[2]; - d[2] = tdir; - } - - if (d[1] == turnaround) - d[1] = DI_NODIR; - if (d[2] == turnaround) - d[2] = DI_NODIR; - - if (d[1] != DI_NODIR) - { - actor->movedir = d[1]; - if (P_TryWalk(actor)) - return; /*either moved forward or attacked */ - } - - if (d[2] != DI_NODIR) - { - actor->movedir = d[2]; - if (P_TryWalk(actor)) - return; - } - -/* there is no direct path to the player, so pick another direction */ - - if (olddir != DI_NODIR) - { - actor->movedir = olddir; - if (P_TryWalk(actor)) - return; - } - - if (P_Random() & 1) /*randomly determine direction of search */ - { - for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) - { - if (tdir != turnaround) - { - actor->movedir = tdir; - if (P_TryWalk(actor)) - return; - } - } - } - else - { - tdir = DI_SOUTHEAST; - - for (;;) - { - if (tdir != turnaround) - { - actor->movedir = tdir; - if (P_TryWalk(actor)) - return; - } - - if (tdir == DI_EAST) - { - break; - } - - --tdir; - } - } - - if (turnaround != DI_NODIR) - { - actor->movedir = turnaround; - if (P_TryWalk(actor)) - return; - } - - actor->movedir = DI_NODIR; // can't move -} - -//--------------------------------------------------------------------------- -// -// FUNC P_LookForMonsters -// -//--------------------------------------------------------------------------- - -#define MONS_LOOK_RANGE (16*64*FRACUNIT) -#define MONS_LOOK_LIMIT 64 - -boolean P_LookForMonsters(mobj_t * actor) -{ - int count; - mobj_t *mo; - thinker_t *think; - - if (!P_CheckSight(players[0].mo, actor)) - { // Player can't see monster - return (false); - } - count = 0; - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - if (!(mo->flags & MF_COUNTKILL) || (mo == actor) || (mo->health <= 0)) - { // Not a valid monster - continue; - } - if (P_AproxDistance(actor->x - mo->x, actor->y - mo->y) - > MONS_LOOK_RANGE) - { // Out of range - continue; - } - if (P_Random() < 16) - { // Skip - continue; - } - if (count++ > MONS_LOOK_LIMIT) - { // Stop searching - return (false); - } - if (!P_CheckSight(actor, mo)) - { // Out of sight - continue; - } - if (actor->type == MT_MINOTAUR) - { - if ((mo->type == MT_MINOTAUR) && - (mo->target != actor->special1.p->mo)) - { - continue; - } - } - // Found a target monster - actor->target = mo; - return (true); - } - return (false); -} - -/* -================ -= -= P_LookForPlayers -= -= If allaround is false, only look 180 degrees in front -= returns true if a player is targeted -================ -*/ - -boolean P_LookForPlayers(mobj_t * actor, boolean allaround) -{ - int c; - int stop; - player_t *player; - angle_t an; - fixed_t dist; - int consecutive_missing = 0; // for breaking infinite loop - - if (!netgame && players[0].health <= 0) - { // Single player game and player is dead, look for monsters - return (P_LookForMonsters(actor)); - } - c = 0; - - // The 3 below is probably a mistake (it should be MAXPLAYERS - 1, or 7) - // and in vanilla this can potentially cause an infinite loop in - // multiplayer. Unfortunately we can't correct the mistake - doing so will - // cause desyncs. Upon spawning, each enemy's lastlook is initialized to a - // random value between 0 and 7 (i.e MAXPLAYERS - 1). There's a chance - // that the first call of this function for that enemy will return early - // courtesy of the actor->lastlook == stop condition. In a single-player - // game this occurs when (actor->lastlook - 1) & 3 equals 0, or when - // lastlook equals 1 or 5. - - // If you use MAXPLAYERS - 1, it has the side effect of altering which - // enemies are affected by an early actor->lastlook == stop return. Now it - // happens when (actor->lastlook - 1) & 7 equals 0, or when lastlook equals - // 1, *not* 1 and 5 as above. - - stop = (actor->lastlook - 1) & 3; - for (;; actor->lastlook = (actor->lastlook + 1) & 3) - { - if (!playeringame[actor->lastlook]) - { - // Break the vanilla infinite loop here. It can occur if there are - // > 4 players and players 0 - 3 all quit the game. Error out - // instead. - if (consecutive_missing == 4) - { - I_Error("P_LookForPlayers: No player 1 - 4.\n"); - } - consecutive_missing++; - continue; - } - - consecutive_missing = 0; - - if (c++ == 2 || actor->lastlook == stop) - return false; // done looking - - player = &players[actor->lastlook]; - if (player->health <= 0) - continue; // dead - if (!P_CheckSight(actor, player->mo)) - continue; // out of sight - - if (!allaround) - { - an = R_PointToAngle2(actor->x, actor->y, - player->mo->x, player->mo->y) - actor->angle; - if (an > ANG90 && an < ANG270) - { - dist = P_AproxDistance(player->mo->x - actor->x, - player->mo->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - if (player->mo->flags & MF_SHADOW) - { // Player is invisible - if ((P_AproxDistance(player->mo->x - actor->x, - player->mo->y - actor->y) > 2 * MELEERANGE) - && P_AproxDistance(player->mo->momx, player->mo->momy) - < 5 * FRACUNIT) - { // Player is sneaking - can't detect - return (false); - } - if (P_Random() < 225) - { // Player isn't sneaking, but still didn't detect - return (false); - } - } - if (actor->type == MT_MINOTAUR) - { - if (actor->special1.p == player) - { - continue; // Don't target master - } - } - - actor->target = player->mo; - return (true); - } - return (false); -} - -/* -=============================================================================== - - ACTION ROUTINES - -=============================================================================== -*/ - -/* -============== -= -= A_Look -= -= Stay in state until a player is sighted -= -============== -*/ - -void A_Look(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *targ; - - actor->threshold = 0; // any shot will wake up - targ = actor->subsector->sector->soundtarget; - if (targ && (targ->flags & MF_SHOOTABLE)) - { - actor->target = targ; - if (actor->flags & MF_AMBUSH) - { - if (P_CheckSight(actor, actor->target)) - goto seeyou; - } - else - goto seeyou; - } - - - if (!P_LookForPlayers(actor, false)) - return; - -// go into chase state - seeyou: - if (actor->info->seesound) - { - int sound; - - sound = actor->info->seesound; - if (actor->flags2 & MF2_BOSS) - { // Full volume - S_StartSound(NULL, sound); - } - else - { - S_StartSound(actor, sound); - } - } - P_SetMobjState(actor, actor->info->seestate); -} - - -/* -============== -= -= A_Chase -= -= Actor has a melee attack, so it tries to close as fast as possible -= -============== -*/ - -void A_Chase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int delta; - - if (actor->reactiontime) - { - actor->reactiontime--; - } - - // Modify target threshold - if (actor->threshold) - { - actor->threshold--; - } - - if (gameskill == sk_nightmare) - { // Monsters move faster in nightmare mode - actor->tics -= actor->tics / 2; - if (actor->tics < 3) - { - actor->tics = 3; - } - } - -// -// turn towards movement direction if not there yet -// - if (actor->movedir < 8) - { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - if (delta > 0) - { - actor->angle -= ANG90 / 2; - } - else if (delta < 0) - { - actor->angle += ANG90 / 2; - } - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { // look for a new target - if (P_LookForPlayers(actor, true)) - { // got a new target - return; - } - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - -// -// don't attack twice in a row -// - if (actor->flags & MF_JUSTATTACKED) - { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare) - P_NewChaseDir(actor); - return; - } - -// -// check for melee attack -// - if (actor->info->meleestate && P_CheckMeleeRange(actor)) - { - if (actor->info->attacksound) - { - S_StartSound(actor, actor->info->attacksound); - } - P_SetMobjState(actor, actor->info->meleestate); - return; - } - -// -// check for missile attack -// - if (actor->info->missilestate) - { - if (gameskill < sk_nightmare && actor->movecount) - goto nomissile; - if (!P_CheckMissileRange(actor)) - goto nomissile; - P_SetMobjState(actor, actor->info->missilestate); - actor->flags |= MF_JUSTATTACKED; - return; - } - nomissile: - -// -// possibly choose another target -// - if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) - { - if (P_LookForPlayers(actor, true)) - return; // got a new target - } - -// -// chase towards player -// - if (--actor->movecount < 0 || !P_Move(actor)) - { - P_NewChaseDir(actor); - } - -// -// make active sound -// - if (actor->info->activesound && P_Random() < 3) - { - if (actor->type == MT_BISHOP && P_Random() < 128) - { - S_StartSound(actor, actor->info->seesound); - } - else if (actor->type == MT_PIG) - { - S_StartSound(actor, SFX_PIG_ACTIVE1 + (P_Random() & 1)); - } - else if (actor->flags2 & MF2_BOSS) - { - S_StartSound(NULL, actor->info->activesound); - } - else - { - S_StartSound(actor, actor->info->activesound); - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FaceTarget -// -//---------------------------------------------------------------------------- - -void A_FaceTarget(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - actor->flags &= ~MF_AMBUSH; - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, - actor->target->y); - if (actor->target->flags & MF_SHADOW) - { // Target is a ghost - actor->angle += P_SubRandom() << 21; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_Pain -// -//---------------------------------------------------------------------------- - -void A_Pain(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->info->painsound) - { - S_StartSound(actor, actor->info->painsound); - } -} - -//============================================================================ -// -// A_SetInvulnerable -// -//============================================================================ - -void A_SetInvulnerable(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 |= MF2_INVULNERABLE; -} - -//============================================================================ -// -// A_UnSetInvulnerable -// -//============================================================================ - -void A_UnSetInvulnerable(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 &= ~MF2_INVULNERABLE; -} - -//============================================================================ -// -// A_SetReflective -// -//============================================================================ - -void A_SetReflective(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 |= MF2_REFLECTIVE; - - if ((actor->type == MT_CENTAUR) || (actor->type == MT_CENTAURLEADER)) - { - A_SetInvulnerable(actor, player, psp); - } -} - -//============================================================================ -// -// A_UnSetReflective -// -//============================================================================ - -void A_UnSetReflective(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 &= ~MF2_REFLECTIVE; - - if ((actor->type == MT_CENTAUR) || (actor->type == MT_CENTAURLEADER)) - { - A_UnSetInvulnerable(actor, player, psp); - } -} - - -//---------------------------------------------------------------------------- -// -// FUNC P_UpdateMorphedMonster -// -// Returns true if the pig morphs. -// -//---------------------------------------------------------------------------- - -boolean P_UpdateMorphedMonster(mobj_t * actor, int tics) -{ - mobj_t *fog; - fixed_t x; - fixed_t y; - fixed_t z; - mobjtype_t moType; - mobj_t *mo; - mobj_t oldMonster; - - actor->special1.i -= tics; - if (actor->special1.i > 0) - { - return (false); - } - moType = actor->special2.i; - switch (moType) - { - case MT_WRAITHB: // These must remain morphed - case MT_SERPENT: - case MT_SERPENTLEADER: - case MT_MINOTAUR: - return (false); - default: - break; - } - x = actor->x; - y = actor->y; - z = actor->z; - oldMonster = *actor; // Save pig vars - - P_RemoveMobjFromTIDList(actor); - P_SetMobjState(actor, S_FREETARGMOBJ); - mo = P_SpawnMobj(x, y, z, moType); - - if (P_TestMobjLocation(mo) == false) - { // Didn't fit - P_RemoveMobj(mo); - mo = P_SpawnMobj(x, y, z, oldMonster.type); - mo->angle = oldMonster.angle; - mo->flags = oldMonster.flags; - mo->health = oldMonster.health; - mo->target = oldMonster.target; - mo->special = oldMonster.special; - mo->special1.i = 5 * 35; // Next try in 5 seconds - mo->special2.i = moType; - mo->tid = oldMonster.tid; - memcpy(mo->args, oldMonster.args, 5); - P_InsertMobjIntoTIDList(mo, oldMonster.tid); - return (false); - } - mo->angle = oldMonster.angle; - mo->target = oldMonster.target; - mo->tid = oldMonster.tid; - mo->special = oldMonster.special; - memcpy(mo->args, oldMonster.args, 5); - P_InsertMobjIntoTIDList(mo, oldMonster.tid); - fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, SFX_TELEPORT); - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC A_PigLook -// -//---------------------------------------------------------------------------- - -void A_PigLook(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateMorphedMonster(actor, 10)) - { - return; - } - A_Look(actor, player, psp); -} - -//---------------------------------------------------------------------------- -// -// PROC A_PigChase -// -//---------------------------------------------------------------------------- - -void A_PigChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateMorphedMonster(actor, 3)) - { - return; - } - A_Chase(actor, player, psp); -} - -//============================================================================ -// -// A_PigAttack -// -//============================================================================ - -void A_PigAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_UpdateMorphedMonster(actor, 18)) - { - return; - } - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, 2 + (P_Random() & 1)); - S_StartSound(actor, SFX_PIG_ATTACK); - } -} - -//============================================================================ -// -// A_PigPain -// -//============================================================================ - -void A_PigPain(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_Pain(actor, player, psp); - if (actor->z <= actor->floorz) - { - actor->momz = 3.5 * FRACUNIT; - } -} - - - -void FaceMovementDirection(mobj_t * actor) -{ - switch (actor->movedir) - { - case DI_EAST: - actor->angle = 0u << 24; - break; - case DI_NORTHEAST: - actor->angle = 32u << 24; - break; - case DI_NORTH: - actor->angle = 64u << 24; - break; - case DI_NORTHWEST: - actor->angle = 96u << 24; - break; - case DI_WEST: - actor->angle = 128u << 24; - break; - case DI_SOUTHWEST: - actor->angle = 160u << 24; - break; - case DI_SOUTH: - actor->angle = 192u << 24; - break; - case DI_SOUTHEAST: - actor->angle = 224u << 24; - break; - } -} - - -//---------------------------------------------------------------------------- -// -// Minotaur variables -// -// special1 pointer to player that spawned it (mobj_t) -// special2 internal to minotaur AI -// args[0] args[0]-args[3] together make up minotaur start time -// args[1] | -// args[2] | -// args[3] V -// args[4] charge duration countdown -//---------------------------------------------------------------------------- - -void A_MinotaurFade0(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_ALTSHADOW; - actor->flags |= MF_SHADOW; -} - -void A_MinotaurFade1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - // Second level of transparency - actor->flags &= ~MF_SHADOW; - actor->flags |= MF_ALTSHADOW; -} - -void A_MinotaurFade2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - // Make fully visible - actor->flags &= ~MF_SHADOW; - actor->flags &= ~MF_ALTSHADOW; -} - - -//---------------------------------------------------------------------------- -// -// A_MinotaurRoam - -// -// -//---------------------------------------------------------------------------- - - -// Check the age of the minotaur and stomp it after MAULATORTICS of time -// have passed. Returns false if killed. -static boolean CheckMinotaurAge(mobj_t *mo) -{ - unsigned int starttime; - - // The start time is stored in the mobj_t structure, but it is stored - // in little endian format. For Vanilla savegame compatibility we must - // swap it to the native endianness. - memcpy(&starttime, mo->args, sizeof(unsigned int)); - - if (leveltime - LONG(starttime) >= MAULATORTICS) - { - P_DamageMobj(mo, NULL, NULL, 10000); - return false; - } - - return true; -} - -void A_MinotaurRoam(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SHADOW; // In case pain caused him to - actor->flags &= ~MF_ALTSHADOW; // skip his fade in. - - if (!CheckMinotaurAge(actor)) - { - return; - } - - if (P_Random() < 30) - A_MinotaurLook(actor, player, psp); // adjust to closest target - - if (P_Random() < 6) - { - //Choose new direction - actor->movedir = P_Random() % 8; - FaceMovementDirection(actor); - } - if (!P_Move(actor)) - { - // Turn - if (P_Random() & 1) - actor->movedir = (actor->movedir + 1) % 8; - else - actor->movedir = (actor->movedir + 7) % 8; - FaceMovementDirection(actor); - } -} - - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurLook -// -// Look for enemy of player -//---------------------------------------------------------------------------- -#define MINOTAUR_LOOK_DIST (16*54*FRACUNIT) - -void A_MinotaurLook(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - mobj_t *mo = NULL; - player_t *player; - thinker_t *think; - fixed_t dist; - int i; - mobj_t *master = actor->special1.m; - - actor->target = NULL; - if (deathmatch) // Quick search for players - { - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - continue; - player = &players[i]; - mo = player->mo; - if (mo == master) - continue; - if (mo->health <= 0) - continue; - dist = P_AproxDistance(actor->x - mo->x, actor->y - mo->y); - if (dist > MINOTAUR_LOOK_DIST) - continue; - actor->target = mo; - break; - } - } - - if (!actor->target) // Near player monster search - { - if (master && (master->health > 0) && (master->player)) - mo = P_RoughMonsterSearch(master, 20); - else - mo = P_RoughMonsterSearch(actor, 20); - actor->target = mo; - } - - if (!actor->target) // Normal monster search - { - for (think = thinkercap.next; think != &thinkercap; - think = think->next) - { - if (think->function != P_MobjThinker) - continue; - mo = (mobj_t *) think; - if (!(mo->flags & MF_COUNTKILL)) - continue; - if (mo->health <= 0) - continue; - if (!(mo->flags & MF_SHOOTABLE)) - continue; - dist = P_AproxDistance(actor->x - mo->x, actor->y - mo->y); - if (dist > MINOTAUR_LOOK_DIST) - continue; - if ((mo == master) || (mo == actor)) - continue; - if ((mo->type == MT_MINOTAUR) && - (mo->special1.m == actor->special1.m)) - continue; - actor->target = mo; - break; // Found mobj to attack - } - } - - if (actor->target) - { - P_SetMobjStateNF(actor, S_MNTR_WALK1); - } - else - { - P_SetMobjStateNF(actor, S_MNTR_ROAM1); - } -} - - - - -void A_MinotaurChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SHADOW; // In case pain caused him to - actor->flags &= ~MF_ALTSHADOW; // skip his fade in. - - if (!CheckMinotaurAge(actor)) - { - return; - } - - if (P_Random() < 30) - A_MinotaurLook(actor, player, psp); // adjust to closest target - - if (!actor->target || (actor->target->health <= 0) || - !(actor->target->flags & MF_SHOOTABLE)) - { // look for a new target - P_SetMobjState(actor, S_MNTR_LOOK1); - return; - } - - FaceMovementDirection(actor); - actor->reactiontime = 0; - - // Melee attack - if (actor->info->meleestate && P_CheckMeleeRange(actor)) - { - if (actor->info->attacksound) - { - S_StartSound(actor, actor->info->attacksound); - } - P_SetMobjState(actor, actor->info->meleestate); - return; - } - - // Missile attack - if (actor->info->missilestate && P_CheckMissileRange(actor)) - { - P_SetMobjState(actor, actor->info->missilestate); - return; - } - - // chase towards target - if (!P_Move(actor)) - { - P_NewChaseDir(actor); - } - - // Active sound - if (actor->info->activesound && P_Random() < 6) - { - S_StartSound(actor, actor->info->activesound); - } - -} - - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk1 -// -// Melee attack. -// -//---------------------------------------------------------------------------- - -void A_MinotaurAtk1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - return; - - S_StartSound(actor, SFX_MAULATOR_HAMMER_SWING); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(4)); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurDecide -// -// Choose a missile attack. -// -//---------------------------------------------------------------------------- - -#define MNTR_CHARGE_SPEED (23*FRACUNIT) - -void A_MinotaurDecide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - mobj_t *target = actor->target; - int dist; - - if (!target) - return; - dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); - - if (target->z + target->height > actor->z - && target->z + target->height < actor->z + actor->height - && dist < 16 * 64 * FRACUNIT - && dist > 1 * 64 * FRACUNIT && P_Random() < 230) - { // Charge attack - // Don't call the state function right away - P_SetMobjStateNF(actor, S_MNTR_ATK4_1); - actor->flags |= MF_SKULLFLY; - A_FaceTarget(actor, player, psp); - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(MNTR_CHARGE_SPEED, finecosine[angle]); - actor->momy = FixedMul(MNTR_CHARGE_SPEED, finesine[angle]); - actor->args[4] = 35 / 2; // Charge duration - } - else if (target->z == target->floorz - && dist < 9 * 64 * FRACUNIT && P_Random() < 100) - { // Floor fire attack - P_SetMobjState(actor, S_MNTR_ATK3_1); - actor->special2.i = 0; - } - else - { // Swing attack - A_FaceTarget(actor, player, psp); - // Don't need to call P_SetMobjState because the current state - // falls through to the swing attack - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurCharge -// -//---------------------------------------------------------------------------- - -void A_MinotaurCharge(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *puff; - - if (!actor->target) - return; - - if (actor->args[4] > 0) - { - puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PUNCHPUFF); - puff->momz = 2 * FRACUNIT; - actor->args[4]--; - } - else - { - actor->flags &= ~MF_SKULLFLY; - P_SetMobjState(actor, actor->info->seestate); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk2 -// -// Swing attack. -// -//---------------------------------------------------------------------------- - -void A_MinotaurAtk2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - fixed_t momz; - - if (!actor->target) - return; - - S_StartSound(actor, SFX_MAULATOR_HAMMER_SWING); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(3)); - return; - } - mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX1); - if (mo) - { - //S_StartSound(mo, sfx_minat2); - momz = mo->momz; - angle = mo->angle; - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 8), momz); - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 8), momz); - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle - (ANG45 / 16), momz); - P_SpawnMissileAngle(actor, MT_MNTRFX1, angle + (ANG45 / 16), momz); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MinotaurAtk3 -// -// Floor fire attack. -// -//---------------------------------------------------------------------------- - -void A_MinotaurAtk3(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - mobj_t *mo; - player_t *player; - - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(3)); - if ((player = actor->target->player) != NULL) - { // Squish the player - player->deltaviewheight = -16 * FRACUNIT; - } - } - else - { - mo = P_SpawnMissile(actor, actor->target, MT_MNTRFX2); - if (mo != NULL) - { - S_StartSound(mo, SFX_MAULATOR_HAMMER_HIT); - } - } - if (P_Random() < 192 && actor->special2.i == 0) - { - P_SetMobjState(actor, S_MNTR_ATK3_4); - actor->special2.i = 1; - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_MntrFloorFire -// -//---------------------------------------------------------------------------- - -void A_MntrFloorFire(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1, r2; - - r1 = P_SubRandom(); - r2 = P_SubRandom(); - - actor->z = actor->floorz; - mo = P_SpawnMobj(actor->x + (r2 << 10), - actor->y + (r1 << 10), ONFLOORZ, - MT_MNTRFX3); - mo->target = actor->target; - mo->momx = 1; // Force block checking - P_CheckMissileSpawn(mo); -} - - -//---------------------------------------------------------------------------- -// -// PROC A_Scream -// -//---------------------------------------------------------------------------- - -void A_Scream(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int sound; - - S_StopSound(actor); - if (actor->player) - { - if (actor->player->morphTics) - { - S_StartSound(actor, actor->info->deathsound); - } - else - { - // Handle the different player death screams - if (actor->momz <= -39 * FRACUNIT) - { // Falling splat - sound = SFX_PLAYER_FALLING_SPLAT; - } - else if (actor->health > -50) - { // Normal death sound - switch (actor->player->class) - { - case PCLASS_FIGHTER: - sound = SFX_PLAYER_FIGHTER_NORMAL_DEATH; - break; - case PCLASS_CLERIC: - sound = SFX_PLAYER_CLERIC_NORMAL_DEATH; - break; - case PCLASS_MAGE: - sound = SFX_PLAYER_MAGE_NORMAL_DEATH; - break; - default: - sound = SFX_NONE; - break; - } - } - else if (actor->health > -100) - { // Crazy death sound - switch (actor->player->class) - { - case PCLASS_FIGHTER: - sound = SFX_PLAYER_FIGHTER_CRAZY_DEATH; - break; - case PCLASS_CLERIC: - sound = SFX_PLAYER_CLERIC_CRAZY_DEATH; - break; - case PCLASS_MAGE: - sound = SFX_PLAYER_MAGE_CRAZY_DEATH; - break; - default: - sound = SFX_NONE; - break; - } - } - else - { // Extreme death sound - switch (actor->player->class) - { - case PCLASS_FIGHTER: - sound = SFX_PLAYER_FIGHTER_EXTREME1_DEATH; - break; - case PCLASS_CLERIC: - sound = SFX_PLAYER_CLERIC_EXTREME1_DEATH; - break; - case PCLASS_MAGE: - sound = SFX_PLAYER_MAGE_EXTREME1_DEATH; - break; - default: - sound = SFX_NONE; - break; - } - sound += P_Random() % 3; // Three different extreme deaths - } - S_StartSound(actor, sound); - } - } - else - { - S_StartSound(actor, actor->info->deathsound); - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_DropItem -// -//--------------------------------------------------------------------------- - -/* -void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance) -{ - mobj_t *mo; - - if(P_Random() > chance) - { - return; - } - mo = P_SpawnMobj(source->x, source->y, - source->z+(source->height>>1), type); - mo->momx = P_SubRandom()<<8; - mo->momy = P_SubRandom()<<8; - mo->momz = FRACUNIT*5+(P_Random()<<10); - mo->flags2 |= MF2_DROPPED; - mo->health = special; -} -*/ - -//---------------------------------------------------------------------------- -// -// PROC A_NoBlocking -// -//---------------------------------------------------------------------------- - -void A_NoBlocking(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags &= ~MF_SOLID; - - // Check for monsters dropping things -/* switch(actor->type) - { - // Add the monster dropped items here - case MT_MUMMYLEADERGHOST: - P_DropItem(actor, MT_AMGWNDWIMPY, 3, 84); - break; - default: - break; - } -*/ -} - -//---------------------------------------------------------------------------- -// -// PROC A_Explode -// -// Handles a bunch of exploding things. -// -//---------------------------------------------------------------------------- - -void A_Explode(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int damage; - int distance; - boolean damageSelf; - - damage = 128; - distance = 128; - damageSelf = true; - switch (actor->type) - { - case MT_FIREBOMB: // Time Bombs - actor->z += 32 * FRACUNIT; - actor->flags &= ~MF_SHADOW; - break; - case MT_MNTRFX2: // Minotaur floor fire - damage = 24; - break; - case MT_BISHOP: // Bishop radius death - damage = 25 + (P_Random() & 15); - break; - case MT_HAMMER_MISSILE: // Fighter Hammer - damage = 128; - damageSelf = false; - break; - case MT_FSWORD_MISSILE: // Fighter Runesword - damage = 64; - damageSelf = false; - break; - case MT_CIRCLEFLAME: // Cleric Flame secondary flames - damage = 20; - damageSelf = false; - break; - case MT_SORCBALL1: // Sorcerer balls - case MT_SORCBALL2: - case MT_SORCBALL3: - distance = 255; - damage = 255; - actor->args[0] = 1; // don't play bounce - break; - case MT_SORCFX1: // Sorcerer spell 1 - damage = 30; - break; - case MT_SORCFX4: // Sorcerer spell 4 - damage = 20; - break; - case MT_TREEDESTRUCTIBLE: - damage = 10; - break; - case MT_DRAGON_FX2: - damage = 80; - damageSelf = false; - break; - case MT_MSTAFF_FX: - damage = 64; - distance = 192; - damageSelf = false; - break; - case MT_MSTAFF_FX2: - damage = 80; - distance = 192; - damageSelf = false; - break; - case MT_POISONCLOUD: - damage = 4; - distance = 40; - break; - case MT_ZXMAS_TREE: - case MT_ZSHRUB2: - damage = 30; - distance = 64; - break; - default: - break; - } - P_RadiusAttack(actor, actor->target, damage, distance, damageSelf); - if (actor->z <= actor->floorz + (distance << FRACBITS) - && actor->type != MT_POISONCLOUD) - { - P_HitFloor(actor); - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_Massacre -// -// Kills all monsters. -// -//---------------------------------------------------------------------------- - -int P_Massacre(void) -{ - int count; - mobj_t *mo; - thinker_t *think; - - count = 0; - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - if ((mo->flags & MF_COUNTKILL) && (mo->health > 0)) - { - mo->flags2 &= ~(MF2_NONSHOOTABLE + MF2_INVULNERABLE); - mo->flags |= MF_SHOOTABLE; - P_DamageMobj(mo, NULL, NULL, 10000); - count++; - } - } - return count; -} - - - -//---------------------------------------------------------------------------- -// -// PROC A_SkullPop -// -//---------------------------------------------------------------------------- - -void A_SkullPop(mobj_t *actor, player_t *player_, pspdef_t *psp) -{ - mobj_t *mo; - player_t *player; - - if (!actor->player) - { - return; - } - actor->flags &= ~MF_SOLID; - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 48 * FRACUNIT, - MT_BLOODYSKULL); - //mo->target = actor; - mo->momx = P_SubRandom() << 9; - mo->momy = P_SubRandom() << 9; - mo->momz = FRACUNIT * 2 + (P_Random() << 6); - // Attach player mobj to bloody skull - player = actor->player; - actor->player = NULL; - actor->special1.i = player->class; - mo->player = player; - mo->health = actor->health; - mo->angle = actor->angle; - player->mo = mo; - player->lookdir = 0; - player->damagecount = 32; -} - -//---------------------------------------------------------------------------- -// -// PROC A_CheckSkullFloor -// -//---------------------------------------------------------------------------- - -void A_CheckSkullFloor(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->z <= actor->floorz) - { - P_SetMobjState(actor, S_BLOODYSKULLX1); - S_StartSound(actor, SFX_DRIP); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_CheckSkullDone -// -//---------------------------------------------------------------------------- - -void A_CheckSkullDone(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special2.i == 666) - { - P_SetMobjState(actor, S_BLOODYSKULLX2); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_CheckBurnGone -// -//---------------------------------------------------------------------------- - -void A_CheckBurnGone(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special2.i == 666) - { - P_SetMobjState(actor, S_PLAY_FDTH20); - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_FreeTargMobj -// -//---------------------------------------------------------------------------- - -void A_FreeTargMobj(mobj_t *mo, player_t *player, pspdef_t *psp) -{ - mo->momx = mo->momy = mo->momz = 0; - mo->z = mo->ceilingz + 4 * FRACUNIT; - mo->flags &= - ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_SOLID | MF_COUNTKILL); - mo->flags |= MF_CORPSE | MF_DROPOFF | MF_NOGRAVITY; - mo->flags2 &= ~(MF2_PASSMOBJ | MF2_LOGRAV); - mo->flags2 |= MF2_DONTDRAW; - mo->player = NULL; - mo->health = -1000; // Don't resurrect -} - - -//---------------------------------------------------------------------------- -// -// CorpseQueue Routines -// -//---------------------------------------------------------------------------- - -// Corpse queue for monsters - this should be saved out -#define CORPSEQUEUESIZE 64 -mobj_t *corpseQueue[CORPSEQUEUESIZE]; -int corpseQueueSlot; - -// throw another corpse on the queue -void A_QueueCorpse(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *corpse; - - if (corpseQueueSlot >= CORPSEQUEUESIZE) - { // Too many corpses - remove an old one - corpse = corpseQueue[corpseQueueSlot % CORPSEQUEUESIZE]; - if (corpse) - P_RemoveMobj(corpse); - } - corpseQueue[corpseQueueSlot % CORPSEQUEUESIZE] = actor; - corpseQueueSlot++; -} - -// Remove a mobj from the queue (for resurrection) -void A_DeQueueCorpse(mobj_t *actor) -{ - int slot; - - for (slot = 0; slot < CORPSEQUEUESIZE; slot++) - { - if (corpseQueue[slot] == actor) - { - corpseQueue[slot] = NULL; - break; - } - } -} - -void P_InitCreatureCorpseQueue(boolean corpseScan) -{ - thinker_t *think; - mobj_t *mo; - - // Initialize queue - corpseQueueSlot = 0; - memset(corpseQueue, 0, sizeof(mobj_t *) * CORPSEQUEUESIZE); - - if (!corpseScan) - return; - - // Search mobj list for corpses and place them in this queue - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - continue; - mo = (mobj_t *) think; - if (!(mo->flags & MF_CORPSE)) - continue; // Must be a corpse - if (mo->flags & MF_ICECORPSE) - continue; // Not ice corpses - // Only corpses that call A_QueueCorpse from death routine - switch (mo->type) - { - case MT_CENTAUR: - case MT_CENTAURLEADER: - case MT_DEMON: - case MT_DEMON2: - case MT_WRAITH: - case MT_WRAITHB: - case MT_BISHOP: - case MT_ETTIN: - case MT_PIG: - case MT_CENTAUR_SHIELD: - case MT_CENTAUR_SWORD: - case MT_DEMONCHUNK1: - case MT_DEMONCHUNK2: - case MT_DEMONCHUNK3: - case MT_DEMONCHUNK4: - case MT_DEMONCHUNK5: - case MT_DEMON2CHUNK1: - case MT_DEMON2CHUNK2: - case MT_DEMON2CHUNK3: - case MT_DEMON2CHUNK4: - case MT_DEMON2CHUNK5: - case MT_FIREDEMON_SPLOTCH1: - case MT_FIREDEMON_SPLOTCH2: - A_QueueCorpse(mo, NULL, NULL); // Add corpse to queue - break; - default: - break; - } - } -} - - -//---------------------------------------------------------------------------- -// -// PROC A_AddPlayerCorpse -// -//---------------------------------------------------------------------------- - -#define BODYQUESIZE 32 -mobj_t *bodyque[BODYQUESIZE]; -int bodyqueslot; - -void A_AddPlayerCorpse(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (bodyqueslot >= BODYQUESIZE) - { // Too many player corpses - remove an old one - P_RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]); - } - bodyque[bodyqueslot % BODYQUESIZE] = actor; - bodyqueslot++; -} - -//============================================================================ -// -// A_SerpentUnHide -// -//============================================================================ - -void A_SerpentUnHide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 &= ~MF2_DONTDRAW; - actor->floorclip = 24 * FRACUNIT; -} - -//============================================================================ -// -// A_SerpentHide -// -//============================================================================ - -void A_SerpentHide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 |= MF2_DONTDRAW; - actor->floorclip = 0; -} - -//============================================================================ -// -// A_SerpentChase -// -//============================================================================ - -void A_SerpentChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int delta; - int oldX, oldY, oldFloor; - - if (actor->reactiontime) - { - actor->reactiontime--; - } - - // Modify target threshold - if (actor->threshold) - { - actor->threshold--; - } - - if (gameskill == sk_nightmare) - { // Monsters move faster in nightmare mode - actor->tics -= actor->tics / 2; - if (actor->tics < 3) - { - actor->tics = 3; - } - } - -// -// turn towards movement direction if not there yet -// - if (actor->movedir < 8) - { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - if (delta > 0) - { - actor->angle -= ANG90 / 2; - } - else if (delta < 0) - { - actor->angle += ANG90 / 2; - } - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { // look for a new target - if (P_LookForPlayers(actor, true)) - { // got a new target - return; - } - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - -// -// don't attack twice in a row -// - if (actor->flags & MF_JUSTATTACKED) - { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare) - P_NewChaseDir(actor); - return; - } - -// -// check for melee attack -// - if (actor->info->meleestate && P_CheckMeleeRange(actor)) - { - if (actor->info->attacksound) - { - S_StartSound(actor, actor->info->attacksound); - } - P_SetMobjState(actor, actor->info->meleestate); - return; - } - -// -// possibly choose another target -// - if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) - { - if (P_LookForPlayers(actor, true)) - return; // got a new target - } - -// -// chase towards player -// - oldX = actor->x; - oldY = actor->y; - oldFloor = actor->subsector->sector->floorpic; - if (--actor->movecount < 0 || !P_Move(actor)) - { - P_NewChaseDir(actor); - } - if (actor->subsector->sector->floorpic != oldFloor) - { - P_TryMove(actor, oldX, oldY); - P_NewChaseDir(actor); - } - -// -// make active sound -// - if (actor->info->activesound && P_Random() < 3) - { - S_StartSound(actor, actor->info->activesound); - } -} - -//============================================================================ -// -// A_SerpentRaiseHump -// -// Raises the hump above the surface by raising the floorclip level -//============================================================================ - -void A_SerpentRaiseHump(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->floorclip -= 4 * FRACUNIT; -} - -//============================================================================ -// -// A_SerpentLowerHump -// -//============================================================================ - -void A_SerpentLowerHump(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->floorclip += 4 * FRACUNIT; -} - -//============================================================================ -// -// A_SerpentHumpDecide -// -// Decided whether to hump up, or if the mobj is a serpent leader, -// to missile attack -//============================================================================ - -void A_SerpentHumpDecide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->type == MT_SERPENTLEADER) - { - if (P_Random() > 30) - { - return; - } - else if (P_Random() < 40) - { // Missile attack - P_SetMobjState(actor, S_SERPENT_SURFACE1); - return; - } - } - else if (P_Random() > 3) - { - return; - } - if (!P_CheckMeleeRange(actor)) - { // The hump shouldn't occur when within melee range - if (actor->type == MT_SERPENTLEADER && P_Random() < 128) - { - P_SetMobjState(actor, S_SERPENT_SURFACE1); - } - else - { - P_SetMobjState(actor, S_SERPENT_HUMP1); - S_StartSound(actor, SFX_SERPENT_ACTIVE); - } - } -} - -//============================================================================ -// -// A_SerpentBirthScream -// -//============================================================================ - -void A_SerpentBirthScream(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(actor, SFX_SERPENT_BIRTH); -} - -//============================================================================ -// -// A_SerpentDiveSound -// -//============================================================================ - -void A_SerpentDiveSound(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(actor, SFX_SERPENT_ACTIVE); -} - -//============================================================================ -// -// A_SerpentWalk -// -// Similar to A_Chase, only has a hardcoded entering of meleestate -//============================================================================ - -void A_SerpentWalk(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int delta; - - if (actor->reactiontime) - { - actor->reactiontime--; - } - - // Modify target threshold - if (actor->threshold) - { - actor->threshold--; - } - - if (gameskill == sk_nightmare) - { // Monsters move faster in nightmare mode - actor->tics -= actor->tics / 2; - if (actor->tics < 3) - { - actor->tics = 3; - } - } - -// -// turn towards movement direction if not there yet -// - if (actor->movedir < 8) - { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - if (delta > 0) - { - actor->angle -= ANG90 / 2; - } - else if (delta < 0) - { - actor->angle += ANG90 / 2; - } - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { // look for a new target - if (P_LookForPlayers(actor, true)) - { // got a new target - return; - } - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - -// -// don't attack twice in a row -// - if (actor->flags & MF_JUSTATTACKED) - { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare) - P_NewChaseDir(actor); - return; - } - -// -// check for melee attack -// - if (actor->info->meleestate && P_CheckMeleeRange(actor)) - { - if (actor->info->attacksound) - { - S_StartSound(actor, actor->info->attacksound); - } - P_SetMobjState(actor, S_SERPENT_ATK1); - return; - } -// -// possibly choose another target -// - if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) - { - if (P_LookForPlayers(actor, true)) - return; // got a new target - } - -// -// chase towards player -// - if (--actor->movecount < 0 || !P_Move(actor)) - { - P_NewChaseDir(actor); - } -} - -//============================================================================ -// -// A_SerpentCheckForAttack -// -//============================================================================ - -void A_SerpentCheckForAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - if (actor->type == MT_SERPENTLEADER) - { - if (!P_CheckMeleeRange(actor)) - { - P_SetMobjState(actor, S_SERPENT_ATK1); - return; - } - } - if (P_CheckMeleeRange2(actor)) - { - P_SetMobjState(actor, S_SERPENT_WALK1); - } - else if (P_CheckMeleeRange(actor)) - { - if (P_Random() < 32) - { - P_SetMobjState(actor, S_SERPENT_WALK1); - } - else - { - P_SetMobjState(actor, S_SERPENT_ATK1); - } - } -} - -//============================================================================ -// -// A_SerpentChooseAttack -// -//============================================================================ - -void A_SerpentChooseAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target || P_CheckMeleeRange(actor)) - { - return; - } - if (actor->type == MT_SERPENTLEADER) - { - P_SetMobjState(actor, S_SERPENT_MISSILE1); - } -} - -//============================================================================ -// -// A_SerpentMeleeAttack -// -//============================================================================ - -void A_SerpentMeleeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(5)); - S_StartSound(actor, SFX_SERPENT_MELEEHIT); - } - if (P_Random() < 96) - { - A_SerpentCheckForAttack(actor, player, psp); - } -} - -//============================================================================ -// -// A_SerpentMissileAttack -// -//============================================================================ - -void A_SerpentMissileAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - - P_SpawnMissile(actor, actor->target, MT_SERPENTFX); -} - -//============================================================================ -// -// A_SerpentHeadPop -// -//============================================================================ - -void A_SerpentHeadPop(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_SERPENT_HEAD); -} - -//============================================================================ -// -// A_SerpentSpawnGibs -// -//============================================================================ - -void A_SerpentSpawnGibs(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1, r2; - - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12), - actor->y + ((r1 - 128) << 12), - actor->floorz + FRACUNIT, MT_SERPENT_GIB1); - if (mo) - { - mo->momx = (P_Random() - 128) << 6; - mo->momy = (P_Random() - 128) << 6; - mo->floorclip = 6 * FRACUNIT; - } - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12), - actor->y + ((r1 - 128) << 12), - actor->floorz + FRACUNIT, MT_SERPENT_GIB2); - if (mo) - { - mo->momx = (P_Random() - 128) << 6; - mo->momy = (P_Random() - 128) << 6; - mo->floorclip = 6 * FRACUNIT; - } - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r2 - 128) << 12), - actor->y + ((r1 - 128) << 12), - actor->floorz + FRACUNIT, MT_SERPENT_GIB3); - if (mo) - { - mo->momx = (P_Random() - 128) << 6; - mo->momy = (P_Random() - 128) << 6; - mo->floorclip = 6 * FRACUNIT; - } -} - -//============================================================================ -// -// A_FloatGib -// -//============================================================================ - -void A_FloatGib(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->floorclip -= FRACUNIT; -} - -//============================================================================ -// -// A_SinkGib -// -//============================================================================ - -void A_SinkGib(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->floorclip += FRACUNIT; -} - -//============================================================================ -// -// A_DelayGib -// -//============================================================================ - -void A_DelayGib(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->tics -= P_Random() >> 2; -} - -//============================================================================ -// -// A_SerpentHeadCheck -// -//============================================================================ - -void A_SerpentHeadCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->z <= actor->floorz) - { - if (P_GetThingFloorType(actor) >= FLOOR_LIQUID) - { - P_HitFloor(actor); - P_SetMobjState(actor, S_NULL); - } - else - { - P_SetMobjState(actor, S_SERPENT_HEAD_X1); - } - } -} - -//============================================================================ -// -// A_CentaurAttack -// -//============================================================================ - -void A_CentaurAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, P_Random() % 7 + 3); - } -} - -//============================================================================ -// -// A_CentaurAttack2 -// -//============================================================================ - -void A_CentaurAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - P_SpawnMissile(actor, actor->target, MT_CENTAUR_FX); - S_StartSound(actor, SFX_CENTAURLEADER_ATTACK); -} - -//============================================================================ -// -// A_CentaurDropStuff -// -// Spawn shield/sword sprites when the centaur pulps //============================================================================ - -void A_CentaurDropStuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_CENTAUR_SHIELD); - if (mo) - { - angle = actor->angle + ANG90; - mo->momz = FRACUNIT * 8 + (P_Random() << 10); - mo->momx = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_CENTAUR_SWORD); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = FRACUNIT * 8 + (P_Random() << 10); - mo->momx = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul(((P_Random() - 128) << 11) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } -} - -//============================================================================ -// -// A_CentaurDefend -// -//============================================================================ - -void A_CentaurDefend(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_FaceTarget(actor, player, psp); - if (P_CheckMeleeRange(actor) && P_Random() < 32) - { - A_UnSetInvulnerable(actor, player, psp); - P_SetMobjState(actor, actor->info->meleestate); - } -} - -//============================================================================ -// -// A_BishopAttack -// -//============================================================================ - -void A_BishopAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - { - return; - } - S_StartSound(actor, actor->info->attacksound); - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(4)); - return; - } - actor->special1.i = (P_Random() & 3) + 5; -} - -//============================================================================ -// -// A_BishopAttack2 -// -// Spawns one of a string of bishop missiles -//============================================================================ - -void A_BishopAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - if (!actor->target || !actor->special1.i) - { - actor->special1.i = 0; - P_SetMobjState(actor, S_BISHOP_WALK1); - return; - } - mo = P_SpawnMissile(actor, actor->target, MT_BISH_FX); - if (mo) - { - mo->special1.m = actor->target; - mo->special2.i = 16; // High word == x/y, Low word == z - } - actor->special1.i--; -} - -//============================================================================ -// -// A_BishopMissileWeave -// -//============================================================================ - -void A_BishopMissileWeave(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t newX, newY; - int weaveXY, weaveZ; - int angle; - - weaveXY = actor->special2.i >> 16; - weaveZ = actor->special2.i & 0xFFFF; - angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - newX = actor->x - FixedMul(finecosine[angle], - FloatBobOffsets[weaveXY] << 1); - newY = actor->y - FixedMul(finesine[angle], - FloatBobOffsets[weaveXY] << 1); - weaveXY = (weaveXY + 2) & 63; - newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 1); - newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 1); - P_TryMove(actor, newX, newY); - actor->z -= FloatBobOffsets[weaveZ]; - weaveZ = (weaveZ + 2) & 63; - actor->z += FloatBobOffsets[weaveZ]; - actor->special2.i = weaveZ + (weaveXY << 16); -} - -//============================================================================ -// -// A_BishopMissileSeek -// -//============================================================================ - -void A_BishopMissileSeek(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SeekerMissile(actor, ANG1 * 2, ANG1 * 3); -} - -//============================================================================ -// -// A_BishopDecide -// -//============================================================================ - -void A_BishopDecide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_Random() < 220) - { - return; - } - else - { - P_SetMobjState(actor, S_BISHOP_BLUR1); - } -} - -//============================================================================ -// -// A_BishopDoBlur -// -//============================================================================ - -void A_BishopDoBlur(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->special1.i = (P_Random() & 3) + 3; // Random number of blurs - if (P_Random() < 120) - { - P_ThrustMobj(actor, actor->angle + ANG90, 11 * FRACUNIT); - } - else if (P_Random() > 125) - { - P_ThrustMobj(actor, actor->angle - ANG90, 11 * FRACUNIT); - } - else - { // Thrust forward - P_ThrustMobj(actor, actor->angle, 11 * FRACUNIT); - } - S_StartSound(actor, SFX_BISHOP_BLUR); -} - -//============================================================================ -// -// A_BishopSpawnBlur -// -//============================================================================ - -void A_BishopSpawnBlur(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - if (!--actor->special1.i) - { - actor->momx = 0; - actor->momy = 0; - if (P_Random() > 96) - { - P_SetMobjState(actor, S_BISHOP_WALK1); - } - else - { - P_SetMobjState(actor, S_BISHOP_ATK1); - } - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BISHOPBLUR); - if (mo) - { - mo->angle = actor->angle; - } -} - -//============================================================================ -// -// A_BishopChase -// -//============================================================================ - -void A_BishopChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->z -= FloatBobOffsets[actor->special2.i] >> 1; - actor->special2.i = (actor->special2.i + 4) & 63; - actor->z += FloatBobOffsets[actor->special2.i] >> 1; -} - -//============================================================================ -// -// A_BishopPuff -// -//============================================================================ - -void A_BishopPuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 40 * FRACUNIT, - MT_BISHOP_PUFF); - if (mo) - { - mo->momz = FRACUNIT / 2; - } -} - -//============================================================================ -// -// A_BishopPainBlur -// -//============================================================================ - -void A_BishopPainBlur(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int r1,r2,r3; - - if (P_Random() < 64) - { - P_SetMobjState(actor, S_BISHOP_BLUR1); - return; - } - - r1 = P_SubRandom(); - r2 = P_SubRandom(); - r3 = P_SubRandom(); - - mo = P_SpawnMobj(actor->x + (r3 << 12), actor->y - + (r2 << 12), - actor->z + (r1 << 11), - MT_BISHOPPAINBLUR); - if (mo) - { - mo->angle = actor->angle; - } -} - -//============================================================================ -// -// DragonSeek -// -//============================================================================ - -static void DragonSeek(mobj_t * actor, angle_t thresh, angle_t turnMax) -{ - int dir; - int dist; - angle_t delta; - angle_t angle; - mobj_t *target; - int search; - int i; - int bestArg; - angle_t bestAngle; - angle_t angleToSpot, angleToTarget; - mobj_t *mo; - - target = actor->special1.m; - if (target == NULL) - { - return; - } - dir = P_FaceMobj(actor, target, &delta); - if (delta > thresh) - { - delta >>= 1; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->angle += delta; - } - else - { // Turn counter clockwise - actor->angle -= delta; - } - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(actor->info->speed, finecosine[angle]); - actor->momy = FixedMul(actor->info->speed, finesine[angle]); - if (actor->z + actor->height < target->z - || target->z + target->height < actor->z) - { - dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); - dist = dist / actor->info->speed; - if (dist < 1) - { - dist = 1; - } - actor->momz = (target->z - actor->z) / dist; - } - else - { - dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); - dist = dist / actor->info->speed; - } - if (target->flags & MF_SHOOTABLE && P_Random() < 64) - { // attack the destination mobj if it's attackable - mobj_t *oldTarget; - - if (abs((int) actor->angle - (int) R_PointToAngle2(actor->x, actor->y, - target->x, - target->y)) < ANG45 / 2) - { - oldTarget = actor->target; - actor->target = target; - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(10)); - S_StartSound(actor, SFX_DRAGON_ATTACK); - } - else if (P_Random() < 128 && P_CheckMissileRange(actor)) - { - P_SpawnMissile(actor, target, MT_DRAGON_FX); - S_StartSound(actor, SFX_DRAGON_ATTACK); - } - actor->target = oldTarget; - } - } - if (dist < 4) - { // Hit the target thing - if (actor->target && P_Random() < 200) - { - bestArg = -1; - bestAngle = ANG_MAX; - angleToTarget = R_PointToAngle2(actor->x, actor->y, - actor->target->x, - actor->target->y); - for (i = 0; i < 5; i++) - { - if (!target->args[i]) - { - continue; - } - search = -1; - mo = P_FindMobjFromTID(target->args[i], &search); - angleToSpot = R_PointToAngle2(actor->x, actor->y, - mo->x, mo->y); - if (abs((int) angleToSpot - (int) angleToTarget) < bestAngle) - { - bestAngle = abs((int) angleToSpot - (int) angleToTarget); - bestArg = i; - } - } - if (bestArg != -1) - { - search = -1; - actor->special1.m = - P_FindMobjFromTID(target->args[bestArg], &search); - } - } - else - { - do - { - i = (P_Random() >> 2) % 5; - } - while (!target->args[i]); - search = -1; - actor->special1.m = - P_FindMobjFromTID(target->args[i], &search); - } - } -} - -//============================================================================ -// -// A_DragonInitFlight -// -//============================================================================ - -void A_DragonInitFlight(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int search; - - search = -1; - do - { // find the first tid identical to the dragon's tid - actor->special1.m = P_FindMobjFromTID(actor->tid, &search); - if (search == -1) - { - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - } - while (actor->special1.m == actor); - P_RemoveMobjFromTIDList(actor); -} - -//============================================================================ -// -// A_DragonFlight -// -//============================================================================ - -void A_DragonFlight(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - - DragonSeek(actor, 4 * ANG1, 8 * ANG1); - if (actor->target) - { - if (!(actor->target->flags & MF_SHOOTABLE)) - { // target died - actor->target = NULL; - return; - } - angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, - actor->target->y); - if (abs((int) actor->angle - (int) angle) < ANG45 / 2 - && P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(8)); - S_StartSound(actor, SFX_DRAGON_ATTACK); - } - else if (abs((int) actor->angle - (int) angle) <= ANG1 * 20) - { - P_SetMobjState(actor, actor->info->missilestate); - S_StartSound(actor, SFX_DRAGON_ATTACK); - } - } - else - { - P_LookForPlayers(actor, true); - } -} - -//============================================================================ -// -// A_DragonFlap -// -//============================================================================ - -void A_DragonFlap(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_DragonFlight(actor, player, psp); - if (P_Random() < 240) - { - S_StartSound(actor, SFX_DRAGON_WINGFLAP); - } - else - { - S_StartSound(actor, actor->info->activesound); - } -} - -//============================================================================ -// -// A_DragonAttack -// -//============================================================================ - -void A_DragonAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMissile(actor, actor->target, MT_DRAGON_FX); -} - -//============================================================================ -// -// A_DragonFX2 -// -//============================================================================ - -void A_DragonFX2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int i; - int r1,r2,r3; - int delay; - - delay = 16 + (P_Random() >> 3); - for (i = 1 + (P_Random() & 3); i; i--) - { - r1 = P_Random(); - r2 = P_Random(); - r3 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r3 - 128) << 14), - actor->y + ((r2 - 128) << 14), - actor->z + ((r1 - 128) << 12), - MT_DRAGON_FX2); - if (mo) - { - mo->tics = delay + (P_Random() & 3) * i * 2; - mo->target = actor->target; - } - } -} - -//============================================================================ -// -// A_DragonPain -// -//============================================================================ - -void A_DragonPain(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_Pain(actor, player, psp); - if (!actor->special1.i) - { // no destination spot yet - P_SetMobjState(actor, S_DRAGON_INIT); - } -} - -//============================================================================ -// -// A_DragonCheckCrash -// -//============================================================================ - -void A_DragonCheckCrash(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->z <= actor->floorz) - { - P_SetMobjState(actor, S_DRAGON_CRASH1); - } -} - -//============================================================================ -// Demon AI -//============================================================================ - -// -// A_DemonAttack1 (melee) -// -void A_DemonAttack1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(2)); - } -} - - -// -// A_DemonAttack2 (missile) -// -void A_DemonAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int fireBall; - - if (actor->type == MT_DEMON) - { - fireBall = MT_DEMONFX1; - } - else - { - fireBall = MT_DEMON2FX1; - } - mo = P_SpawnMissile(actor, actor->target, fireBall); - if (mo) - { - mo->z += 30 * FRACUNIT; - S_StartSound(actor, SFX_DEMON_MISSILE_FIRE); - } -} - -// -// A_DemonDeath -// - -void A_DemonDeath(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMONCHUNK1); - if (mo) - { - angle = actor->angle + ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMONCHUNK2); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMONCHUNK3); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMONCHUNK4); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMONCHUNK5); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } -} - -//=========================================================================== -// -// A_Demon2Death -// -//=========================================================================== - -void A_Demon2Death(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMON2CHUNK1); - if (mo) - { - angle = actor->angle + ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMON2CHUNK2); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMON2CHUNK3); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMON2CHUNK4); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 45 * FRACUNIT, - MT_DEMON2CHUNK5); - if (mo) - { - angle = actor->angle - ANG90; - mo->momz = 8 * FRACUNIT; - mo->momx = FixedMul((P_Random() << 10) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 10) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - } -} - - - -// -// A_SinkMobj -// Sink a mobj incrementally into the floor -// - -boolean A_SinkMobj(mobj_t * actor) -{ - if (actor->floorclip < actor->info->height) - { - switch (actor->type) - { - case MT_THRUSTFLOOR_DOWN: - case MT_THRUSTFLOOR_UP: - actor->floorclip += 6 * FRACUNIT; - break; - default: - actor->floorclip += FRACUNIT; - break; - } - return false; - } - return true; -} - -// -// A_RaiseMobj -// Raise a mobj incrementally from the floor to -// - -boolean A_RaiseMobj(mobj_t * actor) -{ - int done = true; - - // Raise a mobj from the ground - if (actor->floorclip > 0) - { - switch (actor->type) - { - case MT_WRAITHB: - actor->floorclip -= 2 * FRACUNIT; - break; - case MT_THRUSTFLOOR_DOWN: - case MT_THRUSTFLOOR_UP: - actor->floorclip -= actor->special2.i * FRACUNIT; - break; - default: - actor->floorclip -= 2 * FRACUNIT; - break; - } - if (actor->floorclip <= 0) - { - actor->floorclip = 0; - done = true; - } - else - { - done = false; - } - } - return done; // Reached target height -} - - -//============================================================================ -// Wraith Variables -// -// special1 Internal index into floatbob -// special2 -//============================================================================ - -// -// A_WraithInit -// - -void A_WraithInit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->z += 48 << FRACBITS; - actor->special1.i = 0; // index into floatbob -} - -void A_WraithRaiseInit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags2 &= ~MF2_DONTDRAW; - actor->flags2 &= ~MF2_NONSHOOTABLE; - actor->flags |= MF_SHOOTABLE | MF_SOLID; - actor->floorclip = actor->info->height; -} - -void A_WraithRaise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (A_RaiseMobj(actor)) - { - // Reached it's target height - P_SetMobjState(actor, S_WRAITH_CHASE1); - } - - P_SpawnDirt(actor, actor->radius); -} - - -void A_WraithMelee(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int amount; - - // Steal health from target and give to player - if (P_CheckMeleeRange(actor) && (P_Random() < 220)) - { - amount = HITDICE(2); - P_DamageMobj(actor->target, actor, actor, amount); - actor->health += amount; - } -} - -void A_WraithMissile(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMissile(actor, actor->target, MT_WRAITHFX1); - if (mo) - { - S_StartSound(actor, SFX_WRAITH_MISSILE_FIRE); - } -} - - -// -// A_WraithFX2 - spawns sparkle tail of missile -// - -void A_WraithFX2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t angle; - int i; - - for (i = 0; i < 2; i++) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX2); - if (mo) - { - if (P_Random() < 128) - { - angle = actor->angle + (P_Random() << 22); - } - else - { - angle = actor->angle - (P_Random() << 22); - } - mo->momz = 0; - mo->momx = FixedMul((P_Random() << 7) + FRACUNIT, - finecosine[angle >> ANGLETOFINESHIFT]); - mo->momy = FixedMul((P_Random() << 7) + FRACUNIT, - finesine[angle >> ANGLETOFINESHIFT]); - mo->target = actor; - mo->floorclip = 10 * FRACUNIT; - } - } -} - - -// Spawn an FX3 around the actor during attacks -void A_WraithFX3(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int numdropped = P_Random() % 15; - int i; - - for (i = 0; i < numdropped; i++) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX3); - if (mo) - { - mo->x += (P_Random() - 128) << 11; - mo->y += (P_Random() - 128) << 11; - mo->z += (P_Random() << 10); - mo->target = actor; - } - } -} - -// Spawn an FX4 during movement -void A_WraithFX4(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int chance = P_Random(); - int spawn4, spawn5; - - if (chance < 10) - { - spawn4 = true; - spawn5 = false; - } - else if (chance < 20) - { - spawn4 = false; - spawn5 = true; - } - else if (chance < 25) - { - spawn4 = true; - spawn5 = true; - } - else - { - spawn4 = false; - spawn5 = false; - } - - if (spawn4) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX4); - if (mo) - { - mo->x += (P_Random() - 128) << 12; - mo->y += (P_Random() - 128) << 12; - mo->z += (P_Random() << 10); - mo->target = actor; - } - } - if (spawn5) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_WRAITHFX5); - if (mo) - { - mo->x += (P_Random() - 128) << 11; - mo->y += (P_Random() - 128) << 11; - mo->z += (P_Random() << 10); - mo->target = actor; - } - } -} - - -void A_WraithLook(mobj_t *actor, player_t *player, pspdef_t *psp) -{ -// A_WraithFX4(actor); // too expensive - A_Look(actor, player, psp); -} - - -void A_WraithChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int weaveindex = actor->special1.i; - actor->z += FloatBobOffsets[weaveindex]; - actor->special1.i = (weaveindex + 2) & 63; -// if (actor->floorclip > 0) -// { -// P_SetMobjState(actor, S_WRAITH_RAISE2); -// return; -// } - A_Chase(actor, player, psp); - A_WraithFX4(actor, player, psp); -} - - - -//============================================================================ -// Ettin AI -//============================================================================ - -void A_EttinAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_CheckMeleeRange(actor)) - { - P_DamageMobj(actor->target, actor, actor, HITDICE(2)); - } -} - - -void A_DropMace(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, - actor->z + (actor->height >> 1), MT_ETTIN_MACE); - if (mo) - { - mo->momx = (P_Random() - 128) << 11; - mo->momy = (P_Random() - 128) << 11; - mo->momz = FRACUNIT * 10 + (P_Random() << 10); - mo->target = actor; - } -} - - -//============================================================================ -// Fire Demon AI -// -// special1 index into floatbob -// special2 whether strafing or not -//============================================================================ - -void A_FiredSpawnRock(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int x, y, z; - int rtype = 0; - - switch (P_Random() % 5) - { - case 0: - rtype = MT_FIREDEMON_FX1; - break; - case 1: - rtype = MT_FIREDEMON_FX2; - break; - case 2: - rtype = MT_FIREDEMON_FX3; - break; - case 3: - rtype = MT_FIREDEMON_FX4; - break; - case 4: - rtype = MT_FIREDEMON_FX5; - break; - } - - x = actor->x + ((P_Random() - 128) << 12); - y = actor->y + ((P_Random() - 128) << 12); - z = actor->z + ((P_Random()) << 11); - mo = P_SpawnMobj(x, y, z, rtype); - if (mo) - { - mo->target = actor; - mo->momx = (P_Random() - 128) << 10; - mo->momy = (P_Random() - 128) << 10; - mo->momz = (P_Random() << 10); - mo->special1.i = 2; // Number bounces - } - - // Initialize fire demon - actor->special2.i = 0; - actor->flags &= ~MF_JUSTATTACKED; -} - -void A_FiredRocks(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_FiredSpawnRock(actor, player, psp); - A_FiredSpawnRock(actor, player, psp); - A_FiredSpawnRock(actor, player, psp); - A_FiredSpawnRock(actor, player, psp); - A_FiredSpawnRock(actor, player, psp); -} - -void A_FiredAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - mo = P_SpawnMissile(actor, actor->target, MT_FIREDEMON_FX6); - if (mo) - S_StartSound(actor, SFX_FIRED_ATTACK); -} - -void A_SmBounce(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - // give some more momentum (x,y,&z) - actor->z = actor->floorz + FRACUNIT; - actor->momz = (2 * FRACUNIT) + (P_Random() << 10); - actor->momx = P_Random() % 3 << FRACBITS; - actor->momy = P_Random() % 3 << FRACBITS; -} - - -#define FIREDEMON_ATTACK_RANGE 64*8*FRACUNIT - -void A_FiredChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int weaveindex = actor->special1.i; - mobj_t *target = actor->target; - angle_t ang; - fixed_t dist; - - if (actor->reactiontime) - actor->reactiontime--; - if (actor->threshold) - actor->threshold--; - - // Float up and down - actor->z += FloatBobOffsets[weaveindex]; - actor->special1.i = (weaveindex + 2) & 63; - - // Insure it stays above certain height - if (actor->z < actor->floorz + (64 * FRACUNIT)) - { - actor->z += 2 * FRACUNIT; - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { // Invalid target - P_LookForPlayers(actor, true); - return; - } - - // Strafe - if (actor->special2.i > 0) - { - actor->special2.i--; - } - else - { - actor->special2.i = 0; - actor->momx = actor->momy = 0; - dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); - if (dist < FIREDEMON_ATTACK_RANGE) - { - if (P_Random() < 30) - { - ang = - R_PointToAngle2(actor->x, actor->y, target->x, target->y); - if (P_Random() < 128) - ang += ANG90; - else - ang -= ANG90; - ang >>= ANGLETOFINESHIFT; - actor->momx = FixedMul(8 * FRACUNIT, finecosine[ang]); - actor->momy = FixedMul(8 * FRACUNIT, finesine[ang]); - actor->special2.i = 3; // strafe time - } - } - } - - FaceMovementDirection(actor); - - // Normal movement - if (!actor->special2.i) - { - if (--actor->movecount < 0 || !P_Move(actor)) - { - P_NewChaseDir(actor); - } - } - - // Do missile attack - if (!(actor->flags & MF_JUSTATTACKED)) - { - if (P_CheckMissileRange(actor) && (P_Random() < 20)) - { - P_SetMobjState(actor, actor->info->missilestate); - actor->flags |= MF_JUSTATTACKED; - return; - } - } - else - { - actor->flags &= ~MF_JUSTATTACKED; - } - - // make active sound - if (actor->info->activesound && P_Random() < 3) - { - S_StartSound(actor, actor->info->activesound); - } -} - -void A_FiredSplotch(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FIREDEMON_SPLOTCH1); - if (mo) - { - mo->momx = (P_Random() - 128) << 11; - mo->momy = (P_Random() - 128) << 11; - mo->momz = FRACUNIT * 3 + (P_Random() << 10); - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FIREDEMON_SPLOTCH2); - if (mo) - { - mo->momx = (P_Random() - 128) << 11; - mo->momy = (P_Random() - 128) << 11; - mo->momz = FRACUNIT * 3 + (P_Random() << 10); - } -} - - -//============================================================================ -// -// A_IceGuyLook -// -//============================================================================ - -void A_IceGuyLook(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t dist; - fixed_t an; - - A_Look(actor, player, psp); - if (P_Random() < 64) - { - dist = ((P_Random() - 128) * actor->radius) >> 7; - an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - - P_SpawnMobj(actor->x + FixedMul(dist, finecosine[an]), - actor->y + FixedMul(dist, finesine[an]), - actor->z + 60 * FRACUNIT, - MT_ICEGUY_WISP1 + (P_Random() & 1)); - } -} - -//============================================================================ -// -// A_IceGuyChase -// -//============================================================================ - -void A_IceGuyChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t dist; - fixed_t an; - mobj_t *mo; - - A_Chase(actor, player, psp); - if (P_Random() < 128) - { - dist = ((P_Random() - 128) * actor->radius) >> 7; - an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - - mo = P_SpawnMobj(actor->x + FixedMul(dist, finecosine[an]), - actor->y + FixedMul(dist, finesine[an]), - actor->z + 60 * FRACUNIT, - MT_ICEGUY_WISP1 + (P_Random() & 1)); - if (mo) - { - mo->momx = actor->momx; - mo->momy = actor->momy; - mo->momz = actor->momz; - mo->target = actor; - } - } -} - -//============================================================================ -// -// A_IceGuyAttack -// -//============================================================================ - -void A_IceGuyAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t an; - - if (!actor->target) - { - return; - } - an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - P_SpawnMissileXYZ(actor->x + FixedMul(actor->radius >> 1, - finecosine[an]), - actor->y + FixedMul(actor->radius >> 1, finesine[an]), - actor->z + 40 * FRACUNIT, actor, actor->target, - MT_ICEGUY_FX); - an = (actor->angle - ANG90) >> ANGLETOFINESHIFT; - P_SpawnMissileXYZ(actor->x + FixedMul(actor->radius >> 1, - finecosine[an]), - actor->y + FixedMul(actor->radius >> 1, finesine[an]), - actor->z + 40 * FRACUNIT, actor, actor->target, - MT_ICEGUY_FX); - S_StartSound(actor, actor->info->attacksound); -} - -//============================================================================ -// -// A_IceGuyMissilePuff -// -//============================================================================ - -void A_IceGuyMissilePuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMobj(actor->x, actor->y, actor->z + 2 * FRACUNIT, MT_ICEFX_PUFF); -} - -//============================================================================ -// -// A_IceGuyDie -// -//============================================================================ - -void A_IceGuyDie(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->momx = 0; - actor->momy = 0; - actor->momz = 0; - actor->height <<= 2; - A_FreezeDeathChunks(actor, player, psp); -} - -//============================================================================ -// -// A_IceGuyMissileExplode -// -//============================================================================ - -void A_IceGuyMissileExplode(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - unsigned int i; - - for (i = 0; i < 8; i++) - { - mo = P_SpawnMissileAngle(actor, MT_ICEGUY_FX2, i * ANG45, - -0.3 * FRACUNIT); - if (mo) - { - mo->target = actor->target; - } - } -} - - - - - - - - - -//============================================================================ -// -// Sorcerer stuff -// -// Sorcerer Variables -// special1 Angle of ball 1 (all others relative to that) -// special2 which ball to stop at in stop mode (MT_???) -// args[0] Denfense time -// args[1] Number of full rotations since stopping mode -// args[2] Target orbit speed for acceleration/deceleration -// args[3] Movement mode (see SORC_ macros) -// args[4] Current ball orbit speed -// Sorcerer Ball Variables -// special1 Previous angle of ball (for woosh) -// special2 Countdown of rapid fire (FX4) -// args[0] If set, don't play the bounce sound when bouncing -//============================================================================ - -#define SORCBALL_INITIAL_SPEED 7 -#define SORCBALL_TERMINAL_SPEED 25 -#define SORCBALL_SPEED_ROTATIONS 5 -#define SORC_DEFENSE_TIME 255 -#define SORC_DEFENSE_HEIGHT 45 -#define BOUNCE_TIME_UNIT (35/2) -#define SORCFX4_RAPIDFIRE_TIME (6*3) // 3 seconds -#define SORCFX4_SPREAD_ANGLE 20 - -#define SORC_DECELERATE 0 -#define SORC_ACCELERATE 1 -#define SORC_STOPPING 2 -#define SORC_FIRESPELL 3 -#define SORC_STOPPED 4 -#define SORC_NORMAL 5 -#define SORC_FIRING_SPELL 6 - -#define BALL1_ANGLEOFFSET 0 -#define BALL2_ANGLEOFFSET (ANG_MAX/3) -#define BALL3_ANGLEOFFSET ((ANG_MAX/3)*2) - - -// Spawn spinning balls above head - actor is sorcerer -void A_SorcSpinBalls(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - fixed_t z; - - A_SlowBalls(actor, player, psp); - actor->args[0] = 0; // Currently no defense - actor->args[3] = SORC_NORMAL; - actor->args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed - actor->special1.i = ANG1; - z = actor->z - actor->floorclip + actor->info->height; - - mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCBALL1); - if (mo) - { - mo->target = actor; - mo->special2.i = SORCFX4_RAPIDFIRE_TIME; - } - mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCBALL2); - if (mo) - mo->target = actor; - mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCBALL3); - if (mo) - mo->target = actor; -} - - -// -// A_SorcBallOrbit() ========================================== -// - -void A_SorcBallOrbit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int x, y; - angle_t angle, baseangle; - int mode = actor->target->args[3]; - mobj_t *parent = (mobj_t *) actor->target; - int dist = parent->radius - (actor->radius << 1); - angle_t prevangle = actor->special1.i; - - if (actor->target->health <= 0) - P_SetMobjState(actor, actor->info->painstate); - - baseangle = (angle_t) parent->special1.i; - switch (actor->type) - { - case MT_SORCBALL1: - angle = baseangle + BALL1_ANGLEOFFSET; - break; - case MT_SORCBALL2: - angle = baseangle + BALL2_ANGLEOFFSET; - break; - case MT_SORCBALL3: - angle = baseangle + BALL3_ANGLEOFFSET; - break; - default: - I_Error("corrupted sorcerer"); - return; - } - actor->angle = angle; - angle >>= ANGLETOFINESHIFT; - - switch (mode) - { - case SORC_NORMAL: // Balls rotating normally - A_SorcUpdateBallAngle(actor, player, psp); - break; - case SORC_DECELERATE: // Balls decelerating - A_DecelBalls(actor, player, psp); - A_SorcUpdateBallAngle(actor, player, psp); - break; - case SORC_ACCELERATE: // Balls accelerating - A_AccelBalls(actor, player, psp); - A_SorcUpdateBallAngle(actor, player, psp); - break; - case SORC_STOPPING: // Balls stopping - if ((parent->special2.i == actor->type) && - (parent->args[1] > SORCBALL_SPEED_ROTATIONS) && - (abs((int) angle - (int) (parent->angle >> ANGLETOFINESHIFT)) < - (30 << 5))) - { - // Can stop now - actor->target->args[3] = SORC_FIRESPELL; - actor->target->args[4] = 0; - // Set angle so ball angle == sorcerer angle - switch (actor->type) - { - case MT_SORCBALL1: - parent->special1.i = (int) (parent->angle - - BALL1_ANGLEOFFSET); - break; - case MT_SORCBALL2: - parent->special1.i = (int) (parent->angle - - BALL2_ANGLEOFFSET); - break; - case MT_SORCBALL3: - parent->special1.i = (int) (parent->angle - - BALL3_ANGLEOFFSET); - break; - default: - break; - } - } - else - { - A_SorcUpdateBallAngle(actor, player, psp); - } - break; - case SORC_FIRESPELL: // Casting spell - if (parent->special2.i == actor->type) - { - // Put sorcerer into special throw spell anim - if (parent->health > 0) - P_SetMobjStateNF(parent, S_SORC_ATTACK1); - - if (actor->type == MT_SORCBALL1 && P_Random() < 200) - { - S_StartSound(NULL, SFX_SORCERER_SPELLCAST); - actor->special2.i = SORCFX4_RAPIDFIRE_TIME; - actor->args[4] = 128; - parent->args[3] = SORC_FIRING_SPELL; - } - else - { - A_CastSorcererSpell(actor, player, psp); - parent->args[3] = SORC_STOPPED; - } - } - break; - case SORC_FIRING_SPELL: - if (parent->special2.i == actor->type) - { - if (actor->special2.i-- <= 0) - { - // Done rapid firing - parent->args[3] = SORC_STOPPED; - // Back to orbit balls - if (parent->health > 0) - P_SetMobjStateNF(parent, S_SORC_ATTACK4); - } - else - { - // Do rapid fire spell - A_SorcOffense2(actor, player, psp); - } - } - break; - case SORC_STOPPED: // Balls stopped - default: - break; - } - - if ((angle < prevangle) && (parent->args[4] == SORCBALL_TERMINAL_SPEED)) - { - parent->args[1]++; // Bump rotation counter - // Completed full rotation - make woosh sound - S_StartSound(actor, SFX_SORCERER_BALLWOOSH); - } - actor->special1.i = angle; // Set previous angle - x = parent->x + FixedMul(dist, finecosine[angle]); - y = parent->y + FixedMul(dist, finesine[angle]); - actor->x = x; - actor->y = y; - actor->z = parent->z - parent->floorclip + parent->info->height; -} - - -// -// Set balls to speed mode - actor is sorcerer -// -void A_SpeedBalls(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->args[3] = SORC_ACCELERATE; // speed mode - actor->args[2] = SORCBALL_TERMINAL_SPEED; // target speed -} - - -// -// Set balls to slow mode - actor is sorcerer -// -void A_SlowBalls(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->args[3] = SORC_DECELERATE; // slow mode - actor->args[2] = SORCBALL_INITIAL_SPEED; // target speed -} - - -// -// Instant stop when rotation gets to ball in special2 -// actor is sorcerer -// -void A_StopBalls(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int chance = P_Random(); - actor->args[3] = SORC_STOPPING; // stopping mode - actor->args[1] = 0; // Reset rotation counter - - if ((actor->args[0] <= 0) && (chance < 200)) - { - actor->special2.i = MT_SORCBALL2; // Blue - } - else if ((actor->health < (actor->info->spawnhealth >> 1)) && - (chance < 200)) - { - actor->special2.i = MT_SORCBALL3; // Green - } - else - { - actor->special2.i = MT_SORCBALL1; // Yellow - } - - -} - - -// -// Increase ball orbit speed - actor is ball -// -void A_AccelBalls(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *sorc = actor->target; - - if (sorc->args[4] < sorc->args[2]) - { - sorc->args[4]++; - } - else - { - sorc->args[3] = SORC_NORMAL; - if (sorc->args[4] >= SORCBALL_TERMINAL_SPEED) - { - // Reached terminal velocity - stop balls - A_StopBalls(sorc, player, psp); - } - } -} - - -// Decrease ball orbit speed - actor is ball -void A_DecelBalls(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *sorc = actor->target; - - if (sorc->args[4] > sorc->args[2]) - { - sorc->args[4]--; - } - else - { - sorc->args[3] = SORC_NORMAL; - } -} - - -// Update angle if first ball - actor is ball -void A_SorcUpdateBallAngle(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->type == MT_SORCBALL1) - { - actor->target->special1.i += ANG1 * actor->target->args[4]; - } -} - - -// actor is ball -void A_CastSorcererSpell(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int spell = actor->type; - angle_t ang1, ang2; - fixed_t z; - mobj_t *parent = actor->target; - - S_StartSound(NULL, SFX_SORCERER_SPELLCAST); - - // Put sorcerer into throw spell animation - if (parent->health > 0) - P_SetMobjStateNF(parent, S_SORC_ATTACK4); - - switch (spell) - { - case MT_SORCBALL1: // Offensive - A_SorcOffense1(actor, player, psp); - break; - case MT_SORCBALL2: // Defensive - z = parent->z - parent->floorclip + - SORC_DEFENSE_HEIGHT * FRACUNIT; - mo = P_SpawnMobj(actor->x, actor->y, z, MT_SORCFX2); - parent->flags2 |= MF2_REFLECTIVE | MF2_INVULNERABLE; - parent->args[0] = SORC_DEFENSE_TIME; - if (mo) - mo->target = parent; - break; - case MT_SORCBALL3: // Reinforcements - ang1 = actor->angle - ANG45; - ang2 = actor->angle + ANG45; - if (actor->health < (actor->info->spawnhealth / 3)) - { // Spawn 2 at a time - mo = P_SpawnMissileAngle(parent, MT_SORCFX3, ang1, - 4 * FRACUNIT); - if (mo) - mo->target = parent; - mo = P_SpawnMissileAngle(parent, MT_SORCFX3, ang2, - 4 * FRACUNIT); - if (mo) - mo->target = parent; - } - else - { - if (P_Random() < 128) - ang1 = ang2; - mo = P_SpawnMissileAngle(parent, MT_SORCFX3, ang1, - 4 * FRACUNIT); - if (mo) - mo->target = parent; - } - break; - default: - break; - } -} - -/* -void A_SpawnReinforcements(mobj_t *actor) -{ - mobj_t *parent = actor->target; - mobj_t *mo; - angle_t ang; - - ang = ANG1 * P_Random(); - mo = P_SpawnMissileAngle(actor, MT_SORCFX3, ang, 5*FRACUNIT); - if (mo) mo->target = parent; -} -*/ - -// actor is ball -void A_SorcOffense1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - angle_t ang1, ang2; - mobj_t *parent = (mobj_t *) actor->target; - - ang1 = actor->angle + ANG1 * 70; - ang2 = actor->angle - ANG1 * 70; - mo = P_SpawnMissileAngle(parent, MT_SORCFX1, ang1, 0); - if (mo) - { - mo->target = parent; - mo->special1.m = parent->target; - mo->args[4] = BOUNCE_TIME_UNIT; - mo->args[3] = 15; // Bounce time in seconds - } - mo = P_SpawnMissileAngle(parent, MT_SORCFX1, ang2, 0); - if (mo) - { - mo->target = parent; - mo->special1.m = parent->target; - mo->args[4] = BOUNCE_TIME_UNIT; - mo->args[3] = 15; // Bounce time in seconds - } -} - - -// Actor is ball -void A_SorcOffense2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t ang1; - mobj_t *mo; - int delta, index; - mobj_t *parent = actor->target; - mobj_t *dest = parent->target; - int dist; - - index = actor->args[4] << 5; - actor->args[4] += 15; - delta = (finesine[index]) * SORCFX4_SPREAD_ANGLE; - delta = (delta >> FRACBITS) * ANG1; - ang1 = actor->angle + delta; - mo = P_SpawnMissileAngle(parent, MT_SORCFX4, ang1, 0); - if (mo) - { - mo->special2.i = 35 * 5 / 2; // 5 seconds - dist = P_AproxDistance(dest->x - mo->x, dest->y - mo->y); - dist = dist / mo->info->speed; - if (dist < 1) - dist = 1; - mo->momz = (dest->z - mo->z) / dist; - } -} - - -// Resume ball spinning -void A_SorcBossAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->args[3] = SORC_ACCELERATE; - actor->args[2] = SORCBALL_INITIAL_SPEED; -} - - -// spell cast magic fizzle -void A_SpawnFizzle(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t x, y, z; - fixed_t dist = 5 * FRACUNIT; - angle_t angle = actor->angle >> ANGLETOFINESHIFT; - fixed_t speed = actor->info->speed; - angle_t rangle; - mobj_t *mo; - int ix; - - x = actor->x + FixedMul(dist, finecosine[angle]); - y = actor->y + FixedMul(dist, finesine[angle]); - z = actor->z - actor->floorclip + (actor->height >> 1); - for (ix = 0; ix < 5; ix++) - { - mo = P_SpawnMobj(x, y, z, MT_SORCSPARK1); - if (mo) - { - rangle = angle + ((P_Random() % 5) << 1); - mo->momx = FixedMul(P_Random() % speed, finecosine[rangle]); - mo->momy = FixedMul(P_Random() % speed, finesine[rangle]); - mo->momz = FRACUNIT * 2; - } - } -} - - -//============================================================================ -// Yellow spell - offense -//============================================================================ - -void A_SorcFX1Seek(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_BounceCheck(actor, player, psp); - P_SeekerMissile(actor, ANG1 * 2, ANG1 * 6); -} - - -//============================================================================ -// Blue spell - defense -//============================================================================ -// -// FX2 Variables -// special1 current angle -// special2 -// args[0] 0 = CW, 1 = CCW -// args[1] -//============================================================================ - -// Split ball in two -void A_SorcFX2Split(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCFX2); - if (mo) - { - mo->target = actor->target; - mo->args[0] = 0; // CW - mo->special1.i = actor->angle; // Set angle - P_SetMobjStateNF(mo, S_SORCFX2_ORBIT1); - } - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCFX2); - if (mo) - { - mo->target = actor->target; - mo->args[0] = 1; // CCW - mo->special1.i = actor->angle; // Set angle - P_SetMobjStateNF(mo, S_SORCFX2_ORBIT1); - } - P_SetMobjStateNF(actor, S_NULL); -} - - -// Orbit FX2 about sorcerer -void A_SorcFX2Orbit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - fixed_t x, y, z; - mobj_t *parent = actor->target; - fixed_t dist = parent->info->radius; - - if ((parent->health <= 0) || // Sorcerer is dead - (!parent->args[0])) // Time expired - { - P_SetMobjStateNF(actor, actor->info->deathstate); - parent->args[0] = 0; - parent->flags2 &= ~MF2_REFLECTIVE; - parent->flags2 &= ~MF2_INVULNERABLE; - } - - if (actor->args[0] && (parent->args[0]-- <= 0)) // Time expired - { - P_SetMobjStateNF(actor, actor->info->deathstate); - parent->args[0] = 0; - parent->flags2 &= ~MF2_REFLECTIVE; - } - - // Move to new position based on angle - if (actor->args[0]) // Counter clock-wise - { - actor->special1.i += ANG1 * 10; - angle = ((angle_t) actor->special1.i) >> ANGLETOFINESHIFT; - x = parent->x + FixedMul(dist, finecosine[angle]); - y = parent->y + FixedMul(dist, finesine[angle]); - z = parent->z - parent->floorclip + SORC_DEFENSE_HEIGHT * FRACUNIT; - z += FixedMul(15 * FRACUNIT, finecosine[angle]); - // Spawn trailer - P_SpawnMobj(x, y, z, MT_SORCFX2_T1); - } - else // Clock wise - { - actor->special1.i -= ANG1 * 10; - angle = ((angle_t) actor->special1.i) >> ANGLETOFINESHIFT; - x = parent->x + FixedMul(dist, finecosine[angle]); - y = parent->y + FixedMul(dist, finesine[angle]); - z = parent->z - parent->floorclip + SORC_DEFENSE_HEIGHT * FRACUNIT; - z += FixedMul(20 * FRACUNIT, finesine[angle]); - // Spawn trailer - P_SpawnMobj(x, y, z, MT_SORCFX2_T1); - } - - actor->x = x; - actor->y = y; - actor->z = z; -} - - - -//============================================================================ -// Green spell - spawn bishops -//============================================================================ - -void A_SpawnBishop(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BISHOP); - if (mo) - { - if (!P_TestMobjLocation(mo)) - { - P_SetMobjState(mo, S_NULL); - } - } - P_SetMobjState(actor, S_NULL); -} - -/* -void A_SmokePuffEntry(mobj_t *actor) -{ - P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKE); -} -*/ - -void A_SmokePuffExit(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMobj(actor->x, actor->y, actor->z, MT_MNTRSMOKEEXIT); -} - -void A_SorcererBishopEntry(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMobj(actor->x, actor->y, actor->z, MT_SORCFX3_EXPLOSION); - S_StartSound(actor, actor->info->seesound); -} - - -//============================================================================ -// FX4 - rapid fire balls -//============================================================================ - -void A_SorcFX4Check(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special2.i-- <= 0) - { - P_SetMobjStateNF(actor, actor->info->deathstate); - } -} - -//============================================================================ -// Ball death - spawn stuff -//============================================================================ - -void A_SorcBallPop(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, SFX_SORCERER_BALLPOP); - actor->flags &= ~MF_NOGRAVITY; - actor->flags2 |= MF2_LOGRAV; - actor->momx = ((P_Random() % 10) - 5) << FRACBITS; - actor->momy = ((P_Random() % 10) - 5) << FRACBITS; - actor->momz = (2 + (P_Random() % 3)) << FRACBITS; - actor->special2.i = 4 * FRACUNIT; // Initial bounce factor - actor->args[4] = BOUNCE_TIME_UNIT; // Bounce time unit - actor->args[3] = 5; // Bounce time in seconds -} - - - -void A_BounceCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->args[4]-- <= 0) - { - if (actor->args[3]-- <= 0) - { - P_SetMobjState(actor, actor->info->deathstate); - switch (actor->type) - { - case MT_SORCBALL1: - case MT_SORCBALL2: - case MT_SORCBALL3: - S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE); - break; - case MT_SORCFX1: - S_StartSound(NULL, SFX_SORCERER_HEADSCREAM); - break; - default: - break; - } - } - else - { - actor->args[4] = BOUNCE_TIME_UNIT; - } - } -} - - - - -//============================================================================ -// Class Bosses -//============================================================================ -#define CLASS_BOSS_STRAFE_RANGE 64*10*FRACUNIT - -void A_FastChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int delta; - fixed_t dist; - angle_t ang; - mobj_t *target; - - if (actor->reactiontime) - { - actor->reactiontime--; - } - - // Modify target threshold - if (actor->threshold) - { - actor->threshold--; - } - - if (gameskill == sk_nightmare) - { // Monsters move faster in nightmare mode - actor->tics -= actor->tics / 2; - if (actor->tics < 3) - { - actor->tics = 3; - } - } - -// -// turn towards movement direction if not there yet -// - if (actor->movedir < 8) - { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - if (delta > 0) - { - actor->angle -= ANG90 / 2; - } - else if (delta < 0) - { - actor->angle += ANG90 / 2; - } - } - - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { // look for a new target - if (P_LookForPlayers(actor, true)) - { // got a new target - return; - } - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - -// -// don't attack twice in a row -// - if (actor->flags & MF_JUSTATTACKED) - { - actor->flags &= ~MF_JUSTATTACKED; - if (gameskill != sk_nightmare) - P_NewChaseDir(actor); - return; - } - - // Strafe - if (actor->special2.i > 0) - { - actor->special2.i--; - } - else - { - target = actor->target; - actor->special2.i = 0; - actor->momx = actor->momy = 0; - dist = P_AproxDistance(actor->x - target->x, actor->y - target->y); - if (dist < CLASS_BOSS_STRAFE_RANGE) - { - if (P_Random() < 100) - { - ang = R_PointToAngle2(actor->x, actor->y, - target->x, target->y); - if (P_Random() < 128) - ang += ANG90; - else - ang -= ANG90; - ang >>= ANGLETOFINESHIFT; - actor->momx = FixedMul(13 * FRACUNIT, finecosine[ang]); - actor->momy = FixedMul(13 * FRACUNIT, finesine[ang]); - actor->special2.i = 3; // strafe time - } - } - } - -// -// check for missile attack -// - if (actor->info->missilestate) - { - if (gameskill < sk_nightmare && actor->movecount) - goto nomissile; - if (!P_CheckMissileRange(actor)) - goto nomissile; - P_SetMobjState(actor, actor->info->missilestate); - actor->flags |= MF_JUSTATTACKED; - return; - } - nomissile: - -// -// possibly choose another target -// - if (netgame && !actor->threshold && !P_CheckSight(actor, actor->target)) - { - if (P_LookForPlayers(actor, true)) - return; // got a new target - } - -// -// chase towards player -// - if (!actor->special2.i) - { - if (--actor->movecount < 0 || !P_Move(actor)) - { - P_NewChaseDir(actor); - } - } -} - - -void A_FighterAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - return; - A_FSwordAttack2(actor, player, psp); -} - - -void A_ClericAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - return; - A_CHolyAttack3(actor, player, psp); -} - - - -void A_MageAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!actor->target) - return; - A_MStaffAttack2(actor, player, psp); -} - -void A_ClassBossHealth(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (netgame && !deathmatch) // co-op only - { - if (!actor->special1.i) - { - actor->health *= 5; - actor->special1.i = true; // has been initialized - } - } -} - - -//=========================================================================== -// -// A_CheckFloor - Checks if an object hit the floor -// -//=========================================================================== - -void A_CheckFloor(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->z <= actor->floorz) - { - actor->z = actor->floorz; - actor->flags2 &= ~MF2_LOGRAV; - P_SetMobjState(actor, actor->info->deathstate); - } -} - -//============================================================================ -// -// A_FreezeDeath -// -//============================================================================ - -void A_FreezeDeath(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int r = P_Random(); - actor->tics = 75 + r + P_Random(); - actor->flags |= MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD; - actor->flags2 |= MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ | MF2_SLIDE; - actor->height <<= 2; - S_StartSound(actor, SFX_FREEZE_DEATH); - - if (actor->player) - { - actor->player->damagecount = 0; - actor->player->poisoncount = 0; - actor->player->bonuscount = 0; - if (actor->player == &players[consoleplayer]) - { - SB_PaletteFlash(false); - } - } - else if (actor->flags & MF_COUNTKILL && actor->special) - { - // Initiate monster death actions. - P_ExecuteLineSpecial(actor->special, actor->args, NULL, 0, actor); - } -} - -//============================================================================ -// -// A_IceSetTics -// -//============================================================================ - -void A_IceSetTics(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int floor; - - actor->tics = 70 + (P_Random() & 63); - floor = P_GetThingFloorType(actor); - if (floor == FLOOR_LAVA) - { - actor->tics >>= 2; - } - else if (floor == FLOOR_ICE) - { - actor->tics <<= 1; - } -} - -//============================================================================ -// -// A_IceCheckHeadDone -// -//============================================================================ - -void A_IceCheckHeadDone(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->special2.i == 666) - { - P_SetMobjState(actor, S_ICECHUNK_HEAD2); - } -} - -//============================================================================ -// -// A_FreezeDeathChunks -// -//============================================================================ - -void A_FreezeDeathChunks(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - int r1,r2,r3; - mobj_t *mo; - - if (actor->momx || actor->momy || actor->momz) - { - actor->tics = 105; - return; - } - S_StartSound(actor, SFX_FREEZE_SHATTER); - - for (i = 12 + (P_Random() & 15); i >= 0; i--) - { - r1 = P_Random(); - r2 = P_Random(); - r3 = P_Random(); - mo = P_SpawnMobj(actor->x + - (((r3 - 128) * actor->radius) >> 7), - actor->y + - (((r2 - 128) * actor->radius) >> 7), - actor->z + (r1 * actor->height / 255), - MT_ICECHUNK); - P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3)); - mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2; - mo->momx = P_SubRandom() << (FRACBITS - 7); - mo->momy = P_SubRandom() << (FRACBITS - 7); - A_IceSetTics(mo, NULL, NULL); // set a random tic wait - } - for (i = 12 + (P_Random() & 15); i >= 0; i--) - { - r1 = P_Random(); - r2 = P_Random(); - r3 = P_Random(); - mo = P_SpawnMobj(actor->x + - (((r3 - 128) * actor->radius) >> 7), - actor->y + - (((r2 - 128) * actor->radius) >> 7), - actor->z + (r1 * actor->height / 255), - MT_ICECHUNK); - P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3)); - mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2; - mo->momx = P_SubRandom() << (FRACBITS - 7); - mo->momy = P_SubRandom() << (FRACBITS - 7); - A_IceSetTics(mo, NULL, NULL); // set a random tic wait - } - if (actor->player) - { // attach the player's view to a chunk of ice - mo = P_SpawnMobj(actor->x, actor->y, actor->z + VIEWHEIGHT, - MT_ICECHUNK); - P_SetMobjState(mo, S_ICECHUNK_HEAD); - mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2; - mo->momx = P_SubRandom() << (FRACBITS - 7); - mo->momy = P_SubRandom() << (FRACBITS - 7); - mo->flags2 |= MF2_ICEDAMAGE; // used to force blue palette - mo->flags2 &= ~MF2_FLOORCLIP; - mo->player = actor->player; - actor->player = NULL; - mo->health = actor->health; - mo->angle = actor->angle; - mo->player->mo = mo; - mo->player->lookdir = 0; - } - P_RemoveMobjFromTIDList(actor); - P_SetMobjState(actor, S_FREETARGMOBJ); - actor->flags2 |= MF2_DONTDRAW; -} - -//=========================================================================== -// Korax Variables -// special1 last teleport destination -// special2 set if "below half" script not yet run -// -// Korax Scripts (reserved) -// 249 Tell scripts that we are below half health -// 250-254 Control scripts -// 255 Death script -// -// Korax TIDs (reserved) -// 245 Reserved for Korax himself -// 248 Initial teleport destination -// 249 Teleport destination -// 250-254 For use in respective control scripts -// 255 For use in death script (spawn spots) -//=========================================================================== -#define KORAX_SPIRIT_LIFETIME (5*(35/5)) // 5 seconds -#define KORAX_COMMAND_HEIGHT (120*FRACUNIT) -#define KORAX_COMMAND_OFFSET (27*FRACUNIT) - -void KoraxFire1(mobj_t * actor, int type); -void KoraxFire2(mobj_t * actor, int type); -void KoraxFire3(mobj_t * actor, int type); -void KoraxFire4(mobj_t * actor, int type); -void KoraxFire5(mobj_t * actor, int type); -void KoraxFire6(mobj_t * actor, int type); -void KSpiritInit(mobj_t * spirit, mobj_t * korax); - -#define KORAX_TID (245) -#define KORAX_FIRST_TELEPORT_TID (248) -#define KORAX_TELEPORT_TID (249) - -void A_KoraxChase(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *spot; - int lastfound; - byte args[3] = {0, 0, 0}; - - if ((!actor->special2.i) && - (actor->health <= (actor->info->spawnhealth / 2))) - { - lastfound = 0; - spot = P_FindMobjFromTID(KORAX_FIRST_TELEPORT_TID, &lastfound); - if (spot) - { - P_Teleport(actor, spot->x, spot->y, spot->angle, true); - } - - CheckACSPresent(249); - P_StartACS(249, 0, args, actor, NULL, 0); - actor->special2.i = 1; // Don't run again - - return; - } - - if (!actor->target) - return; - if (P_Random() < 30) - { - P_SetMobjState(actor, actor->info->missilestate); - } - else if (P_Random() < 30) - { - S_StartSound(NULL, SFX_KORAX_ACTIVE); - } - - // Teleport away - if (actor->health < (actor->info->spawnhealth >> 1)) - { - if (P_Random() < 10) - { - lastfound = actor->special1.i; - spot = P_FindMobjFromTID(KORAX_TELEPORT_TID, &lastfound); - actor->special1.i = lastfound; - if (spot) - { - P_Teleport(actor, spot->x, spot->y, spot->angle, true); - } - } - } -} - -void A_KoraxStep(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_Chase(actor, player, psp); -} - -void A_KoraxStep2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - S_StartSound(NULL, SFX_KORAX_STEP); - A_Chase(actor, player, psp); -} - -void A_KoraxBonePop(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - byte args[5]; - - args[0] = args[1] = args[2] = args[3] = args[4] = 0; - - // Spawn 6 spirits equalangularly - mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT1, ANG60 * 0, - 5 * FRACUNIT); - if (mo) - KSpiritInit(mo, actor); - mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT2, ANG60 * 1, - 5 * FRACUNIT); - if (mo) - KSpiritInit(mo, actor); - mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT3, ANG60 * 2, - 5 * FRACUNIT); - if (mo) - KSpiritInit(mo, actor); - mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT4, ANG60 * 3, - 5 * FRACUNIT); - if (mo) - KSpiritInit(mo, actor); - mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT5, ANG60 * 4, - 5 * FRACUNIT); - if (mo) - KSpiritInit(mo, actor); - mo = P_SpawnMissileAngle(actor, MT_KORAX_SPIRIT6, ANG60 * 5, - 5 * FRACUNIT); - if (mo) - KSpiritInit(mo, actor); - - CheckACSPresent(255); - P_StartACS(255, 0, args, actor, NULL, 0); // Death script -} - -void KSpiritInit(mobj_t * spirit, mobj_t * korax) -{ - int i; - mobj_t *tail, *next; - - spirit->health = KORAX_SPIRIT_LIFETIME; - - spirit->special1.m = korax; // Swarm around korax - spirit->special2.i = 32 + (P_Random() & 7); // Float bob index - spirit->args[0] = 10; // initial turn value - spirit->args[1] = 0; // initial look angle - - // Spawn a tail for spirit - tail = P_SpawnMobj(spirit->x, spirit->y, spirit->z, MT_HOLY_TAIL); - tail->special2.m = spirit; // parent - for (i = 1; i < 3; i++) - { - next = P_SpawnMobj(spirit->x, spirit->y, spirit->z, MT_HOLY_TAIL); - P_SetMobjState(next, next->info->spawnstate + 1); - tail->special1.m = next; - tail = next; - } - tail->special1.m = NULL; // last tail bit -} - -void A_KoraxDecide(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (P_Random() < 220) - { - P_SetMobjState(actor, S_KORAX_MISSILE1); - } - else - { - P_SetMobjState(actor, S_KORAX_COMMAND1); - } -} - -void A_KoraxMissile(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int type = P_Random() % 6; - int sound = 0; - - S_StartSound(actor, SFX_KORAX_ATTACK); - - switch (type) - { - case 0: - type = MT_WRAITHFX1; - sound = SFX_WRAITH_MISSILE_FIRE; - break; - case 1: - type = MT_DEMONFX1; - sound = SFX_DEMON_MISSILE_FIRE; - break; - case 2: - type = MT_DEMON2FX1; - sound = SFX_DEMON_MISSILE_FIRE; - break; - case 3: - type = MT_FIREDEMON_FX6; - sound = SFX_FIRED_ATTACK; - break; - case 4: - type = MT_CENTAUR_FX; - sound = SFX_CENTAURLEADER_ATTACK; - break; - case 5: - type = MT_SERPENTFX; - sound = SFX_CENTAURLEADER_ATTACK; - break; - } - - // Fire all 6 missiles at once - S_StartSound(NULL, sound); - KoraxFire1(actor, type); - KoraxFire2(actor, type); - KoraxFire3(actor, type); - KoraxFire4(actor, type); - KoraxFire5(actor, type); - KoraxFire6(actor, type); -} - - -// Call action code scripts (250-254) -void A_KoraxCommand(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - byte args[5]; - fixed_t x, y, z; - angle_t ang; - int numcommands; - - S_StartSound(actor, SFX_KORAX_COMMAND); - - // Shoot stream of lightning to ceiling - ang = (actor->angle - ANG90) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_COMMAND_OFFSET, finecosine[ang]); - y = actor->y + FixedMul(KORAX_COMMAND_OFFSET, finesine[ang]); - z = actor->z + KORAX_COMMAND_HEIGHT; - P_SpawnMobj(x, y, z, MT_KORAX_BOLT); - - args[0] = args[1] = args[2] = args[3] = args[4] = 0; - - if (actor->health <= (actor->info->spawnhealth >> 1)) - { - numcommands = 5; - } - else - { - numcommands = 4; - } - - switch (P_Random() % numcommands) - { - case 0: - CheckACSPresent(250); - P_StartACS(250, 0, args, actor, NULL, 0); - break; - case 1: - CheckACSPresent(251); - P_StartACS(251, 0, args, actor, NULL, 0); - break; - case 2: - CheckACSPresent(252); - P_StartACS(252, 0, args, actor, NULL, 0); - break; - case 3: - CheckACSPresent(253); - P_StartACS(253, 0, args, actor, NULL, 0); - break; - case 4: - CheckACSPresent(254); - P_StartACS(254, 0, args, actor, NULL, 0); - break; - } -} - - -#define KORAX_DELTAANGLE (85*ANG1) -#define KORAX_ARM_EXTENSION_SHORT (40*FRACUNIT) -#define KORAX_ARM_EXTENSION_LONG (55*FRACUNIT) - -#define KORAX_ARM1_HEIGHT (108*FRACUNIT) -#define KORAX_ARM2_HEIGHT (82*FRACUNIT) -#define KORAX_ARM3_HEIGHT (54*FRACUNIT) -#define KORAX_ARM4_HEIGHT (104*FRACUNIT) -#define KORAX_ARM5_HEIGHT (86*FRACUNIT) -#define KORAX_ARM6_HEIGHT (53*FRACUNIT) - - -// Arm projectiles -// arm positions numbered: -// 1 top left -// 2 middle left -// 3 lower left -// 4 top right -// 5 middle right -// 6 lower right - - -// Arm 1 projectile -void KoraxFire1(mobj_t * actor, int type) -{ - angle_t ang; - fixed_t x, y, z; - - ang = (actor->angle - KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_ARM_EXTENSION_SHORT, finecosine[ang]); - y = actor->y + FixedMul(KORAX_ARM_EXTENSION_SHORT, finesine[ang]); - z = actor->z - actor->floorclip + KORAX_ARM1_HEIGHT; - P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); -} - - -// Arm 2 projectile -void KoraxFire2(mobj_t * actor, int type) -{ - angle_t ang; - fixed_t x, y, z; - - ang = (actor->angle - KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); - y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); - z = actor->z - actor->floorclip + KORAX_ARM2_HEIGHT; - P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); -} - -// Arm 3 projectile -void KoraxFire3(mobj_t * actor, int type) -{ - angle_t ang; - fixed_t x, y, z; - - ang = (actor->angle - KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); - y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); - z = actor->z - actor->floorclip + KORAX_ARM3_HEIGHT; - P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); -} - -// Arm 4 projectile -void KoraxFire4(mobj_t * actor, int type) -{ - angle_t ang; - fixed_t x, y, z; - - ang = (actor->angle + KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_ARM_EXTENSION_SHORT, finecosine[ang]); - y = actor->y + FixedMul(KORAX_ARM_EXTENSION_SHORT, finesine[ang]); - z = actor->z - actor->floorclip + KORAX_ARM4_HEIGHT; - P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); -} - -// Arm 5 projectile -void KoraxFire5(mobj_t * actor, int type) -{ - angle_t ang; - fixed_t x, y, z; - - ang = (actor->angle + KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); - y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); - z = actor->z - actor->floorclip + KORAX_ARM5_HEIGHT; - P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); -} - -// Arm 6 projectile -void KoraxFire6(mobj_t * actor, int type) -{ - angle_t ang; - fixed_t x, y, z; - - ang = (actor->angle + KORAX_DELTAANGLE) >> ANGLETOFINESHIFT; - x = actor->x + FixedMul(KORAX_ARM_EXTENSION_LONG, finecosine[ang]); - y = actor->y + FixedMul(KORAX_ARM_EXTENSION_LONG, finesine[ang]); - z = actor->z - actor->floorclip + KORAX_ARM6_HEIGHT; - P_SpawnKoraxMissile(x, y, z, actor, actor->target, type); -} - - -void A_KSpiritWeave(mobj_t *actor) -{ - fixed_t newX, newY; - int weaveXY, weaveZ; - int angle; - - weaveXY = actor->special2.i >> 16; - weaveZ = actor->special2.i & 0xFFFF; - angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - newX = actor->x - FixedMul(finecosine[angle], - FloatBobOffsets[weaveXY] << 2); - newY = actor->y - FixedMul(finesine[angle], - FloatBobOffsets[weaveXY] << 2); - weaveXY = (weaveXY + (P_Random() % 5)) & 63; - newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 2); - newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 2); - P_TryMove(actor, newX, newY); - actor->z -= FloatBobOffsets[weaveZ] << 1; - weaveZ = (weaveZ + (P_Random() % 5)) & 63; - actor->z += FloatBobOffsets[weaveZ] << 1; - actor->special2.i = weaveZ + (weaveXY << 16); -} - -void A_KSpiritSeeker(mobj_t * actor, angle_t thresh, angle_t turnMax) -{ - int dir; - int dist; - angle_t delta; - angle_t angle; - mobj_t *target; - fixed_t newZ; - fixed_t deltaZ; - - target = actor->special1.m; - if (target == NULL) - { - return; - } - dir = P_FaceMobj(actor, target, &delta); - if (delta > thresh) - { - delta >>= 1; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->angle += delta; - } - else - { // Turn counter clockwise - actor->angle -= delta; - } - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(actor->info->speed, finecosine[angle]); - actor->momy = FixedMul(actor->info->speed, finesine[angle]); - - if (!(leveltime & 15) - || actor->z > target->z + (target->info->height) - || actor->z + actor->height < target->z) - { - newZ = target->z + ((P_Random() * target->info->height) >> 8); - deltaZ = newZ - actor->z; - if (abs(deltaZ) > 15 * FRACUNIT) - { - if (deltaZ > 0) - { - deltaZ = 15 * FRACUNIT; - } - else - { - deltaZ = -15 * FRACUNIT; - } - } - dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); - dist = dist / actor->info->speed; - if (dist < 1) - { - dist = 1; - } - actor->momz = deltaZ / dist; - } - return; -} - - -void A_KSpiritRoam(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (actor->health-- <= 0) - { - S_StartSound(actor, SFX_SPIRIT_DIE); - P_SetMobjState(actor, S_KSPIRIT_DEATH1); - } - else - { - if (actor->special1.m) - { - A_KSpiritSeeker(actor, actor->args[0] * ANG1, - actor->args[0] * ANG1 * 2); - } - A_KSpiritWeave(actor); - if (P_Random() < 50) - { - S_StartSound(NULL, SFX_SPIRIT_ACTIVE); - } - } -} - -void A_KBolt(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - // Countdown lifetime - if (actor->special1.i-- <= 0) - { - P_SetMobjState(actor, S_NULL); - } -} - - -#define KORAX_BOLT_HEIGHT 48*FRACUNIT -#define KORAX_BOLT_LIFETIME 3 - -void A_KBoltRaise(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - fixed_t z; - - // Spawn a child upward - z = actor->z + KORAX_BOLT_HEIGHT; - - if ((z + KORAX_BOLT_HEIGHT) < actor->ceilingz) - { - mo = P_SpawnMobj(actor->x, actor->y, z, MT_KORAX_BOLT); - if (mo) - { - mo->special1.i = KORAX_BOLT_LIFETIME; - } - } - else - { - // Maybe cap it off here - } -} diff --git a/games/NXDoom/src/hexen/p_floor.c b/games/NXDoom/src/hexen/p_floor.c deleted file mode 100644 index 370cb173fec..00000000000 --- a/games/NXDoom/src/hexen/p_floor.c +++ /dev/null @@ -1,946 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "p_local.h" - - -//================================================================== -//================================================================== -// -// FLOORS -// -//================================================================== -//================================================================== - -//================================================================== -// -// Move a plane (floor or ceiling) and check for crushing -// -//================================================================== -result_e T_MovePlane(sector_t * sector, fixed_t speed, - fixed_t dest, int crush, int floorOrCeiling, - int direction) -{ - boolean flag; - fixed_t lastpos; - - switch (floorOrCeiling) - { - case 0: // FLOOR - switch (direction) - { - case -1: // DOWN - if (sector->floorheight - speed < dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - //return RES_CRUSHED; - } - return RES_PASTDEST; - } - else - { - lastpos = sector->floorheight; - sector->floorheight -= speed; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - return RES_CRUSHED; - } - } - break; - - case 1: // UP - if (sector->floorheight + speed > dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - //return RES_CRUSHED; - } - return RES_PASTDEST; - } - else // COULD GET CRUSHED - { - lastpos = sector->floorheight; - sector->floorheight += speed; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - //if (crush == true) - //{ - // return RES_CRUSHED; - //} - sector->floorheight = lastpos; - P_ChangeSector(sector, crush); - return RES_CRUSHED; - } - } - break; - } - break; - - case 1: // CEILING - switch (direction) - { - case -1: // DOWN - if (sector->ceilingheight - speed < dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - //return RES_CRUSHED; - } - return RES_PASTDEST; - } - else // COULD GET CRUSHED - { - lastpos = sector->ceilingheight; - sector->ceilingheight -= speed; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - //if (crush == true) - //{ - // return RES_CRUSHED; - //} - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - return RES_CRUSHED; - } - } - break; - - case 1: // UP - if (sector->ceilingheight + speed > dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector, crush); - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - //return RES_CRUSHED; - } - return RES_PASTDEST; - } - else - { - lastpos = sector->ceilingheight; - sector->ceilingheight += speed; - flag = P_ChangeSector(sector, crush); -#if 0 - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector, crush); - return RES_CRUSHED; - } -#endif - } - break; - } - break; - - } - return RES_OK; -} - -//================================================================== -// -// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) -// -//================================================================== -void T_MoveFloor(thinker_t *thinker) -{ - floormove_t *floor = (floormove_t *) thinker; - result_e res; - - if (floor->resetDelayCount) - { - floor->resetDelayCount--; - if (!floor->resetDelayCount) - { - floor->floordestheight = floor->resetHeight; - floor->direction = -floor->direction; - floor->resetDelay = 0; - floor->delayCount = 0; - floor->delayTotal = 0; - } - } - if (floor->delayCount) - { - floor->delayCount--; - if (!floor->delayCount && floor->textureChange) - { - floor->sector->floorpic += floor->textureChange; - } - return; - } - - res = T_MovePlane(floor->sector, floor->speed, - floor->floordestheight, floor->crush, 0, - floor->direction); - - if (floor->type == FLEV_RAISEBUILDSTEP) - { - if ((floor->direction == 1 && floor->sector->floorheight >= - floor->stairsDelayHeight) || (floor->direction == -1 && - floor->sector->floorheight <= - floor->stairsDelayHeight)) - { - floor->delayCount = floor->delayTotal; - floor->stairsDelayHeight += floor->stairsDelayHeightDelta; - } - } - if (res == RES_PASTDEST) - { - SN_StopSequence((mobj_t *) & floor->sector->soundorg); - if (floor->delayTotal) - { - floor->delayTotal = 0; - } - if (floor->resetDelay) - { -// floor->resetDelayCount = floor->resetDelay; -// floor->resetDelay = 0; - return; - } - floor->sector->specialdata = NULL; - /* - if (floor->direction == 1) - switch(floor->type) - { - case donutRaise: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - else if (floor->direction == -1) - switch(floor->type) - { - case lowerAndChange: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - */ - if (floor->textureChange) - { - floor->sector->floorpic -= floor->textureChange; - } - P_TagFinished(floor->sector->tag); - P_RemoveThinker(&floor->thinker); - } -} - -//================================================================== -// -// HANDLE FLOOR TYPES -// -//================================================================== -int EV_DoFloor(line_t * line, byte * args, floor_e floortype) -{ - int secnum; - int rtn; - sector_t *sec; - floormove_t *floor = NULL; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // - // new floor thinker - // - rtn = 1; - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - memset(floor, 0, sizeof(*floor)); - P_AddThinker(&floor->thinker); - sec->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = floortype; - floor->crush = 0; - floor->speed = args[1] * (FRACUNIT / 8); - if (floortype == FLEV_LOWERTIMES8INSTANT || - floortype == FLEV_RAISETIMES8INSTANT) - { - floor->speed = 2000 << FRACBITS; - } - switch (floortype) - { - case FLEV_LOWERFLOOR: - floor->direction = -1; - floor->sector = sec; - floor->floordestheight = P_FindHighestFloorSurrounding(sec); - break; - case FLEV_LOWERFLOORTOLOWEST: - floor->direction = -1; - floor->sector = sec; - floor->floordestheight = P_FindLowestFloorSurrounding(sec); - break; - case FLEV_LOWERFLOORBYVALUE: - floor->direction = -1; - floor->sector = sec; - floor->floordestheight = floor->sector->floorheight - - args[2] * FRACUNIT; - break; - case FLEV_LOWERTIMES8INSTANT: - case FLEV_LOWERBYVALUETIMES8: - floor->direction = -1; - floor->sector = sec; - floor->floordestheight = floor->sector->floorheight - - args[2] * FRACUNIT * 8; - break; - case FLEV_RAISEFLOORCRUSH: - floor->crush = args[2]; // arg[2] = crushing value - floor->direction = 1; - floor->sector = sec; - floor->floordestheight = sec->ceilingheight - 8 * FRACUNIT; - break; - case FLEV_RAISEFLOOR: - floor->direction = 1; - floor->sector = sec; - floor->floordestheight = P_FindLowestCeilingSurrounding(sec); - if (floor->floordestheight > sec->ceilingheight) - floor->floordestheight = sec->ceilingheight; - break; - case FLEV_RAISEFLOORTONEAREST: - floor->direction = 1; - floor->sector = sec; - floor->floordestheight = - P_FindNextHighestFloor(sec, sec->floorheight); - break; - case FLEV_RAISEFLOORBYVALUE: - floor->direction = 1; - floor->sector = sec; - floor->floordestheight = floor->sector->floorheight + - args[2] * FRACUNIT; - break; - case FLEV_RAISETIMES8INSTANT: - case FLEV_RAISEBYVALUETIMES8: - floor->direction = 1; - floor->sector = sec; - floor->floordestheight = floor->sector->floorheight + - args[2] * FRACUNIT * 8; - break; - case FLEV_MOVETOVALUETIMES8: - floor->sector = sec; - floor->floordestheight = args[2] * FRACUNIT * 8; - if (args[3]) - { - floor->floordestheight = -floor->floordestheight; - } - if (floor->floordestheight > floor->sector->floorheight) - { - floor->direction = 1; - } - else if (floor->floordestheight < floor->sector->floorheight) - { - floor->direction = -1; - } - else - { // already at lowest position - rtn = 0; - } - break; - default: - rtn = 0; - break; - } - } - if (rtn) - { - SN_StartSequence((mobj_t *) & floor->sector->soundorg, - SEQ_PLATFORM + floor->sector->seqType); - } - return rtn; -} - -//============================================================================ -// -// EV_DoFloorAndCeiling -// -//============================================================================ - -int EV_DoFloorAndCeiling(line_t * line, byte * args, boolean raise) -{ - boolean floor, ceiling; - int secnum; - sector_t *sec; - - if (raise) - { - floor = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE); - secnum = -1; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - sec->specialdata = NULL; - } - ceiling = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE); - } - else - { - floor = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE); - secnum = -1; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - sec->specialdata = NULL; - } - ceiling = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE); - } - return (floor | ceiling); -} - -// ===== Build Stairs Private Data ===== - -#define STAIR_SECTOR_TYPE 26 -#define STAIR_QUEUE_SIZE 32 - -struct -{ - sector_t *sector; - int type; - int height; -} StairQueue[STAIR_QUEUE_SIZE]; - -static int QueueHead; -static int QueueTail; - -static int StepDelta; -static int Direction; -static int Speed; -static int Texture; -static int StartDelay; -static int StartDelayDelta; -static int TextureChange; -static int StartHeight; - -//========================================================================== -// -// QueueStairSector -// -//========================================================================== - -static void QueueStairSector(sector_t * sec, int type, int height) -{ - if ((QueueTail + 1) % STAIR_QUEUE_SIZE == QueueHead) - { - I_Error("BuildStairs: Too many branches located.\n"); - } - StairQueue[QueueTail].sector = sec; - StairQueue[QueueTail].type = type; - StairQueue[QueueTail].height = height; - - QueueTail = (QueueTail + 1) % STAIR_QUEUE_SIZE; -} - -//========================================================================== -// -// DequeueStairSector -// -//========================================================================== - -static sector_t *DequeueStairSector(int *type, int *height) -{ - sector_t *sec; - - if (QueueHead == QueueTail) - { // queue is empty - return NULL; - } - *type = StairQueue[QueueHead].type; - *height = StairQueue[QueueHead].height; - sec = StairQueue[QueueHead].sector; - QueueHead = (QueueHead + 1) % STAIR_QUEUE_SIZE; - - return sec; -} - -//========================================================================== -// -// ProcessStairSector -// -//========================================================================== - -static void ProcessStairSector(sector_t * sec, int type, int height, - stairs_e stairsType, int delay, int resetDelay) -{ - int i; - sector_t *tsec; - floormove_t *floor; - - // - // new floor thinker - // - height += StepDelta; - floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0); - memset(floor, 0, sizeof(*floor)); - P_AddThinker(&floor->thinker); - sec->specialdata = floor; - floor->thinker.function = T_MoveFloor; - floor->type = FLEV_RAISEBUILDSTEP; - floor->direction = Direction; - floor->sector = sec; - floor->floordestheight = height; - switch (stairsType) - { - case STAIRS_NORMAL: - floor->speed = Speed; - if (delay) - { - floor->delayTotal = delay; - floor->stairsDelayHeight = sec->floorheight + StepDelta; - floor->stairsDelayHeightDelta = StepDelta; - } - floor->resetDelay = resetDelay; - floor->resetDelayCount = resetDelay; - floor->resetHeight = sec->floorheight; - break; - case STAIRS_SYNC: - floor->speed = FixedMul(Speed, FixedDiv(height - StartHeight, - StepDelta)); - floor->resetDelay = delay; //arg4 - floor->resetDelayCount = delay; - floor->resetHeight = sec->floorheight; - break; -/* - case STAIRS_PHASED: - floor->floordestheight = sec->floorheight+StepDelta; - floor->speed = Speed; - floor->delayCount = StartDelay; - StartDelay += StartDelayDelta; - floor->textureChange = TextureChange; - floor->resetDelayCount = StartDelay; - break; -*/ - default: - break; - } - SN_StartSequence((mobj_t *) & sec->soundorg, SEQ_PLATFORM + sec->seqType); - // - // Find next sector to raise - // Find nearby sector with sector special equal to type - // - for (i = 0; i < sec->linecount; i++) - { - if (!((sec->lines[i])->flags & ML_TWOSIDED)) - { - continue; - } - tsec = (sec->lines[i])->frontsector; - if (tsec->special == type + STAIR_SECTOR_TYPE && !tsec->specialdata - && tsec->floorpic == Texture && tsec->validcount != validcount) - { - QueueStairSector(tsec, type ^ 1, height); - tsec->validcount = validcount; - //tsec->special = 0; - } - tsec = (sec->lines[i])->backsector; - if (tsec->special == type + STAIR_SECTOR_TYPE && !tsec->specialdata - && tsec->floorpic == Texture && tsec->validcount != validcount) - { - QueueStairSector(tsec, type ^ 1, height); - tsec->validcount = validcount; - //tsec->special = 0; - } - } -} - -//================================================================== -// -// BUILD A STAIRCASE! -// -// Direction is either positive or negative, denoting build stairs -// up or down. -//================================================================== - -int EV_BuildStairs(line_t * line, byte * args, int direction, - stairs_e stairsType) -{ - int secnum; - int height; - int delay; - int resetDelay; - sector_t *sec; - sector_t *qSec; - int type; - - // Set global stairs variables - TextureChange = 0; - Direction = direction; - StepDelta = Direction * (args[2] * FRACUNIT); - Speed = args[1] * (FRACUNIT / 8); - resetDelay = args[4]; - delay = args[3]; - if (stairsType == STAIRS_PHASED) - { - StartDelayDelta = args[3]; - StartDelay = StartDelayDelta; - resetDelay = StartDelayDelta; - delay = 0; - TextureChange = args[4]; - } - - secnum = -1; - - validcount++; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - - Texture = sec->floorpic; - StartHeight = sec->floorheight; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - QueueStairSector(sec, 0, sec->floorheight); - sec->special = 0; - } - while ((qSec = DequeueStairSector(&type, &height)) != NULL) - { - ProcessStairSector(qSec, type, height, stairsType, delay, resetDelay); - } - return (1); -} - -//========================================================================= -// -// T_BuildPillar -// -//========================================================================= - -void T_BuildPillar(thinker_t *thinker) -{ - pillar_t *pillar = (pillar_t *) thinker; - result_e res1; - result_e res2; - - // First, raise the floor - res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floordest, pillar->crush, 0, pillar->direction); // floorOrCeiling, direction - // Then, lower the ceiling - res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed, - pillar->ceilingdest, pillar->crush, 1, - -pillar->direction); - if (res1 == RES_PASTDEST && res2 == RES_PASTDEST) - { - pillar->sector->specialdata = NULL; - SN_StopSequence((mobj_t *) & pillar->sector->soundorg); - P_TagFinished(pillar->sector->tag); - P_RemoveThinker(&pillar->thinker); - } -} - -//========================================================================= -// -// EV_BuildPillar -// -//========================================================================= - -int EV_BuildPillar(line_t * line, byte * args, boolean crush) -{ - int secnum; - sector_t *sec; - pillar_t *pillar; - int newHeight; - int rtn; - - rtn = 0; - secnum = -1; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; // already moving - if (sec->floorheight == sec->ceilingheight) - { // pillar is already closed - continue; - } - rtn = 1; - if (!args[2]) - { - newHeight = sec->floorheight + - ((sec->ceilingheight - sec->floorheight) / 2); - } - else - { - newHeight = sec->floorheight + (args[2] << FRACBITS); - } - - pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0); - sec->specialdata = pillar; - P_AddThinker(&pillar->thinker); - pillar->thinker.function = T_BuildPillar; - pillar->sector = sec; - if (!args[2]) - { - pillar->ceilingSpeed = pillar->floorSpeed = - args[1] * (FRACUNIT / 8); - } - else if (newHeight - sec->floorheight > - sec->ceilingheight - newHeight) - { - pillar->floorSpeed = args[1] * (FRACUNIT / 8); - pillar->ceilingSpeed = FixedMul(sec->ceilingheight - newHeight, - FixedDiv(pillar->floorSpeed, - newHeight - - sec->floorheight)); - } - else - { - pillar->ceilingSpeed = args[1] * (FRACUNIT / 8); - pillar->floorSpeed = FixedMul(newHeight - sec->floorheight, - FixedDiv(pillar->ceilingSpeed, - sec->ceilingheight - - newHeight)); - } - pillar->floordest = newHeight; - pillar->ceilingdest = newHeight; - pillar->direction = 1; - pillar->crush = crush * args[3]; - SN_StartSequence((mobj_t *) & pillar->sector->soundorg, - SEQ_PLATFORM + pillar->sector->seqType); - } - return rtn; -} - -//========================================================================= -// -// EV_OpenPillar -// -//========================================================================= - -int EV_OpenPillar(line_t * line, byte * args) -{ - int secnum; - sector_t *sec; - pillar_t *pillar; - int rtn; - - rtn = 0; - secnum = -1; - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; // already moving - if (sec->floorheight != sec->ceilingheight) - { // pillar isn't closed - continue; - } - rtn = 1; - pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0); - sec->specialdata = pillar; - P_AddThinker(&pillar->thinker); - pillar->thinker.function = T_BuildPillar; - pillar->sector = sec; - if (!args[2]) - { - pillar->floordest = P_FindLowestFloorSurrounding(sec); - } - else - { - pillar->floordest = sec->floorheight - (args[2] << FRACBITS); - } - if (!args[3]) - { - pillar->ceilingdest = P_FindHighestCeilingSurrounding(sec); - } - else - { - pillar->ceilingdest = sec->ceilingheight + (args[3] << FRACBITS); - } - if (sec->floorheight - pillar->floordest >= pillar->ceilingdest - - sec->ceilingheight) - { - pillar->floorSpeed = args[1] * (FRACUNIT / 8); - pillar->ceilingSpeed = FixedMul(sec->ceilingheight - - pillar->ceilingdest, - FixedDiv(pillar->floorSpeed, - pillar->floordest - - sec->floorheight)); - } - else - { - pillar->ceilingSpeed = args[1] * (FRACUNIT / 8); - pillar->floorSpeed = - FixedMul(pillar->floordest - sec->floorheight, - FixedDiv(pillar->ceilingSpeed, - sec->ceilingheight - pillar->ceilingdest)); - } - pillar->direction = -1; // open the pillar - SN_StartSequence((mobj_t *) & pillar->sector->soundorg, - SEQ_PLATFORM + pillar->sector->seqType); - } - return rtn; -} - -//========================================================================= -// -// EV_FloorCrushStop -// -//========================================================================= - -int EV_FloorCrushStop(line_t * line, byte * args) -{ - thinker_t *think; - floormove_t *floor; - boolean rtn; - - rtn = 0; - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != T_MoveFloor) - { - continue; - } - floor = (floormove_t *) think; - if (floor->type != FLEV_RAISEFLOORCRUSH) - { - continue; - } - // Completely remove the crushing floor - SN_StopSequence((mobj_t *) & floor->sector->soundorg); - floor->sector->specialdata = NULL; - P_TagFinished(floor->sector->tag); - P_RemoveThinker(&floor->thinker); - rtn = 1; - } - return rtn; -} - -//========================================================================== -// -// T_FloorWaggle -// -//========================================================================== - -#define WGLSTATE_EXPAND 1 -#define WGLSTATE_STABLE 2 -#define WGLSTATE_REDUCE 3 - -void T_FloorWaggle(thinker_t *thinker) -{ - floorWaggle_t *waggle = (floorWaggle_t *) thinker; - switch (waggle->state) - { - case WGLSTATE_EXPAND: - if ((waggle->scale += waggle->scaleDelta) >= waggle->targetScale) - { - waggle->scale = waggle->targetScale; - waggle->state = WGLSTATE_STABLE; - } - break; - case WGLSTATE_REDUCE: - if ((waggle->scale -= waggle->scaleDelta) <= 0) - { // Remove - waggle->sector->floorheight = waggle->originalHeight; - P_ChangeSector(waggle->sector, true); - waggle->sector->specialdata = NULL; - P_TagFinished(waggle->sector->tag); - P_RemoveThinker(&waggle->thinker); - return; - } - break; - case WGLSTATE_STABLE: - if (waggle->ticker != -1) - { - if (!--waggle->ticker) - { - waggle->state = WGLSTATE_REDUCE; - } - } - break; - } - waggle->accumulator += waggle->accDelta; - waggle->sector->floorheight = waggle->originalHeight - + FixedMul(FloatBobOffsets[(waggle->accumulator >> FRACBITS) & 63], - waggle->scale); - P_ChangeSector(waggle->sector, true); -} - -//========================================================================== -// -// EV_StartFloorWaggle -// -//========================================================================== - -boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset, - int timer) -{ - int sectorIndex; - sector_t *sector; - floorWaggle_t *waggle; - boolean retCode; - - retCode = false; - sectorIndex = -1; - while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0) - { - sector = §ors[sectorIndex]; - if (sector->specialdata) - { // Already busy with another thinker - continue; - } - retCode = true; - waggle = Z_Malloc(sizeof(*waggle), PU_LEVSPEC, 0); - sector->specialdata = waggle; - waggle->thinker.function = T_FloorWaggle; - waggle->sector = sector; - waggle->originalHeight = sector->floorheight; - waggle->accumulator = offset * FRACUNIT; - waggle->accDelta = speed << 10; - waggle->scale = 0; - waggle->targetScale = height << 10; - waggle->scaleDelta = waggle->targetScale - / (35 + ((3 * 35) * height) / 255); - waggle->ticker = timer ? timer * 35 : -1; - waggle->state = WGLSTATE_EXPAND; - P_AddThinker(&waggle->thinker); - } - return retCode; -} diff --git a/games/NXDoom/src/hexen/p_inter.c b/games/NXDoom/src/hexen/p_inter.c deleted file mode 100644 index fab06674c2a..00000000000 --- a/games/NXDoom/src/hexen/p_inter.c +++ /dev/null @@ -1,2231 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "m_misc.h" -#include "m_random.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" - -#define BONUSADD 6 - -int ArmorIncrement[NUMCLASSES][NUMARMOR] = { - {25 * FRACUNIT, 20 * FRACUNIT, 15 * FRACUNIT, 5 * FRACUNIT}, - {10 * FRACUNIT, 25 * FRACUNIT, 5 * FRACUNIT, 20 * FRACUNIT}, - {5 * FRACUNIT, 15 * FRACUNIT, 10 * FRACUNIT, 25 * FRACUNIT}, - {0, 0, 0, 0} -}; - -int AutoArmorSave[NUMCLASSES] = - { 15 * FRACUNIT, 10 * FRACUNIT, 5 * FRACUNIT, 0 }; - -const char *TextKeyMessages[] = { - TXT_KEY_STEEL, - TXT_KEY_CAVE, - TXT_KEY_AXE, - TXT_KEY_FIRE, - TXT_KEY_EMERALD, - TXT_KEY_DUNGEON, - TXT_KEY_SILVER, - TXT_KEY_RUSTED, - TXT_KEY_HORN, - TXT_KEY_SWAMP, - TXT_KEY_CASTLE -}; - -static void SetDormantArtifact(mobj_t * arti); -static void TryPickupArtifact(player_t * player, artitype_t artifactType, - mobj_t * artifact); -static void TryPickupWeapon(player_t * player, pclass_t weaponClass, - weapontype_t weaponType, mobj_t * weapon, - const char *message); -static void TryPickupWeaponPiece(player_t * player, pclass_t matchClass, - int pieceValue, mobj_t * pieceMobj); - -//-------------------------------------------------------------------------- -// -// PROC P_SetMessage -// -//-------------------------------------------------------------------------- - -void P_SetMessage(player_t * player, const char *message, boolean ultmsg) -{ - if ((player->ultimateMessage || !messageson) && !ultmsg) - { - return; - } - - M_StringCopy(player->message, message, sizeof(player->message)); -// strupr(player->message); - player->messageTics = MESSAGETICS; - player->yellowMessage = false; - if (ultmsg) - { - player->ultimateMessage = true; - } - if (player == &players[consoleplayer]) - { - BorderTopRefresh = true; - } -} - -//========================================================================== -// -// P_SetYellowMessage -// -//========================================================================== - -void P_SetYellowMessage(player_t * player, const char *message, boolean ultmsg) -{ - if ((player->ultimateMessage || !messageson) && !ultmsg) - { - return; - } - M_StringCopy(player->message, message, sizeof(player->message)); - player->messageTics = 5 * MESSAGETICS; // Bold messages last longer - player->yellowMessage = true; - if (ultmsg) - { - player->ultimateMessage = true; - } - if (player == &players[consoleplayer]) - { - BorderTopRefresh = true; - } -} - -//========================================================================== -// -// P_ClearMessage -// -//========================================================================== - -void P_ClearMessage(player_t * player) -{ - player->messageTics = 0; - if (player == &players[consoleplayer]) - { - BorderTopRefresh = true; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_HideSpecialThing -// -//---------------------------------------------------------------------------- - -void P_HideSpecialThing(mobj_t * thing) -{ - thing->flags &= ~MF_SPECIAL; - thing->flags2 |= MF2_DONTDRAW; - P_SetMobjState(thing, S_HIDESPECIAL1); -} - -//-------------------------------------------------------------------------- -// -// FUNC P_GiveMana -// -// Returns true if the player accepted the mana, false if it was -// refused (player has MAX_MANA). -// -//-------------------------------------------------------------------------- - -boolean P_GiveMana(player_t * player, manatype_t mana, int count) -{ - int prevMana; - //weapontype_t changeWeapon; - - if (mana == MANA_NONE || mana == MANA_BOTH) - { - return (false); - } - if ((unsigned int) mana > NUMMANA) - { - I_Error("P_GiveMana: bad type %i", mana); - } - if (player->mana[mana] == MAX_MANA) - { - return (false); - } - if (gameskill == sk_baby || gameskill == sk_nightmare) - { // extra mana in baby mode and nightmare mode - count += count >> 1; - } - prevMana = player->mana[mana]; - - player->mana[mana] += count; - if (player->mana[mana] > MAX_MANA) - { - player->mana[mana] = MAX_MANA; - } - if (player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND - && mana == MANA_1 && prevMana <= 0) - { - P_SetPsprite(player, ps_weapon, S_FAXEREADY_G); - } - return (true); -} - -//========================================================================== -// -// TryPickupWeapon -// -//========================================================================== - -static void TryPickupWeapon(player_t * player, pclass_t weaponClass, - weapontype_t weaponType, mobj_t * weapon, - const char *message) -{ - boolean remove; - boolean gaveMana; - boolean gaveWeapon; - - remove = true; - if (player->class != weaponClass) - { // Wrong class, but try to pick up for mana - if (netgame && !deathmatch) - { // Can't pick up weapons for other classes in coop netplay - return; - } - if (weaponType == WP_SECOND) - { - if (!P_GiveMana(player, MANA_1, 25)) - { - return; - } - } - else - { - if (!P_GiveMana(player, MANA_2, 25)) - { - return; - } - } - } - else if (netgame && !deathmatch) - { // Cooperative net-game - if (player->weaponowned[weaponType]) - { - return; - } - player->weaponowned[weaponType] = true; - if (weaponType == WP_SECOND) - { - P_GiveMana(player, MANA_1, 25); - } - else - { - P_GiveMana(player, MANA_2, 25); - } - player->pendingweapon = weaponType; - remove = false; - } - else - { // Deathmatch or single player game - if (weaponType == WP_SECOND) - { - gaveMana = P_GiveMana(player, MANA_1, 25); - } - else - { - gaveMana = P_GiveMana(player, MANA_2, 25); - } - if (player->weaponowned[weaponType]) - { - gaveWeapon = false; - } - else - { - gaveWeapon = true; - player->weaponowned[weaponType] = true; - if (weaponType > player->readyweapon) - { // Only switch to more powerful weapons - player->pendingweapon = weaponType; - } - } - if (!(gaveWeapon || gaveMana)) - { // Player didn't need the weapon or any mana - return; - } - } - - P_SetMessage(player, message, false); - if (weapon->special) - { - P_ExecuteLineSpecial(weapon->special, weapon->args, - NULL, 0, player->mo); - weapon->special = 0; - } - - if (remove) - { - if (deathmatch && !(weapon->flags2 & MF2_DROPPED)) - { - P_HideSpecialThing(weapon); - } - else - { - P_RemoveMobj(weapon); - } - } - - player->bonuscount += BONUSADD; - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, SFX_PICKUP_WEAPON); - SB_PaletteFlash(false); - } -} - -//-------------------------------------------------------------------------- -// -// FUNC P_GiveWeapon -// -// Returns true if the weapon or its mana was accepted. -// -//-------------------------------------------------------------------------- - -/* -boolean P_GiveWeapon(player_t *player, pclass_t class, weapontype_t weapon) -{ - boolean gaveMana; - boolean gaveWeapon; - - if(player->class != class) - { // player cannot use this weapon, take it anyway, and get mana - if(netgame && !deathmatch) - { // Can't pick up weapons for other classes in coop netplay - return false; - } - if(weapon == WP_SECOND) - { - return P_GiveMana(player, MANA_1, 25); - } - else - { - return P_GiveMana(player, MANA_2, 25); - } - } - if(netgame && !deathmatch) - { // Cooperative net-game - if(player->weaponowned[weapon]) - { - return(false); - } - player->bonuscount += BONUSADD; - player->weaponowned[weapon] = true; - if(weapon == WP_SECOND) - { - P_GiveMana(player, MANA_1, 25); - } - else - { - P_GiveMana(player, MANA_2, 25); - } - player->pendingweapon = weapon; - if(player == &players[consoleplayer]) - { - S_StartSound(NULL, SFX_PICKUP_WEAPON); - } - return(false); - } - if(weapon == WP_SECOND) - { - gaveMana = P_GiveMana(player, MANA_1, 25); - } - else - { - gaveMana = P_GiveMana(player, MANA_2, 25); - } - if(player->weaponowned[weapon]) - { - gaveWeapon = false; - } - else - { - gaveWeapon = true; - player->weaponowned[weapon] = true; - if(weapon > player->readyweapon) - { // Only switch to more powerful weapons - player->pendingweapon = weapon; - } - } - return(gaveWeapon || gaveMana); -} -*/ - -//=========================================================================== -// -// P_GiveWeaponPiece -// -//=========================================================================== - -/* -boolean P_GiveWeaponPiece(player_t *player, pclass_t class, int piece) -{ - P_GiveMana(player, MANA_1, 20); - P_GiveMana(player, MANA_2, 20); - if(player->class != class) - { - return true; - } - else if(player->pieces&piece) - { // player already has that weapon piece - return true; - } - player->pieces |= piece; - if(player->pieces == 7) - { // player has built the fourth weapon! - P_GiveWeapon(player, class, WP_FOURTH); - S_StartSound(player->mo, SFX_WEAPON_BUILD); - } - return true; -} -*/ - -//========================================================================== -// -// TryPickupWeaponPiece -// -//========================================================================== - -static void TryPickupWeaponPiece(player_t * player, pclass_t matchClass, - int pieceValue, mobj_t * pieceMobj) -{ - boolean remove; - boolean checkAssembled; - boolean gaveWeapon; - int gaveMana; - static const char *fourthWeaponText[] = { - TXT_WEAPON_F4, - TXT_WEAPON_C4, - TXT_WEAPON_M4 - }; - static const char *weaponPieceText[] = { - TXT_QUIETUS_PIECE, - TXT_WRAITHVERGE_PIECE, - TXT_BLOODSCOURGE_PIECE - }; - static int pieceValueTrans[] = { - 0, // 0: never - WPIECE1 | WPIECE2 | WPIECE3, // WPIECE1 (1) - WPIECE2 | WPIECE3, // WPIECE2 (2) - 0, // 3: never - WPIECE3 // WPIECE3 (4) - }; - - remove = true; - checkAssembled = true; - gaveWeapon = false; - if (player->class != matchClass) - { // Wrong class, but try to pick up for mana - if (netgame && !deathmatch) - { // Can't pick up wrong-class weapons in coop netplay - return; - } - checkAssembled = false; - gaveMana = P_GiveMana(player, MANA_1, 20) + - P_GiveMana(player, MANA_2, 20); - if (!gaveMana) - { // Didn't need the mana, so don't pick it up - return; - } - } - else if (netgame && !deathmatch) - { // Cooperative net-game - if (player->pieces & pieceValue) - { // Already has the piece - return; - } - pieceValue = pieceValueTrans[pieceValue]; - P_GiveMana(player, MANA_1, 20); - P_GiveMana(player, MANA_2, 20); - remove = false; - } - else - { // Deathmatch or single player game - gaveMana = P_GiveMana(player, MANA_1, 20) + - P_GiveMana(player, MANA_2, 20); - if (player->pieces & pieceValue) - { // Already has the piece, check if mana needed - if (!gaveMana) - { // Didn't need the mana, so don't pick it up - return; - } - checkAssembled = false; - } - } - - // Pick up the weapon piece - if (pieceMobj->special) - { - P_ExecuteLineSpecial(pieceMobj->special, pieceMobj->args, - NULL, 0, player->mo); - pieceMobj->special = 0; - } - if (remove) - { - if (deathmatch && !(pieceMobj->flags2 & MF2_DROPPED)) - { - P_HideSpecialThing(pieceMobj); - } - else - { - P_RemoveMobj(pieceMobj); - } - } - player->bonuscount += BONUSADD; - if (player == &players[consoleplayer]) - { - SB_PaletteFlash(false); - } - - // Check if fourth weapon assembled - if (checkAssembled) - { - player->pieces |= pieceValue; - if (player->pieces == (WPIECE1 | WPIECE2 | WPIECE3)) - { - gaveWeapon = true; - player->weaponowned[WP_FOURTH] = true; - player->pendingweapon = WP_FOURTH; - } - } - - if (gaveWeapon) - { - P_SetMessage(player, fourthWeaponText[matchClass], false); - // Play the build-sound full volume for all players - S_StartSound(NULL, SFX_WEAPON_BUILD); - } - else - { - P_SetMessage(player, weaponPieceText[matchClass], false); - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, SFX_PICKUP_WEAPON); - } - } -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GiveBody -// -// Returns false if the body isn't needed at all. -// -//--------------------------------------------------------------------------- - -boolean P_GiveBody(player_t * player, int num) -{ - int max; - - max = MAXHEALTH; - if (player->morphTics) - { - max = MAXMORPHHEALTH; - } - if (player->health >= max) - { - return (false); - } - player->health += num; - if (player->health > max) - { - player->health = max; - } - player->mo->health = player->health; - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GiveArmor -// -// Returns false if the armor is worse than the current armor. -// -//--------------------------------------------------------------------------- - -boolean P_GiveArmor(player_t * player, armortype_t armortype, int amount) -{ - int hits; - int totalArmor; - - if (amount == -1) - { - hits = ArmorIncrement[player->class][armortype]; - if (player->armorpoints[armortype] >= hits) - { - return false; - } - else - { - player->armorpoints[armortype] = hits; - } - } - else - { - hits = amount * 5 * FRACUNIT; - totalArmor = player->armorpoints[ARMOR_ARMOR] - + player->armorpoints[ARMOR_SHIELD] - + player->armorpoints[ARMOR_HELMET] - + player->armorpoints[ARMOR_AMULET] - + AutoArmorSave[player->class]; - if (totalArmor < ArmorMax[player->class] * 5 * FRACUNIT) - { - player->armorpoints[armortype] += hits; - } - else - { - return false; - } - } - return true; -} - -//--------------------------------------------------------------------------- -// -// PROC P_GiveKey -// -//--------------------------------------------------------------------------- - -int P_GiveKey(player_t * player, keytype_t key) -{ - if (player->keys & (1 << key)) - { - return false; - } - player->bonuscount += BONUSADD; - player->keys |= 1 << key; - return true; -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GivePower -// -// Returns true if power accepted. -// -//--------------------------------------------------------------------------- - -boolean P_GivePower(player_t * player, powertype_t power) -{ - if (power == pw_invulnerability) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = INVULNTICS; - player->mo->flags2 |= MF2_INVULNERABLE; - if (player->class == PCLASS_MAGE) - { - player->mo->flags2 |= MF2_REFLECTIVE; - } - return (true); - } - if (power == pw_flight) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = FLIGHTTICS; - player->mo->flags2 |= MF2_FLY; - player->mo->flags |= MF_NOGRAVITY; - if (player->mo->z <= player->mo->floorz) - { - player->flyheight = 10; // thrust the player in the air a bit - } - return (true); - } - if (power == pw_infrared) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = INFRATICS; - return (true); - } - if (power == pw_speed) - { - if (player->powers[power] > BLINKTHRESHOLD) - { // Already have it - return (false); - } - player->powers[power] = SPEEDTICS; - return (true); - } - if (power == pw_minotaur) - { - // Doesn't matter if already have power, renew ticker - player->powers[power] = MAULATORTICS; - return (true); - } -/* - if(power == pw_ironfeet) - { - player->powers[power] = IRONTICS; - return(true); - } - if(power == pw_strength) - { - P_GiveBody(player, 100); - player->powers[power] = 1; - return(true); - } -*/ - if (player->powers[power]) - { - return (false); // already got it - } - player->powers[power] = 1; - return (true); -} - -//========================================================================== -// -// TryPickupArtifact -// -//========================================================================== - -static void TryPickupArtifact(player_t * player, artitype_t artifactType, - mobj_t * artifact) -{ - static const char *artifactMessages[NUMARTIFACTS] = { - NULL, - TXT_ARTIINVULNERABILITY, - TXT_ARTIHEALTH, - TXT_ARTISUPERHEALTH, - TXT_ARTIHEALINGRADIUS, - TXT_ARTISUMMON, - TXT_ARTITORCH, - TXT_ARTIEGG, - TXT_ARTIFLY, - TXT_ARTIBLASTRADIUS, - TXT_ARTIPOISONBAG, - TXT_ARTITELEPORTOTHER, - TXT_ARTISPEED, - TXT_ARTIBOOSTMANA, - TXT_ARTIBOOSTARMOR, - TXT_ARTITELEPORT, - TXT_ARTIPUZZSKULL, - TXT_ARTIPUZZGEMBIG, - TXT_ARTIPUZZGEMRED, - TXT_ARTIPUZZGEMGREEN1, - TXT_ARTIPUZZGEMGREEN2, - TXT_ARTIPUZZGEMBLUE1, - TXT_ARTIPUZZGEMBLUE2, - TXT_ARTIPUZZBOOK1, - TXT_ARTIPUZZBOOK2, - TXT_ARTIPUZZSKULL2, - TXT_ARTIPUZZFWEAPON, - TXT_ARTIPUZZCWEAPON, - TXT_ARTIPUZZMWEAPON, - TXT_ARTIPUZZGEAR, // All gear pickups use the same text - TXT_ARTIPUZZGEAR, - TXT_ARTIPUZZGEAR, - TXT_ARTIPUZZGEAR - }; - - if (gamemode == shareware) - { - artifactMessages[arti_blastradius] = TXT_ARTITELEPORT; - artifactMessages[arti_teleport] = TXT_ARTIBLASTRADIUS; - } - - if (P_GiveArtifact(player, artifactType, artifact)) - { - if (artifact->special) - { - P_ExecuteLineSpecial(artifact->special, artifact->args, - NULL, 0, NULL); - artifact->special = 0; - } - player->bonuscount += BONUSADD; - if (artifactType < arti_firstpuzzitem) - { - SetDormantArtifact(artifact); - S_StartSound(artifact, SFX_PICKUP_ARTIFACT); - P_SetMessage(player, artifactMessages[artifactType], false); - } - else - { // Puzzle item - S_StartSound(NULL, SFX_PICKUP_ITEM); - P_SetMessage(player, artifactMessages[artifactType], true); - if (!netgame || deathmatch) - { // Remove puzzle items if not cooperative netplay - P_RemoveMobj(artifact); - } - } - } -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GiveArtifact -// -// Returns true if artifact accepted. -// -//--------------------------------------------------------------------------- - -boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo) -{ - int i; - int j; - boolean slidePointer; - - slidePointer = false; - i = 0; - while (player->inventory[i].type != arti && i < player->inventorySlotNum) - { - i++; - } - if (i == player->inventorySlotNum) - { - if (arti < arti_firstpuzzitem) - { - i = 0; - while (player->inventory[i].type < arti_firstpuzzitem - && i < player->inventorySlotNum) - { - i++; - } - if (i != player->inventorySlotNum) - { - for (j = player->inventorySlotNum; j > i; j--) - { - player->inventory[j].count = - player->inventory[j - 1].count; - player->inventory[j].type = player->inventory[j - 1].type; - slidePointer = true; - } - } - } - player->inventory[i].count = 1; - player->inventory[i].type = arti; - player->inventorySlotNum++; - } - else - { - if (arti >= arti_firstpuzzitem && netgame && !deathmatch) - { // Can't carry more than 1 puzzle item in coop netplay - return false; - } - if (player->inventory[i].count >= 25) - { // Player already has 25 of this item - return false; - } - player->inventory[i].count++; - } - if (!player->artifactCount) - { - player->readyArtifact = arti; - } - else if (player == &players[consoleplayer] && slidePointer - && i <= inv_ptr) - { - inv_ptr++; - curpos++; - if (curpos > 6) - { - curpos = 6; - } - } - player->artifactCount++; - return (true); -} - -//========================================================================== -// -// SetDormantArtifact -// -// Removes the MF_SPECIAL flag and initiates the artifact pickup -// animation. -// -//========================================================================== - -static void SetDormantArtifact(mobj_t * arti) -{ - arti->flags &= ~MF_SPECIAL; - if (deathmatch && !(arti->flags2 & MF2_DROPPED)) - { - if (arti->type == MT_ARTIINVULNERABILITY) - { - P_SetMobjState(arti, S_DORMANTARTI3_1); - } - else if (arti->type == MT_SUMMONMAULATOR || arti->type == MT_ARTIFLY) - { - P_SetMobjState(arti, S_DORMANTARTI2_1); - } - else - { - P_SetMobjState(arti, S_DORMANTARTI1_1); - } - } - else - { // Don't respawn - P_SetMobjState(arti, S_DEADARTI1); - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreArtifact -// -//--------------------------------------------------------------------------- - -void A_RestoreArtifact(mobj_t *arti, player_t *player, pspdef_t *psp) -{ - arti->flags |= MF_SPECIAL; - P_SetMobjState(arti, arti->info->spawnstate); - S_StartSound(arti, SFX_RESPAWN); -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialThing1 -// -// Make a special thing visible again. -// -//--------------------------------------------------------------------------- - -void A_RestoreSpecialThing1(mobj_t * thing, player_t *player, pspdef_t *psp) -{ - thing->flags2 &= ~MF2_DONTDRAW; - S_StartSound(thing, SFX_RESPAWN); -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialThing2 -// -//--------------------------------------------------------------------------- - -void A_RestoreSpecialThing2(mobj_t * thing, player_t *player, pspdef_t *psp) -{ - thing->flags |= MF_SPECIAL; - P_SetMobjState(thing, thing->info->spawnstate); -} - -//--------------------------------------------------------------------------- -// -// PROC P_TouchSpecialThing -// -//--------------------------------------------------------------------------- - -void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher) -{ - player_t *player; - fixed_t delta; - int sound; - boolean respawn; - - delta = special->z - toucher->z; - if (delta > toucher->height || delta < -32 * FRACUNIT) - { // Out of reach - return; - } - if (toucher->health <= 0) - { // Toucher is dead - return; - } - sound = SFX_PICKUP_ITEM; - player = toucher->player; - respawn = true; - switch (special->sprite) - { - // Items - case SPR_PTN1: // Item_HealingPotion - if (!P_GiveBody(player, 10)) - { - return; - } - P_SetMessage(player, TXT_ITEMHEALTH, false); - break; - case SPR_ARM1: - if (!P_GiveArmor(player, ARMOR_ARMOR, -1)) - { - return; - } - P_SetMessage(player, TXT_ARMOR1, false); - break; - case SPR_ARM2: - if (!P_GiveArmor(player, ARMOR_SHIELD, -1)) - { - return; - } - P_SetMessage(player, TXT_ARMOR2, false); - break; - case SPR_ARM3: - if (!P_GiveArmor(player, ARMOR_HELMET, -1)) - { - return; - } - P_SetMessage(player, TXT_ARMOR3, false); - break; - case SPR_ARM4: - if (!P_GiveArmor(player, ARMOR_AMULET, -1)) - { - return; - } - P_SetMessage(player, TXT_ARMOR4, false); - break; - - // Keys - case SPR_KEY1: - case SPR_KEY2: - case SPR_KEY3: - case SPR_KEY4: - case SPR_KEY5: - case SPR_KEY6: - case SPR_KEY7: - case SPR_KEY8: - case SPR_KEY9: - case SPR_KEYA: - case SPR_KEYB: - if (!P_GiveKey(player, special->sprite - SPR_KEY1)) - { - return; - } - P_SetMessage(player, TextKeyMessages[special->sprite - SPR_KEY1], - true); - sound = SFX_PICKUP_KEY; - - // Check and process the special now in case the key doesn't - // get removed for coop netplay - if (special->special) - { - P_ExecuteLineSpecial(special->special, special->args, - NULL, 0, toucher); - special->special = 0; - } - - if (!netgame) - { // Only remove keys in single player game - break; - } - player->bonuscount += BONUSADD; - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, sound); - SB_PaletteFlash(false); - } - return; - - // Artifacts - case SPR_PTN2: - TryPickupArtifact(player, arti_health, special); - return; - case SPR_SOAR: - TryPickupArtifact(player, arti_fly, special); - return; - case SPR_INVU: - TryPickupArtifact(player, arti_invulnerability, special); - return; - case SPR_SUMN: - TryPickupArtifact(player, arti_summon, special); - return; - case SPR_PORK: - TryPickupArtifact(player, arti_egg, special); - return; - case SPR_SPHL: - TryPickupArtifact(player, arti_superhealth, special); - return; - case SPR_HRAD: - TryPickupArtifact(player, arti_healingradius, special); - return; - case SPR_TRCH: - TryPickupArtifact(player, arti_torch, special); - return; - case SPR_ATLP: - TryPickupArtifact(player, arti_teleport, special); - return; - case SPR_TELO: - TryPickupArtifact(player, arti_teleportother, special); - return; - case SPR_PSBG: - TryPickupArtifact(player, arti_poisonbag, special); - return; - case SPR_SPED: - TryPickupArtifact(player, arti_speed, special); - return; - case SPR_BMAN: - TryPickupArtifact(player, arti_boostmana, special); - return; - case SPR_BRAC: - TryPickupArtifact(player, arti_boostarmor, special); - return; - case SPR_BLST: - TryPickupArtifact(player, arti_blastradius, special); - return; - - // Puzzle artifacts - case SPR_ASKU: - TryPickupArtifact(player, arti_puzzskull, special); - return; - case SPR_ABGM: - TryPickupArtifact(player, arti_puzzgembig, special); - return; - case SPR_AGMR: - TryPickupArtifact(player, arti_puzzgemred, special); - return; - case SPR_AGMG: - TryPickupArtifact(player, arti_puzzgemgreen1, special); - return; - case SPR_AGG2: - TryPickupArtifact(player, arti_puzzgemgreen2, special); - return; - case SPR_AGMB: - TryPickupArtifact(player, arti_puzzgemblue1, special); - return; - case SPR_AGB2: - TryPickupArtifact(player, arti_puzzgemblue2, special); - return; - case SPR_ABK1: - TryPickupArtifact(player, arti_puzzbook1, special); - return; - case SPR_ABK2: - TryPickupArtifact(player, arti_puzzbook2, special); - return; - case SPR_ASK2: - TryPickupArtifact(player, arti_puzzskull2, special); - return; - case SPR_AFWP: - TryPickupArtifact(player, arti_puzzfweapon, special); - return; - case SPR_ACWP: - TryPickupArtifact(player, arti_puzzcweapon, special); - return; - case SPR_AMWP: - TryPickupArtifact(player, arti_puzzmweapon, special); - return; - case SPR_AGER: - TryPickupArtifact(player, arti_puzzgear1, special); - return; - case SPR_AGR2: - TryPickupArtifact(player, arti_puzzgear2, special); - return; - case SPR_AGR3: - TryPickupArtifact(player, arti_puzzgear3, special); - return; - case SPR_AGR4: - TryPickupArtifact(player, arti_puzzgear4, special); - return; - - // Mana - case SPR_MAN1: - if (!P_GiveMana(player, MANA_1, 15)) - { - return; - } - P_SetMessage(player, TXT_MANA_1, false); - break; - case SPR_MAN2: - if (!P_GiveMana(player, MANA_2, 15)) - { - return; - } - P_SetMessage(player, TXT_MANA_2, false); - break; - case SPR_MAN3: // Double Mana Dodecahedron - if (!P_GiveMana(player, MANA_1, 20)) - { - if (!P_GiveMana(player, MANA_2, 20)) - { - return; - } - } - else - { - P_GiveMana(player, MANA_2, 20); - } - P_SetMessage(player, TXT_MANA_BOTH, false); - break; - - // 2nd and 3rd Mage Weapons - case SPR_WMCS: // Frost Shards - TryPickupWeapon(player, PCLASS_MAGE, WP_SECOND, - special, TXT_WEAPON_M2); - return; - case SPR_WMLG: // Arc of Death - TryPickupWeapon(player, PCLASS_MAGE, WP_THIRD, - special, TXT_WEAPON_M3); - return; - - // 2nd and 3rd Fighter Weapons - case SPR_WFAX: // Timon's Axe - TryPickupWeapon(player, PCLASS_FIGHTER, WP_SECOND, - special, TXT_WEAPON_F2); - return; - case SPR_WFHM: // Hammer of Retribution - TryPickupWeapon(player, PCLASS_FIGHTER, WP_THIRD, - special, TXT_WEAPON_F3); - return; - - // 2nd and 3rd Cleric Weapons - case SPR_WCSS: // Serpent Staff - TryPickupWeapon(player, PCLASS_CLERIC, WP_SECOND, - special, TXT_WEAPON_C2); - return; - case SPR_WCFM: // Firestorm - TryPickupWeapon(player, PCLASS_CLERIC, WP_THIRD, - special, TXT_WEAPON_C3); - return; - - // Fourth Weapon Pieces - case SPR_WFR1: - TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE1, special); - return; - case SPR_WFR2: - TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE2, special); - return; - case SPR_WFR3: - TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE3, special); - return; - case SPR_WCH1: - TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE1, special); - return; - case SPR_WCH2: - TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE2, special); - return; - case SPR_WCH3: - TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE3, special); - return; - case SPR_WMS1: - TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE1, special); - return; - case SPR_WMS2: - TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE2, special); - return; - case SPR_WMS3: - TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE3, special); - return; - - default: - I_Error("P_SpecialThing: Unknown gettable thing"); - } - if (special->special) - { - P_ExecuteLineSpecial(special->special, special->args, NULL, - 0, toucher); - special->special = 0; - } - if (deathmatch && respawn && !(special->flags2 & MF2_DROPPED)) - { - P_HideSpecialThing(special); - } - else - { - P_RemoveMobj(special); - } - player->bonuscount += BONUSADD; - if (player == &players[consoleplayer]) - { - S_StartSound(NULL, sound); - SB_PaletteFlash(false); - } -} - -// Search thinker list for minotaur -mobj_t *ActiveMinotaur(player_t * master) -{ - mobj_t *mo; - player_t *plr; - thinker_t *think; - unsigned int *starttime; - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - continue; - mo = (mobj_t *) think; - if (mo->type != MT_MINOTAUR) - continue; - if (mo->health <= 0) - continue; - if (!(mo->flags & MF_COUNTKILL)) - continue; // for morphed minotaurs - if (mo->flags & MF_CORPSE) - continue; - starttime = (unsigned int *) mo->args; - if ((leveltime - *starttime) >= MAULATORTICS) - continue; - plr = mo->special1.m->player; - if (plr == master) - return (mo); - } - return (NULL); -} - - -//--------------------------------------------------------------------------- -// -// PROC P_KillMobj -// -//--------------------------------------------------------------------------- - -void P_KillMobj(mobj_t * source, mobj_t * target) -{ - byte dummyArgs[3] = {0, 0, 0}; - mobj_t *master; - - target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_NOGRAVITY); - target->flags |= MF_CORPSE | MF_DROPOFF; - target->flags2 &= ~MF2_PASSMOBJ; - target->height >>= 2; - if ((target->flags & MF_COUNTKILL || target->type == MT_ZBELL) - && target->special) - { // Initiate monster death actions - if (target->type == MT_SORCBOSS) - { - P_StartACS(target->special, 0, dummyArgs, target, NULL, 0); - } - else - { - P_ExecuteLineSpecial(target->special, target->args, - NULL, 0, target); - } - } - if (source && source->player) - { // Check for frag changes - if (target->player) - { - if (target == source) - { // Self-frag - target->player->frags[target->player - players]--; - if (cmdfrag && netgame - && source->player == &players[consoleplayer]) - { // Send out a frag count packet - NET_SendFrags(source->player); - } - } - else - { - source->player->frags[target->player - players]++; - if (cmdfrag && netgame - && source->player == &players[consoleplayer]) - { // Send out a frag count packet - NET_SendFrags(source->player); - } - } - } - } - if (target->player) - { // Player death - if (!source) - { // Self-frag - target->player->frags[target->player - players]--; - if (cmdfrag && netgame - && target->player == &players[consoleplayer]) - { // Send out a frag count packet - NET_SendFrags(target->player); - } - } - target->flags &= ~MF_SOLID; - target->flags2 &= ~MF2_FLY; - target->player->powers[pw_flight] = 0; - target->player->playerstate = PST_DEAD; - P_DropWeapon(target->player); - if (target->flags2 & MF2_FIREDAMAGE) - { // Player flame death - switch (target->player->class) - { - case PCLASS_FIGHTER: - S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH); - P_SetMobjState(target, S_PLAY_F_FDTH1); - return; - case PCLASS_CLERIC: - S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH); - P_SetMobjState(target, S_PLAY_C_FDTH1); - return; - case PCLASS_MAGE: - S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH); - P_SetMobjState(target, S_PLAY_M_FDTH1); - return; - default: - break; - } - } - if (target->flags2 & MF2_ICEDAMAGE) - { // Player ice death - target->flags &= ~(7 << MF_TRANSSHIFT); //no translation - target->flags |= MF_ICECORPSE; - switch (target->player->class) - { - case PCLASS_FIGHTER: - P_SetMobjState(target, S_FPLAY_ICE); - return; - case PCLASS_CLERIC: - P_SetMobjState(target, S_CPLAY_ICE); - return; - case PCLASS_MAGE: - P_SetMobjState(target, S_MPLAY_ICE); - return; - case PCLASS_PIG: - P_SetMobjState(target, S_PIG_ICE); - return; - default: - break; - } - } - } - if (target->flags2 & MF2_FIREDAMAGE) - { - if (target->type == MT_FIGHTER_BOSS - || target->type == MT_CLERIC_BOSS || target->type == MT_MAGE_BOSS) - { - switch (target->type) - { - case MT_FIGHTER_BOSS: - S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH); - P_SetMobjState(target, S_PLAY_F_FDTH1); - return; - case MT_CLERIC_BOSS: - S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH); - P_SetMobjState(target, S_PLAY_C_FDTH1); - return; - case MT_MAGE_BOSS: - S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH); - P_SetMobjState(target, S_PLAY_M_FDTH1); - return; - default: - break; - } - } - else if (target->type == MT_TREEDESTRUCTIBLE) - { - P_SetMobjState(target, S_ZTREEDES_X1); - target->height = 24 * FRACUNIT; - S_StartSound(target, SFX_TREE_EXPLODE); - return; - } - } - if (target->flags2 & MF2_ICEDAMAGE) - { - target->flags |= MF_ICECORPSE; - switch (target->type) - { - case MT_BISHOP: - P_SetMobjState(target, S_BISHOP_ICE); - return; - case MT_CENTAUR: - case MT_CENTAURLEADER: - P_SetMobjState(target, S_CENTAUR_ICE); - return; - case MT_DEMON: - case MT_DEMON2: - P_SetMobjState(target, S_DEMON_ICE); - return; - case MT_SERPENT: - case MT_SERPENTLEADER: - P_SetMobjState(target, S_SERPENT_ICE); - return; - case MT_WRAITH: - case MT_WRAITHB: - P_SetMobjState(target, S_WRAITH_ICE); - return; - case MT_ETTIN: - P_SetMobjState(target, S_ETTIN_ICE1); - return; - case MT_FIREDEMON: - P_SetMobjState(target, S_FIRED_ICE1); - return; - case MT_FIGHTER_BOSS: - P_SetMobjState(target, S_FIGHTER_ICE); - return; - case MT_CLERIC_BOSS: - P_SetMobjState(target, S_CLERIC_ICE); - return; - case MT_MAGE_BOSS: - P_SetMobjState(target, S_MAGE_ICE); - return; - case MT_PIG: - P_SetMobjState(target, S_PIG_ICE); - return; - default: - target->flags &= ~MF_ICECORPSE; - break; - } - } - - if (target->type == MT_MINOTAUR) - { - master = target->special1.m; - if (master->health > 0) - { - if (!ActiveMinotaur(master->player)) - { - master->player->powers[pw_minotaur] = 0; - } - } - } - else if (target->type == MT_TREEDESTRUCTIBLE) - { - target->height = 24 * FRACUNIT; - } - if (target->health < -(target->info->spawnhealth >> 1) - && target->info->xdeathstate) - { // Extreme death - P_SetMobjState(target, target->info->xdeathstate); - } - else - { // Normal death - if ((target->type == MT_FIREDEMON) && - (target->z <= target->floorz + 2 * FRACUNIT) && - (target->info->xdeathstate)) - { - // This is to fix the imps' staying in fall state - P_SetMobjState(target, target->info->xdeathstate); - } - else - { - P_SetMobjState(target, target->info->deathstate); - } - } - target->tics -= P_Random() & 3; -// I_StartSound(&actor->r, actor->info->deathsound); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_MinotaurSlam -// -//--------------------------------------------------------------------------- - -void P_MinotaurSlam(mobj_t * source, mobj_t * target) -{ - angle_t angle; - fixed_t thrust; - - angle = R_PointToAngle2(source->x, source->y, target->x, target->y); - angle >>= ANGLETOFINESHIFT; - thrust = 16 * FRACUNIT + (P_Random() << 10); - target->momx += FixedMul(thrust, finecosine[angle]); - target->momy += FixedMul(thrust, finesine[angle]); - P_DamageMobj(target, NULL, source, HITDICE(4)); - if (target->player) - { - target->reactiontime = 14 + (P_Random() & 7); - } - source->args[0] = 0; // Stop charging -} - - -//--------------------------------------------------------------------------- -// -// FUNC P_MorphPlayer -// -// Returns true if the player gets turned into a pig -// -//--------------------------------------------------------------------------- - -boolean P_MorphPlayer(player_t * player) -{ - mobj_t *pmo; - mobj_t *fog; - mobj_t *beastMo; - fixed_t x; - fixed_t y; - fixed_t z; - angle_t angle; - int oldFlags2; - - if (player->powers[pw_invulnerability]) - { // Immune when invulnerable - return (false); - } - if (player->morphTics) - { // Player is already a beast - return false; - } - pmo = player->mo; - x = pmo->x; - y = pmo->y; - z = pmo->z; - angle = pmo->angle; - oldFlags2 = pmo->flags2; - P_SetMobjState(pmo, S_FREETARGMOBJ); - fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, SFX_TELEPORT); - beastMo = P_SpawnMobj(x, y, z, MT_PIGPLAYER); - beastMo->special1.i = player->readyweapon; - beastMo->angle = angle; - beastMo->player = player; - player->health = beastMo->health = MAXMORPHHEALTH; - player->mo = beastMo; - memset(&player->armorpoints[0], 0, NUMARMOR * sizeof(int)); - player->class = PCLASS_PIG; - if (oldFlags2 & MF2_FLY) - { - beastMo->flags2 |= MF2_FLY; - } - player->morphTics = MORPHTICS; - P_ActivateMorphWeapon(player); - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_MorphMonster -// -//--------------------------------------------------------------------------- - -boolean P_MorphMonster(mobj_t * actor) -{ - mobj_t *master, *monster, *fog; - mobjtype_t moType; - fixed_t x; - fixed_t y; - fixed_t z; - mobj_t oldMonster; - - if (actor->player) - return (false); - if (!(actor->flags & MF_COUNTKILL)) - return false; - if (actor->flags2 & MF2_BOSS) - return false; - moType = actor->type; - switch (moType) - { - case MT_PIG: - return (false); - case MT_FIGHTER_BOSS: - case MT_CLERIC_BOSS: - case MT_MAGE_BOSS: - return (false); - default: - break; - } - - oldMonster = *actor; - x = oldMonster.x; - y = oldMonster.y; - z = oldMonster.z; - P_RemoveMobjFromTIDList(actor); - P_SetMobjState(actor, S_FREETARGMOBJ); - fog = P_SpawnMobj(x, y, z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, SFX_TELEPORT); - monster = P_SpawnMobj(x, y, z, MT_PIG); - monster->special2.i = moType; - monster->special1.i = MORPHTICS + P_Random(); - monster->flags |= (oldMonster.flags & MF_SHADOW); - monster->target = oldMonster.target; - monster->angle = oldMonster.angle; - monster->tid = oldMonster.tid; - monster->special = oldMonster.special; - P_InsertMobjIntoTIDList(monster, oldMonster.tid); - memcpy(monster->args, oldMonster.args, 5); - - // check for turning off minotaur power for active icon - if (moType == MT_MINOTAUR) - { - master = oldMonster.special1.m; - if (master->health > 0) - { - if (!ActiveMinotaur(master->player)) - { - master->player->powers[pw_minotaur] = 0; - } - } - } - return (true); -} - -//--------------------------------------------------------------------------- -// -// PROC P_AutoUseHealth -// -//--------------------------------------------------------------------------- - -void P_AutoUseHealth(player_t * player, int saveHealth) -{ - int i; - int count; - int normalCount; - int normalSlot = 0; - int superCount; - int superSlot = 0; - - normalCount = superCount = 0; - for (i = 0; i < player->inventorySlotNum; i++) - { - if (player->inventory[i].type == arti_health) - { - normalSlot = i; - normalCount = player->inventory[i].count; - } - else if (player->inventory[i].type == arti_superhealth) - { - superSlot = i; - superCount = player->inventory[i].count; - } - } - if ((gameskill == sk_baby) && (normalCount * 25 >= saveHealth)) - { // Use quartz flasks - count = (saveHealth + 24) / 25; - for (i = 0; i < count; i++) - { - player->health += 25; - P_PlayerRemoveArtifact(player, normalSlot); - } - } - else if (superCount * 100 >= saveHealth) - { // Use mystic urns - count = (saveHealth + 99) / 100; - for (i = 0; i < count; i++) - { - player->health += 100; - P_PlayerRemoveArtifact(player, superSlot); - } - } - else if ((gameskill == sk_baby) - && (superCount * 100 + normalCount * 25 >= saveHealth)) - { // Use mystic urns and quartz flasks - count = (saveHealth + 24) / 25; - saveHealth -= count * 25; - for (i = 0; i < count; i++) - { - player->health += 25; - P_PlayerRemoveArtifact(player, normalSlot); - } - count = (saveHealth + 99) / 100; - for (i = 0; i < count; i++) - { - player->health += 100; - P_PlayerRemoveArtifact(player, normalSlot); - } - } - player->mo->health = player->health; -} - -/* -================= -= -= P_DamageMobj -= -= Damages both enemies and players -= inflictor is the thing that caused the damage -= creature or missile, can be NULL (slime, etc) -= source is the thing to target after taking damage -= creature or NULL -= Source and inflictor are the same for melee attacks -= source can be null for barrel explosions and other environmental stuff -================== -*/ - -void P_DamageMobj - (mobj_t * target, mobj_t * inflictor, mobj_t * source, int damage) -{ - unsigned ang; - int saved; - fixed_t savedPercent; - player_t *player; - mobj_t *master; - fixed_t thrust; - int temp; - int i; - - if (!(target->flags & MF_SHOOTABLE)) - { - // Shouldn't happen - return; - } - if (target->health <= 0) - { - if (inflictor && inflictor->flags2 & MF2_ICEDAMAGE) - { - return; - } - else if (target->flags & MF_ICECORPSE) // frozen - { - target->tics = 1; - target->momx = target->momy = 0; - } - return; - } - if ((target->flags2 & MF2_INVULNERABLE) && damage < 10000) - { // mobj is invulnerable - if (target->player) - return; // for player, no exceptions - if (inflictor) - { - switch (inflictor->type) - { - // These inflictors aren't foiled by invulnerability - case MT_HOLY_FX: - case MT_POISONCLOUD: - case MT_FIREBOMB: - break; - default: - return; - } - } - else - { - return; - } - } - if (target->player) - { - if (damage < 1000 && ((target->player->cheats & CF_GODMODE) - || target->player->powers[pw_invulnerability])) - { - return; - } - } - if (target->flags & MF_SKULLFLY) - { - target->momx = target->momy = target->momz = 0; - } - if (target->flags2 & MF2_DORMANT) - { - // Invulnerable, and won't wake up - return; - } - player = target->player; - if (player && gameskill == sk_baby) - { - // Take half damage in trainer mode - damage >>= 1; - } - // Special damage types - if (inflictor) - { - switch (inflictor->type) - { - case MT_EGGFX: - if (player) - { - P_MorphPlayer(player); - } - else - { - P_MorphMonster(target); - } - return; // Always return - case MT_TELOTHER_FX1: - case MT_TELOTHER_FX2: - case MT_TELOTHER_FX3: - case MT_TELOTHER_FX4: - case MT_TELOTHER_FX5: - if ((target->flags & MF_COUNTKILL) && - (target->type != MT_SERPENT) && - (target->type != MT_SERPENTLEADER) && - (!(target->flags2 & MF2_BOSS))) - { - P_TeleportOther(target); - } - return; - case MT_MINOTAUR: - if (inflictor->flags & MF_SKULLFLY) - { // Slam only when in charge mode - P_MinotaurSlam(inflictor, target); - return; - } - break; - case MT_BISH_FX: - // Bishops are just too nasty - damage >>= 1; - break; - case MT_SHARDFX1: - switch (inflictor->special2.i) - { - case 3: - damage <<= 3; - break; - case 2: - damage <<= 2; - break; - case 1: - damage <<= 1; - break; - default: - break; - } - break; - case MT_CSTAFF_MISSILE: - // Cleric Serpent Staff does poison damage - if (target->player) - { - P_PoisonPlayer(target->player, source, 20); - damage >>= 1; - } - break; - case MT_ICEGUY_FX2: - damage >>= 1; - break; - case MT_POISONDART: - if (target->player) - { - P_PoisonPlayer(target->player, source, 20); - damage >>= 1; - } - break; - case MT_POISONCLOUD: - if (target->player) - { - if (target->player->poisoncount < 4) - { - P_PoisonDamage(target->player, source, 15 + (P_Random() & 15), false); // Don't play painsound - P_PoisonPlayer(target->player, source, 50); - S_StartSound(target, SFX_PLAYER_POISONCOUGH); - } - return; - } - else if (!(target->flags & MF_COUNTKILL)) - { // only damage monsters/players with the poison cloud - return; - } - break; - case MT_FSWORD_MISSILE: - if (target->player) - { - damage -= damage >> 2; - } - break; - default: - break; - } - } - // Push the target unless source is using the gauntlets - if (inflictor && (!source || !source->player) - && !(inflictor->flags2 & MF2_NODMGTHRUST)) - { - ang = R_PointToAngle2(inflictor->x, inflictor->y, - target->x, target->y); - //thrust = damage*(FRACUNIT>>3)*100/target->info->mass; - thrust = damage * (FRACUNIT >> 3) * 150 / target->info->mass; - // make fall forwards sometimes - if ((damage < 40) && (damage > target->health) - && (target->z - inflictor->z > 64 * FRACUNIT) && (P_Random() & 1)) - { - ang += ANG180; - thrust *= 4; - } - ang >>= ANGLETOFINESHIFT; - target->momx += FixedMul(thrust, finecosine[ang]); - target->momy += FixedMul(thrust, finesine[ang]); - } - - // - // player specific - // - if (player) - { - savedPercent = AutoArmorSave[player->class] - + player->armorpoints[ARMOR_ARMOR] + - player->armorpoints[ARMOR_SHIELD] + - player->armorpoints[ARMOR_HELMET] + - player->armorpoints[ARMOR_AMULET]; - if (savedPercent) - { // armor absorbed some damage - if (savedPercent > 100 * FRACUNIT) - { - savedPercent = 100 * FRACUNIT; - } - for (i = 0; i < NUMARMOR; i++) - { - if (player->armorpoints[i]) - { - player->armorpoints[i] -= - FixedDiv(FixedMul(damage << FRACBITS, - ArmorIncrement[player->class][i]), - 300 * FRACUNIT); - if (player->armorpoints[i] < 2 * FRACUNIT) - { - player->armorpoints[i] = 0; - } - } - } - saved = FixedDiv(FixedMul(damage << FRACBITS, savedPercent), - 100 * FRACUNIT); - if (saved > savedPercent * 2) - { - saved = savedPercent * 2; - } - damage -= saved >> FRACBITS; - } - if (damage >= player->health - && ((gameskill == sk_baby) || deathmatch) && !player->morphTics) - { // Try to use some inventory health - P_AutoUseHealth(player, damage - player->health + 1); - } - player->health -= damage; // mirror mobj health here for Dave - if (player->health < 0) - { - player->health = 0; - } - player->attacker = source; - player->damagecount += damage; // add damage after armor / invuln - if (player->damagecount > 100) - { - player->damagecount = 100; // teleport stomp does 10k points... - } - temp = damage < 100 ? damage : 100; - if (player == &players[consoleplayer]) - { - I_Tactile(40, 10, 40 + temp * 2); - SB_PaletteFlash(false); - } - } - - // - // do the damage - // - target->health -= damage; - if (target->health <= 0) - { // Death - if (inflictor) - { // check for special fire damage or ice damage deaths - if (inflictor->flags2 & MF2_FIREDAMAGE) - { - if (player && !player->morphTics) - { // Check for flame death - if (target->health > -50 && damage > 25) - { - target->flags2 |= MF2_FIREDAMAGE; - } - } - else - { - target->flags2 |= MF2_FIREDAMAGE; - } - } - else if (inflictor->flags2 & MF2_ICEDAMAGE) - { - target->flags2 |= MF2_ICEDAMAGE; - } - } - if (source && (source->type == MT_MINOTAUR)) - { // Minotaur's kills go to his master - master = source->special1.m; - // Make sure still alive and not a pointer to fighter head - if (master->player && (master->player->mo == master)) - { - source = master; - } - } - if (source && (source->player) && - (source->player->readyweapon == WP_FOURTH)) - { - // Always extreme death from fourth weapon - target->health = -5000; - } - P_KillMobj(source, target); - return; - } - if ((P_Random() < target->info->painchance) - && !(target->flags & MF_SKULLFLY)) - { - if (inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR - && inflictor->type <= MT_LIGHTNING_ZAP)) - { - if (P_Random() < 96) - { - target->flags |= MF_JUSTHIT; // fight back! - P_SetMobjState(target, target->info->painstate); - } - else - { // "electrocute" the target - target->frame |= FF_FULLBRIGHT; - if (target->flags & MF_COUNTKILL && P_Random() < 128 - && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT)) - { - if ((target->type == MT_CENTAUR) || - (target->type == MT_CENTAURLEADER) || - (target->type == MT_ETTIN)) - { - S_StartSound(target, SFX_PUPPYBEAT); - } - } - } - } - else - { - target->flags |= MF_JUSTHIT; // fight back! - P_SetMobjState(target, target->info->painstate); - if (inflictor && inflictor->type == MT_POISONCLOUD) - { - if (target->flags & MF_COUNTKILL && P_Random() < 128 - && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT)) - { - if ((target->type == MT_CENTAUR) || - (target->type == MT_CENTAURLEADER) || - (target->type == MT_ETTIN)) - { - S_StartSound(target, SFX_PUPPYBEAT); - } - } - } - } - } - target->reactiontime = 0; // we're awake now... - if (!target->threshold && source && !(source->flags2 & MF2_BOSS) - && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR)) - { - // Target actor is not intent on another actor, - // so make him chase after source - if ((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER) - || (target->type == MT_CENTAURLEADER - && source->type == MT_CENTAUR)) - { - return; - } - target->target = source; - target->threshold = BASETHRESHOLD; - if (target->state == &states[target->info->spawnstate] - && target->info->seestate != S_NULL) - { - P_SetMobjState(target, target->info->seestate); - } - } -} - -//========================================================================== -// -// P_FallingDamage -// -//========================================================================== - -void P_FallingDamage(player_t * player) -{ - int damage; - int mom; - int dist; - - mom = abs(player->mo->momz); - dist = FixedMul(mom, 16 * FRACUNIT / 23); - - if (mom >= 63 * FRACUNIT) - { // automatic death - P_DamageMobj(player->mo, NULL, NULL, 10000); - return; - } - damage = ((FixedMul(dist, dist) / 10) >> FRACBITS) - 24; - if (player->mo->momz > -39 * FRACUNIT && damage > player->mo->health - && player->mo->health != 1) - { // No-death threshold - damage = player->mo->health - 1; - } - S_StartSound(player->mo, SFX_PLAYER_LAND); - P_DamageMobj(player->mo, NULL, NULL, damage); -} - -//========================================================================== -// -// P_PoisonPlayer - Sets up all data concerning poisoning -// -//========================================================================== - -void P_PoisonPlayer(player_t * player, mobj_t * poisoner, int poison) -{ - if ((player->cheats & CF_GODMODE) || player->powers[pw_invulnerability]) - { - return; - } - player->poisoncount += poison; - player->poisoner = poisoner; - if (player->poisoncount > 100) - { - player->poisoncount = 100; - } -} - -//========================================================================== -// -// P_PoisonDamage - Similar to P_DamageMobj -// -//========================================================================== - -void P_PoisonDamage(player_t * player, mobj_t * source, int damage, - boolean playPainSound) -{ - mobj_t *target; - mobj_t *inflictor; - - target = player->mo; - inflictor = source; - if (target->health <= 0) - { - return; - } - if (target->flags2 & MF2_INVULNERABLE && damage < 10000) - { // mobj is invulnerable - return; - } - if (gameskill == sk_baby) - { - // Take half damage in trainer mode - damage >>= 1; - } - if (damage < 1000 && ((player->cheats & CF_GODMODE) - || player->powers[pw_invulnerability])) - { - return; - } - if (damage >= player->health - && ((gameskill == sk_baby) || deathmatch) && !player->morphTics) - { // Try to use some inventory health - P_AutoUseHealth(player, damage - player->health + 1); - } - player->health -= damage; // mirror mobj health here for Dave - if (player->health < 0) - { - player->health = 0; - } - player->attacker = source; - - // - // do the damage - // - target->health -= damage; - if (target->health <= 0) - { // Death - target->special1.i = damage; - if (inflictor && !player->morphTics) - { // Check for flame death - if ((inflictor->flags2 & MF2_FIREDAMAGE) - && (target->health > -50) && (damage > 25)) - { - target->flags2 |= MF2_FIREDAMAGE; - } - if (inflictor->flags2 & MF2_ICEDAMAGE) - { - target->flags2 |= MF2_ICEDAMAGE; - } - } - P_KillMobj(source, target); - return; - } - if (!(leveltime & 63) && playPainSound) - { - P_SetMobjState(target, target->info->painstate); - } -/* - if((P_Random() < target->info->painchance) - && !(target->flags&MF_SKULLFLY)) - { - target->flags |= MF_JUSTHIT; // fight back! - P_SetMobjState(target, target->info->painstate); - } -*/ -} diff --git a/games/NXDoom/src/hexen/p_lights.c b/games/NXDoom/src/hexen/p_lights.c deleted file mode 100644 index aae27212f6e..00000000000 --- a/games/NXDoom/src/hexen/p_lights.c +++ /dev/null @@ -1,369 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "m_random.h" -#include "p_local.h" - -//============================================================================ -// -// T_Light -// -//============================================================================ - -void T_Light(thinker_t *thinker) -{ - light_t *light = (light_t *) thinker; - if (light->count) - { - light->count--; - return; - } - switch (light->type) - { - case LITE_FADE: - light->sector->lightlevel = - ((light->sector->lightlevel << FRACBITS) + - light->value2) >> FRACBITS; - if (light->tics2 == 1) - { - if (light->sector->lightlevel >= light->value1) - { - light->sector->lightlevel = light->value1; - P_RemoveThinker(&light->thinker); - } - } - else if (light->sector->lightlevel <= light->value1) - { - light->sector->lightlevel = light->value1; - P_RemoveThinker(&light->thinker); - } - break; - case LITE_GLOW: - light->sector->lightlevel = - ((light->sector->lightlevel << FRACBITS) + - light->tics1) >> FRACBITS; - if (light->tics2 == 1) - { - if (light->sector->lightlevel >= light->value1) - { - light->sector->lightlevel = light->value1; - light->tics1 = -light->tics1; - light->tics2 = -1; // reverse direction - } - } - else if (light->sector->lightlevel <= light->value2) - { - light->sector->lightlevel = light->value2; - light->tics1 = -light->tics1; - light->tics2 = 1; // reverse direction - } - break; - case LITE_FLICKER: - if (light->sector->lightlevel == light->value1) - { - light->sector->lightlevel = light->value2; - light->count = (P_Random() & 7) + 1; - } - else - { - light->sector->lightlevel = light->value1; - light->count = (P_Random() & 31) + 1; - } - break; - case LITE_STROBE: - if (light->sector->lightlevel == light->value1) - { - light->sector->lightlevel = light->value2; - light->count = light->tics2; - } - else - { - light->sector->lightlevel = light->value1; - light->count = light->tics1; - } - break; - default: - break; - } -} - -//============================================================================ -// -// EV_SpawnLight -// -//============================================================================ - -boolean EV_SpawnLight(line_t * line, byte * arg, lighttype_t type) -{ - light_t *light; - sector_t *sec; - int secNum; - int arg1, arg2, arg3, arg4; - boolean think; - boolean rtn; - - /* - Original code; redundant considering that a byte value is always - in the range 0-255: - - arg1 = arg[1] > 255 ? 255 : arg[1]; - arg1 = arg1 < 0 ? 0 : arg1; - arg2 = arg[2] > 255 ? 255 : arg[2]; - arg2 = arg2 < 0 ? 0 : arg2; - arg3 = arg[3] > 255 ? 255 : arg[3]; - arg3 = arg3 < 0 ? 0 : arg3; - arg4 = arg[4] > 255 ? 255 : arg[4]; - arg4 = arg4 < 0 ? 0 : arg4; - */ - - arg1 = arg[1]; - arg2 = arg[2]; - arg3 = arg[3]; - arg4 = arg[4]; - - secNum = -1; - rtn = false; - while ((secNum = P_FindSectorFromTag(arg[0], secNum)) >= 0) - { - think = false; - sec = §ors[secNum]; - - light = (light_t *) Z_Malloc(sizeof(light_t), PU_LEVSPEC, 0); - light->type = type; - light->sector = sec; - light->count = 0; - rtn = true; - switch (type) - { - case LITE_RAISEBYVALUE: - sec->lightlevel += arg1; - if (sec->lightlevel > 255) - { - sec->lightlevel = 255; - } - break; - case LITE_LOWERBYVALUE: - sec->lightlevel -= arg1; - if (sec->lightlevel < 0) - { - sec->lightlevel = 0; - } - break; - case LITE_CHANGETOVALUE: - sec->lightlevel = arg1; - if (sec->lightlevel < 0) - { - sec->lightlevel = 0; - } - else if (sec->lightlevel > 255) - { - sec->lightlevel = 255; - } - break; - case LITE_FADE: - think = true; - light->value1 = arg1; // destination lightlevel - light->value2 = FixedDiv((arg1 - sec->lightlevel) << FRACBITS, arg2 << FRACBITS); // delta lightlevel - if (sec->lightlevel <= arg1) - { - light->tics2 = 1; // get brighter - } - else - { - light->tics2 = -1; - } - break; - case LITE_GLOW: - think = true; - light->value1 = arg1; // upper lightlevel - light->value2 = arg2; // lower lightlevel - light->tics1 = FixedDiv((arg1 - sec->lightlevel) << FRACBITS, arg3 << FRACBITS); // lightlevel delta - if (sec->lightlevel <= arg1) - { - light->tics2 = 1; // get brighter - } - else - { - light->tics2 = -1; - } - break; - case LITE_FLICKER: - think = true; - light->value1 = arg1; // upper lightlevel - light->value2 = arg2; // lower lightlevel - sec->lightlevel = light->value1; - light->count = (P_Random() & 64) + 1; - break; - case LITE_STROBE: - think = true; - light->value1 = arg1; // upper lightlevel - light->value2 = arg2; // lower lightlevel - light->tics1 = arg3; // upper tics - light->tics2 = arg4; // lower tics - light->count = arg3; - sec->lightlevel = light->value1; - break; - default: - rtn = false; - break; - } - if (think) - { - P_AddThinker(&light->thinker); - light->thinker.function = T_Light; - } - else - { - Z_Free(light); - } - } - return rtn; -} - -//============================================================================ -// -// T_Phase -// -//============================================================================ - -int PhaseTable[64] = { - 128, 112, 96, 80, 64, 48, 32, 32, - 16, 16, 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 16, 16, 16, - 32, 32, 48, 64, 80, 96, 112, 128 -}; - -void T_Phase(thinker_t *thinker) -{ - phase_t *phase = (phase_t *) thinker; - phase->index = (phase->index + 1) & 63; - phase->sector->lightlevel = phase->base + PhaseTable[phase->index]; -} - -//========================================================================== -// -// P_SpawnPhasedLight -// -//========================================================================== - -void P_SpawnPhasedLight(sector_t * sector, int base, int index) -{ - phase_t *phase; - - phase = Z_Malloc(sizeof(*phase), PU_LEVSPEC, 0); - P_AddThinker(&phase->thinker); - phase->sector = sector; - if (index == -1) - { // sector->lightlevel as the index - phase->index = sector->lightlevel & 63; - } - else - { - phase->index = index & 63; - } - phase->base = base & 255; - sector->lightlevel = phase->base + PhaseTable[phase->index]; - phase->thinker.function = T_Phase; - - sector->special = 0; -} - -//========================================================================== -// -// P_SpawnLightSequence -// -//========================================================================== - -void P_SpawnLightSequence(sector_t * sector, int indexStep) -{ - sector_t *sec; - sector_t *nextSec; - sector_t *tempSec; - int seqSpecial; - int i; - int count; - fixed_t index; - fixed_t indexDelta; - int base; - - seqSpecial = LIGHT_SEQUENCE; // look for Light_Sequence, first - sec = sector; - count = 1; - do - { - nextSec = NULL; - sec->special = LIGHT_SEQUENCE_START; // make sure that the search doesn't back up. - for (i = 0; i < sec->linecount; i++) - { - tempSec = getNextSector(sec->lines[i], sec); - if (!tempSec) - { - continue; - } - if (tempSec->special == seqSpecial) - { - if (seqSpecial == LIGHT_SEQUENCE) - { - seqSpecial = LIGHT_SEQUENCE_ALT; - } - else - { - seqSpecial = LIGHT_SEQUENCE; - } - nextSec = tempSec; - count++; - } - } - sec = nextSec; - } - while (sec); - - sec = sector; - count *= indexStep; - index = 0; - indexDelta = FixedDiv(64 * FRACUNIT, count * FRACUNIT); - base = sector->lightlevel; - do - { - nextSec = NULL; - if (sec->lightlevel) - { - base = sec->lightlevel; - } - P_SpawnPhasedLight(sec, base, index >> FRACBITS); - index += indexDelta; - for (i = 0; i < sec->linecount; i++) - { - tempSec = getNextSector(sec->lines[i], sec); - if (!tempSec) - { - continue; - } - if (tempSec->special == LIGHT_SEQUENCE_START) - { - nextSec = tempSec; - } - } - sec = nextSec; - } - while (sec); -} diff --git a/games/NXDoom/src/hexen/p_local.h b/games/NXDoom/src/hexen/p_local.h deleted file mode 100644 index 9bd92dd9637..00000000000 --- a/games/NXDoom/src/hexen/p_local.h +++ /dev/null @@ -1,429 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __P_LOCAL__ -#define __P_LOCAL__ - -#ifndef __R_LOCAL__ -#include "r_local.h" -#endif - -#define STARTREDPALS 1 -#define STARTBONUSPALS 9 -#define STARTPOISONPALS 13 -#define STARTICEPAL 21 -#define STARTHOLYPAL 22 -#define STARTSCOURGEPAL 25 -#define NUMREDPALS 8 -#define NUMBONUSPALS 4 -#define NUMPOISONPALS 8 - -#define TOCENTER -8 -#define FLOATSPEED (FRACUNIT*4) - -#define MAXHEALTH 100 -#define MAXMORPHHEALTH 30 -#define VIEWHEIGHT (48*FRACUNIT) - -// mapblocks are used to check movement against lines and things -#define MAPBLOCKUNITS 128 -#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) -#define MAPBLOCKSHIFT (FRACBITS+7) -#define MAPBMASK (MAPBLOCKSIZE-1) -#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) - -// player radius for movement checking -#define PLAYERRADIUS 16*FRACUNIT - -// MAXRADIUS is for precalculated sector block boxes -// the spider demon is larger, but we don't have any moving sectors -// nearby -#define MAXRADIUS 32*FRACUNIT - -#define GRAVITY FRACUNIT -#define MAXMOVE (30*FRACUNIT) - -#define USERANGE (64*FRACUNIT) -#define MELEERANGE (64*FRACUNIT) -#define MISSILERANGE (32*64*FRACUNIT) - -typedef enum -{ - DI_EAST, - DI_NORTHEAST, - DI_NORTH, - DI_NORTHWEST, - DI_WEST, - DI_SOUTHWEST, - DI_SOUTH, - DI_SOUTHEAST, - DI_NODIR, - NUMDIRS -} dirtype_t; - -#define BASETHRESHOLD 100 // follow a player exlusively for 3 seconds - -// ***** P_TICK ***** - -extern thinker_t thinkercap; // both the head and tail of the thinker list -extern int TimerGame; // tic countdown for deathmatch - -void P_InitThinkers(void); -void P_AddThinker(thinker_t * thinker); -void P_RemoveThinker(thinker_t * thinker); - -// ***** P_PSPR ***** - -#define USE_MANA1 1 -#define USE_MANA2 1 - -void P_SetPsprite(player_t * player, int position, statenum_t stnum); -void P_SetPspriteNF(player_t * player, int position, statenum_t stnum); -void P_SetupPsprites(player_t * curplayer); -void P_MovePsprites(player_t * curplayer); -void P_DropWeapon(player_t * player); -void P_ActivateMorphWeapon(player_t * player); -void P_PostMorphWeapon(player_t * player, weapontype_t weapon); - -// ***** P_USER ***** - - -extern int ArmorMax[NUMCLASSES]; -extern int PStateNormal[NUMCLASSES]; -extern int PStateRun[NUMCLASSES]; -extern int PStateAttack[NUMCLASSES]; -extern int PStateAttackEnd[NUMCLASSES]; - -void P_PlayerThink(player_t * player); -void P_Thrust(player_t * player, angle_t angle, fixed_t move); -void P_PlayerNextArtifact(player_t *player); -void P_PlayerRemoveArtifact(player_t * player, int slot); -void P_PlayerUseArtifact(player_t * player, artitype_t arti); -boolean P_UseArtifact(player_t * player, artitype_t arti); -int P_GetPlayerNum(player_t * player); -void P_TeleportOther(mobj_t * victim); -void ResetBlasted(mobj_t * mo); -boolean P_UndoPlayerMorph(player_t *player); - - -// ***** P_MOBJ ***** - -// Any floor type >= FLOOR_LIQUID will floorclip sprites -enum -{ - FLOOR_SOLID, - FLOOR_ICE, - FLOOR_LIQUID, - FLOOR_WATER, - FLOOR_LAVA, - FLOOR_SLUDGE -}; - -#define ONFLOORZ INT_MIN -#define ONCEILINGZ INT_MAX -#define FLOATRANDZ (INT_MAX-1) -#define FROMCEILINGZ128 (INT_MAX-2) - -extern mobjtype_t PuffType; -extern mobj_t *MissileMobj; - -extern fixed_t FloatBobOffsets[64]; - - -mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); -void P_RemoveMobj(mobj_t * th); -boolean P_SetMobjState(mobj_t * mobj, statenum_t state); -boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state); -void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move); -int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta); -boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax); -void P_MobjThinker(thinker_t *thinker); -void P_DegenMobjThinker(thinker_t *thinker); -void P_BlasterMobjThinker(thinker_t *thinker); -void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z); -void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage); -void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator); -void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator); -void P_RipperBlood(mobj_t * mo); -int P_GetThingFloorType(mobj_t * thing); -int P_HitFloor(mobj_t * thing); -boolean P_CheckMissileSpawn(mobj_t * missile); -mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type); -mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z, - mobj_t * source, mobj_t * dest, mobjtype_t type); -mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, - angle_t angle, fixed_t momz); -mobj_t *P_SpawnMissileAngleSpeed(mobj_t * source, mobjtype_t type, - angle_t angle, fixed_t momz, fixed_t speed); -mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type); -mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle); -mobj_t *P_SPMAngleXYZ(mobj_t * source, fixed_t x, fixed_t y, - fixed_t z, mobjtype_t type, angle_t angle); -void P_CreateTIDList(void); -void P_RemoveMobjFromTIDList(mobj_t * mobj); -void P_InsertMobjIntoTIDList(mobj_t * mobj, int tid); -mobj_t *P_FindMobjFromTID(int tid, int *searchPosition); -void P_ExplodeMissile(mobj_t *mo); -mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z, - mobj_t * source, mobj_t * dest, mobjtype_t type); - -// ***** P_ENEMY ***** - -void P_NoiseAlert(mobj_t * target, mobj_t * emmiter); -int P_Massacre(void); -boolean A_RaiseMobj(mobj_t * actor); -boolean A_SinkMobj(mobj_t * actor); -void A_NoBlocking(mobj_t *actor, player_t *player, pspdef_t *psp); -boolean P_LookForMonsters(mobj_t * actor); -void P_InitCreatureCorpseQueue(boolean corpseScan); -void A_DeQueueCorpse(mobj_t * actor); -void A_Explode(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CHolyAttack3(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FSwordAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MStaffAttack2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_FreezeDeathChunks(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcBallOrbit(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcSpinBalls(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SpeedBalls(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SlowBalls(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_StopBalls(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_AccelBalls(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_DecelBalls(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcBossAttack(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SpawnFizzle(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_CastSorcererSpell(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcUpdateBallAngle(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_BounceCheck(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcFX1Seek(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcOffense1(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_SorcOffense2(mobj_t *actor, player_t *player, pspdef_t *psp); -void A_MinotaurLook(mobj_t *actor, player_t *player, pspdef_t *psp); - - -// ***** P_MAPUTL ***** - -typedef struct -{ - fixed_t x, y, dx, dy; -} divline_t; - -typedef struct -{ - fixed_t frac; // along trace line - boolean isaline; - union - { - mobj_t *thing; - line_t *line; - } d; -} intercept_t; - -#define MAXINTERCEPTS 128 -extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p; -typedef boolean(*traverser_t) (intercept_t * in); - - -fixed_t P_AproxDistance(fixed_t dx, fixed_t dy); -int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line); -int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line); -void P_MakeDivline(line_t * li, divline_t * dl); -fixed_t P_InterceptVector(divline_t * v2, divline_t * v1); -int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld); - -extern fixed_t opentop, openbottom, openrange; -extern fixed_t lowfloor; -void P_LineOpening(line_t * linedef); - -boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)); -boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)); - -#define PT_ADDLINES 1 -#define PT_ADDTHINGS 2 -#define PT_EARLYOUT 4 - -extern divline_t trace; -boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, - int flags, boolean(*trav) (intercept_t *)); - -void P_UnsetThingPosition(mobj_t * thing); -void P_SetThingPosition(mobj_t * thing); -mobj_t *P_RoughMonsterSearch(mobj_t * mo, int distance); - -// ***** P_MAP ***** - - -#define MAXSPECIALCROSS 8 - - -extern boolean floatok; // if true, move would be ok if -extern fixed_t tmfloorz, tmceilingz; // within tmfloorz - tmceilingz -extern int tmfloorpic; -extern mobj_t *BlockingMobj; - -extern line_t *ceilingline; -extern line_t *spechit[MAXSPECIALCROSS]; -extern int numspechit; - -extern fixed_t topslope, bottomslope; // slopes to top and bottom of target - - -boolean P_TestMobjLocation(mobj_t * mobj); -boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y); -mobj_t *P_CheckOnmobj(mobj_t * thing); -void P_FakeZMovement(mobj_t * mo); -boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y); -boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y); -void P_SlideMove(mobj_t * mo); -void P_BounceWall(mobj_t * mo); -boolean P_CheckSight(mobj_t * t1, mobj_t * t2); -void P_UseLines(player_t * player); -boolean P_UsePuzzleItem(player_t * player, int itemType); -void PIT_ThrustSpike(mobj_t * actor); -void P_InitSlideLine(void); - -boolean P_ChangeSector(sector_t * sector, int crunch); - -extern mobj_t *PuffSpawned; // true if a puff was spawned -extern mobj_t *linetarget; // who got hit (or NULL) -fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance); - -void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, - int damage); - -void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage, int distance, - boolean damageSource); - -// ***** P_SETUP ***** - -extern byte *rejectmatrix; // for fast sight rejection -extern short *blockmaplump; // offsets in blockmap are from here -extern short *blockmap; -extern int bmapwidth, bmapheight; // in mapblocks -extern fixed_t bmaporgx, bmaporgy; // origin of block map -extern mobj_t **blocklinks; // for thing chains - -// ***** P_INTER ***** - -extern int clipmana[NUMMANA]; -extern int ArmorIncrement[NUMCLASSES][NUMARMOR]; -extern int AutoArmorSave[NUMCLASSES]; -extern const char *TextKeyMessages[]; - - -void P_SetMessage(player_t * player, const char *message, boolean ultmsg); -void P_SetYellowMessage(player_t * player, const char *message, boolean ultmsg); -void P_ClearMessage(player_t * player); -void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher); -void P_DamageMobj(mobj_t * target, mobj_t * inflictor, mobj_t * source, - int damage); -void P_FallingDamage(player_t * player); -void P_PoisonPlayer(player_t * player, mobj_t * poisoner, int poison); -void P_PoisonDamage(player_t * player, mobj_t * source, int damage, - boolean playPainSound); -boolean P_GiveMana(player_t * player, manatype_t mana, int count); -boolean P_GiveArtifact(player_t * player, artitype_t arti, mobj_t * mo); -boolean P_GiveArmor(player_t * player, armortype_t armortype, int amount); -boolean P_GiveBody(player_t * player, int num); -boolean P_GivePower(player_t * player, powertype_t power); -boolean P_MorphPlayer(player_t * player); - -// ***** AM_MAP ***** - -boolean AM_Responder(event_t * ev); -void AM_Ticker(void); -void AM_Drawer(void); - -// ***** A_ACTION ***** -boolean A_LocalQuake(byte * args, mobj_t * victim); -void P_SpawnDirt(mobj_t * actor, fixed_t radius); -void A_BridgeRemove(mobj_t * actor); -void A_UnHideThing(mobj_t *actor, player_t *player, pspdef_t *psp); - - -// ***** SB_BAR ***** - -extern int SB_state; -extern int ArtifactFlash; -void SB_PaletteFlash(boolean forceChange); - -// ===== PO_MAN ===== - -typedef enum -{ - PODOOR_NONE, - PODOOR_SLIDE, - PODOOR_SWING, -} podoortype_t; - -typedef struct -{ - thinker_t thinker; - int polyobj; - int speed; - unsigned int dist; - int angle; - fixed_t xSpeed; // for sliding walls - fixed_t ySpeed; -} polyevent_t; - -typedef struct -{ - thinker_t thinker; - int polyobj; - int speed; - int dist; - int totalDist; - int direction; - fixed_t xSpeed, ySpeed; - int tics; - int waitTics; - podoortype_t type; - boolean close; -} polydoor_t; - -enum -{ - PO_ANCHOR_TYPE = 3000, - PO_SPAWN_TYPE, - PO_SPAWNCRUSH_TYPE -}; - -#define PO_LINE_START 1 // polyobj line start special -#define PO_LINE_EXPLICIT 5 - -extern polyobj_t *polyobjs; // list of all poly-objects on the level -extern int po_NumPolyobjs; -extern polyblock_t **PolyBlockMap; - - -void T_PolyDoor(thinker_t *thinker); -void T_RotatePoly(thinker_t *thinker); -boolean EV_RotatePoly(line_t * line, byte * args, int direction, boolean - overRide); -void T_MovePoly(thinker_t *thinker); -boolean EV_MovePoly(line_t * line, byte * args, boolean timesEight, boolean - overRide); -boolean EV_OpenPolyDoor(line_t * line, byte * args, podoortype_t type); - -boolean PO_MovePolyobj(int num, int x, int y); -boolean PO_RotatePolyobj(int num, angle_t angle); -void PO_Init(int lump); -boolean PO_Busy(int polyobj); - -#include "p_spec.h" - -#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/hexen/p_map.c b/games/NXDoom/src/hexen/p_map.c deleted file mode 100644 index 6a3886015e7..00000000000 --- a/games/NXDoom/src/hexen/p_map.c +++ /dev/null @@ -1,2338 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "m_bbox.h" -#include "p_local.h" -#include "s_sound.h" - -static void CheckForPushSpecial(line_t * line, int side, mobj_t * mobj); - -/* -=============================================================================== - -NOTES: - - -=============================================================================== -*/ - -/* -=============================================================================== - -mobj_t NOTES - -mobj_ts are used to tell the refresh where to draw an image, tell the world simulation when objects are contacted, and tell the sound driver how to position a sound. - -The refresh uses the next and prev links to follow lists of things in sectors as they are being drawn. The sprite, frame, and angle elements determine which patch_t is used to draw the sprite if it is visible. The sprite and frame values are allmost allways set from state_t structures. The statescr.exe utility generates the states.h and states.c files that contain the sprite/frame numbers from the statescr.txt source file. The xyz origin point represents a point at the bottom middle of the sprite (between the feet of a biped). This is the default origin position for patch_ts grabbed with lumpy.exe. A walking creature will have its z equal to the floor it is standing on. - -The sound code uses the x,y, and subsector fields to do stereo positioning of any sound effited by the mobj_t. - -The play simulation uses the blocklinks, x,y,z, radius, height to determine when mobj_ts are touching each other, touching lines in the map, or hit by trace lines (gunshots, lines of sight, etc). The mobj_t->flags element has various bit flags used by the simulation. - - -Every mobj_t is linked into a single sector based on it's origin coordinates. -The subsector_t is found with R_PointInSubsector(x,y), and the sector_t can be found with subsector->sector. The sector links are only used by the rendering code, the play simulation does not care about them at all. - -Any mobj_t that needs to be acted upon be something else in the play world (block movement, be shot, etc) will also need to be linked into the blockmap. If the thing has the MF_NOBLOCK flag set, it will not use the block links. It can still interact with other things, but only as the instigator (missiles will run into other things, but nothing can run into a missile). Each block in the grid is 128*128 units, and knows about every line_t that it contains a piece of, and every interactable mobj_t that has it's origin contained. - -A valid mobj_t is a mobj_t that has the proper subsector_t filled in for it's xy coordinates and is linked into the subsector's sector or has the MF_NOSECTOR flag set (the subsector_t needs to be valid even if MF_NOSECTOR is set), and is linked into a blockmap block or has the MF_NOBLOCKMAP flag set. Links should only be modified by the P_[Un]SetThingPosition () functions. Do not change the MF_NO? flags while a thing is valid. - - -=============================================================================== -*/ - -fixed_t tmbbox[4]; -mobj_t *tmthing; -mobj_t *tsthing; -int tmflags; -fixed_t tmx, tmy; - -boolean floatok; // if true, move would be ok if - // within tmfloorz - tmceilingz - -fixed_t tmfloorz, tmceilingz, tmdropoffz; -int tmfloorpic; - -// keep track of the line that lowers the ceiling, so missiles don't explode -// against sky hack walls -line_t *ceilingline; - -// keep track of special lines as they are hit, but don't process them -// until the move is proven valid - -line_t *spechit[MAXSPECIALCROSS]; -int numspechit; - -mobj_t *onmobj; // generic global onmobj...used for landing on pods/players -mobj_t *BlockingMobj; - -/* -=============================================================================== - - TELEPORT MOVE - -=============================================================================== -*/ - -/* -================== -= -= PIT_StompThing -= -================== -*/ - -boolean PIT_StompThing(mobj_t * thing) -{ - fixed_t blockdist; - - if (!(thing->flags & MF_SHOOTABLE)) - return true; - - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - return true; // didn't hit it - - if (thing == tmthing) - return true; // don't clip against self - - if (!(tmthing->flags2 & MF2_TELESTOMP)) - { // Not allowed to stomp things - return (false); - } - - P_DamageMobj(thing, tmthing, tmthing, 10000); - - return true; -} - - -/* -=================== -= -= P_TeleportMove -= -=================== -*/ - -boolean P_TeleportMove(mobj_t * thing, fixed_t x, fixed_t y) -{ - int xl, xh, yl, yh, bx, by; - subsector_t *newsubsec; - -// -// kill anything occupying the position -// - - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; - -// -// the base floor / ceiling is from the subsector that contains the -// point. Any contacted lines the step closer together will adjust them -// - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - tmfloorpic = newsubsec->sector->floorpic; - - validcount++; - numspechit = 0; - -// -// stomp on any things contacted -// - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_StompThing)) - return false; - -// -// the move is ok, so link the thing into its new position -// - P_UnsetThingPosition(thing); - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - - P_SetThingPosition(thing); - - return true; -} - - -boolean PIT_ThrustStompThing(mobj_t * thing) -{ - fixed_t blockdist; - - if (!(thing->flags & MF_SHOOTABLE)) - return true; - - blockdist = thing->radius + tsthing->radius; - if (abs(thing->x - tsthing->x) >= blockdist || - abs(thing->y - tsthing->y) >= blockdist || - (thing->z > tsthing->z + tsthing->height)) - return true; // didn't hit it - - if (thing == tsthing) - return true; // don't clip against self - - P_DamageMobj(thing, tsthing, tsthing, 10001); - tsthing->args[1] = 1; // Mark thrust thing as bloody - - return true; -} - - - -void PIT_ThrustSpike(mobj_t * actor) -{ - int xl, xh, yl, yh, bx, by; - int x0, x2, y0, y2; - - tsthing = actor; - - x0 = actor->x - actor->info->radius; - x2 = actor->x + actor->info->radius; - y0 = actor->y - actor->info->radius; - y2 = actor->y + actor->info->radius; - - xl = (x0 - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (x2 - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (y0 - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (y2 - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - // stomp on any things contacted - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - P_BlockThingsIterator(bx, by, PIT_ThrustStompThing); -} - - - -/* -=============================================================================== - - MOVEMENT ITERATOR FUNCTIONS - -=============================================================================== -*/ - -/* -================== -= -= PIT_CheckLine -= -= Adjusts tmfloorz and tmceilingz as lines are contacted -================== -*/ - -boolean PIT_CheckLine(line_t * ld) -{ - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - { - return (true); - } - if (P_BoxOnLineSide(tmbbox, ld) != -1) - { - return (true); - } - -// a line has been hit -/* -= -= The moving thing's destination position will cross the given line. -= If this should not be allowed, return false. -= If the line is special, keep track of it to process later if the move -= is proven ok. NOTE: specials are NOT sorted by order, so two special lines -= that are only 8 pixels apart could be crossed in either order. -*/ - - if (!ld->backsector) - { // One sided line - if (tmthing->flags2 & MF2_BLASTED) - { - P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); - } - CheckForPushSpecial(ld, 0, tmthing); - return (false); - } - if (!(tmthing->flags & MF_MISSILE)) - { - if (ld->flags & ML_BLOCKING) - { // Explicitly blocking everything - if (tmthing->flags2 & MF2_BLASTED) - { - P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); - } - CheckForPushSpecial(ld, 0, tmthing); - return (false); - } - if (!tmthing->player && ld->flags & ML_BLOCKMONSTERS) - { // Block monsters only - if (tmthing->flags2 & MF2_BLASTED) - { - P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); - } - return (false); - } - } - P_LineOpening(ld); // set openrange, opentop, openbottom - // adjust floor / ceiling heights - if (opentop < tmceilingz) - { - tmceilingz = opentop; - ceilingline = ld; - } - if (openbottom > tmfloorz) - { - tmfloorz = openbottom; - } - if (lowfloor < tmdropoffz) - { - tmdropoffz = lowfloor; - } - if (ld->special) - { // Contacted a special line, add it to the list - spechit[numspechit] = ld; - numspechit++; - } - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC PIT_CheckThing -// -//--------------------------------------------------------------------------- - -boolean PIT_CheckThing(mobj_t * thing) -{ - fixed_t blockdist; - boolean solid; - int damage; - - if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) - { // Can't hit thing - return (true); - } - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - { // Didn't hit thing - return (true); - } - if (thing == tmthing) - { // Don't clip against self - return (true); - } - BlockingMobj = thing; - if (tmthing->flags2 & MF2_PASSMOBJ) - { // check if a mobj passed over/under another object - if (tmthing->type == MT_BISHOP && thing->type == MT_BISHOP) - { // don't let bishops fly over other bishops - return false; - } - if (tmthing->z >= thing->z + thing->height - && !(thing->flags & MF_SPECIAL)) - { - return (true); - } - else if (tmthing->z + tmthing->height < thing->z - && !(thing->flags & MF_SPECIAL)) - { // under thing - return (true); - } - } - // Check for skulls slamming into things - if (tmthing->flags & MF_SKULLFLY) - { - if (tmthing->type == MT_MINOTAUR) - { - // Slamming minotaurs shouldn't move non-creatures - if (!(thing->flags & MF_COUNTKILL)) - { - return (false); - } - } - else if (tmthing->type == MT_HOLY_FX) - { - if (thing->flags & MF_SHOOTABLE && thing != tmthing->target) - { - if (netgame && !deathmatch && thing->player) - { // don't attack other co-op players - return true; - } - if (thing->flags2 & MF2_REFLECTIVE - && (thing->player || thing->flags2 & MF2_BOSS)) - { - tmthing->special1.m = tmthing->target; - tmthing->target = thing; - return true; - } - if (thing->flags & MF_COUNTKILL || thing->player) - { - tmthing->special1.m = thing; - } - if (P_Random() < 96) - { - damage = 12; - if (thing->player || thing->flags2 & MF2_BOSS) - { - damage = 3; - // ghost burns out faster when attacking players/bosses - tmthing->health -= 6; - } - P_DamageMobj(thing, tmthing, tmthing->target, damage); - if (P_Random() < 128) - { - P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, - MT_HOLY_PUFF); - S_StartSound(tmthing, SFX_SPIRIT_ATTACK); - if (thing->flags & MF_COUNTKILL && P_Random() < 128 - && !S_GetSoundPlayingInfo(thing, SFX_PUPPYBEAT)) - { - if ((thing->type == MT_CENTAUR) || - (thing->type == MT_CENTAURLEADER) || - (thing->type == MT_ETTIN)) - { - S_StartSound(thing, SFX_PUPPYBEAT); - } - } - } - } - if (thing->health <= 0) - { - tmthing->special1.i = 0; - } - } - return true; - } - damage = ((P_Random() % 8) + 1) * tmthing->damage; - P_DamageMobj(thing, tmthing, tmthing, damage); - tmthing->flags &= ~MF_SKULLFLY; - tmthing->momx = tmthing->momy = tmthing->momz = 0; - P_SetMobjState(tmthing, tmthing->info->seestate); - return (false); - } - // Check for blasted thing running into another - if (tmthing->flags2 & MF2_BLASTED && thing->flags & MF_SHOOTABLE) - { - if (!(thing->flags2 & MF2_BOSS) && (thing->flags & MF_COUNTKILL)) - { - thing->momx += tmthing->momx; - thing->momy += tmthing->momy; - if ((thing->momx + thing->momy) > 3 * FRACUNIT) - { - damage = (tmthing->info->mass / 100) + 1; - P_DamageMobj(thing, tmthing, tmthing, damage); - damage = (thing->info->mass / 100) + 1; - P_DamageMobj(tmthing, thing, thing, damage >> 2); - } - return (false); - } - } - // Check for missile - if (tmthing->flags & MF_MISSILE) - { - // Check for a non-shootable mobj - if (thing->flags2 & MF2_NONSHOOTABLE) - { - return true; - } - // Check if it went over / under - if (tmthing->z > thing->z + thing->height) - { // Over thing - return (true); - } - if (tmthing->z + tmthing->height < thing->z) - { // Under thing - return (true); - } - if (tmthing->flags2 & MF2_FLOORBOUNCE) - { - if (tmthing->target == thing || !(thing->flags & MF_SOLID)) - { - return true; - } - else - { - return false; - } - } - if (tmthing->type == MT_LIGHTNING_FLOOR - || tmthing->type == MT_LIGHTNING_CEILING) - { - if (thing->flags & MF_SHOOTABLE && thing != tmthing->target) - { - if (thing->info->mass != INT_MAX) - { - thing->momx += tmthing->momx >> 4; - thing->momy += tmthing->momy >> 4; - } - if ((!thing->player && !(thing->flags2 & MF2_BOSS)) - || !(leveltime & 1)) - { - if (thing->type == MT_CENTAUR - || thing->type == MT_CENTAURLEADER) - { // Lightning does more damage to centaurs - P_DamageMobj(thing, tmthing, tmthing->target, 9); - } - else - { - P_DamageMobj(thing, tmthing, tmthing->target, 3); - } - if (!(S_GetSoundPlayingInfo(tmthing, - SFX_MAGE_LIGHTNING_ZAP))) - { - S_StartSound(tmthing, SFX_MAGE_LIGHTNING_ZAP); - } - if (thing->flags & MF_COUNTKILL && P_Random() < 64 - && !S_GetSoundPlayingInfo(thing, SFX_PUPPYBEAT)) - { - if ((thing->type == MT_CENTAUR) || - (thing->type == MT_CENTAURLEADER) || - (thing->type == MT_ETTIN)) - { - S_StartSound(thing, SFX_PUPPYBEAT); - } - } - } - tmthing->health--; - if (tmthing->health <= 0 || thing->health <= 0) - { - return false; - } - if (tmthing->type == MT_LIGHTNING_FLOOR) - { - if (tmthing->special2.m - && !tmthing->special2.m->special1.m) - { - tmthing->special2.m->special1.m = thing; - } - } - else if (!tmthing->special1.m) - { - tmthing->special1.m = thing; - } - } - return true; // lightning zaps through all sprites - } - else if (tmthing->type == MT_LIGHTNING_ZAP) - { - mobj_t *lmo; - - if (thing->flags & MF_SHOOTABLE && thing != tmthing->target) - { - lmo = tmthing->special2.m; - if (lmo) - { - if (lmo->type == MT_LIGHTNING_FLOOR) - { - if (lmo->special2.m - && !lmo->special2.m->special1.m) - { - lmo->special2.m->special1.m = thing; - } - } - else if (!lmo->special1.m) - { - lmo->special1.m = thing; - } - if (!(leveltime & 3)) - { - lmo->health--; - } - } - } - } - else if (tmthing->type == MT_MSTAFF_FX2 && thing != tmthing->target) - { - if (!thing->player && !(thing->flags2 & MF2_BOSS)) - { - switch (thing->type) - { - case MT_FIGHTER_BOSS: // these not flagged boss - case MT_CLERIC_BOSS: // so they can be blasted - case MT_MAGE_BOSS: - break; - default: - P_DamageMobj(thing, tmthing, tmthing->target, 10); - return true; - break; - } - } - } - if (tmthing->target && tmthing->target->type == thing->type) - { // Don't hit same species as originator - if (thing == tmthing->target) - { // Don't missile self - return (true); - } - if (!thing->player) - { // Hit same species as originator, explode, no damage - return (false); - } - } - if (!(thing->flags & MF_SHOOTABLE)) - { // Didn't do any damage - return !(thing->flags & MF_SOLID); - } - if (tmthing->flags2 & MF2_RIP) - { - if (!(thing->flags & MF_NOBLOOD) && - !(thing->flags2 & MF2_REFLECTIVE) && - !(thing->flags2 & MF2_INVULNERABLE)) - { // Ok to spawn some blood - P_RipperBlood(tmthing); - } - //S_StartSound(tmthing, sfx_ripslop); - damage = ((P_Random() & 3) + 2) * tmthing->damage; - P_DamageMobj(thing, tmthing, tmthing->target, damage); - if (thing->flags2 & MF2_PUSHABLE - && !(tmthing->flags2 & MF2_CANNOTPUSH)) - { // Push thing - thing->momx += tmthing->momx >> 2; - thing->momy += tmthing->momy >> 2; - } - numspechit = 0; - return (true); - } - // Do damage - damage = ((P_Random() % 8) + 1) * tmthing->damage; - if (damage) - { - if (!(thing->flags & MF_NOBLOOD) && - !(thing->flags2 & MF2_REFLECTIVE) && - !(thing->flags2 & MF2_INVULNERABLE) && - !(tmthing->type == MT_TELOTHER_FX1) && - !(tmthing->type == MT_TELOTHER_FX2) && - !(tmthing->type == MT_TELOTHER_FX3) && - !(tmthing->type == MT_TELOTHER_FX4) && - !(tmthing->type == MT_TELOTHER_FX5) && (P_Random() < 192)) - { - P_BloodSplatter(tmthing->x, tmthing->y, tmthing->z, thing); - } - P_DamageMobj(thing, tmthing, tmthing->target, damage); - } - return (false); - } - if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH)) - { // Push thing - thing->momx += tmthing->momx >> 2; - thing->momy += tmthing->momy >> 2; - } - // Check for special thing - if (thing->flags & MF_SPECIAL) - { - solid = (thing->flags & MF_SOLID) != 0; - if (tmflags & MF_PICKUP) - { // Can be picked up by tmthing - P_TouchSpecialThing(thing, tmthing); // Can remove thing - } - return (!solid); - } - return (!(thing->flags & MF_SOLID)); -} - -//--------------------------------------------------------------------------- -// -// PIT_CheckOnmobjZ -// -//--------------------------------------------------------------------------- - -boolean PIT_CheckOnmobjZ(mobj_t * thing) -{ - fixed_t blockdist; - - if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) - { // Can't hit thing - return (true); - } - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - { // Didn't hit thing - return (true); - } - if (thing == tmthing) - { // Don't clip against self - return (true); - } - if (tmthing->z > thing->z + thing->height) - { - return (true); - } - else if (tmthing->z + tmthing->height < thing->z) - { // under thing - return (true); - } - if (thing->flags & MF_SOLID) - { - onmobj = thing; - } - return (!(thing->flags & MF_SOLID)); -} - -/* -=============================================================================== - - MOVEMENT CLIPPING - -=============================================================================== -*/ - -//---------------------------------------------------------------------------- -// -// FUNC P_TestMobjLocation -// -// Returns true if the mobj is not blocked by anything at its current -// location, otherwise returns false. -// -//---------------------------------------------------------------------------- - -boolean P_TestMobjLocation(mobj_t * mobj) -{ - int flags; - - flags = mobj->flags; - mobj->flags &= ~MF_PICKUP; - if (P_CheckPosition(mobj, mobj->x, mobj->y)) - { // XY is ok, now check Z - mobj->flags = flags; - if ((mobj->z < mobj->floorz) - || (mobj->z + mobj->height > mobj->ceilingz)) - { // Bad Z - return (false); - } - return (true); - } - mobj->flags = flags; - return (false); -} - -/* -================== -= -= P_CheckPosition -= -= This is purely informative, nothing is modified (except things picked up) - -in: -a mobj_t (can be valid or invalid) -a position to be checked (doesn't need to be related to the mobj_t->x,y) - -during: -special things are touched if MF_PICKUP -early out on solid lines? - -out: -newsubsec -floorz -ceilingz -tmdropoffz = the lowest point contacted (monsters won't move to a dropoff) -speciallines[] -numspeciallines -mobj_t *BlockingMobj = pointer to thing that blocked position (NULL if not -blocked, or blocked by a line). - -================== -*/ - -boolean P_CheckPosition(mobj_t * thing, fixed_t x, fixed_t y) -{ - int xl, xh, yl, yh, bx, by; - subsector_t *newsubsec; - - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; - -// -// the base floor / ceiling is from the subsector that contains the -// point. Any contacted lines the step closer together will adjust them -// - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - tmfloorpic = newsubsec->sector->floorpic; - - validcount++; - numspechit = 0; - - if (tmflags & MF_NOCLIP && !(tmflags & MF_SKULLFLY)) - { - return true; - } - -// -// check things first, possibly picking things up -// the bounding box is extended by MAXRADIUS because mobj_ts are grouped -// into mapblocks based on their origin point, and can overlap into adjacent -// blocks by up to MAXRADIUS units -// - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - BlockingMobj = NULL; - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) - return false; -// -// check lines -// - if (tmflags & MF_NOCLIP) - { - return true; - } - - BlockingMobj = NULL; - xl = (tmbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockLinesIterator(bx, by, PIT_CheckLine)) - return false; - return true; -} - -//============================================================================= -// -// P_CheckOnmobj(mobj_t *thing) -// -// Checks if the new Z position is legal -//============================================================================= - -mobj_t *P_CheckOnmobj(mobj_t * thing) -{ - int xl, xh, yl, yh, bx, by; - subsector_t *newsubsec; - fixed_t x; - fixed_t y; - mobj_t oldmo; - - x = thing->x; - y = thing->y; - tmthing = thing; - tmflags = thing->flags; - oldmo = *thing; // save the old mobj before the fake zmovement - P_FakeZMovement(tmthing); - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector(x, y); - ceilingline = NULL; - -// -// the base floor / ceiling is from the subsector that contains the -// point. Any contacted lines the step closer together will adjust them -// - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - tmfloorpic = newsubsec->sector->floorpic; - - validcount++; - numspechit = 0; - - if (tmflags & MF_NOCLIP) - return NULL; - -// -// check things first, possibly picking things up -// the bounding box is extended by MAXRADIUS because mobj_ts are grouped -// into mapblocks based on their origin point, and can overlap into adjacent -// blocks by up to MAXRADIUS units -// - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockThingsIterator(bx, by, PIT_CheckOnmobjZ)) - { - *tmthing = oldmo; - return onmobj; - } - *tmthing = oldmo; - return NULL; -} - -//============================================================================= -// -// P_FakeZMovement -// -// Fake the zmovement so that we can check if a move is legal -//============================================================================= - -void P_FakeZMovement(mobj_t * mo) -{ - int dist; - int delta; -// -// adjust height -// - mo->z += mo->momz; - if (mo->flags & MF_FLOAT && mo->target) - { // float down towards target if too close - if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) - { - dist = - P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); - delta = (mo->target->z + (mo->height >> 1)) - mo->z; - if (delta < 0 && dist < -(delta * 3)) - mo->z -= FLOATSPEED; - else if (delta > 0 && dist < (delta * 3)) - mo->z += FLOATSPEED; - } - } - if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) - && leveltime & 2) - { - mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; - } - -// -// clip movement -// - if (mo->z <= mo->floorz) - { // Hit the floor - mo->z = mo->floorz; - if (mo->momz < 0) - { - mo->momz = 0; - } - if (mo->flags & MF_SKULLFLY) - { // The skull slammed into something - mo->momz = -mo->momz; - } - if (mo->info->crashstate && (mo->flags & MF_CORPSE)) - { - return; - } - } - else if (mo->flags2 & MF2_LOGRAV) - { - if (mo->momz == 0) - mo->momz = -(GRAVITY >> 3) * 2; - else - mo->momz -= GRAVITY >> 3; - } - else if (!(mo->flags & MF_NOGRAVITY)) - { - if (mo->momz == 0) - mo->momz = -GRAVITY * 2; - else - mo->momz -= GRAVITY; - } - - if (mo->z + mo->height > mo->ceilingz) - { // hit the ceiling - if (mo->momz > 0) - mo->momz = 0; - mo->z = mo->ceilingz - mo->height; - if (mo->flags & MF_SKULLFLY) - { // the skull slammed into something - mo->momz = -mo->momz; - } - } -} - -//=========================================================================== -// -// CheckForPushSpecial -// -//=========================================================================== - -static void CheckForPushSpecial(line_t * line, int side, mobj_t * mobj) -{ - if (line->special) - { - if (mobj->flags2 & MF2_PUSHWALL) - { - P_ActivateLine(line, mobj, side, SPAC_PUSH); - } - else if (mobj->flags2 & MF2_IMPACT) - { - P_ActivateLine(line, mobj, side, SPAC_IMPACT); - } - } -} - -/* -=================== -= -= P_TryMove -= -= Attempt to move to a new position, crossing special lines unless MF_TELEPORT -= is set -= -=================== -*/ - -boolean P_TryMove(mobj_t * thing, fixed_t x, fixed_t y) -{ - fixed_t oldx, oldy; - int side, oldside; - line_t *ld; - - floatok = false; - if (!P_CheckPosition(thing, x, y)) - { // Solid wall or thing - if (!BlockingMobj || BlockingMobj->player || !thing->player) - { - goto pushline; - } - else if (BlockingMobj->z + BlockingMobj->height - thing->z - > 24 * FRACUNIT - || (BlockingMobj->subsector->sector->ceilingheight - - (BlockingMobj->z + BlockingMobj->height) < - thing->height) - || (tmceilingz - (BlockingMobj->z + BlockingMobj->height) < - thing->height)) - { - goto pushline; - } - } - if (!(thing->flags & MF_NOCLIP)) - { - if (tmceilingz - tmfloorz < thing->height) - { // Doesn't fit - goto pushline; - } - floatok = true; - if (!(thing->flags & MF_TELEPORT) - && tmceilingz - thing->z < thing->height - && thing->type != MT_LIGHTNING_CEILING - && !(thing->flags2 & MF2_FLY)) - { // mobj must lower itself to fit - goto pushline; - } - if (thing->flags2 & MF2_FLY) - { - if (thing->z + thing->height > tmceilingz) - { - thing->momz = -8 * FRACUNIT; - goto pushline; - } - else if (thing->z < tmfloorz - && tmfloorz - tmdropoffz > 24 * FRACUNIT) - { - thing->momz = 8 * FRACUNIT; - goto pushline; - } - } - if (!(thing->flags & MF_TELEPORT) - // The Minotaur floor fire (MT_MNTRFX2) can step up any amount - && thing->type != MT_MNTRFX2 && thing->type != MT_LIGHTNING_FLOOR - && tmfloorz - thing->z > 24 * FRACUNIT) - { - goto pushline; - } - if (!(thing->flags & (MF_DROPOFF | MF_FLOAT)) && - (tmfloorz - tmdropoffz > 24 * FRACUNIT) && - !(thing->flags2 & MF2_BLASTED)) - { // Can't move over a dropoff unless it's been blasted - return (false); - } - if (thing->flags2 & MF2_CANTLEAVEFLOORPIC - && (tmfloorpic != thing->subsector->sector->floorpic - || tmfloorz - thing->z != 0)) - { // must stay within a sector of a certain floor type - return false; - } - } - -// -// the move is ok, so link the thing into its new position -// - P_UnsetThingPosition(thing); - - oldx = thing->x; - oldy = thing->y; - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->floorpic = tmfloorpic; - thing->x = x; - thing->y = y; - - P_SetThingPosition(thing); - - if (thing->flags2 & MF2_FLOORCLIP) - { - if (thing->z == thing->subsector->sector->floorheight - && P_GetThingFloorType(thing) >= FLOOR_LIQUID) - { - thing->floorclip = 10 * FRACUNIT; - } - else - { - thing->floorclip = 0; - } - } - -// -// if any special lines were hit, do the effect -// - if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) - { - while (numspechit > 0) - { - numspechit--; - // see if the line was crossed - ld = spechit[numspechit]; - side = P_PointOnLineSide(thing->x, thing->y, ld); - oldside = P_PointOnLineSide(oldx, oldy, ld); - if (side != oldside) - { - if (ld->special) - { - if (thing->player) - { - P_ActivateLine(ld, thing, oldside, SPAC_CROSS); - } - else if (thing->flags2 & MF2_MCROSS) - { - P_ActivateLine(ld, thing, oldside, SPAC_MCROSS); - } - else if (thing->flags2 & MF2_PCROSS) - { - P_ActivateLine(ld, thing, oldside, SPAC_PCROSS); - } - } - } - } - } - return true; - - pushline: - if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) - { - int numSpecHitTemp; - - if (tmthing->flags2 & MF2_BLASTED) - { - P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass >> 5); - } - numSpecHitTemp = numspechit; - while (numSpecHitTemp > 0) - { - numSpecHitTemp--; - // see if the line was crossed - ld = spechit[numSpecHitTemp]; - side = P_PointOnLineSide(thing->x, thing->y, ld); - CheckForPushSpecial(ld, side, thing); - } - } - return false; -} - -/* -================== -= -= P_ThingHeightClip -= -= Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, -= anf possibly thing->z -= -= This is called for all nearby monsters whenever a sector changes height -= -= If the thing doesn't fit, the z will be set to the lowest value and -= false will be returned -================== -*/ - -boolean P_ThingHeightClip(mobj_t * thing) -{ - boolean onfloor; - - onfloor = (thing->z == thing->floorz); - - P_CheckPosition(thing, thing->x, thing->y); - // what about stranding a monster partially off an edge? - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->floorpic = tmfloorpic; - - if (onfloor) - { // walking monsters rise and fall with the floor - if ((thing->z - thing->floorz < 9 * FRACUNIT) - || (thing->flags & MF_NOGRAVITY)) - { - thing->z = thing->floorz; - } - } - else - { // don't adjust a floating monster unless forced to - if (thing->z + thing->height > thing->ceilingz) - thing->z = thing->ceilingz - thing->height; - } - - if (thing->ceilingz - thing->floorz < thing->height) - return false; - - return true; -} - - -/* -============================================================================== - - SLIDE MOVE - -Allows the player to slide along any angled walls - -============================================================================== -*/ - -fixed_t bestslidefrac, secondslidefrac; -line_t *bestslideline, *secondslideline; -mobj_t *slidemo; - -fixed_t tmxmove, tmymove; - -/* -================== -= -= P_HitSlideLine -= -= Adjusts the xmove / ymove so that the next move will slide along the wall -================== -*/ - -void P_HitSlideLine(line_t * ld) -{ - int side; - angle_t lineangle, moveangle, deltaangle; - fixed_t movelen, newlen; - - - if (ld->slopetype == ST_HORIZONTAL) - { - tmymove = 0; - return; - } - if (ld->slopetype == ST_VERTICAL) - { - tmxmove = 0; - return; - } - - side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - - lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); - if (side == 1) - lineangle += ANG180; - moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove); - deltaangle = moveangle - lineangle; - if (deltaangle > ANG180) - deltaangle += ANG180; -// I_Error ("SlideLine: ang>ANG180"); - - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance(tmxmove, tmymove); - newlen = FixedMul(movelen, finecosine[deltaangle]); - tmxmove = FixedMul(newlen, finecosine[lineangle]); - tmymove = FixedMul(newlen, finesine[lineangle]); -} - -/* -============== -= -= PTR_SlideTraverse -= -============== -*/ - -boolean PTR_SlideTraverse(intercept_t * in) -{ - line_t *li; - - if (!in->isaline) - I_Error("PTR_SlideTraverse: not a line?"); - - li = in->d.line; - if (!(li->flags & ML_TWOSIDED)) - { - if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) - return true; // don't hit the back side - goto isblocking; - } - - P_LineOpening(li); // set openrange, opentop, openbottom - if (openrange < slidemo->height) - goto isblocking; // doesn't fit - - if (opentop - slidemo->z < slidemo->height) - goto isblocking; // mobj is too high - - if (openbottom - slidemo->z > 24 * FRACUNIT) - goto isblocking; // too big a step up - - return true; // this line doesn't block movement - -// the line does block movement, see if it is closer than best so far - isblocking: - if (in->frac < bestslidefrac) - { - secondslidefrac = bestslidefrac; - secondslideline = bestslideline; - bestslidefrac = in->frac; - bestslideline = li; - } - - return false; // stop -} - - -/* -================== -= -= P_SlideMove -= -= The momx / momy move is bad, so try to slide along a wall -= -= Find the first line hit, move flush to it, and slide along it -= -= This is a kludgy mess. -================== -*/ - -void P_SlideMove(mobj_t * mo) -{ - fixed_t leadx, leady; - fixed_t trailx, traily; - fixed_t newx, newy; - int hitcount; - - slidemo = mo; - hitcount = 0; - retry: - if (++hitcount == 3) - goto stairstep; // don't loop forever - -// -// trace along the three leading corners -// - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; - - P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, - PT_ADDLINES, PTR_SlideTraverse); - -// -// move up to the wall -// - if (bestslidefrac == FRACUNIT + 1) - { // the move must have hit the middle, so stairstep - stairstep: - if (!P_TryMove(mo, mo->x, mo->y + mo->momy)) - { - P_TryMove(mo, mo->x + mo->momx, mo->y); - } - return; - } - - bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit - if (bestslidefrac > 0) - { - newx = FixedMul(mo->momx, bestslidefrac); - newy = FixedMul(mo->momy, bestslidefrac); - if (!P_TryMove(mo, mo->x + newx, mo->y + newy)) - goto stairstep; - } - -// -// now continue along the wall -// - bestslidefrac = FRACUNIT - (bestslidefrac + 0x800); // remainder - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - if (bestslidefrac <= 0) - return; - - tmxmove = FixedMul(mo->momx, bestslidefrac); - tmymove = FixedMul(mo->momy, bestslidefrac); - - P_HitSlideLine(bestslideline); // clip the moves - - mo->momx = tmxmove; - mo->momy = tmymove; - - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove)) - { - goto retry; - } -} - -//============================================================================ -// -// P_InitSlideLine -// -//============================================================================ - -void P_InitSlideLine(void) -{ - // use relevant parts from first bestslideline in demo1 (hexen.wad) - static vertex_t initvertex1 = {-77594624, 37748736}; - static line_t initslideline = {&initvertex1, NULL, 0, 6291456, 0, 0, 0, 0, - 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0 }, 0, NULL, NULL, 0, NULL}; - - if (bestslideline == NULL) - { - bestslideline = &initslideline; - } -} - -//============================================================================ -// -// PTR_BounceTraverse -// -//============================================================================ - -boolean PTR_BounceTraverse(intercept_t * in) -{ - line_t *li; - - if (!in->isaline) - I_Error("PTR_BounceTraverse: not a line?"); - - li = in->d.line; - if (!(li->flags & ML_TWOSIDED)) - { - if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) - return true; // don't hit the back side - goto bounceblocking; - } - - P_LineOpening(li); // set openrange, opentop, openbottom - if (openrange < slidemo->height) - goto bounceblocking; // doesn't fit - - if (opentop - slidemo->z < slidemo->height) - goto bounceblocking; // mobj is too high - return true; // this line doesn't block movement - -// the line does block movement, see if it is closer than best so far - bounceblocking: - if (in->frac < bestslidefrac) - { - secondslidefrac = bestslidefrac; - secondslideline = bestslideline; - bestslidefrac = in->frac; - bestslideline = li; - } - return false; // stop -} - -//============================================================================ -// -// P_BounceWall -// -//============================================================================ - -void P_BounceWall(mobj_t * mo) -{ - fixed_t leadx, leady; - int side; - angle_t lineangle, moveangle, deltaangle; - fixed_t movelen; - - slidemo = mo; - -// -// trace along the three leading corners -// - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - } - else - { - leadx = mo->x - mo->radius; - } - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - } - else - { - leady = mo->y - mo->radius; - } - bestslidefrac = FRACUNIT + 1; - P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, - PT_ADDLINES, PTR_BounceTraverse); - - // P_BounceWall call on a tall sector after fresh game start - // without the player sliding along any walls before. - // For more details check: - // https://github.com/chocolate-doom/chocolate-doom/issues/1732 - // https://github.com/chocolate-doom/chocolate-doom/issues/1160 - if (bestslideline == NULL) - { - I_Error("P_BounceWall: No bestslideline was set. Try bumping walls."); - } - - side = P_PointOnLineSide(mo->x, mo->y, bestslideline); - lineangle = R_PointToAngle2(0, 0, bestslideline->dx, bestslideline->dy); - if (side == 1) - lineangle += ANG180; - moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); - deltaangle = (2 * lineangle) - moveangle; -// if (deltaangle > ANG180) -// deltaangle += ANG180; -// I_Error ("SlideLine: ang>ANG180"); - - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance(mo->momx, mo->momy); - movelen = FixedMul(movelen, 0.75 * FRACUNIT); // friction - if (movelen < FRACUNIT) - movelen = 2 * FRACUNIT; - mo->momx = FixedMul(movelen, finecosine[deltaangle]); - mo->momy = FixedMul(movelen, finesine[deltaangle]); -} - - -/* -============================================================================== - - P_LineAttack - -============================================================================== -*/ - - -mobj_t *PuffSpawned; -mobj_t *linetarget; // who got hit (or NULL) -mobj_t *shootthing; -fixed_t shootz; // height if not aiming up or down - // ???: use slope for monsters? -int la_damage; -fixed_t attackrange; - -fixed_t aimslope; - - -/* -=============================================================================== -= -= PTR_AimTraverse -= -= Sets linetaget and aimslope when a target is aimed at -=============================================================================== -*/ - -boolean PTR_AimTraverse(intercept_t * in) -{ - line_t *li; - mobj_t *th; - fixed_t slope, thingtopslope, thingbottomslope; - fixed_t dist; - - if (in->isaline) - { - li = in->d.line; - if (!(li->flags & ML_TWOSIDED)) - return false; // stop -// -// crosses a two sided line -// a two sided line will restrict the possible target ranges - P_LineOpening(li); - - if (openbottom >= opentop) - return false; // stop - - dist = FixedMul(attackrange, in->frac); - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv(openbottom - shootz, dist); - if (slope > bottomslope) - bottomslope = slope; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv(opentop - shootz, dist); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - - return true; // shot continues - } - -// -// shoot a thing -// - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - if (!(th->flags & MF_SHOOTABLE)) - { // corpse or something - return true; - } - if (th->player && netgame && !deathmatch) - { // don't aim at fellow co-op players - return true; - } - -// check angles to see if the thing can be aimed at - - dist = FixedMul(attackrange, in->frac); - thingtopslope = FixedDiv(th->z + th->height - shootz, dist); - if (thingtopslope < bottomslope) - return true; // shot over the thing - thingbottomslope = FixedDiv(th->z - shootz, dist); - if (thingbottomslope > topslope) - return true; // shot under the thing - -// -// this thing can be hit! -// - if (thingtopslope > topslope) - thingtopslope = topslope; - if (thingbottomslope < bottomslope) - thingbottomslope = bottomslope; - - aimslope = (thingtopslope + thingbottomslope) / 2; - linetarget = th; - - return false; // don't go any farther -} - - -/* -============================================================================== -= -= PTR_ShootTraverse -= -============================================================================== -*/ - -boolean PTR_ShootTraverse(intercept_t * in) -{ - fixed_t x, y, z; - fixed_t frac; - line_t *li; - mobj_t *th; - fixed_t slope; - fixed_t dist; - fixed_t thingtopslope, thingbottomslope; - - if (in->isaline) - { - li = in->d.line; - if (li->special) - { - P_ActivateLine(li, shootthing, 0, SPAC_IMPACT); -// P_ShootSpecialLine (shootthing, li); - } - if (!(li->flags & ML_TWOSIDED)) - goto hitline; - -// -// crosses a two sided line -// - P_LineOpening(li); - - dist = FixedMul(attackrange, in->frac); - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv(openbottom - shootz, dist); - if (slope > aimslope) - goto hitline; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv(opentop - shootz, dist); - if (slope < aimslope) - goto hitline; - } - - return true; // shot continues -// -// hit line -// - hitline: - // position a bit closer - frac = in->frac - FixedDiv(4 * FRACUNIT, attackrange); - x = trace.x + FixedMul(trace.dx, frac); - y = trace.y + FixedMul(trace.dy, frac); - z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); - - if (li->frontsector->ceilingpic == skyflatnum) - { - if (z > li->frontsector->ceilingheight) - return false; // don't shoot the sky! - if (li->backsector && li->backsector->ceilingpic == skyflatnum) - return false; // it's a sky hack wall - } - - P_SpawnPuff(x, y, z); - return false; // don't go any farther - } - -// -// shoot a thing -// - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - if (!(th->flags & MF_SHOOTABLE)) - return true; // corpse or something - -// -// check for physical attacks on a ghost -// -/* FIX: Impliment Heretic 2 weapons here - if(th->flags&MF_SHADOW && shootthing->player->readyweapon == wp_staff) - { - return(true); - } -*/ - -// check angles to see if the thing can be aimed at - dist = FixedMul(attackrange, in->frac); - thingtopslope = FixedDiv(th->z + th->height - shootz, dist); - if (thingtopslope < aimslope) - return true; // shot over the thing - thingbottomslope = FixedDiv(th->z - shootz, dist); - if (thingbottomslope > aimslope) - return true; // shot under the thing - -// -// hit thing -// - // position a bit closer - frac = in->frac - FixedDiv(10 * FRACUNIT, attackrange); - x = trace.x + FixedMul(trace.dx, frac); - y = trace.y + FixedMul(trace.dy, frac); - z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); - P_SpawnPuff(x, y, z); - if (la_damage) - { - if (!(in->d.thing->flags & MF_NOBLOOD) && - !(in->d.thing->flags2 & MF2_INVULNERABLE)) - { - if (PuffType == MT_AXEPUFF || PuffType == MT_AXEPUFF_GLOW) - { - P_BloodSplatter2(x, y, z, in->d.thing); - } - if (P_Random() < 192) - { - P_BloodSplatter(x, y, z, in->d.thing); - } - } - if (PuffType == MT_FLAMEPUFF2) - { // Cleric FlameStrike does fire damage - P_DamageMobj(th, &LavaInflictor, shootthing, la_damage); - } - else - { - P_DamageMobj(th, shootthing, shootthing, la_damage); - } - } - return (false); // don't go any farther -} - -/* -================= -= -= P_AimLineAttack -= -================= -*/ - -fixed_t P_AimLineAttack(mobj_t * t1, angle_t angle, fixed_t distance) -{ - fixed_t x2, y2; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; - y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; - shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; - topslope = 100 * FRACUNIT / 160; // can't shoot outside view angles - bottomslope = -100 * FRACUNIT / 160; - attackrange = distance; - linetarget = NULL; - - P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, - PTR_AimTraverse); - - if (linetarget) - return aimslope; - return 0; -} - - - -/* -================= -= -= P_LineAttack -= -= if damage == 0, it is just a test trace that will leave linetarget set -= -================= -*/ - -void P_LineAttack(mobj_t * t1, angle_t angle, fixed_t distance, fixed_t slope, - int damage) -{ - fixed_t x2, y2; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - la_damage = damage; - x2 = t1->x + (distance >> FRACBITS) * finecosine[angle]; - y2 = t1->y + (distance >> FRACBITS) * finesine[angle]; - shootz = t1->z + (t1->height >> 1) + 8 * FRACUNIT; - shootz -= t1->floorclip; - attackrange = distance; - aimslope = slope; - - if (P_PathTraverse(t1->x, t1->y, x2, y2, PT_ADDLINES | PT_ADDTHINGS, - PTR_ShootTraverse)) - { - switch (PuffType) - { - case MT_PUNCHPUFF: - S_StartSound(t1, SFX_FIGHTER_PUNCH_MISS); - break; - case MT_HAMMERPUFF: - case MT_AXEPUFF: - case MT_AXEPUFF_GLOW: - S_StartSound(t1, SFX_FIGHTER_HAMMER_MISS); - break; - case MT_FLAMEPUFF: - P_SpawnPuff(x2, y2, shootz + FixedMul(slope, distance)); - break; - default: - break; - } - } -} - -/* -============================================================================== - - USE LINES - -============================================================================== -*/ - -mobj_t *usething; - -boolean PTR_UseTraverse(intercept_t * in) -{ - int sound; - fixed_t pheight; - - if (!in->d.line->special) - { - P_LineOpening(in->d.line); - if (openrange <= 0) - { - if (usething->player) - { - switch (usething->player->class) - { - case PCLASS_FIGHTER: - sound = SFX_PLAYER_FIGHTER_FAILED_USE; - break; - case PCLASS_CLERIC: - sound = SFX_PLAYER_CLERIC_FAILED_USE; - break; - case PCLASS_MAGE: - sound = SFX_PLAYER_MAGE_FAILED_USE; - break; - case PCLASS_PIG: - sound = SFX_PIG_ACTIVE1; - break; - default: - sound = SFX_NONE; - break; - } - S_StartSound(usething, sound); - } - return false; // can't use through a wall - } - if (usething->player) - { - pheight = usething->z + (usething->height / 2); - if ((opentop < pheight) || (openbottom > pheight)) - { - switch (usething->player->class) - { - case PCLASS_FIGHTER: - sound = SFX_PLAYER_FIGHTER_FAILED_USE; - break; - case PCLASS_CLERIC: - sound = SFX_PLAYER_CLERIC_FAILED_USE; - break; - case PCLASS_MAGE: - sound = SFX_PLAYER_MAGE_FAILED_USE; - break; - case PCLASS_PIG: - sound = SFX_PIG_ACTIVE1; - break; - default: - sound = SFX_NONE; - break; - } - S_StartSound(usething, sound); - } - } - return true; // not a special line, but keep checking - } - - if (P_PointOnLineSide(usething->x, usething->y, in->d.line) == 1) - return false; // don't use back sides - -// P_UseSpecialLine (usething, in->d.line); - P_ActivateLine(in->d.line, usething, 0, SPAC_USE); - - return false; // can't use for than one special line in a row -} - - -/* -================ -= -= P_UseLines -= -= Looks for special lines in front of the player to activate -================ -*/ - -void P_UseLines(player_t * player) -{ - int angle; - fixed_t x1, y1, x2, y2; - - usething = player->mo; - - angle = player->mo->angle >> ANGLETOFINESHIFT; - x1 = player->mo->x; - y1 = player->mo->y; - x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; - y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; - - P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse); -} - -//========================================================================== -// -// PTR_PuzzleItemTraverse -// -//========================================================================== - -#define USE_PUZZLE_ITEM_SPECIAL 129 - -static mobj_t *PuzzleItemUser; -static int PuzzleItemType; -static boolean PuzzleActivated; - -boolean PTR_PuzzleItemTraverse(intercept_t * in) -{ - mobj_t *mobj; - byte args[3]; - int sound; - - if (in->isaline) - { // Check line - if (in->d.line->special != USE_PUZZLE_ITEM_SPECIAL) - { - P_LineOpening(in->d.line); - if (openrange <= 0) - { - sound = SFX_NONE; - if (PuzzleItemUser->player) - { - switch (PuzzleItemUser->player->class) - { - case PCLASS_FIGHTER: - sound = SFX_PUZZLE_FAIL_FIGHTER; - break; - case PCLASS_CLERIC: - sound = SFX_PUZZLE_FAIL_CLERIC; - break; - case PCLASS_MAGE: - sound = SFX_PUZZLE_FAIL_MAGE; - break; - default: - sound = SFX_NONE; - break; - } - } - S_StartSound(PuzzleItemUser, sound); - return false; // can't use through a wall - } - return true; // Continue searching - } - if (P_PointOnLineSide(PuzzleItemUser->x, PuzzleItemUser->y, - in->d.line) == 1) - { // Don't use back sides - return false; - } - if (PuzzleItemType != in->d.line->arg1) - { // Item type doesn't match - return false; - } - - // Construct an args[] array that would contain the values from - // the line that would be passed by Vanilla Hexen. - args[0] = in->d.line->arg3; - args[1] = in->d.line->arg4; - args[2] = in->d.line->arg5; - - P_StartACS(in->d.line->arg2, 0, args, PuzzleItemUser, in->d.line, 0); - in->d.line->special = 0; - PuzzleActivated = true; - return false; // Stop searching - } - // Check thing - mobj = in->d.thing; - if (mobj->special != USE_PUZZLE_ITEM_SPECIAL) - { // Wrong special - return true; - } - if (PuzzleItemType != mobj->args[0]) - { // Item type doesn't match - return true; - } - - P_StartACS(mobj->args[1], 0, &mobj->args[2], PuzzleItemUser, NULL, 0); - mobj->special = 0; - PuzzleActivated = true; - return false; // Stop searching -} - -//========================================================================== -// -// P_UsePuzzleItem -// -// Returns true if the puzzle item was used on a line or a thing. -// -//========================================================================== - -boolean P_UsePuzzleItem(player_t * player, int itemType) -{ - int angle; - fixed_t x1, y1, x2, y2; - - PuzzleItemType = itemType; - PuzzleItemUser = player->mo; - PuzzleActivated = false; - angle = player->mo->angle >> ANGLETOFINESHIFT; - x1 = player->mo->x; - y1 = player->mo->y; - x2 = x1 + (USERANGE >> FRACBITS) * finecosine[angle]; - y2 = y1 + (USERANGE >> FRACBITS) * finesine[angle]; - P_PathTraverse(x1, y1, x2, y2, PT_ADDLINES | PT_ADDTHINGS, - PTR_PuzzleItemTraverse); - return PuzzleActivated; -} - -/* -============================================================================== - - RADIUS ATTACK - -============================================================================== -*/ - -mobj_t *bombsource; -mobj_t *bombspot; -int bombdamage; -int bombdistance; -boolean DamageSource; - -/* -================= -= -= PIT_RadiusAttack -= -= Source is the creature that casued the explosion at spot -================= -*/ - -boolean PIT_RadiusAttack(mobj_t * thing) -{ - fixed_t dx, dy, dist; - int damage; - - if (!(thing->flags & MF_SHOOTABLE)) - { - return true; - } -// if(thing->flags2&MF2_BOSS) -// { // Bosses take no damage from PIT_RadiusAttack -// return(true); -// } - if (!DamageSource && thing == bombsource) - { // don't damage the source of the explosion - return true; - } - if (abs((thing->z - bombspot->z) >> FRACBITS) > 2 * bombdistance) - { // too high/low - return true; - } - dx = abs(thing->x - bombspot->x); - dy = abs(thing->y - bombspot->y); - dist = dx > dy ? dx : dy; - dist = (dist - thing->radius) >> FRACBITS; - if (dist < 0) - { - dist = 0; - } - if (dist >= bombdistance) - { // Out of range - return true; - } - if (P_CheckSight(thing, bombspot)) - { // OK to damage, target is in direct path - damage = (bombdamage * (bombdistance - dist) / bombdistance) + 1; - if (thing->player) - { - damage >>= 2; - } - P_DamageMobj(thing, bombspot, bombsource, damage); - } - return (true); -} - -/* -================= -= -= P_RadiusAttack -= -= Source is the creature that caused the explosion at spot -================= -*/ - -void P_RadiusAttack(mobj_t * spot, mobj_t * source, int damage, int distance, - boolean damageSource) -{ - int x, y, xl, xh, yl, yh; - fixed_t dist; - - dist = (distance + MAXRADIUS) << FRACBITS; - yh = (spot->y + dist - bmaporgy) >> MAPBLOCKSHIFT; - yl = (spot->y - dist - bmaporgy) >> MAPBLOCKSHIFT; - xh = (spot->x + dist - bmaporgx) >> MAPBLOCKSHIFT; - xl = (spot->x - dist - bmaporgx) >> MAPBLOCKSHIFT; - bombspot = spot; - bombsource = source; - bombdamage = damage; - bombdistance = distance; - DamageSource = damageSource; - for (y = yl; y <= yh; y++) - { - for (x = xl; x <= xh; x++) - { - P_BlockThingsIterator(x, y, PIT_RadiusAttack); - } - } -} - -/* -============================================================================== - - SECTOR HEIGHT CHANGING - -= After modifying a sectors floor or ceiling height, call this -= routine to adjust the positions of all things that touch the -= sector. -= -= If anything doesn't fit anymore, true will be returned. -= If crunch is true, they will take damage as they are being crushed -= If Crunch is false, you should set the sector height back the way it -= was and call P_ChangeSector again to undo the changes -============================================================================== -*/ - -int crushchange; -boolean nofit; - -/* -=============== -= -= PIT_ChangeSector -= -=============== -*/ - -boolean PIT_ChangeSector(mobj_t * thing) -{ - mobj_t *mo; - - if (P_ThingHeightClip(thing)) - return true; // keep checking - - // crunch bodies to giblets - if ((thing->flags & MF_CORPSE) && (thing->health <= 0)) - { - if (thing->flags & MF_NOBLOOD) - { - P_RemoveMobj(thing); - } - else - { - if (thing->state != &states[S_GIBS1]) - { - P_SetMobjState(thing, S_GIBS1); - thing->height = 0; - thing->radius = 0; - S_StartSound(thing, SFX_PLAYER_FALLING_SPLAT); - } - } - return true; // keep checking - } - - // crunch dropped items - if (thing->flags2 & MF2_DROPPED) - { - P_RemoveMobj(thing); - return true; // keep checking - } - - if (!(thing->flags & MF_SHOOTABLE)) - return true; // assume it is bloody gibs or something - - nofit = true; - if (crushchange && !(leveltime & 3)) - { - P_DamageMobj(thing, NULL, NULL, crushchange); - // spray blood in a random direction - if ((!(thing->flags & MF_NOBLOOD)) && - (!(thing->flags2 & MF2_INVULNERABLE))) - { - mo = P_SpawnMobj(thing->x, thing->y, thing->z + thing->height / 2, - MT_BLOOD); - mo->momx = P_SubRandom() << 12; - mo->momy = P_SubRandom() << 12; - } - } - - return true; // keep checking (crush other things) -} - -/* -=============== -= -= P_ChangeSector -= -=============== -*/ - -boolean P_ChangeSector(sector_t * sector, int crunch) -{ - int x, y; - - nofit = false; - crushchange = crunch; - -// recheck heights for all things near the moving sector - - for (x = sector->blockbox[BOXLEFT]; x <= sector->blockbox[BOXRIGHT]; x++) - for (y = sector->blockbox[BOXBOTTOM]; y <= sector->blockbox[BOXTOP]; - y++) - P_BlockThingsIterator(x, y, PIT_ChangeSector); - - - return nofit; -} diff --git a/games/NXDoom/src/hexen/p_maputl.c b/games/NXDoom/src/hexen/p_maputl.c deleted file mode 100644 index 1ed0aa968e3..00000000000 --- a/games/NXDoom/src/hexen/p_maputl.c +++ /dev/null @@ -1,1072 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "m_bbox.h" -#include "m_misc.h" -#include "p_local.h" - -static mobj_t *RoughBlockCheck(mobj_t * mo, int index); - -/* -=================== -= -= P_AproxDistance -= -= Gives an estimation of distance (not exact) -= -=================== -*/ - -fixed_t P_AproxDistance(fixed_t dx, fixed_t dy) -{ - dx = abs(dx); - dy = abs(dy); - if (dx < dy) - return dx + dy - (dx >> 1); - return dx + dy - (dy >> 1); -} - - -/* -================== -= -= P_PointOnLineSide -= -= Returns 0 or 1 -================== -*/ - -int P_PointOnLineSide(fixed_t x, fixed_t y, line_t * line) -{ - fixed_t dx, dy; - fixed_t left, right; - - if (!line->dx) - { - if (x <= line->v1->x) - return line->dy > 0; - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->v1->y) - return line->dx < 0; - return line->dx > 0; - } - - dx = (x - line->v1->x); - dy = (y - line->v1->y); - - left = FixedMul(line->dy >> FRACBITS, dx); - right = FixedMul(dy, line->dx >> FRACBITS); - - if (right < left) - return 0; // front side - return 1; // back side -} - - -/* -================= -= -= P_BoxOnLineSide -= -= Considers the line to be infinite -= Returns side 0 or 1, -1 if box crosses the line -================= -*/ - -int P_BoxOnLineSide(fixed_t * tmbox, line_t * ld) -{ - int p1 = 0, p2 = 0; - - switch (ld->slopetype) - { - case ST_HORIZONTAL: - p1 = tmbox[BOXTOP] > ld->v1->y; - p2 = tmbox[BOXBOTTOM] > ld->v1->y; - if (ld->dx < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - case ST_VERTICAL: - p1 = tmbox[BOXRIGHT] < ld->v1->x; - p2 = tmbox[BOXLEFT] < ld->v1->x; - if (ld->dy < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - case ST_POSITIVE: - p1 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); - break; - case ST_NEGATIVE: - p1 = P_PointOnLineSide(tmbox[BOXRIGHT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide(tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); - break; - } - - if (p1 == p2) - return p1; - return -1; -} - -/* -================== -= -= P_PointOnDivlineSide -= -= Returns 0 or 1 -================== -*/ - -int P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t * line) -{ - fixed_t dx, dy; - fixed_t left, right; - - if (!line->dx) - { - if (x <= line->x) - return line->dy > 0; - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->y) - return line->dx < 0; - return line->dx > 0; - } - - dx = (x - line->x); - dy = (y - line->y); - -// try to quickly decide by looking at sign bits - if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000) - { - if ((line->dy ^ dx) & 0x80000000) - return 1; // (left is negative) - return 0; - } - - left = FixedMul(line->dy >> 8, dx >> 8); - right = FixedMul(dy >> 8, line->dx >> 8); - - if (right < left) - return 0; // front side - return 1; // back side -} - - - -/* -============== -= -= P_MakeDivline -= -============== -*/ - -void P_MakeDivline(line_t * li, divline_t * dl) -{ - dl->x = li->v1->x; - dl->y = li->v1->y; - dl->dx = li->dx; - dl->dy = li->dy; -} - - -/* -=============== -= -= P_InterceptVector -= -= Returns the fractional intercept point along the first divline -= -= This is only called by the addthings and addlines traversers -=============== -*/ - -fixed_t P_InterceptVector(divline_t * v2, divline_t * v1) -{ -#if 1 - fixed_t frac, num, den; - - den = FixedMul(v1->dy >> 8, v2->dx) - FixedMul(v1->dx >> 8, v2->dy); - if (den == 0) - return 0; -// I_Error ("P_InterceptVector: parallel"); - num = FixedMul((v1->x - v2->x) >> 8, v1->dy) + - FixedMul((v2->y - v1->y) >> 8, v1->dx); - frac = FixedDiv(num, den); - - return frac; -#else - float frac, num, den, v1x, v1y, v1dx, v1dy, v2x, v2y, v2dx, v2dy; - - v1x = (float) v1->x / FRACUNIT; - v1y = (float) v1->y / FRACUNIT; - v1dx = (float) v1->dx / FRACUNIT; - v1dy = (float) v1->dy / FRACUNIT; - v2x = (float) v2->x / FRACUNIT; - v2y = (float) v2->y / FRACUNIT; - v2dx = (float) v2->dx / FRACUNIT; - v2dy = (float) v2->dy / FRACUNIT; - - den = v1dy * v2dx - v1dx * v2dy; - if (den == 0) - return 0; // parallel - num = (v1x - v2x) * v1dy + (v2y - v1y) * v1dx; - frac = num / den; - - return frac * FRACUNIT; -#endif -} - -/* -================== -= -= P_LineOpening -= -= Sets opentop and openbottom to the window through a two sided line -= OPTIMIZE: keep this precalculated -================== -*/ - -fixed_t opentop, openbottom, openrange; -fixed_t lowfloor; - -void P_LineOpening(line_t * linedef) -{ - sector_t *front, *back; - - if (linedef->sidenum[1] == -1) - { // single sided line - openrange = 0; - return; - } - - front = linedef->frontsector; - back = linedef->backsector; - - if (front->ceilingheight < back->ceilingheight) - opentop = front->ceilingheight; - else - opentop = back->ceilingheight; - if (front->floorheight > back->floorheight) - { - openbottom = front->floorheight; - lowfloor = back->floorheight; - tmfloorpic = front->floorpic; - } - else - { - openbottom = back->floorheight; - lowfloor = front->floorheight; - tmfloorpic = back->floorpic; - } - - openrange = opentop - openbottom; -} - -/* -=============================================================================== - - THING POSITION SETTING - -=============================================================================== -*/ - -/* -=================== -= -= P_UnsetThingPosition -= -= Unlinks a thing from block map and sectors -= -=================== -*/ - -void P_UnsetThingPosition(mobj_t * thing) -{ - int blockx, blocky; - - if (!(thing->flags & MF_NOSECTOR)) - { // inert things don't need to be in blockmap -// unlink from subsector - if (thing->snext) - thing->snext->sprev = thing->sprev; - if (thing->sprev) - thing->sprev->snext = thing->snext; - else - thing->subsector->sector->thinglist = thing->snext; - } - - if (!(thing->flags & MF_NOBLOCKMAP)) - { // inert things don't need to be in blockmap -// unlink from block map - if (thing->bnext) - thing->bnext->bprev = thing->bprev; - if (thing->bprev) - thing->bprev->bnext = thing->bnext; - else - { - blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; - if (blockx >= 0 && blockx < bmapwidth - && blocky >= 0 && blocky < bmapheight) - blocklinks[blocky * bmapwidth + blockx] = thing->bnext; - } - } -} - - -/* -=================== -= -= P_SetThingPosition -= -= Links a thing into both a block and a subsector based on it's x y -= Sets thing->subsector properly -= -=================== -*/ - -void P_SetThingPosition(mobj_t * thing) -{ - subsector_t *ss; - sector_t *sec; - int blockx, blocky; - mobj_t **link; - -// -// link into subsector -// - ss = R_PointInSubsector(thing->x, thing->y); - thing->subsector = ss; - if (!(thing->flags & MF_NOSECTOR)) - { // invisible things don't go into the sector links - sec = ss->sector; - - thing->sprev = NULL; - thing->snext = sec->thinglist; - if (sec->thinglist) - sec->thinglist->sprev = thing; - sec->thinglist = thing; - } - -// -// link into blockmap -// - if (!(thing->flags & MF_NOBLOCKMAP)) - { // inert things don't need to be in blockmap - blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; - if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 - && blocky < bmapheight) - { - link = &blocklinks[blocky * bmapwidth + blockx]; - thing->bprev = NULL; - thing->bnext = *link; - if (*link) - (*link)->bprev = thing; - *link = thing; - } - else - { // thing is off the map - thing->bnext = thing->bprev = NULL; - } - } -} - - - -/* -=============================================================================== - - BLOCK MAP ITERATORS - -For each line/thing in the given mapblock, call the passed function. -If the function returns false, exit with false without checking anything else. - -=============================================================================== -*/ - -/* -================== -= -= P_BlockLinesIterator -= -= The validcount flags are used to avoid checking lines -= that are marked in multiple mapblocks, so increment validcount before -= the first call to P_BlockLinesIterator, then make one or more calls to it -=================== -*/ - -boolean P_BlockLinesIterator(int x, int y, boolean(*func) (line_t *)) -{ - int offset; - short *list; - line_t *ld; - - int i; - polyblock_t *polyLink; - seg_t **tempSeg; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - return true; - offset = y * bmapwidth + x; - - polyLink = PolyBlockMap[offset]; - while (polyLink) - { - if (polyLink->polyobj) - { - if (polyLink->polyobj->validcount != validcount) - { - polyLink->polyobj->validcount = validcount; - tempSeg = polyLink->polyobj->segs; - for (i = 0; i < polyLink->polyobj->numsegs; i++, tempSeg++) - { - if ((*tempSeg)->linedef->validcount == validcount) - { - continue; - } - (*tempSeg)->linedef->validcount = validcount; - if (!func((*tempSeg)->linedef)) - { - return false; - } - } - } - } - polyLink = polyLink->next; - } - - offset = *(blockmap + offset); - - for (list = blockmaplump + offset; *list != -1; list++) - { - ld = &lines[*list]; - if (ld->validcount == validcount) - continue; // line has already been checked - ld->validcount = validcount; - - if (!func(ld)) - return false; - } - - return true; // everything was checked -} - - -/* -================== -= -= P_BlockThingsIterator -= -================== -*/ - -boolean P_BlockThingsIterator(int x, int y, boolean(*func) (mobj_t *)) -{ - mobj_t *mobj; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - return true; - - LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); - - for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext) - if (!func(mobj)) - return false; - - return true; -} - -/* -=============================================================================== - - INTERCEPT ROUTINES - -=============================================================================== -*/ - -intercept_t intercepts[MAXINTERCEPTS], *intercept_p; - -divline_t trace; -boolean earlyout; -int ptflags; - -/* -================== -= -= PIT_AddLineIntercepts -= -= Looks for lines in the given block that intercept the given trace -= to add to the intercepts list -= A line is crossed if its endpoints are on opposite sides of the trace -= Returns true if earlyout and a solid line hit -================== -*/ - -boolean PIT_AddLineIntercepts(line_t * ld) -{ - int s1, s2; - fixed_t frac; - divline_t dl; - -// avoid precision problems with two routines - if (trace.dx > FRACUNIT * 16 || trace.dy > FRACUNIT * 16 - || trace.dx < -FRACUNIT * 16 || trace.dy < -FRACUNIT * 16) - { - s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); - } - else - { - s1 = P_PointOnLineSide(trace.x, trace.y, ld); - s2 = P_PointOnLineSide(trace.x + trace.dx, trace.y + trace.dy, ld); - } - if (s1 == s2) - return true; // line isn't crossed - -// -// hit the line -// - P_MakeDivline(ld, &dl); - frac = P_InterceptVector(&trace, &dl); - if (frac < 0) - return true; // behind source - -// try to early out the check - if (earlyout && frac < FRACUNIT && !ld->backsector) - return false; // stop checking - - intercept_p->frac = frac; - intercept_p->isaline = true; - intercept_p->d.line = ld; - intercept_p++; - - return true; // continue -} - - - -/* -================== -= -= PIT_AddThingIntercepts -= -================== -*/ - -boolean PIT_AddThingIntercepts(mobj_t * thing) -{ - fixed_t x1, y1, x2, y2; - int s1, s2; - boolean tracepositive; - divline_t dl; - fixed_t frac; - - tracepositive = (trace.dx ^ trace.dy) > 0; - - // check a corner to corner crossection for hit - - if (tracepositive) - { - x1 = thing->x - thing->radius; - y1 = thing->y + thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y - thing->radius; - } - else - { - x1 = thing->x - thing->radius; - y1 = thing->y - thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y + thing->radius; - } - s1 = P_PointOnDivlineSide(x1, y1, &trace); - s2 = P_PointOnDivlineSide(x2, y2, &trace); - if (s1 == s2) - return true; // line isn't crossed - - dl.x = x1; - dl.y = y1; - dl.dx = x2 - x1; - dl.dy = y2 - y1; - frac = P_InterceptVector(&trace, &dl); - if (frac < 0) - return true; // behind source - intercept_p->frac = frac; - intercept_p->isaline = false; - intercept_p->d.thing = thing; - intercept_p++; - - return true; // keep going -} - - -/* -==================== -= -= P_TraverseIntercepts -= -= Returns true if the traverser function returns true for all lines -==================== -*/ - -boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) -{ - int count; - fixed_t dist; - intercept_t *scan, *in; - - count = intercept_p - intercepts; - in = 0; // shut up compiler warning - - while (count--) - { - dist = INT_MAX; - for (scan = intercepts; scan < intercept_p; scan++) - if (scan->frac < dist) - { - dist = scan->frac; - in = scan; - } - - if (dist > maxfrac) - return true; // checked everything in range -#if 0 - { // don't check these yet, ther may be others inserted - in = scan = intercepts; - for (scan = intercepts; scan < intercept_p; scan++) - if (scan->frac > maxfrac) - *in++ = *scan; - intercept_p = in; - return false; - } -#endif - - if (!func(in)) - return false; // don't bother going farther - in->frac = INT_MAX; - } - - return true; // everything was traversed -} - - - -/* -================== -= -= P_PathTraverse -= -= Traces a line from x1,y1 to x2,y2, calling the traverser function for each -= Returns true if the traverser function returns true for all lines -================== -*/ - -boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, - int flags, boolean(*trav) (intercept_t *)) -{ - fixed_t xt1, yt1, xt2, yt2; - fixed_t xstep, ystep; - fixed_t partial; - fixed_t xintercept, yintercept; - int mapx, mapy, mapxstep, mapystep; - int count; - - earlyout = (flags & PT_EARLYOUT) != 0; - - validcount++; - intercept_p = intercepts; - - if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) - x1 += FRACUNIT; // don't side exactly on a line - if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) - y1 += FRACUNIT; // don't side exactly on a line - trace.x = x1; - trace.y = y1; - trace.dx = x2 - x1; - trace.dy = y2 - y1; - - x1 -= bmaporgx; - y1 -= bmaporgy; - xt1 = x1 >> MAPBLOCKSHIFT; - yt1 = y1 >> MAPBLOCKSHIFT; - - x2 -= bmaporgx; - y2 -= bmaporgy; - xt2 = x2 >> MAPBLOCKSHIFT; - yt2 = y2 >> MAPBLOCKSHIFT; - - if (xt2 > xt1) - { - mapxstep = 1; - partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else if (xt2 < xt1) - { - mapxstep = -1; - partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else - { - mapxstep = 0; - partial = FRACUNIT; - ystep = 256 * FRACUNIT; - } - yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); - - - if (yt2 > yt1) - { - mapystep = 1; - partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else - { - mapystep = 0; - partial = FRACUNIT; - xstep = 256 * FRACUNIT; - } - xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); - - -// -// step through map blocks -// Count is present to prevent a round off error from skipping the break - mapx = xt1; - mapy = yt1; - - for (count = 0; count < 64; count++) - { - if (flags & PT_ADDLINES) - { - if (!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts)) - return false; // early out - } - if (flags & PT_ADDTHINGS) - { - if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts)) - return false; // early out - } - - if (mapx == xt2 && mapy == yt2) - break; - - if ((yintercept >> FRACBITS) == mapy) - { - yintercept += ystep; - mapx += mapxstep; - } - else if ((xintercept >> FRACBITS) == mapx) - { - xintercept += xstep; - mapy += mapystep; - } - - } - - -// -// go through the sorted list -// - return P_TraverseIntercepts(trav, FRACUNIT); -} - -//=========================================================================== -// -// P_RoughMonsterSearch -// -// Searches though the surrounding mapblocks for monsters/players -// distance is in MAPBLOCKUNITS -//=========================================================================== - -mobj_t *P_RoughMonsterSearch(mobj_t * mo, int distance) -{ - int blockX; - int blockY; - int startX, startY; - int blockIndex; - int firstStop; - int secondStop; - int thirdStop; - int finalStop; - int count; - mobj_t *target; - - startX = (mo->x - bmaporgx) >> MAPBLOCKSHIFT; - startY = (mo->y - bmaporgy) >> MAPBLOCKSHIFT; - - if (startX >= 0 && startX < bmapwidth && startY >= 0 - && startY < bmapheight) - { - target = RoughBlockCheck(mo, startY * bmapwidth + startX); - if (target != NULL) - { // found a target right away - return target; - } - } - for (count = 1; count <= distance; count++) - { - blockX = startX - count; - blockY = startY - count; - - if (blockY < 0) - { - blockY = 0; - } - else if (blockY >= bmapheight) - { - blockY = bmapheight - 1; - } - if (blockX < 0) - { - blockX = 0; - } - else if (blockX >= bmapwidth) - { - blockX = bmapwidth - 1; - } - blockIndex = blockY * bmapwidth + blockX; - firstStop = startX + count; - if (firstStop < 0) - { - continue; - } - if (firstStop >= bmapwidth) - { - firstStop = bmapwidth - 1; - } - secondStop = startY + count; - if (secondStop < 0) - { - continue; - } - if (secondStop >= bmapheight) - { - secondStop = bmapheight - 1; - } - thirdStop = secondStop * bmapwidth + blockX; - secondStop = secondStop * bmapwidth + firstStop; - firstStop += blockY * bmapwidth; - finalStop = blockIndex; - - // Trace the first block section (along the top) - for (; blockIndex <= firstStop; blockIndex++) - { - target = RoughBlockCheck(mo, blockIndex); - if (target != NULL) - { - return target; - } - } - // Trace the second block section (right edge) - for (blockIndex--; blockIndex <= secondStop; blockIndex += bmapwidth) - { - target = RoughBlockCheck(mo, blockIndex); - if (target != NULL) - { - return target; - } - } - // Trace the third block section (bottom edge) - for (blockIndex -= bmapwidth; blockIndex >= thirdStop; blockIndex--) - { - target = RoughBlockCheck(mo, blockIndex); - if (target != NULL) - { - return target; - } - } - // Trace the final block section (left edge) - for (blockIndex++; blockIndex > finalStop; blockIndex -= bmapwidth) - { - target = RoughBlockCheck(mo, blockIndex); - if (target != NULL) - { - return target; - } - } - } - return NULL; -} - -//=========================================================================== -// -// RoughBlockCheck -// -//=========================================================================== - -static mobj_t *RoughBlockCheck(mobj_t * mo, int index) -{ - mobj_t *link; - mobj_t *master; - angle_t angle; - - link = blocklinks[index]; - while (link) - { - if (mo->player) // Minotaur looking around player - { - if ((link->flags & MF_COUNTKILL) || - (link->player && (link != mo))) - { - if (!(link->flags & MF_SHOOTABLE)) - { - link = link->bnext; - continue; - } - if (link->flags2 & MF2_DORMANT) - { - link = link->bnext; - continue; - } - if ((link->type == MT_MINOTAUR) && - (link->special1.m == mo)) - { - link = link->bnext; - continue; - } - if (netgame && !deathmatch && link->player) - { - link = link->bnext; - continue; - } - if (P_CheckSight(mo, link)) - { - return link; - } - } - link = link->bnext; - } - else if (mo->type == MT_MINOTAUR) // looking around minotaur - { - master = mo->special1.m; - if ((link->flags & MF_COUNTKILL) || - (link->player && (link != master))) - { - if (!(link->flags & MF_SHOOTABLE)) - { - link = link->bnext; - continue; - } - if (link->flags2 & MF2_DORMANT) - { - link = link->bnext; - continue; - } - if ((link->type == MT_MINOTAUR) && - (link->special1.m == mo->special1.m)) - { - link = link->bnext; - continue; - } - if (netgame && !deathmatch && link->player) - { - link = link->bnext; - continue; - } - if (P_CheckSight(mo, link)) - { - return link; - } - } - link = link->bnext; - } - else if (mo->type == MT_MSTAFF_FX2) // bloodscourge - { - if ((link->flags & MF_COUNTKILL || - (link->player && link != mo->target)) - && !(link->flags2 & MF2_DORMANT)) - { - if (!(link->flags & MF_SHOOTABLE)) - { - link = link->bnext; - continue; - } - if (netgame && !deathmatch && link->player) - { - link = link->bnext; - continue; - } - else if (P_CheckSight(mo, link)) - { - master = mo->target; - angle = R_PointToAngle2(master->x, master->y, - link->x, link->y) - master->angle; - angle >>= 24; - if (angle > 226 || angle < 30) - { - return link; - } - } - } - link = link->bnext; - } - else // spirits - { - if ((link->flags & MF_COUNTKILL || - (link->player && link != mo->target)) - && !(link->flags2 & MF2_DORMANT)) - { - if (!(link->flags & MF_SHOOTABLE)) - { - link = link->bnext; - continue; - } - if (netgame && !deathmatch && link->player) - { - link = link->bnext; - continue; - } - if (link == mo->target) - { - link = link->bnext; - continue; - } - else if (P_CheckSight(mo, link)) - { - return link; - } - } - link = link->bnext; - } - } - return NULL; -} diff --git a/games/NXDoom/src/hexen/p_mobj.c b/games/NXDoom/src/hexen/p_mobj.c deleted file mode 100644 index 0c302ed14fe..00000000000 --- a/games/NXDoom/src/hexen/p_mobj.c +++ /dev/null @@ -1,2469 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" -#include "sounds.h" - -// MACROS ------------------------------------------------------------------ - -#define MAX_TID_COUNT 200 - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -void G_PlayerReborn(int player); -void P_MarkAsLeaving(mobj_t * corpse); - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -void P_SpawnMapThing(mapthing_t * mthing); - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void PlayerLandedOnThing(mobj_t * mo, mobj_t * onmobj); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -mobjtype_t PuffType; -mobj_t *MissileMobj; - -fixed_t FloatBobOffsets[64] = { - 0, 51389, 102283, 152192, - 200636, 247147, 291278, 332604, - 370727, 405280, 435929, 462380, - 484378, 501712, 514213, 521763, - 524287, 521763, 514213, 501712, - 484378, 462380, 435929, 405280, - 370727, 332604, 291278, 247147, - 200636, 152192, 102283, 51389, - -1, -51390, -102284, -152193, - -200637, -247148, -291279, -332605, - -370728, -405281, -435930, -462381, - -484380, -501713, -514215, -521764, - -524288, -521764, -514214, -501713, - -484379, -462381, -435930, -405280, - -370728, -332605, -291279, -247148, - -200637, -152193, -102284, -51389 -}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int TIDList[MAX_TID_COUNT + 1]; // +1 for termination marker -static mobj_t *TIDMobj[MAX_TID_COUNT]; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// P_SetMobjState -// -// Returns true if the mobj is still present. -// -//========================================================================== - -boolean P_SetMobjState(mobj_t * mobj, statenum_t state) -{ - state_t *st; - - if (state == S_NULL) - { // Remove mobj - mobj->state = (state_t *) S_NULL; - P_RemoveMobj(mobj); - return (false); - } - st = &states[state]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - if (st->action) - { // Call action function - st->action(mobj, NULL, NULL); - } - return (true); -} - -//========================================================================== -// -// P_SetMobjStateNF -// -// Same as P_SetMobjState, but does not call the state function. -// -//========================================================================== - -boolean P_SetMobjStateNF(mobj_t * mobj, statenum_t state) -{ - state_t *st; - - if (state == S_NULL) - { // Remove mobj - mobj->state = (state_t *) S_NULL; - P_RemoveMobj(mobj); - return (false); - } - st = &states[state]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC P_ExplodeMissile -// -//---------------------------------------------------------------------------- - -void P_ExplodeMissile(mobj_t * mo) -{ - mo->momx = mo->momy = mo->momz = 0; - P_SetMobjState(mo, mobjinfo[mo->type].deathstate); - //mo->tics -= P_Random()&3; - mo->flags &= ~MF_MISSILE; - - switch (mo->type) - { - case MT_SORCBALL1: - case MT_SORCBALL2: - case MT_SORCBALL3: - S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE); - break; - case MT_SORCFX1: - S_StartSound(NULL, SFX_SORCERER_HEADSCREAM); - break; - default: - if (mo->info->deathsound) - { - S_StartSound(mo, mo->info->deathsound); - } - break; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_FloorBounceMissile -// -//---------------------------------------------------------------------------- - -void P_FloorBounceMissile(mobj_t * mo) -{ - if (P_HitFloor(mo) >= FLOOR_LIQUID) - { - switch (mo->type) - { - case MT_SORCFX1: - case MT_SORCBALL1: - case MT_SORCBALL2: - case MT_SORCBALL3: - break; - default: - P_RemoveMobj(mo); - return; - } - } - switch (mo->type) - { - case MT_SORCFX1: - mo->momz = -mo->momz; // no energy absorbed - break; - case MT_SGSHARD1: - case MT_SGSHARD2: - case MT_SGSHARD3: - case MT_SGSHARD4: - case MT_SGSHARD5: - case MT_SGSHARD6: - case MT_SGSHARD7: - case MT_SGSHARD8: - case MT_SGSHARD9: - case MT_SGSHARD0: - mo->momz = FixedMul(mo->momz, -0.3 * FRACUNIT); - if (abs(mo->momz) < (FRACUNIT / 2)) - { - P_SetMobjState(mo, S_NULL); - return; - } - break; - default: - mo->momz = FixedMul(mo->momz, -0.7 * FRACUNIT); - break; - } - mo->momx = 2 * mo->momx / 3; - mo->momy = 2 * mo->momy / 3; - if (mo->info->seesound) - { - switch (mo->type) - { - case MT_SORCBALL1: - case MT_SORCBALL2: - case MT_SORCBALL3: - if (!mo->args[0]) - S_StartSound(mo, mo->info->seesound); - break; - default: - S_StartSound(mo, mo->info->seesound); - break; - } - S_StartSound(mo, mo->info->seesound); - } -// P_SetMobjState(mo, mobjinfo[mo->type].deathstate); -} - -//---------------------------------------------------------------------------- -// -// PROC P_ThrustMobj -// -//---------------------------------------------------------------------------- - -void P_ThrustMobj(mobj_t * mo, angle_t angle, fixed_t move) -{ - angle >>= ANGLETOFINESHIFT; - mo->momx += FixedMul(move, finecosine[angle]); - mo->momy += FixedMul(move, finesine[angle]); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_FaceMobj -// -// Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs -// to turn counter clockwise. 'delta' is set to the amount 'source' -// needs to turn. -// -//---------------------------------------------------------------------------- - -int P_FaceMobj(mobj_t * source, mobj_t * target, angle_t * delta) -{ - angle_t diff; - angle_t angle1; - angle_t angle2; - - angle1 = source->angle; - angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y); - if (angle2 > angle1) - { - diff = angle2 - angle1; - if (diff > ANG180) - { - *delta = ANG_MAX - diff; - return (0); - } - else - { - *delta = diff; - return (1); - } - } - else - { - diff = angle1 - angle2; - if (diff > ANG180) - { - *delta = ANG_MAX - diff; - return (1); - } - else - { - *delta = diff; - return (0); - } - } -} - -//---------------------------------------------------------------------------- -// -// -// The missile special1 field must be mobj_t *target. Returns true if -// target was tracked, false if not. -// -//---------------------------------------------------------------------------- - -boolean P_SeekerMissile(mobj_t * actor, angle_t thresh, angle_t turnMax) -{ - int dir; - int dist; - angle_t delta; - angle_t angle; - mobj_t *target; - - target = actor->special1.m; - if (target == NULL) - { - return (false); - } - if (!(target->flags & MF_SHOOTABLE)) - { // Target died - actor->special1.m = NULL; - return (false); - } - dir = P_FaceMobj(actor, target, &delta); - if (delta > thresh) - { - delta >>= 1; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->angle += delta; - } - else - { // Turn counter clockwise - actor->angle -= delta; - } - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(actor->info->speed, finecosine[angle]); - actor->momy = FixedMul(actor->info->speed, finesine[angle]); - if (actor->z + actor->height < target->z - || target->z + target->height < actor->z) - { // Need to seek vertically - dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); - dist = dist / actor->info->speed; - if (dist < 1) - { - dist = 1; - } - actor->momz = (target->z + (target->height >> 1) - - (actor->z + (actor->height >> 1))) / dist; - } - return (true); -} - -//---------------------------------------------------------------------------- -// -// PROC P_XYMovement -// -//---------------------------------------------------------------------------- - -#define STOPSPEED 0x1000 -#define FRICTION_NORMAL 0xe800 -#define FRICTION_LOW 0xf900 -#define FRICTION_FLY 0xeb00 - -void P_XYMovement(mobj_t * mo) -{ - fixed_t ptryx, ptryy; - player_t *player; - fixed_t xmove, ymove; - int special; - angle_t angle; - static int windTab[3] = { 2048 * 5, 2048 * 10, 2048 * 25 }; - - if (!mo->momx && !mo->momy) - { - if (mo->flags & MF_SKULLFLY) - { // A flying mobj slammed into something - mo->flags &= ~MF_SKULLFLY; - mo->momx = mo->momy = mo->momz = 0; - P_SetMobjState(mo, mo->info->seestate); - } - return; - } - special = mo->subsector->sector->special; - if (mo->flags2 & MF2_WINDTHRUST) - { - switch (special) - { - case 40: - case 41: - case 42: // Wind_East - P_ThrustMobj(mo, 0, windTab[special - 40]); - break; - case 43: - case 44: - case 45: // Wind_North - P_ThrustMobj(mo, ANG90, windTab[special - 43]); - break; - case 46: - case 47: - case 48: // Wind_South - P_ThrustMobj(mo, ANG270, windTab[special - 46]); - break; - case 49: - case 50: - case 51: // Wind_West - P_ThrustMobj(mo, ANG180, windTab[special - 49]); - break; - } - } - player = mo->player; - if (mo->momx > MAXMOVE) - { - mo->momx = MAXMOVE; - } - else if (mo->momx < -MAXMOVE) - { - mo->momx = -MAXMOVE; - } - if (mo->momy > MAXMOVE) - { - mo->momy = MAXMOVE; - } - else if (mo->momy < -MAXMOVE) - { - mo->momy = -MAXMOVE; - } - xmove = mo->momx; - ymove = mo->momy; - do - { - if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2) - { - ptryx = mo->x + xmove / 2; - ptryy = mo->y + ymove / 2; - xmove >>= 1; - ymove >>= 1; - } - else - { - ptryx = mo->x + xmove; - ptryy = mo->y + ymove; - xmove = ymove = 0; - } - if (!P_TryMove(mo, ptryx, ptryy)) - { // Blocked move - if (mo->flags2 & MF2_SLIDE) - { // Try to slide along it - if (BlockingMobj == NULL) - { // Slide against wall - P_SlideMove(mo); - } - else - { // Slide against mobj - //if(P_TryMove(mo, mo->x, mo->y+mo->momy)) - if (P_TryMove(mo, mo->x, ptryy)) - { - mo->momx = 0; - } - //else if(P_TryMove(mo, mo->x+mo->momx, mo->y)) - else if (P_TryMove(mo, ptryx, mo->y)) - { - mo->momy = 0; - } - else - { - mo->momx = mo->momy = 0; - } - } - } - else if (mo->flags & MF_MISSILE) - { - if (mo->flags2 & MF2_FLOORBOUNCE) - { - if (BlockingMobj) - { - if ((BlockingMobj->flags2 & MF2_REFLECTIVE) || - ((!BlockingMobj->player) && - (!(BlockingMobj->flags & MF_COUNTKILL)))) - { - fixed_t speed; - - angle = R_PointToAngle2(BlockingMobj->x, - BlockingMobj->y, mo->x, - mo->y) + - ANG1 * ((P_Random() % 16) - 8); - speed = P_AproxDistance(mo->momx, mo->momy); - speed = FixedMul(speed, 0.75 * FRACUNIT); - mo->angle = angle; - angle >>= ANGLETOFINESHIFT; - mo->momx = FixedMul(speed, finecosine[angle]); - mo->momy = FixedMul(speed, finesine[angle]); - if (mo->info->seesound) - { - S_StartSound(mo, mo->info->seesound); - } - return; - } - else - { // Struck a player/creature - P_ExplodeMissile(mo); - } - } - else - { // Struck a wall - P_BounceWall(mo); - switch (mo->type) - { - case MT_SORCBALL1: - case MT_SORCBALL2: - case MT_SORCBALL3: - case MT_SORCFX1: - break; - default: - if (mo->info->seesound) - { - S_StartSound(mo, mo->info->seesound); - } - break; - } - return; - } - } - if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE)) - { - angle = R_PointToAngle2(BlockingMobj->x, - BlockingMobj->y, mo->x, mo->y); - - // Change angle for delflection/reflection - switch (BlockingMobj->type) - { - case MT_CENTAUR: - case MT_CENTAURLEADER: - if (abs((int) angle - (int) BlockingMobj->angle) >> 24 > 45) - goto explode; - if (mo->type == MT_HOLY_FX) - goto explode; - // Drop through to sorcerer full reflection - case MT_SORCBOSS: - // Deflection - if (P_Random() < 128) - angle += ANG45; - else - angle -= ANG45; - break; - default: - // Reflection - angle += ANG1 * ((P_Random() % 16) - 8); - break; - } - - // Reflect the missile along angle - mo->angle = angle; - angle >>= ANGLETOFINESHIFT; - mo->momx = - FixedMul(mo->info->speed >> 1, finecosine[angle]); - mo->momy = - FixedMul(mo->info->speed >> 1, finesine[angle]); -// mo->momz = -mo->momz; - if (mo->flags2 & MF2_SEEKERMISSILE) - { - mo->special1.m = mo->target; - } - mo->target = BlockingMobj; - return; - } - explode: - // Explode a missile - if (ceilingline && ceilingline->backsector - && ceilingline->backsector->ceilingpic == skyflatnum) - { // Hack to prevent missiles exploding against the sky - if (mo->type == MT_BLOODYSKULL) - { - mo->momx = mo->momy = 0; - mo->momz = -FRACUNIT; - } - else if (mo->type == MT_HOLY_FX) - { - P_ExplodeMissile(mo); - } - else - { - P_RemoveMobj(mo); - } - return; - } - P_ExplodeMissile(mo); - } - //else if(mo->info->crashstate) - //{ - // mo->momx = mo->momy = 0; - // P_SetMobjState(mo, mo->info->crashstate); - // return; - //} - else - { - mo->momx = mo->momy = 0; - } - } - } - while (xmove || ymove); - - // Friction - - if (player && player->cheats & CF_NOMOMENTUM) - { // Debug option for no sliding at all - mo->momx = mo->momy = 0; - return; - } - if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) - { // No friction for missiles - return; - } - if (mo->z > mo->floorz && !(mo->flags2 & MF2_FLY) - && !(mo->flags2 & MF2_ONMOBJ)) - { // No friction when falling - if (mo->type != MT_BLASTEFFECT) - return; - } - if (mo->flags & MF_CORPSE) - { // Don't stop sliding if halfway off a step with some momentum - if (mo->momx > FRACUNIT / 4 || mo->momx < -FRACUNIT / 4 - || mo->momy > FRACUNIT / 4 || mo->momy < -FRACUNIT / 4) - { - if (mo->floorz != mo->subsector->sector->floorheight) - { - return; - } - } - } - if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED - && mo->momy > -STOPSPEED && mo->momy < STOPSPEED - && (!player || (player->cmd.forwardmove == 0 - && player->cmd.sidemove == 0))) - { // If in a walking frame, stop moving - if (player) - { - if ((unsigned) ((player->mo->state - states) - - PStateRun[player->class]) < 4) - { - P_SetMobjState(player->mo, PStateNormal[player->class]); - } - } - mo->momx = 0; - mo->momy = 0; - } - else - { - if (mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) - && !(mo->flags2 & MF2_ONMOBJ)) - { - mo->momx = FixedMul(mo->momx, FRICTION_FLY); - mo->momy = FixedMul(mo->momy, FRICTION_FLY); - } - else if (P_GetThingFloorType(mo) == FLOOR_ICE) - { - mo->momx = FixedMul(mo->momx, FRICTION_LOW); - mo->momy = FixedMul(mo->momy, FRICTION_LOW); - } - else - { - mo->momx = FixedMul(mo->momx, FRICTION_NORMAL); - mo->momy = FixedMul(mo->momy, FRICTION_NORMAL); - } - } -} - - -// Move this to p_inter *** -void P_MonsterFallingDamage(mobj_t * mo) -{ - int damage; - int mom; - - mom = abs(mo->momz); - if (mom > 35 * FRACUNIT) - { // automatic death - damage = 10000; - } - else - { - damage = ((mom - (23 * FRACUNIT)) * 6) >> FRACBITS; - } - damage = 10000; // always kill 'em - P_DamageMobj(mo, NULL, NULL, damage); -} - - - -/* -=============== -= -= P_ZMovement -= -=============== -*/ - -void P_ZMovement(mobj_t * mo) -{ - int dist; - int delta; -// -// check for smooth step up -// - if (mo->player && mo->z < mo->floorz) - { - mo->player->viewheight -= mo->floorz - mo->z; - mo->player->deltaviewheight = - (VIEWHEIGHT - mo->player->viewheight) >> 3; - } -// -// adjust height -// - mo->z += mo->momz; - if (mo->flags & MF_FLOAT && mo->target) - { // float down towards target if too close - if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) - { - dist = - P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); - delta = (mo->target->z + (mo->height >> 1)) - mo->z; - if (delta < 0 && dist < -(delta * 3)) - mo->z -= FLOATSPEED; - else if (delta > 0 && dist < (delta * 3)) - mo->z += FLOATSPEED; - } - } - if (mo->player && mo->flags2 & MF2_FLY && !(mo->z <= mo->floorz) - && leveltime & 2) - { - mo->z += finesine[(FINEANGLES / 20 * leveltime >> 2) & FINEMASK]; - } - -// -// clip movement -// - if (mo->z <= mo->floorz) - { // Hit the floor - if (mo->flags & MF_MISSILE) - { - mo->z = mo->floorz; - if (mo->flags2 & MF2_FLOORBOUNCE) - { - P_FloorBounceMissile(mo); - return; - } - else if (mo->type == MT_HOLY_FX) - { // The spirit struck the ground - mo->momz = 0; - P_HitFloor(mo); - return; - } - else if (mo->type == MT_MNTRFX2 || mo->type == MT_LIGHTNING_FLOOR) - { // Minotaur floor fire can go up steps - return; - } - else - { - P_HitFloor(mo); - P_ExplodeMissile(mo); - return; - } - } - if (mo->flags & MF_COUNTKILL) // Blasted mobj falling - { - if (mo->momz < -(23 * FRACUNIT)) - { - P_MonsterFallingDamage(mo); - } - } - if (mo->z - mo->momz > mo->floorz) - { // Spawn splashes, etc. - P_HitFloor(mo); - } - mo->z = mo->floorz; - if (mo->momz < 0) - { - if (mo->flags2 & MF2_ICEDAMAGE && mo->momz < -GRAVITY * 8) - { - mo->tics = 1; - mo->momx = 0; - mo->momy = 0; - mo->momz = 0; - return; - } - if (mo->player) - { - mo->player->jumpTics = 7; // delay any jumping for a short time - if (mo->momz < -GRAVITY * 8 && !(mo->flags2 & MF2_FLY)) - { // squat down - mo->player->deltaviewheight = mo->momz >> 3; - if (mo->momz < -23 * FRACUNIT) - { - P_FallingDamage(mo->player); - P_NoiseAlert(mo, mo); - } - else if (mo->momz < -GRAVITY * 12 - && !mo->player->morphTics) - { - S_StartSound(mo, SFX_PLAYER_LAND); - switch (mo->player->class) - { - case PCLASS_FIGHTER: - S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT); - break; - case PCLASS_CLERIC: - S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT); - break; - case PCLASS_MAGE: - S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT); - break; - default: - break; - } - } - else if ((P_GetThingFloorType(mo) < FLOOR_LIQUID) && - (!mo->player->morphTics)) - { - S_StartSound(mo, SFX_PLAYER_LAND); - } - // haleyjd: removed externdriver crap - mo->player->centering = true; - } - } - else if (mo->type >= MT_POTTERY1 && mo->type <= MT_POTTERY3) - { - P_DamageMobj(mo, NULL, NULL, 25); - } - else if (mo->flags & MF_COUNTKILL) - { - if (mo->momz < -23 * FRACUNIT) - { - // Doesn't get here - } - } - mo->momz = 0; - } - if (mo->flags & MF_SKULLFLY) - { // The skull slammed into something - mo->momz = -mo->momz; - } - if (mo->info->crashstate && - (mo->flags & MF_CORPSE) && !(mo->flags2 & MF2_ICEDAMAGE)) - { - P_SetMobjState(mo, mo->info->crashstate); - return; - } - } - else if (mo->flags2 & MF2_LOGRAV) - { - if (mo->momz == 0) - mo->momz = -(GRAVITY >> 3) * 2; - else - mo->momz -= GRAVITY >> 3; - } - else if (!(mo->flags & MF_NOGRAVITY)) - { - if (mo->momz == 0) - mo->momz = -GRAVITY * 2; - else - mo->momz -= GRAVITY; - } - - if (mo->z + mo->height > mo->ceilingz) - { // hit the ceiling - if (mo->momz > 0) - mo->momz = 0; - mo->z = mo->ceilingz - mo->height; - if (mo->flags2 & MF2_FLOORBOUNCE) - { - // Maybe reverse momentum here for ceiling bounce - // Currently won't happen - - if (mo->info->seesound) - { - S_StartSound(mo, mo->info->seesound); - } - return; - } - if (mo->flags & MF_SKULLFLY) - { // the skull slammed into something - mo->momz = -mo->momz; - } - if (mo->flags & MF_MISSILE) - { - if (mo->type == MT_LIGHTNING_CEILING) - { - return; - } - if (mo->subsector->sector->ceilingpic == skyflatnum) - { - if (mo->type == MT_BLOODYSKULL) - { - mo->momx = mo->momy = 0; - mo->momz = -FRACUNIT; - } - else if (mo->type == MT_HOLY_FX) - { - P_ExplodeMissile(mo); - } - else - { - P_RemoveMobj(mo); - } - return; - } - P_ExplodeMissile(mo); - return; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_BlasterMobjThinker -// -// -//---------------------------------------------------------------------------- - -void P_BlasterMobjThinker(thinker_t *thinker) -{ - mobj_t *mobj = (mobj_t *) thinker; - int i; - fixed_t xfrac; - fixed_t yfrac; - fixed_t zfrac; - fixed_t z; - boolean changexy; - mobj_t *mo; - - // Handle movement - if (mobj->momx || mobj->momy || (mobj->z != mobj->floorz) || mobj->momz) - { - xfrac = mobj->momx >> 3; - yfrac = mobj->momy >> 3; - zfrac = mobj->momz >> 3; - changexy = xfrac || yfrac; - for (i = 0; i < 8; i++) - { - if (changexy) - { - if (!P_TryMove(mobj, mobj->x + xfrac, mobj->y + yfrac)) - { // Blocked move - P_ExplodeMissile(mobj); - return; - } - } - mobj->z += zfrac; - if (mobj->z <= mobj->floorz) - { // Hit the floor - mobj->z = mobj->floorz; - P_HitFloor(mobj); - P_ExplodeMissile(mobj); - return; - } - if (mobj->z + mobj->height > mobj->ceilingz) - { // Hit the ceiling - mobj->z = mobj->ceilingz - mobj->height; - P_ExplodeMissile(mobj); - return; - } - if (changexy) - { - if (mobj->type == MT_MWAND_MISSILE && (P_Random() < 128)) - { - z = mobj->z - 8 * FRACUNIT; - if (z < mobj->floorz) - { - z = mobj->floorz; - } - P_SpawnMobj(mobj->x, mobj->y, z, MT_MWANDSMOKE); - } - else if (!--mobj->special1.i) - { - mobj->special1.i = 4; - z = mobj->z - 12 * FRACUNIT; - if (z < mobj->floorz) - { - z = mobj->floorz; - } - mo = P_SpawnMobj(mobj->x, mobj->y, z, MT_CFLAMEFLOOR); - if (mo) - { - mo->angle = mobj->angle; - } - } - } - } - } - // Advance the state - if (mobj->tics != -1) - { - mobj->tics--; - while (!mobj->tics) - { - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - { // mobj was removed - return; - } - } - } -} - -//=========================================================================== -// -// PlayerLandedOnThing -// -//=========================================================================== - -static void PlayerLandedOnThing(mobj_t * mo, mobj_t * onmobj) -{ - mo->player->deltaviewheight = mo->momz >> 3; - if (mo->momz < -23 * FRACUNIT) - { - P_FallingDamage(mo->player); - P_NoiseAlert(mo, mo); - } - else if (mo->momz < -GRAVITY * 12 && !mo->player->morphTics) - { - S_StartSound(mo, SFX_PLAYER_LAND); - switch (mo->player->class) - { - case PCLASS_FIGHTER: - S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT); - break; - case PCLASS_CLERIC: - S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT); - break; - case PCLASS_MAGE: - S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT); - break; - default: - break; - } - } - else if (!mo->player->morphTics) - { - S_StartSound(mo, SFX_PLAYER_LAND); - } - // haleyjd: removed externdriver crap - mo->player->centering = true; -} - -//---------------------------------------------------------------------------- -// -// PROC P_MobjThinker -// -//---------------------------------------------------------------------------- - -void P_MobjThinker(thinker_t *thinker) -{ - mobj_t *mobj = (mobj_t *) thinker; - mobj_t *onmo; -/* - // Reset to not blasted when momentums are gone - if((mobj->flags2&MF2_BLASTED) && (!(mobj->momx)) && (!(mobj->momy))) - ResetBlasted(mobj); -*/ - // Handle X and Y momentums - BlockingMobj = NULL; - if (mobj->momx || mobj->momy || (mobj->flags & MF_SKULLFLY)) - { - P_XYMovement(mobj); - if (mobj->thinker.function == (think_t) - 1) - { // mobj was removed - return; - } - } - else if (mobj->flags2 & MF2_BLASTED) - { // Reset to not blasted when momentums are gone - ResetBlasted(mobj); - } - if (mobj->flags2 & MF2_FLOATBOB) - { // Floating item bobbing motion (special1 is height) - mobj->z = mobj->floorz + - mobj->special1.i + FloatBobOffsets[(mobj->health++) & 63]; - } - else if ((mobj->z != mobj->floorz) || mobj->momz || BlockingMobj) - { // Handle Z momentum and gravity - if (mobj->flags2 & MF2_PASSMOBJ) - { - if (!(onmo = P_CheckOnmobj(mobj))) - { - P_ZMovement(mobj); - if (mobj->player && mobj->flags & MF2_ONMOBJ) - { - mobj->flags2 &= ~MF2_ONMOBJ; - } - } - else - { - if (mobj->player) - { - if (mobj->momz < -GRAVITY * 8 - && !(mobj->flags2 & MF2_FLY)) - { - PlayerLandedOnThing(mobj, onmo); - } - if (onmo->z + onmo->height - mobj->z <= 24 * FRACUNIT) - { - mobj->player->viewheight -= onmo->z + onmo->height - - mobj->z; - mobj->player->deltaviewheight = - (VIEWHEIGHT - mobj->player->viewheight) >> 3; - mobj->z = onmo->z + onmo->height; - mobj->flags2 |= MF2_ONMOBJ; - mobj->momz = 0; - } - else - { // hit the bottom of the blocking mobj - mobj->momz = 0; - } - } -/* Landing on another player, and mimicking his movements - if(mobj->player && onmo->player) - { - mobj->momx = onmo->momx; - mobj->momy = onmo->momy; - if(onmo->z < onmo->floorz) - { - mobj->z += onmo->floorz-onmo->z; - if(onmo->player) - { - onmo->player->viewheight -= onmo->floorz-onmo->z; - onmo->player->deltaviewheight = (VIEWHEIGHT- - onmo->player->viewheight)>>3; - } - onmo->z = onmo->floorz; - } - } -*/ - } - } - else - { - P_ZMovement(mobj); - } - if (mobj->thinker.function == (think_t) - 1) - { // mobj was removed - return; - } - } - - // Cycle through states, calling action functions at transitions - if (mobj->tics != -1) - { - mobj->tics--; - // you can cycle through multiple states in a tic - while (!mobj->tics) - { - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - { // mobj was removed - return; - } - } - } -} - -//========================================================================== -// -// P_SpawnMobj -// -//========================================================================== - -mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) -{ - mobj_t *mobj; - state_t *st; - mobjinfo_t *info; - fixed_t space; - - mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL); - memset(mobj, 0, sizeof(*mobj)); - info = &mobjinfo[type]; - mobj->type = type; - mobj->info = info; - mobj->x = x; - mobj->y = y; - mobj->radius = info->radius; - mobj->height = info->height; - mobj->flags = info->flags; - mobj->flags2 = info->flags2; - mobj->damage = info->damage; - mobj->health = info->spawnhealth; - if (gameskill != sk_nightmare) - { - mobj->reactiontime = info->reactiontime; - } - mobj->lastlook = P_Random() % maxplayers; - - // Set the state, but do not use P_SetMobjState, because action - // routines can't be called yet. If the spawnstate has an action - // routine, it will not be called. - st = &states[info->spawnstate]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - - // Set subsector and/or block links. - P_SetThingPosition(mobj); - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - if (z == ONFLOORZ) - { - mobj->z = mobj->floorz; - } - else if (z == ONCEILINGZ) - { - mobj->z = mobj->ceilingz - mobj->info->height; - } - else if (z == FLOATRANDZ) - { - space = ((mobj->ceilingz) - (mobj->info->height)) - mobj->floorz; - if (space > 48 * FRACUNIT) - { - space -= 40 * FRACUNIT; - mobj->z = - ((space * P_Random()) >> 8) + mobj->floorz + 40 * FRACUNIT; - } - else - { - mobj->z = mobj->floorz; - } - } - else if (mobj->flags2 & MF2_FLOATBOB) - { - mobj->z = mobj->floorz + z; // artifact z passed in as height - } - else - { - mobj->z = z; - } - if (mobj->flags2 & MF2_FLOORCLIP - && P_GetThingFloorType(mobj) >= FLOOR_LIQUID - && mobj->z == mobj->subsector->sector->floorheight) - { - mobj->floorclip = 10 * FRACUNIT; - } - else - { - mobj->floorclip = 0; - } - - mobj->thinker.function = P_MobjThinker; - P_AddThinker(&mobj->thinker); - return (mobj); -} - -//========================================================================== -// -// P_RemoveMobj -// -//========================================================================== - -void P_RemoveMobj(mobj_t * mobj) -{ - // Remove from creature queue - if (mobj->flags & MF_COUNTKILL && mobj->flags & MF_CORPSE) - { - A_DeQueueCorpse(mobj); - } - - if (mobj->tid) - { // Remove from TID list - P_RemoveMobjFromTIDList(mobj); - } - - // Unlink from sector and block lists - P_UnsetThingPosition(mobj); - - // Stop any playing sound - S_StopSound(mobj); - - // Free block - P_RemoveThinker((thinker_t *) mobj); -} - -//========================================================================== -// -// P_SpawnPlayer -// -// Called when a player is spawned on the level. Most of the player -// structure stays unchanged between levels. -// -//========================================================================== - -void P_SpawnPlayer(mapthing_t * mthing) -{ - player_t *p; - fixed_t x, y, z; - mobj_t *mobj; - - if (mthing->type - 1 >= maxplayers || !playeringame[mthing->type - 1]) - { // Not playing - return; - } - - p = &players[mthing->type - 1]; - if (p->playerstate == PST_REBORN) - { - G_PlayerReborn(mthing->type - 1); - } - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - z = ONFLOORZ; - if (randomclass && deathmatch) - { - p->class = P_Random() % 3; - if (p->class == PlayerClass[mthing->type - 1]) - { - p->class = (p->class + 1) % 3; - } - PlayerClass[mthing->type - 1] = p->class; - SB_SetClassData(); - } - else - { - p->class = PlayerClass[mthing->type - 1]; - } - switch (p->class) - { - case PCLASS_FIGHTER: - mobj = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER); - break; - case PCLASS_CLERIC: - mobj = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC); - break; - case PCLASS_MAGE: - mobj = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE); - break; - default: - I_Error("P_SpawnPlayer: Unknown class type"); - return; - } - - // Set translation table data - if (p->class == PCLASS_FIGHTER - && (mthing->type == 1 || mthing->type == 3)) - { - // The first type should be blue, and the third should be the - // Fighter's original gold color - if (mthing->type == 1) - { - mobj->flags |= 2 << MF_TRANSSHIFT; - } - } - else if (mthing->type > 1) - { // Set color translation bits for player sprites - mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT; - } - - mobj->angle = ANG45 * (mthing->angle / 45); - mobj->player = p; - mobj->health = p->health; - p->mo = mobj; - p->playerstate = PST_LIVE; - p->refire = 0; - P_ClearMessage(p); - p->damagecount = 0; - p->bonuscount = 0; - p->poisoncount = 0; - p->morphTics = 0; - p->extralight = 0; - p->fixedcolormap = 0; - p->viewheight = VIEWHEIGHT; - P_SetupPsprites(p); - if (deathmatch) - { // Give all keys in death match mode - p->keys = 2047; - } -} - -//========================================================================== -// -// P_SpawnMapThing -// -// The fields of the mapthing should already be in host byte order. -// -//========================================================================== - -void P_SpawnMapThing(mapthing_t * mthing) -{ - int i; - unsigned int spawnMask; - mobj_t *mobj; - fixed_t x, y, z; - static unsigned int classFlags[] = { - MTF_FIGHTER, - MTF_CLERIC, - MTF_MAGE - }; - - // Count deathmatch start positions - if (mthing->type == 11) - { - if (deathmatch_p < &deathmatchstarts[MAXDEATHMATCHSTARTS]) - { - memcpy(deathmatch_p, mthing, sizeof(*mthing)); - deathmatch_p++; - } - return; - } - if (mthing->type == PO_ANCHOR_TYPE) - { // Polyobj Anchor Pt. - return; - } - else if (mthing->type == PO_SPAWN_TYPE - || mthing->type == PO_SPAWNCRUSH_TYPE) - { // Polyobj Anchor Pt. - po_NumPolyobjs++; - return; - } - - // Check for player starts 1 to 4 - if (mthing->type <= 4) - { - playerstarts[mthing->arg1][mthing->type - 1] = *mthing; - if (!deathmatch && !mthing->arg1) - { - P_SpawnPlayer(mthing); - } - return; - } - // Check for player starts 5 to 8 - if (mthing->type >= 9100 && mthing->type <= 9103) - { - mapthing_t *player_start; - int player; - - player = 4 + mthing->type - 9100; - - player_start = &playerstarts[mthing->arg1][player]; - memcpy(player_start, mthing, sizeof(mapthing_t)); - player_start->type = player + 1; - - if (!deathmatch && !player_start->arg1) - { - P_SpawnPlayer(player_start); - } - return; - } - - if (mthing->type >= 1400 && mthing->type < 1410) - { - R_PointInSubsector(mthing->x << FRACBITS, - mthing->y << FRACBITS)->sector->seqType = - mthing->type - 1400; - return; - } - - // Check current game type with spawn flags - if (netgame == false) - { - spawnMask = MTF_GSINGLE; - } - else if (deathmatch) - { - spawnMask = MTF_GDEATHMATCH; - } - else - { - spawnMask = MTF_GCOOP; - } - if (!(mthing->options & spawnMask)) - { - return; - } - - // Check current skill with spawn flags - if (gameskill == sk_baby || gameskill == sk_easy) - { - spawnMask = MTF_EASY; - } - else if (gameskill == sk_hard || gameskill == sk_nightmare) - { - spawnMask = MTF_HARD; - } - else - { - spawnMask = MTF_NORMAL; - } - if (!(mthing->options & spawnMask)) - { - return; - } - - // Check current character classes with spawn flags - if (netgame == false) - { // Single player - if ((mthing->options & classFlags[PlayerClass[0]]) == 0) - { // Not for current class - return; - } - } - else if (deathmatch == false) - { // Cooperative - spawnMask = 0; - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - spawnMask |= classFlags[PlayerClass[i]]; - } - } - if ((mthing->options & spawnMask) == 0) - { - return; - } - } - - // Find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - { - if (mthing->type == mobjinfo[i].doomednum) - { - break; - } - } - - if (i == NUMMOBJTYPES) - { // Can't find thing type - I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)", - mthing->type, mthing->x, mthing->y); - } - - // Don't spawn keys and players in deathmatch - if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) - { - return; - } - - // Don't spawn monsters if -nomonsters - if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) - { - return; - } - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - if (mobjinfo[i].flags & MF_SPAWNCEILING) - { - z = ONCEILINGZ; - } - else if (mobjinfo[i].flags2 & MF2_SPAWNFLOAT) - { - z = FLOATRANDZ; - } - else if (mobjinfo[i].flags2 & MF2_FLOATBOB) - { - z = mthing->height << FRACBITS; - } - else - { - z = ONFLOORZ; - } - switch (i) - { // Special stuff - case MT_ZLYNCHED_NOHEART: - P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODPOOL); - break; - default: - break; - } - mobj = P_SpawnMobj(x, y, z, i); - if (z == ONFLOORZ) - { - mobj->z += mthing->height << FRACBITS; - } - else if (z == ONCEILINGZ) - { - mobj->z -= mthing->height << FRACBITS; - } - mobj->tid = mthing->tid; - mobj->special = mthing->special; - mobj->args[0] = mthing->arg1; - mobj->args[1] = mthing->arg2; - mobj->args[2] = mthing->arg3; - mobj->args[3] = mthing->arg4; - mobj->args[4] = mthing->arg5; - if (mobj->flags2 & MF2_FLOATBOB) - { // Seed random starting index for bobbing motion - mobj->health = P_Random(); - mobj->special1.i = mthing->height << FRACBITS; - } - if (mobj->tics > 0) - { - mobj->tics = 1 + (P_Random() % mobj->tics); - } -// if(mobj->flags&MF_COUNTITEM) -// { -// totalitems++; -// } - if (mobj->flags & MF_COUNTKILL) - { - // Quantize angle to 45 degree increments - mobj->angle = ANG45 * (mthing->angle / 45); - } - else - { - // Scale angle correctly (source is 0..359) - mobj->angle = ((mthing->angle << 8) / 360) << 24; - } - if (mthing->options & MTF_AMBUSH) - { - mobj->flags |= MF_AMBUSH; - } - if (mthing->options & MTF_DORMANT) - { - mobj->flags2 |= MF2_DORMANT; - if (mobj->type == MT_ICEGUY) - { - P_SetMobjState(mobj, S_ICEGUY_DORMANT); - } - mobj->tics = -1; - } -} - -//========================================================================== -// -// P_CreateTIDList -// -//========================================================================== - -void P_CreateTIDList(void) -{ - int i; - mobj_t *mobj; - thinker_t *t; - - i = 0; - for (t = thinkercap.next; t != &thinkercap; t = t->next) - { // Search all current thinkers - if (t->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mobj = (mobj_t *) t; - if (mobj->tid != 0) - { // Add to list - if (i == MAX_TID_COUNT) - { - I_Error("P_CreateTIDList: MAX_TID_COUNT (%d) exceeded.", - MAX_TID_COUNT); - } - TIDList[i] = mobj->tid; - TIDMobj[i++] = mobj; - } - } - // Add termination marker - TIDList[i] = 0; -} - -//========================================================================== -// -// P_InsertMobjIntoTIDList -// -//========================================================================== - -void P_InsertMobjIntoTIDList(mobj_t * mobj, int tid) -{ - int i; - int index; - - index = -1; - for (i = 0; TIDList[i] != 0; i++) - { - if (TIDList[i] == -1) - { // Found empty slot - index = i; - break; - } - } - if (index == -1) - { // Append required - if (i == MAX_TID_COUNT) - { - I_Error("P_InsertMobjIntoTIDList: MAX_TID_COUNT (%d)" - "exceeded.", MAX_TID_COUNT); - } - index = i; - TIDList[index + 1] = 0; - } - mobj->tid = tid; - TIDList[index] = tid; - TIDMobj[index] = mobj; -} - -//========================================================================== -// -// P_RemoveMobjFromTIDList -// -//========================================================================== - -void P_RemoveMobjFromTIDList(mobj_t * mobj) -{ - int i; - - for (i = 0; TIDList[i] != 0; i++) - { - if (TIDMobj[i] == mobj) - { - TIDList[i] = -1; - TIDMobj[i] = NULL; - mobj->tid = 0; - return; - } - } - mobj->tid = 0; -} - -//========================================================================== -// -// P_FindMobjFromTID -// -//========================================================================== - -mobj_t *P_FindMobjFromTID(int tid, int *searchPosition) -{ - int i; - - for (i = *searchPosition + 1; TIDList[i] != 0; i++) - { - if (TIDList[i] == tid) - { - *searchPosition = i; - return TIDMobj[i]; - } - } - *searchPosition = -1; - return NULL; -} - -/* -=============================================================================== - - GAME SPAWN FUNCTIONS - -=============================================================================== -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_SpawnPuff -// -//--------------------------------------------------------------------------- - - -void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z) -{ - mobj_t *puff; - - z += (P_SubRandom() << 10); - puff = P_SpawnMobj(x, y, z, PuffType); - if (linetarget && puff->info->seesound) - { // Hit thing sound - S_StartSound(puff, puff->info->seesound); - } - else if (puff->info->attacksound) - { - S_StartSound(puff, puff->info->attacksound); - } - switch (PuffType) - { - case MT_PUNCHPUFF: - puff->momz = FRACUNIT; - break; - case MT_HAMMERPUFF: - puff->momz = .8 * FRACUNIT; - break; - default: - break; - } - PuffSpawned = puff; -} - -/* -================ -= -= P_SpawnBlood -= -================ -*/ - -/* -void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) -{ - mobj_t *th; - - z += (P_SubRandom()<<10); - th = P_SpawnMobj (x,y,z, MT_BLOOD); - th->momz = FRACUNIT*2; - th->tics -= P_Random()&3; - - if (damage <= 12 && damage >= 9) - P_SetMobjState (th,S_BLOOD2); - else if (damage < 9) - P_SetMobjState (th,S_BLOOD3); -} -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_BloodSplatter -// -//--------------------------------------------------------------------------- - -void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator) -{ - mobj_t *mo; - - mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER); - mo->target = originator; - mo->momx = P_SubRandom() << 10; - mo->momy = P_SubRandom() << 10; - mo->momz = 3 * FRACUNIT; -} - -//=========================================================================== -// -// P_BloodSplatter2 -// -//=========================================================================== - -void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator) -{ - mobj_t *mo; - int r1, r2; - - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(x + ((r2 - 128) << 11), - y + ((r1 - 128) << 11), z, MT_AXEBLOOD); - mo->target = originator; -} - -//--------------------------------------------------------------------------- -// -// PROC P_RipperBlood -// -//--------------------------------------------------------------------------- - -void P_RipperBlood(mobj_t * mo) -{ - mobj_t *th; - fixed_t x, y, z; - - x = mo->x + (P_SubRandom() << 12); - y = mo->y + (P_SubRandom() << 12); - z = mo->z + (P_SubRandom() << 12); - th = P_SpawnMobj(x, y, z, MT_BLOOD); -// th->flags |= MF_NOGRAVITY; - th->momx = mo->momx >> 1; - th->momy = mo->momy >> 1; - th->tics += P_Random() & 3; -} - -//--------------------------------------------------------------------------- -// -// FUNC P_GetThingFloorType -// -//--------------------------------------------------------------------------- - -int P_GetThingFloorType(mobj_t * thing) -{ - if (thing->floorpic) - { - return (TerrainTypes[thing->floorpic]); - } - else - { - return (TerrainTypes[thing->subsector->sector->floorpic]); - } -/* - if(thing->subsector->sector->floorpic - == W_GetNumForName("FLTWAWA1")-firstflat) - { - return(FLOOR_WATER); - } - else - { - return(FLOOR_SOLID); - } -*/ -} - -//--------------------------------------------------------------------------- -// -// FUNC P_HitFloor -// -//--------------------------------------------------------------------------- -#define SMALLSPLASHCLIP 12<floorz != thing->subsector->sector->floorheight) - { // don't splash if landing on the edge above water/lava/etc.... - return (FLOOR_SOLID); - } - - // Things that don't splash go here - switch (thing->type) - { - case MT_LEAF1: - case MT_LEAF2: -// case MT_BLOOD: // I set these to low mass -- pm -// case MT_BLOODSPLATTER: - case MT_SPLASH: - case MT_SLUDGECHUNK: - return (FLOOR_SOLID); - default: - break; - } - - // Small splash for small masses - if (thing->info->mass < 10) - smallsplash = true; - - switch (P_GetThingFloorType(thing)) - { - case FLOOR_WATER: - if (smallsplash) - { - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE); - if (mo) - mo->floorclip += SMALLSPLASHCLIP; - S_StartSound(mo, SFX_AMBIENT10); // small drip - } - else - { - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH); - mo->target = thing; - mo->momx = P_SubRandom() << 8; - mo->momy = P_SubRandom() << 8; - mo->momz = 2 * FRACUNIT + (P_Random() << 8); - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE); - if (thing->player) - P_NoiseAlert(thing, thing); - S_StartSound(mo, SFX_WATER_SPLASH); - } - return (FLOOR_WATER); - case FLOOR_LAVA: - if (smallsplash) - { - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH); - if (mo) - mo->floorclip += SMALLSPLASHCLIP; - } - else - { - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE); - mo->momz = FRACUNIT + (P_Random() << 7); - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH); - if (thing->player) - P_NoiseAlert(thing, thing); - } - S_StartSound(mo, SFX_LAVA_SIZZLE); - if (thing->player && leveltime & 31) - { - P_DamageMobj(thing, &LavaInflictor, NULL, 5); - } - return (FLOOR_LAVA); - case FLOOR_SLUDGE: - if (smallsplash) - { - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, - MT_SLUDGESPLASH); - if (mo) - mo->floorclip += SMALLSPLASHCLIP; - } - else - { - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, - MT_SLUDGECHUNK); - mo->target = thing; - mo->momx = P_SubRandom() << 8; - mo->momy = P_SubRandom() << 8; - mo->momz = FRACUNIT + (P_Random() << 8); - mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, - MT_SLUDGESPLASH); - if (thing->player) - P_NoiseAlert(thing, thing); - } - S_StartSound(mo, SFX_SLUDGE_GLOOP); - return (FLOOR_SLUDGE); - } - return (FLOOR_SOLID); -} - - -//--------------------------------------------------------------------------- -// -// FUNC P_CheckMissileSpawn -// -// Returns true if the missile is at a valid spawn point, otherwise -// explodes it and returns false. -// -//--------------------------------------------------------------------------- - -boolean P_CheckMissileSpawn(mobj_t * missile) -{ - //missile->tics -= P_Random()&3; - - // move a little forward so an angle can be computed if it - // immediately explodes - missile->x += (missile->momx >> 1); - missile->y += (missile->momy >> 1); - missile->z += (missile->momz >> 1); - if (!P_TryMove(missile, missile->x, missile->y)) - { - P_ExplodeMissile(missile); - return (false); - } - return (true); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_SpawnMissile -// -// Returns NULL if the missile exploded immediately, otherwise returns -// a mobj_t pointer to the missile. -// -//--------------------------------------------------------------------------- - -mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type) -{ - fixed_t z; - mobj_t *th; - angle_t an; - int dist; - - switch (type) - { - case MT_MNTRFX1: // Minotaur swing attack missile - z = source->z + 40 * FRACUNIT; - break; - case MT_MNTRFX2: // Minotaur floor fire missile - z = ONFLOORZ + source->floorclip; - break; - case MT_CENTAUR_FX: - z = source->z + 45 * FRACUNIT; - break; - case MT_ICEGUY_FX: - z = source->z + 40 * FRACUNIT; - break; - case MT_HOLY_MISSILE: - z = source->z + 40 * FRACUNIT; - break; - default: - z = source->z + 32 * FRACUNIT; - break; - } - z -= source->floorclip; - th = P_SpawnMobj(source->x, source->y, z, type); - if (th->info->seesound) - { - S_StartSound(th, th->info->seesound); - } - th->target = source; // Originator - an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); - if (dest->flags & MF_SHADOW) - { // Invisible target - an += P_SubRandom() << 21; - } - th->angle = an; - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul(th->info->speed, finecosine[an]); - th->momy = FixedMul(th->info->speed, finesine[an]); - dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); - dist = dist / th->info->speed; - if (dist < 1) - { - dist = 1; - } - th->momz = (dest->z - source->z) / dist; - return (P_CheckMissileSpawn(th) ? th : NULL); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_SpawnMissileXYZ -// -// Returns NULL if the missile exploded immediately, otherwise returns -// a mobj_t pointer to the missile. -// -//--------------------------------------------------------------------------- - -mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z, - mobj_t * source, mobj_t * dest, mobjtype_t type) -{ - mobj_t *th; - angle_t an; - int dist; - - z -= source->floorclip; - th = P_SpawnMobj(x, y, z, type); - if (th->info->seesound) - { - S_StartSound(th, th->info->seesound); - } - th->target = source; // Originator - an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); - if (dest->flags & MF_SHADOW) - { // Invisible target - an += P_SubRandom() << 21; - } - th->angle = an; - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul(th->info->speed, finecosine[an]); - th->momy = FixedMul(th->info->speed, finesine[an]); - dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); - dist = dist / th->info->speed; - if (dist < 1) - { - dist = 1; - } - th->momz = (dest->z - source->z) / dist; - return (P_CheckMissileSpawn(th) ? th : NULL); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_SpawnMissileAngle -// -// Returns NULL if the missile exploded immediately, otherwise returns -// a mobj_t pointer to the missile. -// -//--------------------------------------------------------------------------- - -mobj_t *P_SpawnMissileAngle(mobj_t * source, mobjtype_t type, - angle_t angle, fixed_t momz) -{ - fixed_t z; - mobj_t *mo; - - switch (type) - { - case MT_MNTRFX1: // Minotaur swing attack missile - z = source->z + 40 * FRACUNIT; - break; - case MT_MNTRFX2: // Minotaur floor fire missile - z = ONFLOORZ + source->floorclip; - break; - case MT_ICEGUY_FX2: // Secondary Projectiles of the Ice Guy - z = source->z + 3 * FRACUNIT; - break; - case MT_MSTAFF_FX2: - z = source->z + 40 * FRACUNIT; - break; - default: - z = source->z + 32 * FRACUNIT; - break; - } - z -= source->floorclip; - mo = P_SpawnMobj(source->x, source->y, z, type); - if (mo->info->seesound) - { - S_StartSound(mo, mo->info->seesound); - } - mo->target = source; // Originator - mo->angle = angle; - angle >>= ANGLETOFINESHIFT; - mo->momx = FixedMul(mo->info->speed, finecosine[angle]); - mo->momy = FixedMul(mo->info->speed, finesine[angle]); - mo->momz = momz; - return (P_CheckMissileSpawn(mo) ? mo : NULL); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_SpawnMissileAngleSpeed -// -// Returns NULL if the missile exploded immediately, otherwise returns -// a mobj_t pointer to the missile. -// -//--------------------------------------------------------------------------- - -mobj_t *P_SpawnMissileAngleSpeed(mobj_t * source, mobjtype_t type, - angle_t angle, fixed_t momz, fixed_t speed) -{ - fixed_t z; - mobj_t *mo; - - z = source->z; - z -= source->floorclip; - mo = P_SpawnMobj(source->x, source->y, z, type); - if (mo->info->seesound) - { - //S_StartSound(mo, mo->info->seesound); - } - mo->target = source; // Originator - mo->angle = angle; - angle >>= ANGLETOFINESHIFT; - mo->momx = FixedMul(speed, finecosine[angle]); - mo->momy = FixedMul(speed, finesine[angle]); - mo->momz = momz; - return (P_CheckMissileSpawn(mo) ? mo : NULL); -} - - - -/* -================ -= -= P_SpawnPlayerMissile -= -= Tries to aim at a nearby monster -================ -*/ - -mobj_t *P_SpawnPlayerMissile(mobj_t * source, mobjtype_t type) -{ - angle_t an; - fixed_t x, y, z, slope; - - // Try to find a target - an = source->angle; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an += 1 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an -= 2 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - } - if (!linetarget) - { - an = source->angle; - slope = ((source->player->lookdir) << FRACBITS) / 173; - } - } - x = source->x; - y = source->y; - if (type == MT_LIGHTNING_FLOOR) - { - z = ONFLOORZ; - slope = 0; - } - else if (type == MT_LIGHTNING_CEILING) - { - z = ONCEILINGZ; - slope = 0; - } - else - { - z = source->z + 4 * 8 * FRACUNIT + - ((source->player->lookdir) << FRACBITS) / 173; - z -= source->floorclip; - } - MissileMobj = P_SpawnMobj(x, y, z, type); - if (MissileMobj->info->seesound) - { - //S_StartSound(MissileMobj, MissileMobj->info->seesound); - } - MissileMobj->target = source; - MissileMobj->angle = an; - MissileMobj->momx = FixedMul(MissileMobj->info->speed, - finecosine[an >> ANGLETOFINESHIFT]); - MissileMobj->momy = FixedMul(MissileMobj->info->speed, - finesine[an >> ANGLETOFINESHIFT]); - MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope); - if (MissileMobj->type == MT_MWAND_MISSILE - || MissileMobj->type == MT_CFLAME_MISSILE) - { // Ultra-fast ripper spawning missile - MissileMobj->x += (MissileMobj->momx >> 3); - MissileMobj->y += (MissileMobj->momy >> 3); - MissileMobj->z += (MissileMobj->momz >> 3); - } - else - { // Normal missile - MissileMobj->x += (MissileMobj->momx >> 1); - MissileMobj->y += (MissileMobj->momy >> 1); - MissileMobj->z += (MissileMobj->momz >> 1); - } - if (!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y)) - { // Exploded immediately - P_ExplodeMissile(MissileMobj); - return (NULL); - } - return (MissileMobj); -} - - -//---------------------------------------------------------------------------- -// -// P_SpawnPlayerMinotaur - -// -// Special missile that has larger blocking than player -//---------------------------------------------------------------------------- - -/* -mobj_t *P_SpawnPlayerMinotaur(mobj_t *source, mobjtype_t type) -{ - angle_t an; - fixed_t x, y, z; - fixed_t dist=0 *FRACUNIT; - - an = source->angle; - x = source->x + FixedMul(dist, finecosine[an>>ANGLETOFINESHIFT]); - y = source->y + FixedMul(dist, finesine[an>>ANGLETOFINESHIFT]); - z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<floorclip; - MissileMobj = P_SpawnMobj(x, y, z, type); - if(MissileMobj->info->seesound) - { - //S_StartSound(MissileMobj, MissileMobj->info->seesound); - } - MissileMobj->target = source; - MissileMobj->angle = an; - MissileMobj->momx = FixedMul(MissileMobj->info->speed, - finecosine[an>>ANGLETOFINESHIFT]); - MissileMobj->momy = FixedMul(MissileMobj->info->speed, - finesine[an>>ANGLETOFINESHIFT]); - MissileMobj->momz = 0; - -// MissileMobj->x += (MissileMobj->momx>>3); -// MissileMobj->y += (MissileMobj->momy>>3); -// MissileMobj->z += (MissileMobj->momz>>3); - - if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y)) - { // Wouln't fit - - return(NULL); - } - return(MissileMobj); -} -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_SPMAngle -// -//--------------------------------------------------------------------------- - -mobj_t *P_SPMAngle(mobj_t * source, mobjtype_t type, angle_t angle) -{ - mobj_t *th; - angle_t an; - fixed_t x, y, z, slope; - -// -// see which target is to be aimed at -// - an = angle; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an += 1 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an -= 2 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - } - if (!linetarget) - { - an = angle; - slope = ((source->player->lookdir) << FRACBITS) / 173; - } - } - x = source->x; - y = source->y; - z = source->z + 4 * 8 * FRACUNIT + - ((source->player->lookdir) << FRACBITS) / 173; - z -= source->floorclip; - th = P_SpawnMobj(x, y, z, type); -// if(th->info->seesound) -// { -// S_StartSound(th, th->info->seesound); -// } - th->target = source; - th->angle = an; - th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); - th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); - th->momz = FixedMul(th->info->speed, slope); - return (P_CheckMissileSpawn(th) ? th : NULL); -} - -//=========================================================================== -// -// P_SPMAngleXYZ -// -//=========================================================================== - -mobj_t *P_SPMAngleXYZ(mobj_t * source, fixed_t x, fixed_t y, - fixed_t z, mobjtype_t type, angle_t angle) -{ - mobj_t *th; - angle_t an; - fixed_t slope; - -// -// see which target is to be aimed at -// - an = angle; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an += 1 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - if (!linetarget) - { - an -= 2 << 26; - slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); - } - if (!linetarget) - { - an = angle; - slope = ((source->player->lookdir) << FRACBITS) / 173; - } - } - z += 4 * 8 * FRACUNIT + ((source->player->lookdir) << FRACBITS) / 173; - z -= source->floorclip; - th = P_SpawnMobj(x, y, z, type); -// if(th->info->seesound) -// { -// S_StartSound(th, th->info->seesound); -// } - th->target = source; - th->angle = an; - th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); - th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); - th->momz = FixedMul(th->info->speed, slope); - return (P_CheckMissileSpawn(th) ? th : NULL); -} - -mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z, - mobj_t * source, mobj_t * dest, mobjtype_t type) -{ - mobj_t *th; - angle_t an; - int dist; - - z -= source->floorclip; - th = P_SpawnMobj(x, y, z, type); - if (th->info->seesound) - { - S_StartSound(th, th->info->seesound); - } - th->target = source; // Originator - an = R_PointToAngle2(x, y, dest->x, dest->y); - if (dest->flags & MF_SHADOW) - { // Invisible target - an += P_SubRandom() << 21; - } - th->angle = an; - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul(th->info->speed, finecosine[an]); - th->momy = FixedMul(th->info->speed, finesine[an]); - dist = P_AproxDistance(dest->x - x, dest->y - y); - dist = dist / th->info->speed; - if (dist < 1) - { - dist = 1; - } - th->momz = (dest->z - z + (30 * FRACUNIT)) / dist; - return (P_CheckMissileSpawn(th) ? th : NULL); -} diff --git a/games/NXDoom/src/hexen/p_plats.c b/games/NXDoom/src/hexen/p_plats.c deleted file mode 100644 index 8c91b357553..00000000000 --- a/games/NXDoom/src/hexen/p_plats.c +++ /dev/null @@ -1,277 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "p_local.h" - -plat_t *activeplats[MAXPLATS]; - -//================================================================== -// -// Move a plat up and down -// -//================================================================== -void T_PlatRaise(thinker_t *thinker) -{ - plat_t *plat = (plat_t *) thinker; - result_e res; - - switch (plat->status) - { - case PLAT_UP: - res = T_MovePlane(plat->sector, plat->speed, - plat->high, plat->crush, 0, 1); - if (res == RES_CRUSHED && (!plat->crush)) - { - plat->count = plat->wait; - plat->status = PLAT_DOWN; - SN_StartSequence((mobj_t *) & plat->sector->soundorg, - SEQ_PLATFORM + plat->sector->seqType); - } - else if (res == RES_PASTDEST) - { - plat->count = plat->wait; - plat->status = PLAT_WAITING; - SN_StopSequence((mobj_t *) & plat->sector->soundorg); - switch (plat->type) - { - case PLAT_DOWNWAITUPSTAY: - case PLAT_DOWNBYVALUEWAITUPSTAY: - P_RemoveActivePlat(plat); - break; - default: - break; - } - } - break; - case PLAT_DOWN: - res = - T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, - -1); - if (res == RES_PASTDEST) - { - plat->count = plat->wait; - plat->status = PLAT_WAITING; - switch (plat->type) - { - case PLAT_UPWAITDOWNSTAY: - case PLAT_UPBYVALUEWAITDOWNSTAY: - P_RemoveActivePlat(plat); - break; - default: - break; - } - SN_StopSequence((mobj_t *) & plat->sector->soundorg); - } - break; - case PLAT_WAITING: - if (!--plat->count) - { - if (plat->sector->floorheight == plat->low) - plat->status = PLAT_UP; - else - plat->status = PLAT_DOWN; - SN_StartSequence((mobj_t *) & plat->sector->soundorg, - SEQ_PLATFORM + plat->sector->seqType); - } -// case PLAT_IN_STASIS: -// break; - } -} - -//================================================================== -// -// Do Platforms -// "amount" is only used for SOME platforms. -// -//================================================================== -int EV_DoPlat(line_t * line, byte * args, plattype_e type, int amount) -{ - plat_t *plat; - int secnum; - int rtn; - sector_t *sec; - - secnum = -1; - rtn = 0; - -/* - // - // Activate all plats that are in_stasis - // - switch(type) - { - case PLAT_PERPETUALRAISE: - P_ActivateInStasis(args[0]); - break; - default: - break; - } -*/ - - while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - // - // Find lowest & highest floors around sector - // - rtn = 1; - plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, 0); - P_AddThinker(&plat->thinker); - - plat->type = type; - plat->sector = sec; - plat->sector->specialdata = plat; - plat->thinker.function = T_PlatRaise; - plat->crush = false; - plat->tag = args[0]; - plat->speed = args[1] * (FRACUNIT / 8); - switch (type) - { - case PLAT_DOWNWAITUPSTAY: - plat->low = P_FindLowestFloorSurrounding(sec) + 8 * FRACUNIT; - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - plat->high = sec->floorheight; - plat->wait = args[2]; - plat->status = PLAT_DOWN; - break; - case PLAT_DOWNBYVALUEWAITUPSTAY: - plat->low = sec->floorheight - args[3] * 8 * FRACUNIT; - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - plat->high = sec->floorheight; - plat->wait = args[2]; - plat->status = PLAT_DOWN; - break; - case PLAT_UPWAITDOWNSTAY: - plat->high = P_FindHighestFloorSurrounding(sec); - if (plat->high < sec->floorheight) - plat->high = sec->floorheight; - plat->low = sec->floorheight; - plat->wait = args[2]; - plat->status = PLAT_UP; - break; - case PLAT_UPBYVALUEWAITDOWNSTAY: - plat->high = sec->floorheight + args[3] * 8 * FRACUNIT; - if (plat->high < sec->floorheight) - plat->high = sec->floorheight; - plat->low = sec->floorheight; - plat->wait = args[2]; - plat->status = PLAT_UP; - break; - case PLAT_PERPETUALRAISE: - plat->low = P_FindLowestFloorSurrounding(sec) + 8 * FRACUNIT; - if (plat->low > sec->floorheight) - plat->low = sec->floorheight; - plat->high = P_FindHighestFloorSurrounding(sec); - if (plat->high < sec->floorheight) - plat->high = sec->floorheight; - plat->wait = args[2]; - plat->status = P_Random() & 1; - break; - } - P_AddActivePlat(plat); - SN_StartSequence((mobj_t *) & sec->soundorg, - SEQ_PLATFORM + sec->seqType); - } - return rtn; -} - -#if 0 -void P_ActivateInStasis(int tag) -{ - int i; - - for (i = 0; i < MAXPLATS; i++) - if (activeplats[i] && - (activeplats[i])->tag == tag && - (activeplats[i])->status == PLAT_IN_STASIS) - { - (activeplats[i])->status = (activeplats[i])->oldstatus; - (activeplats[i])->thinker.function = T_PlatRaise; - } -} -#endif - -void EV_StopPlat(line_t * line, byte * args) -{ - int i; - - for (i = 0; i < MAXPLATS; i++) - { - activeplats[i]->tag = args[0]; - - if (activeplats[i]->tag != 0) - { - activeplats[i]->sector->specialdata = NULL; - P_TagFinished(activeplats[i]->sector->tag); - P_RemoveThinker(&activeplats[i]->thinker); - activeplats[i] = NULL; - - return; - } - } - -/* - int j; - - for (j = 0;j < MAXPLATS;j++) - { - if (activeplats[j] && ((activeplats[j])->status != PLAT_IN_STASIS) && - ((activeplats[j])->tag == args[0])) - { - (activeplats[j])->oldstatus = (activeplats[j])->status; - (activeplats[j])->status = PLAT_IN_STASIS; - (activeplats[j])->thinker.function = NULL; - SN_StopSequence((mobj_t *)&(activeplats[j])->sector->soundorg); - } - } -*/ -} - -void P_AddActivePlat(plat_t * plat) -{ - int i; - for (i = 0; i < MAXPLATS; i++) - if (activeplats[i] == NULL) - { - activeplats[i] = plat; - return; - } - I_Error("P_AddActivePlat: no more plats!"); -} - -void P_RemoveActivePlat(plat_t * plat) -{ - int i; - for (i = 0; i < MAXPLATS; i++) - if (plat == activeplats[i]) - { - (activeplats[i])->sector->specialdata = NULL; - P_TagFinished(plat->sector->tag); - P_RemoveThinker(&(activeplats[i])->thinker); - activeplats[i] = NULL; - return; - } - I_Error("P_RemoveActivePlat: can't find plat!"); -} diff --git a/games/NXDoom/src/hexen/p_pspr.c b/games/NXDoom/src/hexen/p_pspr.c deleted file mode 100644 index 230841344b7..00000000000 --- a/games/NXDoom/src/hexen/p_pspr.c +++ /dev/null @@ -1,2476 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -#define LOWERSPEED FRACUNIT*6 -#define RAISESPEED FRACUNIT*6 -#define WEAPONBOTTOM 128*FRACUNIT -#define WEAPONTOP 32*FRACUNIT - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -fixed_t bulletslope; - -weaponinfo_t WeaponInfo[NUMWEAPONS][NUMCLASSES] = { - { // First Weapons - { // Fighter First Weapon - Punch - MANA_NONE, // mana - S_PUNCHUP, // upstate - S_PUNCHDOWN, // downstate - S_PUNCHREADY, // readystate - S_PUNCHATK1_1, // atkstate - S_PUNCHATK1_1, // holdatkstate - S_NULL // flashstate - }, - { // Cleric First Weapon - Mace - MANA_NONE, // mana - S_CMACEUP, // upstate - S_CMACEDOWN, // downstate - S_CMACEREADY, // readystate - S_CMACEATK_1, // atkstate - S_CMACEATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Mage First Weapon - Wand - MANA_NONE, - S_MWANDUP, - S_MWANDDOWN, - S_MWANDREADY, - S_MWANDATK_1, - S_MWANDATK_1, - S_NULL}, - { // Pig - Snout - MANA_NONE, // mana - S_SNOUTUP, // upstate - S_SNOUTDOWN, // downstate - S_SNOUTREADY, // readystate - S_SNOUTATK1, // atkstate - S_SNOUTATK1, // holdatkstate - S_NULL // flashstate - } - }, - { // Second Weapons - { // Fighter - Axe - MANA_NONE, // mana - S_FAXEUP, // upstate - S_FAXEDOWN, // downstate - S_FAXEREADY, // readystate - S_FAXEATK_1, // atkstate - S_FAXEATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Cleric - Serpent Staff - MANA_1, // mana - S_CSTAFFUP, // upstate - S_CSTAFFDOWN, // downstate - S_CSTAFFREADY, // readystate - S_CSTAFFATK_1, // atkstate - S_CSTAFFATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Mage - Cone of shards - MANA_1, // mana - S_CONEUP, // upstate - S_CONEDOWN, // downstate - S_CONEREADY, // readystate - S_CONEATK1_1, // atkstate - S_CONEATK1_3, // holdatkstate - S_NULL // flashstate - }, - { // Pig - Snout - MANA_NONE, // mana - S_SNOUTUP, // upstate - S_SNOUTDOWN, // downstate - S_SNOUTREADY, // readystate - S_SNOUTATK1, // atkstate - S_SNOUTATK1, // holdatkstate - S_NULL // flashstate - } - }, - { // Third Weapons - { // Fighter - Hammer - MANA_NONE, // mana - S_FHAMMERUP, // upstate - S_FHAMMERDOWN, // downstate - S_FHAMMERREADY, // readystate - S_FHAMMERATK_1, // atkstate - S_FHAMMERATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Cleric - Flame Strike - MANA_2, // mana - S_CFLAMEUP, // upstate - S_CFLAMEDOWN, // downstate - S_CFLAMEREADY1, // readystate - S_CFLAMEATK_1, // atkstate - S_CFLAMEATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Mage - Lightning - MANA_2, // mana - S_MLIGHTNINGUP, // upstate - S_MLIGHTNINGDOWN, // downstate - S_MLIGHTNINGREADY, // readystate - S_MLIGHTNINGATK_1, // atkstate - S_MLIGHTNINGATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Pig - Snout - MANA_NONE, // mana - S_SNOUTUP, // upstate - S_SNOUTDOWN, // downstate - S_SNOUTREADY, // readystate - S_SNOUTATK1, // atkstate - S_SNOUTATK1, // holdatkstate - S_NULL // flashstate - } - }, - { // Fourth Weapons - { // Fighter - Rune Sword - MANA_BOTH, // mana - S_FSWORDUP, // upstate - S_FSWORDDOWN, // downstate - S_FSWORDREADY, // readystate - S_FSWORDATK_1, // atkstate - S_FSWORDATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Cleric - Holy Symbol - MANA_BOTH, // mana - S_CHOLYUP, // upstate - S_CHOLYDOWN, // downstate - S_CHOLYREADY, // readystate - S_CHOLYATK_1, // atkstate - S_CHOLYATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Mage - Staff - MANA_BOTH, // mana - S_MSTAFFUP, // upstate - S_MSTAFFDOWN, // downstate - S_MSTAFFREADY, // readystate - S_MSTAFFATK_1, // atkstate - S_MSTAFFATK_1, // holdatkstate - S_NULL // flashstate - }, - { // Pig - Snout - MANA_NONE, // mana - S_SNOUTUP, // upstate - S_SNOUTDOWN, // downstate - S_SNOUTREADY, // readystate - S_SNOUTATK1, // atkstate - S_SNOUTATK1, // holdatkstate - S_NULL // flashstate - } - } -}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int WeaponManaUse[NUMCLASSES][NUMWEAPONS] = { - {0, 2, 3, 14}, - {0, 1, 4, 18}, - {0, 3, 5, 15}, - {0, 0, 0, 0} -}; - -// CODE -------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// -// PROC P_SetPsprite -// -//--------------------------------------------------------------------------- - -void P_SetPsprite(player_t * player, int position, statenum_t stnum) -{ - pspdef_t *psp; - state_t *state; - - psp = &player->psprites[position]; - do - { - if (!stnum) - { // Object removed itself. - psp->state = NULL; - break; - } - state = &states[stnum]; - psp->state = state; - psp->tics = state->tics; // could be 0 - if (state->misc1) - { // Set coordinates. - psp->sx = state->misc1 << FRACBITS; - } - if (state->misc2) - { - psp->sy = state->misc2 << FRACBITS; - } - if (state->action) - { // Call action routine. - state->action(NULL, player, psp); - if (!psp->state) - { - break; - } - } - stnum = psp->state->nextstate; - } - while (!psp->tics); // An initial state of 0 could cycle through. -} - -//--------------------------------------------------------------------------- -// -// PROC P_SetPspriteNF -// -// Identical to P_SetPsprite, without calling the action function -//--------------------------------------------------------------------------- - -void P_SetPspriteNF(player_t * player, int position, statenum_t stnum) -{ - pspdef_t *psp; - state_t *state; - - psp = &player->psprites[position]; - do - { - if (!stnum) - { // Object removed itself. - psp->state = NULL; - break; - } - state = &states[stnum]; - psp->state = state; - psp->tics = state->tics; // could be 0 - if (state->misc1) - { // Set coordinates. - psp->sx = state->misc1 << FRACBITS; - } - if (state->misc2) - { - psp->sy = state->misc2 << FRACBITS; - } - stnum = psp->state->nextstate; - } - while (!psp->tics); // An initial state of 0 could cycle through. -} - -/* -================= -= -= P_CalcSwing -= -================= -*/ - -/* -fixed_t swingx, swingy; -void P_CalcSwing (player_t *player) -{ - fixed_t swing; - int angle; - -// OPTIMIZE: tablify this - - swing = player->bob; - - angle = (FINEANGLES/70*leveltime)&FINEMASK; - swingx = FixedMul ( swing, finesine[angle]); - - angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK; - swingy = -FixedMul ( swingx, finesine[angle]); -} -*/ - -//--------------------------------------------------------------------------- -// -// PROC P_ActivateMorphWeapon -// -//--------------------------------------------------------------------------- - -void P_ActivateMorphWeapon(player_t * player) -{ - player->pendingweapon = WP_NOCHANGE; - player->psprites[ps_weapon].sy = WEAPONTOP; - player->readyweapon = WP_FIRST; // Snout is the first weapon - P_SetPsprite(player, ps_weapon, S_SNOUTREADY); -} - - -//--------------------------------------------------------------------------- -// -// PROC P_PostMorphWeapon -// -//--------------------------------------------------------------------------- - -void P_PostMorphWeapon(player_t * player, weapontype_t weapon) -{ - player->pendingweapon = WP_NOCHANGE; - player->readyweapon = weapon; - player->psprites[ps_weapon].sy = WEAPONBOTTOM; - P_SetPsprite(player, ps_weapon, - WeaponInfo[weapon][player->class].upstate); -} - -//--------------------------------------------------------------------------- -// -// PROC P_BringUpWeapon -// -// Starts bringing the pending weapon up from the bottom of the screen. -// -//--------------------------------------------------------------------------- - -void P_BringUpWeapon(player_t * player) -{ - statenum_t new; - - if (player->pendingweapon == WP_NOCHANGE) - { - player->pendingweapon = player->readyweapon; - } - if (player->class == PCLASS_FIGHTER && player->pendingweapon == WP_SECOND - && player->mana[MANA_1]) - { - new = S_FAXEUP_G; - } - else - { - new = WeaponInfo[player->pendingweapon][player->class].upstate; - } - player->pendingweapon = WP_NOCHANGE; - player->psprites[ps_weapon].sy = WEAPONBOTTOM; - P_SetPsprite(player, ps_weapon, new); -} - -//--------------------------------------------------------------------------- -// -// FUNC P_CheckMana -// -// Returns true if there is enough mana to shoot. If not, selects the -// next weapon to use. -// -//--------------------------------------------------------------------------- - -boolean P_CheckMana(player_t * player) -{ - manatype_t mana; - int count; - - mana = WeaponInfo[player->readyweapon][player->class].mana; - count = WeaponManaUse[player->class][player->readyweapon]; - if (mana == MANA_BOTH) - { - if (player->mana[MANA_1] >= count && player->mana[MANA_2] >= count) - { - return true; - } - } - else if (mana == MANA_NONE || player->mana[mana] >= count) - { - return (true); - } - // out of mana, pick a weapon to change to - do - { - if (player->weaponowned[WP_THIRD] - && player->mana[MANA_2] >= WeaponManaUse[player->class][WP_THIRD]) - { - player->pendingweapon = WP_THIRD; - } - else if (player->weaponowned[WP_SECOND] - && player->mana[MANA_1] >= - WeaponManaUse[player->class][WP_SECOND]) - { - player->pendingweapon = WP_SECOND; - } - else if (player->weaponowned[WP_FOURTH] - && player->mana[MANA_1] >= - WeaponManaUse[player->class][WP_FOURTH] - && player->mana[MANA_2] >= - WeaponManaUse[player->class][WP_FOURTH]) - { - player->pendingweapon = WP_FOURTH; - } - else - { - player->pendingweapon = WP_FIRST; - } - } - while (player->pendingweapon == WP_NOCHANGE); - P_SetPsprite(player, ps_weapon, - WeaponInfo[player->readyweapon][player->class].downstate); - return (false); -} - -//--------------------------------------------------------------------------- -// -// PROC P_FireWeapon -// -//--------------------------------------------------------------------------- - -void P_FireWeapon(player_t * player) -{ - statenum_t attackState; - - if (!P_CheckMana(player)) - { - return; - } - P_SetMobjState(player->mo, PStateAttack[player->class]); // S_PLAY_ATK1); - if (player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND - && player->mana[MANA_1] > 0) - { // Glowing axe - attackState = S_FAXEATK_G1; - } - else - { - attackState = player->refire ? - WeaponInfo[player->readyweapon][player->class].holdatkstate - : WeaponInfo[player->readyweapon][player->class].atkstate; - } - P_SetPsprite(player, ps_weapon, attackState); - P_NoiseAlert(player->mo, player->mo); -} - -//--------------------------------------------------------------------------- -// -// PROC P_DropWeapon -// -// The player died, so put the weapon away. -// -//--------------------------------------------------------------------------- - -void P_DropWeapon(player_t * player) -{ - P_SetPsprite(player, ps_weapon, - WeaponInfo[player->readyweapon][player->class].downstate); -} - -//--------------------------------------------------------------------------- -// -// PROC A_WeaponReady -// -// The player can fire the weapon or change to another weapon at this time. -// -//--------------------------------------------------------------------------- - -void A_WeaponReady(mobj_t *obj, player_t *player, pspdef_t *psp) -{ - int angle; - - // Change player from attack state - if (player->mo->state >= &states[PStateAttack[player->class]] - && player->mo->state <= &states[PStateAttackEnd[player->class]]) - { - P_SetMobjState(player->mo, PStateNormal[player->class]); - } - // Put the weapon away if the player has a pending weapon or has - // died. - if (player->pendingweapon != WP_NOCHANGE || !player->health) - { - P_SetPsprite(player, ps_weapon, - WeaponInfo[player->readyweapon][player->class]. - downstate); - return; - } - - // Check for fire. - if (player->cmd.buttons & BT_ATTACK) - { - player->attackdown = true; - P_FireWeapon(player); - return; - } - else - { - player->attackdown = false; - } - - if (!player->morphTics) - { - // Bob the weapon based on movement speed. - angle = (128 * leveltime) & FINEMASK; - psp->sx = FRACUNIT + FixedMul(player->bob, finecosine[angle]); - angle &= FINEANGLES / 2 - 1; - psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]); - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_ReFire -// -// The player can re fire the weapon without lowering it entirely. -// -//--------------------------------------------------------------------------- - -void A_ReFire(mobj_t *mobj, player_t *player, pspdef_t *psp) -{ - if ((player->cmd.buttons & BT_ATTACK) - && player->pendingweapon == WP_NOCHANGE && player->health) - { - player->refire++; - P_FireWeapon(player); - } - else - { - player->refire = 0; - P_CheckMana(player); - } -} - -//--------------------------------------------------------------------------- -// -// PROC A_Lower -// -//--------------------------------------------------------------------------- - -void A_Lower(mobj_t *mobj, player_t *player, pspdef_t *psp) -{ - if (player->morphTics) - { - psp->sy = WEAPONBOTTOM; - } - else - { - psp->sy += LOWERSPEED; - } - if (psp->sy < WEAPONBOTTOM) - { // Not lowered all the way yet - return; - } - if (player->playerstate == PST_DEAD) - { // Player is dead, so don't bring up a pending weapon - psp->sy = WEAPONBOTTOM; - return; - } - if (!player->health) - { // Player is dead, so keep the weapon off screen - P_SetPsprite(player, ps_weapon, S_NULL); - return; - } - player->readyweapon = player->pendingweapon; - P_BringUpWeapon(player); -} - -//--------------------------------------------------------------------------- -// -// PROC A_Raise -// -//--------------------------------------------------------------------------- - -void A_Raise(mobj_t *mobj, player_t *player, pspdef_t *psp) -{ - psp->sy -= RAISESPEED; - if (psp->sy > WEAPONTOP) - { // Not raised all the way yet - return; - } - psp->sy = WEAPONTOP; - if (player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND - && player->mana[MANA_1]) - { - P_SetPsprite(player, ps_weapon, S_FAXEREADY_G); - } - else - { - P_SetPsprite(player, ps_weapon, - WeaponInfo[player->readyweapon][player->class]. - readystate); - } -} - -/* -=============== -= -= P_BulletSlope -= -= Sets a slope so a near miss is at aproximately the height of the -= intended target -= -=============== -*/ - -/* -void P_BulletSlope (mobj_t *mo) -{ - angle_t an; - -// -// see which target is to be aimed at -// - an = mo->angle; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - if (!linetarget) - { - an += 1<<26; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - if (!linetarget) - { - an -= 2<<26; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - } - if (!linetarget) - { - an += 1<<26; - bulletslope = (mo->player->lookdir<x, pmo->y, linetarget->x, linetarget->y); - difference = (int) angle - (int) pmo->angle; - if (abs(difference) > MAX_ANGADJUST) - { - pmo->angle += difference > 0 ? MAX_ANGADJUST : -MAX_ANGADJUST; - } - else - { - pmo->angle = angle; - } -} - -//============================================================================ -// -// A_SnoutAttack -// -//============================================================================ - -void A_SnoutAttack(mobj_t *mobj, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - - damage = 3 + (P_Random() & 3); - angle = player->mo->angle; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - PuffType = MT_SNOUTPUFF; - PuffSpawned = NULL; - P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); - S_StartSound(player->mo, SFX_PIG_ACTIVE1 + (P_Random() & 1)); - if (linetarget) - { - AdjustPlayerAngle(player->mo); -// player->mo->angle = R_PointToAngle2(player->mo->x, -// player->mo->y, linetarget->x, linetarget->y); - if (PuffSpawned) - { // Bit something - S_StartSound(player->mo, SFX_PIG_ATTACK); - } - } -} - -//============================================================================ -// -// A_FHammerAttack -// -//============================================================================ - -#define HAMMER_RANGE (MELEERANGE+MELEERANGE/2) - -void A_FHammerAttack(mobj_t *mobj, player_t *player, pspdef_t *psp) -{ - angle_t angle; - mobj_t *pmo = player->mo; - int damage; - fixed_t power; - int slope; - int i; - - damage = 60 + (P_Random() & 63); - power = 10 * FRACUNIT; - PuffType = MT_HAMMERPUFF; - for (i = 0; i < 16; i++) - { - angle = pmo->angle + i * (ANG45 / 32); - slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE); - if (linetarget) - { - P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage); - AdjustPlayerAngle(pmo); - if (linetarget->flags & MF_COUNTKILL || linetarget->player) - { - P_ThrustMobj(linetarget, angle, power); - } - pmo->special1.i = false; // Don't throw a hammer - goto hammerdone; - } - angle = pmo->angle - i * (ANG45 / 32); - slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE); - if (linetarget) - { - P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage); - AdjustPlayerAngle(pmo); - if (linetarget->flags & MF_COUNTKILL || linetarget->player) - { - P_ThrustMobj(linetarget, angle, power); - } - pmo->special1.i = false; // Don't throw a hammer - goto hammerdone; - } - } - // didn't find any targets in meleerange, so set to throw out a hammer - PuffSpawned = NULL; - angle = pmo->angle; - slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE); - P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage); - if (PuffSpawned) - { - pmo->special1.i = false; - } - else - { - pmo->special1.i = true; - } - hammerdone: - if (player->mana[MANA_2] < - WeaponManaUse[player->class][player->readyweapon]) - { // Don't spawn a hammer if the player doesn't have enough mana - pmo->special1.i = false; - } - return; -} - -//============================================================================ -// -// A_FHammerThrow -// -//============================================================================ - -void A_FHammerThrow(mobj_t *mobj, player_t * player, pspdef_t * psp) -{ - mobj_t *mo; - - if (!player->mo->special1.i) - { - return; - } - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; - mo = P_SpawnPlayerMissile(player->mo, MT_HAMMER_MISSILE); - if (mo) - { - mo->special1.i = 0; - } -} - -//============================================================================ -// -// A_FSwordAttack -// -//============================================================================ - -void A_FSwordAttack(mobj_t *mobj, player_t *player, pspdef_t *psp) -{ - mobj_t *pmo; - - player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; - pmo = player->mo; - P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z - 10 * FRACUNIT, - MT_FSWORD_MISSILE, pmo->angle + ANG45 / 4); - P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z - 5 * FRACUNIT, - MT_FSWORD_MISSILE, pmo->angle + ANG45 / 8); - P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z, MT_FSWORD_MISSILE, pmo->angle); - P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z + 5 * FRACUNIT, - MT_FSWORD_MISSILE, pmo->angle - ANG45 / 8); - P_SPMAngleXYZ(pmo, pmo->x, pmo->y, pmo->z + 10 * FRACUNIT, - MT_FSWORD_MISSILE, pmo->angle - ANG45 / 4); - S_StartSound(pmo, SFX_FIGHTER_SWORD_FIRE); -} - -//============================================================================ -// -// A_FSwordAttack2 -// -//============================================================================ - -void A_FSwordAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle = actor->angle; - - P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle + ANG45 / 4, 0); - P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle + ANG45 / 8, 0); - P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle, 0); - P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle - ANG45 / 8, 0); - P_SpawnMissileAngle(actor, MT_FSWORD_MISSILE, angle - ANG45 / 4, 0); - S_StartSound(actor, SFX_FIGHTER_SWORD_FIRE); -} - -//============================================================================ -// -// A_FSwordFlames -// -//============================================================================ - -void A_FSwordFlames(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - int r1,r2,r3; - - for (i = 1 + (P_Random() & 3); i; i--) - { - r1 = P_Random(); - r2 = P_Random(); - r3 = P_Random(); - P_SpawnMobj(actor->x + ((r3 - 128) << 12), actor->y - + ((r2 - 128) << 12), - actor->z + ((r1 - 128) << 11), MT_FSWORD_FLAME); - } -} - -//============================================================================ -// -// A_MWandAttack -// -//============================================================================ - -void A_MWandAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnPlayerMissile(player->mo, MT_MWAND_MISSILE); - if (mo) - { - mo->thinker.function = P_BlasterMobjThinker; - } - S_StartSound(player->mo, SFX_MAGE_WAND_FIRE); -} - -// ===== Mage Lightning Weapon ===== - -//============================================================================ -// -// A_LightningReady -// -//============================================================================ - -void A_LightningReady(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_WeaponReady(actor, player, psp); - if (P_Random() < 160) - { - S_StartSound(player->mo, SFX_MAGE_LIGHTNING_READY); - } -} - -//============================================================================ -// -// A_LightningClip -// -//============================================================================ - -#define ZAGSPEED FRACUNIT - -void A_LightningClip(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *cMo; - mobj_t *target = NULL; - int zigZag; - - if (actor->type == MT_LIGHTNING_FLOOR) - { - actor->z = actor->floorz; - target = actor->special2.m->special1.m; - } - else if (actor->type == MT_LIGHTNING_CEILING) - { - actor->z = actor->ceilingz - actor->height; - target = actor->special1.m; - } - if (actor->type == MT_LIGHTNING_FLOOR) - { // floor lightning zig-zags, and forces the ceiling lightning to mimic - cMo = actor->special2.m; - zigZag = P_Random(); - if ((zigZag > 128 && actor->special1.i < 2) || actor->special1.i < -2) - { - P_ThrustMobj(actor, actor->angle + ANG90, ZAGSPEED); - if (cMo) - { - P_ThrustMobj(cMo, actor->angle + ANG90, ZAGSPEED); - } - actor->special1.i++; - } - else - { - P_ThrustMobj(actor, actor->angle - ANG90, ZAGSPEED); - if (cMo) - { - P_ThrustMobj(cMo, cMo->angle - ANG90, ZAGSPEED); - } - actor->special1.i--; - } - } - if (target) - { - if (target->health <= 0) - { - P_ExplodeMissile(actor); - } - else - { - actor->angle = R_PointToAngle2(actor->x, actor->y, target->x, - target->y); - actor->momx = 0; - actor->momy = 0; - P_ThrustMobj(actor, actor->angle, actor->info->speed >> 1); - } - } -} - -//============================================================================ -// -// A_LightningZap -// -//============================================================================ - -void A_LightningZap(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - fixed_t deltaZ; - int r1,r2; - - A_LightningClip(actor, player, psp); - - actor->health -= 8; - if (actor->health <= 0) - { - P_SetMobjState(actor, actor->info->deathstate); - return; - } - if (actor->type == MT_LIGHTNING_FLOOR) - { - deltaZ = 10 * FRACUNIT; - } - else - { - deltaZ = -10 * FRACUNIT; - } - r1 = P_Random(); - r2 = P_Random(); - mo = P_SpawnMobj(actor->x + ((r2 - 128) * actor->radius / 256), - actor->y + ((r1 - 128) * actor->radius / 256), - actor->z + deltaZ, MT_LIGHTNING_ZAP); - if (mo) - { - mo->special2.m = actor; - mo->momx = actor->momx; - mo->momy = actor->momy; - mo->target = actor->target; - if (actor->type == MT_LIGHTNING_FLOOR) - { - mo->momz = 20 * FRACUNIT; - } - else - { - mo->momz = -20 * FRACUNIT; - } - } -/* - mo = P_SpawnMobj(actor->x+((P_Random()-128)*actor->radius/256), - actor->y+((P_Random()-128)*actor->radius/256), - actor->z+deltaZ, MT_LIGHTNING_ZAP); - if(mo) - { - mo->special2.m = actor; - mo->momx = actor->momx; - mo->momy = actor->momy; - mo->target = actor->target; - if(actor->type == MT_LIGHTNING_FLOOR) - { - mo->momz = 16*FRACUNIT; - } - else - { - mo->momz = -16*FRACUNIT; - } - } -*/ - if (actor->type == MT_LIGHTNING_FLOOR && P_Random() < 160) - { - S_StartSound(actor, SFX_MAGE_LIGHTNING_CONTINUOUS); - } -} - -//============================================================================ -// -// A_MLightningAttack2 -// -//============================================================================ - -void A_MLightningAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *fmo, *cmo; - - fmo = P_SpawnPlayerMissile(actor, MT_LIGHTNING_FLOOR); - cmo = P_SpawnPlayerMissile(actor, MT_LIGHTNING_CEILING); - if (fmo) - { - fmo->special1.m = NULL; - fmo->special2.m = cmo; - A_LightningZap(fmo, player, psp); - } - if (cmo) - { - cmo->special1.m = NULL; // mobj that it will track - cmo->special2.m = fmo; - A_LightningZap(cmo, player, psp); - } - S_StartSound(actor, SFX_MAGE_LIGHTNING_FIRE); -} - -//============================================================================ -// -// A_MLightningAttack -// -//============================================================================ - -void A_MLightningAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_MLightningAttack2(player->mo, player, psp); - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; -} - -//============================================================================ -// -// A_ZapMimic -// -//============================================================================ - -void A_ZapMimic(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = actor->special2.m; - if (mo) - { - if (mo->state >= &states[mo->info->deathstate] - || mo->state == &states[S_FREETARGMOBJ]) - { - P_ExplodeMissile(actor); - } - else - { - actor->momx = mo->momx; - actor->momy = mo->momy; - } - } -} - -//============================================================================ -// -// A_LastZap -// -//============================================================================ - -void A_LastZap(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_LIGHTNING_ZAP); - if (mo) - { - P_SetMobjState(mo, S_LIGHTNING_ZAP_X1); - mo->momz = 40 * FRACUNIT; - } -} - -//============================================================================ -// -// A_LightningRemove -// -//============================================================================ - -void A_LightningRemove(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = actor->special2.m; - if (mo) - { - mo->special2.m = NULL; - P_ExplodeMissile(mo); - } -} - - -//============================================================================ -// -// MStaffSpawn -// -//============================================================================ -void MStaffSpawn(mobj_t * pmo, angle_t angle) -{ - mobj_t *mo; - - mo = P_SPMAngle(pmo, MT_MSTAFF_FX2, angle); - if (mo) - { - mo->target = pmo; - mo->special1.m = P_RoughMonsterSearch(mo, 10); - } -} - -//============================================================================ -// -// A_MStaffAttack -// -//============================================================================ - -void A_MStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - mobj_t *pmo; - - player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; - pmo = player->mo; - angle = pmo->angle; - - MStaffSpawn(pmo, angle); - MStaffSpawn(pmo, angle - ANG1 * 5); - MStaffSpawn(pmo, angle + ANG1 * 5); - S_StartSound(player->mo, SFX_MAGE_STAFF_FIRE); - if (player == &players[consoleplayer]) - { - player->damagecount = 0; - player->bonuscount = 0; - I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), - PU_CACHE) + - STARTSCOURGEPAL * 768); - } -} - -//============================================================================ -// -// A_MStaffPalette -// -//============================================================================ - -void A_MStaffPalette(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int pal; - - if (player == &players[consoleplayer]) - { - pal = STARTSCOURGEPAL + psp->state - (&states[S_MSTAFFATK_2]); - if (pal == STARTSCOURGEPAL + 3) - { // reset back to original playpal - pal = 0; - } - I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), - PU_CACHE) + pal * 768); - } -} - -//============================================================================ -// -// A_MStaffWeave -// -//============================================================================ - -void A_MStaffWeave(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t newX, newY; - int weaveXY, weaveZ; - int angle; - - weaveXY = actor->special2.i >> 16; - weaveZ = actor->special2.i & 0xFFFF; - angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - newX = actor->x - FixedMul(finecosine[angle], - FloatBobOffsets[weaveXY] << 2); - newY = actor->y - FixedMul(finesine[angle], - FloatBobOffsets[weaveXY] << 2); - weaveXY = (weaveXY + 6) & 63; - newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 2); - newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 2); - P_TryMove(actor, newX, newY); - actor->z -= FloatBobOffsets[weaveZ] << 1; - weaveZ = (weaveZ + 3) & 63; - actor->z += FloatBobOffsets[weaveZ] << 1; - if (actor->z <= actor->floorz) - { - actor->z = actor->floorz + FRACUNIT; - } - actor->special2.i = weaveZ + (weaveXY << 16); -} - - -//============================================================================ -// -// A_MStaffTrack -// -//============================================================================ - -void A_MStaffTrack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if ((actor->special1.m == NULL) && (P_Random() < 50)) - { - actor->special1.m = P_RoughMonsterSearch(actor, 10); - } - P_SeekerMissile(actor, ANG1 * 2, ANG1 * 10); -} - - -//============================================================================ -// -// MStaffSpawn2 - for use by mage class boss -// -//============================================================================ - -void MStaffSpawn2(mobj_t * actor, angle_t angle) -{ - mobj_t *mo; - - mo = P_SpawnMissileAngle(actor, MT_MSTAFF_FX2, angle, 0); - if (mo) - { - mo->target = actor; - mo->special1.m = P_RoughMonsterSearch(mo, 10); - } -} - -//============================================================================ -// -// A_MStaffAttack2 - for use by mage class boss -// -//============================================================================ - -void A_MStaffAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - angle = actor->angle; - MStaffSpawn2(actor, angle); - MStaffSpawn2(actor, angle - ANG1 * 5); - MStaffSpawn2(actor, angle + ANG1 * 5); - S_StartSound(actor, SFX_MAGE_STAFF_FIRE); -} - -//============================================================================ -// -// A_FPunchAttack -// -//============================================================================ - -void A_FPunchAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - mobj_t *pmo = player->mo; - fixed_t power; - int i; - - damage = 40 + (P_Random() & 15); - power = 2 * FRACUNIT; - PuffType = MT_PUNCHPUFF; - for (i = 0; i < 16; i++) - { - angle = pmo->angle + i * (ANG45 / 16); - slope = P_AimLineAttack(pmo, angle, 2 * MELEERANGE); - if (linetarget) - { - player->mo->special1.i++; - if (pmo->special1.i == 3) - { - damage <<= 1; - power = 6 * FRACUNIT; - PuffType = MT_HAMMERPUFF; - } - P_LineAttack(pmo, angle, 2 * MELEERANGE, slope, damage); - if (linetarget->flags & MF_COUNTKILL || linetarget->player) - { - P_ThrustMobj(linetarget, angle, power); - } - AdjustPlayerAngle(pmo); - goto punchdone; - } - angle = pmo->angle - i * (ANG45 / 16); - slope = P_AimLineAttack(pmo, angle, 2 * MELEERANGE); - if (linetarget) - { - pmo->special1.i++; - if (pmo->special1.i == 3) - { - damage <<= 1; - power = 6 * FRACUNIT; - PuffType = MT_HAMMERPUFF; - } - P_LineAttack(pmo, angle, 2 * MELEERANGE, slope, damage); - if (linetarget->flags & MF_COUNTKILL || linetarget->player) - { - P_ThrustMobj(linetarget, angle, power); - } - AdjustPlayerAngle(pmo); - goto punchdone; - } - } - // didn't find any creatures, so try to strike any walls - pmo->special1.i = 0; - - angle = pmo->angle; - slope = P_AimLineAttack(pmo, angle, MELEERANGE); - P_LineAttack(pmo, angle, MELEERANGE, slope, damage); - - punchdone: - if (pmo->special1.i == 3) - { - pmo->special1.i = 0; - P_SetPsprite(player, ps_weapon, S_PUNCHATK2_1); - S_StartSound(pmo, SFX_FIGHTER_GRUNT); - } - return; -} - -//============================================================================ -// -// A_FAxeAttack -// -//============================================================================ - -#define AXERANGE 2.25*MELEERANGE - -void A_FAxeAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - mobj_t *pmo = player->mo; - fixed_t power; - int damage; - int slope; - int i; - int useMana; - int r; - - r = P_Random(); - damage = 40 + (r & 15) + (P_Random() & 7); - power = 0; - if (player->mana[MANA_1] > 0) - { - damage <<= 1; - power = 6 * FRACUNIT; - PuffType = MT_AXEPUFF_GLOW; - useMana = 1; - } - else - { - PuffType = MT_AXEPUFF; - useMana = 0; - } - for (i = 0; i < 16; i++) - { - angle = pmo->angle + i * (ANG45 / 16); - slope = P_AimLineAttack(pmo, angle, AXERANGE); - if (linetarget) - { - P_LineAttack(pmo, angle, AXERANGE, slope, damage); - if (linetarget->flags & MF_COUNTKILL || linetarget->player) - { - P_ThrustMobj(linetarget, angle, power); - } - AdjustPlayerAngle(pmo); - useMana++; - goto axedone; - } - angle = pmo->angle - i * (ANG45 / 16); - slope = P_AimLineAttack(pmo, angle, AXERANGE); - if (linetarget) - { - P_LineAttack(pmo, angle, AXERANGE, slope, damage); - if (linetarget->flags & MF_COUNTKILL) - { - P_ThrustMobj(linetarget, angle, power); - } - AdjustPlayerAngle(pmo); - useMana++; - goto axedone; - } - } - // didn't find any creatures, so try to strike any walls - pmo->special1.m = NULL; - - angle = pmo->angle; - slope = P_AimLineAttack(pmo, angle, MELEERANGE); - P_LineAttack(pmo, angle, MELEERANGE, slope, damage); - - axedone: - if (useMana == 2) - { - player->mana[MANA_1] -= - WeaponManaUse[player->class][player->readyweapon]; - if (player->mana[MANA_1] <= 0) - { - P_SetPsprite(player, ps_weapon, S_FAXEATK_5); - } - } - return; -} - -//=========================================================================== -// -// A_CMaceAttack -// -//=========================================================================== - -void A_CMaceAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int slope; - int i; - - damage = 25 + (P_Random() & 15); - PuffType = MT_HAMMERPUFF; - for (i = 0; i < 16; i++) - { - angle = player->mo->angle + i * (ANG45 / 16); - slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE); - if (linetarget) - { - P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage); - AdjustPlayerAngle(player->mo); -// player->mo->angle = R_PointToAngle2(player->mo->x, -// player->mo->y, linetarget->x, linetarget->y); - goto macedone; - } - angle = player->mo->angle - i * (ANG45 / 16); - slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE); - if (linetarget) - { - P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage); - AdjustPlayerAngle(player->mo); -// player->mo->angle = R_PointToAngle2(player->mo->x, -// player->mo->y, linetarget->x, linetarget->y); - goto macedone; - } - } - // didn't find any creatures, so try to strike any walls - player->mo->special1.m = NULL; - - angle = player->mo->angle; - slope = P_AimLineAttack(player->mo, angle, MELEERANGE); - P_LineAttack(player->mo, angle, MELEERANGE, slope, damage); - macedone: - return; -} - -//============================================================================ -// -// A_CStaffCheck -// -//============================================================================ - -void A_CStaffCheck(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *pmo; - int damage; - int newLife; - angle_t angle; - int slope; - int i; - - pmo = player->mo; - damage = 20 + (P_Random() & 15); - PuffType = MT_CSTAFFPUFF; - for (i = 0; i < 3; i++) - { - angle = pmo->angle + i * (ANG45 / 16); - slope = P_AimLineAttack(pmo, angle, 1.5 * MELEERANGE); - if (linetarget) - { - P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage); - pmo->angle = R_PointToAngle2(pmo->x, pmo->y, - linetarget->x, linetarget->y); - if ((linetarget->player || linetarget->flags & MF_COUNTKILL) - && (!(linetarget->flags2 & (MF2_DORMANT + MF2_INVULNERABLE)))) - { - newLife = player->health + (damage >> 3); - newLife = newLife > 100 ? 100 : newLife; - pmo->health = player->health = newLife; - P_SetPsprite(player, ps_weapon, S_CSTAFFATK2_1); - } - player->mana[MANA_1] -= - WeaponManaUse[player->class][player->readyweapon]; - break; - } - angle = pmo->angle - i * (ANG45 / 16); - slope = P_AimLineAttack(player->mo, angle, 1.5 * MELEERANGE); - if (linetarget) - { - P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage); - pmo->angle = R_PointToAngle2(pmo->x, pmo->y, - linetarget->x, linetarget->y); - if (linetarget->player || linetarget->flags & MF_COUNTKILL) - { - newLife = player->health + (damage >> 4); - newLife = newLife > 100 ? 100 : newLife; - pmo->health = player->health = newLife; - P_SetPsprite(player, ps_weapon, S_CSTAFFATK2_1); - } - player->mana[MANA_1] -= - WeaponManaUse[player->class][player->readyweapon]; - break; - } - } -} - -//============================================================================ -// -// A_CStaffAttack -// -//============================================================================ - -void A_CStaffAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - mobj_t *pmo; - - player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; - pmo = player->mo; - mo = P_SPMAngle(pmo, MT_CSTAFF_MISSILE, pmo->angle - (ANG45 / 15)); - if (mo) - { - mo->special2.i = 32; - } - mo = P_SPMAngle(pmo, MT_CSTAFF_MISSILE, pmo->angle + (ANG45 / 15)); - if (mo) - { - mo->special2.i = 0; - } - S_StartSound(player->mo, SFX_CLERIC_CSTAFF_FIRE); -} - -//============================================================================ -// -// A_CStaffMissileSlither -// -//============================================================================ - -void A_CStaffMissileSlither(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - fixed_t newX, newY; - int weaveXY; - int angle; - - weaveXY = actor->special2.i; - angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - newX = actor->x - FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); - newY = actor->y - FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); - weaveXY = (weaveXY + 3) & 63; - newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]); - newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]); - P_TryMove(actor, newX, newY); - actor->special2.i = weaveXY; -} - -//============================================================================ -// -// A_CStaffInitBlink -// -//============================================================================ - -void A_CStaffInitBlink(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->mo->special1.i = (P_Random() >> 1) + 20; -} - -//============================================================================ -// -// A_CStaffCheckBlink -// -//============================================================================ - -void A_CStaffCheckBlink(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - if (!--player->mo->special1.i) - { - P_SetPsprite(player, ps_weapon, S_CSTAFFBLINK1); - player->mo->special1.i = (P_Random() + 50) >> 2; - } -} - -//============================================================================ -// -// A_CFlameAttack -// -//============================================================================ - -#define FLAMESPEED (0.45*FRACUNIT) -#define CFLAMERANGE (12*64*FRACUNIT) - -void A_CFlameAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - - mo = P_SpawnPlayerMissile(player->mo, MT_CFLAME_MISSILE); - if (mo) - { - mo->thinker.function = P_BlasterMobjThinker; - mo->special1.i = 2; - } - - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; - S_StartSound(player->mo, SFX_CLERIC_FLAME_FIRE); -} - -//============================================================================ -// -// A_CFlamePuff -// -//============================================================================ - -void A_CFlamePuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_UnHideThing(actor, player, psp); - actor->momx = 0; - actor->momy = 0; - actor->momz = 0; - S_StartSound(actor, SFX_CLERIC_FLAME_EXPLODE); -} - -//============================================================================ -// -// A_CFlameMissile -// -//============================================================================ - -void A_CFlameMissile(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int i; - int an; - fixed_t dist; - mobj_t *mo; - - A_UnHideThing(actor, player, psp); - S_StartSound(actor, SFX_CLERIC_FLAME_EXPLODE); - if (BlockingMobj && BlockingMobj->flags & MF_SHOOTABLE) - { // Hit something, so spawn the flame circle around the thing - dist = BlockingMobj->radius + 18 * FRACUNIT; - for (i = 0; i < 4; i++) - { - an = (i * ANG45) >> ANGLETOFINESHIFT; - mo = P_SpawnMobj(BlockingMobj->x + FixedMul(dist, finecosine[an]), - BlockingMobj->y + FixedMul(dist, finesine[an]), - BlockingMobj->z + 5 * FRACUNIT, MT_CIRCLEFLAME); - if (mo) - { - mo->angle = an << ANGLETOFINESHIFT; - mo->target = actor->target; - mo->momx = mo->special1.i = - FixedMul(FLAMESPEED, finecosine[an]); - mo->momy = mo->special2.i = FixedMul(FLAMESPEED, finesine[an]); - mo->tics -= P_Random() & 3; - } - mo = P_SpawnMobj(BlockingMobj->x - FixedMul(dist, finecosine[an]), - BlockingMobj->y - FixedMul(dist, finesine[an]), - BlockingMobj->z + 5 * FRACUNIT, MT_CIRCLEFLAME); - if (mo) - { - mo->angle = ANG180 + (an << ANGLETOFINESHIFT); - mo->target = actor->target; - mo->momx = mo->special1.i = FixedMul(-FLAMESPEED, - finecosine[an]); - mo->momy = mo->special2.i = FixedMul(-FLAMESPEED, finesine[an]); - mo->tics -= P_Random() & 3; - } - } - P_SetMobjState(actor, S_FLAMEPUFF2_1); - } -} - -/* -void A_CFlameAttack(player_t *player, pspdef_t *psp) -{ - mobj_t *pmo; - angle_t angle; - int damage; - int i; - int an, an90; - fixed_t dist; - mobj_t *mo; - - pmo = player->mo; - P_BulletSlope(pmo); - damage = 25+HITDICE(3); - angle = pmo->angle; - if(player->refire) - { - angle += P_SubRandom()<<17; - } - P_AimLineAttack(pmo, angle, CFLAMERANGE); // Correctly set linetarget - if(!linetarget) - { - angle += ANG1*2; - P_AimLineAttack(pmo, angle, CFLAMERANGE); - if(!linetarget) - { - angle -= ANG1*4; - P_AimLineAttack(pmo, angle, CFLAMERANGE); - if(!linetarget) - { - angle += ANG1*2; - } - } - } - if(linetarget) - { - PuffType = MT_FLAMEPUFF2; - } - else - { - PuffType = MT_FLAMEPUFF; - } - P_LineAttack(pmo, angle, CFLAMERANGE, bulletslope, damage); - if(linetarget) - { // Hit something, so spawn the flame circle around the thing - dist = linetarget->radius+18*FRACUNIT; - for(i = 0; i < 4; i++) - { - an = (i*ANG45)>>ANGLETOFINESHIFT; - an90 = (i*ANG45+ANG90)>>ANGLETOFINESHIFT; - mo = P_SpawnMobj(linetarget->x+FixedMul(dist, finecosine[an]), - linetarget->y+FixedMul(dist, finesine[an]), - linetarget->z+5*FRACUNIT, MT_CIRCLEFLAME); - if(mo) - { - mo->angle = an<target = pmo; - mo->momx = mo->special1.i = FixedMul(FLAMESPEED, finecosine[an]); - mo->momy = mo->special2.i = FixedMul(FLAMESPEED, finesine[an]); - mo->tics -= P_Random()&3; - } - mo = P_SpawnMobj(linetarget->x-FixedMul(dist, finecosine[an]), - linetarget->y-FixedMul(dist, finesine[an]), - linetarget->z+5*FRACUNIT, MT_CIRCLEFLAME); - if(mo) - { - mo->angle = ANG180+(an<target = pmo; - mo->momx = mo->special1.i = FixedMul(-FLAMESPEED, - finecosine[an]); - mo->momy = mo->special2.i = FixedMul(-FLAMESPEED, finesine[an]); - mo->tics -= P_Random()&3; - } - } - } -// Create a line of flames from the player to the flame puff - CFlameCreateFlames(player->mo); - - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; - S_StartSound(player->mo, SFX_CLERIC_FLAME_FIRE); -} -*/ - -//============================================================================ -// -// A_CFlameRotate -// -//============================================================================ - -#define FLAMEROTSPEED 2*FRACUNIT - -void A_CFlameRotate(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int an; - - an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - actor->momx = actor->special1.i + FixedMul(FLAMEROTSPEED, finecosine[an]); - actor->momy = actor->special2.i + FixedMul(FLAMEROTSPEED, finesine[an]); - actor->angle += ANG90 / 15; -} - - -//============================================================================ -// -// A_CHolyAttack3 -// -// Spawns the spirits -//============================================================================ - -void A_CHolyAttack3(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMissile(actor, actor->target, MT_HOLY_MISSILE); - S_StartSound(actor, SFX_CHOLY_FIRE); -} - - -//============================================================================ -// -// A_CHolyAttack2 -// -// Spawns the spirits -//============================================================================ - -void A_CHolyAttack2(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int j; - int i; - int r; - mobj_t *mo; - mobj_t *tail, *next; - - for (j = 0; j < 4; j++) - { - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_HOLY_FX); - if (!mo) - { - continue; - } - switch (j) - { // float bob index - case 0: - mo->special2.i = P_Random() & 7; // upper-left - break; - case 1: - mo->special2.i = 32 + (P_Random() & 7); // upper-right - break; - case 2: - mo->special2.i = (32 + (P_Random() & 7)) << 16; // lower-left - break; - case 3: - r = P_Random(); - mo->special2.i = - ((32 + (r & 7)) << 16) + 32 + (P_Random() & 7); - break; - } - mo->z = actor->z; - mo->angle = actor->angle + (ANG45 + ANG45 / 2) - ANG45 * j; - P_ThrustMobj(mo, mo->angle, mo->info->speed); - mo->target = actor->target; - mo->args[0] = 10; // initial turn value - mo->args[1] = 0; // initial look angle - if (deathmatch) - { // Ghosts last slightly less longer in DeathMatch - mo->health = 85; - } - if (linetarget) - { - mo->special1.m = linetarget; - mo->flags |= MF_NOCLIP | MF_SKULLFLY; - mo->flags &= ~MF_MISSILE; - } - tail = P_SpawnMobj(mo->x, mo->y, mo->z, MT_HOLY_TAIL); - tail->special2.m = mo; // parent - for (i = 1; i < 3; i++) - { - next = P_SpawnMobj(mo->x, mo->y, mo->z, MT_HOLY_TAIL); - P_SetMobjState(next, next->info->spawnstate + 1); - tail->special1.m = next; - tail = next; - } - tail->special1.m = NULL; // last tail bit - } -} - -//============================================================================ -// -// A_CHolyAttack -// -//============================================================================ - -void A_CHolyAttack(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; - player->mana[MANA_2] -= WeaponManaUse[player->class][player->readyweapon]; - P_SpawnPlayerMissile(player->mo, MT_HOLY_MISSILE); - if (player == &players[consoleplayer]) - { - player->damagecount = 0; - player->bonuscount = 0; - I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), - PU_CACHE) + STARTHOLYPAL * 768); - } - S_StartSound(player->mo, SFX_CHOLY_FIRE); -} - -//============================================================================ -// -// A_CHolyPalette -// -//============================================================================ - -void A_CHolyPalette(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - int pal; - - if (player == &players[consoleplayer]) - { - pal = STARTHOLYPAL + psp->state - (&states[S_CHOLYATK_6]); - if (pal == STARTHOLYPAL + 3) - { // reset back to original playpal - pal = 0; - } - I_SetPalette((byte *) W_CacheLumpNum(W_GetNumForName("playpal"), - PU_CACHE) + pal * 768); - } -} - -//============================================================================ -// -// CHolyFindTarget -// -//============================================================================ - -static void CHolyFindTarget(mobj_t * actor) -{ - mobj_t *target; - - target = P_RoughMonsterSearch(actor, 6); - if (target != NULL) - { - actor->special1.m = target; - actor->flags |= MF_NOCLIP | MF_SKULLFLY; - actor->flags &= ~MF_MISSILE; - } -} - -//============================================================================ -// -// CHolySeekerMissile -// -// Similar to P_SeekerMissile, but seeks to a random Z on the target -//============================================================================ - -static void CHolySeekerMissile(mobj_t * actor, angle_t thresh, - angle_t turnMax) -{ - int dir; - int dist; - angle_t delta; - angle_t angle; - mobj_t *target; - fixed_t newZ; - fixed_t deltaZ; - - target = actor->special1.m; - if (target == NULL) - { - return; - } - if (!(target->flags & MF_SHOOTABLE) - || (!(target->flags & MF_COUNTKILL) && !target->player)) - { // Target died/target isn't a player or creature - actor->special1.m = NULL; - actor->flags &= ~(MF_NOCLIP | MF_SKULLFLY); - actor->flags |= MF_MISSILE; - CHolyFindTarget(actor); - return; - } - dir = P_FaceMobj(actor, target, &delta); - if (delta > thresh) - { - delta >>= 1; - if (delta > turnMax) - { - delta = turnMax; - } - } - if (dir) - { // Turn clockwise - actor->angle += delta; - } - else - { // Turn counter clockwise - actor->angle -= delta; - } - angle = actor->angle >> ANGLETOFINESHIFT; - actor->momx = FixedMul(actor->info->speed, finecosine[angle]); - actor->momy = FixedMul(actor->info->speed, finesine[angle]); - if (!(leveltime & 15) - || actor->z > target->z + (target->height) - || actor->z + actor->height < target->z) - { - newZ = target->z + ((P_Random() * target->height) >> 8); - deltaZ = newZ - actor->z; - if (abs(deltaZ) > 15 * FRACUNIT) - { - if (deltaZ > 0) - { - deltaZ = 15 * FRACUNIT; - } - else - { - deltaZ = -15 * FRACUNIT; - } - } - dist = P_AproxDistance(target->x - actor->x, target->y - actor->y); - dist = dist / actor->info->speed; - if (dist < 1) - { - dist = 1; - } - actor->momz = deltaZ / dist; - } - return; -} - -//============================================================================ -// -// A_CHolyWeave -// -//============================================================================ - -static void CHolyWeave(mobj_t * actor) -{ - fixed_t newX, newY; - int weaveXY, weaveZ; - int angle; - - weaveXY = actor->special2.i >> 16; - weaveZ = actor->special2.i & 0xFFFF; - angle = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - newX = actor->x - FixedMul(finecosine[angle], - FloatBobOffsets[weaveXY] << 2); - newY = actor->y - FixedMul(finesine[angle], - FloatBobOffsets[weaveXY] << 2); - weaveXY = (weaveXY + (P_Random() % 5)) & 63; - newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY] << 2); - newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY] << 2); - P_TryMove(actor, newX, newY); - actor->z -= FloatBobOffsets[weaveZ] << 1; - weaveZ = (weaveZ + (P_Random() % 5)) & 63; - actor->z += FloatBobOffsets[weaveZ] << 1; - actor->special2.i = weaveZ + (weaveXY << 16); -} - -//============================================================================ -// -// A_CHolySeek -// -//============================================================================ - -void A_CHolySeek(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->health--; - if (actor->health <= 0) - { - actor->momx >>= 2; - actor->momy >>= 2; - actor->momz = 0; - P_SetMobjState(actor, actor->info->deathstate); - actor->tics -= P_Random() & 3; - return; - } - if (actor->special1.m) - { - CHolySeekerMissile(actor, actor->args[0] * ANG1, - actor->args[0] * ANG1 * 2); - if (!((leveltime + 7) & 15)) - { - actor->args[0] = 5 + (P_Random() / 20); - } - } - CHolyWeave(actor); -} - -//============================================================================ -// -// CHolyTailFollow -// -//============================================================================ - -static void CHolyTailFollow(mobj_t * actor, fixed_t dist) -{ - mobj_t *child; - int an; - fixed_t oldDistance, newDistance; - - child = actor->special1.m; - if (child) - { - an = R_PointToAngle2(actor->x, actor->y, child->x, - child->y) >> ANGLETOFINESHIFT; - oldDistance = - P_AproxDistance(child->x - actor->x, child->y - actor->y); - if (P_TryMove - (child, actor->x + FixedMul(dist, finecosine[an]), - actor->y + FixedMul(dist, finesine[an]))) - { - newDistance = P_AproxDistance(child->x - actor->x, - child->y - actor->y) - FRACUNIT; - if (oldDistance < FRACUNIT) - { - if (child->z < actor->z) - { - child->z = actor->z - dist; - } - else - { - child->z = actor->z + dist; - } - } - else - { - child->z = actor->z + FixedMul(FixedDiv(newDistance, - oldDistance), - child->z - actor->z); - } - } - CHolyTailFollow(child, dist - FRACUNIT); - } -} - -//============================================================================ -// -// CHolyTailRemove -// -//============================================================================ - -static void CHolyTailRemove(mobj_t * actor) -{ - mobj_t *child; - - child = actor->special1.m; - if (child) - { - CHolyTailRemove(child); - } - P_RemoveMobj(actor); -} - -//============================================================================ -// -// A_CHolyTail -// -//============================================================================ - -void A_CHolyTail(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *parent; - - parent = actor->special2.m; - - if (parent) - { - if (parent->state >= &states[parent->info->deathstate]) - { // Ghost removed, so remove all tail parts - CHolyTailRemove(actor); - return; - } - else if (P_TryMove(actor, parent->x - FixedMul(14 * FRACUNIT, - finecosine[parent-> - angle >> - ANGLETOFINESHIFT]), - parent->y - FixedMul(14 * FRACUNIT, - finesine[parent-> - angle >> - ANGLETOFINESHIFT]))) - { - actor->z = parent->z - 5 * FRACUNIT; - } - CHolyTailFollow(actor, 10 * FRACUNIT); - } -} - -//============================================================================ -// -// A_CHolyCheckScream -// -//============================================================================ - -void A_CHolyCheckScream(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - A_CHolySeek(actor, player, psp); - if (P_Random() < 20) - { - S_StartSound(actor, SFX_SPIRIT_ACTIVE); - } - if (!actor->special1.m) - { - CHolyFindTarget(actor); - } -} - -//============================================================================ -// -// A_CHolySpawnPuff -// -//============================================================================ - -void A_CHolySpawnPuff(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - P_SpawnMobj(actor->x, actor->y, actor->z, MT_HOLY_MISSILE_PUFF); -} - -//---------------------------------------------------------------------------- -// -// PROC A_FireConePL1 -// -//---------------------------------------------------------------------------- - -#define SHARDSPAWN_LEFT 1 -#define SHARDSPAWN_RIGHT 2 -#define SHARDSPAWN_UP 4 -#define SHARDSPAWN_DOWN 8 - -void A_FireConePL1(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - angle_t angle; - int damage; - int i; - mobj_t *pmo, *mo; - int conedone = false; - - pmo = player->mo; - player->mana[MANA_1] -= WeaponManaUse[player->class][player->readyweapon]; - S_StartSound(pmo, SFX_MAGE_SHARDS_FIRE); - - damage = 90 + (P_Random() & 15); - for (i = 0; i < 16; i++) - { - angle = pmo->angle + i * (ANG45 / 16); - P_AimLineAttack(pmo, angle, MELEERANGE); - if (linetarget) - { - pmo->flags2 |= MF2_ICEDAMAGE; - P_DamageMobj(linetarget, pmo, pmo, damage); - pmo->flags2 &= ~MF2_ICEDAMAGE; - conedone = true; - break; - } - } - - // didn't find any creatures, so fire projectiles - if (!conedone) - { - mo = P_SpawnPlayerMissile(pmo, MT_SHARDFX1); - if (mo) - { - mo->special1.i = SHARDSPAWN_LEFT | SHARDSPAWN_DOWN | SHARDSPAWN_UP - | SHARDSPAWN_RIGHT; - mo->special2.i = 3; // Set sperm count (levels of reproductivity) - mo->target = pmo; - mo->args[0] = 3; // Mark Initial shard as super damage - } - } -} - -void A_ShedShard(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - mobj_t *mo; - int spawndir = actor->special1.i; - int spermcount = actor->special2.i; - - if (spermcount <= 0) - return; // No sperm left - actor->special2.i = 0; - spermcount--; - - // every so many calls, spawn a new missile in it's set directions - if (spawndir & SHARDSPAWN_LEFT) - { - mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, - actor->angle + (ANG45 / 9), 0, - (20 + 2 * spermcount) << FRACBITS); - if (mo) - { - mo->special1.i = SHARDSPAWN_LEFT; - mo->special2.i = spermcount; - mo->momz = actor->momz; - mo->target = actor->target; - mo->args[0] = (spermcount == 3) ? 2 : 0; - } - } - if (spawndir & SHARDSPAWN_RIGHT) - { - mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, - actor->angle - (ANG45 / 9), 0, - (20 + 2 * spermcount) << FRACBITS); - if (mo) - { - mo->special1.i = SHARDSPAWN_RIGHT; - mo->special2.i = spermcount; - mo->momz = actor->momz; - mo->target = actor->target; - mo->args[0] = (spermcount == 3) ? 2 : 0; - } - } - if (spawndir & SHARDSPAWN_UP) - { - mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, actor->angle, - 0, (15 + 2 * spermcount) << FRACBITS); - if (mo) - { - mo->momz = actor->momz; - mo->z += 8 * FRACUNIT; - if (spermcount & 1) // Every other reproduction - mo->special1.i = - SHARDSPAWN_UP | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; - else - mo->special1.i = SHARDSPAWN_UP; - mo->special2.i = spermcount; - mo->target = actor->target; - mo->args[0] = (spermcount == 3) ? 2 : 0; - } - } - if (spawndir & SHARDSPAWN_DOWN) - { - mo = P_SpawnMissileAngleSpeed(actor, MT_SHARDFX1, actor->angle, - 0, (15 + 2 * spermcount) << FRACBITS); - if (mo) - { - mo->momz = actor->momz; - mo->z -= 4 * FRACUNIT; - if (spermcount & 1) // Every other reproduction - mo->special1.i = - SHARDSPAWN_DOWN | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; - else - mo->special1.i = SHARDSPAWN_DOWN; - mo->special2.i = spermcount; - mo->target = actor->target; - mo->args[0] = (spermcount == 3) ? 2 : 0; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC A_HideInCeiling -// -//---------------------------------------------------------------------------- - -/* -void A_HideInCeiling(mobj_t *actor) -{ - actor->z = actor->ceilingz+4*FRACUNIT; -} -*/ - -//---------------------------------------------------------------------------- -// -// PROC A_FloatPuff -// -//---------------------------------------------------------------------------- - -/* -void A_FloatPuff(mobj_t *puff) -{ - puff->momz += 1.8*FRACUNIT; -} -*/ - -void A_Light0(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - player->extralight = 0; -} - -/* -void A_Light1(player_t *player, pspdef_t *psp) -{ - player->extralight = 1; -} -*/ - -/* -void A_Light2(player_t *player, pspdef_t *psp) -{ - player->extralight = 2; -} -*/ - -//------------------------------------------------------------------------ -// -// PROC P_SetupPsprites -// -// Called at start of level for each player -// -//------------------------------------------------------------------------ - -void P_SetupPsprites(player_t * player) -{ - int i; - - // Remove all psprites - for (i = 0; i < NUMPSPRITES; i++) - { - player->psprites[i].state = NULL; - } - // Spawn the ready weapon - player->pendingweapon = player->readyweapon; - P_BringUpWeapon(player); -} - -//------------------------------------------------------------------------ -// -// PROC P_MovePsprites -// -// Called every tic by player thinking routine -// -//------------------------------------------------------------------------ - -void P_MovePsprites(player_t * player) -{ - int i; - pspdef_t *psp; - - psp = &player->psprites[0]; - for (i = 0; i < NUMPSPRITES; i++, psp++) - { - if (psp->state != 0) // a null state means not active - { - // drop tic count and possibly change state - if (psp->tics != -1) // a -1 tic count never changes - { - psp->tics--; - if (!psp->tics) - { - P_SetPsprite(player, i, psp->state->nextstate); - } - } - } - } - player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; - player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; -} diff --git a/games/NXDoom/src/hexen/p_setup.c b/games/NXDoom/src/hexen/p_setup.c deleted file mode 100644 index d71907727ae..00000000000 --- a/games/NXDoom/src/hexen/p_setup.c +++ /dev/null @@ -1,1273 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include -#include -#include "h2def.h" -#include "i_system.h" -#include "m_argv.h" -#include "m_bbox.h" -#include "m_misc.h" -#include "i_swap.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_rejectpad.h" - -// MACROS ------------------------------------------------------------------ - -#define MAPINFO_SCRIPT_NAME "MAPINFO" -#define MCMD_SKY1 1 -#define MCMD_SKY2 2 -#define MCMD_LIGHTNING 3 -#define MCMD_FADETABLE 4 -#define MCMD_DOUBLESKY 5 -#define MCMD_CLUSTER 6 -#define MCMD_WARPTRANS 7 -#define MCMD_NEXT 8 -#define MCMD_CDTRACK 9 -#define MCMD_CD_STARTTRACK 10 -#define MCMD_CD_END1TRACK 11 -#define MCMD_CD_END2TRACK 12 -#define MCMD_CD_END3TRACK 13 -#define MCMD_CD_INTERTRACK 14 -#define MCMD_CD_TITLETRACK 15 - -#define UNKNOWN_MAP_NAME "DEVELOPMENT MAP" -#define DEFAULT_SKY_NAME "SKY1" -#define DEFAULT_SONG_LUMP "DEFSONG" -#define DEFAULT_FADE_TABLE "COLORMAP" - -// TYPES ------------------------------------------------------------------- - -typedef struct mapInfo_s mapInfo_t; -struct mapInfo_s -{ - short cluster; - short warpTrans; - short nextMap; - short cdTrack; - char name[32]; - short sky1Texture; - short sky2Texture; - fixed_t sky1ScrollDelta; - fixed_t sky2ScrollDelta; - boolean doubleSky; - boolean lightning; - int fadetable; - char songLump[10]; -}; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -void P_SpawnMapThing(mapthing_t * mthing); - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static int QualifyMap(int map); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -int MapCount; -mapthing_t deathmatchstarts[MAXDEATHMATCHSTARTS], *deathmatch_p; -mapthing_t playerstarts[MAX_PLAYER_STARTS][MAXPLAYERS]; -int numvertexes; -vertex_t *vertexes; -int numsegs; -seg_t *segs; -int numsectors; -sector_t *sectors; -int numsubsectors; -subsector_t *subsectors; -int numnodes; -node_t *nodes; -int numlines; -line_t *lines; -int numsides; -side_t *sides; -static int totallines; -short *blockmaplump; // offsets in blockmap are from here -short *blockmap; -int bmapwidth, bmapheight; // in mapblocks -fixed_t bmaporgx, bmaporgy; // origin of block map -mobj_t **blocklinks; // for thing chains -byte *rejectmatrix; // for fast sight rejection - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static mapInfo_t MapInfo[99]; -static const char *MapCmdNames[] = { - "SKY1", - "SKY2", - "DOUBLESKY", - "LIGHTNING", - "FADETABLE", - "CLUSTER", - "WARPTRANS", - "NEXT", - "CDTRACK", - "CD_START_TRACK", - "CD_END1_TRACK", - "CD_END2_TRACK", - "CD_END3_TRACK", - "CD_INTERMISSION_TRACK", - "CD_TITLE_TRACK", - NULL -}; -static int MapCmdIDs[] = { - MCMD_SKY1, - MCMD_SKY2, - MCMD_DOUBLESKY, - MCMD_LIGHTNING, - MCMD_FADETABLE, - MCMD_CLUSTER, - MCMD_WARPTRANS, - MCMD_NEXT, - MCMD_CDTRACK, - MCMD_CD_STARTTRACK, - MCMD_CD_END1TRACK, - MCMD_CD_END2TRACK, - MCMD_CD_END3TRACK, - MCMD_CD_INTERTRACK, - MCMD_CD_TITLETRACK -}; - -static int cd_NonLevelTracks[6]; // Non-level specific song cd track numbers - -// CODE -------------------------------------------------------------------- - -/* -================= -= -= P_LoadVertexes -= -================= -*/ - -void P_LoadVertexes(int lump) -{ - byte *data; - int i; - mapvertex_t *ml; - vertex_t *li; - - numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t); - vertexes = Z_Malloc(numvertexes * sizeof(vertex_t), PU_LEVEL, 0); - data = W_CacheLumpNum(lump, PU_STATIC); - - ml = (mapvertex_t *) data; - li = vertexes; - for (i = 0; i < numvertexes; i++, li++, ml++) - { - li->x = SHORT(ml->x) << FRACBITS; - li->y = SHORT(ml->y) << FRACBITS; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSegs -= -================= -*/ - -void P_LoadSegs(int lump) -{ - byte *data; - int i; - mapseg_t *ml; - seg_t *li; - line_t *ldef; - int linedef, side; - - numsegs = W_LumpLength(lump) / sizeof(mapseg_t); - segs = Z_Malloc(numsegs * sizeof(seg_t), PU_LEVEL, 0); - memset(segs, 0, numsegs * sizeof(seg_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - ml = (mapseg_t *) data; - li = segs; - for (i = 0; i < numsegs; i++, li++, ml++) - { - li->v1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; - - li->angle = (SHORT(ml->angle)) << 16; - li->offset = (SHORT(ml->offset)) << 16; - linedef = SHORT(ml->linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - side = SHORT(ml->side); - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef->flags & ML_TWOSIDED) - li->backsector = sides[ldef->sidenum[side ^ 1]].sector; - else - li->backsector = 0; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSubsectors -= -================= -*/ - -void P_LoadSubsectors(int lump) -{ - byte *data; - int i; - mapsubsector_t *ms; - subsector_t *ss; - - numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t); - subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0); - data = W_CacheLumpNum(lump, PU_STATIC); - - ms = (mapsubsector_t *) data; - memset(subsectors, 0, numsubsectors * sizeof(subsector_t)); - ss = subsectors; - for (i = 0; i < numsubsectors; i++, ss++, ms++) - { - ss->numlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSectors -= -================= -*/ - -void P_LoadSectors(int lump) -{ - byte *data; - int i; - mapsector_t *ms; - sector_t *ss; - - numsectors = W_LumpLength(lump) / sizeof(mapsector_t); - sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0); - memset(sectors, 0, numsectors * sizeof(sector_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - ms = (mapsector_t *) data; - ss = sectors; - - for (i = 0; i < numsectors; i++, ss++, ms++) - { - ss->floorheight = SHORT(ms->floorheight) << FRACBITS; - ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS; - ss->floorpic = R_FlatNumForName(ms->floorpic); - ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); - ss->lightlevel = SHORT(ms->lightlevel); - ss->special = SHORT(ms->special); - ss->tag = SHORT(ms->tag); - ss->thinglist = NULL; - ss->seqType = SEQTYPE_STONE; // default seqType - } - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadNodes -= -================= -*/ - -void P_LoadNodes(int lump) -{ - byte *data; - int i, j, k; - mapnode_t *mn; - node_t *no; - - numnodes = W_LumpLength(lump) / sizeof(mapnode_t); - nodes = Z_Malloc(numnodes * sizeof(node_t), PU_LEVEL, 0); - data = W_CacheLumpNum(lump, PU_STATIC); - - mn = (mapnode_t *) data; - no = nodes; - for (i = 0; i < numnodes; i++, no++, mn++) - { - no->x = SHORT(mn->x) << FRACBITS; - no->y = SHORT(mn->y) << FRACBITS; - no->dx = SHORT(mn->dx) << FRACBITS; - no->dy = SHORT(mn->dy) << FRACBITS; - for (j = 0; j < 2; j++) - { - no->children[j] = SHORT(mn->children[j]); - for (k = 0; k < 4; k++) - no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; - } - } - W_ReleaseLumpNum(lump); -} - -//========================================================================== -// -// P_LoadThings -// -//========================================================================== - -void P_LoadThings(int lump) -{ - byte *data; - int i; - mapthing_t spawnthing; - mapthing_t *mt; - int numthings; - int playerCount; - int deathSpotsCount; - - data = W_CacheLumpNum(lump, PU_STATIC); - numthings = W_LumpLength(lump) / sizeof(mapthing_t); - - mt = (mapthing_t *) data; - for (i = 0; i < numthings; i++, mt++) - { - spawnthing.tid = SHORT(mt->tid); - spawnthing.x = SHORT(mt->x); - spawnthing.y = SHORT(mt->y); - spawnthing.height = SHORT(mt->height); - spawnthing.angle = SHORT(mt->angle); - spawnthing.type = SHORT(mt->type); - spawnthing.options = SHORT(mt->options); - - spawnthing.special = mt->special; - spawnthing.arg1 = mt->arg1; - spawnthing.arg2 = mt->arg2; - spawnthing.arg3 = mt->arg3; - spawnthing.arg4 = mt->arg4; - spawnthing.arg5 = mt->arg5; - - P_SpawnMapThing(&spawnthing); - } - P_CreateTIDList(); - P_InitCreatureCorpseQueue(false); // false = do NOT scan for corpses - W_ReleaseLumpNum(lump); - - if (!deathmatch) - { // Don't need to check deathmatch spots - return; - } - playerCount = 0; - for (i = 0; i < maxplayers; i++) - { - playerCount += playeringame[i]; - } - deathSpotsCount = deathmatch_p - deathmatchstarts; - if (deathSpotsCount < playerCount) - { - I_Error("P_LoadThings: Player count (%d) exceeds deathmatch " - "spots (%d)", playerCount, deathSpotsCount); - } -} - -/* -================= -= -= P_LoadLineDefs -= -================= -*/ - -void P_LoadLineDefs(int lump) -{ - byte *data; - int i; - maplinedef_t *mld; - line_t *ld; - vertex_t *v1, *v2; - - numlines = W_LumpLength(lump) / sizeof(maplinedef_t); - lines = Z_Malloc(numlines * sizeof(line_t), PU_LEVEL, 0); - memset(lines, 0, numlines * sizeof(line_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - mld = (maplinedef_t *) data; - ld = lines; - for (i = 0; i < numlines; i++, mld++, ld++) - { - ld->flags = SHORT(mld->flags); - - // Old line special info ... - //ld->special = SHORT(mld->special); - //ld->tag = SHORT(mld->tag); - - // New line special info ... - ld->special = mld->special; - ld->arg1 = mld->arg1; - ld->arg2 = mld->arg2; - ld->arg3 = mld->arg3; - ld->arg4 = mld->arg4; - ld->arg5 = mld->arg5; - - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else - { - if (FixedDiv(ld->dy, ld->dx) > 0) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - } - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - if (ld->sidenum[0] != -1) - ld->frontsector = sides[ld->sidenum[0]].sector; - else - ld->frontsector = 0; - if (ld->sidenum[1] != -1) - ld->backsector = sides[ld->sidenum[1]].sector; - else - ld->backsector = 0; - } - - W_ReleaseLumpNum(lump); -} - - -/* -================= -= -= P_LoadSideDefs -= -================= -*/ - -void P_LoadSideDefs(int lump) -{ - byte *data; - int i; - mapsidedef_t *msd; - side_t *sd; - - numsides = W_LumpLength(lump) / sizeof(mapsidedef_t); - sides = Z_Malloc(numsides * sizeof(side_t), PU_LEVEL, 0); - memset(sides, 0, numsides * sizeof(side_t)); - data = W_CacheLumpNum(lump, PU_STATIC); - - msd = (mapsidedef_t *) data; - sd = sides; - - for (i = 0; i < numsides; i++, msd++, sd++) - { - sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS; - sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS; - sd->toptexture = R_TextureNumForName(msd->toptexture); - sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); - sd->midtexture = R_TextureNumForName(msd->midtexture); - sd->sector = §ors[SHORT(msd->sector)]; - } - W_ReleaseLumpNum(lump); -} - -/* -================= -= -= P_LoadBlockMap -= -================= -*/ - -void P_LoadBlockMap(int lump) -{ - int i, count; - int lumplen; - - lumplen = W_LumpLength(lump); - - blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); - W_ReadLump(lump, blockmaplump); - blockmap = blockmaplump + 4; - - // Swap all short integers to native byte ordering: - - count = lumplen / 2; - - for (i = 0; i < count; i++) - blockmaplump[i] = SHORT(blockmaplump[i]); - - bmaporgx = blockmaplump[0] << FRACBITS; - bmaporgy = blockmaplump[1] << FRACBITS; - bmapwidth = blockmaplump[2]; - bmapheight = blockmaplump[3]; - - // clear out mobj chains - - count = sizeof(*blocklinks) * bmapwidth * bmapheight; - blocklinks = Z_Malloc(count, PU_LEVEL, 0); - memset(blocklinks, 0, count); -} - - - - -/* -================= -= -= P_GroupLines -= -= Builds sector line lists and subsector sector numbers -= Finds block bounding boxes for sectors -================= -*/ - -void P_DegenMobjThinker(thinker_t *thinker) -{ - (void) thinker; - I_Error("This function should never get called."); -} - -void P_GroupLines(void) -{ - line_t **linebuffer; - int i, j; - line_t *li; - sector_t *sector; - subsector_t *ss; - seg_t *seg; - fixed_t bbox[4]; - int block; - -// look up sector number for each subsector - ss = subsectors; - for (i = 0; i < numsubsectors; i++, ss++) - { - seg = &segs[ss->firstline]; - ss->sector = seg->sidedef->sector; - } - -// count number of lines in each sector - li = lines; - totallines = 0; - for (i = 0; i < numlines; i++, li++) - { - totallines++; - li->frontsector->linecount++; - if (li->backsector && li->backsector != li->frontsector) - { - li->backsector->linecount++; - totallines++; - } - } - -// build line tables for each sector - linebuffer = Z_Malloc(totallines * sizeof(line_t *), PU_LEVEL, 0); - sector = sectors; - for (i = 0; i < numsectors; i++, sector++) - { - M_ClearBox(bbox); - sector->lines = linebuffer; - li = lines; - for (j = 0; j < numlines; j++, li++) - { - if (li->frontsector == sector || li->backsector == sector) - { - *linebuffer++ = li; - M_AddToBox(bbox, li->v1->x, li->v1->y); - M_AddToBox(bbox, li->v2->x, li->v2->y); - } - } - if (linebuffer - sector->lines != sector->linecount) - I_Error("P_GroupLines: miscounted"); - - // set the degenmobj_t to the middle of the bounding box - sector->soundorg.x = (bbox[BOXRIGHT] + bbox[BOXLEFT]) / 2; - sector->soundorg.y = (bbox[BOXTOP] + bbox[BOXBOTTOM]) / 2; - sector->soundorg.thinker.function = (think_t) P_DegenMobjThinker; - - // adjust bounding box to map blocks - block = (bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - block = block >= bmapheight ? bmapheight - 1 : block; - sector->blockbox[BOXTOP] = block; - - block = (bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXBOTTOM] = block; - - block = (bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - block = block >= bmapwidth ? bmapwidth - 1 : block; - sector->blockbox[BOXRIGHT] = block; - - block = (bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXLEFT] = block; - } - -} - - -static void P_LoadReject(int lumpnum) -{ - int minlength; - int lumplen; - - // Calculate the size that the REJECT lump *should* be. - - minlength = (numsectors * numsectors + 7) / 8; - - // If the lump meets the minimum length, it can be loaded directly. - // Otherwise, we need to allocate a buffer of the correct size - // and pad it with appropriate data. - - lumplen = W_LumpLength(lumpnum); - - if (lumplen >= minlength) - { - rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); - } - else - { - rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); - W_ReadLump(lumpnum, rejectmatrix); - - PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); - } -} - -//============================================================================= - -lumpinfo_t *maplumpinfo; - -/* -================= -= -= P_SetupLevel -= -================= -*/ - -void P_SetupLevel(int episode, int map, int playermask, skill_t skill) -{ - int i; - int parm; - char lumpname[9]; - int lumpnum; - mobj_t *mobj; - - for (i = 0; i < maxplayers; i++) - { - players[i].killcount = players[i].secretcount - = players[i].itemcount = 0; - } - players[consoleplayer].viewz = 1; // will be set by player think - - // Waiting-for-level-load song; not played if playing music from CD - // (the seek time will be so long it will just make loading take - // longer) - if (!cdmusic) - { - S_StartSongName("chess", true); - } - - Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); - - P_InitThinkers(); - leveltime = 0; - - M_snprintf(lumpname, sizeof(lumpname), "MAP%02d", map); - lumpnum = W_GetNumForName(lumpname); - - maplumpinfo = lumpinfo[lumpnum]; - - // - // Begin processing map lumps - // Note: most of this ordering is important - // - P_LoadBlockMap(lumpnum + ML_BLOCKMAP); - P_LoadVertexes(lumpnum + ML_VERTEXES); - P_LoadSectors(lumpnum + ML_SECTORS); - P_LoadSideDefs(lumpnum + ML_SIDEDEFS); - P_LoadLineDefs(lumpnum + ML_LINEDEFS); - P_LoadSubsectors(lumpnum + ML_SSECTORS); - P_LoadNodes(lumpnum + ML_NODES); - P_LoadSegs(lumpnum + ML_SEGS); - P_GroupLines(); - P_LoadReject(lumpnum + ML_REJECT); - bodyqueslot = 0; - po_NumPolyobjs = 0; - deathmatch_p = deathmatchstarts; - P_LoadThings(lumpnum + ML_THINGS); - PO_Init(lumpnum + ML_THINGS); // Initialize the polyobjs - P_LoadACScripts(lumpnum + ML_BEHAVIOR); // ACS object code - // - // End of map lump processing - // - - // If deathmatch, randomly spawn the active players - TimerGame = 0; - if (deathmatch) - { - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { // must give a player spot before deathmatchspawn - mobj = P_SpawnMobj(playerstarts[0][i].x << 16, - playerstarts[0][i].y << 16, 0, - MT_PLAYER_FIGHTER); - players[i].mo = mobj; - G_DeathMatchSpawnPlayer(i); - P_RemoveMobj(mobj); - } - } - - //! - // @arg - // @category net - // @vanilla - // - // For multiplayer games: exit each level after n minutes. - // - - parm = M_CheckParmWithArgs("-timer", 1); - if (parm) - { - TimerGame = atoi(myargv[parm + 1]) * 35 * 60; - } - } - -// set up world state - P_SpawnSpecials(); - -// build subsector connect matrix -// P_ConnectSubsectors (); - -// Load colormap and set the fullbright flag - i = P_GetMapFadeTable(gamemap); - W_ReadLump(i, colormaps); - if (i == W_GetNumForName("COLORMAP")) - { - LevelUseFullBright = true; - } - else - { // Probably fog ... don't use fullbright sprites - LevelUseFullBright = false; - } - -// preload graphics - if (precache) - R_PrecacheLevel(); - - // Check if the level is a lightning level - P_InitLightning(); - - S_StopAllSound(); - SN_StopAllSequences(); - S_StartSong(gamemap, true); - -//printf ("free memory: 0x%x\n", Z_FreeMemory()); - -} - -//========================================================================== -// -// InitMapInfo -// -//========================================================================== - -static void InitMapInfo(void) -{ - int map; - int mapMax; - int mcmdValue; - mapInfo_t *info; - char songMulch[10]; - const char *default_sky_name = DEFAULT_SKY_NAME; - - mapMax = 1; - - if (gamemode == shareware) - { - default_sky_name = "SKY2"; - } - - // Put defaults into MapInfo[0] - info = MapInfo; - info->cluster = 0; - info->warpTrans = 0; - info->nextMap = 1; // Always go to map 1 if not specified - info->cdTrack = 1; - info->sky1Texture = R_TextureNumForName(default_sky_name); - info->sky2Texture = info->sky1Texture; - info->sky1ScrollDelta = 0; - info->sky2ScrollDelta = 0; - info->doubleSky = false; - info->lightning = false; - info->fadetable = W_GetNumForName(DEFAULT_FADE_TABLE); - M_StringCopy(info->name, UNKNOWN_MAP_NAME, sizeof(info->name)); - -// M_StringCopy(info->songLump, DEFAULT_SONG_LUMP, sizeof(info->songLump)); - SC_Open(MAPINFO_SCRIPT_NAME); - while (SC_GetString()) - { - if (SC_Compare("MAP") == false) - { - SC_ScriptError(NULL); - } - SC_MustGetNumber(); - if (sc_Number < 1 || sc_Number > 99) - { // - SC_ScriptError(NULL); - } - map = sc_Number; - - info = &MapInfo[map]; - - // Save song lump name - M_StringCopy(songMulch, info->songLump, sizeof(songMulch)); - - // Copy defaults to current map definition - memcpy(info, &MapInfo[0], sizeof(*info)); - - // Restore song lump name - M_StringCopy(info->songLump, songMulch, sizeof(info->songLump)); - - // The warp translation defaults to the map number - info->warpTrans = map; - - // Map name must follow the number - SC_MustGetString(); - M_StringCopy(info->name, sc_String, sizeof(info->name)); - - // Process optional tokens - while (SC_GetString()) - { - if (SC_Compare("MAP")) - { // Start next map definition - SC_UnGet(); - break; - } - mcmdValue = MapCmdIDs[SC_MustMatchString(MapCmdNames)]; - switch (mcmdValue) - { - case MCMD_CLUSTER: - SC_MustGetNumber(); - info->cluster = sc_Number; - break; - case MCMD_WARPTRANS: - SC_MustGetNumber(); - info->warpTrans = sc_Number; - break; - case MCMD_NEXT: - SC_MustGetNumber(); - info->nextMap = sc_Number; - break; - case MCMD_CDTRACK: - SC_MustGetNumber(); - info->cdTrack = sc_Number; - break; - case MCMD_SKY1: - SC_MustGetString(); - info->sky1Texture = R_TextureNumForName(sc_String); - SC_MustGetNumber(); - info->sky1ScrollDelta = sc_Number << 8; - break; - case MCMD_SKY2: - SC_MustGetString(); - info->sky2Texture = R_TextureNumForName(sc_String); - SC_MustGetNumber(); - info->sky2ScrollDelta = sc_Number << 8; - break; - case MCMD_DOUBLESKY: - info->doubleSky = true; - break; - case MCMD_LIGHTNING: - info->lightning = true; - break; - case MCMD_FADETABLE: - SC_MustGetString(); - info->fadetable = W_GetNumForName(sc_String); - break; - case MCMD_CD_STARTTRACK: - case MCMD_CD_END1TRACK: - case MCMD_CD_END2TRACK: - case MCMD_CD_END3TRACK: - case MCMD_CD_INTERTRACK: - case MCMD_CD_TITLETRACK: - SC_MustGetNumber(); - cd_NonLevelTracks[mcmdValue - MCMD_CD_STARTTRACK] = - sc_Number; - break; - } - } - mapMax = map > mapMax ? map : mapMax; - } - SC_Close(); - MapCount = mapMax; -} - -//========================================================================== -// -// P_GetMapCluster -// -//========================================================================== - -int P_GetMapCluster(int map) -{ - return MapInfo[QualifyMap(map)].cluster; -} - -//========================================================================== -// -// P_GetMapCDTrack -// -//========================================================================== - -int P_GetMapCDTrack(int map) -{ - return MapInfo[QualifyMap(map)].cdTrack; -} - -//========================================================================== -// -// P_GetMapWarpTrans -// -//========================================================================== - -int P_GetMapWarpTrans(int map) -{ - return MapInfo[QualifyMap(map)].warpTrans; -} - -//========================================================================== -// -// P_GetMapNextMap -// -//========================================================================== - -int P_GetMapNextMap(int map) -{ - return MapInfo[QualifyMap(map)].nextMap; -} - -//========================================================================== -// -// P_TranslateMap -// -// Returns the actual map number given a warp map number. -// -//========================================================================== - -int P_TranslateMap(int map) -{ - int i; - - for (i = 1; i < 99; i++) // Make this a macro - { - if (MapInfo[i].warpTrans == map) - { - return i; - } - } - // Not found - return -1; -} - -//========================================================================== -// -// P_GetMapSky1Texture -// -//========================================================================== - -int P_GetMapSky1Texture(int map) -{ - return MapInfo[QualifyMap(map)].sky1Texture; -} - -//========================================================================== -// -// P_GetMapSky2Texture -// -//========================================================================== - -int P_GetMapSky2Texture(int map) -{ - return MapInfo[QualifyMap(map)].sky2Texture; -} - -//========================================================================== -// -// P_GetMapName -// -//========================================================================== - -char *P_GetMapName(int map) -{ - return MapInfo[QualifyMap(map)].name; -} - -//========================================================================== -// -// P_GetMapSky1ScrollDelta -// -//========================================================================== - -fixed_t P_GetMapSky1ScrollDelta(int map) -{ - return MapInfo[QualifyMap(map)].sky1ScrollDelta; -} - -//========================================================================== -// -// P_GetMapSky2ScrollDelta -// -//========================================================================== - -fixed_t P_GetMapSky2ScrollDelta(int map) -{ - return MapInfo[QualifyMap(map)].sky2ScrollDelta; -} - -//========================================================================== -// -// P_GetMapDoubleSky -// -//========================================================================== - -boolean P_GetMapDoubleSky(int map) -{ - return MapInfo[QualifyMap(map)].doubleSky; -} - -//========================================================================== -// -// P_GetMapLightning -// -//========================================================================== - -boolean P_GetMapLightning(int map) -{ - return MapInfo[QualifyMap(map)].lightning; -} - -//========================================================================== -// -// P_GetMapFadeTable -// -//========================================================================== - -boolean P_GetMapFadeTable(int map) -{ - return MapInfo[QualifyMap(map)].fadetable; -} - -//========================================================================== -// -// P_GetMapSongLump -// -//========================================================================== - -char *P_GetMapSongLump(int map) -{ - if (!strcasecmp(MapInfo[QualifyMap(map)].songLump, DEFAULT_SONG_LUMP)) - { - return NULL; - } - else - { - return MapInfo[QualifyMap(map)].songLump; - } -} - -//========================================================================== -// -// P_PutMapSongLump -// -//========================================================================== - -void P_PutMapSongLump(int map, char *lumpName) -{ - if (map < 1 || map > MapCount) - { - return; - } - M_StringCopy(MapInfo[map].songLump, lumpName, - sizeof(MapInfo[map].songLump)); -} - -//========================================================================== -// -// P_GetCDStartTrack -// -//========================================================================== - -int P_GetCDStartTrack(void) -{ - return cd_NonLevelTracks[MCMD_CD_STARTTRACK - MCMD_CD_STARTTRACK]; -} - -//========================================================================== -// -// P_GetCDEnd1Track -// -//========================================================================== - -int P_GetCDEnd1Track(void) -{ - return cd_NonLevelTracks[MCMD_CD_END1TRACK - MCMD_CD_STARTTRACK]; -} - -//========================================================================== -// -// P_GetCDEnd2Track -// -//========================================================================== - -int P_GetCDEnd2Track(void) -{ - return cd_NonLevelTracks[MCMD_CD_END2TRACK - MCMD_CD_STARTTRACK]; -} - -//========================================================================== -// -// P_GetCDEnd3Track -// -//========================================================================== - -int P_GetCDEnd3Track(void) -{ - return cd_NonLevelTracks[MCMD_CD_END3TRACK - MCMD_CD_STARTTRACK]; -} - -//========================================================================== -// -// P_GetCDIntermissionTrack -// -//========================================================================== - -int P_GetCDIntermissionTrack(void) -{ - return cd_NonLevelTracks[MCMD_CD_INTERTRACK - MCMD_CD_STARTTRACK]; -} - -//========================================================================== -// -// P_GetCDTitleTrack -// -//========================================================================== - -int P_GetCDTitleTrack(void) -{ - return cd_NonLevelTracks[MCMD_CD_TITLETRACK - MCMD_CD_STARTTRACK]; -} - -//========================================================================== -// -// QualifyMap -// -//========================================================================== - -static int QualifyMap(int map) -{ - return (map < 1 || map > MapCount) ? 0 : map; -} - -//========================================================================== -// -// P_Init -// -//========================================================================== - -void P_Init(void) -{ - InitMapInfo(); - P_InitSwitchList(); - P_InitFTAnims(); // Init flat and texture animations - P_InitTerrainTypes(); - P_InitLava(); - R_InitSprites(sprnames); -} - - -// Special early initializer needed to start sound before R_Init() -void InitMapMusicInfo(void) -{ - int i; - - for (i = 0; i < 99; i++) - { - M_StringCopy(MapInfo[i].songLump, DEFAULT_SONG_LUMP, - sizeof(MapInfo[i].songLump)); - } - MapCount = 98; -} - -/* -void My_Debug(void) -{ - int i; - - printf("My debug stuff ----------------------\n"); - printf("gamemap=%d\n",gamemap); - for (i=0; i<10; i++) - { - printf("i=%d songlump=%s\n",i,MapInfo[i].songLump); - } -} -*/ diff --git a/games/NXDoom/src/hexen/p_sight.c b/games/NXDoom/src/hexen/p_sight.c deleted file mode 100644 index b5efd07f604..00000000000 --- a/games/NXDoom/src/hexen/p_sight.c +++ /dev/null @@ -1,398 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "p_local.h" - -/* -============================================================================== - - P_CheckSight - -This uses specialized forms of the maputils routines for optimized performance - -============================================================================== -*/ - -fixed_t sightzstart; // eye z of looker -fixed_t topslope, bottomslope; // slopes to top and bottom of target - -int sightcounts[3]; - -/* -============== -= -= PTR_SightTraverse -= -============== -*/ - -boolean PTR_SightTraverse(intercept_t * in) -{ - line_t *li; - fixed_t slope; - - li = in->d.line; - -// -// crosses a two sided line -// - P_LineOpening(li); - - if (openbottom >= opentop) // quick test for totally closed doors - return false; // stop - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv(openbottom - sightzstart, in->frac); - if (slope > bottomslope) - bottomslope = slope; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv(opentop - sightzstart, in->frac); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - - return true; // keep going -} - - - -/* -================== -= -= P_SightBlockLinesIterator -= -=================== -*/ - -boolean P_SightBlockLinesIterator(int x, int y) -{ - int offset; - short *list; - line_t *ld; - int s1, s2; - divline_t dl; - - polyblock_t *polyLink; - seg_t **segList; - int i; - - offset = y * bmapwidth + x; - - polyLink = PolyBlockMap[offset]; - while (polyLink) - { - if (polyLink->polyobj) - { // only check non-empty links - if (polyLink->polyobj->validcount != validcount) - { - segList = polyLink->polyobj->segs; - for (i = 0; i < polyLink->polyobj->numsegs; i++, segList++) - { - ld = (*segList)->linedef; - if (ld->validcount == validcount) - { - continue; - } - ld->validcount = validcount; - s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); - if (s1 == s2) - continue; // line isn't crossed - P_MakeDivline(ld, &dl); - s1 = P_PointOnDivlineSide(trace.x, trace.y, &dl); - s2 = P_PointOnDivlineSide(trace.x + trace.dx, - trace.y + trace.dy, &dl); - if (s1 == s2) - continue; // line isn't crossed - - // try to early out the check - if (!ld->backsector) - return false; // stop checking - - // store the line for later intersection testing - intercept_p->d.line = ld; - intercept_p++; - } - polyLink->polyobj->validcount = validcount; - } - } - polyLink = polyLink->next; - } - - offset = *(blockmap + offset); - - for (list = blockmaplump + offset; *list != -1; list++) - { - ld = &lines[*list]; - if (ld->validcount == validcount) - continue; // line has already been checked - ld->validcount = validcount; - - s1 = P_PointOnDivlineSide(ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide(ld->v2->x, ld->v2->y, &trace); - if (s1 == s2) - continue; // line isn't crossed - P_MakeDivline(ld, &dl); - s1 = P_PointOnDivlineSide(trace.x, trace.y, &dl); - s2 = P_PointOnDivlineSide(trace.x + trace.dx, trace.y + trace.dy, - &dl); - if (s1 == s2) - continue; // line isn't crossed - - // try to early out the check - if (!ld->backsector) - return false; // stop checking - - // store the line for later intersection testing - intercept_p->d.line = ld; - intercept_p++; - - } - - return true; // everything was checked -} - -/* -==================== -= -= P_SightTraverseIntercepts -= -= Returns true if the traverser function returns true for all lines -==================== -*/ - -boolean P_SightTraverseIntercepts(void) -{ - int count; - fixed_t dist; - intercept_t *scan, *in; - divline_t dl; - - count = intercept_p - intercepts; -// -// calculate intercept distance -// - for (scan = intercepts; scan < intercept_p; scan++) - { - P_MakeDivline(scan->d.line, &dl); - scan->frac = P_InterceptVector(&trace, &dl); - } - -// -// go through in order -// - in = 0; // shut up compiler warning - - while (count--) - { - dist = INT_MAX; - for (scan = intercepts; scan < intercept_p; scan++) - if (scan->frac < dist) - { - dist = scan->frac; - in = scan; - } - - if (!PTR_SightTraverse(in)) - return false; // don't bother going farther - in->frac = INT_MAX; - } - - return true; // everything was traversed -} - - - -/* -================== -= -= P_SightPathTraverse -= -= Traces a line from x1,y1 to x2,y2, calling the traverser function for each -= Returns true if the traverser function returns true for all lines -================== -*/ - -boolean P_SightPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) -{ - fixed_t xt1, yt1, xt2, yt2; - fixed_t xstep, ystep; - fixed_t partial; - fixed_t xintercept, yintercept; - int mapx, mapy, mapxstep, mapystep; - int count; - - validcount++; - intercept_p = intercepts; - - if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0) - x1 += FRACUNIT; // don't side exactly on a line - if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0) - y1 += FRACUNIT; // don't side exactly on a line - trace.x = x1; - trace.y = y1; - trace.dx = x2 - x1; - trace.dy = y2 - y1; - - x1 -= bmaporgx; - y1 -= bmaporgy; - xt1 = x1 >> MAPBLOCKSHIFT; - yt1 = y1 >> MAPBLOCKSHIFT; - - x2 -= bmaporgx; - y2 -= bmaporgy; - xt2 = x2 >> MAPBLOCKSHIFT; - yt2 = y2 >> MAPBLOCKSHIFT; - -// points should never be out of bounds, but check once instead of -// each block - if (xt1 < 0 || yt1 < 0 || xt1 >= bmapwidth || yt1 >= bmapheight - || xt2 < 0 || yt2 < 0 || xt2 >= bmapwidth || yt2 >= bmapheight) - return false; - - if (xt2 > xt1) - { - mapxstep = 1; - partial = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else if (xt2 < xt1) - { - mapxstep = -1; - partial = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1); - ystep = FixedDiv(y2 - y1, abs(x2 - x1)); - } - else - { - mapxstep = 0; - partial = FRACUNIT; - ystep = 256 * FRACUNIT; - } - yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partial, ystep); - - - if (yt2 > yt1) - { - mapystep = 1; - partial = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1)); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partial = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1); - xstep = FixedDiv(x2 - x1, abs(y2 - y1)); - } - else - { - mapystep = 0; - partial = FRACUNIT; - xstep = 256 * FRACUNIT; - } - xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partial, xstep); - - -// -// step through map blocks -// Count is present to prevent a round off error from skipping the break - mapx = xt1; - mapy = yt1; - - - for (count = 0; count < 64; count++) - { - if (!P_SightBlockLinesIterator(mapx, mapy)) - { - sightcounts[1]++; - return false; // early out - } - - if (mapx == xt2 && mapy == yt2) - break; - - if ((yintercept >> FRACBITS) == mapy) - { - yintercept += ystep; - mapx += mapxstep; - } - else if ((xintercept >> FRACBITS) == mapx) - { - xintercept += xstep; - mapy += mapystep; - } - - } - - -// -// couldn't early out, so go through the sorted list -// - sightcounts[2]++; - - return P_SightTraverseIntercepts(); -} - - - -/* -===================== -= -= P_CheckSight -= -= Returns true if a straight line between t1 and t2 is unobstructed -= look from eyes of t1 to any part of t2 -= -===================== -*/ - -boolean P_CheckSight(mobj_t * t1, mobj_t * t2) -{ - int s1, s2; - int pnum, bytenum, bitnum; - -// -// check for trivial rejection -// - s1 = (t1->subsector->sector - sectors); - s2 = (t2->subsector->sector - sectors); - pnum = s1 * numsectors + s2; - bytenum = pnum >> 3; - bitnum = 1 << (pnum & 7); - - if (rejectmatrix[bytenum] & bitnum) - { - sightcounts[0]++; - return false; // can't possibly be connected - } - -// -// check precisely -// - sightzstart = t1->z + t1->height - (t1->height >> 2); - topslope = (t2->z + t2->height) - sightzstart; - bottomslope = (t2->z) - sightzstart; - - return P_SightPathTraverse(t1->x, t1->y, t2->x, t2->y); -} diff --git a/games/NXDoom/src/hexen/p_spec.c b/games/NXDoom/src/hexen/p_spec.c deleted file mode 100644 index 400bf70df32..00000000000 --- a/games/NXDoom/src/hexen/p_spec.c +++ /dev/null @@ -1,1202 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "i_system.h" -#include "m_misc.h" -#include "p_local.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -#define MAX_TAGGED_LINES 64 - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static boolean CheckedLockedDoor(mobj_t * mo, byte lock); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -int *TerrainTypes; -struct -{ - const char *name; - int type; -} TerrainTypeDefs[] = -{ - { - "X_005", FLOOR_WATER}, - { - "X_001", FLOOR_LAVA}, - { - "X_009", FLOOR_SLUDGE}, - { - "F_033", FLOOR_ICE}, - { - "END", -1} -}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static struct -{ - line_t *line; - int lineTag; -} TaggedLines[MAX_TAGGED_LINES]; -static int TaggedLineCount; - -mobj_t LavaInflictor; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// P_InitLava -// -//========================================================================== - -void P_InitLava(void) -{ - memset(&LavaInflictor, 0, sizeof(mobj_t)); - LavaInflictor.type = MT_CIRCLEFLAME; - LavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST; -} - -//========================================================================== -// -// P_InitTerrainTypes -// -//========================================================================== - -void P_InitTerrainTypes(void) -{ - int i; - int lump; - int size; - - size = (numflats + 1) * sizeof(int); - TerrainTypes = Z_Malloc(size, PU_STATIC, 0); - memset(TerrainTypes, 0, size); - for (i = 0; TerrainTypeDefs[i].type != -1; i++) - { - lump = W_CheckNumForName(TerrainTypeDefs[i].name); - if (lump != -1) - { - TerrainTypes[lump - firstflat] = TerrainTypeDefs[i].type; - } - } -} - -//========================================================================== -// -// getSide -// -// Will return a side_t* given the number of the current sector, the -// line number, and the side (0/1) that you want. -// -//========================================================================== - -/* -side_t *getSide(int currentSector, int line, int side) -{ - return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; -} -*/ - -//========================================================================== -// -// getSector -// -// Will return a sector_t* given the number of the current sector, the -// line number, and the side (0/1) that you want. -// -//========================================================================== - -/* -sector_t *getSector(int currentSector, int line, int side) -{ - return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; -} -*/ - -//========================================================================== -// -// twoSided -// -// Given the sector number and the line number, will tell you whether -// the line is two-sided or not. -// -//========================================================================== - -/* -int twoSided(int sector, int line) -{ - return (sectors[sector].lines[line])->flags & ML_TWOSIDED; -} -*/ - -//================================================================== -// -// Return sector_t * of sector next to current. NULL if not two-sided line -// -//================================================================== -sector_t *getNextSector(line_t * line, sector_t * sec) -{ - if (!(line->flags & ML_TWOSIDED)) - return NULL; - - if (line->frontsector == sec) - return line->backsector; - - return line->frontsector; -} - -//================================================================== -// -// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindLowestFloorSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t floor = sec->floorheight; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->floorheight < floor) - floor = other->floorheight; - } - return floor; -} - -//================================================================== -// -// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindHighestFloorSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t floor = -500 * FRACUNIT; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->floorheight > floor) - floor = other->floorheight; - } - return floor; -} - -//================================================================== -// -// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight) -{ - int i; - int h; - int min; - line_t *check; - sector_t *other; - fixed_t height = currentheight; - fixed_t heightlist[20]; // 20 adjoining sectors max! - - heightlist[0] = 0; - - for (i = 0, h = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->floorheight > height) - heightlist[h++] = other->floorheight; - } - - // - // Find lowest height in list - // - min = heightlist[0]; - for (i = 1; i < h; i++) - if (heightlist[i] < min) - min = heightlist[i]; - - return min; -} - -//================================================================== -// -// FIND LOWEST CEILING IN THE SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindLowestCeilingSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t height = INT_MAX; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->ceilingheight < height) - height = other->ceilingheight; - } - return height; -} - -//================================================================== -// -// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS -// -//================================================================== -fixed_t P_FindHighestCeilingSurrounding(sector_t * sec) -{ - int i; - line_t *check; - sector_t *other; - fixed_t height = 0; - - for (i = 0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check, sec); - if (!other) - continue; - if (other->ceilingheight > height) - height = other->ceilingheight; - } - return height; -} - -//================================================================== -// -// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO -// -//================================================================== - -/* -int P_FindSectorFromLineTag(line_t *line,int start) -{ - int i; - - for (i=start+1;iarg1) - return i; - return -1; -} -*/ - -//========================================================================= -// -// P_FindSectorFromTag -// -//========================================================================= - -int P_FindSectorFromTag(int tag, int start) -{ - int i; - - for (i = start + 1; i < numsectors; i++) - { - if (sectors[i].tag == tag) - { - return i; - } - } - return -1; -} - -//================================================================== -// -// Find minimum light from an adjacent sector -// -//================================================================== - -/* -int P_FindMinSurroundingLight(sector_t *sector,int max) -{ - int i; - int min; - line_t *line; - sector_t *check; - - min = max; - for (i=0 ; i < sector->linecount ; i++) - { - line = sector->lines[i]; - check = getNextSector(line,sector); - if (!check) - continue; - if (check->lightlevel < min) - min = check->lightlevel; - } - return min; -} -*/ - -//========================================================================= -// -// EV_SectorSoundChange -// -//========================================================================= - -boolean EV_SectorSoundChange(byte * args) -{ - int secNum; - boolean rtn; - - if (!args[0]) - { - return false; - } - secNum = -1; - rtn = false; - while ((secNum = P_FindSectorFromTag(args[0], secNum)) >= 0) - { - sectors[secNum].seqType = args[1]; - rtn = true; - } - return rtn; -} - -//============================================================================ -// -// CheckedLockedDoor -// -//============================================================================ - -static boolean CheckedLockedDoor(mobj_t * mo, byte lock) -{ - char LockedBuffer[80]; - - if (!mo->player) - { - return false; - } - if (!lock) - { - return true; - } - if (!(mo->player->keys & (1 << (lock - 1)))) - { - M_snprintf(LockedBuffer, sizeof(LockedBuffer), - "YOU NEED THE %s\n", TextKeyMessages[lock - 1]); - P_SetMessage(mo->player, LockedBuffer, true); - S_StartSound(mo, SFX_DOOR_LOCKED); - return false; - } - return true; -} - - -//========================================================================== -// -// EV_LineSearchForPuzzleItem -// -//========================================================================== - -boolean EV_LineSearchForPuzzleItem(line_t * line, byte * args, mobj_t * mo) -{ - player_t *player; - int i; - int type; - artitype_t arti; - - if (!mo) - return false; - player = mo->player; - if (!player) - return false; - - // Search player's inventory for puzzle items - for (i = 0; i < player->artifactCount; i++) - { - arti = player->inventory[i].type; - type = arti - arti_firstpuzzitem; - if (type < 0) - continue; - if (type == line->arg1) - { - // A puzzle item was found for the line - if (P_UseArtifact(player, arti)) - { - // A puzzle item was found for the line - P_PlayerRemoveArtifact(player, i); - if (player == &players[consoleplayer]) - { - if (arti < arti_firstpuzzitem) - { - S_StartSound(NULL, SFX_ARTIFACT_USE); - } - else - { - S_StartSound(NULL, SFX_PUZZLE_SUCCESS); - } - ArtifactFlash = 4; - } - return true; - } - } - } - return false; -} - - - -/* -============================================================================== - - EVENTS - -Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers - -============================================================================== -*/ -//============================================================================ -// -// P_ExecuteLineSpecial -// -// Invoked when crossing a linedef. The args[] array should be at least -// 5 elements in length. -// -//============================================================================ - -boolean P_ExecuteLineSpecial(int special, byte * args, line_t * line, - int side, mobj_t * mo) -{ - boolean buttonSuccess; - - buttonSuccess = false; - switch (special) - { - case 1: // Poly Start Line - break; - case 2: // Poly Rotate Left - buttonSuccess = EV_RotatePoly(line, args, 1, false); - break; - case 3: // Poly Rotate Right - buttonSuccess = EV_RotatePoly(line, args, -1, false); - break; - case 4: // Poly Move - buttonSuccess = EV_MovePoly(line, args, false, false); - break; - case 5: // Poly Explicit Line: Only used in initialization - break; - case 6: // Poly Move Times 8 - buttonSuccess = EV_MovePoly(line, args, true, false); - break; - case 7: // Poly Door Swing - buttonSuccess = EV_OpenPolyDoor(line, args, PODOOR_SWING); - break; - case 8: // Poly Door Slide - buttonSuccess = EV_OpenPolyDoor(line, args, PODOOR_SLIDE); - break; - case 10: // Door Close - buttonSuccess = EV_DoDoor(line, args, DREV_CLOSE); - break; - case 11: // Door Open - if (!args[0]) - { - buttonSuccess = EV_VerticalDoor(line, mo); - } - else - { - buttonSuccess = EV_DoDoor(line, args, DREV_OPEN); - } - break; - case 12: // Door Raise - if (!args[0]) - { - buttonSuccess = EV_VerticalDoor(line, mo); - } - else - { - buttonSuccess = EV_DoDoor(line, args, DREV_NORMAL); - } - break; - case 13: // Door Locked_Raise - if (CheckedLockedDoor(mo, args[3])) - { - if (!args[0]) - { - buttonSuccess = EV_VerticalDoor(line, mo); - } - else - { - buttonSuccess = EV_DoDoor(line, args, DREV_NORMAL); - } - } - break; - case 20: // Floor Lower by Value - buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE); - break; - case 21: // Floor Lower to Lowest - buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERFLOORTOLOWEST); - break; - case 22: // Floor Lower to Nearest - buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERFLOOR); - break; - case 23: // Floor Raise by Value - buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE); - break; - case 24: // Floor Raise to Highest - buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOOR); - break; - case 25: // Floor Raise to Nearest - buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOORTONEAREST); - break; - case 26: // Stairs Build Down Normal - buttonSuccess = EV_BuildStairs(line, args, -1, STAIRS_NORMAL); - break; - case 27: // Build Stairs Up Normal - buttonSuccess = EV_BuildStairs(line, args, 1, STAIRS_NORMAL); - break; - case 28: // Floor Raise and Crush - buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEFLOORCRUSH); - break; - case 29: // Build Pillar (no crushing) - buttonSuccess = EV_BuildPillar(line, args, false); - break; - case 30: // Open Pillar - buttonSuccess = EV_OpenPillar(line, args); - break; - case 31: // Stairs Build Down Sync - buttonSuccess = EV_BuildStairs(line, args, -1, STAIRS_SYNC); - break; - case 32: // Build Stairs Up Sync - buttonSuccess = EV_BuildStairs(line, args, 1, STAIRS_SYNC); - break; - case 35: // Raise Floor by Value Times 8 - buttonSuccess = EV_DoFloor(line, args, FLEV_RAISEBYVALUETIMES8); - break; - case 36: // Lower Floor by Value Times 8 - buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERBYVALUETIMES8); - break; - case 40: // Ceiling Lower by Value - buttonSuccess = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE); - break; - case 41: // Ceiling Raise by Value - buttonSuccess = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE); - break; - case 42: // Ceiling Crush and Raise - buttonSuccess = EV_DoCeiling(line, args, CLEV_CRUSHANDRAISE); - break; - case 43: // Ceiling Lower and Crush - buttonSuccess = EV_DoCeiling(line, args, CLEV_LOWERANDCRUSH); - break; - case 44: // Ceiling Crush Stop - buttonSuccess = EV_CeilingCrushStop(line, args); - break; - case 45: // Ceiling Crush Raise and Stay - buttonSuccess = EV_DoCeiling(line, args, CLEV_CRUSHRAISEANDSTAY); - break; - case 46: // Floor Crush Stop - buttonSuccess = EV_FloorCrushStop(line, args); - break; - case 60: // Plat Perpetual Raise - buttonSuccess = EV_DoPlat(line, args, PLAT_PERPETUALRAISE, 0); - break; - case 61: // Plat Stop - EV_StopPlat(line, args); - break; - case 62: // Plat Down-Wait-Up-Stay - buttonSuccess = EV_DoPlat(line, args, PLAT_DOWNWAITUPSTAY, 0); - break; - case 63: // Plat Down-by-Value*8-Wait-Up-Stay - buttonSuccess = EV_DoPlat(line, args, PLAT_DOWNBYVALUEWAITUPSTAY, - 0); - break; - case 64: // Plat Up-Wait-Down-Stay - buttonSuccess = EV_DoPlat(line, args, PLAT_UPWAITDOWNSTAY, 0); - break; - case 65: // Plat Up-by-Value*8-Wait-Down-Stay - buttonSuccess = EV_DoPlat(line, args, PLAT_UPBYVALUEWAITDOWNSTAY, - 0); - break; - case 66: // Floor Lower Instant * 8 - buttonSuccess = EV_DoFloor(line, args, FLEV_LOWERTIMES8INSTANT); - break; - case 67: // Floor Raise Instant * 8 - buttonSuccess = EV_DoFloor(line, args, FLEV_RAISETIMES8INSTANT); - break; - case 68: // Floor Move to Value * 8 - buttonSuccess = EV_DoFloor(line, args, FLEV_MOVETOVALUETIMES8); - break; - case 69: // Ceiling Move to Value * 8 - buttonSuccess = EV_DoCeiling(line, args, CLEV_MOVETOVALUETIMES8); - break; - case 70: // Teleport - if (side == 0) - { // Only teleport when crossing the front side of a line - buttonSuccess = EV_Teleport(args[0], mo, true); - } - break; - case 71: // Teleport, no fog - if (side == 0) - { // Only teleport when crossing the front side of a line - buttonSuccess = EV_Teleport(args[0], mo, false); - } - break; - case 72: // Thrust Mobj - if (!side) // Only thrust on side 0 - { - P_ThrustMobj(mo, args[0] * (ANG90 / 64), - args[1] << FRACBITS); - buttonSuccess = 1; - } - break; - case 73: // Damage Mobj - if (args[0]) - { - P_DamageMobj(mo, NULL, NULL, args[0]); - } - else - { // If arg1 is zero, then guarantee a kill - P_DamageMobj(mo, NULL, NULL, 10000); - } - buttonSuccess = 1; - break; - case 74: // Teleport_NewMap - if (side == 0) - { // Only teleport when crossing the front side of a line - if (!(mo && mo->player && mo->player->playerstate == PST_DEAD)) // Players must be alive to teleport - { - G_Completed(args[0], args[1]); - buttonSuccess = true; - } - } - break; - case 75: // Teleport_EndGame - if (side == 0) - { // Only teleport when crossing the front side of a line - if (!(mo && mo->player && mo->player->playerstate == PST_DEAD)) // Players must be alive to teleport - { - buttonSuccess = true; - if (deathmatch) - { // Winning in deathmatch just goes back to map 1 - G_Completed(1, 0); - } - else - { // Passing -1, -1 to G_Completed() starts the Finale - G_Completed(-1, -1); - } - } - } - break; - case 80: // ACS_Execute - buttonSuccess = - P_StartACS(args[0], args[1], &args[2], mo, line, side); - break; - case 81: // ACS_Suspend - buttonSuccess = P_SuspendACS(args[0], args[1]); - break; - case 82: // ACS_Terminate - buttonSuccess = P_TerminateACS(args[0], args[1]); - break; - case 83: // ACS_LockedExecute - buttonSuccess = P_StartLockedACS(line, args, mo, side); - break; - case 90: // Poly Rotate Left Override - buttonSuccess = EV_RotatePoly(line, args, 1, true); - break; - case 91: // Poly Rotate Right Override - buttonSuccess = EV_RotatePoly(line, args, -1, true); - break; - case 92: // Poly Move Override - buttonSuccess = EV_MovePoly(line, args, false, true); - break; - case 93: // Poly Move Times 8 Override - buttonSuccess = EV_MovePoly(line, args, true, true); - break; - case 94: // Build Pillar Crush - buttonSuccess = EV_BuildPillar(line, args, true); - break; - case 95: // Lower Floor and Ceiling - buttonSuccess = EV_DoFloorAndCeiling(line, args, false); - break; - case 96: // Raise Floor and Ceiling - buttonSuccess = EV_DoFloorAndCeiling(line, args, true); - break; - case 109: // Force Lightning - buttonSuccess = true; - P_ForceLightning(); - break; - case 110: // Light Raise by Value - buttonSuccess = EV_SpawnLight(line, args, LITE_RAISEBYVALUE); - break; - case 111: // Light Lower by Value - buttonSuccess = EV_SpawnLight(line, args, LITE_LOWERBYVALUE); - break; - case 112: // Light Change to Value - buttonSuccess = EV_SpawnLight(line, args, LITE_CHANGETOVALUE); - break; - case 113: // Light Fade - buttonSuccess = EV_SpawnLight(line, args, LITE_FADE); - break; - case 114: // Light Glow - buttonSuccess = EV_SpawnLight(line, args, LITE_GLOW); - break; - case 115: // Light Flicker - buttonSuccess = EV_SpawnLight(line, args, LITE_FLICKER); - break; - case 116: // Light Strobe - buttonSuccess = EV_SpawnLight(line, args, LITE_STROBE); - break; - case 120: // Quake Tremor - buttonSuccess = A_LocalQuake(args, mo); - break; - case 129: // UsePuzzleItem - buttonSuccess = EV_LineSearchForPuzzleItem(line, args, mo); - break; - case 130: // Thing_Activate - buttonSuccess = EV_ThingActivate(args[0]); - break; - case 131: // Thing_Deactivate - buttonSuccess = EV_ThingDeactivate(args[0]); - break; - case 132: // Thing_Remove - buttonSuccess = EV_ThingRemove(args[0]); - break; - case 133: // Thing_Destroy - buttonSuccess = EV_ThingDestroy(args[0]); - break; - case 134: // Thing_Projectile - buttonSuccess = EV_ThingProjectile(args, 0); - break; - case 135: // Thing_Spawn - buttonSuccess = EV_ThingSpawn(args, 1); - break; - case 136: // Thing_ProjectileGravity - buttonSuccess = EV_ThingProjectile(args, 1); - break; - case 137: // Thing_SpawnNoFog - buttonSuccess = EV_ThingSpawn(args, 0); - break; - case 138: // Floor_Waggle - buttonSuccess = EV_StartFloorWaggle(args[0], args[1], - args[2], args[3], args[4]); - break; - case 140: // Sector_SoundChange - buttonSuccess = EV_SectorSoundChange(args); - break; - - // Line specials only processed during level initialization - // 100: Scroll_Texture_Left - // 101: Scroll_Texture_Right - // 102: Scroll_Texture_Up - // 103: Scroll_Texture_Down - // 121: Line_SetIdentification - - // Inert Line specials - default: - break; - } - return buttonSuccess; -} - -//============================================================================ -// -// P_ActivateLine -// -//============================================================================ - -boolean P_ActivateLine(line_t * line, mobj_t * mo, int side, - int activationType) -{ - byte args[5]; - int lineActivation; - boolean repeat; - boolean buttonSuccess; - - lineActivation = GET_SPAC(line->flags); - if (lineActivation != activationType) - { - return false; - } - if (!mo->player && !(mo->flags & MF_MISSILE)) - { - if (lineActivation != SPAC_MCROSS) - { // currently, monsters can only activate the MCROSS activation type - return false; - } - if (line->flags & ML_SECRET) - return false; // never open secret doors - } - repeat = (line->flags & ML_REPEAT_SPECIAL) != 0; - - // Construct args[] array to contain the arguments from the line, as we - // cannot rely on struct field ordering and layout. - args[0] = line->arg1; - args[1] = line->arg2; - args[2] = line->arg3; - args[3] = line->arg4; - args[4] = line->arg5; - buttonSuccess = P_ExecuteLineSpecial(line->special, args, line, side, mo); - if (!repeat && buttonSuccess) - { // clear the special on non-retriggerable lines - line->special = 0; - } - if ((lineActivation == SPAC_USE || lineActivation == SPAC_IMPACT) - && buttonSuccess) - { - P_ChangeSwitchTexture(line, repeat); - } - return true; -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerInSpecialSector -// -// Called every tic frame that the player origin is in a special sector. -// -//---------------------------------------------------------------------------- - -void P_PlayerInSpecialSector(player_t * player) -{ - sector_t *sector; - static int pushTab[3] = { - 2048 * 5, - 2048 * 10, - 2048 * 25 - }; - - sector = player->mo->subsector->sector; - if (player->mo->z != sector->floorheight) - { // Player is not touching the floor - return; - } - switch (sector->special) - { - case 9: // SecretArea - player->secretcount++; - sector->special = 0; - break; - - case 201: - case 202: - case 203: // Scroll_North_xxx - P_Thrust(player, ANG90, pushTab[sector->special - 201]); - break; - case 204: - case 205: - case 206: // Scroll_East_xxx - P_Thrust(player, 0, pushTab[sector->special - 204]); - break; - case 207: - case 208: - case 209: // Scroll_South_xxx - P_Thrust(player, ANG270, pushTab[sector->special - 207]); - break; - case 210: - case 211: - case 212: // Scroll_West_xxx - P_Thrust(player, ANG180, pushTab[sector->special - 210]); - break; - case 213: - case 214: - case 215: // Scroll_NorthWest_xxx - P_Thrust(player, ANG90 + ANG45, pushTab[sector->special - 213]); - break; - case 216: - case 217: - case 218: // Scroll_NorthEast_xxx - P_Thrust(player, ANG45, pushTab[sector->special - 216]); - break; - case 219: - case 220: - case 221: // Scroll_SouthEast_xxx - P_Thrust(player, ANG270 + ANG45, pushTab[sector->special - 219]); - break; - case 222: - case 223: - case 224: // Scroll_SouthWest_xxx - P_Thrust(player, ANG180 + ANG45, pushTab[sector->special - 222]); - break; - - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - case 48: - case 49: - case 50: - case 51: - // Wind specials are handled in (P_mobj):P_XYMovement - break; - - case 26: // Stairs_Special1 - case 27: // Stairs_Special2 - // Used in (P_floor):ProcessStairSector - break; - - case 198: // Lightning Special - case 199: // Lightning Flash special - case 200: // Sky2 - // Used in (R_plane):R_Drawplanes - break; - default: - I_Error("P_PlayerInSpecialSector: " - "unknown special %i", sector->special); - } -} - -//============================================================================ -// -// P_PlayerOnSpecialFlat -// -//============================================================================ - -void P_PlayerOnSpecialFlat(player_t * player, int floorType) -{ - if (player->mo->z != player->mo->floorz) - { // Player is not touching the floor - return; - } - switch (floorType) - { - case FLOOR_LAVA: - if (!(leveltime & 31)) - { - P_DamageMobj(player->mo, &LavaInflictor, NULL, 10); - S_StartSound(player->mo, SFX_LAVA_SIZZLE); - } - break; - default: - break; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_UpdateSpecials -// -//---------------------------------------------------------------------------- - -void P_UpdateSpecials(void) -{ - int i; - - // Handle buttons - for (i = 0; i < MAXBUTTONS; i++) - { - if (buttonlist[i].btimer) - { - buttonlist[i].btimer--; - if (!buttonlist[i].btimer) - { - switch (buttonlist[i].where) - { - case SWTCH_TOP: - sides[buttonlist[i].line->sidenum[0]].toptexture = - buttonlist[i].btexture; - break; - case SWTCH_MIDDLE: - sides[buttonlist[i].line->sidenum[0]].midtexture = - buttonlist[i].btexture; - break; - case SWTCH_BOTTOM: - sides[buttonlist[i].line->sidenum[0]].bottomtexture = - buttonlist[i].btexture; - break; - } - //S_StartSound((mobj_t *)&buttonlist[i].soundorg, sfx_switch); - memset(&buttonlist[i], 0, sizeof(button_t)); - } - } - } -} - -/* -============================================================================== - - SPECIAL SPAWNING - -============================================================================== -*/ -/* -================================================================================ -= P_SpawnSpecials -= -= After the map has been loaded, scan for specials that -= spawn thinkers -= -=============================================================================== -*/ - -short numlinespecials; -line_t *linespeciallist[MAXLINEANIMS]; - -void P_SpawnSpecials(void) -{ - sector_t *sector; - int i; - - // - // Init special SECTORs - // - sector = sectors; - for (i = 0; i < numsectors; i++, sector++) - { - if (!sector->special) - continue; - switch (sector->special) - { - case 1: // Phased light - // Hardcoded base, use sector->lightlevel as the index - P_SpawnPhasedLight(sector, 80, -1); - break; - case 2: // Phased light sequence start - P_SpawnLightSequence(sector, 1); - break; - // Specials 3 & 4 are used by the phased light sequences - - /* - case 1: // FLICKERING LIGHTS - P_SpawnLightFlash (sector); - break; - case 2: // STROBE FAST - P_SpawnStrobeFlash(sector,FASTDARK,0); - break; - case 3: // STROBE SLOW - P_SpawnStrobeFlash(sector,SLOWDARK,0); - break; - case 4: // STROBE FAST/DEATH SLIME - P_SpawnStrobeFlash(sector,FASTDARK,0); - sector->special = 4; - break; - case 8: // GLOWING LIGHT - P_SpawnGlowingLight(sector); - break; - case 9: // SECRET SECTOR - totalsecret++; - break; - case 10: // DOOR CLOSE IN 30 SECONDS - P_SpawnDoorCloseIn30 (sector); - break; - case 12: // SYNC STROBE SLOW - P_SpawnStrobeFlash (sector, SLOWDARK, 1); - break; - case 13: // SYNC STROBE FAST - P_SpawnStrobeFlash (sector, FASTDARK, 1); - break; - case 14: // DOOR RAISE IN 5 MINUTES - P_SpawnDoorRaiseIn5Mins (sector, i); - break; - */ - } - } - - - // - // Init line EFFECTs - // - numlinespecials = 0; - TaggedLineCount = 0; - for (i = 0; i < numlines; i++) - { - switch (lines[i].special) - { - case 100: // Scroll_Texture_Left - case 101: // Scroll_Texture_Right - case 102: // Scroll_Texture_Up - case 103: // Scroll_Texture_Down - linespeciallist[numlinespecials] = &lines[i]; - numlinespecials++; - break; - case 121: // Line_SetIdentification - if (lines[i].arg1) - { - if (TaggedLineCount == MAX_TAGGED_LINES) - { - I_Error("P_SpawnSpecials: MAX_TAGGED_LINES " - "(%d) exceeded.", MAX_TAGGED_LINES); - } - TaggedLines[TaggedLineCount].line = &lines[i]; - TaggedLines[TaggedLineCount++].lineTag = lines[i].arg1; - } - lines[i].special = 0; - break; - } - } - - // - // Init other misc stuff - // - for (i = 0; i < MAXCEILINGS; i++) - activeceilings[i] = NULL; - for (i = 0; i < MAXPLATS; i++) - activeplats[i] = NULL; - for (i = 0; i < MAXBUTTONS; i++) - memset(&buttonlist[i], 0, sizeof(button_t)); - - // Initialize flat and texture animations - P_InitFTAnims(); -} - -//========================================================================== -// -// P_FindLine -// -//========================================================================== - -line_t *P_FindLine(int lineTag, int *searchPosition) -{ - int i; - - for (i = *searchPosition + 1; i < TaggedLineCount; i++) - { - if (TaggedLines[i].lineTag == lineTag) - { - *searchPosition = i; - return TaggedLines[i].line; - } - } - *searchPosition = -1; - return NULL; -} diff --git a/games/NXDoom/src/hexen/p_spec.h b/games/NXDoom/src/hexen/p_spec.h deleted file mode 100644 index 3814484baa1..00000000000 --- a/games/NXDoom/src/hexen/p_spec.h +++ /dev/null @@ -1,586 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef P_SPEC_H -#define P_SPEC_H - - -extern int *TerrainTypes; - -// -// scrolling line specials -// - -#define MAXLINEANIMS 64 -extern short numlinespecials; -extern line_t *linespeciallist[MAXLINEANIMS]; - -extern mobj_t LavaInflictor; - - -// Define values for map objects -#define MO_TELEPORTMAN 14 - -// at game start -void P_InitTerrainTypes(void); -void P_InitLava(void); - -// at map load -void P_SpawnSpecials(void); - -// every tic -void P_UpdateSpecials(void); - -// when needed -boolean P_ExecuteLineSpecial(int special, byte * args, line_t * line, - int side, mobj_t * mo); -boolean P_ActivateLine(line_t * ld, mobj_t * mo, int side, - int activationType); -//boolean P_UseSpecialLine ( mobj_t *thing, line_t *line); -//void P_ShootSpecialLine ( mobj_t *thing, line_t *line); -//void P_CrossSpecialLine (int linenum, int side, mobj_t *thing); - -void P_PlayerInSpecialSector(player_t * player); -void P_PlayerOnSpecialFlat(player_t * player, int floorType); - -//int twoSided(int sector,int line); -//sector_t *getSector(int currentSector,int line,int side); -//side_t *getSide(int currentSector,int line, int side); -fixed_t P_FindLowestFloorSurrounding(sector_t * sec); -fixed_t P_FindHighestFloorSurrounding(sector_t * sec); -fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight); -fixed_t P_FindLowestCeilingSurrounding(sector_t * sec); -fixed_t P_FindHighestCeilingSurrounding(sector_t * sec); -//int P_FindSectorFromLineTag(line_t *line,int start); -int P_FindSectorFromTag(int tag, int start); -//int P_FindMinSurroundingLight(sector_t *sector,int max); -sector_t *getNextSector(line_t * line, sector_t * sec); -line_t *P_FindLine(int lineTag, int *searchPosition); - -// -// SPECIAL -// -//int EV_DoDonut(line_t *line); - -//------------------------------- -// P_anim.c -//------------------------------- - - -extern fixed_t Sky1ScrollDelta; -extern fixed_t Sky2ScrollDelta; - - -void P_AnimateSurfaces(void); -void P_InitFTAnims(void); -void P_InitLightning(void); -void P_ForceLightning(void); - -/* -=============================================================================== - - P_LIGHTS - -=============================================================================== -*/ - -typedef enum -{ - LITE_RAISEBYVALUE, - LITE_LOWERBYVALUE, - LITE_CHANGETOVALUE, - LITE_FADE, - LITE_GLOW, - LITE_FLICKER, - LITE_STROBE -} lighttype_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - lighttype_t type; - int value1; - int value2; - int tics1; - int tics2; - int count; -} light_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int index; - int base; -} phase_t; - -#define LIGHT_SEQUENCE_START 2 -#define LIGHT_SEQUENCE 3 -#define LIGHT_SEQUENCE_ALT 4 - -void T_Phase(thinker_t *thinker); -void T_Light(thinker_t *thinker); -void P_SpawnPhasedLight(sector_t * sector, int base, int index); -void P_SpawnLightSequence(sector_t * sector, int indexStep); -boolean EV_SpawnLight(line_t * line, byte * arg, lighttype_t type); - -#if 0 -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int count; - int maxlight; - int minlight; - int maxtime; - int mintime; -} lightflash_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int count; - int minlight; - int maxlight; - int darktime; - int brighttime; -} strobe_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int minlight; - int maxlight; - int direction; -} glow_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int index; - int base; -} phase_t; - -#define GLOWSPEED 8 -#define STROBEBRIGHT 5 -#define FASTDARK 15 -#define SLOWDARK 35 - -#define LIGHT_SEQUENCE_START 2 -#define LIGHT_SEQUENCE 3 -#define LIGHT_SEQUENCE_ALT 4 - -void T_LightFlash(lightflash_t * flash); -void P_SpawnLightFlash(sector_t * sector); -void T_StrobeFlash(strobe_t * flash); -void P_SpawnStrobeFlash(sector_t * sector, int fastOrSlow, int inSync); -void EV_StartLightStrobing(line_t * line); -void EV_TurnTagLightsOff(line_t * line); -void EV_LightTurnOn(line_t * line, int bright); -void T_Glow(glow_t * g); -void P_SpawnGlowingLight(sector_t * sector); -void T_Phase(phase_t * phase); -void P_SpawnPhasedLight(sector_t * sector, int base, int index); -void P_SpawnLightSequence(sector_t * sector, int indexStep); -#endif - -/* -=============================================================================== - - P_SWITCH - -=============================================================================== -*/ -typedef struct -{ - char name1[9]; - char name2[9]; - int soundID; -} switchlist_t; - -typedef enum -{ - SWTCH_TOP, - SWTCH_MIDDLE, - SWTCH_BOTTOM -} bwhere_e; - -typedef struct -{ - line_t *line; - bwhere_e where; - int btexture; - int btimer; - mobj_t *soundorg; -} button_t; - -#define MAXSWITCHES 50 // max # of wall switches in a level -#define MAXBUTTONS 16 // 4 players, 4 buttons each at once, max. -#define BUTTONTIME 35 // 1 second - -extern button_t buttonlist[MAXBUTTONS]; - -void P_ChangeSwitchTexture(line_t * line, int useAgain); -void P_InitSwitchList(void); - -/* -=============================================================================== - - P_PLATS - -=============================================================================== -*/ - -typedef enum -{ - PLAT_UP, - PLAT_DOWN, - PLAT_WAITING, -// PLAT_IN_STASIS -} plat_e; - -typedef enum -{ - PLAT_PERPETUALRAISE, - PLAT_DOWNWAITUPSTAY, - PLAT_DOWNBYVALUEWAITUPSTAY, - PLAT_UPWAITDOWNSTAY, - PLAT_UPBYVALUEWAITDOWNSTAY, - //PLAT_RAISEANDCHANGE, - //PLAT_RAISETONEARESTANDCHANGE -} plattype_e; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - fixed_t speed; - fixed_t low; - fixed_t high; - int wait; - int count; - plat_e status; - plat_e oldstatus; - int crush; - int tag; - plattype_e type; -} plat_t; - -#define PLATWAIT 3 -#define PLATSPEED FRACUNIT -#define MAXPLATS 30 - -extern plat_t *activeplats[MAXPLATS]; - -void T_PlatRaise(thinker_t *thinker); -int EV_DoPlat(line_t * line, byte * args, plattype_e type, int amount); -void P_AddActivePlat(plat_t * plat); -void P_RemoveActivePlat(plat_t * plat); -void EV_StopPlat(line_t * line, byte * args); - -/* -=============================================================================== - - P_DOORS - -=============================================================================== -*/ -typedef enum -{ - DREV_NORMAL, - DREV_CLOSE30THENOPEN, - DREV_CLOSE, - DREV_OPEN, - DREV_RAISEIN5MINS, -} vldoor_e; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - vldoor_e type; - fixed_t topheight; - fixed_t speed; - int direction; // 1 = up, 0 = waiting at top, -1 = down - int topwait; // tics to wait at the top (keep in case a door going down is reset) - int topcountdown; // when it reaches 0, start going down -} vldoor_t; - -#define VDOORSPEED FRACUNIT*2 -#define VDOORWAIT 150 - -boolean EV_VerticalDoor(line_t * line, mobj_t * thing); -int EV_DoDoor(line_t * line, byte * args, vldoor_e type); -void T_VerticalDoor(thinker_t *thinker); -//void P_SpawnDoorCloseIn30(sector_t *sec); -//void P_SpawnDoorRaiseIn5Mins(sector_t *sec, int secnum); - -/* -=============================================================================== - - P_CEILNG - -=============================================================================== -*/ -typedef enum -{ - CLEV_LOWERTOFLOOR, - CLEV_RAISETOHIGHEST, - CLEV_LOWERANDCRUSH, - CLEV_CRUSHANDRAISE, - CLEV_LOWERBYVALUE, - CLEV_RAISEBYVALUE, - CLEV_CRUSHRAISEANDSTAY, - CLEV_MOVETOVALUETIMES8 -} ceiling_e; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - ceiling_e type; - fixed_t bottomheight, topheight; - fixed_t speed; - int crush; - int direction; // 1 = up, 0 = waiting, -1 = down - int tag; // ID - int olddirection; -} ceiling_t; - -#define CEILSPEED FRACUNIT -#define CEILWAIT 150 -#define MAXCEILINGS 30 - -extern ceiling_t *activeceilings[MAXCEILINGS]; - -int EV_DoCeiling(line_t * line, byte * args, ceiling_e type); -void T_MoveCeiling(thinker_t *thinker); -void P_AddActiveCeiling(ceiling_t * c); -void P_RemoveActiveCeiling(ceiling_t * c); -int EV_CeilingCrushStop(line_t * line, byte * args); - -/* -=============================================================================== - - P_FLOOR - -=============================================================================== -*/ -typedef enum -{ - FLEV_LOWERFLOOR, // lower floor to highest surrounding floor - FLEV_LOWERFLOORTOLOWEST, // lower floor to lowest surrounding floor - FLEV_LOWERFLOORBYVALUE, - FLEV_RAISEFLOOR, // raise floor to lowest surrounding CEILING - FLEV_RAISEFLOORTONEAREST, // raise floor to next highest surrounding floor - FLEV_RAISEFLOORBYVALUE, - FLEV_RAISEFLOORCRUSH, - FLEV_RAISEBUILDSTEP, // One step of a staircase - FLEV_RAISEBYVALUETIMES8, - FLEV_LOWERBYVALUETIMES8, - FLEV_LOWERTIMES8INSTANT, - FLEV_RAISETIMES8INSTANT, - FLEV_MOVETOVALUETIMES8 -} floor_e; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - floor_e type; - int crush; - int direction; - int newspecial; - short texture; - fixed_t floordestheight; - fixed_t speed; - int delayCount; - int delayTotal; - fixed_t stairsDelayHeight; - fixed_t stairsDelayHeightDelta; - fixed_t resetHeight; - short resetDelay; - short resetDelayCount; - byte textureChange; -} floormove_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - int ceilingSpeed; - int floorSpeed; - int floordest; - int ceilingdest; - int direction; - int crush; -} pillar_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; - fixed_t originalHeight; - fixed_t accumulator; - fixed_t accDelta; - fixed_t targetScale; - fixed_t scale; - fixed_t scaleDelta; - int ticker; - int state; -} floorWaggle_t; - -#define FLOORSPEED FRACUNIT - -typedef enum -{ - RES_OK, - RES_CRUSHED, - RES_PASTDEST -} result_e; - -typedef enum -{ - STAIRS_NORMAL, - STAIRS_SYNC, - STAIRS_PHASED -} stairs_e; - -result_e T_MovePlane(sector_t * sector, fixed_t speed, - fixed_t dest, int crush, int floorOrCeiling, - int direction); - -int EV_BuildStairs(line_t * line, byte * args, int direction, stairs_e type); -int EV_DoFloor(line_t * line, byte * args, floor_e floortype); -void T_MoveFloor(thinker_t *thinker); -void T_BuildPillar(thinker_t *thinker); -void T_FloorWaggle(thinker_t *thinker); -int EV_BuildPillar(line_t * line, byte * args, boolean crush); -int EV_OpenPillar(line_t * line, byte * args); -int EV_DoFloorAndCeiling(line_t * line, byte * args, boolean raise); -int EV_FloorCrushStop(line_t * line, byte * args); -boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset, - int timer); - -//-------------------------------------------------------------------------- -// -// p_telept -// -//-------------------------------------------------------------------------- - -boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle, - boolean useFog); -boolean EV_Teleport(int tid, mobj_t * thing, boolean fog); - -//-------------------------------------------------------------------------- -// -// p_acs -// -//-------------------------------------------------------------------------- - -#define MAX_ACS_SCRIPT_VARS 10 -#define MAX_ACS_MAP_VARS 32 -#define MAX_ACS_WORLD_VARS 64 -#define ACS_STACK_DEPTH 32 -#define MAX_ACS_STORE 20 - -typedef enum -{ - ASTE_INACTIVE, - ASTE_RUNNING, - ASTE_SUSPENDED, - ASTE_WAITINGFORTAG, - ASTE_WAITINGFORPOLY, - ASTE_WAITINGFORSCRIPT, - ASTE_TERMINATING -} aste_t; - -typedef struct acs_s acs_t; -typedef struct acsInfo_s acsInfo_t; - -struct acsInfo_s -{ - int number; - int offset; - int argCount; - aste_t state; - int waitValue; -}; - -struct acs_s -{ - thinker_t thinker; - mobj_t *activator; - line_t *line; - int side; - int number; - int infoIndex; - int delayCount; - int stack[ACS_STACK_DEPTH]; - int stackPtr; - int vars[MAX_ACS_SCRIPT_VARS]; - int ip; -}; - -typedef struct -{ - int map; // Target map - int script; // Script number on target map - byte args[4]; // Padded to 4 for alignment -} acsstore_t; - -void P_LoadACScripts(int lump); -boolean P_StartACS(int number, int map, byte * args, mobj_t * activator, - line_t * line, int side); -boolean P_StartLockedACS(line_t * line, byte * args, mobj_t * mo, int side); -boolean P_TerminateACS(int number, int map); -boolean P_SuspendACS(int number, int map); -void T_InterpretACS(thinker_t *thinker); -void P_TagFinished(int tag); -void P_PolyobjFinished(int po); -void P_ACSInitNewGame(void); -void P_CheckACSStore(void); -void CheckACSPresent(int number); - -extern int ACScriptCount; -extern byte *ActionCodeBase; -extern acsInfo_t *ACSInfo; -extern int MapVars[MAX_ACS_MAP_VARS]; -extern int WorldVars[MAX_ACS_WORLD_VARS]; -extern acsstore_t ACSStore[MAX_ACS_STORE + 1]; // +1 for termination marker - -//-------------------------------------------------------------------------- -// -// p_things -// -//-------------------------------------------------------------------------- - -extern mobjtype_t TranslateThingType[]; - -boolean EV_ThingProjectile(byte * args, boolean gravity); -boolean EV_ThingSpawn(byte * args, boolean fog); -boolean EV_ThingActivate(int tid); -boolean EV_ThingDeactivate(int tid); -boolean EV_ThingRemove(int tid); -boolean EV_ThingDestroy(int tid); - - -#endif // P_SPEC_H diff --git a/games/NXDoom/src/hexen/p_switch.c b/games/NXDoom/src/hexen/p_switch.c deleted file mode 100644 index a90269a799f..00000000000 --- a/games/NXDoom/src/hexen/p_switch.c +++ /dev/null @@ -1,172 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" - -//================================================================== -// -// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE -// -//================================================================== -switchlist_t alphSwitchListDemo[] = { - {"SW_1_UP", "SW_1_DN", SFX_SWITCH1}, - {"SW_2_UP", "SW_2_DN", SFX_SWITCH1}, - {"SW52_OFF", "SW52_ON", SFX_SWITCH2}, - {"\0", "\0", 0} -}; - -switchlist_t alphSwitchListFull[] = { - {"SW_1_UP", "SW_1_DN", SFX_SWITCH1}, - {"SW_2_UP", "SW_2_DN", SFX_SWITCH1}, - {"VALVE1", "VALVE2", SFX_VALVE_TURN}, - {"SW51_OFF", "SW51_ON", SFX_SWITCH2}, - {"SW52_OFF", "SW52_ON", SFX_SWITCH2}, - {"SW53_UP", "SW53_DN", SFX_ROPE_PULL}, - {"PUZZLE5", "PUZZLE9", SFX_SWITCH1}, - {"PUZZLE6", "PUZZLE10", SFX_SWITCH1}, - {"PUZZLE7", "PUZZLE11", SFX_SWITCH1}, - {"PUZZLE8", "PUZZLE12", SFX_SWITCH1}, - {"\0", "\0", 0} -}; - -switchlist_t *alphSwitchList = NULL; - -int switchlist[MAXSWITCHES * 2]; -int numswitches; -button_t buttonlist[MAXBUTTONS]; - -/* -=============== -= -= P_InitSwitchList -= -= Only called at game initialization -= -=============== -*/ - -void P_InitSwitchList(void) -{ - int i; - int index; - - if (!alphSwitchList) - { - if (gamemode == shareware) - { - alphSwitchList = alphSwitchListDemo; - } - else - { - alphSwitchList = alphSwitchListFull; - } - } - - for (index = 0, i = 0; i < MAXSWITCHES; i++) - { - if (!alphSwitchList[i].soundID) - { - numswitches = index / 2; - switchlist[index] = -1; - break; - } - switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1); - switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2); - } -} - -//================================================================== -// -// Start a button counting down till it turns off. -// -//================================================================== -void P_StartButton(line_t * line, bwhere_e w, int texture, int time) -{ - int i; - - for (i = 0; i < MAXBUTTONS; i++) - { - if (!buttonlist[i].btimer) - { - buttonlist[i].line = line; - buttonlist[i].where = w; - buttonlist[i].btexture = texture; - buttonlist[i].btimer = time; - buttonlist[i].soundorg = (mobj_t *) & line->frontsector->soundorg; - return; - } - } - I_Error("P_StartButton: no button slots left!"); -} - -//================================================================== -// -// Function that changes wall texture. -// Tell it if switch is ok to use again (1=yes, it's a button). -// -//================================================================== -void P_ChangeSwitchTexture(line_t * line, int useAgain) -{ - int texTop; - int texMid; - int texBot; - int i; - - texTop = sides[line->sidenum[0]].toptexture; - texMid = sides[line->sidenum[0]].midtexture; - texBot = sides[line->sidenum[0]].bottomtexture; - - for (i = 0; i < numswitches * 2; i++) - { - if (switchlist[i] == texTop) - { - S_StartSound((mobj_t *) & line->frontsector->soundorg, - alphSwitchList[i / 2].soundID); - sides[line->sidenum[0]].toptexture = switchlist[i ^ 1]; - if (useAgain) - { - P_StartButton(line, SWTCH_TOP, switchlist[i], BUTTONTIME); - } - return; - } - else if (switchlist[i] == texMid) - { - S_StartSound((mobj_t *) & line->frontsector->soundorg, - alphSwitchList[i / 2].soundID); - sides[line->sidenum[0]].midtexture = switchlist[i ^ 1]; - if (useAgain) - { - P_StartButton(line, SWTCH_MIDDLE, switchlist[i], BUTTONTIME); - } - return; - } - else if (switchlist[i] == texBot) - { - S_StartSound((mobj_t *) & line->frontsector->soundorg, - alphSwitchList[i / 2].soundID); - sides[line->sidenum[0]].bottomtexture = switchlist[i ^ 1]; - if (useAgain) - { - P_StartButton(line, SWTCH_BOTTOM, switchlist[i], BUTTONTIME); - } - return; - } - } -} diff --git a/games/NXDoom/src/hexen/p_telept.c b/games/NXDoom/src/hexen/p_telept.c deleted file mode 100644 index ba5416b27d0..00000000000 --- a/games/NXDoom/src/hexen/p_telept.c +++ /dev/null @@ -1,190 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// P_Teleport -// -//========================================================================== - -boolean P_Teleport(mobj_t * thing, fixed_t x, fixed_t y, angle_t angle, - boolean useFog) -{ - fixed_t oldx; - fixed_t oldy; - fixed_t oldz; - fixed_t aboveFloor; - fixed_t fogDelta; - player_t *player; - unsigned an; - mobj_t *fog; - - oldx = thing->x; - oldy = thing->y; - oldz = thing->z; - aboveFloor = thing->z - thing->floorz; - if (!P_TeleportMove(thing, x, y)) - { - return false; - } - if (thing->player) - { - player = thing->player; - if (player->powers[pw_flight] && aboveFloor) - { - thing->z = thing->floorz + aboveFloor; - if (thing->z + thing->height > thing->ceilingz) - { - thing->z = thing->ceilingz - thing->height; - } - player->viewz = thing->z + player->viewheight; - } - else - { - thing->z = thing->floorz; - player->viewz = thing->z + player->viewheight; - if (useFog) - { - player->lookdir = 0; - } - } - } - else if (thing->flags & MF_MISSILE) - { - thing->z = thing->floorz + aboveFloor; - if (thing->z + thing->height > thing->ceilingz) - { - thing->z = thing->ceilingz - thing->height; - } - } - else - { - thing->z = thing->floorz; - } - // Spawn teleport fog at source and destination - if (useFog) - { - fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; - fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG); - S_StartSound(fog, SFX_TELEPORT); - an = angle >> ANGLETOFINESHIFT; - fog = P_SpawnMobj(x + 20 * finecosine[an], - y + 20 * finesine[an], thing->z + fogDelta, - MT_TFOG); - S_StartSound(fog, SFX_TELEPORT); - if (thing->player && !thing->player->powers[pw_speed]) - { // Freeze player for about .5 sec - thing->reactiontime = 18; - } - thing->angle = angle; - } - if (thing->flags2 & MF2_FLOORCLIP) - { - if (thing->z == thing->subsector->sector->floorheight - && P_GetThingFloorType(thing) > FLOOR_SOLID) - { - thing->floorclip = 10 * FRACUNIT; - } - else - { - thing->floorclip = 0; - } - } - if (thing->flags & MF_MISSILE) - { - angle >>= ANGLETOFINESHIFT; - thing->momx = FixedMul(thing->info->speed, finecosine[angle]); - thing->momy = FixedMul(thing->info->speed, finesine[angle]); - } - else if (useFog) // no fog doesn't alter the player's momentums - { - thing->momx = thing->momy = thing->momz = 0; - } - return true; -} - -//========================================================================== -// -// EV_Teleport -// -//========================================================================== - -boolean EV_Teleport(int tid, mobj_t * thing, boolean fog) -{ - int i; - int count; - mobj_t *mo; - int searcher; - - if (!thing) - { // Teleport function called with an invalid mobj - return false; - } - if (thing->flags2 & MF2_NOTELEPORT) - { - return false; - } - count = 0; - searcher = -1; - while (P_FindMobjFromTID(tid, &searcher) != NULL) - { - count++; - } - if (count == 0) - { - return false; - } - count = 1 + (P_Random() % count); - searcher = -1; - mo = NULL; - - for (i = 0; i < count; i++) - { - mo = P_FindMobjFromTID(tid, &searcher); - } - if (mo == NULL) - { - I_Error("Can't find teleport mapspot\n"); - } - return P_Teleport(thing, mo->x, mo->y, mo->angle, fog); -} diff --git a/games/NXDoom/src/hexen/p_things.c b/games/NXDoom/src/hexen/p_things.c deleted file mode 100644 index 12ec8547e00..00000000000 --- a/games/NXDoom/src/hexen/p_things.c +++ /dev/null @@ -1,537 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "p_local.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static boolean ActivateThing(mobj_t * mobj); -static boolean DeactivateThing(mobj_t * mobj); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -mobjtype_t TranslateThingType[] = { - MT_MAPSPOT, // T_NONE - MT_CENTAUR, // T_CENTAUR - MT_CENTAURLEADER, // T_CENTAURLEADER - MT_DEMON, // T_DEMON - MT_ETTIN, // T_ETTIN - MT_FIREDEMON, // T_FIREGARGOYLE - MT_SERPENT, // T_WATERLURKER - MT_SERPENTLEADER, // T_WATERLURKERLEADER - MT_WRAITH, // T_WRAITH - MT_WRAITHB, // T_WRAITHBURIED - MT_FIREBALL1, // T_FIREBALL1 - MT_MANA1, // T_MANA1 - MT_MANA2, // T_MANA2 - MT_SPEEDBOOTS, // T_ITEMBOOTS - MT_ARTIEGG, // T_ITEMEGG - MT_ARTIFLY, // T_ITEMFLIGHT - MT_SUMMONMAULATOR, // T_ITEMSUMMON - MT_TELEPORTOTHER, // T_ITEMTPORTOTHER - MT_ARTITELEPORT, // T_ITEMTELEPORT - MT_BISHOP, // T_BISHOP - MT_ICEGUY, // T_ICEGOLEM - MT_BRIDGE, // T_BRIDGE - MT_BOOSTARMOR, // T_DRAGONSKINBRACERS - MT_HEALINGBOTTLE, // T_ITEMHEALTHPOTION - MT_HEALTHFLASK, // T_ITEMHEALTHFLASK - MT_ARTISUPERHEAL, // T_ITEMHEALTHFULL - MT_BOOSTMANA, // T_ITEMBOOSTMANA - MT_FW_AXE, // T_FIGHTERAXE - MT_FW_HAMMER, // T_FIGHTERHAMMER - MT_FW_SWORD1, // T_FIGHTERSWORD1 - MT_FW_SWORD2, // T_FIGHTERSWORD2 - MT_FW_SWORD3, // T_FIGHTERSWORD3 - MT_CW_SERPSTAFF, // T_CLERICSTAFF - MT_CW_HOLY1, // T_CLERICHOLY1 - MT_CW_HOLY2, // T_CLERICHOLY2 - MT_CW_HOLY3, // T_CLERICHOLY3 - MT_MW_CONE, // T_MAGESHARDS - MT_MW_STAFF1, // T_MAGESTAFF1 - MT_MW_STAFF2, // T_MAGESTAFF2 - MT_MW_STAFF3, // T_MAGESTAFF3 - MT_EGGFX, // T_MORPHBLAST - MT_ROCK1, // T_ROCK1 - MT_ROCK2, // T_ROCK2 - MT_ROCK3, // T_ROCK3 - MT_DIRT1, // T_DIRT1 - MT_DIRT2, // T_DIRT2 - MT_DIRT3, // T_DIRT3 - MT_DIRT4, // T_DIRT4 - MT_DIRT5, // T_DIRT5 - MT_DIRT6, // T_DIRT6 - MT_ARROW, // T_ARROW - MT_DART, // T_DART - MT_POISONDART, // T_POISONDART - MT_RIPPERBALL, // T_RIPPERBALL - MT_SGSHARD1, // T_STAINEDGLASS1 - MT_SGSHARD2, // T_STAINEDGLASS2 - MT_SGSHARD3, // T_STAINEDGLASS3 - MT_SGSHARD4, // T_STAINEDGLASS4 - MT_SGSHARD5, // T_STAINEDGLASS5 - MT_SGSHARD6, // T_STAINEDGLASS6 - MT_SGSHARD7, // T_STAINEDGLASS7 - MT_SGSHARD8, // T_STAINEDGLASS8 - MT_SGSHARD9, // T_STAINEDGLASS9 - MT_SGSHARD0, // T_STAINEDGLASS0 - MT_PROJECTILE_BLADE, // T_BLADE - MT_ICESHARD, // T_ICESHARD - MT_FLAME_SMALL, // T_FLAME_SMALL - MT_FLAME_LARGE, // T_FLAME_LARGE - MT_ARMOR_1, // T_MESHARMOR - MT_ARMOR_2, // T_FALCONSHIELD - MT_ARMOR_3, // T_PLATINUMHELM - MT_ARMOR_4, // T_AMULETOFWARDING - MT_ARTIPOISONBAG, // T_ITEMFLECHETTE - MT_ARTITORCH, // T_ITEMTORCH - MT_BLASTRADIUS, // T_ITEMREPULSION - MT_MANA3, // T_MANA3 - MT_ARTIPUZZSKULL, // T_PUZZSKULL - MT_ARTIPUZZGEMBIG, // T_PUZZGEMBIG - MT_ARTIPUZZGEMRED, // T_PUZZGEMRED - MT_ARTIPUZZGEMGREEN1, // T_PUZZGEMGREEN1 - MT_ARTIPUZZGEMGREEN2, // T_PUZZGEMGREEN2 - MT_ARTIPUZZGEMBLUE1, // T_PUZZGEMBLUE1 - MT_ARTIPUZZGEMBLUE2, // T_PUZZGEMBLUE2 - MT_ARTIPUZZBOOK1, // T_PUZZBOOK1 - MT_ARTIPUZZBOOK2, // T_PUZZBOOK2 - MT_KEY1, // T_METALKEY - MT_KEY2, // T_SMALLMETALKEY - MT_KEY3, // T_AXEKEY - MT_KEY4, // T_FIREKEY - MT_KEY5, // T_GREENKEY - MT_KEY6, // T_MACEKEY - MT_KEY7, // T_SILVERKEY - MT_KEY8, // T_RUSTYKEY - MT_KEY9, // T_HORNKEY - MT_KEYA, // T_SERPENTKEY - MT_WATER_DRIP, // T_WATERDRIP - MT_FLAME_SMALL_TEMP, // T_TEMPSMALLFLAME - MT_FLAME_SMALL, // T_PERMSMALLFLAME - MT_FLAME_LARGE_TEMP, // T_TEMPLARGEFLAME - MT_FLAME_LARGE, // T_PERMLARGEFLAME - MT_DEMON_MASH, // T_DEMON_MASH - MT_DEMON2_MASH, // T_DEMON2_MASH - MT_ETTIN_MASH, // T_ETTIN_MASH - MT_CENTAUR_MASH, // T_CENTAUR_MASH - MT_THRUSTFLOOR_UP, // T_THRUSTSPIKEUP - MT_THRUSTFLOOR_DOWN, // T_THRUSTSPIKEDOWN - MT_WRAITHFX4, // T_FLESH_DRIP1 - MT_WRAITHFX5, // T_FLESH_DRIP2 - MT_WRAITHFX2 // T_SPARK_DRIP -}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// EV_ThingProjectile -// -//========================================================================== - -boolean EV_ThingProjectile(byte * args, boolean gravity) -{ - int tid; - angle_t angle; - int fineAngle; - fixed_t speed; - fixed_t vspeed; - mobjtype_t moType; - mobj_t *mobj; - mobj_t *newMobj; - int searcher; - boolean success; - - success = false; - searcher = -1; - tid = args[0]; - moType = TranslateThingType[args[1]]; - if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL)) - { // Don't spawn monsters if -nomonsters - return false; - } - angle = (int) args[2] << 24; - fineAngle = angle >> ANGLETOFINESHIFT; - speed = (int) args[3] << 13; - vspeed = (int) args[4] << 13; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - newMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, moType); - if (newMobj->info->seesound) - { - S_StartSound(newMobj, newMobj->info->seesound); - } - newMobj->target = mobj; // Originator - newMobj->angle = angle; - newMobj->momx = FixedMul(speed, finecosine[fineAngle]); - newMobj->momy = FixedMul(speed, finesine[fineAngle]); - newMobj->momz = vspeed; - newMobj->flags2 |= MF2_DROPPED; // Don't respawn - if (gravity == true) - { - newMobj->flags &= ~MF_NOGRAVITY; - newMobj->flags2 |= MF2_LOGRAV; - } - if (P_CheckMissileSpawn(newMobj) == true) - { - success = true; - } - } - return success; -} - -//========================================================================== -// -// EV_ThingSpawn -// -//========================================================================== - -boolean EV_ThingSpawn(byte * args, boolean fog) -{ - int tid; - angle_t angle; - mobj_t *mobj; - mobj_t *newMobj; - mobj_t *fogMobj; - mobjtype_t moType; - int searcher; - boolean success; - fixed_t z; - - success = false; - searcher = -1; - tid = args[0]; - moType = TranslateThingType[args[1]]; - if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL)) - { // Don't spawn monsters if -nomonsters - return false; - } - angle = (int) args[2] << 24; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - if (mobjinfo[moType].flags2 & MF2_FLOATBOB) - { - z = mobj->z - mobj->floorz; - } - else - { - z = mobj->z; - } - newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType); - if (P_TestMobjLocation(newMobj) == false) - { // Didn't fit - P_RemoveMobj(newMobj); - } - else - { - newMobj->angle = angle; - if (fog == true) - { - fogMobj = P_SpawnMobj(mobj->x, mobj->y, - mobj->z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fogMobj, SFX_TELEPORT); - } - newMobj->flags2 |= MF2_DROPPED; // Don't respawn - if (newMobj->flags2 & MF2_FLOATBOB) - { - newMobj->special1.i = newMobj->z - newMobj->floorz; - } - success = true; - } - } - return success; -} - -//========================================================================== -// -// EV_ThingActivate -// -//========================================================================== - -boolean EV_ThingActivate(int tid) -{ - mobj_t *mobj; - int searcher; - boolean success; - - success = false; - searcher = -1; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - if (ActivateThing(mobj) == true) - { - success = true; - } - } - return success; -} - -//========================================================================== -// -// EV_ThingDeactivate -// -//========================================================================== - -boolean EV_ThingDeactivate(int tid) -{ - mobj_t *mobj; - int searcher; - boolean success; - - success = false; - searcher = -1; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - if (DeactivateThing(mobj) == true) - { - success = true; - } - } - return success; -} - -//========================================================================== -// -// EV_ThingRemove -// -//========================================================================== - -boolean EV_ThingRemove(int tid) -{ - mobj_t *mobj; - int searcher; - boolean success; - - success = false; - searcher = -1; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - if (mobj->type == MT_BRIDGE) - { - A_BridgeRemove(mobj); - return true; - } - P_RemoveMobj(mobj); - success = true; - } - return success; -} - -//========================================================================== -// -// EV_ThingDestroy -// -//========================================================================== - -boolean EV_ThingDestroy(int tid) -{ - mobj_t *mobj; - int searcher; - boolean success; - - success = false; - searcher = -1; - while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) - { - if (mobj->flags & MF_SHOOTABLE) - { - P_DamageMobj(mobj, NULL, NULL, 10000); - success = true; - } - } - return success; -} - -//========================================================================== -// -// EV_ThingMove -// -// arg[0] = tid -// arg[1] = speed -// arg[2] = angle (255 = use mobj angle) -// arg[3] = distance (pixels>>2) -// -//========================================================================== - -/* -boolean EV_ThingMove(byte *args) -{ - return false; -} -*/ - -//========================================================================== -// -// ActivateThing -// -//========================================================================== - -static boolean ActivateThing(mobj_t * mobj) -{ - if (mobj->flags & MF_COUNTKILL) - { // Monster - if (mobj->flags2 & MF2_DORMANT) - { - mobj->flags2 &= ~MF2_DORMANT; - mobj->tics = 1; - return true; - } - return false; - } - switch (mobj->type) - { - case MT_ZTWINEDTORCH: - case MT_ZTWINEDTORCH_UNLIT: - P_SetMobjState(mobj, S_ZTWINEDTORCH_1); - S_StartSound(mobj, SFX_IGNITE); - break; - case MT_ZWALLTORCH: - case MT_ZWALLTORCH_UNLIT: - P_SetMobjState(mobj, S_ZWALLTORCH1); - S_StartSound(mobj, SFX_IGNITE); - break; - case MT_ZGEMPEDESTAL: - P_SetMobjState(mobj, S_ZGEMPEDESTAL2); - break; - case MT_ZWINGEDSTATUENOSKULL: - P_SetMobjState(mobj, S_ZWINGEDSTATUENOSKULL2); - break; - case MT_THRUSTFLOOR_UP: - case MT_THRUSTFLOOR_DOWN: - if (mobj->args[0] == 0) - { - S_StartSound(mobj, SFX_THRUSTSPIKE_LOWER); - mobj->flags2 &= ~MF2_DONTDRAW; - if (mobj->args[1]) - P_SetMobjState(mobj, S_BTHRUSTRAISE1); - else - P_SetMobjState(mobj, S_THRUSTRAISE1); - } - break; - case MT_ZFIREBULL: - case MT_ZFIREBULL_UNLIT: - P_SetMobjState(mobj, S_ZFIREBULL_BIRTH); - S_StartSound(mobj, SFX_IGNITE); - break; - case MT_ZBELL: - if (mobj->health > 0) - { - P_DamageMobj(mobj, NULL, NULL, 10); // 'ring' the bell - } - break; - case MT_ZCAULDRON: - case MT_ZCAULDRON_UNLIT: - P_SetMobjState(mobj, S_ZCAULDRON1); - S_StartSound(mobj, SFX_IGNITE); - break; - case MT_FLAME_SMALL: - S_StartSound(mobj, SFX_IGNITE); - P_SetMobjState(mobj, S_FLAME_SMALL1); - break; - case MT_FLAME_LARGE: - S_StartSound(mobj, SFX_IGNITE); - P_SetMobjState(mobj, S_FLAME_LARGE1); - break; - case MT_BAT_SPAWNER: - P_SetMobjState(mobj, S_SPAWNBATS1); - break; - default: - return false; - break; - } - return true; -} - -//========================================================================== -// -// DeactivateThing -// -//========================================================================== - -static boolean DeactivateThing(mobj_t * mobj) -{ - if (mobj->flags & MF_COUNTKILL) - { // Monster - if (!(mobj->flags2 & MF2_DORMANT)) - { - mobj->flags2 |= MF2_DORMANT; - mobj->tics = -1; - return true; - } - return false; - } - switch (mobj->type) - { - case MT_ZTWINEDTORCH: - case MT_ZTWINEDTORCH_UNLIT: - P_SetMobjState(mobj, S_ZTWINEDTORCH_UNLIT); - break; - case MT_ZWALLTORCH: - case MT_ZWALLTORCH_UNLIT: - P_SetMobjState(mobj, S_ZWALLTORCH_U); - break; - case MT_THRUSTFLOOR_UP: - case MT_THRUSTFLOOR_DOWN: - if (mobj->args[0] == 1) - { - S_StartSound(mobj, SFX_THRUSTSPIKE_RAISE); - if (mobj->args[1]) - P_SetMobjState(mobj, S_BTHRUSTLOWER); - else - P_SetMobjState(mobj, S_THRUSTLOWER); - } - break; - case MT_ZFIREBULL: - case MT_ZFIREBULL_UNLIT: - P_SetMobjState(mobj, S_ZFIREBULL_DEATH); - break; - case MT_ZCAULDRON: - case MT_ZCAULDRON_UNLIT: - P_SetMobjState(mobj, S_ZCAULDRON_U); - break; - case MT_FLAME_SMALL: - P_SetMobjState(mobj, S_FLAME_SDORM1); - break; - case MT_FLAME_LARGE: - P_SetMobjState(mobj, S_FLAME_LDORM1); - break; - case MT_BAT_SPAWNER: - P_SetMobjState(mobj, S_SPAWNBATS_OFF); - break; - default: - return false; - break; - } - return true; -} diff --git a/games/NXDoom/src/hexen/p_tick.c b/games/NXDoom/src/hexen/p_tick.c deleted file mode 100644 index 3d3dd389c77..00000000000 --- a/games/NXDoom/src/hexen/p_tick.c +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "p_local.h" - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void RunThinkers(void); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -int leveltime; -int TimerGame; -thinker_t thinkercap; // The head and tail of the thinker list - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// P_Ticker -// -//========================================================================== - -void P_Ticker(void) -{ - int i; - - if (paused) - { - return; - } - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - P_PlayerThink(&players[i]); - } - } - if (TimerGame) - { - if (!--TimerGame) - { - G_Completed(P_TranslateMap(P_GetMapNextMap(gamemap)), 0); - } - } - RunThinkers(); - P_UpdateSpecials(); - P_AnimateSurfaces(); - leveltime++; -} - -//========================================================================== -// -// RunThinkers -// -//========================================================================== - -static void RunThinkers(void) -{ - thinker_t *currentthinker, *nextthinker; - - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) - { - if (currentthinker->function == (think_t) - 1) - { // Time to remove it - nextthinker = currentthinker->next; - currentthinker->next->prev = currentthinker->prev; - currentthinker->prev->next = currentthinker->next; - Z_Free(currentthinker); - } - else - { - if (currentthinker->function) - currentthinker->function(currentthinker); - nextthinker = currentthinker->next; - } - - currentthinker = nextthinker; - } -} - -//========================================================================== -// -// P_InitThinkers -// -//========================================================================== - -void P_InitThinkers(void) -{ - thinkercap.prev = thinkercap.next = &thinkercap; -} - -//========================================================================== -// -// P_AddThinker -// -// Adds a new thinker at the end of the list. -// -//========================================================================== - -void P_AddThinker(thinker_t * thinker) -{ - thinkercap.prev->next = thinker; - thinker->next = &thinkercap; - thinker->prev = thinkercap.prev; - thinkercap.prev = thinker; -} - -//========================================================================== -// -// P_RemoveThinker -// -// Deallocation is lazy -- it will not actually be freed until its -// thinking turn comes up. -// -//========================================================================== - -void P_RemoveThinker(thinker_t * thinker) -{ - thinker->function = (think_t) - 1; -} diff --git a/games/NXDoom/src/hexen/p_user.c b/games/NXDoom/src/hexen/p_user.c deleted file mode 100644 index 52986bd2306..00000000000 --- a/games/NXDoom/src/hexen/p_user.c +++ /dev/null @@ -1,1643 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "m_random.h" -#include "i_system.h" -#include "p_local.h" -#include "s_sound.h" - - -// Macros - -#define MAXBOB 0x100000 // 16 pixels of bob - -// Data - -boolean onground; -int newtorch; // used in the torch flicker effect. -int newtorchdelta; - -int PStateNormal[NUMCLASSES] = { - S_FPLAY, - S_CPLAY, - S_MPLAY, - S_PIGPLAY -}; - -int PStateRun[NUMCLASSES] = { - S_FPLAY_RUN1, - S_CPLAY_RUN1, - S_MPLAY_RUN1, - S_PIGPLAY_RUN1 -}; - -int PStateAttack[NUMCLASSES] = { - S_FPLAY_ATK1, - S_CPLAY_ATK1, - S_MPLAY_ATK1, - S_PIGPLAY_ATK1 -}; - -int PStateAttackEnd[NUMCLASSES] = { - S_FPLAY_ATK2, - S_CPLAY_ATK3, - S_MPLAY_ATK2, - S_PIGPLAY_ATK1 -}; - -int ArmorMax[NUMCLASSES] = { 20, 18, 16, 1 }; - -/* -================== -= -= P_Thrust -= -= moves the given origin along a given angle -= -================== -*/ - -void P_Thrust(player_t * player, angle_t angle, fixed_t move) -{ - angle >>= ANGLETOFINESHIFT; - if (player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz)) - { - player->mo->momx += FixedMul(move, finecosine[angle]); - player->mo->momy += FixedMul(move, finesine[angle]); - } - else if (P_GetThingFloorType(player->mo) == FLOOR_ICE) // Friction_Low - { - player->mo->momx += FixedMul(move >> 1, finecosine[angle]); - player->mo->momy += FixedMul(move >> 1, finesine[angle]); - } - else - { - player->mo->momx += FixedMul(move, finecosine[angle]); - player->mo->momy += FixedMul(move, finesine[angle]); - } -} - - -/* -================== -= -= P_CalcHeight -= -=Calculate the walking / running height adjustment -= -================== -*/ - -void P_CalcHeight(player_t * player) -{ - int angle; - fixed_t bob; - -// -// regular movement bobbing (needs to be calculated for gun swing even -// if not on ground) -// OPTIMIZE: tablify angle - - player->bob = FixedMul(player->mo->momx, player->mo->momx) + - FixedMul(player->mo->momy, player->mo->momy); - player->bob >>= 2; - if (player->bob > MAXBOB) - player->bob = MAXBOB; - if (player->mo->flags2 & MF2_FLY && !onground) - { - player->bob = FRACUNIT / 2; - } - - if ((player->cheats & CF_NOMOMENTUM)) - { - player->viewz = player->mo->z + VIEWHEIGHT; - if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) - player->viewz = player->mo->ceilingz - 4 * FRACUNIT; - player->viewz = player->mo->z + player->viewheight; - return; - } - - angle = (FINEANGLES / 20 * leveltime) & FINEMASK; - bob = FixedMul(player->bob / 2, finesine[angle]); - -// -// move viewheight -// - if (player->playerstate == PST_LIVE) - { - player->viewheight += player->deltaviewheight; - if (player->viewheight > VIEWHEIGHT) - { - player->viewheight = VIEWHEIGHT; - player->deltaviewheight = 0; - } - if (player->viewheight < VIEWHEIGHT / 2) - { - player->viewheight = VIEWHEIGHT / 2; - if (player->deltaviewheight <= 0) - player->deltaviewheight = 1; - } - - if (player->deltaviewheight) - { - player->deltaviewheight += FRACUNIT / 4; - if (!player->deltaviewheight) - player->deltaviewheight = 1; - } - } - - if (player->morphTics) - { - player->viewz = player->mo->z + player->viewheight - (20 * FRACUNIT); - } - else - { - player->viewz = player->mo->z + player->viewheight + bob; - } - if (player->mo->floorclip && player->playerstate != PST_DEAD - && player->mo->z <= player->mo->floorz) - { - player->viewz -= player->mo->floorclip; - } - if (player->viewz > player->mo->ceilingz - 4 * FRACUNIT) - { - player->viewz = player->mo->ceilingz - 4 * FRACUNIT; - } - if (player->viewz < player->mo->floorz + 4 * FRACUNIT) - { - player->viewz = player->mo->floorz + 4 * FRACUNIT; - } -} - -/* -================= -= -= P_MovePlayer -= -================= -*/ - -void P_MovePlayer(player_t * player) -{ - int look; - int fly; - ticcmd_t *cmd; - - cmd = &player->cmd; - player->mo->angle += (cmd->angleturn << 16); - - onground = (player->mo->z <= player->mo->floorz - || (player->mo->flags2 & MF2_ONMOBJ)); - - if (cmd->forwardmove) - { - if (onground || player->mo->flags2 & MF2_FLY) - { - P_Thrust(player, player->mo->angle, cmd->forwardmove * 2048); - } - else - { - P_Thrust(player, player->mo->angle, FRACUNIT >> 8); - } - } - if (cmd->sidemove) - { - if (onground || player->mo->flags2 & MF2_FLY) - { - P_Thrust(player, player->mo->angle - ANG90, cmd->sidemove * 2048); - } - else - { - P_Thrust(player, player->mo->angle, FRACUNIT >> 8); - } - } - if (cmd->forwardmove || cmd->sidemove) - { - if (player->mo->state == &states[PStateNormal[player->class]]) - { - P_SetMobjState(player->mo, PStateRun[player->class]); - } - } - - look = cmd->lookfly & 15; - if (look > 7) - { - look -= 16; - } - if (look) - { - if (look == TOCENTER) - { - player->centering = true; - } - else - { - player->lookdir += 5 * look; - if (player->lookdir > 90 || player->lookdir < -110) - { - player->lookdir -= 5 * look; - } - } - } - if (player->centering) - { - if (player->lookdir > 0) - { - player->lookdir -= 8; - } - else if (player->lookdir < 0) - { - player->lookdir += 8; - } - if (abs(player->lookdir) < 8) - { - player->lookdir = 0; - player->centering = false; - } - } - fly = cmd->lookfly >> 4; - if (fly > 7) - { - fly -= 16; - } - if (fly && player->powers[pw_flight]) - { - if (fly != TOCENTER) - { - player->flyheight = fly * 2; - if (!(player->mo->flags2 & MF2_FLY)) - { - player->mo->flags2 |= MF2_FLY; - player->mo->flags |= MF_NOGRAVITY; - if (player->mo->momz <= -39 * FRACUNIT) - { // stop falling scream - S_StopSound(player->mo); - } - } - } - else - { - player->mo->flags2 &= ~MF2_FLY; - player->mo->flags &= ~MF_NOGRAVITY; - } - } - else if (fly > 0) - { - P_PlayerUseArtifact(player, arti_fly); - } - if (player->mo->flags2 & MF2_FLY) - { - player->mo->momz = player->flyheight * FRACUNIT; - if (player->flyheight) - { - player->flyheight /= 2; - } - } -} - -//========================================================================== -// -// P_DeathThink -// -//========================================================================== - -void P_DeathThink(player_t * player) -{ - int dir; - angle_t delta; - int lookDelta; - - P_MovePsprites(player); - - onground = (player->mo->z <= player->mo->floorz); - if (player->mo->type == MT_BLOODYSKULL || player->mo->type == MT_ICECHUNK) - { // Flying bloody skull or flying ice chunk - player->viewheight = 6 * FRACUNIT; - player->deltaviewheight = 0; - //player->damagecount = 20; - if (onground) - { - if (player->lookdir < 60) - { - lookDelta = (60 - player->lookdir) / 8; - if (lookDelta < 1 && (leveltime & 1)) - { - lookDelta = 1; - } - else if (lookDelta > 6) - { - lookDelta = 6; - } - player->lookdir += lookDelta; - } - } - } - else if (!(player->mo->flags2 & MF2_ICEDAMAGE)) - { // Fall to ground (if not frozen) - player->deltaviewheight = 0; - if (player->viewheight > 6 * FRACUNIT) - { - player->viewheight -= FRACUNIT; - } - if (player->viewheight < 6 * FRACUNIT) - { - player->viewheight = 6 * FRACUNIT; - } - if (player->lookdir > 0) - { - player->lookdir -= 6; - } - else if (player->lookdir < 0) - { - player->lookdir += 6; - } - if (abs(player->lookdir) < 6) - { - player->lookdir = 0; - } - } - P_CalcHeight(player); - - if (player->attacker && player->attacker != player->mo) - { // Watch killer - dir = P_FaceMobj(player->mo, player->attacker, &delta); - if (delta < ANG1 * 10) - { // Looking at killer, so fade damage and poison counters - if (player->damagecount) - { - player->damagecount--; - } - if (player->poisoncount) - { - player->poisoncount--; - } - } - delta = delta / 8; - if (delta > ANG1 * 5) - { - delta = ANG1 * 5; - } - if (dir) - { // Turn clockwise - player->mo->angle += delta; - } - else - { // Turn counter clockwise - player->mo->angle -= delta; - } - } - else if (player->damagecount || player->poisoncount) - { - if (player->damagecount) - { - player->damagecount--; - } - else - { - player->poisoncount--; - } - } - - if (player->cmd.buttons & BT_USE) - { - if (player == &players[consoleplayer]) - { - I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE)); - inv_ptr = 0; - curpos = 0; - newtorch = 0; - newtorchdelta = 0; - } - player->playerstate = PST_REBORN; - player->mo->special1.i = player->class; - if (player->mo->special1.i > 2) - { - player->mo->special1.i = 0; - } - // Let the mobj know the player has entered the reborn state. Some - // mobjs need to know when it's ok to remove themselves. - player->mo->special2.i = 666; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_MorphPlayerThink -// -//---------------------------------------------------------------------------- - -void P_MorphPlayerThink(player_t * player) -{ - mobj_t *pmo; - - if (player->morphTics & 15) - { - return; - } - pmo = player->mo; - if (!(pmo->momx + pmo->momy) && P_Random() < 64) - { // Snout sniff - P_SetPspriteNF(player, ps_weapon, S_SNOUTATK2); - S_StartSound(pmo, SFX_PIG_ACTIVE1); // snort - return; - } - if (P_Random() < 48) - { - if (P_Random() < 128) - { - S_StartSound(pmo, SFX_PIG_ACTIVE1); - } - else - { - S_StartSound(pmo, SFX_PIG_ACTIVE2); - } - } -} - -//---------------------------------------------------------------------------- -// -// FUNC P_GetPlayerNum -// -//---------------------------------------------------------------------------- - -int P_GetPlayerNum(player_t * player) -{ - int i; - - for (i = 0; i < maxplayers; i++) - { - if (player == &players[i]) - { - return (i); - } - } - return (0); -} - -//---------------------------------------------------------------------------- -// -// FUNC P_UndoPlayerMorph -// -//---------------------------------------------------------------------------- - -boolean P_UndoPlayerMorph(player_t * player) -{ - mobj_t *fog; - mobj_t *mo; - mobj_t *pmo; - fixed_t x; - fixed_t y; - fixed_t z; - angle_t angle; - int playerNum; - weapontype_t weapon; - int oldFlags; - int oldFlags2; - int oldBeast; - - pmo = player->mo; - x = pmo->x; - y = pmo->y; - z = pmo->z; - angle = pmo->angle; - weapon = pmo->special1.i; - oldFlags = pmo->flags; - oldFlags2 = pmo->flags2; - oldBeast = pmo->type; - P_SetMobjState(pmo, S_FREETARGMOBJ); - playerNum = P_GetPlayerNum(player); - switch (PlayerClass[playerNum]) - { - case PCLASS_FIGHTER: - mo = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER); - break; - case PCLASS_CLERIC: - mo = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC); - break; - case PCLASS_MAGE: - mo = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE); - break; - default: - I_Error("P_UndoPlayerMorph: Unknown player class %d\n", - player->class); - return false; - } - if (P_TestMobjLocation(mo) == false) - { // Didn't fit - P_RemoveMobj(mo); - mo = P_SpawnMobj(x, y, z, oldBeast); - mo->angle = angle; - mo->health = player->health; - mo->special1.i = weapon; - mo->player = player; - mo->flags = oldFlags; - mo->flags2 = oldFlags2; - player->mo = mo; - player->morphTics = 2 * 35; - return (false); - } - if (player->class == PCLASS_FIGHTER) - { - // The first type should be blue, and the third should be the - // Fighter's original gold color - if (playerNum == 0) - { - mo->flags |= 2 << MF_TRANSSHIFT; - } - else if (playerNum != 2) - { - mo->flags |= playerNum << MF_TRANSSHIFT; - } - } - else if (playerNum) - { // Set color translation bits for player sprites - mo->flags |= playerNum << MF_TRANSSHIFT; - } - mo->angle = angle; - mo->player = player; - mo->reactiontime = 18; - if (oldFlags2 & MF2_FLY) - { - mo->flags2 |= MF2_FLY; - mo->flags |= MF_NOGRAVITY; - } - player->morphTics = 0; - player->health = mo->health = MAXHEALTH; - player->mo = mo; - player->class = PlayerClass[playerNum]; - angle >>= ANGLETOFINESHIFT; - fog = P_SpawnMobj(x + 20 * finecosine[angle], - y + 20 * finesine[angle], z + TELEFOGHEIGHT, MT_TFOG); - S_StartSound(fog, SFX_TELEPORT); - P_PostMorphWeapon(player, weapon); - return (true); -} - - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerThink -// -//---------------------------------------------------------------------------- - -void P_PlayerThink(player_t * player) -{ - ticcmd_t *cmd; - weapontype_t newweapon; - int floorType; - mobj_t *pmo; - - // No-clip cheat - if (player->cheats & CF_NOCLIP) - { - player->mo->flags |= MF_NOCLIP; - } - else - { - player->mo->flags &= ~MF_NOCLIP; - } - cmd = &player->cmd; - if (player->mo->flags & MF_JUSTATTACKED) - { // Gauntlets attack auto forward motion - cmd->angleturn = 0; - cmd->forwardmove = 0xc800 / 512; - cmd->sidemove = 0; - player->mo->flags &= ~MF_JUSTATTACKED; - } -// messageTics is above the rest of the counters so that messages will -// go away, even in death. - player->messageTics--; // Can go negative - if (!player->messageTics || player->messageTics == -1) - { // Refresh the screen when a message goes away - player->ultimateMessage = false; // clear out any chat messages. - player->yellowMessage = false; - if (player == &players[consoleplayer]) - { - BorderTopRefresh = true; - } - } - player->worldTimer++; - if (player->playerstate == PST_DEAD) - { - P_DeathThink(player); - return; - } - if (player->jumpTics) - { - player->jumpTics--; - } - if (player->morphTics) - { - P_MorphPlayerThink(player); - } - // Handle movement - if (player->mo->reactiontime) - { // Player is frozen - player->mo->reactiontime--; - } - else - { - P_MovePlayer(player); - pmo = player->mo; - if (player->powers[pw_speed] && !(leveltime & 1) - && P_AproxDistance(pmo->momx, pmo->momy) > 12 * FRACUNIT) - { - mobj_t *speedMo; - int playerNum; - - speedMo = P_SpawnMobj(pmo->x, pmo->y, pmo->z, MT_PLAYER_SPEED); - if (speedMo) - { - speedMo->angle = pmo->angle; - playerNum = P_GetPlayerNum(player); - if (player->class == PCLASS_FIGHTER) - { - // The first type should be blue, and the - // third should be the Fighter's original gold color - if (playerNum == 0) - { - speedMo->flags |= 2 << MF_TRANSSHIFT; - } - else if (playerNum != 2) - { - speedMo->flags |= playerNum << MF_TRANSSHIFT; - } - } - else if (playerNum) - { // Set color translation bits for player sprites - speedMo->flags |= playerNum << MF_TRANSSHIFT; - } - speedMo->target = pmo; - speedMo->special1.i = player->class; - if (speedMo->special1.i > 2) - { - speedMo->special1.i = 0; - } - speedMo->sprite = pmo->sprite; - speedMo->floorclip = pmo->floorclip; - if (player == &players[consoleplayer]) - { - speedMo->flags2 |= MF2_DONTDRAW; - } - } - } - } - P_CalcHeight(player); - if (player->mo->subsector->sector->special) - { - P_PlayerInSpecialSector(player); - } - if ((floorType = P_GetThingFloorType(player->mo)) != FLOOR_SOLID) - { - P_PlayerOnSpecialFlat(player, floorType); - } - switch (player->class) - { - case PCLASS_FIGHTER: - if (player->mo->momz <= -35 * FRACUNIT - && player->mo->momz >= -40 * FRACUNIT && !player->morphTics - && !S_GetSoundPlayingInfo(player->mo, - SFX_PLAYER_FIGHTER_FALLING_SCREAM)) - { - S_StartSound(player->mo, SFX_PLAYER_FIGHTER_FALLING_SCREAM); - } - break; - case PCLASS_CLERIC: - if (player->mo->momz <= -35 * FRACUNIT - && player->mo->momz >= -40 * FRACUNIT && !player->morphTics - && !S_GetSoundPlayingInfo(player->mo, - SFX_PLAYER_CLERIC_FALLING_SCREAM)) - { - S_StartSound(player->mo, SFX_PLAYER_CLERIC_FALLING_SCREAM); - } - break; - case PCLASS_MAGE: - if (player->mo->momz <= -35 * FRACUNIT - && player->mo->momz >= -40 * FRACUNIT && !player->morphTics - && !S_GetSoundPlayingInfo(player->mo, - SFX_PLAYER_MAGE_FALLING_SCREAM)) - { - S_StartSound(player->mo, SFX_PLAYER_MAGE_FALLING_SCREAM); - } - break; - default: - break; - } - if (cmd->arti) - { // Use an artifact - if ((cmd->arti & AFLAG_JUMP) && onground && !player->jumpTics) - { - if (player->morphTics) - { - player->mo->momz = 6 * FRACUNIT; - } - else - { - player->mo->momz = 9 * FRACUNIT; - } - player->mo->flags2 &= ~MF2_ONMOBJ; - player->jumpTics = 18; - } - else if (cmd->arti & AFLAG_SUICIDE) - { - P_DamageMobj(player->mo, NULL, NULL, 10000); - } - if (cmd->arti == NUMARTIFACTS) - { // use one of each artifact (except puzzle artifacts) - int i; - - for (i = 1; i < arti_firstpuzzitem; i++) - { - P_PlayerUseArtifact(player, i); - } - } - else - { - P_PlayerUseArtifact(player, cmd->arti & AFLAG_MASK); - } - } - // Check for weapon change - if (cmd->buttons & BT_SPECIAL) - { // A special event has no other buttons - cmd->buttons = 0; - } - if (cmd->buttons & BT_CHANGE && !player->morphTics) - { - // The actual changing of the weapon is done when the weapon - // psprite can do it (A_WeaponReady), so it doesn't happen in - // the middle of an attack. - newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; - if (player->weaponowned[newweapon] - && newweapon != player->readyweapon) - { - player->pendingweapon = newweapon; - } - } - // Check for use - if (cmd->buttons & BT_USE) - { - if (!player->usedown) - { - P_UseLines(player); - player->usedown = true; - } - } - else - { - player->usedown = false; - } - // Morph counter - if (player->morphTics) - { - if (!--player->morphTics) - { // Attempt to undo the pig - P_UndoPlayerMorph(player); - } - } - // Cycle psprites - P_MovePsprites(player); - // Other Counters - if (player->powers[pw_invulnerability]) - { - if (player->class == PCLASS_CLERIC) - { - if (!(leveltime & 7) && player->mo->flags & MF_SHADOW - && !(player->mo->flags2 & MF2_DONTDRAW)) - { - player->mo->flags &= ~MF_SHADOW; - if (!(player->mo->flags & MF_ALTSHADOW)) - { - player->mo->flags2 |= MF2_DONTDRAW | MF2_NONSHOOTABLE; - } - } - if (!(leveltime & 31)) - { - if (player->mo->flags2 & MF2_DONTDRAW) - { - if (!(player->mo->flags & MF_SHADOW)) - { - player->mo->flags |= MF_SHADOW | MF_ALTSHADOW; - } - else - { - player->mo->flags2 &= - ~(MF2_DONTDRAW | MF2_NONSHOOTABLE); - } - } - else - { - player->mo->flags |= MF_SHADOW; - player->mo->flags &= ~MF_ALTSHADOW; - } - } - } - if (!(--player->powers[pw_invulnerability])) - { - player->mo->flags2 &= ~(MF2_INVULNERABLE | MF2_REFLECTIVE); - if (player->class == PCLASS_CLERIC) - { - player->mo->flags2 &= ~(MF2_DONTDRAW | MF2_NONSHOOTABLE); - player->mo->flags &= ~(MF_SHADOW | MF_ALTSHADOW); - } - } - } - if (player->powers[pw_minotaur]) - { - player->powers[pw_minotaur]--; - } - if (player->powers[pw_infrared]) - { - player->powers[pw_infrared]--; - } - if (player->powers[pw_flight] && netgame) - { - if (!--player->powers[pw_flight]) - { - if (player->mo->z != player->mo->floorz) - { - // haleyjd: removed externdriver crap - player->centering = true; - } - player->mo->flags2 &= ~MF2_FLY; - player->mo->flags &= ~MF_NOGRAVITY; - BorderTopRefresh = true; //make sure the sprite's cleared out - } - } - if (player->powers[pw_speed]) - { - player->powers[pw_speed]--; - } - if (player->damagecount) - { - player->damagecount--; - } - if (player->bonuscount) - { - player->bonuscount--; - } - if (player->poisoncount && !(leveltime & 15)) - { - player->poisoncount -= 5; - if (player->poisoncount < 0) - { - player->poisoncount = 0; - } - P_PoisonDamage(player, player->poisoner, 1, true); - } - // Colormaps -// if(player->powers[pw_invulnerability]) -// { -// if(player->powers[pw_invulnerability] > BLINKTHRESHOLD -// || (player->powers[pw_invulnerability]&8)) -// { -// player->fixedcolormap = INVERSECOLORMAP; -// } -// else -// { -// player->fixedcolormap = 0; -// } -// } -// else - if (player->powers[pw_infrared]) - { - if (player->powers[pw_infrared] <= BLINKTHRESHOLD) - { - if (player->powers[pw_infrared] & 8) - { - player->fixedcolormap = 0; - } - else - { - player->fixedcolormap = 1; - } - } - else if (!(leveltime & 16) && player == &players[consoleplayer]) - { - if (newtorch) - { - if (player->fixedcolormap + newtorchdelta > 7 - || player->fixedcolormap + newtorchdelta < 1 - || newtorch == player->fixedcolormap) - { - newtorch = 0; - } - else - { - player->fixedcolormap += newtorchdelta; - } - } - else - { - newtorch = (M_Random() & 7) + 1; - newtorchdelta = (newtorch == player->fixedcolormap) ? - 0 : ((newtorch > player->fixedcolormap) ? 1 : -1); - } - } - } - else - { - player->fixedcolormap = 0; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_ArtiTele -// -//---------------------------------------------------------------------------- - -void P_ArtiTele(player_t * player) -{ - int i; - int selections; - fixed_t destX; - fixed_t destY; - angle_t destAngle; - - if (deathmatch) - { - selections = deathmatch_p - deathmatchstarts; - i = P_Random() % selections; - destX = deathmatchstarts[i].x << FRACBITS; - destY = deathmatchstarts[i].y << FRACBITS; - destAngle = ANG45 * (deathmatchstarts[i].angle / 45); - } - else - { - destX = playerstarts[0][0].x << FRACBITS; - destY = playerstarts[0][0].y << FRACBITS; - destAngle = ANG45 * (playerstarts[0][0].angle / 45); - } - P_Teleport(player->mo, destX, destY, destAngle, true); - if (player->morphTics) - { // Teleporting away will undo any morph effects (pig) - P_UndoPlayerMorph(player); - } - //S_StartSound(NULL, sfx_wpnup); // Full volume laugh -} - - -//---------------------------------------------------------------------------- -// -// PROC P_ArtiTeleportOther -// -//---------------------------------------------------------------------------- - -void P_ArtiTeleportOther(player_t * player) -{ - mobj_t *mo; - - mo = P_SpawnPlayerMissile(player->mo, MT_TELOTHER_FX1); - if (mo) - { - mo->target = player->mo; - } -} - - -void P_TeleportToPlayerStarts(mobj_t * victim) -{ - int i, selections = 0; - fixed_t destX, destY; - angle_t destAngle; - - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - continue; - selections++; - } - i = P_Random() % selections; - destX = playerstarts[0][i].x << FRACBITS; - destY = playerstarts[0][i].y << FRACBITS; - destAngle = ANG45 * (playerstarts[0][i].angle / 45); - P_Teleport(victim, destX, destY, destAngle, true); - //S_StartSound(NULL, sfx_wpnup); // Full volume laugh -} - -void P_TeleportToDeathmatchStarts(mobj_t * victim) -{ - int i, selections; - fixed_t destX, destY; - angle_t destAngle; - - selections = deathmatch_p - deathmatchstarts; - if (selections) - { - i = P_Random() % selections; - destX = deathmatchstarts[i].x << FRACBITS; - destY = deathmatchstarts[i].y << FRACBITS; - destAngle = ANG45 * (deathmatchstarts[i].angle / 45); - P_Teleport(victim, destX, destY, destAngle, true); - //S_StartSound(NULL, sfx_wpnup); // Full volume laugh - } - else - { - P_TeleportToPlayerStarts(victim); - } -} - - - -//---------------------------------------------------------------------------- -// -// PROC P_TeleportOther -// -//---------------------------------------------------------------------------- -void P_TeleportOther(mobj_t * victim) -{ - if (victim->player) - { - if (deathmatch) - P_TeleportToDeathmatchStarts(victim); - else - P_TeleportToPlayerStarts(victim); - } - else - { - // If death action, run it upon teleport - if (victim->flags & MF_COUNTKILL && victim->special) - { - P_RemoveMobjFromTIDList(victim); - P_ExecuteLineSpecial(victim->special, victim->args, - NULL, 0, victim); - victim->special = 0; - } - - // Send all monsters to deathmatch spots - P_TeleportToDeathmatchStarts(victim); - } -} - - - -#define BLAST_RADIUS_DIST 255*FRACUNIT -#define BLAST_SPEED 20*FRACUNIT -#define BLAST_FULLSTRENGTH 255 - -void ResetBlasted(mobj_t * mo) -{ - mo->flags2 &= ~MF2_BLASTED; - if (!(mo->flags & MF_ICECORPSE)) - { - mo->flags2 &= ~MF2_SLIDE; - } -} - -void P_BlastMobj(mobj_t * source, mobj_t * victim, fixed_t strength) -{ - angle_t angle, ang; - mobj_t *mo; - fixed_t x, y, z; - - angle = R_PointToAngle2(source->x, source->y, victim->x, victim->y); - angle >>= ANGLETOFINESHIFT; - if (strength < BLAST_FULLSTRENGTH) - { - victim->momx = FixedMul(strength, finecosine[angle]); - victim->momy = FixedMul(strength, finesine[angle]); - if (victim->player) - { - // Players handled automatically - } - else - { - victim->flags2 |= MF2_SLIDE; - victim->flags2 |= MF2_BLASTED; - } - } - else // full strength blast from artifact - { - if (victim->flags & MF_MISSILE) - { - switch (victim->type) - { - case MT_SORCBALL1: // don't blast sorcerer balls - case MT_SORCBALL2: - case MT_SORCBALL3: - return; - break; - case MT_MSTAFF_FX2: // Reflect to originator - victim->special1.m = victim->target; - victim->target = source; - break; - default: - break; - } - } - if (victim->type == MT_HOLY_FX) - { - if (victim->special1.m == source) - { - victim->special1.m = victim->target; - victim->target = source; - } - } - victim->momx = FixedMul(BLAST_SPEED, finecosine[angle]); - victim->momy = FixedMul(BLAST_SPEED, finesine[angle]); - - // Spawn blast puff - ang = R_PointToAngle2(victim->x, victim->y, source->x, source->y); - ang >>= ANGLETOFINESHIFT; - x = victim->x + FixedMul(victim->radius + FRACUNIT, finecosine[ang]); - y = victim->y + FixedMul(victim->radius + FRACUNIT, finesine[ang]); - z = victim->z - victim->floorclip + (victim->height >> 1); - mo = P_SpawnMobj(x, y, z, MT_BLASTEFFECT); - if (mo) - { - mo->momx = victim->momx; - mo->momy = victim->momy; - } - - if (victim->flags & MF_MISSILE) - { - victim->momz = 8 * FRACUNIT; - mo->momz = victim->momz; - } - else - { - victim->momz = (1000 / victim->info->mass) << FRACBITS; - } - if (victim->player) - { - // Players handled automatically - } - else - { - victim->flags2 |= MF2_SLIDE; - victim->flags2 |= MF2_BLASTED; - } - } -} - - -// Blast all mobj things away -void P_BlastRadius(player_t * player) -{ - mobj_t *mo; - mobj_t *pmo = player->mo; - thinker_t *think; - fixed_t dist; - - S_StartSound(pmo, SFX_ARTIFACT_BLAST); - P_NoiseAlert(player->mo, player->mo); - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - if ((mo == pmo) || (mo->flags2 & MF2_BOSS)) - { // Not a valid monster - continue; - } - if ((mo->type == MT_POISONCLOUD) || // poison cloud - (mo->type == MT_HOLY_FX) || // holy fx - (mo->flags & MF_ICECORPSE)) // frozen corpse - { - // Let these special cases go - } - else if ((mo->flags & MF_COUNTKILL) && (mo->health <= 0)) - { - continue; - } - else if (!(mo->flags & MF_COUNTKILL) && - !(mo->player) && !(mo->flags & MF_MISSILE)) - { // Must be monster, player, or missile - continue; - } - if (mo->flags2 & MF2_DORMANT) - { - continue; // no dormant creatures - } - if ((mo->type == MT_WRAITHB) && (mo->flags2 & MF2_DONTDRAW)) - { - continue; // no underground wraiths - } - if ((mo->type == MT_SPLASHBASE) || (mo->type == MT_SPLASH)) - { - continue; - } - if (mo->type == MT_SERPENT || mo->type == MT_SERPENTLEADER) - { - continue; - } - dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y); - if (dist > BLAST_RADIUS_DIST) - { // Out of range - continue; - } - P_BlastMobj(pmo, mo, BLAST_FULLSTRENGTH); - } -} - - -#define HEAL_RADIUS_DIST 255*FRACUNIT - -// Do class specific effect for everyone in radius -boolean P_HealRadius(player_t * player) -{ - mobj_t *mo; - mobj_t *pmo = player->mo; - thinker_t *think; - fixed_t dist; - int effective = false; - int amount; - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - mo = (mobj_t *) think; - - if (!mo->player) - continue; - if (mo->health <= 0) - continue; - dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y); - if (dist > HEAL_RADIUS_DIST) - { // Out of range - continue; - } - - switch (player->class) - { - case PCLASS_FIGHTER: // Radius armor boost - if ((P_GiveArmor(mo->player, ARMOR_ARMOR, 1)) || - (P_GiveArmor(mo->player, ARMOR_SHIELD, 1)) || - (P_GiveArmor(mo->player, ARMOR_HELMET, 1)) || - (P_GiveArmor(mo->player, ARMOR_AMULET, 1))) - { - effective = true; - S_StartSound(mo, SFX_MYSTICINCANT); - } - break; - case PCLASS_CLERIC: // Radius heal - amount = 50 + (P_Random() % 50); - if (P_GiveBody(mo->player, amount)) - { - effective = true; - S_StartSound(mo, SFX_MYSTICINCANT); - } - break; - case PCLASS_MAGE: // Radius mana boost - amount = 50 + (P_Random() % 50); - if ((P_GiveMana(mo->player, MANA_1, amount)) || - (P_GiveMana(mo->player, MANA_2, amount))) - { - effective = true; - S_StartSound(mo, SFX_MYSTICINCANT); - } - break; - case PCLASS_PIG: - default: - break; - } - } - return (effective); -} - - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerNextArtifact -// -//---------------------------------------------------------------------------- - -void P_PlayerNextArtifact(player_t * player) -{ - if (player == &players[consoleplayer]) - { - inv_ptr--; - if (inv_ptr < 6) - { - curpos--; - if (curpos < 0) - { - curpos = 0; - } - } - if (inv_ptr < 0) - { - inv_ptr = player->inventorySlotNum - 1; - if (inv_ptr < 6) - { - curpos = inv_ptr; - } - else - { - curpos = 6; - } - } - player->readyArtifact = player->inventory[inv_ptr].type; - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerRemoveArtifact -// -//---------------------------------------------------------------------------- - -void P_PlayerRemoveArtifact(player_t * player, int slot) -{ - int i; - - player->artifactCount--; - if (!(--player->inventory[slot].count)) - { // Used last of a type - compact the artifact list - player->readyArtifact = arti_none; - player->inventory[slot].type = arti_none; - for (i = slot + 1; i < player->inventorySlotNum; i++) - { - player->inventory[i - 1] = player->inventory[i]; - } - player->inventorySlotNum--; - if (player == &players[consoleplayer]) - { // Set position markers and get next readyArtifact - inv_ptr--; - if (inv_ptr < 6) - { - curpos--; - if (curpos < 0) - { - curpos = 0; - } - } - if (inv_ptr >= player->inventorySlotNum) - { - inv_ptr = player->inventorySlotNum - 1; - } - if (inv_ptr < 0) - { - inv_ptr = 0; - } - player->readyArtifact = player->inventory[inv_ptr].type; - } - } -} - -//---------------------------------------------------------------------------- -// -// PROC P_PlayerUseArtifact -// -//---------------------------------------------------------------------------- - -void P_PlayerUseArtifact(player_t * player, artitype_t arti) -{ - int i; - - for (i = 0; i < player->inventorySlotNum; i++) - { - if (player->inventory[i].type == arti) - { // Found match - try to use - if (P_UseArtifact(player, arti)) - { // Artifact was used - remove it from inventory - P_PlayerRemoveArtifact(player, i); - if (player == &players[consoleplayer]) - { - if (arti < arti_firstpuzzitem) - { - S_StartSound(NULL, SFX_ARTIFACT_USE); - } - else - { - S_StartSound(NULL, SFX_PUZZLE_SUCCESS); - } - ArtifactFlash = 4; - } - } - else if (arti < arti_firstpuzzitem) - { // Unable to use artifact, advance pointer - P_PlayerNextArtifact(player); - } - break; - } - } -} - -//========================================================================== -// -// P_UseArtifact -// -// Returns true if the artifact was used. -// -//========================================================================== - -boolean P_UseArtifact(player_t * player, artitype_t arti) -{ - mobj_t *mo; - angle_t angle; - int i; - int count; - - switch (arti) - { - case arti_invulnerability: - if (!P_GivePower(player, pw_invulnerability)) - { - return (false); - } - break; - case arti_health: - if (!P_GiveBody(player, 25)) - { - return (false); - } - break; - case arti_superhealth: - if (!P_GiveBody(player, 100)) - { - return (false); - } - break; - case arti_healingradius: - if (!P_HealRadius(player)) - { - return (false); - } - break; - case arti_torch: - if (!P_GivePower(player, pw_infrared)) - { - return (false); - } - break; - case arti_egg: - mo = player->mo; - P_SpawnPlayerMissile(mo, MT_EGGFX); - P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 6)); - P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 6)); - P_SPMAngle(mo, MT_EGGFX, mo->angle - (ANG45 / 3)); - P_SPMAngle(mo, MT_EGGFX, mo->angle + (ANG45 / 3)); - break; - case arti_fly: - if (!P_GivePower(player, pw_flight)) - { - return (false); - } - if (player->mo->momz <= -35 * FRACUNIT) - { // stop falling scream - S_StopSound(player->mo); - } - break; - case arti_summon: - mo = P_SpawnPlayerMissile(player->mo, MT_SUMMON_FX); - if (mo) - { - mo->target = player->mo; - mo->special1.m = (player->mo); - mo->momz = 5 * FRACUNIT; - } - break; - case arti_teleport: - P_ArtiTele(player); - break; - case arti_teleportother: - P_ArtiTeleportOther(player); - break; - case arti_poisonbag: - angle = player->mo->angle >> ANGLETOFINESHIFT; - if (player->class == PCLASS_CLERIC) - { - mo = P_SpawnMobj(player->mo->x + 16 * finecosine[angle], - player->mo->y + 24 * finesine[angle], - player->mo->z - player->mo->floorclip + - 8 * FRACUNIT, MT_POISONBAG); - if (mo) - { - mo->target = player->mo; - } - } - else if (player->class == PCLASS_MAGE) - { - mo = P_SpawnMobj(player->mo->x + 16 * finecosine[angle], - player->mo->y + 24 * finesine[angle], - player->mo->z - player->mo->floorclip + - 8 * FRACUNIT, MT_FIREBOMB); - if (mo) - { - mo->target = player->mo; - } - } - else // PCLASS_FIGHTER, obviously (also pig, not so obviously) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, - player->mo->z - player->mo->floorclip + - 35 * FRACUNIT, MT_THROWINGBOMB); - if (mo) - { - mo->angle = - player->mo->angle + (((P_Random() & 7) - 4) << 24); - mo->momz = - 4 * FRACUNIT + ((player->lookdir) << (FRACBITS - 4)); - mo->z += player->lookdir << (FRACBITS - 4); - P_ThrustMobj(mo, mo->angle, mo->info->speed); - mo->momx += player->mo->momx >> 1; - mo->momy += player->mo->momy >> 1; - mo->target = player->mo; - mo->tics -= P_Random() & 3; - P_CheckMissileSpawn(mo); - } - } - break; - case arti_speed: - if (!P_GivePower(player, pw_speed)) - { - return (false); - } - break; - case arti_boostmana: - if (!P_GiveMana(player, MANA_1, MAX_MANA)) - { - if (!P_GiveMana(player, MANA_2, MAX_MANA)) - { - return false; - } - - } - else - { - P_GiveMana(player, MANA_2, MAX_MANA); - } - break; - case arti_boostarmor: - count = 0; - - for (i = 0; i < NUMARMOR; i++) - { - count += P_GiveArmor(player, i, 1); // 1 point per armor type - } - if (!count) - { - return false; - } - break; - case arti_blastradius: - P_BlastRadius(player); - break; - - case arti_puzzskull: - case arti_puzzgembig: - case arti_puzzgemred: - case arti_puzzgemgreen1: - case arti_puzzgemgreen2: - case arti_puzzgemblue1: - case arti_puzzgemblue2: - case arti_puzzbook1: - case arti_puzzbook2: - case arti_puzzskull2: - case arti_puzzfweapon: - case arti_puzzcweapon: - case arti_puzzmweapon: - case arti_puzzgear1: - case arti_puzzgear2: - case arti_puzzgear3: - case arti_puzzgear4: - if (P_UsePuzzleItem(player, arti - arti_firstpuzzitem)) - { - return true; - } - else - { - P_SetYellowMessage(player, TXT_USEPUZZLEFAILED, false); - return false; - } - break; - default: - return false; - } - return true; -} - -//============================================================================ -// -// A_SpeedFade -// -//============================================================================ - -void A_SpeedFade(mobj_t *actor, player_t *player, pspdef_t *psp) -{ - actor->flags |= MF_SHADOW; - actor->flags &= ~MF_ALTSHADOW; - actor->sprite = actor->target->sprite; -} diff --git a/games/NXDoom/src/hexen/po_man.c b/games/NXDoom/src/hexen/po_man.c deleted file mode 100644 index 89364ad536d..00000000000 --- a/games/NXDoom/src/hexen/po_man.c +++ /dev/null @@ -1,1505 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "i_system.h" -#include "m_bbox.h" -#include "i_swap.h" -#include "p_local.h" -#include "r_local.h" - -// MACROS ------------------------------------------------------------------ - -#define PO_MAXPOLYSEGS 64 - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static polyobj_t *GetPolyobj(int polyNum); -static int GetPolyobjMirror(int poly); -static void ThrustMobj(mobj_t * mobj, seg_t * seg, polyobj_t * po); -static void UpdateSegBBox(seg_t * seg); -static void RotatePt(int an, fixed_t * x, fixed_t * y, fixed_t startSpotX, - fixed_t startSpotY); -static void UnLinkPolyobj(polyobj_t * po); -static void LinkPolyobj(polyobj_t * po); -static boolean CheckMobjBlocking(seg_t * seg, polyobj_t * po); -static void InitBlockMap(void); -static void IterFindPolySegs(int x, int y, seg_t ** segList); -static void SpawnPolyobj(int index, int tag, boolean crush); -static void TranslateToStartSpot(int tag, int originX, int originY); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -polyblock_t **PolyBlockMap; -polyobj_t *polyobjs; // list of all poly-objects on the level -int po_NumPolyobjs; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int PolySegCount; -static fixed_t PolyStartX; -static fixed_t PolyStartY; - -// CODE -------------------------------------------------------------------- - -// ===== Polyobj Event Code ===== - -//========================================================================== -// -// T_RotatePoly -// -//========================================================================== - -void T_RotatePoly(thinker_t *thinker) -{ - polyevent_t *pe = (polyevent_t *) thinker; - int absSpeed; - polyobj_t *poly; - - if (PO_RotatePolyobj(pe->polyobj, pe->speed)) - { - absSpeed = abs(pe->speed); - - if (pe->dist == -1) - { // perpetual polyobj - return; - } - pe->dist -= absSpeed; - if (pe->dist <= 0) - { - poly = GetPolyobj(pe->polyobj); - if (poly->specialdata == pe) - { - poly->specialdata = NULL; - } - SN_StopSequence((mobj_t *) & poly->startSpot); - P_PolyobjFinished(poly->tag); - P_RemoveThinker(&pe->thinker); - } - if (pe->dist < absSpeed) - { - pe->speed = pe->dist * (pe->speed < 0 ? -1 : 1); - } - } -} - -//========================================================================== -// -// EV_RotatePoly -// -//========================================================================== - -boolean EV_RotatePoly(line_t * line, byte * args, int direction, boolean - overRide) -{ - int mirror; - int polyNum; - polyevent_t *pe; - polyobj_t *poly; - - polyNum = args[0]; - poly = GetPolyobj(polyNum); - if (poly != NULL) - { - if (poly->specialdata && !overRide) - { // poly is already moving - return false; - } - } - else - { - I_Error("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); - } - pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); - P_AddThinker(&pe->thinker); - pe->thinker.function = T_RotatePoly; - pe->polyobj = polyNum; - if (args[2]) - { - if (args[2] == 255) - { - pe->dist = -1; - } - else - { - pe->dist = args[2] * (ANG90 / 64); // Angle - } - } - else - { - pe->dist = ANG_MAX - 1; - } - pe->speed = (args[1] * direction * (ANG90 / 64)) >> 3; - poly->specialdata = pe; - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - - while ((mirror = GetPolyobjMirror(polyNum)) != 0) - { - poly = GetPolyobj(mirror); - if (poly && poly->specialdata && !overRide) - { // mirroring poly is already in motion - break; - } - pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); - P_AddThinker(&pe->thinker); - pe->thinker.function = T_RotatePoly; - poly->specialdata = pe; - pe->polyobj = mirror; - if (args[2]) - { - if (args[2] == 255) - { - pe->dist = -1; - } - else - { - pe->dist = args[2] * (ANG90 / 64); // Angle - } - } - else - { - pe->dist = ANG_MAX - 1; - } - poly = GetPolyobj(polyNum); - if (poly != NULL) - { - poly->specialdata = pe; - } - else - { - I_Error("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); - } - direction = -direction; - pe->speed = (args[1] * direction * (ANG90 / 64)) >> 3; - polyNum = mirror; - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - return true; -} - -//========================================================================== -// -// T_MovePoly -// -//========================================================================== - -void T_MovePoly(thinker_t *thinker) -{ - polyevent_t *pe = (polyevent_t *) thinker; - int absSpeed; - polyobj_t *poly; - - if (PO_MovePolyobj(pe->polyobj, pe->xSpeed, pe->ySpeed)) - { - absSpeed = abs(pe->speed); - pe->dist -= absSpeed; - if (pe->dist <= 0) - { - poly = GetPolyobj(pe->polyobj); - if (poly->specialdata == pe) - { - poly->specialdata = NULL; - } - SN_StopSequence((mobj_t *) & poly->startSpot); - P_PolyobjFinished(poly->tag); - P_RemoveThinker(&pe->thinker); - } - if (pe->dist < absSpeed) - { - pe->speed = pe->dist * (pe->speed < 0 ? -1 : 1); - pe->xSpeed = FixedMul(pe->speed, finecosine[pe->angle]); - pe->ySpeed = FixedMul(pe->speed, finesine[pe->angle]); - } - } -} - -//========================================================================== -// -// EV_MovePoly -// -//========================================================================== - -boolean EV_MovePoly(line_t * line, byte * args, boolean timesEight, boolean - overRide) -{ - int mirror; - int polyNum; - polyevent_t *pe; - polyobj_t *poly; - angle_t an; - - polyNum = args[0]; - poly = GetPolyobj(polyNum); - if (poly != NULL) - { - if (poly->specialdata && !overRide) - { // poly is already moving - return false; - } - } - else - { - I_Error("EV_MovePoly: Invalid polyobj num: %d\n", polyNum); - } - pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); - P_AddThinker(&pe->thinker); - pe->thinker.function = T_MovePoly; - pe->polyobj = polyNum; - if (timesEight) - { - pe->dist = args[3] * 8 * FRACUNIT; - } - else - { - pe->dist = args[3] * FRACUNIT; // Distance - } - pe->speed = args[1] * (FRACUNIT / 8); - poly->specialdata = pe; - - an = args[2] * (ANG90 / 64); - - pe->angle = an >> ANGLETOFINESHIFT; - pe->xSpeed = FixedMul(pe->speed, finecosine[pe->angle]); - pe->ySpeed = FixedMul(pe->speed, finesine[pe->angle]); - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - - while ((mirror = GetPolyobjMirror(polyNum)) != 0) - { - poly = GetPolyobj(mirror); - if (poly && poly->specialdata && !overRide) - { // mirroring poly is already in motion - break; - } - pe = Z_Malloc(sizeof(polyevent_t), PU_LEVSPEC, 0); - P_AddThinker(&pe->thinker); - pe->thinker.function = T_MovePoly; - pe->polyobj = mirror; - poly->specialdata = pe; - if (timesEight) - { - pe->dist = args[3] * 8 * FRACUNIT; - } - else - { - pe->dist = args[3] * FRACUNIT; // Distance - } - pe->speed = args[1] * (FRACUNIT / 8); - an = an + ANG180; // reverse the angle - pe->angle = an >> ANGLETOFINESHIFT; - pe->xSpeed = FixedMul(pe->speed, finecosine[pe->angle]); - pe->ySpeed = FixedMul(pe->speed, finesine[pe->angle]); - polyNum = mirror; - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - return true; -} - -//========================================================================== -// -// T_PolyDoor -// -//========================================================================== - -void T_PolyDoor(thinker_t *thinker) -{ - polydoor_t *pd = (polydoor_t *) thinker; - int absSpeed; - polyobj_t *poly; - - if (pd->tics) - { - if (!--pd->tics) - { - poly = GetPolyobj(pd->polyobj); - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - return; - } - switch (pd->type) - { - case PODOOR_SLIDE: - if (PO_MovePolyobj(pd->polyobj, pd->xSpeed, pd->ySpeed)) - { - absSpeed = abs(pd->speed); - pd->dist -= absSpeed; - if (pd->dist <= 0) - { - poly = GetPolyobj(pd->polyobj); - SN_StopSequence((mobj_t *) & poly->startSpot); - if (!pd->close) - { - pd->dist = pd->totalDist; - pd->close = true; - pd->tics = pd->waitTics; - pd->direction = (ANG_MAX >> ANGLETOFINESHIFT) - - pd->direction; - pd->xSpeed = -pd->xSpeed; - pd->ySpeed = -pd->ySpeed; - } - else - { - if (poly->specialdata == pd) - { - poly->specialdata = NULL; - } - P_PolyobjFinished(poly->tag); - P_RemoveThinker(&pd->thinker); - } - } - } - else - { - poly = GetPolyobj(pd->polyobj); - if (poly->crush || !pd->close) - { // continue moving if the poly is a crusher, or is opening - return; - } - else - { // open back up - pd->dist = pd->totalDist - pd->dist; - pd->direction = (ANG_MAX >> ANGLETOFINESHIFT) - - pd->direction; - pd->xSpeed = -pd->xSpeed; - pd->ySpeed = -pd->ySpeed; - pd->close = false; - SN_StartSequence((mobj_t *) & poly->startSpot, - SEQ_DOOR_STONE + poly->seqType); - } - } - break; - case PODOOR_SWING: - if (PO_RotatePolyobj(pd->polyobj, pd->speed)) - { - absSpeed = abs(pd->speed); - if (pd->dist == -1) - { // perpetual polyobj - return; - } - pd->dist -= absSpeed; - if (pd->dist <= 0) - { - poly = GetPolyobj(pd->polyobj); - SN_StopSequence((mobj_t *) & poly->startSpot); - if (!pd->close) - { - pd->dist = pd->totalDist; - pd->close = true; - pd->tics = pd->waitTics; - pd->speed = -pd->speed; - } - else - { - if (poly->specialdata == pd) - { - poly->specialdata = NULL; - } - P_PolyobjFinished(poly->tag); - P_RemoveThinker(&pd->thinker); - } - } - } - else - { - poly = GetPolyobj(pd->polyobj); - if (poly->crush || !pd->close) - { // continue moving if the poly is a crusher, or is opening - return; - } - else - { // open back up and rewait - pd->dist = pd->totalDist - pd->dist; - pd->speed = -pd->speed; - pd->close = false; - SN_StartSequence((mobj_t *) & poly->startSpot, - SEQ_DOOR_STONE + poly->seqType); - } - } - break; - default: - break; - } -} - -//========================================================================== -// -// EV_OpenPolyDoor -// -//========================================================================== - -boolean EV_OpenPolyDoor(line_t * line, byte * args, podoortype_t type) -{ - int mirror; - int polyNum; - polydoor_t *pd; - polyobj_t *poly; - angle_t an = 0; - - polyNum = args[0]; - poly = GetPolyobj(polyNum); - if (poly != NULL) - { - if (poly->specialdata) - { // poly is already moving - return false; - } - } - else - { - I_Error("EV_OpenPolyDoor: Invalid polyobj num: %d\n", polyNum); - } - pd = Z_Malloc(sizeof(polydoor_t), PU_LEVSPEC, 0); - memset(pd, 0, sizeof(polydoor_t)); - P_AddThinker(&pd->thinker); - pd->thinker.function = T_PolyDoor; - pd->type = type; - pd->polyobj = polyNum; - if (type == PODOOR_SLIDE) - { - pd->waitTics = args[4]; - pd->speed = args[1] * (FRACUNIT / 8); - pd->totalDist = args[3] * FRACUNIT; // Distance - pd->dist = pd->totalDist; - an = args[2] * (ANG90 / 64); - pd->direction = an >> ANGLETOFINESHIFT; - pd->xSpeed = FixedMul(pd->speed, finecosine[pd->direction]); - pd->ySpeed = FixedMul(pd->speed, finesine[pd->direction]); - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - else if (type == PODOOR_SWING) - { - pd->waitTics = args[3]; - pd->direction = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR - pd->speed = (args[1] * pd->direction * (ANG90 / 64)) >> 3; - pd->totalDist = args[2] * (ANG90 / 64); - pd->dist = pd->totalDist; - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - - poly->specialdata = pd; - - while ((mirror = GetPolyobjMirror(polyNum)) != 0) - { - poly = GetPolyobj(mirror); - if (poly && poly->specialdata) - { // mirroring poly is already in motion - break; - } - pd = Z_Malloc(sizeof(polydoor_t), PU_LEVSPEC, 0); - memset(pd, 0, sizeof(polydoor_t)); - P_AddThinker(&pd->thinker); - pd->thinker.function = T_PolyDoor; - pd->polyobj = mirror; - pd->type = type; - poly->specialdata = pd; - if (type == PODOOR_SLIDE) - { - pd->waitTics = args[4]; - pd->speed = args[1] * (FRACUNIT / 8); - pd->totalDist = args[3] * FRACUNIT; // Distance - pd->dist = pd->totalDist; - an = an + ANG180; // reverse the angle - pd->direction = an >> ANGLETOFINESHIFT; - pd->xSpeed = FixedMul(pd->speed, finecosine[pd->direction]); - pd->ySpeed = FixedMul(pd->speed, finesine[pd->direction]); - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - else if (type == PODOOR_SWING) - { - pd->waitTics = args[3]; - pd->direction = -1; // ADD: same as above - pd->speed = (args[1] * pd->direction * (ANG90 / 64)) >> 3; - pd->totalDist = args[2] * (ANG90 / 64); - pd->dist = pd->totalDist; - SN_StartSequence((mobj_t *) & poly->startSpot, SEQ_DOOR_STONE + - poly->seqType); - } - polyNum = mirror; - } - return true; -} - -// ===== Higher Level Poly Interface code ===== - -//========================================================================== -// -// GetPolyobj -// -//========================================================================== - -static polyobj_t *GetPolyobj(int polyNum) -{ - int i; - - for (i = 0; i < po_NumPolyobjs; i++) - { - if (polyobjs[i].tag == polyNum) - { - return &polyobjs[i]; - } - } - return NULL; -} - -//========================================================================== -// -// GetPolyobjMirror -// -//========================================================================== - -static int GetPolyobjMirror(int poly) -{ - int i; - - for (i = 0; i < po_NumPolyobjs; i++) - { - if (polyobjs[i].tag == poly) - { - return ((*polyobjs[i].segs)->linedef->arg2); - } - } - return 0; -} - -//========================================================================== -// -// ThrustMobj -// -//========================================================================== - -static void ThrustMobj(mobj_t * mobj, seg_t * seg, polyobj_t * po) -{ - int thrustAngle; - int thrustX; - int thrustY; - polyevent_t *pe; - - int force; - - if (!(mobj->flags & MF_SHOOTABLE) && !mobj->player) - { - return; - } - thrustAngle = (seg->angle - ANG90) >> ANGLETOFINESHIFT; - - pe = po->specialdata; - if (pe) - { - if (pe->thinker.function == T_RotatePoly) - { - force = pe->speed >> 8; - } - else - { - force = pe->speed >> 3; - } - if (force < FRACUNIT) - { - force = FRACUNIT; - } - else if (force > 4 * FRACUNIT) - { - force = 4 * FRACUNIT; - } - } - else - { - force = FRACUNIT; - } - - thrustX = FixedMul(force, finecosine[thrustAngle]); - thrustY = FixedMul(force, finesine[thrustAngle]); - mobj->momx += thrustX; - mobj->momy += thrustY; - if (po->crush) - { - if (!P_CheckPosition(mobj, mobj->x + thrustX, mobj->y + thrustY)) - { - P_DamageMobj(mobj, NULL, NULL, 3); - } - } -} - -//========================================================================== -// -// UpdateSegBBox -// -//========================================================================== - -static void UpdateSegBBox(seg_t * seg) -{ - line_t *line; - - line = seg->linedef; - - if (seg->v1->x < seg->v2->x) - { - line->bbox[BOXLEFT] = seg->v1->x; - line->bbox[BOXRIGHT] = seg->v2->x; - } - else - { - line->bbox[BOXLEFT] = seg->v2->x; - line->bbox[BOXRIGHT] = seg->v1->x; - } - if (seg->v1->y < seg->v2->y) - { - line->bbox[BOXBOTTOM] = seg->v1->y; - line->bbox[BOXTOP] = seg->v2->y; - } - else - { - line->bbox[BOXBOTTOM] = seg->v2->y; - line->bbox[BOXTOP] = seg->v1->y; - } - - // Update the line's slopetype - line->dx = line->v2->x - line->v1->x; - line->dy = line->v2->y - line->v1->y; - if (!line->dx) - { - line->slopetype = ST_VERTICAL; - } - else if (!line->dy) - { - line->slopetype = ST_HORIZONTAL; - } - else - { - if (FixedDiv(line->dy, line->dx) > 0) - { - line->slopetype = ST_POSITIVE; - } - else - { - line->slopetype = ST_NEGATIVE; - } - } -} - -//========================================================================== -// -// PO_MovePolyobj -// -//========================================================================== - -boolean PO_MovePolyobj(int num, int x, int y) -{ - int count; - seg_t **segList; - seg_t **veryTempSeg; - polyobj_t *po; - vertex_t *prevPts; - boolean blocked; - - if (!(po = GetPolyobj(num))) - { - I_Error("PO_MovePolyobj: Invalid polyobj number: %d\n", num); - } - - UnLinkPolyobj(po); - - segList = po->segs; - prevPts = po->prevPts; - blocked = false; - - validcount++; - for (count = po->numsegs; count; count--, segList++, prevPts++) - { - if ((*segList)->linedef->validcount != validcount) - { - (*segList)->linedef->bbox[BOXTOP] += y; - (*segList)->linedef->bbox[BOXBOTTOM] += y; - (*segList)->linedef->bbox[BOXLEFT] += x; - (*segList)->linedef->bbox[BOXRIGHT] += x; - (*segList)->linedef->validcount = validcount; - } - for (veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++) - { - if ((*veryTempSeg)->v1 == (*segList)->v1) - { - break; - } - } - if (veryTempSeg == segList) - { - (*segList)->v1->x += x; - (*segList)->v1->y += y; - } - (*prevPts).x += x; // previous points are unique for each seg - (*prevPts).y += y; - } - segList = po->segs; - for (count = po->numsegs; count; count--, segList++) - { - if (CheckMobjBlocking(*segList, po)) - { - blocked = true; - } - } - if (blocked) - { - count = po->numsegs; - segList = po->segs; - prevPts = po->prevPts; - validcount++; - while (count--) - { - if ((*segList)->linedef->validcount != validcount) - { - (*segList)->linedef->bbox[BOXTOP] -= y; - (*segList)->linedef->bbox[BOXBOTTOM] -= y; - (*segList)->linedef->bbox[BOXLEFT] -= x; - (*segList)->linedef->bbox[BOXRIGHT] -= x; - (*segList)->linedef->validcount = validcount; - } - for (veryTempSeg = po->segs; veryTempSeg != segList; - veryTempSeg++) - { - if ((*veryTempSeg)->v1 == (*segList)->v1) - { - break; - } - } - if (veryTempSeg == segList) - { - (*segList)->v1->x -= x; - (*segList)->v1->y -= y; - } - (*prevPts).x -= x; - (*prevPts).y -= y; - segList++; - prevPts++; - } - LinkPolyobj(po); - return false; - } - po->startSpot.x += x; - po->startSpot.y += y; - LinkPolyobj(po); - return true; -} - -//========================================================================== -// -// RotatePt -// -//========================================================================== - -static void RotatePt(int an, fixed_t * x, fixed_t * y, fixed_t startSpotX, - fixed_t startSpotY) -{ - fixed_t trx, try; - fixed_t gxt, gyt; - - trx = *x; - try = *y; - - gxt = FixedMul(trx, finecosine[an]); - gyt = FixedMul(try, finesine[an]); - *x = (gxt - gyt) + startSpotX; - - gxt = FixedMul(trx, finesine[an]); - gyt = FixedMul(try, finecosine[an]); - *y = (gyt + gxt) + startSpotY; -} - -//========================================================================== -// -// PO_RotatePolyobj -// -//========================================================================== - -boolean PO_RotatePolyobj(int num, angle_t angle) -{ - int count; - seg_t **segList; - vertex_t *originalPts; - vertex_t *prevPts; - int an; - polyobj_t *po; - boolean blocked; - - if (!(po = GetPolyobj(num))) - { - I_Error("PO_RotatePolyobj: Invalid polyobj number: %d\n", num); - } - an = (po->angle + angle) >> ANGLETOFINESHIFT; - - UnLinkPolyobj(po); - - segList = po->segs; - originalPts = po->originalPts; - prevPts = po->prevPts; - - for (count = po->numsegs; count; count--, segList++, originalPts++, - prevPts++) - { - prevPts->x = (*segList)->v1->x; - prevPts->y = (*segList)->v1->y; - (*segList)->v1->x = originalPts->x; - (*segList)->v1->y = originalPts->y; - RotatePt(an, &(*segList)->v1->x, &(*segList)->v1->y, po->startSpot.x, - po->startSpot.y); - } - segList = po->segs; - blocked = false; - validcount++; - for (count = po->numsegs; count; count--, segList++) - { - if (CheckMobjBlocking(*segList, po)) - { - blocked = true; - } - if ((*segList)->linedef->validcount != validcount) - { - UpdateSegBBox(*segList); - (*segList)->linedef->validcount = validcount; - } - (*segList)->angle += angle; - } - if (blocked) - { - segList = po->segs; - prevPts = po->prevPts; - for (count = po->numsegs; count; count--, segList++, prevPts++) - { - (*segList)->v1->x = prevPts->x; - (*segList)->v1->y = prevPts->y; - } - segList = po->segs; - validcount++; - for (count = po->numsegs; count; count--, segList++, prevPts++) - { - if ((*segList)->linedef->validcount != validcount) - { - UpdateSegBBox(*segList); - (*segList)->linedef->validcount = validcount; - } - (*segList)->angle -= angle; - } - LinkPolyobj(po); - return false; - } - po->angle += angle; - LinkPolyobj(po); - return true; -} - -//========================================================================== -// -// UnLinkPolyobj -// -//========================================================================== - -static void UnLinkPolyobj(polyobj_t * po) -{ - polyblock_t *link; - int i, j; - int index; - - // remove the polyobj from each blockmap section - for (j = po->bbox[BOXBOTTOM]; j <= po->bbox[BOXTOP]; j++) - { - index = j * bmapwidth; - for (i = po->bbox[BOXLEFT]; i <= po->bbox[BOXRIGHT]; i++) - { - if (i >= 0 && i < bmapwidth && j >= 0 && j < bmapheight) - { - link = PolyBlockMap[index + i]; - while (link != NULL && link->polyobj != po) - { - link = link->next; - } - if (link == NULL) - { // polyobj not located in the link cell - continue; - } - link->polyobj = NULL; - } - } - } -} - -//========================================================================== -// -// LinkPolyobj -// -//========================================================================== - -static void LinkPolyobj(polyobj_t * po) -{ - int leftX, rightX; - int topY, bottomY; - seg_t **tempSeg; - polyblock_t **link; - polyblock_t *tempLink; - int i, j; - - // calculate the polyobj bbox - tempSeg = po->segs; - rightX = leftX = (*tempSeg)->v1->x; - topY = bottomY = (*tempSeg)->v1->y; - - for (i = 0; i < po->numsegs; i++, tempSeg++) - { - if ((*tempSeg)->v1->x > rightX) - { - rightX = (*tempSeg)->v1->x; - } - if ((*tempSeg)->v1->x < leftX) - { - leftX = (*tempSeg)->v1->x; - } - if ((*tempSeg)->v1->y > topY) - { - topY = (*tempSeg)->v1->y; - } - if ((*tempSeg)->v1->y < bottomY) - { - bottomY = (*tempSeg)->v1->y; - } - } - po->bbox[BOXRIGHT] = (rightX - bmaporgx) >> MAPBLOCKSHIFT; - po->bbox[BOXLEFT] = (leftX - bmaporgx) >> MAPBLOCKSHIFT; - po->bbox[BOXTOP] = (topY - bmaporgy) >> MAPBLOCKSHIFT; - po->bbox[BOXBOTTOM] = (bottomY - bmaporgy) >> MAPBLOCKSHIFT; - // add the polyobj to each blockmap section - for (j = po->bbox[BOXBOTTOM] * bmapwidth; - j <= po->bbox[BOXTOP] * bmapwidth; j += bmapwidth) - { - for (i = po->bbox[BOXLEFT]; i <= po->bbox[BOXRIGHT]; i++) - { - if (i >= 0 && i < bmapwidth && j >= 0 - && j < bmapheight * bmapwidth) - { - link = &PolyBlockMap[j + i]; - if (!(*link)) - { // Create a new link at the current block cell - *link = Z_Malloc(sizeof(polyblock_t), PU_LEVEL, 0); - (*link)->next = NULL; - (*link)->prev = NULL; - (*link)->polyobj = po; - continue; - } - else - { - tempLink = *link; - while (tempLink->next != NULL - && tempLink->polyobj != NULL) - { - tempLink = tempLink->next; - } - } - if (tempLink->polyobj == NULL) - { - tempLink->polyobj = po; - continue; - } - else - { - tempLink->next = Z_Malloc(sizeof(polyblock_t), - PU_LEVEL, 0); - tempLink->next->next = NULL; - tempLink->next->prev = tempLink; - tempLink->next->polyobj = po; - } - } - // else, don't link the polyobj, since it's off the map - } - } -} - -//========================================================================== -// -// CheckMobjBlocking -// -//========================================================================== - -static boolean CheckMobjBlocking(seg_t * seg, polyobj_t * po) -{ - mobj_t *mobj; - int i, j; - int left, right, top, bottom; - int tmbbox[4]; - line_t *ld; - boolean blocked; - - ld = seg->linedef; - - top = (ld->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; - bottom = (ld->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - left = (ld->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - right = (ld->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - - blocked = false; - - bottom = bottom < 0 ? 0 : bottom; - bottom = bottom >= bmapheight ? bmapheight - 1 : bottom; - top = top < 0 ? 0 : top; - top = top >= bmapheight ? bmapheight - 1 : top; - left = left < 0 ? 0 : left; - left = left >= bmapwidth ? bmapwidth - 1 : left; - right = right < 0 ? 0 : right; - right = right >= bmapwidth ? bmapwidth - 1 : right; - - for (j = bottom * bmapwidth; j <= top * bmapwidth; j += bmapwidth) - { - for (i = left; i <= right; i++) - { - for (mobj = blocklinks[j + i]; mobj; mobj = mobj->bnext) - { - if (mobj->flags & MF_SOLID || mobj->player) - { - tmbbox[BOXTOP] = mobj->y + mobj->radius; - tmbbox[BOXBOTTOM] = mobj->y - mobj->radius; - tmbbox[BOXLEFT] = mobj->x - mobj->radius; - tmbbox[BOXRIGHT] = mobj->x + mobj->radius; - - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - { - continue; - } - if (P_BoxOnLineSide(tmbbox, ld) != -1) - { - continue; - } - ThrustMobj(mobj, seg, po); - blocked = true; - } - } - } - } - return blocked; -} - -//========================================================================== -// -// InitBlockMap -// -//========================================================================== - -static void InitBlockMap(void) -{ - int i; - int j; - seg_t **segList; - int leftX, rightX; - int topY, bottomY; - - PolyBlockMap = Z_Malloc(bmapwidth * bmapheight * sizeof(polyblock_t *), - PU_LEVEL, 0); - memset(PolyBlockMap, 0, bmapwidth * bmapheight * sizeof(polyblock_t *)); - - for (i = 0; i < po_NumPolyobjs; i++) - { - LinkPolyobj(&polyobjs[i]); - - // calculate a rough area - // right now, working like shit...gotta fix this... - segList = polyobjs[i].segs; - leftX = rightX = (*segList)->v1->x; - topY = bottomY = (*segList)->v1->y; - for (j = 0; j < polyobjs[i].numsegs; j++, segList++) - { - if ((*segList)->v1->x < leftX) - { - leftX = (*segList)->v1->x; - } - if ((*segList)->v1->x > rightX) - { - rightX = (*segList)->v1->x; - } - if ((*segList)->v1->y < bottomY) - { - bottomY = (*segList)->v1->y; - } - if ((*segList)->v1->y > topY) - { - topY = (*segList)->v1->y; - } - } -// area = ((rightX >> FRACBITS) - (leftX >> FRACBITS)) * -// ((topY >> FRACBITS) - (bottomY >> FRACBITS)); - -// fprintf(stdaux, "Area of Polyobj[%d]: %d\n", polyobjs[i].tag, area); -// fprintf(stdaux, "\t[%d]\n[%d]\t\t[%d]\n\t[%d]\n", topY>>FRACBITS, -// leftX>>FRACBITS, -// rightX>>FRACBITS, bottomY>>FRACBITS); - } -} - -//========================================================================== -// -// IterFindPolySegs -// -// Passing NULL for segList will cause IterFindPolySegs to -// count the number of segs in the polyobj -//========================================================================== - -static void IterFindPolySegs(int x, int y, seg_t ** segList) -{ - int i; - - if (x == PolyStartX && y == PolyStartY) - { - return; - } - for (i = 0; i < numsegs; i++) - { - if (segs[i].v1->x == x && segs[i].v1->y == y) - { - if (!segList) - { - PolySegCount++; - } - else - { - *segList++ = &segs[i]; - } - IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, segList); - return; - } - } - I_Error("IterFindPolySegs: Non-closed Polyobj located.\n"); -} - - -//========================================================================== -// -// SpawnPolyobj -// -//========================================================================== - -static void SpawnPolyobj(int index, int tag, boolean crush) -{ - int i; - int j; - int psIndex; - int psIndexOld; - seg_t *polySegList[PO_MAXPOLYSEGS]; - - for (i = 0; i < numsegs; i++) - { - if (segs[i].linedef->special == PO_LINE_START && - segs[i].linedef->arg1 == tag) - { - if (polyobjs[index].segs) - { - I_Error("SpawnPolyobj: Polyobj %d already spawned.\n", tag); - } - segs[i].linedef->special = 0; - segs[i].linedef->arg1 = 0; - PolySegCount = 1; - PolyStartX = segs[i].v1->x; - PolyStartY = segs[i].v1->y; - IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, NULL); - - polyobjs[index].numsegs = PolySegCount; - polyobjs[index].segs = Z_Malloc(PolySegCount * sizeof(seg_t *), - PU_LEVEL, 0); - *(polyobjs[index].segs) = &segs[i]; // insert the first seg - IterFindPolySegs(segs[i].v2->x, segs[i].v2->y, - polyobjs[index].segs + 1); - polyobjs[index].crush = crush; - polyobjs[index].tag = tag; - polyobjs[index].seqType = segs[i].linedef->arg3; - if (polyobjs[index].seqType < 0 - || polyobjs[index].seqType >= SEQTYPE_NUMSEQ) - { - polyobjs[index].seqType = 0; - } - break; - } - } - if (!polyobjs[index].segs) - { // didn't find a polyobj through PO_LINE_START - psIndex = 0; - polyobjs[index].numsegs = 0; - for (j = 1; j < PO_MAXPOLYSEGS; j++) - { - psIndexOld = psIndex; - for (i = 0; i < numsegs; i++) - { - if (segs[i].linedef->special == PO_LINE_EXPLICIT && - segs[i].linedef->arg1 == tag) - { - if (!segs[i].linedef->arg2) - { - I_Error - ("SpawnPolyobj: Explicit line missing order number (probably %d) in poly %d.\n", - j + 1, tag); - } - if (segs[i].linedef->arg2 == j) - { - polySegList[psIndex] = &segs[i]; - polyobjs[index].numsegs++; - psIndex++; - if (psIndex > PO_MAXPOLYSEGS) - { - I_Error - ("SpawnPolyobj: psIndex > PO_MAXPOLYSEGS\n"); - } - } - } - } - // Clear out any specials for these segs...we cannot clear them out - // in the above loop, since we aren't guaranteed one seg per - // linedef. - for (i = 0; i < numsegs; i++) - { - if (segs[i].linedef->special == PO_LINE_EXPLICIT && - segs[i].linedef->arg1 == tag - && segs[i].linedef->arg2 == j) - { - segs[i].linedef->special = 0; - segs[i].linedef->arg1 = 0; - } - } - if (psIndex == psIndexOld) - { // Check if an explicit line order has been skipped - // A line has been skipped if there are any more explicit - // lines with the current tag value - for (i = 0; i < numsegs; i++) - { - if (segs[i].linedef->special == PO_LINE_EXPLICIT && - segs[i].linedef->arg1 == tag) - { - I_Error - ("SpawnPolyobj: Missing explicit line %d for poly %d\n", - j, tag); - } - } - } - } - if (polyobjs[index].numsegs) - { - PolySegCount = polyobjs[index].numsegs; // PolySegCount used globally - polyobjs[index].crush = crush; - polyobjs[index].tag = tag; - polyobjs[index].segs = Z_Malloc(polyobjs[index].numsegs - * sizeof(seg_t *), PU_LEVEL, 0); - for (i = 0; i < polyobjs[index].numsegs; i++) - { - polyobjs[index].segs[i] = polySegList[i]; - } - polyobjs[index].seqType = (*polyobjs[index].segs)->linedef->arg4; - } - // Next, change the polyobjs first line to point to a mirror - // if it exists - (*polyobjs[index].segs)->linedef->arg2 = - (*polyobjs[index].segs)->linedef->arg3; - } -} - -//========================================================================== -// -// TranslateToStartSpot -// -//========================================================================== - -static void TranslateToStartSpot(int tag, int originX, int originY) -{ - seg_t **tempSeg; - seg_t **veryTempSeg; - vertex_t *tempPt; - subsector_t *sub; - polyobj_t *po; - int deltaX; - int deltaY; - vertex_t avg; // used to find a polyobj's center, and hence subsector - int i; - - po = NULL; - for (i = 0; i < po_NumPolyobjs; i++) - { - if (polyobjs[i].tag == tag) - { - po = &polyobjs[i]; - break; - } - } - if (!po) - { // didn't match the tag with a polyobj tag - I_Error("TranslateToStartSpot: Unable to match polyobj tag: %d\n", - tag); - } - if (po->segs == NULL) - { - I_Error - ("TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", - tag); - } - po->originalPts = Z_Malloc(po->numsegs * sizeof(vertex_t), PU_LEVEL, 0); - po->prevPts = Z_Malloc(po->numsegs * sizeof(vertex_t), PU_LEVEL, 0); - deltaX = originX - po->startSpot.x; - deltaY = originY - po->startSpot.y; - - tempSeg = po->segs; - tempPt = po->originalPts; - avg.x = 0; - avg.y = 0; - - validcount++; - for (i = 0; i < po->numsegs; i++, tempSeg++, tempPt++) - { - if ((*tempSeg)->linedef->validcount != validcount) - { - (*tempSeg)->linedef->bbox[BOXTOP] -= deltaY; - (*tempSeg)->linedef->bbox[BOXBOTTOM] -= deltaY; - (*tempSeg)->linedef->bbox[BOXLEFT] -= deltaX; - (*tempSeg)->linedef->bbox[BOXRIGHT] -= deltaX; - (*tempSeg)->linedef->validcount = validcount; - } - for (veryTempSeg = po->segs; veryTempSeg != tempSeg; veryTempSeg++) - { - if ((*veryTempSeg)->v1 == (*tempSeg)->v1) - { - break; - } - } - if (veryTempSeg == tempSeg) - { // the point hasn't been translated, yet - (*tempSeg)->v1->x -= deltaX; - (*tempSeg)->v1->y -= deltaY; - } - avg.x += (*tempSeg)->v1->x >> FRACBITS; - avg.y += (*tempSeg)->v1->y >> FRACBITS; - // the original Pts are based off the startSpot Pt, and are - // unique to each seg, not each linedef - tempPt->x = (*tempSeg)->v1->x - po->startSpot.x; - tempPt->y = (*tempSeg)->v1->y - po->startSpot.y; - } - avg.x /= po->numsegs; - avg.y /= po->numsegs; - sub = R_PointInSubsector(avg.x << FRACBITS, avg.y << FRACBITS); - if (sub->poly != NULL) - { - I_Error - ("PO_TranslateToStartSpot: Multiple polyobjs in a single subsector.\n"); - } - sub->poly = po; -} - -//========================================================================== -// -// PO_Init -// -//========================================================================== - -void PO_Init(int lump) -{ - byte *data; - int i; - mapthing_t spawnthing; - mapthing_t *mt; - int numthings; - int polyIndex; - - polyobjs = Z_Malloc(po_NumPolyobjs * sizeof(polyobj_t), PU_LEVEL, 0); - memset(polyobjs, 0, po_NumPolyobjs * sizeof(polyobj_t)); - - data = W_CacheLumpNum(lump, PU_STATIC); - numthings = W_LumpLength(lump) / sizeof(mapthing_t); - mt = (mapthing_t *) data; - polyIndex = 0; // index polyobj number - // Find the startSpot points, and spawn each polyobj - for (i = 0; i < numthings; i++, mt++) - { - spawnthing.x = SHORT(mt->x); - spawnthing.y = SHORT(mt->y); - spawnthing.angle = SHORT(mt->angle); - spawnthing.type = SHORT(mt->type); - - // 3001 = no crush, 3002 = crushing - if (spawnthing.type == PO_SPAWN_TYPE - || spawnthing.type == PO_SPAWNCRUSH_TYPE) - { // Polyobj StartSpot Pt. - polyobjs[polyIndex].startSpot.x = spawnthing.x << FRACBITS; - polyobjs[polyIndex].startSpot.y = spawnthing.y << FRACBITS; - polyobjs[polyIndex].startSpot.thinker.function = (think_t) P_DegenMobjThinker; - SpawnPolyobj(polyIndex, spawnthing.angle, - (spawnthing.type == PO_SPAWNCRUSH_TYPE)); - polyIndex++; - } - } - mt = (mapthing_t *) data; - for (i = 0; i < numthings; i++, mt++) - { - spawnthing.x = SHORT(mt->x); - spawnthing.y = SHORT(mt->y); - spawnthing.angle = SHORT(mt->angle); - spawnthing.type = SHORT(mt->type); - if (spawnthing.type == PO_ANCHOR_TYPE) - { // Polyobj Anchor Pt. - TranslateToStartSpot(spawnthing.angle, - spawnthing.x << FRACBITS, - spawnthing.y << FRACBITS); - } - } - W_ReleaseLumpNum(lump); - // check for a startspot without an anchor point - for (i = 0; i < po_NumPolyobjs; i++) - { - if (!polyobjs[i].originalPts) - { - I_Error - ("PO_Init: StartSpot located without an Anchor point: %d\n", - polyobjs[i].tag); - } - } - InitBlockMap(); -} - -//========================================================================== -// -// PO_Busy -// -//========================================================================== - -boolean PO_Busy(int polyobj) -{ - polyobj_t *poly; - - poly = GetPolyobj(polyobj); - if (!poly->specialdata) - { - return false; - } - else - { - return true; - } -} diff --git a/games/NXDoom/src/hexen/r_bsp.c b/games/NXDoom/src/hexen/r_bsp.c deleted file mode 100644 index cae9cbfd466..00000000000 --- a/games/NXDoom/src/hexen/r_bsp.c +++ /dev/null @@ -1,508 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "m_bbox.h" -#include "r_local.h" - -seg_t *curline; -side_t *sidedef; -line_t *linedef; -sector_t *frontsector, *backsector; - -drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; - -void R_StoreWallRange(int start, int stop); - -/* -==================== -= -= R_ClearDrawSegs -= -==================== -*/ - -void R_ClearDrawSegs(void) -{ - ds_p = drawsegs; -} - -//============================================================================= - - -/* -=============================================================================== -= -= ClipWallSegment -= -= Clips the given range of columns and includes it in the new clip list -=============================================================================== -*/ - -typedef struct -{ - int first, last; -} cliprange_t; - -// We must expand MAXSEGS to the theoretical limit of the number of solidsegs -// that can be generated in a scene by the DOOM engine. This was determined by -// Lee Killough during BOOM development to be a function of the screensize. -// The simplest thing we can do, other than fix this bug, is to let the game -// render overage and then bomb out by detecting the overflow after the -// fact. -haleyjd -//#define MAXSEGS 32 -#define MAXSEGS (SCREENWIDTH / 2 + 1) - -cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg - - -void R_ClipSolidWallSegment(int first, int last) -{ - cliprange_t *next, *start; - -// find the first range that touches the range (adjacent pixels are touching) - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first - 1) - { // post is entirely visible (above start), so insert a new clippost - R_StoreWallRange(first, last); - next = newend; - newend++; - while (next != start) - { - *next = *(next - 1); - next--; - } - next->first = first; - next->last = last; - return; - } - - // there is a fragment above *start - R_StoreWallRange(first, start->first - 1); - start->first = first; // adjust the clip size - } - - if (last <= start->last) - return; // bottom contained in start - - next = start; - while (last >= (next + 1)->first - 1) - { - // there is a fragment between two posts - R_StoreWallRange(next->last + 1, (next + 1)->first - 1); - next++; - if (last <= next->last) - { // bottom is contained in next - start->last = next->last; // adjust the clip size - goto crunch; - } - } - - // there is a fragment after *next - R_StoreWallRange(next->last + 1, last); - start->last = last; // adjust the clip size - - -// remove start+1 to next from the clip list, -// because start now covers their area - crunch: - if (next == start) - return; // post just extended past the bottom of one post - - while (next++ != newend) // remove a post - *++start = *next; - newend = start + 1; -} - -/* -=============================================================================== -= -= R_ClipPassWallSegment -= -= Clips the given range of columns, but does not includes it in the clip list -=============================================================================== -*/ - -void R_ClipPassWallSegment(int first, int last) -{ - cliprange_t *start; - -// find the first range that touches the range (adjacent pixels are touching) - start = solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first - 1) - { // post is entirely visible (above start) - R_StoreWallRange(first, last); - return; - } - - // there is a fragment above *start - R_StoreWallRange(first, start->first - 1); - } - - if (last <= start->last) - return; // bottom contained in start - - while (last >= (start + 1)->first - 1) - { - // there is a fragment between two posts - R_StoreWallRange(start->last + 1, (start + 1)->first - 1); - start++; - if (last <= start->last) - return; - } - - // there is a fragment after *next - R_StoreWallRange(start->last + 1, last); -} - - - -/* -==================== -= -= R_ClearClipSegs -= -==================== -*/ - -void R_ClearClipSegs(void) -{ - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = -1; - solidsegs[1].first = viewwidth; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs + 2; -} - - -//============================================================================= - -/* -====================== -= -= R_AddLine -= -= Clips the given segment and adds any visible pieces to the line list -= -====================== -*/ - -void R_AddLine(seg_t * line) -{ - int x1, x2; - angle_t angle1, angle2, span, tspan; - - curline = line; - -// OPTIMIZE: quickly reject orthogonal back sides - - angle1 = R_PointToAngle(line->v1->x, line->v1->y); - angle2 = R_PointToAngle(line->v2->x, line->v2->y); - -// -// clip to view edges -// OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW) - span = angle1 - angle2; - if (span >= ANG180) - return; // back side - - rw_angle1 = angle1; // global angle needed by segcalc - angle1 -= viewangle; - angle2 -= viewangle; - - tspan = angle1 + clipangle; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return; // totally off the left edge - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return; // totally off the left edge - angle2 = -clipangle; - } - -// -// the seg is in the view range, but not necessarily visible -// - angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; - angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; - if (x1 == x2) - return; // does not cross a pixel - - backsector = line->backsector; - - if (!backsector) - goto clipsolid; // single sided line - - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - goto clipsolid; // closed door - - if (backsector->ceilingheight != frontsector->ceilingheight - || backsector->floorheight != frontsector->floorheight) - goto clippass; // window - -// reject empty lines used for triggers and special events - if (backsector->ceilingpic == frontsector->ceilingpic - && backsector->floorpic == frontsector->floorpic - && backsector->lightlevel == frontsector->lightlevel - && backsector->special == frontsector->special - && curline->sidedef->midtexture == 0) - return; - - clippass: - R_ClipPassWallSegment(x1, x2 - 1); - return; - - clipsolid: - R_ClipSolidWallSegment(x1, x2 - 1); -} - -//============================================================================ - - -/* -=============================================================================== -= -= R_CheckBBox -= -= Returns true if some part of the bbox might be visible -= -=============================================================================== -*/ - -int checkcoord[12][4] = { - {3, 0, 2, 1}, - {3, 0, 2, 0}, - {3, 1, 2, 0}, - {0}, - {2, 0, 2, 1}, - {0, 0, 0, 0}, - {3, 1, 3, 0}, - {0}, - {2, 0, 3, 1}, - {2, 1, 3, 1}, - {2, 1, 3, 0} -}; - - -boolean R_CheckBBox(fixed_t * bspcoord) -{ - int boxx, boxy, boxpos; - fixed_t x1, y1, x2, y2; - angle_t angle1, angle2, span, tspan; - cliprange_t *start; - int sx1, sx2; - -// find the corners of the box that define the edges from current viewpoint - if (viewx <= bspcoord[BOXLEFT]) - boxx = 0; - else if (viewx < bspcoord[BOXRIGHT]) - boxx = 1; - else - boxx = 2; - - if (viewy >= bspcoord[BOXTOP]) - boxy = 0; - else if (viewy > bspcoord[BOXBOTTOM]) - boxy = 1; - else - boxy = 2; - - boxpos = (boxy << 2) + boxx; - if (boxpos == 5) - return true; - - x1 = bspcoord[checkcoord[boxpos][0]]; - y1 = bspcoord[checkcoord[boxpos][1]]; - x2 = bspcoord[checkcoord[boxpos][2]]; - y2 = bspcoord[checkcoord[boxpos][3]]; - - -// -// check clip list for an open space -// - angle1 = R_PointToAngle(x1, y1) - viewangle; - angle2 = R_PointToAngle(x2, y2) - viewangle; - - span = angle1 - angle2; - if (span >= ANG180) - return true; // sitting on a line - tspan = angle1 + clipangle; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return false; // totally off the left edge - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2 * clipangle) - { - tspan -= 2 * clipangle; - if (tspan >= span) - return false; // totally off the left edge - angle2 = -clipangle; - } - - -// find the first clippost that touches the source post (adjacent pixels are touching) - angle1 = (angle1 + ANG90) >> ANGLETOFINESHIFT; - angle2 = (angle2 + ANG90) >> ANGLETOFINESHIFT; - sx1 = viewangletox[angle1]; - sx2 = viewangletox[angle2]; - if (sx1 == sx2) - return false; // does not cross a pixel - sx2--; - - start = solidsegs; - while (start->last < sx2) - start++; - if (sx1 >= start->first && sx2 <= start->last) - return false; // the clippost contains the new span - - return true; -} - - -/* -================ -= -= R_Subsector -= -= Draw one or more segments -================ -*/ - -void R_Subsector(int num) -{ - int count; - seg_t *line; - subsector_t *sub; - int polyCount; - seg_t **polySeg; - -#ifdef RANGECHECK - if (num >= numsubsectors) - I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); -#endif - - sscount++; - sub = &subsectors[num]; - frontsector = sub->sector; - count = sub->numlines; - line = &segs[sub->firstline]; - - if (frontsector->floorheight < viewz) - { - floorplane = R_FindPlane(frontsector->floorheight, - frontsector->floorpic, - frontsector->lightlevel, - frontsector->special); - } - else - { - floorplane = NULL; - } - - if (frontsector->ceilingheight > viewz - || frontsector->ceilingpic == skyflatnum) - { - ceilingplane = R_FindPlane(frontsector->ceilingheight, - frontsector->ceilingpic, - frontsector->lightlevel, 0); - } - else - { - ceilingplane = NULL; - } - - R_AddSprites(frontsector); - if (sub->poly) - { // Render the polyobj in the subsector first - polyCount = sub->poly->numsegs; - polySeg = sub->poly->segs; - while (polyCount--) - { - R_AddLine(*polySeg++); - } - } - while (count--) - { - R_AddLine(line); - line++; - } - - // check for solidsegs overflow - extremely unsatisfactory! - if(newend > &solidsegs[32]) - I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); -} - - -/* -=============================================================================== -= -= RenderBSPNode -= -=============================================================================== -*/ - -void R_RenderBSPNode(int bspnum) -{ - node_t *bsp; - int side; - - if (bspnum & NF_SUBSECTOR) - { - if (bspnum == -1) - R_Subsector(0); - else - R_Subsector(bspnum & (~NF_SUBSECTOR)); - return; - } - - bsp = &nodes[bspnum]; - -// -// decide which side the view point is on -// - side = R_PointOnSide(viewx, viewy, bsp); - - R_RenderBSPNode(bsp->children[side]); // recursively divide front space - - if (R_CheckBBox(bsp->bbox[side ^ 1])) // possibly divide back space - R_RenderBSPNode(bsp->children[side ^ 1]); -} diff --git a/games/NXDoom/src/hexen/r_data.c b/games/NXDoom/src/hexen/r_data.c deleted file mode 100644 index 1c4ef7c36a5..00000000000 --- a/games/NXDoom/src/hexen/r_data.c +++ /dev/null @@ -1,689 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "i_swap.h" -#include "m_misc.h" -#include "r_local.h" -#include "p_local.h" - -typedef struct -{ - int originx; // block origin (allways UL), which has allready - int originy; // accounted for the patch's internal origin - int patch; -} texpatch_t; - -// a maptexturedef_t describes a rectangular texture, which is composed of one -// or more mappatch_t structures that arrange graphic patches -typedef struct -{ - char name[8]; // for switch changing, etc - short width; - short height; - short patchcount; - texpatch_t patches[1]; // [patchcount] drawn back to front - // into the cached texture -} texture_t; - - - -int firstflat, lastflat, numflats; -int firstpatch, lastpatch, numpatches; -int firstspritelump, lastspritelump, numspritelumps; - -int numtextures; -texture_t **textures; -int *texturewidthmask; -fixed_t *textureheight; // needed for texture pegging -int *texturecompositesize; -short **texturecolumnlump; -unsigned short **texturecolumnofs; -byte **texturecomposite; - -int *flattranslation; // for global animation -int *texturetranslation; // for global animation - -fixed_t *spritewidth; // needed for pre rendering -fixed_t *spriteoffset; -fixed_t *spritetopoffset; - -lighttable_t *colormaps; - - -/* -============================================================================== - - MAPTEXTURE_T CACHING - -when a texture is first needed, it counts the number of composite columns -required in the texture and allocates space for a column directory and any -new columns. The directory will simply point inside other patches if there -is only one patch in a given column, but any columns with multiple patches -will have new column_ts generated. - -============================================================================== -*/ - -/* -=================== -= -= R_DrawColumnInCache -= -= Clip and draw a column from a patch into a cached post -= -=================== -*/ - -void R_DrawColumnInCache(column_t * patch, byte * cache, int originy, - int cacheheight) -{ - int count, position; - byte *source; - - while (patch->topdelta != 0xff) - { - source = (byte *) patch + 3; - count = patch->length; - position = originy + patch->topdelta; - if (position < 0) - { - count += position; - position = 0; - } - if (position + count > cacheheight) - count = cacheheight - position; - if (count > 0) - memcpy(cache + position, source, count); - - patch = (column_t *) ((byte *) patch + patch->length + 4); - } -} - - -/* -=================== -= -= R_GenerateComposite -= -=================== -*/ - -void R_GenerateComposite(int texnum) -{ - byte *block; - texture_t *texture; - texpatch_t *patch; - patch_t *realpatch; - int x, x1, x2; - int i; - column_t *patchcol; - short *collump; - unsigned short *colofs; - - texture = textures[texnum]; - block = Z_Malloc(texturecompositesize[texnum], PU_STATIC, - &texturecomposite[texnum]); - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - -// -// composite the columns together -// - for (i = 0, patch = texture->patches; i < texture->patchcount; - i++, patch++) - { - realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1 < 0) - x = 0; - else - x = x1; - if (x2 > texture->width) - x2 = texture->width; - - for (; x < x2; x++) - { - if (collump[x] >= 0) - continue; // column does not have multiple patches - patchcol = (column_t *) ((byte *) realpatch + - LONG(realpatch->columnofs[x - x1])); - R_DrawColumnInCache(patchcol, block + colofs[x], patch->originy, - texture->height); - } - - } - -// now that the texture has been built, it is purgable - Z_ChangeTag(block, PU_CACHE); -} - - -/* -=================== -= -= R_GenerateLookup -= -=================== -*/ - -void R_GenerateLookup(int texnum) -{ - texture_t *texture; - byte *patchcount; // [texture->width] - texpatch_t *patch; - patch_t *realpatch; - int x, x1, x2; - int i; - short *collump; - unsigned short *colofs; - - texture = textures[texnum]; - - texturecomposite[texnum] = 0; // composited not created yet - texturecompositesize[texnum] = 0; - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - -// -// count the number of columns that are covered by more than one patch -// fill in the lump / offset, so columns with only a single patch are -// all done -// - patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); - memset(patchcount, 0, texture->width); - for (i = 0, patch = texture->patches; i < texture->patchcount; - i++, patch++) - { - realpatch = W_CacheLumpNum(patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - if (x1 < 0) - x = 0; - else - x = x1; - if (x2 > texture->width) - x2 = texture->width; - for (; x < x2; x++) - { - patchcount[x]++; - collump[x] = patch->patch; - colofs[x] = LONG(realpatch->columnofs[x - x1]) + 3; - } - } - - for (x = 0; x < texture->width; x++) - { - if (!patchcount[x]) - { - ST_Message("R_GenerateLookup: column without a patch (%s)\n", - texture->name); - return; - } -// I_Error ("R_GenerateLookup: column without a patch"); - if (patchcount[x] > 1) - { - collump[x] = -1; // use the cached block - colofs[x] = texturecompositesize[texnum]; - if (texturecompositesize[texnum] > 0x10000 - texture->height) - I_Error("R_GenerateLookup: texture %i is >64k", texnum); - texturecompositesize[texnum] += texture->height; - } - } - - Z_Free(patchcount); -} - - -/* -================ -= -= R_GetColumn -= -================ -*/ - -byte *R_GetColumn(int tex, int col) -{ - int lump, ofs; - - col &= texturewidthmask[tex]; - lump = texturecolumnlump[tex][col]; - ofs = texturecolumnofs[tex][col]; - if (lump > 0) - return (byte *) W_CacheLumpNum(lump, PU_CACHE) + ofs; - if (!texturecomposite[tex]) - R_GenerateComposite(tex); - return texturecomposite[tex] + ofs; -} - - -/* -================== -= -= R_InitTextures -= -= Initializes the texture list with the textures from the world map -= -================== -*/ - -void R_InitTextures(void) -{ - maptexture_t *mtexture; - texture_t *texture; - mappatch_t *mpatch; - texpatch_t *patch; - int i, j; - int *maptex, *maptex2, *maptex1; - char name[9], *names, *name_p; - int *patchlookup; - int nummappatches; - int offset, maxoff, maxoff2; - int numtextures1, numtextures2; - int *directory; - -// -// load the patch names from pnames.lmp -// - names = W_CacheLumpName("PNAMES", PU_STATIC); - nummappatches = LONG(*((int *) names)); - name_p = names + 4; - patchlookup = Z_Malloc(nummappatches * sizeof(*patchlookup), PU_STATIC, NULL); - for (i = 0; i < nummappatches; i++) - { - M_StringCopy(name, name_p + i * 8, sizeof(name)); - patchlookup[i] = W_CheckNumForName(name); - } - W_ReleaseLumpName("PNAMES"); - -// -// load the map texture definitions from textures.lmp -// - maptex = maptex1 = W_CacheLumpName("TEXTURE1", PU_STATIC); - numtextures1 = LONG(*maptex); - maxoff = W_LumpLength(W_GetNumForName("TEXTURE1")); - directory = maptex + 1; - - if (W_CheckNumForName("TEXTURE2") != -1) - { - maptex2 = W_CacheLumpName("TEXTURE2", PU_STATIC); - numtextures2 = LONG(*maptex2); - maxoff2 = W_LumpLength(W_GetNumForName("TEXTURE2")); - } - else - { - maptex2 = NULL; - numtextures2 = 0; - maxoff2 = 0; - } - numtextures = numtextures1 + numtextures2; - - textures = Z_Malloc(numtextures * sizeof(texture_t *), PU_STATIC, 0); - texturecolumnlump = Z_Malloc(numtextures * sizeof(short *), PU_STATIC, 0); - texturecolumnofs = Z_Malloc(numtextures * sizeof(short *), PU_STATIC, 0); - texturecomposite = Z_Malloc(numtextures * sizeof(byte *), PU_STATIC, 0); - texturecompositesize = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); - texturewidthmask = Z_Malloc(numtextures * sizeof(int), PU_STATIC, 0); - textureheight = Z_Malloc(numtextures * sizeof(fixed_t), PU_STATIC, 0); - - for (i = 0; i < numtextures; i++, directory++) - { - if (i == numtextures1) - { // start looking in second texture file - maptex = maptex2; - maxoff = maxoff2; - directory = maptex + 1; - } - - offset = LONG(*directory); - if (offset > maxoff) - I_Error("R_InitTextures: bad texture directory"); - mtexture = (maptexture_t *) ((byte *) maptex + offset); - texture = textures[i] = Z_Malloc(sizeof(texture_t) - + - sizeof(texpatch_t) * - (SHORT(mtexture->patchcount) - 1), - PU_STATIC, 0); - texture->width = SHORT(mtexture->width); - texture->height = SHORT(mtexture->height); - texture->patchcount = SHORT(mtexture->patchcount); - memcpy(texture->name, mtexture->name, sizeof(texture->name)); - mpatch = &mtexture->patches[0]; - patch = &texture->patches[0]; - for (j = 0; j < texture->patchcount; j++, mpatch++, patch++) - { - patch->originx = SHORT(mpatch->originx); - patch->originy = SHORT(mpatch->originy); - patch->patch = patchlookup[SHORT(mpatch->patch)]; - if (patch->patch == -1) - I_Error("R_InitTextures: Missing patch in texture %s", - texture->name); - } - texturecolumnlump[i] = Z_Malloc(texture->width * sizeof(short), PU_STATIC, 0); - texturecolumnofs[i] = Z_Malloc(texture->width * sizeof(short), PU_STATIC, 0); - j = 1; - while (j * 2 <= texture->width) - j <<= 1; - texturewidthmask[i] = j - 1; - textureheight[i] = texture->height << FRACBITS; - } - - Z_Free(patchlookup); - - W_ReleaseLumpName("TEXTURE1"); - if (maptex2) - W_ReleaseLumpName("TEXTURE2"); - -// -// precalculate whatever possible -// - for (i = 0; i < numtextures; i++) - { - R_GenerateLookup(i); - if (!(i & 31)) - ST_Progress(); - } - -// -// translation table for global animation -// - texturetranslation = Z_Malloc((numtextures + 1) * sizeof(int), PU_STATIC, 0); - for (i = 0; i < numtextures; i++) - texturetranslation[i] = i; -} - - -/* -================ -= -= R_InitFlats -= -================= -*/ - -void R_InitFlats(void) -{ - int i; - - firstflat = W_GetNumForName("F_START") + 1; - lastflat = W_GetNumForName("F_END") - 1; - numflats = lastflat - firstflat + 1; - -// translation table for global animation - flattranslation = Z_Malloc((numflats + 1) * sizeof(int), PU_STATIC, 0); - for (i = 0; i < numflats; i++) - flattranslation[i] = i; -} - - -/* -================ -= -= R_InitSpriteLumps -= -= Finds the width and hoffset of all sprites in the wad, so the sprite doesn't -= need to be cached just for the header during rendering -================= -*/ - -void R_InitSpriteLumps(void) -{ - int i; - patch_t *patch; - - firstspritelump = W_GetNumForName("S_START") + 1; - lastspritelump = W_GetNumForName("S_END") - 1; - numspritelumps = lastspritelump - firstspritelump + 1; - spritewidth = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); - spriteoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); - spritetopoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0); - - for (i = 0; i < numspritelumps; i++) - { - if (!(i & 127)) - ST_Progress(); - patch = W_CacheLumpNum(firstspritelump + i, PU_CACHE); - spritewidth[i] = SHORT(patch->width) << FRACBITS; - spriteoffset[i] = SHORT(patch->leftoffset) << FRACBITS; - spritetopoffset[i] = SHORT(patch->topoffset) << FRACBITS; - } -} - - -/* -================ -= -= R_InitColormaps -= -================= -*/ - -void R_InitColormaps(void) -{ - int lump, length; -// -// load in the light tables -// 256 byte align tables -// - lump = W_GetNumForName("COLORMAP"); - length = W_LumpLength(lump); - colormaps = Z_Malloc(length, PU_STATIC, 0); - W_ReadLump(lump, colormaps); -} - - -/* -================ -= -= R_InitData -= -= Locates all the lumps that will be used by all views -= Must be called after W_Init -================= -*/ - -void R_InitData(void) -{ - R_InitTextures(); - R_InitFlats(); - R_InitSpriteLumps(); - R_InitColormaps(); -} - -//============================================================================= - -/* -================ -= -= R_FlatNumForName -= -================ -*/ - -int R_FlatNumForName(const char *name) -{ - int i; - char namet[9]; - - i = W_CheckNumForName(name); - if (i == -1) - { - namet[8] = 0; - memcpy(namet, name, 8); - I_Error("R_FlatNumForName: %s not found", namet); - } - return i - firstflat; -} - - -/* -================ -= -= R_CheckTextureNumForName -= -================ -*/ - -int R_CheckTextureNumForName(const char *name) -{ - int i; - - if (name[0] == '-') // no texture marker - return 0; - - for (i = 0; i < numtextures; i++) - if (!strncasecmp(textures[i]->name, name, 8)) - return i; - - return -1; -} - - -/* -================ -= -= R_TextureNumForName -= -================ -*/ - -int R_TextureNumForName(const char *name) -{ - int i; - //char namet[9]; - - i = R_CheckTextureNumForName(name); - if (i == -1) - I_Error("R_TextureNumForName: %s not found", name); - - return i; -} - - -/* -================= -= -= R_PrecacheLevel -= -= Preloads all relevent graphics for the level -================= -*/ - -int flatmemory, texturememory, spritememory; - -void R_PrecacheLevel(void) -{ - char *flatpresent; - char *texturepresent; - char *spritepresent; - int i, j, k, lump; - texture_t *texture; - thinker_t *th; - spriteframe_t *sf; - - if (demoplayback) - return; - -// -// precache flats -// - flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); - memset(flatpresent, 0, numflats); - for (i = 0; i < numsectors; i++) - { - flatpresent[sectors[i].floorpic] = 1; - flatpresent[sectors[i].ceilingpic] = 1; - } - - flatmemory = 0; - for (i = 0; i < numflats; i++) - if (flatpresent[i]) - { - lump = firstflat + i; - flatmemory += lumpinfo[lump]->size; - W_CacheLumpNum(lump, PU_CACHE); - } - - Z_Free(flatpresent); - -// -// precache textures -// - texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); - memset(texturepresent, 0, numtextures); - - for (i = 0; i < numsides; i++) - { - texturepresent[sides[i].toptexture] = 1; - texturepresent[sides[i].midtexture] = 1; - texturepresent[sides[i].bottomtexture] = 1; - } - - texturepresent[Sky1Texture] = 1; - texturepresent[Sky2Texture] = 1; - - texturememory = 0; - for (i = 0; i < numtextures; i++) - { - if (!texturepresent[i]) - continue; - texture = textures[i]; - for (j = 0; j < texture->patchcount; j++) - { - lump = texture->patches[j].patch; - texturememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump, PU_CACHE); - } - } - - Z_Free(texturepresent); - -// -// precache sprites -// - spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); - memset(spritepresent, 0, numsprites); - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function == P_MobjThinker) - spritepresent[((mobj_t *) th)->sprite] = 1; - } - - spritememory = 0; - for (i = 0; i < numsprites; i++) - { - if (!spritepresent[i]) - continue; - for (j = 0; j < sprites[i].numframes; j++) - { - sf = &sprites[i].spriteframes[j]; - for (k = 0; k < 8; k++) - { - lump = firstspritelump + sf->lump[k]; - spritememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump, PU_CACHE); - } - } - } - - Z_Free(spritepresent); -} diff --git a/games/NXDoom/src/hexen/r_draw.c b/games/NXDoom/src/hexen/r_draw.c deleted file mode 100644 index 13a0421b498..00000000000 --- a/games/NXDoom/src/hexen/r_draw.c +++ /dev/null @@ -1,558 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "i_video.h" -#include "r_local.h" -#include "v_video.h" - -/* - -All drawing to the view buffer is accomplished in this file. The other refresh -files only know about ccordinates, not the architecture of the frame buffer. - -*/ - -byte *viewimage; -int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; -byte *ylookup[MAXHEIGHT]; -int columnofs[MAXWIDTH]; -//byte translations[3][256]; // color tables for different players - -/* -================== -= -= R_DrawColumn -= -= Source is the top of the column to scale -= -================== -*/ - -lighttable_t *dc_colormap; -int dc_x; -int dc_yl; -int dc_yh; -fixed_t dc_iscale; -fixed_t dc_texturemid; -byte *dc_source; // first pixel in a column (possibly virtual) - -int dccount; // just for profiling - -void R_DrawColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -void R_DrawColumnLow(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -// dccount++; -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -void R_DrawTLColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - if (!dc_yl) - dc_yl = 1; - if (dc_yh == viewheight - 1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = tinttable[*dest + - (dc_colormap[dc_source[(frac >> FRACBITS) & 127]] << - 8)]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -//============================================================================ -// -// R_DrawAltTLColumn -// -//============================================================================ - -void R_DrawAltTLColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - if (!dc_yl) - dc_yl = 1; - if (dc_yh == viewheight - 1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawAltTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = tinttable[((*dest) << 8) - + dc_colormap[dc_source[(frac >> FRACBITS) & 127]]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -/* -======================== -= -= R_DrawTranslatedColumn -= -======================== -*/ - -byte *dc_translation; -byte *translationtables; - -void R_DrawTranslatedColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -//============================================================================ -// -// R_DrawTranslatedTLColumn -// -//============================================================================ - -void R_DrawTranslatedTLColumn(void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery) * fracstep; - - do - { - *dest = tinttable[((*dest) << 8) - + - dc_colormap[dc_translation - [dc_source[frac >> FRACBITS]]]]; - dest += SCREENWIDTH; - frac += fracstep; - } - while (count--); -} - -//============================================================================ -// -// R_DrawTranslatedAltTLColumn -// -//============================================================================ - -/* -void R_DrawTranslatedAltTLColumn (void) -{ - int count; - byte *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - do - { - *dest = tinttable[*dest - +(dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8)]; - dest += SCREENWIDTH; - frac += fracstep; - } while (count--); -} -*/ - -//-------------------------------------------------------------------------- -// -// PROC R_InitTranslationTables -// -//-------------------------------------------------------------------------- - -void R_InitTranslationTables(void) -{ - int i; - byte *transLump; - int lumpnum; - - V_LoadTintTable(); - - // Allocate translation tables - translationtables = Z_Malloc(256 * 3 * (maxplayers - 1), PU_STATIC, 0); - - for (i = 0; i < 3 * (maxplayers - 1); i++) - { - lumpnum = W_GetNumForName("trantbl0") + i; - transLump = W_CacheLumpNum(lumpnum, PU_STATIC); - memcpy(translationtables + i * 256, transLump, 256); - W_ReleaseLumpNum(lumpnum); - } -} - -/* -================ -= -= R_DrawSpan -= -================ -*/ - -int ds_y; -int ds_x1; -int ds_x2; -lighttable_t *ds_colormap; -fixed_t ds_xfrac; -fixed_t ds_yfrac; -fixed_t ds_xstep; -fixed_t ds_ystep; -byte *ds_source; // start of a 64*64 tile image - -int dscount; // just for profiling - -void R_DrawSpan(void) -{ - fixed_t xfrac, yfrac; - byte *dest; - int count, spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH - || (unsigned) ds_y > SCREENHEIGHT) - I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); -// dscount++; -#endif - - xfrac = ds_xfrac; - yfrac = ds_yfrac; - - dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1; - do - { - spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); - *dest++ = ds_colormap[ds_source[spot]]; - xfrac += ds_xstep; - yfrac += ds_ystep; - } - while (count--); -} - -void R_DrawSpanLow(void) -{ - fixed_t xfrac, yfrac; - byte *dest; - int count, spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH - || (unsigned) ds_y > SCREENHEIGHT) - I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); -// dscount++; -#endif - - xfrac = ds_xfrac; - yfrac = ds_yfrac; - - dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1; - do - { - spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63); - *dest++ = ds_colormap[ds_source[spot]]; - xfrac += ds_xstep; - yfrac += ds_ystep; - } - while (count--); -} - - - -/* -================ -= -= R_InitBuffer -= -================= -*/ - -void R_InitBuffer(int width, int height) -{ - int i; - - viewwindowx = (SCREENWIDTH - width) >> 1; - for (i = 0; i < width; i++) - columnofs[i] = viewwindowx + i; - if (width == SCREENWIDTH) - viewwindowy = 0; - else - viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1; - for (i = 0; i < height; i++) - ylookup[i] = I_VideoBuffer + (i + viewwindowy) * SCREENWIDTH; -} - - -/* -================== -= -= R_DrawViewBorder -= -= Draws the border around the view for different size windows -================== -*/ - -boolean BorderNeedRefresh; - -void R_DrawViewBorder(void) -{ - byte *src, *dest; - int x, y; - - if (scaledviewwidth == SCREENWIDTH) - return; - - src = W_CacheLumpName("F_022", PU_CACHE); - dest = I_VideoBuffer; - - for (y = 0; y < SCREENHEIGHT - SBARHEIGHT; y++) - { - for (x = 0; x < SCREENWIDTH / 64; x++) - { - memcpy(dest, src + ((y & 63) << 6), 64); - dest += 64; - } - if (SCREENWIDTH & 63) - { - memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); - dest += (SCREENWIDTH & 63); - } - } - for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) - { - V_DrawPatch(x, viewwindowy - 4, W_CacheLumpName("bordt", PU_CACHE)); - V_DrawPatch(x, viewwindowy + viewheight, W_CacheLumpName("bordb", - PU_CACHE)); - } - for (y = viewwindowy; y < viewwindowy + viewheight; y += 16) - { - V_DrawPatch(viewwindowx - 4, y, W_CacheLumpName("bordl", PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, y, W_CacheLumpName("bordr", - PU_CACHE)); - } - V_DrawPatch(viewwindowx - 4, viewwindowy - 4, W_CacheLumpName("bordtl", - PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, - W_CacheLumpName("bordtr", PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy + viewheight, - W_CacheLumpName("bordbr", PU_CACHE)); - V_DrawPatch(viewwindowx - 4, viewwindowy + viewheight, - W_CacheLumpName("bordbl", PU_CACHE)); -} - -/* -================== -= -= R_DrawTopBorder -= -= Draws the top border around the view for different size windows -================== -*/ - -boolean BorderTopRefresh; - -void R_DrawTopBorder(void) -{ - byte *src, *dest; - int x, y; - - if (scaledviewwidth == SCREENWIDTH) - return; - -/* if(gamemode == shareware) - { - src = W_CacheLumpName ("FLOOR04", PU_CACHE); - } - else - { - src = W_CacheLumpName ("FLAT513", PU_CACHE); - } -*/ - src = W_CacheLumpName("F_022", PU_CACHE); - dest = I_VideoBuffer; - - for (y = 0; y < 34; y++) - { - for (x = 0; x < SCREENWIDTH / 64; x++) - { - memcpy(dest, src + ((y & 63) << 6), 64); - dest += 64; - } - if (SCREENWIDTH & 63) - { - memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); - dest += (SCREENWIDTH & 63); - } - } - if (viewwindowy < 35) - { - for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16) - { - V_DrawPatch(x, viewwindowy - 4, - W_CacheLumpName("bordt", PU_CACHE)); - } - V_DrawPatch(viewwindowx - 4, viewwindowy, W_CacheLumpName("bordl", - PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy, - W_CacheLumpName("bordr", PU_CACHE)); - V_DrawPatch(viewwindowx - 4, viewwindowy + 16, - W_CacheLumpName("bordl", PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy + 16, - W_CacheLumpName("bordr", PU_CACHE)); - - V_DrawPatch(viewwindowx - 4, viewwindowy - 4, - W_CacheLumpName("bordtl", PU_CACHE)); - V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4, - W_CacheLumpName("bordtr", PU_CACHE)); - } -} diff --git a/games/NXDoom/src/hexen/r_local.h b/games/NXDoom/src/hexen/r_local.h deleted file mode 100644 index e9cb26ce03d..00000000000 --- a/games/NXDoom/src/hexen/r_local.h +++ /dev/null @@ -1,554 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __R_LOCAL__ -#define __R_LOCAL__ - -#include "i_video.h" - -#define ANGLETOSKYSHIFT 22 // sky map is 256*128*4 maps - -#define BASEYCENTER 100 - -#define MAXWIDTH 1120 -#define MAXHEIGHT 832 - -#define PI 3.141592657 - -#define CENTERY (SCREENHEIGHT/2) - -#define MINZ (FRACUNIT*4) - -#define FIELDOFVIEW 2048 // fineangles in the SCREENWIDTH wide window - -// -// lighting constants -// -#define LIGHTLEVELS 16 -#define LIGHTSEGSHIFT 4 -#define MAXLIGHTSCALE 48 -#define LIGHTSCALESHIFT 12 -#define MAXLIGHTZ 128 -#define LIGHTZSHIFT 20 -#define NUMCOLORMAPS 32 // number of diminishing -#define INVERSECOLORMAP 32 - -/* -============================================================================== - - INTERNAL MAP TYPES - -============================================================================== -*/ - -//================ used by play and refresh - -typedef struct -{ - fixed_t x, y; -} vertex_t; - -struct line_s; - -typedef struct -{ - fixed_t floorheight, ceilingheight; - short floorpic, ceilingpic; - short lightlevel; - short special, tag; - - int soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 - mobj_t *soundtarget; // thing that made a sound (or null) - seqtype_t seqType; // stone, metal, heavy, etc... - - int blockbox[4]; // mapblock bounding box for height changes - degenmobj_t soundorg; // for any sounds played by the sector - int validcount; // if == validcount, already checked - mobj_t *thinglist; // list of mobjs in sector - void *specialdata; // thinker_t for reversable actions - int linecount; - struct line_s **lines; // [linecount] size -} sector_t; - -typedef struct -{ - fixed_t textureoffset; // add this to the calculated texture col - fixed_t rowoffset; // add this to the calculated texture top - short toptexture, bottomtexture, midtexture; - sector_t *sector; -} side_t; - -typedef enum -{ - ST_HORIZONTAL, - ST_VERTICAL, - ST_POSITIVE, - ST_NEGATIVE -} slopetype_t; - -/* -typedef struct line_s -{ - vertex_t *v1, *v2; - fixed_t dx,dy; // v2 - v1 for side checking - short flags; - short special, tag; - short sidenum[2]; // sidenum[1] will be -1 if one sided - fixed_t bbox[4]; - slopetype_t slopetype; // to aid move clipping - sector_t *frontsector, *backsector; - int validcount; // if == validcount, already checked - void *specialdata; // thinker_t for reversable actions -} line_t; -*/ - -typedef struct line_s -{ - vertex_t *v1; - vertex_t *v2; - fixed_t dx; - fixed_t dy; - short flags; - byte special; - byte arg1; - byte arg2; - byte arg3; - byte arg4; - byte arg5; - short sidenum[2]; - fixed_t bbox[4]; - slopetype_t slopetype; - sector_t *frontsector; - sector_t *backsector; - int validcount; - void *specialdata; -} line_t; - -typedef struct -{ - vertex_t *v1, *v2; - fixed_t offset; - angle_t angle; - side_t *sidedef; - line_t *linedef; - sector_t *frontsector; - sector_t *backsector; // NULL for one sided lines -} seg_t; - -// ===== Polyobj data ===== -typedef struct -{ - int numsegs; - seg_t **segs; - degenmobj_t startSpot; - vertex_t *originalPts; // used as the base for the rotations - vertex_t *prevPts; // use to restore the old point values - angle_t angle; - int tag; // reference tag assigned in HereticEd - int bbox[4]; - int validcount; - boolean crush; // should the polyobj attempt to crush mobjs? - int seqType; - fixed_t size; // polyobj size (area of POLY_AREAUNIT == size of FRACUNIT) - void *specialdata; // pointer a thinker, if the poly is moving -} polyobj_t; - -typedef struct polyblock_s -{ - polyobj_t *polyobj; - struct polyblock_s *prev; - struct polyblock_s *next; -} polyblock_t; - -typedef struct subsector_s -{ - sector_t *sector; - short numlines; - short firstline; - polyobj_t *poly; -} subsector_t; - -typedef struct -{ - fixed_t x, y, dx, dy; // partition line - fixed_t bbox[2][4]; // bounding box for each child - unsigned short children[2]; // if NF_SUBSECTOR its a subsector -} node_t; - - -/* -============================================================================== - - OTHER TYPES - -============================================================================== -*/ - -typedef byte lighttable_t; // this could be wider for >8 bit display - -#define MAXVISPLANES 160 -#define MAXOPENINGS SCREENWIDTH*64 - -typedef struct -{ - fixed_t height; - int picnum; - int lightlevel; - int special; - int minx, maxx; - byte pad1; // leave pads for [minx-1]/[maxx+1] - byte top[SCREENWIDTH]; - byte pad2; - byte pad3; - byte bottom[SCREENWIDTH]; - byte pad4; -} visplane_t; - -typedef struct drawseg_s -{ - seg_t *curline; - int x1, x2; - fixed_t scale1, scale2, scalestep; - int silhouette; // 0=none, 1=bottom, 2=top, 3=both - fixed_t bsilheight; // don't clip sprites above this - fixed_t tsilheight; // don't clip sprites below this -// pointers to lists for sprite clipping - short *sprtopclip; // adjusted so [x1] is first value - short *sprbottomclip; // adjusted so [x1] is first value - short *maskedtexturecol; // adjusted so [x1] is first value -} drawseg_t; - -#define SIL_NONE 0 -#define SIL_BOTTOM 1 -#define SIL_TOP 2 -#define SIL_BOTH 3 - -#define MAXDRAWSEGS 256 - -// A vissprite_t is a thing that will be drawn during a refresh -typedef struct vissprite_s -{ - struct vissprite_s *prev, *next; - int x1, x2; - fixed_t gx, gy; // for line side calculation - fixed_t gz, gzt; // global bottom / top for silhouette clipping - fixed_t startfrac; // horizontal position of x1 - fixed_t scale; - fixed_t xiscale; // negative if flipped - fixed_t texturemid; - int patch; - lighttable_t *colormap; - int mobjflags; // for color translation and shadow draw - boolean psprite; // true if psprite - int class; // player class (used in translation) - fixed_t floorclip; -} vissprite_t; - - -extern visplane_t *floorplane, *ceilingplane; - -// Sprites are patches with a special naming convention so they can be -// recognized by R_InitSprites. The sprite and frame specified by a -// thing_t is range checked at run time. -// a sprite is a patch_t that is assumed to represent a three dimensional -// object and may have multiple rotations pre drawn. Horizontal flipping -// is used to save space. Some sprites will only have one picture used -// for all views. - -typedef struct -{ - boolean rotate; // if false use 0 for any position - short lump[8]; // lump to use for view angles 0-7 - byte flip[8]; // flip (1 = flip) to use for view angles 0-7 -} spriteframe_t; - -typedef struct -{ - int numframes; - spriteframe_t *spriteframes; -} spritedef_t; - -extern spritedef_t *sprites; -extern int numsprites; - -//============================================================================= - -extern int numvertexes; -extern vertex_t *vertexes; - -extern int numsegs; -extern seg_t *segs; - -extern int numsectors; -extern sector_t *sectors; - -extern int numsubsectors; -extern subsector_t *subsectors; - -extern int numnodes; -extern node_t *nodes; - -extern int numlines; -extern line_t *lines; - -extern int numsides; -extern side_t *sides; - - - -extern fixed_t viewx, viewy, viewz; -extern angle_t viewangle; -extern player_t *viewplayer; - - -extern angle_t clipangle; - -extern int viewangletox[FINEANGLES / 2]; -extern angle_t xtoviewangle[SCREENWIDTH + 1]; - -extern fixed_t rw_distance; -extern angle_t rw_normalangle; - -// -// R_main.c -// -extern int screenblocks; -extern int viewwidth, viewheight, viewwindowx, viewwindowy; -extern int scaledviewwidth; -extern int centerx, centery; -extern int flyheight; -extern fixed_t centerxfrac; -extern fixed_t centeryfrac; -extern fixed_t projection; - -extern int validcount; - -extern int sscount, linecount, loopcount; -extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; -extern lighttable_t *scalelightfixed[MAXLIGHTSCALE]; -extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; - -extern int extralight; -extern lighttable_t *fixedcolormap; - -extern fixed_t viewcos, viewsin; - -extern int detailshift; // 0 = high, 1 = low - -extern void (*colfunc) (void); -extern void (*basecolfunc) (void); -extern void (*tlcolfunc) (void); -extern void (*spanfunc) (void); - -int R_PointOnSide(fixed_t x, fixed_t y, node_t * node); -int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line); -angle_t R_PointToAngle(fixed_t x, fixed_t y); -angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); -fixed_t R_PointToDist(fixed_t x, fixed_t y); -fixed_t R_ScaleFromGlobalAngle(angle_t visangle); -subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); -//void R_AddPointToBox (int x, int y, fixed_t *box); - - -// -// R_bsp.c -// -extern seg_t *curline; -extern side_t *sidedef; -extern line_t *linedef; -extern sector_t *frontsector, *backsector; - -extern int rw_x; -extern int rw_stopx; - -extern boolean segtextured; -extern boolean markfloor; // false if the back side is the same plane -extern boolean markceiling; -extern boolean skymap; - -extern drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; - -extern lighttable_t **hscalelight, **vscalelight, **dscalelight; - -typedef void (*drawfunc_t) (int start, int stop); -void R_ClearClipSegs(void); - -void R_ClearDrawSegs(void); -void R_InitSkyMap(void); -void R_RenderBSPNode(int bspnum); - -// -// R_segs.c -// -extern int rw_angle1; // angle to line origin -extern int TransTextureStart; -extern int TransTextureEnd; -extern lighttable_t **walllights; - - -void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2); - -// -// R_plane.c -// -typedef void (*planefunction_t) (int top, int bottom); -extern planefunction_t floorfunc, ceilingfunc; - -extern fixed_t Sky1ColumnOffset; -extern fixed_t Sky2ColumnOffset; -extern int skyflatnum; -extern boolean DoubleSky; - -extern short openings[MAXOPENINGS], *lastopening; - -extern short floorclip[SCREENWIDTH]; -extern short ceilingclip[SCREENWIDTH]; - -extern fixed_t yslope[SCREENHEIGHT]; -extern fixed_t distscale[SCREENWIDTH]; - -void R_InitPlanes(void); -void R_ClearPlanes(void); -void R_MapPlane(int y, int x1, int x2); -void R_MakeSpans(int x, int t1, int b1, int t2, int b2); -void R_DrawPlanes(void); - -visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel, - int special); -visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop); - -void R_InitSky(int map); - - -// -// R_debug.m -// -extern int drawbsp; - -void RD_OpenMapWindow(void); -void RD_ClearMapWindow(void); -void RD_DisplayLine(int x1, int y1, int x2, int y2, float gray); -void RD_DrawNodeLine(node_t * node); -void RD_DrawLineCheck(seg_t * line); -void RD_DrawLine(seg_t * line); -void RD_DrawBBox(fixed_t * bbox); - - -// -// R_data.c -// -extern fixed_t *textureheight; // needed for texture pegging -extern fixed_t *spritewidth; // needed for pre rendering (fracs) -extern fixed_t *spriteoffset; -extern fixed_t *spritetopoffset; -extern lighttable_t *colormaps; -extern int firstflat; -extern int numflats; - -extern int *flattranslation; // for global animation -extern int *texturetranslation; // for global animation - -extern int firstspritelump, lastspritelump, numspritelumps; -extern boolean LevelUseFullBright; - -byte *R_GetColumn(int tex, int col); -void R_InitData(void); -void R_PrecacheLevel(void); - - -// -// R_things.c -// -#define MAXVISSPRITES 192 - -extern vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; -extern vissprite_t vsprsortedhead; - -// constant arrays used for psprite clipping and initializing clipping -extern short negonearray[SCREENWIDTH]; -extern short screenheightarray[SCREENWIDTH]; - -// vars for R_DrawMaskedColumn -extern short *mfloorclip; -extern short *mceilingclip; -extern fixed_t spryscale; -extern fixed_t sprtopscreen; -extern fixed_t sprbotscreen; - -extern fixed_t pspritescale, pspriteiscale; - - -void R_DrawMaskedColumn(column_t * column, signed int baseclip); - - -void R_SortVisSprites(void); - -void R_AddSprites(sector_t * sec); -void R_AddPSprites(void); -void R_DrawSprites(void); -void R_InitSprites(const char **namelist); -void R_ClearSprites(void); -void R_DrawMasked(void); -void R_ClipVisSprite(vissprite_t * vis, int xl, int xh); - -//============================================================================= -// -// R_draw.c -// -//============================================================================= - -extern lighttable_t *dc_colormap; -extern int dc_x; -extern int dc_yl; -extern int dc_yh; -extern fixed_t dc_iscale; -extern fixed_t dc_texturemid; -extern byte *dc_source; // first pixel in a column -extern byte *ylookup[MAXHEIGHT]; -extern int columnofs[MAXWIDTH]; - - -void R_DrawColumn(void); -void R_DrawColumnLow(void); -void R_DrawTLColumn(void); -void R_DrawTLColumnLow(void); -void R_DrawTranslatedColumn(void); -void R_DrawTranslatedTLColumn(void); -void R_DrawTranslatedColumnLow(void); -void R_DrawAltTLColumn(void); -//void R_DrawTranslatedAltTLColumn(void); - -extern int ds_y; -extern int ds_x1; -extern int ds_x2; -extern lighttable_t *ds_colormap; -extern fixed_t ds_xfrac; -extern fixed_t ds_yfrac; -extern fixed_t ds_xstep; -extern fixed_t ds_ystep; -extern byte *ds_source; // start of a 64*64 tile image - -extern byte *translationtables; -extern byte *dc_translation; - -void R_DrawSpan(void); -void R_DrawSpanLow(void); - -void R_InitBuffer(int width, int height); -void R_InitTranslationTables(void); - -#endif // __R_LOCAL__ diff --git a/games/NXDoom/src/hexen/r_main.c b/games/NXDoom/src/hexen/r_main.c deleted file mode 100644 index 3bbb4fce2f5..00000000000 --- a/games/NXDoom/src/hexen/r_main.c +++ /dev/null @@ -1,830 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include -#include "m_random.h" -#include "h2def.h" -#include "m_bbox.h" -#include "r_local.h" - -int viewangleoffset; - -// haleyjd: removed WATCOMC - -int validcount = 1; // increment every time a check is made - -lighttable_t *fixedcolormap; - -int centerx, centery; -fixed_t centerxfrac, centeryfrac; -fixed_t projection; - -int framecount; // just for profiling purposes - -int sscount, linecount, loopcount; - -fixed_t viewx, viewy, viewz; -angle_t viewangle; -fixed_t viewcos, viewsin; -player_t *viewplayer; - -int detailshift; // 0 = high, 1 = low - -// -// precalculated math tables -// -angle_t clipangle; - -// The viewangletox[viewangle + FINEANGLES/4] lookup maps the visible view -// angles to screen X coordinates, flattening the arc to a flat projection -// plane. There will be many angles mapped to the same X. -int viewangletox[FINEANGLES / 2]; - -// The xtoviewangleangle[] table maps a screen pixel to the lowest viewangle -// that maps back to x ranges from clipangle to -clipangle -angle_t xtoviewangle[SCREENWIDTH + 1]; - -lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; -lighttable_t *scalelightfixed[MAXLIGHTSCALE]; -lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; - -int extralight; // bumped light from gun blasts - -void (*colfunc) (void); -void (*basecolfunc) (void); -void (*tlcolfunc) (void); -void (*transcolfunc) (void); -void (*spanfunc) (void); - -/* -=================== -= -= R_AddPointToBox -= -=================== -*/ - -/* -void R_AddPointToBox (int x, int y, fixed_t *box) -{ - if (x< box[BOXLEFT]) - box[BOXLEFT] = x; - if (x> box[BOXRIGHT]) - box[BOXRIGHT] = x; - if (y< box[BOXBOTTOM]) - box[BOXBOTTOM] = y; - if (y> box[BOXTOP]) - box[BOXTOP] = y; -} -*/ - - -/* -=============================================================================== -= -= R_PointOnSide -= -= Returns side 0 (front) or 1 (back) -=============================================================================== -*/ - -int R_PointOnSide(fixed_t x, fixed_t y, node_t * node) -{ - fixed_t dx, dy; - fixed_t left, right; - - if (!node->dx) - { - if (x <= node->x) - return node->dy > 0; - return node->dy < 0; - } - if (!node->dy) - { - if (y <= node->y) - return node->dx < 0; - return node->dx > 0; - } - - dx = (x - node->x); - dy = (y - node->y); - -// try to quickly decide by looking at sign bits - if ((node->dy ^ node->dx ^ dx ^ dy) & 0x80000000) - { - if ((node->dy ^ dx) & 0x80000000) - return 1; // (left is negative) - return 0; - } - - left = FixedMul(node->dy >> FRACBITS, dx); - right = FixedMul(dy, node->dx >> FRACBITS); - - if (right < left) - return 0; // front side - return 1; // back side -} - - -int R_PointOnSegSide(fixed_t x, fixed_t y, seg_t * line) -{ - fixed_t lx, ly; - fixed_t ldx, ldy; - fixed_t dx, dy; - fixed_t left, right; - - lx = line->v1->x; - ly = line->v1->y; - - ldx = line->v2->x - lx; - ldy = line->v2->y - ly; - - if (!ldx) - { - if (x <= lx) - return ldy > 0; - return ldy < 0; - } - if (!ldy) - { - if (y <= ly) - return ldx < 0; - return ldx > 0; - } - - dx = (x - lx); - dy = (y - ly); - -// try to quickly decide by looking at sign bits - if ((ldy ^ ldx ^ dx ^ dy) & 0x80000000) - { - if ((ldy ^ dx) & 0x80000000) - return 1; // (left is negative) - return 0; - } - - left = FixedMul(ldy >> FRACBITS, dx); - right = FixedMul(dy, ldx >> FRACBITS); - - if (right < left) - return 0; // front side - return 1; // back side -} - - -/* -=============================================================================== -= -= R_PointToAngle -= -=============================================================================== -*/ - -#define DBITS (FRACBITS-SLOPEBITS) - -angle_t R_PointToAngle(fixed_t x, fixed_t y) -{ - x -= viewx; - y -= viewy; - if ((!x) && (!y)) - return 0; - if (x >= 0) - { // x >=0 - if (y >= 0) - { // y>= 0 - if (x > y) - return tantoangle[SlopeDiv(y, x)]; // octant 0 - else - return ANG90 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 1 - } - else - { // y<0 - y = -y; - if (x > y) - return -tantoangle[SlopeDiv(y, x)]; // octant 8 - else - return ANG270 + tantoangle[SlopeDiv(x, y)]; // octant 7 - } - } - else - { // x<0 - x = -x; - if (y >= 0) - { // y>= 0 - if (x > y) - return ANG180 - 1 - tantoangle[SlopeDiv(y, x)]; // octant 3 - else - return ANG90 + tantoangle[SlopeDiv(x, y)]; // octant 2 - } - else - { // y<0 - y = -y; - if (x > y) - return ANG180 + tantoangle[SlopeDiv(y, x)]; // octant 4 - else - return ANG270 - 1 - tantoangle[SlopeDiv(x, y)]; // octant 5 - } - } - - return 0; -} - - -angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) -{ - viewx = x1; - viewy = y1; - return R_PointToAngle(x2, y2); -} - - -fixed_t R_PointToDist(fixed_t x, fixed_t y) -{ - int angle; - fixed_t dx, dy, temp; - fixed_t dist; - - dx = abs(x - viewx); - dy = abs(y - viewy); - - if (dy > dx) - { - temp = dx; - dx = dy; - dy = temp; - } - - angle = - (tantoangle[FixedDiv(dy, dx) >> DBITS] + ANG90) >> ANGLETOFINESHIFT; - - dist = FixedDiv(dx, finesine[angle]); // use as cosine - - return dist; -} - - - -/* -================= -= -= R_InitPointToAngle -= -================= -*/ - -void R_InitPointToAngle(void) -{ -// now getting from tables.c -#if 0 - int i; - long t; - float f; -// -// slope (tangent) to angle lookup -// - for (i = 0; i <= SLOPERANGE; i++) - { - f = atan((float) i / SLOPERANGE) / (3.141592657 * 2); - t = 0xffffffff * f; - tantoangle[i] = t; - } -#endif -} - -//============================================================================= - -/* -================ -= -= R_ScaleFromGlobalAngle -= -= Returns the texture mapping scale for the current line at the given angle -= rw_distance must be calculated first -================ -*/ - -fixed_t R_ScaleFromGlobalAngle(angle_t visangle) -{ - fixed_t scale; - int anglea, angleb; - int sinea, sineb; - fixed_t num, den; - -#if 0 - { - fixed_t dist, z; - fixed_t sinv, cosv; - - sinv = finesine[(visangle - rw_normalangle) >> ANGLETOFINESHIFT]; - dist = FixedDiv(rw_distance, sinv); - cosv = finecosine[(viewangle - visangle) >> ANGLETOFINESHIFT]; - z = abs(FixedMul(dist, cosv)); - scale = FixedDiv(projection, z); - return scale; - } -#endif - - anglea = ANG90 + (visangle - viewangle); - angleb = ANG90 + (visangle - rw_normalangle); -// bothe sines are allways positive - sinea = finesine[anglea >> ANGLETOFINESHIFT]; - sineb = finesine[angleb >> ANGLETOFINESHIFT]; - num = FixedMul(projection, sineb) << detailshift; - den = FixedMul(rw_distance, sinea); - if (den > num >> 16) - { - scale = FixedDiv(num, den); - if (scale > 64 * FRACUNIT) - scale = 64 * FRACUNIT; - else if (scale < 256) - scale = 256; - } - else - scale = 64 * FRACUNIT; - - return scale; -} - - - -/* -================= -= -= R_InitTables -= -================= -*/ - -void R_InitTables(void) -{ -// now getting from tables.c -#if 0 - int i; - float a, fv; - int t; - -// -// viewangle tangent table -// - for (i = 0; i < FINEANGLES / 2; i++) - { - a = (i - FINEANGLES / 4 + 0.5) * PI * 2 / FINEANGLES; - fv = FRACUNIT * tan(a); - t = fv; - finetangent[i] = t; - } - -// -// finesine table -// - for (i = 0; i < 5 * FINEANGLES / 4; i++) - { -// OPTIMIZE: mirror... - a = (i + 0.5) * PI * 2 / FINEANGLES; - t = FRACUNIT * sin(a); - finesine[i] = t; - } -#endif - -} - - -/* -================= -= -= R_InitTextureMapping -= -================= -*/ - -void R_InitTextureMapping(void) -{ - int i; - int x; - int t; - fixed_t focallength; - - -// -// use tangent table to generate viewangletox -// viewangletox will give the next greatest x after the view angle -// - // calc focallength so FIELDOFVIEW angles covers SCREENWIDTH - focallength = - FixedDiv(centerxfrac, finetangent[FINEANGLES / 4 + FIELDOFVIEW / 2]); - - for (i = 0; i < FINEANGLES / 2; i++) - { - if (finetangent[i] > FRACUNIT * 2) - t = -1; - else if (finetangent[i] < -FRACUNIT * 2) - t = viewwidth + 1; - else - { - t = FixedMul(finetangent[i], focallength); - t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS; - if (t < -1) - t = -1; - else if (t > viewwidth + 1) - t = viewwidth + 1; - } - viewangletox[i] = t; - } - -// -// scan viewangletox[] to generate xtoviewangleangle[] -// -// xtoviewangle will give the smallest view angle that maps to x - for (x = 0; x <= viewwidth; x++) - { - i = 0; - while (viewangletox[i] > x) - i++; - xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90; - } - -// -// take out the fencepost cases from viewangletox -// - for (i = 0; i < FINEANGLES / 2; i++) - { - t = FixedMul(finetangent[i], focallength); - t = centerx - t; - if (viewangletox[i] == -1) - viewangletox[i] = 0; - else if (viewangletox[i] == viewwidth + 1) - viewangletox[i] = viewwidth; - } - - clipangle = xtoviewangle[0]; -} - -//============================================================================= - -/* -==================== -= -= R_InitLightTables -= -= Only inits the zlight table, because the scalelight table changes -= with view size -= -==================== -*/ - -#define DISTMAP 2 - -void R_InitLightTables(void) -{ - int i, j, level, startmap; - int scale; - -// -// Calculate the light levels to use for each level / distance combination -// - for (i = 0; i < LIGHTLEVELS; i++) - { - startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; - for (j = 0; j < MAXLIGHTZ; j++) - { - scale = - FixedDiv((SCREENWIDTH / 2 * FRACUNIT), - (j + 1) << LIGHTZSHIFT); - scale >>= LIGHTSCALESHIFT; - level = startmap - scale / DISTMAP; - if (level < 0) - level = 0; - if (level >= NUMCOLORMAPS) - level = NUMCOLORMAPS - 1; - zlight[i][j] = colormaps + level * 256; - } - } -} - - -/* -============== -= -= R_SetViewSize -= -= Don't really change anything here, because i might be in the middle of -= a refresh. The change will take effect next refresh. -= -============== -*/ - -boolean setsizeneeded; -int setblocks, setdetail; - -void R_SetViewSize(int blocks, int detail) -{ - setsizeneeded = true; - setblocks = blocks; - setdetail = detail; -} - -/* -============== -= -= R_ExecuteSetViewSize -= -============== -*/ - -void R_ExecuteSetViewSize(void) -{ - fixed_t cosadj, dy; - int i, j, level, startmap; - - setsizeneeded = false; - - if (setblocks == 11) - { - scaledviewwidth = SCREENWIDTH; - viewheight = SCREENHEIGHT; - } - else - { - scaledviewwidth = setblocks * 32; - viewheight = (setblocks * 161 / 10); - } - - detailshift = setdetail; - viewwidth = scaledviewwidth >> detailshift; - - centery = viewheight / 2; - centerx = viewwidth / 2; - centerxfrac = centerx << FRACBITS; - centeryfrac = centery << FRACBITS; - projection = centerxfrac; - - if (!detailshift) - { - colfunc = basecolfunc = R_DrawColumn; - tlcolfunc = R_DrawTLColumn; - transcolfunc = R_DrawTranslatedColumn; - spanfunc = R_DrawSpan; - } - else - { - colfunc = basecolfunc = R_DrawColumnLow; - tlcolfunc = R_DrawTLColumn; - transcolfunc = R_DrawTranslatedColumn; - spanfunc = R_DrawSpanLow; - } - - R_InitBuffer(scaledviewwidth, viewheight); - - R_InitTextureMapping(); - -// -// psprite scales -// - pspritescale = FRACUNIT * viewwidth / SCREENWIDTH; - pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth; - -// -// thing clipping -// - for (i = 0; i < viewwidth; i++) - screenheightarray[i] = viewheight; - -// -// planes -// - for (i = 0; i < viewheight; i++) - { - dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; - dy = abs(dy); - yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, dy); - } - - for (i = 0; i < viewwidth; i++) - { - cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); - distscale[i] = FixedDiv(FRACUNIT, cosadj); - } - -// -// Calculate the light levels to use for each level / scale combination -// - for (i = 0; i < LIGHTLEVELS; i++) - { - startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS; - for (j = 0; j < MAXLIGHTSCALE; j++) - { - level = - startmap - - j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP; - if (level < 0) - level = 0; - if (level >= NUMCOLORMAPS) - level = NUMCOLORMAPS - 1; - scalelight[i][j] = colormaps + level * 256; - } - } - -// -// draw the border -// - R_DrawViewBorder(); // erase old menu stuff -} - - -/* -============== -= -= R_Init -= -============== -*/ - -int detailLevel; -int screenblocks = 10; - -void R_Init(void) -{ - R_InitData(); - R_InitPointToAngle(); - R_InitTables(); - // viewwidth / viewheight / detailLevel are set by the defaults - R_SetViewSize(screenblocks, detailLevel); - R_InitPlanes(); - R_InitLightTables(); - R_InitSkyMap(); - R_InitTranslationTables(); - framecount = 0; -} - -/* -============== -= -= R_PointInSubsector -= -============== -*/ - -subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) -{ - node_t *node; - int side, nodenum; - - if (!numnodes) // single subsector is a special case - return subsectors; - - nodenum = numnodes - 1; - - while (!(nodenum & NF_SUBSECTOR)) - { - node = &nodes[nodenum]; - side = R_PointOnSide(x, y, node); - nodenum = node->children[side]; - } - - return &subsectors[nodenum & ~NF_SUBSECTOR]; - -} - -//---------------------------------------------------------------------------- -// -// PROC R_SetupFrame -// -//---------------------------------------------------------------------------- - -void R_SetupFrame(player_t * player) -{ - int i; - int tableAngle; - int tempCentery; - int intensity; - - //drawbsp = 1; - viewplayer = player; - // haleyjd: removed WATCOMC - // haleyjd FIXME: viewangleoffset handling? - viewangle = player->mo->angle + viewangleoffset; - tableAngle = viewangle >> ANGLETOFINESHIFT; - viewx = player->mo->x; - viewy = player->mo->y; - - if (localQuakeHappening[displayplayer] && !paused) - { - intensity = localQuakeHappening[displayplayer]; - viewx += ((M_Random() % (intensity << 2)) - - (intensity << 1)) << FRACBITS; - viewy += ((M_Random() % (intensity << 2)) - - (intensity << 1)) << FRACBITS; - } - - extralight = player->extralight; - viewz = player->viewz; - - tempCentery = viewheight / 2 + (player->lookdir) * screenblocks / 10; - if (centery != tempCentery) - { - centery = tempCentery; - centeryfrac = centery << FRACBITS; - for (i = 0; i < viewheight; i++) - { - yslope[i] = FixedDiv((viewwidth << detailshift) / 2 * FRACUNIT, - abs(((i - centery) << FRACBITS) + - FRACUNIT / 2)); - } - } - viewsin = finesine[tableAngle]; - viewcos = finecosine[tableAngle]; - sscount = 0; - if (player->fixedcolormap) - { - fixedcolormap = colormaps + player->fixedcolormap - * 256 * sizeof(lighttable_t); - walllights = scalelightfixed; - for (i = 0; i < MAXLIGHTSCALE; i++) - { - scalelightfixed[i] = fixedcolormap; - } - } - else - { - fixedcolormap = 0; - } - framecount++; - validcount++; - if (BorderNeedRefresh) - { - if (setblocks < 10) - { - R_DrawViewBorder(); - } - BorderNeedRefresh = false; - BorderTopRefresh = false; - UpdateState |= I_FULLSCRN; - } - if (BorderTopRefresh) - { - if (setblocks < 10) - { - R_DrawTopBorder(); - } - BorderTopRefresh = false; - UpdateState |= I_MESSAGES; - } - -#if 0 - { - static int frame; - memset(screen, frame, SCREENWIDTH * SCREENHEIGHT); - frame++; - } -#endif -} - -/* -============== -= -= R_RenderView -= -============== -*/ - -void R_RenderPlayerView(player_t * player) -{ - R_SetupFrame(player); - R_ClearClipSegs(); - R_ClearDrawSegs(); - R_ClearPlanes(); - R_ClearSprites(); - NetUpdate(); // check for new console commands - - // Make displayed player invisible locally - if (localQuakeHappening[displayplayer] && gamestate == GS_LEVEL) - { - players[displayplayer].mo->flags2 |= MF2_DONTDRAW; - R_RenderBSPNode(numnodes - 1); // head node is the last node output - players[displayplayer].mo->flags2 &= ~MF2_DONTDRAW; - } - else - { - R_RenderBSPNode(numnodes - 1); // head node is the last node output - } - - NetUpdate(); // check for new console commands - R_DrawPlanes(); - NetUpdate(); // check for new console commands - R_DrawMasked(); - NetUpdate(); // check for new console commands -} diff --git a/games/NXDoom/src/hexen/r_plane.c b/games/NXDoom/src/hexen/r_plane.c deleted file mode 100644 index 8acbcc43cb0..00000000000 --- a/games/NXDoom/src/hexen/r_plane.c +++ /dev/null @@ -1,579 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "i_system.h" -#include "r_local.h" -#include "p_spec.h" - - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -int Sky1Texture; -int Sky2Texture; -fixed_t Sky1ColumnOffset; -fixed_t Sky2ColumnOffset; -int skyflatnum; -int skytexturemid; -fixed_t skyiscale; -boolean DoubleSky; -planefunction_t floorfunc, ceilingfunc; - -// Opening -visplane_t visplanes[MAXVISPLANES], *lastvisplane; -visplane_t *floorplane, *ceilingplane; -short openings[MAXOPENINGS], *lastopening; - -// Clip values are the solid pixel bounding the range. -// floorclip start out SCREENHEIGHT -// ceilingclip starts out -1 -short floorclip[SCREENWIDTH]; -short ceilingclip[SCREENWIDTH]; - -// spanstart holds the start of a plane span, initialized to 0 -int spanstart[SCREENHEIGHT]; -int spanstop[SCREENHEIGHT]; - -// Texture mapping -lighttable_t **planezlight; -fixed_t planeheight; -fixed_t yslope[SCREENHEIGHT]; -fixed_t distscale[SCREENWIDTH]; -fixed_t basexscale, baseyscale; -fixed_t cachedheight[SCREENHEIGHT]; -fixed_t cacheddistance[SCREENHEIGHT]; -fixed_t cachedxstep[SCREENHEIGHT]; -fixed_t cachedystep[SCREENHEIGHT]; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// R_InitSky -// -// Called at level load. -// -//========================================================================== - -void R_InitSky(int map) -{ - Sky1Texture = P_GetMapSky1Texture(map); - Sky2Texture = P_GetMapSky2Texture(map); - Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map); - Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map); - Sky1ColumnOffset = 0; - Sky2ColumnOffset = 0; - DoubleSky = P_GetMapDoubleSky(map); -} - -//========================================================================== -// -// R_InitSkyMap -// -// Called whenever the view size changes. -// -//========================================================================== - -void R_InitSkyMap(void) -{ - skyflatnum = R_FlatNumForName("F_SKY"); - skytexturemid = 200 * FRACUNIT; - skyiscale = FRACUNIT; -} - -//========================================================================== -// -// R_InitPlanes -// -// Called at game startup. -// -//========================================================================== - -void R_InitPlanes(void) -{ -} - -//========================================================================== -// -// R_MapPlane -// -// Globals used: planeheight, ds_source, basexscale, baseyscale, -// viewx, viewy. -// -//========================================================================== - -void R_MapPlane(int y, int x1, int x2) -{ - angle_t angle; - fixed_t distance, length; - unsigned index; - -#ifdef RANGECHECK - if (x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned) y > viewheight) - { - I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); - } -#endif - - if (planeheight != cachedheight[y]) - { - cachedheight[y] = planeheight; - distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); - ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); - ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); - } - else - { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; - } - - length = FixedMul(distance, distscale[x1]); - angle = (viewangle + xtoviewangle[x1]) >> ANGLETOFINESHIFT; - ds_xfrac = viewx + FixedMul(finecosine[angle], length); - ds_yfrac = -viewy - FixedMul(finesine[angle], length); - - if (fixedcolormap) - { - ds_colormap = fixedcolormap; - } - else - { - index = distance >> LIGHTZSHIFT; - if (index >= MAXLIGHTZ) - { - index = MAXLIGHTZ - 1; - } - ds_colormap = planezlight[index]; - } - - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; - - spanfunc(); // High or low detail -} - -//========================================================================== -// -// R_ClearPlanes -// -// Called at the beginning of each frame. -// -//========================================================================== - -void R_ClearPlanes(void) -{ - int i; - angle_t angle; - - // Opening / clipping determination - for (i = 0; i < viewwidth; i++) - { - floorclip[i] = viewheight; - ceilingclip[i] = -1; - } - - lastvisplane = visplanes; - lastopening = openings; - - // Texture calculation - memset(cachedheight, 0, sizeof(cachedheight)); - angle = (viewangle - ANG90) >> ANGLETOFINESHIFT; // left to right mapping - // Scale will be unit scale at SCREENWIDTH/2 distance - basexscale = FixedDiv(finecosine[angle], centerxfrac); - baseyscale = -FixedDiv(finesine[angle], centerxfrac); -} - -//========================================================================== -// -// R_FindPlane -// -//========================================================================== - -visplane_t *R_FindPlane(fixed_t height, int picnum, - int lightlevel, int special) -{ - visplane_t *check; - - if (special < 150) - { // Don't let low specials affect search - special = 0; - } - - if (picnum == skyflatnum) - { // All skies map together - height = 0; - lightlevel = 0; - } - - for (check = visplanes; check < lastvisplane; check++) - { - if (height == check->height - && picnum == check->picnum - && lightlevel == check->lightlevel && special == check->special) - break; - } - - if (check < lastvisplane) - { - return (check); - } - - if (lastvisplane - visplanes == MAXVISPLANES) - { - I_Error("R_FindPlane: no more visplanes"); - } - - lastvisplane++; - check->height = height; - check->picnum = picnum; - check->lightlevel = lightlevel; - check->special = special; - check->minx = SCREENWIDTH; - check->maxx = -1; - memset(check->top, 0xff, sizeof(check->top)); - return (check); -} - -//========================================================================== -// -// R_CheckPlane -// -//========================================================================== - -visplane_t *R_CheckPlane(visplane_t * pl, int start, int stop) -{ - int intrl, intrh; - int unionl, unionh; - int x; - - if (start < pl->minx) - { - intrl = pl->minx; - unionl = start; - } - else - { - unionl = pl->minx; - intrl = start; - } - if (stop > pl->maxx) - { - intrh = pl->maxx; - unionh = stop; - } - else - { - unionh = pl->maxx; - intrh = stop; - } - - for (x = intrl; x <= intrh; x++) - { - if (pl->top[x] != 0xff) - { - break; - } - } - - if (x > intrh) - { - pl->minx = unionl; - pl->maxx = unionh; - return pl; // use the same visplane - } - - // Make a new visplane - lastvisplane->height = pl->height; - lastvisplane->picnum = pl->picnum; - lastvisplane->lightlevel = pl->lightlevel; - lastvisplane->special = pl->special; - pl = lastvisplane++; - pl->minx = start; - pl->maxx = stop; - memset(pl->top, 0xff, sizeof(pl->top)); - - return pl; -} - -//========================================================================== -// -// R_MakeSpans -// -//========================================================================== - -void R_MakeSpans(int x, int t1, int b1, int t2, int b2) -{ - while (t1 < t2 && t1 <= b1) - { - R_MapPlane(t1, spanstart[t1], x - 1); - t1++; - } - while (b1 > b2 && b1 >= t1) - { - R_MapPlane(b1, spanstart[b1], x - 1); - b1--; - } - while (t2 < t1 && t2 <= b2) - { - spanstart[t2] = x; - t2++; - } - while (b2 > b1 && b2 >= t2) - { - spanstart[b2] = x; - b2--; - } -} - -//========================================================================== -// -// R_DrawPlanes -// -//========================================================================== - -#define SKYTEXTUREMIDSHIFTED 200 - -void R_DrawPlanes(void) -{ - visplane_t *pl; - int light; - int x, stop; - int angle; - byte *tempSource; - byte *source; - byte *source2; - byte *dest; - int count; - int offset; - int skyTexture; - int offset2; - int skyTexture2; - int scrollOffset; - -#ifdef RANGECHECK - if (ds_p - drawsegs > MAXDRAWSEGS) - { - I_Error("R_DrawPlanes: drawsegs overflow (%td)", - ds_p - drawsegs); - } - if (lastvisplane - visplanes > MAXVISPLANES) - { - I_Error("R_DrawPlanes: visplane overflow (%td)", - lastvisplane - visplanes); - } - if (lastopening - openings > MAXOPENINGS) - { - I_Error("R_DrawPlanes: opening overflow (%td)", - lastopening - openings); - } -#endif - - for (pl = visplanes; pl < lastvisplane; pl++) - { - if (pl->minx > pl->maxx) - { - continue; - } - if (pl->picnum == skyflatnum) - { // Sky flat - if (DoubleSky) - { // Render 2 layers, sky 1 in front - offset = Sky1ColumnOffset >> 16; - skyTexture = texturetranslation[Sky1Texture]; - offset2 = Sky2ColumnOffset >> 16; - skyTexture2 = texturetranslation[Sky2Texture]; - for (x = pl->minx; x <= pl->maxx; x++) - { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; - if (dc_yl <= dc_yh) - { - count = dc_yh - dc_yl; - if (count < 0) - { - return; - } - angle = (viewangle + xtoviewangle[x]) - >> ANGLETOSKYSHIFT; - source = R_GetColumn(skyTexture, angle + offset) - + SKYTEXTUREMIDSHIFTED + (dc_yl - centery); - source2 = R_GetColumn(skyTexture2, angle + offset2) - + SKYTEXTUREMIDSHIFTED + (dc_yl - centery); - dest = ylookup[dc_yl] + columnofs[x]; - do - { - if (*source) - { - *dest = *source++; - source2++; - } - else - { - *dest = *source2++; - source++; - } - dest += SCREENWIDTH; - } - while (count--); - } - } - continue; // Next visplane - } - else - { // Render single layer - if (pl->special == 200) - { // Use sky 2 - offset = Sky2ColumnOffset >> 16; - skyTexture = texturetranslation[Sky2Texture]; - } - else - { // Use sky 1 - offset = Sky1ColumnOffset >> 16; - skyTexture = texturetranslation[Sky1Texture]; - } - for (x = pl->minx; x <= pl->maxx; x++) - { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; - if (dc_yl <= dc_yh) - { - count = dc_yh - dc_yl; - if (count < 0) - { - return; - } - angle = (viewangle + xtoviewangle[x]) - >> ANGLETOSKYSHIFT; - source = R_GetColumn(skyTexture, angle + offset) - + SKYTEXTUREMIDSHIFTED + (dc_yl - centery); - dest = ylookup[dc_yl] + columnofs[x]; - do - { - *dest = *source++; - dest += SCREENWIDTH; - } - while (count--); - } - } - continue; // Next visplane - } - } - // Regular flat - tempSource = W_CacheLumpNum(firstflat + - flattranslation[pl->picnum], PU_STATIC); - scrollOffset = leveltime >> 1 & 63; - switch (pl->special) - { // Handle scrolling flats - case 201: - case 202: - case 203: // Scroll_North_xxx - ds_source = tempSource + ((scrollOffset - << (pl->special - 201) & 63) << 6); - break; - case 204: - case 205: - case 206: // Scroll_East_xxx - ds_source = tempSource + ((63 - scrollOffset) - << (pl->special - 204) & 63); - break; - case 207: - case 208: - case 209: // Scroll_South_xxx - ds_source = tempSource + (((63 - scrollOffset) - << (pl->special - 207) & 63) << 6); - break; - case 210: - case 211: - case 212: // Scroll_West_xxx - ds_source = tempSource + (scrollOffset - << (pl->special - 210) & 63); - break; - case 213: - case 214: - case 215: // Scroll_NorthWest_xxx - ds_source = tempSource + (scrollOffset - << (pl->special - 213) & 63) + - ((scrollOffset << (pl->special - 213) & 63) << 6); - break; - case 216: - case 217: - case 218: // Scroll_NorthEast_xxx - ds_source = tempSource + ((63 - scrollOffset) - << (pl->special - 216) & 63) + - ((scrollOffset << (pl->special - 216) & 63) << 6); - break; - case 219: - case 220: - case 221: // Scroll_SouthEast_xxx - ds_source = tempSource + ((63 - scrollOffset) - << (pl->special - 219) & 63) + - (((63 - scrollOffset) << (pl->special - 219) & 63) << 6); - break; - case 222: - case 223: - case 224: // Scroll_SouthWest_xxx - ds_source = tempSource + (scrollOffset - << (pl->special - 222) & 63) + - (((63 - scrollOffset) << (pl->special - 222) & 63) << 6); - break; - default: - ds_source = tempSource; - break; - } - planeheight = abs(pl->height - viewz); - light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (light >= LIGHTLEVELS) - { - light = LIGHTLEVELS - 1; - } - if (light < 0) - { - light = 0; - } - planezlight = zlight[light]; - - pl->top[pl->maxx + 1] = 0xff; - pl->top[pl->minx - 1] = 0xff; - - stop = pl->maxx + 1; - for (x = pl->minx; x <= stop; x++) - { - R_MakeSpans(x, pl->top[x - 1], pl->bottom[x - 1], - pl->top[x], pl->bottom[x]); - } - W_ReleaseLumpNum(firstflat + flattranslation[pl->picnum]); - } -} diff --git a/games/NXDoom/src/hexen/r_segs.c b/games/NXDoom/src/hexen/r_segs.c deleted file mode 100644 index 003cf2eb0ec..00000000000 --- a/games/NXDoom/src/hexen/r_segs.c +++ /dev/null @@ -1,654 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "i_system.h" -#include "r_local.h" - -// OPTIMIZE: closed two sided lines as single sided - -boolean segtextured; // true if any of the segs textures might be vis -boolean markfloor; // false if the back side is the same plane -boolean markceiling; -boolean maskedtexture; -int toptexture, bottomtexture, midtexture; - - -angle_t rw_normalangle; -int rw_angle1; // angle to line origin - -// -// wall -// -int rw_x; -int rw_stopx; -angle_t rw_centerangle; -fixed_t rw_offset; -fixed_t rw_distance; -fixed_t rw_scale; -fixed_t rw_scalestep; -fixed_t rw_midtexturemid; -fixed_t rw_toptexturemid; -fixed_t rw_bottomtexturemid; - -int worldtop, worldbottom, worldhigh, worldlow; - -fixed_t pixhigh, pixlow; -fixed_t pixhighstep, pixlowstep; -fixed_t topfrac, topstep; -fixed_t bottomfrac, bottomstep; - - -lighttable_t **walllights; - -short *maskedtexturecol; - -/* -================ -= -= R_RenderMaskedSegRange -= -================ -*/ - -void R_RenderMaskedSegRange(drawseg_t * ds, int x1, int x2) -{ - unsigned index; - column_t *col; - int lightnum; - int texnum; - -// -// calculate light table -// use different light tables for horizontal / vertical / diagonal -// OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; - frontsector = curline->frontsector; - backsector = curline->backsector; - texnum = texturetranslation[curline->sidedef->midtexture]; - - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; - //if (curline->v1->y == curline->v2->y) - // lightnum--; - //else if (curline->v1->x == curline->v2->x) - // lightnum++; - //if (lightnum < 0) - // walllights = scalelight[0]; - if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS - 1]; - else - walllights = scalelight[lightnum]; - - maskedtexturecol = ds->maskedtexturecol; - - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1) * rw_scalestep; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; - -// -// find positioning -// - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - { - dc_texturemid = frontsector->floorheight > backsector->floorheight - ? frontsector->floorheight : backsector->floorheight; - dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; - } - else - { - dc_texturemid = frontsector->ceilingheight < backsector->ceilingheight - ? frontsector->ceilingheight : backsector->ceilingheight; - dc_texturemid = dc_texturemid - viewz; - } - dc_texturemid += curline->sidedef->rowoffset; - - if (fixedcolormap) - dc_colormap = fixedcolormap; -// -// draw the columns -// - for (dc_x = x1; dc_x <= x2; dc_x++) - { - // calculate lighting - if (maskedtexturecol[dc_x] != SHRT_MAX) - { - if (!fixedcolormap) - { - index = spryscale >> LIGHTSCALESHIFT; - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE - 1; - dc_colormap = walllights[index]; - } - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned) spryscale; - - // - // draw the texture - // - col = (column_t *) ((byte *) - R_GetColumn(texnum, - maskedtexturecol[dc_x]) - 3); - - R_DrawMaskedColumn(col, -1); - maskedtexturecol[dc_x] = SHRT_MAX; - } - spryscale += rw_scalestep; - } - -} - -/* -================ -= -= R_RenderSegLoop -= -= Draws zero, one, or two textures (and possibly a masked texture) for walls -= Can draw or mark the starting pixel of floor and ceiling textures -= -= CALLED: CORE LOOPING ROUTINE -================ -*/ - -#define HEIGHTBITS 12 -#define HEIGHTUNIT (1<> HEIGHTBITS; - if (yl < ceilingclip[rw_x] + 1) - yl = ceilingclip[rw_x] + 1; // no space above wall - if (markceiling) - { - top = ceilingclip[rw_x] + 1; - bottom = yl - 1; - if (bottom >= floorclip[rw_x]) - bottom = floorclip[rw_x] - 1; - if (top <= bottom) - { - ceilingplane->top[rw_x] = top; - ceilingplane->bottom[rw_x] = bottom; - } - } - - yh = bottomfrac >> HEIGHTBITS; - if (yh >= floorclip[rw_x]) - yh = floorclip[rw_x] - 1; - if (markfloor) - { - top = yh + 1; - bottom = floorclip[rw_x] - 1; - if (top <= ceilingclip[rw_x]) - top = ceilingclip[rw_x] + 1; - if (top <= bottom) - { - floorplane->top[rw_x] = top; - floorplane->bottom[rw_x] = bottom; - } - } - -// -// texturecolumn and lighting are independent of wall tiers -// - if (segtextured) - { - // calculate texture offset - angle = (rw_centerangle + xtoviewangle[rw_x]) >> ANGLETOFINESHIFT; - texturecolumn = - rw_offset - FixedMul(finetangent[angle], rw_distance); - texturecolumn >>= FRACBITS; - // calculate lighting - index = rw_scale >> LIGHTSCALESHIFT; - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE - 1; - dc_colormap = walllights[index]; - dc_x = rw_x; - dc_iscale = 0xffffffffu / (unsigned) rw_scale; - } - -// -// draw the wall tiers -// - if (midtexture) - { // single sided line - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture, texturecolumn); - colfunc(); - ceilingclip[rw_x] = viewheight; - floorclip[rw_x] = -1; - } - else - { // two sided line - if (toptexture) - { // top wall - mid = pixhigh >> HEIGHTBITS; - pixhigh += pixhighstep; - if (mid >= floorclip[rw_x]) - mid = floorclip[rw_x] - 1; - if (mid >= yl) - { - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture, texturecolumn); - colfunc(); - ceilingclip[rw_x] = mid; - } - else - ceilingclip[rw_x] = yl - 1; - } - else - { // no top wall - if (markceiling) - ceilingclip[rw_x] = yl - 1; - } - - if (bottomtexture) - { // bottom wall - mid = (pixlow + HEIGHTUNIT - 1) >> HEIGHTBITS; - pixlow += pixlowstep; - if (mid <= ceilingclip[rw_x]) - mid = ceilingclip[rw_x] + 1; // no space above wall - if (mid <= yh) - { - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, texturecolumn); - colfunc(); - floorclip[rw_x] = mid; - } - else - floorclip[rw_x] = yh + 1; - } - else - { // no bottom wall - if (markfloor) - floorclip[rw_x] = yh + 1; - } - - if (maskedtexture) - { // save texturecol for backdrawing of masked mid texture - maskedtexturecol[rw_x] = texturecolumn; - } - } - - rw_scale += rw_scalestep; - topfrac += topstep; - bottomfrac += bottomstep; - } - -} - - - -/* -===================== -= -= R_StoreWallRange -= -= A wall segment will be drawn between start and stop pixels (inclusive) -= -====================== -*/ - -void R_StoreWallRange(int start, int stop) -{ - fixed_t hyp; - fixed_t sineval; - angle_t distangle, offsetangle; - fixed_t vtop; - int lightnum; - - if (ds_p == &drawsegs[MAXDRAWSEGS]) - return; // don't overflow and crash - -#ifdef RANGECHECK - if (start >= viewwidth || start > stop) - I_Error("Bad R_RenderWallRange: %i to %i", start, stop); -#endif - - sidedef = curline->sidedef; - linedef = curline->linedef; - -// mark the segment as visible for auto map - linedef->flags |= ML_MAPPED; - -// -// calculate rw_distance for scale calculation -// - rw_normalangle = curline->angle + ANG90; - offsetangle = abs((int) rw_normalangle - (int) rw_angle1); - if (offsetangle > ANG90) - offsetangle = ANG90; - distangle = ANG90 - offsetangle; - hyp = R_PointToDist(curline->v1->x, curline->v1->y); - sineval = finesine[distangle >> ANGLETOFINESHIFT]; - rw_distance = FixedMul(hyp, sineval); - - - ds_p->x1 = rw_x = start; - ds_p->x2 = stop; - ds_p->curline = curline; - rw_stopx = stop + 1; - -// -// calculate scale at both ends and step -// - ds_p->scale1 = rw_scale = - R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); - if (stop > start) - { - ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); - ds_p->scalestep = rw_scalestep = - (ds_p->scale2 - rw_scale) / (stop - start); - } - else - { - // - // try to fix the stretched line bug - // -#if 0 - if (rw_distance < FRACUNIT / 2) - { - fixed_t trx, try; - fixed_t gxt, gyt; - - trx = curline->v1->x - viewx; - try = curline->v1->y - viewy; - - gxt = FixedMul(trx, viewcos); - gyt = -FixedMul(try, viewsin); - ds_p->scale1 = FixedDiv(projection, gxt - gyt); - } -#endif - ds_p->scale2 = ds_p->scale1; - } - - -// -// calculate texture boundaries and decide if floor / ceiling marks -// are needed -// - worldtop = frontsector->ceilingheight - viewz; - worldbottom = frontsector->floorheight - viewz; - - midtexture = toptexture = bottomtexture = maskedtexture = 0; - ds_p->maskedtexturecol = NULL; - - if (!backsector) - { -// -// single sided line -// - midtexture = texturetranslation[sidedef->midtexture]; - // a single sided line is terminal, so it must mark ends - markfloor = markceiling = true; - if (linedef->flags & ML_DONTPEGBOTTOM) - { - vtop = frontsector->floorheight + - textureheight[sidedef->midtexture]; - rw_midtexturemid = vtop - viewz; // bottom of texture at bottom - } - else - rw_midtexturemid = worldtop; // top of texture at top - rw_midtexturemid += sidedef->rowoffset; - ds_p->silhouette = SIL_BOTH; - ds_p->sprtopclip = screenheightarray; - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->tsilheight = INT_MIN; - } - else - { -// -// two sided line -// - ds_p->sprtopclip = ds_p->sprbottomclip = NULL; - ds_p->silhouette = 0; - if (frontsector->floorheight > backsector->floorheight) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = frontsector->floorheight; - } - else if (backsector->floorheight > viewz) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; -// ds_p->sprbottomclip = negonearray; - } - if (frontsector->ceilingheight < backsector->ceilingheight) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = frontsector->ceilingheight; - } - else if (backsector->ceilingheight < viewz) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; -// ds_p->sprtopclip = screenheightarray; - } - - if (backsector->ceilingheight <= frontsector->floorheight) - { - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->silhouette |= SIL_BOTTOM; - } - if (backsector->floorheight >= frontsector->ceilingheight) - { - ds_p->sprtopclip = screenheightarray; - ds_p->tsilheight = INT_MIN; - ds_p->silhouette |= SIL_TOP; - } - worldhigh = backsector->ceilingheight - viewz; - worldlow = backsector->floorheight - viewz; - - // hack to allow height changes in outdoor areas - if (frontsector->ceilingpic == skyflatnum - && backsector->ceilingpic == skyflatnum) - worldtop = worldhigh; - - if (worldlow != worldbottom - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel - || backsector->special != frontsector->special) - markfloor = true; - else - markfloor = false; // same plane on both sides - - if (worldhigh != worldtop - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel) - markceiling = true; - else - markceiling = false; // same plane on both sides - - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - markceiling = markfloor = true; // closed door - - if (worldhigh < worldtop) - { // top texture - toptexture = texturetranslation[sidedef->toptexture]; - if (linedef->flags & ML_DONTPEGTOP) - rw_toptexturemid = worldtop; // top of texture at top - else - { - vtop = backsector->ceilingheight + - textureheight[sidedef->toptexture]; - rw_toptexturemid = vtop - viewz; // bottom of texture - } - } - if (worldlow > worldbottom) - { // bottom texture - bottomtexture = texturetranslation[sidedef->bottomtexture]; - if (linedef->flags & ML_DONTPEGBOTTOM) - { // bottom of texture at bottom - rw_bottomtexturemid = worldtop; // top of texture at top - } - else // top of texture at top - rw_bottomtexturemid = worldlow; - } - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; - - // - // allocate space for masked texture tables - // - if (sidedef->midtexture) - { // masked midtexture - maskedtexture = true; - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; - } - } - -// -// calculate rw_offset (only needed for textured lines) -// - segtextured = midtexture | toptexture | bottomtexture | maskedtexture; - - if (segtextured) - { - offsetangle = rw_normalangle - rw_angle1; - if (offsetangle > ANG180) - offsetangle = -offsetangle; - if (offsetangle > ANG90) - offsetangle = ANG90; - sineval = finesine[offsetangle >> ANGLETOFINESHIFT]; - rw_offset = FixedMul(hyp, sineval); - if (rw_normalangle - rw_angle1 < ANG180) - rw_offset = -rw_offset; - rw_offset += sidedef->textureoffset + curline->offset; - rw_centerangle = ANG90 + viewangle - rw_normalangle; - - // - // calculate light table - // use different light tables for horizontal / vertical / diagonal - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - if (!fixedcolormap) - { - lightnum = - (frontsector->lightlevel >> LIGHTSEGSHIFT) + extralight; - //if (curline->v1->y == curline->v2->y) - // lightnum--; - //else if (curline->v1->x == curline->v2->x) - // lightnum++; - //if (lightnum < 0) - // walllights = scalelight[0]; - if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS - 1]; - else - walllights = scalelight[lightnum]; - } - } - - -// -// if a floor / ceiling plane is on the wrong side of the view plane -// it is definately invisible and doesn't need to be marked -// - if (frontsector->floorheight >= viewz) - markfloor = false; // above view plane - if (frontsector->ceilingheight <= viewz - && frontsector->ceilingpic != skyflatnum) - markceiling = false; // below view plane - -// -// calculate incremental stepping values for texture edges -// - worldtop >>= 4; - worldbottom >>= 4; - - topstep = -FixedMul(rw_scalestep, worldtop); - topfrac = (centeryfrac >> 4) - FixedMul(worldtop, rw_scale); - - bottomstep = -FixedMul(rw_scalestep, worldbottom); - bottomfrac = (centeryfrac >> 4) - FixedMul(worldbottom, rw_scale); - - if (backsector) - { - worldhigh >>= 4; - worldlow >>= 4; - - if (worldhigh < worldtop) - { - pixhigh = (centeryfrac >> 4) - FixedMul(worldhigh, rw_scale); - pixhighstep = -FixedMul(rw_scalestep, worldhigh); - } - if (worldlow > worldbottom) - { - pixlow = (centeryfrac >> 4) - FixedMul(worldlow, rw_scale); - pixlowstep = -FixedMul(rw_scalestep, worldlow); - } - } - -// -// render it -// - if (markceiling) - ceilingplane = R_CheckPlane(ceilingplane, rw_x, rw_stopx - 1); - if (markfloor) - floorplane = R_CheckPlane(floorplane, rw_x, rw_stopx - 1); - - R_RenderSegLoop(); - -// -// save sprite clipping info -// - if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) - { - memcpy(lastopening, ceilingclip + start, 2 * (rw_stopx - start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } - if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) - && !ds_p->sprbottomclip) - { - memcpy(lastopening, floorclip + start, 2 * (rw_stopx - start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; - } - if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; - } - if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) - { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; - } - ds_p++; -} diff --git a/games/NXDoom/src/hexen/r_things.c b/games/NXDoom/src/hexen/r_things.c deleted file mode 100644 index e9cfeccdb09..00000000000 --- a/games/NXDoom/src/hexen/r_things.c +++ /dev/null @@ -1,1044 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include -#include -#include "h2def.h" -#include "i_system.h" -#include "i_swap.h" -#include "r_local.h" - -//void R_DrawTranslatedAltTLColumn(void); - -typedef struct -{ - int x1, x2; - - int column; - int topclip; - int bottomclip; -} maskdraw_t; - -/* - -Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis. -This is not the same as the angle, which increases counter clockwise -(protractor). There was a lot of stuff grabbed wrong, so I changed it... - -*/ - - -fixed_t pspritescale, pspriteiscale; - -lighttable_t **spritelights; - -// constant arrays used for psprite clipping and initializing clipping -short negonearray[SCREENWIDTH]; -short screenheightarray[SCREENWIDTH]; - -boolean LevelUseFullBright; -/* -=============================================================================== - - INITIALIZATION FUNCTIONS - -=============================================================================== -*/ - -// variables used to look up and range check thing_t sprites patches -spritedef_t *sprites; -int numsprites; - -spriteframe_t sprtemp[30]; -int maxframe; -static const char *spritename; - - - -/* -================= -= -= R_InstallSpriteLump -= -= Local function for R_InitSprites -================= -*/ - -void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, - boolean flipped) -{ - int r; - - if (frame >= 30 || rotation > 8) - I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump); - - if ((int) frame > maxframe) - maxframe = frame; - - if (rotation == 0) - { -// the lump should be used for all rotations - if (sprtemp[frame].rotate == false) - I_Error("R_InitSprites: Sprite %s frame %c has multip rot=0 lump", - spritename, 'A' + frame); - if (sprtemp[frame].rotate == true) - I_Error - ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", - spritename, 'A' + frame); - - sprtemp[frame].rotate = false; - for (r = 0; r < 8; r++) - { - sprtemp[frame].lump[r] = lump - firstspritelump; - sprtemp[frame].flip[r] = (byte) flipped; - } - return; - } - -// the lump is only used for one rotation - if (sprtemp[frame].rotate == false) - I_Error - ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump", - spritename, 'A' + frame); - - sprtemp[frame].rotate = true; - - rotation--; // make 0 based - if (sprtemp[frame].lump[rotation] != -1) - I_Error - ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it", - spritename, 'A' + frame, '1' + rotation); - - sprtemp[frame].lump[rotation] = lump - firstspritelump; - sprtemp[frame].flip[rotation] = (byte) flipped; -} - -/* -================= -= -= R_InitSpriteDefs -= -= Pass a null terminated list of sprite names (4 chars exactly) to be used -= Builds the sprite rotation matrixes to account for horizontally flipped -= sprites. Will report an error if the lumps are inconsistant -=Only called at startup -= -= Sprite lump names are 4 characters for the actor, a letter for the frame, -= and a number for the rotation, A sprite that is flippable will have an -= additional letter/number appended. The rotation character can be 0 to -= signify no rotations -================= -*/ - -void R_InitSpriteDefs(const char **namelist) -{ - const char **check; - int i, l, frame, rotation; - int start, end; - -// count the number of sprite names - check = namelist; - while (*check != NULL) - check++; - numsprites = check - namelist; - - if (!numsprites) - return; - - sprites = Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); - - start = firstspritelump - 1; - end = lastspritelump + 1; - -// scan all the lump names for each of the names, noting the highest -// frame letter -// Just compare 4 characters as ints - for (i = 0; i < numsprites; i++) - { - spritename = namelist[i]; - memset(sprtemp, -1, sizeof(sprtemp)); - - maxframe = -1; - - // - // scan the lumps, filling in the frames for whatever is found - // - for (l = start + 1; l < end; l++) - if (!strncmp(lumpinfo[l]->name, namelist[i], 4)) - { - frame = lumpinfo[l]->name[4] - 'A'; - rotation = lumpinfo[l]->name[5] - '0'; - R_InstallSpriteLump(l, frame, rotation, false); - if (lumpinfo[l]->name[6]) - { - frame = lumpinfo[l]->name[6] - 'A'; - rotation = lumpinfo[l]->name[7] - '0'; - R_InstallSpriteLump(l, frame, rotation, true); - } - } - - // - // check the frames that were found for completeness - // - if (maxframe == -1) - { - //continue; - sprites[i].numframes = 0; - if (gamemode == shareware) - continue; - I_Error("R_InitSprites: No lumps found for sprite %s", - namelist[i]); - } - - maxframe++; - for (frame = 0; frame < maxframe; frame++) - { - switch ((int) sprtemp[frame].rotate) - { - case -1: // no rotations were found for that frame at all - I_Error("R_InitSprites: No patches found for %s frame %c", - namelist[i], frame + 'A'); - case 0: // only the first rotation is needed - break; - - case 1: // must have all 8 frames - for (rotation = 0; rotation < 8; rotation++) - if (sprtemp[frame].lump[rotation] == -1) - I_Error - ("R_InitSprites: Sprite %s frame %c is missing rotations", - namelist[i], frame + 'A'); - } - } - - // - // allocate space for the frames present and copy sprtemp to it - // - sprites[i].numframes = maxframe; - sprites[i].spriteframes = - Z_Malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); - memcpy(sprites[i].spriteframes, sprtemp, - maxframe * sizeof(spriteframe_t)); - } - -} - - -/* -=============================================================================== - - GAME FUNCTIONS - -=============================================================================== -*/ - -vissprite_t vissprites[MAXVISSPRITES], *vissprite_p; -int newvissprite; - - -/* -=================== -= -= R_InitSprites -= -= Called at program start -=================== -*/ - -void R_InitSprites(const char **namelist) -{ - int i; - - for (i = 0; i < SCREENWIDTH; i++) - { - negonearray[i] = -1; - } - - R_InitSpriteDefs(namelist); -} - - -/* -=================== -= -= R_ClearSprites -= -= Called at frame start -=================== -*/ - -void R_ClearSprites(void) -{ - vissprite_p = vissprites; -} - - -/* -=================== -= -= R_NewVisSprite -= -=================== -*/ - -vissprite_t overflowsprite; - -vissprite_t *R_NewVisSprite(void) -{ - if (vissprite_p == &vissprites[MAXVISSPRITES]) - return &overflowsprite; - vissprite_p++; - return vissprite_p - 1; -} - - -/* -================ -= -= R_DrawMaskedColumn -= -= Used for sprites and masked mid textures -================ -*/ - -short *mfloorclip; -short *mceilingclip; -fixed_t spryscale; -fixed_t sprtopscreen; -fixed_t sprbotscreen; - -void R_DrawMaskedColumn(column_t * column, signed int baseclip) -{ - int topscreen, bottomscreen; - fixed_t basetexturemid; - - basetexturemid = dc_texturemid; - - for (; column->topdelta != 0xff;) - { -// calculate unclipped screen coordinates for post - topscreen = sprtopscreen + spryscale * column->topdelta; - bottomscreen = topscreen + spryscale * column->length; - dc_yl = (topscreen + FRACUNIT - 1) >> FRACBITS; - dc_yh = (bottomscreen - 1) >> FRACBITS; - - if (dc_yh >= mfloorclip[dc_x]) - dc_yh = mfloorclip[dc_x] - 1; - if (dc_yl <= mceilingclip[dc_x]) - dc_yl = mceilingclip[dc_x] + 1; - - if (dc_yh >= baseclip && baseclip != -1) - dc_yh = baseclip; - - if (dc_yl <= dc_yh) - { - dc_source = (byte *) column + 3; - dc_texturemid = basetexturemid - (column->topdelta << FRACBITS); -// dc_source = (byte *)column + 3 - column->topdelta; - colfunc(); // either R_DrawColumn or R_DrawTLColumn - } - column = (column_t *) ((byte *) column + column->length + 4); - } - - dc_texturemid = basetexturemid; -} - - -/* -================ -= -= R_DrawVisSprite -= -= mfloorclip and mceilingclip should also be set -================ -*/ - -void R_DrawVisSprite(vissprite_t * vis, int x1, int x2) -{ - column_t *column; - int texturecolumn; - fixed_t frac; - patch_t *patch; - fixed_t baseclip; - - - patch = W_CacheLumpNum(vis->patch + firstspritelump, PU_CACHE); - - dc_colormap = vis->colormap; - -// if(!dc_colormap) -// colfunc = tlcolfunc; // NULL colormap = shadow draw - - if (vis->mobjflags & (MF_SHADOW | MF_ALTSHADOW)) - { - if (vis->mobjflags & MF_TRANSLATION) - { - colfunc = R_DrawTranslatedTLColumn; - dc_translation = translationtables - 256 - + vis->class * ((maxplayers - 1) * 256) + - ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); - } - else if (vis->mobjflags & MF_SHADOW) - { // Draw using shadow column function - colfunc = tlcolfunc; - } - else - { - colfunc = R_DrawAltTLColumn; - } - } - else if (vis->mobjflags & MF_TRANSLATION) - { - // Draw using translated column function - colfunc = R_DrawTranslatedColumn; - dc_translation = translationtables - 256 - + vis->class * ((maxplayers - 1) * 256) + - ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); - } - - dc_iscale = abs(vis->xiscale) >> detailshift; - dc_texturemid = vis->texturemid; - frac = vis->startfrac; - spryscale = vis->scale; - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - - // check to see if vissprite is a weapon - if (vis->psprite) - { - dc_texturemid += FixedMul(((centery - viewheight / 2) << FRACBITS), - vis->xiscale); - sprtopscreen += (viewheight / 2 - centery) << FRACBITS; - } - - if (vis->floorclip && !vis->psprite) - { - sprbotscreen = sprtopscreen + FixedMul(SHORT(patch->height) << FRACBITS, - spryscale); - baseclip = (sprbotscreen - FixedMul(vis->floorclip, - spryscale)) >> FRACBITS; - } - else - { - baseclip = -1; - } - - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) - { - texturecolumn = frac >> FRACBITS; -#ifdef RANGECHECK - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - I_Error("R_DrawSpriteRange: bad texturecolumn"); -#endif - column = (column_t *) ((byte *) patch + - LONG(patch->columnofs[texturecolumn])); - R_DrawMaskedColumn(column, baseclip); - } - - colfunc = basecolfunc; -} - - - -/* -=================== -= -= R_ProjectSprite -= -= Generates a vissprite for a thing if it might be visible -= -=================== -*/ - -void R_ProjectSprite(mobj_t * thing) -{ - fixed_t trx, try; - fixed_t gxt, gyt; - fixed_t tx, tz; - fixed_t xscale; - int x1, x2; - spritedef_t *sprdef; - spriteframe_t *sprframe; - int lump; - unsigned rot; - boolean flip; - int index; - vissprite_t *vis; - angle_t ang; - fixed_t iscale; - - if (thing->flags2 & MF2_DONTDRAW) - { // Never make a vissprite when MF2_DONTDRAW is flagged. - return; - } - -// -// transform the origin point -// - trx = thing->x - viewx; - try = thing->y - viewy; - - gxt = FixedMul(trx, viewcos); - gyt = -FixedMul(try, viewsin); - tz = gxt - gyt; - - if (tz < MINZ) - return; // thing is behind view plane - xscale = FixedDiv(projection, tz); - - gxt = -FixedMul(trx, viewsin); - gyt = FixedMul(try, viewcos); - tx = -(gyt + gxt); - - if (abs(tx) > (tz << 2)) - return; // too far off the side - -// -// decide which patch to use for sprite reletive to player -// -#ifdef RANGECHECK - if ((unsigned) thing->sprite >= numsprites) - I_Error("R_ProjectSprite: invalid sprite number %i ", thing->sprite); -#endif - sprdef = &sprites[thing->sprite]; -#ifdef RANGECHECK - if ((thing->frame & FF_FRAMEMASK) >= sprdef->numframes) - I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", - thing->sprite, thing->frame); -#endif - sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; - - if (sprframe->rotate) - { // choose a different rotation based on player view - ang = R_PointToAngle(thing->x, thing->y); - rot = (ang - thing->angle + (unsigned) (ANG45 / 2) * 9) >> 29; - lump = sprframe->lump[rot]; - flip = (boolean) sprframe->flip[rot]; - } - else - { // use single rotation for all views - lump = sprframe->lump[0]; - flip = (boolean) sprframe->flip[0]; - } - -// -// calculate edges of the shape -// - tx -= spriteoffset[lump]; - x1 = (centerxfrac + FixedMul(tx, xscale)) >> FRACBITS; - if (x1 > viewwidth) - return; // off the right side - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul(tx, xscale)) >> FRACBITS) - 1; - if (x2 < 0) - return; // off the left side - - -// -// store information in a vissprite -// - vis = R_NewVisSprite(); - vis->mobjflags = thing->flags; - vis->psprite = false; - vis->scale = xscale << detailshift; - vis->gx = thing->x; - vis->gy = thing->y; - vis->gz = thing->z; - vis->gzt = thing->z + spritetopoffset[lump]; - if (thing->flags & MF_TRANSLATION) - { - if (thing->player) - { - vis->class = thing->player->class; - } - else - { - vis->class = thing->special1.i; - } - if (vis->class > 2) - { - vis->class = 0; - } - } - // foot clipping - vis->floorclip = thing->floorclip; - vis->texturemid = vis->gzt - viewz - vis->floorclip; - - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; - iscale = FixedDiv(FRACUNIT, xscale); - if (flip) - { - vis->startfrac = spritewidth[lump] - 1; - vis->xiscale = -iscale; - } - else - { - vis->startfrac = 0; - vis->xiscale = iscale; - } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale * (vis->x1 - x1); - vis->patch = lump; -// -// get light level -// - -// if (thing->flags & MF_SHADOW) -// vis->colormap = NULL; // shadow draw -// else ... - - if (fixedcolormap) - vis->colormap = fixedcolormap; // fixed map - else if (LevelUseFullBright && thing->frame & FF_FULLBRIGHT) - vis->colormap = colormaps; // full bright - else - { // diminished light - index = xscale >> (LIGHTSCALESHIFT - detailshift); - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE - 1; - vis->colormap = spritelights[index]; - } -} - - - - -/* -======================== -= -= R_AddSprites -= -======================== -*/ - -void R_AddSprites(sector_t * sec) -{ - mobj_t *thing; - int lightnum; - - if (sec->validcount == validcount) - return; // already added - - sec->validcount = validcount; - - lightnum = (sec->lightlevel >> LIGHTSEGSHIFT) + extralight; - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS - 1]; - else - spritelights = scalelight[lightnum]; - - - for (thing = sec->thinglist; thing; thing = thing->snext) - R_ProjectSprite(thing); -} - - -/* -======================== -= -= R_DrawPSprite -= -======================== -*/ - -// Y-adjustment values for full screen (4 weapons) -int PSpriteSY[NUMCLASSES][NUMWEAPONS] = { - {0, -12 * FRACUNIT, -10 * FRACUNIT, 10 * FRACUNIT}, // Fighter - {-8 * FRACUNIT, 10 * FRACUNIT, 10 * FRACUNIT, 0}, // Cleric - {9 * FRACUNIT, 20 * FRACUNIT, 20 * FRACUNIT, 20 * FRACUNIT}, // Mage - {10 * FRACUNIT, 10 * FRACUNIT, 10 * FRACUNIT, 10 * FRACUNIT} // Pig -}; - -void R_DrawPSprite(pspdef_t * psp) -{ - fixed_t tx; - int x1, x2; - spritedef_t *sprdef; - spriteframe_t *sprframe; - int lump; - boolean flip; - vissprite_t *vis, avis; - - int tempangle; - -// -// decide which patch to use -// -#ifdef RANGECHECK - if ((unsigned) psp->state->sprite >= numsprites) - I_Error("R_ProjectSprite: invalid sprite number %i ", - psp->state->sprite); -#endif - sprdef = &sprites[psp->state->sprite]; -#ifdef RANGECHECK - if ((psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) - I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", - psp->state->sprite, psp->state->frame); -#endif - sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; - - lump = sprframe->lump[0]; - flip = (boolean) sprframe->flip[0]; - -// -// calculate edges of the shape -// - tx = psp->sx - 160 * FRACUNIT; - - tx -= spriteoffset[lump]; - if (viewangleoffset) - { - tempangle = - ((centerxfrac / 1024) * (viewangleoffset >> ANGLETOFINESHIFT)); - } - else - { - tempangle = 0; - } - x1 = (centerxfrac + FixedMul(tx, pspritescale) + tempangle) >> FRACBITS; - if (x1 > viewwidth) - return; // off the right side - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul(tx, pspritescale) + - tempangle) >> FRACBITS) - 1; - if (x2 < 0) - return; // off the left side - -// -// store information in a vissprite -// - vis = &avis; - vis->mobjflags = 0; - vis->class = 0; - vis->psprite = true; - vis->floorclip = 0; - vis->texturemid = (BASEYCENTER << FRACBITS) + FRACUNIT / 2 - - (psp->sy - spritetopoffset[lump]); - if (viewheight == SCREENHEIGHT) - { - vis->texturemid -= PSpriteSY[viewplayer->class] - [players[consoleplayer].readyweapon]; - } - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; - vis->scale = pspritescale << detailshift; - if (flip) - { - vis->xiscale = -pspriteiscale; - vis->startfrac = spritewidth[lump] - 1; - } - else - { - vis->xiscale = pspriteiscale; - vis->startfrac = 0; - } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale * (vis->x1 - x1); - vis->patch = lump; - - if (viewplayer->powers[pw_invulnerability] && viewplayer->class - == PCLASS_CLERIC) - { - vis->colormap = spritelights[MAXLIGHTSCALE - 1]; - if (viewplayer->powers[pw_invulnerability] > 4 * 32) - { - if (viewplayer->mo->flags2 & MF2_DONTDRAW) - { // don't draw the psprite - vis->mobjflags |= MF_SHADOW; - } - else if (viewplayer->mo->flags & MF_SHADOW) - { - vis->mobjflags |= MF_ALTSHADOW; - } - } - else if (viewplayer->powers[pw_invulnerability] & 8) - { - vis->mobjflags |= MF_SHADOW; - } - } - else if (fixedcolormap) - { - // Fixed color - vis->colormap = fixedcolormap; - } - else if (psp->state->frame & FF_FULLBRIGHT) - { - // Full bright - vis->colormap = colormaps; - } - else - { - // local light - vis->colormap = spritelights[MAXLIGHTSCALE - 1]; - } - R_DrawVisSprite(vis, vis->x1, vis->x2); -} - -/* -======================== -= -= R_DrawPlayerSprites -= -======================== -*/ - -void R_DrawPlayerSprites(void) -{ - int i, lightnum; - pspdef_t *psp; - -// -// get light level -// - lightnum = - (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + - extralight; - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS - 1]; - else - spritelights = scalelight[lightnum]; -// -// clip to screen bounds -// - mfloorclip = screenheightarray; - mceilingclip = negonearray; - -// -// add all active psprites -// - for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; i++, psp++) - if (psp->state) - R_DrawPSprite(psp); - -} - - -/* -======================== -= -= R_SortVisSprites -= -======================== -*/ - -vissprite_t vsprsortedhead; - -void R_SortVisSprites(void) -{ - int i, count; - vissprite_t *ds, *best; - static vissprite_t unsorted; - fixed_t bestscale; - - count = vissprite_p - vissprites; - - unsorted.next = unsorted.prev = &unsorted; - if (!count) - return; - - for (ds = vissprites; ds < vissprite_p; ds++) - { - ds->next = ds + 1; - ds->prev = ds - 1; - } - vissprites[0].prev = &unsorted; - unsorted.next = &vissprites[0]; - (vissprite_p - 1)->next = &unsorted; - unsorted.prev = vissprite_p - 1; - -// -// pull the vissprites out by scale -// - best = 0; // shut up the compiler warning - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i = 0; i < count; i++) - { - bestscale = INT_MAX; - for (ds = unsorted.next; ds != &unsorted; ds = ds->next) - { - if (ds->scale < bestscale) - { - bestscale = ds->scale; - best = ds; - } - } - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; - } -} - - - -/* -======================== -= -= R_DrawSprite -= -======================== -*/ - -void R_DrawSprite(vissprite_t * spr) -{ - drawseg_t *ds; - short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH]; - int x, r1, r2; - fixed_t scale, lowscale; - int silhouette; - - for (x = spr->x1; x <= spr->x2; x++) - clipbot[x] = cliptop[x] = -2; - -// -// scan drawsegs from end to start for obscuring segs -// the first drawseg that has a greater scale is the clip seg -// - for (ds = ds_p - 1; ds >= drawsegs; ds--) - { - // - // determine if the drawseg obscures the sprite - // - if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || - (!ds->silhouette && !ds->maskedtexturecol)) - continue; // doesn't cover sprite - - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->scale || (lowscale < spr->scale - && !R_PointOnSegSide(spr->gx, spr->gy, - ds->curline))) - { - if (ds->maskedtexturecol) // masked mid texture - R_RenderMaskedSegRange(ds, r1, r2); - continue; // seg is behind sprite - } - -// -// clip this piece of the sprite -// - silhouette = ds->silhouette; - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; - - if (silhouette == 1) - { // bottom sil - for (x = r1; x <= r2; x++) - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == 2) - { // top sil - for (x = r1; x <= r2; x++) - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == 3) - { // both - for (x = r1; x <= r2; x++) - { - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - } - - } - -// -// all clipping has been performed, so draw the sprite -// - -// check for unclipped columns - for (x = spr->x1; x <= spr->x2; x++) - { - if (clipbot[x] == -2) - clipbot[x] = viewheight; - if (cliptop[x] == -2) - cliptop[x] = -1; - } - - mfloorclip = clipbot; - mceilingclip = cliptop; - R_DrawVisSprite(spr, spr->x1, spr->x2); -} - - -/* -======================== -= -= R_DrawMasked -= -======================== -*/ - -void R_DrawMasked(void) -{ - vissprite_t *spr; - drawseg_t *ds; - - R_SortVisSprites(); - - if (vissprite_p > vissprites) - { - // draw all vissprites back to front - - for (spr = vsprsortedhead.next; spr != &vsprsortedhead; - spr = spr->next) - R_DrawSprite(spr); - } - -// -// render any remaining masked mid textures -// - for (ds = ds_p - 1; ds >= drawsegs; ds--) - if (ds->maskedtexturecol) - R_RenderMaskedSegRange(ds, ds->x1, ds->x2); - -// -// draw the psprites on top of everything -// -// Added for the sideviewing with an external device - if (viewangleoffset <= 1024 << ANGLETOFINESHIFT || viewangleoffset >= - -(1024 << ANGLETOFINESHIFT)) - { // don't draw on side views - R_DrawPlayerSprites(); - } - -// if (!viewangleoffset) // don't draw on side views -// R_DrawPlayerSprites (); -} diff --git a/games/NXDoom/src/hexen/s_sound.c b/games/NXDoom/src/hexen/s_sound.c deleted file mode 100644 index 33e62167189..00000000000 --- a/games/NXDoom/src/hexen/s_sound.c +++ /dev/null @@ -1,1014 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include "h2def.h" -#include "m_random.h" -#include "i_cdmus.h" -#include "i_sound.h" -#include "i_system.h" -#include "i_timer.h" -#include "m_argv.h" -#include "m_misc.h" -#include "r_local.h" -#include "p_local.h" // for P_AproxDistance -#include "sounds.h" -#include "s_sound.h" - -#define PRIORITY_MAX_ADJUST 10 -#define DIST_ADJUST (MAX_SND_DIST/PRIORITY_MAX_ADJUST) - -#define DEFAULT_ARCHIVEPATH "o:\\sound\\archive\\" - -void S_ShutDown(void); - -// If true, CD music playback is enabled (snd_musicdevice == SNDDEVICE_CD -// and CD initialization succeeded). -boolean cdmusic; - -// Track number of a track to play explicitly chosen by the -// player using cheats. A value of zero means no track chosen: -static int cd_custom_track = 0; - -// Currently playing track: -static int cd_current_track = 0; - -// Time (MS) at which the currently-playing CD track will finish playing -// and should be looped. Zero if we are not currently playing a track: -static int cd_track_end_time = 0; - -/* -=============================================================================== - - MUSIC & SFX API - -=============================================================================== -*/ - -//static channel_t channel[MAX_CHANNELS]; - -//static int rs; //the current registered song. -//int mus_song = -1; -//int mus_lumpnum; -//void *mus_sndptr; -//byte *soundCurve; - - -static channel_t Channel[MAX_CHANNELS]; -static void *RegisteredSong; //the current registered song. -static boolean MusicPaused; -static int Mus_Song = -1; -static byte *Mus_SndPtr; -static byte *SoundCurve; - -int snd_MaxVolume = 10; // maximum volume for sound -int snd_MusicVolume = 10; // maximum volume for music -int snd_Channels = 16; - -// int AmbChan; - -//========================================================================== -// -// S_Start -// -//========================================================================== - -void S_Start(void) -{ - S_StopAllSound(); - S_StartSong(gamemap, true); -} - -//========================================================================== -// -// Returns true if we are playing a looping CD track and it is time to -// restart it. -// -//========================================================================== - -static boolean ShouldRestartCDTrack(void) -{ - return cd_track_end_time != 0 && I_GetTimeMS() > cd_track_end_time; -} - -//========================================================================== -// -// Start playing a CD track. Returns true for success. -// -//========================================================================== - -static boolean StartCDTrack(int track, boolean loop) -{ - // Already playing? If so, don't bother. - - if (track == cd_current_track && !ShouldRestartCDTrack()) - { - return true; - } - - if (I_CDMusPlay(track)) - { - return false; - } - - cd_current_track = track; - - if (loop) - { - cd_track_end_time = I_GetTimeMS() + 1000 * I_CDMusTrackLength(track); - } - else - { - cd_track_end_time = 0; - } - - return true; -} - -//========================================================================== -// -// S_StartSong -// -//========================================================================== - -void S_StartSong(int song, boolean loop) -{ - char *songLump; - int lumpnum; - int length; - int track; - - // If we're in CD music mode, play a CD track, instead: - if (cdmusic) - { - // Default to the player-chosen track - if (cd_custom_track != 0) - { - track = cd_custom_track; - } - else - { - track = P_GetMapCDTrack(gamemap); - } - - StartCDTrack(track, loop); - } - else - { - if (song == Mus_Song) - { // don't replay an old song - return; - } - if (RegisteredSong) - { - I_StopSong(); - I_UnRegisterSong(RegisteredSong); - RegisteredSong = 0; - } - songLump = P_GetMapSongLump(song); - if (!songLump) - { - return; - } - - lumpnum = W_GetNumForName(songLump); - Mus_SndPtr = W_CacheLumpNum(lumpnum, PU_STATIC); - length = W_LumpLength(lumpnum); - - RegisteredSong = I_RegisterSong(Mus_SndPtr, length); - I_PlaySong(RegisteredSong, loop); - Mus_Song = song; - - W_ReleaseLumpNum(lumpnum); - } -} - -//========================================================================== -// -// Play a custom-chosen music track selected by the player. -// -// Returns true for success. -// -//========================================================================== - -boolean S_StartCustomCDTrack(int tracknum) -{ - boolean result; - - result = StartCDTrack(tracknum, true); - - if (result) - { - cd_custom_track = tracknum; - } - - return result; -} - -//========================================================================== -// -// Get the currently-playing CD track; returns -1 if not playing. -// -//========================================================================== - -int S_GetCurrentCDTrack(void) -{ - if (!cdmusic || cd_current_track == 0) - { - return -1; - } - - return cd_current_track; -} - -//========================================================================== -// -// S_StartSongName -// -//========================================================================== - -void S_StartSongName(const char *songLump, boolean loop) -{ - int lumpnum; - int cdTrack; - int length; - - if (!songLump) - { - return; - } - if (cdmusic) - { - cdTrack = 0; - - if (!strcmp(songLump, "hexen")) - { - cdTrack = P_GetCDTitleTrack(); - } - else if (!strcmp(songLump, "hub")) - { - cdTrack = P_GetCDIntermissionTrack(); - } - else if (!strcmp(songLump, "hall")) - { - cdTrack = P_GetCDEnd1Track(); - } - else if (!strcmp(songLump, "orb")) - { - cdTrack = P_GetCDEnd2Track(); - } - else if (!strcmp(songLump, "chess") && cd_custom_track == 0) - { - cdTrack = P_GetCDEnd3Track(); - } -/* Uncomment this, if Kevin writes a specific song for startup - else if(!strcmp(songLump, "start")) - { - cdTrack = P_GetCDStartTrack(); - } -*/ - if (cdTrack != 0) - { - cd_custom_track = 0; - StartCDTrack(cdTrack, loop); - } - } - else - { - if (RegisteredSong) - { - I_StopSong(); - I_UnRegisterSong(RegisteredSong); - RegisteredSong = NULL; - } - - lumpnum = W_GetNumForName(songLump); - Mus_SndPtr = W_CacheLumpNum(lumpnum, PU_MUSIC); - length = W_LumpLength(lumpnum); - - RegisteredSong = I_RegisterSong(Mus_SndPtr, length); - I_PlaySong(RegisteredSong, loop); - W_ReleaseLumpNum(lumpnum); - Mus_Song = -1; - } -} - -//========================================================================== -// -// S_GetSoundID -// -//========================================================================== - -int S_GetSoundID(char *name) -{ - int i; - - for (i = 0; i < NUMSFX; i++) - { - if (!strcmp(S_sfx[i].tagname, name)) - { - return i; - } - } - return 0; -} - -//========================================================================== -// -// S_StartSound -// -//========================================================================== - -void S_StartSound(mobj_t * origin, int sound_id) -{ - S_StartSoundAtVolume(origin, sound_id, 127); -} - -static mobj_t *GetSoundListener(void) -{ - static degenmobj_t dummy_listener; - - // If we are at the title screen, the console player doesn't have an - // object yet, so return a pointer to a static dummy listener instead. - - if (players[displayplayer].mo != NULL) - { - return players[displayplayer].mo; - } - else - { - dummy_listener.x = 0; - dummy_listener.y = 0; - dummy_listener.z = 0; - - return (mobj_t *) &dummy_listener; - } -} - -//========================================================================== -// -// S_StartSoundAtVolume -// -//========================================================================== - -void S_StartSoundAtVolume(mobj_t * origin, int sound_id, int volume) -{ - mobj_t *listener; - int dist, vol; - int i; - int priority; - int sep; - int angle; - int absx; - int absy; - - static int sndcount = 0; - int chan; - - if (sound_id == 0 || snd_MaxVolume == 0) - return; - - listener = GetSoundListener(); - - if (origin == NULL) - { - origin = listener; - } - if (volume == 0) - { - return; - } - - // calculate the distance before other stuff so that we can throw out - // sounds that are beyond the hearing range. - absx = abs(origin->x - listener->x); - absy = abs(origin->y - listener->y); - dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); - dist >>= FRACBITS; - if (dist >= MAX_SND_DIST) - { - return; // sound is beyond the hearing range... - } - if (dist < 0) - { - dist = 0; - } - priority = S_sfx[sound_id].priority; - priority *= (PRIORITY_MAX_ADJUST - (dist / DIST_ADJUST)); - #if 0 - // TODO - if (!S_StopSoundID(sound_id, priority)) - { - return; // other sounds have greater priority - } - #endif - for (i = 0; i < snd_Channels; i++) - { - // The origin pointer may point to an object of type degenmobj_t - // (i.e. sector_t.soundorg and polyobj_t.startSpot) which does not have - // a player element. Thus the origin->player pointer may point to - // random memory which most likely evaluates to true. - if (origin->thinker.function == P_DegenMobjThinker || origin->player) - { - i = snd_Channels; - break; // let the player have more than one sound. - } - if (origin == Channel[i].mo) - { // only allow other mobjs one sound - S_StopSound(Channel[i].mo); - break; - } - } - if (i >= snd_Channels) - { - for (i = 0; i < snd_Channels; i++) - { - if (Channel[i].mo == NULL) - { - break; - } - } - if (i >= snd_Channels) - { - // look for a lower priority sound to replace. - sndcount++; - if (sndcount >= snd_Channels) - { - sndcount = 0; - } - for (chan = 0; chan < snd_Channels; chan++) - { - i = (sndcount + chan) % snd_Channels; - if (priority >= Channel[i].priority) - { - chan = -1; //denote that sound should be replaced. - break; - } - } - if (chan != -1) - { - return; //no free channels. - } - else //replace the lower priority sound. - { - if (Channel[i].handle) - { - if (I_SoundIsPlaying(Channel[i].handle)) - { - I_StopSound(Channel[i].handle); - } - if (S_sfx[Channel[i].sound_id].usefulness > 0) - { - S_sfx[Channel[i].sound_id].usefulness--; - } - } - } - } - } - - Channel[i].mo = origin; - - vol = (SoundCurve[dist] * (snd_MaxVolume * 8) * volume) >> 14; - if (origin == listener) - { - sep = 128; -// vol = (volume*(snd_MaxVolume+1)*8)>>7; - } - else - { - angle = R_PointToAngle2(listener->x, - listener->y, - Channel[i].mo->x, Channel[i].mo->y); - angle = (angle - viewangle) >> 24; - sep = angle * 2 - 128; - if (sep < 64) - sep = -sep; - if (sep > 192) - sep = 512 - sep; -// vol = SoundCurve[dist]; - } - - // if the sfxinfo_t is marked as 'can be pitch shifted' - if (S_sfx[sound_id].pitch) - { - Channel[i].pitch = (byte) (NORM_PITCH + (M_Random() & 7) - (M_Random() & 7)); - } - else - { - Channel[i].pitch = NORM_PITCH; - } - - if (S_sfx[sound_id].lumpnum == 0) - { - S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]); - } - - Channel[i].handle = I_StartSound(&S_sfx[sound_id], - i, - vol, - sep, - Channel[i].pitch); - Channel[i].sound_id = sound_id; - Channel[i].priority = priority; - Channel[i].volume = volume; - if (S_sfx[sound_id].usefulness < 0) - { - S_sfx[sound_id].usefulness = 1; - } - else - { - S_sfx[sound_id].usefulness++; - } -} - -//========================================================================== -// -// S_StopSoundID -// -//========================================================================== - -boolean S_StopSoundID(int sound_id, int priority) -{ - int i; - int lp; //least priority - int found; - - if (S_sfx[sound_id].numchannels == -1) - { - return (true); - } - lp = -1; //denote the argument sound_id - found = 0; - for (i = 0; i < snd_Channels; i++) - { - if (Channel[i].sound_id == sound_id && Channel[i].mo) - { - found++; //found one. Now, should we replace it?? - if (priority >= Channel[i].priority) - { // if we're gonna kill one, then this'll be it - lp = i; - priority = Channel[i].priority; - } - } - } - if (found < S_sfx[sound_id].numchannels) - { - return (true); - } - else if (lp == -1) - { - return (false); // don't replace any sounds - } - if (Channel[lp].handle) - { - if (I_SoundIsPlaying(Channel[lp].handle)) - { - I_StopSound(Channel[lp].handle); - } - if (S_sfx[Channel[lp].sound_id].usefulness > 0) - { - S_sfx[Channel[lp].sound_id].usefulness--; - } - Channel[lp].mo = NULL; - } - return (true); -} - -//========================================================================== -// -// S_StopSound -// -//========================================================================== - -void S_StopSound(mobj_t * origin) -{ - int i; - - for (i = 0; i < snd_Channels; i++) - { - if (Channel[i].mo == origin) - { - I_StopSound(Channel[i].handle); - if (S_sfx[Channel[i].sound_id].usefulness > 0) - { - S_sfx[Channel[i].sound_id].usefulness--; - } - Channel[i].handle = 0; - Channel[i].mo = NULL; - } - } -} - -//========================================================================== -// -// S_StopAllSound -// -//========================================================================== - -void S_StopAllSound(void) -{ - int i; - - //stop all sounds - for (i = 0; i < snd_Channels; i++) - { - if (Channel[i].handle) - { - S_StopSound(Channel[i].mo); - } - } - memset(Channel, 0, 8 * sizeof(channel_t)); -} - -//========================================================================== -// -// S_SoundLink -// -//========================================================================== - -void S_SoundLink(mobj_t * oldactor, mobj_t * newactor) -{ - int i; - - for (i = 0; i < snd_Channels; i++) - { - if (Channel[i].mo == oldactor) - Channel[i].mo = newactor; - } -} - -//========================================================================== -// -// S_PauseSound -// -//========================================================================== - -void S_PauseSound(void) -{ - if (cdmusic) - { - I_CDMusStop(); - } - else - { - I_PauseSong(); - } -} - -//========================================================================== -// -// S_ResumeSound -// -//========================================================================== - -void S_ResumeSound(void) -{ - if (cdmusic) - { - I_CDMusResume(); - } - else - { - I_ResumeSong(); - } -} - -//========================================================================== -// -// S_UpdateSounds -// -//========================================================================== - -void S_UpdateSounds(mobj_t * listener) -{ - int i, dist, vol; - int angle; - int sep; - int priority; - int absx; - int absy; - - I_UpdateSound(); - - // If we are looping a CD track, we need to check if it has - // finished playing and needs to restart. - if (cdmusic && ShouldRestartCDTrack()) - { - StartCDTrack(cd_current_track, true); - } - - if (snd_MaxVolume == 0) - { - return; - } - - // Update any Sequences - SN_UpdateActiveSequences(); - - for (i = 0; i < snd_Channels; i++) - { - if (!Channel[i].handle || S_sfx[Channel[i].sound_id].usefulness == -1) - { - continue; - } - if (!I_SoundIsPlaying(Channel[i].handle)) - { - if (S_sfx[Channel[i].sound_id].usefulness > 0) - { - S_sfx[Channel[i].sound_id].usefulness--; - } - Channel[i].handle = 0; - Channel[i].mo = NULL; - Channel[i].sound_id = 0; - } - if (Channel[i].mo == NULL || Channel[i].sound_id == 0 - || Channel[i].mo == listener || listener == NULL) - { - continue; - } - else - { - absx = abs(Channel[i].mo->x - listener->x); - absy = abs(Channel[i].mo->y - listener->y); - dist = absx + absy - (absx > absy ? absy >> 1 : absx >> 1); - dist >>= FRACBITS; - - if (dist >= MAX_SND_DIST) - { - S_StopSound(Channel[i].mo); - continue; - } - if (dist < 0) - { - dist = 0; - } - //vol = SoundCurve[dist]; - vol = - (SoundCurve[dist] * (snd_MaxVolume * 8) * - Channel[i].volume) >> 14; - if (Channel[i].mo == listener) - { - sep = 128; - } - else - { - angle = R_PointToAngle2(listener->x, listener->y, - Channel[i].mo->x, Channel[i].mo->y); - angle = (angle - viewangle) >> 24; - sep = angle * 2 - 128; - if (sep < 64) - sep = -sep; - if (sep > 192) - sep = 512 - sep; - } - I_UpdateSoundParams(i, vol, sep); - priority = S_sfx[Channel[i].sound_id].priority; - priority *= PRIORITY_MAX_ADJUST - (dist / DIST_ADJUST); - Channel[i].priority = priority; - } - } -} - -//========================================================================== -// -// S_Init -// -//========================================================================== - -void S_Init(void) -{ - I_SetOPLDriverVer(opl_doom2_1_666); - SoundCurve = W_CacheLumpName("SNDCURVE", PU_STATIC); -// SoundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL); - - if (snd_Channels > 8) - { - snd_Channels = 8; - } - I_SetMusicVolume(snd_MusicVolume * 8); - - I_AtExit(S_ShutDown, true); - - // Hexen defaults to pitch-shifting on - if (snd_pitchshift == -1) - { - snd_pitchshift = 1; - } - - I_PrecacheSounds(S_sfx, NUMSFX); - - // Attempt to setup CD music - if (snd_musicdevice == SNDDEVICE_CD) - { - ST_Message(" Attempting to initialize CD Music: "); - if (!cdrom) - { - cdmusic = (I_CDMusInit() != -1); - } - else - { - // The user is trying to use the cdrom for both game and music - cdmusic = false; - } - - if (cdmusic) - { - ST_Message("initialized.\n"); - } - else - { - ST_Message("failed.\n"); - } - - I_CDMusPrintStartup(); - } -} - -//========================================================================== -// -// S_GetChannelInfo -// -//========================================================================== - -void S_GetChannelInfo(SoundInfo_t * s) -{ - int i; - ChanInfo_t *c; - - s->channelCount = snd_Channels; - s->musicVolume = snd_MusicVolume; - s->soundVolume = snd_MaxVolume; - for (i = 0; i < snd_Channels; i++) - { - c = &s->chan[i]; - c->id = Channel[i].sound_id; - c->priority = Channel[i].priority; - c->name = S_sfx[c->id].name; - c->mo = Channel[i].mo; - - if (c->mo != NULL) - { - c->distance = P_AproxDistance(c->mo->x - viewx, c->mo->y - viewy) - >> FRACBITS; - } - else - { - c->distance = 0; - } - } -} - -//========================================================================== -// -// S_GetSoundPlayingInfo -// -//========================================================================== - -boolean S_GetSoundPlayingInfo(mobj_t * mobj, int sound_id) -{ - int i; - - for (i = 0; i < snd_Channels; i++) - { - if (Channel[i].sound_id == sound_id && Channel[i].mo == mobj) - { - if (I_SoundIsPlaying(Channel[i].handle)) - { - return true; - } - } - } - return false; -} - -//========================================================================== -// -// S_SetMusicVolume -// -//========================================================================== - -void S_SetMusicVolume(void) -{ - if (cdmusic) - { - I_CDMusSetVolume(snd_MusicVolume * 16); // 0-255 - } - else - { - I_SetMusicVolume(snd_MusicVolume * 8); - } - if (snd_MusicVolume == 0) - { - if (!cdmusic) - { - I_PauseSong(); - } - MusicPaused = true; - } - else if (MusicPaused) - { - if (!cdmusic) - { - I_ResumeSong(); - } - MusicPaused = false; - } -} - -//========================================================================== -// -// S_ShutDown -// -//========================================================================== - -void S_ShutDown(void) -{ - I_StopSong(); - I_UnRegisterSong(RegisteredSong); - I_ShutdownSound(); - if (cdmusic) - { - I_CDMusStop(); - } -} - -//========================================================================== -// -// S_InitScript -// -//========================================================================== - -void S_InitScript(void) -{ - int i; - - SC_OpenLump("sndinfo"); - - while (SC_GetString()) - { - if (*sc_String == '$') - { - if (!strcasecmp(sc_String, "$ARCHIVEPATH")) - { - SC_MustGetString(); - } - else if (!strcasecmp(sc_String, "$MAP")) - { - SC_MustGetNumber(); - SC_MustGetString(); - if (sc_Number) - { - P_PutMapSongLump(sc_Number, sc_String); - } - } - continue; - } - else - { - for (i = 0; i < NUMSFX; i++) - { - if (!strcmp(S_sfx[i].tagname, sc_String)) - { - SC_MustGetString(); - if (*sc_String != '?') - { - M_StringCopy(S_sfx[i].name, sc_String, - sizeof(S_sfx[i].name)); - } - else - { - M_StringCopy(S_sfx[i].name, "default", - sizeof(S_sfx[i].name)); - } - break; - } - } - if (i == NUMSFX) - { - SC_MustGetString(); - } - } - } - SC_Close(); - - for (i = 0; i < NUMSFX; i++) - { - if (!strcmp(S_sfx[i].name, "")) - { - M_StringCopy(S_sfx[i].name, "default", sizeof(S_sfx[i].name)); - } - } -} - diff --git a/games/NXDoom/src/hexen/s_sound.h b/games/NXDoom/src/hexen/s_sound.h deleted file mode 100644 index f8284be7787..00000000000 --- a/games/NXDoom/src/hexen/s_sound.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __S_SOUND__ -#define __S_SOUND__ - -/* -typedef struct -{ - char name[8]; - int p1; -} musicinfo_t; -*/ - -/* -typedef struct sfxinfo_s -{ - char tagName[32]; - char lumpname[12]; // Only need 9 bytes, but padded out to be dword aligned - //struct sfxinfo_s *link; // Make alias for another sound - int priority; // Higher priority takes precendence - int usefulness; // Determines when a sound should be cached out - void *snd_ptr; - int lumpnum; - int numchannels; // total number of channels a sound type may occupy - boolean changePitch; -} sfxinfo_t; -*/ - -typedef struct -{ - mobj_t *mo; - int sound_id; - int handle; - int volume; - int pitch; - int priority; -} channel_t; - -typedef struct -{ - int id; - unsigned short priority; - char *name; - mobj_t *mo; - int distance; -} ChanInfo_t; - -typedef struct -{ - int channelCount; - int musicVolume; - int soundVolume; - ChanInfo_t chan[8]; -} SoundInfo_t; - -extern int snd_MaxVolume; -extern int snd_MusicVolume; -extern int snd_Channels; -extern boolean cdmusic; - -void S_Start(void); -void S_StartSound(mobj_t * origin, int sound_id); -int S_GetSoundID(char *name); -void S_StartSoundAtVolume(mobj_t * origin, int sound_id, int volume); -void S_StopSound(mobj_t * origin); -void S_StopAllSound(void); -void S_PauseSound(void); -void S_ResumeSound(void); -void S_UpdateSounds(mobj_t * listener); -void S_StartSong(int song, boolean loop); -void S_StartSongName(const char *songLump, boolean loop); -void S_Init(void); -void S_GetChannelInfo(SoundInfo_t * s); -void S_SetMusicVolume(void); -boolean S_GetSoundPlayingInfo(mobj_t * mobj, int sound_id); -boolean S_StartCustomCDTrack(int tracknum); -int S_GetCurrentCDTrack(void); - -#endif diff --git a/games/NXDoom/src/hexen/sb_bar.c b/games/NXDoom/src/hexen/sb_bar.c deleted file mode 100644 index fa94d59a3a1..00000000000 --- a/games/NXDoom/src/hexen/sb_bar.c +++ /dev/null @@ -1,2000 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "i_cdmus.h" -#include "i_video.h" -#include "m_bbox.h" -#include "m_cheat.h" -#include "m_misc.h" -#include "p_local.h" -#include "s_sound.h" -#include "v_video.h" -#include "i_swap.h" -#include "am_map.h" - - -// TYPES ------------------------------------------------------------------- - -typedef struct Cheat_s -{ - void (*func) (player_t * player, struct Cheat_s * cheat); - cheatseq_t *seq; -} Cheat_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void DrawSoundInfo(void); -static void DrINumber(signed int val, int x, int y); -static void DrRedINumber(signed int val, int x, int y); -static void DrBNumber(signed int val, int x, int y); -static void DrawCommonBar(void); -static void DrawMainBar(void); -static void DrawInventoryBar(void); -static void DrawKeyBar(void); -static void DrawWeaponPieces(void); -static void DrawFullScreenStuff(void); -static void DrawAnimatedIcons(void); -static boolean HandleCheats(byte key); -static boolean CheatAddKey(Cheat_t * cheat, byte key, boolean * eat); -static void CheatGodFunc(player_t * player, Cheat_t * cheat); -static void CheatNoClipFunc(player_t * player, Cheat_t * cheat); -static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat); -static void CheatHealthFunc(player_t * player, Cheat_t * cheat); -static void CheatKeysFunc(player_t * player, Cheat_t * cheat); -static void CheatSoundFunc(player_t * player, Cheat_t * cheat); -static void CheatTickerFunc(player_t * player, Cheat_t * cheat); -static void CheatArtifactAllFunc(player_t * player, Cheat_t * cheat); -static void CheatPuzzleFunc(player_t * player, Cheat_t * cheat); -static void CheatWarpFunc(player_t * player, Cheat_t * cheat); -static void CheatPigFunc(player_t * player, Cheat_t * cheat); -static void CheatMassacreFunc(player_t * player, Cheat_t * cheat); -static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat); -static void CheatQuickenFunc1(player_t * player, Cheat_t * cheat); -static void CheatQuickenFunc2(player_t * player, Cheat_t * cheat); -static void CheatQuickenFunc3(player_t * player, Cheat_t * cheat); -static void CheatClassFunc1(player_t * player, Cheat_t * cheat); -static void CheatClassFunc2(player_t * player, Cheat_t * cheat); -static void CheatInitFunc(player_t * player, Cheat_t * cheat); -static void CheatVersionFunc(player_t * player, Cheat_t * cheat); -static void CheatDebugFunc(player_t * player, Cheat_t * cheat); -static void CheatScriptFunc1(player_t * player, Cheat_t * cheat); -static void CheatScriptFunc2(player_t * player, Cheat_t * cheat); -static void CheatScriptFunc3(player_t * player, Cheat_t * cheat); -static void CheatRevealFunc(player_t * player, Cheat_t * cheat); -static void CheatTrackFunc1(player_t * player, Cheat_t * cheat); -static void CheatTrackFunc2(player_t * player, Cheat_t * cheat); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DECLARATIONS ------------------------------------------------ - -boolean DebugSound; // Debug flag for displaying sound info -boolean inventory; -int curpos; -int inv_ptr; -int ArtifactFlash; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int DisplayTicker = 0; -static int HealthMarker; -//static int ChainWiggle; -static player_t *CPlayer; -static int SpinFlylump; -static int SpinMinotaurLump; -static int SpinSpeedLump; -static int SpinDefenseLump; - -static int FontBNumBase; -static int PlayPalette; - -static patch_t *PatchH2BAR; -static patch_t *PatchH2TOP; -static patch_t *PatchLFEDGE; -static patch_t *PatchRTEDGE; -static patch_t *PatchARMCLEAR; -static patch_t *PatchARTICLEAR; -static patch_t *PatchMANACLEAR; -static patch_t *PatchKILLS; -static patch_t *PatchMANAVIAL1; -static patch_t *PatchMANAVIAL2; -static patch_t *PatchMANAVIALDIM1; -static patch_t *PatchMANAVIALDIM2; -static patch_t *PatchMANADIM1; -static patch_t *PatchMANADIM2; -static patch_t *PatchMANABRIGHT1; -static patch_t *PatchMANABRIGHT2; -static patch_t *PatchCHAIN; -static patch_t *PatchSTATBAR; -static patch_t *PatchKEYBAR; -static patch_t *PatchLIFEGEM; -static patch_t *PatchSELECTBOX; -static patch_t *PatchINumbers[10]; -static patch_t *PatchNEGATIVE; -static patch_t *PatchSmNumbers[10]; -static patch_t *PatchINVBAR; -static patch_t *PatchWEAPONSLOT; -static patch_t *PatchWEAPONFULL; -static patch_t *PatchPIECE1; -static patch_t *PatchPIECE2; -static patch_t *PatchPIECE3; -static patch_t *PatchINVLFGEM1; -static patch_t *PatchINVLFGEM2; -static patch_t *PatchINVRTGEM1; -static patch_t *PatchINVRTGEM2; - -// Toggle god mode -cheatseq_t CheatGodSeq = CHEAT("satan", 0); - -// Toggle no clipping mode -cheatseq_t CheatNoClipSeq = CHEAT("casper", 0); - -// Get all weapons and mana -cheatseq_t CheatWeaponsSeq = CHEAT("nra", 0); - -// Get full health -cheatseq_t CheatHealthSeq = CHEAT("clubmed", 0); - -// Get all keys -cheatseq_t CheatKeysSeq = CHEAT("locksmith", 0); - -// Toggle sound debug info -cheatseq_t CheatSoundSeq = CHEAT("noise", 0); - -// Toggle ticker -cheatseq_t CheatTickerSeq = CHEAT("ticker", 0); - -// Get all artifacts -cheatseq_t CheatArtifactAllSeq = CHEAT("indiana", 0); - -// Get all puzzle pieces -cheatseq_t CheatPuzzleSeq = CHEAT("sherlock", 0); - -// Warp to new level -cheatseq_t CheatWarpSeq = CHEAT("visit", 2); - -// Become a pig -cheatseq_t CheatPigSeq = CHEAT("deliverance", 0); - -// Kill all monsters -cheatseq_t CheatMassacreSeq = CHEAT("butcher", 0); - -cheatseq_t CheatIDKFASeq = CHEAT("conan", 0); - -cheatseq_t CheatQuickenSeq1 = CHEAT("martek", 0); - -cheatseq_t CheatQuickenSeq2 = CHEAT("martekmartek", 0); - -cheatseq_t CheatQuickenSeq3 = CHEAT("martekmartekmartek", 0); - -// New class -cheatseq_t CheatClass1Seq = CHEAT("shadowcaster", 0); - -cheatseq_t CheatClass2Seq = CHEAT("shadowcaster", 1); - -cheatseq_t CheatInitSeq = CHEAT("init", 0); - -cheatseq_t CheatVersionSeq = CHEAT("mrjones", 0); - -cheatseq_t CheatDebugSeq = CHEAT("where", 0); - -cheatseq_t CheatScriptSeq1 = CHEAT("puke", 0); - -cheatseq_t CheatScriptSeq2 = CHEAT("puke", 1); - -cheatseq_t CheatScriptSeq3 = CHEAT("puke", 2); - -cheatseq_t CheatRevealSeq = CHEAT("mapsco", 0); - -cheatseq_t CheatTrackSeq1 = CHEAT("`", 0); - -cheatseq_t CheatTrackSeq2 = CHEAT("`", 2); - -static Cheat_t Cheats[] = { - {CheatTrackFunc1, &CheatTrackSeq1}, - {CheatTrackFunc2, &CheatTrackSeq2}, - {CheatGodFunc, &CheatGodSeq}, - {CheatNoClipFunc, &CheatNoClipSeq}, - {CheatWeaponsFunc, &CheatWeaponsSeq}, - {CheatHealthFunc, &CheatHealthSeq}, - {CheatKeysFunc, &CheatKeysSeq}, - {CheatSoundFunc, &CheatSoundSeq}, - {CheatTickerFunc, &CheatTickerSeq}, - {CheatArtifactAllFunc, &CheatArtifactAllSeq}, - {CheatPuzzleFunc, &CheatPuzzleSeq}, - {CheatWarpFunc, &CheatWarpSeq}, - {CheatPigFunc, &CheatPigSeq}, - {CheatMassacreFunc, &CheatMassacreSeq}, - {CheatIDKFAFunc, &CheatIDKFASeq}, - {CheatQuickenFunc1, &CheatQuickenSeq1}, - {CheatQuickenFunc2, &CheatQuickenSeq2}, - {CheatQuickenFunc3, &CheatQuickenSeq3}, - {CheatClassFunc1, &CheatClass1Seq}, - {CheatClassFunc2, &CheatClass2Seq}, - {CheatInitFunc, &CheatInitSeq}, - {CheatVersionFunc, &CheatVersionSeq}, - {CheatDebugFunc, &CheatDebugSeq}, - {CheatScriptFunc1, &CheatScriptSeq1}, - {CheatScriptFunc2, &CheatScriptSeq2}, - {CheatScriptFunc3, &CheatScriptSeq3}, - {CheatRevealFunc, &CheatRevealSeq}, -}; - -#define SET_CHEAT(cheat, seq) \ - { memcpy(cheat.sequence, seq, sizeof(seq)); \ - cheat.sequence_len = sizeof(seq) - 1; } - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// SB_Init -// -//========================================================================== - -void SB_Init(void) -{ - int i; - int startLump; - - PatchH2BAR = W_CacheLumpName("H2BAR", PU_STATIC); - PatchH2TOP = W_CacheLumpName("H2TOP", PU_STATIC); - PatchINVBAR = W_CacheLumpName("INVBAR", PU_STATIC); - PatchLFEDGE = W_CacheLumpName("LFEDGE", PU_STATIC); - PatchRTEDGE = W_CacheLumpName("RTEDGE", PU_STATIC); - PatchSTATBAR = W_CacheLumpName("STATBAR", PU_STATIC); - PatchKEYBAR = W_CacheLumpName("KEYBAR", PU_STATIC); - PatchSELECTBOX = W_CacheLumpName("SELECTBOX", PU_STATIC); - PatchARTICLEAR = W_CacheLumpName("ARTICLS", PU_STATIC); - PatchARMCLEAR = W_CacheLumpName("ARMCLS", PU_STATIC); - PatchMANACLEAR = W_CacheLumpName("MANACLS", PU_STATIC); - PatchMANAVIAL1 = W_CacheLumpName("MANAVL1", PU_STATIC); - PatchMANAVIAL2 = W_CacheLumpName("MANAVL2", PU_STATIC); - PatchMANAVIALDIM1 = W_CacheLumpName("MANAVL1D", PU_STATIC); - PatchMANAVIALDIM2 = W_CacheLumpName("MANAVL2D", PU_STATIC); - PatchMANADIM1 = W_CacheLumpName("MANADIM1", PU_STATIC); - PatchMANADIM2 = W_CacheLumpName("MANADIM2", PU_STATIC); - PatchMANABRIGHT1 = W_CacheLumpName("MANABRT1", PU_STATIC); - PatchMANABRIGHT2 = W_CacheLumpName("MANABRT2", PU_STATIC); - PatchINVLFGEM1 = W_CacheLumpName("invgeml1", PU_STATIC); - PatchINVLFGEM2 = W_CacheLumpName("invgeml2", PU_STATIC); - PatchINVRTGEM1 = W_CacheLumpName("invgemr1", PU_STATIC); - PatchINVRTGEM2 = W_CacheLumpName("invgemr2", PU_STATIC); - -// PatchCHAINBACK = W_CacheLumpName("CHAINBACK", PU_STATIC); - startLump = W_GetNumForName("IN0"); - for (i = 0; i < 10; i++) - { - PatchINumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); - } - PatchNEGATIVE = W_CacheLumpName("NEGNUM", PU_STATIC); - FontBNumBase = W_GetNumForName("FONTB16"); - startLump = W_GetNumForName("SMALLIN0"); - for (i = 0; i < 10; i++) - { - PatchSmNumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC); - } - PlayPalette = W_GetNumForName("PLAYPAL"); - SpinFlylump = W_GetNumForName("SPFLY0"); - SpinMinotaurLump = W_GetNumForName("SPMINO0"); - SpinSpeedLump = W_GetNumForName("SPBOOT0"); - SpinDefenseLump = W_GetNumForName("SPSHLD0"); - - if (deathmatch) - { - PatchKILLS = W_CacheLumpName("KILLS", PU_STATIC); - } - SB_SetClassData(); - - if (gamemode == shareware) - { - SET_CHEAT(CheatGodSeq, "bgokey"); - SET_CHEAT(CheatNoClipSeq, "rjohnson"); - SET_CHEAT(CheatWeaponsSeq, "crhinehart"); - SET_CHEAT(CheatHealthSeq,"sgurno"); - SET_CHEAT(CheatKeysSeq, "mraymondjudy"); - SET_CHEAT(CheatSoundSeq, "kschilder"); - SET_CHEAT(CheatTickerSeq, "rrettenmund"); - SET_CHEAT(CheatArtifactAllSeq, "braffel"); - SET_CHEAT(CheatPuzzleSeq, "tmoore"); - SET_CHEAT(CheatWarpSeq, "bpelletier"); - SET_CHEAT(CheatPigSeq, "ebiessman"); - SET_CHEAT(CheatMassacreSeq, "cstika"); - SET_CHEAT(CheatIDKFASeq, "rambo"); - SET_CHEAT(CheatQuickenSeq1, "quicken"); - SET_CHEAT(CheatQuickenSeq2, "quickenquicken"); - SET_CHEAT(CheatQuickenSeq3, "quickenquickenquicken"); - SET_CHEAT(CheatClass1Seq, "plipo"); - SET_CHEAT(CheatClass2Seq, "plipo"); - SET_CHEAT(CheatVersionSeq, "pmacarther"); - SET_CHEAT(CheatDebugSeq, "jsumwalt"); - SET_CHEAT(CheatScriptSeq1, "mwagabaza"); - SET_CHEAT(CheatScriptSeq2, "mwagabaza"); - SET_CHEAT(CheatScriptSeq3, "mwagabaza"); - SET_CHEAT(CheatRevealSeq, "reveal"); - } -} - -//========================================================================== -// -// SB_SetClassData -// -//========================================================================== - -void SB_SetClassData(void) -{ - int class; - - class = PlayerClass[consoleplayer]; // original player class (not pig) - PatchWEAPONSLOT = W_CacheLumpNum(W_GetNumForName("wpslot0") - + class, PU_STATIC); - PatchWEAPONFULL = W_CacheLumpNum(W_GetNumForName("wpfull0") - + class, PU_STATIC); - PatchPIECE1 = W_CacheLumpNum(W_GetNumForName("wpiecef1") - + class, PU_STATIC); - PatchPIECE2 = W_CacheLumpNum(W_GetNumForName("wpiecef2") - + class, PU_STATIC); - PatchPIECE3 = W_CacheLumpNum(W_GetNumForName("wpiecef3") - + class, PU_STATIC); - PatchCHAIN = W_CacheLumpNum(W_GetNumForName("chain") + class, PU_STATIC); - if (!netgame) - { // single player game uses red life gem (the second gem) - PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("lifegem") - + maxplayers * class + 1, PU_STATIC); - } - else - { - PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("lifegem") - + maxplayers * class + consoleplayer, - PU_STATIC); - } - SB_state = -1; - UpdateState |= I_FULLSCRN; -} - -//========================================================================== -// -// SB_Ticker -// -//========================================================================== - -void SB_Ticker(void) -{ - int delta; - int curHealth; - - curHealth = players[consoleplayer].mo->health; - if (curHealth < 0) - { - curHealth = 0; - } - if (curHealth < HealthMarker) - { - delta = (HealthMarker - curHealth) >> 2; - if (delta < 1) - { - delta = 1; - } - else if (delta > 6) - { - delta = 6; - } - HealthMarker -= delta; - } - else if (curHealth > HealthMarker) - { - delta = (curHealth - HealthMarker) >> 2; - if (delta < 1) - { - delta = 1; - } - else if (delta > 6) - { - delta = 6; - } - HealthMarker += delta; - } -} - -//========================================================================== -// -// DrINumber -// -// Draws a three digit number. -// -//========================================================================== - -static void DrINumber(signed int val, int x, int y) -{ - patch_t *patch; - int oldval; - - oldval = val; - if (val < 0) - { - val = -val; - if (val > 99) - { - val = 99; - } - if (val > 9) - { - patch = PatchINumbers[val / 10]; - V_DrawPatch(x + 8, y, patch); - V_DrawPatch(x, y, PatchNEGATIVE); - } - else - { - V_DrawPatch(x + 8, y, PatchNEGATIVE); - } - val = val % 10; - patch = PatchINumbers[val]; - V_DrawPatch(x + 16, y, patch); - return; - } - if (val > 99) - { - patch = PatchINumbers[val / 100]; - V_DrawPatch(x, y, patch); - } - val = val % 100; - if (val > 9 || oldval > 99) - { - patch = PatchINumbers[val / 10]; - V_DrawPatch(x + 8, y, patch); - } - val = val % 10; - patch = PatchINumbers[val]; - V_DrawPatch(x + 16, y, patch); -} - -//========================================================================== -// -// DrRedINumber -// -// Draws a three digit number using the red font -// -//========================================================================== - -static void DrRedINumber(signed int val, int x, int y) -{ - patch_t *patch; - int oldval; - - oldval = val; - if (val < 0) - { - val = 0; - } - if (val > 99) - { - patch = - W_CacheLumpNum(W_GetNumForName("inred0") + val / 100, PU_CACHE); - V_DrawPatch(x, y, patch); - } - val = val % 100; - if (val > 9 || oldval > 99) - { - patch = - W_CacheLumpNum(W_GetNumForName("inred0") + val / 10, PU_CACHE); - V_DrawPatch(x + 8, y, patch); - } - val = val % 10; - patch = W_CacheLumpNum(W_GetNumForName("inred0") + val, PU_CACHE); - V_DrawPatch(x + 16, y, patch); -} - -//========================================================================== -// -// DrBNumber -// -// Draws a three digit number using FontB -// -//========================================================================== - -static void DrBNumber(signed int val, int x, int y) -{ - patch_t *patch; - int xpos; - int oldval; - - oldval = val; - xpos = x; - if (val < 0) - { - val = 0; - } - if (val > 99) - { - patch = W_CacheLumpNum(FontBNumBase + val / 100, PU_CACHE); - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - } - val = val % 100; - xpos += 12; - if (val > 9 || oldval > 99) - { - patch = W_CacheLumpNum(FontBNumBase + val / 10, PU_CACHE); - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); - } - val = val % 10; - xpos += 12; - patch = W_CacheLumpNum(FontBNumBase + val, PU_CACHE); - V_DrawShadowedPatch(xpos + 6 - SHORT(patch->width) / 2, y, patch); -} - -//========================================================================== -// -// DrSmallNumber -// -// Draws a small two digit number. -// -//========================================================================== - -static void DrSmallNumber(int val, int x, int y) -{ - patch_t *patch; - - if (val <= 0) - { - return; - } - if (val > 999) - { - val %= 1000; - } - if (val > 99) - { - patch = PatchSmNumbers[val / 100]; - V_DrawPatch(x, y, patch); - patch = PatchSmNumbers[(val % 100) / 10]; - V_DrawPatch(x + 4, y, patch); - } - else if (val > 9) - { - patch = PatchSmNumbers[val / 10]; - V_DrawPatch(x + 4, y, patch); - } - val %= 10; - patch = PatchSmNumbers[val]; - V_DrawPatch(x + 8, y, patch); -} - -/* -//========================================================================== -// -// ShadeLine -// -//========================================================================== - -static void ShadeLine(int x, int y, int height, int shade) -{ - byte *dest; - byte *shades; - - shades = colormaps+9*256+shade*2*256; - dest = I_VideoBuffer+y*SCREENWIDTH+x; - while(height--) - { - *(dest) = *(shades+*dest); - dest += SCREENWIDTH; - } -} - -//========================================================================== -// -// ShadeChain -// -//========================================================================== - -static void ShadeChain(void) -{ - int i; - - for(i = 0; i < 16; i++) - { - ShadeLine(277+i, 190, 10, i/2); - ShadeLine(19+i, 190, 10, 7-(i/2)); - } -} -*/ - -//========================================================================== -// -// DrawSoundInfo -// -// Displays sound debugging information. -// -//========================================================================== - -static void DrawSoundInfo(void) -{ - int i; - SoundInfo_t s; - ChanInfo_t *c; - char text[32]; - int x; - int y; - int xPos[7] = { 1, 75, 112, 156, 200, 230, 260 }; - - if (leveltime & 16) - { - MN_DrTextA("*** SOUND DEBUG INFO ***", xPos[0], 20); - } - S_GetChannelInfo(&s); - if (s.channelCount == 0) - { - return; - } - x = 0; - MN_DrTextA("NAME", xPos[x++], 30); - MN_DrTextA("MO.T", xPos[x++], 30); - MN_DrTextA("MO.X", xPos[x++], 30); - MN_DrTextA("MO.Y", xPos[x++], 30); - MN_DrTextA("ID", xPos[x++], 30); - MN_DrTextA("PRI", xPos[x++], 30); - MN_DrTextA("DIST", xPos[x++], 30); - for (i = 0; i < s.channelCount; i++) - { - c = &s.chan[i]; - x = 0; - y = 40 + i * 10; - if (c->mo == NULL) - { // Channel is unused - MN_DrTextA("------", xPos[0], y); - continue; - } - M_snprintf(text, sizeof(text), "%s", c->name); - M_ForceUppercase(text); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->mo->type); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", (int) c->id); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->priority); - MN_DrTextA(text, xPos[x++], y); - M_snprintf(text, sizeof(text), "%d", c->distance); - MN_DrTextA(text, xPos[x++], y); - } - UpdateState |= I_FULLSCRN; - BorderNeedRefresh = true; -} - -//========================================================================== -// -// SB_Drawer -// -//========================================================================== - -char patcharti[][10] = { - {"ARTIBOX"}, // none - {"ARTIINVU"}, // invulnerability - {"ARTIPTN2"}, // health - {"ARTISPHL"}, // superhealth - {"ARTIHRAD"}, // healing radius - {"ARTISUMN"}, // summon maulator - {"ARTITRCH"}, // torch - {"ARTIPORK"}, // egg - {"ARTISOAR"}, // fly - {"ARTIBLST"}, // blast radius - {"ARTIPSBG"}, // poison bag - {"ARTITELO"}, // teleport other - {"ARTISPED"}, // speed - {"ARTIBMAN"}, // boost mana - {"ARTIBRAC"}, // boost armor - {"ARTIATLP"}, // teleport - {"ARTISKLL"}, // arti_puzzskull - {"ARTIBGEM"}, // arti_puzzgembig - {"ARTIGEMR"}, // arti_puzzgemred - {"ARTIGEMG"}, // arti_puzzgemgreen1 - {"ARTIGMG2"}, // arti_puzzgemgreen2 - {"ARTIGEMB"}, // arti_puzzgemblue1 - {"ARTIGMB2"}, // arti_puzzgemblue2 - {"ARTIBOK1"}, // arti_puzzbook1 - {"ARTIBOK2"}, // arti_puzzbook2 - {"ARTISKL2"}, // arti_puzzskull2 - {"ARTIFWEP"}, // arti_puzzfweapon - {"ARTICWEP"}, // arti_puzzcweapon - {"ARTIMWEP"}, // arti_puzzmweapon - {"ARTIGEAR"}, // arti_puzzgear1 - {"ARTIGER2"}, // arti_puzzgear2 - {"ARTIGER3"}, // arti_puzzgear3 - {"ARTIGER4"}, // arti_puzzgear4 -}; - -int SB_state = -1; -static int oldarti = 0; -static int oldartiCount = 0; -static int oldfrags = -9999; -static int oldmana1 = -1; -static int oldmana2 = -1; -static int oldarmor = -1; -static int oldhealth = -1; -static int oldlife = -1; -static int oldpieces = -1; -static int oldweapon = -1; -static int oldkeys = -1; - - -void SB_Drawer(void) -{ - // Sound info debug stuff - if (DebugSound == true) - { - DrawSoundInfo(); - } - CPlayer = &players[consoleplayer]; - if (viewheight == SCREENHEIGHT && !automapactive) - { - DrawFullScreenStuff(); - SB_state = -1; - } - else - { - if (SB_state == -1) - { - V_DrawPatch(0, 134, PatchH2BAR); - oldhealth = -1; - } - DrawCommonBar(); - if (!inventory) - { - if (SB_state != 0) - { - // Main interface - if (!automapactive) - { - V_DrawPatch(38, 162, PatchSTATBAR); - } - else - { - V_DrawPatch(38, 162, PatchKEYBAR); - } - oldarti = 0; - oldmana1 = -1; - oldmana2 = -1; - oldarmor = -1; - oldpieces = -1; - oldfrags = -9999; //can't use -1, 'cuz of negative frags - oldlife = -1; - oldweapon = -1; - oldkeys = -1; - } - if (!automapactive) - { - DrawMainBar(); - } - else - { - DrawKeyBar(); - } - SB_state = 0; - } - else - { - DrawInventoryBar(); - SB_state = 1; - } - } - SB_PaletteFlash(false); - DrawAnimatedIcons(); -} - -//========================================================================== -// -// DrawAnimatedIcons -// -//========================================================================== - -static void DrawAnimatedIcons(void) -{ - int frame; - static boolean hitCenterFrame; - - // Wings of wrath - if (CPlayer->powers[pw_flight]) - { - if (CPlayer->powers[pw_flight] > BLINKTHRESHOLD - || !(CPlayer->powers[pw_flight] & 16)) - { - frame = (leveltime / 3) & 15; - if (CPlayer->mo->flags2 & MF2_FLY) - { - if (hitCenterFrame && (frame != 15 && frame != 0)) - { - V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + 15, - PU_CACHE)); - } - else - { - V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + frame, - PU_CACHE)); - hitCenterFrame = false; - } - } - else - { - if (!hitCenterFrame && (frame != 15 && frame != 0)) - { - V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + frame, - PU_CACHE)); - hitCenterFrame = false; - } - else - { - V_DrawPatch(20, 19, W_CacheLumpNum(SpinFlylump + 15, - PU_CACHE)); - hitCenterFrame = true; - } - } - } - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - - // Speed Boots - if (CPlayer->powers[pw_speed]) - { - if (CPlayer->powers[pw_speed] > BLINKTHRESHOLD - || !(CPlayer->powers[pw_speed] & 16)) - { - frame = (leveltime / 3) & 15; - V_DrawPatch(60, 19, W_CacheLumpNum(SpinSpeedLump + frame, - PU_CACHE)); - } - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - - // Defensive power - if (CPlayer->powers[pw_invulnerability]) - { - if (CPlayer->powers[pw_invulnerability] > BLINKTHRESHOLD - || !(CPlayer->powers[pw_invulnerability] & 16)) - { - frame = (leveltime / 3) & 15; - V_DrawPatch(260, 19, W_CacheLumpNum(SpinDefenseLump + frame, - PU_CACHE)); - } - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } - - // Minotaur Active - if (CPlayer->powers[pw_minotaur]) - { - if (CPlayer->powers[pw_minotaur] > BLINKTHRESHOLD - || !(CPlayer->powers[pw_minotaur] & 16)) - { - frame = (leveltime / 3) & 15; - V_DrawPatch(300, 19, W_CacheLumpNum(SpinMinotaurLump + frame, - PU_CACHE)); - } - BorderTopRefresh = true; - UpdateState |= I_MESSAGES; - } -} - -//========================================================================== -// -// SB_PaletteFlash -// -// Sets the new palette based upon the current values of -// consoleplayer->damagecount and consoleplayer->bonuscount. -// -//========================================================================== - -void SB_PaletteFlash(boolean forceChange) -{ - static int sb_palette = 0; - int palette; - byte *pal; - - if (forceChange) - { - sb_palette = -1; - } - if (gamestate == GS_LEVEL) - { - CPlayer = &players[consoleplayer]; - if (CPlayer->poisoncount) - { - palette = 0; - palette = (CPlayer->poisoncount + 7) >> 3; - if (palette >= NUMPOISONPALS) - { - palette = NUMPOISONPALS - 1; - } - palette += STARTPOISONPALS; - } - else if (CPlayer->damagecount) - { - palette = (CPlayer->damagecount + 7) >> 3; - if (palette >= NUMREDPALS) - { - palette = NUMREDPALS - 1; - } - palette += STARTREDPALS; - } - else if (CPlayer->bonuscount) - { - palette = (CPlayer->bonuscount + 7) >> 3; - if (palette >= NUMBONUSPALS) - { - palette = NUMBONUSPALS - 1; - } - palette += STARTBONUSPALS; - } - else if (CPlayer->mo->flags2 & MF2_ICEDAMAGE) - { // Frozen player - palette = STARTICEPAL; - } - else - { - palette = 0; - } - } - else - { - palette = 0; - } - if (palette != sb_palette) - { - sb_palette = palette; - pal = (byte *) W_CacheLumpNum(PlayPalette, PU_CACHE) + palette * 768; - I_SetPalette(pal); - } -} - -//========================================================================== -// -// DrawCommonBar -// -//========================================================================== - -void DrawCommonBar(void) -{ - int healthPos; - - V_DrawPatch(0, 134, PatchH2TOP); - - if (oldhealth != HealthMarker) - { - oldhealth = HealthMarker; - healthPos = HealthMarker; - if (healthPos < 0) - { - healthPos = 0; - } - if (healthPos > 100) - { - healthPos = 100; - } - V_DrawPatch(28 + (((healthPos * 196) / 100) % 9), 193, PatchCHAIN); - V_DrawPatch(7 + ((healthPos * 11) / 5), 193, PatchLIFEGEM); - V_DrawPatch(0, 193, PatchLFEDGE); - V_DrawPatch(277, 193, PatchRTEDGE); -// ShadeChain(); - UpdateState |= I_STATBAR; - } -} - -//========================================================================== -// -// DrawMainBar -// -//========================================================================== - -void DrawMainBar(void) -{ - int i; - int temp; - patch_t *manaPatch1, *manaPatch2; - patch_t *manaVialPatch1, *manaVialPatch2; - - manaPatch1 = NULL; - manaPatch2 = NULL; - manaVialPatch1 = NULL; - manaVialPatch2 = NULL; - - // Ready artifact - if (ArtifactFlash) - { - V_DrawPatch(144, 160, PatchARTICLEAR); - V_DrawPatch(148, 164, W_CacheLumpNum(W_GetNumForName("useartia") - + ArtifactFlash - 1, PU_CACHE)); - ArtifactFlash--; - oldarti = -1; // so that the correct artifact fills in after the flash - UpdateState |= I_STATBAR; - } - else if (oldarti != CPlayer->readyArtifact - || oldartiCount != CPlayer->inventory[inv_ptr].count) - { - V_DrawPatch(144, 160, PatchARTICLEAR); - if (CPlayer->readyArtifact > 0) - { - V_DrawPatch(143, 163, - W_CacheLumpName(patcharti[CPlayer->readyArtifact], - PU_CACHE)); - if (CPlayer->inventory[inv_ptr].count > 1) - { - DrSmallNumber(CPlayer->inventory[inv_ptr].count, 162, 184); - } - } - oldarti = CPlayer->readyArtifact; - oldartiCount = CPlayer->inventory[inv_ptr].count; - UpdateState |= I_STATBAR; - } - - // Frags - if (deathmatch) - { - temp = 0; - for (i = 0; i < maxplayers; i++) - { - temp += CPlayer->frags[i]; - } - if (temp != oldfrags) - { - V_DrawPatch(38, 162, PatchKILLS); - DrINumber(temp, 40, 176); - oldfrags = temp; - UpdateState |= I_STATBAR; - } - } - else - { - temp = HealthMarker; - if (temp < 0) - { - temp = 0; - } - else if (temp > 100) - { - temp = 100; - } - if (oldlife != temp) - { - oldlife = temp; - V_DrawPatch(41, 178, PatchARMCLEAR); - if (temp >= 25) - { - DrINumber(temp, 40, 176); - } - else - { - DrRedINumber(temp, 40, 176); - } - UpdateState |= I_STATBAR; - } - } - // Mana - temp = CPlayer->mana[0]; - if (oldmana1 != temp) - { - V_DrawPatch(77, 178, PatchMANACLEAR); - DrSmallNumber(temp, 79, 181); - manaVialPatch1 = (patch_t *) 1; // force a vial update - if (temp == 0) - { // Draw Dim Mana icon - manaPatch1 = PatchMANADIM1; - } - else if (oldmana1 == 0) - { - manaPatch1 = PatchMANABRIGHT1; - } - oldmana1 = temp; - UpdateState |= I_STATBAR; - } - temp = CPlayer->mana[1]; - if (oldmana2 != temp) - { - V_DrawPatch(109, 178, PatchMANACLEAR); - DrSmallNumber(temp, 111, 181); - manaVialPatch1 = (patch_t *) 1; // force a vial update - if (temp == 0) - { // Draw Dim Mana icon - manaPatch2 = PatchMANADIM2; - } - else if (oldmana2 == 0) - { - manaPatch2 = PatchMANABRIGHT2; - } - oldmana2 = temp; - UpdateState |= I_STATBAR; - } - if (oldweapon != CPlayer->readyweapon || manaPatch1 || manaPatch2 - || manaVialPatch1) - { // Update mana graphics based upon mana count/weapon type - if (CPlayer->readyweapon == WP_FIRST) - { - manaPatch1 = PatchMANADIM1; - manaPatch2 = PatchMANADIM2; - manaVialPatch1 = PatchMANAVIALDIM1; - manaVialPatch2 = PatchMANAVIALDIM2; - } - else if (CPlayer->readyweapon == WP_SECOND) - { - if (!manaPatch1) - { - manaPatch1 = PatchMANABRIGHT1; - } - manaVialPatch1 = PatchMANAVIAL1; - manaPatch2 = PatchMANADIM2; - manaVialPatch2 = PatchMANAVIALDIM2; - } - else if (CPlayer->readyweapon == WP_THIRD) - { - manaPatch1 = PatchMANADIM1; - manaVialPatch1 = PatchMANAVIALDIM1; - if (!manaPatch2) - { - manaPatch2 = PatchMANABRIGHT2; - } - manaVialPatch2 = PatchMANAVIAL2; - } - else - { - manaVialPatch1 = PatchMANAVIAL1; - manaVialPatch2 = PatchMANAVIAL2; - if (!manaPatch1) - { - manaPatch1 = PatchMANABRIGHT1; - } - if (!manaPatch2) - { - manaPatch2 = PatchMANABRIGHT2; - } - } - V_DrawPatch(77, 164, manaPatch1); - V_DrawPatch(110, 164, manaPatch2); - V_DrawPatch(94, 164, manaVialPatch1); - for (i = 165; i < 187 - (22 * CPlayer->mana[0]) / MAX_MANA; i++) - { - I_VideoBuffer[i * SCREENWIDTH + 95] = 0; - I_VideoBuffer[i * SCREENWIDTH + 96] = 0; - I_VideoBuffer[i * SCREENWIDTH + 97] = 0; - } - V_DrawPatch(102, 164, manaVialPatch2); - for (i = 165; i < 187 - (22 * CPlayer->mana[1]) / MAX_MANA; i++) - { - I_VideoBuffer[i * SCREENWIDTH + 103] = 0; - I_VideoBuffer[i * SCREENWIDTH + 104] = 0; - I_VideoBuffer[i * SCREENWIDTH + 105] = 0; - } - oldweapon = CPlayer->readyweapon; - UpdateState |= I_STATBAR; - } - // Armor - temp = AutoArmorSave[CPlayer->class] - + CPlayer->armorpoints[ARMOR_ARMOR] + - CPlayer->armorpoints[ARMOR_SHIELD] + - CPlayer->armorpoints[ARMOR_HELMET] + - CPlayer->armorpoints[ARMOR_AMULET]; - if (oldarmor != temp) - { - oldarmor = temp; - V_DrawPatch(255, 178, PatchARMCLEAR); - DrINumber(FixedDiv(temp, 5 * FRACUNIT) >> FRACBITS, 250, 176); - UpdateState |= I_STATBAR; - } - // Weapon Pieces - if (oldpieces != CPlayer->pieces) - { - DrawWeaponPieces(); - oldpieces = CPlayer->pieces; - UpdateState |= I_STATBAR; - } -} - -//========================================================================== -// -// DrawInventoryBar -// -//========================================================================== - -void DrawInventoryBar(void) -{ - int i; - int x; - - x = inv_ptr - curpos; - UpdateState |= I_STATBAR; - V_DrawPatch(38, 162, PatchINVBAR); - for (i = 0; i < 7; i++) - { - //V_DrawPatch(50+i*31, 160, W_CacheLumpName("ARTIBOX", PU_CACHE)); - if (CPlayer->inventorySlotNum > x + i - && CPlayer->inventory[x + i].type != arti_none) - { - V_DrawPatch(50 + i * 31, 163, - W_CacheLumpName(patcharti - [CPlayer->inventory[x + i].type], - PU_CACHE)); - if (CPlayer->inventory[x + i].count > 1) - { - DrSmallNumber(CPlayer->inventory[x + i].count, 68 + i * 31, - 185); - } - } - } - V_DrawPatch(50 + curpos * 31, 163, PatchSELECTBOX); - if (x != 0) - { - V_DrawPatch(42, 163, !(leveltime & 4) ? PatchINVLFGEM1 : - PatchINVLFGEM2); - } - if (CPlayer->inventorySlotNum - x > 7) - { - V_DrawPatch(269, 163, !(leveltime & 4) ? PatchINVRTGEM1 : - PatchINVRTGEM2); - } -} - -//========================================================================== -// -// DrawKeyBar -// -//========================================================================== - -void DrawKeyBar(void) -{ - int i; - int xPosition; - int temp; - - if (oldkeys != CPlayer->keys) - { - xPosition = 46; - for (i = 0; i < NUM_KEY_TYPES && xPosition <= 126; i++) - { - if (CPlayer->keys & (1 << i)) - { - V_DrawPatch(xPosition, 164, - W_CacheLumpNum(W_GetNumForName("keyslot1") + i, - PU_CACHE)); - xPosition += 20; - } - } - oldkeys = CPlayer->keys; - UpdateState |= I_STATBAR; - } - temp = AutoArmorSave[CPlayer->class] - + CPlayer->armorpoints[ARMOR_ARMOR] + - CPlayer->armorpoints[ARMOR_SHIELD] + - CPlayer->armorpoints[ARMOR_HELMET] + - CPlayer->armorpoints[ARMOR_AMULET]; - if (oldarmor != temp) - { - for (i = 0; i < NUMARMOR; i++) - { - if (!CPlayer->armorpoints[i]) - { - continue; - } - if (CPlayer->armorpoints[i] <= - (ArmorIncrement[CPlayer->class][i] >> 2)) - { - V_DrawTLPatch(150 + 31 * i, 164, - W_CacheLumpNum(W_GetNumForName("armslot1") + - i, PU_CACHE)); - } - else if (CPlayer->armorpoints[i] <= - (ArmorIncrement[CPlayer->class][i] >> 1)) - { - V_DrawAltTLPatch(150 + 31 * i, 164, - W_CacheLumpNum(W_GetNumForName("armslot1") - + i, PU_CACHE)); - } - else - { - V_DrawPatch(150 + 31 * i, 164, - W_CacheLumpNum(W_GetNumForName("armslot1") + i, - PU_CACHE)); - } - } - oldarmor = temp; - UpdateState |= I_STATBAR; - } -} - -//========================================================================== -// -// DrawWeaponPieces -// -//========================================================================== - -static int PieceX[NUMCLASSES][3] = { - {190, 225, 234}, - {190, 212, 225}, - {190, 205, 224}, - {0, 0, 0} // Pig is never used -}; - -static void DrawWeaponPieces(void) -{ - if (CPlayer->pieces == 7) - { - V_DrawPatch(190, 162, PatchWEAPONFULL); - return; - } - V_DrawPatch(190, 162, PatchWEAPONSLOT); - if (CPlayer->pieces & WPIECE1) - { - V_DrawPatch(PieceX[PlayerClass[consoleplayer]][0], 162, PatchPIECE1); - } - if (CPlayer->pieces & WPIECE2) - { - V_DrawPatch(PieceX[PlayerClass[consoleplayer]][1], 162, PatchPIECE2); - } - if (CPlayer->pieces & WPIECE3) - { - V_DrawPatch(PieceX[PlayerClass[consoleplayer]][2], 162, PatchPIECE3); - } -} - -//========================================================================== -// -// DrawFullScreenStuff -// -//========================================================================== - -void DrawFullScreenStuff(void) -{ - int i; - int x; - int temp; - - UpdateState |= I_FULLSCRN; - if (CPlayer->mo->health > 0) - { - DrBNumber(CPlayer->mo->health, 5, 180); - } - else - { - DrBNumber(0, 5, 180); - } - if (deathmatch) - { - temp = 0; - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - temp += CPlayer->frags[i]; - } - } - DrINumber(temp, 45, 185); - } - if (!inventory) - { - if (CPlayer->readyArtifact > 0) - { - V_DrawTLPatch(286, 170, W_CacheLumpName("ARTIBOX", PU_CACHE)); - V_DrawPatch(284, 169, - W_CacheLumpName(patcharti[CPlayer->readyArtifact], - PU_CACHE)); - if (CPlayer->inventory[inv_ptr].count > 1) - { - DrSmallNumber(CPlayer->inventory[inv_ptr].count, 302, 192); - } - } - } - else - { - x = inv_ptr - curpos; - for (i = 0; i < 7; i++) - { - V_DrawTLPatch(50 + i * 31, 168, W_CacheLumpName("ARTIBOX", - PU_CACHE)); - if (CPlayer->inventorySlotNum > x + i - && CPlayer->inventory[x + i].type != arti_none) - { - V_DrawPatch(49 + i * 31, 167, - W_CacheLumpName(patcharti - [CPlayer->inventory[x + i].type], - PU_CACHE)); - if (CPlayer->inventory[x + i].count > 1) - { - DrSmallNumber(CPlayer->inventory[x + i].count, - 66 + i * 31, 188); - } - } - } - V_DrawPatch(50 + curpos * 31, 167, PatchSELECTBOX); - if (x != 0) - { - V_DrawPatch(40, 167, !(leveltime & 4) ? PatchINVLFGEM1 : - PatchINVLFGEM2); - } - if (CPlayer->inventorySlotNum - x > 7) - { - V_DrawPatch(268, 167, !(leveltime & 4) ? - PatchINVRTGEM1 : PatchINVRTGEM2); - } - } -} - - -//========================================================================== -// -// Draw_TeleportIcon -// -//========================================================================== -void Draw_TeleportIcon(void) -{ - patch_t *patch; - patch = W_CacheLumpNum(W_GetNumForName("teleicon"), PU_CACHE); - V_DrawPatch(100, 68, patch); - UpdateState |= I_FULLSCRN; - I_FinishUpdate(); - UpdateState |= I_FULLSCRN; -} - -//========================================================================== -// -// Draw_SaveIcon -// -//========================================================================== -void Draw_SaveIcon(void) -{ - patch_t *patch; - patch = W_CacheLumpNum(W_GetNumForName("saveicon"), PU_CACHE); - V_DrawPatch(100, 68, patch); - UpdateState |= I_FULLSCRN; - I_FinishUpdate(); - UpdateState |= I_FULLSCRN; -} - -//========================================================================== -// -// Draw_LoadIcon -// -//========================================================================== -void Draw_LoadIcon(void) -{ - patch_t *patch; - patch = W_CacheLumpNum(W_GetNumForName("loadicon"), PU_CACHE); - V_DrawPatch(100, 68, patch); - UpdateState |= I_FULLSCRN; - I_FinishUpdate(); - UpdateState |= I_FULLSCRN; -} - - - -//========================================================================== -// -// SB_Responder -// -//========================================================================== - -boolean SB_Responder(event_t * event) -{ - if (event->type == ev_keydown) - { - if (HandleCheats(event->data1)) - { // Need to eat the key - return (true); - } - } - return (false); -} - -//========================================================================== -// -// HandleCheats -// -// Returns true if the caller should eat the key. -// -//========================================================================== - -static boolean HandleCheats(byte key) -{ - int i; - boolean eat; - - if (gameskill == sk_nightmare) - { // Can't cheat in nightmare mode - return (false); - } - else if (netgame) - { // change CD track is the only cheat available in deathmatch - eat = false; - if (cdmusic) - { - if (CheatAddKey(&Cheats[0], key, &eat)) - { - Cheats[0].func(&players[consoleplayer], &Cheats[0]); - S_StartSound(NULL, SFX_PLATFORM_STOP); - } - if (CheatAddKey(&Cheats[1], key, &eat)) - { - Cheats[1].func(&players[consoleplayer], &Cheats[1]); - S_StartSound(NULL, SFX_PLATFORM_STOP); - } - } - return eat; - } - if (players[consoleplayer].health <= 0) - { // Dead players can't cheat - return (false); - } - eat = false; - for (i = 0; ipos) - { - cheat->pos = cheat->sequence; - cheat->currentArg = 0; - } - if (*cheat->pos == 0) - { - *eat = true; - cheat->args[cheat->currentArg++] = key; - cheat->pos++; - } - else if (CheatLookup[key] == *cheat->pos) - { - cheat->pos++; - } - else - { - cheat->pos = cheat->sequence; - cheat->currentArg = 0; - } - if (*cheat->pos == 0xff) - { - cheat->pos = cheat->sequence; - cheat->currentArg = 0; - return (true); - } - return (false); - */ - - *eat = cht_CheckCheat(cheat->seq, key); - - return *eat; -} - -//========================================================================== -// -// CHEAT FUNCTIONS -// -//========================================================================== - -static void CheatGodFunc(player_t * player, Cheat_t * cheat) -{ - player->cheats ^= CF_GODMODE; - if (player->cheats & CF_GODMODE) - { - P_SetMessage(player, TXT_CHEATGODON, true); - } - else - { - P_SetMessage(player, TXT_CHEATGODOFF, true); - } - SB_state = -1; -} - -static void CheatNoClipFunc(player_t * player, Cheat_t * cheat) -{ - player->cheats ^= CF_NOCLIP; - if (player->cheats & CF_NOCLIP) - { - P_SetMessage(player, TXT_CHEATNOCLIPON, true); - } - else - { - P_SetMessage(player, TXT_CHEATNOCLIPOFF, true); - } -} - -static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat) -{ - int i; - - for (i = 0; i < NUMARMOR; i++) - { - player->armorpoints[i] = ArmorIncrement[player->class][i]; - } - for (i = 0; i < NUMWEAPONS; i++) - { - player->weaponowned[i] = true; - } - for (i = 0; i < NUMMANA; i++) - { - player->mana[i] = MAX_MANA; - } - P_SetMessage(player, TXT_CHEATWEAPONS, true); -} - -static void CheatHealthFunc(player_t * player, Cheat_t * cheat) -{ - if (player->morphTics) - { - player->health = player->mo->health = MAXMORPHHEALTH; - } - else - { - player->health = player->mo->health = MAXHEALTH; - } - P_SetMessage(player, TXT_CHEATHEALTH, true); -} - -static void CheatKeysFunc(player_t * player, Cheat_t * cheat) -{ - player->keys = 2047; - P_SetMessage(player, TXT_CHEATKEYS, true); -} - -static void CheatSoundFunc(player_t * player, Cheat_t * cheat) -{ - DebugSound = !DebugSound; - if (DebugSound) - { - P_SetMessage(player, TXT_CHEATSOUNDON, true); - } - else - { - P_SetMessage(player, TXT_CHEATSOUNDOFF, true); - } -} - -static void CheatTickerFunc(player_t * player, Cheat_t * cheat) -{ - DisplayTicker = !DisplayTicker; - if (DisplayTicker) - { - P_SetMessage(player, TXT_CHEATTICKERON, true); - } - else - { - P_SetMessage(player, TXT_CHEATTICKEROFF, true); - } - - I_DisplayFPSDots(DisplayTicker); -} - -static void CheatArtifactAllFunc(player_t * player, Cheat_t * cheat) -{ - int i; - int j; - - for (i = arti_none + 1; i < arti_firstpuzzitem; i++) - { - for (j = 0; j < 25; j++) - { - P_GiveArtifact(player, i, NULL); - } - } - P_SetMessage(player, TXT_CHEATARTIFACTS3, true); -} - -static void CheatPuzzleFunc(player_t * player, Cheat_t * cheat) -{ - int i; - - for (i = arti_firstpuzzitem; i < NUMARTIFACTS; i++) - { - P_GiveArtifact(player, i, NULL); - } - P_SetMessage(player, TXT_CHEATARTIFACTS3, true); -} - -static void CheatInitFunc(player_t * player, Cheat_t * cheat) -{ - G_DeferedInitNew(gameskill, gameepisode, gamemap); - P_SetMessage(player, TXT_CHEATWARP, true); -} - -static void CheatWarpFunc(player_t * player, Cheat_t * cheat) -{ - int tens; - int ones; - int map; - char mapName[9]; - char args[2]; - - cht_GetParam(cheat->seq, args); - - tens = args[0] - '0'; - ones = args[1] - '0'; - if (tens < 0 || tens > 9 || ones < 0 || ones > 9) - { // Bad map - P_SetMessage(player, TXT_CHEATBADINPUT, true); - return; - } - map = P_TranslateMap((args[0] - '0') * 10 + args[1] - '0'); - if (map == -1) - { // Not found - P_SetMessage(player, TXT_CHEATNOMAP, true); - return; - } - if (map == gamemap) - { // Don't try to teleport to current map - P_SetMessage(player, TXT_CHEATBADINPUT, true); - return; - } - M_snprintf(mapName, sizeof(mapName), "MAP%02d", map); - if (W_CheckNumForName(mapName) == -1) - { // Can't find - P_SetMessage(player, TXT_CHEATNOMAP, true); - return; - } - P_SetMessage(player, TXT_CHEATWARP, true); - G_TeleportNewMap(map, 0); -} - -static void CheatPigFunc(player_t * player, Cheat_t * cheat) -{ - if (player->morphTics) - { - P_UndoPlayerMorph(player); - } - else - { - P_MorphPlayer(player); - } - P_SetMessage(player, "SQUEAL!!", true); -} - -static void CheatMassacreFunc(player_t * player, Cheat_t * cheat) -{ - int count; - char buffer[80]; - - count = P_Massacre(); - M_snprintf(buffer, sizeof(buffer), "%d MONSTERS KILLED\n", count); - P_SetMessage(player, buffer, true); -} - -static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat) -{ - int i; - if (player->morphTics) - { - return; - } - for (i = 1; i < NUMWEAPONS; i++) - { - player->weaponowned[i] = false; - } - - // In the original code, NUMWEAPONS was 8. So the writes to weaponowned - // overflowed the array. We must set the following fields to zero as - // well: - - player->mana[0] = 0; - player->mana[1] = 0; - player->attackdown = 0; - player->usedown = 0; - - player->pendingweapon = WP_FIRST; - P_SetMessage(player, TXT_CHEATIDKFA, true); -} - -static void CheatQuickenFunc1(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, "TRYING TO CHEAT? THAT'S ONE....", true); -} - -static void CheatQuickenFunc2(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, "THAT'S TWO....", true); -} - -static void CheatQuickenFunc3(player_t * player, Cheat_t * cheat) -{ - P_DamageMobj(player->mo, NULL, player->mo, 10000); - P_SetMessage(player, "THAT'S THREE! TIME TO DIE.", true); -} - -static void CheatClassFunc1(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, "ENTER NEW PLAYER CLASS (0 - 2)", true); -} - -static void CheatClassFunc2(player_t * player, Cheat_t * cheat) -{ - int i; - int class; - char args[2]; - - cht_GetParam(cheat->seq, args); - - if (player->morphTics) - { // don't change class if the player is morphed - return; - } - class = args[0] - '0'; - if (class > 2 || class < 0) - { - P_SetMessage(player, "INVALID PLAYER CLASS", true); - return; - } - player->class = class; - for (i = 0; i < NUMARMOR; i++) - { - player->armorpoints[i] = 0; - } - PlayerClass[consoleplayer] = class; - P_PostMorphWeapon(player, WP_FIRST); - SB_SetClassData(); - SB_state = -1; - UpdateState |= I_FULLSCRN; -} - -static void CheatVersionFunc(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, HEXEN_VERSIONTEXT, true); -} - -static void CheatDebugFunc(player_t * player, Cheat_t * cheat) -{ - char textBuffer[50]; - M_snprintf(textBuffer, sizeof(textBuffer), - "MAP %d (%d) X:%5d Y:%5d Z:%5d", - P_GetMapWarpTrans(gamemap), - gamemap, - player->mo->x >> FRACBITS, - player->mo->y >> FRACBITS, player->mo->z >> FRACBITS); - P_SetMessage(player, textBuffer, true); -} - -static void CheatScriptFunc1(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, "RUN WHICH SCRIPT(01-99)?", true); -} - -static void CheatScriptFunc2(player_t * player, Cheat_t * cheat) -{ - P_SetMessage(player, "RUN WHICH SCRIPT(01-99)?", true); -} - -static void CheatScriptFunc3(player_t * player, Cheat_t * cheat) -{ - int script; - byte script_args[3]; - int tens, ones; - char textBuffer[40]; - char args[2]; - - cht_GetParam(cheat->seq, args); - - tens = args[0] - '0'; - ones = args[1] - '0'; - script = tens * 10 + ones; - if (script < 1) - return; - if (script > 99) - return; - script_args[0] = script_args[1] = script_args[2] = 0; - - if (P_StartACS(script, 0, script_args, player->mo, NULL, 0)) - { - M_snprintf(textBuffer, sizeof(textBuffer), - "RUNNING SCRIPT %.2d", script); - P_SetMessage(player, textBuffer, true); - } -} - - -static void CheatRevealFunc(player_t * player, Cheat_t * cheat) -{ - cheating = (cheating + 1) % 3; -} - -//=========================================================================== -// -// CheatTrackFunc1 -// -//=========================================================================== - -static void CheatTrackFunc1(player_t * player, Cheat_t * cheat) -{ - char buffer[80]; - - if (!cdmusic) - { - return; - } - - if (I_CDMusInit() == -1) - { - P_SetMessage(player, "ERROR INITIALIZING CD", true); - } - - M_snprintf(buffer, sizeof(buffer), "ENTER DESIRED CD TRACK (%.2d - %.2d):\n", - I_CDMusFirstTrack(), I_CDMusLastTrack()); - P_SetMessage(player, buffer, true); -} - -//=========================================================================== -// -// CheatTrackFunc2 -// -//=========================================================================== - -static void CheatTrackFunc2(player_t * player, Cheat_t * cheat) -{ - char buffer[80]; - int track; - char args[2]; - - cht_GetParam(cheat->seq, args); - - if (!cdmusic) - { - return; - } - - track = (args[0] - '0') * 10 + (args[1] - '0'); - if (track < I_CDMusFirstTrack() || track > I_CDMusLastTrack()) - { - P_SetMessage(player, "INVALID TRACK NUMBER\n", true); - return; - } - - if (track == S_GetCurrentCDTrack()) - { - return; - } - - if (!S_StartCustomCDTrack(track)) - { - M_snprintf(buffer, sizeof(buffer), - "ERROR WHILE TRYING TO PLAY CD TRACK: %.2d\n", track); - P_SetMessage(player, buffer, true); - } - else - { - // No error encountered while attempting to play the track - M_snprintf(buffer, sizeof(buffer), "PLAYING TRACK: %.2d\n", track); - P_SetMessage(player, buffer, true); - } -} diff --git a/games/NXDoom/src/hexen/sc_man.c b/games/NXDoom/src/hexen/sc_man.c deleted file mode 100644 index 489bc72e0ec..00000000000 --- a/games/NXDoom/src/hexen/sc_man.c +++ /dev/null @@ -1,465 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include -#include -#include "h2def.h" -#include "i_system.h" -#include "m_misc.h" - -// MACROS ------------------------------------------------------------------ - -#define MAX_STRING_SIZE 64 -#define ASCII_COMMENT (';') -#define ASCII_QUOTE (34) -#define LUMP_SCRIPT 1 -#define FILE_ZONE_SCRIPT 2 - -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void CheckOpen(void); -static void OpenScript(const char *name, int type); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -char *sc_String; -int sc_Number; -int sc_Line; -boolean sc_End; -boolean sc_Crossed; -boolean sc_FileScripts = false; -const char *sc_ScriptsDir = ""; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static char ScriptName[16]; -static char *ScriptBuffer; -static char *ScriptPtr; -static char *ScriptEndPtr; -static char StringBuffer[MAX_STRING_SIZE]; -static int ScriptLumpNum; -static boolean ScriptOpen = false; -static int ScriptSize; -static boolean AlreadyGot = false; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// SC_Open -// -//========================================================================== - -void SC_Open(const char *name) -{ - char fileName[128]; - - if (sc_FileScripts == true) - { - M_snprintf(fileName, sizeof(fileName), "%s%s.txt", sc_ScriptsDir, name); - SC_OpenFile(fileName); - } - else - { - SC_OpenLump(name); - } -} - -//========================================================================== -// -// SC_OpenLump -// -// Loads a script (from the WAD files) and prepares it for parsing. -// -//========================================================================== - -void SC_OpenLump(const char *name) -{ - OpenScript(name, LUMP_SCRIPT); -} - -//========================================================================== -// -// SC_OpenFile -// -// Loads a script (from a file) and prepares it for parsing. Uses the -// zone memory allocator for memory allocation and de-allocation. -// -//========================================================================== - -void SC_OpenFile(const char *name) -{ - OpenScript(name, FILE_ZONE_SCRIPT); -} - -//========================================================================== -// -// OpenScript -// -//========================================================================== - -static void OpenScript(const char *name, int type) -{ - SC_Close(); - if (type == LUMP_SCRIPT) - { // Lump script - ScriptLumpNum = W_GetNumForName(name); - ScriptBuffer = (char *) W_CacheLumpNum(ScriptLumpNum, PU_STATIC); - ScriptSize = W_LumpLength(ScriptLumpNum); - M_StringCopy(ScriptName, name, sizeof(ScriptName)); - } - else if (type == FILE_ZONE_SCRIPT) - { // File script - zone - ScriptLumpNum = -1; - ScriptSize = M_ReadFile(name, (byte **) & ScriptBuffer); - M_ExtractFileBase(name, ScriptName); - } - ScriptPtr = ScriptBuffer; - ScriptEndPtr = ScriptPtr + ScriptSize; - sc_Line = 1; - sc_End = false; - ScriptOpen = true; - sc_String = StringBuffer; - AlreadyGot = false; -} - -//========================================================================== -// -// SC_Close -// -//========================================================================== - -void SC_Close(void) -{ - if (ScriptOpen) - { - if (ScriptLumpNum >= 0) - { - W_ReleaseLumpNum(ScriptLumpNum); - } - else - { - Z_Free(ScriptBuffer); - } - ScriptOpen = false; - } -} - -//========================================================================== -// -// SC_GetString -// -//========================================================================== - -boolean SC_GetString(void) -{ - char *text; - boolean foundToken; - - CheckOpen(); - if (AlreadyGot) - { - AlreadyGot = false; - return true; - } - foundToken = false; - sc_Crossed = false; - if (ScriptPtr >= ScriptEndPtr) - { - sc_End = true; - return false; - } - while (foundToken == false) - { - while (ScriptPtr < ScriptEndPtr && *ScriptPtr <= 32) - { - if (*ScriptPtr++ == '\n') - { - sc_Line++; - sc_Crossed = true; - } - } - if (ScriptPtr >= ScriptEndPtr) - { - sc_End = true; - return false; - } - if (*ScriptPtr != ASCII_COMMENT) - { // Found a token - foundToken = true; - } - else - { // Skip comment - while (*ScriptPtr++ != '\n') - { - if (ScriptPtr >= ScriptEndPtr) - { - sc_End = true; - return false; - } - } - sc_Line++; - sc_Crossed = true; - } - } - text = sc_String; - if (*ScriptPtr == ASCII_QUOTE) - { // Quoted string - ScriptPtr++; - while (*ScriptPtr != ASCII_QUOTE) - { - *text++ = *ScriptPtr++; - if (ScriptPtr == ScriptEndPtr - || text == &sc_String[MAX_STRING_SIZE - 1]) - { - break; - } - } - ScriptPtr++; - } - else - { // Normal string - while ((*ScriptPtr > 32) && (*ScriptPtr != ASCII_COMMENT)) - { - *text++ = *ScriptPtr++; - if (ScriptPtr == ScriptEndPtr - || text == &sc_String[MAX_STRING_SIZE - 1]) - { - break; - } - } - } - *text = 0; - return true; -} - -//========================================================================== -// -// SC_MustGetString -// -//========================================================================== - -void SC_MustGetString(void) -{ - if (SC_GetString() == false) - { - SC_ScriptError("Missing string."); - } -} - -//========================================================================== -// -// SC_MustGetStringName -// -//========================================================================== - -void SC_MustGetStringName(char *name) -{ - SC_MustGetString(); - if (SC_Compare(name) == false) - { - SC_ScriptError(NULL); - } -} - -//========================================================================== -// -// SC_GetNumber -// -//========================================================================== - -boolean SC_GetNumber(void) -{ - char *stopper; - - CheckOpen(); - if (SC_GetString()) - { - sc_Number = strtol(sc_String, &stopper, 0); - if (*stopper != 0) - { - I_Error("SC_GetNumber: Bad numeric constant \"%s\".\n" - "Script %s, Line %d", sc_String, ScriptName, sc_Line); - } - return true; - } - else - { - return false; - } -} - -//========================================================================== -// -// SC_MustGetNumber -// -//========================================================================== - -void SC_MustGetNumber(void) -{ - if (SC_GetNumber() == false) - { - SC_ScriptError("Missing integer."); - } -} - -//========================================================================== -// -// SC_UnGet -// -// Assumes there is a valid string in sc_String. -// -//========================================================================== - -void SC_UnGet(void) -{ - AlreadyGot = true; -} - -//========================================================================== -// -// SC_Check -// -// Returns true if another token is on the current line. -// -//========================================================================== - -/* -boolean SC_Check(void) -{ - char *text; - - CheckOpen(); - text = ScriptPtr; - if(text >= ScriptEndPtr) - { - return false; - } - while(*text <= 32) - { - if(*text == '\n') - { - return false; - } - text++; - if(text == ScriptEndPtr) - { - return false; - } - } - if(*text == ASCII_COMMENT) - { - return false; - } - return true; -} -*/ - -//========================================================================== -// -// SC_MatchString -// -// Returns the index of the first match to sc_String from the passed -// array of strings, or -1 if not found. -// -//========================================================================== - -int SC_MatchString(const char **strings) -{ - int i; - - for (i = 0; *strings != NULL; i++) - { - if (SC_Compare(*strings++)) - { - return i; - } - } - return -1; -} - -//========================================================================== -// -// SC_MustMatchString -// -//========================================================================== - -int SC_MustMatchString(const char **strings) -{ - int i; - - i = SC_MatchString(strings); - if (i == -1) - { - SC_ScriptError(NULL); - } - return i; -} - -//========================================================================== -// -// SC_Compare -// -//========================================================================== - -boolean SC_Compare(const char *text) -{ - if (strcasecmp(text, sc_String) == 0) - { - return true; - } - return false; -} - -//========================================================================== -// -// SC_ScriptError -// -//========================================================================== - -void SC_ScriptError(const char *message) -{ - if (message == NULL) - { - message = "Bad syntax."; - } - I_Error("Script error, \"%s\" line %d: %s", ScriptName, sc_Line, message); -} - -//========================================================================== -// -// CheckOpen -// -//========================================================================== - -static void CheckOpen(void) -{ - if (ScriptOpen == false) - { - I_Error("SC_ call before SC_Open()."); - } -} diff --git a/games/NXDoom/src/hexen/sn_sonix.c b/games/NXDoom/src/hexen/sn_sonix.c deleted file mode 100644 index 81c506babc7..00000000000 --- a/games/NXDoom/src/hexen/sn_sonix.c +++ /dev/null @@ -1,535 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include -#include "m_random.h" -#include "h2def.h" -#include "i_system.h" -#include "i_sound.h" -#include "s_sound.h" - -// MACROS ------------------------------------------------------------------ - -#define SS_MAX_SCRIPTS 64 -#define SS_TEMPBUFFER_SIZE 1024 -#define SS_SEQUENCE_NAME_LENGTH 32 - -#define SS_SCRIPT_NAME "SNDSEQ" -#define SS_STRING_PLAY "play" -#define SS_STRING_PLAYUNTILDONE "playuntildone" -#define SS_STRING_PLAYTIME "playtime" -#define SS_STRING_PLAYREPEAT "playrepeat" -#define SS_STRING_DELAY "delay" -#define SS_STRING_DELAYRAND "delayrand" -#define SS_STRING_VOLUME "volume" -#define SS_STRING_END "end" -#define SS_STRING_STOPSOUND "stopsound" - -// TYPES ------------------------------------------------------------------- - -typedef enum -{ - SS_CMD_NONE, - SS_CMD_PLAY, - SS_CMD_WAITUNTILDONE, // used by PLAYUNTILDONE - SS_CMD_PLAYTIME, - SS_CMD_PLAYREPEAT, - SS_CMD_DELAY, - SS_CMD_DELAYRAND, - SS_CMD_VOLUME, - SS_CMD_STOPSOUND, - SS_CMD_END -} sscmds_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void VerifySequencePtr(int *base, int *ptr); -static int GetSoundOffset(char *name); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static struct -{ - char name[SS_SEQUENCE_NAME_LENGTH]; - int scriptNum; - int stopSound; -} SequenceTranslate[SEQ_NUMSEQ] = -{ - { - "Platform", 0, 0}, - { - "Platform", 0, 0}, // a 'heavy' platform is just a platform - { - "PlatformMetal", 0, 0}, - { - "Platform", 0, 0}, // same with a 'creak' platform - { - "Silence", 0, 0}, - { - "Lava", 0, 0}, - { - "Water", 0, 0}, - { - "Ice", 0, 0}, - { - "Earth", 0, 0}, - { - "PlatformMetal2", 0, 0}, - { - "DoorNormal", 0, 0}, - { - "DoorHeavy", 0, 0}, - { - "DoorMetal", 0, 0}, - { - "DoorCreak", 0, 0}, - { - "Silence", 0, 0}, - { - "Lava", 0, 0}, - { - "Water", 0, 0}, - { - "Ice", 0, 0}, - { - "Earth", 0, 0}, - { - "DoorMetal2", 0, 0}, - { - "Wind", 0, 0} -}; - -static int *SequenceData[SS_MAX_SCRIPTS]; - -int ActiveSequences; -seqnode_t *SequenceListHead; - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// VerifySequencePtr -// -// Verifies the integrity of the temporary ptr, and ensures that the ptr -// isn't exceeding the size of the temporary buffer -//========================================================================== - -static void VerifySequencePtr(int *base, int *ptr) -{ - if (ptr - base > SS_TEMPBUFFER_SIZE) - { - I_Error("VerifySequencePtr: tempPtr >= %d\n", SS_TEMPBUFFER_SIZE); - } -} - -//========================================================================== -// -// GetSoundOffset -// -//========================================================================== - -static int GetSoundOffset(char *name) -{ - int i; - - for (i = 0; i < NUMSFX; i++) - { - if (!strcasecmp(name, S_sfx[i].tagname)) - { - return i; - } - } - SC_ScriptError("GetSoundOffset: Unknown sound name\n"); - return 0; -} - -//========================================================================== -// -// SN_InitSequenceScript -// -//========================================================================== - -void SN_InitSequenceScript(void) -{ - int i, j; - int inSequence; - int *tempDataStart = NULL; - int *tempDataPtr = NULL; - - inSequence = -1; - ActiveSequences = 0; - for (i = 0; i < SS_MAX_SCRIPTS; i++) - { - SequenceData[i] = NULL; - } - SC_Open(SS_SCRIPT_NAME); - while (SC_GetString()) - { - if (*sc_String == ':') - { - if (inSequence != -1) - { - SC_ScriptError("SN_InitSequenceScript: Nested Script Error"); - } - tempDataStart = (int *) Z_Malloc(SS_TEMPBUFFER_SIZE, - PU_STATIC, NULL); - memset(tempDataStart, 0, SS_TEMPBUFFER_SIZE); - tempDataPtr = tempDataStart; - for (i = 0; i < SS_MAX_SCRIPTS; i++) - { - if (SequenceData[i] == NULL) - { - break; - } - } - if (i == SS_MAX_SCRIPTS) - { - I_Error("Number of SS Scripts >= SS_MAX_SCRIPTS"); - } - for (j = 0; j < SEQ_NUMSEQ; j++) - { - if (!strcasecmp(SequenceTranslate[j].name, sc_String + 1)) - { - SequenceTranslate[j].scriptNum = i; - inSequence = j; - break; - } - } - continue; // parse the next command - } - if (inSequence == -1) - { - continue; - } - if (SC_Compare(SS_STRING_PLAYUNTILDONE)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - SC_MustGetString(); - *tempDataPtr++ = SS_CMD_PLAY; - *tempDataPtr++ = GetSoundOffset(sc_String); - *tempDataPtr++ = SS_CMD_WAITUNTILDONE; - } - else if (SC_Compare(SS_STRING_PLAY)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - SC_MustGetString(); - *tempDataPtr++ = SS_CMD_PLAY; - *tempDataPtr++ = GetSoundOffset(sc_String); - } - else if (SC_Compare(SS_STRING_PLAYTIME)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - SC_MustGetString(); - *tempDataPtr++ = SS_CMD_PLAY; - *tempDataPtr++ = GetSoundOffset(sc_String); - SC_MustGetNumber(); - *tempDataPtr++ = SS_CMD_DELAY; - *tempDataPtr++ = sc_Number; - } - else if (SC_Compare(SS_STRING_PLAYREPEAT)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - SC_MustGetString(); - *tempDataPtr++ = SS_CMD_PLAYREPEAT; - *tempDataPtr++ = GetSoundOffset(sc_String); - } - else if (SC_Compare(SS_STRING_DELAY)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - *tempDataPtr++ = SS_CMD_DELAY; - SC_MustGetNumber(); - *tempDataPtr++ = sc_Number; - } - else if (SC_Compare(SS_STRING_DELAYRAND)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - *tempDataPtr++ = SS_CMD_DELAYRAND; - SC_MustGetNumber(); - *tempDataPtr++ = sc_Number; - SC_MustGetNumber(); - *tempDataPtr++ = sc_Number; - } - else if (SC_Compare(SS_STRING_VOLUME)) - { - VerifySequencePtr(tempDataStart, tempDataPtr); - *tempDataPtr++ = SS_CMD_VOLUME; - SC_MustGetNumber(); - *tempDataPtr++ = sc_Number; - } - else if (SC_Compare(SS_STRING_END)) - { - int dataSize; - - *tempDataPtr++ = SS_CMD_END; - dataSize = (tempDataPtr - tempDataStart) * sizeof(int); - SequenceData[i] = (int *) Z_Malloc(dataSize, PU_STATIC, NULL); - memcpy(SequenceData[i], tempDataStart, dataSize); - Z_Free(tempDataStart); - inSequence = -1; - } - else if (SC_Compare(SS_STRING_STOPSOUND)) - { - SC_MustGetString(); - SequenceTranslate[inSequence].stopSound = - GetSoundOffset(sc_String); - *tempDataPtr++ = SS_CMD_STOPSOUND; - } - else - { - SC_ScriptError("SN_InitSequenceScript: Unknown commmand.\n"); - } - } -} - -//========================================================================== -// -// SN_StartSequence -// -//========================================================================== - -void SN_StartSequence(mobj_t * mobj, int sequence) -{ - seqnode_t *node; - - SN_StopSequence(mobj); // Stop any previous sequence - node = (seqnode_t *) Z_Malloc(sizeof(seqnode_t), PU_STATIC, NULL); - node->sequencePtr = SequenceData[SequenceTranslate[sequence].scriptNum]; - node->sequence = sequence; - node->mobj = mobj; - node->delayTics = 0; - node->stopSound = SequenceTranslate[sequence].stopSound; - node->volume = 127; // Start at max volume - - if (!SequenceListHead) - { - SequenceListHead = node; - node->next = node->prev = NULL; - } - else - { - SequenceListHead->prev = node; - node->next = SequenceListHead; - node->prev = NULL; - SequenceListHead = node; - } - ActiveSequences++; - return; -} - -//========================================================================== -// -// SN_StartSequenceName -// -//========================================================================== - -void SN_StartSequenceName(mobj_t * mobj, char *name) -{ - int i; - - for (i = 0; i < SEQ_NUMSEQ; i++) - { - if (!strcmp(name, SequenceTranslate[i].name)) - { - SN_StartSequence(mobj, i); - return; - } - } -} - -//========================================================================== -// -// SN_StopSequence -// -//========================================================================== - -void SN_StopSequence(mobj_t * mobj) -{ - seqnode_t *node; - - for (node = SequenceListHead; node; node = node->next) - { - if (node->mobj == mobj) - { - S_StopSound(mobj); - if (node->stopSound) - { - S_StartSoundAtVolume(mobj, node->stopSound, node->volume); - } - if (SequenceListHead == node) - { - SequenceListHead = node->next; - } - if (node->prev) - { - node->prev->next = node->next; - } - if (node->next) - { - node->next->prev = node->prev; - } - Z_Free(node); - ActiveSequences--; - } - } -} - -//========================================================================== -// -// SN_UpdateActiveSequences -// -//========================================================================== - -void SN_UpdateActiveSequences(void) -{ - seqnode_t *node; - boolean sndPlaying; - - if (!ActiveSequences || paused) - { // No sequences currently playing/game is paused - return; - } - for (node = SequenceListHead; node; node = node->next) - { - if (node->delayTics) - { - node->delayTics--; - continue; - } - sndPlaying = S_GetSoundPlayingInfo(node->mobj, node->currentSoundID); - switch (*node->sequencePtr) - { - case SS_CMD_PLAY: - if (!sndPlaying) - { - node->currentSoundID = *(node->sequencePtr + 1); - S_StartSoundAtVolume(node->mobj, node->currentSoundID, - node->volume); - } - node->sequencePtr += 2; - break; - case SS_CMD_WAITUNTILDONE: - if (!sndPlaying) - { - node->sequencePtr++; - node->currentSoundID = 0; - } - break; - case SS_CMD_PLAYREPEAT: - if (!sndPlaying) - { - node->currentSoundID = *(node->sequencePtr + 1); - S_StartSoundAtVolume(node->mobj, node->currentSoundID, - node->volume); - } - break; - case SS_CMD_DELAY: - node->delayTics = *(node->sequencePtr + 1); - node->sequencePtr += 2; - node->currentSoundID = 0; - break; - case SS_CMD_DELAYRAND: - node->delayTics = *(node->sequencePtr + 1) + - M_Random() % (*(node->sequencePtr + 2) - - *(node->sequencePtr + 1)); - node->sequencePtr += 2; - node->currentSoundID = 0; - break; - case SS_CMD_VOLUME: - node->volume = (127 * (*(node->sequencePtr + 1))) / 100; - node->sequencePtr += 2; - break; - case SS_CMD_STOPSOUND: - // Wait until something else stops the sequence - break; - case SS_CMD_END: - SN_StopSequence(node->mobj); - break; - default: - break; - } - } -} - -//========================================================================== -// -// SN_StopAllSequences -// -//========================================================================== - -void SN_StopAllSequences(void) -{ - seqnode_t *node; - - for (node = SequenceListHead; node; node = node->next) - { - node->stopSound = 0; // don't play any stop sounds - SN_StopSequence(node->mobj); - } -} - -//========================================================================== -// -// SN_GetSequenceOffset -// -//========================================================================== - -int SN_GetSequenceOffset(int sequence, int *sequencePtr) -{ - return (sequencePtr - - SequenceData[SequenceTranslate[sequence].scriptNum]); -} - -//========================================================================== -// -// SN_ChangeNodeData -// -// nodeNum zero is the first node -//========================================================================== - -void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume, - int currentSoundID) -{ - int i; - seqnode_t *node; - - i = 0; - node = SequenceListHead; - while (node && i < nodeNum) - { - node = node->next; - i++; - } - if (!node) - { // reach the end of the list before finding the nodeNum-th node - return; - } - node->delayTics = delayTics; - node->volume = volume; - node->sequencePtr += seqOffset; - node->currentSoundID = currentSoundID; -} diff --git a/games/NXDoom/src/hexen/sounds.c b/games/NXDoom/src/hexen/sounds.c deleted file mode 100644 index fe322baa4c9..00000000000 --- a/games/NXDoom/src/hexen/sounds.c +++ /dev/null @@ -1,313 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#include "h2def.h" -#include "sounds.h" - -// Music info - -/* -musicinfo_t S_music[] = -{ - { "MUS_E1M1", 0 }, // 1-1 - { "MUS_E1M2", 0 }, - { "MUS_E1M3", 0 }, - { "MUS_E1M4", 0 }, - { "MUS_E1M5", 0 }, - { "MUS_E1M6", 0 }, - { "MUS_E1M7", 0 }, - { "MUS_E1M8", 0 }, - { "MUS_E1M9", 0 }, - { "MUS_E2M1", 0 }, // 2-1 - { "MUS_E2M2", 0 }, - { "MUS_E2M3", 0 }, - { "MUS_E2M4", 0 }, - { "MUS_E1M4", 0 }, - { "MUS_E2M6", 0 }, - { "MUS_E2M7", 0 }, - { "MUS_E2M8", 0 }, - { "MUS_E2M9", 0 }, - { "MUS_E1M1", 0 }, // 3-1 - { "MUS_E3M2", 0 }, - { "MUS_E3M3", 0 }, - { "MUS_E1M6", 0 }, - { "MUS_E1M3", 0 }, - { "MUS_E1M2", 0 }, - { "MUS_E1M5", 0 }, - { "MUS_E1M9", 0 }, - { "MUS_E2M6", 0 }, - { "MUS_E1M6", 0 }, // 4-1 - { "MUS_TITL", 0 }, - { "MUS_INTR", 0 }, - { "MUS_CPTD", 0 } -}; -*/ - -// Sound info - -#define SOUND(name, priority, numchannels, pitchshift) \ - { name, "", priority, NULL, pitchshift, 0, -1, 0, numchannels, NULL } - -sfxinfo_t S_sfx[] = { - // tagname, lumpname, priority, usefulness, snd_ptr, lumpnum, numchannels, - // pitchshift - SOUND("", 0, 0, 0), - SOUND("PlayerFighterNormalDeath", 256, 2, 1), - SOUND("PlayerFighterCrazyDeath", 256, 2, 1), - SOUND("PlayerFighterExtreme1Death", 256, 2, 1), - SOUND("PlayerFighterExtreme2Death", 256, 2, 1), - SOUND("PlayerFighterExtreme3Death", 256, 2, 1), - SOUND("PlayerFighterBurnDeath", 256, 2, 1), - SOUND("PlayerClericNormalDeath", 256, 2, 1), - SOUND("PlayerClericCrazyDeath", 256, 2, 1), - SOUND("PlayerClericExtreme1Death", 256, 2, 1), - SOUND("PlayerClericExtreme2Death", 256, 2, 1), - SOUND("PlayerClericExtreme3Death", 256, 2, 1), - SOUND("PlayerClericBurnDeath", 256, 2, 1), - SOUND("PlayerMageNormalDeath", 256, 2, 0), - SOUND("PlayerMageCrazyDeath", 256, 2, 0), - SOUND("PlayerMageExtreme1Death", 256, 2, 0), - SOUND("PlayerMageExtreme2Death", 256, 2, 0), - SOUND("PlayerMageExtreme3Death", 256, 2, 0), - SOUND("PlayerMageBurnDeath", 256, 2, 0), - SOUND("PlayerFighterPain", 256, 2, 1), - SOUND("PlayerClericPain", 256, 2, 1), - SOUND("PlayerMagePain", 256, 2, 0), - SOUND("PlayerFighterGrunt", 256, 2, 1), - SOUND("PlayerClericGrunt", 256, 2, 1), - SOUND("PlayerMageGrunt", 256, 2, 0), - SOUND("PlayerLand", 32, 2, 1), - SOUND("PlayerPoisonCough", 256, 2, 1), - SOUND("PlayerFighterFallingScream", 256, 2, 1), - SOUND("PlayerClericFallingScream", 256, 2, 1), - SOUND("PlayerMageFallingScream", 256, 2, 0), - SOUND("PlayerFallingSplat", 256, 2, 1), - SOUND("PlayerFighterFailedUse", 256, 1, 1), - SOUND("PlayerClericFailedUse", 256, 1, 1), - SOUND("PlayerMageFailedUse", 256, 1, 0), - SOUND("PlatformStart", 36, 2, 1), - SOUND("PlatformStartMetal", 36, 2, 1), - SOUND("PlatformStop", 40, 2, 1), - SOUND("StoneMove", 32, 2, 1), - SOUND("MetalMove", 32, 2, 1), - SOUND("DoorOpen", 36, 2, 1), - SOUND("DoorLocked", 36, 2, 1), - SOUND("DoorOpenMetal", 36, 2, 1), - SOUND("DoorCloseMetal", 36, 2, 1), - SOUND("DoorCloseLight", 36, 2, 1), - SOUND("DoorCloseHeavy", 36, 2, 1), - SOUND("DoorCreak", 36, 2, 1), - SOUND("PickupWeapon", 36, 2, 0), - SOUND("PickupArtifact", 36, 2, 1), - SOUND("PickupKey", 36, 2, 1), - SOUND("PickupItem", 36, 2, 1), - SOUND("PickupPiece", 36, 2, 0), - SOUND("WeaponBuild", 36, 2, 0), - SOUND("UseArtifact", 36, 2, 1), - SOUND("BlastRadius", 36, 2, 1), - SOUND("Teleport", 256, 2, 1), - SOUND("ThunderCrash", 30, 2, 1), - SOUND("FighterPunchMiss", 80, 2, 1), - SOUND("FighterPunchHitThing", 80, 2, 1), - SOUND("FighterPunchHitWall", 80, 2, 1), - SOUND("FighterGrunt", 80, 2, 1), - SOUND("FighterAxeHitThing", 80, 2, 1), - SOUND("FighterHammerMiss", 80, 2, 1), - SOUND("FighterHammerHitThing", 80, 2, 1), - SOUND("FighterHammerHitWall", 80, 2, 1), - SOUND("FighterHammerContinuous", 32, 2, 1), - SOUND("FighterHammerExplode", 80, 2, 1), - SOUND("FighterSwordFire", 80, 2, 1), - SOUND("FighterSwordExplode", 80, 2, 1), - SOUND("ClericCStaffFire", 80, 2, 1), - SOUND("ClericCStaffExplode", 40, 2, 1), - SOUND("ClericCStaffHitThing", 80, 2, 1), - SOUND("ClericFlameFire", 80, 2, 1), - SOUND("ClericFlameExplode", 80, 2, 1), - SOUND("ClericFlameCircle", 80, 2, 1), - SOUND("MageWandFire", 80, 2, 1), - SOUND("MageLightningFire", 80, 2, 1), - SOUND("MageLightningZap", 32, 2, 1), - SOUND("MageLightningContinuous", 32, 2, 1), - SOUND("MageLightningReady", 30, 2, 1), - SOUND("MageShardsFire", 80, 2, 1), - SOUND("MageShardsExplode", 36, 2, 1), - SOUND("MageStaffFire", 80, 2, 1), - SOUND("MageStaffExplode", 40, 2, 1), - SOUND("Switch1", 32, 2, 1), - SOUND("Switch2", 32, 2, 1), - SOUND("SerpentSight", 32, 2, 1), - SOUND("SerpentActive", 32, 2, 1), - SOUND("SerpentPain", 32, 2, 1), - SOUND("SerpentAttack", 32, 2, 1), - SOUND("SerpentMeleeHit", 32, 2, 1), - SOUND("SerpentDeath", 40, 2, 1), - SOUND("SerpentBirth", 32, 2, 1), - SOUND("SerpentFXContinuous", 32, 2, 1), - SOUND("SerpentFXHit", 32, 2, 1), - SOUND("PotteryExplode", 32, 2, 1), - SOUND("Drip", 32, 2, 1), - SOUND("CentaurSight", 32, 2, 1), - SOUND("CentaurActive", 32, 2, 1), - SOUND("CentaurPain", 32, 2, 1), - SOUND("CentaurAttack", 32, 2, 1), - SOUND("CentaurDeath", 40, 2, 1), - SOUND("CentaurLeaderAttack", 32, 2, 1), - SOUND("CentaurMissileExplode", 32, 2, 1), - SOUND("Wind", 1, 2, 1), - SOUND("BishopSight", 32, 2, 1), - SOUND("BishopActive", 32, 2, 1), - SOUND("BishopPain", 32, 2, 1), - SOUND("BishopAttack", 32, 2, 1), - SOUND("BishopDeath", 40, 2, 1), - SOUND("BishopMissileExplode", 32, 2, 1), - SOUND("BishopBlur", 32, 2, 1), - SOUND("DemonSight", 32, 2, 1), - SOUND("DemonActive", 32, 2, 1), - SOUND("DemonPain", 32, 2, 1), - SOUND("DemonAttack", 32, 2, 1), - SOUND("DemonMissileFire", 32, 2, 1), - SOUND("DemonMissileExplode", 32, 2, 1), - SOUND("DemonDeath", 40, 2, 1), - SOUND("WraithSight", 32, 2, 1), - SOUND("WraithActive", 32, 2, 1), - SOUND("WraithPain", 32, 2, 1), - SOUND("WraithAttack", 32, 2, 1), - SOUND("WraithMissileFire", 32, 2, 1), - SOUND("WraithMissileExplode", 32, 2, 1), - SOUND("WraithDeath", 40, 2, 1), - SOUND("PigActive1", 32, 2, 1), - SOUND("PigActive2", 32, 2, 1), - SOUND("PigPain", 32, 2, 1), - SOUND("PigAttack", 32, 2, 1), - SOUND("PigDeath", 40, 2, 1), - SOUND("MaulatorSight", 32, 2, 1), - SOUND("MaulatorActive", 32, 2, 1), - SOUND("MaulatorPain", 32, 2, 1), - SOUND("MaulatorHamSwing", 32, 2, 1), - SOUND("MaulatorHamHit", 32, 2, 1), - SOUND("MaulatorMissileHit", 32, 2, 1), - SOUND("MaulatorDeath", 40, 2, 1), - SOUND("FreezeDeath", 40, 2, 1), - SOUND("FreezeShatter", 40, 2, 1), - SOUND("EttinSight", 32, 2, 1), - SOUND("EttinActive", 32, 2, 1), - SOUND("EttinPain", 32, 2, 1), - SOUND("EttinAttack", 32, 2, 1), - SOUND("EttinDeath", 40, 2, 1), - SOUND("FireDemonSpawn", 32, 2, 1), - SOUND("FireDemonActive", 32, 2, 1), - SOUND("FireDemonPain", 32, 2, 1), - SOUND("FireDemonAttack", 32, 2, 1), - SOUND("FireDemonMissileHit", 32, 2, 1), - SOUND("FireDemonDeath", 40, 2, 1), - SOUND("IceGuySight", 32, 2, 1), - SOUND("IceGuyActive", 32, 2, 1), - SOUND("IceGuyAttack", 32, 2, 1), - SOUND("IceGuyMissileExplode", 32, 2, 1), - SOUND("SorcererSight", 256, 2, 1), - SOUND("SorcererActive", 256, 2, 1), - SOUND("SorcererPain", 256, 2, 1), - SOUND("SorcererSpellCast", 256, 2, 1), - SOUND("SorcererBallWoosh", 256, 4, 1), - SOUND("SorcererDeathScream", 256, 2, 1), - SOUND("SorcererBishopSpawn", 80, 2, 1), - SOUND("SorcererBallPop", 80, 2, 1), - SOUND("SorcererBallBounce", 80, 3, 1), - SOUND("SorcererBallExplode", 80, 3, 1), - SOUND("SorcererBigBallExplode", 80, 3, 1), - SOUND("SorcererHeadScream", 256, 2, 1), - SOUND("DragonSight", 64, 2, 1), - SOUND("DragonActive", 64, 2, 1), - SOUND("DragonWingflap", 64, 2, 1), - SOUND("DragonAttack", 64, 2, 1), - SOUND("DragonPain", 64, 2, 1), - SOUND("DragonDeath", 64, 2, 1), - SOUND("DragonFireballExplode", 32, 2, 1), - SOUND("KoraxSight", 256, 2, 1), - SOUND("KoraxActive", 256, 2, 1), - SOUND("KoraxPain", 256, 2, 1), - SOUND("KoraxAttack", 256, 2, 1), - SOUND("KoraxCommand", 256, 2, 1), - SOUND("KoraxDeath", 256, 2, 1), - SOUND("KoraxStep", 128, 2, 1), - SOUND("ThrustSpikeRaise", 32, 2, 1), - SOUND("ThrustSpikeLower", 32, 2, 1), - SOUND("GlassShatter", 32, 2, 1), - SOUND("FlechetteBounce", 32, 2, 1), - SOUND("FlechetteExplode", 32, 2, 1), - SOUND("LavaMove", 36, 2, 1), - SOUND("WaterMove", 36, 2, 1), - SOUND("IceStartMove", 36, 2, 1), - SOUND("EarthStartMove", 36, 2, 1), - SOUND("WaterSplash", 32, 2, 1), - SOUND("LavaSizzle", 32, 2, 1), - SOUND("SludgeGloop", 32, 2, 1), - SOUND("HolySymbolFire", 64, 2, 1), - SOUND("SpiritActive", 32, 2, 1), - SOUND("SpiritAttack", 32, 2, 1), - SOUND("SpiritDie", 32, 2, 1), - SOUND("ValveTurn", 36, 2, 1), - SOUND("RopePull", 36, 2, 1), - SOUND("FlyBuzz", 20, 2, 1), - SOUND("Ignite", 32, 2, 1), - SOUND("PuzzleSuccess", 256, 2, 1), - SOUND("PuzzleFailFighter", 256, 2, 1), - SOUND("PuzzleFailCleric", 256, 2, 1), - SOUND("PuzzleFailMage", 256, 2, 1), - SOUND("Earthquake", 32, 2, 1), - SOUND("BellRing", 32, 2, 0), - SOUND("TreeBreak", 32, 2, 1), - SOUND("TreeExplode", 32, 2, 1), - SOUND("SuitofArmorBreak", 32, 2, 1), - SOUND("PoisonShroomPain", 20, 2, 1), - SOUND("PoisonShroomDeath", 32, 2, 1), - SOUND("Ambient1", 1, 1, 1), - SOUND("Ambient2", 1, 1, 1), - SOUND("Ambient3", 1, 1, 1), - SOUND("Ambient4", 1, 1, 1), - SOUND("Ambient5", 1, 1, 1), - SOUND("Ambient6", 1, 1, 1), - SOUND("Ambient7", 1, 1, 1), - SOUND("Ambient8", 1, 1, 1), - SOUND("Ambient9", 1, 1, 1), - SOUND("Ambient10", 1, 1, 1), - SOUND("Ambient11", 1, 1, 1), - SOUND("Ambient12", 1, 1, 1), - SOUND("Ambient13", 1, 1, 1), - SOUND("Ambient14", 1, 1, 1), - SOUND("Ambient15", 1, 1, 1), - SOUND("StartupTick", 32, 2, 1), - SOUND("SwitchOtherLevel", 32, 2, 1), - SOUND("Respawn", 32, 2, 1), - SOUND("KoraxVoiceGreetings", 512, 2, 1), - SOUND("KoraxVoiceReady", 512, 2, 1), - SOUND("KoraxVoiceBlood", 512, 2, 1), - SOUND("KoraxVoiceGame", 512, 2, 1), - SOUND("KoraxVoiceBoard", 512, 2, 1), - SOUND("KoraxVoiceWorship", 512, 2, 1), - SOUND("KoraxVoiceMaybe", 512, 2, 1), - SOUND("KoraxVoiceStrong", 512, 2, 1), - SOUND("KoraxVoiceFace", 512, 2, 1), - SOUND("BatScream", 32, 2, 1), - SOUND("Chat", 512, 2, 1), - SOUND("MenuMove", 32, 2, 1), - SOUND("ClockTick", 32, 2, 1), - SOUND("Fireball", 32, 2, 1), - SOUND("PuppyBeat", 30, 2, 1), - SOUND("MysticIncant", 32, 4, 1), -}; diff --git a/games/NXDoom/src/hexen/sounds.h b/games/NXDoom/src/hexen/sounds.h deleted file mode 100644 index 1fe2345f233..00000000000 --- a/games/NXDoom/src/hexen/sounds.h +++ /dev/null @@ -1,321 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __SOUNDSH__ -#define __SOUNDSH__ - -#include "i_sound.h" - -#define MAX_SND_DIST 2025 -#define MAX_CHANNELS 16 - -// Music identifiers - -typedef enum -{ - mus_e1m1, - mus_e1m2, - mus_e1m3, - mus_e1m4, - mus_e1m5, - mus_e1m6, - mus_e1m7, - mus_e1m8, - mus_e1m9, - mus_e2m1, - mus_e2m2, - mus_e2m3, - mus_e2m4, - mus_e2m5, - mus_e2m6, - mus_e2m7, - mus_e2m8, - mus_e2m9, - mus_e3m1, - mus_e3m2, - mus_e3m3, - mus_e3m4, - mus_e3m5, - mus_e3m6, - mus_e3m7, - mus_e3m8, - mus_e3m9, - mus_e4m1, - mus_titl, - mus_intr, - mus_cptd, - NUMMUSIC -} musicenum_t; - -// Sound identifiers - -typedef enum -{ - SFX_NONE, - SFX_PLAYER_FIGHTER_NORMAL_DEATH, // class specific death screams - SFX_PLAYER_FIGHTER_CRAZY_DEATH, - SFX_PLAYER_FIGHTER_EXTREME1_DEATH, - SFX_PLAYER_FIGHTER_EXTREME2_DEATH, - SFX_PLAYER_FIGHTER_EXTREME3_DEATH, - SFX_PLAYER_FIGHTER_BURN_DEATH, - SFX_PLAYER_CLERIC_NORMAL_DEATH, - SFX_PLAYER_CLERIC_CRAZY_DEATH, - SFX_PLAYER_CLERIC_EXTREME1_DEATH, - SFX_PLAYER_CLERIC_EXTREME2_DEATH, - SFX_PLAYER_CLERIC_EXTREME3_DEATH, - SFX_PLAYER_CLERIC_BURN_DEATH, - SFX_PLAYER_MAGE_NORMAL_DEATH, - SFX_PLAYER_MAGE_CRAZY_DEATH, - SFX_PLAYER_MAGE_EXTREME1_DEATH, - SFX_PLAYER_MAGE_EXTREME2_DEATH, - SFX_PLAYER_MAGE_EXTREME3_DEATH, - SFX_PLAYER_MAGE_BURN_DEATH, - SFX_PLAYER_FIGHTER_PAIN, - SFX_PLAYER_CLERIC_PAIN, - SFX_PLAYER_MAGE_PAIN, - SFX_PLAYER_FIGHTER_GRUNT, - SFX_PLAYER_CLERIC_GRUNT, - SFX_PLAYER_MAGE_GRUNT, - SFX_PLAYER_LAND, - SFX_PLAYER_POISONCOUGH, - SFX_PLAYER_FIGHTER_FALLING_SCREAM, // class specific falling screams - SFX_PLAYER_CLERIC_FALLING_SCREAM, - SFX_PLAYER_MAGE_FALLING_SCREAM, - SFX_PLAYER_FALLING_SPLAT, - SFX_PLAYER_FIGHTER_FAILED_USE, - SFX_PLAYER_CLERIC_FAILED_USE, - SFX_PLAYER_MAGE_FAILED_USE, - SFX_PLATFORM_START, - SFX_PLATFORM_STARTMETAL, - SFX_PLATFORM_STOP, - SFX_STONE_MOVE, - SFX_METAL_MOVE, - SFX_DOOR_OPEN, - SFX_DOOR_LOCKED, - SFX_DOOR_METAL_OPEN, - SFX_DOOR_METAL_CLOSE, - SFX_DOOR_LIGHT_CLOSE, - SFX_DOOR_HEAVY_CLOSE, - SFX_DOOR_CREAK, - SFX_PICKUP_WEAPON, - SFX_PICKUP_ARTIFACT, - SFX_PICKUP_KEY, - SFX_PICKUP_ITEM, - SFX_PICKUP_PIECE, - SFX_WEAPON_BUILD, - SFX_ARTIFACT_USE, - SFX_ARTIFACT_BLAST, - SFX_TELEPORT, - SFX_THUNDER_CRASH, - SFX_FIGHTER_PUNCH_MISS, - SFX_FIGHTER_PUNCH_HITTHING, - SFX_FIGHTER_PUNCH_HITWALL, - SFX_FIGHTER_GRUNT, - SFX_FIGHTER_AXE_HITTHING, - SFX_FIGHTER_HAMMER_MISS, - SFX_FIGHTER_HAMMER_HITTHING, - SFX_FIGHTER_HAMMER_HITWALL, - SFX_FIGHTER_HAMMER_CONTINUOUS, - SFX_FIGHTER_HAMMER_EXPLODE, - SFX_FIGHTER_SWORD_FIRE, - SFX_FIGHTER_SWORD_EXPLODE, - SFX_CLERIC_CSTAFF_FIRE, - SFX_CLERIC_CSTAFF_EXPLODE, - SFX_CLERIC_CSTAFF_HITTHING, - SFX_CLERIC_FLAME_FIRE, - SFX_CLERIC_FLAME_EXPLODE, - SFX_CLERIC_FLAME_CIRCLE, - SFX_MAGE_WAND_FIRE, - SFX_MAGE_LIGHTNING_FIRE, - SFX_MAGE_LIGHTNING_ZAP, - SFX_MAGE_LIGHTNING_CONTINUOUS, - SFX_MAGE_LIGHTNING_READY, - SFX_MAGE_SHARDS_FIRE, - SFX_MAGE_SHARDS_EXPLODE, - SFX_MAGE_STAFF_FIRE, - SFX_MAGE_STAFF_EXPLODE, - SFX_SWITCH1, - SFX_SWITCH2, - SFX_SERPENT_SIGHT, - SFX_SERPENT_ACTIVE, - SFX_SERPENT_PAIN, - SFX_SERPENT_ATTACK, - SFX_SERPENT_MELEEHIT, - SFX_SERPENT_DEATH, - SFX_SERPENT_BIRTH, - SFX_SERPENTFX_CONTINUOUS, - SFX_SERPENTFX_HIT, - SFX_POTTERY_EXPLODE, - SFX_DRIP, - SFX_CENTAUR_SIGHT, - SFX_CENTAUR_ACTIVE, - SFX_CENTAUR_PAIN, - SFX_CENTAUR_ATTACK, - SFX_CENTAUR_DEATH, - SFX_CENTAURLEADER_ATTACK, - SFX_CENTAUR_MISSILE_EXPLODE, - SFX_WIND, - SFX_BISHOP_SIGHT, - SFX_BISHOP_ACTIVE, - SFX_BISHOP_PAIN, - SFX_BISHOP_ATTACK, - SFX_BISHOP_DEATH, - SFX_BISHOP_MISSILE_EXPLODE, - SFX_BISHOP_BLUR, - SFX_DEMON_SIGHT, - SFX_DEMON_ACTIVE, - SFX_DEMON_PAIN, - SFX_DEMON_ATTACK, - SFX_DEMON_MISSILE_FIRE, - SFX_DEMON_MISSILE_EXPLODE, - SFX_DEMON_DEATH, - SFX_WRAITH_SIGHT, - SFX_WRAITH_ACTIVE, - SFX_WRAITH_PAIN, - SFX_WRAITH_ATTACK, - SFX_WRAITH_MISSILE_FIRE, - SFX_WRAITH_MISSILE_EXPLODE, - SFX_WRAITH_DEATH, - SFX_PIG_ACTIVE1, - SFX_PIG_ACTIVE2, - SFX_PIG_PAIN, - SFX_PIG_ATTACK, - SFX_PIG_DEATH, - SFX_MAULATOR_SIGHT, - SFX_MAULATOR_ACTIVE, - SFX_MAULATOR_PAIN, - SFX_MAULATOR_HAMMER_SWING, - SFX_MAULATOR_HAMMER_HIT, - SFX_MAULATOR_MISSILE_HIT, - SFX_MAULATOR_DEATH, - SFX_FREEZE_DEATH, - SFX_FREEZE_SHATTER, - SFX_ETTIN_SIGHT, - SFX_ETTIN_ACTIVE, - SFX_ETTIN_PAIN, - SFX_ETTIN_ATTACK, - SFX_ETTIN_DEATH, - SFX_FIRED_SPAWN, - SFX_FIRED_ACTIVE, - SFX_FIRED_PAIN, - SFX_FIRED_ATTACK, - SFX_FIRED_MISSILE_HIT, - SFX_FIRED_DEATH, - SFX_ICEGUY_SIGHT, - SFX_ICEGUY_ACTIVE, - SFX_ICEGUY_ATTACK, - SFX_ICEGUY_FX_EXPLODE, - SFX_SORCERER_SIGHT, - SFX_SORCERER_ACTIVE, - SFX_SORCERER_PAIN, - SFX_SORCERER_SPELLCAST, - SFX_SORCERER_BALLWOOSH, - SFX_SORCERER_DEATHSCREAM, - SFX_SORCERER_BISHOPSPAWN, - SFX_SORCERER_BALLPOP, - SFX_SORCERER_BALLBOUNCE, - SFX_SORCERER_BALLEXPLODE, - SFX_SORCERER_BIGBALLEXPLODE, - SFX_SORCERER_HEADSCREAM, - SFX_DRAGON_SIGHT, - SFX_DRAGON_ACTIVE, - SFX_DRAGON_WINGFLAP, - SFX_DRAGON_ATTACK, - SFX_DRAGON_PAIN, - SFX_DRAGON_DEATH, - SFX_DRAGON_FIREBALL_EXPLODE, - SFX_KORAX_SIGHT, - SFX_KORAX_ACTIVE, - SFX_KORAX_PAIN, - SFX_KORAX_ATTACK, - SFX_KORAX_COMMAND, - SFX_KORAX_DEATH, - SFX_KORAX_STEP, - SFX_THRUSTSPIKE_RAISE, - SFX_THRUSTSPIKE_LOWER, - SFX_STAINEDGLASS_SHATTER, - SFX_FLECHETTE_BOUNCE, - SFX_FLECHETTE_EXPLODE, - SFX_LAVA_MOVE, - SFX_WATER_MOVE, - SFX_ICE_STARTMOVE, - SFX_EARTH_STARTMOVE, - SFX_WATER_SPLASH, - SFX_LAVA_SIZZLE, - SFX_SLUDGE_GLOOP, - SFX_CHOLY_FIRE, - SFX_SPIRIT_ACTIVE, - SFX_SPIRIT_ATTACK, - SFX_SPIRIT_DIE, - SFX_VALVE_TURN, - SFX_ROPE_PULL, - SFX_FLY_BUZZ, - SFX_IGNITE, - SFX_PUZZLE_SUCCESS, - SFX_PUZZLE_FAIL_FIGHTER, - SFX_PUZZLE_FAIL_CLERIC, - SFX_PUZZLE_FAIL_MAGE, - SFX_EARTHQUAKE, - SFX_BELLRING, - SFX_TREE_BREAK, - SFX_TREE_EXPLODE, - SFX_SUITOFARMOR_BREAK, - SFX_POISONSHROOM_PAIN, - SFX_POISONSHROOM_DEATH, - SFX_AMBIENT1, - SFX_AMBIENT2, - SFX_AMBIENT3, - SFX_AMBIENT4, - SFX_AMBIENT5, - SFX_AMBIENT6, - SFX_AMBIENT7, - SFX_AMBIENT8, - SFX_AMBIENT9, - SFX_AMBIENT10, - SFX_AMBIENT11, - SFX_AMBIENT12, - SFX_AMBIENT13, - SFX_AMBIENT14, - SFX_AMBIENT15, - SFX_STARTUP_TICK, - SFX_SWITCH_OTHERLEVEL, - SFX_RESPAWN, - SFX_KORAX_VOICE_1, - SFX_KORAX_VOICE_2, - SFX_KORAX_VOICE_3, - SFX_KORAX_VOICE_4, - SFX_KORAX_VOICE_5, - SFX_KORAX_VOICE_6, - SFX_KORAX_VOICE_7, - SFX_KORAX_VOICE_8, - SFX_KORAX_VOICE_9, - SFX_BAT_SCREAM, - SFX_CHAT, - SFX_MENU_MOVE, - SFX_CLOCK_TICK, - SFX_FIREBALL, - SFX_PUPPYBEAT, - SFX_MYSTICINCANT, - NUMSFX -} sfxenum_t; - - -extern sfxinfo_t S_sfx[]; -extern musicinfo_t S_music[]; - - -#endif diff --git a/games/NXDoom/src/hexen/st_start.c b/games/NXDoom/src/hexen/st_start.c deleted file mode 100644 index aa104358db1..00000000000 --- a/games/NXDoom/src/hexen/st_start.c +++ /dev/null @@ -1,310 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - - -// HEADER FILES ------------------------------------------------------------ - -#include - -#include "config.h" - -#include "h2def.h" -#include "i_system.h" -#include "i_video.h" -#include "i_videohr.h" -#include "s_sound.h" -#include "st_start.h" - - -// MACROS ------------------------------------------------------------------ -#define ST_MAX_NOTCHES 32 -#define ST_NOTCH_WIDTH 16 -#define ST_NOTCH_HEIGHT 23 -#define ST_PROGRESS_X 64 // Start of notches x screen pos. -#define ST_PROGRESS_Y 441 // Start of notches y screen pos. - -#define ST_NETPROGRESS_X 288 -#define ST_NETPROGRESS_Y 32 -#define ST_NETNOTCH_WIDTH 8 -#define ST_NETNOTCH_HEIGHT 16 -#define ST_MAX_NETNOTCHES 8 - -byte *ST_LoadScreen(void); -void ST_UpdateNotches(int notchPosition); -void ST_UpdateNetNotches(int notchPosition); - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ -static const byte *bitmap = NULL; -int graphical_startup = 1; -static boolean using_graphical_startup; - -static const byte notchTable[] = { - // plane 0 - 0x00, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, - 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xC0, - 0x0F, 0x90, 0x1B, 0x68, 0x3D, 0xBC, 0x3F, 0xFC, 0x20, 0x08, 0x20, 0x08, - 0x2F, 0xD8, 0x37, 0xD8, 0x37, 0xF8, 0x1F, 0xF8, 0x1C, 0x50, - - // plane 1 - 0x00, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xA0, - 0x30, 0x6C, 0x24, 0x94, 0x42, 0x4A, 0x60, 0x0E, 0x60, 0x06, 0x7F, 0xF6, - 0x7F, 0xF6, 0x7F, 0xF6, 0x5E, 0xF6, 0x38, 0x16, 0x23, 0xAC, - - // plane 2 - 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, - 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xE0, - 0x30, 0x6C, 0x24, 0x94, 0x52, 0x6A, 0x7F, 0xFE, 0x60, 0x0E, 0x60, 0x0E, - 0x6F, 0xD6, 0x77, 0xD6, 0x56, 0xF6, 0x38, 0x36, 0x23, 0xAC, - - // plane 3 - 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x02, 0x40, - 0x0F, 0x90, 0x1B, 0x68, 0x3D, 0xB4, 0x1F, 0xF0, 0x1F, 0xF8, 0x1F, 0xF8, - 0x10, 0x28, 0x08, 0x28, 0x29, 0x08, 0x07, 0xE8, 0x1C, 0x50 -}; - - -// Red Network Progress notches -static const byte netnotchTable[] = { - // plane 0 - 0x80, 0x50, 0xD0, 0xf0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xD0, 0xF0, 0xC0, - 0x70, 0x50, 0x80, 0x60, - - // plane 1 - 0x60, 0xE0, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, 0xA0, - 0xA0, 0xE0, 0x60, 0x00, - - // plane 2 - 0x80, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, - 0x10, 0x10, 0x80, 0x60, - - // plane 3 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -// CODE -------------------------------------------------------------------- - - - -//-------------------------------------------------------------------------- -// -// Startup Screen Functions -// -//-------------------------------------------------------------------------- - - -//========================================================================== -// -// ST_Init - Do the startup screen -// -//========================================================================== - -void ST_Init(void) -{ - byte *pal; - byte *buffer; - - using_graphical_startup = false; - - if (graphical_startup && !debugmode && !testcontrols) - { - I_SetWindowTitleHR("Hexen startup - " PACKAGE_STRING); - - // Set 640x480x16 mode - if (I_SetVideoModeHR()) - { - using_graphical_startup = true; - I_InitWindowIcon(); - - S_StartSongName("orb", true); - - I_ClearScreenHR(); - I_InitPaletteHR(); - I_BlackPaletteHR(); - - // Load graphic - buffer = ST_LoadScreen(); - pal = buffer; - bitmap = buffer + 16 * 3; - - I_SlamHR(bitmap); - I_FadeToPaletteHR(pal); - Z_Free(buffer); - } - } -} - -void ST_Done(void) -{ - if (using_graphical_startup) - { - I_ClearScreenHR(); - I_UnsetVideoModeHR(); - } -} - - -//========================================================================== -// -// ST_UpdateNotches -// -//========================================================================== - -void ST_UpdateNotches(int notchPosition) -{ - int x = ST_PROGRESS_X + notchPosition * ST_NOTCH_WIDTH; - int y = ST_PROGRESS_Y; - I_SlamBlockHR(x, y, ST_NOTCH_WIDTH, ST_NOTCH_HEIGHT, notchTable); -} - - -//========================================================================== -// -// ST_UpdateNetNotches - indicates network progress -// -//========================================================================== - -void ST_UpdateNetNotches(int notchPosition) -{ - int x = ST_NETPROGRESS_X + notchPosition * ST_NETNOTCH_WIDTH; - int y = ST_NETPROGRESS_Y; - I_SlamBlockHR(x, y, ST_NETNOTCH_WIDTH, ST_NETNOTCH_HEIGHT, netnotchTable); -} - - -//========================================================================== -// -// ST_Progress - increments progress indicator -// -//========================================================================== - -void ST_Progress(void) -{ - // Check for ESC press -- during startup all events eaten here - if (I_CheckAbortHR()) - { - I_Quit(); - } - - if (using_graphical_startup) - { - static int notchPosition = 0; - - if (notchPosition < ST_MAX_NOTCHES) - { - ST_UpdateNotches(notchPosition); - S_StartSound(NULL, SFX_STARTUP_TICK); - //I_Sleep(1000); - notchPosition++; - } - } - - printf("."); -} - - -//========================================================================== -// -// ST_NetProgress - indicates network progress -// -//========================================================================== - -void ST_NetProgress(void) -{ - printf("*"); - - if (using_graphical_startup) - { - static int netnotchPosition = 0; - - if (netnotchPosition < ST_MAX_NETNOTCHES) - { - ST_UpdateNetNotches(netnotchPosition); - S_StartSound(NULL, SFX_DRIP); - netnotchPosition++; - } - } -} - - -//========================================================================== -// -// ST_NetDone - net progress complete -// -//========================================================================== -void ST_NetDone(void) -{ - if (using_graphical_startup) - { - S_StartSound(NULL, SFX_PICKUP_WEAPON); - } -} - - -//========================================================================== -// -// ST_Message - gives debug message -// -//========================================================================== - -void ST_Message(const char *message, ...) -{ - va_list argptr; - - va_start(argptr, message); - vprintf(message, argptr); - va_end(argptr); -} - -//========================================================================== -// -// ST_RealMessage - gives user message -// -//========================================================================== - -void ST_RealMessage(const char *message, ...) -{ - va_list argptr; - - va_start(argptr, message); - vprintf(message, argptr); - va_end(argptr); -} - - - -//========================================================================== -// -// ST_LoadScreen - loads startup graphic -// -//========================================================================== - - -byte *ST_LoadScreen(void) -{ - int length, lump; - byte *buffer; - - lump = W_GetNumForName("STARTUP"); - length = W_LumpLength(lump); - buffer = (byte *) Z_Malloc(length, PU_STATIC, NULL); - W_ReadLump(lump, buffer); - return (buffer); -} - diff --git a/games/NXDoom/src/hexen/st_start.h b/games/NXDoom/src/hexen/st_start.h deleted file mode 100644 index d38d28303a5..00000000000 --- a/games/NXDoom/src/hexen/st_start.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef STSTART_H -#define STSTART_H - -#include "doomtype.h" - -// HEADER FILES ------------------------------------------------------------ - -// MACROS ------------------------------------------------------------------ - -// TYPES ------------------------------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- -extern void ST_Init(void); -extern void ST_Done(void); -extern void ST_Message(const char *message, ...) PRINTF_ATTR(1, 2); -extern void ST_RealMessage(const char *message, ...) PRINTF_ATTR(1, 2); -extern void ST_Progress(void); -extern void ST_NetProgress(void); -extern void ST_NetDone(void); - -// PUBLIC DATA DECLARATIONS ------------------------------------------------ - -extern int graphical_startup; - -#endif diff --git a/games/NXDoom/src/hexen/sv_save.c b/games/NXDoom/src/hexen/sv_save.c deleted file mode 100644 index 007e63340f9..00000000000 --- a/games/NXDoom/src/hexen/sv_save.c +++ /dev/null @@ -1,3508 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// HEADER FILES ------------------------------------------------------------ - -#include "h2def.h" -#include "i_system.h" -#include "m_misc.h" -#include "i_swap.h" -#include "p_local.h" - -// MACROS ------------------------------------------------------------------ - -#define MAX_TARGET_PLAYERS 512 -#define MOBJ_NULL -1 -#define MOBJ_XX_PLAYER -2 -#define MAX_MAPS 99 -#define BASE_SLOT 6 -#define REBORN_SLOT 7 -#define REBORN_DESCRIPTION "TEMP GAME" -#define MAX_THINKER_SIZE 256 - -// TYPES ------------------------------------------------------------------- - -typedef enum -{ - ASEG_GAME_HEADER = 101, - ASEG_MAP_HEADER, - ASEG_WORLD, - ASEG_POLYOBJS, - ASEG_MOBJS, - ASEG_THINKERS, - ASEG_SCRIPTS, - ASEG_PLAYERS, - ASEG_SOUNDS, - ASEG_MISC, - ASEG_END -} gameArchiveSegment_t; - -typedef enum -{ - TC_NULL, - TC_MOVE_CEILING, - TC_VERTICAL_DOOR, - TC_MOVE_FLOOR, - TC_PLAT_RAISE, - TC_INTERPRET_ACS, - TC_FLOOR_WAGGLE, - TC_LIGHT, - TC_PHASE, - TC_BUILD_PILLAR, - TC_ROTATE_POLY, - TC_MOVE_POLY, - TC_POLY_DOOR -} thinkClass_t; - -typedef struct -{ - thinkClass_t tClass; - think_t thinkerFunc; - void (*writeFunc)(thinker_t *thinker); - void (*readFunc)(thinker_t *thinker); - void (*restoreFunc)(thinker_t *thinker); - size_t size; -} thinkInfo_t; - -typedef struct -{ - thinker_t thinker; - sector_t *sector; -} ssthinker_t; - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -void P_SpawnPlayer(mapthing_t * mthing); - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- - -static void ArchiveWorld(void); -static void UnarchiveWorld(void); -static void ArchivePolyobjs(void); -static void UnarchivePolyobjs(void); -static void ArchiveMobjs(void); -static void UnarchiveMobjs(void); -static void ArchiveThinkers(void); -static void UnarchiveThinkers(void); -static void ArchiveScripts(void); -static void UnarchiveScripts(void); -static void ArchivePlayers(void); -static void UnarchivePlayers(void); -static void ArchiveSounds(void); -static void UnarchiveSounds(void); -static void ArchiveMisc(void); -static void UnarchiveMisc(void); -static void SetMobjArchiveNums(void); -static void RemoveAllThinkers(void); -static int GetMobjNum(mobj_t * mobj); -static void SetMobjPtr(mobj_t **ptr, unsigned int archiveNum); -static void RestoreSSThinker(thinker_t *sst); -static void RestorePlatRaise(thinker_t *thinker); -static void RestoreMoveCeiling(thinker_t *thinker); -static void AssertSegment(gameArchiveSegment_t segType); -static void ClearSaveSlot(int slot); -static void CopySaveSlot(int sourceSlot, int destSlot); -static void CopyFile(char *sourceName, char *destName); -static boolean ExistingFile(char *name); -static void SV_OpenRead(char *fileName); -static void SV_OpenWrite(char *fileName); -static void SV_Close(void); -static void SV_Read(void *buffer, int size); -static byte SV_ReadByte(void); -static uint16_t SV_ReadWord(void); -static uint32_t SV_ReadLong(void); -static void *SV_ReadPtr(void); -static void SV_Write(const void *buffer, int size); -static void SV_WriteByte(byte val); -static void SV_WriteWord(unsigned short val); -static void SV_WriteLong(unsigned int val); -static void SV_WritePtr(void *ptr); - -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -#define DEFAULT_SAVEPATH "hexndata/" - -char *SavePath = DEFAULT_SAVEPATH; - -int vanilla_savegame_limit = 1; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int MobjCount; -static mobj_t **MobjList; -static mobj_t ***TargetPlayerAddrs; -static int TargetPlayerCount; -static boolean SavingPlayers; -static FILE *SavingFP; - -// CODE -------------------------------------------------------------------- - -// Autogenerated functions for reading/writing structs: - -// -// acsstore_t -// - -static void StreamIn_acsstore_t(acsstore_t *str) -{ - int i; - - // int map; - str->map = SV_ReadLong(); - - // int script; - str->script = SV_ReadLong(); - - // byte args[4]; - for (i=0; i<4; ++i) - { - str->args[i] = SV_ReadByte(); - } -} - -static void StreamOut_acsstore_t(acsstore_t *str) -{ - int i; - - // int map; - SV_WriteLong(str->map); - - // int script; - SV_WriteLong(str->script); - - // byte args[4]; - for (i=0; i<4; ++i) - { - SV_WriteByte(str->args[i]); - } -} - - -// -// ticcmd_t -// (this is based on the Vanilla definition of the struct) -// - -static void StreamIn_ticcmd_t(ticcmd_t *str) -{ - // char forwardmove; - str->forwardmove = SV_ReadByte(); - - // char sidemove; - str->sidemove = SV_ReadByte(); - - // short angleturn; - str->angleturn = SV_ReadWord(); - - // short consistancy; - str->consistancy = SV_ReadWord(); - - // byte chatchar; - str->chatchar = SV_ReadByte(); - - // byte buttons; - str->buttons = SV_ReadByte(); - - // byte lookfly; - str->lookfly = SV_ReadByte(); - - // byte arti; - str->arti = SV_ReadByte(); -} - -static void StreamOut_ticcmd_t(ticcmd_t *str) -{ - // char forwardmove; - SV_WriteByte(str->forwardmove); - - // char sidemove; - SV_WriteByte(str->sidemove); - - // short angleturn; - SV_WriteWord(str->angleturn); - - // short consistancy; - SV_WriteWord(str->consistancy); - - // byte chatchar; - SV_WriteByte(str->chatchar); - - // byte buttons; - SV_WriteByte(str->buttons); - - // byte lookfly; - SV_WriteByte(str->lookfly); - - // byte arti; - SV_WriteByte(str->arti); -} - - - -// -// inventory_t -// - -static void StreamIn_inventory_t(inventory_t *str) -{ - // int type; - str->type = SV_ReadLong(); - - // int count; - str->count = SV_ReadLong(); -} - -static void StreamOut_inventory_t(inventory_t *str) -{ - // int type; - SV_WriteLong(str->type); - - // int count; - SV_WriteLong(str->count); -} - - -// -// pspdef_t -// - -static void StreamIn_pspdef_t(pspdef_t *str) -{ - int state_num; - - // state_t *state; - - // This is a pointer; it is stored as an index into the states table. - - state_num = SV_ReadLong(); - - if (state_num != 0) - { - str->state = states + state_num; - } - else - { - str->state = NULL; - } - - // int tics; - str->tics = SV_ReadLong(); - - // fixed_t sx, sy; - str->sx = SV_ReadLong(); - str->sy = SV_ReadLong(); -} - -static void StreamOut_pspdef_t(pspdef_t *str) -{ - // state_t *state; - // This is a pointer; store the index in the states table, - // rather than the pointer itself. - if (str->state != NULL) - { - SV_WriteLong(str->state - states); - } - else - { - SV_WriteLong(0); - } - - // int tics; - SV_WriteLong(str->tics); - - // fixed_t sx, sy; - SV_WriteLong(str->sx); - SV_WriteLong(str->sy); -} - - -// -// player_t -// - -static void StreamIn_player_t(player_t *str) -{ - int i; - - // mobj_t *mo; - // Pointer value is reset on load. - str->mo = SV_ReadPtr(); - str->mo = NULL; - - // playerstate_t playerstate; - str->playerstate = SV_ReadLong(); - - // ticcmd_t cmd; - StreamIn_ticcmd_t(&str->cmd); - - // pclass_t class; - str->class = SV_ReadLong(); - - // fixed_t viewz; - str->viewz = SV_ReadLong(); - - // fixed_t viewheight; - str->viewheight = SV_ReadLong(); - - // fixed_t deltaviewheight; - str->deltaviewheight = SV_ReadLong(); - - // fixed_t bob; - str->bob = SV_ReadLong(); - - // int flyheight; - str->flyheight = SV_ReadLong(); - - // int lookdir; - str->lookdir = SV_ReadLong(); - - // boolean centering; - str->centering = SV_ReadLong(); - - // int health; - str->health = SV_ReadLong(); - - // int armorpoints[NUMARMOR]; - for (i=0; iarmorpoints[i] = SV_ReadLong(); - } - - // inventory_t inventory[NUMINVENTORYSLOTS]; - for (i=0; iinventory[i]); - } - - // artitype_t readyArtifact; - str->readyArtifact = SV_ReadLong(); - - // int artifactCount; - str->artifactCount = SV_ReadLong(); - - // int inventorySlotNum; - str->inventorySlotNum = SV_ReadLong(); - - // int powers[NUMPOWERS]; - for (i=0; ipowers[i] = SV_ReadLong(); - } - - // int keys; - str->keys = SV_ReadLong(); - - // int pieces; - str->pieces = SV_ReadLong(); - - // signed int frags[MAXPLAYERS]; - for (i=0; ifrags[i] = SV_ReadLong(); - } - - // weapontype_t readyweapon; - str->readyweapon = SV_ReadLong(); - - // weapontype_t pendingweapon; - str->pendingweapon = SV_ReadLong(); - - // boolean weaponowned[NUMWEAPONS]; - for (i=0; iweaponowned[i] = SV_ReadLong(); - } - - // int mana[NUMMANA]; - for (i=0; imana[i] = SV_ReadLong(); - } - - // int attackdown, usedown; - str->attackdown = SV_ReadLong(); - str->usedown = SV_ReadLong(); - - // int cheats; - str->cheats = SV_ReadLong(); - - // int refire; - str->refire = SV_ReadLong(); - - // int killcount, itemcount, secretcount; - str->killcount = SV_ReadLong(); - str->itemcount = SV_ReadLong(); - str->secretcount = SV_ReadLong(); - - // char message[80]; - for (i=0; i<80; ++i) - { - str->message[i] = SV_ReadByte(); - } - - // int messageTics; - str->messageTics = SV_ReadLong(); - - // short ultimateMessage; - str->ultimateMessage = SV_ReadWord(); - - // short yellowMessage; - str->yellowMessage = SV_ReadWord(); - - // int damagecount, bonuscount; - str->damagecount = SV_ReadLong(); - str->bonuscount = SV_ReadLong(); - - // int poisoncount; - str->poisoncount = SV_ReadLong(); - - // mobj_t *poisoner; - // Pointer value is reset. - str->poisoner = SV_ReadPtr(); - str->poisoner = NULL; - - // mobj_t *attacker; - // Pointer value is reset. - str->attacker = SV_ReadPtr(); - str->attacker = NULL; - - // int extralight; - str->extralight = SV_ReadLong(); - - // int fixedcolormap; - str->fixedcolormap = SV_ReadLong(); - - // int colormap; - str->colormap = SV_ReadLong(); - - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; ipsprites[i]); - } - - // int morphTics; - str->morphTics = SV_ReadLong(); - - // unsigned int jumpTics; - str->jumpTics = SV_ReadLong(); - - // unsigned int worldTimer; - str->worldTimer = SV_ReadLong(); -} - -static void StreamOut_player_t(player_t *str) -{ - int i; - - // mobj_t *mo; - SV_WritePtr(str->mo); - - // playerstate_t playerstate; - SV_WriteLong(str->playerstate); - - // ticcmd_t cmd; - StreamOut_ticcmd_t(&str->cmd); - - // pclass_t class; - SV_WriteLong(str->class); - - // fixed_t viewz; - SV_WriteLong(str->viewz); - - // fixed_t viewheight; - SV_WriteLong(str->viewheight); - - // fixed_t deltaviewheight; - SV_WriteLong(str->deltaviewheight); - - // fixed_t bob; - SV_WriteLong(str->bob); - - // int flyheight; - SV_WriteLong(str->flyheight); - - // int lookdir; - SV_WriteLong(str->lookdir); - - // boolean centering; - SV_WriteLong(str->centering); - - // int health; - SV_WriteLong(str->health); - - // int armorpoints[NUMARMOR]; - for (i=0; iarmorpoints[i]); - } - - // inventory_t inventory[NUMINVENTORYSLOTS]; - for (i=0; iinventory[i]); - } - - // artitype_t readyArtifact; - SV_WriteLong(str->readyArtifact); - - // int artifactCount; - SV_WriteLong(str->artifactCount); - - // int inventorySlotNum; - SV_WriteLong(str->inventorySlotNum); - - // int powers[NUMPOWERS]; - for (i=0; ipowers[i]); - } - - // int keys; - SV_WriteLong(str->keys); - - // int pieces; - SV_WriteLong(str->pieces); - - // signed int frags[MAXPLAYERS]; - for (i=0; ifrags[i]); - } - - // weapontype_t readyweapon; - SV_WriteLong(str->readyweapon); - - // weapontype_t pendingweapon; - SV_WriteLong(str->pendingweapon); - - // boolean weaponowned[NUMWEAPONS]; - for (i=0; iweaponowned[i]); - } - - // int mana[NUMMANA]; - for (i=0; imana[i]); - } - - // int attackdown, usedown; - SV_WriteLong(str->attackdown); - SV_WriteLong(str->usedown); - - // int cheats; - SV_WriteLong(str->cheats); - - // int refire; - SV_WriteLong(str->refire); - - // int killcount, itemcount, secretcount; - SV_WriteLong(str->killcount); - SV_WriteLong(str->itemcount); - SV_WriteLong(str->secretcount); - - // char message[80]; - for (i=0; i<80; ++i) - { - SV_WriteByte(str->message[i]); - } - - // int messageTics; - SV_WriteLong(str->messageTics); - - // short ultimateMessage; - SV_WriteWord(str->ultimateMessage); - - // short yellowMessage; - SV_WriteWord(str->yellowMessage); - - // int damagecount, bonuscount; - SV_WriteLong(str->damagecount); - SV_WriteLong(str->bonuscount); - - // int poisoncount; - SV_WriteLong(str->poisoncount); - - // mobj_t *poisoner; - SV_WritePtr(str->poisoner); - - // mobj_t *attacker; - SV_WritePtr(str->attacker); - - // int extralight; - SV_WriteLong(str->extralight); - - // int fixedcolormap; - SV_WriteLong(str->fixedcolormap); - - // int colormap; - SV_WriteLong(str->colormap); - - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; ipsprites[i]); - } - - // int morphTics; - SV_WriteLong(str->morphTics); - - // unsigned int jumpTics; - SV_WriteLong(str->jumpTics); - - // unsigned int worldTimer; - SV_WriteLong(str->worldTimer); -} - - -// -// thinker_t -// - -static void StreamIn_thinker_t(thinker_t *str) -{ - // struct thinker_s *prev, *next; - // Pointers are discarded: - str->prev = SV_ReadPtr(); - str->prev = NULL; - str->next = SV_ReadPtr(); - str->next = NULL; - - // think_t function; - // Function pointer is discarded: - str->function = SV_ReadPtr(); - str->function = NULL; -} - -static void StreamOut_thinker_t(thinker_t *str) -{ - // struct thinker_s *prev, *next; - SV_WritePtr(str->prev); - SV_WritePtr(str->next); - - // think_t function; - SV_WritePtr(&str->function); -} - - -// -// mobj_t -// - -static void StreamInMobjSpecials(mobj_t *mobj) -{ - unsigned int special1, special2; - - special1 = SV_ReadLong(); - special2 = SV_ReadLong(); - - mobj->special1.i = special1; - mobj->special2.i = special2; - - switch (mobj->type) - { - // Just special1 - case MT_BISH_FX: - case MT_HOLY_FX: - case MT_DRAGON: - case MT_THRUSTFLOOR_UP: - case MT_THRUSTFLOOR_DOWN: - case MT_MINOTAUR: - case MT_SORCFX1: - SetMobjPtr(&mobj->special1.m, special1); - break; - - // Just special2 - case MT_LIGHTNING_FLOOR: - case MT_LIGHTNING_ZAP: - SetMobjPtr(&mobj->special2.m, special2); - break; - - // Both special1 and special2 - case MT_HOLY_TAIL: - case MT_LIGHTNING_CEILING: - SetMobjPtr(&mobj->special1.m, special1); - SetMobjPtr(&mobj->special2.m, special2); - break; - - default: - break; - } -} - -static void StreamIn_mobj_t(mobj_t *str) -{ - unsigned int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // fixed_t x, y, z; - str->x = SV_ReadLong(); - str->y = SV_ReadLong(); - str->z = SV_ReadLong(); - - // struct mobj_s *snext, *sprev; - // Pointer values are discarded: - str->snext = SV_ReadPtr(); - str->snext = NULL; - str->sprev = SV_ReadPtr(); - str->sprev = NULL; - - // angle_t angle; - str->angle = SV_ReadLong(); - - // spritenum_t sprite; - str->sprite = SV_ReadLong(); - - // int frame; - str->frame = SV_ReadLong(); - - // struct mobj_s *bnext, *bprev; - // Values are read but discarded; this will be restored when the thing's - // position is set. - str->bnext = SV_ReadPtr(); - str->bnext = NULL; - str->bprev = SV_ReadPtr(); - str->bprev = NULL; - - // struct subsector_s *subsector; - // Read but discard: pointer will be restored when thing position is set. - str->subsector = SV_ReadPtr(); - str->subsector = NULL; - - // fixed_t floorz, ceilingz; - str->floorz = SV_ReadLong(); - str->ceilingz = SV_ReadLong(); - - // fixed_t floorpic; - str->floorpic = SV_ReadLong(); - - // fixed_t radius, height; - str->radius = SV_ReadLong(); - str->height = SV_ReadLong(); - - // fixed_t momx, momy, momz; - str->momx = SV_ReadLong(); - str->momy = SV_ReadLong(); - str->momz = SV_ReadLong(); - - // int validcount; - str->validcount = SV_ReadLong(); - - // mobjtype_t type; - str->type = SV_ReadLong(); - - // mobjinfo_t *info; - // Pointer value is read but discarded. - str->info = SV_ReadPtr(); - str->info = NULL; - - // int tics; - str->tics = SV_ReadLong(); - - // state_t *state; - // Restore as index into states table. - i = SV_ReadLong(); - str->state = &states[i]; - - // int damage; - str->damage = SV_ReadLong(); - - // int flags; - str->flags = SV_ReadLong(); - - // int flags2; - str->flags2 = SV_ReadLong(); - - // specialval_t special1; - // specialval_t special2; - // Read in special values: there are special cases to deal with with - // mobj pointers. - StreamInMobjSpecials(str); - - // int health; - str->health = SV_ReadLong(); - - // int movedir; - str->movedir = SV_ReadLong(); - - // int movecount; - str->movecount = SV_ReadLong(); - - // struct mobj_s *target; - i = SV_ReadLong(); - SetMobjPtr(&str->target, i); - - // int reactiontime; - str->reactiontime = SV_ReadLong(); - - // int threshold; - str->threshold = SV_ReadLong(); - - // struct player_s *player; - // Saved as player number. - i = SV_ReadLong(); - if (i == 0) - { - str->player = NULL; - } - else - { - str->player = &players[i - 1]; - str->player->mo = str; - } - - // int lastlook; - str->lastlook = SV_ReadLong(); - - // fixed_t floorclip; - str->floorclip = SV_ReadLong(); - - // int archiveNum; - str->archiveNum = SV_ReadLong(); - - // short tid; - str->tid = SV_ReadWord(); - - // byte special; - str->special = SV_ReadByte(); - - // byte args[5]; - for (i=0; i<5; ++i) - { - str->args[i] = SV_ReadByte(); - } -} - -static void StreamOutMobjSpecials(mobj_t *mobj) -{ - unsigned int special1, special2; - boolean corpse; - - corpse = (mobj->flags & MF_CORPSE) != 0; - special1 = mobj->special1.i; - special2 = mobj->special2.i; - - switch (mobj->type) - { - // Just special1 - case MT_BISH_FX: - case MT_HOLY_FX: - case MT_DRAGON: - case MT_THRUSTFLOOR_UP: - case MT_THRUSTFLOOR_DOWN: - case MT_MINOTAUR: - case MT_SORCFX1: - case MT_MSTAFF_FX2: - if (corpse) - { - special1 = MOBJ_NULL; - } - else - { - special1 = GetMobjNum(mobj->special1.m); - } - break; - - // Just special2 - case MT_LIGHTNING_FLOOR: - case MT_LIGHTNING_ZAP: - if (corpse) - { - special2 = MOBJ_NULL; - } - else - { - special2 = GetMobjNum(mobj->special2.m); - } - break; - - // Both special1 and special2 - case MT_HOLY_TAIL: - case MT_LIGHTNING_CEILING: - if (corpse) - { - special1 = MOBJ_NULL; - special2 = MOBJ_NULL; - } - else - { - special1 = GetMobjNum(mobj->special1.m); - special2 = GetMobjNum(mobj->special2.m); - } - break; - - // Miscellaneous - case MT_KORAX: - special1 = 0; // Searching index - break; - - default: - break; - } - - // Write special values to savegame file. - - SV_WriteLong(special1); - SV_WriteLong(special2); -} - -static void StreamOut_mobj_t(mobj_t *str) -{ - int i; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // fixed_t x, y, z; - SV_WriteLong(str->x); - SV_WriteLong(str->y); - SV_WriteLong(str->z); - - // struct mobj_s *snext, *sprev; - SV_WritePtr(str->snext); - SV_WritePtr(str->sprev); - - // angle_t angle; - SV_WriteLong(str->angle); - - // spritenum_t sprite; - SV_WriteLong(str->sprite); - - // int frame; - SV_WriteLong(str->frame); - - // struct mobj_s *bnext, *bprev; - SV_WritePtr(str->bnext); - SV_WritePtr(str->bprev); - - // struct subsector_s *subsector; - SV_WritePtr(str->subsector); - - // fixed_t floorz, ceilingz; - SV_WriteLong(str->floorz); - SV_WriteLong(str->ceilingz); - - // fixed_t floorpic; - SV_WriteLong(str->floorpic); - - // fixed_t radius, height; - SV_WriteLong(str->radius); - SV_WriteLong(str->height); - - // fixed_t momx, momy, momz; - SV_WriteLong(str->momx); - SV_WriteLong(str->momy); - SV_WriteLong(str->momz); - - // int validcount; - SV_WriteLong(str->validcount); - - // mobjtype_t type; - SV_WriteLong(str->type); - - // mobjinfo_t *info; - SV_WritePtr(str->info); - - // int tics; - SV_WriteLong(str->tics); - - // state_t *state; - // Save as index into the states table. - SV_WriteLong(str->state - states); - - // int damage; - SV_WriteLong(str->damage); - - // int flags; - SV_WriteLong(str->flags); - - // int flags2; - SV_WriteLong(str->flags2); - - // specialval_t special1; - // specialval_t special2; - // There are lots of special cases for the special values: - StreamOutMobjSpecials(str); - - // int health; - SV_WriteLong(str->health); - - // int movedir; - SV_WriteLong(str->movedir); - - // int movecount; - SV_WriteLong(str->movecount); - - // struct mobj_s *target; - if ((str->flags & MF_CORPSE) != 0) - { - SV_WriteLong(MOBJ_NULL); - } - else - { - SV_WriteLong(GetMobjNum(str->target)); - } - - // int reactiontime; - SV_WriteLong(str->reactiontime); - - // int threshold; - SV_WriteLong(str->threshold); - - // struct player_s *player; - // Stored as index into players[] array, if there is a player pointer. - if (str->player != NULL) - { - SV_WriteLong(str->player - players + 1); - } - else - { - SV_WriteLong(0); - } - - // int lastlook; - SV_WriteLong(str->lastlook); - - // fixed_t floorclip; - SV_WriteLong(str->floorclip); - - // int archiveNum; - SV_WriteLong(str->archiveNum); - - // short tid; - SV_WriteWord(str->tid); - - // byte special; - SV_WriteByte(str->special); - - // byte args[5]; - for (i=0; i<5; ++i) - { - SV_WriteByte(str->args[i]); - } -} - - -// -// floormove_t -// - -static void StreamIn_floormove_t(thinker_t *thinker) -{ - floormove_t *str = (floormove_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = sectors + i; - - // floor_e type; - str->type = SV_ReadLong(); - - // int crush; - str->crush = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // int newspecial; - str->newspecial = SV_ReadLong(); - - // short texture; - str->texture = SV_ReadWord(); - - // fixed_t floordestheight; - str->floordestheight = SV_ReadLong(); - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // int delayCount; - str->delayCount = SV_ReadLong(); - - // int delayTotal; - str->delayTotal = SV_ReadLong(); - - // fixed_t stairsDelayHeight; - str->stairsDelayHeight = SV_ReadLong(); - - // fixed_t stairsDelayHeightDelta; - str->stairsDelayHeightDelta = SV_ReadLong(); - - // fixed_t resetHeight; - str->resetHeight = SV_ReadLong(); - - // short resetDelay; - str->resetDelay = SV_ReadWord(); - - // short resetDelayCount; - str->resetDelayCount = SV_ReadWord(); - - // byte textureChange; - str->textureChange = SV_ReadByte(); -} - -static void StreamOut_floormove_t(thinker_t *thinker) -{ - floormove_t *str = (floormove_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // floor_e type; - SV_WriteLong(str->type); - - // int crush; - SV_WriteLong(str->crush); - - // int direction; - SV_WriteLong(str->direction); - - // int newspecial; - SV_WriteLong(str->newspecial); - - // short texture; - SV_WriteWord(str->texture); - - // fixed_t floordestheight; - SV_WriteLong(str->floordestheight); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // int delayCount; - SV_WriteLong(str->delayCount); - - // int delayTotal; - SV_WriteLong(str->delayTotal); - - // fixed_t stairsDelayHeight; - SV_WriteLong(str->stairsDelayHeight); - - // fixed_t stairsDelayHeightDelta; - SV_WriteLong(str->stairsDelayHeightDelta); - - // fixed_t resetHeight; - SV_WriteLong(str->resetHeight); - - // short resetDelay; - SV_WriteWord(str->resetDelay); - - // short resetDelayCount; - SV_WriteWord(str->resetDelayCount); - - // byte textureChange; - SV_WriteByte(str->textureChange); -} - - -// -// plat_t -// - -static void StreamIn_plat_t(thinker_t *thinker) -{ - plat_t *str = (plat_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = sectors + i; - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // fixed_t low; - str->low = SV_ReadLong(); - - // fixed_t high; - str->high = SV_ReadLong(); - - // int wait; - str->wait = SV_ReadLong(); - - // int count; - str->count = SV_ReadLong(); - - // plat_e status; - str->status = SV_ReadLong(); - - // plat_e oldstatus; - str->oldstatus = SV_ReadLong(); - - // int crush; - str->crush = SV_ReadLong(); - - // int tag; - str->tag = SV_ReadLong(); - - // plattype_e type; - str->type = SV_ReadLong(); -} - -static void StreamOut_plat_t(thinker_t *thinker) -{ - plat_t *str = (plat_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // fixed_t low; - SV_WriteLong(str->low); - - // fixed_t high; - SV_WriteLong(str->high); - - // int wait; - SV_WriteLong(str->wait); - - // int count; - SV_WriteLong(str->count); - - // plat_e status; - SV_WriteLong(str->status); - - // plat_e oldstatus; - SV_WriteLong(str->oldstatus); - - // int crush; - SV_WriteLong(str->crush); - - // int tag; - SV_WriteLong(str->tag); - - // plattype_e type; - SV_WriteLong(str->type); -} - - -// -// ceiling_t -// - -static void StreamIn_ceiling_t(thinker_t *thinker) -{ - ceiling_t *str = (ceiling_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = sectors + i; - - // ceiling_e type; - str->type = SV_ReadLong(); - - // fixed_t bottomheight, topheight; - str->bottomheight = SV_ReadLong(); - str->topheight = SV_ReadLong(); - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // int crush; - str->crush = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // int tag; - str->tag = SV_ReadLong(); - - // int olddirection; - str->olddirection = SV_ReadLong(); -} - -static void StreamOut_ceiling_t(thinker_t *thinker) -{ - ceiling_t *str = (ceiling_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // ceiling_e type; - SV_WriteLong(str->type); - - // fixed_t bottomheight, topheight; - SV_WriteLong(str->bottomheight); - SV_WriteLong(str->topheight); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // int crush; - SV_WriteLong(str->crush); - - // int direction; - SV_WriteLong(str->direction); - - // int tag; - SV_WriteLong(str->tag); - - // int olddirection; - SV_WriteLong(str->olddirection); -} - - -// -// light_t -// - -static void StreamIn_light_t(thinker_t *thinker) -{ - light_t *str = (light_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = sectors + i; - - // lighttype_t type; - str->type = SV_ReadLong(); - - // int value1; - str->value1 = SV_ReadLong(); - - // int value2; - str->value2 = SV_ReadLong(); - - // int tics1; - str->tics1 = SV_ReadLong(); - - // int tics2; - str->tics2 = SV_ReadLong(); - - // int count; - str->count = SV_ReadLong(); -} - -static void StreamOut_light_t(thinker_t *thinker) -{ - light_t *str = (light_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // lighttype_t type; - SV_WriteLong(str->type); - - // int value1; - SV_WriteLong(str->value1); - - // int value2; - SV_WriteLong(str->value2); - - // int tics1; - SV_WriteLong(str->tics1); - - // int tics2; - SV_WriteLong(str->tics2); - - // int count; - SV_WriteLong(str->count); -} - - -// -// vldoor_t -// - -static void StreamIn_vldoor_t(thinker_t *thinker) -{ - vldoor_t *str = (vldoor_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // vldoor_e type; - str->type = SV_ReadLong(); - - // fixed_t topheight; - str->topheight = SV_ReadLong(); - - // fixed_t speed; - str->speed = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // int topwait; - str->topwait = SV_ReadLong(); - - // int topcountdown; - str->topcountdown = SV_ReadLong(); -} - -static void StreamOut_vldoor_t(thinker_t *thinker) -{ - vldoor_t *str = (vldoor_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // vldoor_e type; - SV_WriteLong(str->type); - - // fixed_t topheight; - SV_WriteLong(str->topheight); - - // fixed_t speed; - SV_WriteLong(str->speed); - - // int direction; - SV_WriteLong(str->direction); - - // int topwait; - SV_WriteLong(str->topwait); - - // int topcountdown; - SV_WriteLong(str->topcountdown); -} - - -// -// phase_t -// - -static void StreamIn_phase_t(thinker_t *thinker) -{ - phase_t *str = (phase_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // int index; - str->index = SV_ReadLong(); - - // int base; - str->base = SV_ReadLong(); -} - -static void StreamOut_phase_t(thinker_t *thinker) -{ - phase_t *str = (phase_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // int index; - SV_WriteLong(str->index); - - // int base; - SV_WriteLong(str->base); -} - - -// -// acs_t -// - -static void StreamIn_acs_t(thinker_t *thinker) -{ - acs_t *str = (acs_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // mobj_t *activator; - i = SV_ReadLong(); - SetMobjPtr(&str->activator, i); - - // line_t *line; - i = SV_ReadLong(); - if (i != -1) - { - str->line = &lines[i]; - } - else - { - str->line = NULL; - } - - // int side; - str->side = SV_ReadLong(); - - // int number; - str->number = SV_ReadLong(); - - // int infoIndex; - str->infoIndex = SV_ReadLong(); - - // int delayCount; - str->delayCount = SV_ReadLong(); - - // int stack[ACS_STACK_DEPTH]; - for (i=0; istack[i] = SV_ReadLong(); - } - - // int stackPtr; - str->stackPtr = SV_ReadLong(); - - // int vars[MAX_ACS_SCRIPT_VARS]; - for (i=0; ivars[i] = SV_ReadLong(); - } - - // int *ip; - str->ip = SV_ReadLong(); -} - -static void StreamOut_acs_t(thinker_t *thinker) -{ - acs_t *str = (acs_t *) thinker; - - int i; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // mobj_t *activator; - SV_WriteLong(GetMobjNum(str->activator)); - - // line_t *line; - if (str->line != NULL) - { - SV_WriteLong(str->line - lines); - } - else - { - SV_WriteLong(-1); - } - - // int side; - SV_WriteLong(str->side); - - // int number; - SV_WriteLong(str->number); - - // int infoIndex; - SV_WriteLong(str->infoIndex); - - // int delayCount; - SV_WriteLong(str->delayCount); - - // int stack[ACS_STACK_DEPTH]; - for (i=0; istack[i]); - } - - // int stackPtr; - SV_WriteLong(str->stackPtr); - - // int vars[MAX_ACS_SCRIPT_VARS]; - for (i=0; ivars[i]); - } - - // int *ip; - SV_WriteLong(str->ip); -} - - -// -// polyevent_t -// - -static void StreamIn_polyevent_t(thinker_t *thinker) -{ - polyevent_t *str = (polyevent_t *) thinker; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // int polyobj; - str->polyobj = SV_ReadLong(); - - // int speed; - str->speed = SV_ReadLong(); - - // unsigned int dist; - str->dist = SV_ReadLong(); - - // int angle; - str->angle = SV_ReadLong(); - - // fixed_t xSpeed; - str->xSpeed = SV_ReadLong(); - - // fixed_t ySpeed; - str->ySpeed = SV_ReadLong(); -} - -static void StreamOut_polyevent_t(thinker_t *thinker) -{ - polyevent_t *str = (polyevent_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // int polyobj; - SV_WriteLong(str->polyobj); - - // int speed; - SV_WriteLong(str->speed); - - // unsigned int dist; - SV_WriteLong(str->dist); - - // int angle; - SV_WriteLong(str->angle); - - // fixed_t xSpeed; - SV_WriteLong(str->xSpeed); - - // fixed_t ySpeed; - SV_WriteLong(str->ySpeed); -} - - -// -// pillar_t -// - -static void StreamIn_pillar_t(thinker_t *thinker) -{ - pillar_t *str = (pillar_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // int ceilingSpeed; - str->ceilingSpeed = SV_ReadLong(); - - // int floorSpeed; - str->floorSpeed = SV_ReadLong(); - - // int floordest; - str->floordest = SV_ReadLong(); - - // int ceilingdest; - str->ceilingdest = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // int crush; - str->crush = SV_ReadLong(); -} - -static void StreamOut_pillar_t(thinker_t *thinker) -{ - pillar_t *str = (pillar_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // int ceilingSpeed; - SV_WriteLong(str->ceilingSpeed); - - // int floorSpeed; - SV_WriteLong(str->floorSpeed); - - // int floordest; - SV_WriteLong(str->floordest); - - // int ceilingdest; - SV_WriteLong(str->ceilingdest); - - // int direction; - SV_WriteLong(str->direction); - - // int crush; - SV_WriteLong(str->crush); -} - - -// -// polydoor_t -// - -static void StreamIn_polydoor_t(thinker_t *thinker) -{ - polydoor_t *str = (polydoor_t *) thinker; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // int polyobj; - str->polyobj = SV_ReadLong(); - - // int speed; - str->speed = SV_ReadLong(); - - // int dist; - str->dist = SV_ReadLong(); - - // int totalDist; - str->totalDist = SV_ReadLong(); - - // int direction; - str->direction = SV_ReadLong(); - - // fixed_t xSpeed, ySpeed; - str->xSpeed = SV_ReadLong(); - str->ySpeed = SV_ReadLong(); - - // int tics; - str->tics = SV_ReadLong(); - - // int waitTics; - str->waitTics = SV_ReadLong(); - - // podoortype_t type; - str->type = SV_ReadLong(); - - // boolean close; - str->close = SV_ReadLong(); -} - -static void StreamOut_polydoor_t(thinker_t *thinker) -{ - polydoor_t *str = (polydoor_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // int polyobj; - SV_WriteLong(str->polyobj); - - // int speed; - SV_WriteLong(str->speed); - - // int dist; - SV_WriteLong(str->dist); - - // int totalDist; - SV_WriteLong(str->totalDist); - - // int direction; - SV_WriteLong(str->direction); - - // fixed_t xSpeed, ySpeed; - SV_WriteLong(str->xSpeed); - SV_WriteLong(str->ySpeed); - - // int tics; - SV_WriteLong(str->tics); - - // int waitTics; - SV_WriteLong(str->waitTics); - - // podoortype_t type; - SV_WriteLong(str->type); - - // boolean close; - SV_WriteLong(str->close); -} - - -// -// floorWaggle_t -// - -static void StreamIn_floorWaggle_t(thinker_t *thinker) -{ - floorWaggle_t *str = (floorWaggle_t *) thinker; - - int i; - - // thinker_t thinker; - StreamIn_thinker_t(&str->thinker); - - // sector_t *sector; - i = SV_ReadLong(); - str->sector = §ors[i]; - - // fixed_t originalHeight; - str->originalHeight = SV_ReadLong(); - - // fixed_t accumulator; - str->accumulator = SV_ReadLong(); - - // fixed_t accDelta; - str->accDelta = SV_ReadLong(); - - // fixed_t targetScale; - str->targetScale = SV_ReadLong(); - - // fixed_t scale; - str->scale = SV_ReadLong(); - - // fixed_t scaleDelta; - str->scaleDelta = SV_ReadLong(); - - // int ticker; - str->ticker = SV_ReadLong(); - - // int state; - str->state = SV_ReadLong(); -} - -static void StreamOut_floorWaggle_t(thinker_t *thinker) -{ - floorWaggle_t *str = (floorWaggle_t *) thinker; - - // thinker_t thinker; - StreamOut_thinker_t(&str->thinker); - - // sector_t *sector; - SV_WriteLong(str->sector - sectors); - - // fixed_t originalHeight; - SV_WriteLong(str->originalHeight); - - // fixed_t accumulator; - SV_WriteLong(str->accumulator); - - // fixed_t accDelta; - SV_WriteLong(str->accDelta); - - // fixed_t targetScale; - SV_WriteLong(str->targetScale); - - // fixed_t scale; - SV_WriteLong(str->scale); - - // fixed_t scaleDelta; - SV_WriteLong(str->scaleDelta); - - // int ticker; - SV_WriteLong(str->ticker); - - // int state; - SV_WriteLong(str->state); -} - - -//========================================================================== -// -// SV_SaveGame -// -//========================================================================== - -void SV_SaveGame(int slot, const char *description) -{ - char fileName[100]; - char versionText[HXS_VERSION_TEXT_LENGTH]; - unsigned int i; - - // Open the output file - M_snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath); - SV_OpenWrite(fileName); - - // Write game save description - SV_Write(description, HXS_DESCRIPTION_LENGTH); - - // Write version info - memset(versionText, 0, HXS_VERSION_TEXT_LENGTH); - M_StringCopy(versionText, HXS_VERSION_TEXT, HXS_VERSION_TEXT_LENGTH); - SV_Write(versionText, HXS_VERSION_TEXT_LENGTH); - - // Place a header marker - SV_WriteLong(ASEG_GAME_HEADER); - - // Write current map and difficulty - SV_WriteByte(gamemap); - SV_WriteByte(gameskill); - - // Write global script info - for (i = 0; i < MAX_ACS_WORLD_VARS; ++i) - { - SV_WriteLong(WorldVars[i]); - } - - for (i = 0; i < MAX_ACS_STORE + 1; ++i) - { - StreamOut_acsstore_t(&ACSStore[i]); - } - - ArchivePlayers(); - - // Place a termination marker - SV_WriteLong(ASEG_END); - - // Close the output file - SV_Close(); - - // Save out the current map - SV_SaveMap(true); // true = save player info - - // Clear all save files at destination slot - ClearSaveSlot(slot); - - // Copy base slot to destination slot - CopySaveSlot(BASE_SLOT, slot); -} - -//========================================================================== -// -// SV_SaveMap -// -//========================================================================== - -void SV_SaveMap(boolean savePlayers) -{ - char fileName[100]; - - SavingPlayers = savePlayers; - - // Open the output file - M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap); - SV_OpenWrite(fileName); - - // Place a header marker - SV_WriteLong(ASEG_MAP_HEADER); - - // Write the level timer - SV_WriteLong(leveltime); - - // Set the mobj archive numbers - SetMobjArchiveNums(); - - ArchiveWorld(); - ArchivePolyobjs(); - ArchiveMobjs(); - ArchiveThinkers(); - ArchiveScripts(); - ArchiveSounds(); - ArchiveMisc(); - - // Place a termination marker - SV_WriteLong(ASEG_END); - - // Close the output file - SV_Close(); -} - -//========================================================================== -// -// SV_LoadGame -// -//========================================================================== - -void SV_LoadGame(int slot) -{ - int i; - char fileName[100]; - char version_text[HXS_VERSION_TEXT_LENGTH]; - player_t playerBackup[MAXPLAYERS]; - mobj_t *mobj; - - // Copy all needed save files to the base slot - if (slot != BASE_SLOT) - { - ClearSaveSlot(BASE_SLOT); - CopySaveSlot(slot, BASE_SLOT); - } - - // Create the name - M_snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath); - - // Load the file - SV_OpenRead(fileName); - - // Set the save pointer and skip the description field - fseek(SavingFP, HXS_DESCRIPTION_LENGTH, SEEK_CUR); - - // Check the version text - - for (i = 0; i < sizeof(version_text); ++i) - { - version_text[i] = SV_ReadByte(); - } - if (strncmp(version_text, HXS_VERSION_TEXT, HXS_VERSION_TEXT_LENGTH) != 0) - { // Bad version - return; - } - - AssertSegment(ASEG_GAME_HEADER); - - gameepisode = 1; - gamemap = SV_ReadByte(); - gameskill = SV_ReadByte(); - - // Read global script info - - for (i = 0; i < MAX_ACS_WORLD_VARS; ++i) - { - WorldVars[i] = SV_ReadLong(); - } - - for (i = 0; i < MAX_ACS_STORE + 1; ++i) - { - StreamIn_acsstore_t(&ACSStore[i]); - } - - // Read the player structures - UnarchivePlayers(); - - AssertSegment(ASEG_END); - - // Save player structs - for (i = 0; i < maxplayers; i++) - { - playerBackup[i] = players[i]; - } - - SV_Close(); - - // Load the current map - SV_LoadMap(); - - // Don't need the player mobj relocation info for load game - Z_Free(TargetPlayerAddrs); - - // Restore player structs - inv_ptr = 0; - curpos = 0; - for (i = 0; i < maxplayers; i++) - { - mobj = players[i].mo; - players[i] = playerBackup[i]; - players[i].mo = mobj; - if (i == consoleplayer) - { - players[i].readyArtifact = players[i].inventory[inv_ptr].type; - } - } - - // Set Bestslideline after loading - P_InitSlideLine(); -} - -//========================================================================== -// -// SV_UpdateRebornSlot -// -// Copies the base slot to the reborn slot. -// -//========================================================================== - -void SV_UpdateRebornSlot(void) -{ - ClearSaveSlot(REBORN_SLOT); - CopySaveSlot(BASE_SLOT, REBORN_SLOT); -} - -//========================================================================== -// -// SV_ClearRebornSlot -// -//========================================================================== - -void SV_ClearRebornSlot(void) -{ - ClearSaveSlot(REBORN_SLOT); -} - -//========================================================================== -// -// SV_MapTeleport -// -//========================================================================== - -void SV_MapTeleport(int map, int position) -{ - int i; - int j; - char fileName[100]; - player_t playerBackup[MAXPLAYERS]; - mobj_t *targetPlayerMobj; - mobj_t *mobj; - int inventoryPtr; - int currentInvPos; - boolean rClass; - boolean playerWasReborn; - boolean oldWeaponowned[NUMWEAPONS]; - int oldKeys = 0; - int oldPieces = 0; - int bestWeapon; - - if (!deathmatch) - { - if (P_GetMapCluster(gamemap) == P_GetMapCluster(map)) - { // Same cluster - save map without saving player mobjs - SV_SaveMap(false); - } - else - { // Entering new cluster - clear base slot - ClearSaveSlot(BASE_SLOT); - } - } - - // Store player structs for later - rClass = randomclass; - randomclass = false; - for (i = 0; i < maxplayers; i++) - { - playerBackup[i] = players[i]; - } - - // Save some globals that get trashed during the load - inventoryPtr = inv_ptr; - currentInvPos = curpos; - - // Only SV_LoadMap() uses TargetPlayerAddrs, so it's NULLed here - // for the following check (player mobj redirection) - TargetPlayerAddrs = NULL; - - gamemap = map; - M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap); - if (!deathmatch && ExistingFile(fileName)) - { // Unarchive map - SV_LoadMap(); - } - else - { // New map - G_InitNew(gameskill, gameepisode, gamemap); - - // Destroy all freshly spawned players - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - P_RemoveMobj(players[i].mo); - } - } - } - - // Restore player structs - targetPlayerMobj = NULL; - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - { - continue; - } - players[i] = playerBackup[i]; - P_ClearMessage(&players[i]); - players[i].attacker = NULL; - players[i].poisoner = NULL; - - if (netgame) - { - if (players[i].playerstate == PST_DEAD) - { // In a network game, force all players to be alive - players[i].playerstate = PST_REBORN; - } - if (!deathmatch) - { // Cooperative net-play, retain keys and weapons - oldKeys = players[i].keys; - oldPieces = players[i].pieces; - for (j = 0; j < NUMWEAPONS; j++) - { - oldWeaponowned[j] = players[i].weaponowned[j]; - } - } - } - playerWasReborn = (players[i].playerstate == PST_REBORN); - if (deathmatch) - { - memset(players[i].frags, 0, sizeof(players[i].frags)); - mobj = P_SpawnMobj(playerstarts[0][i].x << 16, - playerstarts[0][i].y << 16, 0, - MT_PLAYER_FIGHTER); - players[i].mo = mobj; - G_DeathMatchSpawnPlayer(i); - P_RemoveMobj(mobj); - } - else - { - P_SpawnPlayer(&playerstarts[position][i]); - } - - if (playerWasReborn && netgame && !deathmatch) - { // Restore keys and weapons when reborn in co-op - players[i].keys = oldKeys; - players[i].pieces = oldPieces; - for (bestWeapon = 0, j = 0; j < NUMWEAPONS; j++) - { - if (oldWeaponowned[j]) - { - bestWeapon = j; - players[i].weaponowned[j] = true; - } - } - players[i].mana[MANA_1] = 25; - players[i].mana[MANA_2] = 25; - if (bestWeapon) - { // Bring up the best weapon - players[i].pendingweapon = bestWeapon; - } - } - - if (targetPlayerMobj == NULL) - { // The poor sap - targetPlayerMobj = players[i].mo; - } - } - randomclass = rClass; - - // Redirect anything targeting a player mobj - if (TargetPlayerAddrs) - { - for (i = 0; i < TargetPlayerCount; i++) - { - *TargetPlayerAddrs[i] = targetPlayerMobj; - } - Z_Free(TargetPlayerAddrs); - } - - // Destroy all things touching players - for (i = 0; i < maxplayers; i++) - { - if (playeringame[i]) - { - P_TeleportMove(players[i].mo, players[i].mo->x, players[i].mo->y); - } - } - - // Restore trashed globals - inv_ptr = inventoryPtr; - curpos = currentInvPos; - - // Launch waiting scripts - if (!deathmatch) - { - P_CheckACSStore(); - } - - // For single play, save immediately into the reborn slot - if (!netgame) - { - SV_SaveGame(REBORN_SLOT, REBORN_DESCRIPTION); - } -} - -//========================================================================== -// -// SV_GetRebornSlot -// -//========================================================================== - -int SV_GetRebornSlot(void) -{ - return (REBORN_SLOT); -} - -//========================================================================== -// -// SV_RebornSlotAvailable -// -// Returns true if the reborn slot is available. -// -//========================================================================== - -boolean SV_RebornSlotAvailable(void) -{ - char fileName[100]; - - M_snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, REBORN_SLOT); - return ExistingFile(fileName); -} - -//========================================================================== -// -// SV_LoadMap -// -//========================================================================== - -void SV_LoadMap(void) -{ - char fileName[100]; - - // Load a base level - G_InitNew(gameskill, gameepisode, gamemap); - - // Remove all thinkers - RemoveAllThinkers(); - - // Create the name - M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap); - - // Load the file - SV_OpenRead(fileName); - - AssertSegment(ASEG_MAP_HEADER); - - // Read the level timer - leveltime = SV_ReadLong(); - - UnarchiveWorld(); - UnarchivePolyobjs(); - UnarchiveMobjs(); - UnarchiveThinkers(); - UnarchiveScripts(); - UnarchiveSounds(); - UnarchiveMisc(); - - AssertSegment(ASEG_END); - - // Free mobj list and save buffer - Z_Free(MobjList); - SV_Close(); -} - -//========================================================================== -// -// SV_InitBaseSlot -// -//========================================================================== - -void SV_InitBaseSlot(void) -{ - ClearSaveSlot(BASE_SLOT); -} - -//========================================================================== -// -// ArchivePlayers -// -//========================================================================== - -static void ArchivePlayers(void) -{ - int i; - - SV_WriteLong(ASEG_PLAYERS); - for (i = 0; i < maxplayers; i++) - { - SV_WriteByte(playeringame[i]); - } - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - { - continue; - } - SV_WriteByte(PlayerClass[i]); - StreamOut_player_t(&players[i]); - } -} - -//========================================================================== -// -// UnarchivePlayers -// -//========================================================================== - -static void UnarchivePlayers(void) -{ - int i; - - AssertSegment(ASEG_PLAYERS); - for (i = 0; i < maxplayers; i++) - { - playeringame[i] = SV_ReadByte(); - } - for (i = 0; i < maxplayers; i++) - { - if (!playeringame[i]) - { - continue; - } - PlayerClass[i] = SV_ReadByte(); - StreamIn_player_t(&players[i]); - P_ClearMessage(&players[i]); - } -} - -//========================================================================== -// -// ArchiveWorld -// -//========================================================================== - -static void ArchiveWorld(void) -{ - int i; - int j; - sector_t *sec; - line_t *li; - side_t *si; - - SV_WriteLong(ASEG_WORLD); - for (i = 0, sec = sectors; i < numsectors; i++, sec++) - { - SV_WriteWord(sec->floorheight >> FRACBITS); - SV_WriteWord(sec->ceilingheight >> FRACBITS); - SV_WriteWord(sec->floorpic); - SV_WriteWord(sec->ceilingpic); - SV_WriteWord(sec->lightlevel); - SV_WriteWord(sec->special); - SV_WriteWord(sec->tag); - SV_WriteWord(sec->seqType); - } - for (i = 0, li = lines; i < numlines; i++, li++) - { - SV_WriteWord(li->flags); - SV_WriteByte(li->special); - SV_WriteByte(li->arg1); - SV_WriteByte(li->arg2); - SV_WriteByte(li->arg3); - SV_WriteByte(li->arg4); - SV_WriteByte(li->arg5); - for (j = 0; j < 2; j++) - { - if (li->sidenum[j] == -1) - { - continue; - } - si = &sides[li->sidenum[j]]; - SV_WriteWord(si->textureoffset >> FRACBITS); - SV_WriteWord(si->rowoffset >> FRACBITS); - SV_WriteWord(si->toptexture); - SV_WriteWord(si->bottomtexture); - SV_WriteWord(si->midtexture); - } - } -} - -//========================================================================== -// -// UnarchiveWorld -// -//========================================================================== - -static void UnarchiveWorld(void) -{ - int i; - int j; - sector_t *sec; - line_t *li; - side_t *si; - - AssertSegment(ASEG_WORLD); - for (i = 0, sec = sectors; i < numsectors; i++, sec++) - { - sec->floorheight = SV_ReadWord() << FRACBITS; - sec->ceilingheight = SV_ReadWord() << FRACBITS; - sec->floorpic = SV_ReadWord(); - sec->ceilingpic = SV_ReadWord(); - sec->lightlevel = SV_ReadWord(); - sec->special = SV_ReadWord(); - sec->tag = SV_ReadWord(); - sec->seqType = SV_ReadWord(); - sec->specialdata = 0; - sec->soundtarget = 0; - } - for (i = 0, li = lines; i < numlines; i++, li++) - { - li->flags = SV_ReadWord(); - li->special = SV_ReadByte(); - li->arg1 = SV_ReadByte(); - li->arg2 = SV_ReadByte(); - li->arg3 = SV_ReadByte(); - li->arg4 = SV_ReadByte(); - li->arg5 = SV_ReadByte(); - for (j = 0; j < 2; j++) - { - if (li->sidenum[j] == -1) - { - continue; - } - si = &sides[li->sidenum[j]]; - si->textureoffset = SV_ReadWord() << FRACBITS; - si->rowoffset = SV_ReadWord() << FRACBITS; - si->toptexture = SV_ReadWord(); - si->bottomtexture = SV_ReadWord(); - si->midtexture = SV_ReadWord(); - } - } -} - -//========================================================================== -// -// SetMobjArchiveNums -// -// Sets the archive numbers in all mobj structs. Also sets the MobjCount -// global. Ignores player mobjs if SavingPlayers is false. -// -//========================================================================== - -static void SetMobjArchiveNums(void) -{ - mobj_t *mobj; - thinker_t *thinker; - - MobjCount = 0; - for (thinker = thinkercap.next; thinker != &thinkercap; - thinker = thinker->next) - { - if (thinker->function == P_MobjThinker) - { - mobj = (mobj_t *) thinker; - if (mobj->player && !SavingPlayers) - { // Skipping player mobjs - continue; - } - mobj->archiveNum = MobjCount++; - } - } -} - -//========================================================================== -// -// ArchiveMobjs -// -//========================================================================== - -static void ArchiveMobjs(void) -{ - int count; - thinker_t *thinker; - - SV_WriteLong(ASEG_MOBJS); - SV_WriteLong(MobjCount); - count = 0; - for (thinker = thinkercap.next; thinker != &thinkercap; - thinker = thinker->next) - { - if (thinker->function != P_MobjThinker) - { // Not a mobj thinker - continue; - } - if (((mobj_t *) thinker)->player && !SavingPlayers) - { // Skipping player mobjs - continue; - } - count++; - StreamOut_mobj_t((mobj_t *) thinker); - } - if (count != MobjCount) - { - I_Error("ArchiveMobjs: bad mobj count"); - } -} - -//========================================================================== -// -// UnarchiveMobjs -// -//========================================================================== - -static void UnarchiveMobjs(void) -{ - int i; - mobj_t *mobj; - - AssertSegment(ASEG_MOBJS); - TargetPlayerAddrs = Z_Malloc(MAX_TARGET_PLAYERS * sizeof(mobj_t **), - PU_STATIC, NULL); - TargetPlayerCount = 0; - MobjCount = SV_ReadLong(); - MobjList = Z_Malloc(MobjCount * sizeof(mobj_t *), PU_STATIC, NULL); - for (i = 0; i < MobjCount; i++) - { - MobjList[i] = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL); - } - for (i = 0; i < MobjCount; i++) - { - mobj = MobjList[i]; - StreamIn_mobj_t(mobj); - - // Restore broken pointers. - mobj->info = &mobjinfo[mobj->type]; - P_SetThingPosition(mobj); - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - - mobj->thinker.function = P_MobjThinker; - P_AddThinker(&mobj->thinker); - } - P_CreateTIDList(); - P_InitCreatureCorpseQueue(true); // true = scan for corpses -} - -//========================================================================== -// -// GetMobjNum -// -//========================================================================== - -static int GetMobjNum(mobj_t * mobj) -{ - if (mobj == NULL) - { - return MOBJ_NULL; - } - if (mobj->player && !SavingPlayers) - { - return MOBJ_XX_PLAYER; - } - return mobj->archiveNum; -} - -//========================================================================== -// -// SetMobjPtr -// -//========================================================================== - -static void SetMobjPtr(mobj_t **ptr, unsigned int archiveNum) -{ - if (archiveNum == MOBJ_NULL) - { - *ptr = NULL; - } - else if (archiveNum == MOBJ_XX_PLAYER) - { - if (TargetPlayerCount == MAX_TARGET_PLAYERS) - { - I_Error("RestoreMobj: exceeded MAX_TARGET_PLAYERS"); - } - TargetPlayerAddrs[TargetPlayerCount++] = ptr; - *ptr = NULL; - } - else - { - *ptr = MobjList[archiveNum]; - } -} - -//========================================================================== -// -// Thinker types list. -// -// This is used by ArchiveThinkers and UnarchiveThinkers, below. -// -// Original comment: -// "This list has been prioritized using frequency estimates" -// -//========================================================================== - -static thinkInfo_t ThinkerInfo[] = { - { - TC_MOVE_FLOOR, - T_MoveFloor, - StreamOut_floormove_t, - StreamIn_floormove_t, - RestoreSSThinker, - sizeof(floormove_t) - }, - { - TC_PLAT_RAISE, - T_PlatRaise, - StreamOut_plat_t, - StreamIn_plat_t, - RestorePlatRaise, - sizeof(plat_t) - }, - { - TC_MOVE_CEILING, - T_MoveCeiling, - StreamOut_ceiling_t, - StreamIn_ceiling_t, - RestoreMoveCeiling, - sizeof(ceiling_t) - }, - { - TC_LIGHT, - T_Light, - StreamOut_light_t, - StreamIn_light_t, - NULL, - sizeof(light_t) - }, - { - TC_VERTICAL_DOOR, - T_VerticalDoor, - StreamOut_vldoor_t, - StreamIn_vldoor_t, - RestoreSSThinker, - sizeof(vldoor_t) - }, - { - TC_PHASE, - T_Phase, - StreamOut_phase_t, - StreamIn_phase_t, - NULL, - sizeof(phase_t) - }, - { - TC_INTERPRET_ACS, - T_InterpretACS, - StreamOut_acs_t, - StreamIn_acs_t, - NULL, - sizeof(acs_t) - }, - { - TC_ROTATE_POLY, - T_RotatePoly, - StreamOut_polyevent_t, - StreamIn_polyevent_t, - NULL, - sizeof(polyevent_t) - }, - { - TC_BUILD_PILLAR, - T_BuildPillar, - StreamOut_pillar_t, - StreamIn_pillar_t, - RestoreSSThinker, - sizeof(pillar_t) - }, - { - TC_MOVE_POLY, - T_MovePoly, - StreamOut_polyevent_t, - StreamIn_polyevent_t, - NULL, - sizeof(polyevent_t) - }, - { - TC_POLY_DOOR, - T_PolyDoor, - StreamOut_polydoor_t, - StreamIn_polydoor_t, - NULL, - sizeof(polydoor_t) - }, - { - TC_FLOOR_WAGGLE, - T_FloorWaggle, - StreamOut_floorWaggle_t, - StreamIn_floorWaggle_t, - RestoreSSThinker, - sizeof(floorWaggle_t) - }, - { TC_NULL, NULL, NULL, NULL, NULL, 0}, -}; - -//========================================================================== -// -// ArchiveThinkers -// -//========================================================================== - -static void ArchiveThinkers(void) -{ - thinker_t *thinker; - thinkInfo_t *info; - - SV_WriteLong(ASEG_THINKERS); - for (thinker = thinkercap.next; thinker != &thinkercap; - thinker = thinker->next) - { - for (info = ThinkerInfo; info->tClass != TC_NULL; info++) - { - if (thinker->function == info->thinkerFunc) - { - SV_WriteByte(info->tClass); - info->writeFunc(thinker); - break; - } - } - } - // Add a termination marker - SV_WriteByte(TC_NULL); -} - -//========================================================================== -// -// UnarchiveThinkers -// -//========================================================================== - -static void UnarchiveThinkers(void) -{ - int tClass; - thinker_t *thinker; - thinkInfo_t *info; - - AssertSegment(ASEG_THINKERS); - while ((tClass = SV_ReadByte()) != TC_NULL) - { - for (info = ThinkerInfo; info->tClass != TC_NULL; info++) - { - if (tClass == info->tClass) - { - thinker = Z_Malloc(info->size, PU_LEVEL, NULL); - info->readFunc(thinker); - thinker->function = info->thinkerFunc; - if (info->restoreFunc) - { - info->restoreFunc(thinker); - } - P_AddThinker(thinker); - break; - } - } - if (info->tClass == TC_NULL) - { - I_Error("UnarchiveThinkers: Unknown tClass %d in " - "savegame", tClass); - } - } -} - -//========================================================================== -// -// RestoreSSThinker -// -//========================================================================== - -static void RestoreSSThinker(thinker_t *thinker) -{ - ssthinker_t *sst = (ssthinker_t *) thinker; - sst->sector->specialdata = sst->thinker.function; -} - -//========================================================================== -// -// RestorePlatRaise -// -//========================================================================== - -static void RestorePlatRaise(thinker_t *thinker) -{ - plat_t *plat = (plat_t *) thinker; - plat->sector->specialdata = T_PlatRaise; - P_AddActivePlat(plat); -} - -//========================================================================== -// -// RestoreMoveCeiling -// -//========================================================================== - -static void RestoreMoveCeiling(thinker_t *thinker) -{ - ceiling_t *ceiling = (ceiling_t *) thinker; - ceiling->sector->specialdata = T_MoveCeiling; - P_AddActiveCeiling(ceiling); -} - -//========================================================================== -// -// ArchiveScripts -// -//========================================================================== - -static void ArchiveScripts(void) -{ - int i; - - SV_WriteLong(ASEG_SCRIPTS); - for (i = 0; i < ACScriptCount; i++) - { - SV_WriteWord(ACSInfo[i].state); - SV_WriteWord(ACSInfo[i].waitValue); - } - - for (i = 0; i< MAX_ACS_MAP_VARS; ++i) - { - SV_WriteLong(MapVars[i]); - } -} - -//========================================================================== -// -// UnarchiveScripts -// -//========================================================================== - -static void UnarchiveScripts(void) -{ - int i; - - AssertSegment(ASEG_SCRIPTS); - for (i = 0; i < ACScriptCount; i++) - { - ACSInfo[i].state = SV_ReadWord(); - ACSInfo[i].waitValue = SV_ReadWord(); - } - - for (i = 0; i < MAX_ACS_MAP_VARS; ++i) - { - MapVars[i] = SV_ReadLong(); - } -} - -//========================================================================== -// -// ArchiveMisc -// -//========================================================================== - -static void ArchiveMisc(void) -{ - int ix; - - SV_WriteLong(ASEG_MISC); - for (ix = 0; ix < maxplayers; ix++) - { - SV_WriteLong(localQuakeHappening[ix]); - } -} - -//========================================================================== -// -// UnarchiveMisc -// -//========================================================================== - -static void UnarchiveMisc(void) -{ - int ix; - - AssertSegment(ASEG_MISC); - for (ix = 0; ix < maxplayers; ix++) - { - localQuakeHappening[ix] = SV_ReadLong(); - } -} - -//========================================================================== -// -// RemoveAllThinkers -// -//========================================================================== - -static void RemoveAllThinkers(void) -{ - thinker_t *thinker; - thinker_t *nextThinker; - - thinker = thinkercap.next; - while (thinker != &thinkercap) - { - nextThinker = thinker->next; - if (thinker->function == P_MobjThinker) - { - P_RemoveMobj((mobj_t *) thinker); - } - else - { - Z_Free(thinker); - } - thinker = nextThinker; - } - P_InitThinkers(); -} - -//========================================================================== -// -// ArchiveSounds -// -//========================================================================== - -static void ArchiveSounds(void) -{ - seqnode_t *node; - sector_t *sec; - int difference; - int i; - - SV_WriteLong(ASEG_SOUNDS); - - // Save the sound sequences - SV_WriteLong(ActiveSequences); - for (node = SequenceListHead; node; node = node->next) - { - SV_WriteLong(node->sequence); - SV_WriteLong(node->delayTics); - SV_WriteLong(node->volume); - SV_WriteLong(SN_GetSequenceOffset(node->sequence, - node->sequencePtr)); - SV_WriteLong(node->currentSoundID); - for (i = 0; i < po_NumPolyobjs; i++) - { - if (node->mobj == (mobj_t *) & polyobjs[i].startSpot) - { - break; - } - } - if (i == po_NumPolyobjs) - { // Sound is attached to a sector, not a polyobj - sec = R_PointInSubsector(node->mobj->x, node->mobj->y)->sector; - difference = (int) ((byte *) sec - - (byte *) & sectors[0]) / sizeof(sector_t); - SV_WriteLong(0); // 0 -- sector sound origin - } - else - { - SV_WriteLong(1); // 1 -- polyobj sound origin - difference = i; - } - SV_WriteLong(difference); - } -} - -//========================================================================== -// -// UnarchiveSounds -// -//========================================================================== - -static void UnarchiveSounds(void) -{ - int i; - int numSequences; - int sequence; - int delayTics; - int volume; - int seqOffset; - int soundID; - int polySnd; - int secNum; - mobj_t *sndMobj; - - AssertSegment(ASEG_SOUNDS); - - // Reload and restart all sound sequences - numSequences = SV_ReadLong(); - i = 0; - while (i < numSequences) - { - sequence = SV_ReadLong(); - delayTics = SV_ReadLong(); - volume = SV_ReadLong(); - seqOffset = SV_ReadLong(); - - soundID = SV_ReadLong(); - polySnd = SV_ReadLong(); - secNum = SV_ReadLong(); - if (!polySnd) - { - sndMobj = (mobj_t *) & sectors[secNum].soundorg; - } - else - { - sndMobj = (mobj_t *) & polyobjs[secNum].startSpot; - } - SN_StartSequence(sndMobj, sequence); - SN_ChangeNodeData(i, seqOffset, delayTics, volume, soundID); - i++; - } -} - -//========================================================================== -// -// ArchivePolyobjs -// -//========================================================================== - -static void ArchivePolyobjs(void) -{ - int i; - - SV_WriteLong(ASEG_POLYOBJS); - SV_WriteLong(po_NumPolyobjs); - for (i = 0; i < po_NumPolyobjs; i++) - { - SV_WriteLong(polyobjs[i].tag); - SV_WriteLong(polyobjs[i].angle); - SV_WriteLong(polyobjs[i].startSpot.x); - SV_WriteLong(polyobjs[i].startSpot.y); - } -} - -//========================================================================== -// -// UnarchivePolyobjs -// -//========================================================================== - -static void UnarchivePolyobjs(void) -{ - int i; - fixed_t deltaX; - fixed_t deltaY; - - AssertSegment(ASEG_POLYOBJS); - if (SV_ReadLong() != po_NumPolyobjs) - { - I_Error("UnarchivePolyobjs: Bad polyobj count"); - } - for (i = 0; i < po_NumPolyobjs; i++) - { - if (SV_ReadLong() != polyobjs[i].tag) - { - I_Error("UnarchivePolyobjs: Invalid polyobj tag"); - } - PO_RotatePolyobj(polyobjs[i].tag, (angle_t) SV_ReadLong()); - deltaX = SV_ReadLong() - polyobjs[i].startSpot.x; - deltaY = SV_ReadLong() - polyobjs[i].startSpot.y; - PO_MovePolyobj(polyobjs[i].tag, deltaX, deltaY); - } -} - -//========================================================================== -// -// AssertSegment -// -//========================================================================== - -static void AssertSegment(gameArchiveSegment_t segType) -{ - if (SV_ReadLong() != segType) - { - I_Error("Corrupt save game: Segment [%d] failed alignment check", - segType); - } -} - -//========================================================================== -// -// ClearSaveSlot -// -// Deletes all save game files associated with a slot number. -// -//========================================================================== - -static void ClearSaveSlot(int slot) -{ - int i; - char fileName[100]; - - for (i = 0; i < MAX_MAPS; i++) - { - M_snprintf(fileName, sizeof(fileName), - "%shex%d%02d.hxs", SavePath, slot, i); - M_remove(fileName); - } - M_snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, slot); - M_remove(fileName); -} - -//========================================================================== -// -// CopySaveSlot -// -// Copies all the save game files from one slot to another. -// -//========================================================================== - -static void CopySaveSlot(int sourceSlot, int destSlot) -{ - int i; - char sourceName[100]; - char destName[100]; - - for (i = 0; i < MAX_MAPS; i++) - { - M_snprintf(sourceName, sizeof(sourceName), - "%shex%d%02d.hxs", SavePath, sourceSlot, i); - if (ExistingFile(sourceName)) - { - M_snprintf(destName, sizeof(destName), - "%shex%d%02d.hxs", SavePath, destSlot, i); - CopyFile(sourceName, destName); - } - } - M_snprintf(sourceName, sizeof(sourceName), - "%shex%d.hxs", SavePath, sourceSlot); - if (ExistingFile(sourceName)) - { - M_snprintf(destName, sizeof(destName), - "%shex%d.hxs", SavePath, destSlot); - CopyFile(sourceName, destName); - } - else - { - I_Error("Could not load savegame %s", sourceName); - } -} - -//========================================================================== -// -// CopyFile -// -// This function was rewritten to copy files with minimal strain on zone -// allocation and allow for big maps that technically work in vanilla to -// save without error. -//========================================================================== - -static void CopyFile(char *source_name, char *dest_name) -{ - const int BUFFER_CHUNK_SIZE = 0x10000; - - byte *buffer; - int file_length, file_remaining; - FILE *read_handle, *write_handle; - int buf_count, read_count, write_count; - - read_handle = M_fopen(source_name, "rb"); - if (read_handle == NULL) - { - I_Error ("Couldn't read file %s", source_name); - } - file_length = file_remaining = M_FileLength(read_handle); - - // Vanilla savegame emulation. - // - // CopyFile() typically calls M_ReadFile() which stores the entire file - // in memory: Chocolate Hexen should force an allocation error here - // whenever it's appropriate. - - if (vanilla_savegame_limit) - { - buffer = Z_Malloc(file_length, PU_STATIC, NULL); - Z_Free(buffer); - } - - write_handle = M_fopen(dest_name, "wb"); - if (write_handle == NULL) - { - I_Error ("Couldn't read file %s", dest_name); - } - - buffer = Z_Malloc (BUFFER_CHUNK_SIZE, PU_STATIC, NULL); - - do - { - buf_count = BUFFER_CHUNK_SIZE; - if( file_remaining < BUFFER_CHUNK_SIZE) - { - buf_count = file_remaining; - } - - read_count = fread(buffer, 1, buf_count, read_handle); - if (read_count < buf_count) - { - I_Error ("Couldn't read file %s", source_name); - } - - write_count = fwrite(buffer, 1, buf_count, write_handle); - if (write_count < buf_count) - { - I_Error ("Couldn't write to file %s", dest_name); - } - - file_remaining -= buf_count; - } while (file_remaining > 0); - - Z_Free(buffer); - fclose(read_handle); - fclose(write_handle); -} - -//========================================================================== -// -// ExistingFile -// -//========================================================================== - -static boolean ExistingFile(char *name) -{ - FILE *fp; - - if ((fp = M_fopen(name, "rb")) != NULL) - { - fclose(fp); - return true; - } - else - { - return false; - } -} - -//========================================================================== -// -// SV_Open -// -//========================================================================== - -static void SV_OpenRead(char *fileName) -{ - SavingFP = M_fopen(fileName, "rb"); - - // Should never happen, only if hex6.hxs cannot ever be created. - if (SavingFP == NULL) - { - I_Error("Could not load savegame %s", fileName); - } -} - -static void SV_OpenWrite(char *fileName) -{ - SavingFP = M_fopen(fileName, "wb"); -} - -//========================================================================== -// -// SV_Close -// -//========================================================================== - -static void SV_Close(void) -{ - if (SavingFP) - { - fclose(SavingFP); - SavingFP = NULL; - } -} - -//========================================================================== -// -// SV_Read -// -//========================================================================== - -static void SV_Read(void *buffer, int size) -{ - int retval = fread(buffer, 1, size, SavingFP); - if (retval != size) - { - I_Error("Incomplete read in SV_Read: Expected %d, got %d bytes", - size, retval); - } -} - -static byte SV_ReadByte(void) -{ - byte result; - SV_Read(&result, sizeof(byte)); - return result; -} - -static uint16_t SV_ReadWord(void) -{ - uint16_t result; - SV_Read(&result, sizeof(unsigned short)); - return SHORT(result); -} - -static uint32_t SV_ReadLong(void) -{ - uint32_t result; - SV_Read(&result, sizeof(int)); - return LONG(result); -} - -static void *SV_ReadPtr(void) -{ - return (void *) (intptr_t) SV_ReadLong(); -} - -//========================================================================== -// -// SV_Write -// -//========================================================================== - -static void SV_Write(const void *buffer, int size) -{ - fwrite(buffer, size, 1, SavingFP); -} - -static void SV_WriteByte(byte val) -{ - fwrite(&val, sizeof(byte), 1, SavingFP); -} - -static void SV_WriteWord(unsigned short val) -{ - val = SHORT(val); - fwrite(&val, sizeof(unsigned short), 1, SavingFP); -} - -static void SV_WriteLong(unsigned int val) -{ - val = LONG(val); - fwrite(&val, sizeof(int), 1, SavingFP); -} - -static void SV_WritePtr(void *val) -{ - long ptr; - - // Write a pointer value. In Vanilla Hexen pointers are 32-bit but - // nowadays they might be larger. Whatever value we write here isn't - // going to be much use when we reload the game. - - ptr = (long)(intptr_t) val; - SV_WriteLong((unsigned int) (ptr & 0xffffffff)); -} diff --git a/games/NXDoom/src/hexen/textdefs.h b/games/NXDoom/src/hexen/textdefs.h deleted file mode 100644 index febeb178d54..00000000000 --- a/games/NXDoom/src/hexen/textdefs.h +++ /dev/null @@ -1,172 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -// MN_menu.c --------------------------------------------------------------- - -#define PRESSKEY "press a key." -#define PRESSYN "press y or n." -#define TXT_PAUSED "PAUSED" -#define QUITMSG "are you sure you want to\nquit this great game?" -#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY -#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY -#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY -#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY -#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN -#define QLPROMPT "do you want to quickload the game named"\ - "\n\n'%s'?\n\n"PRESSYN -#define NEWGAME "you can't start a new game\n"\ - "while in a network game.\n\n"PRESSKEY -#define MSGOFF "Messages OFF" -#define MSGON "Messages ON" -#define NETEND "you can't end a netgame!\n\n"PRESSKEY -#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN -#define DOSY "(press y to quit to dos.)" -#define TXT_GAMMA_LEVEL_OFF "GAMMA CORRECTION OFF" -#define TXT_GAMMA_LEVEL_1 "GAMMA CORRECTION LEVEL 1" -#define TXT_GAMMA_LEVEL_2 "GAMMA CORRECTION LEVEL 2" -#define TXT_GAMMA_LEVEL_3 "GAMMA CORRECTION LEVEL 3" -#define TXT_GAMMA_LEVEL_4 "GAMMA CORRECTION LEVEL 4" -#define EMPTYSTRING "empty slot" - -// P_inter.c --------------------------------------------------------------- - -// Mana - -#define TXT_MANA_1 "BLUE MANA" -#define TXT_MANA_2 "GREEN MANA" -#define TXT_MANA_BOTH "COMBINED MANA" - -// Keys - -#define TXT_KEY_STEEL "STEEL KEY" -#define TXT_KEY_CAVE "CAVE KEY" -#define TXT_KEY_AXE "AXE KEY" -#define TXT_KEY_FIRE "FIRE KEY" -#define TXT_KEY_EMERALD "EMERALD KEY" -#define TXT_KEY_DUNGEON "DUNGEON KEY" -#define TXT_KEY_SILVER "SILVER KEY" -#define TXT_KEY_RUSTED "RUSTED KEY" -#define TXT_KEY_HORN "HORN KEY" -#define TXT_KEY_SWAMP "SWAMP KEY" -#define TXT_KEY_CASTLE "CASTLE KEY" - -// Artifacts - -#define TXT_ARTIINVULNERABILITY "ICON OF THE DEFENDER" -#define TXT_ARTIHEALTH "QUARTZ FLASK" -#define TXT_ARTISUPERHEALTH "MYSTIC URN" -#define TXT_ARTISUMMON "DARK SERVANT" -#define TXT_ARTITORCH "TORCH" -#define TXT_ARTIEGG "PORKALATOR" -#define TXT_ARTIFLY "WINGS OF WRATH" -#define TXT_ARTITELEPORT "CHAOS DEVICE" -#define TXT_ARTIPOISONBAG "FLECHETTE" -#define TXT_ARTITELEPORTOTHER "BANISHMENT DEVICE" -#define TXT_ARTISPEED "BOOTS OF SPEED" -#define TXT_ARTIBOOSTMANA "KRATER OF MIGHT" -#define TXT_ARTIBOOSTARMOR "DRAGONSKIN BRACERS" -#define TXT_ARTIBLASTRADIUS "DISC OF REPULSION" -#define TXT_ARTIHEALINGRADIUS "MYSTIC AMBIT INCANT" - -// Puzzle artifacts - -#define TXT_ARTIPUZZSKULL "YORICK'S SKULL" -#define TXT_ARTIPUZZGEMBIG "HEART OF D'SPARIL" -#define TXT_ARTIPUZZGEMRED "RUBY PLANET" -#define TXT_ARTIPUZZGEMGREEN1 "EMERALD PLANET" -#define TXT_ARTIPUZZGEMGREEN2 "EMERALD PLANET" -#define TXT_ARTIPUZZGEMBLUE1 "SAPPHIRE PLANET" -#define TXT_ARTIPUZZGEMBLUE2 "SAPPHIRE PLANET" -#define TXT_ARTIPUZZBOOK1 "DAEMON CODEX" -#define TXT_ARTIPUZZBOOK2 "LIBER OSCURA" -#define TXT_ARTIPUZZSKULL2 "FLAME MASK" -#define TXT_ARTIPUZZFWEAPON "GLAIVE SEAL" -#define TXT_ARTIPUZZCWEAPON "HOLY RELIC" -#define TXT_ARTIPUZZMWEAPON "SIGIL OF THE MAGUS" -#define TXT_ARTIPUZZGEAR "CLOCK GEAR" -#define TXT_USEPUZZLEFAILED "YOU CANNOT USE THIS HERE" - -// Items - -#define TXT_ITEMHEALTH "CRYSTAL VIAL" -#define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING" -#define TXT_ITEMSHIELD1 "SILVER SHIELD" -#define TXT_ITEMSHIELD2 "ENCHANTED SHIELD" -#define TXT_ITEMSUPERMAP "MAP SCROLL" -#define TXT_ARMOR1 "MESH ARMOR" -#define TXT_ARMOR2 "FALCON SHIELD" -#define TXT_ARMOR3 "PLATINUM HELMET" -#define TXT_ARMOR4 "AMULET OF WARDING" - -// Weapons - -#define TXT_WEAPON_F2 "TIMON'S AXE" -#define TXT_WEAPON_F3 "HAMMER OF RETRIBUTION" -#define TXT_WEAPON_F4 "QUIETUS ASSEMBLED" -#define TXT_WEAPON_C2 "SERPENT STAFF" -#define TXT_WEAPON_C3 "FIRESTORM" -#define TXT_WEAPON_C4 "WRAITHVERGE ASSEMBLED" -#define TXT_WEAPON_M2 "FROST SHARDS" -#define TXT_WEAPON_M3 "ARC OF DEATH" -#define TXT_WEAPON_M4 "BLOODSCOURGE ASSEMBLED" -#define TXT_QUIETUS_PIECE "SEGMENT OF QUIETUS" -#define TXT_WRAITHVERGE_PIECE "SEGMENT OF WRAITHVERGE" -#define TXT_BLOODSCOURGE_PIECE "SEGMENT OF BLOODSCOURGE" - -// SB_bar.c ---------------------------------------------------------------- - -#define TXT_CHEATGODON "GOD MODE ON" -#define TXT_CHEATGODOFF "GOD MODE OFF" -#define TXT_CHEATNOCLIPON "NO CLIPPING ON" -#define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF" -#define TXT_CHEATWEAPONS "ALL WEAPONS" -#define TXT_CHEATHEALTH "FULL HEALTH" -#define TXT_CHEATKEYS "ALL KEYS" -#define TXT_CHEATSOUNDON "SOUND DEBUG ON" -#define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF" -#define TXT_CHEATTICKERON "TICKER ON" -#define TXT_CHEATTICKEROFF "TICKER OFF" -#define TXT_CHEATARTIFACTS3 "ALL ARTIFACTS" -#define TXT_CHEATARTIFACTSFAIL "BAD INPUT" -#define TXT_CHEATWARP "LEVEL WARP" -#define TXT_CHEATSCREENSHOT "SCREENSHOT" -#define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!" -#define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS" -#define TXT_CHEATBADINPUT "BAD INPUT" -#define TXT_CHEATNOMAP "CAN'T FIND MAP" - -// G_game.c ---------------------------------------------------------------- - -#define TXT_GAMESAVED "GAME SAVED" - -// M_misc.c ---------------------------------------------------------------- - -#define HUSTR_CHATMACRO1 "I'm ready to kick butt!" -#define HUSTR_CHATMACRO2 "I'm OK." -#define HUSTR_CHATMACRO3 "I'm not looking too good!" -#define HUSTR_CHATMACRO4 "Help!" -#define HUSTR_CHATMACRO5 "You suck!" -#define HUSTR_CHATMACRO6 "Next time, scumbag..." -#define HUSTR_CHATMACRO7 "Come here!" -#define HUSTR_CHATMACRO8 "I'll take care of it." -#define HUSTR_CHATMACRO9 "Yes" -#define HUSTR_CHATMACRO0 "No" - -// AM_map.c ---------------------------------------------------------------- - -#define AMSTR_FOLLOWON "FOLLOW MODE ON" -#define AMSTR_FOLLOWOFF "FOLLOW MODE OFF" diff --git a/games/NXDoom/src/hexen/xddefs.h b/games/NXDoom/src/hexen/xddefs.h deleted file mode 100644 index 544f4ce2806..00000000000 --- a/games/NXDoom/src/hexen/xddefs.h +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - - -#ifndef __XDDEFS__ -#define __XDDEFS__ - -#include "doomtype.h" -#include "v_patch.h" - -//-------------------------------------------------------------------------- -// -// Map level types -// -//-------------------------------------------------------------------------- - -// lump order in a map wad -enum -{ - ML_LABEL, - ML_THINGS, - ML_LINEDEFS, - ML_SIDEDEFS, - ML_VERTEXES, - ML_SEGS, - ML_SSECTORS, - ML_NODES, - ML_SECTORS, - ML_REJECT, - ML_BLOCKMAP, - ML_BEHAVIOR -}; - -typedef PACKED_STRUCT ( -{ - short x; - short y; -}) mapvertex_t; - -typedef PACKED_STRUCT ( -{ - short textureoffset; - short rowoffset; - char toptexture[8]; - char bottomtexture[8]; - char midtexture[8]; - short sector; // on viewer's side -}) mapsidedef_t; - -typedef PACKED_STRUCT ( -{ - short v1; - short v2; - short flags; - byte special; - byte arg1; - byte arg2; - byte arg3; - byte arg4; - byte arg5; - short sidenum[2]; // sidenum[1] will be -1 if one sided -}) maplinedef_t; - -#define ML_BLOCKING 0x0001 -#define ML_BLOCKMONSTERS 0x0002 -#define ML_TWOSIDED 0x0004 -#define ML_DONTPEGTOP 0x0008 -#define ML_DONTPEGBOTTOM 0x0010 -#define ML_SECRET 0x0020 // don't map as two sided: IT'S A SECRET! -#define ML_SOUNDBLOCK 0x0040 // don't let sound cross two of these -#define ML_DONTDRAW 0x0080 // don't draw on the automap -#define ML_MAPPED 0x0100 // set if already drawn in automap -#define ML_REPEAT_SPECIAL 0x0200 // special is repeatable -#define ML_SPAC_SHIFT 10 -#define ML_SPAC_MASK 0x1c00 -#define GET_SPAC(flags) ((flags&ML_SPAC_MASK)>>ML_SPAC_SHIFT) - -// Special activation types -#define SPAC_CROSS 0 // when player crosses line -#define SPAC_USE 1 // when player uses line -#define SPAC_MCROSS 2 // when monster crosses line -#define SPAC_IMPACT 3 // when projectile hits line -#define SPAC_PUSH 4 // when player/monster pushes line -#define SPAC_PCROSS 5 // when projectile crosses line - -typedef PACKED_STRUCT ( -{ - short floorheight; - short ceilingheight; - char floorpic[8]; - char ceilingpic[8]; - short lightlevel; - short special; - short tag; -}) mapsector_t; - -typedef PACKED_STRUCT ( -{ - short numsegs; - short firstseg; // segs are stored sequentially -}) mapsubsector_t; - -typedef PACKED_STRUCT ( -{ - short v1; - short v2; - short angle; - short linedef; - short side; - short offset; -}) mapseg_t; - -#define NF_SUBSECTOR 0x8000 -typedef PACKED_STRUCT ( -{ - short x, y, dx, dy; // partition line - short bbox[2][4]; // bounding box for each child - unsigned short children[2]; // if NF_SUBSECTOR its a subsector -}) mapnode_t; - -typedef PACKED_STRUCT ( -{ - short tid; - short x; - short y; - short height; - short angle; - short type; - short options; - byte special; - byte arg1; - byte arg2; - byte arg3; - byte arg4; - byte arg5; -}) mapthing_t; - -#define MTF_EASY 1 -#define MTF_NORMAL 2 -#define MTF_HARD 4 -#define MTF_AMBUSH 8 -#define MTF_DORMANT 16 -#define MTF_FIGHTER 32 -#define MTF_CLERIC 64 -#define MTF_MAGE 128 -#define MTF_GSINGLE 256 -#define MTF_GCOOP 512 -#define MTF_GDEATHMATCH 1024 - -//-------------------------------------------------------------------------- -// -// Texture definition -// -//-------------------------------------------------------------------------- - -typedef PACKED_STRUCT ( -{ - short originx; - short originy; - short patch; - short stepdir; - short colormap; -}) mappatch_t; - -typedef PACKED_STRUCT ( -{ - char name[8]; - boolean masked; - short width; - short height; - int obsolete; - short patchcount; - mappatch_t patches[1]; -}) maptexture_t; - -#endif // __XDDEFS__ diff --git a/games/NXDoom/src/i_cdmus.c b/games/NXDoom/src/i_cdmus.c deleted file mode 100644 index caad87af8d4..00000000000 --- a/games/NXDoom/src/i_cdmus.c +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// -// 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. -// -// -// Hexen CD interface. -// - -#include - -#include "SDL.h" - -#include "doomtype.h" - -#include "i_cdmus.h" - -int cd_Error; - -int I_CDMusInit(void) -{ - fprintf(stderr, - "I_CDMusInit: CD music playback is no longer supported! " - "Please use digital music packs instead:\n" - "https://www.chocolate-doom.org/wiki/index.php/Digital_music_packs\n"); - return -1; -} - -// We cannot print status messages inline during startup, they must -// be deferred until after I_CDMusInit has returned. - -void I_CDMusPrintStartup(void) -{ -} - -int I_CDMusPlay(int track) -{ - return 0; -} - -int I_CDMusStop(void) -{ - return 0; -} - -int I_CDMusResume(void) -{ - return 0; -} - -int I_CDMusSetVolume(int volume) -{ - return 0; -} - -int I_CDMusFirstTrack(void) -{ - return 0; -} - -int I_CDMusLastTrack(void) -{ - return 0; -} - -int I_CDMusTrackLength(int track_num) -{ - return 0; -} - diff --git a/games/NXDoom/src/i_cdmus.h b/games/NXDoom/src/i_cdmus.h deleted file mode 100644 index 31db2a659ae..00000000000 --- a/games/NXDoom/src/i_cdmus.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// -// 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. -// - -// i_cdmus.h - -#ifndef __ICDMUS__ -#define __ICDMUS__ - -#define CDERR_NOTINSTALLED 10 // MSCDEX not installed -#define CDERR_NOAUDIOSUPPORT 11 // CD-ROM Doesn't support audio -#define CDERR_NOAUDIOTRACKS 12 // Current CD has no audio tracks -#define CDERR_BADDRIVE 20 // Bad drive number -#define CDERR_BADTRACK 21 // Bad track number -#define CDERR_IOCTLBUFFMEM 22 // Not enough low memory for IOCTL -#define CDERR_DEVREQBASE 100 // DevReq errors - -extern int cd_Error; - -int I_CDMusInit(void); -void I_CDMusPrintStartup(void); -int I_CDMusPlay(int track); -int I_CDMusStop(void); -int I_CDMusResume(void); -int I_CDMusSetVolume(int volume); -int I_CDMusFirstTrack(void); -int I_CDMusLastTrack(void); -int I_CDMusTrackLength(int track); - -#endif diff --git a/games/NXDoom/src/i_endoom.c b/games/NXDoom/src/i_endoom.c index 9beacc90199..97a797ee8fa 100644 --- a/games/NXDoom/src/i_endoom.c +++ b/games/NXDoom/src/i_endoom.c @@ -1,19 +1,28 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Exit text-mode ENDOOM screen. -// +/**************************************************************************** + * apps/games/NXDoom/src/i_endoom.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Exit text-mode ENDOOM screen. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -24,56 +33,67 @@ #include "txt_main.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define ENDOOM_W 80 #define ENDOOM_H 25 -// -// Displays the text mode ending screen after the game quits -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i_endoom + * + * Description: + * Displays the text mode ending screen after the game quits + * + ****************************************************************************/ -void I_Endoom(byte *endoom_data) +void i_endoom(byte *endoom_data) { - unsigned char *screendata; - int y; - int indent; + unsigned char *screendata; + int y; + int indent; - // Set up text mode screen + /* Set up text mode screen */ - TXT_Init(); + txt_init(); - TXT_SetWindowTitle(PACKAGE_STRING); - // SDL2-TODO I_InitWindowTitle(); - // SDL2-TODO I_InitWindowIcon(); + txt_set_window_title(PACKAGE_STRING); - // Write the data to the screen memory + /* SDL2-TODO i_init_window_title(); + */ - screendata = TXT_GetScreenData(); + /* Write the data to the screen memory */ - indent = (ENDOOM_W - TXT_SCREEN_W) / 2; + screendata = txt_get_screen_data(); - for (y=0; y 0) + if (txt_getchar() > 0) { - break; + break; } - TXT_Sleep(0); + txt_sleep(0); } - // Shut down text mode screen + /* Shut down text mode screen */ - TXT_Shutdown(); + txt_shutdown(); } - diff --git a/games/NXDoom/src/i_endoom.h b/games/NXDoom/src/i_endoom.h index 8c8ff457fae..22a773dc45d 100644 --- a/games/NXDoom/src/i_endoom.h +++ b/games/NXDoom/src/i_endoom.h @@ -1,29 +1,40 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Exit text-mode ENDOOM screen. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_endoom.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Exit text-mode ENDOOM screen. + * + ****************************************************************************/ #ifndef __I_ENDOOM__ #define __I_ENDOOM__ -// Display the Endoom screen on shutdown. Pass a pointer to the -// ENDOOM lump. +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_GAMES_NXDOOM_ENDOOM -void I_Endoom(byte *data); +/* Display the Endoom screen on shutdown. Pass a pointer to the + * ENDOOM lump. + */ +void i_endoom(byte *data); #endif +#endif /* __I_ENDOOM__ */ diff --git a/games/NXDoom/src/i_flmusic.c b/games/NXDoom/src/i_flmusic.c deleted file mode 100644 index a0978a0f189..00000000000 --- a/games/NXDoom/src/i_flmusic.c +++ /dev/null @@ -1,332 +0,0 @@ -// -// Copyright(C) 2022 Roman Fomin -// Copyright(C) 2023 Michael Day -// -// 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. -// -// DESCRIPTION: -// FluidSynth backend - -#include "config.h" - -#ifdef HAVE_FLUIDSYNTH - -#include "fluidsynth.h" - -#if (FLUIDSYNTH_VERSION_MAJOR < 2 || \ - (FLUIDSYNTH_VERSION_MAJOR == 2 && FLUIDSYNTH_VERSION_MINOR < 2)) - -typedef int fluid_int_t; -typedef long fluid_long_long_t; - -#else - -typedef fluid_long_long_t fluid_int_t; - -#endif - -#include "SDL_mixer.h" - -#include "doomtype.h" -#include "i_system.h" -#include "i_sound.h" -#include "m_misc.h" -#include "memio.h" -#include "mus2mid.h" - -#include - -char *fsynth_sf_path = ""; -int fsynth_chorus_active = 1; -float fsynth_chorus_depth = 5.0f; -float fsynth_chorus_level = 0.35f; -int fsynth_chorus_nr = 3; -float fsynth_chorus_speed = 0.3f; -char *fsynth_midibankselect = "gs"; -int fsynth_polyphony = 256; -int fsynth_reverb_active = 1; -float fsynth_reverb_damp = 0.4f; -float fsynth_reverb_level = 0.15f; -float fsynth_reverb_roomsize = 0.6f; -float fsynth_reverb_width = 4.0f; -float fsynth_gain = 1.0f; - -static fluid_synth_t *synth = NULL; -static fluid_settings_t *settings = NULL; -static fluid_player_t *player = NULL; - -static void FL_Mix_Callback(void *udata, Uint8 *stream, int len) -{ - int result; - - result = fluid_synth_write_s16(synth, len / 4, stream, 0, 2, stream, 1, 2); - - if (result != FLUID_OK) - { - fprintf(stderr, - "FL_Mix_Callback: Error generating FluidSynth audio.\n"); - } -} - -static boolean I_FL_InitMusic(void) -{ - int sf_id; - - if (strlen(fsynth_sf_path) == 0) - { - fprintf(stderr, - "I_FL_InitMusic: No FluidSynth soundfont file specified.\n"); - return false; - } - - settings = new_fluid_settings(); - - fluid_settings_setnum(settings, "synth.sample-rate", snd_samplerate); - fluid_settings_setstr(settings, "synth.midi-bank-select", - fsynth_midibankselect); - fluid_settings_setint(settings, "synth.polyphony", fsynth_polyphony); - - fluid_settings_setint(settings, "synth.chorus.active", - fsynth_chorus_active); - fluid_settings_setint(settings, "synth.reverb.active", - fsynth_reverb_active); - - if (fsynth_reverb_active) - { - fluid_settings_setnum(settings, "synth.reverb.room-size", - fsynth_reverb_roomsize); - fluid_settings_setnum(settings, "synth.reverb.damp", - fsynth_reverb_damp); - fluid_settings_setnum(settings, "synth.reverb.width", - fsynth_reverb_width); - fluid_settings_setnum(settings, "synth.reverb.level", - fsynth_reverb_level); - } - - if (fsynth_chorus_active) - { - fluid_settings_setnum(settings, "synth.chorus.level", - fsynth_chorus_level); - fluid_settings_setnum(settings, "synth.chorus.depth", - fsynth_chorus_depth); - fluid_settings_setint(settings, "synth.chorus.nr", fsynth_chorus_nr); - fluid_settings_setnum(settings, "synth.chorus.speed", - fsynth_chorus_speed); - } - - if (fsynth_gain < 0.0f) - { - fsynth_gain = 0.0f; - } - if (fsynth_gain > 10.0f) - { - fsynth_gain = 10.0f; - } - - synth = new_fluid_synth(settings); - - if (synth == NULL) - { - fprintf(stderr, - "I_FL_InitMusic: FluidSynth failed to initialize synth.\n"); - return false; - } - - sf_id = fluid_synth_sfload(synth, fsynth_sf_path, true); - if (sf_id == FLUID_FAILED) - { - delete_fluid_synth(synth); - synth = NULL; - delete_fluid_settings(settings); - settings = NULL; - fprintf(stderr, - "I_FL_InitMusic: Error loading FluidSynth soundfont: '%s'.\n", - fsynth_sf_path); - return false; - } - - printf("I_FL_InitMusic: Using '%s'.\n", fsynth_sf_path); - - return true; -} - -static void I_FL_SetMusicVolume(int volume) -{ - if (synth == NULL) - { - return; - } - // FluidSynth's default is 0.2. Make 1.0 the maximum. - // 0 -- 0.2 -- 10.0 - fluid_synth_set_gain(synth, ((float) volume / 127) * fsynth_gain); -} - -static void I_FL_PauseSong(void) -{ - if (player) - { - Mix_HookMusic(NULL, NULL); - } -} - -static void I_FL_ResumeSong(void) -{ - if (player) - { - Mix_HookMusic(FL_Mix_Callback, NULL); - } -} - -static void I_FL_PlaySong(void *handle, boolean looping) -{ - if (player) - { - fluid_player_set_loop(player, looping ? -1 : 1); - fluid_player_play(player); - } -} - -static void I_FL_StopSong(void) -{ - if (player) - { - fluid_player_stop(player); - } -} - -// Determine whether memory block is a .mid file - -static boolean IsMid(const byte *mem, int len) -{ - return len > 4 && !memcmp(mem, "MThd", 4); -} - -static void *I_FL_RegisterSong(void *data, int len) -{ - int result = FLUID_FAILED; - - player = new_fluid_player(synth); - - if (player == NULL) - { - fprintf(stderr, - "I_FL_RegisterSong: FluidSynth failed to initialize player.\n"); - return NULL; - } - - if (IsMid(data, len)) - { - result = fluid_player_add_mem(player, data, len); - - if (result == FLUID_FAILED) - { - fprintf(stderr, - "I_FL_RegisterSong: FluidSynth failed to load MIDI.\n"); - return NULL; - } - } - else - { - // Assume a MUS file and try to convert - MEMFILE *instream; - MEMFILE *outstream; - void *outbuf; - size_t outbuf_len; - - instream = mem_fopen_read(data, len); - outstream = mem_fopen_write(); - - if (mus2mid(instream, outstream) == 0) - { - mem_get_buf(outstream, &outbuf, &outbuf_len); - result = fluid_player_add_mem(player, outbuf, outbuf_len); - } - - mem_fclose(instream); - mem_fclose(outstream); - - if (result == FLUID_FAILED) - { - fprintf(stderr, - "I_FL_RegisterSong: FluidSynth failed to load MUS.\n"); - return NULL; - } - } - - Mix_HookMusic(FL_Mix_Callback, NULL); - return player; -} - -static void I_FL_UnRegisterSong(void *handle) -{ - if (player) - { - fluid_synth_program_reset(synth); - fluid_synth_system_reset(synth); - - Mix_HookMusic(NULL, NULL); - - delete_fluid_player(player); - player = NULL; - } -} - -static void I_FL_ShutdownMusic(void) -{ - I_FL_StopSong(); - I_FL_UnRegisterSong(NULL); - - if (synth) - { - delete_fluid_synth(synth); - synth = NULL; - } - - if (settings) - { - delete_fluid_settings(settings); - settings = NULL; - } -} - -static boolean I_FL_MusicIsPlaying(void) -{ - if (player == NULL) - { - return false; - } - - return (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING); -} - -static const snddevice_t music_fl_devices[] = -{ - SNDDEVICE_FSYNTH, -}; - -const music_module_t music_fl_module = -{ - music_fl_devices, - arrlen(music_fl_devices), - I_FL_InitMusic, - I_FL_ShutdownMusic, - I_FL_SetMusicVolume, - I_FL_PauseSong, - I_FL_ResumeSong, - I_FL_RegisterSong, - I_FL_UnRegisterSong, - I_FL_PlaySong, - I_FL_StopSong, - I_FL_MusicIsPlaying, - NULL // Poll -}; - -#endif diff --git a/games/NXDoom/src/i_glob.c b/games/NXDoom/src/i_glob.c index 79c3e898366..6f2df49e094 100644 --- a/games/NXDoom/src/i_glob.c +++ b/games/NXDoom/src/i_glob.c @@ -1,373 +1,431 @@ -// -// Copyright(C) 2018 Simon Howard -// -// 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. -// -// -// File globbing API. This allows the contents of the filesystem -// to be interrogated. -// +/**************************************************************************** + * apps/games/NXDoom/src/i_glob.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2018 Simon Howard + * + * 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. + * + * + * File globbing API. This allows the contents of the filesystem + * to be interrogated. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include -#include +#include "config.h" #include "i_glob.h" #include "m_misc.h" -#include "config.h" -#if defined(_WIN32) -#include -#ifndef S_ISDIR -#define S_ISDIR(m) (((m)& S_IFMT) == S_IFDIR) -#endif -#elif defined(HAVE_DIRENT_H) +#if defined(HAVE_DIRENT_H) #include #include #elif defined(__WATCOMC__) -// Watcom has the same API in a different header. +/* Watcom has the same API in a different header. */ #include #else #define NO_DIRENT_IMPLEMENTATION #endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct glob_s +{ + char **globs; + int num_globs; + int flags; + DIR *dir; + char *directory; + char *last_filename; + + /* These fields are only used when the GLOB_FLAG_SORTED flag is set: + */ + + char **filenames; + int filenames_len; + int next_index; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + #ifndef NO_DIRENT_IMPLEMENTATION -// Only the fields d_name and (as an XSI extension) d_ino are specified -// in POSIX.1. Other than Linux, the d_type field is available mainly -// only on BSD systems. The remaining fields are available on many, but -// not all systems. -static boolean IsDirectory(char *dir, struct dirent *de) +/* Only the fields d_name and (as an XSI extension) d_ino are specified + * in POSIX.1. Other than Linux, the d_type field is available mainly + * only on BSD systems. The remaining fields are available on many, but + * not all systems. + */ + +static boolean is_directory(char *dir, struct dirent *de) { #if defined(_DIRENT_HAVE_D_TYPE) - if (de->d_type != DT_UNKNOWN && de->d_type != DT_LNK) + if (de->d_type != DT_UNKNOWN && de->d_type != DT_LNK) { - return de->d_type == DT_DIR; + return de->d_type == DT_DIR; } - else + else #endif { - char *filename; - struct stat sb; - int result; + char *filename; + struct stat sb; + int result; - filename = M_StringJoin(dir, DIR_SEPARATOR_S, de->d_name, NULL); - result = M_stat(filename, &sb); - free(filename); + filename = m_string_join(dir, DIR_SEPARATOR_S, de->d_name, NULL); + result = m_stat(filename, &sb); + free(filename); - if (result != 0) + if (result != 0) { - return false; + return false; } - return S_ISDIR(sb.st_mode); + return S_ISDIR(sb.st_mode); } } -struct glob_s -{ - char **globs; - int num_globs; - int flags; - DIR *dir; - char *directory; - char *last_filename; - // These fields are only used when the GLOB_FLAG_SORTED flag is set: - char **filenames; - int filenames_len; - int next_index; -}; - -static void FreeStringList(char **globs, int num_globs) +static void free_string_list(char **globs, int num_globs) { - int i; - for (i = 0; i < num_globs; ++i) + int i; + for (i = 0; i < num_globs; ++i) { - free(globs[i]); + free(globs[i]); } - free(globs); + + free(globs); } -glob_t *I_StartMultiGlob(const char *directory, int flags, - const char *glob, ...) +static boolean matches_glob(const char *name, const char *glob, int flags) { - char **globs; - int num_globs; - glob_t *result; - va_list args; + int n; + int g; - globs = malloc(sizeof(char *)); - if (globs == NULL) + while (*glob != '\0') { - return NULL; - } - globs[0] = M_StringDuplicate(glob); - num_globs = 1; - - va_start(args, glob); - for (;;) - { - const char *arg = va_arg(args, const char *); - char **new_globs; + n = *name; + g = *glob; - if (arg == NULL) + if ((flags & GLOB_FLAG_NOCASE) != 0) { - break; + n = tolower(n); + g = tolower(g); } - new_globs = realloc(globs, sizeof(char *) * (num_globs + 1)); - if (new_globs == NULL) + if (g == '*') { - FreeStringList(globs, num_globs); - } - globs = new_globs; - globs[num_globs] = M_StringDuplicate(arg); - ++num_globs; - } - va_end(args); + /* To handle *-matching we skip past the * and recurse + * to check each subsequent character in turn. If none + * match then the whole match is a failure. + */ - result = malloc(sizeof(glob_t)); - if (result == NULL) - { - FreeStringList(globs, num_globs); - return NULL; - } + while (*name != '\0') + { + if (matches_glob(name, glob + 1, flags)) + { + return true; + } - result->dir = opendir(directory); - if (result->dir == NULL) - { - FreeStringList(globs, num_globs); - free(result); - return NULL; - } + ++name; + } - result->directory = M_StringDuplicate(directory); - result->globs = globs; - result->num_globs = num_globs; - result->flags = flags; - result->last_filename = NULL; - result->filenames = NULL; - result->filenames_len = 0; - result->next_index = -1; - return result; -} + return glob[1] == '\0'; + } + else if (g != '?' && n != g) + { + /* For normal characters the name must match the glob, + * but for ? we don't care what the character is. + */ -glob_t *I_StartGlob(const char *directory, const char *glob, int flags) -{ - return I_StartMultiGlob(directory, flags, glob, NULL); -} + return false; + } -void I_EndGlob(glob_t *glob) -{ - if (glob == NULL) - { - return; + ++name; + ++glob; } - FreeStringList(glob->globs, glob->num_globs); - FreeStringList(glob->filenames, glob->filenames_len); + /* Match successful when glob and name end at the same time. */ - free(glob->directory); - free(glob->last_filename); - (void) closedir(glob->dir); - free(glob); + return *name == '\0'; } -static boolean MatchesGlob(const char *name, const char *glob, int flags) +static boolean matches_any_glob(const char *name, glob_t *glob) { - int n, g; + int i; - while (*glob != '\0') + for (i = 0; i < glob->num_globs; ++i) { - n = *name; - g = *glob; - - if ((flags & GLOB_FLAG_NOCASE) != 0) + if (matches_glob(name, glob->globs[i], glob->flags)) { - n = tolower(n); - g = tolower(g); - } - - if (g == '*') - { - // To handle *-matching we skip past the * and recurse - // to check each subsequent character in turn. If none - // match then the whole match is a failure. - while (*name != '\0') - { - if (MatchesGlob(name, glob + 1, flags)) - { - return true; - } - ++name; - } - return glob[1] == '\0'; + return true; } - else if (g != '?' && n != g) - { - // For normal characters the name must match the glob, - // but for ? we don't care what the character is. - return false; - } - - ++name; - ++glob; } - // Match successful when glob and name end at the same time. - return *name == '\0'; + return false; } -static boolean MatchesAnyGlob(const char *name, glob_t *glob) +static char *next_glob(glob_t *glob) { - int i; + struct dirent *de; - for (i = 0; i < glob->num_globs; ++i) + do { - if (MatchesGlob(name, glob->globs[i], glob->flags)) + de = readdir(glob->dir); + if (de == NULL) { - return true; + return NULL; } } - return false; + while (is_directory(glob->directory, de) || + !matches_any_glob(de->d_name, glob)); + + /* Return the fully-qualified path, not just the bare filename. */ + + return m_string_join(glob->directory, DIR_SEPARATOR_S, de->d_name, NULL); } -static char *NextGlob(glob_t *glob) +static void read_all_filenames(glob_t *glob) { - struct dirent *de; + char *name; + + glob->filenames = NULL; + glob->filenames_len = 0; + glob->next_index = 0; - do + for (; ; ) { - de = readdir(glob->dir); - if (de == NULL) + name = next_glob(glob); + if (name == NULL) { - return NULL; + break; } - } while (IsDirectory(glob->directory, de) - || !MatchesAnyGlob(de->d_name, glob)); - // Return the fully-qualified path, not just the bare filename. - return M_StringJoin(glob->directory, DIR_SEPARATOR_S, de->d_name, NULL); + glob->filenames = realloc(glob->filenames, + (glob->filenames_len + 1) * sizeof(char *)); + glob->filenames[glob->filenames_len] = name; + ++glob->filenames_len; + } } -static void ReadAllFilenames(glob_t *glob) +static void sort_filenames(char **filenames, int len, int flags) { - char *name; + char *pivot; + char *tmp; + int i; + int left_len; + int cmp; - glob->filenames = NULL; - glob->filenames_len = 0; - glob->next_index = 0; + if (len <= 1) + { + return; + } - for (;;) + pivot = filenames[len - 1]; + left_len = 0; + for (i = 0; i < len - 1; ++i) { - name = NextGlob(glob); - if (name == NULL) + if ((flags & GLOB_FLAG_NOCASE) != 0) { - break; + cmp = strcasecmp(filenames[i], pivot); + } + else + { + cmp = strcmp(filenames[i], pivot); + } + + if (cmp < 0) + { + tmp = filenames[i]; + filenames[i] = filenames[left_len]; + filenames[left_len] = tmp; + ++left_len; } - glob->filenames = realloc(glob->filenames, - (glob->filenames_len + 1) * sizeof(char *)); - glob->filenames[glob->filenames_len] = name; - ++glob->filenames_len; } + + filenames[len - 1] = filenames[left_len]; + filenames[left_len] = pivot; + + sort_filenames(filenames, left_len, flags); + sort_filenames(&filenames[left_len + 1], len - left_len - 1, flags); } -static void SortFilenames(char **filenames, int len, int flags) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +glob_t *i_start_multi_glob(const char *directory, int flags, + const char *glob, ...) { - char *pivot, *tmp; - int i, left_len, cmp; + char **globs; + int num_globs; + glob_t *result; + va_list args; - if (len <= 1) + globs = malloc(sizeof(char *)); + if (globs == NULL) { - return; + return NULL; } - pivot = filenames[len - 1]; - left_len = 0; - for (i = 0; i < len-1; ++i) + + globs[0] = m_string_duplicate(glob); + num_globs = 1; + + va_start(args, glob); + for (; ; ) { - if ((flags & GLOB_FLAG_NOCASE) != 0) - { - cmp = strcasecmp(filenames[i], pivot); - } - else + const char *arg = va_arg(args, const char *); + char **new_globs; + + if (arg == NULL) { - cmp = strcmp(filenames[i], pivot); + break; } - if (cmp < 0) + new_globs = realloc(globs, sizeof(char *) * (num_globs + 1)); + if (new_globs == NULL) { - tmp = filenames[i]; - filenames[i] = filenames[left_len]; - filenames[left_len] = tmp; - ++left_len; + free_string_list(globs, num_globs); } + + globs = new_globs; + globs[num_globs] = m_string_duplicate(arg); + ++num_globs; } - filenames[len - 1] = filenames[left_len]; - filenames[left_len] = pivot; - SortFilenames(filenames, left_len, flags); - SortFilenames(&filenames[left_len + 1], len - left_len - 1, flags); + va_end(args); + + result = malloc(sizeof(glob_t)); + if (result == NULL) + { + free_string_list(globs, num_globs); + return NULL; + } + + result->dir = opendir(directory); + if (result->dir == NULL) + { + free_string_list(globs, num_globs); + free(result); + return NULL; + } + + result->directory = m_string_duplicate(directory); + result->globs = globs; + result->num_globs = num_globs; + result->flags = flags; + result->last_filename = NULL; + result->filenames = NULL; + result->filenames_len = 0; + result->next_index = -1; + return result; } -const char *I_NextGlob(glob_t *glob) +glob_t *i_start_glob(const char *directory, const char *glob, int flags) { - const char *result; + return i_start_multi_glob(directory, flags, glob, NULL); +} - if (glob == NULL) +void i_end_glob(glob_t *glob) +{ + if (glob == NULL) { - return NULL; + return; } - // In unsorted mode we just return the filenames as we read - // them back from the system API. - if ((glob->flags & GLOB_FLAG_SORTED) == 0) + free_string_list(glob->globs, glob->num_globs); + free_string_list(glob->filenames, glob->filenames_len); + + free(glob->directory); + free(glob->last_filename); + (void)closedir(glob->dir); + free(glob); +} + +const char *i_next_glob(glob_t *glob) +{ + const char *result; + + if (glob == NULL) { - free(glob->last_filename); - glob->last_filename = NextGlob(glob); - return glob->last_filename; + return NULL; } - // In sorted mode we read the whole list of filenames into memory, - // sort them and return them one at a time. - if (glob->next_index < 0) + /* In unsorted mode we just return the filenames as we read + * them back from the system API. + */ + + if ((glob->flags & GLOB_FLAG_SORTED) == 0) { - ReadAllFilenames(glob); - SortFilenames(glob->filenames, glob->filenames_len, glob->flags); + free(glob->last_filename); + glob->last_filename = next_glob(glob); + return glob->last_filename; } - if (glob->next_index >= glob->filenames_len) + + /* In sorted mode we read the whole list of filenames into memory, + * sort them and return them one at a time. + */ + + if (glob->next_index < 0) { - return NULL; + read_all_filenames(glob); + sort_filenames(glob->filenames, glob->filenames_len, glob->flags); } - result = glob->filenames[glob->next_index]; - ++glob->next_index; - return result; + + if (glob->next_index >= glob->filenames_len) + { + return NULL; + } + + result = glob->filenames[glob->next_index]; + ++glob->next_index; + return result; } #else /* #ifdef NO_DIRENT_IMPLEMENTATION */ -#warning No native implementation of file globbing. +#warning "No native implementation of file globbing." -glob_t *I_StartGlob(const char *directory, const char *glob, int flags) +glob_t *i_start_glob(const char *directory, const char *glob, int flags) { - return NULL; + return NULL; } -void I_EndGlob(glob_t *glob) +void i_end_glob(glob_t *glob) { + return; } -const char *I_NextGlob(glob_t *glob) +const char *i_next_glob(glob_t *glob) { - return ""; + return ""; } -#endif /* #ifdef NO_DIRENT_IMPLEMENTATION */ +glob_t *i_start_multi_glob(const char *directory, int flags, + const char *glob, ...) +{ + return NULL; +} +#endif /* NO_DIRENT_IMPLEMENTATION */ diff --git a/games/NXDoom/src/i_glob.h b/games/NXDoom/src/i_glob.h index f976db01c4f..a151795adfc 100644 --- a/games/NXDoom/src/i_glob.h +++ b/games/NXDoom/src/i_glob.h @@ -1,44 +1,87 @@ -// -// Copyright(C) 2018 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System specific file globbing interface. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_glob.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2018 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System specific file globbing interface. + * + ****************************************************************************/ #ifndef __I_GLOB__ #define __I_GLOB__ -#define GLOB_FLAG_NOCASE 0x01 -#define GLOB_FLAG_SORTED 0x02 +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +#define GLOB_FLAG_NOCASE 0x01 +#define GLOB_FLAG_SORTED 0x02 + +/**************************************************************************** + * Public Types + ****************************************************************************/ typedef struct glob_s glob_t; -// Start reading a list of file paths from the given directory which match -// the given glob pattern. I_EndGlob() must be called on completion. -glob_t *I_StartGlob(const char *directory, const char *glob, int flags); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: i_start_glob + * + * Description: + * Start reading a list of file paths from the given directory which match + * the given glob pattern. i_end_glob() must be called on completion. + * + ****************************************************************************/ + +glob_t *i_start_glob(const char *directory, const char *glob, int flags); + +/**************************************************************************** + * Name: i_start_multi_glob + * + * Description: + * Same as i_start_glob but multiple glob patterns can be provided. The list + * of patterns must be terminated with NULL. + * + ****************************************************************************/ + +glob_t *i_start_multi_glob(const char *directory, int flags, + const char *glob, ...); -// Same as I_StartGlob but multiple glob patterns can be provided. The list -// of patterns must be terminated with NULL. -glob_t *I_StartMultiGlob(const char *directory, int flags, - const char *glob, ...); +/**************************************************************************** + * Name: i_end_glob + * + * Description: + * Finish reading file list. + * + ****************************************************************************/ -// Finish reading file list. -void I_EndGlob(glob_t *glob); +void i_end_glob(glob_t *glob); -// Read the name of the next globbed filename. NULL is returned if there -// are no more found. -const char *I_NextGlob(glob_t *glob); +/**************************************************************************** + * Name: i_next_glob + * + * Description: + * Read the name of the next globbed filename. NULL is returned if there + * are no more found. + * + ****************************************************************************/ -#endif +const char *i_next_glob(glob_t *glob); +#endif /* __I_GLOB__ */ diff --git a/games/NXDoom/src/i_input.c b/games/NXDoom/src/i_input.c index 091aa6b88eb..8cb3a863019 100644 --- a/games/NXDoom/src/i_input.c +++ b/games/NXDoom/src/i_input.c @@ -1,473 +1,402 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// SDL implementation of system-specific input interface. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_input.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * SDL implementation of system-specific input interface. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include #include +#include -#include "SDL.h" -#include "SDL_keycode.h" +#ifdef CONFIG_GAMES_NXDOOM_KEYBOARD +#include +#endif +#include "d_event.h" #include "doomkeys.h" #include "doomtype.h" -#include "d_event.h" #include "i_input.h" #include "m_argv.h" #include "m_config.h" -static const int scancode_translate_table[] = SCANCODE_TO_KEYS_ARRAY; +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct keyboard_dev +{ + int fd; + bool inited; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_GAMES_NXDOOM_KEYBOARD +struct keyboard_dev g_kbd_dev = +{ + .fd = -1, + .inited = false, +}; +#endif + +#if 0 +static const int g_scancode_translate_table[] = SCANCODE_TO_KEYS_ARRAY; + +/* Lookup table for mapping ASCII characters to their equivalent when + * shift is pressed on a US layout keyboard. This is the original table + * as found in the Doom sources, comments and all. + */ -// Lookup table for mapping ASCII characters to their equivalent when -// shift is pressed on a US layout keyboard. This is the original table -// as found in the Doom sources, comments and all. static const char shiftxform[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ' ', '!', '"', '#', '$', '%', '&', - '"', // shift-' + '"', /* shift-' */ '(', ')', '*', '+', - '<', // shift-, - '_', // shift-- - '>', // shift-. - '?', // shift-/ - ')', // shift-0 - '!', // shift-1 - '@', // shift-2 - '#', // shift-3 - '$', // shift-4 - '%', // shift-5 - '^', // shift-6 - '&', // shift-7 - '*', // shift-8 - '(', // shift-9 + '<', /* shift-, */ + '_', /* shift-- */ + '>', /* shift-. */ + '?', /* shift-/ */ + ')', /* shift-0 */ + '!', /* shift-1 */ + '@', /* shift-2 */ + '#', /* shift-3 */ + '$', /* shift-4 */ + '%', /* shift-5 */ + '^', /* shift-6 */ + '&', /* shift-7 */ + '*', /* shift-8 */ + '(', /* shift-9 */ ':', - ':', // shift-; + ':', /* shift-; */ '<', - '+', // shift-= + '+', /* shift-= */ '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '[', // shift-[ - '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK - ']', // shift-] + '[', /* shift-[ */ + '!', /* shift-backslash - OH MY GOD DOES WATCOM SUCK */ + ']', /* shift-] */ '"', '_', - '\'', // shift-` + '\'', /* shift-` */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127 }; -// If true, I_StartTextInput() has been called, and we are populating -// the data3 field of ev_keydown events. +/* If true, i_start_text_input() has been called, and we are populating + * the data3 field of ev_keydown events. + */ + static boolean text_input_enabled = true; -// Bit mask of mouse button state. +/* Bit mask of mouse button state. */ + static unsigned int mouse_button_state = 0; +#endif + +/* Disallow mouse and joystick movement to cause forward/backward + * motion. Specified with the '-novert' command line parameter. + * This is an int to allow saving to config file + */ -// Disallow mouse and joystick movement to cause forward/backward -// motion. Specified with the '-novert' command line parameter. -// This is an int to allow saving to config file int novert = 0; -// If true, keyboard mapping is ignored, like in Vanilla Doom. -// The sensible thing to do is to disable this if you have a non-US -// keyboard. +/* If true, keyboard mapping is ignored, like in Vanilla Doom. + * The sensible thing to do is to disable this if you have a non-US + * keyboard. + */ int vanilla_keyboard_mapping = true; -// Mouse acceleration -// -// This emulates some of the behavior of DOS mouse drivers by increasing -// the speed when the mouse is moved fast. -// -// The mouse input values are input directly to the game, but when -// the values exceed the value of mouse_threshold, they are multiplied -// by mouse_acceleration to increase the speed. +/* Mouse acceleration + * + * This emulates some of the behavior of DOS mouse drivers by increasing + * the speed when the mouse is moved fast. + * + * The mouse input values are input directly to the game, but when + * the values exceed the value of mouse_threshold, they are multiplied + * by mouse_acceleration to increase the speed. + */ + float mouse_acceleration = 2.0; int mouse_threshold = 10; -// Translates the SDL key to a value of the type found in doomkeys.h -static int TranslateKey(SDL_Keysym *sym) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: init_kbd_dev + * + * Description: + * Set up the keyboard device for getting keyboard events. + * + * Return: + * 0 on success, error code otherwise. + * + ****************************************************************************/ + +static int init_kbd_dev(struct keyboard_dev *dev) { - int scancode = sym->scancode; - - switch (scancode) + if (dev->inited) { - case SDL_SCANCODE_LCTRL: - case SDL_SCANCODE_RCTRL: - return KEY_RCTRL; - - case SDL_SCANCODE_LSHIFT: - case SDL_SCANCODE_RSHIFT: - return KEY_RSHIFT; - - case SDL_SCANCODE_LALT: - return KEY_LALT; - - case SDL_SCANCODE_RALT: - return KEY_RALT; - - default: - if (scancode >= 0 && scancode < arrlen(scancode_translate_table)) - { - return scancode_translate_table[scancode]; - } - else - { - return 0; - } + return 0; } -} -// Get the localized version of the key press. This takes into account the -// keyboard layout, but does not apply any changes due to modifiers, (eg. -// shift-, alt-, etc.) -static int GetLocalizedKey(SDL_Keysym *sym) -{ - // When using Vanilla mapping, we just base everything off the scancode - // and always pretend the user is using a US layout keyboard. - if (vanilla_keyboard_mapping) + dev->fd = open(CONFIG_GAMES_NXDOOM_KBDPATH, O_RDONLY | O_NONBLOCK); + if (dev->fd < 0) { - return TranslateKey(sym); + return errno; } - else - { - int result = sym->sym; - if (result < 0 || result >= 128) - { - result = 0; - } - - return result; - } + dev->inited = true; + return 0; } -// Get the equivalent ASCII (Unicode?) character for a keypress. -static int GetTypedChar(SDL_Keysym *sym) +/**************************************************************************** + * Name: translate_key + * + * Description: + * Translates a NuttX key code into one from doomkeys.h. + * + * Return: + * The translated key code. + * + ****************************************************************************/ + +static int translate_key(uint32_t keycode) { - // We only return typed characters when entering text, after - // I_StartTextInput() has been called. Otherwise we return nothing. - if (!text_input_enabled) + switch (keycode) { - return 0; + case KEYCODE_LEFT: + return KEY_LEFTARROW; + case KEYCODE_RIGHT: + return KEY_RIGHTARROW; + case KEYCODE_UP: + return KEY_UPARROW; + case KEYCODE_DOWN: + return KEY_DOWNARROW; + case KEYCODE_ENTER: + return KEY_ENTER; + default: + return keycode; } +} - // If we're strictly emulating Vanilla, we should always act like - // we're using a US layout keyboard (in ev_keydown, data1=data2). - // Otherwise we should use the native key mapping. - if (vanilla_keyboard_mapping) - { - int result = TranslateKey(sym); +/**************************************************************************** + * Name: get_localized_key + * + * Description: + * Get the localized version of the key press. This takes into account the + * keyboard layout, but does not apply any changes due to modifiers, (eg. + * shift-, alt-, etc.) + * + ****************************************************************************/ + +static int get_localized_key(uint32_t sym) +{ + /* NOTE: Argument was SDL_Keysym *sym */ - // If shift is held down, apply the original uppercase - // translation table used under DOS. - if ((SDL_GetModState() & KMOD_SHIFT) != 0 - && result >= 0 && result < arrlen(shiftxform)) - { - result = shiftxform[result]; - } + /* When using Vanilla mapping, we just base everything off the scancode + * and always pretend the user is using a US layout keyboard. + */ - return result; + if (vanilla_keyboard_mapping) + { + return translate_key(sym); } - else + else { - SDL_Event next_event; + int result = sym; - // Special cases, where we always return a fixed value. - switch (sym->sym) + if (result < 0 || result >= 128) { - case SDLK_BACKSPACE: return KEY_BACKSPACE; - case SDLK_RETURN: return KEY_ENTER; - default: - break; + result = 0; } - // The following is a gross hack, but I don't see an easier way - // of doing this within the SDL2 API (in SDL1 it was easier). - // We want to get the fully transformed input character associated - // with this keypress - correct keyboard layout, appropriately - // transformed by any modifier keys, etc. So peek ahead in the SDL - // event queue and see if the key press is immediately followed by - // an SDL_TEXTINPUT event. If it is, it's reasonable to assume the - // key press and the text input are connected. Technically the SDL - // API does not guarantee anything of the sort, but in practice this - // is what happens and I've verified it through manual inspect of - // the SDL source code. - // - // In an ideal world we'd split out ev_keydown into a separate - // ev_textinput event, as SDL2 has done. But this doesn't work - // (I experimented with the idea), because lots of Doom's code is - // based around different responders "eating" events to stop them - // being passed on to another responder. If code is listening for - // a text input, it cannot block the corresponding keydown events - // which can affect other responders. - // - // So we're stuck with this as a rather fragile alternative. - - if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT, - SDL_FIRSTEVENT, SDL_LASTEVENT) == 1 - && next_event.type == SDL_TEXTINPUT) - { - // If an SDL_TEXTINPUT event is found, we always assume it - // matches the key press. The input text must be a single - // ASCII character - if it isn't, it's possible the input - // char is a Unicode value instead; better to send a null - // character than the unshifted key. - if (strlen(next_event.text.text) == 1 - && (next_event.text.text[0] & 0x80) == 0) - { - return next_event.text.text[0]; - } - } - - // Failed to find anything :/ - return 0; + return result; } } -void I_HandleKeyboardEvent(SDL_Event *sdlevent) -{ - // XXX: passing pointers to event for access after this function - // has terminated is undefined behaviour - event_t event; - - switch (sdlevent->type) - { - case SDL_KEYDOWN: - event.type = ev_keydown; - event.data1 = TranslateKey(&sdlevent->key.keysym); - event.data2 = GetLocalizedKey(&sdlevent->key.keysym); - event.data3 = GetTypedChar(&sdlevent->key.keysym); - - if (event.data1 != 0) - { - D_PostEvent(&event); - } - break; - - case SDL_KEYUP: - event.type = ev_keyup; - event.data1 = TranslateKey(&sdlevent->key.keysym); - - // data2/data3 are initialized to zero for ev_keyup. - // For ev_keydown it's the shifted Unicode character - // that was typed, but if something wants to detect - // key releases it should do so based on data1 - // (key ID), not the printable char. - - event.data2 = 0; - event.data3 = 0; - - if (event.data1 != 0) - { - D_PostEvent(&event); - } - break; - - default: - break; - } -} +/**************************************************************************** + * Name: get_typed_char + * + * Description: + * Get the equivalent ASCII (Unicode?) character for a keypress. + * + ****************************************************************************/ -void I_StartTextInput(int x1, int y1, int x2, int y2) +static int get_typed_char(uint32_t sym) { - text_input_enabled = true; - - if (!vanilla_keyboard_mapping) - { - // SDL2-TODO: SDL_SetTextInputRect(...); - SDL_StartTextInput(); - } + return 0; } -void I_StopTextInput(void) -{ - text_input_enabled = false; +/**************************************************************************** + * Public Functions + ****************************************************************************/ - if (!vanilla_keyboard_mapping) - { - SDL_StopTextInput(); - } -} +#ifdef CONFIG_GAMES_NXDOOM_KEYBOARD -static void UpdateMouseButtonState(unsigned int button, boolean on) +/**************************************************************************** + * Name: get_kbd_event + * + * Description: + * Read a single keyboard event from the keyboard device. + * + * Return: + * 0 on success, error code otherwise. + * + ****************************************************************************/ + +int get_kbd_event(struct keyboard_event_s *sample) { - static event_t event; + int err; + ssize_t nbytes; + + /* Initialize the keyboard device if it isn't already */ - if (button < SDL_BUTTON_LEFT || button > MAX_MOUSE_BUTTONS) + err = init_kbd_dev(&g_kbd_dev); + if (err) { - return; + return err; } - // Note: button "0" is left, button "1" is right, - // button "2" is middle for Doom. This is different - // to how SDL sees things. - // In the end: Left=0, Right=1, Middle=2, - // WheelUp=3 WheelDown=4, XButton1=5, XButton2=6 + /* Read events until we're out of them */ - switch (button) + nbytes = read(g_kbd_dev.fd, sample, sizeof(*sample)); + if (nbytes < 0) { - case SDL_BUTTON_LEFT: - button = 0; - break; - - case SDL_BUTTON_RIGHT: - button = 1; - break; - - case SDL_BUTTON_MIDDLE: - button = 2; - break; - - default: - // SDL buttons are indexed from 1. - // And the wheel is mapped to button 3/4 - // So we have to increment 2 and decrement 1 => inc 1. - button++; - break; + err = errno; + if (err != EINTR) + { + return err; + } } - - // Turn bit representing this button on or off. - - if (on) + else if (nbytes != sizeof(*sample)) { - mouse_button_state |= (1 << button); + return EIO; } - else + else if (nbytes == 0) { - mouse_button_state &= ~(1 << button); + return EAGAIN; /* No event */ } - // Post an event with the new button state. - - event.type = ev_mouse; - event.data1 = mouse_button_state; - event.data2 = event.data3 = 0; - D_PostEvent(&event); + return 0; } +#endif -static void MapMouseWheelToButtons(SDL_MouseWheelEvent *wheel) +void i_handle_keyboard_event(struct keyboard_event_s *kevent) { - // SDL2 distinguishes button events from mouse wheel events. - // We want to treat the mouse wheel as two buttons, as per - // SDL1 - static event_t up, down; - int button; - - if (wheel->y <= 0) - { // scroll down - button = 4; - } - else - { // scroll up - button = 3; - } + /* XXX: passing pointers to event for access after this function + * has terminated is undefined behaviour + */ - // post a button down event - mouse_button_state |= (1 << button); - down.type = ev_mouse; - down.data1 = mouse_button_state; - down.data2 = down.data3 = 0; - D_PostEvent(&down); - - // post a button up event - mouse_button_state &= ~(1 << button); - up.type = ev_mouse; - up.data1 = mouse_button_state; - up.data2 = up.data3 = 0; - D_PostEvent(&up); -} + event_t event; -void I_HandleMouseEvent(SDL_Event *sdlevent) -{ - switch (sdlevent->type) + switch (kevent->type) { - case SDL_MOUSEBUTTONDOWN: - UpdateMouseButtonState(sdlevent->button.button, true); - break; + case KEYBOARD_PRESS: + event.type = ev_keydown; + event.data1 = translate_key(kevent->code); + event.data2 = get_localized_key(kevent->code); + event.data3 = get_typed_char(kevent->code); - case SDL_MOUSEBUTTONUP: - UpdateMouseButtonState(sdlevent->button.button, false); - break; + if (event.data1 != 0) + { + d_post_event(&event); + } + break; - case SDL_MOUSEWHEEL: - MapMouseWheelToButtons(&(sdlevent->wheel)); - break; + case KEYBOARD_RELEASE: + event.type = ev_keyup; + event.data1 = translate_key(kevent->code); - default: - break; - } -} + /* data2/data3 are initialized to zero for ev_keyup. + * For ev_keydown it's the shifted Unicode character + * that was typed, but if something wants to detect + * key releases it should do so based on data1 + * (key ID), not the printable char. + */ -static int AccelerateMouse(int val) -{ - if (val < 0) - return -AccelerateMouse(-val); + event.data2 = 0; + event.data3 = 0; - if (val > mouse_threshold) - { - return (int)((val - mouse_threshold) * mouse_acceleration + mouse_threshold); - } - else - { - return val; + if (event.data1 != 0) + { + d_post_event(&event); + } + break; + + default: + break; } } -// -// Read the change in mouse state to generate mouse motion events -// -// This is to combine all mouse movement for a tic into one mouse -// motion event. -void I_ReadMouse(void) +void i_start_text_input(int x1, int y1, int x2, int y2) { - int x, y; - event_t ev; +} - SDL_GetRelativeMouseState(&x, &y); +void i_stop_text_input(void) +{ +} - if (x != 0 || y != 0) - { - ev.type = ev_mouse; - ev.data1 = mouse_button_state; - ev.data2 = AccelerateMouse(x); +void i_handle_mouse_event(void) +{ + /* Argument was SDL_Event *sdlevent */ +} - if (!novert) - { - ev.data3 = -AccelerateMouse(y); - } - else - { - ev.data3 = 0; - } +/**************************************************************************** + * Name: i_read_mouse + * + * Description: + * Read the change in mouse state to generate mouse motion events. This is + * to combine all mouse movement for a tic into one mouse motion event. + * + ****************************************************************************/ - // XXX: undefined behaviour since event is scoped to - // this function - D_PostEvent(&ev); - } +void i_read_mouse(void) +{ } -// Bind all variables controlling input options. -void I_BindInputVariables(void) +/**************************************************************************** + * Name: i_bind_input_variables + * + * Description: + * Bind all variables controlling input options. + * + ****************************************************************************/ + +void i_bind_input_variables(void) { - M_BindFloatVariable("mouse_acceleration", &mouse_acceleration); - M_BindIntVariable("mouse_threshold", &mouse_threshold); - M_BindIntVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); - M_BindIntVariable("novert", &novert); + m_bind_float_variable("mouse_acceleration", &mouse_acceleration); + m_bind_int_variable("mouse_threshold", &mouse_threshold); + m_bind_int_variable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); + m_bind_int_variable("novert", &novert); } diff --git a/games/NXDoom/src/i_input.h b/games/NXDoom/src/i_input.h index 0dda76d073f..97fc81bf7fc 100644 --- a/games/NXDoom/src/i_input.h +++ b/games/NXDoom/src/i_input.h @@ -1,49 +1,77 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System-specific keyboard/mouse input. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_input.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System-specific keyboard/mouse input. + * + ****************************************************************************/ #ifndef __I_INPUT__ #define __I_INPUT__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -#include "SDL.h" +#ifdef CONFIG_GAMES_NXDOOM_KEYBOARD +#include +#endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ #define MAX_MOUSE_BUTTONS 8 +/**************************************************************************** + * Public Data + ****************************************************************************/ + extern float mouse_acceleration; extern int mouse_threshold; -void I_BindInputVariables(void); -void I_ReadMouse(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// I_StartTextInput begins text input, activating the on-screen keyboard -// (if one is used). The caller indicates that any entered text will be -// displayed in the rectangle given by the provided set of coordinates. -void I_StartTextInput(int x1, int y1, int x2, int y2); +void i_bind_input_variables(void); +void i_read_mouse(void); -// I_StopTextInput finishes text input, deactivating the on-screen keyboard -// (if one is used). -void I_StopTextInput(void); +/* i_start_text_input begins text input, activating the on-screen keyboard + * (if one is used). The caller indicates that any entered text will be + * displayed in the rectangle given by the provided set of coordinates. + */ -void I_HandleKeyboardEvent(SDL_Event *sdlevent); -void I_HandleMouseEvent(SDL_Event *sdlevent); +void i_start_text_input(int x1, int y1, int x2, int y2); +/* i_stop_text_input finishes text input, deactivating the on-screen keyboard + * (if one is used). + */ +void i_stop_text_input(void); + +void i_handle_keyboard_event(struct keyboard_event_s *kevent); +void i_handle_mouse_event(void); + +#ifdef CONFIG_GAMES_NXDOOM_KEYBOARD +int get_kbd_event(struct keyboard_event_s *sample); #endif + +#endif /* __I_INPUT__ */ diff --git a/games/NXDoom/src/i_joystick.c b/games/NXDoom/src/i_joystick.c index 9e28a100831..4ae0b3a32a7 100644 --- a/games/NXDoom/src/i_joystick.c +++ b/games/NXDoom/src/i_joystick.c @@ -1,31 +1,35 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// SDL Joystick code. -// - - -#include "SDL.h" -#include "SDL_joystick.h" -#include "SDL_gamecontroller.h" +/**************************************************************************** + * apps/games/NXDoom/src/i_joystick.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * SDL Joystick code. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include #include +#include #include -#include "doomtype.h" #include "d_event.h" +#include "doomtype.h" #include "i_joystick.h" #include "i_system.h" @@ -33,794 +37,145 @@ #include "m_fixed.h" #include "m_misc.h" -static SDL_GameController *gamepad = NULL; -static SDL_Joystick *joystick = NULL; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Configuration variables: +#define DIRECTION_DEADZONE (50 * 32768 / 100) -// Standard default.cfg Joystick enable/disable +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Configuration variables: */ + +/* Standard default.cfg Joystick enable/disable */ static int usejoystick = 0; -// Use SDL_gamecontroller interface for the selected device +/* Use SDL_gamecontroller interface for the selected device */ + static int use_gamepad = 0; -// SDL_GameControllerType of gamepad +/* SDL_GameControllerType of gamepad */ + static int gamepad_type = 0; -// SDL GUID and index of the joystick to use. +/* SDL GUID and index of the joystick to use. */ + static char *joystick_guid = ""; static int joystick_index = -1; -// Which joystick axis to use for horizontal movement, and whether to -// invert the direction: +/* Which joystick axis to use for horizontal movement, and whether to + * invert the direction: + */ static int joystick_x_axis = 0; static int joystick_x_invert = 0; -// Which joystick axis to use for vertical movement, and whether to -// invert the direction: +/* Which joystick axis to use for vertical movement, and whether to + * invert the direction: + */ static int joystick_y_axis = 1; static int joystick_y_invert = 0; -// Which joystick axis to use for strafing? +/* Which joystick axis to use for strafing? */ static int joystick_strafe_axis = -1; static int joystick_strafe_invert = 0; -// Which joystick axis to use for looking? +/* Which joystick axis to use for looking? */ static int joystick_look_axis = -1; static int joystick_look_invert = 0; -// Configurable dead zone for each axis, specified as a percentage of the axis -// max value. +/* Configurable dead zone for each axis, specified as a percentage of the + * axis max value. + */ + static int joystick_x_dead_zone = 33; static int joystick_y_dead_zone = 33; static int joystick_strafe_dead_zone = 33; static int joystick_look_dead_zone = 33; -int use_analog = 0; - -int joystick_turn_sensitivity = 10; -int joystick_move_sensitivity = 10; -int joystick_look_sensitivity = 10; - -// Virtual to physical button joystick button mapping. By default this -// is a straight mapping. -static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 -}; - -void I_ShutdownGamepad(void) -{ - if (gamepad != NULL) - { - SDL_GameControllerClose(gamepad); - gamepad = NULL; - SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); - } -} - -static int FindFirstGamepad(void) -{ - int i; - int gamepadindex = -1; - - for (i = 0; i < SDL_NumJoysticks(); ++i) - { - if (SDL_IsGameController(i)) - { - gamepadindex = i; - break; - } - } - - return gamepadindex; -} - -static int FindSpecificGamepad(SDL_JoystickGUID guid) -{ - SDL_JoystickGUID dev_guid; - int i; - int gamepadindex = -1; - - for (i = 0; i < SDL_NumJoysticks(); ++i) - { - dev_guid = SDL_JoystickGetDeviceGUID(i); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - gamepadindex = i; - break; - } - } - - return gamepadindex; -} - -static int DeviceIndexGamepad(void) -{ - SDL_JoystickGUID guid, dev_guid; - int index = -1; - - if (strcmp(joystick_guid, "")) - { - guid = SDL_JoystickGetGUIDFromString(joystick_guid); - - // First, look for the gamepad at the previously-used index. - if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) - { - dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - return joystick_index; - } - } - - // Maybe the index has moved? - index = FindSpecificGamepad(guid); - } - - // If the previous gamepad isn't present, see if a different one is - // available. - if (index < 0) - { - index = FindFirstGamepad(); - } - - return index; -} +/* Virtual to physical button joystick button mapping. By default this + * is a straight mapping. + */ -void I_InitGamepad(void) +static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = { - SDL_JoystickGUID guid; - int index; - - if (!use_gamepad) - { - return; - } - - if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) - { - return; - } - - index = DeviceIndexGamepad(); - - if (index < 0) - { - printf("I_InitGamepad: No gamepad found.\n"); - SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); - return; - } - - gamepad = SDL_GameControllerOpen(index); - - if (gamepad == NULL) - { - printf("I_InitGamepad: Failed to open gamepad: %s\n", SDL_GetError()); - SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); - return; - } - - joystick_index = index; - gamepad_type = SDL_GameControllerTypeForIndex(index); - - if (strcmp(joystick_guid, "")) - { - joystick_guid = malloc(GUID_STRING_BUF_SIZE); - } - - guid = SDL_JoystickGetDeviceGUID(joystick_index); - SDL_JoystickGetGUIDString(guid, joystick_guid, GUID_STRING_BUF_SIZE); - - // GameController events do not fire if Joystick events are disabled. - SDL_JoystickEventState(SDL_ENABLE); - SDL_GameControllerEventState(SDL_ENABLE); - - printf("I_InitGamepad: %s\n", SDL_GameControllerName(gamepad)); - I_AtExit(I_ShutdownGamepad, true); -} - -static int GetTriggerStateGamepad(SDL_GameControllerAxis trigger) -{ - return (SDL_GameControllerGetAxis(gamepad, trigger) > TRIGGER_THRESHOLD); -} - -// Get the state of the given virtual button. - -static int ReadButtonStateGamepad(int vbutton) -{ - int physbutton, state; - - // Map from virtual button to physical (SDL) button. - if (vbutton < NUM_VIRTUAL_BUTTONS) - { - physbutton = joystick_physical_buttons[vbutton]; - } - else - { - physbutton = vbutton; - } - - switch (physbutton) - { - case GAMEPAD_BUTTON_TRIGGERLEFT: - state = GetTriggerStateGamepad(SDL_CONTROLLER_AXIS_TRIGGERLEFT); - break; - - case GAMEPAD_BUTTON_TRIGGERRIGHT: - state = GetTriggerStateGamepad(SDL_CONTROLLER_AXIS_TRIGGERRIGHT); - break; - - default: - state = SDL_GameControllerGetButton(gamepad, physbutton); - break; - } - - return state; -} - -// Get a bitmask of all currently-pressed buttons - -static int GetButtonsStateGamepad(void) -{ - int i; - int result = 0; - - for (i = 0; i < MAX_VIRTUAL_BUTTONS; ++i) - { - if (ReadButtonStateGamepad(i)) - { - result |= 1u << i; - } - } - - return result; -} - -// Read the state of an axis, inverting if necessary. - -static int GetAxisStateGamepad(const int *axis_values, int axis, int invert, - int dead_zone) -{ - int result; - - // Axis -1 means disabled. - - if (axis < 0) - { - return 0; - } - - // Dead zone is expressed as percentage of axis max value - dead_zone = 32768 * dead_zone / 100; - - result = axis_values[axis]; - - if (result < dead_zone && result > -dead_zone) - { - return 0; - } - - if (invert) - { - result = -result; - } - - result *= FRACUNIT / 32768; // Want FXP number between -1 and 1 - - return result; -} - -#define DIRECTION_DEADZONE (50 * 32768 / 100) - -static int GetDirectionalInputGamepad(const int *axis_values) -{ - int value; - int dpad = JOY_DIR_NONE; - int leftstick = JOY_DIR_NONE; - int rightstick = JOY_DIR_NONE; - - // Dpad. - if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_UP)) - { - dpad |= JOY_DIR_UP; - } - - if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) - { - dpad |= JOY_DIR_DOWN; - } - - if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) - { - dpad |= JOY_DIR_LEFT; - } - - if (SDL_GameControllerGetButton(gamepad, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) - { - dpad |= JOY_DIR_RIGHT; - } - - // Left stick. - value = axis_values[SDL_CONTROLLER_AXIS_LEFTY]; - - if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) - { - if (value > 0) - { - leftstick |= JOY_DIR_DOWN; - } - else - { - leftstick |= JOY_DIR_UP; - } - } - - value = axis_values[SDL_CONTROLLER_AXIS_LEFTX]; - - if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) - { - if (value > 0) - { - leftstick |= JOY_DIR_RIGHT; - } - else - { - leftstick |= JOY_DIR_LEFT; - } - } - - // Right stick. - value = axis_values[SDL_CONTROLLER_AXIS_RIGHTX]; - - if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) - { - if (value > 0) - { - rightstick |= JOY_DIR_RIGHT; - } - else - { - rightstick |= JOY_DIR_LEFT; - } - } - - value = axis_values[SDL_CONTROLLER_AXIS_RIGHTY]; - - if (value > DIRECTION_DEADZONE || value < -DIRECTION_DEADZONE) - { - if (value > 0) - { - rightstick |= JOY_DIR_DOWN; - } - else - { - rightstick |= JOY_DIR_UP; - } - } - - return ((dpad << DPAD_SHIFT) | (leftstick << LSTICK_SHIFT) | - (rightstick << RSTICK_SHIFT)); -} - -void I_UpdateGamepad(void) -{ - if (gamepad != NULL) - { - event_t ev; - int axis_values[SDL_CONTROLLER_AXIS_MAX]; - - axis_values[SDL_CONTROLLER_AXIS_LEFTX] = - SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_LEFTX); - - axis_values[SDL_CONTROLLER_AXIS_LEFTY] = - SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_LEFTY); - - axis_values[SDL_CONTROLLER_AXIS_RIGHTX] = - SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTX); - - axis_values[SDL_CONTROLLER_AXIS_RIGHTY] = - SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTY); - - ev.type = ev_joystick; - ev.data1 = GetButtonsStateGamepad(); - ev.data2 = GetAxisStateGamepad(axis_values, joystick_x_axis, - joystick_x_invert, joystick_x_dead_zone); - ev.data3 = GetAxisStateGamepad(axis_values, joystick_y_axis, - joystick_y_invert, joystick_y_dead_zone); - ev.data4 = GetAxisStateGamepad(axis_values, joystick_strafe_axis, - joystick_strafe_invert, - joystick_strafe_dead_zone); - ev.data5 = GetAxisStateGamepad(axis_values, joystick_look_axis, - joystick_look_invert, - joystick_look_dead_zone); - ev.data6 = GetDirectionalInputGamepad(axis_values); - - D_PostEvent(&ev); - } -} - -void I_ShutdownJoystick(void) -{ - if (joystick != NULL) - { - SDL_JoystickClose(joystick); - joystick = NULL; - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } -} - -static boolean IsValidAxis(int axis) -{ - int num_axes; - - if (axis < 0) - { - return true; - } - - if (IS_BUTTON_AXIS(axis)) - { - return true; - } - - if (IS_HAT_AXIS(axis)) - { - return HAT_AXIS_HAT(axis) < SDL_JoystickNumHats(joystick); - } - - num_axes = SDL_JoystickNumAxes(joystick); - - return axis < num_axes; -} - -static int DeviceIndex(void) -{ - SDL_JoystickGUID guid, dev_guid; - int i; - - guid = SDL_JoystickGetGUIDFromString(joystick_guid); - - // GUID identifies a class of device rather than a specific device. - // Check if joystick_index has the expected GUID, as this can act - // as a tie-breaker in case there are multiple identical devices. - if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) - { - dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - return joystick_index; - } - } - - // Check all devices to look for one with the expected GUID. - for (i = 0; i < SDL_NumJoysticks(); ++i) - { - dev_guid = SDL_JoystickGetDeviceGUID(i); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - printf("I_InitJoystick: Joystick moved to index %d.\n", i); - return i; - } - } - - // No joystick found with the expected GUID. - return -1; -} - -void I_InitJoystick(void) -{ - int index; - - if (!usejoystick || !strcmp(joystick_guid, "")) - { - return; - } - - if (use_gamepad) - { - I_InitGamepad(); - return; - } - - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) - { - return; - } - - index = DeviceIndex(); - - if (index < 0) - { - printf("I_InitJoystick: Couldn't find joystick with GUID \"%s\": " - "device not found or not connected?\n", - joystick_guid); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - return; - } - - // Open the joystick - - joystick = SDL_JoystickOpen(index); - - if (joystick == NULL) - { - printf("I_InitJoystick: Failed to open joystick #%i: %s\n", index, - SDL_GetError()); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - return; - } - - if (!IsValidAxis(joystick_x_axis) - || !IsValidAxis(joystick_y_axis) - || !IsValidAxis(joystick_strafe_axis) - || !IsValidAxis(joystick_look_axis)) - { - printf("I_InitJoystick: Invalid joystick axis for configured joystick " - "(run joystick setup again)\n"); - - SDL_JoystickClose(joystick); - joystick = NULL; - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } - - SDL_JoystickEventState(SDL_ENABLE); - - // Initialized okay! + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 +}; - printf("I_InitJoystick: %s\n", SDL_JoystickName(joystick)); +/**************************************************************************** + * Public Data + ****************************************************************************/ - I_AtExit(I_ShutdownJoystick, true); -} +int use_analog = 0; -static boolean IsAxisButton(int physbutton) -{ - if (IS_BUTTON_AXIS(joystick_x_axis)) - { - if (physbutton == BUTTON_AXIS_NEG(joystick_x_axis) - || physbutton == BUTTON_AXIS_POS(joystick_x_axis)) - { - return true; - } - } - if (IS_BUTTON_AXIS(joystick_y_axis)) - { - if (physbutton == BUTTON_AXIS_NEG(joystick_y_axis) - || physbutton == BUTTON_AXIS_POS(joystick_y_axis)) - { - return true; - } - } - if (IS_BUTTON_AXIS(joystick_strafe_axis)) - { - if (physbutton == BUTTON_AXIS_NEG(joystick_strafe_axis) - || physbutton == BUTTON_AXIS_POS(joystick_strafe_axis)) - { - return true; - } - } - if (IS_BUTTON_AXIS(joystick_look_axis)) - { - if (physbutton == BUTTON_AXIS_NEG(joystick_look_axis) - || physbutton == BUTTON_AXIS_POS(joystick_look_axis)) - { - return true; - } - } +int joystick_turn_sensitivity = 10; +int joystick_move_sensitivity = 10; +int joystick_look_sensitivity = 10; - return false; -} +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// Get the state of the given virtual button. +/**************************************************************************** + * Public Functions + ****************************************************************************/ -static int ReadButtonState(int vbutton) +void i_init_joystick(void) { - int physbutton; - - // Map from virtual button to physical (SDL) button. - if (vbutton < NUM_VIRTUAL_BUTTONS) - { - physbutton = joystick_physical_buttons[vbutton]; - } - else - { - physbutton = vbutton; - } - - // Never read axis buttons as buttons. - if (IsAxisButton(physbutton)) - { - return 0; - } - - return SDL_JoystickGetButton(joystick, physbutton); } -// Get a bitmask of all currently-pressed buttons - -static int GetButtonsState(void) +void i_update_gamepad(void) { - int i; - int result = 0; - - for (i = 0; i < MAX_VIRTUAL_BUTTONS; ++i) - { - if (ReadButtonState(i)) - { - result |= 1 << i; - } - } - - return result; } -// Read the state of an axis, inverting if necessary. - -static int GetAxisState(int axis, int invert, int dead_zone) +void i_shutdown_joystick(void) { - int result; - - // Axis -1 means disabled. - - if (axis < 0) - { - return 0; - } - - // Is this a button axis, or a hat axis? - // If so, we need to handle it specially. - - result = 0; - - if (IS_BUTTON_AXIS(axis)) - { - if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_NEG(axis))) - { - result -= 32767; - } - if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_POS(axis))) - { - result += 32767; - } - } - else if (IS_HAT_AXIS(axis)) - { - int direction = HAT_AXIS_DIRECTION(axis); - int hatval = SDL_JoystickGetHat(joystick, HAT_AXIS_HAT(axis)); - - if (direction == HAT_AXIS_HORIZONTAL) - { - if ((hatval & SDL_HAT_LEFT) != 0) - { - result -= 32767; - } - else if ((hatval & SDL_HAT_RIGHT) != 0) - { - result += 32767; - } - } - else if (direction == HAT_AXIS_VERTICAL) - { - if ((hatval & SDL_HAT_UP) != 0) - { - result -= 32767; - } - else if ((hatval & SDL_HAT_DOWN) != 0) - { - result += 32767; - } - } - } - else - { - result = SDL_JoystickGetAxis(joystick, axis); - - // Dead zone is expressed as percentage of axis max value - dead_zone = 32768 * dead_zone / 100; - - if (result < dead_zone && result > -dead_zone) - { - result = 0; - } - } - - if (invert) - { - result = -result; - } - - result *= FRACUNIT / 32768; // Want FXP number between -1 and 1 - - return result; } -static int GetDirectionalInput(int x, int y) +void i_update_joystick(void) { - int retval = JOY_DIR_NONE; - - if (x > 0) - { - retval |= JOY_DIR_RIGHT; - } - else if (x < 0) - { - retval |= JOY_DIR_LEFT; - } - - if (y > 0) - { - retval |= JOY_DIR_DOWN; - } - else if (y < 0) - { - retval |= JOY_DIR_UP; - } - - return (retval << DPAD_SHIFT); } -void I_UpdateJoystick(void) +void i_bind_joystick_variables(void) { - if (use_gamepad) - { - I_UpdateGamepad(); - return; - } + int i; - if (joystick != NULL) - { - event_t ev; - - ev.type = ev_joystick; - ev.data1 = GetButtonsState(); - ev.data2 = GetAxisState(joystick_x_axis, joystick_x_invert, - joystick_x_dead_zone); - ev.data3 = GetAxisState(joystick_y_axis, joystick_y_invert, - joystick_y_dead_zone); - ev.data4 = GetAxisState(joystick_strafe_axis, joystick_strafe_invert, - joystick_strafe_dead_zone); - ev.data5 = GetAxisState(joystick_look_axis, joystick_look_invert, - joystick_look_dead_zone); - ev.data6 = GetDirectionalInput(ev.data2, ev.data3); - D_PostEvent(&ev); - } -} + m_bind_int_variable("use_joystick", &usejoystick); + m_bind_int_variable("use_gamepad", &use_gamepad); + m_bind_int_variable("gamepad_type", &gamepad_type); + m_bind_string_variable("joystick_guid", &joystick_guid); + m_bind_int_variable("joystick_index", &joystick_index); + m_bind_int_variable("joystick_x_axis", &joystick_x_axis); + m_bind_int_variable("joystick_y_axis", &joystick_y_axis); + m_bind_int_variable("joystick_strafe_axis", &joystick_strafe_axis); + m_bind_int_variable("joystick_x_invert", &joystick_x_invert); + m_bind_int_variable("joystick_y_invert", &joystick_y_invert); + m_bind_int_variable("joystick_strafe_invert", &joystick_strafe_invert); + m_bind_int_variable("joystick_look_axis", &joystick_look_axis); + m_bind_int_variable("joystick_look_invert", &joystick_look_invert); + m_bind_int_variable("joystick_x_dead_zone", &joystick_x_dead_zone); + m_bind_int_variable("joystick_y_dead_zone", &joystick_y_dead_zone); + m_bind_int_variable("joystick_strafe_dead_zone", + &joystick_strafe_dead_zone); + m_bind_int_variable("joystick_look_dead_zone", &joystick_look_dead_zone); + m_bind_int_variable("use_analog", &use_analog); + m_bind_int_variable("joystick_turn_sensitivity", + &joystick_turn_sensitivity); + m_bind_int_variable("joystick_move_sensitivity", + &joystick_move_sensitivity); + m_bind_int_variable("joystick_look_sensitivity", + &joystick_look_sensitivity); -void I_BindJoystickVariables(void) -{ - int i; - - M_BindIntVariable("use_joystick", &usejoystick); - M_BindIntVariable("use_gamepad", &use_gamepad); - M_BindIntVariable("gamepad_type", &gamepad_type); - M_BindStringVariable("joystick_guid", &joystick_guid); - M_BindIntVariable("joystick_index", &joystick_index); - M_BindIntVariable("joystick_x_axis", &joystick_x_axis); - M_BindIntVariable("joystick_y_axis", &joystick_y_axis); - M_BindIntVariable("joystick_strafe_axis", &joystick_strafe_axis); - M_BindIntVariable("joystick_x_invert", &joystick_x_invert); - M_BindIntVariable("joystick_y_invert", &joystick_y_invert); - M_BindIntVariable("joystick_strafe_invert",&joystick_strafe_invert); - M_BindIntVariable("joystick_look_axis", &joystick_look_axis); - M_BindIntVariable("joystick_look_invert", &joystick_look_invert); - M_BindIntVariable("joystick_x_dead_zone", &joystick_x_dead_zone); - M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone); - M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone); - M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone); - M_BindIntVariable("use_analog", &use_analog); - M_BindIntVariable("joystick_turn_sensitivity", &joystick_turn_sensitivity); - M_BindIntVariable("joystick_move_sensitivity", &joystick_move_sensitivity); - M_BindIntVariable("joystick_look_sensitivity", &joystick_look_sensitivity); - - for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) + for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) { - char name[32]; - M_snprintf(name, sizeof(name), "joystick_physical_button%i", i); - M_BindIntVariable(name, &joystick_physical_buttons[i]); + char name[32]; + snprintf(name, sizeof(name), "joystick_physical_button%i", i); + m_bind_int_variable(name, &joystick_physical_buttons[i]); } } - diff --git a/games/NXDoom/src/i_joystick.h b/games/NXDoom/src/i_joystick.h index 15c8daa300e..6c1ff3df593 100644 --- a/games/NXDoom/src/i_joystick.h +++ b/games/NXDoom/src/i_joystick.h @@ -1,80 +1,104 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System-specific joystick interface. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_joystick.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System-specific joystick interface. + * + ****************************************************************************/ #ifndef __I_JOYSTICK__ #define __I_JOYSTICK__ -#include "SDL_gamecontroller.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Number of "virtual" joystick buttons defined in configuration files. + * This needs to be at least as large as the number of different key + * bindings supported by the higher-level game code (joyb* variables). + */ -// Number of "virtual" joystick buttons defined in configuration files. -// This needs to be at least as large as the number of different key -// bindings supported by the higher-level game code (joyb* variables). #define NUM_VIRTUAL_BUTTONS 17 -// Max allowed number of virtual mappings. Chosen to be less than joybspeed -// autorun value. +/* Max allowed number of virtual mappings. Chosen to be less than joybspeed + * autorun value. + */ + #define MAX_VIRTUAL_BUTTONS 20 -// If this bit is set in a configuration file axis value, the axis is -// not actually a joystick axis, but instead is a "button axis". This -// means that instead of reading an SDL joystick axis, we read the -// state of two buttons to get the axis value. This is needed for eg. -// the PS3 SIXAXIS controller, where the D-pad buttons register as -// buttons, not as two axes. +/* If this bit is set in a configuration file axis value, the axis is + * not actually a joystick axis, but instead is a "button axis". This + * means that instead of reading an SDL joystick axis, we read the + * state of two buttons to get the axis value. This is needed for eg. + * the PS3 SIXAXIS controller, where the D-pad buttons register as + * buttons, not as two axes. + */ + #define BUTTON_AXIS 0x10000 -// Query whether a given axis value describes a button axis. +/* Query whether a given axis value describes a button axis. */ + #define IS_BUTTON_AXIS(axis) ((axis) >= 0 && ((axis) & BUTTON_AXIS) != 0) -// Get the individual buttons from a button axis value. -#define BUTTON_AXIS_NEG(axis) ((axis) & 0xff) -#define BUTTON_AXIS_POS(axis) (((axis) >> 8) & 0xff) +/* Get the individual buttons from a button axis value. */ + +#define BUTTON_AXIS_NEG(axis) ((axis) & 0xff) +#define BUTTON_AXIS_POS(axis) (((axis) >> 8) & 0xff) + +/* Create a button axis value from two button values. */ -// Create a button axis value from two button values. #define CREATE_BUTTON_AXIS(neg, pos) (BUTTON_AXIS | (neg) | ((pos) << 8)) -// If this bit is set in an axis value, the axis is not actually a -// joystick axis, but is a "hat" axis. This means that we read (one of) -// the hats on the joystick. -#define HAT_AXIS 0x20000 +/* If this bit is set in an axis value, the axis is not actually a + * joystick axis, but is a "hat" axis. This means that we read (one of) + * the hats on the joystick. + */ + +#define HAT_AXIS 0x20000 #define IS_HAT_AXIS(axis) ((axis) >= 0 && ((axis) & HAT_AXIS) != 0) -// Get the hat number from a hat axis value. -#define HAT_AXIS_HAT(axis) ((axis) & 0xff) -// Which axis of the hat? (horizonal or vertical) -#define HAT_AXIS_DIRECTION(axis) (((axis) >> 8) & 0xff) +/* Get the hat number from a hat axis value. */ + +#define HAT_AXIS_HAT(axis) ((axis) & 0xff) -#define CREATE_HAT_AXIS(hat, direction) \ - (HAT_AXIS | (hat) | ((direction) << 8)) +/* Which axis of the hat? (horizontal or vertical) */ + +#define HAT_AXIS_DIRECTION(axis) (((axis) >> 8) & 0xff) + +#define CREATE_HAT_AXIS(hat, direction) \ + (HAT_AXIS | (hat) | ((direction) << 8)) #define HAT_AXIS_HORIZONTAL 1 -#define HAT_AXIS_VERTICAL 2 +#define HAT_AXIS_VERTICAL 2 + +/* When a trigger reads greater than this, consider it to be pressed. 30 + * comes from XINPUT_GAMEPAD_TRIGGER_THRESHOLD in xinput.h, and is scaled + * here for the SDL_GameController trigger max value. + */ -// When a trigger reads greater than this, consider it to be pressed. 30 comes -// from XINPUT_GAMEPAD_TRIGGER_THRESHOLD in xinput.h, and is scaled here for -// the SDL_GameController trigger max value. #define TRIGGER_THRESHOLD (30 * 32767 / 255) -// To be used with SDL_JoystickGetGUIDString; see SDL_joystick.h +/* To be used with SDL_JoystickGetGUIDString; see SDL_joystick.h */ + #define GUID_STRING_BUF_SIZE 33 -// Helper macros for bitpacked directional data from gamepad inputs. +/* Helper macros for bitpacked directional data from gamepad inputs. */ + #define DPAD_SHIFT 0 #define LSTICK_SHIFT 4 #define RSTICK_SHIFT 8 @@ -82,34 +106,47 @@ #define JOY_GET_LSTICK(x) (((x) >> LSTICK_SHIFT) & 0xf) #define JOY_GET_RSTICK(x) (((x) >> RSTICK_SHIFT) & 0xf) -// 4-way direction data for gamepad directional inputs. +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* 4-way direction data for gamepad directional inputs. */ + enum { - JOY_DIR_NONE = 0x0, - JOY_DIR_UP = 0x1, - JOY_DIR_DOWN = 0x2, - JOY_DIR_LEFT = 0x4, - JOY_DIR_RIGHT = 0x8 + JOY_DIR_NONE = 0x0, + JOY_DIR_UP = 0x1, + JOY_DIR_DOWN = 0x2, + JOY_DIR_LEFT = 0x4, + JOY_DIR_RIGHT = 0x8 }; -// Extend the SDL_GameControllerButton enum to include the triggers. +/* Extend the SDL_GameControllerButton enum to include the triggers. */ + enum { - GAMEPAD_BUTTON_TRIGGERLEFT = SDL_CONTROLLER_BUTTON_MAX, - GAMEPAD_BUTTON_TRIGGERRIGHT, - GAMEPAD_BUTTON_MAX + GAMEPAD_BUTTON_TRIGGERLEFT, /* = SDL_CONTROLLER_BUTTON_MAX, */ + GAMEPAD_BUTTON_TRIGGERRIGHT, + GAMEPAD_BUTTON_MAX }; +/**************************************************************************** + * Public Data + ****************************************************************************/ + extern int use_analog; extern int joystick_turn_sensitivity; extern int joystick_move_sensitivity; extern int joystick_look_sensitivity; -void I_InitJoystick(void); -void I_ShutdownJoystick(void); -void I_UpdateJoystick(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void I_BindJoystickVariables(void); +void i_init_joystick(void); +void i_shutdown_joystick(void); +void i_update_joystick(void); -#endif /* #ifndef __I_JOYSTICK__ */ +void i_bind_joystick_variables(void); +#endif /* __I_JOYSTICK__ */ diff --git a/games/NXDoom/src/i_main.c b/games/NXDoom/src/i_main.c index 851f0e9d26f..bd9dab60910 100644 --- a/games/NXDoom/src/i_main.c +++ b/games/NXDoom/src/i_main.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Main program, simply calls D_DoomMain high level loop. -// +/**************************************************************************** + * apps/games/NXDoom/src/i_main.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Main program, simply calls d_doom_main high level loop. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "config.h" @@ -22,58 +31,57 @@ #include #include -#include "SDL.h" - #include "doomtype.h" #include "i_system.h" #include "m_argv.h" #include "m_misc.h" +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: d_doom_main() + * + * Description: + * Not a globally visible function, just included for source reference, + * calls all startup code, parses command line options. + * + ****************************************************************************/ -// -// D_DoomMain() -// Not a globally visible function, just included for source reference, -// calls all startup code, parses command line options. -// +void d_doom_main(void); -void D_DoomMain (void); +/**************************************************************************** + * Public Functions + ****************************************************************************/ int main(int argc, char **argv) { - // save arguments + /* save arguments */ - myargc = argc; - myargv = malloc(argc * sizeof(char *)); - assert(myargv != NULL); + myargc = argc; + myargv = malloc(argc * sizeof(char *)); + assert(myargv != NULL); - for (int i = 0; i < argc; i++) + for (int i = 0; i < argc; i++) { - myargv[i] = M_StringDuplicate(argv[i]); - } - - //! - // Print the program version and exit. - // - if (M_ParmExists("-version") || M_ParmExists("--version")) { - puts(PACKAGE_STRING); - exit(0); + myargv[i] = m_string_duplicate(argv[i]); } -#if defined(_WIN32) - // compose a proper command line from loose file paths passed as arguments - // to allow for loading WADs and DEHACKED patches by drag-and-drop - M_AddLooseFiles(); -#endif + /* Print the program version and exit. */ - M_FindResponseFile(); - M_SetExeDir(); + if (m_parm_exists("-version") || m_parm_exists("--version")) + { + puts(PACKAGE_STRING); + exit(0); + } - SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); + m_find_response_file(); + m_set_exe_dir(); - // start doom + /* start doom */ - D_DoomMain (); + d_doom_main(); - return 0; + return 0; } - diff --git a/games/NXDoom/src/i_musicpack.c b/games/NXDoom/src/i_musicpack.c index 10a2d16481f..733a45c7c4e 100644 --- a/games/NXDoom/src/i_musicpack.c +++ b/games/NXDoom/src/i_musicpack.c @@ -1,28 +1,34 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System interface for music. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_musicpack.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System interface for music. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include - -#include "SDL.h" #include "i_glob.h" @@ -34,8 +40,8 @@ #include "deh_str.h" #include "gusconf.h" #include "i_sound.h" -#include "i_system.h" #include "i_swap.h" +#include "i_system.h" #include "m_argv.h" #include "m_config.h" #include "m_misc.h" @@ -43,1454 +49,104 @@ #include "w_wad.h" #include "z_zone.h" +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static boolean i_null_init_music(void); +static void i_null_shutdown_music(void); +static void i_null_set_music_volume(int volume); +static void i_null_pause_song(void); +static void i_null_resume_song(void); +static void *i_null_register_song(void *data, int len); +static void i_null_unregister_song(void *handle); +static void i_null_play_song(void *handle, boolean looping); +static void i_null_stop_song(void); +static boolean i_null_musicisplaying(void); +static void i_null_pollmusic(void); + +/**************************************************************************** + * Public Data + ****************************************************************************/ char *music_pack_path = ""; - -#ifndef DISABLE_SDL2MIXER - -#include "SDL_mixer.h" - -#define MID_HEADER_MAGIC "MThd" -#define MUS_HEADER_MAGIC "MUS\x1a" - -// Starting with 2.6.0, SDL_mixer supports OGG and FLAC looping natively. -// TODO: Once SDL_mixer 2.6.0+ is a requirement, delete the old looping code. -#if !defined(USE_SDL_MIXER_LOOPING) -#if defined(SDL_MIXER_VERSION_ATLEAST) -#if SDL_MIXER_VERSION_ATLEAST(2, 6, 0) -#define USE_SDL_MIXER_LOOPING 1 -#else -#define USE_SDL_MIXER_LOOPING 0 -#endif // SDL_MIXER_VERSION_ATLEAST(2, 6, 0) -#else -#define USE_SDL_MIXER_LOOPING 0 -#endif // defined(SDL_MIXER_VERSION_ATLEAST) -#endif // !defined(USE_SDL_MIXER_LOOPING) - -#if !USE_SDL_MIXER_LOOPING -#define FLAC_HEADER "fLaC" -#define OGG_HEADER "OggS" - -// Looping Vorbis metadata tag names. These have been defined by ZDoom -// for specifying the start and end positions for looping music tracks -// in .ogg and .flac files. -// More information is here: http://zdoom.org/wiki/Audio_loop -#define LOOP_START_TAG "LOOP_START" -#define LOOP_END_TAG "LOOP_END" - -// FLAC metadata headers that we care about. -#define FLAC_STREAMINFO 0 -#define FLAC_VORBIS_COMMENT 4 - -// Ogg metadata headers that we care about. -#define OGG_ID_HEADER 1 -#define OGG_COMMENT_HEADER 3 -#endif // !USE_SDL_MIXER_LOOPING - -// Structure for music substitution. -// We store a mapping based on SHA1 checksum -> filename of substitute music -// file to play, so that substitution occurs based on content rather than -// lump name. This has some inherent advantages: -// * Music for Plutonia (reused from Doom 1) works automatically. -// * If a PWAD replaces music, the replacement music is used rather than -// the substitute music for the IWAD. -// * If a PWAD reuses music from an IWAD (even from a different game), we get -// the high quality version of the music automatically (neat!) - -typedef struct -{ - const char *hash_prefix; - const char *filename; -} subst_music_t; - -#if !USE_SDL_MIXER_LOOPING -// Structure containing parsed metadata read from a digital music track: -typedef struct -{ - boolean valid; - unsigned int samplerate_hz; - int start_time, end_time; -} file_metadata_t; -#endif // !USE_SDL_MIXER_LOOPING - -static subst_music_t *subst_music = NULL; -static unsigned int subst_music_len = 0; - -static boolean music_initialized = false; - -// If this is true, this module initialized SDL sound and has the -// responsibility to shut it down - -static boolean sdl_was_initialized = false; - -#if !USE_SDL_MIXER_LOOPING -// If true, we are playing a substitute digital track rather than in-WAD -// MIDI/MUS track, and file_metadata contains loop metadata. -static file_metadata_t file_metadata; - -// Position (in samples) that we have reached in the current track. -// This is updated by the TrackPositionCallback function. -static unsigned int current_track_pos; -#endif // !USE_SDL_MIXER_LOOPING - -// Currently playing music track. -static Mix_Music *current_track_music = NULL; - -// If true, the currently playing track is being played on loop. -static boolean current_track_loop; - -// Table of known hashes and filenames to look up for them. This allows -// users to drop in a set of files without having to also provide a -// configuration file. -static const subst_music_t known_filenames[] = { - // Doom 1 music files. - {"b2e05b4e8dff8d76f8f4", "d_inter.{ext}"}, - {"0c0acce45130bab935d2", "d_intro.{ext}"}, - {"fca4086939a68ae4ed84", "d_victor.{ext}"}, - {"5971e5e20554f47ca065", "d_intro.{ext}"}, - {"99767e32769229897f77", "d_e1m1.{ext}"}, - {"b5e7dfb4efe9e688bf2a", "d_e1m2.{ext}"}, - {"fda8fa73e4d30a6b961c", "d_e1m3.{ext}"}, - {"3805f9bf3f1702f7e7f5", "d_e1m4.{ext}"}, - {"f546ed823b234fe39165", "d_e1m5.{ext}"}, - {"4450811b5a6748cfd83e", "d_e1m6.{ext}"}, - {"73edb50d96b0ac03be34", "d_e1m7.{ext}"}, - {"47d711a6fd32f5047879", "d_e1m8.{ext}"}, - {"62c631c2fdaa5ecd9a8d", "d_e1m9.{ext}"}, - {"7702a6449585428e7185", "d_e2m1.{ext}"}, - {"1cb1810989cbfae2b29b", "d_e2m2.{ext}"}, - {"7d740f3c881a22945e47", "d_e2m4.{ext}"}, - {"ae9c3dc2f9aeea002327", "d_e2m6.{ext}"}, - {"b26aad3caa420e9a2c76", "d_e2m7.{ext}"}, - {"90f06251a2a90bfaefd4", "d_e2m8.{ext}"}, - {"b2fb439f23c08c8e2577", "d_e3m1.{ext}"}, - {"b6c07bb249526b864208", "d_e3m2.{ext}"}, - {"ce3587ee503ffe707b2d", "d_e3m3.{ext}"}, - {"d746ea2aa16b3237422c", "d_e3m8.{ext}"}, - {"3da3b1335560a92912e6", "d_bunny.{ext}"}, - - // Duplicates that don't have identical hashes: - {"4a5badc4f10a7d4ed021", "d_inter.{ext}"}, // E2M3 - {"36b14bf165b3fdd3958e", "d_e1m7.{ext}"}, // E3M5 - {"e77c3d42f2ea87f04607", "d_e1m6.{ext}"}, // E3M6 - {"3d85ec9c10b5ea465568", "d_e2m7.{ext}"}, // E3M7 - {"4d42e2ce1c1ff192500e", "d_e1m9.{ext}"}, // E3M9 - - // These tracks are reused in Alien Vendetta, but are MIDs: - {"a05e45f67e1b64733fe3", "d_e2m1.{ext}"}, // MAP02 - {"8024ae1616ddd97ce330", "d_e1m4.{ext}"}, // MAP03 - {"3af8d79ddba49edaf9eb", "d_victor.{ext}"}, // MAP05 - {"a55352c96c025b6bd08a", "d_inter.{ext}"}, // MAP07 - {"76d1fc25ab7b1b4a58d6", "d_e1m8.{ext}"}, // MAP11 - {"497777f0863eca7cea87", "d_e1m2.{ext}"}, // MAP12 - {"0228fd87f8762f112fb6", "d_e2m2.{ext}"}, // MAP13 - {"db94e8e1d7c02092eab5", "d_e1m6.{ext}"}, // MAP14 - {"5a8d7a307eebc952795c", "d_e2m7.{ext}"}, // MAP16 - {"1a36b692bf26d94a72cc", "d_e1m7.{ext}"}, // MAP23 - {"37c6cefa351b06995152", "d_e1m5.{ext}"}, // MAP27 - {"36b97b87fe98348d44b6", "d_e2m6.{ext}"}, // MAP28 - - // Doom II music files. - {"79080e9681a2d7bec3fb", "d_runnin.{ext}"}, // MAP01,15 - {"868b3aae73c7b12e92c0", "d_stalks.{ext}"}, // MAP02,11,17 - {"19237754d2eb85f41d84", "d_countd.{ext}"}, // MAP03,21 - {"00abff3b61b25a6855d2", "d_betwee.{ext}"}, // MAP04 - {"954636c7ee09edf5d98f", "d_doom.{ext}"}, // MAP05,13 - {"8d32b2b7aa3b806474c1", "d_the_da.{ext}"}, // MAP06,12,24 - {"41efc3c84bb321af2b6b", "d_shawn.{ext}"}, // MAP07,19,29 - // Assuming single D_DDTBLU: http://doomwiki.org/wiki/Doom_II_music#Trivia - {"51c0872fec9f43259318", "d_ddtblu.{ext}"}, // MAP08 - {"acb7ad85494d18235df8", "d_ddtblu.{ext}"}, // MAP14,22 - {"4b7ceccbf47e78e2fa0b", "d_in_cit.{ext}"}, // MAP09 - {"1d1f4a9edba174584e11", "d_dead.{ext}"}, // MAP10,16 - {"1736c81aac77f9bffd3d", "d_romero.{ext}"}, // MAP18,27 - {"a55d400570ad255a576b", "d_messag.{ext}"}, // MAP20,26 - {"29d30c3fbd712016f2e5", "d_ampie.{ext}"}, // MAP23 - {"bcfe9786afdcfb704afa", "d_adrian.{ext}"}, // MAP25 - {"e05c10389e71836834ae", "d_tense.{ext}"}, // MAP28 - {"b779022b1d0f0010b8f0", "d_openin.{ext}"}, // MAP30 - {"a9a5f7b0ab3be0f4fc24", "d_evil.{ext}"}, // MAP31 - {"4503d155aafec0296689", "d_ultima.{ext}"}, // MAP32 - {"56f2363f01df38908c77", "d_dm2ttl.{ext}"}, - {"71e58baf9e9dea4dd24a", "d_dm2int.{ext}"}, - {"e632318629869811f7dc", "d_read_m.{ext}"}, - - // Duplicate filenames: the above filenames are the "canonical" files - // for the given SHA1 hashes, but we can also look for these filenames - // corresponding to the duplicated music tracks too. - {"868b3aae73c7b12e92c0", "d_stlks2.{ext}"}, - {"868b3aae73c7b12e92c0", "d_stlks3.{ext}"}, - {"8d32b2b7aa3b806474c1", "d_theda2.{ext}"}, - {"8d32b2b7aa3b806474c1", "d_theda3.{ext}"}, - {"954636c7ee09edf5d98f", "d_doom2.{ext}"}, - {"acb7ad85494d18235df8", "d_ddtbl2.{ext}"}, - {"acb7ad85494d18235df8", "d_ddtbl3.{ext}"}, - {"79080e9681a2d7bec3fb", "d_runni2.{ext}"}, - {"1d1f4a9edba174584e11", "d_dead2.{ext}"}, - {"41efc3c84bb321af2b6b", "d_shawn2.{ext}"}, - {"41efc3c84bb321af2b6b", "d_shawn3.{ext}"}, - {"19237754d2eb85f41d84", "d_count2.{ext}"}, - {"a55d400570ad255a576b", "d_messg2.{ext}"}, - {"1736c81aac77f9bffd3d", "d_romer2.{ext}"}, - - // These tracks are reused in Alien Vendetta, but are MIDs: - {"9433604c098b7b1119a4", "d_in_cit.{ext}"}, // MAP26 - - // Heretic tracks. - {"12818ca0d3c957e7d57e", "mus_titl.{ext}"}, - {"5cb988538ce1b1857349", "mus_intr.{ext}"}, - {"6f126abe35a78b61b930", "mus_cptd.{ext}"}, - {"62557250f0427c067dc9", "mus_e1m1.{ext}"}, - {"1e8d5fd814490b9ae166", "mus_e1m2.{ext}"}, - {"f0f31e8834e85035d434", "mus_e1m3.{ext}"}, - {"054d6997405cc5a32b46", "mus_e1m4.{ext}"}, - {"31950ab062cc1e5ca49d", "mus_e1m5.{ext}"}, - {"7389024fbab0dff47211", "mus_e1m6.{ext}"}, - {"f2aa312dddd0a294a095", "mus_e1m7.{ext}"}, - {"cd6856731d1ae1f3aa4e", "mus_e1m8.{ext}"}, - {"d7fe793f266733d92e61", "mus_e1m9.{ext}"}, - {"933545b48fad8c66f042", "mus_e2m1.{ext}"}, - {"bf88ecd4ae1621222592", "mus_e2m2.{ext}"}, - {"4f619f87a828c2ca4801", "mus_e2m3.{ext}"}, - {"13033a83c49424b2f2ab", "mus_e2m4.{ext}"}, - {"b3851f9351ae411d9de3", "mus_e2m6.{ext}"}, - {"82539791159fbbc02a23", "mus_e2m7.{ext}"}, - {"fd9e53a49cfa62c463a0", "mus_e2m8.{ext}"}, - {"29503959324d2ca67958", "mus_e2m9.{ext}"}, - {"3aa632257c5be375b97b", "mus_e3m2.{ext}"}, - {"69ba0dce7913d53b67a8", "mus_e3m3.{ext}"}, - - // These Heretic tracks are reused in Alien Vendetta, but are MIDs: - {"51344131e8d260753ce7", "mus_e2m3.{ext}"}, // MAP15 - {"78b570b2397570440aff", "mus_e1m1.{ext}"}, // MAP19 - {"ee21ba9fad4de3dfaef0", "mus_e1m4.{ext}"}, // MAP29 - {"d2bb643a60696ccbca03", "mus_e1m9.{ext}"}, // MAP32 - - // Hexen tracks: - {"fbf55fc1ee26bd01266b", "winnowr.{ext}"}, - {"71776e2da2b7ba607d81", "jachr.{ext}"}, - {"c5c8630608b8132b33cd", "simonr.{ext}"}, - {"43683b3f55a031de88d4", "wutzitr.{ext}"}, - {"a6062883f29436ef73db", "falconr.{ext}"}, - {"512cb6cc9b558d5f0fef", "levelr.{ext}"}, - {"d31226ae75fce6a24208", "chartr.{ext}"}, - {"bf1f1e561bbdba4e699f", "swampr.{ext}"}, - {"b303193f756ca0e2de0f", "deepr.{ext}"}, - {"f0635f0386d883b00186", "fubasr.{ext}"}, - {"18f2a01f83df6e3abedc", "grover.{ext}"}, - {"b2527eb0522f08b2cf5f", "fortr.{ext}"}, - {"343addba8ba53a20a160", "foojar.{ext}"}, - {"c13109045b06b5a63386", "sixater.{ext}"}, - {"693525aaf69eac5429ab", "wobabyr.{ext}"}, - {"8f884223811c2bb8311d", "cryptr.{ext}"}, - {"de540e6826e62b32c01c", "fantar.{ext}"}, - {"efdff548df918934f71f", "blechr.{ext}"}, - {"de91f150f6a127e72e35", "voidr.{ext}"}, - {"e0497fe27289fe18515b", "chap_1r.{ext}"}, - {"f2ef1abdc3f672a3519a", "chap_2r.{ext}"}, - {"78cd9882f61cc441bef4", "chap_3r.{ext}"}, - {"97b2b575d9d096c1f89f", "chap_4r.{ext}"}, - {"ad0197a0f6c52ac30915", "chippyr.{ext}"}, - {"30506c62e9f0989ffe09", "percr.{ext}"}, - {"3542803beaa43bf1de1a", "secretr.{ext}"}, - {"81067721f40c611d09fb", "bonesr.{ext}"}, - {"4822af2e1a2eb7faf660", "octor.{ext}"}, - {"26bb3cec902ed8008fc2", "rithmr.{ext}"}, - {"94ab641c7aa93caac77a", "stalkr.{ext}"}, - {"d0a3f337c54b0703b4d3", "borkr.{ext}"}, - {"79e7781ec7eb9b9434b5", "crucibr.{ext}"}, - {"c2786e5581a7f8801969", "hexen.{ext}"}, - {"97fae9a084c0efda5151", "hub.{ext}"}, - {"c5da52d5c2ec4803ef8f", "hall.{ext}"}, - {"1e71bc0e2feafb06214e", "orb.{ext}"}, - {"bc9dcfa6632e847e03af", "chess.{ext}"}, - - // Hexen CD tracks: alternate filenames for a ripped copy of - // the CD soundtrack. - {"71776e2da2b7ba607d81", "hexen02.{ext}"}, // level 2 (jachr) - {"efdff548df918934f71f", "hexen03.{ext}"}, // level 26 (blechr) - {"c2786e5581a7f8801969", "hexen04.{ext}"}, // (hexen) - {"1e71bc0e2feafb06214e", "hexen05.{ext}"}, // (orb) - {"f0635f0386d883b00186", "hexen06.{ext}"}, // level 10 (fubasr) - {"bc9dcfa6632e847e03af", "hexen07.{ext}"}, // (chess) - {"8f884223811c2bb8311d", "hexen08.{ext}"}, // level 24 (cryptr) - {"a6062883f29436ef73db", "hexen09.{ext}"}, // level 5 (falconr) - {"4822af2e1a2eb7faf660", "hexen10.{ext}"}, // level 36 (octor) - {"26bb3cec902ed8008fc2", "hexen11.{ext}"}, // level 37 (rithmr) - {"c13109045b06b5a63386", "hexen12.{ext}"}, // level 22 (sixater) - {"fbf55fc1ee26bd01266b", "hexen13.{ext}"}, // level 1 (winnowr) - {"bf1f1e561bbdba4e699f", "hexen14.{ext}"}, // level 8 (swampr) - {"43683b3f55a031de88d4", "hexen15.{ext}"}, // level 4 (wutzitr) - {"81067721f40c611d09fb", "hexen16.{ext}"}, // level 35 (bonesr) - {"e0497fe27289fe18515b", "hexen17.{ext}"}, // level 28 (chap_1r) - {"97b2b575d9d096c1f89f", "hexen18.{ext}"}, // level 31 (chap_4r) - {"de540e6826e62b32c01c", "hexen19.{ext}"}, // level 25 (fantar) - {"343addba8ba53a20a160", "hexen20.{ext}"}, // level 21 (foojar) - {"512cb6cc9b558d5f0fef", "hexen21.{ext}"}, // level 6 (levelr) - {"c5c8630608b8132b33cd", "hexen22.{ext}"}, // level 3 (simonr) - - // Strife: - {"8ac2b2b47707f0fdf8f6", "d_logo.{ext}"}, // Title - {"62e1c58054a1f1bc39b2", "d_action.{ext}"}, // 1,15,28 - {"12fa000f3fa1edac5c4f", "d_tavern.{ext}"}, // 2 - {"695e56ab3251792d20e5", "d_danger.{ext}"}, // 3,11 - {"96fe30e8712217b60dd7", "d_fast.{ext}"}, // 4 - {"61345598a3de04aad508", "d_darker.{ext}"}, // 6,14 - {"52353e9a435b7b1cb268", "d_strike.{ext}"}, // 7,19 - {"061164504907bffc9c22", "d_slide.{ext}"}, // 8,18,22 - {"3dbb4b703ce69aafcdd5", "d_tribal.{ext}"}, // 9 - {"393773688eba050c3548", "d_march.{ext}"}, // 10 - {"3cba3c627de065a667dd", "d_mood.{ext}"}, // 12 - {"b1f65a333e5c70255784", "d_castle.{ext}"}, // 13 - {"e1455a83a04c9ac4a09f", "d_fight.{ext}"}, // 16,31 - {"17f822b7374b1f069b89", "d_spense.{ext}"}, // 17 - {"e66c5a1a7d05f021f4ae", "d_dark.{ext}"}, // 20 - {"1c92bd0625026af30dad", "d_tech.{ext}"}, // 21,27 - {"7ae280713d078de7933a", "d_drone.{ext}"}, // 23,30 - {"4a664afd0d7eae79c97a", "d_panthr.{ext}"}, // 24 - {"4a7d62beeac5601ccf21", "d_sad.{ext}"}, // 25 - {"e60e109779400f2855d7", "d_instry.{ext}"}, // 26,29 - {"b7d36878faeb291d6df5", "d_happy.{ext}"}, // Better ending - {"ff4a342c8c5ec51b06c3", "d_end.{ext}"}, // Worse ending - // This conflicts with Doom's d_intro: - //{"ec8fa484c4e85adbf700", "d_intro.{ext}"}, // 5 -}; - -#if !USE_SDL_MIXER_LOOPING -// Given a time string (for LOOP_START/LOOP_END), parse it and return -// the time (in # samples since start of track) it represents. -static unsigned int ParseVorbisTime(unsigned int samplerate_hz, char *value) -{ - char *num_start, *p; - unsigned int result = 0; - char c; - - if (strchr(value, ':') == NULL) - { - return atoi(value); - } - - result = 0; - num_start = value; - - for (p = value; *p != '\0'; ++p) - { - if (*p == '.' || *p == ':') - { - c = *p; *p = '\0'; - result = result * 60 + atoi(num_start); - num_start = p + 1; - *p = c; - } - - if (*p == '.') - { - return result * samplerate_hz - + (unsigned int) (atof(p) * samplerate_hz); - } - } - - return (result * 60 + atoi(num_start)) * samplerate_hz; -} - -// Given a vorbis comment string (eg. "LOOP_START=12345"), set fields -// in the metadata structure as appropriate. -static void ParseVorbisComment(file_metadata_t *metadata, char *comment) -{ - char *eq, *key, *value; - - eq = strchr(comment, '='); - - if (eq == NULL) - { - return; - } - - key = comment; - *eq = '\0'; - value = eq + 1; - - if (!strcmp(key, LOOP_START_TAG)) - { - metadata->start_time = ParseVorbisTime(metadata->samplerate_hz, value); - } - else if (!strcmp(key, LOOP_END_TAG)) - { - metadata->end_time = ParseVorbisTime(metadata->samplerate_hz, value); - } -} - -// Parse a vorbis comments structure, reading from the given file. -static void ParseVorbisComments(file_metadata_t *metadata, FILE *fs) -{ - uint32_t buf; - unsigned int num_comments, i, comment_len; - char *comment; - - // We must have read the sample rate already from an earlier header. - if (metadata->samplerate_hz == 0) - { - return; - } - - // Skip the starting part we don't care about. - if (fread(&buf, 4, 1, fs) < 1) - { - return; - } - if (fseek(fs, LONG(buf), SEEK_CUR) != 0) - { - return; - } - - // Read count field for number of comments. - if (fread(&buf, 4, 1, fs) < 1) - { - return; - } - num_comments = LONG(buf); - - // Read each individual comment. - for (i = 0; i < num_comments; ++i) - { - // Read length of comment. - if (fread(&buf, 4, 1, fs) < 1) - { - return; - } - - comment_len = LONG(buf); - - // Read actual comment data into string buffer. - comment = calloc(1, comment_len + 1); - if (comment == NULL - || fread(comment, 1, comment_len, fs) < comment_len) - { - free(comment); - break; - } - - // Parse comment string. - ParseVorbisComment(metadata, comment); - free(comment); - } -} - -static void ParseFlacStreaminfo(file_metadata_t *metadata, FILE *fs) -{ - byte buf[34]; - - // Read block data. - if (fread(buf, sizeof(buf), 1, fs) < 1) - { - return; - } - - // We only care about sample rate and song length. - metadata->samplerate_hz = (buf[10] << 12) | (buf[11] << 4) - | (buf[12] >> 4); - // Song length is actually a 36 bit field, but 32 bits should be - // enough for everybody. - //metadata->song_length = (buf[14] << 24) | (buf[15] << 16) - // | (buf[16] << 8) | buf[17]; -} - -static void ParseFlacFile(file_metadata_t *metadata, FILE *fs) -{ - byte header[4]; - unsigned int block_type; - size_t block_len; - boolean last_block; - - for (;;) - { - long pos = -1; - - // Read METADATA_BLOCK_HEADER: - if (fread(header, 4, 1, fs) < 1) - { - return; - } - - block_type = header[0] & ~0x80; - last_block = (header[0] & 0x80) != 0; - block_len = (header[1] << 16) | (header[2] << 8) | header[3]; - - pos = ftell(fs); - if (pos < 0) - { - return; - } - - if (block_type == FLAC_STREAMINFO) - { - ParseFlacStreaminfo(metadata, fs); - } - else if (block_type == FLAC_VORBIS_COMMENT) - { - ParseVorbisComments(metadata, fs); - } - - if (last_block) - { - break; - } - - // Seek to start of next block. - if (fseek(fs, pos + block_len, SEEK_SET) != 0) - { - return; - } - } -} - -static void ParseOggIdHeader(file_metadata_t *metadata, FILE *fs) -{ - byte buf[21]; - - if (fread(buf, sizeof(buf), 1, fs) < 1) - { - return; - } - - metadata->samplerate_hz = (buf[8] << 24) | (buf[7] << 16) - | (buf[6] << 8) | buf[5]; -} - -static void ParseOggFile(file_metadata_t *metadata, FILE *fs) -{ - byte buf[7]; - unsigned int offset; - - // Scan through the start of the file looking for headers. They - // begin '[byte]vorbis' where the byte value indicates header type. - memset(buf, 0, sizeof(buf)); - - for (offset = 0; offset < 100 * 1024; ++offset) - { - // buf[] is used as a sliding window. Each iteration, we - // move the buffer one byte to the left and read an extra - // byte onto the end. - memmove(buf, buf + 1, sizeof(buf) - 1); - - if (fread(&buf[6], 1, 1, fs) < 1) - { - return; - } - - if (!memcmp(buf + 1, "vorbis", 6)) - { - switch (buf[0]) - { - case OGG_ID_HEADER: - ParseOggIdHeader(metadata, fs); - break; - case OGG_COMMENT_HEADER: - ParseVorbisComments(metadata, fs); - break; - default: - break; - } - } - } -} - -static void ReadLoopPoints(const char *filename, file_metadata_t *metadata) -{ - FILE *fs; - char header[4]; - - metadata->valid = false; - metadata->samplerate_hz = 0; - metadata->start_time = 0; - metadata->end_time = -1; - - fs = M_fopen(filename, "rb"); - - if (fs == NULL) - { - return; - } - - // Check for a recognized file format; use the first four bytes - // of the file. - - if (fread(header, 4, 1, fs) < 1) - { - fclose(fs); - return; - } - - if (memcmp(header, FLAC_HEADER, 4) == 0) - { - ParseFlacFile(metadata, fs); - } - else if (memcmp(header, OGG_HEADER, 4) == 0) - { - ParseOggFile(metadata, fs); - } - - fclose(fs); - - // Only valid if at the very least we read the sample rate. - metadata->valid = metadata->samplerate_hz > 0; - - // If start and end time are both zero, ignore the loop tags. - // This is consistent with other source ports. - if (metadata->start_time == 0 && metadata->end_time == 0) - { - metadata->valid = false; - } -} -#endif // !USE_SDL_MIXER_LOOPING - -// Given a MUS lump, look up a substitute MUS file to play instead -// (or NULL to just use normal MIDI playback). - -static const char *GetSubstituteMusicFile(void *data, size_t data_len) -{ - sha1_context_t context; - sha1_digest_t hash; - const char *filename; - char hash_str[sizeof(sha1_digest_t) * 2 + 1]; - unsigned int i; - - // Don't bother doing a hash if we're never going to find anything. - if (subst_music_len == 0) - { - return NULL; - } - - SHA1_Init(&context); - SHA1_Update(&context, data, data_len); - SHA1_Final(hash, &context); - - // Build a string representation of the hash. - for (i = 0; i < sizeof(sha1_digest_t); ++i) - { - M_snprintf(hash_str + i * 2, sizeof(hash_str) - i * 2, - "%02x", hash[i]); - } - - // Look for a hash that matches. - // The substitute mapping list can (intentionally) contain multiple - // filename mappings for the same hash. This allows us to try - // different files and fall back if our first choice isn't found. - - filename = NULL; - - for (i = 0; i < subst_music_len; ++i) - { - if (M_StringStartsWith(hash_str, subst_music[i].hash_prefix)) - { - filename = subst_music[i].filename; - - // If the file exists, then use this file in preference to - // any fallbacks. But we always return a filename if it's - // in the list, even if it's just so we can print an error - // message to the user saying it doesn't exist. - if (M_FileExists(filename)) - { - break; - } - } - } - - return filename; -} - -static char *GetFullPath(const char *musicdir, const char *path) -{ - char *result; - char *systemized_path; - - // Starting with directory separator means we have an absolute path, - // so just return it. - if (path[0] == DIR_SEPARATOR) - { - return M_StringDuplicate(path); - } - -#ifdef _WIN32 - // d:\path\... - if (isalpha(path[0]) && path[1] == ':' && path[2] == DIR_SEPARATOR) - { - return M_StringDuplicate(path); - } -#endif - - // Paths in the substitute filenames can contain Unix-style / - // path separators, but we should convert this to the separator - // for the native platform. - systemized_path = M_StringReplace(path, "/", DIR_SEPARATOR_S); - - // Copy config filename and cut off the filename to just get the - // parent dir. - result = M_StringJoin(musicdir, systemized_path, NULL); - free(systemized_path); - - return result; -} - -// If filename ends with .{ext}, check if a .ogg, .flac or .mp3 exists with -// that name, returning it if found. If none exist, NULL is returned. If the -// filename doesn't end with .{ext} then it just acts as a wrapper around -// GetFullPath(). -static char *ExpandFileExtension(const char *musicdir, const char *filename) -{ - static const char *extns[] = {".flac", ".ogg", ".mp3"}; - char *replaced, *result; - int i; - - if (!M_StringEndsWith(filename, ".{ext}")) - { - return GetFullPath(musicdir, filename); - } - - for (i = 0; i < arrlen(extns); ++i) - { - replaced = M_StringReplace(filename, ".{ext}", extns[i]); - result = GetFullPath(musicdir, replaced); - free(replaced); - if (M_FileExists(result)) - { - return result; - } - free(result); - } - - return NULL; -} - -// Add a substitute music file to the lookup list. -static void AddSubstituteMusic(const char *musicdir, const char *hash_prefix, - const char *filename) -{ - subst_music_t *s; - char *path; - - path = ExpandFileExtension(musicdir, filename); - if (path == NULL) - { - return; - } - - ++subst_music_len; - subst_music = - I_Realloc(subst_music, sizeof(subst_music_t) * subst_music_len); - s = &subst_music[subst_music_len - 1]; - s->hash_prefix = hash_prefix; - s->filename = path; -} - -static const char *ReadHashPrefix(char *line) -{ - char *result; - char *p; - int i, len; - - for (p = line; *p != '\0' && !isspace(*p) && *p != '='; ++p) - { - if (!isxdigit(*p)) - { - return NULL; - } - } - - len = p - line; - if (len == 0 || len > sizeof(sha1_digest_t) * 2) - { - return NULL; - } - - result = malloc(len + 1); - if (result == NULL) - { - return NULL; - } - - for (i = 0; i < len; ++i) - { - result[i] = tolower(line[i]); - } - result[len] = '\0'; - - return result; -} - -// Parse a line from substitute music configuration file; returns error -// message or NULL for no error. - -static const char *ParseSubstituteLine(char *musicdir, char *line) -{ - const char *hash_prefix; - char *filename; - char *p; - - // Strip out comments if present. - p = strchr(line, '#'); - if (p != NULL) - { - while (p > line && isspace(*(p - 1))) - { - --p; - } - *p = '\0'; - } - - // Skip leading spaces. - for (p = line; *p != '\0' && isspace(*p); ++p); - - // Empty line? This includes comment lines now that comments have - // been stripped. - if (*p == '\0') - { - return NULL; - } - - hash_prefix = ReadHashPrefix(p); - if (hash_prefix == NULL) - { - return "Invalid hash prefix"; - } - - p += strlen(hash_prefix); - - // Skip spaces. - for (; *p != '\0' && isspace(*p); ++p); - - if (*p != '=') - { - return "Expected '='"; - } - - ++p; - - // Skip spaces. - for (; *p != '\0' && isspace(*p); ++p); - - filename = p; - - // We're now at the filename. Cut off trailing space characters. - while (strlen(p) > 0 && isspace(p[strlen(p) - 1])) - { - p[strlen(p) - 1] = '\0'; - } - - if (strlen(p) == 0) - { - return "No filename specified for music substitution"; - } - - // Expand full path and add to our database of substitutes. - AddSubstituteMusic(musicdir, hash_prefix, filename); - - return NULL; -} - -// Read a substitute music configuration file. - -static boolean ReadSubstituteConfig(char *musicdir, const char *filename) -{ - char *buffer; - char *line; - int linenum = 1; - - // This unnecessarily opens the file twice... - if (!M_FileExists(filename)) - { - return false; - } - - M_ReadFile(filename, (byte **) &buffer); - - line = buffer; - - while (line != NULL) - { - const char *error; - char *next; - - // find end of line - char *eol = strchr(line, '\n'); - if (eol != NULL) - { - // change the newline into NUL - *eol = '\0'; - next = eol + 1; - } - else - { - // end of buffer - next = NULL; - } - - error = ParseSubstituteLine(musicdir, line); - - if (error != NULL) - { - fprintf(stderr, "%s:%i: Error: %s\n", filename, linenum, error); - } - - ++linenum; - line = next; - } - - Z_Free(buffer); - - return true; -} - -// Find substitute configs and try to load them. - -static void LoadSubstituteConfigs(void) -{ - glob_t *glob; - char *musicdir; - const char *path; - unsigned int old_music_len; - unsigned int i; - - // We can configure the path to music packs using the music_pack_path - // configuration variable. Otherwise we use the current directory, or - // $configdir/music to look for .cfg files. - if (strcmp(music_pack_path, "") != 0) - { - musicdir = M_StringJoin(music_pack_path, DIR_SEPARATOR_S, NULL); - } - else if (!strcmp(configdir, exedir)) - { - musicdir = M_StringDuplicate(""); - } - else - { - musicdir = M_StringJoin(configdir, "music", DIR_SEPARATOR_S, NULL); - } - - // Load all music packs, by searching for .cfg files. - glob = I_StartGlob(musicdir, "*.cfg", GLOB_FLAG_SORTED|GLOB_FLAG_NOCASE); - for (;;) - { - path = I_NextGlob(glob); - if (path == NULL) - { - break; - } - ReadSubstituteConfig(musicdir, path); - } - I_EndGlob(glob); - - if (subst_music_len > 0) - { - printf("Loaded %u music substitutions from config files.\n", - subst_music_len); - } - - old_music_len = subst_music_len; - - // Add entries from known filenames list. We add this after those from the - // configuration files, so that the entries here can be overridden. - for (i = 0; i < arrlen(known_filenames); ++i) - { - AddSubstituteMusic(musicdir, known_filenames[i].hash_prefix, - known_filenames[i].filename); - } - - if (subst_music_len > old_music_len) - { - printf("Configured %u music substitutions based on filename.\n", - subst_music_len - old_music_len); - } - - free(musicdir); -} - -// Returns true if the given lump number is a music lump that should -// be included in substitute configs. -// Identifying music lumps by name is not feasible; some games (eg. -// Heretic, Hexen) don't have a common naming pattern for music lumps. - -static boolean IsMusicLump(int lumpnum) -{ - byte *data; - boolean result; - - if (W_LumpLength(lumpnum) < 4) - { - return false; - } - - data = W_CacheLumpNum(lumpnum, PU_STATIC); - - result = memcmp(data, MUS_HEADER_MAGIC, 4) == 0 - || memcmp(data, MID_HEADER_MAGIC, 4) == 0; - - W_ReleaseLumpNum(lumpnum); - - return result; -} - -// Dump an example config file containing checksums for all MIDI music -// found in the WAD directory. - -static void DumpSubstituteConfig(const char *filename) -{ - sha1_context_t context; - sha1_digest_t digest; - char name[9]; - byte *data; - FILE *fs; - unsigned int lumpnum; - size_t h; - - fs = M_fopen(filename, "w"); - - if (fs == NULL) - { - I_Error("Failed to open %s for writing", filename); - return; - } - - fprintf(fs, "# Example %s substitute MIDI file.\n\n", PACKAGE_NAME); - fprintf(fs, "# SHA1 hash = filename\n"); - - for (lumpnum = 0; lumpnum < numlumps; ++lumpnum) - { - strncpy(name, lumpinfo[lumpnum]->name, 8); - name[8] = '\0'; - - if (!IsMusicLump(lumpnum)) - { - continue; - } - - // Calculate hash. - data = W_CacheLumpNum(lumpnum, PU_STATIC); - SHA1_Init(&context); - SHA1_Update(&context, data, W_LumpLength(lumpnum)); - SHA1_Final(digest, &context); - W_ReleaseLumpNum(lumpnum); - - // Print line. - for (h = 0; h < sizeof(sha1_digest_t); ++h) - { - fprintf(fs, "%02x", digest[h]); - } - - fprintf(fs, " = %s.ogg\n", name); - } - - fprintf(fs, "\n"); - fclose(fs); - - printf("Substitute MIDI config file written to %s.\n", filename); - I_Quit(); -} - -// Shutdown music - -static void I_MP_ShutdownMusic(void) -{ - if (music_initialized) - { - Mix_HaltMusic(); - music_initialized = false; - - if (sdl_was_initialized) - { - Mix_CloseAudio(); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - sdl_was_initialized = false; - } - } -} - -static boolean SDLIsInitialized(void) -{ - int freq, channels; - Uint16 format; - - return Mix_QuerySpec(&freq, &format, &channels) != 0; -} - -#if !USE_SDL_MIXER_LOOPING -// Callback function that is invoked to track current track position. -void TrackPositionCallback(int chan, void *stream, int len, void *udata) -{ - // Position is doubled up twice: for 16-bit samples and for stereo. - current_track_pos += len / 4; -} -#endif // !USE_SDL_MIXER_LOOPING - -// Initialize music subsystem -static boolean I_MP_InitMusic(void) -{ - int i; - - //! - // @category obscure - // @arg - // - // Read all MIDI files from loaded WAD files, dump an example - // substitution music config file to the specified file, and quit. - // - i = M_CheckParmWithArgs("-dumpsubstconfig", 1); - - if (i > 0) - { - DumpSubstituteConfig(myargv[i + 1]); - } - - // If we're in GENMIDI mode, try to load sound packs. - LoadSubstituteConfigs(); - - // We can't initialize if we don't have any substitute files to work with. - // If so, don't bother with SDL initialization etc. - if (subst_music_len == 0) - { - return false; - } - - // If SDL_mixer is not initialized, we have to initialize it - // and have the responsibility to shut it down later on. - if (SDLIsInitialized()) - { - music_initialized = true; - } - else if (SDL_Init(SDL_INIT_AUDIO) < 0) - { - fprintf(stderr, "Unable to set up sound.\n"); - } - else if (Mix_OpenAudioDevice(snd_samplerate, AUDIO_S16SYS, 2, 1024, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) - { - fprintf(stderr, "Error initializing SDL_mixer: %s\n", - Mix_GetError()); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } - else - { - SDL_PauseAudio(0); - - sdl_was_initialized = true; - music_initialized = true; - } - - // Initialize SDL_Mixer for digital music playback - Mix_Init(MIX_INIT_FLAC | MIX_INIT_OGG | MIX_INIT_MP3); - -#if !USE_SDL_MIXER_LOOPING - // Register an effect function to track the music position. - Mix_RegisterEffect(MIX_CHANNEL_POST, TrackPositionCallback, NULL, NULL); -#endif // !USE_SDL_MIXER_LOOPING - - return music_initialized; -} - -// Set music volume (0 - 127) - -static void I_MP_SetMusicVolume(int volume) -{ - Mix_VolumeMusic((volume * MIX_MAX_VOLUME) / 127); -} - -// Start playing a mid - -static void I_MP_PlaySong(void *handle, boolean looping) -{ - int loops; - - if (!music_initialized) - { - return; - } - - if (handle == NULL) - { - return; - } - - current_track_music = (Mix_Music *) handle; - current_track_loop = looping; - - if (looping) - { - loops = -1; - } - else - { - loops = 1; - } - -#if !USE_SDL_MIXER_LOOPING - // Don't loop when playing substitute music, as we do it - // ourselves instead. - if (file_metadata.valid) - { - loops = 1; - SDL_LockAudio(); - current_track_pos = 0; // start of track - SDL_UnlockAudio(); - } -#endif // !USE_SDL_MIXER_LOOPING - - if (Mix_PlayMusic(current_track_music, loops) == -1) - { - fprintf(stderr, "I_MP_PlaySong: Error starting track: %s\n", - Mix_GetError()); - } -} - -static void I_MP_PauseSong(void) -{ - if (!music_initialized) - { - return; - } - - Mix_PauseMusic(); -} - -static void I_MP_ResumeSong(void) -{ - if (!music_initialized) - { - return; - } - - Mix_ResumeMusic(); -} - -static void I_MP_StopSong(void) -{ - if (!music_initialized) - { - return; - } - - Mix_HaltMusic(); - current_track_music = NULL; -} - -static void I_MP_UnRegisterSong(void *handle) -{ - Mix_Music *music = (Mix_Music *) handle; - - if (!music_initialized) - { - return; - } - - if (handle == NULL) - { - return; - } - - Mix_FreeMusic(music); -} - -static void *I_MP_RegisterSong(void *data, int len) -{ - const char *filename; - Mix_Music *music; - - if (!music_initialized) - { - return NULL; - } - - // See if we're substituting this MUS for a high-quality replacement. - filename = GetSubstituteMusicFile(data, len); - if (filename == NULL) - { - return NULL; - } - - music = Mix_LoadMUS(filename); - if (music == NULL) - { - // Fall through and play MIDI normally, but print an error - // message. - fprintf(stderr, "Failed to load substitute music file: %s: %s\n", - filename, Mix_GetError()); - return NULL; - } - -#if !USE_SDL_MIXER_LOOPING - // Read loop point metadata from the file so that we know where - // to loop the music. - ReadLoopPoints(filename, &file_metadata); -#endif // !USE_SDL_MIXER_LOOPING - return music; -} - -// Is the song playing? -static boolean I_MP_MusicIsPlaying(void) -{ - if (!music_initialized) - { - return false; - } - - return Mix_PlayingMusic(); -} - -#if !USE_SDL_MIXER_LOOPING -// Get position in substitute music track, in seconds since start of track. -static double GetMusicPosition(void) -{ - unsigned int music_pos; - int freq; - - Mix_QuerySpec(&freq, NULL, NULL); - - SDL_LockAudio(); - music_pos = current_track_pos; - SDL_UnlockAudio(); - - return (double) music_pos / freq; -} - -static void RestartCurrentTrack(void) -{ - double start = (double) file_metadata.start_time - / file_metadata.samplerate_hz; - - // If the track finished we need to restart it. - if (current_track_music != NULL) - { - Mix_PlayMusic(current_track_music, 1); - } - - Mix_SetMusicPosition(start); - SDL_LockAudio(); - current_track_pos = file_metadata.start_time; - SDL_UnlockAudio(); -} -#endif // !USE_SDL_MIXER_LOOPING - -// Poll music position; if we have passed the loop point end position -// then we need to go back. -static void I_MP_PollMusic(void) -{ -#if !USE_SDL_MIXER_LOOPING - // When playing substitute tracks, loop tags only apply if we're playing - // a looping track. Tracks like the title screen music have the loop - // tags ignored. - if (current_track_loop && file_metadata.valid) - { - double end = (double) file_metadata.end_time - / file_metadata.samplerate_hz; - - // If we have reached the loop end point then we have to take action. - if (file_metadata.end_time >= 0 && GetMusicPosition() >= end) - { - RestartCurrentTrack(); - } - - // Have we reached the actual end of track (not loop end)? - if (!Mix_PlayingMusic()) - { - RestartCurrentTrack(); - } - } -#endif // !USE_SDL_MIXER_LOOPING -} - const music_module_t music_pack_module = { - NULL, - 0, - I_MP_InitMusic, - I_MP_ShutdownMusic, - I_MP_SetMusicVolume, - I_MP_PauseSong, - I_MP_ResumeSong, - I_MP_RegisterSong, - I_MP_UnRegisterSong, - I_MP_PlaySong, - I_MP_StopSong, - I_MP_MusicIsPlaying, - I_MP_PollMusic, + NULL, + 0, + i_null_init_music, + i_null_shutdown_music, + i_null_set_music_volume, + i_null_pause_song, + i_null_resume_song, + i_null_register_song, + i_null_unregister_song, + i_null_play_song, + i_null_stop_song, + i_null_musicisplaying, + i_null_pollmusic, }; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -#else // DISABLE_SDL2MIXER - - -static boolean I_NULL_InitMusic(void) +static boolean i_null_init_music(void) { - return false; + return false; } - -static void I_NULL_ShutdownMusic(void) +static void i_null_shutdown_music(void) { + return; } - -static void I_NULL_SetMusicVolume(int volume) +static void i_null_set_music_volume(int volume) { + return; } - -static void I_NULL_PauseSong(void) +static void i_null_pause_song(void) { + return; } - -static void I_NULL_ResumeSong(void) +static void i_null_resume_song(void) { + return; } - -static void *I_NULL_RegisterSong(void *data, int len) +static void *i_null_register_song(void *data, int len) { - return NULL; + return NULL; } - -static void I_NULL_UnRegisterSong(void *handle) +static void i_null_unregister_song(void *handle) { + return; } - -static void I_NULL_PlaySong(void *handle, boolean looping) +static void i_null_play_song(void *handle, boolean looping) { + return; } - -static void I_NULL_StopSong(void) +static void i_null_stop_song(void) { + return; } - -static boolean I_NULL_MusicIsPlaying(void) +static boolean i_null_musicisplaying(void) { - return false; + return false; } - -static void I_NULL_PollMusic(void) +static void i_null_pollmusic(void) { + return; } -const music_module_t music_pack_module = -{ - NULL, - 0, - I_NULL_InitMusic, - I_NULL_ShutdownMusic, - I_NULL_SetMusicVolume, - I_NULL_PauseSong, - I_NULL_ResumeSong, - I_NULL_RegisterSong, - I_NULL_UnRegisterSong, - I_NULL_PlaySong, - I_NULL_StopSong, - I_NULL_MusicIsPlaying, - I_NULL_PollMusic, -}; - - -#endif // DISABLE_SDL2MIXER +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/games/NXDoom/src/i_oplmusic.c b/games/NXDoom/src/i_oplmusic.c deleted file mode 100644 index 54e7dac3c35..00000000000 --- a/games/NXDoom/src/i_oplmusic.c +++ /dev/null @@ -1,1898 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System interface for music. -// - - -#include -#include -#include - -#include "memio.h" -#include "mus2mid.h" - -#include "deh_main.h" -#include "i_sound.h" -#include "i_swap.h" -#include "m_misc.h" -#include "w_wad.h" -#include "z_zone.h" - -#include "opl.h" -#include "midifile.h" - -// #define OPL_MIDI_DEBUG - -#define MAXMIDLENGTH (96 * 1024) -#define GENMIDI_NUM_INSTRS 128 -#define GENMIDI_NUM_PERCUSSION 47 - -#define GENMIDI_HEADER "#OPL_II#" -#define GENMIDI_FLAG_FIXED 0x0001 /* fixed pitch */ -#define GENMIDI_FLAG_2VOICE 0x0004 /* double voice (OPL3) */ - -#define PERCUSSION_LOG_LEN 16 - -typedef PACKED_STRUCT ( -{ - byte tremolo; - byte attack; - byte sustain; - byte waveform; - byte scale; - byte level; -}) genmidi_op_t; - -typedef PACKED_STRUCT ( -{ - genmidi_op_t modulator; - byte feedback; - genmidi_op_t carrier; - byte unused; - short base_note_offset; -}) genmidi_voice_t; - -typedef PACKED_STRUCT ( -{ - unsigned short flags; - byte fine_tuning; - byte fixed_note; - - genmidi_voice_t voices[2]; -}) genmidi_instr_t; - -// Data associated with a channel of a track that is currently playing. - -typedef struct -{ - // The instrument currently used for this track. - - genmidi_instr_t *instrument; - - // Volume level - - int volume; - int volume_base; - - // Pan - - int pan; - - // Pitch bend value: - - int bend; - -} opl_channel_data_t; - -// Data associated with a track that is currently playing. - -typedef struct -{ - // Track iterator used to read new events. - - midi_track_iter_t *iter; -} opl_track_data_t; - -typedef struct opl_voice_s opl_voice_t; - -struct opl_voice_s -{ - // Index of this voice: - int index; - - // The operators used by this voice: - int op1, op2; - - // Array used by voice: - int array; - - // Currently-loaded instrument data - genmidi_instr_t *current_instr; - - // The voice number in the instrument to use. - // This is normally set to zero; if this is a double voice - // instrument, it may be one. - unsigned int current_instr_voice; - - // The channel currently using this voice. - opl_channel_data_t *channel; - - // The midi key that this voice is playing. - unsigned int key; - - // The note being played. This is normally the same as - // the key, but if the instrument is a fixed pitch - // instrument, it is different. - unsigned int note; - - // The frequency value being used. - unsigned int freq; - - // The volume of the note being played on this channel. - unsigned int note_volume; - - // The current volume (register value) that has been set for this channel. - unsigned int car_volume; - unsigned int mod_volume; - - // Pan. - unsigned int reg_pan; - - // Priority. - unsigned int priority; -}; - -// Operators used by the different voices. - -static const int voice_operators[2][OPL_NUM_VOICES] = { - { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12 }, - { 0x03, 0x04, 0x05, 0x0b, 0x0c, 0x0d, 0x13, 0x14, 0x15 } -}; - -// Frequency values to use for each note. - -static const unsigned short frequency_curve[] = { - - 0x133, 0x133, 0x134, 0x134, 0x135, 0x136, 0x136, 0x137, // -1 - 0x137, 0x138, 0x138, 0x139, 0x139, 0x13a, 0x13b, 0x13b, - 0x13c, 0x13c, 0x13d, 0x13d, 0x13e, 0x13f, 0x13f, 0x140, - 0x140, 0x141, 0x142, 0x142, 0x143, 0x143, 0x144, 0x144, - - 0x145, 0x146, 0x146, 0x147, 0x147, 0x148, 0x149, 0x149, // -2 - 0x14a, 0x14a, 0x14b, 0x14c, 0x14c, 0x14d, 0x14d, 0x14e, - 0x14f, 0x14f, 0x150, 0x150, 0x151, 0x152, 0x152, 0x153, - 0x153, 0x154, 0x155, 0x155, 0x156, 0x157, 0x157, 0x158, - - // These are used for the first seven MIDI note values: - - 0x158, 0x159, 0x15a, 0x15a, 0x15b, 0x15b, 0x15c, 0x15d, // 0 - 0x15d, 0x15e, 0x15f, 0x15f, 0x160, 0x161, 0x161, 0x162, - 0x162, 0x163, 0x164, 0x164, 0x165, 0x166, 0x166, 0x167, - 0x168, 0x168, 0x169, 0x16a, 0x16a, 0x16b, 0x16c, 0x16c, - - 0x16d, 0x16e, 0x16e, 0x16f, 0x170, 0x170, 0x171, 0x172, // 1 - 0x172, 0x173, 0x174, 0x174, 0x175, 0x176, 0x176, 0x177, - 0x178, 0x178, 0x179, 0x17a, 0x17a, 0x17b, 0x17c, 0x17c, - 0x17d, 0x17e, 0x17e, 0x17f, 0x180, 0x181, 0x181, 0x182, - - 0x183, 0x183, 0x184, 0x185, 0x185, 0x186, 0x187, 0x188, // 2 - 0x188, 0x189, 0x18a, 0x18a, 0x18b, 0x18c, 0x18d, 0x18d, - 0x18e, 0x18f, 0x18f, 0x190, 0x191, 0x192, 0x192, 0x193, - 0x194, 0x194, 0x195, 0x196, 0x197, 0x197, 0x198, 0x199, - - 0x19a, 0x19a, 0x19b, 0x19c, 0x19d, 0x19d, 0x19e, 0x19f, // 3 - 0x1a0, 0x1a0, 0x1a1, 0x1a2, 0x1a3, 0x1a3, 0x1a4, 0x1a5, - 0x1a6, 0x1a6, 0x1a7, 0x1a8, 0x1a9, 0x1a9, 0x1aa, 0x1ab, - 0x1ac, 0x1ad, 0x1ad, 0x1ae, 0x1af, 0x1b0, 0x1b0, 0x1b1, - - 0x1b2, 0x1b3, 0x1b4, 0x1b4, 0x1b5, 0x1b6, 0x1b7, 0x1b8, // 4 - 0x1b8, 0x1b9, 0x1ba, 0x1bb, 0x1bc, 0x1bc, 0x1bd, 0x1be, - 0x1bf, 0x1c0, 0x1c0, 0x1c1, 0x1c2, 0x1c3, 0x1c4, 0x1c4, - 0x1c5, 0x1c6, 0x1c7, 0x1c8, 0x1c9, 0x1c9, 0x1ca, 0x1cb, - - 0x1cc, 0x1cd, 0x1ce, 0x1ce, 0x1cf, 0x1d0, 0x1d1, 0x1d2, // 5 - 0x1d3, 0x1d3, 0x1d4, 0x1d5, 0x1d6, 0x1d7, 0x1d8, 0x1d8, - 0x1d9, 0x1da, 0x1db, 0x1dc, 0x1dd, 0x1de, 0x1de, 0x1df, - 0x1e0, 0x1e1, 0x1e2, 0x1e3, 0x1e4, 0x1e5, 0x1e5, 0x1e6, - - 0x1e7, 0x1e8, 0x1e9, 0x1ea, 0x1eb, 0x1ec, 0x1ed, 0x1ed, // 6 - 0x1ee, 0x1ef, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5, - 0x1f6, 0x1f6, 0x1f7, 0x1f8, 0x1f9, 0x1fa, 0x1fb, 0x1fc, - 0x1fd, 0x1fe, 0x1ff, 0x200, 0x201, 0x201, 0x202, 0x203, - - // First note of looped range used for all octaves: - - 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, // 7 - 0x20c, 0x20d, 0x20e, 0x20f, 0x210, 0x210, 0x211, 0x212, - 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a, - 0x21b, 0x21c, 0x21d, 0x21e, 0x21f, 0x220, 0x221, 0x222, - - 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22a, // 8 - 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, 0x230, 0x231, 0x232, - 0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, - 0x23b, 0x23c, 0x23d, 0x23e, 0x23f, 0x240, 0x241, 0x242, - - 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b, // 9 - 0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253, - 0x254, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x25b, 0x25c, - 0x25d, 0x25e, 0x25f, 0x260, 0x262, 0x263, 0x264, 0x265, - - 0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, // 10 - 0x26f, 0x270, 0x271, 0x272, 0x273, 0x275, 0x276, 0x277, - 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280, - 0x281, 0x282, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, - - 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x292, 0x293, // 11 - 0x294, 0x295, 0x296, 0x298, 0x299, 0x29a, 0x29b, 0x29c, - 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6, - 0x2a7, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ae, 0x2af, 0x2b0, - - 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba, // 12 - 0x2bb, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c2, 0x2c3, 0x2c4, - 0x2c5, 0x2c7, 0x2c8, 0x2c9, 0x2cb, 0x2cc, 0x2cd, 0x2ce, - 0x2d0, 0x2d1, 0x2d2, 0x2d4, 0x2d5, 0x2d6, 0x2d8, 0x2d9, - - 0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, // 13 - 0x2e5, 0x2e6, 0x2e8, 0x2e9, 0x2ea, 0x2ec, 0x2ed, 0x2ee, - 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9, - 0x2fb, 0x2fc, 0x2fd, 0x2ff, 0x300, 0x302, 0x303, 0x304, - - 0x306, 0x307, 0x309, 0x30a, 0x30b, 0x30d, 0x30e, 0x310, // 14 - 0x311, 0x312, 0x314, 0x315, 0x317, 0x318, 0x31a, 0x31b, - 0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327, - 0x328, 0x329, 0x32b, 0x32c, 0x32e, 0x32f, 0x331, 0x332, - - 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e, // 15 - 0x340, 0x341, 0x343, 0x344, 0x346, 0x347, 0x349, 0x34a, - 0x34c, 0x34d, 0x34f, 0x350, 0x352, 0x353, 0x355, 0x357, - 0x358, 0x35a, 0x35b, 0x35d, 0x35e, 0x360, 0x361, 0x363, - - 0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, // 16 - 0x371, 0x373, 0x374, 0x376, 0x378, 0x379, 0x37b, 0x37c, - 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389, - 0x38b, 0x38d, 0x38e, 0x390, 0x392, 0x393, 0x395, 0x397, - - 0x398, 0x39a, 0x39c, 0x39d, 0x39f, 0x3a1, 0x3a2, 0x3a4, // 17 - 0x3a6, 0x3a7, 0x3a9, 0x3ab, 0x3ac, 0x3ae, 0x3b0, 0x3b1, - 0x3b3, 0x3b5, 0x3b7, 0x3b8, 0x3ba, 0x3bc, 0x3bd, 0x3bf, - 0x3c1, 0x3c3, 0x3c4, 0x3c6, 0x3c8, 0x3ca, 0x3cb, 0x3cd, - - // The last note has an incomplete range, and loops round back to - // the start. Note that the last value is actually a buffer overrun - // and does not fit with the other values. - - 0x3cf, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3da, 0x3db, // 18 - 0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e4, 0x3e6, 0x3e8, 0x3ea, - 0x3ec, 0x3ed, 0x3ef, 0x3f1, 0x3f3, 0x3f5, 0x3f6, 0x3f8, - 0x3fa, 0x3fc, 0x3fe, 0x36c, -}; - -// Mapping from MIDI volume level to OPL level value. - -static const unsigned int volume_mapping_table[] = { - 0, 1, 3, 5, 6, 8, 10, 11, - 13, 14, 16, 17, 19, 20, 22, 23, - 25, 26, 27, 29, 30, 32, 33, 34, - 36, 37, 39, 41, 43, 45, 47, 49, - 50, 52, 54, 55, 57, 59, 60, 61, - 63, 64, 66, 67, 68, 69, 71, 72, - 73, 74, 75, 76, 77, 79, 80, 81, - 82, 83, 84, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 92, 93, 94, 95, - 96, 96, 97, 98, 99, 99, 100, 101, - 101, 102, 103, 103, 104, 105, 105, 106, - 107, 107, 108, 109, 109, 110, 110, 111, - 112, 112, 113, 113, 114, 114, 115, 115, - 116, 117, 117, 118, 118, 119, 119, 120, - 120, 121, 121, 122, 122, 123, 123, 123, - 124, 124, 125, 125, 126, 126, 127, 127 -}; - -static opl_driver_ver_t opl_drv_ver = opl_doom_1_9; -static boolean music_initialized = false; - -//static boolean musicpaused = false; -static int start_music_volume; -static int current_music_volume; - -// GENMIDI lump instrument data: - -static genmidi_instr_t *main_instrs; -static genmidi_instr_t *percussion_instrs; -static char (*main_instr_names)[32]; -static char (*percussion_names)[32]; - -// Voices: - -static opl_voice_t voices[OPL_NUM_VOICES * 2]; -static opl_voice_t *voice_free_list[OPL_NUM_VOICES * 2]; -static opl_voice_t *voice_alloced_list[OPL_NUM_VOICES * 2]; -static int voice_free_num; -static int voice_alloced_num; -static int opl_opl3mode; -static int num_opl_voices; - -// Data for each channel. - -static opl_channel_data_t channels[MIDI_CHANNELS_PER_TRACK]; - -// Track data for playing tracks: - -static opl_track_data_t *tracks; -static unsigned int num_tracks = 0; -static unsigned int running_tracks = 0; -static boolean song_looping; - -// Tempo control variables - -static unsigned int ticks_per_beat; -static unsigned int us_per_beat; - -// Mini-log of recently played percussion instruments: - -static uint8_t last_perc[PERCUSSION_LOG_LEN]; -static unsigned int last_perc_count; - -// Configuration file variable, containing the port number for the -// adlib chip. - -char *snd_dmxoption = ""; -int opl_io_port = 0x388; - -// If true, OPL sound channels are reversed to their correct arrangement -// (as intended by the MIDI standard) rather than the backwards one -// used by DMX due to a bug. - -static boolean opl_stereo_correct = false; - -// Load instrument table from GENMIDI lump: - -static boolean LoadInstrumentTable(void) -{ - byte *lump; - - lump = W_CacheLumpName(DEH_String("genmidi"), PU_STATIC); - - // DMX does not check header - - main_instrs = (genmidi_instr_t *) (lump + strlen(GENMIDI_HEADER)); - percussion_instrs = main_instrs + GENMIDI_NUM_INSTRS; - main_instr_names = - (char (*)[32]) (percussion_instrs + GENMIDI_NUM_PERCUSSION); - percussion_names = main_instr_names + GENMIDI_NUM_INSTRS; - - return true; -} - -// Get the next available voice from the freelist. - -static opl_voice_t *GetFreeVoice(void) -{ - opl_voice_t *result; - int i; - - // None available? - - if (voice_free_num == 0) - { - return NULL; - } - - // Remove from free list - - result = voice_free_list[0]; - - voice_free_num--; - - for (i = 0; i < voice_free_num; i++) - { - voice_free_list[i] = voice_free_list[i + 1]; - } - - // Add to allocated list - - voice_alloced_list[voice_alloced_num++] = result; - - return result; -} - -// Release a voice back to the freelist. - -static void VoiceKeyOff(opl_voice_t *voice); - -static void ReleaseVoice(int index) -{ - opl_voice_t *voice; - boolean double_voice; - int i; - - // Doom 2 1.666 OPL crash emulation. - if (index >= voice_alloced_num) - { - - voice_alloced_num = 0; - voice_free_num = 0; - return; - } - - voice = voice_alloced_list[index]; - - VoiceKeyOff(voice); - - voice->channel = NULL; - voice->note = 0; - - double_voice = voice->current_instr_voice != 0; - - // Remove from alloced list. - - voice_alloced_num--; - - for (i = index; i < voice_alloced_num; i++) - { - voice_alloced_list[i] = voice_alloced_list[i + 1]; - } - - // Search to the end of the freelist (This is how Doom behaves!) - - voice_free_list[voice_free_num++] = voice; - - if (double_voice && opl_drv_ver < opl_doom_1_9) - { - ReleaseVoice(index); - } -} - -// Load data to the specified operator - -static void LoadOperatorData(int operator, genmidi_op_t *data, - boolean max_level, unsigned int *volume) -{ - int level; - - // The scale and level fields must be combined for the level register. - // For the carrier wave we always set the maximum level. - - level = data->scale; - - if (max_level) - { - level |= 0x3f; - } - else - { - level |= data->level; - } - - *volume = level; - - OPL_WriteRegister(OPL_REGS_LEVEL + operator, level); - OPL_WriteRegister(OPL_REGS_TREMOLO + operator, data->tremolo); - OPL_WriteRegister(OPL_REGS_ATTACK + operator, data->attack); - OPL_WriteRegister(OPL_REGS_SUSTAIN + operator, data->sustain); - OPL_WriteRegister(OPL_REGS_WAVEFORM + operator, data->waveform); -} - -// Set the instrument for a particular voice. - -static void SetVoiceInstrument(opl_voice_t *voice, - genmidi_instr_t *instr, - unsigned int instr_voice) -{ - genmidi_voice_t *data; - unsigned int modulating; - - // Instrument already set for this channel? - - if (voice->current_instr == instr - && voice->current_instr_voice == instr_voice) - { - return; - } - - voice->current_instr = instr; - voice->current_instr_voice = instr_voice; - - data = &instr->voices[instr_voice]; - - // Are we usind modulated feedback mode? - - modulating = (data->feedback & 0x01) == 0; - - // Doom loads the second operator first, then the first. - // The carrier is set to minimum volume until the voice volume - // is set in SetVoiceVolume (below). If we are not using - // modulating mode, we must set both to minimum volume. - - LoadOperatorData(voice->op2 | voice->array, &data->carrier, true, - &voice->car_volume); - LoadOperatorData(voice->op1 | voice->array, &data->modulator, !modulating, - &voice->mod_volume); - - // Set feedback register that control the connection between the - // two operators. Turn on bits in the upper nybble; I think this - // is for OPL3, where it turns on channel A/B. - - OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array, - data->feedback | voice->reg_pan); - - // Calculate voice priority. - - voice->priority = 0x0f - (data->carrier.attack >> 4) - + 0x0f - (data->carrier.sustain & 0x0f); -} - -static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume) -{ - genmidi_voice_t *opl_voice; - unsigned int midi_volume; - unsigned int full_volume; - unsigned int car_volume; - unsigned int mod_volume; - - voice->note_volume = volume; - - opl_voice = &voice->current_instr->voices[voice->current_instr_voice]; - - // Multiply note volume and channel volume to get the actual volume. - - midi_volume = 2 * (volume_mapping_table[voice->channel->volume] + 1); - - full_volume = (volume_mapping_table[voice->note_volume] * midi_volume) - >> 9; - - // The volume value to use in the register: - car_volume = 0x3f - full_volume; - - // Update the volume register(s) if necessary. - - if (car_volume != (voice->car_volume & 0x3f)) - { - voice->car_volume = car_volume | (voice->car_volume & 0xc0); - - OPL_WriteRegister((OPL_REGS_LEVEL + voice->op2) | voice->array, - voice->car_volume); - - // If we are using non-modulated feedback mode, we must set the - // volume for both voices. - - if ((opl_voice->feedback & 0x01) != 0 - && opl_voice->modulator.level != 0x3f) - { - mod_volume = opl_voice->modulator.level; - if (mod_volume < car_volume) - { - mod_volume = car_volume; - } - - mod_volume |= voice->mod_volume & 0xc0; - - if(mod_volume != voice->mod_volume) - { - voice->mod_volume = mod_volume; - OPL_WriteRegister((OPL_REGS_LEVEL + voice->op1) | voice->array, - mod_volume | - (opl_voice->modulator.scale & 0xc0)); - } - } - } -} - -static void SetVoicePan(opl_voice_t *voice, unsigned int pan) -{ - genmidi_voice_t *opl_voice; - - voice->reg_pan = pan; - opl_voice = &voice->current_instr->voices[voice->current_instr_voice];; - - OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array, - opl_voice->feedback | pan); -} - -// Initialize the voice table and freelist - -static void InitVoices(void) -{ - int i; - - // Start with an empty free list. - - voice_free_num = num_opl_voices; - voice_alloced_num = 0; - - // Initialize each voice. - - for (i = 0; i < num_opl_voices; ++i) - { - voices[i].index = i % OPL_NUM_VOICES; - voices[i].op1 = voice_operators[0][i % OPL_NUM_VOICES]; - voices[i].op2 = voice_operators[1][i % OPL_NUM_VOICES]; - voices[i].array = (i / OPL_NUM_VOICES) << 8; - voices[i].current_instr = NULL; - - // Add this voice to the freelist. - - voice_free_list[i] = &voices[i]; - } -} - -static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume, - boolean clip_start); - -// Set music volume (0 - 127) - -static void I_OPL_SetMusicVolume(int volume) -{ - unsigned int i; - - if (current_music_volume == volume) - { - return; - } - - // Internal state variable. - - current_music_volume = volume; - - // Update the volume of all voices. - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - if (i == 15) - { - SetChannelVolume(&channels[i], volume, false); - } - else - { - SetChannelVolume(&channels[i], channels[i].volume_base, false); - } - } -} - -static void VoiceKeyOff(opl_voice_t *voice) -{ - OPL_WriteRegister((OPL_REGS_FREQ_2 + voice->index) | voice->array, - voice->freq >> 8); -} - -static opl_channel_data_t *TrackChannelForEvent(opl_track_data_t *track, - midi_event_t *event) -{ - unsigned int channel_num = event->data.channel.channel; - - // MIDI uses track #9 for percussion, but for MUS it's track #15 - // instead. Because DMX works on MUS data internally, we need to - // swap back to the MUS version of the channel number. - if (channel_num == 9) - { - channel_num = 15; - } - else if (channel_num == 15) - { - channel_num = 9; - } - - return &channels[channel_num]; -} - -// Get the frequency that we should be using for a voice. - -static void KeyOffEvent(opl_track_data_t *track, midi_event_t *event) -{ - opl_channel_data_t *channel; - int i; - unsigned int key; - -/* - printf("note off: channel %i, %i, %i\n", - event->data.channel.channel, - event->data.channel.param1, - event->data.channel.param2); -*/ - - channel = TrackChannelForEvent(track, event); - key = event->data.channel.param1; - - // Turn off voices being used to play this key. - // If it is a double voice instrument there will be two. - - for (i = 0; i < voice_alloced_num; i++) - { - if (voice_alloced_list[i]->channel == channel - && voice_alloced_list[i]->key == key) - { - // Finished with this voice now. - - ReleaseVoice(i); - - i--; - } - } -} - -// When all voices are in use, we must discard an existing voice to -// play a new note. Find and free an existing voice. The channel -// passed to the function is the channel for the new note to be -// played. - -static void ReplaceExistingVoice(void) -{ - int i; - int result; - - // Check the allocated voices, if we find an instrument that is - // of a lower priority to the new instrument, discard it. - // If a voice is being used to play the second voice of an instrument, - // use that, as second voices are non-essential. - // Lower numbered MIDI channels implicitly have a higher priority - // than higher-numbered channels, eg. MIDI channel 1 is never - // discarded for MIDI channel 2. - - result = 0; - - for (i = 0; i < voice_alloced_num; i++) - { - if (voice_alloced_list[i]->current_instr_voice != 0 - || voice_alloced_list[i]->channel - >= voice_alloced_list[result]->channel) - { - result = i; - } - } - - ReleaseVoice(result); -} - -// Alternate versions of ReplaceExistingVoice() used when emulating old -// versions of the DMX library used in Doom 1.666, Heretic and Hexen. - -static void ReplaceExistingVoiceDoom1(void) -{ - int i; - int result; - - result = 0; - - for (i = 0; i < voice_alloced_num; i++) - { - if (voice_alloced_list[i]->channel - > voice_alloced_list[result]->channel) - { - result = i; - } - } - - ReleaseVoice(result); -} - -static void ReplaceExistingVoiceDoom2(opl_channel_data_t *channel) -{ - int i; - int result; - int priority; - - result = 0; - - priority = 0x8000; - - for (i = 0; i < voice_alloced_num - 3; i++) - { - if (voice_alloced_list[i]->priority < priority - && voice_alloced_list[i]->channel >= channel) - { - priority = voice_alloced_list[i]->priority; - result = i; - } - } - - ReleaseVoice(result); -} - - -static unsigned int FrequencyForVoice(opl_voice_t *voice) -{ - genmidi_voice_t *gm_voice; - signed int freq_index; - unsigned int octave; - unsigned int sub_index; - signed int note; - - note = voice->note; - - // Apply note offset. - // Don't apply offset if the instrument is a fixed note instrument. - - gm_voice = &voice->current_instr->voices[voice->current_instr_voice]; - - if ((SHORT(voice->current_instr->flags) & GENMIDI_FLAG_FIXED) == 0) - { - note += (signed short) SHORT(gm_voice->base_note_offset); - } - - // Avoid possible overflow due to base note offset: - - while (note < 0) - { - note += 12; - } - - while (note > 95) - { - note -= 12; - } - - freq_index = 64 + 32 * note + voice->channel->bend; - - // If this is the second voice of a double voice instrument, the - // frequency index can be adjusted by the fine tuning field. - - if (voice->current_instr_voice != 0) - { - freq_index += (voice->current_instr->fine_tuning / 2) - 64; - } - - if (freq_index < 0) - { - freq_index = 0; - } - - // The first 7 notes use the start of the table, while - // consecutive notes loop around the latter part. - - if (freq_index < 284) - { - return frequency_curve[freq_index]; - } - - sub_index = (freq_index - 284) % (12 * 32); - octave = (freq_index - 284) / (12 * 32); - - // Once the seventh octave is reached, things break down. - // We can only go up to octave 7 as a maximum anyway (the OPL - // register only has three bits for octave number), but for the - // notes in octave 7, the first five bits have octave=7, the - // following notes have octave=6. This 7/6 pattern repeats in - // following octaves (which are technically impossible to - // represent anyway). - - if (octave >= 7) - { - octave = 7; - } - - // Calculate the resulting register value to use for the frequency. - - return frequency_curve[sub_index + 284] | (octave << 10); -} - -// Update the frequency that a voice is programmed to use. - -static void UpdateVoiceFrequency(opl_voice_t *voice) -{ - unsigned int freq; - - // Calculate the frequency to use for this voice and update it - // if neccessary. - - freq = FrequencyForVoice(voice); - - if (voice->freq != freq) - { - OPL_WriteRegister((OPL_REGS_FREQ_1 + voice->index) | voice->array, - freq & 0xff); - OPL_WriteRegister((OPL_REGS_FREQ_2 + voice->index) | voice->array, - (freq >> 8) | 0x20); - - voice->freq = freq; - } -} - -// Program a single voice for an instrument. For a double voice -// instrument (GENMIDI_FLAG_2VOICE), this is called twice for each -// key on event. - -static void VoiceKeyOn(opl_channel_data_t *channel, - genmidi_instr_t *instrument, - unsigned int instrument_voice, - unsigned int note, - unsigned int key, - unsigned int volume) -{ - opl_voice_t *voice; - - if (!opl_opl3mode && opl_drv_ver == opl_doom1_1_666) - { - instrument_voice = 0; - } - - // Find a voice to use for this new note. - - voice = GetFreeVoice(); - - if (voice == NULL) - { - return; - } - - voice->channel = channel; - voice->key = key; - - // Work out the note to use. This is normally the same as - // the key, unless it is a fixed pitch instrument. - - if ((SHORT(instrument->flags) & GENMIDI_FLAG_FIXED) != 0) - { - voice->note = instrument->fixed_note; - } - else - { - voice->note = note; - } - - voice->reg_pan = channel->pan; - - // Program the voice with the instrument data: - - SetVoiceInstrument(voice, instrument, instrument_voice); - - // Set the volume level. - - SetVoiceVolume(voice, volume); - - // Write the frequency value to turn the note on. - - voice->freq = 0; - UpdateVoiceFrequency(voice); -} - -static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event) -{ - genmidi_instr_t *instrument; - opl_channel_data_t *channel; - unsigned int note, key, volume, voicenum; - boolean double_voice; - -/* - printf("note on: channel %i, %i, %i\n", - event->data.channel.channel, - event->data.channel.param1, - event->data.channel.param2); -*/ - - note = event->data.channel.param1; - key = event->data.channel.param1; - volume = event->data.channel.param2; - - // A volume of zero means key off. Some MIDI tracks, eg. the ones - // in AV.wad, use a second key on with a volume of zero to mean - // key off. - if (volume <= 0) - { - KeyOffEvent(track, event); - return; - } - - // The channel. - channel = TrackChannelForEvent(track, event); - - // Percussion channel is treated differently. - if (event->data.channel.channel == 9) - { - if (key < 35 || key > 81) - { - return; - } - - instrument = &percussion_instrs[key - 35]; - - last_perc[last_perc_count] = key; - last_perc_count = (last_perc_count + 1) % PERCUSSION_LOG_LEN; - note = 60; - } - else - { - instrument = channel->instrument; - } - - double_voice = (SHORT(instrument->flags) & GENMIDI_FLAG_2VOICE) != 0; - - switch (opl_drv_ver) - { - case opl_doom1_1_666: - voicenum = double_voice + 1; - if (!opl_opl3mode) - { - voicenum = 1; - } - while (voice_alloced_num > num_opl_voices - voicenum) - { - ReplaceExistingVoiceDoom1(); - } - - // Find and program a voice for this instrument. If this - // is a double voice instrument, we must do this twice. - - if (double_voice) - { - VoiceKeyOn(channel, instrument, 1, note, key, volume); - } - - VoiceKeyOn(channel, instrument, 0, note, key, volume); - break; - case opl_doom2_1_666: - if (voice_alloced_num == num_opl_voices) - { - ReplaceExistingVoiceDoom2(channel); - } - if (voice_alloced_num == num_opl_voices - 1 && double_voice) - { - ReplaceExistingVoiceDoom2(channel); - } - - // Find and program a voice for this instrument. If this - // is a double voice instrument, we must do this twice. - - if (double_voice) - { - VoiceKeyOn(channel, instrument, 1, note, key, volume); - } - - VoiceKeyOn(channel, instrument, 0, note, key, volume); - break; - default: - case opl_doom_1_9: - if (voice_free_num == 0) - { - ReplaceExistingVoice(); - } - - // Find and program a voice for this instrument. If this - // is a double voice instrument, we must do this twice. - - VoiceKeyOn(channel, instrument, 0, note, key, volume); - - if (double_voice) - { - VoiceKeyOn(channel, instrument, 1, note, key, volume); - } - break; - } -} - -static void ProgramChangeEvent(opl_track_data_t *track, midi_event_t *event) -{ - opl_channel_data_t *channel; - int instrument; - - // Set the instrument used on this channel. - - channel = TrackChannelForEvent(track, event); - instrument = event->data.channel.param1; - channel->instrument = &main_instrs[instrument]; - - // TODO: Look through existing voices that are turned on on this - // channel, and change the instrument. -} - -static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume, - boolean clip_start) -{ - unsigned int i; - - channel->volume_base = volume; - - if (volume > current_music_volume) - { - volume = current_music_volume; - } - - if (clip_start && volume > start_music_volume) - { - volume = start_music_volume; - } - - channel->volume = volume; - - // Update all voices that this channel is using. - - for (i = 0; i < num_opl_voices; ++i) - { - if (voices[i].channel == channel) - { - SetVoiceVolume(&voices[i], voices[i].note_volume); - } - } -} - -static void SetChannelPan(opl_channel_data_t *channel, unsigned int pan) -{ - unsigned int reg_pan; - unsigned int i; - - // The DMX library has the stereo channels backwards, maybe because - // Paul Radek had a Soundblaster card with the channels reversed, or - // perhaps it was just a bug in the OPL3 support that was never - // finished. By default we preserve this bug, but we also provide a - // secret DMXOPTION to fix it. - if (opl_stereo_correct) - { - pan = 144 - pan; - } - - if (opl_opl3mode) - { - if (pan >= 96) - { - reg_pan = 0x10; - } - else if (pan <= 48) - { - reg_pan = 0x20; - } - else - { - reg_pan = 0x30; - } - if (channel->pan != reg_pan) - { - channel->pan = reg_pan; - for (i = 0; i < num_opl_voices; i++) - { - if (voices[i].channel == channel) - { - SetVoicePan(&voices[i], reg_pan); - } - } - } - } -} - -// Handler for the MIDI_CONTROLLER_ALL_NOTES_OFF channel event. -static void AllNotesOff(opl_channel_data_t *channel, unsigned int param) -{ - int i; - - for (i = 0; i < voice_alloced_num; i++) - { - if (voice_alloced_list[i]->channel == channel) - { - // Finished with this voice now. - - ReleaseVoice(i); - - i--; - } - } -} - -static void ControllerEvent(opl_track_data_t *track, midi_event_t *event) -{ - opl_channel_data_t *channel; - unsigned int controller; - unsigned int param; - -/* - printf("change controller: channel %i, %i, %i\n", - event->data.channel.channel, - event->data.channel.param1, - event->data.channel.param2); -*/ - - channel = TrackChannelForEvent(track, event); - controller = event->data.channel.param1; - param = event->data.channel.param2; - - switch (controller) - { - case MIDI_CONTROLLER_VOLUME_MSB: - SetChannelVolume(channel, param, true); - break; - - case MIDI_CONTROLLER_PAN: - SetChannelPan(channel, param); - break; - - case MIDI_CONTROLLER_ALL_NOTES_OFF: - AllNotesOff(channel, param); - break; - - default: -#ifdef OPL_MIDI_DEBUG - fprintf(stderr, "Unknown MIDI controller type: %u\n", controller); -#endif - break; - } -} - -// Process a pitch bend event. - -static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event) -{ - opl_channel_data_t *channel; - int i; - opl_voice_t *voice_updated_list[OPL_NUM_VOICES * 2]; - unsigned int voice_updated_num = 0; - opl_voice_t *voice_not_updated_list[OPL_NUM_VOICES * 2]; - unsigned int voice_not_updated_num = 0; - - // Update the channel bend value. Only the MSB of the pitch bend - // value is considered: this is what Doom does. - - channel = TrackChannelForEvent(track, event); - channel->bend = event->data.channel.param2 - 64; - - // Update all voices for this channel. - - for (i = 0; i < voice_alloced_num; ++i) - { - if (voice_alloced_list[i]->channel == channel) - { - UpdateVoiceFrequency(voice_alloced_list[i]); - voice_updated_list[voice_updated_num++] = voice_alloced_list[i]; - } - else - { - voice_not_updated_list[voice_not_updated_num++] = - voice_alloced_list[i]; - } - } - - for (i = 0; i < voice_not_updated_num; i++) - { - voice_alloced_list[i] = voice_not_updated_list[i]; - } - - for (i = 0; i < voice_updated_num; i++) - { - voice_alloced_list[i + voice_not_updated_num] = voice_updated_list[i]; - } -} - -static void MetaSetTempo(unsigned int tempo) -{ - OPL_AdjustCallbacks((float) us_per_beat / tempo); - us_per_beat = tempo; -} - -// Process a meta event. - -static void MetaEvent(opl_track_data_t *track, midi_event_t *event) -{ - byte *data = event->data.meta.data; - unsigned int data_len = event->data.meta.length; - - switch (event->data.meta.type) - { - // Things we can just ignore. - - case MIDI_META_SEQUENCE_NUMBER: - case MIDI_META_TEXT: - case MIDI_META_COPYRIGHT: - case MIDI_META_TRACK_NAME: - case MIDI_META_INSTR_NAME: - case MIDI_META_LYRICS: - case MIDI_META_MARKER: - case MIDI_META_CUE_POINT: - case MIDI_META_SEQUENCER_SPECIFIC: - break; - - case MIDI_META_SET_TEMPO: - if (data_len == 3) - { - MetaSetTempo((data[0] << 16) | (data[1] << 8) | data[2]); - } - break; - - // End of track - actually handled when we run out of events - // in the track, see below. - - case MIDI_META_END_OF_TRACK: - break; - - default: -#ifdef OPL_MIDI_DEBUG - fprintf(stderr, "Unknown MIDI meta event type: %u\n", - event->data.meta.type); -#endif - break; - } -} - -// Process a MIDI event from a track. - -static void ProcessEvent(opl_track_data_t *track, midi_event_t *event) -{ - switch (event->event_type) - { - case MIDI_EVENT_NOTE_OFF: - KeyOffEvent(track, event); - break; - - case MIDI_EVENT_NOTE_ON: - KeyOnEvent(track, event); - break; - - case MIDI_EVENT_CONTROLLER: - ControllerEvent(track, event); - break; - - case MIDI_EVENT_PROGRAM_CHANGE: - ProgramChangeEvent(track, event); - break; - - case MIDI_EVENT_PITCH_BEND: - PitchBendEvent(track, event); - break; - - case MIDI_EVENT_META: - MetaEvent(track, event); - break; - - // SysEx events can be ignored. - - case MIDI_EVENT_SYSEX: - case MIDI_EVENT_SYSEX_SPLIT: - break; - - default: -#ifdef OPL_MIDI_DEBUG - fprintf(stderr, "Unknown MIDI event type %i\n", event->event_type); -#endif - break; - } -} - -static void ScheduleTrack(opl_track_data_t *track); -static void InitChannel(opl_channel_data_t *channel); - -// Restart a song from the beginning. - -static void RestartSong(void *unused) -{ - unsigned int i; - - running_tracks = num_tracks; - - start_music_volume = current_music_volume; - - for (i = 0; i < num_tracks; ++i) - { - MIDI_RestartIterator(tracks[i].iter); - ScheduleTrack(&tracks[i]); - } - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - InitChannel(&channels[i]); - } -} - -// Callback function invoked when another event needs to be read from -// a track. - -static void TrackTimerCallback(void *arg) -{ - opl_track_data_t *track = arg; - midi_event_t *event; - - // Get the next event and process it. - - if (!MIDI_GetNextEvent(track->iter, &event)) - { - return; - } - - ProcessEvent(track, event); - - // End of track? - - if (event->event_type == MIDI_EVENT_META - && event->data.meta.type == MIDI_META_END_OF_TRACK) - { - --running_tracks; - - // When all tracks have finished, restart the song. - // Don't restart the song immediately, but wait for 5ms - // before triggering a restart. Otherwise it is possible - // to construct an empty MIDI file that causes the game - // to lock up in an infinite loop. (5ms should be short - // enough not to be noticeable by the listener). - - if (running_tracks <= 0 && song_looping) - { - OPL_SetCallback(5000, RestartSong, NULL); - } - - return; - } - - // Reschedule the callback for the next event in the track. - - ScheduleTrack(track); -} - -static void ScheduleTrack(opl_track_data_t *track) -{ - unsigned int nticks; - uint64_t us; - - // Get the number of microseconds until the next event. - - nticks = MIDI_GetDeltaTime(track->iter); - us = ((uint64_t) nticks * us_per_beat) / ticks_per_beat; - - // Set a timer to be invoked when the next event is - // ready to play. - - OPL_SetCallback(us, TrackTimerCallback, track); -} - -// Initialize a channel. - -static void InitChannel(opl_channel_data_t *channel) -{ - // TODO: Work out sensible defaults? - - channel->instrument = &main_instrs[0]; - channel->volume = current_music_volume; - channel->volume_base = 100; - if (channel->volume > channel->volume_base) - { - channel->volume = channel->volume_base; - } - channel->pan = 0x30; - channel->bend = 0; -} - -// Start a MIDI track playing: - -static void StartTrack(midi_file_t *file, unsigned int track_num) -{ - opl_track_data_t *track; - - track = &tracks[track_num]; - track->iter = MIDI_IterateTrack(file, track_num); - - // Schedule the first event. - - ScheduleTrack(track); -} - -// Start playing a mid - -static void I_OPL_PlaySong(void *handle, boolean looping) -{ - midi_file_t *file; - unsigned int i; - - if (!music_initialized || handle == NULL) - { - return; - } - - file = handle; - - // Allocate track data. - - tracks = malloc(MIDI_NumTracks(file) * sizeof(opl_track_data_t)); - - num_tracks = MIDI_NumTracks(file); - running_tracks = num_tracks; - song_looping = looping; - - ticks_per_beat = MIDI_GetFileTimeDivision(file); - - // Default is 120 bpm. - // TODO: this is wrong - - us_per_beat = 500 * 1000; - - start_music_volume = current_music_volume; - - for (i = 0; i < num_tracks; ++i) - { - StartTrack(file, i); - } - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - InitChannel(&channels[i]); - } - - // If the music was previously paused, it needs to be unpaused; playing - // a new song implies that we turn off pause. This matches vanilla - // behavior of the DMX library, and some of the higher-level code in - // s_sound.c relies on this. - OPL_SetPaused(0); -} - -static void I_OPL_PauseSong(void) -{ - unsigned int i; - - if (!music_initialized) - { - return; - } - - // Pause OPL callbacks. - - OPL_SetPaused(1); - - // Turn off all main instrument voices (not percussion). - // This is what Vanilla does. - - for (i = 0; i < num_opl_voices; ++i) - { - if (voices[i].channel != NULL - && voices[i].current_instr < percussion_instrs) - { - VoiceKeyOff(&voices[i]); - } - } -} - -static void I_OPL_ResumeSong(void) -{ - if (!music_initialized) - { - return; - } - - OPL_SetPaused(0); -} - -static void I_OPL_StopSong(void) -{ - unsigned int i; - - if (!music_initialized) - { - return; - } - - OPL_Lock(); - - // Stop all playback. - - OPL_ClearCallbacks(); - - // Free all voices. - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - AllNotesOff(&channels[i], 0); - } - - // Free all track data. - - for (i = 0; i < num_tracks; ++i) - { - MIDI_FreeIterator(tracks[i].iter); - } - - free(tracks); - - tracks = NULL; - num_tracks = 0; - - OPL_Unlock(); -} - -static void I_OPL_UnRegisterSong(void *handle) -{ - if (!music_initialized) - { - return; - } - - if (handle != NULL) - { - MIDI_FreeFile(handle); - } -} - -// Determine whether memory block is a .mid file - -static boolean IsMid(byte *mem, int len) -{ - return len > 4 && !memcmp(mem, "MThd", 4); -} - -static boolean ConvertMus(byte *musdata, int len, char *filename) -{ - MEMFILE *instream; - MEMFILE *outstream; - void *outbuf; - size_t outbuf_len; - int result; - - instream = mem_fopen_read(musdata, len); - outstream = mem_fopen_write(); - - result = mus2mid(instream, outstream); - - if (result == 0) - { - mem_get_buf(outstream, &outbuf, &outbuf_len); - - M_WriteFile(filename, outbuf, outbuf_len); - } - - mem_fclose(instream); - mem_fclose(outstream); - - return result; -} - -static void *I_OPL_RegisterSong(void *data, int len) -{ - midi_file_t *result; - char *filename; - - if (!music_initialized) - { - return NULL; - } - - // MUS files begin with "MUS" - // Reject anything which doesnt have this signature - - filename = M_TempFile("doom.mid"); - - if (IsMid(data, len) && len < MAXMIDLENGTH) - { - M_WriteFile(filename, data, len); - } - else - { - // Assume a MUS file and try to convert - - ConvertMus(data, len, filename); - } - - result = MIDI_LoadFile(filename); - - if (result == NULL) - { - fprintf(stderr, "I_OPL_RegisterSong: Failed to load MID.\n"); - } - - // remove file now - - M_remove(filename); - free(filename); - - return result; -} - -// Is the song playing? - -static boolean I_OPL_MusicIsPlaying(void) -{ - if (!music_initialized) - { - return false; - } - - return num_tracks > 0; -} - -// Shutdown music - -static void I_OPL_ShutdownMusic(void) -{ - if (music_initialized) - { - // Stop currently-playing track, if there is one: - - I_OPL_StopSong(); - - OPL_Shutdown(); - - // Release GENMIDI lump - - W_ReleaseLumpName(DEH_String("genmidi")); - - music_initialized = false; - } -} - -// Initialize music subsystem - -static boolean I_OPL_InitMusic(void) -{ - const char *dmxoption; - opl_init_result_t chip_type; - - OPL_SetSampleRate(snd_samplerate); - - chip_type = OPL_Init(opl_io_port); - if (chip_type == OPL_INIT_NONE) - { - printf("Dude. The Adlib isn't responding.\n"); - return false; - } - - // The DMXOPTION variable must be set to enable OPL3 support. - // As an extension, we also allow it to be set from the config file. - dmxoption = getenv("DMXOPTION"); - if (dmxoption == NULL) - { - dmxoption = snd_dmxoption != NULL ? snd_dmxoption : ""; - } - - if (chip_type == OPL_INIT_OPL3 && strstr(dmxoption, "-opl3") != NULL) - { - opl_opl3mode = 1; - num_opl_voices = OPL_NUM_VOICES * 2; - } - else - { - opl_opl3mode = 0; - num_opl_voices = OPL_NUM_VOICES; - } - - // Secret, undocumented DMXOPTION that reverses the stereo channels - // into their correct orientation. - opl_stereo_correct = strstr(dmxoption, "-reverse") != NULL; - - // Initialize all registers. - - OPL_InitRegisters(opl_opl3mode); - - // Load instruments from GENMIDI lump: - - if (!LoadInstrumentTable()) - { - OPL_Shutdown(); - return false; - } - - InitVoices(); - - tracks = NULL; - num_tracks = 0; - music_initialized = true; - - return true; -} - -const static snddevice_t music_opl_devices[] = -{ - SNDDEVICE_ADLIB, - SNDDEVICE_SB, -}; - -const music_module_t music_opl_module = -{ - music_opl_devices, - arrlen(music_opl_devices), - I_OPL_InitMusic, - I_OPL_ShutdownMusic, - I_OPL_SetMusicVolume, - I_OPL_PauseSong, - I_OPL_ResumeSong, - I_OPL_RegisterSong, - I_OPL_UnRegisterSong, - I_OPL_PlaySong, - I_OPL_StopSong, - I_OPL_MusicIsPlaying, - NULL, // Poll -}; - -void I_SetOPLDriverVer(opl_driver_ver_t ver) -{ - opl_drv_ver = ver; -} - -//---------------------------------------------------------------------- -// -// Development / debug message generation, to help developing GENMIDI -// lumps. -// -//---------------------------------------------------------------------- - -static int NumActiveChannels(void) -{ - int i; - - for (i = MIDI_CHANNELS_PER_TRACK - 1; i >= 0; --i) - { - if (channels[i].instrument != &main_instrs[0]) - { - return i + 1; - } - } - - return 0; -} - -static int ChannelInUse(opl_channel_data_t *channel) -{ - int i; - - for (i = 0; i < voice_alloced_num; i++) - { - if (voice_alloced_list[i]->channel == channel) - { - return 1; - } - } - - return 0; -} - -void I_OPL_DevMessages(char *result, size_t result_len) -{ - char tmp[80]; - int instr_num; - int lines; - int i; - - if (num_tracks == 0) - { - M_snprintf(result, result_len, "No OPL track!"); - return; - } - - M_snprintf(result, result_len, "Tracks:\n"); - lines = 1; - - for (i = 0; i < NumActiveChannels(); ++i) - { - if (channels[i].instrument == NULL) - { - continue; - } - - instr_num = channels[i].instrument - main_instrs; - - M_snprintf(tmp, sizeof(tmp), - "chan %i: %c i#%i (%s)\n", - i, - ChannelInUse(&channels[i]) ? '\'' : ' ', - instr_num + 1, - main_instr_names[instr_num]); - M_StringConcat(result, tmp, result_len); - - ++lines; - } - - M_snprintf(tmp, sizeof(tmp), "\nLast percussion:\n"); - M_StringConcat(result, tmp, result_len); - lines += 2; - - i = (last_perc_count + PERCUSSION_LOG_LEN - 1) % PERCUSSION_LOG_LEN; - - do { - if (last_perc[i] == 0) - { - break; - } - - M_snprintf(tmp, sizeof(tmp), - "%cp#%i (%s)\n", - i == 0 ? '\'' : ' ', - last_perc[i], - percussion_names[last_perc[i] - 35]); - M_StringConcat(result, tmp, result_len); - ++lines; - - i = (i + PERCUSSION_LOG_LEN - 1) % PERCUSSION_LOG_LEN; - } while (lines < 25 && i != last_perc_count); -} - diff --git a/games/NXDoom/src/i_pcsound.c b/games/NXDoom/src/i_pcsound.c index c3ec62803b6..2548fbe967b 100644 --- a/games/NXDoom/src/i_pcsound.c +++ b/games/NXDoom/src/i_pcsound.c @@ -1,21 +1,29 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System interface for PC speaker sound. -// - -#include "SDL.h" +/**************************************************************************** + * apps/games/NXDoom/src/i_pcsound.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System interface for PC speaker sound. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include #include "doomtype.h" @@ -28,311 +36,201 @@ #include "pcsound.h" -#define TIMER_FREQ 1193181 /* hz */ - -static boolean pcs_initialized = false; - -static SDL_mutex *sound_lock; -static GameMission_t gamemission; - -static uint8_t *current_sound_lump = NULL; -static uint8_t *current_sound_pos = NULL; -static unsigned int current_sound_remaining = 0; -static int current_sound_handle = 0; -static int current_sound_lump_num = -1; - -static const uint16_t divisors[] = { - 0, - 6818, 6628, 6449, 6279, 6087, 5906, 5736, 5575, - 5423, 5279, 5120, 4971, 4830, 4697, 4554, 4435, - 4307, 4186, 4058, 3950, 3836, 3728, 3615, 3519, - 3418, 3323, 3224, 3131, 3043, 2960, 2875, 2794, - 2711, 2633, 2560, 2485, 2415, 2348, 2281, 2213, - 2153, 2089, 2032, 1975, 1918, 1864, 1810, 1757, - 1709, 1659, 1612, 1565, 1521, 1478, 1435, 1395, - 1355, 1316, 1280, 1242, 1207, 1173, 1140, 1107, - 1075, 1045, 1015, 986, 959, 931, 905, 879, - 854, 829, 806, 783, 760, 739, 718, 697, - 677, 658, 640, 621, 604, 586, 570, 553, - 538, 522, 507, 493, 479, 465, 452, 439, - 427, 415, 403, 391, 380, 369, 359, 348, - 339, 329, 319, 310, 302, 293, 285, 276, - 269, 261, 253, 246, 239, 232, 226, 219, - 213, 207, 201, 195, 190, 184, 179, -}; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -static void PCSCallbackFunc(int *duration, int *freq) -{ - unsigned int tone; +#define TIMER_FREQ 1193181 /* Hz */ - *duration = 1000 / 140; +/**************************************************************************** + * Private Data + ****************************************************************************/ - if (SDL_LockMutex(sound_lock) < 0) - { - *freq = 0; - return; - } +static boolean g_pcs_initialized = false; - if (current_sound_lump != NULL && current_sound_remaining > 0) - { - // Read the next tone +static gamemission_t g_gamemission; - tone = *current_sound_pos; +static uint8_t *g_current_sound_lump = NULL; +static uint8_t *g_current_sound_pos = NULL; +static unsigned int g_current_sound_remaining = 0; +static int g_current_sound_handle = 0; +static int g_current_sound_lump_num = -1; - // Use the tone -> frequency lookup table. See pcspkr10.zip - // for a full discussion of this. - // Check we don't overflow the frequency table. +static const uint16_t g_divisors[] = +{ + 0, 6818, 6628, 6449, 6279, 6087, 5906, 5736, 5575, 5423, 5279, 5120, + 4971, 4830, 4697, 4554, 4435, 4307, 4186, 4058, 3950, 3836, 3728, 3615, + 3519, 3418, 3323, 3224, 3131, 3043, 2960, 2875, 2794, 2711, 2633, 2560, + 2485, 2415, 2348, 2281, 2213, 2153, 2089, 2032, 1975, 1918, 1864, 1810, + 1757, 1709, 1659, 1612, 1565, 1521, 1478, 1435, 1395, 1355, 1316, 1280, + 1242, 1207, 1173, 1140, 1107, 1075, 1045, 1015, 986, 959, 931, 905, + 879, 854, 829, 806, 783, 760, 739, 718, 697, 677, 658, 640, + 621, 604, 586, 570, 553, 538, 522, 507, 493, 479, 465, 452, + 439, 427, 415, 403, 391, 380, 369, 359, 348, 339, 329, 319, + 310, 302, 293, 285, 276, 269, 261, 253, 246, 239, 232, 226, + 219, 213, 207, 201, 195, 190, 184, 179, +}; - if (tone < arrlen(divisors) && divisors[tone] != 0) - { - *freq = (int) (TIMER_FREQ / divisors[tone]); - } - else - { - *freq = 0; - } +static const snddevice_t g_sound_pcsound_devices[] = +{ + SNDDEVICE_PCSPEAKER, +}; - ++current_sound_pos; - --current_sound_remaining; - } - else - { - *freq = 0; - } +/**************************************************************************** + * Public Data + ****************************************************************************/ - SDL_UnlockMutex(sound_lock); +const sound_module_t sound_pcsound_module = +{ + g_sound_pcsound_devices, + arrlen(g_sound_pcsound_devices), +#if 0 + i_pcs_init_sound, + i_pcs_shutdown_sound, + i_pcs_get_sfx_lumpnum, + i_pcs_update_sound, + i_pcs_update_sound_params, + i_pcs_start_sound, + i_pcs_stop_sound, + i_pcs_sound_is_playing, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void pcs_callback_func(int *duration, int *freq) +{ } -static boolean CachePCSLump(sfxinfo_t *sfxinfo) +static boolean cache_pcs_lump(sfxinfo_t *sfxinfo) { - int lumplen; - int headerlen; + int lumplen; + int headerlen; + + /* Free the current sound lump back to the cache */ - // Free the current sound lump back to the cache - - if (current_sound_lump != NULL) + if (g_current_sound_lump != NULL) { - W_ReleaseLumpNum(current_sound_lump_num); - current_sound_lump = NULL; + w_release_lump_num(g_current_sound_lump_num); + g_current_sound_lump = NULL; } - // Load from WAD + /* Load from WAD */ - current_sound_lump = W_CacheLumpNum(sfxinfo->lumpnum, PU_STATIC); - lumplen = W_LumpLength(sfxinfo->lumpnum); + g_current_sound_lump = w_cache_lump_num(sfxinfo->lumpnum, PU_STATIC); + lumplen = w_lump_length(sfxinfo->lumpnum); - // Read header - - if (current_sound_lump[0] != 0x00 || current_sound_lump[1] != 0x00) + /* Read header */ + + if (g_current_sound_lump[0] != 0x00 || g_current_sound_lump[1] != 0x00) { - return false; + return false; } - headerlen = (current_sound_lump[3] << 8) | current_sound_lump[2]; + headerlen = (g_current_sound_lump[3] << 8) | g_current_sound_lump[2]; - if (headerlen > lumplen - 4) + if (headerlen > lumplen - 4) { - return false; + return false; } - // Header checks out ok + /* Header checks out ok */ - current_sound_remaining = headerlen; - current_sound_pos = current_sound_lump + 4; - current_sound_lump_num = sfxinfo->lumpnum; + g_current_sound_remaining = headerlen; + g_current_sound_pos = g_current_sound_lump + 4; + g_current_sound_lump_num = sfxinfo->lumpnum; - return true; + return true; } -// These Doom PC speaker sounds are not played - this can be seen in the -// Heretic source code, where there are remnants of this left over -// from Doom. +/* These Doom PC speaker sounds are not played - this can be seen in the + * Heretic source code, where there are remnants of this left over + * from Doom. + */ -static boolean IsDisabledSound(sfxinfo_t *sfxinfo) +static boolean is_disabled_sound(sfxinfo_t *sfxinfo) { - int i; - const char *disabled_sounds[] = { - "posact", - "bgact", - "dmact", - "dmpain", - "popain", - "sawidl", - "rifle", - }; - - for (i=0; iname, disabled_sounds[i])) + if (!strcmp(sfxinfo->name, disabled_sounds[i])) { - return true; + return true; } } - return false; + return false; } -static int I_PCS_StartSound(sfxinfo_t *sfxinfo, - int channel, - int vol, - int sep, - int pitch) +static int i_pcs_start_sound(sfxinfo_t *sfxinfo, int channel, int vol, + int sep, int pitch) { - int result; - - if (!pcs_initialized) - { - return -1; - } - - if (IsDisabledSound(sfxinfo)) - { - return -1; - } - - if (SDL_LockMutex(sound_lock) < 0) - { - return -1; - } - - result = CachePCSLump(sfxinfo); - - if (result) - { - current_sound_handle = channel; - } - - SDL_UnlockMutex(sound_lock); - - if (result) - { - return channel; - } - else - { - return -1; - } } -static void I_PCS_StopSound(int handle) +static void i_pcs_stop_sound(int handle) { - if (!pcs_initialized) - { - return; - } - - if (SDL_LockMutex(sound_lock) < 0) - { - return; - } - - // If this is the channel currently playing, immediately end it. - - if (current_sound_handle == handle) - { - current_sound_remaining = 0; - } - - SDL_UnlockMutex(sound_lock); } -// -// Retrieve the raw data lump index -// for a given SFX name. -// +/* Retrieve the raw data lump index for a given SFX name. */ -static int I_PCS_GetSfxLumpNum(sfxinfo_t* sfx) +static int i_pcs_get_sfx_lumpnum(sfxinfo_t *sfx) { - char namebuf[9]; + char namebuf[9]; - if (gamemission == doom || gamemission == strife) + if (g_gamemission == doom || g_gamemission == strife) { - M_snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String(sfx->name)); + snprintf(namebuf, sizeof(namebuf), "dp%s", (sfx->name)); - if (gamemission == strife && W_CheckNumForName(namebuf) == -1) + if (g_gamemission == strife && w_check_num_for_name(namebuf) == -1) { - // Missing sounds replaced with DPRIFLE. - M_snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String("rifle")); + /* Missing sounds replaced with DPRIFLE. */ + + snprintf(namebuf, sizeof(namebuf), "dp%s", ("rifle")); } } - else + else { - M_StringCopy(namebuf, DEH_String(sfx->name), sizeof(namebuf)); + m_str_copy(namebuf, (sfx->name), sizeof(namebuf)); } - return W_GetNumForName(namebuf); + return w_get_num_for_name(namebuf); } - -static boolean I_PCS_SoundIsPlaying(int handle) +static boolean i_pcs_sound_is_playing(int handle) { - if (!pcs_initialized) + if (!g_pcs_initialized) { - return false; + return false; } - if (handle != current_sound_handle) + if (handle != g_current_sound_handle) { - return false; + return false; } - return current_sound_lump != NULL && current_sound_remaining > 0; + return g_current_sound_lump != NULL && g_current_sound_remaining > 0; } -static boolean I_PCS_InitSound(GameMission_t mission) +static boolean i_pcs_init_sound(gamemission_t mission) { - gamemission = mission; - - // Use the sample rate from the configuration file - - PCSound_SetSampleRate(snd_samplerate); - - // Initialize the PC speaker subsystem. - - pcs_initialized = PCSound_Init(PCSCallbackFunc); - - if (pcs_initialized) - { - sound_lock = SDL_CreateMutex(); - } - - return pcs_initialized; } -static void I_PCS_ShutdownSound(void) +static void i_pcs_shutdown_sound(void) { - if (pcs_initialized) - { - PCSound_Shutdown(); - } } -static void I_PCS_UpdateSound(void) +static void i_pcs_update_sound(void) { - // no-op. + /* no-op. */ } -void I_PCS_UpdateSoundParams(int channel, int vol, int sep) +static void i_pcs_update_sound_params(int channel, int vol, int sep) { - // no-op. + /* no-op. */ } - -static const snddevice_t sound_pcsound_devices[] = -{ - SNDDEVICE_PCSPEAKER, -}; - -const sound_module_t sound_pcsound_module = -{ - sound_pcsound_devices, - arrlen(sound_pcsound_devices), - I_PCS_InitSound, - I_PCS_ShutdownSound, - I_PCS_GetSfxLumpNum, - I_PCS_UpdateSound, - I_PCS_UpdateSoundParams, - I_PCS_StartSound, - I_PCS_StopSound, - I_PCS_SoundIsPlaying, -}; - diff --git a/games/NXDoom/src/i_sdlmusic.c b/games/NXDoom/src/i_sdlmusic.c index 70502d0b203..29af65a4e62 100644 --- a/games/NXDoom/src/i_sdlmusic.c +++ b/games/NXDoom/src/i_sdlmusic.c @@ -1,28 +1,34 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System interface for music. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_sdlmusic.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System interface for music. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include - -#include "SDL.h" #include "config.h" #include "doomtype.h" @@ -32,8 +38,8 @@ #include "deh_str.h" #include "gusconf.h" #include "i_sound.h" -#include "i_system.h" #include "i_swap.h" +#include "i_system.h" #include "m_argv.h" #include "m_config.h" #include "m_misc.h" @@ -41,433 +47,103 @@ #include "w_wad.h" #include "z_zone.h" - -char *timidity_cfg_path = ""; +/**************************************************************************** + * Private Data + ****************************************************************************/ static char *temp_timidity_cfg = NULL; -// If the temp_timidity_cfg config variable is set, generate a "wrapper" -// config file for Timidity to point to the actual config file. This -// is needed to inject a "dir" command so that the patches are read -// relative to the actual config file. - -static boolean WriteWrapperTimidityConfig(char *write_path) -{ - char *path; - FILE *fstream; - - if (!strcmp(timidity_cfg_path, "")) - { - return false; - } - - fstream = M_fopen(write_path, "w"); - - if (fstream == NULL) - { - return false; - } - - path = M_DirName(timidity_cfg_path); - fprintf(fstream, "dir %s\n", path); - free(path); - - fprintf(fstream, "source %s\n", timidity_cfg_path); - fclose(fstream); - - return true; -} - - -// putenv requires a non-const string whose lifetime is the whole program -// so can't use a string directly, have to do this silliness -static char sdl_mixer_disable_fluidsynth[] = "SDL_MIXER_DISABLE_FLUIDSYNTH=1"; - - -void I_InitTimidityConfig(void) -{ - char *env_string; - boolean success; - - temp_timidity_cfg = M_TempFile("timidity.cfg"); - - if (snd_musicdevice == SNDDEVICE_GUS) - { - success = GUS_WriteConfig(temp_timidity_cfg); - } - else - { - success = WriteWrapperTimidityConfig(temp_timidity_cfg); - } - - // Set the TIMIDITY_CFG environment variable to point to the temporary - // config file. - if (success) - { - env_string = M_StringJoin("TIMIDITY_CFG=", temp_timidity_cfg, NULL); - putenv(env_string); - // env_string deliberately not freed; see putenv manpage - - // If we're explicitly configured to use Timidity (either through - // timidity_cfg_path or GUS mode), then disable Fluidsynth, because - // SDL_mixer considers Fluidsynth a higher priority than Timidity and - // therefore can end up circumventing Timidity entirely. - putenv(sdl_mixer_disable_fluidsynth); - } - else - { - free(temp_timidity_cfg); - temp_timidity_cfg = NULL; - } -} - - -#ifndef DISABLE_SDL2MIXER +/* putenv requires a non-const string whose lifetime is the whole program + * so can't use a string directly, have to do this silliness + */ -#include "SDL_mixer.h" +static char sdl_mixer_disable_fluidsynth[] = + "SDL_MIXER_DISABLE_FLUIDSYNTH=1"; +/**************************************************************************** + * Public Data + ****************************************************************************/ -#define MAXMIDLENGTH (96 * 1024) - -static boolean music_initialized = false; - -// If this is true, this module initialized SDL sound and has the -// responsibility to shut it down - -static boolean sdl_was_initialized = false; - -static boolean musicpaused = false; -static int current_music_volume; - - -// Remove the temporary config file generated by I_InitTimidityConfig(). - -static void RemoveTimidityConfig(void) -{ - if (temp_timidity_cfg != NULL) - { - M_remove(temp_timidity_cfg); - free(temp_timidity_cfg); - } -} - -// Shutdown music - -static void I_SDL_ShutdownMusic(void) -{ - if (music_initialized) - { - Mix_HaltMusic(); - music_initialized = false; - - if (sdl_was_initialized) - { - Mix_CloseAudio(); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - sdl_was_initialized = false; - } - } -} - -static boolean SDLIsInitialized(void) -{ - int freq, channels; - Uint16 format; - - return Mix_QuerySpec(&freq, &format, &channels) != 0; -} - -#ifdef _WIN32 -// putenv requires a non-const string whose lifetime is the whole program -static char sdl_mixer_disable_nativemidi[] = "SDL_MIXER_DISABLE_NATIVEMIDI=1"; -#endif - -// Initialize music subsystem -static boolean I_SDL_InitMusic(void) -{ - // If SDL_mixer is not initialized, we have to initialize it - // and have the responsibility to shut it down later on. - - if (SDLIsInitialized()) - { - music_initialized = true; - } - else - { - if (SDL_Init(SDL_INIT_AUDIO) < 0) - { - fprintf(stderr, "Unable to set up sound.\n"); - } - else if (Mix_OpenAudioDevice(snd_samplerate, AUDIO_S16SYS, 2, 1024, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) - { - fprintf(stderr, "Error initializing SDL_mixer: %s\n", - Mix_GetError()); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } - else - { - SDL_PauseAudio(0); - - sdl_was_initialized = true; - music_initialized = true; - } - } - - #ifdef _WIN32 - // Never let SDL Mixer use native midi on Windows. Avoids SDL Mixer bug - // where music volume affects global application volume. - putenv(sdl_mixer_disable_nativemidi); - #endif - - // Initialize SDL_Mixer for MIDI music playback - Mix_Init(MIX_INIT_MID); - - // Once initialization is complete, the temporary Timidity config - // file can be removed. - - RemoveTimidityConfig(); - - // If snd_musiccmd is set, we need to call Mix_SetMusicCMD to - // configure an external music playback program. - - if (strlen(snd_musiccmd) > 0) - { - Mix_SetMusicCMD(snd_musiccmd); - } - - return music_initialized; -} - -// -// SDL_mixer's native MIDI music playing does not pause properly. -// As a workaround, set the volume to 0 when paused. -// - -static void UpdateMusicVolume(void) -{ - int vol; - - if (musicpaused) - { - vol = 0; - } - else - { - vol = (current_music_volume * MIX_MAX_VOLUME) / 127; - } - - Mix_VolumeMusic(vol); -} - -// Set music volume (0 - 127) - -static void I_SDL_SetMusicVolume(int volume) -{ - // Internal state variable. - current_music_volume = volume; - - UpdateMusicVolume(); -} - -// Start playing a mid - -static void I_SDL_PlaySong(void *handle, boolean looping) -{ - int loops; - - if (!music_initialized) - { - return; - } - - if (handle == NULL) - { - return; - } - - if (looping) - { - loops = -1; - } - else - { - loops = 1; - } - - Mix_PlayMusic((Mix_Music *) handle, loops); -} - -static void I_SDL_PauseSong(void) -{ - if (!music_initialized) - { - return; - } +char *timidity_cfg_path = ""; - musicpaused = true; +/**************************************************************************** + * Private Functions + ****************************************************************************/ - UpdateMusicVolume(); -} +/* If the temp_timidity_cfg config variable is set, generate a "wrapper" + * config file for Timidity to point to the actual config file. This + * is needed to inject a "dir" command so that the patches are read + * relative to the actual config file. + */ -static void I_SDL_ResumeSong(void) +static boolean write_wrapper_timidity_config(char *write_path) { - if (!music_initialized) - { - return; - } + char *path; + FILE *fstream; - musicpaused = false; - - UpdateMusicVolume(); -} - -static void I_SDL_StopSong(void) -{ - if (!music_initialized) + if (!strcmp(timidity_cfg_path, "")) { - return; + return false; } - Mix_HaltMusic(); -} - -static void I_SDL_UnRegisterSong(void *handle) -{ - Mix_Music *music = (Mix_Music *) handle; + fstream = fopen(write_path, "w"); - if (!music_initialized) + if (fstream == NULL) { - return; + return false; } - if (handle != NULL) - { - Mix_FreeMusic(music); - } -} + path = m_dir_name(timidity_cfg_path); + fprintf(fstream, "dir %s\n", path); + free(path); -// Determine whether memory block is a .mid file + fprintf(fstream, "source %s\n", timidity_cfg_path); + fclose(fstream); -static boolean IsMid(byte *mem, int len) -{ - return len > 4 && !memcmp(mem, "MThd", 4); + return true; } -static boolean ConvertMus(byte *musdata, int len, const char *filename) -{ - MEMFILE *instream; - MEMFILE *outstream; - void *outbuf; - size_t outbuf_len; - int result; - - instream = mem_fopen_read(musdata, len); - outstream = mem_fopen_write(); - - result = mus2mid(instream, outstream); - - if (result == 0) - { - mem_get_buf(outstream, &outbuf, &outbuf_len); - - M_WriteFile(filename, outbuf, outbuf_len); - } - - mem_fclose(instream); - mem_fclose(outstream); - - return result; -} +/**************************************************************************** + * Public Functions + ****************************************************************************/ -static void *I_SDL_RegisterSong(void *data, int len) +void i_init_timidity_config(void) { - char *filename; - Mix_Music *music; - - if (!music_initialized) - { - return NULL; - } - - // MUS files begin with "MUS" - // Reject anything which doesnt have this signature + char *env_string; + boolean success; - filename = M_TempFile("doom.mid"); + temp_timidity_cfg = m_temp_file("timidity.cfg"); - if (IsMid(data, len) && len < MAXMIDLENGTH) + if (snd_musicdevice == SNDDEVICE_GUS) { - M_WriteFile(filename, data, len); + success = gus_write_config(temp_timidity_cfg); } - else + else { - // Assume a MUS file and try to convert - - ConvertMus(data, len, filename); + success = write_wrapper_timidity_config(temp_timidity_cfg); } - // Load the MIDI. In an ideal world we'd be using Mix_LoadMUS_RW() - // by now, but Mix_SetMusicCMD() only works with Mix_LoadMUS(), so - // we have to generate a temporary file. + /* Set the TIMIDITY_CFG environment variable to point to the temporary + * config file. + */ - music = Mix_LoadMUS(filename); - if (music == NULL) + if (success) { - // Failed to load - fprintf(stderr, "Error loading midi: %s\n", Mix_GetError()); - } + env_string = m_string_join("TIMIDITY_CFG=", temp_timidity_cfg, NULL); + putenv(env_string); - // Remove the temporary MIDI file; however, when using an external - // MIDI program we can't delete the file. Otherwise, the program - // won't find the file to play. This means we leave a mess on - // disk :( + /* env_string deliberately not freed; see putenv manpage + * If we're explicitly configured to use Timidity (either through + * timidity_cfg_path or GUS mode), then disable Fluidsynth, because + * SDL_mixer considers Fluidsynth a higher priority than Timidity and + * therefore can end up circumventing Timidity entirely. + */ - if (strlen(snd_musiccmd) == 0) - { - M_remove(filename); + putenv(sdl_mixer_disable_fluidsynth); } - - free(filename); - - return music; -} - -// Is the song playing? -static boolean I_SDL_MusicIsPlaying(void) -{ - if (!music_initialized) + else { - return false; + free(temp_timidity_cfg); + temp_timidity_cfg = NULL; } - - return Mix_PlayingMusic(); } - -static const snddevice_t music_sdl_devices[] = -{ - SNDDEVICE_PAS, - SNDDEVICE_GUS, - SNDDEVICE_WAVEBLASTER, - SNDDEVICE_SOUNDCANVAS, - SNDDEVICE_GENMIDI, - SNDDEVICE_AWE32, -}; - -const music_module_t music_sdl_module = -{ - music_sdl_devices, - arrlen(music_sdl_devices), - I_SDL_InitMusic, - I_SDL_ShutdownMusic, - I_SDL_SetMusicVolume, - I_SDL_PauseSong, - I_SDL_ResumeSong, - I_SDL_RegisterSong, - I_SDL_UnRegisterSong, - I_SDL_PlaySong, - I_SDL_StopSong, - I_SDL_MusicIsPlaying, - NULL, // Poll -}; - - -#endif // DISABLE_SDL2MIXER diff --git a/games/NXDoom/src/i_sdlsound.c b/games/NXDoom/src/i_sdlsound.c deleted file mode 100644 index 18a51a09d86..00000000000 --- a/games/NXDoom/src/i_sdlsound.c +++ /dev/null @@ -1,1146 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// Copyright(C) 2008 David Flater -// -// 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. -// -// DESCRIPTION: -// System interface for sound. -// - -#include "config.h" - -#include -#include -#include -#include -#include "SDL.h" - -#ifdef HAVE_LIBSAMPLERATE -#include -#endif - -#include "deh_str.h" -#include "i_sound.h" -#include "i_system.h" -#include "i_swap.h" -#include "m_argv.h" -#include "m_misc.h" -#include "w_wad.h" -#include "z_zone.h" - -#include "doomtype.h" - - -int use_libsamplerate = 0; - -// Scale factor used when converting libsamplerate floating point numbers -// to integers. Too high means the sounds can clip; too low means they -// will be too quiet. This is an amount that should avoid clipping most -// of the time: with all the Doom IWAD sound effects, at least. If a PWAD -// is used, clipping might occur. - -float libsamplerate_scale = 0.65f; - - -#ifndef DISABLE_SDL2MIXER - -#include "SDL_mixer.h" - - -#define LOW_PASS_FILTER -//#define DEBUG_DUMP_WAVS -#define NUM_CHANNELS 16 - -typedef struct allocated_sound_s allocated_sound_t; - -struct allocated_sound_s -{ - sfxinfo_t *sfxinfo; - Mix_Chunk chunk; - int use_count; - int pitch; - allocated_sound_t *prev, *next; -}; - -static boolean sound_initialized = false; - -static allocated_sound_t *channels_playing[NUM_CHANNELS]; - -static int mixer_freq; -static Uint16 mixer_format; -static int mixer_channels; -static boolean use_sfx_prefix; -static boolean (*ExpandSoundData)(sfxinfo_t *sfxinfo, - byte *data, - int samplerate, - int length) = NULL; - -// Doubly-linked list of allocated sounds. -// When a sound is played, it is moved to the head, so that the oldest -// sounds not used recently are at the tail. - -static allocated_sound_t *allocated_sounds_head = NULL; -static allocated_sound_t *allocated_sounds_tail = NULL; -static int allocated_sounds_size = 0; - - -// Hook a sound into the linked list at the head. - -static void AllocatedSoundLink(allocated_sound_t *snd) -{ - snd->prev = NULL; - - snd->next = allocated_sounds_head; - allocated_sounds_head = snd; - - if (allocated_sounds_tail == NULL) - { - allocated_sounds_tail = snd; - } - else - { - snd->next->prev = snd; - } -} - -// Unlink a sound from the linked list. - -static void AllocatedSoundUnlink(allocated_sound_t *snd) -{ - if (snd->prev == NULL) - { - allocated_sounds_head = snd->next; - } - else - { - snd->prev->next = snd->next; - } - - if (snd->next == NULL) - { - allocated_sounds_tail = snd->prev; - } - else - { - snd->next->prev = snd->prev; - } -} - -static void FreeAllocatedSound(allocated_sound_t *snd) -{ - // Unlink from linked list. - - AllocatedSoundUnlink(snd); - - // Keep track of the amount of allocated sound data: - - allocated_sounds_size -= snd->chunk.alen; - - free(snd); -} - -// Search from the tail backwards along the allocated sounds list, find -// and free a sound that is not in use, to free up memory. Return true -// for success. - -static boolean FindAndFreeSound(void) -{ - allocated_sound_t *snd; - - snd = allocated_sounds_tail; - - while (snd != NULL) - { - if (snd->use_count == 0) - { - FreeAllocatedSound(snd); - return true; - } - - snd = snd->prev; - } - - // No available sounds to free... - - return false; -} - -// Enforce SFX cache size limit. We are just about to allocate "len" -// bytes on the heap for a new sound effect, so free up some space -// so that we keep allocated_sounds_size < snd_cachesize - -static void ReserveCacheSpace(size_t len) -{ - if (snd_cachesize <= 0) - { - return; - } - - // Keep freeing sound effects that aren't currently being played, - // until there is enough space for the new sound. - - while (allocated_sounds_size + len > snd_cachesize) - { - // Free a sound. If there is nothing more to free, stop. - - if (!FindAndFreeSound()) - { - break; - } - } -} - -// Allocate a block for a new sound effect. - -static allocated_sound_t *AllocateSound(sfxinfo_t *sfxinfo, size_t len) -{ - allocated_sound_t *snd; - - // Keep allocated sounds within the cache size. - - ReserveCacheSpace(len); - - // Allocate the sound structure and data. The data will immediately - // follow the structure, which acts as a header. - - do - { - snd = malloc(sizeof(allocated_sound_t) + len); - - // Out of memory? Try to free an old sound, then loop round - // and try again. - - if (snd == NULL && !FindAndFreeSound()) - { - return NULL; - } - - } while (snd == NULL); - - // Skip past the chunk structure for the audio buffer - - snd->chunk.abuf = (byte *) (snd + 1); - snd->chunk.alen = len; - snd->chunk.allocated = 1; - snd->chunk.volume = MIX_MAX_VOLUME; - snd->pitch = NORM_PITCH; - - snd->sfxinfo = sfxinfo; - snd->use_count = 0; - - // Keep track of how much memory all these cached sounds are using... - - allocated_sounds_size += len; - - AllocatedSoundLink(snd); - - return snd; -} - -// Lock a sound, to indicate that it may not be freed. - -static void LockAllocatedSound(allocated_sound_t *snd) -{ - // Increase use count, to stop the sound being freed. - - ++snd->use_count; - - //printf("++ %s: Use count=%i\n", snd->sfxinfo->name, snd->use_count); - - // When we use a sound, re-link it into the list at the head, so - // that the oldest sounds fall to the end of the list for freeing. - - AllocatedSoundUnlink(snd); - AllocatedSoundLink(snd); -} - -// Unlock a sound to indicate that it may now be freed. - -static void UnlockAllocatedSound(allocated_sound_t *snd) -{ - if (snd->use_count <= 0) - { - I_Error("Sound effect released more times than it was locked..."); - } - - --snd->use_count; - - //printf("-- %s: Use count=%i\n", snd->sfxinfo->name, snd->use_count); -} - -// Search through the list of allocated sounds and return the one that matches -// the supplied sfxinfo entry and pitch level. - -static allocated_sound_t * GetAllocatedSoundBySfxInfoAndPitch(sfxinfo_t *sfxinfo, int pitch) -{ - allocated_sound_t * p = allocated_sounds_head; - - while (p != NULL) - { - if (p->sfxinfo == sfxinfo && p->pitch == pitch) - { - return p; - } - p = p->next; - } - - return NULL; -} - -// Allocate a new sound chunk and pitch-shift an existing sound up-or-down -// into it. - -static allocated_sound_t * PitchShift(allocated_sound_t *insnd, int pitch) -{ - allocated_sound_t * outsnd; - Sint16 *inp, *outp; - Sint16 *srcbuf, *dstbuf; - Uint32 srclen, dstlen; - - srcbuf = (Sint16 *)insnd->chunk.abuf; - srclen = insnd->chunk.alen; - - // determine ratio pitch:NORM_PITCH and apply to srclen, then invert. - // This is an approximation of vanilla behaviour based on measurements - dstlen = (int)((1 + (1 - (float)pitch / NORM_PITCH)) * srclen); - - // ensure that the new buffer is an even length - if ((dstlen % 2) == 0) - { - dstlen++; - } - - outsnd = AllocateSound(insnd->sfxinfo, dstlen); - - if (!outsnd) - { - return NULL; - } - - outsnd->pitch = pitch; - dstbuf = (Sint16 *)outsnd->chunk.abuf; - - // loop over output buffer. find corresponding input cell, copy over - for (outp = dstbuf; outp < dstbuf + dstlen/2; ++outp) - { - inp = srcbuf + (int)((float)(outp - dstbuf) / dstlen * srclen); - *outp = *inp; - } - - return outsnd; -} - -// When a sound stops, check if it is still playing. If it is not, -// we can mark the sound data as CACHE to be freed back for other -// means. - -static void ReleaseSoundOnChannel(int channel) -{ - allocated_sound_t *snd = channels_playing[channel]; - - Mix_HaltChannel(channel); - - if (snd == NULL) - { - return; - } - - channels_playing[channel] = NULL; - - UnlockAllocatedSound(snd); - - // if the sound is a pitch-shift and it's not in use, immediately - // free it - if (snd->pitch != NORM_PITCH && snd->use_count <= 0) - { - FreeAllocatedSound(snd); - } -} - -#ifdef HAVE_LIBSAMPLERATE - -// Returns the conversion mode for libsamplerate to use. - -static int SRC_ConversionMode(void) -{ - switch (use_libsamplerate) - { - // 0 = disabled - - default: - case 0: - return -1; - - // Ascending numbers give higher quality - - case 1: - return SRC_LINEAR; - case 2: - return SRC_ZERO_ORDER_HOLD; - case 3: - return SRC_SINC_FASTEST; - case 4: - return SRC_SINC_MEDIUM_QUALITY; - case 5: - return SRC_SINC_BEST_QUALITY; - } -} - -// libsamplerate-based generic sound expansion function for any sample rate -// unsigned 8 bits --> signed 16 bits -// mono --> stereo -// samplerate --> mixer_freq -// Returns number of clipped samples. -// DWF 2008-02-10 with cleanups by Simon Howard. - -static boolean ExpandSoundData_SRC(sfxinfo_t *sfxinfo, - byte *data, - int samplerate, - int length) -{ - SRC_DATA src_data; - float *data_in; - uint32_t i, abuf_index=0, clipped=0; -// uint32_t alen; - int retn; - int16_t *expanded; - allocated_sound_t *snd; - Mix_Chunk *chunk; - - src_data.input_frames = length; - data_in = malloc(length * sizeof(float)); - src_data.data_in = data_in; - src_data.src_ratio = (double)mixer_freq / samplerate; - - // We include some extra space here in case of rounding-up. - src_data.output_frames = src_data.src_ratio * length + (mixer_freq / 4); - src_data.data_out = malloc(src_data.output_frames * sizeof(float)); - - assert(src_data.data_in != NULL && src_data.data_out != NULL); - - // Convert input data to floats - - for (i=0; ichunk; - expanded = (int16_t *) chunk->abuf; - - // Convert the result back into 16-bit integers. - - for (i=0; i INT16_MAX) - { - cvtval_i = INT16_MAX; - ++clipped; - } - - // Left and right channels - - expanded[abuf_index++] = cvtval_i; - expanded[abuf_index++] = cvtval_i; - } - - free(data_in); - free(src_data.data_out); - - if (clipped > 0) - { - fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", - sfxinfo->name, clipped, - 400.0 * clipped / chunk->alen); - } - - return true; -} - -#endif - -static boolean ConvertibleRatio(int freq1, int freq2) -{ - int ratio; - - if (freq1 > freq2) - { - return ConvertibleRatio(freq2, freq1); - } - else if ((freq2 % freq1) != 0) - { - // Not in a direct ratio - - return false; - } - else - { - // Check the ratio is a power of 2 - - ratio = freq2 / freq1; - - while ((ratio & 1) == 0) - { - ratio = ratio >> 1; - } - - return ratio == 1; - } -} - -#ifdef DEBUG_DUMP_WAVS - -// Debug code to dump resampled sound effects to WAV files for analysis. - -static void WriteWAV(char *filename, byte *data, - uint32_t length, int samplerate) -{ - FILE *wav; - unsigned int i; - unsigned short s; - - wav = M_fopen(filename, "wb"); - - // Header - - fwrite("RIFF", 1, 4, wav); - i = LONG(36 + samplerate); - fwrite(&i, 4, 1, wav); - fwrite("WAVE", 1, 4, wav); - - // Subchunk 1 - - fwrite("fmt ", 1, 4, wav); - i = LONG(16); - fwrite(&i, 4, 1, wav); // Length - s = SHORT(1); - fwrite(&s, 2, 1, wav); // Format (PCM) - s = SHORT(2); - fwrite(&s, 2, 1, wav); // Channels (2=stereo) - i = LONG(samplerate); - fwrite(&i, 4, 1, wav); // Sample rate - i = LONG(samplerate * 2 * 2); - fwrite(&i, 4, 1, wav); // Byte rate (samplerate * stereo * 16 bit) - s = SHORT(2 * 2); - fwrite(&s, 2, 1, wav); // Block align (stereo * 16 bit) - s = SHORT(16); - fwrite(&s, 2, 1, wav); // Bits per sample (16 bit) - - // Data subchunk - - fwrite("data", 1, 4, wav); - i = LONG(length); - fwrite(&i, 4, 1, wav); // Data length - fwrite(data, 1, length, wav); // Data - - fclose(wav); -} - -#endif - -// Generic sound expansion function for any sample rate. -// Returns number of clipped samples (always 0). - -static boolean ExpandSoundData_SDL(sfxinfo_t *sfxinfo, - byte *data, - int samplerate, - int length) -{ - SDL_AudioCVT convertor; - allocated_sound_t *snd; - Mix_Chunk *chunk; - uint32_t expanded_length; - - // Calculate the length of the expanded version of the sample. - - expanded_length = (uint32_t) ((((uint64_t) length) * mixer_freq) / samplerate); - - // Double up twice: 8 -> 16 bit and mono -> stereo - - expanded_length *= 4; - - // Allocate a chunk in which to expand the sound - - snd = AllocateSound(sfxinfo, expanded_length); - - if (snd == NULL) - { - return false; - } - - chunk = &snd->chunk; - - // If we can, use the standard / optimized SDL conversion routines. - - if (samplerate <= mixer_freq - && ConvertibleRatio(samplerate, mixer_freq) - && SDL_BuildAudioCVT(&convertor, - AUDIO_U8, 1, samplerate, - mixer_format, mixer_channels, mixer_freq)) - { - convertor.len = length; - convertor.buf = malloc(convertor.len * convertor.len_mult); - assert(convertor.buf != NULL); - memcpy(convertor.buf, data, length); - - SDL_ConvertAudio(&convertor); - - memcpy(chunk->abuf, convertor.buf, chunk->alen); - free(convertor.buf); - } - else - { - Sint16 *expanded = (Sint16 *) chunk->abuf; - int expanded_length; - int expand_ratio; - int i; - - // Generic expansion if conversion does not work: - // - // SDL's audio conversion only works for rate conversions that are - // powers of 2; if the two formats are not in a direct power of 2 - // ratio, do this naive conversion instead. - - // number of samples in the converted sound - - expanded_length = ((uint64_t) length * mixer_freq) / samplerate; - expand_ratio = (length << 8) / expanded_length; - - for (i=0; i> 8; - - sample = data[src] | (data[src] << 8); - sample -= 32768; - - // expand 8->16 bits, mono->stereo - - expanded[i * 2] = expanded[i * 2 + 1] = sample; - } - -#ifdef LOW_PASS_FILTER - // Perform a low-pass filter on the upscaled sound to filter - // out high-frequency noise from the conversion process. - - { - float rc, dt, alpha; - - // Low-pass filter for cutoff frequency f: - // - // For sampling rate r, dt = 1 / r - // rc = 1 / 2*pi*f - // alpha = dt / (rc + dt) - - // Filter to the half sample rate of the original sound effect - // (maximum frequency, by nyquist) - - dt = 1.0f / mixer_freq; - rc = 1.0f / (3.14f * samplerate); - alpha = dt / (rc + dt); - - // Both channels are processed in parallel, hence [i-2]: - - for (i=2; ilumpnum; - data = W_CacheLumpNum(lumpnum, PU_STATIC); - lumplen = W_LumpLength(lumpnum); - - // Check the header, and ensure this is a valid sound - - if (lumplen < 8 - || data[0] != 0x03 || data[1] != 0x00) - { - // Invalid sound - - return false; - } - - // 16 bit sample rate field, 32 bit length field - - samplerate = (data[3] << 8) | data[2]; - length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; - - // If the header specifies that the length of the sound is greater than - // the length of the lump itself, this is an invalid sound lump - - // We also discard sound lumps that are less than 49 samples long, - // as this is how DMX behaves - although the actual cut-off length - // seems to vary slightly depending on the sample rate. This needs - // further investigation to better understand the correct - // behavior. - - if (length > lumplen - 8 || length <= 48) - { - return false; - } - - // The DMX sound library seems to skip the first 16 and last 16 - // bytes of the lump - reason unknown. - - data += 16; - length -= 32; - - // Sample rate conversion - - if (!ExpandSoundData(sfxinfo, data + 8, samplerate, length)) - { - return false; - } - -#ifdef DEBUG_DUMP_WAVS - { - char filename[16]; - allocated_sound_t * snd; - - M_snprintf(filename, sizeof(filename), "%s.wav", - DEH_String(sfxinfo->name)); - snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, NORM_PITCH); - WriteWAV(filename, snd->chunk.abuf, snd->chunk.alen,mixer_freq); - } -#endif - - // don't need the original lump any more - - W_ReleaseLumpNum(lumpnum); - - return true; -} - -static void GetSfxLumpName(sfxinfo_t *sfx, char *buf, size_t buf_len) -{ - // Linked sfx lumps? Get the lump number for the sound linked to. - - if (sfx->link != NULL) - { - sfx = sfx->link; - } - - // Doom adds a DS* prefix to sound lumps; Heretic and Hexen don't - // do this. - - if (use_sfx_prefix) - { - M_snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name)); - } - else - { - M_StringCopy(buf, DEH_String(sfx->name), buf_len); - } -} - -// Preload all the sound effects - stops nasty ingame freezes - -static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds) -{ - char namebuf[9]; - int i; - - printf("I_SDL_PrecacheSounds: Precaching all sound effects.."); - - for (i=0; i= NUM_CHANNELS) - { - return; - } - - left = ((254 - sep) * vol) / 127; - right = ((sep) * vol) / 127; - - if (left < 0) left = 0; - else if ( left > 255) left = 255; - if (right < 0) right = 0; - else if (right > 255) right = 255; - - Mix_SetPanning(handle, left, right); -} - -// -// Starting a sound means adding it -// to the current list of active sounds -// in the internal channels. -// As the SFX info struct contains -// e.g. a pointer to the raw data, -// it is ignored. -// As our sound handling does not handle -// priority, it is ignored. -// Pitching (that is, increased speed of playback) -// is set, but currently not used by mixing. -// - -static int I_SDL_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch) -{ - allocated_sound_t *snd; - - if (!sound_initialized || channel < 0 || channel >= NUM_CHANNELS) - { - return -1; - } - - // Release a sound effect if there is already one playing - // on this channel - - ReleaseSoundOnChannel(channel); - - // Get the sound data - - if (!LockSound(sfxinfo)) - { - return -1; - } - - snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, pitch); - - if (snd == NULL) - { - allocated_sound_t *newsnd; - // fetch the base sound effect, un-pitch-shifted - snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, NORM_PITCH); - - if (snd == NULL) - { - return -1; - } - - if (snd_pitchshift) - { - newsnd = PitchShift(snd, pitch); - - if (newsnd) - { - LockAllocatedSound(newsnd); - UnlockAllocatedSound(snd); - snd = newsnd; - } - } - } - else - { - LockAllocatedSound(snd); - } - - // play sound - - Mix_PlayChannel(channel, &snd->chunk, 0); - - channels_playing[channel] = snd; - - // set separation, etc. - - I_SDL_UpdateSoundParams(channel, vol, sep); - - return channel; -} - -static void I_SDL_StopSound(int handle) -{ - if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS) - { - return; - } - - // Sound data is no longer needed; release the - // sound data being used for this channel - - ReleaseSoundOnChannel(handle); -} - - -static boolean I_SDL_SoundIsPlaying(int handle) -{ - if (!sound_initialized || handle < 0 || handle >= NUM_CHANNELS) - { - return false; - } - - return Mix_Playing(handle); -} - -// -// Periodically called to update the sound system -// - -static void I_SDL_UpdateSound(void) -{ - int i; - - // Check all channels to see if a sound has finished - - for (i=0; i limit) - { - return (1 << n); - } - } - - // Should never happen? - - return 1024; -} - -static boolean I_SDL_InitSound(GameMission_t mission) -{ - int i; - - use_sfx_prefix = (mission == doom || mission == strife); - - // No sounds yet - for (i=0; i #include @@ -27,514 +34,484 @@ #include "m_argv.h" #include "m_config.h" -#ifndef DISABLE_SDL2MIXER +/**************************************************************************** + * Public Data + ****************************************************************************/ -#include "SDL_mixer.h" - -#endif // DISABLE_SDL2MIXER - - -// Sound sample rate to use for digital output (Hz) +/* Sound sample rate to use for digital output (Hz) */ int snd_samplerate = 44100; -// Maximum number of bytes to dedicate to allocated sound effects. -// (Default: 64MB) +/* Maximum number of bytes to dedicate to allocated sound effects. + * (Default: 64MB) + */ int snd_cachesize = 64 * 1024 * 1024; -// Config variable that controls the sound buffer size. -// We default to 28ms (1000 / 35fps = 1 buffer per tic). +/* Config variable that controls the sound buffer size. + * We default to 28ms (1000 / 35fps = 1 buffer per tic). + */ int snd_maxslicetime_ms = 28; -// External command to invoke to play back music. +/* External command to invoke to play back music. */ char *snd_musiccmd = ""; -// Whether to vary the pitch of sound effects -// Each game will set the default differently +/* Whether to vary the pitch of sound effects + * Each game will set the default differently + */ int snd_pitchshift = -1; int snd_musicdevice = SNDDEVICE_SB; int snd_sfxdevice = SNDDEVICE_SB; -// Low-level sound and music modules we are using +/* Scale factor used when converting libsamplerate floating point numbers + * to integers. Too high means the sounds can clip; too low means they + * will be too quiet. This is an amount that should avoid clipping most + * of the time: with all the Doom IWAD sound effects, at least. If a PWAD + * is used, clipping might occur. + * + * NOTE: originally from i_sdlsound.c + */ + +float libsamplerate_scale = 0.65f; +int use_libsamplerate = 0; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Low-level sound and music modules we are using */ + static const sound_module_t *sound_module; static const music_module_t *music_module; -// If true, the music pack module was successfully initialized. +/* If true, the music pack module was successfully initialized. */ + static boolean music_packs_active = false; -// This is either equal to music_module or &music_pack_module, -// depending on whether the current track is substituted. -static const music_module_t *active_music_module; +/* This is either equal to music_module or &music_pack_module, + * depending on whether the current track is substituted. + */ +static const music_module_t *active_music_module; -// DOS-specific options: These are unused but should be maintained -// so that the config file can be shared between chocolate -// doom and doom.exe +/* DOS-specific options: These are unused but should be maintained + * so that the config file can be shared between chocolate + * doom and doom.exe + */ static int snd_sbport = 0; static int snd_sbirq = 0; static int snd_sbdma = 0; static int snd_mport = 0; -// Compiled-in sound modules: +/* Compiled-in sound modules: */ static const sound_module_t *sound_modules[] = { -#ifndef DISABLE_SDL2MIXER - &sound_sdl_module, -#endif // DISABLE_SDL2MIXER - &sound_pcsound_module, - NULL, + &sound_pcsound_module, + NULL, }; -// Compiled-in music modules: +/* Compiled-in music modules: */ static const music_module_t *music_modules[] = { -#ifdef _WIN32 - &music_win_module, -#endif -#ifdef HAVE_FLUIDSYNTH - &music_fl_module, -#endif // HAVE_FLUIDSYNTH -#ifndef DISABLE_SDL2MIXER - &music_sdl_module, -#endif // DISABLE_SDL2MIXER +#if 0 &music_opl_module, +#endif NULL, }; -// Check if a sound device is in the given list of devices +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Check if a sound device is in the given list of devices */ -static boolean SndDeviceInList(snddevice_t device, const snddevice_t *list, - int len) +static boolean snd_device_in_list(snddevice_t device, + const snddevice_t *list, int len) { - int i; + int i; - for (i=0; isound_devices, - sound_modules[i]->num_sound_devices)) + if (snd_device_in_list(snd_sfxdevice, sound_modules[i]->sound_devices, + sound_modules[i]->num_sound_devices)) { - // Initialize the module + /* initialize the module */ - if (sound_modules[i]->Init(mission)) + if (sound_modules[i]->init(mission)) { - sound_module = sound_modules[i]; - return; + sound_module = sound_modules[i]; + return; } } } } -// Initialize music according to snd_musicdevice. +/* initialize music according to snd_musicdevice. */ -static void InitMusicModule(void) +static void init_music_module(void) { - int i; + int i; - music_module = NULL; + music_module = NULL; - for (i=0; music_modules[i] != NULL; ++i) + for (i = 0; music_modules[i] != NULL; ++i) { - // Is the music device in the list of devices supported - // by this module? + /* Is the music device in the list of devices supported + * by this module? + */ - if (SndDeviceInList(snd_musicdevice, - music_modules[i]->sound_devices, - music_modules[i]->num_sound_devices)) + if (snd_device_in_list(snd_musicdevice, + music_modules[i]->sound_devices, + music_modules[i]->num_sound_devices)) { - #ifdef _WIN32 - // Skip the native Windows MIDI module if using Timidity. + /* initialize the module */ - if (strcmp(timidity_cfg_path, "") && - music_modules[i] == &music_win_module) + if (music_modules[i]->init()) { - continue; + music_module = music_modules[i]; + return; } - #endif + } + } +} - // Initialize the module +static void check_volume_separation(int *vol, int *sep) +{ + if (*sep < 0) + { + *sep = 0; + } + else if (*sep > 254) + { + *sep = 254; + } - if (music_modules[i]->Init()) - { - music_module = music_modules[i]; - return; - } - } + if (*vol < 0) + { + *vol = 0; + } + else if (*vol > 127) + { + *vol = 127; } } -// -// Initializes sound stuff, including volume -// Sets channels, SFX and music volume, -// allocates channel buffer, sets S_sfx lookup. -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void I_InitSound(GameMission_t mission) +/* initializes sound stuff, including volume + * Sets channels, SFX and music volume, allocates channel buffer, sets s_sfx + * lookup. + */ + +void i_init_sound(gamemission_t mission) { - boolean nosound, nosfx, nomusic, nomusicpacks; + boolean nosound, nosfx, nomusic, nomusicpacks; + + /* @vanilla + * + * Disable all sound output. + */ - //! - // @vanilla - // - // Disable all sound output. - // + nosound = m_check_parm("-nosound") > 0; - nosound = M_CheckParm("-nosound") > 0; + /* @vanilla + * + * Disable sound effects. + */ - //! - // @vanilla - // - // Disable sound effects. - // + nosfx = m_check_parm("-nosfx") > 0; - nosfx = M_CheckParm("-nosfx") > 0; + /* @vanilla + * + * Disable music. + */ - //! - // @vanilla - // - // Disable music. - // + nomusic = m_check_parm("-nomusic") > 0; - nomusic = M_CheckParm("-nomusic") > 0; + /* Disable substitution music packs. */ - //! - // - // Disable substitution music packs. - // + nomusicpacks = m_parm_exists("-nomusicpacks"); - nomusicpacks = M_ParmExists("-nomusicpacks"); + /* Auto configure the music pack directory. */ - // Auto configure the music pack directory. - M_SetMusicPackDir(); + m_set_music_pack_dir(); - // Initialize the sound and music subsystems. + /* initialize the sound and music subsystems. */ - if (!nosound && !screensaver_mode) + if (!nosound && !screensaver_mode) { - // This is kind of a hack. If native MIDI is enabled, set up - // the TIMIDITY_CFG environment variable here before SDL_mixer - // is opened. + /* This is kind of a hack. If native MIDI is enabled, set up + * the TIMIDITY_CFG environment variable here before SDL_mixer + * is opened. + */ - if (!nomusic - && (snd_musicdevice == SNDDEVICE_GENMIDI - || snd_musicdevice == SNDDEVICE_GUS)) + if (!nomusic && (snd_musicdevice == SNDDEVICE_GENMIDI || + snd_musicdevice == SNDDEVICE_GUS)) { - I_InitTimidityConfig(); + i_init_timidity_config(); } - if (!nosfx) + if (!nosfx) { - InitSfxModule(mission); + init_sfx_module(mission); } - if (!nomusic) + if (!nomusic) { - InitMusicModule(); - active_music_module = music_module; + init_music_module(); + active_music_module = music_module; } - // We may also have substitute MIDIs we can load. - if (!nomusicpacks && music_module != NULL) + /* We may also have substitute MIDIs we can load. */ + + if (!nomusicpacks && music_module != NULL) { - music_packs_active = music_pack_module.Init(); + music_packs_active = music_pack_module.init(); } } } -void I_ShutdownSound(void) +void i_shutdown_sound(void) { - if (sound_module != NULL) + if (sound_module != NULL) { - sound_module->Shutdown(); + sound_module->shutdown(); } - if (music_packs_active) + if (music_packs_active) { - music_pack_module.Shutdown(); + music_pack_module.shutdown(); } - if (music_module != NULL) - { - music_module->Shutdown(); - } -} - -int I_GetSfxLumpNum(sfxinfo_t *sfxinfo) -{ - if (sound_module != NULL) - { - return sound_module->GetSfxLumpNum(sfxinfo); - } - else + if (music_module != NULL) { - return 0; + music_module->shutdown(); } } -void I_UpdateSound(void) +int i_get_sfx_lumpnum(sfxinfo_t *sfxinfo) { - if (sound_module != NULL) + if (sound_module != NULL) { - sound_module->Update(); + return sound_module->get_sfx_lumpnum(sfxinfo); } - - if (active_music_module != NULL && active_music_module->Poll != NULL) + else { - active_music_module->Poll(); + return 0; } } -static void CheckVolumeSeparation(int *vol, int *sep) +void i_update_sound(void) { - if (*sep < 0) + if (sound_module != NULL) { - *sep = 0; - } - else if (*sep > 254) - { - *sep = 254; + sound_module->update(); } - if (*vol < 0) - { - *vol = 0; - } - else if (*vol > 127) + if (active_music_module != NULL && active_music_module->poll != NULL) { - *vol = 127; + active_music_module->poll(); } } -void I_UpdateSoundParams(int channel, int vol, int sep) +void i_update_sound_params(int channel, int vol, int sep) { - if (sound_module != NULL) + if (sound_module != NULL) { - CheckVolumeSeparation(&vol, &sep); - sound_module->UpdateSoundParams(channel, vol, sep); + check_volume_separation(&vol, &sep); + sound_module->update_sound_params(channel, vol, sep); } } -int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch) +int i_start_sound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, + int pitch) { - if (sound_module != NULL) + if (sound_module != NULL) { - CheckVolumeSeparation(&vol, &sep); - return sound_module->StartSound(sfxinfo, channel, vol, sep, pitch); + check_volume_separation(&vol, &sep); + return sound_module->start_sound(sfxinfo, channel, vol, sep, pitch); } - else + else { - return 0; + return 0; } } -void I_StopSound(int channel) +void i_stop_sound(int channel) { - if (sound_module != NULL) + if (sound_module != NULL) { - sound_module->StopSound(channel); + sound_module->stop_sound(channel); } } -boolean I_SoundIsPlaying(int channel) +boolean i_sound_playing(int channel) { - if (sound_module != NULL) + if (sound_module != NULL) { - return sound_module->SoundIsPlaying(channel); + return sound_module->sound_is_playing(channel); } - else + else { - return false; + return false; } } -void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds) +void i_precache_sounds(sfxinfo_t *sounds, int num_sounds) { - if (sound_module != NULL && sound_module->CacheSounds != NULL) + if (sound_module != NULL && sound_module->cache_sounds != NULL) { - sound_module->CacheSounds(sounds, num_sounds); + sound_module->cache_sounds(sounds, num_sounds); } } -void I_InitMusic(void) +void i_init_music(void) { } -void I_ShutdownMusic(void) +void i_shutdown_music(void) { - } -void I_SetMusicVolume(int volume) +void i_set_music_volume(int volume) { - if (music_module != NULL) + if (music_module != NULL) { - music_module->SetMusicVolume(volume); + music_module->set_music_volume(volume); - if (music_packs_active && music_module != &music_pack_module) + if (music_packs_active && music_module != &music_pack_module) { - music_pack_module.SetMusicVolume(volume); + music_pack_module.set_music_volume(volume); } } } -void I_PauseSong(void) +void i_pause_song(void) { - if (active_music_module != NULL) + if (active_music_module != NULL) { - active_music_module->PauseMusic(); + active_music_module->pause_music(); } } -void I_ResumeSong(void) +void i_resume_song(void) { - if (active_music_module != NULL) + if (active_music_module != NULL) { - active_music_module->ResumeMusic(); + active_music_module->resume_music(); } } -void *I_RegisterSong(void *data, int len) +void *i_register_song(void *data, int len) { - // If the music pack module is active, check to see if there is a - // valid substitution for this track. If there is, we set the - // active_music_module pointer to the music pack module for the - // duration of this particular track. - if (music_packs_active) + /* If the music pack module is active, check to see if there is a + * valid substitution for this track. If there is, we set the + * active_music_module pointer to the music pack module for the + * duration of this particular track. + */ + + if (music_packs_active) { - void *handle; + void *handle; - handle = music_pack_module.RegisterSong(data, len); - if (handle != NULL) + handle = music_pack_module.register_song(data, len); + if (handle != NULL) { - active_music_module = &music_pack_module; - return handle; + active_music_module = &music_pack_module; + return handle; } } - // No substitution for this track, so use the main module. - active_music_module = music_module; - if (active_music_module != NULL) - { - return active_music_module->RegisterSong(data, len); - } - else + /* No substitution for this track, so use the main module. */ + + active_music_module = music_module; + if (active_music_module != NULL) { - return NULL; + return active_music_module->register_song(data, len); } -} - -void I_UnRegisterSong(void *handle) -{ - if (active_music_module != NULL) + else { - active_music_module->UnRegisterSong(handle); + return NULL; } } -void I_PlaySong(void *handle, boolean looping) +void i_unregister_song(void *handle) { - if (active_music_module != NULL) + if (active_music_module != NULL) { - active_music_module->PlaySong(handle, looping); + active_music_module->unregister_song(handle); } } -void I_StopSong(void) +void i_play_song(void *handle, boolean looping) { - if (active_music_module != NULL) + if (active_music_module != NULL) { - active_music_module->StopSong(); + active_music_module->play_song(handle, looping); } } -boolean I_MusicIsPlaying(void) +void i_stop_song(void) { - if (active_music_module != NULL) - { - return active_music_module->MusicIsPlaying(); - } - else + if (active_music_module != NULL) { - return false; + active_music_module->stop_song(); } } -void I_BindSoundVariables(void) +void i_bind_sound_variables(void) { - M_BindIntVariable("snd_musicdevice", &snd_musicdevice); - M_BindIntVariable("snd_sfxdevice", &snd_sfxdevice); - M_BindIntVariable("snd_sbport", &snd_sbport); - M_BindIntVariable("snd_sbirq", &snd_sbirq); - M_BindIntVariable("snd_sbdma", &snd_sbdma); - M_BindIntVariable("snd_mport", &snd_mport); - M_BindIntVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms); - M_BindStringVariable("snd_musiccmd", &snd_musiccmd); - M_BindStringVariable("snd_dmxoption", &snd_dmxoption); - M_BindIntVariable("snd_samplerate", &snd_samplerate); - M_BindIntVariable("snd_cachesize", &snd_cachesize); - M_BindIntVariable("opl_io_port", &opl_io_port); - M_BindIntVariable("snd_pitchshift", &snd_pitchshift); - - M_BindStringVariable("music_pack_path", &music_pack_path); - M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path); - M_BindStringVariable("gus_patch_path", &gus_patch_path); - M_BindIntVariable("gus_ram_kb", &gus_ram_kb); -#ifdef _WIN32 - M_BindStringVariable("winmm_midi_device", &winmm_midi_device); - M_BindIntVariable("winmm_complevel", &winmm_complevel); - M_BindIntVariable("winmm_reset_type", &winmm_reset_type); - M_BindIntVariable("winmm_reset_delay", &winmm_reset_delay); -#endif - -#ifdef HAVE_FLUIDSYNTH - M_BindIntVariable("fsynth_chorus_active", &fsynth_chorus_active); - M_BindFloatVariable("fsynth_chorus_depth", &fsynth_chorus_depth); - M_BindFloatVariable("fsynth_chorus_level", &fsynth_chorus_level); - M_BindIntVariable("fsynth_chorus_nr", &fsynth_chorus_nr); - M_BindFloatVariable("fsynth_chorus_speed", &fsynth_chorus_speed); - M_BindStringVariable("fsynth_midibankselect", &fsynth_midibankselect); - M_BindIntVariable("fsynth_polyphony", &fsynth_polyphony); - M_BindIntVariable("fsynth_reverb_active", &fsynth_reverb_active); - M_BindFloatVariable("fsynth_reverb_damp", &fsynth_reverb_damp); - M_BindFloatVariable("fsynth_reverb_level", &fsynth_reverb_level); - M_BindFloatVariable("fsynth_reverb_roomsize", &fsynth_reverb_roomsize); - M_BindFloatVariable("fsynth_reverb_width", &fsynth_reverb_width); - M_BindFloatVariable("fsynth_gain", &fsynth_gain); - M_BindStringVariable("fsynth_sf_path", &fsynth_sf_path); -#endif // HAVE_FLUIDSYNTH - - M_BindIntVariable("use_libsamplerate", &use_libsamplerate); - M_BindFloatVariable("libsamplerate_scale", &libsamplerate_scale); + m_bind_int_variable("snd_musicdevice", &snd_musicdevice); + m_bind_int_variable("snd_sfxdevice", &snd_sfxdevice); + m_bind_int_variable("snd_sbport", &snd_sbport); + m_bind_int_variable("snd_sbirq", &snd_sbirq); + m_bind_int_variable("snd_sbdma", &snd_sbdma); + m_bind_int_variable("snd_mport", &snd_mport); + m_bind_int_variable("snd_maxslicetime_ms", &snd_maxslicetime_ms); + m_bind_string_variable("snd_musiccmd", &snd_musiccmd); + m_bind_int_variable("snd_samplerate", &snd_samplerate); + m_bind_int_variable("snd_cachesize", &snd_cachesize); + m_bind_int_variable("snd_pitchshift", &snd_pitchshift); + + m_bind_string_variable("music_pack_path", &music_pack_path); + m_bind_string_variable("timidity_cfg_path", &timidity_cfg_path); + m_bind_string_variable("gus_patch_path", &gus_patch_path); + m_bind_int_variable("gus_ram_kb", &gus_ram_kb); + + m_bind_int_variable("use_libsamplerate", &use_libsamplerate); + m_bind_float_variable("libsamplerate_scale", &libsamplerate_scale); } - diff --git a/games/NXDoom/src/i_sound.h b/games/NXDoom/src/i_sound.h index 376e1bb9c81..d1ad8d8ebbd 100644 --- a/games/NXDoom/src/i_sound.h +++ b/games/NXDoom/src/i_sound.h @@ -1,233 +1,260 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The not so system specific sound interface. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_sound.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * The not so system specific sound interface. + * + ****************************************************************************/ #ifndef __I_SOUND__ #define __I_SOUND__ -#include "doomtype.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_mode.h" +#include "doomtype.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* so that the individual game logic and sound driver code agree */ -// so that the individual game logic and sound driver code agree #define NORM_PITCH 127 -// -// SoundFX struct. -// -typedef struct sfxinfo_struct sfxinfo_t; +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* SoundFX struct. */ + +typedef struct sfxinfo_struct sfxinfo_t; struct sfxinfo_struct { - // tag name, used for hexen. - const char *tagname; + /* tag name, used for hexen. */ + + const char *tagname; + + /* lump name. If we are running with use_sfx_prefix=true, a + * 'DS' (or 'DP' for PC speaker sounds) is prepended to this. + */ - // lump name. If we are running with use_sfx_prefix=true, a - // 'DS' (or 'DP' for PC speaker sounds) is prepended to this. + char name[9]; - char name[9]; + /* Sfx priority */ - // Sfx priority - int priority; + int priority; - // referenced sound if a link - sfxinfo_t *link; + /* referenced sound if a link */ - // pitch if a link (Doom), whether to pitch-shift (Hexen) - int pitch; + sfxinfo_t *link; - // volume if a link - int volume; + /* pitch if a link (Doom), whether to pitch-shift (Hexen) */ - // this is checked every second to see if sound - // can be thrown out (if 0, then decrement, if -1, - // then throw out, if > 0, then it is in use) - int usefulness; + int pitch; - // lump number of sfx - int lumpnum; + /* volume if a link */ - // Maximum number of channels that the sound can be played on - // (Heretic) - int numchannels; + int volume; - // data used by the low level code - void *driver_data; + /* this is checked every second to see if sound + * can be thrown out (if 0, then decrement, if -1, + * then throw out, if > 0, then it is in use) + */ + + int usefulness; + + /* lump number of sfx */ + + int lumpnum; + + /* Maximum number of channels that the sound can be played on + * (Heretic) + */ + + int numchannels; + + /* data used by the low level code */ + + void *driver_data; }; -// -// MusicInfo struct. -// +/* MusicInfo struct. */ + typedef struct { - // up to 6-character name - const char *name; + /* up to 6-character name */ + + const char *name; - // lump number of music - int lumpnum; + /* lump number of music */ - // music data - void *data; + int lumpnum; - // music handle once registered - void *handle; + /* music data */ + void *data; + + /* music handle once registered */ + + void *handle; } musicinfo_t; -typedef enum +typedef enum { - SNDDEVICE_NONE = 0, - SNDDEVICE_PCSPEAKER = 1, - SNDDEVICE_ADLIB = 2, - SNDDEVICE_SB = 3, - SNDDEVICE_PAS = 4, - SNDDEVICE_GUS = 5, - SNDDEVICE_WAVEBLASTER = 6, - SNDDEVICE_SOUNDCANVAS = 7, - SNDDEVICE_GENMIDI = 8, - SNDDEVICE_AWE32 = 9, - SNDDEVICE_CD = 10, - SNDDEVICE_FSYNTH = 11, + SNDDEVICE_NONE = 0, + SNDDEVICE_PCSPEAKER = 1, + SNDDEVICE_ADLIB = 2, + SNDDEVICE_SB = 3, + SNDDEVICE_PAS = 4, + SNDDEVICE_GUS = 5, + SNDDEVICE_WAVEBLASTER = 6, + SNDDEVICE_SOUNDCANVAS = 7, + SNDDEVICE_GENMIDI = 8, + SNDDEVICE_AWE32 = 9, + SNDDEVICE_CD = 10, + SNDDEVICE_FSYNTH = 11, } snddevice_t; -// Interface for sound modules +/* Interface for sound modules */ typedef struct { - // List of sound devices that this sound module is used for. - - const snddevice_t *sound_devices; - int num_sound_devices; + /* List of sound devices that this sound module is used for. */ - // Initialise sound module - // Returns true if successfully initialised + const snddevice_t *sound_devices; + int num_sound_devices; - boolean (*Init)(GameMission_t mission); + /* initialise sound module + * Returns true if successfully initialised + */ - // Shutdown sound module + boolean (*init)(gamemission_t mission); - void (*Shutdown)(void); + /* shutdown sound module */ - // Returns the lump index of the given sound. + void (*shutdown)(void); - int (*GetSfxLumpNum)(sfxinfo_t *sfxinfo); + /* Returns the lump index of the given sound. */ - // Called periodically to update the subsystem. + int (*get_sfx_lumpnum)(sfxinfo_t *sfxinfo); - void (*Update)(void); + /* Called periodically to update the subsystem. */ - // Update the sound settings on the given channel. + void (*update)(void); - void (*UpdateSoundParams)(int channel, int vol, int sep); + /* Update the sound settings on the given channel. */ - // Start a sound on a given channel. Returns the channel id - // or -1 on failure. + void (*update_sound_params)(int channel, int vol, int sep); - int (*StartSound)(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch); + /* Start a sound on a given channel. Returns the channel id + * or -1 on failure. + */ - // Stop the sound playing on the given channel. + int (*start_sound)(sfxinfo_t *sfxinfo, int channel, int vol, int sep, + int pitch); - void (*StopSound)(int channel); + /* Stop the sound playing on the given channel. */ - // Query if a sound is playing on the given channel + void (*stop_sound)(int channel); - boolean (*SoundIsPlaying)(int channel); + /* Query if a sound is playing on the given channel */ - // Called on startup to precache sound effects (if necessary) + boolean (*sound_is_playing)(int channel); - void (*CacheSounds)(sfxinfo_t *sounds, int num_sounds); + /* Called on startup to precache sound effects (if necessary) */ + void (*cache_sounds)(sfxinfo_t *sounds, int num_sounds); } sound_module_t; -void I_InitSound(GameMission_t mission); -void I_ShutdownSound(void); -int I_GetSfxLumpNum(sfxinfo_t *sfxinfo); -void I_UpdateSound(void); -void I_UpdateSoundParams(int channel, int vol, int sep); -int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch); -void I_StopSound(int channel); -boolean I_SoundIsPlaying(int channel); -void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds); - -// Interface for music modules +/* Interface for music modules */ typedef struct { - // List of sound devices that this music module is used for. + /* List of sound devices that this music module is used for. */ - const snddevice_t *sound_devices; - int num_sound_devices; + const snddevice_t *sound_devices; + int num_sound_devices; - // Initialise the music subsystem + /* initialise the music subsystem */ - boolean (*Init)(void); + boolean (*init)(void); - // Shutdown the music subsystem + /* shutdown the music subsystem */ - void (*Shutdown)(void); + void (*shutdown)(void); - // Set music volume - range 0-127 + /* Set music volume - range 0-127 */ - void (*SetMusicVolume)(int volume); + void (*set_music_volume)(int volume); - // Pause music + /* Pause music */ - void (*PauseMusic)(void); + void (*pause_music)(void); - // Un-pause music + /* Un-pause music */ - void (*ResumeMusic)(void); + void (*resume_music)(void); - // Register a song handle from data - // Returns a handle that can be used to play the song + /* Register a song handle from data + * Returns a handle that can be used to play the song + */ - void *(*RegisterSong)(void *data, int len); + void *(*register_song)(void *data, int len); - // Un-register (free) song data + /* Un-register (free) song data */ - void (*UnRegisterSong)(void *handle); + void (*unregister_song)(void *handle); - // Play the song + /* Play the song */ - void (*PlaySong)(void *handle, boolean looping); + void (*play_song)(void *handle, boolean looping); - // Stop playing the current song. + /* Stop playing the current song. */ - void (*StopSong)(void); + void (*stop_song)(void); - // Query if music is playing. + /* Query if music is playing. */ - boolean (*MusicIsPlaying)(void); + boolean (*music_is_playing)(void); - // Invoked periodically to poll. + /* Invoked periodically to poll. */ - void (*Poll)(void); + void (*poll)(void); } music_module_t; -void I_InitMusic(void); -void I_ShutdownMusic(void); -void I_SetMusicVolume(int volume); -void I_PauseSong(void); -void I_ResumeSong(void); -void *I_RegisterSong(void *data, int len); -void I_UnRegisterSong(void *handle); -void I_PlaySong(void *handle, boolean looping); -void I_StopSong(void); -boolean I_MusicIsPlaying(void); +#if 0 +/* DMX version to emulate for OPL emulation: */ + +typedef enum +{ + opl_doom1_1_666, /* Doom 1 v1.666 */ + opl_doom2_1_666, /* Doom 2 v1.666, Hexen, Heretic */ + opl_doom_1_9 /* Doom v1.9, Strife */ +} opl_driver_ver_t; +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ extern int snd_sfxdevice; extern int snd_musicdevice; @@ -236,65 +263,54 @@ extern int snd_cachesize; extern int snd_maxslicetime_ms; extern char *snd_musiccmd; extern int snd_pitchshift; -extern char *snd_dmxoption; extern int use_libsamplerate; extern float libsamplerate_scale; -void I_BindSoundVariables(void); - -// DMX version to emulate for OPL emulation: -typedef enum { - opl_doom1_1_666, // Doom 1 v1.666 - opl_doom2_1_666, // Doom 2 v1.666, Hexen, Heretic - opl_doom_1_9 // Doom v1.9, Strife -} opl_driver_ver_t; - -void I_SetOPLDriverVer(opl_driver_ver_t ver); -void I_OPL_DevMessages(char *, size_t); - -// Sound modules - -void I_InitTimidityConfig(void); extern const sound_module_t sound_sdl_module; extern const sound_module_t sound_pcsound_module; extern const music_module_t music_sdl_module; -extern const music_module_t music_opl_module; extern const music_module_t music_pack_module; -extern const music_module_t music_win_module; extern const music_module_t music_fl_module; -// For OPL module: - -extern int opl_io_port; - -// For native music module: +/* For native music module: */ extern char *music_pack_path; extern char *timidity_cfg_path; -#ifdef _WIN32 -extern char *winmm_midi_device; -extern int winmm_complevel; -extern int winmm_reset_type; -extern int winmm_reset_delay; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void i_init_sound(gamemission_t mission); +void i_shutdown_sound(void); +int i_get_sfx_lumpnum(sfxinfo_t *sfxinfo); +void i_update_sound(void); +void i_update_sound_params(int channel, int vol, int sep); +int i_start_sound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, + int pitch); +void i_stop_sound(int channel); +boolean i_sound_playing(int channel); +void i_precache_sounds(sfxinfo_t *sounds, int num_sounds); + +void i_init_music(void); +void i_shutdown_music(void); +void i_set_music_volume(int volume); +void i_pause_song(void); +void i_resume_song(void); +void *i_register_song(void *data, int len); +void i_unregister_song(void *handle); +void i_play_song(void *handle, boolean looping); +void i_stop_song(void); + +void i_bind_sound_variables(void); + +#if 0 +void i_set_opl_driver_ver(opl_driver_ver_t ver); +void i_opl_dev_messages(char *, size_t); #endif -// For FluidSynth module: - -#ifdef HAVE_FLUIDSYNTH -extern char *fsynth_sf_path; -extern int fsynth_chorus_active; -extern float fsynth_chorus_depth; -extern float fsynth_chorus_level; -extern int fsynth_chorus_nr; -extern float fsynth_chorus_speed; -extern char *fsynth_midibankselect; -extern int fsynth_polyphony; -extern int fsynth_reverb_active; -extern float fsynth_reverb_damp; -extern float fsynth_reverb_level; -extern float fsynth_reverb_roomsize; -extern float fsynth_reverb_width; -extern float fsynth_gain; -#endif // HAVE_FLUIDSYNTH +/* Sound modules */ -#endif +void i_init_timidity_config(void); + +#endif /* __I_SOUND__ */ diff --git a/games/NXDoom/src/i_swap.h b/games/NXDoom/src/i_swap.h index 3dee8e3f685..72b64236f4d 100644 --- a/games/NXDoom/src/i_swap.h +++ b/games/NXDoom/src/i_swap.h @@ -1,43 +1,54 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Endianess handling, swapping 16bit and 32bit. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_swap.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Endianness handling, swapping 16bit and 32bit. + * + ****************************************************************************/ #ifndef __I_SWAP__ #define __I_SWAP__ -#include "SDL_endian.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ -// Endianess handling. -// WAD files are stored little endian. +#include -// Just use SDL's endianness swapping functions. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// These are deliberately cast to signed values; this is the behaviour -// of the macros in the original source and some code relies on it. +/* Endianness handling. + * WAD files are stored little endian. + */ -#define SHORT(x) ((signed short) SDL_SwapLE16(x)) -#define LONG(x) ((signed int) SDL_SwapLE32(x)) +/* These are deliberately cast to signed values; this is the behaviour + * of the macros in the original source and some code relies on it. + */ -// Defines for checking the endianness of the system. +#define SHORT(x) ((signed short)le16toh(x)) +#define LONG(x) ((signed int)le32toh(x)) -#if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define SYS_BIG_ENDIAN -#endif +/* Defines for checking the endianness of the system. */ +#if BYTE_ORDER == BIG_ENDIAN +#define SYS_BIG_ENDIAN #endif +#endif /* __I_SWAP__ */ diff --git a/games/NXDoom/src/i_system.c b/games/NXDoom/src/i_system.c index dba359035ce..b3867e0add9 100644 --- a/games/NXDoom/src/i_system.c +++ b/games/NXDoom/src/i_system.c @@ -1,470 +1,482 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// +/**************************************************************************** + * apps/games/NXDoom/src/i_system.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - - -#include +#include #include +#include #include - -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#else #include -#endif - -#include "SDL.h" #include "config.h" #include "deh_str.h" #include "doomtype.h" -#include "m_argv.h" -#include "m_config.h" -#include "m_misc.h" #include "i_joystick.h" #include "i_sound.h" #include "i_timer.h" #include "i_video.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_misc.h" #include "i_system.h" #include "w_wad.h" #include "z_zone.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define DEFAULT_RAM 16 /* MiB */ -#define MIN_RAM 4 /* MiB */ +#define MIN_RAM 4 /* MiB */ + +#define DOS_MEM_DUMP_SIZE 10 +/**************************************************************************** + * Private Types + ****************************************************************************/ typedef struct atexit_listentry_s atexit_listentry_t; struct atexit_listentry_s { - atexit_func_t func; - boolean run_on_error; - atexit_listentry_t *next; + atexit_func_t func; + boolean run_on_error; + atexit_listentry_t *next; }; +/**************************************************************************** + * Private Data + ****************************************************************************/ + static atexit_listentry_t *exit_funcs = NULL; -void I_AtExit(atexit_func_t func, boolean run_on_error) +static boolean already_quitting = false; + +/* Read Access Violation emulation. + * + * From PrBoom+, by entryway. + */ + +/* C:\>debug + * -d 0:0 + * + * DOS 6.22: + * 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) + * DOS 7.1: + * 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) + * Win98: + * 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) + * DOSBox under XP: + * 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) + */ + +static const unsigned char mem_dump_dos622[DOS_MEM_DUMP_SIZE] = { - atexit_listentry_t *entry; + 0x57, 0x92, 0x19, 0x00, 0xf4, 0x06, 0x70, 0x00, 0x16, 0x00, +}; - entry = malloc(sizeof(*entry)); +static const unsigned char mem_dump_win98[DOS_MEM_DUMP_SIZE] = +{ + 0x9e, 0x0f, 0xc9, 0x00, 0x65, 0x04, 0x70, 0x00, 0x16, 0x00, +}; - entry->func = func; - entry->run_on_error = run_on_error; - entry->next = exit_funcs; - exit_funcs = entry; -} +static const unsigned char mem_dump_dosbox[DOS_MEM_DUMP_SIZE] = +{ + 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, +}; -// Tactile feedback function, probably used for the Logitech Cyberman +static unsigned char mem_dump_custom[DOS_MEM_DUMP_SIZE]; -void I_Tactile(int on, int off, int total) -{ -} +static const unsigned char *dos_mem_dump = mem_dump_dos622; -// Zone memory auto-allocation function that allocates the zone size -// by trying progressively smaller zone sizes until one is found that -// works. +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static byte *AutoAllocMemory(int *size, int default_ram, int min_ram) +/* Zone memory auto-allocation function that allocates the zone size + * by trying progressively smaller zone sizes until one is found that + * works. + */ + +static byte *auto_alloc_memory(int *size, int default_ram, int min_ram) { - byte *zonemem; + byte *zonemem; - // Allocate the zone memory. This loop tries progressively smaller - // zone sizes until a size is found that can be allocated. - // If we used the -mb command line parameter, only the parameter - // provided is accepted. + /* Allocate the zone memory. This loop tries progressively smaller + * zone sizes until a size is found that can be allocated. + * If we used the -mb command line parameter, only the parameter + * provided is accepted. + */ - zonemem = NULL; + zonemem = NULL; - while (zonemem == NULL) + while (zonemem == NULL) { - // We need a reasonable minimum amount of RAM to start. + /* We need a reasonable minimum amount of RAM to start. */ - if (default_ram < min_ram) + if (default_ram < min_ram) { - I_Error("Unable to allocate %i MiB of RAM for zone", default_ram); + i_error("Unable to allocate %i MiB of RAM for zone", default_ram); } - // Try to allocate the zone memory. + /* Try to allocate the zone memory. */ - *size = default_ram * 1024 * 1024; + *size = default_ram * 1024 * 1024; - zonemem = malloc(*size); + zonemem = malloc(*size); - // Failed to allocate? Reduce zone size until we reach a size - // that is acceptable. + /* Failed to allocate? Reduce zone size until we reach a size + * that is acceptable. + */ - if (zonemem == NULL) + if (zonemem == NULL) { - default_ram -= 1; + default_ram -= 1; } } - return zonemem; + return zonemem; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void i_at_exit(atexit_func_t func, boolean run_on_error) +{ + atexit_listentry_t *entry; + + entry = malloc(sizeof(*entry)); + + entry->func = func; + entry->run_on_error = run_on_error; + entry->next = exit_funcs; + exit_funcs = entry; } -byte *I_ZoneBase (int *size) +/* Tactile feedback function, probably used for the Logitech Cyberman */ + +void i_tactile(int on, int off, int total) { - byte *zonemem; - int min_ram, default_ram; - int p; +} - //! - // @category obscure - // @arg - // - // Specify the heap size, in MiB. - // +byte *i_zone_base(int *size) +{ + byte *zonemem; + int min_ram; + int default_ram; + int p; + + /* @category obscure + * @arg + * + * Specify the heap size, in MiB. + */ - p = M_CheckParmWithArgs("-mb", 1); + p = m_check_parm_with_args("-mb", 1); - if (p > 0) + if (p > 0) { - default_ram = atoi(myargv[p+1]); - min_ram = default_ram; + default_ram = atoi(myargv[p + 1]); + min_ram = default_ram; } - else + else { - // Because of the 8-byte pointer size in a 64-bit build, the default - // heap size (16 MiB) is insufficient compared to a 32-bit build. For - // example, the Alien Vendetta avm62402.lmp demo completes successfully - // on a 32-bit build, but terminates with an out of memory error on a - // 64-bit build. Therefore, to maintain consistency with a 32-bit - // build, the heap size should be increased. - - if (sizeof(void *) == 8) + /* Because of the 8-byte pointer size in a 64-bit build, the default + * heap size (16 MiB) is insufficient compared to a 32-bit build. For + * example, the Alien Vendetta avm62402.lmp demo completes successfully + * on a 32-bit build, but terminates with an out of memory error on a + * 64-bit build. Therefore, to maintain consistency with a 32-bit + * build, the heap size should be increased. + */ + + if (sizeof(void *) == 8) { - default_ram = DEFAULT_RAM * 2; + default_ram = DEFAULT_RAM * 2; } - else + else { - default_ram = DEFAULT_RAM; + default_ram = DEFAULT_RAM; } - min_ram = MIN_RAM; + + min_ram = MIN_RAM; } - zonemem = AutoAllocMemory(size, default_ram, min_ram); + zonemem = auto_alloc_memory(size, default_ram, min_ram); - printf("zone memory: %p, %x allocated for zone\n", - zonemem, *size); + printf("zone memory: %p, %x allocated for zone\n", zonemem, *size); - return zonemem; + return zonemem; } -void I_PrintBanner(const char *msg) +void i_print_banner(const char *msg) { - int i; - int spaces = 35 - (strlen(msg) / 2); + int i; + int spaces = 35 - (strlen(msg) / 2); - for (i=0; ifunc(); - entry = entry->next; + entry->func(); + entry = entry->next; } - SDL_Quit(); - - exit(0); + exit(0); } - - -// -// I_Error -// - -static boolean already_quitting = false; - -void I_Error (const char *error, ...) +void i_error(const char *error, ...) { - char msgbuf[512]; - va_list argptr; - atexit_listentry_t *entry; - boolean exit_gui_popup; + char msgbuf[512]; + va_list argptr; + atexit_listentry_t *entry; + boolean exit_gui_popup; - if (already_quitting) + if (already_quitting) { - fprintf(stderr, "Warning: recursive call to I_Error detected.\n"); - exit(-1); + fprintf(stderr, "Warning: recursive call to i_error detected.\n"); + exit(-1); } - else + else { - already_quitting = true; + already_quitting = true; } - // Message first. - va_start(argptr, error); - //fprintf(stderr, "\nError: "); - vfprintf(stderr, error, argptr); - fprintf(stderr, "\n\n"); - va_end(argptr); - fflush(stderr); + /* Message first. */ + + va_start(argptr, error); + + vfprintf(stderr, error, argptr); + fprintf(stderr, "\n\n"); + va_end(argptr); + fflush(stderr); - // Write a copy of the message into buffer. - va_start(argptr, error); - memset(msgbuf, 0, sizeof(msgbuf)); - M_vsnprintf(msgbuf, sizeof(msgbuf), error, argptr); - va_end(argptr); + /* Write a copy of the message into buffer. */ - // Shutdown. Here might be other errors. + va_start(argptr, error); + memset(msgbuf, 0, sizeof(msgbuf)); + vsnprintf(msgbuf, sizeof(msgbuf), error, argptr); + va_end(argptr); - entry = exit_funcs; + /* Shutdown. Here might be other errors. */ - while (entry != NULL) + entry = exit_funcs; + + while (entry != NULL) { - if (entry->run_on_error) + if (entry->run_on_error) { - entry->func(); + entry->func(); } - entry = entry->next; + entry = entry->next; } - //! - // @category obscure - // - // If specified, don't show a GUI window for error messages when the - // game exits with an error. - // - exit_gui_popup = !M_ParmExists("-nogui"); - - // Pop up a GUI dialog box to show the error message, if the - // game was not run from the console (and the user will - // therefore be unable to otherwise see the message). - if (exit_gui_popup && !I_ConsoleStdout()) + /* @category obscure + * + * If specified, don't show a GUI window for error messages when the + * game exits with an error. + */ + + exit_gui_popup = !m_parm_exists("-nogui"); + + /* Pop up a GUI dialog box to show the error message, if the + * game was not run from the console (and the user will + * therefore be unable to otherwise see the message). + */ + + if (exit_gui_popup && !i_console_stdout()) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, - PACKAGE_STRING, msgbuf, NULL); } - // abort(); + /* abort(); */ - SDL_Quit(); - - exit(-1); + exit(-1); } -// -// I_Realloc -// - -void *I_Realloc(void *ptr, size_t size) +void *i_realloc(void *ptr, size_t size) { - void *new_ptr; + void *new_ptr; - new_ptr = realloc(ptr, size); + new_ptr = realloc(ptr, size); - if (size != 0 && new_ptr == NULL) + if (size != 0 && new_ptr == NULL) { - I_Error ("I_Realloc: failed on reallocation of %zu bytes", size); + i_error("i_realloc: failed on reallocation of %zu bytes", size); } - return new_ptr; + return new_ptr; } -// -// Read Access Violation emulation. -// -// From PrBoom+, by entryway. -// - -// C:\>debug -// -d 0:0 -// -// DOS 6.22: -// 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) -// DOS 7.1: -// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) -// Win98: -// 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) -// DOSBox under XP: -// 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) - -#define DOS_MEM_DUMP_SIZE 10 - -static const unsigned char mem_dump_dos622[DOS_MEM_DUMP_SIZE] = { - 0x57, 0x92, 0x19, 0x00, 0xF4, 0x06, 0x70, 0x00, 0x16, 0x00}; -static const unsigned char mem_dump_win98[DOS_MEM_DUMP_SIZE] = { - 0x9E, 0x0F, 0xC9, 0x00, 0x65, 0x04, 0x70, 0x00, 0x16, 0x00}; -static const unsigned char mem_dump_dosbox[DOS_MEM_DUMP_SIZE] = { - 0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00}; -static unsigned char mem_dump_custom[DOS_MEM_DUMP_SIZE]; - -static const unsigned char *dos_mem_dump = mem_dump_dos622; - -boolean I_GetMemoryValue(unsigned int offset, void *value, int size) +boolean i_get_memory_value(unsigned int offset, void *value, int size) { - static boolean firsttime = true; + static boolean firsttime = true; - if (firsttime) + if (firsttime) { - int p, i, val; + int p; + int i; + int val; - firsttime = false; - i = 0; + firsttime = false; + i = 0; - //! - // @category compat - // @arg - // - // Specify DOS version to emulate for NULL pointer dereference - // emulation. Supported versions are: dos622, dos71, dosbox. - // The default is to emulate DOS 7.1 (Windows 98). - // + /* @category compat + * @arg + * + * Specify DOS version to emulate for NULL pointer dereference + * emulation. Supported versions are: dos622, dos71, dosbox. + * The default is to emulate DOS 7.1 (Windows 98). + */ - p = M_CheckParmWithArgs("-setmem", 1); + p = m_check_parm_with_args("-setmem", 1); - if (p > 0) + if (p > 0) { - if (!strcasecmp(myargv[p + 1], "dos622")) + if (!strcasecmp(myargv[p + 1], "dos622")) { - dos_mem_dump = mem_dump_dos622; + dos_mem_dump = mem_dump_dos622; } - if (!strcasecmp(myargv[p + 1], "dos71")) + + if (!strcasecmp(myargv[p + 1], "dos71")) { - dos_mem_dump = mem_dump_win98; + dos_mem_dump = mem_dump_win98; } - else if (!strcasecmp(myargv[p + 1], "dosbox")) + else if (!strcasecmp(myargv[p + 1], "dosbox")) { - dos_mem_dump = mem_dump_dosbox; + dos_mem_dump = mem_dump_dosbox; } - else + else { - for (i = 0; i < DOS_MEM_DUMP_SIZE; ++i) + for (i = 0; i < DOS_MEM_DUMP_SIZE; ++i) { - ++p; + ++p; - if (p >= myargc || myargv[p][0] == '-') + if (p >= myargc || myargv[p][0] == '-') { - break; + break; } - M_StrToInt(myargv[p], &val); - mem_dump_custom[i++] = (unsigned char) val; + m_str_to_int(myargv[p], &val); + mem_dump_custom[i++] = (unsigned char)val; } - dos_mem_dump = mem_dump_custom; + dos_mem_dump = mem_dump_custom; } } } - switch (size) + switch (size) { case 1: - *((unsigned char *) value) = dos_mem_dump[offset]; - return true; + *((unsigned char *)value) = dos_mem_dump[offset]; + return true; case 2: - *((unsigned short *) value) = dos_mem_dump[offset] - | (dos_mem_dump[offset + 1] << 8); - return true; + *((unsigned short *)value) = + dos_mem_dump[offset] | (dos_mem_dump[offset + 1] << 8); + return true; case 4: - *((unsigned int *) value) = dos_mem_dump[offset] - | (dos_mem_dump[offset + 1] << 8) - | (dos_mem_dump[offset + 2] << 16) - | (dos_mem_dump[offset + 3] << 24); - return true; + *((unsigned int *)value) = + dos_mem_dump[offset] | (dos_mem_dump[offset + 1] << 8) | + (dos_mem_dump[offset + 2] << 16) | + (dos_mem_dump[offset + 3] << 24); + return true; } - return false; + return false; } - diff --git a/games/NXDoom/src/i_system.h b/games/NXDoom/src/i_system.h index 78376f3cc7b..ae1c568068b 100644 --- a/games/NXDoom/src/i_system.h +++ b/games/NXDoom/src/i_system.h @@ -1,86 +1,107 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System specific interface stuff. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_system.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System specific interface stuff. + * + ****************************************************************************/ #ifndef __I_SYSTEM__ #define __I_SYSTEM__ -#include "d_ticcmd.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_event.h" +#include "d_ticcmd.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ typedef void (*atexit_func_t)(void); -// Called by DoomMain. -void I_Init (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Called by startup code -// to get the ammount of memory to malloc -// for the zone management. -byte* I_ZoneBase (int *size); +/* Called by DoomMain. */ -boolean I_ConsoleStdout(void); +void i_init(void); +/* Called by startup code to get the amount of memory to malloc for the zone + * management. + */ -// Asynchronous interrupt functions should maintain private queues -// that are read by the synchronous functions -// to be converted into events. +byte *i_zone_base(int *size); -// Either returns a null ticcmd, -// or calls a loadable driver to build it. -// This ticcmd will then be modified by the gameloop -// for normal input. -ticcmd_t* I_BaseTiccmd (void); +boolean i_console_stdout(void); +/* Asynchronous interrupt functions should maintain private queues + * that are read by the synchronous functions + * to be converted into events. + */ -// Called by M_Responder when quit is selected. -// Clean exit, displays sell blurb. -void I_Quit (void) NORETURN; +#if 0 /* Unused */ -void I_Error (const char *error, ...) NORETURN PRINTF_ATTR(1, 2); +/* Either returns a null ticcmd, or calls a loadable driver to build it. + * This ticcmd will then be modified by the gameloop for normal input. + */ -void I_Tactile (int on, int off, int total); +ticcmd_t *i_base_ticcmd(void); +#endif -void *I_Realloc(void *ptr, size_t size); +/* Called by m_responder when quit is selected. + * Clean exit, displays sell blurb. + */ -boolean I_GetMemoryValue(unsigned int offset, void *value, int size); +void i_quit(void) NORETURN; -// Schedule a function to be called when the program exits. -// If run_if_error is true, the function is called if the exit -// is due to an error (I_Error) +void i_error(const char *error, ...) NORETURN PRINTF_ATTR(1, 2); -void I_AtExit(atexit_func_t func, boolean run_if_error); +void i_tactile(int on, int off, int total); -// Add all system-specific config file variable bindings. +void *i_realloc(void *ptr, size_t size); -void I_BindVariables(void); +boolean i_get_memory_value(unsigned int offset, void *value, int size); -// Print startup banner copyright message. +/* Schedule a function to be called when the program exits. + * If run_if_error is true, the function is called if the exit + * is due to an error (i_error) + */ -void I_PrintStartupBanner(const char *gamedescription); +void i_at_exit(atexit_func_t func, boolean run_if_error); -// Print a centered text banner displaying the given string. +/* Add all system-specific config file variable bindings. */ -void I_PrintBanner(const char *text); +void i_bind_variables(void); -// Print a dividing line for startup banners. +/* Print startup banner copyright message. */ -void I_PrintDivider(void); +void i_print_startup_banner(const char *gamedescription); -#endif +/* Print a centered text banner displaying the given string. */ + +void i_print_banner(const char *text); + +/* Print a dividing line for startup banners. */ + +void i_print_divider(void); +#endif /* __I_SYSTEM__ */ diff --git a/games/NXDoom/src/i_timer.c b/games/NXDoom/src/i_timer.c index 4ec6fb047ef..abde6d4c9fc 100644 --- a/games/NXDoom/src/i_timer.c +++ b/games/NXDoom/src/i_timer.c @@ -1,82 +1,107 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Timer functions. -// - -#include "SDL.h" +/**************************************************************************** + * apps/games/NXDoom/src/i_timer.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Timer functions. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include -#include "i_timer.h" #include "doomtype.h" +#include "i_timer.h" -// -// I_GetTime -// returns time in 1/35th second tics -// +/**************************************************************************** + * Private Data + ****************************************************************************/ -static Uint32 basetime = 0; +/* The start time of the game used as the base for tic calculations. */ -int I_GetTime (void) +static struct timespec basetime = { - Uint32 ticks; - - ticks = SDL_GetTicks(); - - if (basetime == 0) - basetime = ticks; - - ticks -= basetime; - - return (ticks * TICRATE) / 1000; + .tv_nsec = 0, .tv_sec = 0 +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i_get_time + * + * Description: + * Called by D_DoomLoop. + * + * Returns: + * The current time in 1/35th second tics. + ****************************************************************************/ + +int i_get_time(void) +{ + return (i_get_time_ms() * TICRATE) / 1000; } -// -// Same as I_GetTime, but returns time in milliseconds -// +/**************************************************************************** + * Name: i_get_time_ms + * + * Returns: + * The current time in ms. + ****************************************************************************/ -int I_GetTimeMS(void) +int i_get_time_ms(void) { - Uint32 ticks; + struct timespec curtime; - ticks = SDL_GetTicks(); + /* NOTE: we ignore any possible error here */ - if (basetime == 0) - basetime = ticks; + clock_gettime(CLOCK_MONOTONIC, &curtime); + if (basetime.tv_sec == 0 && basetime.tv_nsec == 0) + { + clock_gettime(CLOCK_MONOTONIC, &basetime); + } - return ticks - basetime; + return (clock_time2usec(&curtime) - clock_time2usec(&basetime)) / 1000; } -// Sleep for a specified number of ms +/**************************************************************************** + * Name: i_init_timer + * + * Description: + * Initialize timer. + ****************************************************************************/ -void I_Sleep(int ms) +void i_init_timer(void) { - SDL_Delay(ms); -} - -void I_WaitVBL(int count) -{ - I_Sleep((count * 1000) / 70); } +/**************************************************************************** + * Name: i_wait_vbl + * + * Description: + * Wait for vertical retrace or pause a bit. + ****************************************************************************/ -void I_InitTimer(void) +void i_wait_vbl(int count) { - // initialize timer - - SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1"); - - SDL_Init(SDL_INIT_TIMER); + usleep((count * 1000000) / 70); } - diff --git a/games/NXDoom/src/i_timer.h b/games/NXDoom/src/i_timer.h index 9b3dbb8d105..eb9d7756c37 100644 --- a/games/NXDoom/src/i_timer.h +++ b/games/NXDoom/src/i_timer.h @@ -1,42 +1,76 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System-specific timer interface -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_timer.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System-specific timer interface + * + ****************************************************************************/ #ifndef __I_TIMER__ #define __I_TIMER__ +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + #define TICRATE 35 -// Called by D_DoomLoop, -// returns current time in tics. -int I_GetTime (void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: i_get_time + * + * Description: + * Called by d_doomloop. + * + * Returns: + * The current time in tics. + ****************************************************************************/ + +int i_get_time(void); + +/**************************************************************************** + * Name: i_get_time_ms + * + * Returns: + * The current time in ms. + ****************************************************************************/ -// returns current time in ms -int I_GetTimeMS (void); +int i_get_time_ms(void); -// Pause for a specified number of ms -void I_Sleep(int ms); +/**************************************************************************** + * Name: i_init_timer + * + * Description: + * Initialize timer. + ****************************************************************************/ -// Initialize timer -void I_InitTimer(void); +void i_init_timer(void); -// Wait for vertical retrace or pause a bit. -void I_WaitVBL(int count); +/**************************************************************************** + * Name: i_wait_vbl + * + * Description: + * Wait for vertical retrace or pause a bit. + ****************************************************************************/ -#endif +void i_wait_vbl(int count); +#endif /* __I_TIMER__ */ diff --git a/games/NXDoom/src/i_video.c b/games/NXDoom/src/i_video.c index 6ff3b80e1d0..0d3b41af30e 100644 --- a/games/NXDoom/src/i_video.c +++ b/games/NXDoom/src/i_video.c @@ -1,34 +1,40 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM graphics stuff for SDL. -// - - +/**************************************************************************** + * apps/games/NXDoom/src/i_video.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * DOOM graphics stuff for SDL. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include #include #include - -#include "SDL.h" -#include "SDL_opengl.h" - -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#endif +#include +#include #include "config.h" #include "d_loop.h" @@ -48,1490 +54,779 @@ #include "w_wad.h" #include "z_zone.h" -// These are (1) the window (or the full screen) that our game is rendered to -// and (2) the renderer that scales the texture (see below) into this window. +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ -static SDL_Window *screen; -static SDL_Renderer *renderer; +#define RESIZE_DELAY 500 -// Window title +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -static const char *window_title = ""; +/**************************************************************************** + * Private Types + ****************************************************************************/ -// These are (1) the 320x200x8 paletted buffer that we draw to (i.e. the one -// that holds I_VideoBuffer), (2) the 320x200x32 RGBA intermediate buffer that -// we blit the former buffer to, (3) the intermediate 320x200 texture that we -// load the RGBA buffer to and that we render into another texture (4) which -// is upscaled by an integer factor UPSCALE using "nearest" scaling and which -// in turn is finally rendered to screen using "linear" scaling. +struct graphics_state_s +{ + int fd; /* File descriptor handle to frame buffer */ -static SDL_Surface *screenbuffer = NULL; -static SDL_Surface *argbbuffer = NULL; -static SDL_Texture *texture = NULL; -static SDL_Texture *texture_upscaled = NULL; + /* The 320x200x32 RGBA intermediate buffer is what we blit the former + * buffer to. On NuttX, this is the frame buffer memory `fbmem`. It may not + * have 32-bit depth, but if it doesn't, the code is adjusted accordingly. + */ -static SDL_Rect blit_rect = { - 0, - 0, - SCREENWIDTH, - SCREENHEIGHT -}; + FAR void *fbmem; -// palette - -static SDL_Color palette[256]; -static boolean palette_to_set; + /* 8-bit depth screen buffer (320x200x8) that we draw to (i.e. the one that + * holds i_video_buffer) + */ -// display has been set up? + pixel_t *scrnbuf; -static boolean initialized = false; + /* Information about the frame buffer needed for rendering. */ -// disable mouse? + struct fb_videoinfo_s vinfo; + struct fb_planeinfo_s pinfo; -static boolean nomouse = false; -int usemouse = 1; + /* Scale multiplier for rendering large image */ -// Save screenshots in PNG format. + uint8_t scale; -int png_screenshots = 0; + bool inited; /* Track initialization */ +}; -// SDL video driver name +/**************************************************************************** + * Private Data + ****************************************************************************/ -char *video_driver = ""; +/* NuttX graphics state */ -// Window position: +static struct graphics_state_s g_graphics_state = +{ + 0 +}; -char *window_position = "center"; +/* Window title */ -// SDL display number on which to run. +static const char *g_window_title = ""; -int video_display = 0; +/* Colour palette map from 8-bit colour to 32-bit */ -// Screen width and height, from configuration file. +static struct argbcolor_s g_palette[256]; -int window_width = 800; -int window_height = 600; +static boolean palette_to_set; -// Fullscreen mode, 0x0 for SDL_WINDOW_FULLSCREEN_DESKTOP. +/* disable mouse? */ -int fullscreen_width = 0, fullscreen_height = 0; +static boolean nomouse = false; -// Maximum number of pixels to use for intermediate scale buffer. +/* Maximum number of pixels to use for intermediate scale buffer. */ static int max_scaling_buffer_pixels = 16000000; -// Run in full screen mode? (int type for config code) - -int fullscreen = true; - -// Aspect ratio correction mode - -int aspect_ratio_correct = true; -static int actualheight; - -// Smooth pixel scaling -int smooth_pixel_scaling = true; - -// Force integer scales for resolution-independent rendering - -int integer_scaling = false; - -// VGA Porch palette change emulation - -int vga_porch_flash = false; - -// Force software rendering, for systems which lack effective hardware -// acceleration - -int force_software_renderer = false; - -// Time to wait for the screen to settle on startup before starting the -// game (ms) +/* Time to wait for the screen to settle on startup before starting the game + * (ms) + */ static int startup_delay = 1000; -// Grab the mouse? (int type for config code). nograbmouse_override allows -// this to be temporarily disabled via the command line. +/* Grab the mouse? (int type for config code). nograbmouse_override allows + * this to be temporarily disabled via the command line. + */ static int grabmouse = true; static boolean nograbmouse_override = false; -// The screen buffer; this is modified to draw things to the screen - -pixel_t *I_VideoBuffer = NULL; - -// If true, game is running as a screensaver - -boolean screensaver_mode = false; - -// Flag indicating whether the screen is currently visible: -// when the screen isnt visible, don't render the screen - -boolean screenvisible = true; - -// If true, we display dots at the bottom of the screen to -// indicate FPS. +/* If true, we display dots at the bottom of the screen to + * indicate FPS. + */ static boolean display_fps_dots; -// If this is true, the screen is rendered but not blitted to the -// video buffer. +/* If this is true, the screen is rendered but not blitted to the + * video buffer. + */ static boolean noblit; -// Callback function to invoke to determine whether to grab the -// mouse pointer. +/* Callback function to invoke to determine whether to grab the + * mouse pointer. + */ static grabmouse_callback_t grabmouse_callback = NULL; -// Does the window currently have focus? +/* Does the window currently have focus? */ static boolean window_focused = true; -// Window resize state. +/* Window resize state. */ +#if 0 static boolean need_resize = false; static unsigned int last_resize_time; -#define RESIZE_DELAY 500 +#endif -// Gamma correction level to use +/**************************************************************************** + * Public Data + ****************************************************************************/ -int usegamma = 0; +int usemouse = 1; -// Joystick/gamepad hysteresis -unsigned int joywait = 0; +/* Save screenshots in PNG format. */ -// Icon RGB data and dimensions -static const unsigned int *icon_data; -static int icon_w; -static int icon_h; +int png_screenshots = 0; -static boolean MouseShouldBeGrabbed() -{ - // never grab the mouse when in screensaver mode - - if (screensaver_mode) - return false; +/* SDL video driver name */ - // if the window doesn't have focus, never grab it +char *video_driver = ""; - if (!window_focused) - return false; +/* Window position: */ - // always grab the mouse when full screen (dont want to - // see the mouse pointer) +char *window_position = "center"; - if (fullscreen) - return true; +/* SDL display number on which to run. */ - // Don't grab the mouse if mouse input is disabled +int video_display = 0; - if (!usemouse || nomouse) - return false; +/* Screen width and height, from configuration file. */ - // if we specify not to grab the mouse, never grab +int window_width = 320; +int window_height = 200; - if (nograbmouse_override || !grabmouse) - return false; +/* Fullscreen mode, 0x0 for SDL_WINDOW_FULLSCREEN_DESKTOP. */ - // Invoke the grabmouse callback function to determine whether - // the mouse should be grabbed +int fullscreen_width = 0; +int fullscreen_height = 0; - if (grabmouse_callback != NULL) - { - return grabmouse_callback(); - } - else - { - return true; - } -} +/* Run in full screen mode? (int type for config code) */ -void I_SetGrabMouseCallback(grabmouse_callback_t func) -{ - grabmouse_callback = func; -} +int fullscreen = true; -// Set the variable controlling FPS dots. +/* Smooth pixel scaling */ -void I_DisplayFPSDots(boolean dots_on) -{ - display_fps_dots = dots_on; -} +int smooth_pixel_scaling = true; -static void SetShowCursor(boolean show) -{ - if (!screensaver_mode) - { - // When the cursor is hidden, grab the input. - // Relative mode implicitly hides the cursor. - SDL_SetRelativeMouseMode(!show); - SDL_GetRelativeMouseState(NULL, NULL); - } -} +/* Force integer scales for resolution-independent rendering */ -void I_ShutdownGraphics(void) -{ - if (initialized) - { - SetShowCursor(true); +int integer_scaling = false; - SDL_FreeSurface(argbbuffer); - SDL_FreeSurface(screenbuffer); - SDL_DestroyTexture(texture_upscaled); - SDL_DestroyTexture(texture); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(screen); - SDL_QuitSubSystem(SDL_INIT_VIDEO); +/* VGA Porch palette change emulation */ - initialized = false; - } -} +int vga_porch_flash = false; +/* Force software rendering, for systems which lack effective hardware + * acceleration + */ +int force_software_renderer = false; -// -// I_StartFrame -// -void I_StartFrame (void) -{ - // er? +/* The screen buffer; this is modified to draw things to the screen */ -} +pixel_t *i_video_buffer = NULL; -// Adjust window_width / window_height variables to be an an aspect -// ratio consistent with the aspect_ratio_correct variable. -static void AdjustWindowSize(void) -{ - if (aspect_ratio_correct || integer_scaling) - { - if (window_width * actualheight <= window_height * SCREENWIDTH) - { - // We round up window_height if the ratio is not exact; this leaves - // the result stable. - window_height = (window_width * actualheight + SCREENWIDTH - 1) / SCREENWIDTH; - } - else - { - window_width = window_height * SCREENWIDTH / actualheight; - } - } -} +/* If true, game is running as a screensaver */ -static void HandleWindowEvent(SDL_WindowEvent *event) -{ - int i; +boolean screensaver_mode = false; - switch (event->event) - { -#if 0 // SDL2-TODO - case SDL_ACTIVEEVENT: - // need to update our focus state - UpdateFocus(); - break; -#endif - case SDL_WINDOWEVENT_EXPOSED: - palette_to_set = true; - break; - - case SDL_WINDOWEVENT_RESIZED: - need_resize = true; - last_resize_time = SDL_GetTicks(); - break; - - // Don't render the screen when the window is minimized: - - case SDL_WINDOWEVENT_MINIMIZED: - screenvisible = false; - break; - - case SDL_WINDOWEVENT_MAXIMIZED: - case SDL_WINDOWEVENT_RESTORED: - screenvisible = true; - break; - - // Update the value of window_focused when we get a focus event - // - // We try to make ourselves be well-behaved: the grab on the mouse - // is removed if we lose focus (such as a popup window appearing), - // and we dont move the mouse around if we aren't focused either. - - case SDL_WINDOWEVENT_FOCUS_GAINED: - window_focused = true; - break; - - case SDL_WINDOWEVENT_FOCUS_LOST: - window_focused = false; - break; - - // We want to save the user's preferred monitor to use for running the - // game, so that next time we're run we start on the same display. So - // every time the window is moved, find which display we're now on and - // update the video_display config variable. - - case SDL_WINDOWEVENT_MOVED: - i = SDL_GetWindowDisplayIndex(screen); - if (i >= 0) - { - video_display = i; - } - break; +/* Flag indicating whether the screen is currently visible: + * when the screen isn't visible, don't render the screen + */ - default: - break; - } -} +boolean screenvisible = true; -static boolean ToggleFullScreenKeyShortcut(SDL_Keysym *sym) -{ - Uint16 flags = (KMOD_LALT | KMOD_RALT); -#if defined(__MACOSX__) - flags |= (KMOD_LGUI | KMOD_RGUI); -#endif - return (sym->scancode == SDL_SCANCODE_RETURN || - sym->scancode == SDL_SCANCODE_KP_ENTER) && (sym->mod & flags) != 0; -} +/* Gamma correction level to use */ -static void I_ToggleFullScreen(void) -{ - unsigned int flags = 0; +int usegamma = 0; - // TODO: Consider implementing fullscreen toggle for SDL_WINDOW_FULLSCREEN - // (mode-changing) setup. This is hard because we have to shut down and - // restart again. - if (fullscreen_width != 0 || fullscreen_height != 0) - { - return; - } +/* Joystick/gamepad hysteresis */ - fullscreen = !fullscreen; +unsigned int joywait = 0; - if (fullscreen) - { - flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - } +/* TODO: I'm sure more of the variables above can be private */ - SDL_SetWindowFullscreen(screen, flags); +/**************************************************************************** + * Private Functions + ****************************************************************************/ - if (!fullscreen) - { - AdjustWindowSize(); - SDL_SetWindowSize(screen, window_width, window_height); - } -} +/**************************************************************************** + * Name: blit_screen + * + * Description: + * Blit the 8-bit depth buffer that DOOM renders to onto the frame buffer + * in a higher colour depth. + * + ****************************************************************************/ -void I_GetEvent(void) +static void blit_screen(void) { - SDL_Event sdlevent; + uint8_t p_idx; + void *fbptr; - SDL_PumpEvents(); + /* TODO: It would be best to do this more efficiently/with less memory. + * It also would be good if we could handle the palette translation here + * such that DOOM can be played on frame buffers with differing bit depths + * and pixel formats. + */ - while (SDL_PollEvent(&sdlevent)) + fbptr = g_graphics_state.fbmem; + for (unsigned y = 0; y < SCREENHEIGHT * g_graphics_state.scale; y++) { - switch (sdlevent.type) + for (unsigned x = 0; x < SCREENWIDTH * g_graphics_state.scale; x++) { - case SDL_KEYDOWN: - if (ToggleFullScreenKeyShortcut(&sdlevent.key.keysym)) - { - I_ToggleFullScreen(); - break; - } - // deliberate fall-though - - case SDL_KEYUP: - I_HandleKeyboardEvent(&sdlevent); - break; - - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - case SDL_MOUSEWHEEL: - if (usemouse && !nomouse && window_focused) - { - I_HandleMouseEvent(&sdlevent); - } - break; - - case SDL_QUIT: - if (screensaver_mode) - { - I_Quit(); - } - else - { - event_t event; - event.type = ev_quit; - D_PostEvent(&event); - } - break; - - case SDL_WINDOWEVENT: - if (sdlevent.window.windowID == SDL_GetWindowID(screen)) - { - HandleWindowEvent(&sdlevent.window); - } - break; - - default: - break; - } - } -} + p_idx = g_graphics_state + .scrnbuf[(y / g_graphics_state.scale) * SCREENWIDTH + + (x / g_graphics_state.scale)]; -// -// I_StartTic -// -void I_StartTic (void) -{ - if (!initialized) - { - return; - } - - I_GetEvent(); - - if (usemouse && !nomouse && window_focused) - { - I_ReadMouse(); - } + ((uint32_t *)(fbptr))[x] = + ARGBTO32(g_palette[p_idx].a, g_palette[p_idx].r, + g_palette[p_idx].g, g_palette[p_idx].b); + } - if (joywait < I_GetTime()) - { - I_UpdateJoystick(); + fbptr += g_graphics_state.pinfo.stride; } } - -// -// I_UpdateNoBlit -// -void I_UpdateNoBlit (void) +static void update_grab(void) { - // what is this? } -static void UpdateGrab(void) +static void set_video_mode(void) { - static boolean currently_grabbed = false; - boolean grab; - - grab = MouseShouldBeGrabbed(); - - if (screensaver_mode) - { - // Hide the cursor in screensaver mode - - SetShowCursor(false); - } - else if (grab && !currently_grabbed) - { - SetShowCursor(false); - } - else if (!grab && currently_grabbed) - { - int screen_w, screen_h; - - SetShowCursor(true); - - // When releasing the mouse from grab, warp the mouse cursor to - // the bottom-right of the screen. This is a minimally distracting - // place for it to appear - we may only have released the grab - // because we're at an end of level intermission screen, for - // example. - - SDL_GetWindowSize(screen, &screen_w, &screen_h); - SDL_WarpMouseInWindow(screen, screen_w - 16, screen_h - 16); - SDL_GetRelativeMouseState(NULL, NULL); - } - - currently_grabbed = grab; } -static void LimitTextureSize(int *w_upscale, int *h_upscale) +static void i_get_event(void) { - SDL_RendererInfo rinfo; - int orig_w, orig_h; - - orig_w = *w_upscale; - orig_h = *h_upscale; - - // Query renderer and limit to maximum texture dimensions of hardware: - if (SDL_GetRendererInfo(renderer, &rinfo) != 0) - { - I_Error("CreateUpscaledTexture: SDL_GetRendererInfo() call failed: %s", - SDL_GetError()); - } + int err; +#if CONFIG_GAMES_NXDOOM_KEYBOARD + struct keyboard_event_s kbdevent; - while (*w_upscale * SCREENWIDTH > rinfo.max_texture_width) + while ((err = get_kbd_event(&kbdevent)) == 0) { - --*w_upscale; - } - while (*h_upscale * SCREENHEIGHT > rinfo.max_texture_height) - { - --*h_upscale; - } - - if ((*w_upscale < 1 && rinfo.max_texture_width > 0) || - (*h_upscale < 1 && rinfo.max_texture_height > 0)) - { - I_Error("CreateUpscaledTexture: Can't create a texture big enough for " - "the whole screen! Maximum texture size %dx%d", - rinfo.max_texture_width, rinfo.max_texture_height); - } + switch (kbdevent.type) + { + case KEYBOARD_PRESS: - // We limit the amount of texture memory used for the intermediate buffer, - // since beyond a certain point there are diminishing returns. Also, - // depending on the hardware there may be performance problems with very - // huge textures, so the user can use this to reduce the maximum texture - // size if desired. + /* deliberate fall-though */ - if (max_scaling_buffer_pixels < SCREENWIDTH * SCREENHEIGHT) - { - I_Error("CreateUpscaledTexture: max_scaling_buffer_pixels too small " - "to create a texture buffer: %d < %d", - max_scaling_buffer_pixels, SCREENWIDTH * SCREENHEIGHT); - } + case KEYBOARD_RELEASE: + i_handle_keyboard_event(&kbdevent); + break; - while (*w_upscale * *h_upscale * SCREENWIDTH * SCREENHEIGHT - > max_scaling_buffer_pixels) - { - if (*w_upscale > *h_upscale) - { - --*w_upscale; - } - else - { - --*h_upscale; + default: + break; } } - - if (*w_upscale != orig_w || *h_upscale != orig_h) - { - printf("CreateUpscaledTexture: Limited texture size to %dx%d " - "(max %d pixels, max texture size %dx%d)\n", - *w_upscale * SCREENWIDTH, *h_upscale * SCREENHEIGHT, - max_scaling_buffer_pixels, - rinfo.max_texture_width, rinfo.max_texture_height); - } +#endif } -static void CreateUpscaledTexture(boolean force) -{ - int w, h; - int h_upscale, w_upscale; - static int h_upscale_old, w_upscale_old; +/**************************************************************************** + * Public Functions + ****************************************************************************/ - SDL_Texture *new_texture, *old_texture; - - // Get the size of the renderer output. The units this gives us will be - // real world pixels, which are not necessarily equivalent to the screen's - // window size (because of highdpi). - if (SDL_GetRendererOutputSize(renderer, &w, &h) != 0) - { - I_Error("Failed to get renderer output size: %s", SDL_GetError()); - } +void i_set_grab_mouse_callback(grabmouse_callback_t func) +{ + grabmouse_callback = func; +} - // When the screen or window dimensions do not match the aspect ratio - // of the texture, the rendered area is scaled down to fit. Calculate - // the actual dimensions of the rendered area. +/* Set the variable controlling FPS dots. */ - if (w * actualheight < h * SCREENWIDTH) - { - // Tall window. +void i_display_fps_dots(boolean dots_on) +{ + display_fps_dots = dots_on; +} - h = w * actualheight / SCREENWIDTH; - } - else +void i_shutdown_graphics(void) +{ + if (!g_graphics_state.inited) { - // Wide window. - - w = h * SCREENWIDTH / actualheight; + return; } - // Pick texture size the next integer multiple of the screen dimensions. - // If one screen dimension matches an integer multiple of the original - // resolution, there is no need to overscale in this direction. + close(g_graphics_state.fd); + munmap(g_graphics_state.fbmem, g_graphics_state.pinfo.fblen); + free(g_graphics_state.scrnbuf); + g_graphics_state.inited = false; +} - w_upscale = (w + SCREENWIDTH - 1) / SCREENWIDTH; - h_upscale = (h + SCREENHEIGHT - 1) / SCREENHEIGHT; +void i_start_frame(void) +{ + /* er? */ +} - // Minimum texture dimensions of 320x200. +/**************************************************************************** + * Public Functions + ****************************************************************************/ - if (w_upscale < 1) - { - w_upscale = 1; - } - if (h_upscale < 1) +void i_start_tic(void) +{ + if (!g_graphics_state.inited) { - h_upscale = 1; + return; } - LimitTextureSize(&w_upscale, &h_upscale); - - // Create a new texture only if the upscale factors have actually changed. + i_get_event(); - if (h_upscale == h_upscale_old && w_upscale == w_upscale_old && !force) + if (usemouse && !nomouse && window_focused) { - return; + i_read_mouse(); } - h_upscale_old = h_upscale; - w_upscale_old = w_upscale; - - // Set the scaling quality for rendering the upscaled texture to "linear", - // which looks much softer and smoother than "nearest" but does a better - // job at downscaling from the upscaled texture to screen. - - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - - new_texture = SDL_CreateTexture(renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_TARGET, - w_upscale*SCREENWIDTH, - h_upscale*SCREENHEIGHT); - - old_texture = texture_upscaled; - texture_upscaled = new_texture; - - if (old_texture != NULL) + if (joywait < i_get_time()) { - SDL_DestroyTexture(old_texture); + i_update_joystick(); } } -// -// I_FinishUpdate -// -void I_FinishUpdate (void) +void i_update_no_blit(void) { - static int lasttic; - int tics; - int i; - - if (!initialized) - return; - - if (noblit) - return; - - if (need_resize) - { - if (SDL_GetTicks() > last_resize_time + RESIZE_DELAY) - { - int flags; - // When the window is resized (we're not in fullscreen mode), - // save the new window size. - flags = SDL_GetWindowFlags(screen); - if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) - { - SDL_GetWindowSize(screen, &window_width, &window_height); - - // Adjust the window by resizing again so that the window - // is the right aspect ratio. - AdjustWindowSize(); - SDL_SetWindowSize(screen, window_width, window_height); - } - CreateUpscaledTexture(false); - need_resize = false; - palette_to_set = true; - } - else - { - return; - } - } - - UpdateGrab(); - -#if 0 // SDL2-TODO - // Don't update the screen if the window isn't visible. - // Not doing this breaks under Windows when we alt-tab away - // while fullscreen. + /* what is this? */ +} - if (!(SDL_GetAppState() & SDL_APPACTIVE)) - return; -#endif +void i_finish_update(void) +{ + static int lasttic; + int tics; + int i; - // draws little dots on the bottom of the screen + if (!g_graphics_state.inited) return; - if (display_fps_dots) - { - i = I_GetTime(); - tics = i - lasttic; - lasttic = i; - if (tics > 20) tics = 20; - - for (i=0 ; iformat->palette, palette, 0, 256); - palette_to_set = false; + i = i_get_time(); + tics = i - lasttic; + lasttic = i; + if (tics > 20) tics = 20; - if (vga_porch_flash) - { - // "flash" the pillars/letterboxes with palette changes, emulating - // VGA "porch" behaviour (GitHub issue #832) - SDL_SetRenderDrawColor(renderer, palette[0].r, palette[0].g, - palette[0].b, SDL_ALPHA_OPAQUE); - } + for (i = 0; i < tics * 4; i += 4) + i_video_buffer[(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0xff; + for (; i < 20 * 4; i += 4) + i_video_buffer[(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0x0; } - // Blit from the paletted 8-bit screen buffer to the intermediate - // 32-bit RGBA buffer and update the intermediate texture with the - // contents of the RGBA buffer. - - SDL_LockTexture(texture, &blit_rect, &argbbuffer->pixels, - &argbbuffer->pitch); - SDL_LowerBlit(screenbuffer, &blit_rect, argbbuffer, &blit_rect); - SDL_UnlockTexture(texture); - - // Make sure the pillarboxes are kept clear each frame. + /* Draw disk icon before blit, if necessary. */ - SDL_RenderClear(renderer); + v_draw_disk_icon(); - if (smooth_pixel_scaling && !force_software_renderer) + if (palette_to_set) { - // Render this intermediate texture into the upscaled texture - // using "nearest" integer scaling. - SDL_SetRenderTarget(renderer, texture_upscaled); - SDL_RenderCopy(renderer, texture, NULL, NULL); - - // Finally, render this upscaled texture to screen using linear scaling. - - SDL_SetRenderTarget(renderer, NULL); - SDL_RenderCopy(renderer, texture_upscaled, NULL, NULL); - } - else - { - SDL_SetRenderTarget(renderer, NULL); - SDL_RenderCopy(renderer, texture, NULL, NULL); + palette_to_set = false; } + blit_screen(); - // Draw! + /* Draw! */ - SDL_RenderPresent(renderer); + /* Restore background and undo the disk indicator, if it was drawn. */ - // Restore background and undo the disk indicator, if it was drawn. - V_RestoreDiskBackground(); + v_restore_disk_background(); } - -// -// I_ReadScreen -// -void I_ReadScreen (pixel_t* scr) +void i_read_screen(pixel_t *scr) { - memcpy(scr, I_VideoBuffer, SCREENWIDTH*SCREENHEIGHT*sizeof(*scr)); + memcpy(scr, i_video_buffer, SCREENWIDTH * SCREENHEIGHT * sizeof(*scr)); } +/**************************************************************************** + * Name: i_set_palette + ****************************************************************************/ -// -// I_SetPalette -// -void I_SetPalette (byte *doompalette) +void i_set_palette(byte *doompalette) { - int i; - - for (i=0; i<256; ++i) + for (int i = 0; i < 256; ++i) { - // Zero out the bottom two bits of each channel - the PC VGA - // controller only supports 6 bits of accuracy. + /* Zero out the bottom two bits of each channel - the PC VGA + * controller only supports 6 bits of accuracy. + */ - palette[i].a = 0xFFU; - palette[i].r = gammatable[usegamma][*doompalette++] & ~3; - palette[i].g = gammatable[usegamma][*doompalette++] & ~3; - palette[i].b = gammatable[usegamma][*doompalette++] & ~3; + g_palette[i].a = 0xffu; + g_palette[i].r = gammatable[usegamma][*doompalette++] & ~3; + g_palette[i].g = gammatable[usegamma][*doompalette++] & ~3; + g_palette[i].b = gammatable[usegamma][*doompalette++] & ~3; } - palette_to_set = true; + palette_to_set = true; } -// Given an RGB value, find the closest matching palette index. +/**************************************************************************** + * Name: i_get_palette_index + * + * Description: + * Given an RGB value, find the closest matching palette index. + * + * Return: + * An index into the palette lookup table for the best match. + * + ****************************************************************************/ -int I_GetPaletteIndex(int r, int g, int b) +int i_get_palette_index(int r, int g, int b) { - int best, best_diff, diff; - int i; - - best = 0; best_diff = INT_MAX; + int best = 0; + int best_diff = INT_MAX; + int diff; - for (i = 0; i < 256; ++i) + for (int i = 0; i < 256; ++i) { - diff = (r - palette[i].r) * (r - palette[i].r) - + (g - palette[i].g) * (g - palette[i].g) - + (b - palette[i].b) * (b - palette[i].b); + diff = (r - g_palette[i].r) * (r - g_palette[i].r) + + (g - g_palette[i].g) * (g - g_palette[i].g) + + (b - g_palette[i].b) * (b - g_palette[i].b); - if (diff < best_diff) + if (diff < best_diff) { - best = i; - best_diff = diff; + best = i; + best_diff = diff; } - if (diff == 0) + if (diff == 0) { - break; + break; } } - return best; + return best; } -// -// Set the window title -// +/**************************************************************************** + * Name: i_set_window_title + * + * Description: + * Set the window title internally. + * + ****************************************************************************/ -void I_SetWindowTitle(const char *title) +void i_set_window_title(const char *title) { - window_title = title; + g_window_title = title; } -// -// Call the SDL function to set the window title, based on -// the title set with I_SetWindowTitle. -// +/**************************************************************************** + * Name: i_init_window_title + * + * Description: + * Actually cause the window title to update with whatever window title was + * last set via i_set_window_title. + * + ****************************************************************************/ -void I_InitWindowTitle(void) +void i_init_window_title(void) { - char *buf; - - buf = M_StringJoin(window_title, " - ", PACKAGE_STRING, NULL); - SDL_SetWindowTitle(screen, buf); - free(buf); } -void I_RegisterWindowIcon(const unsigned int *icon, int width, int height) -{ - icon_data = icon; - icon_w = width; - icon_h = height; -} +/**************************************************************************** + * Name: i_set_window_title + ****************************************************************************/ -// Set the application icon - -void I_InitWindowIcon(void) +void i_graphics_check_commandline(void) { - SDL_Surface *surface; + int i; - surface = SDL_CreateRGBSurfaceFrom((void *) icon_data, icon_w, icon_h, - 32, icon_w * 4, - 0xffu << 24, 0xffu << 16, - 0xffu << 8, 0xffu << 0); + /* @category video + * @vanilla + * + * Disable blitting the screen. + */ - SDL_SetWindowIcon(screen, surface); - SDL_FreeSurface(surface); -} + noblit = m_check_parm("-noblit"); -// Set video size to a particular scale factor (1x, 2x, 3x, etc.) + /* @category video + * + * Don't grab the mouse when running in windowed mode. + */ -static void SetScaleFactor(int factor) -{ - int height; - - // Pick 320x200 or 320x240, depending on aspect ratio correct - if (aspect_ratio_correct) - { - height = SCREENHEIGHT_4_3; - } - else - { - height = SCREENHEIGHT; - } - - window_width = factor * SCREENWIDTH; - window_height = factor * height; - fullscreen = false; -} - -void I_GraphicsCheckCommandLine(void) -{ - int i; - - //! - // @category video - // @vanilla - // - // Disable blitting the screen. - // + nograbmouse_override = m_parm_exists("-nograbmouse"); - noblit = M_CheckParm ("-noblit"); + /* default to fullscreen mode, allow override with command line + * nofullscreen because we love prboom + */ - //! - // @category video - // - // Don't grab the mouse when running in windowed mode. - // + /* @category video + * + * Run in a window. + */ - nograbmouse_override = M_ParmExists("-nograbmouse"); - - // default to fullscreen mode, allow override with command line - // nofullscreen because we love prboom - - //! - // @category video - // - // Run in a window. - // - - if (M_CheckParm("-window") || M_CheckParm("-nofullscreen")) + if (m_check_parm("-window") || m_check_parm("-nofullscreen")) { - fullscreen = false; + fullscreen = false; } - //! - // @category video - // - // Run in fullscreen mode. - // + /* @category video + * + * Run in fullscreen mode. + */ - if (M_CheckParm("-fullscreen")) + if (m_check_parm("-fullscreen")) { - fullscreen = true; + fullscreen = true; } - //! - // @category video - // - // Disable the mouse. - // + /* @category video + * + * Disable the mouse. + */ - nomouse = M_CheckParm("-nomouse") > 0; + nomouse = m_check_parm("-nomouse") > 0; - //! - // @category video - // @arg - // - // Specify the screen width, in pixels. Implies -window. - // + /* @category video + * @arg + * + * Specify the screen width, in pixels. Implies -window. + */ - i = M_CheckParmWithArgs("-width", 1); + i = m_check_parm_with_args("-width", 1); - if (i > 0) + if (i > 0) { - window_width = atoi(myargv[i + 1]); - fullscreen = false; + window_width = atoi(myargv[i + 1]); + fullscreen = false; } - //! - // @category video - // @arg - // - // Specify the screen height, in pixels. Implies -window. - // + /* @category video + * @arg + * + * Specify the screen height, in pixels. Implies -window. + */ - i = M_CheckParmWithArgs("-height", 1); + i = m_check_parm_with_args("-height", 1); - if (i > 0) + if (i > 0) { - window_height = atoi(myargv[i + 1]); - fullscreen = false; + window_height = atoi(myargv[i + 1]); + fullscreen = false; } - //! - // @category video - // @arg - // - // Specify the dimensions of the window. Implies -window. - // + /* @category video + * @arg + * + * Specify the dimensions of the window. Implies -window. + */ - i = M_CheckParmWithArgs("-geometry", 1); + i = m_check_parm_with_args("-geometry", 1); - if (i > 0) + if (i > 0) { - int w, h, s; + int w; + int h; + int s; - s = sscanf(myargv[i + 1], "%ix%i", &w, &h); - if (s == 2) + s = sscanf(myargv[i + 1], "%ix%i", &w, &h); + if (s == 2) { - window_width = w; - window_height = h; - fullscreen = false; + window_width = w; + window_height = h; + fullscreen = false; } } - //! - // @category video - // @arg - // - // Specify the display number on which to show the screen. - // + /* @category video + * @arg + * + * Specify the display number on which to show the screen. + */ - i = M_CheckParmWithArgs("-display", 1); + i = m_check_parm_with_args("-display", 1); - if (i > 0) + if (i > 0) { - int display = atoi(myargv[i + 1]); - if (display >= 0) + int display = atoi(myargv[i + 1]); + if (display >= 0) { - video_display = display; + video_display = display; } } - - //! - // @category video - // - // Don't scale up the screen. Implies -window. - // - - if (M_CheckParm("-1")) - { - SetScaleFactor(1); - } - - //! - // @category video - // - // Double up the screen to 2x its normal size. Implies -window. - // - - if (M_CheckParm("-2")) - { - SetScaleFactor(2); - } - - //! - // @category video - // - // Double up the screen to 3x its normal size. Implies -window. - // - - if (M_CheckParm("-3")) - { - SetScaleFactor(3); - } } -// Check if we have been invoked as a screensaver by xscreensaver. +/* Check if we have been invoked as a screensaver by xscreensaver. */ -void I_CheckIsScreensaver(void) +void i_check_is_screensaver(void) { - char *env; + char *env; - env = getenv("XSCREENSAVER_WINDOW"); + env = getenv("XSCREENSAVER_WINDOW"); - if (env != NULL) + if (env != NULL) { - screensaver_mode = true; + screensaver_mode = true; } } -static void SetSDLVideoDriver(void) -{ - // Allow a default value for the SDL video driver to be specified - // in the configuration file. - - if (strcmp(video_driver, "") != 0) - { - char *env_string; - - env_string = M_StringJoin("SDL_VIDEODRIVER=", video_driver, NULL); - putenv(env_string); - free(env_string); - } -} +/* Check the display bounds of the display referred to by 'video_display' and + * set x and y to a location that places the window in the center of that + * display. + */ -// Check the display bounds of the display referred to by 'video_display' and -// set x and y to a location that places the window in the center of that -// display. -static void CenterWindow(int *x, int *y, int w, int h) +static void center_window(int *x, int *y, int w, int h) { - SDL_Rect bounds; - - if (SDL_GetDisplayBounds(video_display, &bounds) < 0) - { - fprintf(stderr, "CenterWindow: Failed to read display bounds " - "for display #%d!\n", video_display); - return; - } - - *x = bounds.x + SDL_max((bounds.w - w) / 2, 0); - *y = bounds.y + SDL_max((bounds.h - h) / 2, 0); + *x = MAX((g_graphics_state.vinfo.xres - w) / 2, 0); + *y = MAX((g_graphics_state.vinfo.yres - h) / 2, 0); } -void I_GetWindowPosition(int *x, int *y, int w, int h) +void i_get_window_position(int *x, int *y, int w, int h) { - // Check that video_display corresponds to a display that really exists, - // and if it doesn't, reset it. - if (video_display < 0 || video_display >= SDL_GetNumVideoDisplays()) - { - fprintf(stderr, - "I_GetWindowPosition: We were configured to run on display #%d, " - "but it no longer exists (max %d). Moving to display 0.\n", - video_display, SDL_GetNumVideoDisplays() - 1); - video_display = 0; - } - - // in fullscreen mode, the window "position" still matters, because - // we use it to control which display we run fullscreen on. + /* in fullscreen mode, the window "position" still matters, because + * we use it to control which display we run fullscreen on. + */ - if (fullscreen) + if (fullscreen) { - CenterWindow(x, y, w, h); - return; - } - - // in windowed mode, the desired window position can be specified - // in the configuration file. - - if (window_position == NULL || !strcmp(window_position, "")) - { - *x = *y = SDL_WINDOWPOS_UNDEFINED; - } - else if (!strcmp(window_position, "center")) - { - // Note: SDL has a SDL_WINDOWPOS_CENTER, but this is useless for our - // purposes, since we also want to control which display we appear on. - // So we have to do this ourselves. - CenterWindow(x, y, w, h); - } - else if (sscanf(window_position, "%i,%i", x, y) != 2) - { - // invalid format: revert to default - fprintf(stderr, "I_GetWindowPosition: invalid window_position setting\n"); - *x = *y = SDL_WINDOWPOS_UNDEFINED; + center_window(x, y, w, h); + return; } } -static void SetVideoMode(void) +void i_init_graphics(void) { - int w, h; - int x, y; - int window_flags = 0, renderer_flags = 0; - SDL_DisplayMode mode; - - w = window_width; - h = window_height; - - // In windowed mode, the window can be resized while the game is - // running. - window_flags = SDL_WINDOW_RESIZABLE; - - // Set the highdpi flag - this makes a big difference on Macs with - // retina displays, especially when using small window sizes. - window_flags |= SDL_WINDOW_ALLOW_HIGHDPI; - - if (fullscreen) - { - if (fullscreen_width == 0 && fullscreen_height == 0) - { - // This window_flags means "Never change the screen resolution! - // Instead, draw to the entire screen by scaling the texture - // appropriately". - window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - } - else - { - w = fullscreen_width; - h = fullscreen_height; - window_flags |= SDL_WINDOW_FULLSCREEN; - } - } - - // Running without window decorations is potentially useful if you're - // playing in three window mode and want to line up three game windows - // next to each other on a single desktop. - // Deliberately not documented because I'm not sure how useful this is yet. - if (M_ParmExists("-borderless")) - { - window_flags |= SDL_WINDOW_BORDERLESS; - } - - I_GetWindowPosition(&x, &y, w, h); - - // Create window and renderer contexts. We set the window title - // later anyway and leave the window position "undefined". If - // "window_flags" contains the fullscreen flag (see above), then - // w and h are ignored. - - if (screen == NULL) - { - screen = SDL_CreateWindow(NULL, x, y, w, h, window_flags); - - if (screen == NULL) - { - I_Error("Error creating window for video startup: %s", - SDL_GetError()); - } - - SDL_SetWindowMinimumSize(screen, SCREENWIDTH, actualheight); - - I_InitWindowTitle(); - I_InitWindowIcon(); - } - - // The SDL_RENDERER_TARGETTEXTURE flag is required to render the - // intermediate texture into the upscaled texture. - renderer_flags = SDL_RENDERER_TARGETTEXTURE; - - if (SDL_GetCurrentDisplayMode(video_display, &mode) != 0) - { - I_Error("Could not get display mode for video display #%d: %s", - video_display, SDL_GetError()); - } - - // Turn on vsync if we aren't in a -timedemo - if (!singletics && mode.refresh_rate > 0) - { - renderer_flags |= SDL_RENDERER_PRESENTVSYNC; - } - - if (force_software_renderer) - { - renderer_flags |= SDL_RENDERER_SOFTWARE; - renderer_flags &= ~SDL_RENDERER_PRESENTVSYNC; - } - - if (renderer != NULL) - { - SDL_DestroyRenderer(renderer); - // all associated textures get destroyed - texture = NULL; - texture_upscaled = NULL; - } - - renderer = SDL_CreateRenderer(screen, -1, renderer_flags); - - // If we could not find a matching render driver, - // try again without hardware acceleration. + uint8_t xscale; + uint8_t yscale; + int err; + byte *doompal; - if (renderer == NULL && !force_software_renderer) - { - renderer_flags |= SDL_RENDERER_SOFTWARE; - renderer_flags &= ~SDL_RENDERER_PRESENTVSYNC; - - renderer = SDL_CreateRenderer(screen, -1, renderer_flags); - - // If this helped, save the setting for later. - if (renderer != NULL) - { - force_software_renderer = 1; - } - } + /* Open frame buffer */ - if (renderer == NULL) + g_graphics_state.fd = open(CONFIG_GAMES_NXDOOM_FBPATH, O_RDWR); + if (g_graphics_state.fd < 0) { - I_Error("Error creating renderer for screen window: %s", - SDL_GetError()); + i_error("Failed to open frame buffer: %d", errno); } - // Important: Set the "logical size" of the rendering context. At the same - // time this also defines the aspect ratio that is preserved while scaling - // and stretching the texture into the window. + /* Get frame buffer characteristics */ - if (aspect_ratio_correct || integer_scaling) + err = ioctl(g_graphics_state.fd, FBIOGET_VIDEOINFO, + (unsigned long)(uintptr_t)&g_graphics_state.vinfo); + if (err < 0) { - SDL_RenderSetLogicalSize(renderer, - SCREENWIDTH, - actualheight); + close(g_graphics_state.fd); + i_error("Failed to get video info: %d", errno); } - // Force integer scales for resolution-independent rendering. + /* Here, we check the dimensions of the frame buffer. If we have enough + * space to scale up the rendered image in both width and height, record + * that so we can make use of it elsewhere. + * + * If we don't have enough frame buffer space for the game, quit! + */ - SDL_RenderSetIntegerScale(renderer, integer_scaling); - - // Blank out the full screen area in case there is any junk in - // the borders that won't otherwise be overwritten. - - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - - // Create the 8-bit paletted and the 32-bit RGBA screenbuffer surfaces. - - if (screenbuffer != NULL) + if (g_graphics_state.vinfo.xres < SCREENWIDTH) { - SDL_FreeSurface(screenbuffer); - screenbuffer = NULL; + i_error("Resolution width of %u px < minimum of %u px\n", + g_graphics_state.vinfo.xres, SCREENWIDTH); } - if (screenbuffer == NULL) + if (g_graphics_state.vinfo.yres < SCREENHEIGHT) { - screenbuffer = SDL_CreateRGBSurface(0, - SCREENWIDTH, SCREENHEIGHT, 8, - 0, 0, 0, 0); - SDL_FillRect(screenbuffer, NULL, 0); + i_error("Resolution height of %u px < minimum of %u px\n", + g_graphics_state.vinfo.yres, SCREENHEIGHT); } - // Format of argbbuffer must match the screen pixel format because we - // import the surface data into the texture. - - if (argbbuffer != NULL) - { - SDL_FreeSurface(argbbuffer); - argbbuffer = NULL; - } - - if (argbbuffer == NULL) - { - // pixels and pitch will be filled with the texture's values - // in I_FinishUpdate() - argbbuffer = SDL_CreateRGBSurfaceWithFormatFrom( - NULL, w, h, 0, 0, SDL_PIXELFORMAT_ARGB8888); - } - - if (texture != NULL) - { - SDL_DestroyTexture(texture); - } - - // Set the scaling quality for rendering the intermediate texture into - // the upscaled texture to "nearest", which is gritty and pixelated and - // resembles software scaling pretty well. - - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + xscale = g_graphics_state.vinfo.xres / SCREENWIDTH; + yscale = g_graphics_state.vinfo.yres / SCREENHEIGHT; + g_graphics_state.scale = xscale > yscale ? yscale : xscale; - // Create the intermediate texture that the RGBA surface gets loaded into. - // The SDL_TEXTUREACCESS_STREAMING flag means that this texture's content - // is going to change frequently. + /* Get frame buffer plane info */ - texture = SDL_CreateTexture(renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - SCREENWIDTH, SCREENHEIGHT); - - // Workaround for SDL 2.0.14+ alt-tab bug (taken from Doom Retro via Prboom-plus and Woof) -#if defined(_WIN32) + if (ioctl(g_graphics_state.fd, FBIOGET_PLANEINFO, + (unsigned long)((uintptr_t)&g_graphics_state.pinfo)) < 0) { - SDL_version ver; - SDL_GetVersion(&ver); - if (ver.major == 2 && ver.minor == 0 && (ver.patch == 14 || ver.patch == 16)) - { - SDL_SetHintWithPriority(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1", SDL_HINT_OVERRIDE); - } + i_error("ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno); } -#endif - - // Initially create the upscaled texture for rendering to screen - CreateUpscaledTexture(true); -} + /* Initialize frame buffer memory for actual rendering */ -void I_InitGraphics(void) -{ - SDL_Event dummy; - byte *doompal; - char *env; - - // Pass through the XSCREENSAVER_WINDOW environment variable to - // SDL_WINDOWID, to embed the SDL window into the Xscreensaver - // window. - - env = getenv("XSCREENSAVER_WINDOW"); - - if (env != NULL) + g_graphics_state.fbmem = + mmap(NULL, g_graphics_state.pinfo.fblen, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FILE, g_graphics_state.fd, 0); + if (g_graphics_state.fbmem == MAP_FAILED) { - char winenv[30]; - unsigned int winid; - - sscanf(env, "0x%x", &winid); - M_snprintf(winenv, sizeof(winenv), "SDL_WINDOWID=%u", winid); - - putenv(winenv); + i_error("mmap() of frame buffer failed: %d\n", errno); } - SetSDLVideoDriver(); + /* Create an 8-bit depth screen buffer for DOOM to render to */ - if (SDL_Init(SDL_INIT_VIDEO) < 0) + g_graphics_state.scrnbuf = malloc(SCREENWIDTH * SCREENHEIGHT); + if (g_graphics_state.scrnbuf == NULL) { - I_Error("Failed to initialize video: %s", SDL_GetError()); + i_error("Couldn't allocate screen buffer: %d\n", errno); } - // When in screensaver mode, run full screen and auto detect - // screen dimensions (don't change video mode) - if (screensaver_mode) - { - fullscreen = true; - } - - if (aspect_ratio_correct == 1) - { - actualheight = SCREENHEIGHT_4_3; - } - else - { - actualheight = SCREENHEIGHT; - } + /* Create the game window; this may switch graphic modes depending + * on configuration. + * AdjustWindowSize(); + */ - // Create the game window; this may switch graphic modes depending - // on configuration. - AdjustWindowSize(); - SetVideoMode(); + set_video_mode(); - // Start with a clear black screen - // (screen will be flipped after we set the palette) + /* Start with a clear black screen + * (screen will be flipped after we set the palette) + */ - SDL_FillRect(screenbuffer, NULL, 0); + memset(g_graphics_state.scrnbuf, 0, SCREENHEIGHT * SCREENWIDTH); - // Set the palette + /* Set the palette */ - doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE); - I_SetPalette(doompal); - SDL_SetPaletteColors(screenbuffer->format->palette, palette, 0, 256); + doompal = w_cache_lump_name(("PLAYPAL"), PU_CACHE); + i_set_palette(doompal); - // SDL2-TODO UpdateFocus(); - UpdateGrab(); + update_grab(); - // On some systems, it takes a second or so for the screen to settle - // after changing modes. We include the option to add a delay when - // setting the screen mode, so that the game doesn't start immediately - // with the player unable to see anything. + /* On some systems, it takes a second or so for the screen to settle + * after changing modes. We include the option to add a delay when + * setting the screen mode, so that the game doesn't start immediately + * with the player unable to see anything. + */ - if (fullscreen && !screensaver_mode) + if (fullscreen && !screensaver_mode) { - SDL_Delay(startup_delay); + usleep(startup_delay * 1000); } - // The actual 320x200 canvas that we draw to. This is the pixel buffer of - // the 8-bit paletted screen buffer that gets blit on an intermediate - // 32-bit RGBA screen buffer that gets loaded into a texture that gets - // finally rendered into our window or full screen in I_FinishUpdate(). + /* The actual 320x200 canvas that we draw to. This is the pixel buffer of + * the 8-bit paletted screen buffer that gets blit on an intermediate + * 32-bit RGBA screen buffer that gets loaded into a texture that gets + * finally rendered into our window or full screen in i_finish_update(). + */ - I_VideoBuffer = screenbuffer->pixels; - V_RestoreBuffer(); + i_video_buffer = g_graphics_state.scrnbuf; + v_restore_buffer(); - // Clear the screen to black. + /* Clear the screen to black. */ - memset(I_VideoBuffer, 0, SCREENWIDTH * SCREENHEIGHT * sizeof(*I_VideoBuffer)); + memset(i_video_buffer, 0, + SCREENWIDTH * SCREENHEIGHT * sizeof(*i_video_buffer)); - // clear out any events waiting at the start and center the mouse - - while (SDL_PollEvent(&dummy)); + /* clear out any events waiting at the start and center the mouse */ - initialized = true; + g_graphics_state.inited = true; - // Call I_ShutdownGraphics on quit + /* Call i_shutdown_graphics on quit */ - I_AtExit(I_ShutdownGraphics, true); + i_at_exit(i_shutdown_graphics, true); } -// Bind all variables controlling video options into the configuration -// file system. -void I_BindVideoVariables(void) +/* Bind all variables controlling video options into the configuration + * file system. + */ + +void i_bind_video_variables(void) { - M_BindIntVariable("use_mouse", &usemouse); - M_BindIntVariable("fullscreen", &fullscreen); - M_BindIntVariable("video_display", &video_display); - M_BindIntVariable("aspect_ratio_correct", &aspect_ratio_correct); - M_BindIntVariable("integer_scaling", &integer_scaling); - M_BindIntVariable("smooth_pixel_scaling", &smooth_pixel_scaling); - M_BindIntVariable("vga_porch_flash", &vga_porch_flash); - M_BindIntVariable("startup_delay", &startup_delay); - M_BindIntVariable("fullscreen_width", &fullscreen_width); - M_BindIntVariable("fullscreen_height", &fullscreen_height); - M_BindIntVariable("force_software_renderer", &force_software_renderer); - M_BindIntVariable("max_scaling_buffer_pixels", &max_scaling_buffer_pixels); - M_BindIntVariable("window_width", &window_width); - M_BindIntVariable("window_height", &window_height); - M_BindIntVariable("grabmouse", &grabmouse); - M_BindStringVariable("video_driver", &video_driver); - M_BindStringVariable("window_position", &window_position); - M_BindIntVariable("usegamma", &usegamma); - M_BindIntVariable("png_screenshots", &png_screenshots); -} \ No newline at end of file + m_bind_int_variable("use_mouse", &usemouse); + m_bind_int_variable("fullscreen", &fullscreen); + m_bind_int_variable("video_display", &video_display); + m_bind_int_variable("integer_scaling", &integer_scaling); + m_bind_int_variable("smooth_pixel_scaling", &smooth_pixel_scaling); + m_bind_int_variable("vga_porch_flash", &vga_porch_flash); + m_bind_int_variable("startup_delay", &startup_delay); + m_bind_int_variable("fullscreen_width", &fullscreen_width); + m_bind_int_variable("fullscreen_height", &fullscreen_height); + m_bind_int_variable("force_software_renderer", &force_software_renderer); + m_bind_int_variable("max_scaling_buffer_pixels", + &max_scaling_buffer_pixels); + m_bind_int_variable("window_width", &window_width); + m_bind_int_variable("window_height", &window_height); + m_bind_int_variable("grabmouse", &grabmouse); + m_bind_string_variable("video_driver", &video_driver); + m_bind_string_variable("window_position", &window_position); + m_bind_int_variable("usegamma", &usegamma); + m_bind_int_variable("png_screenshots", &png_screenshots); +} diff --git a/games/NXDoom/src/i_video.h b/games/NXDoom/src/i_video.h index d98b8f5076e..322160f9bff 100644 --- a/games/NXDoom/src/i_video.h +++ b/games/NXDoom/src/i_video.h @@ -1,83 +1,57 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System specific interface stuff. -// - +/**************************************************************************** + * apps/games/NXDoom/src/i_video.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * System specific interface stuff. + * + ****************************************************************************/ #ifndef __I_VIDEO__ #define __I_VIDEO__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -// Screen width and height. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Screen width and height. */ -#define SCREENWIDTH 320 +#define SCREENWIDTH 320 #define SCREENHEIGHT 200 -// Screen height used when aspect_ratio_correct=true. +/* Screen height used when aspect_ratio_correct=true. */ #define SCREENHEIGHT_4_3 240 -typedef boolean (*grabmouse_callback_t)(void); - -// Called by D_DoomMain, -// determines the hardware configuration -// and sets up the video mode -void I_InitGraphics (void); - -void I_GraphicsCheckCommandLine(void); - -void I_ShutdownGraphics(void); - -// Takes full 8 bit values. -void I_SetPalette (byte* palette); -int I_GetPaletteIndex(int r, int g, int b); - -void I_UpdateNoBlit (void); -void I_FinishUpdate (void); - -void I_ReadScreen (pixel_t* scr); +/**************************************************************************** + * Public Types + ****************************************************************************/ -void I_BeginRead (void); - -void I_SetWindowTitle(const char *title); - -void I_CheckIsScreensaver(void); -void I_SetGrabMouseCallback(grabmouse_callback_t func); - -void I_DisplayFPSDots(boolean dots_on); -void I_BindVideoVariables(void); - -void I_InitWindowTitle(void); -void I_RegisterWindowIcon(const unsigned int *icon, int width, int height); -void I_InitWindowIcon(void); - -// Called before processing any tics in a frame (just after displaying a frame). -// Time consuming syncronous operations are performed here (joystick reading). - -void I_StartFrame (void); - -// Called before processing each tic in a frame. -// Quick syncronous operations are performed here. - -void I_StartTic (void); - -// Enable the loading disk image displayed when reading from disk. +typedef boolean (*grabmouse_callback_t)(void); -void I_EnableLoadingDisk(int xoffs, int yoffs); +/**************************************************************************** + * Public Data + ****************************************************************************/ extern char *video_driver; extern boolean screenvisible; @@ -85,7 +59,7 @@ extern boolean screenvisible; extern int vanilla_keyboard_mapping; extern boolean screensaver_mode; extern int usegamma; -extern pixel_t *I_VideoBuffer; +extern pixel_t *i_video_buffer; extern int screen_width; extern int screen_height; @@ -99,12 +73,82 @@ extern int force_software_renderer; extern int png_screenshots; extern char *window_position; -void I_GetWindowPosition(int *x, int *y, int w, int h); -// Joystic/gamepad hysteresis +/* Joystic/gamepad hysteresis */ + extern unsigned int joywait; extern int usemouse; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: i_init_graphics + * + * Description: + * Called by d_doom_main, determines the hardware configuration and sets up + * the video mode. + * + ****************************************************************************/ + +void i_init_graphics(void); + +void i_graphics_check_commandline(void); + +void i_shutdown_graphics(void); + +/**************************************************************************** + * Name: i_set_palette + * + * Description: + * Takes full 8 bit values. + * + ****************************************************************************/ + +void i_set_palette(byte *palette); + +int i_get_palette_index(int r, int g, int b); + +void i_update_no_blit(void); +void i_finish_update(void); + +void i_read_screen(pixel_t *scr); + +void i_set_window_title(const char *title); + +void i_check_is_screensaver(void); +void i_set_grab_mouse_callback(grabmouse_callback_t func); + +void i_display_fps_dots(boolean dots_on); +void i_bind_video_variables(void); + +void i_init_window_title(void); + +/**************************************************************************** + * Name: i_start_frame + * + * Description: + * Called before processing any tics in a frame (just after displaying a + * frame). Time consuming synchronous operations are performed here + * (joystick reading). + * + ****************************************************************************/ + +void i_start_frame(void); + +/**************************************************************************** + * Name: i_start_tic + * + * Description: + * Called before processing each tic in a frame. Quick synchronous + * operations are performed here. + * + ****************************************************************************/ + +void i_start_tic(void); + +void i_get_window_position(int *x, int *y, int w, int h); -#endif \ No newline at end of file +#endif /* __I_VIDEO__ */ diff --git a/games/NXDoom/src/i_videohr.c b/games/NXDoom/src/i_videohr.c deleted file mode 100644 index 08e23033677..00000000000 --- a/games/NXDoom/src/i_videohr.c +++ /dev/null @@ -1,257 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// SDL emulation of VGA 640x480x4 planar video mode, -// for Hexen startup loading screen. -// - -#include "SDL.h" -#include "string.h" - -#include "doomtype.h" -#include "i_timer.h" -#include "i_video.h" - -// Palette fade-in takes two seconds - -#define FADE_TIME 2000 - -#define HR_SCREENWIDTH 640 -#define HR_SCREENHEIGHT 480 - -static SDL_Window *hr_screen = NULL; -static SDL_Surface *hr_surface = NULL; -static const char *window_title = ""; - -boolean I_SetVideoModeHR(void) -{ - int x, y; - - if (SDL_Init(SDL_INIT_VIDEO) < 0) - { - return false; - } - - I_GetWindowPosition(&x, &y, HR_SCREENWIDTH, HR_SCREENHEIGHT); - - // Create screen surface at the native desktop pixel depth (bpp=0), - // as we cannot trust true 8-bit to reliably work nowadays. - hr_screen = SDL_CreateWindow(window_title, x, y, - HR_SCREENWIDTH, HR_SCREENHEIGHT, - 0); - - if (hr_screen == NULL) - { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - return false; - } - - // We do all actual drawing into an intermediate surface. - hr_surface = SDL_CreateRGBSurface(0, HR_SCREENWIDTH, HR_SCREENHEIGHT, - 8, 0, 0, 0, 0); - - return true; -} - -void I_SetWindowTitleHR(const char *title) -{ - window_title = title; -} - -void I_UnsetVideoModeHR(void) -{ - if (hr_screen != NULL) - { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - hr_screen = NULL; - SDL_FreeSurface(hr_surface); - hr_surface = NULL; - } -} - -void I_ClearScreenHR(void) -{ - SDL_Rect area = { 0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT }; - - SDL_FillRect(hr_surface, &area, 0); -} - -void I_SlamBlockHR(int x, int y, int w, int h, const byte *src) -{ - SDL_Rect blit_rect; - const byte *srcptrs[4]; - byte srcbits[4]; - byte *dest; - int x1, y1; - int i; - int bit; - - // Set up source pointers to read from source buffer - each 4-bit - // pixel has its bits split into four sub-buffers - - for (i=0; i<4; ++i) - { - srcptrs[i] = src + (i * w * h / 8); - } - - if (SDL_LockSurface(hr_surface) < 0) - { - return; - } - - // Draw each pixel - - bit = 0; - - for (y1=y; y1pixels) + y1 * hr_surface->pitch + x; - - for (x1=x; x1> (7 - (bit % 8))) & 0x1; - } - - // Reassemble the pixel value - - *dest = (srcbits[0] << 0) - | (srcbits[1] << 1) - | (srcbits[2] << 2) - | (srcbits[3] << 3); - - // Next pixel! - - ++dest; - ++bit; - } - } - - SDL_UnlockSurface(hr_surface); - - // Update the region we drew. - blit_rect.x = x; - blit_rect.y = y; - blit_rect.w = w; - blit_rect.h = h; - SDL_BlitSurface(hr_surface, &blit_rect, - SDL_GetWindowSurface(hr_screen), &blit_rect); - SDL_UpdateWindowSurfaceRects(hr_screen, &blit_rect, 1); -} - -void I_SlamHR(const byte *buffer) -{ - I_SlamBlockHR(0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT, buffer); -} - -void I_InitPaletteHR(void) -{ - // ... -} - -void I_SetPaletteHR(const byte *palette) -{ - SDL_Rect screen_rect = {0, 0, HR_SCREENWIDTH, HR_SCREENHEIGHT}; - SDL_Color sdlpal[16]; - int i; - - for (i=0; i<16; ++i) - { - sdlpal[i].r = palette[i * 3 + 0] * 4; - sdlpal[i].g = palette[i * 3 + 1] * 4; - sdlpal[i].b = palette[i * 3 + 2] * 4; - } - - // After setting colors, update the screen. - SDL_SetPaletteColors(hr_surface->format->palette, sdlpal, 0, 16); - SDL_BlitSurface(hr_surface, &screen_rect, - SDL_GetWindowSurface(hr_screen), &screen_rect); - SDL_UpdateWindowSurfaceRects(hr_screen, &screen_rect, 1); -} - -void I_FadeToPaletteHR(const byte *palette) -{ - byte tmppal[16 * 3]; - int starttime; - int elapsed; - int i; - - starttime = I_GetTimeMS(); - - for (;;) - { - elapsed = I_GetTimeMS() - starttime; - - if (elapsed >= FADE_TIME) - { - break; - } - - // Generate the fake palette - - for (i=0; i<16 * 3; ++i) - { - tmppal[i] = (palette[i] * elapsed) / FADE_TIME; - } - - I_SetPaletteHR(tmppal); - SDL_UpdateWindowSurface(hr_screen); - - // Sleep a bit - - I_Sleep(10); - } - - // Set the final palette - - I_SetPaletteHR(palette); -} - -void I_BlackPaletteHR(void) -{ - byte blackpal[16 * 3]; - - memset(blackpal, 0, sizeof(blackpal)); - - I_SetPaletteHR(blackpal); -} - -// Check if the user has hit the escape key to abort startup. -boolean I_CheckAbortHR(void) -{ - SDL_Event ev; - boolean result = false; - - // Not initialized? - if (hr_surface == NULL) - { - return false; - } - - while (SDL_PollEvent(&ev)) - { - if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE) - { - result = true; - } - } - - return result; -} - diff --git a/games/NXDoom/src/i_videohr.h b/games/NXDoom/src/i_videohr.h deleted file mode 100644 index d0a0dca501c..00000000000 --- a/games/NXDoom/src/i_videohr.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// SDL emulation of VGA 640x480x4 planar video mode, -// for Hexen startup loading screen. -// - -#ifndef I_VIDEOHR_H -#define I_VIDEOHR_H - -boolean I_SetVideoModeHR(void); -void I_UnsetVideoModeHR(void); -void I_SetWindowTitleHR(const char *title); -void I_ClearScreenHR(void); -void I_SlamBlockHR(int x, int y, int w, int h, const byte *src); -void I_SlamHR(const byte *buffer); -void I_InitPaletteHR(void); -void I_SetPaletteHR(const byte *palette); -void I_FadeToPaletteHR(const byte *palette); -void I_BlackPaletteHR(void); -boolean I_CheckAbortHR(void); - -#endif /* #ifndef I_VIDEOHR_H */ - diff --git a/games/NXDoom/src/i_winmusic.c b/games/NXDoom/src/i_winmusic.c deleted file mode 100644 index 6871fe22451..00000000000 --- a/games/NXDoom/src/i_winmusic.c +++ /dev/null @@ -1,1920 +0,0 @@ -// -// Copyright(C) 2021-2022 Roman Fomin -// Copyright(C) 2022 ceski -// -// 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. -// -// DESCRIPTION: -// Windows native MIDI - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include -#include -#include -#include - -#include "doomtype.h" -#include "i_sound.h" -#include "i_system.h" -#include "m_misc.h" -#include "memio.h" -#include "mus2mid.h" -#include "midifile.h" -#include "midifallback.h" - -enum -{ - COMP_VANILLA, - COMP_STANDARD, - COMP_FULL, -}; - -enum -{ - RESET_TYPE_NONE, - RESET_TYPE_GM, - RESET_TYPE_GS, - RESET_TYPE_XG, -}; - -char *winmm_midi_device = NULL; -int winmm_complevel = COMP_VANILLA; -int winmm_reset_type = RESET_TYPE_GM; -int winmm_reset_delay = 0; - -static const byte gm_system_on[] = { - 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 -}; - -static const byte gs_reset[] = { - 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7 -}; - -static const byte xg_system_on[] = { - 0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00, 0xF7 -}; - -static const byte ff_loopStart[] = {'l', 'o', 'o', 'p', 'S', 't', 'a', 'r', 't'}; -static const byte ff_loopEnd[] = {'l', 'o', 'o', 'p', 'E', 'n', 'd'}; - -static boolean use_fallback; - -#define DEFAULT_VOLUME 100 -static byte channel_volume[MIDI_CHANNELS_PER_TRACK]; -static float volume_factor = 0.0f; -static boolean update_volume = false; - -typedef enum -{ - STATE_STARTUP, - STATE_SHUTDOWN, - STATE_EXIT, - STATE_STOPPING, - STATE_STOPPED, - STATE_PLAYING, - STATE_PAUSED -} win_midi_state_t; - -static win_midi_state_t win_midi_state; - -static DWORD timediv; -static DWORD tempo; - -static UINT MidiDevice; -static HMIDISTRM hMidiStream; -static MIDIHDR MidiStreamHdr; -static HANDLE hBufferReturnEvent; -static HANDLE hStoppedEvent; -static HANDLE hPlayerThread; -static CRITICAL_SECTION CriticalSection; - -#define EMIDI_DEVICE (1U << EMIDI_DEVICE_GENERAL_MIDI) - -// This is a reduced Windows MIDIEVENT structure for MEVT_F_SHORT -// type of events. - -typedef struct -{ - DWORD dwDeltaTime; - DWORD dwStreamID; // always 0 - DWORD dwEvent; -} native_event_t; - -typedef struct -{ - midi_track_iter_t *iter; - unsigned int elapsed_time; - unsigned int saved_elapsed_time; - boolean end_of_track; - boolean saved_end_of_track; - unsigned int emidi_device_flags; - boolean emidi_designated; - boolean emidi_program; - boolean emidi_volume; - int emidi_loop_count; -} win_midi_track_t; - -typedef struct -{ - win_midi_track_t *tracks; - unsigned int elapsed_time; - unsigned int saved_elapsed_time; - unsigned int num_tracks; - boolean registered; - boolean looping; - boolean ff_loop; - boolean ff_restart; - boolean rpg_loop; -} win_midi_song_t; - -static win_midi_song_t song; - -#define BUFFER_INITIAL_SIZE 8192 - -#define PLAYER_THREAD_WAIT_TIME 3000 - -typedef struct -{ - byte *data; - unsigned int size; - unsigned int position; - boolean prepared; -} buffer_t; - -static buffer_t buffer; - -// Maximum of 4 events in the buffer for faster volume updates. - -#define STREAM_MAX_EVENTS 4 - -#define MAKE_EVT(a, b, c, d) \ - ((DWORD)(a) | ((DWORD)(b) << 8) | ((DWORD)(c) << 16) | ((DWORD)(d) << 24)) - -#define PADDED_SIZE(x) (((x) + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1)) - -// Check for midiStream errors. - -static void MidiError(const char *prefix, DWORD dwError) -{ - wchar_t werror[MAXERRORLENGTH]; - MMRESULT mmr; - - mmr = midiOutGetErrorTextW(dwError, (LPWSTR) werror, MAXERRORLENGTH); - if (mmr == MMSYSERR_NOERROR) - { - char *error = M_ConvertWideToUtf8(werror); - fprintf(stderr, "%s: %s.\n", prefix, error); - free(error); - } - else - { - fprintf(stderr, "%s: Unknown midiStream error.\n", prefix); - } -} - -// midiStream callback. - -static void CALLBACK MidiStreamProc(HMIDIOUT hMidi, UINT uMsg, - DWORD_PTR dwInstance, DWORD_PTR dwParam1, - DWORD_PTR dwParam2) -{ - if (uMsg == MOM_DONE) - { - SetEvent(hBufferReturnEvent); - } -} - -// Unprepare MIDI header. The calling thread must have exclusive access to the -// shared resources in this function. - -static void UnprepareHeader(void) -{ - // Avoid ASan detection. Commentary by Microsoft: "It looks like - // midiOutPrepareHeader() allocates with HeapAlloc(), and then - // midiOutUnprepareHeader() deallocates with GlobalFree(GlobalHandle - // (...)). By design, this kind of allocator mismatch is an issue that ASan - // is designed to catch. It is theoretically possible for us to support - // this kind of code, but it’s not very high priority since it is undefined - // behavior, though it happens to work right now outside of ASan." - // https://developercommunity.visualstudio.com/t/1597288 - -#ifndef __SANITIZE_ADDRESS__ - MIDIHDR *hdr = &MidiStreamHdr; - MMRESULT mmr; - - mmr = midiOutUnprepareHeader((HMIDIOUT)hMidiStream, hdr, sizeof(MIDIHDR)); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiOutUnprepareHeader", mmr); - } -#endif -} - -// Allocate buffer. The calling thread must have exclusive access to the shared -// resources in this function. - -static void AllocateBuffer(const unsigned int size) -{ - buffer.size = PADDED_SIZE(size); - buffer.data = I_Realloc(buffer.data, buffer.size); -} - -// Pads the buffer with zeros so that an integral number of DWORDs are stored. -// Required for long messages (SysEx). Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static void WriteBufferPad(void) -{ - unsigned int padding = PADDED_SIZE(buffer.position); - memset(buffer.data + buffer.position, 0, padding - buffer.position); - buffer.position = padding; -} - -// Writes message data to buffer. Call this function from the MIDI thread only, -// with exclusive access to shared resources. - -static void WriteBuffer(const byte *ptr, unsigned int size) -{ - if (buffer.prepared) - { - UnprepareHeader(); - buffer.prepared = false; - } - - if (buffer.position + size >= buffer.size) - { - AllocateBuffer(size + buffer.size * 2); - } - - memcpy(buffer.data + buffer.position, ptr, size); - buffer.position += size; -} - -// Streams out the current buffer. Call this function from the MIDI thread only, -// with exclusive access to shared resources. - -static void StreamOut(void) -{ - MIDIHDR *hdr = &MidiStreamHdr; - MMRESULT mmr; - - memset(hdr, 0, sizeof(*hdr)); - hdr->lpData = (LPSTR)buffer.data; - hdr->dwBytesRecorded = buffer.position; - hdr->dwBufferLength = buffer.size; - - // Reset buffer position even if midiStreamOut fails. - buffer.position = 0; - - mmr = midiOutPrepareHeader((HMIDIOUT)hMidiStream, hdr, sizeof(MIDIHDR)); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiOutPrepareHeader", mmr); - return; - } - - buffer.prepared = true; - - mmr = midiStreamOut(hMidiStream, hdr, sizeof(MIDIHDR)); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamOut", mmr); - } -} - -// Writes a short MIDI message. Call this function from the MIDI thread only, -// with exclusive access to shared resources. - -static void SendShortMsg(unsigned int delta_time, byte status, byte channel, - byte param1, byte param2) -{ - native_event_t native_event; - native_event.dwDeltaTime = delta_time; - native_event.dwStreamID = 0; - native_event.dwEvent = MAKE_EVT(status | channel, param1, param2, MEVT_SHORTMSG); - WriteBuffer((byte *)&native_event, sizeof(native_event_t)); -} - -// Writes a short MIDI message (from an event). Call this function from the MIDI -// thread only, with exclusive access to shared resources. - -static void SendChannelMsg(unsigned int delta_time, const midi_event_t *event, - boolean use_param2) -{ - SendShortMsg(delta_time, event->event_type, event->data.channel.channel, - event->data.channel.param1, - use_param2 ? event->data.channel.param2 : 0); -} - -// Writes a long MIDI message (SysEx). Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static void SendLongMsg(unsigned int delta_time, const byte *ptr, - unsigned int length) -{ - native_event_t native_event; - native_event.dwDeltaTime = delta_time; - native_event.dwStreamID = 0; - native_event.dwEvent = MAKE_EVT(length, 0, 0, MEVT_LONGMSG); - WriteBuffer((byte *)&native_event, sizeof(native_event_t)); - WriteBuffer(ptr, length); - WriteBufferPad(); -} - -// Writes an RPN message set to NULL (0x7F). Prevents accidental data entry. -// Call this function from the MIDI thread only, with exclusive access to shared -// resources. - -static void SendNullRPN(unsigned int delta_time, const midi_event_t *event) -{ - const byte channel = event->data.channel.channel; - SendShortMsg(delta_time, MIDI_EVENT_CONTROLLER, channel, - MIDI_CONTROLLER_RPN_LSB, MIDI_RPN_NULL); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, channel, - MIDI_CONTROLLER_RPN_MSB, MIDI_RPN_NULL); -} - -// Writes a NOP message (ticks). Call this function from the MIDI thread only, -// with exclusive access to shared resources. - -static void SendNOPMsg(unsigned int delta_time) -{ - native_event_t native_event; - native_event.dwDeltaTime = delta_time; - native_event.dwStreamID = 0; - native_event.dwEvent = MAKE_EVT(0, 0, 0, MEVT_NOP); - WriteBuffer((byte *)&native_event, sizeof(native_event_t)); -} - -// Writes a NOP message (milliseconds). Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static void SendDelayMsg(unsigned int time_ms) -{ - // Convert ms to ticks (see "Standard MIDI Files 1.0" page 14). - const unsigned int ticks = (float) time_ms * 1000 * timediv / tempo + 0.5f; - SendNOPMsg(ticks); -} - -// Writes a tempo MIDI meta message. Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static void UpdateTempo(unsigned int delta_time, const midi_event_t *event) -{ - native_event_t native_event; - - tempo = MAKE_EVT(event->data.meta.data[2], event->data.meta.data[1], - event->data.meta.data[0], 0); - - native_event.dwDeltaTime = delta_time; - native_event.dwStreamID = 0; - native_event.dwEvent = MAKE_EVT(tempo, 0, 0, MEVT_TEMPO); - WriteBuffer((byte *)&native_event, sizeof(native_event_t)); -} - -// Writes a MIDI volume message. The value is scaled by the volume slider. Call -// this function from the MIDI thread only, with exclusive access to shared -// resources. - -static void SendManualVolumeMsg(unsigned int delta_time, byte channel, - byte volume) -{ - unsigned int scaled_volume; - - scaled_volume = volume * volume_factor + 0.5f; - - if (scaled_volume > 127) - { - scaled_volume = 127; - } - - SendShortMsg(delta_time, MIDI_EVENT_CONTROLLER, channel, - MIDI_CONTROLLER_VOLUME_MSB, scaled_volume); - - channel_volume[channel] = volume; -} - -// Writes a MIDI volume message (from an event). The value is scaled by the -// volume slider. Call this function from the MIDI thread only, with exclusive -// access to shared resources. - -static void SendVolumeMsg(unsigned int delta_time, const midi_event_t *event) -{ - SendManualVolumeMsg(delta_time, event->data.channel.channel, - event->data.channel.param2); -} - -// Sets each channel to its saved volume level, scaled by the volume slider. -// Call this function from the MIDI thread only, with exclusive access to shared -// resources. - -static void UpdateVolume(void) -{ - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - SendManualVolumeMsg(0, i, channel_volume[i]); - } -} - -// Sets each channel to the default volume level, scaled by the volume slider. -// Call this function from the MIDI thread only, with exclusive access to shared -// resources. - -static void ResetVolume(void) -{ - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - SendManualVolumeMsg(0, i, DEFAULT_VOLUME); - } -} - -// Writes "notes off" and "sound off" messages for each channel. Some devices -// may support only one or the other. Held notes (sustained, etc.) are released -// to prevent hanging notes. Call this function from the MIDI thread only, with -// exclusive access to shared resources. - -static void SendNotesSoundOff(void) -{ - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_NOTES_OFF, 0); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_SOUND_OFF, 0); - } -} - -// Resets commonly used controllers. This is only for a reset type of "none" for -// devices that don't support SysEx resets. Call this function from the MIDI -// thread only, with exclusive access to shared resources. - -static void ResetControllers(void) -{ - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - // Reset commonly used controllers. - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RESET_ALL_CTRLS, 0); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_PAN, 64); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_BANK_SELECT_MSB, 0); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_BANK_SELECT_LSB, 0); - SendShortMsg(0, MIDI_EVENT_PROGRAM_CHANGE, i, 0, 0); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_REVERB, 40); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_CHORUS, 0); - } -} - -// Resets the pitch bend sensitivity for each channel. This must be sent during -// a reset due to an MS GS Wavetable Synth bug. Call this function from the MIDI -// thread only, with exclusive access to shared resources. - -static void ResetPitchBendSensitivity(void) -{ - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - // Set RPN MSB/LSB to pitch bend sensitivity. - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_LSB, 0); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_MSB, 0); - - // Reset pitch bend sensitivity to +/- 2 semitones and 0 cents. - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_DATA_ENTRY_MSB, 2); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_DATA_ENTRY_LSB, 0); - - // Set RPN MSB/LSB to null value after data entry. - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_LSB, 127); - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RPN_MSB, 127); - } -} - -// Resets the MIDI device. Call this function before each song starts and once -// at shut down. Call this function from the MIDI thread only, with exclusive -// access to shared resources. - -static void ResetDevice(void) -{ - MIDI_ResetFallback(); - use_fallback = false; - - switch (winmm_reset_type) - { - case RESET_TYPE_NONE: - ResetControllers(); - break; - - case RESET_TYPE_GS: - SendLongMsg(0, gs_reset, sizeof(gs_reset)); - use_fallback = (winmm_complevel != COMP_VANILLA); - break; - - case RESET_TYPE_XG: - SendLongMsg(0, xg_system_on, sizeof(xg_system_on)); - break; - - default: - SendLongMsg(0, gm_system_on, sizeof(gm_system_on)); - break; - } - - // MS GS Wavetable Synth doesn't reset pitch bend sensitivity. - ResetPitchBendSensitivity(); - - // Reset volume (initial playback or on shutdown if no SysEx reset). - // Scale by slider on initial playback, max on shutdown. - if (win_midi_state == STATE_STARTUP) - { - ResetVolume(); - } - else if (winmm_reset_type == RESET_TYPE_NONE) - { - volume_factor = 1.0f; - ResetVolume(); - } - - // Send delay after reset. This is for hardware devices only (e.g. SC-55). - if (winmm_reset_delay > 0) - { - SendDelayMsg(winmm_reset_delay); - } -} - -// Normally, volume is controlled by channel volume messages. Roland defined a -// special SysEx message called "part level" that is equivalent to this. MS GS -// Wavetable Synth ignores these messages, but other MIDI devices support them. -// Returns true if there is a match. Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static boolean IsPartLevel(const byte *msg, unsigned int length) -{ - if (length == 10 && - msg[0] == 0x41 && // Roland - msg[2] == 0x42 && // GS - msg[3] == 0x12 && // DT1 - msg[4] == 0x40 && // Address MSB - msg[5] >= 0x10 && // Address - msg[5] <= 0x1F && // Address - msg[6] == 0x19 && // Address LSB - msg[9] == 0xF7) // SysEx EOX - { - const byte checksum = - 128 - ((int) msg[4] + msg[5] + msg[6] + msg[7]) % 128; - - if (msg[8] == checksum) - { - // GS Part Level (aka Channel Volume) - // 41 42 12 40 19 F7 - return true; - } - } - - return false; -} - -// Checks if the current SysEx message matches any known SysEx reset message. -// Returns true if there is a match. Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static boolean IsSysExReset(const byte *msg, unsigned int length) -{ - if (length < 5) - { - return false; - } - - switch (msg[0]) - { - case 0x41: // Roland - switch (msg[2]) - { - case 0x42: // GS - switch (msg[3]) - { - case 0x12: // DT1 - if (length == 10 && - msg[4] == 0x00 && // Address MSB - msg[5] == 0x00 && // Address - msg[6] == 0x7F && // Address LSB - ((msg[7] == 0x00 && // Data (MODE-1) - msg[8] == 0x01) || // Checksum (MODE-1) - (msg[7] == 0x01 && // Data (MODE-2) - msg[8] == 0x00))) // Checksum (MODE-2) - { - // SC-88 System Mode Set - // 41 42 12 00 00 7F 00 01 F7 (MODE-1) - // 41 42 12 00 00 7F 01 00 F7 (MODE-2) - return true; - } - else if (length == 10 && - msg[4] == 0x40 && // Address MSB - msg[5] == 0x00 && // Address - msg[6] == 0x7F && // Address LSB - msg[7] == 0x00 && // Data (GS Reset) - msg[8] == 0x41) // Checksum - { - // GS Reset - // 41 42 12 40 00 7F 00 41 F7 - return true; - } - break; - } - break; - } - break; - - case 0x43: // Yamaha - switch (msg[2]) - { - case 0x2B: // TG300 - if (length == 9 && - msg[3] == 0x00 && // Start Address b20 - b14 - msg[4] == 0x00 && // Start Address b13 - b7 - msg[5] == 0x7F && // Start Address b6 - b0 - msg[6] == 0x00 && // Data - msg[7] == 0x01) // Checksum - { - // TG300 All Parameter Reset - // 43 2B 00 00 7F 00 01 F7 - return true; - } - break; - - case 0x4C: // XG - if (length == 8 && - msg[3] == 0x00 && // Address High - msg[4] == 0x00 && // Address Mid - (msg[5] == 0x7E || // Address Low (System On) - msg[5] == 0x7F) && // Address Low (All Parameter Reset) - msg[6] == 0x00) // Data - { - // XG System On, XG All Parameter Reset - // 43 4C 00 00 7E 00 F7 - // 43 4C 00 00 7F 00 F7 - return true; - } - break; - } - break; - - case 0x7E: // Universal Non-Real Time - switch (msg[2]) - { - case 0x09: // General Midi - if (length == 5 && - (msg[3] == 0x01 || // GM System On - msg[3] == 0x02 || // GM System Off - msg[3] == 0x03)) // GM2 System On - { - // GM System On/Off, GM2 System On - // 7E 09 01 F7 - // 7E 09 02 F7 - // 7E 09 03 F7 - return true; - } - break; - } - break; - } - return false; -} - -// Writes a MIDI SysEx message. Call this function from the MIDI thread only, -// with exclusive access to shared resources. - -static void SendSysExMsg(unsigned int delta_time, const midi_event_t *event) -{ - native_event_t native_event; - const byte event_type = MIDI_EVENT_SYSEX; - const byte *data = event->data.sysex.data; - const unsigned int length = event->data.sysex.length; - - if (IsPartLevel(data, length)) - { - byte channel; - - // Convert "block number" to a channel number. - if (data[5] == 0x10) // Channel 10 - { - channel = 9; - } - else if (data[5] < 0x1A) // Channels 1-9 - { - channel = (data[5] & 0x0F) - 1; - } - else // Channels 11-16 - { - channel = data[5] & 0x0F; - } - - // Replace SysEx part level message with channel volume message. - SendManualVolumeMsg(delta_time, channel, data[7]); - return; - } - - // Send the SysEx message. - native_event.dwDeltaTime = delta_time; - native_event.dwStreamID = 0; - native_event.dwEvent = MAKE_EVT(length + sizeof(byte), 0, 0, MEVT_LONGMSG); - WriteBuffer((byte *)&native_event, sizeof(native_event_t)); - WriteBuffer(&event_type, sizeof(byte)); - WriteBuffer(data, length); - WriteBufferPad(); - - if (IsSysExReset(data, length)) - { - // SysEx reset also resets volume. Take the default channel volumes - // and scale them by the user's volume slider. - ResetVolume(); - - // Disable instrument fallback and give priority to MIDI file. Fallback - // assumes GS (SC-55 level) and the MIDI file could be GM, GM2, XG, or - // GS (SC-88 or higher). Preserve the composer's intent. - if (use_fallback) - { - MIDI_ResetFallback(); - use_fallback = false; - } - } -} - -// Writes a MIDI program change message. If applicable, emulates capital tone -// fallback to fix invalid instruments. Call this function from the MIDI thread -// only, with exclusive access to shared resources. - -static void SendProgramMsg(unsigned int delta_time, byte channel, byte program, - const midi_fallback_t *fallback) -{ - switch ((int)fallback->type) - { - case FALLBACK_BANK_MSB: - SendShortMsg(delta_time, MIDI_EVENT_CONTROLLER, channel, - MIDI_CONTROLLER_BANK_SELECT_MSB, fallback->value); - SendShortMsg(0, MIDI_EVENT_PROGRAM_CHANGE, channel, program, 0); - break; - - case FALLBACK_DRUMS: - SendShortMsg(delta_time, MIDI_EVENT_PROGRAM_CHANGE, channel, - fallback->value, 0); - break; - - default: - SendShortMsg(delta_time, MIDI_EVENT_PROGRAM_CHANGE, channel, - program, 0); - break; - } -} - -// Sets a Final Fantasy or RPG Maker loop point. Call this function from the -// MIDI thread only, with exclusive access to shared resources. - -static void SetLoopPoint(void) -{ - unsigned int i; - - for (i = 0; i < song.num_tracks; ++i) - { - MIDI_SetLoopPoint(song.tracks[i].iter); - song.tracks[i].saved_end_of_track = song.tracks[i].end_of_track; - song.tracks[i].saved_elapsed_time = song.tracks[i].elapsed_time; - } - song.saved_elapsed_time = song.elapsed_time; -} - -// Checks if the MIDI meta message contains a Final Fantasy loop marker. Call -// this function from the MIDI thread only, with exclusive access to shared -// resources. - -static void CheckFFLoop(const midi_event_t *event) -{ - if (event->data.meta.length == sizeof(ff_loopStart) && - !memcmp(event->data.meta.data, ff_loopStart, sizeof(ff_loopStart))) - { - SetLoopPoint(); - song.ff_loop = true; - } - else if (song.ff_loop && event->data.meta.length == sizeof(ff_loopEnd) && - !memcmp(event->data.meta.data, ff_loopEnd, sizeof(ff_loopEnd))) - { - song.ff_restart = true; - } -} - -// Writes an EMIDI message. Call this function from the MIDI thread only, with -// exclusive access to shared resources. - -static void SendEMIDI(unsigned int delta_time, const midi_event_t *event, - win_midi_track_t *track, const midi_fallback_t *fallback) -{ - unsigned int i; - unsigned int flag; - int count; - - switch (event->data.channel.param1) - { - case EMIDI_CONTROLLER_TRACK_DESIGNATION: - if (track->elapsed_time < timediv) - { - flag = event->data.channel.param2; - - if (flag == EMIDI_DEVICE_ALL) - { - track->emidi_device_flags = UINT_MAX; - track->emidi_designated = true; - } - else if (flag <= EMIDI_DEVICE_ULTRASOUND) - { - track->emidi_device_flags |= 1U << flag; - track->emidi_designated = true; - } - } - SendNOPMsg(delta_time); - break; - - case EMIDI_CONTROLLER_TRACK_EXCLUSION: - if (song.rpg_loop) - { - SetLoopPoint(); - } - else if (track->elapsed_time < timediv) - { - flag = event->data.channel.param2; - - if (!track->emidi_designated) - { - track->emidi_device_flags = UINT_MAX; - track->emidi_designated = true; - } - - if (flag <= EMIDI_DEVICE_ULTRASOUND) - { - track->emidi_device_flags &= ~(1U << flag); - } - } - SendNOPMsg(delta_time); - break; - - case EMIDI_CONTROLLER_PROGRAM_CHANGE: - if (track->emidi_program || track->elapsed_time < timediv) - { - track->emidi_program = true; - SendProgramMsg(delta_time, event->data.channel.channel, - event->data.channel.param2, fallback); - } - else - { - SendNOPMsg(delta_time); - } - break; - - case EMIDI_CONTROLLER_VOLUME: - if (track->emidi_volume || track->elapsed_time < timediv) - { - track->emidi_volume = true; - SendVolumeMsg(delta_time, event); - } - else - { - SendNOPMsg(delta_time); - } - break; - - case EMIDI_CONTROLLER_LOOP_BEGIN: - count = event->data.channel.param2; - count = (count == 0) ? (-1) : count; - track->emidi_loop_count = count; - MIDI_SetLoopPoint(track->iter); - SendNOPMsg(delta_time); - break; - - case EMIDI_CONTROLLER_LOOP_END: - if (event->data.channel.param2 == EMIDI_LOOP_FLAG) - { - if (track->emidi_loop_count != 0) - { - MIDI_RestartAtLoopPoint(track->iter); - } - - if (track->emidi_loop_count > 0) - { - track->emidi_loop_count--; - } - } - SendNOPMsg(delta_time); - break; - - case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: - count = event->data.channel.param2; - count = (count == 0) ? (-1) : count; - for (i = 0; i < song.num_tracks; ++i) - { - song.tracks[i].emidi_loop_count = count; - MIDI_SetLoopPoint(song.tracks[i].iter); - song.tracks[i].saved_end_of_track = song.tracks[i].end_of_track; - song.tracks[i].saved_elapsed_time = song.tracks[i].elapsed_time; - } - song.saved_elapsed_time = song.elapsed_time; - SendNOPMsg(delta_time); - break; - - case EMIDI_CONTROLLER_GLOBAL_LOOP_END: - if (event->data.channel.param2 == EMIDI_LOOP_FLAG) - { - for (i = 0; i < song.num_tracks; ++i) - { - if (song.tracks[i].emidi_loop_count != 0) - { - MIDI_RestartAtLoopPoint(song.tracks[i].iter); - song.tracks[i].end_of_track = - song.tracks[i].saved_end_of_track; - song.tracks[i].elapsed_time = - song.tracks[i].saved_elapsed_time; - song.elapsed_time = song.saved_elapsed_time; - } - - if (song.tracks[i].emidi_loop_count > 0) - { - song.tracks[i].emidi_loop_count--; - } - } - } - SendNOPMsg(delta_time); - break; - } -} - -// Writes a MIDI meta message. Call this function from the MIDI thread only, -// with exclusive access to shared resources. - -static void SendMetaMsg(unsigned int delta_time, const midi_event_t *event, - win_midi_track_t *track) -{ - switch (event->data.meta.type) - { - case MIDI_META_END_OF_TRACK: - track->end_of_track = true; - SendNOPMsg(delta_time); - break; - - case MIDI_META_SET_TEMPO: - UpdateTempo(delta_time, event); - break; - - case MIDI_META_MARKER: - if (winmm_complevel != COMP_VANILLA) - { - CheckFFLoop(event); - } - SendNOPMsg(delta_time); - break; - - default: - SendNOPMsg(delta_time); - break; - } -} - -// AddToBuffer function for vanilla (DMX MPU-401) compatibility level. Do not -// call this function directly. See the AddToBuffer function pointer. - -static boolean AddToBuffer_Vanilla(unsigned int delta_time, - const midi_event_t *event, - win_midi_track_t *track) -{ - switch ((int) event->event_type) - { - case MIDI_EVENT_SYSEX: - SendNOPMsg(delta_time); - return false; - - case MIDI_EVENT_META: - SendMetaMsg(delta_time, event, track); - break; - - case MIDI_EVENT_CONTROLLER: - switch (event->data.channel.param1) - { - case MIDI_CONTROLLER_BANK_SELECT_MSB: - case MIDI_CONTROLLER_BANK_SELECT_LSB: - // DMX has broken bank select support and runs in GM mode. - SendChannelMsg(delta_time, event, false); - break; - - case MIDI_CONTROLLER_MODULATION: - case MIDI_CONTROLLER_PAN: - case MIDI_CONTROLLER_EXPRESSION: - case MIDI_CONTROLLER_HOLD1_PEDAL: - case MIDI_CONTROLLER_SOFT_PEDAL: - case MIDI_CONTROLLER_REVERB: - case MIDI_CONTROLLER_CHORUS: - case MIDI_CONTROLLER_ALL_SOUND_OFF: - case MIDI_CONTROLLER_ALL_NOTES_OFF: - SendChannelMsg(delta_time, event, true); - break; - - case MIDI_CONTROLLER_VOLUME_MSB: - SendVolumeMsg(delta_time, event); - break; - - case MIDI_CONTROLLER_RESET_ALL_CTRLS: - // MS GS Wavetable Synth resets volume if param2 isn't zero. - SendChannelMsg(delta_time, event, false); - break; - - default: - SendNOPMsg(delta_time); - break; - } - break; - - case MIDI_EVENT_NOTE_OFF: - case MIDI_EVENT_NOTE_ON: - case MIDI_EVENT_PITCH_BEND: - SendChannelMsg(delta_time, event, true); - break; - - case MIDI_EVENT_PROGRAM_CHANGE: - SendChannelMsg(delta_time, event, false); - break; - - default: - SendNOPMsg(delta_time); - break; - } - - return true; -} - -// AddToBuffer function for standard and full MIDI compatibility levels. Do not -// call this function directly. See the AddToBuffer function pointer. - -static boolean AddToBuffer_Standard(unsigned int delta_time, - const midi_event_t *event, - win_midi_track_t *track) -{ - midi_fallback_t fallback = {FALLBACK_NONE, 0}; - - if (use_fallback) - { - MIDI_CheckFallback(event, &fallback, winmm_complevel == COMP_FULL); - } - - switch ((int) event->event_type) - { - case MIDI_EVENT_SYSEX: - if (winmm_complevel == COMP_FULL) - { - SendSysExMsg(delta_time, event); - } - else - { - SendNOPMsg(delta_time); - } - return false; - - case MIDI_EVENT_META: - SendMetaMsg(delta_time, event, track); - return true; - } - - if (track->emidi_designated && (EMIDI_DEVICE & ~track->emidi_device_flags)) - { - // Send NOP if this device has been excluded from this track. - SendNOPMsg(delta_time); - return true; - } - - switch ((int) event->event_type) - { - case MIDI_EVENT_CONTROLLER: - switch (event->data.channel.param1) - { - case MIDI_CONTROLLER_BANK_SELECT_MSB: - case MIDI_CONTROLLER_MODULATION: - case MIDI_CONTROLLER_DATA_ENTRY_MSB: - case MIDI_CONTROLLER_PAN: - case MIDI_CONTROLLER_EXPRESSION: - case MIDI_CONTROLLER_DATA_ENTRY_LSB: - case MIDI_CONTROLLER_HOLD1_PEDAL: - case MIDI_CONTROLLER_SOFT_PEDAL: - case MIDI_CONTROLLER_REVERB: - case MIDI_CONTROLLER_CHORUS: - case MIDI_CONTROLLER_ALL_SOUND_OFF: - case MIDI_CONTROLLER_ALL_NOTES_OFF: - case MIDI_CONTROLLER_POLY_MODE_OFF: - case MIDI_CONTROLLER_POLY_MODE_ON: - SendChannelMsg(delta_time, event, true); - break; - - case MIDI_CONTROLLER_VOLUME_MSB: - if (track->emidi_volume) - { - SendNOPMsg(delta_time); - } - else - { - SendVolumeMsg(delta_time, event); - } - break; - - case MIDI_CONTROLLER_VOLUME_LSB: - SendNOPMsg(delta_time); - break; - - case MIDI_CONTROLLER_BANK_SELECT_LSB: - SendChannelMsg(delta_time, event, - fallback.type != FALLBACK_BANK_LSB); - break; - - case MIDI_CONTROLLER_NRPN_LSB: - case MIDI_CONTROLLER_NRPN_MSB: - if (winmm_complevel == COMP_FULL) - { - SendChannelMsg(delta_time, event, true); - } - else - { - // MS GS Wavetable Synth nulls RPN for any NRPN. - SendNullRPN(delta_time, event); - } - break; - - case MIDI_CONTROLLER_RPN_LSB: - switch (event->data.channel.param2) - { - case MIDI_RPN_PITCH_BEND_SENS_LSB: - case MIDI_RPN_FINE_TUNING_LSB: - case MIDI_RPN_COARSE_TUNING_LSB: - case MIDI_RPN_NULL: - SendChannelMsg(delta_time, event, true); - break; - - default: - if (winmm_complevel == COMP_FULL) - { - SendChannelMsg(delta_time, event, true); - } - else - { - // MS GS Wavetable Synth ignores other RPNs. - SendNullRPN(delta_time, event); - } - break; - } - break; - - case MIDI_CONTROLLER_RPN_MSB: - switch (event->data.channel.param2) - { - case MIDI_RPN_MSB: - case MIDI_RPN_NULL: - SendChannelMsg(delta_time, event, true); - break; - - default: - if (winmm_complevel == COMP_FULL) - { - SendChannelMsg(delta_time, event, true); - } - else - { - // MS GS Wavetable Synth ignores other RPNs. - SendNullRPN(delta_time, event); - } - break; - } - break; - - case EMIDI_CONTROLLER_TRACK_DESIGNATION: - case EMIDI_CONTROLLER_TRACK_EXCLUSION: - case EMIDI_CONTROLLER_PROGRAM_CHANGE: - case EMIDI_CONTROLLER_VOLUME: - case EMIDI_CONTROLLER_LOOP_BEGIN: - case EMIDI_CONTROLLER_LOOP_END: - case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: - case EMIDI_CONTROLLER_GLOBAL_LOOP_END: - SendEMIDI(delta_time, event, track, &fallback); - break; - - case MIDI_CONTROLLER_RESET_ALL_CTRLS: - // MS GS Wavetable Synth resets volume if param2 isn't zero. - SendChannelMsg(delta_time, event, false); - break; - - default: - if (winmm_complevel == COMP_FULL) - { - SendChannelMsg(delta_time, event, true); - } - else - { - SendNOPMsg(delta_time); - } - break; - } - break; - - case MIDI_EVENT_NOTE_OFF: - case MIDI_EVENT_NOTE_ON: - case MIDI_EVENT_PITCH_BEND: - SendChannelMsg(delta_time, event, true); - break; - - case MIDI_EVENT_PROGRAM_CHANGE: - if (track->emidi_program) - { - SendNOPMsg(delta_time); - } - else - { - SendProgramMsg(delta_time, event->data.channel.channel, - event->data.channel.param1, &fallback); - } - break; - - case MIDI_EVENT_AFTERTOUCH: - if (winmm_complevel == COMP_FULL) - { - SendChannelMsg(delta_time, event, true); - } - else - { - SendNOPMsg(delta_time); - } - break; - - case MIDI_EVENT_CHAN_AFTERTOUCH: - if (winmm_complevel == COMP_FULL) - { - SendChannelMsg(delta_time, event, false); - } - else - { - SendNOPMsg(delta_time); - } - break; - - default: - SendNOPMsg(delta_time); - break; - } - - return true; -} - -// Function pointer determined by the desired MIDI compatibility level. Set -// during initialization by the main thread, then called from the MIDI thread -// only. The calling thread must have exclusive access to the shared resources -// in this function. - -static boolean (*AddToBuffer)(unsigned int delta_time, - const midi_event_t *event, - win_midi_track_t *track) = AddToBuffer_Vanilla; - -// Restarts a song that uses a Final Fantasy or RPG Maker loop point. Call this -// function from the MIDI thread only, with exclusive access to shared -// resources. - -static void RestartLoop(void) -{ - unsigned int i; - - for (i = 0; i < song.num_tracks; ++i) - { - MIDI_RestartAtLoopPoint(song.tracks[i].iter); - song.tracks[i].end_of_track = song.tracks[i].saved_end_of_track; - song.tracks[i].elapsed_time = song.tracks[i].saved_elapsed_time; - } - song.elapsed_time = song.saved_elapsed_time; -} - -// Restarts a song that uses standard looping. Call this function from the MIDI -// thread only, with exclusive access to shared resources. - -static void RestartTracks(void) -{ - unsigned int i; - - for (i = 0; i < song.num_tracks; ++i) - { - MIDI_RestartIterator(song.tracks[i].iter); - song.tracks[i].elapsed_time = 0; - song.tracks[i].end_of_track = false; - song.tracks[i].emidi_device_flags = 0; - song.tracks[i].emidi_designated = false; - song.tracks[i].emidi_program = false; - song.tracks[i].emidi_volume = false; - song.tracks[i].emidi_loop_count = 0; - } - song.elapsed_time = 0; -} - -// The controllers "EMIDI track exclusion" and "RPG Maker loop point" share the -// same number (CC#111) and are not compatible with each other. As a workaround, -// allow an RPG Maker loop point only if no other EMIDI events are present. Call -// this function from the MIDI thread only, before the song starts, with -// exclusive access to shared resources. - -static boolean IsRPGLoop(void) -{ - unsigned int i; - unsigned int num_rpg_events = 0; - unsigned int num_emidi_events = 0; - midi_event_t *event = NULL; - - for (i = 0; i < song.num_tracks; ++i) - { - while (MIDI_GetNextEvent(song.tracks[i].iter, &event)) - { - if (event->event_type == MIDI_EVENT_CONTROLLER) - { - switch (event->data.channel.param1) - { - case EMIDI_CONTROLLER_TRACK_EXCLUSION: - num_rpg_events++; - break; - - case EMIDI_CONTROLLER_TRACK_DESIGNATION: - case EMIDI_CONTROLLER_PROGRAM_CHANGE: - case EMIDI_CONTROLLER_VOLUME: - case EMIDI_CONTROLLER_LOOP_BEGIN: - case EMIDI_CONTROLLER_LOOP_END: - case EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN: - case EMIDI_CONTROLLER_GLOBAL_LOOP_END: - num_emidi_events++; - break; - } - } - } - - MIDI_RestartIterator(song.tracks[i].iter); - } - - return (num_rpg_events == 1 && num_emidi_events == 0); -} - -// Fills the output buffer with events from the current song and then streams it -// out. Call this function from the MIDI thread only, with exclusive access to -// shared resources. - -static void FillBuffer(void) -{ - unsigned int i; - int num_events; - - for (num_events = 0; num_events < STREAM_MAX_EVENTS; ) - { - midi_event_t *event = NULL; - win_midi_track_t *track = NULL; - unsigned int min_time = UINT_MAX; - unsigned int delta_time; - - // Find next event across all tracks. - for (i = 0; i < song.num_tracks; ++i) - { - if (!song.tracks[i].end_of_track) - { - unsigned int time = song.tracks[i].elapsed_time + - MIDI_GetDeltaTime(song.tracks[i].iter); - if (time < min_time) - { - min_time = time; - track = &song.tracks[i]; - } - } - } - - // No more events. Restart or stop song. - if (track == NULL) - { - if (song.elapsed_time) - { - if (song.ff_restart || song.rpg_loop) - { - song.ff_restart = false; - RestartLoop(); - continue; - } - else if (song.looping) - { - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i) - { - SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_RESET_ALL_CTRLS, 0); - } - RestartTracks(); - continue; - } - } - break; - } - - track->elapsed_time = min_time; - delta_time = min_time - song.elapsed_time; - song.elapsed_time = min_time; - - if (!MIDI_GetNextEvent(track->iter, &event)) - { - track->end_of_track = true; - continue; - } - - // Restart FF loop after sending all events that share same timediv. - if (song.ff_restart && MIDI_GetDeltaTime(track->iter) > 0) - { - song.ff_restart = false; - RestartLoop(); - continue; - } - - if (!AddToBuffer(delta_time, event, track)) - { - StreamOut(); - return; - } - - num_events++; - } - - if (num_events) - { - StreamOut(); - } -} - -// The Windows API documentation states: "Applications should not call any -// multimedia functions from inside the callback function, as doing so can -// cause a deadlock." We use a thread to avoid possible deadlocks. - -static DWORD WINAPI PlayerProc(void) -{ - boolean keep_going = true; - - while (keep_going) - { - if (WaitForSingleObject(hBufferReturnEvent, INFINITE) != WAIT_OBJECT_0) - { - continue; - } - - // The MIDI thread must have exclusive access to shared resources until - // the end of the current loop iteration or when the thread exits. - EnterCriticalSection(&CriticalSection); - - switch (win_midi_state) - { - case STATE_STARTUP: - ResetDevice(); - StreamOut(); - song.rpg_loop = IsRPGLoop(); - win_midi_state = STATE_PLAYING; - break; - - case STATE_SHUTDOWN: - // Send notes/sound off prior to reset to prevent volume spikes. - SendNotesSoundOff(); - ResetDevice(); - StreamOut(); - win_midi_state = STATE_EXIT; - break; - - case STATE_EXIT: - keep_going = false; - break; - - case STATE_PLAYING: - if (update_volume) - { - UpdateVolume(); - StreamOut(); - update_volume = false; - break; - } - FillBuffer(); - break; - - case STATE_STOPPING: - // Send notes/sound off to prevent hanging notes. - SendNotesSoundOff(); - StreamOut(); - win_midi_state = STATE_STOPPED; - break; - - case STATE_STOPPED: - SetEvent(hStoppedEvent); - break; - - case STATE_PAUSED: - break; - } - - LeaveCriticalSection(&CriticalSection); - } - - return 0; -} - -// Restarts the MIDI stream. Call this function from the main thread only, with -// exclusive access to shared resources. - -static void StreamStart(void) -{ - MMRESULT mmr; - - SetEvent(hBufferReturnEvent); - - mmr = midiStreamRestart(hMidiStream); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamRestart", mmr); - } -} - -// Turns off notes but does not release all held ones (use SendNotesSoundOff() -// to prevent hanging notes). The output buffer is returned to the callback -// function and flagged as MHDR_DONE. Call this function from the main thread -// only, with exclusive access to shared resources. - -static void StreamStop(void) -{ - MMRESULT mmr; - - mmr = midiStreamStop(hMidiStream); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamStop", mmr); - } - - ResetEvent(hBufferReturnEvent); - ResetEvent(hStoppedEvent); -} - -static boolean I_WIN_InitMusic(void) -{ - const int all_devices = midiOutGetNumDevs(); - int i; - MMRESULT mmr; - - if (winmm_midi_device == NULL) - { - winmm_midi_device = M_StringDuplicate(""); - } - - for (i = 0; i < all_devices; i++) - { - MIDIOUTCAPS caps; - - if (midiOutGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR && - !strncasecmp(winmm_midi_device, caps.szPname, MAXPNAMELEN)) - { - MidiDevice = i; - break; - } - } - - if (i == all_devices) - { - free(winmm_midi_device); - winmm_midi_device = M_StringDuplicate("Microsoft MIDI Mapper"); - MidiDevice = MIDI_MAPPER; - } - - mmr = midiStreamOpen(&hMidiStream, &MidiDevice, (DWORD)1, - (DWORD_PTR)MidiStreamProc, (DWORD_PTR)NULL, - CALLBACK_FUNCTION); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamOpen", mmr); - hMidiStream = NULL; - return false; - } - - AllocateBuffer(BUFFER_INITIAL_SIZE); - - hBufferReturnEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - hStoppedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - hPlayerThread = - CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayerProc, 0, 0, 0); - SetThreadPriority(hPlayerThread, THREAD_PRIORITY_TIME_CRITICAL); - InitializeCriticalSectionAndSpinCount(&CriticalSection, 1024); - - AddToBuffer = (winmm_complevel == COMP_VANILLA) ? AddToBuffer_Vanilla - : AddToBuffer_Standard; - MIDI_InitFallback(); - - return true; -} - -static void I_WIN_SetMusicVolume(int volume) -{ - static int last_volume = -1; - - if (last_volume == volume) - { - // Ignore holding key down in volume menu. - return; - } - last_volume = volume; - - EnterCriticalSection(&CriticalSection); - volume_factor = sqrtf((float)volume / 120); - update_volume = song.registered; - LeaveCriticalSection(&CriticalSection); -} - -static void I_WIN_StopSong(void) -{ - if (!hMidiStream) - { - return; - } - - EnterCriticalSection(&CriticalSection); - StreamStop(); - win_midi_state = STATE_STOPPING; - StreamStart(); - LeaveCriticalSection(&CriticalSection); - - WaitForSingleObject(hStoppedEvent, PLAYER_THREAD_WAIT_TIME); - StreamStop(); -} - -static void I_WIN_PlaySong(void *handle, boolean looping) -{ - if (!hMidiStream) - { - return; - } - - EnterCriticalSection(&CriticalSection); - song.looping = looping; - win_midi_state = STATE_STARTUP; - StreamStart(); - LeaveCriticalSection(&CriticalSection); -} - -static void I_WIN_PauseSong(void) -{ - if (!hMidiStream) - { - return; - } - - I_WIN_StopSong(); - - EnterCriticalSection(&CriticalSection); - win_midi_state = STATE_PAUSED; - LeaveCriticalSection(&CriticalSection); -} - -static void I_WIN_ResumeSong(void) -{ - if (!hMidiStream) - { - return; - } - - EnterCriticalSection(&CriticalSection); - if (win_midi_state == STATE_PAUSED) - { - win_midi_state = STATE_PLAYING; - StreamStart(); - } - LeaveCriticalSection(&CriticalSection); -} - -// Determine whether memory block is a .mid file - -static boolean IsMid(byte *mem, int len) -{ - return len > 4 && !memcmp(mem, "MThd", 4); -} - -static boolean ConvertMus(byte *musdata, int len, const char *filename) -{ - MEMFILE *instream; - MEMFILE *outstream; - void *outbuf; - size_t outbuf_len; - int result; - - instream = mem_fopen_read(musdata, len); - outstream = mem_fopen_write(); - - result = mus2mid(instream, outstream); - - if (result == 0) - { - mem_get_buf(outstream, &outbuf, &outbuf_len); - - M_WriteFile(filename, outbuf, outbuf_len); - } - - mem_fclose(instream); - mem_fclose(outstream); - - return result; -} - -static void *I_WIN_RegisterSong(void *data, int len) -{ - unsigned int i; - char *filename; - midi_file_t *file; - - MIDIPROPTIMEDIV prop_timediv; - MIDIPROPTEMPO prop_tempo; - MMRESULT mmr; - - if (!hMidiStream) - { - return NULL; - } - - // MUS files begin with "MUS" - // Reject anything which doesnt have this signature - - filename = M_TempFile("doom.mid"); - - if (IsMid(data, len)) - { - M_WriteFile(filename, data, len); - } - else - { - // Assume a MUS file and try to convert - - ConvertMus(data, len, filename); - } - - file = MIDI_LoadFile(filename); - - M_remove(filename); - free(filename); - - if (file == NULL) - { - fprintf(stderr, "I_WIN_RegisterSong: Failed to load MID.\n"); - return NULL; - } - - prop_timediv.cbStruct = sizeof(MIDIPROPTIMEDIV); - prop_timediv.dwTimeDiv = MIDI_GetFileTimeDivision(file); - mmr = midiStreamProperty(hMidiStream, (LPBYTE)&prop_timediv, - MIDIPROP_SET | MIDIPROP_TIMEDIV); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamProperty", mmr); - return NULL; - } - timediv = prop_timediv.dwTimeDiv; - - // Set initial tempo. - prop_tempo.cbStruct = sizeof(MIDIPROPTIMEDIV); - prop_tempo.dwTempo = 500000; // 120 BPM - mmr = midiStreamProperty(hMidiStream, (LPBYTE)&prop_tempo, - MIDIPROP_SET | MIDIPROP_TEMPO); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamProperty", mmr); - return NULL; - } - tempo = prop_tempo.dwTempo; - - song.num_tracks = MIDI_NumTracks(file); - song.tracks = calloc(song.num_tracks, sizeof(win_midi_track_t)); - for (i = 0; i < song.num_tracks; ++i) - { - song.tracks[i].iter = MIDI_IterateTrack(file, i); - } - song.registered = true; - - return file; -} - -static void I_WIN_UnRegisterSong(void *handle) -{ - if (!hMidiStream) - { - return; - } - - if (song.tracks) - { - unsigned int i; - for (i = 0; i < song.num_tracks; ++i) - { - MIDI_FreeIterator(song.tracks[i].iter); - song.tracks[i].iter = NULL; - } - free(song.tracks); - song.tracks = NULL; - } - if (handle) - { - MIDI_FreeFile(handle); - } - song.elapsed_time = 0; - song.saved_elapsed_time = 0; - song.num_tracks = 0; - song.registered = false; - song.looping = false; - song.ff_loop = false; - song.ff_restart = false; - song.rpg_loop = false; -} - -static void I_WIN_ShutdownMusic(void) -{ - MMRESULT mmr; - - if (!hMidiStream) - { - return; - } - - EnterCriticalSection(&CriticalSection); - StreamStop(); - I_WIN_UnRegisterSong(NULL); - win_midi_state = STATE_SHUTDOWN; - StreamStart(); - LeaveCriticalSection(&CriticalSection); - - if (WaitForSingleObject(hPlayerThread, PLAYER_THREAD_WAIT_TIME) == - WAIT_OBJECT_0) - { - CloseHandle(hPlayerThread); - hPlayerThread = NULL; - } - StreamStop(); - - if (buffer.prepared) - { - UnprepareHeader(); - buffer.prepared = false; - } - - mmr = midiStreamClose(hMidiStream); - if (mmr != MMSYSERR_NOERROR) - { - MidiError("midiStreamClose", mmr); - } - hMidiStream = NULL; - - free(buffer.data); - buffer.data = NULL; - buffer.size = 0; - buffer.position = 0; - - CloseHandle(hBufferReturnEvent); - CloseHandle(hStoppedEvent); - DeleteCriticalSection(&CriticalSection); -} - -static boolean I_WIN_MusicIsPlaying(void) -{ - return (song.num_tracks > 0); -} - -static const snddevice_t music_win_devices[] = -{ - SNDDEVICE_PAS, - SNDDEVICE_WAVEBLASTER, - SNDDEVICE_SOUNDCANVAS, - SNDDEVICE_GENMIDI, - SNDDEVICE_AWE32, -}; - -const music_module_t music_win_module = -{ - music_win_devices, - arrlen(music_win_devices), - I_WIN_InitMusic, - I_WIN_ShutdownMusic, - I_WIN_SetMusicVolume, - I_WIN_PauseSong, - I_WIN_ResumeSong, - I_WIN_RegisterSong, - I_WIN_UnRegisterSong, - I_WIN_PlaySong, - I_WIN_StopSong, - I_WIN_MusicIsPlaying, - NULL, // Poll -}; - -#endif diff --git a/games/NXDoom/src/m_argv.c b/games/NXDoom/src/m_argv.c index 724a42b6726..a9b0ccd148b 100644 --- a/games/NXDoom/src/m_argv.c +++ b/games/NXDoom/src/m_argv.c @@ -1,556 +1,349 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_argv.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include #include #include -#include "SDL_stdinc.h" - -#include "doomtype.h" #include "d_iwad.h" +#include "doomtype.h" #include "i_system.h" +#include "m_argv.h" #include "m_misc.h" -#include "m_argv.h" // haleyjd 20110212: warning fix -int myargc; -char** myargv; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define MAXARGVS 100 +/**************************************************************************** + * Public Data + ****************************************************************************/ +int myargc; +char **myargv; -// -// M_CheckParm -// Checks for the given parameter -// in the program's command line arguments. -// Returns the argument number (1 to argc-1) -// or 0 if not present -// - -int M_CheckParmWithArgs(const char *check, int num_args) -{ - int i; - - // Check if myargv[i] has been set to NULL in LoadResponseFile(), - // which may call I_Error(), which in turn calls M_ParmExists("-nogui"). - - for (i = 1; i < myargc - num_args && myargv[i]; i++) - { - if (!strcasecmp(check, myargv[i])) - return i; - } - - return 0; -} +char *exedir = NULL; -// -// M_ParmExists -// -// Returns true if the given parameter exists in the program's command -// line arguments, false if not. -// +/**************************************************************************** + * Private Functions + ****************************************************************************/ -boolean M_ParmExists(const char *check) +static void load_response_file(int argv_index, const char *filename) { - return M_CheckParm(check) != 0; -} + FILE *handle; + int size; + char *infile; + char *file; + char **newargv; + int newargc; + int i; + int k; -int M_CheckParm(const char *check) -{ - return M_CheckParmWithArgs(check, 0); -} + /* Read the response file into memory */ -#define MAXARGVS 100 + handle = fopen(filename, "rb"); -static void LoadResponseFile(int argv_index, const char *filename) -{ - FILE *handle; - int size; - char *infile; - char *file; - char **newargv; - int newargc; - int i, k; - - // Read the response file into memory - handle = M_fopen(filename, "rb"); - - if (handle == NULL) + if (handle == NULL) { - printf ("\nNo such response file!"); - exit(1); + printf("\nNo such response file!"); + exit(1); } - printf("Found response file %s!\n", filename); + printf("Found response file %s!\n", filename); - size = M_FileLength(handle); + size = m_file_length(handle); - // Read in the entire file - // Allocate one byte extra - this is in case there is an argument - // at the end of the response file, in which case a '\0' will be - // needed. + /* Read in the entire file + * Allocate one byte extra - this is in case there is an argument + * at the end of the response file, in which case a '\0' will be + * needed. + */ - file = malloc(size + 1); + file = malloc(size + 1); - i = 0; + i = 0; - while (i < size) + while (i < size) { - k = fread(file + i, 1, size - i, handle); + k = fread(file + i, 1, size - i, handle); - if (k < 0) + if (k < 0) { - I_Error("Failed to read full contents of '%s'", filename); + i_error("Failed to read full contents of '%s'", filename); } - i += k; + i += k; } - fclose(handle); + fclose(handle); - // Create new arguments list array + /* Create new arguments list array */ - newargv = malloc(sizeof(char *) * MAXARGVS); - newargc = 0; - memset(newargv, 0, sizeof(char *) * MAXARGVS); + newargv = malloc(sizeof(char *) * MAXARGVS); + newargc = 0; + memset(newargv, 0, sizeof(char *) * MAXARGVS); - // Copy all the arguments in the list up to the response file + /* Copy all the arguments in the list up to the response file */ - if (argv_index >= MAXARGVS) + if (argv_index >= MAXARGVS) { - I_Error("Too many arguments up to the response file!"); + i_error("Too many arguments up to the response file!"); } - for (i=0; i= size) + if (k >= size) { - break; + break; } - // If the next argument is enclosed in quote marks, treat - // the contents as a single argument. This allows long filenames - // to be specified. + /* If the next argument is enclosed in quote marks, treat + * the contents as a single argument. This allows long filenames + * to be specified. + */ - if (infile[k] == '\"') + if (infile[k] == '\"') { - char *argstart; - // Skip the first character(") - ++k; + char *argstart; - argstart = &infile[k]; + /* Skip the first character(") */ - // Read all characters between quotes + ++k; - while (k < size && infile[k] != '\"' && infile[k] != '\n') + argstart = &infile[k]; + + /* Read all characters between quotes */ + + while (k < size && infile[k] != '\"' && infile[k] != '\n') { - ++k; + ++k; } - if (k >= size || infile[k] == '\n') + if (k >= size || infile[k] == '\n') { - I_Error("Quotes unclosed in response file '%s'", - filename); + i_error("Quotes unclosed in response file '%s'", filename); } - // Cut off the string at the closing quote + /* Cut off the string at the closing quote */ - infile[k] = '\0'; - ++k; + infile[k] = '\0'; + ++k; - if (newargc >= MAXARGVS) + if (newargc >= MAXARGVS) { - I_Error("Too many arguments in the response file!"); + i_error("Too many arguments in the response file!"); } - newargv[newargc++] = M_StringDuplicate(argstart); + newargv[newargc++] = m_string_duplicate(argstart); } - else + else { - char *argstart; - // Read in the next argument until a space is reached + char *argstart; + + /* Read in the next argument until a space is reached */ - argstart = &infile[k]; + argstart = &infile[k]; - while(k < size && !isspace(infile[k])) + while (k < size && !isspace(infile[k])) { - ++k; + ++k; } - // Cut off the end of the argument at the first space + /* Cut off the end of the argument at the first space */ - infile[k] = '\0'; - ++k; + infile[k] = '\0'; + ++k; - if (newargc >= MAXARGVS) + if (newargc >= MAXARGVS) { - I_Error("Too many arguments in the response file!"); + i_error("Too many arguments in the response file!"); } - newargv[newargc++] = M_StringDuplicate(argstart); + newargv[newargc++] = m_string_duplicate(argstart); } } - // Add arguments following the response file argument + /* Add arguments following the response file argument */ - if (newargc + myargc - (argv_index + 1) >= MAXARGVS) + if (newargc + myargc - (argv_index + 1) >= MAXARGVS) { - I_Error("Too many arguments following the response file!"); + i_error("Too many arguments following the response file!"); } - for (i=argv_index + 1; i - // - // Load extra command-line arguments from the given response - // file. Arguments read from the file are inserted into the - // command line, replacing this argument. A response file can - // also be loaded using the abbreviated syntax '@file.rsp'. - // - i = M_CheckParmWithArgs("-response", 1); - if (i <= 0) - { - break; - } - // Replace the -response argument so that the next time through - // the loop we'll ignore it. Since some parameters stop reading when - // an argument beginning with a '-' is encountered, we keep something - // that starts with a '-'. - free(myargv[i]); - myargv[i] = M_StringDuplicate("-_"); - LoadResponseFile(i + 1, myargv[i + 1]); - } -} +/* m_check_parm + * Checks for the given parameter in the program's command line arguments. + * Returns the argument number (1 to argc-1) or 0 if not present + */ -#if defined(_WIN32) -enum +int m_check_parm_with_args(const char *check, int num_args) { - FILETYPE_UNKNOWN = 0x0, - FILETYPE_IWAD = 0x2, - FILETYPE_PWAD = 0x4, - FILETYPE_DEH = 0x8, - FILETYPE_DEMO = 0x10, -}; - -static boolean FileIsDemoLump(const char *filename) -{ - FILE *handle; - int count, ver; - byte buf[12], *p = buf; - - handle = M_fopen(filename, "rb"); - - if (handle == NULL) - { - return false; - } - - count = fread(buf, 1, sizeof(buf), handle); - fclose(handle); + int i; - if (count != sizeof(buf)) - { - return false; - } + /* Check if myargv[i] has been set to NULL in load_response_file(), + * which may call i_error(), which in turn calls m_parm_exists("-nogui"). + */ - ver = *p++; - - if (ver >= 0 && ver <= 4) // v1.0/v1.1/v1.2 + for (i = 1; i < myargc - num_args && myargv[i]; i++) { - p--; - } - else - { - switch (ver) - { - case 104: // v1.4 - case 105: // v1.5 - case 106: // v1.6/v1.666 - case 107: // v1.7/v1.7a - case 108: // v1.8 - case 109: // v1.9 - case 111: // v1.91 hack - break; - default: - return false; - break; - } + if (!strcasecmp(check, myargv[i])) return i; } - if (*p++ > 5) // skill - { - return false; - } - if (*p++ > 9) // episode - { - return false; - } - if (*p++ > 99) // map - { - return false; - } - - return true; -} - -static int GuessFileType(const char *name) -{ - int ret = FILETYPE_UNKNOWN; - const char *base; - char *lower; - static boolean iwad_found = false, demo_found = false; - - base = M_BaseName(name); - lower = M_StringDuplicate(base); - M_ForceLowercase(lower); - - // only ever add one argument to the -iwad parameter - - if (iwad_found == false && D_IsIWADName(lower)) - { - ret = FILETYPE_IWAD; - iwad_found = true; - } - else if (M_StringEndsWith(lower, ".wad")) - { - ret = FILETYPE_PWAD; - } - else if (M_StringEndsWith(lower, ".lmp")) - { - // only ever add one argument to the -playdemo parameter - - if (demo_found == false && FileIsDemoLump(name)) - { - ret = FILETYPE_DEMO; - demo_found = true; - } - else - { - ret = FILETYPE_PWAD; - } - } - else if (M_StringEndsWith(lower, ".deh") || -// M_StringEndsWith(lower, ".bex") || - M_StringEndsWith(lower, ".hhe") || - M_StringEndsWith(lower, ".seh")) - { - ret = FILETYPE_DEH; - } - - free(lower); - - return ret; + return 0; } -typedef struct -{ - char *str; - int type, stable; -} argument_t; +/* m_parm_exists + * + * Returns true if the given parameter exists in the program's command + * line arguments, false if not. + */ -static int CompareByFileType(const void *a, const void *b) +boolean m_parm_exists(const char *check) { - const argument_t *arg_a = (const argument_t *) a; - const argument_t *arg_b = (const argument_t *) b; - - const int ret = arg_a->type - arg_b->type; - - return ret ? ret : (arg_a->stable - arg_b->stable); + return m_check_parm(check) != 0; } -void M_AddLooseFiles(void) +int m_check_parm(const char *check) { - int i, types = 0; - char **newargv; - argument_t *arguments; - - if (myargc < 2) - { - return; - } - - // allocate space for up to four additional regular parameters - // (-iwad, -merge, -deh, -playdemo) + return m_check_parm_with_args(check, 0); +} - arguments = malloc((myargc + 4) * sizeof(*arguments)); - memset(arguments, 0, (myargc + 4) * sizeof(*arguments)); +/* Find a Response File */ - // check the command line and make sure it does not already - // contain any regular parameters or response files - // but only fully-qualified LFS or UNC file paths +void m_find_response_file(void) +{ + int i; - for (i = 1; i < myargc; i++) + for (i = 1; i < myargc; i++) { - char *arg = myargv[i]; - int type; - - if (strlen(arg) < 3 || - arg[0] == '-' || - arg[0] == '@' || - ((!isalpha(arg[0]) || arg[1] != ':' || arg[2] != '\\') && - (arg[0] != '\\' || arg[1] != '\\'))) + if (myargv[i][0] == '@') { - free(arguments); - return; + load_response_file(i, myargv[i] + 1); } - - type = GuessFileType(arg); - arguments[i].str = arg; - arguments[i].type = type; - arguments[i].stable = i; - types |= type; } - // add space for one additional regular parameter - // for each discovered file type in the new argument list - // and sort parameters right before their corresponding file paths - - if (types & FILETYPE_IWAD) - { - arguments[myargc].str = M_StringDuplicate("-iwad"); - arguments[myargc].type = FILETYPE_IWAD - 1; - myargc++; - } - if (types & FILETYPE_PWAD) - { - arguments[myargc].str = M_StringDuplicate("-merge"); - arguments[myargc].type = FILETYPE_PWAD - 1; - myargc++; - } - if (types & FILETYPE_DEH) - { - arguments[myargc].str = M_StringDuplicate("-deh"); - arguments[myargc].type = FILETYPE_DEH - 1; - myargc++; - } - if (types & FILETYPE_DEMO) + for (; ; ) { - arguments[myargc].str = M_StringDuplicate("-playdemo"); - arguments[myargc].type = FILETYPE_DEMO - 1; - myargc++; - } - - newargv = malloc(myargc * sizeof(*newargv)); - - // sort the argument list by file type, except for the zeroth argument - // which is the executable invocation itself - - SDL_qsort(arguments + 1, myargc - 1, sizeof(*arguments), CompareByFileType); + /* @arg + * + * Load extra command-line arguments from the given response + * file. Arguments read from the file are inserted into the + * command line, replacing this argument. A response file can + * also be loaded using the abbreviated syntax '@file.rsp'. + */ + + i = m_check_parm_with_args("-response", 1); + if (i <= 0) + { + break; + } - newargv[0] = myargv[0]; + /* Replace the -response argument so that the next time through + * the loop we'll ignore it. Since some parameters stop reading when + * an argument beginning with a '-' is encountered, we keep something + * that starts with a '-'. + */ - for (i = 1; i < myargc; i++) - { - newargv[i] = arguments[i].str; + free(myargv[i]); + myargv[i] = m_string_duplicate("-_"); + load_response_file(i + 1, myargv[i + 1]); } - - free(arguments); - - free(myargv); - myargv = newargv; } -#endif -// Return the name of the executable used to start the program: +/* Return the name of the executable used to start the program: */ -const char *M_GetExecutableName(void) +const char *m_get_executable_name(void) { - return M_BaseName(myargv[0]); + return m_base_name(myargv[0]); } -char *exedir = NULL; - -void M_SetExeDir(void) +void m_set_exe_dir(void) { - char *dirname; + char *dirname; - dirname = M_DirName(myargv[0]); - exedir = M_StringJoin(dirname, DIR_SEPARATOR_S, NULL); - free(dirname); + dirname = m_dir_name(myargv[0]); + exedir = m_string_join(dirname, DIR_SEPARATOR_S, NULL); + free(dirname); } diff --git a/games/NXDoom/src/m_argv.h b/games/NXDoom/src/m_argv.h index b42f11cd479..bb7f6a8cbe4 100644 --- a/games/NXDoom/src/m_argv.h +++ b/games/NXDoom/src/m_argv.h @@ -1,53 +1,92 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Nil. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_argv.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ #ifndef __M_ARGV__ #define __M_ARGV__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -// -// MISC -// -extern int myargc; -extern char** myargv; +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern int myargc; +extern char **myargv; extern char *exedir; -void M_SetExeDir(void); -// Returns the position of the given parameter -// in the arg list (0 if not found). -int M_CheckParm (const char* check); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void m_set_exe_dir(void); + +/**************************************************************************** + * Name: m_check_parm + * + * Description: + * Returns the position of the given parameter in the arg list. + * + * Returns: + * The position of the given parameter in the arg list (0 if not found). + * + ****************************************************************************/ + +int m_check_parm(const char *check); + +/**************************************************************************** + * Name: m_check_parm_with_args + * + * Description: + * Same as m_check_parm, but checks that num_args arguments are available + * following the specified argument. + * + ****************************************************************************/ -// Same as M_CheckParm, but checks that num_args arguments are available -// following the specified argument. -int M_CheckParmWithArgs(const char *check, int num_args); +int m_check_parm_with_args(const char *check, int num_args); -void M_FindResponseFile(void); -void M_AddLooseFiles(void); +void m_find_response_file(void); +void m_add_loose_files(void); -// Parameter has been specified? +/**************************************************************************** + * Name: m_parm_exists + * + * Description: + * Parameter has been specified? + * + ****************************************************************************/ -boolean M_ParmExists(const char *check); +boolean m_parm_exists(const char *check); -// Get name of executable used to run this program: +/**************************************************************************** + * Name: m_get_executable_name + * + * Description: + * Get name of executable used to run this program. + * + ****************************************************************************/ -const char *M_GetExecutableName(void); +const char *m_get_executable_name(void); #endif diff --git a/games/NXDoom/src/m_bbox.c b/games/NXDoom/src/m_bbox.c index fb3f270d1b4..226237fbbec 100644 --- a/games/NXDoom/src/m_bbox.c +++ b/games/NXDoom/src/m_bbox.c @@ -1,54 +1,53 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Main loop menu stuff. -// Random number LUT. -// Default Config File. -// PCX Screenshots. -// - - +/**************************************************************************** + * apps/games/NXDoom/src/m_bbox.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Main loop menu stuff. + * Random number LUT. + * Default Config File. + * PCX Screenshots. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include "m_bbox.h" +/**************************************************************************** + * Public Functions + ****************************************************************************/ - - -void M_ClearBox (fixed_t *box) +void m_clear_box(fixed_t *box) { - box[BOXTOP] = box[BOXRIGHT] = INT_MIN; - box[BOXBOTTOM] = box[BOXLEFT] = INT_MAX; + box[BOXTOP] = box[BOXRIGHT] = INT_MIN; + box[BOXBOTTOM] = box[BOXLEFT] = INT_MAX; } -void -M_AddToBox -( fixed_t* box, - fixed_t x, - fixed_t y ) +void m_add_to_box(fixed_t *box, fixed_t x, fixed_t y) { - if (xbox[BOXRIGHT]) - box[BOXRIGHT] = x; - if (ybox[BOXTOP]) - box[BOXTOP] = y; + if (x < box[BOXLEFT]) + box[BOXLEFT] = x; + else if (x > box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y < box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + else if (y > box[BOXTOP]) + box[BOXTOP] = y; } - - - - - diff --git a/games/NXDoom/src/m_bbox.h b/games/NXDoom/src/m_bbox.h index 5a7af57c458..a36d545d557 100644 --- a/games/NXDoom/src/m_bbox.h +++ b/games/NXDoom/src/m_bbox.h @@ -1,47 +1,59 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Nil. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_bbox.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Nil. + * + ****************************************************************************/ #ifndef __M_BBOX__ #define __M_BBOX__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include #include "m_fixed.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Bounding box coordinate storage. */ -// Bounding box coordinate storage. enum { - BOXTOP, - BOXBOTTOM, - BOXLEFT, - BOXRIGHT -}; // bbox coordinates + BOXTOP, + BOXBOTTOM, + BOXLEFT, + BOXRIGHT +}; /* bbox coordinates */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// Bounding box functions. -void M_ClearBox (fixed_t* box); +/* Bounding box functions. */ -void -M_AddToBox -( fixed_t* box, - fixed_t x, - fixed_t y ); +void m_clear_box(fixed_t *box); +void m_add_to_box(fixed_t *box, fixed_t x, fixed_t y); -#endif +#endif /* __M_BBOX__ */ diff --git a/games/NXDoom/src/m_cheat.c b/games/NXDoom/src/m_cheat.c index 1565f9ef5e3..038d771077d 100644 --- a/games/NXDoom/src/m_cheat.c +++ b/games/NXDoom/src/m_cheat.c @@ -1,89 +1,95 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Cheat sequence checking. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_cheat.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Cheat sequence checking. + * + ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include "doomtype.h" #include "m_cheat.h" -// -// CHEAT SEQUENCE PACKAGE -// - -// -// Called in st_stuff module, which handles the input. -// Returns a 1 if the cheat was successful, 0 if failed. -// -int -cht_CheckCheat -( cheatseq_t* cht, - char key ) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* CHEAT SEQUENCE PACKAGE */ + +/* Called in st_stuff module, which handles the input. + * Returns a 1 if the cheat was successful, 0 if failed. + */ + +int cht_check_cheat(cheatseq_t *cht, char key) { - // if we make a short sequence on a cheat with parameters, this - // will not work in vanilla doom. behave the same. + /* if we make a short sequence on a cheat with parameters, this + * will not work in vanilla doom. behave the same. + */ + + if (cht->parameter_chars > 0 && strlen(cht->sequence) < cht->sequence_len) + { + return false; + } - if (cht->parameter_chars > 0 && strlen(cht->sequence) < cht->sequence_len) - return false; - - if (cht->chars_read < strlen(cht->sequence)) + if (cht->chars_read < strlen(cht->sequence)) { - // still reading characters from the cheat code - // and verifying. reset back to the beginning - // if a key is wrong - - if (key == cht->sequence[cht->chars_read]) - ++cht->chars_read; - else - cht->chars_read = 0; - - cht->param_chars_read = 0; + /* still reading characters from the cheat code + * and verifying. reset back to the beginning + * if a key is wrong + */ + + if (key == cht->sequence[cht->chars_read]) + ++cht->chars_read; + else + cht->chars_read = 0; + + cht->param_chars_read = 0; } - else if (cht->param_chars_read < cht->parameter_chars) + else if (cht->param_chars_read < cht->parameter_chars) { - // we have passed the end of the cheat sequence and are - // entering parameters now - - cht->parameter_buf[cht->param_chars_read] = key; - - ++cht->param_chars_read; + /* we have passed the end of the cheat sequence and are + * entering parameters now + */ + + cht->parameter_buf[cht->param_chars_read] = key; + + ++cht->param_chars_read; } - if (cht->chars_read >= strlen(cht->sequence) - && cht->param_chars_read >= cht->parameter_chars) + if (cht->chars_read >= strlen(cht->sequence) && + cht->param_chars_read >= cht->parameter_chars) { - cht->chars_read = cht->param_chars_read = 0; + cht->chars_read = cht->param_chars_read = 0; - return true; + return true; } - - // cheat not matched yet - return false; + /* cheat not matched yet */ + + return false; } -void -cht_GetParam -( cheatseq_t* cht, - char* buffer ) +void ch_get_param(cheatseq_t *cht, char *buffer) { - memcpy(buffer, cht->parameter_buf, cht->parameter_chars); + memcpy(buffer, cht->parameter_buf, cht->parameter_chars); } - - diff --git a/games/NXDoom/src/m_cheat.h b/games/NXDoom/src/m_cheat.h index 6775e709e41..8fa745615f9 100644 --- a/games/NXDoom/src/m_cheat.h +++ b/games/NXDoom/src/m_cheat.h @@ -1,62 +1,68 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Cheat code checking. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_cheat.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Cheat code checking. + * + ****************************************************************************/ #ifndef __M_CHEAT__ #define __M_CHEAT__ -// -// CHEAT SEQUENCE PACKAGE -// +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CHEAT SEQUENCE PACKAGE */ -// declaring a cheat +/* declaring a cheat */ -#define CHEAT(value, parameters) \ - { value, sizeof(value) - 1, parameters, 0, 0, "" } +#define CHEAT(value, parameters) \ + {value, sizeof(value) - 1, parameters, 0, 0, ""} #define MAX_CHEAT_LEN 25 #define MAX_CHEAT_PARAMS 5 +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef struct { - // settings for this cheat + /* settings for this cheat */ - char sequence[MAX_CHEAT_LEN]; - size_t sequence_len; - int parameter_chars; + char sequence[MAX_CHEAT_LEN]; + size_t sequence_len; + int parameter_chars; - // state used during the game + /* state used during the game */ - size_t chars_read; - int param_chars_read; - char parameter_buf[MAX_CHEAT_PARAMS]; + size_t chars_read; + int param_chars_read; + char parameter_buf[MAX_CHEAT_PARAMS]; } cheatseq_t; -int -cht_CheckCheat -( cheatseq_t* cht, - char key ); - +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void -cht_GetParam -( cheatseq_t* cht, - char* buffer ); +int cht_check_cheat(cheatseq_t *cht, char key); +void ch_get_param(cheatseq_t *cht, char *buffer); -#endif +#endif /* __M_CHEAT__ */ diff --git a/games/NXDoom/src/m_config.c b/games/NXDoom/src/m_config.c index e1a0260a226..d4441f5eaae 100644 --- a/games/NXDoom/src/m_config.c +++ b/games/NXDoom/src/m_config.c @@ -1,37 +1,43 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Configuration file interface. -// +/**************************************************************************** + * apps/games/NXDoom/src/m_config.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 1993-2008 Raven Software + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Configuration file interface. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ - -#include -#include -#include +#include #include #include -#include #include - -#include "SDL_filesystem.h" +#include +#include +#include #include "config.h" -#include "doomtype.h" #include "doomkeys.h" +#include "doomtype.h" #include "i_system.h" #include "m_argv.h" #include "m_config.h" @@ -39,654 +45,557 @@ #include "z_zone.h" -// -// DEFAULTS -// +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Location where all configuration data is stored - -// default.cfg, savegames, etc. +#define CONFIG_VARIABLE_GENERIC(name, type) {#name, {NULL}, type, 0, 0, false} -const char *configdir; - -static char *autoload_path = ""; +#define CONFIG_VARIABLE_KEY(name) CONFIG_VARIABLE_GENERIC(name, DEFAULT_KEY) +#define CONFIG_VARIABLE_INT(name) CONFIG_VARIABLE_GENERIC(name, DEFAULT_INT) +#define CONFIG_VARIABLE_INT_HEX(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_INT_HEX) +#define CONFIG_VARIABLE_FLOAT(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_FLOAT) +#define CONFIG_VARIABLE_STRING(name) \ + CONFIG_VARIABLE_GENERIC(name, DEFAULT_STRING) -// Default filenames for configuration files. - -static const char *default_main_config; -static const char *default_extra_config; +/**************************************************************************** + * Private Types + ****************************************************************************/ -typedef enum +typedef enum { - DEFAULT_INT, - DEFAULT_INT_HEX, - DEFAULT_STRING, - DEFAULT_FLOAT, - DEFAULT_KEY, + DEFAULT_INT, + DEFAULT_INT_HEX, + DEFAULT_STRING, + DEFAULT_FLOAT, + DEFAULT_KEY, } default_type_t; typedef struct { - // Name of the variable - const char *name; - - // Pointer to the location in memory of the variable - union { - int *i; - char **s; - float *f; - } location; - - // Type of the variable - default_type_t type; - - // If this is a key value, the original integer scancode we read from - // the config file before translating it to the internal key value. - // If zero, we didn't read this value from a config file. - int untranslated; - - // The value we translated the scancode into when we read the - // config file on startup. If the variable value is different from - // this, it has been changed and needs to be converted; otherwise, - // use the 'untranslated' value. - int original_translated; - - // If true, this config variable has been bound to a variable - // and is being used. - boolean bound; + /* Name of the variable */ + + const char *name; + + /* Pointer to the location in memory of the variable */ + + union + { + int *i; + char **s; + float *f; + } location; + + /* Type of the variable */ + + default_type_t type; + + /* If this is a key value, the original integer scancode we read from + * the config file before translating it to the internal key value. + * If zero, we didn't read this value from a config file. + */ + + int untranslated; + + /* The value we translated the scancode into when we read the + * config file on startup. If the variable value is different from + * this, it has been changed and needs to be converted; otherwise, + * use the 'untranslated' value. + */ + + int original_translated; + + /* If true, this config variable has been bound to a variable + * and is being used. + */ + + boolean bound; } default_t; typedef struct { - default_t *defaults; - int numdefaults; - const char *filename; + default_t *defaults; + int numdefaults; + const char *filename; } default_collection_t; -#define CONFIG_VARIABLE_GENERIC(name, type) \ - { #name, {NULL}, type, 0, 0, false } +/**************************************************************************** + * Private Data + ****************************************************************************/ -#define CONFIG_VARIABLE_KEY(name) \ - CONFIG_VARIABLE_GENERIC(name, DEFAULT_KEY) -#define CONFIG_VARIABLE_INT(name) \ - CONFIG_VARIABLE_GENERIC(name, DEFAULT_INT) -#define CONFIG_VARIABLE_INT_HEX(name) \ - CONFIG_VARIABLE_GENERIC(name, DEFAULT_INT_HEX) -#define CONFIG_VARIABLE_FLOAT(name) \ - CONFIG_VARIABLE_GENERIC(name, DEFAULT_FLOAT) -#define CONFIG_VARIABLE_STRING(name) \ - CONFIG_VARIABLE_GENERIC(name, DEFAULT_STRING) +static char *autoload_path = ""; + +/* Default filenames for configuration files. */ + +static const char *default_main_config; +static const char *default_extra_config; -//! @begin_config_file default +/* @begin_config_file default */ -static default_t doom_defaults_list[] = +static default_t doom_defaults_list[] = { - //! - // Mouse sensitivity. This value is used to multiply input mouse - // movement to control the effect of moving the mouse. - // - // The "normal" maximum value available for this through the - // in-game options menu is 9. A value of 31 or greater will cause - // the game to crash when entering the options menu. - // + /* Mouse sensitivity. This value is used to multiply input mouse + * movement to control the effect of moving the mouse. + * + * The "normal" maximum value available for this through the + * in-game options menu is 9. A value of 31 or greater will cause + * the game to crash when entering the options menu. + * + */ - CONFIG_VARIABLE_INT(mouse_sensitivity), + CONFIG_VARIABLE_INT(mouse_sensitivity), - //! - // Volume of sound effects, range 0-15. - // + /* Volume of sound effects, range 0-15. */ - CONFIG_VARIABLE_INT(sfx_volume), + CONFIG_VARIABLE_INT(sfx_volume), - //! - // Volume of in-game music, range 0-15. - // + /* Volume of in-game music, range 0-15. */ - CONFIG_VARIABLE_INT(music_volume), + CONFIG_VARIABLE_INT(music_volume), - //! - // @game strife - // - // If non-zero, dialogue text is displayed over characters' pictures - // when engaging actors who have voices. - // + /* @game strife + * + * If non-zero, dialogue text is displayed over characters' pictures + * when engaging actors who have voices. + */ - CONFIG_VARIABLE_INT(show_talk), + CONFIG_VARIABLE_INT(show_talk), - //! - // @game strife - // - // Volume of voice sound effects, range 0-15. - // + /* @game strife + * + * Volume of voice sound effects, range 0-15. + */ - CONFIG_VARIABLE_INT(voice_volume), + CONFIG_VARIABLE_INT(voice_volume), - //! - // @game doom - // - // If non-zero, messages are displayed on the heads-up display - // in the game ("picked up a clip", etc). If zero, these messages - // are not displayed. - // + /* @game doom + * + * If non-zero, messages are displayed on the heads-up display + * in the game ("picked up a clip", etc). If zero, these messages + * are not displayed. + */ - CONFIG_VARIABLE_INT(show_messages), + CONFIG_VARIABLE_INT(show_messages), - //! - // Keyboard key to turn right. - // + /* Keyboard key to turn right. */ - CONFIG_VARIABLE_KEY(key_right), + CONFIG_VARIABLE_KEY(key_right), - //! - // Keyboard key to turn left. - // + /* Keyboard key to turn left. */ - CONFIG_VARIABLE_KEY(key_left), + CONFIG_VARIABLE_KEY(key_left), - //! - // Keyboard key to move forward. - // + /* Keyboard key to move forward. */ - CONFIG_VARIABLE_KEY(key_up), + CONFIG_VARIABLE_KEY(key_up), - //! - // Keyboard key to move backward. - // + /* Keyboard key to move backward. */ - CONFIG_VARIABLE_KEY(key_down), + CONFIG_VARIABLE_KEY(key_down), - //! - // Keyboard key to strafe left. - // + /* Keyboard key to strafe left. */ - CONFIG_VARIABLE_KEY(key_strafeleft), + CONFIG_VARIABLE_KEY(key_strafeleft), - //! - // Keyboard key to strafe right. - // + /* Keyboard key to strafe right. */ - CONFIG_VARIABLE_KEY(key_straferight), + CONFIG_VARIABLE_KEY(key_straferight), - //! - // @game strife - // - // Keyboard key to use health. - // + /* @game strife + * + * Keyboard key to use health. + */ - CONFIG_VARIABLE_KEY(key_useHealth), + CONFIG_VARIABLE_KEY(key_use_health), - //! - // @game hexen - // - // Keyboard key to jump. - // + /* @game hexen + * + * Keyboard key to jump. + */ - CONFIG_VARIABLE_KEY(key_jump), + CONFIG_VARIABLE_KEY(key_jump), - //! - // @game heretic hexen - // - // Keyboard key to fly upward. - // + /* @game heretic hexen + * + * Keyboard key to fly upward. + */ - CONFIG_VARIABLE_KEY(key_flyup), + CONFIG_VARIABLE_KEY(key_flyup), - //! - // @game heretic hexen - // - // Keyboard key to fly downwards. - // + /* @game heretic hexen + * + * Keyboard key to fly downwards. + */ - CONFIG_VARIABLE_KEY(key_flydown), + CONFIG_VARIABLE_KEY(key_flydown), - //! - // @game heretic hexen - // - // Keyboard key to center flying. - // + /* @game heretic hexen + * + * Keyboard key to center flying. + */ - CONFIG_VARIABLE_KEY(key_flycenter), + CONFIG_VARIABLE_KEY(key_flycenter), - //! - // @game heretic hexen - // - // Keyboard key to look up. - // + /* @game heretic hexen + * + * Keyboard key to look up. + */ - CONFIG_VARIABLE_KEY(key_lookup), + CONFIG_VARIABLE_KEY(key_lookup), - //! - // @game heretic hexen - // - // Keyboard key to look down. - // + /* @game heretic hexen + * + * Keyboard key to look down. + */ - CONFIG_VARIABLE_KEY(key_lookdown), + CONFIG_VARIABLE_KEY(key_lookdown), - //! - // @game heretic hexen - // - // Keyboard key to center the view. - // + /* @game heretic hexen + * + * Keyboard key to center the view. + */ - CONFIG_VARIABLE_KEY(key_lookcenter), + CONFIG_VARIABLE_KEY(key_lookcenter), - //! - // @game strife - // - // Keyboard key to query inventory. - // + /* @game strife + * + * Keyboard key to query inventory. + */ - CONFIG_VARIABLE_KEY(key_invquery), + CONFIG_VARIABLE_KEY(key_invquery), - //! - // @game strife - // - // Keyboard key to display mission objective. - // + /* @game strife + * + * Keyboard key to display mission objective. + */ - CONFIG_VARIABLE_KEY(key_mission), + CONFIG_VARIABLE_KEY(key_mission), - //! - // @game strife - // - // Keyboard key to display inventory popup. - // + /* @game strife + * + * Keyboard key to display inventory popup. + */ - CONFIG_VARIABLE_KEY(key_invPop), + CONFIG_VARIABLE_KEY(key_inv_pop), - //! - // @game strife - // - // Keyboard key to display keys popup. - // + /* @game strife + * + * Keyboard key to display keys popup. + */ - CONFIG_VARIABLE_KEY(key_invKey), + CONFIG_VARIABLE_KEY(key_inv_key), - //! - // @game strife - // - // Keyboard key to jump to start of inventory. - // + /* @game strife + * + * Keyboard key to jump to start of inventory. + */ - CONFIG_VARIABLE_KEY(key_invHome), + CONFIG_VARIABLE_KEY(key_inv_home), - //! - // @game strife - // - // Keyboard key to jump to end of inventory. - // + /* @game strife + * + * Keyboard key to jump to end of inventory. + */ - CONFIG_VARIABLE_KEY(key_invEnd), + CONFIG_VARIABLE_KEY(key_inv_end), - //! - // @game heretic hexen - // - // Keyboard key to scroll left in the inventory. - // + /* @game heretic hexen + * + * Keyboard key to scroll left in the inventory. + */ - CONFIG_VARIABLE_KEY(key_invleft), + CONFIG_VARIABLE_KEY(key_invleft), - //! - // @game heretic hexen - // - // Keyboard key to scroll right in the inventory. - // + /* @game heretic hexen + * + * Keyboard key to scroll right in the inventory. + */ - CONFIG_VARIABLE_KEY(key_invright), + CONFIG_VARIABLE_KEY(key_invright), - //! - // @game strife - // - // Keyboard key to scroll left in the inventory. - // + /* @game strife + * + * Keyboard key to scroll left in the inventory. + */ - CONFIG_VARIABLE_KEY(key_invLeft), + CONFIG_VARIABLE_KEY(key_inv_left), - //! - // @game strife - // - // Keyboard key to scroll right in the inventory. - // + /* @game strife + * + * Keyboard key to scroll right in the inventory. + */ - CONFIG_VARIABLE_KEY(key_invRight), + CONFIG_VARIABLE_KEY(key_inv_right), - //! - // @game heretic hexen - // - // Keyboard key to use the current item in the inventory. - // + /* @game heretic hexen + * + * Keyboard key to use the current item in the inventory. + */ - CONFIG_VARIABLE_KEY(key_useartifact), + CONFIG_VARIABLE_KEY(key_useartifact), - //! - // @game strife - // - // Keyboard key to use inventory item. - // + /* @game strife + * + * Keyboard key to use inventory item. + */ - CONFIG_VARIABLE_KEY(key_invUse), + CONFIG_VARIABLE_KEY(key_inv_use), - //! - // @game strife - // - // Keyboard key to drop an inventory item. - // + /* @game strife + * + * Keyboard key to drop an inventory item. + */ - CONFIG_VARIABLE_KEY(key_invDrop), + CONFIG_VARIABLE_KEY(key_inv_drop), - //! - // @game strife - // - // Keyboard key to look up. - // + /* @game strife + * + * Keyboard key to look up. + */ - CONFIG_VARIABLE_KEY(key_lookUp), + CONFIG_VARIABLE_KEY(key_look_up), - //! - // @game strife - // - // Keyboard key to look down. - // + /* @game strife + * + * Keyboard key to look down. + */ - CONFIG_VARIABLE_KEY(key_lookDown), + CONFIG_VARIABLE_KEY(key_look_down), - //! - // Keyboard key to fire the currently selected weapon. - // + /* Keyboard key to fire the currently selected weapon. */ - CONFIG_VARIABLE_KEY(key_fire), + CONFIG_VARIABLE_KEY(key_fire), - //! - // Keyboard key to "use" an object, eg. a door or switch. - // + /* Keyboard key to "use" an object, eg. a door or switch. */ - CONFIG_VARIABLE_KEY(key_use), + CONFIG_VARIABLE_KEY(key_use), - //! - // Keyboard key to turn on strafing. When held down, pressing the - // key to turn left or right causes the player to strafe left or - // right instead. - // + /* Keyboard key to turn on strafing. When held down, pressing the + * key to turn left or right causes the player to strafe left or + * right instead. + */ - CONFIG_VARIABLE_KEY(key_strafe), + CONFIG_VARIABLE_KEY(key_strafe), - //! - // Keyboard key to make the player run. - // + /* Keyboard key to make the player run. */ - CONFIG_VARIABLE_KEY(key_speed), + CONFIG_VARIABLE_KEY(key_speed), - //! - // If non-zero, mouse input is enabled. If zero, mouse input is - // disabled. - // + /* If non-zero, mouse input is enabled. If zero, mouse input is + * disabled. + */ - CONFIG_VARIABLE_INT(use_mouse), + CONFIG_VARIABLE_INT(use_mouse), - //! - // Mouse button to fire the currently selected weapon. - // + /* Mouse button to fire the currently selected weapon. */ - CONFIG_VARIABLE_INT(mouseb_fire), + CONFIG_VARIABLE_INT(mouseb_fire), - //! - // Mouse button to turn on strafing. When held down, the player - // will strafe left and right instead of turning left and right. - // + /* Mouse button to turn on strafing. When held down, the player + * will strafe left and right instead of turning left and right. + */ - CONFIG_VARIABLE_INT(mouseb_strafe), + CONFIG_VARIABLE_INT(mouseb_strafe), - //! - // Mouse button to move forward. - // + /* Mouse button to move forward. */ - CONFIG_VARIABLE_INT(mouseb_forward), + CONFIG_VARIABLE_INT(mouseb_forward), - //! - // Mouse button to turn on running. When held down, the player - // will run while moving. - // + /* Mouse button to turn on running. When held down, the player + * will run while moving. + */ - CONFIG_VARIABLE_INT(mouseb_speed), + CONFIG_VARIABLE_INT(mouseb_speed), - //! - // @game hexen strife - // - // Mouse button to jump. - // + /* @game hexen strife + * + * Mouse button to jump. + */ - CONFIG_VARIABLE_INT(mouseb_jump), + CONFIG_VARIABLE_INT(mouseb_jump), - //! - // If non-zero, joystick input is enabled. - // + /* If non-zero, joystick input is enabled. */ - CONFIG_VARIABLE_INT(use_joystick), + CONFIG_VARIABLE_INT(use_joystick), - //! - // Joystick virtual button that fires the current weapon. - // + /* Joystick virtual button that fires the current weapon. */ - CONFIG_VARIABLE_INT(joyb_fire), + CONFIG_VARIABLE_INT(joyb_fire), - //! - // Joystick virtual button that makes the player strafe while - // held down. - // + /* Joystick virtual button that makes the player strafe while + * held down. + */ - CONFIG_VARIABLE_INT(joyb_strafe), + CONFIG_VARIABLE_INT(joyb_strafe), - //! - // Joystick virtual button to "use" an object, eg. a door or switch. - // + /* Joystick virtual button to "use" an object, eg. a door or switch. */ - CONFIG_VARIABLE_INT(joyb_use), + CONFIG_VARIABLE_INT(joyb_use), - //! - // Joystick virtual button that makes the player run while held - // down. - // - // If this has a value of 20 or greater, the player will always run, - // even if use_joystick is 0. - // + /* Joystick virtual button that makes the player run while held + * down. + * + * If this has a value of 20 or greater, the player will always run, + * even if use_joystick is 0. + */ - CONFIG_VARIABLE_INT(joyb_speed), + CONFIG_VARIABLE_INT(joyb_speed), - //! - // @game hexen strife - // - // Joystick virtual button that makes the player jump. - // + /* @game hexen strife + * + * Joystick virtual button that makes the player jump. + */ - CONFIG_VARIABLE_INT(joyb_jump), + CONFIG_VARIABLE_INT(joyb_jump), - //! - // @game doom heretic hexen - // - // Screen size, range 3-11. - // - // A value of 11 gives a full-screen view with the status bar not - // displayed. A value of 10 gives a full-screen view with the - // status bar displayed. - // + /* @game doom heretic hexen + * + * Screen size, range 3-11. + * + * A value of 11 gives a full-screen view with the status bar not + * displayed. A value of 10 gives a full-screen view with the + * status bar displayed. + */ - CONFIG_VARIABLE_INT(screenblocks), + CONFIG_VARIABLE_INT(screenblocks), - //! - // @game strife - // - // Screen size, range 3-11. - // - // A value of 11 gives a full-screen view with the status bar not - // displayed. A value of 10 gives a full-screen view with the - // status bar displayed. - // + /* @game strife + * + * Screen size, range 3-11. + * + * A value of 11 gives a full-screen view with the status bar not + * displayed. A value of 10 gives a full-screen view with the + * status bar displayed. + */ - CONFIG_VARIABLE_INT(screensize), + CONFIG_VARIABLE_INT(screensize), - //! - // @game doom - // - // Screen detail. Zero gives normal "high detail" mode, while - // a non-zero value gives "low detail" mode. - // + /* @game doom + * + * Screen detail. Zero gives normal "high detail" mode, while + * a non-zero value gives "low detail" mode. + */ - CONFIG_VARIABLE_INT(detaillevel), + CONFIG_VARIABLE_INT(detaillevel), - //! - // Number of sounds that will be played simultaneously. - // + /* Number of sounds that will be played simultaneously. */ - CONFIG_VARIABLE_INT(snd_channels), + CONFIG_VARIABLE_INT(snd_channels), - //! - // Music output device. A non-zero value gives MIDI sound output, - // while a value of zero disables music. - // + /* Music output device. A non-zero value gives MIDI sound output, + * while a value of zero disables music. + */ - CONFIG_VARIABLE_INT(snd_musicdevice), + CONFIG_VARIABLE_INT(snd_musicdevice), - //! - // Sound effects device. A value of zero disables in-game sound - // effects, a value of 1 enables PC speaker sound effects, while - // a value in the range 2-9 enables the "normal" digital sound - // effects. - // + /* Sound effects device. A value of zero disables in-game sound + * effects, a value of 1 enables PC speaker sound effects, while + * a value in the range 2-9 enables the "normal" digital sound + * effects. + */ - CONFIG_VARIABLE_INT(snd_sfxdevice), + CONFIG_VARIABLE_INT(snd_sfxdevice), - //! - // SoundBlaster I/O port. Unused. - // + /* SoundBlaster I/O port. Unused. */ - CONFIG_VARIABLE_INT(snd_sbport), + CONFIG_VARIABLE_INT(snd_sbport), - //! - // SoundBlaster IRQ. Unused. - // + /* SoundBlaster IRQ. Unused. */ - CONFIG_VARIABLE_INT(snd_sbirq), + CONFIG_VARIABLE_INT(snd_sbirq), - //! - // SoundBlaster DMA channel. Unused. - // + /* SoundBlaster DMA channel. Unused. */ - CONFIG_VARIABLE_INT(snd_sbdma), + CONFIG_VARIABLE_INT(snd_sbdma), - //! - // Output port to use for OPL MIDI playback. Unused. - // + /* Output port to use for OPL MIDI playback. Unused. */ - CONFIG_VARIABLE_INT(snd_mport), + CONFIG_VARIABLE_INT(snd_mport), - //! - // Gamma correction level. A value of zero disables gamma - // correction, while a value in the range 1-4 gives increasing - // levels of gamma correction. - // + /* Gamma correction level. A value of zero disables gamma + * correction, while a value in the range 1-4 gives increasing + * levels of gamma correction. + */ - CONFIG_VARIABLE_INT(usegamma), + CONFIG_VARIABLE_INT(usegamma), - //! - // @game hexen - // - // Directory in which to store savegames. - // + /* @game hexen + * + * Directory in which to store savegames. + */ - CONFIG_VARIABLE_STRING(savedir), + CONFIG_VARIABLE_STRING(savedir), - //! - // @game hexen - // - // Controls whether messages are displayed in the heads-up display. - // If this has a non-zero value, messages are displayed. - // + /* @game hexen + * + * Controls whether messages are displayed in the heads-up display. + * If this has a non-zero value, messages are displayed. + */ - CONFIG_VARIABLE_INT(messageson), + CONFIG_VARIABLE_INT(messageson), - //! - // @game strife - // - // Name of background flat used by view border. - // + /* @game strife + * + * Name of background flat used by view border. + */ - CONFIG_VARIABLE_STRING(back_flat), + CONFIG_VARIABLE_STRING(back_flat), - //! - // @game strife - // - // Multiplayer nickname (?). - // + /* @game strife + * + * Multiplayer nickname (?). + */ - CONFIG_VARIABLE_STRING(nickname), + CONFIG_VARIABLE_STRING(nickname), - //! - // Multiplayer chat macro: message to send when alt+0 is pressed. - // + /* Multiplayer chat macro: message to send when alt+0 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro0), + CONFIG_VARIABLE_STRING(chatmacro0), - //! - // Multiplayer chat macro: message to send when alt+1 is pressed. - // + /* Multiplayer chat macro: message to send when alt+1 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro1), + CONFIG_VARIABLE_STRING(chatmacro1), - //! - // Multiplayer chat macro: message to send when alt+2 is pressed. - // + /* Multiplayer chat macro: message to send when alt+2 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro2), + CONFIG_VARIABLE_STRING(chatmacro2), - //! - // Multiplayer chat macro: message to send when alt+3 is pressed. - // + /* Multiplayer chat macro: message to send when alt+3 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro3), + CONFIG_VARIABLE_STRING(chatmacro3), - //! - // Multiplayer chat macro: message to send when alt+4 is pressed. - // + /* Multiplayer chat macro: message to send when alt+4 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro4), + CONFIG_VARIABLE_STRING(chatmacro4), - //! - // Multiplayer chat macro: message to send when alt+5 is pressed. - // + /* Multiplayer chat macro: message to send when alt+5 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro5), + CONFIG_VARIABLE_STRING(chatmacro5), - //! - // Multiplayer chat macro: message to send when alt+6 is pressed. - // + /* Multiplayer chat macro: message to send when alt+6 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro6), + CONFIG_VARIABLE_STRING(chatmacro6), - //! - // Multiplayer chat macro: message to send when alt+7 is pressed. - // + /* Multiplayer chat macro: message to send when alt+7 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro7), + CONFIG_VARIABLE_STRING(chatmacro7), - //! - // Multiplayer chat macro: message to send when alt+8 is pressed. - // + /* Multiplayer chat macro: message to send when alt+8 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro8), + CONFIG_VARIABLE_STRING(chatmacro8), - //! - // Multiplayer chat macro: message to send when alt+9 is pressed. - // + /* Multiplayer chat macro: message to send when alt+9 is pressed. */ - CONFIG_VARIABLE_STRING(chatmacro9), + CONFIG_VARIABLE_STRING(chatmacro9), - //! - // @game strife - // - // Serial port number to use for SERSETUP.EXE (unused). - // + /* @game strife + * + * Serial port number to use for SERSETUP.EXE (unused). + */ - CONFIG_VARIABLE_INT(comport), + CONFIG_VARIABLE_INT(comport), }; static default_collection_t doom_defaults = @@ -696,1376 +605,1072 @@ static default_collection_t doom_defaults = NULL, }; -//! @begin_config_file extended +/* @begin_config_file extended */ static default_t extra_defaults_list[] = { - //! - // Name of the SDL video driver to use. If this is an empty string, - // the default video driver is used. - // + /* Name of the SDL video driver to use. If this is an empty string, + * the default video driver is used. + */ - CONFIG_VARIABLE_STRING(video_driver), + CONFIG_VARIABLE_STRING(video_driver), - //! - // Position of the window on the screen when running in windowed - // mode. Accepted values are: "" (empty string) - don't care, - // "center" - place window at center of screen, "x,y" - place - // window at the specified coordinates. - // + /* Position of the window on the screen when running in windowed + * mode. Accepted values are: "" (empty string) - don't care, + * "center" - place window at center of screen, "x,y" - place + * window at the specified coordinates. + */ - CONFIG_VARIABLE_STRING(window_position), + CONFIG_VARIABLE_STRING(window_position), - //! - // If non-zero, the game will run in full screen mode. If zero, - // the game will run in a window. - // + /* If non-zero, the game will run in full screen mode. If zero, + * the game will run in a window. + */ - CONFIG_VARIABLE_INT(fullscreen), + CONFIG_VARIABLE_INT(fullscreen), - //! - // Index of the display on which the game should run. This has no - // effect if running in windowed mode (fullscreen=0) and - // window_position is not set to "center". - // + /* Index of the display on which the game should run. This has no + * effect if running in windowed mode (fullscreen=0) and + * window_position is not set to "center". + */ - CONFIG_VARIABLE_INT(video_display), + CONFIG_VARIABLE_INT(video_display), - //! - // If non-zero, the screen will be stretched vertically to display - // correctly on a square pixel video mode. - // + /* If non-zero, the screen will be stretched vertically to display + * correctly on a square pixel video mode. + */ - CONFIG_VARIABLE_INT(aspect_ratio_correct), + CONFIG_VARIABLE_INT(aspect_ratio_correct), - //! - // If non-zero, the screen will have smooth scaling. - // + /* If non-zero, the screen will have smooth scaling. */ - CONFIG_VARIABLE_INT(smooth_pixel_scaling), + CONFIG_VARIABLE_INT(smooth_pixel_scaling), - //! - // If non-zero, forces integer scales for resolution-independent rendering. - // + /* If non-zero, forces integer scales for resolution-independent + * rendering. + */ - CONFIG_VARIABLE_INT(integer_scaling), + CONFIG_VARIABLE_INT(integer_scaling), - // If non-zero, any pillar/letter boxes drawn around the game area - // will "flash" when the game palette changes, simulating the VGA - // "porch" + /* If non-zero, any pillar/letter boxes drawn around the game area + * will "flash" when the game palette changes, simulating the VGA + * "porch" + */ - CONFIG_VARIABLE_INT(vga_porch_flash), + CONFIG_VARIABLE_INT(vga_porch_flash), - //! - // Window width when running in windowed mode. - // + /* Window width when running in windowed mode. */ - CONFIG_VARIABLE_INT(window_width), + CONFIG_VARIABLE_INT(window_width), - //! - // Window height when running in windowed mode. - // + /* Window height when running in windowed mode. */ - CONFIG_VARIABLE_INT(window_height), + CONFIG_VARIABLE_INT(window_height), - //! - // Width for screen mode when running fullscreen. - // If this and fullscreen_height are both set to zero, we run - // fullscreen as a desktop window that covers the entire screen, - // rather than ever switching screen modes. It should usually - // be unnecessary to set this value. - // + /* Width for screen mode when running fullscreen. + * If this and fullscreen_height are both set to zero, we run + * fullscreen as a desktop window that covers the entire screen, + * rather than ever switching screen modes. It should usually + * be unnecessary to set this value. + */ - CONFIG_VARIABLE_INT(fullscreen_width), + CONFIG_VARIABLE_INT(fullscreen_width), - //! - // Height for screen mode when running fullscreen. - // See documentation for fullscreen_width. - // + /* Height for screen mode when running fullscreen. + * See documentation for fullscreen_width. + */ - CONFIG_VARIABLE_INT(fullscreen_height), + CONFIG_VARIABLE_INT(fullscreen_height), - //! - // If non-zero, force the use of a software renderer. For use on - // systems lacking hardware acceleration. - // + /* If non-zero, force the use of a software renderer. For use on + * systems lacking hardware acceleration. + */ - CONFIG_VARIABLE_INT(force_software_renderer), + CONFIG_VARIABLE_INT(force_software_renderer), - //! - // Maximum number of pixels to use for intermediate scaling buffer. - // More pixels mean that the screen can be rendered more precisely, - // but there are diminishing returns on quality. The default limits to - // 16,000,000 pixels, which is enough to cover 4K monitor standards. + /* Maximum number of pixels to use for intermediate scaling buffer. + * More pixels mean that the screen can be rendered more precisely, + * but there are diminishing returns on quality. The default limits to + * 16,000,000 pixels, which is enough to cover 4K monitor standards. + */ - CONFIG_VARIABLE_INT(max_scaling_buffer_pixels), + CONFIG_VARIABLE_INT(max_scaling_buffer_pixels), - //! - // Number of milliseconds to wait on startup after the video mode - // has been set, before the game will start. This allows the - // screen to settle on some monitors that do not display an image - // for a brief interval after changing video modes. - // + /* Number of milliseconds to wait on startup after the video mode + * has been set, before the game will start. This allows the + * screen to settle on some monitors that do not display an image + * for a brief interval after changing video modes. + */ - CONFIG_VARIABLE_INT(startup_delay), + CONFIG_VARIABLE_INT(startup_delay), - //! - // @game heretic hexen strife - // - // If non-zero, display the graphical startup screen. - // + /* @game heretic hexen strife + * + * If non-zero, display the graphical startup screen. + */ - CONFIG_VARIABLE_INT(graphical_startup), + CONFIG_VARIABLE_INT(graphical_startup), - //! - // @game doom heretic strife - // - // If non-zero, the ENDOOM text screen is displayed when exiting the - // game. If zero, the ENDOOM screen is not displayed. - // - - CONFIG_VARIABLE_INT(show_endoom), + /* @game doom heretic strife + * + * If non-zero, the ENDOOM text screen is displayed when exiting the + * game. If zero, the ENDOOM screen is not displayed. + */ - //! - // @game doom strife - // - // If non-zero, a disk activity indicator is displayed when data is read - // from disk. If zero, the disk activity indicator is not displayed. - // + CONFIG_VARIABLE_INT(show_endoom), - CONFIG_VARIABLE_INT(show_diskicon), + /* @game doom strife + * + * If non-zero, a disk activity indicator is displayed when data is read + * from disk. If zero, the disk activity indicator is not displayed. + */ - //! - // If non-zero, save screenshots in PNG format. If zero, screenshots are - // saved in PCX format, as Vanilla Doom does. - // - - CONFIG_VARIABLE_INT(png_screenshots), + CONFIG_VARIABLE_INT(show_diskicon), - //! - // Sound output sample rate, in Hz. Typical values to use are - // 11025, 22050, 44100 and 48000. - // - - CONFIG_VARIABLE_INT(snd_samplerate), - - //! - // Maximum number of bytes to allocate for caching converted sound - // effects in memory. If set to zero, there is no limit applied. - // - - CONFIG_VARIABLE_INT(snd_cachesize), - - //! - // Maximum size of the output sound buffer size in milliseconds. - // Sound output is generated periodically in slices. Higher values - // might be more efficient but will introduce latency to the - // sound output. The default is 28ms (one slice per tic with the - // 35fps timer). - // - - CONFIG_VARIABLE_INT(snd_maxslicetime_ms), - - //! - // If non-zero, sound effects will have their pitch varied up or - // down by a random amount during play. If zero, sound effects - // play back at their default pitch. - // - - CONFIG_VARIABLE_INT(snd_pitchshift), - - //! - // External command to invoke to perform MIDI playback. If set to - // the empty string, SDL_mixer's internal MIDI playback is used. - // This only has any effect when snd_musicdevice is set to General - // MIDI output. - // - - CONFIG_VARIABLE_STRING(snd_musiccmd), - - //! - // Value to set for the DMXOPTION environment variable. If this contains - // "-opl3", output for an OPL3 chip is generated when in OPL MIDI - // playback mode. - // - - CONFIG_VARIABLE_STRING(snd_dmxoption), - - //! - // The I/O port to use to access the OPL chip. Only relevant when - // using native OPL music playback. - // - - CONFIG_VARIABLE_INT_HEX(opl_io_port), - - //! - // Controls whether libsamplerate support is used for performing - // sample rate conversions of sound effects. Support for this - // must be compiled into the program. - // - // If zero, libsamplerate support is disabled. If non-zero, - // libsamplerate is enabled. Increasing values roughly correspond - // to higher quality conversion; the higher the quality, the - // slower the conversion process. Linear conversion = 1; - // Zero order hold = 2; Fast Sinc filter = 3; Medium quality - // Sinc filter = 4; High quality Sinc filter = 5. - // - - CONFIG_VARIABLE_INT(use_libsamplerate), - - //! - // Scaling factor used by libsamplerate. This is used when converting - // sounds internally back into integer form; normally it should not - // be necessary to change it from the default value. The only time - // it might be needed is if a PWAD file is loaded that contains very - // loud sounds, in which case the conversion may cause sound clipping - // and the scale factor should be reduced. The lower the value, the - // quieter the sound effects become, so it should be set as high as is - // possible without clipping occurring. - - CONFIG_VARIABLE_FLOAT(libsamplerate_scale), - - //! - // Full path to a directory in which WAD files and dehacked patches - // can be placed to be automatically loaded on startup. A subdirectory - // of this directory matching the IWAD name is checked to find the - // files to load. - - CONFIG_VARIABLE_STRING(autoload_path), - - //! - // Full path to a directory containing configuration files for - // substitute music packs. These packs contain high quality renderings - // of game music to be played instead of using the system's built-in - // MIDI playback. - // - - CONFIG_VARIABLE_STRING(music_pack_path), + /* If non-zero, save screenshots in PNG format. If zero, screenshots are + * saved in PCX format, as Vanilla Doom does. + */ -#ifdef HAVE_FLUIDSYNTH - //! - // If 1, activate the FluidSynth chorus effects module. If 0, no chorus - // will be added to the output signal. - // + CONFIG_VARIABLE_INT(png_screenshots), + + /* Sound output sample rate, in Hz. Typical values to use are + * 11025, 22050, 44100 and 48000. + */ + + CONFIG_VARIABLE_INT(snd_samplerate), + + /* Maximum number of bytes to allocate for caching converted sound + * effects in memory. If set to zero, there is no limit applied. + */ + + CONFIG_VARIABLE_INT(snd_cachesize), + + /* Maximum size of the output sound buffer size in milliseconds. + * Sound output is generated periodically in slices. Higher values + * might be more efficient but will introduce latency to the + * sound output. The default is 28ms (one slice per tic with the + * 35fps timer). + */ - CONFIG_VARIABLE_INT(fsynth_chorus_active), + CONFIG_VARIABLE_INT(snd_maxslicetime_ms), - //! - // Specifies the modulation depth of the FluidSynth chorus. Default is - // 5.0, range is 0.0 to 256.0. - // + /* If non-zero, sound effects will have their pitch varied up or + * down by a random amount during play. If zero, sound effects + * play back at their default pitch. + */ - CONFIG_VARIABLE_FLOAT(fsynth_chorus_depth), + CONFIG_VARIABLE_INT(snd_pitchshift), - //! - // Specifies the output amplitude of the FluidSynth chorus signal. Default - // is 0.35, range is 0.0 to 10.0. - // + /* External command to invoke to perform MIDI playback. If set to + * the empty string, SDL_mixer's internal MIDI playback is used. + * This only has any effect when snd_musicdevice is set to General + * MIDI output. + */ - CONFIG_VARIABLE_FLOAT(fsynth_chorus_level), + CONFIG_VARIABLE_STRING(snd_musiccmd), - //! - // Sets the voice count of the FluidSynth chorus signal. Default is 3, - // range is 0 to 99. - // + /* Controls whether libsamplerate support is used for performing + * sample rate conversions of sound effects. Support for this + * must be compiled into the program. + * + * If zero, libsamplerate support is disabled. If non-zero, + * libsamplerate is enabled. Increasing values roughly correspond + * to higher quality conversion; the higher the quality, the + * slower the conversion process. Linear conversion = 1; + * Zero order hold = 2; Fast Sinc filter = 3; Medium quality + * Sinc filter = 4; High quality Sinc filter = 5. + */ - CONFIG_VARIABLE_INT(fsynth_chorus_nr), + CONFIG_VARIABLE_INT(use_libsamplerate), - //! - // Sets the FluidSynth chorus modulation speed in Hz. Default is 0.3, - // range is 0.1 to 5.0. - // + /* Scaling factor used by libsamplerate. This is used when converting + * sounds internally back into integer form; normally it should not + * be necessary to change it from the default value. The only time + * it might be needed is if a PWAD file is loaded that contains very + * loud sounds, in which case the conversion may cause sound clipping + * and the scale factor should be reduced. The lower the value, the + * quieter the sound effects become, so it should be set as high as is + * possible without clipping occurring. + */ - CONFIG_VARIABLE_FLOAT(fsynth_chorus_speed), + CONFIG_VARIABLE_FLOAT(libsamplerate_scale), - //! - // This setting defines how FluidSynth interprets Bank Select messages. The - // default is "gs". Other possible values are "gm", "xg" and "mma". - // + /* Full path to a directory in which WAD files and dehacked patches + * can be placed to be automatically loaded on startup. A subdirectory + * of this directory matching the IWAD name is checked to find the + * files to load. + */ + + CONFIG_VARIABLE_STRING(autoload_path), + + /* Full path to a directory containing configuration files for + * substitute music packs. These packs contain high quality renderings + * of game music to be played instead of using the system's built-in + * MIDI playback. + */ + + CONFIG_VARIABLE_STRING(music_pack_path), + +#ifdef HAVE_FLUIDSYNTH + /* If 1, activate the FluidSynth chorus effects module. If 0, no chorus + * will be added to the output signal. + */ - CONFIG_VARIABLE_STRING(fsynth_midibankselect), + CONFIG_VARIABLE_INT(fsynth_chorus_active), - //! - // Sets the number of FluidSynth voices that can be played in parallel. - // Default is 256, range is 1 - 65535. - // + /* Specifies the modulation depth of the FluidSynth chorus. Default is + * 5.0, range is 0.0 to 256.0. + */ - CONFIG_VARIABLE_INT(fsynth_polyphony), + CONFIG_VARIABLE_FLOAT(fsynth_chorus_depth), - //! - // If 1, activate the FluidSynth reverb effects module. If 0, no reverb - // will be added to the output signal. - // + /* Specifies the output amplitude of the FluidSynth chorus signal. Default + * is 0.35, range is 0.0 to 10.0. + */ - CONFIG_VARIABLE_INT(fsynth_reverb_active), + CONFIG_VARIABLE_FLOAT(fsynth_chorus_level), - //! - // Sets the amount of FluidSynth reverb damping. Default is 0.4, range is - // 0.0 to 1.0. - // + /* Sets the voice count of the FluidSynth chorus signal. Default is 3, + * range is 0 to 99. + */ - CONFIG_VARIABLE_FLOAT(fsynth_reverb_damp), + CONFIG_VARIABLE_INT(fsynth_chorus_nr), - //! - // Sets the FluidSynth reverb amplitude. Default is 0.15, range is 0.0 - - // 1.0. - // + /* Sets the FluidSynth chorus modulation speed in Hz. Default is 0.3, + * range is 0.1 to 5.0. + */ - CONFIG_VARIABLE_FLOAT(fsynth_reverb_level), + CONFIG_VARIABLE_FLOAT(fsynth_chorus_speed), - //! - // Sets the room size(i.e. amount of wet) FluidSynth reverb. Default is - // 0.6, range is 0.0 - 1.0. - // + /* This setting defines how FluidSynth interprets Bank Select messages. + * The default is "gs". Other possible values are "gm", "xg" and "mma". + */ - CONFIG_VARIABLE_FLOAT(fsynth_reverb_roomsize), + CONFIG_VARIABLE_STRING(fsynth_midibankselect), - //! - // Sets the stereo spread of the FluidSynth reverb signal. Default is - // 0.4, range is 0.0 - 100.0. - // + /* Sets the number of FluidSynth voices that can be played in parallel. + * Default is 256, range is 1 - 65535. + */ - CONFIG_VARIABLE_FLOAT(fsynth_reverb_width), + CONFIG_VARIABLE_INT(fsynth_polyphony), - //! - // Fine tune the FluidSynth output level. Default is 1.0, - // range is 0.0 - 10.0. - // + /* If 1, activate the FluidSynth reverb effects module. If 0, no reverb + * will be added to the output signal. + */ - CONFIG_VARIABLE_FLOAT(fsynth_gain), + CONFIG_VARIABLE_INT(fsynth_reverb_active), - //! - // Full path to a soundfont file to use with FluidSynth MIDI playback. - // + /* Sets the amount of FluidSynth reverb damping. Default is 0.4, range is + * 0.0 to 1.0. + */ - CONFIG_VARIABLE_STRING(fsynth_sf_path), -#endif // HAVE_FLUIDSYNTH + CONFIG_VARIABLE_FLOAT(fsynth_reverb_damp), - //! - // Full path to a Timidity configuration file to use for MIDI - // playback. The file will be evaluated from the directory where - // it is evaluated, so there is no need to add "dir" commands - // into it. - // + /* Sets the FluidSynth reverb amplitude. Default is 0.15, range is 0.0 - + * 1.0. + */ - CONFIG_VARIABLE_STRING(timidity_cfg_path), + CONFIG_VARIABLE_FLOAT(fsynth_reverb_level), - //! - // Path to GUS patch files to use when operating in GUS emulation - // mode. - // + /* Sets the room size(i.e. amount of wet) FluidSynth reverb. Default is + * 0.6, range is 0.0 - 1.0. + */ - CONFIG_VARIABLE_STRING(gus_patch_path), + CONFIG_VARIABLE_FLOAT(fsynth_reverb_roomsize), - //! - // Number of kilobytes of RAM to use in GUS emulation mode. Valid - // values are 256, 512, 768 or 1024. - // + /* Sets the stereo spread of the FluidSynth reverb signal. Default is + * 0.4, range is 0.0 - 100.0. + */ - CONFIG_VARIABLE_INT(gus_ram_kb), + CONFIG_VARIABLE_FLOAT(fsynth_reverb_width), -#ifdef _WIN32 - //! - // MIDI device for native Windows MIDI. - // + /* Fine tune the FluidSynth output level. Default is 1.0, + * range is 0.0 - 10.0. + */ - CONFIG_VARIABLE_STRING(winmm_midi_device), + CONFIG_VARIABLE_FLOAT(fsynth_gain), - //! - // Compatibility level for native Windows MIDI, default 0. Valid values are - // 0 (Vanilla), 1 (Standard), 2 (Full). - // + /* Full path to a soundfont file to use with FluidSynth MIDI playback. */ - CONFIG_VARIABLE_INT(winmm_complevel), + CONFIG_VARIABLE_STRING(fsynth_sf_path), +#endif /* HAVE_FLUIDSYNTH */ - //! - // Reset device type for native Windows MIDI, default 1. Valid values are - // 0 (None), 1 (GM Mode), 2 (GS Mode), 3 (XG Mode). - // + /* Full path to a Timidity configuration file to use for MIDI + * playback. The file will be evaluated from the directory where + * it is evaluated, so there is no need to add "dir" commands + * into it. + */ - CONFIG_VARIABLE_INT(winmm_reset_type), + CONFIG_VARIABLE_STRING(timidity_cfg_path), - //! - // Reset device delay for native Windows MIDI, default 0, median value 100 ms. - // + /* Path to GUS patch files to use when operating in GUS emulation + * mode. + */ - CONFIG_VARIABLE_INT(winmm_reset_delay), -#endif + CONFIG_VARIABLE_STRING(gus_patch_path), - //! - // @game doom strife - // - // If non-zero, the Vanilla savegame limit is enforced; if the - // savegame exceeds 180224 bytes in size, the game will exit with - // an error. If this has a value of zero, there is no limit to - // the size of savegames. - // + /* Number of kilobytes of RAM to use in GUS emulation mode. Valid + * values are 256, 512, 768 or 1024. + */ - CONFIG_VARIABLE_INT(vanilla_savegame_limit), + CONFIG_VARIABLE_INT(gus_ram_kb), - //! - // @game doom strife - // - // If non-zero, the Vanilla demo size limit is enforced; the game - // exits with an error when a demo exceeds the demo size limit - // (128KiB by default). If this has a value of zero, there is no - // limit to the size of demos. - // + /* @game doom strife + * + * If non-zero, the Vanilla savegame limit is enforced; if the + * savegame exceeds 180224 bytes in size, the game will exit with + * an error. If this has a value of zero, there is no limit to + * the size of savegames. + */ - CONFIG_VARIABLE_INT(vanilla_demo_limit), + CONFIG_VARIABLE_INT(vanilla_savegame_limit), - //! - // If non-zero, the game behaves like Vanilla Doom, always assuming - // an American keyboard mapping. If this has a value of zero, the - // native keyboard mapping of the keyboard is used. - // + /* @game doom strife + * + * If non-zero, the Vanilla demo size limit is enforced; the game + * exits with an error when a demo exceeds the demo size limit + * (128KiB by default). If this has a value of zero, there is no + * limit to the size of demos. + */ - CONFIG_VARIABLE_INT(vanilla_keyboard_mapping), + CONFIG_VARIABLE_INT(vanilla_demo_limit), - //! - // Name to use in network games for identification. This is only - // used on the "waiting" screen while waiting for the game to start. - // + /* If non-zero, the game behaves like Vanilla Doom, always assuming + * an American keyboard mapping. If this has a value of zero, the + * native keyboard mapping of the keyboard is used. + */ - CONFIG_VARIABLE_STRING(player_name), + CONFIG_VARIABLE_INT(vanilla_keyboard_mapping), - //! - // If this is non-zero, the mouse will be "grabbed" when running - // in windowed mode so that it can be used as an input device. - // When running full screen, this has no effect. - // + /* Name to use in network games for identification. This is only + * used on the "waiting" screen while waiting for the game to start. + */ - CONFIG_VARIABLE_INT(grabmouse), + CONFIG_VARIABLE_STRING(player_name), - //! - // If non-zero, all vertical mouse movement is ignored. This - // emulates the behavior of the "novert" tool available under DOS - // that performs the same function. - // + /* If this is non-zero, the mouse will be "grabbed" when running + * in windowed mode so that it can be used as an input device. + * When running full screen, this has no effect. + */ - CONFIG_VARIABLE_INT(novert), + CONFIG_VARIABLE_INT(grabmouse), - //! - // Mouse acceleration factor. When the speed of mouse movement - // exceeds the threshold value (mouse_threshold), the speed is - // multiplied by this value. - // + /* If non-zero, all vertical mouse movement is ignored. This + * emulates the behavior of the "novert" tool available under DOS + * that performs the same function. + */ - CONFIG_VARIABLE_FLOAT(mouse_acceleration), + CONFIG_VARIABLE_INT(novert), - //! - // Mouse acceleration threshold. When the speed of mouse movement - // exceeds this threshold value, the speed is multiplied by an - // acceleration factor (mouse_acceleration). - // + /* Mouse acceleration factor. When the speed of mouse movement + * exceeds the threshold value (mouse_threshold), the speed is + * multiplied by this value. + */ - CONFIG_VARIABLE_INT(mouse_threshold), + CONFIG_VARIABLE_FLOAT(mouse_acceleration), - //! - // Mouse button to strafe left. - // + /* Mouse acceleration threshold. When the speed of mouse movement + * exceeds this threshold value, the speed is multiplied by an + * acceleration factor (mouse_acceleration). + */ - CONFIG_VARIABLE_INT(mouseb_strafeleft), + CONFIG_VARIABLE_INT(mouse_threshold), - //! - // Mouse button to strafe right. - // + /* Mouse button to strafe left. */ - CONFIG_VARIABLE_INT(mouseb_straferight), + CONFIG_VARIABLE_INT(mouseb_strafeleft), - //! - // Mouse button to turn left. - // + /* Mouse button to strafe right. */ - CONFIG_VARIABLE_INT(mouseb_turnleft), + CONFIG_VARIABLE_INT(mouseb_straferight), - //! - // Mouse button to turn right. - // + /* Mouse button to turn left. */ - CONFIG_VARIABLE_INT(mouseb_turnright), + CONFIG_VARIABLE_INT(mouseb_turnleft), - //! - // Mouse button to "use" an object, eg. a door or switch. - // + /* Mouse button to turn right. */ - CONFIG_VARIABLE_INT(mouseb_use), + CONFIG_VARIABLE_INT(mouseb_turnright), - //! - // Mouse button to move backwards. - // + /* Mouse button to "use" an object, eg. a door or switch. */ - CONFIG_VARIABLE_INT(mouseb_backward), + CONFIG_VARIABLE_INT(mouseb_use), - //! - // Mouse button to cycle to the previous weapon. - // + /* Mouse button to move backwards. */ - CONFIG_VARIABLE_INT(mouseb_prevweapon), + CONFIG_VARIABLE_INT(mouseb_backward), - //! - // Mouse button to cycle to the next weapon. - // + /* Mouse button to cycle to the previous weapon. */ - CONFIG_VARIABLE_INT(mouseb_nextweapon), - - //! - // @game heretic - // - // Mouse button to move to the left in the inventory. - // + CONFIG_VARIABLE_INT(mouseb_prevweapon), - CONFIG_VARIABLE_INT(mouseb_invleft), + /* Mouse button to cycle to the next weapon. */ - //! - // @game heretic - // - // Mouse button to move to the right in the inventory. - // + CONFIG_VARIABLE_INT(mouseb_nextweapon), - CONFIG_VARIABLE_INT(mouseb_invright), + /* @game heretic + * + * Mouse button to move to the left in the inventory. + */ - //! - // @game heretic hexen - // - // Mouse button to use artifact. - // + CONFIG_VARIABLE_INT(mouseb_invleft), - CONFIG_VARIABLE_INT(mouseb_useartifact), + /* @game heretic + * + * Mouse button to move to the right in the inventory. + */ - //! - // If non-zero, double-clicking a mouse button acts like pressing - // the "use" key to use an object in-game, eg. a door or switch. - // + CONFIG_VARIABLE_INT(mouseb_invright), - CONFIG_VARIABLE_INT(dclick_use), + /* @game heretic hexen + * + * Mouse button to use artifact. + */ - //! - // SDL GUID string indicating the joystick to use. An empty string - // indicates that no joystick is configured. - // + CONFIG_VARIABLE_INT(mouseb_useartifact), - CONFIG_VARIABLE_STRING(joystick_guid), + /* If non-zero, double-clicking a mouse button acts like pressing + * the "use" key to use an object in-game, eg. a door or switch. + */ - //! - // Index of SDL joystick to use; this is only used in the case where - // multiple identical joystick devices are connected which have the - // same GUID, to distinguish between devices. - // + CONFIG_VARIABLE_INT(dclick_use), - CONFIG_VARIABLE_INT(joystick_index), + /* SDL GUID string indicating the joystick to use. An empty string + * indicates that no joystick is configured. + */ - //! - // If non-zero, use analog movement when playing with a gamepad. - // + CONFIG_VARIABLE_STRING(joystick_guid), - CONFIG_VARIABLE_INT(use_analog), + /* Index of SDL joystick to use; this is only used in the case where + * multiple identical joystick devices are connected which have the + * same GUID, to distinguish between devices. + */ - //! - // Joystick axis to use to for horizontal (X) movement. - // + CONFIG_VARIABLE_INT(joystick_index), - CONFIG_VARIABLE_INT(joystick_x_axis), + /* If non-zero, use analog movement when playing with a gamepad. */ - //! - // If non-zero, movement on the horizontal joystick axis is inverted. - // + CONFIG_VARIABLE_INT(use_analog), - CONFIG_VARIABLE_INT(joystick_x_invert), + /* Joystick axis to use to for horizontal (X) movement. */ - //! - // Joystick turn analog sensitivity, specified as a value between 0 and 20. - // + CONFIG_VARIABLE_INT(joystick_x_axis), - CONFIG_VARIABLE_INT(joystick_turn_sensitivity), + /* If non-zero, movement on the horizontal joystick axis is inverted. */ - //! - // Joystick axis to use to for vertical (Y) movement. - // + CONFIG_VARIABLE_INT(joystick_x_invert), - CONFIG_VARIABLE_INT(joystick_y_axis), + /* Joystick turn analog sensitivity, specified as a value between 0 + * and 20. + */ - //! - // If non-zero, movement on the vertical joystick axis is inverted. - // + CONFIG_VARIABLE_INT(joystick_turn_sensitivity), - CONFIG_VARIABLE_INT(joystick_y_invert), + /* Joystick axis to use to for vertical (Y) movement. */ - //! - // Joystick axis to use to for strafing movement. - // + CONFIG_VARIABLE_INT(joystick_y_axis), - CONFIG_VARIABLE_INT(joystick_strafe_axis), + /* If non-zero, movement on the vertical joystick axis is inverted. */ - //! - // If non-zero, movement on the joystick axis used for strafing - // is inverted. - // + CONFIG_VARIABLE_INT(joystick_y_invert), - CONFIG_VARIABLE_INT(joystick_strafe_invert), + /* Joystick axis to use to for strafing movement. */ - //! - // Joystick move and strafe analog sensitivity, specified as a value - // between 0 and 20. - // + CONFIG_VARIABLE_INT(joystick_strafe_axis), - CONFIG_VARIABLE_INT(joystick_move_sensitivity), - //! - // Joystick axis to use to for looking up and down. - // + /* If non-zero, movement on the joystick axis used for strafing + * is inverted. + */ - CONFIG_VARIABLE_INT(joystick_look_axis), + CONFIG_VARIABLE_INT(joystick_strafe_invert), - //! - // If non-zero, movement on the joystick axis used for looking - // is inverted. - // + /* Joystick move and strafe analog sensitivity, specified as a value + * between 0 and 20. + */ - CONFIG_VARIABLE_INT(joystick_look_invert), + CONFIG_VARIABLE_INT(joystick_move_sensitivity), - //! - // Joystick look analog sensitivity, specified as a value between 0 and 20. - // + /* Joystick axis to use to for looking up and down. */ - CONFIG_VARIABLE_INT(joystick_look_sensitivity), + CONFIG_VARIABLE_INT(joystick_look_axis), - //! - // The physical joystick button that corresponds to joystick - // virtual button #0. - // + /* If non-zero, movement on the joystick axis used for looking + * is inverted. + */ - CONFIG_VARIABLE_INT(joystick_physical_button0), + CONFIG_VARIABLE_INT(joystick_look_invert), - //! - // The physical joystick button that corresponds to joystick - // virtual button #1. - // + /* Joystick look analog sensitivity, specified as a value between 0 + * and 20. + */ - CONFIG_VARIABLE_INT(joystick_physical_button1), + CONFIG_VARIABLE_INT(joystick_look_sensitivity), - //! - // The physical joystick button that corresponds to joystick - // virtual button #2. - // + /* The physical joystick button that corresponds to joystick + * virtual button #0. + */ - CONFIG_VARIABLE_INT(joystick_physical_button2), + CONFIG_VARIABLE_INT(joystick_physical_button0), - //! - // The physical joystick button that corresponds to joystick - // virtual button #3. - // + /* The physical joystick button that corresponds to joystick + * virtual button #1. + */ - CONFIG_VARIABLE_INT(joystick_physical_button3), + CONFIG_VARIABLE_INT(joystick_physical_button1), - //! - // The physical joystick button that corresponds to joystick - // virtual button #4. - // + /* The physical joystick button that corresponds to joystick + * virtual button #2. + */ - CONFIG_VARIABLE_INT(joystick_physical_button4), + CONFIG_VARIABLE_INT(joystick_physical_button2), - //! - // The physical joystick button that corresponds to joystick - // virtual button #5. - // + /* The physical joystick button that corresponds to joystick + * virtual button #3. + */ - CONFIG_VARIABLE_INT(joystick_physical_button5), + CONFIG_VARIABLE_INT(joystick_physical_button3), - //! - // The physical joystick button that corresponds to joystick - // virtual button #6. - // + /* The physical joystick button that corresponds to joystick + * virtual button #4. + */ - CONFIG_VARIABLE_INT(joystick_physical_button6), + CONFIG_VARIABLE_INT(joystick_physical_button4), - //! - // The physical joystick button that corresponds to joystick - // virtual button #7. - // + /* The physical joystick button that corresponds to joystick + * virtual button #5. + */ - CONFIG_VARIABLE_INT(joystick_physical_button7), + CONFIG_VARIABLE_INT(joystick_physical_button5), - //! - // The physical joystick button that corresponds to joystick - // virtual button #8. - // + /* The physical joystick button that corresponds to joystick + * virtual button #6. + */ - CONFIG_VARIABLE_INT(joystick_physical_button8), + CONFIG_VARIABLE_INT(joystick_physical_button6), - //! - // The physical joystick button that corresponds to joystick - // virtual button #9. - // + /* The physical joystick button that corresponds to joystick + * virtual button #7. + */ - CONFIG_VARIABLE_INT(joystick_physical_button9), + CONFIG_VARIABLE_INT(joystick_physical_button7), - //! - // The physical joystick button that corresponds to joystick - // virtual button #10. - // + /* The physical joystick button that corresponds to joystick + * virtual button #8. + */ - CONFIG_VARIABLE_INT(joystick_physical_button10), + CONFIG_VARIABLE_INT(joystick_physical_button8), - //! - // The physical joystick button that corresponds to joystick - // virtual button #11. - // + /* The physical joystick button that corresponds to joystick + * virtual button #9. + */ - CONFIG_VARIABLE_INT(joystick_physical_button11), + CONFIG_VARIABLE_INT(joystick_physical_button9), - //! - // The physical joystick button that corresponds to joystick - // virtual button #12. - // + /* The physical joystick button that corresponds to joystick + * virtual button #10. + */ - CONFIG_VARIABLE_INT(joystick_physical_button12), + CONFIG_VARIABLE_INT(joystick_physical_button10), - //! - // The physical joystick button that corresponds to joystick - // virtual button #13. - // + /* The physical joystick button that corresponds to joystick + * virtual button #11. + */ - CONFIG_VARIABLE_INT(joystick_physical_button13), + CONFIG_VARIABLE_INT(joystick_physical_button11), - //! - // The physical joystick button that corresponds to joystick - // virtual button #14. - // + /* The physical joystick button that corresponds to joystick + * virtual button #12. + */ - CONFIG_VARIABLE_INT(joystick_physical_button14), + CONFIG_VARIABLE_INT(joystick_physical_button12), - //! - // The physical joystick button that corresponds to joystick - // virtual button #15. - // + /* The physical joystick button that corresponds to joystick + * virtual button #13. + */ - CONFIG_VARIABLE_INT(joystick_physical_button15), + CONFIG_VARIABLE_INT(joystick_physical_button13), - //! - // The physical joystick button that corresponds to joystick - // virtual button #16. - // + /* The physical joystick button that corresponds to joystick + * virtual button #14. + */ - CONFIG_VARIABLE_INT(joystick_physical_button16), + CONFIG_VARIABLE_INT(joystick_physical_button14), - //! - // If non-zero, use the SDL_GameController interface instead of the - // SDL_Joystick interface. - // + /* The physical joystick button that corresponds to joystick + * virtual button #15. + */ - CONFIG_VARIABLE_INT(use_gamepad), + CONFIG_VARIABLE_INT(joystick_physical_button15), - //! - // Stores the SDL_GameControllerType of the last configured gamepad. - // + /* The physical joystick button that corresponds to joystick + * virtual button #16. + */ - CONFIG_VARIABLE_INT(gamepad_type), + CONFIG_VARIABLE_INT(joystick_physical_button16), - //! - // Joystick x axis dead zone, specified as a percentage of the axis max - // value. - // + /* If non-zero, use the SDL_GameController interface instead of the + * SDL_Joystick interface. + */ - CONFIG_VARIABLE_INT(joystick_x_dead_zone), + CONFIG_VARIABLE_INT(use_gamepad), - //! - // Joystick y axis dead zone, specified as a percentage of the axis max - // value. - // + /* Stores the SDL_GameControllerType of the last configured gamepad. */ - CONFIG_VARIABLE_INT(joystick_y_dead_zone), + CONFIG_VARIABLE_INT(gamepad_type), - //! - // Joystick strafe axis dead zone, specified as a percentage of the axis - // max value. - // + /* Joystick x axis dead zone, specified as a percentage of the axis max + * value. + */ - CONFIG_VARIABLE_INT(joystick_strafe_dead_zone), + CONFIG_VARIABLE_INT(joystick_x_dead_zone), - //! - // Joystick look axis dead zone, specified as a percentage of the axis max - // value. - // + /* Joystick y axis dead zone, specified as a percentage of the axis max + * value. + */ - CONFIG_VARIABLE_INT(joystick_look_dead_zone), + CONFIG_VARIABLE_INT(joystick_y_dead_zone), - //! - // Joystick virtual button to make the player strafe left. - // + /* Joystick strafe axis dead zone, specified as a percentage of the axis + * max value. + */ - CONFIG_VARIABLE_INT(joyb_strafeleft), + CONFIG_VARIABLE_INT(joystick_strafe_dead_zone), - //! - // Joystick virtual button to make the player strafe right. - // + /* Joystick look axis dead zone, specified as a percentage of the axis max + * value. + */ - CONFIG_VARIABLE_INT(joyb_straferight), + CONFIG_VARIABLE_INT(joystick_look_dead_zone), - //! - // Joystick virtual button to activate the menu. - // + /* Joystick virtual button to make the player strafe left. */ - CONFIG_VARIABLE_INT(joyb_menu_activate), + CONFIG_VARIABLE_INT(joyb_strafeleft), - //! - // Joystick virtual button to toggle the automap. - // + /* Joystick virtual button to make the player strafe right. */ - CONFIG_VARIABLE_INT(joyb_toggle_automap), + CONFIG_VARIABLE_INT(joyb_straferight), - //! - // Joystick virtual button that cycles to the previous weapon. - // + /* Joystick virtual button to activate the menu. */ - CONFIG_VARIABLE_INT(joyb_prevweapon), + CONFIG_VARIABLE_INT(joyb_menu_activate), - //! - // Joystick virtual button that cycles to the next weapon. - // + /* Joystick virtual button to toggle the automap. */ - CONFIG_VARIABLE_INT(joyb_nextweapon), + CONFIG_VARIABLE_INT(joyb_toggle_automap), - //! - // @game heretic hexen - // Joystick virtual button to activate artifact. - // + /* Joystick virtual button that cycles to the previous weapon. */ - CONFIG_VARIABLE_INT(joyb_useartifact), + CONFIG_VARIABLE_INT(joyb_prevweapon), - //! - // @game heretic hexen - // Joystick virtual button to move left in the inventory. - // + /* Joystick virtual button that cycles to the next weapon. */ - CONFIG_VARIABLE_INT(joyb_invleft), + CONFIG_VARIABLE_INT(joyb_nextweapon), - //! - // @game heretic hexen - // Joystick virtual button to move right in the inventory. - // + /* @game heretic hexen + * Joystick virtual button to activate artifact. + */ - CONFIG_VARIABLE_INT(joyb_invright), + CONFIG_VARIABLE_INT(joyb_useartifact), - //! - // @game heretic hexen - // Joystick virtual button to fly up. - // + /* @game heretic hexen + * Joystick virtual button to move left in the inventory. + */ - CONFIG_VARIABLE_INT(joyb_flyup), + CONFIG_VARIABLE_INT(joyb_invleft), - //! - // @game heretic hexen - // Joystick virtual button to fly down. - // + /* @game heretic hexen + * Joystick virtual button to move right in the inventory. + */ - CONFIG_VARIABLE_INT(joyb_flydown), + CONFIG_VARIABLE_INT(joyb_invright), - //! - // @game heretic hexen - // Joystick virtual button to center flying. - // + /* @game heretic hexen + * Joystick virtual button to fly up. + */ - CONFIG_VARIABLE_INT(joyb_flycenter), + CONFIG_VARIABLE_INT(joyb_flyup), - //! - // Key to pause or unpause the game. - // + /* @game heretic hexen + * Joystick virtual button to fly down. + */ - CONFIG_VARIABLE_KEY(key_pause), + CONFIG_VARIABLE_INT(joyb_flydown), - //! - // Key that activates the menu when pressed. - // + /* @game heretic hexen + * Joystick virtual button to center flying. + */ - CONFIG_VARIABLE_KEY(key_menu_activate), + CONFIG_VARIABLE_INT(joyb_flycenter), - //! - // Key that moves the cursor up on the menu. - // + /* Key to pause or unpause the game. */ - CONFIG_VARIABLE_KEY(key_menu_up), + CONFIG_VARIABLE_KEY(key_pause), - //! - // Key that moves the cursor down on the menu. - // + /* Key that activates the menu when pressed. */ - CONFIG_VARIABLE_KEY(key_menu_down), + CONFIG_VARIABLE_KEY(key_menu_activate), - //! - // Key that moves the currently selected slider on the menu left. - // + /* Key that moves the cursor up on the menu. */ - CONFIG_VARIABLE_KEY(key_menu_left), + CONFIG_VARIABLE_KEY(key_menu_up), - //! - // Key that moves the currently selected slider on the menu right. - // + /* Key that moves the cursor down on the menu. */ - CONFIG_VARIABLE_KEY(key_menu_right), + CONFIG_VARIABLE_KEY(key_menu_down), - //! - // Key to go back to the previous menu. - // + /* Key that moves the currently selected slider on the menu left. */ - CONFIG_VARIABLE_KEY(key_menu_back), + CONFIG_VARIABLE_KEY(key_menu_left), - //! - // Key to activate the currently selected menu item. - // + /* Key that moves the currently selected slider on the menu right. */ - CONFIG_VARIABLE_KEY(key_menu_forward), + CONFIG_VARIABLE_KEY(key_menu_right), - //! - // Key to answer 'yes' to a question in the menu. - // + /* Key to go back to the previous menu. */ - CONFIG_VARIABLE_KEY(key_menu_confirm), + CONFIG_VARIABLE_KEY(key_menu_back), - //! - // Key to answer 'no' to a question in the menu. - // + /* Key to activate the currently selected menu item. */ - CONFIG_VARIABLE_KEY(key_menu_abort), + CONFIG_VARIABLE_KEY(key_menu_forward), - //! - // Keyboard shortcut to bring up the help screen. - // + /* Key to answer 'yes' to a question in the menu. */ - CONFIG_VARIABLE_KEY(key_menu_help), + CONFIG_VARIABLE_KEY(key_menu_confirm), - //! - // Keyboard shortcut to bring up the save game menu. - // + /* Key to answer 'no' to a question in the menu. */ - CONFIG_VARIABLE_KEY(key_menu_save), + CONFIG_VARIABLE_KEY(key_menu_abort), - //! - // Keyboard shortcut to bring up the load game menu. - // + /* Keyboard shortcut to bring up the help screen. */ - CONFIG_VARIABLE_KEY(key_menu_load), + CONFIG_VARIABLE_KEY(key_menu_help), - //! - // Keyboard shortcut to bring up the sound volume menu. - // + /* Keyboard shortcut to bring up the save game menu. */ - CONFIG_VARIABLE_KEY(key_menu_volume), + CONFIG_VARIABLE_KEY(key_menu_save), - //! - // Keyboard shortcut to toggle the detail level. - // + /* Keyboard shortcut to bring up the load game menu. */ - CONFIG_VARIABLE_KEY(key_menu_detail), + CONFIG_VARIABLE_KEY(key_menu_load), - //! - // Keyboard shortcut to quicksave the current game. - // + /* Keyboard shortcut to bring up the sound volume menu. */ - CONFIG_VARIABLE_KEY(key_menu_qsave), + CONFIG_VARIABLE_KEY(key_menu_volume), - //! - // Keyboard shortcut to end the game. - // + /* Keyboard shortcut to toggle the detail level. */ - CONFIG_VARIABLE_KEY(key_menu_endgame), + CONFIG_VARIABLE_KEY(key_menu_detail), - //! - // Keyboard shortcut to toggle heads-up messages. - // + /* Keyboard shortcut to quicksave the current game. */ - CONFIG_VARIABLE_KEY(key_menu_messages), + CONFIG_VARIABLE_KEY(key_menu_qsave), - //! - // Keyboard shortcut to load the last quicksave. - // + /* Keyboard shortcut to end the game. */ - CONFIG_VARIABLE_KEY(key_menu_qload), + CONFIG_VARIABLE_KEY(key_menu_endgame), - //! - // Keyboard shortcut to quit the game. - // + /* Keyboard shortcut to toggle heads-up messages. */ - CONFIG_VARIABLE_KEY(key_menu_quit), + CONFIG_VARIABLE_KEY(key_menu_messages), - //! - // Keyboard shortcut to toggle the gamma correction level. - // + /* Keyboard shortcut to load the last quicksave. */ - CONFIG_VARIABLE_KEY(key_menu_gamma), + CONFIG_VARIABLE_KEY(key_menu_qload), - //! - // Keyboard shortcut to switch view in multiplayer. - // + /* Keyboard shortcut to quit the game. */ - CONFIG_VARIABLE_KEY(key_spy), + CONFIG_VARIABLE_KEY(key_menu_quit), - //! - // Keyboard shortcut to increase the screen size. - // + /* Keyboard shortcut to toggle the gamma correction level. */ - CONFIG_VARIABLE_KEY(key_menu_incscreen), + CONFIG_VARIABLE_KEY(key_menu_gamma), - //! - // Keyboard shortcut to decrease the screen size. - // + /* Keyboard shortcut to switch view in multiplayer. */ - CONFIG_VARIABLE_KEY(key_menu_decscreen), + CONFIG_VARIABLE_KEY(key_spy), - //! - // Keyboard shortcut to save a screenshot. - // + /* Keyboard shortcut to increase the screen size. */ - CONFIG_VARIABLE_KEY(key_menu_screenshot), + CONFIG_VARIABLE_KEY(key_menu_incscreen), - //! - // Key to toggle the map view. - // + /* Keyboard shortcut to decrease the screen size. */ - CONFIG_VARIABLE_KEY(key_map_toggle), + CONFIG_VARIABLE_KEY(key_menu_decscreen), - //! - // Key to pan north when in the map view. - // + /* Keyboard shortcut to save a screenshot. */ - CONFIG_VARIABLE_KEY(key_map_north), + CONFIG_VARIABLE_KEY(key_menu_screenshot), - //! - // Key to pan south when in the map view. - // + /* Key to toggle the map view. */ - CONFIG_VARIABLE_KEY(key_map_south), + CONFIG_VARIABLE_KEY(key_map_toggle), - //! - // Key to pan east when in the map view. - // + /* Key to pan north when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_east), + CONFIG_VARIABLE_KEY(key_map_north), - //! - // Key to pan west when in the map view. - // + /* Key to pan south when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_west), + CONFIG_VARIABLE_KEY(key_map_south), - //! - // Key to zoom in when in the map view. - // + /* Key to pan east when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_zoomin), + CONFIG_VARIABLE_KEY(key_map_east), - //! - // Key to zoom out when in the map view. - // + /* Key to pan west when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_zoomout), + CONFIG_VARIABLE_KEY(key_map_west), - //! - // Key to zoom out the maximum amount when in the map view. - // + /* Key to zoom in when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_maxzoom), + CONFIG_VARIABLE_KEY(key_map_zoomin), - //! - // Key to toggle follow mode when in the map view. - // + /* Key to zoom out when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_follow), + CONFIG_VARIABLE_KEY(key_map_zoomout), - //! - // Key to toggle the grid display when in the map view. - // + /* Key to zoom out the maximum amount when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_grid), + CONFIG_VARIABLE_KEY(key_map_maxzoom), - //! - // Key to set a mark when in the map view. - // + /* Key to toggle follow mode when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_mark), + CONFIG_VARIABLE_KEY(key_map_follow), - //! - // Key to clear all marks when in the map view. - // + /* Key to toggle the grid display when in the map view. */ - CONFIG_VARIABLE_KEY(key_map_clearmark), + CONFIG_VARIABLE_KEY(key_map_grid), - //! - // Key to select weapon 1. - // + /* Key to set a mark when in the map view. */ - CONFIG_VARIABLE_KEY(key_weapon1), + CONFIG_VARIABLE_KEY(key_map_mark), - //! - // Key to select weapon 2. - // + /* Key to clear all marks when in the map view. */ - CONFIG_VARIABLE_KEY(key_weapon2), + CONFIG_VARIABLE_KEY(key_map_clearmark), - //! - // Key to select weapon 3. - // + /* Key to select weapon 1. */ - CONFIG_VARIABLE_KEY(key_weapon3), + CONFIG_VARIABLE_KEY(key_weapon1), - //! - // Key to select weapon 4. - // + /* Key to select weapon 2. */ - CONFIG_VARIABLE_KEY(key_weapon4), + CONFIG_VARIABLE_KEY(key_weapon2), - //! - // Key to select weapon 5. - // + /* Key to select weapon 3. */ - CONFIG_VARIABLE_KEY(key_weapon5), + CONFIG_VARIABLE_KEY(key_weapon3), - //! - // Key to select weapon 6. - // + /* Key to select weapon 4. */ - CONFIG_VARIABLE_KEY(key_weapon6), + CONFIG_VARIABLE_KEY(key_weapon4), - //! - // Key to select weapon 7. - // + /* Key to select weapon 5. */ - CONFIG_VARIABLE_KEY(key_weapon7), + CONFIG_VARIABLE_KEY(key_weapon5), - //! - // Key to select weapon 8. - // + /* Key to select weapon 6. */ - CONFIG_VARIABLE_KEY(key_weapon8), + CONFIG_VARIABLE_KEY(key_weapon6), - //! - // Key to cycle to the previous weapon. - // + /* Key to select weapon 7. */ - CONFIG_VARIABLE_KEY(key_prevweapon), + CONFIG_VARIABLE_KEY(key_weapon7), - //! - // Key to cycle to the next weapon. - // + /* Key to select weapon 8. */ - CONFIG_VARIABLE_KEY(key_nextweapon), + CONFIG_VARIABLE_KEY(key_weapon8), - //! - // @game heretic - // - // Key to use "quartz flask" artifact. - // + /* Key to cycle to the previous weapon. */ - CONFIG_VARIABLE_KEY(key_arti_quartz), + CONFIG_VARIABLE_KEY(key_prevweapon), - //! - // @game heretic - // - // Key to use "mystic urn" artifact. - // + /* Key to cycle to the next weapon. */ - CONFIG_VARIABLE_KEY(key_arti_urn), + CONFIG_VARIABLE_KEY(key_nextweapon), - //! - // @game heretic - // - // Key to use "timebomb of the ancients" artifact. - // + /* @game heretic + * + * Key to use "quartz flask" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_bomb), + CONFIG_VARIABLE_KEY(key_arti_quartz), - //! - // @game heretic - // - // Key to use "tome of power" artifact. - // + /* @game heretic + * + * Key to use "mystic urn" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_tome), + CONFIG_VARIABLE_KEY(key_arti_urn), - //! - // @game heretic - // - // Key to use "ring of invincibility" artifact. - // + /* @game heretic + * + * Key to use "timebomb of the ancients" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_ring), + CONFIG_VARIABLE_KEY(key_arti_bomb), - //! - // @game heretic - // - // Key to use "chaos device" artifact. - // + /* @game heretic + * + * Key to use "tome of power" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_chaosdevice), + CONFIG_VARIABLE_KEY(key_arti_tome), - //! - // @game heretic - // - // Key to use "shadowsphere" artifact. - // + /* @game heretic + * + * Key to use "ring of invincibility" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_shadowsphere), + CONFIG_VARIABLE_KEY(key_arti_ring), - //! - // @game heretic - // - // Key to use "wings of wrath" artifact. - // + /* @game heretic + * + * Key to use "chaos device" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_wings), + CONFIG_VARIABLE_KEY(key_arti_chaosdevice), - //! - // @game heretic - // - // Key to use "torch" artifact. - // + /* @game heretic + * + * Key to use "shadowsphere" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_torch), + CONFIG_VARIABLE_KEY(key_arti_shadowsphere), - //! - // @game heretic - // - // Key to use "morph ovum" artifact. - // + /* @game heretic + * + * Key to use "wings of wrath" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_morph), + CONFIG_VARIABLE_KEY(key_arti_wings), - //! - // @game hexen - // - // Key to use one of each artifact. - // + /* @game heretic + * + * Key to use "torch" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_all), + CONFIG_VARIABLE_KEY(key_arti_torch), - //! - // @game hexen - // - // Key to use "quartz flask" artifact. - // + /* @game heretic + * + * Key to use "morph ovum" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_health), + CONFIG_VARIABLE_KEY(key_arti_morph), - //! - // @game hexen - // - // Key to use "flechette" artifact. - // + /* @game hexen + * + * Key to use one of each artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_poisonbag), + CONFIG_VARIABLE_KEY(key_arti_all), - //! - // @game hexen - // - // Key to use "disc of repulsion" artifact. - // + /* @game hexen + * + * Key to use "quartz flask" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_blastradius), + CONFIG_VARIABLE_KEY(key_arti_health), - //! - // @game hexen - // - // Key to use "chaos device" artifact. - // + /* @game hexen + * + * Key to use "flechette" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_teleport), + CONFIG_VARIABLE_KEY(key_arti_poisonbag), - //! - // @game hexen - // - // Key to use "banishment device" artifact. - // + /* @game hexen + * + * Key to use "disc of repulsion" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_teleportother), + CONFIG_VARIABLE_KEY(key_arti_blastradius), - //! - // @game hexen - // - // Key to use "porkalator" artifact. - // + /* @game hexen + * + * Key to use "chaos device" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_egg), + CONFIG_VARIABLE_KEY(key_arti_teleport), - //! - // @game hexen - // - // Key to use "icon of the defender" artifact. - // + /* @game hexen + * + * Key to use "banishment device" artifact. + */ - CONFIG_VARIABLE_KEY(key_arti_invulnerability), + CONFIG_VARIABLE_KEY(key_arti_teleportother), - //! - // Key to re-display last message. - // + /* @game hexen + * + * Key to use "porkalator" artifact. + */ - CONFIG_VARIABLE_KEY(key_message_refresh), + CONFIG_VARIABLE_KEY(key_arti_egg), - //! - // Key to quit the game when recording a demo. - // + /* @game hexen + * + * Key to use "icon of the defender" artifact. + */ - CONFIG_VARIABLE_KEY(key_demo_quit), + CONFIG_VARIABLE_KEY(key_arti_invulnerability), - //! - // Key to send a message during multiplayer games. - // + /* Key to re-display last message. */ - CONFIG_VARIABLE_KEY(key_multi_msg), + CONFIG_VARIABLE_KEY(key_message_refresh), - //! - // Key to send a message to player 1 during multiplayer games. - // + /* Key to quit the game when recording a demo. */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer1), + CONFIG_VARIABLE_KEY(key_demo_quit), - //! - // Key to send a message to player 2 during multiplayer games. - // + /* Key to send a message during multiplayer games. */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer2), + CONFIG_VARIABLE_KEY(key_multi_msg), - //! - // Key to send a message to player 3 during multiplayer games. - // + /* Key to send a message to player 1 during multiplayer games. */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer3), + CONFIG_VARIABLE_KEY(key_multi_msgplayer1), - //! - // Key to send a message to player 4 during multiplayer games. - // + /* Key to send a message to player 2 during multiplayer games. */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer4), + CONFIG_VARIABLE_KEY(key_multi_msgplayer2), - //! - // @game hexen strife - // - // Key to send a message to player 5 during multiplayer games. - // + /* Key to send a message to player 3 during multiplayer games. */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer5), + CONFIG_VARIABLE_KEY(key_multi_msgplayer3), - //! - // @game hexen strife - // - // Key to send a message to player 6 during multiplayer games. - // + /* Key to send a message to player 4 during multiplayer games. */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer6), + CONFIG_VARIABLE_KEY(key_multi_msgplayer4), - //! - // @game hexen strife - // - // Key to send a message to player 7 during multiplayer games. - // + /* @game hexen strife + * + * Key to send a message to player 5 during multiplayer games. + */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer7), + CONFIG_VARIABLE_KEY(key_multi_msgplayer5), - //! - // @game hexen strife - // - // Key to send a message to player 8 during multiplayer games. - // + /* @game hexen strife + * + * Key to send a message to player 6 during multiplayer games. + */ - CONFIG_VARIABLE_KEY(key_multi_msgplayer8), + CONFIG_VARIABLE_KEY(key_multi_msgplayer6), + + /* @game hexen strife + * + * Key to send a message to player 7 during multiplayer games. + */ + + CONFIG_VARIABLE_KEY(key_multi_msgplayer7), + + /* @game hexen strife + * + * Key to send a message to player 8 during multiplayer games. + */ + + CONFIG_VARIABLE_KEY(key_multi_msgplayer8), }; static default_collection_t extra_defaults = @@ -2075,737 +1680,815 @@ static default_collection_t extra_defaults = NULL, }; -// Search a collection for a variable +/* Mapping from DOS keyboard scan code to internal key code (as defined + * in doomkey.h). I think I (fraggle) reused this from somewhere else + * but I can't find where. Anyway, notes: + * * KEY_PAUSE is wrong - it's in the KEY_NUMLOCK spot. This shouldn't + * matter in terms of Vanilla compatibility because neither of + * those were valid for key bindings. + * * There is no proper scan code for PrintScreen (on DOS machines it + * sends an interrupt). So I added a fake scan code of 126 for it. + * The presence of this is important so we can bind PrintScreen as + * a screenshot key. + */ + +static const int scantokey[128] = +{ + 0, + 27, + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '-', + '=', + KEY_BACKSPACE, + 9, + 'q', + 'w', + 'e', + 'r', + 't', + 'y', + 'u', + 'i', + 'o', + 'p', + '[', + ']', + 13, + KEY_RCTRL, + 'a', + 's', + 'd', + 'f', + 'g', + 'h', + 'j', + 'k', + 'l', + ';', + '\'', + '`', + KEY_RSHIFT, + '\\', + 'z', + 'x', + 'c', + 'v', + 'b', + 'n', + 'm', + ',', + '.', + '/', + KEY_RSHIFT, + KEYP_MULTIPLY, + KEY_RALT, + ' ', + KEY_CAPSLOCK, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + + /* KEY_NUMLOCK? */ + + KEY_PAUSE, + KEY_SCRLCK, + KEY_HOME, + KEY_UPARROW, + KEY_PGUP, + KEY_MINUS, + KEY_LEFTARROW, + KEYP_5, + KEY_RIGHTARROW, + KEYP_PLUS, + KEY_END, + KEY_DOWNARROW, + KEY_PGDN, + KEY_INS, + KEY_DEL, + 0, + 0, + 0, + KEY_F11, + KEY_F12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + KEY_PRTSCR, + 0, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* DEFAULTS */ + +/* Location where all configuration data is stored - default.cfg, savegames, + * etc. + */ -static default_t *SearchCollection(default_collection_t *collection, const char *name) +const char *configdir; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: search_collection + * + * Description: + * Search a collection for a variable + * + ****************************************************************************/ + +static default_t *search_collection(default_collection_t *collection, + const char *name) { - int i; + int i; - for (i=0; inumdefaults; ++i) + for (i = 0; i < collection->numdefaults; ++i) { - if (!strcmp(name, collection->defaults[i].name)) + if (!strcmp(name, collection->defaults[i].name)) { - return &collection->defaults[i]; + return &collection->defaults[i]; } } - return NULL; + return NULL; } -// Mapping from DOS keyboard scan code to internal key code (as defined -// in doomkey.h). I think I (fraggle) reused this from somewhere else -// but I can't find where. Anyway, notes: -// * KEY_PAUSE is wrong - it's in the KEY_NUMLOCK spot. This shouldn't -// matter in terms of Vanilla compatibility because neither of -// those were valid for key bindings. -// * There is no proper scan code for PrintScreen (on DOS machines it -// sends an interrupt). So I added a fake scan code of 126 for it. -// The presence of this is important so we can bind PrintScreen as -// a screenshot key. -static const int scantokey[128] = +static void save_default_collection(default_collection_t *collection) { - 0 , 27, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', KEY_BACKSPACE, 9, - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', 13, KEY_RCTRL, 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', KEY_RSHIFT,'\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,KEYP_MULTIPLY, - KEY_RALT, ' ', KEY_CAPSLOCK,KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, - KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, /*KEY_NUMLOCK?*/KEY_PAUSE,KEY_SCRLCK,KEY_HOME, - KEY_UPARROW,KEY_PGUP,KEY_MINUS,KEY_LEFTARROW,KEYP_5,KEY_RIGHTARROW,KEYP_PLUS,KEY_END, - KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0, 0, 0, KEY_F11, - KEY_F12, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, KEY_PRTSCR, 0 -}; + default_t *defaults; + int i; + int v; + FILE *f; + f = fopen(collection->filename, "w"); + if (!f) return; /* can't write the file, but don't complain */ -static void SaveDefaultCollection(default_collection_t *collection) -{ - default_t *defaults; - int i, v; - FILE *f; - - f = M_fopen(collection->filename, "w"); - if (!f) - return; // can't write the file, but don't complain - - defaults = collection->defaults; - - for (i=0 ; inumdefaults ; i++) + defaults = collection->defaults; + + for (i = 0; i < collection->numdefaults; i++) { - int chars_written; + int chars_written; - // Ignore unbound variables + /* Ignore unbound variables */ - if (!defaults[i].bound) + if (!defaults[i].bound) { - continue; + continue; } - // Print the name and line up all values at 30 characters + /* Print the name and line up all values at 30 characters */ - chars_written = fprintf(f, "%s ", defaults[i].name); + chars_written = fprintf(f, "%s ", defaults[i].name); - for (; chars_written < 30; ++chars_written) - fprintf(f, " "); + for (; chars_written < 30; ++chars_written) + fprintf(f, " "); - // Print the value + /* Print the value */ - switch (defaults[i].type) + switch (defaults[i].type) { - case DEFAULT_KEY: + case DEFAULT_KEY: - // use the untranslated version if we can, to reduce - // the possibility of screwing up the user's config - // file - - v = *defaults[i].location.i; + /* use the untranslated version if we can, to reduce + * the possibility of screwing up the user's config + * file + */ - if (v == KEY_RSHIFT) - { - // Special case: for shift, force scan code for - // right shift, as this is what Vanilla uses. - // This overrides the change check below, to fix - // configuration files made by old versions that - // mistakenly used the scan code for left shift. + v = *defaults[i].location.i; - v = 54; - } - else if (defaults[i].untranslated - && v == defaults[i].original_translated) - { - // Has not been changed since the last time we - // read the config file. + if (v == KEY_RSHIFT) + { + /* Special case: for shift, force scan code for + * right shift, as this is what Vanilla uses. + * This overrides the change check below, to fix + * configuration files made by old versions that + * mistakenly used the scan code for left shift. + */ + + v = 54; + } + else if (defaults[i].untranslated && + v == defaults[i].original_translated) + { + /* Has not been changed since the last time we read the config + * file. + */ - v = defaults[i].untranslated; - } - else - { - // search for a reverse mapping back to a scancode - // in the scantokey table + v = defaults[i].untranslated; + } + else + { + /* search for a reverse mapping back to a scancode + * in the scantokey table + */ - int s; + int s; - for (s=0; s<128; ++s) + for (s = 0; s < 128; ++s) + { + if (scantokey[s] == v) { - if (scantokey[s] == v) - { - v = s; - break; - } + v = s; + break; } } + } - fprintf(f, "%i", v); - break; + fprintf(f, "%i", v); + break; - case DEFAULT_INT: - fprintf(f, "%i", *defaults[i].location.i); - break; + case DEFAULT_INT: + fprintf(f, "%i", *defaults[i].location.i); + break; - case DEFAULT_INT_HEX: - fprintf(f, "0x%x", *defaults[i].location.i); - break; + case DEFAULT_INT_HEX: + fprintf(f, "0x%x", *defaults[i].location.i); + break; - case DEFAULT_FLOAT: - fprintf(f, "%f", *defaults[i].location.f); - break; + case DEFAULT_FLOAT: + fprintf(f, "%f", *defaults[i].location.f); + break; - case DEFAULT_STRING: - fprintf(f,"\"%s\"", *defaults[i].location.s); - break; + case DEFAULT_STRING: + fprintf(f, "\"%s\"", *defaults[i].location.s); + break; } - fprintf(f, "\n"); + fprintf(f, "\n"); } - fclose (f); + fclose(f); } -// Parses integer values in the configuration file +/**************************************************************************** + * Name: parse_int_parameter + * + * Description: + * Parses integer values in the configuration file + * + ****************************************************************************/ -static int ParseIntParameter(const char *strparm) +static int parse_int_parameter(const char *strparm) { - int parm; + int param; - if (strparm[0] == '0' && strparm[1] == 'x') - sscanf(strparm+2, "%x", (unsigned int *) &parm); - else - sscanf(strparm, "%i", &parm); + if (strparm[0] == '0' && strparm[1] == 'x') + sscanf(strparm + 2, "%x", (unsigned int *)¶m); + else + sscanf(strparm, "%i", ¶m); - return parm; + return param; } -static void SetVariable(default_t *def, const char *value) +static void set_variable(default_t *def, const char *value) { - int intparm; + int intparm; - // parameter found + /* parameter found */ - switch (def->type) + switch (def->type) { - case DEFAULT_STRING: - *def->location.s = M_StringDuplicate(value); - break; + case DEFAULT_STRING: + *def->location.s = m_string_duplicate(value); + break; - case DEFAULT_INT: - case DEFAULT_INT_HEX: - *def->location.i = ParseIntParameter(value); - break; + case DEFAULT_INT: + case DEFAULT_INT_HEX: + *def->location.i = parse_int_parameter(value); + break; - case DEFAULT_KEY: - - // translate scancodes read from config - // file (save the old value in untranslated) + case DEFAULT_KEY: - intparm = ParseIntParameter(value); - def->untranslated = intparm; - if (intparm >= 0 && intparm < 128) - { - intparm = scantokey[intparm]; - } - else - { - intparm = 0; - } + /* translate scancodes read from config + * file (save the old value in untranslated) + */ - def->original_translated = intparm; - *def->location.i = intparm; - break; - - case DEFAULT_FLOAT: + intparm = parse_int_parameter(value); + def->untranslated = intparm; + if (intparm >= 0 && intparm < 128) { - // Different locales use different decimal separators. - // However, the choice of the current locale isn't always - // under our own control. If the atof() function fails to - // parse the string representing the floating point number - // using the current locale's decimal separator, it will - // return 0, resulting in silent sound effects. To - // mitigate this, we replace the first non-digit, - // non-minus character in the string with the current - // locale's decimal separator before passing it to atof(). - struct lconv *lc = localeconv(); - char dec, *str; - int i = 0; - - dec = lc->decimal_point[0]; - str = M_StringDuplicate(value); - - // Skip sign indicators. - if (str[i] == '-' || str[i] == '+') - { - i++; - } + intparm = scantokey[intparm]; + } + else + { + intparm = 0; + } - for ( ; str[i] != '\0'; i++) - { - if (!isdigit(str[i])) - { - str[i] = dec; - break; - } - } + def->original_translated = intparm; + *def->location.i = intparm; + break; + + case DEFAULT_FLOAT: + { + /* Different locales use different decimal separators. + * However, the choice of the current locale isn't always + * under our own control. If the atof() function fails to + * parse the string representing the floating point number + * using the current locale's decimal separator, it will + * return 0, resulting in silent sound effects. To + * mitigate this, we replace the first non-digit, + * non-minus character in the string with the current + * locale's decimal separator before passing it to atof(). + */ + + struct lconv *lc = localeconv(); + char dec; + char *str; + int i = 0; + + dec = lc->decimal_point[0]; + str = m_string_duplicate(value); + + /* Skip sign indicators. */ + + if (str[i] == '-' || str[i] == '+') + { + i++; + } + + for (; str[i] != '\0'; i++) + { + if (!isdigit(str[i])) + { + str[i] = dec; + break; + } + } - *def->location.f = (float) atof(str); - free(str); - } - break; + *def->location.f = (float)atof(str); + free(str); + } + break; } } -static void LoadDefaultCollection(default_collection_t *collection) +static void load_default_collection(default_collection_t *collection) { - FILE *f; - default_t *def; - char defname[80]; - char strparm[100]; + FILE *f; + default_t *def; + char defname[80]; + char strparm[100]; + + /* read the file in, overriding any set defaults */ - // read the file in, overriding any set defaults - f = M_fopen(collection->filename, "r"); + f = fopen(collection->filename, "r"); - if (f == NULL) + if (f == NULL) { - // File not opened, but don't complain. - // It's probably just the first time they ran the game. + /* File not opened, but don't complain. + * It's probably just the first time they ran the game. + */ - return; + return; } - while (!feof(f)) + while (!feof(f)) { - if (fscanf(f, "%79s %99[^\n]\n", defname, strparm) != 2) + if (fscanf(f, "%79s %99[^\n]\n", defname, strparm) != 2) { - // This line doesn't match + /* This line doesn't match */ - continue; + continue; } - // Find the setting in the list + /* Find the setting in the list */ - def = SearchCollection(collection, defname); + def = search_collection(collection, defname); - if (def == NULL || !def->bound) + if (def == NULL || !def->bound) { - // Unknown variable? Unbound variables are also treated - // as unknown. + /* Unknown variable? Unbound variables are also treated + * as unknown. + */ - continue; + continue; } - // Strip off trailing non-printable characters (\r characters - // from DOS text files) + /* Strip off trailing non-printable characters (\r characters + * from DOS text files) + */ - while (strlen(strparm) > 0 && !isprint(strparm[strlen(strparm)-1])) + while (strlen(strparm) > 0 && !isprint(strparm[strlen(strparm) - 1])) { - strparm[strlen(strparm)-1] = '\0'; + strparm[strlen(strparm) - 1] = '\0'; } - // Surrounded by quotes? If so, remove them. - if (strlen(strparm) >= 2 - && strparm[0] == '"' && strparm[strlen(strparm) - 1] == '"') + /* Surrounded by quotes? If so, remove them. */ + + if (strlen(strparm) >= 2 && strparm[0] == '"' && + strparm[strlen(strparm) - 1] == '"') { - strparm[strlen(strparm) - 1] = '\0'; - memmove(strparm, strparm + 1, sizeof(strparm) - 1); + strparm[strlen(strparm) - 1] = '\0'; + memmove(strparm, strparm + 1, sizeof(strparm) - 1); } - SetVariable(def, strparm); + set_variable(def, strparm); } - fclose (f); + fclose(f); } -// Set the default filenames to use for configuration files. +/* Get a configuration file variable by its name */ -void M_SetConfigFilenames(const char *main_config, const char *extra_config) +static default_t *get_default_for_name(const char *name) { - default_main_config = main_config; - default_extra_config = extra_config; + default_t *result; + + /* Try the main list and the extras */ + + result = search_collection(&doom_defaults, name); + + if (result == NULL) + { + result = search_collection(&extra_defaults, name); + } + + /* Not found? Internal error. */ + + if (result == NULL) + { + i_error("Unknown configuration variable: '%s'", name); + } + + return result; } -// -// M_SaveDefaults -// +/* Get the path to the default configuration dir to use, if NULL + * is passed to m_set_config_dir. + */ -void M_SaveDefaults (void) +static char *get_default_config_dir(void) { - SaveDefaultCollection(&doom_defaults); - SaveDefaultCollection(&extra_defaults); + /* Configuration settings are stored in an OS-appropriate path + * determined by SDL. On typical Unix systems, this might be + * ~/.local/share/chocolate-doom. On Windows, we behave like + * Vanilla Doom and save in the current directory. + */ + + char *result = CONFIG_GAMES_NXDOOM_PREFDIR "/"; + char *copy = m_string_duplicate(result); + return copy; } -// -// Save defaults to alternate filenames -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void M_SaveDefaultsAlternate(const char *main, const char *extra) -{ - const char *orig_main; - const char *orig_extra; +/* Set the default filenames to use for configuration files. */ - // Temporarily change the filenames +void m_set_config_filenames(const char *main_config, + const char *extra_config) +{ + default_main_config = main_config; + default_extra_config = extra_config; +} - orig_main = doom_defaults.filename; - orig_extra = extra_defaults.filename; +void m_save_defaults(void) +{ + save_default_collection(&doom_defaults); + save_default_collection(&extra_defaults); +} - doom_defaults.filename = main; - extra_defaults.filename = extra; +/* Save defaults to alternate filenames */ - M_SaveDefaults(); +void m_save_defaults_alternate(const char *main, const char *extra) +{ + const char *orig_main; + const char *orig_extra; - // Restore normal filenames + /* Temporarily change the filenames */ - doom_defaults.filename = orig_main; - extra_defaults.filename = orig_extra; -} + orig_main = doom_defaults.filename; + orig_extra = extra_defaults.filename; -// -// M_LoadDefaults -// + doom_defaults.filename = main; + extra_defaults.filename = extra; -void M_LoadDefaults (void) -{ - int i; + m_save_defaults(); - // This variable is a special snowflake for no good reason. - M_BindStringVariable("autoload_path", &autoload_path); + /* Restore normal filenames */ - // check for a custom default file + doom_defaults.filename = orig_main; + extra_defaults.filename = orig_extra; +} - //! - // @arg - // @vanilla - // - // Load main configuration from the specified file, instead of the - // default. - // +void m_load_defaults(void) +{ + int i; - i = M_CheckParmWithArgs("-config", 1); + /* This variable is a special snowflake for no good reason. */ - if (i) - { - doom_defaults.filename = myargv[i+1]; - printf (" default file: %s\n",doom_defaults.filename); - } - else - { - doom_defaults.filename - = M_StringJoin(configdir, default_main_config, NULL); - } + m_bind_string_variable("autoload_path", &autoload_path); - printf("saving config in %s\n", doom_defaults.filename); + /* check for a custom default file */ - //! - // @arg - // - // Load additional configuration from the specified file, instead of - // the default. - // + /* @arg + * @vanilla + * + * Load main configuration from the specified file, instead of the + * default. + */ - i = M_CheckParmWithArgs("-extraconfig", 1); + i = m_check_parm_with_args("-config", 1); - if (i) + if (i) { - extra_defaults.filename = myargv[i+1]; - printf(" extra configuration file: %s\n", - extra_defaults.filename); + doom_defaults.filename = myargv[i + 1]; + printf("\tdefault file: %s\n", doom_defaults.filename); } - else + else { - extra_defaults.filename - = M_StringJoin(configdir, default_extra_config, NULL); + doom_defaults.filename = + m_string_join(configdir, default_main_config, NULL); } - LoadDefaultCollection(&doom_defaults); - LoadDefaultCollection(&extra_defaults); -} - -// Get a configuration file variable by its name + printf("saving config in %s\n", doom_defaults.filename); -static default_t *GetDefaultForName(const char *name) -{ - default_t *result; - - // Try the main list and the extras + /* @arg + * + * Load additional configuration from the specified file, instead of + * the default. + */ - result = SearchCollection(&doom_defaults, name); + i = m_check_parm_with_args("-extraconfig", 1); - if (result == NULL) + if (i) { - result = SearchCollection(&extra_defaults, name); + extra_defaults.filename = myargv[i + 1]; + printf(" extra configuration file: %s\n", + extra_defaults.filename); } - - // Not found? Internal error. - - if (result == NULL) + else { - I_Error("Unknown configuration variable: '%s'", name); + extra_defaults.filename = + m_string_join(configdir, default_extra_config, NULL); } - return result; + load_default_collection(&doom_defaults); + load_default_collection(&extra_defaults); } -// -// Bind a variable to a given configuration file variable, by name. -// - -void M_BindIntVariable(const char *name, int *location) -{ - default_t *variable; - - variable = GetDefaultForName(name); - assert(variable->type == DEFAULT_INT - || variable->type == DEFAULT_INT_HEX - || variable->type == DEFAULT_KEY); - - variable->location.i = location; - variable->bound = true; -} +/* Bind a variable to a given configuration file variable, by name. */ -void M_BindFloatVariable(const char *name, float *location) +void m_bind_int_variable(const char *name, int *location) { - default_t *variable; + default_t *variable; - variable = GetDefaultForName(name); - assert(variable->type == DEFAULT_FLOAT); + variable = get_default_for_name(name); + assert(variable->type == DEFAULT_INT || + variable->type == DEFAULT_INT_HEX || variable->type == DEFAULT_KEY); - variable->location.f = location; - variable->bound = true; + variable->location.i = location; + variable->bound = true; } -void M_BindStringVariable(const char *name, char **location) +void m_bind_float_variable(const char *name, float *location) { - default_t *variable; + default_t *variable; - variable = GetDefaultForName(name); - assert(variable->type == DEFAULT_STRING); + variable = get_default_for_name(name); + assert(variable->type == DEFAULT_FLOAT); - variable->location.s = location; - variable->bound = true; + variable->location.f = location; + variable->bound = true; } -// Set the value of a particular variable; an API function for other -// parts of the program to assign values to config variables by name. - -boolean M_SetVariable(const char *name, const char *value) +void m_bind_string_variable(const char *name, char **location) { - default_t *variable; - - variable = GetDefaultForName(name); - - if (variable == NULL || !variable->bound) - { - return false; - } + default_t *variable; - SetVariable(variable, value); + variable = get_default_for_name(name); + assert(variable->type == DEFAULT_STRING); - return true; + variable->location.s = location; + variable->bound = true; } -// Get the value of a variable. +/* Set the value of a particular variable; an API function for other + * parts of the program to assign values to config variables by name. + */ -int M_GetIntVariable(const char *name) +boolean m_set_variable(const char *name, const char *value) { - default_t *variable; + default_t *variable; - variable = GetDefaultForName(name); + variable = get_default_for_name(name); - if (variable == NULL || !variable->bound - || (variable->type != DEFAULT_INT && variable->type != DEFAULT_INT_HEX)) + if (variable == NULL || !variable->bound) { - return 0; + return false; } - return *variable->location.i; -} - -const char *M_GetStringVariable(const char *name) -{ - default_t *variable; - - variable = GetDefaultForName(name); - - if (variable == NULL || !variable->bound - || variable->type != DEFAULT_STRING) - { - return NULL; - } + set_variable(variable, value); - return *variable->location.s; + return true; } -float M_GetFloatVariable(const char *name) +const char *m_get_string_variable(const char *name) { - default_t *variable; + default_t *variable; - variable = GetDefaultForName(name); + variable = get_default_for_name(name); - if (variable == NULL || !variable->bound - || variable->type != DEFAULT_FLOAT) + if (variable == NULL || !variable->bound || + variable->type != DEFAULT_STRING) { - return 0; + return NULL; } - return *variable->location.f; -} - -// Get the path to the default configuration dir to use, if NULL -// is passed to M_SetConfigDir. - -static char *GetDefaultConfigDir(void) -{ -#if !defined(_WIN32) || defined(_WIN32_WCE) - - // Configuration settings are stored in an OS-appropriate path - // determined by SDL. On typical Unix systems, this might be - // ~/.local/share/chocolate-doom. On Windows, we behave like - // Vanilla Doom and save in the current directory. - - char *result; - char *copy; - - result = SDL_GetPrefPath("", PACKAGE_TARNAME); - if (result != NULL) - { - copy = M_StringDuplicate(result); - SDL_free(result); - return copy; - } -#endif /* #ifndef _WIN32 */ - return M_StringDuplicate(exedir); + return *variable->location.s; } -// -// SetConfigDir: -// -// Sets the location of the configuration directory, where configuration -// files are stored - default.cfg, chocolate-doom.cfg, savegames, etc. -// +/* SetConfigDir: + * + * Sets the location of the configuration directory, where configuration + * files are stored - default.cfg, chocolate-doom.cfg, savegames, etc. + */ -void M_SetConfigDir(const char *dir) +void m_set_config_dir(const char *dir) { - // Use the directory that was passed, or find the default. + /* Use the directory that was passed, or find the default. */ - if (dir != NULL) + if (dir != NULL) { - configdir = dir; + configdir = dir; } - else + else { - configdir = GetDefaultConfigDir(); + configdir = get_default_config_dir(); } - if (strcmp(configdir, exedir) != 0) + if (strcmp(configdir, exedir) != 0) { - printf("Using %s for configuration and saves\n", configdir); + printf("Using %s for configuration and saves\n", configdir); } - // Make the directory if it doesn't already exist: + /* Make the directory if it doesn't already exist: */ - M_MakeDirectory(configdir); + m_make_directory(configdir); } -#define MUSIC_PACK_README \ -"Extract music packs into this directory in .flac or .ogg format;\n" \ -"they will be automatically loaded based on filename to replace the\n" \ -"in-game music with high quality versions.\n\n" \ -"For more information check here:\n\n" \ -" \n\n" +/* Set the value of music_pack_path if it is currently empty, and create + * the directory if necessary. + */ -// Set the value of music_pack_path if it is currently empty, and create -// the directory if necessary. -void M_SetMusicPackDir(void) +void m_set_music_pack_dir(void) { - const char *current_path; - char *prefdir, *music_pack_path, *readme_path; + const char *current_path; + char *prefdir; + char *music_pack_path; - current_path = M_GetStringVariable("music_pack_path"); + current_path = m_get_string_variable("music_pack_path"); - if (current_path != NULL && strlen(current_path) > 0) + if (current_path != NULL && strlen(current_path) > 0) { - return; + return; } - prefdir = SDL_GetPrefPath("", PACKAGE_TARNAME); - if (prefdir == NULL) - { - printf("M_SetMusicPackDir: SDL_GetPrefPath failed, music pack directory not set\n"); - return; - } - music_pack_path = M_StringJoin(prefdir, "music-packs", NULL); - - M_MakeDirectory(prefdir); - M_MakeDirectory(music_pack_path); - M_SetVariable("music_pack_path", music_pack_path); + prefdir = CONFIG_GAMES_NXDOOM_PREFDIR "/"; + music_pack_path = m_string_join(prefdir, "music-packs", NULL); - // We write a README file with some basic instructions on how to use - // the directory. - readme_path = M_StringJoin(music_pack_path, DIR_SEPARATOR_S, - "README.txt", NULL); - M_WriteFile(readme_path, MUSIC_PACK_README, strlen(MUSIC_PACK_README)); + m_make_directory(prefdir); + m_make_directory(music_pack_path); + m_set_variable("music_pack_path", music_pack_path); - free(readme_path); - free(music_pack_path); - SDL_free(prefdir); + free(music_pack_path); } -// -// Calculate the path to the directory to use to store save games. -// Creates the directory as necessary. -// +/* Calculate the path to the directory to use to store save games. + * Creates the directory as necessary. + */ -char *M_GetSaveGameDir(const char *iwadname) +char *m_get_save_game_dir(const char *iwadname) { - char *savegamedir; - char *topdir; - int p; - - //! - // @arg - // - // Specify a path from which to load and save games. If the - // directory does not exist then it will automatically be created. - // - - p = M_CheckParmWithArgs("-savedir", 1); - if (p) + char *savegamedir; + char *topdir; + int p; + + /* @arg + * + * Specify a path from which to load and save games. If the + * directory does not exist then it will automatically be created. + */ + + p = m_check_parm_with_args("-savedir", 1); + if (p) { - savegamedir = myargv[p + 1]; - if (!M_FileExists(savegamedir)) + savegamedir = myargv[p + 1]; + if (!m_file_exists(savegamedir)) { - M_MakeDirectory(savegamedir); + m_make_directory(savegamedir); } - // add separator at end just in case - savegamedir = M_StringJoin(savegamedir, DIR_SEPARATOR_S, NULL); + /* add separator at end just in case */ - printf("Save directory changed to %s.\n", savegamedir); - } -#ifdef _WIN32 - // In -cdrom mode, we write savegames to a specific directory - // in addition to configs. + savegamedir = m_string_join(savegamedir, DIR_SEPARATOR_S, NULL); - else if (M_ParmExists("-cdrom")) - { - savegamedir = M_StringDuplicate(configdir); + printf("Save directory changed to %s.\n", savegamedir); } -#endif - // If not "doing" a configuration directory (Windows), don't "do" - // a savegame directory, either. - else if (!strcmp(configdir, exedir)) + + /* If not "doing" a configuration directory (Windows), don't "do" + * a savegame directory, either. + */ + + else if (!strcmp(configdir, exedir)) { - savegamedir = M_StringDuplicate(""); + savegamedir = m_string_duplicate(""); } - else + else { - // ~/.local/share/chocolate-doom/savegames + /* ~/.local/share/chocolate-doom/savegames */ - topdir = M_StringJoin(configdir, "savegames", NULL); - M_MakeDirectory(topdir); + topdir = m_string_join(configdir, "savegames", NULL); + m_make_directory(topdir); - // eg. ~/.local/share/chocolate-doom/savegames/doom2.wad/ + /* eg. ~/.local/share/chocolate-doom/savegames/doom2.wad/ */ - savegamedir = M_StringJoin(topdir, DIR_SEPARATOR_S, iwadname, - DIR_SEPARATOR_S, NULL); + savegamedir = m_string_join(topdir, DIR_SEPARATOR_S, iwadname, + DIR_SEPARATOR_S, NULL); - M_MakeDirectory(savegamedir); + m_make_directory(savegamedir); - free(topdir); + free(topdir); } - return savegamedir; + return savegamedir; } -// -// Calculate the path to the directory for autoloaded WADs/DEHs. -// Creates the directory as necessary. -// -char *M_GetAutoloadDir(const char *iwadname) +/* Calculate the path to the directory for autoloaded WADs/DEHs. + * Creates the directory as necessary. + */ + +char *m_get_autoload_dir(const char *iwadname) { - char *result; + char *result; - if (autoload_path == NULL || strlen(autoload_path) == 0) + if (autoload_path == NULL || strlen(autoload_path) == 0) { - char *prefdir; - prefdir = SDL_GetPrefPath("", PACKAGE_TARNAME); - if (prefdir == NULL) - { - printf("M_GetAutoloadDir: SDL_GetPrefPath failed\n"); - return NULL; - } - autoload_path = M_StringJoin(prefdir, "autoload", NULL); - SDL_free(prefdir); + char *prefdir = CONFIG_GAMES_NXDOOM_PREFDIR "/"; + autoload_path = m_string_join(prefdir, "autoload", NULL); } - M_MakeDirectory(autoload_path); + m_make_directory(autoload_path); - result = M_StringJoin(autoload_path, DIR_SEPARATOR_S, iwadname, NULL); - M_MakeDirectory(result); + result = m_string_join(autoload_path, DIR_SEPARATOR_S, iwadname, NULL); + m_make_directory(result); - // TODO: Add README file + /* TODO: Add README file */ - return result; -} \ No newline at end of file + return result; +} diff --git a/games/NXDoom/src/m_config.h b/games/NXDoom/src/m_config.h index 5939b6bef8f..5dd8358b742 100644 --- a/games/NXDoom/src/m_config.h +++ b/games/NXDoom/src/m_config.h @@ -1,43 +1,58 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Configuration file interface. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_config.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Configuration file interface. + * + ****************************************************************************/ #ifndef __M_CONFIG__ #define __M_CONFIG__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -void M_LoadDefaults(void); -void M_SaveDefaults(void); -void M_SaveDefaultsAlternate(const char *main, const char *extra); -void M_SetConfigDir(const char *dir); -void M_SetMusicPackDir(void); -void M_BindIntVariable(const char *name, int *variable); -void M_BindFloatVariable(const char *name, float *variable); -void M_BindStringVariable(const char *name, char **variable); -boolean M_SetVariable(const char *name, const char *value); -int M_GetIntVariable(const char *name); -const char *M_GetStringVariable(const char *name); -float M_GetFloatVariable(const char *name); -void M_SetConfigFilenames(const char *main_config, const char *extra_config); -char *M_GetSaveGameDir(const char *iwadname); -char *M_GetAutoloadDir(const char *iwadname); +/**************************************************************************** + * Public Data + ****************************************************************************/ extern const char *configdir; -#endif +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void m_load_defaults(void); +void m_save_defaults(void); +void m_save_defaults_alternate(const char *main, const char *extra); +void m_set_config_dir(const char *dir); +void m_set_music_pack_dir(void); +void m_bind_int_variable(const char *name, int *variable); +void m_bind_float_variable(const char *name, float *variable); +void m_bind_string_variable(const char *name, char **variable); +boolean m_set_variable(const char *name, const char *value); +const char *m_get_string_variable(const char *name); +void m_set_config_filenames(const char *main_config, + const char *extra_config); +char *m_get_save_game_dir(const char *iwadname); +char *m_get_autoload_dir(const char *iwadname); + +#endif /* __M_CONFIG__ */ diff --git a/games/NXDoom/src/m_controls.c b/games/NXDoom/src/m_controls.c index 1a5f520e144..2266df2ceaf 100644 --- a/games/NXDoom/src/m_controls.c +++ b/games/NXDoom/src/m_controls.c @@ -1,47 +1,56 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// +/**************************************************************************** + * apps/games/NXDoom/src/m_controls.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 1993-2008 Raven Software + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include -#include "doomtype.h" #include "doomkeys.h" +#include "doomtype.h" #include "m_config.h" #include "m_misc.h" -// -// Keyboard controls -// +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Keyboard controls */ int key_right = KEY_RIGHTARROW; int key_left = KEY_LEFTARROW; int key_up = KEY_UPARROW; -int key_down = KEY_DOWNARROW; -int key_strafeleft = ','; +int key_down = KEY_DOWNARROW; +int key_strafeleft = 0x2c; /* Comma, ',' */ int key_straferight = '.'; int key_fire = KEY_RCTRL; int key_use = ' '; int key_strafe = KEY_RALT; -int key_speed = KEY_RSHIFT; +int key_speed = KEY_RSHIFT; + +/* Heretic keyboard controls */ -// -// Heretic keyboard controls -// - int key_flyup = KEY_PGUP; int key_flydown = KEY_INS; int key_flycenter = KEY_HOME; @@ -65,44 +74,38 @@ int key_arti_wings = 0; int key_arti_torch = 0; int key_arti_morph = 0; -// -// Hexen key controls -// +/* Hexen key controls */ int key_jump = '/'; -int key_arti_all = KEY_BACKSPACE; -int key_arti_health = '\\'; -int key_arti_poisonbag = '0'; -int key_arti_blastradius = '9'; -int key_arti_teleport = '8'; -int key_arti_teleportother = '7'; -int key_arti_egg = '6'; +int key_arti_all = KEY_BACKSPACE; +int key_arti_health = '\\'; +int key_arti_poisonbag = '0'; +int key_arti_blastradius = '9'; +int key_arti_teleport = '8'; +int key_arti_teleportother = '7'; +int key_arti_egg = '6'; int key_arti_invulnerability = '5'; -// -// Strife key controls -// -// haleyjd 09/01/10 -// - -// Note: Strife also uses key_invleft, key_invright, key_jump, key_lookup, and -// key_lookdown, but with different default values. +/* Strife key controls + * + * haleyjd 09/01/10 + * + * Note: Strife also uses key_invleft, key_invright, key_jump, key_lookup, + * and key_lookdown, but with different default values. + */ int key_usehealth = 'h'; -int key_invquery = 'q'; -int key_mission = 'w'; -int key_invpop = 'z'; -int key_invkey = 'k'; -int key_invhome = KEY_HOME; -int key_invend = KEY_END; -int key_invuse = KEY_ENTER; -int key_invdrop = KEY_BACKSPACE; - +int key_invquery = 'q'; +int key_mission = 'w'; +int key_invpop = 'z'; +int key_invkey = 'k'; +int key_invhome = KEY_HOME; +int key_invend = KEY_END; +int key_invuse = KEY_ENTER; +int key_invdrop = KEY_BACKSPACE; -// -// Mouse controls -// +/* Mouse controls */ int mousebfire = 0; int mousebstrafe = 1; @@ -129,12 +132,12 @@ int key_pause = KEY_PAUSE; int key_demo_quit = 'q'; int key_spy = KEY_F12; -// Multiplayer chat keys: +/* Multiplayer chat keys: */ int key_multi_msg = 't'; int key_multi_msgplayer[8]; -// Weapon selection keys: +/* Weapon selection keys: */ int key_weapon1 = '1'; int key_weapon2 = '2'; @@ -147,52 +150,50 @@ int key_weapon8 = '8'; int key_prevweapon = 0; int key_nextweapon = 0; -// Map control keys: - -int key_map_north = KEY_UPARROW; -int key_map_south = KEY_DOWNARROW; -int key_map_east = KEY_RIGHTARROW; -int key_map_west = KEY_LEFTARROW; -int key_map_zoomin = '='; -int key_map_zoomout = '-'; -int key_map_toggle = KEY_TAB; -int key_map_maxzoom = '0'; -int key_map_follow = 'f'; -int key_map_grid = 'g'; -int key_map_mark = 'm'; +/* Map control keys: */ + +int key_map_north = KEY_UPARROW; +int key_map_south = KEY_DOWNARROW; +int key_map_east = KEY_RIGHTARROW; +int key_map_west = KEY_LEFTARROW; +int key_map_zoomin = '='; +int key_map_zoomout = '-'; +int key_map_toggle = KEY_TAB; +int key_map_maxzoom = '0'; +int key_map_follow = 'f'; +int key_map_grid = 'g'; +int key_map_mark = 'm'; int key_map_clearmark = 'c'; -// menu keys: - -int key_menu_activate = KEY_ESCAPE; -int key_menu_up = KEY_UPARROW; -int key_menu_down = KEY_DOWNARROW; -int key_menu_left = KEY_LEFTARROW; -int key_menu_right = KEY_RIGHTARROW; -int key_menu_back = KEY_BACKSPACE; -int key_menu_forward = KEY_ENTER; -int key_menu_confirm = 'y'; -int key_menu_abort = 'n'; - -int key_menu_help = KEY_F1; -int key_menu_save = KEY_F2; -int key_menu_load = KEY_F3; -int key_menu_volume = KEY_F4; -int key_menu_detail = KEY_F5; -int key_menu_qsave = KEY_F6; -int key_menu_endgame = KEY_F7; -int key_menu_messages = KEY_F8; -int key_menu_qload = KEY_F9; -int key_menu_quit = KEY_F10; -int key_menu_gamma = KEY_F11; +/* menu keys: */ + +int key_menu_activate = KEY_ESCAPE; +int key_menu_up = KEY_UPARROW; +int key_menu_down = KEY_DOWNARROW; +int key_menu_left = KEY_LEFTARROW; +int key_menu_right = KEY_RIGHTARROW; +int key_menu_back = KEY_BACKSPACE; +int key_menu_forward = KEY_ENTER; +int key_menu_confirm = 'y'; +int key_menu_abort = 'n'; + +int key_menu_help = KEY_F1; +int key_menu_save = KEY_F2; +int key_menu_load = KEY_F3; +int key_menu_volume = KEY_F4; +int key_menu_detail = KEY_F5; +int key_menu_qsave = KEY_F6; +int key_menu_endgame = KEY_F7; +int key_menu_messages = KEY_F8; +int key_menu_qload = KEY_F9; +int key_menu_quit = KEY_F10; +int key_menu_gamma = KEY_F11; int key_menu_incscreen = KEY_EQUALS; int key_menu_decscreen = KEY_MINUS; int key_menu_screenshot = 0; -// -// Joystick controls -// +/* Joystick controls */ int joybfire = 0; int joybstrafe = 1; @@ -218,240 +219,249 @@ int joybflyup = -1; int joybflydown = -1; int joybflycenter = -1; -// Control whether if a mouse button is double clicked, it acts like -// "use" has been pressed +/* Control whether if a mouse button is double clicked, it acts like + * "use" has been pressed + */ int dclick_use = 1; - -// -// Bind all of the common controls used by Doom and all other games. -// -void M_BindBaseControls(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Bind all of the common controls used by Doom and all other games. */ + +void m_bind_base_controls(void) { - M_BindIntVariable("key_right", &key_right); - M_BindIntVariable("key_left", &key_left); - M_BindIntVariable("key_up", &key_up); - M_BindIntVariable("key_down", &key_down); - M_BindIntVariable("key_strafeleft", &key_strafeleft); - M_BindIntVariable("key_straferight", &key_straferight); - M_BindIntVariable("key_fire", &key_fire); - M_BindIntVariable("key_use", &key_use); - M_BindIntVariable("key_strafe", &key_strafe); - M_BindIntVariable("key_speed", &key_speed); - - M_BindIntVariable("mouseb_fire", &mousebfire); - M_BindIntVariable("mouseb_strafe", &mousebstrafe); - M_BindIntVariable("mouseb_forward", &mousebforward); - M_BindIntVariable("mouseb_speed", &mousebspeed); - - M_BindIntVariable("joyb_fire", &joybfire); - M_BindIntVariable("joyb_strafe", &joybstrafe); - M_BindIntVariable("joyb_use", &joybuse); - M_BindIntVariable("joyb_speed", &joybspeed); - - M_BindIntVariable("joyb_menu_activate", &joybmenu); - M_BindIntVariable("joyb_toggle_automap", &joybautomap); - - // Extra controls that are not in the Vanilla versions: - - M_BindIntVariable("joyb_strafeleft", &joybstrafeleft); - M_BindIntVariable("joyb_straferight", &joybstraferight); - M_BindIntVariable("mouseb_strafeleft", &mousebstrafeleft); - M_BindIntVariable("mouseb_straferight", &mousebstraferight); - M_BindIntVariable("mouseb_turnleft", &mousebturnleft); - M_BindIntVariable("mouseb_turnright", &mousebturnright); - M_BindIntVariable("mouseb_use", &mousebuse); - M_BindIntVariable("mouseb_backward", &mousebbackward); - M_BindIntVariable("dclick_use", &dclick_use); - M_BindIntVariable("key_pause", &key_pause); - M_BindIntVariable("key_message_refresh", &key_message_refresh); + m_bind_int_variable("key_right", &key_right); + m_bind_int_variable("key_left", &key_left); + m_bind_int_variable("key_up", &key_up); + m_bind_int_variable("key_down", &key_down); + m_bind_int_variable("key_strafeleft", &key_strafeleft); + m_bind_int_variable("key_straferight", &key_straferight); + m_bind_int_variable("key_fire", &key_fire); + m_bind_int_variable("key_use", &key_use); + m_bind_int_variable("key_strafe", &key_strafe); + m_bind_int_variable("key_speed", &key_speed); + + m_bind_int_variable("mouseb_fire", &mousebfire); + m_bind_int_variable("mouseb_strafe", &mousebstrafe); + m_bind_int_variable("mouseb_forward", &mousebforward); + m_bind_int_variable("mouseb_speed", &mousebspeed); + + m_bind_int_variable("joyb_fire", &joybfire); + m_bind_int_variable("joyb_strafe", &joybstrafe); + m_bind_int_variable("joyb_use", &joybuse); + m_bind_int_variable("joyb_speed", &joybspeed); + + m_bind_int_variable("joyb_menu_activate", &joybmenu); + m_bind_int_variable("joyb_toggle_automap", &joybautomap); + + /* Extra controls that are not in the Vanilla versions: */ + + m_bind_int_variable("joyb_strafeleft", &joybstrafeleft); + m_bind_int_variable("joyb_straferight", &joybstraferight); + m_bind_int_variable("mouseb_strafeleft", &mousebstrafeleft); + m_bind_int_variable("mouseb_straferight", &mousebstraferight); + m_bind_int_variable("mouseb_turnleft", &mousebturnleft); + m_bind_int_variable("mouseb_turnright", &mousebturnright); + m_bind_int_variable("mouseb_use", &mousebuse); + m_bind_int_variable("mouseb_backward", &mousebbackward); + m_bind_int_variable("dclick_use", &dclick_use); + m_bind_int_variable("key_pause", &key_pause); + m_bind_int_variable("key_message_refresh", &key_message_refresh); } -void M_BindHereticControls(void) +void m_bind_heretic_controls(void) { - M_BindIntVariable("key_flyup", &key_flyup); - M_BindIntVariable("key_flydown", &key_flydown); - M_BindIntVariable("key_flycenter", &key_flycenter); - - M_BindIntVariable("key_lookup", &key_lookup); - M_BindIntVariable("key_lookdown", &key_lookdown); - M_BindIntVariable("key_lookcenter", &key_lookcenter); - - M_BindIntVariable("key_invleft", &key_invleft); - M_BindIntVariable("key_invright", &key_invright); - M_BindIntVariable("key_useartifact", &key_useartifact); - - M_BindIntVariable("mouseb_invleft", &mousebinvleft); - M_BindIntVariable("mouseb_invright", &mousebinvright); - M_BindIntVariable("mouseb_useartifact", &mousebuseartifact); - - M_BindIntVariable("joyb_invleft", &joybinvleft); - M_BindIntVariable("joyb_invright", &joybinvright); - M_BindIntVariable("joyb_useartifact", &joybuseartifact); - - M_BindIntVariable("joyb_flyup", &joybflyup); - M_BindIntVariable("joyb_flydown", &joybflydown); - M_BindIntVariable("joyb_flycenter", &joybflycenter); - - M_BindIntVariable("key_arti_quartz", &key_arti_quartz); - M_BindIntVariable("key_arti_urn", &key_arti_urn); - M_BindIntVariable("key_arti_bomb", &key_arti_bomb); - M_BindIntVariable("key_arti_tome", &key_arti_tome); - M_BindIntVariable("key_arti_ring", &key_arti_ring); - M_BindIntVariable("key_arti_chaosdevice", &key_arti_chaosdevice); - M_BindIntVariable("key_arti_shadowsphere", &key_arti_shadowsphere); - M_BindIntVariable("key_arti_wings", &key_arti_wings); - M_BindIntVariable("key_arti_torch", &key_arti_torch); - M_BindIntVariable("key_arti_morph", &key_arti_morph); + m_bind_int_variable("key_flyup", &key_flyup); + m_bind_int_variable("key_flydown", &key_flydown); + m_bind_int_variable("key_flycenter", &key_flycenter); + + m_bind_int_variable("key_lookup", &key_lookup); + m_bind_int_variable("key_lookdown", &key_lookdown); + m_bind_int_variable("key_lookcenter", &key_lookcenter); + + m_bind_int_variable("key_invleft", &key_invleft); + m_bind_int_variable("key_invright", &key_invright); + m_bind_int_variable("key_useartifact", &key_useartifact); + + m_bind_int_variable("mouseb_invleft", &mousebinvleft); + m_bind_int_variable("mouseb_invright", &mousebinvright); + m_bind_int_variable("mouseb_useartifact", &mousebuseartifact); + + m_bind_int_variable("joyb_invleft", &joybinvleft); + m_bind_int_variable("joyb_invright", &joybinvright); + m_bind_int_variable("joyb_useartifact", &joybuseartifact); + + m_bind_int_variable("joyb_flyup", &joybflyup); + m_bind_int_variable("joyb_flydown", &joybflydown); + m_bind_int_variable("joyb_flycenter", &joybflycenter); + + m_bind_int_variable("key_arti_quartz", &key_arti_quartz); + m_bind_int_variable("key_arti_urn", &key_arti_urn); + m_bind_int_variable("key_arti_bomb", &key_arti_bomb); + m_bind_int_variable("key_arti_tome", &key_arti_tome); + m_bind_int_variable("key_arti_ring", &key_arti_ring); + m_bind_int_variable("key_arti_chaosdevice", &key_arti_chaosdevice); + m_bind_int_variable("key_arti_shadowsphere", &key_arti_shadowsphere); + m_bind_int_variable("key_arti_wings", &key_arti_wings); + m_bind_int_variable("key_arti_torch", &key_arti_torch); + m_bind_int_variable("key_arti_morph", &key_arti_morph); } -void M_BindHexenControls(void) +void m_bind_hexen_controls(void) { - M_BindIntVariable("key_jump", &key_jump); - M_BindIntVariable("mouseb_jump", &mousebjump); - M_BindIntVariable("joyb_jump", &joybjump); - - M_BindIntVariable("key_arti_all", &key_arti_all); - M_BindIntVariable("key_arti_health", &key_arti_health); - M_BindIntVariable("key_arti_poisonbag", &key_arti_poisonbag); - M_BindIntVariable("key_arti_blastradius", &key_arti_blastradius); - M_BindIntVariable("key_arti_teleport", &key_arti_teleport); - M_BindIntVariable("key_arti_teleportother", &key_arti_teleportother); - M_BindIntVariable("key_arti_egg", &key_arti_egg); - M_BindIntVariable("key_arti_invulnerability", &key_arti_invulnerability); + m_bind_int_variable("key_jump", &key_jump); + m_bind_int_variable("mouseb_jump", &mousebjump); + m_bind_int_variable("joyb_jump", &joybjump); + + m_bind_int_variable("key_arti_all", &key_arti_all); + m_bind_int_variable("key_arti_health", &key_arti_health); + m_bind_int_variable("key_arti_poisonbag", &key_arti_poisonbag); + m_bind_int_variable("key_arti_blastradius", &key_arti_blastradius); + m_bind_int_variable("key_arti_teleport", &key_arti_teleport); + m_bind_int_variable("key_arti_teleportother", &key_arti_teleportother); + m_bind_int_variable("key_arti_egg", &key_arti_egg); + m_bind_int_variable("key_arti_invulnerability", &key_arti_invulnerability); } -void M_BindStrifeControls(void) +void m_bind_strife_controls(void) { - // These are shared with all games, but have different defaults: - key_message_refresh = '/'; - - // These keys are shared with Heretic/Hexen but have different defaults: - key_jump = 'a'; - key_lookup = KEY_PGUP; - key_lookdown = KEY_PGDN; - key_invleft = KEY_INS; - key_invright = KEY_DEL; - - M_BindIntVariable("key_jump", &key_jump); - M_BindIntVariable("key_lookUp", &key_lookup); - M_BindIntVariable("key_lookDown", &key_lookdown); - M_BindIntVariable("key_invLeft", &key_invleft); - M_BindIntVariable("key_invRight", &key_invright); - - // Custom Strife-only Keys: - M_BindIntVariable("key_useHealth", &key_usehealth); - M_BindIntVariable("key_invquery", &key_invquery); - M_BindIntVariable("key_mission", &key_mission); - M_BindIntVariable("key_invPop", &key_invpop); - M_BindIntVariable("key_invKey", &key_invkey); - M_BindIntVariable("key_invHome", &key_invhome); - M_BindIntVariable("key_invEnd", &key_invend); - M_BindIntVariable("key_invUse", &key_invuse); - M_BindIntVariable("key_invDrop", &key_invdrop); - - // Strife also supports jump on mouse and joystick, and in the exact same - // manner as Hexen! - M_BindIntVariable("mouseb_jump", &mousebjump); - M_BindIntVariable("joyb_jump", &joybjump); - - // Subset of inventory actions common to Heretic/Hexen and Strife. - M_BindIntVariable("joyb_invleft", &joybinvleft); - M_BindIntVariable("joyb_invright", &joybinvright); - // This is technically "invuse" in Strife, but let's reuse the value. - M_BindIntVariable("joyb_useartifact", &joybuseartifact); + /* These are shared with all games, but have different defaults: */ + + key_message_refresh = '/'; + + /* These keys are shared with Heretic/Hexen but have different defaults: */ + + key_jump = 'a'; + key_lookup = KEY_PGUP; + key_lookdown = KEY_PGDN; + key_invleft = KEY_INS; + key_invright = KEY_DEL; + + m_bind_int_variable("key_jump", &key_jump); + m_bind_int_variable("key_look_up", &key_lookup); + m_bind_int_variable("key_look_down", &key_lookdown); + m_bind_int_variable("key_inv_left", &key_invleft); + m_bind_int_variable("key_inv_right", &key_invright); + + /* Custom Strife-only Keys: */ + + m_bind_int_variable("key_use_health", &key_usehealth); + m_bind_int_variable("key_invquery", &key_invquery); + m_bind_int_variable("key_mission", &key_mission); + m_bind_int_variable("key_inv_pop", &key_invpop); + m_bind_int_variable("key_inv_key", &key_invkey); + m_bind_int_variable("key_invHome", &key_invhome); + m_bind_int_variable("key_inv_end", &key_invend); + m_bind_int_variable("key_inv_use", &key_invuse); + m_bind_int_variable("key_inv_drop", &key_invdrop); + + /* Strife also supports jump on mouse and joystick, and in the exact same + * manner as Hexen! + */ + + m_bind_int_variable("mouseb_jump", &mousebjump); + m_bind_int_variable("joyb_jump", &joybjump); + + /* Subset of inventory actions common to Heretic/Hexen and Strife. */ + + m_bind_int_variable("joyb_invleft", &joybinvleft); + m_bind_int_variable("joyb_invright", &joybinvright); + + /* This is technically "invuse" in Strife, but let's reuse the value. */ + + m_bind_int_variable("joyb_useartifact", &joybuseartifact); } -void M_BindWeaponControls(void) +void m_bind_weapon_controls(void) { - M_BindIntVariable("key_weapon1", &key_weapon1); - M_BindIntVariable("key_weapon2", &key_weapon2); - M_BindIntVariable("key_weapon3", &key_weapon3); - M_BindIntVariable("key_weapon4", &key_weapon4); - M_BindIntVariable("key_weapon5", &key_weapon5); - M_BindIntVariable("key_weapon6", &key_weapon6); - M_BindIntVariable("key_weapon7", &key_weapon7); - M_BindIntVariable("key_weapon8", &key_weapon8); - - M_BindIntVariable("key_prevweapon", &key_prevweapon); - M_BindIntVariable("key_nextweapon", &key_nextweapon); - - M_BindIntVariable("joyb_prevweapon", &joybprevweapon); - M_BindIntVariable("joyb_nextweapon", &joybnextweapon); - - M_BindIntVariable("mouseb_prevweapon", &mousebprevweapon); - M_BindIntVariable("mouseb_nextweapon", &mousebnextweapon); + m_bind_int_variable("key_weapon1", &key_weapon1); + m_bind_int_variable("key_weapon2", &key_weapon2); + m_bind_int_variable("key_weapon3", &key_weapon3); + m_bind_int_variable("key_weapon4", &key_weapon4); + m_bind_int_variable("key_weapon5", &key_weapon5); + m_bind_int_variable("key_weapon6", &key_weapon6); + m_bind_int_variable("key_weapon7", &key_weapon7); + m_bind_int_variable("key_weapon8", &key_weapon8); + + m_bind_int_variable("key_prevweapon", &key_prevweapon); + m_bind_int_variable("key_nextweapon", &key_nextweapon); + + m_bind_int_variable("joyb_prevweapon", &joybprevweapon); + m_bind_int_variable("joyb_nextweapon", &joybnextweapon); + + m_bind_int_variable("mouseb_prevweapon", &mousebprevweapon); + m_bind_int_variable("mouseb_nextweapon", &mousebnextweapon); } -void M_BindMapControls(void) +void m_bind_map_controls(void) { - M_BindIntVariable("key_map_north", &key_map_north); - M_BindIntVariable("key_map_south", &key_map_south); - M_BindIntVariable("key_map_east", &key_map_east); - M_BindIntVariable("key_map_west", &key_map_west); - M_BindIntVariable("key_map_zoomin", &key_map_zoomin); - M_BindIntVariable("key_map_zoomout", &key_map_zoomout); - M_BindIntVariable("key_map_toggle", &key_map_toggle); - M_BindIntVariable("key_map_maxzoom", &key_map_maxzoom); - M_BindIntVariable("key_map_follow", &key_map_follow); - M_BindIntVariable("key_map_grid", &key_map_grid); - M_BindIntVariable("key_map_mark", &key_map_mark); - M_BindIntVariable("key_map_clearmark", &key_map_clearmark); + m_bind_int_variable("key_map_north", &key_map_north); + m_bind_int_variable("key_map_south", &key_map_south); + m_bind_int_variable("key_map_east", &key_map_east); + m_bind_int_variable("key_map_west", &key_map_west); + m_bind_int_variable("key_map_zoomin", &key_map_zoomin); + m_bind_int_variable("key_map_zoomout", &key_map_zoomout); + m_bind_int_variable("key_map_toggle", &key_map_toggle); + m_bind_int_variable("key_map_maxzoom", &key_map_maxzoom); + m_bind_int_variable("key_map_follow", &key_map_follow); + m_bind_int_variable("key_map_grid", &key_map_grid); + m_bind_int_variable("key_map_mark", &key_map_mark); + m_bind_int_variable("key_map_clearmark", &key_map_clearmark); } -void M_BindMenuControls(void) +void m_bind_menu_controls(void) { - M_BindIntVariable("key_menu_activate", &key_menu_activate); - M_BindIntVariable("key_menu_up", &key_menu_up); - M_BindIntVariable("key_menu_down", &key_menu_down); - M_BindIntVariable("key_menu_left", &key_menu_left); - M_BindIntVariable("key_menu_right", &key_menu_right); - M_BindIntVariable("key_menu_back", &key_menu_back); - M_BindIntVariable("key_menu_forward", &key_menu_forward); - M_BindIntVariable("key_menu_confirm", &key_menu_confirm); - M_BindIntVariable("key_menu_abort", &key_menu_abort); - - M_BindIntVariable("key_menu_help", &key_menu_help); - M_BindIntVariable("key_menu_save", &key_menu_save); - M_BindIntVariable("key_menu_load", &key_menu_load); - M_BindIntVariable("key_menu_volume", &key_menu_volume); - M_BindIntVariable("key_menu_detail", &key_menu_detail); - M_BindIntVariable("key_menu_qsave", &key_menu_qsave); - M_BindIntVariable("key_menu_endgame", &key_menu_endgame); - M_BindIntVariable("key_menu_messages", &key_menu_messages); - M_BindIntVariable("key_menu_qload", &key_menu_qload); - M_BindIntVariable("key_menu_quit", &key_menu_quit); - M_BindIntVariable("key_menu_gamma", &key_menu_gamma); - - M_BindIntVariable("key_menu_incscreen", &key_menu_incscreen); - M_BindIntVariable("key_menu_decscreen", &key_menu_decscreen); - M_BindIntVariable("key_menu_screenshot",&key_menu_screenshot); - M_BindIntVariable("key_demo_quit", &key_demo_quit); - M_BindIntVariable("key_spy", &key_spy); + m_bind_int_variable("key_menu_activate", &key_menu_activate); + m_bind_int_variable("key_menu_up", &key_menu_up); + m_bind_int_variable("key_menu_down", &key_menu_down); + m_bind_int_variable("key_menu_left", &key_menu_left); + m_bind_int_variable("key_menu_right", &key_menu_right); + m_bind_int_variable("key_menu_back", &key_menu_back); + m_bind_int_variable("key_menu_forward", &key_menu_forward); + m_bind_int_variable("key_menu_confirm", &key_menu_confirm); + m_bind_int_variable("key_menu_abort", &key_menu_abort); + + m_bind_int_variable("key_menu_help", &key_menu_help); + m_bind_int_variable("key_menu_save", &key_menu_save); + m_bind_int_variable("key_menu_load", &key_menu_load); + m_bind_int_variable("key_menu_volume", &key_menu_volume); + m_bind_int_variable("key_menu_detail", &key_menu_detail); + m_bind_int_variable("key_menu_qsave", &key_menu_qsave); + m_bind_int_variable("key_menu_endgame", &key_menu_endgame); + m_bind_int_variable("key_menu_messages", &key_menu_messages); + m_bind_int_variable("key_menu_qload", &key_menu_qload); + m_bind_int_variable("key_menu_quit", &key_menu_quit); + m_bind_int_variable("key_menu_gamma", &key_menu_gamma); + + m_bind_int_variable("key_menu_incscreen", &key_menu_incscreen); + m_bind_int_variable("key_menu_decscreen", &key_menu_decscreen); + m_bind_int_variable("key_menu_screenshot", &key_menu_screenshot); + m_bind_int_variable("key_demo_quit", &key_demo_quit); + m_bind_int_variable("key_spy", &key_spy); } -void M_BindChatControls(unsigned int num_players) +void m_bind_chat_controls(unsigned int num_players) { - char name[32]; // haleyjd: 20 not large enough - Thank you, come again! - unsigned int i; // haleyjd: signedness conflict + char name[32]; /* haleyjd: 20 not large enough - Thank you, come again! */ + unsigned int i; /* haleyjd: signedness conflict */ - M_BindIntVariable("key_multi_msg", &key_multi_msg); + m_bind_int_variable("key_multi_msg", &key_multi_msg); - for (i=0; i> FRACBITS; + return ((int64_t)a * (int64_t)b) >> FRACBITS; } +/* fixed_div, C version. */ - -// -// FixedDiv, C version. -// - -fixed_t FixedDiv(fixed_t a, fixed_t b) +fixed_t fixed_div(fixed_t a, fixed_t b) { - if ((abs(a) >> 14) >= abs(b)) + if ((abs(a) >> 14) >= abs(b)) { - return (a^b) < 0 ? INT_MIN : INT_MAX; + return (a ^ b) < 0 ? INT_MIN : INT_MAX; } - else + else { - int64_t result; + int64_t result; - result = ((int64_t) a << FRACBITS) / b; + result = ((int64_t)a << FRACBITS) / b; - return (fixed_t) result; + return (fixed_t)result; } } - diff --git a/games/NXDoom/src/m_fixed.h b/games/NXDoom/src/m_fixed.h index 733b2901ce8..abb837b318b 100644 --- a/games/NXDoom/src/m_fixed.h +++ b/games/NXDoom/src/m_fixed.h @@ -1,39 +1,49 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Fixed point arithemtics, implementation. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_fixed.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Fixed point arithemtics, implementation. + * + ****************************************************************************/ #ifndef __M_FIXED__ #define __M_FIXED__ +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Fixed point, 32bit as 16.16. */ +#define FRACBITS 16 +#define FRACUNIT (1 << FRACBITS) -// -// Fixed point, 32bit as 16.16. -// -#define FRACBITS 16 -#define FRACUNIT (1< +#include #include #include #include -#include -#include -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#else #include -#endif #include "doomtype.h" @@ -39,926 +40,581 @@ #include "m_misc.h" #include "z_zone.h" -#ifdef _WIN32 -static wchar_t *ConvertMultiByteToWide(const char *str, UINT code_page) -{ - wchar_t *wstr = NULL; - int wlen = 0; - - wlen = MultiByteToWideChar(code_page, 0, str, -1, NULL, 0); - - if (!wlen) - { - errno = EINVAL; - printf("ConvertMultiByteToWide: Failed to convert path to wide encoding.\n"); - return NULL; - } - - wstr = malloc(sizeof(wchar_t) * wlen); - - if (!wstr) - { - I_Error("ConvertMultiByteToWide: Failed to allocate new string."); - return NULL; - } - - if (MultiByteToWideChar(code_page, 0, str, -1, wstr, wlen) == 0) - { - errno = EINVAL; - printf("ConvertMultiByteToWide: Failed to convert path to wide encoding.\n"); - free(wstr); - return NULL; - } +/**************************************************************************** + * Public Functions + ****************************************************************************/ - return wstr; +void m_make_directory(const char *path) +{ + mkdir(path, 0755); } -static char *ConvertWideToMultiByte(const wchar_t *wstr, UINT code_page) +boolean m_file_exists(const char *filename) { - char *str = NULL; - int len = 0; + FILE *fstream; - len = WideCharToMultiByte(code_page, 0, wstr, -1, NULL, 0, NULL, NULL); + fstream = fopen(filename, "r"); - if (!len) + if (fstream != NULL) { - errno = EINVAL; - printf("ConvertWideToMultiByte: Failed to convert path to multibyte encoding.\n"); - return NULL; + fclose(fstream); + return true; } - - str = malloc(sizeof(char) * len); - - if (!str) + else { - I_Error("ConvertWideToMultiByte: Failed to allocate new string."); - return NULL; - } + /* If we can't open because the file is a directory, the + * "file" exists at least! + */ - if (WideCharToMultiByte(code_page, 0, wstr, -1, str, len, NULL, NULL) == 0) - { - errno = EINVAL; - printf("ConvertWideToMultiByte: Failed to convert path to multibyte encoding.\n"); - free(str); - return NULL; + return errno == EISDIR; } - - return str; -} - -// Convert wide string to a UTF8 string. The result is newly allocated and must -// be freed by the caller after use. - -char *M_ConvertWideToUtf8(const wchar_t *wstr) -{ - return ConvertWideToMultiByte(wstr, CP_UTF8); } -// Convert UTF8 string to a wide string. The result is newly allocated and must -// be freed by the caller after use. +/* Check if a file exists by probing for common case variation of its + * filename. Returns a newly allocated string that the caller is responsible + * for freeing. + */ -wchar_t *M_ConvertUtf8ToWide(const char *str) +char *m_file_case_exists(const char *path) { - return ConvertMultiByteToWide(str, CP_UTF8); -} -#endif + char *path_dup; + char *filename; + char *ext; -FILE *M_fopen(const char *filename, const char *mode) -{ -#ifdef _WIN32 - FILE *file; - wchar_t *wname = NULL; - wchar_t *wmode = NULL; + path_dup = m_string_duplicate(path); - wname = M_ConvertUtf8ToWide(filename); + /* 0: actual path */ - if (!wname) + if (m_file_exists(path_dup)) { - return NULL; + return path_dup; } - wmode = M_ConvertUtf8ToWide(mode); - - if (!wmode) + filename = strrchr(path_dup, DIR_SEPARATOR); + if (filename != NULL) { - free(wname); - return NULL; + filename++; } - - file = _wfopen(wname, wmode); - - free(wname); - free(wmode); - - return file; -#else - return fopen(filename, mode); -#endif -} - -int M_remove(const char *path) -{ -#ifdef _WIN32 - wchar_t *wpath = NULL; - int ret; - - wpath = M_ConvertUtf8ToWide(path); - - if (!wpath) + else { - return 0; + filename = path_dup; } - ret = _wremove(wpath); + /* 1: lowercase filename, e.g. doom2.wad */ - free(wpath); - - return ret; -#else - return remove(path); -#endif -} + m_force_lowercase(filename); -int M_rename(const char *oldname, const char *newname) -{ -#ifdef _WIN32 - wchar_t *wold = NULL; - wchar_t *wnew = NULL; - int ret; - - wold = M_ConvertUtf8ToWide(oldname); - - if (!wold) - { - return 0; - } - - wnew = M_ConvertUtf8ToWide(newname); - - if (!wnew) + if (m_file_exists(path_dup)) { - free(wold); - return 0; + return path_dup; } - ret = _wrename(wold, wnew); - - free(wold); - free(wnew); - - return ret; -#else - return rename(oldname, newname); -#endif -} - -int M_stat(const char *path, struct stat *buf) -{ -#ifdef _WIN32 - wchar_t *wpath = NULL; - struct _stat wbuf; - int ret; + /* 2: uppercase filename, e.g. DOOM2.WAD */ - wpath = M_ConvertUtf8ToWide(path); + m_force_uppercase(filename); - if (!wpath) + if (m_file_exists(path_dup)) { - return -1; + return path_dup; } - ret = _wstat(wpath, &wbuf); - - // The _wstat() function expects a struct _stat* parameter that is - // incompatible with struct stat*. We copy only the required compatible - // field. - buf->st_mode = wbuf.st_mode; - - free(wpath); - - return ret; -#else - return stat(path, buf); -#endif -} - -#ifdef _WIN32 -typedef struct { - char *var; - const char *name; -} env_var_t; - -static env_var_t *env_vars; -static int num_vars; -#endif - -char *M_getenv(const char *name) -{ -#ifdef _WIN32 - int i; - wchar_t *wenv = NULL, *wname = NULL; - char *env = NULL; + /* 3. uppercase basename with lowercase extension, e.g. DOOM2.wad */ - for (i = 0; i < num_vars; ++i) + ext = strrchr(path_dup, '.'); + if (ext != NULL && ext > filename) { - if (!strcasecmp(name, env_vars[i].name)) + m_force_lowercase(ext + 1); + + if (m_file_exists(path_dup)) { - return env_vars[i].var; + return path_dup; } } - wname = M_ConvertUtf8ToWide(name); + /* 4. lowercase filename with uppercase first letter, e.g. Doom2.wad */ - if (!wname) + if (strlen(filename) > 1) { - return NULL; - } - - wenv = _wgetenv(wname); + m_force_lowercase(filename + 1); - free(wname); - - if (wenv) - { - env = M_ConvertWideToUtf8(wenv); - } - else - { - env = NULL; + if (m_file_exists(path_dup)) + { + return path_dup; + } } - env_vars = I_Realloc(env_vars, (num_vars + 1) * sizeof(*env_vars)); - env_vars[num_vars].var = env; - env_vars[num_vars].name = M_StringDuplicate(name); - ++num_vars; + /* 5. no luck */ - return env; -#else - return getenv(name); -#endif + free(path_dup); + return NULL; } -// -// Create a directory -// - -void M_MakeDirectory(const char *path) +long m_file_length(FILE *handle) { -#ifdef _WIN32 - wchar_t *wdir; + long savedpos; + long length; - wdir = M_ConvertUtf8ToWide(path); + /* save the current position in the file */ - if (!wdir) - { - return; - } + savedpos = ftell(handle); - _wmkdir(wdir); + /* jump to the end and find the length */ - free(wdir); -#else - mkdir(path, 0755); -#endif -} + fseek(handle, 0, SEEK_END); + length = ftell(handle); -// Check if a file exists - -boolean M_FileExists(const char *filename) -{ - FILE *fstream; + /* go back to the old location */ - fstream = M_fopen(filename, "r"); - - if (fstream != NULL) - { - fclose(fstream); - return true; - } - else - { - // If we can't open because the file is a directory, the - // "file" exists at least! + fseek(handle, savedpos, SEEK_SET); - return errno == EISDIR; - } + return length; } -// Check if a file exists by probing for common case variation of its filename. -// Returns a newly allocated string that the caller is responsible for freeing. - -char *M_FileCaseExists(const char *path) +boolean m_write_file(const char *name, const void *source, int length) { - char *path_dup, *filename, *ext; + FILE *handle; + int count; - path_dup = M_StringDuplicate(path); + handle = fopen(name, "wb"); - // 0: actual path - if (M_FileExists(path_dup)) - { - return path_dup; - } + if (handle == NULL) return false; - filename = strrchr(path_dup, DIR_SEPARATOR); - if (filename != NULL) - { - filename++; - } - else - { - filename = path_dup; - } + count = fwrite(source, 1, length, handle); + fclose(handle); - // 1: lowercase filename, e.g. doom2.wad - M_ForceLowercase(filename); + if (count < length) return false; - if (M_FileExists(path_dup)) - { - return path_dup; - } + return true; +} - // 2: uppercase filename, e.g. DOOM2.WAD - M_ForceUppercase(filename); +int m_read_file(const char *name, byte **buffer) +{ + FILE *handle; + int count; + int length; + byte *buf; - if (M_FileExists(path_dup)) - { - return path_dup; - } + handle = fopen(name, "rb"); + if (handle == NULL) i_error("Couldn't read file %s", name); - // 3. uppercase basename with lowercase extension, e.g. DOOM2.wad - ext = strrchr(path_dup, '.'); - if (ext != NULL && ext > filename) - { - M_ForceLowercase(ext + 1); + /* find the size of the file by seeking to the end and + * reading the current position + */ - if (M_FileExists(path_dup)) - { - return path_dup; - } - } + length = m_file_length(handle); - // 4. lowercase filename with uppercase first letter, e.g. Doom2.wad - if (strlen(filename) > 1) - { - M_ForceLowercase(filename + 1); + buf = z_malloc(length + 1, PU_STATIC, NULL); + count = fread(buf, 1, length, handle); + fclose(handle); - if (M_FileExists(path_dup)) - { - return path_dup; - } - } + if (count < length) i_error("Couldn't read file %s", name); - // 5. no luck - free(path_dup); - return NULL; + buf[length] = '\0'; + *buffer = buf; + return length; } -// -// Determine the length of an open file. -// - -long M_FileLength(FILE *handle) -{ - long savedpos; - long length; +/* Returns the path to a temporary file of the given name, stored + * inside the system temporary directory. + * + * The returned value must be freed with z_free after use. + */ - // save the current position in the file - savedpos = ftell(handle); - - // jump to the end and find the length - fseek(handle, 0, SEEK_END); - length = ftell(handle); +char *m_temp_file(const char *s) +{ + const char *tempdir; - // go back to the old location - fseek(handle, savedpos, SEEK_SET); + /* Check the $TMPDIR environment variable to find the location. */ - return length; -} + tempdir = getenv("TMPDIR"); -// -// M_WriteFile -// + if (tempdir == NULL) + { + tempdir = "/tmp"; + } -boolean M_WriteFile(const char *name, const void *source, int length) -{ - FILE *handle; - int count; - - handle = M_fopen(name, "wb"); - - if (handle == NULL) - return false; - - count = fwrite(source, 1, length, handle); - fclose(handle); - - if (count < length) - return false; - - return true; + return m_string_join(tempdir, DIR_SEPARATOR_S, s, NULL); } - -// -// M_ReadFile -// - -int M_ReadFile(const char *name, byte **buffer) +boolean m_str_to_int(const char *str, int *result) { - FILE *handle; - int count, length; - byte *buf; - - handle = M_fopen(name, "rb"); - if (handle == NULL) - I_Error ("Couldn't read file %s", name); - - // find the size of the file by seeking to the end and - // reading the current position - - length = M_FileLength(handle); - - buf = Z_Malloc (length + 1, PU_STATIC, NULL); - count = fread(buf, 1, length, handle); - fclose (handle); - - if (count < length) - I_Error ("Couldn't read file %s", name); - - buf[length] = '\0'; - *buffer = buf; - return length; + return sscanf(str, " 0x%x", (unsigned int *)result) == 1 || + sscanf(str, " 0X%x", (unsigned int *)result) == 1 || + sscanf(str, " 0%o", (unsigned int *)result) == 1 || + sscanf(str, " %d", result) == 1; } -// Returns the path to a temporary file of the given name, stored -// inside the system temporary directory. -// -// The returned value must be freed with Z_Free after use. +/* Returns the directory portion of the given path, without the trailing + * slash separator character. If no directory is described in the path, + * the string "." is returned. In either case, the result is newly allocated + * and must be freed by the caller after use. + */ -char *M_TempFile(const char *s) +char *m_dir_name(const char *path) { - const char *tempdir; + char *result; + const char *pf; + const char *pb; -#ifdef _WIN32 + pf = strrchr(path, '/'); + pb = NULL; - // Check the TEMP environment variable to find the location. - - tempdir = M_getenv("TEMP"); - - if (tempdir == NULL) + if (pf == NULL && pb == NULL) { - tempdir = "."; + return m_string_duplicate("."); } -#else - // Check the $TMPDIR environment variable to find the location. - - tempdir = getenv("TMPDIR"); - - if (tempdir == NULL) + else { - tempdir = "/tmp"; + const char *p = (pb > pf) ? pb : pf; + result = m_string_duplicate(path); + result[p - path] = '\0'; + return result; } -#endif - - return M_StringJoin(tempdir, DIR_SEPARATOR_S, s, NULL); } -boolean M_StrToInt(const char *str, int *result) -{ - return sscanf(str, " 0x%x", (unsigned int *) result) == 1 - || sscanf(str, " 0X%x", (unsigned int *) result) == 1 - || sscanf(str, " 0%o", (unsigned int *) result) == 1 - || sscanf(str, " %d", result) == 1; -} +/* Returns the base filename described by the given path (without the + * directory name). The result points inside path and nothing new is + * allocated. + */ -// Returns the directory portion of the given path, without the trailing -// slash separator character. If no directory is described in the path, -// the string "." is returned. In either case, the result is newly allocated -// and must be freed by the caller after use. -char *M_DirName(const char *path) +const char *m_base_name(const char *path) { - char *result; - const char *pf, *pb; - - pf = strrchr(path, '/'); -#ifdef _WIN32 - pb = strrchr(path, '\\'); -#else - pb = NULL; -#endif - if (pf == NULL && pb == NULL) - { - return M_StringDuplicate("."); - } - else - { - const char *p = (pb > pf) ? pb : pf; - result = M_StringDuplicate(path); - result[p - path] = '\0'; - return result; - } -} + const char *pf; + const char *pb; -// Returns the base filename described by the given path (without the -// directory name). The result points inside path and nothing new is -// allocated. -const char *M_BaseName(const char *path) -{ - const char *pf, *pb; - - pf = strrchr(path, '/'); -#ifdef _WIN32 - pb = strrchr(path, '\\'); -#else - pb = NULL; -#endif - if (pf == NULL && pb == NULL) + pf = strrchr(path, '/'); + pb = NULL; + + if (pf == NULL && pb == NULL) { - return path; + return path; } - else + else { - const char *p = (pb > pf) ? pb : pf; - return p + 1; + const char *p = (pb > pf) ? pb : pf; + return p + 1; } } -void M_ExtractFileBase(const char *path, char *dest) +void m_extract_file_base(const char *path, char *dest) { - const char *src; - const char *filename; - int length; + const char *src; + const char *filename; + int length; + + src = path + strlen(path) - 1; - src = path + strlen(path) - 1; + /* back up until a \ or the start */ - // back up until a \ or the start - while (src != path && *(src - 1) != DIR_SEPARATOR) + while (src != path && *(src - 1) != DIR_SEPARATOR) { - src--; + src--; } - filename = src; + filename = src; - // Copy up to eight characters - // Note: Vanilla Doom exits with an error if a filename is specified - // with a base of more than eight characters. To remove the 8.3 - // filename limit, instead we simply truncate the name. + /* Copy up to eight characters + * Note: Vanilla Doom exits with an error if a filename is specified + * with a base of more than eight characters. To remove the 8.3 + * filename limit, instead we simply truncate the name. + */ - length = 0; - memset(dest, 0, 8); + length = 0; + memset(dest, 0, 8); - while (*src != '\0' && *src != '.') + while (*src != '\0' && *src != '.') { - if (length >= 8) + if (length >= 8) { - printf("Warning: Truncated '%s' lump name to '%.8s'.\n", - filename, dest); - break; + printf("Warning: Truncated '%s' lump name to '%.8s'.\n", filename, + dest); + break; } - dest[length++] = toupper((int)*src++); + dest[length++] = toupper((int)*src++); } } -//--------------------------------------------------------------------------- -// -// PROC M_ForceUppercase -// -// Change string to uppercase. -// -//--------------------------------------------------------------------------- +/**************************************************************************** + * Name: m_force_uppercase + * + * Description: + * (PROC) Change string to uppercase. + * + ****************************************************************************/ -void M_ForceUppercase(char *text) +void m_force_uppercase(char *text) { - char *p; + char *p; - for (p = text; *p != '\0'; ++p) + for (p = text; *p != '\0'; ++p) { - *p = toupper(*p); + *p = toupper(*p); } } -//--------------------------------------------------------------------------- -// -// PROC M_ForceLowercase -// -// Change string to lowercase. -// -//--------------------------------------------------------------------------- +/**************************************************************************** + * Name: m_force_lowercase + * + * Description: + * (PROC) Change string to lowercase. + * + ****************************************************************************/ -void M_ForceLowercase(char *text) +void m_force_lowercase(char *text) { - char *p; + char *p; - for (p = text; *p != '\0'; ++p) + for (p = text; *p != '\0'; ++p) { - *p = tolower(*p); + *p = tolower(*p); } } -// -// M_StrCaseStr -// -// Case-insensitive version of strstr() -// +/**************************************************************************** + * Name: m_string_duplicate + * + * Description: + * Safe version of strdup() that checks the string was successfully + * allocated. + * + ****************************************************************************/ -const char *M_StrCaseStr(const char *haystack, const char *needle) +char *m_string_duplicate(const char *orig) { - unsigned int haystack_len; - unsigned int needle_len; - unsigned int len; - unsigned int i; + char *result; - haystack_len = strlen(haystack); - needle_len = strlen(needle); + result = strdup(orig); - if (haystack_len < needle_len) + if (result == NULL) { - return NULL; - } - - len = haystack_len - needle_len; - - for (i = 0; i <= len; ++i) - { - if (!strncasecmp(haystack + i, needle, needle_len)) - { - return haystack + i; - } + i_error("Failed to duplicate string (length %zu)\n", strlen(orig)); } - return NULL; + return result; } -// -// Safe version of strdup() that checks the string was successfully -// allocated. -// - -char *M_StringDuplicate(const char *orig) +char *m_string_replace(const char *haystack, const char *needle, + const char *replacement) { - char *result; - - result = strdup(orig); - - if (result == NULL) - { - I_Error("Failed to duplicate string (length %zu)\n", - strlen(orig)); - } - - return result; -} + char *result; + char *dst; + const char *p; + size_t needle_len = strlen(needle); + size_t result_len; + size_t dst_len; -// -// String replace function. -// - -char *M_StringReplace(const char *haystack, const char *needle, - const char *replacement) -{ - char *result, *dst; - const char *p; - size_t needle_len = strlen(needle); - size_t result_len, dst_len; + /* Iterate through occurrences of 'needle' and calculate the size of + * the new string. + */ - // Iterate through occurrences of 'needle' and calculate the size of - // the new string. - result_len = strlen(haystack) + 1; - p = haystack; + result_len = strlen(haystack) + 1; + p = haystack; - for (;;) + for (; ; ) { - p = strstr(p, needle); - if (p == NULL) + p = strstr(p, needle); + if (p == NULL) { - break; + break; } - p += needle_len; - result_len += strlen(replacement) - needle_len; + p += needle_len; + result_len += strlen(replacement) - needle_len; } - // Construct new string. + /* Construct new string. */ - result = malloc(result_len); - if (result == NULL) + result = malloc(result_len); + if (result == NULL) { - I_Error("M_StringReplace: Failed to allocate new string"); - return NULL; + i_error("m_string_replace: Failed to allocate new string"); + return NULL; } - dst = result; dst_len = result_len; - p = haystack; + dst = result; + dst_len = result_len; + p = haystack; - while (*p != '\0') + while (*p != '\0') { - if (!strncmp(p, needle, needle_len)) + if (!strncmp(p, needle, needle_len)) { - M_StringCopy(dst, replacement, dst_len); - p += needle_len; - dst += strlen(replacement); - dst_len -= strlen(replacement); + m_str_copy(dst, replacement, dst_len); + p += needle_len; + dst += strlen(replacement); + dst_len -= strlen(replacement); } - else + else { - *dst = *p; - ++dst; --dst_len; - ++p; + *dst = *p; + ++dst; + --dst_len; + ++p; } } - *dst = '\0'; + *dst = '\0'; - return result; + return result; } -// Safe string copy function that works like OpenBSD's strlcpy(). -// Returns true if the string was not truncated. +/* Safe string copy function that works like OpenBSD's strlcpy(). + * Returns true if the string was not truncated. + */ -boolean M_StringCopy(char *dest, const char *src, size_t dest_size) +boolean m_str_copy(char *dest, const char *src, size_t dest_size) { - size_t len; + size_t len; - if (dest_size >= 1) + if (dest_size >= 1) { - dest[dest_size - 1] = '\0'; - strncpy(dest, src, dest_size - 1); + dest[dest_size - 1] = '\0'; + strncpy(dest, src, dest_size - 1); } - else + else { - return false; + return false; } - len = strlen(dest); - return src[len] == '\0'; + len = strlen(dest); + return src[len] == '\0'; } -// Safe string concat function that works like OpenBSD's strlcat(). -// Returns true if string not truncated. +/* Safe string concat function that works like OpenBSD's strlcat(). + * Returns true if string not truncated. + */ -boolean M_StringConcat(char *dest, const char *src, size_t dest_size) +boolean m_string_concat(char *dest, const char *src, size_t dest_size) { - size_t offset; + size_t offset; - offset = strlen(dest); - if (offset > dest_size) + offset = strlen(dest); + if (offset > dest_size) { - offset = dest_size; + offset = dest_size; } - return M_StringCopy(dest + offset, src, dest_size - offset); + return m_str_copy(dest + offset, src, dest_size - offset); } -// Returns true if 's' begins with the specified prefix. +/* Returns true if 's' begins with the specified prefix. */ -boolean M_StringStartsWith(const char *s, const char *prefix) +boolean m_string_starts_with(const char *s, const char *prefix) { - return strlen(s) >= strlen(prefix) - && strncmp(s, prefix, strlen(prefix)) == 0; + return strlen(s) >= strlen(prefix) && + strncmp(s, prefix, strlen(prefix)) == 0; } -// Returns true if 's' ends with the specified suffix. +/* Returns true if 's' ends with the specified suffix. */ -boolean M_StringEndsWith(const char *s, const char *suffix) +boolean m_string_ends_with(const char *s, const char *suffix) { - return strlen(s) >= strlen(suffix) - && strcmp(s + strlen(s) - strlen(suffix), suffix) == 0; + return strlen(s) >= strlen(suffix) && + strcmp(s + strlen(s) - strlen(suffix), suffix) == 0; } -// Return a newly-malloced string with all the strings given as arguments -// concatenated together. +/* Return a newly-malloced string with all the strings given as arguments + * concatenated together. + */ -char *M_StringJoin(const char *s, ...) +char *m_string_join(const char *s, ...) { - char *result; - const char *v; - va_list args; - size_t result_len; + char *result; + const char *v; + va_list args; + size_t result_len; - result_len = strlen(s) + 1; + result_len = strlen(s) + 1; - va_start(args, s); - for (;;) + va_start(args, s); + + for (; ; ) { - v = va_arg(args, const char *); - if (v == NULL) + v = va_arg(args, const char *); + if (v == NULL) { - break; + break; } - result_len += strlen(v); + result_len += strlen(v); } - va_end(args); - result = malloc(result_len); + va_end(args); + + result = malloc(result_len); - if (result == NULL) + if (result == NULL) { - I_Error("M_StringJoin: Failed to allocate new string."); - return NULL; + i_error("m_string_join: Failed to allocate new string."); + return NULL; } - M_StringCopy(result, s, result_len); + m_str_copy(result, s, result_len); + + va_start(args, s); - va_start(args, s); - for (;;) + for (; ; ) { - v = va_arg(args, const char *); - if (v == NULL) + v = va_arg(args, const char *); + if (v == NULL) { - break; + break; } - M_StringConcat(result, v, result_len); + m_string_concat(result, v, result_len); } - va_end(args); - - return result; -} -// On Windows, vsnprintf() is _vsnprintf(). -#ifdef _WIN32 -#if _MSC_VER < 1400 /* not needed for Visual Studio 2008 */ -#define vsnprintf _vsnprintf -#endif -#endif - -// Safe, portable vsnprintf(). -int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args) -{ - int result; - - if (buf_len < 1) - { - return 0; - } + va_end(args); - // Windows (and other OSes?) has a vsnprintf() that doesn't always - // append a trailing \0. So we must do it, and write into a buffer - // that is one byte shorter; otherwise this function is unsafe. - result = vsnprintf(buf, buf_len, s, args); - - // If truncated, change the final char in the buffer to a \0. - // A negative result indicates a truncated buffer on Windows. - if (result < 0 || result >= buf_len) - { - buf[buf_len - 1] = '\0'; - result = buf_len - 1; - } - - return result; + return result; } -// Safe, portable snprintf(). -int M_snprintf(char *buf, size_t buf_len, const char *s, ...) -{ - va_list args; - int result; - va_start(args, s); - result = M_vsnprintf(buf, buf_len, s, args); - va_end(args); - return result; -} +/**************************************************************************** + * Name: m_normalize_slashes + * + * Description: + * Remove trailing slashes, translate backslashes to slashes. The string to + * normalize is passed and returned in str. + * + * killough 11/98: rewritten + * + * [STRIFE] - haleyjd 20110210: Borrowed from Eternity and adapted to + * respect the DIR_SEPARATOR define used by Choco Doom. This routine + * originated in BOOM. + * + ****************************************************************************/ -// -// M_NormalizeSlashes -// -// Remove trailing slashes, translate backslashes to slashes -// The string to normalize is passed and returned in str -// -// killough 11/98: rewritten -// -// [STRIFE] - haleyjd 20110210: Borrowed from Eternity and adapted to respect -// the DIR_SEPARATOR define used by Choco Doom. This routine originated in -// BOOM. -// -void M_NormalizeSlashes(char *str) +void m_normalize_slashes(char *str) { - char *p; + char *p; + + /* Convert all slashes/backslashes to DIR_SEPARATOR */ - // Convert all slashes/backslashes to DIR_SEPARATOR - for (p = str; *p; p++) + for (p = str; *p; p++) { - if ((*p == '/' || *p == '\\') && *p != DIR_SEPARATOR) + if ((*p == '/' || *p == '\\') && *p != DIR_SEPARATOR) { - *p = DIR_SEPARATOR; + *p = DIR_SEPARATOR; } } - // Remove trailing slashes - while (p > str && *--p == DIR_SEPARATOR) + /* Remove trailing slashes */ + + while (p > str && *--p == DIR_SEPARATOR) { - *p = 0; + *p = 0; } - // Collapse multiple slashes - for (p = str; (*str++ = *p); ) + /* Collapse multiple slashes */ + + for (p = str; (*str++ = *p); ) { - if (*p++ == DIR_SEPARATOR) + if (*p++ == DIR_SEPARATOR) { - while (*p == DIR_SEPARATOR) + while (*p == DIR_SEPARATOR) { - p++; + p++; } } } diff --git a/games/NXDoom/src/m_misc.h b/games/NXDoom/src/m_misc.h index 6dc18ccfa36..0b310371e35 100644 --- a/games/NXDoom/src/m_misc.h +++ b/games/NXDoom/src/m_misc.h @@ -1,107 +1,111 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Miscellaneous. -// - +/**************************************************************************** + * apps/games/NXDoom/src/m_misc.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Miscellaneous. + * + ****************************************************************************/ #ifndef __M_MISC__ #define __M_MISC__ -#include +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include +#include #include #include "doomtype.h" -#ifdef _WIN32 -wchar_t *M_ConvertUtf8ToWide(const char *str); -char *M_ConvertWideToUtf8(const wchar_t *wstr); -#endif +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -FILE *M_fopen(const char *filename, const char *mode); -int M_remove(const char *path); -int M_rename(const char *oldname, const char *newname); -int M_stat(const char *path, struct stat *buf); -char *M_getenv(const char *name); -boolean M_WriteFile(const char *name, const void *source, int length); -int M_ReadFile(const char *name, byte **buffer); -void M_MakeDirectory(const char *dir); -char *M_TempFile(const char *s); -boolean M_FileExists(const char *file); -char *M_FileCaseExists(const char *file); -long M_FileLength(FILE *handle); -boolean M_StrToInt(const char *str, int *result); -char *M_DirName(const char *path); -const char *M_BaseName(const char *path); -void M_ExtractFileBase(const char *path, char *dest); -void M_ForceUppercase(char *text); -void M_ForceLowercase(char *text); -const char *M_StrCaseStr(const char *haystack, const char *needle); -char *M_StringDuplicate(const char *orig); -boolean M_StringCopy(char *dest, const char *src, size_t dest_size); -boolean M_StringConcat(char *dest, const char *src, size_t dest_size); -char *M_StringReplace(const char *haystack, const char *needle, - const char *replacement); -char *M_StringJoin(const char *s, ...); -boolean M_StringStartsWith(const char *s, const char *prefix); -boolean M_StringEndsWith(const char *s, const char *suffix); -int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args); -int M_snprintf(char *buf, size_t buf_len, const char *s, ...) PRINTF_ATTR(3, 4); -void M_NormalizeSlashes(char *str); +/* debugging code to check there are no loops in a linked list + * disabled unless explicitly requested + */ - -// debugging code to check there are no loops in a linked list -// disabled unless explicitly requested #ifdef DEBUG_LINKED_LISTS - -#define LINKED_LIST_CHECK_NO_CYCLE(list_type, list, next_member) \ - do \ - { \ - if (list != NULL) { \ - list_type *slow, *fast; \ - slow = list; \ - fast = list->next_member; \ - while (fast) { \ - if (!fast->next_member) { \ - break; \ - } \ - fast = fast->next_member->next_member; \ - slow = slow->next_member; \ - if (slow == fast) { \ - fprintf(stderr, "loop in linked list " # list " in %s:%d", __FILE__, __LINE__); \ - __builtin_trap(); \ - } \ - } \ - } \ - } while (0) \ - - - -#else // DEBUG_LINKED_LISTS - - -#define LINKED_LIST_CHECK_NO_CYCLE(list_type, list, next_member) \ - do \ - { \ - } while (0) \ - - -#endif // DEBUG_LINKED_LISTS - - -#endif - +#define LINKED_LIST_CHECK_NO_CYCLE(list_type, list, next_member) \ + do \ + { \ + if (list != NULL) \ + { \ + list_type *slow, *fast; \ + slow = list; \ + fast = list->next_member; \ + while (fast) \ + { \ + if (!fast->next_member) \ + { \ + break; \ + } \ + fast = fast->next_member->next_member; \ + slow = slow->next_member; \ + if (slow == fast) \ + { \ + fprintf(stderr, "loop in linked list " #list " in %s:%d", \ + __FILE__, __LINE__); \ + __builtin_trap(); \ + } \ + } \ + } \ + } \ + while (0) + +#else /* DEBUG_LINKED_LISTS */ + +#define LINKED_LIST_CHECK_NO_CYCLE(list_type, list, next_member) \ + do \ + { \ + } \ + while (0) + +#endif /* DEBUG_LINKED_LISTS */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +boolean m_write_file(const char *name, const void *source, int length); +int m_read_file(const char *name, byte **buffer); +void m_make_directory(const char *dir); +char *m_temp_file(const char *s); +boolean m_file_exists(const char *file); +char *m_file_case_exists(const char *file); +long m_file_length(FILE *handle); +boolean m_str_to_int(const char *str, int *result); +char *m_dir_name(const char *path); +const char *m_base_name(const char *path); +void m_extract_file_base(const char *path, char *dest); +void m_force_uppercase(char *text); +void m_force_lowercase(char *text); +char *m_string_duplicate(const char *orig); +boolean m_str_copy(char *dest, const char *src, size_t dest_size); +boolean m_string_concat(char *dest, const char *src, size_t dest_size); +char *m_string_replace(const char *haystack, const char *needle, + const char *replacement); +char *m_string_join(const char *s, ...); +boolean m_string_starts_with(const char *s, const char *prefix); +boolean m_string_ends_with(const char *s, const char *suffix); +void m_normalize_slashes(char *str); + +#endif /* __M_MISC__ */ diff --git a/games/NXDoom/src/memio.c b/games/NXDoom/src/memio.c index 299a66bf73d..aeb8ac8a8ce 100644 --- a/games/NXDoom/src/memio.c +++ b/games/NXDoom/src/memio.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Emulates the IO functions in C stdio.h reading and writing to -// memory. -// +/**************************************************************************** + * apps/games/NXDoom/src/memio.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Emulates the IO functions in C stdio.h reading and writing to + * memory. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -24,174 +33,183 @@ #include "z_zone.h" -typedef enum { - MODE_READ, - MODE_WRITE, +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef enum +{ + MODE_READ, + MODE_WRITE, } memfile_mode_t; -struct _MEMFILE { - unsigned char *buf; - size_t buflen; - size_t alloced; - unsigned int position; - memfile_mode_t mode; +struct _MEMFILE +{ + unsigned char *buf; + size_t buflen; + size_t alloced; + unsigned int position; + memfile_mode_t mode; }; -// Open a memory area for reading +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Open a memory area for reading */ MEMFILE *mem_fopen_read(void *buf, size_t buflen) { - MEMFILE *file; + MEMFILE *file; - file = Z_Malloc(sizeof(MEMFILE), PU_STATIC, 0); + file = z_malloc(sizeof(MEMFILE), PU_STATIC, 0); - file->buf = (unsigned char *) buf; - file->buflen = buflen; - file->position = 0; - file->mode = MODE_READ; + file->buf = (unsigned char *)buf; + file->buflen = buflen; + file->position = 0; + file->mode = MODE_READ; - return file; + return file; } -// Read bytes +/* Read bytes */ size_t mem_fread(void *buf, size_t size, size_t nmemb, MEMFILE *stream) { - size_t items; - - if (stream->mode != MODE_READ) - { - printf("not a read stream\n"); - return -1; - } - - // Trying to read more bytes than we have left? - - items = nmemb; - - if (items * size > stream->buflen - stream->position) - { - items = (stream->buflen - stream->position) / size; - } - - // Copy bytes to buffer - - memcpy(buf, stream->buf + stream->position, items * size); - - // Update position - - stream->position += items * size; - - return items; + size_t items; + + if (stream->mode != MODE_READ) + { + printf("not a read stream\n"); + return -1; + } + + /* Trying to read more bytes than we have left? */ + + items = nmemb; + + if (items * size > stream->buflen - stream->position) + { + items = (stream->buflen - stream->position) / size; + } + + /* Copy bytes to buffer */ + + memcpy(buf, stream->buf + stream->position, items * size); + + /* Update position */ + + stream->position += items * size; + + return items; } -// Open a memory area for writing +/* Open a memory area for writing */ MEMFILE *mem_fopen_write(void) { - MEMFILE *file; + MEMFILE *file; - file = Z_Malloc(sizeof(MEMFILE), PU_STATIC, 0); + file = z_malloc(sizeof(MEMFILE), PU_STATIC, 0); - file->alloced = 1024; - file->buf = Z_Malloc(file->alloced, PU_STATIC, 0); - file->buflen = 0; - file->position = 0; - file->mode = MODE_WRITE; + file->alloced = 1024; + file->buf = z_malloc(file->alloced, PU_STATIC, 0); + file->buflen = 0; + file->position = 0; + file->mode = MODE_WRITE; - return file; + return file; } -// Write bytes to stream +/* Write bytes to stream */ -size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, MEMFILE *stream) +size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, + MEMFILE *stream) { - size_t bytes; - - if (stream->mode != MODE_WRITE) - { - return -1; - } - - // More bytes than can fit in the buffer? - // If so, reallocate bigger. - - bytes = size * nmemb; - - while (bytes > stream->alloced - stream->position) - { - unsigned char *newbuf; - - newbuf = Z_Malloc(stream->alloced * 2, PU_STATIC, 0); - memcpy(newbuf, stream->buf, stream->alloced); - Z_Free(stream->buf); - stream->buf = newbuf; - stream->alloced *= 2; - } - - // Copy into buffer - - memcpy(stream->buf + stream->position, ptr, bytes); - stream->position += bytes; - - if (stream->position > stream->buflen) - stream->buflen = stream->position; - - return nmemb; + size_t bytes; + + if (stream->mode != MODE_WRITE) + { + return -1; + } + + /* More bytes than can fit in the buffer? + * If so, reallocate bigger. + */ + + bytes = size * nmemb; + + while (bytes > stream->alloced - stream->position) + { + unsigned char *newbuf; + + newbuf = z_malloc(stream->alloced * 2, PU_STATIC, 0); + memcpy(newbuf, stream->buf, stream->alloced); + z_free(stream->buf); + stream->buf = newbuf; + stream->alloced *= 2; + } + + /* Copy into buffer */ + + memcpy(stream->buf + stream->position, ptr, bytes); + stream->position += bytes; + + if (stream->position > stream->buflen) stream->buflen = stream->position; + + return nmemb; } void mem_get_buf(MEMFILE *stream, void **buf, size_t *buflen) { - *buf = stream->buf; - *buflen = stream->buflen; + *buf = stream->buf; + *buflen = stream->buflen; } void mem_fclose(MEMFILE *stream) { - if (stream->mode == MODE_WRITE) - { - Z_Free(stream->buf); - } + if (stream->mode == MODE_WRITE) + { + z_free(stream->buf); + } - Z_Free(stream); + z_free(stream); } long mem_ftell(MEMFILE *stream) { - return stream->position; + return stream->position; } int mem_fseek(MEMFILE *stream, signed long position, mem_rel_t whence) { - unsigned int newpos; - - switch (whence) - { - case MEM_SEEK_SET: - newpos = (int) position; - break; - - case MEM_SEEK_CUR: - newpos = (int) (stream->position + position); - break; - - case MEM_SEEK_END: - newpos = (int) (stream->buflen + position); - break; - default: - return -1; - } - - if (newpos < stream->buflen) - { - stream->position = newpos; - return 0; - } - else - { - printf("Error seeking to %u\n", newpos); - return -1; - } + unsigned int newpos; + + switch (whence) + { + case MEM_SEEK_SET: + newpos = (int)position; + break; + + case MEM_SEEK_CUR: + newpos = (int)(stream->position + position); + break; + + case MEM_SEEK_END: + newpos = (int)(stream->buflen + position); + break; + default: + return -1; + } + + if (newpos < stream->buflen) + { + stream->position = newpos; + return 0; + } + else + { + printf("Error seeking to %u\n", newpos); + return -1; + } } - - diff --git a/games/NXDoom/src/memio.h b/games/NXDoom/src/memio.h index 03706a3171a..275fbc753b5 100644 --- a/games/NXDoom/src/memio.h +++ b/games/NXDoom/src/memio.h @@ -1,38 +1,51 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// +/**************************************************************************** + * apps/games/NXDoom/src/memio.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + ****************************************************************************/ #ifndef MEMIO_H #define MEMIO_H +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef struct _MEMFILE MEMFILE; -typedef enum +typedef enum { - MEM_SEEK_SET, - MEM_SEEK_CUR, - MEM_SEEK_END, + MEM_SEEK_SET, + MEM_SEEK_CUR, + MEM_SEEK_END, } mem_rel_t; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + MEMFILE *mem_fopen_read(void *buf, size_t buflen); size_t mem_fread(void *buf, size_t size, size_t nmemb, MEMFILE *stream); MEMFILE *mem_fopen_write(void); -size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, MEMFILE *stream); +size_t mem_fwrite(const void *ptr, size_t size, size_t nmemb, + MEMFILE *stream); void mem_get_buf(MEMFILE *stream, void **buf, size_t *buflen); void mem_fclose(MEMFILE *stream); long mem_ftell(MEMFILE *stream); int mem_fseek(MEMFILE *stream, signed long offset, mem_rel_t whence); -#endif /* #ifndef MEMIO_H */ - +#endif /* MEMIO_H */ diff --git a/games/NXDoom/src/midifallback.c b/games/NXDoom/src/midifallback.c deleted file mode 100644 index 615d6880f23..00000000000 --- a/games/NXDoom/src/midifallback.c +++ /dev/null @@ -1,370 +0,0 @@ -// -// Copyright(C) 2022 ceski -// -// 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. -// -// DESCRIPTION: -// MIDI instrument fallback support -// - -#ifdef _WIN32 - -#include "doomtype.h" -#include "midifile.h" -#include "midifallback.h" - -static const byte drums_table[128] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x18, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F -}; - -static byte variation[128][128]; -static byte bank_msb[MIDI_CHANNELS_PER_TRACK]; -static byte drum_map[MIDI_CHANNELS_PER_TRACK]; -static boolean selected[MIDI_CHANNELS_PER_TRACK]; - -static void UpdateDrumMap(const byte *msg, unsigned int length) -{ - byte idx; - byte checksum; - - // GS allows drums on any channel using SysEx messages. - // The message format is F0 followed by: - // - // 41 10 42 12 40 15 F7 - // - // is [11-19, 10, 1A-1F] for channels 1-16. Note the position of 10. - // is 00-02 for off (normal part), drum map 1, or drum map 2. - // is checksum. - - if (length == 10 && - msg[0] == 0x41 && // Roland - msg[1] == 0x10 && // Device ID - msg[2] == 0x42 && // GS - msg[3] == 0x12 && // DT1 - msg[4] == 0x40 && // Address MSB - msg[6] == 0x15 && // Address LSB - msg[9] == 0xF7) // SysEx EOX - { - checksum = 128 - ((int)msg[4] + msg[5] + msg[6] + msg[7]) % 128; - - if (msg[8] != checksum) - { - return; - } - - if (msg[5] == 0x10) // Channel 10 - { - idx = 9; - } - else if (msg[5] < 0x1A) // Channels 1-9 - { - idx = (msg[5] & 0x0F) - 1; - } - else // Channels 11-16 - { - idx = msg[5] & 0x0F; - } - - drum_map[idx] = msg[7]; - } -} - -static boolean GetProgramFallback(byte idx, byte program, - midi_fallback_t *fallback) -{ - if (drum_map[idx] == 0) // Normal channel - { - if (bank_msb[idx] == 0 || variation[bank_msb[idx]][program]) - { - // Found a capital or variation for this bank select MSB. - selected[idx] = true; - return false; - } - - fallback->type = FALLBACK_BANK_MSB; - - if (!selected[idx] || bank_msb[idx] > 63) - { - // Fall to capital when no instrument has (successfully) - // selected this variation or if the variation is above 63. - fallback->value = 0; - return true; - } - - // A previous instrument used this variation but it's not - // valid for the current instrument. Fall to the next valid - // "sub-capital" (next variation that is a multiple of 8). - fallback->value = (bank_msb[idx] / 8) * 8; - while (fallback->value > 0) - { - if (variation[fallback->value][program]) - { - break; - } - fallback->value -= 8; - } - return true; - } - else // Drums channel - { - if (program != drums_table[program]) - { - // Use drum set from drums fallback table. - // Drums 0-63 and 127: same as original SC-55 (1.00 - 1.21). - // Drums 64-126: standard drum set (0). - fallback->type = FALLBACK_DRUMS; - fallback->value = drums_table[program]; - selected[idx] = true; - return true; - } - } - - return false; -} - -void MIDI_CheckFallback(const midi_event_t *event, midi_fallback_t *fallback, - boolean allow_sysex) -{ - byte idx; - byte program; - - switch ((int)event->event_type) - { - case MIDI_EVENT_SYSEX: - if (allow_sysex) - { - UpdateDrumMap(event->data.sysex.data, event->data.sysex.length); - } - break; - - case MIDI_EVENT_CONTROLLER: - idx = event->data.channel.channel; - switch (event->data.channel.param1) - { - case MIDI_CONTROLLER_BANK_SELECT_MSB: - bank_msb[idx] = event->data.channel.param2; - selected[idx] = false; - break; - - case MIDI_CONTROLLER_BANK_SELECT_LSB: - selected[idx] = false; - if (event->data.channel.param2 > 0) - { - // Bank select LSB > 0 not supported. This also - // preserves user's current SC-XX map. - fallback->type = FALLBACK_BANK_LSB; - fallback->value = 0; - return; - } - break; - - case EMIDI_CONTROLLER_PROGRAM_CHANGE: - program = event->data.channel.param2; - if (GetProgramFallback(idx, program, fallback)) - { - return; - } - break; - } - break; - - case MIDI_EVENT_PROGRAM_CHANGE: - idx = event->data.channel.channel; - program = event->data.channel.param1; - if (GetProgramFallback(idx, program, fallback)) - { - return; - } - break; - } - - fallback->type = FALLBACK_NONE; - fallback->value = 0; -} - -void MIDI_ResetFallback(void) -{ - int i; - - for (i = 0; i < MIDI_CHANNELS_PER_TRACK; i++) - { - bank_msb[i] = 0; - drum_map[i] = 0; - selected[i] = false; - } - - // Channel 10 (index 9) is set to drum map 1 by default. - drum_map[9] = 1; -} - -void MIDI_InitFallback(void) -{ - byte program; - - MIDI_ResetFallback(); - - // Capital - for (program = 0; program < 128; program++) - { - variation[0][program] = 1; - } - - // Variation #1 - variation[1][38] = 1; - variation[1][57] = 1; - variation[1][60] = 1; - variation[1][80] = 1; - variation[1][81] = 1; - variation[1][98] = 1; - variation[1][102] = 1; - variation[1][104] = 1; - variation[1][120] = 1; - variation[1][121] = 1; - variation[1][122] = 1; - variation[1][123] = 1; - variation[1][124] = 1; - variation[1][125] = 1; - variation[1][126] = 1; - variation[1][127] = 1; - - // Variation #2 - variation[2][102] = 1; - variation[2][120] = 1; - variation[2][122] = 1; - variation[2][123] = 1; - variation[2][124] = 1; - variation[2][125] = 1; - variation[2][126] = 1; - variation[2][127] = 1; - - // Variation #3 - variation[3][122] = 1; - variation[3][123] = 1; - variation[3][124] = 1; - variation[3][125] = 1; - variation[3][126] = 1; - variation[3][127] = 1; - - // Variation #4 - variation[4][122] = 1; - variation[4][124] = 1; - variation[4][125] = 1; - variation[4][126] = 1; - - // Variation #5 - variation[5][122] = 1; - variation[5][124] = 1; - variation[5][125] = 1; - variation[5][126] = 1; - - // Variation #6 - variation[6][125] = 1; - - // Variation #7 - variation[7][125] = 1; - - // Variation #8 - variation[8][0] = 1; - variation[8][1] = 1; - variation[8][2] = 1; - variation[8][3] = 1; - variation[8][4] = 1; - variation[8][5] = 1; - variation[8][6] = 1; - variation[8][11] = 1; - variation[8][12] = 1; - variation[8][14] = 1; - variation[8][16] = 1; - variation[8][17] = 1; - variation[8][19] = 1; - variation[8][21] = 1; - variation[8][24] = 1; - variation[8][25] = 1; - variation[8][26] = 1; - variation[8][27] = 1; - variation[8][28] = 1; - variation[8][30] = 1; - variation[8][31] = 1; - variation[8][38] = 1; - variation[8][39] = 1; - variation[8][40] = 1; - variation[8][48] = 1; - variation[8][50] = 1; - variation[8][61] = 1; - variation[8][62] = 1; - variation[8][63] = 1; - variation[8][80] = 1; - variation[8][81] = 1; - variation[8][107] = 1; - variation[8][115] = 1; - variation[8][116] = 1; - variation[8][117] = 1; - variation[8][118] = 1; - variation[8][125] = 1; - - // Variation #9 - variation[9][14] = 1; - variation[9][118] = 1; - variation[9][125] = 1; - - // Variation #16 - variation[16][0] = 1; - variation[16][4] = 1; - variation[16][5] = 1; - variation[16][6] = 1; - variation[16][16] = 1; - variation[16][19] = 1; - variation[16][24] = 1; - variation[16][25] = 1; - variation[16][28] = 1; - variation[16][39] = 1; - variation[16][62] = 1; - variation[16][63] = 1; - - // Variation #24 - variation[24][4] = 1; - variation[24][6] = 1; - - // Variation #32 - variation[32][16] = 1; - variation[32][17] = 1; - variation[32][24] = 1; - variation[32][52] = 1; - - // CM-64 Map (PCM) - for (program = 0; program < 64; program++) - { - variation[126][program] = 1; - } - - // CM-64 Map (LA) - for (program = 0; program < 128; program++) - { - variation[127][program] = 1; - } -} - -#endif diff --git a/games/NXDoom/src/midifallback.h b/games/NXDoom/src/midifallback.h deleted file mode 100644 index 6093b2e6ffa..00000000000 --- a/games/NXDoom/src/midifallback.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright(C) 2022 ceski -// -// 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. -// -// DESCRIPTION: -// MIDI instrument fallback support -// - -#ifdef _WIN32 - -#ifndef MIDIFALLBACK_H -#define MIDIFALLBACK_H - -#include "doomtype.h" -#include "midifile.h" - -typedef enum midi_fallback_type_t -{ - FALLBACK_NONE, - FALLBACK_BANK_MSB, - FALLBACK_BANK_LSB, - FALLBACK_DRUMS, -} midi_fallback_type_t; - -typedef struct midi_fallback_t -{ - midi_fallback_type_t type; - byte value; -} midi_fallback_t; - -void MIDI_CheckFallback(const midi_event_t *event, midi_fallback_t *fallback, - boolean allow_sysex); -void MIDI_ResetFallback(void); -void MIDI_InitFallback(void); - -#endif // MIDIFALLBACK_H - -#endif // _WIN32 diff --git a/games/NXDoom/src/midifile.c b/games/NXDoom/src/midifile.c index 258154eeab9..8374ac50dd6 100644 --- a/games/NXDoom/src/midifile.c +++ b/games/NXDoom/src/midifile.c @@ -1,24 +1,33 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Reading of MIDI files. -// +/**************************************************************************** + * apps/games/NXDoom/src/midifile.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Reading of MIDI files. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include #include "doomtype.h" #include "i_swap.h" @@ -26,813 +35,844 @@ #include "m_misc.h" #include "midifile.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define HEADER_CHUNK_ID "MThd" -#define TRACK_CHUNK_ID "MTrk" +#define TRACK_CHUNK_ID "MTrk" #define MAX_BUFFER_SIZE 0x10000 -// haleyjd 09/09/10: packing required +/* haleyjd 09/09/10: packing required */ + #ifdef _MSC_VER #pragma pack(push, 1) #endif -typedef PACKED_STRUCT ( +/**************************************************************************** + * Private Types + ****************************************************************************/ + +begin_packed_struct struct chunk_header_t { - byte chunk_id[4]; - unsigned int chunk_size; -}) chunk_header_t; + byte chunk_id[4]; + unsigned int chunk_size; +} end_packed_struct; + +typedef struct chunk_header_t chunk_header_t; -typedef PACKED_STRUCT ( +begin_packed_struct struct midi_header_t { - chunk_header_t chunk_header; - unsigned short format_type; - unsigned short num_tracks; - unsigned short time_division; -}) midi_header_t; + chunk_header_t chunk_header; + unsigned short format_type; + unsigned short num_tracks; + unsigned short time_division; +} begin_packed_struct; + +typedef struct midi_header_t midi_header_t; + +/* haleyjd 09/09/10: packing off. */ -// haleyjd 09/09/10: packing off. #ifdef _MSC_VER #pragma pack(pop) #endif typedef struct { - // Length in bytes: + /* Length in bytes: */ - unsigned int data_len; + unsigned int data_len; - // Events in this track: + /* Events in this track: */ - midi_event_t *events; - int num_events; + midi_event_t *events; + int num_events; } midi_track_t; struct midi_track_iter_s { - midi_track_t *track; - unsigned int position; - unsigned int loop_point; + midi_track_t *track; + unsigned int position; + unsigned int loop_point; }; struct midi_file_s { - midi_header_t header; + midi_header_t header; - // All tracks in this file: - midi_track_t *tracks; - unsigned int num_tracks; + /* All tracks in this file: */ - // Data buffer used to store data read for SysEx or meta events: - byte *buffer; - unsigned int buffer_size; + midi_track_t *tracks; + unsigned int num_tracks; + + /* Data buffer used to store data read for SysEx or meta events: */ + + byte *buffer; + unsigned int buffer_size; }; -// Check the header of a chunk: +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static boolean CheckChunkHeader(chunk_header_t *chunk, +/* Check the header of a chunk: */ + +static boolean check_chunk_header(chunk_header_t *chunk, const char *expected_id) { - boolean result; - - result = (memcmp((char *) chunk->chunk_id, expected_id, 4) == 0); + boolean result; + + result = (memcmp((char *)chunk->chunk_id, expected_id, 4) == 0); - if (!result) + if (!result) { - fprintf(stderr, "CheckChunkHeader: Expected '%s' chunk header, " - "got '%c%c%c%c'\n", - expected_id, - chunk->chunk_id[0], chunk->chunk_id[1], - chunk->chunk_id[2], chunk->chunk_id[3]); + fprintf(stderr, + "check_chunk_header: Expected '%s' chunk header, " + "got '%c%c%c%c'\n", + expected_id, chunk->chunk_id[0], chunk->chunk_id[1], + chunk->chunk_id[2], chunk->chunk_id[3]); } - return result; + return result; } -// Read a single byte. Returns false on error. +/* Read a single byte. Returns false on error. */ -static boolean ReadByte(byte *result, FILE *stream) +static boolean read_byte(byte *result, FILE *stream) { - int c; + int c; - c = fgetc(stream); + c = fgetc(stream); - if (c == EOF) + if (c == EOF) { - fprintf(stderr, "ReadByte: Unexpected end of file\n"); - return false; + fprintf(stderr, "read_byte: Unexpected end of file\n"); + return false; } - else + else { - *result = (byte) c; + *result = (byte)c; - return true; + return true; } } -// Read a variable-length value. +/* Read a variable-length value. */ -static boolean ReadVariableLength(unsigned int *result, FILE *stream) +static boolean read_variable_length(unsigned int *result, FILE *stream) { - int i; - byte b = 0; + int i; + byte b = 0; - *result = 0; + *result = 0; - for (i=0; i<4; ++i) + for (i = 0; i < 4; ++i) { - if (!ReadByte(&b, stream)) + if (!read_byte(&b, stream)) { - fprintf(stderr, "ReadVariableLength: Error while reading " - "variable-length value\n"); - return false; + fprintf(stderr, "read_variable_length: Error while reading " + "variable-length value\n"); + return false; } - // Insert the bottom seven bits from this byte. + /* Insert the bottom seven bits from this byte. */ - *result <<= 7; - *result |= b & 0x7f; + *result <<= 7; + *result |= b & 0x7f; - // If the top bit is not set, this is the end. + /* If the top bit is not set, this is the end. */ - if ((b & 0x80) == 0) + if ((b & 0x80) == 0) { - return true; + return true; } } - fprintf(stderr, "ReadVariableLength: Variable-length value too " - "long: maximum of four bytes\n"); - return false; + fprintf(stderr, "read_variable_length: Variable-length value too " + "long: maximum of four bytes\n"); + return false; } -// Read a byte sequence into the data buffer. +/* Read a byte sequence into the data buffer. */ -static void *ReadByteSequence(unsigned int num_bytes, FILE *stream) +static void *read_byte_sequence(unsigned int num_bytes, FILE *stream) { - unsigned int i; - byte *result; + unsigned int i; + byte *result; - // Allocate a buffer. Allocate one extra byte, as malloc(0) is - // non-portable. + /* Allocate a buffer. Allocate one extra byte, as malloc(0) is + * non-portable. + */ - result = malloc(num_bytes + 1); + result = malloc(num_bytes + 1); - if (result == NULL) + if (result == NULL) { - fprintf(stderr, "ReadByteSequence: Failed to allocate buffer\n"); - return NULL; + fprintf(stderr, "read_byte_sequence: Failed to allocate buffer\n"); + return NULL; } - // Read the data: + /* Read the data: */ - for (i=0; ievent_type = event_type & 0xf0; - event->data.channel.channel = event_type & 0x0f; + event->event_type = event_type & 0xf0; + event->data.channel.channel = event_type & 0x0f; - // Read parameters: + /* Read parameters: */ - if (!ReadByte(&b, stream)) + if (!read_byte(&b, stream)) { - fprintf(stderr, "ReadChannelEvent: Error while reading channel " - "event parameters\n"); - return false; + fprintf(stderr, "read_channel_event: Error while reading channel " + "event parameters\n"); + return false; } - event->data.channel.param1 = b; + event->data.channel.param1 = b; - // Second parameter: + /* Second parameter: */ - if (two_param) + if (two_param) { - if (!ReadByte(&b, stream)) + if (!read_byte(&b, stream)) { - fprintf(stderr, "ReadChannelEvent: Error while reading channel " - "event parameters\n"); - return false; + fprintf(stderr, "read_channel_event: Error while reading channel " + "event parameters\n"); + return false; } - event->data.channel.param2 = b; + event->data.channel.param2 = b; } - return true; + return true; } -// Read sysex event: +/* Read sysex event: */ -static boolean ReadSysExEvent(midi_event_t *event, int event_type, +static boolean read_sys_ex_event(midi_event_t *event, int event_type, FILE *stream) { - event->event_type = event_type; + event->event_type = event_type; - if (!ReadVariableLength(&event->data.sysex.length, stream)) + if (!read_variable_length(&event->data.sysex.length, stream)) { - fprintf(stderr, "ReadSysExEvent: Failed to read length of " - "SysEx block\n"); - return false; + fprintf(stderr, "read_sys_ex_event: Failed to read length of " + "SysEx block\n"); + return false; } - // Read the byte sequence: + /* Read the byte sequence: */ - event->data.sysex.data = ReadByteSequence(event->data.sysex.length, stream); + event->data.sysex.data = + read_byte_sequence(event->data.sysex.length, stream); - if (event->data.sysex.data == NULL) + if (event->data.sysex.data == NULL) { - fprintf(stderr, "ReadSysExEvent: Failed while reading SysEx event\n"); - return false; + fprintf(stderr, + "read_sys_ex_event: Failed while reading SysEx event\n"); + return false; } - return true; + return true; } -// Read meta event: +/* Read meta event: */ -static boolean ReadMetaEvent(midi_event_t *event, FILE *stream) +static boolean read_meta_event(midi_event_t *event, FILE *stream) { - byte b = 0; + byte b = 0; - event->event_type = MIDI_EVENT_META; + event->event_type = MIDI_EVENT_META; - // Read meta event type: + /* Read meta event type: */ - if (!ReadByte(&b, stream)) + if (!read_byte(&b, stream)) { - fprintf(stderr, "ReadMetaEvent: Failed to read meta event type\n"); - return false; + fprintf(stderr, "read_meta_event: Failed to read meta event type\n"); + return false; } - event->data.meta.type = b; + event->data.meta.type = b; - // Read length of meta event data: + /* Read length of meta event data: */ - if (!ReadVariableLength(&event->data.meta.length, stream)) + if (!read_variable_length(&event->data.meta.length, stream)) { - fprintf(stderr, "ReadSysExEvent: Failed to read length of " - "SysEx block\n"); - return false; + fprintf(stderr, "read_sys_ex_event: Failed to read length of " + "SysEx block\n"); + return false; } - // Read the byte sequence: + /* Read the byte sequence: */ - event->data.meta.data = ReadByteSequence(event->data.meta.length, stream); + event->data.meta.data = + read_byte_sequence(event->data.meta.length, stream); - if (event->data.meta.data == NULL) + if (event->data.meta.data == NULL) { - fprintf(stderr, "ReadSysExEvent: Failed while reading SysEx event\n"); - return false; + fprintf(stderr, + "read_sys_ex_event: Failed while reading SysEx event\n"); + return false; } - return true; + return true; } -static boolean ReadEvent(midi_event_t *event, unsigned int *last_event_type, +static boolean read_event(midi_event_t *event, unsigned int *last_event_type, FILE *stream) { - byte event_type = 0; + byte event_type = 0; - if (!ReadVariableLength(&event->delta_time, stream)) + if (!read_variable_length(&event->delta_time, stream)) { - fprintf(stderr, "ReadEvent: Failed to read event timestamp\n"); - return false; + fprintf(stderr, "read_event: Failed to read event timestamp\n"); + return false; } - if (!ReadByte(&event_type, stream)) + if (!read_byte(&event_type, stream)) { - fprintf(stderr, "ReadEvent: Failed to read event type\n"); - return false; + fprintf(stderr, "read_event: Failed to read event type\n"); + return false; } - // All event types have their top bit set. Therefore, if - // the top bit is not set, it is because we are using the "same - // as previous event type" shortcut to save a byte. Skip back - // a byte so that we read this byte again. + /* All event types have their top bit set. Therefore, if + * the top bit is not set, it is because we are using the "same + * as previous event type" shortcut to save a byte. Skip back + * a byte so that we read this byte again. + */ - if ((event_type & 0x80) == 0) + if ((event_type & 0x80) == 0) { - event_type = *last_event_type; + event_type = *last_event_type; - if (fseek(stream, -1, SEEK_CUR) < 0) + if (fseek(stream, -1, SEEK_CUR) < 0) { - fprintf(stderr, "ReadEvent: Unable to seek in stream\n"); - return false; + fprintf(stderr, "read_event: Unable to seek in stream\n"); + return false; } } - else + else { - *last_event_type = event_type; + *last_event_type = event_type; } - // Check event type: + /* Check event type: */ - switch (event_type & 0xf0) + switch (event_type & 0xf0) { - // Two parameter channel events: + /* Two parameter channel events: */ - case MIDI_EVENT_NOTE_OFF: - case MIDI_EVENT_NOTE_ON: - case MIDI_EVENT_AFTERTOUCH: - case MIDI_EVENT_CONTROLLER: - case MIDI_EVENT_PITCH_BEND: - return ReadChannelEvent(event, event_type, true, stream); + case MIDI_EVENT_NOTE_OFF: + case MIDI_EVENT_NOTE_ON: + case MIDI_EVENT_AFTERTOUCH: + case MIDI_EVENT_CONTROLLER: + case MIDI_EVENT_PITCH_BEND: + return read_channel_event(event, event_type, true, stream); - // Single parameter channel events: + /* Single parameter channel events: */ - case MIDI_EVENT_PROGRAM_CHANGE: - case MIDI_EVENT_CHAN_AFTERTOUCH: - return ReadChannelEvent(event, event_type, false, stream); + case MIDI_EVENT_PROGRAM_CHANGE: + case MIDI_EVENT_CHAN_AFTERTOUCH: + return read_channel_event(event, event_type, false, stream); - default: - break; + default: + break; } - // Specific value? + /* Specific value? */ - switch (event_type) + switch (event_type) { - case MIDI_EVENT_SYSEX: - case MIDI_EVENT_SYSEX_SPLIT: - return ReadSysExEvent(event, event_type, stream); + case MIDI_EVENT_SYSEX: + case MIDI_EVENT_SYSEX_SPLIT: + return read_sys_ex_event(event, event_type, stream); - case MIDI_EVENT_META: - return ReadMetaEvent(event, stream); + case MIDI_EVENT_META: + return read_meta_event(event, stream); - default: - break; + default: + break; } - fprintf(stderr, "ReadEvent: Unknown MIDI event type: 0x%x\n", event_type); - return false; + fprintf(stderr, "read_event: Unknown MIDI event type: 0x%x\n", event_type); + return false; } -// Free an event: +/* Free an event: */ -static void FreeEvent(midi_event_t *event) +static void free_event(midi_event_t *event) { - // Some event types have dynamically allocated buffers assigned - // to them that must be freed. + /* Some event types have dynamically allocated buffers assigned + * to them that must be freed. + */ - switch (event->event_type) + switch (event->event_type) { - case MIDI_EVENT_SYSEX: - case MIDI_EVENT_SYSEX_SPLIT: - free(event->data.sysex.data); - break; + case MIDI_EVENT_SYSEX: + case MIDI_EVENT_SYSEX_SPLIT: + free(event->data.sysex.data); + break; - case MIDI_EVENT_META: - free(event->data.meta.data); - break; + case MIDI_EVENT_META: + free(event->data.meta.data); + break; - default: - // Nothing to do. - break; + default: + break; /* Nothing to do. */ } } -// Read and check the track chunk header +/* Read and check the track chunk header */ -static boolean ReadTrackHeader(midi_track_t *track, FILE *stream) +static boolean read_track_header(midi_track_t *track, FILE *stream) { - size_t records_read; - chunk_header_t chunk_header; + size_t records_read; + chunk_header_t chunk_header; - records_read = fread(&chunk_header, sizeof(chunk_header_t), 1, stream); + records_read = fread(&chunk_header, sizeof(chunk_header_t), 1, stream); - if (records_read < 1) + if (records_read < 1) { - return false; + return false; } - if (!CheckChunkHeader(&chunk_header, TRACK_CHUNK_ID)) + if (!check_chunk_header(&chunk_header, TRACK_CHUNK_ID)) { - return false; + return false; } - track->data_len = SDL_SwapBE32(chunk_header.chunk_size); + track->data_len = be32toh(chunk_header.chunk_size); - return true; + return true; } -static boolean ReadTrack(midi_track_t *track, FILE *stream) +static boolean read_track(midi_track_t *track, FILE *stream) { - midi_event_t *new_events; - midi_event_t *event; - unsigned int last_event_type; + midi_event_t *new_events; + midi_event_t *event; + unsigned int last_event_type; - track->num_events = 0; - track->events = NULL; + track->num_events = 0; + track->events = NULL; - // Read the header: + /* Read the header: */ - if (!ReadTrackHeader(track, stream)) + if (!read_track_header(track, stream)) { - return false; + return false; } - // Then the events: + /* Then the events: */ - last_event_type = 0; + last_event_type = 0; - for (;;) + for (; ; ) { - // Resize the track slightly larger to hold another event: + /* Resize the track slightly larger to hold another event: */ - new_events = I_Realloc(track->events, + new_events = i_realloc(track->events, sizeof(midi_event_t) * (track->num_events + 1)); - track->events = new_events; + track->events = new_events; - // Read the next event: + /* Read the next event: */ - event = &track->events[track->num_events]; - if (!ReadEvent(event, &last_event_type, stream)) + event = &track->events[track->num_events]; + if (!read_event(event, &last_event_type, stream)) { - return false; + return false; } - ++track->num_events; + ++track->num_events; - // End of track? + /* End of track? */ - if (event->event_type == MIDI_EVENT_META - && event->data.meta.type == MIDI_META_END_OF_TRACK) + if (event->event_type == MIDI_EVENT_META && + event->data.meta.type == MIDI_META_END_OF_TRACK) { - break; + break; } } - return true; + return true; } -// Free a track: +/* Free a track: */ -static void FreeTrack(midi_track_t *track) +static void free_track(midi_track_t *track) { - unsigned int i; + unsigned int i; - for (i=0; inum_events; ++i) + for (i = 0; i < track->num_events; ++i) { - FreeEvent(&track->events[i]); + free_event(&track->events[i]); } - free(track->events); + free(track->events); } -static boolean ReadAllTracks(midi_file_t *file, FILE *stream) +static boolean read_all_tracks(midi_file_t *file, FILE *stream) { - unsigned int i; + unsigned int i; - // Allocate list of tracks and read each track: + /* Allocate list of tracks and read each track: */ - file->tracks = malloc(sizeof(midi_track_t) * file->num_tracks); + file->tracks = malloc(sizeof(midi_track_t) * file->num_tracks); - if (file->tracks == NULL) + if (file->tracks == NULL) { - return false; + return false; } - memset(file->tracks, 0, sizeof(midi_track_t) * file->num_tracks); + memset(file->tracks, 0, sizeof(midi_track_t) * file->num_tracks); - // Read each track: + /* Read each track: */ - for (i=0; inum_tracks; ++i) + for (i = 0; i < file->num_tracks; ++i) { - if (!ReadTrack(&file->tracks[i], stream)) + if (!read_track(&file->tracks[i], stream)) { - return false; + return false; } } - return true; + return true; } -// Read and check the header chunk. +/* Read and check the header chunk. */ -static boolean ReadFileHeader(midi_file_t *file, FILE *stream) +static boolean read_file_header(midi_file_t *file, FILE *stream) { - size_t records_read; - unsigned int format_type; + size_t records_read; + unsigned int format_type; - records_read = fread(&file->header, sizeof(midi_header_t), 1, stream); + records_read = fread(&file->header, sizeof(midi_header_t), 1, stream); - if (records_read < 1) + if (records_read < 1) { - return false; + return false; } - if (!CheckChunkHeader(&file->header.chunk_header, HEADER_CHUNK_ID) - || SDL_SwapBE32(file->header.chunk_header.chunk_size) != 6) + if (!check_chunk_header(&file->header.chunk_header, HEADER_CHUNK_ID) || + be32toh(file->header.chunk_header.chunk_size) != 6) { - fprintf(stderr, "ReadFileHeader: Invalid MIDI chunk header! " - "chunk_size=%i\n", - SDL_SwapBE32(file->header.chunk_header.chunk_size)); - return false; + fprintf(stderr, + "read_file_header: Invalid MIDI chunk header! " + "chunk_size=%i\n", + be32toh(file->header.chunk_header.chunk_size)); + return false; } - format_type = SDL_SwapBE16(file->header.format_type); - file->num_tracks = SDL_SwapBE16(file->header.num_tracks); + format_type = be32toh(file->header.format_type); + file->num_tracks = be32toh(file->header.num_tracks); - if ((format_type != 0 && format_type != 1) - || file->num_tracks < 1) + if ((format_type != 0 && format_type != 1) || file->num_tracks < 1) { - fprintf(stderr, "ReadFileHeader: Only type 0/1 " - "MIDI files supported!\n"); - return false; + fprintf(stderr, "read_file_header: Only type 0/1 " + "MIDI files supported!\n"); + return false; } - return true; + return true; } -void MIDI_FreeFile(midi_file_t *file) +void midi_free_file(midi_file_t *file) { - int i; + int i; - if (file->tracks != NULL) + if (file->tracks != NULL) { - for (i=0; inum_tracks; ++i) + for (i = 0; i < file->num_tracks; ++i) { - FreeTrack(&file->tracks[i]); + free_track(&file->tracks[i]); } - free(file->tracks); + free(file->tracks); } - free(file); + free(file); } -midi_file_t *MIDI_LoadFile(char *filename) +midi_file_t *midi_loadfile(char *filename) { - midi_file_t *file; - FILE *stream; + midi_file_t *file; + FILE *stream; - file = malloc(sizeof(midi_file_t)); + file = malloc(sizeof(midi_file_t)); - if (file == NULL) + if (file == NULL) { - return NULL; + return NULL; } - file->tracks = NULL; - file->num_tracks = 0; - file->buffer = NULL; - file->buffer_size = 0; + file->tracks = NULL; + file->num_tracks = 0; + file->buffer = NULL; + file->buffer_size = 0; - // Open file + /* Open file */ - stream = M_fopen(filename, "rb"); + stream = fopen(filename, "rb"); - if (stream == NULL) + if (stream == NULL) { - fprintf(stderr, "MIDI_LoadFile: Failed to open '%s'\n", filename); - MIDI_FreeFile(file); - return NULL; + fprintf(stderr, "midi_loadfile: Failed to open '%s'\n", filename); + midi_free_file(file); + return NULL; } - // Read MIDI file header + /* Read MIDI file header */ - if (!ReadFileHeader(file, stream)) + if (!read_file_header(file, stream)) { - fclose(stream); - MIDI_FreeFile(file); - return NULL; + fclose(stream); + midi_free_file(file); + return NULL; } - // Read all tracks: + /* Read all tracks: */ - if (!ReadAllTracks(file, stream)) + if (!read_all_tracks(file, stream)) { - fclose(stream); - MIDI_FreeFile(file); - return NULL; + fclose(stream); + midi_free_file(file); + return NULL; } - fclose(stream); + fclose(stream); - return file; + return file; } -// Get the number of tracks in a MIDI file. +#ifdef TEST +static char *midi_event_type_to_string(midi_event_type_t event_type) +{ + switch (event_type) + { + case MIDI_EVENT_NOTE_OFF: + return "MIDI_EVENT_NOTE_OFF"; + case MIDI_EVENT_NOTE_ON: + return "MIDI_EVENT_NOTE_ON"; + case MIDI_EVENT_AFTERTOUCH: + return "MIDI_EVENT_AFTERTOUCH"; + case MIDI_EVENT_CONTROLLER: + return "MIDI_EVENT_CONTROLLER"; + case MIDI_EVENT_PROGRAM_CHANGE: + return "MIDI_EVENT_PROGRAM_CHANGE"; + case MIDI_EVENT_CHAN_AFTERTOUCH: + return "MIDI_EVENT_CHAN_AFTERTOUCH"; + case MIDI_EVENT_PITCH_BEND: + return "MIDI_EVENT_PITCH_BEND"; + case MIDI_EVENT_SYSEX: + return "MIDI_EVENT_SYSEX"; + case MIDI_EVENT_SYSEX_SPLIT: + return "MIDI_EVENT_SYSEX_SPLIT"; + case MIDI_EVENT_META: + return "MIDI_EVENT_META"; + + default: + return "(unknown)"; + } +} +#endif -unsigned int MIDI_NumTracks(midi_file_t *file) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Get the number of tracks in a MIDI file. */ + +unsigned int midi_num_tracks(midi_file_t *file) { - return file->num_tracks; + return file->num_tracks; } -// Start iterating over the events in a track. +/* Start iterating over the events in a track. */ -midi_track_iter_t *MIDI_IterateTrack(midi_file_t *file, unsigned int track) +midi_track_iter_t *midi_iterate_track(midi_file_t *file, unsigned int track) { - midi_track_iter_t *iter; + midi_track_iter_t *iter; - assert(track < file->num_tracks); + assert(track < file->num_tracks); - iter = malloc(sizeof(*iter)); - iter->track = &file->tracks[track]; - iter->position = 0; - iter->loop_point = 0; + iter = malloc(sizeof(*iter)); + iter->track = &file->tracks[track]; + iter->position = 0; + iter->loop_point = 0; - return iter; + return iter; } -void MIDI_FreeIterator(midi_track_iter_t *iter) +void midi_free_iterator(midi_track_iter_t *iter) { - free(iter); + free(iter); } -// Get the time until the next MIDI event in a track. +/* Get the time until the next MIDI event in a track. */ -unsigned int MIDI_GetDeltaTime(midi_track_iter_t *iter) +unsigned int midi_get_delta_time(midi_track_iter_t *iter) { - if (iter->position < iter->track->num_events) + if (iter->position < iter->track->num_events) { - midi_event_t *next_event; + midi_event_t *next_event; - next_event = &iter->track->events[iter->position]; + next_event = &iter->track->events[iter->position]; - return next_event->delta_time; + return next_event->delta_time; } - else + else { - return 0; + return 0; } } -// Get a pointer to the next MIDI event. +/* Get a pointer to the next MIDI event. */ -int MIDI_GetNextEvent(midi_track_iter_t *iter, midi_event_t **event) +int midi_get_next_event(midi_track_iter_t *iter, midi_event_t **event) { - if (iter->position < iter->track->num_events) + if (iter->position < iter->track->num_events) { - *event = &iter->track->events[iter->position]; - ++iter->position; + *event = &iter->track->events[iter->position]; + ++iter->position; - return 1; + return 1; } - else + else { - return 0; + return 0; } } -unsigned int MIDI_GetFileTimeDivision(midi_file_t *file) +unsigned int midi_get_file_time_division(midi_file_t *file) { - short result = SDL_SwapBE16(file->header.time_division); + short result = be16toh(file->header.time_division); - // Negative time division indicates SMPTE time and must be handled - // differently. - if (result < 0) + /* Negative time division indicates SMPTE time and must be handled + * differently. + */ + + if (result < 0) { - return (signed int)(-(result/256)) - * (signed int)(result & 0xFF); + return (signed int)(-(result / 256)) * + (signed int)(result & 0xff); } - else + else { - return result; + return result; } } -void MIDI_RestartIterator(midi_track_iter_t *iter) +void midi_restart_iterator(midi_track_iter_t *iter) { - iter->position = 0; - iter->loop_point = 0; + iter->position = 0; + iter->loop_point = 0; } -void MIDI_SetLoopPoint(midi_track_iter_t *iter) +void midi_set_loop_point(midi_track_iter_t *iter) { - iter->loop_point = iter->position; + iter->loop_point = iter->position; } -void MIDI_RestartAtLoopPoint(midi_track_iter_t *iter) +void midi_restart_at_loop_point(midi_track_iter_t *iter) { - iter->position = iter->loop_point; + iter->position = iter->loop_point; } #ifdef TEST - -static char *MIDI_EventTypeToString(midi_event_type_t event_type) +void print_track(midi_track_t *track) { - switch (event_type) + midi_event_t *event; + unsigned int i; + + for (i = 0; i < track->num_events; ++i) { + event = &track->events[i]; + + if (event->delta_time > 0) + { + printf("Delay: %u ticks\n", event->delta_time); + } + + printf("Event type: %s (%i)\n", + midi_event_type_to_string(event->event_type), + event->event_type); + + switch (event->event_type) + { case MIDI_EVENT_NOTE_OFF: - return "MIDI_EVENT_NOTE_OFF"; case MIDI_EVENT_NOTE_ON: - return "MIDI_EVENT_NOTE_ON"; case MIDI_EVENT_AFTERTOUCH: - return "MIDI_EVENT_AFTERTOUCH"; case MIDI_EVENT_CONTROLLER: - return "MIDI_EVENT_CONTROLLER"; case MIDI_EVENT_PROGRAM_CHANGE: - return "MIDI_EVENT_PROGRAM_CHANGE"; case MIDI_EVENT_CHAN_AFTERTOUCH: - return "MIDI_EVENT_CHAN_AFTERTOUCH"; case MIDI_EVENT_PITCH_BEND: - return "MIDI_EVENT_PITCH_BEND"; + printf("\tChannel: %u\n", event->data.channel.channel); + printf("\tParameter 1: %u\n", event->data.channel.param1); + printf("\tParameter 2: %u\n", event->data.channel.param2); + break; + case MIDI_EVENT_SYSEX: - return "MIDI_EVENT_SYSEX"; case MIDI_EVENT_SYSEX_SPLIT: - return "MIDI_EVENT_SYSEX_SPLIT"; - case MIDI_EVENT_META: - return "MIDI_EVENT_META"; - - default: - return "(unknown)"; - } -} - -void PrintTrack(midi_track_t *track) -{ - midi_event_t *event; - unsigned int i; - - for (i=0; inum_events; ++i) - { - event = &track->events[i]; - - if (event->delta_time > 0) - { - printf("Delay: %u ticks\n", event->delta_time); - } + printf("\tLength: %u\n", event->data.sysex.length); + break; - printf("Event type: %s (%i)\n", - MIDI_EventTypeToString(event->event_type), - event->event_type); - - switch(event->event_type) - { - case MIDI_EVENT_NOTE_OFF: - case MIDI_EVENT_NOTE_ON: - case MIDI_EVENT_AFTERTOUCH: - case MIDI_EVENT_CONTROLLER: - case MIDI_EVENT_PROGRAM_CHANGE: - case MIDI_EVENT_CHAN_AFTERTOUCH: - case MIDI_EVENT_PITCH_BEND: - printf("\tChannel: %u\n", event->data.channel.channel); - printf("\tParameter 1: %u\n", event->data.channel.param1); - printf("\tParameter 2: %u\n", event->data.channel.param2); - break; - - case MIDI_EVENT_SYSEX: - case MIDI_EVENT_SYSEX_SPLIT: - printf("\tLength: %u\n", event->data.sysex.length); - break; - - case MIDI_EVENT_META: - printf("\tMeta type: %u\n", event->data.meta.type); - printf("\tLength: %u\n", event->data.meta.length); - break; + case MIDI_EVENT_META: + printf("\tMeta type: %u\n", event->data.meta.type); + printf("\tLength: %u\n", event->data.meta.length); + break; } } } int main(int argc, char *argv[]) { - midi_file_t *file; - unsigned int i; + midi_file_t *file; + unsigned int i; - if (argc < 2) + if (argc < 2) { - printf("Usage: %s \n", argv[0]); - exit(1); + printf("Usage: %s \n", argv[0]); + exit(1); } - file = MIDI_LoadFile(argv[1]); + file = midi_loadfile(argv[1]); - if (file == NULL) + if (file == NULL) { - fprintf(stderr, "Failed to open %s\n", argv[1]); - exit(1); + fprintf(stderr, "Failed to open %s\n", argv[1]); + exit(1); } - for (i=0; inum_tracks; ++i) + for (i = 0; i < file->num_tracks; ++i) { - printf("\n== Track %u ==\n\n", i); + printf("\n== Track %u ==\n\n", i); - PrintTrack(&file->tracks[i]); + print_track(&file->tracks[i]); } - return 0; + return 0; } - #endif - diff --git a/games/NXDoom/src/midifile.h b/games/NXDoom/src/midifile.h index 035d6f8aa75..e6dc9166e51 100644 --- a/games/NXDoom/src/midifile.h +++ b/games/NXDoom/src/midifile.h @@ -1,232 +1,251 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// MIDI file parsing. -// +/**************************************************************************** + * apps/games/NXDoom/src/midifile.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * MIDI file parsing. + * + ****************************************************************************/ #ifndef MIDIFILE_H #define MIDIFILE_H -typedef struct midi_file_s midi_file_t; -typedef struct midi_track_iter_s midi_track_iter_t; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ #define MIDI_CHANNELS_PER_TRACK 16 -#define MIDI_RPN_MSB 0x00 +#define MIDI_RPN_MSB 0x00 #define MIDI_RPN_PITCH_BEND_SENS_LSB 0x00 -#define MIDI_RPN_FINE_TUNING_LSB 0x01 -#define MIDI_RPN_COARSE_TUNING_LSB 0x02 -#define MIDI_RPN_NULL 0x7F +#define MIDI_RPN_FINE_TUNING_LSB 0x01 +#define MIDI_RPN_COARSE_TUNING_LSB 0x02 +#define MIDI_RPN_NULL 0x7f + +#define EMIDI_LOOP_FLAG 0x7f + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef struct midi_file_s midi_file_t; +typedef struct midi_track_iter_s midi_track_iter_t; typedef enum { - MIDI_EVENT_NOTE_OFF = 0x80, - MIDI_EVENT_NOTE_ON = 0x90, - MIDI_EVENT_AFTERTOUCH = 0xA0, - MIDI_EVENT_CONTROLLER = 0xB0, - MIDI_EVENT_PROGRAM_CHANGE = 0xC0, - MIDI_EVENT_CHAN_AFTERTOUCH = 0xD0, - MIDI_EVENT_PITCH_BEND = 0xE0, - - MIDI_EVENT_SYSEX = 0xF0, - MIDI_EVENT_SYSEX_SPLIT = 0xF7, - MIDI_EVENT_META = 0xFF, + MIDI_EVENT_NOTE_OFF = 0x80, + MIDI_EVENT_NOTE_ON = 0x90, + MIDI_EVENT_AFTERTOUCH = 0xa0, + MIDI_EVENT_CONTROLLER = 0xb0, + MIDI_EVENT_PROGRAM_CHANGE = 0xc0, + MIDI_EVENT_CHAN_AFTERTOUCH = 0xd0, + MIDI_EVENT_PITCH_BEND = 0xe0, + + MIDI_EVENT_SYSEX = 0xf0, + MIDI_EVENT_SYSEX_SPLIT = 0xf7, + MIDI_EVENT_META = 0xff, } midi_event_type_t; typedef enum { - MIDI_CONTROLLER_BANK_SELECT_MSB = 0x00, - MIDI_CONTROLLER_MODULATION = 0x01, - MIDI_CONTROLLER_BREATH_CONTROL = 0x02, - MIDI_CONTROLLER_FOOT_CONTROL = 0x04, - MIDI_CONTROLLER_PORTAMENTO = 0x05, - MIDI_CONTROLLER_DATA_ENTRY_MSB = 0x06, - MIDI_CONTROLLER_VOLUME_MSB = 0x07, - MIDI_CONTROLLER_PAN = 0x0A, - MIDI_CONTROLLER_EXPRESSION = 0x0B, - - MIDI_CONTROLLER_BANK_SELECT_LSB = 0x20, - MIDI_CONTROLLER_DATA_ENTRY_LSB = 0x26, - MIDI_CONTROLLER_VOLUME_LSB = 0X27, - - MIDI_CONTROLLER_HOLD1_PEDAL = 0x40, - MIDI_CONTROLLER_SOFT_PEDAL = 0x43, - - MIDI_CONTROLLER_REVERB = 0x5B, - MIDI_CONTROLLER_CHORUS = 0x5D, - - MIDI_CONTROLLER_NRPN_LSB = 0x62, - MIDI_CONTROLLER_NRPN_MSB = 0x63, - MIDI_CONTROLLER_RPN_LSB = 0x64, - MIDI_CONTROLLER_RPN_MSB = 0x65, - - MIDI_CONTROLLER_ALL_SOUND_OFF = 0x78, - MIDI_CONTROLLER_RESET_ALL_CTRLS = 0x79, - MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B, - - MIDI_CONTROLLER_POLY_MODE_OFF = 0x7E, - MIDI_CONTROLLER_POLY_MODE_ON = 0x7F, + MIDI_CONTROLLER_BANK_SELECT_MSB = 0x00, + MIDI_CONTROLLER_MODULATION = 0x01, + MIDI_CONTROLLER_BREATH_CONTROL = 0x02, + MIDI_CONTROLLER_FOOT_CONTROL = 0x04, + MIDI_CONTROLLER_PORTAMENTO = 0x05, + MIDI_CONTROLLER_DATA_ENTRY_MSB = 0x06, + MIDI_CONTROLLER_VOLUME_MSB = 0x07, + MIDI_CONTROLLER_PAN = 0x0a, + MIDI_CONTROLLER_EXPRESSION = 0x0b, + + MIDI_CONTROLLER_BANK_SELECT_LSB = 0x20, + MIDI_CONTROLLER_DATA_ENTRY_LSB = 0x26, + MIDI_CONTROLLER_VOLUME_LSB = 0X27, + + MIDI_CONTROLLER_HOLD1_PEDAL = 0x40, + MIDI_CONTROLLER_SOFT_PEDAL = 0x43, + + MIDI_CONTROLLER_REVERB = 0x5b, + MIDI_CONTROLLER_CHORUS = 0x5d, + + MIDI_CONTROLLER_NRPN_LSB = 0x62, + MIDI_CONTROLLER_NRPN_MSB = 0x63, + MIDI_CONTROLLER_RPN_LSB = 0x64, + MIDI_CONTROLLER_RPN_MSB = 0x65, + + MIDI_CONTROLLER_ALL_SOUND_OFF = 0x78, + MIDI_CONTROLLER_RESET_ALL_CTRLS = 0x79, + MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7b, + + MIDI_CONTROLLER_POLY_MODE_OFF = 0x7e, + MIDI_CONTROLLER_POLY_MODE_ON = 0x7f, } midi_controller_t; typedef enum { - MIDI_META_SEQUENCE_NUMBER = 0x00, - - MIDI_META_TEXT = 0x01, - MIDI_META_COPYRIGHT = 0x02, - MIDI_META_TRACK_NAME = 0x03, - MIDI_META_INSTR_NAME = 0x04, - MIDI_META_LYRICS = 0x05, - MIDI_META_MARKER = 0x06, - MIDI_META_CUE_POINT = 0x07, - - MIDI_META_CHANNEL_PREFIX = 0x20, - MIDI_META_END_OF_TRACK = 0x2F, - - MIDI_META_SET_TEMPO = 0x51, - MIDI_META_SMPTE_OFFSET = 0x54, - MIDI_META_TIME_SIGNATURE = 0x58, - MIDI_META_KEY_SIGNATURE = 0x59, - MIDI_META_SEQUENCER_SPECIFIC = 0x7F, + MIDI_META_SEQUENCE_NUMBER = 0x00, + + MIDI_META_TEXT = 0x01, + MIDI_META_COPYRIGHT = 0x02, + MIDI_META_TRACK_NAME = 0x03, + MIDI_META_INSTR_NAME = 0x04, + MIDI_META_LYRICS = 0x05, + MIDI_META_MARKER = 0x06, + MIDI_META_CUE_POINT = 0x07, + + MIDI_META_CHANNEL_PREFIX = 0x20, + MIDI_META_END_OF_TRACK = 0x2f, + + MIDI_META_SET_TEMPO = 0x51, + MIDI_META_SMPTE_OFFSET = 0x54, + MIDI_META_TIME_SIGNATURE = 0x58, + MIDI_META_KEY_SIGNATURE = 0x59, + MIDI_META_SEQUENCER_SPECIFIC = 0x7f, } midi_meta_event_type_t; -#define EMIDI_LOOP_FLAG 0x7F - typedef enum { - EMIDI_DEVICE_GENERAL_MIDI = 0x00, - EMIDI_DEVICE_SOUND_CANVAS = 0x01, - EMIDI_DEVICE_AWE32 = 0x02, - EMIDI_DEVICE_WAVE_BLASTER = 0x03, - EMIDI_DEVICE_SOUND_BLASTER = 0x04, - EMIDI_DEVICE_PRO_AUDIO = 0x05, - EMIDI_DEVICE_SOUND_MAN_16 = 0x06, - EMIDI_DEVICE_ADLIB = 0x07, - EMIDI_DEVICE_SOUNDSCAPE = 0x08, - EMIDI_DEVICE_ULTRASOUND = 0x09, - EMIDI_DEVICE_ALL = 0x7F, + EMIDI_DEVICE_GENERAL_MIDI = 0x00, + EMIDI_DEVICE_SOUND_CANVAS = 0x01, + EMIDI_DEVICE_AWE32 = 0x02, + EMIDI_DEVICE_WAVE_BLASTER = 0x03, + EMIDI_DEVICE_SOUND_BLASTER = 0x04, + EMIDI_DEVICE_PRO_AUDIO = 0x05, + EMIDI_DEVICE_SOUND_MAN_16 = 0x06, + EMIDI_DEVICE_ADLIB = 0x07, + EMIDI_DEVICE_SOUNDSCAPE = 0x08, + EMIDI_DEVICE_ULTRASOUND = 0x09, + EMIDI_DEVICE_ALL = 0x7f, } emidi_device_t; typedef enum { - EMIDI_CONTROLLER_TRACK_DESIGNATION = 0x6E, - EMIDI_CONTROLLER_TRACK_EXCLUSION = 0x6F, - EMIDI_CONTROLLER_PROGRAM_CHANGE = 0x70, - EMIDI_CONTROLLER_VOLUME = 0x71, - EMIDI_CONTROLLER_LOOP_BEGIN = 0x74, - EMIDI_CONTROLLER_LOOP_END = 0x75, - EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN = 0x76, - EMIDI_CONTROLLER_GLOBAL_LOOP_END = 0x77, + EMIDI_CONTROLLER_TRACK_DESIGNATION = 0x6e, + EMIDI_CONTROLLER_TRACK_EXCLUSION = 0x6f, + EMIDI_CONTROLLER_PROGRAM_CHANGE = 0x70, + EMIDI_CONTROLLER_VOLUME = 0x71, + EMIDI_CONTROLLER_LOOP_BEGIN = 0x74, + EMIDI_CONTROLLER_LOOP_END = 0x75, + EMIDI_CONTROLLER_GLOBAL_LOOP_BEGIN = 0x76, + EMIDI_CONTROLLER_GLOBAL_LOOP_END = 0x77, } emidi_controller_t; typedef struct { - // Meta event type: + /* Meta event type: */ - unsigned int type; + unsigned int type; - // Length: + /* Length: */ - unsigned int length; + unsigned int length; - // Meta event data: + /* Meta event data: */ - byte *data; + byte *data; } midi_meta_event_data_t; typedef struct { - // Length: + /* Length: */ - unsigned int length; + unsigned int length; - // Event data: + /* Event data: */ - byte *data; + byte *data; } midi_sysex_event_data_t; typedef struct { - // The channel number to which this applies: + /* The channel number to which this applies: */ - unsigned int channel; + unsigned int channel; - // Extra parameters: + /* Extra parameters: */ - unsigned int param1; - unsigned int param2; + unsigned int param1; + unsigned int param2; } midi_channel_event_data_t; typedef struct { - // Time between the previous event and this event. - unsigned int delta_time; - - // Type of event: - midi_event_type_t event_type; - - union - { - midi_channel_event_data_t channel; - midi_meta_event_data_t meta; - midi_sysex_event_data_t sysex; - } data; + /* Time between the previous event and this event. */ + + unsigned int delta_time; + + /* Type of event: */ + + midi_event_type_t event_type; + + union + { + midi_channel_event_data_t channel; + midi_meta_event_data_t meta; + midi_sysex_event_data_t sysex; + } data; } midi_event_t; -// Load a MIDI file. +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -midi_file_t *MIDI_LoadFile(char *filename); +/* Load a MIDI file. */ -// Free a MIDI file. +midi_file_t *midi_loadfile(char *filename); -void MIDI_FreeFile(midi_file_t *file); +/* Free a MIDI file. */ -// Get the time division value from the MIDI header. +void midi_free_file(midi_file_t *file); -unsigned int MIDI_GetFileTimeDivision(midi_file_t *file); +/* Get the time division value from the MIDI header. */ -// Get the number of tracks in a MIDI file. +unsigned int midi_get_file_time_division(midi_file_t *file); -unsigned int MIDI_NumTracks(midi_file_t *file); +/* Get the number of tracks in a MIDI file. */ -// Start iterating over the events in a track. +unsigned int midi_num_tracks(midi_file_t *file); -midi_track_iter_t *MIDI_IterateTrack(midi_file_t *file, unsigned int track_num); +/* Start iterating over the events in a track. */ -// Free an iterator. +midi_track_iter_t *midi_iterate_track(midi_file_t *file, + unsigned int track_num); -void MIDI_FreeIterator(midi_track_iter_t *iter); +/* Free an iterator. */ -// Get the time until the next MIDI event in a track. +void midi_free_iterator(midi_track_iter_t *iter); -unsigned int MIDI_GetDeltaTime(midi_track_iter_t *iter); +/* Get the time until the next MIDI event in a track. */ -// Get a pointer to the next MIDI event. +unsigned int midi_get_delta_time(midi_track_iter_t *iter); -int MIDI_GetNextEvent(midi_track_iter_t *iter, midi_event_t **event); +/* Get a pointer to the next MIDI event. */ -// Reset an iterator to the beginning of a track. +int midi_get_next_event(midi_track_iter_t *iter, midi_event_t **event); -void MIDI_RestartIterator(midi_track_iter_t *iter); +/* Reset an iterator to the beginning of a track. */ -// Set loop point to current position. +void midi_restart_iterator(midi_track_iter_t *iter); -void MIDI_SetLoopPoint(midi_track_iter_t *iter); +/* Set loop point to current position. */ -// Set position to saved loop point. +void midi_set_loop_point(midi_track_iter_t *iter); -void MIDI_RestartAtLoopPoint(midi_track_iter_t *iter); +/* Set position to saved loop point. */ -#endif /* #ifndef MIDIFILE_H */ +void midi_restart_at_loop_point(midi_track_iter_t *iter); +#endif /* MIDIFILE_H */ diff --git a/games/NXDoom/src/mus2mid.c b/games/NXDoom/src/mus2mid.c index f81f939f22f..502e1025262 100644 --- a/games/NXDoom/src/mus2mid.c +++ b/games/NXDoom/src/mus2mid.c @@ -1,20 +1,30 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// Copyright(C) 2006 Ben Ryves 2006 -// -// 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. -// -// mus2mid.c - Ben Ryves 2006 - http://benryves.com - benryves@benryves.com -// Use to convert a MUS file into a single track, type 0 MIDI file. +/**************************************************************************** + * apps/games/NXDoom/src/mus2mid.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * Copyright(C) 2006 Ben Ryves 2006 + * + * 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. + * + * mus2mid.c - Ben Ryves 2006 - http: *benryves.com - benryves@benryves.com + * Use to convert a MUS file into a single track, type 0 MIDI file. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -25,712 +35,760 @@ #include "memio.h" #include "mus2mid.h" +#ifdef STANDALONE +#include "m_misc.h" +#include "z_zone.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define NUM_CHANNELS 16 #define MIDI_PERCUSSION_CHAN 9 #define MUS_PERCUSSION_CHAN 15 -// MUS event codes +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* MUS event codes */ + typedef enum { - mus_releasekey = 0x00, - mus_presskey = 0x10, - mus_pitchwheel = 0x20, - mus_systemevent = 0x30, - mus_changecontroller = 0x40, - mus_scoreend = 0x60 + mus_releasekey = 0x00, + mus_presskey = 0x10, + mus_pitchwheel = 0x20, + mus_systemevent = 0x30, + mus_changecontroller = 0x40, + mus_scoreend = 0x60 } musevent; -// MIDI event codes +/* MIDI event codes */ + typedef enum { - midi_releasekey = 0x80, - midi_presskey = 0x90, - midi_aftertouchkey = 0xA0, - midi_changecontroller = 0xB0, - midi_changepatch = 0xC0, - midi_aftertouchchannel = 0xD0, - midi_pitchwheel = 0xE0 + midi_releasekey = 0x80, + midi_presskey = 0x90, + midi_aftertouchkey = 0xa0, + midi_changecontroller = 0xb0, + midi_changepatch = 0xc0, + midi_aftertouchchannel = 0xd0, + midi_pitchwheel = 0xe0 } midievent; -// Structure to hold MUS file header -typedef PACKED_STRUCT ( +/* Structure to hold MUS file header */ + +begin_packed_struct struct musheader { - byte id[4]; - unsigned short scorelength; - unsigned short scorestart; - unsigned short primarychannels; - unsigned short secondarychannels; - unsigned short instrumentcount; -}) musheader; - -// Standard MIDI type 0 header + track header + byte id[4]; + unsigned short scorelength; + unsigned short scorestart; + unsigned short primarychannels; + unsigned short secondarychannels; + unsigned short instrumentcount; +} end_packed_struct; + +typedef struct musheader musheader; + +/* Standard MIDI type 0 header + track header */ + static const byte midiheader[] = { - 'M', 'T', 'h', 'd', // Main header - 0x00, 0x00, 0x00, 0x06, // Header size - 0x00, 0x00, // MIDI type (0) - 0x00, 0x01, // Number of tracks - 0x00, 0x46, // Resolution - 'M', 'T', 'r', 'k', // Start of track - 0x00, 0x00, 0x00, 0x00 // Placeholder for track length + 'M', 'T', 'h', 'd', /* Main header */ + 0x00, 0x00, 0x00, 0x06, /* Header size */ + 0x00, 0x00, /* MIDI type (0) */ + 0x00, 0x01, /* Number of tracks */ + 0x00, 0x46, /* Resolution */ + 'M', 'T', 'r', 'k', /* Start of track */ + 0x00, 0x00, 0x00, 0x00 /* Placeholder for track length */ }; -// Cached channel velocities +/* Cached channel velocities */ + static byte channelvelocities[] = { - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127 + 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, }; -// Timestamps between sequences of MUS events +/* Timestamps between sequences of MUS events */ static unsigned int queuedtime = 0; -// Counter for the length of the track +/* Counter for the length of the track */ static unsigned int tracksize; static const byte controller_map[] = { - 0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D, - 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79 + 0x00, 0x20, 0x01, 0x07, 0x0a, 0x0b, 0x5b, 0x5d, + 0x40, 0x43, 0x78, 0x7b, 0x7e, 0x7f, 0x79, }; static int channel_map[NUM_CHANNELS]; -// Write timestamp to a MIDI file. +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Write timestamp to a MIDI file. */ -static boolean WriteTime(unsigned int time, MEMFILE *midioutput) +static boolean write_time(unsigned int time, MEMFILE *midioutput) { - unsigned int buffer = time & 0x7F; - byte writeval; + unsigned int buffer = time & 0x7f; + byte writeval; - while ((time >>= 7) != 0) + while ((time >>= 7) != 0) { - buffer <<= 8; - buffer |= ((time & 0x7F) | 0x80); + buffer <<= 8; + buffer |= ((time & 0x7f) | 0x80); } - for (;;) + for (; ; ) { - writeval = (byte)(buffer & 0xFF); + writeval = (byte)(buffer & 0xff); - if (mem_fwrite(&writeval, 1, 1, midioutput) != 1) + if (mem_fwrite(&writeval, 1, 1, midioutput) != 1) { - return true; + return true; } - ++tracksize; + ++tracksize; - if ((buffer & 0x80) != 0) + if ((buffer & 0x80) != 0) { - buffer >>= 8; + buffer >>= 8; } - else + else { - queuedtime = 0; - return false; + queuedtime = 0; + return false; } } } +/* Write the end of track marker */ -// Write the end of track marker -static boolean WriteEndTrack(MEMFILE *midioutput) +static boolean write_end_track(MEMFILE *midioutput) { - byte endtrack[] = {0xFF, 0x2F, 0x00}; + byte endtrack[] = + { + 0xff, 0x2f, 0x00 + }; - if (WriteTime(queuedtime, midioutput)) + if (write_time(queuedtime, midioutput)) { - return true; + return true; } - if (mem_fwrite(endtrack, 1, 3, midioutput) != 3) + if (mem_fwrite(endtrack, 1, 3, midioutput) != 3) { - return true; + return true; } - tracksize += 3; - return false; + tracksize += 3; + return false; } -// Write a key press event -static boolean WritePressKey(byte channel, byte key, - byte velocity, MEMFILE *midioutput) +/* Write a key press event */ + +static boolean write_press_key(byte channel, byte key, byte velocity, + MEMFILE *midioutput) { - byte working = midi_presskey | channel; + byte working = midi_presskey | channel; - if (WriteTime(queuedtime, midioutput)) + if (write_time(queuedtime, midioutput)) { - return true; + return true; } - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = key & 0x7F; + working = key & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = velocity & 0x7F; + working = velocity & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - tracksize += 3; + tracksize += 3; - return false; + return false; } -// Write a key release event -static boolean WriteReleaseKey(byte channel, byte key, - MEMFILE *midioutput) +/* Write a key release event */ + +static boolean write_release_key(byte channel, byte key, MEMFILE *midioutput) { - byte working = midi_releasekey | channel; + byte working = midi_releasekey | channel; - if (WriteTime(queuedtime, midioutput)) + if (write_time(queuedtime, midioutput)) { - return true; + return true; } - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = key & 0x7F; + working = key & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = 0; + working = 0; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - tracksize += 3; + tracksize += 3; - return false; + return false; } -// Write a pitch wheel/bend event -static boolean WritePitchWheel(byte channel, short wheel, - MEMFILE *midioutput) +/* Write a pitch wheel/bend event */ + +static boolean write_pitch_wheel(byte channel, short wheel, + MEMFILE *midioutput) { - byte working = midi_pitchwheel | channel; + byte working = midi_pitchwheel | channel; - if (WriteTime(queuedtime, midioutput)) + if (write_time(queuedtime, midioutput)) { - return true; + return true; } - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = wheel & 0x7F; + working = wheel & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = (wheel >> 7) & 0x7F; + working = (wheel >> 7) & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - tracksize += 3; - return false; + tracksize += 3; + return false; } -// Write a patch change event -static boolean WriteChangePatch(byte channel, byte patch, - MEMFILE *midioutput) +/* Write a patch change event */ + +static boolean write_change_patch(byte channel, byte patch, + MEMFILE *midioutput) { - byte working = midi_changepatch | channel; + byte working = midi_changepatch | channel; - if (WriteTime(queuedtime, midioutput)) + if (write_time(queuedtime, midioutput)) { - return true; + return true; } - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = patch & 0x7F; + working = patch & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - tracksize += 2; + tracksize += 2; - return false; + return false; } -// Write a valued controller change event +/* Write a valued controller change event */ -static boolean WriteChangeController_Valued(byte channel, - byte control, - byte value, - MEMFILE *midioutput) +static boolean write_change_controller_valued(byte channel, byte control, + byte value, MEMFILE *midioutput) { - byte working = midi_changecontroller | channel; + byte working = midi_changecontroller | channel; - if (WriteTime(queuedtime, midioutput)) + if (write_time(queuedtime, midioutput)) { - return true; + return true; } - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - working = control & 0x7F; + working = control & 0x7f; - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - // Quirk in vanilla DOOM? MUS controller values should be - // 7-bit, not 8-bit. + /* Quirk in vanilla DOOM? MUS controller values should be + * 7-bit, not 8-bit. + */ - working = value;// & 0x7F; + working = value; /* & 0x7F; */ - // Fix on said quirk to stop MIDI players from complaining that - // the value is out of range: + /* Fix on said quirk to stop MIDI players from complaining that + * the value is out of range: + */ - if (working & 0x80) + if (working & 0x80) { - working = 0x7F; + working = 0x7f; } - if (mem_fwrite(&working, 1, 1, midioutput) != 1) + if (mem_fwrite(&working, 1, 1, midioutput) != 1) { - return true; + return true; } - tracksize += 3; + tracksize += 3; - return false; + return false; } -// Write a valueless controller change event -static boolean WriteChangeController_Valueless(byte channel, - byte control, +/* Write a valueless controller change event */ + +static boolean write_change_controller_valueless(byte channel, byte control, MEMFILE *midioutput) { - return WriteChangeController_Valued(channel, control, 0, - midioutput); + return write_change_controller_valued(channel, control, 0, midioutput); } -// Allocate a free MIDI channel. +/* Allocate a free MIDI channel. */ -static int AllocateMIDIChannel(void) +static int allocate_midi_channel(void) { - int result; - int max; - int i; + int result; + int max; + int i; - // Find the current highest-allocated channel. + /* Find the current highest-allocated channel. */ - max = -1; + max = -1; - for (i=0; i max) + if (channel_map[i] > max) { - max = channel_map[i]; + max = channel_map[i]; } } - // max is now equal to the highest-allocated MIDI channel. We can - // now allocate the next available channel. This also works if - // no channels are currently allocated (max=-1) + /* max is now equal to the highest-allocated MIDI channel. We can + * now allocate the next available channel. This also works if + * no channels are currently allocated (max=-1) + */ - result = max + 1; + result = max + 1; - // Don't allocate the MIDI percussion channel! + /* Don't allocate the MIDI percussion channel! */ - if (result == MIDI_PERCUSSION_CHAN) + if (result == MIDI_PERCUSSION_CHAN) { - ++result; + ++result; } - return result; + return result; } -// Given a MUS channel number, get the MIDI channel number to use -// in the outputted file. +/* Given a MUS channel number, get the MIDI channel number to use + * in the outputted file. + */ -static int GetMIDIChannel(int mus_channel, MEMFILE *midioutput) +static int get_midi_channel(int mus_channel, MEMFILE *midioutput) { - // Find the MIDI channel to use for this MUS channel. - // MUS channel 15 is the percusssion channel. + /* Find the MIDI channel to use for this MUS channel. + * MUS channel 15 is the percusssion channel. + */ - if (mus_channel == MUS_PERCUSSION_CHAN) + if (mus_channel == MUS_PERCUSSION_CHAN) { - return MIDI_PERCUSSION_CHAN; + return MIDI_PERCUSSION_CHAN; } - else + else { - // If a MIDI channel hasn't been allocated for this MUS channel - // yet, allocate the next free MIDI channel. + /* If a MIDI channel hasn't been allocated for this MUS channel + * yet, allocate the next free MIDI channel. + */ - if (channel_map[mus_channel] == -1) + if (channel_map[mus_channel] == -1) { - channel_map[mus_channel] = AllocateMIDIChannel(); + channel_map[mus_channel] = allocate_midi_channel(); + + /* First time using the channel, send an "all notes off" + * event. This fixes "The D_DDTBLU disease" described here: + * https: *www.doomworld.com/vb/source-ports/66802-the + */ - // First time using the channel, send an "all notes off" - // event. This fixes "The D_DDTBLU disease" described here: - // https://www.doomworld.com/vb/source-ports/66802-the - WriteChangeController_Valueless(channel_map[mus_channel], 0x7b, - midioutput); + write_change_controller_valueless(channel_map[mus_channel], 0x7b, + midioutput); } - return channel_map[mus_channel]; + return channel_map[mus_channel]; } } -static boolean ReadMusHeader(MEMFILE *file, musheader *header) +static boolean read_mus_header(MEMFILE *file, musheader *header) { - boolean result; + boolean result; - result = mem_fread(&header->id, sizeof(byte), 4, file) == 4 - && mem_fread(&header->scorelength, sizeof(short), 1, file) == 1 - && mem_fread(&header->scorestart, sizeof(short), 1, file) == 1 - && mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1 - && mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1 - && mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1; + result = + mem_fread(&header->id, sizeof(byte), 4, file) == 4 && + mem_fread(&header->scorelength, sizeof(short), 1, file) == 1 && + mem_fread(&header->scorestart, sizeof(short), 1, file) == 1 && + mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1 && + mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1 && + mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1; - if (result) + if (result) { - header->scorelength = SHORT(header->scorelength); - header->scorestart = SHORT(header->scorestart); - header->primarychannels = SHORT(header->primarychannels); - header->secondarychannels = SHORT(header->secondarychannels); - header->instrumentcount = SHORT(header->instrumentcount); + header->scorelength = SHORT(header->scorelength); + header->scorestart = SHORT(header->scorestart); + header->primarychannels = SHORT(header->primarychannels); + header->secondarychannels = SHORT(header->secondarychannels); + header->instrumentcount = SHORT(header->instrumentcount); } - return result; + return result; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// Read a MUS file from a stream (musinput) and output a MIDI file to -// a stream (midioutput). -// -// Returns 0 on success or 1 on failure. +/* Read a MUS file from a stream (musinput) and output a MIDI file to + * a stream (midioutput). + * + * Returns 0 on success or 1 on failure. + */ boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput) { - // Header for the MUS file - musheader musfileheader; + /* Header for the MUS file */ + + musheader musfileheader; + + /* Descriptor for the current MUS event */ + + byte eventdescriptor; + int channel; /* Channel number */ + musevent event; - // Descriptor for the current MUS event - byte eventdescriptor; - int channel; // Channel number - musevent event; + /* Bunch of vars read from MUS lump */ + byte key; + byte controllernumber; + byte controllervalue; - // Bunch of vars read from MUS lump - byte key; - byte controllernumber; - byte controllervalue; + /* Buffer used for MIDI track size record */ - // Buffer used for MIDI track size record - byte tracksizebuffer[4]; + byte tracksizebuffer[4]; - // Flag for when the score end marker is hit. - int hitscoreend = 0; + /* Flag for when the score end marker is hit. */ - // Temp working byte - byte working; - // Used in building up time delays - unsigned int timedelay; + int hitscoreend = 0; - // Initialise channel map to mark all channels as unused. + /* Temp working byte */ - for (channel=0; channel 14) - { - return true; - } + case mus_systemevent: + if (mem_fread(&controllernumber, 1, 1, musinput) != 1) + { + return true; + } - if (WriteChangeController_Valueless(channel, - controller_map[controllernumber], - midioutput)) - { - return true; - } + if (controllernumber < 10 || controllernumber > 14) + { + return true; + } - break; + if (write_change_controller_valueless( + channel, controller_map[controllernumber], midioutput)) + { + return true; + } - case mus_changecontroller: - if (mem_fread(&controllernumber, 1, 1, musinput) != 1) - { - return true; - } + break; - if (mem_fread(&controllervalue, 1, 1, musinput) != 1) + case mus_changecontroller: + if (mem_fread(&controllernumber, 1, 1, musinput) != 1) + { + return true; + } + + if (mem_fread(&controllervalue, 1, 1, musinput) != 1) + { + return true; + } + + if (controllernumber == 0) + { + if (write_change_patch(channel, controllervalue, + midioutput)) { - return true; + return true; } - - if (controllernumber == 0) + } + else + { + if (controllernumber < 1 || controllernumber > 9) { - if (WriteChangePatch(channel, controllervalue, - midioutput)) - { - return true; - } + return true; } - else + + if (write_change_controller_valued( + channel, controller_map[controllernumber], + controllervalue, midioutput)) { - if (controllernumber < 1 || controllernumber > 9) - { - return true; - } - - if (WriteChangeController_Valued(channel, - controller_map[controllernumber], - controllervalue, - midioutput)) - { - return true; - } + return true; } + } - break; + break; - case mus_scoreend: - hitscoreend = 1; - break; + case mus_scoreend: + hitscoreend = 1; + break; - default: - return true; - break; + default: + return true; + break; } - if (eventdescriptor & 0x80) + if (eventdescriptor & 0x80) { - break; + break; } } - // Now we need to read the time code: - if (!hitscoreend) + + /* Now we need to read the time code: */ + + if (!hitscoreend) { - timedelay = 0; - for (;;) + timedelay = 0; + for (; ; ) { - if (mem_fread(&working, 1, 1, musinput) != 1) + if (mem_fread(&working, 1, 1, musinput) != 1) { - return true; + return true; } - timedelay = timedelay * 128 + (working & 0x7F); - if ((working & 0x80) == 0) + timedelay = timedelay * 128 + (working & 0x7f); + if ((working & 0x80) == 0) { - break; + break; } } - queuedtime += timedelay; + + queuedtime += timedelay; } } - // End of track - if (WriteEndTrack(midioutput)) + /* End of track */ + + if (write_end_track(midioutput)) { - return true; + return true; } - // Write the track size into the stream - if (mem_fseek(midioutput, 18, MEM_SEEK_SET)) + /* Write the track size into the stream */ + + if (mem_fseek(midioutput, 18, MEM_SEEK_SET)) { - return true; + return true; } - tracksizebuffer[0] = (tracksize >> 24) & 0xff; - tracksizebuffer[1] = (tracksize >> 16) & 0xff; - tracksizebuffer[2] = (tracksize >> 8) & 0xff; - tracksizebuffer[3] = tracksize & 0xff; + tracksizebuffer[0] = (tracksize >> 24) & 0xff; + tracksizebuffer[1] = (tracksize >> 16) & 0xff; + tracksizebuffer[2] = (tracksize >> 8) & 0xff; + tracksizebuffer[3] = tracksize & 0xff; - if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4) + if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4) { - return true; + return true; } - return false; + return false; } #ifdef STANDALONE - -#include "m_misc.h" -#include "z_zone.h" - int main(int argc, char *argv[]) { - MEMFILE *src, *dst; - byte *infile; - long infile_len; - void *outfile; - size_t outfile_len; + MEMFILE *src, *dst; + byte *infile; + long infile_len; + void *outfile; + size_t outfile_len; - if (argc != 3) + if (argc != 3) { - printf("Usage: %s \n", argv[0]); - exit(-1); + printf("Usage: %s \n", argv[0]); + exit(-1); } - Z_Init(); + z_init(); - infile_len = M_ReadFile(argv[1], &infile); + infile_len = m_read_file(argv[1], &infile); - src = mem_fopen_read(infile, infile_len); - dst = mem_fopen_write(); + src = mem_fopen_read(infile, infile_len); + dst = mem_fopen_write(); - if (mus2mid(src, dst)) + if (mus2mid(src, dst)) { - fprintf(stderr, "mus2mid() failed\n"); - exit(-1); + fprintf(stderr, "mus2mid() failed\n"); + exit(-1); } - // Write result to output file: + /* Write result to output file: */ - mem_get_buf(dst, &outfile, &outfile_len); + mem_get_buf(dst, &outfile, &outfile_len); - M_WriteFile(argv[2], outfile, outfile_len); + m_write_file(argv[2], outfile, outfile_len); - return 0; + return 0; } - -#endif - +#endif /* STANDALONE */ diff --git a/games/NXDoom/src/mus2mid.h b/games/NXDoom/src/mus2mid.h index 324025a2c53..e8cafc4a8ac 100644 --- a/games/NXDoom/src/mus2mid.h +++ b/games/NXDoom/src/mus2mid.h @@ -1,29 +1,41 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// Copyright(C) 2006 Ben Ryves 2006 -// -// 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. -// -// -// mus2mid.h - Ben Ryves 2006 - http://benryves.com - benryves@benryves.com -// Use to convert a MUS file into a single track, type 0 MIDI file. +/**************************************************************************** + * apps/games/NXDoom/src/mus2mid.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * Copyright(C) 2006 Ben Ryves 2006 + * + * 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. + * + * mus2mid.h - Ben Ryves 2006 - http: *benryves.com - benryves@benryves.com + * Use to convert a MUS file into a single track, type 0 MIDI file. + * + ****************************************************************************/ #ifndef MUS2MID_H #define MUS2MID_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" #include "memio.h" -boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef MUS2MID_H */ +boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput); +#endif /* MUS2MID_H */ diff --git a/games/NXDoom/src/net_client.c b/games/NXDoom/src/net_client.c index 19b720fa6a4..fb589f692a3 100644 --- a/games/NXDoom/src/net_client.c +++ b/games/NXDoom/src/net_client.c @@ -1,18 +1,27 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Network client code -// +/**************************************************************************** + * apps/games/NXDoom/src/net_client.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Network client code + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -20,15 +29,15 @@ #include #include "config.h" -#include "doomtype.h" +#include "d_loop.h" #include "deh_main.h" #include "deh_str.h" -#include "d_loop.h" +#include "doomtype.h" #include "i_system.h" #include "i_timer.h" #include "m_argv.h" -#include "m_fixed.h" #include "m_config.h" +#include "m_fixed.h" #include "m_misc.h" #include "net_client.h" #include "net_common.h" @@ -39,1191 +48,1264 @@ #include "net_query.h" #include "net_server.h" #include "net_structrw.h" -#include "net_petname.h" #include "w_checksum.h" #include "w_wad.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define net_cl_expand_ticnum(b) net_expand_tic_num(recvwindow_start, (b)) + +#define KP 0.1 +#define KI 0.01 +#define KD 0.02 + +/**************************************************************************** + * Private Types + ****************************************************************************/ typedef enum { - // waiting for the game to launch + /* waiting for the game to launch */ - CLIENT_STATE_WAITING_LAUNCH, + CLIENT_STATE_WAITING_LAUNCH, - // waiting for the game to start + /* waiting for the game to start */ - CLIENT_STATE_WAITING_START, + CLIENT_STATE_WAITING_START, - // in game - - CLIENT_STATE_IN_GAME, + /* in game */ + CLIENT_STATE_IN_GAME, } net_clientstate_t; -// Type of structure used in the receive window +/* Type of structure used in the receive window */ typedef struct { - // Whether this tic has been received yet - - boolean active; + /* Whether this tic has been received yet */ - // Last time we sent a resend request for this tic + boolean active; - unsigned int resend_time; + /* Last time we sent a resend request for this tic */ - // Tic data from server + unsigned int resend_time; - net_full_ticcmd_t cmd; + /* Tic data from server */ + net_full_ticcmd_t cmd; } net_server_recv_t; -// Type of structure used in the send window +/* Type of structure used in the send window */ typedef struct { - // Whether this slot is active yet + /* Whether this slot is active yet */ - boolean active; + boolean active; - // The tic number + /* The tic number */ - unsigned int seq; + unsigned int seq; - // Time the command was generated + /* Time the command was generated */ - unsigned int time; + unsigned int time; - // Ticcmd diff + /* Ticcmd diff */ - net_ticdiff_t cmd; + net_ticdiff_t cmd; } net_server_send_t; +/**************************************************************************** + * Private Data + ****************************************************************************/ static net_connection_t client_connection; static net_clientstate_t client_state; static net_addr_t *server_addr; static net_context_t *client_context; -// game settings, as received from the server when the game started +/* game settings, as received from the server when the game started */ static net_gamesettings_t settings; -// Why did the server reject us? -char *net_client_reject_reason = NULL; +/* The last ticcmd constructed */ -// true if the client code is in use +static ticcmd_t last_ticcmd; -boolean net_client_connected; +/* Buffer of ticcmd diffs being sent to the server */ -// true if we have received waiting data from the server, -// and the wait data that was received. +static net_server_send_t send_queue[CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; -boolean net_client_received_wait_data; -net_waitdata_t net_client_wait_data; +/* Receive window */ -// Waiting at the initial wait screen for the game to be launched? +static ticcmd_t recvwindow_cmd_base[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; +static int recvwindow_start; +static net_server_recv_t recvwindow[CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; -boolean net_waiting_for_launch = false; +/* Whether we need to send an acknowledgement and + * when gamedata was last received. + */ -// Name that we send to the server +static boolean need_to_acknowledge; +static unsigned int gamedata_recv_time; -char *net_player_name = NULL; +/* The latency (time between when we sent our command and we got all + * the other players' commands from the server) for the last tic we + * received. We include this latency in tics we send to the server so + * that they can adjust to us. + */ -// Connected but not participating in the game (observer) +static int last_latency; -boolean drone = false; +/**************************************************************************** + * Public Data + ****************************************************************************/ -// The last ticcmd constructed +/* Why did the server reject us? */ -static ticcmd_t last_ticcmd; +char *net_client_reject_reason = NULL; -// Buffer of ticcmd diffs being sent to the server +/* true if the client code is in use */ -static net_server_send_t send_queue[BACKUPTICS]; +boolean net_client_connected; -// Receive window +/* true if we have received waiting data from the server, + * and the wait data that was received. + */ -static ticcmd_t recvwindow_cmd_base[NET_MAXPLAYERS]; -static int recvwindow_start; -static net_server_recv_t recvwindow[BACKUPTICS]; +boolean net_client_received_wait_data; +net_waitdata_t net_client_wait_data; -// Whether we need to send an acknowledgement and -// when gamedata was last received. +/* Waiting at the initial wait screen for the game to be launched? */ -static boolean need_to_acknowledge; -static unsigned int gamedata_recv_time; +boolean net_waiting_for_launch = false; -// The latency (time between when we sent our command and we got all -// the other players' commands from the server) for the last tic we -// received. We include this latency in tics we send to the server so -// that they can adjust to us. -static int last_latency; +/* Name that we send to the server */ -// Hash checksums of our wad directory and dehacked data. +char *net_player_name = NULL; + +/* Connected but not participating in the game (observer) */ + +boolean drone = false; + +/* Hash checksums of our wad directory and dehacked data. */ sha1_digest_t net_local_wad_sha1sum; sha1_digest_t net_local_deh_sha1sum; -// Are we playing with the freedoom IWAD? +/* Are we playing with the freedoom IWAD? */ unsigned int net_local_is_freedoom; -#define NET_CL_ExpandTicNum(b) NET_ExpandTicNum(recvwindow_start, (b)) +/**************************************************************************** + * Private Functions + ****************************************************************************/ -// Called when we become disconnected from the server +/* Called when we become disconnected from the server */ -static void NET_CL_Disconnected(void) +static void net_cl_disconnected(void) { - D_ReceiveTic(NULL, NULL); + d_receive_tic(NULL, NULL); } -// Called when a packet is received from the server containing game -// data. This updates the clock synchronization variable (offsetms) -// using a PID filter that keeps client clocks in sync. -static void UpdateClockSync(unsigned int seq, - unsigned int remote_latency) +/* Called when a packet is received from the server containing game + * data. This updates the clock synchronization variable (offsetms) + * using a PID filter that keeps client clocks in sync. + */ + +static void update_clock_sync(unsigned int seq, unsigned int remote_latency) { - static int last_error, cumul_error; - int latency, error; + static int last_error; + static int cumul_error; + int latency; + int error; - if (seq == send_queue[seq % BACKUPTICS].seq) + if (seq == send_queue[seq % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].seq) { - latency = I_GetTimeMS() - send_queue[seq % BACKUPTICS].time; + latency = i_get_time_ms() - + send_queue[seq % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].time; } - else if (seq > send_queue[seq % BACKUPTICS].seq) + else if (seq > send_queue[seq % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].seq) { - // We have received the ticcmd from the server before we have - // even sent ours + /* We have received the ticcmd from the server before we have + * even sent ours + */ - latency = 0; + latency = 0; } - else + else { - return; + return; } - // PID filter. These are manually trained parameters. -#define KP 0.1 -#define KI 0.01 -#define KD 0.02 + /* PID filter. These are manually trained parameters. */ - // How does our latency compare to the worst other player? - error = latency - remote_latency; - cumul_error += error; + /* How does our latency compare to the worst other player? */ - offsetms = KP * (FRACUNIT * error) - - KI * (FRACUNIT * cumul_error) - + (KD * FRACUNIT) * (last_error - error); + error = latency - remote_latency; + cumul_error += error; - last_error = error; - last_latency = latency; + offsetms = KP * (FRACUNIT * error) - KI * (FRACUNIT * cumul_error) + + (KD * FRACUNIT) * (last_error - error); - NET_Log("client: latency %d, remote %d -> offset=%dms, cumul_error=%d", - latency, remote_latency, offsetms / FRACUNIT, cumul_error); + last_error = error; + last_latency = latency; + + net_log_info( + "client: latency %d, remote %d -> offset=%dms, cumul_error=%d", + latency, remote_latency, offsetms / FRACUNIT, cumul_error); } -// Expand a net_full_ticcmd_t, applying the diffs in cmd->cmds as -// patches against recvwindow_cmd_base. Place the results into -// the d_net.c structures (netcmds/nettics) and save the new ticcmd -// back into recvwindow_cmd_base. +/* Expand a net_full_ticcmd_t, applying the diffs in cmd->cmds as + * patches against recvwindow_cmd_base. Place the results into + * the d_net.c structures (netcmds/nettics) and save the new ticcmd + * back into recvwindow_cmd_base. + */ -static void NET_CL_ExpandFullTiccmd(net_full_ticcmd_t *cmd, unsigned int seq, - ticcmd_t *ticcmds) +static void net_cl_expand_full_ticcmd(net_full_ticcmd_t *cmd, + unsigned int seq, ticcmd_t *ticcmds) { - int i; + int i; + + /* Expand tic diffs for all players */ - // Expand tic diffs for all players - - for (i=0; iplayeringame[i]) + + if (cmd->playeringame[i]) { - net_ticdiff_t *diff; + net_ticdiff_t *diff; - diff = &cmd->cmds[i]; + diff = &cmd->cmds[i]; - // Use the ticcmd diff to patch the previous ticcmd to - // the new ticcmd + /* Use the ticcmd diff to patch the previous ticcmd to + * the new ticcmd + */ - NET_TiccmdPatch(&recvwindow_cmd_base[i], diff, &ticcmds[i]); + net_ticcmd_patch(&recvwindow_cmd_base[i], diff, &ticcmds[i]); - // Store a copy for next time + /* Store a copy for next time */ - recvwindow_cmd_base[i] = ticcmds[i]; + recvwindow_cmd_base[i] = ticcmds[i]; } } } -// Advance the receive window +/* Advance the receive window */ -static void NET_CL_AdvanceWindow(void) +static void net_cl_advance_window(void) { - ticcmd_t ticcmds[NET_MAXPLAYERS]; + ticcmd_t ticcmds[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; - while (recvwindow[0].active) + while (recvwindow[0].active) { - // Expand tic diff data into d_net.c structures + /* Expand tic diff data into d_net.c structures */ - NET_CL_ExpandFullTiccmd(&recvwindow[0].cmd, recvwindow_start, + net_cl_expand_full_ticcmd(&recvwindow[0].cmd, recvwindow_start, ticcmds); - D_ReceiveTic(ticcmds, recvwindow[0].cmd.playeringame); + d_receive_tic(ticcmds, recvwindow[0].cmd.playeringame); - // Advance the window + /* Advance the window */ - memmove(recvwindow, recvwindow + 1, - sizeof(net_server_recv_t) * (BACKUPTICS - 1)); - memset(&recvwindow[BACKUPTICS-1], 0, sizeof(net_server_recv_t)); + memmove(recvwindow, recvwindow + 1, + sizeof(net_server_recv_t) * + (CONFIG_GAMES_NXDOOM_NET_BACKUPTICS - 1)); + memset(&recvwindow[CONFIG_GAMES_NXDOOM_NET_BACKUPTICS - 1], 0, + sizeof(net_server_recv_t)); - ++recvwindow_start; + ++recvwindow_start; - NET_Log("client: advanced receive window to %d", recvwindow_start); + net_log_info("client: advanced receive window to %d", + recvwindow_start); } } -// Shut down the client code, etc. Invoked after a disconnect. +/* Shut down the client code, etc. Invoked after a disconnect. */ -static void NET_CL_Shutdown(void) +static void net_cl_shutdown(void) { - if (net_client_connected) + if (net_client_connected) { - net_client_connected = false; + net_client_connected = false; - NET_ReleaseAddress(server_addr); + net_release_address(server_addr); - // Shut down network module, etc. To do. + /* Shut down network module, etc. To do. */ } } -void NET_CL_LaunchGame(void) +static void net_cl_send_game_data_ack(void) { - NET_Conn_NewReliable(&client_connection, NET_PACKET_TYPE_LAUNCH); -} + net_packet_t *packet; -void NET_CL_StartGame(net_gamesettings_t *settings) -{ - net_packet_t *packet; + packet = net_new_packet(10); - // Start from a ticcmd of all zeros + net_write_int16(packet, NET_PACKET_TYPE_GAMEDATA_ACK); + net_write_int8(packet, recvwindow_start & 0xff); - memset(&last_ticcmd, 0, sizeof(ticcmd_t)); - - // Send packet + net_conn_send_packet(&client_connection, packet); - packet = NET_Conn_NewReliable(&client_connection, - NET_PACKET_TYPE_GAMESTART); + net_free_packet(packet); - NET_WriteSettings(packet, settings); + need_to_acknowledge = false; } -static void NET_CL_SendGameDataACK(void) +static void net_cl_send_tics(int start, int end) { - net_packet_t *packet; - - packet = NET_NewPacket(10); - - NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_ACK); - NET_WriteInt8(packet, recvwindow_start & 0xff); - - NET_Conn_SendPacket(&client_connection, packet); - - NET_FreePacket(packet); + net_packet_t *packet; + int i; - need_to_acknowledge = false; -} - -static void NET_CL_SendTics(int start, int end) -{ - net_packet_t *packet; - int i; - - if (!net_client_connected) + if (!net_client_connected) { - // Disconnected from server + /* Disconnected from server */ - return; + return; } - if (start < 0) - start = 0; - - // Build a new packet to send to the server + if (start < 0) start = 0; + + /* Build a new packet to send to the server */ - packet = NET_NewPacket(512); - NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); + packet = net_new_packet(512); + net_write_int16(packet, NET_PACKET_TYPE_GAMEDATA); - // Write the start tic and number of tics. Send only the low byte - // of start - it can be inferred by the server. + /* Write the start tic and number of tics. Send only the low byte + * of start - it can be inferred by the server. + */ - NET_WriteInt8(packet, recvwindow_start & 0xff); - NET_WriteInt8(packet, start & 0xff); - NET_WriteInt8(packet, end - start + 1); + net_write_int8(packet, recvwindow_start & 0xff); + net_write_int8(packet, start & 0xff); + net_write_int8(packet, end - start + 1); - // Add the tics. + /* Add the tics. */ - for (i=start; i<=end; ++i) + for (i = start; i <= end; ++i) { - net_server_send_t *sendobj; + net_server_send_t *sendobj; - sendobj = &send_queue[i % BACKUPTICS]; + sendobj = &send_queue[i % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; - NET_WriteInt16(packet, last_latency); + net_write_int16(packet, last_latency); - NET_WriteTiccmdDiff(packet, &sendobj->cmd, settings.lowres_turn); + net_write_ticcmd_diff(packet, &sendobj->cmd, settings.lowres_turn); } - - // Send the packet - NET_Conn_SendPacket(&client_connection, packet); - - // All done! + /* Send the packet */ - NET_FreePacket(packet); + net_conn_send_packet(&client_connection, packet); - // Acknowledgement has been sent as part of the packet + /* All done! */ - need_to_acknowledge = false; -} - -// Add a new ticcmd to the send queue - -void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic) -{ - net_ticdiff_t diff; - net_server_send_t *sendobj; - int starttic, endtic; - - // Calculate the difference to the last ticcmd + net_free_packet(packet); - NET_TiccmdDiff(&last_ticcmd, ticcmd, &diff); - - // Store in the send queue + /* Acknowledgement has been sent as part of the packet */ - sendobj = &send_queue[maketic % BACKUPTICS]; - sendobj->active = true; - sendobj->seq = maketic; - sendobj->time = I_GetTimeMS(); - sendobj->cmd = diff; - - last_ticcmd = *ticcmd; - - // Send to server. - - starttic = maketic - settings.extratics; - endtic = maketic; - - if (starttic < 0) - starttic = 0; - - NET_Log("client: generated tic %d, sending %d-%d", - maketic, starttic, endtic); - NET_CL_SendTics(starttic, endtic); + need_to_acknowledge = false; } -// Parse a SYN packet received back from the server indicating a successful -// connection attempt. -static void NET_CL_ParseSYN(net_packet_t *packet) +/* Parse a SYN packet received back from the server indicating a successful + * connection attempt. + */ + +static void net_cl_parse_syn(net_packet_t *packet) { - net_protocol_t protocol; - char *server_version; + net_protocol_t protocol; + char *server_version; - NET_Log("client: processing SYN response"); + net_log_info("client: processing SYN response"); - server_version = NET_ReadSafeString(packet); - if (server_version == NULL) + server_version = net_read_safe_string(packet); + if (server_version == NULL) { - NET_Log("client: error: failed to read server version"); - return; + net_log_err("client: failed to read server version"); + return; } - protocol = NET_ReadProtocol(packet); - if (protocol == NET_PROTOCOL_UNKNOWN) + protocol = net_read_protocol(packet); + if (protocol == NET_PROTOCOL_UNKNOWN) { - NET_Log("client: error: can't find a common protocol"); - return; + net_log_err("client: can't find a common protocol"); + return; } - // We are now successfully connected. - NET_Log("client: connected to server"); - client_connection.state = NET_CONN_STATE_CONNECTED; - client_connection.protocol = protocol; + /* We are now successfully connected. */ + + net_log_info("client: connected to server"); + client_connection.state = NET_CONN_STATE_CONNECTED; + client_connection.protocol = protocol; + + /* Even though we have negotiated a compatible protocol, the game may still + * desync. Chocolate Doom's philosophy makes this unlikely, but if we're + * playing with a forked version, or even against a different version that + * fixes a compatibility issue, we may still have problems. + */ - // Even though we have negotiated a compatible protocol, the game may still - // desync. Chocolate Doom's philosophy makes this unlikely, but if we're - // playing with a forked version, or even against a different version that - // fixes a compatibility issue, we may still have problems. - if (strcmp(server_version, PACKAGE_STRING) != 0) + if (strcmp(server_version, PACKAGE_STRING) != 0) { - fprintf(stderr, "NET_CL_ParseSYN: This is '%s', but the server is " - "'%s'. It is possible that this mismatch may cause the game " - "to desync.\n", PACKAGE_STRING, server_version); + fprintf(stderr, + "NET_CL_ParseSYN: This is '%s', but the server is " + "'%s'. It is possible that this mismatch may cause the game " + "to desync.\n", + PACKAGE_STRING, server_version); } } -static void SetRejectReason(const char *s) +static void set_reject_reason(const char *s) { - free(net_client_reject_reason); - if (s != NULL) + free(net_client_reject_reason); + if (s != NULL) { - net_client_reject_reason = strdup(s); + net_client_reject_reason = strdup(s); } - else + else { - net_client_reject_reason = NULL; + net_client_reject_reason = NULL; } } -static void NET_CL_ParseReject(net_packet_t *packet) +static void net_cl_parse_reject(net_packet_t *packet) { - char *msg; + char *msg; - msg = NET_ReadSafeString(packet); - if (msg == NULL) + msg = net_read_safe_string(packet); + if (msg == NULL) { - return; + return; } - if (client_connection.state == NET_CONN_STATE_CONNECTING) + if (client_connection.state == NET_CONN_STATE_CONNECTING) { - client_connection.state = NET_CONN_STATE_DISCONNECTED; - client_connection.disconnect_reason = NET_DISCONNECT_REMOTE; - SetRejectReason(msg); + client_connection.state = NET_CONN_STATE_DISCONNECTED; + client_connection.disconnect_reason = NET_DISCONNECT_REMOTE; + set_reject_reason(msg); } } -// data received while we are waiting for the game to start +/* data received while we are waiting for the game to start */ -static void NET_CL_ParseWaitingData(net_packet_t *packet) +static void net_cl_parse_waiting_data(net_packet_t *packet) { - net_waitdata_t wait_data; + net_waitdata_t wait_data; - if (!NET_ReadWaitData(packet, &wait_data)) + if (!net_read_wait_data(packet, &wait_data)) { - // Invalid packet? - return; + /* Invalid packet? */ + + return; } - if (wait_data.num_players > wait_data.max_players - || wait_data.ready_players > wait_data.num_players - || wait_data.max_players > NET_MAXPLAYERS) + if (wait_data.num_players > wait_data.max_players || + wait_data.ready_players > wait_data.num_players || + wait_data.max_players > CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS) { - // insane data + /* insane data */ - return; + return; } - if ((wait_data.consoleplayer >= 0 && drone) - || (wait_data.consoleplayer < 0 && !drone) - || (wait_data.consoleplayer >= wait_data.num_players)) + if ((wait_data.consoleplayer >= 0 && drone) || + (wait_data.consoleplayer < 0 && !drone) || + (wait_data.consoleplayer >= wait_data.num_players)) { - // Invalid player number + /* Invalid player number */ - return; + return; } - memcpy(&net_client_wait_data, &wait_data, sizeof(net_waitdata_t)); - net_client_received_wait_data = true; + memcpy(&net_client_wait_data, &wait_data, sizeof(net_waitdata_t)); + net_client_received_wait_data = true; } -static void NET_CL_ParseLaunch(net_packet_t *packet) +static void net_cl_parse_launch(net_packet_t *packet) { - unsigned int num_players; + unsigned int num_players; - NET_Log("client: processing launch packet"); + net_log_info("client: processing launch packet"); - if (client_state != CLIENT_STATE_WAITING_LAUNCH) + if (client_state != CLIENT_STATE_WAITING_LAUNCH) { - NET_Log("client: error: not in waiting launch state, client_state=%d", - client_state); - return; + net_log_err("client: not in waiting launch state, client_state=%d", + client_state); + return; } - // The launch packet contains the number of players that will be - // in the game when it starts, so that we can do the startup - // progress indicator (the wait data is unreliable). + /* The launch packet contains the number of players that will be + * in the game when it starts, so that we can do the startup + * progress indicator (the wait data is unreliable). + */ - if (!NET_ReadInt8(packet, &num_players)) + if (!net_read_int8(packet, &num_players)) { - NET_Log("client: error: failed to read number of players"); - return; + net_log_err("client: failed to read number of players"); + return; } - net_client_wait_data.num_players = num_players; - client_state = CLIENT_STATE_WAITING_START; - NET_Log("client: now waiting for game start"); + net_client_wait_data.num_players = num_players; + client_state = CLIENT_STATE_WAITING_START; + net_log_err("client: now waiting for game start"); } -static void NET_CL_ParseGameStart(net_packet_t *packet) +static void net_cl_parse_game_start(net_packet_t *packet) { - NET_Log("client: processing game start packet"); + net_log_info("client: processing game start packet"); - if (!NET_ReadSettings(packet, &settings)) + if (!net_read_settings(packet, &settings)) { - NET_Log("client: error: failed to read settings"); - return; + net_log_err("client: failed to read settings"); + return; } - if (client_state != CLIENT_STATE_WAITING_START) + if (client_state != CLIENT_STATE_WAITING_START) { - NET_Log("client: error: not in waiting start state, client_state=%d", - client_state); - return; + net_log_err("client: not in waiting start state, client_state=%d", + client_state); + return; } - if (settings.num_players > NET_MAXPLAYERS - || settings.consoleplayer >= (signed int) settings.num_players) + if (settings.num_players > CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS || + settings.consoleplayer >= (signed int)settings.num_players) { - // insane values - NET_Log("client: error: bad settings, num_players=%d, consoleplayer=%d", - settings.num_players, settings.consoleplayer); - return; + /* insane values */ + + net_log_err("client: bad settings, num_players=%d, consoleplayer=%d", + settings.num_players, settings.consoleplayer); + return; } - if ((drone && settings.consoleplayer >= 0) - || (!drone && settings.consoleplayer < 0)) + if ((drone && settings.consoleplayer >= 0) || + (!drone && settings.consoleplayer < 0)) { - // Invalid player number: must be positive for real players, - // negative for drones - NET_Log("client: error: mismatch: drone=%d, consoleplayer=%d", - drone, settings.consoleplayer); - return; + /* Invalid player number: must be positive for real players, + * negative for drones + */ + + net_log_err("client: mismatch: drone=%d, consoleplayer=%d", drone, + settings.consoleplayer); + return; } - NET_Log("client: beginning game state"); - client_state = CLIENT_STATE_IN_GAME; + net_log_info("client: beginning game state"); + client_state = CLIENT_STATE_IN_GAME; - // Clear the receive window + /* Clear the receive window */ - memset(recvwindow, 0, sizeof(recvwindow)); - recvwindow_start = 0; - memset(&recvwindow_cmd_base, 0, sizeof(recvwindow_cmd_base)); + memset(recvwindow, 0, sizeof(recvwindow)); + recvwindow_start = 0; + memset(&recvwindow_cmd_base, 0, sizeof(recvwindow_cmd_base)); - // Clear the send queue + /* Clear the send queue */ - memset(&send_queue, 0x00, sizeof(send_queue)); + memset(&send_queue, 0x00, sizeof(send_queue)); } -static void NET_CL_SendResendRequest(int start, int end) +static void net_cl_send_resend_request(int start, int end) { - net_packet_t *packet; - unsigned int nowtime; - int i; + net_packet_t *packet; + unsigned int nowtime; + int i; - //printf("CL: Send resend %i-%i\n", start, end); - - packet = NET_NewPacket(64); - NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); - NET_WriteInt32(packet, start); - NET_WriteInt8(packet, end - start + 1); - NET_Conn_SendPacket(&client_connection, packet); - NET_FreePacket(packet); + packet = net_new_packet(64); + net_write_int16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); + net_write_int32(packet, start); + net_write_int8(packet, end - start + 1); + net_conn_send_packet(&client_connection, packet); + net_free_packet(packet); - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - // Save the time we sent the resend request + /* Save the time we sent the resend request */ - for (i=start; i<=end; ++i) + for (i = start; i <= end; ++i) { - int index; + int index; - index = i - recvwindow_start; + index = i - recvwindow_start; - if (index < 0 || index >= BACKUPTICS) - continue; + if (index < 0 || index >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) continue; - recvwindow[index].resend_time = nowtime; + recvwindow[index].resend_time = nowtime; } } -// Check for expired resend requests +/* Check for expired resend requests */ -static void NET_CL_CheckResends(void) +static void net_cl_check_resends(void) { - int i; - int resend_start, resend_end; - unsigned int nowtime; - boolean maybe_deadlocked; + int i; + int resend_start; + int resend_end; + unsigned int nowtime; + boolean maybe_deadlocked; - nowtime = I_GetTimeMS(); - maybe_deadlocked = nowtime - gamedata_recv_time > 1000; + nowtime = i_get_time_ms(); + maybe_deadlocked = nowtime - gamedata_recv_time > 1000; - resend_start = -1; - resend_end = -1; + resend_start = -1; + resend_end = -1; - for (i=0; iactive - && recvobj->resend_time != 0 - && nowtime > recvobj->resend_time + 300; + need_resend = !recvobj->active && recvobj->resend_time != 0 && + nowtime > recvobj->resend_time + 300; - // if no game data has been received in a long time, we may be in - // a deadlock scenario where tics from the server have been lost, so - // we've stopped generating any more, so the server isn't sending us - // any, so we don't get any to trigger a resend request. So force the - // first few tics in the receive window to be requested. - if (i == 0 && !recvobj->active && recvobj->resend_time == 0 - && maybe_deadlocked) + /* if no game data has been received in a long time, we may be in + * a deadlock scenario where tics from the server have been lost, so + * we've stopped generating any more, so the server isn't sending us + * any, so we don't get any to trigger a resend request. So force the + * first few tics in the receive window to be requested. + */ + + if (i == 0 && !recvobj->active && recvobj->resend_time == 0 && + maybe_deadlocked) { - need_resend = true; + need_resend = true; } - if (need_resend) + if (need_resend) { - // Start a new run of resend tics? + /* Start a new run of resend tics? */ - if (resend_start < 0) + if (resend_start < 0) { - resend_start = i; + resend_start = i; } - resend_end = i; + resend_end = i; } - else if (resend_start >= 0) + else if (resend_start >= 0) { - // End of a run of resend tics - NET_Log("client: resend request timed out for %d-%d (%d)", - recvwindow_start + resend_start, - recvwindow_start + resend_end, - recvwindow[resend_start].resend_time); - NET_CL_SendResendRequest(recvwindow_start + resend_start, + /* End of a run of resend tics */ + + net_log_info("client: resend request timed out for %d-%d (%d)", + recvwindow_start + resend_start, + recvwindow_start + resend_end, + recvwindow[resend_start].resend_time); + net_cl_send_resend_request(recvwindow_start + resend_start, recvwindow_start + resend_end); - resend_start = -1; + resend_start = -1; } } - if (resend_start >= 0) + if (resend_start >= 0) { - NET_Log("client: resend request timed out for %d-%d (%d)", - recvwindow_start + resend_start, - recvwindow_start + resend_end, - recvwindow[resend_start].resend_time); - NET_CL_SendResendRequest(recvwindow_start + resend_start, + net_log_info("client: resend request timed out for %d-%d (%d)", + recvwindow_start + resend_start, + recvwindow_start + resend_end, + recvwindow[resend_start].resend_time); + net_cl_send_resend_request(recvwindow_start + resend_start, recvwindow_start + resend_end); } - // We have received some data from the server and not acknowledged - // it yet. Normally this gets acknowledged when we send our game - // data, but if the client is a drone we need to do this. + /* We have received some data from the server and not acknowledged + * it yet. Normally this gets acknowledged when we send our game + * data, but if the client is a drone we need to do this. + */ - if (need_to_acknowledge && nowtime - gamedata_recv_time > 200) + if (need_to_acknowledge && nowtime - gamedata_recv_time > 200) { - NET_Log("client: no game data received since %d: triggering ack", - gamedata_recv_time); - NET_CL_SendGameDataACK(); + net_log_info("client: no game data received since %d: triggering ack", + gamedata_recv_time); + net_cl_send_game_data_ack(); } } +/* Parsing of NET_PACKET_TYPE_GAMEDATA packets + * (packets containing the actual ticcmd data) + */ -// Parsing of NET_PACKET_TYPE_GAMEDATA packets -// (packets containing the actual ticcmd data) - -static void NET_CL_ParseGameData(net_packet_t *packet) +static void net_cl_parse_game_data(net_packet_t *packet) { - net_server_recv_t *recvobj; - unsigned int seq, num_tics; - unsigned int nowtime; - int resend_start, resend_end; - size_t i; - int index; - - NET_Log("client: processing game data packet"); - - // Read header - if (!NET_ReadInt8(packet, &seq) - || !NET_ReadInt8(packet, &num_tics)) + net_server_recv_t *recvobj; + unsigned int seq; + unsigned int num_tics; + unsigned int nowtime; + int resend_start; + int resend_end; + size_t i; + int index; + + net_log_info("client: processing game data packet"); + + /* Read header */ + + if (!net_read_int8(packet, &seq) || !net_read_int8(packet, &num_tics)) { - NET_Log("client: error: failed to read header"); - return; + net_log_info("client: error: failed to read header"); + return; } - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - // Whatever happens, we now need to send an acknowledgement of our - // current receive point. + /* Whatever happens, we now need to send an acknowledgement of our + * current receive point. + */ - if (!need_to_acknowledge) + if (!need_to_acknowledge) { - need_to_acknowledge = true; - gamedata_recv_time = nowtime; + need_to_acknowledge = true; + gamedata_recv_time = nowtime; } - // Expand byte value into the full tic number - seq = NET_CL_ExpandTicNum(seq); - NET_Log("client: got game data, seq=%d, num_tics=%d", seq, num_tics); + /* Expand byte value into the full tic number */ - for (i=0; i= BACKUPTICS) + if (index < 0 || index >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) { - // Out of range of the recv window + /* Out of range of the recv window */ - continue; + continue; } - // Store in the receive window + /* Store in the receive window */ + + recvobj = &recvwindow[index]; - recvobj = &recvwindow[index]; + recvobj->active = true; + recvobj->cmd = cmd; + net_log_info("client: stored tic %zu in receive window", seq + i); - recvobj->active = true; - recvobj->cmd = cmd; - NET_Log("client: stored tic %d in receive window", seq + i); + /* If a packet is lost or arrives out of order, we might get + * the tic in the next packet instead (because of extratic). + * If that's the case then the latency for receiving that tic + * now will be bogus. So we only use the last tic in the packet + * to trigger a clock sync update. + */ - // If a packet is lost or arrives out of order, we might get - // the tic in the next packet instead (because of extratic). - // If that's the case then the latency for receiving that tic - // now will be bogus. So we only use the last tic in the packet - // to trigger a clock sync update. - if (i == num_tics - 1) + if (i == num_tics - 1) { - UpdateClockSync(seq + i, cmd.latency); + update_clock_sync(seq + i, cmd.latency); } } - // Has this been received out of sequence, ie. have we not received - // all tics before the first tic in this packet? If so, send a - // resend request. + /* Has this been received out of sequence, ie. have we not received + * all tics before the first tic in this packet? If so, send a + * resend request. + */ - //printf("CL: %p: %i\n", client, seq); + resend_end = seq - recvwindow_start; - resend_end = seq - recvwindow_start; + if (resend_end <= 0) return; - if (resend_end <= 0) - return; + if (resend_end >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) + { + resend_end = CONFIG_GAMES_NXDOOM_NET_BACKUPTICS - 1; + } - if (resend_end >= BACKUPTICS) - resend_end = BACKUPTICS - 1; + index = resend_end - 1; + resend_start = resend_end; - index = resend_end - 1; - resend_start = resend_end; - - while (index >= 0) + while (index >= 0) { - recvobj = &recvwindow[index]; + recvobj = &recvwindow[index]; - if (recvobj->active) + if (recvobj->active) { - // ended our run of unreceived tics + /* ended our run of unreceived tics */ - break; + break; } - if (recvobj->resend_time != 0) + if (recvobj->resend_time != 0) { - // Already sent a resend request for this tic + /* Already sent a resend request for this tic */ - break; + break; } - resend_start = index; - --index; + resend_start = index; + --index; } - // Possibly send a resend request - if (resend_start < resend_end) + /* Possibly send a resend request */ + + if (resend_start < resend_end) { - NET_Log("client: request resend for %d-%d before %d", - recvwindow_start + resend_start, - recvwindow_start + resend_end - 1, seq); - NET_CL_SendResendRequest(recvwindow_start + resend_start, + net_log_info("client: request resend for %d-%d before %d", + recvwindow_start + resend_start, + recvwindow_start + resend_end - 1, seq); + net_cl_send_resend_request(recvwindow_start + resend_start, recvwindow_start + resend_end - 1); } } -// Parse a resend request from the server due to a dropped packet +/* Parse a resend request from the server due to a dropped packet */ -static void NET_CL_ParseResendRequest(net_packet_t *packet) +static void net_cl_parse_resend_request(net_packet_t *packet) { - static unsigned int start; - static unsigned int end; - static unsigned int num_tics; + static unsigned int start; + static unsigned int end; + static unsigned int num_tics; - NET_Log("client: processing resend request"); + net_log_info("client: processing resend request"); - if (drone) + if (drone) { - // Drones don't send gamedata. - NET_Log("client: error: resend request but we're a drone?"); - return; + /* Drones don't send gamedata. */ + + net_log_err("client: resend request but we're a drone?"); + return; } - if (!NET_ReadInt32(packet, &start) - || !NET_ReadInt8(packet, &num_tics)) + if (!net_read_int32(packet, &start) || !net_read_int8(packet, &num_tics)) { - NET_Log("client: error: couldn't read start and num_tics"); - return; + net_log_err("client: couldn't read start and num_tics"); + return; } - end = start + num_tics - 1; + end = start + num_tics - 1; - //printf("requested resend %i-%i .. ", start, end); - NET_Log("client: resend request: start=%d, num_tics=%d", start, num_tics); + net_log_info("client: resend request: start=%d, num_tics=%d", start, + num_tics); - // Check we have the tics being requested. If not, reduce the - // window of tics to only what we have. + /* Check we have the tics being requested. If not, reduce the + * window of tics to only what we have. + */ - while (start <= end - && (!send_queue[start % BACKUPTICS].active - || send_queue[start % BACKUPTICS].seq != start)) + while ( + start <= end && + (!send_queue[start % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].active || + send_queue[start % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].seq != start)) { - ++start; + ++start; } - - while (start <= end - && (!send_queue[end % BACKUPTICS].active - || send_queue[end % BACKUPTICS].seq != end)) + + while (start <= end && + (!send_queue[end % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].active || + send_queue[end % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS].seq != end)) { - --end; + --end; } - // Resend those tics - if (start <= end) + /* Resend those tics */ + + if (start <= end) { - NET_Log("client: resending %d-%d", start, end); - NET_CL_SendTics(start, end); + net_log_info("client: resending %d-%d", start, end); + net_cl_send_tics(start, end); } - else + else { - NET_Log("client: don't have the tics to resend"); + net_log_info("client: don't have the tics to resend"); } } -// Console message that the server wants the client to print +/* Console message that the server wants the client to print */ -static void NET_CL_ParseConsoleMessage(net_packet_t *packet) +static void net_cl_parse_console_message(net_packet_t *packet) { - char *msg; + char *msg; - msg = NET_ReadSafeString(packet); + msg = net_read_safe_string(packet); - if (msg == NULL) + if (msg == NULL) { - return; + return; } - printf("Message from server:\n%s\n", msg); + printf("Message from server:\n%s\n", msg); } -// parse a received packet +/* parse a received packet */ -static void NET_CL_ParsePacket(net_packet_t *packet) +static void net_cl_parse_packet(net_packet_t *packet) { - unsigned int packet_type; + unsigned int packet_type; - if (!NET_ReadInt16(packet, &packet_type)) + if (!net_read_int16(packet, &packet_type)) { - return; + return; } - NET_Log("client: packet from server, type %d", - packet_type & ~NET_RELIABLE_PACKET); - NET_LogPacket(packet); + net_log_info("client: packet from server, type %d", + packet_type & ~NET_RELIABLE_PACKET); + net_log_packet(packet); - if (NET_Conn_Packet(&client_connection, packet, &packet_type)) + if (net_conn_packet(&client_connection, packet, &packet_type)) { - // Packet eaten by the common connection code + /* Packet eaten by the common connection code */ } - else + else { - switch (packet_type) + switch (packet_type) { - case NET_PACKET_TYPE_SYN: - NET_CL_ParseSYN(packet); - break; + case NET_PACKET_TYPE_SYN: + net_cl_parse_syn(packet); + break; - case NET_PACKET_TYPE_REJECTED: - NET_CL_ParseReject(packet); - break; + case NET_PACKET_TYPE_REJECTED: + net_cl_parse_reject(packet); + break; - case NET_PACKET_TYPE_WAITING_DATA: - NET_CL_ParseWaitingData(packet); - break; + case NET_PACKET_TYPE_WAITING_DATA: + net_cl_parse_waiting_data(packet); + break; - case NET_PACKET_TYPE_LAUNCH: - NET_CL_ParseLaunch(packet); - break; + case NET_PACKET_TYPE_LAUNCH: + net_cl_parse_launch(packet); + break; - case NET_PACKET_TYPE_GAMESTART: - NET_CL_ParseGameStart(packet); - break; + case NET_PACKET_TYPE_GAMESTART: + net_cl_parse_game_start(packet); + break; - case NET_PACKET_TYPE_GAMEDATA: - NET_CL_ParseGameData(packet); - break; + case NET_PACKET_TYPE_GAMEDATA: + net_cl_parse_game_data(packet); + break; - case NET_PACKET_TYPE_GAMEDATA_RESEND: - NET_CL_ParseResendRequest(packet); - break; + case NET_PACKET_TYPE_GAMEDATA_RESEND: + net_cl_parse_resend_request(packet); + break; - case NET_PACKET_TYPE_CONSOLE_MESSAGE: - NET_CL_ParseConsoleMessage(packet); - break; + case NET_PACKET_TYPE_CONSOLE_MESSAGE: + net_cl_parse_console_message(packet); + break; - default: - break; + default: + break; } } } -// "Run" the client code: check for new packets, send packets as -// needed +static void net_cl_send_syn(net_connect_data_t *data) +{ + net_packet_t *packet; + + net_log_info("client: sending SYN"); + + packet = net_new_packet(10); + net_write_int16(packet, NET_PACKET_TYPE_SYN); + net_write_int32(packet, NET_MAGIC_NUMBER); + net_write_string(packet, PACKAGE_STRING); + net_write_protocol_list(packet); + net_write_connect_data(packet, data); + net_write_string(packet, net_player_name); + net_conn_send_packet(&client_connection, packet); + net_free_packet(packet); +} + +static void net_cl_init(void) +{ + /* Try to set from the USER and USERNAME environment variables + * Otherwise, fallback to "Player" + */ + + if (net_player_name == NULL) + { + net_player_name = "Player"; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void net_cl_launch_game(void) +{ + net_conn_new_reliable(&client_connection, NET_PACKET_TYPE_LAUNCH); +} + +void net_cl_start_game(net_gamesettings_t *p_settings) +{ + net_packet_t *packet; + + /* Start from a ticcmd of all zeros */ + + memset(&last_ticcmd, 0, sizeof(ticcmd_t)); + + /* Send packet */ + + packet = + net_conn_new_reliable(&client_connection, NET_PACKET_TYPE_GAMESTART); + + net_write_settings(packet, p_settings); +} + +/* Add a new ticcmd to the send queue */ + +void net_cl_send_ticcmd(ticcmd_t *ticcmd, int maketic) +{ + net_ticdiff_t diff; + net_server_send_t *sendobj; + int starttic; + int endtic; + + /* Calculate the difference to the last ticcmd */ + + net_ticcmd_diff(&last_ticcmd, ticcmd, &diff); + + /* Store in the send queue */ + + sendobj = &send_queue[maketic % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; + sendobj->active = true; + sendobj->seq = maketic; + sendobj->time = i_get_time_ms(); + sendobj->cmd = diff; + + last_ticcmd = *ticcmd; + + /* Send to server. */ + + starttic = maketic - settings.extratics; + endtic = maketic; + + if (starttic < 0) starttic = 0; + + net_log_info("client: generated tic %d, sending %d-%d", maketic, starttic, + endtic); + net_cl_send_tics(starttic, endtic); +} + +/* "Run" the client code: check for new packets, send packets as + * needed + */ -void NET_CL_Run(void) +void net_cl_run(void) { - net_addr_t *addr; - net_packet_t *packet; - - if (!net_client_connected) + net_addr_t *addr; + net_packet_t *packet; + + if (!net_client_connected) { - return; + return; } - - while (NET_RecvPacket(client_context, &addr, &packet)) + + while (net_recv_packet(client_context, &addr, &packet)) { - // only accept packets from the server + /* only accept packets from the server */ - if (addr == server_addr) + if (addr == server_addr) { - NET_CL_ParsePacket(packet); + net_cl_parse_packet(packet); } - NET_FreePacket(packet); - NET_ReleaseAddress(addr); + net_free_packet(packet); + net_release_address(addr); } - // Run the common connection code to send any packets as needed + /* Run the common connection code to send any packets as needed */ - NET_Conn_Run(&client_connection); + net_conn_run(&client_connection); - if (client_connection.state == NET_CONN_STATE_DISCONNECTED - || client_connection.state == NET_CONN_STATE_DISCONNECTED_SLEEP) + if (client_connection.state == NET_CONN_STATE_DISCONNECTED || + client_connection.state == NET_CONN_STATE_DISCONNECTED_SLEEP) { - NET_CL_Disconnected(); + net_cl_disconnected(); - NET_CL_Shutdown(); + net_cl_shutdown(); } - net_waiting_for_launch = - client_connection.state == NET_CONN_STATE_CONNECTED - && client_state == CLIENT_STATE_WAITING_LAUNCH; + net_waiting_for_launch = + client_connection.state == NET_CONN_STATE_CONNECTED && + client_state == CLIENT_STATE_WAITING_LAUNCH; - if (client_state == CLIENT_STATE_IN_GAME) + if (client_state == CLIENT_STATE_IN_GAME) { - // Possibly advance the receive window + /* Possibly advance the receive window */ - NET_CL_AdvanceWindow(); + net_cl_advance_window(); - // Check if our resend requests have timed out + /* Check if our resend requests have timed out */ - NET_CL_CheckResends(); + net_cl_check_resends(); } } -static void NET_CL_SendSYN(net_connect_data_t *data) -{ - net_packet_t *packet; - - NET_Log("client: sending SYN"); - - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_PACKET_TYPE_SYN); - NET_WriteInt32(packet, NET_MAGIC_NUMBER); - NET_WriteString(packet, PACKAGE_STRING); - NET_WriteProtocolList(packet); - NET_WriteConnectData(packet, data); - NET_WriteString(packet, net_player_name); - NET_Conn_SendPacket(&client_connection, packet); - NET_FreePacket(packet); -} +/* Connect to a server */ -// Connect to a server -boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data) +boolean net_cl_connect(net_addr_t *addr, net_connect_data_t *data) { - int start_time; - int last_send_time; - boolean sent_hole_punch; + int start_time; + int last_send_time; + boolean sent_hole_punch; + + server_addr = addr; + net_reference_address(addr); - server_addr = addr; - NET_ReferenceAddress(addr); + memcpy(net_local_wad_sha1sum, data->wad_sha1sum, sizeof(sha1_digest_t)); + memcpy(net_local_deh_sha1sum, data->deh_sha1sum, sizeof(sha1_digest_t)); + net_local_is_freedoom = data->is_freedoom; - memcpy(net_local_wad_sha1sum, data->wad_sha1sum, sizeof(sha1_digest_t)); - memcpy(net_local_deh_sha1sum, data->deh_sha1sum, sizeof(sha1_digest_t)); - net_local_is_freedoom = data->is_freedoom; + /* create a new network I/O context and add just the necessary module */ - // create a new network I/O context and add just the necessary module - client_context = NET_NewContext(); + client_context = net_new_context(); - // initialize module for client mode - if (!addr->module->InitClient()) + /* initialize module for client mode */ + + if (!addr->module->init_client()) { - SetRejectReason("Failed to initialize client module"); - return false; + set_reject_reason("Failed to initialize client module"); + return false; } - NET_AddModule(client_context, addr->module); + net_add_module(client_context, addr->module); + + net_client_connected = true; + net_client_received_wait_data = false; + sent_hole_punch = false; - net_client_connected = true; - net_client_received_wait_data = false; - sent_hole_punch = false; + net_conn_init_client(&client_connection, addr, NET_PROTOCOL_UNKNOWN); - NET_Conn_InitClient(&client_connection, addr, NET_PROTOCOL_UNKNOWN); + /* try to connect */ - // try to connect - start_time = I_GetTimeMS(); - last_send_time = -1; - SetRejectReason("Unknown reason"); + start_time = i_get_time_ms(); + last_send_time = -1; + set_reject_reason("Unknown reason"); - while (client_connection.state == NET_CONN_STATE_CONNECTING) + while (client_connection.state == NET_CONN_STATE_CONNECTING) { - int nowtime = I_GetTimeMS(); + int nowtime = i_get_time_ms(); - // Send a SYN packet every second. - if (nowtime - last_send_time > 1000 || last_send_time < 0) + /* Send a SYN packet every second. */ + + if (nowtime - last_send_time > 1000 || last_send_time < 0) { - NET_CL_SendSYN(data); - last_send_time = nowtime; + net_cl_send_syn(data); + last_send_time = nowtime; } - // time out after 5 seconds - if (nowtime - start_time > 5000) + /* time out after 5 seconds */ + + if (nowtime - start_time > 5000) { - SetRejectReason("No response from server"); - break; + set_reject_reason("No response from server"); + break; } - if (!sent_hole_punch && nowtime - start_time > 2000) + if (!sent_hole_punch && nowtime - start_time > 2000) { - NET_Log("client: no response to SYN, requesting hole punch"); - NET_RequestHolePunch(client_context, addr); - sent_hole_punch = true; + net_log_warn("client: no response to SYN, requesting hole punch"); + net_request_hole_punch(client_context, addr); + sent_hole_punch = true; } - // run client code - NET_CL_Run(); + /* run client code */ + + net_cl_run(); + + /* run the server, just in case we are doing a loopback connect */ - // run the server, just in case we are doing a loopback connect - NET_SV_Run(); + net_sv_run(); - // Don't hog the CPU - I_Sleep(1); + /* Don't hog the CPU */ + + usleep(1000); } - if (client_connection.state == NET_CONN_STATE_CONNECTED) + if (client_connection.state == NET_CONN_STATE_CONNECTED) { - // connected ok! - NET_Log("client: connected successfully"); - SetRejectReason(NULL); - client_state = CLIENT_STATE_WAITING_LAUNCH; - drone = data->drone; + /* connected ok! */ + + net_log_info("client: connected successfully"); + set_reject_reason(NULL); + client_state = CLIENT_STATE_WAITING_LAUNCH; + drone = data->drone; - return true; + return true; } - else + else { - // failed to connect - NET_Log("client: failed to connect"); - NET_CL_Shutdown(); + /* failed to connect */ - return false; + net_log_err("client: failed to connect"); + net_cl_shutdown(); + + return false; } } -// read game settings received from server +/* read game settings received from server */ -boolean NET_CL_GetSettings(net_gamesettings_t *_settings) +boolean net_cl_get_settings(net_gamesettings_t *_settings) { - if (client_state != CLIENT_STATE_IN_GAME) + if (client_state != CLIENT_STATE_IN_GAME) { - return false; + return false; } - memcpy(_settings, &settings, sizeof(net_gamesettings_t)); + memcpy(_settings, &settings, sizeof(net_gamesettings_t)); - return true; + return true; } -// disconnect from the server +/* disconnect from the server */ -void NET_CL_Disconnect(void) +void net_cl_disconnect(void) { - int start_time; + int start_time; - if (!net_client_connected) + if (!net_client_connected) { - return; + return; } - NET_Log("client: beginning disconnect"); - NET_Conn_Disconnect(&client_connection); + net_log_info("client: beginning disconnect"); + net_conn_disconnect(&client_connection); - start_time = I_GetTimeMS(); + start_time = i_get_time_ms(); - while (client_connection.state != NET_CONN_STATE_DISCONNECTED - && client_connection.state != NET_CONN_STATE_DISCONNECTED_SLEEP) + while (client_connection.state != NET_CONN_STATE_DISCONNECTED && + client_connection.state != NET_CONN_STATE_DISCONNECTED_SLEEP) { - if (I_GetTimeMS() - start_time > 5000) + if (i_get_time_ms() - start_time > 5000) { - // time out after 5 seconds + /* time out after 5 seconds */ - NET_Log("client: no acknowledgement of disconnect received"); - client_state = CLIENT_STATE_WAITING_START; + net_log_err("client: no acknowledgement of disconnect received"); + client_state = CLIENT_STATE_WAITING_START; - fprintf(stderr, "NET_CL_Disconnect: Timeout while disconnecting " - "from server\n"); - break; + fprintf(stderr, "net_cl_disconnect: Timeout while disconnecting " + "from server\n"); + break; } - NET_CL_Run(); - NET_SV_Run(); + net_cl_run(); + net_sv_run(); - I_Sleep(1); + usleep(1000); } - // Finished sending disconnect packets, etc. - NET_Log("client: disconnect complete"); - NET_CL_Shutdown(); -} - -void NET_CL_Init(void) -{ - // Try to set from the USER and USERNAME environment variables - // Otherwise, fallback to "Player" + /* Finished sending disconnect packets, etc. */ - if (net_player_name == NULL) - { - net_player_name = NET_GetRandomPetName(); - } + net_log_info("client: disconnect complete"); + net_cl_shutdown(); } -void NET_Init(void) +void net_init(void) { - NET_OpenLog(); - NET_CL_Init(); + net_cl_init(); } -void NET_BindVariables(void) +void net_bind_variables(void) { - M_BindStringVariable("player_name", &net_player_name); + m_bind_string_variable("player_name", &net_player_name); } diff --git a/games/NXDoom/src/net_client.h b/games/NXDoom/src/net_client.h index 37ba01984e4..abe3d1b8256 100644 --- a/games/NXDoom/src/net_client.h +++ b/games/NXDoom/src/net_client.h @@ -1,38 +1,39 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Network client code -// +/**************************************************************************** + * apps/games/NXDoom/src/net_client.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Network client code + * + ****************************************************************************/ #ifndef NET_CLIENT_H #define NET_CLIENT_H -#include "doomtype.h" +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_ticcmd.h" -#include "sha1.h" +#include "doomtype.h" #include "net_defs.h" +#include "sha1.h" -boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data); -void NET_CL_Disconnect(void); -void NET_CL_Run(void); -void NET_CL_Init(void); -void NET_CL_LaunchGame(void); -void NET_CL_StartGame(net_gamesettings_t *settings); -void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic); -boolean NET_CL_GetSettings(net_gamesettings_t *_settings); -void NET_Init(void); - -void NET_BindVariables(void); +/**************************************************************************** + * Public Data + ****************************************************************************/ extern boolean net_client_connected; extern boolean net_client_received_wait_data; @@ -50,4 +51,19 @@ extern unsigned int net_local_is_freedoom; extern boolean drone; -#endif /* #ifndef NET_CLIENT_H */ +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +boolean net_cl_connect(net_addr_t *addr, net_connect_data_t *data); +void net_cl_disconnect(void); +void net_cl_run(void); +void net_cl_launch_game(void); +void net_cl_start_game(net_gamesettings_t *settings); +void net_cl_send_ticcmd(ticcmd_t *ticcmd, int maketic); +boolean net_cl_get_settings(net_gamesettings_t *_settings); +void net_init(void); + +void net_bind_variables(void); + +#endif /* NET_CLIENT_H */ diff --git a/games/NXDoom/src/net_common.c b/games/NXDoom/src/net_common.c index 99b32c25608..62dac01ca6d 100644 --- a/games/NXDoom/src/net_common.c +++ b/games/NXDoom/src/net_common.c @@ -1,26 +1,35 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Common code shared between the client and server -// +/**************************************************************************** + * apps/games/NXDoom/src/net_common.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Common code shared between the client and server + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include -#include #include -#include "doomtype.h" #include "d_mode.h" +#include "doomtype.h" #include "i_system.h" #include "i_timer.h" #include "m_argv.h" @@ -31,497 +40,493 @@ #include "net_packet.h" #include "net_structrw.h" -// connections time out after 30 seconds +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* connections time out after 30 seconds */ #define CONNECTION_TIMEOUT_LEN 30 -// maximum time between sending packets +/* maximum time between sending packets */ #define KEEPALIVE_PERIOD 1 -// reliable packet that is guaranteed to reach its destination +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* reliable packet that is guaranteed to reach its destination */ struct net_reliable_packet_s { - net_packet_t *packet; - int last_send_time; - int seq; - net_reliable_packet_t *next; + net_packet_t *packet; + int last_send_time; + int seq; + net_reliable_packet_t *next; }; -static FILE *net_debug = NULL; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static void NET_Conn_Init(net_connection_t *conn, net_addr_t *addr, +static void net_conn_init(net_connection_t *conn, net_addr_t *addr, net_protocol_t protocol) { - conn->last_send_time = -1; - conn->num_retries = 0; - conn->addr = addr; - conn->protocol = protocol; - conn->reliable_packets = NULL; - conn->reliable_send_seq = 0; - conn->reliable_recv_seq = 0; - conn->keepalive_recv_time = I_GetTimeMS(); + conn->last_send_time = -1; + conn->num_retries = 0; + conn->addr = addr; + conn->protocol = protocol; + conn->reliable_packets = NULL; + conn->reliable_send_seq = 0; + conn->reliable_recv_seq = 0; + conn->keepalive_recv_time = i_get_time_ms(); } -// Initialize as a client connection - -void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr, - net_protocol_t protocol) +static void net_conn_parse_disconnect(net_connection_t *conn, + net_packet_t *packet) { - NET_Conn_Init(conn, addr, protocol); - conn->state = NET_CONN_STATE_CONNECTING; -} + net_packet_t *reply; -// Initialize as a server connection + /* Other end wants to disconnect + * Send a DISCONNECT_ACK reply. + */ -void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr, - net_protocol_t protocol) -{ - NET_Conn_Init(conn, addr, protocol); - conn->state = NET_CONN_STATE_CONNECTED; -} + reply = net_new_packet(10); + net_write_int16(reply, NET_PACKET_TYPE_DISCONNECT_ACK); + net_conn_send_packet(conn, reply); + net_free_packet(reply); -// Send a packet to a connection -// All packets should be sent through this interface, as it maintains the -// keepalive_send_time counter. + conn->last_send_time = i_get_time_ms(); -void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet) -{ - conn->keepalive_send_time = I_GetTimeMS(); - NET_SendPacket(conn->addr, packet); + conn->state = NET_CONN_STATE_DISCONNECTED_SLEEP; + conn->disconnect_reason = NET_DISCONNECT_REMOTE; } -static void NET_Conn_ParseDisconnect(net_connection_t *conn, net_packet_t *packet) -{ - net_packet_t *reply; - - // Other end wants to disconnect - // Send a DISCONNECT_ACK reply. - - reply = NET_NewPacket(10); - NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK); - NET_Conn_SendPacket(conn, reply); - NET_FreePacket(reply); - - conn->last_send_time = I_GetTimeMS(); - - conn->state = NET_CONN_STATE_DISCONNECTED_SLEEP; - conn->disconnect_reason = NET_DISCONNECT_REMOTE; -} - -// Parse a DISCONNECT_ACK packet +/* Parse a DISCONNECT_ACK packet */ -static void NET_Conn_ParseDisconnectACK(net_connection_t *conn, - net_packet_t *packet) +static void net_conn_parse_disconnect_ack(net_connection_t *conn, + net_packet_t *packet) { - - if (conn->state == NET_CONN_STATE_DISCONNECTING) + if (conn->state == NET_CONN_STATE_DISCONNECTING) { - // We have received an acknowledgement to our disconnect - // request. We have been disconnected successfully. - - conn->state = NET_CONN_STATE_DISCONNECTED; - conn->disconnect_reason = NET_DISCONNECT_LOCAL; - conn->last_send_time = -1; + /* We have received an acknowledgement to our disconnect + * request. We have been disconnected successfully. + */ + + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_LOCAL; + conn->last_send_time = -1; } } -static void NET_Conn_ParseReliableACK(net_connection_t *conn, net_packet_t *packet) +static void net_conn_parse_reliable_ack(net_connection_t *conn, + net_packet_t *packet) { - unsigned int seq; + unsigned int seq; - if (!NET_ReadInt8(packet, &seq)) + if (!net_read_int8(packet, &seq)) { - return; + return; } - if (conn->reliable_packets == NULL) + if (conn->reliable_packets == NULL) { - return; + return; } - - // Is this an acknowledgement for the first packet in the list? - if (seq == (unsigned int)((conn->reliable_packets->seq + 1) & 0xff)) + /* Is this an acknowledgement for the first packet in the list? */ + + if (seq == (unsigned int)((conn->reliable_packets->seq + 1) & 0xff)) { - net_reliable_packet_t *rp; + net_reliable_packet_t *rp; - // Discard it, then. - // Unlink from the list. + /* Discard it, then. + * Unlink from the list. + */ - rp = conn->reliable_packets; - conn->reliable_packets = rp->next; - - NET_FreePacket(rp->packet); - free(rp); + rp = conn->reliable_packets; + conn->reliable_packets = rp->next; + + net_free_packet(rp->packet); + free(rp); } } -// Process the header of a reliable packet -// -// Returns true if the packet should be discarded (incorrect sequence) +/* Process the header of a reliable packet + * + * Returns true if the packet should be discarded (incorrect sequence) + */ -static boolean NET_Conn_ReliablePacket(net_connection_t *conn, - net_packet_t *packet) +static boolean net_connect_reliable_packet(net_connection_t *conn, + net_packet_t *packet) { - unsigned int seq; - net_packet_t *reply; - boolean result; + unsigned int seq; + net_packet_t *reply; + boolean result; - // Read the sequence number + /* Read the sequence number */ - if (!NET_ReadInt8(packet, &seq)) + if (!net_read_int8(packet, &seq)) { - return true; + return true; } - if (seq != (unsigned int)(conn->reliable_recv_seq & 0xff)) + if (seq != (unsigned int)(conn->reliable_recv_seq & 0xff)) { - // This is not the next expected packet in the sequence! - // - // Discard the packet. If we were smart, we would use a proper - // sliding window protocol to do this, but I'm lazy. + /* This is not the next expected packet in the sequence! + * + * Discard the packet. If we were smart, we would use a proper + * sliding window protocol to do this, but I'm lazy. + */ - result = true; + result = true; } - else + else { - // Now we can receive the next packet in the sequence. + /* Now we can receive the next packet in the sequence. */ + + conn->reliable_recv_seq = (conn->reliable_recv_seq + 1) & 0xff; - conn->reliable_recv_seq = (conn->reliable_recv_seq + 1) & 0xff; - - result = false; + result = false; } - // Send an acknowledgement + /* Send an acknowledgement */ - // Note: this is braindead. It would be much more sensible to - // include this in the next packet, rather than the overhead of - // sending a complete packet just for one byte of information. + /* Note: this is braindead. It would be much more sensible to + * include this in the next packet, rather than the overhead of + * sending a complete packet just for one byte of information. + */ - reply = NET_NewPacket(10); + reply = net_new_packet(10); - NET_WriteInt16(reply, NET_PACKET_TYPE_RELIABLE_ACK); - NET_WriteInt8(reply, conn->reliable_recv_seq & 0xff); + net_write_int16(reply, NET_PACKET_TYPE_RELIABLE_ACK); + net_write_int8(reply, conn->reliable_recv_seq & 0xff); + + net_conn_send_packet(conn, reply); + + net_free_packet(reply); + + return result; +} - NET_Conn_SendPacket(conn, reply); +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Initialize as a client connection */ + +void net_conn_init_client(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol) +{ + net_conn_init(conn, addr, protocol); + conn->state = NET_CONN_STATE_CONNECTING; +} + +/* Initialize as a server connection */ + +void net_conn_init_server(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol) +{ + net_conn_init(conn, addr, protocol); + conn->state = NET_CONN_STATE_CONNECTED; +} - NET_FreePacket(reply); +/* Send a packet to a connection + * All packets should be sent through this interface, as it maintains the + * keepalive_send_time counter. + */ - return result; +void net_conn_send_packet(net_connection_t *conn, net_packet_t *packet) +{ + conn->keepalive_send_time = i_get_time_ms(); + net_send_packet(conn->addr, packet); } -// Process a packet received by the server -// -// Returns true if eaten by common code +/* Process a packet received by the server + * + * Returns true if eaten by common code + */ -boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet, +boolean net_conn_packet(net_connection_t *conn, net_packet_t *packet, unsigned int *packet_type) { - conn->keepalive_recv_time = I_GetTimeMS(); + conn->keepalive_recv_time = i_get_time_ms(); - // Is this a reliable packet? + /* Is this a reliable packet? */ - if (*packet_type & NET_RELIABLE_PACKET) + if (*packet_type & NET_RELIABLE_PACKET) { - if (NET_Conn_ReliablePacket(conn, packet)) + if (net_connect_reliable_packet(conn, packet)) { - // Invalid packet: eat it. + /* Invalid packet: eat it. */ - return true; + return true; } - // Remove the reliable bit + /* Remove the reliable bit */ - *packet_type &= ~NET_RELIABLE_PACKET; + *packet_type &= ~NET_RELIABLE_PACKET; } - - switch (*packet_type) + + switch (*packet_type) { - case NET_PACKET_TYPE_DISCONNECT: - NET_Conn_ParseDisconnect(conn, packet); - break; - case NET_PACKET_TYPE_DISCONNECT_ACK: - NET_Conn_ParseDisconnectACK(conn, packet); - break; - case NET_PACKET_TYPE_KEEPALIVE: - // No special action needed. - break; - case NET_PACKET_TYPE_RELIABLE_ACK: - NET_Conn_ParseReliableACK(conn, packet); - break; - default: - // Not a common packet - - return false; + case NET_PACKET_TYPE_DISCONNECT: + net_conn_parse_disconnect(conn, packet); + break; + case NET_PACKET_TYPE_DISCONNECT_ACK: + net_conn_parse_disconnect_ack(conn, packet); + break; + case NET_PACKET_TYPE_KEEPALIVE: + break; /* No special action needed. */ + case NET_PACKET_TYPE_RELIABLE_ACK: + net_conn_parse_reliable_ack(conn, packet); + break; + default: + return false; /* Not a common packet */ } - // We found a packet that we found interesting, and ate it. + /* We found a packet that we found interesting, and ate it. */ - return true; + return true; } -void NET_Conn_Disconnect(net_connection_t *conn) +void net_conn_disconnect(net_connection_t *conn) { - if (conn->state != NET_CONN_STATE_DISCONNECTED - && conn->state != NET_CONN_STATE_DISCONNECTING - && conn->state != NET_CONN_STATE_DISCONNECTED_SLEEP) + if (conn->state != NET_CONN_STATE_DISCONNECTED && + conn->state != NET_CONN_STATE_DISCONNECTING && + conn->state != NET_CONN_STATE_DISCONNECTED_SLEEP) { - conn->state = NET_CONN_STATE_DISCONNECTING; - conn->disconnect_reason = NET_DISCONNECT_LOCAL; - conn->last_send_time = -1; - conn->num_retries = 0; + conn->state = NET_CONN_STATE_DISCONNECTING; + conn->disconnect_reason = NET_DISCONNECT_LOCAL; + conn->last_send_time = -1; + conn->num_retries = 0; } } -void NET_Conn_Run(net_connection_t *conn) +void net_conn_run(net_connection_t *conn) { - net_packet_t *packet; - unsigned int nowtime; + net_packet_t *packet; + unsigned int nowtime; - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - if (conn->state == NET_CONN_STATE_CONNECTED) + if (conn->state == NET_CONN_STATE_CONNECTED) { - // Check the keepalive counters + /* Check the keepalive counters */ - if (nowtime - conn->keepalive_recv_time > CONNECTION_TIMEOUT_LEN * 1000) + if (nowtime - conn->keepalive_recv_time > + CONNECTION_TIMEOUT_LEN * 1000) { - // Haven't received any packets from the other end in a long - // time. Assume disconnected. + /* Haven't received any packets from the other end in a long + * time. Assume disconnected. + */ - conn->state = NET_CONN_STATE_DISCONNECTED; - conn->disconnect_reason = NET_DISCONNECT_TIMEOUT; + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_TIMEOUT; } - - if (nowtime - conn->keepalive_send_time > KEEPALIVE_PERIOD * 1000) - { - // We have not sent anything in a long time. - // Send a keepalive. - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_PACKET_TYPE_KEEPALIVE); - NET_Conn_SendPacket(conn, packet); - NET_FreePacket(packet); + if (nowtime - conn->keepalive_send_time > KEEPALIVE_PERIOD * 1000) + { + /* We have not sent anything in a long time. + * Send a keepalive. + */ + + packet = net_new_packet(10); + net_write_int16(packet, NET_PACKET_TYPE_KEEPALIVE); + net_conn_send_packet(conn, packet); + net_free_packet(packet); } - // Check the reliable packet list. Has the first packet in the - // list timed out? - // - // NB. This is braindead, we have a fixed time of one second. + /* Check the reliable packet list. Has the first packet in the + * list timed out? + * + * NB. This is braindead, we have a fixed time of one second. + */ - if (conn->reliable_packets != NULL - && (conn->reliable_packets->last_send_time < 0 - || nowtime - conn->reliable_packets->last_send_time > 1000)) + if (conn->reliable_packets != NULL && + (conn->reliable_packets->last_send_time < 0 || + nowtime - conn->reliable_packets->last_send_time > 1000)) { - // Packet timed out, time to resend + /* Packet timed out, time to resend */ - NET_Conn_SendPacket(conn, conn->reliable_packets->packet); - conn->reliable_packets->last_send_time = nowtime; + net_conn_send_packet(conn, conn->reliable_packets->packet); + conn->reliable_packets->last_send_time = nowtime; } } - else if (conn->state == NET_CONN_STATE_DISCONNECTING) + else if (conn->state == NET_CONN_STATE_DISCONNECTING) { - // Waiting for a reply to our DISCONNECT request. + /* Waiting for a reply to our DISCONNECT request. */ - if (conn->last_send_time < 0 - || nowtime - conn->last_send_time > 1000) + if (conn->last_send_time < 0 || nowtime - conn->last_send_time > 1000) { - // it has been a second since the last disconnect packet - // was sent, and still no reply. + /* it has been a second since the last disconnect packet + * was sent, and still no reply. + */ - if (conn->num_retries < MAX_RETRIES) + if (conn->num_retries < MAX_RETRIES) { - // send another disconnect + /* send another disconnect */ - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT); - NET_Conn_SendPacket(conn, packet); - NET_FreePacket(packet); - conn->last_send_time = nowtime; + packet = net_new_packet(10); + net_write_int16(packet, NET_PACKET_TYPE_DISCONNECT); + net_conn_send_packet(conn, packet); + net_free_packet(packet); + conn->last_send_time = nowtime; - ++conn->num_retries; + ++conn->num_retries; } - else + else { - // No more retries allowed. - // Force disconnect. + /* No more retries allowed. Force disconnect. */ - conn->state = NET_CONN_STATE_DISCONNECTED; - conn->disconnect_reason = NET_DISCONNECT_LOCAL; + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_LOCAL; } } } - else if (conn->state == NET_CONN_STATE_DISCONNECTED_SLEEP) + else if (conn->state == NET_CONN_STATE_DISCONNECTED_SLEEP) { - // We are disconnected, waiting in case we need to send - // a DISCONNECT_ACK to the server again. + /* We are disconnected, waiting in case we need to send + * a DISCONNECT_ACK to the server again. + */ - if (nowtime - conn->last_send_time > 5000) + if (nowtime - conn->last_send_time > 5000) { - // Idle for 5 seconds, switch state + /* Idle for 5 seconds, switch state */ - conn->state = NET_CONN_STATE_DISCONNECTED; - conn->disconnect_reason = NET_DISCONNECT_REMOTE; + conn->state = NET_CONN_STATE_DISCONNECTED; + conn->disconnect_reason = NET_DISCONNECT_REMOTE; } } } -net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type) +net_packet_t *net_conn_new_reliable(net_connection_t *conn, int packet_type) { - net_packet_t *packet; - net_reliable_packet_t *rp; - net_reliable_packet_t **listend; - - // Generate a packet with the right header - - packet = NET_NewPacket(100); - - NET_WriteInt16(packet, packet_type | NET_RELIABLE_PACKET); + net_packet_t *packet; + net_reliable_packet_t *rp; + net_reliable_packet_t **listend; - // write the low byte of the send sequence number - - NET_WriteInt8(packet, conn->reliable_send_seq & 0xff); + /* Generate a packet with the right header */ - // Add to the list of reliable packets + packet = net_new_packet(100); - rp = malloc(sizeof(net_reliable_packet_t)); - rp->packet = packet; - rp->next = NULL; - rp->seq = conn->reliable_send_seq; - rp->last_send_time = -1; + net_write_int16(packet, packet_type | NET_RELIABLE_PACKET); - for (listend = &conn->reliable_packets; - *listend != NULL; - listend = &((*listend)->next)); + /* write the low byte of the send sequence number */ - *listend = rp; + net_write_int8(packet, conn->reliable_send_seq & 0xff); - // Count along the sequence + /* Add to the list of reliable packets */ - conn->reliable_send_seq = (conn->reliable_send_seq + 1) & 0xff; + rp = malloc(sizeof(net_reliable_packet_t)); + rp->packet = packet; + rp->next = NULL; + rp->seq = conn->reliable_send_seq; + rp->last_send_time = -1; - // Finished - - return packet; -} + for (listend = &conn->reliable_packets; *listend != NULL; + listend = &((*listend)->next)) + ; -// Used to expand the least significant byte of a tic number into -// the full tic number, from the current tic number + *listend = rp; -unsigned int NET_ExpandTicNum(unsigned int relative, unsigned int b) -{ - unsigned int l, h; - unsigned int result; + /* Count along the sequence */ - h = relative & ~0xff; - l = relative & 0xff; + conn->reliable_send_seq = (conn->reliable_send_seq + 1) & 0xff; - result = h | b; + /* Finished */ - if (l < 0x40 && b > 0xb0) - result -= 0x100; - if (l > 0xb0 && b < 0x40) - result += 0x100; - - return result; + return packet; } -// Check that game settings are valid +/* Used to expand the least significant byte of a tic number into + * the full tic number, from the current tic number + */ -boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission, - net_gamesettings_t *settings) +unsigned int net_expand_tic_num(unsigned int relative, unsigned int b) { - if (settings->ticdup <= 0) - return false; - - if (settings->extratics < 0) - return false; - - if (settings->deathmatch < 0 || settings->deathmatch > 2) - return false; + unsigned int l; + unsigned int h; + unsigned int result; - if (settings->skill < sk_noitems || settings->skill > sk_nightmare) - return false; + h = relative & ~0xff; + l = relative & 0xff; - if (!D_ValidGameVersion(mission, settings->gameversion)) - return false; + result = h | b; - if (!D_ValidEpisodeMap(mission, mode, settings->episode, settings->map)) - return false; + if (l < 0x40 && b > 0xb0) result -= 0x100; + if (l > 0xb0 && b < 0x40) result += 0x100; - return true; + return result; } -static void CloseLog(void) +/* Check that game settings are valid */ + +boolean net_valid_game_settings(game_mode_t mode, gamemission_t mission, + net_gamesettings_t *settings) { - if (net_debug != NULL) + if (settings->ticdup <= 0) { - fclose(net_debug); - net_debug = NULL; + return false; } -} -void NET_OpenLog(void) -{ - int p; + if (settings->extratics < 0) + { + return false; + } - p = M_CheckParmWithArgs("-netlog", 1); - if (p > 0) + if (settings->deathmatch < 0 || settings->deathmatch > 2) { - net_debug = M_fopen(myargv[p + 1], "w"); - if (net_debug == NULL) - { - I_Error("Failed to open %s to write debug log.", myargv[p + 1]); - } - I_AtExit(CloseLog, true); + return false; } -} -void NET_Log(const char *fmt, ...) -{ - va_list args; + if (settings->skill < sk_noitems || settings->skill > sk_nightmare) + { + return false; + } - if (net_debug == NULL) + if (!d_valid_game_version(mission, settings->gameversion)) { - return; + return false; } - fprintf(net_debug, "%8d: ", I_GetTimeMS()); - va_start(args, fmt); - vfprintf(net_debug, fmt, args); - va_end(args); - fprintf(net_debug, "\n"); + if (!d_valid_episode_map(mission, mode, settings->episode, settings->map)) + { + return false; + } + + return true; } -void NET_LogPacket(net_packet_t *packet) +#ifdef CONFIG_GAMES_NXDOOM_NET_LOGS +void net_log_packet(net_packet_t *packet) { - int i, bytes; + int i; + int bytes; - if (net_debug == NULL) + bytes = packet->len - packet->pos; + if (bytes == 0) { - return; + return; } - bytes = packet->len - packet->pos; - if (bytes == 0) - { - return; - } - fprintf(net_debug, "\t%02x", packet->data[packet->pos]); - for (i = 1; i < bytes; ++i) + fprintf(stderr, "\t%02x", packet->data[packet->pos]); + + for (i = 1; i < bytes; ++i) { - if ((i % 16) == 0) + if ((i % 16) == 0) { - fprintf(net_debug, "\n\t"); + fprintf(stderr, "\n\t"); } - else + else { - fprintf(net_debug, " "); + fprintf(stderr, " "); } - fprintf(net_debug, "%02x", packet->data[packet->pos + i]); + + fprintf(stderr, "%02x", packet->data[packet->pos + i]); } - fprintf(net_debug, "\n"); -} + fprintf(stderr, "\n"); +} +#endif /* CONFIG_GAMES_NXDOOM_NET_LOGS */ diff --git a/games/NXDoom/src/net_common.h b/games/NXDoom/src/net_common.h index 15a7684aef8..09770a1b2ba 100644 --- a/games/NXDoom/src/net_common.h +++ b/games/NXDoom/src/net_common.h @@ -1,106 +1,145 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Common code shared between the client and server -// +/**************************************************************************** + * apps/games/NXDoom/src/net_common.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Common code shared between the client and server + * + ****************************************************************************/ #ifndef NET_COMMON_H #define NET_COMMON_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + #include "d_mode.h" #include "net_defs.h" #include "net_packet.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_RETRIES 5 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef enum { - // Client has sent a SYN, is waiting for a SYN in response. - NET_CONN_STATE_CONNECTING, + /* Client has sent a SYN, is waiting for a SYN in response. */ + + NET_CONN_STATE_CONNECTING, + + /* Successfully connected. */ + + NET_CONN_STATE_CONNECTED, - // Successfully connected. - NET_CONN_STATE_CONNECTED, + /* Sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply */ - // Sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply - NET_CONN_STATE_DISCONNECTING, + NET_CONN_STATE_DISCONNECTING, - // Client successfully disconnected - NET_CONN_STATE_DISCONNECTED, + /* Client successfully disconnected */ - // We are disconnected, but in a sleep state, waiting for several - // seconds. This is in case the DISCONNECT_ACK we sent failed - // to arrive, and we need to send another one. We keep this as - // a valid connection for a few seconds until we are sure that - // the other end has successfully disconnected as well. - NET_CONN_STATE_DISCONNECTED_SLEEP, + NET_CONN_STATE_DISCONNECTED, + /* We are disconnected, but in a sleep state, waiting for several + * seconds. This is in case the DISCONNECT_ACK we sent failed + * to arrive, and we need to send another one. We keep this as + * a valid connection for a few seconds until we are sure that + * the other end has successfully disconnected as well. + */ + + NET_CONN_STATE_DISCONNECTED_SLEEP, } net_connstate_t; -// Reason a connection was terminated +/* Reason a connection was terminated */ typedef enum { - // As the result of a local disconnect request - - NET_DISCONNECT_LOCAL, + /* As the result of a local disconnect request */ - // As the result of a remote disconnect request + NET_DISCONNECT_LOCAL, - NET_DISCONNECT_REMOTE, + /* As the result of a remote disconnect request */ - // Timeout (no data received in a long time) + NET_DISCONNECT_REMOTE, - NET_DISCONNECT_TIMEOUT, + /* Timeout (no data received in a long time) */ + NET_DISCONNECT_TIMEOUT, } net_disconnect_reason_t; -#define MAX_RETRIES 5 - typedef struct net_reliable_packet_s net_reliable_packet_t; -typedef struct +typedef struct { - net_connstate_t state; - net_disconnect_reason_t disconnect_reason; - net_addr_t *addr; - net_protocol_t protocol; - int last_send_time; - int num_retries; - int keepalive_send_time; - int keepalive_recv_time; - net_reliable_packet_t *reliable_packets; - int reliable_send_seq; - int reliable_recv_seq; + net_connstate_t state; + net_disconnect_reason_t disconnect_reason; + net_addr_t *addr; + net_protocol_t protocol; + int last_send_time; + int num_retries; + int keepalive_send_time; + int keepalive_recv_time; + net_reliable_packet_t *reliable_packets; + int reliable_send_seq; + int reliable_recv_seq; } net_connection_t; +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet); -void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr, +void net_conn_send_packet(net_connection_t *conn, net_packet_t *packet); +void net_conn_init_client(net_connection_t *conn, net_addr_t *addr, + net_protocol_t protocol); +void net_conn_init_server(net_connection_t *conn, net_addr_t *addr, net_protocol_t protocol); -void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr, - net_protocol_t protocol); -boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet, +boolean net_conn_packet(net_connection_t *conn, net_packet_t *packet, unsigned int *packet_type); -void NET_Conn_Disconnect(net_connection_t *conn); -void NET_Conn_Run(net_connection_t *conn); -net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type); +void net_conn_disconnect(net_connection_t *conn); +void net_conn_run(net_connection_t *conn); +net_packet_t *net_conn_new_reliable(net_connection_t *conn, int packet_type); + +/* Other miscellaneous common functions */ -// Other miscellaneous common functions -unsigned int NET_ExpandTicNum(unsigned int relative, unsigned int b); -boolean NET_ValidGameSettings(GameMode_t mode, GameMission_t mission, +unsigned int net_expand_tic_num(unsigned int relative, unsigned int b); +boolean net_valid_game_settings(game_mode_t mode, gamemission_t mission, net_gamesettings_t *settings); -void NET_OpenLog(void); -void NET_Log(const char *fmt, ...); -void NET_LogPacket(net_packet_t *packet); +/* Conditional logging */ + +#ifdef CONFIG_GAMES_NXDOOM_NET_LOGS +#define net_log_info(fmt, ...) syslog(LOG_USER | LOG_INFO, fmt, ##__VA_ARGS__) +#define net_log_warn(fmt, ...) \ + syslog(LOG_USER | LOG_WARNING, fmt, ##__VA_ARGS__) +#define net_log_err(fmt, ...) syslog(LOG_USER | LOG_ERR, fmt, ##__VA_ARGS__) + +void net_log_packet(net_packet_t *packet); +#else +#define net_log_info(fmt, ...) +#define net_log_warn(fmt, ...) +#define net_log_err(fmt, ...) -#endif /* #ifndef NET_COMMON_H */ +#define net_log_packet(pkt) +#endif /* CONFIG_GAMES_NXDOOM_NET_LOGS */ +#endif /* NET_COMMON_H */ diff --git a/games/NXDoom/src/net_dedicated.c b/games/NXDoom/src/net_dedicated.c index dcb9f8fae2a..8c59fb7bbf8 100644 --- a/games/NXDoom/src/net_dedicated.c +++ b/games/NXDoom/src/net_dedicated.c @@ -1,19 +1,27 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dedicated server code. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_dedicated.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Dedicated server code. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -29,52 +37,65 @@ #include "net_sdl.h" #include "net_server.h" -// -// People can become confused about how dedicated servers work. Game -// options are specified to the controlling player who is the first to -// join a game. Bomb out with an error message if game options are -// specified to a dedicated server. -// +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* People can become confused about how dedicated servers work. Game + * options are specified to the controlling player who is the first to + * join a game. Bomb out with an error message if game options are + * specified to a dedicated server. + */ static const char *not_dedicated_options[] = { - "-deh", "-iwad", "-cdrom", "-gameversion", "-nomonsters", "-respawn", - "-fast", "-altdeath", "-deathmatch", "-turbo", "-merge", "-af", "-as", - "-aa", "-file", "-wart", "-skill", "-episode", "-timer", "-avg", "-warp", - "-loadgame", "-longtics", "-extratics", "-dup", "-shorttics", NULL, + "-deh", "-iwad", "-cdrom", "-gameversion", "-nomonsters", + "-respawn", "-fast", "-altdeath", "-deathmatch", "-turbo", + "-merge", "-af", "-as", "-aa", "-file", + "-wart", "-skill", "-episode", "-timer", "-avg", + "-warp", "-loadgame", "-longtics", "-extratics", "-dup", + "-shorttics", NULL, }; -static void CheckForClientOptions(void) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void check_for_client_options(void) { - int i; + int i; - for (i=0; not_dedicated_options[i] != NULL; ++i) + for (i = 0; not_dedicated_options[i] != NULL; ++i) { - if (M_CheckParm(not_dedicated_options[i]) > 0) + if (m_check_parm(not_dedicated_options[i]) > 0) { - I_Error("The command line parameter '%s' was specified to a " - "dedicated server.\nGame parameters should be specified " - "to the first player to join a server, \nnot to the " - "server itself. ", - not_dedicated_options[i]); + i_error("The command line parameter '%s' was specified to a " + "dedicated server.\nGame parameters should be specified " + "to the first player to join a server, \nnot to the " + "server itself. ", + not_dedicated_options[i]); } } } -void NET_DedicatedServer(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void net_dedicated_server(void) { - CheckForClientOptions(); + check_for_client_options(); - NET_OpenLog(); - NET_SV_Init(); - NET_SV_AddModule(&net_sdl_module); - NET_SV_RegisterWithMaster(); + net_sv_init(); + net_sv_add_module(&net_sdl_module); + net_sv_register_with_master(); - while (true) + while (true) { - NET_SV_Run(); - // TODO: Block on socket instead of polling. - I_Sleep(1); + net_sv_run(); + + /* TODO: Block on socket instead of polling. */ + + usleep(1000); } } - diff --git a/games/NXDoom/src/net_dedicated.h b/games/NXDoom/src/net_dedicated.h index 3d7387b5782..2f87bc5d59e 100644 --- a/games/NXDoom/src/net_dedicated.h +++ b/games/NXDoom/src/net_dedicated.h @@ -1,25 +1,32 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Dedicated server code. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_dedicated.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Dedicated server code. + * + ****************************************************************************/ #ifndef NET_DEDICATED_H #define NET_DEDICATED_H -void NET_DedicatedServer(void); - -#endif /* #ifndef NET_DEDICATED_H */ +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +void net_dedicated_server(void); +#endif /* NET_DEDICATED_H */ diff --git a/games/NXDoom/src/net_defs.h b/games/NXDoom/src/net_defs.h index ab852c08eec..be735863029 100644 --- a/games/NXDoom/src/net_defs.h +++ b/games/NXDoom/src/net_defs.h @@ -1,48 +1,104 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Definitions for use in networking code. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_defs.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Definitions for use in networking code. + * + ****************************************************************************/ #ifndef NET_DEFS_H -#define NET_DEFS_H +#define NET_DEFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include -#include "doomtype.h" #include "d_ticcmd.h" +#include "doomtype.h" #include "sha1.h" -// Absolute maximum number of "nodes" in the game. This is different to -// NET_MAXPLAYERS, as there may be observers that are not participating -// (eg. left/right monitors) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Absolute maximum number of "nodes" in the game. This is different to + * NET_MAXPLAYERS, as there may be observers that are not participating + * (eg. left/right monitors) + */ #define MAXNETNODES 16 -// The maximum number of players, multiplayer/networking. -// This is the maximum supported by the networking code; individual games -// have their own values for MAXPLAYERS that can be smaller. +#ifndef CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME + +/* We don't need player names. TODO: I should be smarter about this + * and avoid compiling ANY networking related stuff (i.e. player name + * members in the structs below) at all when net stuff is not enabled. + */ + +#define CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME (1) +#endif /* CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME */ + +/* The maximum number of players, multiplayer/networking. + * This is the maximum supported by the networking code; individual games + * have their own values for MAXPLAYERS that can be smaller. + */ + +#ifndef CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS + +/* No players if not set up for networking */ + +#define CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS (1) +#endif /* CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS */ + +/* Networking and tick handling related. */ + +#ifndef CONFIG_GAMES_NXDOOM_NET_BACKUPTICS + +/* Surely we don't need any for a local game? */ + +#define CONFIG_GAMES_NXDOOM_NET_BACKUPTICS (1) +#endif /* CONFIG_GAMES_NXDOOM_NET_BACKUPTICS */ -#define NET_MAXPLAYERS 8 +/* Magic number sent when connecting to check this is a valid client */ -// Maximum length of a player's name. +#define NET_MAGIC_NUMBER 1454104972U -#define MAXPLAYERNAME 30 +/* Old magic number used by Chocolate Doom versions before v3.0: */ -// Networking and tick handling related. +#define NET_OLD_MAGIC_NUMBER 3436803284U + +/* header field value indicating that the packet is a reliable packet */ + +#define NET_RELIABLE_PACKET (1 << 15) -#define BACKUPTICS 128 +#define NET_TICDIFF_FORWARD (1 << 0) +#define NET_TICDIFF_SIDE (1 << 1) +#define NET_TICDIFF_TURN (1 << 2) +#define NET_TICDIFF_BUTTONS (1 << 3) +#define NET_TICDIFF_CONSISTANCY (1 << 4) +#define NET_TICDIFF_CHATCHAR (1 << 5) +#define NET_TICDIFF_RAVEN (1 << 6) +#define NET_TICDIFF_STRIFE (1 << 7) + +/**************************************************************************** + * Public Types + ****************************************************************************/ typedef struct _net_module_s net_module_t; typedef struct _net_packet_s net_packet_t; @@ -51,226 +107,217 @@ typedef struct _net_context_s net_context_t; struct _net_packet_s { - byte *data; - size_t len; - size_t alloced; - unsigned int pos; + byte *data; + size_t len; + size_t alloced; + unsigned int pos; }; struct _net_module_s { - // Initialize this module for use as a client + /* Initialize this module for use as a client */ - boolean (*InitClient)(void); + boolean (*init_client)(void); - // Initialize this module for use as a server + /* Initialize this module for use as a server */ - boolean (*InitServer)(void); + boolean (*init_server)(void); - // Send a packet + /* Send a packet */ - void (*SendPacket)(net_addr_t *addr, net_packet_t *packet); + void (*send_packet)(net_addr_t *addr, net_packet_t *packet); - // Check for new packets to receive - // - // Returns true if packet received + /* Check for new packets to receive + * + * Returns true if packet received + */ - boolean (*RecvPacket)(net_addr_t **addr, net_packet_t **packet); + boolean (*recv_packet)(net_addr_t **addr, net_packet_t **packet); - // Converts an address to a string + /* Converts an address to a string */ - void (*AddrToString)(net_addr_t *addr, char *buffer, int buffer_len); + void (*addr_to_string)(net_addr_t *addr, char *buffer, int buffer_len); - // Free back an address when no longer in use + /* Free back an address when no longer in use */ - void (*FreeAddress)(net_addr_t *addr); + void (*free_address)(net_addr_t *addr); - // Try to resolve a name to an address + /* Try to resolve a name to an address */ - net_addr_t *(*ResolveAddress)(const char *addr); + net_addr_t *(*resolve_address)(const char *addr); }; -// net_addr_t +/* net_addr_t */ struct _net_addr_s { - net_module_t *module; - int refcount; - void *handle; + net_module_t *module; + int refcount; + void *handle; }; -// Magic number sent when connecting to check this is a valid client -#define NET_MAGIC_NUMBER 1454104972U - -// Old magic number used by Chocolate Doom versions before v3.0: -#define NET_OLD_MAGIC_NUMBER 3436803284U - -// header field value indicating that the packet is a reliable packet - -#define NET_RELIABLE_PACKET (1 << 15) +/* Supported protocols. If you're developing a fork of Chocolate + * Doom, you can add your own entry to this list while maintaining + * compatibility with Chocolate Doom servers. Higher-numbered enum values + * will be preferred when negotiating a protocol for the client and server + * to use, so the order matters. + * NOTE: The values in this enum do not have any special value outside of + * the program they're compiled in. What matters is the string + * representation. + */ -// Supported protocols. If you're developing a fork of Chocolate -// Doom, you can add your own entry to this list while maintaining -// compatibility with Chocolate Doom servers. Higher-numbered enum values -// will be preferred when negotiating a protocol for the client and server -// to use, so the order matters. -// NOTE: The values in this enum do not have any special value outside of -// the program they're compiled in. What matters is the string representation. typedef enum { - // Protocol introduced with Chocolate Doom v3.0. Each compatibility- - // breaking change to the network protocol will produce a new protocol - // number in this enum. - NET_PROTOCOL_CHOCOLATE_DOOM_0, + /* Protocol introduced with Chocolate Doom v3.0. Each compatibility- + * breaking change to the network protocol will produce a new protocol + * number in this enum. + */ + + NET_PROTOCOL_CHOCOLATE_DOOM_0, - // Add your own protocol here; be sure to add a name for it to the list - // in net_common.c too. + /* Add your own protocol here; be sure to add a name for it to the list + * in net_common.c too. + */ - NET_NUM_PROTOCOLS, - NET_PROTOCOL_UNKNOWN, + NET_NUM_PROTOCOLS, + NET_PROTOCOL_UNKNOWN, } net_protocol_t; -// packet types +/* packet types */ typedef enum { - NET_PACKET_TYPE_SYN, - NET_PACKET_TYPE_ACK, // deprecated - NET_PACKET_TYPE_REJECTED, - NET_PACKET_TYPE_KEEPALIVE, - NET_PACKET_TYPE_WAITING_DATA, - NET_PACKET_TYPE_GAMESTART, - NET_PACKET_TYPE_GAMEDATA, - NET_PACKET_TYPE_GAMEDATA_ACK, - NET_PACKET_TYPE_DISCONNECT, - NET_PACKET_TYPE_DISCONNECT_ACK, - NET_PACKET_TYPE_RELIABLE_ACK, - NET_PACKET_TYPE_GAMEDATA_RESEND, - NET_PACKET_TYPE_CONSOLE_MESSAGE, - NET_PACKET_TYPE_QUERY, - NET_PACKET_TYPE_QUERY_RESPONSE, - NET_PACKET_TYPE_LAUNCH, - NET_PACKET_TYPE_NAT_HOLE_PUNCH, + NET_PACKET_TYPE_SYN, + NET_PACKET_TYPE_ACK, /* deprecated */ + NET_PACKET_TYPE_REJECTED, + NET_PACKET_TYPE_KEEPALIVE, + NET_PACKET_TYPE_WAITING_DATA, + NET_PACKET_TYPE_GAMESTART, + NET_PACKET_TYPE_GAMEDATA, + NET_PACKET_TYPE_GAMEDATA_ACK, + NET_PACKET_TYPE_DISCONNECT, + NET_PACKET_TYPE_DISCONNECT_ACK, + NET_PACKET_TYPE_RELIABLE_ACK, + NET_PACKET_TYPE_GAMEDATA_RESEND, + NET_PACKET_TYPE_CONSOLE_MESSAGE, + NET_PACKET_TYPE_QUERY, + NET_PACKET_TYPE_QUERY_RESPONSE, + NET_PACKET_TYPE_LAUNCH, + NET_PACKET_TYPE_NAT_HOLE_PUNCH, } net_packet_type_t; typedef enum { - NET_MASTER_PACKET_TYPE_ADD, - NET_MASTER_PACKET_TYPE_ADD_RESPONSE, - NET_MASTER_PACKET_TYPE_QUERY, - NET_MASTER_PACKET_TYPE_QUERY_RESPONSE, - NET_MASTER_PACKET_TYPE_GET_METADATA, - NET_MASTER_PACKET_TYPE_GET_METADATA_RESPONSE, - NET_MASTER_PACKET_TYPE_SIGN_START, - NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, - NET_MASTER_PACKET_TYPE_SIGN_END, - NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, - NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH, - NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL, + NET_MASTER_PACKET_TYPE_ADD, + NET_MASTER_PACKET_TYPE_ADD_RESPONSE, + NET_MASTER_PACKET_TYPE_QUERY, + NET_MASTER_PACKET_TYPE_QUERY_RESPONSE, + NET_MASTER_PACKET_TYPE_GET_METADATA, + NET_MASTER_PACKET_TYPE_GET_METADATA_RESPONSE, + NET_MASTER_PACKET_TYPE_SIGN_START, + NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, + NET_MASTER_PACKET_TYPE_SIGN_END, + NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, + NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH, + NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL, } net_master_packet_type_t; -// Settings specified when the client connects to the server. +/* Settings specified when the client connects to the server. */ typedef struct { - int gamemode; - int gamemission; - int lowres_turn; - int drone; - int max_players; - int is_freedoom; - sha1_digest_t wad_sha1sum; - sha1_digest_t deh_sha1sum; - int player_class; + int gamemode; + int gamemission; + int lowres_turn; + int drone; + int max_players; + int is_freedoom; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; + int player_class; } net_connect_data_t; -// Game settings sent by client to server when initiating game start, -// and received from the server by clients when the game starts. +/* Game settings sent by client to server when initiating game start, + * and received from the server by clients when the game starts. + */ typedef struct { - int ticdup; - int extratics; - int deathmatch; - int episode; - int nomonsters; - int fast_monsters; - int respawn_monsters; - int map; - int skill; - int gameversion; - int lowres_turn; - int new_sync; - int timelimit; - int loadgame; - int random; // [Strife only] - - // These fields are only used by the server when sending a game - // start message: - - int num_players; - int consoleplayer; - - // Hexen player classes: - - int player_classes[NET_MAXPLAYERS]; - + int ticdup; + int extratics; + int deathmatch; + int episode; + int nomonsters; + int fast_monsters; + int respawn_monsters; + int map; + int skill; + int gameversion; + int lowres_turn; + int new_sync; + int timelimit; + int loadgame; + int random; /* [Strife only] */ + + /* These fields are only used by the server when sending a game + * start message: + */ + + int num_players; + int consoleplayer; + + /* Hexen player classes: */ + + int player_classes[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; } net_gamesettings_t; -#define NET_TICDIFF_FORWARD (1 << 0) -#define NET_TICDIFF_SIDE (1 << 1) -#define NET_TICDIFF_TURN (1 << 2) -#define NET_TICDIFF_BUTTONS (1 << 3) -#define NET_TICDIFF_CONSISTANCY (1 << 4) -#define NET_TICDIFF_CHATCHAR (1 << 5) -#define NET_TICDIFF_RAVEN (1 << 6) -#define NET_TICDIFF_STRIFE (1 << 7) - typedef struct { - unsigned int diff; - ticcmd_t cmd; + unsigned int diff; + ticcmd_t cmd; } net_ticdiff_t; -// Complete set of ticcmds from all players +/* Complete set of ticcmds from all players */ -typedef struct +typedef struct { - signed int latency; - unsigned int seq; - boolean playeringame[NET_MAXPLAYERS]; - net_ticdiff_t cmds[NET_MAXPLAYERS]; + signed int latency; + unsigned int seq; + boolean playeringame[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; + net_ticdiff_t cmds[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; } net_full_ticcmd_t; -// Data sent in response to server queries +/* Data sent in response to server queries */ typedef struct { - const char *version; - int server_state; - int num_players; - int max_players; - int gamemode; - int gamemission; - const char *description; - net_protocol_t protocol; + const char *version; + int server_state; + int num_players; + int max_players; + int gamemode; + int gamemission; + const char *description; + net_protocol_t protocol; } net_querydata_t; -// Data sent by the server while waiting for the game to start. +/* Data sent by the server while waiting for the game to start. */ typedef struct { - int num_players; - int num_drones; - int ready_players; - int max_players; - int is_controller; - int consoleplayer; - char player_names[NET_MAXPLAYERS][MAXPLAYERNAME]; - char player_addrs[NET_MAXPLAYERS][MAXPLAYERNAME]; - sha1_digest_t wad_sha1sum; - sha1_digest_t deh_sha1sum; - int is_freedoom; + int num_players; + int num_drones; + int ready_players; + int max_players; + int is_controller; + int consoleplayer; + char player_names[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS] + [CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME]; + char player_addrs[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS] + [CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME]; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; + int is_freedoom; } net_waitdata_t; -#endif /* #ifndef NET_DEFS_H */ +#endif /* NET_DEFS_H */ diff --git a/games/NXDoom/src/net_gui.c b/games/NXDoom/src/net_gui.c index 0a73fa43cd9..f731693caf7 100644 --- a/games/NXDoom/src/net_gui.c +++ b/games/NXDoom/src/net_gui.c @@ -1,26 +1,35 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Graphical stuff related to the networking code: -// -// * The client waiting screen when we are waiting for the server to -// start the game. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_gui.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Graphical stuff related to the networking code: + * + * * The client waiting screen when we are waiting for the server to + * start the game. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include #include "config.h" #include "doomkeys.h" @@ -38,397 +47,423 @@ #include "textscreen.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ + static txt_window_t *window; static int old_max_players; -static txt_label_t *player_labels[NET_MAXPLAYERS]; -static txt_label_t *ip_labels[NET_MAXPLAYERS]; +static txt_label_t *player_labels[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; +static txt_label_t *ip_labels[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; static txt_label_t *drone_label; static txt_label_t *master_msg_label; static boolean had_warning; -// Number of players we expect to be in the game. When the number is -// reached, we auto-start the game (if we're the controller). If -// zero, do not autostart. +/* Number of players we expect to be in the game. When the number is + * reached, we auto-start the game (if we're the controller). If + * zero, do not autostart. + */ + static int expected_nodes; -static void EscapePressed(TXT_UNCAST_ARG(widget), void *unused) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void escape_pressed(TXT_UNCAST_ARG(widget), void *unused) { - TXT_Shutdown(); - I_Quit(); + txt_shutdown(); + i_quit(); } -static void StartGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +static void start_game(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) { - NET_CL_LaunchGame(); + net_cl_launch_game(); } -static void OpenWaitDialog(void) +static void open_wait_dialog(void) { - txt_window_action_t *cancel; + txt_window_action_t *cancel; - TXT_SetDesktopTitle(PACKAGE_STRING); + txt_set_desktop_title(PACKAGE_STRING); - window = TXT_NewWindow("Waiting for game start..."); + window = txt_new_window("Waiting for game start..."); - TXT_AddWidget(window, TXT_NewLabel("\nPlease wait...\n\n")); + txt_add_widget(window, txt_new_label("\nPlease wait...\n\n")); - cancel = TXT_NewWindowAction(KEY_ESCAPE, "Cancel"); - TXT_SignalConnect(cancel, "pressed", EscapePressed, NULL); + cancel = txt_new_window_action(KEY_ESCAPE, "Cancel"); + txt_signal_connect(cancel, "pressed", escape_pressed, NULL); - TXT_SetWindowAction(window, TXT_HORIZ_LEFT, cancel); - TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_BOTTOM, - TXT_SCREEN_W / 2, TXT_SCREEN_H - 9); + txt_set_window_action(window, TXT_HORIZ_LEFT, cancel); + txt_set_window_position(window, TXT_HORIZ_CENTER, TXT_VERT_BOTTOM, + TXT_SCREEN_W / 2, TXT_SCREEN_H - 9); - old_max_players = 0; + old_max_players = 0; } -static void BuildWindow(void) +static void build_window(void) { - char buf[50]; - txt_table_t *table; - int i; + char buf[50]; + txt_table_t *table; + int i; - TXT_ClearTable(window); - table = TXT_NewTable(3); - TXT_AddWidget(window, table); + txt_clear_table(window); + table = txt_new_table(3); + txt_add_widget(window, table); - // Add spacers + /* Add spacers */ - TXT_AddWidget(table, NULL); - TXT_AddWidget(table, TXT_NewStrut(25, 1)); - TXT_AddWidget(table, TXT_NewStrut(17, 1)); + txt_add_widget(table, NULL); + txt_add_widget(table, txt_new_strut(25, 1)); + txt_add_widget(table, txt_new_strut(17, 1)); - // Player labels + /* Player labels */ - for (i = 0; i < net_client_wait_data.max_players; ++i) + for (i = 0; i < net_client_wait_data.max_players; ++i) { - M_snprintf(buf, sizeof(buf), " %i. ", i + 1); - TXT_AddWidget(table, TXT_NewLabel(buf)); - player_labels[i] = TXT_NewLabel(""); - ip_labels[i] = TXT_NewLabel(""); - TXT_AddWidget(table, player_labels[i]); - TXT_AddWidget(table, ip_labels[i]); + snprintf(buf, sizeof(buf), " %i. ", i + 1); + txt_add_widget(table, txt_new_label(buf)); + player_labels[i] = txt_new_label(""); + ip_labels[i] = txt_new_label(""); + txt_add_widget(table, player_labels[i]); + txt_add_widget(table, ip_labels[i]); } - drone_label = TXT_NewLabel(""); + drone_label = txt_new_label(""); - TXT_AddWidget(window, drone_label); + txt_add_widget(window, drone_label); } -static void UpdateGUI(void) +static void update_gui(void) { - txt_window_action_t *startgame; - char buf[50]; - unsigned int i; + txt_window_action_t *startgame; + char buf[50]; + unsigned int i; - // If the value of max_players changes, we must rebuild the - // contents of the window. This includes when the first - // waiting data packet is received. + /* If the value of max_players changes, we must rebuild the + * contents of the window. This includes when the first + * waiting data packet is received. + */ - if (net_client_received_wait_data) + if (net_client_received_wait_data) { - if (net_client_wait_data.max_players != old_max_players) + if (net_client_wait_data.max_players != old_max_players) { - BuildWindow(); + build_window(); } } - else + else { - return; + return; } - for (i = 0; i < net_client_wait_data.max_players; ++i) + for (i = 0; i < net_client_wait_data.max_players; ++i) { - txt_color_t color = TXT_COLOR_BRIGHT_WHITE; + txt_color_t color = TXT_COLOR_BRIGHT_WHITE; - if ((signed) i == net_client_wait_data.consoleplayer) + if ((signed)i == net_client_wait_data.consoleplayer) { - color = TXT_COLOR_YELLOW; + color = TXT_COLOR_YELLOW; } - TXT_SetFGColor(player_labels[i], color); - TXT_SetFGColor(ip_labels[i], color); + txt_set_fg_colour(player_labels[i], color); + txt_set_fg_colour(ip_labels[i], color); - if (i < net_client_wait_data.num_players) + if (i < net_client_wait_data.num_players) { - TXT_SetLabel(player_labels[i], - net_client_wait_data.player_names[i]); - TXT_SetLabel(ip_labels[i], - net_client_wait_data.player_addrs[i]); + txt_set_label(player_labels[i], + net_client_wait_data.player_names[i]); + txt_set_label(ip_labels[i], net_client_wait_data.player_addrs[i]); } - else + else { - TXT_SetLabel(player_labels[i], ""); - TXT_SetLabel(ip_labels[i], ""); + txt_set_label(player_labels[i], ""); + txt_set_label(ip_labels[i], ""); } } - if (net_client_wait_data.num_drones > 0) + if (net_client_wait_data.num_drones > 0) { - M_snprintf(buf, sizeof(buf), " (+%i observer clients)", - net_client_wait_data.num_drones); - TXT_SetLabel(drone_label, buf); + snprintf(buf, sizeof(buf), " (+%i observer clients)", + net_client_wait_data.num_drones); + txt_set_label(drone_label, buf); } - else + else { - TXT_SetLabel(drone_label, ""); + txt_set_label(drone_label, ""); } - if (net_client_wait_data.is_controller) + if (net_client_wait_data.is_controller) { - startgame = TXT_NewWindowAction(' ', "Start game"); - TXT_SignalConnect(startgame, "pressed", StartGame, NULL); + startgame = txt_new_window_action(' ', "Start game"); + txt_signal_connect(startgame, "pressed", start_game, NULL); } - else + else { - startgame = NULL; + startgame = NULL; } - TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, startgame); + txt_set_window_action(window, TXT_HORIZ_RIGHT, startgame); } -static void BuildMasterStatusWindow(void) +static void build_master_status_window(void) { - txt_window_t *master_window; - - master_window = TXT_NewWindow(NULL); - master_msg_label = TXT_NewLabel(""); - TXT_AddWidget(master_window, master_msg_label); - - // This window is here purely for information, so it should be - // in the background. - - TXT_LowerWindow(master_window); - TXT_SetWindowPosition(master_window, TXT_HORIZ_CENTER, TXT_VERT_CENTER, - TXT_SCREEN_W / 2, TXT_SCREEN_H - 4); - TXT_SetWindowAction(master_window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction(master_window, TXT_HORIZ_CENTER, NULL); - TXT_SetWindowAction(master_window, TXT_HORIZ_RIGHT, NULL); + txt_window_t *master_window; + + master_window = txt_new_window(NULL); + master_msg_label = txt_new_label(""); + txt_add_widget(master_window, master_msg_label); + + /* This window is here purely for information, so it should be + * in the background. + */ + + txt_lower_window(master_window); + txt_set_window_position(master_window, TXT_HORIZ_CENTER, TXT_VERT_CENTER, + TXT_SCREEN_W / 2, TXT_SCREEN_H - 4); + txt_set_window_action(master_window, TXT_HORIZ_LEFT, NULL); + txt_set_window_action(master_window, TXT_HORIZ_CENTER, NULL); + txt_set_window_action(master_window, TXT_HORIZ_RIGHT, NULL); } -static void CheckMasterStatus(void) +static void check_master_status(void) { - boolean added; + boolean added; - if (!NET_Query_CheckAddedToMaster(&added)) + if (!net_query_check_added_to_master(&added)) { - return; + return; } - if (master_msg_label == NULL) + if (master_msg_label == NULL) { - BuildMasterStatusWindow(); + build_master_status_window(); } - if (added) + if (added) { - TXT_SetLabel(master_msg_label, - "Your server is now registered with the global master server.\n" - "Other players can find your server online."); + txt_set_label( + master_msg_label, + "Your server is now registered with the global master server.\n" + "Other players can find your server online."); } - else + else { - TXT_SetLabel(master_msg_label, - "Failed to register with the master server. Your server is not\n" - "publicly accessible. You may need to reconfigure your Internet\n" - "router to add a port forward for UDP port 2342. Look up\n" - "information on port forwarding online."); + txt_set_label( + master_msg_label, + "Failed to register with the master server. Your server is not\n" + "publicly accessible. You may need to reconfigure your Internet\n" + "router to add a port forward for UDP port 2342. Look up\n" + "information on port forwarding online."); } } -static void PrintSHA1Digest(const char *s, const byte *digest) +static void print_sha1_digest(const char *s, const byte *digest) { - unsigned int i; + unsigned int i; - printf("%s: ", s); + printf("%s: ", s); - for (i=0; i - // @category net - // - // Autostart the netgame when n nodes (clients) have joined the server. - // + /* @arg + * @category net + * + * Autostart the netgame when n nodes (clients) have joined the server. + */ - i = M_CheckParmWithArgs("-nodes", 1); - if (i > 0) + i = m_check_parm_with_args("-nodes", 1); + if (i > 0) { - expected_nodes = atoi(myargv[i + 1]); + expected_nodes = atoi(myargv[i + 1]); } } -static void CheckAutoLaunch(void) +static void check_auto_latch(void) { - int nodes; + int nodes; - if (net_client_received_wait_data - && net_client_wait_data.is_controller - && expected_nodes > 0) + if (net_client_received_wait_data && net_client_wait_data.is_controller && + expected_nodes > 0) { - nodes = net_client_wait_data.num_players - + net_client_wait_data.num_drones; + nodes = + net_client_wait_data.num_players + net_client_wait_data.num_drones; - if (nodes >= expected_nodes) + if (nodes >= expected_nodes) { - StartGame(NULL, NULL); - expected_nodes = 0; + start_game(NULL, NULL); + expected_nodes = 0; } } } -void NET_WaitForLaunch(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void net_wait_for_launch(void) { - if (!TXT_Init()) + if (!txt_init()) { - fprintf(stderr, "Failed to initialize GUI\n"); - exit(-1); + fprintf(stderr, "Failed to initialize GUI\n"); + exit(-1); } - TXT_SetColor(TXT_COLOR_BLUE, 0x04, 0x14, 0x40); // Romero's "funky blue" color - - I_InitWindowIcon(); + /* Romero's "funky blue" color */ + + txt_set_colour(TXT_COLOR_BLUE, 0x04, 0x14, 0x40); - ParseCommandLineArgs(); - OpenWaitDialog(); - had_warning = false; + parse_command_line_args(); + open_wait_dialog(); + had_warning = false; - while (net_waiting_for_launch) + while (net_waiting_for_launch) { - UpdateGUI(); - CheckAutoLaunch(); - CheckSHA1Sums(); - CheckMasterStatus(); + update_gui(); + check_auto_latch(); + check_sha1_sums(); + check_master_status(); - TXT_DispatchEvents(); - TXT_DrawDesktop(); + txt_dispatch_events(); + txt_draw_desktop(); - NET_CL_Run(); - NET_SV_Run(); + net_cl_run(); + net_sv_run(); - if (!net_client_connected) + if (!net_client_connected) { - I_Error("Lost connection to server"); + i_error("Lost connection to server"); } - TXT_Sleep(100); + txt_sleep(100); } - TXT_Shutdown(); + txt_shutdown(); } diff --git a/games/NXDoom/src/net_gui.h b/games/NXDoom/src/net_gui.h index 4f4198b6087..377b6646c67 100644 --- a/games/NXDoom/src/net_gui.h +++ b/games/NXDoom/src/net_gui.h @@ -1,29 +1,40 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Graphical stuff related to the networking code: -// -// * The client waiting screen when we are waiting for the server to -// start the game. -// - +/**************************************************************************** + * apps/games/NXDoom/src/net_gui.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Graphical stuff related to the networking code: + * + * * The client waiting screen when we are waiting for the server to + * start the game. + * + ****************************************************************************/ #ifndef NET_GUI_H #define NET_GUI_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -extern void NET_WaitForLaunch(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef NET_GUI_H */ +extern void net_wait_for_launch(void); +#endif /* NET_GUI_H */ diff --git a/games/NXDoom/src/net_io.c b/games/NXDoom/src/net_io.c index 02519afe21d..0c9c4a4fb12 100644 --- a/games/NXDoom/src/net_io.c +++ b/games/NXDoom/src/net_io.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Network packet I/O. Base layer for sending/receiving packets, -// through the network module system -// +/**************************************************************************** + * apps/games/NXDoom/src/net_io.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Network packet I/O. Base layer for sending/receiving packets, + * through the network module system + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -23,125 +32,139 @@ #include "net_io.h" #include "z_zone.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define MAX_MODULES 16 +/**************************************************************************** + * Private Types + ****************************************************************************/ + struct _net_context_s { - net_module_t *modules[MAX_MODULES]; - int num_modules; + net_module_t *modules[MAX_MODULES]; + int num_modules; }; +/**************************************************************************** + * Public Data + ****************************************************************************/ + net_addr_t net_broadcast_addr; -net_context_t *NET_NewContext(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +net_context_t *net_new_context(void) { - net_context_t *context; + net_context_t *context; - context = Z_Malloc(sizeof(net_context_t), PU_STATIC, 0); - context->num_modules = 0; + context = z_malloc(sizeof(net_context_t), PU_STATIC, 0); + context->num_modules = 0; - return context; + return context; } -void NET_AddModule(net_context_t *context, net_module_t *module) +void net_add_module(net_context_t *context, net_module_t *module) { - if (context->num_modules >= MAX_MODULES) + if (context->num_modules >= MAX_MODULES) { - I_Error("NET_AddModule: No more modules for context"); + i_error("net_add_module: No more modules for context"); } - - context->modules[context->num_modules] = module; - ++context->num_modules; + + context->modules[context->num_modules] = module; + ++context->num_modules; } -net_addr_t *NET_ResolveAddress(net_context_t *context, const char *addr) +net_addr_t *net_resolve_address(net_context_t *context, const char *addr) { - int i; - net_addr_t *result; + int i; + net_addr_t *result; - for (i=0; inum_modules; ++i) + for (i = 0; i < context->num_modules; ++i) { - result = context->modules[i]->ResolveAddress(addr); + result = context->modules[i]->resolve_address(addr); - if (result != NULL) + if (result != NULL) { - NET_ReferenceAddress(result); - return result; + net_reference_address(result); + return result; } } - return NULL; + return NULL; } -void NET_SendPacket(net_addr_t *addr, net_packet_t *packet) +void net_send_packet(net_addr_t *addr, net_packet_t *packet) { - addr->module->SendPacket(addr, packet); + addr->module->send_packet(addr, packet); } -void NET_SendBroadcast(net_context_t *context, net_packet_t *packet) +void net_send_broadcast(net_context_t *context, net_packet_t *packet) { - int i; + int i; - for (i=0; inum_modules; ++i) + for (i = 0; i < context->num_modules; ++i) { - context->modules[i]->SendPacket(&net_broadcast_addr, packet); + context->modules[i]->send_packet(&net_broadcast_addr, packet); } } -boolean NET_RecvPacket(net_context_t *context, - net_addr_t **addr, +boolean net_recv_packet(net_context_t *context, net_addr_t **addr, net_packet_t **packet) { - int i; - - // check all modules for new packets - - for (i=0; inum_modules; ++i) + int i; + + /* check all modules for new packets */ + + for (i = 0; i < context->num_modules; ++i) { - if (context->modules[i]->RecvPacket(addr, packet)) + if (context->modules[i]->recv_packet(addr, packet)) { - NET_ReferenceAddress(*addr); - return true; + net_reference_address(*addr); + return true; } } - return false; + return false; } -// Note: this prints into a static buffer, calling again overwrites -// the first result +/* Note: this prints into a static buffer, calling again overwrites + * the first result + */ -char *NET_AddrToString(net_addr_t *addr) +char *net_addr_to_string(net_addr_t *addr) { - static char buf[128]; + static char buf[128]; - addr->module->AddrToString(addr, buf, sizeof(buf) - 1); + addr->module->addr_to_string(addr, buf, sizeof(buf) - 1); - return buf; + return buf; } -void NET_ReferenceAddress(net_addr_t *addr) +void net_reference_address(net_addr_t *addr) { - if (addr == NULL) + if (addr == NULL) { - return; + return; } - ++addr->refcount; - //printf("%s: +refcount=%d\n", NET_AddrToString(addr), addr->refcount); + + ++addr->refcount; } -void NET_ReleaseAddress(net_addr_t *addr) +void net_release_address(net_addr_t *addr) { - if (addr == NULL) + if (addr == NULL) { - return; + return; } - --addr->refcount; - //printf("%s: -refcount=%d\n", NET_AddrToString(addr), addr->refcount); - if (addr->refcount <= 0) + --addr->refcount; + if (addr->refcount <= 0) { - addr->module->FreeAddress(addr); + addr->module->free_address(addr); } } - diff --git a/games/NXDoom/src/net_io.h b/games/NXDoom/src/net_io.h index d61a1eb3d9f..d83d3ace369 100644 --- a/games/NXDoom/src/net_io.h +++ b/games/NXDoom/src/net_io.h @@ -1,61 +1,90 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Network packet manipulation (net_packet_t) -// +/**************************************************************************** + * apps/games/NXDoom/src/net_io.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Network packet manipulation (net_packet_t) + * + ****************************************************************************/ #ifndef NET_IO_H #define NET_IO_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "net_defs.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ + extern net_addr_t net_broadcast_addr; -// Create a new network context. -net_context_t *NET_NewContext(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Create a new network context. */ + +net_context_t *net_new_context(void); + +/* Add a network module to a context. */ + +void net_add_module(net_context_t *context, net_module_t *module); + +/* Send a packet to the given address. */ + +void net_send_packet(net_addr_t *addr, net_packet_t *packet); + +/* Send a broadcast using all modules in the given context. */ + +void net_send_broadcast(net_context_t *context, net_packet_t *packet); + +/* Check all modules in the given context and receive a packet, returning + * true if a packet was received. The result is stored in *packet and the + * source is stored in *addr, with an implicit reference added. The packet + * must be freed by the caller and the reference released. + */ -// Add a network module to a context. -void NET_AddModule(net_context_t *context, net_module_t *module); +boolean net_recv_packet(net_context_t *context, net_addr_t **addr, + net_packet_t **packet); -// Send a packet to the given address. -void NET_SendPacket(net_addr_t *addr, net_packet_t *packet); +/* Return a string representation of the given address. The result points + * to a static buffer and will become invalid with the next call. + */ -// Send a broadcast using all modules in the given context. -void NET_SendBroadcast(net_context_t *context, net_packet_t *packet); +char *net_addr_to_string(net_addr_t *addr); -// Check all modules in the given context and receive a packet, returning true -// if a packet was received. The result is stored in *packet and the source is -// stored in *addr, with an implicit reference added. The packet must be freed -// by the caller and the reference releasd. -boolean NET_RecvPacket(net_context_t *context, net_addr_t **addr, - net_packet_t **packet); +/* Add a reference to the given address. */ -// Return a string representation of the given address. The result points to a -// static buffer and will become invalid with the next call. -char *NET_AddrToString(net_addr_t *addr); +void net_reference_address(net_addr_t *addr); -// Add a reference to the given address. -void NET_ReferenceAddress(net_addr_t *addr); +/* Release a reference to the given address. When there are no more + * references, the address will be freed. + */ -// Release a reference to the given address. When there are no more references, -// the address will be freed. -void NET_ReleaseAddress(net_addr_t *addr); +void net_release_address(net_addr_t *addr); -// Resolve a string representation of an address. If successful, a net_addr_t -// pointer is received with an implicit reference that must be freed by the -// caller when it is no longer needed. -net_addr_t *NET_ResolveAddress(net_context_t *context, const char *address); +/* Resolve a string representation of an address. If successful, a net_addr_t + * pointer is received with an implicit reference that must be freed by the + * caller when it is no longer needed. + */ -#endif /* #ifndef NET_IO_H */ +net_addr_t *net_resolve_address(net_context_t *context, const char *address); +#endif /* NET_IO_H */ diff --git a/games/NXDoom/src/net_loop.c b/games/NXDoom/src/net_loop.c index 65140fa3bc9..d31d29cfc33 100644 --- a/games/NXDoom/src/net_loop.c +++ b/games/NXDoom/src/net_loop.c @@ -1,19 +1,28 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Loopback network module for server compiled into the client -// +/**************************************************************************** + * apps/games/NXDoom/src/net_loop.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Loopback network module for server compiled into the client + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -25,207 +34,239 @@ #include "net_loop.h" #include "net_packet.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define MAX_QUEUE_SIZE 16 +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef struct { - net_packet_t *packets[MAX_QUEUE_SIZE]; - int head, tail; + net_packet_t *packets[MAX_QUEUE_SIZE]; + int head; + int tail; } packet_queue_t; +/**************************************************************************** + * Private Data + ****************************************************************************/ + static packet_queue_t client_queue; static packet_queue_t server_queue; static net_addr_t client_addr; static net_addr_t server_addr; -static void QueueInit(packet_queue_t *queue) +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static boolean net_cl_init_client(void); +static boolean net_cl_init_server(void); +static void net_cl_send_packet(net_addr_t *addr, net_packet_t *packet); +static boolean net_cl_recv_packet(net_addr_t **addr, net_packet_t **packet); +static void net_cl_addr_to_string(net_addr_t *addr, char *buffer, + int buffer_len); +static void net_cl_free_address(net_addr_t *addr); +static net_addr_t *net_cl_resolve_address(const char *address); + +static boolean net_sv_init_client(void); +static boolean net_sv_init_server(void); +static void net_sv_send_packet(net_addr_t *addr, net_packet_t *packet); +static boolean net_sv_recv_packet(net_addr_t **addr, net_packet_t **packet); +static void net_sv_addr_to_string(net_addr_t *addr, char *buffer, + int buffer_len); +static void net_sv_free_address(net_addr_t *addr); +static net_addr_t *net_sv_resolve_address(const char *address); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +net_module_t net_loop_client_module = +{ + net_cl_init_client, net_cl_init_server, net_cl_send_packet, + net_cl_recv_packet, net_cl_addr_to_string, net_cl_free_address, + net_cl_resolve_address, +}; + +net_module_t net_loop_server_module = { - queue->head = queue->tail = 0; + net_sv_init_client, net_sv_init_server, net_sv_send_packet, + net_sv_recv_packet, net_sv_addr_to_string, net_sv_free_address, + net_sv_resolve_address, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void queue_init(packet_queue_t *queue) +{ + queue->head = queue->tail = 0; } -static void QueuePush(packet_queue_t *queue, net_packet_t *packet) +static void queue_push(packet_queue_t *queue, net_packet_t *packet) { - int new_tail; + int new_tail; - new_tail = (queue->tail + 1) % MAX_QUEUE_SIZE; + new_tail = (queue->tail + 1) % MAX_QUEUE_SIZE; - if (new_tail == queue->head) + if (new_tail == queue->head) { - // queue is full - - return; + /* queue is full */ + + return; } - queue->packets[queue->tail] = packet; - queue->tail = new_tail; + queue->packets[queue->tail] = packet; + queue->tail = new_tail; } -static net_packet_t *QueuePop(packet_queue_t *queue) +static net_packet_t *queue_pop(packet_queue_t *queue) { - net_packet_t *packet; - - if (queue->tail == queue->head) + net_packet_t *packet; + + if (queue->tail == queue->head) { - // queue empty + /* queue empty */ - return NULL; + return NULL; } - packet = queue->packets[queue->head]; - queue->head = (queue->head + 1) % MAX_QUEUE_SIZE; + packet = queue->packets[queue->head]; + queue->head = (queue->head + 1) % MAX_QUEUE_SIZE; - return packet; + return packet; } -//----------------------------------------------------------------------------- -// -// Client end code -// -//----------------------------------------------------------------------------- +/**************************************************************************** + * Client-end code + ****************************************************************************/ -static boolean NET_CL_InitClient(void) +static boolean net_cl_init_client(void) { - QueueInit(&client_queue); + queue_init(&client_queue); - return true; + return true; } -static boolean NET_CL_InitServer(void) +static boolean net_cl_init_server(void) { - I_Error("NET_CL_InitServer: attempted to initialize client pipe end as a server!"); - return false; + i_error("NET_CL_init_server: attempted to initialize client pipe end as a " + "server!"); + return false; } -static void NET_CL_SendPacket(net_addr_t *addr, net_packet_t *packet) +static void net_cl_send_packet(net_addr_t *addr, net_packet_t *packet) { - QueuePush(&server_queue, NET_PacketDup(packet)); + queue_push(&server_queue, net_packet_dup(packet)); } -static boolean NET_CL_RecvPacket(net_addr_t **addr, net_packet_t **packet) +static boolean net_cl_recv_packet(net_addr_t **addr, net_packet_t **packet) { - net_packet_t *popped; + net_packet_t *popped; - popped = QueuePop(&client_queue); + popped = queue_pop(&client_queue); - if (popped != NULL) + if (popped != NULL) { - *packet = popped; - *addr = &client_addr; - client_addr.module = &net_loop_client_module; - - return true; + *packet = popped; + *addr = &client_addr; + client_addr.module = &net_loop_client_module; + + return true; } - return false; + return false; } -static void NET_CL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +static void net_cl_addr_to_string(net_addr_t *addr, char *buffer, + int buffer_len) { - M_snprintf(buffer, buffer_len, "local server"); + snprintf(buffer, buffer_len, "local server"); } -static void NET_CL_FreeAddress(net_addr_t *addr) +static void net_cl_free_address(net_addr_t *addr) { } -static net_addr_t *NET_CL_ResolveAddress(const char *address) +static net_addr_t *net_cl_resolve_address(const char *address) { - if (address == NULL) + if (address == NULL) { - client_addr.module = &net_loop_client_module; + client_addr.module = &net_loop_client_module; - return &client_addr; + return &client_addr; } - else + else { - return NULL; + return NULL; } } -net_module_t net_loop_client_module = -{ - NET_CL_InitClient, - NET_CL_InitServer, - NET_CL_SendPacket, - NET_CL_RecvPacket, - NET_CL_AddrToString, - NET_CL_FreeAddress, - NET_CL_ResolveAddress, -}; - -//----------------------------------------------------------------------------- -// -// Server end code -// -//----------------------------------------------------------------------------- +/**************************************************************************** + * Server-end code + ****************************************************************************/ -static boolean NET_SV_InitClient(void) +static boolean net_sv_init_client(void) { - I_Error("NET_SV_InitClient: attempted to initialize server pipe end as a client!"); - return false; + i_error("net_sv_initClient: attempted to initialize server pipe end as a " + "client!"); + return false; } -static boolean NET_SV_InitServer(void) +static boolean net_sv_init_server(void) { - QueueInit(&server_queue); - - return true; + queue_init(&server_queue); + return true; } -static void NET_SV_SendPacket(net_addr_t *addr, net_packet_t *packet) +static void net_sv_send_packet(net_addr_t *addr, net_packet_t *packet) { - QueuePush(&client_queue, NET_PacketDup(packet)); + queue_push(&client_queue, net_packet_dup(packet)); } -static boolean NET_SV_RecvPacket(net_addr_t **addr, net_packet_t **packet) +static boolean net_sv_recv_packet(net_addr_t **addr, net_packet_t **packet) { - net_packet_t *popped; + net_packet_t *popped; - popped = QueuePop(&server_queue); + popped = queue_pop(&server_queue); - if (popped != NULL) + if (popped != NULL) { - *packet = popped; - *addr = &server_addr; - server_addr.module = &net_loop_server_module; - - return true; + *packet = popped; + *addr = &server_addr; + server_addr.module = &net_loop_server_module; + + return true; } - return false; + return false; } -static void NET_SV_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +static void net_sv_addr_to_string(net_addr_t *addr, char *buffer, + int buffer_len) { - M_snprintf(buffer, buffer_len, "local client"); + snprintf(buffer, buffer_len, "local client"); } -static void NET_SV_FreeAddress(net_addr_t *addr) +static void net_sv_free_address(net_addr_t *addr) { } -static net_addr_t *NET_SV_ResolveAddress(const char *address) +static net_addr_t *net_sv_resolve_address(const char *address) { - if (address == NULL) + if (address == NULL) { - server_addr.module = &net_loop_server_module; - return &server_addr; + server_addr.module = &net_loop_server_module; + return &server_addr; } - else + else { - return NULL; + return NULL; } } - -net_module_t net_loop_server_module = -{ - NET_SV_InitClient, - NET_SV_InitServer, - NET_SV_SendPacket, - NET_SV_RecvPacket, - NET_SV_AddrToString, - NET_SV_FreeAddress, - NET_SV_ResolveAddress, -}; - - diff --git a/games/NXDoom/src/net_loop.h b/games/NXDoom/src/net_loop.h index 5a2e58ee1c9..222660ffc94 100644 --- a/games/NXDoom/src/net_loop.h +++ b/games/NXDoom/src/net_loop.h @@ -1,27 +1,39 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Loopback network module for server compiled into the client -// +/**************************************************************************** + * apps/games/NXDoom/src/net_loop.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Loopback network module for server compiled into the client + * + ****************************************************************************/ #ifndef NET_LOOP_H #define NET_LOOP_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "net_defs.h" +/**************************************************************************** + * Public Data + ****************************************************************************/ + extern net_module_t net_loop_client_module; extern net_module_t net_loop_server_module; -#endif /* #ifndef NET_LOOP_H */ - +#endif /* NET_LOOP_H */ diff --git a/games/NXDoom/src/net_packet.c b/games/NXDoom/src/net_packet.c index 23bfda675e5..d7a57e1e2b3 100644 --- a/games/NXDoom/src/net_packet.c +++ b/games/NXDoom/src/net_packet.c @@ -1,328 +1,357 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Network packet manipulation (net_packet_t) -// +/**************************************************************************** + * apps/games/NXDoom/src/net_packet.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Network packet manipulation (net_packet_t) + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include -#include -#include "m_misc.h" #include "net_packet.h" +#include "m_misc.h" #include "z_zone.h" +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int g_total_packet_memory = 0; -static int total_packet_memory = 0; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -net_packet_t *NET_NewPacket(int initial_size) +/* Dynamically increases the size of a packet */ + +static void net_increase_packet(net_packet_t *packet) { - net_packet_t *packet; + byte *newdata; + + g_total_packet_memory -= packet->alloced; - packet = (net_packet_t *) Z_Malloc(sizeof(net_packet_t), PU_STATIC, 0); - - if (initial_size == 0) - initial_size = 256; + packet->alloced *= 2; - packet->alloced = initial_size; - packet->data = Z_Malloc(initial_size, PU_STATIC, 0); - packet->len = 0; - packet->pos = 0; + newdata = z_malloc(packet->alloced, PU_STATIC, 0); - total_packet_memory += sizeof(net_packet_t) + initial_size; + memcpy(newdata, packet->data, packet->len); - //printf("total packet memory: %i bytes\n", total_packet_memory); - //printf("%p: allocated\n", packet); + z_free(packet->data); + packet->data = newdata; + + g_total_packet_memory += packet->alloced; +} + +#if 0 /* Unused */ +static boolean net_read_sint32(net_packet_t *packet, signed int *data) +{ + if (net_read_int32(packet, (unsigned int *)data)) + { + if (*data & (1U << 31)) + { + *data &= ~(1U << 31); + *data -= (1U << 31); + } - return packet; + return true; + } + else + { + return false; + } } +#endif -// duplicates an existing packet +/**************************************************************************** + * Public Functions + ****************************************************************************/ -net_packet_t *NET_PacketDup(net_packet_t *packet) +net_packet_t *net_new_packet(int initial_size) { - net_packet_t *newpacket; + net_packet_t *packet; + + packet = (net_packet_t *)z_malloc(sizeof(net_packet_t), PU_STATIC, 0); + + if (initial_size == 0) initial_size = 256; + + packet->alloced = initial_size; + packet->data = z_malloc(initial_size, PU_STATIC, 0); + packet->len = 0; + packet->pos = 0; - newpacket = NET_NewPacket(packet->len); - memcpy(newpacket->data, packet->data, packet->len); - newpacket->len = packet->len; + g_total_packet_memory += sizeof(net_packet_t) + initial_size; - return newpacket; + /* printf("total packet memory: %i bytes\n", total_packet_memory); + * printf("%p: allocated\n", packet); + */ + + return packet; } -void NET_FreePacket(net_packet_t *packet) +/* duplicates an existing packet */ + +net_packet_t *net_packet_dup(net_packet_t *packet) { - //printf("%p: destroyed\n", packet); - - total_packet_memory -= sizeof(net_packet_t) + packet->alloced; - Z_Free(packet->data); - Z_Free(packet); + net_packet_t *newpacket; + + newpacket = net_new_packet(packet->len); + memcpy(newpacket->data, packet->data, packet->len); + newpacket->len = packet->len; + + return newpacket; } -// Read a byte from the packet, returning true if read -// successfully +void net_free_packet(net_packet_t *packet) +{ + /* printf("%p: destroyed\n", packet); */ + + g_total_packet_memory -= sizeof(net_packet_t) + packet->alloced; + z_free(packet->data); + z_free(packet); +} -boolean NET_ReadInt8(net_packet_t *packet, unsigned int *data) +/* Read a byte from the packet, returning true if read + * successfully + */ + +boolean net_read_int8(net_packet_t *packet, unsigned int *data) { - if (packet->pos + 1 > packet->len) - return false; + if (packet->pos + 1 > packet->len) return false; - *data = packet->data[packet->pos]; + *data = packet->data[packet->pos]; - packet->pos += 1; + packet->pos += 1; - return true; + return true; } -// Read a 16-bit integer from the packet, returning true if read -// successfully +/* Read a 16-bit integer from the packet, returning true if read + * successfully + */ -boolean NET_ReadInt16(net_packet_t *packet, unsigned int *data) +boolean net_read_int16(net_packet_t *packet, unsigned int *data) { - byte *p; + byte *p; - if (packet->pos + 2 > packet->len) - return false; + if (packet->pos + 2 > packet->len) return false; - p = packet->data + packet->pos; + p = packet->data + packet->pos; - *data = (p[0] << 8) | p[1]; - packet->pos += 2; + *data = (p[0] << 8) | p[1]; + packet->pos += 2; - return true; + return true; } -// Read a 32-bit integer from the packet, returning true if read -// successfully +/* Read a 32-bit integer from the packet, returning true if read + * successfully + */ -boolean NET_ReadInt32(net_packet_t *packet, unsigned int *data) +boolean net_read_int32(net_packet_t *packet, unsigned int *data) { - byte *p; + byte *p; + + if (packet->pos + 4 > packet->len) return false; - if (packet->pos + 4 > packet->len) - return false; + p = packet->data + packet->pos; - p = packet->data + packet->pos; + *data = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + packet->pos += 4; - *data = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - packet->pos += 4; - - return true; + return true; } -// Signed read functions +/* Signed read functions */ -boolean NET_ReadSInt8(net_packet_t *packet, signed int *data) +boolean net_read_sint8(net_packet_t *packet, signed int *data) { - if (NET_ReadInt8(packet,(unsigned int *) data)) + if (net_read_int8(packet, (unsigned int *)data)) { - if (*data & (1 << 7)) + if (*data & (1 << 7)) { - *data &= ~(1 << 7); - *data -= (1 << 7); + *data &= ~(1 << 7); + *data -= (1 << 7); } - return true; - } - else - { - return false; - } -} -boolean NET_ReadSInt16(net_packet_t *packet, signed int *data) -{ - if (NET_ReadInt16(packet, (unsigned int *) data)) - { - if (*data & (1 << 15)) - { - *data &= ~(1 << 15); - *data -= (1 << 15); - } - return true; + return true; } - else + else { - return false; + return false; } } -boolean NET_ReadSInt32(net_packet_t *packet, signed int *data) +boolean net_read_sint16(net_packet_t *packet, signed int *data) { - if (NET_ReadInt32(packet, (unsigned int *) data)) + if (net_read_int16(packet, (unsigned int *)data)) { - if (*data & (1U << 31)) + if (*data & (1 << 15)) { - *data &= ~(1U << 31); - *data -= (1U << 31); + *data &= ~(1 << 15); + *data -= (1 << 15); } - return true; + + return true; } - else + else { - return false; + return false; } } -// Read a string from the packet. Returns NULL if a terminating -// NUL character was not found before the end of the packet. +/* Read a string from the packet. Returns NULL if a terminating + * NUL character was not found before the end of the packet. + */ -char *NET_ReadString(net_packet_t *packet) +char *net_read_string(net_packet_t *packet) { - char *start; + char *start; - start = (char *) packet->data + packet->pos; + start = (char *)packet->data + packet->pos; - // Search forward for a NUL character + /* Search forward for a NUL character */ - while (packet->pos < packet->len && packet->data[packet->pos] != '\0') + while (packet->pos < packet->len && packet->data[packet->pos] != '\0') { - ++packet->pos; + ++packet->pos; } - if (packet->pos >= packet->len) + if (packet->pos >= packet->len) { - // Reached the end of the packet + /* Reached the end of the packet */ - return NULL; + return NULL; } - // packet->data[packet->pos] == '\0': We have reached a terminating - // NULL. Skip past this NULL and continue reading immediately - // after it. + /* packet->data[packet->pos] == '\0': We have reached a terminating + * NULL. Skip past this NULL and continue reading immediately + * after it. + */ + + ++packet->pos; - ++packet->pos; - - return start; + return start; } -// Read a string from the packet, but (potentially) modify it to strip -// out any unprintable characters which could be malicious control codes. -// Note that this may modify the original packet contents. -char *NET_ReadSafeString(net_packet_t *packet) +/* Read a string from the packet, but (potentially) modify it to strip + * out any unprintable characters which could be malicious control codes. + * Note that this may modify the original packet contents. + */ + +char *net_read_safe_string(net_packet_t *packet) { - char *r, *w, *result; + char *r; + char *w; + char *result; - result = NET_ReadString(packet); - if (result == NULL) + result = net_read_string(packet); + if (result == NULL) { - return NULL; + return NULL; } - // w is always <= r, so we never produce a longer string than the original. - w = result; - for (r = result; *r != '\0'; ++r) + /* w is always <= r, so we never produce a longer string than the original. + */ + + w = result; + for (r = result; *r != '\0'; ++r) { - // TODO: This is a very naive way of producing a safe string; only - // ASCII characters are allowed. Probably this should really support - // UTF-8 characters as well. - if (isprint(*r) || *r == '\n') + /* TODO: This is a very naive way of producing a safe string; only + * ASCII characters are allowed. Probably this should really support + * UTF-8 characters as well. + */ + + if (isprint(*r) || *r == '\n') { - *w = *r; - ++w; + *w = *r; + ++w; } } - *w = '\0'; - return result; -} - -// Dynamically increases the size of a packet - -static void NET_IncreasePacket(net_packet_t *packet) -{ - byte *newdata; - - total_packet_memory -= packet->alloced; - - packet->alloced *= 2; - - newdata = Z_Malloc(packet->alloced, PU_STATIC, 0); - - memcpy(newdata, packet->data, packet->len); + *w = '\0'; - Z_Free(packet->data); - packet->data = newdata; - - total_packet_memory += packet->alloced; + return result; } -// Write a single byte to the packet +/* Write a single byte to the packet */ -void NET_WriteInt8(net_packet_t *packet, unsigned int i) +void net_write_int8(net_packet_t *packet, unsigned int i) { - if (packet->len + 1 > packet->alloced) - NET_IncreasePacket(packet); + if (packet->len + 1 > packet->alloced) net_increase_packet(packet); - packet->data[packet->len] = i; - packet->len += 1; + packet->data[packet->len] = i; + packet->len += 1; } -// Write a 16-bit integer to the packet +/* Write a 16-bit integer to the packet */ -void NET_WriteInt16(net_packet_t *packet, unsigned int i) +void net_write_int16(net_packet_t *packet, unsigned int i) { - byte *p; - - if (packet->len + 2 > packet->alloced) - NET_IncreasePacket(packet); + byte *p; - p = packet->data + packet->len; + if (packet->len + 2 > packet->alloced) net_increase_packet(packet); - p[0] = (i >> 8) & 0xff; - p[1] = i & 0xff; + p = packet->data + packet->len; - packet->len += 2; -} + p[0] = (i >> 8) & 0xff; + p[1] = i & 0xff; + packet->len += 2; +} -// Write a single byte to the packet +/* Write a single byte to the packet */ -void NET_WriteInt32(net_packet_t *packet, unsigned int i) +void net_write_int32(net_packet_t *packet, unsigned int i) { - byte *p; + byte *p; - if (packet->len + 4 > packet->alloced) - NET_IncreasePacket(packet); + if (packet->len + 4 > packet->alloced) net_increase_packet(packet); - p = packet->data + packet->len; + p = packet->data + packet->len; - p[0] = (i >> 24) & 0xff; - p[1] = (i >> 16) & 0xff; - p[2] = (i >> 8) & 0xff; - p[3] = i & 0xff; + p[0] = (i >> 24) & 0xff; + p[1] = (i >> 16) & 0xff; + p[2] = (i >> 8) & 0xff; + p[3] = i & 0xff; - packet->len += 4; + packet->len += 4; } -void NET_WriteString(net_packet_t *packet, const char *string) +void net_write_string(net_packet_t *packet, const char *string) { - byte *p; - size_t string_size; + byte *p; + size_t string_size; - string_size = strlen(string) + 1; + string_size = strlen(string) + 1; - // Increase the packet size until large enough to hold the string + /* Increase the packet size until large enough to hold the string */ - while (packet->len + string_size > packet->alloced) + while (packet->len + string_size > packet->alloced) { - NET_IncreasePacket(packet); + net_increase_packet(packet); } - p = packet->data + packet->len; + p = packet->data + packet->len; - M_StringCopy((char *) p, string, string_size); + m_str_copy((char *)p, string, string_size); - packet->len += string_size; + packet->len += string_size; } - - - - diff --git a/games/NXDoom/src/net_packet.h b/games/NXDoom/src/net_packet.h index 6beb44b2aac..f2d412b95e3 100644 --- a/games/NXDoom/src/net_packet.h +++ b/games/NXDoom/src/net_packet.h @@ -1,45 +1,56 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Definitions for use in networking code. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_packet.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Definitions for use in networking code. + * + ****************************************************************************/ #ifndef NET_PACKET_H #define NET_PACKET_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "net_defs.h" -net_packet_t *NET_NewPacket(int initial_size); -net_packet_t *NET_PacketDup(net_packet_t *packet); -void NET_FreePacket(net_packet_t *packet); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -boolean NET_ReadInt8(net_packet_t *packet, unsigned int *data); -boolean NET_ReadInt16(net_packet_t *packet, unsigned int *data); -boolean NET_ReadInt32(net_packet_t *packet, unsigned int *data); +net_packet_t *net_new_packet(int initial_size); +net_packet_t *net_packet_dup(net_packet_t *packet); +void net_free_packet(net_packet_t *packet); -boolean NET_ReadSInt8(net_packet_t *packet, signed int *data); -boolean NET_ReadSInt16(net_packet_t *packet, signed int *data); -boolean NET_ReadSInt32(net_packet_t *packet, signed int *data); +boolean net_read_int8(net_packet_t *packet, unsigned int *data); +boolean net_read_int16(net_packet_t *packet, unsigned int *data); +boolean net_read_int32(net_packet_t *packet, unsigned int *data); -char *NET_ReadString(net_packet_t *packet); -char *NET_ReadSafeString(net_packet_t *packet); +boolean net_read_sint8(net_packet_t *packet, signed int *data); +boolean net_read_sint16(net_packet_t *packet, signed int *data); -void NET_WriteInt8(net_packet_t *packet, unsigned int i); -void NET_WriteInt16(net_packet_t *packet, unsigned int i); -void NET_WriteInt32(net_packet_t *packet, unsigned int i); +char *net_read_string(net_packet_t *packet); +char *net_read_safe_string(net_packet_t *packet); -void NET_WriteString(net_packet_t *packet, const char *string); +void net_write_int8(net_packet_t *packet, unsigned int i); +void net_write_int16(net_packet_t *packet, unsigned int i); +void net_write_int32(net_packet_t *packet, unsigned int i); -#endif /* #ifndef NET_PACKET_H */ +void net_write_string(net_packet_t *packet, const char *string); +#endif /* NET_PACKET_H */ diff --git a/games/NXDoom/src/net_petname.c b/games/NXDoom/src/net_petname.c deleted file mode 100644 index db6600db6a2..00000000000 --- a/games/NXDoom/src/net_petname.c +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright(C) 2019 Jonathan Dowland -// -// 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. -// -// DESCRIPTION: -// Generate a randomized, private, memorable name for a Player -// - -#include -#include -#include "doomtype.h" -#include "m_misc.h" - -static const char * const adjectives [] = { - "Grumpy", - "Ecstatic", - "Surly", - "Prepared", - "Crafty", - "Alert", - "Sluggish", - "Testy", - "Reluctant", - "Languid", - "Passive", - "Pacifist", - "Aggressive", - "Hostile", - "Bubbly", - "Giggly", - "Laughing", - "Crying", - "Frowning", - "Torpid", - "Lethargic", - "Manic", - "Patient", - "Protective", - "Philosophical", - "Enquiring", - "Debating", - "Furious", - "Laid-Back", - "Easy-Going", - "Cromulent", - "Excitable", - "Tired", - "Exhausted", - "Ruminating", - "Redundant", - "Sporty", - "Ginger", - "Scary", - "Posh", - "Baby", -}; - -static const char * const nouns[] = { - "Frad", - // Doom - "Cacodemon", - "Arch-Vile", - "Cyberdemon", - "Imp", - "Demon", - "Mancubus", - "Arachnotron", - "Baron", - "Knight", - "Revenant", - // Hexen - "Ettin", - "Maulotaur", - "Centaur", - "Afrit", - "Serpent", - // Heretic - "Disciple", - "Gargoyle", - "Golem", - "Lich", - // Strife - "Sentinel", - "Acolyte", - "Templar", - "Reaver", - "Spectre", -}; - -/* - * ideally we would export this and the caller would invoke it during - * their setup routine. But, the two callers only invoke getRandomPetName - * once, so the initialization might as well occur then. - */ -static void InitPetName() -{ - srand((unsigned int)time(NULL)); -} - -char *NET_GetRandomPetName() -{ - const char *a, *n; - - InitPetName(); - a = adjectives[rand() % arrlen(adjectives)]; - n = nouns[rand() % arrlen(nouns)]; - - return M_StringJoin(a, " ", n, NULL); -} diff --git a/games/NXDoom/src/net_petname.h b/games/NXDoom/src/net_petname.h deleted file mode 100644 index 29225074402..00000000000 --- a/games/NXDoom/src/net_petname.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright(C) 2019 Jonathan Dowland -// -// 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. -// -// DESCRIPTION: -// Generate a randomized, private, memorable name for a Player -// - -char *NET_GetRandomPetName(); diff --git a/games/NXDoom/src/net_query.c b/games/NXDoom/src/net_query.c index d9c8b2d96f1..ea80d8ccd14 100644 --- a/games/NXDoom/src/net_query.c +++ b/games/NXDoom/src/net_query.c @@ -1,22 +1,31 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Querying servers to find their current status. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_query.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Querying servers to find their current status. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include #include +#include #include #include @@ -29,978 +38,1026 @@ #include "net_io.h" #include "net_packet.h" #include "net_query.h" -#include "net_structrw.h" #include "net_sdl.h" +#include "net_structrw.h" -// DNS address of the Internet master server. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* DNS address of the Internet master server. */ #define MASTER_SERVER_ADDRESS "master.chocolate-doom.org:2342" -// Time to wait for a response before declaring a timeout. +/* Time to wait for a response before declaring a timeout. */ #define QUERY_TIMEOUT_SECS 2 -// Time to wait for secure demo signatures before declaring a timeout. +/* Time to wait for secure demo signatures before declaring a timeout. */ #define SIGNATURE_TIMEOUT_SECS 5 -// Number of query attempts to make before giving up on a server. +/* Number of query attempts to make before giving up on a server. */ #define QUERY_MAX_ATTEMPTS 3 +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef enum { - QUERY_TARGET_SERVER, // Normal server target. - QUERY_TARGET_MASTER, // The master server. - QUERY_TARGET_BROADCAST // Send a broadcast query + QUERY_TARGET_SERVER, /* Normal server target. */ + QUERY_TARGET_MASTER, /* The master server. */ + QUERY_TARGET_BROADCAST /* Send a broadcast query */ } query_target_type_t; typedef enum { - QUERY_TARGET_QUEUED, // Query not yet sent - QUERY_TARGET_QUERIED, // Query sent, waiting response - QUERY_TARGET_RESPONDED, // Response received - QUERY_TARGET_NO_RESPONSE + QUERY_TARGET_QUEUED, /* Query not yet sent */ + QUERY_TARGET_QUERIED, /* Query sent, waiting response */ + QUERY_TARGET_RESPONDED, /* Response received */ + QUERY_TARGET_NO_RESPONSE } query_target_state_t; typedef struct { - query_target_type_t type; - query_target_state_t state; - net_addr_t *addr; - net_querydata_t data; - unsigned int ping_time; - unsigned int query_time; - unsigned int query_attempts; - boolean printed; + query_target_type_t type; + query_target_state_t state; + net_addr_t *addr; + net_querydata_t data; + unsigned int ping_time; + unsigned int query_time; + unsigned int query_attempts; + boolean printed; } query_target_t; -static boolean registered_with_master = false; -static boolean got_master_response = false; +/**************************************************************************** + * Private Data + ****************************************************************************/ -static net_context_t *query_context; -static query_target_t *targets; -static int num_targets; +static boolean g_registered_with_master = false; +static boolean g_got_master_response = false; -static boolean query_loop_running = false; -static boolean printed_header = false; -static int last_query_time = 0; +static net_context_t *g_query_context; +static query_target_t *g_targets; +static int g_num_targets; -static char *securedemo_start_message = NULL; +static boolean g_query_loop_running = false; +static boolean g_printed_header = false; +static int g_last_query_time = 0; -// Resolve the master server address. +#if 0 +static char *g_securedemo_start_message = NULL; +#endif -net_addr_t *NET_Query_ResolveMaster(net_context_t *context) -{ - net_addr_t *addr; - - addr = NET_ResolveAddress(context, MASTER_SERVER_ADDRESS); - - if (addr == NULL) - { - fprintf(stderr, "Warning: Failed to resolve address " - "for master server: %s\n", MASTER_SERVER_ADDRESS); - } - - return addr; -} +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ -// Send a registration packet to the master server to register -// ourselves with the global list. - -void NET_Query_AddToMaster(net_addr_t *master_addr) -{ - net_packet_t *packet; - - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_ADD); - NET_SendPacket(master_addr, packet); - NET_FreePacket(packet); -} - -// Process a packet received from the master server. - -void NET_Query_AddResponse(net_packet_t *packet) -{ - unsigned int result; - - if (!NET_ReadInt16(packet, &result)) - { - return; - } - - if (result != 0) - { - // Only show the message once. - - if (!registered_with_master) - { - printf("Registered with master server at %s\n", - MASTER_SERVER_ADDRESS); - registered_with_master = true; - } - } - else - { - // Always show rejections. - - printf("Failed to register with master server at %s\n", - MASTER_SERVER_ADDRESS); - } - - got_master_response = true; -} - -boolean NET_Query_CheckAddedToMaster(boolean *result) -{ - // Got response from master yet? - - if (!got_master_response) - { - return false; - } - - *result = registered_with_master; - return true; -} - -// Send a query to the master server. - -static void NET_Query_SendMasterQuery(net_addr_t *addr) -{ - net_packet_t *packet; +static void formatted_printf(int wide, const char *s, ...) PRINTF_ATTR(2, 3); - packet = NET_NewPacket(4); - NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_QUERY); - NET_SendPacket(addr, packet); - NET_FreePacket(packet); +/**************************************************************************** + * Private Functions + ****************************************************************************/ - // We also send a NAT_HOLE_PUNCH_ALL packet so that servers behind - // NAT gateways will open themselves up to us. - packet = NET_NewPacket(4); - NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL); - NET_SendPacket(addr, packet); - NET_FreePacket(packet); -} +/* Send a query to the master server. */ -// Send a hole punch request to the master server for the server at the -// given address. -void NET_RequestHolePunch(net_context_t *context, net_addr_t *addr) +static void net_query_send_master_query(net_addr_t *addr) { - net_addr_t *master_addr; - net_packet_t *packet; + net_packet_t *packet; - master_addr = NET_Query_ResolveMaster(context); - if (master_addr == NULL) - { - return; - } + packet = net_new_packet(4); + net_write_int16(packet, NET_MASTER_PACKET_TYPE_QUERY); + net_send_packet(addr, packet); + net_free_packet(packet); - packet = NET_NewPacket(32); - NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH); - NET_WriteString(packet, NET_AddrToString(addr)); - NET_SendPacket(master_addr, packet); + /* We also send a NAT_HOLE_PUNCH_ALL packet so that servers behind + * NAT gateways will open themselves up to us. + */ - NET_FreePacket(packet); - NET_ReleaseAddress(master_addr); + packet = net_new_packet(4); + net_write_int16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH_ALL); + net_send_packet(addr, packet); + net_free_packet(packet); } -// Given the specified address, find the target associated. If no -// target is found, and 'create' is true, a new target is created. +/* Given the specified address, find the target associated. If no + * target is found, and 'create' is true, a new target is created. + */ -static query_target_t *GetTargetForAddr(net_addr_t *addr, boolean create) +static query_target_t *get_target_for_addr(net_addr_t *addr, boolean create) { - query_target_t *target; - int i; + query_target_t *target; + int i; - for (i=0; itype = QUERY_TARGET_SERVER; - target->state = QUERY_TARGET_QUEUED; - target->printed = false; - target->query_attempts = 0; - target->addr = addr; - NET_ReferenceAddress(addr); - ++num_targets; + target = &g_targets[g_num_targets]; + target->type = QUERY_TARGET_SERVER; + target->state = QUERY_TARGET_QUEUED; + target->printed = false; + target->query_attempts = 0; + target->addr = addr; + net_reference_address(addr); + ++g_num_targets; - return target; + return target; } -static void FreeTargets(void) +static void free_targets(void) { - int i; + int i; - for (i = 0; i < num_targets; ++i) + for (i = 0; i < g_num_targets; ++i) { - NET_ReleaseAddress(targets[i].addr); + net_release_address(g_targets[i].addr); } - free(targets); - targets = NULL; - num_targets = 0; + + free(g_targets); + g_targets = NULL; + g_num_targets = 0; } -// Transmit a query packet +/* Transmit a query packet */ -static void NET_Query_SendQuery(net_addr_t *addr) +static void net_query_send_query(net_addr_t *addr) { - net_packet_t *request; + net_packet_t *request; - request = NET_NewPacket(10); - NET_WriteInt16(request, NET_PACKET_TYPE_QUERY); + request = net_new_packet(10); + net_write_int16(request, NET_PACKET_TYPE_QUERY); - if (addr == NULL) + if (addr == NULL) { - NET_SendBroadcast(query_context, request); + net_send_broadcast(g_query_context, request); } - else + else { - NET_SendPacket(addr, request); + net_send_packet(addr, request); } - NET_FreePacket(request); + net_free_packet(request); } -static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet, - net_query_callback_t callback, - void *user_data) +static void net_query_parse_response(net_addr_t *addr, net_packet_t *packet, + net_query_callback_t callback, + void *user_data) { - unsigned int packet_type; - net_querydata_t querydata; - query_target_t *target; + unsigned int packet_type; + net_querydata_t querydata; + query_target_t *target; - // Read the header + /* Read the header */ - if (!NET_ReadInt16(packet, &packet_type) - || packet_type != NET_PACKET_TYPE_QUERY_RESPONSE) + if (!net_read_int16(packet, &packet_type) || + packet_type != NET_PACKET_TYPE_QUERY_RESPONSE) { - return; + return; } - // Read query data + /* Read query data */ - if (!NET_ReadQueryData(packet, &querydata)) + if (!net_read_query_data(packet, &querydata)) { - return; + return; } - // Find the target that responded. + /* Find the target that responded. */ - target = GetTargetForAddr(addr, false); + target = get_target_for_addr(addr, false); - // If the target is not found, it may be because we are doing - // a LAN broadcast search, in which case we need to create a - // target for the new responder. + /* If the target is not found, it may be because we are doing + * a LAN broadcast search, in which case we need to create a + * target for the new responder. + */ - if (target == NULL) + if (target == NULL) { - query_target_t *broadcast_target; + query_target_t *broadcast_target; - broadcast_target = GetTargetForAddr(NULL, false); + broadcast_target = get_target_for_addr(NULL, false); - // Not in broadcast mode, unexpected response that came out - // of nowhere. Ignore. + /* Not in broadcast mode, unexpected response that came out + * of nowhere. Ignore. + */ - if (broadcast_target == NULL - || broadcast_target->state != QUERY_TARGET_QUERIED) + if (broadcast_target == NULL || + broadcast_target->state != QUERY_TARGET_QUERIED) { - return; + return; } - // Create new target. + /* Create new target. */ - target = GetTargetForAddr(addr, true); - broadcast_target = GetTargetForAddr(NULL, false); - target->state = QUERY_TARGET_QUERIED; - target->query_time = broadcast_target->query_time; + target = get_target_for_addr(addr, true); + broadcast_target = get_target_for_addr(NULL, false); + target->state = QUERY_TARGET_QUERIED; + target->query_time = broadcast_target->query_time; } - if (target->state != QUERY_TARGET_RESPONDED) + if (target->state != QUERY_TARGET_RESPONDED) { - target->state = QUERY_TARGET_RESPONDED; - memcpy(&target->data, &querydata, sizeof(net_querydata_t)); + target->state = QUERY_TARGET_RESPONDED; + memcpy(&target->data, &querydata, sizeof(net_querydata_t)); - // Calculate RTT. + /* Calculate RTT. */ - target->ping_time = I_GetTimeMS() - target->query_time; + target->ping_time = i_get_time_ms() - target->query_time; - // Invoke callback to signal that we have a new address. + /* Invoke callback to signal that we have a new address. */ - callback(addr, &target->data, target->ping_time, user_data); + callback(addr, &target->data, target->ping_time, user_data); } } -// Parse a response packet from the master server. +/* Parse a response packet from the master server. */ -static void NET_Query_ParseMasterResponse(net_addr_t *master_addr, - net_packet_t *packet) +static void net_query_parse_master_response(net_addr_t *master_addr, + net_packet_t *packet) { - unsigned int packet_type; - query_target_t *target; - char *addr_str; - net_addr_t *addr; + unsigned int packet_type; + query_target_t *target; + char *addr_str; + net_addr_t *addr; - // Read the header. We are only interested in query responses. + /* Read the header. We are only interested in query responses. */ - if (!NET_ReadInt16(packet, &packet_type) - || packet_type != NET_MASTER_PACKET_TYPE_QUERY_RESPONSE) + if (!net_read_int16(packet, &packet_type) || + packet_type != NET_MASTER_PACKET_TYPE_QUERY_RESPONSE) { - return; + return; } - // Read a list of strings containing the addresses of servers - // that the master knows about. + /* Read a list of strings containing the addresses of servers + * that the master knows about. + */ - for (;;) + for (; ; ) { - addr_str = NET_ReadString(packet); + addr_str = net_read_string(packet); - if (addr_str == NULL) + if (addr_str == NULL) { - break; + break; } - // Resolve address and add to targets list if it is not already - // there. + /* Resolve address and add to targets list if it is not already + * there. + */ - addr = NET_ResolveAddress(query_context, addr_str); - if (addr != NULL) + addr = net_resolve_address(g_query_context, addr_str); + if (addr != NULL) { - GetTargetForAddr(addr, true); - NET_ReleaseAddress(addr); + get_target_for_addr(addr, true); + net_release_address(addr); } } - // Mark the master as having responded. + /* Mark the master as having responded. */ - target = GetTargetForAddr(master_addr, true); - target->state = QUERY_TARGET_RESPONDED; + target = get_target_for_addr(master_addr, true); + target->state = QUERY_TARGET_RESPONDED; } -static void NET_Query_ParsePacket(net_addr_t *addr, net_packet_t *packet, - net_query_callback_t callback, - void *user_data) +static void net_query_parse_packet(net_addr_t *addr, net_packet_t *packet, + net_query_callback_t callback, + void *user_data) { - query_target_t *target; + query_target_t *target; - // This might be the master server responding. + /* This might be the master server responding. */ - target = GetTargetForAddr(addr, false); + target = get_target_for_addr(addr, false); - if (target != NULL && target->type == QUERY_TARGET_MASTER) + if (target != NULL && target->type == QUERY_TARGET_MASTER) { - NET_Query_ParseMasterResponse(addr, packet); + net_query_parse_master_response(addr, packet); } - else + else { - NET_Query_ParseResponse(addr, packet, callback, user_data); + net_query_parse_response(addr, packet, callback, user_data); } } -static void NET_Query_GetResponse(net_query_callback_t callback, - void *user_data) +static void net_query_get_response(net_query_callback_t callback, + void *user_data) { - net_addr_t *addr; - net_packet_t *packet; + net_addr_t *addr; + net_packet_t *packet; - if (NET_RecvPacket(query_context, &addr, &packet)) + if (net_recv_packet(g_query_context, &addr, &packet)) { - NET_Query_ParsePacket(addr, packet, callback, user_data); - NET_ReleaseAddress(addr); - NET_FreePacket(packet); + net_query_parse_packet(addr, packet, callback, user_data); + net_release_address(addr); + net_free_packet(packet); } } -// Find a target we have not yet queried and send a query. +/* Find a target we have not yet queried and send a query. */ -static void SendOneQuery(void) +static void send_one_query(void) { - unsigned int now; - unsigned int i; + unsigned int now; + unsigned int i; - now = I_GetTimeMS(); + now = i_get_time_ms(); - // Rate limit - only send one query every 50ms. + /* Rate limit - only send one query every 50ms. */ - if (now - last_query_time < 50) + if (now - g_last_query_time < 50) { - return; + return; } - for (i = 0; i < num_targets; ++i) + for (i = 0; i < g_num_targets; ++i) { - // Not queried yet? - // Or last query timed out without a response? + /* Not queried yet? + * Or last query timed out without a response? + */ - if (targets[i].state == QUERY_TARGET_QUEUED - || (targets[i].state == QUERY_TARGET_QUERIED - && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000)) + if (g_targets[i].state == QUERY_TARGET_QUEUED || + (g_targets[i].state == QUERY_TARGET_QUERIED && + now - g_targets[i].query_time > QUERY_TIMEOUT_SECS * 1000)) { - break; + break; } } - if (i >= num_targets) + if (i >= g_num_targets) { - return; + return; } - // Found a target to query. Send a query; how to do this depends on - // the target type. + /* Found a target to query. Send a query; how to do this depends on + * the target type. + */ - switch (targets[i].type) + switch (g_targets[i].type) { - case QUERY_TARGET_SERVER: - NET_Query_SendQuery(targets[i].addr); - break; + case QUERY_TARGET_SERVER: + net_query_send_query(g_targets[i].addr); + break; - case QUERY_TARGET_BROADCAST: - NET_Query_SendQuery(NULL); - break; + case QUERY_TARGET_BROADCAST: + net_query_send_query(NULL); + break; - case QUERY_TARGET_MASTER: - NET_Query_SendMasterQuery(targets[i].addr); - break; + case QUERY_TARGET_MASTER: + net_query_send_master_query(g_targets[i].addr); + break; } - //printf("Queried %s\n", NET_AddrToString(targets[i].addr)); - targets[i].state = QUERY_TARGET_QUERIED; - targets[i].query_time = now; - ++targets[i].query_attempts; + /* printf("Queried %s\n", net_addr_to_string(targets[i].addr)); */ - last_query_time = now; + g_targets[i].state = QUERY_TARGET_QUERIED; + g_targets[i].query_time = now; + ++g_targets[i].query_attempts; + + g_last_query_time = now; } -// Time out servers that have been queried and not responded. +/* Time out servers that have been queried and not responded. */ -static void CheckTargetTimeouts(void) +static void check_target_timeouts(void) { - unsigned int i; - unsigned int now; + unsigned int i; + unsigned int now; - now = I_GetTimeMS(); + now = i_get_time_ms(); - for (i = 0; i < num_targets; ++i) + for (i = 0; i < g_num_targets; ++i) { - /* - printf("target %i: state %i, queries %i, query time %i\n", - i, targets[i].state, targets[i].query_attempts, - now - targets[i].query_time); - */ - - // We declare a target to be "no response" when we've sent - // multiple query packets to it (QUERY_MAX_ATTEMPTS) and - // received no response to any of them. - - if (targets[i].state == QUERY_TARGET_QUERIED - && targets[i].query_attempts >= QUERY_MAX_ATTEMPTS - && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000) + /* printf("target %i: state %i, queries %i, query time %i\n", + * i, targets[i].state, targets[i].query_attempts, + * now - targets[i].query_time); + */ + + /* We declare a target to be "no response" when we've sent + * multiple query packets to it (QUERY_MAX_ATTEMPTS) and + * received no response to any of them. + */ + + if (g_targets[i].state == QUERY_TARGET_QUERIED && + g_targets[i].query_attempts >= QUERY_MAX_ATTEMPTS && + now - g_targets[i].query_time > QUERY_TIMEOUT_SECS * 1000) { - targets[i].state = QUERY_TARGET_NO_RESPONSE; + g_targets[i].state = QUERY_TARGET_NO_RESPONSE; - if (targets[i].type == QUERY_TARGET_MASTER) + if (g_targets[i].type == QUERY_TARGET_MASTER) { - fprintf(stderr, "NET_MasterQuery: no response " - "from master server.\n"); + fprintf(stderr, "net_master_query: no response " + "from master server.\n"); } } } } -// If all targets have responded or timed out, returns true. +/* If all targets have responded or timed out, returns true. */ -static boolean AllTargetsDone(void) +static boolean all_targets_done(void) { - unsigned int i; + unsigned int i; - for (i = 0; i < num_targets; ++i) + for (i = 0; i < g_num_targets; ++i) { - if (targets[i].state != QUERY_TARGET_RESPONDED - && targets[i].state != QUERY_TARGET_NO_RESPONSE) + if (g_targets[i].state != QUERY_TARGET_RESPONDED && + g_targets[i].state != QUERY_TARGET_NO_RESPONSE) { - return false; + return false; } } - return true; + return true; } -// Polling function, invoked periodically to send queries and -// interpret new responses received from remote servers. -// Returns zero when the query sequence has completed and all targets -// have returned responses or timed out. +/* Stop the query loop */ -int NET_Query_Poll(net_query_callback_t callback, void *user_data) +static void net_query_exit_loop(void) { - CheckTargetTimeouts(); - - // Send a query. This will only send a single query at once. - - SendOneQuery(); - - // Check for a response - - NET_Query_GetResponse(callback, user_data); - - return !AllTargetsDone(); + g_query_loop_running = false; } -// Stop the query loop +/* Loop waiting for responses. + * The specified callback is invoked when a new server responds. + */ -static void NET_Query_ExitLoop(void) +static void net_query_query_loop(net_query_callback_t callback, + void *user_data) { - query_loop_running = false; -} - -// Loop waiting for responses. -// The specified callback is invoked when a new server responds. + g_query_loop_running = true; -static void NET_Query_QueryLoop(net_query_callback_t callback, void *user_data) -{ - query_loop_running = true; - - while (query_loop_running && NET_Query_Poll(callback, user_data)) + while (g_query_loop_running && net_query_poll(callback, user_data)) { - // Don't thrash the CPU + /* Don't thrash the CPU */ - I_Sleep(1); + usleep(1000); } } -void NET_Query_Init(void) +static void net_query_init(void) { - if (query_context == NULL) + if (g_query_context == NULL) { - query_context = NET_NewContext(); - NET_AddModule(query_context, &net_sdl_module); - net_sdl_module.InitClient(); + g_query_context = net_new_context(); + net_add_module(g_query_context, &net_sdl_module); + net_sdl_module.init_client(); } - free(targets); - targets = NULL; - num_targets = 0; + free(g_targets); + g_targets = NULL; + g_num_targets = 0; - printed_header = false; + g_printed_header = false; } -// Callback that exits the query loop when the first server is found. +/* Callback that exits the query loop when the first server is found. */ -static void NET_Query_ExitCallback(net_addr_t *addr, net_querydata_t *data, - unsigned int ping_time, void *user_data) +static void net_query_exit_callback(net_addr_t *addr, net_querydata_t *data, + unsigned int ping_time, void *user_data) { - NET_Query_ExitLoop(); + net_query_exit_loop(); } -// Search the targets list and find a target that has responded. -// If none have responded, returns NULL. +/* Search the targets list and find a target that has responded. + * If none have responded, returns NULL. + */ -static query_target_t *FindFirstResponder(void) +static query_target_t *find_first_responder(void) { - unsigned int i; + unsigned int i; - for (i = 0; i < num_targets; ++i) + for (i = 0; i < g_num_targets; ++i) { - if (targets[i].type == QUERY_TARGET_SERVER - && targets[i].state == QUERY_TARGET_RESPONDED) + if (g_targets[i].type == QUERY_TARGET_SERVER && + g_targets[i].state == QUERY_TARGET_RESPONDED) { - return &targets[i]; + return &g_targets[i]; } } - return NULL; + return NULL; } -// Return a count of the number of responses. +/* Return a count of the number of responses. */ -static int GetNumResponses(void) +static int get_num_responses(void) { - unsigned int i; - int result; + unsigned int i; + int result; - result = 0; + result = 0; - for (i = 0; i < num_targets; ++i) + for (i = 0; i < g_num_targets; ++i) { - if (targets[i].type == QUERY_TARGET_SERVER - && targets[i].state == QUERY_TARGET_RESPONDED) + if (g_targets[i].type == QUERY_TARGET_SERVER && + g_targets[i].state == QUERY_TARGET_RESPONDED) { - ++result; + ++result; } } - return result; -} - -int NET_StartLANQuery(void) -{ - query_target_t *target; - - NET_Query_Init(); - - // Add a broadcast target to the list. - - target = GetTargetForAddr(NULL, true); - target->type = QUERY_TARGET_BROADCAST; - - return 1; + return result; } -int NET_StartMasterQuery(void) -{ - net_addr_t *master; - query_target_t *target; - - NET_Query_Init(); - - // Resolve master address and add to targets list. - - master = NET_Query_ResolveMaster(query_context); - - if (master == NULL) - { - return 0; - } - - target = GetTargetForAddr(master, true); - target->type = QUERY_TARGET_MASTER; - NET_ReleaseAddress(master); - - return 1; -} - -// ----------------------------------------------------------------------- - -static void formatted_printf(int wide, const char *s, ...) PRINTF_ATTR(2, 3); static void formatted_printf(int wide, const char *s, ...) { - va_list args; - int i; + va_list args; + int i; - va_start(args, s); - i = vprintf(s, args); - va_end(args); + va_start(args, s); + i = vprintf(s, args); + va_end(args); - while (i < wide) + while (i < wide) { - putchar(' '); - ++i; + putchar(' '); + ++i; } } -static const char *GameDescription(GameMode_t mode, GameMission_t mission) +static const char *game_description(game_mode_t mode, gamemission_t mission) { - switch (mission) + switch (mission) { - case doom: - if (mode == shareware) - return "swdoom"; - else if (mode == registered) - return "regdoom"; - else if (mode == retail) - return "ultdoom"; - else - return "doom"; - case doom2: - return "doom2"; - case pack_tnt: - return "tnt"; - case pack_plut: - return "plutonia"; - case pack_chex: - return "chex"; - case pack_hacx: - return "hacx"; - case heretic: - return "heretic"; - case hexen: - return "hexen"; - case strife: - return "strife"; - default: - return "?"; + case doom: + if (mode == shareware) + return "swdoom"; + else if (mode == registered) + return "regdoom"; + else if (mode == retail) + return "ultdoom"; + else + return "doom"; + case doom2: + return "doom2"; + case pack_tnt: + return "tnt"; + case pack_plut: + return "plutonia"; + case pack_chex: + return "chex"; + case pack_hacx: + return "hacx"; + case heretic: + return "heretic"; + case hexen: + return "hexen"; + case strife: + return "strife"; + default: + return "?"; } } -static void PrintHeader(void) +static void print_header(void) { - int i; + int i; - putchar('\n'); - formatted_printf(5, "Ping"); - formatted_printf(18, "Address"); - formatted_printf(8, "Players"); - puts("Description"); + putchar('\n'); + formatted_printf(5, "Ping"); + formatted_printf(18, "Address"); + formatted_printf(8, "Players"); + puts("Description"); - for (i=0; i<70; ++i) - putchar('='); - putchar('\n'); + for (i = 0; i < 70; ++i) + putchar('='); + putchar('\n'); } -// Callback function that just prints information in a table. +/* Callback function that just prints information in a table. */ -static void NET_QueryPrintCallback(net_addr_t *addr, - net_querydata_t *data, - unsigned int ping_time, - void *user_data) +static void net_query_print_callback(net_addr_t *addr, net_querydata_t *data, + unsigned int ping_time, void *user_data) { - // If this is the first server, print the header. + /* If this is the first server, print the header. */ - if (!printed_header) + if (!g_printed_header) { - PrintHeader(); - printed_header = true; + print_header(); + g_printed_header = true; } - formatted_printf(5, "%4i", ping_time); - formatted_printf(22, "%s", NET_AddrToString(addr)); - formatted_printf(4, "%i/%i ", data->num_players, - data->max_players); + formatted_printf(5, "%4i", ping_time); + formatted_printf(22, "%s", net_addr_to_string(addr)); + formatted_printf(4, "%i/%i ", data->num_players, data->max_players); - if (data->gamemode != indetermined) + if (data->gamemode != indetermined) { - printf("(%s) ", GameDescription(data->gamemode, - data->gamemission)); + printf("(%s) ", game_description(data->gamemode, data->gamemission)); } - if (data->server_state) + if (data->server_state) { - printf("(game running) "); + printf("(game running) "); } - printf("%s\n", data->description); + printf("%s\n", data->description); } -void NET_LANQuery(void) +#if 0 /* UNUSED */ + +/* Block until a packet of the given type is received from the given + * address. + */ + +static net_packet_t *block_for_packet(net_addr_t *addr, + unsigned int packet_type, + unsigned int timeout_ms) { - if (NET_StartLANQuery()) + net_packet_t *packet; + net_addr_t *packet_src; + unsigned int read_packet_type; + unsigned int start_time; + + start_time = i_get_time_ms(); + + while (i_get_time_ms() < start_time + timeout_ms) { - printf("\nSearching for servers on local LAN ...\n"); + if (!net_recv_packet(g_query_context, &packet_src, &packet)) + { + usleep(20000); + continue; + } + + /* Caller doesn't need additional reference. */ + + net_release_address(packet_src); - NET_Query_QueryLoop(NET_QueryPrintCallback, NULL); + if (packet_src == addr && net_read_int16(packet, &read_packet_type) && + packet_type == read_packet_type) + { + return packet; + } - printf("\n%i server(s) found.\n", GetNumResponses()); - FreeTargets(); + net_free_packet(packet); } + + /* Timeout - no response. */ + + return NULL; } -void NET_MasterQuery(void) +/* Query master server for secure demo start seed value. */ + +static boolean net_start_secure_demo(prng_seed_t seed) { - if (NET_StartMasterQuery()) + net_packet_t *request, *response; + net_addr_t *master_addr; + char *signature; + boolean result; + + net_query_init(); + master_addr = net_query_resolve_master(g_query_context); + + /* Send request packet to master server. */ + + request = net_new_packet(10); + net_write_int16(request, NET_MASTER_PACKET_TYPE_SIGN_START); + net_send_packet(master_addr, request); + net_free_packet(request); + + /* Block for response and read contents. + * The signed start message will be saved for later. + */ + + response = block_for_packet(master_addr, + NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, + SIGNATURE_TIMEOUT_SECS * 1000); + + result = false; + + if (response != NULL) { - printf("\nSearching for servers on Internet ...\n"); + if (net_read_prng_seed(response, seed)) + { + signature = net_read_string(response); - NET_Query_QueryLoop(NET_QueryPrintCallback, NULL); + if (signature != NULL) + { + g_securedemo_start_message = m_string_duplicate(signature); + result = true; + } + } - printf("\n%i server(s) found.\n", GetNumResponses()); - FreeTargets(); + net_free_packet(response); } + + return result; } -void NET_QueryAddress(const char *addr_str) +/* Query master server for secure demo end signature. */ + +static char *net_end_secure_demo(sha1_digest_t demo_hash) { - net_addr_t *addr; - query_target_t *target; + net_packet_t *request, *response; + net_addr_t *master_addr; + char *signature; + + master_addr = net_query_resolve_master(g_query_context); + + /* Construct end request and send to master server. */ - NET_Query_Init(); + request = net_new_packet(10); + net_write_int16(request, NET_MASTER_PACKET_TYPE_SIGN_END); + net_write_sha1_sum(request, demo_hash); + net_write_string(request, g_securedemo_start_message); + net_send_packet(master_addr, request); + net_free_packet(request); - addr = NET_ResolveAddress(query_context, addr_str); + /* Block for response. The response packet simply contains a string + * with the ASCII signature. + */ - if (addr == NULL) + response = + block_for_packet(master_addr, NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, + SIGNATURE_TIMEOUT_SECS * 1000); + + if (response == NULL) { - I_Error("NET_QueryAddress: Host '%s' not found!", addr_str); + return NULL; } - // Add the address to the list of targets. + signature = net_read_string(response); + + net_free_packet(response); - target = GetTargetForAddr(addr, true); + return signature; +} +#endif - printf("\nQuerying '%s'...\n", addr_str); +/**************************************************************************** + * Public Functions + ****************************************************************************/ - // Run query loop. +/* Resolve the master server address. */ - NET_Query_QueryLoop(NET_Query_ExitCallback, NULL); +net_addr_t *net_query_resolve_master(net_context_t *context) +{ + net_addr_t *addr; - // Check if the target responded. + addr = net_resolve_address(context, MASTER_SERVER_ADDRESS); - if (target->state == QUERY_TARGET_RESPONDED) - { - NET_QueryPrintCallback(addr, &target->data, target->ping_time, NULL); - NET_ReleaseAddress(addr); - FreeTargets(); - } - else + if (addr == NULL) { - I_Error("No response from '%s'", addr_str); + fprintf(stderr, + "Warning: Failed to resolve address " + "for master server: %s\n", + MASTER_SERVER_ADDRESS); } -} -net_addr_t *NET_FindLANServer(void) -{ - query_target_t *target; - query_target_t *responder; - net_addr_t *result; + return addr; +} - NET_Query_Init(); +/* Send a registration packet to the master server to register + * ourselves with the global list. + */ - // Add a broadcast target to the list. +void net_query_add_to_master(net_addr_t *master_addr) +{ + net_packet_t *packet; - target = GetTargetForAddr(NULL, true); - target->type = QUERY_TARGET_BROADCAST; + packet = net_new_packet(10); + net_write_int16(packet, NET_MASTER_PACKET_TYPE_ADD); + net_send_packet(master_addr, packet); + net_free_packet(packet); +} - // Run the query loop, and stop at the first target found. +/* Process a packet received from the master server. */ - NET_Query_QueryLoop(NET_Query_ExitCallback, NULL); +void net_query_add_response(net_packet_t *packet) +{ + unsigned int result; - responder = FindFirstResponder(); + if (!net_read_int16(packet, &result)) + { + return; + } - if (responder != NULL) + if (result != 0) { - result = responder->addr; - NET_ReferenceAddress(result); + /* Only show the message once. */ + + if (!g_registered_with_master) + { + printf("Registered with master server at %s\n", + MASTER_SERVER_ADDRESS); + g_registered_with_master = true; + } } - else + else { - result = NULL; + /* Always show rejections. */ + + printf("Failed to register with master server at %s\n", + MASTER_SERVER_ADDRESS); } - FreeTargets(); - return result; + g_got_master_response = true; } -// Block until a packet of the given type is received from the given -// address. - -static net_packet_t *BlockForPacket(net_addr_t *addr, unsigned int packet_type, - unsigned int timeout_ms) +boolean net_query_check_added_to_master(boolean *result) { - net_packet_t *packet; - net_addr_t *packet_src; - unsigned int read_packet_type; - unsigned int start_time; - - start_time = I_GetTimeMS(); + /* Got response from master yet? */ - while (I_GetTimeMS() < start_time + timeout_ms) + if (!g_got_master_response) { - if (!NET_RecvPacket(query_context, &packet_src, &packet)) - { - I_Sleep(20); - continue; - } + return false; + } + + *result = g_registered_with_master; + return true; +} - // Caller doesn't need additional reference. - NET_ReleaseAddress(packet_src); +/* Send a hole punch request to the master server for the server at the + * given address. + */ - if (packet_src == addr - && NET_ReadInt16(packet, &read_packet_type) - && packet_type == read_packet_type) - { - return packet; - } +void net_request_hole_punch(net_context_t *context, net_addr_t *addr) +{ + net_addr_t *master_addr; + net_packet_t *packet; - NET_FreePacket(packet); + master_addr = net_query_resolve_master(context); + if (master_addr == NULL) + { + return; } - // Timeout - no response. + packet = net_new_packet(32); + net_write_int16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH); + net_write_string(packet, net_addr_to_string(addr)); + net_send_packet(master_addr, packet); - return NULL; + net_free_packet(packet); + net_release_address(master_addr); } -// Query master server for secure demo start seed value. +/* Polling function, invoked periodically to send queries and + * interpret new responses received from remote servers. + * Returns zero when the query sequence has completed and all targets + * have returned responses or timed out. + */ -boolean NET_StartSecureDemo(prng_seed_t seed) +int net_query_poll(net_query_callback_t callback, void *user_data) { - net_packet_t *request, *response; - net_addr_t *master_addr; - char *signature; - boolean result; + check_target_timeouts(); - NET_Query_Init(); - master_addr = NET_Query_ResolveMaster(query_context); + /* Send a query. This will only send a single query at once. */ - // Send request packet to master server. + send_one_query(); - request = NET_NewPacket(10); - NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_START); - NET_SendPacket(master_addr, request); - NET_FreePacket(request); + /* Check for a response */ - // Block for response and read contents. - // The signed start message will be saved for later. + net_query_get_response(callback, user_data); - response = BlockForPacket(master_addr, - NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, - SIGNATURE_TIMEOUT_SECS * 1000); + return !all_targets_done(); +} - result = false; +int net_start_lan_query(void) +{ + query_target_t *target; - if (response != NULL) - { - if (NET_ReadPRNGSeed(response, seed)) - { - signature = NET_ReadString(response); + net_query_init(); - if (signature != NULL) - { - securedemo_start_message = M_StringDuplicate(signature); - result = true; - } - } + /* Add a broadcast target to the list. */ + + target = get_target_for_addr(NULL, true); + target->type = QUERY_TARGET_BROADCAST; + + return 1; +} + +int net_start_master_query(void) +{ + net_addr_t *master; + query_target_t *target; + + net_query_init(); + + /* Resolve master address and add to targets list. */ - NET_FreePacket(response); + master = net_query_resolve_master(g_query_context); + + if (master == NULL) + { + return 0; } - return result; + target = get_target_for_addr(master, true); + target->type = QUERY_TARGET_MASTER; + net_release_address(master); + + return 1; } -// Query master server for secure demo end signature. +void net_lan_query(void) +{ + if (net_start_lan_query()) + { + printf("\nSearching for servers on local LAN ...\n"); + + net_query_query_loop(net_query_print_callback, NULL); -char *NET_EndSecureDemo(sha1_digest_t demo_hash) + printf("\n%i server(s) found.\n", get_num_responses()); + free_targets(); + } +} + +void net_master_query(void) { - net_packet_t *request, *response; - net_addr_t *master_addr; - char *signature; + if (net_start_master_query()) + { + printf("\nSearching for servers on Internet ...\n"); - master_addr = NET_Query_ResolveMaster(query_context); + net_query_query_loop(net_query_print_callback, NULL); - // Construct end request and send to master server. + printf("\n%i server(s) found.\n", get_num_responses()); + free_targets(); + } +} - request = NET_NewPacket(10); - NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_END); - NET_WriteSHA1Sum(request, demo_hash); - NET_WriteString(request, securedemo_start_message); - NET_SendPacket(master_addr, request); - NET_FreePacket(request); +void net_query_address(const char *addr_str) +{ + net_addr_t *addr; + query_target_t *target; - // Block for response. The response packet simply contains a string - // with the ASCII signature. + net_query_init(); - response = BlockForPacket(master_addr, - NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, - SIGNATURE_TIMEOUT_SECS * 1000); + addr = net_resolve_address(g_query_context, addr_str); - if (response == NULL) + if (addr == NULL) { - return NULL; + i_error("net_query_address: Host '%s' not found!", addr_str); } - signature = NET_ReadString(response); + /* Add the address to the list of targets. */ + + target = get_target_for_addr(addr, true); + + printf("\nQuerying '%s'...\n", addr_str); + + /* Run query loop. */ + + net_query_query_loop(net_query_exit_callback, NULL); - NET_FreePacket(response); + /* Check if the target responded. */ - return signature; + if (target->state == QUERY_TARGET_RESPONDED) + { + net_query_print_callback(addr, &target->data, target->ping_time, NULL); + net_release_address(addr); + free_targets(); + } + else + { + i_error("No response from '%s'", addr_str); + } } +net_addr_t *net_find_lan_server(void) +{ + query_target_t *target; + query_target_t *responder; + net_addr_t *result; + + net_query_init(); + + /* Add a broadcast target to the list. */ + + target = get_target_for_addr(NULL, true); + target->type = QUERY_TARGET_BROADCAST; + + /* Run the query loop, and stop at the first target found. */ + + net_query_query_loop(net_query_exit_callback, NULL); + + responder = find_first_responder(); + + if (responder != NULL) + { + result = responder->addr; + net_reference_address(result); + } + else + { + result = NULL; + } + + free_targets(); + return result; +} diff --git a/games/NXDoom/src/net_query.h b/games/NXDoom/src/net_query.h index e0c9e9bef2d..70dacfecd88 100644 --- a/games/NXDoom/src/net_query.h +++ b/games/NXDoom/src/net_query.h @@ -1,45 +1,61 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Querying servers to find their current status. -// +/**************************************************************************** + * apps/games/NXDoom/src/net_query.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Querying servers to find their current status. + * + ****************************************************************************/ #ifndef NET_QUERY_H #define NET_QUERY_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "net_defs.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ + typedef void (*net_query_callback_t)(net_addr_t *addr, net_querydata_t *querydata, unsigned int ping_time, void *user_data); -extern int NET_StartLANQuery(void); -extern int NET_StartMasterQuery(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -extern void NET_LANQuery(void); -extern void NET_MasterQuery(void); -extern void NET_QueryAddress(const char *addr); -extern net_addr_t *NET_FindLANServer(void); +extern int net_start_lan_query(void); +extern int net_start_master_query(void); -extern int NET_Query_Poll(net_query_callback_t callback, void *user_data); +extern void net_lan_query(void); +extern void net_master_query(void); +extern void net_query_address(const char *addr); +extern net_addr_t *net_find_lan_server(void); -extern net_addr_t *NET_Query_ResolveMaster(net_context_t *context); -extern void NET_Query_AddToMaster(net_addr_t *master_addr); -extern boolean NET_Query_CheckAddedToMaster(boolean *result); -extern void NET_Query_AddResponse(net_packet_t *packet); -extern void NET_RequestHolePunch(net_context_t *context, net_addr_t *addr); +extern int net_query_poll(net_query_callback_t callback, void *user_data); -#endif /* #ifndef NET_QUERY_H */ +extern net_addr_t *net_query_resolve_master(net_context_t *context); +extern void net_query_add_to_master(net_addr_t *master_addr); +extern boolean net_query_check_added_to_master(boolean *result); +extern void net_query_add_response(net_packet_t *packet); +extern void net_request_hole_punch(net_context_t *context, net_addr_t *addr); +#endif /* NET_QUERY_H */ diff --git a/games/NXDoom/src/net_sdl.c b/games/NXDoom/src/net_sdl.c index 2965f42340b..b57f4d20625 100644 --- a/games/NXDoom/src/net_sdl.c +++ b/games/NXDoom/src/net_sdl.c @@ -1,23 +1,32 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Networking module which uses SDL_net -// +/**************************************************************************** + * apps/games/NXDoom/src/net_sdl.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Networking module which uses SDL_net + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include -#include #include "doomtype.h" #include "i_system.h" @@ -29,413 +38,65 @@ #include "net_sdl.h" #include "z_zone.h" -// -// NETWORKING -// - - -#ifndef DISABLE_SDL2NET - - -#include - -#define DEFAULT_PORT 2342 - -static boolean initted = false; -static int port = DEFAULT_PORT; -static UDPsocket udpsocket; -static UDPpacket *recvpacket; - -typedef struct -{ - net_addr_t net_addr; - IPaddress sdl_addr; -} addrpair_t; - -static addrpair_t **addr_table; -static int addr_table_size = -1; - -// Initializes the address table - -static void NET_SDL_InitAddrTable(void) -{ - addr_table_size = 16; - - addr_table = Z_Malloc(sizeof(addrpair_t *) * addr_table_size, - PU_STATIC, 0); - memset(addr_table, 0, sizeof(addrpair_t *) * addr_table_size); -} - -static boolean AddressesEqual(IPaddress *a, IPaddress *b) -{ - return a->host == b->host - && a->port == b->port; -} - -// Finds an address by searching the table. If the address is not found, -// it is added to the table. - -static net_addr_t *NET_SDL_FindAddress(IPaddress *addr) -{ - addrpair_t *new_entry; - int empty_entry = -1; - int i; - - if (addr_table_size < 0) - { - NET_SDL_InitAddrTable(); - } - - for (i=0; isdl_addr)) - { - return &addr_table[i]->net_addr; - } - - if (empty_entry < 0 && addr_table[i] == NULL) - empty_entry = i; - } - - // Was not found in list. We need to add it. - - // Is there any space in the table? If not, increase the table size - - if (empty_entry < 0) - { - addrpair_t **new_addr_table; - int new_addr_table_size; - - // after reallocing, we will add this in as the first entry - // in the new block of memory - - empty_entry = addr_table_size; - - // allocate a new array twice the size, init to 0 and copy - // the existing table in. replace the old table. - - new_addr_table_size = addr_table_size * 2; - new_addr_table = Z_Malloc(sizeof(addrpair_t *) * new_addr_table_size, - PU_STATIC, 0); - memset(new_addr_table, 0, sizeof(addrpair_t *) * new_addr_table_size); - memcpy(new_addr_table, addr_table, - sizeof(addrpair_t *) * addr_table_size); - Z_Free(addr_table); - addr_table = new_addr_table; - addr_table_size = new_addr_table_size; - } - - // Add a new entry - - new_entry = Z_Malloc(sizeof(addrpair_t), PU_STATIC, 0); - - new_entry->sdl_addr = *addr; - new_entry->net_addr.refcount = 0; - new_entry->net_addr.handle = &new_entry->sdl_addr; - new_entry->net_addr.module = &net_sdl_module; - - addr_table[empty_entry] = new_entry; - - return &new_entry->net_addr; -} - -static void NET_SDL_FreeAddress(net_addr_t *addr) -{ - int i; - - for (i=0; inet_addr) - { - Z_Free(addr_table[i]); - addr_table[i] = NULL; - return; - } - } - - I_Error("NET_SDL_FreeAddress: Attempted to remove an unused address!"); -} - -static boolean NET_SDL_InitClient(void) -{ - int p; - - if (initted) - return true; - - //! - // @category net - // @arg - // - // Use the specified UDP port for communications, instead of - // the default (2342). - // - - p = M_CheckParmWithArgs("-port", 1); - if (p > 0) - port = atoi(myargv[p+1]); - - SDLNet_Init(); - - udpsocket = SDLNet_UDP_Open(0); - - if (udpsocket == NULL) - { - I_Error("NET_SDL_InitClient: Unable to open a socket!"); - } - - recvpacket = SDLNet_AllocPacket(1500); - -#ifdef DROP_PACKETS - srand(time(NULL)); -#endif - - initted = true; - - return true; -} - -static boolean NET_SDL_InitServer(void) -{ - int p; - - if (initted) - return true; - - p = M_CheckParmWithArgs("-port", 1); - if (p > 0) - port = atoi(myargv[p+1]); - - SDLNet_Init(); +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ - udpsocket = SDLNet_UDP_Open(port); +static boolean net_null_init_client(void); +static boolean net_null_init_server(void); +static void net_null_send_packet(net_addr_t *addr, net_packet_t *packet); +static boolean net_null_recv_packet(net_addr_t **addr, + net_packet_t **packet); +static void net_null_addr_to_string(net_addr_t *addr, char *buffer, + int buffer_len); +static void net_null_free_address(net_addr_t *addr); +static net_addr_t *net_null_resolve_address(const char *address); - if (udpsocket == NULL) - { - I_Error("NET_SDL_InitServer: Unable to bind to port %i", port); - } - - recvpacket = SDLNet_AllocPacket(1500); -#ifdef DROP_PACKETS - srand(time(NULL)); -#endif - - initted = true; - - return true; -} - -static void NET_SDL_SendPacket(net_addr_t *addr, net_packet_t *packet) -{ - UDPpacket sdl_packet; - IPaddress ip; - - if (addr == &net_broadcast_addr) - { - SDLNet_ResolveHost(&ip, NULL, port); - ip.host = INADDR_BROADCAST; - } - else - { - ip = *((IPaddress *) addr->handle); - } - -#if 0 - { - static int this_second_sent = 0; - static int lasttime; - - this_second_sent += packet->len + 64; - - if (I_GetTime() - lasttime > TICRATE) - { - printf("%i bytes sent in the last second\n", this_second_sent); - lasttime = I_GetTime(); - this_second_sent = 0; - } - } -#endif - -#ifdef DROP_PACKETS - if ((rand() % 4) == 0) - return; -#endif - - sdl_packet.channel = 0; - sdl_packet.data = packet->data; - sdl_packet.len = packet->len; - sdl_packet.address = ip; - - if (!SDLNet_UDP_Send(udpsocket, -1, &sdl_packet)) - { - I_Error("NET_SDL_SendPacket: Error transmitting packet: %s", - SDLNet_GetError()); - } -} - -static boolean NET_SDL_RecvPacket(net_addr_t **addr, net_packet_t **packet) -{ - int result; - - result = SDLNet_UDP_Recv(udpsocket, recvpacket); - - if (result < 0) - { - I_Error("NET_SDL_RecvPacket: Error receiving packet: %s", - SDLNet_GetError()); - } - - // no packets received - - if (result == 0) - return false; - - // Put the data into a new packet structure - - *packet = NET_NewPacket(recvpacket->len); - memcpy((*packet)->data, recvpacket->data, recvpacket->len); - (*packet)->len = recvpacket->len; - - // Address - - *addr = NET_SDL_FindAddress(&recvpacket->address); - - return true; -} - -void NET_SDL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) -{ - IPaddress *ip; - uint32_t host; - uint16_t port; - - ip = (IPaddress *) addr->handle; - host = SDLNet_Read32(&ip->host); - port = SDLNet_Read16(&ip->port); - - M_snprintf(buffer, buffer_len, "%i.%i.%i.%i", - (host >> 24) & 0xff, (host >> 16) & 0xff, - (host >> 8) & 0xff, host & 0xff); - - // If we are using the default port we just need to show the IP address, - // but otherwise we need to include the port. This is important because - // we use the string representation in the setup tool to provided an - // address to connect to. - if (port != DEFAULT_PORT) - { - char portbuf[10]; - M_snprintf(portbuf, sizeof(portbuf), ":%i", port); - M_StringConcat(buffer, portbuf, buffer_len); - } -} - -net_addr_t *NET_SDL_ResolveAddress(const char *address) -{ - IPaddress ip; - char *addr_hostname; - int addr_port; - int result; - char *colon; - - colon = strchr(address, ':'); - - addr_hostname = M_StringDuplicate(address); - if (colon != NULL) - { - addr_hostname[colon - address] = '\0'; - addr_port = atoi(colon + 1); - } - else - { - addr_port = port; - } - - result = SDLNet_ResolveHost(&ip, addr_hostname, addr_port); - - free(addr_hostname); - - if (result) - { - // unable to resolve - - return NULL; - } - else - { - return NET_SDL_FindAddress(&ip); - } -} - -// Complete module +/**************************************************************************** + * Public Data + ****************************************************************************/ net_module_t net_sdl_module = { - NET_SDL_InitClient, - NET_SDL_InitServer, - NET_SDL_SendPacket, - NET_SDL_RecvPacket, - NET_SDL_AddrToString, - NET_SDL_FreeAddress, - NET_SDL_ResolveAddress, + net_null_init_client, net_null_init_server, net_null_send_packet, + net_null_recv_packet, net_null_addr_to_string, net_null_free_address, + net_null_resolve_address, }; +/**************************************************************************** + * Private Functions + ****************************************************************************/ -#else // DISABLE_SDL2NET - -// no-op implementation - - -static boolean NET_NULL_InitClient(void) +static net_addr_t *net_null_resolve_address(const char *address) { - return false; + return NULL; } - -static boolean NET_NULL_InitServer(void) +static boolean net_null_init_client(void) { - return false; + return false; } - -static void NET_NULL_SendPacket(net_addr_t *addr, net_packet_t *packet) +static boolean net_null_init_server(void) { + return false; } - -static boolean NET_NULL_RecvPacket(net_addr_t **addr, net_packet_t **packet) +static void net_null_send_packet(net_addr_t *addr, net_packet_t *packet) { - return false; } - -static void NET_NULL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len) +static boolean net_null_recv_packet(net_addr_t **addr, + net_packet_t **packet) { - + return false; } - -static void NET_NULL_FreeAddress(net_addr_t *addr) +static void net_null_addr_to_string(net_addr_t *addr, char *buffer, + int buffer_len) { } - -net_addr_t *NET_NULL_ResolveAddress(const char *address) +static void net_null_free_address(net_addr_t *addr) { - return NULL; } - - -net_module_t net_sdl_module = -{ - NET_NULL_InitClient, - NET_NULL_InitServer, - NET_NULL_SendPacket, - NET_NULL_RecvPacket, - NET_NULL_AddrToString, - NET_NULL_FreeAddress, - NET_NULL_ResolveAddress, -}; - - -#endif // DISABLE_SDL2NET diff --git a/games/NXDoom/src/net_sdl.h b/games/NXDoom/src/net_sdl.h index c249de1c490..6f972fd1d3f 100644 --- a/games/NXDoom/src/net_sdl.h +++ b/games/NXDoom/src/net_sdl.h @@ -1,26 +1,39 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Networking module which uses SDL_net -// +/**************************************************************************** + * apps/games/NXDoom/src/net_sdl.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Networking module which uses SDL_net + * + * + ****************************************************************************/ #ifndef NET_SDL_H #define NET_SDL_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "net_defs.h" -extern net_module_t net_sdl_module; +/**************************************************************************** + * Public Data + ****************************************************************************/ -#endif /* #ifndef NET_SDL_H */ +extern net_module_t net_sdl_module; +#endif /* NET_SDL_H */ diff --git a/games/NXDoom/src/net_server.c b/games/NXDoom/src/net_server.c index 9374b64ec71..61b5246f17c 100644 --- a/games/NXDoom/src/net_server.c +++ b/games/NXDoom/src/net_server.c @@ -1,28 +1,37 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Network server code -// +/**************************************************************************** + * apps/games/NXDoom/src/net_server.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Network server code + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include #include +#include #include #include #include "config.h" -#include "doomtype.h" #include "d_mode.h" +#include "doomtype.h" #include "i_system.h" #include "i_timer.h" #include "m_argv.h" @@ -35,2063 +44,2167 @@ #include "net_loop.h" #include "net_packet.h" #include "net_query.h" -#include "net_server.h" #include "net_sdl.h" +#include "net_server.h" #include "net_structrw.h" -// How often to refresh our registration with the master server. -#define MASTER_REFRESH_PERIOD 30 /* twice per minute */ +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* How often to refresh our registration with the master server. */ + +#define MASTER_REFRESH_PERIOD 30 /* twice per minute */ + +/* How often to re-resolve the address of the master server? */ -// How often to re-resolve the address of the master server? #define MASTER_RESOLVE_PERIOD 8 * 60 * 60 /* 8 hours */ +#define net_sv_expand_ticnum(b) net_expand_tic_num(recvwindow_start, (b)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef enum { - // waiting for the game to be "launched" (key player to press the start - // button) + /* waiting for the game to be "launched" (key player to press the start + * button) + */ - SERVER_WAITING_LAUNCH, + SERVER_WAITING_LAUNCH, - // game has been launched, we are waiting for all players to be ready - // so the game can start. + /* game has been launched, we are waiting for all players to be ready + * so the game can start. + */ - SERVER_WAITING_START, + SERVER_WAITING_START, - // in a game + /* in a game */ - SERVER_IN_GAME, + SERVER_IN_GAME, } net_server_state_t; typedef struct { - boolean active; - int player_number; - net_addr_t *addr; - net_connection_t connection; - int last_send_time; - char *name; - - // If true, the client has sent the NET_PACKET_TYPE_GAMESTART - // message indicating that it is ready for the game to start. + boolean active; + int player_number; + net_addr_t *addr; + net_connection_t connection; + int last_send_time; + char *name; - boolean ready; + /* If true, the client has sent the NET_PACKET_TYPE_GAMESTART + * message indicating that it is ready for the game to start. + */ - // Time that this client connected to the server. - // This is used to determine the controller (oldest client). + boolean ready; - unsigned int connect_time; + /* Time that this client connected to the server. + * This is used to determine the controller (oldest client). + */ - // Last time new gamedata was received from this client + unsigned int connect_time; - int last_gamedata_time; + /* Last time new gamedata was received from this client */ - // recording a demo without -longtics + int last_gamedata_time; - boolean recording_lowres; + /* recording a demo without -longtics */ - // send queue: items to send to the client - // this is a circular buffer + boolean recording_lowres; - int sendseq; - net_full_ticcmd_t sendqueue[BACKUPTICS]; + /* send queue: items to send to the client + * this is a circular buffer + */ - // Latest acknowledged by the client + int sendseq; + net_full_ticcmd_t sendqueue[CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; - unsigned int acknowledged; + /* Latest acknowledged by the client */ - // Value of max_players specified by the client on connect. + unsigned int acknowledged; - int max_players; + /* Value of max_players specified by the client on connect. */ - // Observer: receives data but does not participate in the game. + int max_players; - boolean drone; + /* Observer: receives data but does not participate in the game. */ - // SHA1 hash sums of the client's WAD directory and dehacked data + boolean drone; - sha1_digest_t wad_sha1sum; - sha1_digest_t deh_sha1sum; + /* SHA1 hash sums of the client's WAD directory and dehacked data */ - // Is this client is playing with the Freedoom IWAD? + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; - unsigned int is_freedoom; + /* Is this client is playing with the Freedoom IWAD? */ - // Player class (for Hexen) + unsigned int is_freedoom; - int player_class; + /* Player class (for Hexen) */ + int player_class; } net_client_t; -// structure used for the recv window +/* structure used for the recv window */ -typedef struct +typedef struct { - // Whether this tic has been received yet + /* Whether this tic has been received yet */ - boolean active; + boolean active; - // Latency value received from the client + /* Latency value received from the client */ - signed int latency; + signed int latency; - // Last time we sent a resend request for this tic + /* Last time we sent a resend request for this tic */ - unsigned int resend_time; + unsigned int resend_time; - // Tic data itself + /* Tic data itself */ - net_ticdiff_t diff; + net_ticdiff_t diff; } net_client_recv_t; +typedef enum +{ + RANGE_LOCALHOST, /* Same process or 127.x */ + RANGE_PRIVATE, /* RFC 1918 */ + RANGE_PUBLIC, /* The public Internet */ +} ip_range_t; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + static net_server_state_t server_state; static boolean server_initialized = false; static net_client_t clients[MAXNETNODES]; -static net_client_t *sv_players[NET_MAXPLAYERS]; +static net_client_t *sv_players[CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; static net_context_t *server_context; static unsigned int sv_gamemode; static unsigned int sv_gamemission; static net_gamesettings_t sv_settings; -// For registration with master server: +/* For registration with master server: */ static net_addr_t *master_server = NULL; static unsigned int master_refresh_time; static unsigned int master_resolve_time; -// receive window +/* receive window */ static unsigned int recvwindow_start; -static net_client_recv_t recvwindow[BACKUPTICS][NET_MAXPLAYERS]; +static net_client_recv_t recvwindow[CONFIG_GAMES_NXDOOM_NET_BACKUPTICS] + [CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ -#define NET_SV_ExpandTicNum(b) NET_ExpandTicNum(recvwindow_start, (b)) +static void net_sv_send_console_message(net_client_t *client, const char *s, + ...) PRINTF_ATTR(2, 3); +static void net_sv_broadcast_message(const char *s, ...) PRINTF_ATTR(1, 2); -static void NET_SV_DisconnectClient(net_client_t *client) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void net_sv_disconnect_client(net_client_t *client) { - if (client->active) + if (client->active) { - NET_Conn_Disconnect(&client->connection); + net_conn_disconnect(&client->connection); } } -static boolean ClientConnected(net_client_t *client) +static boolean client_connected(net_client_t *client) { - // Check that the client is properly connected: ie. not in the - // process of connecting or disconnecting + /* Check that the client is properly connected: ie. not in the + * process of connecting or disconnecting + */ - return client->active - && client->connection.state == NET_CONN_STATE_CONNECTED; + return client->active && + client->connection.state == NET_CONN_STATE_CONNECTED; } -// Send a message to be displayed on a client's console +/* Send a message to be displayed on a client's console */ -static void NET_SV_SendConsoleMessage(net_client_t *client, const char *s, ...) PRINTF_ATTR(2, 3); -static void NET_SV_SendConsoleMessage(net_client_t *client, const char *s, ...) +static void net_sv_send_console_message(net_client_t *client, const char *s, + ...) { - char buf[1024]; - va_list args; - net_packet_t *packet; - - va_start(args, s); - M_vsnprintf(buf, sizeof(buf), s, args); - va_end(args); - - packet = NET_Conn_NewReliable(&client->connection, - NET_PACKET_TYPE_CONSOLE_MESSAGE); - - NET_WriteString(packet, buf); + char buf[1024]; + va_list args; + net_packet_t *packet; + + va_start(args, s); + vsnprintf(buf, sizeof(buf), s, args); + va_end(args); + + packet = net_conn_new_reliable(&client->connection, + NET_PACKET_TYPE_CONSOLE_MESSAGE); + + net_write_string(packet, buf); } -// Send a message to all clients +/* Send a message to all clients */ -static void NET_SV_BroadcastMessage(const char *s, ...) PRINTF_ATTR(1, 2); -static void NET_SV_BroadcastMessage(const char *s, ...) +static void net_sv_broadcast_message(const char *s, ...) { - char buf[1024]; - va_list args; - int i; + char buf[1024]; + va_list args; + int i; - va_start(args, s); - M_vsnprintf(buf, sizeof(buf), s, args); - va_end(args); + va_start(args, s); + vsnprintf(buf, sizeof(buf), s, args); + va_end(args); - for (i=0; iplayer_number = pl; - ++pl; + sv_players[pl] = &clients[i]; + sv_players[pl]->player_number = pl; + ++pl; } - else + else { - clients[i].player_number = -1; + clients[i].player_number = -1; } } } - for (; plconnect_time) + if (best == NULL || clients[i].connect_time < best->connect_time) { - best = &clients[i]; + best = &clients[i]; } } - return best; + return best; } -typedef enum -{ - RANGE_LOCALHOST, // Same process or 127.x - RANGE_PRIVATE, // RFC 1918 - RANGE_PUBLIC, // The public Internet -} ip_range_t; - -static ip_range_t ClientAddressRange(const char *addr) +static ip_range_t client_address_range(const char *addr) { - if (!strcmp(addr, "local client") - || M_StringStartsWith(addr, "127.")) + if (!strcmp(addr, "local client") || m_string_starts_with(addr, "127.")) { - return RANGE_LOCALHOST; + return RANGE_LOCALHOST; } - if (M_StringStartsWith(addr, "10.") - || M_StringStartsWith(addr, "192.168.")) + + if (m_string_starts_with(addr, "10.") || + m_string_starts_with(addr, "192.168.")) { - return RANGE_PRIVATE; + return RANGE_PRIVATE; } - return RANGE_PUBLIC; + + return RANGE_PUBLIC; } -static void NET_SV_SendWaitingData(net_client_t *client) +static void net_sv_send_waiting_data(net_client_t *client) { - net_waitdata_t wait_data; - net_packet_t *packet; - net_client_t *controller; - ip_range_t client_range, player_range; - const char *addr; - int i; + net_waitdata_t wait_data; + net_packet_t *packet; + net_client_t *controller; + ip_range_t client_range, player_range; + const char *addr; + int i; - NET_SV_AssignPlayers(); + net_sv_assign_players(); - controller = NET_SV_Controller(); + controller = net_sv_controller(); - wait_data.num_players = NET_SV_NumPlayers(); - wait_data.num_drones = NET_SV_NumDrones(); - wait_data.ready_players = NET_SV_NumReadyPlayers(); - wait_data.max_players = NET_SV_MaxPlayers(); - wait_data.is_controller = (client == controller); - wait_data.consoleplayer = client->player_number; + wait_data.num_players = net_sv_num_players(); + wait_data.num_drones = net_sv_num_drones(); + wait_data.ready_players = net_sv_num_ready_players(); + wait_data.max_players = net_sv_max_players(); + wait_data.is_controller = (client == controller); + wait_data.consoleplayer = client->player_number; - // Send the WAD and dehacked checksums of the controlling client. - // If no controller found (?), send the details that the client - // is expecting anyway. + /* Send the WAD and dehacked checksums of the controlling client. + * If no controller found (?), send the details that the client + * is expecting anyway. + */ - if (controller == NULL) + if (controller == NULL) { - controller = client; + controller = client; } - memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, - sizeof(sha1_digest_t)); - memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, - sizeof(sha1_digest_t)); - wait_data.is_freedoom = controller->is_freedoom; + memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, + sizeof(sha1_digest_t)); + memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, + sizeof(sha1_digest_t)); + wait_data.is_freedoom = controller->is_freedoom; + + /* We only send IP addresses to locally-connected clients (including + * the 127.* loopback range): + */ - // We only send IP addresses to locally-connected clients (including - // the 127.* loopback range): - addr = NET_AddrToString(client->connection.addr); - client_range = ClientAddressRange(addr); + addr = net_addr_to_string(client->connection.addr); + client_range = client_address_range(addr); - // set name and address of each player: + /* set name and address of each player: */ - for (i = 0; i < wait_data.num_players; ++i) + for (i = 0; i < wait_data.num_players; ++i) { - M_StringCopy(wait_data.player_names[i], - sv_players[i]->name, - MAXPLAYERNAME); + m_str_copy(wait_data.player_names[i], sv_players[i]->name, + CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME); - // For privacy, only local clients or those on a LAN get to see - // addresses. Public clients only get to see their own address, - // though we do reveal localhost addresses since they're harmless, - // and we do reveal when a client is connected via LAN. - addr = NET_AddrToString(sv_players[i]->addr); - player_range = ClientAddressRange(addr); - if (client_range == RANGE_LOCALHOST || client_range == RANGE_PRIVATE - || i == wait_data.consoleplayer || player_range == RANGE_LOCALHOST) + /* For privacy, only local clients or those on a LAN get to see + * addresses. Public clients only get to see their own address, + * though we do reveal localhost addresses since they're harmless, + * and we do reveal when a client is connected via LAN. + */ + + addr = net_addr_to_string(sv_players[i]->addr); + player_range = client_address_range(addr); + if (client_range == RANGE_LOCALHOST || client_range == RANGE_PRIVATE || + i == wait_data.consoleplayer || player_range == RANGE_LOCALHOST) { - M_StringCopy(wait_data.player_addrs[i], addr, MAXPLAYERNAME); + m_str_copy(wait_data.player_addrs[i], addr, + CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME); } - else if (player_range == RANGE_PRIVATE) + else if (player_range == RANGE_PRIVATE) { - M_snprintf(wait_data.player_addrs[i], MAXPLAYERNAME, - "[LAN player]"); + snprintf(wait_data.player_addrs[i], + CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME, + "[LAN player]"); } - else + else { - M_snprintf(wait_data.player_addrs[i], MAXPLAYERNAME, - "[address hidden]"); + snprintf(wait_data.player_addrs[i], + CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME, + "[address hidden]"); } } - // Construct packet: + /* Construct packet: */ - packet = NET_NewPacket(10); - NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA); - NET_WriteWaitData(packet, &wait_data); + packet = net_new_packet(10); + net_write_int16(packet, NET_PACKET_TYPE_WAITING_DATA); + net_write_wait_data(packet, &wait_data); - // Send packet to client and free + /* Send packet to client and free */ - NET_Conn_SendPacket(&client->connection, packet); - NET_FreePacket(packet); + net_conn_send_packet(&client->connection, packet); + net_free_packet(packet); } -// Find the latest tic which has been acknowledged as received by -// all clients. +/* Find the latest tic which has been acknowledged as received by + * all clients. + */ -static unsigned int NET_SV_LatestAcknowledged(void) +static unsigned int net_sv_latest_acknowledged(void) { - unsigned int lowtic = UINT_MAX; - int i; + unsigned int lowtic = UINT_MAX; + int i; - for (i=0; iactive = true; - client->connect_time = I_GetTimeMS(); - NET_Conn_InitServer(&client->connection, addr, protocol); - client->addr = addr; - NET_ReferenceAddress(addr); - client->last_send_time = -1; + client->active = true; + client->connect_time = i_get_time_ms(); + net_conn_init_server(&client->connection, addr, protocol); + client->addr = addr; + net_reference_address(addr); + client->last_send_time = -1; - // init the ticcmd send queue + /* init the ticcmd send queue */ - client->sendseq = 0; - client->acknowledged = 0; - client->drone = false; - client->ready = false; + client->sendseq = 0; + client->acknowledged = 0; + client->drone = false; + client->ready = false; - client->last_gamedata_time = 0; + client->last_gamedata_time = 0; - memset(client->sendqueue, 0xff, sizeof(client->sendqueue)); + memset(client->sendqueue, 0xff, sizeof(client->sendqueue)); - NET_Log("server: initialized new client from %s", NET_AddrToString(addr)); + net_log_info("server: initialized new client from %s", + net_addr_to_string(addr)); } -// parse a SYN from a client(initiating a connection) +/* parse a SYN from a client(initiating a connection) */ -static void NET_SV_ParseSYN(net_packet_t *packet, net_client_t *client, - net_addr_t *addr) +static void net_sv_parse_syn(net_packet_t *packet, net_client_t *client, + net_addr_t *addr) { - unsigned int magic; - net_connect_data_t data; - net_packet_t *reply; - net_protocol_t protocol; - char *player_name; - char *client_version; - int num_players; - int i; + unsigned int magic; + net_connect_data_t data; + net_packet_t *reply; + net_protocol_t protocol; + char *player_name; + char *client_version; + int num_players; + int i; - NET_Log("server: processing SYN packet"); + net_log_info("server: processing SYN packet"); - // Read the magic number and check it is the expected one. - if (!NET_ReadInt32(packet, &magic)) + /* Read the magic number and check it is the expected one. */ + + if (!net_read_int32(packet, &magic)) { - NET_Log("server: error: no magic number for SYN"); - return; + net_log_err("server: no magic number for SYN"); + return; } - switch (magic) + switch (magic) { - case NET_MAGIC_NUMBER: - break; + case NET_MAGIC_NUMBER: + break; - case NET_OLD_MAGIC_NUMBER: - NET_Log("server: error: client using old magic number: %d", magic); - NET_SV_SendReject(addr, - "You are using an old client version that is not supported by " - "this server. This server is running " PACKAGE_STRING "."); - return; + case NET_OLD_MAGIC_NUMBER: + net_log_err("server: client using old magic number: %d", magic); + net_sv_send_reject( + addr, + "You are using an old client version that is not supported by " + "this server. This server is running " PACKAGE_STRING "."); + return; - default: - NET_Log("server: error: wrong magic number: %d", magic); - return; + default: + net_log_err("server: wrong magic number: %d", magic); + return; } - // Read the client version string. We actually now only use this when - // sending a reject message, as we only reject if we can't negotiate a - // common protocol (below). - client_version = NET_ReadString(packet); - if (client_version == NULL) + /* Read the client version string. We actually now only use this when + * sending a reject message, as we only reject if we can't negotiate a + * common protocol (below). + */ + + client_version = net_read_string(packet); + if (client_version == NULL) { - NET_Log("server: error: no version from client"); - return; + net_log_err("server: no version from client"); + return; } - // Read the client's list of accepted protocols. Net play between forks - // of Chocolate Doom is accepted provided that they can negotiate a - // common accepted protocol. - protocol = NET_ReadProtocolList(packet); - if (protocol == NET_PROTOCOL_UNKNOWN) + /* Read the client's list of accepted protocols. Net play between forks + * of Chocolate Doom is accepted provided that they can negotiate a + * common accepted protocol. + */ + + protocol = net_read_protocol_list(packet); + if (protocol == NET_PROTOCOL_UNKNOWN) { - char reject_msg[256]; + char reject_msg[256]; - M_snprintf(reject_msg, sizeof(reject_msg), - "Version mismatch: server version is: " PACKAGE_STRING "; " - "client is: %s. No common compatible protocol could be " - "negotiated.", client_version); - NET_SV_SendReject(addr, reject_msg); - NET_Log("server: error: no common protocol"); - return; + snprintf(reject_msg, sizeof(reject_msg), + "Version mismatch: server version is: " PACKAGE_STRING "; " + "client is: %s. No common compatible protocol could be " + "negotiated.", + client_version); + net_sv_send_reject(addr, reject_msg); + net_log_err("server: no common protocol"); + return; } - // Read connect data, and check that the game mode/mission are valid - // and the max_players value is in a sensible range. - if (!NET_ReadConnectData(packet, &data)) + /* Read connect data, and check that the game mode/mission are valid + * and the max_players value is in a sensible range. + */ + + if (!net_read_connect_data(packet, &data)) { - NET_Log("server: error: failed to read connect data"); - return; + net_log_err("server: failed to read connect data"); + return; } - if (!D_ValidGameMode(data.gamemission, data.gamemode) - || data.max_players > NET_MAXPLAYERS) + if (!d_valid_game_mode(data.gamemission, data.gamemode) || + data.max_players > CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS) { - NET_Log("server: error: invalid connect data, max_players=%d, " - "gamemission=%d, gamemode=%d", - data.max_players, data.gamemission, data.gamemode); - return; + net_log_err("server: invalid connect data, max_players=%d, " + "gamemission=%d, gamemode=%d", + data.max_players, data.gamemission, data.gamemode); + return; } - // Read the player's name - player_name = NET_ReadString(packet); - if (player_name == NULL) + /* Read the player's name */ + + player_name = net_read_string(packet); + if (player_name == NULL) { - NET_Log("server: error: failed to read player name"); - return; + net_log_err("server: failed to read player name"); + return; } - // At this point we have received a valid SYN. + /* At this point we have received a valid SYN. */ + + /* Not accepting new connections? */ - // Not accepting new connections? - if (server_state != SERVER_WAITING_LAUNCH) + if (server_state != SERVER_WAITING_LAUNCH) { - NET_Log("server: error: not in waiting launch state, server_state=%d", - server_state); - NET_SV_SendReject(addr, - "Server is not currently accepting connections"); - return; + net_log_err("server: not in waiting launch state, server_state=%d", + server_state); + net_sv_send_reject(addr, + "Server is not currently accepting connections"); + return; } - // Before accepting a new client, check that there is a slot free. - NET_SV_AssignPlayers(); - num_players = NET_SV_NumPlayers(); + /* Before accepting a new client, check that there is a slot free. */ - if ((!data.drone && num_players >= NET_SV_MaxPlayers()) - || NET_SV_NumClients() >= MAXNETNODES) + net_sv_assign_players(); + num_players = net_sv_num_players(); + + if ((!data.drone && num_players >= net_sv_max_players()) || + net_sv_num_clients() >= MAXNETNODES) { - NET_Log("server: no more players, num_players=%d, max=%d", - num_players, NET_SV_MaxPlayers()); - NET_SV_SendReject(addr, "Server is full!"); - return; + net_log_info("server: no more players, num_players=%d, max=%d", + num_players, net_sv_max_players()); + net_sv_send_reject(addr, "Server is full!"); + return; } - // TODO: Add server option to allow rejecting clients which set - // lowres_turn. This is potentially desirable as the presence of such - // clients affects turning resolution. + /* TODO: Add server option to allow rejecting clients which set + * lowres_turn. This is potentially desirable as the presence of such + * clients affects turning resolution. + */ + + /* Adopt the game mode and mission of the first connecting client: */ - // Adopt the game mode and mission of the first connecting client: - if (num_players == 0 && !data.drone) + if (num_players == 0 && !data.drone) { - sv_gamemode = data.gamemode; - sv_gamemission = data.gamemission; - NET_Log("server: new game, mode=%d, mission=%d", - sv_gamemode, sv_gamemission); + sv_gamemode = data.gamemode; + sv_gamemission = data.gamemission; + net_log_info("server: new game, mode=%d, mission=%d", sv_gamemode, + sv_gamemission); } - // Check the connecting client is playing the same game as all - // the other clients - if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission) + /* Check the connecting client is playing the same game as all + * the other clients + */ + + if (data.gamemode != sv_gamemode || data.gamemission != sv_gamemission) { - char msg[128]; - NET_Log("server: wrong mode/mission, %d != %d || %d != %d", - data.gamemode, sv_gamemode, data.gamemission, sv_gamemission); - M_snprintf(msg, sizeof(msg), - "Game mismatch: server is %s (%s), client is %s (%s)", - D_GameMissionString(sv_gamemission), - D_GameModeString(sv_gamemode), - D_GameMissionString(data.gamemission), - D_GameModeString(data.gamemode)); + char msg[128]; + net_log_warn("server: wrong mode/mission, %d != %d || %d != %d", + data.gamemode, sv_gamemode, data.gamemission, + sv_gamemission); + snprintf(msg, sizeof(msg), + "Game mismatch: server is %s (%s), client is %s (%s)", + d_game_mission_string(sv_gamemission), + d_game_mode_string(sv_gamemode), + d_game_mission_string(data.gamemission), + d_game_mode_string(data.gamemode)); - NET_SV_SendReject(addr, msg); - return; + net_sv_send_reject(addr, msg); + return; } - // Allocate a client slot if there isn't one already - if (client == NULL) + /* Allocate a client slot if there isn't one already */ + + if (client == NULL) { - // find a slot, or return if none found + /* find a slot, or return if none found */ - for (i=0; iconnection.state == NET_CONN_STATE_DISCONNECTED) + if (client->connection.state == NET_CONN_STATE_DISCONNECTED) { - client->active = false; + client->active = false; } } - // Client already connected? - if (client->active) + /* Client already connected? */ + + if (client->active) { - NET_Log("server: client is already initialized (duplicate SYN?)"); - return; + net_log_warn("server: client is already initialized (duplicate SYN?)"); + return; } - // Activate, initialize connection - NET_SV_InitNewClient(client, addr, protocol); + /* Activate, initialize connection */ + + net_sv_init_new_client(client, addr, protocol); + + /* Save the SHA1 checksums and other details. */ - // Save the SHA1 checksums and other details. - memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t)); - memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t)); - client->is_freedoom = data.is_freedoom; - client->max_players = data.max_players; - client->name = M_StringDuplicate(player_name); - client->recording_lowres = data.lowres_turn; - client->drone = data.drone; - client->player_class = data.player_class; + memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t)); + memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t)); + client->is_freedoom = data.is_freedoom; + client->max_players = data.max_players; + client->name = m_string_duplicate(player_name); + client->recording_lowres = data.lowres_turn; + client->drone = data.drone; + client->player_class = data.player_class; - // Send a reply back to the client, indicating a successful connection - // and specifying the protocol that will be used for communications. - reply = NET_Conn_NewReliable(&client->connection, NET_PACKET_TYPE_SYN); - NET_WriteString(reply, PACKAGE_STRING); - NET_WriteProtocol(reply, protocol); + /* Send a reply back to the client, indicating a successful connection + * and specifying the protocol that will be used for communications. + */ + + reply = net_conn_new_reliable(&client->connection, NET_PACKET_TYPE_SYN); + net_write_string(reply, PACKAGE_STRING); + net_write_protocol(reply, protocol); } -// Parse a launch packet. This is sent by the key player when the "start" -// button is pressed, and causes the startup process to continue. +/* Parse a launch packet. This is sent by the key player when the "start" + * button is pressed, and causes the startup process to continue. + */ -static void NET_SV_ParseLaunch(net_packet_t *packet, net_client_t *client) +static void net_sv_parse_launch(net_packet_t *packet, net_client_t *client) { - net_packet_t *launchpacket; - int num_players; - unsigned int i; + net_packet_t *launchpacket; + int num_players; + unsigned int i; - NET_Log("server: processing launch packet"); + net_log_info("server: processing launch packet"); - // Only the controller can launch the game. + /* Only the controller can launch the game. */ - if (client != NET_SV_Controller()) + if (client != net_sv_controller()) { - NET_Log("server: error: this client isn't the controller, %d != %d", - client, NET_SV_Controller()); - return; + net_log_err("server: this client isn't the controller, %p != %p", + client, net_sv_controller()); + return; } - // Can only launch when we are in the waiting state. + /* Can only launch when we are in the waiting state. */ - if (server_state != SERVER_WAITING_LAUNCH) + if (server_state != SERVER_WAITING_LAUNCH) { - NET_Log("server: error: not in waiting launch state, state=%d", - server_state); - return; + net_log_err("server: not in waiting launch state, state=%d", + server_state); + return; } - // Forward launch on to all clients. - NET_Log("server: sending launch to all clients"); - NET_SV_AssignPlayers(); - num_players = NET_SV_NumPlayers(); + /* Forward launch on to all clients. */ + + net_log_info("server: sending launch to all clients"); + net_sv_assign_players(); + num_players = net_sv_num_players(); - for (i=0; irecording_lowres) + if (sv_players[i] != NULL && sv_players[i]->recording_lowres) { - sv_settings.lowres_turn = true; + sv_settings.lowres_turn = true; } } - sv_settings.num_players = NET_SV_NumPlayers(); + sv_settings.num_players = net_sv_num_players(); - // Copy player classes: + /* Copy player classes: */ - for (i = 0; i < NET_MAXPLAYERS; ++i) + for (i = 0; i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; ++i) { - if (sv_players[i] != NULL) + if (sv_players[i] != NULL) { - sv_settings.player_classes[i] = sv_players[i]->player_class; + sv_settings.player_classes[i] = sv_players[i]->player_class; } - else + else { - sv_settings.player_classes[i] = 0; + sv_settings.player_classes[i] = 0; } } - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - // Send start packets to each connected node + /* Send start packets to each connected node */ - for (i = 0; i < MAXNETNODES; ++i) + for (i = 0; i < MAXNETNODES; ++i) { - if (!ClientConnected(&clients[i])) - continue; + if (!client_connected(&clients[i])) continue; - clients[i].last_gamedata_time = nowtime; + clients[i].last_gamedata_time = nowtime; - startpacket = NET_Conn_NewReliable(&clients[i].connection, - NET_PACKET_TYPE_GAMESTART); + startpacket = net_conn_new_reliable(&clients[i].connection, + NET_PACKET_TYPE_GAMESTART); - sv_settings.consoleplayer = clients[i].player_number; + sv_settings.consoleplayer = clients[i].player_number; - NET_WriteSettings(startpacket, &sv_settings); + net_write_settings(startpacket, &sv_settings); } - // Change server state - NET_Log("server: beginning game state"); - server_state = SERVER_IN_GAME; + /* Change server state */ - memset(recvwindow, 0, sizeof(recvwindow)); - recvwindow_start = 0; + net_log_info("server: beginning game state"); + server_state = SERVER_IN_GAME; + + memset(recvwindow, 0, sizeof(recvwindow)); + recvwindow_start = 0; } -// Returns true when all nodes have indicated readiness to start the game. +/* Returns true when all nodes have indicated readiness to start the game. */ -static boolean AllNodesReady(void) +static boolean all_nodes_ready(void) { - unsigned int i; + unsigned int i; - for (i = 0; i < MAXNETNODES; ++i) + for (i = 0; i < MAXNETNODES; ++i) { - if (ClientConnected(&clients[i]) && !clients[i].ready) + if (client_connected(&clients[i]) && !clients[i].ready) { - return false; + return false; } } - return true; + return true; } -// Check if the game should start, and if so, start it. +/* Check if the game should start, and if so, start it. */ -static void CheckStartGame(void) +static void check_start_game(void) { - if (!AllNodesReady()) + if (!all_nodes_ready()) { - NET_Log("server: not all clients ready to start yet"); - return; + net_log_warn("server: not all clients ready to start yet"); + return; } - NET_Log("server: all clients ready, starting game"); - StartGame(); + net_log_info("server: all clients ready, starting game"); + start_game(); } -// Send waiting data with current status to all nodes that are ready to -// start the game. +/* Send waiting data with current status to all nodes that are ready to + * start the game. + */ -static void SendAllWaitingData(void) +static void send_all_waiting_data(void) { - unsigned int i; + unsigned int i; - for (i = 0; i < MAXNETNODES; ++i) + for (i = 0; i < MAXNETNODES; ++i) { - if (ClientConnected(&clients[i]) && clients[i].ready) + if (client_connected(&clients[i]) && clients[i].ready) { - NET_SV_SendWaitingData(&clients[i]); + net_sv_send_waiting_data(&clients[i]); } } } -// Parse a game start packet +/* Parse a game start packet */ -static void NET_SV_ParseGameStart(net_packet_t *packet, net_client_t *client) +static void net_sv_parse_game_start(net_packet_t *packet, + net_client_t *client) { - net_gamesettings_t settings; + net_gamesettings_t settings; - NET_Log("server: processing game start packet"); + net_log_info("server: processing game start packet"); - // Can only start a game if we are in the waiting start state. + /* Can only start a game if we are in the waiting start state. */ - if (server_state != SERVER_WAITING_START) + if (server_state != SERVER_WAITING_START) { - NET_Log("server: error: not in waiting start state, server_state=%d", - server_state); - return; + net_log_info( + "server: error: not in waiting start state, server_state=%d", + server_state); + return; } - if (client == NET_SV_Controller()) + if (client == net_sv_controller()) { - if (!NET_ReadSettings(packet, &settings)) + if (!net_read_settings(packet, &settings)) { - // Malformed packet - NET_Log("server: error: no settings from controller"); - return; + /* Malformed packet */ + + net_log_err("server: no settings from controller"); + return; } - // Check the game settings are valid + /* Check the game settings are valid */ - if (!NET_ValidGameSettings(sv_gamemode, sv_gamemission, &settings)) + if (!net_valid_game_settings(sv_gamemode, sv_gamemission, &settings)) { - NET_Log("server: error: invalid game settings"); - return; + net_log_err("server: invalid game settings"); + return; } - sv_settings = settings; + sv_settings = settings; } - client->ready = true; + client->ready = true; - CheckStartGame(); + check_start_game(); - // Update all ready clients with the current state (number of players - // ready, etc.). This is used by games that show startup progress - // (eg. Hexen's spinal loading) + /* Update all ready clients with the current state (number of players + * ready, etc.). This is used by games that show startup progress + * (eg. Hexen's spinal loading) + */ - SendAllWaitingData(); + send_all_waiting_data(); } -// Send a resend request to a client +/* Send a resend request to a client */ -static void NET_SV_SendResendRequest(net_client_t *client, int start, int end) +static void net_sv_send_resend_request(net_client_t *client, int start, + int end) { - net_packet_t *packet; - net_client_recv_t *recvobj; - int i; - unsigned int nowtime; - int index; + net_packet_t *packet; + net_client_recv_t *recvobj; + int i; + unsigned int nowtime; + int index; - NET_Log("server: send resend to %s for tics %d-%d", - NET_AddrToString(client->addr), start, end); + net_log_info("server: send resend to %s for tics %d-%d", + net_addr_to_string(client->addr), start, end); - packet = NET_NewPacket(20); + packet = net_new_packet(20); - NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); - NET_WriteInt32(packet, start); - NET_WriteInt8(packet, end - start + 1); + net_write_int16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); + net_write_int32(packet, start); + net_write_int8(packet, end - start + 1); - NET_Conn_SendPacket(&client->connection, packet); - NET_FreePacket(packet); + net_conn_send_packet(&client->connection, packet); + net_free_packet(packet); - // Store the time we send the resend request + /* Store the time we send the resend request */ - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - for (i=start; i<=end; ++i) + for (i = start; i <= end; ++i) { - index = i - recvwindow_start; + index = i - recvwindow_start; - if (index >= BACKUPTICS) + if (index >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) { - // Outside the range + /* Outside the range */ - continue; + continue; } - - recvobj = &recvwindow[index][client->player_number]; - recvobj->resend_time = nowtime; + recvobj = &recvwindow[index][client->player_number]; + + recvobj->resend_time = nowtime; } } -// Check for expired resend requests +/* Check for expired resend requests */ -static void NET_SV_CheckResends(net_client_t *client) +static void net_sv_check_resends(net_client_t *client) { - int i; - int player; - int resend_start, resend_end; - unsigned int nowtime; + int i; + int player; + int resend_start; + int resend_end; + unsigned int nowtime; - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - player = client->player_number; - resend_start = -1; - resend_end = -1; + player = client->player_number; + resend_start = -1; + resend_end = -1; - for (i=0; iactive - && recvobj->resend_time != 0 - && nowtime > recvobj->resend_time + 300; + need_resend = !recvobj->active && recvobj->resend_time != 0 && + nowtime > recvobj->resend_time + 300; - if (need_resend) + if (need_resend) { - // Start a new run of resend tics? - if (resend_start < 0) + /* Start a new run of resend tics? */ + + if (resend_start < 0) { - resend_start = i; + resend_start = i; } - resend_end = i; + + resend_end = i; } - else if (resend_start >= 0) + else if (resend_start >= 0) { - // End of a run of resend tics - NET_Log("server: resend request to %s timed out for %d-%d (%d)", - NET_AddrToString(client->addr), - recvwindow_start + resend_start, - recvwindow_start + resend_end, - &recvwindow[resend_start][player].resend_time); - NET_SV_SendResendRequest(client, - recvwindow_start + resend_start, + /* End of a run of resend tics */ + + net_log_warn( + "server: resend request to %s timed out for %d-%d (%p)", + net_addr_to_string(client->addr), + recvwindow_start + resend_start, + recvwindow_start + resend_end, + &recvwindow[resend_start][player].resend_time); + + net_sv_send_resend_request(client, recvwindow_start + resend_start, recvwindow_start + resend_end); - resend_start = -1; + resend_start = -1; } } - if (resend_start >= 0) + if (resend_start >= 0) { - NET_Log("server: resend request to %s timed out for %d-%d (%d)", - NET_AddrToString(client->addr), - recvwindow_start + resend_start, - recvwindow_start + resend_end, - &recvwindow[resend_start][player].resend_time); - NET_SV_SendResendRequest(client, - recvwindow_start + resend_start, + net_log_warn("server: resend request to %s timed out for %d-%d (%p)", + net_addr_to_string(client->addr), + recvwindow_start + resend_start, + recvwindow_start + resend_end, + &recvwindow[resend_start][player].resend_time); + net_sv_send_resend_request(client, recvwindow_start + resend_start, recvwindow_start + resend_end); } } -// Process game data from a client +/* Process game data from a client */ -static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) +static void net_sv_parse_game_data(net_packet_t *packet, + net_client_t *client) { - net_client_recv_t *recvobj; - unsigned int seq; - unsigned int ackseq; - unsigned int num_tics; - unsigned int nowtime; - size_t i; - int player; - int resend_start, resend_end; - int index; + net_client_recv_t *recvobj; + unsigned int seq; + unsigned int ackseq; + unsigned int num_tics; + unsigned int nowtime; + size_t i; + int player; + int resend_start; + int resend_end; + int index; - if (server_state != SERVER_IN_GAME) + if (server_state != SERVER_IN_GAME) { - NET_Log("server: error: not in game state: server_state=%d", - server_state); - return; + net_log_err("server: not in game state: server_state=%d", + server_state); + return; } - if (client->drone) + if (client->drone) { - // Drones do not contribute any game data. - NET_Log("server: error: game data from a drone?"); - return; + /* Drones do not contribute any game data. */ + + net_log_err("server: game data from a drone?"); + return; } - player = client->player_number; + player = client->player_number; + + /* Read header */ - // Read header - if (!NET_ReadInt8(packet, &ackseq) - || !NET_ReadInt8(packet, &seq) - || !NET_ReadInt8(packet, &num_tics)) + if (!net_read_int8(packet, &ackseq) || !net_read_int8(packet, &seq) || + !net_read_int8(packet, &num_tics)) { - NET_Log("server: error: failed to read header"); - return; + net_log_err("server: failed to read header"); + return; } - NET_Log("server: got game data, seq=%d, num_tics=%d, ackseq=%d", - seq, num_tics, ackseq); + net_log_info("server: got game data, seq=%d, num_tics=%d, ackseq=%d", seq, + num_tics, ackseq); - // Get the current time - nowtime = I_GetTimeMS(); + /* Get the current time */ - // Expand 8-bit values to the full sequence number - ackseq = NET_SV_ExpandTicNum(ackseq); - seq = NET_SV_ExpandTicNum(seq); + nowtime = i_get_time_ms(); - // Sanity checks + /* Expand 8-bit values to the full sequence number */ - for (i=0; i= BACKUPTICS) + if (index < 0 || index >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) { - // Not in range of the recv window + /* Not in range of the recv window */ - continue; + continue; } - recvobj = &recvwindow[index][player]; - recvobj->active = true; - recvobj->diff = diff; - recvobj->latency = latency; + recvobj = &recvwindow[index][player]; + recvobj->active = true; + recvobj->diff = diff; + recvobj->latency = latency; - client->last_gamedata_time = nowtime; - NET_Log("server: stored tic %d for player %d", seq + i, player); + client->last_gamedata_time = nowtime; + net_log_info("server: stored tic %zu for player %d", seq + i, player); } - // Higher acknowledgement point? + /* Higher acknowledgement point? */ - if (ackseq > client->acknowledged) + if (ackseq > client->acknowledged) { - NET_Log("server: acknowledged up to %d", ackseq); - client->acknowledged = ackseq; + net_log_info("server: acknowledged up to %d", ackseq); + client->acknowledged = ackseq; } - // Has this been received out of sequence, ie. have we not received - // all tics before the first tic in this packet? If so, send a - // resend request. + /* Has this been received out of sequence, ie. have we not received + * all tics before the first tic in this packet? If so, send a + * resend request. + */ - //printf("SV: %p: %i\n", client, seq); + resend_end = seq - recvwindow_start; - resend_end = seq - recvwindow_start; + if (resend_end <= 0) return; - if (resend_end <= 0) - return; + if (resend_end >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) + { + resend_end = CONFIG_GAMES_NXDOOM_NET_BACKUPTICS - 1; + } - if (resend_end >= BACKUPTICS) - resend_end = BACKUPTICS - 1; + index = resend_end - 1; + resend_start = resend_end; - index = resend_end - 1; - resend_start = resend_end; - - while (index >= 0) + while (index >= 0) { - recvobj = &recvwindow[index][player]; + recvobj = &recvwindow[index][player]; - if (recvobj->active) + if (recvobj->active) { - // ended our run of unreceived tics + /* ended our run of unreceived tics */ - break; + break; } - if (recvobj->resend_time != 0) + if (recvobj->resend_time != 0) { - // Already sent a resend request for this tic + /* Already sent a resend request for this tic */ - break; + break; } - resend_start = index; - --index; + resend_start = index; + --index; } - // Possibly send a resend request - if (resend_start < resend_end) + /* Possibly send a resend request */ + + if (resend_start < resend_end) { - NET_Log("server: request resend for %d-%d before %d", - recvwindow_start + resend_start, - recvwindow_start + resend_end - 1, seq); - NET_SV_SendResendRequest(client, - recvwindow_start + resend_start, + net_log_info("server: request resend for %d-%d before %d", + recvwindow_start + resend_start, + recvwindow_start + resend_end - 1, seq); + net_sv_send_resend_request(client, recvwindow_start + resend_start, recvwindow_start + resend_end - 1); } } -static void NET_SV_ParseGameDataACK(net_packet_t *packet, net_client_t *client) +static void net_sv_parse_game_data_ack(net_packet_t *packet, + net_client_t *client) { - unsigned int ackseq; + unsigned int ackseq; - NET_Log("server: processing game data ack packet"); + net_log_info("server: processing game data ack packet"); - if (server_state != SERVER_IN_GAME) + if (server_state != SERVER_IN_GAME) { - NET_Log("server: error: not in game state, server_state=%d", - server_state); - return; + net_log_err("server: not in game state, server_state=%d", + server_state); + return; } - // Read header + /* Read header */ - if (!NET_ReadInt8(packet, &ackseq)) + if (!net_read_int8(packet, &ackseq)) { - NET_Log("server: error: missing acknowledgement field"); - return; + net_log_err("server: missing acknowledgement field"); + return; } - // Expand 8-bit values to the full sequence number + /* Expand 8-bit values to the full sequence number */ - ackseq = NET_SV_ExpandTicNum(ackseq); + ackseq = net_sv_expand_ticnum(ackseq); - // Higher acknowledgement point than we already have? + /* Higher acknowledgement point than we already have? */ - if (ackseq > client->acknowledged) + if (ackseq > client->acknowledged) { - NET_Log("server: acknowledged up to %d", ackseq); - client->acknowledged = ackseq; + net_log_info("server: acknowledged up to %d", ackseq); + client->acknowledged = ackseq; } } -static void NET_SV_SendTics(net_client_t *client, - unsigned int start, unsigned int end) +static void net_sv_send_tics(net_client_t *client, unsigned int start, + unsigned int end) { - net_packet_t *packet; - unsigned int i; + net_packet_t *packet; + unsigned int i; - packet = NET_NewPacket(500); + packet = net_new_packet(500); - NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); + net_write_int16(packet, NET_PACKET_TYPE_GAMEDATA); - // Send the start tic and number of tics + /* Send the start tic and number of tics */ - NET_WriteInt8(packet, start & 0xff); - NET_WriteInt8(packet, end-start + 1); + net_write_int8(packet, start & 0xff); + net_write_int8(packet, end - start + 1); - // Write the tics + /* Write the tics */ - for (i=start; i<=end; ++i) + for (i = start; i <= end; ++i) { - net_full_ticcmd_t *cmd; + net_full_ticcmd_t *cmd; - cmd = &client->sendqueue[i % BACKUPTICS]; + cmd = &client->sendqueue[i % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; - if (i != cmd->seq) + if (i != cmd->seq) { - I_Error("Wanted to send %i, but %i is in its place", i, cmd->seq); + i_error("Wanted to send %i, but %i is in its place", i, cmd->seq); } - // Add command - - NET_WriteFullTiccmd(packet, cmd, sv_settings.lowres_turn); + /* Add command */ + + net_write_full_ticcmd(packet, cmd, sv_settings.lowres_turn); } - - // Send packet - NET_Conn_SendPacket(&client->connection, packet); - - NET_FreePacket(packet); + /* Send packet */ + + net_conn_send_packet(&client->connection, packet); + + net_free_packet(packet); } -// Parse a retransmission request from a client +/* Parse a retransmission request from a client */ -static void NET_SV_ParseResendRequest(net_packet_t *packet, net_client_t *client) +static void net_sv_parse_resend_request(net_packet_t *packet, + net_client_t *client) { - unsigned int start, last; - unsigned int num_tics; - unsigned int i; + unsigned int start; + unsigned int last; + unsigned int num_tics; + unsigned int i; - NET_Log("server: processing resend request"); + net_log_info("server: processing resend request"); - // Read the starting tic and number of tics + /* Read the starting tic and number of tics */ - if (!NET_ReadInt32(packet, &start) - || !NET_ReadInt8(packet, &num_tics)) + if (!net_read_int32(packet, &start) || !net_read_int8(packet, &num_tics)) { - NET_Log("server: error: missing fields for resend"); - return; + net_log_err("server: missing fields for resend"); + return; } - //printf("SV: %p: resend %i-%i\n", client, start, start+num_tics-1); - - // Check we have all the requested tics + /* Check we have all the requested tics */ - last = start + num_tics - 1; + last = start + num_tics - 1; - for (i=start; i<=last; ++i) + for (i = start; i <= last; ++i) { - net_full_ticcmd_t *cmd; + net_full_ticcmd_t *cmd; - cmd = &client->sendqueue[i % BACKUPTICS]; + cmd = &client->sendqueue[i % CONFIG_GAMES_NXDOOM_NET_BACKUPTICS]; - if (i != cmd->seq) + if (i != cmd->seq) { - // We do not have the requested tic (any more) - // This is pretty fatal. We could disconnect the client, - // but then again this could be a spoofed packet. Just - // ignore it. - NET_Log("server: error: don't have tic %d any more, " - "can't resend", i); - return; + /* We do not have the requested tic (any more) + * This is pretty fatal. We could disconnect the client, + * but then again this could be a spoofed packet. Just + * ignore it. + */ + + net_log_err("server: don't have tic %d any more, " + "can't resend", + i); + return; } } - // Resend those tics - NET_Log("server: resending tics %d-%d", start, last); - NET_SV_SendTics(client, start, last); -} + /* Resend those tics */ -// Send a response back to the client + net_log_info("server: resending tics %d-%d", start, last); + net_sv_send_tics(client, start, last); +} -void NET_SV_SendQueryResponse(net_addr_t *addr) +static void net_sv_parse_hole_punch(net_packet_t *packet) { - net_packet_t *reply; - net_querydata_t querydata; - int p; - - // Version - - querydata.version = PACKAGE_STRING; + const char *addr_string; + net_packet_t *sendpacket; + net_addr_t *addr; - // Server state - - querydata.server_state = server_state; - - // Number of players/maximum players - - querydata.num_players = NET_SV_NumPlayers(); - querydata.max_players = NET_SV_MaxPlayers(); - - // Game mode/mission - - querydata.gamemode = sv_gamemode; - querydata.gamemission = sv_gamemission; - - //! - // @category net - // @arg - // - // When starting a network server, specify a name for the server. - // - - p = M_CheckParmWithArgs("-servername", 1); - - if (p > 0) + addr_string = net_read_string(packet); + if (addr_string == NULL) { - querydata.description = myargv[p + 1]; + net_log_err("server: hole punch request but no address provided"); + return; } - else + + addr = net_resolve_address(server_context, addr_string); + if (addr == NULL) { - querydata.description = "Unnamed server"; + net_log_err("server: failed to resolve address: %s", addr_string); + return; } - // Send it and we're done. - NET_Log("server: sending query response to %s", NET_AddrToString(addr)); - reply = NET_NewPacket(64); - NET_WriteInt16(reply, NET_PACKET_TYPE_QUERY_RESPONSE); - NET_WriteQueryData(reply, &querydata); - NET_SendPacket(addr, reply); - NET_FreePacket(reply); + sendpacket = net_new_packet(16); + net_write_int16(sendpacket, NET_PACKET_TYPE_NAT_HOLE_PUNCH); + net_send_packet(addr, sendpacket); + net_free_packet(sendpacket); + net_release_address(addr); + net_log_info("server: sent hole punch to %s", addr_string); } -static void NET_SV_ParseHolePunch(net_packet_t *packet) +static void net_sv_master_packet(net_packet_t *packet) { - const char *addr_string; - net_packet_t *sendpacket; - net_addr_t *addr; + unsigned int packet_type; + + /* Read the packet type */ - addr_string = NET_ReadString(packet); - if (addr_string == NULL) + if (!net_read_int16(packet, &packet_type)) { - NET_Log("server: error: hole punch request but no address provided"); - return; + net_log_err("server: no packet type in master server message"); + return; } - addr = NET_ResolveAddress(server_context, addr_string); - if (addr == NULL) + net_log_info("server: packet from master server; type %d", packet_type); + net_log_packet(packet); + + switch (packet_type) { - NET_Log("server: error: failed to resolve address: %s", addr_string); - return; - } + case NET_MASTER_PACKET_TYPE_ADD_RESPONSE: + net_query_add_response(packet); + break; - sendpacket = NET_NewPacket(16); - NET_WriteInt16(sendpacket, NET_PACKET_TYPE_NAT_HOLE_PUNCH); - NET_SendPacket(addr, sendpacket); - NET_FreePacket(sendpacket); - NET_ReleaseAddress(addr); - NET_Log("server: sent hole punch to %s", addr_string); + case NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH: + net_sv_parse_hole_punch(packet); + break; + } } -static void NET_SV_MasterPacket(net_packet_t *packet) +/* Send a response back to the client */ + +static void net_sv_send_query_response(net_addr_t *addr) { - unsigned int packet_type; + net_packet_t *reply; + net_querydata_t querydata; + int p; - // Read the packet type + /* Version */ - if (!NET_ReadInt16(packet, &packet_type)) - { - NET_Log("server: error: no packet type in master server message"); - return; - } + querydata.version = PACKAGE_STRING; - NET_Log("server: packet from master server; type %d", packet_type); - NET_LogPacket(packet); + /* Server state */ - switch (packet_type) - { - case NET_MASTER_PACKET_TYPE_ADD_RESPONSE: - NET_Query_AddResponse(packet); - break; + querydata.server_state = server_state; + + /* Number of players/maximum players */ + + querydata.num_players = net_sv_num_players(); + querydata.max_players = net_sv_max_players(); - case NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH: - NET_SV_ParseHolePunch(packet); - break; + /* Game mode/mission */ + + querydata.gamemode = sv_gamemode; + querydata.gamemission = sv_gamemission; + + /* @category net + * @arg + * + * When starting a network server, specify a name for the server. + */ + + p = m_check_parm_with_args("-servername", 1); + + if (p > 0) + { + querydata.description = myargv[p + 1]; } + else + { + querydata.description = "Unnamed server"; + } + + /* Send it and we're done. */ + + net_log_info("server: sending query response to %s", + net_addr_to_string(addr)); + reply = net_new_packet(64); + net_write_int16(reply, NET_PACKET_TYPE_QUERY_RESPONSE); + net_write_query_data(reply, &querydata); + net_send_packet(addr, reply); + net_free_packet(reply); } -// Process a packet received by the server +/* Process a packet received by the server */ -static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) +static void net_sv_packet(net_packet_t *packet, net_addr_t *addr) { - net_client_t *client; - unsigned int packet_type; + net_client_t *client; + unsigned int packet_type; - // Response from master server? + /* Response from master server? */ - if (addr != NULL && addr == master_server) + if (addr != NULL && addr == master_server) { - NET_SV_MasterPacket(packet); - return; + net_sv_master_packet(packet); + return; } - // Find which client this packet came from + /* Find which client this packet came from */ - client = NET_SV_FindClient(addr); + client = net_sv_find_client(addr); - // Read the packet type + /* Read the packet type */ - if (!NET_ReadInt16(packet, &packet_type)) + if (!net_read_int16(packet, &packet_type)) { - // no packet type + /* no packet type */ - return; + return; } - NET_Log("server: packet from %s; type %d", NET_AddrToString(addr), - packet_type & ~NET_RELIABLE_PACKET); - NET_LogPacket(packet); + net_log_info("server: packet from %s; type %d", net_addr_to_string(addr), + packet_type & ~NET_RELIABLE_PACKET); + net_log_packet(packet); - if (packet_type == NET_PACKET_TYPE_SYN) + if (packet_type == NET_PACKET_TYPE_SYN) { - NET_SV_ParseSYN(packet, client, addr); + net_sv_parse_syn(packet, client, addr); } - else if (packet_type == NET_PACKET_TYPE_QUERY) + else if (packet_type == NET_PACKET_TYPE_QUERY) { - NET_SV_SendQueryResponse(addr); + net_sv_send_query_response(addr); } - else if (client == NULL) + else if (client == NULL) { - // Must come from a valid client; ignore otherwise + /* Must come from a valid client; ignore otherwise */ } - else if (NET_Conn_Packet(&client->connection, packet, &packet_type)) + else if (net_conn_packet(&client->connection, packet, &packet_type)) { - // Packet was eaten by the common connection code + /* Packet was eaten by the common connection code */ } - else + else { - //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type); - - switch (packet_type) + switch (packet_type) { - case NET_PACKET_TYPE_GAMESTART: - NET_SV_ParseGameStart(packet, client); - break; - case NET_PACKET_TYPE_LAUNCH: - NET_SV_ParseLaunch(packet, client); - break; - case NET_PACKET_TYPE_GAMEDATA: - NET_SV_ParseGameData(packet, client); - break; - case NET_PACKET_TYPE_GAMEDATA_ACK: - NET_SV_ParseGameDataACK(packet, client); - break; - case NET_PACKET_TYPE_GAMEDATA_RESEND: - NET_SV_ParseResendRequest(packet, client); - break; - default: - // unknown packet type - - break; + case NET_PACKET_TYPE_GAMESTART: + net_sv_parse_game_start(packet, client); + break; + case NET_PACKET_TYPE_LAUNCH: + net_sv_parse_launch(packet, client); + break; + case NET_PACKET_TYPE_GAMEDATA: + net_sv_parse_game_data(packet, client); + break; + case NET_PACKET_TYPE_GAMEDATA_ACK: + net_sv_parse_game_data_ack(packet, client); + break; + case NET_PACKET_TYPE_GAMEDATA_RESEND: + net_sv_parse_resend_request(packet, client); + break; + default: + break; /* unknown packet type */ } } } - -static void NET_SV_PumpSendQueue(net_client_t *client) +static void net_sv_pump_send_queue(net_client_t *client) { - net_full_ticcmd_t cmd; - int recv_index; - int num_players; - int i; - int starttic, endtic; + net_full_ticcmd_t cmd; + int recv_index; + int num_players; + int i; + int starttic; + int endtic; - // If a client has not sent any acknowledgments for a while, - // wait until they catch up. + /* If a client has not sent any acknowledgments for a while, + * wait until they catch up. + */ - if (client->sendseq - NET_SV_LatestAcknowledged() > 40) + if (client->sendseq - net_sv_latest_acknowledged() > 40) { - return; + return; } - - // Work out the index into the receive window - - recv_index = client->sendseq - recvwindow_start; - if (recv_index < 0 || recv_index >= BACKUPTICS) + /* Work out the index into the receive window */ + + recv_index = client->sendseq - recvwindow_start; + + if (recv_index < 0 || recv_index >= CONFIG_GAMES_NXDOOM_NET_BACKUPTICS) { - return; + return; } - // Check if we can generate a new entry for the send queue - // using the data in recvwindow. + /* Check if we can generate a new entry for the send queue + * using the data in recvwindow. + */ - num_players = 0; + num_players = 0; - for (i=0; isendseq > recvwindow_start + 10) + if (num_players == 0 && client->sendseq > recvwindow_start + 10) { - return; + return; } - // We have all data we need to generate a command for this tic. - - cmd.seq = client->sendseq; + /* We have all data we need to generate a command for this tic. */ - // Add ticcmds from all players + cmd.seq = client->sendseq; - cmd.latency = 0; + /* Add ticcmds from all players */ - for (i=0; idiff; + cmd.cmds[i] = recvobj->diff; - if (recvobj->latency > cmd.latency) - cmd.latency = recvobj->latency; + if (recvobj->latency > cmd.latency) cmd.latency = recvobj->latency; } - //printf("SV: %i: latency %i\n", client->player_number, cmd.latency); + /* Add into the queue */ - // Add into the queue + client->sendqueue[client->sendseq % + CONFIG_GAMES_NXDOOM_NET_BACKUPTICS] = cmd; - client->sendqueue[client->sendseq % BACKUPTICS] = cmd; + /* Transmit the new tic to the client */ - // Transmit the new tic to the client + starttic = client->sendseq - sv_settings.extratics; + endtic = client->sendseq; - starttic = client->sendseq - sv_settings.extratics; - endtic = client->sendseq; + if (starttic < 0) starttic = 0; - if (starttic < 0) - starttic = 0; + net_log_info("server: send tics %d-%d to %s", starttic, endtic, + net_addr_to_string(client->addr)); + net_sv_send_tics(client, starttic, endtic); + + ++client->sendseq; +} - NET_Log("server: send tics %d-%d to %s", starttic, endtic, - NET_AddrToString(client->addr)); - NET_SV_SendTics(client, starttic, endtic); +/* Called when all players have disconnected. Return to listening for + * players to start a new game, and disconnect any drones still connected. + */ - ++client->sendseq; +static void net_sv_game_ended(void) +{ + int i; + + server_state = SERVER_WAITING_LAUNCH; + sv_gamemode = indetermined; + + for (i = 0; i < MAXNETNODES; ++i) + { + if (clients[i].active) + { + net_sv_disconnect_client(&clients[i]); + } + } } -// Prevent against deadlock: resend requests are usually only -// triggered if we miss a packet and receive the next one. -// If we miss a whole load of packets, we can end up in a -// deadlock situation where the client will not send any more. -// If we don't receive any game data in a while, trigger a resend -// request for the next tic we're expecting. +/* Prevent against deadlock: resend requests are usually only + * triggered if we miss a packet and receive the next one. + * If we miss a whole load of packets, we can end up in a + * deadlock situation where the client will not send any more. + * If we don't receive any game data in a while, trigger a resend + * request for the next tic we're expecting. + */ -void NET_SV_CheckDeadlock(net_client_t *client) +static void net_sv_check_deadlock(net_client_t *client) { - int nowtime; - int i; + int nowtime; + int i; - // Don't expect game data from clients. + /* Don't expect game data from clients. */ - if (client->drone) + if (client->drone) { - return; + return; } - nowtime = I_GetTimeMS(); + nowtime = i_get_time_ms(); - // If we haven't received anything for a long time, it may be a deadlock. + /* If we haven't received anything for a long time, it may be a deadlock. */ - if (nowtime - client->last_gamedata_time > 1000) + if (nowtime - client->last_gamedata_time > 1000) { - NET_Log("server: no gamedata from %s since %d - deadlock?", - NET_AddrToString(client->addr), - client->last_gamedata_time); + net_log_warn("server: no gamedata from %s since %d - deadlock?", + net_addr_to_string(client->addr), + client->last_gamedata_time); - // Search the receive window for the first tic we are expecting - // from this player. + /* Search the receive window for the first tic we are expecting + * from this player. + */ - for (i=0; iplayer_number].active) + if (!recvwindow[i][client->player_number].active) { - NET_Log("server: deadlock: sending resend request for %d-%d", - recvwindow_start + i, recvwindow_start + i + 5); + net_log_warn( + "server: deadlock: sending resend request for %d-%d", + recvwindow_start + i, recvwindow_start + i + 5); - // Found a tic we haven't received. Send a resend request. + /* Found a tic we haven't received. Send a resend request. */ - NET_SV_SendResendRequest(client, - recvwindow_start + i, + net_sv_send_resend_request(client, recvwindow_start + i, recvwindow_start + i + 5); - client->last_gamedata_time = nowtime; - break; + client->last_gamedata_time = nowtime; + break; } } - // If we sent a resend request to break the deadlock, also trigger a - // resend of any tics we have sitting in the send queue, in case the - // client is blocked waiting on tics from us that have been lost. - // This fixes deadlock with some older clients which do not send - // resends to break deadlock. - if (i < BACKUPTICS && client->sendseq > client->acknowledged) - { - NET_Log("server: also resending tics %d-%d to break deadlock", - client->acknowledged, client->sendseq - 1); - NET_SV_SendTics(client, client->acknowledged, client->sendseq - 1); - } - } -} - -// Called when all players have disconnected. Return to listening for -// players to start a new game, and disconnect any drones still connected. - -static void NET_SV_GameEnded(void) -{ - int i; + /* If we sent a resend request to break the deadlock, also trigger a + * resend of any tics we have sitting in the send queue, in case the + * client is blocked waiting on tics from us that have been lost. + * This fixes deadlock with some older clients which do not send + * resends to break deadlock. + */ - server_state = SERVER_WAITING_LAUNCH; - sv_gamemode = indetermined; - - for (i=0; isendseq > client->acknowledged) { - NET_SV_DisconnectClient(&clients[i]); + net_log_warn("server: also resending tics %d-%d to break deadlock", + client->acknowledged, client->sendseq - 1); + net_sv_send_tics(client, client->acknowledged, + client->sendseq - 1); } } } -// Perform any needed action on a client +/* Perform any needed action on a client */ -static void NET_SV_RunClient(net_client_t *client) +static void net_sv_run_client(net_client_t *client) { - // Run common code + /* Run common code */ - NET_Conn_Run(&client->connection); + net_conn_run(&client->connection); - if (client->connection.state == NET_CONN_STATE_DISCONNECTED - && client->connection.disconnect_reason == NET_DISCONNECT_TIMEOUT) + if (client->connection.state == NET_CONN_STATE_DISCONNECTED && + client->connection.disconnect_reason == NET_DISCONNECT_TIMEOUT) { - NET_Log("server: client at %s timed out", - NET_AddrToString(client->addr)); - NET_SV_BroadcastMessage("Client '%s' timed out and disconnected", - client->name); + net_log_warn("server: client at %s timed out", + net_addr_to_string(client->addr)); + net_sv_broadcast_message("Client '%s' timed out and disconnected", + client->name); } - // Is this client disconnected? + /* Is this client disconnected? */ - if (client->connection.state == NET_CONN_STATE_DISCONNECTED) + if (client->connection.state == NET_CONN_STATE_DISCONNECTED) { - client->active = false; + client->active = false; - // If we were about to start a game, any player disconnecting - // should cause an abort. + /* If we were about to start a game, any player disconnecting + * should cause an abort. + */ - if (server_state == SERVER_WAITING_START && !client->drone) + if (server_state == SERVER_WAITING_START && !client->drone) { - NET_SV_BroadcastMessage("Game startup aborted because " - "player '%s' disconnected.", - client->name); - NET_SV_GameEnded(); + net_sv_broadcast_message("Game startup aborted because " + "player '%s' disconnected.", + client->name); + net_sv_game_ended(); } - free(client->name); - NET_ReleaseAddress(client->addr); + free(client->name); + net_release_address(client->addr); - // Are there any clients left connected? If not, return the - // server to the waiting-for-players state. - // - // Disconnect any drones still connected. + /* Are there any clients left connected? If not, return the + * server to the waiting-for-players state. + * + * Disconnect any drones still connected. + */ - if (NET_SV_NumPlayers() <= 0) + if (net_sv_num_players() <= 0) { - NET_Log("server: no player clients left, game ended"); - NET_SV_GameEnded(); + net_log_info("server: no player clients left, game ended"); + net_sv_game_ended(); } } - if (!ClientConnected(client)) + if (!client_connected(client)) { - // client has not yet finished connecting + /* client has not yet finished connecting */ - return; + return; } - if (server_state == SERVER_WAITING_LAUNCH) + if (server_state == SERVER_WAITING_LAUNCH) { - // Waiting for the game to start + /* Waiting for the game to start */ - // Send information once every second + /* Send information once every second */ - if (client->last_send_time < 0 - || I_GetTimeMS() - client->last_send_time > 1000) + if (client->last_send_time < 0 || + i_get_time_ms() - client->last_send_time > 1000) { - NET_SV_SendWaitingData(client); - client->last_send_time = I_GetTimeMS(); + net_sv_send_waiting_data(client); + client->last_send_time = i_get_time_ms(); } } - if (server_state == SERVER_IN_GAME) + if (server_state == SERVER_IN_GAME) { - NET_SV_PumpSendQueue(client); - NET_SV_CheckDeadlock(client); + net_sv_pump_send_queue(client); + net_sv_check_deadlock(client); } } -// Add a network module to the server context - -void NET_SV_AddModule(net_module_t *module) +static void update_master_server(void) { - module->InitServer(); - NET_AddModule(server_context, module); -} + unsigned int now; -// Initialize server and wait for connections + now = i_get_time_ms(); -void NET_SV_Init(void) -{ - int i; + /* The address of the master server can change. Periodically + * re-resolve the master server to update. + */ - // initialize send/receive context + if (now - master_resolve_time > MASTER_RESOLVE_PERIOD * 1000) + { + net_addr_t *new_addr; - server_context = NET_NewContext(); + new_addr = net_query_resolve_master(server_context); + net_release_address(master_server); + master_server = new_addr; - // no clients yet - - for (i=0; i MASTER_REFRESH_PERIOD * 1000) + { + net_query_add_to_master(master_server); + master_refresh_time = now; + } } -static void UpdateMasterServer(void) -{ - unsigned int now; +/**************************************************************************** + * Public Functions + ****************************************************************************/ - now = I_GetTimeMS(); +/* Add a network module to the server context */ - // The address of the master server can change. Periodically - // re-resolve the master server to update. +void net_sv_add_module(net_module_t *module) +{ + module->init_server(); + net_add_module(server_context, module); +} - if (now - master_resolve_time > MASTER_RESOLVE_PERIOD * 1000) - { - net_addr_t *new_addr; +/* Initialize server and wait for connections */ - new_addr = NET_Query_ResolveMaster(server_context); - NET_ReleaseAddress(master_server); - master_server = new_addr; +void net_sv_init(void) +{ + int i; - master_resolve_time = now; - } + /* initialize send/receive context */ + + server_context = net_new_context(); - // Possibly refresh our registration with the master server. + /* no clients yet */ - if (now - master_refresh_time > MASTER_REFRESH_PERIOD * 1000) + for (i = 0; i < MAXNETNODES; ++i) { - NET_Query_AddToMaster(master_server); - master_refresh_time = now; + clients[i].active = false; } + + net_sv_assign_players(); + + server_state = SERVER_WAITING_LAUNCH; + sv_gamemode = indetermined; + server_initialized = true; } -void NET_SV_RegisterWithMaster(void) +void net_sv_register_with_master(void) { - //! - // @category net - // - // When running a server, don't register with the global master server. - // Implies -server. - // + /* @category net + * + * When running a server, don't register with the global master server. + * Implies -server. + */ - if (!M_CheckParm("-privateserver")) + if (!m_check_parm("-privateserver")) { - master_server = NET_Query_ResolveMaster(server_context); + master_server = net_query_resolve_master(server_context); } - else + else { - master_server = NULL; + master_server = NULL; } - // Send request. + /* Send request. */ - if (master_server != NULL) + if (master_server != NULL) { - NET_Query_AddToMaster(master_server); - master_refresh_time = I_GetTimeMS(); - master_resolve_time = master_refresh_time; + net_query_add_to_master(master_server); + master_refresh_time = i_get_time_ms(); + master_resolve_time = master_refresh_time; } } -// Run server code to check for new packets/send packets as the server -// requires +/* Run server code to check for new packets/send packets as the server + * requires + */ -void NET_SV_Run(void) +void net_sv_run(void) { - net_addr_t *addr; - net_packet_t *packet; - int i; + net_addr_t *addr; + net_packet_t *packet; + int i; - if (!server_initialized) + if (!server_initialized) { - return; + return; } - while (NET_RecvPacket(server_context, &addr, &packet)) + while (net_recv_packet(server_context, &addr, &packet)) { - NET_SV_Packet(packet, addr); - NET_FreePacket(packet); - NET_ReleaseAddress(addr); + net_sv_packet(packet, addr); + net_free_packet(packet); + net_release_address(addr); } - if (master_server != NULL) + if (master_server != NULL) { - UpdateMasterServer(); + update_master_server(); } - // "Run" any clients that may have things to do, independent of responses - // to received packets + /* "Run" any clients that may have things to do, independent of responses + * to received packets + */ - for (i=0; i 5000) + if (i_get_time_ms() - start_time > 5000) { - running = false; - fprintf(stderr, "SV: Timed out waiting for clients to disconnect.\n"); + running = false; + fprintf(stderr, + "SV: Timed out waiting for clients to disconnect.\n"); } - // Run the client code in case this is a loopback client. + /* Run the client code in case this is a loopback client. */ - NET_CL_Run(); - NET_SV_Run(); + net_cl_run(); + net_sv_run(); - // Don't hog the CPU + /* Don't hog the CPU */ - I_Sleep(1); + usleep(1000); } } diff --git a/games/NXDoom/src/net_server.h b/games/NXDoom/src/net_server.h index b9de7456ef8..9d1db98b928 100644 --- a/games/NXDoom/src/net_server.h +++ b/games/NXDoom/src/net_server.h @@ -1,42 +1,51 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Network server code -// +/**************************************************************************** + * apps/games/NXDoom/src/net_server.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Network server code + * + ****************************************************************************/ #ifndef NET_SERVER_H #define NET_SERVER_H -// initialize server and wait for connections +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -void NET_SV_Init(void); +/* initialize server and wait for connections */ -// run server: check for new packets received etc. +void net_sv_init(void); -void NET_SV_Run(void); +/* run server: check for new packets received etc. */ -// Shut down the server -// Blocks until all clients disconnect, or until a 5 second timeout +void net_sv_run(void); -void NET_SV_Shutdown(void); +/* Shut down the server + * Blocks until all clients disconnect, or until a 5 second timeout + */ -// Add a network module to the context used by the server +void net_sv_shutdown(void); -void NET_SV_AddModule(net_module_t *module); +/* Add a network module to the context used by the server */ -// Register server with master server. +void net_sv_add_module(net_module_t *module); -void NET_SV_RegisterWithMaster(void); +/* Register server with master server. */ -#endif /* #ifndef NET_SERVER_H */ +void net_sv_register_with_master(void); +#endif /* NET_SERVER_H */ diff --git a/games/NXDoom/src/net_structrw.c b/games/NXDoom/src/net_structrw.c index 2dbd2740a13..371aa4f7a9e 100644 --- a/games/NXDoom/src/net_structrw.c +++ b/games/NXDoom/src/net_structrw.c @@ -1,18 +1,27 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// Reading and writing various structures into packets -// +/**************************************************************************** + * apps/games/NXDoom/src/net_structrw.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * Reading and writing various structures into packets + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -24,653 +33,682 @@ #include "net_packet.h" #include "net_structrw.h" -// String names for the enum values in net_protocol_t, which are what is -// sent over the wire. Every enum value must have an entry in this list. -static struct +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct protocol_name +{ + net_protocol_t protocol; + const char *name; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* String names for the enum values in net_protocol_t, which are what is + * sent over the wire. Every enum value must have an entry in this list. + */ + +static struct protocol_name g_protocol_names[] = { - net_protocol_t protocol; - const char *name; -} protocol_names[] = { - {NET_PROTOCOL_CHOCOLATE_DOOM_0, "CHOCOLATE_DOOM_0"}, + {NET_PROTOCOL_CHOCOLATE_DOOM_0, "CHOCOLATE_DOOM_0"}, }; -void NET_WriteConnectData(net_packet_t *packet, net_connect_data_t *data) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static boolean net_read_blob(net_packet_t *packet, uint8_t *buf, size_t len) +{ + unsigned int b; + int i; + + for (i = 0; i < len; ++i) + { + if (!net_read_int8(packet, &b)) + { + return false; + } + + buf[i] = b; + } + + return true; +} + +static void net_write_blob(net_packet_t *packet, uint8_t *buf, size_t len) +{ + int i; + + for (i = 0; i < len; ++i) + { + net_write_int8(packet, buf[i]); + } +} + +static net_protocol_t parse_protocol_name(const char *name) { - NET_WriteInt8(packet, data->gamemode); - NET_WriteInt8(packet, data->gamemission); - NET_WriteInt8(packet, data->lowres_turn); - NET_WriteInt8(packet, data->drone); - NET_WriteInt8(packet, data->max_players); - NET_WriteInt8(packet, data->is_freedoom); - NET_WriteSHA1Sum(packet, data->wad_sha1sum); - NET_WriteSHA1Sum(packet, data->deh_sha1sum); - NET_WriteInt8(packet, data->player_class); + int i; + + for (i = 0; i < arrlen(g_protocol_names); ++i) + { + if (!strcmp(g_protocol_names[i].name, name)) + { + return g_protocol_names[i].protocol; + } + } + + return NET_PROTOCOL_UNKNOWN; } -boolean NET_ReadConnectData(net_packet_t *packet, net_connect_data_t *data) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void net_write_connect_data(net_packet_t *packet, net_connect_data_t *data) { - return NET_ReadInt8(packet, (unsigned int *) &data->gamemode) - && NET_ReadInt8(packet, (unsigned int *) &data->gamemission) - && NET_ReadInt8(packet, (unsigned int *) &data->lowres_turn) - && NET_ReadInt8(packet, (unsigned int *) &data->drone) - && NET_ReadInt8(packet, (unsigned int *) &data->max_players) - && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom) - && NET_ReadSHA1Sum(packet, data->wad_sha1sum) - && NET_ReadSHA1Sum(packet, data->deh_sha1sum) - && NET_ReadInt8(packet, (unsigned int *) &data->player_class); + net_write_int8(packet, data->gamemode); + net_write_int8(packet, data->gamemission); + net_write_int8(packet, data->lowres_turn); + net_write_int8(packet, data->drone); + net_write_int8(packet, data->max_players); + net_write_int8(packet, data->is_freedoom); + net_write_sha1_sum(packet, data->wad_sha1sum); + net_write_sha1_sum(packet, data->deh_sha1sum); + net_write_int8(packet, data->player_class); } -void NET_WriteSettings(net_packet_t *packet, net_gamesettings_t *settings) +boolean net_read_connect_data(net_packet_t *packet, net_connect_data_t *data) { - int i; - - NET_WriteInt8(packet, settings->ticdup); - NET_WriteInt8(packet, settings->extratics); - NET_WriteInt8(packet, settings->deathmatch); - NET_WriteInt8(packet, settings->nomonsters); - NET_WriteInt8(packet, settings->fast_monsters); - NET_WriteInt8(packet, settings->respawn_monsters); - NET_WriteInt8(packet, settings->episode); - NET_WriteInt8(packet, settings->map); - NET_WriteInt8(packet, settings->skill); - NET_WriteInt8(packet, settings->gameversion); - NET_WriteInt8(packet, settings->lowres_turn); - NET_WriteInt8(packet, settings->new_sync); - NET_WriteInt32(packet, settings->timelimit); - NET_WriteInt8(packet, settings->loadgame); - NET_WriteInt8(packet, settings->random); - NET_WriteInt8(packet, settings->num_players); - NET_WriteInt8(packet, settings->consoleplayer); - - for (i = 0; i < settings->num_players; ++i) - { - NET_WriteInt8(packet, settings->player_classes[i]); + return net_read_int8(packet, (unsigned int *)&data->gamemode) && + net_read_int8(packet, (unsigned int *)&data->gamemission) && + net_read_int8(packet, (unsigned int *)&data->lowres_turn) && + net_read_int8(packet, (unsigned int *)&data->drone) && + net_read_int8(packet, (unsigned int *)&data->max_players) && + net_read_int8(packet, (unsigned int *)&data->is_freedoom) && + net_read_sha1_sum(packet, data->wad_sha1sum) && + net_read_sha1_sum(packet, data->deh_sha1sum) && + net_read_int8(packet, (unsigned int *)&data->player_class); +} + +void net_write_settings(net_packet_t *packet, net_gamesettings_t *settings) +{ + int i; + + net_write_int8(packet, settings->ticdup); + net_write_int8(packet, settings->extratics); + net_write_int8(packet, settings->deathmatch); + net_write_int8(packet, settings->nomonsters); + net_write_int8(packet, settings->fast_monsters); + net_write_int8(packet, settings->respawn_monsters); + net_write_int8(packet, settings->episode); + net_write_int8(packet, settings->map); + net_write_int8(packet, settings->skill); + net_write_int8(packet, settings->gameversion); + net_write_int8(packet, settings->lowres_turn); + net_write_int8(packet, settings->new_sync); + net_write_int32(packet, settings->timelimit); + net_write_int8(packet, settings->loadgame); + net_write_int8(packet, settings->random); + net_write_int8(packet, settings->num_players); + net_write_int8(packet, settings->consoleplayer); + + for (i = 0; i < settings->num_players; ++i) + { + net_write_int8(packet, settings->player_classes[i]); } } -boolean NET_ReadSettings(net_packet_t *packet, net_gamesettings_t *settings) +boolean net_read_settings(net_packet_t *packet, net_gamesettings_t *settings) { - boolean success; - int i; - - success = NET_ReadInt8(packet, (unsigned int *) &settings->ticdup) - && NET_ReadInt8(packet, (unsigned int *) &settings->extratics) - && NET_ReadInt8(packet, (unsigned int *) &settings->deathmatch) - && NET_ReadInt8(packet, (unsigned int *) &settings->nomonsters) - && NET_ReadInt8(packet, (unsigned int *) &settings->fast_monsters) - && NET_ReadInt8(packet, (unsigned int *) &settings->respawn_monsters) - && NET_ReadInt8(packet, (unsigned int *) &settings->episode) - && NET_ReadInt8(packet, (unsigned int *) &settings->map) - && NET_ReadSInt8(packet, &settings->skill) - && NET_ReadInt8(packet, (unsigned int *) &settings->gameversion) - && NET_ReadInt8(packet, (unsigned int *) &settings->lowres_turn) - && NET_ReadInt8(packet, (unsigned int *) &settings->new_sync) - && NET_ReadInt32(packet, (unsigned int *) &settings->timelimit) - && NET_ReadSInt8(packet, (signed int *) &settings->loadgame) - && NET_ReadInt8(packet, (unsigned int *) &settings->random) - && NET_ReadInt8(packet, (unsigned int *) &settings->num_players) - && NET_ReadSInt8(packet, (signed int *) &settings->consoleplayer); - - if (!success) - { - return false; - } - - for (i = 0; i < settings->num_players && i < NET_MAXPLAYERS; ++i) - { - if (!NET_ReadInt8(packet, - (unsigned int *) &settings->player_classes[i])) + boolean success; + int i; + + success = + net_read_int8(packet, (unsigned int *)&settings->ticdup) && + net_read_int8(packet, (unsigned int *)&settings->extratics) && + net_read_int8(packet, (unsigned int *)&settings->deathmatch) && + net_read_int8(packet, (unsigned int *)&settings->nomonsters) && + net_read_int8(packet, (unsigned int *)&settings->fast_monsters) && + net_read_int8(packet, (unsigned int *)&settings->respawn_monsters) && + net_read_int8(packet, (unsigned int *)&settings->episode) && + net_read_int8(packet, (unsigned int *)&settings->map) && + net_read_sint8(packet, &settings->skill) && + net_read_int8(packet, (unsigned int *)&settings->gameversion) && + net_read_int8(packet, (unsigned int *)&settings->lowres_turn) && + net_read_int8(packet, (unsigned int *)&settings->new_sync) && + net_read_int32(packet, (unsigned int *)&settings->timelimit) && + net_read_sint8(packet, (signed int *)&settings->loadgame) && + net_read_int8(packet, (unsigned int *)&settings->random) && + net_read_int8(packet, (unsigned int *)&settings->num_players) && + net_read_sint8(packet, (signed int *)&settings->consoleplayer); + + if (!success) + { + return false; + } + + for (i = 0; + i < settings->num_players && i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; + ++i) + { + if (!net_read_int8(packet, + (unsigned int *)&settings->player_classes[i])) { - return false; + return false; } } - return true; + return true; } -boolean NET_ReadQueryData(net_packet_t *packet, net_querydata_t *query) +boolean net_read_query_data(net_packet_t *packet, net_querydata_t *query) { - boolean success; + boolean success; - query->version = NET_ReadSafeString(packet); + query->version = net_read_safe_string(packet); - success = query->version != NULL - && NET_ReadInt8(packet, (unsigned int *) &query->server_state) - && NET_ReadInt8(packet, (unsigned int *) &query->num_players) - && NET_ReadInt8(packet, (unsigned int *) &query->max_players) - && NET_ReadInt8(packet, (unsigned int *) &query->gamemode) - && NET_ReadInt8(packet, (unsigned int *) &query->gamemission); + success = query->version != NULL && + net_read_int8(packet, (unsigned int *)&query->server_state) && + net_read_int8(packet, (unsigned int *)&query->num_players) && + net_read_int8(packet, (unsigned int *)&query->max_players) && + net_read_int8(packet, (unsigned int *)&query->gamemode) && + net_read_int8(packet, (unsigned int *)&query->gamemission); - if (!success) + if (!success) { - return false; + return false; } - query->description = NET_ReadSafeString(packet); + query->description = net_read_safe_string(packet); + + /* We read the list of protocols supported by the server. However, + * old versions of Chocolate Doom do not support this field; it is + * okay if it cannot be successfully read. + */ - // We read the list of protocols supported by the server. However, - // old versions of Chocolate Doom do not support this field; it is - // okay if it cannot be successfully read. - query->protocol = NET_ReadProtocolList(packet); + query->protocol = net_read_protocol_list(packet); - return query->description != NULL; + return query->description != NULL; } -void NET_WriteQueryData(net_packet_t *packet, net_querydata_t *query) +void net_write_query_data(net_packet_t *packet, net_querydata_t *query) { - NET_WriteString(packet, query->version); - NET_WriteInt8(packet, query->server_state); - NET_WriteInt8(packet, query->num_players); - NET_WriteInt8(packet, query->max_players); - NET_WriteInt8(packet, query->gamemode); - NET_WriteInt8(packet, query->gamemission); - NET_WriteString(packet, query->description); - - // Write a list of all supported protocols. Note that the query->protocol - // field is ignored here; it is only used when receiving. - NET_WriteProtocolList(packet); + net_write_string(packet, query->version); + net_write_int8(packet, query->server_state); + net_write_int8(packet, query->num_players); + net_write_int8(packet, query->max_players); + net_write_int8(packet, query->gamemode); + net_write_int8(packet, query->gamemission); + net_write_string(packet, query->description); + + /* Write a list of all supported protocols. Note that the query->protocol + * field is ignored here; it is only used when receiving. + */ + + net_write_protocol_list(packet); } -void NET_WriteTiccmdDiff(net_packet_t *packet, net_ticdiff_t *diff, +void net_write_ticcmd_diff(net_packet_t *packet, net_ticdiff_t *diff, boolean lowres_turn) { - // Header + /* Header */ - NET_WriteInt8(packet, diff->diff); + net_write_int8(packet, diff->diff); - // Write the fields which are enabled: + /* Write the fields which are enabled: */ - if (diff->diff & NET_TICDIFF_FORWARD) - NET_WriteInt8(packet, diff->cmd.forwardmove); - if (diff->diff & NET_TICDIFF_SIDE) - NET_WriteInt8(packet, diff->cmd.sidemove); - if (diff->diff & NET_TICDIFF_TURN) + if (diff->diff & NET_TICDIFF_FORWARD) + net_write_int8(packet, diff->cmd.forwardmove); + if (diff->diff & NET_TICDIFF_SIDE) + net_write_int8(packet, diff->cmd.sidemove); + if (diff->diff & NET_TICDIFF_TURN) { - if (lowres_turn) + if (lowres_turn) { - NET_WriteInt8(packet, diff->cmd.angleturn / 256); + net_write_int8(packet, diff->cmd.angleturn / 256); } - else + else { - NET_WriteInt16(packet, diff->cmd.angleturn); + net_write_int16(packet, diff->cmd.angleturn); } } - if (diff->diff & NET_TICDIFF_BUTTONS) - NET_WriteInt8(packet, diff->cmd.buttons); - if (diff->diff & NET_TICDIFF_CONSISTANCY) - NET_WriteInt8(packet, diff->cmd.consistancy); - if (diff->diff & NET_TICDIFF_CHATCHAR) - NET_WriteInt8(packet, diff->cmd.chatchar); - if (diff->diff & NET_TICDIFF_RAVEN) + + if (diff->diff & NET_TICDIFF_BUTTONS) + net_write_int8(packet, diff->cmd.buttons); + if (diff->diff & NET_TICDIFF_CONSISTANCY) + net_write_int8(packet, diff->cmd.consistency); + if (diff->diff & NET_TICDIFF_CHATCHAR) + net_write_int8(packet, diff->cmd.chatchar); + if (diff->diff & NET_TICDIFF_RAVEN) { - NET_WriteInt8(packet, diff->cmd.lookfly); - NET_WriteInt8(packet, diff->cmd.arti); + net_write_int8(packet, diff->cmd.lookfly); + net_write_int8(packet, diff->cmd.arti); } - if (diff->diff & NET_TICDIFF_STRIFE) + + if (diff->diff & NET_TICDIFF_STRIFE) { - NET_WriteInt8(packet, diff->cmd.buttons2); - NET_WriteInt16(packet, diff->cmd.inventory); + net_write_int8(packet, diff->cmd.buttons2); + net_write_int16(packet, diff->cmd.inventory); } } -boolean NET_ReadTiccmdDiff(net_packet_t *packet, net_ticdiff_t *diff, +boolean net_read_ticcmd_diff(net_packet_t *packet, net_ticdiff_t *diff, boolean lowres_turn) { - unsigned int val; - signed int sval; + unsigned int val; + signed int sval; - // Read header + /* Read header */ - if (!NET_ReadInt8(packet, &diff->diff)) - return false; - - // Read fields + if (!net_read_int8(packet, &diff->diff)) return false; - if (diff->diff & NET_TICDIFF_FORWARD) + /* Read fields */ + + if (diff->diff & NET_TICDIFF_FORWARD) { - if (!NET_ReadSInt8(packet, &sval)) - return false; - diff->cmd.forwardmove = sval; + if (!net_read_sint8(packet, &sval)) return false; + diff->cmd.forwardmove = sval; } - if (diff->diff & NET_TICDIFF_SIDE) + if (diff->diff & NET_TICDIFF_SIDE) { - if (!NET_ReadSInt8(packet, &sval)) - return false; - diff->cmd.sidemove = sval; + if (!net_read_sint8(packet, &sval)) return false; + diff->cmd.sidemove = sval; } - if (diff->diff & NET_TICDIFF_TURN) + if (diff->diff & NET_TICDIFF_TURN) { - if (lowres_turn) + if (lowres_turn) { - if (!NET_ReadSInt8(packet, &sval)) - return false; - diff->cmd.angleturn = sval * 256; + if (!net_read_sint8(packet, &sval)) return false; + diff->cmd.angleturn = sval * 256; } - else + else { - if (!NET_ReadSInt16(packet, &sval)) - return false; - diff->cmd.angleturn = sval; + if (!net_read_sint16(packet, &sval)) return false; + diff->cmd.angleturn = sval; } } - if (diff->diff & NET_TICDIFF_BUTTONS) + if (diff->diff & NET_TICDIFF_BUTTONS) { - if (!NET_ReadInt8(packet, &val)) - return false; - diff->cmd.buttons = val; + if (!net_read_int8(packet, &val)) return false; + diff->cmd.buttons = val; } - if (diff->diff & NET_TICDIFF_CONSISTANCY) + if (diff->diff & NET_TICDIFF_CONSISTANCY) { - if (!NET_ReadInt8(packet, &val)) - return false; - diff->cmd.consistancy = val; + if (!net_read_int8(packet, &val)) return false; + diff->cmd.consistency = val; } - if (diff->diff & NET_TICDIFF_CHATCHAR) + if (diff->diff & NET_TICDIFF_CHATCHAR) { - if (!NET_ReadInt8(packet, &val)) - return false; - diff->cmd.chatchar = val; + if (!net_read_int8(packet, &val)) return false; + diff->cmd.chatchar = val; } - if (diff->diff & NET_TICDIFF_RAVEN) + if (diff->diff & NET_TICDIFF_RAVEN) { - if (!NET_ReadInt8(packet, &val)) - return false; - diff->cmd.lookfly = val; + if (!net_read_int8(packet, &val)) return false; + diff->cmd.lookfly = val; - if (!NET_ReadInt8(packet, &val)) - return false; - diff->cmd.arti = val; + if (!net_read_int8(packet, &val)) return false; + diff->cmd.arti = val; } - if (diff->diff & NET_TICDIFF_STRIFE) + if (diff->diff & NET_TICDIFF_STRIFE) { - if (!NET_ReadInt8(packet, &val)) - return false; - diff->cmd.buttons2 = val; + if (!net_read_int8(packet, &val)) return false; + diff->cmd.buttons2 = val; - if (!NET_ReadInt16(packet, &val)) - return false; - diff->cmd.inventory = val; + if (!net_read_int16(packet, &val)) return false; + diff->cmd.inventory = val; } - return true; + return true; } -void NET_TiccmdDiff(ticcmd_t *tic1, ticcmd_t *tic2, net_ticdiff_t *diff) +void net_ticcmd_diff(ticcmd_t *tic1, ticcmd_t *tic2, net_ticdiff_t *diff) { - diff->diff = 0; - diff->cmd = *tic2; - - if (tic1->forwardmove != tic2->forwardmove) - diff->diff |= NET_TICDIFF_FORWARD; - if (tic1->sidemove != tic2->sidemove) - diff->diff |= NET_TICDIFF_SIDE; - if (tic1->angleturn != tic2->angleturn) - diff->diff |= NET_TICDIFF_TURN; - if (tic1->buttons != tic2->buttons) - diff->diff |= NET_TICDIFF_BUTTONS; - if (tic1->consistancy != tic2->consistancy) - diff->diff |= NET_TICDIFF_CONSISTANCY; - if (tic2->chatchar != 0) - diff->diff |= NET_TICDIFF_CHATCHAR; - - // Heretic/Hexen-specific - - if (tic1->lookfly != tic2->lookfly || tic2->arti != 0) - diff->diff |= NET_TICDIFF_RAVEN; - - // Strife-specific - - if (tic1->buttons2 != tic2->buttons2 || tic2->inventory != 0) - diff->diff |= NET_TICDIFF_STRIFE; + diff->diff = 0; + diff->cmd = *tic2; + + if (tic1->forwardmove != tic2->forwardmove) + diff->diff |= NET_TICDIFF_FORWARD; + if (tic1->sidemove != tic2->sidemove) diff->diff |= NET_TICDIFF_SIDE; + if (tic1->angleturn != tic2->angleturn) diff->diff |= NET_TICDIFF_TURN; + if (tic1->buttons != tic2->buttons) diff->diff |= NET_TICDIFF_BUTTONS; + if (tic1->consistency != tic2->consistency) + diff->diff |= NET_TICDIFF_CONSISTANCY; + if (tic2->chatchar != 0) diff->diff |= NET_TICDIFF_CHATCHAR; + + /* Heretic/Hexen-specific */ + + if (tic1->lookfly != tic2->lookfly || tic2->arti != 0) + diff->diff |= NET_TICDIFF_RAVEN; + + /* Strife-specific */ + + if (tic1->buttons2 != tic2->buttons2 || tic2->inventory != 0) + diff->diff |= NET_TICDIFF_STRIFE; } -void NET_TiccmdPatch(ticcmd_t *src, net_ticdiff_t *diff, ticcmd_t *dest) +void net_ticcmd_patch(ticcmd_t *src, net_ticdiff_t *diff, ticcmd_t *dest) { - memmove(dest, src, sizeof(ticcmd_t)); + memmove(dest, src, sizeof(ticcmd_t)); - // Apply the diff + /* Apply the diff */ - if (diff->diff & NET_TICDIFF_FORWARD) - dest->forwardmove = diff->cmd.forwardmove; - if (diff->diff & NET_TICDIFF_SIDE) - dest->sidemove = diff->cmd.sidemove; - if (diff->diff & NET_TICDIFF_TURN) - dest->angleturn = diff->cmd.angleturn; - if (diff->diff & NET_TICDIFF_BUTTONS) - dest->buttons = diff->cmd.buttons; - if (diff->diff & NET_TICDIFF_CONSISTANCY) - dest->consistancy = diff->cmd.consistancy; + if (diff->diff & NET_TICDIFF_FORWARD) + dest->forwardmove = diff->cmd.forwardmove; + if (diff->diff & NET_TICDIFF_SIDE) dest->sidemove = diff->cmd.sidemove; + if (diff->diff & NET_TICDIFF_TURN) dest->angleturn = diff->cmd.angleturn; + if (diff->diff & NET_TICDIFF_BUTTONS) dest->buttons = diff->cmd.buttons; + if (diff->diff & NET_TICDIFF_CONSISTANCY) + dest->consistency = diff->cmd.consistency; - if (diff->diff & NET_TICDIFF_CHATCHAR) - dest->chatchar = diff->cmd.chatchar; - else - dest->chatchar = 0; + if (diff->diff & NET_TICDIFF_CHATCHAR) + dest->chatchar = diff->cmd.chatchar; + else + dest->chatchar = 0; - // Heretic/Hexen specific: + /* Heretic/Hexen specific: */ - if (diff->diff & NET_TICDIFF_RAVEN) + if (diff->diff & NET_TICDIFF_RAVEN) { - dest->lookfly = diff->cmd.lookfly; - dest->arti = diff->cmd.arti; + dest->lookfly = diff->cmd.lookfly; + dest->arti = diff->cmd.arti; } - else + else { - dest->arti = 0; + dest->arti = 0; } - // Strife-specific: + /* Strife-specific: */ - if (diff->diff & NET_TICDIFF_STRIFE) + if (diff->diff & NET_TICDIFF_STRIFE) { - dest->buttons2 = diff->cmd.buttons2; - dest->inventory = diff->cmd.inventory; + dest->buttons2 = diff->cmd.buttons2; + dest->inventory = diff->cmd.inventory; } - else + else { - dest->inventory = 0; + dest->inventory = 0; } } -// -// net_full_ticcmd_t -// +/* net_full_ticcmd_t */ -boolean NET_ReadFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn) +boolean net_read_full_ticcmd(net_packet_t *packet, net_full_ticcmd_t *cmd, + boolean lowres_turn) { - unsigned int bitfield; - int i; + unsigned int bitfield; + int i; - // Latency + /* Latency */ - if (!NET_ReadSInt16(packet, &cmd->latency)) + if (!net_read_sint16(packet, &cmd->latency)) { - return false; + return false; } - // Regenerate playeringame from the "header" bitfield + /* Regenerate playeringame from the "header" bitfield */ - if (!NET_ReadInt8(packet, &bitfield)) + if (!net_read_int8(packet, &bitfield)) { - return false; + return false; } - - for (i=0; iplayeringame[i] = (bitfield & (1 << i)) != 0; + cmd->playeringame[i] = (bitfield & (1 << i)) != 0; } - - // Read cmds - for (i=0; iplayeringame[i]) + if (cmd->playeringame[i]) { - if (!NET_ReadTiccmdDiff(packet, &cmd->cmds[i], lowres_turn)) + if (!net_read_ticcmd_diff(packet, &cmd->cmds[i], lowres_turn)) { - return false; + return false; } } } - return true; + return true; } -void NET_WriteFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn) +void net_write_full_ticcmd(net_packet_t *packet, net_full_ticcmd_t *cmd, + boolean lowres_turn) { - unsigned int bitfield; - int i; + unsigned int bitfield; + int i; - // Write the latency + /* Write the latency */ - NET_WriteInt16(packet, cmd->latency); + net_write_int16(packet, cmd->latency); - // Write "header" byte indicating which players are active - // in this ticcmd + /* Write "header" byte indicating which players are active + * in this ticcmd + */ - bitfield = 0; - - for (i=0; iplayeringame[i]) + if (cmd->playeringame[i]) { - bitfield |= 1 << i; + bitfield |= 1 << i; } } - - NET_WriteInt8(packet, bitfield); - // Write player ticcmds + net_write_int8(packet, bitfield); + + /* Write player ticcmds */ - for (i=0; iplayeringame[i]) + if (cmd->playeringame[i]) { - NET_WriteTiccmdDiff(packet, &cmd->cmds[i], lowres_turn); + net_write_ticcmd_diff(packet, &cmd->cmds[i], lowres_turn); } } } -void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data) +void net_write_wait_data(net_packet_t *packet, net_waitdata_t *data) { - int i; + int i; - NET_WriteInt8(packet, data->num_players); - NET_WriteInt8(packet, data->num_drones); - NET_WriteInt8(packet, data->ready_players); - NET_WriteInt8(packet, data->max_players); - NET_WriteInt8(packet, data->is_controller); - NET_WriteInt8(packet, data->consoleplayer); + net_write_int8(packet, data->num_players); + net_write_int8(packet, data->num_drones); + net_write_int8(packet, data->ready_players); + net_write_int8(packet, data->max_players); + net_write_int8(packet, data->is_controller); + net_write_int8(packet, data->consoleplayer); - for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i) + for (i = 0; + i < data->num_players && i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; + ++i) { - NET_WriteString(packet, data->player_names[i]); - NET_WriteString(packet, data->player_addrs[i]); + net_write_string(packet, data->player_names[i]); + net_write_string(packet, data->player_addrs[i]); } - NET_WriteSHA1Sum(packet, data->wad_sha1sum); - NET_WriteSHA1Sum(packet, data->deh_sha1sum); - NET_WriteInt8(packet, data->is_freedoom); + net_write_sha1_sum(packet, data->wad_sha1sum); + net_write_sha1_sum(packet, data->deh_sha1sum); + net_write_int8(packet, data->is_freedoom); } -boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data) +boolean net_read_wait_data(net_packet_t *packet, net_waitdata_t *data) { - int i; - char *s; + int i; + char *s; - if (!NET_ReadInt8(packet, (unsigned int *) &data->num_players) - || !NET_ReadInt8(packet, (unsigned int *) &data->num_drones) - || !NET_ReadInt8(packet, (unsigned int *) &data->ready_players) - || !NET_ReadInt8(packet, (unsigned int *) &data->max_players) - || !NET_ReadInt8(packet, (unsigned int *) &data->is_controller) - || !NET_ReadSInt8(packet, &data->consoleplayer)) + if (!net_read_int8(packet, (unsigned int *)&data->num_players) || + !net_read_int8(packet, (unsigned int *)&data->num_drones) || + !net_read_int8(packet, (unsigned int *)&data->ready_players) || + !net_read_int8(packet, (unsigned int *)&data->max_players) || + !net_read_int8(packet, (unsigned int *)&data->is_controller) || + !net_read_sint8(packet, &data->consoleplayer)) { - return false; + return false; } - for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i) + for (i = 0; + i < data->num_players && i < CONFIG_GAMES_NXDOOM_NET_MAXPLAYERS; + ++i) { - s = NET_ReadString(packet); + s = net_read_string(packet); - if (s == NULL || strlen(s) >= MAXPLAYERNAME) + if (s == NULL || strlen(s) >= CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME) { - return false; + return false; } - M_StringCopy(data->player_names[i], s, MAXPLAYERNAME); + m_str_copy(data->player_names[i], s, + CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME); - s = NET_ReadString(packet); + s = net_read_string(packet); - if (s == NULL || strlen(s) >= MAXPLAYERNAME) + if (s == NULL || strlen(s) >= CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME) { - return false; + return false; } - M_StringCopy(data->player_addrs[i], s, MAXPLAYERNAME); + m_str_copy(data->player_addrs[i], s, + CONFIG_GAMES_NXDOOM_NET_MAXPLAYERNAME); } - return NET_ReadSHA1Sum(packet, data->wad_sha1sum) - && NET_ReadSHA1Sum(packet, data->deh_sha1sum) - && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom); + return net_read_sha1_sum(packet, data->wad_sha1sum) && + net_read_sha1_sum(packet, data->deh_sha1sum) && + net_read_int8(packet, (unsigned int *)&data->is_freedoom); } -static boolean NET_ReadBlob(net_packet_t *packet, uint8_t *buf, size_t len) +boolean net_read_sha1_sum(net_packet_t *packet, sha1_digest_t digest) { - unsigned int b; - int i; - - for (i=0; i #include @@ -23,59 +31,66 @@ #include "m_argv.h" #include "p_rejectpad.h" +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// Pad the REJECT lump with extra data when the lump is too small, -// to simulate a REJECT buffer overflow in Vanilla Doom. +/* Pad the REJECT lump with extra data when the lump is too small, + * to simulate a REJECT buffer overflow in Vanilla Doom. + */ -void PadRejectArray(byte *array, unsigned int len, int totallines) +void pad_reject_array(byte *array, unsigned int len, int totallines) { - unsigned int i; - unsigned int byte_num; - byte *dest; - unsigned int padvalue; + unsigned int i; + unsigned int byte_num; + byte *dest; + unsigned int padvalue; - // Values to pad the REJECT array with: + /* Values to pad the REJECT array with: */ - unsigned int rejectpad[4] = - { - 0, // Size - 0, // Part of z_zone block header - 50, // PU_LEVEL - 0x1d4a11 // DOOM_CONST_ZONEID - }; + unsigned int rejectpad[4] = + { + 0, /* Size */ + 0, /* Part of z_zone block header */ + 50, /* PU_LEVEL */ + 0x1d4a11 /* DOOM_CONST_ZONEID */ + }; - rejectpad[0] = ((totallines * 4 + 3) & ~3) + 24; + rejectpad[0] = ((totallines * 4 + 3) & ~3) + 24; - // Copy values from rejectpad into the destination array. + /* Copy values from rejectpad into the destination array. */ - dest = array; + dest = array; - for (i=0; i> (byte_num * 8)) & 0xff; - ++dest; + byte_num = i % 4; + *dest = (rejectpad[i / 4] >> (byte_num * 8)) & 0xff; + ++dest; } - // We only have a limited pad size. Print a warning if the - // REJECT lump is too small. + /* We only have a limited pad size. Print a warning if the + * REJECT lump is too small. + */ - if (len > sizeof(rejectpad)) + if (len > sizeof(rejectpad)) { - fprintf(stderr, "PadRejectArray: REJECT lump too short to pad! (%u > %i)\n", - len, (int) sizeof(rejectpad)); + fprintf(stderr, + "pad_reject_array: REJECT lump too short to pad! (%u > %i)\n", + len, (int)sizeof(rejectpad)); - // Pad remaining space with 0 (or 0xff, if specified on command line). + /* Pad remaining space with 0 (or 0xff, if specified on command line). + */ - if (M_CheckParm("-reject_pad_with_ff")) + if (m_check_parm("-reject_pad_with_ff")) { - padvalue = 0xff; + padvalue = 0xff; } - else + else { - padvalue = 0x00; + padvalue = 0x00; } - memset(array + sizeof(rejectpad), padvalue, len - sizeof(rejectpad)); + memset(array + sizeof(rejectpad), padvalue, len - sizeof(rejectpad)); } } diff --git a/games/NXDoom/src/p_rejectpad.h b/games/NXDoom/src/p_rejectpad.h index 78ab8407069..adb0372dd85 100644 --- a/games/NXDoom/src/p_rejectpad.h +++ b/games/NXDoom/src/p_rejectpad.h @@ -1,28 +1,41 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Padding of Reject Lump -// - +/**************************************************************************** + * apps/games/NXDoom/src/p_rejectpad.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Padding of Reject Lump + * + ****************************************************************************/ #ifndef __P_REJECTPAD__ #define __P_REJECTPAD__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -// Padding of Reject Lump -void PadRejectArray(byte *array, unsigned int len, int totallines); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Padding of Reject Lump */ + +void pad_reject_array(byte *array, unsigned int len, int totallines); -#endif +#endif /* __P_REJECTPAD__ */ diff --git a/games/NXDoom/src/setup-res.rc.in b/games/NXDoom/src/setup-res.rc.in deleted file mode 100644 index 2be914f96b6..00000000000 --- a/games/NXDoom/src/setup-res.rc.in +++ /dev/null @@ -1,28 +0,0 @@ -1 ICON "@top_srcdir@/data/setup.ico" - -1 24 MOVEABLE PURE "@top_builddir@/src/setup/setup-manifest.xml" - -1 VERSIONINFO -PRODUCTVERSION @WINDOWS_RC_VERSION@ -FILEVERSION @WINDOWS_RC_VERSION@ -FILETYPE 1 -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "@PACKAGE_VERSION@.0" - VALUE "FileDescription", "@PACKAGE_STRING@ Setup" - VALUE "InternalName", "@PACKAGE_TARNAME@" - VALUE "CompanyName", "@PACKAGE_BUGREPORT@" - VALUE "LegalCopyright", "GNU General Public License" - VALUE "ProductName", "@PACKAGE_NAME@ Setup" - VALUE "ProductVersion", "@PACKAGE_VERSION@" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - diff --git a/games/NXDoom/src/setup/.gitignore b/games/NXDoom/src/setup/.gitignore deleted file mode 100644 index f41d11c73e7..00000000000 --- a/games/NXDoom/src/setup/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile.in -Makefile -.deps -setup-manifest.xml -*.rc -tags -TAGS diff --git a/games/NXDoom/src/setup/CMakeLists.txt b/games/NXDoom/src/setup/CMakeLists.txt deleted file mode 100644 index c25af659944..00000000000 --- a/games/NXDoom/src/setup/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -add_library(setup STATIC - compatibility.c compatibility.h - display.c display.h - joystick.c joystick.h - keyboard.c keyboard.h - mainmenu.c - mode.c mode.h - mouse.c mouse.h - multiplayer.c multiplayer.h - sound.c sound.h - execute.c execute.h - txt_joyaxis.c txt_joyaxis.h - txt_joybinput.c txt_joybinput.h - txt_keyinput.c txt_keyinput.h - txt_mouseinput.c txt_mouseinput.h) - -target_include_directories(setup PRIVATE "../" "${CMAKE_CURRENT_BINARY_DIR}/../../") - -if (DEFINED EMSCRIPTEN) - set(SDL_FLAGS "-s USE_SDL=2") - if(ENABLE_SDL2_MIXER) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") - endif() -else() - set(SDL_LINK_LIBS, "SDL2::SDL2") - if(ENABLE_SDL2_MIXER) - list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) - endif() -endif() -target_link_libraries(setup textscreen ${SDL_LINK_LIBS}) -set_target_properties(setup PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") -set_target_properties(setup PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/setup/Makefile.am b/games/NXDoom/src/setup/Makefile.am deleted file mode 100644 index 493b0b47240..00000000000 --- a/games/NXDoom/src/setup/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ - -AM_CFLAGS = @SDL_CFLAGS@ \ - @SDLMIXER_CFLAGS@ \ - -I$(top_srcdir)/textscreen -I$(top_srcdir)/src - -noinst_LIBRARIES = libsetup.a - -libsetup_a_SOURCES = \ - compatibility.c compatibility.h \ - display.c display.h \ - joystick.c joystick.h \ - keyboard.c keyboard.h \ - mainmenu.c \ - mode.c mode.h \ - mouse.c mouse.h \ - multiplayer.c multiplayer.h \ - sound.c sound.h \ - execute.c execute.h \ - txt_joyaxis.c txt_joyaxis.h \ - txt_joybinput.c txt_joybinput.h \ - txt_keyinput.c txt_keyinput.h \ - txt_mouseinput.c txt_mouseinput.h - -EXTRA_DIST= \ - CMakeLists.txt \ - setup_icon.c - -appdir = $(prefix)/share/applications -app_DATA = @PACKAGE_RDNS@.Setup.desktop - -CLEANFILES = $(app_DATA) - -@PACKAGE_RDNS@.Setup.desktop : Setup.desktop - cp Setup.desktop $@ - -if HAVE_ICONS - -setup_icon.c : $(top_builddir)/data/setup.png - $(top_builddir)/data/convert-icon $(top_builddir)/data/setup.png $@ - -endif - diff --git a/games/NXDoom/src/setup/Setup.desktop.in b/games/NXDoom/src/setup/Setup.desktop.in deleted file mode 100644 index 2a5e71fa1e2..00000000000 --- a/games/NXDoom/src/setup/Setup.desktop.in +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_SHORTNAME@ Setup -Exec=@PROGRAM_PREFIX@setup -Icon=@PROGRAM_PREFIX@setup -Type=Application -Comment=Setup tool for @PACKAGE_SHORTNAME@ -Categories=Settings; -Keywords=first;person;shooter;doom;heretic;hexen;strife;vanilla; diff --git a/games/NXDoom/src/setup/compatibility.c b/games/NXDoom/src/setup/compatibility.c deleted file mode 100644 index b96228f6115..00000000000 --- a/games/NXDoom/src/setup/compatibility.c +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// Sound control menu - -#include - -#include "m_config.h" -#include "textscreen.h" -#include "mode.h" - -#include "compatibility.h" - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-compat" - -int vanilla_savegame_limit = 1; -int vanilla_demo_limit = 1; - -void CompatibilitySettings(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - - window = TXT_NewWindow("Compatibility"); - - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - TXT_AddWidgets(window, - TXT_NewCheckBox("Vanilla savegame limit", - &vanilla_savegame_limit), - TXT_NewCheckBox("Vanilla demo limit", - &vanilla_demo_limit), - NULL); -} - -void BindCompatibilityVariables(void) -{ - M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); - M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); -} - diff --git a/games/NXDoom/src/setup/compatibility.h b/games/NXDoom/src/setup/compatibility.h deleted file mode 100644 index 39a5fc8f7f6..00000000000 --- a/games/NXDoom/src/setup/compatibility.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_COMPATIBILITY_H -#define SETUP_COMPATIBILITY_H - -void CompatibilitySettings(void *widget, void *user_data); -void BindCompatibilityVariables(void); - -extern int vanilla_savegame_limit; -extern int vanilla_demo_limit; - -#endif /* #ifndef SETUP_COMPATIBILITY_H */ diff --git a/games/NXDoom/src/setup/display.c b/games/NXDoom/src/setup/display.c deleted file mode 100644 index 0f89a09310f..00000000000 --- a/games/NXDoom/src/setup/display.c +++ /dev/null @@ -1,289 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#endif - -#include "textscreen.h" -#include "m_config.h" -#include "m_misc.h" -#include "mode.h" - -#include "display.h" -#include "config.h" - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-display" - - -typedef struct -{ - int w, h; -} window_size_t; - -// List of aspect ratio-uncorrected window sizes: -static window_size_t window_sizes_unscaled[] = -{ - { 320, 200 }, - { 640, 400 }, - { 960, 600 }, - { 1280, 800 }, - { 1600, 1000 }, - { 0, 0}, -}; - -// List of aspect ratio-corrected window sizes: -static window_size_t window_sizes_scaled[] = -{ - { 320, 240 }, - { 512, 400 }, - { 640, 480 }, - { 800, 600 }, - { 960, 720 }, - { 1024, 800 }, - { 1280, 960 }, - { 1600, 1200 }, - { 1920, 1440 }, - { 0, 0}, -}; - -static char *video_driver = ""; -static char *window_position = ""; -static int video_display = 0; -static int aspect_ratio_correct = 1; -static int integer_scaling = 0; -static int smooth_pixel_scaling = 1; -static int vga_porch_flash = 0; -static int force_software_renderer = 0; -static int fullscreen = 1; -static int fullscreen_width = 0, fullscreen_height = 0; -static int window_width = 800, window_height = 600; -static int startup_delay = 1000; -static int max_scaling_buffer_pixels = 16000000; -static int usegamma = 0; - -int graphical_startup = 1; -int show_endoom = 1; -int show_diskicon = 1; -int png_screenshots = 0; - -static int system_video_env_set; - -// Set the SDL_VIDEODRIVER environment variable - -void SetDisplayDriver(void) -{ - static int first_time = 1; - - if (first_time) - { - system_video_env_set = getenv("SDL_VIDEODRIVER") != NULL; - - first_time = 0; - } - - // Don't override the command line environment, if it has been set. - - if (system_video_env_set) - { - return; - } - - // Use the value from the configuration file, if it has been set. - - if (strcmp(video_driver, "") != 0) - { - char *env_string; - - env_string = M_StringJoin("SDL_VIDEODRIVER=", video_driver, NULL); - putenv(env_string); - free(env_string); - } -} - -static void WindowSizeSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(size)) -{ - TXT_CAST_ARG(window_size_t, size); - - window_width = size->w; - window_height = size->h; -} - -static txt_radiobutton_t *SizeSelectButton(window_size_t *size) -{ - char buf[15]; - txt_radiobutton_t *result; - - M_snprintf(buf, sizeof(buf), "%ix%i", size->w, size->h); - result = TXT_NewRadioButton(buf, &window_width, size->w); - TXT_SignalConnect(result, "selected", WindowSizeSelected, size); - - return result; -} - -static void GenerateSizesTable(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(sizes_table)) -{ - TXT_CAST_ARG(txt_table_t, sizes_table); - window_size_t *sizes; - boolean have_size; - int i; - - // Pick which window sizes list to use - if (aspect_ratio_correct == 1) - { - sizes = window_sizes_scaled; - } - else - { - sizes = window_sizes_unscaled; - } - - // Build the table - TXT_ClearTable(sizes_table); - TXT_SetColumnWidths(sizes_table, 14, 14, 14); - - TXT_AddWidget(sizes_table, TXT_NewSeparator("Window size")); - - have_size = false; - - for (i = 0; sizes[i].w != 0; ++i) - { - TXT_AddWidget(sizes_table, SizeSelectButton(&sizes[i])); - have_size = have_size || window_width == sizes[i].w; - } - - // Windows can be any arbitrary size. We key off the width of the - // window in pixels. If the current size is not in the list of - // standard (integer multiply) sizes, create a special button to - // mean "the current window size". - if (!have_size) - { - static window_size_t current_size; - current_size.w = window_width; - current_size.h = window_height; - TXT_AddWidget(sizes_table, SizeSelectButton(¤t_size)); - } -} - -static void AdvancedDisplayConfig(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(sizes_table)) -{ - TXT_CAST_ARG(txt_table_t, sizes_table); - txt_window_t *window; - txt_checkbox_t *ar_checkbox; - - window = TXT_NewWindow("Advanced display options"); - - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - TXT_SetColumnWidths(window, 40); - - TXT_AddWidgets(window, - ar_checkbox = TXT_NewCheckBox("Force correct aspect ratio", - &aspect_ratio_correct), - TXT_If(gamemission == heretic || gamemission == hexen - || gamemission == strife, - TXT_NewCheckBox("Graphical startup", &graphical_startup)), - TXT_If(gamemission == doom || gamemission == heretic - || gamemission == strife, - TXT_NewCheckBox("Show ENDOOM screen on exit", - &show_endoom)), -#ifdef HAVE_LIBPNG - TXT_NewCheckBox("Save screenshots in PNG format", - &png_screenshots), -#endif - TXT_NewCheckBox("Smooth pixel scaling", &smooth_pixel_scaling), - NULL); - - TXT_SignalConnect(ar_checkbox, "changed", GenerateSizesTable, sizes_table); -} - -void ConfigDisplay(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - txt_table_t *sizes_table; - txt_window_action_t *advanced_button; - - // Open the window - window = TXT_NewWindow("Display Configuration"); - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - // Build window: - TXT_AddWidgets(window, - TXT_NewCheckBox("Full screen", &fullscreen), - TXT_NewConditional(&fullscreen, 0, - sizes_table = TXT_NewTable(3)), - NULL); - - TXT_SetColumnWidths(window, 42); - - // The window is set at a fixed vertical position. This keeps - // the top of the window stationary when switching between - // fullscreen and windowed mode (which causes the window's - // height to change). - TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, - TXT_SCREEN_W / 2, 6); - - GenerateSizesTable(NULL, sizes_table); - - // Button to open "advanced" window. - // Need to pass a pointer to the window sizes table, as some of the options - // in there trigger a rebuild of it. - advanced_button = TXT_NewWindowAction('a', "Advanced"); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, advanced_button); - TXT_SignalConnect(advanced_button, "pressed", - AdvancedDisplayConfig, sizes_table); -} - -void BindDisplayVariables(void) -{ - M_BindIntVariable("video_display", &video_display); - M_BindIntVariable("aspect_ratio_correct", &aspect_ratio_correct); - M_BindIntVariable("integer_scaling", &integer_scaling); - M_BindIntVariable("smooth_pixel_scaling", &smooth_pixel_scaling); - M_BindIntVariable("fullscreen", &fullscreen); - M_BindIntVariable("fullscreen_width", &fullscreen_width); - M_BindIntVariable("fullscreen_height", &fullscreen_height); - M_BindIntVariable("window_width", &window_width); - M_BindIntVariable("window_height", &window_height); - M_BindIntVariable("startup_delay", &startup_delay); - M_BindStringVariable("video_driver", &video_driver); - M_BindStringVariable("window_position", &window_position); - M_BindIntVariable("usegamma", &usegamma); - M_BindIntVariable("png_screenshots", &png_screenshots); - M_BindIntVariable("vga_porch_flash", &vga_porch_flash); - M_BindIntVariable("force_software_renderer", &force_software_renderer); - M_BindIntVariable("max_scaling_buffer_pixels", &max_scaling_buffer_pixels); - - if (gamemission == doom || gamemission == heretic - || gamemission == strife) - { - M_BindIntVariable("show_endoom", &show_endoom); - } - - if (gamemission == doom || gamemission == strife) - { - M_BindIntVariable("show_diskicon", &show_diskicon); - } - - if (gamemission == heretic || gamemission == hexen || gamemission == strife) - { - M_BindIntVariable("graphical_startup", &graphical_startup); - } -} \ No newline at end of file diff --git a/games/NXDoom/src/setup/display.h b/games/NXDoom/src/setup/display.h deleted file mode 100644 index 0c20c51a2db..00000000000 --- a/games/NXDoom/src/setup/display.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_DISPLAY_H -#define SETUP_DISPLAY_H - -void ConfigDisplay(void *widget, void *user_data); -void SetDisplayDriver(void); -void BindDisplayVariables(void); - -extern int show_endoom; -extern int graphical_startup; -extern int png_screenshots; - -#endif /* #ifndef SETUP_DISPLAY_H */ diff --git a/games/NXDoom/src/setup/execute.c b/games/NXDoom/src/setup/execute.c deleted file mode 100644 index 2dc0ba85d90..00000000000 --- a/games/NXDoom/src/setup/execute.c +++ /dev/null @@ -1,429 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// Code for invoking Doom - -#include -#include -#include -#include -#include - -#include - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -#else - -#include -#include - -#endif - -#include "textscreen.h" - -#include "config.h" -#include "execute.h" -#include "mode.h" -#include "m_argv.h" -#include "m_config.h" -#include "m_misc.h" - -struct execute_context_s -{ - char *response_file; - FILE *stream; -}; - -// Returns the path to a temporary file of the given name, stored -// inside the system temporary directory. - -static char *TempFile(const char *s) -{ - const char *tempdir; - -#ifdef _WIN32 - // Check the TEMP environment variable to find the location. - - tempdir = M_getenv("TEMP"); - - if (tempdir == NULL) - { - tempdir = "."; - } -#else - // Check the $TMPDIR environment variable to find the location. - - tempdir = getenv("TMPDIR"); - - if (tempdir == NULL) - { - tempdir = "/tmp"; - } -#endif - - return M_StringJoin(tempdir, DIR_SEPARATOR_S, s, NULL); -} - -static int ArgumentNeedsEscape(const char *arg) -{ - const char *p; - - for (p = arg; *p != '\0'; ++p) - { - if (isspace(*p)) - { - return 1; - } - } - - return 0; -} - -// Arguments passed to the setup tool should be passed through to the -// game when launching a game. Calling this adds all arguments from -// myargv to the output context. - -void PassThroughArguments(execute_context_t *context) -{ - int i; - - for (i = 1; i < myargc; ++i) - { - if (ArgumentNeedsEscape(myargv[i])) - { - AddCmdLineParameter(context, "\"%s\"", myargv[i]); - } - else - { - AddCmdLineParameter(context, "%s", myargv[i]); - } - } -} - -execute_context_t *NewExecuteContext(void) -{ - execute_context_t *result; - - result = malloc(sizeof(execute_context_t)); - - result->response_file = TempFile("chocolat.rsp"); - result->stream = M_fopen(result->response_file, "w"); - - if (result->stream == NULL) - { - fprintf(stderr, "Error opening response file\n"); - exit(-1); - } - - return result; -} - -void AddCmdLineParameter(execute_context_t *context, const char *s, ...) -{ - va_list args; - - va_start(args, s); - - vfprintf(context->stream, s, args); - fprintf(context->stream, "\n"); - - va_end(args); -} - -#if defined(_WIN32) - -boolean OpenFolder(const char *path) -{ - // "If the function succeeds, it returns a value greater than 32." - return (int)ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; -} - -// Wait for the specified process to exit. Returns the exit code. -static unsigned int WaitForProcessExit(HANDLE subprocess) -{ - DWORD exit_code; - - for (;;) - { - WaitForSingleObject(subprocess, INFINITE); - - if (!GetExitCodeProcess(subprocess, &exit_code)) - { - return -1; - } - - if (exit_code != STILL_ACTIVE) - { - return exit_code; - } - } -} - -static void ConcatWCString(wchar_t *buf, const char *value) -{ - MultiByteToWideChar(CP_OEMCP, 0, - value, strlen(value) + 1, - buf + wcslen(buf), strlen(value) + 1); -} - -// Build the command line string, a wide character string of the form: -// -// "program" "arg" - -static wchar_t *BuildCommandLine(const char *program, const char *arg) -{ - wchar_t exe_path[MAX_PATH]; - wchar_t *result; - wchar_t *sep; - - // Get the path to this .exe file. - - GetModuleFileNameW(NULL, exe_path, MAX_PATH); - - // Allocate buffer to contain result string. - - result = calloc(wcslen(exe_path) + strlen(program) + strlen(arg) + 6, - sizeof(wchar_t)); - - wcscpy(result, L"\""); - - // Copy the path part of the filename (including ending \) - // into the result buffer: - - sep = wcsrchr(exe_path, DIR_SEPARATOR); - - if (sep != NULL) - { - wcsncpy(result + 1, exe_path, sep - exe_path + 1); - result[sep - exe_path + 2] = '\0'; - } - - // Concatenate the name of the program: - - ConcatWCString(result, program); - - // End of program name, start of argument: - - wcscat(result, L"\" \""); - - ConcatWCString(result, arg); - - wcscat(result, L"\""); - - return result; -} - -static int ExecuteCommand(const char *program, const char *arg) -{ - STARTUPINFOW startup_info; - PROCESS_INFORMATION proc_info; - wchar_t *command; - int result = 0; - - command = BuildCommandLine(program, arg); - - // Invoke the program: - - memset(&proc_info, 0, sizeof(proc_info)); - memset(&startup_info, 0, sizeof(startup_info)); - startup_info.cb = sizeof(startup_info); - - if (!CreateProcessW(NULL, command, - NULL, NULL, FALSE, 0, NULL, NULL, - &startup_info, &proc_info)) - { - result = -1; - } - else - { - // Wait for the process to finish, and save the exit code. - - result = WaitForProcessExit(proc_info.hProcess); - - CloseHandle(proc_info.hProcess); - CloseHandle(proc_info.hThread); - } - - free(command); - - return result; -} - -#else - -boolean OpenFolder(const char *path) -{ - char *cmd; - int result; - -#if defined(__MACOSX__) - cmd = M_StringJoin("open \"", path, "\"", NULL); -#else - cmd = M_StringJoin("xdg-open \"", path, "\"", NULL); -#endif - result = system(cmd); - free(cmd); - - return result == 0; -} - -// Given the specified program name, get the full path to the program, -// assuming that it is in the same directory as this program is. - -static char *GetFullExePath(const char *program) -{ - char *result; - char *sep; - size_t result_len; - unsigned int path_len; - - sep = strrchr(myargv[0], DIR_SEPARATOR); - - if (sep == NULL) - { - result = M_StringDuplicate(program); - } - else - { - path_len = sep - myargv[0] + 1; - result_len = strlen(program) + path_len + 1; - result = malloc(result_len); - - M_StringCopy(result, myargv[0], result_len); - result[path_len] = '\0'; - - M_StringConcat(result, program, result_len); - } - - return result; -} - -static int ExecuteCommand(const char *program, const char *arg) -{ - pid_t childpid; - int result; - const char *argv[3]; - - childpid = fork(); - - if (childpid == 0) - { - // This is the child. Execute the command. - - argv[0] = GetFullExePath(program); - argv[1] = arg; - argv[2] = NULL; - - execvp(argv[0], (char **) argv); - - exit(0x80); - } - else - { - // This is the parent. Wait for the child to finish, and return - // the status code. - - waitpid(childpid, &result, 0); - - if (WIFEXITED(result) && WEXITSTATUS(result) != 0x80) - { - return WEXITSTATUS(result); - } - else - { - return -1; - } - } -} - -#endif - -int ExecuteDoom(execute_context_t *context) -{ - char *response_file_arg; - int result; - - fclose(context->stream); - - // Build the command line - - response_file_arg = M_StringJoin("@", context->response_file, NULL); - - // Run Doom - - result = ExecuteCommand(GetExecutableName(), response_file_arg); - - free(response_file_arg); - - // Destroy context - M_remove(context->response_file); - free(context->response_file); - free(context); - - return result; -} - -static void TestCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) -{ - execute_context_t *exec; - char *main_cfg; - char *extra_cfg; - txt_window_t *testwindow; - - testwindow = TXT_MessageBox("Starting Doom", - "Starting Doom to test the\n" - "settings. Please wait."); - TXT_DrawDesktop(); - - // Save temporary configuration files with the current configuration - - main_cfg = TempFile("tmp.cfg"); - extra_cfg = TempFile("extratmp.cfg"); - - M_SaveDefaultsAlternate(main_cfg, extra_cfg); - - // Run with the -testcontrols parameter - - exec = NewExecuteContext(); - AddCmdLineParameter(exec, "-testcontrols"); - AddCmdLineParameter(exec, "-config \"%s\"", main_cfg); - AddCmdLineParameter(exec, "-extraconfig \"%s\"", extra_cfg); - ExecuteDoom(exec); - - TXT_CloseWindow(testwindow); - - // Delete the temporary config files - - M_remove(main_cfg); - M_remove(extra_cfg); - free(main_cfg); - free(extra_cfg); -} - -txt_window_action_t *TestConfigAction(void) -{ - txt_window_action_t *test_action; - - test_action = TXT_NewWindowAction('t', "Test"); - TXT_SignalConnect(test_action, "pressed", TestCallback, NULL); - - return test_action; -} - diff --git a/games/NXDoom/src/setup/execute.h b/games/NXDoom/src/setup/execute.h deleted file mode 100644 index 21530f14d60..00000000000 --- a/games/NXDoom/src/setup/execute.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef TESTCONFIG_H -#define TESTCONFIG_H - -#include "doomtype.h" -#include "textscreen.h" - -typedef struct execute_context_s execute_context_t; - -#define IWAD_DOOM2 (1 << 0) /* doom2.wad */ -#define IWAD_PLUTONIA (1 << 1) /* plutonia.wad */ -#define IWAD_TNT (1 << 2) /* tnt.wad */ -#define IWAD_DOOM (1 << 3) /* doom.wad */ -#define IWAD_DOOM1 (1 << 4) /* doom1.wad */ -#define IWAD_CHEX (1 << 5) /* chex.wad */ - -execute_context_t *NewExecuteContext(void); -void AddCmdLineParameter(execute_context_t *context, const char *s, ...) PRINTF_ATTR(2, 3); -void PassThroughArguments(execute_context_t *context); -int ExecuteDoom(execute_context_t *context); -int FindInstalledIWADs(void); -boolean OpenFolder(const char *path); - -txt_window_action_t *TestConfigAction(void); - -#endif /* #ifndef TESTCONFIG_H */ - diff --git a/games/NXDoom/src/setup/joystick.c b/games/NXDoom/src/setup/joystick.c deleted file mode 100644 index 3a2b5a9089d..00000000000 --- a/games/NXDoom/src/setup/joystick.c +++ /dev/null @@ -1,1365 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include -#include - -#include "doomtype.h" -#include "i_joystick.h" -#include "m_config.h" -#include "m_controls.h" -#include "m_misc.h" -#include "textscreen.h" - -#include "execute.h" -#include "joystick.h" -#include "mode.h" -#include "txt_joyaxis.h" -#include "txt_joybinput.h" - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-gamepad" - -typedef struct -{ - const char *name; // Config file name - int value; -} joystick_config_t; - -typedef struct -{ - const char *name; - int axes, buttons, hats; - const joystick_config_t *configs; -} known_joystick_t; - -// SDL joystick successfully initialized? - -static int joystick_initted = 0; - -// Joystick enable/disable - -static int usejoystick = 0; - -// GUID and index of joystick to use. - -char *joystick_guid = ""; -int joystick_index = -1; - -// Calibration button. This is the button the user pressed at the -// start of the calibration sequence. They *must* press this button -// for each subsequent sequence. - -static int calibrate_button = -1; - -// Which joystick axis to use for horizontal movement, and whether to -// invert the direction: - -static int joystick_x_axis = 0; -static int joystick_x_invert = 0; - -// Which joystick axis to use for vertical movement, and whether to -// invert the direction: - -static int joystick_y_axis = 1; -static int joystick_y_invert = 0; - -// Strafe axis. - -static int joystick_strafe_axis = -1; -static int joystick_strafe_invert = 0; - -// Look axis. - -static int joystick_look_axis = -1; -static int joystick_look_invert = 0; - -// Configurable dead zone for each axis, specified as a percentage of the axis -// max value. -static int joystick_x_dead_zone = 33; -static int joystick_y_dead_zone = 33; -static int joystick_strafe_dead_zone = 33; -static int joystick_look_dead_zone = 33; - -int use_analog = 0; - -int joystick_turn_sensitivity = 10; -int joystick_move_sensitivity = 10; -int joystick_look_sensitivity = 10; - -// Virtual to physical mapping. -int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 -}; - -static txt_button_t *joystick_button; -static txt_joystick_axis_t *x_axis_widget; -static txt_joystick_axis_t *y_axis_widget; - -// -// Calibration -// - -static txt_window_t *calibration_window; -static SDL_Joystick **all_joysticks = NULL; -static int all_joysticks_len = 0; - -// Known controllers. -// There are lots of game controllers on the market. Try to configure -// them in a consistent way: -// -// * Use the D-pad rather than an analog stick. left/right turns the -// player, up/down moves forward/backward - ie. a "traditional" -// layout like Vanilla Doom rather than something more elaborate. -// * No strafe axis. -// * Fire and run keys together, on the main right-side buttons, -// ideally arranged so both can be controlled/covered simultaneously -// with the thumb. -// * Jump/use keys in the same cluster if possible. -// * Strafe left/right configured to map to shoulder buttons if they -// are present. No "strafe on" key unless shoulder buttons not present. -// * If a second set of shoulder buttons are also present, these map -// to prev weapon/next weapon. -// * Menu button mapped to start button. -// -// With the common right-side button arrangement that looks like this, -// which is similar to the Vanilla default configuration when using -// a Gravis Gamepad: -// -// B A = Fire -// A D B = Jump -// C C = Speed -// D = Use - -// Always loaded before others, to get a known starting configuration. -static const joystick_config_t empty_defaults[] = -{ - {"joystick_x_axis", -1}, - {"joystick_x_invert", 0}, - {"joystick_y_axis", -1}, - {"joystick_y_invert", 0}, - {"joystick_strafe_axis", -1}, - {"joystick_strafe_invert", 0}, - {"joystick_look_axis", -1}, - {"joystick_look_invert", 0}, - {"joyb_fire", -1}, - {"joyb_use", -1}, - {"joyb_strafe", -1}, - {"joyb_speed", -1}, - {"joyb_strafeleft", -1}, - {"joyb_straferight", -1}, - {"joyb_prevweapon", -1}, - {"joyb_nextweapon", -1}, - {"joyb_jump", -1}, - {"joyb_menu_activate", -1}, - {"joyb_toggle_automap", -1}, - {"joyb_useartifact", -1}, - {"joyb_invleft", -1}, - {"joyb_invright", -1}, - {"joyb_flyup", -1}, - {"joyb_flydown", -1}, - {"joyb_flycenter", -1}, - {"joystick_physical_button0", 0}, - {"joystick_physical_button1", 1}, - {"joystick_physical_button2", 2}, - {"joystick_physical_button3", 3}, - {"joystick_physical_button4", 4}, - {"joystick_physical_button5", 5}, - {"joystick_physical_button6", 6}, - {"joystick_physical_button7", 7}, - {"joystick_physical_button8", 8}, - {"joystick_physical_button9", 9}, - {"joystick_physical_button10", 10}, - {"joystick_physical_button11", 11}, - {"joystick_physical_button12", 12}, - {"joystick_physical_button13", 13}, - {"joystick_physical_button14", 14}, - {"joystick_physical_button15", 15}, - {"joystick_physical_button16", 16}, - {NULL, 0}, -}; - -static const joystick_config_t ps3_controller[] = -{ - {"joystick_x_axis", CREATE_BUTTON_AXIS(7, 5)}, - {"joystick_y_axis", CREATE_BUTTON_AXIS(4, 6)}, - {"joyb_fire", 15}, // Square - {"joyb_speed", 14}, // X - {"joyb_use", 13}, // Circle - {"joyb_jump", 12}, // Triangle - {"joyb_strafeleft", 8}, // Bottom shoulder buttons - {"joyb_straferight", 9}, - {"joyb_prevweapon", 10}, // Top shoulder buttons - {"joyb_nextweapon", 11}, - {"joyb_menu_activate", 3}, // Start - {NULL, 0}, -}; - -// Playstation 4 Dual Shock 4 (DS4) -static const joystick_config_t ps4_ds4_controller[] = -{ - {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, - {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, - {"joyb_fire", 0}, // Square - {"joyb_speed", 1}, // X - {"joyb_use", 2}, // Circle - {"joyb_jump", 3}, // Triangle - {"joyb_strafeleft", 6}, // Bottom shoulder buttons - {"joyb_straferight", 7}, - {"joyb_prevweapon", 4}, // Top shoulder buttons - {"joyb_nextweapon", 5}, - {"joyb_menu_activate", 12}, // Playstation logo button -}; - -static const joystick_config_t airflo_controller[] = -{ - {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, - {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, - {"joyb_fire", 2}, // "3" - {"joyb_speed", 0}, // "1" - {"joyb_jump", 3}, // "4" - {"joyb_use", 1}, // "2" - {"joyb_strafeleft", 6}, // Bottom shoulder buttons - {"joyb_straferight", 7}, - {"joyb_prevweapon", 4}, // Top shoulder buttons - {"joyb_nextweapon", 5}, - {"joyb_menu_activate", 9}, // "10", where "Start" usually is. - {NULL, 0}, -}; - -// Wii controller is weird, so we have to take some liberties. -// Also it's not a HID device, so it won't appear the same everywhere. -// Assume there is no nunchuk or classic controller attached. - -// When using WJoy on OS X. -static const joystick_config_t wii_controller_wjoy[] = -{ - {"joystick_x_axis", CREATE_BUTTON_AXIS(2, 3)}, - {"joystick_y_axis", CREATE_BUTTON_AXIS(1, 0)}, - {"joyb_fire", 9}, // Button 1 - {"joyb_speed", 10}, // Button 2 - {"joyb_use", 5}, // Button B (trigger) - {"joyb_prevweapon", 7}, // - - {"joyb_nextweapon", 6}, // + - {"joyb_menu_activate", 9}, // Button A - {NULL, 0}, -}; - -// Xbox 360 controller. Thanks to Brad Harding for the details. -static const joystick_config_t xbox360_controller[] = -{ - {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, - {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, - {"joystick_strafe_axis", 2}, // Trigger buttons form an axis(???) - {"joyb_fire", 2}, // X - {"joyb_speed", 0}, // A - {"joyb_jump", 3}, // Y - {"joyb_use", 1}, // B - {"joyb_prevweapon", 4}, // LB - {"joyb_nextweapon", 5}, // RB - {"joyb_menu_activate", 9}, // Start - {NULL, 0}, -}; - -// Xbox 360 controller under Linux. -static const joystick_config_t xbox360_controller_linux[] = -{ - {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, - {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, - // Ideally we'd like the trigger buttons to be strafe left/right - // But Linux presents each trigger button as its own axis, which - // we can't really work with. So we have to settle for a - // suboptimal setup. - {"joyb_fire", 2}, // X - {"joyb_speed", 0}, // A - {"joyb_jump", 3}, // Y - {"joyb_use", 1}, // B - {"joyb_strafeleft", 4}, // LB - {"joyb_straferight", 5}, // RB - {"joyb_menu_activate", 7}, // Start - {"joyb_prevweapon", 6}, // Back - {NULL, 0}, -}; - -// Logitech Dual Action (F310, F710). Thanks to Brad Harding for details. -static const joystick_config_t logitech_f310_controller[] = -{ - {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, - {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, - {"joyb_fire", 0}, // X - {"joyb_speed", 1}, // A - {"joyb_jump", 3}, // Y - {"joyb_use", 2}, // B - {"joyb_strafeleft", 6}, // LT - {"joyb_straferight", 7}, // RT - {"joyb_prevweapon", 4}, // LB - {"joyb_nextweapon", 5}, // RB - {"joyb_menu_activate", 11}, // Start - {NULL, 0}, -}; - -// Multilaser JS030 gamepad, similar to a PS2 controller. -static const joystick_config_t multilaser_js030_controller[] = -{ - {"joystick_x_axis", 0}, // Left stick / D-pad - {"joystick_y_axis", 1}, - {"joyb_fire", 3}, // Square - {"joyb_speed", 2}, // X - {"joyb_use", 1}, // Circle - {"joyb_jump", 0}, // Triangle - {"joyb_strafeleft", 6}, // Bottom shoulder buttons - {"joyb_straferight", 7}, - {"joyb_prevweapon", 4}, // Top shoulder buttons - {"joyb_nextweapon", 5}, - {"joyb_menu_activate", 9}, // Start - {NULL, 0}, -}; - -// Buffalo Classic USB Gamepad (thanks Fabian Greffrath). -static const joystick_config_t buffalo_classic_controller[] = -{ - {"joystick_x_axis", 0}, - {"joystick_y_axis", 1}, - {"joyb_use", 0}, // A - {"joyb_speed", 1}, // B - {"joyb_jump", 2}, // X - {"joyb_fire", 3}, // Y - {"joyb_strafeleft", 4}, // Left shoulder - {"joyb_straferight", 5}, // Right shoulder - {"joyb_prevweapon", 6}, // Select - {"joyb_menu_activate", 7}, // Start - {NULL, 0}, -}; - -// Config for if the user is actually using an old PC joystick or gamepad, -// probably via a USB-Gameport adapter. -static const joystick_config_t pc_gameport_controller[] = -{ - {"joystick_x_axis", 0}, - {"joystick_y_axis", 1}, - // Button configuration is the default as used for Vanilla Doom, - // Heretic and Hexen. When playing with a Gravis Gamepad, this - // layout should also be vaguely similar to the standard layout - // described above. - {"joyb_fire", 0}, - {"joyb_strafe", 1}, - {"joyb_use", 3}, - {"joyb_speed", 2}, - {NULL, 0}, -}; - -// http://www.8bitdo.com/nes30pro/ and http://www.8bitdo.com/fc30pro/ -static const joystick_config_t nes30_pro_controller[] = -{ - {"joystick_x_axis", CREATE_HAT_AXIS(0, HAT_AXIS_HORIZONTAL)}, - {"joystick_y_axis", CREATE_HAT_AXIS(0, HAT_AXIS_VERTICAL)}, - {"joyb_fire", 4}, // Y - {"joyb_speed", 1}, // B - {"joyb_jump", 3}, // X - {"joyb_use", 0}, // A - {"joyb_strafeleft", 6}, // L1 - {"joyb_straferight", 7}, // R1 - {"joyb_prevweapon", 8}, // L2 - {"joyb_nextweapon", 9}, // R2 - {"joyb_menu_activate", 11}, // Start - {"joyb_toggle_automap", 10}, // Select - {NULL, 0}, -}; - -// http://www.8bitdo.com/sfc30/ or http://www.8bitdo.com/snes30/ -// and http://www.nes30.com/ and http://www.fc30.com/ -static const joystick_config_t sfc30_controller[] = -{ - {"joystick_x_axis", 0}, - {"joystick_y_axis", 1}, - {"joyb_fire", 4}, // Y - {"joyb_speed", 1}, // B - {"joyb_jump", 3}, // X - {"joyb_use", 0}, // A - {"joyb_strafeleft", 6}, // L - {"joyb_straferight", 7}, // R - {"joyb_menu_activate", 11}, // Start - {"joyb_toggle_automap", 10}, // Select - {NULL, 0}, -}; - -static const known_joystick_t known_joysticks[] = -{ - { - "PLAYSTATION(R)3 Controller", - 4, 19, 0, - ps3_controller, - }, - - { - "AIRFLO ", - 4, 13, 1, - airflo_controller, - }, - - { - "Wiimote (*", // WJoy includes the Wiimote MAC address. - 6, 26, 0, - wii_controller_wjoy, - }, - - { - "Controller (XBOX 360 For Windows)", - 5, 10, 1, - xbox360_controller, - }, - - { - "Controller (XBOX One For Windows)", - 5, 10, 1, - xbox360_controller, - }, - - // Xbox 360 controller as it appears on Linux. - { - "Microsoft X-Box 360 pad", - 6, 11, 1, - xbox360_controller_linux, - }, - - // Xbox One controller as it appears on Linux. - { - "Microsoft X-Box One pad", - 6, 11, 1, - xbox360_controller_linux, - }, - - { - "Logitech Dual Action", - 4, 12, 1, - logitech_f310_controller, - }, - - { - "USB Vibration Joystick", - 4, 12, 1, - multilaser_js030_controller, - }, - - { - "USB,2-axis 8-button gamepad ", - 2, 8, 0, - buffalo_classic_controller, - }, - - // PS4 controller just appears as the generic-sounding "Wireless - // Controller". Hopefully the number of buttons/axes/hats should be - // enough to distinguish it from other gamepads. - { - "Wireless Controller", - 6, 14, 1, - ps4_ds4_controller, - }, - - // This is the configuration for the USB-Gameport adapter listed on - // this page as the "Mayflash USB to Gameport Adapter" (though the - // device is labeled as "Super Joy Box 7"): - // https://sites.google.com/site/joystickrehab/itemcatal - // TODO: Add extra configurations here for other USB-Gameport adapters, - // which should just be the same configuration. - { - "WiseGroup.,Ltd Gameport to USB Controller", - 4, 8, 1, - pc_gameport_controller, - }, - - // How the Super Joy Box 7 appears on Mac OS X. - { - "Gameport to USB Controller", - 2, 8, 1, - pc_gameport_controller, - }, - - // 8Bitdo NES30 Pro, http://www.8bitdo.com/nes30pro/ - { - "8Bitdo NES30 Pro", - 4, 16, 1, - nes30_pro_controller, - }, - - // the above, NES variant, via USB on Linux/Raspbian (odd values) - { - "8Bitdo NES30 Pro*", - 6, 15, 1, - nes30_pro_controller, - }, - - // the above, NES variant, connected over bluetooth - { - "8Bitdo NES30 Pro", - 6, 16, 1, - nes30_pro_controller, - }, - - // 8bitdo NES30 Pro, in joystick mode (R1+Power), swaps the D-Pad - // and analog stick inputs. Only applicable over Bluetooth. On USB, - // this mode registers the device as an Xbox 360 pad. - { - "8Bitdo NES30 Pro Joystick", - 6, 16, 1, - nes30_pro_controller, - }, - - // variant of the above, via USB on Mac - // Note: untested, but theorized to exist based on us comparing - // a NES30 Pro tested on Linux with a FC30 Pro tested with Mac & Linux - { - "8Bitdo NES30 Pro", - 4, 15, 1, - nes30_pro_controller, - }, - - - // 8Bitdo FC30 Pro, http://8bitdo.cn/fc30pro/ - // connected over bluetooth - { - "8Bitdo FC30 Pro", - 4, 16, 1, - nes30_pro_controller, - }, - - // variant of the above, via USB on Linux/Raspbian - { - "8Bitdo FC30 Pro*", - 6, 15, 1, - nes30_pro_controller, - }, - - // variant of the above, Linux/bluetooth - { - "8Bitdo FC30 Pro", - 6, 16, 1, - nes30_pro_controller, - }, - - // variant of the above, via USB on Mac - { - "8Bitdo FC30 Pro", - 4, 15, 1, - nes30_pro_controller, - }, - - // 8Bitdo SFC30 SNES replica controller - // in default mode and in controller mode (Start+R) - // the latter suffixes "Joystick" to the name - // http://www.8bitdo.com/sfc30/ - { - "8Bitdo SFC30 GamePad*", - 4, 16, 1, - sfc30_controller, - }, - - // As above, but as detected on RHEL Linux (odd extra axes) - { - "8Bitdo SFC30 GamePad*", - 6, 16, 1, - sfc30_controller, - }, - - // SNES30 colour variation of the above - // http://www.8bitdo.com/snes30/ - { - "8Bitdo SNES30 GamePad*", - 4, 16, 1, - sfc30_controller, - }, - - // 8Bitdo SFC30 SNES replica controller in USB controller mode - // tested with firmware V2.68 (Beta); latest stable V2.65 doesn't work on - // OS X in USB controller mode - // Names seen so far: - // 'SFC30 Joystick' (OS X) - // 'SFC30 SFC30 Joystick' (Fedora 24; RHEL7) - // XXX: there is probably a SNES30 variant of this too - { - "SFC30 *", - 4, 12, 1, - sfc30_controller, - }, - - // NES30 (not pro), tested in default and "hold R whilst turning on" - // mode, with whatever firmware it came with out of the box. Latter - // mode puts " Joystick" suffix on the name string - { - "8Bitdo NES30 GamePad*", - 4, 16, 1, - sfc30_controller, // identical to SFC30 - }, - // FC30 variant of the above - { - "8Bitdo FC30 GamePad*", - 4, 16, 1, - sfc30_controller, // identical to SFC30 - }, - - // NES30 in USB mode - { - "NES30*", - 4, 12, 1, - sfc30_controller, // identical to SFC30 - }, - // FC30 variant of the above - { - "FC30*", - 4, 12, 1, - sfc30_controller, // identical to SFC30 - }, -}; - -// Use SDL_GameController interface -int use_gamepad = 0; - -// SDL_GameControllerType of gamepad -int gamepad_type = 0; - -// Based on Unity Doom mapping -static const joystick_config_t modern_gamepad[] = -{ - {"joystick_x_axis", SDL_CONTROLLER_AXIS_RIGHTX}, - {"joystick_y_axis", SDL_CONTROLLER_AXIS_LEFTY}, - {"joystick_strafe_axis", SDL_CONTROLLER_AXIS_LEFTX}, - {"joystick_look_axis", SDL_CONTROLLER_AXIS_RIGHTY}, - {"joyb_fire", GAMEPAD_BUTTON_TRIGGERRIGHT}, - {"joyb_speed", GAMEPAD_BUTTON_TRIGGERLEFT}, - {"joyb_use", SDL_CONTROLLER_BUTTON_B}, - {"joyb_jump", SDL_CONTROLLER_BUTTON_A}, - {"joyb_prevweapon", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, - {"joyb_nextweapon", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, - {"joyb_menu_activate", SDL_CONTROLLER_BUTTON_START}, - {"joyb_toggle_automap", SDL_CONTROLLER_BUTTON_Y}, - {"joyb_useartifact", SDL_CONTROLLER_BUTTON_X}, - {"joyb_invleft", SDL_CONTROLLER_BUTTON_DPAD_LEFT}, - {"joyb_invright", SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, - {"joyb_flyup", SDL_CONTROLLER_BUTTON_DPAD_UP}, - {"joyb_flydown", SDL_CONTROLLER_BUTTON_DPAD_DOWN}, - {"joyb_flycenter", SDL_CONTROLLER_BUTTON_LEFTSTICK}, - {NULL, 0}, -}; - -// Based on the SNES Doom mapping -static const joystick_config_t classic_gamepad[] = -{ - {"joystick_x_axis", SDL_CONTROLLER_AXIS_LEFTX}, - {"joystick_y_axis", SDL_CONTROLLER_AXIS_LEFTY}, - {"joyb_fire", SDL_CONTROLLER_BUTTON_X}, // SNES Y - {"joyb_speed", SDL_CONTROLLER_BUTTON_A}, // SNES B - {"joyb_use", SDL_CONTROLLER_BUTTON_B}, // SNES A - {"joyb_strafeleft", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, // SNES L - {"joyb_straferight", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, // SNES R - {"joyb_nextweapon", SDL_CONTROLLER_BUTTON_Y}, // SNES X - {"joyb_menu_activate", SDL_CONTROLLER_BUTTON_START}, // SNES Start - {"joyb_toggle_automap", SDL_CONTROLLER_BUTTON_BACK}, // SNES Select - {NULL, 0}, -}; - -// SNES Doom mapping with extra shoulder buttons -static const joystick_config_t classic_gamepad_plus[] = -{ - {"joystick_x_axis", SDL_CONTROLLER_AXIS_LEFTX}, - {"joystick_y_axis", SDL_CONTROLLER_AXIS_LEFTY}, - {"joyb_fire", SDL_CONTROLLER_BUTTON_X}, // SNES Y - {"joyb_speed", SDL_CONTROLLER_BUTTON_A}, // SNES B - {"joyb_use", SDL_CONTROLLER_BUTTON_B}, // SNES A - {"joyb_strafeleft", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, // L1 - {"joyb_straferight", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, // R1 - {"joyb_prevweapon", GAMEPAD_BUTTON_TRIGGERLEFT}, // L2 - {"joyb_nextweapon", GAMEPAD_BUTTON_TRIGGERRIGHT}, // R2 - {"joyb_menu_activate", SDL_CONTROLLER_BUTTON_START}, // SNES Start - {"joyb_toggle_automap", SDL_CONTROLLER_BUTTON_BACK}, // SNES Select - {NULL, 0}, -}; - -static const known_joystick_t *GetJoystickType(int index) -{ - SDL_Joystick *joystick; - const char *name; - int axes, buttons, hats; - int i; - - joystick = all_joysticks[index]; - name = SDL_JoystickName(joystick); - axes = SDL_JoystickNumAxes(joystick); - buttons = SDL_JoystickNumButtons(joystick); - hats = SDL_JoystickNumHats(joystick); - - for (i = 0; i < arrlen(known_joysticks); ++i) - { - // Check for a name match. If the name ends in '*', this means - // ignore the rest. - if (M_StringEndsWith(known_joysticks[i].name, "*")) - { - if (strncmp(known_joysticks[i].name, name, - strlen(known_joysticks[i].name) - 1) != 0) - { - continue; - } - } - else - { - if (strcmp(known_joysticks[i].name, name) != 0) - { - continue; - } - } - - if (known_joysticks[i].axes == axes - && known_joysticks[i].buttons == buttons - && known_joysticks[i].hats == hats) - { - return &known_joysticks[i]; - } - } - - printf("Unknown joystick '%s' with %i axes, %i buttons, %i hats\n", - name, axes, buttons, hats); - printf("Please consider sending in details about your gamepad!\n"); - - return NULL; -} - -// Query if the joystick at the given index is a known joystick type. -static boolean IsKnownJoystick(int index) -{ - return GetJoystickType(index) != NULL; -} - -// Load a configuration set. -static void LoadConfigurationSet(const joystick_config_t *configs) -{ - const joystick_config_t *config; - char buf[10]; - int button; - int i; - - button = 0; - - for (i = 0; configs[i].name != NULL; ++i) - { - config = &configs[i]; - - // Don't overwrite autorun if it is set. - if (!strcmp(config->name, "joyb_speed") && - joybspeed >= MAX_VIRTUAL_BUTTONS) - { - continue; - } - - // For buttons, set the virtual button mapping as well. - if (M_StringStartsWith(config->name, "joyb_") && config->value >= 0) - { - joystick_physical_buttons[button] = config->value; - M_snprintf(buf, sizeof(buf), "%i", button); - M_SetVariable(config->name, buf); - ++button; - } - else - { - M_snprintf(buf, sizeof(buf), "%i", config->value); - M_SetVariable(config->name, buf); - } - } -} - -// Load configuration for joystick_index based on known types. -static void LoadKnownConfiguration(void) -{ - const known_joystick_t *jstype; - - jstype = GetJoystickType(joystick_index); - if (jstype == NULL) - { - return; - } - - LoadConfigurationSet(empty_defaults); - LoadConfigurationSet(jstype->configs); -} - -static void InitJoystick(void) -{ - if (!joystick_initted) - { - joystick_initted = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0; - } -} - -static void UnInitJoystick(void) -{ - if (joystick_initted) - { - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - joystick_initted = 0; - } -} - -// We identify joysticks using GUID where possible, but joystick_index -// is used to distinguish between different devices. As the index can -// change, UpdateJoystickIndex() checks to see if it is still valid and -// updates it as appropriate. -static void UpdateJoystickIndex(void) -{ - SDL_JoystickGUID guid, dev_guid; - int i; - - guid = SDL_JoystickGetGUIDFromString(joystick_guid); - - // Is joystick_index already correct? - if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) - { - dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - return; - } - } - - // If index is not correct, look for the first device with the - // expected GUID. It may have moved to a different index. - for (i = 0; i < SDL_NumJoysticks(); ++i) - { - dev_guid = SDL_JoystickGetDeviceGUID(i); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - joystick_index = i; - return; - } - } - - // Not found; it's possible the device is disconnected. Do not - // reset joystick_guid or joystick_index in case they are - // reconnected later. -} - -// Set the label showing the name of the currently selected joystick -static void SetJoystickButtonLabel(void) -{ - SDL_JoystickGUID guid, dev_guid; - const char *name; - - if (!usejoystick || !strcmp(joystick_guid, "")) - { - name = "None set"; - } - else - { - name = "Not found (device disconnected?)"; - - // Use the device name if the GUID and index match. - if (joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) - { - guid = SDL_JoystickGetGUIDFromString(joystick_guid); - dev_guid = SDL_JoystickGetDeviceGUID(joystick_index); - if (!memcmp(&guid, &dev_guid, sizeof(SDL_JoystickGUID))) - { - name = SDL_JoystickNameForIndex(joystick_index); - } - } - } - - TXT_SetButtonLabel(joystick_button, (char *) name); -} - -// Try to open all joysticks visible to SDL. - -static int OpenAllJoysticks(void) -{ - int i; - int result; - - InitJoystick(); - - // SDL_JoystickOpen() all joysticks. - - all_joysticks_len = SDL_NumJoysticks(); - all_joysticks = calloc(all_joysticks_len, sizeof(SDL_Joystick *)); - - result = 0; - - for (i = 0; i < all_joysticks_len; ++i) - { - all_joysticks[i] = SDL_JoystickOpen(i); - - // If any joystick is successfully opened, return true. - - if (all_joysticks[i] != NULL) - { - result = 1; - } - } - - // Success? Turn on joystick events. - - if (result) - { - SDL_JoystickEventState(SDL_ENABLE); - } - else - { - free(all_joysticks); - all_joysticks = NULL; - } - - return result; -} - -// Close all the joysticks opened with OpenAllJoysticks() - -static void CloseAllJoysticks(void) -{ - int i; - - for (i = 0; i < all_joysticks_len; ++i) - { - if (all_joysticks[i] != NULL) - { - SDL_JoystickClose(all_joysticks[i]); - } - } - - SDL_JoystickEventState(SDL_DISABLE); - - free(all_joysticks); - all_joysticks = NULL; - - UnInitJoystick(); -} - -static void CalibrateXAxis(void) -{ - TXT_ConfigureJoystickAxis(x_axis_widget, calibrate_button, NULL); -} - -// Given the SDL_JoystickID instance ID from a button event, set the -// joystick_guid and joystick_index config variables. -static boolean SetJoystickGUID(SDL_JoystickID joy_id) -{ - SDL_JoystickGUID guid; - int i; - - for (i = 0; i < all_joysticks_len; ++i) - { - if (SDL_JoystickInstanceID(all_joysticks[i]) == joy_id) - { - guid = SDL_JoystickGetGUID(all_joysticks[i]); - joystick_guid = malloc(GUID_STRING_BUF_SIZE); - SDL_JoystickGetGUIDString(guid, joystick_guid, - GUID_STRING_BUF_SIZE); - joystick_index = i; - - return true; - } - } - - return false; -} - -static void GetGamepadDefaultConfig(void) -{ - boolean have_four_shoulder, have_dual_sticks; - char *mapping; - SDL_JoystickGUID guid; - - guid = SDL_JoystickGetGUID(all_joysticks[joystick_index]); - mapping = SDL_GameControllerMappingForGUID(guid); - have_four_shoulder = - strstr(mapping, "leftshoulder") && strstr(mapping, "rightshoulder") && - strstr(mapping, "lefttrigger") && strstr(mapping, "righttrigger"); - have_dual_sticks = strstr(mapping, "leftx") && strstr(mapping, "rightx"); - SDL_free(mapping); - - LoadConfigurationSet(empty_defaults); - - if (have_four_shoulder && have_dual_sticks) - { - LoadConfigurationSet(modern_gamepad); - } - else if (have_four_shoulder) - { - LoadConfigurationSet(classic_gamepad_plus); - } - else - { - LoadConfigurationSet(classic_gamepad); - } -} - -static int CalibrationEventCallback(SDL_Event *event, void *user_data) -{ - if (event->type != SDL_JOYBUTTONDOWN) - { - return 0; - } - - if (!SetJoystickGUID(event->jbutton.which)) - { - return 0; - } - - if (SDL_IsGameController(joystick_index)) - { - usejoystick = 1; - use_gamepad = 1; - gamepad_type = SDL_GameControllerTypeForIndex(joystick_index); - LoadConfigurationSet(empty_defaults); - GetGamepadDefaultConfig(); - TXT_CloseWindow(calibration_window); - return 1; - } - - // At this point, we have a button press. - // In the first "center" stage, we're just trying to work out which - // joystick is being configured and which button the user is pressing. - usejoystick = 1; - use_gamepad = 0; - gamepad_type = SDL_CONTROLLER_TYPE_UNKNOWN; - calibrate_button = event->jbutton.button; - - // If the joystick is a known one, auto-load default - // config for it. Otherwise, proceed with calibration. - if (IsKnownJoystick(joystick_index)) - { - LoadKnownConfiguration(); - TXT_CloseWindow(calibration_window); - } - else - { - TXT_CloseWindow(calibration_window); - - // Calibrate joystick axes: Y axis first, then X axis once - // completed. - TXT_ConfigureJoystickAxis(y_axis_widget, calibrate_button, - CalibrateXAxis); - } - - return 1; -} - -static void NoJoystick(void) -{ - TXT_MessageBox(NULL, "No gamepads or joysticks could be found.\n\n" - "Try configuring your controller from within\n" - "your OS first. Maybe you need to install\n" - "some drivers or otherwise configure it."); - - usejoystick = 0; - use_gamepad = 0; - joystick_index = -1; - SetJoystickButtonLabel(); -} - -static void RefreshJoystickWindow(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(unused)) -{ - ConfigJoystick(NULL, NULL); -} - -static void CalibrateWindowClosed(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(joystick_window)) -{ - TXT_CAST_ARG(txt_window_t, joystick_window); - TXT_SDL_SetEventCallback(NULL, NULL); - SetJoystickButtonLabel(); - CloseAllJoysticks(); - - // Refresh Joystick window to update button and axis widgets. - TXT_SignalConnect(joystick_window, "closed", RefreshJoystickWindow, NULL); - TXT_CloseWindow(joystick_window); -} - -static void CalibrateJoystick(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(joystick_window)) -{ - TXT_CAST_ARG(txt_window_t, joystick_window); - - // Try to open all available joysticks. If none are opened successfully, - // bomb out with an error. - - if (!OpenAllJoysticks()) - { - NoJoystick(); - return; - } - - calibration_window = TXT_NewWindow("Gamepad/Joystick calibration"); - - TXT_AddWidgets(calibration_window, - TXT_NewStrut(0, 1), - TXT_NewLabel("Center the D-pad or joystick,\n" - "and press a button."), - TXT_NewStrut(0, 1), - NULL); - - TXT_SetWindowAction(calibration_window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction(calibration_window, TXT_HORIZ_CENTER, - TXT_NewWindowAbortAction(calibration_window)); - TXT_SetWindowAction(calibration_window, TXT_HORIZ_RIGHT, NULL); - - TXT_SDL_SetEventCallback(CalibrationEventCallback, NULL); - - TXT_SignalConnect(calibration_window, "closed", CalibrateWindowClosed, - joystick_window); - - // Start calibration -} - -// -// GUI -// - -static void AddJoystickControl(TXT_UNCAST_ARG(table), const char *label, int *var) -{ - TXT_CAST_ARG(txt_table_t, table); - txt_joystick_input_t *joy_input; - - joy_input = TXT_NewJoystickInput(var); - - TXT_AddWidgets(table, - TXT_NewLabel(label), - joy_input, - TXT_TABLE_EMPTY, - NULL); -} - -static void SwapLRSticks(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - // Single pad/stick controllers don't get a joystick_strafe_axis value - if (joystick_strafe_axis >= 0) - { - if (joystick_x_axis == SDL_CONTROLLER_AXIS_LEFTX) - { - joystick_x_axis = SDL_CONTROLLER_AXIS_RIGHTX; - joystick_y_axis = SDL_CONTROLLER_AXIS_LEFTY; - joystick_strafe_axis = SDL_CONTROLLER_AXIS_LEFTX; - joystick_look_axis = SDL_CONTROLLER_AXIS_RIGHTY; - } - else - { - joystick_x_axis = SDL_CONTROLLER_AXIS_LEFTX; - joystick_y_axis = SDL_CONTROLLER_AXIS_RIGHTY; - joystick_strafe_axis = SDL_CONTROLLER_AXIS_RIGHTX; - joystick_look_axis = SDL_CONTROLLER_AXIS_LEFTY; - } - } -} - -static void AdjustAnalog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - txt_window_t *window; - - window = TXT_NewWindow("Analog Settings"); - TXT_SetTableColumns(window, 2); - TXT_SetColumnWidths(window, 10, 6); - TXT_AddWidgets(window, - TXT_NewCheckBox("Use analog controls", &use_analog), - TXT_NewSeparator("Sensitivity"), - TXT_NewLabel("Movement"), - TXT_NewSpinControl(&joystick_move_sensitivity, 0, 20), - TXT_NewLabel("Turn"), - TXT_NewSpinControl(&joystick_turn_sensitivity, 0, 20), - NULL); - if (gamemission == heretic || gamemission == hexen || gamemission == strife) - { - TXT_AddWidgets(window, - TXT_NewLabel("Look"), - TXT_NewSpinControl(&joystick_look_sensitivity, 0, 20), NULL); - } - TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, - TXT_NewWindowEscapeAction(window)); - TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); - TXT_SetWidgetAlign(window, TXT_HORIZ_CENTER); -} - -static void MoreControls(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - txt_window_t *window; - - window = TXT_NewWindow("Additional Gamepad/Joystick buttons"); - TXT_SetTableColumns(window, 6); - TXT_SetColumnWidths(window, 20, 10, 1, 20, 10, 0); - - AddJoystickControl(window, "Use inventory item", &joybuseartifact); - AddJoystickControl(window, "Inventory left", &joybinvleft); - AddJoystickControl(window, "Inventory right", &joybinvright); - if (gamemission == heretic || gamemission == hexen) - { - AddJoystickControl(window, "Fly up", &joybflyup); - AddJoystickControl(window, "Fly down", &joybflydown); - AddJoystickControl(window, "Fly center", &joybflycenter); - } - - TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, - TXT_NewWindowEscapeAction(window)); - TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); - TXT_SetWidgetAlign(window, TXT_HORIZ_CENTER); -} - -void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - - window = TXT_NewWindow("Gamepad/Joystick configuration"); - TXT_SetTableColumns(window, 6); - TXT_SetColumnWidths(window, 18, 10, 1, 18, 10, 0); - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - TXT_AddWidgets(window, - TXT_NewLabel("Controller"), - joystick_button = TXT_NewButton("zzzz"), - TXT_TABLE_EOL, - - TXT_NewSeparator("Axes"), - TXT_NewLabel("Forward/backward"), - y_axis_widget = TXT_NewJoystickAxis(&joystick_y_axis, - &joystick_y_invert, - &joystick_y_dead_zone, - JOYSTICK_AXIS_VERTICAL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_EMPTY, - TXT_TABLE_EMPTY, - - TXT_NewLabel("Turn left/right"), - x_axis_widget = - TXT_NewJoystickAxis(&joystick_x_axis, - &joystick_x_invert, - &joystick_x_dead_zone, - JOYSTICK_AXIS_HORIZONTAL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_EMPTY, - TXT_TABLE_EMPTY, - - TXT_NewLabel("Strafe left/right"), - TXT_NewJoystickAxis(&joystick_strafe_axis, - &joystick_strafe_invert, - &joystick_strafe_dead_zone, - JOYSTICK_AXIS_HORIZONTAL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_EMPTY, - TXT_TABLE_EMPTY, - NULL); - - if (gamemission == heretic || gamemission == hexen || gamemission == strife) - { - TXT_AddWidgets(window, - TXT_NewLabel("Look up/down"), - TXT_NewJoystickAxis(&joystick_look_axis, - &joystick_look_invert, - &joystick_look_dead_zone, - JOYSTICK_AXIS_VERTICAL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_EMPTY, - TXT_TABLE_EMPTY, - NULL); - } - - TXT_AddWidget(window, - TXT_NewConditional(&use_gamepad, 1, - TXT_NewButton2("Swap L and R sticks", SwapLRSticks, NULL))); - TXT_AddWidget(window, TXT_TABLE_EOL); - - TXT_AddWidget(window, - TXT_NewButton2("Analog settings", AdjustAnalog, NULL)); - TXT_AddWidget(window, TXT_TABLE_EOL); - - TXT_AddWidget(window, TXT_NewSeparator("Buttons")); - - AddJoystickControl(window, "Fire/Attack", &joybfire); - AddJoystickControl(window, "Strafe Left", &joybstrafeleft); - - AddJoystickControl(window, "Use", &joybuse); - AddJoystickControl(window, "Strafe Right", &joybstraferight); - - AddJoystickControl(window, "Previous weapon", &joybprevweapon); - AddJoystickControl(window, "Strafe", &joybstrafe); - - AddJoystickControl(window, "Next weapon", &joybnextweapon); - - // High values of joybspeed are used to activate the "always run mode" - // trick in Vanilla Doom. If this has been enabled, not only is the - // joybspeed value meaningless, but the control itself is useless. - - if (joybspeed < MAX_VIRTUAL_BUTTONS) - { - AddJoystickControl(window, "Run", &joybspeed); - } - - if (gamemission == hexen || gamemission == strife) - { - AddJoystickControl(window, "Jump", &joybjump); - } - - AddJoystickControl(window, "Activate menu", &joybmenu); - - AddJoystickControl(window, "Toggle Automap", &joybautomap); - - if (gamemission == heretic || gamemission == hexen || gamemission == strife) - { - TXT_AddWidget(window, - TXT_NewButton2("More controls...", MoreControls, NULL)); - TXT_AddWidget(window, TXT_TABLE_EOL); - } - - TXT_SignalConnect(joystick_button, "pressed", CalibrateJoystick, window); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); - - InitJoystick(); - UpdateJoystickIndex(); - SetJoystickButtonLabel(); - UnInitJoystick(); -} - -void BindJoystickVariables(void) -{ - int i; - - M_BindIntVariable("use_joystick", &usejoystick); - M_BindIntVariable("use_gamepad", &use_gamepad); - M_BindIntVariable("gamepad_type", &gamepad_type); - M_BindStringVariable("joystick_guid", &joystick_guid); - M_BindIntVariable("joystick_index", &joystick_index); - M_BindIntVariable("joystick_x_axis", &joystick_x_axis); - M_BindIntVariable("joystick_y_axis", &joystick_y_axis); - M_BindIntVariable("joystick_strafe_axis", &joystick_strafe_axis); - M_BindIntVariable("joystick_x_invert", &joystick_x_invert); - M_BindIntVariable("joystick_y_invert", &joystick_y_invert); - M_BindIntVariable("joystick_strafe_invert", &joystick_strafe_invert); - M_BindIntVariable("joystick_look_axis", &joystick_look_axis); - M_BindIntVariable("joystick_look_invert", &joystick_look_invert); - M_BindIntVariable("joystick_x_dead_zone", &joystick_x_dead_zone); - M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone); - M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone); - M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone); - M_BindIntVariable("use_analog", &use_analog); - M_BindIntVariable("joystick_turn_sensitivity", &joystick_turn_sensitivity); - M_BindIntVariable("joystick_move_sensitivity", &joystick_move_sensitivity); - M_BindIntVariable("joystick_look_sensitivity", &joystick_look_sensitivity); - - for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) - { - char name[32]; - M_snprintf(name, sizeof(name), "joystick_physical_button%i", i); - M_BindIntVariable(name, &joystick_physical_buttons[i]); - } -} - diff --git a/games/NXDoom/src/setup/joystick.h b/games/NXDoom/src/setup/joystick.h deleted file mode 100644 index dd17b7d92f0..00000000000 --- a/games/NXDoom/src/setup/joystick.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_JOYSTICK_H -#define SETUP_JOYSTICK_H - - -#include "i_joystick.h" - - -extern int joystick_index; -extern int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS]; -extern int use_gamepad; -extern int gamepad_type; - - -void ConfigJoystick(void *widget, void *user_data); -void BindJoystickVariables(void); - -#endif /* #ifndef SETUP_JOYSTICK_H */ - diff --git a/games/NXDoom/src/setup/keyboard.c b/games/NXDoom/src/setup/keyboard.c deleted file mode 100644 index 02de4f88b3d..00000000000 --- a/games/NXDoom/src/setup/keyboard.c +++ /dev/null @@ -1,448 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include "textscreen.h" -#include "doomtype.h" -#include "m_config.h" -#include "m_controls.h" -#include "m_misc.h" - -#include "execute.h" -#include "txt_keyinput.h" - -#include "mode.h" -#include "joystick.h" -#include "keyboard.h" - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-keyboard" - -int vanilla_keyboard_mapping = 1; - -static int always_run = 0; - -// Keys within these groups cannot have the same value. - -static int *controls[] = { &key_left, &key_right, &key_up, &key_down, - &key_strafeleft, &key_straferight, &key_fire, - &key_use, &key_strafe, &key_speed, &key_jump, - &key_flyup, &key_flydown, &key_flycenter, - &key_lookup, &key_lookdown, &key_lookcenter, - &key_invleft, &key_invright, &key_invquery, - &key_invuse, &key_invpop, &key_mission, &key_invkey, - &key_invhome, &key_invend, &key_invdrop, - &key_useartifact, &key_pause, &key_usehealth, - &key_weapon1, &key_weapon2, &key_weapon3, - &key_weapon4, &key_weapon5, &key_weapon6, - &key_weapon7, &key_weapon8, - &key_arti_quartz, &key_arti_urn, &key_arti_bomb, - &key_arti_tome, &key_arti_ring, &key_arti_chaosdevice, - &key_arti_shadowsphere, &key_arti_wings, - &key_arti_torch, &key_arti_morph, - &key_arti_all, &key_arti_health, &key_arti_poisonbag, - &key_arti_blastradius, &key_arti_teleport, - &key_arti_teleportother, &key_arti_egg, - &key_arti_invulnerability, - &key_prevweapon, &key_nextweapon, NULL }; - -static int *menu_nav[] = { &key_menu_activate, &key_menu_up, &key_menu_down, - &key_menu_left, &key_menu_right, &key_menu_back, - &key_menu_forward, NULL }; - -static int *shortcuts[] = { &key_menu_help, &key_menu_save, &key_menu_load, - &key_menu_volume, &key_menu_detail, &key_menu_qsave, - &key_menu_endgame, &key_menu_messages, &key_spy, - &key_menu_qload, &key_menu_quit, &key_menu_gamma, - &key_menu_incscreen, &key_menu_decscreen, - &key_menu_screenshot, - &key_message_refresh, &key_multi_msg, - &key_multi_msgplayer[0], &key_multi_msgplayer[1], - &key_multi_msgplayer[2], &key_multi_msgplayer[3], NULL }; - -static int *map_keys[] = { &key_map_north, &key_map_south, &key_map_east, - &key_map_west, &key_map_zoomin, &key_map_zoomout, - &key_map_toggle, &key_map_maxzoom, &key_map_follow, - &key_map_grid, &key_map_mark, &key_map_clearmark, - NULL }; - -static void UpdateJoybSpeed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(var)) -{ - if (always_run) - { - /* - if you want to pick one for chocolate doom to use, - pick 29, since that is the most universal one that - also works with heretic, hexen and strife =P - - NB. This choice also works with original, ultimate and final exes. - */ - - joybspeed = 29; - } - else - { - joybspeed = 2; - } -} - -static int VarInGroup(int *variable, int **group) -{ - unsigned int i; - - for (i=0; group[i] != NULL; ++i) - { - if (group[i] == variable) - { - return 1; - } - } - - return 0; -} - -static void CheckKeyGroup(int *variable, int **group) -{ - unsigned int i; - - // Don't check unless the variable is in this group. - - if (!VarInGroup(variable, group)) - { - return; - } - - // If another variable has the same value as the new value, reset it. - - for (i=0; group[i] != NULL; ++i) - { - if (*variable == *group[i] && group[i] != variable) - { - // A different key has the same value. Clear the existing - // value. This ensures that no two keys can have the same - // value. - - *group[i] = 0; - } - } -} - -// Callback invoked when a key control is set - -static void KeySetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) -{ - TXT_CAST_ARG(int, variable); - - CheckKeyGroup(variable, controls); - CheckKeyGroup(variable, menu_nav); - CheckKeyGroup(variable, shortcuts); - CheckKeyGroup(variable, map_keys); -} - -// Add a label and keyboard input to the specified table. - -static void AddKeyControl(TXT_UNCAST_ARG(table), const char *name, int *var) -{ - TXT_CAST_ARG(txt_table_t, table); - txt_key_input_t *key_input; - - TXT_AddWidget(table, TXT_NewLabel(name)); - key_input = TXT_NewKeyInput(var); - TXT_AddWidget(table, key_input); - - TXT_SignalConnect(key_input, "set", KeySetCallback, var); -} - -static void AddSectionLabel(TXT_UNCAST_ARG(table), const char *title, - boolean add_space) -{ - TXT_CAST_ARG(txt_table_t, table); - char buf[64]; - - if (add_space) - { - TXT_AddWidgets(table, - TXT_NewStrut(0, 1), - TXT_TABLE_EOL, - NULL); - } - - M_snprintf(buf, sizeof(buf), " - %s - ", title); - - TXT_AddWidgets(table, - TXT_NewLabel(buf), - TXT_TABLE_EOL, - NULL); -} -static void ConfigExtraKeys(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - txt_window_t *window; - txt_scrollpane_t *scrollpane; - txt_table_t *table; - boolean extra_keys = gamemission == heretic - || gamemission == hexen - || gamemission == strife; - - window = TXT_NewWindow("Extra keyboard controls"); - - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - table = TXT_NewTable(2); - - TXT_SetColumnWidths(table, 21, 9); - - if (extra_keys) - { - // When we have extra controls, a scrollable pane must be used. - - scrollpane = TXT_NewScrollPane(0, 13, table); - TXT_AddWidget(window, scrollpane); - - AddSectionLabel(table, "View", false); - - AddKeyControl(table, "Look up", &key_lookup); - AddKeyControl(table, "Look down", &key_lookdown); - AddKeyControl(table, "Center view", &key_lookcenter); - - if (gamemission == heretic || gamemission == hexen) - { - AddSectionLabel(table, "Flying", true); - - AddKeyControl(table, "Fly up", &key_flyup); - AddKeyControl(table, "Fly down", &key_flydown); - AddKeyControl(table, "Fly center", &key_flycenter); - } - - AddSectionLabel(table, "Inventory", true); - - AddKeyControl(table, "Inventory left", &key_invleft); - AddKeyControl(table, "Inventory right", &key_invright); - - if (gamemission == strife) - { - AddKeyControl(table, "Home", &key_invhome); - AddKeyControl(table, "End", &key_invend); - AddKeyControl(table, "Query", &key_invquery); - AddKeyControl(table, "Drop", &key_invdrop); - AddKeyControl(table, "Show weapons", &key_invpop); - AddKeyControl(table, "Show mission", &key_mission); - AddKeyControl(table, "Show keys", &key_invkey); - AddKeyControl(table, "Use", &key_invuse); - AddKeyControl(table, "Use health", &key_usehealth); - } - else - { - AddKeyControl(table, "Use artifact", &key_useartifact); - } - - if (gamemission == heretic) - { - AddSectionLabel(table, "Artifacts", true); - - AddKeyControl(table, "Quartz Flask", &key_arti_quartz); - AddKeyControl(table, "Mystic Urn", &key_arti_urn); - AddKeyControl(table, "Timebomb", &key_arti_bomb); - AddKeyControl(table, "Tome of Power", &key_arti_tome); - AddKeyControl(table, "Ring of Invincibility ", &key_arti_ring); - AddKeyControl(table, "Chaos Device", &key_arti_chaosdevice); - AddKeyControl(table, "Shadowsphere", &key_arti_shadowsphere); - AddKeyControl(table, "Wings of Wrath", &key_arti_wings); - AddKeyControl(table, "Torch", &key_arti_torch); - AddKeyControl(table, "Morph Ovum", &key_arti_morph); - } - - if (gamemission == hexen) - { - AddSectionLabel(table, "Artifacts", true); - - AddKeyControl(table, "One of each", &key_arti_all); - AddKeyControl(table, "Quartz Flask", &key_arti_health); - AddKeyControl(table, "Flechette", &key_arti_poisonbag); - AddKeyControl(table, "Disc of Repulsion", &key_arti_blastradius); - AddKeyControl(table, "Chaos Device", &key_arti_teleport); - AddKeyControl(table, "Banishment Device", &key_arti_teleportother); - AddKeyControl(table, "Porkalator", &key_arti_egg); - AddKeyControl(table, "Icon of the Defender", - &key_arti_invulnerability); - } - } - else - { - TXT_AddWidget(window, table); - } - - AddSectionLabel(table, "Weapons", extra_keys); - - AddKeyControl(table, "Weapon 1", &key_weapon1); - AddKeyControl(table, "Weapon 2", &key_weapon2); - AddKeyControl(table, "Weapon 3", &key_weapon3); - AddKeyControl(table, "Weapon 4", &key_weapon4); - AddKeyControl(table, "Weapon 5", &key_weapon5); - AddKeyControl(table, "Weapon 6", &key_weapon6); - AddKeyControl(table, "Weapon 7", &key_weapon7); - AddKeyControl(table, "Weapon 8", &key_weapon8); - AddKeyControl(table, "Previous weapon", &key_prevweapon); - AddKeyControl(table, "Next weapon", &key_nextweapon); -} - -static void OtherKeysDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - txt_window_t *window; - txt_table_t *table; - txt_scrollpane_t *scrollpane; - - window = TXT_NewWindow("Other keys"); - - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - table = TXT_NewTable(2); - - TXT_SetColumnWidths(table, 25, 9); - - AddSectionLabel(table, "Menu navigation", false); - - AddKeyControl(table, "Activate menu", &key_menu_activate); - AddKeyControl(table, "Move cursor up", &key_menu_up); - AddKeyControl(table, "Move cursor down", &key_menu_down); - AddKeyControl(table, "Move slider left", &key_menu_left); - AddKeyControl(table, "Move slider right", &key_menu_right); - AddKeyControl(table, "Go to previous menu", &key_menu_back); - AddKeyControl(table, "Activate menu item", &key_menu_forward); - AddKeyControl(table, "Confirm action", &key_menu_confirm); - AddKeyControl(table, "Cancel action", &key_menu_abort); - - AddSectionLabel(table, "Shortcut keys", true); - - AddKeyControl(table, "Pause game", &key_pause); - AddKeyControl(table, "Help screen", &key_menu_help); - AddKeyControl(table, "Save game", &key_menu_save); - AddKeyControl(table, "Load game", &key_menu_load); - AddKeyControl(table, "Sound volume", &key_menu_volume); - AddKeyControl(table, "Toggle detail", &key_menu_detail); - AddKeyControl(table, "Quick save", &key_menu_qsave); - AddKeyControl(table, "End game", &key_menu_endgame); - AddKeyControl(table, "Toggle messages", &key_menu_messages); - AddKeyControl(table, "Quick load", &key_menu_qload); - AddKeyControl(table, "Quit game", &key_menu_quit); - AddKeyControl(table, "Toggle gamma", &key_menu_gamma); - AddKeyControl(table, "Multiplayer spy", &key_spy); - - AddKeyControl(table, "Increase screen size", &key_menu_incscreen); - AddKeyControl(table, "Decrease screen size", &key_menu_decscreen); - AddKeyControl(table, "Save a screenshot", &key_menu_screenshot); - - AddKeyControl(table, "Display last message", &key_message_refresh); - AddKeyControl(table, "Finish recording demo", &key_demo_quit); - - AddSectionLabel(table, "Map", true); - AddKeyControl(table, "Toggle map", &key_map_toggle); - AddKeyControl(table, "Zoom in", &key_map_zoomin); - AddKeyControl(table, "Zoom out", &key_map_zoomout); - AddKeyControl(table, "Maximum zoom out", &key_map_maxzoom); - AddKeyControl(table, "Follow mode", &key_map_follow); - AddKeyControl(table, "Pan north", &key_map_north); - AddKeyControl(table, "Pan south", &key_map_south); - AddKeyControl(table, "Pan east", &key_map_east); - AddKeyControl(table, "Pan west", &key_map_west); - AddKeyControl(table, "Toggle grid", &key_map_grid); - AddKeyControl(table, "Mark location", &key_map_mark); - AddKeyControl(table, "Clear all marks", &key_map_clearmark); - - AddSectionLabel(table, "Multiplayer", true); - - AddKeyControl(table, "Send message", &key_multi_msg); - AddKeyControl(table, "- to player 1", &key_multi_msgplayer[0]); - AddKeyControl(table, "- to player 2", &key_multi_msgplayer[1]); - AddKeyControl(table, "- to player 3", &key_multi_msgplayer[2]); - AddKeyControl(table, "- to player 4", &key_multi_msgplayer[3]); - - if (gamemission == hexen || gamemission == strife) - { - AddKeyControl(table, "- to player 5", &key_multi_msgplayer[4]); - AddKeyControl(table, "- to player 6", &key_multi_msgplayer[5]); - AddKeyControl(table, "- to player 7", &key_multi_msgplayer[6]); - AddKeyControl(table, "- to player 8", &key_multi_msgplayer[7]); - } - - scrollpane = TXT_NewScrollPane(0, 13, table); - - TXT_AddWidget(window, scrollpane); -} - -void ConfigKeyboard(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - txt_checkbox_t *run_control; - - always_run = joybspeed >= 20; - - window = TXT_NewWindow("Keyboard configuration"); - - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - // The window is on a 5-column grid layout that looks like: - // Label | Control | | Label | Control - // There is a small gap between the two conceptual "columns" of - // controls, just for spacing. - TXT_SetTableColumns(window, 5); - TXT_SetColumnWidths(window, 15, 8, 2, 15, 8); - - TXT_AddWidget(window, TXT_NewSeparator("Movement")); - AddKeyControl(window, "Move Forward", &key_up); - TXT_AddWidget(window, TXT_TABLE_EMPTY); - AddKeyControl(window, "Strafe Left", &key_strafeleft); - - AddKeyControl(window, "Move Backward", &key_down); - TXT_AddWidget(window, TXT_TABLE_EMPTY); - AddKeyControl(window, "Strafe Right", &key_straferight); - - AddKeyControl(window, "Turn Left", &key_left); - TXT_AddWidget(window, TXT_TABLE_EMPTY); - AddKeyControl(window, "Run", &key_speed); - - AddKeyControl(window, "Turn Right", &key_right); - TXT_AddWidget(window, TXT_TABLE_EMPTY); - AddKeyControl(window, "Strafe On", &key_strafe); - - if (gamemission == hexen || gamemission == strife) - { - AddKeyControl(window, "Jump", &key_jump); - } - - TXT_AddWidget(window, TXT_NewSeparator("Action")); - AddKeyControl(window, "Fire/Attack", &key_fire); - TXT_AddWidget(window, TXT_TABLE_EMPTY); - AddKeyControl(window, "Use", &key_use); - - TXT_AddWidgets(window, - TXT_NewButton2("More controls...", ConfigExtraKeys, NULL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_TABLE_EMPTY, - TXT_NewButton2("Other keys...", OtherKeysDialog, NULL), - TXT_TABLE_OVERFLOW_RIGHT, - - TXT_NewSeparator("Misc."), - run_control = TXT_NewCheckBox("Always run", &always_run), - TXT_TABLE_EOL, - TXT_NewInvertedCheckBox("Use native keyboard mapping", - &vanilla_keyboard_mapping), - TXT_TABLE_EOL, - NULL); - - TXT_SignalConnect(run_control, "changed", UpdateJoybSpeed, NULL); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); -} - -void BindKeyboardVariables(void) -{ - M_BindIntVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); -} diff --git a/games/NXDoom/src/setup/keyboard.h b/games/NXDoom/src/setup/keyboard.h deleted file mode 100644 index 81b8b91a26c..00000000000 --- a/games/NXDoom/src/setup/keyboard.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_KEYBOARD_H -#define SETUP_KEYBOARD_H - -void ConfigKeyboard(void *widget, void *user_data); -void BindKeyboardVariables(void); - -extern int vanilla_keyboard_mapping; - -#endif /* #ifndef SETUP_KEYBOARD_H */ diff --git a/games/NXDoom/src/setup/mainmenu.c b/games/NXDoom/src/setup/mainmenu.c deleted file mode 100644 index 94b765f3796..00000000000 --- a/games/NXDoom/src/setup/mainmenu.c +++ /dev/null @@ -1,346 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include -#include - -#include "config.h" -#include "textscreen.h" - -#include "execute.h" - -#include "m_argv.h" -#include "m_config.h" -#include "m_controls.h" -#include "m_misc.h" -#include "z_zone.h" - -#include "setup_icon.c" -#include "mode.h" - -#include "compatibility.h" -#include "display.h" -#include "joystick.h" -#include "keyboard.h" -#include "mouse.h" -#include "multiplayer.h" -#include "sound.h" - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup" - -static const int cheat_sequence[] = -{ - KEY_UPARROW, KEY_UPARROW, KEY_DOWNARROW, KEY_DOWNARROW, - KEY_LEFTARROW, KEY_RIGHTARROW, KEY_LEFTARROW, KEY_RIGHTARROW, - 'b', 'a', KEY_ENTER, 0 -}; - -static unsigned int cheat_sequence_index = 0; - -// I think these are good "sensible" defaults: - -static void SensibleDefaults(void) -{ - key_up = 'w'; - key_down = 's'; - key_strafeleft = 'a'; - key_straferight = 'd'; - key_jump = '/'; - key_lookup = KEY_PGUP; - key_lookdown = KEY_PGDN; - key_lookcenter = KEY_HOME; - key_flyup = KEY_INS; - key_flydown = KEY_DEL; - key_flycenter = KEY_END; - key_prevweapon = ','; - key_nextweapon = '.'; - key_invleft = '['; - key_invright = ']'; - key_message_refresh = '\''; - key_mission = 'i'; // Strife keys - key_invpop = 'o'; - key_invkey = 'p'; - key_multi_msgplayer[0] = 'g'; - key_multi_msgplayer[1] = 'h'; - key_multi_msgplayer[2] = 'j'; - key_multi_msgplayer[3] = 'k'; - key_multi_msgplayer[4] = 'v'; - key_multi_msgplayer[5] = 'b'; - key_multi_msgplayer[6] = 'n'; - key_multi_msgplayer[7] = 'm'; - mousebprevweapon = 4; // Scroll wheel = weapon cycle - mousebnextweapon = 3; - snd_musicdevice = 3; - joybspeed = 29; // Always run - vanilla_savegame_limit = 0; - vanilla_keyboard_mapping = 0; - vanilla_demo_limit = 0; - graphical_startup = 0; - show_endoom = 0; - dclick_use = 0; - novert = 1; - snd_dmxoption = "-opl3 -reverse"; - png_screenshots = 1; -} - -static int MainMenuKeyPress(txt_window_t *window, int key, void *user_data) -{ - if (key == cheat_sequence[cheat_sequence_index]) - { - ++cheat_sequence_index; - - if (cheat_sequence[cheat_sequence_index] == 0) - { - SensibleDefaults(); - cheat_sequence_index = 0; - - window = TXT_MessageBox(NULL, " \x01 "); - - return 1; - } - } - else - { - cheat_sequence_index = 0; - } - - return 0; -} - -static void DoQuit(void *widget, void *dosave) -{ - if (dosave != NULL) - { - M_SaveDefaults(); - } - - TXT_Shutdown(); - - exit(0); -} - -static void QuitConfirm(void *unused1, void *unused2) -{ - txt_window_t *window; - txt_label_t *label; - txt_button_t *yes_button; - txt_button_t *no_button; - - window = TXT_NewWindow(NULL); - - TXT_AddWidgets(window, - label = TXT_NewLabel("Exiting setup.\nSave settings?"), - TXT_NewStrut(24, 0), - yes_button = TXT_NewButton2(" Yes ", DoQuit, DoQuit), - no_button = TXT_NewButton2(" No ", DoQuit, NULL), - NULL); - - TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); - TXT_SetWidgetAlign(yes_button, TXT_HORIZ_CENTER); - TXT_SetWidgetAlign(no_button, TXT_HORIZ_CENTER); - - // Only an "abort" button in the middle. - TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, - TXT_NewWindowAbortAction(window)); - TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); -} - -static void LaunchDoom(void *unused1, void *unused2) -{ - execute_context_t *exec; - - // Save configuration first - - M_SaveDefaults(); - - // Shut down textscreen GUI - - TXT_Shutdown(); - - // Launch Doom - - exec = NewExecuteContext(); - PassThroughArguments(exec); - ExecuteDoom(exec); - - exit(0); -} - -static txt_button_t *GetLaunchButton(void) -{ - const char *label; - - switch (gamemission) - { - case doom: - label = "Save parameters and launch DOOM"; - break; - case heretic: - label = "Save parameters and launch Heretic"; - break; - case hexen: - label = "Save parameters and launch Hexen"; - break; - case strife: - label = "Save parameters and launch STRIFE!"; - break; - default: - label = "Save parameters and launch game"; - break; - } - - return TXT_NewButton2(label, LaunchDoom, NULL); -} - -void MainMenu(void) -{ - txt_window_t *window; - txt_window_action_t *quit_action; - txt_window_action_t *warp_action; - - window = TXT_NewWindow("Main Menu"); - - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - TXT_AddWidgets(window, - TXT_NewButton2("Configure Display", - (TxtWidgetSignalFunc) ConfigDisplay, NULL), - TXT_NewButton2("Configure Sound", - (TxtWidgetSignalFunc) ConfigSound, NULL), - TXT_NewButton2("Configure Keyboard", - (TxtWidgetSignalFunc) ConfigKeyboard, NULL), - TXT_NewButton2("Configure Mouse", - (TxtWidgetSignalFunc) ConfigMouse, NULL), - TXT_NewButton2("Configure Gamepad/Joystick", - (TxtWidgetSignalFunc) ConfigJoystick, NULL), - TXT_NewButton2("Compatibility", - (TxtWidgetSignalFunc) CompatibilitySettings, NULL), - GetLaunchButton(), - TXT_NewStrut(0, 1), - TXT_NewButton2("Start a Network Game", - (TxtWidgetSignalFunc) StartMultiGame, NULL), - TXT_NewButton2("Join a Network Game", - (TxtWidgetSignalFunc) JoinMultiGame, NULL), - TXT_NewButton2("Multiplayer Configuration", - (TxtWidgetSignalFunc) MultiplayerConfig, NULL), - NULL); - - quit_action = TXT_NewWindowAction(KEY_ESCAPE, "Quit"); - warp_action = TXT_NewWindowAction(KEY_F2, "Warp"); - TXT_SignalConnect(quit_action, "pressed", QuitConfirm, NULL); - TXT_SignalConnect(warp_action, "pressed", - (TxtWidgetSignalFunc) WarpMenu, NULL); - TXT_SetWindowAction(window, TXT_HORIZ_LEFT, quit_action); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, warp_action); - - TXT_SetKeyListener(window, MainMenuKeyPress, NULL); -} - -// -// Initialize all configuration variables, load config file, etc -// - -static void InitConfig(void) -{ - M_SetConfigDir(NULL); - InitBindings(); - - SetChatMacroDefaults(); - SetPlayerNameDefault(); - - M_LoadDefaults(); - - // Create and configure the music pack directory if it does not - // already exist. - M_SetMusicPackDir(); -} - -// -// Application icon -// - -static void SetIcon(void) -{ - SDL_Surface *surface; - - surface = SDL_CreateRGBSurfaceFrom((void *) setup_icon_data, setup_icon_w, - setup_icon_h, 32, setup_icon_w * 4, - 0xffu << 24, 0xffu << 16, - 0xffu << 8, 0xffu << 0); - - SDL_SetWindowIcon(TXT_SDLWindow, surface); - SDL_FreeSurface(surface); -} - -static void SetWindowTitle(void) -{ - char *title; - - title = M_StringReplace(PACKAGE_NAME " Setup ver " PACKAGE_VERSION, - "Doom", - GetGameTitle()); - - - TXT_SetDesktopTitle(title); - - free(title); -} - -// Initialize the textscreen library. - -static void InitTextscreen(void) -{ - SetDisplayDriver(); - - if (!TXT_Init()) - { - fprintf(stderr, "Failed to initialize GUI\n"); - exit(-1); - } - - // Set Romero's "funky blue" color: - // - TXT_SetColor(TXT_COLOR_BLUE, 0x04, 0x14, 0x40); - - SetIcon(); - SetWindowTitle(); -} - - -// -// Initialize and run the textscreen GUI. -// - -static void RunGUI(void) -{ - InitTextscreen(); - - TXT_GUIMainLoop(); -} - -static void MissionSet(void) -{ - SetWindowTitle(); - InitConfig(); - MainMenu(); -} - -void D_DoomMain(void) -{ - SetupMission(MissionSet); - - RunGUI(); -} diff --git a/games/NXDoom/src/setup/mode.c b/games/NXDoom/src/setup/mode.c deleted file mode 100644 index 0f604094315..00000000000 --- a/games/NXDoom/src/setup/mode.c +++ /dev/null @@ -1,384 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include - -#include "doomtype.h" - -#include "config.h" -#include "textscreen.h" - -#include "doomtype.h" -#include "d_mode.h" -#include "d_iwad.h" -#include "i_system.h" -#include "m_argv.h" -#include "m_config.h" -#include "m_controls.h" -#include "m_misc.h" - -#include "compatibility.h" -#include "display.h" -#include "joystick.h" -#include "keyboard.h" -#include "mouse.h" -#include "multiplayer.h" -#include "sound.h" - -#include "mode.h" - -GameMission_t gamemission; -static const iwad_t **iwads; - -typedef struct -{ - const char *label; - GameMission_t mission; - int mask; - const char *name; - const char *config_file; - const char *extra_config_file; - const char *executable; -} mission_config_t; - -// Default mission to fall back on, if no IWADs are found at all: - -#define DEFAULT_MISSION (&mission_configs[0]) - -static mission_config_t mission_configs[] = -{ - { - "Doom", - doom, - IWAD_MASK_DOOM, - "doom", - "default.cfg", - PROGRAM_PREFIX "doom.cfg", - PROGRAM_PREFIX "doom" - }, - { - "Heretic", - heretic, - IWAD_MASK_HERETIC, - "heretic", - "heretic.cfg", - PROGRAM_PREFIX "heretic.cfg", - PROGRAM_PREFIX "heretic" - }, - { - "Hexen", - hexen, - IWAD_MASK_HEXEN, - "hexen", - "hexen.cfg", - PROGRAM_PREFIX "hexen.cfg", - PROGRAM_PREFIX "hexen" - }, - { - "Strife", - strife, - IWAD_MASK_STRIFE, - "strife", - "strife.cfg", - PROGRAM_PREFIX "strife.cfg", - PROGRAM_PREFIX "strife" - } -}; - -static GameSelectCallback game_selected_callback; - -// Miscellaneous variables that aren't used in setup. - -static int showMessages = 1; -static int screenblocks = 9; -static int detailLevel = 0; -static char *savedir = NULL; -static char *executable = NULL; -static const char *game_title = "Doom"; -static char *back_flat = "F_PAVE01"; -static int comport = 0; -static char *nickname = NULL; - -static void BindMiscVariables(void) -{ - if (gamemission == doom) - { - M_BindIntVariable("detaillevel", &detailLevel); - M_BindIntVariable("show_messages", &showMessages); - } - - if (gamemission == hexen) - { - M_BindStringVariable("savedir", &savedir); - M_BindIntVariable("messageson", &showMessages); - - // Hexen has a variable to control the savegame directory - // that is used. - - savedir = M_GetSaveGameDir("hexen.wad"); - - // On Windows, hexndata\ is the default. - - if (!strcmp(savedir, "")) - { - free(savedir); - savedir = "hexndata" DIR_SEPARATOR_S; - } - } - - if (gamemission == strife) - { - // Strife has a different default value than the other games - screenblocks = 10; - - M_BindStringVariable("back_flat", &back_flat); - M_BindStringVariable("nickname", &nickname); - - M_BindIntVariable("screensize", &screenblocks); - M_BindIntVariable("comport", &comport); - } - else - { - M_BindIntVariable("screenblocks", &screenblocks); - } - -} - -// -// Initialise all configuration file bindings. -// - -void InitBindings(void) -{ - M_ApplyPlatformDefaults(); - - // Keyboard, mouse, joystick controls - - M_BindBaseControls(); - M_BindWeaponControls(); - M_BindMapControls(); - M_BindMenuControls(); - - if (gamemission == heretic || gamemission == hexen) - { - M_BindHereticControls(); - } - - if (gamemission == hexen) - { - M_BindHexenControls(); - } - - if (gamemission == strife) - { - M_BindStrifeControls(); - } - - // All other variables - - BindCompatibilityVariables(); - BindDisplayVariables(); - BindJoystickVariables(); - BindKeyboardVariables(); - BindMouseVariables(); - BindSoundVariables(); - BindMiscVariables(); - BindMultiplayerVariables(); -} - -// Set the name of the executable program to run the game: - -static void SetExecutable(mission_config_t *config) -{ - char *extension; - - free(executable); - -#ifdef _WIN32 - extension = ".exe"; -#else - extension = ""; -#endif - - executable = M_StringJoin(config->executable, extension, NULL); -} - -static void SetMission(mission_config_t *config) -{ - iwads = D_FindAllIWADs(config->mask); - gamemission = config->mission; - SetExecutable(config); - game_title = config->label; - M_SetConfigFilenames(config->config_file, config->extra_config_file); -} - -static mission_config_t *GetMissionForName(const char *name) -{ - int i; - - for (i=0; iname) != NULL) - { - SetMission(config); - callback(); - return true; - } - } - - return false; -} - -static void GameSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(config)) -{ - TXT_CAST_ARG(mission_config_t, config); - - SetMission(config); - game_selected_callback(); -} - -static void OpenGameSelectDialog(GameSelectCallback callback) -{ - mission_config_t *mission = NULL; - txt_window_t *window; - const iwad_t **iwads; - int num_games; - int i; - - window = TXT_NewWindow("Select game"); - - TXT_AddWidget(window, TXT_NewLabel("Select a game to configure:\n")); - num_games = 0; - - // Add a button for each game. - - for (i=0; i - // - // Specify the game to configure the settings for. Valid - // values are 'doom', 'heretic', 'hexen' and 'strife'. - // - - p = M_CheckParm("-game"); - - if (p > 0) - { - mission_name = myargv[p + 1]; - - config = GetMissionForName(mission_name); - - if (config == NULL) - { - I_Error("Invalid parameter - '%s'", mission_name); - } - - SetMission(config); - callback(); - } - else if (!CheckExecutableName(callback)) - { - OpenGameSelectDialog(callback); - } -} - -const char *GetExecutableName(void) -{ - return executable; -} - -const char *GetGameTitle(void) -{ - return game_title; -} - -const iwad_t **GetIwads(void) -{ - return iwads; -} - diff --git a/games/NXDoom/src/setup/mode.h b/games/NXDoom/src/setup/mode.h deleted file mode 100644 index 2687a4889aa..00000000000 --- a/games/NXDoom/src/setup/mode.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_MODE_H -#define SETUP_MODE_H - -#include "d_mode.h" -#include "d_iwad.h" - -typedef void (*GameSelectCallback)(void); -extern GameMission_t gamemission; - -void SetupMission(GameSelectCallback callback); -void InitBindings(void); -const char *GetExecutableName(void); -const char *GetGameTitle(void); -const iwad_t **GetIwads(void); - -#endif /* #ifndef SETUP_MODE_H */ - diff --git a/games/NXDoom/src/setup/mouse.c b/games/NXDoom/src/setup/mouse.c deleted file mode 100644 index 95a83320928..00000000000 --- a/games/NXDoom/src/setup/mouse.c +++ /dev/null @@ -1,176 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include - -#include "textscreen.h" -#include "doomtype.h" -#include "m_config.h" -#include "m_controls.h" - -#include "execute.h" -#include "txt_mouseinput.h" - -#include "mode.h" -#include "mouse.h" - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-mouse" - -static int usemouse = 1; - -static int mouseSensitivity = 5; -static float mouse_acceleration = 2.0; -static int mouse_threshold = 10; -static int grabmouse = 1; - -int novert = 0; - -static int *all_mouse_buttons[] = { - &mousebfire, - &mousebstrafe, - &mousebforward, - &mousebstrafeleft, - &mousebstraferight, - &mousebbackward, - &mousebuse, - &mousebjump, - &mousebprevweapon, - &mousebnextweapon, - &mousebspeed, - &mousebinvleft, - &mousebinvright, - &mousebuseartifact, - &mousebturnleft, - &mousebturnright, -}; - -static void MouseSetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) -{ - TXT_CAST_ARG(int, variable); - unsigned int i; - - // Check if the same mouse button is used for a different action - // If so, set the other action(s) to -1 (unset) - - for (i=0; i -#include -#include - -#include "doomtype.h" - -#include "textscreen.h" - -#include "d_iwad.h" -#include "m_config.h" -#include "m_misc.h" -#include "doom/d_englsh.h" -#include "m_controls.h" - -#include "multiplayer.h" -#include "mode.h" -#include "execute.h" - -#include "net_io.h" -#include "net_query.h" - -#include "net_petname.h" - -#define MULTI_START_HELP_URL "https://www.chocolate-doom.org/setup-multi-start" -#define MULTI_JOIN_HELP_URL "https://www.chocolate-doom.org/setup-multi-join" -#define MULTI_CONFIG_HELP_URL "https://www.chocolate-doom.org/setup-multi-config" -#define LEVEL_WARP_HELP_URL "https://www.chocolate-doom.org/setup-level-warp" - -#define NUM_WADS 10 -#define NUM_EXTRA_PARAMS 10 - -typedef enum -{ - WARP_ExMy, - WARP_MAPxy, -} warptype_t; - -// Fallback IWADs to use if no IWADs are detected. - -static const iwad_t fallback_iwads[] = { - { "doom.wad", doom, registered, "Doom" }, - { "heretic.wad", heretic, retail, "Heretic" }, - { "hexen.wad", hexen, commercial, "Hexen" }, - { "strife1.wad", strife, commercial, "Strife" }, -}; - -// Array of IWADs found to be installed - -static const iwad_t **found_iwads; -static const char **iwad_labels; - -// Index of the currently selected IWAD - -static int found_iwad_selected = -1; - -// Filename to pass to '-iwad'. - -static const char *iwadfile; - -static const char *wad_extensions[] = { "wad", "lmp", "deh", NULL }; - -static const char *doom_skills[] = -{ - "I'm too young to die.", "Hey, not too rough.", "Hurt me plenty.", - "Ultra-Violence.", "NIGHTMARE!", -}; - -static const char *chex_skills[] = -{ - "Easy does it", "Not so sticky", "Gobs of goo", "Extreme ooze", - "SUPER SLIMEY!" -}; - -static const char *heretic_skills[] = -{ - "Thou needeth a wet-nurse", "Yellowbellies-R-us", "Bringest them oneth", - "Thou art a smite-meister", "Black plague possesses thee" -}; - -static const char *hexen_fighter_skills[] = -{ - "Squire", "Knight", "Warrior", "Berserker", "Titan" -}; - -static const char *hexen_cleric_skills[] = -{ - "Altar boy", "Acolyte", "Priest", "Cardinal", "Pope" -}; - -static const char *hexen_mage_skills[] = -{ - "Apprentice", "Enchanter", "Sorceror", "Warlock", "Archimage" -}; - -static const char *strife_skills[] = -{ - "Training", "Rookie", "Veteran", "Elite", "Bloodbath" -}; - -static const char *character_classes[] = { "Fighter", "Cleric", "Mage" }; - -static const char *gamemodes[] = { "Co-operative", "Deathmatch", "Deathmatch 2.0" }; - -static const char *strife_gamemodes[] = -{ - "Normal deathmatch", - "Items respawn", // (altdeath) -}; - -static char *net_player_name; -static char *chat_macros[10]; - -static char *wads[NUM_WADS]; -static char *extra_params[NUM_EXTRA_PARAMS]; -static int character_class = 0; -static int skill = 2; -static int nomonsters = 0; -static int deathmatch = 0; -static int strife_altdeath = 0; -static int fast = 0; -static int respawn = 0; -static int udpport = 2342; -static int timer = 0; -static int privateserver = 0; - -static txt_dropdown_list_t *skillbutton; -static txt_button_t *warpbutton; -static warptype_t warptype = WARP_MAPxy; -static int warpepisode = 1; -static int warpmap = 1; - -// Address to connect to when joining a game - -static char *connect_address = NULL; - -static txt_window_t *query_window; -static int query_servers_found; - -// Find an IWAD from its description - -static const iwad_t *GetCurrentIWAD(void) -{ - return found_iwads[found_iwad_selected]; -} - -// Is the currently selected IWAD the Chex Quest chex.wad? - -static boolean IsChexQuest(const iwad_t *iwad) -{ - return !strcmp(iwad->name, "chex.wad"); -} - -static void AddWADs(execute_context_t *exec) -{ - int have_wads = 0; - int i; - - for (i=0; i 0) - { - if (!have_wads) - { - AddCmdLineParameter(exec, "-merge"); - have_wads = 1; - } - - AddCmdLineParameter(exec, "\"%s\"", wads[i]); - } - } -} - -static void AddExtraParameters(execute_context_t *exec) -{ - int i; - - for (i=0; i 0) - { - AddCmdLineParameter(exec, "%s", extra_params[i]); - } - } -} - -static void AddIWADParameter(execute_context_t *exec) -{ - if (iwadfile != NULL) - { - AddCmdLineParameter(exec, "-iwad %s", iwadfile); - } -} - -// Callback function invoked to launch the game. -// This is used when starting a server and also when starting a -// single player game via the "warp" menu. - -static void StartGame(int multiplayer) -{ - execute_context_t *exec; - - exec = NewExecuteContext(); - - // Extra parameters come first, before all others; this way, - // they can override any of the options set in the dialog. - - AddExtraParameters(exec); - - AddIWADParameter(exec); - AddCmdLineParameter(exec, "-skill %i", skill + 1); - - if (gamemission == hexen) - { - AddCmdLineParameter(exec, "-class %i", character_class); - } - - if (nomonsters) - { - AddCmdLineParameter(exec, "-nomonsters"); - } - - if (fast) - { - AddCmdLineParameter(exec, "-fast"); - } - - if (respawn) - { - AddCmdLineParameter(exec, "-respawn"); - } - - if (warptype == WARP_ExMy) - { - // TODO: select IWAD based on warp type - AddCmdLineParameter(exec, "-warp %i %i", warpepisode, warpmap); - } - else if (warptype == WARP_MAPxy) - { - AddCmdLineParameter(exec, "-warp %i", warpmap); - } - - // Multiplayer-specific options: - - if (multiplayer) - { - AddCmdLineParameter(exec, "-server"); - AddCmdLineParameter(exec, "-port %i", udpport); - - if (deathmatch == 1) - { - AddCmdLineParameter(exec, "-deathmatch"); - } - else if (deathmatch == 2 || strife_altdeath != 0) - { - AddCmdLineParameter(exec, "-altdeath"); - } - - if (timer > 0) - { - AddCmdLineParameter(exec, "-timer %i", timer); - } - - if (privateserver) - { - AddCmdLineParameter(exec, "-privateserver"); - } - } - - AddWADs(exec); - - TXT_Shutdown(); - - M_SaveDefaults(); - PassThroughArguments(exec); - - ExecuteDoom(exec); - - exit(0); -} - -static void StartServerGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - StartGame(1); -} - -static void StartSinglePlayerGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - StartGame(0); -} - -static void UpdateWarpButton(void) -{ - char buf[10]; - - if (warptype == WARP_ExMy) - { - M_snprintf(buf, sizeof(buf), "E%iM%i", warpepisode, warpmap); - } - else if (warptype == WARP_MAPxy) - { - M_snprintf(buf, sizeof(buf), "MAP%02i", warpmap); - } - - TXT_SetButtonLabel(warpbutton, buf); -} - -static void UpdateSkillButton(void) -{ - const iwad_t *iwad = GetCurrentIWAD(); - - if (IsChexQuest(iwad)) - { - skillbutton->values = chex_skills; - } - else switch(gamemission) - { - default: - case doom: - skillbutton->values = doom_skills; - break; - - case heretic: - skillbutton->values = heretic_skills; - break; - - case hexen: - if (character_class == 0) - { - skillbutton->values = hexen_fighter_skills; - } - else if (character_class == 1) - { - skillbutton->values = hexen_cleric_skills; - } - else - { - skillbutton->values = hexen_mage_skills; - } - break; - - case strife: - skillbutton->values = strife_skills; - break; - } -} - -static void SetExMyWarp(TXT_UNCAST_ARG(widget), void *val) -{ - int l; - - l = (intptr_t) val; - - warpepisode = l / 10; - warpmap = l % 10; - - UpdateWarpButton(); -} - -static void SetMAPxyWarp(TXT_UNCAST_ARG(widget), void *val) -{ - int l; - - l = (intptr_t) val; - - warpmap = l; - - UpdateWarpButton(); -} - -static void CloseLevelSelectDialog(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(window)) -{ - TXT_CAST_ARG(txt_window_t, window); - - TXT_CloseWindow(window); -} - -static void LevelSelectDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) -{ - txt_window_t *window; - txt_button_t *button; - const iwad_t *iwad; - char buf[10]; - int episodes; - int x, y; - int l; - int i; - - window = TXT_NewWindow("Select level"); - iwad = GetCurrentIWAD(); - - if (warptype == WARP_ExMy) - { - episodes = D_GetNumEpisodes(iwad->mission, iwad->mode); - TXT_SetTableColumns(window, episodes); - - // ExMy levels - - for (y=1; y<10; ++y) - { - for (x=1; x<=episodes; ++x) - { - if (IsChexQuest(iwad) && (x > 1 || y > 5)) - { - continue; - } - - if (!D_ValidEpisodeMap(iwad->mission, iwad->mode, x, y)) - { - TXT_AddWidget(window, NULL); - continue; - } - - M_snprintf(buf, sizeof(buf), - " E%dM%d ", x, y); - button = TXT_NewButton(buf); - TXT_SignalConnect(button, "pressed", - SetExMyWarp, (void *) (intptr_t) (x * 10 + y)); - TXT_SignalConnect(button, "pressed", - CloseLevelSelectDialog, window); - TXT_AddWidget(window, button); - - if (warpepisode == x && warpmap == y) - { - TXT_SelectWidget(window, button); - } - } - } - } - else - { - TXT_SetTableColumns(window, 6); - - for (i=0; i<60; ++i) - { - x = i % 6; - y = i / 6; - - l = x * 10 + y + 1; - - if (!D_ValidEpisodeMap(iwad->mission, iwad->mode, 1, l)) - { - TXT_AddWidget(window, NULL); - continue; - } - - M_snprintf(buf, sizeof(buf), " MAP%02d ", l); - button = TXT_NewButton(buf); - TXT_SignalConnect(button, "pressed", - SetMAPxyWarp, (void *) (intptr_t) l); - TXT_SignalConnect(button, "pressed", - CloseLevelSelectDialog, window); - TXT_AddWidget(window, button); - - if (warpmap == l) - { - TXT_SelectWidget(window, button); - } - } - } -} - -static void IWADSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - const iwad_t *iwad; - - // Find the iwad_t selected - - iwad = GetCurrentIWAD(); - - // Update iwadfile - - iwadfile = iwad->name; -} - -// Called when the IWAD button is changed, to update warptype. - -static void UpdateWarpType(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - warptype_t new_warptype; - const iwad_t *iwad; - - // Get the selected IWAD - - iwad = GetCurrentIWAD(); - - // Find the new warp type - - if (D_IsEpisodeMap(iwad->mission)) - { - new_warptype = WARP_ExMy; - } - else - { - new_warptype = WARP_MAPxy; - } - - // Reset to E1M1 / MAP01 when the warp type is changed. - - if (new_warptype != warptype) - { - warpepisode = 1; - warpmap = 1; - } - - warptype = new_warptype; - - UpdateWarpButton(); - UpdateSkillButton(); -} - -// Get an IWAD list with a default fallback IWAD that is appropriate -// for the game we are configuring (matches gamemission global variable). - -static const iwad_t **GetFallbackIwadList(void) -{ - static const iwad_t *fallback_iwad_list[2]; - unsigned int i; - - // Default to use if we don't find something better. - - fallback_iwad_list[0] = &fallback_iwads[0]; - fallback_iwad_list[1] = NULL; - - for (i = 0; i < arrlen(fallback_iwads); ++i) - { - if (gamemission == fallback_iwads[i].mission) - { - fallback_iwad_list[0] = &fallback_iwads[i]; - break; - } - } - - return fallback_iwad_list; -} - -static txt_widget_t *IWADSelector(void) -{ - txt_dropdown_list_t *dropdown; - txt_widget_t *result; - int num_iwads; - unsigned int i; - - // Find out what WADs are installed - - found_iwads = GetIwads(); - - // Build a list of the descriptions for all installed IWADs - - num_iwads = 0; - - for (i=0; found_iwads[i] != NULL; ++i) - { - ++num_iwads; - } - - iwad_labels = malloc(sizeof(*iwad_labels) * num_iwads); - - for (i=0; i < num_iwads; ++i) - { - iwad_labels[i] = found_iwads[i]->description; - } - - // If no IWADs are found, provide Doom 2 as an option, but - // we're probably screwed. - - if (num_iwads == 0) - { - found_iwads = GetFallbackIwadList(); - num_iwads = 1; - } - - // Build a dropdown list of IWADs - - if (num_iwads < 2) - { - // We have only one IWAD. Show as a label. - - result = (txt_widget_t *) TXT_NewLabel(found_iwads[0]->description); - } - else - { - // Dropdown list allowing IWAD to be selected. - - dropdown = TXT_NewDropdownList(&found_iwad_selected, - iwad_labels, num_iwads); - - TXT_SignalConnect(dropdown, "changed", IWADSelected, NULL); - - result = (txt_widget_t *) dropdown; - } - - // The first time the dialog is opened, found_iwad_selected=-1, - // so select the first IWAD in the list. Don't lose the setting - // if we close and reopen the dialog. - - if (found_iwad_selected < 0 || found_iwad_selected >= num_iwads) - { - found_iwad_selected = 0; - } - - IWADSelected(NULL, NULL); - - return result; -} - -// Create the window action button to start the game. This invokes -// a different callback depending on whether to start a multiplayer -// or single player game. - -static txt_window_action_t *StartGameAction(int multiplayer) -{ - txt_window_action_t *action; - TxtWidgetSignalFunc callback; - - action = TXT_NewWindowAction(KEY_F10, "Start"); - - if (multiplayer) - { - callback = StartServerGame; - } - else - { - callback = StartSinglePlayerGame; - } - - TXT_SignalConnect(action, "pressed", callback, NULL); - - return action; -} - -static void OpenWadsWindow(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) -{ - txt_window_t *window; - int i; - - window = TXT_NewWindow("Add WADs"); - - for (i=0; iserver_state != 0) - { - TXT_MessageBox("Cannot connect to server", - "Gameplay is already in progress\n" - "on this server."); - return; - } - - // Set address to connect to: - - free(connect_address); - connect_address = M_StringDuplicate(button->label); - - // Auto-choose IWAD if there is already a player connected. - - if (querydata->num_players > 0) - { - for (i = 0; found_iwads[i] != NULL; ++i) - { - if (found_iwads[i]->mode == querydata->gamemode - && found_iwads[i]->mission == querydata->gamemission) - { - found_iwad_selected = i; - iwadfile = found_iwads[i]->name; - break; - } - } - - if (found_iwads[i] == NULL) - { - TXT_MessageBox(NULL, - "The game on this server seems to be:\n" - "\n" - " %s\n" - "\n" - "but the IWAD file %s is not found!\n" - "Without the required IWAD file, it may not be\n" - "possible to join this game.", - D_SuggestGameName(querydata->gamemission, - querydata->gamemode), - D_SuggestIWADName(querydata->gamemission, - querydata->gamemode)); - } - } - - // Finished with search. - - TXT_CloseWindow(query_window); -} - -static void QueryResponseCallback(net_addr_t *addr, - net_querydata_t *querydata, - unsigned int ping_time, - TXT_UNCAST_ARG(results_table)) -{ - TXT_CAST_ARG(txt_table_t, results_table); - char ping_time_str[16]; - char description[47]; - - // When we connect we'll have to negotiate a common protocol that we - // can agree upon between the client and server. If we can't then we - // won't be able to connect, so it's pointless to include it in the - // results list. If protocol==NET_PROTOCOL_UNKNOWN then this may be - // an old, pre-3.0 Chocolate Doom server that doesn't support the new - // protocol negotiation mechanism, or it may be an incompatible fork. - if (querydata->protocol == NET_PROTOCOL_UNKNOWN) - { - return; - } - - M_snprintf(ping_time_str, sizeof(ping_time_str), "%ims", ping_time); - - // Build description from server name field. Because there is limited - // space, we only include the player count if there are already players - // connected to the server. - if (querydata->num_players > 0) - { - M_snprintf(description, sizeof(description), "(%d/%d) ", - querydata->num_players, querydata->max_players); - } - else - { - M_StringCopy(description, "", sizeof(description)); - } - - M_StringConcat(description, querydata->description, sizeof(description)); - - TXT_AddWidgets(results_table, - TXT_NewLabel(ping_time_str), - TXT_NewButton2(NET_AddrToString(addr), - SelectQueryAddress, querydata), - TXT_NewLabel(description), - NULL); - - ++query_servers_found; -} - -static void QueryPeriodicCallback(TXT_UNCAST_ARG(results_table)) -{ - TXT_CAST_ARG(txt_table_t, results_table); - - if (!NET_Query_Poll(QueryResponseCallback, results_table)) - { - TXT_SetPeriodicCallback(NULL, NULL, 0); - - if (query_servers_found == 0) - { - TXT_AddWidgets(results_table, - TXT_TABLE_EMPTY, - TXT_NewLabel("No compatible servers found."), - NULL - ); - } - } -} - -static void QueryWindowClosed(TXT_UNCAST_ARG(window), void *unused) -{ - TXT_SetPeriodicCallback(NULL, NULL, 0); -} - -static void ServerQueryWindow(const char *title) -{ - txt_table_t *results_table; - - query_servers_found = 0; - - query_window = TXT_NewWindow(title); - - TXT_AddWidget(query_window, - TXT_NewScrollPane(70, 10, - results_table = TXT_NewTable(3))); - - TXT_SetColumnWidths(results_table, 7, 22, 40); - TXT_SetPeriodicCallback(QueryPeriodicCallback, results_table, 1); - - TXT_SignalConnect(query_window, "closed", QueryWindowClosed, NULL); -} - -static void FindInternetServer(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(user_data)) -{ - NET_StartMasterQuery(); - ServerQueryWindow("Find Internet server"); -} - -static void FindLANServer(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(user_data)) -{ - NET_StartLANQuery(); - ServerQueryWindow("Find LAN server"); -} - -void JoinMultiGame(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - txt_inputbox_t *address_box; - - window = TXT_NewWindow("Join multiplayer game"); - TXT_SetTableColumns(window, 2); - TXT_SetColumnWidths(window, 12, 12); - - TXT_SetWindowHelpURL(window, MULTI_JOIN_HELP_URL); - - TXT_AddWidgets(window, - TXT_NewLabel("Game"), - IWADSelector(), - NULL); - - if (gamemission == hexen) - { - TXT_AddWidgets(window, - TXT_NewLabel("Character class "), - TXT_NewDropdownList(&character_class, - character_classes, 3), - NULL); - } - - TXT_AddWidgets(window, - TXT_NewSeparator("Server"), - TXT_NewLabel("Connect to address: "), - address_box = TXT_NewInputBox(&connect_address, 30), - - TXT_NewButton2("Find server on Internet...", - FindInternetServer, NULL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_NewButton2("Find server on local network...", - FindLANServer, NULL), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_NewStrut(0, 1), - TXT_TABLE_OVERFLOW_RIGHT, - TXT_NewButton2("Add extra parameters...", - OpenExtraParamsWindow, NULL), - NULL); - - TXT_SelectWidget(window, address_box); - - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, WadWindowAction()); - TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, JoinGameAction()); -} - -void SetChatMacroDefaults(void) -{ - int i; - const char *const defaults[] = - { - HUSTR_CHATMACRO0, - HUSTR_CHATMACRO1, - HUSTR_CHATMACRO2, - HUSTR_CHATMACRO3, - HUSTR_CHATMACRO4, - HUSTR_CHATMACRO5, - HUSTR_CHATMACRO6, - HUSTR_CHATMACRO7, - HUSTR_CHATMACRO8, - HUSTR_CHATMACRO9, - }; - - // If the chat macros have not been set, initialize with defaults. - - for (i=0; i<10; ++i) - { - if (chat_macros[i] == NULL) - { - chat_macros[i] = M_StringDuplicate(defaults[i]); - } - } -} - -void SetPlayerNameDefault(void) -{ - if (net_player_name == NULL) - { - net_player_name = NET_GetRandomPetName(); - } -} - -void MultiplayerConfig(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - txt_label_t *label; - txt_table_t *table; - char buf[10]; - int i; - - window = TXT_NewWindow("Multiplayer Configuration"); - TXT_SetWindowHelpURL(window, MULTI_CONFIG_HELP_URL); - - TXT_AddWidgets(window, - TXT_NewStrut(0, 1), - TXT_NewHorizBox(TXT_NewLabel("Player name: "), - TXT_NewInputBox(&net_player_name, 25), - NULL), - TXT_NewStrut(0, 1), - TXT_NewSeparator("Chat macros"), - NULL); - - table = TXT_NewTable(2); - - for (i=0; i<10; ++i) - { - M_snprintf(buf, sizeof(buf), "#%i ", i + 1); - - label = TXT_NewLabel(buf); - TXT_SetFGColor(label, TXT_COLOR_BRIGHT_CYAN); - - TXT_AddWidgets(table, - label, - TXT_NewInputBox(&chat_macros[(i + 1) % 10], 40), - NULL); - } - - TXT_AddWidget(window, table); -} - -void BindMultiplayerVariables(void) -{ - char buf[15]; - int i; - - M_BindStringVariable("player_name", &net_player_name); - - for (i=0; i<10; ++i) - { - M_snprintf(buf, sizeof(buf), "chatmacro%i", i); - M_BindStringVariable(buf, &chat_macros[i]); - } - - switch (gamemission) - { - case doom: - M_BindChatControls(4); - key_multi_msgplayer[0] = 'g'; - key_multi_msgplayer[1] = 'i'; - key_multi_msgplayer[2] = 'b'; - key_multi_msgplayer[3] = 'r'; - break; - - case heretic: - M_BindChatControls(4); - key_multi_msgplayer[0] = 'g'; - key_multi_msgplayer[1] = 'y'; - key_multi_msgplayer[2] = 'r'; - key_multi_msgplayer[3] = 'b'; - break; - - case hexen: - M_BindChatControls(8); - key_multi_msgplayer[0] = 'b'; - key_multi_msgplayer[1] = 'r'; - key_multi_msgplayer[2] = 'y'; - key_multi_msgplayer[3] = 'g'; - key_multi_msgplayer[4] = 'j'; - key_multi_msgplayer[5] = 'w'; - key_multi_msgplayer[6] = 'h'; - key_multi_msgplayer[7] = 'p'; - break; - - default: - break; - } -} - diff --git a/games/NXDoom/src/setup/multiplayer.h b/games/NXDoom/src/setup/multiplayer.h deleted file mode 100644 index 911afbd0c1e..00000000000 --- a/games/NXDoom/src/setup/multiplayer.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_MULTIPLAYER_H -#define SETUP_MULTIPLAYER_H - -void StartMultiGame(void *widget, void *user_data); -void WarpMenu(void *widget, void *user_data); -void JoinMultiGame(void *widget, void *user_data); -void MultiplayerConfig(void *widget, void *user_data); - -void SetChatMacroDefaults(void); -void SetPlayerNameDefault(void); - -void BindMultiplayerVariables(void); - -#endif /* #ifndef SETUP_MULTIPLAYER_H */ - diff --git a/games/NXDoom/src/setup/setup-manifest.xml.in b/games/NXDoom/src/setup/setup-manifest.xml.in deleted file mode 100644 index 111ad0f888b..00000000000 --- a/games/NXDoom/src/setup/setup-manifest.xml.in +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - diff --git a/games/NXDoom/src/setup/setup_icon.c b/games/NXDoom/src/setup/setup_icon.c deleted file mode 100644 index 748cc93e961..00000000000 --- a/games/NXDoom/src/setup/setup_icon.c +++ /dev/null @@ -1,2736 +0,0 @@ -static int setup_icon_w = 128; -static int setup_icon_h = 128; - -static const unsigned int setup_icon_data[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, - 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, - 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, - 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, - 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, - 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, - 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, - 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, - 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, - 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, - 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, - 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, - 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, - 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, - 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, - 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, - 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, - 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, - 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, - 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, - 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, - 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, - 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, - 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, - 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, - 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, - 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, - 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, - 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, - 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, - 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, - 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, - 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, - 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, - 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, - 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, - 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, - 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, - 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, - 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, - 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, - 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, - 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, - 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, - 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, - 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, - 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, - 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x93756aff, 0x90756aff, 0x8b7974ff, 0x877b7bff, - 0x877b7bff, 0x877b7bff, 0x877b7bff, 0x877b7bff, 0x877b7bff, 0x928888ff, - 0xaba3a3ff, 0xaaa3a3ff, 0xaaa3a3ff, 0xa9a2a2ff, 0xa8a2a2ff, 0xa7a1a0ff, - 0xa6a09fff, 0xa6a09fff, 0xa59e9eff, 0x938989ff, 0x867a7aff, 0x867a79ff, - 0x867a79ff, 0x867979ff, 0x857878ff, 0x837676ff, 0x817474ff, 0x7f7272ff, - 0x807373ff, 0x928989ff, 0x968e8eff, 0x958d8dff, 0x938b8cff, 0x918989ff, - 0x8e8787ff, 0x8d8585ff, 0x8c8484ff, 0x898282ff, 0x837b7bff, 0x695c5cff, - 0x675a5aff, 0x655959ff, 0x635657ff, 0x615455ff, 0x5f5253ff, 0x5e5152ff, - 0x5c4e4fff, 0x5a4c4dff, 0x665a5bff, 0x756d6dff, 0x736b6bff, 0x72696aff, - 0x706767ff, 0x6e6666ff, 0x6d6464ff, 0x6b6262ff, 0x685f60ff, 0x685f5fff, - 0x504344ff, 0x443637ff, 0x423336ff, 0x45373bff, 0x473a41ff, 0x4a3c47ff, - 0x4c3f4bff, 0x54424dff, 0x5e454cff, 0x674e55ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, - 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, - 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, - 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, - 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, - 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, - 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, - 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, - 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, - 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, - 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, - 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, - 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, - 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, - 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, - 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, - 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, - 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, - 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, - 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, - 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, - 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8e9faeff, 0x94a5b3ff, - 0x93a3b2ff, 0x93a3b2ff, 0x92a2b1ff, 0x92a1b1ff, 0x91a0b0ff, 0x90a0afff, - 0x8f9faeff, 0x8394a5ff, 0x647b92ff, 0x647a92ff, 0x647a92ff, 0x647a91ff, - 0x647a91ff, 0x647990ff, 0x637890ff, 0x637890ff, 0x637890ff, 0x78899cff, - 0x8795a5ff, 0x8694a4ff, 0x8694a4ff, 0x8593a3ff, 0x8490a1ff, 0x828ea0ff, - 0x808d9dff, 0x7f8b9cff, 0x7c899aff, 0x5c6e86ff, 0x566882ff, 0x546680ff, - 0x53657eff, 0x51627cff, 0x4f617aff, 0x4d5e78ff, 0x4c5d77ff, 0x495b75ff, - 0x4f5f77ff, 0x697486ff, 0x687384ff, 0x677183ff, 0x656f81ff, 0x636e80ff, - 0x626c7eff, 0x606a7cff, 0x5e697aff, 0x5c6678ff, 0x4b576dff, 0x35435fff, - 0x33415cff, 0x32405bff, 0x2f3d58ff, 0x2e3b57ff, 0x2c3955ff, 0x2a3854ff, - 0x283552ff, 0x273450ff, 0x3f485eff, 0x485063ff, 0x464f61ff, 0x475065ff, - 0x485067ff, 0x475169ff, 0x49526cff, 0x4a536eff, 0x4b5471ff, 0x4c5573ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x1b3f5eff, 0x1a3e60ff, 0x1a3e5fff, 0x193d5fff, 0x193c5eff, 0x193c5eff, - 0x183b5dff, 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, - 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, - 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, - 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, - 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, - 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, - 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, - 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, - 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, - 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x1b3e5eff, 0x1a3e5fff, 0x193d5fff, 0x193c5eff, - 0x193c5eff, 0x183b5dff, 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, - 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, - 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, - 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, - 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, - 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, - 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, - 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, - 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, - 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, - 0x041541ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b3e5dff, 0x193d5fff, - 0x193c5eff, 0x193c5eff, 0x183b5dff, 0x183a5dff, 0x183a5cff, 0x17395cff, - 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, - 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, - 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, - 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, - 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, - 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, - 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, - 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, - 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, - 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x1b3d5dff, 0x193c5eff, 0x193c5eff, 0x183b5dff, 0x183a5dff, 0x183a5cff, - 0x17395cff, 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, - 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, - 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, - 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, - 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, - 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, - 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, - 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, - 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, - 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x1b3c5cff, 0x193c5eff, 0x183b5dff, 0x183a5dff, - 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, - 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, - 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, - 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, - 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, - 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, - 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, - 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, - 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, - 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1b3c5cff, 0x183b5dff, - 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, 0x16375aff, - 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, - 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, - 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, - 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, - 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, - 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, - 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, - 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, - 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x1a3b5bff, 0x183a5dff, 0x183a5cff, 0x17395cff, 0x17385bff, 0x17385bff, - 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, - 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, - 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, - 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, - 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, - 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, - 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, - 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, - 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x1a3a5bff, 0x183a5cff, 0x17395cff, 0x17385bff, - 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, - 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, - 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, - 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, - 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, - 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, - 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, - 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, - 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, - 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1a3a5aff, 0x17395cff, - 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, 0x153559ff, - 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, - 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, - 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, - 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, - 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, - 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, - 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, - 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, - 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x19395aff, 0x17385bff, 0x17385bff, 0x16375aff, 0x16375aff, 0x163659ff, - 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, - 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, - 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, - 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, - 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, - 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, - 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, - 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, - 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x193859ff, 0x17385bff, 0x16375aff, 0x16375aff, - 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, - 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, - 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, - 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, - 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, - 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, - 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, - 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, - 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x193859ff, 0x16375aff, - 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, 0x143357ff, - 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, - 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, - 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, - 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, - 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, - 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, - 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, - 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x183758ff, 0x16375aff, 0x163659ff, 0x153559ff, 0x153558ff, 0x153458ff, - 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, - 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, - 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, - 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x36496aff, - 0xadb5c3ff, 0xbec4cfff, 0xbec4cfff, 0xbec4cfff, 0xbec4cfff, 0xbec4ceff, - 0xbec4ceff, 0xacb3c1ff, 0x324364ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, - 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, - 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x183758ff, 0x163659ff, 0x153559ff, 0x153558ff, - 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, - 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, - 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, - 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, - 0x0d244cff, 0xc9ced7ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xc7cad0ff, 0x081b41ff, - 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, - 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, - 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x183657ff, 0x153559ff, - 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, 0x133156ff, - 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, - 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, - 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, - 0x0d254dff, 0x0d244cff, 0x0c244cff, 0xf4f5f7ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xf4f5f6ff, 0x06122cff, 0x071a40ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, - 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, - 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x173557ff, 0x153558ff, 0x153458ff, 0x143357ff, 0x143357ff, 0x143256ff, - 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, - 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, - 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, - 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x20355aff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfdfdfdff, 0x19243bff, 0x05112cff, 0x06193fff, - 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, - 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x173556ff, 0x153458ff, 0x143357ff, 0x143357ff, - 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, - 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, - 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, - 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, - 0x3f5070ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0x374054ff, - 0x041029ff, 0x04102bff, 0x06173eff, 0x061944ff, 0x061843ff, 0x061743ff, - 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x173456ff, 0x143357ff, - 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, 0x122f55ff, - 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, - 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, - 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, - 0x0c234bff, 0x0c224bff, 0x5c6c86ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, - 0xfafafaff, 0x565e6eff, 0x041029ff, 0x040f29ff, 0x04102bff, 0x06163dff, - 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x163355ff, 0x143357ff, 0x143256ff, 0x133156ff, 0x133156ff, 0x133055ff, - 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, - 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, - 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, - 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x7b879dff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, - 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0x737a87ff, 0x040f29ff, 0x040f29ff, - 0x040e28ff, 0x040e2aff, 0x05153dff, 0x051642ff, 0x051641ff, 0x041541ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x163355ff, 0x143256ff, 0x133156ff, 0x133156ff, - 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, - 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, - 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, - 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x132850ff, - 0xaeb5c2ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xa5a9b2ff, - 0x0d1731ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x030e2aff, 0x05143cff, - 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x163254ff, 0x133156ff, - 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, - 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, - 0x0f2950ff, 0x253b5fff, 0x243b5fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, - 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x20355aff, - 0x909aadff, 0xeff0f3ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, - 0xf5f5f5ff, 0xf4f4f4ff, 0xe3e4e6ff, 0x868a96ff, 0x18223aff, 0x030d28ff, - 0x030d27ff, 0x020d29ff, 0x04123bff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x17254dff, 0x18264eff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x153154ff, 0x133156ff, 0x133055ff, 0x122f55ff, 0x122f54ff, 0x122e54ff, - 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, - 0x0f2a50ff, 0x0f2950ff, 0x576883ff, 0xfafbfcff, 0xfdfdfeff, 0xb7becaff, - 0x50627fff, 0x0e264eff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0f254dff, - 0x78859bff, 0xf4f5f6ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, - 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, - 0xe4e5e6ff, 0x6c7180ff, 0x05102aff, 0x020c26ff, 0x030d28ff, 0x04133bff, - 0x051541ff, 0x414d6cff, 0x9da2b0ff, 0xdededfff, 0xd9d9daff, 0x444e69ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x153154ff, 0x133055ff, 0x122f55ff, 0x122f54ff, - 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, - 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x183056ff, 0xe3e6eaff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xdbdee4ff, 0x76839aff, 0x1a3056ff, - 0x22365bff, 0xc5cad4ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, - 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, - 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xb1b4baff, 0x172038ff, - 0x0f1831ff, 0x636979ff, 0xc1c3c9ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, - 0xddddddff, 0xc1c3c6ff, 0x0c193fff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x153053ff, 0x122f55ff, - 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, - 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x8693a7ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xf4f5f7ff, 0xe9ebefff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, - 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, - 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xd1d2d4ff, 0xd9dadbff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, - 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0x6e7382ff, 0x031138ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x142f53ff, 0x122f54ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, 0x112c52ff, - 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, - 0x284062ff, 0xf5f6f7ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, - 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, - 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, - 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, - 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, - 0xceced0ff, 0x1e2541ff, 0x041239ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x142f52ff, 0x122e54ff, 0x112d53ff, 0x112d53ff, - 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, - 0x0f284fff, 0x0e284fff, 0xabb4c1ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfdfdfdff, 0xfcfcfcff, 0xd4d6daff, 0x8a8f9aff, 0x606877ff, 0x4a5264ff, - 0x4a5264ff, 0x5e6575ff, 0x868a96ff, 0xcaccd0ff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, - 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, - 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0x8b8e98ff, 0x050d2dff, 0x051239ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x142e52ff, 0x112d53ff, - 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, - 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x465977ff, 0xfefefeff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfdfdfdff, 0xb6bac1ff, 0x353e53ff, 0x041029ff, 0x041029ff, - 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x030d28ff, - 0x30384dff, 0xaaadb4ff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, - 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, - 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd1d1d1ff, - 0x343a53ff, 0x050e2eff, 0x05123aff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x132d51ff, 0x112d53ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, 0x102a51ff, - 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0xc0c6d0ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xf1f2f3ff, 0x545d6dff, 0x05102aff, 0x041029ff, - 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, - 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0x4c5365ff, 0xdbdcddff, - 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, - 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, - 0xd2d2d2ff, 0xd0d0d0ff, 0x999ca4ff, 0x050f2eff, 0x050f2eff, 0x05123aff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x132d51ff, 0x112c52ff, 0x102c52ff, 0x102b51ff, - 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, - 0x0e264eff, 0xc4cad3ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xe7e8ebff, 0x323c50ff, 0x05102aff, - 0x041029ff, 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x040e28ff, - 0x030e28ff, 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0x020c26ff, - 0x020c26ff, 0x2b3348ff, 0xcfd0d2ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, - 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, - 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0x9b9ea6ff, 0x050f2eff, - 0x050f30ff, 0x050f30ff, 0x05123aff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x132c50ff, 0x102c52ff, - 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, - 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x324666ff, 0xd9dce0ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf7f7f8ff, 0x3f485bff, - 0x05102aff, 0x041029ff, 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, - 0x040e28ff, 0x030e28ff, 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, - 0x020c26ff, 0x020c26ff, 0x020c26ff, 0x020c27ff, 0x373e53ff, 0xdbdbdcff, - 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, - 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xafb0b5ff, - 0x242d47ff, 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x05123aff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x122c50ff, 0x102b51ff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, 0x0f284fff, - 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, - 0x172d51ff, 0xaaafb8ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfdfdfdff, - 0x787e8cff, 0x05102aff, 0x041029ff, 0x041029ff, 0x040f29ff, 0x040f29ff, - 0x09132cff, 0x5e6575ff, 0xabaeb6ff, 0xcbcdd1ff, 0xcaccd0ff, 0xa8abb2ff, - 0x595f70ff, 0x07112aff, 0x020c26ff, 0x020c26ff, 0x020c27ff, 0x020c27ff, - 0x020c27ff, 0x696e7eff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, - 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, - 0x888b96ff, 0x0f1836ff, 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, - 0x060f31ff, 0x061032ff, 0x05123bff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x122b4fff, 0x102a51ff, 0x0f2a50ff, 0x0f2950ff, - 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, - 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0b2047ff, 0x6d7685ff, 0xf8f9f9ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfdfdfdff, 0xe0e1e4ff, 0x0d1731ff, 0x041029ff, 0x041029ff, 0x040f29ff, - 0x040f29ff, 0x262f45ff, 0xcacbd0ff, 0xefefefff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xbec0c5ff, 0x222a41ff, 0x020c27ff, - 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x0b142fff, 0xc2c3c7ff, 0xdadadaff, - 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, - 0xc9c9caff, 0x585e70ff, 0x050f2eff, 0x050f30ff, 0x050f30ff, 0x050f30ff, - 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x05123bff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x122a4fff, 0x0f2a50ff, - 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, 0x0d264dff, - 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, - 0x0a1f47ff, 0x384359ff, 0xdddfe2ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0x747a88ff, 0x041029ff, 0x041029ff, - 0x040f29ff, 0x040f29ff, 0x1e273eff, 0xd8d9dcff, 0xefefefff, 0xeeeeeeff, - 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, - 0xcbcccfff, 0x19223aff, 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, - 0x656a7aff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, - 0xd0d0d0ff, 0xb4b5b9ff, 0x2d354eff, 0x050f2eff, 0x050f30ff, 0x050f30ff, - 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, - 0x061034ff, 0x061034ff, 0x05123bff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x112a4eff, 0x0f2950ff, 0x0f284fff, 0x0e284fff, 0x0e274eff, 0x0e264eff, - 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, - 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a1e46ff, 0x888f9bff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, 0x273247ff, - 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0xa5a9b1ff, 0xefefefff, - 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0x9699a2ff, 0x020c29ff, 0x040d29ff, - 0x040d29ff, 0x040d2aff, 0x212943ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, - 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0x6a6f7fff, 0x050f2eff, 0x050f30ff, - 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, - 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x05123cff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x11294eff, 0x0f284fff, 0x0e284fff, 0x0e274eff, - 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, - 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, - 0xafb6c2ff, 0xffffffff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, 0xfafafaff, - 0xdbdde0ff, 0x041029ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, 0x1f273eff, - 0xeeeeeeff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, - 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xddddddff, - 0x1c243cff, 0x040d29ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, 0xbebec2ff, - 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0x898c97ff, - 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, - 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, - 0x061035ff, 0x061136ff, 0x05123cff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x11284dff, 0x0e284fff, - 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, 0x0c244cff, - 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, - 0x0a1f48ff, 0x0a1f48ff, 0xc3c8d2ff, 0xffffffff, 0xfdfdfdff, 0xfcfcfcff, - 0xfafafaff, 0xf8f8f8ff, 0xc0c3c8ff, 0x040f29ff, 0x040f29ff, 0x040e28ff, - 0x040e28ff, 0x596070ff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, - 0xdededeff, 0xddddddff, 0x525769ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, - 0x050d2cff, 0xa5a7aeff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, - 0xccccccff, 0x989ba3ff, 0x050f30ff, 0x050f30ff, 0x050f31ff, 0x060f31ff, - 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, - 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x07133bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x10284dff, 0x0e274eff, 0x0e264eff, 0x0d264dff, 0x0d254dff, 0x0d244cff, - 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, - 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0xcdd1d9ff, 0xfdfdfdff, - 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xabafb7ff, 0x040f29ff, - 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x6d7281ff, 0xecececff, 0xebebebff, - 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, - 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0x646979ff, 0x040d2bff, - 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x9496a0ff, 0xd0d0d0ff, 0xcfcfcfff, - 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xa1a3aaff, 0x050f30ff, 0x050f31ff, - 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, - 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, - 0x061137ff, 0x081237ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x10274cff, 0x0e264eff, 0x0d264dff, 0x0d254dff, - 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, - 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, - 0xc2c7d1ff, 0xfcfcfcff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, - 0xbbbec4ff, 0x040e28ff, 0x040e28ff, 0x030e28ff, 0x030d28ff, 0x5d6373ff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, - 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, - 0x53596cff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x9fa1a9ff, - 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0x989ba2ff, - 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, - 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, - 0x061136ff, 0x061137ff, 0x061137ff, 0x081237ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10264cff, 0x0d264dff, - 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, 0x0b224aff, - 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, - 0x091d47ff, 0x091d46ff, 0xb0b6c3ff, 0xfafafaff, 0xf8f8f8ff, 0xf7f7f7ff, - 0xf5f5f5ff, 0xf4f4f4ff, 0xd2d3d6ff, 0x040e28ff, 0x030e28ff, 0x030d28ff, - 0x030d27ff, 0x262f45ff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, - 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, - 0xdadadaff, 0xd8d8d8ff, 0x222a45ff, 0x050d2cff, 0x050d2cff, 0x050d2dff, - 0x050d2dff, 0xb4b5b9ff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0x8b8e98ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, - 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, - 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x081237ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0f264bff, 0x0d254dff, 0x0d244cff, 0x0c244cff, 0x0c234bff, 0x0c224bff, - 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, - 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x8992a6ff, 0xf8f8f8ff, - 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf0f0f0ff, 0x1b253cff, - 0x030d28ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0xaeb0b7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, - 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0x9fa1aaff, 0x050d2cff, 0x050d2cff, - 0x050d2dff, 0x050d2dff, 0x1b233fff, 0xccccccff, 0xccccccff, 0xcacacaff, - 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0x6e7281ff, 0x061031ff, 0x061032ff, - 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, - 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, - 0x061138ff, 0x081238ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x0f254bff, 0x0d244cff, 0x0c244cff, 0x0c234bff, - 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, - 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x223359ff, - 0xc5c9d2ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, - 0xefefefff, 0x636979ff, 0x030d27ff, 0x020d27ff, 0x020c26ff, 0x020c26ff, - 0x283046ff, 0xd8d9daff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdededeff, - 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xcacbccff, 0x252c46ff, - 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x575d6fff, 0xccccccff, - 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0x9a9ca3ff, - 0x1a2342ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, - 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, - 0x061137ff, 0x061138ff, 0x061138ff, 0x081238ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0f244bff, 0x0c244cff, - 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, - 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, - 0x4c5979ff, 0xe5e6eaff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, - 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xc4c5caff, 0x05102aff, 0x020c26ff, - 0x020c26ff, 0x020c26ff, 0x020c26ff, 0x373e53ff, 0xcecfd1ff, 0xe0e0e0ff, - 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, 0xc3c4c7ff, - 0x353b53ff, 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x07112fff, - 0xabacb2ff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, - 0xc2c2c2ff, 0xc1c1c1ff, 0xafb0b3ff, 0x39415bff, 0x061034ff, 0x061034ff, - 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, - 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x081238ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0e244bff, 0x0c234bff, 0x0c224bff, 0x0b224aff, 0x0b214aff, 0x0b2149ff, - 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, - 0x0b1f48ff, 0x848da2ff, 0xf6f6f7ff, 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, - 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, - 0x5b6171ff, 0x020c26ff, 0x020c26ff, 0x020c26ff, 0x020c27ff, 0x020c27ff, - 0x121b34ff, 0x737886ff, 0xbbbcc0ff, 0xd8d8d9ff, 0xd7d7d8ff, 0xb7b8bdff, - 0x707483ff, 0x131a37ff, 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, - 0x050f2eff, 0x51576aff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbbbbbbff, - 0x636879ff, 0x081236ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, - 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, - 0x061239ff, 0x081339ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x0e234aff, 0x0c224bff, 0x0b224aff, 0x0b214aff, - 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, - 0x091d46ff, 0x1e3057ff, 0xbcc1ccff, 0xf8f8f8ff, 0xf7f7f7ff, 0xf5f5f5ff, - 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xd9dadbff, 0x252d43ff, 0x020c26ff, 0x020c27ff, - 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, 0x060f2cff, - 0x060f2dff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x050d2dff, - 0x050e2dff, 0x050f2eff, 0x242d47ff, 0xbebfc1ff, 0xc9c9c9ff, 0xc7c7c7ff, - 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, - 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, 0x8b8d97ff, 0x151f40ff, 0x061136ff, - 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, - 0x061138ff, 0x061239ff, 0x061239ff, 0x081339ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e224aff, 0x0b224aff, - 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, - 0x091d47ff, 0x091d46ff, 0x081c46ff, 0xb2b8c5ff, 0xf8f8f8ff, 0xf7f7f7ff, - 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, - 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xc2c4c8ff, - 0x182139ff, 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, - 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, - 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x19223dff, 0xadaeb3ff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, - 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, - 0x80838eff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, - 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x081339ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0d2249ff, 0x0b214aff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, 0x0a1f48ff, - 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0xc3c7d0ff, - 0xf7f7f7ff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, 0xefefefff, - 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xe3e3e3ff, 0xc9cacdff, 0x2f374cff, 0x020c29ff, 0x040d29ff, - 0x040d29ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, - 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x2e364eff, 0xb6b7baff, - 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, - 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, - 0xb6b6b6ff, 0xb5b5b5ff, 0x8b8e96ff, 0x061137ff, 0x061137ff, 0x061137ff, - 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, - 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x0d2149ff, 0x0b2149ff, 0x0a2049ff, 0x0a1f48ff, - 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, - 0x071b45ff, 0x525f7cff, 0xf5f5f5ff, 0xf4f4f4ff, 0xf2f2f2ff, 0xf1f1f1ff, - 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, - 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, 0xdadadbff, - 0x878a95ff, 0x19213aff, 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, - 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x151e3aff, 0x6f7482ff, - 0xc4c4c5ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, - 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, 0xb9b9b9ff, - 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb3b3b3ff, 0x3b435dff, 0x061137ff, - 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, - 0x06123aff, 0x06123aff, 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0d2148ff, 0x0a2049ff, - 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, - 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0xb5bac5ff, 0xf2f2f2ff, - 0xf1f1f1ff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, 0xe0e0e0ff, - 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xd3d3d4ff, 0x999ca5ff, 0x595f71ff, - 0x383e55ff, 0x232a44ff, 0x232a45ff, 0x373d55ff, 0x585d6fff, 0x93969fff, - 0xc6c6c7ff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, - 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, - 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb3b3b3ff, 0x848791ff, - 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, - 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x08133aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0c2048ff, 0x0a1f48ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, 0x091d46ff, - 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, - 0x2d3c60ff, 0xececedff, 0xefefefff, 0xeeeeeeff, 0xecececff, 0xebebebff, - 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe3e3e3ff, 0xe1e1e1ff, - 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, 0xd8d8d8ff, - 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, - 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, - 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb3b3b3ff, - 0xafafb0ff, 0x242d4cff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, - 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x0c1f47ff, 0x0a1f48ff, 0x091e47ff, 0x091d47ff, - 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, - 0x061944ff, 0x061843ff, 0x061743ff, 0x8d95a7ff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xe2e2e2ff, - 0xdbdbdcff, 0xe0e0e0ff, 0xdededeff, 0xddddddff, 0xdbdbdbff, 0xdadadaff, - 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, - 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, - 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xb8b9baff, - 0xbbbbbbff, 0xbbbbbbff, 0xb9b9b9ff, 0xb8b8b8ff, 0xb6b6b6ff, 0xb5b5b5ff, - 0xb3b3b3ff, 0xb1b1b1ff, 0x696d7dff, 0x061137ff, 0x061138ff, 0x061138ff, - 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x06123aff, 0x06123aff, 0x08133aff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0c1f47ff, 0x091e47ff, - 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, - 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x15254eff, - 0xdadcdfff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xd8d9daff, - 0x898d98ff, 0x293147ff, 0x242c43ff, 0xbabcc1ff, 0xddddddff, 0xdbdbdbff, - 0xdadadaff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, 0xd2d2d2ff, - 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, - 0xa3a4aaff, 0x252d4bff, 0x202947ff, 0x666a7cff, 0xacadb0ff, 0xb6b6b6ff, - 0xb5b5b5ff, 0xb3b3b3ff, 0xb1b1b1ff, 0xa4a5a8ff, 0x141e41ff, 0x061138ff, - 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x08143bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0b1e46ff, 0x091d47ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, 0x071b45ff, - 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, - 0x051642ff, 0x051641ff, 0x5f6a84ff, 0xe9e9e9ff, 0xe7e7e7ff, 0xc1c3c7ff, - 0x616776ff, 0x0e1731ff, 0x020c27ff, 0x020c27ff, 0x020c29ff, 0x0f1732ff, - 0x828591ff, 0xd9d9d9ff, 0xd8d8d8ff, 0xd6d6d6ff, 0xd5d5d5ff, 0xd3d3d3ff, - 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, - 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, - 0xbebebeff, 0x707483ff, 0x0f183bff, 0x061034ff, 0x061035ff, 0x061035ff, - 0x0f183bff, 0x4f556bff, 0x97999fff, 0xb1b1b1ff, 0xb0b0b0ff, 0x484e65ff, - 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x07133bff, 0x07143bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x0b1d46ff, 0x091d46ff, 0x081c46ff, 0x081b46ff, - 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, - 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x323d59ff, - 0x353c51ff, 0x030d27ff, 0x020c27ff, 0x020c27ff, 0x020c27ff, 0x020c29ff, - 0x040d29ff, 0x040d29ff, 0x040d2aff, 0x2b334bff, 0x9497a1ff, 0xd3d3d3ff, - 0xd3d3d3ff, 0xd2d2d2ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, 0xccccccff, - 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, - 0xbfbfc0ff, 0x838691ff, 0x272f4dff, 0x061034ff, 0x061034ff, 0x061035ff, - 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x071238ff, 0x2c3452ff, - 0x28314fff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, - 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x07133bff, 0x06133cff, 0x07143bff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0b1d45ff, 0x081c46ff, - 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, 0x061843ff, - 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x031034ff, 0x020c27ff, 0x020c27ff, 0x020c27ff, - 0x020c29ff, 0x040d29ff, 0x040d29ff, 0x040d2aff, 0x040d2bff, 0x040d2cff, - 0x050d2cff, 0x1d2440ff, 0x9c9ea7ff, 0xd0d0d0ff, 0xcfcfcfff, 0xcdcdcdff, - 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, - 0xc2c2c2ff, 0x90929bff, 0x1a2342ff, 0x061034ff, 0x061034ff, 0x061034ff, - 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, - 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, - 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x07143cff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0a1c45ff, 0x081b46ff, 0x071b45ff, 0x071a45ff, 0x071944ff, 0x061944ff, - 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x031034ff, - 0x020c27ff, 0x020c29ff, 0x040d29ff, 0x040d29ff, 0x040d2aff, 0x040d2bff, - 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x676b7bff, 0xcfcfcfff, - 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0x5e6375ff, 0x061034ff, 0x061034ff, - 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, - 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, - 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, - 0x06133cff, 0x07143cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x0a1b45ff, 0x071b45ff, 0x071a45ff, 0x071944ff, - 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, - 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x031035ff, 0x040d29ff, 0x040d29ff, 0x040d2aff, - 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, 0x050d2dff, - 0x4c5266ff, 0xcdcdcdff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, - 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0x464c64ff, - 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, - 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, - 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, - 0x06133cff, 0x06133cff, 0x06133dff, 0x07143cff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x091b44ff, 0x071a45ff, - 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, 0x051642ff, - 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x031135ff, - 0x040d2aff, 0x040d2bff, 0x040d2cff, 0x050d2cff, 0x050d2cff, 0x050d2dff, - 0x050d2dff, 0x050e2dff, 0x333b53ff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, - 0xbebebeff, 0x2f3652ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, - 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, - 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, - 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x07143cff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x091a44ff, 0x071944ff, 0x061944ff, 0x061843ff, 0x061743ff, 0x051742ff, - 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x031136ff, 0x040d2cff, 0x050d2cff, 0x050d2cff, - 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x19223eff, 0xcacacaff, - 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, 0xc1c1c1ff, - 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0x172041ff, 0x061035ff, 0x061035ff, - 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, - 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, - 0x06133cff, 0x08133cff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x091a43ff, 0x061944ff, 0x061843ff, 0x061743ff, - 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041137ff, - 0x050d2cff, 0x050d2dff, 0x050d2dff, 0x050e2dff, 0x050f2eff, 0x050f2eff, - 0x061031ff, 0xc3c3c5ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xc2c2c2ff, - 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xb5b6b7ff, 0x071136ff, - 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, - 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, - 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, - 0x06133dff, 0x06133cff, 0x06123dff, 0x08143dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x081a43ff, 0x061843ff, - 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041137ff, 0x050d2dff, 0x050e2dff, 0x050f2eff, - 0x050f2eff, 0x050f30ff, 0x050f30ff, 0xa4a6acff, 0xc6c6c6ff, 0xc4c4c4ff, - 0xc2c2c2ff, 0xc1c1c1ff, 0xbfbfbfff, 0xbebebeff, 0xbcbcbcff, 0xbbbbbbff, - 0x999ba2ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, - 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, - 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, - 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x08143dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x081942ff, 0x061743ff, 0x051742ff, 0x051642ff, 0x051641ff, 0x041541ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041137ff, - 0x050f2eff, 0x050f2eff, 0x050f30ff, 0x050f30ff, 0x050f30ff, 0x363d57ff, - 0x9ea0a7ff, 0xa9aaafff, 0xa8a9aeff, 0xa7a8adff, 0xa6a7acff, 0xa4a5aaff, - 0xa3a4a9ff, 0x95979fff, 0x323955ff, 0x061035ff, 0x061136ff, 0x061136ff, - 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, - 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, - 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, - 0x06133eff, 0x08143dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x081842ff, 0x051742ff, 0x051642ff, 0x051641ff, - 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041138ff, 0x050f30ff, 0x050f30ff, 0x050f30ff, - 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, 0x061034ff, - 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, - 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, - 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, - 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, - 0x06133dff, 0x06133eff, 0x06133eff, 0x08143eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x071841ff, 0x051642ff, - 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041138ff, - 0x050f30ff, 0x050f31ff, 0x060f31ff, 0x061031ff, 0x061032ff, 0x061032ff, - 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, - 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, - 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, - 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, - 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x07143eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x071741ff, 0x051641ff, 0x041541ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041139ff, 0x060f31ff, 0x061031ff, 0x061032ff, - 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, 0x061035ff, - 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, - 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, - 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, - 0x05133fff, 0x07143eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x071740ff, 0x041541ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x04113aff, - 0x061032ff, 0x061032ff, 0x061034ff, 0x061034ff, 0x061034ff, 0x061035ff, - 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, - 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, - 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, - 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, - 0x06133eff, 0x05133fff, 0x05133fff, 0x07143eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x061640ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x05123aff, 0x061034ff, 0x061034ff, 0x061034ff, - 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, 0x061137ff, - 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, - 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, - 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, - 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x07143eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05123aff, - 0x061034ff, 0x061035ff, 0x061035ff, 0x061035ff, 0x061136ff, 0x061136ff, - 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, - 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, - 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, - 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, - 0x05133fff, 0x07143eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x05123bff, 0x061035ff, 0x061035ff, 0x061136ff, - 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, 0x061138ff, - 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, - 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, - 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, - 0x05133eff, 0x05133fff, 0x05133fff, 0x07153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06123bff, - 0x061136ff, 0x061136ff, 0x061137ff, 0x061137ff, 0x061137ff, 0x061138ff, - 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, - 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, - 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, - 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x06153eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x06123cff, 0x061137ff, 0x061137ff, 0x061137ff, - 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, 0x06123aff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, - 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, - 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, - 0x04143fff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06123cff, - 0x061137ff, 0x061138ff, 0x061138ff, 0x061138ff, 0x061239ff, 0x061239ff, - 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, - 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, - 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, - 0x051440ff, 0x04143fff, 0x04143fff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x06123cff, 0x061138ff, 0x061138ff, 0x061239ff, - 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, 0x06123aff, - 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, - 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, - 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, - 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06123dff, - 0x061239ff, 0x061239ff, 0x06123aff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, - 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, - 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, - 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x06123dff, 0x06123aff, 0x06123aff, 0x06123aff, - 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, 0x06133cff, - 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, - 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, - 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05133dff, - 0x06123aff, 0x06123bff, 0x06123aff, 0x06123aff, 0x06123bff, 0x07133bff, - 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, - 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, - 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, - 0x04143fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x05133eff, 0x06123aff, 0x06123aff, 0x06123bff, - 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, 0x06133dff, - 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, - 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, - 0x04143fff, 0x04143fff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x06153fff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05133eff, - 0x06123bff, 0x07133bff, 0x06133cff, 0x06133cff, 0x06133cff, 0x06133dff, - 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, 0x06133eff, - 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, 0x05133fff, - 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x06153fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e163bff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x05133eff, 0x06133cff, 0x06133cff, 0x06133cff, - 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, 0x06133eff, - 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, 0x05133fff, - 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x0f163aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x2e1f2fea, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x05133dff, - 0x06133cff, 0x06133dff, 0x06133dff, 0x06133cff, 0x06123dff, 0x06133dff, - 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, 0x05133eff, - 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x2e1f30e9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x5a2d2d22, 0x231c32f7, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x05133eff, 0x06133dff, 0x06133cff, 0x06123dff, - 0x06133dff, 0x06133eff, 0x06133eff, 0x06133eff, 0x05133fff, 0x05133fff, - 0x05133eff, 0x05133fff, 0x05133fff, 0x051440ff, 0x04143fff, 0x04143fff, - 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, 0x041440ff, - 0x041440ff, 0x041440ff, 0x231b33f6, 0x58303020, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x552c254b, 0x4c292a97, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4627299d, - 0x4625299d, 0x46272a9d, 0x4627299d, 0x4627299d, 0x4627299d, 0x4627299d, - 0x4627299c, 0x4627299c, 0x4827299c, 0x4827299c, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, 0x4827299b, - 0x4827299b, 0x4827299b, 0x4c292a97, 0x552c254b, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; diff --git a/games/NXDoom/src/setup/sound.c b/games/NXDoom/src/setup/sound.c deleted file mode 100644 index 982ce00bccc..00000000000 --- a/games/NXDoom/src/setup/sound.c +++ /dev/null @@ -1,410 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -// Sound control menu - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#endif - -#include -#include - -#include "textscreen.h" -#include "m_config.h" -#include "m_misc.h" - -#include "execute.h" -#include "mode.h" -#include "sound.h" - -#ifndef DISABLE_SDL2MIXER - -#include "SDL_mixer.h" - -#endif // DISABLE_SDL2MIXER - - -#define WINDOW_HELP_URL "https://www.chocolate-doom.org/setup-sound" - -typedef enum -{ - OPLMODE_OPL2, - OPLMODE_OPL3, - NUM_OPLMODES, -} oplmode_t; - -static const char *opltype_strings[] = -{ - "OPL2", - "OPL3" -}; - -static const char *cfg_extension[] = { "cfg", NULL }; - -#ifdef HAVE_FLUIDSYNTH -static const char *sf_extension[] = { "sf2", "sf3", NULL }; -#endif - -// Config file variables: - -int snd_sfxdevice = SNDDEVICE_SB; -int snd_musicdevice = SNDDEVICE_SB; -int snd_samplerate = 44100; -int opl_io_port = 0x388; -int snd_cachesize = 64 * 1024 * 1024; -int snd_maxslicetime_ms = 28; -char *snd_musiccmd = ""; -int snd_pitchshift = 0; -char *snd_dmxoption = ""; - -static int numChannels = 8; -static int sfxVolume = 8; -static int musicVolume = 8; -static int voiceVolume = 15; -static int show_talk = 0; -int use_libsamplerate = 0; -float libsamplerate_scale = 0.65; - -char *music_pack_path = NULL; -char *timidity_cfg_path = NULL; -static char *gus_patch_path = NULL; -static int gus_ram_kb = 1024; -#ifdef _WIN32 -#define MAX_MIDI_DEVICES 20 -static char *midi_names[MAX_MIDI_DEVICES]; -static int midi_index; -char *winmm_midi_device = NULL; -int winmm_complevel = 0; -int winmm_reset_type = 1; -int winmm_reset_delay = 0; -#endif - -#ifdef HAVE_FLUIDSYNTH -char *fsynth_sf_path = NULL; -int fsynth_chorus_active = 1; -float fsynth_chorus_depth = 5.0f; -float fsynth_chorus_level = 0.35f; -int fsynth_chorus_nr = 3; -float fsynth_chorus_speed = 0.3f; -char *fsynth_midibankselect = "gs"; -int fsynth_polyphony = 256; -int fsynth_reverb_active = 1; -float fsynth_reverb_damp = 0.4f; -float fsynth_reverb_level = 0.15f; -float fsynth_reverb_roomsize = 0.6f; -float fsynth_reverb_width = 4.0f; -float fsynth_gain = 1.0f; -#endif // HAVE_FLUIDSYNTH - -// DOS specific variables: these are unused but should be maintained -// so that the config file can be shared between chocolate -// doom and doom.exe - -static int snd_sbport = 0; -static int snd_sbirq = 0; -static int snd_sbdma = 0; -static int snd_mport = 0; - -static int snd_oplmode; - -static void UpdateSndDevices(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) -{ - switch (snd_oplmode) - { - default: - case OPLMODE_OPL2: - snd_dmxoption = ""; - break; - - case OPLMODE_OPL3: - snd_dmxoption = "-opl3"; - break; - } -} - -static txt_dropdown_list_t *OPLTypeSelector(void) -{ - txt_dropdown_list_t *result; - - if (snd_dmxoption != NULL && strstr(snd_dmxoption, "-opl3") != NULL) - { - snd_oplmode = OPLMODE_OPL3; - } - else - { - snd_oplmode = OPLMODE_OPL2; - } - - result = TXT_NewDropdownList(&snd_oplmode, opltype_strings, 2); - - TXT_SignalConnect(result, "changed", UpdateSndDevices, NULL); - - return result; -} - -static void OpenMusicPackDir(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) -{ - if (!OpenFolder(music_pack_path)) - { - TXT_MessageBox("Error", "Failed to open music pack directory."); - } -} - -#ifdef _WIN32 -static void UpdateMidiDevice(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) -{ - free(winmm_midi_device); - winmm_midi_device = M_StringDuplicate(midi_names[midi_index]); -} - -static txt_dropdown_list_t *MidiDeviceSelector(void) -{ - txt_dropdown_list_t *result; - int num_devices = 1; - int all_devices = midiOutGetNumDevs(); - int i; - - midi_index = 0; - free(midi_names[0]); - midi_names[0] = M_StringDuplicate("Microsoft MIDI Mapper"); - - if (all_devices > MAX_MIDI_DEVICES - num_devices) - { - all_devices = MAX_MIDI_DEVICES - num_devices; - } - - for (i = 0; i < all_devices; i++) - { - MIDIOUTCAPS caps; - - if (midiOutGetDevCaps(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) - { - free(midi_names[num_devices]); - midi_names[num_devices] = M_StringDuplicate(caps.szPname); - - if (!strncasecmp(winmm_midi_device, midi_names[num_devices], - MAXPNAMELEN)) - { - // Set the dropdown list index to the saved device. - midi_index = num_devices; - } - - num_devices++; - } - } - - free(winmm_midi_device); - winmm_midi_device = M_StringDuplicate(midi_names[midi_index]); - - result = TXT_NewDropdownList(&midi_index, (const char **) midi_names, - num_devices); - TXT_SignalConnect(result, "changed", UpdateMidiDevice, NULL); - - return result; -} -#endif - -void ConfigSound(TXT_UNCAST_ARG(widget), void *user_data) -{ - txt_window_t *window; - txt_window_action_t *music_action; - - // Build the window - - window = TXT_NewWindow("Sound configuration"); - TXT_SetWindowHelpURL(window, WINDOW_HELP_URL); - - TXT_SetColumnWidths(window, 40); - TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, - TXT_SCREEN_W / 2, 3); - - music_action = TXT_NewWindowAction('m', "Music Packs"); - TXT_SetWindowAction(window, TXT_HORIZ_CENTER, music_action); - TXT_SignalConnect(music_action, "pressed", OpenMusicPackDir, NULL); - - TXT_AddWidgets(window, - TXT_NewSeparator("Sound effects"), - TXT_NewRadioButton("Disabled", &snd_sfxdevice, SNDDEVICE_NONE), - TXT_If(gamemission == doom || gamemission == strife, - TXT_NewRadioButton("PC speaker effects", &snd_sfxdevice, - SNDDEVICE_PCSPEAKER)), - TXT_NewRadioButton("Digital sound effects", - &snd_sfxdevice, - SNDDEVICE_SB), - TXT_If(gamemission == doom || gamemission == heretic - || gamemission == hexen, - TXT_NewConditional(&snd_sfxdevice, SNDDEVICE_SB, - TXT_NewHorizBox( - TXT_NewStrut(4, 0), - TXT_NewCheckBox("Pitch-shifted sounds", &snd_pitchshift), - NULL))), - TXT_If(gamemission == strife, - TXT_NewConditional(&snd_sfxdevice, SNDDEVICE_SB, - TXT_NewHorizBox( - TXT_NewStrut(4, 0), - TXT_NewCheckBox("Show text with voices", &show_talk), - NULL))), - - TXT_NewSeparator("Music"), - TXT_NewRadioButton("Disabled", &snd_musicdevice, SNDDEVICE_NONE), - - TXT_NewRadioButton("OPL (Adlib/Soundblaster)", &snd_musicdevice, - SNDDEVICE_SB), - TXT_NewConditional(&snd_musicdevice, SNDDEVICE_SB, - TXT_NewHorizBox( - TXT_NewStrut(4, 0), - TXT_NewLabel("Chip type: "), - OPLTypeSelector(), - NULL)), - - TXT_NewRadioButton("GUS (emulated)", &snd_musicdevice, SNDDEVICE_GUS), - TXT_NewConditional(&snd_musicdevice, SNDDEVICE_GUS, - TXT_MakeTable(2, - TXT_NewStrut(4, 0), - TXT_NewLabel("Path to patch files: "), - TXT_NewStrut(4, 0), - TXT_NewFileSelector(&gus_patch_path, 34, - "Select directory containing GUS patches", - TXT_DIRECTORY), - NULL)), - - TXT_NewRadioButton("Native MIDI", &snd_musicdevice, SNDDEVICE_GENMIDI), -#ifdef _WIN32 - TXT_NewConditional(&snd_musicdevice, SNDDEVICE_GENMIDI, - TXT_NewHorizBox( - TXT_NewStrut(4, 0), - TXT_NewLabel("Device: "), - MidiDeviceSelector(), - NULL)), -#endif - TXT_NewConditional(&snd_musicdevice, SNDDEVICE_GENMIDI, - TXT_MakeTable(2, - TXT_NewStrut(4, 0), - TXT_NewLabel("Timidity configuration file: "), - TXT_NewStrut(4, 0), - TXT_NewFileSelector(&timidity_cfg_path, 34, - "Select Timidity config file", - cfg_extension), - NULL)), -#ifdef HAVE_FLUIDSYNTH - TXT_NewRadioButton("FluidSynth", &snd_musicdevice, SNDDEVICE_FSYNTH), - TXT_NewConditional(&snd_musicdevice, SNDDEVICE_FSYNTH, - TXT_MakeTable(2, - TXT_NewStrut(4, 0), - TXT_NewLabel("Soundfont file: "), - TXT_NewStrut(4, 0), - TXT_NewFileSelector(&fsynth_sf_path, 34, - "Select FluidSynth soundfont file", - sf_extension), - NULL)), -#endif - NULL); -} - -void BindSoundVariables(void) -{ - M_BindIntVariable("snd_sfxdevice", &snd_sfxdevice); - M_BindIntVariable("snd_musicdevice", &snd_musicdevice); - M_BindIntVariable("snd_channels", &numChannels); - M_BindIntVariable("snd_samplerate", &snd_samplerate); - M_BindIntVariable("sfx_volume", &sfxVolume); - M_BindIntVariable("music_volume", &musicVolume); - - M_BindIntVariable("use_libsamplerate", &use_libsamplerate); - M_BindFloatVariable("libsamplerate_scale", &libsamplerate_scale); - - M_BindIntVariable("gus_ram_kb", &gus_ram_kb); - M_BindStringVariable("gus_patch_path", &gus_patch_path); - M_BindStringVariable("music_pack_path", &music_pack_path); - M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path); -#ifdef _WIN32 - M_BindStringVariable("winmm_midi_device", &winmm_midi_device); - M_BindIntVariable("winmm_complevel", &winmm_complevel); - M_BindIntVariable("winmm_reset_type", &winmm_reset_type); - M_BindIntVariable("winmm_reset_delay", &winmm_reset_delay); -#endif - -#ifdef HAVE_FLUIDSYNTH - M_BindIntVariable("fsynth_chorus_active", &fsynth_chorus_active); - M_BindFloatVariable("fsynth_chorus_depth", &fsynth_chorus_depth); - M_BindFloatVariable("fsynth_chorus_level", &fsynth_chorus_level); - M_BindIntVariable("fsynth_chorus_nr", &fsynth_chorus_nr); - M_BindFloatVariable("fsynth_chorus_speed", &fsynth_chorus_speed); - M_BindStringVariable("fsynth_midibankselect", &fsynth_midibankselect); - M_BindIntVariable("fsynth_polyphony", &fsynth_polyphony); - M_BindIntVariable("fsynth_reverb_active", &fsynth_reverb_active); - M_BindFloatVariable("fsynth_reverb_damp", &fsynth_reverb_damp); - M_BindFloatVariable("fsynth_reverb_level", &fsynth_reverb_level); - M_BindFloatVariable("fsynth_reverb_roomsize", &fsynth_reverb_roomsize); - M_BindFloatVariable("fsynth_reverb_width", &fsynth_reverb_width); - M_BindFloatVariable("fsynth_gain", &fsynth_gain); - M_BindStringVariable("fsynth_sf_path", &fsynth_sf_path); -#endif // HAVE_FLUIDSYNTH - - M_BindIntVariable("snd_sbport", &snd_sbport); - M_BindIntVariable("snd_sbirq", &snd_sbirq); - M_BindIntVariable("snd_sbdma", &snd_sbdma); - M_BindIntVariable("snd_mport", &snd_mport); - M_BindIntVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms); - M_BindStringVariable("snd_musiccmd", &snd_musiccmd); - M_BindStringVariable("snd_dmxoption", &snd_dmxoption); - - M_BindIntVariable("snd_cachesize", &snd_cachesize); - M_BindIntVariable("opl_io_port", &opl_io_port); - - M_BindIntVariable("snd_pitchshift", &snd_pitchshift); - - if (gamemission == strife) - { - M_BindIntVariable("voice_volume", &voiceVolume); - M_BindIntVariable("show_talk", &show_talk); - } - - music_pack_path = M_StringDuplicate(""); - timidity_cfg_path = M_StringDuplicate(""); - gus_patch_path = M_StringDuplicate(""); - -#ifdef _WIN32 - winmm_midi_device = M_StringDuplicate(""); -#endif - -#ifdef HAVE_FLUIDSYNTH - fsynth_sf_path = M_StringDuplicate(""); -#endif - - // All versions of Heretic and Hexen did pitch-shifting. - // Most versions of Doom did not and Strife never did. - snd_pitchshift = gamemission == heretic || gamemission == hexen; - - // Default sound volumes - different games use different values. - - switch (gamemission) - { - case doom: - default: - sfxVolume = 8; musicVolume = 8; - break; - case heretic: - case hexen: - sfxVolume = 10; musicVolume = 10; - break; - case strife: - sfxVolume = 8; musicVolume = 13; - break; - } -} - diff --git a/games/NXDoom/src/setup/sound.h b/games/NXDoom/src/setup/sound.h deleted file mode 100644 index a21570135b8..00000000000 --- a/games/NXDoom/src/setup/sound.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef SETUP_SOUND_H -#define SETUP_SOUND_H - -#include "i_sound.h" - -void ConfigSound(void *widget, void *user_data); -void BindSoundVariables(void); - - -#endif /* #ifndef SETUP_SOUND_H */ diff --git a/games/NXDoom/src/setup/txt_joyaxis.c b/games/NXDoom/src/setup/txt_joyaxis.c deleted file mode 100644 index 620c0bfa41e..00000000000 --- a/games/NXDoom/src/setup/txt_joyaxis.c +++ /dev/null @@ -1,654 +0,0 @@ -// -// Copyright(C) 2014 Simon Howard -// -// 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. -// - -#include -#include -#include - -#include "SDL.h" - -#include "joystick.h" -#include "i_joystick.h" -#include "i_system.h" -#include "m_controls.h" -#include "m_misc.h" - -#include "textscreen.h" -#include "txt_gui.h" -#include "txt_io.h" -#include "txt_joyaxis.h" -#include "txt_utf8.h" - -#define JOYSTICK_AXIS_WIDTH 20 - -static const char *CalibrationLabel(txt_joystick_axis_t *joystick_axis) -{ - switch (joystick_axis->config_stage) - { - case CONFIG_CENTER: - return "Center the D-pad or joystick,\n" - "and press a button."; - - case CONFIG_STAGE1: - if (joystick_axis->dir == JOYSTICK_AXIS_VERTICAL) - { - return "Push the D-pad or joystick up,\n" - "and press the button."; - } - else - { - return "Push the D-pad or joystick to the\n" - "left, and press the button."; - } - - case CONFIG_STAGE2: - if (joystick_axis->dir == JOYSTICK_AXIS_VERTICAL) - { - return "Push the D-pad or joystick down,\n" - "and press the button."; - } - else - { - return "Push the D-pad or joystick to the\n" - "right, and press the button."; - } - } - - return NULL; -} - -static void SetCalibrationLabel(txt_joystick_axis_t *joystick_axis) -{ - TXT_SetLabel(joystick_axis->config_label, CalibrationLabel(joystick_axis)); -} - -// Search all axes on joystick being configured; find a button that is -// pressed (other than the calibrate button). Returns the button number. - -static int FindPressedAxisButton(txt_joystick_axis_t *joystick_axis) -{ - int i; - - for (i = 0; i < SDL_JoystickNumButtons(joystick_axis->joystick); ++i) - { - if (i == joystick_axis->config_button) - { - continue; - } - - if (SDL_JoystickGetButton(joystick_axis->joystick, i)) - { - return i; - } - } - - return -1; -} - -// Look for a hat that isn't centered. Returns the encoded hat axis. - -static int FindUncenteredHat(SDL_Joystick *joystick, int *axis_invert) -{ - int i, hatval; - - for (i = 0; i < SDL_JoystickNumHats(joystick); ++i) - { - hatval = SDL_JoystickGetHat(joystick, i); - - switch (hatval) - { - case SDL_HAT_LEFT: - case SDL_HAT_RIGHT: - *axis_invert = hatval != SDL_HAT_LEFT; - return CREATE_HAT_AXIS(i, HAT_AXIS_HORIZONTAL); - - case SDL_HAT_UP: - case SDL_HAT_DOWN: - *axis_invert = hatval != SDL_HAT_UP; - return CREATE_HAT_AXIS(i, HAT_AXIS_VERTICAL); - - // If the hat is centered, or is not pointing in a - // definite direction, then ignore it. We don't accept - // the hat being pointed to the upper-left for example, - // because it's ambiguous. - case SDL_HAT_CENTERED: - default: - break; - } - } - - // None found. - return -1; -} - -static boolean CalibrateAxis(txt_joystick_axis_t *joystick_axis) -{ - int best_axis; - int best_value; - int best_invert; - Sint16 axis_value; - int i; - - // Check all axes to find which axis has the largest value. We test - // for one axis at a time, so eg. when we prompt to push the joystick - // left, whichever axis has the largest value is the left axis. - - best_axis = 0; - best_value = 0; - best_invert = 0; - - for (i = 0; i < SDL_JoystickNumAxes(joystick_axis->joystick); ++i) - { - axis_value = SDL_JoystickGetAxis(joystick_axis->joystick, i); - - if (joystick_axis->bad_axis[i]) - { - continue; - } - - if (abs(axis_value) > best_value) - { - best_value = abs(axis_value); - best_invert = axis_value > 0; - best_axis = i; - } - } - - // Did we find one axis that had a significant value? - - if (best_value > 32768 / 4) - { - // Save the best values we have found - - *joystick_axis->axis = best_axis; - *joystick_axis->invert = best_invert; - return true; - } - - // Otherwise, maybe this is a "button axis", like the PS3 SIXAXIS - // controller that exposes the D-pad as four individual buttons. - // Search for a button. - - i = FindPressedAxisButton(joystick_axis); - - if (i >= 0) - { - *joystick_axis->axis = CREATE_BUTTON_AXIS(i, 0); - *joystick_axis->invert = 0; - return true; - } - - // Maybe it's a D-pad that is presented as a hat. This sounds weird - // but gamepads like this really do exist; an example is the - // Nyko AIRFLO Ex. - - i = FindUncenteredHat(joystick_axis->joystick, joystick_axis->invert); - - if (i >= 0) - { - *joystick_axis->axis = i; - return true; - } - - // User pressed the button without pushing the joystick anywhere. - return false; -} - -static boolean SetButtonAxisPositive(txt_joystick_axis_t *joystick_axis) -{ - int button; - - button = FindPressedAxisButton(joystick_axis); - - if (button >= 0) - { - *joystick_axis->axis |= CREATE_BUTTON_AXIS(0, button); - return true; - } - - return false; -} - -static void IdentifyBadAxes(txt_joystick_axis_t *joystick_axis) -{ - int i, val; - - free(joystick_axis->bad_axis); - - joystick_axis->bad_axis - = calloc(SDL_JoystickNumAxes(joystick_axis->joystick), - sizeof(boolean)); - - // Look for uncentered axes. - - for (i = 0; i < SDL_JoystickNumAxes(joystick_axis->joystick); ++i) - { - val = SDL_JoystickGetAxis(joystick_axis->joystick, i); - - joystick_axis->bad_axis[i] = abs(val) > (32768 / 5); - - if (joystick_axis->bad_axis[i]) - { - printf("Ignoring uncentered joystick axis #%i: %i\n", i, val); - } - } -} - -static int NextCalibrateStage(txt_joystick_axis_t *joystick_axis) -{ - switch (joystick_axis->config_stage) - { - case CONFIG_CENTER: - return CONFIG_STAGE1; - - // After pushing to the left, there are two possibilities: - // either it is a button axis, in which case we need to find - // the other button, or we can just move on to the next axis. - case CONFIG_STAGE1: - if (IS_BUTTON_AXIS(*joystick_axis->axis)) - { - return CONFIG_STAGE2; - } - else - { - return CONFIG_CENTER; - } - - case CONFIG_STAGE2: - return CONFIG_CENTER; - } - - return -1; -} - -static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_axis)) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - boolean advance; - - if (event->type != SDL_JOYBUTTONDOWN) - { - return 0; - } - - // At this point, we have a button press. - // In the first "center" stage, we're just trying to work out which - // joystick is being configured and which button the user is pressing. - if (joystick_axis->config_stage == CONFIG_CENTER) - { - joystick_axis->config_button = event->jbutton.button; - IdentifyBadAxes(joystick_axis); - - // Advance to next stage. - joystick_axis->config_stage = CONFIG_STAGE1; - SetCalibrationLabel(joystick_axis); - - return 1; - } - - // In subsequent stages, the user is asked to push in a specific - // direction and press the button. They must push the same button - // as they did before; this is necessary to support button axes. - if (event->jbutton.which == SDL_JoystickInstanceID(joystick_axis->joystick) - && event->jbutton.button == joystick_axis->config_button) - { - switch (joystick_axis->config_stage) - { - default: - case CONFIG_STAGE1: - advance = CalibrateAxis(joystick_axis); - break; - - case CONFIG_STAGE2: - advance = SetButtonAxisPositive(joystick_axis); - break; - } - - // Advance to the next calibration stage? - - if (advance) - { - joystick_axis->config_stage = NextCalibrateStage(joystick_axis); - SetCalibrationLabel(joystick_axis); - - // Finished? - if (joystick_axis->config_stage == CONFIG_CENTER) - { - TXT_CloseWindow(joystick_axis->config_window); - - if (joystick_axis->callback != NULL) - { - joystick_axis->callback(); - } - } - - return 1; - } - } - - return 0; -} - -static void CalibrateWindowClosed(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(joystick_axis)) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - - free(joystick_axis->bad_axis); - joystick_axis->bad_axis = NULL; - - SDL_JoystickClose(joystick_axis->joystick); - SDL_JoystickEventState(SDL_DISABLE); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - TXT_SDL_SetEventCallback(NULL, NULL); -} - -void TXT_ConfigureJoystickAxis(txt_joystick_axis_t *joystick_axis, - int using_button, - txt_joystick_axis_callback_t callback) -{ - // Open the joystick first. - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) - { - return; - } - - joystick_axis->joystick = SDL_JoystickOpen(joystick_index); - if (joystick_axis->joystick == NULL) - { - TXT_MessageBox(NULL, "Please configure a controller first!"); - return; - } - - SDL_JoystickEventState(SDL_ENABLE); - - // Build the prompt window. - - joystick_axis->config_window - = TXT_NewWindow("Gamepad/Joystick calibration"); - TXT_AddWidgets(joystick_axis->config_window, - TXT_NewStrut(0, 1), - joystick_axis->config_label = TXT_NewLabel(""), - TXT_NewStrut(0, 1), - NULL); - - TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_CENTER, - TXT_NewWindowAbortAction(joystick_axis->config_window)); - TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_RIGHT, NULL); - TXT_SetWidgetAlign(joystick_axis->config_window, TXT_HORIZ_CENTER); - - if (using_button >= 0) - { - joystick_axis->config_stage = CONFIG_STAGE1; - joystick_axis->config_button = using_button; - IdentifyBadAxes(joystick_axis); - } - else - { - joystick_axis->config_stage = CONFIG_CENTER; - } - - SetCalibrationLabel(joystick_axis); - - // Close the joystick and shut down joystick subsystem when the window - // is closed. - TXT_SignalConnect(joystick_axis->config_window, "closed", - CalibrateWindowClosed, joystick_axis); - - TXT_SDL_SetEventCallback(EventCallback, joystick_axis); - - // When successfully calibrated, invoke this callback: - joystick_axis->callback = callback; -} - -void TXT_ConfigureGamepadAxis(txt_joystick_axis_t *joystick_axis, - int using_button, - txt_joystick_axis_callback_t callback) -{ - // Build the prompt window. - - joystick_axis->config_window = TXT_NewWindow("Configure axis"); - TXT_SetTableColumns(joystick_axis->config_window, 2); - TXT_SetColumnWidths(joystick_axis->config_window, 10, 5); - TXT_AddWidgets(joystick_axis->config_window, - TXT_NewCheckBox("Invert", joystick_axis->invert), - TXT_TABLE_EMPTY, - TXT_NewLabel("Dead zone"), - TXT_NewSpinControl(joystick_axis->dead_zone, 10, 90), - NULL); - - TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_LEFT, NULL); - TXT_SetWindowAction( - joystick_axis->config_window, TXT_HORIZ_CENTER, - TXT_NewWindowEscapeAction(joystick_axis->config_window)); - TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_RIGHT, NULL); - TXT_SetWidgetAlign(joystick_axis->config_window, TXT_HORIZ_CENTER); -} - -static void TXT_JoystickAxisSizeCalc(TXT_UNCAST_ARG(joystick_axis)) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - - // All joystickinputs are the same size. - - joystick_axis->widget.w = JOYSTICK_AXIS_WIDTH; - joystick_axis->widget.h = 1; -} - -static void TXT_JoystickAxisDrawer(TXT_UNCAST_ARG(joystick_axis)) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - char buf[JOYSTICK_AXIS_WIDTH + 1]; - int i; - - if (*joystick_axis->axis < 0) - { - M_StringCopy(buf, "(none)", sizeof(buf)); - } - else if (IS_BUTTON_AXIS(*joystick_axis->axis)) - { - int neg, pos; - - neg = BUTTON_AXIS_NEG(*joystick_axis->axis); - pos = BUTTON_AXIS_POS(*joystick_axis->axis); - M_snprintf(buf, sizeof(buf), "BUTTONS #%i+#%i", neg, pos); - } - else if (IS_HAT_AXIS(*joystick_axis->axis)) - { - int hat, dir; - - hat = HAT_AXIS_HAT(*joystick_axis->axis); - dir = HAT_AXIS_DIRECTION(*joystick_axis->axis); - - M_snprintf(buf, sizeof(buf), "HAT #%i (%s)", hat, - dir == HAT_AXIS_HORIZONTAL ? "horizontal" : "vertical"); - } - else - { - M_snprintf(buf, sizeof(buf), "AXIS #%i", *joystick_axis->axis); - } - - TXT_SetWidgetBG(joystick_axis); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_DrawString(buf); - - for (i = TXT_UTF8_Strlen(buf); i < joystick_axis->widget.w; ++i) - { - TXT_DrawString(" "); - } -} - -static void GetAxisDescription(int axis, char *buf, size_t buf_len) -{ - switch (axis) - { - case SDL_CONTROLLER_AXIS_INVALID: - M_StringCopy(buf, "(none)", sizeof(buf)); - break; - - case SDL_CONTROLLER_AXIS_LEFTX: - M_StringCopy(buf, "Left X", sizeof(buf)); - break; - - case SDL_CONTROLLER_AXIS_LEFTY: - M_StringCopy(buf, "Left Y", sizeof(buf)); - break; - - case SDL_CONTROLLER_AXIS_RIGHTX: - M_StringCopy(buf, "Right X", sizeof(buf)); - break; - - case SDL_CONTROLLER_AXIS_RIGHTY: - M_StringCopy(buf, "Right Y", sizeof(buf)); - break; - - default: - M_StringCopy(buf, "(unknown)", sizeof(buf)); - break; - } -} - -static void TXT_GamepadAxisDrawer(TXT_UNCAST_ARG(joystick_axis)) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - char buf[JOYSTICK_AXIS_WIDTH + 1]; - int i; - - GetAxisDescription(*joystick_axis->axis, buf, sizeof(buf)); - - TXT_SetWidgetBG(joystick_axis); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_DrawString(buf); - - for (i = TXT_UTF8_Strlen(buf); i < joystick_axis->widget.w; ++i) - { - TXT_DrawString(" "); - } -} - -static void TXT_JoystickAxisDestructor(TXT_UNCAST_ARG(joystick_axis)) -{ -} - -static int TXT_JoystickAxisKeyPress(TXT_UNCAST_ARG(joystick_axis), int key) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - - if (key == KEY_ENTER) - { - TXT_ConfigureJoystickAxis(joystick_axis, -1, NULL); - return 1; - } - - if (key == KEY_BACKSPACE || key == KEY_DEL) - { - *joystick_axis->axis = -1; - } - - return 0; -} - -static int TXT_GamepadAxisKeyPress(TXT_UNCAST_ARG(joystick_axis), int key) -{ - TXT_CAST_ARG(txt_joystick_axis_t, joystick_axis); - - if (key == KEY_ENTER) - { - TXT_ConfigureGamepadAxis(joystick_axis, -1, NULL); - return 1; - } - - if (key == KEY_BACKSPACE || key == KEY_DEL) - { - *joystick_axis->axis = -1; - } - - return 0; -} - -static void TXT_JoystickAxisMousePress(TXT_UNCAST_ARG(widget), - int x, int y, int b) -{ - TXT_CAST_ARG(txt_joystick_axis_t, widget); - - // Clicking is like pressing enter - - if (b == TXT_MOUSE_LEFT) - { - TXT_JoystickAxisKeyPress(widget, KEY_ENTER); - } -} - -static void TXT_GamepadAxisMousePress(TXT_UNCAST_ARG(widget), int x, int y, - int b) -{ - TXT_CAST_ARG(txt_joystick_axis_t, widget); - - // Clicking is like pressing enter - - if (b == TXT_MOUSE_LEFT) - { - TXT_GamepadAxisKeyPress(widget, KEY_ENTER); - } -} - -txt_widget_class_t txt_joystick_axis_class = -{ - TXT_AlwaysSelectable, - TXT_JoystickAxisSizeCalc, - TXT_JoystickAxisDrawer, - TXT_JoystickAxisKeyPress, - TXT_JoystickAxisDestructor, - TXT_JoystickAxisMousePress, - NULL, -}; - -txt_widget_class_t txt_gamepad_axis_class = -{ - TXT_AlwaysSelectable, - TXT_JoystickAxisSizeCalc, - TXT_GamepadAxisDrawer, - TXT_GamepadAxisKeyPress, - TXT_JoystickAxisDestructor, - TXT_GamepadAxisMousePress, - NULL, -}; - -txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert, int *dead_zone, - txt_joystick_axis_direction_t dir) -{ - txt_joystick_axis_t *joystick_axis; - - joystick_axis = malloc(sizeof(txt_joystick_axis_t)); - - if (use_gamepad) - { - TXT_InitWidget(joystick_axis, &txt_gamepad_axis_class); - } - else - { - TXT_InitWidget(joystick_axis, &txt_joystick_axis_class); - } - joystick_axis->axis = axis; - joystick_axis->invert = invert; - joystick_axis->dead_zone = dead_zone; - joystick_axis->dir = dir; - joystick_axis->bad_axis = NULL; - - return joystick_axis; -} - diff --git a/games/NXDoom/src/setup/txt_joyaxis.h b/games/NXDoom/src/setup/txt_joyaxis.h deleted file mode 100644 index f0527c5b106..00000000000 --- a/games/NXDoom/src/setup/txt_joyaxis.h +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef TXT_JOY_AXIS_H -#define TXT_JOY_AXIS_H - -typedef struct txt_joystick_axis_s txt_joystick_axis_t; - -typedef enum -{ - JOYSTICK_AXIS_HORIZONTAL, - JOYSTICK_AXIS_VERTICAL, -} txt_joystick_axis_direction_t; - -typedef enum -{ - CONFIG_CENTER, // "Center the joystick and press a button..." - CONFIG_STAGE1, // "Top or left and press a button..." - CONFIG_STAGE2, // [Optional] "Bottom or right and press a button..." -} txt_joystick_axis_stage_t; - -// Callback invoked when calibration is completed. -typedef void (*txt_joystick_axis_callback_t)(void); - -#include "txt_widget.h" -#include "txt_window.h" - -#include "SDL.h" - -// -// A joystick axis. -// - -struct txt_joystick_axis_s -{ - txt_widget_t widget; - int *axis, *invert, *dead_zone; - txt_joystick_axis_direction_t dir; - - // Only used when configuring: - - // Configuration prompt window and label. - txt_window_t *config_window; - txt_label_t *config_label; - - // SDL joystick handle for reading joystick state. - SDL_Joystick *joystick; - - // "Bad" joystick axes. Sometimes an axis can be stuck or "bad". An - // example I found is that if you unplug the nunchuck extension from - // a Wii remote, the axes from the nunchuck can be stuck at one of - // the maximum values. These have to be ignored, so when we ask the - // user to center the joystick, we look for bad axes that are not - // close to zero. - boolean *bad_axis; - - // Stage we have reached in configuring joystick axis. - txt_joystick_axis_stage_t config_stage; - - // Button to press to advance to next stage. - int config_button; - - // Callback invoked when the axis is calibrated. - txt_joystick_axis_callback_t callback; -}; - -txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert, int *dead_zone, - txt_joystick_axis_direction_t dir); - -// Configure a joystick axis widget. -// axis: The axis widget to configure. -// using_button: If non-negative, use this joystick button as the button -// to expect from the user. Otherwise, ask. -void TXT_ConfigureJoystickAxis(txt_joystick_axis_t *axis, int using_button, - txt_joystick_axis_callback_t callback); - -#endif /* #ifndef TXT_JOY_AXIS_H */ - - diff --git a/games/NXDoom/src/setup/txt_joybinput.c b/games/NXDoom/src/setup/txt_joybinput.c deleted file mode 100644 index a4362e34019..00000000000 --- a/games/NXDoom/src/setup/txt_joybinput.c +++ /dev/null @@ -1,780 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include -#include - -#include "SDL_joystick.h" -#include "SDL_gamecontroller.h" - -#include "doomkeys.h" -#include "joystick.h" -#include "i_joystick.h" -#include "i_system.h" -#include "m_controls.h" -#include "m_misc.h" - -#include "txt_joybinput.h" -#include "txt_gui.h" -#include "txt_io.h" -#include "txt_label.h" -#include "txt_sdl.h" -#include "txt_utf8.h" -#include "txt_window.h" - -#define JOYSTICK_INPUT_WIDTH 10 - - -// Joystick button variables. -// The ordering of this array is important. We will always try to map -// each variable to the virtual button with the same array index. For -// example: joybfire should always be 0, and then we change -// joystick_physical_buttons[0] to point to the physical joystick -// button that the user wants to use for firing. We do this so that -// the menus work (the game code is hard coded to interpret -// button #0 = select menu item, button #1 = go back to previous menu). -static int *all_joystick_buttons[NUM_VIRTUAL_BUTTONS] = -{ - &joybfire, - &joybuse, - &joybstrafe, - &joybspeed, - &joybstrafeleft, - &joybstraferight, - &joybprevweapon, - &joybnextweapon, - &joybjump, - &joybmenu, - &joybautomap, - &joybuseartifact, - &joybinvleft, - &joybinvright, - &joybflyup, - &joybflydown, - &joybflycenter, -}; - -// For indirection so that we're not dependent on item ordering in the -// SDL_GameControllerButton enum. -static const int gamepad_buttons[GAMEPAD_BUTTON_MAX] = -{ - SDL_CONTROLLER_BUTTON_A, - SDL_CONTROLLER_BUTTON_B, - SDL_CONTROLLER_BUTTON_X, - SDL_CONTROLLER_BUTTON_Y, - SDL_CONTROLLER_BUTTON_BACK, - SDL_CONTROLLER_BUTTON_GUIDE, - SDL_CONTROLLER_BUTTON_START, - SDL_CONTROLLER_BUTTON_LEFTSTICK, - SDL_CONTROLLER_BUTTON_RIGHTSTICK, - SDL_CONTROLLER_BUTTON_LEFTSHOULDER, - SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, - SDL_CONTROLLER_BUTTON_DPAD_UP, - SDL_CONTROLLER_BUTTON_DPAD_DOWN, - SDL_CONTROLLER_BUTTON_DPAD_LEFT, - SDL_CONTROLLER_BUTTON_DPAD_RIGHT, - SDL_CONTROLLER_BUTTON_MISC1, - SDL_CONTROLLER_BUTTON_PADDLE1, - SDL_CONTROLLER_BUTTON_PADDLE2, - SDL_CONTROLLER_BUTTON_PADDLE3, - SDL_CONTROLLER_BUTTON_PADDLE4, - SDL_CONTROLLER_BUTTON_TOUCHPAD, - GAMEPAD_BUTTON_TRIGGERLEFT, - GAMEPAD_BUTTON_TRIGGERRIGHT, -}; - -// Items in the following button lists are ordered according to gamepad_buttons -// above. -static const char *xbox360_buttons[GAMEPAD_BUTTON_MAX] = -{ - "A", - "B", - "X", - "Y", - "BACK", - "GUIDE", - "START", - "LSB", - "RSB", - "LB", - "RB", - "DPAD U", - "DPAD D", - "DPAD L", - "DPAD R", - "", - "", - "", - "", - "", - "", - "LT", - "RT", -}; - -static const char *xboxone_buttons[GAMEPAD_BUTTON_MAX] = -{ - "A", - "B", - "X", - "Y", - "VIEW", - "XBOX", - "MENU", - "LSB", - "RSB", - "LB", - "RB", - "DPAD U", - "DPAD D", - "DPAD L", - "DPAD R", - "PROFILE", - "P1", - "P2", - "P3", - "P4", - "", - "LT", - "RT", -}; - -static const char *ps3_buttons[GAMEPAD_BUTTON_MAX] = -{ - "X", - "CIRCLE", - "SQUARE", - "TRIANGLE", - "SELECT", - "PS", - "START", - "L3", - "R3", - "L1", - "R1", - "DPAD U", - "DPAD D", - "DPAD L", - "DPAD R", - "", - "", - "", - "", - "", - "", - "L2", - "R2", -}; - -static const char *ps4_buttons[GAMEPAD_BUTTON_MAX] = -{ - "X", - "CIRCLE", - "SQUARE", - "TRIANGLE", - "SHARE", - "PS", - "OPTIONS", - "L3", - "R3", - "L1", - "R1", - "DPAD U", - "DPAD D", - "DPAD L", - "DPAD R", - "", - "", - "", - "", - "", - "TOUCH", - "L2", - "R2", -}; - -static const char *ps5_buttons[GAMEPAD_BUTTON_MAX] = -{ - "X", - "CIRCLE", - "SQUARE", - "TRIANGLE", - "SHARE", - "PS", - "OPTIONS", - "L3", - "R3", - "L1", - "R1", - "DPAD U", - "DPAD D", - "DPAD L", - "DPAD R", - "MUTE", - "", - "", - "", - "", - "TOUCH", - "L2", - "R2", -}; - -static const char *switchpro_buttons[GAMEPAD_BUTTON_MAX] = -{ - "B", - "A", - "Y", - "X", - "MINUS", - "HOME", - "PLUS", - "LSB", - "RSB", - "L", - "R", - "DPAD U", - "DPAD D", - "DPAD L", - "DPAD R", - "CAPTURE", - "", - "", - "", - "", - "", - "ZL", - "ZR", -}; - -static int PhysicalForVirtualButton(int vbutton) -{ - if (vbutton < NUM_VIRTUAL_BUTTONS) - { - return joystick_physical_buttons[vbutton]; - } - else - { - return vbutton; - } -} - -// Get the virtual button number for the given variable, ie. the -// variable's index in all_joystick_buttons[NUM_VIRTUAL_BUTTONS]. -static int VirtualButtonForVariable(int *variable) -{ - int i; - - for (i = 0; i < arrlen(all_joystick_buttons); ++i) - { - if (variable == all_joystick_buttons[i]) - { - return i; - } - } - - I_Error("Couldn't find virtual button"); - return -1; -} - -// Rearrange joystick button configuration to be in "canonical" form: -// each joyb* variable should have a value equal to its index in -// all_joystick_buttons[NUM_VIRTUAL_BUTTONS] above. -static void CanonicalizeButtons(void) -{ - int new_mapping[NUM_VIRTUAL_BUTTONS]; - int vbutton; - int i; - - for (i = 0; i < arrlen(all_joystick_buttons); ++i) - { - vbutton = *all_joystick_buttons[i]; - - // Don't remap the speed key if it's bound to "always run". - // Also preserve "unbound" variables. - if ((all_joystick_buttons[i] == &joybspeed && - vbutton >= MAX_VIRTUAL_BUTTONS) || - vbutton < 0) - { - new_mapping[i] = i; - } - else - { - new_mapping[i] = PhysicalForVirtualButton(vbutton); - *all_joystick_buttons[i] = i; - } - } - - for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i) - { - joystick_physical_buttons[i] = new_mapping[i]; - } -} - -// Check all existing buttons and clear any using the specified physical -// button. -static void ClearVariablesUsingButton(int physbutton) -{ - int vbutton; - int i; - - for (i = 0; i < arrlen(all_joystick_buttons); ++i) - { - vbutton = *all_joystick_buttons[i]; - - if (vbutton >= 0 && physbutton == PhysicalForVirtualButton(vbutton)) - { - *all_joystick_buttons[i] = -1; - } - } -} - -// Called in response to SDL events when the prompt window is open: - -static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_input)) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - - // Got the joystick button press? - - if (event->type == SDL_JOYBUTTONDOWN) - { - int vbutton, physbutton; - - // Before changing anything, remap button configuration into - // canonical form, to avoid conflicts. - CanonicalizeButtons(); - - vbutton = VirtualButtonForVariable(joystick_input->variable); - physbutton = event->jbutton.button; - - if (joystick_input->check_conflicts) - { - ClearVariablesUsingButton(physbutton); - } - - // Set mapping. - *joystick_input->variable = vbutton; - joystick_physical_buttons[vbutton] = physbutton; - - TXT_CloseWindow(joystick_input->prompt_window); - return 1; - } - - return 0; -} - -static int EventCallbackGamepad(SDL_Event *event, - TXT_UNCAST_ARG(joystick_input)) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - - // Got the joystick button press? - - if (event->type == SDL_CONTROLLERBUTTONDOWN || - event->type == SDL_CONTROLLERAXISMOTION) - { - int vbutton, physbutton, axis; - - // Before changing anything, remap button configuration into - // canonical form, to avoid conflicts. - CanonicalizeButtons(); - - vbutton = VirtualButtonForVariable(joystick_input->variable); - axis = event->caxis.axis; - - if (event->type == SDL_CONTROLLERAXISMOTION && - (axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT || - axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) && - event->caxis.value > TRIGGER_THRESHOLD) - { - if (axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) - { - physbutton = GAMEPAD_BUTTON_TRIGGERLEFT; - } - else - { - physbutton = GAMEPAD_BUTTON_TRIGGERRIGHT; - } - } - else if (event->type == SDL_CONTROLLERBUTTONDOWN) - { - physbutton = event->cbutton.button; - } - else - { - return 0; - } - - if (joystick_input->check_conflicts) - { - ClearVariablesUsingButton(physbutton); - } - - // Set mapping. - *joystick_input->variable = vbutton; - joystick_physical_buttons[vbutton] = physbutton; - - TXT_CloseWindow(joystick_input->prompt_window); - return 1; - } - - return 0; -} - -// When the prompt window is closed, disable the event callback function; -// we are no longer interested in receiving notification of events. - -static void PromptWindowClosed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(joystick)) -{ - TXT_CAST_ARG(SDL_Joystick, joystick); - - SDL_JoystickClose(joystick); - TXT_SDL_SetEventCallback(NULL, NULL); - SDL_JoystickEventState(SDL_DISABLE); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); -} - -static void PromptWindowClosedGamepad(TXT_UNCAST_ARG(widget), - TXT_UNCAST_ARG(joystick)) -{ - TXT_CAST_ARG(SDL_GameController, joystick); - - SDL_GameControllerClose(joystick); - TXT_SDL_SetEventCallback(NULL, NULL); - SDL_JoystickEventState(SDL_DISABLE); - SDL_GameControllerEventState(SDL_DISABLE); - SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); -} - -static void OpenErrorWindow(void) -{ - TXT_MessageBox(NULL, "Please configure a controller first!"); -} - -static void OpenPromptWindow(txt_joystick_input_t *joystick_input) -{ - txt_window_t *window; - SDL_Joystick *joystick; - - // Silently update when the shift button is held down. - - joystick_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); - - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) - { - return; - } - - // Check the current joystick is valid - - joystick = SDL_JoystickOpen(joystick_index); - - if (joystick == NULL) - { - OpenErrorWindow(); - return; - } - - // Open the prompt window - - window = TXT_MessageBox(NULL, "Press the new button on the controller..."); - - TXT_SDL_SetEventCallback(EventCallback, joystick_input); - TXT_SignalConnect(window, "closed", PromptWindowClosed, joystick); - joystick_input->prompt_window = window; - - SDL_JoystickEventState(SDL_ENABLE); -} - -static void OpenPromptWindowGamepad(txt_joystick_input_t *joystick_input) -{ - txt_window_t *window; - SDL_GameController *gamepad; - - // Silently update when the shift button is held down. - - joystick_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); - - if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) - { - return; - } - - // Check the current joystick is valid - - gamepad = SDL_GameControllerOpen(joystick_index); - - if (gamepad == NULL) - { - OpenErrorWindow(); - return; - } - - // Open the prompt window - - window = TXT_MessageBox(NULL, "Press the new button on the controller..."); - - TXT_SDL_SetEventCallback(EventCallbackGamepad, joystick_input); - TXT_SignalConnect(window, "closed", PromptWindowClosedGamepad, gamepad); - joystick_input->prompt_window = window; - - // GameController events do not fire if Joystick events are disabled. - SDL_JoystickEventState(SDL_ENABLE); - SDL_GameControllerEventState(SDL_ENABLE); -} - -static void TXT_JoystickInputSizeCalc(TXT_UNCAST_ARG(joystick_input)) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - - // All joystickinputs are the same size. - - joystick_input->widget.w = JOYSTICK_INPUT_WIDTH; - joystick_input->widget.h = 1; -} - -static void GetJoystickButtonDescription(int vbutton, char *buf, - size_t buf_len) -{ - M_snprintf(buf, buf_len, "BUTTON #%i", - PhysicalForVirtualButton(vbutton) + 1); -} - -static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input)) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - char buf[20]; - int i; - - if (*joystick_input->variable < 0) - { - M_StringCopy(buf, "(none)", sizeof(buf)); - } - else - { - GetJoystickButtonDescription(*joystick_input->variable, - buf, sizeof(buf)); - } - - TXT_SetWidgetBG(joystick_input); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_DrawString(buf); - - for (i = TXT_UTF8_Strlen(buf); i < JOYSTICK_INPUT_WIDTH; ++i) - { - TXT_DrawString(" "); - } -} - -static int GetGamepadButtonIndex(int button) -{ - int i; - - for (i = 0; i < arrlen(gamepad_buttons); ++i) - { - if (button == gamepad_buttons[i]) - { - return i; - } - } - - return -1; -} - -static void GetGamepadButtonDescription(int vbutton, char *buf, size_t buf_len) -{ - int index; - - index = GetGamepadButtonIndex(PhysicalForVirtualButton(vbutton)); - - if (index < 0) - { - M_StringCopy(buf, "(unknown)", buf_len); - return; - } - - switch (gamepad_type) - { - case SDL_CONTROLLER_TYPE_XBOX360: - M_snprintf(buf, buf_len, "%s", xbox360_buttons[index]); - break; - - case SDL_CONTROLLER_TYPE_XBOXONE: - M_snprintf(buf, buf_len, "%s", xboxone_buttons[index]); - break; - - case SDL_CONTROLLER_TYPE_PS3: - M_snprintf(buf, buf_len, "%s", ps3_buttons[index]); - break; - - case SDL_CONTROLLER_TYPE_PS4: - M_snprintf(buf, buf_len, "%s", ps4_buttons[index]); - break; - - case SDL_CONTROLLER_TYPE_PS5: - M_snprintf(buf, buf_len, "%s", ps5_buttons[index]); - break; - - case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: - M_snprintf(buf, buf_len, "%s", switchpro_buttons[index]); - break; - - default: - M_snprintf(buf, buf_len, "BUTTON #%i", - PhysicalForVirtualButton(vbutton) + 1); - break; - } -} - -static void TXT_GamepadInputDrawer(TXT_UNCAST_ARG(joystick_input)) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - char buf[20]; // Need to fit "BUTTON #XX" - int i; - - if (*joystick_input->variable < 0) - { - M_StringCopy(buf, "(none)", sizeof(buf)); - } - else - { - GetGamepadButtonDescription(*joystick_input->variable, buf, - sizeof(buf)); - } - - TXT_SetWidgetBG(joystick_input); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_DrawString(buf); - - for (i = TXT_UTF8_Strlen(buf); i < JOYSTICK_INPUT_WIDTH; ++i) - { - TXT_DrawString(" "); - } -} - -static void TXT_JoystickInputDestructor(TXT_UNCAST_ARG(joystick_input)) -{ -} - -static int TXT_JoystickInputKeyPress(TXT_UNCAST_ARG(joystick_input), int key) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - - if (key == KEY_ENTER) - { - // Open a window to prompt for the new joystick press - OpenPromptWindow(joystick_input); - - return 1; - } - - if (key == KEY_BACKSPACE || key == KEY_DEL) - { - *joystick_input->variable = -1; - } - - return 0; -} - -static int TXT_GamepadInputKeyPress(TXT_UNCAST_ARG(joystick_input), int key) -{ - TXT_CAST_ARG(txt_joystick_input_t, joystick_input); - - if (key == KEY_ENTER) - { - // Open a window to prompt for the new joystick press - OpenPromptWindowGamepad(joystick_input); - - return 1; - } - - if (key == KEY_BACKSPACE || key == KEY_DEL) - { - *joystick_input->variable = -1; - } - - return 0; -} - -static void TXT_JoystickInputMousePress(TXT_UNCAST_ARG(widget), - int x, int y, int b) -{ - TXT_CAST_ARG(txt_joystick_input_t, widget); - - // Clicking is like pressing enter - - if (b == TXT_MOUSE_LEFT) - { - TXT_JoystickInputKeyPress(widget, KEY_ENTER); - } -} - -static void TXT_GamepadInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, - int b) -{ - TXT_CAST_ARG(txt_joystick_input_t, widget); - - // Clicking is like pressing enter - - if (b == TXT_MOUSE_LEFT) - { - TXT_GamepadInputKeyPress(widget, KEY_ENTER); - } -} - -txt_widget_class_t txt_joystick_input_class = -{ - TXT_AlwaysSelectable, - TXT_JoystickInputSizeCalc, - TXT_JoystickInputDrawer, - TXT_JoystickInputKeyPress, - TXT_JoystickInputDestructor, - TXT_JoystickInputMousePress, - NULL, -}; - -txt_widget_class_t txt_gamepad_input_class = -{ - TXT_AlwaysSelectable, - TXT_JoystickInputSizeCalc, - TXT_GamepadInputDrawer, - TXT_GamepadInputKeyPress, - TXT_JoystickInputDestructor, - TXT_GamepadInputMousePress, - NULL, -}; - -txt_joystick_input_t *TXT_NewJoystickInput(int *variable) -{ - txt_joystick_input_t *joystick_input; - - joystick_input = malloc(sizeof(txt_joystick_input_t)); - - if (use_gamepad) - { - TXT_InitWidget(joystick_input, &txt_gamepad_input_class); - } - else - { - TXT_InitWidget(joystick_input, &txt_joystick_input_class); - } - joystick_input->variable = variable; - - return joystick_input; -} - diff --git a/games/NXDoom/src/setup/txt_joybinput.h b/games/NXDoom/src/setup/txt_joybinput.h deleted file mode 100644 index 26a9f24c320..00000000000 --- a/games/NXDoom/src/setup/txt_joybinput.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef TXT_JOYB_INPUT_H -#define TXT_JOYB_INPUT_H - -typedef struct txt_joystick_input_s txt_joystick_input_t; - -#include "txt_widget.h" -#include "txt_window.h" - -// -// A joystick input is like an input box. When selected, a box pops up -// allowing a joystick button to be pressed to select it. -// - -struct txt_joystick_input_s -{ - txt_widget_t widget; - int *variable; - txt_window_t *prompt_window; - int check_conflicts; -}; - -txt_joystick_input_t *TXT_NewJoystickInput(int *variable); - -#endif /* #ifndef TXT_JOYB_INPUT_H */ - - diff --git a/games/NXDoom/src/setup/txt_keyinput.c b/games/NXDoom/src/setup/txt_keyinput.c deleted file mode 100644 index 6c3b35917d0..00000000000 --- a/games/NXDoom/src/setup/txt_keyinput.c +++ /dev/null @@ -1,185 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include - -#include "doomkeys.h" -#include "m_misc.h" - -#include "txt_keyinput.h" -#include "txt_gui.h" -#include "txt_io.h" -#include "txt_label.h" -#include "txt_utf8.h" -#include "txt_window.h" - -#define KEY_INPUT_WIDTH 8 - -static int KeyPressCallback(txt_window_t *window, int key, - TXT_UNCAST_ARG(key_input)) -{ - TXT_CAST_ARG(txt_key_input_t, key_input); - - if (key != KEY_ESCAPE) - { - // Got the key press. Save to the variable and close the window. - - *key_input->variable = key; - - if (key_input->check_conflicts) - { - TXT_EmitSignal(key_input, "set"); - } - - TXT_CloseWindow(window); - - // Return to normal input mode now that we have the key. - TXT_SetInputMode(TXT_INPUT_NORMAL); - - return 1; - } - else - { - return 0; - } -} - -static void ReleaseGrab(TXT_UNCAST_ARG(window), TXT_UNCAST_ARG(unused)) -{ - // SDL2-TODO: Needed? - // SDL_WM_GrabInput(SDL_GRAB_OFF); -} - -static void OpenPromptWindow(txt_key_input_t *key_input) -{ - txt_window_t *window; - - // Silently update when the shift button is held down. - - key_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); - - window = TXT_MessageBox(NULL, "Press the new key..."); - - TXT_SetKeyListener(window, KeyPressCallback, key_input); - - // Switch to raw input mode while we're grabbing the key. - TXT_SetInputMode(TXT_INPUT_RAW); - - // Grab input while reading the key. On Windows Mobile - // handheld devices, the hardware keypresses are only - // detected when input is grabbed. - - // SDL2-TODO: Needed? - //SDL_WM_GrabInput(SDL_GRAB_ON); - TXT_SignalConnect(window, "closed", ReleaseGrab, NULL); -} - -static void TXT_KeyInputSizeCalc(TXT_UNCAST_ARG(key_input)) -{ - TXT_CAST_ARG(txt_key_input_t, key_input); - - // All keyinputs are the same size. - - key_input->widget.w = KEY_INPUT_WIDTH; - key_input->widget.h = 1; -} - - -static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input)) -{ - TXT_CAST_ARG(txt_key_input_t, key_input); - char buf[20]; - int i; - - if (*key_input->variable == 0) - { - M_StringCopy(buf, "(none)", sizeof(buf)); - } - else - { - TXT_GetKeyDescription(*key_input->variable, buf, sizeof(buf)); - } - - TXT_SetWidgetBG(key_input); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_DrawString(buf); - - for (i = TXT_UTF8_Strlen(buf); i < KEY_INPUT_WIDTH; ++i) - { - TXT_DrawString(" "); - } -} - -static void TXT_KeyInputDestructor(TXT_UNCAST_ARG(key_input)) -{ -} - -static int TXT_KeyInputKeyPress(TXT_UNCAST_ARG(key_input), int key) -{ - TXT_CAST_ARG(txt_key_input_t, key_input); - - if (key == KEY_ENTER) - { - // Open a window to prompt for the new key press - - OpenPromptWindow(key_input); - - return 1; - } - - if (key == KEY_BACKSPACE || key == KEY_DEL) - { - *key_input->variable = 0; - } - - return 0; -} - -static void TXT_KeyInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) -{ - TXT_CAST_ARG(txt_key_input_t, widget); - - // Clicking is like pressing enter - - if (b == TXT_MOUSE_LEFT) - { - TXT_KeyInputKeyPress(widget, KEY_ENTER); - } -} - -txt_widget_class_t txt_key_input_class = -{ - TXT_AlwaysSelectable, - TXT_KeyInputSizeCalc, - TXT_KeyInputDrawer, - TXT_KeyInputKeyPress, - TXT_KeyInputDestructor, - TXT_KeyInputMousePress, - NULL, -}; - -txt_key_input_t *TXT_NewKeyInput(int *variable) -{ - txt_key_input_t *key_input; - - key_input = malloc(sizeof(txt_key_input_t)); - - TXT_InitWidget(key_input, &txt_key_input_class); - key_input->variable = variable; - - return key_input; -} - diff --git a/games/NXDoom/src/setup/txt_keyinput.h b/games/NXDoom/src/setup/txt_keyinput.h deleted file mode 100644 index 334d6c1cf15..00000000000 --- a/games/NXDoom/src/setup/txt_keyinput.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef TXT_KEY_INPUT_H -#define TXT_KEY_INPUT_H - -typedef struct txt_key_input_s txt_key_input_t; - -#include "txt_widget.h" - -// -// A key input is like an input box. When selected, a box pops up -// allowing a key to be selected. -// - -struct txt_key_input_s -{ - txt_widget_t widget; - int *variable; - int check_conflicts; -}; - -txt_key_input_t *TXT_NewKeyInput(int *variable); - -#endif /* #ifndef TXT_KEY_INPUT_H */ - - diff --git a/games/NXDoom/src/setup/txt_mouseinput.c b/games/NXDoom/src/setup/txt_mouseinput.c deleted file mode 100644 index 99196a581ee..00000000000 --- a/games/NXDoom/src/setup/txt_mouseinput.c +++ /dev/null @@ -1,184 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include -#include - -#include "doomkeys.h" -#include "m_misc.h" - -#include "txt_mouseinput.h" -#include "txt_gui.h" -#include "txt_io.h" -#include "txt_label.h" -#include "txt_utf8.h" -#include "txt_window.h" - -// eg. "BUTTON #10" -#define MOUSE_INPUT_WIDTH 10 - -static int MousePressCallback(txt_window_t *window, - int x, int y, int b, - TXT_UNCAST_ARG(mouse_input)) -{ - TXT_CAST_ARG(txt_mouse_input_t, mouse_input); - - // Got the mouse press. Save to the variable and close the window. - - *mouse_input->variable = b - TXT_MOUSE_BASE; - - if (mouse_input->check_conflicts) - { - TXT_EmitSignal(mouse_input, "set"); - } - - TXT_CloseWindow(window); - - return 1; -} - -static void OpenPromptWindow(txt_mouse_input_t *mouse_input) -{ - txt_window_t *window; - - // Silently update when the shift key is held down. - mouse_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT); - - window = TXT_MessageBox(NULL, "Press the new mouse button..."); - - TXT_SetMouseListener(window, MousePressCallback, mouse_input); -} - -static void TXT_MouseInputSizeCalc(TXT_UNCAST_ARG(mouse_input)) -{ - TXT_CAST_ARG(txt_mouse_input_t, mouse_input); - - // All mouseinputs are the same size. - - mouse_input->widget.w = MOUSE_INPUT_WIDTH; - mouse_input->widget.h = 1; -} - -static void GetMouseButtonDescription(int button, char *buf, size_t buf_len) -{ - switch (button) - { - case 0: - M_StringCopy(buf, "LEFT", buf_len); - break; - case 1: - M_StringCopy(buf, "RIGHT", buf_len); - break; - case 2: - M_StringCopy(buf, "MID", buf_len); - break; - case 3: - M_StringCopy(buf, "WHEEL UP", buf_len); - break; - case 4: - M_StringCopy(buf, "WHEEL DOWN", buf_len); - break; - default: - M_snprintf(buf, buf_len, "BUTTON #%i", button - 1); - break; - } -} - -static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input)) -{ - TXT_CAST_ARG(txt_mouse_input_t, mouse_input); - char buf[20]; - int i; - - if (*mouse_input->variable < 0) - { - M_StringCopy(buf, "(none)", sizeof(buf)); - } - else - { - GetMouseButtonDescription(*mouse_input->variable, buf, sizeof(buf)); - } - - TXT_SetWidgetBG(mouse_input); - TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); - - TXT_DrawString(buf); - - for (i = TXT_UTF8_Strlen(buf); i < MOUSE_INPUT_WIDTH; ++i) - { - TXT_DrawString(" "); - } -} - -static void TXT_MouseInputDestructor(TXT_UNCAST_ARG(mouse_input)) -{ -} - -static int TXT_MouseInputKeyPress(TXT_UNCAST_ARG(mouse_input), int key) -{ - TXT_CAST_ARG(txt_mouse_input_t, mouse_input); - - if (key == KEY_ENTER) - { - // Open a window to prompt for the new mouse press - - OpenPromptWindow(mouse_input); - - return 1; - } - - if (key == KEY_BACKSPACE || key == KEY_DEL) - { - *mouse_input->variable = -1; - } - - return 0; -} - -static void TXT_MouseInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) -{ - TXT_CAST_ARG(txt_mouse_input_t, widget); - - // Clicking is like pressing enter - - if (b == TXT_MOUSE_LEFT) - { - TXT_MouseInputKeyPress(widget, KEY_ENTER); - } -} - -txt_widget_class_t txt_mouse_input_class = -{ - TXT_AlwaysSelectable, - TXT_MouseInputSizeCalc, - TXT_MouseInputDrawer, - TXT_MouseInputKeyPress, - TXT_MouseInputDestructor, - TXT_MouseInputMousePress, - NULL, -}; - -txt_mouse_input_t *TXT_NewMouseInput(int *variable) -{ - txt_mouse_input_t *mouse_input; - - mouse_input = malloc(sizeof(txt_mouse_input_t)); - - TXT_InitWidget(mouse_input, &txt_mouse_input_class); - mouse_input->variable = variable; - - return mouse_input; -} - diff --git a/games/NXDoom/src/setup/txt_mouseinput.h b/games/NXDoom/src/setup/txt_mouseinput.h deleted file mode 100644 index 2b05c371823..00000000000 --- a/games/NXDoom/src/setup/txt_mouseinput.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#ifndef TXT_MOUSE_INPUT_H -#define TXT_MOUSE_INPUT_H - -typedef struct txt_mouse_input_s txt_mouse_input_t; - -#include "txt_widget.h" - -// -// A mouse input is like an input box. When selected, a box pops up -// allowing a mouse to be selected. -// - -struct txt_mouse_input_s -{ - txt_widget_t widget; - int *variable; - int check_conflicts; -}; - -txt_mouse_input_t *TXT_NewMouseInput(int *variable); - -#endif /* #ifndef TXT_MOUSE_INPUT_H */ - - diff --git a/games/NXDoom/src/sha1.c b/games/NXDoom/src/sha1.c deleted file mode 100644 index 8504134a985..00000000000 --- a/games/NXDoom/src/sha1.c +++ /dev/null @@ -1,321 +0,0 @@ -/* sha1.c - SHA1 hash function - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * This file is part of GnuPG. - * - * GnuPG 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. - * - * GnuPG 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. - */ - - -/* Test vectors: - * - * "abc" - * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D - * - * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 - */ - -#include -#include -#include -#include - -#include "i_swap.h" -#include "sha1.h" - -void SHA1_Init(sha1_context_t *hd) -{ - hd->h0 = 0x67452301; - hd->h1 = 0xefcdab89; - hd->h2 = 0x98badcfe; - hd->h3 = 0x10325476; - hd->h4 = 0xc3d2e1f0; - hd->nblocks = 0; - hd->count = 0; -} - - -/**************** - * Transform the message X which consists of 16 32-bit-words - */ -static void Transform(sha1_context_t *hd, byte *data) -{ - uint32_t a,b,c,d,e,tm; - uint32_t x[16]; - - /* get values from the chaining vars */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - -#ifdef SYS_BIG_ENDIAN - memcpy(x, data, 64); -#else - { - int i; - byte *p2; - for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) - { - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif - - -#define K1 0x5A827999L -#define K2 0x6ED9EBA1L -#define K3 0x8F1BBCDCL -#define K4 0xCA62C1D6L -#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) -#define F2(x,y,z) ( x ^ y ^ z ) -#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) -#define F4(x,y,z) ( x ^ y ^ z ) - -#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) - -#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ - ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ - , (x[i&0x0f] = rol(tm,1)) ) - -#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ - + f( b, c, d ) \ - + k \ - + m; \ - b = rol( b, 30 ); \ - } while(0) - R( a, b, c, d, e, F1, K1, x[ 0] ); - R( e, a, b, c, d, F1, K1, x[ 1] ); - R( d, e, a, b, c, F1, K1, x[ 2] ); - R( c, d, e, a, b, F1, K1, x[ 3] ); - R( b, c, d, e, a, F1, K1, x[ 4] ); - R( a, b, c, d, e, F1, K1, x[ 5] ); - R( e, a, b, c, d, F1, K1, x[ 6] ); - R( d, e, a, b, c, F1, K1, x[ 7] ); - R( c, d, e, a, b, F1, K1, x[ 8] ); - R( b, c, d, e, a, F1, K1, x[ 9] ); - R( a, b, c, d, e, F1, K1, x[10] ); - R( e, a, b, c, d, F1, K1, x[11] ); - R( d, e, a, b, c, F1, K1, x[12] ); - R( c, d, e, a, b, F1, K1, x[13] ); - R( b, c, d, e, a, F1, K1, x[14] ); - R( a, b, c, d, e, F1, K1, x[15] ); - R( e, a, b, c, d, F1, K1, M(16) ); - R( d, e, a, b, c, F1, K1, M(17) ); - R( c, d, e, a, b, F1, K1, M(18) ); - R( b, c, d, e, a, F1, K1, M(19) ); - R( a, b, c, d, e, F2, K2, M(20) ); - R( e, a, b, c, d, F2, K2, M(21) ); - R( d, e, a, b, c, F2, K2, M(22) ); - R( c, d, e, a, b, F2, K2, M(23) ); - R( b, c, d, e, a, F2, K2, M(24) ); - R( a, b, c, d, e, F2, K2, M(25) ); - R( e, a, b, c, d, F2, K2, M(26) ); - R( d, e, a, b, c, F2, K2, M(27) ); - R( c, d, e, a, b, F2, K2, M(28) ); - R( b, c, d, e, a, F2, K2, M(29) ); - R( a, b, c, d, e, F2, K2, M(30) ); - R( e, a, b, c, d, F2, K2, M(31) ); - R( d, e, a, b, c, F2, K2, M(32) ); - R( c, d, e, a, b, F2, K2, M(33) ); - R( b, c, d, e, a, F2, K2, M(34) ); - R( a, b, c, d, e, F2, K2, M(35) ); - R( e, a, b, c, d, F2, K2, M(36) ); - R( d, e, a, b, c, F2, K2, M(37) ); - R( c, d, e, a, b, F2, K2, M(38) ); - R( b, c, d, e, a, F2, K2, M(39) ); - R( a, b, c, d, e, F3, K3, M(40) ); - R( e, a, b, c, d, F3, K3, M(41) ); - R( d, e, a, b, c, F3, K3, M(42) ); - R( c, d, e, a, b, F3, K3, M(43) ); - R( b, c, d, e, a, F3, K3, M(44) ); - R( a, b, c, d, e, F3, K3, M(45) ); - R( e, a, b, c, d, F3, K3, M(46) ); - R( d, e, a, b, c, F3, K3, M(47) ); - R( c, d, e, a, b, F3, K3, M(48) ); - R( b, c, d, e, a, F3, K3, M(49) ); - R( a, b, c, d, e, F3, K3, M(50) ); - R( e, a, b, c, d, F3, K3, M(51) ); - R( d, e, a, b, c, F3, K3, M(52) ); - R( c, d, e, a, b, F3, K3, M(53) ); - R( b, c, d, e, a, F3, K3, M(54) ); - R( a, b, c, d, e, F3, K3, M(55) ); - R( e, a, b, c, d, F3, K3, M(56) ); - R( d, e, a, b, c, F3, K3, M(57) ); - R( c, d, e, a, b, F3, K3, M(58) ); - R( b, c, d, e, a, F3, K3, M(59) ); - R( a, b, c, d, e, F4, K4, M(60) ); - R( e, a, b, c, d, F4, K4, M(61) ); - R( d, e, a, b, c, F4, K4, M(62) ); - R( c, d, e, a, b, F4, K4, M(63) ); - R( b, c, d, e, a, F4, K4, M(64) ); - R( a, b, c, d, e, F4, K4, M(65) ); - R( e, a, b, c, d, F4, K4, M(66) ); - R( d, e, a, b, c, F4, K4, M(67) ); - R( c, d, e, a, b, F4, K4, M(68) ); - R( b, c, d, e, a, F4, K4, M(69) ); - R( a, b, c, d, e, F4, K4, M(70) ); - R( e, a, b, c, d, F4, K4, M(71) ); - R( d, e, a, b, c, F4, K4, M(72) ); - R( c, d, e, a, b, F4, K4, M(73) ); - R( b, c, d, e, a, F4, K4, M(74) ); - R( a, b, c, d, e, F4, K4, M(75) ); - R( e, a, b, c, d, F4, K4, M(76) ); - R( d, e, a, b, c, F4, K4, M(77) ); - R( c, d, e, a, b, F4, K4, M(78) ); - R( b, c, d, e, a, F4, K4, M(79) ); - - /* update chainig vars */ - hd->h0 += a; - hd->h1 += b; - hd->h2 += c; - hd->h3 += d; - hd->h4 += e; -} - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -void SHA1_Update(sha1_context_t *hd, byte *inbuf, size_t inlen) -{ - if (hd->count == 64) - { - /* flush the buffer */ - Transform(hd, hd->buf); - hd->count = 0; - hd->nblocks++; - } - if (!inbuf) - return; - if (hd->count) - { - for (; inlen && hd->count < 64; inlen--) - hd->buf[hd->count++] = *inbuf++; - SHA1_Update(hd, NULL, 0); - if (!inlen) - return; - } - - while (inlen >= 64) - { - Transform(hd, inbuf); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - for (; inlen && hd->count < 64; inlen--) - hd->buf[hd->count++] = *inbuf++; -} - - -/* The routine final terminates the computation and - * returns the digest. - * The handle is prepared for a new cycle, but adding bytes to the - * handle will the destroy the returned buffer. - * Returns: 20 bytes representing the digest. - */ - -void SHA1_Final(sha1_digest_t digest, sha1_context_t *hd) -{ - uint32_t t, msb, lsb; - byte *p; - - SHA1_Update(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if ((lsb += hd->count) < t) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if (hd->count < 56) - { - /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while (hd->count < 56) - hd->buf[hd->count++] = 0; /* pad */ - } - else - { - /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while (hd->count < 64) - hd->buf[hd->count++] = 0; - SHA1_Update(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = msb >> 24; - hd->buf[57] = msb >> 16; - hd->buf[58] = msb >> 8; - hd->buf[59] = msb ; - hd->buf[60] = lsb >> 24; - hd->buf[61] = lsb >> 16; - hd->buf[62] = lsb >> 8; - hd->buf[63] = lsb ; - Transform(hd, hd->buf); - - p = hd->buf; -#ifdef SYS_BIG_ENDIAN -#define X(a) do { *(uint32_t*)p = hd->h##a ; p += 4; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) -#endif - X(0); - X(1); - X(2); - X(3); - X(4); -#undef X - - memcpy(digest, hd->buf, sizeof(sha1_digest_t)); -} - -void SHA1_UpdateInt32(sha1_context_t *context, unsigned int val) -{ - byte buf[4]; - - buf[0] = (val >> 24) & 0xff; - buf[1] = (val >> 16) & 0xff; - buf[2] = (val >> 8) & 0xff; - buf[3] = val & 0xff; - - SHA1_Update(context, buf, 4); -} - -void SHA1_UpdateString(sha1_context_t *context, char *str) -{ - SHA1_Update(context, (byte *) str, strlen(str) + 1); -} - diff --git a/games/NXDoom/src/sha1.h b/games/NXDoom/src/sha1.h index 249571be335..eb0f7c360bc 100644 --- a/games/NXDoom/src/sha1.h +++ b/games/NXDoom/src/sha1.h @@ -1,40 +1,59 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// SHA-1 digest. -// +/**************************************************************************** + * apps/games/NXDoom/src/sha1.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * SHA-1 digest. + * + ****************************************************************************/ #ifndef __SHA1_H__ #define __SHA1_H__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + #include "doomtype.h" -typedef struct sha1_context_s sha1_context_t; -typedef byte sha1_digest_t[20]; +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define sha1_updatestring(ctx, str) \ + sha1update((ctx), (byte *)(str), strlen((str)) + 1) -struct sha1_context_s { - uint32_t h0,h1,h2,h3,h4; - uint32_t nblocks; - byte buf[64]; - int count; -}; +#define sha1_updateint32(ctx, val) \ + do \ + { \ + byte __sha1__tmp__buf[4]; \ + __sha1__tmp__buf[0] = ((val) >> 24) & 0xff; \ + __sha1__tmp__buf[1] = ((val) >> 16) & 0xff; \ + __sha1__tmp__buf[2] = ((val) >> 8) & 0xff; \ + __sha1__tmp__buf[3] = (val) & 0xff; \ + sha1update((ctx), __sha1__tmp__buf, 4); \ + } \ + while (0) -void SHA1_Init(sha1_context_t *context); -void SHA1_Update(sha1_context_t *context, byte *buf, size_t len); -void SHA1_Final(sha1_digest_t digest, sha1_context_t *context); -void SHA1_UpdateInt32(sha1_context_t *context, unsigned int val); -void SHA1_UpdateString(sha1_context_t *context, char *str); +/**************************************************************************** + * Public Types + ****************************************************************************/ -#endif /* #ifndef __SHA1_H__ */ +typedef byte sha1_digest_t[SHA1_DIGEST_LENGTH]; +#endif /* __SHA1_H__ */ diff --git a/games/NXDoom/src/strife-res.rc.in b/games/NXDoom/src/strife-res.rc.in deleted file mode 100644 index ab9a2580de7..00000000000 --- a/games/NXDoom/src/strife-res.rc.in +++ /dev/null @@ -1,30 +0,0 @@ -1 ICON "@top_srcdir@/data/strife.ico" - -#include - -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@top_srcdir@/src/manifest.xml" - -1 VERSIONINFO -PRODUCTVERSION @WINDOWS_RC_VERSION@ -FILEVERSION @WINDOWS_RC_VERSION@ -FILETYPE 1 -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "FileVersion", "@PACKAGE_VERSION@.0" - VALUE "FileDescription", "@PACKAGE_STRING@" - VALUE "InternalName", "@PACKAGE_TARNAME@" - VALUE "CompanyName", "@PACKAGE_BUGREPORT@" - VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@" - VALUE "ProductName", "@PACKAGE_NAME@" - VALUE "ProductVersion", "@PACKAGE_VERSION@" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x409, 1252 - } -} - diff --git a/games/NXDoom/src/strife/.gitignore b/games/NXDoom/src/strife/.gitignore deleted file mode 100644 index d4e88e5a219..00000000000 --- a/games/NXDoom/src/strife/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -Makefile -Makefile.in -.deps -tags -TAGS diff --git a/games/NXDoom/src/strife/CMakeLists.txt b/games/NXDoom/src/strife/CMakeLists.txt deleted file mode 100644 index 20d336cdb67..00000000000 --- a/games/NXDoom/src/strife/CMakeLists.txt +++ /dev/null @@ -1,92 +0,0 @@ -set(STRIFE_SOURCES - am_map.c am_map.h - deh_ammo.c - deh_cheat.c - deh_strife.c - deh_frame.c - deh_misc.c deh_misc.h - deh_ptr.c - deh_sound.c - deh_thing.c - deh_weapon.c - d_englsh.h - d_items.c d_items.h - d_main.c d_main.h - d_net.c - doomdata.h - doomdef.c doomdef.h - doomstat.c doomstat.h - d_player.h - dstrings.c dstrings.h - d_textur.h - d_think.h - f_finale.c f_finale.h - f_wipe.c f_wipe.h - g_game.c g_game.h - hu_lib.c hu_lib.h - hu_stuff.c hu_stuff.h - info.c info.h - m_menu.c m_menu.h - m_random.c m_random.h - m_saves.c m_saves.h - p_ceilng.c - p_dialog.c p_dialog.h - p_doors.c - p_enemy.c - p_floor.c - p_inter.c p_inter.h - p_lights.c - p_local.h - p_map.c - p_maputl.c - p_mobj.c p_mobj.h - p_plats.c - p_pspr.c p_pspr.h - p_saveg.c p_saveg.h - p_setup.c p_setup.h - p_sight.c - p_spec.c p_spec.h - p_switch.c - p_telept.c - p_tick.c p_tick.h - p_user.c - r_bsp.c r_bsp.h - r_data.c r_data.h - r_defs.h - r_draw.c r_draw.h - r_local.h - r_main.c r_main.h - r_plane.c r_plane.h - r_segs.c r_segs.h - r_sky.c r_sky.h - r_state.h - r_things.c r_things.h - s_sound.c s_sound.h - sounds.c sounds.h - st_lib.c st_lib.h - st_stuff.c st_stuff.h - wi_stuff.c wi_stuff.h) - -add_library(strife STATIC ${STRIFE_SOURCES}) - -target_include_directories(strife PRIVATE "../" "../../win32/" "${CMAKE_CURRENT_BINARY_DIR}/../../") -if (DEFINED EMSCRIPTEN) - set(SDL_FLAGS "-s USE_SDL=2") - if(ENABLE_SDL2_MIXER) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") - endif() - if(ENABLE_SDL2_NET) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") - endif() -else() - set(SDL_LINK_LIBS, "SDL2::SDL2") - if(ENABLE_SDL2_MIXER) - list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) - endif() - if(ENABLE_SDL2_NET) - list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) - endif() -endif() -target_link_libraries(strife textscreen ${SDL_LINK_LIBS}) -set_target_properties(strife PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") -set_target_properties(strife PROPERTIES LINK_FLAGS "${SDL_FLAGS}") diff --git a/games/NXDoom/src/strife/Makefile.am b/games/NXDoom/src/strife/Makefile.am deleted file mode 100644 index 36d7b0c58fa..00000000000 --- a/games/NXDoom/src/strife/Makefile.am +++ /dev/null @@ -1,85 +0,0 @@ -AM_CFLAGS=-I$(top_srcdir)/src \ - -I$(top_srcdir)/textscreen \ - @SDL_CFLAGS@ @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@ - -EXTRA_DIST = \ - CMakeLists.txt \ - strife_icon.c - -noinst_LIBRARIES=libstrife.a - -libstrife_a_SOURCES = \ -am_map.c am_map.h \ -deh_ammo.c \ -deh_cheat.c \ -deh_strife.c \ -deh_frame.c \ -deh_misc.c deh_misc.h \ -deh_ptr.c \ -deh_sound.c \ -deh_thing.c \ -deh_weapon.c \ - d_englsh.h \ -d_items.c d_items.h \ -d_main.c d_main.h \ -d_net.c \ - doomdata.h \ -doomdef.c doomdef.h \ -doomstat.c doomstat.h \ - d_player.h \ -dstrings.c dstrings.h \ - d_textur.h \ - d_think.h \ -f_finale.c f_finale.h \ -f_wipe.c f_wipe.h \ -g_game.c g_game.h \ -hu_lib.c hu_lib.h \ -hu_stuff.c hu_stuff.h \ -info.c info.h \ -m_menu.c m_menu.h \ -m_random.c m_random.h \ -m_saves.c m_saves.h \ -p_ceilng.c \ -p_dialog.c p_dialog.h \ -p_doors.c \ -p_enemy.c \ -p_floor.c \ -p_inter.c p_inter.h \ -p_lights.c \ - p_local.h \ -p_map.c \ -p_maputl.c \ -p_mobj.c p_mobj.h \ -p_plats.c \ -p_pspr.c p_pspr.h \ -p_saveg.c p_saveg.h \ -p_setup.c p_setup.h \ -p_sight.c \ -p_spec.c p_spec.h \ -p_switch.c \ -p_telept.c \ -p_tick.c p_tick.h \ -p_user.c \ -r_bsp.c r_bsp.h \ -r_data.c r_data.h \ - r_defs.h \ -r_draw.c r_draw.h \ - r_local.h \ -r_main.c r_main.h \ -r_plane.c r_plane.h \ -r_segs.c r_segs.h \ -r_sky.c r_sky.h \ - r_state.h \ -r_things.c r_things.h \ -s_sound.c s_sound.h \ -sounds.c sounds.h \ -st_lib.c st_lib.h \ -st_stuff.c st_stuff.h \ -wi_stuff.c wi_stuff.h - -if HAVE_ICONS - -strife_icon.c : $(top_builddir)/data/strife.png - $(top_builddir)/data/convert-icon $(top_builddir)/data/strife.png $@ - -endif diff --git a/games/NXDoom/src/strife/am_map.c b/games/NXDoom/src/strife/am_map.c deleted file mode 100644 index e36fb56d5cb..00000000000 --- a/games/NXDoom/src/strife/am_map.c +++ /dev/null @@ -1,1415 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: the automap code -// - - -#include - -#include "deh_main.h" - -#include "z_zone.h" -#include "doomkeys.h" -#include "doomdef.h" -#include "m_misc.h" -#include "st_stuff.h" -#include "p_local.h" -#include "w_wad.h" - -#include "m_cheat.h" -#include "m_controls.h" -#include "i_system.h" -#include "i_timer.h" - -// Needs access to LFB. -#include "v_video.h" - -// State. -#include "doomstat.h" -#include "r_state.h" - -// Data. -#include "dstrings.h" - -#include "am_map.h" - - -// Automap colors -#define BACKGROUND 240 // haleyjd [STRIFE] -#define WALLCOLORS 5 // villsa [STRIFE] -#define WALLRANGE 16 -#define TSWALLCOLORS 16 -#define FDWALLCOLORS 122 // villsa [STRIFE] -#define CDWALLCOLORS 116 -#define CTWALLCOLORS 19 // villsa [STRIFE] -#define SPWALLCOLORS 243 // villsa [STRIFE] -#define THINGCOLORS 233 // villsa [STRIFE] -#define MISSILECOLORS 227 // villsa [STRIFE] -#define SHOOTABLECOLORS 235 // villsa [STRIFE] - -// drawing stuff - -#define AM_NUMMARKPOINTS 10 - -// scale on entry -#define INITSCALEMTOF (.2*FRACUNIT) -// how much the automap moves window per tic in frame-buffer coordinates -// moves 140 pixels in 1 second -#define F_PANINC 4 -// how much zoom-in per tic -// goes to 2x in 1 second -#define M_ZOOMIN ((int) (1.02*FRACUNIT)) -// how much zoom-out per tic -// pulls out to 0.5x in 1 second -#define M_ZOOMOUT ((int) (FRACUNIT/1.02)) - -// translates between frame-buffer and map distances -#define FTOM(x) FixedMul(((x)<<16),scale_ftom) -#define MTOF(x) (FixedMul((x),scale_mtof)>>16) -// translates between frame-buffer and map coordinates -#define CXMTOF(x) (f_x + MTOF((x)-m_x)) -#define CYMTOF(y) (f_y + (f_h - MTOF((y)-m_y))) - -// the following is crap -#define LINE_NEVERSEE ML_DONTDRAW - -typedef struct -{ - int x, y; -} fpoint_t; - -typedef struct -{ - fpoint_t a, b; -} fline_t; - -typedef struct -{ - fixed_t x,y; -} mpoint_t; - -typedef struct -{ - mpoint_t a, b; -} mline_t; - -typedef struct -{ - fixed_t slp, islp; -} islope_t; - - - -// -// The vector graphics for the automap. -// A line drawing of the player pointing right, -// starting from the middle. -// -#define R ((8*PLAYERRADIUS)/7) -mline_t player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/4 } }, // -----> - { { R, 0 }, { R-R/2, -R/4 } }, - { { -R+R/8, 0 }, { -R-R/8, R/4 } }, // >----> - { { -R+R/8, 0 }, { -R-R/8, -R/4 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/4 } }, // >>---> - { { -R+3*R/8, 0 }, { -R+R/8, -R/4 } } -}; -#undef R - -#define R ((8*PLAYERRADIUS)/7) -mline_t cheat_player_arrow[] = { - { { -R+R/8, 0 }, { R, 0 } }, // ----- - { { R, 0 }, { R-R/2, R/6 } }, // -----> - { { R, 0 }, { R-R/2, -R/6 } }, - { { -R+R/8, 0 }, { -R-R/8, R/6 } }, // >-----> - { { -R+R/8, 0 }, { -R-R/8, -R/6 } }, - { { -R+3*R/8, 0 }, { -R+R/8, R/6 } }, // >>-----> - { { -R+3*R/8, 0 }, { -R+R/8, -R/6 } }, - { { -R/2, 0 }, { -R/2, -R/6 } }, // >>-d---> - { { -R/2, -R/6 }, { -R/2+R/6, -R/6 } }, - { { -R/2+R/6, -R/6 }, { -R/2+R/6, R/4 } }, - { { -R/6, 0 }, { -R/6, -R/6 } }, // >>-dd--> - { { -R/6, -R/6 }, { 0, -R/6 } }, - { { 0, -R/6 }, { 0, R/4 } }, - { { R/6, R/4 }, { R/6, -R/7 } }, // >>-ddt-> - { { R/6, -R/7 }, { R/6+R/32, -R/7-R/32 } }, - { { R/6+R/32, -R/7-R/32 }, { R/6+R/10, -R/7 } } -}; -#undef R - -#define R (FRACUNIT) -mline_t triangle_guy[] = { - { { (fixed_t)(-.867*R), (fixed_t)(-.5*R) }, { (fixed_t)(.867*R ), (fixed_t)(-.5*R) } }, - { { (fixed_t)(.867*R ), (fixed_t)(-.5*R) }, { (fixed_t)(0 ), (fixed_t)(R ) } }, - { { (fixed_t)(0 ), (fixed_t)(R ) }, { (fixed_t)(-.867*R), (fixed_t)(-.5*R) } } -}; -#undef R - -#define R (FRACUNIT) -mline_t thintriangle_guy[] = { - { { (fixed_t)(-.5*R), (fixed_t)(-.7*R) }, { (fixed_t)(R ), (fixed_t)(0 ) } }, - { { (fixed_t)(R ), (fixed_t)(0 ) }, { (fixed_t)(-.5*R), (fixed_t)(.7*R ) } }, - { { (fixed_t)(-.5*R), (fixed_t)(.7*R ) }, { (fixed_t)(-.5*R), (fixed_t)(-.7*R) } } -}; -#undef R - - - - -static int cheating = 0; -//static int grid = 0; [STRIFE]: no such variable - -boolean automapactive = false; -static int finit_width = SCREENWIDTH; -static int finit_height = SCREENHEIGHT - 32; - -// location of window on screen -static int f_x; -static int f_y; - -// size of window on screen -static int f_w; -static int f_h; - -static int lightlev; // used for funky strobing effect -static byte* fb; // pseudo-frame buffer -static int amclock; - -static mpoint_t m_paninc; // how far the window pans each tic (map coords) -static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords) -static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords) - -static fixed_t m_x, m_y; // LL x,y where the window is on the map (map coords) -static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords) - -// -// width/height of window on map (map coords) -// -static fixed_t m_w; -static fixed_t m_h; - -// based on level size -static fixed_t min_x; -static fixed_t min_y; -static fixed_t max_x; -static fixed_t max_y; - -static fixed_t max_w; // max_x-min_x, -static fixed_t max_h; // max_y-min_y - -// based on player size -static fixed_t min_w; -static fixed_t min_h; - - -static fixed_t min_scale_mtof; // used to tell when to stop zooming out -static fixed_t max_scale_mtof; // used to tell when to stop zooming in - -// old stuff for recovery later -static fixed_t old_m_w, old_m_h; -static fixed_t old_m_x, old_m_y; - -// old location used by the Follower routine -static mpoint_t f_oldloc; - -// used by MTOF to scale from map-to-frame-buffer coords -static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF; -// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof) -static fixed_t scale_ftom; - -static player_t *plr; // the player represented by an arrow - -static patch_t *marknums[10]; // numbers used for marking by the automap -static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are -static int markpointnum = 0; // next point to be assigned -static int mapmarknum = 0; // villsa [STRIFE] unused but this was meant to be used for objective based markers -static int followplayer = 1; // specifies whether to follow the player around - -cheatseq_t cheat_amap = CHEAT("topo", 0); // villsa [STRIFE] - -static boolean stopped = true; - - -// Calculates the slope and slope according to the x-axis of a line -// segment in map coordinates (with the upright y-axis n' all) so -// that it can be used with the brain-dead drawing stuff. - -void -AM_getIslope -( mline_t* ml, - islope_t* is ) -{ - int dx, dy; - - dy = ml->a.y - ml->b.y; - dx = ml->b.x - ml->a.x; - if (!dy) is->islp = (dx<0?-INT_MAX:INT_MAX); - else is->islp = FixedDiv(dx, dy); - if (!dx) is->slp = (dy<0?-INT_MAX:INT_MAX); - else is->slp = FixedDiv(dy, dx); - -} - -// -// -// -void AM_activateNewScale(void) -{ - m_x += m_w/2; - m_y += m_h/2; - m_w = FTOM(f_w); - m_h = FTOM(f_h); - m_x -= m_w/2; - m_y -= m_h/2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; -} - -// -// -// -void AM_saveScaleAndLoc(void) -{ - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; -} - -// -// -// -void AM_restoreScaleAndLoc(void) -{ - - m_w = old_m_w; - m_h = old_m_h; - if (!followplayer) - { - m_x = old_m_x; - m_y = old_m_y; - } else { - m_x = plr->mo->x - m_w/2; - m_y = plr->mo->y - m_h/2; - } - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - - // Change the scaling multipliers - scale_mtof = FixedDiv(f_w<mo->x; // 20160306 [STRIFE]: use player position - markpoints[markpointnum].y = plr->mo->y; - //markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS; - ++markpointnum; // haleyjd 20141101: [STRIFE] does not wrap around -} - -// -// Determines bounding box of all vertices, -// sets global variables controlling zoom range. -// -void AM_findMinMaxBoundaries(void) -{ - int i; - fixed_t a; - fixed_t b; - - min_x = min_y = INT_MAX; - max_x = max_y = -INT_MAX; - - for (i=0;i max_x) - max_x = vertexes[i].x; - - if (vertexes[i].y < min_y) - min_y = vertexes[i].y; - else if (vertexes[i].y > max_y) - max_y = vertexes[i].y; - } - - max_w = max_x - min_x; - max_h = max_y - min_y; - - min_w = 2*PLAYERRADIUS; // const? never changed? - min_h = 2*PLAYERRADIUS; - - a = FixedDiv(f_w< max_x) - m_x = max_x - m_w/2; - else if (m_x + m_w/2 < min_x) - m_x = min_x - m_w/2; - - if (m_y + m_h/2 > max_y) - m_y = max_y - m_h/2; - else if (m_y + m_h/2 < min_y) - m_y = min_y - m_h/2; - - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; -} - - -// -// -// -void AM_initVariables(void) -{ - int pnum; - static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 }; - - automapactive = true; - fb = I_VideoBuffer; - - f_oldloc.x = INT_MAX; - amclock = 0; - lightlev = 0; - - m_paninc.x = m_paninc.y = 0; - ftom_zoommul = FRACUNIT; - mtof_zoommul = FRACUNIT; - - m_w = FTOM(f_w); - m_h = FTOM(f_h); - - // find player to center on initially - if (playeringame[consoleplayer]) - { - plr = &players[consoleplayer]; - } - else - { - plr = &players[0]; - - for (pnum=0;pnummo->x - m_w/2; - m_y = plr->mo->y - m_h/2; - AM_changeWindowLoc(); - - // for saving & restoring - old_m_x = m_x; - old_m_y = m_y; - old_m_w = m_w; - old_m_h = m_h; - - // inform the status bar of the change - ST_Responder(&st_notify); - -} - -// -// AM_loadPics -// -// haleyjd 08/27/10: [STRIFE] Changed marknums to PLMNUM%d -// -void AM_loadPics(void) -{ - int i; - char namebuf[9]; - - for (i=0;i<10;i++) - { - DEH_snprintf(namebuf, 9, "PLMNUM%d", i); - marknums[i] = W_CacheLumpName(namebuf, PU_STATIC); - } - -} - -void AM_unloadPics(void) -{ - int i; - char namebuf[9]; - - for (i=0;i<10;i++) - { - DEH_snprintf(namebuf, 9, "PLMNUM%d", i); - W_ReleaseLumpName(namebuf); - } -} - -void AM_clearMarks(void) -{ - int i; - - for (i=0;i max_scale_mtof) - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); -} - - - - -// -// -// -void AM_Stop (void) -{ - static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 }; - - AM_unloadPics(); - automapactive = false; - ST_Responder(&st_notify); - stopped = true; -} - -// -// -// -void AM_Start (void) -{ - static int lastlevel = -1; - //static int lastepisode = -1; - - if (!stopped) AM_Stop(); - stopped = false; - if (lastlevel != gamemap /*|| lastepisode != gameepisode*/) - { - AM_LevelInit(); - lastlevel = gamemap; - //lastepisode = gameepisode; - } - AM_initVariables(); - AM_loadPics(); -} - -// -// set the window scale to the maximum size -// -void AM_minOutWindowScale(void) -{ - scale_mtof = min_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); -} - -// -// set the window scale to the minimum size -// -void AM_maxOutWindowScale(void) -{ - scale_mtof = max_scale_mtof; - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - AM_activateNewScale(); -} - - -// -// Handle events (user inputs) in automap mode -// -boolean -AM_Responder -( event_t* ev ) -{ - - int rc; - static int bigstate=0; - static int joywait = 0; - static char buffer[20]; - int key; - - rc = false; - - if (ev->type == ev_joystick && joybautomap >= 0 - && (ev->data1 & (1 << joybautomap)) != 0 && joywait < I_GetTime()) - { - joywait = I_GetTime() + 5; - - if (!automapactive) - { - AM_Start (); - viewactive = false; - } - else - { - bigstate = 0; - viewactive = true; - AM_Stop (); - } - - return true; - } - - - if (!automapactive) - { - if (ev->type == ev_keydown && ev->data1 == key_map_toggle) - { - AM_Start (); - viewactive = false; - rc = true; - } - } - else if (ev->type == ev_keydown) - { - rc = true; - key = ev->data1; - - if (key == key_map_east) // pan right - { - if (!followplayer) m_paninc.x = FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_west) // pan left - { - if (!followplayer) m_paninc.x = -FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_north) // pan up - { - if (!followplayer) m_paninc.y = FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_south) // pan down - { - if (!followplayer) m_paninc.y = -FTOM(F_PANINC); - else rc = false; - } - else if (key == key_map_zoomout) // zoom out - { - mtof_zoommul = M_ZOOMOUT; - ftom_zoommul = M_ZOOMIN; - } - else if (key == key_map_zoomin) // zoom in - { - mtof_zoommul = M_ZOOMIN; - ftom_zoommul = M_ZOOMOUT; - } - else if (key == key_map_toggle) - { - bigstate = 0; - viewactive = true; - AM_Stop (); - } - else if (key == key_map_maxzoom) - { - bigstate = !bigstate; - if (bigstate) - { - AM_saveScaleAndLoc(); - AM_minOutWindowScale(); - } - else AM_restoreScaleAndLoc(); - } - else if (key == key_map_follow) - { - followplayer = !followplayer; - f_oldloc.x = INT_MAX; - if (followplayer) - plr->message = DEH_String(AMSTR_FOLLOWON); - else - plr->message = DEH_String(AMSTR_FOLLOWOFF); - } - // haleyjd 20141101: [STRIFE] grid is not supported - /* - else if (key == key_map_grid) - { - grid = !grid; - if (grid) - plr->message = DEH_String(AMSTR_GRIDON); - else - plr->message = DEH_String(AMSTR_GRIDOFF); - } - */ - else if (key == key_map_mark) - { - // haleyjd 20141101: [STRIFE] if full, mark 9 is replaced - if(markpointnum == AM_NUMMARKPOINTS) - --markpointnum; - M_snprintf(buffer, sizeof(buffer), - "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum + 1); // [STRIFE] - plr->message = buffer; - AM_addMark(); - } - else if (key == key_map_clearmark) - { - // haleyjd 20141101: [STRIFE] clears last mark only - if(markpointnum > 0) - { - markpoints[markpointnum - 1].x = -1; - --markpointnum; - plr->message = DEH_String(AMSTR_MARKSCLEARED); - } - } - else - { - rc = false; - } - - if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data2)) - { - rc = false; - cheating = (cheating+1) % 3; - } - } - else if (ev->type == ev_keyup) - { - rc = false; - key = ev->data1; - - if (key == key_map_east) - { - if (!followplayer) m_paninc.x = 0; - } - else if (key == key_map_west) - { - if (!followplayer) m_paninc.x = 0; - } - else if (key == key_map_north) - { - if (!followplayer) m_paninc.y = 0; - } - else if (key == key_map_south) - { - if (!followplayer) m_paninc.y = 0; - } - else if (key == key_map_zoomout || key == key_map_zoomin) - { - mtof_zoommul = FRACUNIT; - ftom_zoommul = FRACUNIT; - } - } - - return rc; - -} - - -// -// Zooming -// -void AM_changeWindowScale(void) -{ - - // Change the scaling multipliers - scale_mtof = FixedMul(scale_mtof, mtof_zoommul); - scale_ftom = FixedDiv(FRACUNIT, scale_mtof); - - if (scale_mtof < min_scale_mtof) - AM_minOutWindowScale(); - else if (scale_mtof > max_scale_mtof) - AM_maxOutWindowScale(); - else - AM_activateNewScale(); -} - - -// -// -// -void AM_doFollowPlayer(void) -{ - - if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y) - { - m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; - m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; - m_x2 = m_x + m_w; - m_y2 = m_y + m_h; - f_oldloc.x = plr->mo->x; - f_oldloc.y = plr->mo->y; - - // m_x = FTOM(MTOF(plr->mo->x - m_w/2)); - // m_y = FTOM(MTOF(plr->mo->y - m_h/2)); - // m_x = plr->mo->x - m_w/2; - // m_y = plr->mo->y - m_h/2; - - } - -} - -// -// -// -void AM_updateLightLev(void) -{ - static int nexttic = 0; - //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; - static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; - static int litelevelscnt = 0; - - // Change light level - if (amclock>nexttic) - { - lightlev = litelevels[litelevelscnt++]; - if (litelevelscnt == arrlen(litelevels)) litelevelscnt = 0; - nexttic = amclock + 6 - (amclock % 6); - } - -} - - -// -// Updates on Game Tick -// -void AM_Ticker (void) -{ - - if (!automapactive) - return; - - amclock++; - - if (followplayer) - AM_doFollowPlayer(); - - // Change the zoom if necessary - if (ftom_zoommul != FRACUNIT) - AM_changeWindowScale(); - - // Change x,y location - if (m_paninc.x || m_paninc.y) - AM_changeWindowLoc(); - - // Update light level - // AM_updateLightLev(); - -} - - -// -// Clear automap frame buffer. -// -void AM_clearFB(int color) -{ - memset(fb, color, f_w*f_h); -} - - -// -// Automap clipping of lines. -// -// Based on Cohen-Sutherland clipping algorithm but with a slightly -// faster reject and precalculated slopes. If the speed is needed, -// use a hash algorithm to handle the common cases. -// -boolean -AM_clipMline -( mline_t* ml, - fline_t* fl ) -{ - enum - { - LEFT =1, - RIGHT =2, - BOTTOM =4, - TOP =8 - }; - - register int outcode1 = 0; - register int outcode2 = 0; - register int outside; - - fpoint_t tmp; - int dx; - int dy; - - -#define DOOUTCODE(oc, mx, my) \ - (oc) = 0; \ - if ((my) < 0) (oc) |= TOP; \ - else if ((my) >= f_h) (oc) |= BOTTOM; \ - if ((mx) < 0) (oc) |= LEFT; \ - else if ((mx) >= f_w) (oc) |= RIGHT; - - - // do trivial rejects and outcodes - if (ml->a.y > m_y2) - outcode1 = TOP; - else if (ml->a.y < m_y) - outcode1 = BOTTOM; - - if (ml->b.y > m_y2) - outcode2 = TOP; - else if (ml->b.y < m_y) - outcode2 = BOTTOM; - - if (outcode1 & outcode2) - return false; // trivially outside - - if (ml->a.x < m_x) - outcode1 |= LEFT; - else if (ml->a.x > m_x2) - outcode1 |= RIGHT; - - if (ml->b.x < m_x) - outcode2 |= LEFT; - else if (ml->b.x > m_x2) - outcode2 |= RIGHT; - - if (outcode1 & outcode2) - return false; // trivially outside - - // transform to frame-buffer coordinates. - fl->a.x = CXMTOF(ml->a.x); - fl->a.y = CYMTOF(ml->a.y); - fl->b.x = CXMTOF(ml->b.x); - fl->b.y = CYMTOF(ml->b.y); - - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - - if (outcode1 & outcode2) - return false; - - while (outcode1 | outcode2) - { - // may be partially inside box - // find an outside point - if (outcode1) - outside = outcode1; - else - outside = outcode2; - - // clip to each side - if (outside & TOP) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx*(fl->a.y))/dy; - tmp.y = 0; - } - else if (outside & BOTTOM) - { - dy = fl->a.y - fl->b.y; - dx = fl->b.x - fl->a.x; - tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy; - tmp.y = f_h-1; - } - else if (outside & RIGHT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx; - tmp.x = f_w-1; - } - else if (outside & LEFT) - { - dy = fl->b.y - fl->a.y; - dx = fl->b.x - fl->a.x; - tmp.y = fl->a.y + (dy*(-fl->a.x))/dx; - tmp.x = 0; - } - else - { - tmp.x = 0; - tmp.y = 0; - } - - if (outside == outcode1) - { - fl->a = tmp; - DOOUTCODE(outcode1, fl->a.x, fl->a.y); - } - else - { - fl->b = tmp; - DOOUTCODE(outcode2, fl->b.x, fl->b.y); - } - - if (outcode1 & outcode2) - return false; // trivially outside - } - - return true; -} -#undef DOOUTCODE - - -// -// Classic Bresenham w/ whatever optimizations needed for speed -// -void -AM_drawFline -( fline_t* fl, - int color ) -{ - register int x; - register int y; - register int dx; - register int dy; - register int sx; - register int sy; - register int ax; - register int ay; - register int d; - - static int fuck = 0; - - // For debugging only - if ( fl->a.x < 0 || fl->a.x >= f_w - || fl->a.y < 0 || fl->a.y >= f_h - || fl->b.x < 0 || fl->b.x >= f_w - || fl->b.y < 0 || fl->b.y >= f_h) - { - DEH_fprintf(stderr, "fuck %d \r", fuck++); - return; - } - -#define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) - - dx = fl->b.x - fl->a.x; - ax = 2 * (dx<0 ? -dx : dx); - sx = dx<0 ? -1 : 1; - - dy = fl->b.y - fl->a.y; - ay = 2 * (dy<0 ? -dy : dy); - sy = dy<0 ? -1 : 1; - - x = fl->a.x; - y = fl->a.y; - - if (ax > ay) - { - d = ay - ax/2; - while (1) - { - PUTDOT(x,y,color); - if (x == fl->b.x) return; - if (d>=0) - { - y += sy; - d -= ax; - } - x += sx; - d += ay; - } - } - else - { - d = ax - ay/2; - while (1) - { - PUTDOT(x, y, color); - if (y == fl->b.y) return; - if (d >= 0) - { - x += sx; - d -= ay; - } - y += sy; - d += ax; - } - } -} - - -// -// Clip lines, draw visible part sof lines. -// -void -AM_drawMline -( mline_t* ml, - int color ) -{ - static fline_t fl; - - if (AM_clipMline(ml, &fl)) - AM_drawFline(&fl, color); // draws it on frame buffer using fb coords -} - - - -// -// Draws flat (floor/ceiling tile) aligned grid lines. -// -/*void AM_drawGrid(int color) -{ - fixed_t x, y; - fixed_t start, end; - mline_t ml; - - // Figure out start of vertical gridlines - start = m_x; - if ((start-bmaporgx)%(MAPBLOCKUNITS<v1->x; - l.a.y = line->v1->y; - l.b.x = line->v2->x; - l.b.y = line->v2->y; - - if(cheating || (line->flags & ML_MAPPED)) - { - if((line->flags & LINE_NEVERSEE) && !cheating) - continue; - - // villsa [STRIFE] - if(line->special == 145 || line->special == 186) - { - AM_drawMline(&l, SPWALLCOLORS); - } - // villsa [STRIFE] lightlev is unused here - else if(!line->backsector) - { - AM_drawMline(&l, WALLCOLORS); - } - else - { - if(line->special == 39) - { // teleporters - AM_drawMline(&l, WALLCOLORS+WALLRANGE/2); - } - else if (line->flags & ML_SECRET) // secret door - { - // villsa [STRIFE] just draw the wall as is! - AM_drawMline(&l, WALLCOLORS); - } - else if(line->backsector->floorheight != line->frontsector->floorheight) - { - AM_drawMline(&l, FDWALLCOLORS); // floor level change - } - else if(line->backsector->ceilingheight != line->frontsector->ceilingheight) - { - AM_drawMline(&l, CDWALLCOLORS); // ceiling level change - } - else if (cheating) - { - AM_drawMline(&l, TSWALLCOLORS); - } - } - } - // villsa [STRIFE] show all of the map on map 15 - else if(plr->powers[pw_allmap] || gamemap == 15) - { - if(!(line->flags & LINE_NEVERSEE)) - AM_drawMline(&l, CTWALLCOLORS); - } - } -} - - -// -// Rotation in 2D. -// Used to rotate player arrow line character. -// -void -AM_rotate -( fixed_t* x, - fixed_t* y, - angle_t a ) -{ - fixed_t tmpx; - - tmpx = - FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT]) - - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]); - - *y = - FixedMul(*x,finesine[a>>ANGLETOFINESHIFT]) - + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]); - - *x = tmpx; -} - -void -AM_drawLineCharacter -( mline_t* lineguy, - int lineguylines, - fixed_t scale, - angle_t angle, - int color, - fixed_t x, - fixed_t y ) -{ - int i; - mline_t l; - - for (i=0;imo->angle, - 224, plr->mo->x, plr->mo->y); - return; - } - - for(i = 0; i < MAXPLAYERS; i++) - { - their_color++; - p = &players[i]; - - // villsa [STRIFE] check for gameskill?? - if((gameskill && deathmatch && !singledemo) && p != plr) - continue; - - if(!playeringame[i]) - continue; - - // villsa [STRIFE] change to 27 - if(p->powers[pw_invisibility]) - color = 27; // *close* to black - else - color = their_colors[their_color]; - - AM_drawLineCharacter - (player_arrow, arrlen(player_arrow), 0, p->mo->angle, - color, p->mo->x, p->mo->y); - } - -} - -// -// AM_drawThings -// -// villsa [STRIFE] no arguments -// -void AM_drawThings(void) -{ - int i; - mobj_t* t; - int colors; - fixed_t radius; - - // villsa [STRIFE] almost re-written - // specific things can have different radius, color and appearence - for(i = 0; i < numsectors; i++) - { - t = sectors[i].thinglist; - while(t) - { - radius = t->radius; - - if(t->flags & (MF_MISSILE|MF_SPECIAL)) - { - colors = MISSILECOLORS; - } - else if(t->flags & MF_COUNTKILL) - { - colors = SHOOTABLECOLORS; - } - else - { - colors = THINGCOLORS; - radius = (16<angle, colors, t->x, t->y); - - t = t->snext; - } - } -} - -// -// AM_drawMarks -// -void AM_drawMarks(void) -{ - int i, fx, fy, w, h; - - for(i = 0; i < AM_NUMMARKPOINTS; i++) - { - if(markpoints[i].x != -1) - { - // w = SHORT(marknums[i]->width); - // h = SHORT(marknums[i]->height); - w = 5; // because something's wrong with the wad, i guess - h = 6; // because something's wrong with the wad, i guess - fx = CXMTOF(markpoints[i].x); - fy = CYMTOF(markpoints[i].y); - if(fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) - { - // villsa [STRIFE] - if(i >= mapmarknum) - V_DrawPatch(fx, fy, marknums[i]); - } - } - } - -} - -// villsa [STRIFE] unused -/*void AM_drawCrosshair(int color) -{ - fb[(f_w*(f_h+1))/2] = color; // single point for now -}*/ - -void AM_Drawer (void) -{ - if (!automapactive) return; - - AM_clearFB(BACKGROUND); - - // villsa [STRIFE] not used - /*if(grid) - AM_drawGrid(GRIDCOLORS);*/ - - AM_drawWalls(); - AM_drawPlayers(); - - // villsa [STRIFE] draw things when map powerup is enabled - if(cheating == 2 || plr->powers[pw_allmap] > 1) - AM_drawThings(); - - // villsa [STRIFE] not used - //AM_drawCrosshair(XHAIRCOLORS); - - AM_drawMarks(); - V_MarkRect(f_x, f_y, f_w, f_h); - -} diff --git a/games/NXDoom/src/strife/am_map.h b/games/NXDoom/src/strife/am_map.h deleted file mode 100644 index 572d2389bc2..00000000000 --- a/games/NXDoom/src/strife/am_map.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// AutoMap module. -// - -#ifndef __AMMAP_H__ -#define __AMMAP_H__ - -#include "d_event.h" -#include "m_cheat.h" - -// Used by ST StatusBar stuff. -#define AM_MSGHEADER (('a'<<24)+('m'<<16)) -#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8)) -#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8)) - - -// Called by main loop. -boolean AM_Responder (event_t* ev); - -// Called by main loop. -void AM_Ticker (void); - -// Called by main loop, -// called instead of view drawer if automap active. -void AM_Drawer (void); - -// Called to force the automap to quit -// if the level is completed while it is up. -void AM_Stop (void); - - -extern cheatseq_t cheat_amap; - - -#endif diff --git a/games/NXDoom/src/strife/d_englsh.h b/games/NXDoom/src/strife/d_englsh.h deleted file mode 100644 index 57312a89f17..00000000000 --- a/games/NXDoom/src/strife/d_englsh.h +++ /dev/null @@ -1,593 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Printed strings for translation. -// English language support (default). -// - -#ifndef __D_ENGLSH__ -#define __D_ENGLSH__ - -// -// Printed strings for translation -// - -// -// D_Main.C -// -#define D_DEVSTR "Development mode ON.\n" -#define D_CDROM "CD-ROM Version: Accessing strife.cd\n" - -// -// M_Menu.C -// -#define PRESSKEY "press a key." -#define PRESSYN "press y or n." -#define QUITMSG "are you sure you want to\nquit this great game?" -// [STRIFE] modified: -#define LOADNET "you can't load while in a net game!\n\n"PRESSKEY -#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY -// [STRIFE] modified: -#define QSAVESPOT "you haven't picked a\nquicksave slot yet!\n\n"PRESSKEY -// [STRIFE] modified: -#define SAVEDEAD "you're not playing a game\n\n"PRESSKEY -#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN -// [STRIFE] modified: -#define QLPROMPT "do you want to quickload\n\n'%s'?\n\n"PRESSYN - -#define NEWGAME \ -"you can't start a new game\n"\ -"while in a network game.\n\n"PRESSKEY - -#define NIGHTMARE \ -"are you sure? this skill level\n"\ -"isn't even remotely fair.\n\n"PRESSYN - -#define SWSTRING \ -"this is the shareware version of doom.\n\n"\ -"you need to order the entire trilogy.\n\n"PRESSKEY - -#define MSGOFF "Messages OFF" -#define MSGON "Messages ON" -#define NETEND "you can't end a netgame!\n\n"PRESSKEY -#define ENDGAME "are you sure you want\nto end the game?\n\n"PRESSYN - -// haleyjd 09/11/10: [STRIFE] No "to dos." on this -#define DOSY "(press y to quit)" - -#define DETAILHI "High detail" -#define DETAILLO "Low detail" -#define GAMMALVL0 "Gamma correction OFF" -#define GAMMALVL1 "Gamma correction level 1" -#define GAMMALVL2 "Gamma correction level 2" -#define GAMMALVL3 "Gamma correction level 3" -#define GAMMALVL4 "Gamma correction level 4" -#define EMPTYSTRING "empty slot" - -// -// P_inter.C -// -#define GOTARMOR "Picked up the armor." -#define GOTMEGA "Picked up the MegaArmor!" -#define GOTHTHBONUS "Picked up a health bonus." -#define GOTARMBONUS "Picked up an armor bonus." -#define GOTSTIM "Picked up a stimpack." -#define GOTMEDINEED "Picked up a medikit that you REALLY need!" -#define GOTMEDIKIT "Picked up a medikit." -#define GOTSUPER "Supercharge!" - -#define GOTBLUECARD "Picked up a blue keycard." -#define GOTYELWCARD "Picked up a yellow keycard." -#define GOTREDCARD "Picked up a red keycard." -#define GOTBLUESKUL "Picked up a blue skull key." -#define GOTYELWSKUL "Picked up a yellow skull key." -#define GOTREDSKULL "Picked up a red skull key." - -#define GOTINVUL "Invulnerability!" -#define GOTBERSERK "Berserk!" -#define GOTINVIS "Partial Invisibility" -#define GOTSUIT "Radiation Shielding Suit" -#define GOTMAP "Computer Area Map" -#define GOTVISOR "Light Amplification Visor" -#define GOTMSPHERE "MegaSphere!" - -#define GOTCLIP "Picked up a clip." -#define GOTCLIPBOX "Picked up a box of bullets." -#define GOTROCKET "Picked up a rocket." -#define GOTROCKBOX "Picked up a box of rockets." -#define GOTCELL "Picked up an energy cell." -#define GOTCELLBOX "Picked up an energy cell pack." -#define GOTSHELLS "Picked up 4 shotgun shells." -#define GOTSHELLBOX "Picked up a box of shotgun shells." -#define GOTBACKPACK "Picked up a backpack full of ammo!" - -#define GOTBFG9000 "You got the BFG9000! Oh, yes." -#define GOTCHAINGUN "You got the chaingun!" -#define GOTCHAINSAW "A chainsaw! Find some meat!" -#define GOTLAUNCHER "You got the rocket launcher!" -#define GOTPLASMA "You got the plasma gun!" -#define GOTSHOTGUN "You got the shotgun!" -#define GOTSHOTGUN2 "You got the super shotgun!" - -// -// P_Doors.C -// -#define PD_BLUEO "You need a blue key to activate this object" -#define PD_REDO "You need a red key to activate this object" -#define PD_YELLOWO "You need a yellow key to activate this object" -#define PD_BLUEK "You need a blue key to open this door" -#define PD_REDK "You need a red key to open this door" -#define PD_YELLOWK "You need a yellow key to open this door" - -// -// G_game.C -// -#define GGSAVED "game saved." - -// -// HU_stuff.C -// -#define HUSTR_MSGU "[Message unsent]" - -// haleyjd 08/31/10: [STRIFE] Strife map names - -#define HUSTR_1 "AREA 1: sanctuary" -#define HUSTR_2 "AREA 2: town" -#define HUSTR_3 "AREA 3: front base" -#define HUSTR_4 "AREA 4: power station" -#define HUSTR_5 "AREA 5: prison" -#define HUSTR_6 "AREA 6: sewers" -#define HUSTR_7 "AREA 7: castle" -#define HUSTR_8 "AREA 8: Audience Chamber" -#define HUSTR_9 "AREA 9: Castle: Programmer's Keep" - -#define HUSTR_10 "AREA 10: New Front Base" -#define HUSTR_11 "AREA 11: Borderlands" -#define HUSTR_12 "AREA 12: the temple of the oracle" -#define HUSTR_13 "AREA 13: Catacombs" -#define HUSTR_14 "AREA 14: mines" -#define HUSTR_15 "AREA 15: Fortress: Administration" -#define HUSTR_16 "AREA 16: Fortress: Bishop's Tower" -#define HUSTR_17 "AREA 17: Fortress: The Bailey" -#define HUSTR_18 "AREA 18: Fortress: Stores" -#define HUSTR_19 "AREA 19: Fortress: Security Complex" - -#define HUSTR_20 "AREA 20: Factory: Receiving" -#define HUSTR_21 "AREA 21: Factory: Manufacturing" -#define HUSTR_22 "AREA 22: Factory: Forge" -#define HUSTR_23 "AREA 23: Order Commons" -#define HUSTR_24 "AREA 24: Factory: Conversion Chapel" -#define HUSTR_25 "AREA 25: Catacombs: Ruined Temple" -#define HUSTR_26 "AREA 26: proving grounds" -#define HUSTR_27 "AREA 27: The Lab" -#define HUSTR_28 "AREA 28: Alien Ship" -#define HUSTR_29 "AREA 29: Entity's Lair" - -#define HUSTR_30 "AREA 30: Abandoned Front Base" -#define HUSTR_31 "AREA 31: Training Facility" - -#define HUSTR_32 "AREA 1: Sanctuary" -#define HUSTR_33 "AREA 2: Town" -#define HUSTR_34 "AREA 3: Movement Base" - -// haleyjd 20110219: [STRIFE] replaced all with Strife chat macros: -#define HUSTR_CHATMACRO1 "Fucker!" -#define HUSTR_CHATMACRO2 "--SPLAT-- Instant wall art." -#define HUSTR_CHATMACRO3 "That had to hurt!" -#define HUSTR_CHATMACRO4 "Smackings!" -#define HUSTR_CHATMACRO5 "Gib-O-Matic baby." -#define HUSTR_CHATMACRO6 "Burn! Yah! Yah!" -#define HUSTR_CHATMACRO7 "Buh-Bye!" -#define HUSTR_CHATMACRO8 "Sizzle chest!" -#define HUSTR_CHATMACRO9 "That sucked!" -#define HUSTR_CHATMACRO0 "Mommy?" - -#define HUSTR_TALKTOSELF1 "You mumble to yourself" -#define HUSTR_TALKTOSELF2 "Who's there?" -#define HUSTR_TALKTOSELF3 "You scare yourself" -#define HUSTR_TALKTOSELF4 "You start to rave" -#define HUSTR_TALKTOSELF5 "You've lost it..." - -#define HUSTR_MESSAGESENT "[Message Sent]" - -// The following should NOT be changed unless it seems -// just AWFULLY necessary - -// [STRIFE]: Not used, as strings are local to hu_stuff.c -//#define HUSTR_PLRGREEN "Green: " -//#define HUSTR_PLRINDIGO "Indigo: " -//#define HUSTR_PLRBROWN "Brown: " -//#define HUSTR_PLRRED "Red: " - -#define HUSTR_KEYGREEN 'g' -#define HUSTR_KEYINDIGO 'i' -#define HUSTR_KEYBROWN 'b' -#define HUSTR_KEYRED 'r' - -// -// AM_map.C -// - -#define AMSTR_FOLLOWON "Follow Mode ON" -#define AMSTR_FOLLOWOFF "Follow Mode OFF" - -#define AMSTR_GRIDON "Grid ON" -#define AMSTR_GRIDOFF "Grid OFF" - -#define AMSTR_MARKEDSPOT "Marked Spot" -#define AMSTR_MARKSCLEARED "Last Mark Cleared" // [STRIFE] - -// -// ST_stuff.C -// - -#define STSTR_MUS "Music Change" -#define STSTR_NOMUS "IMPOSSIBLE SELECTION" -#define STSTR_DQDON "You're Invincible!" // [STRIFE] -#define STSTR_DQDOFF "You're a looney!" // [STRIFE] - -#define STSTR_KFAADDED "Very Happy Ammo Added" -#define STSTR_FAADDED "Ammo Added" // [STRIFE] - -#define STSTR_NCON "No Clipping Mode ON" -#define STSTR_NCOFF "No Clipping Mode OFF" - -#define STSTR_BEHOLD "Bzrk, Inviso, Mask, Health, Pack, Stats" // [STRIFE] -#define STSTR_BEHOLDX "Power-up Toggled" - -#define STSTR_CHOPPERS "... doesn't suck - GM" -#define STSTR_CLEV "Changing Level..." - -// -// F_Finale.C -// -#define E1TEXT \ -"Once you beat the big badasses and\n"\ -"clean out the moon base you're supposed\n"\ -"to win, aren't you? Aren't you? Where's\n"\ -"your fat reward and ticket home? What\n"\ -"the hell is this? It's not supposed to\n"\ -"end this way!\n"\ -"\n" \ -"It stinks like rotten meat, but looks\n"\ -"like the lost Deimos base. Looks like\n"\ -"you're stuck on The Shores of Hell.\n"\ -"The only way out is through.\n"\ -"\n"\ -"To continue the DOOM experience, play\n"\ -"The Shores of Hell and its amazing\n"\ -"sequel, Inferno!\n" - - -#define E2TEXT \ -"You've done it! The hideous cyber-\n"\ -"demon lord that ruled the lost Deimos\n"\ -"moon base has been slain and you\n"\ -"are triumphant! But ... where are\n"\ -"you? You clamber to the edge of the\n"\ -"moon and look down to see the awful\n"\ -"truth.\n" \ -"\n"\ -"Deimos floats above Hell itself!\n"\ -"You've never heard of anyone escaping\n"\ -"from Hell, but you'll make the bastards\n"\ -"sorry they ever heard of you! Quickly,\n"\ -"you rappel down to the surface of\n"\ -"Hell.\n"\ -"\n" \ -"Now, it's on to the final chapter of\n"\ -"DOOM! -- Inferno." - - -#define E3TEXT \ -"The loathsome spiderdemon that\n"\ -"masterminded the invasion of the moon\n"\ -"bases and caused so much death has had\n"\ -"its ass kicked for all time.\n"\ -"\n"\ -"A hidden doorway opens and you enter.\n"\ -"You've proven too tough for Hell to\n"\ -"contain, and now Hell at last plays\n"\ -"fair -- for you emerge from the door\n"\ -"to see the green fields of Earth!\n"\ -"Home at last.\n" \ -"\n"\ -"You wonder what's been happening on\n"\ -"Earth while you were battling evil\n"\ -"unleashed. It's good that no Hell-\n"\ -"spawn could have come through that\n"\ -"door with you ..." - - -#define E4TEXT \ -"the spider mastermind must have sent forth\n"\ -"its legions of hellspawn before your\n"\ -"final confrontation with that terrible\n"\ -"beast from hell. but you stepped forward\n"\ -"and brought forth eternal damnation and\n"\ -"suffering upon the horde as a true hero\n"\ -"would in the face of something so evil.\n"\ -"\n"\ -"besides, someone was gonna pay for what\n"\ -"happened to daisy, your pet rabbit.\n"\ -"\n"\ -"but now, you see spread before you more\n"\ -"potential pain and gibbitude as a nation\n"\ -"of demons run amok among our cities.\n"\ -"\n"\ -"next stop, hell on earth!" - - -// after level 6, put this: - -#define C1TEXT \ -"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \ -"STARPORT. BUT SOMETHING IS WRONG. THE\n" \ -"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \ -"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \ -"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \ -"\n"\ -"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \ -"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \ -"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \ -"OF THE STARBASE AND FIND THE CONTROLLING\n" \ -"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \ -"HOSTAGE." - -// After level 11, put this: - -#define C2TEXT \ -"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \ -"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\ -"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\ -"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\ -"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\ -"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\ -"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\ -"THAT YOU HAVE SAVED YOUR SPECIES.\n"\ -"\n"\ -"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\ -"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\ -"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\ -"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\ -"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\ -"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\ -"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\ -"UP AND RETURN TO THE FRAY." - - -// After level 20, put this: - -#define C3TEXT \ -"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\ -"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\ -"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\ -"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\ -"TEETH AND PLUNGE THROUGH IT.\n"\ -"\n"\ -"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\ -"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\ -"GOT TO GO THROUGH HELL TO GET TO IT?" - - -// After level 29, put this: - -#define C4TEXT \ -"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\ -"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\ -"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\ -"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\ -"UP AND DIES, ITS THRASHING LIMBS\n"\ -"DEVASTATING UNTOLD MILES OF HELL'S\n"\ -"SURFACE.\n"\ -"\n"\ -"YOU'VE DONE IT. THE INVASION IS OVER.\n"\ -"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\ -"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\ -"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\ -"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\ -"HOME. REBUILDING EARTH OUGHT TO BE A\n"\ -"LOT MORE FUN THAN RUINING IT WAS.\n" - - - -// Before level 31, put this: - -#define C5TEXT \ -"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\ -"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\ -"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\ -"WHO THE INMATES OF THIS CORNER OF HELL\n"\ -"WILL BE." - - -// Before level 32, put this: - -#define C6TEXT \ -"CONGRATULATIONS, YOU'VE FOUND THE\n"\ -"SUPER SECRET LEVEL! YOU'D BETTER\n"\ -"BLAZE THROUGH THIS ONE!\n" - - -// after map 06 - -#define P1TEXT \ -"You gloat over the steaming carcass of the\n"\ -"Guardian. With its death, you've wrested\n"\ -"the Accelerator from the stinking claws\n"\ -"of Hell. You relax and glance around the\n"\ -"room. Damn! There was supposed to be at\n"\ -"least one working prototype, but you can't\n"\ -"see it. The demons must have taken it.\n"\ -"\n"\ -"You must find the prototype, or all your\n"\ -"struggles will have been wasted. Keep\n"\ -"moving, keep fighting, keep killing.\n"\ -"Oh yes, keep living, too." - - -// after map 11 - -#define P2TEXT \ -"Even the deadly Arch-Vile labyrinth could\n"\ -"not stop you, and you've gotten to the\n"\ -"prototype Accelerator which is soon\n"\ -"efficiently and permanently deactivated.\n"\ -"\n"\ -"You're good at that kind of thing." - - -// after map 20 - -#define P3TEXT \ -"You've bashed and battered your way into\n"\ -"the heart of the devil-hive. Time for a\n"\ -"Search-and-Destroy mission, aimed at the\n"\ -"Gatekeeper, whose foul offspring is\n"\ -"cascading to Earth. Yeah, he's bad. But\n"\ -"you know who's worse!\n"\ -"\n"\ -"Grinning evilly, you check your gear, and\n"\ -"get ready to give the bastard a little Hell\n"\ -"of your own making!" - -// after map 30 - -#define P4TEXT \ -"The Gatekeeper's evil face is splattered\n"\ -"all over the place. As its tattered corpse\n"\ -"collapses, an inverted Gate forms and\n"\ -"sucks down the shards of the last\n"\ -"prototype Accelerator, not to mention the\n"\ -"few remaining demons. You're done. Hell\n"\ -"has gone back to pounding bad dead folks \n"\ -"instead of good live ones. Remember to\n"\ -"tell your grandkids to put a rocket\n"\ -"launcher in your coffin. If you go to Hell\n"\ -"when you die, you'll need it for some\n"\ -"final cleaning-up ..." - -// before map 31 - -#define P5TEXT \ -"You've found the second-hardest level we\n"\ -"got. Hope you have a saved game a level or\n"\ -"two previous. If not, be prepared to die\n"\ -"aplenty. For master marines only." - -// before map 32 - -#define P6TEXT \ -"Betcha wondered just what WAS the hardest\n"\ -"level we had ready for ya? Now you know.\n"\ -"No one gets out alive." - - -#define T1TEXT \ -"You've fought your way out of the infested\n"\ -"experimental labs. It seems that UAC has\n"\ -"once again gulped it down. With their\n"\ -"high turnover, it must be hard for poor\n"\ -"old UAC to buy corporate health insurance\n"\ -"nowadays..\n"\ -"\n"\ -"Ahead lies the military complex, now\n"\ -"swarming with diseased horrors hot to get\n"\ -"their teeth into you. With luck, the\n"\ -"complex still has some warlike ordnance\n"\ -"laying around." - - -#define T2TEXT \ -"You hear the grinding of heavy machinery\n"\ -"ahead. You sure hope they're not stamping\n"\ -"out new hellspawn, but you're ready to\n"\ -"ream out a whole herd if you have to.\n"\ -"They might be planning a blood feast, but\n"\ -"you feel about as mean as two thousand\n"\ -"maniacs packed into one mad killer.\n"\ -"\n"\ -"You don't plan to go down easy." - - -#define T3TEXT \ -"The vista opening ahead looks real damn\n"\ -"familiar. Smells familiar, too -- like\n"\ -"fried excrement. You didn't like this\n"\ -"place before, and you sure as hell ain't\n"\ -"planning to like it now. The more you\n"\ -"brood on it, the madder you get.\n"\ -"Hefting your gun, an evil grin trickles\n"\ -"onto your face. Time to take some names." - -#define T4TEXT \ -"Suddenly, all is silent, from one horizon\n"\ -"to the other. The agonizing echo of Hell\n"\ -"fades away, the nightmare sky turns to\n"\ -"blue, the heaps of monster corpses start \n"\ -"to evaporate along with the evil stench \n"\ -"that filled the air. Jeeze, maybe you've\n"\ -"done it. Have you really won?\n"\ -"\n"\ -"Something rumbles in the distance.\n"\ -"A blue light begins to glow inside the\n"\ -"ruined skull of the demon-spitter." - - -#define T5TEXT \ -"What now? Looks totally different. Kind\n"\ -"of like King Tut's condo. Well,\n"\ -"whatever's here can't be any worse\n"\ -"than usual. Can it? Or maybe it's best\n"\ -"to let sleeping gods lie.." - - -#define T6TEXT \ -"Time for a vacation. You've burst the\n"\ -"bowels of hell and by golly you're ready\n"\ -"for a break. You mutter to yourself,\n"\ -"Maybe someone else can kick Hell's ass\n"\ -"next time around. Ahead lies a quiet town,\n"\ -"with peaceful flowing water, quaint\n"\ -"buildings, and presumably no Hellspawn.\n"\ -"\n"\ -"As you step off the transport, you hear\n"\ -"the stomp of a cyberdemon's iron shoe." - - - -// -// Character cast strings F_FINALE.C -// -#define CC_ZOMBIE "ZOMBIEMAN" -#define CC_SHOTGUN "SHOTGUN GUY" -#define CC_HEAVY "HEAVY WEAPON DUDE" -#define CC_IMP "IMP" -#define CC_DEMON "DEMON" -#define CC_LOST "LOST SOUL" -#define CC_CACO "CACODEMON" -#define CC_HELL "HELL KNIGHT" -#define CC_BARON "BARON OF HELL" -#define CC_ARACH "ARACHNOTRON" -#define CC_PAIN "PAIN ELEMENTAL" -#define CC_REVEN "REVENANT" -#define CC_MANCU "MANCUBUS" -#define CC_ARCH "ARCH-VILE" -#define CC_SPIDER "THE SPIDER MASTERMIND" -#define CC_CYBER "THE CYBERDEMON" -#define CC_HERO "OUR HERO" - - -#endif diff --git a/games/NXDoom/src/strife/d_items.c b/games/NXDoom/src/strife/d_items.c deleted file mode 100644 index a57ed61ea84..00000000000 --- a/games/NXDoom/src/strife/d_items.c +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// - - -// We are referring to sprite numbers. -#include "info.h" - -#include "d_items.h" - - -// -// PSPRITE ACTIONS for waepons. -// This struct controls the weapon animations. -// -// Each entry is: -// ammo/amunition type -// upstate -// downstate -// readystate -// atkstate, i.e. attack/fire/hit frame -// flashstate, muzzle flash -// - -// villsa [STRIFE] -weaponinfo_t weaponinfo[NUMWEAPONS] = -{ - { - // fist - am_noammo, - S_PNCH_03, - S_PNCH_02, - S_PNCH_01, - S_PNCH_04, - S_NULL, - 1 - }, - { - // electric bow - am_elecbolts, - S_XBOW_02, - S_XBOW_01, - S_XBOW_00, - S_XBOW_03, - S_NULL, - 1 - }, - { - // rifle - am_bullets, - S_RIFG_02, - S_RIFG_01, - S_RIFG_00, - S_RIFF_00, - S_NULL, - 1 - }, - { - // missile launcher - am_missiles, - S_MMIS_02, - S_MMIS_01, - S_MMIS_00, - S_MMIS_03, - S_NULL, - 0 - }, - { - // grenade launcher - am_hegrenades, - S_GREN_02, - S_GREN_01, - S_GREN_00, - S_GREN_03, - S_GREF_00, - 0 - }, - { - // flame thrower - am_cell, - S_FLMT_03, - S_FLMT_02, - S_FLMT_00, - S_FLMF_00, - S_NULL, - 1 - }, - { - // mauler - am_cell, - S_BLST_05, - S_BLST_04, - S_BLST_00, - S_BLSF_00, - S_NULL, - 0 - }, - { - // sigil - am_noammo, - S_SIGH_06, - S_SIGH_05, - S_SIGH_00, - S_SIGH_07, - S_SIGF_00, - 0 - }, - { - // poison bow - am_poisonbolts, - S_XBOW_15, - S_XBOW_14, - S_XBOW_13, - S_XBOW_16, - S_NULL, - 1 - }, - { - // wp grenade launcher - am_wpgrenades, - S_GREN_10, - S_GREN_09, - S_GREN_08, - S_GREN_11, - S_GREF_03, - 0 - }, - { - // torpedo - am_cell, - S_BLST_18, - S_BLST_17, - S_BLST_13, - S_BLST_19, - S_NULL, - 0 - }, -}; - - - - - - - - diff --git a/games/NXDoom/src/strife/d_items.h b/games/NXDoom/src/strife/d_items.h deleted file mode 100644 index eb4d725f29c..00000000000 --- a/games/NXDoom/src/strife/d_items.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Items: key cards, artifacts, weapon, ammunition. -// - - -#ifndef __D_ITEMS__ -#define __D_ITEMS__ - -#include "doomdef.h" - - - -// Weapon info: sprite frames, ammunition use. -typedef struct -{ - ammotype_t ammo; - int upstate; - int downstate; - int readystate; - int atkstate; - int flashstate; - boolean availabledemo; // villsa [STRIFE] - -} weaponinfo_t; - -extern weaponinfo_t weaponinfo[NUMWEAPONS]; - -#endif diff --git a/games/NXDoom/src/strife/d_main.c b/games/NXDoom/src/strife/d_main.c deleted file mode 100644 index 56372b53803..00000000000 --- a/games/NXDoom/src/strife/d_main.c +++ /dev/null @@ -1,2191 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM main program (D_DoomMain) and game loop (D_DoomLoop), -// plus functions to determine game mode (shareware, registered), -// parse command line parameters, configure game parameters (turbo), -// and call the startup functions. -// - - -#include -#include -#include -#include - -#include "config.h" -#include "deh_main.h" -#include "doomdef.h" -#include "doomstat.h" - -#include "dstrings.h" -#include "sounds.h" - -#include "txt_main.h" -#include "txt_io.h" - -#include "d_iwad.h" - -#include "z_zone.h" -#include "w_main.h" -#include "w_wad.h" -#include "s_sound.h" -#include "v_diskicon.h" -#include "v_video.h" - -#include "f_finale.h" -#include "f_wipe.h" - -#include "m_argv.h" -#include "m_config.h" -#include "m_controls.h" -#include "m_misc.h" -#include "m_menu.h" -#include "m_saves.h" // haleyjd [STRIFE] -#include "p_saveg.h" -#include "p_dialog.h" // haleyjd [STRIFE] - -#include "i_endoom.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "i_swap.h" - -#include "g_game.h" - -#include "hu_stuff.h" -#include "wi_stuff.h" -#include "st_stuff.h" -#include "am_map.h" -#include "net_client.h" -#include "net_dedicated.h" -#include "net_query.h" - -#include "p_setup.h" -#include "r_local.h" - -#include "d_main.h" - -#include "strife_icon.c" - -// -// D-DoomLoop() -// Not a globally visible function, -// just included for source reference, -// called by D_DoomMain, never exits. -// Manages timing and IO, -// calls all ?_Responder, ?_Ticker, and ?_Drawer, -// calls I_GetTime, I_StartFrame, and I_StartTic -// -void D_DoomLoop (void); - -static boolean D_AddFile(char *filename); - -// Location where savegames are stored - -char * savegamedir; - -// location of IWAD and WAD files - -char * iwadfile; - - -boolean devparm; // started game with -devparm -boolean nomonsters; // checkparm of -nomonsters -boolean respawnparm; // checkparm of -respawn -boolean fastparm; // checkparm of -fast -boolean flipparm; // [STRIFE] haleyjd 20110629: checkparm of -flip -boolean randomparm; // [STRIFE] haleyjd 20130915: checkparm of -random - -boolean showintro = true; // [STRIFE] checkparm of -nograph, disables intro - - -skill_t startskill; -int startepisode; -int startmap; -boolean autostart; -int startloadgame; - -boolean advancedemo; - -// villsa [STRIFE] workparm variable (similar to devparm?) -boolean workparm = false; - -// villsa [STRIFE] stonecold cheat variable -boolean stonecold = false; - -// haleyjd 09/11/10: [STRIFE] Game type variables -boolean isregistered; -boolean isdemoversion; - -// Store demo, do not accept any inputs -// haleyjd [STRIFE] Unused. -//boolean storedemo; - - -int show_endoom = 1; -int show_diskicon = 1; -int graphical_startup = 1; -static boolean using_text_startup; - -// If true, startup has completed and the main game loop has started. - -static boolean main_loop_started = false; - -// fraggle 06/03/11 [STRIFE]: Unused config variable, preserved -// for compatibility: - -static int comport = 0; - -// fraggle 06/03/11 [STRIFE]: Multiplayer nickname? -char *nickname = NULL; - -void D_ConnectNetGame(void); -void D_CheckNetGame(void); - - -// -// D_ProcessEvents -// Send all the events of the given timestamp down the responder chain -// -void D_ProcessEvents (void) -{ - event_t* ev; - - // haleyjd 08/22/2010: [STRIFE] there is no such thing as a "store demo" - // version of Strife - - // IF STORE DEMO, DO NOT ACCEPT INPUT - //if (storedemo) - // return; - - while ((ev = D_PopEvent()) != NULL) - { - if (M_Responder (ev)) - continue; // menu ate the event - G_Responder (ev); - } -} - - - - -// -// D_Display -// draw current display, possibly wiping it from the previous -// -// wipegamestate can be set to -1 to force a wipe on the next draw -// -// haleyjd 08/23/10: [STRIFE]: -// * Changes to eliminate intermission and change timing of screenwipe -// * 20100901: Added ST_DrawExternal and popupactivestate static variable -// * 20110206: Start wipegamestate at GS_UNKNOWN (STRIFE-TODO: rename?) -// -gamestate_t wipegamestate = GS_UNKNOWN; - -void D_Display (void) -{ - static boolean viewactivestate = false; - static boolean menuactivestate = false; - static boolean inhelpscreensstate = false; - static boolean popupactivestate = false; // [STRIFE] - static boolean fullscreen = false; - static gamestate_t oldgamestate = -1; - static int borderdrawcount; - int nowtime; - int tics; - int wipestart; - int y; - boolean done; - boolean wipe; - boolean redrawsbar; - - if (nodrawers) - return; // for comparative timing / profiling - - redrawsbar = false; - - // change the view size if needed - if (setsizeneeded) - { - R_ExecuteSetViewSize (); - oldgamestate = -1; // force background redraw - borderdrawcount = 3; - } - - // save the current screen if about to wipe - if (gamestate != wipegamestate) - { - wipe = true; - wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); - } - else - wipe = false; - - if (gamestate == GS_LEVEL && gametic) - HU_Erase(); - - // do buffered drawing - switch (gamestate) - { - case GS_LEVEL: - if (!gametic) - break; - if (automapactive) - AM_Drawer (); - if (wipe || (viewheight != 200 && fullscreen) ) - redrawsbar = true; - // haleyjd 08/29/10: [STRIFE] Always redraw sbar if menu is/was active - if (menuactivestate || (inhelpscreensstate && !inhelpscreens)) - redrawsbar = true; // just put away the help screen - ST_Drawer (viewheight == 200, redrawsbar ); - fullscreen = viewheight == 200; - break; - - // haleyjd 08/23/2010: [STRIFE] No intermission - /* - case GS_INTERMISSION: - WI_Drawer (); - break; - */ - - case GS_FINALE: - F_Drawer (); - break; - - case GS_DEMOSCREEN: - D_PageDrawer (); - break; - - default: - break; - } - - // draw buffered stuff to screen - I_UpdateNoBlit (); - - // draw the view directly - if (gamestate == GS_LEVEL && !automapactive && gametic) - R_RenderPlayerView (&players[displayplayer]); - - // clean up border stuff - if (gamestate != oldgamestate && gamestate != GS_LEVEL) - I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); - - // see if the border needs to be initially drawn - if (gamestate == GS_LEVEL && oldgamestate != GS_LEVEL) - { - viewactivestate = false; // view was not active - R_FillBackScreen (); // draw the pattern into the back screen - } - - // see if the border needs to be updated to the screen - if (gamestate == GS_LEVEL && !automapactive && scaledviewwidth != 320) - { - if (menuactive || menuactivestate || !viewactivestate) - { - borderdrawcount = 3; - popupactivestate = false; - } - if (borderdrawcount) - { - R_DrawViewBorder (); // erase old menu stuff - borderdrawcount--; - } - - } - - if (testcontrols) - { - // Box showing current mouse speed - - V_DrawMouseSpeedBox(testcontrols_mousespeed); - } - - menuactivestate = menuactive; - viewactivestate = viewactive; - inhelpscreensstate = inhelpscreens; - oldgamestate = wipegamestate = gamestate; - - // haleyjd 20120208: [STRIFE] Rogue moved this down to below border drawing - if (gamestate == GS_LEVEL && gametic) - { - HU_Drawer (); - if(ST_DrawExternal()) - popupactivestate = true; - else if(popupactivestate) - { - popupactivestate = false; - menuactivestate = 1; - } - } - - // draw pause pic - if (paused) - { - if (automapactive) - y = 4; - else - y = viewwindowy+4; - V_DrawPatchDirect(viewwindowx + (scaledviewwidth - 68) / 2, y, - W_CacheLumpName (DEH_String("M_PAUSE"), PU_CACHE)); - } - - - // menus go directly to the screen - M_Drawer (); // menu is drawn even on top of everything - NetUpdate (); // send out any new accumulation - - - // normal update - if (!wipe) - { - I_FinishUpdate (); // page flip or blit buffer - return; - } - - // wipe update - wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); - - wipestart = I_GetTime () - 1; - - do - { - do - { - nowtime = I_GetTime (); - tics = nowtime - wipestart; - I_Sleep(1); - } while (tics < 3); // haleyjd 08/23/2010: [STRIFE] Changed from == 0 to < 3 - - // haleyjd 08/26/10: [STRIFE] Changed to use ColorXForm wipe. - wipestart = nowtime; - done = wipe_ScreenWipe(wipe_ColorXForm - , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics); - I_UpdateNoBlit (); - M_Drawer (); // menu is drawn even on top of wipes - I_FinishUpdate (); // page flip or blit buffer - } while (!done); -} - -// -// Add configuration file variable bindings. -// - - -static const char * const chat_macro_defaults[10] = -{ - HUSTR_CHATMACRO0, - HUSTR_CHATMACRO1, - HUSTR_CHATMACRO2, - HUSTR_CHATMACRO3, - HUSTR_CHATMACRO4, - HUSTR_CHATMACRO5, - HUSTR_CHATMACRO6, - HUSTR_CHATMACRO7, - HUSTR_CHATMACRO8, - HUSTR_CHATMACRO9 -}; - - -void D_BindVariables(void) -{ - int i; - - M_ApplyPlatformDefaults(); - - I_BindInputVariables(); - I_BindVideoVariables(); - I_BindJoystickVariables(); - I_BindSoundVariables(); - - M_BindBaseControls(); - M_BindWeaponControls(); - M_BindMapControls(); - M_BindMenuControls(); - M_BindStrifeControls(); // haleyjd 09/01/10: [STRIFE] - M_BindChatControls(MAXPLAYERS); - - // haleyjd 20130915: Strife chat keys - key_multi_msgplayer[0] = '1'; - key_multi_msgplayer[1] = '2'; - key_multi_msgplayer[2] = '3'; - key_multi_msgplayer[3] = '4'; - key_multi_msgplayer[4] = '5'; - key_multi_msgplayer[5] = '6'; - key_multi_msgplayer[6] = '7'; - key_multi_msgplayer[7] = '8'; - - NET_BindVariables(); - - // haleyjd 08/29/10: [STRIFE] - // * Added voice volume - // * Added back flat - // * Removed show_messages - // * Added show_talk - // fraggle 03/06/10: [STRIFE] - // * Removed detailLevel - // * screenblocks -> screensize - // * Added nickname, comport - - M_BindIntVariable("mouse_sensitivity", &mouseSensitivity); - M_BindIntVariable("sfx_volume", &sfxVolume); - M_BindIntVariable("music_volume", &musicVolume); - M_BindIntVariable("voice_volume", &voiceVolume); - M_BindIntVariable("show_talk", &dialogshowtext); - M_BindIntVariable("screensize", &screenblocks); - M_BindIntVariable("snd_channels", &snd_channels); - M_BindIntVariable("vanilla_savegame_limit", &vanilla_savegame_limit); - M_BindIntVariable("vanilla_demo_limit", &vanilla_demo_limit); - M_BindIntVariable("show_endoom", &show_endoom); - M_BindIntVariable("show_diskicon", &show_diskicon); - M_BindIntVariable("graphical_startup", &graphical_startup); - - M_BindStringVariable("back_flat", &back_flat); - M_BindStringVariable("nickname", &nickname); - - M_BindIntVariable("comport", &comport); - - // Multiplayer chat macros - - for (i=0; i<10; ++i) - { - char buf[12]; - - chat_macros[i] = M_StringDuplicate(chat_macro_defaults[i]); - M_snprintf(buf, sizeof(buf), "chatmacro%i", i); - M_BindStringVariable(buf, &chat_macros[i]); - } -} - -// -// D_GrabMouseCallback -// -// Called to determine whether to grab the mouse pointer -// - -boolean D_GrabMouseCallback(void) -{ - // Drone players don't need mouse focus - - if (drone) - return false; - - // when menu is active or game is paused, release the mouse. - - if (menuactive || paused) - return false; - - // only grab mouse when playing levels (but not demos) - - return (gamestate == GS_LEVEL) && !demoplayback; -} - -// During startup, never grab the mouse. - -static boolean D_StartupGrabCallback(void) -{ - return false; -} - -// -// D_DoomLoop -// -// haleyjd 08/23/10: [STRIFE] Verified unmodified. -// -void D_DoomLoop (void) -{ - if (demorecording) - G_BeginRecording (); - - main_loop_started = true; - - TryRunTics(); - - if (!showintro) - { - I_RegisterWindowIcon(strife_icon_data, strife_icon_w, strife_icon_h); - I_InitGraphics(); - } - - if (show_diskicon) - { - V_EnableLoadingDisk("STDISK", SCREENWIDTH - LOADING_DISK_W, 3); - } - I_SetGrabMouseCallback(D_GrabMouseCallback); - - V_RestoreBuffer(); - R_ExecuteSetViewSize(); - - D_StartGameLoop(); - - if (testcontrols) - { - wipegamestate = gamestate; - } - - while (1) - { - // frame syncronous IO operations - I_StartFrame (); - - // process one or more tics - TryRunTics (); // will run at least one tic - - S_UpdateSounds (players[consoleplayer].mo);// move positional sounds - - // Update display, next frame, with current state. - if (screenvisible) - D_Display (); - } -} - - - -// -// DEMO LOOP -// -int demosequence; -int pagetic; -const char *pagename; - - -// -// D_PageTicker -// Handles timing for warped projection -// -// haleyjd 08/22/2010: [STRIFE] verified unmodified -// -void D_PageTicker (void) -{ - if (--pagetic < 0) - D_AdvanceDemo (); -} - - - -// -// D_PageDrawer -// -// haleyjd 08/22/2010: [STRIFE] verified unmodified -// -void D_PageDrawer (void) -{ - V_DrawPatch (0, 0, W_CacheLumpName(pagename, PU_CACHE)); -} - - -// -// D_AdvanceDemo -// Called after each demo or intro demosequence finishes -// -// haleyjd 08/22/2010: [STRIFE] verified unmodified -// -void D_AdvanceDemo (void) -{ - advancedemo = true; -} - - -// -// This cycles through the demo sequences. -// FIXME - version dependend demo numbers? -// -// [STRIFE] Modified for the opening slideshow and the exit screen -// -void D_DoAdvanceDemo (void) -{ - players[consoleplayer].playerstate = PST_LIVE; // not reborn - advancedemo = false; - usergame = false; // no save / end game here - paused = false; - gameaction = ga_nothing; - - // villsa 09/12/10: [STRIFE] converted pagetics to ticrate - switch (demosequence) - { - case -5: // exit the game - I_Quit(); - return; - case -4: // show exit screen - menuactive = false; - pagetic = 3*TICRATE; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("PANEL7"); - S_StartMusic(mus_fast); - if(isdemoversion) - demosequence = -3; // show Velocity logo - else - demosequence = -5; // exit - return; - case -3: // show Velocity logo for demo version - pagetic = 6*TICRATE; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("vellogo"); - demosequence = -5; // exit - return; - case -2: // title screen - pagetic = 6*TICRATE; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("TITLEPIC"); - S_StartMusic(mus_logo); - demosequence = -1; // start intro cinematic - return; - case -1: // start of intro cinematic - pagetic = 10; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("PANEL0"); - S_StartSound(NULL, sfx_rb2act); - wipegamestate = -1; - break; - case 0: // Rogue logo - pagetic = 4*TICRATE; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("RGELOGO"); - wipegamestate = -1; - break; - case 1: - pagetic = 7*TICRATE; // The comet struck our planet without - gamestate = GS_DEMOSCREEN; // warning.We lost our paradise in a - pagename = DEH_String("PANEL1"); // single, violent stroke. - I_StartVoice(DEH_String("pro1")); - S_StartMusic(mus_intro); - break; - case 2: - pagetic = 9*TICRATE; // The impact released a virus which - gamestate = GS_DEMOSCREEN; // swept through the land and killed - pagename = DEH_String("PANEL2"); // millions. They turned out to be - I_StartVoice(DEH_String("pro2")); // the lucky ones... - break; - case 3: - pagetic = 12*TICRATE; // For those that did not die became - gamestate = GS_DEMOSCREEN; // mutations of humanity. Some became - pagename = DEH_String("PANEL3"); // fanatics who heard the voice of a - I_StartVoice(DEH_String("pro3")); // malignant God in their heads, and - break; // called themselves the Order. - case 4: - pagetic = 11*TICRATE; // Those of us who were deaf to this - pagename = DEH_String("PANEL4"); // voice suffer horribly and are - gamestate = GS_DEMOSCREEN; // forced to serve these ruthless - I_StartVoice(DEH_String("pro4")); // psychotics, who wield weapons more - break; // powerful than anything we can muster. - case 5: - pagetic = 10*TICRATE; // They destroy our women and children, - gamestate = GS_DEMOSCREEN; // so that we must hide them underground, - pagename = DEH_String("PANEL5"); // and live like animals in constant - I_StartVoice(DEH_String("pro5")); // fear for our lives. - break; - case 6: // But there are whispers of discontent. - pagetic = 16*TICRATE; // If we organize, can we defeat our - gamestate = GS_DEMOSCREEN; // masters? Weapons are being stolen, - pagename = DEH_String("PANEL6"); // soldiers are being trained. A - I_StartVoice(DEH_String("pro6")); // Movement is born! Born of lifelong - break; // STRIFE! - case 7: // titlepic again - unused... - pagetic = 9*TICRATE; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("TITLEPIC"); - wipegamestate = -1; - break; - case 8: // demo - ClearTmp(); - pagetic = 9*TICRATE; - G_DeferedPlayDemo(DEH_String("demo1")); - break; - case 9: // velocity logo? - unused... - pagetic = 6*TICRATE; - gamestate = GS_DEMOSCREEN; - pagename = DEH_String("vellogo"); - wipegamestate = -1; - break; - case 10: // credits - gamestate = GS_DEMOSCREEN; - pagetic = 12*TICRATE; - pagename = DEH_String("CREDIT"); - wipegamestate = -1; - break; - default: - break; - } - - ++demosequence; - - if(demosequence > 11) - demosequence = -2; - if(demosequence == 7 || demosequence == 9) - ++demosequence; -} - - - -// -// D_StartTitle -// -// [STRIFE] -// haleyjd 09/11/10: Small modifications for new demo sequence. -// -void D_StartTitle (void) -{ - gamestate = GS_DEMOSCREEN; - gameaction = ga_nothing; - demosequence = -2; - D_AdvanceDemo (); -} - -// -// D_QuitGame -// -// [STRIFE] New function -// haleyjd 09/11/10: Sets up the quit game snippet powered by the -// demo sequence. -// -void D_QuitGame(void) -{ - gameaction = ga_nothing; - demosequence = -4; - D_AdvanceDemo(); -} - -// Strings for dehacked replacements of the startup banner -// -// These are from the original source: some of them are perhaps -// not used in any dehacked patches - -static const char *banners[] = -{ - // strife1.wad: - - " " - "STRIFE: Quest for the Sigil v1.2" - " " -}; - -// -// Get game name: if the startup banner has been replaced, use that. -// Otherwise, use the name given -// - -static char *GetGameName(char *gamename) -{ - size_t i; - const char *deh_sub; - - for (i=0; i 1996 || date.day > 15 && date.month > 4) - I_Error("Data error! Corrupted WAD File!"); - serial_year = serialnum / 10000; - serial_month = serialnum / 100 - 100 * serial_year; - if(date.year < serial_year || - date.day < serialnum - 100 * serial_month - 10000 * serial_year && - date.month < serial_month) - I_Error("Bad wadfile"); -} -#endif - -// Set the gamedescription string - -void D_SetGameDescription(void) -{ - gamedescription = GetGameName("Strife: Quest for the Sigil"); -} - -// print title for every printed line -static char title[128] = ""; - -static void InitTitleString(void) -{ - switch (gameversion) - { - case exe_strife_1_2: - DEH_snprintf(title, sizeof(title), " " - "STRIFE: Quest for the Sigil v1.2" - " " - ); - break; - case exe_strife_1_31: - default: - DEH_snprintf(title, sizeof(title), " " - "STRIFE: Quest for the Sigil v1.31" - " " - ); - break; - } -} - -static boolean D_AddFile(char *filename) -{ - wad_file_t *handle; - - printf(" adding %s\n", filename); - handle = W_AddFile(filename); - - return handle != NULL; -} - -// Copyright message banners -// Some dehacked mods replace these. These are only displayed if they are -// replaced by dehacked. -// haleyjd 08/22/2010: [STRIFE] altered to match strings from binary -static const char *copyright_banners[] = -{ - "===========================================================================\n" - "ATTENTION: This version of STRIFE has extra files added to it.\n" - " You will not receive technical support for modified games.\n" - "===========================================================================\n", - - "===========================================================================\n" - " This version is NOT SHAREWARE, do not distribute!\n" - " Please report software piracy to the SPA: 1-800-388-PIR8\n" - "===========================================================================\n", - - "===========================================================================\n" - " Shareware!\n" - "===========================================================================\n" -}; - -// Prints a message only if it has been modified by dehacked. - -void PrintDehackedBanners(void) -{ - size_t i; - - for (i=0; i - // @category compat - // - // Emulate a specific version of Strife. Valid values are "1.2" and "1.31". - // - - p = M_CheckParmWithArgs("-gameversion", 1); - - if (p) - { - int i; - for (i=0; gameversions[i].description != NULL; ++i) - { - if (!strcmp(myargv[p+1], gameversions[i].cmdline)) - { - gameversion = gameversions[i].version; - break; - } - } - - if (gameversions[i].description == NULL) - { - printf("Supported game versions:\n"); - - for (i=0; gameversions[i].description != NULL; ++i) - { - printf("\t%s (%s)\n", gameversions[i].cmdline, - gameversions[i].description); - } - - I_Error("Unknown game version '%s'", myargv[p+1]); - } - } - else - { - gameversion = exe_strife_1_31; - } -} - -void PrintGameVersion(void) -{ - int i; - - for (i=0; gameversions[i].description != NULL; ++i) - { - if (gameversions[i].version == gameversion) - { - printf("Emulating the behavior of the " - "'%s' executable.\n", gameversions[i].description); - break; - } - } -} - -// Function called at exit to display the ENDOOM screen - -static void D_Endoom(void) -{ - byte *endoom; - - // Don't show ENDOOM if we have it disabled, or we're running - // in screensaver or control test mode. Only show it once the - // game has actually started. - - - if (!show_endoom || !main_loop_started || screensaver_mode || testcontrols) - { - return; - } - - // haleyjd 08/27/10: [STRIFE] ENDOOM -> ENDSTRF - endoom = W_CacheLumpName(DEH_String("ENDSTRF"), PU_STATIC); - - I_Endoom(endoom); -} - -// -// D_GetCursorColumn -// -static int D_GetCursorColumn(void) -{ - int x, y; - TXT_GetXY(&x, &y); - return x; -} - -// -// D_GetCursorRow -// -static int D_GetCursorRow(void) -{ - int x, y; - TXT_GetXY(&x, &y); - return y; -} - -// -// D_SetCursorPosition -// -static void D_SetCursorPosition(int column, int row) -{ - TXT_GotoXY(column, row); -} - -// -// D_SetChar -// -static void D_SetChar(char c) -{ - int x, y; - // Backup position - TXT_GetXY(&x, &y); - TXT_PutChar(c); - // Restore position - TXT_GotoXY(x, y); -} - -// -// D_DrawText -// -static void D_DrawText(const char *string, int bc, int fc) -{ - int column; - int row; - int i; - - if (!using_text_startup) - { - return; - } - - // Set text color - TXT_BGColor(bc, 0); - TXT_FGColor(fc); - - // Get column position - column = D_GetCursorColumn(); - - // Get row position - row = D_GetCursorRow(); - - for (i = 0; i < strlen(string); i++) - { - // Set character - D_SetChar(string[i]); - - // Check cursor position - if (++column >= 80) - column = 0; - - // Set postition - D_SetCursorPosition(column, row); - } -} - -//============================================================================= -// -// haleyjd: Chocolate Strife Specifics -// -// None of the code in here is from the original executable, but is needed for -// other reasons. - -// -// D_PatchClipCallback -// -// haleyjd 08/28/10: Clip patches to the framebuffer without errors. -// Returns false if V_DrawPatch should return without drawing. -// -boolean D_PatchClipCallback(patch_t *patch, int x, int y) -{ - // note that offsets were already accounted for in V_DrawPatch - return (x >= 0 && y >= 0 - && x + SHORT(patch->width) <= SCREENWIDTH - && y + SHORT(patch->height) <= SCREENHEIGHT); -} - -// -// D_InitChocoStrife -// -// haleyjd 08/28/10: Take care of some Strife-specific initialization -// that is necessitated by Chocolate Doom issues, such as setting global -// callbacks. -// -static void D_InitChocoStrife(void) -{ - // set the V_DrawPatch clipping callback - V_SetPatchClipCallback(D_PatchClipCallback); -} - - -// -// STRIFE Graphical Intro Sequence -// - -#define MAXINTROPROGRESS 69 - -static int introprogress; // track the progress of the intro - -static byte *rawgfx_startup0; // raw linear gfx for intro -static byte *rawgfx_startp[4]; -static byte *rawgfx_startlz[2]; -static byte *rawgfx_startbot; - -// -// D_IntroBackground -// -// [STRIFE] New function -// haleyjd 20110206: Strife only drew this once, but for supporting double- -// buffered or page-flipped surfaces it is best to redraw the entire screen -// every frame. -// -static void D_IntroBackground(void) -{ - if(!showintro) - return; - - // Fill the background entirely (wasn't needed in vanilla) - V_DrawFilledBox(0, 0, SCREENWIDTH, SCREENHEIGHT, 0); - - // Strife cleared the screen somewhere in the low-level code between the - // intro and the titlescreen, so this is to take care of that and get - // proper fade-in behavior on the titlescreen - if(introprogress >= MAXINTROPROGRESS) - { - I_FinishUpdate(); - return; - } - - // Draw a 95-pixel rect from STARTUP0 starting at y=57 to (0,41) on the - // screen (this was a memcpy directly to 0xA3340 in low DOS memory) - V_DrawBlock(0, 41, 320, 95, rawgfx_startup0 + (320*57)); -} - -// -// D_InitIntroSequence -// -// [STRIFE] New function -// haleyjd 20110206: Initialize the graphical introduction sequence -// - -static void D_InitIntroSequence(void) -{ - byte *textScreen; - char string[80]; - - if (devparm || !graphical_startup || testcontrols) - { - using_text_startup = false; - showintro = false; - return; - } - - if(showintro) - { - // In vanilla Strife, Mode 13h was initialized directly in D_DoomMain. - // We have to be a little more courteous of the low-level code here. - I_SetGrabMouseCallback(D_StartupGrabCallback); - I_RegisterWindowIcon(strife_icon_data, strife_icon_h, strife_icon_w); - I_InitGraphics(); - V_RestoreBuffer(); // make the V_ routines work - - // Load all graphics - rawgfx_startup0 = W_CacheLumpName("STARTUP0", PU_STATIC); - rawgfx_startp[0] = W_CacheLumpName("STRTPA1", PU_STATIC); - rawgfx_startp[1] = W_CacheLumpName("STRTPB1", PU_STATIC); - rawgfx_startp[2] = W_CacheLumpName("STRTPC1", PU_STATIC); - rawgfx_startp[3] = W_CacheLumpName("STRTPD1", PU_STATIC); - rawgfx_startlz[0] = W_CacheLumpName("STRTLZ1", PU_STATIC); - rawgfx_startlz[1] = W_CacheLumpName("STRTLZ2", PU_STATIC); - rawgfx_startbot = W_CacheLumpName("STRTBOT", PU_STATIC); - - // Draw the background - D_IntroBackground(); - - using_text_startup = false; - } - else - { - if (!TXT_Init()) - { - using_text_startup = false; - return; - } - - I_InitWindowTitle(); - I_InitWindowIcon(); - - // Clear screen - textScreen = TXT_GetScreenData(); - memset(textScreen, 0, 4000); - - using_text_startup = true; - - // Print title - - D_SetCursorPosition(0, 0); - D_DrawText(title, TXT_COLOR_GREEN, TXT_COLOR_BLACK); - - DEH_snprintf(string, sizeof(string), "Rogue Entertainment"); - D_SetCursorPosition(40 - strlen(string) / 2, 5); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - DEH_snprintf(string, sizeof(string), "and"); - D_SetCursorPosition(40 - strlen(string) / 2, 7); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - DEH_snprintf(string, sizeof(string), "Velocity Games"); - D_SetCursorPosition(40 - strlen(string) / 2, 9); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - DEH_snprintf(string, sizeof(string), "present"); - D_SetCursorPosition(40 - strlen(string) / 2, 11); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - DEH_snprintf(string, sizeof(string), "S T R I F E"); - D_SetCursorPosition(40 - strlen(string) / 2, 14); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - DEH_snprintf(string, sizeof(string), "Loading..."); - D_SetCursorPosition(40 - strlen(string) / 2, 17); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - DEH_snprintf(string, sizeof(string), - "[ ]"); - D_SetCursorPosition(14, 18); - D_DrawText(string, TXT_COLOR_BLUE, TXT_COLOR_GREEN); - - TXT_UpdateScreen(); - } -} - -// -// D_DrawIntroSequence -// -// [STRIFE] New function -// haleyjd 20110206: Refresh the intro sequence -// -static void D_DrawIntroSequence(void) -{ - int laserpos; - int robotpos; - int i; - - if (showintro) - { - D_IntroBackground(); // haleyjd: refresh the background - - // Laser position - laserpos = (200 * introprogress / MAXINTROPROGRESS) + 60; - - // BUG: (?) Due to this clip, the laser never even comes close to - // touching the peasant; confirmed with vanilla. This MAY have been - // intentional, for effect, however, since no death frames are shown - // either... kind of a black-out death. - if (laserpos > 200) - laserpos = 200; - - // Draw the laser - // Blitted 16 bytes for 16 rows starting at 705280 + laserpos - // (705280 - 0xA0000) / 320 == 156 - V_DrawBlock(laserpos, 156, 16, 16, rawgfx_startlz[laserpos % 2]); - - // Robot position - robotpos = laserpos % 5 - 2; - - // Draw the robot - // Blitted 48 bytes for 48 rows starting at 699534 + (320*robotpos) - // 699534 - 0xA0000 == 44174, which % 320 == 14, / 320 == 138 - V_DrawBlock(14, 138 + robotpos, 48, 48, rawgfx_startbot); - - // Draw the peasant - // Blitted 32 bytes for 64 rows starting at 699142 - // 699142 - 0xA0000 == 43782, which % 320 == 262, / 320 == 136 - V_DrawBlock(262, 136, 32, 64, rawgfx_startp[laserpos % 4]); - - I_FinishUpdate(); - } - else if (using_text_startup) - { - // Laser position - laserpos = 50 * introprogress / MAXINTROPROGRESS; - - if (laserpos > 50) - { - laserpos = 50; - } - - for (i = 0; i < laserpos; i++) - { - D_SetCursorPosition(15 + i, 18); - D_DrawText("#", TXT_COLOR_GREEN, TXT_COLOR_BLUE); - } - - I_Sleep(10); - - TXT_UpdateScreen(); - } -} - -// -// D_IntroTick -// -// Advance the intro sequence -// -void D_IntroTick(void) -{ - static boolean didsound = false; // haleyjd 20120209 - - if(devparm) - return; - - ++introprogress; - if(introprogress >= MAXINTROPROGRESS) - { - D_IntroBackground(); // haleyjd: clear the bg anyway - - // haleyjd 20120209: This isn't 100% true to vanilla because vanilla - // would play this sound a half-dozen times. BUT, in vanilla, for - // whatever reason, under DMX, playing the same sound multiple times - // doesn't add up violently like it does under SDL_mixer. This means - // that without this one-time limitation, the sound is far too loud. - if(!didsound) - { - S_StartSound(NULL, sfx_psdtha); - didsound = true; - } - } - else - D_DrawIntroSequence(); -} - -// -// End Chocolate Strife Specifics -// -//============================================================================= - -static void G_CheckDemoStatusAtExit (void) -{ - G_CheckDemoStatus(); -} - -// -// D_DoomMain -// -void D_DoomMain (void) -{ - int p; - char file[256]; - char demolumpname[9]; - - I_AtExit(D_Endoom, false); - - // haleyjd 20110206 [STRIFE]: -nograph parameter - - //! - // @vanilla - // - // Disable graphical introduction sequence - // - - if (M_ParmExists("-nograph")) - showintro = false; - - // Undocumented: - // Invoked by setup to test the controls. - - if (M_ParmExists("-testcontrols")) - { - testcontrols = true; - showintro = false; - } - - // haleyjd 20110206: Moved up -devparm for max visibility - - //! - // @vanilla - // - // Developer mode. Implies -nograph. - // - - devparm = M_CheckParm ("-devparm"); - - // print banner - - I_PrintBanner(PACKAGE_STRING); - - //DEH_printf("Z_Init: Init zone memory allocation daemon. \n"); [STRIFE] removed - Z_Init (); - - //! - // @category net - // - // Start a dedicated server, routing packets but not participating - // in the game itself. - // - - if (M_CheckParm("-dedicated") > 0) - { - printf("Dedicated server mode.\n"); - NET_DedicatedServer(); - - // Never returns - } - - //! - // @category net - // - // Query the Internet master server for a global list of active - // servers. - // - - if (M_CheckParm("-search")) - { - NET_MasterQuery(); - exit(0); - } - - //! - // @arg
- // @category net - // - // Query the status of the server running on the given IP - // address. - // - - p = M_CheckParmWithArgs("-query", 1); - - if (p) - { - NET_QueryAddress(myargv[p+1]); - exit(0); - } - - //! - // @category net - // - // Search the local LAN for running servers. - // - - if (M_CheckParm("-localsearch")) - { - NET_LANQuery(); - exit(0); - } - - //! - // @category game - // @vanilla - // - // Disable monsters. - // - - nomonsters = M_CheckParm ("-nomonsters"); - - //! - // @category obscure - // @vanilla - // - // Set Rogue playtesting mode - // (god mode; no cliping mode toggled by backspace). - // - - workparm = M_CheckParm ("-work"); - - //! - // @category obscure - // @vanilla - // - // Flip player gun sprites (broken). - // - - flipparm = M_CheckParm ("-flip"); - - //! - // @category game - // @vanilla - // - // Respawn monsters after they are killed. - // - - respawnparm = M_CheckParm ("-respawn"); - - //! - // @category game - // @vanilla - // - // Items respawn at random locations - // - - randomparm = M_CheckParm ("-random"); - - //! - // @category game - // @vanilla - // - // Monsters move faster. - // - - fastparm = M_CheckParm ("-fast"); - - I_DisplayFPSDots(devparm); - - // haleyjd 20110206 [STRIFE]: -devparm implies -nograph - if(devparm) - showintro = false; - - // Note: Vanilla Strife does not understand the -deathmatch command - // line parameter. deathmatch=1 is the default behavior when - // playing a netgame. - - //! - // @category net - // @vanilla - // - // Start a deathmatch game. Weapons do not stay in place and - // all items respawn after 30 seconds. - // - - if (M_CheckParm ("-altdeath")) - deathmatch = 2; - - if (devparm) - DEH_printf(D_DEVSTR); - - // find which dir to use for config files - -#ifdef _WIN32 - - //! - // @category obscure - // @platform windows - // @vanilla - // - // Save configuration data and savegames in c:\strife.cd, - // allowing play from CD. - // - - if (M_CheckParm("-cdrom") > 0) - { - printf(D_CDROM); - - // haleyjd 08/22/2010: [STRIFE] Use strife.cd folder for -cdrom - M_SetConfigDir("c:\\strife.cd\\"); - } - else -#endif - { - // Auto-detect the configuration dir. - - M_SetConfigDir(NULL); - } - - //! - // @category game - // @arg - // @vanilla - // - // Turbo mode. The player's speed is multiplied by x%. If unspecified, - // x defaults to 200. Values are rounded up to 10 and down to 400. - // - - if ( (p=M_CheckParm ("-turbo")) ) - { - int scale = 200; - - if (p 400) - scale = 400; - DEH_printf("turbo scale: %i%%\n", scale); - forwardmove[0] = forwardmove[0]*scale/100; - forwardmove[1] = forwardmove[1]*scale/100; - sidemove[0] = sidemove[0]*scale/100; - sidemove[1] = sidemove[1]*scale/100; - } - - // init subsystems - // DEH_printf("V_Init: allocate screens.\n"); [STRIFE] removed - V_Init (); - - // Load configuration files before initialising other subsystems. - // haleyjd 08/22/2010: [STRIFE] - use strife.cfg - // DEH_printf("M_LoadDefaults: Load system defaults.\n"); [STRIFE] removed - M_SetConfigFilenames("strife.cfg", PROGRAM_PREFIX "strife.cfg"); - D_BindVariables(); - M_LoadDefaults(); - - // Save configuration at exit. - I_AtExit(M_SaveDefaults, false); - - // Find the main IWAD file and load it. - iwadfile = D_FindIWAD(IWAD_MASK_STRIFE, &gamemission); - - // None found? - if (iwadfile == NULL) - { - I_Error("Game mode indeterminate. No IWAD file was found. Try\n" - "specifying one with the '-iwad' command line parameter.\n"); - } - - modifiedgame = false; - - if(devparm) // [STRIFE] Devparm only - DEH_printf("W_Init: Init WADfiles.\n"); - D_AddFile(iwadfile); - W_CheckCorrectIWAD(strife); - D_IdentifyVersion(); - - //! - // @category mod - // - // Disable auto-loading of .wad files. - // - if (!M_ParmExists("-noautoload")) - { - char *autoload_dir; - autoload_dir = M_GetAutoloadDir("strife1.wad"); - if (autoload_dir != NULL) - { - DEH_AutoLoadPatches(autoload_dir); - W_AutoLoadWADs(autoload_dir); - free(autoload_dir); - } - } - - // Load dehacked patches specified on the command line. - DEH_ParseCommandLine(); - - // Load PWAD files. - modifiedgame = W_ParseCommandLine(); - - // [STRIFE] serial number output - if(devparm) - { - char msgbuf[80]; - char *serial = W_CacheLumpName("SERIAL", PU_CACHE); - int serialnum = atoi(serial); - - DEH_snprintf(msgbuf, sizeof(msgbuf), "Wad Serial Number: %d:", serialnum); - printf("%s\n", msgbuf); - } - - // add any files specified on the command line with -file wadfile - // to the wad list - // - - // Debug: -// W_PrintDirectory(); - - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp. - // - - p = M_CheckParmWithArgs ("-playdemo", 1); - - if (!p) - { - //! - // @arg - // @category demo - // @vanilla - // - // Play back the demo named demo.lmp, determining the framerate - // of the screen. - // - p = M_CheckParmWithArgs("-timedemo", 1); - - } - - if (p) - { - char *uc_filename = strdup(myargv[p + 1]); - M_ForceUppercase(uc_filename); - - // With Vanilla you have to specify the file without extension, - // but make that optional. - if (M_StringEndsWith(uc_filename, ".LMP")) - { - M_StringCopy(file, myargv[p + 1], sizeof(file)); - } - else - { - DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p+1]); - } - - free(uc_filename); - - if (D_AddFile (file)) - { - M_StringCopy(demolumpname, lumpinfo[numlumps - 1]->name, - sizeof(demolumpname)); - } - else - { - // If file failed to load, still continue trying to play - // the demo in the same way as Vanilla Doom. This makes - // tricks like "-playdemo demo1" possible. - - M_StringCopy(demolumpname, myargv[p + 1], sizeof(demolumpname)); - } - - printf("Playing demo %s.\n", file); - } - - I_AtExit(G_CheckDemoStatusAtExit, true); - - // Generate the WAD hash table. Speed things up a bit. - - W_GenerateHashTable(); - - InitGameVersion(); - InitTitleString(); - D_SetGameDescription(); - I_SetWindowTitle(gamedescription); - savegamedir = M_GetSaveGameDir("strife1.wad"); - - // fraggle 20130405: I_InitTimer is needed here for the netgame - // startup. Start low-level sound init here too. - I_InitTimer(); - I_InitSound(strife); - I_InitMusic(); - - if(devparm) // [STRIFE] - printf ("NET_Init: Init network subsystem.\n"); - NET_Init(); - D_ConnectNetGame(); - - // haleyjd 20110210: Create Strife hub save folders - M_CreateSaveDirs(savegamedir); - - I_GraphicsCheckCommandLine(); - - // haleyjd 20110206 [STRIFE] Startup the introduction sequence - D_InitIntroSequence(); - - // haleyjd 20110924: moved S_Init up to here - if(devparm) // [STRIFE] - DEH_printf("S_Init: Setting up sound.\n"); - S_Init (sfxVolume * 8, musicVolume * 8, voiceVolume * 8); // [STRIFE]: voice - D_IntroTick(); // [STRIFE] - - // Check for -file in shareware - if (modifiedgame) - { - // These are the lumps that will be checked in IWAD, - // if any one is not present, execution will be aborted. - // haleyjd 08/22/2010: [STRIFE] Check for Strife lumps. - char name[3][8]= - { - "map23", "map30", "ROB3E1" - }; - int i; - - // haleyjd 08/22/2010: [STRIFE] Changed string to match binary - // STRIFE-FIXME: Needs to test isdemoversion variable - if ( gamemode == shareware) - I_Error(DEH_String("\nYou cannot -file with the demo " - "version. You must buy the real game!")); - - // Check for fake IWAD with right name, - // but w/o all the lumps of the registered version. - // STRIFE-FIXME: Needs to test isregistered variable - if (gamemode == registered) - for (i = 0; i < 3; i++) - if (W_CheckNumForName(name[i])<0) - I_Error(DEH_String("\nThis is not the registered version.")); - } - - D_IntroTick(); // [STRIFE] - - // get skill / episode / map from parms - startskill = sk_easy; // [STRIFE]: inits to sk_easy - startepisode = 1; - startmap = 1; - autostart = false; - - //! - // @category game - // @arg - // @vanilla - // - // Set the game skill, 1-5 (1: easiest, 5: hardest). A skill of - // 0 disables all monsters. - // - - p = M_CheckParmWithArgs("-skill", 1); - - if (p) - { - startskill = myargv[p+1][0]-'1'; - autostart = true; - } - - // [STRIFE] no such thing in Strife - // - // // @category game - // // @arg - // // @vanilla - // // - // // Start playing episode n (1-4). - // // - - // p = M_CheckParmWithArgs("-episode", 1); - - // if (p) - // { - // startepisode = myargv[p+1][0]-'0'; - // startmap = 1; - // autostart = true; - // } - - timelimit = 0; - - //! - // @arg - // @category net - // @vanilla - // - // For multiplayer games: exit each level after n minutes. - // - - p = M_CheckParmWithArgs("-timer", 1); - - if (p) - { - timelimit = atoi(myargv[p+1]); - printf("timer: %i\n", timelimit); - } - - //! - // @category net - // @vanilla - // - // Austin Virtual Gaming: end levels after 20 minutes. - // - - p = M_CheckParm ("-avg"); - - if (p) - { - timelimit = 20; - } - - //! - // @category game - // @arg x - // @vanilla - // - // Start a game immediately, warping to level x. - // - - p = M_CheckParmWithArgs("-warp", 1); - - if (p) - { - if (gamemode == commercial) - startmap = atoi (myargv[p+1]); - else - { - startepisode = myargv[p+1][0]-'0'; - - if (p + 2 < myargc) - { - startmap = myargv[p+2][0]-'0'; - } - else - { - startmap = 1; - } - } - autostart = true; - } - - if (testcontrols) - { - startepisode = 1; - startmap = 3; - autostart = true; - } - - // Check for load game parameter - // We do this here and save the slot number, so that the network code - // can override it or send the load slot to other players. - - //! - // @category game - // @arg - // @vanilla - // - // Load the game in slot s. - // - - p = M_CheckParmWithArgs("-loadgame", 1); - - if (p) - { - startloadgame = atoi(myargv[p+1]); - } - else - { - // Not loading a game - startloadgame = -1; - } - - if (W_CheckNumForName("SS_START") >= 0 - || W_CheckNumForName("FF_END") >= 0) - { - I_PrintDivider(); - printf(" WARNING: The loaded WAD file contains modified sprites or\n" - " floor textures. You may want to use the '-merge' command\n" - " line option instead of '-file'.\n"); - } - - I_PrintStartupBanner(gamedescription); - PrintDehackedBanners(); - - // haleyjd 08/28/10: Init Choco Strife stuff. - D_InitChocoStrife(); - - // haleyjd 08/22/2010: [STRIFE] Modified string to match binary - if(devparm) // [STRIFE] - DEH_printf("R_Init: Loading Graphics - "); - R_Init (); - D_IntroTick(); // [STRIFE] - - if(devparm) // [STRIFE] - DEH_printf("\nP_Init: Init Playloop state.\n"); - P_Init (); - D_IntroTick(); // [STRIFE] - - if(devparm) // [STRIFE] - DEH_printf("I_Init: Setting up machine state.\n"); - I_CheckIsScreensaver(); - I_InitJoystick(); - D_IntroTick(); // [STRIFE] - - D_IntroTick(); // [STRIFE] - - if(devparm) // [STRIFE] - DEH_printf("M_Init: Init Menu.\n"); - M_Init (); - D_IntroTick(); // [STRIFE] - - // haleyjd 20110924: Moved S_Init up. - D_IntroTick(); - - // haleyjd 20110220: This stuff was done in I_StartupSound in vanilla, but - // we'll do it here instead so we don't have to modify the low-level shared - // code with Strife-specific stuff. - - //! - // @vanilla - // - // Disable voice dialog and show dialog as text instead, - // even if voices.wad can be found. - // - - if(disable_voices || M_CheckParm("-novoice")) - { - dialogshowtext = disable_voices = 1; - } - - if(devparm) - DEH_printf(" Play voices = %d\n", disable_voices == 0); - - if(devparm) // [STRIFE] - DEH_printf("D_CheckNetGame: Checking network game status.\n"); - D_CheckNetGame (); - - PrintGameVersion(); - - if(devparm) - DEH_printf("HU_Init: Setting up heads up display.\n"); - HU_Init (); - D_IntroTick(); // [STRIFE] - - if(devparm) - DEH_printf("ST_Init: Init status bar.\n"); - ST_Init (); - D_IntroTick(); // [STRIFE] - - // haleyjd [STRIFE] -statcopy used to be here... - D_IntroTick(); // [STRIFE] - - // If Doom II without a MAP01 lump, this is a store demo. - // Moved this here so that MAP01 isn't constantly looked up - // in the main loop. - // haleyjd 08/23/2010: [STRIFE] There is no storedemo version of Strife - /* - if (gamemode == commercial && W_CheckNumForName("map01") < 0) - storedemo = true; - */ - - //! - // @arg - // @category demo - // @vanilla - // - // Record a demo named x.lmp. - // - - p = M_CheckParmWithArgs("-record", 1); - - if (p) - { - G_RecordDemo (myargv[p+1]); - autostart = true; - } - D_IntroTick(); // [STRIFE] - - p = M_CheckParmWithArgs("-playdemo", 1); - if (p) - { - singledemo = true; // quit after one demo - G_DeferedPlayDemo (demolumpname); - D_DoomLoop (); // never returns - } - D_IntroTick(); // [STRIFE] - - p = M_CheckParmWithArgs("-timedemo", 1); - if (p) - { - G_TimeDemo (demolumpname); - D_DoomLoop (); // never returns - } - D_IntroTick(); // [STRIFE] - - if (startloadgame >= 0) - { - // [STRIFE]: different, for hubs - M_LoadSelect(startloadgame); - } - D_IntroTick(); // [STRIFE] - - - if (gameaction != ga_loadgame ) - { - if (autostart || netgame) - G_InitNew (startskill, startmap); - else - D_StartTitle (); // start up intro loop - } - - if (using_text_startup) - { - TXT_Shutdown(); - } - - D_DoomLoop (); // never returns -} diff --git a/games/NXDoom/src/strife/d_main.h b/games/NXDoom/src/strife/d_main.h deleted file mode 100644 index 22f55488d66..00000000000 --- a/games/NXDoom/src/strife/d_main.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// System specific interface stuff. -// - - -#ifndef __D_MAIN__ -#define __D_MAIN__ - -#include "doomdef.h" - -#include "v_patch.h" - - -// Read events from all input devices - -void D_ProcessEvents (void); - - -// -// BASE LEVEL -// -void D_PageTicker (void); -void D_PageDrawer (void); -void D_AdvanceDemo (void); -void D_DoAdvanceDemo (void); -void D_StartTitle (void); -void D_QuitGame (void); // [STRIFE] - -void D_IntroTick(void); // [STRIFE] - -boolean D_PatchClipCallback(patch_t *patch, int x, int y); // [STRIFE] - - -// -// GLOBAL VARIABLES -// - -extern gameaction_t gameaction; -extern boolean isregistered; // villsa [STRIFE] -extern boolean isdemoversion; // haleyjd [STRIFE] -extern boolean stonecold; // villsa [STRIFE] -extern boolean workparm; // villsa [STRIFE] -extern boolean advancedemo; - -// haleyjd 20130915 [STRIFE]: need nickname -extern char *nickname; - - -#endif - diff --git a/games/NXDoom/src/strife/d_net.c b/games/NXDoom/src/strife/d_net.c deleted file mode 100644 index 26d807830f0..00000000000 --- a/games/NXDoom/src/strife/d_net.c +++ /dev/null @@ -1,290 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM Network game communication and protocol, -// all OS independend parts. -// - -#include - -#include "d_main.h" -#include "m_argv.h" -#include "m_menu.h" -#include "m_misc.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "g_game.h" -#include "doomdef.h" -#include "doomstat.h" -#include "w_checksum.h" - -#include "deh_main.h" - -#include "d_loop.h" - -ticcmd_t *netcmds; - -// Called when a player leaves the game - -static void PlayerQuitGame(player_t *player) -{ - static char exitmsg[80]; - unsigned int player_num; - - player_num = player - players; - - // Do this the same way as Vanilla Doom does, to allow dehacked - // replacements of this message - - M_StringCopy(exitmsg, DEH_String("Player 1 left the game"), - sizeof(exitmsg)); - - exitmsg[7] += player_num; - - playeringame[player_num] = false; - players[consoleplayer].message = exitmsg; - - // TODO: check if it is sensible to do this: - - if (demorecording) - { - G_CheckDemoStatus (); - } -} - -static void RunTic(ticcmd_t *cmds, boolean *ingame) -{ - unsigned int i; - - // Check for player quits. - - for (i = 0; i < MAXPLAYERS; ++i) - { - if (!demoplayback && playeringame[i] && !ingame[i]) - { - PlayerQuitGame(&players[i]); - } - } - - netcmds = cmds; - - // check that there are players in the game. if not, we cannot - // run a tic. - - if (advancedemo) - D_DoAdvanceDemo (); - - M_Ticker(); - G_Ticker(); -} - -static void NullMenuTicker() -{ - // no-op. -} - -static loop_interface_t strife_loop_interface = { - D_ProcessEvents, - G_BuildTiccmd, - RunTic, - NullMenuTicker -}; - - -// Load game settings from the specified structure and -// set global variables. - -static void LoadGameSettings(net_gamesettings_t *settings) -{ - unsigned int i; - - deathmatch = settings->deathmatch; - ticdup = settings->ticdup; - startepisode = settings->episode; - startmap = settings->map; - startskill = settings->skill; - startloadgame = settings->loadgame; - lowres_turn = settings->lowres_turn; - nomonsters = settings->nomonsters; - fastparm = settings->fast_monsters; - respawnparm = settings->respawn_monsters; - timelimit = settings->timelimit; - consoleplayer = settings->consoleplayer; - randomparm = settings->random; - - if (lowres_turn) - { - printf("NOTE: Turning resolution is reduced; this is probably " - "because there is a client recording a Vanilla demo.\n"); - } - - for (i = 0; i < MAXPLAYERS; ++i) - { - playeringame[i] = i < settings->num_players; - } -} - -// Save the game settings from global variables to the specified -// game settings structure. - -static void SaveGameSettings(net_gamesettings_t *settings) -{ - // Fill in game settings structure with appropriate parameters - // for the new game - - settings->deathmatch = deathmatch; - settings->episode = startepisode; - settings->map = startmap; - settings->skill = startskill; - settings->loadgame = startloadgame; - settings->gameversion = gameversion; - settings->nomonsters = nomonsters; - settings->fast_monsters = fastparm; - settings->respawn_monsters = respawnparm; - settings->timelimit = timelimit; - settings->random = randomparm; - - settings->lowres_turn = M_ParmExists("-record") - && !M_ParmExists("-longtics"); -} - -static void InitConnectData(net_connect_data_t *connect_data) -{ - connect_data->drone = false; - connect_data->max_players = MAXPLAYERS; - - //! - // @category net - // - // Run as the left screen in three screen mode. - // - - if (M_CheckParm("-left") > 0) - { - viewangleoffset = ANG90; - connect_data->drone = true; - } - - //! - // @category net - // - // Run as the right screen in three screen mode. - // - - if (M_CheckParm("-right") > 0) - { - viewangleoffset = ANG270; - connect_data->drone = true; - } - - // - // Connect data - // - - // Game type fields: - - connect_data->gamemode = gamemode; - connect_data->gamemission = gamemission; - - // Are we recording a demo? Possibly set lowres turn mode - - connect_data->lowres_turn = M_CheckParm("-record") > 0 - && M_CheckParm("-longtics") == 0; - - // Read checksums of our WAD directory and dehacked information - - W_Checksum(connect_data->wad_sha1sum); - DEH_Checksum(connect_data->deh_sha1sum); - - connect_data->is_freedoom = 0; -} - -void D_ConnectNetGame(void) -{ - net_connect_data_t connect_data; - - InitConnectData(&connect_data); - netgame = D_InitNetGame(&connect_data); - - //! - // @category net - // - // Start the game playing as though in a netgame with a single - // player. This can also be used to play back single player netgame - // demos. - // - - if (M_CheckParm("-solo-net") > 0) - { - netgame = true; - } -} - -// -// D_CheckNetGame -// Works out player numbers among the net participants -// -void D_CheckNetGame(void) -{ - net_gamesettings_t settings; - - D_RegisterLoopCallbacks(&strife_loop_interface); - - if (netgame) - { - autostart = true; - } - - SaveGameSettings(&settings); - D_StartNetGame(&settings, NULL); - LoadGameSettings(&settings); - - // Strife games are always deathmatch, though -altdeath is - // supported for respawning items. - - if (netgame && deathmatch == 0) - { - deathmatch = 1; - } - - DEH_printf("startmap: %i, skill: %i, enemies: %i, random: %i\n", - startmap, startskill, !nomonsters, randomparm); - - - DEH_printf("player %i of %i (%i nodes)\n", - consoleplayer+1, settings.num_players, settings.num_players); - - // Show players here; the server might have specified a time limit - - if (timelimit > 0 && deathmatch) - { - // Gross hack to work like Vanilla: - - if (timelimit == 20 && M_CheckParm("-avg")) - { - DEH_printf("Austin Virtual Gaming: Levels will end " - "after 20 minutes\n"); - } - else - { - DEH_printf("Levels will end after %d minute", timelimit); - if (timelimit > 1) - printf("s"); - printf(".\n"); - } - } -} - diff --git a/games/NXDoom/src/strife/d_player.h b/games/NXDoom/src/strife/d_player.h deleted file mode 100644 index 1f5b4ec00ed..00000000000 --- a/games/NXDoom/src/strife/d_player.h +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - - -#ifndef __D_PLAYER__ -#define __D_PLAYER__ - - -// The player data structure depends on a number -// of other structs: items (internal inventory), -// animation states (closely tied to the sprites -// used to represent them, unfortunately). -#include "d_items.h" -#include "p_pspr.h" - -// In addition, the player is just a special -// case of the generic moving object/actor. -#include "p_mobj.h" - -// Finally, for odd reasons, the player input -// is buffered within the player data struct, -// as commands per game tick. -#include "d_ticcmd.h" - -#include "net_defs.h" - - - - -// -// Player states. -// -typedef enum -{ - // Playing or camping. - PST_LIVE, - // Dead on the ground, view follows killer. - PST_DEAD, - // Ready to restart/respawn??? - PST_REBORN - -} playerstate_t; - - -// -// Player internal flags, for cheats and debug. -// -typedef enum -{ - // No clipping, walk through barriers. - CF_NOCLIP = 1, - // No damage, no health loss. - CF_GODMODE = 2, - // Not really a cheat, just a debug aid. - CF_NOMOMENTUM = 4, - // villsa [STRIFE] new cheat - // set when on fire and disable inventory - CF_ONFIRE = 8, - // villsa [STRIFE] new cheat - // auto-use medkits - CF_AUTOHEALTH = 16 - -} cheat_t; - -// haleyjd 08/30/10: [STRIFE] -// Player Inventory Item Structure -typedef struct inventory_s -{ - int sprite; // a sprite number - int type; // a thing type - int amount; // amount being carried -} inventory_t; - -#define NUMINVENTORY 32 - -// -// Extended player object info: player_t -// -// haleyjd 08/30/10: [STRIFE] -// * Transformed to match binary structure layout. -// -typedef struct player_s -{ - mobj_t* mo; - playerstate_t playerstate; - ticcmd_t cmd; - - // Determine POV, - // including viewpoint bobbing during movement. - // Focal origin above r.z - fixed_t viewz; - // Base height above floor for viewz. - fixed_t viewheight; - // Bob/squat speed. - fixed_t deltaviewheight; - // bounded/scaled total momentum. - fixed_t bob; - - // This is only used between levels, - // mo->health is used during levels. - int health; - short armorpoints; // [STRIFE] Changed to short - // Armor type is 0-2. - short armortype; // [STRIFE] Changed to short - - // Power ups. invinc and invis are tic counters. - int powers[NUMPOWERS]; - - // [STRIFE] Additions: - int sigiltype; // Type of Sigil carried - int nukagecount; // Nukage exposure counter - int questflags; // Quest bit flags - int pitch; // Up/down look angle - boolean centerview; // True if view should be centered - inventory_t inventory[NUMINVENTORY]; // Player inventory items - boolean st_update; // If true, update status bar - short numinventory; // Num. active inventory items - short inventorycursor; // Selected inventory item - short accuracy; // Accuracy stat - short stamina; // Stamina stat - - boolean cards[NUMCARDS]; - boolean backpack; - - // True if button down last tic. - int attackdown; - int usedown; - int inventorydown; // [STRIFE] Use inventory item - - // Frags, kills of other players. - int frags[MAXPLAYERS]; - weapontype_t readyweapon; - - // Is wp_nochange if not changing. - weapontype_t pendingweapon; - - boolean weaponowned[NUMWEAPONS]; - int ammo[NUMAMMO]; - int maxammo[NUMAMMO]; - - // Bit flags, for cheats and debug. - // See cheat_t, above. - int cheats; - - // Refired shots are less accurate. - int refire; - - // For intermission stats. - short killcount; // [STRIFE] Changed to short - //int itemcount; // [STRIFE] Eliminated these. - //int secretcount; - - // Hint messages. - const char *message; - - // For screen flashing (red or bright). - int damagecount; - int bonuscount; - - // Who did damage (NULL for floors/ceilings). - mobj_t* attacker; - - // So gun flashes light up areas. - int extralight; - - // Current PLAYPAL, ??? - // can be set to REDCOLORMAP for pain, etc. - int fixedcolormap; - - // Player skin colorshift, - // 0-3 for which color to draw player. - //int colormap; [STRIFE] no such? or did it become the below? - - // [STRIFE] For use of teleport beacons - short allegiance; - - // Overlay view sprites (gun, etc). - pspdef_t psprites[NUMPSPRITES]; - - // [STRIFE] Inefficient means of tracking automap state on all maps - boolean mapstate[40]; - - // True if secret level has been done. - //boolean didsecret; [STRIFE] Removed this. - -} player_t; - - -// -// INTERMISSION -// Structure passed e.g. to WI_Start(wb) -// -typedef struct -{ - boolean in; // whether the player is in game - - // Player stats, kills, collected items etc. - int skills; - int sitems; - int ssecret; - int stime; - int frags[4]; - int score; // current score on entry, modified on return - -} wbplayerstruct_t; - -typedef struct -{ - int epsd; // episode # (0-2) - - // if true, splash the secret level - boolean didsecret; - - // previous and next levels, origin 0 - int last; - int next; - - int maxkills; - int maxitems; - int maxsecret; - int maxfrags; - - // the par time - int partime; - - // index of this player in game - int pnum; - - wbplayerstruct_t plyr[MAXPLAYERS]; - -} wbstartstruct_t; - - -#endif diff --git a/games/NXDoom/src/strife/d_textur.h b/games/NXDoom/src/strife/d_textur.h deleted file mode 100644 index 1afe040eb04..00000000000 --- a/games/NXDoom/src/strife/d_textur.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Typedefs related to to textures etc., -// isolated here to make it easier separating modules. -// - - -#ifndef __D_TEXTUR__ -#define __D_TEXTUR__ - -#include "doomtype.h" - - - - -// -// Flats? -// -// a pic is an unmasked block of pixels -typedef struct -{ - byte width; - byte height; - byte data; -} pic_t; - - - - -#endif diff --git a/games/NXDoom/src/strife/d_think.h b/games/NXDoom/src/strife/d_think.h deleted file mode 100644 index 0966ad96023..00000000000 --- a/games/NXDoom/src/strife/d_think.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// MapObj data. Map Objects or mobjs are actors, entities, -// thinker, take-your-pick... anything that moves, acts, or -// suffers state changes of more or less violent nature. -// - - -#ifndef __D_THINK__ -#define __D_THINK__ - - - - - -// -// Experimental stuff. -// To compile this as "ANSI C with classes" -// we will need to handle the various -// action functions cleanly. -// -typedef void (*actionf_v)(); -typedef void (*actionf_p1)( void* ); -typedef void (*actionf_p2)( void*, void* ); - -typedef union -{ - actionf_v acv; - actionf_p1 acp1; - actionf_p2 acp2; - -} actionf_t; - - - - - -// Historically, "think_t" is yet another -// function pointer to a routine to handle -// an actor. -typedef actionf_t think_t; - - -// Doubly linked list of actors. -typedef struct thinker_s -{ - struct thinker_s* prev; - struct thinker_s* next; - think_t function; - -} thinker_t; - - - -#endif diff --git a/games/NXDoom/src/strife/deh_ammo.c b/games/NXDoom/src/strife/deh_ammo.c deleted file mode 100644 index dd8bee54678..00000000000 --- a/games/NXDoom/src/strife/deh_ammo.c +++ /dev/null @@ -1,103 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Ammo" sections in dehacked files -// - -#include -#include -#include - -#include "doomdef.h" -#include "doomtype.h" -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" -#include "p_local.h" - -static void *DEH_AmmoStart(deh_context_t *context, char *line) -{ - int ammo_number = 0; - - if (sscanf(line, "Ammo %i", &ammo_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (ammo_number < 0 || ammo_number >= NUMAMMO) - { - DEH_Warning(context, "Invalid ammo number: %i", ammo_number); - return NULL; - } - - return &maxammo[ammo_number]; -} - -static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) -{ - char *variable_name, *value; - int ivalue; - int ammo_number; - - if (tag == NULL) - return; - - ammo_number = ((int *) tag) - maxammo; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - ivalue = atoi(value); - - // maxammo - - if (!strcasecmp(variable_name, "Per ammo")) - clipammo[ammo_number] = ivalue; - else if (!strcasecmp(variable_name, "Max ammo")) - maxammo[ammo_number] = ivalue; - else - { - DEH_Warning(context, "Field named '%s' not found", variable_name); - } -} - -static void DEH_AmmoSHA1Hash(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include - -#include "doomtype.h" - -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" -#include "am_map.h" -#include "st_stuff.h" - -typedef struct -{ - const char *name; - cheatseq_t *seq; -} deh_cheat_t; - -static deh_cheat_t allcheats[] = -{ - // haleyjd 20110224: filled in all cheats - {"Change music", &cheat_mus }, - {"Level Warp", &cheat_clev }, - {"Stealth Boots", &cheat_stealth }, - {"Sigil piece", &cheat_lego }, - {"FPS", &cheat_mypos }, - {"TeleportMapSpot", &cheat_scoot }, - {"Gold&StatTokens", &cheat_midas }, - {"God mode", &cheat_god }, - {"Keys", &cheat_keys }, - {"Weapons & Ammo", &cheat_ammo }, - {"Massacre", &cheat_nuke }, - {"No Clipping", &cheat_noclip }, - {"Berserk", &cheat_powerup[0] }, - {"Invisibility", &cheat_powerup[1] }, - {"Enviro Suit", &cheat_powerup[2] }, - {"Health", &cheat_powerup[3] }, - {"Backpack", &cheat_powerup[4] }, - // STRIFE-FIXME/TODO: Does SeHackEd not support PUMPUP{S,T,nil}, or "DOTS" ? -}; - -static deh_cheat_t *FindCheatByName(char *name) -{ - size_t i; - - for (i=0; i= cheat->seq->sequence_len) - { - DEH_Warning(context, "Cheat sequence longer than supported by " - "Vanilla dehacked"); - break; - } - - if (deh_apply_cheats) - { - cheat->seq->sequence[i] = unsvalue[i]; - } - ++i; - - // Absolute limit - don't exceed - - if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars) - { - DEH_Error(context, "Cheat sequence too long!"); - return; - } - } - - if (deh_apply_cheats) - { - cheat->seq->sequence[i] = '\0'; - } -} - -deh_section_t deh_section_cheat = -{ - "Cheat", - NULL, - DEH_CheatStart, - DEH_CheatParseLine, - NULL, - NULL, -}; - diff --git a/games/NXDoom/src/strife/deh_frame.c b/games/NXDoom/src/strife/deh_frame.c deleted file mode 100644 index c36f3e34ced..00000000000 --- a/games/NXDoom/src/strife/deh_frame.c +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Frame" sections in dehacked files -// - -#include -#include - -#include "doomtype.h" -#include "d_items.h" -#include "info.h" - -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" -#include "deh_mapping.h" - -DEH_BEGIN_MAPPING(state_mapping, state_t) - DEH_MAPPING("Sprite number", sprite) - DEH_MAPPING("Sprite subnumber", frame) - DEH_MAPPING("Duration", tics) - DEH_MAPPING("Next frame", nextstate) - DEH_UNSUPPORTED_MAPPING("Action pointer") -DEH_END_MAPPING - -static void *DEH_FrameStart(deh_context_t *context, char *line) -{ - int frame_number = 0; - state_t *state; - - if (sscanf(line, "Frame %i", &frame_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (frame_number < 0 || frame_number >= NUMSTATES) - { - DEH_Warning(context, "Invalid frame number: %i", frame_number); - return NULL; - } - - if (frame_number >= DEH_VANILLA_NUMSTATES) - { - DEH_Warning(context, "Attempt to modify frame %i: this will cause " - "problems in Vanilla dehacked.", frame_number); - } - - state = &states[frame_number]; - - return state; -} - -// Simulate a frame overflow: Doom has 967 frames in the states[] array, but -// DOS dehacked internally only allocates memory for 966. As a result, -// attempts to set frame 966 (the last frame) will overflow the dehacked -// array and overwrite the weaponinfo[] array instead. -// -// This is noticable in Batman Doom where it is impossible to switch weapons -// away from the fist once selected. - -static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value) -{ - if (!strcasecmp(varname, "Duration")) - { - weaponinfo[0].ammo = value; - } - else if (!strcasecmp(varname, "Codep frame")) - { - weaponinfo[0].upstate = value; - } - else if (!strcasecmp(varname, "Next frame")) - { - weaponinfo[0].downstate = value; - } - else if (!strcasecmp(varname, "Unknown 1")) - { - weaponinfo[0].readystate = value; - } - else if (!strcasecmp(varname, "Unknown 2")) - { - weaponinfo[0].atkstate = value; - } - else - { - DEH_Error(context, "Unable to simulate frame overflow: field '%s'", - varname); - } -} - -static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) -{ - state_t *state; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; - - state = (state_t *) tag; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - // all values are integers - - ivalue = atoi(value); - - if (state == &states[NUMSTATES - 1]) - { - DEH_FrameOverflow(context, variable_name, ivalue); - } - else - { - // set the appropriate field - - DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); - } -} - -static void DEH_FrameSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include - -#include "doomtype.h" -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" -#include "deh_misc.h" - -// Dehacked: "Initial Health" -// This is the initial health a player has when starting anew. -// See G_PlayerReborn in g_game.c - -int deh_initial_health = DEH_DEFAULT_INITIAL_HEALTH; - -// Dehacked: "Initial bullets" -// This is the number of bullets the player has when starting anew. -// See G_PlayerReborn in g_game.c - -int deh_initial_bullets = DEH_DEFAULT_INITIAL_BULLETS; - -// Dehacked: "Max Health" -// This is the maximum health that can be reached using medikits -// alone. See P_TouchSpecialThing in p_inter.c - -int deh_max_health = DEH_DEFAULT_MAX_HEALTH; - -// Dehacked: "Max Armor" -// This is the maximum armor which can be reached by picking up -// armor helmets. See P_TouchSpecialThing in p_inter.c - -int deh_max_armor = DEH_DEFAULT_MAX_ARMOR; - -// Dehacked: "Green Armor Class" -// This is the armor class that is given when picking up the green -// armor or an armor helmet. See P_TouchSpecialThing in p_inter.c -// -// DOS dehacked only modifies the behavior of the green armor shirt, -// the armor class set by armor helmets is not affected. - -int deh_green_armor_class = DEH_DEFAULT_GREEN_ARMOR_CLASS; - -// Dehacked: "Blue Armor Class" -// This is the armor class that is given when picking up the blue -// armor or a megasphere. See P_TouchSpecialThing in p_inter.c -// -// DOS dehacked only modifies the MegaArmor behavior and not -// the MegaSphere, which always gives armor type 2. - -int deh_blue_armor_class = DEH_DEFAULT_BLUE_ARMOR_CLASS; - -// Dehacked: "Max soulsphere" -// The maximum health which can be reached by picking up the -// soulsphere. See P_TouchSpecialThing in p_inter.c - -int deh_max_soulsphere = DEH_DEFAULT_MAX_SOULSPHERE; - -// Dehacked: "Soulsphere health" -// The amount of health bonus that picking up a soulsphere -// gives. See P_TouchSpecialThing in p_inter.c - -int deh_soulsphere_health = DEH_DEFAULT_SOULSPHERE_HEALTH; - -// Dehacked: "Megasphere health" -// This is what the health is set to after picking up a -// megasphere. See P_TouchSpecialThing in p_inter.c - -int deh_megasphere_health = DEH_DEFAULT_MEGASPHERE_HEALTH; - -// Dehacked: "God mode health" -// This is what the health value is set to when cheating using -// the IDDQD god mode cheat. See ST_Responder in st_stuff.c - -int deh_god_mode_health = DEH_DEFAULT_GOD_MODE_HEALTH; - -// Dehacked: "IDFA Armor" -// This is what the armor is set to when using the IDFA cheat. -// See ST_Responder in st_stuff.c - -int deh_idfa_armor = DEH_DEFAULT_IDFA_ARMOR; - -// Dehacked: "IDFA Armor Class" -// This is what the armor class is set to when using the IDFA cheat. -// See ST_Responder in st_stuff.c - -int deh_idfa_armor_class = DEH_DEFAULT_IDFA_ARMOR_CLASS; - -// Dehacked: "IDKFA Armor" -// This is what the armor is set to when using the IDKFA cheat. -// See ST_Responder in st_stuff.c - -int deh_idkfa_armor = DEH_DEFAULT_IDKFA_ARMOR; - -// Dehacked: "IDKFA Armor Class" -// This is what the armor class is set to when using the IDKFA cheat. -// See ST_Responder in st_stuff.c - -int deh_idkfa_armor_class = DEH_DEFAULT_IDKFA_ARMOR_CLASS; - -// Dehacked: "BFG Cells/Shot" -// This is the number of CELLs firing the BFG uses up. -// See P_CheckAmmo and A_FireBFG in p_pspr.c - -int deh_bfg_cells_per_shot = DEH_DEFAULT_BFG_CELLS_PER_SHOT; - -// Dehacked: "Monsters infight" -// This controls whether monsters can harm other monsters of the same -// species. For example, whether an imp fireball will damage other -// imps. The value of this in dehacked patches is weird - '202' means -// off, while '221' means on. -// -// See PIT_CheckThing in p_map.c - -int deh_species_infighting = DEH_DEFAULT_SPECIES_INFIGHTING; - -static struct -{ - const char *deh_name; - int *value; -} misc_settings[] = { - {"Initial Health", &deh_initial_health}, - {"Initial Bullets", &deh_initial_bullets}, - {"Max Health", &deh_max_health}, - {"Max Armor", &deh_max_armor}, - {"LeatherArmorClass", &deh_green_armor_class}, - {"Metal Armor Class", &deh_blue_armor_class}, - {"Max Soulsphere", &deh_max_soulsphere}, - {"Soulsphere Health", &deh_soulsphere_health}, - {"Megasphere Health", &deh_megasphere_health}, - {"God Mode Health", &deh_god_mode_health}, - {"IDFA Armor", &deh_idfa_armor}, - {"IDFA Armor Class", &deh_idfa_armor_class}, - {"IDKFA Armor", &deh_idkfa_armor}, - {"IDKFA Armor Class", &deh_idkfa_armor_class}, - {"Mauler Cells/Shot", &deh_bfg_cells_per_shot}, -}; - -static void *DEH_MiscStart(deh_context_t *context, char *line) -{ - return NULL; -} - -static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag) -{ - char *variable_name, *value; - int ivalue; - size_t i; - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - ivalue = atoi(value); - - if (!strcasecmp(variable_name, "Monsters Infight")) - { - // See notes above. - - if (ivalue == 202) - { - deh_species_infighting = 0; - } - else if (ivalue == 221) - { - deh_species_infighting = 1; - } - else - { - DEH_Warning(context, - "Invalid value for 'Monsters Infight': %i", ivalue); - } - - return; - } - - for (i=0; i -#include -#include - -#include "doomtype.h" -#include "info.h" - -#include "deh_defs.h" -#include "deh_io.h" -#include "deh_main.h" - -static actionf_t codeptrs[NUMSTATES]; - -static int CodePointerIndex(actionf_t *ptr) -{ - int i; - - for (i=0; i= NUMSTATES) - { - DEH_Warning(context, "Invalid frame number: %i", frame_number); - return NULL; - } - - return &states[frame_number]; -} - -static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag) -{ - state_t *state; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; - - state = (state_t *) tag; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - DEH_Warning(context, "Failed to parse assignment"); - return; - } - -// printf("Set %s to %s for state\n", variable_name, value); - - // all values are integers - - ivalue = atoi(value); - - // set the appropriate field - - if (!strcasecmp(variable_name, "Codep frame")) - { - if (ivalue < 0 || ivalue >= NUMSTATES) - { - DEH_Warning(context, "Invalid state '%i'", ivalue); - } - else - { - state->action = codeptrs[ivalue]; - } - } - else - { - DEH_Warning(context, "Unknown variable name '%s'", variable_name); - } -} - -static void DEH_PointerSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include - -#include "doomtype.h" -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_mapping.h" -#include "sounds.h" - -DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t) - DEH_UNSUPPORTED_MAPPING("Offset") - DEH_UNSUPPORTED_MAPPING("Zero/One") - DEH_MAPPING("Value", priority) - DEH_MAPPING("Zero 1", link) - DEH_MAPPING("Zero 2", pitch) - DEH_MAPPING("Zero 3", volume) - DEH_UNSUPPORTED_MAPPING("Zero 4") - DEH_MAPPING("Neg. One 1", usefulness) - DEH_MAPPING("Neg. One 2", lumpnum) -DEH_END_MAPPING - -static void *DEH_SoundStart(deh_context_t *context, char *line) -{ - int sound_number = 0; - - if (sscanf(line, "Sound %i", &sound_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (sound_number < 0 || sound_number >= NUMSFX) - { - DEH_Warning(context, "Invalid sound number: %i", sound_number); - return NULL; - } - - if (sound_number >= DEH_VANILLA_NUMSFX) - { - DEH_Warning(context, "Attempt to modify SFX %i. This will cause " - "problems in Vanilla dehacked.", sound_number); - } - - return &S_sfx[sound_number]; -} - -static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag) -{ - sfxinfo_t *sfx; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; - - sfx = (sfxinfo_t *) tag; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - // all values are integers - - ivalue = atoi(value); - - // Set the field value - - DEH_SetMapping(context, &sound_mapping, sfx, variable_name, ivalue); -} - -deh_section_t deh_section_sound = -{ - "Sound", - NULL, - DEH_SoundStart, - DEH_SoundParseLine, - NULL, - NULL, -}; - diff --git a/games/NXDoom/src/strife/deh_strife.c b/games/NXDoom/src/strife/deh_strife.c deleted file mode 100644 index 76cb496c16f..00000000000 --- a/games/NXDoom/src/strife/deh_strife.c +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Top-level dehacked definitions for Strife dehacked (sehacked) -// - -#include -#include "deh_defs.h" -#include "deh_main.h" - -const char *deh_signatures[] = -{ - "Patch File for SeHackEd v0.4", - "Patch File for SeHackEd v0.3", - NULL -}; - - -// -// List of section types: -// - -deh_section_t *deh_section_types[] = -{ - &deh_section_ammo, - &deh_section_cheat, - &deh_section_frame, - &deh_section_misc, - &deh_section_pointer, - &deh_section_sound, - &deh_section_text, - &deh_section_thing, - &deh_section_weapon, - NULL -}; - diff --git a/games/NXDoom/src/strife/deh_thing.c b/games/NXDoom/src/strife/deh_thing.c deleted file mode 100644 index 72b92642ede..00000000000 --- a/games/NXDoom/src/strife/deh_thing.c +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// Parses "Thing" sections in dehacked files -// - -#include -#include - -#include "doomtype.h" - -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_mapping.h" - -#include "info.h" - -DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t) - DEH_MAPPING("ID #", doomednum) - DEH_MAPPING("Initial frame", spawnstate) - DEH_MAPPING("Hit points", spawnhealth) - DEH_MAPPING("First moving frame", seestate) - DEH_MAPPING("Alert sound", seesound) - DEH_MAPPING("Reaction time", reactiontime) - DEH_MAPPING("Attack sound", attacksound) - DEH_MAPPING("Injury frame", painstate) - DEH_MAPPING("Pain chance", painchance) - DEH_MAPPING("Pain sound", painsound) - DEH_MAPPING("Close attack frame", meleestate) - DEH_MAPPING("Far attack frame", missilestate) - DEH_MAPPING("Crash frame", crashstate) - DEH_MAPPING("Death frame", deathstate) - DEH_MAPPING("Exploding frame", xdeathstate) - DEH_MAPPING("Death sound", deathsound) - DEH_MAPPING("Speed", speed) - DEH_MAPPING("Width", radius) - DEH_MAPPING("Height", height) - DEH_MAPPING("Mass", mass) - DEH_MAPPING("Missile damage", damage) - DEH_MAPPING("Action sound", activesound) - DEH_MAPPING("Bits", flags) - DEH_UNSUPPORTED_MAPPING("Name pointer") -DEH_END_MAPPING - -static void *DEH_ThingStart(deh_context_t *context, char *line) -{ - int thing_number = 0; - mobjinfo_t *mobj; - - if (sscanf(line, "Thing %i", &thing_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - // dehacked files are indexed from 1 - --thing_number; - - if (thing_number < 0 || thing_number >= NUMMOBJTYPES) - { - DEH_Warning(context, "Invalid thing number: %i", thing_number); - return NULL; - } - - mobj = &mobjinfo[thing_number]; - - return mobj; -} - -static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) -{ - mobjinfo_t *mobj; - char *variable_name, *value; - int ivalue; - - if (tag == NULL) - return; - - mobj = (mobjinfo_t *) tag; - - // Parse the assignment - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - -// printf("Set %s to %s for mobj\n", variable_name, value); - - // all values are integers - - ivalue = atoi(value); - - // Set the field value - - DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); -} - -static void DEH_ThingSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include -#include - -#include "doomtype.h" - -#include "d_items.h" - -#include "deh_defs.h" -#include "deh_main.h" -#include "deh_mapping.h" - -DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t) - DEH_MAPPING("Ammo type", ammo) - DEH_MAPPING("Deselect frame", upstate) - DEH_MAPPING("Select frame", downstate) - DEH_MAPPING("Bobbing frame", readystate) - DEH_MAPPING("Shooting frame", atkstate) - DEH_MAPPING("Firing frame", flashstate) - DEH_UNSUPPORTED_MAPPING("? Unknown") -DEH_END_MAPPING - -static void *DEH_WeaponStart(deh_context_t *context, char *line) -{ - int weapon_number = 0; - - if (sscanf(line, "Weapon %i", &weapon_number) != 1) - { - DEH_Warning(context, "Parse error on section start"); - return NULL; - } - - if (weapon_number < 0 || weapon_number >= NUMWEAPONS) - { - DEH_Warning(context, "Invalid weapon number: %i", weapon_number); - return NULL; - } - - return &weaponinfo[weapon_number]; -} - -static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) -{ - char *variable_name, *value; - weaponinfo_t *weapon; - int ivalue; - - if (tag == NULL) - return; - - weapon = (weaponinfo_t *) tag; - - if (!DEH_ParseAssignment(line, &variable_name, &value)) - { - // Failed to parse - - DEH_Warning(context, "Failed to parse assignment"); - return; - } - - ivalue = atoi(value); - - DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); -} - -static void DEH_WeaponSHA1Sum(sha1_context_t *context) -{ - int i; - - for (i=0; i -#include - -#include "doomtype.h" -#include "i_timer.h" -#include "d_mode.h" - -// -// Global parameters/defines. -// -// DOOM version -// -// haleyjd 09/28/10: Replaced with Strife version -#define STRIFE_VERSION 101 - -// Version code for cph's longtics hack ("v1.91") -#define DOOM_191_VERSION 111 - - -// Maximum players for Strife: -#define MAXPLAYERS 8 - -// If rangecheck is undefined, -// most parameter validation debugging code will not be compiled -#define RANGECHECK - -// The current state of the game: whether we are -// playing, gazing at the intermission screen, -// the game final animation, or a demo. -typedef enum -{ - GS_LEVEL, - GS_UNKNOWN, - GS_FINALE, - GS_DEMOSCREEN, -} gamestate_t; - -typedef enum -{ - ga_nothing, - ga_loadlevel, - ga_newgame, - ga_loadgame, - ga_savegame, - ga_playdemo, - ga_completed, - ga_victory, - ga_worlddone, - ga_screenshot -} gameaction_t; - -// -// Difficulty/skill settings/filters. -// - -// Skill flags. -#define MTF_EASY 1 -#define MTF_NORMAL 2 -#define MTF_HARD 4 -// villsa [STRIFE] standing monsters -#define MTF_STAND 8 -// villsa [STRIFE] don't spawn in single player -#define MTF_NOTSINGLE 16 -// Deaf monsters/do not react to sound. -#define MTF_AMBUSH 32 -// villsa [STRIFE] friendly to players -#define MTF_FRIEND 64 -// villsa [STRIFE] TODO - identify -#define MTF_UNKNOWN1 128 -// villsa [STRIFE] thing is translucent - STRIFE-TODO: But how much? -#define MTF_TRANSLUCENT 256 -// villsa [STRIFE] thing is more - or less? - translucent - STRIFE-TODO -#define MTF_MVIS 512 -// villsa [STRIFE] TODO - identify -#define MTF_UNKNOWN2 1024 - - - -// -// Key cards. -// -// villsa [STRIFE] -typedef enum -{ - key_BaseKey, // 0 - key_GovsKey, // 1 - key_Passcard, // 2 - key_IDCard, // 3 - key_PrisonKey, // 4 - key_SeveredHand, // 5 - key_Power1Key, // 6 - key_Power2Key, // 7 - key_Power3Key, // 8 - key_GoldKey, // 9 - key_IDBadge, // 10 - key_SilverKey, // 11 - key_OracleKey, // 12 - key_MilitaryID, // 13 - key_OrderKey, // 14 - key_WarehouseKey, // 15 - key_BrassKey, // 16 - key_RedCrystalKey, // 17 - key_BlueCrystalKey, // 18 - key_ChapelKey, // 19 - key_CatacombKey, // 20 - key_SecurityKey, // 21 - key_CoreKey, // 22 - key_MaulerKey, // 23 - key_FactoryKey, // 24 - key_MineKey, // 25 - key_NewKey5, // 26 - - NUMCARDS // 27 -} card_t; - - - -// The defined weapons, -// including a marker indicating -// user has not changed weapon. -// villsa [STRIFE] -typedef enum -{ - wp_fist, - wp_elecbow, - wp_rifle, - wp_missile, - wp_hegrenade, - wp_flame, - wp_mauler, - wp_sigil, - wp_poisonbow, - wp_wpgrenade, - wp_torpedo, - - NUMWEAPONS, - - // No pending weapon change. - wp_nochange - -} weapontype_t; - - -// Ammunition types defined. -typedef enum -{ - am_bullets, - am_elecbolts, - am_poisonbolts, - am_cell, - am_missiles, - am_hegrenades, - am_wpgrenades, - - NUMAMMO, - - am_noammo // unlimited ammo - -} ammotype_t; - - -// Power up artifacts. -// villsa [STRIFE] -typedef enum -{ - pw_strength, - pw_invisibility, - pw_ironfeet, - pw_allmap, - pw_communicator, - pw_targeter, - NUMPOWERS - -} powertype_t; - -// villsa [STRIFE] -// quest numbers -typedef enum -{ // Hex Watcom Name player_t offset - tk_quest1, // 0x00000001 questflags & 1 0x4D - tk_quest2, // 0x00000002 questflags & 2 - tk_quest3, // 0x00000004 questflags & 4 - tk_quest4, // 0x00000008 questflags & 8 - tk_quest5, // 0x00000010 questflags & 10h - tk_quest6, // 0x00000020 questflags & 20h - tk_quest7, // 0x00000040 questflags & 40h - tk_quest8, // 0x00000080 questflags & 80h - tk_quest9, // 0x00000100 BYTE1(questflags) & 1 0x4E - tk_quest10, // 0x00000200 BYTE1(questflags) & 2 - tk_quest11, // 0x00000400 BYTE1(questflags) & 4 - tk_quest12, // 0x00000800 BYTE1(questflags) & 8 - tk_quest13, // 0x00001000 BYTE1(questflags) & 10h - tk_quest14, // 0x00002000 BYTE1(questflags) & 20h - tk_quest15, // 0x00004000 BYTE1(questflags) & 40h - tk_quest16, // 0x00008000 BYTE1(questflags) & 80h - tk_quest17, // 0x00010000 BYTE2(questflags) & 1 0x4F - tk_quest18, // 0x00020000 BYTE2(questflags) & 2 - tk_quest19, // 0x00040000 BYTE2(questflags) & 4 - tk_quest20, // 0x00080000 BYTE2(questflags) & 8 - tk_quest21, // 0x00100000 BYTE2(questflags) & 10h - tk_quest22, // 0x00200000 BYTE2(questflags) & 20h - tk_quest23, // 0x00400000 BYTE2(questflags) & 40h - tk_quest24, // 0x00800000 BYTE2(questflags) & 80h - tk_quest25, // 0x01000000 BYTE3(questflags) & 1 0x50 - tk_quest26, // 0x02000000 BYTE3(questflags) & 2 - tk_quest27, // 0x04000000 BYTE3(questflags) & 4 - tk_quest28, // 0x08000000 BYTE3(questflags) & 8 - tk_quest29, // 0x10000000 BYTE3(questflags) & 10h - tk_quest30, // 0x20000000 BYTE3(questflags) & 20h - tk_quest31, // 0x40000000 BYTE3(questflags) & 40h - tk_quest32, // most likely unused - tk_numquests -} questtype_t; - -// haleyjd 09/12/10: [STRIFE] -// flag values for each quest. -enum -{ // Name Flag from bitnum Purpose, if known - QF_QUEST1 = (1 << tk_quest1), // Obtained Beldin's ring - QF_QUEST2 = (1 << tk_quest2), // Stole the Chalice - QF_QUEST3 = (1 << tk_quest3), // Permission to visit Irale (visited Macil) - QF_QUEST4 = (1 << tk_quest4), // Accepted Gov. Mourel's "messy" chore - QF_QUEST5 = (1 << tk_quest5), // Accepted Gov. Mourel's "bloody" chore - QF_QUEST6 = (1 << tk_quest6), // Destroyed the Power Coupling - QF_QUEST7 = (1 << tk_quest7), // Killed Blue Acolytes ("Scanning Team") - QF_QUEST8 = (1 << tk_quest8), // Unused; formerly, picked up Broken Coupling - QF_QUEST9 = (1 << tk_quest9), // Obtained Derwin's ear - QF_QUEST10 = (1 << tk_quest10), // Obtained Prison Pass - QF_QUEST11 = (1 << tk_quest11), // Obtained Prison Key - QF_QUEST12 = (1 << tk_quest12), // Obtained Judge Wolenick's hand - QF_QUEST13 = (1 << tk_quest13), // Freed the Prisoners - QF_QUEST14 = (1 << tk_quest14), // Destroyed the Power Crystal - QF_QUEST15 = (1 << tk_quest15), // Obtained Guard Uniform - QF_QUEST16 = (1 << tk_quest16), // Destroyed the Gate Mechanism - QF_QUEST17 = (1 << tk_quest17), // Heard Macil's story about the Sigil (MAP10) - QF_QUEST18 = (1 << tk_quest18), // Obtained Oracle Pass - QF_QUEST19 = (1 << tk_quest19), - QF_QUEST20 = (1 << tk_quest20), - QF_QUEST21 = (1 << tk_quest21), // Killed Bishop - QF_QUEST22 = (1 << tk_quest22), // Killed Oracle with QUEST21 set - QF_QUEST23 = (1 << tk_quest23), // Killed Oracle (always given) - QF_QUEST24 = (1 << tk_quest24), // Killed Macil - QF_QUEST25 = (1 << tk_quest25), // Destroyed the Converter - QF_QUEST26 = (1 << tk_quest26), // Killed Loremaster - QF_QUEST27 = (1 << tk_quest27), // Destroyed the Computer (checked for good ending) - QF_QUEST28 = (1 << tk_quest28), // Obtained Catacomb Key (checked by line type 228) - QF_QUEST29 = (1 << tk_quest29), // Destroyed the Mines Transmitter - QF_QUEST30 = (1 << tk_quest30), - QF_QUEST31 = (1 << tk_quest31), - QF_QUEST32 = (1U << tk_quest32), // Unused; BUG: Broken Coupling accidentally sets it. - - QF_ALLQUESTS = (QF_QUEST31 + (QF_QUEST31 - 1)) // does not include bit 32! -}; - -// -// Power up durations, -// how many seconds till expiration, -// assuming TICRATE is 35 ticks/second. -// -typedef enum -{ - INVISTICS = (55*TICRATE), // villsa [STRIFE] changed from 60 to 55 - IRONTICS = (80*TICRATE), // villsa [STRIFE] changed from 60 to 80 - PMUPTICS = (80*TICRATE), // villsa [STRIFE] - TARGTICS = (160*TICRATE),// villsa [STRIFE] - -} powerduration_t; - -#endif // __DOOMDEF__ diff --git a/games/NXDoom/src/strife/doomstat.c b/games/NXDoom/src/strife/doomstat.c deleted file mode 100644 index 7f3116b5c99..00000000000 --- a/games/NXDoom/src/strife/doomstat.c +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Put all global tate variables here. -// - -#include - -#include "doomstat.h" - - -// Game Mode - identify IWAD as shareware, retail etc. -GameMode_t gamemode = indetermined; -GameMission_t gamemission = doom; -GameVersion_t gameversion = exe_strife_1_31; -const char *gamedescription; - -// Set if homebrew PWAD stuff has been added. -boolean modifiedgame; - - - - diff --git a/games/NXDoom/src/strife/doomstat.h b/games/NXDoom/src/strife/doomstat.h deleted file mode 100644 index 4be2435b134..00000000000 --- a/games/NXDoom/src/strife/doomstat.h +++ /dev/null @@ -1,281 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// All the global variables that store the internal state. -// Theoretically speaking, the internal state of the engine -// should be found by looking at the variables collected -// here, and every relevant module will have to include -// this header file. -// In practice, things are a bit messy. -// - - -#ifndef __D_STATE__ -#define __D_STATE__ - -// We need globally shared data structures, -// for defining the global state variables. -#include "doomdata.h" -#include "d_loop.h" - -// We need the playr data structure as well. -#include "d_player.h" - -// Game mode/mission -#include "d_mode.h" - -#include "net_defs.h" - - - -// ------------------------ -// Command line parameters. -// -extern boolean nomonsters; // checkparm of -nomonsters -extern boolean respawnparm; // checkparm of -respawn -extern boolean fastparm; // checkparm of -fast -extern boolean randomparm; // [STRIFE] checkparm of -random -extern boolean flipparm; // [STRIFE] checkparm of -flip - -extern boolean devparm; // DEBUG: launched with -devparm - - -// ----------------------------------------------------- -// Game Mode - identify IWAD as shareware, retail etc. -// -extern GameMode_t gamemode; -extern GameMission_t gamemission; -extern GameVersion_t gameversion; -extern const char *gamedescription; - -// Set if homebrew PWAD stuff has been added. -extern boolean modifiedgame; - - -// ------------------------------------------- -// Selected skill type, map etc. -// - -// Defaults for menu, methinks. -extern skill_t startskill; -extern int startepisode; -extern int startmap; - -// Savegame slot to load on startup. This is the value provided to -// the -loadgame option. If this has not been provided, this is -1. - -extern int startloadgame; - -extern boolean autostart; - -// Selected by user. -extern skill_t gameskill; -extern int gameepisode; -extern int gamemap; - -// If non-zero, exit the level after this number of minutes -extern int timelimit; - -// Nightmare mode flag, single player. -extern boolean respawnmonsters; - -// Netgame? Only true if >1 player. -extern boolean netgame; - -// 0=Co-op; 1=Deathmatch; 2=Altdeath -extern int deathmatch; - -// ------------------------- -// Internal parameters for sound rendering. -// These have been taken from the DOS version, -// but are not (yet) supported with Linux -// (e.g. no sound volume adjustment with menu. - -// From m_menu.c: -// Sound FX volume has default, 0 - 15 -// Music volume has default, 0 - 15 -// These are multiplied by 8. -extern int sfxVolume; -extern int musicVolume; -extern int voiceVolume; // haleyjd 08/29/10: [STRIFE] - -// Current music/sfx card - index useless -// w/o a reference LUT in a sound module. -// Ideally, this would use indices found -// in: /usr/include/linux/soundcard.h -extern int snd_MusicDevice; -extern int snd_SfxDevice; -// Config file? Same disclaimer as above. -extern int snd_DesiredMusicDevice; -extern int snd_DesiredSfxDevice; - - -// ------------------------- -// Status flags for refresh. -// - -// Depending on view size - no status bar? -// Note that there is no way to disable the -// status bar explicitely. -extern boolean statusbaractive; - -extern boolean automapactive; // In AutoMap mode? -extern boolean menuactive; // Menu overlayed? -extern boolean menupause; // haleyjd 08/29/10: [STRIFE] -extern int menupausetime; // haleyjd 09/04/10: [STRIFE] -extern boolean menuindialog; // haleyjd: ditto -extern boolean paused; // Game Pause? - - -extern boolean viewactive; - -extern boolean nodrawers; - -extern boolean testcontrols; -extern int testcontrols_mousespeed; - - - - -// This one is related to the 3-screen display mode. -// ANG90 = left side, ANG270 = right -extern int viewangleoffset; - -// Player taking events, and displaying. -extern int consoleplayer; -extern int displayplayer; - - -// ------------------------------------- -// Scores, rating. -// Statistics on a given map, for intermission. -// -extern int totalkills; -//extern int totalitems; [STRIFE] unused -extern int totalsecret; - -// Timer, for scores. -extern int levelstarttic; // gametic at level start -extern int leveltime; // tics in game play for par - - - -// -------------------------------------- -// DEMO playback/recording related stuff. -// No demo, there is a human player in charge? -// Disable save/end game? -extern boolean usergame; - -//? -extern boolean demoplayback; -extern boolean demorecording; -extern int mouse_fire_countdown; // villsa [STRIFE] -extern int joystick_fire_countdown; - -extern fixed_t forwardmove[2]; -extern fixed_t sidemove[2]; - -// Round angleturn in ticcmds to the nearest 256. This is used when -// recording Vanilla demos in netgames. - -extern boolean lowres_turn; - -// Quit after playing a demo from cmdline. -extern boolean singledemo; - - - - -//? -extern gamestate_t gamestate; - - - - - - -//----------------------------- -// Internal parameters, fixed. -// These are set by the engine, and not changed -// according to user inputs. Partly load from -// WAD, partly set at startup time. - - -// Bookkeeping on players - state. -extern player_t players[MAXPLAYERS]; - -// Alive? Disconnected? -extern boolean playeringame[MAXPLAYERS]; - - -// Player spawn spots for deathmatch. -#define MAX_DM_STARTS 10 -extern mapthing_t deathmatchstarts[MAX_DM_STARTS]; -extern mapthing_t* deathmatch_p; - -// Player spawn spots. -extern mapthing_t playerstarts[MAXPLAYERS]; - -// haleyjd 08/24/10: [STRIFE] rift spots -#define MAXRIFTSPOTS 16 -extern mapthing_t riftSpots[MAXRIFTSPOTS]; - -// Intermission stats. -// Parameters for world map / intermission. -extern wbstartstruct_t wminfo; - - - - - - -//----------------------------------------- -// Internal parameters, used for engine. -// - -// File handling stuff. -extern char * savegamedir; - -// if true, load all graphics at level load -extern boolean precache; - - -// wipegamestate can be set to -1 -// to force a wipe on the next draw -extern gamestate_t wipegamestate; - -extern int mouseSensitivity; - -//extern int bodyqueslot; [STRIFE] unused - - - -// Needed to store the number of the dummy sky flat. -// Used for rendering, -// as well as tracking projectiles etc. -extern int skyflatnum; - - - -// Netgame stuff (buffers and pointers, i.e. indices). - - -extern int rndindex; - -extern ticcmd_t *netcmds; - - - -#endif diff --git a/games/NXDoom/src/strife/dstrings.c b/games/NXDoom/src/strife/dstrings.c deleted file mode 100644 index 86433ab280f..00000000000 --- a/games/NXDoom/src/strife/dstrings.c +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Globally defined strings. -// - - - -#include "dstrings.h" - -const char *doom1_endmsg[] = -{ - "are you sure you want to\nquit this great game?", - "please don't leave, there's more\ndemons to toast!", - "let's beat it -- this is turning\ninto a bloodbath!", - "i wouldn't leave if i were you.\ndos is much worse.", - "you're trying to say you like dos\nbetter than me, right?", - "don't leave yet -- there's a\ndemon around that corner!", - "ya know, next time you come in here\ni'm gonna toast ya.", - "go ahead and leave. see if i care.", -}; - -const char *doom2_endmsg[] = -{ - // QuitDOOM II messages - "are you sure you want to\nquit this great game?", - "you want to quit?\nthen, thou hast lost an eighth!", - "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!", - "get outta here and go back\nto your boring programs.", - "if i were your boss, i'd \n deathmatch ya in a minute!", - "look, bud. you leave now\nand you forfeit your body count!", - "just leave. when you come\nback, i'll be waiting with a bat.", - "you're lucky i don't smack\nyou for thinking about leaving.", -}; - -#if 0 - -// UNUSED messages included in the source release - -char* endmsg[] = -{ - // DOOM1 - QUITMSG, - // FinalDOOM? - "fuck you, pussy!\nget the fuck out!", - "you quit and i'll jizz\nin your cystholes!", - "if you leave, i'll make\nthe lord drink my jizz.", - "hey, ron! can we say\n'fuck' in the game?", - "i'd leave: this is just\nmore monsters and levels.\nwhat a load.", - "suck it down, asshole!\nyou're a fucking wimp!", - "don't quit now! we're \nstill spending your money!", - - // Internal debug. Different style, too. - "THIS IS NO MESSAGE!\nPage intentionally left blank." -}; - -#endif - - - - diff --git a/games/NXDoom/src/strife/dstrings.h b/games/NXDoom/src/strife/dstrings.h deleted file mode 100644 index 81115792a29..00000000000 --- a/games/NXDoom/src/strife/dstrings.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: -// DOOM strings, by language. -// - - -#ifndef __DSTRINGS__ -#define __DSTRINGS__ - - -// All important printed strings. - -#include "d_englsh.h" - -// Misc. other strings. -#define SAVEGAMENAME "doomsav" - - -// QuitDOOM messages -// 8 per each game type -#define NUM_QUITMESSAGES 8 - -extern const char *doom1_endmsg[]; -extern const char *doom2_endmsg[]; - - -#endif diff --git a/games/NXDoom/src/strife/f_finale.c b/games/NXDoom/src/strife/f_finale.c deleted file mode 100644 index a6d139938ab..00000000000 --- a/games/NXDoom/src/strife/f_finale.c +++ /dev/null @@ -1,1047 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// Copyright(C) 2010 James Haley, Samuel Villarreal -// -// 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. -// -// DESCRIPTION: -// Game completion, final screen animation. -// -// [STRIFE] Module marked finished 2010-09-13 22:56 -// - - -#include -#include - -// Functions. -#include "deh_main.h" -#include "i_system.h" -#include "i_swap.h" -#include "z_zone.h" -#include "v_video.h" -#include "w_wad.h" -#include "s_sound.h" - -// Data. -#include "d_main.h" -#include "dstrings.h" -#include "sounds.h" - -#include "doomstat.h" -#include "r_state.h" - -#include "p_dialog.h" // [STRIFE] - -typedef enum -{ - F_STAGE_TEXT, - F_STAGE_ARTSCREEN, - F_STAGE_CAST, -} finalestage_t; - -// ? -//#include "doomstat.h" -//#include "r_local.h" -//#include "f_finale.h" - -// Stage of animation: -finalestage_t finalestage; - -unsigned int finalecount; - -// haleyjd 09/12/10: [STRIFE] Slideshow variables -const char *slideshow_panel; -unsigned int slideshow_tics; -int slideshow_state; - -// haleyjd 09/13/10: [STRIFE] All this is unused. -/* -#define TEXTSPEED 3 -#define TEXTWAIT 250 - -typedef struct -{ - GameMission_t mission; - int episode, level; - char *background; - char *text; -} textscreen_t; - -static textscreen_t textscreens[] = -{ - { doom, 1, 8, "FLOOR4_8", E1TEXT}, - { doom, 2, 8, "SFLR6_1", E2TEXT}, - { doom, 3, 8, "MFLR8_4", E3TEXT}, - { doom, 4, 8, "MFLR8_3", E4TEXT}, - - { doom2, 1, 6, "SLIME16", C1TEXT}, - { doom2, 1, 11, "RROCK14", C2TEXT}, - { doom2, 1, 20, "RROCK07", C3TEXT}, - { doom2, 1, 30, "RROCK17", C4TEXT}, - { doom2, 1, 15, "RROCK13", C5TEXT}, - { doom2, 1, 31, "RROCK19", C6TEXT}, - - { pack_tnt, 1, 6, "SLIME16", T1TEXT}, - { pack_tnt, 1, 11, "RROCK14", T2TEXT}, - { pack_tnt, 1, 20, "RROCK07", T3TEXT}, - { pack_tnt, 1, 30, "RROCK17", T4TEXT}, - { pack_tnt, 1, 15, "RROCK13", T5TEXT}, - { pack_tnt, 1, 31, "RROCK19", T6TEXT}, - - { pack_plut, 1, 6, "SLIME16", P1TEXT}, - { pack_plut, 1, 11, "RROCK14", P2TEXT}, - { pack_plut, 1, 20, "RROCK07", P3TEXT}, - { pack_plut, 1, 30, "RROCK17", P4TEXT}, - { pack_plut, 1, 15, "RROCK13", P5TEXT}, - { pack_plut, 1, 31, "RROCK19", P6TEXT}, -}; - -char* finaletext; -char* finaleflat; -*/ - -void F_StartCast (void); -void F_CastTicker (void); -boolean F_CastResponder (event_t *ev); -void F_CastDrawer (void); - -// [STRIFE] - Slideshow states enumeration -enum -{ - // Exit states - SLIDE_EXITHACK = -99, // Hacky exit - start a new dialog - SLIDE_HACKHACK = -9, // Bizarre unused state - SLIDE_EXIT = -1, // Exit to next finale state - SLIDE_CHOCO = -2, // haleyjd: This state is Choco-specific... see below. - - // Unknown - SLIDE_UNKNOWN = 0, // Dunno what it's for, possibly unused - - // MAP03 - Macil's Programmer exposition - SLIDE_PROGRAMMER1 = 1, - SLIDE_PROGRAMMER2, - SLIDE_PROGRAMMER3, - SLIDE_PROGRAMMER4, // Next state = -99 - - // MAP10 - Macil's Sigil exposition - SLIDE_SIGIL1 = 5, - SLIDE_SIGIL2, - SLIDE_SIGIL3, - SLIDE_SIGIL4, // Next state = -99 - - // MAP29 - Endings - // Good Ending - SLIDE_GOODEND1 = 10, - SLIDE_GOODEND2, - SLIDE_GOODEND3, - SLIDE_GOODEND4, // Next state = -1 - - // Bad Ending - SLIDE_BADEND1 = 14, - SLIDE_BADEND2, - SLIDE_BADEND3, // Next state = -1 - - // Blah Ending - SLIDE_BLAHEND1 = 17, - SLIDE_BLAHEND2, - SLIDE_BLAHEND3, // Next state = -1 - - // Demo Ending - haleyjd 20130301: v1.31 only - SLIDE_DEMOEND1 = 25, - SLIDE_DEMOEND2 // Next state = -1 -}; - -// -// F_StartFinale -// -// [STRIFE] -// haleyjd 09/13/10: Modified to drive slideshow sequences. -// -void F_StartFinale (void) -{ -#if 0 - // haleyjd 20111006: see below... - patch_t *panel; -#endif - - gameaction = ga_nothing; - gamestate = GS_FINALE; - viewactive = false; - automapactive = false; - wipegamestate = -1; // [STRIFE] - - // [STRIFE] Setup the slide show - slideshow_panel = DEH_String("PANEL0"); - - // haleyjd 20111006: These two lines of code *are* in vanilla Strife; - // however, there, they were completely inconsequential due to the dirty - // rects system. No intervening V_MarkRect call means PANEL0 was never - // drawn to the framebuffer. In Chocolate Strife, however, with no such - // system in place, this only manages to fuck up the fade-out that is - // supposed to happen at the beginning of all finales. So, don't do it! -#if 0 - panel = (patch_t *)W_CacheLumpName(slideshow_panel, PU_CACHE); - V_DrawPatch(0, 0, panel); -#endif - - switch(gamemap) - { - case 3: // Macil's exposition on the Programmer - slideshow_state = SLIDE_PROGRAMMER1; - break; - case 9: // Super hack for death of Programmer - slideshow_state = SLIDE_EXITHACK; - break; - case 10: // Macil's exposition on the Sigil - slideshow_state = SLIDE_SIGIL1; - break; - case 29: // Endings - if(!netgame) - { - if(players[0].health <= 0) // Bad ending - slideshow_state = SLIDE_BADEND1; // - Humanity goes extinct - else - { - if((players[0].questflags & QF_QUEST25) && // Converter destroyed - (players[0].questflags & QF_QUEST27)) // Computer destroyed (wtf?!) - { - // Good ending - You get the hot babe. - slideshow_state = SLIDE_GOODEND1; - } - else - { - // Blah ending - You win the battle, but fail at life. - slideshow_state = SLIDE_BLAHEND1; - } - } - } - break; - case 34: // For the demo version ending - slideshow_state = SLIDE_EXIT; - - // haleyjd 20130301: Somebody noticed the demo levels were missing the - // ending they used to have in the demo version EXE, I guess. But the - // weird thing is, this will only trigger if you run with strife0.wad, - // and no released version thereof actually works with the 1.31 EXE - // due to differing dialog formats... was there to be an updated demo - // that never got released?! - if(gameversion == exe_strife_1_31 && isdemoversion) - slideshow_state = SLIDE_DEMOEND1; - break; - } - - S_ChangeMusic(mus_dark, 1); - slideshow_tics = 7; - finalestage = F_STAGE_TEXT; - finalecount = 0; -} - -// -// F_Responder -// -// [STRIFE] Verified unmodified -// -boolean F_Responder (event_t *event) -{ - if (finalestage == F_STAGE_CAST) - return F_CastResponder (event); - - return false; -} - -// -// F_WaitTicker -// -// [STRIFE] New function -// haleyjd 09/13/10: This is called from G_Ticker if gamestate is 1, but we -// have no idea for what it's supposed to be. It is unused. -// -void F_WaitTicker(void) -{ - if(++finalecount >= 250) - { - gamestate = GS_FINALE; - finalestage = 0; - finalecount = 0; - } -} - -// -// F_DoSlideShow -// -// [STRIFE] New function -// haleyjd 09/13/10: Handles slideshow states. Begging to be tabulated! -// -static void F_DoSlideShow(void) -{ - patch_t *patch; - - switch(slideshow_state) - { - case SLIDE_UNKNOWN: // state #0, seems to be unused - slideshow_tics = 700; - slideshow_state = SLIDE_EXIT; - // falls through into state 1, so above is pointless? ... - - case SLIDE_PROGRAMMER1: // state #1 - slideshow_panel = DEH_String("SS2F1"); - I_StartVoice(DEH_String("MAC10")); - slideshow_state = SLIDE_PROGRAMMER2; - slideshow_tics = 315; - break; - case SLIDE_PROGRAMMER2: // state #2 - slideshow_panel = DEH_String("SS2F2"); - I_StartVoice(DEH_String("MAC11")); - slideshow_state = SLIDE_PROGRAMMER3; - slideshow_tics = 350; - break; - case SLIDE_PROGRAMMER3: // state #3 - slideshow_panel = DEH_String("SS2F3"); - I_StartVoice(DEH_String("MAC12")); - slideshow_state = SLIDE_PROGRAMMER4; - slideshow_tics = 420; - break; - case SLIDE_PROGRAMMER4: // state #4 - slideshow_panel = DEH_String("SS2F4"); - I_StartVoice(DEH_String("MAC13")); - slideshow_state = SLIDE_EXITHACK; // End of slides - slideshow_tics = 595; - break; - - case SLIDE_SIGIL1: // state #5 - slideshow_panel = DEH_String("SS3F1"); - I_StartVoice(DEH_String("MAC16")); - slideshow_state = SLIDE_SIGIL2; - slideshow_tics = 350; - break; - case SLIDE_SIGIL2: // state #6 - slideshow_panel = DEH_String("SS3F2"); - I_StartVoice(DEH_String("MAC17")); - slideshow_state = SLIDE_SIGIL3; - slideshow_tics = 420; - break; - case SLIDE_SIGIL3: // state #7 - slideshow_panel = DEH_String("SS3F3"); - I_StartVoice(DEH_String("MAC18")); - slideshow_tics = 420; - slideshow_state = SLIDE_SIGIL4; - break; - case SLIDE_SIGIL4: // state #8 - slideshow_panel = DEH_String("SS3F4"); - I_StartVoice(DEH_String("MAC19")); - slideshow_tics = 385; - slideshow_state = SLIDE_EXITHACK; // End of slides - break; - - case SLIDE_GOODEND1: // state #10 - slideshow_panel = DEH_String("SS4F1"); - S_StartMusic(mus_happy); - I_StartVoice(DEH_String("RIE01")); - slideshow_state = SLIDE_GOODEND2; - slideshow_tics = 455; - break; - case SLIDE_GOODEND2: // state #11 - slideshow_panel = DEH_String("SS4F2"); - I_StartVoice(DEH_String("BBX01")); - slideshow_state = SLIDE_GOODEND3; - slideshow_tics = 385; - break; - case SLIDE_GOODEND3: // state #12 - slideshow_panel = DEH_String("SS4F3"); - I_StartVoice(DEH_String("BBX02")); - slideshow_state = SLIDE_GOODEND4; - slideshow_tics = 490; - break; - case SLIDE_GOODEND4: // state #13 - slideshow_panel = DEH_String("SS4F4"); - slideshow_state = SLIDE_EXIT; // Go to end credits - slideshow_tics = 980; - break; - - case SLIDE_BADEND1: // state #14 - S_StartMusic(mus_sad); - slideshow_panel = DEH_String("SS5F1"); - I_StartVoice(DEH_String("SS501b")); - slideshow_state = SLIDE_BADEND2; - slideshow_tics = 385; - break; - case SLIDE_BADEND2: // state #15 - slideshow_panel = DEH_String("SS5F2"); - I_StartVoice(DEH_String("SS502b")); - slideshow_state = SLIDE_BADEND3; - slideshow_tics = 350; - break; - case SLIDE_BADEND3: // state #16 - slideshow_panel = DEH_String("SS5F3"); - I_StartVoice(DEH_String("SS503b")); - slideshow_state = SLIDE_EXIT; // Go to end credits - slideshow_tics = 385; - break; - - case SLIDE_BLAHEND1: // state #17 - S_StartMusic(mus_end); - slideshow_panel = DEH_String("SS6F1"); - I_StartVoice(DEH_String("SS601A")); - slideshow_state = SLIDE_BLAHEND2; - slideshow_tics = 280; - break; - case SLIDE_BLAHEND2: // state #18 - S_StartMusic(mus_end); - slideshow_panel = DEH_String("SS6F2"); - I_StartVoice(DEH_String("SS602A")); - slideshow_state = SLIDE_BLAHEND3; - slideshow_tics = 280; - break; - case SLIDE_BLAHEND3: // state #19 - S_StartMusic(mus_end); - slideshow_panel = DEH_String("SS6F3"); - I_StartVoice(DEH_String("SS603A")); - slideshow_state = SLIDE_EXIT; // Go to credits - slideshow_tics = 315; - break; - - case SLIDE_DEMOEND1: // state #25 - only exists in 1.31 - slideshow_panel = DEH_String("PANEL7"); - slideshow_tics = 175; - slideshow_state = SLIDE_DEMOEND2; - break; - case SLIDE_DEMOEND2: // state #26 - ditto - slideshow_panel = DEH_String("VELLOGO"); - slideshow_tics = 175; - slideshow_state = SLIDE_EXIT; // Go to end credits - break; - - case SLIDE_EXITHACK: // state -99: super hack state - gamestate = GS_LEVEL; - P_DialogStartP1(); - break; - case SLIDE_HACKHACK: // state -9: unknown bizarre unused state - S_StartSound(NULL, sfx_rifle); - slideshow_tics = 3150; - break; - case SLIDE_EXIT: // state -1: proceed to next finale stage - finalecount = 0; - finalestage = F_STAGE_ARTSCREEN; - wipegamestate = -1; - S_StartMusic(mus_fast); - // haleyjd 20130301: The ONLY glitch fixed in 1.31 of Strife - // *would* be something this insignificant, of course! - if(gameversion != exe_strife_1_31) - slideshow_state = SLIDE_CHOCO; // haleyjd: see below... - break; - case SLIDE_CHOCO: - // haleyjd 09/14/10: This wouldn't be necessary except that Choco - // doesn't support the V_MarkRect dirty rectangles system. This - // just so happens to have hidden the fact that the ending - // does a screenfade every ~19 seconds due to remaining stuck in - // SLIDE_EXIT state above, UNLESS the menus were active - the - // V_MarkRect calls in the menu system cause it to be visible. - // This means that in order to get the same behavior as the vanilla - // EXE, I need different code. So, come to this state and only set - // wipegamestate if menuactive is true. - finalecount = 0; - finalestage = F_STAGE_ARTSCREEN; - if(menuactive) - wipegamestate = -1; - S_StartMusic(mus_fast); - slideshow_state = SLIDE_CHOCO; // remain here. - break; - default: - break; - } - - finalecount = 0; - if(gameversion != exe_strife_1_31) // See above. This was removed in 1.31. - { - patch = (patch_t *)W_CacheLumpName(DEH_String("PANEL0"), PU_CACHE); - V_DrawPatch(0, 0, patch); - } -} - -// -// F_Ticker -// -// [STRIFE] Modifications for new finales -// haleyjd 09/13/10: Calls F_DoSlideShow -// -void F_Ticker (void) -{ - size_t i; - - // check for skipping - if (finalecount > 50) // [STRIFE] No commercial check - { - // go on to the next level - for (i=0 ; i slideshow_tics) // [STRIFE] Advance slideshow - F_DoSlideShow(); - - // [STRIFE]: Rest is unused - /* - if ( gamemode == commercial) - return; - - if (finalestage == F_STAGE_TEXT - && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT) - { - finalecount = 0; - finalestage = F_STAGE_ARTSCREEN; - wipegamestate = -1; // force a wipe - if (gameepisode == 3) - S_StartMusic (mus_logo); - } - */ -} - -// haleyjd 09/13/10: Not present in Strife: Cast drawing functions - -#include "hu_stuff.h" - -/* -// -// F_TextWrite -// -void F_TextWrite (void) -{ - byte* src; - byte* dest; - - int x,y,w; - signed int count; - char* ch; - int c; - int cx; - int cy; - - // erase the entire screen to a tiled background - src = W_CacheLumpName ( finaleflat , PU_CACHE); - dest = I_VideoBuffer; - - for (y=0 ; y HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - if (cx+w > SCREENWIDTH) - break; - V_DrawPatch(cx, cy, hu_font[c]); - cx+=w; - } - -} -*/ - -// -// Final DOOM 2 animation -// Casting by id Software. -// in order of appearance -// -typedef struct -{ - int isindemo; // [STRIFE] Changed from name, which is in mobjinfo - mobjtype_t type; -} castinfo_t; - -// haleyjd: [STRIFE] A new cast order was defined, however it is unused in any -// of the released versions of Strife, even including the demo version :( -castinfo_t castorder[] = { - { 1, MT_PLAYER }, - { 1, MT_BEGGAR1 }, - { 1, MT_PEASANT2_A }, - { 1, MT_REBEL1 }, - { 1, MT_GUARD1 }, - { 1, MT_CRUSADER }, - { 1, MT_RLEADER2 }, - { 0, MT_SENTINEL }, - { 0, MT_STALKER }, - { 0, MT_PROGRAMMER }, - { 0, MT_REAVER }, - { 0, MT_PGUARD }, - { 0, MT_INQUISITOR }, - { 0, MT_PRIEST }, - { 0, MT_SPECTRE_A }, - { 0, MT_BISHOP }, - { 0, MT_ENTITY }, - { 1, NUMMOBJTYPES } -}; - -int castnum; -int casttics; -state_t* caststate; -boolean castdeath; -int castframes; -int castonmelee; -boolean castattacking; - -// -// F_StartCast -// -// haleyjd 09/13/10: [STRIFE] Heavily modified, yet unused. -// Evidence suggests this was meant to be started from a menu item. -// See m_menu.c for more info. -// -void F_StartCast (void) -{ - usergame = false; - gameaction = ga_nothing; - viewactive = false; - automapactive = false; - castnum = 0; - gamestate = GS_FINALE; - caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - casttics = caststate->tics; - if(casttics > 50) - casttics = 50; - wipegamestate = -1; // force a screen wipe - castdeath = false; - finalestage = F_STAGE_CAST; - castframes = 0; - castonmelee = 0; - castattacking = false; -} - - -// -// F_CastTicker -// -// [STRIFE] Heavily modified, but unused. -// haleyjd 09/13/10: Yeah, I bothered translating this even though it isn't -// going to be seen, in part because I hope some Strife port or another will -// pick it up and finish it, adding it as the optional menu item it was -// meant to be, or just adding it as part of the ending sequence. -// -void F_CastTicker (void) -{ - int st; - - if (--casttics > 0) - return; // not time to change state yet - - if (caststate->tics == -1 || caststate->nextstate == S_NULL) - { - // switch from deathstate to next monster - castnum++; - castdeath = false; - if (isdemoversion) - { - // [STRIFE] Demo version had a shorter cast - if(!castorder[castnum].isindemo) - castnum = 0; - } - // [STRIFE] Break on type == NUMMOBJTYPES rather than name == NULL - if (castorder[castnum].type == NUMMOBJTYPES) - castnum = 0; - if (mobjinfo[castorder[castnum].type].seesound) - S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound); - caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - castframes = 0; - } - else - { - int sfx = 0; - - // just advance to next state in animation - if (caststate == &states[S_PLAY_05]) // villsa [STRIFE] - updated - goto stopattack; // Oh, gross hack! - st = caststate->nextstate; - caststate = &states[st]; - castframes++; - - if (st != mobjinfo[castorder[castnum].type].meleestate && - st != mobjinfo[castorder[castnum].type].missilestate) - { - if (st == S_PLAY_05) - sfx = sfx_rifle; - else - sfx = 0; - } - else - sfx = mobjinfo[castorder[castnum].type].attacksound; - - if (sfx) - S_StartSound (NULL, sfx); - } - - if (!castdeath && castframes == 12) - { - // go into attack frame - castattacking = true; - if (castonmelee) - caststate=&states[mobjinfo[castorder[castnum].type].meleestate]; - else - caststate=&states[mobjinfo[castorder[castnum].type].missilestate]; - castonmelee ^= 1; - if (caststate == &states[S_NULL]) - { - if (castonmelee) - caststate = &states[mobjinfo[castorder[castnum].type].meleestate]; - else - caststate = &states[mobjinfo[castorder[castnum].type].missilestate]; - } - } - - if (castattacking) - { - if (castframes == 24 - || caststate == &states[mobjinfo[castorder[castnum].type].seestate] ) - { -stopattack: - castattacking = false; - castframes = 0; - caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - } - } - - casttics = caststate->tics; - if (casttics > 50) // [STRIFE] Cap tics - casttics = 50; - else if (casttics == -1) - casttics = 15; -} - - -// -// F_CastResponder -// -// [STRIFE] This still exists in Strife but is never used. -// It was used at some point in development, however, as they made -// numerous modifications to the cast call system. -// -boolean F_CastResponder (event_t* ev) -{ - if (ev->type != ev_keydown) - return false; - - if (castdeath) - return true; // already in dying frames - - // go into death frame - castdeath = true; - caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; - casttics = caststate->tics; - if(casttics > 50) // [STRIFE] Upper bound on casttics - casttics = 50; - castframes = 0; - castattacking = false; - if (mobjinfo[castorder[castnum].type].deathsound) - S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound); - - return true; -} - -// -// F_CastPrint -// -// [STRIFE] Verified unmodified, and unused. -// -void F_CastPrint (char* text) -{ - char* ch; - int c; - int cx; - int w; - int width; - - // find width - ch = text; - width = 0; - - while (ch) - { - c = *ch++; - if (!c) - break; - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c> HU_FONTSIZE) - { - width += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - width += w; - } - - // draw it - cx = 160-width/2; - ch = text; - while (ch) - { - c = *ch++; - if (!c) - break; - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c> HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - V_DrawPatch(cx, 180, hu_font[c]); - cx+=w; - } - -} - -// haleyjd 09/13/10: [STRIFE] Unfortunately they removed whatever was -// partway finished of this function from the binary, as there is no -// trace of it. This means we cannot know for sure what the cast call -// would have looked like. :( -/* -// -// F_CastDrawer -// -void F_CastDrawer (void) -{ - spritedef_t* sprdef; - spriteframe_t* sprframe; - int lump; - boolean flip; - patch_t* patch; - - // erase the entire screen to a background - V_DrawPatch (0, 0, W_CacheLumpName (DEH_String("BOSSBACK"), PU_CACHE)); - - F_CastPrint (DEH_String(castorder[castnum].name)); - - // draw the current frame in the middle of the screen - sprdef = &sprites[caststate->sprite]; - sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK]; - lump = sprframe->lump[0]; - flip = (boolean)sprframe->flip[0]; - - patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE); - if (flip) - V_DrawPatchFlipped(160, 170, patch); - else - V_DrawPatch(160, 170, patch); -} -*/ - -#ifdef STRIFE_DEMO_CODE -// -// F_DrawPatchCol -// -// [STRIFE] Verified unmodified, but not present in 1.2 -// It WAS present in the demo version, however... -// -void -F_DrawPatchCol -( int x, - patch_t* patch, - int col ) -{ - column_t* column; - byte* source; - byte* dest; - byte* desttop; - int count; - - column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); - desttop = I_VideoBuffer + x; - - // step through the posts in a column - while (column->topdelta != 0xff ) - { - source = (byte *)column + 3; - dest = desttop + column->topdelta*SCREENWIDTH; - count = column->length; - - while (count--) - { - *dest = *source++; - dest += SCREENWIDTH; - } - column = (column_t *)( (byte *)column + column->length + 4 ); - } -} -#endif - -// -// F_DrawMap34End -// -// [STRIFE] Modified from F_BunnyScroll -// * In 1.2 and up this just causes a weird black screen. -// * In the demo version, it was an actual scroll between two screens. -// I have implemented both code segments, though only the black screen -// one will currently be used, as full demo version support isn't looking -// likely right now. -// -void F_DrawMap34End (void) -{ - signed int scrolled; - int x; -// patch_t* p1; -// patch_t* p2; - -// p1 = W_CacheLumpName (DEH_String("credit"), PU_LEVEL); -// p2 = W_CacheLumpName (DEH_String("vellogo"), PU_LEVEL); - - V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); - - - scrolled = (320 - ((signed int) finalecount-430)/2); - if (scrolled > 320) - scrolled = 320; - if (scrolled < 0) - scrolled = 0; - -#ifdef STRIFE_DEMO_CODE - for ( x=0 ; x - -#include "z_zone.h" -#include "i_video.h" -#include "v_video.h" -#include "m_random.h" - -#include "doomtype.h" - -#include "r_defs.h" // haleyjd [STRIFE] -#include "r_draw.h" - -#include "f_wipe.h" - -// -// SCREEN WIPE PACKAGE -// - -// when zero, stop the wipe -static boolean go = 0; - -static byte* wipe_scr_start; -static byte* wipe_scr_end; -static byte* wipe_scr; - - -void -wipe_shittyColMajorXform -( short* array, - int width, - int height ) -{ - int x; - int y; - short* dest; - - dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0); - - for(y=0;y 0; i--) - { - if(*cur_screen != *end_screen) - { - changed = true; - *cur_screen = xlatab[(*cur_screen << 8) + *end_screen]; - } - ++cur_screen; - ++end_screen; - } - - return !changed; -} - -// haleyjd 08/26/10: [STRIFE] Verified unmodified. -int -wipe_exitColorXForm -( int width, - int height, - int ticks ) -{ - return 0; -} - - -static int* y; - -int -wipe_initMelt -( int width, - int height, - int ticks ) -{ - int i, r; - - // copy start screen to main screen - memcpy(wipe_scr, wipe_scr_start, width*height); - - // makes this wipe faster (in theory) - // to have stuff in column-major format - wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height); - wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height); - - // setup initial column positions - // (y<0 => not ready to scroll yet) - y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0); - y[0] = -(M_Random()%16); - for (i=1;i 0) y[i] = 0; - else if (y[i] == -16) y[i] = -15; - } - - return 0; -} - -int -wipe_doMelt -( int width, - int height, - int ticks ) -{ - int i; - int j; - int dy; - int idx; - - short* s; - short* d; - boolean done = true; - - width/=2; - - while (ticks--) - { - for (i=0;i= height) dy = height - y[i]; - s = &((short *)wipe_scr_end)[i*height+y[i]]; - d = &((short *)wipe_scr)[y[i]*width+i]; - idx = 0; - for (j=dy;j;j--) - { - d[idx] = *(s++); - idx += width; - } - y[i] += dy; - s = &((short *)wipe_scr_start)[i*height]; - d = &((short *)wipe_scr)[y[i]*width+i]; - idx = 0; - for (j=height-y[i];j;j--) - { - d[idx] = *(s++); - idx += width; - } - done = false; - } - } - } - - return done; - -} - -int -wipe_exitMelt -( int width, - int height, - int ticks ) -{ - Z_Free(y); - Z_Free(wipe_scr_start); - Z_Free(wipe_scr_end); - return 0; -} - -// haleyjd 08/26/10: [STRIFE] Verified unmodified. -int -wipe_StartScreen -( int x, - int y, - int width, - int height ) -{ - wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); - I_ReadScreen(wipe_scr_start); - return 0; -} - -// haleyjd 08/26/10: [STRIFE] Verified unmodified. -int -wipe_EndScreen -( int x, - int y, - int width, - int height ) -{ - wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); - I_ReadScreen(wipe_scr_end); - V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr. - return 0; -} - -// haleyjd 08/26/10: [STRIFE] Verified unmodified. -int -wipe_ScreenWipe -( int wipeno, - int x, - int y, - int width, - int height, - int ticks ) -{ - int rc; - static int (*wipes[])(int, int, int) = - { - wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm, - wipe_initMelt, wipe_doMelt, wipe_exitMelt - }; - - // initial stuff - if (!go) - { - go = 1; - // haleyjd 20110629 [STRIFE]: We *must* use a temp buffer here. - wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG - //wipe_scr = I_VideoBuffer; - (*wipes[wipeno*3])(width, height, ticks); - } - - // do a piece of wipe-in - V_MarkRect(0, 0, width, height); - rc = (*wipes[wipeno*3+1])(width, height, ticks); - - // haleyjd 20110629 [STRIFE]: Copy temp buffer to the real screen. - V_DrawBlock(x, y, width, height, wipe_scr); - - // final stuff - if (rc) - { - go = 0; - (*wipes[wipeno*3+2])(width, height, ticks); - } - - return !go; -} - diff --git a/games/NXDoom/src/strife/f_wipe.h b/games/NXDoom/src/strife/f_wipe.h deleted file mode 100644 index 6ffd05872a6..00000000000 --- a/games/NXDoom/src/strife/f_wipe.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Mission start screen wipe/melt, special effects. -// - - -#ifndef __F_WIPE_H__ -#define __F_WIPE_H__ - -// -// SCREEN WIPE PACKAGE -// - -enum -{ - // [STRIFE]: ColorXForm reimplemented as a proper crossfade - wipe_ColorXForm, - - // weird screen melt - wipe_Melt, - - wipe_NUMWIPES -}; - -int -wipe_StartScreen -( int x, - int y, - int width, - int height ); - - -int -wipe_EndScreen -( int x, - int y, - int width, - int height ); - - -int -wipe_ScreenWipe -( int wipeno, - int x, - int y, - int width, - int height, - int ticks ); - -#endif diff --git a/games/NXDoom/src/strife/g_game.c b/games/NXDoom/src/strife/g_game.c deleted file mode 100644 index 50faee1c845..00000000000 --- a/games/NXDoom/src/strife/g_game.c +++ /dev/null @@ -1,2534 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// - -#include -#include -#include - -#include "doomdef.h" -#include "doomkeys.h" -#include "doomstat.h" - -#include "deh_main.h" -#include "deh_misc.h" -#include "z_zone.h" -#include "f_finale.h" -#include "m_argv.h" -#include "m_controls.h" -#include "m_misc.h" -#include "m_menu.h" -#include "m_misc.h" -#include "m_saves.h" // STRIFE -#include "m_random.h" -#include "i_input.h" -#include "i_joystick.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "p_setup.h" -#include "p_saveg.h" -#include "p_tick.h" -#include "d_main.h" -#include "wi_stuff.h" -#include "hu_stuff.h" -#include "st_stuff.h" -#include "am_map.h" - -// Needs access to LFB. -#include "v_video.h" - -#include "w_wad.h" - -#include "p_local.h" - -#include "s_sound.h" - -// Data. -#include "dstrings.h" -#include "sounds.h" - -// SKY handling - still the wrong place. -#include "r_data.h" -#include "r_sky.h" - -#include "p_dialog.h" // villsa [STRIFE] - -#include "g_game.h" - - -#define SAVEGAMESIZE 0x2c000 - -void G_ReadDemoTiccmd (ticcmd_t* cmd); -void G_WriteDemoTiccmd (ticcmd_t* cmd); -void G_PlayerReborn (int player); - -void G_DoReborn (int playernum); - -void G_DoLoadLevel (void); -void G_DoNewGame (void); -void G_DoPlayDemo (void); -void G_DoCompleted (void); -void G_DoVictory (void); -void G_DoWorldDone (void); -void G_DoSaveGame (char *path); - -// Gamestate the last time G_Ticker was called. - -gamestate_t oldgamestate; - -gameaction_t gameaction; -gamestate_t gamestate; -skill_t gameskill = 2; // [STRIFE] Default value set to 2. -boolean respawnmonsters; -//int gameepisode; -int gamemap; - -// haleyjd 08/24/10: [STRIFE] New variables -int destmap; // current destination map when exiting -int riftdest; // destination spot for player -angle_t riftangle; // player angle saved during exit - -// If non-zero, exit the level after this number of minutes. - -int timelimit; - -boolean paused; -boolean sendpause; // send a pause event next tic -boolean sendsave; // send a save event next tic -boolean usergame; // ok to save / end game - -boolean timingdemo; // if true, exit with report on completion -boolean nodrawers; // for comparative timing purposes -int starttime; // for comparative timing purposes - -boolean viewactive; - -int deathmatch; // only if started as net death -boolean netgame; // only true if packets are broadcast -boolean playeringame[MAXPLAYERS]; -player_t players[MAXPLAYERS]; - -boolean turbodetected[MAXPLAYERS]; - -int consoleplayer; // player taking events and displaying -int displayplayer; // view being displayed -int levelstarttic; // gametic at level start -int totalkills, /*totalitems,*/ totalsecret; // for intermission - -char *demoname; -boolean demorecording; -boolean longtics; // cph's doom 1.91 longtics hack -boolean lowres_turn; // low resolution turning for longtics -boolean demoplayback; -boolean netdemo; -byte* demobuffer; -byte* demo_p; -byte* demoend; -boolean singledemo; // quit after playing a demo from cmdline - -boolean precache = true; // if true, load all graphics at start - -boolean testcontrols = false; // Invoked by setup to test controls - -wbstartstruct_t wminfo; // parms for world map / intermission - -byte consistancy[MAXPLAYERS][BACKUPTICS]; - -#define MAXPLMOVE (forwardmove[1]) - -#define TURBOTHRESHOLD 0x32 - -fixed_t forwardmove[2] = {0x19, 0x32}; -fixed_t sidemove[2] = {0x18, 0x28}; -fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn - -int mouse_fire_countdown = 0; // villsa [STRIFE] -int joystick_fire_countdown = 0; - -static int *weapon_keys[] = { - &key_weapon1, - &key_weapon2, - &key_weapon3, - &key_weapon4, - &key_weapon5, - &key_weapon6, - &key_weapon7, - &key_weapon8 -}; - -// Set to -1 or +1 to switch to the previous or next weapon. - -static int next_weapon = 0; - -// Used for prev/next weapon keys. -// STRIFE-TODO: Check this table makes sense. - -static const struct -{ - weapontype_t weapon; - weapontype_t weapon_num; -} weapon_order_table[] = { - { wp_fist, wp_fist }, - { wp_poisonbow, wp_elecbow }, - { wp_elecbow, wp_elecbow }, - { wp_rifle, wp_rifle }, - { wp_missile, wp_missile }, - { wp_wpgrenade, wp_hegrenade }, - { wp_hegrenade, wp_hegrenade }, - { wp_flame, wp_flame }, - { wp_torpedo, wp_mauler }, - { wp_mauler, wp_mauler }, - { wp_sigil, wp_sigil }, -}; - -#define SLOWTURNTICS 6 - -#define NUMKEYS 256 -#define MAX_JOY_BUTTONS 20 - -static boolean gamekeydown[NUMKEYS]; -static int turnheld; // for accelerative turning - -static boolean mousearray[MAX_MOUSE_BUTTONS + 1]; -static boolean *mousebuttons = &mousearray[1]; // allow [-1] - -// mouse values are used once -int mousex; -int mousey; - -static int dclicktime; -static boolean dclickstate; -static int dclicks; -static int dclicktime2; -static boolean dclickstate2; -static int dclicks2; - -// joystick values are repeated -static int joyxmove; -static int joyymove; -static int joystrafemove; -static int joylook; -static boolean joyarray[MAX_JOY_BUTTONS + 1]; -static boolean *joybuttons = &joyarray[1]; // allow [-1] - -static int savegameslot = 6; // [STRIFE] initialized to 6 -static char savedescription[32]; - -int testcontrols_mousespeed; - -#define BODYQUESIZE 32 - -mobj_t* bodyque[BODYQUESIZE]; -//int bodyqueslot; [STRIFE] unused - -int vanilla_savegame_limit = 1; -int vanilla_demo_limit = 1; - - -int G_CmdChecksum (ticcmd_t* cmd) -{ - size_t i; - int sum = 0; - - for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++) - sum += ((int *)cmd)[i]; - - return sum; -} - -static boolean WeaponSelectable(weapontype_t weapon) -{ - player_t *player; - - player = &players[consoleplayer]; - - // Can't select a weapon if we don't own it. - - if (!player->weaponowned[weapon]) - { - return false; - } - - // Can't use registered-only weapons in demo mode: - - if (isdemoversion && !weaponinfo[weapon].availabledemo) - { - return false; - } - - // Special rules for switching to alternate versions of weapons. - // These must match the weapon-switching rules in P_PlayerThink() - - // haleyjd 20141024: same fix here as in P_PlayerThink for torpedo. - - if (weapon == wp_torpedo - && player->ammo[weaponinfo[wp_torpedo].ammo] < 30) - { - return false; - } - - if (player->ammo[weaponinfo[weapon].ammo] == 0) - { - return false; - } - - return true; -} - -static int G_NextWeapon(int direction) -{ - weapontype_t weapon; - int start_i, i; - - // Find index in the table. - - if (players[consoleplayer].pendingweapon == wp_nochange) - { - weapon = players[consoleplayer].readyweapon; - } - else - { - weapon = players[consoleplayer].pendingweapon; - } - - for (i=0; i= arrlen(weapon_order_table)) { - I_Error("Internal error: weapon %d not present in weapon_order_table", weapon); - } - - // Switch weapon. - start_i = i; - do - { - i += direction; - i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table); - } while (i != start_i && !WeaponSelectable(weapon_order_table[i].weapon)); - - return weapon_order_table[i].weapon_num; -} - -// -// G_BuildTiccmd -// Builds a ticcmd from all of the available inputs -// or reads it from the demo buffer. -// If recording a demo, write it out -// -void G_BuildTiccmd (ticcmd_t* cmd, int maketic) -{ - int i; - boolean strafe; - boolean bstrafe; - int speed; - int tspeed; - int forward; - int side; - - memset(cmd, 0, sizeof(ticcmd_t)); - - cmd->consistancy = - consistancy[consoleplayer][maketic%BACKUPTICS]; - - // villsa [STRIFE] look up key - if(gamekeydown[key_lookup] || (joylook < 0 && joystick_look_sensitivity)) - cmd->buttons2 |= BT2_LOOKUP; - - // villsa [STRIFE] look down key - if(gamekeydown[key_lookdown] || (joylook > 0 && joystick_look_sensitivity)) - cmd->buttons2 |= BT2_LOOKDOWN; - - // villsa [STRIFE] inventory use key - if(gamekeydown[key_invuse] || joybuttons[joybuseartifact]) - { - player_t* player = &players[consoleplayer]; - if(player->numinventory > 0) - { - cmd->buttons2 |= BT2_INVUSE; - cmd->inventory = player->inventory[player->inventorycursor].sprite; - } - } - - // villsa [STRIFE] inventory drop key - if(gamekeydown[key_invdrop]) - { - player_t* player = &players[consoleplayer]; - if(player->numinventory > 0) - { - cmd->buttons2 |= BT2_INVDROP; - cmd->inventory = player->inventory[player->inventorycursor].sprite; - } - } - - // villsa [STRIFE] use medkit - if(gamekeydown[key_usehealth]) - cmd->buttons2 |= BT2_HEALTH; - - - - strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] - || joybuttons[joybstrafe]; - - // fraggle: support the old "joyb_speed = 31" hack which - // allowed an autorun effect - - speed = key_speed >= NUMKEYS - || joybspeed >= MAX_JOY_BUTTONS - || gamekeydown[key_speed] - || joybuttons[joybspeed] - || mousebuttons[mousebspeed]; - - forward = side = 0; - - // villsa [STRIFE] running causes centerview to occur - if(speed) - cmd->buttons2 |= BT2_CENTERVIEW; - - // villsa [STRIFE] disable running if low on health - if (players[consoleplayer].health <= 15) - speed = 0; - - // use two stage accelerative turning - // on the keyboard and joystick - if (joyxmove < 0 - || joyxmove > 0 - || gamekeydown[key_right] - || gamekeydown[key_left] - || mousebuttons[mousebturnright] - || mousebuttons[mousebturnleft]) - turnheld += ticdup; - else - turnheld = 0; - - if (turnheld < SLOWTURNTICS) - tspeed = 2; // slow turn - else - tspeed = speed; - - // let movement keys cancel each other out - if (strafe) - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - { - // fprintf(stderr, "strafe right\n"); - side += sidemove[speed]; - } - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - { - // fprintf(stderr, "strafe left\n"); - side -= sidemove[speed]; - } - if (use_analog && joyxmove) - { - joyxmove = joyxmove * joystick_move_sensitivity / 10; - joyxmove = (joyxmove > FRACUNIT) ? FRACUNIT : joyxmove; - joyxmove = (joyxmove < -FRACUNIT) ? -FRACUNIT : joyxmove; - side += FixedMul(sidemove[speed], joyxmove); - } - else if (joystick_move_sensitivity) - { - if (joyxmove > 0) - side += sidemove[speed]; - if (joyxmove < 0) - side -= sidemove[speed]; - } - - } - else - { - if (gamekeydown[key_right] || mousebuttons[mousebturnright]) - cmd->angleturn -= angleturn[tspeed]; - if (gamekeydown[key_left] || mousebuttons[mousebturnleft]) - cmd->angleturn += angleturn[tspeed]; - if (use_analog && joyxmove) - { - // Cubic response curve allows for finer control when stick - // deflection is small. - joyxmove = FixedMul(FixedMul(joyxmove, joyxmove), joyxmove); - joyxmove = joyxmove * joystick_turn_sensitivity / 10; - cmd->angleturn -= FixedMul(angleturn[1], joyxmove); - } - else if (joystick_turn_sensitivity) - { - if (joyxmove > 0) - cmd->angleturn -= angleturn[tspeed]; - if (joyxmove < 0) - cmd->angleturn += angleturn[tspeed]; - } - } - - if (gamekeydown[key_up]) - { - // fprintf(stderr, "up\n"); - forward += forwardmove[speed]; - } - if (gamekeydown[key_down]) - { - // fprintf(stderr, "down\n"); - forward -= forwardmove[speed]; - } - - if (use_analog && joyymove) - { - joyymove = joyymove * joystick_move_sensitivity / 10; - joyymove = (joyymove > FRACUNIT) ? FRACUNIT : joyymove; - joyymove = (joyymove < -FRACUNIT) ? FRACUNIT : joyymove; - forward -= FixedMul(forwardmove[speed], joyymove); - } - else if (joystick_move_sensitivity) - { - if (joyymove < 0) - forward += forwardmove[speed]; - if (joyymove > 0) - forward -= forwardmove[speed]; - } - - if (gamekeydown[key_strafeleft] - || joybuttons[joybstrafeleft] - || mousebuttons[mousebstrafeleft]) - { - side -= sidemove[speed]; - } - - if (gamekeydown[key_straferight] - || joybuttons[joybstraferight] - || mousebuttons[mousebstraferight]) - { - side += sidemove[speed]; - } - - if (use_analog && joystrafemove) - { - joystrafemove = joystrafemove * joystick_move_sensitivity / 10; - joystrafemove = (joystrafemove > FRACUNIT) ? FRACUNIT : joystrafemove; - joystrafemove = (joystrafemove < -FRACUNIT) ? -FRACUNIT : joystrafemove; - side += FixedMul(sidemove[speed], joystrafemove); - } - else if (joystick_move_sensitivity) - { - if (joystrafemove < 0) - side -= sidemove[speed]; - if (joystrafemove > 0) - side += sidemove[speed]; - } - // buttons - cmd->chatchar = HU_dequeueChatChar(); - - // villsa [STRIFE] - add mouse button support for jump - if (gamekeydown[key_jump] || mousebuttons[mousebjump] - || joybuttons[joybjump]) - cmd->buttons2 |= BT2_JUMP; - - // villsa [STRIFE]: Moved mousebuttons[mousebfire] to below - if (gamekeydown[key_fire]) - cmd->buttons |= BT_ATTACK; - - // villsa [STRIFE] - if(mousebuttons[mousebfire]) - { - if(mouse_fire_countdown <= 0) - cmd->buttons |= BT_ATTACK; - else - --mouse_fire_countdown; - } - if(joybuttons[joybfire]) - { - if(joystick_fire_countdown <= 0) - cmd->buttons |= BT_ATTACK; - else - --joystick_fire_countdown; - } - - if (gamekeydown[key_use] - || joybuttons[joybuse] - || mousebuttons[mousebuse]) - { - cmd->buttons |= BT_USE; - // clear double clicks if hit use button - dclicks = 0; - } - - // If the previous or next weapon button is pressed, the - // next_weapon variable is set to change weapons when - // we generate a ticcmd. Choose a new weapon. - - if (gamestate == GS_LEVEL && next_weapon != 0) - { - i = G_NextWeapon(next_weapon); - cmd->buttons |= BT_CHANGE; - cmd->buttons |= i << BT_WEAPONSHIFT; - } - else - { - // Check weapon keys. - - for (i=0; ibuttons |= BT_CHANGE; - cmd->buttons |= i< 1 ) - { - dclickstate = mousebuttons[mousebforward]; - if (dclickstate) - dclicks++; - if (dclicks == 2) - { - cmd->buttons |= BT_USE; - dclicks = 0; - } - else - dclicktime = 0; - } - else - { - dclicktime += ticdup; - if (dclicktime > 20) - { - dclicks = 0; - dclickstate = 0; - } - } - - // strafe double click - bstrafe = - mousebuttons[mousebstrafe] - || joybuttons[joybstrafe]; - if (bstrafe != dclickstate2 && dclicktime2 > 1 ) - { - dclickstate2 = bstrafe; - if (dclickstate2) - dclicks2++; - if (dclicks2 == 2) - { - cmd->buttons |= BT_USE; - dclicks2 = 0; - } - else - dclicktime2 = 0; - } - else - { - dclicktime2 += ticdup; - if (dclicktime2 > 20) - { - dclicks2 = 0; - dclickstate2 = 0; - } - } - } - - forward += mousey; - - if (strafe) - side += mousex*2; - else - cmd->angleturn -= mousex*0x8; - - if (mousex == 0) - { - // No movement in the previous frame - - testcontrols_mousespeed = 0; - } - - mousex = mousey = 0; - - if (forward > MAXPLMOVE) - forward = MAXPLMOVE; - else if (forward < -MAXPLMOVE) - forward = -MAXPLMOVE; - if (side > MAXPLMOVE) - side = MAXPLMOVE; - else if (side < -MAXPLMOVE) - side = -MAXPLMOVE; - - cmd->forwardmove += forward; - cmd->sidemove += side; - - // special buttons - if (sendpause) - { - sendpause = false; - cmd->buttons = BT_SPECIAL | BTS_PAUSE; - } - - if (sendsave) - { - sendsave = false; - cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<angleturn + carry; - - // round angleturn to the nearest 256 unit boundary - // for recording demos with single byte values for turn - - cmd->angleturn = (desired_angleturn + 128) & 0xff00; - - // Carry forward the error from the reduced resolution to the - // next tic, so that successive small movements can accumulate. - - carry = desired_angleturn - cmd->angleturn; - } -} - - -// -// G_DoLoadLevel -// -void G_DoLoadLevel (void) -{ - int i; - - // haleyjd 10/03/10: [STRIFE] This is not done here. - //skyflatnum = R_FlatNumForName(DEH_String(SKYFLATNAME)); - - levelstarttic = gametic; // for time calculation - - if (wipegamestate == GS_LEVEL) - wipegamestate = -1; // force a wipe - - gamestate = GS_LEVEL; - - for (i=0 ; iinventorycursor > 0) - player->inventorycursor--; - } - else if (i == joybinvright) - { - if (player->inventorycursor < player->numinventory - 1) - player->inventorycursor++; - } - } - - joybuttons[i] = button_on; - } -} - -static void SetMouseButtons(unsigned int buttons_mask) -{ - int i; - - for (i=0; itype == ev_keydown - && ev->data1 == key_spy && (singledemo || !gameskill) ) // [STRIFE]: o_O - { - // spy mode - do - { - displayplayer++; - if (displayplayer == MAXPLAYERS) - displayplayer = 0; - } while (!playeringame[displayplayer] && displayplayer != consoleplayer); - return true; - } - - // any other key pops up menu if in demos - if (gameaction == ga_nothing && !singledemo && - (demoplayback || gamestate == GS_DEMOSCREEN) - ) - { - if (ev->type == ev_keydown || - (ev->type == ev_mouse && ev->data1) || - (ev->type == ev_joystick && ev->data1) ) - { - if(devparm && ev->data1 == 'g') - D_PageTicker(); // [STRIFE]: wat? o_O - else - M_StartControlPanel (); - return true; - } - return false; - } - - if (gamestate == GS_LEVEL) - { -#if 0 - if (devparm && ev->type == ev_keydown && ev->data1 == ';') - { - G_DeathMatchSpawnPlayer (0); - return true; - } -#endif - if (HU_Responder (ev)) - return true; // chat ate the event - if (ST_Responder (ev)) - return true; // status window ate it - if (AM_Responder (ev)) - return true; // automap ate it - } - - if (gamestate == GS_FINALE) - { - if (F_Responder (ev)) - return true; // finale ate the event - } - - if (testcontrols && ev->type == ev_mouse) - { - // If we are invoked by setup to test the controls, save the - // mouse speed so that we can display it on-screen. - // Perform a low pass filter on this so that the thermometer - // appears to move smoothly. - - testcontrols_mousespeed = abs(ev->data2); - } - - // If the next/previous weapon keys are pressed, set the next_weapon - // variable to change weapons when the next ticcmd is generated. - - if (ev->type == ev_keydown && ev->data1 == key_prevweapon) - { - next_weapon = -1; - } - else if (ev->type == ev_keydown && ev->data1 == key_nextweapon) - { - next_weapon = 1; - } - - switch (ev->type) - { - case ev_keydown: - if (ev->data1 == key_pause) - { - sendpause = true; - } - else if (ev->data1 data1] = true; - } - - return true; // eat key down events - - case ev_keyup: - if (ev->data1 data1] = false; - return false; // always let key up events filter down - - case ev_mouse: - SetMouseButtons(ev->data1); - mousex = ev->data2*(mouseSensitivity+5)/10; - mousey = ev->data3*(mouseSensitivity+5)/10; - return true; // eat events - - case ev_joystick: - SetJoyButtons(ev->data1); - joyxmove = ev->data2; - joyymove = ev->data3; - joystrafemove = ev->data4; - joylook = ev->data5; - return true; // eat events - - default: - break; - } - - return false; -} - -// -// G_Ticker -// Make ticcmd_ts for the players. -// -void G_Ticker (void) -{ - int i; - int buf; - ticcmd_t* cmd; - - // do player reborns if needed - for (i=0 ; iforwardmove > TURBOTHRESHOLD) - { - turbodetected[i] = true; - } - - if ((gametic & 31) == 0 - && ((gametic >> 5) % MAXPLAYERS) == i - && turbodetected[i]) - { - static char turbomessage[80]; - M_snprintf(turbomessage, sizeof(turbomessage), - "%s is turbo!", player_names[i]); - players[consoleplayer].message = turbomessage; - turbodetected[i] = false; - } - - if (netgame && !netdemo && !(gametic%ticdup) ) - { - if (gametic > BACKUPTICS - && consistancy[i][buf] != cmd->consistancy) - { - I_Error ("consistency failure (%i should be %i)", - cmd->consistancy, consistancy[i][buf]); - } - if (players[i].mo) - consistancy[i][buf] = players[i].mo->x; - else - consistancy[i][buf] = rndindex; - } - } - } - - // check for special buttons - for (i=0 ; i>BTS_SAVESHIFT; - gameaction = ga_savegame; - break; - } - } - } - } - - // Have we just finished displaying an intermission screen? - // haleyjd 08/23/10: [STRIFE] No intermission. - /* - if (oldgamestate == GS_INTERMISSION && gamestate != GS_INTERMISSION) - { - WI_End(); - } - */ - - oldgamestate = gamestate; - - // do main actions - switch (gamestate) - { - case GS_LEVEL: - P_Ticker (); - ST_Ticker (); - AM_Ticker (); - HU_Ticker (); - break; - - // haleyjd 08/23/10: [STRIFE] No intermission. - /* - case GS_INTERMISSION: - WI_Ticker (); - break; - */ - case GS_UNKNOWN: // STRIFE-TODO: What is this? is it ever used?? - F_WaitTicker(); - break; - - case GS_FINALE: - F_Ticker (); - break; - - case GS_DEMOSCREEN: - D_PageTicker (); - break; - } -} - - -// -// PLAYER STRUCTURE FUNCTIONS -// also see P_SpawnPlayer in P_Things -// - -// -// G_InitPlayer -// Called at the start. -// Called by the game initialization functions. -// -// [STRIFE] No such function. -/* -void G_InitPlayer (int player) -{ - player_t* p; - - // set up the saved info - p = &players[player]; - - // clear everything else to defaults - G_PlayerReborn (player); - -} -*/ - - -// -// G_PlayerFinishLevel -// Can when a player completes a level. -// -// [STRIFE] No such function. The equivalent to this logic was moved into -// G_DoCompleted. -/* -void G_PlayerFinishLevel (int player) -{ - player_t* p; - - p = &players[player]; - - memset (p->powers, 0, sizeof (p->powers)); - memset (p->cards, 0, sizeof (p->cards)); - p->mo->flags &= ~MF_SHADOW; // cancel invisibility - p->extralight = 0; // cancel gun flashes - p->fixedcolormap = 0; // cancel ir gogles - p->damagecount = 0; // no palette changes - p->bonuscount = 0; -} -*/ - -// -// G_PlayerReborn -// Called after a player dies -// almost everything is cleared and initialized -// -// [STRIFE] Small changes for allegiance, inventory, health auto-use, and -// mission objective. -// -void G_PlayerReborn (int player) -{ - player_t* p; - int i; - int frags[MAXPLAYERS]; - int killcount; - int allegiance; - - killcount = players[player].killcount; - allegiance = players[player].allegiance; // [STRIFE] - - memcpy(frags,players[player].frags,sizeof(frags)); - - p = &players[player]; - memset (p, 0, sizeof(*p)); - - memcpy(p->frags, frags, sizeof(p->frags)); - - p->usedown = true; // don't do anything immediately - p->attackdown = true; - p->inventorydown = true; // villsa [STRIFE] - p->playerstate = PST_LIVE; - p->health = deh_initial_health; // Use dehacked value - p->readyweapon = wp_fist; // villsa [STRIFE] default to fists - p->pendingweapon = wp_fist; // villsa [STRIFE] default to fists - p->weaponowned[wp_fist] = true; // villsa [STRIFE] default to fists - p->cheats |= CF_AUTOHEALTH; // villsa [STRIFE] - p->killcount = killcount; - p->allegiance = allegiance; // villsa [STRIFE] - p->centerview = true; // villsa [STRIFE] - - for(i = 0; i < NUMAMMO; i++) - p->maxammo[i] = maxammo[i]; - - // [STRIFE] clear inventory - for(i = 0; i < 32; i++) - p->inventory[i].type = NUMMOBJTYPES; - - // villsa [STRIFE]: Default objective - M_StringCopy(mission_objective, DEH_String("Find help"), - OBJECTIVE_LEN); -} - -// -// G_CheckSpot -// Returns false if the player cannot be respawned -// at the given mapthing_t spot -// because something is occupying it -// -// [STRIFE] Changed to eliminate body queue and an odd error message was added. -// -void P_SpawnPlayer (mapthing_t* mthing); - -boolean -G_CheckSpot -( int playernum, - mapthing_t* mthing ) -{ - fixed_t x; - fixed_t y; - subsector_t* ss; - unsigned an; - mobj_t* mo; - int i; - - if (!players[playernum].mo) - { - // [STRIFE] weird error message added here: - if(leveltime > 0) - players[playernum].message = DEH_String("you didn't have a body!"); - - // first spawn of level, before corpses - for (i=0 ; ix == mthing->x << FRACBITS - && players[i].mo->y == mthing->y << FRACBITS) - return false; - return true; - } - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - if (!P_CheckPosition (players[playernum].mo, x, y) ) - return false; - - // flush an old corpse if needed - // [STRIFE] player corpses remove themselves after a short time, so - // evidently this wasn't needed. - /* - if (bodyqueslot >= BODYQUESIZE) - P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); - bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; - bodyqueslot++; - */ - - // spawn a teleport fog - ss = R_PointInSubsector (x,y); - an = ( ANG45 * (((unsigned int) mthing->angle)/45) ) >> ANGLETOFINESHIFT; - - mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] - , ss->sector->floorheight - , MT_TFOG); - - if (players[consoleplayer].viewz != 1) - S_StartSound (mo, sfx_telept); // don't start sound on first frame - - return true; -} - - -// -// G_DeathMatchSpawnPlayer -// Spawns a player at one of the random death match spots -// called at level load and each death -// -// [STRIFE]: Modified exit message to match binary. -// -void G_DeathMatchSpawnPlayer (int playernum) -{ - int i,j; - int selections; - - selections = deathmatch_p - deathmatchstarts; - if (selections < 4) - I_Error ("Only %i deathmatch spots, at least 4 required!", selections); - - for (j=0 ; j<20 ; j++) - { - i = P_Random() % selections; - if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) - { - deathmatchstarts[i].type = playernum+1; - P_SpawnPlayer (&deathmatchstarts[i]); - return; - } - } - - // no good spot, so the player will probably get stuck - P_SpawnPlayer (&playerstarts[playernum]); -} - -// -// G_LoadPath -// -// haleyjd 20101003: [STRIFE] New function -// Sets loadpath based on the map and "savepathtemp" -// -void G_LoadPath(int map) -{ - char mapbuf[33]; - - memset(mapbuf, 0, sizeof(mapbuf)); - M_snprintf(mapbuf, sizeof(mapbuf), "%d", map); - - // haleyjd: free if already set, and use M_SafeFilePath - if(loadpath) - Z_Free(loadpath); - loadpath = M_SafeFilePath(savepathtemp, mapbuf); -} - -// -// G_DoReborn -// -void G_DoReborn (int playernum) -{ - int i; - - if (!netgame) - { - // reload the level from scratch - // [STRIFE] Reborn level load - G_LoadPath(gamemap); - gameaction = ga_loadgame; - } - else - { - // respawn at the start - - // first dissasociate the corpse - // [STRIFE] Checks for NULL first - if(players[playernum].mo) - players[playernum].mo->player = NULL; - - // spawn at random spot if in death match - if (deathmatch) - { - G_DeathMatchSpawnPlayer (playernum); - return; - } - - if (G_CheckSpot (playernum, &playerstarts[playernum]) ) - { - P_SpawnPlayer (&playerstarts[playernum]); - return; - } - - // try to spawn at one of the other players spots - for (i=0 ; i Abandoned Front Base - map = 30; - if(map == 7) // Castle -> New Front Base - map = 10; - } - - // no rifting in deathmatch games - if(deathmatch) - spot = 0; - - riftangle = angle; - riftdest = spot; - destmap = map; -} - -// -// G_Exit2 -// -// haleyjd 20101003: [STRIFE] New function. -// No xrefs to this, doesn't seem to be used. Could have gotten inlined -// somewhere but I haven't seen it. -// -void G_Exit2(int dest, angle_t angle) -{ - riftdest = dest; - gameaction = ga_completed; - riftangle = angle; - destmap = gamemap; -} - -// -// G_ExitLevel -// -// haleyjd 20100824: [STRIFE]: -// * Default to next map in numeric order; init destmap and riftdest. -// -void G_ExitLevel (int dest) -{ - if(dest == 0) - dest = gamemap + 1; - destmap = dest; - riftdest = 0; - gameaction = ga_completed; -} - -/* -// haleyjd 20100823: [STRIFE] No secret exits in Strife. -// Here's for the german edition. -void G_SecretExitLevel (void) -{ - // IF NO WOLF3D LEVELS, NO SECRET EXIT! - if ( (gamemode == commercial) - && (W_CheckNumForName("map31")<0)) - secretexit = false; - else - secretexit = true; - gameaction = ga_completed; -} -*/ - -// -// G_StartFinale -// -// haleyjd 20100921: [STRIFE] New function. -// This replaced G_SecretExitLevel in Strife. I don't know that it's actually -// used anywhere in the game, but it *is* usable in mods via linetype 124, -// W1 Start Finale. -// -void G_StartFinale(void) -{ - gameaction = ga_victory; -} - -// -// G_DoCompleted -// -// haleyjd 20100823: [STRIFE]: -// * Removed G_PlayerFinishLevel and just sets some powerup states. -// * Removed Chex, as not relevant to Strife. -// * Removed DOOM level transfer logic -// * Removed intermission code. -// * Added setting gameaction to ga_worlddone. -// -void G_DoCompleted (void) -{ - int i; - - // deal with powerup states - for(i = 0; i < MAXPLAYERS; i++) - { - if(playeringame[i]) - { - // [STRIFE] restore pw_allmap power from mapstate cache - if(destmap < 40) - players[i].powers[pw_allmap] = players[i].mapstate[destmap]; - - // Shadowarmor doesn't persist between maps in netgames - if(netgame) - players[i].powers[pw_invisibility] = 0; - } - } - - stonecold = false; // villsa [STRIFE] - - if (automapactive) - AM_Stop (); - - // [STRIFE] HUB SAVE - if(!deathmatch) - G_DoSaveGame(savepathtemp); - - gameaction = ga_worlddone; -} - - -// haleyjd 20100824: [STRIFE] No secret exits. -/* -// -// G_WorldDone -// -void G_WorldDone (void) -{ - gameaction = ga_worlddone; - - if (secretexit) - players[consoleplayer].didsecret = true; - - if ( gamemode == commercial ) - { - switch (gamemap) - { - case 15: - case 31: - if (!secretexit) - break; - case 6: - case 11: - case 20: - case 30: - F_StartFinale (); - break; - } - } -} -*/ - -// -// G_RiftPlayer -// -// haleyjd 20100824: [STRIFE] New function -// Teleports the player to the appropriate rift spot. -// -void G_RiftPlayer(void) -{ - if(riftdest) - { - P_TeleportMove(players[0].mo, - riftSpots[riftdest - 1].x << FRACBITS, - riftSpots[riftdest - 1].y << FRACBITS); - players[0].mo->angle = riftangle; - players[0].mo->health = players[0].health; - } -} - -// -// G_RiftCheat -// -// haleyjd 20100824: [STRIFE] New function -// Called from the cheat code to jump to a rift spot. -// -boolean G_RiftCheat(int riftSpotNum) -{ - return P_TeleportMove(players[0].mo, - riftSpots[riftSpotNum - 1].x << FRACBITS, - riftSpots[riftSpotNum - 1].y << FRACBITS); -} - -// -// G_DoWorldDone -// -// haleyjd 20100824: [STRIFE] Added destmap -> gamemap set. -// -void G_DoWorldDone (void) -{ - int temp_leveltime = leveltime; - boolean temp_shadow = false; - boolean temp_mvis = false; - - gamestate = GS_LEVEL; - gamemap = destmap; - - // [STRIFE] HUB LOAD - G_LoadPath(destmap); - if (!deathmatch) - { - // Remember Shadowarmor across hub loads - if(players[0].mo->flags & MF_SHADOW) - temp_shadow = true; - if(players[0].mo->flags & MF_MVIS) - temp_mvis = true; - } - G_DoLoadGame(false); - - // [STRIFE] leveltime carries over between maps - leveltime = temp_leveltime; - - if(!deathmatch) - { - // [STRIFE]: transfer saved powerups - players[0].mo->flags &= ~(MF_SHADOW|MF_MVIS); - if(temp_shadow) - players[0].mo->flags |= MF_SHADOW; - if(temp_mvis) - players[0].mo->flags |= MF_MVIS; - - // [STRIFE] HUB SAVE - G_RiftPlayer(); - G_DoSaveGame(savepathtemp); - M_SaveMisObj(savepathtemp); - } - - gameaction = ga_nothing; - viewactive = true; -} - -// -// G_DoWorldDone2 -// -// haleyjd 20101003: [STRIFE] New function. No xrefs; unused. -// -void G_DoWorldDone2(void) -{ - gamestate = GS_LEVEL; - gameaction = ga_nothing; - viewactive = true; -} - -// -// G_ReadCurrent -// -// haleyjd 20101003: [STRIFE] New function. -// Reads the "CURRENT" file from the given path and then sets it to -// gamemap. -// -void G_ReadCurrent(const char *path) -{ - char *temppath = NULL; - byte *buffer = NULL; - - temppath = M_SafeFilePath(path, "\\current"); - - if(M_ReadFile(temppath, &buffer) <= 0) - gameaction = ga_newgame; - else - { - // haleyjd 20110211: do endian-correct read - gamemap = (((int)buffer[0]) | - ((int)buffer[1] << 8) | - ((int)buffer[2] << 16) | - ((int)buffer[3] << 24)); - gameaction = ga_loadgame; - Z_Free(buffer); - } - - Z_Free(temppath); - - G_LoadPath(gamemap); -} - -// -// G_InitFromSavegame -// Can be called by the startup code or the menu task. -// - -char savename[256]; - -// [STRIFE]: No such function. -/* -void G_LoadGame (char* name) -{ - M_StringCopy(savename, name, sizeof(savename)); - gameaction = ga_loadgame; -} -*/ - -// haleyjd 20100928: [STRIFE] VERSIONSIZE == 8 -#define VERSIONSIZE 8 - -void G_DoLoadGame (boolean userload) -{ - int savedleveltime; - - gameaction = ga_nothing; - - save_stream = M_fopen(loadpath, "rb"); - - // [STRIFE] If the file does not exist, G_DoLoadLevel is called. - if (save_stream == NULL) - { - G_DoLoadLevel(); - return; - } - - savegame_error = false; - - if (!P_ReadSaveGameHeader()) - { - fclose(save_stream); - return; - } - - // haleyjd: A comment would be good here, fraggle... - // Evidently this is a Choco-ism, necessitated by reading the savegame - // header *before* calling G_DoLoadLevel. - savedleveltime = leveltime; - - // load a base level - - // STRIFE-TODO: ???? - if(userload) - G_InitNew(gameskill, gamemap); - else - G_DoLoadLevel(); - - leveltime = savedleveltime; - - // dearchive all the modifications - // [STRIFE] some portions of player_t are not overwritten when loading - // between hub levels - P_UnArchivePlayers (userload); - P_UnArchiveWorld (); - P_UnArchiveThinkers (); - P_UnArchiveSpecials (); - - if (!P_ReadSaveGameEOF()) - I_Error ("Bad savegame"); - - fclose(save_stream); - - if (setsizeneeded) - R_ExecuteSetViewSize (); - - // draw the pattern into the back screen - R_FillBackScreen (); -} - -// -// G_WriteSaveName -// -// haleyjd 20101003: [STRIFE] New function -// -// Writes the character name to the NAME file. -// -boolean G_WriteSaveName(int slot, const char *charname) -{ - //char savedir[16]; - char *tmpname; - boolean retval; - - savegameslot = slot; - - // haleyjd: removed special -cdrom treatment, as I believe it is taken - // care of automatically via using Choco's savegamedir setting. - - // haleyjd: free previous path, if any, and allocate new one using - // M_SafeFilePath routine, which isn't limited to 128 characters. - if(savepathtemp) - Z_Free(savepathtemp); - savepathtemp = M_SafeFilePath(savegamedir, "strfsav6.ssg"); - - // haleyjd: as above. - if(savepath) - Z_Free(savepath); - savepath = M_SafeFilePath(savegamedir, M_MakeStrifeSaveDir(savegameslot, "")); - - // haleyjd: memset full character_name for safety - memset(character_name, 0, CHARACTER_NAME_LEN); - M_StringCopy(character_name, charname, sizeof(character_name)); - - // haleyjd: use M_SafeFilePath - tmpname = M_SafeFilePath(savepathtemp, "name"); - - // Write the "name" file under the directory - retval = M_WriteFile(tmpname, character_name, 32); - - Z_Free(tmpname); - - return retval; -} - -// -// G_SaveGame -// Called by the menu task. -// Description is a 24 byte text string -// -// [STRIFE] No such function, at least in v1.2 -// STRIFE-TODO: Does this make a comeback in v1.31? -/* -void -G_SaveGame -( int slot, - char* description ) -{ - savegameslot = slot; - M_StringCopy(savedescription, description, sizeof(savedescription)); - sendsave = true; -} -*/ - -void G_DoSaveGame (char *path) -{ - char *current_path; - char *savegame_file; - char *temp_savegame_file; - byte gamemapbytes[4]; - char gamemapstr[33]; - - temp_savegame_file = P_TempSaveGameFile(); - - // [STRIFE] custom save file path logic - memset(gamemapstr, 0, sizeof(gamemapstr)); - M_snprintf(gamemapstr, sizeof(gamemapstr), "%d", gamemap); - savegame_file = M_SafeFilePath(path, gamemapstr); - - // [STRIFE] write the "current" file, which tells which hub map - // the save slot is currently on. - current_path = M_SafeFilePath(path, "current"); - // haleyjd: endian-agnostic IO - gamemapbytes[0] = (byte)( gamemap & 0xff); - gamemapbytes[1] = (byte)((gamemap >> 8) & 0xff); - gamemapbytes[2] = (byte)((gamemap >> 16) & 0xff); - gamemapbytes[3] = (byte)((gamemap >> 24) & 0xff); - M_WriteFile(current_path, gamemapbytes, 4); - Z_Free(current_path); - - // Open the savegame file for writing. We write to a temporary file - // and then rename it at the end if it was successfully written. - // This prevents an existing savegame from being overwritten by - // a corrupted one, or if a savegame buffer overrun occurs. - - save_stream = M_fopen(temp_savegame_file, "wb"); - - if (save_stream == NULL) - { - return; - } - - savegame_error = false; - - P_WriteSaveGameHeader(savedescription); - - P_ArchivePlayers (); - P_ArchiveWorld (); - P_ArchiveThinkers (); - P_ArchiveSpecials (); - - P_WriteSaveGameEOF(); - - // Enforce the same savegame size limit as in Vanilla Doom, - // except if the vanilla_savegame_limit setting is turned off. - // [STRIFE]: Verified subject to same limit. - - if (vanilla_savegame_limit && ftell(save_stream) > SAVEGAMESIZE) - { - I_Error ("Savegame buffer overrun"); - } - - // Finish up, close the savegame file. - - fclose(save_stream); - - // Now rename the temporary savegame file to the actual savegame - // file, overwriting the old savegame if there was one there. - - M_remove(savegame_file); - M_rename(temp_savegame_file, savegame_file); - - // haleyjd: free the savegame_file path - Z_Free(savegame_file); - - gameaction = ga_nothing; - //M_StringCopy(savedescription, "", sizeof(savedescription)); - - // [STRIFE]: custom message logic - if(!strcmp(path, savepath)) - { - M_snprintf(savename, sizeof(savename), "%s saved.", character_name); - players[consoleplayer].message = savename; - } - - // draw the pattern into the back screen - R_FillBackScreen (); -} - - -// -skill_t d_skill; -//int d_episode; [STRIFE] No such thing as episodes in Strife -int d_map; - -// -// G_DeferedInitNew -// -// Can be called by the startup code or the menu task, -// consoleplayer, displayplayer, playeringame[] should be set. -// -// haleyjd 20100922: [STRIFE] Removed episode parameter -// -void G_DeferedInitNew(skill_t skill, int map) -{ - d_skill = skill; - d_map = map; - gameaction = ga_newgame; -} - -// -// G_DoNewGame -// -// [STRIFE] Code added to turn off the stonecold effect. -// Someone also removed the nomonsters reset... -// -void G_DoNewGame (void) -{ - demoplayback = false; - netdemo = false; - netgame = false; - deathmatch = false; - playeringame[1] = playeringame[2] = playeringame[3] = 0; - respawnparm = false; - fastparm = false; - stonecold = false; // villsa [STRIFE] - //nomonsters = false; [STRIFE] not set here!?! - consoleplayer = 0; - G_InitNew (d_skill, d_map); - gameaction = ga_nothing; -} - -// -// G_InitNew -// -// haleyjd 20100824: [STRIFE]: -// * Added riftdest initialization -// * Removed episode parameter -// -void -G_InitNew -( skill_t skill, - int map ) -{ - const char *skytexturename; - int i; - - if (paused) - { - paused = false; - S_ResumeSound (); - } - - if (skill > sk_nightmare) - skill = sk_nightmare; - - // [STRIFE] Removed episode nonsense and gamemap clipping - - M_ClearRandom (); - - if (skill == sk_nightmare || respawnparm ) - respawnmonsters = true; - else - respawnmonsters = false; - - // [STRIFE] Strife skill level mobjinfo/states tweaking - // BUG: None of this code runs properly when loading save games, so - // basically it's impossible to play any skill level properly unless - // you never quit and reload from the command line. - if(!skill && gameskill) - { - // Setting to Baby skill... make things easier. - - // Acolytes walk, attack, and feel pain slower - for(i = S_AGRD_13; i <= S_AGRD_23; i++) - states[i].tics *= 2; - - // Reavers attack slower - for(i = S_ROB1_10; i <= S_ROB1_15; i++) - states[i].tics *= 2; - - // Turrets attack slower - for(i = S_TURT_02; i <= S_TURT_03; i++) - states[i].tics *= 2; - - // Crusaders attack and feel pain slower - for(i = S_ROB2_09; i <= S_ROB2_19; i++) - states[i].tics *= 2; - - // Stalkers think, walk, and attack slower - for(i = S_SPID_03; i <= S_SPID_10; i++) - states[i].tics *= 2; - - // The Bishop's homing missiles are faster (what?? BUG?) - mobjinfo[MT_SEEKMISSILE].speed *= 2; - } - if(skill && !gameskill) - { - // Setting a higher skill when previously on baby... make things normal - - // Acolytes - for(i = S_AGRD_13; i <= S_AGRD_23; i++) - states[i].tics >>= 1; - - // Reavers - for(i = S_ROB1_10; i <= S_ROB1_15; i++) - states[i].tics >>= 1; - - // Turrets - for(i = S_TURT_02; i <= S_TURT_03; i++) - states[i].tics >>= 1; - - // Crusaders - for(i = S_ROB2_09; i <= S_ROB2_19; i++) - states[i].tics >>= 1; - - // Stalkers - for(i = S_SPID_03; i <= S_SPID_10; i++) - states[i].tics >>= 1; - - // The Bishop's homing missiles - again, seemingly backward. - mobjinfo[MT_SEEKMISSILE].speed >>= 1; - } - if(fastparm || (skill == sk_nightmare && skill != gameskill)) - { - // BLOODBATH! Make some things super-aggressive. - - // Acolytes walk, attack, and feel pain twice as fast - // (This makes just getting out of the first room almost impossible) - for(i = S_AGRD_13; i <= S_AGRD_23; i++) - states[i].tics >>= 1; - - // Bishop's homing missiles again get SLOWER and not faster o_O - mobjinfo[MT_SEEKMISSILE].speed >>= 1; - } - else if(skill != sk_nightmare && gameskill == sk_nightmare) - { - // Setting back to an ordinary skill after being on Bloodbath? - // Put stuff back to normal. - - // Acolytes - for(i = S_AGRD_13; i <= S_AGRD_23; i++) - states[i].tics *= 2; - - // Bishop's homing missiles - mobjinfo[MT_SEEKMISSILE].speed *= 2; - } - - // force players to be initialized upon first level load - for (i=0 ; i= 9 && gamemap < 32) - skytexturename = "skymnt01"; - else - skytexturename = "skymnt02"; - - skytexturename = DEH_String(skytexturename); - - skytexture = R_TextureNumForName(skytexturename); - - // [STRIFE] HUBS - G_LoadPath(gamemap); - G_DoLoadLevel(); -} - - -// -// DEMO RECORDING -// -#define DEMOMARKER 0x80 - -// -// G_ReadDemoTiccmd -// -// [STRIFE] Modified for Strife ticcmd_t -// -void G_ReadDemoTiccmd (ticcmd_t* cmd) -{ - if (*demo_p == DEMOMARKER) - { - // end of demo data stream - G_CheckDemoStatus (); - return; - } - cmd->forwardmove = ((signed char)*demo_p++); - cmd->sidemove = ((signed char)*demo_p++); - cmd->angleturn = ((unsigned char) *demo_p++)<<8; - cmd->buttons = (unsigned char)*demo_p++; - cmd->buttons2 = (unsigned char)*demo_p++; // [STRIFE] - cmd->inventory = (int)*demo_p++; // [STRIFE] -} - -// Increase the size of the demo buffer to allow unlimited demos - -static void IncreaseDemoBuffer(void) -{ - int current_length; - byte *new_demobuffer; - byte *new_demop; - int new_length; - - // Find the current size - - current_length = demoend - demobuffer; - - // Generate a new buffer twice the size - new_length = current_length * 2; - - new_demobuffer = Z_Malloc(new_length, PU_STATIC, 0); - new_demop = new_demobuffer + (demo_p - demobuffer); - - // Copy over the old data - - memcpy(new_demobuffer, demobuffer, current_length); - - // Free the old buffer and point the demo pointers at the new buffer. - - Z_Free(demobuffer); - - demobuffer = new_demobuffer; - demo_p = new_demop; - demoend = demobuffer + new_length; -} - -// -// G_WriteDemoTiccmd -// -// [STRIFE] Modified for Strife ticcmd_t. -// -void G_WriteDemoTiccmd (ticcmd_t* cmd) -{ - byte *demo_start; - - if (gamekeydown[key_demo_quit]) // press q to end demo recording - G_CheckDemoStatus (); - - demo_start = demo_p; - - *demo_p++ = cmd->forwardmove; - *demo_p++ = cmd->sidemove; - *demo_p++ = cmd->angleturn >> 8; - *demo_p++ = cmd->buttons; - *demo_p++ = cmd->buttons2; // [STRIFE] - *demo_p++ = (byte)(cmd->inventory & 0xff); // [STRIFE] - - // reset demo pointer back - demo_p = demo_start; - - if (demo_p > demoend - 16) - { - if (vanilla_demo_limit) - { - // no more space - G_CheckDemoStatus (); - return; - } - else - { - // Vanilla demo limit disabled: unlimited - // demo lengths! - - IncreaseDemoBuffer(); - } - } - - G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same -} - - - -// -// G_RecordDemo -// -// [STRIFE] Verified unmodified -// -void G_RecordDemo (const char* name) -{ - size_t demoname_size; - int i; - int maxsize; - - usergame = false; - demoname_size = strlen(name) + 5; - demoname = Z_Malloc(demoname_size, PU_STATIC, NULL); - M_snprintf(demoname, demoname_size, "%s.lmp", name); - maxsize = 0x20000; - - //! - // @arg - // @category demo - // @vanilla - // - // Specify the demo buffer size (KiB) - // - - i = M_CheckParmWithArgs("-maxdemo", 1); - if (i) - maxsize = atoi(myargv[i+1])*1024; - demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL); - demoend = demobuffer + maxsize; - - demorecording = true; -} - - -void G_BeginRecording (void) -{ - int i; - - // - // @category demo - // - // Record a high resolution "Doom 1.91" demo. - // - - // STRIFE-TODO: if somebody makes a "Strife Plus", we could add this. - /* - longtics = M_CheckParm("-longtics") != 0; - */ - longtics = false; - - // If not recording a longtics demo, record in low res - lowres_turn = !longtics; - - demo_p = demobuffer; - - // Save the right version code for this demo - *demo_p++ = STRIFE_VERSION; - - *demo_p++ = gameskill; - //*demo_p++ = gameepisode; [STRIFE] Doesn't have episodes. - *demo_p++ = gamemap; - *demo_p++ = deathmatch; - *demo_p++ = respawnparm; - *demo_p++ = fastparm; - *demo_p++ = nomonsters; - *demo_p++ = consoleplayer; - - for (i=0 ; i - -#include "doomdef.h" -#include "doomkeys.h" - -#include "v_video.h" -#include "i_swap.h" - -#include "d_main.h" -#include "hu_lib.h" -#include "r_local.h" -#include "r_draw.h" -#include "hu_stuff.h" // [STRIFE] - -#include "doomstat.h" - -// boolean : whether the screen is always erased -#define noterased viewwindowx - - -// -// HUlib_drawYellowText -// -// haleyjd 20100918: [STRIFE] New function. -// -void HUlib_drawYellowText(int x, int y, const char *text) -{ - int start_x = x; - const char *rover = text; - char c; - - while((c = *rover++)) - { - if(c == '\n') - { - x = start_x; - y += 12; - continue; - } - - // haleyjd 20110213: found MORE code ignored/misinterpreted by Hex-Rays: - // Underscores are replaced by spaces. - if(c == '_') - c = ' '; - else if (c == ' ' && x == start_x) // skip spaces at the start of a line - continue; - - c = toupper(c) - HU_FONTSTART; - - if(c >= 0 && c < HU_FONTSIZE) - { - patch_t *patch = yfont[(int) c]; - int width = SHORT(patch->width); - - if(x + width <= (SCREENWIDTH - 20)) - { - // haleyjd: STRIFE-TODO: bit different than the exe... for now - if(!D_PatchClipCallback(patch, x + SHORT(patch->leftoffset), - y + SHORT(patch->topoffset))) - return; - V_DrawPatchDirect(x, y, patch); - x = x + width; - } - else - { - x = start_x; - --rover; - y += 12; - } - } - else - { - x += 4; - } - } -} - -// -// HUlib_init -// -// [STRIFE] Verified unmodified. -// -void HUlib_init(void) -{ -} - -// -// HUlib_clearTextLine -// -// [STRIFE] Verified unmodified. -// -void HUlib_clearTextLine(hu_textline_t* t) -{ - t->len = 0; - t->l[0] = 0; - t->needsupdate = true; -} - -// -// HUlib_initTextLine -// -// [STRIFE] Verified unmodified -// -void -HUlib_initTextLine -( hu_textline_t* t, - int x, - int y, - patch_t** f, - int sc ) -{ - t->x = x; - t->y = y; - t->f = f; - t->sc = sc; - HUlib_clearTextLine(t); -} - -// -// HUlib_addCharToTextLine -// -// [STRIFE] Verified unmodified. -// -boolean -HUlib_addCharToTextLine -( hu_textline_t* t, - char ch ) -{ - if (t->len == HU_MAXLINELENGTH) - return false; - else - { - t->l[t->len++] = ch; - t->l[t->len] = 0; - t->needsupdate = 4; - return true; - } -} - -// -// HUlib_delCharFromTextLine -// -// [STRIFE] Verified unmodified. -// -boolean HUlib_delCharFromTextLine(hu_textline_t* t) -{ - if (!t->len) return false; - else - { - t->l[--t->len] = 0; - t->needsupdate = 4; - return true; - } -} - -// -// HUlib_drawTextLine -// -// haleyjd 09/18/10: [STRIFE] Modified to not draw underscores in text. -// -void -HUlib_drawTextLine -( hu_textline_t* l, - boolean drawcursor ) -{ - int i; - int w; - int x; - unsigned char c; - - // draw the new stuff - x = l->x; - - for(i = 0; i < l->len; i++) - { - c = toupper(l->l[i]); - if (c != ' ' && c >= l->sc && c < '_') // [STRIFE]: Underscores excluded - { - w = SHORT(l->f[c - l->sc]->width); - if (x+w > SCREENWIDTH) - break; - V_DrawPatchDirect(x, l->y, l->f[c - l->sc]); - x += w; - } - else - { - x += 4; - if (x >= SCREENWIDTH) - break; - } - } - - // draw the cursor if requested - if (drawcursor - && x + SHORT(l->f['_' - l->sc]->width) <= SCREENWIDTH) - { - V_DrawPatchDirect(x, l->y, l->f['_' - l->sc]); - } -} - -// -// HUlib_eraseTextLine -// -// sorta called by HU_Erase and just better darn get things straight -// -// [STRIFE] Verified unmodified. -// -void HUlib_eraseTextLine(hu_textline_t* l) -{ - int lh; - int y; - int yoffset; - - // Only erases when NOT in automap and the screen is reduced, - // and the text must either need updating or refreshing - // (because of a recent change back from the automap) - - if (!automapactive && - viewwindowx && l->needsupdate) - { - lh = SHORT(l->f[0]->height) + 1; - for (y=l->y,yoffset=y*SCREENWIDTH ; yy+lh ; y++,yoffset+=SCREENWIDTH) - { - if (y < viewwindowy || y >= viewwindowy + viewheight) - R_VideoErase(yoffset, SCREENWIDTH); // erase entire line - else - { - R_VideoErase(yoffset, viewwindowx); // erase left border - R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); - // erase right border - } - } - } - - if (l->needsupdate) l->needsupdate--; -} - -// -// HUlib_initSText -// -// [STRIFE] Verified unmodified. -// -void -HUlib_initSText -( hu_stext_t* s, - int x, - int y, - int h, - patch_t** font, - int startchar, - boolean* on ) -{ - int i; - - s->h = h; - s->on = on; - s->laston = true; - s->cl = 0; - for (i=0;il[i], - x, y - i*(SHORT(font[0]->height)+1), - font, startchar); - } -} - -// -// HUlib_addLineToSText -// -// [STRIFE] Verified unmodified. -// -void HUlib_addLineToSText(hu_stext_t* s) -{ - int i; - - // add a clear line - if (++s->cl == s->h) - s->cl = 0; - HUlib_clearTextLine(&s->l[s->cl]); - - // everything needs updating - for (i=0 ; ih ; i++) - s->l[i].needsupdate = 4; -} - -// -// HUlib_addMessageToSText -// -// [STRIFE] Verified unmodified. -// -void -HUlib_addMessageToSText -( hu_stext_t* s, - const char *prefix, - const char *msg ) -{ - HUlib_addLineToSText(s); - if (prefix) - while (*prefix) - HUlib_addCharToTextLine(&s->l[s->cl], *(prefix++)); - - while (*msg) - HUlib_addCharToTextLine(&s->l[s->cl], *(msg++)); -} - -// -// HUlib_drawSText -// -// [STRIFE] Verified unmodified. -// -void HUlib_drawSText(hu_stext_t* s) -{ - int i, idx; - hu_textline_t *l; - - if (!*s->on) - return; // if not on, don't draw - - // draw everything - for (i=0 ; ih ; i++) - { - idx = s->cl - i; - if (idx < 0) - idx += s->h; // handle queue of lines - - l = &s->l[idx]; - - // need a decision made here on whether to skip the draw - HUlib_drawTextLine(l, false); // no cursor, please - } -} - -// -// HUlib_eraseSText -// -// [STRIFE] Verified unmodified. -// -void HUlib_eraseSText(hu_stext_t* s) -{ - int i; - - for (i=0 ; ih ; i++) - { - if (s->laston && !*s->on) - s->l[i].needsupdate = 4; - HUlib_eraseTextLine(&s->l[i]); - } - s->laston = *s->on; -} - -// -// HUlib_initIText -// -// [STRIFE] Verified unmodified. -// -void -HUlib_initIText -( hu_itext_t* it, - int x, - int y, - patch_t** font, - int startchar, - boolean* on ) -{ - it->lm = 0; // default left margin is start of text - it->on = on; - it->laston = true; - HUlib_initTextLine(&it->l, x, y, font, startchar); -} - - -// The following deletion routines adhere to the left margin restriction -// [STRIFE] Verified unmodified. -void HUlib_delCharFromIText(hu_itext_t* it) -{ - if (it->l.len != it->lm) - HUlib_delCharFromTextLine(&it->l); -} - -// [STRIFE] Verified unmodified. -void HUlib_eraseLineFromIText(hu_itext_t* it) -{ - while (it->lm != it->l.len) - HUlib_delCharFromTextLine(&it->l); -} - -// Resets left margin as well -// [STRIFE] Verified unmodified. -void HUlib_resetIText(hu_itext_t* it) -{ - it->lm = 0; - HUlib_clearTextLine(&it->l); -} - -// -// HUlib_addPrefixToIText -// -// [STRIFE] Verified unmodified. -// -void -HUlib_addPrefixToIText -( hu_itext_t* it, - char* str ) -{ - while (*str) - HUlib_addCharToTextLine(&it->l, *(str++)); - it->lm = it->l.len; -} - -// wrapper function for handling general keyed input. -// returns true if it ate the key -// [STRIFE] Verified unmodified. -boolean -HUlib_keyInIText -( hu_itext_t* it, - unsigned char ch ) -{ - ch = toupper(ch); - - if (ch >= ' ' && ch <= '_') - HUlib_addCharToTextLine(&it->l, (char) ch); - else if (ch == KEY_BACKSPACE) - HUlib_delCharFromIText(it); - else if (ch != KEY_ENTER) - return false; // did not eat key - - return true; // ate the key -} - -// -// HUlib_drawIText -// -// [STRIFE] Verified unmodified. -// -void HUlib_drawIText(hu_itext_t* it) -{ - hu_textline_t *l = &it->l; - - if (!*it->on) - return; - HUlib_drawTextLine(l, true); // draw the line w/ cursor -} - -// -// HUlib_eraseIText -// -// [STRIFE] Verified unmodified. -// -void HUlib_eraseIText(hu_itext_t* it) -{ - if (it->laston && !*it->on) - it->l.needsupdate = 4; - HUlib_eraseTextLine(&it->l); - it->laston = *it->on; -} - diff --git a/games/NXDoom/src/strife/hu_lib.h b/games/NXDoom/src/strife/hu_lib.h deleted file mode 100644 index 5639860d1f5..00000000000 --- a/games/NXDoom/src/strife/hu_lib.h +++ /dev/null @@ -1,185 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// - -#ifndef __HULIB__ -#define __HULIB__ - -// We are referring to patches. -#include "r_defs.h" - -// font stuff -#define HU_CHARERASE KEY_BACKSPACE - -#define HU_MAXLINES 4 -#define HU_MAXLINELENGTH 80 - -// -// Typedefs of widgets -// - -// Text Line widget -// (parent of Scrolling Text and Input Text widgets) -typedef struct -{ - // left-justified position of scrolling text window - int x; - int y; - - patch_t** f; // font - int sc; // start character - char l[HU_MAXLINELENGTH+1]; // line of text - int len; // current line length - - // whether this line needs to be udpated - int needsupdate; - -} hu_textline_t; - - - -// Scrolling Text window widget -// (child of Text Line widget) -typedef struct -{ - hu_textline_t l[HU_MAXLINES]; // text lines to draw - int h; // height in lines - int cl; // current line number - - // pointer to boolean stating whether to update window - boolean* on; - boolean laston; // last value of *->on. - -} hu_stext_t; - - - -// Input Text Line widget -// (child of Text Line widget) -typedef struct -{ - hu_textline_t l; // text line to input on - - // left margin past which I am not to delete characters - int lm; - - // pointer to boolean stating whether to update window - boolean* on; - boolean laston; // last value of *->on; - -} hu_itext_t; - - -// -// Widget creation, access, and update routines -// - -// initializes heads-up widget library -void HUlib_init(void); - -// -// textline code -// - -// clear a line of text -void HUlib_clearTextLine(hu_textline_t *t); - -void HUlib_initTextLine(hu_textline_t *t, int x, int y, patch_t **f, int sc); - -// returns success -boolean HUlib_addCharToTextLine(hu_textline_t *t, char ch); - -// returns success -boolean HUlib_delCharFromTextLine(hu_textline_t *t); - -// draws tline -void HUlib_drawTextLine(hu_textline_t *l, boolean drawcursor); - -// erases text line -void HUlib_eraseTextLine(hu_textline_t *l); - -// villsa [STRIFE] -void HUlib_drawYellowText(int x, int y, const char *text); - - -// -// Scrolling Text window widget routines -// - -// ? -void -HUlib_initSText -( hu_stext_t* s, - int x, - int y, - int h, - patch_t** font, - int startchar, - boolean* on ); - -// add a new line -void HUlib_addLineToSText(hu_stext_t* s); - -// ? -void -HUlib_addMessageToSText -( hu_stext_t* s, - const char *prefix, - const char *msg ); - -// draws stext -void HUlib_drawSText(hu_stext_t* s); - -// erases all stext lines -void HUlib_eraseSText(hu_stext_t* s); - -// Input Text Line widget routines -void -HUlib_initIText -( hu_itext_t* it, - int x, - int y, - patch_t** font, - int startchar, - boolean* on ); - -// enforces left margin -void HUlib_delCharFromIText(hu_itext_t* it); - -// enforces left margin -void HUlib_eraseLineFromIText(hu_itext_t* it); - -// resets line and left margin -void HUlib_resetIText(hu_itext_t* it); - -// left of left-margin -void -HUlib_addPrefixToIText -( hu_itext_t* it, - char* str ); - -// whether eaten -boolean -HUlib_keyInIText -( hu_itext_t* it, - unsigned char ch ); - -void HUlib_drawIText(hu_itext_t* it); - -// erases all itext lines -void HUlib_eraseIText(hu_itext_t* it); - -#endif diff --git a/games/NXDoom/src/strife/hu_stuff.c b/games/NXDoom/src/strife/hu_stuff.c deleted file mode 100644 index 34f8ff457d8..00000000000 --- a/games/NXDoom/src/strife/hu_stuff.c +++ /dev/null @@ -1,687 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Heads-up displays -// - - -#include - -#include "doomdef.h" -#include "doomkeys.h" - -#include "z_zone.h" - -#include "deh_main.h" -#include "i_input.h" -#include "i_swap.h" -#include "i_video.h" - -#include "d_main.h" -#include "hu_stuff.h" -#include "hu_lib.h" -#include "m_controls.h" -#include "m_misc.h" -#include "w_wad.h" - -#include "s_sound.h" - -#include "doomstat.h" - -// Data. -#include "dstrings.h" -#include "sounds.h" - -// -// Locally used constants, shortcuts. -// -#define HU_TITLE (mapnames[gamemap-1]) -#define HU_TITLEHEIGHT 1 -#define HU_TITLEX 0 - -// haleyjd 09/01/10: [STRIFE] 167 -> 160 to move up level name -#define HU_TITLEY (160 - SHORT(hu_font[0]->height)) - -#define HU_INPUTTOGGLE 't' -#define HU_INPUTX HU_MSGX -#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1)) -#define HU_INPUTWIDTH 64 -#define HU_INPUTHEIGHT 1 - -char *chat_macros[10]; - -// villsa [STRIFE] -char player_names[8][16] = -{ - "1: ", - "2: ", - "3: ", - "4: ", - "5: ", - "6: ", - "7: ", - "8: " -}; - -char chat_char; // remove later. -static player_t* plr; -patch_t* hu_font[HU_FONTSIZE]; -patch_t* yfont[HU_FONTSIZE]; // haleyjd 09/18/10: [STRIFE] -static hu_textline_t w_title; -boolean chat_on; -static hu_itext_t w_chat; -static boolean always_off = false; -static char chat_dest[MAXPLAYERS]; -static hu_itext_t w_inputbuffer[MAXPLAYERS]; - -static boolean message_on; -boolean message_dontfuckwithme; -static boolean message_nottobefuckedwith; - -static hu_stext_t w_message; -static int message_counter; - - -static boolean headsupactive = false; - -// haleyjd 20130915 [STRIFE]: true if setting nickname -static boolean hu_setting_name = false; - -// -// Builtin map names. -// The actual names can be found in DStrings.h. -// - -// haleyjd 08/31/10: [STRIFE] Changed for Strife level names. -// List of names for levels. - -const char *mapnames[] = -{ - // Strife map names - - // First "episode" - Quest to destroy the Order's Castle - HUSTR_1, - HUSTR_2, - HUSTR_3, - HUSTR_4, - HUSTR_5, - HUSTR_6, - HUSTR_7, - HUSTR_8, - HUSTR_9, - - // Second "episode" - Kill the Bishop and Make a Choice - HUSTR_10, - HUSTR_11, - HUSTR_12, - HUSTR_13, - HUSTR_14, - HUSTR_15, - HUSTR_16, - HUSTR_17, - HUSTR_18, - HUSTR_19, - - // Third "episode" - Shut down Factory, kill Loremaster and Entity - HUSTR_20, - HUSTR_21, - HUSTR_22, - HUSTR_23, - HUSTR_24, - HUSTR_25, - HUSTR_26, - HUSTR_27, - HUSTR_28, - HUSTR_29, - - // "Secret" levels - Abandoned Base and Training Facility - HUSTR_30, - HUSTR_31, - - // Demo version maps - HUSTR_32, - HUSTR_33, - HUSTR_34 -}; - -// -// HU_Init -// -// haleyjd 09/18/10: [STRIFE] -// * Modified to load yfont along with hu_font. -// -void HU_Init(void) -{ - int i; - int j; - char buffer[9]; - - // load the heads-up font - j = HU_FONTSTART; - for (i=0;i This is definitely not the best that Rogue had to offer. Markov. -// -// Fastcall Registers: edx ebx -// Temp Registers: esi edi -static void HU_addMessage(const char *prefix, const char *message) -{ - char c; // eax - int width = 0; // edx - const char *rover1; // ebx (in first loop) - const char *rover2; // ecx (in second loop) - char *bufptr; // ebx (in second loop) - char buffer[HU_MAXLINELENGTH+2]; // esp+52h - - // Loop 1: Total up width of prefix. - rover1 = prefix; - if(rover1) - { - while((c = *rover1)) - { - c = toupper(c) - HU_FONTSTART; - ++rover1; - - if(c < 0 || c >= HU_FONTSIZE) - width += 4; - else - width += SHORT(hu_font[(int) c]->width); - } - } - - // Loop 2: Copy as much of message into buffer as will fit on screen - bufptr = buffer; - rover2 = message; - while((c = *rover2)) - { - if((c == ' ' || c == '-') && width > 285) - break; - - *bufptr = c; - ++bufptr; // BUG: No check for overflow. - ++rover2; - c = toupper(c); - - if(c == ' ' || c < '!' || c >= '_') - width += 4; - else - { - c -= HU_FONTSTART; - width += SHORT(hu_font[(int) c]->width); - } - } - - // Too big to fit? - // BUG: doesn't consider by how much it's over. - if(width > 320) - { - // backup a char... hell if I know why. - --bufptr; - --rover2; - } - - // rover2 is not at the end? - if((c = *rover2)) - { - // if not ON a space... - if(c != ' ') - { - // back up both pointers til one is found. - // BUG: no check against LHS of buffer. Hurr! - while(*bufptr != ' ') - { - --bufptr; - --rover2; - } - } - } - - *bufptr = '\0'; - - // Add two message lines. - HUlib_addMessageToSText(&w_message, prefix, buffer); - HUlib_addMessageToSText(&w_message, NULL, rover2); -} - -// -// HU_Ticker -// -// haleyjd 09/18/10: [STRIFE] Changes to split up message into two lines, -// and support for player names (STRIFE-TODO: unfinished!) -// -void HU_Ticker(void) -{ - int i, rc; - char c; - //char *prefix; STRIFE-TODO - - // tick down message counter if message is up - if (message_counter && !--message_counter) - { - message_on = false; - message_nottobefuckedwith = false; - } - - // haleyjd 20110219: [STRIFE] this condition was removed - //if (showMessages || message_dontfuckwithme) - //{ - // display message if necessary - if ((plr->message && !message_nottobefuckedwith) - || (plr->message && message_dontfuckwithme)) - { - //HUlib_addMessageToSText(&w_message, 0, plr->message); - HU_addMessage(NULL, plr->message); // haleyjd [STRIFE] - plr->message = 0; - message_on = true; - message_counter = HU_MSGTIMEOUT; - message_nottobefuckedwith = message_dontfuckwithme; - message_dontfuckwithme = 0; - } - //} // else message_on = false; - - // check for incoming chat characters - if (netgame) - { - for (i=0 ; idata1 == KEY_RSHIFT) - { - return false; - } - else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT) - { - altdown = ev->type == ev_keydown; - return false; - } - - if (ev->type != ev_keydown) - return false; - - if (!chat_on) - { - if (ev->data1 == key_message_refresh) - { - message_on = true; - message_counter = HU_MSGTIMEOUT; - eatkey = true; - } - else if (netgame && ev->data2 == key_multi_msg) - { - StartChatInput(); - eatkey = true; - HUlib_resetIText(&w_chat); - HU_queueChatChar(HU_BROADCAST); - } - // [STRIFE]: You cannot go straight to chatting with a particular - // player from here... you must press 't' first. See below. - } - else - { - c = ev->data3; - // send a macro - if (altdown) - { - c = c - '0'; - if (c > 9) - return false; - // fprintf(stderr, "got here\n"); - macromessage = chat_macros[c]; - - // kill last message with a '\n' - HU_queueChatChar(KEY_ENTER); // DEBUG!!! - - // send the macro message - while (*macromessage) - HU_queueChatChar(*macromessage++); - HU_queueChatChar(KEY_ENTER); - - // leave chat mode and notify that it was sent - StopChatInput(); - M_StringCopy(lastmessage, chat_macros[c], sizeof(lastmessage)); - plr->message = lastmessage; - eatkey = true; - } - else - { - if(w_chat.l.len) // [STRIFE]: past first char of chat? - { - eatkey = HUlib_keyInIText(&w_chat, c); - if (eatkey) - HU_queueChatChar(c); - } - else - { - // [STRIFE]: check for player-specific message; - // slightly different than vanilla, to allow keys to be customized - for(i = 0; i < MAXPLAYERS; i++) - { - if (ev->data1 == key_multi_msgplayer[i]) - break; - } - if(i < MAXPLAYERS) - { - // talking to self? - if(i == consoleplayer) - { - num_nobrainers++; - if (num_nobrainers < 3) - plr->message = DEH_String(HUSTR_TALKTOSELF1); - else if (num_nobrainers < 6) - plr->message = DEH_String(HUSTR_TALKTOSELF2); - else if (num_nobrainers < 9) - plr->message = DEH_String(HUSTR_TALKTOSELF3); - else if (num_nobrainers < 32) - plr->message = DEH_String(HUSTR_TALKTOSELF4); - else - plr->message = DEH_String(HUSTR_TALKTOSELF5); - } - else - { - eatkey = true; - HU_queueChatChar(i+1); - DEH_snprintf(lastmessage, sizeof(lastmessage), - "Talking to: %c", '1' + i); - plr->message = lastmessage; - } - } - else if(c == '$') // [STRIFE]: name changing - { - eatkey = true; - HU_queueChatChar(HU_CHANGENAME); - M_StringCopy(lastmessage, DEH_String("Changing Name:"), - sizeof(lastmessage)); - plr->message = lastmessage; - hu_setting_name = true; - } - else - { - eatkey = HUlib_keyInIText(&w_chat, c); - if (eatkey) - HU_queueChatChar(c); - } - } - - if (c == KEY_ENTER) - { - StopChatInput(); - if (w_chat.l.len) - { - // [STRIFE]: name setting - if(hu_setting_name) - { - DEH_snprintf(lastmessage, sizeof(lastmessage), - "%s now %.13s", player_names[consoleplayer], - w_chat.l.l); - // haleyjd 20141024: missing name set for local client - DEH_snprintf(player_names[consoleplayer], - sizeof(player_names[consoleplayer]), - "%.13s: ", w_chat.l.l); - hu_setting_name = false; - } - else - { - M_StringCopy(lastmessage, w_chat.l.l, - sizeof(lastmessage)); - } - plr->message = lastmessage; - } - } - else if (c == KEY_ESCAPE) - { - StopChatInput(); - } - } - } - - return eatkey; -} diff --git a/games/NXDoom/src/strife/hu_stuff.h b/games/NXDoom/src/strife/hu_stuff.h deleted file mode 100644 index 2140d830ec2..00000000000 --- a/games/NXDoom/src/strife/hu_stuff.h +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Head up display -// - -#ifndef __HU_STUFF_H__ -#define __HU_STUFF_H__ - -#include "d_event.h" -#include "v_patch.h" - -// -// Globally visible constants. -// -#define HU_FONTSTART '!' // the first font characters -#define HU_FONTEND '_' // the last font characters - -// Calculate # of glyphs in font. -#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) - -#define HU_BROADCAST 9 // haleyjd [STRIFE] Changed 5 -> 9 -#define HU_CHANGENAME 10 // haleyjd [STRIFE] Special command - -#define HU_MSGX 0 -#define HU_MSGY (SHORT(hu_font[0]->height) + 1) // [STRIFE]: DOOM bug fix -#define HU_MSGWIDTH 64 // in characters -#define HU_MSGHEIGHT 2 // in lines - -#define HU_MSGTIMEOUT (8*TICRATE) // haleyjd [STRIFE] Doubled message timeout - - -// -// HEADS UP TEXT -// - -void HU_Init(void); -void HU_Start(void); - -boolean HU_Responder(event_t* ev); - -void HU_Ticker(void); -void HU_Drawer(void); -char HU_dequeueChatChar(void); -void HU_Erase(void); - -extern char *chat_macros[10]; -extern char player_names[8][16]; // villsa [STRIFE] - -// haleyjd [STRIFE] externalized: -extern const char *mapnames[]; - -// [STRIFE] -extern patch_t* yfont[HU_FONTSIZE]; // haleyjd 09/18/10: [STRIFE] -extern patch_t *hu_font[HU_FONTSIZE]; - -extern boolean message_dontfuckwithme; - -extern boolean chat_on; -extern boolean sendsave; - - -#endif - diff --git a/games/NXDoom/src/strife/info.c b/games/NXDoom/src/strife/info.c deleted file mode 100644 index 7976299b861..00000000000 --- a/games/NXDoom/src/strife/info.c +++ /dev/null @@ -1,11041 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Thing frame/state LUT, -// generated by multigen utilitiy. -// This one is the original DOOM version, preserved. -// - -#include -#include - -// Data. -#include "sounds.h" -#include "m_fixed.h" - -#include "info.h" - -#include "p_mobj.h" - -// villsa [STRIFE] -const char *sprnames[NUMSPRITES+1] = -{ - "PLAY", "PNCH", "WAVE", "RBPY", "TRGT", "XBOW", "MMIS", "RIFG", - "RIFF", "FLMT", "FLMF", "BLST", "BLSF", "GREN", "GREF", "SIGH", - "SIGF", "POW1", "POW2", "POW3", "ZAP1", "SPRY", "BLOD", "PUFY", - "SHT1", "SHT2", "GRIN", "GRAP", "UBAM", "BNG2", "BNG4", "BNG3", - "FLBE", "XPRK", "OCLW", "CCLW", "TEND", "MICR", "MISS", "AROW", - "ARWP", "TORP", "THIT", "TWAV", "MISL", "TFOG", "IFOG", "SHRD", - "RGIB", "MRYS", "MRNO", "MRST", "MRLK", "MRBD", "MRPN", "MRGT", - "BURN", "DISR", "PEAS", "GIBS", "AGRD", "ARMR", "SACR", "TNK1", - "TNK2", "TNK3", "TNK4", "TNK5", "TNK6", "NEAL", "BEGR", "HMN1", - "LEDR", "LEAD", "ROB1", "PGRD", "ROB2", "MLDR", "ORCL", "PRST", - "PDED", "ALN1", "AL1P", "NODE", "MTHD", "MNAM", "MNAL", "MDTH", - "NEST", "PODD", "ZAP6", "ZOT3", "ZAP7", "ZOT1", "ZAP5", "ZOT2", - "SEWR", "SPID", "ROB3", "RBB3", "PRGR", "BASE", "FRBL", "KLAX", - "TURT", "BALL", "PSTN", "SECR", "TARG", "RING", "EARS", "COMM", - "BOOM", "RATT", "HOGN", "DEAD", "SBAN", "BOTR", "HATR", "TOPR", - "COUP", "BUBB", "BUBF", "BUBC", "ASPR", "SPDL", "TOKN", "OTOK", - "HELT", "GUNT", "FULL", "MEAT", "JUNK", "FFOT", "DIE1", "BEAC", - "ARM1", "ARM2", "BARW", "BART", "LAMP", "LANT", "BARL", "BOWL", - "BRAZ", "TRCH", "LTRH", "LMPC", "LOGS", "TRHO", "WATR", "MUGG", - "FUSL", "CRD1", "CRD2", "TPAS", "KY1G", "KY2S", "KY3B", "HAND", - "CRYS", "PRIS", "PWR1", "PWR2", "PWR3", "ORAC", "GYID", "FUBR", - "WARE", "RCRY", "BCRY", "CHAP", "TUNL", "BLTK", "SECK", "MINE", - "REBL", "PROC", "ANKH", "GOID", "STMP", "MDKT", "COIN", "CRED", - "SACK", "CHST", "SHD1", "MASK", "UNIF", "OFIC", "PMAP", "PMUP", - "BLIT", "BBOX", "MSSL", "ROKT", "BRY1", "CPAC", "PQRL", "XQRL", - "GRN1", "GRN2", "BKPK", "RELC", "RIFL", "FLAM", "BFLM", "MMSL", - "TRPD", "GRND", "CBOW", "SIGL", "LITE", "CNDL", "CLBR", "LITS", - "LITB", "LITG", "ROK1", "ROK2", "ROK3", "ROK4", "LOGG", "RUB1", - "RUB2", "RUB3", "RUB4", "RUB5", "RUB6", "RUB7", "RUB8", "CHAN", - "STAT", "DSTA", "CRAB", "CAGE", "TREE", "TRE1", "BUSH", "SHRB", - "STAK", "BAR1", "VASE", "STOL", "POT1", "TUB1", "ANVL", "TLMP", - "TRAY", "APOW", "AFED", "DRIP", "CDRP", "SPLH", "WTFT", "HERT", - "TELP", "MONI", "STEL", "STLA", "STLE", "HUGE", "STLG", NULL -}; - - -// Doesn't work with g++, needs actionf_p1 -// villsa [STRIFE] -void A_Look(); -void A_RandomWalk(); -void A_FriendLook(); -void A_Listen(); -void A_Chase(); -void A_FaceTarget(); -void A_PeasantPunch(); -void A_ReaverAttack(); -void A_BulletAttack(); -void A_CheckTargetVisible(); -void A_SentinelAttack(); -void A_StalkerThink(); -void A_StalkerSetLook(); -void A_StalkerDrop(); -void A_StalkerScratch(); -void A_FloatWeave(); -void A_RobotMelee(); -void A_TemplarMauler(); -void A_CrusaderAttack(); -void A_CrusaderLeft(); -void A_CrusaderRight(); -void A_CheckTargetVisible2(); -void A_InqFlyCheck(); -void A_InqGrenade(); -void A_InqTakeOff(); -void A_InqFly(); -void A_FireSigilWeapon(); -void A_ProgrammerAttack(); -void A_Sigil_A_Action(); -void A_SpectreEAttack(); -void A_SpectreCAttack(); -void A_AlertSpectreC(); -void A_Sigil_E_Action(); -void A_SigilTrail(); -void A_SpectreDAttack(); -void A_FireSigilEOffshoot(); -void A_ShadowOff(); -void A_ModifyVisibility(); -void A_ShadowOn(); -void A_SetTLOptions(); -void A_BossMeleeAtk(); -void A_BishopAttack(); -void A_FireHookShot(); -void A_FireChainShot(); -void A_MissileSmoke(); -void A_SpawnSparkPuff(); -void A_Tracer(); -void A_ProgrammerMelee(); -void A_Scream(); -void A_XScream(); -void A_Pain(); -void A_PeasantCrash(); -void A_Fall(); -void A_HideZombie(); -void A_MerchantPain(); -void A_ProgrammerDie(); -void A_InqTossArm(); -void A_SpawnSpectreB(); -void A_SpawnSpectreD(); -void A_SpawnSpectreE(); -void A_SpawnEntity(); -void A_EntityDeath(); -void A_SpawnZombie(); -void A_ZombieInSpecialSector(); -void A_CrystalExplode(); -void A_QuestMsg(); -void A_ExtraLightOff(); -void A_CrystalRadiusAtk(); -void A_DeathExplode5(); -void A_DeathExplode1(); -void A_DeathExplode2(); -void A_DeathExplode3(); -void A_RaiseAlarm(); -void A_MissileTick(); -void A_SpawnGrenadeFire(); -void A_NodeChunk(); -void A_HeadChunk(); -void A_BurnSpread(); -void A_AcolyteSpecial(); -void A_BossDeath(); -void A_InqChase(); -void A_StalkerChase(); -void A_PlayerScream(); -void A_TeleportBeacon(); -void A_BodyParts(); -void A_ClaxonBlare(); -void A_ActiveSound(); -void A_ClearSoundTarget(); -void A_DropBurnFlesh(); -void A_FlameDeath(); -void A_ClearForceField(); -void A_WeaponReady(); -void A_ReFire(); -void A_CheckReload(); -void A_Lower(); -void A_Raise(); -void A_GunFlash(); -void A_Punch(); -void A_FireFlameThrower(); -void A_FireMissile(); -void A_FireMauler2(); -void A_FireGrenade(); -void A_FireElectricBolt(); -void A_FirePoisonBolt(); -void A_FireRifle(); -void A_FireMauler1(); -void A_SigilSound(); -void A_FireSigil(); -void A_GunFlashThinker(); -void A_Light0(); -void A_Light1(); -void A_Light2(); -void A_SigilShock(); -void A_TorpedoExplode(); -void A_MaulerSound(); - -// villsa [STRIFE] -state_t states[NUMSTATES] = -{ - -/*S_NULL*/ { SPR_PLAY, 0, -1, { NULL }, S_NULL }, //00 -/*S_PNCH_00*/ { SPR_PNCH, 0, 0, { A_Light0 }, S_NULL }, //01 -/*S_WAVE_00*/ { SPR_WAVE, 32768, 3, { NULL }, S_WAVE_01 }, //02 -/*S_WAVE_01*/ { SPR_WAVE, 32769, 3, { NULL }, S_WAVE_02 }, //03 -/*S_WAVE_02*/ { SPR_WAVE, 32770, 3, { NULL }, S_WAVE_03 }, //04 -/*S_WAVE_03*/ { SPR_WAVE, 32771, 3, { NULL }, S_WAVE_00 }, //05 -/*S_RBPY_00*/ { SPR_RBPY, 32768, 3, { NULL }, S_RBPY_01 }, //06 -/*S_RBPY_01*/ { SPR_RBPY, 32769, 3, { NULL }, S_RBPY_02 }, //07 -/*S_RBPY_02*/ { SPR_RBPY, 32770, 3, { NULL }, S_RBPY_03 }, //08 -/*S_RBPY_03*/ { SPR_RBPY, 32771, 3, { NULL }, S_RBPY_00 }, //09 -/*S_TRGT_00*/ { SPR_TRGT, 0, -1, { NULL }, S_NULL }, //10 -/*S_TRGT_01*/ { SPR_TRGT, 1, -1, { NULL }, S_NULL }, //11 -/*S_TRGT_02*/ { SPR_TRGT, 2, -1, { NULL }, S_NULL }, //12 -/*S_PNCH_01*/ { SPR_PNCH, 0, 1, { A_WeaponReady }, S_PNCH_01 }, //13 -/*S_PNCH_02*/ { SPR_PNCH, 0, 1, { A_Lower }, S_PNCH_02 }, //14 -/*S_PNCH_03*/ { SPR_PNCH, 0, 1, { A_Raise }, S_PNCH_03 }, //15 -/*S_PNCH_04*/ { SPR_PNCH, 1, 4, { NULL }, S_PNCH_05 }, //16 -/*S_PNCH_05*/ { SPR_PNCH, 2, 4, { A_Punch }, S_PNCH_06 }, //17 -/*S_PNCH_06*/ { SPR_PNCH, 3, 5, { NULL }, S_PNCH_07 }, //18 -/*S_PNCH_07*/ { SPR_PNCH, 2, 4, { NULL }, S_PNCH_08 }, //19 -/*S_PNCH_08*/ { SPR_PNCH, 1, 5, { A_ReFire }, S_PNCH_01 }, //20 -/*S_XBOW_00*/ { SPR_XBOW, 0, 1, { A_WeaponReady }, S_XBOW_00 }, //21 -/*S_XBOW_01*/ { SPR_XBOW, 0, 1, { A_Lower }, S_XBOW_01 }, //22 -/*S_XBOW_02*/ { SPR_XBOW, 0, 1, { A_Raise }, S_XBOW_02 }, //23 -/*S_XBOW_03*/ { SPR_XBOW, 0, 3, { A_GunFlashThinker }, S_XBOW_04 }, //24 -/*S_XBOW_04*/ { SPR_XBOW, 1, 6, { A_FireElectricBolt }, S_XBOW_05 }, //25 -/*S_XBOW_05*/ { SPR_XBOW, 2, 4, { NULL }, S_XBOW_06 }, //26 -/*S_XBOW_06*/ { SPR_XBOW, 3, 6, { NULL }, S_XBOW_07 }, //27 -/*S_XBOW_07*/ { SPR_XBOW, 4, 3, { NULL }, S_XBOW_08 }, //28 -/*S_XBOW_08*/ { SPR_XBOW, 5, 5, { NULL }, S_XBOW_09 }, //29 -/*S_XBOW_09*/ { SPR_XBOW, 6, 5, { A_CheckReload }, S_XBOW_00 }, //30 -/*S_XBOW_10*/ { SPR_XBOW, 10, 5, { NULL }, S_XBOW_11 }, //31 -/*S_XBOW_11*/ { SPR_XBOW, 11, 5, { NULL }, S_XBOW_12 }, //32 -/*S_XBOW_12*/ { SPR_XBOW, 12, 5, { NULL }, S_XBOW_10 }, //33 -/*S_XBOW_13*/ { SPR_XBOW, 7, 1, { A_WeaponReady }, S_XBOW_13 }, //34 -/*S_XBOW_14*/ { SPR_XBOW, 7, 1, { A_Lower }, S_XBOW_14 }, //35 -/*S_XBOW_15*/ { SPR_XBOW, 7, 1, { A_Raise }, S_XBOW_15 }, //36 -/*S_XBOW_16*/ { SPR_XBOW, 7, 3, { NULL }, S_XBOW_17 }, //37 -/*S_XBOW_17*/ { SPR_XBOW, 1, 6, { A_FirePoisonBolt }, S_XBOW_18 }, //38 -/*S_XBOW_18*/ { SPR_XBOW, 2, 4, { NULL }, S_XBOW_19 }, //39 -/*S_XBOW_19*/ { SPR_XBOW, 3, 6, { NULL }, S_XBOW_20 }, //40 -/*S_XBOW_20*/ { SPR_XBOW, 4, 3, { NULL }, S_XBOW_21 }, //41 -/*S_XBOW_21*/ { SPR_XBOW, 8, 5, { NULL }, S_XBOW_22 }, //42 -/*S_XBOW_22*/ { SPR_XBOW, 9, 5, { A_CheckReload }, S_XBOW_13 }, //43 -/*S_MMIS_00*/ { SPR_MMIS, 0, 1, { A_WeaponReady }, S_MMIS_00 }, //44 -/*S_MMIS_01*/ { SPR_MMIS, 0, 1, { A_Lower }, S_MMIS_01 }, //45 -/*S_MMIS_02*/ { SPR_MMIS, 0, 1, { A_Raise }, S_MMIS_02 }, //46 -/*S_MMIS_03*/ { SPR_MMIS, 0, 4, { A_FireMissile }, S_MMIS_04 }, //47 -/*S_MMIS_04*/ { SPR_MMIS, 1, 4, { A_Light1 }, S_MMIS_05 }, //48 -/*S_MMIS_05*/ { SPR_MMIS, 32770, 5, { NULL }, S_MMIS_06 }, //49 -/*S_MMIS_06*/ { SPR_MMIS, 32771, 2, { A_Light2 }, S_MMIS_07 }, //50 -/*S_MMIS_07*/ { SPR_MMIS, 32772, 2, { NULL }, S_MMIS_08 }, //51 -/*S_MMIS_08*/ { SPR_MMIS, 32773, 2, { A_Light0 }, S_MMIS_09 }, //52 -/*S_MMIS_09*/ { SPR_MMIS, 5, 0, { A_ReFire }, S_MMIS_00 }, //53 -/*S_RIFG_00*/ { SPR_RIFG, 0, 1, { A_WeaponReady }, S_RIFG_00 }, //54 -/*S_RIFG_01*/ { SPR_RIFG, 1, 1, { A_Lower }, S_RIFG_01 }, //55 -/*S_RIFG_02*/ { SPR_RIFG, 0, 1, { A_Raise }, S_RIFG_02 }, //56 -/*S_RIFF_00*/ { SPR_RIFF, 0, 3, { A_FireRifle }, S_RIFF_01 }, //57 -/*S_RIFF_01*/ { SPR_RIFF, 1, 3, { A_FireRifle }, S_RIFG_03 }, //58 -/*S_RIFG_03*/ { SPR_RIFG, 3, 3, { A_FireRifle }, S_RIFG_04 }, //59 -/*S_RIFG_04*/ { SPR_RIFG, 2, 0, { A_ReFire }, S_RIFG_05 }, //60 -/*S_RIFG_05*/ { SPR_RIFG, 1, 2, { NULL }, S_RIFG_00 }, //61 -/*S_FLMT_00*/ { SPR_FLMT, 0, 3, { A_WeaponReady }, S_FLMT_01 }, //62 -/*S_FLMT_01*/ { SPR_FLMT, 1, 3, { A_WeaponReady }, S_FLMT_00 }, //63 -/*S_FLMT_02*/ { SPR_FLMT, 0, 1, { A_Lower }, S_FLMT_02 }, //64 -/*S_FLMT_03*/ { SPR_FLMT, 0, 1, { A_Raise }, S_FLMT_03 }, //65 -/*S_FLMF_00*/ { SPR_FLMF, 0, 2, { A_FireFlameThrower }, S_FLMF_01 }, //66 -/*S_FLMF_01*/ { SPR_FLMF, 1, 3, { A_ReFire }, S_FLMT_00 }, //67 -/*S_BLST_00*/ { SPR_BLST, 5, 6, { A_WeaponReady }, S_BLST_01 }, //68 -/*S_BLST_01*/ { SPR_BLST, 6, 6, { A_WeaponReady }, S_BLST_02 }, //69 -/*S_BLST_02*/ { SPR_BLST, 7, 6, { A_WeaponReady }, S_BLST_03 }, //70 -/*S_BLST_03*/ { SPR_BLST, 0, 6, { A_WeaponReady }, S_BLST_00 }, //71 -/*S_BLST_04*/ { SPR_BLST, 0, 1, { A_Lower }, S_BLST_04 }, //72 -/*S_BLST_05*/ { SPR_BLST, 0, 1, { A_Raise }, S_BLST_05 }, //73 -/*S_BLSF_00*/ { SPR_BLSF, 32768, 5, { A_FireMauler1 }, S_BLST_06 }, //74 -/*S_BLST_06*/ { SPR_BLST, 32769, 3, { A_Light1 }, S_BLST_07 }, //75 -/*S_BLST_07*/ { SPR_BLST, 2, 2, { A_Light2 }, S_BLST_08 }, //76 -/*S_BLST_08*/ { SPR_BLST, 3, 2, { NULL }, S_BLST_09 }, //77 -/*S_BLST_09*/ { SPR_BLST, 4, 2, { NULL }, S_BLST_10 }, //78 -/*S_BLST_10*/ { SPR_BLST, 0, 7, { A_Light0 }, S_BLST_11 }, //79 -/*S_BLST_11*/ { SPR_BLST, 7, 7, { NULL }, S_BLST_12 }, //80 -/*S_BLST_12*/ { SPR_BLST, 6, 7, { A_CheckReload }, S_BLST_00 }, //81 -/*S_BLST_13*/ { SPR_BLST, 8, 7, { A_WeaponReady }, S_BLST_14 }, //82 -/*S_BLST_14*/ { SPR_BLST, 9, 7, { A_WeaponReady }, S_BLST_15 }, //83 -/*S_BLST_15*/ { SPR_BLST, 10, 7, { A_WeaponReady }, S_BLST_16 }, //84 -/*S_BLST_16*/ { SPR_BLST, 11, 7, { A_WeaponReady }, S_BLST_13 }, //85 -/*S_BLST_17*/ { SPR_BLST, 8, 1, { A_Lower }, S_BLST_17 }, //86 -/*S_BLST_18*/ { SPR_BLST, 8, 1, { A_Raise }, S_BLST_18 }, //87 -/*S_BLST_19*/ { SPR_BLST, 8, 20, { A_MaulerSound }, S_BLST_20 }, //88 -/*S_BLST_20*/ { SPR_BLST, 9, 10, { A_Light1 }, S_BLSF_01 }, //89 -/*S_BLSF_01*/ { SPR_BLSF, 32768, 10, { A_FireMauler2 }, S_BLST_21 }, //90 -/*S_BLST_21*/ { SPR_BLST, 32769, 3, { A_Light2 }, S_BLST_22 }, //91 -/*S_BLST_22*/ { SPR_BLST, 2, 2, { NULL }, S_BLST_23 }, //92 -/*S_BLST_23*/ { SPR_BLST, 3, 2, { A_Light0 }, S_BLST_24 }, //93 -/*S_BLST_24*/ { SPR_BLST, 4, 2, { A_ReFire }, S_BLST_13 }, //94 -/*S_GREN_00*/ { SPR_GREN, 0, 1, { A_WeaponReady }, S_GREN_00 }, //95 -/*S_GREN_01*/ { SPR_GREN, 0, 1, { A_Lower }, S_GREN_01 }, //96 -/*S_GREN_02*/ { SPR_GREN, 0, 1, { A_Raise }, S_GREN_02 }, //97 -/*S_GREN_03*/ { SPR_GREN, 0, 5, { A_FireGrenade }, S_GREN_04 }, //98 -/*S_GREN_04*/ { SPR_GREN, 1, 10, { NULL }, S_GREN_05 }, //99 -/*S_GREN_05*/ { SPR_GREN, 0, 5, { A_FireGrenade }, S_GREN_06 }, //100 -/*S_GREN_06*/ { SPR_GREN, 2, 10, { NULL }, S_GREN_07 }, //101 -/*S_GREN_07*/ { SPR_GREN, 0, 0, { A_ReFire }, S_GREN_00 }, //102 -/*S_GREF_00*/ { SPR_GREF, 32768, 5, { A_Light1 }, S_PNCH_00 }, //103 -/*S_GREF_01*/ { SPR_GREF, 0, 10, { A_Light0 }, S_PNCH_00 }, //104 -/*S_GREF_02*/ { SPR_GREF, 32769, 5, { A_Light2 }, S_PNCH_00 }, //105 -/*S_GREN_08*/ { SPR_GREN, 3, 1, { A_WeaponReady }, S_GREN_08 }, //106 -/*S_GREN_09*/ { SPR_GREN, 3, 1, { A_Lower }, S_GREN_09 }, //107 -/*S_GREN_10*/ { SPR_GREN, 3, 1, { A_Raise }, S_GREN_10 }, //108 -/*S_GREN_11*/ { SPR_GREN, 3, 5, { A_FireGrenade }, S_GREN_12 }, //109 -/*S_GREN_12*/ { SPR_GREN, 4, 10, { NULL }, S_GREN_13 }, //110 -/*S_GREN_13*/ { SPR_GREN, 3, 5, { A_FireGrenade }, S_GREN_14 }, //111 -/*S_GREN_14*/ { SPR_GREN, 5, 10, { NULL }, S_GREN_15 }, //112 -/*S_GREN_15*/ { SPR_GREN, 0, 0, { A_ReFire }, S_GREN_08 }, //113 -/*S_GREF_03*/ { SPR_GREF, 32770, 5, { A_Light1 }, S_PNCH_00 }, //114 -/*S_GREF_04*/ { SPR_GREF, 2, 10, { A_Light0 }, S_PNCH_00 }, //115 -/*S_GREF_05*/ { SPR_GREF, 32771, 5, { A_Light2 }, S_PNCH_00 }, //116 -/*S_SIGH_00*/ { SPR_SIGH, 32768, 1, { A_WeaponReady }, S_SIGH_00 }, //117 -/*S_SIGH_01*/ { SPR_SIGH, 32769, -1, { NULL }, S_NULL }, //118 -/*S_SIGH_02*/ { SPR_SIGH, 32770, -1, { NULL }, S_NULL }, //119 -/*S_SIGH_03*/ { SPR_SIGH, 32771, -1, { NULL }, S_NULL }, //120 -/*S_SIGH_04*/ { SPR_SIGH, 32772, -1, { NULL }, S_NULL }, //121 -/*S_SIGH_05*/ { SPR_SIGH, 32768, 1, { A_Lower }, S_SIGH_05 }, //122 -/*S_SIGH_06*/ { SPR_SIGH, 32768, 1, { A_Raise }, S_SIGH_06 }, //123 -/*S_SIGH_07*/ { SPR_SIGH, 32768, 18, { A_SigilSound }, S_SIGH_08 }, //124 -/*S_SIGH_08*/ { SPR_SIGH, 32768, 3, { A_GunFlash }, S_SIGH_09 }, //125 -/*S_SIGH_09*/ { SPR_SIGH, 0, 10, { A_FireSigil }, S_SIGH_10 }, //126 -/*S_SIGH_10*/ { SPR_SIGH, 0, 5, { A_GunFlashThinker }, S_SIGH_00 }, //127 -/*S_SIGF_00*/ { SPR_SIGF, 32768, 4, { A_Light2 }, S_SIGF_01 }, //128 -/*S_SIGF_01*/ { SPR_SIGF, 32769, 6, { A_SigilShock }, S_SIGF_02 }, //129 -/*S_SIGF_02*/ { SPR_SIGF, 32770, 4, { A_Light1 }, S_PNCH_00 }, //130 -/*S_POW1_00*/ { SPR_POW1, 0, 4, { NULL }, S_POW1_01 }, //131 -/*S_POW1_01*/ { SPR_POW1, 1, 4, { NULL }, S_POW1_02 }, //132 -/*S_POW1_02*/ { SPR_POW1, 2, 4, { NULL }, S_POW1_03 }, //133 -/*S_POW1_03*/ { SPR_POW1, 3, 4, { NULL }, S_POW1_04 }, //134 -/*S_POW1_04*/ { SPR_POW1, 4, 4, { NULL }, S_NULL }, //135 -/*S_POW1_05*/ { SPR_POW1, 5, 4, { NULL }, S_POW1_06 }, //136 -/*S_POW1_06*/ { SPR_POW1, 6, 4, { NULL }, S_POW1_07 }, //137 -/*S_POW1_07*/ { SPR_POW1, 7, 4, { NULL }, S_POW1_08 }, //138 -/*S_POW1_08*/ { SPR_POW1, 8, 4, { NULL }, S_POW1_09 }, //139 -/*S_POW1_09*/ { SPR_POW1, 9, 4, { NULL }, S_NULL }, //140 -/*S_POW2_00*/ { SPR_POW2, 0, 4, { NULL }, S_POW2_01 }, //141 -/*S_POW2_01*/ { SPR_POW2, 1, 4, { NULL }, S_POW2_02 }, //142 -/*S_POW2_02*/ { SPR_POW2, 2, 4, { NULL }, S_POW2_03 }, //143 -/*S_POW2_03*/ { SPR_POW2, 3, 4, { NULL }, S_NULL }, //144 -/*S_POW3_00*/ { SPR_POW3, 0, 3, { NULL }, S_POW3_01 }, //145 -/*S_POW3_01*/ { SPR_POW3, 1, 3, { NULL }, S_POW3_02 }, //146 -/*S_POW3_02*/ { SPR_POW3, 2, 3, { NULL }, S_POW3_03 }, //147 -/*S_POW3_03*/ { SPR_POW3, 3, 3, { NULL }, S_POW3_04 }, //148 -/*S_POW3_04*/ { SPR_POW3, 4, 3, { NULL }, S_POW3_05 }, //149 -/*S_POW3_05*/ { SPR_POW3, 5, 3, { NULL }, S_POW3_06 }, //150 -/*S_POW3_06*/ { SPR_POW3, 6, 3, { NULL }, S_POW3_07 }, //151 -/*S_POW3_07*/ { SPR_POW3, 7, 3, { NULL }, S_NULL }, //152 -/*S_ZAP1_00*/ { SPR_ZAP1, 1, 3, { A_DeathExplode3 }, S_ZAP1_02 }, //153 -/*S_ZAP1_01*/ { SPR_ZAP1, 0, 3, { A_RaiseAlarm }, S_ZAP1_02 }, //154 -/*S_ZAP1_02*/ { SPR_ZAP1, 1, 3, { NULL }, S_ZAP1_03 }, //155 -/*S_ZAP1_03*/ { SPR_ZAP1, 2, 3, { NULL }, S_ZAP1_04 }, //156 -/*S_ZAP1_04*/ { SPR_ZAP1, 3, 3, { NULL }, S_ZAP1_05 }, //157 -/*S_ZAP1_05*/ { SPR_ZAP1, 4, 3, { NULL }, S_ZAP1_06 }, //158 -/*S_ZAP1_06*/ { SPR_ZAP1, 5, 3, { NULL }, S_ZAP1_07 }, //159 -/*S_ZAP1_07*/ { SPR_ZAP1, 4, 3, { NULL }, S_ZAP1_08 }, //160 -/*S_ZAP1_08*/ { SPR_ZAP1, 3, 2, { NULL }, S_ZAP1_09 }, //161 -/*S_ZAP1_09*/ { SPR_ZAP1, 2, 2, { NULL }, S_ZAP1_10 }, //162 -/*S_ZAP1_10*/ { SPR_ZAP1, 1, 2, { NULL }, S_ZAP1_11 }, //163 -/*S_ZAP1_11*/ { SPR_ZAP1, 0, 1, { NULL }, S_NULL }, //164 -/*S_SPRY_00*/ { SPR_SPRY, 0, 3, { NULL }, S_SPRY_01 }, //165 -/*S_SPRY_01*/ { SPR_SPRY, 1, 3, { NULL }, S_SPRY_02 }, //166 -/*S_SPRY_02*/ { SPR_SPRY, 2, 3, { NULL }, S_SPRY_03 }, //167 -/*S_SPRY_03*/ { SPR_SPRY, 3, 3, { NULL }, S_SPRY_04 }, //168 -/*S_SPRY_04*/ { SPR_SPRY, 4, 3, { NULL }, S_SPRY_05 }, //169 -/*S_SPRY_05*/ { SPR_SPRY, 5, 3, { NULL }, S_SPRY_06 }, //170 -/*S_SPRY_06*/ { SPR_SPRY, 6, 2, { NULL }, S_NULL }, //171 -/*S_BLOD_00*/ { SPR_BLOD, 2, 8, { NULL }, S_BLOD_01 }, //172 -/*S_BLOD_01*/ { SPR_BLOD, 1, 8, { NULL }, S_BLOD_02 }, //173 -/*S_BLOD_02*/ { SPR_BLOD, 0, 8, { NULL }, S_NULL }, //174 -/*S_PUFY_00*/ { SPR_PUFY, 32768, 4, { NULL }, S_PUFY_01 }, //175 -/*S_PUFY_01*/ { SPR_PUFY, 1, 4, { NULL }, S_PUFY_02 }, //176 -/*S_PUFY_02*/ { SPR_PUFY, 2, 4, { NULL }, S_PUFY_03 }, //177 -/*S_PUFY_03*/ { SPR_PUFY, 3, 4, { NULL }, S_NULL }, //178 -/*S_SHT1_00*/ { SPR_SHT1, 0, 4, { NULL }, S_SHT1_01 }, //179 -/*S_SHT1_01*/ { SPR_SHT1, 1, 4, { NULL }, S_SHT1_00 }, //180 -/*S_SHT2_00*/ { SPR_SHT2, 0, 5, { NULL }, S_SHT2_01 }, //181 -/*S_SHT2_01*/ { SPR_SHT2, 1, 5, { NULL }, S_POW1_00 }, //182 -/*S_GRIN_00*/ { SPR_GRIN, 0, 3, { A_MissileTick }, S_GRIN_01 }, //183 -/*S_GRIN_01*/ { SPR_GRIN, 1, 3, { A_MissileTick }, S_GRIN_00 }, //184 -/*S_GRAP_00*/ { SPR_GRAP, 0, 3, { A_MissileTick }, S_GRAP_01 }, //185 -/*S_GRAP_01*/ { SPR_GRAP, 1, 3, { A_MissileTick }, S_GRAP_00 }, //186 -/*S_UBAM_00*/ { SPR_UBAM, 0, 3, { A_MissileTick }, S_UBAM_01 }, //187 -/*S_UBAM_01*/ { SPR_UBAM, 1, 3, { A_MissileTick }, S_UBAM_00 }, //188 -/*S_BNG2_00*/ { SPR_BNG2, 32768, 4, { A_DeathExplode5 }, S_BNG2_01 }, //189 -/*S_BNG2_01*/ { SPR_BNG2, 32769, 4, { NULL }, S_BNG2_02 }, //190 -/*S_BNG2_02*/ { SPR_BNG2, 32770, 4, { NULL }, S_BNG2_03 }, //191 -/*S_BNG2_03*/ { SPR_BNG2, 32771, 4, { NULL }, S_BNG2_04 }, //192 -/*S_BNG2_04*/ { SPR_BNG2, 32772, 4, { NULL }, S_BNG2_05 }, //193 -/*S_BNG2_05*/ { SPR_BNG2, 32773, 4, { NULL }, S_BNG2_06 }, //194 -/*S_BNG2_06*/ { SPR_BNG2, 32774, 4, { NULL }, S_BNG2_07 }, //195 -/*S_BNG2_07*/ { SPR_BNG2, 32775, 4, { NULL }, S_BNG2_08 }, //196 -/*S_BNG2_08*/ { SPR_BNG2, 32776, 4, { NULL }, S_NULL }, //197 -/*S_BNG4_00*/ { SPR_BNG4, 32768, 2, { A_DeathExplode5 }, S_BNG4_01 }, //198 -/*S_BNG4_01*/ { SPR_BNG4, 32769, 3, { NULL }, S_BNG4_02 }, //199 -/*S_BNG4_02*/ { SPR_BNG4, 32770, 3, { NULL }, S_BNG4_03 }, //200 -/*S_BNG4_03*/ { SPR_BNG4, 32771, 3, { NULL }, S_BNG4_04 }, //201 -/*S_BNG4_04*/ { SPR_BNG4, 32772, 3, { NULL }, S_BNG4_05 }, //202 -/*S_BNG4_05*/ { SPR_BNG4, 32773, 3, { NULL }, S_BNG4_06 }, //203 -/*S_BNG4_06*/ { SPR_BNG4, 32774, 3, { NULL }, S_BNG4_07 }, //204 -/*S_BNG4_07*/ { SPR_BNG4, 32775, 3, { NULL }, S_BNG4_08 }, //205 -/*S_BNG4_08*/ { SPR_BNG4, 32776, 3, { NULL }, S_BNG4_09 }, //206 -/*S_BNG4_09*/ { SPR_BNG4, 32777, 3, { NULL }, S_BNG4_10 }, //207 -/*S_BNG4_10*/ { SPR_BNG4, 32778, 3, { NULL }, S_BNG4_11 }, //208 -/*S_BNG4_11*/ { SPR_BNG4, 32779, 3, { NULL }, S_BNG4_12 }, //209 -/*S_BNG4_12*/ { SPR_BNG4, 32780, 3, { NULL }, S_BNG4_13 }, //210 -/*S_BNG4_13*/ { SPR_BNG4, 32781, 3, { NULL }, S_NULL }, //211 -/*S_BNG3_00*/ { SPR_BNG3, 32768, 3, { A_DeathExplode5 }, S_BNG3_01 }, //212 -/*S_BNG3_01*/ { SPR_BNG3, 32769, 3, { NULL }, S_BNG3_02 }, //213 -/*S_BNG3_02*/ { SPR_BNG3, 32770, 3, { NULL }, S_BNG3_03 }, //214 -/*S_BNG3_03*/ { SPR_BNG3, 32771, 3, { NULL }, S_BNG3_04 }, //215 -/*S_BNG3_04*/ { SPR_BNG3, 32772, 3, { NULL }, S_BNG3_05 }, //216 -/*S_BNG3_05*/ { SPR_BNG3, 32773, 3, { NULL }, S_BNG3_06 }, //217 -/*S_BNG3_06*/ { SPR_BNG3, 32774, 3, { NULL }, S_BNG3_07 }, //218 -/*S_BNG3_07*/ { SPR_BNG3, 32775, 3, { NULL }, S_NULL }, //219 -/*S_BNG3_08*/ { SPR_BNG3, 0, 1, { A_SpawnGrenadeFire }, S_NULL }, //220 -/*S_BNG3_09*/ { SPR_BNG3, 32769, 2, { A_DeathExplode1 }, S_BNG3_10 }, //221 -/*S_BNG3_10*/ { SPR_BNG3, 32770, 2, { A_MissileTick }, S_FLBE_00 }, //222 -/*S_FLBE_00*/ { SPR_FLBE, 32768, 2, { A_BurnSpread }, S_FLBE_01 }, //223 -/*S_FLBE_01*/ { SPR_FLBE, 32769, 2, { A_MissileTick }, S_FLBE_02 }, //224 -/*S_FLBE_02*/ { SPR_FLBE, 32770, 2, { A_DeathExplode1 }, S_FLBE_03 }, //225 -/*S_FLBE_03*/ { SPR_FLBE, 32771, 3, { A_MissileTick }, S_FLBE_04 }, //226 -/*S_FLBE_04*/ { SPR_FLBE, 32772, 3, { A_DeathExplode1 }, S_FLBE_05 }, //227 -/*S_FLBE_05*/ { SPR_FLBE, 32773, 3, { A_MissileTick }, S_FLBE_06 }, //228 -/*S_FLBE_06*/ { SPR_FLBE, 32774, 3, { A_BurnSpread }, S_FLBE_03 }, //229 -/*S_FLBE_07*/ { SPR_FLBE, 32775, 2, { NULL }, S_FLBE_08 }, //230 -/*S_FLBE_08*/ { SPR_FLBE, 32776, 2, { A_BurnSpread }, S_FLBE_09 }, //231 -/*S_FLBE_09*/ { SPR_FLBE, 32777, 2, { NULL }, S_FLBE_10 }, //232 -/*S_FLBE_10*/ { SPR_FLBE, 32778, 2, { NULL }, S_NULL }, //233 -/*S_XPRK_00*/ { SPR_XPRK, 0, 1, { A_ClearForceField }, S_NULL }, //234 -/*S_OCLW_00*/ { SPR_OCLW, 0, 2, { A_FireChainShot }, S_OCLW_00 }, //235 -/*S_CCLW_00*/ { SPR_CCLW, 0, 6, { NULL }, S_NULL }, //236 -/*S_TEND_00*/ { SPR_TEND, 0, 20, { NULL }, S_NULL }, //237 -/*S_MICR_00*/ { SPR_MICR, 32768, 6, { A_MissileSmoke }, S_MICR_00 }, //238 -/*S_MISS_00*/ { SPR_MISS, 32768, 4, { A_MissileSmoke }, S_MISS_01 }, //239 -/*S_MISS_01*/ { SPR_MISS, 32769, 3, { A_Tracer }, S_MISS_00 }, //240 -/*S_AROW_00*/ { SPR_AROW, 0, 10, { A_ActiveSound }, S_AROW_00 }, //241 -/*S_ARWP_00*/ { SPR_ARWP, 0, 10, { A_ActiveSound }, S_ARWP_00 }, //242 -/*S_AROW_01*/ { SPR_AROW, 0, 1, { NULL }, S_NULL }, //243 -/*S_TORP_00*/ { SPR_TORP, 32768, 4, { NULL }, S_TORP_01 }, //244 -/*S_TORP_01*/ { SPR_TORP, 32769, 4, { NULL }, S_TORP_02 }, //245 -/*S_TORP_02*/ { SPR_TORP, 32770, 4, { NULL }, S_TORP_03 }, //246 -/*S_TORP_03*/ { SPR_TORP, 32771, 4, { NULL }, S_TORP_00 }, //247 -/*S_THIT_00*/ { SPR_THIT, 32768, 8, { NULL }, S_THIT_01 }, //248 -/*S_THIT_01*/ { SPR_THIT, 32769, 8, { NULL }, S_THIT_02 }, //249 -/*S_THIT_02*/ { SPR_THIT, 32770, 8, { A_TorpedoExplode }, S_THIT_03 }, //250 -/*S_THIT_03*/ { SPR_THIT, 32771, 8, { NULL }, S_THIT_04 }, //251 -/*S_THIT_04*/ { SPR_THIT, 32772, 8, { NULL }, S_NULL }, //252 -/*S_TWAV_00*/ { SPR_TWAV, 32768, 9, { NULL }, S_TWAV_01 }, //253 -/*S_TWAV_01*/ { SPR_TWAV, 32769, 9, { NULL }, S_TWAV_02 }, //254 -/*S_TWAV_02*/ { SPR_TWAV, 32770, 9, { NULL }, S_NULL }, //255 -/*S_MISL_00*/ { SPR_MISL, 32768, 5, { NULL }, S_MISL_02 }, //256 -/*S_MISL_01*/ { SPR_MISL, 32768, 5, { A_DeathExplode2 }, S_MISL_02 }, //257 -/*S_MISL_02*/ { SPR_MISL, 32769, 5, { NULL }, S_MISL_03 }, //258 -/*S_MISL_03*/ { SPR_MISL, 32770, 4, { NULL }, S_MISL_04 }, //259 -/*S_MISL_04*/ { SPR_MISL, 32771, 2, { NULL }, S_MISL_05 }, //260 -/*S_MISL_05*/ { SPR_MISL, 32772, 2, { NULL }, S_MISL_06 }, //261 -/*S_MISL_06*/ { SPR_MISL, 32773, 2, { NULL }, S_MISL_07 }, //262 -/*S_MISL_07*/ { SPR_MISL, 32774, 2, { NULL }, S_NULL }, //263 -/*S_TFOG_00*/ { SPR_TFOG, 32768, 6, { NULL }, S_TFOG_01 }, //264 -/*S_TFOG_01*/ { SPR_TFOG, 32769, 6, { NULL }, S_TFOG_02 }, //265 -/*S_TFOG_02*/ { SPR_TFOG, 32770, 6, { NULL }, S_TFOG_03 }, //266 -/*S_TFOG_03*/ { SPR_TFOG, 32771, 6, { NULL }, S_TFOG_04 }, //267 -/*S_TFOG_04*/ { SPR_TFOG, 32772, 6, { NULL }, S_TFOG_05 }, //268 -/*S_TFOG_05*/ { SPR_TFOG, 32773, 6, { NULL }, S_TFOG_06 }, //269 -/*S_TFOG_06*/ { SPR_TFOG, 32772, 6, { NULL }, S_TFOG_07 }, //270 -/*S_TFOG_07*/ { SPR_TFOG, 32771, 6, { NULL }, S_TFOG_08 }, //271 -/*S_TFOG_08*/ { SPR_TFOG, 32770, 6, { NULL }, S_TFOG_09 }, //272 -/*S_TFOG_09*/ { SPR_TFOG, 32769, 6, { NULL }, S_NULL }, //273 -/*S_IFOG_00*/ { SPR_IFOG, 32768, 6, { NULL }, S_IFOG_01 }, //274 -/*S_IFOG_01*/ { SPR_IFOG, 32769, 6, { NULL }, S_IFOG_02 }, //275 -/*S_IFOG_02*/ { SPR_IFOG, 32768, 6, { NULL }, S_IFOG_03 }, //276 -/*S_IFOG_03*/ { SPR_IFOG, 32769, 6, { NULL }, S_IFOG_04 }, //277 -/*S_IFOG_04*/ { SPR_IFOG, 32770, 6, { NULL }, S_IFOG_05 }, //278 -/*S_IFOG_05*/ { SPR_IFOG, 32771, 6, { NULL }, S_IFOG_06 }, //279 -/*S_IFOG_06*/ { SPR_IFOG, 32772, 6, { NULL }, S_NULL }, //280 -/*S_SHRD_00*/ { SPR_SHRD, 0, 128, { NULL }, S_NULL }, //281 -/*S_SHRD_01*/ { SPR_SHRD, 1, 128, { NULL }, S_NULL }, //282 -/*S_SHRD_02*/ { SPR_SHRD, 2, 128, { NULL }, S_NULL }, //283 -/*S_SHRD_03*/ { SPR_SHRD, 3, 128, { NULL }, S_NULL }, //284 -/*S_SHRD_04*/ { SPR_SHRD, 4, 128, { NULL }, S_NULL }, //285 -/*S_SHRD_05*/ { SPR_SHRD, 5, 128, { NULL }, S_NULL }, //286 -/*S_PLAY_00*/ { SPR_PLAY, 0, -1, { NULL }, S_NULL }, //287 -/*S_PLAY_01*/ { SPR_PLAY, 0, 4, { NULL }, S_PLAY_02 }, //288 -/*S_PLAY_02*/ { SPR_PLAY, 1, 4, { NULL }, S_PLAY_03 }, //289 -/*S_PLAY_03*/ { SPR_PLAY, 2, 4, { NULL }, S_PLAY_04 }, //290 -/*S_PLAY_04*/ { SPR_PLAY, 3, 4, { NULL }, S_PLAY_01 }, //291 -/*S_PLAY_05*/ { SPR_PLAY, 4, 12, { NULL }, S_PLAY_00 }, //292 -/*S_PLAY_06*/ { SPR_PLAY, 5, 6, { NULL }, S_PLAY_05 }, //293 -/*S_PLAY_07*/ { SPR_PLAY, 16, 4, { A_Pain }, S_PLAY_08 }, //294 -/*S_PLAY_08*/ { SPR_PLAY, 16, 4, { NULL }, S_PLAY_00 }, //295 -/*S_PLAY_09*/ { SPR_PLAY, 6, 4, { NULL }, S_PLAY_10 }, //296 -/*S_PLAY_10*/ { SPR_PLAY, 7, 3, { A_PlayerScream }, S_PLAY_11 }, //297 -/*S_PLAY_11*/ { SPR_PLAY, 8, 3, { A_Fall }, S_PLAY_12 }, //298 -/*S_PLAY_12*/ { SPR_PLAY, 9, 4, { NULL }, S_PLAY_13 }, //299 -/*S_PLAY_13*/ { SPR_PLAY, 10, 4, { NULL }, S_PLAY_14 }, //300 -/*S_PLAY_14*/ { SPR_PLAY, 11, 4, { NULL }, S_PLAY_15 }, //301 -/*S_PLAY_15*/ { SPR_PLAY, 12, 4, { NULL }, S_PLAY_16 }, //302 -/*S_PLAY_16*/ { SPR_PLAY, 13, 4, { NULL }, S_PLAY_17 }, //303 -/*S_PLAY_17*/ { SPR_PLAY, 14, 4, { NULL }, S_PLAY_18 }, //304 -/*S_PLAY_18*/ { SPR_PLAY, 15, 700, { NULL }, S_RGIB_07 }, //305 -/*S_RGIB_00*/ { SPR_RGIB, 0, 5, { A_BodyParts }, S_RGIB_01 }, //306 -/*S_RGIB_01*/ { SPR_RGIB, 1, 5, { A_XScream }, S_RGIB_02 }, //307 -/*S_RGIB_02*/ { SPR_RGIB, 2, 5, { A_Fall }, S_RGIB_03 }, //308 -/*S_RGIB_03*/ { SPR_RGIB, 3, 5, { A_BodyParts }, S_RGIB_04 }, //309 -/*S_RGIB_04*/ { SPR_RGIB, 4, 5, { A_BodyParts }, S_RGIB_05 }, //310 -/*S_RGIB_05*/ { SPR_RGIB, 5, 5, { A_BodyParts }, S_RGIB_06 }, //311 -/*S_RGIB_06*/ { SPR_RGIB, 6, 5, { A_BodyParts }, S_RGIB_07 }, //312 -/*S_RGIB_07*/ { SPR_RGIB, 7, 1400, { NULL }, S_NULL }, //313 -/*S_MRYS_00*/ { SPR_MRYS, 0, 30, { NULL }, S_MRST_00 }, //314 -/*S_MRNO_00*/ { SPR_MRNO, 0, 6, { NULL }, S_MRNO_01 }, //315 -/*S_MRNO_01*/ { SPR_MRNO, 1, 6, { NULL }, S_MRNO_02 }, //316 -/*S_MRNO_02*/ { SPR_MRNO, 2, 10, { NULL }, S_MRNO_03 }, //317 -/*S_MRNO_03*/ { SPR_MRNO, 1, 6, { NULL }, S_MRNO_04 }, //318 -/*S_MRNO_04*/ { SPR_MRNO, 0, 6, { NULL }, S_MRST_00 }, //319 -/*S_MRST_00*/ { SPR_MRST, 0, 10, { A_FriendLook }, S_MRST_00 }, //320 -/*S_MRLK_00*/ { SPR_MRLK, 0, 30, { A_ActiveSound }, S_MRST_00 }, //321 -/*S_MRLK_01*/ { SPR_MRLK, 1, 30, { NULL }, S_MRST_00 }, //322 -/*S_MRBD_00*/ { SPR_MRBD, 0, 4, { NULL }, S_MRBD_01 }, //323 -/*S_MRBD_01*/ { SPR_MRBD, 1, 4, { NULL }, S_MRBD_02 }, //324 -/*S_MRBD_02*/ { SPR_MRBD, 2, 4, { NULL }, S_MRBD_03 }, //325 -/*S_MRBD_03*/ { SPR_MRBD, 3, 4, { NULL }, S_MRBD_04 }, //326 -/*S_MRBD_04*/ { SPR_MRBD, 4, 4, { NULL }, S_MRBD_05 }, //327 -/*S_MRBD_05*/ { SPR_MRBD, 3, 4, { NULL }, S_MRBD_06 }, //328 -/*S_MRBD_06*/ { SPR_MRBD, 2, 4, { NULL }, S_MRBD_07 }, //329 -/*S_MRBD_07*/ { SPR_MRBD, 1, 4, { NULL }, S_MRBD_08 }, //330 -/*S_MRBD_08*/ { SPR_MRBD, 0, 5, { NULL }, S_MRBD_09 }, //331 -/*S_MRBD_09*/ { SPR_MRBD, 5, 6, { NULL }, S_MRST_00 }, //332 -/*S_MRPN_00*/ { SPR_MRPN, 0, 3, { NULL }, S_MRPN_01 }, //333 -/*S_MRPN_01*/ { SPR_MRPN, 1, 3, { A_Pain }, S_MRPN_02 }, //334 -/*S_MRPN_02*/ { SPR_MRPN, 2, 3, { NULL }, S_MRPN_03 }, //335 -/*S_MRPN_03*/ { SPR_MRPN, 3, 9, { A_MerchantPain }, S_MRPN_04 }, //336 -/*S_MRPN_04*/ { SPR_MRPN, 2, 4, { NULL }, S_MRPN_05 }, //337 -/*S_MRPN_05*/ { SPR_MRPN, 1, 3, { NULL }, S_MRPN_06 }, //338 -/*S_MRPN_06*/ { SPR_MRPN, 0, 3, { A_ClearSoundTarget }, S_MRST_00 }, //339 -/*S_MRGT_00*/ { SPR_MRGT, 0, 5, { NULL }, S_MRGT_01 }, //340 -/*S_MRGT_01*/ { SPR_MRGT, 1, 5, { NULL }, S_MRGT_02 }, //341 -/*S_MRGT_02*/ { SPR_MRGT, 2, 5, { NULL }, S_MRGT_03 }, //342 -/*S_MRGT_03*/ { SPR_MRGT, 3, 5, { NULL }, S_MRGT_04 }, //343 -/*S_MRGT_04*/ { SPR_MRGT, 4, 5, { NULL }, S_MRGT_05 }, //344 -/*S_MRGT_05*/ { SPR_MRGT, 5, 5, { NULL }, S_MRGT_06 }, //345 -/*S_MRGT_06*/ { SPR_MRGT, 6, 5, { NULL }, S_MRGT_07 }, //346 -/*S_MRGT_07*/ { SPR_MRGT, 7, 5, { NULL }, S_MRGT_08 }, //347 -/*S_MRGT_08*/ { SPR_MRGT, 8, 5, { NULL }, S_MRST_00 }, //348 -/*S_BURN_00*/ { SPR_BURN, 0, 3, { A_Scream }, S_BURN_01 }, //349 -/*S_BURN_01*/ { SPR_BURN, 1, 3, { A_DropBurnFlesh }, S_BURN_02 }, //350 -/*S_BURN_02*/ { SPR_BURN, 2, 3, { A_RandomWalk }, S_BURN_03 }, //351 -/*S_BURN_03*/ { SPR_BURN, 3, 3, { A_Fall }, S_BURN_04 }, //352 -/*S_BURN_04*/ { SPR_BURN, 4, 5, { A_DropBurnFlesh }, S_BURN_05 }, //353 -/*S_BURN_05*/ { SPR_BURN, 5, 5, { A_RandomWalk }, S_BURN_06 }, //354 -/*S_BURN_06*/ { SPR_BURN, 6, 5, { A_RandomWalk }, S_BURN_07 }, //355 -/*S_BURN_07*/ { SPR_BURN, 7, 5, { A_RandomWalk }, S_BURN_08 }, //356 -/*S_BURN_08*/ { SPR_BURN, 8, 5, { A_DropBurnFlesh }, S_BURN_09 }, //357 -/*S_BURN_09*/ { SPR_BURN, 9, 5, { A_RandomWalk }, S_BURN_10 }, //358 -/*S_BURN_10*/ { SPR_BURN, 10, 5, { A_RandomWalk }, S_BURN_11 }, //359 -/*S_BURN_11*/ { SPR_BURN, 11, 5, { A_RandomWalk }, S_BURN_12 }, //360 -/*S_BURN_12*/ { SPR_BURN, 12, 3, { A_DropBurnFlesh }, S_BURN_13 }, //361 -/*S_BURN_13*/ { SPR_BURN, 13, 3, { NULL }, S_BURN_14 }, //362 -/*S_BURN_14*/ { SPR_BURN, 14, 5, { NULL }, S_BURN_15 }, //363 -/*S_BURN_15*/ { SPR_BURN, 15, 5, { NULL }, S_BURN_16 }, //364 -/*S_BURN_16*/ { SPR_BURN, 16, 5, { NULL }, S_BURN_17 }, //365 -/*S_BURN_17*/ { SPR_BURN, 15, 5, { NULL }, S_BURN_18 }, //366 -/*S_BURN_18*/ { SPR_BURN, 16, 5, { NULL }, S_BURN_19 }, //367 -/*S_BURN_19*/ { SPR_BURN, 17, 7, { NULL }, S_BURN_20 }, //368 -/*S_BURN_20*/ { SPR_BURN, 18, 7, { NULL }, S_BURN_21 }, //369 -/*S_BURN_21*/ { SPR_BURN, 19, 7, { NULL }, S_BURN_22 }, //370 -/*S_BURN_22*/ { SPR_BURN, 20, 7, { NULL }, S_BURN_23 }, //371 -/*S_BURN_23*/ { SPR_BURN, 21, 700, { A_PeasantCrash }, S_NULL }, //372 -/*S_DISR_00*/ { SPR_DISR, 0, 5, { NULL }, S_DISR_01 }, //373 -/*S_DISR_01*/ { SPR_DISR, 1, 5, { NULL }, S_DISR_02 }, //374 -/*S_DISR_02*/ { SPR_DISR, 2, 5, { NULL }, S_DISR_03 }, //375 -/*S_DISR_03*/ { SPR_DISR, 3, 5, { A_Fall }, S_DISR_04 }, //376 -/*S_DISR_04*/ { SPR_DISR, 4, 5, { NULL }, S_DISR_05 }, //377 -/*S_DISR_05*/ { SPR_DISR, 5, 5, { NULL }, S_DISR_06 }, //378 -/*S_DISR_06*/ { SPR_DISR, 6, 4, { NULL }, S_DISR_07 }, //379 -/*S_DISR_07*/ { SPR_DISR, 7, 4, { NULL }, S_DISR_08 }, //380 -/*S_DISR_08*/ { SPR_DISR, 8, 4, { NULL }, S_DISR_09 }, //381 -/*S_DISR_09*/ { SPR_DISR, 9, 4, { NULL }, S_MEAT_03 }, //382 -/*S_PEAS_00*/ { SPR_PEAS, 0, 10, { A_FriendLook }, S_PEAS_00 }, //383 -/*S_PEAS_01*/ { SPR_PEAS, 0, 5, { A_RandomWalk }, S_PEAS_02 }, //384 -/*S_PEAS_02*/ { SPR_PEAS, 0, 5, { A_RandomWalk }, S_PEAS_03 }, //385 -/*S_PEAS_03*/ { SPR_PEAS, 1, 5, { A_RandomWalk }, S_PEAS_04 }, //386 -/*S_PEAS_04*/ { SPR_PEAS, 1, 5, { A_RandomWalk }, S_PEAS_05 }, //387 -/*S_PEAS_05*/ { SPR_PEAS, 2, 5, { A_RandomWalk }, S_PEAS_06 }, //388 -/*S_PEAS_06*/ { SPR_PEAS, 2, 5, { A_RandomWalk }, S_PEAS_07 }, //389 -/*S_PEAS_07*/ { SPR_PEAS, 3, 5, { A_RandomWalk }, S_PEAS_08 }, //390 -/*S_PEAS_08*/ { SPR_PEAS, 3, 5, { A_RandomWalk }, S_PEAS_00 }, //391 -/*S_PEAS_09*/ { SPR_PEAS, 4, 10, { A_FaceTarget }, S_PEAS_10 }, //392 -/*S_PEAS_10*/ { SPR_PEAS, 5, 8, { A_PeasantPunch }, S_PEAS_11 }, //393 -/*S_PEAS_11*/ { SPR_PEAS, 4, 8, { NULL }, S_PEAS_01 }, //394 -/*S_PEAS_12*/ { SPR_PEAS, 14, 3, { NULL }, S_PEAS_13 }, //395 -/*S_PEAS_13*/ { SPR_PEAS, 14, 3, { A_Pain }, S_PEAS_09 }, //396 -/*S_PEAS_14*/ { SPR_PEAS, 6, 5, { NULL }, S_PEAS_15 }, //397 -/*S_PEAS_15*/ { SPR_PEAS, 7, 10, { A_PeasantCrash }, S_PEAS_16 }, //398 -/*S_PEAS_16*/ { SPR_PEAS, 8, 6, { NULL }, S_PEAS_15 }, //399 -/*S_PEAS_17*/ { SPR_PEAS, 6, 5, { NULL }, S_PEAS_18 }, //400 -/*S_PEAS_18*/ { SPR_PEAS, 7, 5, { A_Scream }, S_PEAS_19 }, //401 -/*S_PEAS_19*/ { SPR_PEAS, 8, 6, { NULL }, S_PEAS_20 }, //402 -/*S_PEAS_20*/ { SPR_PEAS, 9, 5, { A_Fall }, S_PEAS_21 }, //403 -/*S_PEAS_21*/ { SPR_PEAS, 10, 5, { NULL }, S_PEAS_22 }, //404 -/*S_PEAS_22*/ { SPR_PEAS, 11, 6, { NULL }, S_PEAS_23 }, //405 -/*S_PEAS_23*/ { SPR_PEAS, 12, 8, { NULL }, S_PEAS_24 }, //406 -/*S_PEAS_24*/ { SPR_PEAS, 13, 1400, { NULL }, S_GIBS_08 }, //407 -/*S_GIBS_00*/ { SPR_GIBS, 12, 5, { A_BodyParts }, S_GIBS_01 }, //408 -/*S_GIBS_01*/ { SPR_GIBS, 13, 5, { A_XScream }, S_GIBS_02 }, //409 -/*S_GIBS_02*/ { SPR_GIBS, 14, 5, { A_Fall }, S_GIBS_03 }, //410 -/*S_GIBS_03*/ { SPR_GIBS, 15, 4, { A_BodyParts }, S_GIBS_04 }, //411 -/*S_GIBS_04*/ { SPR_GIBS, 16, 4, { A_BodyParts }, S_GIBS_05 }, //412 -/*S_GIBS_05*/ { SPR_GIBS, 17, 4, { A_BodyParts }, S_GIBS_06 }, //413 -/*S_GIBS_06*/ { SPR_GIBS, 18, 4, { A_BodyParts }, S_GIBS_07 }, //414 -/*S_GIBS_07*/ { SPR_GIBS, 19, 4, { NULL }, S_GIBS_08 }, //415 -/*S_GIBS_08*/ { SPR_GIBS, 20, 5, { NULL }, S_GIBS_09 }, //416 -/*S_GIBS_09*/ { SPR_GIBS, 21, 1400, { NULL }, S_NULL }, //417 -/*S_PEAS_25*/ { SPR_PEAS, 0, 5, { A_ZombieInSpecialSector }, S_PEAS_25 }, //418 -/*S_AGRD_00*/ { SPR_AGRD, 0, 5, { A_ZombieInSpecialSector }, S_AGRD_00 }, //419 -/*S_ARMR_00*/ { SPR_ARMR, 0, -1, { NULL }, S_NULL }, //420 -/*S_ARMR_01*/ { SPR_ARMR, 0, -1, { A_HideZombie }, S_NULL }, //421 -/*S_PLAY_19*/ { SPR_PLAY, 0, 175, { A_SpawnZombie }, S_PLAY_19 }, //422 -/*S_SACR_00*/ { SPR_SACR, 0, -1, { NULL }, S_NULL }, //423 -/*S_TNK1_00*/ { SPR_TNK1, 0, 15, { NULL }, S_TNK1_01 }, //424 -/*S_TNK1_01*/ { SPR_TNK1, 1, 11, { NULL }, S_TNK1_02 }, //425 -/*S_TNK1_02*/ { SPR_TNK1, 2, 40, { NULL }, S_TNK1_00 }, //426 -/*S_TNK2_00*/ { SPR_TNK2, 0, 15, { NULL }, S_TNK2_01 }, //427 -/*S_TNK2_01*/ { SPR_TNK2, 1, 11, { NULL }, S_TNK2_02 }, //428 -/*S_TNK2_02*/ { SPR_TNK2, 2, 40, { NULL }, S_TNK2_00 }, //429 -/*S_TNK3_00*/ { SPR_TNK3, 0, 15, { NULL }, S_TNK3_01 }, //430 -/*S_TNK3_01*/ { SPR_TNK3, 1, 11, { NULL }, S_TNK3_02 }, //431 -/*S_TNK3_02*/ { SPR_TNK3, 2, 40, { NULL }, S_TNK3_00 }, //432 -/*S_TNK4_00*/ { SPR_TNK4, 0, 15, { NULL }, S_TNK4_01 }, //433 -/*S_TNK4_01*/ { SPR_TNK4, 1, 11, { NULL }, S_TNK4_02 }, //434 -/*S_TNK4_02*/ { SPR_TNK4, 2, 40, { NULL }, S_TNK4_00 }, //435 -/*S_TNK5_00*/ { SPR_TNK5, 0, 15, { NULL }, S_TNK5_01 }, //436 -/*S_TNK5_01*/ { SPR_TNK5, 1, 11, { NULL }, S_TNK5_02 }, //437 -/*S_TNK5_02*/ { SPR_TNK5, 2, 40, { NULL }, S_TNK5_00 }, //438 -/*S_TNK6_00*/ { SPR_TNK6, 0, 15, { NULL }, S_TNK6_01 }, //439 -/*S_TNK6_01*/ { SPR_TNK6, 1, 11, { NULL }, S_TNK6_02 }, //440 -/*S_TNK6_02*/ { SPR_TNK6, 2, 40, { NULL }, S_TNK6_00 }, //441 -/*S_NEAL_00*/ { SPR_NEAL, 0, 15, { A_ActiveSound }, S_NEAL_01 }, //442 -/*S_NEAL_01*/ { SPR_NEAL, 1, 40, { A_ActiveSound }, S_NEAL_00 }, //443 -/*S_NEAL_02*/ { SPR_NEAL, 2, 5, { A_ShadowOn }, S_NEAL_03 }, //444 -/*S_NEAL_03*/ { SPR_NEAL, 1, 4, { A_Pain }, S_NEAL_04 }, //445 -/*S_NEAL_04*/ { SPR_NEAL, 2, 5, { A_ShadowOff }, S_NEAL_00 }, //446 -/*S_NEAL_05*/ { SPR_NEAL, 1, 6, { NULL }, S_NEAL_06 }, //447 -/*S_NEAL_06*/ { SPR_NEAL, 2, 13, { A_PeasantCrash }, S_NEAL_05 }, //448 -/*S_NEAL_07*/ { SPR_NEAL, 3, 5, { NULL }, S_NEAL_08 }, //449 -/*S_NEAL_08*/ { SPR_NEAL, 4, 5, { A_Scream }, S_NEAL_09 }, //450 -/*S_NEAL_09*/ { SPR_NEAL, 5, 6, { NULL }, S_NEAL_10 }, //451 -/*S_NEAL_10*/ { SPR_NEAL, 6, 5, { A_Fall }, S_NEAL_11 }, //452 -/*S_NEAL_11*/ { SPR_NEAL, 7, 5, { NULL }, S_NEAL_12 }, //453 -/*S_NEAL_12*/ { SPR_NEAL, 8, 6, { NULL }, S_NEAL_13 }, //454 -/*S_NEAL_13*/ { SPR_NEAL, 9, -1, { NULL }, S_NULL }, //455 -/*S_BEGR_00*/ { SPR_BEGR, 0, 10, { A_Look }, S_BEGR_00 }, //456 -/*S_BEGR_01*/ { SPR_BEGR, 0, 4, { A_RandomWalk }, S_BEGR_02 }, //457 -/*S_BEGR_02*/ { SPR_BEGR, 0, 4, { A_RandomWalk }, S_BEGR_03 }, //458 -/*S_BEGR_03*/ { SPR_BEGR, 1, 4, { A_RandomWalk }, S_BEGR_04 }, //459 -/*S_BEGR_04*/ { SPR_BEGR, 1, 4, { A_RandomWalk }, S_BEGR_05 }, //460 -/*S_BEGR_05*/ { SPR_BEGR, 2, 4, { A_RandomWalk }, S_BEGR_06 }, //461 -/*S_BEGR_06*/ { SPR_BEGR, 2, 4, { A_RandomWalk }, S_BEGR_01 }, //462 -/*S_BEGR_07*/ { SPR_BEGR, 3, 8, { NULL }, S_BEGR_08 }, //463 -/*S_BEGR_08*/ { SPR_BEGR, 4, 8, { A_PeasantPunch }, S_BEGR_09 }, //464 -/*S_BEGR_09*/ { SPR_BEGR, 4, 1, { A_Chase }, S_BEGR_10 }, //465 -/*S_BEGR_10*/ { SPR_BEGR, 3, 8, { A_CheckTargetVisible }, S_BEGR_07 }, //466 -/*S_BEGR_11*/ { SPR_BEGR, 0, 3, { A_Pain }, S_BEGR_12 }, //467 -/*S_BEGR_12*/ { SPR_BEGR, 0, 3, { A_Chase }, S_BEGR_07 }, //468 -/*S_BEGR_13*/ { SPR_BEGR, 5, 4, { NULL }, S_BEGR_14 }, //469 -/*S_BEGR_14*/ { SPR_BEGR, 6, 4, { A_Scream }, S_BEGR_15 }, //470 -/*S_BEGR_15*/ { SPR_BEGR, 7, 4, { NULL }, S_BEGR_16 }, //471 -/*S_BEGR_16*/ { SPR_BEGR, 8, 4, { A_Fall }, S_BEGR_17 }, //472 -/*S_BEGR_17*/ { SPR_BEGR, 9, 4, { NULL }, S_BEGR_18 }, //473 -/*S_BEGR_18*/ { SPR_BEGR, 10, 4, { NULL }, S_BEGR_19 }, //474 -/*S_BEGR_19*/ { SPR_BEGR, 11, 4, { NULL }, S_BEGR_20 }, //475 -/*S_BEGR_20*/ { SPR_BEGR, 12, 4, { NULL }, S_BEGR_21 }, //476 -/*S_BEGR_21*/ { SPR_BEGR, 13, -1, { NULL }, S_NULL }, //477 -/*S_BEGR_22*/ { SPR_BEGR, 5, 5, { A_BodyParts }, S_GIBS_01 }, //478 -/*S_HMN1_00*/ { SPR_HMN1, 15, 5, { A_FriendLook }, S_HMN1_00 }, //479 -/*S_HMN1_01*/ { SPR_HMN1, 16, 8, { NULL }, S_HMN1_00 }, //480 -/*S_HMN1_02*/ { SPR_HMN1, 17, 8, { NULL }, S_HMN1_00 }, //481 -/*S_HMN1_03*/ { SPR_HMN1, 0, 6, { A_RandomWalk }, S_HMN1_04 }, //482 -/*S_HMN1_04*/ { SPR_HMN1, 1, 6, { A_RandomWalk }, S_HMN1_05 }, //483 -/*S_HMN1_05*/ { SPR_HMN1, 2, 6, { A_RandomWalk }, S_HMN1_06 }, //484 -/*S_HMN1_06*/ { SPR_HMN1, 3, 6, { A_RandomWalk }, S_HMN1_07 }, //485 -/*S_HMN1_07*/ { SPR_HMN1, 0, 6, { A_RandomWalk }, S_HMN1_08 }, //486 -/*S_HMN1_08*/ { SPR_HMN1, 1, 6, { A_RandomWalk }, S_HMN1_09 }, //487 -/*S_HMN1_09*/ { SPR_HMN1, 2, 6, { A_RandomWalk }, S_HMN1_10 }, //488 -/*S_HMN1_10*/ { SPR_HMN1, 3, 6, { A_RandomWalk }, S_HMN1_00 }, //489 -/*S_HMN1_11*/ { SPR_HMN1, 0, 3, { A_Chase }, S_HMN1_12 }, //490 -/*S_HMN1_12*/ { SPR_HMN1, 0, 3, { A_Chase }, S_HMN1_13 }, //491 -/*S_HMN1_13*/ { SPR_HMN1, 1, 3, { A_Chase }, S_HMN1_14 }, //492 -/*S_HMN1_14*/ { SPR_HMN1, 1, 3, { A_Chase }, S_HMN1_15 }, //493 -/*S_HMN1_15*/ { SPR_HMN1, 2, 3, { A_Chase }, S_HMN1_16 }, //494 -/*S_HMN1_16*/ { SPR_HMN1, 2, 3, { A_Chase }, S_HMN1_17 }, //495 -/*S_HMN1_17*/ { SPR_HMN1, 3, 3, { A_Chase }, S_HMN1_18 }, //496 -/*S_HMN1_18*/ { SPR_HMN1, 3, 3, { A_Chase }, S_HMN1_11 }, //497 -/*S_HMN1_19*/ { SPR_HMN1, 4, 10, { A_FaceTarget }, S_HMN1_20 }, //498 -/*S_HMN1_20*/ { SPR_HMN1, 32773, 10, { A_BulletAttack }, S_HMN1_21 }, //499 -/*S_HMN1_21*/ { SPR_HMN1, 4, 10, { A_BulletAttack }, S_HMN1_11 }, //500 -/*S_HMN1_22*/ { SPR_HMN1, 14, 3, { NULL }, S_HMN1_23 }, //501 -/*S_HMN1_23*/ { SPR_HMN1, 14, 3, { A_Pain }, S_HMN1_11 }, //502 -/*S_HMN1_24*/ { SPR_HMN1, 6, 5, { NULL }, S_HMN1_25 }, //503 -/*S_HMN1_25*/ { SPR_HMN1, 7, 5, { A_Scream }, S_HMN1_26 }, //504 -/*S_HMN1_26*/ { SPR_HMN1, 8, 3, { A_Fall }, S_HMN1_27 }, //505 -/*S_HMN1_27*/ { SPR_HMN1, 9, 4, { NULL }, S_HMN1_28 }, //506 -/*S_HMN1_28*/ { SPR_HMN1, 10, 3, { NULL }, S_HMN1_29 }, //507 -/*S_HMN1_29*/ { SPR_HMN1, 11, 3, { NULL }, S_HMN1_30 }, //508 -/*S_HMN1_30*/ { SPR_HMN1, 12, 3, { NULL }, S_HMN1_31 }, //509 -/*S_HMN1_31*/ { SPR_HMN1, 13, -1, { NULL }, S_NULL }, //510 -/*S_RGIB_08*/ { SPR_RGIB, 0, 4, { A_BodyParts }, S_RGIB_09 }, //511 -/*S_RGIB_09*/ { SPR_RGIB, 1, 4, { A_XScream }, S_RGIB_10 }, //512 -/*S_RGIB_10*/ { SPR_RGIB, 2, 3, { A_Fall }, S_RGIB_11 }, //513 -/*S_RGIB_11*/ { SPR_RGIB, 3, 3, { A_BodyParts }, S_RGIB_12 }, //514 -/*S_RGIB_12*/ { SPR_RGIB, 4, 3, { A_BodyParts }, S_RGIB_13 }, //515 -/*S_RGIB_13*/ { SPR_RGIB, 5, 3, { A_BodyParts }, S_RGIB_14 }, //516 -/*S_RGIB_14*/ { SPR_RGIB, 6, 3, { NULL }, S_RGIB_15 }, //517 -/*S_RGIB_15*/ { SPR_RGIB, 7, 1400, { NULL }, S_NULL }, //518 -/*S_LEDR_00*/ { SPR_LEDR, 2, 5, { A_FriendLook }, S_LEDR_00 }, //519 -/*S_LEDR_01*/ { SPR_LEDR, 0, 8, { NULL }, S_LEDR_00 }, //520 -/*S_LEDR_02*/ { SPR_LEDR, 1, 8, { NULL }, S_LEDR_00 }, //521 -/*S_LEAD_00*/ { SPR_LEAD, 0, 6, { A_RandomWalk }, S_LEAD_01 }, //522 -/*S_LEAD_01*/ { SPR_LEAD, 1, 6, { A_RandomWalk }, S_LEAD_02 }, //523 -/*S_LEAD_02*/ { SPR_LEAD, 2, 6, { A_RandomWalk }, S_LEAD_03 }, //524 -/*S_LEAD_03*/ { SPR_LEAD, 3, 6, { A_RandomWalk }, S_LEDR_00 }, //525 -/*S_LEAD_04*/ { SPR_LEAD, 0, 3, { A_Chase }, S_LEAD_05 }, //526 -/*S_LEAD_05*/ { SPR_LEAD, 0, 3, { A_Chase }, S_LEAD_06 }, //527 -/*S_LEAD_06*/ { SPR_LEAD, 1, 3, { A_Chase }, S_LEAD_07 }, //528 -/*S_LEAD_07*/ { SPR_LEAD, 1, 3, { A_Chase }, S_LEAD_08 }, //529 -/*S_LEAD_08*/ { SPR_LEAD, 2, 3, { A_Chase }, S_LEAD_09 }, //530 -/*S_LEAD_09*/ { SPR_LEAD, 2, 3, { A_Chase }, S_LEAD_10 }, //531 -/*S_LEAD_10*/ { SPR_LEAD, 3, 3, { A_Chase }, S_LEAD_11 }, //532 -/*S_LEAD_11*/ { SPR_LEAD, 3, 3, { A_Chase }, S_LEAD_04 }, //533 -/*S_LEAD_12*/ { SPR_LEAD, 4, 2, { A_FaceTarget }, S_LEAD_13 }, //534 -/*S_LEAD_13*/ { SPR_LEAD, 32773, 2, { A_BulletAttack }, S_LEAD_14 }, //535 -/*S_LEAD_14*/ { SPR_LEAD, 4, 1, { A_CheckTargetVisible }, S_LEAD_12 }, //536 -/*S_LEAD_15*/ { SPR_LEAD, 24, 3, { NULL }, S_LEAD_16 }, //537 -/*S_LEAD_16*/ { SPR_LEAD, 24, 3, { A_Pain }, S_LEAD_04 }, //538 -/*S_LEAD_17*/ { SPR_LEAD, 4, 4, { A_FaceTarget }, S_LEAD_18 }, //539 -/*S_LEAD_18*/ { SPR_LEAD, 32773, 4, { A_BulletAttack }, S_LEAD_19 }, //540 -/*S_LEAD_19*/ { SPR_LEAD, 4, 2, { A_CheckTargetVisible }, S_LEAD_17 }, //541 -/*S_LEAD_20*/ { SPR_LEAD, 6, 5, { NULL }, S_LEAD_21 }, //542 -/*S_LEAD_21*/ { SPR_LEAD, 7, 5, { A_Scream }, S_LEAD_22 }, //543 -/*S_LEAD_22*/ { SPR_LEAD, 8, 4, { NULL }, S_LEAD_23 }, //544 -/*S_LEAD_23*/ { SPR_LEAD, 9, 4, { NULL }, S_LEAD_24 }, //545 -/*S_LEAD_24*/ { SPR_LEAD, 10, 3, { NULL }, S_LEAD_25 }, //546 -/*S_LEAD_25*/ { SPR_LEAD, 11, 3, { A_Fall }, S_LEAD_26 }, //547 -/*S_LEAD_26*/ { SPR_LEAD, 12, 3, { NULL }, S_LEAD_27 }, //548 -/*S_LEAD_27*/ { SPR_LEAD, 13, 3, { NULL }, S_LEAD_28 }, //549 -/*S_LEAD_28*/ { SPR_LEAD, 14, 3, { NULL }, S_LEAD_29 }, //550 -/*S_LEAD_29*/ { SPR_LEAD, 15, 3, { NULL }, S_LEAD_30 }, //551 -/*S_LEAD_30*/ { SPR_LEAD, 16, 3, { NULL }, S_LEAD_31 }, //552 -/*S_LEAD_31*/ { SPR_LEAD, 17, 3, { NULL }, S_LEAD_32 }, //553 -/*S_LEAD_32*/ { SPR_LEAD, 18, 3, { NULL }, S_LEAD_33 }, //554 -/*S_LEAD_33*/ { SPR_LEAD, 19, 3, { NULL }, S_LEAD_34 }, //555 -/*S_LEAD_34*/ { SPR_LEAD, 20, 3, { NULL }, S_LEAD_35 }, //556 -/*S_LEAD_35*/ { SPR_LEAD, 21, 3, { NULL }, S_LEAD_36 }, //557 -/*S_LEAD_36*/ { SPR_LEAD, 22, 3, { A_SpawnSpectreD }, S_LEAD_37 }, //558 -/*S_LEAD_37*/ { SPR_LEAD, 23, -1, { NULL }, S_NULL }, //559 -/*S_PUFY_04*/ { SPR_PUFY, 1, 4, { NULL }, S_PUFY_05 }, //560 -/*S_PUFY_05*/ { SPR_PUFY, 2, 4, { NULL }, S_PUFY_06 }, //561 -/*S_PUFY_06*/ { SPR_PUFY, 1, 4, { NULL }, S_PUFY_07 }, //562 -/*S_PUFY_07*/ { SPR_PUFY, 2, 4, { NULL }, S_PUFY_08 }, //563 -/*S_PUFY_08*/ { SPR_PUFY, 3, 4, { NULL }, S_NULL }, //564 -/*S_MICR_01*/ { SPR_MICR, 32768, 2, { A_Tracer }, S_MICR_02 }, //565 -/*S_MICR_02*/ { SPR_MICR, 32768, 2, { A_Tracer }, S_MICR_01 }, //566 -/*S_ROB1_00*/ { SPR_ROB1, 0, 10, { A_Look }, S_ROB1_01 }, //567 -/*S_ROB1_01*/ { SPR_ROB1, 0, 10, { A_Look }, S_ROB1_00 }, //568 -/*S_ROB1_02*/ { SPR_ROB1, 1, 3, { A_Chase }, S_ROB1_03 }, //569 -/*S_ROB1_03*/ { SPR_ROB1, 1, 3, { A_Chase }, S_ROB1_04 }, //570 -/*S_ROB1_04*/ { SPR_ROB1, 2, 3, { A_Chase }, S_ROB1_05 }, //571 -/*S_ROB1_05*/ { SPR_ROB1, 2, 3, { A_Chase }, S_ROB1_06 }, //572 -/*S_ROB1_06*/ { SPR_ROB1, 3, 3, { A_Chase }, S_ROB1_07 }, //573 -/*S_ROB1_07*/ { SPR_ROB1, 3, 3, { A_Chase }, S_ROB1_08 }, //574 -/*S_ROB1_08*/ { SPR_ROB1, 4, 3, { A_Chase }, S_ROB1_09 }, //575 -/*S_ROB1_09*/ { SPR_ROB1, 4, 3, { A_Chase }, S_ROB1_02 }, //576 -/*S_ROB1_10*/ { SPR_ROB1, 7, 6, { A_FaceTarget }, S_ROB1_11 }, //577 -/*S_ROB1_11*/ { SPR_ROB1, 8, 8, { A_RobotMelee }, S_ROB1_12 }, //578 -/*S_ROB1_12*/ { SPR_ROB1, 7, 6, { NULL }, S_ROB1_02 }, //579 -/*S_ROB1_13*/ { SPR_ROB1, 5, 8, { A_FaceTarget }, S_ROB1_14 }, //580 -/*S_ROB1_14*/ { SPR_ROB1, 32774, 11, { A_ReaverAttack }, S_ROB1_02 }, //581 -/*S_ROB1_15*/ { SPR_ROB1, 0, 2, { NULL }, S_ROB1_16 }, //582 -/*S_ROB1_16*/ { SPR_ROB1, 0, 2, { A_Pain }, S_ROB1_02 }, //583 -/*S_ROB1_17*/ { SPR_ROB1, 32777, 6, { NULL }, S_ROB1_18 }, //584 -/*S_ROB1_18*/ { SPR_ROB1, 32778, 6, { A_Scream }, S_ROB1_19 }, //585 -/*S_ROB1_19*/ { SPR_ROB1, 32779, 5, { NULL }, S_ROB1_20 }, //586 -/*S_ROB1_20*/ { SPR_ROB1, 32780, 5, { A_Fall }, S_ROB1_21 }, //587 -/*S_ROB1_21*/ { SPR_ROB1, 32781, 5, { NULL }, S_ROB1_22 }, //588 -/*S_ROB1_22*/ { SPR_ROB1, 32782, 5, { NULL }, S_ROB1_23 }, //589 -/*S_ROB1_23*/ { SPR_ROB1, 32783, 5, { NULL }, S_ROB1_24 }, //590 -/*S_ROB1_24*/ { SPR_ROB1, 32784, 6, { A_DeathExplode3 }, S_ROB1_25 }, //591 -/*S_ROB1_25*/ { SPR_ROB1, 17, -1, { NULL }, S_NULL }, //592 -/*S_ROB1_26*/ { SPR_ROB1, 32779, 5, { A_BodyParts }, S_ROB1_27 }, //593 -/*S_ROB1_27*/ { SPR_ROB1, 32780, 5, { A_XScream }, S_ROB1_28 }, //594 -/*S_ROB1_28*/ { SPR_ROB1, 32781, 5, { A_BodyParts }, S_ROB1_29 }, //595 -/*S_ROB1_29*/ { SPR_ROB1, 32782, 5, { A_Fall }, S_ROB1_30 }, //596 -/*S_ROB1_30*/ { SPR_ROB1, 32783, 5, { A_BodyParts }, S_ROB1_31 }, //597 -/*S_ROB1_31*/ { SPR_ROB1, 32784, 5, { A_DeathExplode3 }, S_ROB1_32 }, //598 -/*S_ROB1_32*/ { SPR_ROB1, 17, -1, { NULL }, S_NULL }, //599 -/*S_AGRD_01*/ { SPR_AGRD, 0, 5, { A_FriendLook }, S_AGRD_01 }, //600 -/*S_AGRD_02*/ { SPR_AGRD, 1, 8, { A_ShadowOff }, S_AGRD_01 }, //601 -/*S_AGRD_03*/ { SPR_AGRD, 3, 8, { NULL }, S_AGRD_01 }, //602 -/*S_AGRD_04*/ { SPR_AGRD, 0, 5, { A_RandomWalk }, S_AGRD_05 }, //603 -/*S_AGRD_05*/ { SPR_AGRD, 1, 5, { A_RandomWalk }, S_AGRD_06 }, //604 -/*S_AGRD_06*/ { SPR_AGRD, 2, 5, { A_RandomWalk }, S_AGRD_07 }, //605 -/*S_AGRD_07*/ { SPR_AGRD, 3, 5, { A_RandomWalk }, S_AGRD_08 }, //606 -/*S_AGRD_08*/ { SPR_AGRD, 0, 5, { A_RandomWalk }, S_AGRD_09 }, //607 -/*S_AGRD_09*/ { SPR_AGRD, 1, 5, { A_RandomWalk }, S_AGRD_10 }, //608 -/*S_AGRD_10*/ { SPR_AGRD, 2, 5, { A_RandomWalk }, S_AGRD_11 }, //609 -/*S_AGRD_11*/ { SPR_AGRD, 3, 5, { A_RandomWalk }, S_AGRD_01 }, //610 -/*S_AGRD_12*/ { SPR_AGRD, 0, 6, { A_ModifyVisibility }, S_AGRD_14 }, //611 -/*S_AGRD_13*/ { SPR_AGRD, 0, 6, { A_SetTLOptions }, S_AGRD_14 }, //612 -/*S_AGRD_14*/ { SPR_AGRD, 1, 6, { A_Chase }, S_AGRD_15 }, //613 -/*S_AGRD_15*/ { SPR_AGRD, 2, 6, { A_Chase }, S_AGRD_16 }, //614 -/*S_AGRD_16*/ { SPR_AGRD, 3, 6, { A_Chase }, S_AGRD_13 }, //615 -/*S_AGRD_17*/ { SPR_AGRD, 4, 8, { A_FaceTarget }, S_AGRD_18 }, //616 -/*S_AGRD_18*/ { SPR_AGRD, 5, 4, { A_BulletAttack }, S_AGRD_19 }, //617 -/*S_AGRD_19*/ { SPR_AGRD, 4, 4, { A_BulletAttack }, S_AGRD_20 }, //618 -/*S_AGRD_20*/ { SPR_AGRD, 5, 6, { A_BulletAttack }, S_AGRD_13 }, //619 -/*S_AGRD_21*/ { SPR_AGRD, 14, 0, { A_ShadowOn }, S_AGRD_22 }, //620 -/*S_AGRD_22*/ { SPR_AGRD, 14, 8, { A_Pain }, S_AGRD_12 }, //621 -/*S_AGRD_23*/ { SPR_AGRD, 14, 8, { A_Pain }, S_AGRD_13 }, //622 -/*S_AGRD_24*/ { SPR_AGRD, 6, 4, { NULL }, S_AGRD_25 }, //623 -/*S_AGRD_25*/ { SPR_AGRD, 7, 4, { A_Scream }, S_AGRD_26 }, //624 -/*S_AGRD_26*/ { SPR_AGRD, 8, 4, { NULL }, S_AGRD_27 }, //625 -/*S_AGRD_27*/ { SPR_AGRD, 9, 3, { NULL }, S_AGRD_28 }, //626 -/*S_AGRD_28*/ { SPR_AGRD, 10, 3, { A_Fall }, S_AGRD_29 }, //627 -/*S_AGRD_29*/ { SPR_AGRD, 11, 3, { NULL }, S_AGRD_30 }, //628 -/*S_AGRD_30*/ { SPR_AGRD, 12, 3, { A_AcolyteSpecial }, S_AGRD_31 }, //629 -/*S_AGRD_31*/ { SPR_AGRD, 13, 1400, { NULL }, S_GIBS_20 }, //630 -/*S_GIBS_10*/ { SPR_GIBS, 0, 5, { A_Fall }, S_GIBS_11 }, //631 -/*S_GIBS_11*/ { SPR_GIBS, 1, 5, { A_BodyParts }, S_GIBS_12 }, //632 -/*S_GIBS_12*/ { SPR_GIBS, 2, 5, { A_BodyParts }, S_GIBS_13 }, //633 -/*S_GIBS_13*/ { SPR_GIBS, 3, 4, { A_BodyParts }, S_GIBS_14 }, //634 -/*S_GIBS_14*/ { SPR_GIBS, 4, 4, { A_XScream }, S_GIBS_15 }, //635 -/*S_GIBS_15*/ { SPR_GIBS, 5, 4, { A_BodyParts }, S_GIBS_16 }, //636 -/*S_GIBS_16*/ { SPR_GIBS, 6, 4, { NULL }, S_GIBS_17 }, //637 -/*S_GIBS_17*/ { SPR_GIBS, 7, 4, { NULL }, S_GIBS_18 }, //638 -/*S_GIBS_18*/ { SPR_GIBS, 8, 5, { NULL }, S_GIBS_19 }, //639 -/*S_GIBS_19*/ { SPR_GIBS, 9, 5, { A_AcolyteSpecial }, S_GIBS_20 }, //640 -/*S_GIBS_20*/ { SPR_GIBS, 10, 5, { NULL }, S_GIBS_21 }, //641 -/*S_GIBS_21*/ { SPR_GIBS, 11, 1400, { NULL }, S_NULL }, //642 -/*S_PGRD_00*/ { SPR_PGRD, 0, 5, { A_FriendLook }, S_PGRD_00 }, //643 -/*S_PGRD_01*/ { SPR_PGRD, 1, 10, { NULL }, S_PGRD_00 }, //644 -/*S_PGRD_02*/ { SPR_PGRD, 2, 10, { NULL }, S_PGRD_00 }, //645 -/*S_PGRD_03*/ { SPR_PGRD, 1, 10, { A_RandomWalk }, S_PGRD_00 }, //646 -/*S_PGRD_04*/ { SPR_PGRD, 0, 3, { A_Chase }, S_PGRD_05 }, //647 -/*S_PGRD_05*/ { SPR_PGRD, 0, 3, { A_Chase }, S_PGRD_06 }, //648 -/*S_PGRD_06*/ { SPR_PGRD, 1, 3, { A_Chase }, S_PGRD_07 }, //649 -/*S_PGRD_07*/ { SPR_PGRD, 1, 3, { A_Chase }, S_PGRD_08 }, //650 -/*S_PGRD_08*/ { SPR_PGRD, 2, 3, { A_Chase }, S_PGRD_09 }, //651 -/*S_PGRD_09*/ { SPR_PGRD, 2, 3, { A_Chase }, S_PGRD_10 }, //652 -/*S_PGRD_10*/ { SPR_PGRD, 3, 3, { A_Chase }, S_PGRD_11 }, //653 -/*S_PGRD_11*/ { SPR_PGRD, 3, 3, { A_Chase }, S_PGRD_04 }, //654 -/*S_PGRD_12*/ { SPR_PGRD, 4, 8, { A_FaceTarget }, S_PGRD_13 }, //655 -/*S_PGRD_13*/ { SPR_PGRD, 5, 8, { A_RobotMelee }, S_PGRD_04 }, //656 -/*S_PGRD_14*/ { SPR_PGRD, 32774, 8, { A_FaceTarget }, S_PGRD_15 }, //657 -/*S_PGRD_15*/ { SPR_PGRD, 32775, 8, { A_TemplarMauler }, S_PGRD_04 }, //658 -/*S_PGRD_16*/ { SPR_PGRD, 0, 2, { NULL }, S_PGRD_17 }, //659 -/*S_PGRD_17*/ { SPR_PGRD, 0, 2, { A_Pain }, S_PGRD_04 }, //660 -/*S_PGRD_18*/ { SPR_PGRD, 32776, 4, { A_BodyParts }, S_PGRD_19 }, //661 -/*S_PGRD_19*/ { SPR_PGRD, 32777, 4, { A_Scream }, S_PGRD_20 }, //662 -/*S_PGRD_20*/ { SPR_PGRD, 32778, 4, { A_BodyParts }, S_PGRD_21 }, //663 -/*S_PGRD_21*/ { SPR_PGRD, 32779, 4, { A_Fall }, S_PGRD_22 }, //664 -/*S_PGRD_22*/ { SPR_PGRD, 32780, 4, { NULL }, S_PGRD_23 }, //665 -/*S_PGRD_23*/ { SPR_PGRD, 32781, 4, { NULL }, S_PGRD_24 }, //666 -/*S_PGRD_24*/ { SPR_PGRD, 14, 4, { A_BodyParts }, S_PGRD_25 }, //667 -/*S_PGRD_25*/ { SPR_PGRD, 15, 4, { NULL }, S_PGRD_26 }, //668 -/*S_PGRD_26*/ { SPR_PGRD, 16, 4, { NULL }, S_PGRD_27 }, //669 -/*S_PGRD_27*/ { SPR_PGRD, 17, 4, { NULL }, S_PGRD_28 }, //670 -/*S_PGRD_28*/ { SPR_PGRD, 18, 3, { NULL }, S_PGRD_29 }, //671 -/*S_PGRD_29*/ { SPR_PGRD, 19, 3, { NULL }, S_PGRD_30 }, //672 -/*S_PGRD_30*/ { SPR_PGRD, 20, 3, { NULL }, S_PGRD_31 }, //673 -/*S_PGRD_31*/ { SPR_PGRD, 21, 3, { NULL }, S_PGRD_32 }, //674 -/*S_PGRD_32*/ { SPR_PGRD, 22, 3, { NULL }, S_PGRD_33 }, //675 -/*S_PGRD_33*/ { SPR_PGRD, 23, 3, { NULL }, S_PGRD_34 }, //676 -/*S_PGRD_34*/ { SPR_PGRD, 24, 3, { NULL }, S_PGRD_35 }, //677 -/*S_PGRD_35*/ { SPR_PGRD, 25, 3, { NULL }, S_PGRD_36 }, //678 -/*S_PGRD_36*/ { SPR_PGRD, 26, 3, { NULL }, S_PGRD_37 }, //679 -/*S_PGRD_37*/ { SPR_PGRD, 27, -1, { NULL }, S_NULL }, //680 -/*S_ROB2_00*/ { SPR_ROB2, 16, 10, { A_Look }, S_ROB2_00 }, //681 -/*S_ROB2_01*/ { SPR_ROB2, 0, 3, { A_Chase }, S_ROB2_02 }, //682 -/*S_ROB2_02*/ { SPR_ROB2, 0, 3, { A_Chase }, S_ROB2_03 }, //683 -/*S_ROB2_03*/ { SPR_ROB2, 1, 3, { A_Chase }, S_ROB2_04 }, //684 -/*S_ROB2_04*/ { SPR_ROB2, 1, 3, { A_Chase }, S_ROB2_05 }, //685 -/*S_ROB2_05*/ { SPR_ROB2, 2, 3, { A_Chase }, S_ROB2_06 }, //686 -/*S_ROB2_06*/ { SPR_ROB2, 2, 3, { A_Chase }, S_ROB2_07 }, //687 -/*S_ROB2_07*/ { SPR_ROB2, 3, 3, { A_Chase }, S_ROB2_08 }, //688 -/*S_ROB2_08*/ { SPR_ROB2, 3, 3, { A_Chase }, S_ROB2_01 }, //689 -/*S_ROB2_09*/ { SPR_ROB2, 4, 3, { A_FaceTarget }, S_ROB2_10 }, //690 -/*S_ROB2_10*/ { SPR_ROB2, 32773, 2, { A_CrusaderAttack }, S_ROB2_11 }, //691 -/*S_ROB2_11*/ { SPR_ROB2, 32772, 2, { A_CrusaderLeft }, S_ROB2_12 }, //692 -/*S_ROB2_12*/ { SPR_ROB2, 32773, 3, { A_CrusaderLeft }, S_ROB2_13 }, //693 -/*S_ROB2_13*/ { SPR_ROB2, 32772, 2, { A_CrusaderLeft }, S_ROB2_14 }, //694 -/*S_ROB2_14*/ { SPR_ROB2, 32773, 2, { A_CrusaderLeft }, S_ROB2_15 }, //695 -/*S_ROB2_15*/ { SPR_ROB2, 32772, 2, { A_CrusaderRight }, S_ROB2_16 }, //696 -/*S_ROB2_16*/ { SPR_ROB2, 32773, 2, { A_CrusaderRight }, S_ROB2_17 }, //697 -/*S_ROB2_17*/ { SPR_ROB2, 32772, 2, { A_CrusaderRight }, S_ROB2_18 }, //698 -/*S_ROB2_18*/ { SPR_ROB2, 5, 2, { A_CheckTargetVisible2 }, S_ROB2_09 }, //699 -/*S_ROB2_19*/ { SPR_ROB2, 3, 1, { A_Pain }, S_ROB2_01 }, //700 -/*S_ROB2_20*/ { SPR_ROB2, 6, 3, { A_Scream }, S_ROB2_21 }, //701 -/*S_ROB2_21*/ { SPR_ROB2, 7, 5, { A_BodyParts }, S_ROB2_22 }, //702 -/*S_ROB2_22*/ { SPR_ROB2, 32776, 4, { A_BodyParts }, S_ROB2_23 }, //703 -/*S_ROB2_23*/ { SPR_ROB2, 32777, 4, { A_DeathExplode2 }, S_ROB2_24 }, //704 -/*S_ROB2_24*/ { SPR_ROB2, 32778, 4, { A_Fall }, S_ROB2_25 }, //705 -/*S_ROB2_25*/ { SPR_ROB2, 11, 4, { A_DeathExplode2 }, S_ROB2_26 }, //706 -/*S_ROB2_26*/ { SPR_ROB2, 12, 4, { A_BodyParts }, S_ROB2_27 }, //707 -/*S_ROB2_27*/ { SPR_ROB2, 13, 4, { A_BodyParts }, S_ROB2_28 }, //708 -/*S_ROB2_28*/ { SPR_ROB2, 14, 4, { A_DeathExplode2 }, S_ROB2_29 }, //709 -/*S_ROB2_29*/ { SPR_ROB2, 15, -1, { A_BossDeath }, S_NULL }, //710 -/*S_MLDR_00*/ { SPR_MLDR, 0, 10, { A_Look }, S_MLDR_00 }, //711 -/*S_MLDR_01*/ { SPR_MLDR, 0, 3, { A_Chase }, S_MLDR_02 }, //712 -/*S_MLDR_02*/ { SPR_MLDR, 0, 3, { A_Chase }, S_MLDR_03 }, //713 -/*S_MLDR_03*/ { SPR_MLDR, 1, 3, { A_Chase }, S_MLDR_04 }, //714 -/*S_MLDR_04*/ { SPR_MLDR, 1, 3, { A_Chase }, S_MLDR_05 }, //715 -/*S_MLDR_05*/ { SPR_MLDR, 2, 3, { A_Chase }, S_MLDR_06 }, //716 -/*S_MLDR_06*/ { SPR_MLDR, 2, 3, { A_Chase }, S_MLDR_07 }, //717 -/*S_MLDR_07*/ { SPR_MLDR, 3, 3, { A_Chase }, S_MLDR_08 }, //718 -/*S_MLDR_08*/ { SPR_MLDR, 3, 3, { A_Chase }, S_MLDR_01 }, //719 -/*S_MLDR_09*/ { SPR_MLDR, 4, 3, { A_FaceTarget }, S_MLDR_10 }, //720 -/*S_MLDR_10*/ { SPR_MLDR, 32773, 2, { A_BishopAttack }, S_MLDR_01 }, //721 -/*S_MLDR_11*/ { SPR_MLDR, 3, 1, { A_Pain }, S_MLDR_01 }, //722 -/*S_MLDR_12*/ { SPR_MLDR, 32774, 3, { NULL }, S_MLDR_13 }, //723 -/*S_MLDR_13*/ { SPR_MLDR, 32775, 5, { A_Scream }, S_MLDR_14 }, //724 -/*S_MLDR_14*/ { SPR_MLDR, 32776, 4, { A_BodyParts }, S_MLDR_15 }, //725 -/*S_MLDR_15*/ { SPR_MLDR, 32777, 4, { A_DeathExplode2 }, S_MLDR_16 }, //726 -/*S_MLDR_16*/ { SPR_MLDR, 32778, 4, { NULL }, S_MLDR_17 }, //727 -/*S_MLDR_17*/ { SPR_MLDR, 32779, 4, { NULL }, S_MLDR_18 }, //728 -/*S_MLDR_18*/ { SPR_MLDR, 32780, 4, { A_Fall }, S_MLDR_19 }, //729 -/*S_MLDR_19*/ { SPR_MLDR, 32781, 4, { NULL }, S_MLDR_20 }, //730 -/*S_MLDR_20*/ { SPR_MLDR, 32782, 4, { A_BodyParts }, S_MLDR_21 }, //731 -/*S_MLDR_21*/ { SPR_MLDR, 32783, 4, { NULL }, S_MLDR_22 }, //732 -/*S_MLDR_22*/ { SPR_MLDR, 32784, 4, { A_BodyParts }, S_MLDR_23 }, //733 -/*S_MLDR_23*/ { SPR_MLDR, 32785, 4, { NULL }, S_MLDR_24 }, //734 -/*S_MLDR_24*/ { SPR_MLDR, 32786, 4, { A_BodyParts }, S_MLDR_25 }, //735 -/*S_MLDR_25*/ { SPR_MLDR, 32787, 4, { NULL }, S_MLDR_26 }, //736 -/*S_MLDR_26*/ { SPR_MLDR, 32788, 4, { A_BodyParts }, S_MLDR_27 }, //737 -/*S_MLDR_27*/ { SPR_MLDR, 21, 4, { A_SpawnSpectreB }, S_NULL }, //738 -/*S_ORCL_00*/ { SPR_ORCL, 0, -1, { NULL }, S_NULL }, //739 -/*S_ORCL_01*/ { SPR_ORCL, 1, 5, { NULL }, S_ORCL_02 }, //740 -/*S_ORCL_02*/ { SPR_ORCL, 2, 5, { NULL }, S_ORCL_03 }, //741 -/*S_ORCL_03*/ { SPR_ORCL, 3, 5, { NULL }, S_ORCL_04 }, //742 -/*S_ORCL_04*/ { SPR_ORCL, 4, 5, { NULL }, S_ORCL_05 }, //743 -/*S_ORCL_05*/ { SPR_ORCL, 5, 5, { NULL }, S_ORCL_06 }, //744 -/*S_ORCL_06*/ { SPR_ORCL, 6, 5, { NULL }, S_ORCL_07 }, //745 -/*S_ORCL_07*/ { SPR_ORCL, 7, 5, { NULL }, S_ORCL_08 }, //746 -/*S_ORCL_08*/ { SPR_ORCL, 8, 5, { NULL }, S_ORCL_09 }, //747 -/*S_ORCL_09*/ { SPR_ORCL, 9, 5, { NULL }, S_ORCL_10 }, //748 -/*S_ORCL_10*/ { SPR_ORCL, 10, 5, { NULL }, S_ORCL_11 }, //749 -/*S_ORCL_11*/ { SPR_ORCL, 11, 5, { A_Fall }, S_ORCL_12 }, //750 -/*S_ORCL_12*/ { SPR_ORCL, 12, 5, { NULL }, S_ORCL_13 }, //751 -/*S_ORCL_13*/ { SPR_ORCL, 13, 5, { A_AlertSpectreC }, S_ORCL_14 }, //752 -/*S_ORCL_14*/ { SPR_ORCL, 14, 5, { NULL }, S_ORCL_15 }, //753 -/*S_ORCL_15*/ { SPR_ORCL, 15, 5, { NULL }, S_ORCL_16 }, //754 -/*S_ORCL_16*/ { SPR_ORCL, 16, -1, { NULL }, S_NULL }, //755 -/*S_PRST_00*/ { SPR_PRST, 0, 10, { A_Look }, S_PRST_01 }, //756 -/*S_PRST_01*/ { SPR_PRST, 1, 10, { A_FloatWeave }, S_PRST_00 }, //757 -/*S_PRST_02*/ { SPR_PRST, 0, 4, { A_Chase }, S_PRST_03 }, //758 -/*S_PRST_03*/ { SPR_PRST, 0, 4, { A_FloatWeave }, S_PRST_04 }, //759 -/*S_PRST_04*/ { SPR_PRST, 1, 4, { A_Chase }, S_PRST_05 }, //760 -/*S_PRST_05*/ { SPR_PRST, 1, 4, { A_FloatWeave }, S_PRST_06 }, //761 -/*S_PRST_06*/ { SPR_PRST, 2, 4, { A_Chase }, S_PRST_07 }, //762 -/*S_PRST_07*/ { SPR_PRST, 2, 4, { A_FloatWeave }, S_PRST_08 }, //763 -/*S_PRST_08*/ { SPR_PRST, 3, 4, { A_Chase }, S_PRST_09 }, //764 -/*S_PRST_09*/ { SPR_PRST, 3, 4, { A_FloatWeave }, S_PRST_02 }, //765 -/*S_PRST_10*/ { SPR_PRST, 4, 4, { A_FaceTarget }, S_PRST_11 }, //766 -/*S_PRST_11*/ { SPR_PRST, 5, 4, { A_BossMeleeAtk }, S_PRST_12 }, //767 -/*S_PRST_12*/ { SPR_PRST, 4, 4, { A_FloatWeave }, S_PRST_02 }, //768 -/*S_PRST_13*/ { SPR_PRST, 4, 4, { A_FaceTarget }, S_PRST_14 }, //769 -/*S_PRST_14*/ { SPR_PRST, 5, 4, { A_FireHookShot }, S_PRST_15 }, //770 -/*S_PRST_15*/ { SPR_PRST, 4, 4, { A_FloatWeave }, S_PRST_02 }, //771 -/*S_PDED_00*/ { SPR_PDED, 0, 6, { NULL }, S_PDED_01 }, //772 -/*S_PDED_01*/ { SPR_PDED, 1, 6, { A_Scream }, S_PDED_02 }, //773 -/*S_PDED_02*/ { SPR_PDED, 2, 6, { NULL }, S_PDED_03 }, //774 -/*S_PDED_03*/ { SPR_PDED, 3, 6, { A_Fall }, S_PDED_04 }, //775 -/*S_PDED_04*/ { SPR_PDED, 4, 6, { NULL }, S_PDED_05 }, //776 -/*S_PDED_05*/ { SPR_PDED, 5, 5, { NULL }, S_PDED_06 }, //777 -/*S_PDED_06*/ { SPR_PDED, 6, 5, { NULL }, S_PDED_07 }, //778 -/*S_PDED_07*/ { SPR_PDED, 7, 5, { NULL }, S_PDED_08 }, //779 -/*S_PDED_08*/ { SPR_PDED, 8, 5, { NULL }, S_PDED_09 }, //780 -/*S_PDED_09*/ { SPR_PDED, 9, 5, { NULL }, S_PDED_10 }, //781 -/*S_PDED_10*/ { SPR_PDED, 8, 5, { NULL }, S_PDED_11 }, //782 -/*S_PDED_11*/ { SPR_PDED, 9, 5, { NULL }, S_PDED_12 }, //783 -/*S_PDED_12*/ { SPR_PDED, 8, 5, { NULL }, S_PDED_14 }, //784 -/*S_PDED_13*/ { SPR_PDED, 9, 5, { NULL }, S_PDED_14 }, //785 -/*S_PDED_14*/ { SPR_PDED, 10, 5, { NULL }, S_PDED_15 }, //786 -/*S_PDED_15*/ { SPR_PDED, 11, 5, { NULL }, S_PDED_16 }, //787 -/*S_PDED_16*/ { SPR_PDED, 12, 4, { NULL }, S_PDED_17 }, //788 -/*S_PDED_17*/ { SPR_PDED, 13, 4, { NULL }, S_PDED_18 }, //789 -/*S_PDED_18*/ { SPR_PDED, 14, 4, { NULL }, S_PDED_19 }, //790 -/*S_PDED_19*/ { SPR_PDED, 15, 4, { NULL }, S_PDED_20 }, //791 -/*S_PDED_20*/ { SPR_PDED, 16, 4, { A_SpawnSpectreE }, S_PDED_21 }, //792 -/*S_PDED_21*/ { SPR_PDED, 17, 4, { NULL }, S_PDED_22 }, //793 -/*S_PDED_22*/ { SPR_PDED, 18, 4, { NULL }, S_PDED_23 }, //794 -/*S_PDED_23*/ { SPR_PDED, 19, -1, { NULL }, S_NULL }, //795 -/*S_ALN1_00*/ { SPR_ALN1, 0, 10, { A_Look }, S_ALN1_01 }, //796 -/*S_ALN1_01*/ { SPR_ALN1, 1, 10, { A_FloatWeave }, S_ALN1_00 }, //797 -/*S_ALN1_02*/ { SPR_ALN1, 32768, 4, { A_Chase }, S_ALN1_03 }, //798 -/*S_ALN1_03*/ { SPR_ALN1, 32769, 4, { A_Chase }, S_ALN1_04 }, //799 -/*S_ALN1_04*/ { SPR_ALN1, 32770, 4, { A_FloatWeave }, S_ALN1_05 }, //800 -/*S_ALN1_05*/ { SPR_ALN1, 32771, 4, { A_Chase }, S_ALN1_06 }, //801 -/*S_ALN1_06*/ { SPR_ALN1, 32772, 4, { A_Chase }, S_ALN1_07 }, //802 -/*S_ALN1_07*/ { SPR_ALN1, 32773, 4, { A_Chase }, S_ALN1_08 }, //803 -/*S_ALN1_08*/ { SPR_ALN1, 32774, 4, { A_FloatWeave }, S_ALN1_09 }, //804 -/*S_ALN1_09*/ { SPR_ALN1, 32775, 4, { A_Chase }, S_ALN1_10 }, //805 -/*S_ALN1_10*/ { SPR_ALN1, 32776, 4, { A_Chase }, S_ALN1_11 }, //806 -/*S_ALN1_11*/ { SPR_ALN1, 32777, 4, { A_Chase }, S_ALN1_12 }, //807 -/*S_ALN1_12*/ { SPR_ALN1, 32778, 4, { A_FloatWeave }, S_ALN1_02 }, //808 -/*S_ALN1_13*/ { SPR_ALN1, 32777, 4, { A_FaceTarget }, S_ALN1_14 }, //809 -/*S_ALN1_14*/ { SPR_ALN1, 32776, 4, { A_BossMeleeAtk }, S_ALN1_15 }, //810 -/*S_ALN1_15*/ { SPR_ALN1, 32775, 4, { NULL }, S_ALN1_04 }, //811 -/*S_ALN1_16*/ { SPR_ALN1, 32777, 4, { A_FaceTarget }, S_ALN1_17 }, //812 -/*S_ALN1_17*/ { SPR_ALN1, 32776, 4, { A_ProgrammerAttack }, S_ALN1_18 }, //813 -/*S_ALN1_18*/ { SPR_ALN1, 32775, 4, { NULL }, S_ALN1_12 }, //814 -/*S_ALN1_19*/ { SPR_ALN1, 9, 2, { A_Pain }, S_ALN1_08 }, //815 -/*S_AL1P_00*/ { SPR_AL1P, 32768, 6, { A_NodeChunk }, S_AL1P_01 }, //816 -/*S_AL1P_01*/ { SPR_AL1P, 32769, 6, { A_Scream }, S_AL1P_02 }, //817 -/*S_AL1P_02*/ { SPR_AL1P, 32770, 6, { A_NodeChunk }, S_AL1P_03 }, //818 -/*S_AL1P_03*/ { SPR_AL1P, 32771, 6, { NULL }, S_AL1P_04 }, //819 -/*S_AL1P_04*/ { SPR_AL1P, 32772, 6, { NULL }, S_AL1P_05 }, //820 -/*S_AL1P_05*/ { SPR_AL1P, 32773, 6, { A_NodeChunk }, S_AL1P_06 }, //821 -/*S_AL1P_06*/ { SPR_AL1P, 32774, 6, { NULL }, S_AL1P_07 }, //822 -/*S_AL1P_07*/ { SPR_AL1P, 32775, 6, { A_NodeChunk }, S_AL1P_08 }, //823 -/*S_AL1P_08*/ { SPR_AL1P, 32776, 6, { NULL }, S_AL1P_09 }, //824 -/*S_AL1P_09*/ { SPR_AL1P, 32777, 6, { NULL }, S_AL1P_10 }, //825 -/*S_AL1P_10*/ { SPR_AL1P, 32778, 6, { NULL }, S_AL1P_11 }, //826 -/*S_AL1P_11*/ { SPR_AL1P, 32779, 5, { NULL }, S_AL1P_12 }, //827 -/*S_AL1P_12*/ { SPR_AL1P, 32780, 5, { NULL }, S_AL1P_13 }, //828 -/*S_AL1P_13*/ { SPR_AL1P, 32781, 5, { A_HeadChunk }, S_AL1P_14 }, //829 -/*S_AL1P_14*/ { SPR_AL1P, 32782, 5, { NULL }, S_AL1P_15 }, //830 -/*S_AL1P_15*/ { SPR_AL1P, 32783, 5, { NULL }, S_AL1P_16 }, //831 -/*S_AL1P_16*/ { SPR_AL1P, 32784, 5, { NULL }, S_AL1P_17 }, //832 -/*S_AL1P_17*/ { SPR_AL1P, 32785, 5, { A_BossDeath }, S_NULL }, //833 -/*S_NODE_00*/ { SPR_NODE, 32768, 6, { NULL }, S_NODE_01 }, //834 -/*S_NODE_01*/ { SPR_NODE, 32769, 6, { NULL }, S_NODE_02 }, //835 -/*S_NODE_02*/ { SPR_NODE, 32770, 6, { NULL }, S_NODE_03 }, //836 -/*S_NODE_03*/ { SPR_NODE, 32771, 6, { NULL }, S_NODE_04 }, //837 -/*S_NODE_04*/ { SPR_NODE, 32772, 6, { NULL }, S_NODE_05 }, //838 -/*S_NODE_05*/ { SPR_NODE, 32773, 6, { NULL }, S_NODE_06 }, //839 -/*S_NODE_06*/ { SPR_NODE, 32774, 6, { NULL }, S_NULL }, //840 -/*S_MTHD_00*/ { SPR_MTHD, 32768, 5, { NULL }, S_MTHD_01 }, //841 -/*S_MTHD_01*/ { SPR_MTHD, 32769, 5, { NULL }, S_MTHD_02 }, //842 -/*S_MTHD_02*/ { SPR_MTHD, 32770, 5, { NULL }, S_MTHD_03 }, //843 -/*S_MTHD_03*/ { SPR_MTHD, 32771, 5, { NULL }, S_MTHD_04 }, //844 -/*S_MTHD_04*/ { SPR_MTHD, 32772, 5, { NULL }, S_MTHD_05 }, //845 -/*S_MTHD_05*/ { SPR_MTHD, 32773, 5, { NULL }, S_MTHD_06 }, //846 -/*S_MTHD_06*/ { SPR_MTHD, 32774, 5, { NULL }, S_MTHD_07 }, //847 -/*S_MTHD_07*/ { SPR_MTHD, 32775, 5, { NULL }, S_MTHD_08 }, //848 -/*S_MTHD_08*/ { SPR_MTHD, 32776, 5, { NULL }, S_MTHD_09 }, //849 -/*S_MTHD_09*/ { SPR_MTHD, 32777, 5, { NULL }, S_MTHD_10 }, //850 -/*S_MTHD_10*/ { SPR_MTHD, 32778, 5, { NULL }, S_NULL }, //851 -/*S_ALN1_20*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_21 }, //852 -/*S_ALN1_21*/ { SPR_ALN1, 8, 4, { A_FireSigilEOffshoot }, S_ALN1_22 }, //853 -/*S_ALN1_22*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_12 }, //854 -/*S_ALN1_23*/ { SPR_ALN1, 0, 5, { A_FloatWeave }, S_ALN1_24 }, //855 -/*S_ALN1_24*/ { SPR_ALN1, 1, 5, { A_FloatWeave }, S_ALN1_25 }, //856 -/*S_ALN1_25*/ { SPR_ALN1, 2, 5, { A_FloatWeave }, S_ALN1_26 }, //857 -/*S_ALN1_26*/ { SPR_ALN1, 3, 5, { A_FloatWeave }, S_ALN1_27 }, //858 -/*S_ALN1_27*/ { SPR_ALN1, 4, 5, { A_FloatWeave }, S_ALN1_28 }, //859 -/*S_ALN1_28*/ { SPR_ALN1, 5, 5, { A_FloatWeave }, S_ALN1_29 }, //860 -/*S_ALN1_29*/ { SPR_ALN1, 6, 5, { A_FloatWeave }, S_ALN1_30 }, //861 -/*S_ALN1_30*/ { SPR_ALN1, 7, 5, { A_FloatWeave }, S_ALN1_31 }, //862 -/*S_ALN1_31*/ { SPR_ALN1, 8, 5, { A_FloatWeave }, S_ALN1_32 }, //863 -/*S_ALN1_32*/ { SPR_ALN1, 9, 5, { A_FloatWeave }, S_ALN1_33 }, //864 -/*S_ALN1_33*/ { SPR_ALN1, 10, 5, { A_FloatWeave }, S_ALN1_23 }, //865 -/*S_ALN1_34*/ { SPR_ALN1, 0, 5, { A_Chase }, S_ALN1_35 }, //866 -/*S_ALN1_35*/ { SPR_ALN1, 1, 5, { A_Chase }, S_ALN1_36 }, //867 -/*S_ALN1_36*/ { SPR_ALN1, 2, 5, { A_FloatWeave }, S_ALN1_37 }, //868 -/*S_ALN1_37*/ { SPR_ALN1, 3, 5, { A_Chase }, S_ALN1_38 }, //869 -/*S_ALN1_38*/ { SPR_ALN1, 4, 5, { A_Chase }, S_ALN1_39 }, //870 -/*S_ALN1_39*/ { SPR_ALN1, 5, 5, { A_Chase }, S_ALN1_40 }, //871 -/*S_ALN1_40*/ { SPR_ALN1, 6, 5, { A_FloatWeave }, S_ALN1_41 }, //872 -/*S_ALN1_41*/ { SPR_ALN1, 7, 5, { A_Chase }, S_ALN1_42 }, //873 -/*S_ALN1_42*/ { SPR_ALN1, 8, 5, { A_Chase }, S_ALN1_43 }, //874 -/*S_ALN1_43*/ { SPR_ALN1, 9, 5, { A_Chase }, S_ALN1_44 }, //875 -/*S_ALN1_44*/ { SPR_ALN1, 10, 5, { A_FloatWeave }, S_ALN1_34 }, //876 -/*S_ALN1_45*/ { SPR_ALN1, 9, 4, { A_FaceTarget }, S_ALN1_46 }, //877 -/*S_ALN1_46*/ { SPR_ALN1, 8, 4, { A_BossMeleeAtk }, S_ALN1_47 }, //878 -/*S_ALN1_47*/ { SPR_ALN1, 2, 4, { NULL }, S_ALN1_36 }, //879 -/*S_ALN1_48*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_49 }, //880 -/*S_ALN1_49*/ { SPR_ALN1, 8, 4, { A_SpectreCAttack }, S_ALN1_50 }, //881 -/*S_ALN1_50*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_44 }, //882 -/*S_ALN1_51*/ { SPR_ALN1, 9, 2, { A_Pain }, S_ALN1_40 }, //883 -/*S_ALN1_52*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_53 }, //884 -/*S_ALN1_53*/ { SPR_ALN1, 8, 4, { A_SpectreDAttack }, S_ALN1_54 }, //885 -/*S_ALN1_54*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_12 }, //886 -/*S_ALN1_55*/ { SPR_ALN1, 5, 4, { A_FaceTarget }, S_ALN1_56 }, //887 -/*S_ALN1_56*/ { SPR_ALN1, 8, 4, { A_SpectreEAttack }, S_ALN1_57 }, //888 -/*S_ALN1_57*/ { SPR_ALN1, 4, 4, { NULL }, S_ALN1_12 }, //889 -/*S_MNAM_00*/ { SPR_MNAM, 0, 100, { A_FloatWeave }, S_MNAM_01 }, //890 -/*S_MNAM_01*/ { SPR_MNAM, 32769, 60, { A_FloatWeave }, S_MNAM_02 }, //891 -/*S_MNAM_02*/ { SPR_MNAM, 32770, 4, { A_FloatWeave }, S_MNAM_03 }, //892 -/*S_MNAM_03*/ { SPR_MNAM, 32771, 4, { A_FloatWeave }, S_MNAM_04 }, //893 -/*S_MNAM_04*/ { SPR_MNAM, 32772, 4, { A_FloatWeave }, S_MNAM_05 }, //894 -/*S_MNAM_05*/ { SPR_MNAM, 32773, 4, { A_FloatWeave }, S_MNAM_06 }, //895 -/*S_MNAM_06*/ { SPR_MNAM, 32774, 4, { A_FloatWeave }, S_MNAM_07 }, //896 -/*S_MNAM_07*/ { SPR_MNAM, 32775, 4, { A_FloatWeave }, S_MNAM_08 }, //897 -/*S_MNAM_08*/ { SPR_MNAM, 32776, 4, { A_FloatWeave }, S_MNAM_09 }, //898 -/*S_MNAM_09*/ { SPR_MNAM, 32777, 4, { A_FloatWeave }, S_MNAM_10 }, //899 -/*S_MNAM_10*/ { SPR_MNAM, 32778, 4, { A_FloatWeave }, S_MNAM_11 }, //900 -/*S_MNAM_11*/ { SPR_MNAM, 32779, 4, { A_FloatWeave }, S_MNAL_00 }, //901 -/*S_MNAL_00*/ { SPR_MNAL, 32768, 4, { A_Look }, S_MNAL_01 }, //902 -/*S_MNAL_01*/ { SPR_MNAL, 32769, 4, { A_FloatWeave }, S_MNAL_00 }, //903 -/*S_MNAL_02*/ { SPR_MNAL, 32768, 4, { A_Chase }, S_MNAL_03 }, //904 -/*S_MNAL_03*/ { SPR_MNAL, 32769, 4, { A_Chase }, S_MNAL_04 }, //905 -/*S_MNAL_04*/ { SPR_MNAL, 32770, 4, { A_FloatWeave }, S_MNAL_05 }, //906 -/*S_MNAL_05*/ { SPR_MNAL, 32771, 4, { A_Chase }, S_MNAL_06 }, //907 -/*S_MNAL_06*/ { SPR_MNAL, 32772, 4, { A_Chase }, S_MNAL_07 }, //908 -/*S_MNAL_07*/ { SPR_MNAL, 32773, 4, { A_Chase }, S_MNAL_08 }, //909 -/*S_MNAL_08*/ { SPR_MNAL, 32774, 4, { A_FloatWeave }, S_MNAL_09 }, //910 -/*S_MNAL_09*/ { SPR_MNAL, 32775, 4, { A_Chase }, S_MNAL_10 }, //911 -/*S_MNAL_10*/ { SPR_MNAL, 32776, 4, { A_Chase }, S_MNAL_11 }, //912 -/*S_MNAL_11*/ { SPR_MNAL, 32777, 4, { A_Chase }, S_MNAL_12 }, //913 -/*S_MNAL_12*/ { SPR_MNAL, 32778, 4, { A_FloatWeave }, S_MNAL_02 }, //914 -/*S_MNAL_13*/ { SPR_MNAL, 32777, 4, { A_FaceTarget }, S_MNAL_14 }, //915 -/*S_MNAL_14*/ { SPR_MNAL, 32776, 4, { A_BossMeleeAtk }, S_MNAL_15 }, //916 -/*S_MNAL_15*/ { SPR_MNAL, 32770, 4, { NULL }, S_MNAL_04 }, //917 -/*S_MNAL_16*/ { SPR_MNAL, 32773, 4, { A_FaceTarget }, S_MNAL_17 }, //918 -/*S_MNAL_17*/ { SPR_MNAL, 32776, 4, { A_FireSigilWeapon }, S_MNAL_18 }, //919 -/*S_MNAL_18*/ { SPR_MNAL, 32772, 4, { NULL }, S_MNAL_12 }, //920 -/*S_MNAL_19*/ { SPR_MNAL, 32777, 2, { A_Pain }, S_MNAL_08 }, //921 -/*S_MNAL_20*/ { SPR_MNAL, 32779, 7, { A_NodeChunk }, S_MNAL_21 }, //922 -/*S_MNAL_21*/ { SPR_MNAL, 32780, 7, { A_Scream }, S_MNAL_22 }, //923 -/*S_MNAL_22*/ { SPR_MNAL, 32781, 7, { A_NodeChunk }, S_MNAL_23 }, //924 -/*S_MNAL_23*/ { SPR_MNAL, 32782, 7, { A_NodeChunk }, S_MNAL_24 }, //925 -/*S_MNAL_24*/ { SPR_MNAL, 32783, 7, { A_HeadChunk }, S_MNAL_25 }, //926 -/*S_MNAL_25*/ { SPR_MNAL, 32784, 64, { A_NodeChunk }, S_MNAL_26 }, //927 -/*S_MNAL_26*/ { SPR_MNAL, 32784, 6, { A_EntityDeath }, S_NULL }, //928 -/*S_MNAL_27*/ { SPR_MNAL, 32785, 10, { A_Look }, S_MNAL_27 }, //929 -/*S_MNAL_28*/ { SPR_MNAL, 32785, 5, { A_FloatWeave }, S_MNAL_29 }, //930 -/*S_MNAL_29*/ { SPR_MNAL, 32786, 5, { A_Chase }, S_MNAL_30 }, //931 -/*S_MNAL_30*/ { SPR_MNAL, 32787, 5, { A_Chase }, S_MNAL_31 }, //932 -/*S_MNAL_31*/ { SPR_MNAL, 32788, 5, { A_FloatWeave }, S_MNAL_32 }, //933 -/*S_MNAL_32*/ { SPR_MNAL, 32789, 5, { A_Chase }, S_MNAL_33 }, //934 -/*S_MNAL_33*/ { SPR_MNAL, 32790, 5, { A_FloatWeave }, S_MNAL_28 }, //935 -/*S_MNAL_34*/ { SPR_MNAL, 32786, 4, { A_FaceTarget }, S_MNAL_35 }, //936 -/*S_MNAL_35*/ { SPR_MNAL, 32785, 4, { A_BossMeleeAtk }, S_MNAL_36 }, //937 -/*S_MNAL_36*/ { SPR_MNAL, 32787, 4, { A_FloatWeave }, S_MNAL_29 }, //938 -/*S_MNAL_37*/ { SPR_MNAL, 32790, 4, { A_FaceTarget }, S_MNAL_38 }, //939 -/*S_MNAL_38*/ { SPR_MNAL, 32788, 4, { A_FireSigilEOffshoot }, S_MNAL_39 }, //940 -/*S_MNAL_39*/ { SPR_MNAL, 32789, 4, { A_FloatWeave }, S_MNAL_32 }, //941 -/*S_MNAL_40*/ { SPR_MNAL, 32785, 2, { A_Pain }, S_MNAL_28 }, //942 -/*S_MDTH_00*/ { SPR_MDTH, 32768, 3, { A_Scream }, S_MDTH_01 }, //943 -/*S_MDTH_01*/ { SPR_MDTH, 32769, 3, { A_BodyParts }, S_MDTH_02 }, //944 -/*S_MDTH_02*/ { SPR_MDTH, 32770, 3, { A_Fall }, S_MDTH_03 }, //945 -/*S_MDTH_03*/ { SPR_MDTH, 32771, 3, { A_BodyParts }, S_MDTH_04 }, //946 -/*S_MDTH_04*/ { SPR_MDTH, 32772, 3, { A_BodyParts }, S_MDTH_05 }, //947 -/*S_MDTH_05*/ { SPR_MDTH, 32773, 3, { A_BodyParts }, S_MDTH_06 }, //948 -/*S_MDTH_06*/ { SPR_MDTH, 32774, 3, { A_BodyParts }, S_MDTH_07 }, //949 -/*S_MDTH_07*/ { SPR_MDTH, 32775, 3, { A_BodyParts }, S_MDTH_08 }, //950 -/*S_MDTH_08*/ { SPR_MDTH, 32776, 3, { A_BodyParts }, S_MDTH_09 }, //951 -/*S_MDTH_09*/ { SPR_MDTH, 32777, 3, { A_BodyParts }, S_MDTH_10 }, //952 -/*S_MDTH_10*/ { SPR_MDTH, 32778, 3, { A_BodyParts }, S_MDTH_11 }, //953 -/*S_MDTH_11*/ { SPR_MDTH, 32779, 3, { A_BodyParts }, S_MDTH_12 }, //954 -/*S_MDTH_12*/ { SPR_MDTH, 32780, 3, { A_BodyParts }, S_MDTH_13 }, //955 -/*S_MDTH_13*/ { SPR_MDTH, 32781, 3, { A_BodyParts }, S_MDTH_14 }, //956 -/*S_MDTH_14*/ { SPR_MDTH, 32782, 3, { A_BossDeath }, S_NULL }, //957 -/*S_NEST_00*/ { SPR_NEST, 0, -1, { NULL }, S_NULL }, //958 -/*S_PODD_00*/ { SPR_PODD, 0, 60, { A_Look }, S_PODD_00 }, //959 -/*S_PODD_01*/ { SPR_PODD, 0, 360, { NULL }, S_PODD_02 }, //960 -/*S_PODD_02*/ { SPR_PODD, 1, 9, { A_Fall }, S_PODD_03 }, //961 -/*S_PODD_03*/ { SPR_PODD, 2, 9, { NULL }, S_PODD_04 }, //962 -/*S_PODD_04*/ { SPR_PODD, 3, 9, { A_SpawnEntity }, S_PODD_05 }, //963 -/*S_PODD_05*/ { SPR_PODD, 4, -1, { NULL }, S_NULL }, //964 -/*S_ZAP6_00*/ { SPR_ZAP6, 32768, 4, { NULL }, S_ZAP6_01 }, //965 -/*S_ZAP6_01*/ { SPR_ZAP6, 32769, 4, { A_SigilTrail }, S_ZAP6_02 }, //966 -/*S_ZAP6_02*/ { SPR_ZAP6, 32770, 4, { A_SigilTrail }, S_ZAP6_00 }, //967 -/*S_ZOT3_00*/ { SPR_ZOT3, 32768, 4, { NULL }, S_ZOT3_01 }, //968 -/*S_ZOT3_01*/ { SPR_ZOT3, 32769, 4, { NULL }, S_ZOT3_02 }, //969 -/*S_ZOT3_02*/ { SPR_ZOT3, 32770, 4, { NULL }, S_ZOT3_03 }, //970 -/*S_ZOT3_03*/ { SPR_ZOT3, 32771, 4, { NULL }, S_ZOT3_04 }, //971 -/*S_ZOT3_04*/ { SPR_ZOT3, 32772, 4, { NULL }, S_ZOT3_00 }, //972 -/*S_ZAP6_03*/ { SPR_ZAP6, 32768, 5, { NULL }, S_ZAP6_04 }, //973 -/*S_ZAP6_04*/ { SPR_ZAP6, 32769, 5, { NULL }, S_ZAP6_05 }, //974 -/*S_ZAP6_05*/ { SPR_ZAP6, 32770, 5, { NULL }, S_NULL }, //975 -/*S_ZAP7_00*/ { SPR_ZAP7, 32768, 4, { A_Sigil_E_Action }, S_ZAP7_01 }, //976 -/*S_ZAP7_01*/ { SPR_ZAP7, 32769, 4, { A_Sigil_E_Action }, S_ZAP7_02 }, //977 -/*S_ZAP7_02*/ { SPR_ZAP7, 32770, 6, { A_Sigil_E_Action }, S_ZAP7_03 }, //978 -/*S_ZAP7_03*/ { SPR_ZAP7, 32771, 6, { A_Sigil_E_Action }, S_ZAP7_04 }, //979 -/*S_ZAP7_04*/ { SPR_ZAP7, 32772, 6, { A_Sigil_E_Action }, S_ZAP7_00 }, //980 -/*S_ZOT1_00*/ { SPR_ZOT1, 32768, 4, { NULL }, S_ZOT1_01 }, //981 -/*S_ZOT1_01*/ { SPR_ZOT1, 32769, 4, { NULL }, S_ZOT1_02 }, //982 -/*S_ZOT1_02*/ { SPR_ZOT1, 32770, 6, { NULL }, S_ZOT1_03 }, //983 -/*S_ZOT1_03*/ { SPR_ZOT1, 32771, 6, { NULL }, S_ZOT1_04 }, //984 -/*S_ZOT1_04*/ { SPR_ZOT1, 32771, 6, { NULL }, S_ZOT1_00 }, //985 -/*S_ZAP5_00*/ { SPR_ZAP5, 32768, 4, { A_MissileTick }, S_ZAP5_01 }, //986 -/*S_ZAP5_01*/ { SPR_ZAP5, 32769, 4, { A_Sigil_A_Action }, S_ZAP5_02 }, //987 -/*S_ZAP5_02*/ { SPR_ZAP5, 32770, 4, { A_MissileTick }, S_ZAP5_03 }, //988 -/*S_ZAP5_03*/ { SPR_ZAP5, 32771, 4, { A_MissileTick }, S_ZAP5_00 }, //989 -/*S_ZOT2_00*/ { SPR_ZOT2, 32768, 4, { A_Tracer }, S_ZOT2_01 }, //990 -/*S_ZOT2_01*/ { SPR_ZOT2, 32769, 4, { A_Tracer }, S_ZOT2_02 }, //991 -/*S_ZOT2_02*/ { SPR_ZOT2, 32770, 6, { A_Tracer }, S_ZOT2_03 }, //992 -/*S_ZOT2_03*/ { SPR_ZOT2, 32771, 6, { A_Tracer }, S_ZOT2_04 }, //993 -/*S_ZOT2_04*/ { SPR_ZOT2, 32772, 5, { A_Tracer }, S_ZOT2_00 }, //994 -/*S_SEWR_00*/ { SPR_SEWR, 0, 10, { A_Look }, S_SEWR_00 }, //995 -/*S_SEWR_01*/ { SPR_SEWR, 0, 6, { A_FloatWeave }, S_SEWR_02 }, //996 -/*S_SEWR_02*/ { SPR_SEWR, 0, 6, { A_Chase }, S_SEWR_01 }, //997 -/*S_SEWR_03*/ { SPR_SEWR, 1, 4, { A_FaceTarget }, S_SEWR_04 }, //998 -/*S_SEWR_04*/ { SPR_SEWR, 32770, 8, { A_SentinelAttack }, S_SEWR_05 }, //999 -/*S_SEWR_05*/ { SPR_SEWR, 32770, 4, { A_CheckTargetVisible }, S_SEWR_04 }, //1000 -/*S_SEWR_06*/ { SPR_SEWR, 3, 5, { A_Pain }, S_SEWR_05 }, //1001 -/*S_SEWR_07*/ { SPR_SEWR, 3, 7, { A_Fall }, S_SEWR_08 }, //1002 -/*S_SEWR_08*/ { SPR_SEWR, 32772, 8, { A_BodyParts }, S_SEWR_09 }, //1003 -/*S_SEWR_09*/ { SPR_SEWR, 32773, 5, { A_Scream }, S_SEWR_10 }, //1004 -/*S_SEWR_10*/ { SPR_SEWR, 32774, 4, { A_BodyParts }, S_SEWR_11 }, //1005 -/*S_SEWR_11*/ { SPR_SEWR, 32775, 4, { A_BodyParts }, S_SEWR_12 }, //1006 -/*S_SEWR_12*/ { SPR_SEWR, 8, 4, { NULL }, S_SEWR_13 }, //1007 -/*S_SEWR_13*/ { SPR_SEWR, 9, 5, { NULL }, S_NULL }, //1008 -/*S_SPID_00*/ { SPR_SPID, 0, 1, { A_StalkerSetLook }, S_SPID_00 }, //1009 -/*S_SPID_01*/ { SPR_SPID, 0, 10, { A_Look }, S_SPID_01 }, //1010 -/*S_SPID_02*/ { SPR_SPID, 9, 10, { A_Look }, S_SPID_02 }, //1011 -/*S_SPID_03*/ { SPR_SPID, 0, 1, { A_StalkerThink }, S_SPID_04 }, //1012 -/*S_SPID_04*/ { SPR_SPID, 0, 3, { A_Chase }, S_SPID_05 }, //1013 -/*S_SPID_05*/ { SPR_SPID, 1, 3, { A_Chase }, S_SPID_06 }, //1014 -/*S_SPID_06*/ { SPR_SPID, 1, 3, { A_Chase }, S_SPID_07 }, //1015 -/*S_SPID_07*/ { SPR_SPID, 2, 3, { A_StalkerChase }, S_SPID_08 }, //1016 -/*S_SPID_08*/ { SPR_SPID, 2, 3, { A_Chase }, S_SPID_03 }, //1017 -/*S_SPID_09*/ { SPR_SPID, 9, 3, { A_FaceTarget }, S_SPID_10 }, //1018 -/*S_SPID_10*/ { SPR_SPID, 10, 3, { A_StalkerScratch }, S_SPID_18 }, //1019 -/*S_SPID_11*/ { SPR_SPID, 2, 2, { A_StalkerDrop }, S_SPID_12 }, //1020 -/*S_SPID_12*/ { SPR_SPID, 8, 3, { NULL }, S_SPID_13 }, //1021 -/*S_SPID_13*/ { SPR_SPID, 7, 3, { NULL }, S_SPID_14 }, //1022 -/*S_SPID_14*/ { SPR_SPID, 6, 3, { NULL }, S_SPID_15 }, //1023 -/*S_SPID_15*/ { SPR_SPID, 5, 3, { NULL }, S_SPID_16 }, //1024 -/*S_SPID_16*/ { SPR_SPID, 4, 3, { NULL }, S_SPID_17 }, //1025 -/*S_SPID_17*/ { SPR_SPID, 3, 3, { NULL }, S_SPID_09 }, //1026 -/*S_SPID_18*/ { SPR_SPID, 9, 3, { A_StalkerChase }, S_SPID_19 }, //1027 -/*S_SPID_19*/ { SPR_SPID, 9, 3, { A_Chase }, S_SPID_20 }, //1028 -/*S_SPID_20*/ { SPR_SPID, 10, 3, { A_Chase }, S_SPID_21 }, //1029 -/*S_SPID_21*/ { SPR_SPID, 10, 3, { A_Chase }, S_SPID_22 }, //1030 -/*S_SPID_22*/ { SPR_SPID, 11, 3, { A_StalkerChase }, S_SPID_23 }, //1031 -/*S_SPID_23*/ { SPR_SPID, 11, 3, { A_Chase }, S_SPID_18 }, //1032 -/*S_SPID_24*/ { SPR_SPID, 11, 1, { A_Pain }, S_SPID_03 }, //1033 -/*S_SPID_25*/ { SPR_SPID, 14, 4, { NULL }, S_SPID_26 }, //1034 -/*S_SPID_26*/ { SPR_SPID, 15, 4, { A_Scream }, S_SPID_27 }, //1035 -/*S_SPID_27*/ { SPR_SPID, 16, 4, { NULL }, S_SPID_28 }, //1036 -/*S_SPID_28*/ { SPR_SPID, 17, 4, { NULL }, S_SPID_29 }, //1037 -/*S_SPID_29*/ { SPR_SPID, 18, 4, { NULL }, S_SPID_30 }, //1038 -/*S_SPID_30*/ { SPR_SPID, 19, 4, { NULL }, S_SPID_31 }, //1039 -/*S_SPID_31*/ { SPR_SPID, 20, 4, { A_Fall }, S_SPID_32 }, //1040 -/*S_SPID_32*/ { SPR_SPID, 21, 4, { NULL }, S_SPID_33 }, //1041 -/*S_SPID_33*/ { SPR_SPID, 22, 4, { NULL }, S_SPID_34 }, //1042 -/*S_SPID_34*/ { SPR_SPID, 32791, 4, { NULL }, S_SPID_35 }, //1043 -/*S_SPID_35*/ { SPR_SPID, 32792, 4, { NULL }, S_SPID_36 }, //1044 -/*S_SPID_36*/ { SPR_SPID, 32793, 4, { NULL }, S_SPID_37 }, //1045 -/*S_SPID_37*/ { SPR_SPID, 32794, 4, { NULL }, S_NULL }, //1046 -/*S_ROB3_00*/ { SPR_ROB3, 0, 10, { A_Look }, S_ROB3_01 }, //1047 -/*S_ROB3_01*/ { SPR_ROB3, 1, 10, { A_Look }, S_ROB3_00 }, //1048 -/*S_ROB3_02*/ { SPR_ROB3, 1, 3, { A_InqChase }, S_ROB3_03 }, //1049 -/*S_ROB3_03*/ { SPR_ROB3, 1, 3, { A_Chase }, S_ROB3_04 }, //1050 -/*S_ROB3_04*/ { SPR_ROB3, 2, 4, { A_Chase }, S_ROB3_05 }, //1051 -/*S_ROB3_05*/ { SPR_ROB3, 2, 4, { A_Chase }, S_ROB3_06 }, //1052 -/*S_ROB3_06*/ { SPR_ROB3, 3, 4, { A_Chase }, S_ROB3_07 }, //1053 -/*S_ROB3_07*/ { SPR_ROB3, 3, 4, { A_Chase }, S_ROB3_08 }, //1054 -/*S_ROB3_08*/ { SPR_ROB3, 4, 3, { A_InqChase }, S_ROB3_09 }, //1055 -/*S_ROB3_09*/ { SPR_ROB3, 4, 3, { A_InqFlyCheck }, S_ROB3_02 }, //1056 -/*S_ROB3_10*/ { SPR_ROB3, 0, 2, { A_InqFlyCheck }, S_ROB3_11 }, //1057 -/*S_ROB3_11*/ { SPR_ROB3, 5, 6, { A_FaceTarget }, S_ROB3_12 }, //1058 -/*S_ROB3_12*/ { SPR_ROB3, 32774, 8, { A_ReaverAttack }, S_ROB3_13 }, //1059 -/*S_ROB3_13*/ { SPR_ROB3, 6, 8, { A_ReaverAttack }, S_ROB3_02 }, //1060 -/*S_ROB3_14*/ { SPR_ROB3, 10, 12, { A_FaceTarget }, S_ROB3_15 }, //1061 -/*S_ROB3_15*/ { SPR_ROB3, 32777, 6, { A_InqGrenade }, S_ROB3_16 }, //1062 -/*S_ROB3_16*/ { SPR_ROB3, 10, 12, { NULL }, S_ROB3_02 }, //1063 -/*S_ROB3_17*/ { SPR_ROB3, 32775, 8, { A_InqTakeOff }, S_ROB3_18 }, //1064 -/*S_ROB3_18*/ { SPR_ROB3, 32776, 4, { A_InqFly }, S_ROB3_19 }, //1065 -/*S_ROB3_19*/ { SPR_ROB3, 32775, 4, { A_InqFly }, S_ROB3_18 }, //1066 -/*S_ROB3_20*/ { SPR_ROB3, 11, 4, { A_BodyParts }, S_ROB3_21 }, //1067 -/*S_ROB3_21*/ { SPR_ROB3, 12, 4, { A_Scream }, S_ROB3_22 }, //1068 -/*S_ROB3_22*/ { SPR_ROB3, 13, 4, { A_BodyParts }, S_ROB3_23 }, //1069 -/*S_ROB3_23*/ { SPR_ROB3, 32782, 4, { A_DeathExplode1 }, S_ROB3_24 }, //1070 -/*S_ROB3_24*/ { SPR_ROB3, 32783, 4, { A_BodyParts }, S_ROB3_25 }, //1071 -/*S_ROB3_25*/ { SPR_ROB3, 32784, 4, { A_Fall }, S_ROB3_26 }, //1072 -/*S_ROB3_26*/ { SPR_ROB3, 17, 4, { A_BodyParts }, S_ROB3_27 }, //1073 -/*S_ROB3_27*/ { SPR_ROB3, 18, 4, { A_BodyParts }, S_ROB3_28 }, //1074 -/*S_ROB3_28*/ { SPR_ROB3, 19, 4, { A_BodyParts }, S_ROB3_29 }, //1075 -/*S_ROB3_29*/ { SPR_ROB3, 20, 4, { A_BodyParts }, S_ROB3_30 }, //1076 -/*S_ROB3_30*/ { SPR_ROB3, 21, 4, { A_BodyParts }, S_ROB3_31 }, //1077 -/*S_ROB3_31*/ { SPR_ROB3, 32790, 4, { A_DeathExplode1 }, S_ROB3_32 }, //1078 -/*S_ROB3_32*/ { SPR_ROB3, 32791, 4, { A_BodyParts }, S_ROB3_33 }, //1079 -/*S_ROB3_33*/ { SPR_ROB3, 32792, 4, { A_BodyParts }, S_ROB3_34 }, //1080 -/*S_ROB3_34*/ { SPR_ROB3, 25, 4, { A_BodyParts }, S_ROB3_35 }, //1081 -/*S_ROB3_35*/ { SPR_ROB3, 26, 4, { A_BodyParts }, S_ROB3_36 }, //1082 -/*S_ROB3_36*/ { SPR_ROB3, 27, 3, { A_BodyParts }, S_ROB3_37 }, //1083 -/*S_ROB3_37*/ { SPR_ROB3, 32796, 3, { A_DeathExplode1 }, S_RBB3_00 }, //1084 -/*S_RBB3_00*/ { SPR_RBB3, 32768, 3, { A_InqTossArm }, S_RBB3_01 }, //1085 -/*S_RBB3_01*/ { SPR_RBB3, 32769, 3, { A_BodyParts }, S_RBB3_02 }, //1086 -/*S_RBB3_02*/ { SPR_RBB3, 2, 3, { A_BodyParts }, S_RBB3_03 }, //1087 -/*S_RBB3_03*/ { SPR_RBB3, 3, 3, { A_BodyParts }, S_RBB3_04 }, //1088 -/*S_RBB3_04*/ { SPR_RBB3, 4, -1, { A_BossDeath }, S_NULL }, //1089 -/*S_RBB3_05*/ { SPR_RBB3, 32773, 5, { NULL }, S_RBB3_06 }, //1090 -/*S_RBB3_06*/ { SPR_RBB3, 32774, 5, { NULL }, S_RBB3_07 }, //1091 -/*S_RBB3_07*/ { SPR_RBB3, 7, -1, { NULL }, S_NULL }, //1092 -/*S_PRGR_00*/ { SPR_PRGR, 0, 5, { A_Look }, S_PRGR_01 }, //1093 -/*S_PRGR_01*/ { SPR_PRGR, 0, 1, { A_FloatWeave }, S_PRGR_00 }, //1094 -/*S_PRGR_02*/ { SPR_PRGR, 0, 160, { A_FloatWeave }, S_PRGR_03 }, //1095 -/*S_PRGR_03*/ { SPR_PRGR, 1, 5, { A_FloatWeave }, S_PRGR_04 }, //1096 -/*S_PRGR_04*/ { SPR_PRGR, 2, 5, { A_FloatWeave }, S_PRGR_05 }, //1097 -/*S_PRGR_05*/ { SPR_PRGR, 3, 5, { A_FloatWeave }, S_PRGR_06 }, //1098 -/*S_PRGR_06*/ { SPR_PRGR, 4, 2, { A_FloatWeave }, S_PRGR_07 }, //1099 -/*S_PRGR_07*/ { SPR_PRGR, 5, 2, { A_FloatWeave }, S_PRGR_08 }, //1100 -/*S_PRGR_08*/ { SPR_PRGR, 4, 3, { A_Chase }, S_PRGR_09 }, //1101 -/*S_PRGR_09*/ { SPR_PRGR, 5, 3, { A_Chase }, S_PRGR_06 }, //1102 -/*S_PRGR_10*/ { SPR_PRGR, 4, 2, { A_FloatWeave }, S_PRGR_11 }, //1103 -/*S_PRGR_11*/ { SPR_PRGR, 5, 3, { A_FloatWeave }, S_PRGR_12 }, //1104 -/*S_PRGR_12*/ { SPR_PRGR, 4, 3, { A_FaceTarget }, S_PRGR_13 }, //1105 -/*S_PRGR_13*/ { SPR_PRGR, 5, 4, { A_ProgrammerMelee }, S_PRGR_06 }, //1106 -/*S_PRGR_14*/ { SPR_PRGR, 6, 5, { A_FaceTarget }, S_PRGR_15 }, //1107 -/*S_PRGR_15*/ { SPR_PRGR, 7, 5, { A_FloatWeave }, S_PRGR_16 }, //1108 -/*S_PRGR_16*/ { SPR_PRGR, 32776, 5, { A_FaceTarget }, S_PRGR_17 }, //1109 -/*S_PRGR_17*/ { SPR_PRGR, 32777, 5, { A_ProgrammerAttack }, S_PRGR_06 }, //1110 -/*S_PRGR_18*/ { SPR_PRGR, 10, 5, { A_Pain }, S_PRGR_19 }, //1111 -/*S_PRGR_19*/ { SPR_PRGR, 11, 5, { A_FloatWeave }, S_PRGR_06 }, //1112 -/*S_PRGR_20*/ { SPR_PRGR, 32779, 7, { A_BodyParts }, S_PRGR_21 }, //1113 -/*S_PRGR_21*/ { SPR_PRGR, 32780, 7, { A_Scream }, S_PRGR_22 }, //1114 -/*S_PRGR_22*/ { SPR_PRGR, 32781, 7, { A_BodyParts }, S_PRGR_23 }, //1115 -/*S_PRGR_23*/ { SPR_PRGR, 32782, 7, { A_Fall }, S_PRGR_24 }, //1116 -/*S_PRGR_24*/ { SPR_PRGR, 32783, 7, { A_BodyParts }, S_PRGR_25 }, //1117 -/*S_PRGR_25*/ { SPR_PRGR, 32784, 7, { A_ProgrammerDie }, S_PRGR_26 }, //1118 -/*S_PRGR_26*/ { SPR_PRGR, 32785, 7, { NULL }, S_PRGR_27 }, //1119 -/*S_PRGR_27*/ { SPR_PRGR, 32786, 6, { NULL }, S_PRGR_28 }, //1120 -/*S_PRGR_28*/ { SPR_PRGR, 32787, 5, { NULL }, S_PRGR_29 }, //1121 -/*S_PRGR_29*/ { SPR_PRGR, 32788, 5, { NULL }, S_PRGR_30 }, //1122 -/*S_PRGR_30*/ { SPR_PRGR, 32789, 5, { NULL }, S_PRGR_31 }, //1123 -/*S_PRGR_31*/ { SPR_PRGR, 32790, 5, { NULL }, S_PRGR_32 }, //1124 -/*S_PRGR_32*/ { SPR_PRGR, 32791, 32, { NULL }, S_PRGR_33 }, //1125 -/*S_PRGR_33*/ { SPR_PRGR, 32791, -1, { A_BossDeath }, S_NULL }, //1126 -/*S_BASE_00*/ { SPR_BASE, 32768, 5, { A_DeathExplode3 }, S_BASE_01 }, //1127 -/*S_BASE_01*/ { SPR_BASE, 32769, 5, { NULL }, S_BASE_02 }, //1128 -/*S_BASE_02*/ { SPR_BASE, 32770, 5, { NULL }, S_BASE_03 }, //1129 -/*S_BASE_03*/ { SPR_BASE, 32771, 5, { NULL }, S_BASE_04 }, //1130 -/*S_BASE_04*/ { SPR_BASE, 4, 5, { NULL }, S_BASE_05 }, //1131 -/*S_BASE_05*/ { SPR_BASE, 5, 5, { NULL }, S_BASE_06 }, //1132 -/*S_BASE_06*/ { SPR_BASE, 6, 5, { NULL }, S_BASE_07 }, //1133 -/*S_BASE_07*/ { SPR_BASE, 7, -1, { NULL }, S_NULL }, //1134 -/*S_FRBL_00*/ { SPR_FRBL, 32768, 3, { NULL }, S_FRBL_01 }, //1135 -/*S_FRBL_01*/ { SPR_FRBL, 32769, 3, { NULL }, S_FRBL_02 }, //1136 -/*S_FRBL_02*/ { SPR_FRBL, 32770, 3, { A_MissileTick }, S_FRBL_00 }, //1137 -/*S_FRBL_03*/ { SPR_FRBL, 32771, 5, { A_FlameDeath }, S_FRBL_04 }, //1138 -/*S_FRBL_04*/ { SPR_FRBL, 32772, 5, { NULL }, S_FRBL_05 }, //1139 -/*S_FRBL_05*/ { SPR_FRBL, 32773, 5, { NULL }, S_FRBL_06 }, //1140 -/*S_FRBL_06*/ { SPR_FRBL, 32774, 5, { NULL }, S_FRBL_07 }, //1141 -/*S_FRBL_07*/ { SPR_FRBL, 32775, 5, { NULL }, S_FRBL_08 }, //1142 -/*S_FRBL_08*/ { SPR_FRBL, 32776, 5, { NULL }, S_NULL }, //1143 -/*S_KLAX_00*/ { SPR_KLAX, 0, 5, { A_Listen }, S_KLAX_00 }, //1144 -/*S_KLAX_01*/ { SPR_KLAX, 1, 6, { A_ClaxonBlare }, S_KLAX_02 }, //1145 -/*S_KLAX_02*/ { SPR_KLAX, 2, 60, { NULL }, S_KLAX_01 }, //1146 -/*S_TURT_00*/ { SPR_TURT, 0, 5, { A_Listen }, S_TURT_00 }, //1147 -/*S_TURT_01*/ { SPR_TURT, 0, 2, { A_Chase }, S_TURT_01 }, //1148 -/*S_TURT_02*/ { SPR_TURT, 1, 4, { A_BulletAttack }, S_TURT_03 }, //1149 -/*S_TURT_03*/ { SPR_TURT, 3, 3, { A_CheckTargetVisible }, S_TURT_04 }, //1150 -/*S_TURT_04*/ { SPR_TURT, 0, 4, { A_CheckTargetVisible }, S_TURT_02 }, //1151 -/*S_BALL_00*/ { SPR_BALL, 32768, 6, { NULL }, S_BALL_01 }, //1152 -/*S_BALL_01*/ { SPR_BALL, 32769, 6, { NULL }, S_BALL_02 }, //1153 -/*S_BALL_02*/ { SPR_BALL, 32770, 6, { NULL }, S_BALL_03 }, //1154 -/*S_BALL_03*/ { SPR_BALL, 32771, 6, { NULL }, S_BALL_04 }, //1155 -/*S_BALL_04*/ { SPR_BALL, 32772, 6, { NULL }, S_TURT_05 }, //1156 -/*S_TURT_05*/ { SPR_TURT, 2, -1, { NULL }, S_NULL }, //1157 -/*S_PSTN_00*/ { SPR_PSTN, 0, 8, { NULL }, S_PSTN_01 }, //1158 -/*S_PSTN_01*/ { SPR_PSTN, 1, 8, { NULL }, S_PSTN_00 }, //1159 -/*S_PSTN_02*/ { SPR_PSTN, 32768, 4, { A_Scream }, S_PSTN_03 }, //1160 -/*S_PSTN_03*/ { SPR_PSTN, 32769, 4, { A_Fall }, S_PSTN_04 }, //1161 -/*S_PSTN_04*/ { SPR_PSTN, 32770, 4, { A_QuestMsg }, S_PSTN_05 }, //1162 -/*S_PSTN_05*/ { SPR_PSTN, 32771, 4, { A_SpawnSparkPuff }, S_PSTN_06 }, //1163 -/*S_PSTN_06*/ { SPR_PSTN, 32772, 4, { A_BodyParts }, S_PSTN_07 }, //1164 -/*S_PSTN_07*/ { SPR_PSTN, 32773, 4, { NULL }, S_PSTN_08 }, //1165 -/*S_PSTN_08*/ { SPR_PSTN, 32774, 4, { A_SpawnSparkPuff }, S_PSTN_09 }, //1166 -/*S_PSTN_09*/ { SPR_PSTN, 7, 4, { NULL }, S_PSTN_10 }, //1167 -/*S_PSTN_10*/ { SPR_PSTN, 8, -1, { NULL }, S_NULL }, //1168 -/*S_SECR_00*/ { SPR_SECR, 32768, 4, { NULL }, S_SECR_01 }, //1169 -/*S_SECR_01*/ { SPR_SECR, 32769, 4, { NULL }, S_SECR_02 }, //1170 -/*S_SECR_02*/ { SPR_SECR, 32770, 4, { NULL }, S_SECR_03 }, //1171 -/*S_SECR_03*/ { SPR_SECR, 32771, 4, { NULL }, S_SECR_00 }, //1172 -/*S_SECR_04*/ { SPR_SECR, 32772, 5, { A_SpawnSparkPuff }, S_SECR_05 }, //1173 -/*S_SECR_05*/ { SPR_SECR, 32773, 5, { A_Fall }, S_SECR_06 }, //1174 -/*S_SECR_06*/ { SPR_SECR, 32774, 5, { A_QuestMsg }, S_SECR_07 }, //1175 -/*S_SECR_07*/ { SPR_SECR, 32775, 5, { A_BodyParts }, S_SECR_08 }, //1176 -/*S_SECR_08*/ { SPR_SECR, 32776, 5, { A_SpawnSparkPuff }, S_SECR_09 }, //1177 -/*S_SECR_09*/ { SPR_SECR, 9, 5, { NULL }, S_SECR_10 }, //1178 -/*S_SECR_10*/ { SPR_SECR, 10, 5, { A_SpawnSparkPuff }, S_SECR_11 }, //1179 -/*S_SECR_11*/ { SPR_SECR, 11, 5, { NULL }, S_SECR_12 }, //1180 -/*S_SECR_12*/ { SPR_SECR, 12, 5, { A_SpawnSparkPuff }, S_SECR_13 }, //1181 -/*S_SECR_13*/ { SPR_SECR, 13, 5, { NULL }, S_SECR_14 }, //1182 -/*S_SECR_14*/ { SPR_SECR, 14, 5, { A_SpawnSparkPuff }, S_SECR_15 }, //1183 -/*S_SECR_15*/ { SPR_SECR, 15, -1, { NULL }, S_NULL }, //1184 -/*S_XPRK_01*/ { SPR_XPRK, 0, -1, { NULL }, S_NULL }, //1185 -/*S_XPRK_02*/ { SPR_XPRK, 0, 1, { A_ClearForceField }, S_BNG3_00 }, //1186 -/*S_TARG_00*/ { SPR_TARG, 0, -1, { NULL }, S_NULL }, //1187 -/*S_RING_00*/ { SPR_RING, 0, -1, { NULL }, S_NULL }, //1188 -/*S_EARS_00*/ { SPR_EARS, 0, -1, { NULL }, S_NULL }, //1189 -/*S_COMM_00*/ { SPR_COMM, 0, -1, { NULL }, S_NULL }, //1190 -/*S_BOOM_00*/ { SPR_BOOM, 32768, 1, { A_CrystalRadiusAtk }, S_BOOM_01 }, //1191 -/*S_BOOM_01*/ { SPR_BOOM, 32769, 3, { A_QuestMsg }, S_BOOM_02 }, //1192 -/*S_BOOM_02*/ { SPR_BOOM, 32770, 2, { A_CrystalExplode }, S_BOOM_03 }, //1193 -/*S_BOOM_03*/ { SPR_BOOM, 32771, 3, { A_SpawnSparkPuff }, S_BOOM_04 }, //1194 -/*S_BOOM_04*/ { SPR_BOOM, 32772, 3, { NULL }, S_BOOM_05 }, //1195 -/*S_BOOM_05*/ { SPR_BOOM, 32773, 3, { NULL }, S_BOOM_06 }, //1196 -/*S_BOOM_06*/ { SPR_BOOM, 32774, 3, { A_SpawnSparkPuff }, S_BOOM_07 }, //1197 -/*S_BOOM_07*/ { SPR_BOOM, 32775, 1, { A_CrystalRadiusAtk }, S_BOOM_08 }, //1198 -/*S_BOOM_08*/ { SPR_BOOM, 32776, 3, { NULL }, S_BOOM_09 }, //1199 -/*S_BOOM_09*/ { SPR_BOOM, 32777, 3, { A_SpawnSparkPuff }, S_BOOM_10 }, //1200 -/*S_BOOM_10*/ { SPR_BOOM, 32778, 3, { A_SpawnSparkPuff }, S_BOOM_11 }, //1201 -/*S_BOOM_11*/ { SPR_BOOM, 32779, 3, { A_SpawnSparkPuff }, S_BOOM_12 }, //1202 -/*S_BOOM_12*/ { SPR_BOOM, 32780, 3, { NULL }, S_BOOM_13 }, //1203 -/*S_BOOM_13*/ { SPR_BOOM, 32781, 3, { NULL }, S_BOOM_14 }, //1204 -/*S_BOOM_14*/ { SPR_BOOM, 32782, 3, { A_SpawnSparkPuff }, S_BOOM_15 }, //1205 -/*S_BOOM_15*/ { SPR_BOOM, 32783, 3, { NULL }, S_BOOM_16 }, //1206 -/*S_BOOM_16*/ { SPR_BOOM, 32784, 3, { NULL }, S_BOOM_17 }, //1207 -/*S_BOOM_17*/ { SPR_BOOM, 32785, 3, { NULL }, S_BOOM_18 }, //1208 -/*S_BOOM_18*/ { SPR_BOOM, 32786, 3, { NULL }, S_BOOM_19 }, //1209 -/*S_BOOM_19*/ { SPR_BOOM, 32787, 3, { NULL }, S_BOOM_20 }, //1210 -/*S_BOOM_20*/ { SPR_BOOM, 32788, 3, { A_ExtraLightOff }, S_BOOM_21 }, //1211 -/*S_BOOM_21*/ { SPR_BOOM, 32789, 3, { NULL }, S_BOOM_22 }, //1212 -/*S_BOOM_22*/ { SPR_BOOM, 32790, 3, { NULL }, S_BOOM_23 }, //1213 -/*S_BOOM_23*/ { SPR_BOOM, 32791, 3, { NULL }, S_BOOM_24 }, //1214 -/*S_BOOM_24*/ { SPR_BOOM, 32792, 3, { NULL }, S_NULL }, //1215 -/*S_RATT_00*/ { SPR_RATT, 0, 10, { A_Look }, S_RATT_00 }, //1216 -/*S_RATT_01*/ { SPR_RATT, 0, 4, { A_Chase }, S_RATT_02 }, //1217 -/*S_RATT_02*/ { SPR_RATT, 0, 4, { A_Chase }, S_RATT_03 }, //1218 -/*S_RATT_03*/ { SPR_RATT, 1, 4, { A_Chase }, S_RATT_04 }, //1219 -/*S_RATT_04*/ { SPR_RATT, 1, 4, { A_Chase }, S_RATT_01 }, //1220 -/*S_RATT_05*/ { SPR_RATT, 0, 8, { A_RandomWalk }, S_RATT_06 }, //1221 -/*S_RATT_06*/ { SPR_RATT, 1, 4, { A_RandomWalk }, S_RATT_01 }, //1222 -/*S_HOGN_00*/ { SPR_HOGN, 0, 2, { A_ZombieInSpecialSector }, S_HOGN_00 }, //1223 -/*S_HOGN_01*/ { SPR_HOGN, 1, 1, { A_ZombieInSpecialSector }, S_HOGN_02 }, //1224 -/*S_HOGN_02*/ { SPR_HOGN, 2, 1, { A_Pain }, S_HOGN_00 }, //1225 -/*S_DEAD_00*/ { SPR_DEAD, 0, -1, { NULL }, S_NULL }, //1226 -/*S_SBAN_00*/ { SPR_SBAN, 0, -1, { NULL }, S_NULL }, //1227 -/*S_BOTR_00*/ { SPR_BOTR, 0, -1, { NULL }, S_NULL }, //1228 -/*S_HATR_00*/ { SPR_HATR, 0, -1, { NULL }, S_NULL }, //1229 -/*S_TOPR_00*/ { SPR_TOPR, 0, -1, { NULL }, S_NULL }, //1230 -/*S_COUP_00*/ { SPR_COUP, 0, 5, { NULL }, S_COUP_01 }, //1231 -/*S_COUP_01*/ { SPR_COUP, 1, 5, { NULL }, S_COUP_00 }, //1232 -/*S_COUP_02*/ { SPR_COUP, 2, -1, { NULL }, S_COUP_01 }, //1233 -/*S_BUBB_00*/ { SPR_BUBB, 0, 4, { A_ActiveSound }, S_BUBB_00 }, //1234 -/*S_BUBF_00*/ { SPR_BUBF, 0, 4, { A_ActiveSound }, S_BUBF_00 }, //1235 -/*S_BUBC_00*/ { SPR_BUBC, 0, 4, { A_ActiveSound }, S_BUBC_00 }, //1236 -/*S_ASPR_00*/ { SPR_ASPR, 0, 4, { A_ActiveSound }, S_ASPR_00 }, //1237 -/*S_SPDL_00*/ { SPR_SPDL, 0, 5, { A_ActiveSound }, S_SPDL_01 }, //1238 -/*S_SPDL_01*/ { SPR_SPDL, 1, 5, { A_ActiveSound }, S_SPDL_02 }, //1239 -/*S_SPDL_02*/ { SPR_SPDL, 2, 5, { A_ActiveSound }, S_SPDL_00 }, //1240 -/*S_TOKN_00*/ { SPR_TOKN, 0, -1, { NULL }, S_NULL }, //1241 -/*S_OTOK_00*/ { SPR_OTOK, 0, -1, { NULL }, S_NULL }, //1242 -/*S_HELT_00*/ { SPR_HELT, 0, -1, { NULL }, S_NULL }, //1243 -/*S_GUNT_00*/ { SPR_GUNT, 0, -1, { NULL }, S_NULL }, //1244 -/*S_FULL_00*/ { SPR_FULL, 0, 35, { NULL }, S_FULL_01 }, //1245 -/*S_FULL_01*/ { SPR_FULL, 1, 35, { NULL }, S_FULL_00 }, //1246 -/*S_MEAT_00*/ { SPR_MEAT, 0, 700, { NULL }, S_NULL }, //1247 -/*S_MEAT_01*/ { SPR_MEAT, 1, 700, { NULL }, S_NULL }, //1248 -/*S_MEAT_02*/ { SPR_MEAT, 2, 700, { NULL }, S_NULL }, //1249 -/*S_MEAT_03*/ { SPR_MEAT, 3, 700, { NULL }, S_NULL }, //1250 -/*S_MEAT_04*/ { SPR_MEAT, 4, 700, { NULL }, S_NULL }, //1251 -/*S_MEAT_05*/ { SPR_MEAT, 5, 700, { NULL }, S_NULL }, //1252 -/*S_MEAT_06*/ { SPR_MEAT, 6, 700, { NULL }, S_NULL }, //1253 -/*S_MEAT_07*/ { SPR_MEAT, 7, 700, { NULL }, S_NULL }, //1254 -/*S_MEAT_08*/ { SPR_MEAT, 8, 700, { NULL }, S_NULL }, //1255 -/*S_MEAT_09*/ { SPR_MEAT, 9, 700, { NULL }, S_NULL }, //1256 -/*S_MEAT_10*/ { SPR_MEAT, 10, 700, { NULL }, S_NULL }, //1257 -/*S_MEAT_11*/ { SPR_MEAT, 11, 700, { NULL }, S_NULL }, //1258 -/*S_MEAT_12*/ { SPR_MEAT, 12, 700, { NULL }, S_NULL }, //1259 -/*S_MEAT_13*/ { SPR_MEAT, 13, 700, { NULL }, S_NULL }, //1260 -/*S_MEAT_14*/ { SPR_MEAT, 14, 700, { NULL }, S_NULL }, //1261 -/*S_MEAT_15*/ { SPR_MEAT, 15, 700, { NULL }, S_NULL }, //1262 -/*S_MEAT_16*/ { SPR_MEAT, 16, 700, { NULL }, S_NULL }, //1263 -/*S_MEAT_17*/ { SPR_MEAT, 17, 700, { NULL }, S_NULL }, //1264 -/*S_MEAT_18*/ { SPR_MEAT, 18, 700, { NULL }, S_NULL }, //1265 -/*S_MEAT_19*/ { SPR_MEAT, 19, 700, { NULL }, S_NULL }, //1266 -/*S_JUNK_00*/ { SPR_JUNK, 0, 700, { NULL }, S_NULL }, //1267 -/*S_JUNK_01*/ { SPR_JUNK, 1, 700, { NULL }, S_NULL }, //1268 -/*S_JUNK_02*/ { SPR_JUNK, 2, 700, { NULL }, S_NULL }, //1269 -/*S_JUNK_03*/ { SPR_JUNK, 3, 700, { NULL }, S_NULL }, //1270 -/*S_JUNK_04*/ { SPR_JUNK, 4, 700, { NULL }, S_NULL }, //1271 -/*S_JUNK_05*/ { SPR_JUNK, 5, 700, { NULL }, S_NULL }, //1272 -/*S_JUNK_06*/ { SPR_JUNK, 6, 700, { NULL }, S_NULL }, //1273 -/*S_JUNK_07*/ { SPR_JUNK, 7, 700, { NULL }, S_NULL }, //1274 -/*S_JUNK_08*/ { SPR_JUNK, 8, 700, { NULL }, S_NULL }, //1275 -/*S_JUNK_09*/ { SPR_JUNK, 9, 700, { NULL }, S_NULL }, //1276 -/*S_JUNK_10*/ { SPR_JUNK, 10, 700, { NULL }, S_NULL }, //1277 -/*S_JUNK_11*/ { SPR_JUNK, 11, 700, { NULL }, S_NULL }, //1278 -/*S_JUNK_12*/ { SPR_JUNK, 12, 700, { NULL }, S_NULL }, //1279 -/*S_JUNK_13*/ { SPR_JUNK, 13, 700, { NULL }, S_NULL }, //1280 -/*S_JUNK_14*/ { SPR_JUNK, 14, 700, { NULL }, S_NULL }, //1281 -/*S_JUNK_15*/ { SPR_JUNK, 15, 700, { NULL }, S_NULL }, //1282 -/*S_JUNK_16*/ { SPR_JUNK, 16, 700, { NULL }, S_NULL }, //1283 -/*S_JUNK_17*/ { SPR_JUNK, 17, 700, { NULL }, S_NULL }, //1284 -/*S_JUNK_18*/ { SPR_JUNK, 18, 700, { NULL }, S_NULL }, //1285 -/*S_JUNK_19*/ { SPR_JUNK, 19, 700, { NULL }, S_NULL }, //1286 -/*S_FFOT_00*/ { SPR_FFOT, 0, 9, { NULL }, S_FFOT_01 }, //1287 -/*S_FFOT_01*/ { SPR_FFOT, 1, 9, { NULL }, S_FFOT_02 }, //1288 -/*S_FFOT_02*/ { SPR_FFOT, 2, 9, { NULL }, S_FFOT_03 }, //1289 -/*S_FFOT_03*/ { SPR_FFOT, 3, 9, { NULL }, S_NULL }, //1290 -/*S_DIE1_00*/ { SPR_DIE1, 0, -1, { NULL }, S_NULL }, //1291 -/*S_BEAC_00*/ { SPR_BEAC, 0, -1, { NULL }, S_NULL }, //1292 -/*S_BEAC_01*/ { SPR_BEAC, 0, 30, { NULL }, S_BEAC_02 }, //1293 -/*S_BEAC_02*/ { SPR_BEAC, 0, 160, { A_TeleportBeacon }, S_BEAC_01 }, //1294 -/*S_ARM1_00*/ { SPR_ARM1, 0, -1, { NULL }, S_NULL }, //1295 -/*S_ARM2_00*/ { SPR_ARM2, 0, -1, { NULL }, S_NULL }, //1296 -/*S_BARW_00*/ { SPR_BARW, 0, -1, { NULL }, S_NULL }, //1297 -/*S_BARW_01*/ { SPR_BARW, 1, 2, { A_Scream }, S_BARW_02 }, //1298 -/*S_BARW_02*/ { SPR_BARW, 2, 2, { NULL }, S_BARW_03 }, //1299 -/*S_BARW_03*/ { SPR_BARW, 3, 2, { A_Fall }, S_BARW_04 }, //1300 -/*S_BARW_04*/ { SPR_BARW, 4, 2, { NULL }, S_BARW_05 }, //1301 -/*S_BARW_05*/ { SPR_BARW, 5, 2, { NULL }, S_BARW_06 }, //1302 -/*S_BARW_06*/ { SPR_BARW, 6, 2, { NULL }, S_BARW_07 }, //1303 -/*S_BARW_07*/ { SPR_BARW, 7, -1, { NULL }, S_NULL }, //1304 -/*S_BART_00*/ { SPR_BART, 0, -1, { NULL }, S_NULL }, //1305 -/*S_BART_01*/ { SPR_BART, 32769, 2, { A_Scream }, S_BART_02 }, //1306 -/*S_BART_02*/ { SPR_BART, 32770, 2, { NULL }, S_BART_03 }, //1307 -/*S_BART_03*/ { SPR_BART, 32771, 2, { NULL }, S_BART_04 }, //1308 -/*S_BART_04*/ { SPR_BART, 32772, 2, { A_Fall }, S_BART_05 }, //1309 -/*S_BART_05*/ { SPR_BART, 32773, 2, { A_DeathExplode2 }, S_BART_06 }, //1310 -/*S_BART_06*/ { SPR_BART, 32774, 2, { NULL }, S_BART_07 }, //1311 -/*S_BART_07*/ { SPR_BART, 32775, 2, { NULL }, S_BART_08 }, //1312 -/*S_BART_08*/ { SPR_BART, 32776, 2, { NULL }, S_BART_09 }, //1313 -/*S_BART_09*/ { SPR_BART, 32777, 3, { NULL }, S_BART_10 }, //1314 -/*S_BART_10*/ { SPR_BART, 32778, 3, { NULL }, S_BART_11 }, //1315 -/*S_BART_11*/ { SPR_BART, 11, -1, { NULL }, S_NULL }, //1316 -/*S_LAMP_00*/ { SPR_LAMP, 0, -1, { NULL }, S_NULL }, //1317 -/*S_LANT_00*/ { SPR_LANT, 0, -1, { NULL }, S_NULL }, //1318 -/*S_BARL_00*/ { SPR_BARL, 32768, 4, { NULL }, S_BARL_01 }, //1319 -/*S_BARL_01*/ { SPR_BARL, 32769, 4, { NULL }, S_BARL_02 }, //1320 -/*S_BARL_02*/ { SPR_BARL, 32770, 4, { NULL }, S_BARL_03 }, //1321 -/*S_BARL_03*/ { SPR_BARL, 32771, 4, { NULL }, S_BARL_00 }, //1322 -/*S_BOWL_00*/ { SPR_BOWL, 32768, 4, { A_ActiveSound }, S_BOWL_01 }, //1323 -/*S_BOWL_01*/ { SPR_BOWL, 32769, 4, { NULL }, S_BOWL_02 }, //1324 -/*S_BOWL_02*/ { SPR_BOWL, 32770, 4, { NULL }, S_BOWL_03 }, //1325 -/*S_BOWL_03*/ { SPR_BOWL, 32771, 4, { NULL }, S_BOWL_00 }, //1326 -/*S_BRAZ_00*/ { SPR_BRAZ, 32768, 4, { A_ActiveSound }, S_BRAZ_01 }, //1327 -/*S_BRAZ_01*/ { SPR_BRAZ, 32769, 4, { NULL }, S_BRAZ_02 }, //1328 -/*S_BRAZ_02*/ { SPR_BRAZ, 32770, 4, { NULL }, S_BRAZ_03 }, //1329 -/*S_BRAZ_03*/ { SPR_BRAZ, 32771, 4, { NULL }, S_BRAZ_00 }, //1330 -/*S_TRCH_00*/ { SPR_TRCH, 32768, 4, { A_ActiveSound }, S_TRCH_01 }, //1331 -/*S_TRCH_01*/ { SPR_TRCH, 32769, 4, { NULL }, S_TRCH_02 }, //1332 -/*S_TRCH_02*/ { SPR_TRCH, 32770, 4, { NULL }, S_TRCH_03 }, //1333 -/*S_TRCH_03*/ { SPR_TRCH, 32771, 4, { NULL }, S_TRCH_00 }, //1334 -/*S_LTRH_00*/ { SPR_LTRH, 32768, 4, { NULL }, S_LTRH_01 }, //1335 -/*S_LTRH_01*/ { SPR_LTRH, 32769, 4, { NULL }, S_LTRH_02 }, //1336 -/*S_LTRH_02*/ { SPR_LTRH, 32770, 4, { NULL }, S_LTRH_03 }, //1337 -/*S_LTRH_03*/ { SPR_LTRH, 32771, 4, { NULL }, S_LTRH_00 }, //1338 -/*S_LMPC_00*/ { SPR_LMPC, 32768, 4, { A_ActiveSound }, S_LMPC_01 }, //1339 -/*S_LMPC_01*/ { SPR_LMPC, 32769, 4, { NULL }, S_LMPC_02 }, //1340 -/*S_LMPC_02*/ { SPR_LMPC, 32770, 4, { NULL }, S_LMPC_03 }, //1341 -/*S_LMPC_03*/ { SPR_LMPC, 32771, 4, { NULL }, S_LMPC_00 }, //1342 -/*S_LOGS_00*/ { SPR_LOGS, 32768, 4, { A_ActiveSound }, S_LOGS_01 }, //1343 -/*S_LOGS_01*/ { SPR_LOGS, 32769, 4, { NULL }, S_LOGS_02 }, //1344 -/*S_LOGS_02*/ { SPR_LOGS, 32770, 4, { NULL }, S_LOGS_03 }, //1345 -/*S_LOGS_03*/ { SPR_LOGS, 32771, 4, { NULL }, S_LOGS_00 }, //1346 -/*S_TRHO_00*/ { SPR_TRHO, 0, -1, { NULL }, S_NULL }, //1347 -/*S_WATR_00*/ { SPR_WATR, 0, -1, { NULL }, S_NULL }, //1348 -/*S_MUGG_00*/ { SPR_MUGG, 0, -1, { NULL }, S_NULL }, //1349 -/*S_FUSL_00*/ { SPR_FUSL, 0, -1, { NULL }, S_NULL }, //1350 -/*S_CRD1_00*/ { SPR_CRD1, 0, -1, { NULL }, S_NULL }, //1351 -/*S_CRD2_00*/ { SPR_CRD2, 0, -1, { NULL }, S_NULL }, //1352 -/*S_TPAS_00*/ { SPR_TPAS, 0, -1, { NULL }, S_NULL }, //1353 -/*S_KY1G_00*/ { SPR_KY1G, 0, -1, { NULL }, S_NULL }, //1354 -/*S_KY2S_00*/ { SPR_KY2S, 0, -1, { NULL }, S_NULL }, //1355 -/*S_KY3B_00*/ { SPR_KY3B, 0, -1, { NULL }, S_NULL }, //1356 -/*S_HAND_00*/ { SPR_HAND, 0, -1, { NULL }, S_NULL }, //1357 -/*S_CRYS_00*/ { SPR_CRYS, 0, 16, { A_ActiveSound }, S_CRYS_01 }, //1358 -/*S_CRYS_01*/ { SPR_CRYS, 1, 5, { A_ActiveSound }, S_CRYS_02 }, //1359 -/*S_CRYS_02*/ { SPR_CRYS, 2, 4, { A_ActiveSound }, S_CRYS_03 }, //1360 -/*S_CRYS_03*/ { SPR_CRYS, 3, 4, { A_ActiveSound }, S_CRYS_04 }, //1361 -/*S_CRYS_04*/ { SPR_CRYS, 4, 4, { A_ActiveSound }, S_CRYS_05 }, //1362 -/*S_CRYS_05*/ { SPR_CRYS, 5, 4, { A_ActiveSound }, S_CRYS_00 }, //1363 -/*S_PRIS_00*/ { SPR_PRIS, 0, -1, { NULL }, S_NULL }, //1364 -/*S_PWR1_00*/ { SPR_PWR1, 0, -1, { NULL }, S_NULL }, //1365 -/*S_PWR2_00*/ { SPR_PWR2, 0, -1, { NULL }, S_NULL }, //1366 -/*S_PWR3_00*/ { SPR_PWR3, 0, -1, { NULL }, S_NULL }, //1367 -/*S_ORAC_00*/ { SPR_ORAC, 0, -1, { NULL }, S_NULL }, //1368 -/*S_GYID_00*/ { SPR_GYID, 0, -1, { NULL }, S_NULL }, //1369 -/*S_FUBR_00*/ { SPR_FUBR, 0, -1, { NULL }, S_NULL }, //1370 -/*S_WARE_00*/ { SPR_WARE, 0, -1, { NULL }, S_NULL }, //1371 -/*S_RCRY_00*/ { SPR_RCRY, 32768, -1, { NULL }, S_NULL }, //1372 -/*S_BCRY_00*/ { SPR_BCRY, 32768, -1, { NULL }, S_NULL }, //1373 -/*S_CHAP_00*/ { SPR_CHAP, 0, -1, { NULL }, S_NULL }, //1374 -/*S_TUNL_00*/ { SPR_TUNL, 0, -1, { NULL }, S_NULL }, //1375 -/*S_BLTK_00*/ { SPR_BLTK, 0, -1, { NULL }, S_NULL }, //1376 -/*S_SECK_00*/ { SPR_SECK, 0, -1, { NULL }, S_NULL }, //1377 -/*S_MINE_00*/ { SPR_MINE, 0, -1, { NULL }, S_NULL }, //1378 -/*S_REBL_00*/ { SPR_REBL, 0, -1, { NULL }, S_NULL }, //1379 -/*S_PROC_00*/ { SPR_PROC, 0, -1, { NULL }, S_NULL }, //1380 -/*S_ANKH_00*/ { SPR_ANKH, 0, -1, { NULL }, S_NULL }, //1381 -/*S_GOID_00*/ { SPR_GOID, 0, -1, { NULL }, S_NULL }, //1382 -/*S_STMP_00*/ { SPR_STMP, 0, -1, { NULL }, S_NULL }, //1383 -/*S_MDKT_00*/ { SPR_MDKT, 0, -1, { NULL }, S_NULL }, //1384 -/*S_COIN_00*/ { SPR_COIN, 0, -1, { NULL }, S_NULL }, //1385 -/*S_CRED_00*/ { SPR_CRED, 0, -1, { NULL }, S_NULL }, //1386 -/*S_SACK_00*/ { SPR_SACK, 0, -1, { NULL }, S_NULL }, //1387 -/*S_CHST_00*/ { SPR_CHST, 0, -1, { NULL }, S_NULL }, //1388 -/*S_SHD1_00*/ { SPR_SHD1, 0, 17, { A_ShadowOff }, S_SHD1_01 }, //1389 -/*S_SHD1_01*/ { SPR_SHD1, 0, 17, { A_ModifyVisibility }, S_SHD1_02 }, //1390 -/*S_SHD1_02*/ { SPR_SHD1, 0, 17, { A_ShadowOn }, S_SHD1_03 }, //1391 -/*S_SHD1_03*/ { SPR_SHD1, 0, 17, { A_ModifyVisibility }, S_SHD1_00 }, //1392 -/*S_MASK_00*/ { SPR_MASK, 0, -1, { NULL }, S_NULL }, //1393 -/*S_UNIF_00*/ { SPR_UNIF, 0, -1, { NULL }, S_NULL }, //1394 -/*S_OFIC_00*/ { SPR_OFIC, 0, -1, { NULL }, S_NULL }, //1395 -/*S_PMAP_00*/ { SPR_PMAP, 32768, 6, { NULL }, S_PMAP_01 }, //1396 -/*S_PMAP_01*/ { SPR_PMAP, 32769, 6, { NULL }, S_PMAP_00 }, //1397 -/*S_PMUP_00*/ { SPR_PMUP, 32768, 6, { NULL }, S_PMUP_01 }, //1398 -/*S_PMUP_01*/ { SPR_PMUP, 32769, 6, { NULL }, S_PMUP_00 }, //1399 -/*S_BLIT_00*/ { SPR_BLIT, 0, -1, { NULL }, S_NULL }, //1400 -/*S_BBOX_00*/ { SPR_BBOX, 0, -1, { NULL }, S_NULL }, //1401 -/*S_MSSL_00*/ { SPR_MSSL, 0, -1, { NULL }, S_NULL }, //1402 -/*S_ROKT_00*/ { SPR_ROKT, 0, -1, { NULL }, S_NULL }, //1403 -/*S_BRY1_00*/ { SPR_BRY1, 0, 6, { NULL }, S_BRY1_01 }, //1404 -/*S_BRY1_01*/ { SPR_BRY1, 1, 6, { NULL }, S_BRY1_00 }, //1405 -/*S_CPAC_00*/ { SPR_CPAC, 0, 6, { NULL }, S_CPAC_01 }, //1406 -/*S_CPAC_01*/ { SPR_CPAC, 1, 6, { NULL }, S_CPAC_00 }, //1407 -/*S_PQRL_00*/ { SPR_PQRL, 0, -1, { NULL }, S_NULL }, //1408 -/*S_XQRL_00*/ { SPR_XQRL, 0, -1, { NULL }, S_NULL }, //1409 -/*S_GRN1_00*/ { SPR_GRN1, 0, -1, { NULL }, S_NULL }, //1410 -/*S_GRN2_00*/ { SPR_GRN2, 0, -1, { NULL }, S_NULL }, //1411 -/*S_BKPK_00*/ { SPR_BKPK, 0, -1, { NULL }, S_NULL }, //1412 -/*S_RELC_00*/ { SPR_RELC, 32768, -1, { NULL }, S_NULL }, //1413 -/*S_RIFL_00*/ { SPR_RIFL, 0, -1, { NULL }, S_NULL }, //1414 -/*S_RIFL_01*/ { SPR_RIFL, 1, -1, { NULL }, S_NULL }, //1415 -/*S_FLAM_00*/ { SPR_FLAM, 0, -1, { NULL }, S_NULL }, //1416 -/*S_BFLM_00*/ { SPR_BFLM, 0, -1, { NULL }, S_NULL }, //1417 -/*S_MMSL_00*/ { SPR_MMSL, 0, -1, { NULL }, S_NULL }, //1418 -/*S_TRPD_00*/ { SPR_TRPD, 0, -1, { NULL }, S_NULL }, //1419 -/*S_GRND_00*/ { SPR_GRND, 0, -1, { NULL }, S_NULL }, //1420 -/*S_CBOW_00*/ { SPR_CBOW, 0, -1, { NULL }, S_NULL }, //1421 -/*S_SIGL_00*/ { SPR_SIGL, 0, -1, { NULL }, S_NULL }, //1422 -/*S_SIGL_01*/ { SPR_SIGL, 1, -1, { NULL }, S_NULL }, //1423 -/*S_SIGL_02*/ { SPR_SIGL, 2, -1, { NULL }, S_NULL }, //1424 -/*S_SIGL_03*/ { SPR_SIGL, 3, -1, { NULL }, S_NULL }, //1425 -/*S_SIGL_04*/ { SPR_SIGL, 4, -1, { NULL }, S_NULL }, //1426 -/*S_LITE_00*/ { SPR_LITE, 32768, -1, { NULL }, S_NULL }, //1427 -/*S_CNDL_00*/ { SPR_CNDL, 32768, -1, { NULL }, S_NULL }, //1428 -/*S_CLBR_00*/ { SPR_CLBR, 32768, -1, { NULL }, S_NULL }, //1429 -/*S_LITS_00*/ { SPR_LITS, 32768, -1, { NULL }, S_NULL }, //1430 -/*S_LITB_00*/ { SPR_LITB, 32768, -1, { NULL }, S_NULL }, //1431 -/*S_LITG_00*/ { SPR_LITG, 32768, -1, { NULL }, S_NULL }, //1432 -/*S_ROK1_00*/ { SPR_ROK1, 0, -1, { NULL }, S_NULL }, //1433 -/*S_ROK2_00*/ { SPR_ROK2, 0, -1, { NULL }, S_NULL }, //1434 -/*S_ROK3_00*/ { SPR_ROK3, 0, -1, { NULL }, S_NULL }, //1435 -/*S_ROK4_00*/ { SPR_ROK4, 0, -1, { NULL }, S_NULL }, //1436 -/*S_LOGG_00*/ { SPR_LOGG, 0, 5, { A_ActiveSound }, S_LOGG_01 }, //1437 -/*S_LOGG_01*/ { SPR_LOGG, 1, 5, { A_ActiveSound }, S_LOGG_02 }, //1438 -/*S_LOGG_02*/ { SPR_LOGG, 2, 5, { A_ActiveSound }, S_LOGG_03 }, //1439 -/*S_LOGG_03*/ { SPR_LOGG, 3, 5, { A_ActiveSound }, S_LOGG_00 }, //1440 -/*S_RUB1_00*/ { SPR_RUB1, 0, -1, { NULL }, S_NULL }, //1441 -/*S_RUB2_00*/ { SPR_RUB2, 0, -1, { NULL }, S_NULL }, //1442 -/*S_RUB3_00*/ { SPR_RUB3, 0, -1, { NULL }, S_NULL }, //1443 -/*S_RUB4_00*/ { SPR_RUB4, 0, -1, { NULL }, S_NULL }, //1444 -/*S_RUB5_00*/ { SPR_RUB5, 0, -1, { NULL }, S_NULL }, //1445 -/*S_RUB6_00*/ { SPR_RUB6, 0, -1, { NULL }, S_NULL }, //1446 -/*S_RUB7_00*/ { SPR_RUB7, 0, -1, { NULL }, S_NULL }, //1447 -/*S_RUB8_00*/ { SPR_RUB8, 0, -1, { NULL }, S_NULL }, //1448 -/*S_CHAN_00*/ { SPR_CHAN, 0, -1, { NULL }, S_NULL }, //1449 -/*S_STAT_00*/ { SPR_STAT, 0, -1, { NULL }, S_NULL }, //1450 -/*S_DSTA_00*/ { SPR_DSTA, 0, -1, { NULL }, S_NULL }, //1451 -/*S_CRAB_00*/ { SPR_CRAB, 0, -1, { NULL }, S_NULL }, //1452 -/*S_CAGE_00*/ { SPR_CAGE, 0, -1, { NULL }, S_NULL }, //1453 -/*S_TREE_00*/ { SPR_TREE, 0, -1, { NULL }, S_NULL }, //1454 -/*S_TREE_01*/ { SPR_TREE, 1, -1, { NULL }, S_NULL }, //1455 -/*S_TREE_02*/ { SPR_TREE, 2, -1, { NULL }, S_NULL }, //1456 -/*S_TRE1_00*/ { SPR_TRE1, 0, -1, { NULL }, S_NULL }, //1457 -/*S_BUSH_00*/ { SPR_BUSH, 0, -1, { NULL }, S_NULL }, //1458 -/*S_SHRB_00*/ { SPR_SHRB, 0, -1, { NULL }, S_NULL }, //1459 -/*S_STAK_00*/ { SPR_STAK, 0, -1, { NULL }, S_NULL }, //1460 -/*S_BAR1_00*/ { SPR_BAR1, 0, -1, { NULL }, S_NULL }, //1461 -/*S_VASE_00*/ { SPR_VASE, 0, -1, { NULL }, S_NULL }, //1462 -/*S_VASE_01*/ { SPR_VASE, 1, -1, { NULL }, S_NULL }, //1463 -/*S_STOL_00*/ { SPR_STOL, 0, -1, { NULL }, S_NULL }, //1464 -/*S_POT1_00*/ { SPR_POT1, 0, -1, { NULL }, S_NULL }, //1465 -/*S_TUB1_00*/ { SPR_TUB1, 0, -1, { NULL }, S_NULL }, //1466 -/*S_ANVL_00*/ { SPR_ANVL, 0, -1, { NULL }, S_NULL }, //1467 -/*S_TLMP_00*/ { SPR_TLMP, 0, -1, { NULL }, S_NULL }, //1468 -/*S_TLMP_01*/ { SPR_TLMP, 1, -1, { NULL }, S_NULL }, //1469 -/*S_TRAY_00*/ { SPR_TRAY, 0, -1, { NULL }, S_NULL }, //1470 -/*S_APOW_00*/ { SPR_APOW, 0, 4, { A_ActiveSound }, S_APOW_00 }, //1471 -/*S_AFED_00*/ { SPR_AFED, 0, -1, { NULL }, S_NULL }, //1472 -/*S_DRIP_00*/ { SPR_DRIP, 0, 6, { A_ActiveSound }, S_DRIP_01 }, //1473 -/*S_DRIP_01*/ { SPR_DRIP, 1, 4, { NULL }, S_DRIP_02 }, //1474 -/*S_DRIP_02*/ { SPR_DRIP, 2, 4, { NULL }, S_DRIP_03 }, //1475 -/*S_DRIP_03*/ { SPR_DRIP, 3, 4, { A_ActiveSound }, S_DRIP_04 }, //1476 -/*S_DRIP_04*/ { SPR_DRIP, 4, 4, { NULL }, S_DRIP_05 }, //1477 -/*S_DRIP_05*/ { SPR_DRIP, 5, 4, { NULL }, S_DRIP_06 }, //1478 -/*S_DRIP_06*/ { SPR_DRIP, 6, 4, { A_ActiveSound }, S_DRIP_07 }, //1479 -/*S_DRIP_07*/ { SPR_DRIP, 7, 4, { NULL }, S_DRIP_00 }, //1480 -/*S_CDRP_00*/ { SPR_CDRP, 0, 10, { NULL }, S_CDRP_01 }, //1481 -/*S_CDRP_01*/ { SPR_CDRP, 1, 8, { NULL }, S_CDRP_02 }, //1482 -/*S_CDRP_02*/ { SPR_CDRP, 2, 8, { NULL }, S_CDRP_03 }, //1483 -/*S_CDRP_03*/ { SPR_CDRP, 3, 8, { NULL }, S_CDRP_00 }, //1484 -/*S_SPLH_00*/ { SPR_SPLH, 0, 4, { NULL }, S_SPLH_01 }, //1485 -/*S_SPLH_01*/ { SPR_SPLH, 1, 4, { NULL }, S_SPLH_02 }, //1486 -/*S_SPLH_02*/ { SPR_SPLH, 2, 4, { NULL }, S_SPLH_03 }, //1487 -/*S_SPLH_03*/ { SPR_SPLH, 3, 8, { NULL }, S_SPLH_04 }, //1488 -/*S_SPLH_04*/ { SPR_SPLH, 4, 4, { NULL }, S_SPLH_05 }, //1489 -/*S_SPLH_05*/ { SPR_SPLH, 5, 4, { NULL }, S_SPLH_06 }, //1490 -/*S_SPLH_06*/ { SPR_SPLH, 6, 4, { NULL }, S_SPLH_07 }, //1491 -/*S_SPLH_07*/ { SPR_SPLH, 7, 4, { A_ActiveSound }, S_SPLH_00 }, //1492 -/*S_WTFT_00*/ { SPR_WTFT, 0, 4, { NULL }, S_WTFT_01 }, //1493 -/*S_WTFT_01*/ { SPR_WTFT, 1, 4, { NULL }, S_WTFT_02 }, //1494 -/*S_WTFT_02*/ { SPR_WTFT, 2, 4, { NULL }, S_WTFT_03 }, //1495 -/*S_WTFT_03*/ { SPR_WTFT, 3, 4, { A_ActiveSound }, S_WTFT_00 }, //1496 -/*S_HERT_00*/ { SPR_HERT, 32768, 4, { NULL }, S_HERT_01 }, //1497 -/*S_HERT_01*/ { SPR_HERT, 32769, 4, { NULL }, S_HERT_02 }, //1498 -/*S_HERT_02*/ { SPR_HERT, 32770, 4, { NULL }, S_HERT_00 }, //1499 -/*S_TELP_00*/ { SPR_TELP, 32768, 3, { NULL }, S_TELP_01 }, //1500 -/*S_TELP_01*/ { SPR_TELP, 32769, 3, { NULL }, S_TELP_02 }, //1501 -/*S_TELP_02*/ { SPR_TELP, 32770, 3, { NULL }, S_TELP_03 }, //1502 -/*S_TELP_03*/ { SPR_TELP, 32771, 3, { NULL }, S_TELP_00 }, //1503 -/*S_MONI_00*/ { SPR_MONI, 0, -1, { NULL }, S_NULL }, //1504 -/*S_STEL_00*/ { SPR_STEL, 0, -1, { NULL }, S_NULL }, //1505 -/*S_STLA_00*/ { SPR_STLA, 0, -1, { NULL }, S_NULL }, //1506 -/*S_STLE_00*/ { SPR_STLE, 0, -1, { NULL }, S_NULL }, //1507 -/*S_HUGE_00*/ { SPR_HUGE, 0, 4, { NULL }, S_HUGE_01 }, //1508 -/*S_HUGE_01*/ { SPR_HUGE, 1, 5, { NULL }, S_HUGE_02 }, //1509 -/*S_HUGE_02*/ { SPR_HUGE, 2, 5, { NULL }, S_HUGE_03 }, //1510 -/*S_HUGE_03*/ { SPR_HUGE, 3, 5, { NULL }, S_HUGE_00 }, //1511 -/*S_STLG_00*/ { SPR_STLG, 0, -1, { NULL }, S_NULL }, //1512 -/*S_STLG_01*/ { SPR_STLG, 1, -1, { NULL }, S_NULL }, //1513 -/*S_STLG_02*/ { SPR_STLG, 2, -1, { NULL }, S_NULL }, //1514 -/*S_STLG_03*/ { SPR_STLG, 3, -1, { NULL }, S_NULL }, //1515 -/*S_STLG_04*/ { SPR_STLG, 4, -1, { NULL }, S_NULL }, //1516 -/*S_STLG_05*/ { SPR_STLG, 5, -1, { NULL }, S_NULL }, //1517 -}; - - -// villsa [STRIFE] -mobjinfo_t mobjinfo[NUMMOBJTYPES] = -{ - { /*MT_FIELDGUARD*/ - 25, //doomednum - S_TOKN_00, //spawnstate - 10, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_XPRK_00, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 2*FRACUNIT, //radius - 1*FRACUNIT, //height - 10000, //mass - 0, //damage - sfx_None, //activesound - MF_SHOOTABLE|MF_NOSECTOR|MF_NODIALOG, //flags - NULL, //namepointer - }, - - { /*MT_PLAYER*/ - -1, //doomednum - S_PLAY_00, //spawnstate - 100, //spawnhealth - S_PLAY_01, //seestate - sfx_None, //seesound - 0, //reactiontime - sfx_None, //attacksound - S_PLAY_07, //painstate - 255, //painchance - sfx_plpain, //painsound - S_NULL, //meleestate - S_PLAY_05, //missilestate - S_NULL, //crashstate - S_PLAY_09, //deathstate - S_RGIB_00, //xdeathstate - sfx_pldeth, //deathsound - 0, //speed - 18*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_NOTDMATCH|MF_ALLY, //flags - NULL, //namepointer - }, - - { /*MT_SHOPKEEPER_W*/ - 116, //doomednum - S_MRST_00, //spawnstate - 10000000, //spawnhealth - S_MRPN_00, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_MRPN_00, //painstate - 150, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 5000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH, //flags - "Weapon_Smith", //namepointer - }, - - { /*MT_SHOPKEEPER_B*/ - 72, //doomednum - S_MRST_00, //spawnstate - 10000000, //spawnhealth - S_MRPN_00, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_MRPN_00, //painstate - 150, //painchance - sfx_ambbar, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 5000, //mass - 0, //damage - sfx_ambppl, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH|MF_COLORSWAP1|MF_COLORSWAP3, //flags - "Bar_Keep", //namepointer - }, - - { /*MT_SHOPKEEPER_A*/ - 73, //doomednum - S_MRST_00, //spawnstate - 10000000, //spawnhealth - S_MRPN_00, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_MRPN_00, //painstate - 150, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 5000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH|MF_COLORSWAP2|MF_COLORSWAP3, //flags - "Armorer", //namepointer - }, - - { /*MT_SHOPKEEPER_M*/ - 74, //doomednum - S_MRST_00, //spawnstate - 10000000, //spawnhealth - S_MRPN_00, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_MRPN_00, //painstate - 150, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOTDMATCH|MF_COLORSWAP1|MF_COLORSWAP2 - |MF_COLORSWAP3, //flags - "Medic", //namepointer - }, - - { /*MT_PEASANT2_A*/ - 3004, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 4, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT2_B*/ - 130, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 5, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT2_C*/ - 131, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 5, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT5_A*/ - 65, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 7, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT5_B*/ - 132, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 7, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT5_C*/ - 133, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 7, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT4_A*/ - 66, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP2, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT4_B*/ - 134, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP2, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT4_C*/ - 135, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP2, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT6_A*/ - 67, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT6_B*/ - 136, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 7, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT6_C*/ - 137, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT3_A*/ - 172, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT3_B*/ - 173, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT3_C*/ - 174, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT8_A*/ - 175, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2 - |MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT8_B*/ - 176, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2 - |MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT8_C*/ - 177, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP2 - |MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT7_A*/ - 178, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT7_B*/ - 179, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT7_C*/ - 180, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_PEASANT1*/ - 181, //doomednum - S_PEAS_00, //spawnstate - 31, //spawnhealth - S_PEAS_01, //seestate - sfx_rebact, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_PEAS_12, //painstate - 200, //painchance - sfx_pespna, //painsound - S_PEAS_09, //meleestate - S_NULL, //missilestate - S_PEAS_14, //crashstate - S_PEAS_17, //deathstate - S_GIBS_00, //xdeathstate - sfx_psdtha, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL|MF_COLORSWAP1 - |MF_COLORSWAP2|MF_COLORSWAP3, //flags - NULL, //namepointer - }, - - { /*MT_ZOMBIE*/ - 169, //doomednum - S_PEAS_25, //spawnstate - 31, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_AGRD_00, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_GIBS_00, //deathstate - S_NULL, //xdeathstate - sfx_psdtha, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1, //flags - NULL, //namepointer - }, - - { /*MT_BECOMING*/ - 201, //doomednum - S_ARMR_00, //spawnstate - 61, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_ARMR_01, //painstate - 255, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_GIBS_10, //deathstate - S_NULL, //xdeathstate - sfx_psdtha, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_ZOMBIESPAWNER*/ - 170, //doomednum - S_PLAY_19, //spawnstate - 20, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_telept, //activesound - MF_SHOOTABLE|MF_NOSECTOR, //flags - NULL, //namepointer - }, - - { /*MT_HUGE_TANK_1*/ - 209, //doomednum - S_TNK1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 192*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_HUGE_TANK_2*/ - 210, //doomednum - S_TNK2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 192*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_HUGE_TANK_3*/ - 211, //doomednum - S_TNK3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 192*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TANK_4*/ - 213, //doomednum - S_TNK4_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 56*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TANK_5*/ - 214, //doomednum - S_TNK5_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 56*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TANK_6*/ - 229, //doomednum - S_TNK6_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 56*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_KNEELING_GUY*/ - 204, //doomednum - S_NEAL_00, //spawnstate - 51, //spawnhealth - S_NEAL_00, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NEAL_02, //painstate - 255, //painchance - sfx_static, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NEAL_05, //crashstate - S_NEAL_07, //deathstate - S_NULL, //xdeathstate - sfx_static, //deathsound - 0, //speed - 6*FRACUNIT, //radius - 6*FRACUNIT, //height - 50000, //mass - 0, //damage - sfx_chant, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_BEGGAR1*/ - 141, //doomednum - S_BEGR_00, //spawnstate - 20, //spawnhealth - S_BEGR_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_BEGR_11, //painstate - 250, //painchance - sfx_pespna, //painsound - S_BEGR_07, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BEGR_13, //deathstate - S_BEGR_22, //xdeathstate - sfx_psdtha, //deathsound - 3, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - "Beggar", //namepointer - }, - - { /*MT_BEGGAR2*/ - 155, //doomednum - S_BEGR_00, //spawnstate - 20, //spawnhealth - S_BEGR_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_BEGR_11, //painstate - 250, //painchance - sfx_pespna, //painsound - S_BEGR_07, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BEGR_13, //deathstate - S_BEGR_22, //xdeathstate - sfx_psdtha, //deathsound - 3, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - "Beggar", //namepointer - }, - - { /*MT_BEGGAR3*/ - 156, //doomednum - S_BEGR_00, //spawnstate - 20, //spawnhealth - S_BEGR_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_BEGR_11, //painstate - 250, //painchance - sfx_pespna, //painsound - S_BEGR_07, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BEGR_13, //deathstate - S_BEGR_22, //xdeathstate - sfx_psdtha, //deathsound - 3, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - "Beggar", //namepointer - }, - - { /*MT_BEGGAR4*/ - 157, //doomednum - S_BEGR_00, //spawnstate - 20, //spawnhealth - S_BEGR_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_BEGR_11, //painstate - 250, //painchance - sfx_pespna, //painsound - S_BEGR_07, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BEGR_13, //deathstate - S_BEGR_22, //xdeathstate - sfx_psdtha, //deathsound - 3, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - "Beggar", //namepointer - }, - - { /*MT_BEGGAR5*/ - 158, //doomednum - S_BEGR_00, //spawnstate - 20, //spawnhealth - S_BEGR_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_meatht, //attacksound - S_BEGR_11, //painstate - 250, //painchance - sfx_pespna, //painsound - S_BEGR_07, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BEGR_13, //deathstate - S_BEGR_22, //xdeathstate - sfx_psdtha, //deathsound - 3, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_JUSTHIT|MF_COUNTKILL, //flags - "Beggar", //namepointer - }, - - { /*MT_REBEL1*/ - 9, //doomednum - S_HMN1_00, //spawnstate - 60, //spawnhealth - S_HMN1_11, //seestate - sfx_wpnup, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HMN1_22, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_HMN1_19, //missilestate - S_NULL, //crashstate - S_HMN1_24, //deathstate - S_RGIB_08, //xdeathstate - sfx_rebdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags - "Rebel", //namepointer - }, - - { /*MT_REBEL2*/ - 144, //doomednum - S_HMN1_00, //spawnstate - 60, //spawnhealth - S_HMN1_11, //seestate - sfx_wpnup, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HMN1_22, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_HMN1_19, //missilestate - S_NULL, //crashstate - S_HMN1_24, //deathstate - S_RGIB_08, //xdeathstate - sfx_rebdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags - "Rebel", //namepointer - }, - - { /*MT_REBEL3*/ - 145, //doomednum - S_HMN1_00, //spawnstate - 60, //spawnhealth - S_HMN1_11, //seestate - sfx_wpnup, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HMN1_22, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_HMN1_19, //missilestate - S_NULL, //crashstate - S_HMN1_24, //deathstate - S_RGIB_08, //xdeathstate - sfx_rebdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags - "Rebel", //namepointer - }, - - { /*MT_REBEL4*/ - 149, //doomednum - S_HMN1_00, //spawnstate - 60, //spawnhealth - S_HMN1_11, //seestate - sfx_wpnup, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HMN1_22, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_HMN1_19, //missilestate - S_NULL, //crashstate - S_HMN1_24, //deathstate - S_RGIB_08, //xdeathstate - sfx_rebdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags - "Rebel", //namepointer - }, - - { /*MT_REBEL5*/ - 150, //doomednum - S_HMN1_00, //spawnstate - 60, //spawnhealth - S_HMN1_11, //seestate - sfx_wpnup, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HMN1_22, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_HMN1_19, //missilestate - S_NULL, //crashstate - S_HMN1_24, //deathstate - S_RGIB_08, //xdeathstate - sfx_rebdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags - "Rebel", //namepointer - }, - - { /*MT_REBEL6*/ - 151, //doomednum - S_HMN1_00, //spawnstate - 60, //spawnhealth - S_HMN1_11, //seestate - sfx_wpnup, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HMN1_22, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_HMN1_19, //missilestate - S_NULL, //crashstate - S_HMN1_24, //deathstate - S_RGIB_08, //xdeathstate - sfx_rebdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_ALLY, //flags - "Rebel", //namepointer - }, - - { /*MT_RLEADER*/ - 64, //doomednum - S_LEDR_00, //spawnstate - 95, //spawnhealth - S_LEAD_04, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_LEAD_15, //painstate - 250, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_LEAD_12, //missilestate - S_NULL, //crashstate - S_LEAD_04, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_NOTDMATCH, //flags - "MACIL", //namepointer - }, - - { /*MT_RLEADER2*/ - 200, //doomednum - S_LEDR_00, //spawnstate - 95, //spawnhealth - S_LEAD_04, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_LEAD_15, //painstate - 200, //painchance - sfx_pespna, //painsound - S_NULL, //meleestate - S_LEAD_17, //missilestate - S_NULL, //crashstate - S_LEAD_20, //deathstate - S_LEAD_20, //xdeathstate - sfx_slop, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_rebact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_NOTDMATCH|MF_SPECTRAL, //flags - "MACIL", //namepointer - }, - - { /*MT_MISSILESMOKE*/ - -1, //doomednum - S_PUFY_04, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_rflite, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags - NULL, //namepointer - }, - - { /*MT_REAVER*/ - 3001, //doomednum - S_ROB1_00, //spawnstate - 150, //spawnhealth - S_ROB1_02, //seestate - sfx_revsee, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_ROB1_15, //painstate - 128, //painchance - sfx_reavpn, //painsound - S_ROB1_10, //meleestate - S_ROB1_13, //missilestate - S_NULL, //crashstate - S_ROB1_17, //deathstate - S_ROB1_26, //xdeathstate - sfx_revdth, //deathsound - 12, //speed - 20*FRACUNIT, //radius - 60*FRACUNIT, //height - 500, //mass - 0, //damage - sfx_revact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_GUARD1*/ - 3002, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac1, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD2*/ - 142, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac2, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD3*/ - 143, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac3, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP2, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD4*/ - 146, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac1, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1|MF_COLORSWAP2, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD5*/ - 147, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac2, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP3, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD6*/ - 148, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac3, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1|MF_COLORSWAP3, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD7*/ - 232, //doomednum - S_AGRD_01, //spawnstate - 60, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac3, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP2|MF_COLORSWAP3, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_GUARD8*/ - 231, //doomednum - S_AGRD_01, //spawnstate - 60, //spawnhealth - S_AGRD_13, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_23, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac3, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_COLORSWAP1|MF_COLORSWAP2 - |MF_COLORSWAP3, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_SHADOWGUARD*/ - 58, //doomednum - S_AGRD_01, //spawnstate - 70, //spawnhealth - S_AGRD_12, //seestate - sfx_agrsee, //seesound - 8, //reactiontime - sfx_rifle, //attacksound - S_AGRD_21, //painstate - 150, //painchance - sfx_agrdpn, //painsound - S_NULL, //meleestate - S_AGRD_17, //missilestate - S_NULL, //crashstate - S_AGRD_24, //deathstate - S_GIBS_10, //xdeathstate - sfx_agrdth, //deathsound - 7, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_agrac2, //activesound - MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL, //flags - "ACOLYTE", //namepointer - }, - - { /*MT_PGUARD*/ - 3003, //doomednum - S_PGRD_00, //spawnstate - 300, //spawnhealth - S_PGRD_04, //seestate - sfx_pgrsee, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_PGRD_16, //painstate - 100, //painchance - sfx_pgrdpn, //painsound - S_PGRD_12, //meleestate - S_PGRD_14, //missilestate - S_NULL, //crashstate - S_PGRD_18, //deathstate - S_NULL, //xdeathstate - sfx_pgrdth, //deathsound - 8, //speed - 20*FRACUNIT, //radius - 60*FRACUNIT, //height - 500, //mass - 0, //damage - sfx_pgract, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD|MF_COUNTKILL, //flags - "TEMPLAR", //namepointer - }, - - { /*MT_CRUSADER*/ - 3005, //doomednum - S_ROB2_00, //spawnstate - 400, //spawnhealth - S_ROB2_01, //seestate - sfx_rb2see, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_ROB2_19, //painstate - 128, //painchance - sfx_rb2pn, //painsound - S_NULL, //meleestate - S_ROB2_09, //missilestate - S_NULL, //crashstate - S_ROB2_20, //deathstate - S_NULL, //xdeathstate - sfx_rb2dth, //deathsound - 8, //speed - 40*FRACUNIT, //radius - 56*FRACUNIT, //height - 400, //mass - 0, //damage - sfx_rb2act, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_BISHOP*/ - 187, //doomednum - S_MLDR_00, //spawnstate - 500, //spawnhealth - S_MLDR_01, //seestate - sfx_rb2see, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_MLDR_11, //painstate - 128, //painchance - sfx_rb2pn, //painsound - S_NULL, //meleestate - S_MLDR_09, //missilestate - S_NULL, //crashstate - S_MLDR_12, //deathstate - S_NULL, //xdeathstate - sfx_pgrdth, //deathsound - 8, //speed - 40*FRACUNIT, //radius - 56*FRACUNIT, //height - 500, //mass - 0, //damage - sfx_rb2act, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL - |MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_ORACLE*/ - 199, //doomednum - S_ORCL_00, //spawnstate - 1, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ORCL_01, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 15*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH, //flags - "ORACLE", //namepointer - }, - - { /*MT_PRIEST*/ - 12, //doomednum - S_PRST_00, //spawnstate - 800, //spawnhealth - S_PRST_02, //seestate - sfx_lorsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_lorpn, //painsound - S_PRST_10, //meleestate - S_PRST_13, //missilestate - S_NULL, //crashstate - S_PDED_00, //deathstate - S_NULL, //xdeathstate - sfx_slop, //deathsound - 10, //speed - 15*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_tend, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST|MF_FLOAT - |MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH, //flags - "PRIEST", //namepointer - }, - - { /*MT_SPECTRE_A*/ - 129, //doomednum - S_ALN1_00, //spawnstate - 1000, //spawnhealth - S_ALN1_02, //seestate - sfx_alnsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_ALN1_19, //painstate - 250, //painchance - sfx_alnpn, //painsound - S_ALN1_13, //meleestate - S_ALN1_16, //missilestate - S_NULL, //crashstate - S_AL1P_00, //deathstate - S_NULL, //xdeathstate - sfx_alndth, //deathsound - 12, //speed - 64*FRACUNIT, //radius - 64*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_NODE*/ - -1, //doomednum - S_NODE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_SPECTREHEAD*/ - -1, //doomednum - S_MTHD_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_SPECTRE_B*/ - 75, //doomednum - S_ALN1_00, //spawnstate - 1200, //spawnhealth - S_ALN1_02, //seestate - sfx_alnsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_ALN1_19, //painstate - 50, //painchance - sfx_alnpn, //painsound - S_ALN1_13, //meleestate - S_ALN1_20, //missilestate - S_NULL, //crashstate - S_AL1P_00, //deathstate - S_NULL, //xdeathstate - sfx_alndth, //deathsound - 12, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SPECTRE_C*/ - 76, //doomednum - S_ALN1_23, //spawnstate - 1500, //spawnhealth - S_ALN1_34, //seestate - sfx_alnsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_ALN1_51, //painstate - 50, //painchance - sfx_alnpn, //painsound - S_ALN1_45, //meleestate - S_ALN1_48, //missilestate - S_NULL, //crashstate - S_AL1P_00, //deathstate - S_NULL, //xdeathstate - sfx_alndth, //deathsound - 12, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SPECTRE_D*/ - 167, //doomednum - S_ALN1_00, //spawnstate - 1700, //spawnhealth - S_ALN1_02, //seestate - sfx_alnsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_ALN1_19, //painstate - 50, //painchance - sfx_alnpn, //painsound - S_ALN1_13, //meleestate - S_ALN1_52, //missilestate - S_NULL, //crashstate - S_AL1P_00, //deathstate - S_NULL, //xdeathstate - sfx_alndth, //deathsound - 12, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SPECTRE_E*/ - 168, //doomednum - S_ALN1_00, //spawnstate - 2000, //spawnhealth - S_ALN1_02, //seestate - sfx_alnsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_ALN1_19, //painstate - 50, //painchance - sfx_alnpn, //painsound - S_ALN1_13, //meleestate - S_ALN1_55, //missilestate - S_NULL, //crashstate - S_AL1P_00, //deathstate - S_NULL, //xdeathstate - sfx_alndth, //deathsound - 12, //speed - 24*FRACUNIT, //radius - 64*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_ENTITY*/ - 128, //doomednum - S_MNAM_00, //spawnstate - 2500, //spawnhealth - S_MNAL_02, //seestate - sfx_mnalse, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_MNAL_19, //painstate - 255, //painchance - sfx_alnpn, //painsound - S_MNAL_13, //meleestate - S_MNAL_16, //missilestate - S_NULL, //crashstate - S_MNAL_20, //deathstate - S_NULL, //xdeathstate - sfx_mnaldt, //deathsound - 13, //speed - 130*FRACUNIT, //radius - 200*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SUBENTITY*/ - -1, //doomednum - S_MNAL_27, //spawnstate - 990, //spawnhealth - S_MNAL_28, //seestate - sfx_alnsee, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_MNAL_40, //painstate - 255, //painchance - sfx_alnpn, //painsound - S_MNAL_34, //meleestate - S_MNAL_37, //missilestate - S_NULL, //crashstate - S_MDTH_00, //deathstate - S_NULL, //xdeathstate - sfx_alndth, //deathsound - 14, //speed - 130*FRACUNIT, //radius - 200*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_alnact, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_SHADOW|MF_COUNTKILL|MF_NOTDMATCH - |MF_MVIS|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_NEST*/ - 26, //doomednum - S_NEST_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 84*FRACUNIT, //radius - 47*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_POD*/ - 198, //doomednum - S_PODD_00, //spawnstate - 1000, //spawnhealth - S_PODD_01, //seestate - sfx_slop, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 25*FRACUNIT, //radius - 91*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_B_SHOT*/ - -1, //doomednum - S_ZAP6_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_00, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 30*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 70, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_SB_SHOT*/ - -1, //doomednum - S_ZAP6_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_00, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 30*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 20, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_C_SHOT*/ - -1, //doomednum - S_ZOT3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_00, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 30*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 70, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_SC_SHOT*/ - -1, //doomednum - S_ZOT3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_00, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 30*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 20, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_E_OFFSHOOT*/ - -1, //doomednum - S_ZAP6_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_00, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 30*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 10, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_TRAIL*/ - -1, //doomednum - S_ZAP6_03, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_E_SHOT*/ - -1, //doomednum - S_ZAP7_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_02, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 18*FRACUNIT, //speed - 20*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 130, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_SE_SHOT*/ - -1, //doomednum - S_ZAP7_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_02, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 18*FRACUNIT, //speed - 20*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 30, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_A_ZAP_LEFT*/ - -1, //doomednum - S_ZOT1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_06, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 22*FRACUNIT, //speed - 8*FRACUNIT, //radius - 24*FRACUNIT, //height - 100, //mass - 100, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_A_ZAP_RIGHT*/ - -1, //doomednum - S_ZOT1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_06, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 22*FRACUNIT, //speed - 8*FRACUNIT, //radius - 24*FRACUNIT, //height - 100, //mass - 50, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_A_GROUND*/ - -1, //doomednum - S_ZAP5_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 70, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_01, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 18*FRACUNIT, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_SHADOW, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_D_SHOT*/ - -1, //doomednum - S_ZOT2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_01, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 28*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 120, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SIGIL_SD_SHOT*/ - -1, //doomednum - S_ZOT2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_sigil, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_01, //deathstate - S_NULL, //xdeathstate - sfx_sglhit, //deathsound - 28*FRACUNIT, //speed - 8*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 60, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE|MF_SPECTRAL, //flags - NULL, //namepointer - }, - - { /*MT_SENTINEL*/ - 3006, //doomednum - S_SEWR_00, //spawnstate - 100, //spawnhealth - S_SEWR_01, //seestate - sfx_sntsee, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_SEWR_06, //painstate - 255, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_SEWR_03, //missilestate - S_NULL, //crashstate - S_SEWR_07, //deathstate - S_NULL, //xdeathstate - sfx_sntdth, //deathsound - 7, //speed - 23*FRACUNIT, //radius - 53*FRACUNIT, //height - 300, //mass - 0, //damage - sfx_sntact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_SPAWNCEILING|MF_NOGRAVITY|MF_GIVEQUEST - |MF_FLOAT|MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_STALKER*/ - 186, //doomednum - S_SPID_00, //spawnstate - 80, //spawnhealth - S_SPID_03, //seestate - sfx_spisit, //seesound - 8, //reactiontime - sfx_spdatk, //attacksound - S_SPID_24, //painstate - 40, //painchance - sfx_spdatk, //painsound - S_SPID_09, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_SPID_25, //deathstate - S_NULL, //xdeathstate - sfx_spidth, //deathsound - 16, //speed - 31*FRACUNIT, //radius - 25*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_spisit, //activesound - MF_SOLID|MF_SHOOTABLE|MF_SPAWNCEILING|MF_NOGRAVITY|MF_DROPOFF - |MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_INQUISITOR*/ - 16, //doomednum - S_ROB3_00, //spawnstate - 1000, //spawnhealth - S_ROB3_02, //seestate - sfx_inqsee, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_ROB3_10, //missilestate - S_NULL, //crashstate - S_ROB3_20, //deathstate - S_NULL, //xdeathstate - sfx_inqdth, //deathsound - 12, //speed - 40*FRACUNIT, //radius - 110*FRACUNIT, //height - 1000, //mass - 0, //damage - sfx_inqact, //activesound - MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_NOBLOOD|MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_INQARM*/ - -1, //doomednum - S_RBB3_05, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 25, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_PROGRAMMER*/ - 71, //doomednum - S_PRGR_00, //spawnstate - 1100, //spawnhealth - S_PRGR_02, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_revbld, //attacksound - S_PRGR_18, //painstate - 50, //painchance - sfx_prgpn, //painsound - S_PRGR_10, //meleestate - S_PRGR_14, //missilestate - S_NULL, //crashstate - S_PRGR_20, //deathstate - S_NULL, //xdeathstate - sfx_rb2dth, //deathsound - 26, //speed - 45*FRACUNIT, //radius - 60*FRACUNIT, //height - 800, //mass - 4, //damage - sfx_progac, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST|MF_FLOAT - |MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_PROGRAMMERBASE*/ - -1, //doomednum - S_BASE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_HOOKSHOT*/ - -1, //doomednum - S_OCLW_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_chain, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_CCLW_00, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 20*FRACUNIT, //speed - 10*FRACUNIT, //radius - 14*FRACUNIT, //height - 100, //mass - 2, //damage - sfx_swish, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_CHAINSHOT*/ - -1, //doomednum - S_TEND_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_tend, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_MINIMISSLE*/ - -1, //doomednum - S_MICR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_rlaunc, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_MISL_01, //deathstate - S_NULL, //xdeathstate - sfx_mislht, //deathsound - 20*FRACUNIT, //speed - 10*FRACUNIT, //radius - 14*FRACUNIT, //height - 100, //mass - 10, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_C_MISSILE*/ - -1, //doomednum - S_MICR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_rlaunc, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_MISL_00, //deathstate - S_NULL, //xdeathstate - sfx_mislht, //deathsound - 20*FRACUNIT, //speed - 10*FRACUNIT, //radius - 14*FRACUNIT, //height - 100, //mass - 7, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_SEEKMISSILE*/ - -1, //doomednum - S_MISS_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_rlaunc, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_MISL_01, //deathstate - S_NULL, //xdeathstate - sfx_mislht, //deathsound - 20*FRACUNIT, //speed - 10*FRACUNIT, //radius - 14*FRACUNIT, //height - 100, //mass - 10, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_ELECARROW*/ - -1, //doomednum - S_AROW_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_swish, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_ZAP1_01, //deathstate - S_NULL, //xdeathstate - sfx_firxpl, //deathsound - 30*FRACUNIT, //speed - 10*FRACUNIT, //radius - 10*FRACUNIT, //height - 100, //mass - 10, //damage - sfx_swish, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_POISARROW*/ - -1, //doomednum - S_ARWP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_swish, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_AROW_01, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 30*FRACUNIT, //speed - 10*FRACUNIT, //radius - 10*FRACUNIT, //height - 100, //mass - 500, //damage - sfx_swish, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_R_LASER*/ - -1, //doomednum - S_SHT1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_POW1_09, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 40*FRACUNIT, //speed - 10*FRACUNIT, //radius - 8*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_L_LASER*/ - -1, //doomednum - S_SHT1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_plasma, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_POW1_05, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 40*FRACUNIT, //speed - 10*FRACUNIT, //radius - 8*FRACUNIT, //height - 100, //mass - 1, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_HEGRENADE*/ - -1, //doomednum - S_GRAP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_phoot, //seesound - 30, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BNG4_00, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 15*FRACUNIT, //speed - 13*FRACUNIT, //radius - 13*FRACUNIT, //height - 20, //mass - 1, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_PGRENADE*/ - -1, //doomednum - S_GRIN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_phoot, //seesound - 40, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BNG3_08, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 15*FRACUNIT, //speed - 13*FRACUNIT, //radius - 13*FRACUNIT, //height - 20, //mass - 1, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_INQGRENADE*/ - -1, //doomednum - S_UBAM_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_phoot, //seesound - 15, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BNG2_00, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 25*FRACUNIT, //speed - 13*FRACUNIT, //radius - 13*FRACUNIT, //height - 15, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_PFLAME*/ - -1, //doomednum - S_BNG3_09, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 120, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_FLBE_07, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_TORPEDO*/ - -1, //doomednum - S_TORP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_protfl, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_THIT_00, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 20*FRACUNIT, //speed - 13*FRACUNIT, //radius - 8*FRACUNIT, //height - 100, //mass - 1, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_TORPEDOSPREAD*/ - -1, //doomednum - S_TWAV_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_TWAV_02, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 35*FRACUNIT, //speed - 13*FRACUNIT, //radius - 13*FRACUNIT, //height - 100, //mass - 10, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_SFIREBALL*/ - -1, //doomednum - S_FRBL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_flburn, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_FRBL_03, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 15*FRACUNIT, //speed - 8*FRACUNIT, //radius - 11*FRACUNIT, //height - 10, //mass - 4, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_C_FLAME*/ - -1, //doomednum - S_FRBL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_flburn, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_FRBL_03, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 35*FRACUNIT, //speed - 8*FRACUNIT, //radius - 11*FRACUNIT, //height - 50, //mass - 1, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, //flags - NULL, //namepointer - }, - - { /*MT_STRIFEPUFF3*/ - -1, //doomednum - S_SHT2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_STRIFEPUFF*/ - -1, //doomednum - S_PUFY_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags - NULL, //namepointer - }, - - { /*MT_SPARKPUFF*/ - -1, //doomednum - S_POW3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_BLOOD_DEATH*/ - -1, //doomednum - S_SPRY_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_TFOG*/ - -1, //doomednum - S_TFOG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags - NULL, //namepointer - }, - - { /*MT_IFOG*/ - -1, //doomednum - S_IFOG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW, //flags - NULL, //namepointer - }, - - { /*MT_TELEPORTMAN*/ - 14, //doomednum - S_NULL, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOSECTOR|MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_01*/ - 24, //doomednum - S_KLAX_00, //spawnstate - 1000, //spawnhealth - S_KLAX_01, //seestate - sfx_None, //seesound - 60, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_STAND|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_TURRET*/ - 27, //doomednum - S_TURT_00, //spawnstate - 125, //spawnhealth - S_TURT_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_TURT_02, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_TURT_02, //missilestate - S_NULL, //crashstate - S_BALL_00, //deathstate - S_NULL, //xdeathstate - sfx_mislht, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 10000000, //mass - 0, //damage - sfx_None, //activesound - MF_SHOOTABLE|MF_STAND|MF_SPAWNCEILING|MF_NOGRAVITY|MF_NOBLOOD - |MF_COUNTKILL, //flags - NULL, //namepointer - }, - - { /*MT_GATE*/ - 45, //doomednum - S_PSTN_00, //spawnstate - 100, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_PSTN_02, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 16, //speed - 20*FRACUNIT, //radius - 76*FRACUNIT, //height - 10000000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_GIVEQUEST|MF_NODIALOG|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_COMPUTER*/ - 182, //doomednum - S_SECR_00, //spawnstate - 80, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_SECR_04, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 27, //speed - 26*FRACUNIT, //radius - 128*FRACUNIT, //height - 100000, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_GIVEQUEST|MF_NODIALOG|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_INV_MED1*/ - 2011, //doomednum - S_STMP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 20, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Med_patch", //namepointer - }, - - { /*MT_INV_MED2*/ - 2012, //doomednum - S_MDKT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 15, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Medical_kit", //namepointer - }, - - { /*MT_INV_MED3*/ - 83, //doomednum - S_FULL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 5, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Surgery_Kit", //namepointer - }, - - { /*MT_DEGNINORE*/ - 59, //doomednum - S_XPRK_01, //spawnstate - 10, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_XPRK_02, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 16*FRACUNIT, //height - 10, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags - "Degnin_Ore", //namepointer - }, - - { /*MT_INV_ARMOR2*/ - 2019, //doomednum - S_ARM1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 3, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Metal_Armor", //namepointer - }, - - { /*MT_INV_ARMOR1*/ - 2018, //doomednum - S_ARM2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 5, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Leather_Armor", //namepointer - }, - - { /*MT_MISC_22*/ - 2014, //doomednum - S_WATR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_MISC_11*/ - 164, //doomednum - S_MUGG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_KEY_BASE*/ - 230, //doomednum - S_FUSL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Base_Key", //namepointer - }, - - { /*MT_GOVSKEY*/ - -1, //doomednum - S_REBL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Govs_Key", //namepointer - }, - - { /*MT_KEY_TRAVEL*/ - 185, //doomednum - S_TPAS_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Passcard", //namepointer - }, - - { /*MT_KEY_ID_BLUE*/ - 184, //doomednum - S_CRD1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "ID_Badge", //namepointer - }, - - { /*MT_PRISONKEY*/ - -1, //doomednum - S_PRIS_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 11, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags - "Prison_Key", //namepointer - }, - - { /*MT_KEY_HAND*/ - 91, //doomednum - S_HAND_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 12, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags - "Severed_Hand", //namepointer - }, - - { /*MT_POWER1KEY*/ - -1, //doomednum - S_PWR1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Power1_Key", //namepointer - }, - - { /*MT_POWER2KEY*/ - -1, //doomednum - S_PWR2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Power2_Key", //namepointer - }, - - { /*MT_POWER3KEY*/ - -1, //doomednum - S_PWR3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Power3_Key", //namepointer - }, - - { /*MT_KEY_GOLD*/ - 40, //doomednum - S_KY1G_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Gold_Key", //namepointer - }, - - { /*MT_KEY_ID_GOLD*/ - 13, //doomednum - S_CRD2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "ID_Card", //namepointer - }, - - { /*MT_KEY_SILVER*/ - 38, //doomednum - S_KY2S_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Silver_Key", //namepointer - }, - - { /*MT_KEY_ORACLE*/ - 61, //doomednum - S_ORAC_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Oracle_Key", //namepointer - }, - - { /*MT_MILITARYID*/ - -1, //doomednum - S_GYID_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Military_ID", //namepointer - }, - - { /*MT_KEY_ORDER*/ - 86, //doomednum - S_FUBR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Order_Key", //namepointer - }, - - { /*MT_KEY_WAREHOUSE*/ - 166, //doomednum - S_WARE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Warehouse_Key", //namepointer - }, - - { /*MT_KEY_BRASS*/ - 39, //doomednum - S_KY3B_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Brass_Key", //namepointer - }, - - { /*MT_KEY_RED_CRYSTAL*/ - 192, //doomednum - S_RCRY_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Red_Crystal_Key", //namepointer - }, - - { /*MT_KEY_BLUE_CRYSTAL*/ - 193, //doomednum - S_BCRY_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Blue_Crystal_Key", //namepointer - }, - - { /*MT_KEY_CHAPEL*/ - 195, //doomednum - S_CHAP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Chapel_Key", //namepointer - }, - - { /*MT_CATACOMBKEY*/ - -1, //doomednum - S_TUNL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 28, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags - "Catacomb_Key", //namepointer - }, - - { /*MT_SECURITYKEY*/ - -1, //doomednum - S_SECK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Security_Key", //namepointer - }, - - { /*MT_KEY_CORE*/ - 236, //doomednum - S_GOID_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Core_Key", //namepointer - }, - - { /*MT_KEY_MAULER*/ - 233, //doomednum - S_BLTK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Mauler_Key", //namepointer - }, - - { /*MT_KEY_FACTORY*/ - 234, //doomednum - S_PROC_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Factory_Key", //namepointer - }, - - { /*MT_KEY_MINE*/ - 235, //doomednum - S_MINE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "MINE_KEY", //namepointer - }, - - { /*MT_NEWKEY5*/ - -1, //doomednum - S_BLTK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "New_Key5", //namepointer - }, - - { /*MT_INV_SHADOWARMOR*/ - 2024, //doomednum - S_SHD1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 2, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Shadow_armor", //namepointer - }, - - { /*MT_INV_SUIT*/ - 2025, //doomednum - S_MASK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 5, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Environmental_Suit", //namepointer - }, - - { /*MT_QUEST_UNIFORM*/ - 90, //doomednum - S_UNIF_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 15, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST, //flags - "Guard_Uniform", //namepointer - }, - - { /*MT_QUEST_GUARD_UNIFORM*/ - 52, //doomednum - S_OFIC_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Officer's_Uniform", //namepointer - }, - - { /*MT_INV_SUPERMAP*/ - 2026, //doomednum - S_PMAP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "map", //namepointer - }, - - { /*MT_INV_RADAR*/ - 2027, //doomednum - S_PMUP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 1, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "scanner", //namepointer - }, - - { /*MT_BEACON*/ - 10, //doomednum - S_BEAC_00, //spawnstate - 5, //spawnhealth - S_BEAC_01, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 16*FRACUNIT, //height - 3, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_DROPPED, //flags - "Teleporter_Beacon", //namepointer - }, - - { /*MT_INV_TARGETER*/ - 207, //doomednum - S_TARG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 5, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Targeter", //namepointer - }, - - { /*MT_MONY_1*/ - 93, //doomednum - S_COIN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 2147483647, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags - "coin", //namepointer - }, - - { /*MT_MONY_10*/ - 138, //doomednum - S_CRED_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags - "10_gold", //namepointer - }, - - { /*MT_MONY_25*/ - 139, //doomednum - S_SACK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags - "25_gold", //namepointer - }, - - { /*MT_MONY_50*/ - 140, //doomednum - S_CHST_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_DROPPED|MF_NOTDMATCH, //flags - "50_gold", //namepointer - }, - - { /*MT_MONY_300*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 3, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_DROPPED, //flags - "300_gold", //namepointer - }, - - { /*MT_TOKEN_RING*/ - -1, //doomednum - S_RING_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 1, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_NOTDMATCH, //flags - "ring", //namepointer - }, - - { /*MT_INV_CHALICE*/ - 205, //doomednum - S_RELC_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 2, //speed - 10*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_DROPPED, //flags - "Offering_Chalice", //namepointer - }, - - { /*MT_TOKEN_EAR*/ - -1, //doomednum - S_EARS_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 9, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST, //flags - "ear", //namepointer - }, - - { /*MT_INV_COMMUNICATOR*/ - 206, //doomednum - S_COMM_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_NOTDMATCH, //flags - "Communicator", //namepointer - }, - - { /*MT_AGREN*/ - 152, //doomednum - S_GRN1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "HE-Grenade_Rounds", //namepointer - }, - - { /*MT_APGREN*/ - 153, //doomednum - S_GRN2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Phosphorus-Grenade_Rounds", //namepointer - }, - - { /*MT_ACLIP*/ - 2007, //doomednum - S_BLIT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "clip_of_bullets", //namepointer - }, - - { /*MT_AAMMOBOX*/ - 2048, //doomednum - S_BBOX_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "ammo", //namepointer - }, - - { /*MT_AMINI*/ - 2010, //doomednum - S_MSSL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "mini_missiles", //namepointer - }, - - { /*MT_AMINIBOX*/ - 2046, //doomednum - S_ROKT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "crate_of_missiles", //namepointer - }, - - { /*MT_ACELL*/ - 2047, //doomednum - S_BRY1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "energy_pod", //namepointer - }, - - { /*MT_APCELL*/ - 17, //doomednum - S_CPAC_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "energy_pack", //namepointer - }, - - { /*MT_APAROW*/ - 115, //doomednum - S_PQRL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "poison_bolts", //namepointer - }, - - { /*MT_AAROW*/ - 114, //doomednum - S_XQRL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "electric_bolts", //namepointer - }, - - { /*MT_INV_SATCHEL*/ - 183, //doomednum - S_BKPK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "ammo_satchel", //namepointer - }, - - { /*MT_PULSE*/ - 2002, //doomednum - S_RIFL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "assault_gun", //namepointer - }, - - { /*MT_RIFLESTAND*/ - 2006, //doomednum - S_RIFL_01, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "assault_gun", //namepointer - }, - - { /*MT_FLAMETHROWER*/ - 2005, //doomednum - S_FLAM_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "flame_thrower", //namepointer - }, - - { /*MT_TOKEN_FLAME_THROWER_PARTS*/ - -1, //doomednum - S_BFLM_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "flame_thrower_parts", //namepointer - }, - - { /*MT_MISSILELAUNCHER*/ - 2003, //doomednum - S_MMSL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "mini_missile_launcher", //namepointer - }, - - { /*MT_BLASTER*/ - 2004, //doomednum - S_TRPD_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "mauler", //namepointer - }, - - { /*MT_CROSSBOW*/ - 2001, //doomednum - S_CBOW_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "crossbow", //namepointer - }, - - { /*MT_GRENADELAUNCHER*/ - 154, //doomednum - S_GRND_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Grenade_launcher", //namepointer - }, - - { /*MT_SIGIL_A*/ - 77, //doomednum - S_SIGL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "SIGIL", //namepointer - }, - - { /*MT_SIGIL_B*/ - 78, //doomednum - S_SIGL_01, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "SIGIL", //namepointer - }, - - { /*MT_SIGIL_C*/ - 79, //doomednum - S_SIGL_02, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "SIGIL", //namepointer - }, - - { /*MT_SIGIL_D*/ - 80, //doomednum - S_SIGL_03, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "SIGIL", //namepointer - }, - - { /*MT_SIGIL_E*/ - 81, //doomednum - S_SIGL_04, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "SIGIL", //namepointer - }, - - { /*MT_POWER_CRYSTAL*/ - 92, //doomednum - S_CRYS_00, //spawnstate - 50, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BOOM_00, //deathstate - S_NULL, //xdeathstate - sfx_explod, //deathsound - 14, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 99999999, //mass - 0, //damage - sfx_reactr, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_GIVEQUEST|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_RAT*/ - 85, //doomednum - S_RATT_00, //spawnstate - 5, //spawnhealth - S_RATT_01, //seestate - sfx_ratact, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_RATT_05, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_MEAT_16, //deathstate - S_NULL, //xdeathstate - sfx_ratact, //deathsound - 13, //speed - 10*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_ratact, //activesound - MF_NODIALOG|MF_NOBLOOD|MF_COUNTKILL, //flags - "rat_buddy", //namepointer - }, - - { /*MT_MISC_05*/ - 82, //doomednum - S_BARW_00, //spawnstate - 10, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BARW_01, //deathstate - S_NULL, //xdeathstate - sfx_wbrldt, //deathsound - 0, //speed - 10*FRACUNIT, //radius - 32*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_MISC_06*/ - 94, //doomednum - S_BART_00, //spawnstate - 30, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_BART_01, //deathstate - S_NULL, //xdeathstate - sfx_barexp, //deathsound - 0, //speed - 10*FRACUNIT, //radius - 32*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_MISC_15*/ - 208, //doomednum - S_HOGN_00, //spawnstate - 99999999, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_HOGN_01, //painstate - 255, //painchance - sfx_mtalht, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 10*FRACUNIT, //radius - 72*FRACUNIT, //height - 9999999, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_NODIALOG|MF_NOBLOOD, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT14*/ - 95, //doomednum - S_LITS_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 4*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT13*/ - 96, //doomednum - S_LITB_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 4*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT12*/ - 97, //doomednum - S_LITG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 4*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT18*/ - 2028, //doomednum - S_LITE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR2*/ - 48, //doomednum - S_MONI_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR3*/ - 54, //doomednum - S_STEL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR4*/ - 55, //doomednum - S_STLA_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 80*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR5*/ - 56, //doomednum - S_STLE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR6*/ - 57, //doomednum - S_HUGE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 24*FRACUNIT, //radius - 192*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR7*/ - 227, //doomednum - S_APOW_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 24*FRACUNIT, //radius - 192*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_amaln2, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_CAVE2*/ - 98, //doomednum - S_STLG_02, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 54*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_CAVE3*/ - 161, //doomednum - S_STLG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_CAVE4*/ - 160, //doomednum - S_STLG_01, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_CAVE6*/ - 159, //doomednum - S_STLG_03, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_CAVE7*/ - 162, //doomednum - S_STLG_04, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_CAVE5*/ - 163, //doomednum - S_STLG_05, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 25*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT2*/ - 34, //doomednum - S_CNDL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT3*/ - 35, //doomednum - S_CLBR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_03*/ - 103, //doomednum - S_DRIP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_wdrip, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_13*/ - 104, //doomednum - S_SPLH_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_wfall, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_02*/ - 53, //doomednum - S_CDRP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 1*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_MISC_07*/ - 112, //doomednum - S_WTFT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_wsplsh, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_BIO2*/ - 113, //doomednum - S_HERT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TELEPORTSTAND*/ - 23, //doomednum - S_TELP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_SHADOW, //flags - NULL, //namepointer - }, - - { /*MT_DEADTHING1*/ - 22, //doomednum - S_ROB2_28, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_DEADTHING2*/ - 15, //doomednum - S_PLAY_18, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_DEADTHING3*/ - 18, //doomednum - S_PEAS_24, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_DEADTHING4*/ - 21, //doomednum - S_AGRD_31, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_DEADTHING5*/ - 20, //doomednum - S_ROB1_25, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_DEADTHING6*/ - 19, //doomednum - S_HMN1_31, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_BIO1*/ - 212, //doomednum - S_SACR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_GIBS*/ - 54, //doomednum - S_DEAD_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_MISC_04*/ - 70, //doomednum - S_BARL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 48*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT11*/ - 105, //doomednum - S_BOWL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_smfire, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT10*/ - 106, //doomednum - S_BRAZ_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 10*FRACUNIT, //radius - 32*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_smfire, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT9*/ - 107, //doomednum - S_TRCH_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 0*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_smfire, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT8*/ - 108, //doomednum - S_TRHO_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 0*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_14*/ - 109, //doomednum - S_CHAN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 93*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT1*/ - 28, //doomednum - S_CAGE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 3*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR8*/ - 110, //doomednum - S_STAT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 64*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR9*/ - 44, //doomednum - S_DSTA_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT15*/ - 111, //doomednum - S_LTRH_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 4*FRACUNIT, //radius - 72*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT4*/ - 43, //doomednum - S_LAMP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 3*FRACUNIT, //radius - 80*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT5*/ - 46, //doomednum - S_LANT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 3*FRACUNIT, //radius - 80*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_ROCK1*/ - 99, //doomednum - S_ROK1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_ROCK2*/ - 100, //doomednum - S_ROK2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_ROCK3*/ - 101, //doomednum - S_ROK3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_ROCK4*/ - 102, //doomednum - S_ROK4_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_TREE7*/ - 215, //doomednum - S_LOGG_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_wriver, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE1*/ - 29, //doomednum - S_RUB1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE2*/ - 30, //doomednum - S_RUB2_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE3*/ - 31, //doomednum - S_RUB3_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE4*/ - 32, //doomednum - S_RUB4_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE5*/ - 36, //doomednum - S_RUB5_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE6*/ - 37, //doomednum - S_RUB6_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE7*/ - 41, //doomednum - S_RUB7_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_RUBBLE8*/ - 42, //doomednum - S_RUB8_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_08*/ - 117, //doomednum - S_CRAB_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT6*/ - 47, //doomednum - S_LMPC_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 10*FRACUNIT, //radius - 72*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_smfire, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT7*/ - 50, //doomednum - S_LOGS_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 10*FRACUNIT, //radius - 80*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_smfire, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TREE2*/ - 51, //doomednum - S_TREE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 15*FRACUNIT, //radius - 109*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TREE3*/ - 202, //doomednum - S_TREE_01, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 15*FRACUNIT, //radius - 109*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TREE4*/ - 203, //doomednum - S_TREE_02, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 15*FRACUNIT, //radius - 64*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TREE1*/ - 33, //doomednum - S_TRE1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 15*FRACUNIT, //radius - 80*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TREE6*/ - 60, //doomednum - S_BUSH_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 15*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_TREE5*/ - 62, //doomednum - S_SHRB_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 64*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_CAVE1*/ - 63, //doomednum - S_STAK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 64*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR1*/ - 69, //doomednum - S_BAR1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_10*/ - 165, //doomednum - S_VASE_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 12*FRACUNIT, //radius - 24*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_09*/ - 188, //doomednum - S_VASE_01, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 12*FRACUNIT, //radius - 32*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_17*/ - 189, //doomednum - S_STOL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 6*FRACUNIT, //radius - 24*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_18*/ - 190, //doomednum - S_POT1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_19*/ - 191, //doomednum - S_TUB1_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_20*/ - 194, //doomednum - S_ANVL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 32*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT16*/ - 196, //doomednum - S_TLMP_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 11*FRACUNIT, //radius - 64*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT17*/ - 197, //doomednum - S_TLMP_01, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 8*FRACUNIT, //radius - 64*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_21*/ - 68, //doomednum - S_TRAY_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 24*FRACUNIT, //radius - 40*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_12*/ - 228, //doomednum - S_AFED_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 12*FRACUNIT, //radius - 24*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MISC_26*/ - 216, //doomednum - S_SBAN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 24*FRACUNIT, //radius - 96*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_23*/ - 217, //doomednum - S_BOTR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_24*/ - 218, //doomednum - S_HATR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_MISC_25*/ - 219, //doomednum - S_TOPR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP, //flags - NULL, //namepointer - }, - - { /*MT_COUPLING*/ - 220, //doomednum - S_COUP_00, //spawnstate - 40, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 6, //speed - 17*FRACUNIT, //radius - 64*FRACUNIT, //height - 999999, //mass - 0, //damage - sfx_None, //activesound - MF_SOLID|MF_SHOOTABLE|MF_GIVEQUEST|MF_NODIALOG|MF_DROPPED - |MF_NOBLOOD|MF_NOTDMATCH, //flags - NULL, //namepointer - }, - - { /*MT_COUPLING_BROKEN*/ - 226, //doomednum - S_COUP_02, //spawnstate - 40, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 512*FRACUNIT, //speed - 16*FRACUNIT, //radius - 16*FRACUNIT, //height - 1, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST|MF_DROPPED, //flags - "BROKEN_POWER_COUPLING", //namepointer - }, - - { /*MT_PILLAR10*/ - 221, //doomednum - S_BUBB_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_amaln5, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR11*/ - 222, //doomednum - S_BUBF_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 72*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_amaln6, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR12*/ - 223, //doomednum - S_BUBF_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 72*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_amaln4, //activesound - MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY, //flags - NULL, //namepointer - }, - - { /*MT_PILLAR13*/ - 224, //doomednum - S_ASPR_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 16*FRACUNIT, //radius - 128*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_amaln3, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_LIGHT19*/ - 225, //doomednum - S_SPDL_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 32*FRACUNIT, //radius - 56*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_amaln1, //activesound - MF_SOLID, //flags - NULL, //namepointer - }, - - { /*MT_MEAT*/ - -1, //doomednum - S_MEAT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_JUNK*/ - -1, //doomednum - S_JUNK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_BURNDROP*/ - -1, //doomednum - S_FFOT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_NOBLOCKMAP|MF_NOCLIP, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_AMMO*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Ammo", //namepointer - }, - - { /*MT_TOKEN_HEALTH*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Health", //namepointer - }, - - { /*MT_TOKEN*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "info", //namepointer - }, - - { /*MT_TOKEN_ALARM*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "alarm", //namepointer - }, - - { /*MT_TOKEN_DOOR1*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_SHOPCLOSE*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_PRISON_PASS*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 10, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST, //flags - "Prison_pass", //namepointer - }, - - { /*MT_TOKEN_DOOR3*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_STAMINA*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_NEW_ACCURACY*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_REPORT*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "report", //namepointer - }, - - { /*MT_TOKEN_TOUGHNESS*/ - -1, //doomednum - S_HELT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Toughness", //namepointer - }, - - { /*MT_TOKEN_ACCURACY*/ - -1, //doomednum - S_GUNT_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - "Accuracy", //namepointer - }, - - { /*MT_TOKEN_ORACLE_PASS*/ - -1, //doomednum - S_OTOK_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 18, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL|MF_GIVEQUEST, //flags - "Oracle_Pass", //namepointer - }, - - { /*MT_TOKEN_QUEST1*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST2*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST3*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST4*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "quest4", //namepointer - }, - - { /*MT_TOKEN_QUEST5*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "quest5", //namepointer - }, - - { /*MT_TOKEN_QUEST6*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "quest6", //namepointer - }, - - { /*MT_TOKEN_QUEST7*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST8*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST9*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST10*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST11*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST12*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST13*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_CRYSTAL*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You've_Blown_Up_the_Crystal", //namepointer - }, - - { /*MT_TOKEN_QUEST15*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_GATEQUEST*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You've_Blown_Up_the_Gates", //namepointer - }, - - { /*MT_TOKEN_QUEST17*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST18*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST19*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST20*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_BISHOP*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You_Killed_the_Bishop!", //namepointer - }, - - { /*MT_TOKEN_QUEST22*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_ORACLE*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You've_Killed_The_Oracle!", //namepointer - }, - - { /*MT_TOKEN_MACIL*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You_Killed_Macil!", //namepointer - }, - - { /*MT_TOKEN_QUEST25*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_LOREMASTER*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You've_Killed_The_Loremaster!", //namepointer - }, - - { /*MT_SECRQUEST*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - "You've_Blown_Up_the_Computer", //namepointer - }, - - { /*MT_TOKEN_QUEST28*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST29*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST30*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_TOKEN_QUEST31*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - 0, //flags - NULL, //namepointer - }, - - { /*MT_SLIDESHOW*/ - -1, //doomednum - S_TOKN_00, //spawnstate - 1000, //spawnhealth - S_NULL, //seestate - sfx_None, //seesound - 8, //reactiontime - sfx_None, //attacksound - S_NULL, //painstate - 0, //painchance - sfx_None, //painsound - S_NULL, //meleestate - S_NULL, //missilestate - S_NULL, //crashstate - S_NULL, //deathstate - S_NULL, //xdeathstate - sfx_None, //deathsound - 0, //speed - 20*FRACUNIT, //radius - 16*FRACUNIT, //height - 100, //mass - 0, //damage - sfx_None, //activesound - MF_SPECIAL, //flags - NULL, //namepointer - }, - -}; - - - diff --git a/games/NXDoom/src/strife/info.h b/games/NXDoom/src/strife/info.h deleted file mode 100644 index 4c8edc7b61a..00000000000 --- a/games/NXDoom/src/strife/info.h +++ /dev/null @@ -1,2219 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Thing frame/state LUT, -// generated by multigen utilitiy. -// This one is the original DOOM version, preserved. -// - -#ifndef __INFO__ -#define __INFO__ - -// Needed for action function pointer handling. -#include "d_think.h" - -// villsa [STRIFE] -typedef enum -{ - SPR_PLAY, // 0 - SPR_PNCH, // 1 - SPR_WAVE, // 2 - SPR_RBPY, // 3 - SPR_TRGT, // 4 - SPR_XBOW, // 5 - SPR_MMIS, // 6 - SPR_RIFG, // 7 - SPR_RIFF, // 8 - SPR_FLMT, // 9 - SPR_FLMF, // 10 - SPR_BLST, // 11 - SPR_BLSF, // 12 - SPR_GREN, // 13 - SPR_GREF, // 14 - SPR_SIGH, // 15 - SPR_SIGF, // 16 - SPR_POW1, // 17 - SPR_POW2, // 18 - SPR_POW3, // 19 - SPR_ZAP1, // 20 - SPR_SPRY, // 21 - SPR_BLOD, // 22 - SPR_PUFY, // 23 - SPR_SHT1, // 24 - SPR_SHT2, // 25 - SPR_GRIN, // 26 - SPR_GRAP, // 27 - SPR_UBAM, // 28 - SPR_BNG2, // 29 - SPR_BNG4, // 30 - SPR_BNG3, // 31 - SPR_FLBE, // 32 - SPR_XPRK, // 33 - SPR_OCLW, // 34 - SPR_CCLW, // 35 - SPR_TEND, // 36 - SPR_MICR, // 37 - SPR_MISS, // 38 - SPR_AROW, // 39 - SPR_ARWP, // 40 - SPR_TORP, // 41 - SPR_THIT, // 42 - SPR_TWAV, // 43 - SPR_MISL, // 44 - SPR_TFOG, // 45 - SPR_IFOG, // 46 - SPR_SHRD, // 47 - SPR_RGIB, // 48 - SPR_MRYS, // 49 - SPR_MRNO, // 50 - SPR_MRST, // 51 - SPR_MRLK, // 52 - SPR_MRBD, // 53 - SPR_MRPN, // 54 - SPR_MRGT, // 55 - SPR_BURN, // 56 - SPR_DISR, // 57 - SPR_PEAS, // 58 - SPR_GIBS, // 59 - SPR_AGRD, // 60 - SPR_ARMR, // 61 - SPR_SACR, // 62 - SPR_TNK1, // 63 - SPR_TNK2, // 64 - SPR_TNK3, // 65 - SPR_TNK4, // 66 - SPR_TNK5, // 67 - SPR_TNK6, // 68 - SPR_NEAL, // 69 - SPR_BEGR, // 70 - SPR_HMN1, // 71 - SPR_LEDR, // 72 - SPR_LEAD, // 73 - SPR_ROB1, // 74 - SPR_PGRD, // 75 - SPR_ROB2, // 76 - SPR_MLDR, // 77 - SPR_ORCL, // 78 - SPR_PRST, // 79 - SPR_PDED, // 80 - SPR_ALN1, // 81 - SPR_AL1P, // 82 - SPR_NODE, // 83 - SPR_MTHD, // 84 - SPR_MNAM, // 85 - SPR_MNAL, // 86 - SPR_MDTH, // 87 - SPR_NEST, // 88 - SPR_PODD, // 89 - SPR_ZAP6, // 90 - SPR_ZOT3, // 91 - SPR_ZAP7, // 92 - SPR_ZOT1, // 93 - SPR_ZAP5, // 94 - SPR_ZOT2, // 95 - SPR_SEWR, // 96 - SPR_SPID, // 97 - SPR_ROB3, // 98 - SPR_RBB3, // 99 - SPR_PRGR, // 100 - SPR_BASE, // - SPR_FRBL, // - SPR_KLAX, // - SPR_TURT, // - SPR_BALL, // 105 - SPR_PSTN, // - SPR_SECR, // - SPR_TARG, // - SPR_RING, // - SPR_EARS, // 110 - SPR_COMM, // - SPR_BOOM, // - SPR_RATT, // - SPR_HOGN, // - SPR_DEAD, // 115 - SPR_SBAN, // - SPR_BOTR, // - SPR_HATR, // - SPR_TOPR, // - SPR_COUP, // 120 - SPR_BUBB, // - SPR_BUBF, // - SPR_BUBC, // - SPR_ASPR, // - SPR_SPDL, // 125 - SPR_TOKN, // - SPR_OTOK, // - SPR_HELT, // - SPR_GUNT, // - SPR_FULL, // 130 - SPR_MEAT, // - SPR_JUNK, // - SPR_FFOT, // - SPR_DIE1, // - SPR_BEAC, // 135 - SPR_ARM1, // - SPR_ARM2, // - SPR_BARW, // - SPR_BART, // - SPR_LAMP, // 140 - SPR_LANT, // - SPR_BARL, // - SPR_BOWL, // - SPR_BRAZ, // - SPR_TRCH, // 145 - SPR_LTRH, // - SPR_LMPC, // - SPR_LOGS, // - SPR_TRHO, // - SPR_WATR, // 150 - SPR_MUGG, // - SPR_FUSL, // - SPR_CRD1, // - SPR_CRD2, // - SPR_TPAS, // 155 - SPR_KY1G, // - SPR_KY2S, // - SPR_KY3B, // - SPR_HAND, // - SPR_CRYS, // 160 - SPR_PRIS, // - SPR_PWR1, // - SPR_PWR2, // - SPR_PWR3, // - SPR_ORAC, // 165 - SPR_GYID, // - SPR_FUBR, // - SPR_WARE, // - SPR_RCRY, // - SPR_BCRY, // 170 - SPR_CHAP, // - SPR_TUNL, // - SPR_BLTK, // - SPR_SECK, // - SPR_MINE, // 175 - SPR_REBL, // - SPR_PROC, // - SPR_ANKH, // - SPR_GOID, // - SPR_STMP, // 180 - SPR_MDKT, // - SPR_COIN, // - SPR_CRED, // - SPR_SACK, // - SPR_CHST, // 185 - SPR_SHD1, // - SPR_MASK, // - SPR_UNIF, // - SPR_OFIC, // - SPR_PMAP, // 190 - SPR_PMUP, // - SPR_BLIT, // - SPR_BBOX, // - SPR_MSSL, // - SPR_ROKT, // 195 - SPR_BRY1, // - SPR_CPAC, // - SPR_PQRL, // - SPR_XQRL, // - SPR_GRN1, // 200 - SPR_GRN2, // - SPR_BKPK, // - SPR_RELC, // - SPR_RIFL, // - SPR_FLAM, // 205 - SPR_BFLM, // - SPR_MMSL, // - SPR_TRPD, // - SPR_GRND, // - SPR_CBOW, // 210 - SPR_SIGL, // - SPR_LITE, // - SPR_CNDL, // - SPR_CLBR, // - SPR_LITS, // 215 - SPR_LITB, // - SPR_LITG, // - SPR_ROK1, // - SPR_ROK2, // - SPR_ROK3, // 220 - SPR_ROK4, // - SPR_LOGG, // - SPR_RUB1, // - SPR_RUB2, // - SPR_RUB3, // 225 - SPR_RUB4, // - SPR_RUB5, // - SPR_RUB6, // - SPR_RUB7, // - SPR_RUB8, // 230 - SPR_CHAN, // - SPR_STAT, // - SPR_DSTA, // - SPR_CRAB, // - SPR_CAGE, // 235 - SPR_TREE, // - SPR_TRE1, // - SPR_BUSH, // - SPR_SHRB, // - SPR_STAK, // 240 - SPR_BAR1, // - SPR_VASE, // - SPR_STOL, // - SPR_POT1, // - SPR_TUB1, // 245 - SPR_ANVL, // - SPR_TLMP, // - SPR_TRAY, // - SPR_APOW, // - SPR_AFED, // 250 - SPR_DRIP, // - SPR_CDRP, // - SPR_SPLH, // - SPR_WTFT, // - SPR_HERT, // - SPR_TELP, // - SPR_MONI, // - SPR_STEL, // - SPR_STLA, // - SPR_STLE, // 260 - SPR_HUGE, // 261 - SPR_STLG, // 262 - NUMSPRITES - -} spritenum_t; - -// villsa [STRIFE] -typedef enum -{ - S_NULL, // 00 - S_PNCH_00, // 01 - S_WAVE_00, // 02 - S_WAVE_01, // 03 - S_WAVE_02, // 04 - S_WAVE_03, // 05 - S_RBPY_00, // 06 - S_RBPY_01, // 07 - S_RBPY_02, // 08 - S_RBPY_03, // 09 - S_TRGT_00, // 10 - S_TRGT_01, // 11 - S_TRGT_02, // 12 - S_PNCH_01, // 13 - S_PNCH_02, // 14 - S_PNCH_03, // 15 - S_PNCH_04, // 16 - S_PNCH_05, // 17 - S_PNCH_06, // 18 - S_PNCH_07, // 19 - S_PNCH_08, // 20 - S_XBOW_00, // 21 - S_XBOW_01, // 22 - S_XBOW_02, // 23 - S_XBOW_03, // 24 - S_XBOW_04, // 25 - S_XBOW_05, // 26 - S_XBOW_06, // 27 - S_XBOW_07, // 28 - S_XBOW_08, // 29 - S_XBOW_09, // 30 - S_XBOW_10, // 31 - S_XBOW_11, // 32 - S_XBOW_12, // 33 - S_XBOW_13, // 34 - S_XBOW_14, // 35 - S_XBOW_15, // 36 - S_XBOW_16, // 37 - S_XBOW_17, // 38 - S_XBOW_18, // 39 - S_XBOW_19, // 40 - S_XBOW_20, // 41 - S_XBOW_21, // 42 - S_XBOW_22, // 43 - S_MMIS_00, // 44 - S_MMIS_01, // 45 - S_MMIS_02, // 46 - S_MMIS_03, // 47 - S_MMIS_04, // 48 - S_MMIS_05, // 49 - S_MMIS_06, // 50 - S_MMIS_07, // 51 - S_MMIS_08, // 52 - S_MMIS_09, // 53 - S_RIFG_00, // 54 - S_RIFG_01, // 55 - S_RIFG_02, // 56 - S_RIFF_00, // 57 - S_RIFF_01, // 58 - S_RIFG_03, // 59 - S_RIFG_04, // 60 - S_RIFG_05, // 61 - S_FLMT_00, // 62 - S_FLMT_01, // 63 - S_FLMT_02, // 64 - S_FLMT_03, // 65 - S_FLMF_00, // 66 - S_FLMF_01, // 67 - S_BLST_00, // 68 - S_BLST_01, // 69 - S_BLST_02, // 70 - S_BLST_03, // 71 - S_BLST_04, // 72 - S_BLST_05, // 73 - S_BLSF_00, // 74 - S_BLST_06, // 75 - S_BLST_07, // 76 - S_BLST_08, // 77 - S_BLST_09, // 78 - S_BLST_10, // 79 - S_BLST_11, // 80 - S_BLST_12, // 81 - S_BLST_13, // 82 - S_BLST_14, // 83 - S_BLST_15, // 84 - S_BLST_16, // 85 - S_BLST_17, // 86 - S_BLST_18, // 87 - S_BLST_19, // 88 - S_BLST_20, // 89 - S_BLSF_01, // 90 - S_BLST_21, // 91 - S_BLST_22, // 92 - S_BLST_23, // 93 - S_BLST_24, // 94 - S_GREN_00, // 95 - S_GREN_01, // 96 - S_GREN_02, // 97 - S_GREN_03, // 98 - S_GREN_04, // 99 - S_GREN_05, // 100 - S_GREN_06, // 101 - S_GREN_07, // 102 - S_GREF_00, // 103 - S_GREF_01, // 104 - S_GREF_02, // 105 - S_GREN_08, // 106 - S_GREN_09, // 107 - S_GREN_10, // 108 - S_GREN_11, // 109 - S_GREN_12, // 110 - S_GREN_13, // 111 - S_GREN_14, // 112 - S_GREN_15, // 113 - S_GREF_03, // 114 - S_GREF_04, // 115 - S_GREF_05, // 116 - S_SIGH_00, // 117 - S_SIGH_01, // 118 - S_SIGH_02, // 119 - S_SIGH_03, // 120 - S_SIGH_04, // 121 - S_SIGH_05, // 122 - S_SIGH_06, // 123 - S_SIGH_07, // 124 - S_SIGH_08, // 125 - S_SIGH_09, // 126 - S_SIGH_10, // 127 - S_SIGF_00, // 128 - S_SIGF_01, // 129 - S_SIGF_02, // 130 - S_POW1_00, // 131 - S_POW1_01, // 132 - S_POW1_02, // 133 - S_POW1_03, // 134 - S_POW1_04, // 135 - S_POW1_05, // 136 - S_POW1_06, // 137 - S_POW1_07, // 138 - S_POW1_08, // 139 - S_POW1_09, // 140 - S_POW2_00, // 141 - S_POW2_01, // 142 - S_POW2_02, // 143 - S_POW2_03, // 144 - S_POW3_00, // 145 - S_POW3_01, // 146 - S_POW3_02, // 147 - S_POW3_03, // 148 - S_POW3_04, // 149 - S_POW3_05, // 150 - S_POW3_06, // 151 - S_POW3_07, // 152 - S_ZAP1_00, // 153 - S_ZAP1_01, // 154 - S_ZAP1_02, // 155 - S_ZAP1_03, // 156 - S_ZAP1_04, // 157 - S_ZAP1_05, // 158 - S_ZAP1_06, // 159 - S_ZAP1_07, // 160 - S_ZAP1_08, // 161 - S_ZAP1_09, // 162 - S_ZAP1_10, // 163 - S_ZAP1_11, // 164 - S_SPRY_00, // 165 - S_SPRY_01, // 166 - S_SPRY_02, // 167 - S_SPRY_03, // 168 - S_SPRY_04, // 169 - S_SPRY_05, // 170 - S_SPRY_06, // 171 - S_BLOD_00, // 172 - S_BLOD_01, // 173 - S_BLOD_02, // 174 - S_PUFY_00, // 175 - S_PUFY_01, // 176 - S_PUFY_02, // 177 - S_PUFY_03, // 178 - S_SHT1_00, // 179 - S_SHT1_01, // 180 - S_SHT2_00, // 181 - S_SHT2_01, // 182 - S_GRIN_00, // 183 - S_GRIN_01, // 184 - S_GRAP_00, // 185 - S_GRAP_01, // 186 - S_UBAM_00, // 187 - S_UBAM_01, // 188 - S_BNG2_00, // 189 - S_BNG2_01, // 190 - S_BNG2_02, // 191 - S_BNG2_03, // 192 - S_BNG2_04, // 193 - S_BNG2_05, // 194 - S_BNG2_06, // 195 - S_BNG2_07, // 196 - S_BNG2_08, // 197 - S_BNG4_00, // 198 - S_BNG4_01, // 199 - S_BNG4_02, // 200 - S_BNG4_03, // 201 - S_BNG4_04, // 202 - S_BNG4_05, // 203 - S_BNG4_06, // 204 - S_BNG4_07, // 205 - S_BNG4_08, // 206 - S_BNG4_09, // 207 - S_BNG4_10, // 208 - S_BNG4_11, // 209 - S_BNG4_12, // 210 - S_BNG4_13, // 211 - S_BNG3_00, // 212 - S_BNG3_01, // 213 - S_BNG3_02, // 214 - S_BNG3_03, // 215 - S_BNG3_04, // 216 - S_BNG3_05, // 217 - S_BNG3_06, // 218 - S_BNG3_07, // 219 - S_BNG3_08, // 220 - S_BNG3_09, // 221 - S_BNG3_10, // 222 - S_FLBE_00, // 223 - S_FLBE_01, // 224 - S_FLBE_02, // 225 - S_FLBE_03, // 226 - S_FLBE_04, // 227 - S_FLBE_05, // 228 - S_FLBE_06, // 229 - S_FLBE_07, // 230 - S_FLBE_08, // 231 - S_FLBE_09, // 232 - S_FLBE_10, // 233 - S_XPRK_00, // 234 - S_OCLW_00, // 235 - S_CCLW_00, // 236 - S_TEND_00, // 237 - S_MICR_00, // 238 - S_MISS_00, // 239 - S_MISS_01, // 240 - S_AROW_00, // 241 - S_ARWP_00, // 242 - S_AROW_01, // 243 - S_TORP_00, // 244 - S_TORP_01, // 245 - S_TORP_02, // 246 - S_TORP_03, // 247 - S_THIT_00, // 248 - S_THIT_01, // 249 - S_THIT_02, // 250 - S_THIT_03, // 251 - S_THIT_04, // 252 - S_TWAV_00, // 253 - S_TWAV_01, // 254 - S_TWAV_02, // 255 - S_MISL_00, // 256 - S_MISL_01, // 257 - S_MISL_02, // 258 - S_MISL_03, // 259 - S_MISL_04, // 260 - S_MISL_05, // 261 - S_MISL_06, // 262 - S_MISL_07, // 263 - S_TFOG_00, // 264 - S_TFOG_01, // 265 - S_TFOG_02, // 266 - S_TFOG_03, // 267 - S_TFOG_04, // 268 - S_TFOG_05, // 269 - S_TFOG_06, // 270 - S_TFOG_07, // 271 - S_TFOG_08, // 272 - S_TFOG_09, // 273 - S_IFOG_00, // 274 - S_IFOG_01, // 275 - S_IFOG_02, // 276 - S_IFOG_03, // 277 - S_IFOG_04, // 278 - S_IFOG_05, // 279 - S_IFOG_06, // 280 - S_SHRD_00, // 281 - S_SHRD_01, // 282 - S_SHRD_02, // 283 - S_SHRD_03, // 284 - S_SHRD_04, // 285 - S_SHRD_05, // 286 - S_PLAY_00, // 287 - S_PLAY_01, // 288 - S_PLAY_02, // 289 - S_PLAY_03, // 290 - S_PLAY_04, // 291 - S_PLAY_05, // 292 - S_PLAY_06, // 293 - S_PLAY_07, // 294 - S_PLAY_08, // 295 - S_PLAY_09, // 296 - S_PLAY_10, // 297 - S_PLAY_11, // 298 - S_PLAY_12, // 299 - S_PLAY_13, // 300 - S_PLAY_14, // 301 - S_PLAY_15, // 302 - S_PLAY_16, // 303 - S_PLAY_17, // 304 - S_PLAY_18, // 305 - S_RGIB_00, // 306 - S_RGIB_01, // 307 - S_RGIB_02, // 308 - S_RGIB_03, // 309 - S_RGIB_04, // 310 - S_RGIB_05, // 311 - S_RGIB_06, // 312 - S_RGIB_07, // 313 - S_MRYS_00, // 314 - S_MRNO_00, // 315 - S_MRNO_01, // 316 - S_MRNO_02, // 317 - S_MRNO_03, // 318 - S_MRNO_04, // 319 - S_MRST_00, // 320 - S_MRLK_00, // 321 - S_MRLK_01, // 322 - S_MRBD_00, // 323 - S_MRBD_01, // 324 - S_MRBD_02, // 325 - S_MRBD_03, // 326 - S_MRBD_04, // 327 - S_MRBD_05, // 328 - S_MRBD_06, // 329 - S_MRBD_07, // 330 - S_MRBD_08, // 331 - S_MRBD_09, // 332 - S_MRPN_00, // 333 - S_MRPN_01, // 334 - S_MRPN_02, // 335 - S_MRPN_03, // 336 - S_MRPN_04, // 337 - S_MRPN_05, // 338 - S_MRPN_06, // 339 - S_MRGT_00, // 340 - S_MRGT_01, // 341 - S_MRGT_02, // 342 - S_MRGT_03, // 343 - S_MRGT_04, // 344 - S_MRGT_05, // 345 - S_MRGT_06, // 346 - S_MRGT_07, // 347 - S_MRGT_08, // 348 - S_BURN_00, // 349 - S_BURN_01, // 350 - S_BURN_02, // 351 - S_BURN_03, // 352 - S_BURN_04, // 353 - S_BURN_05, // 354 - S_BURN_06, // 355 - S_BURN_07, // 356 - S_BURN_08, // 357 - S_BURN_09, // 358 - S_BURN_10, // 359 - S_BURN_11, // 360 - S_BURN_12, // 361 - S_BURN_13, // 362 - S_BURN_14, // 363 - S_BURN_15, // 364 - S_BURN_16, // 365 - S_BURN_17, // 366 - S_BURN_18, // 367 - S_BURN_19, // 368 - S_BURN_20, // 369 - S_BURN_21, // 370 - S_BURN_22, // 371 - S_BURN_23, // 372 - S_DISR_00, // 373 - S_DISR_01, // 374 - S_DISR_02, // 375 - S_DISR_03, // 376 - S_DISR_04, // 377 - S_DISR_05, // 378 - S_DISR_06, // 379 - S_DISR_07, // 380 - S_DISR_08, // 381 - S_DISR_09, // 382 - S_PEAS_00, // 383 - S_PEAS_01, // 384 - S_PEAS_02, // 385 - S_PEAS_03, // 386 - S_PEAS_04, // 387 - S_PEAS_05, // 388 - S_PEAS_06, // 389 - S_PEAS_07, // 390 - S_PEAS_08, // 391 - S_PEAS_09, // 392 - S_PEAS_10, // 393 - S_PEAS_11, // 394 - S_PEAS_12, // 395 - S_PEAS_13, // 396 - S_PEAS_14, // 397 - S_PEAS_15, // 398 - S_PEAS_16, // 399 - S_PEAS_17, // 400 - S_PEAS_18, // 401 - S_PEAS_19, // 402 - S_PEAS_20, // 403 - S_PEAS_21, // 404 - S_PEAS_22, // 405 - S_PEAS_23, // 406 - S_PEAS_24, // 407 - S_GIBS_00, // 408 - S_GIBS_01, // 409 - S_GIBS_02, // 410 - S_GIBS_03, // 411 - S_GIBS_04, // 412 - S_GIBS_05, // 413 - S_GIBS_06, // 414 - S_GIBS_07, // 415 - S_GIBS_08, // 416 - S_GIBS_09, // 417 - S_PEAS_25, // 418 - S_AGRD_00, // 419 - S_ARMR_00, // 420 - S_ARMR_01, // 421 - S_PLAY_19, // 422 - S_SACR_00, // 423 - S_TNK1_00, // 424 - S_TNK1_01, // 425 - S_TNK1_02, // 426 - S_TNK2_00, // 427 - S_TNK2_01, // 428 - S_TNK2_02, // 429 - S_TNK3_00, // 430 - S_TNK3_01, // 431 - S_TNK3_02, // 432 - S_TNK4_00, // 433 - S_TNK4_01, // 434 - S_TNK4_02, // 435 - S_TNK5_00, // 436 - S_TNK5_01, // 437 - S_TNK5_02, // 438 - S_TNK6_00, // 439 - S_TNK6_01, // 440 - S_TNK6_02, // 441 - S_NEAL_00, // 442 - S_NEAL_01, // 443 - S_NEAL_02, // 444 - S_NEAL_03, // 445 - S_NEAL_04, // 446 - S_NEAL_05, // 447 - S_NEAL_06, // 448 - S_NEAL_07, // 449 - S_NEAL_08, // 450 - S_NEAL_09, // 451 - S_NEAL_10, // 452 - S_NEAL_11, // 453 - S_NEAL_12, // 454 - S_NEAL_13, // 455 - S_BEGR_00, // 456 - S_BEGR_01, // 457 - S_BEGR_02, // 458 - S_BEGR_03, // 459 - S_BEGR_04, // 460 - S_BEGR_05, // 461 - S_BEGR_06, // 462 - S_BEGR_07, // 463 - S_BEGR_08, // 464 - S_BEGR_09, // 465 - S_BEGR_10, // 466 - S_BEGR_11, // 467 - S_BEGR_12, // 468 - S_BEGR_13, // 469 - S_BEGR_14, // 470 - S_BEGR_15, // 471 - S_BEGR_16, // 472 - S_BEGR_17, // 473 - S_BEGR_18, // 474 - S_BEGR_19, // 475 - S_BEGR_20, // 476 - S_BEGR_21, // 477 - S_BEGR_22, // 478 - S_HMN1_00, // 479 - S_HMN1_01, // 480 - S_HMN1_02, // 481 - S_HMN1_03, // 482 - S_HMN1_04, // 483 - S_HMN1_05, // 484 - S_HMN1_06, // 485 - S_HMN1_07, // 486 - S_HMN1_08, // 487 - S_HMN1_09, // 488 - S_HMN1_10, // 489 - S_HMN1_11, // 490 - S_HMN1_12, // 491 - S_HMN1_13, // 492 - S_HMN1_14, // 493 - S_HMN1_15, // 494 - S_HMN1_16, // 495 - S_HMN1_17, // 496 - S_HMN1_18, // 497 - S_HMN1_19, // 498 - S_HMN1_20, // 499 - S_HMN1_21, // 500 - S_HMN1_22, // 501 - S_HMN1_23, // 502 - S_HMN1_24, // 503 - S_HMN1_25, // 504 - S_HMN1_26, // 505 - S_HMN1_27, // 506 - S_HMN1_28, // 507 - S_HMN1_29, // 508 - S_HMN1_30, // 509 - S_HMN1_31, // 510 - S_RGIB_08, // 511 - S_RGIB_09, // 512 - S_RGIB_10, // 513 - S_RGIB_11, // 514 - S_RGIB_12, // 515 - S_RGIB_13, // 516 - S_RGIB_14, // 517 - S_RGIB_15, // 518 - S_LEDR_00, // 519 - S_LEDR_01, // 520 - S_LEDR_02, // 521 - S_LEAD_00, // 522 - S_LEAD_01, // 523 - S_LEAD_02, // 524 - S_LEAD_03, // 525 - S_LEAD_04, // 526 - S_LEAD_05, // 527 - S_LEAD_06, // 528 - S_LEAD_07, // 529 - S_LEAD_08, // 530 - S_LEAD_09, // 531 - S_LEAD_10, // 532 - S_LEAD_11, // 533 - S_LEAD_12, // 534 - S_LEAD_13, // 535 - S_LEAD_14, // 536 - S_LEAD_15, // 537 - S_LEAD_16, // 538 - S_LEAD_17, // 539 - S_LEAD_18, // 540 - S_LEAD_19, // 541 - S_LEAD_20, // 542 - S_LEAD_21, // 543 - S_LEAD_22, // 544 - S_LEAD_23, // 545 - S_LEAD_24, // 546 - S_LEAD_25, // 547 - S_LEAD_26, // 548 - S_LEAD_27, // 549 - S_LEAD_28, // 550 - S_LEAD_29, // 551 - S_LEAD_30, // 552 - S_LEAD_31, // 553 - S_LEAD_32, // 554 - S_LEAD_33, // 555 - S_LEAD_34, // 556 - S_LEAD_35, // 557 - S_LEAD_36, // 558 - S_LEAD_37, // 559 - S_PUFY_04, // 560 - S_PUFY_05, // 561 - S_PUFY_06, // 562 - S_PUFY_07, // 563 - S_PUFY_08, // 564 - S_MICR_01, // 565 - S_MICR_02, // 566 - S_ROB1_00, // 567 - S_ROB1_01, // 568 - S_ROB1_02, // 569 - S_ROB1_03, // 570 - S_ROB1_04, // 571 - S_ROB1_05, // 572 - S_ROB1_06, // 573 - S_ROB1_07, // 574 - S_ROB1_08, // 575 - S_ROB1_09, // 576 - S_ROB1_10, // 577 - S_ROB1_11, // 578 - S_ROB1_12, // 579 - S_ROB1_13, // 580 - S_ROB1_14, // 581 - S_ROB1_15, // 582 - S_ROB1_16, // 583 - S_ROB1_17, // 584 - S_ROB1_18, // 585 - S_ROB1_19, // 586 - S_ROB1_20, // 587 - S_ROB1_21, // 588 - S_ROB1_22, // 589 - S_ROB1_23, // 590 - S_ROB1_24, // 591 - S_ROB1_25, // 592 - S_ROB1_26, // 593 - S_ROB1_27, // 594 - S_ROB1_28, // 595 - S_ROB1_29, // 596 - S_ROB1_30, // 597 - S_ROB1_31, // 598 - S_ROB1_32, // 599 - S_AGRD_01, // 600 - S_AGRD_02, // 601 - S_AGRD_03, // 602 - S_AGRD_04, // 603 - S_AGRD_05, // 604 - S_AGRD_06, // 605 - S_AGRD_07, // 606 - S_AGRD_08, // 607 - S_AGRD_09, // 608 - S_AGRD_10, // 609 - S_AGRD_11, // 610 - S_AGRD_12, // 611 - S_AGRD_13, // 612 - S_AGRD_14, // 613 - S_AGRD_15, // 614 - S_AGRD_16, // 615 - S_AGRD_17, // 616 - S_AGRD_18, // 617 - S_AGRD_19, // 618 - S_AGRD_20, // 619 - S_AGRD_21, // 620 - S_AGRD_22, // 621 - S_AGRD_23, // 622 - S_AGRD_24, // 623 - S_AGRD_25, // 624 - S_AGRD_26, // 625 - S_AGRD_27, // 626 - S_AGRD_28, // 627 - S_AGRD_29, // 628 - S_AGRD_30, // 629 - S_AGRD_31, // 630 - S_GIBS_10, // 631 - S_GIBS_11, // 632 - S_GIBS_12, // 633 - S_GIBS_13, // 634 - S_GIBS_14, // 635 - S_GIBS_15, // 636 - S_GIBS_16, // 637 - S_GIBS_17, // 638 - S_GIBS_18, // 639 - S_GIBS_19, // 640 - S_GIBS_20, // 641 - S_GIBS_21, // 642 - S_PGRD_00, // 643 - S_PGRD_01, // 644 - S_PGRD_02, // 645 - S_PGRD_03, // 646 - S_PGRD_04, // 647 - S_PGRD_05, // 648 - S_PGRD_06, // 649 - S_PGRD_07, // 650 - S_PGRD_08, // 651 - S_PGRD_09, // 652 - S_PGRD_10, // 653 - S_PGRD_11, // 654 - S_PGRD_12, // 655 - S_PGRD_13, // 656 - S_PGRD_14, // 657 - S_PGRD_15, // 658 - S_PGRD_16, // 659 - S_PGRD_17, // 660 - S_PGRD_18, // 661 - S_PGRD_19, // 662 - S_PGRD_20, // 663 - S_PGRD_21, // 664 - S_PGRD_22, // 665 - S_PGRD_23, // 666 - S_PGRD_24, // 667 - S_PGRD_25, // 668 - S_PGRD_26, // 669 - S_PGRD_27, // 670 - S_PGRD_28, // 671 - S_PGRD_29, // 672 - S_PGRD_30, // 673 - S_PGRD_31, // 674 - S_PGRD_32, // 675 - S_PGRD_33, // 676 - S_PGRD_34, // 677 - S_PGRD_35, // 678 - S_PGRD_36, // 679 - S_PGRD_37, // 680 - S_ROB2_00, // 681 - S_ROB2_01, // 682 - S_ROB2_02, // 683 - S_ROB2_03, // 684 - S_ROB2_04, // 685 - S_ROB2_05, // 686 - S_ROB2_06, // 687 - S_ROB2_07, // 688 - S_ROB2_08, // 689 - S_ROB2_09, // 690 - S_ROB2_10, // 691 - S_ROB2_11, // 692 - S_ROB2_12, // 693 - S_ROB2_13, // 694 - S_ROB2_14, // 695 - S_ROB2_15, // 696 - S_ROB2_16, // 697 - S_ROB2_17, // 698 - S_ROB2_18, // 699 - S_ROB2_19, // 700 - S_ROB2_20, // 701 - S_ROB2_21, // 702 - S_ROB2_22, // 703 - S_ROB2_23, // 704 - S_ROB2_24, // 705 - S_ROB2_25, // 706 - S_ROB2_26, // 707 - S_ROB2_27, // 708 - S_ROB2_28, // 709 - S_ROB2_29, // 710 - S_MLDR_00, // 711 - S_MLDR_01, // 712 - S_MLDR_02, // 713 - S_MLDR_03, // 714 - S_MLDR_04, // 715 - S_MLDR_05, // 716 - S_MLDR_06, // 717 - S_MLDR_07, // 718 - S_MLDR_08, // 719 - S_MLDR_09, // 720 - S_MLDR_10, // 721 - S_MLDR_11, // 722 - S_MLDR_12, // 723 - S_MLDR_13, // 724 - S_MLDR_14, // 725 - S_MLDR_15, // 726 - S_MLDR_16, // 727 - S_MLDR_17, // 728 - S_MLDR_18, // 729 - S_MLDR_19, // 730 - S_MLDR_20, // 731 - S_MLDR_21, // 732 - S_MLDR_22, // 733 - S_MLDR_23, // 734 - S_MLDR_24, // 735 - S_MLDR_25, // 736 - S_MLDR_26, // 737 - S_MLDR_27, // 738 - S_ORCL_00, // 739 - S_ORCL_01, // 740 - S_ORCL_02, // 741 - S_ORCL_03, // 742 - S_ORCL_04, // 743 - S_ORCL_05, // 744 - S_ORCL_06, // 745 - S_ORCL_07, // 746 - S_ORCL_08, // 747 - S_ORCL_09, // 748 - S_ORCL_10, // 749 - S_ORCL_11, // 750 - S_ORCL_12, // 751 - S_ORCL_13, // 752 - S_ORCL_14, // 753 - S_ORCL_15, // 754 - S_ORCL_16, // 755 - S_PRST_00, // 756 - S_PRST_01, // 757 - S_PRST_02, // 758 - S_PRST_03, // 759 - S_PRST_04, // 760 - S_PRST_05, // 761 - S_PRST_06, // 762 - S_PRST_07, // 763 - S_PRST_08, // 764 - S_PRST_09, // 765 - S_PRST_10, // 766 - S_PRST_11, // 767 - S_PRST_12, // 768 - S_PRST_13, // 769 - S_PRST_14, // 770 - S_PRST_15, // 771 - S_PDED_00, // 772 - S_PDED_01, // 773 - S_PDED_02, // 774 - S_PDED_03, // 775 - S_PDED_04, // 776 - S_PDED_05, // 777 - S_PDED_06, // 778 - S_PDED_07, // 779 - S_PDED_08, // 780 - S_PDED_09, // 781 - S_PDED_10, // 782 - S_PDED_11, // 783 - S_PDED_12, // 784 - S_PDED_13, // 785 - S_PDED_14, // 786 - S_PDED_15, // 787 - S_PDED_16, // 788 - S_PDED_17, // 789 - S_PDED_18, // 790 - S_PDED_19, // 791 - S_PDED_20, // 792 - S_PDED_21, // 793 - S_PDED_22, // 794 - S_PDED_23, // 795 - S_ALN1_00, // 796 - S_ALN1_01, // 797 - S_ALN1_02, // 798 - S_ALN1_03, // 799 - S_ALN1_04, // 800 - S_ALN1_05, // 801 - S_ALN1_06, // 802 - S_ALN1_07, // 803 - S_ALN1_08, // 804 - S_ALN1_09, // 805 - S_ALN1_10, // 806 - S_ALN1_11, // 807 - S_ALN1_12, // 808 - S_ALN1_13, // 809 - S_ALN1_14, // 810 - S_ALN1_15, // 811 - S_ALN1_16, // 812 - S_ALN1_17, // 813 - S_ALN1_18, // 814 - S_ALN1_19, // 815 - S_AL1P_00, // 816 - S_AL1P_01, // 817 - S_AL1P_02, // 818 - S_AL1P_03, // 819 - S_AL1P_04, // 820 - S_AL1P_05, // 821 - S_AL1P_06, // 822 - S_AL1P_07, // 823 - S_AL1P_08, // 824 - S_AL1P_09, // 825 - S_AL1P_10, // 826 - S_AL1P_11, // 827 - S_AL1P_12, // 828 - S_AL1P_13, // 829 - S_AL1P_14, // 830 - S_AL1P_15, // 831 - S_AL1P_16, // 832 - S_AL1P_17, // 833 - S_NODE_00, // 834 - S_NODE_01, // 835 - S_NODE_02, // 836 - S_NODE_03, // 837 - S_NODE_04, // 838 - S_NODE_05, // 839 - S_NODE_06, // 840 - S_MTHD_00, // 841 - S_MTHD_01, // 842 - S_MTHD_02, // 843 - S_MTHD_03, // 844 - S_MTHD_04, // 845 - S_MTHD_05, // 846 - S_MTHD_06, // 847 - S_MTHD_07, // 848 - S_MTHD_08, // 849 - S_MTHD_09, // 850 - S_MTHD_10, // 851 - S_ALN1_20, // 852 - S_ALN1_21, // 853 - S_ALN1_22, // 854 - S_ALN1_23, // 855 - S_ALN1_24, // 856 - S_ALN1_25, // 857 - S_ALN1_26, // 858 - S_ALN1_27, // 859 - S_ALN1_28, // 860 - S_ALN1_29, // 861 - S_ALN1_30, // 862 - S_ALN1_31, // 863 - S_ALN1_32, // 864 - S_ALN1_33, // 865 - S_ALN1_34, // 866 - S_ALN1_35, // 867 - S_ALN1_36, // 868 - S_ALN1_37, // 869 - S_ALN1_38, // 870 - S_ALN1_39, // 871 - S_ALN1_40, // 872 - S_ALN1_41, // 873 - S_ALN1_42, // 874 - S_ALN1_43, // 875 - S_ALN1_44, // 876 - S_ALN1_45, // 877 - S_ALN1_46, // 878 - S_ALN1_47, // 879 - S_ALN1_48, // 880 - S_ALN1_49, // 881 - S_ALN1_50, // 882 - S_ALN1_51, // 883 - S_ALN1_52, // 884 - S_ALN1_53, // 885 - S_ALN1_54, // 886 - S_ALN1_55, // 887 - S_ALN1_56, // 888 - S_ALN1_57, // 889 - S_MNAM_00, // 890 - S_MNAM_01, // 891 - S_MNAM_02, // 892 - S_MNAM_03, // 893 - S_MNAM_04, // 894 - S_MNAM_05, // 895 - S_MNAM_06, // 896 - S_MNAM_07, // 897 - S_MNAM_08, // 898 - S_MNAM_09, // 899 - S_MNAM_10, // 900 - S_MNAM_11, // 901 - S_MNAL_00, // 902 - S_MNAL_01, // 903 - S_MNAL_02, // 904 - S_MNAL_03, // 905 - S_MNAL_04, // 906 - S_MNAL_05, // 907 - S_MNAL_06, // 908 - S_MNAL_07, // 909 - S_MNAL_08, // 910 - S_MNAL_09, // 911 - S_MNAL_10, // 912 - S_MNAL_11, // 913 - S_MNAL_12, // 914 - S_MNAL_13, // 915 - S_MNAL_14, // 916 - S_MNAL_15, // 917 - S_MNAL_16, // 918 - S_MNAL_17, // 919 - S_MNAL_18, // 920 - S_MNAL_19, // 921 - S_MNAL_20, // 922 - S_MNAL_21, // 923 - S_MNAL_22, // 924 - S_MNAL_23, // 925 - S_MNAL_24, // 926 - S_MNAL_25, // 927 - S_MNAL_26, // 928 - S_MNAL_27, // 929 - S_MNAL_28, // 930 - S_MNAL_29, // 931 - S_MNAL_30, // 932 - S_MNAL_31, // 933 - S_MNAL_32, // 934 - S_MNAL_33, // 935 - S_MNAL_34, // 936 - S_MNAL_35, // 937 - S_MNAL_36, // 938 - S_MNAL_37, // 939 - S_MNAL_38, // 940 - S_MNAL_39, // 941 - S_MNAL_40, // 942 - S_MDTH_00, // 943 - S_MDTH_01, // 944 - S_MDTH_02, // 945 - S_MDTH_03, // 946 - S_MDTH_04, // 947 - S_MDTH_05, // 948 - S_MDTH_06, // 949 - S_MDTH_07, // 950 - S_MDTH_08, // 951 - S_MDTH_09, // 952 - S_MDTH_10, // 953 - S_MDTH_11, // 954 - S_MDTH_12, // 955 - S_MDTH_13, // 956 - S_MDTH_14, // 957 - S_NEST_00, // 958 - S_PODD_00, // 959 - S_PODD_01, // 960 - S_PODD_02, // 961 - S_PODD_03, // 962 - S_PODD_04, // 963 - S_PODD_05, // 964 - S_ZAP6_00, // 965 - S_ZAP6_01, // 966 - S_ZAP6_02, // 967 - S_ZOT3_00, // 968 - S_ZOT3_01, // 969 - S_ZOT3_02, // 970 - S_ZOT3_03, // 971 - S_ZOT3_04, // 972 - S_ZAP6_03, // 973 - S_ZAP6_04, // 974 - S_ZAP6_05, // 975 - S_ZAP7_00, // 976 - S_ZAP7_01, // 977 - S_ZAP7_02, // 978 - S_ZAP7_03, // 979 - S_ZAP7_04, // 980 - S_ZOT1_00, // 981 - S_ZOT1_01, // 982 - S_ZOT1_02, // 983 - S_ZOT1_03, // 984 - S_ZOT1_04, // 985 - S_ZAP5_00, // 986 - S_ZAP5_01, // 987 - S_ZAP5_02, // 988 - S_ZAP5_03, // 989 - S_ZOT2_00, // 990 - S_ZOT2_01, // 991 - S_ZOT2_02, // 992 - S_ZOT2_03, // 993 - S_ZOT2_04, // 994 - S_SEWR_00, // 995 - S_SEWR_01, // 996 - S_SEWR_02, // 997 - S_SEWR_03, // 998 - S_SEWR_04, // 999 - S_SEWR_05, // 1000 - S_SEWR_06, // 1001 - S_SEWR_07, // 1002 - S_SEWR_08, // 1003 - S_SEWR_09, // 1004 - S_SEWR_10, // 1005 - S_SEWR_11, // 1006 - S_SEWR_12, // 1007 - S_SEWR_13, // 1008 - S_SPID_00, // 1009 - S_SPID_01, // 1010 - S_SPID_02, // 1011 - S_SPID_03, // 1012 - S_SPID_04, // 1013 - S_SPID_05, // 1014 - S_SPID_06, // 1015 - S_SPID_07, // 1016 - S_SPID_08, // 1017 - S_SPID_09, // 1018 - S_SPID_10, // 1019 - S_SPID_11, // 1020 - S_SPID_12, // 1021 - S_SPID_13, // 1022 - S_SPID_14, // 1023 - S_SPID_15, // 1024 - S_SPID_16, // 1025 - S_SPID_17, // 1026 - S_SPID_18, // 1027 - S_SPID_19, // 1028 - S_SPID_20, // 1029 - S_SPID_21, // 1030 - S_SPID_22, // 1031 - S_SPID_23, // 1032 - S_SPID_24, // 1033 - S_SPID_25, // 1034 - S_SPID_26, // 1035 - S_SPID_27, // 1036 - S_SPID_28, // 1037 - S_SPID_29, // 1038 - S_SPID_30, // 1039 - S_SPID_31, // 1040 - S_SPID_32, // 1041 - S_SPID_33, // 1042 - S_SPID_34, // 1043 - S_SPID_35, // 1044 - S_SPID_36, // 1045 - S_SPID_37, // 1046 - S_ROB3_00, // 1047 - S_ROB3_01, // 1048 - S_ROB3_02, // 1049 - S_ROB3_03, // 1050 - S_ROB3_04, // 1051 - S_ROB3_05, // 1052 - S_ROB3_06, // 1053 - S_ROB3_07, // 1054 - S_ROB3_08, // 1055 - S_ROB3_09, // 1056 - S_ROB3_10, // 1057 - S_ROB3_11, // 1058 - S_ROB3_12, // 1059 - S_ROB3_13, // 1060 - S_ROB3_14, // 1061 - S_ROB3_15, // 1062 - S_ROB3_16, // 1063 - S_ROB3_17, // 1064 - S_ROB3_18, // 1065 - S_ROB3_19, // 1066 - S_ROB3_20, // 1067 - S_ROB3_21, // 1068 - S_ROB3_22, // 1069 - S_ROB3_23, // 1070 - S_ROB3_24, // 1071 - S_ROB3_25, // 1072 - S_ROB3_26, // 1073 - S_ROB3_27, // 1074 - S_ROB3_28, // 1075 - S_ROB3_29, // 1076 - S_ROB3_30, // 1077 - S_ROB3_31, // 1078 - S_ROB3_32, // 1079 - S_ROB3_33, // 1080 - S_ROB3_34, // 1081 - S_ROB3_35, // 1082 - S_ROB3_36, // 1083 - S_ROB3_37, // 1084 - S_RBB3_00, // 1085 - S_RBB3_01, // 1086 - S_RBB3_02, // 1087 - S_RBB3_03, // 1088 - S_RBB3_04, // 1089 - S_RBB3_05, // 1090 - S_RBB3_06, // 1091 - S_RBB3_07, // 1092 - S_PRGR_00, // 1093 - S_PRGR_01, // 1094 - S_PRGR_02, // 1095 - S_PRGR_03, // 1096 - S_PRGR_04, // 1097 - S_PRGR_05, // 1098 - S_PRGR_06, // 1099 - S_PRGR_07, // 1100 - S_PRGR_08, // 1101 - S_PRGR_09, // 1102 - S_PRGR_10, // 1103 - S_PRGR_11, // 1104 - S_PRGR_12, // 1105 - S_PRGR_13, // 1106 - S_PRGR_14, // 1107 - S_PRGR_15, // 1108 - S_PRGR_16, // 1109 - S_PRGR_17, // 1110 - S_PRGR_18, // 1111 - S_PRGR_19, // 1112 - S_PRGR_20, // 1113 - S_PRGR_21, // 1114 - S_PRGR_22, // 1115 - S_PRGR_23, // 1116 - S_PRGR_24, // 1117 - S_PRGR_25, // 1118 - S_PRGR_26, // 1119 - S_PRGR_27, // 1120 - S_PRGR_28, // 1121 - S_PRGR_29, // 1122 - S_PRGR_30, // 1123 - S_PRGR_31, // 1124 - S_PRGR_32, // 1125 - S_PRGR_33, // 1126 - S_BASE_00, // 1127 - S_BASE_01, // 1128 - S_BASE_02, // 1129 - S_BASE_03, // 1130 - S_BASE_04, // 1131 - S_BASE_05, // 1132 - S_BASE_06, // 1133 - S_BASE_07, // 1134 - S_FRBL_00, // 1135 - S_FRBL_01, // 1136 - S_FRBL_02, // 1137 - S_FRBL_03, // 1138 - S_FRBL_04, // 1139 - S_FRBL_05, // 1140 - S_FRBL_06, // 1141 - S_FRBL_07, // 1142 - S_FRBL_08, // 1143 - S_KLAX_00, // 1144 - S_KLAX_01, // 1145 - S_KLAX_02, // 1146 - S_TURT_00, // 1147 - S_TURT_01, // 1148 - S_TURT_02, // 1149 - S_TURT_03, // 1150 - S_TURT_04, // 1151 - S_BALL_00, // 1152 - S_BALL_01, // 1153 - S_BALL_02, // 1154 - S_BALL_03, // 1155 - S_BALL_04, // 1156 - S_TURT_05, // 1157 - S_PSTN_00, // 1158 - S_PSTN_01, // 1159 - S_PSTN_02, // 1160 - S_PSTN_03, // 1161 - S_PSTN_04, // 1162 - S_PSTN_05, // 1163 - S_PSTN_06, // 1164 - S_PSTN_07, // 1165 - S_PSTN_08, // 1166 - S_PSTN_09, // 1167 - S_PSTN_10, // 1168 - S_SECR_00, // 1169 - S_SECR_01, // 1170 - S_SECR_02, // 1171 - S_SECR_03, // 1172 - S_SECR_04, // 1173 - S_SECR_05, // 1174 - S_SECR_06, // 1175 - S_SECR_07, // 1176 - S_SECR_08, // 1177 - S_SECR_09, // 1178 - S_SECR_10, // 1179 - S_SECR_11, // 1180 - S_SECR_12, // 1181 - S_SECR_13, // 1182 - S_SECR_14, // 1183 - S_SECR_15, // 1184 - S_XPRK_01, // 1185 - S_XPRK_02, // 1186 - S_TARG_00, // 1187 - S_RING_00, // 1188 - S_EARS_00, // 1189 - S_COMM_00, // 1190 - S_BOOM_00, // 1191 - S_BOOM_01, // 1192 - S_BOOM_02, // 1193 - S_BOOM_03, // 1194 - S_BOOM_04, // 1195 - S_BOOM_05, // 1196 - S_BOOM_06, // 1197 - S_BOOM_07, // 1198 - S_BOOM_08, // 1199 - S_BOOM_09, // 1200 - S_BOOM_10, // 1201 - S_BOOM_11, // 1202 - S_BOOM_12, // 1203 - S_BOOM_13, // 1204 - S_BOOM_14, // 1205 - S_BOOM_15, // 1206 - S_BOOM_16, // 1207 - S_BOOM_17, // 1208 - S_BOOM_18, // 1209 - S_BOOM_19, // 1210 - S_BOOM_20, // 1211 - S_BOOM_21, // 1212 - S_BOOM_22, // 1213 - S_BOOM_23, // 1214 - S_BOOM_24, // 1215 - S_RATT_00, // 1216 - S_RATT_01, // 1217 - S_RATT_02, // 1218 - S_RATT_03, // 1219 - S_RATT_04, // 1220 - S_RATT_05, // 1221 - S_RATT_06, // 1222 - S_HOGN_00, // 1223 - S_HOGN_01, // 1224 - S_HOGN_02, // 1225 - S_DEAD_00, // 1226 - S_SBAN_00, // 1227 - S_BOTR_00, // 1228 - S_HATR_00, // 1229 - S_TOPR_00, // 1230 - S_COUP_00, // 1231 - S_COUP_01, // 1232 - S_COUP_02, // 1233 - S_BUBB_00, // 1234 - S_BUBF_00, // 1235 - S_BUBC_00, // 1236 - S_ASPR_00, // 1237 - S_SPDL_00, // 1238 - S_SPDL_01, // 1239 - S_SPDL_02, // 1240 - S_TOKN_00, // 1241 - S_OTOK_00, // 1242 - S_HELT_00, // 1243 - S_GUNT_00, // 1244 - S_FULL_00, // 1245 - S_FULL_01, // 1246 - S_MEAT_00, // 1247 - S_MEAT_01, // 1248 - S_MEAT_02, // 1249 - S_MEAT_03, // 1250 - S_MEAT_04, // 1251 - S_MEAT_05, // 1252 - S_MEAT_06, // 1253 - S_MEAT_07, // 1254 - S_MEAT_08, // 1255 - S_MEAT_09, // 1256 - S_MEAT_10, // 1257 - S_MEAT_11, // 1258 - S_MEAT_12, // 1259 - S_MEAT_13, // 1260 - S_MEAT_14, // 1261 - S_MEAT_15, // 1262 - S_MEAT_16, // 1263 - S_MEAT_17, // 1264 - S_MEAT_18, // 1265 - S_MEAT_19, // 1266 - S_JUNK_00, // 1267 - S_JUNK_01, // 1268 - S_JUNK_02, // 1269 - S_JUNK_03, // 1270 - S_JUNK_04, // 1271 - S_JUNK_05, // 1272 - S_JUNK_06, // 1273 - S_JUNK_07, // 1274 - S_JUNK_08, // 1275 - S_JUNK_09, // 1276 - S_JUNK_10, // 1277 - S_JUNK_11, // 1278 - S_JUNK_12, // 1279 - S_JUNK_13, // 1280 - S_JUNK_14, // 1281 - S_JUNK_15, // 1282 - S_JUNK_16, // 1283 - S_JUNK_17, // 1284 - S_JUNK_18, // 1285 - S_JUNK_19, // 1286 - S_FFOT_00, // 1287 - S_FFOT_01, // 1288 - S_FFOT_02, // 1289 - S_FFOT_03, // 1290 - S_DIE1_00, // 1291 - S_BEAC_00, // 1292 - S_BEAC_01, // 1293 - S_BEAC_02, // 1294 - S_ARM1_00, // 1295 - S_ARM2_00, // 1296 - S_BARW_00, // 1297 - S_BARW_01, // 1298 - S_BARW_02, // 1299 - S_BARW_03, // 1300 - S_BARW_04, // 1301 - S_BARW_05, // 1302 - S_BARW_06, // 1303 - S_BARW_07, // 1304 - S_BART_00, // 1305 - S_BART_01, // 1306 - S_BART_02, // 1307 - S_BART_03, // 1308 - S_BART_04, // 1309 - S_BART_05, // 1310 - S_BART_06, // 1311 - S_BART_07, // 1312 - S_BART_08, // 1313 - S_BART_09, // 1314 - S_BART_10, // 1315 - S_BART_11, // 1316 - S_LAMP_00, // 1317 - S_LANT_00, // 1318 - S_BARL_00, // 1319 - S_BARL_01, // 1320 - S_BARL_02, // 1321 - S_BARL_03, // 1322 - S_BOWL_00, // 1323 - S_BOWL_01, // 1324 - S_BOWL_02, // 1325 - S_BOWL_03, // 1326 - S_BRAZ_00, // 1327 - S_BRAZ_01, // 1328 - S_BRAZ_02, // 1329 - S_BRAZ_03, // 1330 - S_TRCH_00, // 1331 - S_TRCH_01, // 1332 - S_TRCH_02, // 1333 - S_TRCH_03, // 1334 - S_LTRH_00, // 1335 - S_LTRH_01, // 1336 - S_LTRH_02, // 1337 - S_LTRH_03, // 1338 - S_LMPC_00, // 1339 - S_LMPC_01, // 1340 - S_LMPC_02, // 1341 - S_LMPC_03, // 1342 - S_LOGS_00, // 1343 - S_LOGS_01, // 1344 - S_LOGS_02, // 1345 - S_LOGS_03, // 1346 - S_TRHO_00, // 1347 - S_WATR_00, // 1348 - S_MUGG_00, // 1349 - S_FUSL_00, // 1350 - S_CRD1_00, // 1351 - S_CRD2_00, // 1352 - S_TPAS_00, // 1353 - S_KY1G_00, // 1354 - S_KY2S_00, // 1355 - S_KY3B_00, // 1356 - S_HAND_00, // 1357 - S_CRYS_00, // 1358 - S_CRYS_01, // 1359 - S_CRYS_02, // 1360 - S_CRYS_03, // 1361 - S_CRYS_04, // 1362 - S_CRYS_05, // 1363 - S_PRIS_00, // 1364 - S_PWR1_00, // 1365 - S_PWR2_00, // 1366 - S_PWR3_00, // 1367 - S_ORAC_00, // 1368 - S_GYID_00, // 1369 - S_FUBR_00, // 1370 - S_WARE_00, // 1371 - S_RCRY_00, // 1372 - S_BCRY_00, // 1373 - S_CHAP_00, // 1374 - S_TUNL_00, // 1375 - S_BLTK_00, // 1376 - S_SECK_00, // 1377 - S_MINE_00, // 1378 - S_REBL_00, // 1379 - S_PROC_00, // 1380 - S_ANKH_00, // 1381 - S_GOID_00, // 1382 - S_STMP_00, // 1383 - S_MDKT_00, // 1384 - S_COIN_00, // 1385 - S_CRED_00, // 1386 - S_SACK_00, // 1387 - S_CHST_00, // 1388 - S_SHD1_00, // 1389 - S_SHD1_01, // 1390 - S_SHD1_02, // 1391 - S_SHD1_03, // 1392 - S_MASK_00, // 1393 - S_UNIF_00, // 1394 - S_OFIC_00, // 1395 - S_PMAP_00, // 1396 - S_PMAP_01, // 1397 - S_PMUP_00, // 1398 - S_PMUP_01, // 1399 - S_BLIT_00, // 1400 - S_BBOX_00, // 1401 - S_MSSL_00, // 1402 - S_ROKT_00, // 1403 - S_BRY1_00, // 1404 - S_BRY1_01, // 1405 - S_CPAC_00, // 1406 - S_CPAC_01, // 1407 - S_PQRL_00, // 1408 - S_XQRL_00, // 1409 - S_GRN1_00, // 1410 - S_GRN2_00, // 1411 - S_BKPK_00, // 1412 - S_RELC_00, // 1413 - S_RIFL_00, // 1414 - S_RIFL_01, // 1415 - S_FLAM_00, // 1416 - S_BFLM_00, // 1417 - S_MMSL_00, // 1418 - S_TRPD_00, // 1419 - S_GRND_00, // 1420 - S_CBOW_00, // 1421 - S_SIGL_00, // 1422 - S_SIGL_01, // 1423 - S_SIGL_02, // 1424 - S_SIGL_03, // 1425 - S_SIGL_04, // 1426 - S_LITE_00, // 1427 - S_CNDL_00, // 1428 - S_CLBR_00, // 1429 - S_LITS_00, // 1430 - S_LITB_00, // 1431 - S_LITG_00, // 1432 - S_ROK1_00, // 1433 - S_ROK2_00, // 1434 - S_ROK3_00, // 1435 - S_ROK4_00, // 1436 - S_LOGG_00, // 1437 - S_LOGG_01, // 1438 - S_LOGG_02, // 1439 - S_LOGG_03, // 1440 - S_RUB1_00, // 1441 - S_RUB2_00, // 1442 - S_RUB3_00, // 1443 - S_RUB4_00, // 1444 - S_RUB5_00, // 1445 - S_RUB6_00, // 1446 - S_RUB7_00, // 1447 - S_RUB8_00, // 1448 - S_CHAN_00, // 1449 - S_STAT_00, // 1450 - S_DSTA_00, // 1451 - S_CRAB_00, // 1452 - S_CAGE_00, // 1453 - S_TREE_00, // 1454 - S_TREE_01, // 1455 - S_TREE_02, // 1456 - S_TRE1_00, // 1457 - S_BUSH_00, // 1458 - S_SHRB_00, // 1459 - S_STAK_00, // 1460 - S_BAR1_00, // 1461 - S_VASE_00, // 1462 - S_VASE_01, // 1463 - S_STOL_00, // 1464 - S_POT1_00, // 1465 - S_TUB1_00, // 1466 - S_ANVL_00, // 1467 - S_TLMP_00, // 1468 - S_TLMP_01, // 1469 - S_TRAY_00, // 1470 - S_APOW_00, // 1471 - S_AFED_00, // 1472 - S_DRIP_00, // 1473 - S_DRIP_01, // 1474 - S_DRIP_02, // 1475 - S_DRIP_03, // 1476 - S_DRIP_04, // 1477 - S_DRIP_05, // 1478 - S_DRIP_06, // 1479 - S_DRIP_07, // 1480 - S_CDRP_00, // 1481 - S_CDRP_01, // 1482 - S_CDRP_02, // 1483 - S_CDRP_03, // 1484 - S_SPLH_00, // 1485 - S_SPLH_01, // 1486 - S_SPLH_02, // 1487 - S_SPLH_03, // 1488 - S_SPLH_04, // 1489 - S_SPLH_05, // 1490 - S_SPLH_06, // 1491 - S_SPLH_07, // 1492 - S_WTFT_00, // 1493 - S_WTFT_01, // 1494 - S_WTFT_02, // 1495 - S_WTFT_03, // 1496 - S_HERT_00, // 1497 - S_HERT_01, // 1498 - S_HERT_02, // 1499 - S_TELP_00, // 1500 - S_TELP_01, // 1501 - S_TELP_02, // 1502 - S_TELP_03, // 1503 - S_MONI_00, // 1504 - S_STEL_00, // 1505 - S_STLA_00, // 1506 - S_STLE_00, // 1507 - S_HUGE_00, // 1508 - S_HUGE_01, // 1509 - S_HUGE_02, // 1510 - S_HUGE_03, // 1511 - S_STLG_00, // 1512 - S_STLG_01, // 1513 - S_STLG_02, // 1514 - S_STLG_03, // 1515 - S_STLG_04, // 1516 - S_STLG_05, // 1517 - NUMSTATES - -} statenum_t; - - -typedef struct -{ - spritenum_t sprite; - int frame; - int tics; - // void (*action) (); - actionf_t action; - statenum_t nextstate; - //int misc1; // villsa [STRIFE] unused - //int misc2; // villsa [STRIFE] unused -} state_t; - -extern state_t states[NUMSTATES]; -extern const char *sprnames[]; - -typedef enum -{ - MT_FIELDGUARD, //000 - MT_PLAYER, //001 - MT_SHOPKEEPER_W, //002 - MT_SHOPKEEPER_B, //003 - MT_SHOPKEEPER_A, //004 - MT_SHOPKEEPER_M, //005 - MT_PEASANT2_A, //006 - MT_PEASANT2_B, //007 - MT_PEASANT2_C, //008 - MT_PEASANT5_A, //009 - MT_PEASANT5_B, //010 - MT_PEASANT5_C, //011 - MT_PEASANT4_A, //012 - MT_PEASANT4_B, //013 - MT_PEASANT4_C, //014 - MT_PEASANT6_A, //015 - MT_PEASANT6_B, //016 - MT_PEASANT6_C, //017 - MT_PEASANT3_A, //018 - MT_PEASANT3_B, //019 - MT_PEASANT3_C, //020 - MT_PEASANT8_A, //021 - MT_PEASANT8_B, //022 - MT_PEASANT8_C, //023 - MT_PEASANT7_A, //024 - MT_PEASANT7_B, //025 - MT_PEASANT7_C, //026 - MT_PEASANT1, //027 - MT_ZOMBIE, //028 - MT_BECOMING, //029 - MT_ZOMBIESPAWNER, //030 - MT_HUGE_TANK_1, //031 - MT_HUGE_TANK_2, //032 - MT_HUGE_TANK_3, //033 - MT_TANK_4, //034 - MT_TANK_5, //035 - MT_TANK_6, //036 - MT_KNEELING_GUY, //037 - MT_BEGGAR1, //038 - MT_BEGGAR2, //039 - MT_BEGGAR3, //040 - MT_BEGGAR4, //041 - MT_BEGGAR5, //042 - MT_REBEL1, //043 - MT_REBEL2, //044 - MT_REBEL3, //045 - MT_REBEL4, //046 - MT_REBEL5, //047 - MT_REBEL6, //048 - MT_RLEADER, //049 - MT_RLEADER2, //050 - MT_MISSILESMOKE, //051 - MT_REAVER, //052 - MT_GUARD1, //053 - MT_GUARD2, //054 - MT_GUARD3, //055 - MT_GUARD4, //056 - MT_GUARD5, //057 - MT_GUARD6, //058 - MT_GUARD7, //059 - MT_GUARD8, //060 - MT_SHADOWGUARD, //061 - MT_PGUARD, //062 - MT_CRUSADER, //063 - MT_BISHOP, //064 - MT_ORACLE, //065 - MT_PRIEST, //066 - MT_SPECTRE_A, //067 - MT_NODE, //068 - MT_SPECTREHEAD, //069 - MT_SPECTRE_B, //070 - MT_SPECTRE_C, //071 - MT_SPECTRE_D, //072 - MT_SPECTRE_E, //073 - MT_ENTITY, //074 - MT_SUBENTITY, //075 - MT_NEST, //076 - MT_POD, //077 - MT_SIGIL_B_SHOT, //078 - MT_SIGIL_SB_SHOT, //079 - MT_SIGIL_C_SHOT, //080 - MT_SIGIL_SC_SHOT, //081 - MT_SIGIL_E_OFFSHOOT, //082 - MT_SIGIL_TRAIL, //083 - MT_SIGIL_E_SHOT, //084 - MT_SIGIL_SE_SHOT, //085 - MT_SIGIL_A_ZAP_LEFT, //086 - MT_SIGIL_A_ZAP_RIGHT, //087 - MT_SIGIL_A_GROUND, //088 - MT_SIGIL_D_SHOT, //089 - MT_SIGIL_SD_SHOT, //090 - MT_SENTINEL, //091 - MT_STALKER, //092 - MT_INQUISITOR, //093 - MT_INQARM, //094 - MT_PROGRAMMER, //095 - MT_PROGRAMMERBASE, //096 - MT_HOOKSHOT, //097 - MT_CHAINSHOT, //098 - MT_MINIMISSLE, //099 - MT_C_MISSILE, //100 - MT_SEEKMISSILE, //101 - MT_ELECARROW, //102 - MT_POISARROW, //103 - MT_R_LASER, //104 - MT_L_LASER, //105 - MT_HEGRENADE, //106 - MT_PGRENADE, //107 - MT_INQGRENADE, //108 - MT_PFLAME, //109 - MT_TORPEDO, //110 - MT_TORPEDOSPREAD, //111 - MT_SFIREBALL, //112 - MT_C_FLAME, //113 - MT_STRIFEPUFF3, //114 - MT_STRIFEPUFF, //115 - MT_SPARKPUFF, //116 - MT_BLOOD_DEATH, //117 - MT_TFOG, //118 - MT_IFOG, //119 - MT_TELEPORTMAN, //120 - MT_MISC_01, //121 - MT_TURRET, //122 - MT_GATE, //123 - MT_COMPUTER, //124 - MT_INV_MED1, //125 - MT_INV_MED2, //126 - MT_INV_MED3, //127 - MT_DEGNINORE, //128 - MT_INV_ARMOR2, //129 - MT_INV_ARMOR1, //130 - MT_MISC_22, //131 - MT_MISC_11, //132 - MT_KEY_BASE, //133 - MT_GOVSKEY, //134 - MT_KEY_TRAVEL, //135 - MT_KEY_ID_BLUE, //136 - MT_PRISONKEY, //137 - MT_KEY_HAND, //138 - MT_POWER1KEY, //139 - MT_POWER2KEY, //140 - MT_POWER3KEY, //141 - MT_KEY_GOLD, //142 - MT_KEY_ID_GOLD, //143 - MT_KEY_SILVER, //144 - MT_KEY_ORACLE, //145 - MT_MILITARYID, //146 - MT_KEY_ORDER, //147 - MT_KEY_WAREHOUSE, //148 - MT_KEY_BRASS, //149 - MT_KEY_RED_CRYSTAL, //150 - MT_KEY_BLUE_CRYSTAL, //151 - MT_KEY_CHAPEL, //152 - MT_CATACOMBKEY, //153 - MT_SECURITYKEY, //154 - MT_KEY_CORE, //155 - MT_KEY_MAULER, //156 - MT_KEY_FACTORY, //157 - MT_KEY_MINE, //158 - MT_NEWKEY5, //159 - MT_INV_SHADOWARMOR, //160 - MT_INV_SUIT, //161 - MT_QUEST_UNIFORM, //162 - MT_QUEST_GUARD_UNIFORM, //163 - MT_INV_SUPERMAP, //164 - MT_INV_RADAR, //165 - MT_BEACON, //166 - MT_INV_TARGETER, //167 - MT_MONY_1, //168 - MT_MONY_10, //169 - MT_MONY_25, //170 - MT_MONY_50, //171 - MT_MONY_300, //172 - MT_TOKEN_RING, //173 - MT_INV_CHALICE, //174 - MT_TOKEN_EAR, //175 - MT_INV_COMMUNICATOR, //176 - MT_AGREN, //177 - MT_APGREN, //178 - MT_ACLIP, //179 - MT_AAMMOBOX, //180 - MT_AMINI, //181 - MT_AMINIBOX, //182 - MT_ACELL, //183 - MT_APCELL, //184 - MT_APAROW, //185 - MT_AAROW, //186 - MT_INV_SATCHEL, //187 - MT_PULSE, //188 - MT_RIFLESTAND, //189 - MT_FLAMETHROWER, //190 - MT_TOKEN_FLAME_THROWER_PARTS, //191 - MT_MISSILELAUNCHER, //192 - MT_BLASTER, //193 - MT_CROSSBOW, //194 - MT_GRENADELAUNCHER, //195 - MT_SIGIL_A, //196 - MT_SIGIL_B, //197 - MT_SIGIL_C, //198 - MT_SIGIL_D, //199 - MT_SIGIL_E, //200 - MT_POWER_CRYSTAL, //201 - MT_RAT, //202 - MT_MISC_05, //203 - MT_MISC_06, //204 - MT_MISC_15, //205 - MT_LIGHT14, //206 - MT_LIGHT13, //207 - MT_LIGHT12, //208 - MT_LIGHT18, //209 - MT_PILLAR2, //210 - MT_PILLAR3, //211 - MT_PILLAR4, //212 - MT_PILLAR5, //213 - MT_PILLAR6, //214 - MT_PILLAR7, //215 - MT_CAVE2, //216 - MT_CAVE3, //217 - MT_CAVE4, //218 - MT_CAVE6, //219 - MT_CAVE7, //220 - MT_CAVE5, //221 - MT_LIGHT2, //222 - MT_LIGHT3, //223 - MT_MISC_03, //224 - MT_MISC_13, //225 - MT_MISC_02, //226 - MT_MISC_07, //227 - MT_BIO2, //228 - MT_TELEPORTSTAND, //229 - MT_DEADTHING1, //230 - MT_DEADTHING2, //231 - MT_DEADTHING3, //232 - MT_DEADTHING4, //233 - MT_DEADTHING5, //234 - MT_DEADTHING6, //235 - MT_BIO1, //236 - MT_GIBS, //237 - MT_MISC_04, //238 - MT_LIGHT11, //239 - MT_LIGHT10, //240 - MT_LIGHT9, //241 - MT_LIGHT8, //242 - MT_MISC_14, //243 - MT_LIGHT1, //244 - MT_PILLAR8, //245 - MT_PILLAR9, //246 - MT_LIGHT15, //247 - MT_LIGHT4, //248 - MT_LIGHT5, //249 - MT_ROCK1, //250 - MT_ROCK2, //251 - MT_ROCK3, //252 - MT_ROCK4, //253 - MT_TREE7, //254 - MT_RUBBLE1, //255 - MT_RUBBLE2, //256 - MT_RUBBLE3, //257 - MT_RUBBLE4, //258 - MT_RUBBLE5, //259 - MT_RUBBLE6, //260 - MT_RUBBLE7, //261 - MT_RUBBLE8, //262 - MT_MISC_08, //263 - MT_LIGHT6, //264 - MT_LIGHT7, //265 - MT_TREE2, //266 - MT_TREE3, //267 - MT_TREE4, //268 - MT_TREE1, //269 - MT_TREE6, //270 - MT_TREE5, //271 - MT_CAVE1, //272 - MT_PILLAR1, //273 - MT_MISC_10, //274 - MT_MISC_09, //275 - MT_MISC_17, //276 - MT_MISC_18, //277 - MT_MISC_19, //278 - MT_MISC_20, //279 - MT_LIGHT16, //280 - MT_LIGHT17, //281 - MT_MISC_21, //282 - MT_MISC_12, //283 - MT_MISC_26, //284 - MT_MISC_23, //285 - MT_MISC_24, //286 - MT_MISC_25, //287 - MT_COUPLING, //288 - MT_COUPLING_BROKEN, //289 - MT_PILLAR10, //290 - MT_PILLAR11, //291 - MT_PILLAR12, //292 - MT_PILLAR13, //293 - MT_LIGHT19, //294 - MT_MEAT, //295 - MT_JUNK, //296 - MT_BURNDROP, //297 - MT_TOKEN_AMMO, //298 - MT_TOKEN_HEALTH, //299 - MT_TOKEN, //300 - MT_TOKEN_ALARM, //301 - MT_TOKEN_DOOR1, //302 - MT_TOKEN_SHOPCLOSE, //303 - MT_TOKEN_PRISON_PASS, //304 - MT_TOKEN_DOOR3, //305 - MT_TOKEN_STAMINA, //306 - MT_TOKEN_NEW_ACCURACY, //307 - MT_TOKEN_REPORT, //308 - MT_TOKEN_TOUGHNESS, //309 - MT_TOKEN_ACCURACY, //310 - MT_TOKEN_ORACLE_PASS, //311 - MT_TOKEN_QUEST1, //312 - MT_TOKEN_QUEST2, //313 - MT_TOKEN_QUEST3, //314 - MT_TOKEN_QUEST4, //315 - MT_TOKEN_QUEST5, //316 - MT_TOKEN_QUEST6, //317 - MT_TOKEN_QUEST7, //318 - MT_TOKEN_QUEST8, //319 - MT_TOKEN_QUEST9, //320 - MT_TOKEN_QUEST10, //321 - MT_TOKEN_QUEST11, //322 - MT_TOKEN_QUEST12, //323 - MT_TOKEN_QUEST13, //324 - MT_TOKEN_CRYSTAL, //325 - MT_TOKEN_QUEST15, //326 - MT_GATEQUEST, //327 - MT_TOKEN_QUEST17, //328 - MT_TOKEN_QUEST18, //329 - MT_TOKEN_QUEST19, //330 - MT_TOKEN_QUEST20, //331 - MT_TOKEN_BISHOP, //332 - MT_TOKEN_QUEST22, //333 - MT_TOKEN_ORACLE, //334 - MT_TOKEN_MACIL, //335 - MT_TOKEN_QUEST25, //336 - MT_TOKEN_LOREMASTER, //337 - MT_SECRQUEST, //338 - MT_TOKEN_QUEST28, //339 - MT_TOKEN_QUEST29, //340 - MT_TOKEN_QUEST30, //341 - MT_TOKEN_QUEST31, //342 - MT_SLIDESHOW, //343 - NUMMOBJTYPES - -} mobjtype_t; - -// villsa [STRIFE] updated mobjinfo struct -typedef struct -{ - int doomednum; - int spawnstate; - int spawnhealth; - int seestate; - int seesound; - int reactiontime; - int attacksound; - int painstate; - int painchance; - int painsound; - int meleestate; - int missilestate; - int crashstate; - int deathstate; - int xdeathstate; - int deathsound; - int speed; - int radius; - int height; - int mass; - int damage; - int activesound; - int flags; - const char *name; -} mobjinfo_t; - -extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; - -#endif diff --git a/games/NXDoom/src/strife/m_menu.c b/games/NXDoom/src/strife/m_menu.c deleted file mode 100644 index d277fd3c718..00000000000 --- a/games/NXDoom/src/strife/m_menu.c +++ /dev/null @@ -1,2466 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// DOOM selection menu, options, episode etc. -// Sliders and icons. Kinda widget stuff. -// - - -#include -#include - - -#include "doomdef.h" -#include "doomkeys.h" -#include "dstrings.h" - -#include "d_main.h" -#include "deh_main.h" - -#include "i_input.h" -#include "i_joystick.h" -#include "i_swap.h" -#include "i_system.h" -#include "i_timer.h" -#include "i_video.h" -#include "z_zone.h" -#include "v_video.h" -#include "w_wad.h" - -#include "r_local.h" - - -#include "hu_stuff.h" - -#include "g_game.h" - -#include "m_argv.h" -#include "m_controls.h" -#include "m_misc.h" -#include "m_saves.h" // [STRIFE] -#include "p_saveg.h" - -#include "s_sound.h" - -#include "doomstat.h" - -// Data. -#include "sounds.h" - -#include "m_menu.h" -#include "p_dialog.h" - - -void M_QuitStrife(int); - - -// -// defaulted values -// -int mouseSensitivity = 5; - -// [STRIFE]: removed this entirely -// Show messages has default, 0 = off, 1 = on -//int showMessages = 1; - - -// Blocky mode, has default, 0 = high, 1 = normal -int detailLevel = 0; -int screenblocks = 10; // [STRIFE] default 10, not 9 - -// temp for screenblocks (0-9) -int screenSize; - -// -1 = no quicksave slot picked! -int quickSaveSlot; - - // 1 = message to be printed -int messageToPrint; -// ...and here is the message string! -const char *messageString; - -// message x & y -int messx; -int messy; -int messageLastMenuActive; - -// timed message = no input from user -boolean messageNeedsInput; - -void (*messageRoutine)(int response); - -char gammamsg[5][26] = -{ - GAMMALVL0, - GAMMALVL1, - GAMMALVL2, - GAMMALVL3, - GAMMALVL4 -}; - -// we are going to be entering a savegame string -int saveStringEnter; -int saveSlot; // which slot to save in -int saveCharIndex; // which char we're editing -// old save description before edit -char saveOldString[SAVESTRINGSIZE]; - -boolean inhelpscreens; -boolean menuactive; -boolean menupause; // haleyjd 08/29/10: [STRIFE] New global -int menupausetime; // haleyjd 09/04/10: [STRIFE] New global -boolean menuindialog; // haleyjd 09/04/10: ditto - -// haleyjd 08/27/10: [STRIFE] SKULLXOFF == -28, LINEHEIGHT == 19 -#define CURSORXOFF -28 -#define LINEHEIGHT 19 - -char savegamestrings[10][SAVESTRINGSIZE]; - -char endstring[160]; - -// haleyjd 09/04/10: [STRIFE] Moved menuitem / menu structures into header -// because they are needed externally by the dialog engine. - -// haleyjd 08/27/10: [STRIFE] skull* stuff changed to cursor* stuff -short itemOn; // menu item skull is on -short cursorAnimCounter; // skull animation counter -short whichCursor; // which skull to draw - -// graphic name of cursors -// haleyjd 08/27/10: [STRIFE] M_SKULL* -> M_CURS* -const char *cursorName[8] = {"M_CURS1", "M_CURS2", "M_CURS3", "M_CURS4", - "M_CURS5", "M_CURS6", "M_CURS7", "M_CURS8" }; - -// haleyjd 20110210 [STRIFE]: skill level for menus -int menuskill; - -// current menudef -menu_t* currentMenu; - -// haleyjd 03/01/13: [STRIFE] v1.31-only: -// Keeps track of whether the save game menu is being used to name a new -// character slot, or to just save the current game. In the v1.31 disassembly -// this was the new dword_8632C variable. -boolean namingCharacter; - -// -// PROTOTYPES -// -void M_NewGame(int choice); -void M_Episode(int choice); -void M_ChooseSkill(int choice); -void M_LoadGame(int choice); -void M_SaveGame(int choice); -void M_Options(int choice); -void M_EndGame(int choice); -void M_ReadThis(int choice); -void M_ReadThis2(int choice); -void M_ReadThis3(int choice); // [STRIFE] - -//void M_ChangeMessages(int choice); [STRIFE] -void M_ChangeSensitivity(int choice); -void M_SfxVol(int choice); -void M_VoiceVol(int choice); // [STRIFE] -void M_MusicVol(int choice); -void M_SizeDisplay(int choice); -void M_StartGame(int choice); -void M_Sound(int choice); - -//void M_FinishReadThis(int choice); - [STRIFE] unused -void M_SaveSelect(int choice); -void M_ReadSaveStrings(void); -void M_QuickSave(void); -void M_QuickLoad(void); - -void M_DrawMainMenu(void); -void M_DrawReadThis1(void); -void M_DrawReadThis2(void); -void M_DrawReadThis3(void); // [STRIFE] -void M_DrawNewGame(void); -void M_DrawEpisode(void); -void M_DrawOptions(void); -void M_DrawSound(void); -void M_DrawLoad(void); -void M_DrawSave(void); - -void M_DrawSaveLoadBorder(int x,int y); -void M_SetupNextMenu(menu_t *menudef); -void M_DrawThermo(int x,int y,int thermWidth,int thermDot); -void M_DrawEmptyCell(menu_t *menu,int item); -void M_DrawSelCell(menu_t *menu,int item); -int M_StringWidth(const char *string); -int M_StringHeight(const char *string); -void M_StartMessage(const char *string,void *routine,boolean input); -void M_StopMessage(void); - - - - -// -// DOOM MENU -// -enum -{ - newgame = 0, - options, - loadgame, - savegame, - readthis, - quitdoom, - main_end -} main_e; - -menuitem_t MainMenu[]= -{ - {1,"M_NGAME",M_NewGame,'n'}, - {1,"M_OPTION",M_Options,'o'}, - {1,"M_LOADG",M_LoadGame,'l'}, - {1,"M_SAVEG",M_SaveGame,'s'}, - // Another hickup with Special edition. - {1,"M_RDTHIS",M_ReadThis,'h'}, // haleyjd 08/28/10: 'r' -> 'h' - {1,"M_QUITG",M_QuitStrife,'q'} -}; - -menu_t MainDef = -{ - main_end, - NULL, - MainMenu, - M_DrawMainMenu, - 97,45, // haleyjd 08/28/10: [STRIFE] changed y coord - 0 -}; - - -// -// EPISODE SELECT -// -/* -enum -{ - ep1, - ep2, - ep3, - ep4, - ep_end -} episodes_e; - -menuitem_t EpisodeMenu[]= -{ - {1,"M_EPI1", M_Episode,'k'}, - {1,"M_EPI2", M_Episode,'t'}, - {1,"M_EPI3", M_Episode,'i'}, - {1,"M_EPI4", M_Episode,'t'} -}; - -menu_t EpiDef = -{ - ep_end, // # of menu items - &MainDef, // previous menu - EpisodeMenu, // menuitem_t -> - M_DrawEpisode, // drawing routine -> - 48,63, // x,y - ep1 // lastOn -}; -*/ - -// -// NEW GAME -// -enum -{ - killthings, - toorough, - hurtme, - violence, - nightmare, - newg_end -} newgame_e; - -menuitem_t NewGameMenu[]= -{ - // haleyjd 08/28/10: [STRIFE] changed all shortcut letters - {1,"M_JKILL", M_ChooseSkill, 't'}, - {1,"M_ROUGH", M_ChooseSkill, 'r'}, - {1,"M_HURT", M_ChooseSkill, 'v'}, - {1,"M_ULTRA", M_ChooseSkill, 'e'}, - {1,"M_NMARE", M_ChooseSkill, 'b'} -}; - -menu_t NewDef = -{ - newg_end, // # of menu items - &MainDef, // previous menu - haleyjd [STRIFE] changed to MainDef - NewGameMenu, // menuitem_t -> - M_DrawNewGame, // drawing routine -> - 48,63, // x,y - toorough // lastOn - haleyjd [STRIFE]: default to skill 1 -}; - -// -// OPTIONS MENU -// -enum -{ - // haleyjd 08/28/10: [STRIFE] Removed messages, mouse sens., detail. - endgame, - scrnsize, - option_empty1, - soundvol, - opt_end -} options_e; - -menuitem_t OptionsMenu[]= -{ - // haleyjd 08/28/10: [STRIFE] Removed messages, mouse sens., detail. - {1,"M_ENDGAM", M_EndGame,'e'}, - {2,"M_SCRNSZ", M_SizeDisplay,'s'}, - {-1,"",0,'\0'}, - {1,"M_SVOL", M_Sound,'s'} -}; - -menu_t OptionsDef = -{ - opt_end, - &MainDef, - OptionsMenu, - M_DrawOptions, - 60,37, - 0 -}; - -// -// Read This! MENU 1 & 2 & [STRIFE] 3 -// -enum -{ - rdthsempty1, - read1_end -} read_e; - -menuitem_t ReadMenu1[] = -{ - {1,"",M_ReadThis2,0} -}; - -menu_t ReadDef1 = -{ - read1_end, - &MainDef, - ReadMenu1, - M_DrawReadThis1, - 280,185, - 0 -}; - -enum -{ - rdthsempty2, - read2_end -} read_e2; - -menuitem_t ReadMenu2[]= -{ - {1,"",M_ReadThis3,0} // haleyjd 08/28/10: [STRIFE] Go to ReadThis3 -}; - -menu_t ReadDef2 = -{ - read2_end, - &ReadDef1, - ReadMenu2, - M_DrawReadThis2, - 250,185, // haleyjd 08/28/10: [STRIFE] changed coords - 0 -}; - -// haleyjd 08/28/10: Added Read This! menu 3 -enum -{ - rdthsempty3, - read3_end -} read_e3; - -menuitem_t ReadMenu3[]= -{ - {1,"",M_ClearMenus,0} -}; - -menu_t ReadDef3 = -{ - read3_end, - &ReadDef2, - ReadMenu3, - M_DrawReadThis3, - 250, 185, - 0 -}; - -// -// SOUND VOLUME MENU -// -enum -{ - sfx_vol, - sfx_empty1, - music_vol, - sfx_empty2, - voice_vol, - sfx_empty3, - sfx_mouse, - sfx_empty4, - sound_end -} sound_e; - -// haleyjd 08/29/10: -// [STRIFE] -// * Added voice volume -// * Moved mouse sensitivity here (who knows why...) -menuitem_t SoundMenu[]= -{ - {2,"M_SFXVOL",M_SfxVol,'s'}, - {-1,"",0,'\0'}, - {2,"M_MUSVOL",M_MusicVol,'m'}, - {-1,"",0,'\0'}, - {2,"M_VOIVOL",M_VoiceVol,'v'}, - {-1,"",0,'\0'}, - {2,"M_MSENS",M_ChangeSensitivity,'m'}, - {-1,"",0,'\0'} -}; - -menu_t SoundDef = -{ - sound_end, - &OptionsDef, - SoundMenu, - M_DrawSound, - 80,35, // [STRIFE] changed y coord 64 -> 35 - 0 -}; - -// -// LOAD GAME MENU -// -enum -{ - load1, - load2, - load3, - load4, - load5, - load6, - load_end -} load_e; - -menuitem_t LoadMenu[]= -{ - {1,"", M_LoadSelect,'1'}, - {1,"", M_LoadSelect,'2'}, - {1,"", M_LoadSelect,'3'}, - {1,"", M_LoadSelect,'4'}, - {1,"", M_LoadSelect,'5'}, - {1,"", M_LoadSelect,'6'} -}; - -menu_t LoadDef = -{ - load_end, - &MainDef, - LoadMenu, - M_DrawLoad, - 80,54, - 0 -}; - -// -// SAVE GAME MENU -// -menuitem_t SaveMenu[]= -{ - {1,"", M_SaveSelect,'1'}, - {1,"", M_SaveSelect,'2'}, - {1,"", M_SaveSelect,'3'}, - {1,"", M_SaveSelect,'4'}, - {1,"", M_SaveSelect,'5'}, - {1,"", M_SaveSelect,'6'} -}; - -menu_t SaveDef = -{ - load_end, - &MainDef, - SaveMenu, - M_DrawSave, - 80,54, - 0 -}; - -void M_DrawNameChar(void); - -// -// NAME CHARACTER MENU -// -// [STRIFE] -// haleyjd 20110210: New "Name Your Character" Menu -// -menu_t NameCharDef = -{ - load_end, - &NewDef, - SaveMenu, - M_DrawNameChar, - 80,54, - 0 -}; - - -// -// M_ReadSaveStrings -// read the strings from the savegame files -// -// [STRIFE] -// haleyjd 20110210: Rewritten to read "name" file in each slot directory -// -void M_ReadSaveStrings(void) -{ - FILE *handle; - int i; - char *fname = NULL; - - for(i = 0; i < load_end; i++) - { - int retval; - if(fname) - Z_Free(fname); - fname = M_SafeFilePath(savegamedir, M_MakeStrifeSaveDir(i, "\\name")); - - handle = M_fopen(fname, "rb"); - if(handle == NULL) - { - M_StringCopy(savegamestrings[i], DEH_String(EMPTYSTRING), - sizeof(savegamestrings[i])); - LoadMenu[i].status = 0; - continue; - } - retval = fread(savegamestrings[i], 1, SAVESTRINGSIZE, handle); - fclose(handle); - LoadMenu[i].status = retval == SAVESTRINGSIZE; - } - - if(fname) - Z_Free(fname); -} - -// -// M_DrawNameChar -// -// haleyjd 09/22/10: [STRIFE] New function -// Handler for drawing the "Name Your Character" menu. -// -void M_DrawNameChar(void) -{ - int i; - - M_WriteText(72, 28, DEH_String("Name Your Character")); - - for (i = 0;i < load_end; i++) - { - M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); - M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); - } - - if (saveStringEnter) - { - i = M_StringWidth(savegamestrings[quickSaveSlot]); - M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*quickSaveSlot,"_"); - } -} - -// -// M_DoNameChar -// -// haleyjd 09/22/10: [STRIFE] New function -// Handler for items in the "Name Your Character" menu. -// -void M_DoNameChar(int choice) -{ - int map; - - // 20130301: clear naming character flag for 1.31 save logic - if(gameversion == exe_strife_1_31) - namingCharacter = false; - sendsave = 1; - ClearTmp(); - G_WriteSaveName(choice, savegamestrings[choice]); - quickSaveSlot = choice; - SaveDef.lastOn = choice; - ClearSlot(); - FromCurr(); - - if(isdemoversion) - map = 33; - else - map = 2; - - G_DeferedInitNew(menuskill, map); - M_ClearMenus(0); -} - -// -// M_LoadGame & Cie. -// -void M_DrawLoad(void) -{ - int i; - - V_DrawPatchDirect(72, 28, - W_CacheLumpName(DEH_String("M_LOADG"), PU_CACHE)); - - for (i = 0;i < load_end; i++) - { - M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); - M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); - } -} - - - -// -// Draw border for the savegame description -// -void M_DrawSaveLoadBorder(int x,int y) -{ - int i; - - V_DrawPatchDirect(x - 8, y + 7, - W_CacheLumpName(DEH_String("M_LSLEFT"), PU_CACHE)); - - for (i = 0;i < 24;i++) - { - V_DrawPatchDirect(x, y + 7, - W_CacheLumpName(DEH_String("M_LSCNTR"), PU_CACHE)); - x += 8; - } - - V_DrawPatchDirect(x, y + 7, - W_CacheLumpName(DEH_String("M_LSRGHT"), PU_CACHE)); -} - - - -// -// User wants to load this game -// -void M_LoadSelect(int choice) -{ - // [STRIFE]: completely rewritten - char *name = NULL; - - G_WriteSaveName(choice, savegamestrings[choice]); - ToCurr(); - - // use safe & portable filepath concatenation for Choco - name = M_SafeFilePath(savegamedir, M_MakeStrifeSaveDir(choice, "")); - - G_ReadCurrent(name); - quickSaveSlot = choice; - M_ClearMenus(0); - - Z_Free(name); -} - -// -// Selected from DOOM menu -// -// [STRIFE] Verified unmodified -// -void M_LoadGame (int choice) -{ - if (netgame) - { - M_StartMessage(DEH_String(LOADNET), NULL, false); - return; - } - - M_SetupNextMenu(&LoadDef); - M_ReadSaveStrings(); -} - - -// -// M_SaveGame & Cie. -// -void M_DrawSave(void) -{ - int i; - - V_DrawPatchDirect(72, 28, W_CacheLumpName(DEH_String("M_SAVEG"), PU_CACHE)); - for (i = 0;i < load_end; i++) - { - M_DrawSaveLoadBorder(LoadDef.x,LoadDef.y+LINEHEIGHT*i); - M_WriteText(LoadDef.x,LoadDef.y+LINEHEIGHT*i,savegamestrings[i]); - } - - if (saveStringEnter) - { - i = M_StringWidth(savegamestrings[quickSaveSlot]); - M_WriteText(LoadDef.x + i,LoadDef.y+LINEHEIGHT*quickSaveSlot,"_"); - } -} - -// -// M_Responder calls this when user is finished -// -void M_DoSave(int slot) -{ - // [STRIFE]: completely rewritten - if(slot >= 0) - { - sendsave = 1; - G_WriteSaveName(slot, savegamestrings[slot]); - M_ClearMenus(0); - quickSaveSlot = slot; - // haleyjd 20130922: slight divergence. We clear the destination slot - // of files here, which vanilla did not do. As a result, 1.31 had - // broken save behavior to the point of unusability. fraggle agrees - // this is detrimental enough to be fixed - unconditionally, for now. - ClearSlot(); - FromCurr(); - } - else - M_StartMessage(DEH_String(QSAVESPOT), NULL, false); -} - -// -// User wants to save. Start string input for M_Responder -// -void M_SaveSelect(int choice) -{ - int x, y; - - // we are going to be intercepting all chars - saveStringEnter = 1; - - // We need to turn on text input: - x = LoadDef.x - 11; - y = LoadDef.y + choice * LINEHEIGHT - 4; - I_StartTextInput(x, y, x + 8 + 24 * 8 + 8, y + LINEHEIGHT - 2); - - // [STRIFE] - quickSaveSlot = choice; - //saveSlot = choice; - - M_StringCopy(saveOldString, savegamestrings[choice], sizeof(saveOldString)); - if (!strcmp(savegamestrings[choice], DEH_String(EMPTYSTRING))) - savegamestrings[choice][0] = 0; - saveCharIndex = strlen(savegamestrings[choice]); -} - -// -// Selected from DOOM menu -// -void M_SaveGame (int choice) -{ - // [STRIFE] - if (netgame) - { - // haleyjd 20110211: Hooray for Rogue's awesome multiplayer support... - M_StartMessage(DEH_String("You can't save a netgame"), NULL, false); - return; - } - if (!usergame) - { - M_StartMessage(DEH_String(SAVEDEAD),NULL,false); - return; - } - - if (gamestate != GS_LEVEL) - return; - - // [STRIFE] - if(gameversion == exe_strife_1_31) - { - // haleyjd 20130301: in 1.31, we can choose a slot again. - M_SetupNextMenu(&SaveDef); - M_ReadSaveStrings(); - } - else - { - // In 1.2 and lower, you save over your character slot exclusively - M_ReadSaveStrings(); - M_DoSave(quickSaveSlot); - } -} - - - -// -// M_QuickSave -// -char tempstring[80]; - -void M_QuickSaveResponse(int key) -{ - if (key == key_menu_confirm) - { - M_DoSave(quickSaveSlot); - S_StartSound(NULL, sfx_mtalht); // [STRIFE] sound - } -} - -void M_QuickSave(void) -{ - if (netgame) - { - // haleyjd 20110211 [STRIFE]: More fun... - M_StartMessage(DEH_String("You can't save a netgame"), NULL, false); - return; - } - - if (!usergame) - { - S_StartSound(NULL, sfx_oof); - return; - } - - if (gamestate != GS_LEVEL) - return; - - if (quickSaveSlot < 0) - { - M_StartControlPanel(); - M_ReadSaveStrings(); - M_SetupNextMenu(&SaveDef); - quickSaveSlot = -2; // means to pick a slot now - return; - } - DEH_snprintf(tempstring, 80, QSPROMPT, savegamestrings[quickSaveSlot]); - M_StartMessage(tempstring,M_QuickSaveResponse,true); -} - - - -// -// M_QuickLoadResponse -// -void M_QuickLoadResponse(int key) -{ - if (key == key_menu_confirm) - { - M_LoadSelect(quickSaveSlot); - S_StartSound(NULL, sfx_mtalht); // [STRIFE] sound - } -} - -// -// M_QuickLoad -// -// [STRIFE] Verified unmodified -// -void M_QuickLoad(void) -{ - if (netgame) - { - M_StartMessage(DEH_String(QLOADNET),NULL,false); - return; - } - - if (quickSaveSlot < 0) - { - M_StartMessage(DEH_String(QSAVESPOT),NULL,false); - return; - } - DEH_snprintf(tempstring, 80, QLPROMPT, savegamestrings[quickSaveSlot]); - M_StartMessage(tempstring,M_QuickLoadResponse,true); -} - - - - -// -// Read This Menus -// Had a "quick hack to fix romero bug" -// haleyjd 08/28/10: [STRIFE] Draw HELP1, unconditionally. -// -void M_DrawReadThis1(void) -{ - inhelpscreens = true; - - V_DrawPatchDirect (0, 0, W_CacheLumpName(DEH_String("HELP1"), PU_CACHE)); -} - - - -// -// Read This Menus -// haleyjd 08/28/10: [STRIFE] Not optional, draws HELP2 -// -void M_DrawReadThis2(void) -{ - inhelpscreens = true; - - V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP2"), PU_CACHE)); -} - - -// -// Read This Menus -// haleyjd 08/28/10: [STRIFE] New function to draw HELP3. -// -void M_DrawReadThis3(void) -{ - inhelpscreens = true; - - V_DrawPatchDirect(0, 0, W_CacheLumpName(DEH_String("HELP3"), PU_CACHE)); -} - -// -// Change Sfx & Music volumes -// -// haleyjd 08/29/10: [STRIFE] -// * Changed title graphic coordinates -// * Added voice volume and sensitivity sliders -// -void M_DrawSound(void) -{ - V_DrawPatchDirect (100, 10, W_CacheLumpName(DEH_String("M_SVOL"), PU_CACHE)); - - M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_vol+1), - 16,sfxVolume); - - M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1), - 16,musicVolume); - - M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(voice_vol+1), - 16,voiceVolume); - - M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(sfx_mouse+1), - 16,mouseSensitivity); -} - -void M_Sound(int choice) -{ - M_SetupNextMenu(&SoundDef); -} - -void M_SfxVol(int choice) -{ - switch(choice) - { - case 0: - if (sfxVolume) - sfxVolume--; - break; - case 1: - if (sfxVolume < 15) - sfxVolume++; - break; - } - - S_SetSfxVolume(sfxVolume * 8); -} - -// -// M_VoiceVol -// -// haleyjd 08/29/10: [STRIFE] New function -// Sets voice volume level. -// -void M_VoiceVol(int choice) -{ - switch(choice) - { - case 0: - if (voiceVolume) - voiceVolume--; - break; - case 1: - if (voiceVolume < 15) - voiceVolume++; - break; - } - - S_SetVoiceVolume(voiceVolume * 8); -} - -void M_MusicVol(int choice) -{ - switch(choice) - { - case 0: - if (musicVolume) - musicVolume--; - break; - case 1: - if (musicVolume < 15) - musicVolume++; - break; - } - - S_SetMusicVolume(musicVolume * 8); -} - - - - -// -// M_DrawMainMenu -// -// haleyjd 08/27/10: [STRIFE] Changed x coordinate; M_DOOM -> M_STRIFE -// -void M_DrawMainMenu(void) -{ - V_DrawPatchDirect(84, 2, - W_CacheLumpName(DEH_String("M_STRIFE"), PU_CACHE)); -} - - - - -// -// M_NewGame -// -// haleyjd 08/31/10: [STRIFE] Changed M_NEWG -> M_NGAME -// -void M_DrawNewGame(void) -{ - V_DrawPatchDirect(96, 14, W_CacheLumpName(DEH_String("M_NGAME"), PU_CACHE)); - V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_SKILL"), PU_CACHE)); -} - -void M_NewGame(int choice) -{ - if (netgame && !demoplayback) - { - M_StartMessage(DEH_String(NEWGAME),NULL,false); - return; - } - // haleyjd 09/07/10: [STRIFE] Removed Chex Quest and DOOM gamemodes - if(gameversion == exe_strife_1_31) - namingCharacter = true; // for 1.31 save logic - M_SetupNextMenu(&NewDef); -} - - -// -// M_Episode -// - -// haleyjd: [STRIFE] Unused -/* -int epi; - -void M_DrawEpisode(void) -{ - V_DrawPatchDirect(54, 38, W_CacheLumpName(DEH_String("M_EPISOD"), PU_CACHE)); -} - -void M_VerifyNightmare(int key) -{ - if (key != key_menu_confirm) - return; - - G_DeferedInitNew(nightmare, 1); - M_ClearMenus (0); -} -*/ - -void M_ChooseSkill(int choice) -{ - // haleyjd 09/07/10: Removed nightmare confirmation - // [STRIFE]: start "Name Your Character" menu - menuskill = choice; - currentMenu = &NameCharDef; - itemOn = NameCharDef.lastOn; - M_ReadSaveStrings(); -} - -/* -// haleyjd [STRIFE] Unused -void M_Episode(int choice) -{ - if ( (gamemode == shareware) - && choice) - { - M_StartMessage(DEH_String(SWSTRING),NULL,false); - M_SetupNextMenu(&ReadDef1); - return; - } - - // Yet another hack... - if ( (gamemode == registered) - && (choice > 2)) - { - fprintf( stderr, - "M_Episode: 4th episode requires UltimateDOOM\n"); - choice = 0; - } - - epi = choice; - M_SetupNextMenu(&NewDef); -} -*/ - - -// -// M_Options -// -char detailNames[2][9] = {"M_GDHIGH","M_GDLOW"}; -char msgNames[2][9] = {"M_MSGOFF","M_MSGON"}; - - -void M_DrawOptions(void) -{ - // haleyjd 08/27/10: [STRIFE] M_OPTTTL -> M_OPTION - V_DrawPatchDirect(108, 15, - W_CacheLumpName(DEH_String("M_OPTION"), PU_CACHE)); - - // haleyjd 08/26/10: [STRIFE] Removed messages, sensitivity, detail. - - M_DrawThermo(OptionsDef.x,OptionsDef.y+LINEHEIGHT*(scrnsize+1), - 9,screenSize); -} - -void M_Options(int choice) -{ - M_SetupNextMenu(&OptionsDef); -} - -// -// M_AutoUseHealth -// -// [STRIFE] New function -// haleyjd 20110211: toggle autouse health state -// -void M_AutoUseHealth(void) -{ - if(!netgame && usergame) - { - players[consoleplayer].cheats ^= CF_AUTOHEALTH; - - if(players[consoleplayer].cheats & CF_AUTOHEALTH) - players[consoleplayer].message = DEH_String("Auto use health ON"); - else - players[consoleplayer].message = DEH_String("Auto use health OFF"); - } -} - -// -// M_ChangeShowText -// -// [STRIFE] New function -// -void M_ChangeShowText(void) -{ - dialogshowtext ^= true; - - if(dialogshowtext) - players[consoleplayer].message = DEH_String("Conversation Text On"); - else - players[consoleplayer].message = DEH_String("Conversation Text Off"); -} - -// -// Toggle messages on/off -// -// [STRIFE] Messages cannot be disabled in Strife -/* -void M_ChangeMessages(int choice) -{ - // warning: unused parameter `int choice' - choice = 0; - showMessages = 1 - showMessages; - - if (!showMessages) - players[consoleplayer].message = DEH_String(MSGOFF); - else - players[consoleplayer].message = DEH_String(MSGON); - - message_dontfuckwithme = true; -} -*/ - - -// -// M_EndGame -// -void M_EndGameResponse(int key) -{ - if (key != key_menu_confirm) - return; - - currentMenu->lastOn = itemOn; - M_ClearMenus (0); - D_StartTitle (); -} - -void M_EndGame(int choice) -{ - choice = 0; - if (!usergame) - { - S_StartSound(NULL,sfx_oof); - return; - } - - if (netgame) - { - M_StartMessage(DEH_String(NETEND),NULL,false); - return; - } - - M_StartMessage(DEH_String(ENDGAME),M_EndGameResponse,true); -} - - - - -// -// M_ReadThis -// -void M_ReadThis(int choice) -{ - choice = 0; - M_SetupNextMenu(&ReadDef1); -} - -// -// M_ReadThis2 -// -// haleyjd 08/28/10: [STRIFE] Eliminated DOOM stuff. -// -void M_ReadThis2(int choice) -{ - choice = 0; - M_SetupNextMenu(&ReadDef2); -} - -// -// M_ReadThis3 -// -// haleyjd 08/28/10: [STRIFE] New function. -// -void M_ReadThis3(int choice) -{ - choice = 0; - M_SetupNextMenu(&ReadDef3); -} - -/* -// haleyjd 08/28/10: [STRIFE] Not used. -void M_FinishReadThis(int choice) -{ - choice = 0; - M_SetupNextMenu(&MainDef); -} -*/ - -#if 0 - -// -// M_CheckStartCast -// -// [STRIFE] New but unused function. Was going to start a cast -// call from within the menu system... not functional even in -// the earliest demo version. -// -void M_CheckStartCast() -{ - if(usergame) - { - M_StartMessage(DEH_String("You have to end your game first."), NULL, false); - return; - } - - F_StartCast(); - M_ClearMenus(0); -} -#endif - -// -// M_QuitResponse -// -// haleyjd 09/11/10: [STRIFE] Modifications to start up endgame -// demosequence. -// -void M_QuitResponse(int key) -{ - char buffer[20]; - - if (key != key_menu_confirm) - return; - - if(netgame) - I_Quit(); - else - { - DEH_snprintf(buffer, sizeof(buffer), "qfmrm%i", gametic % 8 + 1); - I_StartVoice(buffer); - D_QuitGame(); - } -} - -/* -// haleyjd 09/11/10: [STRIFE] Unused -static char *M_SelectEndMessage(void) -{ -} -*/ - -// -// M_QuitStrife -// -// [STRIFE] Renamed from M_QuitDOOM -// haleyjd 09/11/10: No randomized text message; that's taken care of -// by the randomized voice message after confirmation. -// -void M_QuitStrife(int choice) -{ - DEH_snprintf(endstring, sizeof(endstring), - "Do you really want to leave?\n\n" DOSY); - - M_StartMessage(endstring, M_QuitResponse, true); -} - - - - -void M_ChangeSensitivity(int choice) -{ - switch(choice) - { - case 0: - if (mouseSensitivity) - mouseSensitivity--; - break; - case 1: - if (mouseSensitivity < 9) - mouseSensitivity++; - break; - } -} - -/* -// haleyjd [STRIFE] Unused -void M_ChangeDetail(int choice) -{ - choice = 0; - detailLevel = 1 - detailLevel; - - R_SetViewSize (screenblocks, detailLevel); - - if (!detailLevel) - players[consoleplayer].message = DEH_String(DETAILHI); - else - players[consoleplayer].message = DEH_String(DETAILLO); -} -*/ - -// [STRIFE] Verified unmodified -void M_SizeDisplay(int choice) -{ - switch(choice) - { - case 0: - if (screenSize > 0) - { - screenblocks--; - screenSize--; - } - break; - case 1: - if (screenSize < 8) - { - screenblocks++; - screenSize++; - } - break; - } - - R_SetViewSize (screenblocks, detailLevel); -} - - - - -// -// Menu Functions -// - -// -// M_DrawThermo -// -// haleyjd 08/28/10: [STRIFE] Changes to some patch coordinates. -// -void -M_DrawThermo -( int x, - int y, - int thermWidth, - int thermDot ) -{ - int xx; - int yy; // [STRIFE] Needs a temp y coordinate variable - int i; - - xx = x; - yy = y + 6; // [STRIFE] +6 to y coordinate - V_DrawPatchDirect(xx, yy, W_CacheLumpName(DEH_String("M_THERML"), PU_CACHE)); - xx += 8; - for (i=0;ix - 10, menu->y + item * LINEHEIGHT - 1, - W_CacheLumpName(DEH_String("M_CELL1"), PU_CACHE)); -} - -void -M_DrawSelCell -( menu_t* menu, - int item ) -{ - V_DrawPatchDirect(menu->x - 10, menu->y + item * LINEHEIGHT - 1, - W_CacheLumpName(DEH_String("M_CELL2"), PU_CACHE)); -} - - -void -M_StartMessage -( const char *string, - void* routine, - boolean input ) -{ - messageLastMenuActive = menuactive; - messageToPrint = 1; - messageString = string; - messageRoutine = routine; - messageNeedsInput = input; - menuactive = true; - return; -} - - - -void M_StopMessage(void) -{ - menuactive = messageLastMenuActive; - messageToPrint = 0; -} - - - -// -// Find string width from hu_font chars -// -int M_StringWidth(const char *string) -{ - size_t i; - int w = 0; - int c; - - for (i = 0;i < strlen(string);i++) - { - c = toupper(string[i]) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE) - w += 4; - else - w += SHORT (hu_font[c]->width); - } - - return w; -} - - - -// -// Find string height from hu_font chars -// -int M_StringHeight(const char *string) -{ - size_t i; - int h; - int height = SHORT(hu_font[0]->height); - - h = height; - for (i = 0;i < strlen(string);i++) - if (string[i] == '\n') - h += height; - - return h; -} - - -// -// M_WriteText -// -// Write a string using the hu_font -// haleyjd 09/04/10: [STRIFE] -// * Rogue made a lot of changes to this for the dialog system. -// -int -M_WriteText -( int x, - int y, - const char* string) // haleyjd: made const for safety w/dialog engine -{ - int w; - const char* ch; - int c; - int cx; - int cy; - - ch = string; - cx = x; - cy = y; - - while(1) - { - c = *ch++; - if (!c) - break; - - // haleyjd 09/04/10: [STRIFE] Don't draw spaces at the start of lines. - if(c == ' ' && cx == x) - continue; - - if (c == '\n') - { - cx = x; - cy += 11; // haleyjd 09/04/10: [STRIFE]: Changed 12 -> 11 - continue; - } - - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c>= HU_FONTSIZE) - { - cx += 4; - continue; - } - - w = SHORT (hu_font[c]->width); - - // haleyjd 09/04/10: [STRIFE] Different linebreak handling - if (cx + w > SCREENWIDTH - 20) - { - cx = x; - cy += 11; - --ch; - } - else - { - V_DrawPatchDirect(cx, cy, hu_font[c]); - cx += w; - } - } - - // [STRIFE] Return final y coordinate. - return cy + 12; -} - -// -// M_DialogDimMsg -// -// [STRIFE] New function -// haleyjd 09/04/10: Painstakingly transformed from the assembly code, as the -// decompiler could not touch it. Redimensions a string to fit on screen, leaving -// at least a 20 pixel margin on the right side. The string passed in must be -// writable. -// -void M_DialogDimMsg(int x, int y, char *str, boolean useyfont) -{ - int rightbound = (SCREENWIDTH - 20) - x; - patch_t **fontarray; // ebp - int linewidth = 0; // esi - int i = 0; // edx - char *message = str; // edi - char bl; // bl - - if(useyfont) - fontarray = yfont; - else - fontarray = hu_font; - - bl = toupper(*message); - - if(!bl) - return; - - // outer loop - run to end of string - do - { - if(bl != '\n') - { - int charwidth; // eax - int tempwidth; // ecx - - if(bl < HU_FONTSTART || bl > HU_FONTEND) - charwidth = 4; - else - charwidth = SHORT(fontarray[bl - HU_FONTSTART]->width); - - tempwidth = linewidth + charwidth; - - // Test if the line still fits within the boundary... - if(tempwidth >= rightbound) - { - // Doesn't fit... - char *tempptr = &message[i]; // ebx - char al; // al - - // inner loop - run backward til a space (or the start of the - // string) is found, subtracting width off the current line. - // BUG: shouldn't we stop at a previous '\n' too? - while(*tempptr != ' ' && i > 0) - { - tempptr--; - // BUG: they didn't add the first char to linewidth yet... - linewidth -= charwidth; - i--; - al = toupper(*tempptr); - if(al < HU_FONTSTART || al > HU_FONTEND) - charwidth = 4; - else - charwidth = SHORT(fontarray[al - HU_FONTSTART]->width); - } - // Replace the space with a linebreak. - // BUG: what if i is zero? ... infinite loop time! - message[i] = '\n'; - linewidth = 0; - } - else - { - // The line does fit. - // Spaces at the start of a line don't count though. - if(!(bl == ' ' && linewidth == 0)) - linewidth += charwidth; - } - } - else - linewidth = 0; // '\n' seen, so reset the line width - } - while((bl = toupper(message[++i])) != 0); // step to the next character -} - -// These keys evaluate to a "null" key in Vanilla Doom that allows weird -// jumping in the menus. Preserve this behavior for accuracy. - -static boolean IsNullKey(int key) -{ - return key == KEY_PAUSE || key == KEY_CAPSLOCK - || key == KEY_SCRLCK || key == KEY_NUMLOCK; -} - -// -// CONTROL PANEL -// - -// -// M_Responder -// -boolean M_Responder (event_t* ev) -{ - int ch; - int key; - int i; - static int joywait = 0; - static int mousewait = 0; - static int mousey = 0; - static int lasty = 0; - static int mousex = 0; - static int lastx = 0; - int dir; - - // In testcontrols mode, none of the function keys should do anything - // - the only key is escape to quit. - - if (testcontrols) - { - if (ev->type == ev_quit - || (ev->type == ev_keydown - && (ev->data1 == key_menu_activate || ev->data1 == key_menu_quit))) - { - I_Quit(); - return true; - } - - return false; - } - - // "close" button pressed on window? - if (ev->type == ev_quit) - { - // First click on close button = bring up quit confirm message. - // Second click on close button = confirm quit - - if (menuactive && messageToPrint && messageRoutine == M_QuitResponse) - { - M_QuitResponse(key_menu_confirm); - } - else - { - S_StartSound(NULL, sfx_swtchn); - M_QuitStrife(0); - } - - return true; - } - - // key is the key pressed, ch is the actual character typed - - ch = 0; - key = -1; - - if (ev->type == ev_joystick && joywait < I_GetTime()) - { - if (JOY_GET_DPAD(ev->data6) != JOY_DIR_NONE) - { - dir = JOY_GET_DPAD(ev->data6); - } - else if (JOY_GET_LSTICK(ev->data6) != JOY_DIR_NONE) - { - dir = JOY_GET_LSTICK(ev->data6); - } - else - { - dir = JOY_GET_RSTICK(ev->data6); - } - - if (dir & JOY_DIR_UP) - { - key = key_menu_up; - joywait = I_GetTime() + 5; - } - else if (dir & JOY_DIR_DOWN) - { - key = key_menu_down; - joywait = I_GetTime() + 5; - } - if (dir & JOY_DIR_LEFT) - { - key = key_menu_left; - joywait = I_GetTime() + 5; - } - else if (dir & JOY_DIR_RIGHT) - { - key = key_menu_right; - joywait = I_GetTime() + 5; - } - -#define JOY_BUTTON_MAPPED(x) ((x) >= 0) -#define JOY_BUTTON_PRESSED(x) (JOY_BUTTON_MAPPED(x) && (ev->data1 & (1 << (x))) != 0) - - if (JOY_BUTTON_PRESSED(joybfire)) - { - // Simulate a 'Y' keypress when Doom show a Y/N dialog with Fire button. - if (messageToPrint && messageNeedsInput) - { - key = key_menu_confirm; - } - else - { - key = key_menu_forward; - } - joywait = I_GetTime() + 5; - joystick_fire_countdown = 5; - } - if (JOY_BUTTON_PRESSED(joybuse)) - { - // Simulate a 'N' keypress when Doom show a Y/N dialog with Use button. - if (messageToPrint && messageNeedsInput) - { - key = key_menu_abort; - } - else - { - key = key_menu_back; - } - joywait = I_GetTime() + 5; - } - if (JOY_BUTTON_PRESSED(joybmenu)) - { - key = key_menu_activate; - joywait = I_GetTime() + 5; - } - } - else - { - if (ev->type == ev_mouse && mousewait < I_GetTime()) - { - mousey += ev->data3; - if (mousey < lasty-30) - { - key = key_menu_down; - mousewait = I_GetTime() + 5; - mousey = lasty -= 30; - } - else if (mousey > lasty+30) - { - key = key_menu_up; - mousewait = I_GetTime() + 5; - mousey = lasty += 30; - } - - mousex += ev->data2; - if (mousex < lastx-30) - { - key = key_menu_left; - mousewait = I_GetTime() + 5; - mousex = lastx -= 30; - } - else if (mousex > lastx+30) - { - key = key_menu_right; - mousewait = I_GetTime() + 5; - mousex = lastx += 30; - } - - if (ev->data1&1) - { - key = key_menu_forward; - mousewait = I_GetTime() + 15; - mouse_fire_countdown = 5; // villsa [STRIFE] - } - - if (ev->data1&2) - { - key = key_menu_back; - mousewait = I_GetTime() + 15; - } - } - else - { - if (ev->type == ev_keydown) - { - key = ev->data1; - ch = ev->data2; - } - } - } - - if (key == -1) - return false; - - // Save Game string input - if (saveStringEnter) - { - switch(key) - { - case KEY_BACKSPACE: - if (saveCharIndex > 0) - { - saveCharIndex--; - savegamestrings[quickSaveSlot][saveCharIndex] = 0; - } - break; - - case KEY_ESCAPE: - saveStringEnter = 0; - I_StopTextInput(); - M_StringCopy(savegamestrings[quickSaveSlot], saveOldString, - sizeof(savegamestrings[quickSaveSlot])); - break; - - case KEY_ENTER: - // [STRIFE] - saveStringEnter = 0; - I_StopTextInput(); - if(gameversion == exe_strife_1_31 && !namingCharacter) - { - // In 1.31, we can be here as a result of normal saving again, - // whereas in 1.2 this only ever happens when naming your - // character to begin a new game. - M_DoSave(quickSaveSlot); - return true; - } - if (savegamestrings[quickSaveSlot][0]) - M_DoNameChar(quickSaveSlot); - break; - - default: - // Savegame name entry. This is complicated. - // Vanilla has a bug where the shift key is ignored when entering - // a savegame name. If vanilla_keyboard_mapping is on, we want - // to emulate this bug by using ev->data1. But if it's turned off, - // it implies the user doesn't care about Vanilla emulation: - // instead, use ev->data3 which gives the fully-translated and - // modified key input. - - if (ev->type != ev_keydown) - { - break; - } - - if (vanilla_keyboard_mapping) - { - ch = ev->data1; - } - else - { - ch = ev->data3; - } - - ch = toupper(ch); - - if (ch != ' ' - && (ch - HU_FONTSTART < 0 || ch - HU_FONTSTART >= HU_FONTSIZE)) - { - break; - } - - if (ch >= 32 && ch <= 127 && - saveCharIndex < SAVESTRINGSIZE-1 && - M_StringWidth(savegamestrings[quickSaveSlot]) < - (SAVESTRINGSIZE-2)*8) - { - savegamestrings[quickSaveSlot][saveCharIndex++] = ch; - savegamestrings[quickSaveSlot][saveCharIndex] = 0; - } - break; - } - return true; - } - - // Take care of any messages that need input - if (messageToPrint) - { - if (messageNeedsInput) - { - if (key != ' ' && key != KEY_ESCAPE - && key != key_menu_confirm && key != key_menu_abort) - { - return false; - } - } - - menuactive = messageLastMenuActive; - messageToPrint = 0; - if (messageRoutine) - messageRoutine(key); - - menupause = false; // [STRIFE] unpause - menuactive = false; - S_StartSound(NULL, sfx_mtalht); // [STRIFE] sound - return true; - } - - // [STRIFE]: - // * In v1.2 this is moved to F9 (quickload) - // * In v1.31 it is moved to F12 with DM spy, and quicksave - // functionality is restored separate from normal saving - /* - if (devparm && key == key_menu_help) - { - G_ScreenShot (); - return true; - } - */ - - // F-Keys - if (!menuactive) - { - if (key == key_menu_decscreen) // Screen size down - { - if (automapactive || chat_on) - return false; - M_SizeDisplay(0); - S_StartSound(NULL, sfx_stnmov); - return true; - } - else if (key == key_menu_incscreen) // Screen size up - { - if (automapactive || chat_on) - return false; - M_SizeDisplay(1); - S_StartSound(NULL, sfx_stnmov); - return true; - } - else if (key == key_menu_help) // Help key - { - M_StartControlPanel (); - // haleyjd 08/29/10: [STRIFE] always ReadDef1 - currentMenu = &ReadDef1; - - itemOn = 0; - S_StartSound(NULL, sfx_swtchn); - return true; - } - else if (key == key_menu_save) // Save - { - // [STRIFE]: Hub saves - if(gameversion == exe_strife_1_31) - namingCharacter = false; // just saving normally, in 1.31 - - if(netgame || players[consoleplayer].health <= 0 || - players[consoleplayer].cheats & CF_ONFIRE) - { - S_StartSound(NULL, sfx_oof); - } - else - { - M_StartControlPanel(); - S_StartSound(NULL, sfx_swtchn); - M_SaveGame(0); - } - return true; - } - else if (key == key_menu_load) // Load - { - // [STRIFE]: Hub saves - if(gameversion == exe_strife_1_31) - { - // 1.31: normal save loading - namingCharacter = false; - M_StartControlPanel(); - M_LoadGame(0); - S_StartSound(NULL, sfx_swtchn); - } - else - { - // Pre 1.31: quickload only - S_StartSound(NULL, sfx_swtchn); - M_QuickLoad(); - } - return true; - } - else if (key == key_menu_volume) // Sound Volume - { - M_StartControlPanel (); - currentMenu = &SoundDef; - itemOn = sfx_vol; - S_StartSound(NULL, sfx_swtchn); - return true; - } - else if (key == key_menu_detail) // Detail toggle - { - //M_ChangeDetail(0); - M_AutoUseHealth(); // [STRIFE] - S_StartSound(NULL, sfx_swtchn); - return true; - } - else if (key == key_menu_qsave) // Quicksave - { - // [STRIFE]: Hub saves - if(gameversion == exe_strife_1_31) - namingCharacter = false; // for 1.31 save changes - - if(netgame || players[consoleplayer].health <= 0 || - players[consoleplayer].cheats & CF_ONFIRE) - { - S_StartSound(NULL, sfx_oof); - } - else - { - S_StartSound(NULL, sfx_swtchn); - M_QuickSave(); - } - return true; - } - else if (key == key_menu_endgame) // End game - { - S_StartSound(NULL, sfx_swtchn); - M_EndGame(0); - return true; - } - else if (key == key_menu_messages) // Toggle messages - { - //M_ChangeMessages(0); - M_ChangeShowText(); // [STRIFE] - S_StartSound(NULL, sfx_swtchn); - return true; - } - else if (key == key_menu_qload) // Quickload - { - // [STRIFE] - // * v1.2: takes a screenshot - // * v1.31: does quickload again - if(gameversion == exe_strife_1_31) - { - namingCharacter = false; - S_StartSound(NULL, sfx_swtchn); - M_QuickLoad(); - } - else - G_ScreenShot(); - return true; - } - else if (key == key_menu_quit) // Quit DOOM - { - S_StartSound(NULL, sfx_swtchn); - M_QuitStrife(0); - return true; - } - else if (key == key_menu_gamma) // gamma toggle - { - usegamma++; - if (usegamma > 4) - usegamma = 0; - players[consoleplayer].message = DEH_String(gammamsg[usegamma]); - I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE)); - return true; - } - else if(gameversion == exe_strife_1_31 && key == key_spy) - { - // haleyjd 20130301: 1.31 moved screenshots to F12. - G_ScreenShot(); - return true; - } - else if (key != 0 && key == key_menu_screenshot) - { - G_ScreenShot(); - return true; - } - } - - // Pop-up menu? - if (!menuactive) - { - if (key == key_menu_activate) - { - M_StartControlPanel (); - S_StartSound(NULL, sfx_swtchn); - return true; - } - return false; - } - - - // Keys usable within menu - - if (key == key_menu_down) - { - // Move down to next item - - do - { - if (itemOn+1 > currentMenu->numitems-1) - itemOn = 0; - else itemOn++; - S_StartSound(NULL, sfx_pstop); - } while(currentMenu->menuitems[itemOn].status==-1); - - return true; - } - else if (key == key_menu_up) - { - // Move back up to previous item - - do - { - if (!itemOn) - itemOn = currentMenu->numitems-1; - else itemOn--; - S_StartSound(NULL, sfx_pstop); - } while(currentMenu->menuitems[itemOn].status==-1); - - return true; - } - else if (key == key_menu_left) - { - // Slide slider left - - if (currentMenu->menuitems[itemOn].routine && - currentMenu->menuitems[itemOn].status == 2) - { - S_StartSound(NULL, sfx_stnmov); - currentMenu->menuitems[itemOn].routine(0); - } - return true; - } - else if (key == key_menu_right) - { - // Slide slider right - - if (currentMenu->menuitems[itemOn].routine && - currentMenu->menuitems[itemOn].status == 2) - { - S_StartSound(NULL, sfx_stnmov); - currentMenu->menuitems[itemOn].routine(1); - } - return true; - } - else if (key == key_menu_forward) - { - // Activate menu item - - if (currentMenu->menuitems[itemOn].routine && - currentMenu->menuitems[itemOn].status) - { - currentMenu->lastOn = itemOn; - if (currentMenu->menuitems[itemOn].status == 2) - { - currentMenu->menuitems[itemOn].routine(1); // right arrow - S_StartSound(NULL, sfx_stnmov); - } - else - { - currentMenu->menuitems[itemOn].routine(itemOn); - //S_StartSound(NULL, sfx_swish); [STRIFE] No sound is played here. - } - } - return true; - } - else if (key == key_menu_activate) - { - // Deactivate menu - if(gameversion == exe_strife_1_31) // [STRIFE]: 1.31 saving - namingCharacter = false; - - if(menuindialog) // [STRIFE] - Get out of dialog engine semi-gracefully - P_DialogDoChoice(-1); - - currentMenu->lastOn = itemOn; - M_ClearMenus (0); - S_StartSound(NULL, sfx_mtalht); // villsa [STRIFE]: sounds - return true; - } - else if (key == key_menu_back) - { - // Go back to previous menu - - currentMenu->lastOn = itemOn; - if (currentMenu->prevMenu) - { - currentMenu = currentMenu->prevMenu; - itemOn = currentMenu->lastOn; - S_StartSound(NULL, sfx_swtchn); - } - return true; - } - - // Keyboard shortcut? - // Vanilla Strife has a weird behavior where it jumps to the scroll bars - // when certain keys are pressed, so emulate this. - - else if (ch != 0 || IsNullKey(key)) - { - // Keyboard shortcut? - - for (i = itemOn+1;i < currentMenu->numitems;i++) - { - if (currentMenu->menuitems[i].alphaKey == ch) - { - itemOn = i; - S_StartSound(NULL, sfx_pstop); - return true; - } - } - - for (i = 0;i <= itemOn;i++) - { - if (currentMenu->menuitems[i].alphaKey == ch) - { - itemOn = i; - S_StartSound(NULL, sfx_pstop); - return true; - } - } - } - - return false; -} - - - -// -// M_StartControlPanel -// -void M_StartControlPanel (void) -{ - // intro might call this repeatedly - if (menuactive) - return; - - menuactive = 1; - menupause = true; - currentMenu = &MainDef; // JDC - itemOn = currentMenu->lastOn; // JDC -} - - -// -// M_Drawer -// Called after the view has been rendered, -// but before it has been blitted. -// -void M_Drawer (void) -{ - static short x; - static short y; - unsigned int i; - unsigned int max; - char string[80]; - const char *name; - int start; - - inhelpscreens = false; - - // Horiz. & Vertically center string and print it. - if (messageToPrint) - { - start = 0; - y = 100 - M_StringHeight(messageString) / 2; - while (messageString[start] != '\0') - { - int foundnewline = 0; - - for (i = 0; i < strlen(messageString + start); i++) - { - if (messageString[start + i] == '\n') - { - M_StringCopy(string, messageString + start, - sizeof(string)); - if (i < sizeof(string)) - { - string[i] = '\0'; - } - - foundnewline = 1; - start += i + 1; - break; - } - } - - if (!foundnewline) - { - M_StringCopy(string, messageString + start, - sizeof(string)); - start += strlen(string); - } - - x = 160 - M_StringWidth(string) / 2; - M_WriteText(x, y, string); - y += SHORT(hu_font[0]->height); - } - - return; - } - - if (!menuactive) - return; - - if (currentMenu->routine) - currentMenu->routine(); // call Draw routine - - // DRAW MENU - x = currentMenu->x; - y = currentMenu->y; - max = currentMenu->numitems; - - for (i=0;imenuitems[i].name); - - if (name[0]) - { - V_DrawPatchDirect (x, y, W_CacheLumpName(name, PU_CACHE)); - } - y += LINEHEIGHT; - } - - - // haleyjd 08/27/10: [STRIFE] Adjust to draw spinning Sigil - // DRAW SIGIL - V_DrawPatchDirect(x + CURSORXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT, - W_CacheLumpName(DEH_String(cursorName[whichCursor]), - PU_CACHE)); - -} - - -// -// M_ClearMenus -// -// haleyjd 08/28/10: [STRIFE] Added an int param so this can be called by menus. -// 09/08/10: Added menupause. -// -void M_ClearMenus (int choice) -{ - choice = 0; // haleyjd: for no warning; not from decompilation. - menuactive = 0; - menupause = 0; -} - - - - -// -// M_SetupNextMenu -// -void M_SetupNextMenu(menu_t *menudef) -{ - currentMenu = menudef; - itemOn = currentMenu->lastOn; -} - - -// -// M_Ticker -// -// haleyjd 08/27/10: [STRIFE] Rewritten for Sigil cursor -// -void M_Ticker (void) -{ - if (--cursorAnimCounter <= 0) - { - whichCursor = (whichCursor + 1) % 8; - cursorAnimCounter = 5; - } -} - - -// -// M_Init -// -// haleyjd 08/27/10: [STRIFE] Removed DOOM gamemode stuff -// -void M_Init (void) -{ - currentMenu = &MainDef; - menuactive = 0; - itemOn = currentMenu->lastOn; - whichCursor = 0; - cursorAnimCounter = 10; - screenSize = screenblocks - 3; - messageToPrint = 0; - messageString = NULL; - messageLastMenuActive = menuactive; // STRIFE-FIXME: assigns 0 here... - quickSaveSlot = -1; - - // [STRIFE]: Initialize savegame paths and clear temporary directory - G_WriteSaveName(5, "ME"); - ClearTmp(); - - // Here we could catch other version dependencies, - // like HELP1/2, and four episodes. -} - diff --git a/games/NXDoom/src/strife/m_menu.h b/games/NXDoom/src/strife/m_menu.h deleted file mode 100644 index 08ad1a244dc..00000000000 --- a/games/NXDoom/src/strife/m_menu.h +++ /dev/null @@ -1,104 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Menu widget stuff, episode selection and such. -// - - -#ifndef __M_MENU__ -#define __M_MENU__ - -#include "d_event.h" - -// -// MENU TYPEDEFS -// - -// haleyjd 09/04/10: [STRIFE] Made external - -typedef struct -{ - // 0 = no cursor here, 1 = ok, 2 = arrows ok - short status; - - char name[10]; - - // choice = menu item #. - // if status = 2, - // choice=0:leftarrow,1:rightarrow - void (*routine)(int choice); - - // hotkey in menu - char alphaKey; -} menuitem_t; - -typedef struct menu_s -{ - short numitems; // # of menu items - struct menu_s* prevMenu; // previous menu - menuitem_t* menuitems; // menu items - void (*routine)(); // draw routine - short x; - short y; // x,y of menu - short lastOn; // last item user was on in menu -} menu_t; - -extern menu_t* currentMenu; // villsa [STRIFE] made external -extern short itemOn; - -// -// MENUS -// -// Called by main loop, -// saves config file and calls I_Quit when user exits. -// Even when the menu is not displayed, -// this can resize the view and change game parameters. -// Does all the real work of the menu interaction. -boolean M_Responder (event_t *ev); - - -// Called by main loop, -// only used for menu (skull cursor) animation. -void M_Ticker (void); - -// Called by main loop, -// draws the menus directly into the screen buffer. -void M_Drawer (void); - -// Called by D_DoomMain, -// loads the config file. -void M_Init (void); - -// Called by intro code to force menu up upon a keypress, -// does nothing if menu is already up. -void M_StartControlPanel (void); - -// haleyjd 09/04/10: Externalized. Draws menu text. -int M_WriteText(int x, int y, const char *string); - -// haleyjd 09/04/10: [STRIFE] New function. -void M_DialogDimMsg(int x, int y, char *str, boolean useyfont); - -// haleyjd [STRIFE] Externalized -void M_ClearMenus (int choice); -void M_LoadSelect(int choice); - -extern int detailLevel; -extern int screenblocks; - -extern boolean inhelpscreens; - - -#endif diff --git a/games/NXDoom/src/strife/m_random.c b/games/NXDoom/src/strife/m_random.c deleted file mode 100644 index 2098c1a7a90..00000000000 --- a/games/NXDoom/src/strife/m_random.c +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Random number LUT. -// - - -#include - -#include "m_random.h" - -// -// M_Random -// Returns a 0-255 number -// - -static const unsigned char rndtable[256] = { - 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 , - 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 , - 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 , - 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 , - 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 , - 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 , - 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 , - 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 , - 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 , - 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 , - 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 , - 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 , - 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 , - 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 , - 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 , - 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 , - 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 , - 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 , - 120, 163, 236, 249 -}; - -int rndindex = 0; -int prndindex = 0; - -// Which one is deterministic? -int P_Random (void) -{ - prndindex = (prndindex+1)&0xff; - return rndtable[prndindex]; -} - -int M_Random (void) -{ - rndindex = (rndindex+1)&0xff; - return rndtable[rndindex]; -} - -// -// M_ClearRandom -// -// haleyjd 20110204 [STRIFE]: No "seeding" of M_Random index -// -void M_ClearRandom (void) -{ - prndindex = 0; - rndindex = 0; -} - - - - diff --git a/games/NXDoom/src/strife/m_random.h b/games/NXDoom/src/strife/m_random.h deleted file mode 100644 index aa6291ae9e4..00000000000 --- a/games/NXDoom/src/strife/m_random.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - - -#ifndef __M_RANDOM__ -#define __M_RANDOM__ - - -#include "doomtype.h" - - - -// Returns a number from 0 to 255, -// from a lookup table. -int M_Random (void); - -// As M_Random, but used only by the play simulation. -int P_Random (void); - -// Fix randoms for demos. -void M_ClearRandom (void); - - -#endif diff --git a/games/NXDoom/src/strife/m_saves.c b/games/NXDoom/src/strife/m_saves.c deleted file mode 100644 index 561ec6a23ce..00000000000 --- a/games/NXDoom/src/strife/m_saves.c +++ /dev/null @@ -1,482 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2010 James Haley, Samuel Villarreal -// -// 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. -// -// DESCRIPTION: -// -// [STRIFE] New Module -// -// Strife Hub Saving Code -// - -#include -#include -#include - -#include "z_zone.h" -#include "i_glob.h" -#include "i_system.h" -#include "d_player.h" -#include "deh_str.h" -#include "doomstat.h" -#include "m_misc.h" -#include "m_saves.h" -#include "p_dialog.h" - -// -// File Paths -// -// Strife maintains multiple file paths related to savegames. -// -char *savepath; // The actual path of the selected saveslot -char *savepathtemp; // The path of the temporary saveslot (strfsav6.ssg) -char *loadpath; // Path used while loading the game - -char character_name[CHARACTER_NAME_LEN]; // Name of "character" for saveslot - -// -// ClearTmp -// -// Clear the temporary save directory -// -void ClearTmp(void) -{ - glob_t *glob; - - if(savepathtemp == NULL) - I_Error("you fucked up savedir man!"); - - glob = I_StartGlob(savepathtemp, "*", 0); - if (glob == NULL) - I_Error("ClearTmp: Couldn't open dir %s", savepathtemp); - - for (;;) - { - const char *path = I_NextGlob(glob); - - if (path == NULL) - { - break; - } - M_remove(path); - } - - I_EndGlob(glob); -} - -// -// ClearSlot -// -// Clear a single save slot folder -// -void ClearSlot(void) -{ - glob_t *glob; - - if(savepath == NULL) - I_Error("userdir is fucked up man!"); - - glob = I_StartGlob(savepath, "*", 0); - if (glob == NULL) - I_Error("ClearSlot: Couldn't open dir %s", savepath); - - for (;;) - { - const char *filepath = I_NextGlob(glob); - - if (filepath == NULL) - { - break; - } - - M_remove(filepath); - } - - I_EndGlob(glob); -} - -// -// FromCurr -// -// Copying files from savepathtemp to savepath -// -void FromCurr(void) -{ - glob_t *glob; - - glob = I_StartGlob(savepathtemp, "*", 0); - - if (glob == NULL) - I_Error("FromCurr: Couldn't open dir %s", savepathtemp); - - for (;;) - { - byte *filebuffer; - int filelen; - const char *srcfilename; - char *dstfilename; - - srcfilename = I_NextGlob(glob); - if (srcfilename == NULL) - { - break; - } - - dstfilename = M_SafeFilePath(savepath, M_BaseName(srcfilename)); - - filelen = M_ReadFile(srcfilename, &filebuffer); - M_WriteFile(dstfilename, filebuffer, filelen); - - Z_Free(filebuffer); - Z_Free(dstfilename); - } - - I_EndGlob(glob); -} - -// -// ToCurr -// -// Copying files from savepath to savepathtemp -// -void ToCurr(void) -{ - glob_t *glob; - - ClearTmp(); - - // BUG: Rogue copypasta'd this error message, which is why we don't know - // the real original name of this function. - glob = I_StartGlob(savepath, "*", 0); - if (glob == NULL) - I_Error("ClearSlot: Couldn't open dir %s", savepath); - - for (;;) - { - byte *filebuffer; - int filelen; - const char *srcfilename; - char *dstfilename; - - srcfilename = I_NextGlob(glob); - if (srcfilename == NULL) - { - break; - } - - dstfilename = M_SafeFilePath(savepathtemp, M_BaseName(srcfilename)); - - filelen = M_ReadFile(srcfilename, &filebuffer); - M_WriteFile(dstfilename, filebuffer, filelen); - - Z_Free(filebuffer); - Z_Free(dstfilename); - } - - I_EndGlob(glob); -} - -// -// M_SaveMoveMapToHere -// -// Moves a map to the "HERE" save. -// -void M_SaveMoveMapToHere(void) -{ - char *mapsave = NULL; - char *heresave = NULL; - char tmpnum[33]; - - // haleyjd: no itoa available... - M_snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap); - - // haleyjd: use M_SafeFilePath, not sprintf - mapsave = M_SafeFilePath(savepath, tmpnum); - heresave = M_SafeFilePath(savepath, "here"); - - // haleyjd: use M_FileExists, not access - if(M_FileExists(mapsave)) - { - M_remove(heresave); - M_rename(mapsave, heresave); - } - - Z_Free(mapsave); - Z_Free(heresave); -} - -// -// M_SaveMoveHereToMap -// -// Moves the "HERE" save to a map. -// -void M_SaveMoveHereToMap(void) -{ - char *mapsave = NULL; - char *heresave = NULL; - char tmpnum[33]; - - // haleyjd: no itoa available... - M_snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap); - - mapsave = M_SafeFilePath(savepathtemp, tmpnum); - heresave = M_SafeFilePath(savepathtemp, "here"); - - if(M_FileExists(heresave)) - { - M_remove(mapsave); - M_rename(heresave, mapsave); - } - - Z_Free(mapsave); - Z_Free(heresave); -} - -// -// M_SaveMisObj -// -// Writes the mission objective into the MIS_OBJ file. -// -boolean M_SaveMisObj(const char *path) -{ - boolean result; - char *destpath = NULL; - - // haleyjd 20110210: use M_SafeFilePath, not sprintf - destpath = M_SafeFilePath(path, "mis_obj"); - result = M_WriteFile(destpath, mission_objective, OBJECTIVE_LEN); - - Z_Free(destpath); - return result; -} - -// -// M_ReadMisObj -// -// Reads the mission objective from the MIS_OBJ file. -// -void M_ReadMisObj(void) -{ - FILE *f = NULL; - char *srcpath = NULL; - - // haleyjd: use M_SafeFilePath, not sprintf - srcpath = M_SafeFilePath(savepathtemp, "mis_obj"); - - if((f = M_fopen(srcpath, "rb"))) - { - int retval = fread(mission_objective, 1, OBJECTIVE_LEN, f); - fclose(f); - if (retval != OBJECTIVE_LEN) - { - I_Error("M_ReadMisObj: error while reading mission objective"); - } - } - - Z_Free(srcpath); -} - -//============================================================================= -// -// Original Routines -// -// haleyjd - None of the below code is derived from Strife itself, but has been -// adapted or created in order to provide secure, portable filepath handling -// for the purposes of savegame support. This is partially needed to allow for -// differences in Choco due to it being multiplatform. The rest exists because -// I cannot stand programming in an impoverished ANSI C environment that -// calls sprintf on fixed-size buffers. :P -// - -// -// M_Calloc -// -// haleyjd 20110210 - original routine -// Because Choco doesn't have Z_Calloc O_o -// -void *M_Calloc(size_t n1, size_t n2) -{ - return (n1 *= n2) ? memset(Z_Malloc(n1, PU_STATIC, NULL), 0, n1) : NULL; -} - -// -// M_StringAlloc -// -// haleyjd: This routine takes any number of strings and a number of extra -// characters, calculates their combined length, and calls Z_Alloca to create -// a temporary buffer of that size. This is extremely useful for allocation of -// file paths, and is used extensively in d_main.c. The pointer returned is -// to a temporary Z_Alloca buffer, which lives until the next main loop -// iteration, so don't cache it. Note that this idiom is not possible with the -// normal non-standard alloca function, which allocates stack space. -// -// [STRIFE] - haleyjd 20110210 -// This routine is taken from the Eternity Engine and adapted to do without -// Z_Alloca. I need secure string concatenation for filepath handling. The -// only difference from use in EE is that the pointer returned in *str must -// be manually freed. -// -int M_StringAlloc(char **str, int numstrs, size_t extra, const char *str1, ...) -{ - va_list args; - size_t len = extra; - - if(numstrs < 1) - I_Error("M_StringAlloc: invalid input\n"); - - len += strlen(str1); - - --numstrs; - - if(numstrs != 0) - { - va_start(args, str1); - - while(numstrs != 0) - { - const char *argstr = va_arg(args, const char *); - - len += strlen(argstr); - - --numstrs; - } - - va_end(args); - } - - ++len; - - *str = (char *)(M_Calloc(1, len)); - - return len; -} - -// -// M_SafeFilePath -// -// haleyjd 20110210 - original routine. -// This routine performs safe, portable concatenation of a base file path -// with another path component or file name. The returned string is Z_Malloc'd -// and should be freed when it has exhausted its usefulness. -// -char *M_SafeFilePath(const char *basepath, const char *newcomponent) -{ - int newstrlen = 0; - char *newstr = NULL; - - if (!strcmp(basepath, "")) - { - basepath = "."; - } - - // Always throw in a slash. M_NormalizeSlashes will remove it in the case - // that either basepath or newcomponent includes a redundant slash at the - // end or beginning respectively. - newstrlen = M_StringAlloc(&newstr, 3, 1, basepath, "/", newcomponent); - M_snprintf(newstr, newstrlen, "%s/%s", basepath, newcomponent); - M_NormalizeSlashes(newstr); - - return newstr; -} - -// -// M_CreateSaveDirs -// -// haleyjd 20110210: Vanilla Strife went tits-up if it didn't have the full set -// of save folders which were created externally by the installer. fraggle says -// that's no good for Choco purposes, and I agree, so this routine will create -// the full set of folders under the configured savegamedir. -// -void M_CreateSaveDirs(const char *savedir) -{ - int i; - - for(i = 0; i < 7; i++) - { - char *compositedir; - - // compose the full path by concatenating with savedir - compositedir = M_SafeFilePath(savedir, M_MakeStrifeSaveDir(i, "")); - - M_MakeDirectory(compositedir); - - Z_Free(compositedir); - } -} - -// -// M_MakeStrifeSaveDir -// -// haleyjd 20110211: Convenience routine -// -char *M_MakeStrifeSaveDir(int slotnum, const char *extra) -{ - static char tmpbuffer[32]; - - M_snprintf(tmpbuffer, sizeof(tmpbuffer), - "strfsav%d.ssg%s", slotnum, extra); - - return tmpbuffer; -} - -// -// M_GetFilePath -// -// haleyjd: STRIFE-FIXME: Temporary? -// Code borrowed from Eternity, and modified to return separator char -// -char M_GetFilePath(const char *fn, char *dest, size_t len) -{ - boolean found_slash = false; - char *p; - char sepchar = '\0'; - - memset(dest, 0, len); - - p = dest + len - 1; - - M_StringCopy(dest, fn, len); - - while(p >= dest) - { - if(*p == '/' || *p == '\\') - { - sepchar = *p; - found_slash = true; // mark that the path ended with a slash - *p = '\0'; - break; - } - *p = '\0'; - p--; - } - - // haleyjd: in the case that no slash was ever found, yet the - // path string is empty, we are dealing with a file local to the - // working directory. The proper path to return for such a string is - // not "", but ".", since the format strings add a slash now. When - // the string is empty but a slash WAS found, we really do want to - // return the empty string, since the path is relative to the root. - if(!found_slash && *dest == '\0') - *dest = '.'; - - // if a separator is not found, default to forward, because Windows - // supports that too. - if(sepchar == '\0') - sepchar = '/'; - - return sepchar; -} - -// EOF - - diff --git a/games/NXDoom/src/strife/m_saves.h b/games/NXDoom/src/strife/m_saves.h deleted file mode 100644 index ce278cba96d..00000000000 --- a/games/NXDoom/src/strife/m_saves.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2010 James Haley, Samuel Villareal -// -// 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. -// -// DESCRIPTION: -// -// [STRIFE] New Module -// -// Strife Hub Saving Code -// - -#ifndef M_SAVES_H__ -#define M_SAVES_H__ - -#define CHARACTER_NAME_LEN 32 - -extern char *savepath; -extern char *savepathtemp; -extern char *loadpath; -extern char character_name[CHARACTER_NAME_LEN]; - -// Strife Savegame Functions -void ClearTmp(void); -void ClearSlot(void); -void FromCurr(void); -void ToCurr(void); -void M_SaveMoveMapToHere(void); -void M_SaveMoveHereToMap(void); - -boolean M_SaveMisObj(const char *path); -void M_ReadMisObj(void); - -// Custom Utilities for Filepath Handling -void *M_Calloc(size_t n1, size_t n2); -int M_StringAlloc(char **str, int numstrs, size_t extra, const char *str1, ...); -char *M_SafeFilePath(const char *basepath, const char *newcomponent); -char M_GetFilePath(const char *fn, char *dest, size_t len); -char *M_MakeStrifeSaveDir(int slotnum, const char *extra); -void M_CreateSaveDirs(const char *savedir); - -#endif - -// EOF - - diff --git a/games/NXDoom/src/strife/p_ceilng.c b/games/NXDoom/src/strife/p_ceilng.c deleted file mode 100644 index 93c0c7f2e15..00000000000 --- a/games/NXDoom/src/strife/p_ceilng.c +++ /dev/null @@ -1,343 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Ceiling aninmation (lowering, crushing, raising) -// - - - -#include "z_zone.h" -#include "doomdef.h" -#include "p_local.h" - -#include "s_sound.h" - -// State. -#include "doomstat.h" -#include "r_state.h" - -// Data. -#include "sounds.h" - -// -// CEILINGS -// - - -ceiling_t* activeceilings[MAXCEILINGS]; - - -// -// T_MoveCeiling -// - -void T_MoveCeiling (ceiling_t* ceiling) -{ - result_e res; - - switch(ceiling->direction) - { - case 0: - // IN STASIS - break; - case 1: - // UP - res = T_MovePlane(ceiling->sector, - ceiling->speed, - ceiling->topheight, - false,1,ceiling->direction); - - if (!(leveltime&7)) - { - switch(ceiling->type) - { - case silentCrushAndRaise: - break; - default: - S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); - // ? - break; - } - } - - if (res == pastdest) - { - switch(ceiling->type) - { - case raiseToHighest: - P_RemoveActiveCeiling(ceiling); - break; - - case silentCrushAndRaise: - S_StartSound(&ceiling->sector->soundorg, sfx_pstop); - case fastCrushAndRaise: - case crushAndRaise: - ceiling->direction = -1; - break; - - default: - break; - } - - } - break; - - case -1: - // DOWN - res = T_MovePlane(ceiling->sector, - ceiling->speed, - ceiling->bottomheight, - ceiling->crush,1,ceiling->direction); - - if (!(leveltime&7)) - { - switch(ceiling->type) - { - case silentCrushAndRaise: break; - default: - S_StartSound(&ceiling->sector->soundorg, sfx_stnmov); - } - } - - if (res == pastdest) - { - switch(ceiling->type) - { - case silentCrushAndRaise: - S_StartSound(&ceiling->sector->soundorg, sfx_pstop); - case crushAndRaise: - ceiling->speed = CEILSPEED; - case fastCrushAndRaise: - ceiling->direction = 1; - break; - - case lowerAndCrush: - case lowerToFloor: - P_RemoveActiveCeiling(ceiling); - break; - - default: - break; - } - } - else // ( res != pastdest ) - { - if (res == crushed) - { - switch(ceiling->type) - { - case silentCrushAndRaise: - case crushAndRaise: - case lowerAndCrush: - ceiling->speed = CEILSPEED / 8; - break; - - default: - break; - } - } - } - break; - } -} - - -// -// EV_DoCeiling -// Move a ceiling up/down and all around! -// -// haleyjd 10/04/10: [STRIFE] Changes: -// * Fast crushers were made 2x as fast. -// * lowerAndCrush was apparently "fixed" to actually crush, and was also -// altered to lower all the way to the floor rather than remain 8 above. -// * silentCrushAndRaise and crushAndRaise no longer crush. -int -EV_DoCeiling -( line_t* line, - ceiling_e type ) -{ - int secnum; - int rtn; - sector_t* sec; - ceiling_t* ceiling; - - secnum = -1; - rtn = 0; - - // Reactivate in-stasis ceilings...for certain types. - switch(type) - { - case fastCrushAndRaise: - case silentCrushAndRaise: - case crushAndRaise: - P_ActivateInStasisCeiling(line); - default: - break; - } - - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - // new door thinker - rtn = 1; - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); - P_AddThinker (&ceiling->thinker); - sec->specialdata = ceiling; - ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; - ceiling->sector = sec; - ceiling->crush = false; - - switch(type) - { - case fastCrushAndRaise: - // [STRIFE]: Speed of fast crushers increased by 2x! - ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); - ceiling->direction = -1; - ceiling->speed = CEILSPEED * 4; // [STRIFE] Was CEILSPEED * 2 - break; - - case lowerAndCrush: - // [STRIFE] lowerAndCrush doesn't seem to have crushed in DOOM, - // but it was certainly made to do so in Strife! It is also - // changed to lower all the way to the floor. - ceiling->crush = 1; - ceiling->direction = -1; - ceiling->speed = CEILSPEED; - ceiling->bottomheight = sec->floorheight; - break; - - case silentCrushAndRaise: - case crushAndRaise: - // [STRIFE] haleyjd 20130209: Turns out these types do NOT crush - // in Strife... yeah, that makes a lot of sense. Thanks to Gez for - // having detected this difference. - //ceiling->crush = true; - ceiling->topheight = sec->ceilingheight; - - case lowerToFloor: - ceiling->bottomheight = sec->floorheight; - if (type != lowerToFloor) - ceiling->bottomheight += 8*FRACUNIT; - ceiling->direction = -1; - ceiling->speed = CEILSPEED; - break; - - case raiseToHighest: - ceiling->topheight = P_FindHighestCeilingSurrounding(sec); - ceiling->direction = 1; - ceiling->speed = CEILSPEED; - break; - } - - ceiling->tag = sec->tag; - ceiling->type = type; - P_AddActiveCeiling(ceiling); - } - return rtn; -} - - -// -// Add an active ceiling -// -void P_AddActiveCeiling(ceiling_t* c) -{ - int i; - - for (i = 0; i < MAXCEILINGS;i++) - { - if (activeceilings[i] == NULL) - { - activeceilings[i] = c; - return; - } - } -} - - - -// -// Remove a ceiling's thinker -// -void P_RemoveActiveCeiling(ceiling_t* c) -{ - int i; - - for (i = 0;i < MAXCEILINGS;i++) - { - if (activeceilings[i] == c) - { - activeceilings[i]->sector->specialdata = NULL; - P_RemoveThinker (&activeceilings[i]->thinker); - activeceilings[i] = NULL; - break; - } - } -} - - - -// -// Restart a ceiling that's in-stasis -// -void P_ActivateInStasisCeiling(line_t* line) -{ - int i; - - for (i = 0;i < MAXCEILINGS;i++) - { - if (activeceilings[i] - && (activeceilings[i]->tag == line->tag) - && (activeceilings[i]->direction == 0)) - { - activeceilings[i]->direction = activeceilings[i]->olddirection; - activeceilings[i]->thinker.function.acp1 - = (actionf_p1)T_MoveCeiling; - } - } -} - - - -// -// EV_CeilingCrushStop -// Stop a ceiling from crushing! -// -int EV_CeilingCrushStop(line_t *line) -{ - int i; - int rtn; - - rtn = 0; - for (i = 0;i < MAXCEILINGS;i++) - { - if (activeceilings[i] - && (activeceilings[i]->tag == line->tag) - && (activeceilings[i]->direction != 0)) - { - activeceilings[i]->olddirection = activeceilings[i]->direction; - activeceilings[i]->thinker.function.acv = (actionf_v)NULL; - activeceilings[i]->direction = 0; // in-stasis - rtn = 1; - } - } - - - return rtn; -} diff --git a/games/NXDoom/src/strife/p_dialog.c b/games/NXDoom/src/strife/p_dialog.c deleted file mode 100644 index e2988a481bb..00000000000 --- a/games/NXDoom/src/strife/p_dialog.c +++ /dev/null @@ -1,1413 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2010 James Haley, Samuel Villarreal -// -// 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. -// -// DESCRIPTION: -// -// [STRIFE] New Module -// -// Dialog Engine for Strife -// - -#include - -#include "z_zone.h" -#include "w_wad.h" -#include "deh_str.h" -#include "d_main.h" -#include "d_mode.h" -#include "d_player.h" -#include "doomstat.h" -#include "m_random.h" -#include "m_menu.h" -#include "m_misc.h" -#include "r_main.h" -#include "v_video.h" -#include "p_local.h" -#include "sounds.h" -#include "p_dialog.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_inter.h" - -// -// Defines and Macros -// - -// haleyjd: size of the original Strife mapdialog_t structure. -#define ORIG_MAPDIALOG_SIZE 0x5EC - -#define DIALOG_INT(field, ptr) \ - field = ((int)ptr[0] | \ - ((int)ptr[1] << 8) | \ - ((int)ptr[2] << 16) | \ - ((int)ptr[3] << 24)); \ - ptr += 4; - -#define DIALOG_STR(field, ptr, len) \ - memcpy(field, ptr, len); \ - ptr += len; - -// -// Globals -// - -// This can be toggled at runtime to determine if the full dialog messages -// are subtitled on screen or not. Defaults to off. -int dialogshowtext = false; - -// The global mission objective buffer. This gets written to and read from file, -// and is set by dialogs and line actions. -char mission_objective[OBJECTIVE_LEN]; - -// -// Static Globals -// - -// True if SCRIPT00 is loaded. -static boolean script0loaded; - -// Number of dialogs defined in the current level's script. -static int numleveldialogs; - -// The actual level dialogs. This didn't exist in Strife, but is new to account -// for structure alignment/packing concerns, given that Chocolate Doom is -// multiplatform. -static mapdialog_t *leveldialogs; - -// The actual script00 dialogs. As above. -static mapdialog_t *script0dialogs; - -// Number of dialogs defined in the SCRIPT00 lump. -static int numscript0dialogs; - -// The player engaged in dialog. This is always player 1, though, since Rogue -// never completed the ability to use dialog outside of single-player mode. -static player_t *dialogplayer; - -// The object to which the player is speaking. -static mobj_t *dialogtalker; - -// The talker's current angle -static angle_t dialogtalkerangle; - -// The currently active mapdialog object. -static mapdialog_t *currentdialog; - -// Text at the end of the choices -static char dialoglastmsgbuffer[48]; - -// Item to display to player when picked up or recieved -static char pickupstring[46]; - -// Health based on gameskill given by the front's medic -static const int healthamounts[] = { -100 , -75, -50, -50, -100 }; - -//============================================================================= -// -// Dialog State Sets -// -// These are used to animate certain actors in response to what happens in -// their dialog sequences. -// - -typedef struct dialogstateset_s -{ - mobjtype_t type; // the type of object - statenum_t greet; // greeting state, for start of dialog - statenum_t yes; // "yes" state, for an affirmative response - statenum_t no; // "no" state, when you don't have the right items -} dialogstateset_t; - -static dialogstateset_t dialogstatesets[] = -{ - { MT_PLAYER, S_NULL, S_NULL, S_NULL }, - { MT_SHOPKEEPER_W, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, - { MT_SHOPKEEPER_B, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, - { MT_SHOPKEEPER_A, S_MRGT_00, S_MRYS_00, S_MRNO_00 }, - { MT_SHOPKEEPER_M, S_MRGT_00, S_MRYS_00, S_MRNO_00 } -}; - -// Rogue stored this in a static global rather than making it a define... -static int numdialogstatesets = arrlen(dialogstatesets); - -// Current dialog talker state -static dialogstateset_t *dialogtalkerstates; - -//============================================================================= -// -// Random Messages -// -// Rogue hard-coded these so they wouldn't have to repeat them several times -// in the SCRIPT00 lump, apparently. -// - -#define MAXRNDMESSAGES 10 - -typedef struct rndmessage_s -{ - const char *type_name; - int nummessages; - const char *messages[MAXRNDMESSAGES]; -} rndmessage_t; - -static rndmessage_t rndMessages[] = -{ - // Peasants - { - "PEASANT", - 10, - { - "PLEASE DON'T HURT ME.", - - "IF YOU'RE LOOKING TO HURT ME, I'M \n" - "NOT REALLY WORTH THE EFFORT.", - - "I DON'T KNOW ANYTHING.", - - "GO AWAY OR I'LL CALL THE GUARDS!", - - "I WISH SOMETIMES THAT ALL THESE \n" - "REBELS WOULD JUST LEARN THEIR \n" - "PLACE AND STOP THIS NONSENSE.", - - "JUST LEAVE ME ALONE, OK?", - - "I'M NOT SURE, BUT SOMETIMES I THINK \n" - "THAT I KNOW SOME OF THE ACOLYTES.", - - "THE ORDER'S GOT EVERYTHING AROUND HERE PRETTY WELL LOCKED UP TIGHT.", - - "THERE'S NO WAY THAT THIS IS JUST A \n" - "SECURITY FORCE.", - - "I'VE HEARD THAT THE ORDER IS REALLY \n" - "NERVOUS ABOUT THE FRONT'S \n" - "ACTIONS AROUND HERE." - } - }, - // Rebel - { - "REBEL", - 10, - { - "THERE'S NO WAY THE ORDER WILL \n" - "STAND AGAINST US.", - - "WE'RE ALMOST READY TO STRIKE. \n" - "MACIL'S PLANS ARE FALLING IN PLACE.", - - "WE'RE ALL BEHIND YOU, DON'T WORRY.", - - "DON'T GET TOO CLOSE TO ANY OF THOSE BIG ROBOTS. THEY'LL MELT YOU DOWN \n" - "FOR SCRAP!", - - "THE DAY OF OUR GLORY WILL SOON \n" - "COME, AND THOSE WHO OPPOSE US WILL \n" - "BE CRUSHED!", - - "DON'T GET TOO COMFORTABLE. WE'VE \n" - "STILL GOT OUR WORK CUT OUT FOR US.", - - "MACIL SAYS THAT YOU'RE THE NEW \n" - "HOPE. BEAR THAT IN MIND.", - - "ONCE WE'VE TAKEN THESE CHARLATANS DOWN, WE'LL BE ABLE TO REBUILD THIS " - "WORLD AS IT SHOULD BE.", - - "REMEMBER THAT YOU AREN'T FIGHTING \n" - "JUST FOR YOURSELF, BUT FOR \n" - "EVERYONE HERE AND OUTSIDE.", - - "AS LONG AS ONE OF US STILL STANDS, \n" - "WE WILL WIN." - } - }, - // Acolyte - { - "AGUARD", - 10, - { - "MOVE ALONG, PEASANT.", - - "FOLLOW THE TRUE FAITH, ONLY THEN \n" - "WILL YOU BEGIN TO UNDERSTAND.", - - "ONLY THROUGH DEATH CAN ONE BE \n" - "TRULY REBORN.", - - "I'M NOT INTERESTED IN YOUR USELESS \n" - "DRIVEL.", - - "IF I HAD WANTED TO TALK TO YOU I \n" - "WOULD HAVE TOLD YOU SO.", - - "GO AND ANNOY SOMEONE ELSE!", - - "KEEP MOVING!", - - "IF THE ALARM GOES OFF, JUST STAY OUT OF OUR WAY!", - - "THE ORDER WILL CLEANSE THE WORLD \n" - "AND USHER IT INTO THE NEW ERA.", - - "PROBLEM? NO, I THOUGHT NOT.", - } - }, - // Beggar - { - "BEGGAR", - 10, - { - "ALMS FOR THE POOR?", - - "WHAT ARE YOU LOOKING AT, SURFACER?", - - "YOU WOULDN'T HAVE ANY EXTRA FOOD, WOULD YOU?", - - "YOU SURFACE PEOPLE WILL NEVER \n" - " " - " UNDERSTAND US.", - - "HA, THE GUARDS CAN'T FIND US. THOSE \n" - "IDIOTS DON'T EVEN KNOW WE EXIST.", - - "ONE DAY EVERYONE BUT THOSE WHO SERVE THE ORDER WILL BE FORCED TO " - " JOIN US.", - - "STARE NOW, BUT YOU KNOW THAT THIS WILL BE YOUR OWN FACE ONE DAY.", - - // Note: "NOTHING THING" is an authentic typo - "THERE'S NOTHING THING MORE \n" - "ANNOYING THAN A SURFACER WITH AN ATTITUDE!", - - "THE ORDER WILL MAKE SHORT WORK OF YOUR PATHETIC FRONT.", - - "WATCH YOURSELF SURFACER. WE KNOW OUR ENEMIES!" - } - }, - // Templar - { - "PGUARD", - 10, - { - "WE ARE THE HANDS OF FATE. TO EARN \n" - "OUR WRATH IS TO FIND OBLIVION!", - - "THE ORDER WILL CLEANSE THE WORLD \n" - "OF THE WEAK AND CORRUPT!", - - "OBEY THE WILL OF THE MASTERS!", - - "LONG LIFE TO THE BROTHERS OF THE \n" - "ORDER!", - - "FREE WILL IS AN ILLUSION THAT BINDS \n" - "THE WEAK MINDED.", - - "POWER IS THE PATH TO GLORY. TO \n" - "FOLLOW THE ORDER IS TO WALK THAT \n" - "PATH!", - - "TAKE YOUR PLACE AMONG THE \n" - "RIGHTEOUS, JOIN US!", - - "THE ORDER PROTECTS ITS OWN.", - - "ACOLYTES? THEY HAVE YET TO SEE THE FULL GLORY OF THE ORDER.", - - "IF THERE IS ANY HONOR INSIDE THAT \n" - "PATHETIC SHELL OF A BODY, \n" - "YOU'LL ENTER INTO THE ARMS OF THE \n" - "ORDER." - } - } -}; - -// And again, this could have been a define, but was a variable. -static int numrndmessages = arrlen(rndMessages); - -//============================================================================= -// -// Dialog Menu Structure -// -// The Strife dialog system is actually just a serious abuse of the DOOM menu -// engine. Hence why it doesn't work in multiplayer games or during demo -// recording. -// - -#define NUMDIALOGMENUITEMS 6 - -static void P_DialogDrawer(void); - -static menuitem_t dialogmenuitems[] = -{ - { 1, "", P_DialogDoChoice, '1' }, // These items are loaded dynamically - { 1, "", P_DialogDoChoice, '2' }, - { 1, "", P_DialogDoChoice, '3' }, - { 1, "", P_DialogDoChoice, '4' }, - { 1, "", P_DialogDoChoice, '5' }, - { 1, "", P_DialogDoChoice, '6' } // Item 6 is always the dismissal item -}; - -static menu_t dialogmenu = -{ - NUMDIALOGMENUITEMS, - NULL, - dialogmenuitems, - P_DialogDrawer, - 42, - 75, - 0 -}; - -// Lump number of the dialog background picture, if any. -static int dialogbgpiclumpnum; - -// Name of current speaking character. -static const char *dialogname; - -// Current dialog text. -static const char *dialogtext; - -//============================================================================= -// -// Routines -// - -// -// P_ParseDialogLump -// -// haleyjd 09/02/10: This is an original function added to parse out the -// dialogs from the dialog lump rather than reading them raw from the lump -// pointer. This avoids problems with structure packing. -// -static void P_ParseDialogLump(byte *lump, mapdialog_t **dialogs, - int numdialogs, int tag) -{ - int i; - byte *rover = lump; - - *dialogs = Z_Malloc(numdialogs * sizeof(mapdialog_t), tag, NULL); - - for(i = 0; i < numdialogs; i++) - { - int j; - mapdialog_t *curdialog = &((*dialogs)[i]); - - DIALOG_INT(curdialog->speakerid, rover); - DIALOG_INT(curdialog->dropitem, rover); - DIALOG_INT(curdialog->checkitem[0], rover); - DIALOG_INT(curdialog->checkitem[1], rover); - DIALOG_INT(curdialog->checkitem[2], rover); - DIALOG_INT(curdialog->jumptoconv, rover); - DIALOG_STR(curdialog->name, rover, MDLG_NAMELEN); - DIALOG_STR(curdialog->voice, rover, MDLG_LUMPLEN); - DIALOG_STR(curdialog->backpic, rover, MDLG_LUMPLEN); - DIALOG_STR(curdialog->text, rover, MDLG_TEXTLEN); - - // copy choices - for(j = 0; j < 5; j++) - { - mapdlgchoice_t *curchoice = &(curdialog->choices[j]); - DIALOG_INT(curchoice->giveitem, rover); - DIALOG_INT(curchoice->needitems[0], rover); - DIALOG_INT(curchoice->needitems[1], rover); - DIALOG_INT(curchoice->needitems[2], rover); - DIALOG_INT(curchoice->needamounts[0], rover); - DIALOG_INT(curchoice->needamounts[1], rover); - DIALOG_INT(curchoice->needamounts[2], rover); - DIALOG_STR(curchoice->text, rover, MDLG_CHOICELEN); - DIALOG_STR(curchoice->textok, rover, MDLG_MSGLEN); - DIALOG_INT(curchoice->next, rover); - DIALOG_INT(curchoice->objective, rover); - DIALOG_STR(curchoice->textno, rover, MDLG_MSGLEN); - } - } -} - -// -// P_DialogLoad -// -// [STRIFE] New function -// haleyjd 09/02/10: Loads the dialog script for the current map. Also loads -// SCRIPT00 if it has not yet been loaded. -// -void P_DialogLoad(void) -{ - char lumpname[9]; - int lumpnum; - - // load the SCRIPTxy lump corresponding to MAPxy, if it exists. - DEH_snprintf(lumpname, sizeof(lumpname), "script%02d", gamemap); - if((lumpnum = W_CheckNumForName(lumpname)) == -1) - numleveldialogs = 0; - else - { - byte *leveldialogptr = W_CacheLumpNum(lumpnum, PU_STATIC); - numleveldialogs = W_LumpLength(lumpnum) / ORIG_MAPDIALOG_SIZE; - P_ParseDialogLump(leveldialogptr, &leveldialogs, numleveldialogs, - PU_LEVEL); - Z_Free(leveldialogptr); // haleyjd: free the original lump - } - - // also load SCRIPT00 if it has not been loaded yet - if(!script0loaded) - { - byte *script0ptr; - - script0loaded = true; - // BUG: Rogue should have used W_GetNumForName here... - lumpnum = W_CheckNumForName(DEH_String("script00")); - script0ptr = W_CacheLumpNum(lumpnum, PU_STATIC); - numscript0dialogs = W_LumpLength(lumpnum) / ORIG_MAPDIALOG_SIZE; - P_ParseDialogLump(script0ptr, &script0dialogs, numscript0dialogs, - PU_STATIC); - Z_Free(script0ptr); // haleyjd: free the original lump - } -} - -// -// P_PlayerHasItem -// -// [STRIFE] New function -// haleyjd 09/02/10: Checks for inventory items, quest flags, etc. for dialogs. -// Returns the amount possessed, or 0 if none. -// -int P_PlayerHasItem(player_t *player, mobjtype_t type) -{ - int i; - - if(type > 0) - { - // check keys - if(type >= MT_KEY_BASE && type < MT_INV_SHADOWARMOR) - return (player->cards[type - MT_KEY_BASE]); - - // check sigil pieces - if(type >= MT_SIGIL_A && type <= MT_SIGIL_E) - return (type - MT_SIGIL_A <= player->sigiltype); - - // check quest tokens - if(type >= MT_TOKEN_QUEST1 && type <= MT_TOKEN_QUEST31) - return (player->questflags & (1 << (type - MT_TOKEN_QUEST1))); - - // check inventory - for(i = 0; i < 32; i++) - { - if(type == player->inventory[i].type) - return player->inventory[i].amount; - } - } - return 0; -} - -// -// P_DialogFind -// -// [STRIFE] New function -// haleyjd 09/03/10: Looks for a dialog definition matching the given -// Script ID # for an mobj. -// -mapdialog_t *P_DialogFind(mobjtype_t type, int jumptoconv) -{ - int i; - - // check the map-specific dialogs first - for(i = 0; i < numleveldialogs; i++) - { - if(type == leveldialogs[i].speakerid) - { - if(jumptoconv <= 1) - return &leveldialogs[i]; - else - --jumptoconv; - } - } - - // check SCRIPT00 dialogs next - for(i = 0; i < numscript0dialogs; i++) - { - if(type == script0dialogs[i].speakerid) - return &script0dialogs[i]; - } - - // the default dialog is script 0 in the SCRIPT00 lump. - return &script0dialogs[0]; -} - -// -// P_DialogGetStates -// -// [STRIFE] New function -// haleyjd 09/03/10: Find the set of special dialog states (greetings, yes, no) -// for a particular thing type. -// -static dialogstateset_t *P_DialogGetStates(mobjtype_t type) -{ - int i; - - // look for a match by type - for(i = 0; i < numdialogstatesets; i++) - { - if(type == dialogstatesets[i].type) - return &dialogstatesets[i]; - } - - // return the default 0 record if no match. - return &dialogstatesets[0]; -} - -// -// P_DialogGetMsg -// -// [STRIFE] New function -// haleyjd 09/03/10: Redirects dialog messages when the script indicates that -// the actor should use a random message stored in the executable instead. -// -static const char *P_DialogGetMsg(const char *message) -{ - // if the message starts with "RANDOM"... - if(!strncasecmp(message, DEH_String("RANDOM"), 6)) - { - int i; - const char *nameloc = message + 7; - - // look for a match in rndMessages for the string starting - // 7 chars after "RANDOM_" - for(i = 0; i < numrndmessages; i++) - { - if(!strncasecmp(nameloc, rndMessages[i].type_name, 4)) - { - // found a match, so return a random message - int rnd = M_Random(); - int nummessages = rndMessages[i].nummessages; - return DEH_String(rndMessages[i].messages[rnd % nummessages]); - } - } - } - - // otherwise, just return the message passed in. - return message; -} - -// -// P_GiveInventoryItem -// -// [STRIFE] New function -// haleyjd 09/03/10: Give an inventory item to the player, if possible. -// villsa 09/09/10: Fleshed out routine -// -boolean P_GiveInventoryItem(player_t *player, int sprnum, mobjtype_t type) -{ - int curinv = 0; - int i; - boolean ok = false; - mobjtype_t item = 0; - inventory_t* invtail; - - // repaint the status bar due to inventory changing - player->st_update = true; - - while(1) - { - // inventory is full - if(curinv > player->numinventory) - return true; - - item = player->inventory[curinv].type; - if(type < item) - { - if(curinv != MAXINVENTORYSLOTS) - { - // villsa - sort inventory item if needed - invtail = &player->inventory[player->numinventory - 1]; - if(player->numinventory >= (curinv + 1)) - { - for(i = player->numinventory; i >= (curinv + 1); --i) - { - invtail[1].sprite = invtail[0].sprite; - invtail[1].type = invtail[0].type; - invtail[1].amount = invtail[0].amount; - - invtail--; - } - } - - // villsa - add inventory item - player->inventory[curinv].amount = 1; - player->inventory[curinv].sprite = sprnum; - player->inventory[curinv].type = type; - - // sort cursor if needed - if(player->numinventory) - { - if(curinv <= player->inventorycursor) - player->inventorycursor++; - } - - player->numinventory++; - - return true; - } - - return false; - } - - if(type == item) - break; - - curinv++; - } - - // check amount of inventory item by using the mass from mobjinfo - if(player->inventory[curinv].amount < mobjinfo[item].mass) - { - player->inventory[curinv].amount++; - ok = true; - } - else - ok = false; - - return ok; -} - -// -// P_GiveItemToPlayer -// -// [STRIFE] New function -// haleyjd 09/03/10: Sorts out how to give something to the player. -// Not strictly just for inventory items. -// villsa 09/09/10: Fleshed out function -// -boolean P_GiveItemToPlayer(player_t *player, int sprnum, mobjtype_t type) -{ - int i = 0; - line_t junk; - int sound = sfx_itemup; // haleyjd 09/21/10: different sounds for items - - // set quest if mf_givequest flag is set - if(mobjinfo[type].flags & MF_GIVEQUEST) - player->questflags |= 1 << (mobjinfo[type].speed - 1); - - // check for keys - if(type >= MT_KEY_BASE && type <= MT_NEWKEY5) - { - P_GiveCard(player, type - MT_KEY_BASE); - return true; - } - - // check for quest tokens - if(type >= MT_TOKEN_QUEST1 && type <= MT_TOKEN_QUEST31) - { - if(mobjinfo[type].name) - { - M_StringCopy(pickupstring, DEH_String(mobjinfo[type].name), 39); - player->message = pickupstring; - } - player->questflags |= 1 << (type - MT_TOKEN_QUEST1); - - if(player == &players[consoleplayer]) - S_StartSound(NULL, sound); - return true; - } - - // haleyjd 09/22/10: Refactored to give sprites higher priority than - // mobjtypes and to implement missing logic. - switch(sprnum) - { - case SPR_HELT: // This is given only by the "DONNYTRUMP" cheat (aka Midas) - P_GiveInventoryItem(player, SPR_HELT, MT_TOKEN_TOUGHNESS); - P_GiveInventoryItem(player, SPR_GUNT, MT_TOKEN_ACCURACY); - - // [STRIFE] Bizarre... - for(i = 0; i < 5 * player->accuracy + 300; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - case SPR_ARM1: // Armor 1 - if(!P_GiveArmor(player, -2)) - P_GiveInventoryItem(player, sprnum, type); - break; - - case SPR_ARM2: // Armor 2 - if(!P_GiveArmor(player, -1)) - P_GiveInventoryItem(player, sprnum, type); - break; - - case SPR_COIN: // 1 Gold - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - case SPR_CRED: // 10 Gold - for(i = 0; i < 10; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - case SPR_SACK: // 25 gold - for(i = 0; i < 25; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - case SPR_CHST: // 50 gold - for(i = 0; i < 50; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; // haleyjd 20141215: missing break, caused Rowan to not take ring from you. - - case SPR_BBOX: // Box of Bullets - if(!P_GiveAmmo(player, am_bullets, 5)) - return false; - break; - - case SPR_BLIT: // Bullet Clip - if(!P_GiveAmmo(player, am_bullets, 1)) - return false; - break; - - case SPR_PMAP: // Map powerup - if(!P_GivePower(player, pw_allmap)) - return false; - sound = sfx_yeah; // bluh-doop! - break; - - case SPR_COMM: // Communicator - if(!P_GivePower(player, pw_communicator)) - return false; - sound = sfx_yeah; // bluh-doop! - break; - - case SPR_MSSL: // Mini-missile - if(!P_GiveAmmo(player, am_missiles, 1)) - return false; - break; - - case SPR_ROKT: // Crate of missiles - if(!P_GiveAmmo(player, am_missiles, 5)) - return false; - break; - - case SPR_BRY1: // Battery cell - if(!P_GiveAmmo(player, am_cell, 1)) - return false; - break; - - case SPR_CPAC: // Cell pack - if(!P_GiveAmmo(player, am_cell, 5)) - return false; - break; - - case SPR_PQRL: // Poison bolts - if(!P_GiveAmmo(player, am_poisonbolts, 5)) - return false; - break; - - case SPR_XQRL: // Electric bolts - if(!P_GiveAmmo(player, am_elecbolts, 5)) - return false; - break; - - case SPR_GRN1: // HE Grenades - if(!P_GiveAmmo(player, am_hegrenades, 1)) - return false; - break; - - case SPR_GRN2: // WP Grenades - if(!P_GiveAmmo(player, am_wpgrenades, 1)) - return false; - break; - - case SPR_BKPK: // Backpack (aka Ammo Satchel) - if(!player->backpack) - { - for(i = 0; i < NUMAMMO; i++) - player->maxammo[i] *= 2; - - player->backpack = true; - } - for(i = 0; i < NUMAMMO; i++) - P_GiveAmmo(player, i, 1); - break; - - case SPR_RIFL: // Assault Rifle - if(player->weaponowned[wp_rifle]) - return false; - - if(!P_GiveWeapon(player, wp_rifle, false)) - return false; - - sound = sfx_wpnup; // SHK-CHK! - break; - - case SPR_FLAM: // Flamethrower - if(player->weaponowned[wp_flame]) - return false; - - if(!P_GiveWeapon(player, wp_flame, false)) - return false; - - sound = sfx_wpnup; // SHK-CHK! - break; - - case SPR_MMSL: // Mini-missile Launcher - if(player->weaponowned[wp_missile]) - return false; - - if(!P_GiveWeapon(player, wp_missile, false)) - return false; - - sound = sfx_wpnup; // SHK-CHK! - break; - - case SPR_TRPD: // Mauler - if(player->weaponowned[wp_mauler]) - return false; - - if(!P_GiveWeapon(player, wp_mauler, false)) - return false; - - sound = sfx_wpnup; // SHK-CHK! - break; - - case SPR_CBOW: // Here's a crossbow. Just aim straight, and *SPLAT!* - if(player->weaponowned[wp_elecbow]) - return false; - - if(!P_GiveWeapon(player, wp_elecbow, false)) - return false; - - sound = sfx_wpnup; // SHK-CHK! - break; - - case SPR_TOKN: // Miscellaneous items - These are determined by thingtype. - switch(type) - { - case MT_KEY_HAND: // Severed hand - P_GiveCard(player, key_SeveredHand); - break; - - case MT_MONY_300: // 300 Gold (this is the only way to get it, in fact) - for(i = 0; i < 300; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - case MT_TOKEN_AMMO: // Ammo token - you get this from the Weapons Trainer - if(player->ammo[am_bullets] >= 50) - return false; - - player->ammo[am_bullets] = 50; - break; - - case MT_TOKEN_HEALTH: // Health token - from the Front's doctor - if(!P_GiveBody(player, healthamounts[gameskill])) - return false; - break; - - case MT_TOKEN_ALARM: // Alarm token - particularly from the Oracle. - P_NoiseAlert(player->mo, player->mo); - A_AlertSpectreC(dialogtalker); // BUG: assumes in a dialog o_O - break; - - case MT_TOKEN_DOOR1: // Door special 1 - junk.tag = 222; - EV_DoDoor(&junk, vld_open); - break; - - case MT_TOKEN_PRISON_PASS: // Door special 1 - Prison pass - junk.tag = 223; - EV_DoDoor(&junk, vld_open); - if(gamemap == 2) // If on Tarnhill, give Prison pass object - P_GiveInventoryItem(player, sprnum, type); - break; - - case MT_TOKEN_SHOPCLOSE: // Door special 3 - "Shop close" - unused? - junk.tag = 222; - EV_DoDoor(&junk, vld_close); - break; - - case MT_TOKEN_DOOR3: // Door special 4 (or 3? :P ) - junk.tag = 224; - EV_DoDoor(&junk, vld_close); - break; - - case MT_TOKEN_STAMINA: // Stamina upgrade - if(player->stamina >= 100) - return false; - - player->stamina += 10; - P_GiveBody(player, 200); // full healing - break; - - case MT_TOKEN_NEW_ACCURACY: // Accuracy upgrade - if(player->accuracy >= 100) - return false; - - player->accuracy += 10; - break; - - case MT_SLIDESHOW: // Slideshow (start a finale) - gameaction = ga_victory; - if(gamemap == 10) - P_GiveItemToPlayer(player, SPR_TOKN, MT_TOKEN_QUEST17); - break; - - default: // The default is to just give it as an inventory item. - P_GiveInventoryItem(player, sprnum, type); - break; - } - break; - - default: // The ultimate default: Give it as an inventory item. - if(!P_GiveInventoryItem(player, sprnum, type)) - return false; - break; - } - - // Play sound. - if(player == &players[consoleplayer]) - S_StartSound(NULL, sound); - - return true; -} - -// -// P_TakeDialogItem -// -// [STRIFE] New function -// haleyjd 09/03/10: Removes needed items from the player's inventory. -// -static void P_TakeDialogItem(player_t *player, int type, int amount) -{ - int i; - - if(amount <= 0) - return; - - for(i = 0; i < player->numinventory; i++) - { - // find a matching item - if(type != player->inventory[i].type) - continue; - - // if there is none left... - if((player->inventory[i].amount -= amount) < 1) - { - // ...shift everything above it down - int j; - - // BUG: They should have stopped at j < numinventory. This - // seems to implicitly assume that numinventory is always at - // least one less than the max # of slots, otherwise it - // pulls in data from the following player_t fields: - // st_update, numinventory, inventorycursor, accuracy, stamina - for(j = i + 1; j <= player->numinventory; j++) - { - inventory_t *item1 = &(player->inventory[j - 1]); - inventory_t *item2 = &(player->inventory[j]); - - *item1 = *item2; - } - - // blank the topmost slot - // BUG: This will overwrite the aforementioned fields if - // numinventory is equal to the number of slots! - // STRIFE-TODO: Overflow emulation? - player->inventory[player->numinventory].type = NUMMOBJTYPES; - player->inventory[player->numinventory].sprite = -1; - player->numinventory--; - - // update cursor position - if(player->inventorycursor >= player->numinventory) - { - if(player->inventorycursor) - player->inventorycursor--; - } - } // end if - - return; // done! - - } // end for -} - -// -// P_DialogDrawer -// -// This function is set as the drawer callback for the dialog menu. -// -static void P_DialogDrawer(void) -{ - angle_t angle; - int y; - int i; - int height; - int finaly; - char choicetext[64]; - char choicetext2[64]; - - // Run down bonuscount faster than usual so that flashes from being given - // items are less obvious. - if(dialogplayer->bonuscount) - { - dialogplayer->bonuscount -= 3; - if(dialogplayer->bonuscount < 0) - dialogplayer->bonuscount = 0; - } - - angle = R_PointToAngle2(dialogplayer->mo->x, - dialogplayer->mo->y, - dialogtalker->x, - dialogtalker->y); - angle -= dialogplayer->mo->angle; - - // Dismiss the dialog if the player is out of alignment, or the thing he was - // talking to is now engaged in battle. - if ((angle > ANG45 && angle < (ANG270+ANG45)) - || (dialogtalker->flags & MF_NODIALOG) != 0) - { - P_DialogDoChoice(dialogmenu.numitems - 1); - } - - dialogtalker->reactiontime = 2; - - // draw background - if(dialogbgpiclumpnum != -1) - { - patch_t *patch = W_CacheLumpNum(dialogbgpiclumpnum, PU_CACHE); - V_DrawPatchDirect(0, 0, patch); - } - - // if there's a valid background pic, delay drawing the rest of the menu - // for a while; otherwise, it will appear immediately - if(dialogbgpiclumpnum == -1 || menupausetime <= gametic) - { - if(menuindialog) - { - // time to pause the game? - if(menupausetime + 3 < gametic) - menupause = true; - } - - // draw character name - M_WriteText(12, 18, dialogname); - y = 28; - - // show text (optional for dialogs with voices) - if(dialogshowtext || currentdialog->voice[0] == '\0') - y = M_WriteText(20, 28, dialogtext); - - height = 20 * dialogmenu.numitems; - - finaly = 175 - height; // preferred height - if(y > finaly) - finaly = 199 - height; // height it will bump down to if necessary. - - // draw divider - M_WriteText(42, finaly - 6, DEH_String("______________________________")); - - dialogmenu.y = finaly + 6; - y = 0; - - // draw the menu items - for(i = 0; i < dialogmenu.numitems - 1; i++) - { - DEH_snprintf(choicetext, sizeof(choicetext), - "%d) %s", i + 1, currentdialog->choices[i].text); - - // alternate text for items that need money - if(currentdialog->choices[i].needamounts[0] > 0) - { - // haleyjd 20120401: necessary to avoid undefined behavior: - M_StringCopy(choicetext2, choicetext, sizeof(choicetext2)); - DEH_snprintf(choicetext, sizeof(choicetext), - "%s for %d", choicetext2, - currentdialog->choices[i].needamounts[0]); - } - - M_WriteText(dialogmenu.x, dialogmenu.y + 3 + y, choicetext); - y += 19; - } - - // draw the final item for dismissing the dialog - M_WriteText(dialogmenu.x, 19 * i + dialogmenu.y + 3, dialoglastmsgbuffer); - } -} - -// -// P_DialogDoChoice -// -// [STRIFE] New function -// haleyjd 09/05/10: Handles making a choice in a dialog. Installed as the -// callback for all items in the dialogmenu structure. -// -void P_DialogDoChoice(int choice) -{ - int i = 0, nextdialog = 0; - boolean candochoice = true; - const char *message = NULL; - mapdlgchoice_t *currentchoice; - - if(choice == -1) - choice = dialogmenu.numitems - 1; - - currentchoice = &(currentdialog->choices[choice]); - - I_StartVoice(NULL); // STRIFE-TODO: verify (should stop previous voice I believe) - - // villsa 09/08/10: converted into for loop - for(i = 0; i < MDLG_MAXITEMS; i++) - { - if(P_PlayerHasItem(dialogplayer, currentchoice->needitems[i]) < - currentchoice->needamounts[i]) - { - candochoice = false; // nope, missing something - } - } - - if(choice != dialogmenu.numitems - 1 && candochoice) - { - int item; - - message = currentchoice->textok; - if(dialogtalkerstates->yes) - P_SetMobjState(dialogtalker, dialogtalkerstates->yes); - - item = currentchoice->giveitem; - if(item < 0 || - P_GiveItemToPlayer(dialogplayer, - states[mobjinfo[item].spawnstate].sprite, - item)) - { - // if successful, take needed items - int count = 0; - // villsa 09/08/10: converted into for loop - for(count = 0; count < MDLG_MAXITEMS; count++) - { - P_TakeDialogItem(dialogplayer, - currentchoice->needitems[count], - currentchoice->needamounts[count]); - } - } - else - message = DEH_String("You seem to have enough!"); - - // store next dialog into the talking actor - nextdialog = currentchoice->next; - if(nextdialog != 0) - dialogtalker->miscdata = (byte)(abs(nextdialog)); - } - else - { - // not successful - message = currentchoice->textno; - if(dialogtalkerstates->no) - P_SetMobjState(dialogtalker, dialogtalkerstates->no); - } - - if(choice != dialogmenu.numitems - 1) - { - int objective; - char *objlump; - - if((objective = currentchoice->objective)) - { - DEH_snprintf(mission_objective, OBJECTIVE_LEN, "log%i", objective); - objlump = W_CacheLumpName(mission_objective, PU_CACHE); - M_StringCopy(mission_objective, objlump, OBJECTIVE_LEN); - } - // haleyjd 20130301: v1.31 hack: if first char of message is a period, - // clear the player's message. Is this actually used anywhere? - if(gameversion == exe_strife_1_31 && message[0] == '.') - message = NULL; - dialogplayer->message = message; - } - - dialogtalker->angle = dialogtalkerangle; - dialogplayer->st_update = true; - M_ClearMenus(0); - - if(nextdialog >= 0 || gameaction == ga_victory) // Macil hack - menuindialog = false; - else - P_DialogStart(dialogplayer); -} - -// -// P_DialogStartP1 -// -// [STRIFE] New function -// haleyjd 09/13/10: This is a hack used by the finale system. -// -void P_DialogStartP1(void) -{ - P_DialogStart(&players[0]); -} - -// -// P_DialogStart -// -// villsa [STRIFE] New function -// -void P_DialogStart(player_t *player) -{ - int i = 0; - int pic; - int rnd = 0; - const char *byetext; - int jumptoconv; - - if(menuactive || netgame) - return; - - // are we facing towards our NPC? - P_AimLineAttack(player->mo, player->mo->angle, (128*FRACUNIT)); - if(!linetarget) - { - P_AimLineAttack(player->mo, player->mo->angle + (ANG90/16), (128*FRACUNIT)); - if(!linetarget) - P_AimLineAttack(player->mo, player->mo->angle - (ANG90/16), (128*FRACUNIT)); - } - - if(!linetarget) - return; - - // already in combat, can't talk to it - if(linetarget->flags & MF_NODIALOG) - return; - - // set pointer to the character talking - dialogtalker = linetarget; - - // play a sound - if(player == &players[consoleplayer]) - S_StartSound(0, sfx_radio); - - linetarget->target = player->mo; // target the player - dialogtalker->reactiontime = 2; // set reactiontime - dialogtalkerangle = dialogtalker->angle; // remember original angle - - // face talker towards player - A_FaceTarget(dialogtalker); - - // face towards NPC's direction - player->mo->angle = R_PointToAngle2(player->mo->x, - player->mo->y, - dialogtalker->x, - dialogtalker->y); - // set pointer to player talking - dialogplayer = player; - - // haleyjd 09/08/10: get any stored dialog state from this object - jumptoconv = linetarget->miscdata; - - // check item requirements - while(1) - { - int i = 0; - currentdialog = P_DialogFind(linetarget->type, jumptoconv); - - // dialog's jumptoconv equal to 0? There's nothing to jump to. - if(currentdialog->jumptoconv == 0) - break; - - // villsa 09/08/10: converted into for loop - for(i = 0; i < MDLG_MAXITEMS; i++) - { - // if the item is non-zero, the player must have at least one in his - // or her inventory - if(currentdialog->checkitem[i] != 0 && - P_PlayerHasItem(dialogplayer, currentdialog->checkitem[i]) < 1) - break; - } - - if(i < MDLG_MAXITEMS) // didn't find them all? this is our dialog! - break; - - jumptoconv = currentdialog->jumptoconv; - } - - M_DialogDimMsg(20, 28, currentdialog->text, false); - dialogtext = P_DialogGetMsg(currentdialog->text); - - // get states - dialogtalkerstates = P_DialogGetStates(linetarget->type); - - // have talker greet the player - if(dialogtalkerstates->greet) - P_SetMobjState(dialogtalker, dialogtalkerstates->greet); - - // get talker's name - if(currentdialog->name[0]) - dialogname = currentdialog->name; - else - { - // use a fallback: - if(mobjinfo[linetarget->type].name) - dialogname = DEH_String(mobjinfo[linetarget->type].name); // mobjtype name - else - dialogname = DEH_String("Person"); // default name - like Joe in Doom 3 :P - } - - // setup number of choices to choose from - for(i = 0; i < MDLG_MAXCHOICES; i++) - { - if(!currentdialog->choices[i].giveitem) - break; - } - - // set number of choices to menu - dialogmenu.numitems = i + 1; - - rnd = M_Random() % 3; - - // setup dialog menu - M_StartControlPanel(); - menupause = false; - menuindialog = true; - menupausetime = gametic + 17; - currentMenu = &dialogmenu; - - if(i >= dialogmenu.lastOn) - itemOn = dialogmenu.lastOn; - else - itemOn = 0; - - // get backdrop - pic = W_CheckNumForName(currentdialog->backpic); - dialogbgpiclumpnum = pic; - if(pic != -1) - V_DrawPatchDirect(0, 0, W_CacheLumpNum(pic, PU_CACHE)); - - // get voice - I_StartVoice(currentdialog->voice); - - // get bye text - switch(rnd) - { - case 2: - byetext = DEH_String("BYE!"); - break; - case 1: - byetext = DEH_String("Thanks, Bye!"); - break; - default: - case 0: - byetext = DEH_String("See you later!"); - break; - } - - DEH_snprintf(dialoglastmsgbuffer, sizeof(dialoglastmsgbuffer), - "%d) %s", i + 1, byetext); -} - -// EOF - - diff --git a/games/NXDoom/src/strife/p_dialog.h b/games/NXDoom/src/strife/p_dialog.h deleted file mode 100644 index 08bef81ea75..00000000000 --- a/games/NXDoom/src/strife/p_dialog.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1996 Rogue Entertainment / Velocity, Inc. -// Copyright(C) 2010 James Haley, Samuel Villareal -// -// 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. -// -// DESCRIPTION: -// -// [STRIFE] New Module -// -// Dialog Engine for Strife -// - -#ifndef P_DIALOG_H__ -#define P_DIALOG_H__ - -#define OBJECTIVE_LEN 300 - -#define MAXINVENTORYSLOTS 30 - -#define MDLG_CHOICELEN 32 -#define MDLG_MSGLEN 80 -#define MDLG_NAMELEN 16 -#define MDLG_LUMPLEN 8 -#define MDLG_TEXTLEN 320 -#define MDLG_MAXCHOICES 5 -#define MDLG_MAXITEMS 3 - -extern char mission_objective[OBJECTIVE_LEN]; - -extern int dialogshowtext; - -// villsa - convenient macro for giving objective logs to player -#define GiveObjective(x, minlumpnum) \ -do { \ - int obj_ln = W_CheckNumForName(DEH_String(x)); \ - if(obj_ln > minlumpnum) \ - M_StringCopy(mission_objective, W_CacheLumpNum(obj_ln, PU_CACHE), \ - OBJECTIVE_LEN);\ -} while(0) - -// haleyjd - voice and objective in one -#define GiveVoiceObjective(voice, log, minlumpnum) \ -do { \ - int obj_ln = W_CheckNumForName(DEH_String(log)); \ - I_StartVoice(DEH_String(voice)); \ - if(obj_ln > minlumpnum) \ - M_StringCopy(mission_objective, W_CacheLumpNum(obj_ln, PU_CACHE), \ - OBJECTIVE_LEN);\ -} while(0) - -typedef struct mapdlgchoice_s -{ - int giveitem; // item given when successful - int needitems[MDLG_MAXITEMS]; // item needed for success - int needamounts[MDLG_MAXITEMS]; // amount of items needed - char text[MDLG_CHOICELEN]; // normal text - char textok[MDLG_MSGLEN]; // message given on success - int next; // next dialog? - int objective; // ??? - char textno[MDLG_MSGLEN]; // message given on failure -} mapdlgchoice_t; - -typedef struct mapdialog_s -{ - int speakerid; // script ID# for mobjtype that will use this dialog - int dropitem; // item to drop if that thingtype is killed - int checkitem[MDLG_MAXITEMS]; // item(s) needed to see this dialog - int jumptoconv; // conversation to jump to when... ? - char name[MDLG_NAMELEN]; // name of speaker - char voice[MDLG_LUMPLEN]; // voice file to play - char backpic[MDLG_LUMPLEN]; // backdrop pic for character, if any - char text[MDLG_TEXTLEN]; // main message text - - // options that this dialog gives the player - mapdlgchoice_t choices[MDLG_MAXCHOICES]; -} mapdialog_t; - -void P_DialogLoad(void); -void P_DialogStart(player_t *player); -void P_DialogDoChoice(int choice); -boolean P_GiveItemToPlayer(player_t *player, int sprnum, mobjtype_t type); -boolean P_GiveInventoryItem(player_t *player, int sprnum, mobjtype_t type); -boolean P_UseInventoryItem(player_t* player, int item); -void P_DialogStartP1(void); -mapdialog_t* P_DialogFind(mobjtype_t type, int jumptoconv); -int P_PlayerHasItem(player_t *player, mobjtype_t type); - -#endif - -// EOF - - diff --git a/games/NXDoom/src/strife/p_doors.c b/games/NXDoom/src/strife/p_doors.c deleted file mode 100644 index 30f6e311809..00000000000 --- a/games/NXDoom/src/strife/p_doors.c +++ /dev/null @@ -1,1370 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: Door animation code (opening/closing) -// - - - -#include "z_zone.h" -#include "doomdef.h" -#include "deh_main.h" -#include "p_local.h" - -#include "s_sound.h" - - -// State. -#include "doomstat.h" -#include "r_state.h" - -// Data. -#include "dstrings.h" -#include "sounds.h" - -// [STRIFE] -#include "p_dialog.h" -#include "i_system.h" - - -// -// VERTICAL DOORS -// - -// -// T_VerticalDoor -// -void T_VerticalDoor(vldoor_t* door) -{ - result_e res1; - result_e res2; - - switch(door->direction) - { - case 0: - // WAITING - if (!--door->topcountdown) - { - switch(door->type) - { - case vld_blazeRaise: - door->direction = -1; // time to go back down - S_StartSound(&door->sector->soundorg, sfx_bdcls); - break; - - case vld_normal: - door->direction = -1; // time to go back down - // villsa [STRIFE] closesound added - S_StartSound(&door->sector->soundorg, door->closesound); - break; - - // villsa [STRIFE] - case vld_shopClose: - door->direction = 1; - door->speed = (2*FRACUNIT); - S_StartSound(&door->sector->soundorg, door->opensound); - break; - - case vld_close30ThenOpen: - door->direction = 1; - - // villsa [STRIFE] opensound added - S_StartSound(&door->sector->soundorg, door->opensound); - break; - - default: - break; - } - } - break; - - case 2: - // INITIAL WAIT - if (!--door->topcountdown) - { - switch(door->type) - { - case vld_raiseIn5Mins: - door->direction = 1; - door->type = vld_normal; - - // villsa [STRIFE] opensound added - S_StartSound(&door->sector->soundorg, door->opensound); - break; - - default: - break; - } - } - break; - - // villsa [STRIFE] - case -2: - // SPLIT - res1 = T_MovePlane(door->sector, door->speed, door->topheight, 0, 1, 1); - res2 = T_MovePlane(door->sector, door->speed, door->topwait, 0, 0, -1); - - if(res1 == pastdest && res2 == pastdest) - { - door->sector->specialdata = NULL; - P_RemoveThinker(&door->thinker); // unlink and free - } - - break; - - case -1: - // DOWN - res1 = T_MovePlane(door->sector, door->speed, door->sector->floorheight, false, 1, door->direction); - if(res1 == pastdest) - { - switch(door->type) - { - case vld_normal: - case vld_close: - case vld_blazeRaise: - case vld_blazeClose: - door->sector->specialdata = NULL; - P_RemoveThinker (&door->thinker); // unlink and free - // villsa [STRIFE] no sounds - break; - - case vld_close30ThenOpen: - door->direction = 0; - door->topcountdown = TICRATE*30; - break; - - // villsa [STRIFE] - case vld_shopClose: - door->direction = 0; - door->topcountdown = TICRATE*120; - break; - - default: - break; - } - } - else if(res1 == crushed) - { - switch(door->type) - { - case vld_blazeClose: - case vld_close: // DO NOT GO BACK UP! - case vld_shopClose: // villsa [STRIFE] - break; - - default: - door->direction = 1; - // villsa [STRIFE] opensound added - S_StartSound(&door->sector->soundorg, door->opensound); - break; - } - } - break; - - case 1: - // UP - res1 = T_MovePlane(door->sector, - door->speed, - door->topheight, - false,1,door->direction); - - if(res1 == pastdest) - { - switch(door->type) - { - case vld_blazeRaise: - case vld_normal: - door->direction = 0; // wait at top - door->topcountdown = door->topwait; - break; - - case vld_close30ThenOpen: - case vld_blazeOpen: - case vld_open: - case vld_shopClose: // villsa [STRIFE] - door->sector->specialdata = NULL; - P_RemoveThinker (&door->thinker); // unlink and free - break; - - default: - break; - } - } - break; - } -} - - -// -// EV_DoLockedDoor -// Move a locked door up/down -// -// [STRIFE] This game has a crap load of keys. And this function doesn't even -// deal with all of them... -// -int EV_DoLockedDoor(line_t* line, vldoor_e type, mobj_t* thing) -{ - player_t* p; - - p = thing->player; - - if(!p) - return 0; - - switch(line->special) - { - case 99: - case 133: - if(!p->cards[key_IDCard]) - { - p->message = DEH_String("You need an id card"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 134: - case 135: - if(!p->cards[key_IDBadge]) - { - p->message = DEH_String("You need an id badge"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 136: - case 137: - if(!p->cards[key_Passcard]) - { - p->message = DEH_String("You need a pass card"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 151: - case 164: - if(!p->cards[key_GoldKey]) - { - p->message = DEH_String("You need a gold key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 153: - case 163: - if(!p->cards[key_SilverKey]) - { - p->message = DEH_String("You need a silver key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 152: - case 162: - if(!p->cards[key_BrassKey]) - { - p->message = DEH_String("You need a brass key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 167: - case 168: - if(!p->cards[key_SeveredHand]) - { - p->message = DEH_String("Hand print not on file"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 171: - if(!p->cards[key_PrisonKey]) - { - p->message = DEH_String("You don't have the key to the prison"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 172: - if(!p->cards[key_Power1Key]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 173: - if(!p->cards[key_Power2Key]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 176: - if(!p->cards[key_Power3Key]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 189: - if(!p->cards[key_OracleKey]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 191: - if(!p->cards[key_MilitaryID]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 192: - if(!p->cards[key_WarehouseKey]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - - case 223: - if(!p->cards[key_MineKey]) - { - p->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return 0; - } - break; - } - - return EV_DoDoor(line,type); -} - - -// -// EV_DoDoor -// - -int EV_DoDoor(line_t* line, vldoor_e type) -{ - int secnum, rtn; - sector_t* sec; - vldoor_t* door; - - secnum = -1; - rtn = 0; - - while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - if(sec->specialdata) - continue; - - - // new door thinker - rtn = 1; - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); - sec->specialdata = door; - - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - door->sector = sec; - door->type = type; - door->topwait = VDOORWAIT; - door->speed = VDOORSPEED; - R_SoundNumForDoor(door); // villsa [STRIFE] set door sounds - - switch(type) - { - // villsa [STRIFE] new door type - case vld_splitOpen: - door->direction = -2; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->speed = FRACUNIT; - // yes, it using topwait to get the floor height - door->topwait = P_FindLowestFloorSurrounding(sec); - if(door->topheight == sec->ceilingheight) - continue; - - S_StartSound(&sec->soundorg, door->opensound); - break; - - // villsa [STRIFE] new door type - case vld_splitRaiseNearest: - door->direction = -2; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->speed = FRACUNIT; - // yes, it using topwait to get the floor height - door->topwait = P_FindHighestFloorSurrounding(sec); - if(door->topheight == sec->ceilingheight) - continue; - - S_StartSound(&sec->soundorg, door->opensound); - break; - - case vld_blazeClose: - case vld_shopClose: // villsa [STRIFE] - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->direction = -1; - door->speed = VDOORSPEED * 4; - S_StartSound(&door->sector->soundorg, sfx_bdcls); - break; - - case vld_close: - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->direction = -1; - - // villsa [STRIFE] set door sounds - S_StartSound(&door->sector->soundorg, door->opensound); - break; - - case vld_close30ThenOpen: - door->topheight = sec->ceilingheight; - door->direction = -1; - - // villsa [STRIFE] set door sounds - S_StartSound(&door->sector->soundorg, door->closesound); - break; - - case vld_blazeRaise: - case vld_blazeOpen: - door->direction = 1; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->speed = VDOORSPEED * 4; - if (door->topheight != sec->ceilingheight) - S_StartSound(&door->sector->soundorg, sfx_bdopn); - break; - - case vld_normal: - case vld_open: - door->direction = 1; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - - if(door->topheight != sec->ceilingheight) - S_StartSound(&door->sector->soundorg, door->opensound); - break; - - default: - break; - } - - } - return rtn; -} - -// -// EV_ClearForceFields -// -// villsa [STRIFE] new function -// -boolean EV_ClearForceFields(line_t* line) -{ - int secnum; - sector_t* sec; - int i; - line_t* secline; - boolean ret = false; - - secnum = -1; - - while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - - line->special = 0; - ret = true; - - // haleyjd 09/18/10: fixed to continue w/linecount == 0, not return - for(i = 0; i < sec->linecount; i++) - { - secline = sec->lines[i]; - if(!(secline->flags & ML_TWOSIDED)) - continue; - if(secline->special != 148) - continue; - - secline->flags &= ~ML_BLOCKING; - secline->special = 0; - sides[secline->sidenum[0]].midtexture = 0; - sides[secline->sidenum[1]].midtexture = 0; - } - } - - return ret; -} - - -// -// EV_VerticalDoor : open a door manually, no tag value -// -// [STRIFE] Tons of new door types were added. -// -void EV_VerticalDoor(line_t* line, mobj_t* thing) -{ - player_t* player; - sector_t* sec; - vldoor_t* door; - int side; - - side = 0; // only front sides can be used - - // Check for locks - player = thing->player; - - // haleyjd 09/15/10: [STRIFE] myriad checks here... - switch(line->special) - { - case 26: // DR ID Card door - case 32: // D1 ID Card door - if(!player->cards[key_IDCard]) - { - player->message = DEH_String("You need an id card to open this door"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 27: // DR Pass Card door - case 34: // D1 Pass Card door - if(!player->cards[key_Passcard]) - { - player->message = DEH_String("You need a pass card key to open this door"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 28: // DR ID Badge door - case 33: // D1 ID Badge door - if(!player->cards[key_IDBadge]) - { - player->message = DEH_String("You need an id badge to open this door"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 156: // D1 brass key door - case 161: // DR brass key door - if(!player->cards[key_BrassKey]) - { - player->message = DEH_String("You need a brass key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 157: // D1 silver key door - case 160: // DR silver key door - if(!player->cards[key_SilverKey]) - { - player->message = DEH_String("You need a silver key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 158: // D1 gold key door - case 159: // DR gold key door - if(!player->cards[key_GoldKey]) - { - player->message = DEH_String("You need a gold key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - // villsa [STRIFE] added 09/15/10 - case 165: - player->message = DEH_String("That doesn't seem to work"); - S_StartSound(NULL, sfx_oof); - return; - - case 166: // DR Hand Print door - if(!player->cards[key_SeveredHand]) - { - player->message = DEH_String("Hand print not on file"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 169: // DR Base key door - if(!player->cards[key_BaseKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 170: // DR Gov's Key door - if(!player->cards[key_GovsKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 190: // DR Order Key door - if(!player->cards[key_OrderKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 205: // DR "Only in retail" - player->message = DEH_String("THIS AREA IS ONLY AVAILABLE IN THE " - "RETAIL VERSION OF STRIFE"); - S_StartSound(NULL, sfx_oof); - return; - - case 213: // DR Chalice door - if(!P_PlayerHasItem(player, MT_INV_CHALICE)) - { - player->message = DEH_String("You need the chalice!"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 217: // DR Core Key door - if(!player->cards[key_CoreKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 221: // DR Mauler Key door - if(!player->cards[key_MaulerKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 224: // DR Chapel Key door - if(!player->cards[key_ChapelKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 225: // DR Catacomb Key door - if(!player->cards[key_CatacombKey]) - { - player->message = DEH_String("You don't have the key"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - case 232: // DR Oracle Pass door - if(!(player->questflags & QF_QUEST18)) - { - player->message = DEH_String("You need the Oracle Pass!"); - S_StartSound(NULL, sfx_oof); - return; - } - break; - - default: - break; - } - - // if the sector has an active thinker, use it - sec = sides[ line->sidenum[side^1]] .sector; - - if (sec->specialdata) - { - door = sec->specialdata; - // [STRIFE] Adjusted to handle linetypes handled here by Strife. - // BUG: Not all door types are checked here. This means that certain - // door lines are allowed to fall through and start a new thinker on the - // sector! This is why some doors can become jammed in Strife - stuck in - // midair, or unable to be opened at all. Multiple thinkers will fight - // over how to move the door. They should have added a default return if - // they weren't going to handle this unconditionally... - switch(line->special) - { - case 1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s - case 26: - case 27: - case 28: - case 117: - case 159: // villsa - case 160: // haleyjd - case 161: // villsa - case 166: // villsa - case 169: // villsa - case 170: // villsa - case 190: // villsa - case 213: // villsa - case 232: // villsa - if(door->direction == -1) - door->direction = 1; // go back up - else - { - if (!thing->player) - return; - - // When is a door not a door? - // In Vanilla, door->direction is set, even though - // "specialdata" might not actually point at a door. - - if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor) - { - door->direction = -1; // start going down immediately - } - else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise) - { - // Erm, this is a plat, not a door. - // This notably causes a problem in ep1-0500.lmp where - // a plat and a door are cross-referenced; the door - // doesn't open on 64-bit. - // The direction field in vldoor_t corresponds to the wait - // field in plat_t. Let's set that to -1 instead. - - plat_t *plat; - - plat = (plat_t *) door; - plat->wait = -1; - } - else - { - // This isn't a door OR a plat. Now we're in trouble. - - fprintf(stderr, "EV_VerticalDoor: Tried to close " - "something that wasn't a door.\n"); - - // Try closing it anyway. At least it will work on 32-bit - // machines. - - door->direction = -1; - } - } - return; - default: - break; - } - } - - // haleyjd 09/15/10: [STRIFE] Removed DOOM door sounds - - // new door thinker - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); - sec->specialdata = door; - door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor; - door->sector = sec; - door->direction = 1; - door->speed = VDOORSPEED; - door->topwait = VDOORWAIT; - R_SoundNumForDoor(door); // haleyjd 09/15/10: [STRIFE] Get door sounds - - // for proper sound - [STRIFE] - verified complete - switch(line->special) - { - case 117: // BLAZING DOOR RAISE - case 118: // BLAZING DOOR OPEN - S_StartSound(&sec->soundorg, sfx_bdopn); - break; - - default: // NORMAL DOOR SOUND - S_StartSound(&sec->soundorg, door->opensound); - break; - } - - // haleyjd: [STRIFE] - verified all. - switch(line->special) - { - case 1: - case 26: - case 27: - case 28: - door->type = vld_normal; - break; - - case 31: - case 32: - case 33: - case 34: - case 156: // villsa [STRIFE] - case 157: // villsa [STRIFE] - case 158: // villsa [STRIFE] - door->type = vld_open; - line->special = 0; - break; - - case 117: // blazing door raise - door->type = vld_blazeRaise; - door->speed = VDOORSPEED*4; - break; - - case 118: // blazing door open - door->type = vld_blazeOpen; - line->special = 0; - door->speed = VDOORSPEED*4; - break; - - default: - // haleyjd: [STRIFE] pretty important to have this here! - door->type = vld_normal; - break; - } - - // find the top and bottom of the movement range - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; -} - - -// -// Spawn a door that closes after 30 seconds -// -void P_SpawnDoorCloseIn30 (sector_t* sec) -{ - vldoor_t* door; - - door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); - - P_AddThinker (&door->thinker); - - sec->specialdata = door; - sec->special = 0; - - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - door->sector = sec; - door->direction = 0; - door->type = vld_normal; - door->speed = VDOORSPEED; - door->topcountdown = 30 * TICRATE; -} - -// -// Spawn a door that opens after 5 minutes -// -void -P_SpawnDoorRaiseIn5Mins -( sector_t* sec, - int secnum ) -{ - vldoor_t* door; - - door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); - - P_AddThinker (&door->thinker); - - sec->specialdata = door; - sec->special = 0; - - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - door->sector = sec; - door->direction = 2; - door->type = vld_raiseIn5Mins; - door->speed = VDOORSPEED; - door->topheight = P_FindLowestCeilingSurrounding(sec); - door->topheight -= 4*FRACUNIT; - door->topwait = VDOORWAIT; - door->topcountdown = 5 * 60 * TICRATE; -} - - -// villsa [STRIFE] resurrected sliding doors -// - -// -// villsa [STRIFE] -// -// Sliding door name information -// -static slidename_t slideFrameNames[MAXSLIDEDOORS] = -{ - // SIGLDR - { - "SIGLDR01", // frame1 - "SIGLDR02", // frame2 - "SIGLDR03", // frame3 - "SIGLDR04", // frame4 - "SIGLDR05", // frame5 - "SIGLDR06", // frame6 - "SIGLDR07", // frame7 - "SIGLDR08" // frame8 - }, - // DORSTN - { - "DORSTN01", // frame1 - "DORSTN02", // frame2 - "DORSTN03", // frame3 - "DORSTN04", // frame4 - "DORSTN05", // frame5 - "DORSTN06", // frame6 - "DORSTN07", // frame7 - "DORSTN08" // frame8 - }, - - // DORQTR - { - "DORQTR01", // frame1 - "DORQTR02", // frame2 - "DORQTR03", // frame3 - "DORQTR04", // frame4 - "DORQTR05", // frame5 - "DORQTR06", // frame6 - "DORQTR07", // frame7 - "DORQTR08" // frame8 - }, - - // DORCRG - { - "DORCRG01", // frame1 - "DORCRG02", // frame2 - "DORCRG03", // frame3 - "DORCRG04", // frame4 - "DORCRG05", // frame5 - "DORCRG06", // frame6 - "DORCRG07", // frame7 - "DORCRG08" // frame8 - }, - - // DORCHN - { - "DORCHN01", // frame1 - "DORCHN02", // frame2 - "DORCHN03", // frame3 - "DORCHN04", // frame4 - "DORCHN05", // frame5 - "DORCHN06", // frame6 - "DORCHN07", // frame7 - "DORCHN08" // frame8 - }, - - // DORIRS - { - "DORIRS01", // frame1 - "DORIRS02", // frame2 - "DORIRS03", // frame3 - "DORIRS04", // frame4 - "DORIRS05", // frame5 - "DORIRS06", // frame6 - "DORIRS07", // frame7 - "DORIRS08" // frame8 - }, - - // DORALN - { - "DORALN01", // frame1 - "DORALN02", // frame2 - "DORALN03", // frame3 - "DORALN04", // frame4 - "DORALN05", // frame5 - "DORALN06", // frame6 - "DORALN07", // frame7 - "DORALN08" // frame8 - }, - - {"\0","\0","\0","\0","\0","\0","\0","\0"} -}; - -// -// villsa [STRIFE] -// -// Sliding door open sounds -// -static sfxenum_t slideOpenSounds[MAXSLIDEDOORS] = -{ - sfx_drlmto, sfx_drston, sfx_airlck, sfx_drsmto, - sfx_drchno, sfx_airlck, sfx_airlck, sfx_None -}; - -// -// villsa [STRIFE] -// -// Sliding door close sounds -// -static sfxenum_t slideCloseSounds[MAXSLIDEDOORS] = -{ - sfx_drlmtc, sfx_drston, sfx_airlck, sfx_drsmtc, - sfx_drchnc, sfx_airlck, sfx_airlck, sfx_None -}; - -slideframe_t slideFrames[MAXSLIDEDOORS]; - -// -// P_InitSlidingDoorFrames -// -// villsa [STRIFE] resurrected -// -void P_InitSlidingDoorFrames(void) -{ - int i; - int f1; - int f2; - int f3; - int f4; - - memset(slideFrames, 0, sizeof(slideframe_t) * MAXSLIDEDOORS); - - for(i = 0; i < MAXSLIDEDOORS; i++) - { - if(!slideFrameNames[i].frame1[0]) - break; - - f1 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame1)); - f2 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame2)); - f3 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame3)); - f4 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame4)); - - slideFrames[i].frames[0] = f1; - slideFrames[i].frames[1] = f2; - slideFrames[i].frames[2] = f3; - slideFrames[i].frames[3] = f4; - - f1 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame5)); - f2 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame6)); - f3 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame7)); - f4 = R_TextureNumForName(DEH_String(slideFrameNames[i].frame8)); - - slideFrames[i].frames[4] = f1; - slideFrames[i].frames[5] = f2; - slideFrames[i].frames[6] = f3; - slideFrames[i].frames[7] = f4; - } -} - - -// -// P_FindSlidingDoorType -// -// Return index into "slideFrames" array -// for which door type to use -// -// villsa [STRIFE] resurrected -// -int P_FindSlidingDoorType(line_t* line) -{ - int i; - int val; - - for(i = 0; i < MAXSLIDEDOORS-1; i++) - { - val = sides[line->sidenum[0]].toptexture; - if(val == slideFrames[i].frames[0]) - return i; - } - - return -1; -} - -// -// T_SlidingDoor -// -// villsa [STRIFE] resurrected -// -void T_SlidingDoor(slidedoor_t* door) -{ - sector_t* sec; - - sec = door->frontsector; - - switch(door->status) - { - case sd_opening: - if(!door->timer--) - { - if(++door->frame == SNUMFRAMES) - { - // IF DOOR IS DONE OPENING... - door->line1->flags &= ~ML_BLOCKING; - door->line2->flags &= ~ML_BLOCKING; - - if(door->type == sdt_openOnly) - { - door->frontsector->specialdata = NULL; - P_RemoveThinker (&door->thinker); - return; - } - - door->timer = SDOORWAIT; - door->status = sd_waiting; - } - else - { - // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... - door->timer = SWAITTICS; - - sides[door->line2->sidenum[0]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - - sides[door->line2->sidenum[1]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - - sides[door->line1->sidenum[0]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - - sides[door->line1->sidenum[1]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - } - } - - return; - - case sd_waiting: - // IF DOOR IS DONE WAITING... - if(!door->timer--) - { - fixed_t speed; - fixed_t cheight; - - sec = door->frontsector; - - // CAN DOOR CLOSE? - if(sec->thinglist != NULL) - { - door->timer = SDOORWAIT; - return; - } - else - { - - cheight = sec->ceilingheight; - speed = cheight - sec->floorheight - (10*FRACUNIT); - - // something blocking it? - if(T_MovePlane(sec, speed, sec->floorheight, 0, 1, -1) == crushed) - { - door->timer = SDOORWAIT; - return; - } - else - { - // Instantly move plane - T_MovePlane(sec, (128*FRACUNIT), cheight, 0, 1, 1); - - // turn line blocking back on - door->line1->flags |= ML_BLOCKING; - door->line2->flags |= ML_BLOCKING; - - // play close sound - S_StartSound(&sec->soundorg, slideCloseSounds[door->whichDoorIndex]); - - door->status = sd_closing; - door->timer = SWAITTICS; - } - } - } - - return; - - case sd_closing: - if (!door->timer--) - { - if(--door->frame < 0) - { - // IF DOOR IS DONE CLOSING... - T_MovePlane(sec, (128*FRACUNIT), sec->floorheight, 0, 1, -1); - door->frontsector->specialdata = NULL; - P_RemoveThinker (&door->thinker); - return; - } - else - { - // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME... - door->timer = SWAITTICS; - - sides[door->line2->sidenum[0]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - - sides[door->line2->sidenum[1]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - - sides[door->line1->sidenum[0]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - - sides[door->line1->sidenum[1]].midtexture = - slideFrames[door->whichDoorIndex].frames[door->frame]; - } - } - - return; - } -} - -// -// EV_RemoteSlidingDoor -// -// villsa [STRIFE] new function -// -int EV_RemoteSlidingDoor(line_t* line, mobj_t* thing) -{ - int secnum; - sector_t* sec; - int i; - int rtn; - line_t* secline; - - secnum = -1; - rtn = 0; - - while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - if(sec->specialdata) - continue; - - for(i = 0; i < 4; i++) - { - secline = sec->lines[i]; - - if(P_FindSlidingDoorType(secline) < 0) - continue; - - EV_SlidingDoor(secline, thing); - rtn = 1; - } - } - - return rtn; -} - - -// -// EV_SlidingDoor -// -// villsa [STRIFE] -// -void EV_SlidingDoor(line_t* line, mobj_t* thing) -{ - sector_t* sec; - slidedoor_t* door; - int i; - line_t* secline; - - // Make sure door isn't already being animated - sec = sides[line->sidenum[1]].sector; - door = NULL; - if(sec->specialdata) - { - if (!thing->player) - return; - - door = sec->specialdata; - if(door->type == sdt_openAndClose) - { - if(door->status == sd_waiting) - { - door->status = sd_closing; - door->timer = SWAITTICS; // villsa [STRIFE] - } - } - else - return; - } - - // Init sliding door vars - if(!door) - { - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); - P_AddThinker (&door->thinker); - - sec->specialdata = door; - - door->type = sdt_openAndClose; - door->status = sd_opening; - door->whichDoorIndex = P_FindSlidingDoorType(line); - - // villsa [STRIFE] different error message - if(door->whichDoorIndex < 0) - I_Error(DEH_String("EV_SlidingDoor: Textures are not defined for sliding door!")); - - sides[line->sidenum[0]].midtexture = sides[line->sidenum[0]].toptexture; - - // villsa [STRIFE] - door->line1 = line; - door->line2 = line; - - // villsa [STRIFE] this loop assumes that the sliding door is made up - // of only four linedefs! - for(i = 0; i < 4; i++) - { - secline = sec->lines[i]; - if(secline != line) - { - side_t* side1; - side_t* side2; - - side1 = &sides[secline->sidenum[0]]; - side2 = &sides[line->sidenum[0]]; - - if(side1->toptexture == side2->toptexture) - door->line2 = secline; - } - } - - door->thinker.function.acp1 = (actionf_p1)T_SlidingDoor; - door->timer = SWAITTICS; - door->frontsector = sec; - door->frame = 0; - - // villsa [STRIFE] preset flags - door->line1->flags |= ML_BLOCKING; - door->line2->flags |= ML_BLOCKING; - - // villsa [STRIFE] set the closing sector - T_MovePlane( - door->frontsector, - (128*FRACUNIT), - P_FindLowestCeilingSurrounding(door->frontsector), - 0, - 1, - 1); - - // villsa [STRIFE] play open sound - S_StartSound(&door->frontsector->soundorg, slideOpenSounds[door->whichDoorIndex]); - } -} - diff --git a/games/NXDoom/src/strife/p_enemy.c b/games/NXDoom/src/strife/p_enemy.c deleted file mode 100644 index 7763a87b015..00000000000 --- a/games/NXDoom/src/strife/p_enemy.c +++ /dev/null @@ -1,3388 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Enemy thinking, AI. -// Action Pointer Functions -// that are associated with states/frames. -// - -#include -#include - -#include "m_random.h" -#include "i_system.h" -#include "doomdef.h" -#include "m_misc.h" -#include "p_local.h" -#include "s_sound.h" -#include "g_game.h" -#include "z_zone.h" // villsa [STRIFE] - -// State. -#include "doomstat.h" -#include "r_state.h" - -// Data. -#include "sounds.h" - -// [STRIFE] Dialog / Inventory -#include "p_dialog.h" -#include "deh_str.h" -#include "w_wad.h" -#include "f_finale.h" -#include "p_inter.h" - -// Forward Declarations: -void A_RandomWalk(mobj_t *); -void A_ProgrammerAttack(mobj_t* actor); -void A_FireSigilEOffshoot(mobj_t *actor); -void A_SpectreCAttack(mobj_t *actor); -void A_SpectreDAttack(mobj_t *actor); -void A_SpectreEAttack(mobj_t *actor); - -void P_ThrustMobj(mobj_t *actor, angle_t angle, fixed_t force); - -typedef enum -{ - DI_EAST, - DI_NORTHEAST, - DI_NORTH, - DI_NORTHWEST, - DI_WEST, - DI_SOUTHWEST, - DI_SOUTH, - DI_SOUTHEAST, - DI_NODIR, - NUMDIRS - -} dirtype_t; - - -// -// P_NewChaseDir related LUT. -// -dirtype_t opposite[] = -{ - DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, - DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR -}; - -dirtype_t diags[] = -{ - DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST -}; - - - - - -void A_Fall (mobj_t *actor); - - -// -// ENEMY THINKING -// Enemies are allways spawned -// with targetplayer = -1, threshold = 0 -// Most monsters are spawned unaware of all players, -// but some can be made preaware -// - - -// -// Called by P_NoiseAlert. -// Recursively traverse adjacent sectors, -// sound blocking lines cut off traversal. -// -// haleyjd 09/05/10: [STRIFE] Verified unmodified -// - -mobj_t* soundtarget; - -void -P_RecursiveSound -( sector_t* sec, - int soundblocks ) -{ - int i; - line_t* check; - sector_t* other; - - // wake up all monsters in this sector - if (sec->validcount == validcount - && sec->soundtraversed <= soundblocks+1) - { - return; // already flooded - } - - sec->validcount = validcount; - sec->soundtraversed = soundblocks+1; - sec->soundtarget = soundtarget; - - for (i=0 ;ilinecount ; i++) - { - check = sec->lines[i]; - if (! (check->flags & ML_TWOSIDED) ) - continue; - - P_LineOpening (check); - - if (openrange <= 0) - continue; // closed door - - if ( sides[ check->sidenum[0] ].sector == sec) - other = sides[ check->sidenum[1] ] .sector; - else - other = sides[ check->sidenum[0] ].sector; - - if (check->flags & ML_SOUNDBLOCK) - { - if (!soundblocks) - P_RecursiveSound (other, 1); - } - else - P_RecursiveSound (other, soundblocks); - } -} - - - -// -// P_NoiseAlert -// If a monster yells at a player, -// it will alert other monsters to the player. -// -// haleyjd 09/05/10: [STRIFE] Verified unmodified -// -void -P_NoiseAlert -( mobj_t* target, - mobj_t* emmiter ) -{ - soundtarget = target; - validcount++; - P_RecursiveSound (emmiter->subsector->sector, 0); -} - -// -// P_WakeUpThing -// -// villsa [STRIFE] New function -// Wakes up an mobj.nearby when somebody has been punched. -// -static void P_WakeUpThing(mobj_t* puncher, mobj_t* bystander) -{ - if(!(bystander->flags & MF_NODIALOG)) - { - bystander->target = puncher; - if(bystander->info->seesound) - S_StartSound(bystander, bystander->info->seesound); - P_SetMobjState(bystander, bystander->info->seestate); - } -} - -// -// P_DoPunchAlert -// -// villsa [STRIFE] New function (by Quasar ;) -// Wake up buddies nearby when the player thinks he's gotten too clever -// with the punch dagger. Walks sector links. -// -void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee) -{ - mobj_t *rover; - - // don't bother with this crap if we're already on alert - if(punchee->subsector->sector->soundtarget) - return; - - // gotta still be alive to call for help - if(punchee->health <= 0) - return; - - // has to be something you can wake up and kill too - if(!(punchee->flags & MF_COUNTKILL) || punchee->flags & MF_NODIALOG) - return; - - // make the punchee hurt - haleyjd 09/05/10: Fixed to use painstate. - punchee->target = puncher; - P_SetMobjState(punchee, punchee->info->painstate); - - // wake up everybody nearby - - // scan forward on sector list - for(rover = punchee->snext; rover; rover = rover->snext) - { - // we only wake up certain thing types (Acolytes and Templars?) - if(rover->health > 0 && rover->type >= MT_GUARD1 && rover->type <= MT_PGUARD && - (P_CheckSight(rover, puncher) || P_CheckSight(rover, punchee))) - { - P_WakeUpThing(puncher, rover); - rover->flags |= MF_NODIALOG; - } - } - - // scan backward on sector list - for(rover = punchee->sprev; rover; rover = rover->sprev) - { - // we only wake up certain thing types (Acolytes and Templars?) - if(rover->health > 0 && rover->type >= MT_GUARD1 && rover->type <= MT_PGUARD && - (P_CheckSight(rover, puncher) || P_CheckSight(rover, punchee))) - { - P_WakeUpThing(puncher, rover); - rover->flags |= MF_NODIALOG; - } - } -} - - - - -// -// P_CheckMeleeRange -// -// [STRIFE] Minor change to meleerange. -// -boolean P_CheckMeleeRange(mobj_t* actor) -{ - mobj_t* pl; - fixed_t dist; - - if(!actor->target) - return false; - - pl = actor->target; - if(actor->z + 3 * actor->height / 2 < pl->z) // villsa [STRIFE] - return false; - - dist = P_AproxDistance(pl->x - actor->x, pl->y - actor->y); - - if(dist >= MELEERANGE - 20*FRACUNIT + pl->info->radius) - return false; - - if(!P_CheckSight (actor, actor->target)) - return false; - - return true; -} - -// -// P_CheckMissileRange -// -// [STRIFE] -// Changes to eliminate DOOM-specific code and to allow for -// varying attack ranges for Strife monsters, as well as a general tweak -// to considered distance for all monsters. -// -boolean P_CheckMissileRange(mobj_t* actor) -{ - fixed_t dist; - - if(!P_CheckSight(actor, actor->target)) - return false; - - if(actor->flags & MF_JUSTHIT) - { - // the target just hit the enemy, - // so fight back! - actor->flags &= ~MF_JUSTHIT; - return true; - } - - if(actor->reactiontime) - return false; // do not attack yet - - // OPTIMIZE: get this from a global checksight - dist = P_AproxDistance(actor->x-actor->target->x, - actor->y-actor->target->y) - 64*FRACUNIT; - - if (!actor->info->meleestate) - dist -= 128*FRACUNIT; // no melee attack, so fire more - - dist >>= 16; - - // villsa [STRIFE] checks for acolytes - // haleyjd 09/05/10: Repaired to match disassembly: Was including - // SHADOWGUARD in the wrong case, was missing MT_SENTINEL entirely. - // Structure of ASM also indicates this was probably a switch - // statement turned into a cascading if/else by the compiler. - switch(actor->type) - { - case MT_GUARD1: - case MT_GUARD2: - case MT_GUARD3: - case MT_GUARD4: - case MT_GUARD5: - case MT_GUARD6: - // oddly, not all Acolytes are included here... - dist >>= 4; - break; - case MT_SHADOWGUARD: - case MT_CRUSADER: - case MT_SENTINEL: - dist >>= 1; - break; - default: - break; - } - - // villsa [STRIFE] changed to 150 - if (dist > 150) - dist = 150; - - // haleyjd 20100910: Hex-Rays was leaving this out completely: - if (actor->type == MT_CRUSADER && dist > 120) - dist = 120; - - // haleyjd 20110224 [STRIFE]: reversed predicate - return (dist < P_Random()); -} - -// -// P_CheckRobotRange -// -// villsa [STRIFE] New function -// -boolean P_CheckRobotRange(mobj_t *actor) -{ - fixed_t dist; - - if(!P_CheckSight(actor, actor->target)) - return false; - - if(actor->reactiontime) - return false; // do not attack yet - - dist = (P_AproxDistance(actor->x-actor->target->x, - actor->y-actor->target->y) - 64*FRACUNIT) >> FRACBITS; - - return (dist < 200); -} - - -// -// P_Move -// Move in the current direction, -// returns false if the move is blocked. -// -// [STRIFE] -// villsa/haleyjd 09/05/10: Modified for terrain types and 3D object -// clipping. Below constants are verified to be unmodified: -// -fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000}; -fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000}; - - -boolean P_Move (mobj_t* actor) -{ - fixed_t tryx; - fixed_t tryy; - - line_t* ld; - - // warning: 'catch', 'throw', and 'try' - // are all C++ reserved words - boolean try_ok; - boolean good; - - if (actor->movedir == DI_NODIR) - return false; - - if ((unsigned)actor->movedir >= 8) - I_Error ("Weird actor->movedir!"); - - tryx = actor->x + actor->info->speed*xspeed[actor->movedir]; - tryy = actor->y + actor->info->speed*yspeed[actor->movedir]; - - try_ok = P_TryMove (actor, tryx, tryy); - - if (!try_ok) - { - // open any specials - if (actor->flags & MF_FLOAT && floatok) - { - // must adjust height - if (actor->z < tmfloorz) - actor->z += FLOATSPEED; // [STRIFE] Note FLOATSPEED == 5*FRACUNIT - else - actor->z -= FLOATSPEED; - - actor->flags |= MF_INFLOAT; - return true; - } - - if (!numspechit) - return false; - - actor->movedir = DI_NODIR; - good = false; - while (numspechit--) - { - ld = spechit[numspechit]; - // if the special is not a door - // that can be opened, - // return false - if (P_UseSpecialLine (actor, ld,0)) - good = true; - } - return good; - } - else - { - actor->flags &= ~(MF_INFLOAT|MF_FEETCLIPPED); // villsa [STRIFE] - - // villsa [STRIFE] - if(P_GetTerrainType(actor) != FLOOR_SOLID) - actor->flags |= MF_FEETCLIPPED; - } - - - // villsa [STRIFE] Removed pulling non-floating actors down to the ground. - // (haleyjd 09/05/10: Verified) - /*if (! (actor->flags & MF_FLOAT) ) - actor->z = actor->floorz;*/ - - return true; -} - - -// -// TryWalk -// Attempts to move actor on -// in its current (ob->moveangle) direction. -// If blocked by either a wall or an actor -// returns FALSE -// If move is either clear or blocked only by a door, -// returns TRUE and sets... -// If a door is in the way, -// an OpenDoor call is made to start it opening. -// -// haleyjd 09/05/10: [STRIFE] Verified unmodified. -// -boolean P_TryWalk (mobj_t* actor) -{ - if (!P_Move (actor)) - { - return false; - } - - actor->movecount = P_Random()&15; - return true; -} - - - -// -// P_NewChaseDir -// - -void P_NewChaseDir(mobj_t* actor) -{ - fixed_t deltax; - fixed_t deltay; - - dirtype_t d[3]; - - int tdir; - dirtype_t olddir; - - dirtype_t turnaround; - - // villsa [STRIFE] don't bomb out and instead set spawnstate - if(!actor->target) - { - //I_Error("P_NewChaseDir: called with no target"); - P_SetMobjState(actor, actor->info->spawnstate); - return; - } - - olddir = actor->movedir; - turnaround=opposite[olddir]; - - deltax = actor->target->x - actor->x; - deltay = actor->target->y - actor->y; - - if (deltax>10*FRACUNIT) - d[1]= DI_EAST; - else if (deltax<-10*FRACUNIT) - d[1]= DI_WEST; - else - d[1]=DI_NODIR; - - if (deltay<-10*FRACUNIT) - d[2]= DI_SOUTH; - else if (deltay>10*FRACUNIT) - d[2]= DI_NORTH; - else - d[2]=DI_NODIR; - - // try direct route - if (d[1] != DI_NODIR - && d[2] != DI_NODIR) - { - actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; - if (actor->movedir != (int) turnaround && P_TryWalk(actor)) - return; - } - - // try other directions - if (P_Random() > 200 - || abs(deltay)>abs(deltax)) - { - tdir=d[1]; - d[1]=d[2]; - d[2]=tdir; - } - - if (d[1]==turnaround) - d[1]=DI_NODIR; - if (d[2]==turnaround) - d[2]=DI_NODIR; - - if (d[1]!=DI_NODIR) - { - actor->movedir = d[1]; - if (P_TryWalk(actor)) - { - // either moved forward or attacked - return; - } - } - - if (d[2]!=DI_NODIR) - { - actor->movedir =d[2]; - - if (P_TryWalk(actor)) - return; - } - - // there is no direct path to the player, - // so pick another direction. - if (olddir!=DI_NODIR) - { - actor->movedir =olddir; - - if (P_TryWalk(actor)) - return; - } - - // randomly determine direction of search - if (P_Random()&1) - { - for ( tdir=DI_EAST; - tdir<=DI_SOUTHEAST; - tdir++ ) - { - if (tdir != (int) turnaround) - { - actor->movedir =tdir; - - if ( P_TryWalk(actor) ) - return; - } - } - } - else - { - for ( tdir=DI_SOUTHEAST; - tdir != (DI_EAST-1); - tdir-- ) - { - if (tdir != (int) turnaround) - { - actor->movedir = tdir; - - if ( P_TryWalk(actor) ) - return; - } - } - } - - if (turnaround != DI_NODIR) - { - actor->movedir =turnaround; - if ( P_TryWalk(actor) ) - return; - } - - actor->movedir = DI_NODIR; // can not move -} - -// -// P_NewRandomDir -// -// villsa [STRIFE] new function -// -// haleyjd: Almost identical to the tail-end of P_NewChaseDir, this function -// finds a purely random direction for an object to walk. Called from -// A_RandomWalk. -// -// Shockingly similar to the RandomWalk pointer in Eternity :) -// -void P_NewRandomDir(mobj_t* actor) -{ - int dir = 0; - int omovedir = opposite[actor->movedir]; // haleyjd 20110223: nerfed this... - - // randomly determine direction of search - if(P_Random() & 1) - { - // Try all non-reversal directions forward, first - for(dir = 0; dir < DI_NODIR; dir++) - { - if(dir != omovedir) - { - actor->movedir = dir; - if(P_Random() & 1) - { - if(P_TryWalk(actor)) - break; - } - } - } - - // haleyjd 20110223: logic missing entirely: - // failed all non-reversal directions? try reversing - if(dir > DI_SOUTHEAST) - { - if(omovedir == DI_NODIR) - { - actor->movedir = DI_NODIR; - return; - } - actor->movedir = omovedir; - if(P_TryWalk(actor)) - return; - else - { - actor->movedir = DI_NODIR; - return; - } - } - } - else - { - // Try directions one at a time in backward order - dir = DI_SOUTHEAST; - while(1) - { - // haleyjd 09/05/10: missing random code. - if(dir != omovedir) - { - actor->movedir = dir; - - // villsa 09/06/10: un-inlined code - if(P_TryWalk(actor)) - return; - } - - // Ran out of non-reversal directions to try? Reverse. - if(--dir == -1) - { - if(omovedir == DI_NODIR) - { - actor->movedir = DI_NODIR; - return; - } - actor->movedir = omovedir; - // villsa 09/06/10: un-inlined code - if(P_TryWalk(actor)) - return; - else - { - actor->movedir = DI_NODIR; - return; - } - } // end if(--dir == -1) - } // end while(1) - } // end else -} - - -// -// P_LookForPlayers -// -// If allaround is false, only look 180 degrees in front. -// Returns true if a player is targeted. -// -// [STRIFE] -// haleyjd 09/05/10: Modifications to support friendly units. -// -boolean -P_LookForPlayers -( mobj_t* actor, - boolean allaround ) -{ - int c; - int stop; - player_t* player; - angle_t an; - fixed_t dist; - mobj_t * master = players[actor->miscdata].mo; - int consecutive_missing = 0; // for breaking infinite loop - - // haleyjd 09/05/10: handle Allies - if(actor->flags & MF_ALLY) - { - // Deathmatch: support team behavior for Rebels. - if(netgame) - { - // Rebels adopt the allied player's target if it is not of the same - // allegiance. Other allies do it unconditionally. - if(master && master->target && - (master->target->type != MT_REBEL1 || - master->target->miscdata != actor->miscdata)) - { - actor->target = master->target; - } - else - { - // haleyjd 09/06/10: Note that this sets actor->target in Strife! - P_BulletSlope(actor); - - // Clear target if nothing is visible, or if the target is a - // friendly Rebel or the allied player. - if (linetarget == NULL - || (actor->target->type == MT_REBEL1 - && actor->target->miscdata == actor->miscdata) - || actor->target == master) - { - actor->target = NULL; - return false; - } - } - } - else - { - // Single-player: Adopt any non-allied player target. - if(master && master->target && !(master->target->flags & MF_ALLY)) - { - actor->target = master->target; - return true; - } - - // haleyjd 09/06/10: Note that this sets actor->target in Strife! - P_BulletSlope(actor); - - // Clear target if nothing is visible, or if the target is an ally. - if(!linetarget || actor->target->flags & MF_ALLY) - { - actor->target = NULL; - return false; - } - } - - return true; - } - - c = 0; - - // The 3 below is probably a mistake (it should be MAXPLAYERS - 1, or 7) - // and in vanilla this can potentially cause an infinite loop in - // multiplayer. Unfortunately we can't correct the mistake - doing so will - // cause desyncs. Upon spawning, each enemy's lastlook is initialized to a - // random value between 0 and 7 (i.e MAXPLAYERS - 1). There's a chance - // that the first call of this function for that enemy will return early - // courtesy of the actor->lastlook == stop condition. In a single-player - // game this occurs when (actor->lastlook - 1) & 3 equals 0, or when - // lastlook equals 1 or 5. - - // If you use MAXPLAYERS - 1, it has the side effect of altering which - // enemies are affected by an early actor->lastlook == stop return. Now it - // happens when (actor->lastlook - 1) & 7 equals 0, or when lastlook equals - // 1, *not* 1 and 5 as above. - - stop = (actor->lastlook-1)&3; - - for ( ; ; actor->lastlook = (actor->lastlook+1)&3 ) - { - if (!playeringame[actor->lastlook]) - { - // Break the vanilla infinite loop here. It can occur if there are - // > 4 players and players 0 - 3 all quit the game. Error out - // instead. - if (consecutive_missing == 4) - { - I_Error("P_LookForPlayers: No player 1 - 4.\n"); - } - consecutive_missing++; - continue; - } - - consecutive_missing = 0; - - if (c++ == 2 - || actor->lastlook == stop) - { - // done looking - return false; - } - - player = &players[actor->lastlook]; - - if (player->health <= 0) - continue; // dead - - if (!P_CheckSight (actor, player->mo)) - continue; // out of sight - - if (!allaround) - { - an = R_PointToAngle2(actor->x, - actor->y, - player->mo->x, - player->mo->y) - actor->angle; - - if (an > ANG90 && an < ANG270) - { - dist = P_AproxDistance (player->mo->x - actor->x, - player->mo->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - - actor->target = player->mo; - return true; - } - - return false; -} - -// haleyjd 09/05/10: [STRIFE] Removed A_KeenDie - -// -// ACTION ROUTINES -// - -// -// A_Look -// Stay in state until a player is sighted. -// -// [STRIFE] -// haleyjd 09/05/10: Adjusted for allies, Inquisitors, etc. -// -void A_Look (mobj_t* actor) -{ - mobj_t* targ; - - actor->threshold = 0; // any shot will wake up - targ = actor->subsector->sector->soundtarget; - - if (targ - && (targ->flags & MF_SHOOTABLE) ) - { - // [STRIFE] Allies wander when they call this. - if(actor->flags & MF_ALLY) - A_RandomWalk(actor); - else - { - actor->target = targ; - - if ( actor->flags & MF_AMBUSH ) - { - if (P_CheckSight (actor, actor->target)) - goto seeyou; - } - else - goto seeyou; - } - } - - // haleyjd 09/05/10: This is bizarre, as Rogue keeps using the GIVEQUEST flag - // as a parameter to control allaround look behavior. Did they just run out of - // flags, or what? - // STRIFE-TODO: Needs serious verification. - if (!P_LookForPlayers(actor, (actor->flags & MF_GIVEQUEST) != 0)) - return; - - // go into chase state -seeyou: - if (actor->info->seesound) - { - int sound = actor->info->seesound; - mobj_t * emitter = actor; - - // [STRIFE] Removed DOOM random sounds. - - // [STRIFE] Only Inquisitors roar loudly here. - if (actor->type == MT_INQUISITOR) - emitter = NULL; - - S_StartSound (emitter, sound); - } - - // [STRIFE] Set threshold (kinda odd as it's still set to 0 above...) - actor->threshold = 20; - - P_SetMobjState (actor, actor->info->seestate); -} - -// -// A_RandomWalk -// -// [STRIFE] New function. -// haleyjd 09/05/10: Action routine used to meander about. -// -void A_RandomWalk(mobj_t* actor) -{ - // Standing actors do not wander. - if(actor->flags & MF_STAND) - return; - - if(actor->reactiontime) - actor->reactiontime--; // count down reaction time - else - { - // turn to a new angle - if(actor->movedir < DI_NODIR) - { - int delta; - - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - - if(delta < 0) - actor->angle += ANG90/2; - else if(delta > 0) - actor->angle -= ANG90/2; - } - - // try moving - if(--actor->movecount < 0 || !P_Move(actor)) - { - P_NewRandomDir(actor); - actor->movecount += 5; - } - } -} - -// -// A_FriendLook -// -// [STRIFE] New function -// haleyjd 09/05/10: Action function used mostly by mundane characters such as -// peasants. -// -void A_FriendLook(mobj_t* actor) -{ - mobj_t *soundtarget = actor->subsector->sector->soundtarget; - - actor->threshold = 0; - - if(soundtarget && soundtarget->flags & MF_SHOOTABLE) - { - // Handle allies, except on maps 3 and 34 (Front Base/Movement Base) - if((actor->flags & MF_ALLY) == (soundtarget->flags & MF_ALLY) && - gamemap != 3 && gamemap != 34) - { - // STRIFE-TODO: Needs serious verification. - if(P_LookForPlayers(actor, (actor->flags & MF_GIVEQUEST) != 0)) - { - P_SetMobjState(actor, actor->info->seestate); - actor->flags |= MF_NODIALOG; - return; - } - } - else - { - actor->target = soundtarget; - - if(!(actor->flags & MF_AMBUSH) || P_CheckSight(actor, actor->target)) - { - actor->threshold = 10; - P_SetMobjState(actor, actor->info->seestate); - return; - } - } - } - - // do some idle animation - if(P_Random() < 30) - { - int t = P_Random(); - P_SetMobjState(actor, (t & 1) + actor->info->spawnstate + 1); - } - - // wander around a bit - if(!(actor->flags & MF_STAND) && P_Random() < 40) - P_SetMobjState(actor, actor->info->spawnstate + 3); -} - -// -// A_Listen -// -// [STRIFE] New function -// haleyjd 09/05/10: Action routine used to strictly listen for a target. -// -void A_Listen(mobj_t* actor) -{ - mobj_t *soundtarget; - - actor->threshold = 0; - - soundtarget = actor->subsector->sector->soundtarget; - - if(soundtarget && (soundtarget->flags & MF_SHOOTABLE)) - { - if((actor->flags & MF_ALLY) != (soundtarget->flags & MF_ALLY)) - { - actor->target = soundtarget; - - if(!(actor->flags & MF_AMBUSH) || P_CheckSight(actor, actor->target)) - { - if(actor->info->seesound) - S_StartSound(actor, actor->info->seesound); - - actor->threshold = 10; - - P_SetMobjState(actor, actor->info->seestate); - } - } - } -} - - -// -// A_Chase -// Actor has a melee attack, -// so it tries to close as fast as possible -// -// haleyjd 09/05/10: [STRIFE] Various minor changes -// -void A_Chase (mobj_t* actor) -{ - int delta; - - if (actor->reactiontime) - actor->reactiontime--; - - // modify target threshold - if (actor->threshold) - { - // haleyjd 20110204 [STRIFE]: No health <= 0 check here! - if (actor->target) - actor->threshold--; - else - actor->threshold = 0; - } - - // turn towards movement direction if not there yet - if (actor->movedir < 8) - { - actor->angle &= (7u << 29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANG90/2; - else if (delta < 0) - actor->angle += ANG90/2; - } - - if (!actor->target - || !(actor->target->flags&MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true)) - return; // got a new target - - P_SetMobjState (actor, actor->info->spawnstate); - return; - } - - // do not attack twice in a row - if (actor->flags & MF_JUSTATTACKED) - { - actor->flags &= ~MF_JUSTATTACKED; - // [STRIFE] Checks only against fastparm, not gameskill == 5 - if (!fastparm) - P_NewChaseDir (actor); - return; - } - - // check for melee attack - if (actor->info->meleestate - && P_CheckMeleeRange (actor)) - { - if (actor->info->attacksound) - S_StartSound (actor, actor->info->attacksound); - - P_SetMobjState (actor, actor->info->meleestate); - return; - } - - // check for missile attack - if (actor->info->missilestate) - { - // [STRIFE] Checks only fastparm. - if (!fastparm && actor->movecount) - { - goto nomissile; - } - - if (!P_CheckMissileRange (actor)) - goto nomissile; - - P_SetMobjState (actor, actor->info->missilestate); - - // [STRIFE] Add NODIALOG flag to disable dialog - actor->flags |= (MF_NODIALOG|MF_JUSTATTACKED); - return; - } - - // ? -nomissile: - // possibly choose another target - if (netgame - && !actor->threshold - && !P_CheckSight (actor, actor->target) ) - { - if (P_LookForPlayers(actor, true)) - return; // got a new target - } - - // chase towards player - if (--actor->movecount<0 - || !P_Move (actor)) - { - P_NewChaseDir (actor); - } - - // [STRIFE] Changes to active sound behavior: - // * Significantly more frequent - // * Acolytes have randomized wandering sounds - - // make active sound - if (actor->info->activesound && P_Random () < 38) - { - if(actor->info->activesound >= sfx_agrac1 && - actor->info->activesound <= sfx_agrac4) - { - S_StartSound(actor, sfx_agrac1 + P_Random() % 4); - } - else - S_StartSound(actor, actor->info->activesound); - } -} - - -// -// A_FaceTarget -// -// [STRIFE] -// haleyjd 09/05/10: Handling for visibility-modifying flags. -// -void A_FaceTarget (mobj_t* actor) -{ - if (!actor->target) - return; - - actor->flags &= ~MF_AMBUSH; - - actor->angle = R_PointToAngle2 (actor->x, - actor->y, - actor->target->x, - actor->target->y); - - if(actor->target->flags & MF_SHADOW) - { - // [STRIFE] increased SHADOW inaccuracy by a power of 2 - int t = P_Random(); - actor->angle += (t - P_Random()) << 22; - } - else if(actor->target->flags & MF_MVIS) - { - // [STRIFE] MVIS gives even worse aiming! - int t = P_Random(); - actor->angle += (t - P_Random()) << 23; - } -} - -// -// A_PeasantPunch -// -// [STRIFE] New function -// haleyjd 09/05/10: Attack used by Peasants as a one-time retaliation -// when the player or a monster injures them. Weak doesn't begin to -// describe it :P -// -void A_PeasantPunch(mobj_t* actor) -{ - if(!actor->target) - return; - - A_FaceTarget(actor); - if(P_CheckMeleeRange(actor)) - P_DamageMobj(actor->target, actor, actor, 2 * (P_Random() % 5) + 2); -} - -// -// A_ReaverAttack -// -// [STRIFE] New function -// haleyjd 09/06/10: Action routine used by Reavers to fire bullets. -// Also apparently used by Inquistors, though they don't seem to use -// it too often, as they're content to blow your face off with their -// HE grenades instead. -// -void A_ReaverAttack(mobj_t* actor) -{ - int i = 0; - fixed_t slope; - - if(!actor->target) - return; - - S_StartSound(actor, sfx_reavat); - A_FaceTarget(actor); - - slope = P_AimLineAttack(actor, actor->angle, 2048*FRACUNIT); - - do - { - int t = P_Random(); - angle_t shootangle = actor->angle + ((t - P_Random()) << 20); - int damage = 3*((P_Random() & 7) + 1); - - P_LineAttack(actor, shootangle, 2048*FRACUNIT, slope, damage); - ++i; - } - while(i < 3); -} - -// -// A_BulletAttack -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for generic bullet attacks. Used by -// a lot of different characters, including Acolytes, Rebels, and Macil. -// -void A_BulletAttack(mobj_t* actor) -{ - int t, damage; - fixed_t slope; - angle_t shootangle; - - if(!actor->target) - return; - - S_StartSound(actor, sfx_rifle); - A_FaceTarget(actor); - - slope = P_AimLineAttack(actor, actor->angle, 2048*FRACUNIT); - t = P_Random(); - shootangle = ((t - P_Random()) << 19) + actor->angle; - damage = 3 * (P_Random() % 5 + 1); - - P_LineAttack(actor, shootangle, 2048*FRACUNIT, slope, damage); -} - -// -// A_CheckTargetVisible -// -// [STRIFE] New function -// haleyjd 09/06/10: Action routine which sets a thing back to its -// seestate at random, or if it cannot see its target, or its target -// is dead. Used by diverse actors. -// -void A_CheckTargetVisible(mobj_t* actor) -{ - A_FaceTarget(actor); - - if(P_Random() >= 30) - { - mobj_t *target = actor->target; - - if(!target || target->health <= 0 || !P_CheckSight(actor, target) || - P_Random() < 40) - { - P_SetMobjState(actor, actor->info->seestate); - } - } -} - -// -// A_SentinelAttack -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function implementing the Sentinel's laser attack -// villsa 09/06/10 implemented -// -void A_SentinelAttack(mobj_t* actor) -{ - mobj_t* mo; - mobj_t* mo2; - fixed_t x; - fixed_t y; - fixed_t z; - angle_t an; - int i; - - mo = P_SpawnFacingMissile(actor, actor->target, MT_L_LASER); - an = actor->angle >> ANGLETOFINESHIFT; - - if(mo->momy | mo->momx) // villsa - fixed typo (yes, they actually used '|' instead of'||') - { - for(i = 8; i > 1; i--) - { - x = mo->x + FixedMul(mobjinfo[MT_L_LASER].radius * i, finecosine[an]); - y = mo->y + FixedMul(mobjinfo[MT_L_LASER].radius * i, finesine[an]); - z = mo->z + i * (mo->momz >> 2); - mo2 = P_SpawnMobj(x, y, z, MT_R_LASER); - mo2->target = actor; - mo2->momx = mo->momx; - mo2->momy = mo->momy; - mo2->momz = mo->momz; - P_CheckMissileSpawn(mo2); - } - } - - mo->z += mo->momz >> 2; -} - -// -// A_StalkerThink -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function to drive Stalker logic. -// -void A_StalkerThink(mobj_t* actor) -{ - statenum_t statenum; - - if(actor->flags & MF_NOGRAVITY) - { - if(actor->ceilingz - actor->info->height <= actor->z) - return; - statenum = S_SPID_11; // 1020 - } - else - statenum = S_SPID_18; // 1027 - - P_SetMobjState(actor, statenum); -} - -// -// A_StalkerSetLook -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function to marshall transitions to the -// Stalker's spawnstate. -// -void A_StalkerSetLook(mobj_t* actor) -{ - statenum_t statenum; - - if(!actor) // weird; totally unnecessary. - return; - - if(actor->flags & MF_NOGRAVITY) - { - if(actor->state->nextstate == S_SPID_01) // 1010 - return; - statenum = S_SPID_01; // 1010 - } - else - { - if(actor->state->nextstate == S_SPID_02) // 1011 - return; - statenum = S_SPID_02; // 1011 - } - - P_SetMobjState(actor, statenum); -} - -// -// A_StalkerDrop -// -// [STRIFE] New function -// haleyjd 09/06/10: Dead simple: removes NOGRAVITY status. -// -void A_StalkerDrop(mobj_t* actor) -{ - actor->flags &= ~MF_NOGRAVITY; -} - -// -// A_StalkerScratch -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for Stalker's attack. -// -void A_StalkerScratch(mobj_t* actor) -{ - if(actor->flags & MF_NOGRAVITY) - { - // Drop him down before he can attack - P_SetMobjState(actor, S_SPID_11); // 1020 - return; - } - - if(!actor->target) - return; - - A_FaceTarget(actor); - if(P_CheckMeleeRange(actor)) - P_DamageMobj(actor->target, actor, actor, 2 * (P_Random() % 8) + 2); -} - -// -// A_FloatWeave -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function which is responsible for floating -// actors' constant upward and downward movement. Probably a really bad -// idea in retrospect given how dodgy the 3D clipping implementation is. -// -void A_FloatWeave(mobj_t* actor) -{ - fixed_t height; - fixed_t z; - - if(actor->threshold) - return; - - if(actor->flags & MF_INFLOAT) - return; - - height = actor->info->height; // v2 - z = actor->floorz + 96*FRACUNIT; // v1 - - if ( z > actor->ceilingz - height - 16*FRACUNIT ) - z = actor->ceilingz - height - 16*FRACUNIT; - - if ( z >= actor->z ) - actor->momz += FRACUNIT; - else - actor->momz -= FRACUNIT; - - if ( z == actor->z ) - actor->threshold = 4; - else - actor->threshold = 8; -} - -// -// A_RobotMelee -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for Reaver and Templar melee attacks. -// -void A_RobotMelee(mobj_t* actor) -{ - if(!actor->target) - return; - - A_FaceTarget(actor); - if(P_CheckMeleeRange(actor)) - { - S_StartSound(actor, sfx_revbld); - P_DamageMobj(actor->target, actor, actor, 3 * (P_Random() % 8 + 1)); - } -} - -// -// A_TemplarMauler -// -// [STRIFE] New function -// haleyjd 09/06/10: Exactly what it sounds like. Kicks your ass. -// -void A_TemplarMauler(mobj_t* actor) -{ - int i, t; - int angle; - int bangle; - int damage; - int slope; - - if(!actor->target) - return; - - S_StartSound(actor, sfx_pgrdat); - A_FaceTarget(actor); - bangle = actor->angle; - slope = P_AimLineAttack(actor, bangle, 2048*FRACUNIT); - - for(i = 0; i < 10; i++) - { - // haleyjd 09/06/10: Very carefully preserved order of P_Random calls - damage = (P_Random() & 4) * 2; - t = P_Random(); - angle = bangle + ((t - P_Random()) << 19); - t = P_Random(); - slope = ((t - P_Random()) << 5) + slope; - P_LineAttack(actor, angle, 2112*FRACUNIT, slope, damage); - } -} - -// -// A_CrusaderAttack -// -// villsa [STRIFE] new codepointer -// 09/06/10: Action function for the Crusader's Flamethrower. -// Very similar to the player's flamethrower, seeing how it was ripped -// off a Crusader by the Rat People ;) -// -void A_CrusaderAttack(mobj_t* actor) -{ - if(!actor->target) - return; - - actor->z += (8*FRACUNIT); - - if(P_CheckRobotRange(actor)) - { - A_FaceTarget(actor); - actor->angle -= (ANG90 / 8); - P_SpawnFacingMissile(actor, actor->target, MT_C_FLAME); - } - else if(P_CheckMissileRange(actor)) - { - A_FaceTarget(actor); - actor->z += (16*FRACUNIT); - P_SpawnFacingMissile(actor, actor->target, MT_C_MISSILE); - - actor->angle -= (ANG45 / 32); - actor->z -= (16*FRACUNIT); - P_SpawnFacingMissile(actor, actor->target, MT_C_MISSILE); - - actor->angle += (ANG45 / 16); - P_SpawnFacingMissile(actor, actor->target, MT_C_MISSILE); - - P_SetMobjState(actor, actor->info->seestate); - actor->reactiontime += 15; - } - else - P_SetMobjState(actor, actor->info->seestate); - - actor->z -= (8*FRACUNIT); -} - -// -// A_CrusaderLeft -// -// villsa [STRIFE] new codepointer -// -void A_CrusaderLeft(mobj_t* actor) -{ - mobj_t* mo; - - actor->angle += (ANG90 / 16); - mo = P_SpawnFacingMissile(actor, actor->target, MT_C_FLAME); - mo->momz = FRACUNIT; - mo->z += (16*FRACUNIT); - -} - -// -// A_CrusaderRight -// -// villsa [STRIFE] new codepointer -// -void A_CrusaderRight(mobj_t* actor) -{ - mobj_t* mo; - - actor->angle -= (ANG90 / 16); - mo = P_SpawnFacingMissile(actor, actor->target, MT_C_FLAME); - mo->momz = FRACUNIT; - mo->z += (16*FRACUNIT); -} - -// -// A_CheckTargetVisible2 -// -// [STRIFE] New function -// haleyjd 09/06/10: Mostly the same as CheckTargetVisible, except without -// the randomness. -// -void A_CheckTargetVisible2(mobj_t* actor) -{ - if(!actor->target || actor->target->health <= 0 || - !P_CheckSight(actor, actor->target)) - { - P_SetMobjState(actor, actor->info->seestate); - } -} - -// -// A_InqFlyCheck -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function to check if an Inquisitor wishes -// to take to flight. -// -void A_InqFlyCheck(mobj_t* actor) -{ - if(!actor->target) - return; - - A_FaceTarget(actor); - - // if not in "robot" range, shoot grenades. - if(!P_CheckRobotRange(actor)) - P_SetMobjState(actor, S_ROB3_14); // 1061 - - if(actor->z != actor->target->z) - { - // Take off all zig! - if(actor->z + actor->height + 54*FRACUNIT < actor->ceilingz) - P_SetMobjState(actor, S_ROB3_17); // 1064 - } -} - -// -// A_InqGrenade -// -// villsa [STRIFE] new codepointer -// 09/06/10: Inquisitor grenade attack action routine. -// -void A_InqGrenade(mobj_t* actor) -{ - mobj_t* mo; - - if(!actor->target) - return; - - A_FaceTarget(actor); - - actor->z += MAXRADIUS; - - // grenade 1 - actor->angle -= (ANG45 / 32); - mo = P_SpawnFacingMissile(actor, actor->target, MT_INQGRENADE); - mo->momz += (9*FRACUNIT); - - // grenade 2 - actor->angle += (ANG45 / 16); - mo = P_SpawnFacingMissile(actor, actor->target, MT_INQGRENADE); - mo->momz += (16*FRACUNIT); - - actor->z -= MAXRADIUS; -} - -// -// A_InqTakeOff -// -// [STRIFE] New function -// haleyjd 09/06/10: Makes an Inquisitor start flying. -// -void A_InqTakeOff(mobj_t* actor) -{ - angle_t an; - fixed_t speed = actor->info->speed * (2 * FRACUNIT / 3); - fixed_t dist; - - if(!actor->target) - return; - - S_StartSound(actor, sfx_inqjmp); - - actor->z += 64 * FRACUNIT; - - A_FaceTarget(actor); - - an = actor->angle >> ANGLETOFINESHIFT; - - actor->momx = FixedMul(finecosine[an], speed); - actor->momy = FixedMul(finesine[an], speed); - - dist = P_AproxDistance(actor->target->x - actor->x, - actor->target->y - actor->y); - - dist /= speed; - if(dist < 1) - dist = 1; - - actor->momz = (actor->target->z - actor->z) / dist; - actor->reactiontime = 60; - actor->flags |= MF_NOGRAVITY; -} - -// -// A_InqFly -// -// [STRIFE] New function -// haleyjd 09/06/10: Handles an Inquisitor in flight. -// -void A_InqFly(mobj_t* actor) -{ - if(!(leveltime & 7)) - S_StartSound(actor, sfx_inqjmp); - - if(--actor->reactiontime < 0 || !actor->momx || !actor->momy || - actor->z <= actor->floorz) - { - // Come in for a landing. - P_SetMobjState(actor, actor->info->seestate); - actor->reactiontime = 0; - actor->flags &= ~MF_NOGRAVITY; - } -} - -// -// A_FireSigilWeapon -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for the Entity's attack. -// -void A_FireSigilWeapon(mobj_t* actor) -{ - int choice = P_Random() % 5; - - // STRIFE-TODO: Needs verification. This switch is just weird. - switch(choice) - { - case 0: - A_ProgrammerAttack(actor); - break; - // ain't not seen no case 1, bub... - case 2: - A_FireSigilEOffshoot(actor); - break; - case 3: - A_SpectreCAttack(actor); - break; - case 4: - A_SpectreDAttack(actor); - break; - case 5: // BUG: never used? wtf were they thinking? - A_SpectreEAttack(actor); - break; - default: - break; - } -} - -// -// A_ProgrammerAttack -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for the Programmer's main -// attack; equivalent to the player's first Sigil. -// -void A_ProgrammerAttack(mobj_t* actor) -{ - mobj_t *mo; - - if(!actor->target) - return; - - mo = P_SpawnMobj(actor->target->x, actor->target->y, ONFLOORZ, - MT_SIGIL_A_GROUND); - mo->threshold = 25; - mo->target = actor; - mo->health = -2; - mo->tracer = actor->target; -} - -// -// A_Sigil_A_Action -// -// [STRIFE] New function -// haleyjd 09/06/10: Called by MT_SIGIL_A_GROUND to zot anyone nearby with -// corny looking lightning bolts. -// -void A_Sigil_A_Action(mobj_t* actor) -{ - int t, x, y, type; - mobj_t *mo; - - if(actor->threshold) - actor->threshold--; - - t = P_Random(); - actor->momx += ((t & 3) - (P_Random() & 3)) << FRACBITS; - t = P_Random(); - actor->momy += ((t & 3) - (P_Random() & 3)) << FRACBITS; - - t = P_Random(); - x = 50*FRACUNIT * ((t & 3) - (P_Random() & 3)) + actor->x; - t = P_Random(); - y = 50*FRACUNIT * ((t & 3) - (P_Random() & 3)) + actor->y; - - if(actor->threshold <= 25) - type = MT_SIGIL_A_ZAP_LEFT; - else - type = MT_SIGIL_A_ZAP_RIGHT; - - mo = P_SpawnMobj(x, y, ONCEILINGZ, type); - mo->momz = -18 * FRACUNIT; - mo->target = actor->target; - mo->health = actor->health; - - mo = P_SpawnMobj(actor->x, actor->y, ONCEILINGZ, MT_SIGIL_A_ZAP_RIGHT); - mo->momz = -18 * FRACUNIT; - mo->target = actor->target; - mo->health = actor->health; -} - -// -// A_SpectreEAttack -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for the Loremaster's Spectre. -// Equivalent to the player's final Sigil attack. -// -void A_SpectreEAttack(mobj_t* actor) -{ - mobj_t *mo; - - if(!actor->target) - return; - - mo = P_SpawnMissile(actor, actor->target, MT_SIGIL_SE_SHOT); - mo->health = -2; -} - -// -// A_SpectreCAttack -// -// villsa [STRIFE] new codepointer -// 09/06/10: Action routine for the Oracle's Spectre. Equivalent to the player's -// third Sigil attack. -// -void A_SpectreCAttack(mobj_t* actor) -{ - mobj_t* mo; - int i; - - if(!actor->target) - return; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + (32*FRACUNIT), MT_SIGIL_A_ZAP_RIGHT); - mo->momz = -(18*FRACUNIT); - mo->target = actor; - mo->health = -2; - mo->tracer = actor->target; - - actor->angle -= ANG90; - for(i = 0; i < 20; i++) - { - actor->angle += (ANG90 / 10); - mo = P_SpawnMortar(actor, MT_SIGIL_C_SHOT); - mo->health = -2; - mo->z = actor->z + (32*FRACUNIT); - } - actor->angle -= ANG90; -} - -// -// A_AlertSpectreC -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function called by the Oracle when it is -// killed. Finds an MT_SPECTRE_C anywhere on the map and awakens it. -// -void A_AlertSpectreC(mobj_t* actor) -{ - thinker_t *th; - - for(th = thinkercap.next; th != &thinkercap; th = th->next) - { - if(th->function.acp1 == (actionf_p1)P_MobjThinker) - { - mobj_t *mo = (mobj_t *)th; - - if(mo->type == MT_SPECTRE_C) - { - P_SetMobjState(mo, mo->info->seestate); - mo->target = actor->target; - return; - } - } - } -} - -// -// A_Sigil_E_Action -// -// villsa [STRIFE] new codepointer -// 09/06/10: Action routine for Sigil "E" shots. Spawns the room-filling -// lightning bolts that seem to often do almost nothing. -// -void A_Sigil_E_Action(mobj_t* actor) -{ - actor->angle += ANG90; - P_SpawnMortar(actor, MT_SIGIL_E_OFFSHOOT); - - actor->angle -= ANG180; - P_SpawnMortar(actor, MT_SIGIL_E_OFFSHOOT); - - actor->angle += ANG90; - P_SpawnMortar(actor, MT_SIGIL_E_OFFSHOOT); - -} - -// -// A_SigilTrail -// -// villsa [STRIFE] new codepointer -// -void A_SigilTrail(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x - actor->momx, - actor->y - actor->momy, - actor->z, MT_SIGIL_TRAIL); - - mo->angle = actor->angle; - mo->health = actor->health; - -} - -// -// A_SpectreDAttack -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function for Macil's Spectre. -// Equivalent of the player's fourth Sigil attack. -// -void A_SpectreDAttack(mobj_t* actor) -{ - mobj_t *mo; - - if(!actor->target) - return; - - mo = P_SpawnMissile(actor, actor->target, MT_SIGIL_SD_SHOT); - mo->health = -2; - mo->tracer = actor->target; -} - -// -// A_FireSigilEOffshoot -// -// [STRIFE] New function -// haleyjd 09/06/10: Action function to fire part of a Sigil E -// attack. Used at least by the Entity. -// -void A_FireSigilEOffshoot(mobj_t* actor) -{ - mobj_t *mo; - - if(!actor->target) - return; - - mo = P_SpawnMissile(actor, actor->target, MT_SIGIL_E_OFFSHOOT); - mo->health = -2; -} - -// -// A_ShadowOff -// -// villsa [STRIFE] new codepointer -// 09/06/10: Disables SHADOW and MVIS flags. -// -void A_ShadowOff(mobj_t* actor) -{ - actor->flags &= ~(MF_SHADOW|MF_MVIS); -} - -// -// A_ModifyVisibility -// -// villsa [STRIFE] new codepointer -// 09/06/10: Turns on SHADOW, and turns off MVIS. -// -void A_ModifyVisibility(mobj_t* actor) -{ - actor->flags |= MF_SHADOW; - actor->flags &= ~MF_MVIS; -} - -// -// A_ShadowOn -// -// villsa [STRIFE] new codepointer -// 09/06/10: Turns on SHADOW and MVIS. -// -void A_ShadowOn(mobj_t* actor) -{ - actor->flags |= (MF_SHADOW|MF_MVIS); -} - -// -// A_SetTLOptions -// -// villsa [STRIFE] new codepointer -// 09/06/10: Sets SHADOW and/or MVIS based on the thing's spawnpoint options. -// -void A_SetTLOptions(mobj_t* actor) -{ - if(actor->spawnpoint.options & MTF_TRANSLUCENT) - actor->flags |= MF_SHADOW; - if(actor->spawnpoint.options & MTF_MVIS) - actor->flags |= MF_MVIS; -} - -// -// A_BossMeleeAtk -// -// villsa [STRIFE] new codepointer -// 09/06/10: Gratuitous melee attack used by multiple boss characters, -// just for the sake of having one. It's not like anybody in their right -// mind would get close to any of the maniacs that use this ;) -// -void A_BossMeleeAtk(mobj_t* actor) -{ - if(!actor->target) - return; - - P_DamageMobj(actor->target, actor, actor, 10 * (P_Random() & 9)); -} - -// -// A_BishopAttack -// -// villsa [STRIFE] new codepointer -// 09/06/10: Bishop's homing missile attack. -// -void A_BishopAttack(mobj_t* actor) -{ - mobj_t* mo; - - if(!actor->target) - return; - - actor->z += MAXRADIUS; - - mo = P_SpawnMissile(actor, actor->target, MT_SEEKMISSILE); - mo->tracer = actor->target; - - actor->z -= MAXRADIUS; -} - -// -// A_FireHookShot -// -// villsa [STRIFE] new codepointer -// 09/06/10: Action function for the Loremaster's hookshot attack. -// -void A_FireHookShot(mobj_t* actor) -{ - if(!actor->target) - return; - - P_SpawnMissile(actor, actor->target, MT_HOOKSHOT); -} - -// -// A_FireChainShot -// -// villsa [STRIFE] new codepointer -// 09/06/10: Action function for the hookshot projectile. Spawns echoes -// to create a chain-like appearance. -// -void A_FireChainShot(mobj_t* actor) -{ - S_StartSound(actor, sfx_tend); - - P_SpawnMobj(actor->x, actor->y, actor->z, MT_CHAINSHOT); // haleyjd: fixed type - - P_SpawnMobj(actor->x - (actor->momx >> 1), - actor->y - (actor->momy >> 1), - actor->z, MT_CHAINSHOT); - - P_SpawnMobj(actor->x - actor->momx, - actor->y - actor->momy, - actor->z, MT_CHAINSHOT); -} - -// -// A_MissileSmoke -// -// villsa [STRIFE] new codepointer -// -void A_MissileSmoke(mobj_t* actor) -{ - mobj_t* mo; - - S_StartSound(actor, sfx_rflite); - P_SpawnPuff(actor->x, actor->y, actor->z); - mo = P_SpawnMobj(actor->x - actor->momx, - actor->y - actor->momy, - actor->z, MT_MISSILESMOKE); - - mo->momz = FRACUNIT; -} - -// -// A_SpawnSparkPuff -// -// villsa [STRIFE] new codepointer -// -void A_SpawnSparkPuff(mobj_t* actor) -{ - int r; - mobj_t* mo; - fixed_t x; - fixed_t y; - - r = P_Random(); - x = (10*FRACUNIT) * ((r & 3) - (P_Random() & 3)) + actor->x; - r = P_Random(); - y = (10*FRACUNIT) * ((r & 3) - (P_Random() & 3)) + actor->y; - - mo = P_SpawnMobj(x, y, actor->z, MT_SPARKPUFF); - P_SetMobjState(mo, S_BNG4_01); // 199 - mo->momz = FRACUNIT; -} - - -// haleyjd 09/05/10: [STRIFE] Removed: -// A_PosAttack, A_SPosAttack, A_CPosAttack, A_CPosRefire, A_SpidRefire, -// A_BspiAttack, A_TroopAttack, A_SargAttack, A_HeadAttack, A_CyberAttack, -// A_BruisAttack, A_SkelMissile - - -int TRACEANGLE = 0xE000000; // villsa [STRIFE] changed from 0xC000000 to 0xE000000 - -// -// A_Tracer -// -void A_Tracer (mobj_t* actor) -{ - angle_t exact; - fixed_t dist; - fixed_t slope; - mobj_t* dest; - //mobj_t* th; - - // villsa [STRIFE] removed all randomization and puff code - - // adjust direction - dest = actor->tracer; - - if(!dest || dest->health <= 0) - return; - - // change angle - exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); - - if(exact != actor->angle) - { - // villsa [STRIFE] slightly different algorithm - if(exact - actor->angle <= 0x80000000) - { - actor->angle += TRACEANGLE; - if(exact - actor->angle > 0x80000000) - actor->angle = exact; - } - else - { - actor->angle -= TRACEANGLE; - if (exact - actor->angle < 0x80000000) - actor->angle = exact; - } - } - - exact = actor->angle>>ANGLETOFINESHIFT; - actor->momx = FixedMul (actor->info->speed, finecosine[exact]); - actor->momy = FixedMul (actor->info->speed, finesine[exact]); - - // change slope - dist = P_AproxDistance (dest->x - actor->x, - dest->y - actor->y); - - dist = dist / actor->info->speed; - - if (dist < 1) - dist = 1; - slope = (dest->z+40*FRACUNIT - actor->z) / dist; - - if (slope < actor->momz) - actor->momz -= FRACUNIT/8; - else - actor->momz += FRACUNIT/8; -} - -// -// A_ProgrammerMelee -// -// villsa [STRIFE] new codepointer -// 09/08/10: Melee attack for the Programmer. -// haleyjd - fixed damage formula -// -void A_ProgrammerMelee(mobj_t* actor) -{ - if(!actor->target) - return; - - A_FaceTarget(actor); - if(P_CheckMeleeRange(actor)) - { - int damage = 6 * (P_Random() % 10 + 1); - - S_StartSound(actor, sfx_mtalht); - P_DamageMobj(actor->target, actor, actor, damage); - } - -} - -// haleyjd 09/05/10: [STRIFE] Removed: -// A_SkelWhoosh, A_SkelFist, PIT_VileCheck, A_VileChase, A_VileStart, -// A_StartFire, A_FireCrackle, A_Fire, A_VileTarget, A_VileAttack -// A_FatRaise, A_FatAttack1, A_FatAttack2, A_FatAttack3, A_SkullAttack, -// A_PainShootSkull, A_PainAttack, A_PainDie - -// -// A_Scream -// -// villsa [STRIFE] -// * Has no random death sounds, so play deathsound directly -// * Full-volume roars for the Entity and Inquisitor. -// -void A_Scream(mobj_t* actor) -{ - if(!actor->info->deathsound) - return; - - // Check for bosses. - if(actor->type == MT_ENTITY || actor->type == MT_INQUISITOR) - S_StartSound(NULL, actor->info->deathsound); // full volume - else - S_StartSound(actor, actor->info->deathsound); -} - -// -// A_XScream -// -// villsa [STRIFE] -// * Robots will play deathsound while non-robots play the slop sfx -// -void A_XScream(mobj_t* actor) -{ - int sound; - - if(actor->flags & MF_NOBLOOD && actor->info->deathsound) - sound = actor->info->deathsound; - else - sound = sfx_slop; - - S_StartSound(actor, sound); -} - -// -// A_Pain -// -// villsa [STRIFE] -// * Play random peasant sounds; otherwise play painsound directly -// -void A_Pain(mobj_t* actor) -{ - int sound = actor->info->painsound; - - if(sound) - { - if(sound >= sfx_pespna && sound <= sfx_pespnd) - sound = sfx_pespna + (P_Random() % 4); - - S_StartSound(actor, sound); - } -} - -// -// A_PeasantCrash -// -// villsa [STRIFE] new codepointer -// 09/08/10: Called from Peasant's "crash" state (not to be confused with -// Heretic crash states), which is invoked when the Peasant has taken -// critical but sub-fatal damage. It will "bleed out" the rest of its -// health by calling this function repeatedly. -// -void A_PeasantCrash(mobj_t* actor) -{ - // Set NODIALOG, because you probably wouldn't feel like talking either - // if somebody just stabbed you in the gut with a punch dagger... - actor->flags |= MF_NODIALOG; - - if(!(P_Random() % 5)) - { - A_Pain(actor); // inlined in asm - actor->health--; - } - - if(actor->health <= 0) - P_KillMobj(actor->target, actor); -} - -// -// A_Fall -// -// [STRIFE] -// * Set NODIALOG, and clear NOGRAVITY and SHADOW -// -void A_Fall (mobj_t *actor) -{ - // villsa [STRIFE] set NODIALOG flag to stop dialog - actor->flags |= MF_NODIALOG; - - // actor is on ground, it can be walked over - // villsa [STRIFE] remove nogravity/shadow flags as well - actor->flags &= ~(MF_SOLID|MF_NOGRAVITY|MF_SHADOW); -} - -// -// A_HideZombie -// -// villsa [STRIFE] new codepointer -// Used by the "Becoming" Acolytes on the Loremaster's level. -// -void A_HideZombie(mobj_t* actor) -{ - line_t junk; - - junk.tag = 999; - EV_DoDoor(&junk, vld_blazeClose); - - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// -// A_MerchantPain -// -// villsa [STRIFE] new codepointer -// 09/08/10: Pain pointer for merchant characters. They close up shop for -// a while and set off the alarm. -// -void A_MerchantPain(mobj_t* actor) -{ - line_t junk; - - junk.tag = 999; - EV_DoDoor(&junk, vld_shopClose); - - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// haleyjd 09/05/10: Removed unused CheckBossEnd Choco routine. - -// haleyjd 09/05/10: [STRIFE] Removed: -// A_Hoof, A_Metal, A_BabyMetal, A_OpenShotgun2, A_LoadShotgun2, -// A_CloseShotgun2, A_BrainAwake, A_BrainPain, A_BrainScream, A_BrainExplode, -// A_BrainDie, A_BrainSpit, A_SpawnSound, A_SpawnFly - -// -// A_ProgrammerDie -// -// villsa [STRIFE] new codepointer -// 09/08/10: Action routine for the Programmer's grisly death. Spawns the -// separate mechanical base object and sends it flying off in some random -// direction. -// -void A_ProgrammerDie(mobj_t* actor) -{ - int r; - angle_t an; - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 24*FRACUNIT, MT_PROGRAMMERBASE); - - // haleyjd 20110223: fix add w/ANG180 - r = P_Random(); - an = ((r - P_Random()) << 22) + actor->angle + ANG180; - mo->angle = an; - - P_ThrustMobj(mo, an, mo->info->speed); // inlined in asm - - mo->momz = P_Random() << 9; -} - -// -// A_InqTossArm -// -// villsa [STRIFE] new codepointer -// 09/08/10: Inquisitor death action. Spawns an arm and tosses it. -// -void A_InqTossArm(mobj_t* actor) -{ - int r; - angle_t an; - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + (24*FRACUNIT), MT_INQARM); - - r = P_Random(); - an = ((r - P_Random()) << 22) + actor->angle - ANG90; - mo->angle = an; - - P_ThrustMobj(mo, an, mo->info->speed); // inlined in asm - - mo->momz = P_Random() << 10; -} - -// -// A_SpawnSpectreA -// -// villsa [STRIFE] new codepointer (unused) -// 09/08/10: Spawns Spectre A. Or would, if anything actually used this. -// This is evidence that the Programmer's spectre, which appears in the -// Catacombs in the final version, was originally meant to be spawned -// after his death. -// -void A_SpawnSpectreA(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_A); - mo->momz = P_Random() << 9; -} - -// -// A_SpawnSpectreB -// -// villsa [STRIFE] new codepointer -// 09/08/10: Action function to spawn the Bishop's spectre. -// -void A_SpawnSpectreB(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_B); - mo->momz = P_Random() << 9; -} - -// -// A_SpawnSpectreC -// -// villsa [STRIFE] new codepointer (unused) -// 09/08/10: Action function to spawn the Oracle's spectre. Also -// unused, because the Oracle's spectre is already present on the -// map and is awakened on his death. Also left over from the -// unreleased beta (and demo) versions. -// -void A_SpawnSpectreC(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_C); - mo->momz = P_Random() << 9; -} - -// -// A_SpawnSpectreD -// -// villsa [STRIFE] new codepointer -// 09/08/10: Action function to spawn Macil's Spectre. -// -void A_SpawnSpectreD(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_D); - mo->momz = P_Random() << 9; -} - -// -// A_SpawnSpectreE -// -// villsa [STRIFE] new codepointer -// 09/08/10: Action function to spawn the Loremaster's Spectre. -// -void A_SpawnSpectreE(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPECTRE_E); - mo->momz = P_Random() << 9; -} - -// [STRIFE] New statics - Remember the Entity's spawning position. -static fixed_t entity_pos_x = 0; -static fixed_t entity_pos_y = 0; -static fixed_t entity_pos_z = 0; - -// -// A_SpawnEntity -// -// villsa [STRIFE] new codepointer -// 09/08/10: You will fall on your knees before the True God, the One Light. -// -void A_SpawnEntity(mobj_t* actor) -{ - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 70*FRACUNIT, MT_ENTITY); - mo->momz = 5*FRACUNIT; - - entity_pos_x = mo->x; - entity_pos_y = mo->y; - entity_pos_z = mo->z; -} - -// -// P_ThrustMobj -// -// villsa [STRIFE] new function -// Thrusts an thing in a specified force/direction -// Beware! This is inlined everywhere in the asm -// -void P_ThrustMobj(mobj_t *actor, angle_t angle, fixed_t force) -{ - angle_t an = angle >> ANGLETOFINESHIFT; - actor->momx += FixedMul(finecosine[an], force); - actor->momy += FixedMul(finesine[an], force); -} - -// -// A_EntityDeath -// -// [STRIFE] -// haleyjd 09/08/10: The death of the Entity's spectre brings forth -// three subentities, which are significantly less dangerous on their -// own but threatening together. -// -void A_EntityDeath(mobj_t* actor) -{ - mobj_t *subentity; - angle_t an; - fixed_t dist; - - dist = 2 * mobjinfo[MT_SUBENTITY].radius; - - // Subentity One - an = actor->angle >> ANGLETOFINESHIFT; - subentity = P_SpawnMobj(FixedMul(finecosine[an], dist) + entity_pos_x, - FixedMul(finesine[an], dist) + entity_pos_y, - entity_pos_z, MT_SUBENTITY); - subentity->target = actor->target; - A_FaceTarget(subentity); - P_ThrustMobj(subentity, subentity->angle, 625 << 13); - - // Subentity Two - an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; - subentity = P_SpawnMobj(FixedMul(finecosine[an], dist) + entity_pos_x, - FixedMul(finesine[an], dist) + entity_pos_y, - entity_pos_z, MT_SUBENTITY); - subentity->target = actor->target; - P_ThrustMobj(subentity, actor->angle + ANG90, 4); - A_FaceTarget(subentity); - - // Subentity Three - an = (actor->angle - ANG90) >> ANGLETOFINESHIFT; - subentity = P_SpawnMobj(FixedMul(finecosine[an], dist) + entity_pos_x, - FixedMul(finesine[an], dist) + entity_pos_y, - entity_pos_z, MT_SUBENTITY); - subentity->target = actor->target; - P_ThrustMobj(subentity, actor->angle - ANG90, 4); - A_FaceTarget(subentity); -} - -// -// A_SpawnZombie -// -// villsa [STRIFE] new codepointer -// -void A_SpawnZombie(mobj_t* actor) -{ - P_SpawnMobj(actor->x, actor->y, actor->z, MT_ZOMBIE); -} - -// -// A_ZombieInSpecialSector -// -// villsa [STRIFE] new codepointer -// -void A_ZombieInSpecialSector(mobj_t* actor) -{ - sector_t* sector; - fixed_t force; - angle_t angle; - int tagval; - - sector = actor->subsector->sector; - if(actor->z != sector->floorheight) - return; - - if(sector->special <= 15) - P_DamageMobj(actor, NULL, NULL, 999); - else if(sector->special == 18) - { - tagval = sector->tag - 100; - force = (tagval % 10) << 12; - angle = (tagval / 10) << 29; - P_ThrustMobj(actor, angle, force); // inlined in asm - } -} - -// -// A_CrystalExplode -// -// villsa [STRIFE] new codepointer -// Throws out debris from the Power Crystal and sets its sector floorheight -// to the lowest surrounding floor (this is maybe the only time a direct -// level-changing action is done by an object in this fashion in any of -// the DOOM engine games... they usually call a line special instead) -// -void A_CrystalExplode(mobj_t* actor) -{ - sector_t* sector; - mobj_t* rubble; - int i; - int r; - - sector = actor->subsector->sector; - sector->lightlevel = 0; - sector->floorheight = P_FindLowestFloorSurrounding(sector); - - // spawn rubble - for(i = 0; i < 8; i++) - { - rubble = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RUBBLE1 + i); - r = P_Random(); - rubble->momx = ((r & 0x0f) - (P_Random() & 7)) << FRACBITS; - r = P_Random(); - rubble->momy = ((r & 7) - (P_Random() & 7)) << FRACBITS; - rubble->momz = ((P_Random() & 3) << FRACBITS) + (7*FRACUNIT); - } -} - -// [STRIFE] New static global - buffer used for various player messages. -static char pmsgbuffer[80]; - -// -// P_FreePrisoners -// -// haleyjd 09/08/10: [STRIFE] New function -// * Called when the prisoners get freed, obviously. Gives a -// message and awards quest token 13. -// -void P_FreePrisoners(void) -{ - int i; - - DEH_snprintf(pmsgbuffer, sizeof(pmsgbuffer), "You've freed the prisoners!"); - - for(i = 0; i < MAXPLAYERS; i++) - { - P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_QUEST13); - players[i].message = pmsgbuffer; - } -} - -// -// P_DestroyConverter -// -// haleyjd 09/08/10: [STRIFE] New function -// * Called when the converter is shut down in the factory. -// Gives several items and a message. -// -void P_DestroyConverter(void) -{ - int i; - - DEH_snprintf(pmsgbuffer, sizeof(pmsgbuffer), "You've destroyed the Converter!"); - - for(i = 0; i < MAXPLAYERS; i++) - { - P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_QUEST25); - P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_STAMINA); - P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_NEW_ACCURACY); - players[i].message = pmsgbuffer; - } -} - -// -// A_QuestMsg -// -// villsa [STRIFE] new codepointer -// Displays text based on quest item's name -// Quest item is based on actor's speed -// -void A_QuestMsg(mobj_t* actor) -{ - const char *name; - int quest; - int i; - - // get name - name = DEH_String(mobjinfo[(MT_TOKEN_QUEST1 - 1) + actor->info->speed].name); - M_StringCopy(pmsgbuffer, name, sizeof(pmsgbuffer)); // inlined in asm - - // give quest and display message to players - for(i = 0; i < MAXPLAYERS; i++) - { - quest = 1 << (actor->info->speed - 1); - players[i].message = pmsgbuffer; - players[i].questflags |= quest; - } -} - -// -// A_ExtraLightOff -// -// villsa [STRIFE] new codepointer -// 09/08/10: Called by the Power Crystal to turn off the extended -// flash of light caused by its explosion. -// -void A_ExtraLightOff(mobj_t* actor) -{ - if(!actor->target) - return; - - if(!actor->target->player) - return; - - actor->target->player->extralight = 0; -} - -// -// A_CrystalRadiusAtk -// -// villsa [STRIFE] new codepointer -// 09/08/10: Called by the power crystal when it dies. -// -void A_CrystalRadiusAtk(mobj_t* actor) -{ - P_RadiusAttack(actor, actor->target, 512); - - if(!(actor->target && actor->target->player)) - return; - - // set extralight to 5 for near full-bright - actor->target->player->extralight = 5; -} - -// -// A_DeathExplode5 -// -// villsa [STRIFE] new codepointer -// -void A_DeathExplode5(mobj_t* actor) -{ - P_RadiusAttack(actor, actor->target, 192); - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// -// A_DeathExplode1 -// -// villsa [STRIFE] new codepointer -// -void A_DeathExplode1(mobj_t* actor) -{ - P_RadiusAttack(actor, actor->target, 128); - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// -// A_DeathExplode2 -// -// villsa [STRIFE] new codepointer -// -void A_DeathExplode2(mobj_t* actor) -{ - P_RadiusAttack(actor, actor->target, 64); - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// -// A_DeathExplode3 -// -// villsa [STRIFE] new codepointer -// -void A_DeathExplode3(mobj_t* actor) -{ - P_RadiusAttack(actor, actor->target, 32); - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// -// A_RaiseAlarm -// -// villsa [STRIFE] new codepointer -// 09/08/10: Set off the infamous alarm. This is just a noise alert. -// -void A_RaiseAlarm(mobj_t* actor) -{ - if(actor->target && actor->target->player) - P_NoiseAlert(actor->target, actor); // inlined in asm -} - -// -// A_MissileTick -// villsa [STRIFE] - new codepointer -// -void A_MissileTick(mobj_t* actor) -{ - if(--actor->reactiontime <= 0) - { - P_ExplodeMissile(actor); - actor->flags &= ~MF_MISSILE; - } -} - -// -// A_SpawnGrenadeFire -// villsa [STRIFE] - new codepointer -// -void A_SpawnGrenadeFire(mobj_t* actor) -{ - P_SpawnMobj(actor->x, actor->y, actor->z, MT_PFLAME); -} - -// -// A_NodeChunk -// -// villsa [STRIFE] - new codepointer -// Throw out "nodes" from a spectral entity -// -void A_NodeChunk(mobj_t* actor) -{ - int r; - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 10*FRACUNIT, MT_NODE); - r = P_Random(); - mo->momx = ((r & 0x0f) - (P_Random() & 7)) << FRACBITS; - r = P_Random(); - mo->momy = ((r & 7) - (P_Random() & 0x0f)) << FRACBITS; - mo->momz = (P_Random() & 0x0f) << FRACBITS; -} - -// -// A_HeadChunk -// -// villsa [STRIFE] - new codepointer -// Throw out the little "eye"-like object from a spectral entity when it dies. -// -void A_HeadChunk(mobj_t* actor) -{ - int r; - mobj_t* mo; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + 10*FRACUNIT, MT_SPECTREHEAD); - r = P_Random(); - mo->momx = ((r & 7) - (P_Random() & 0x0f)) << FRACBITS; - r = P_Random(); - mo->momy = ((r & 0x0f) - (P_Random() & 7)) << FRACBITS; - mo->momz = (P_Random() & 7) << FRACBITS; -} - -// -// A_BurnSpread -// villsa [STRIFE] - new codepointer -// -void A_BurnSpread(mobj_t* actor) -{ - int t; - mobj_t* mo; - fixed_t x; - fixed_t y; - - actor->momz -= (8*FRACUNIT); - - t = P_Random(); - actor->momx += ((t & 3) - (P_Random() & 3)) << FRACBITS; - t = P_Random(); - actor->momy += ((t & 3) - (P_Random() & 3)) << FRACBITS; - - S_StartSound(actor, sfx_lgfire); - - if(actor->flags & MF_DROPPED) - return; // not the parent - - // haleyjd 20110223: match order of calls in binary - y = actor->y + (((P_Random() + 12) & 31) << FRACBITS); - x = actor->x + (((P_Random() + 12) & 31) << FRACBITS); - - // spawn child - mo = P_SpawnMobj(x, y, actor->z + (4*FRACUNIT), MT_PFLAME); - - t = P_Random(); - mo->momx += ((t & 7) - (P_Random() & 7)) << FRACBITS; - t = P_Random(); - mo->momy += ((t & 7) - (P_Random() & 7)) << FRACBITS; - mo->momz -= FRACUNIT; - mo->flags |= MF_DROPPED; - mo->reactiontime = (P_Random() & 3) + 2; -} - -// -// A_BossDeath -// -// Possibly trigger special effects -// if on first boss level -// -// haleyjd 09/17/10: [STRIFE] -// * Modified to handle all Strife bosses. -// -void A_BossDeath (mobj_t* actor) -{ - int i; - thinker_t *th; - line_t junk; - - // only the following types can be a boss: - switch(actor->type) - { - case MT_CRUSADER: - case MT_SPECTRE_A: - case MT_SPECTRE_B: - case MT_SPECTRE_C: - case MT_SPECTRE_D: - case MT_SPECTRE_E: - case MT_SUBENTITY: - case MT_PROGRAMMER: - break; - default: - return; - } - - // check for a living player - for(i = 0; i < MAXPLAYERS; i++) - { - if(playeringame[i] && players[i].health > 0) - break; - } - if(i == MAXPLAYERS) - return; // everybody's dead. - - // check for a still living boss - for(th = thinkercap.next; th != &thinkercap; th = th->next) - { - if(th->function.acp1 == (actionf_p1) P_MobjThinker) - { - mobj_t *mo = (mobj_t *)th; - - if(mo != actor && mo->type == actor->type && mo->health > 0) - return; // one is still alive. - } - } - - // Victory! - switch(actor->type) - { - case MT_CRUSADER: - junk.tag = 667; - EV_DoFloor(&junk, lowerFloorToLowest); - break; - - case MT_SPECTRE_A: - GiveVoiceObjective("VOC95", "LOG95", 0); - junk.tag = 999; - EV_DoFloor(&junk, lowerFloorToLowest); - break; - - case MT_SPECTRE_B: - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_BISHOP); - GiveVoiceObjective("VOC74", "LOG74", 0); - break; - - case MT_SPECTRE_C: - // Look for an MT_ORACLE - this is for in case the player awakened the - // Oracle's spectre without killing the Oracle, which is possible by - // looking up to max and firing the Sigil at it. If this were not done, - // a serious sequence break possibility would arise where one could - // kill both the Oracle AND Macil, possibly throwing the game out of - // sorts entirely. Too bad they thought of it ;) However this also - // causes a bug sometimes! The Oracle, in its death state, sets the - // Spectre C back to its seestate. If the Spectre C is already dead, - // it becomes an undead ghost monster. Then it's a REAL spectre ;) - for(th = thinkercap.next; th != &thinkercap; th = th->next) - { - if(th->function.acp1 == (actionf_p1) P_MobjThinker) - { - mobj_t *mo = (mobj_t *)th; - - // KILL ALL ORACLES! RAWWR! - if(mo != actor && mo->type == MT_ORACLE && mo->health > 0) - P_KillMobj(actor, mo); - } - } - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_ORACLE); - - // Bishop is dead? - verify. - if(players[0].questflags & QF_QUEST21) - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_QUEST22); - - // Macil is dead? - if(players[0].questflags & QF_QUEST24) - { - // Loremaster is dead? - if(players[0].questflags & QF_QUEST26) - { - // We wield the complete sigil, blahblah - GiveVoiceObjective("VOC85", "LOG85", 0); - } - } - else - { - // So much for prognostication! - GiveVoiceObjective("VOC87", "LOG87", 0); - } - junk.tag = 222; // Open the exit door again; - EV_DoDoor(&junk, vld_open); // Note this is NOT the Loremaster door... - break; - - case MT_SPECTRE_D: - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_MACIL); - if(players[0].questflags & QF_QUEST25) // Destroyed converter? - GiveVoiceObjective("VOC106", "LOG106", 0); - else - GiveVoiceObjective("VOC79", "LOG79", 0); - break; - - case MT_SPECTRE_E: - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_LOREMASTER); - if(!netgame) - { - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_STAMINA); - P_GiveItemToPlayer(&players[0], SPR_TOKN, MT_TOKEN_NEW_ACCURACY); - } - if(players[0].sigiltype == 4) - GiveVoiceObjective("VOC85", "LOG85", 0); - else - GiveVoiceObjective("VOC83", "LOG83", 0); - junk.tag = 666; - EV_DoFloor(&junk, lowerFloorToLowest); - break; - - case MT_SUBENTITY: - F_StartFinale(); - break; - - case MT_PROGRAMMER: - F_StartFinale(); - G_ExitLevel(0); - break; - - default: - // Real classy, Rogue. - if(actor->type) - I_Error("Error: Unconnected BossDeath id %d", actor->type); - break; - } -} - -// -// A_AcolyteSpecial -// -// villsa [STRIFE] - new codepointer -// Awards quest #7 when all the Blue Acolytes are killed in Tarnhill -// -void A_AcolyteSpecial(mobj_t* actor) -{ - int i; - thinker_t* th; - - if(actor->type != MT_GUARD8) - return; // must be MT_GUARD8 - - for(i = 0; i < MAXPLAYERS; i++) - { - if(playeringame[i] && players[i].health > 0) - break; - } - - if(i == 8) - return; - - for(th = thinkercap.next; th != &thinkercap; th = th->next) - { - if(th->function.acp1 == (actionf_p1) P_MobjThinker) - { - mobj_t *mo = (mobj_t *)th; - - // Found a living MT_GUARD8? - if(mo != actor && mo->type == actor->type && mo->health > 0) - return; - } - } - - // All MT_GUARD8 are dead, give quest token #7 to all players - for(i = 0; i < MAXPLAYERS; i++) - P_GiveItemToPlayer(&players[i], SPR_TOKN, MT_TOKEN_QUEST7); - - // play voice, give objective - GiveVoiceObjective("VOC14", "LOG14", 0); -} - -// -// A_InqChase -// villsa [STRIFE] - new codepointer -// -void A_InqChase(mobj_t* actor) -{ - S_StartSound(actor, sfx_inqact); - A_Chase(actor); -} - -// -// A_StalkerChase -// villsa [STRIFE] - new codepointer -// -void A_StalkerChase(mobj_t* actor) -{ - S_StartSound(actor, sfx_spdwlk); - A_Chase(actor); -} - -// -// A_PlayerScream -// -// [STRIFE] -// * Modified to eliminate gamemode check and to use Strife sound. -// -void A_PlayerScream (mobj_t* mo) -{ - // Default death sound. - int sound = sfx_pldeth; - - // villsa [STRIFE] don't check for gamemode - if(mo->health < -50) - { - // IF THE PLAYER DIES - // LESS THAN -50% WITHOUT GIBBING - sound = sfx_plxdth; // villsa [STRIFE] different sound - } - - S_StartSound (mo, sound); -} - -// -// A_TeleportBeacon -// -// villsa [STRIFE] - new codepointer -// -void A_TeleportBeacon(mobj_t* actor) -{ - mobj_t* mobj; - mobj_t* fog; - fixed_t fog_x; - fixed_t fog_y; - - if(actor->target != players[actor->miscdata].mo) - actor->target = players[actor->miscdata].mo; - - mobj = P_SpawnMobj(actor->x, actor->y, ONFLOORZ, MT_REBEL1); - - // haleyjd 20141024: missing code from disassembly; transfer allegiance - // originally from master player to the rebel. - mobj->miscdata = actor->miscdata; - - if(!P_TryMove(mobj, mobj->x, mobj->y)) - { - // Rebel is probably stuck in something.. too bad - P_RemoveMobj(mobj); - return; - } - - // beacon no longer special - actor->flags &= ~MF_SPECIAL; - - // 20160306: set rebel threshold - mobj->threshold = 100; - - // set rebel color and flags - mobj->flags |= ((actor->miscdata << MF_TRANSSHIFT) | MF_NODIALOG); - mobj->target = NULL; - - // double Rebel's health in deathmatch mode - if(deathmatch) - mobj->health <<= 1; - - if(actor->target) - { - mobj_t* targ = actor->target->target; - - if(targ) - { - if(targ->type != MT_REBEL1 || targ->miscdata != mobj->miscdata) - mobj->target = targ; - } - } - - P_SetMobjState(mobj, mobj->info->seestate); - mobj->angle = actor->angle; - - fog_x = mobj->x + FixedMul(20*FRACUNIT, finecosine[actor->angle>>ANGLETOFINESHIFT]); - fog_y = mobj->y + FixedMul(20*FRACUNIT, finesine[actor->angle>>ANGLETOFINESHIFT]); - - fog = P_SpawnMobj(fog_x, fog_y, mobj->z, MT_TFOG); - S_StartSound(fog, sfx_telept); - - if(--actor->health < 0) - P_RemoveMobj(actor); -} - -// -// A_BodyParts -// -// villsa [STRIFE] new codepointer -// 09/06/10: Spawns gibs when organic actors get splattered, or junk -// when robots explode. -// -void A_BodyParts(mobj_t* actor) -{ - mobjtype_t type; - mobj_t* mo; - angle_t an; - - if(actor->flags & MF_NOBLOOD) // Robots are flagged NOBLOOD - type = MT_JUNK; - else - type = MT_MEAT; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + (24*FRACUNIT), type); - P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 19)); - - an = (P_Random() << 13) / 255; - mo->angle = an << ANGLETOFINESHIFT; - - mo->momx = FixedMul(finecosine[an], (P_Random() & 0x0f) << FRACBITS); - mo->momy = FixedMul(finesine[an], (P_Random() & 0x0f) << FRACBITS); - mo->momz = (P_Random() & 0x0f) << FRACBITS; -} - -// -// A_ClaxonBlare -// -// [STRIFE] New function -// haleyjd 09/08/10: The ever-dreadful Strife alarm! -// -void A_ClaxonBlare(mobj_t* actor) -{ - // Timer ran down? - if(--actor->reactiontime < 0) - { - // reset to initial state - actor->target = NULL; - actor->reactiontime = actor->info->reactiontime; - - // listen for more noise - A_Listen(actor); - - // If we heard something, stay on for a while, - // otherwise return to spawnstate. - if(actor->target) - actor->reactiontime = 50; - else - P_SetMobjState(actor, actor->info->spawnstate); - } - - // When almost ran down, clear the soundtarget so it doesn't - // retrigger the alarm. - // Also, play the harsh, grating claxon. - if(actor->reactiontime == 2) - actor->subsector->sector->soundtarget = NULL; - else if(actor->reactiontime > 50) - S_StartSound(actor, sfx_alarm); -} - -// -// A_ActiveSound -// -// villsa [STRIFE] new codepointer -// 09/06/10: Plays an object's active sound periodically. -// -void A_ActiveSound(mobj_t* actor) -{ - if(actor->info->activesound) - { - if(!(leveltime & 7)) // haleyjd: added parens - S_StartSound(actor, actor->info->activesound); - } -} - -// -// A_ClearSoundTarget -// -// villsa [STRIFE] new codepointer -// 09/06/10: Clears the actor's sector soundtarget, so that the actor -// will not be continually alerted/awakened ad infinitum. Used by -// shopkeepers. -// -void A_ClearSoundTarget(mobj_t* actor) -{ - actor->subsector->sector->soundtarget = NULL; -} - -// -// A_DropBurnFlesh -// -// villsa [STRIFE] new codepointer -// -void A_DropBurnFlesh(mobj_t* actor) -{ - mobj_t* mo; - mobjtype_t type; - - type = actor->type; - - mo = P_SpawnMobj(actor->x, actor->y, actor->z + (24*FRACUNIT), MT_BURNDROP); - mo->momz = -FRACUNIT; - - actor->type = MT_SFIREBALL; - P_RadiusAttack(actor, actor, 64); - actor->type = type; -} - -// -// A_FlameDeath -// -// villsa [STRIFE] new codepointer -// 09/06/10: Death animation for flamethrower fireballs. -// -void A_FlameDeath(mobj_t* actor) -{ - actor->flags |= MF_NOGRAVITY; - actor->momz = (P_Random() & 3) << FRACBITS; -} - -// -// A_ClearForceField -// -// villsa [STRIFE] new codepointer -// check for all matching lines in the sector -// and disable blocking/midtextures -// -void A_ClearForceField(mobj_t* actor) -{ - int i; - sector_t *sec; - line_t *secline; - - actor->flags &= ~(MF_SOLID|MF_SPECIAL); - sec = actor->subsector->sector; - - if(!sec->linecount) - return; - - for(i = 0; i < sec->linecount; i++) - { - secline = sec->lines[i]; - // BUG: will crash if 1S line has TWOSIDED flag! - if(!(secline->flags & ML_TWOSIDED)) - continue; - if(secline->special != 148) - continue; - - secline->flags &= ~ML_BLOCKING; - secline->special = 0; - sides[secline->sidenum[0]].midtexture = 0; - sides[secline->sidenum[1]].midtexture = 0; - } -} - diff --git a/games/NXDoom/src/strife/p_floor.c b/games/NXDoom/src/strife/p_floor.c deleted file mode 100644 index 8efb52ccab6..00000000000 --- a/games/NXDoom/src/strife/p_floor.c +++ /dev/null @@ -1,597 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Floor animation: raising stairs. -// - - - -#include "z_zone.h" -#include "doomdef.h" -#include "p_local.h" - -#include "s_sound.h" - -// State. -#include "doomstat.h" -#include "r_state.h" -// Data. -#include "sounds.h" - -//entryway -#define STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE 10 - -// -// FLOORS -// - -// -// Move a plane (floor or ceiling) and check for crushing -// -// [STRIFE] Various changes were made to remove calls to P_ChangeSector when -// P_ChangeSector returns true. -// -result_e -T_MovePlane -( sector_t* sector, - fixed_t speed, - fixed_t dest, - boolean crush, - int floorOrCeiling, - int direction ) -{ - boolean flag; - fixed_t lastpos; - - switch(floorOrCeiling) - { - case 0: - // FLOOR - switch(direction) - { - case -1: - // DOWN - if (sector->floorheight - speed < dest) - { - // villsa [STRIFE] unused - //lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector,crush); - - // villsa [STRIFE] unused - /*if (flag == true) - { - sector->floorheight =lastpos; - P_ChangeSector(sector,crush); - //return crushed; - }*/ - return pastdest; - } - else - { - // villsa [STRIFE] unused - //lastpos = sector->floorheight; - sector->floorheight -= speed; - flag = P_ChangeSector(sector,crush); - - // villsa [STRIFE] unused - /*if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - }*/ - return ok; - } - break; - - case 1: - // UP - if (sector->floorheight + speed > dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - sector->floorheight = lastpos; - P_ChangeSector(sector,crush); - //return crushed; - } - return pastdest; - } - else - { - // COULD GET CRUSHED - lastpos = sector->floorheight; - sector->floorheight += speed; - flag = P_ChangeSector(sector,crush); - if (flag == true) - { - // haleyjd 20130210: Bug fix - Strife DOES do this. - if (crush == true) - return crushed; - sector->floorheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - } - else - return ok; - } - break; - } - break; - - case 1: - // CEILING - switch(direction) - { - case -1: - // DOWN - if (sector->ceilingheight - speed < dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_ChangeSector(sector,crush); - - if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - //return crushed; - } - return pastdest; - } - else - { - // COULD GET CRUSHED - lastpos = sector->ceilingheight; - sector->ceilingheight -= speed; - flag = P_ChangeSector(sector,crush); - - if (flag == true) - { - if (crush == true) - return crushed; - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - return crushed; - } - } - break; - - case 1: - // UP - if (sector->ceilingheight + speed > dest) - { - // villsa [STRIFE] unused - //lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - - // villsa [STRIFE] unused - //flag = P_ChangeSector(sector,crush); - /*if (flag == true) - { - sector->ceilingheight = lastpos; - P_ChangeSector(sector,crush); - //return crushed; - }*/ - return pastdest; - } - else - { - // villsa [STRIFE] unused - //lastpos = sector->ceilingheight; - sector->ceilingheight += speed; - - // villsa [STRIFE] unused - //flag = P_ChangeSector(sector,crush); - return ok; - } - break; - } - break; - - } - return ok; -} - - -// -// MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) -// -void T_MoveFloor(floormove_t* floor) -{ - result_e res; - - res = T_MovePlane(floor->sector, - floor->speed, - floor->floordestheight, - floor->crush,0,floor->direction); - - if (!(leveltime&7)) - S_StartSound(&floor->sector->soundorg, sfx_stnmov); - - if (res == pastdest) - { - floor->sector->specialdata = NULL; - - if (floor->direction == 1) - { - switch(floor->type) - { - case donutRaise: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - } - else if (floor->direction == -1) - { - switch(floor->type) - { - case lowerAndChange: - floor->sector->special = floor->newspecial; - floor->sector->floorpic = floor->texture; - default: - break; - } - } - P_RemoveThinker(&floor->thinker); - - S_StartSound(&floor->sector->soundorg, sfx_pstop); - } - -} - -// -// HANDLE FLOOR TYPES -// -// haleyjd 09/16/2010: [STRIFE] Modifications to floortypes: -// * raiseFloor24 was changed into raiseFloor64 -// * turboLower does not appear to adjust the floor height (STRIFE-TODO: verify) -// * raiseFloor512AndChange type was added. -// -int -EV_DoFloor -( line_t* line, - floor_e floortype ) -{ - int secnum; - int rtn; - int i; - sector_t* sec; - floormove_t* floor; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // new floor thinker - rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - sec->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->type = floortype; - floor->crush = false; - - switch(floortype) - { - case lowerFloor: // [STRIFE] verified unmodified - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindHighestFloorSurrounding(sec); - break; - - case lowerFloorToLowest: // [STRIFE] verified unmodified - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindLowestFloorSurrounding(sec); - break; - - case turboLower: // [STRIFE] Modified: does not += 8 - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED * 4; - floor->floordestheight = - P_FindHighestFloorSurrounding(sec); - //if (floor->floordestheight != sec->floorheight) - // floor->floordestheight += 8*FRACUNIT; - break; - - case raiseFloorCrush: // [STRIFE] verified unmodified - floor->crush = true; - case raiseFloor: - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindLowestCeilingSurrounding(sec); - if (floor->floordestheight > sec->ceilingheight) - floor->floordestheight = sec->ceilingheight; - floor->floordestheight -= (8*FRACUNIT)* - (floortype == raiseFloorCrush); - break; - - case raiseFloorTurbo: // [STRIFE] verified unmodified - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED*4; - floor->floordestheight = - P_FindNextHighestFloor(sec,sec->floorheight); - break; - - case raiseFloorToNearest: // [STRIFE] verified unmodified - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindNextHighestFloor(sec,sec->floorheight); - break; - - case raiseFloor64: // [STRIFE] modified from raiseFloor24! - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 64 * FRACUNIT; // [STRIFE] - break; - - case raiseFloor512: // [STRIFE] verified unmodified - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 512 * FRACUNIT; - break; - - case raiseFloor24AndChange: // [STRIFE] verified unmodified - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 24 * FRACUNIT; - sec->floorpic = line->frontsector->floorpic; - sec->special = line->frontsector->special; - break; - - case raiseFloor512AndChange: // [STRIFE] New floor type - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = floor->sector->floorheight + - 512 * FRACUNIT; - sec->floorpic = line->frontsector->floorpic; - sec->special = line->frontsector->special; - break; - - case raiseToTexture: // [STRIFE] verified unmodified - { - int minsize = INT_MAX; - side_t* side; - - floor->direction = 1; - floor->sector = sec; - floor->speed = FLOORSPEED; - for (i = 0; i < sec->linecount; i++) - { - if (twoSided (secnum, i) ) - { - side = getSide(secnum,i,0); - if (side->bottomtexture >= 0) - if (textureheight[side->bottomtexture] < - minsize) - minsize = - textureheight[side->bottomtexture]; - side = getSide(secnum,i,1); - if (side->bottomtexture >= 0) - if (textureheight[side->bottomtexture] < - minsize) - minsize = - textureheight[side->bottomtexture]; - } - } - floor->floordestheight = - floor->sector->floorheight + minsize; - } - break; - - case lowerAndChange: // [STRIFE] verified unmodified - floor->direction = -1; - floor->sector = sec; - floor->speed = FLOORSPEED; - floor->floordestheight = - P_FindLowestFloorSurrounding(sec); - floor->texture = sec->floorpic; - - for (i = 0; i < sec->linecount; i++) - { - if ( twoSided(secnum, i) ) - { - if (getSide(secnum,i,0)->sector-sectors == secnum) - { - sec = getSector(secnum,i,1); - - if (sec->floorheight == floor->floordestheight) - { - floor->texture = sec->floorpic; - floor->newspecial = sec->special; - break; - } - } - else - { - sec = getSector(secnum,i,0); - - if (sec->floorheight == floor->floordestheight) - { - floor->texture = sec->floorpic; - floor->newspecial = sec->special; - break; - } - } - } - } - default: - break; - } - } - return rtn; -} - - - - -// -// BUILD A STAIRCASE! -// -int -EV_BuildStairs -( line_t* line, - stair_e type ) -{ - int secnum; - int height; - int i; - int newsecnum; - int texture; - int ok; - int rtn; - - sector_t* sec; - sector_t* tsec; - - floormove_t* floor; - - // Either Watcom or Rogue moved the switch out of the loop below, probably - // because it was a loop invariant, and put the default values in the - // initializers here. I cannot be bothered to figure it out without doing - // this myself :P - fixed_t stairsize = 8*FRACUNIT; - fixed_t speed = FLOORSPEED; - int direction = 1; - - switch(type) - { - case build8: // [STRIFE] Verified unmodified. - speed = FLOORSPEED/4; - break; - case turbo16: // [STRIFE] Verified unmodified. - speed = FLOORSPEED*4; - stairsize = 16*FRACUNIT; - break; - case buildDown16: // [STRIFE] New stair type - stairsize = -16*FRACUNIT; - direction = -1; - break; - } - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (sec->specialdata) - continue; - - // new floor thinker - rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - sec->tag = 0; // haleyjd 20140919: [STRIFE] clears tag of first stair sector - sec->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->direction = direction; // haleyjd 20140919: bug fix: direction, not "1" - floor->sector = sec; - floor->speed = speed; - height = sec->floorheight + stairsize; - floor->floordestheight = height; - // Initialize - floor->type = lowerFloor; - // entryway - // Uninitialized crush field will not be equal to 0 or 1 (true) - // with high probability. So, initialize it with any other value - floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; - - texture = sec->floorpic; - - // Find next sector to raise - // 1. Find 2-sided line with same sector side[0] - // 2. Other side is the next sector to raise - do - { - ok = 0; - for (i = 0;i < sec->linecount;i++) - { - if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) - continue; - - tsec = (sec->lines[i])->frontsector; - newsecnum = tsec-sectors; - - if (secnum != newsecnum) - continue; - - tsec = (sec->lines[i])->backsector; - newsecnum = tsec - sectors; - - if (tsec->floorpic != texture) - continue; - - height += stairsize; - - if (tsec->specialdata) - continue; - - sec = tsec; - secnum = newsecnum; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - - P_AddThinker (&floor->thinker); - - sec->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->direction = direction; // [STRIFE]: for buildDown16 - floor->sector = sec; - floor->speed = speed; - floor->floordestheight = height; - // Initialize - floor->type = lowerFloor; - // entryway - // Uninitialized crush field will not be equal to 0 or 1 (true) - // with high probability. So, initialize it with any other value - floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE; - ok = 1; - break; - } - } while(ok); - } - return rtn; -} - diff --git a/games/NXDoom/src/strife/p_inter.c b/games/NXDoom/src/strife/p_inter.c deleted file mode 100644 index bf36cb14776..00000000000 --- a/games/NXDoom/src/strife/p_inter.c +++ /dev/null @@ -1,1411 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handling interactions (i.e., collisions). -// - -// Data. -#include "doomdef.h" -#include "dstrings.h" -#include "sounds.h" -#include "deh_main.h" -#include "deh_misc.h" -#include "doomstat.h" -#include "m_misc.h" -#include "m_random.h" -#include "i_system.h" -#include "am_map.h" -#include "p_local.h" -#include "p_dialog.h" // villsa [STRIFE] -#include "s_sound.h" -#include "p_inter.h" - -#include "hu_stuff.h" // villsa [STRIFE] -#include "z_zone.h" // villsa [STRIFE] - -// haleyjd [STRIFE] -#include "w_wad.h" -#include "p_pspr.h" -#include "p_dialog.h" -#include "f_finale.h" - - -#define BONUSADD 6 - - -// a weapon is found with two clip loads, -// a big item has five clip loads -// villsa [STRIFE] updated arrays -int maxammo[NUMAMMO] = { 250, 50, 25, 400, 100, 30, 16 }; -int clipammo[NUMAMMO] = { 10, 4, 2, 20, 4, 6, 4 }; - - -// -// GET STUFF -// - -// -// P_GiveAmmo -// Num is the number of clip loads, -// not the individual count (0= 1/2 clip). -// Returns false if the ammo can't be picked up at all -// -// [STRIFE] Modified for Strife ammo types -// -boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int num) -{ - int oldammo; - - if(ammo == am_noammo) - return false; - - if(ammo >= NUMAMMO) - I_Error ("P_GiveAmmo: bad type %i", ammo); - - if(player->ammo[ammo] == player->maxammo[ammo]) - return false; - - if(num) - num *= clipammo[ammo]; - else - num = clipammo[ammo]/2; - - if(gameskill == sk_baby - || gameskill == sk_nightmare) - { - // give double ammo in trainer mode, - // you'll need in nightmare - num <<= 1; - } - - oldammo = player->ammo[ammo]; - player->ammo[ammo] += num; - - if(player->ammo[ammo] > player->maxammo[ammo]) - player->ammo[ammo] = player->maxammo[ammo]; - - // If non zero ammo, - // don't change up weapons, - // player was lower on purpose. - if(oldammo) - return true; - - // We were down to zero, - // so select a new weapon. - // Preferences are not user selectable. - - // villsa [STRIFE] ammo update - // where's the check for grenades? - haleyjd: verified no switch to grenades - // haleyjd 10/03/10: don't change to electric bow when picking up poison - // arrows. - if(!player->readyweapon) - { - switch(ammo) - { - case am_bullets: - if(player->weaponowned[wp_rifle]) - player->pendingweapon = wp_rifle; - break; - - case am_elecbolts: - if(player->weaponowned[wp_elecbow]) - player->pendingweapon = wp_elecbow; - break; - - case am_cell: - if(player->weaponowned[wp_mauler]) - player->pendingweapon = wp_mauler; - break; - - case am_missiles: - if(player->weaponowned[wp_missile]) - player->pendingweapon = wp_missile; - break; - - default: - break; - } - } - - return true; -} - - -// -// P_GiveWeapon -// The weapon name may have a MF_DROPPED flag ored in. -// -// villsa [STRIFE] some stuff has been changed/moved around -// -boolean P_GiveWeapon(player_t* player, weapontype_t weapon, boolean dropped) -{ - boolean gaveammo; - boolean gaveweapon; - - // villsa [STRIFE] new code for giving alternate version - // of the weapon to player - if(player->weaponowned[weapon]) - gaveweapon = false; - else - { - gaveweapon = true; - player->weaponowned[weapon] = true; - - // Alternate "sister" weapons that you also get as a bonus: - switch(weapon) - { - case wp_elecbow: - player->weaponowned[wp_poisonbow] = true; - break; - - case wp_hegrenade: - player->weaponowned[wp_wpgrenade] = true; - break; - - case wp_mauler: - player->weaponowned[wp_torpedo] = true; - break; - - default: - break; - } - - // check for the standard weapons only - if(weapon > player->readyweapon && weapon <= wp_sigil) - player->pendingweapon = weapon; - - } - - if(netgame && (deathmatch != 2) && !dropped) - { - // leave placed weapons forever on net games - if(!gaveweapon) - return false; - - player->bonuscount += BONUSADD; - player->weaponowned[weapon] = true; - - if(deathmatch) - P_GiveAmmo(player, weaponinfo[weapon].ammo, 5); - else - P_GiveAmmo(player, weaponinfo[weapon].ammo, 2); - - if(player == &players[consoleplayer]) - S_StartSound (NULL, sfx_wpnup); - return false; - } - - if(weaponinfo[weapon].ammo != am_noammo) - { - // give one clip with a dropped weapon, - // two clips with a found weapon - if(dropped) - gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1); - else - gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); - } - else - gaveammo = false; - - return(gaveweapon || gaveammo); -} - - - -// -// P_GiveBody -// Returns false if the body isn't needed at all -// -// villsa [STRIFE] a lot of changes have been added for stamina -// -boolean P_GiveBody(player_t* player, int num) -{ - int maxhealth; - int healing; - - maxhealth = MAXHEALTH + player->stamina; - - if(num >= 0) // haleyjd 20100923: fixed to give proper amount of health - { - mobj_t *mo; // haleyjd 20110225: needed below... - - // any healing to do? - if(player->health >= maxhealth) - return false; - - // give, and cap to maxhealth - player->health += num; - if(player->health >= maxhealth) - player->health = maxhealth; - - // Set mo->health for consistency. - // haleyjd 20110225: Seems Strife can call this on a NULL player->mo - // when giving items to players that are not in the game... - mo = P_SubstNullMobj(player->mo); - mo->health = player->health; - } - else - { - // [STRIFE] handle healing from the Front's medic - // The amount the player's health will be set to scales up with stamina - // increases. - // Ex 1: On the wimpiest skill level, -100 is sent in. This restores - // full health no matter what your stamina. - // (100*100)/100 = 100 - // (200*100)/100 = 200 - // Ex 2: On the most stringent skill levels, -50 is sent in. This will - // restore at most half of your health. - // (100*50)/100 = 50 - // (200*50)/100 = 100 - healing = (-num * maxhealth) / MAXHEALTH; - - // This is also the "threshold" of healing. You need less health than - // the amount that will be restored in order to get any benefit. - // So on the easiest skill you will always be fully healed. - // On the hardest skill you must have less than 50 health, and will - // only recover to 50 (assuming base stamina stat) - if(player->health >= healing) - return false; - - // Set health. BUG: Oddly, mo->health is NOT set here... - player->health = healing; - } - - return true; -} - - - -// -// P_GiveArmor -// Returns false if the armor is worse -// than the current armor. -// -// [STRIFE] Modified for Strife armor items -// -boolean P_GiveArmor(player_t* player, int armortype) -{ - int hits; - - // villsa [STRIFE] - if(armortype < 0) - { - if(player->armorpoints) - return false; - - armortype = -armortype; - } - - hits = armortype * 100; - if(player->armorpoints >= hits) - return false; // don't pick up - - player->armortype = armortype; - player->armorpoints = hits; - - return true; -} - - - -// -// P_GiveCard -// -// [STRIFE] Modified to use larger bonuscount -// -boolean P_GiveCard(player_t* player, card_t card) -{ - if (player->cards[card]) - return false; - - // villsa [STRIFE] multiply by 2 - player->bonuscount = BONUSADD * 2; - player->cards[card] = true; - - return true; -} - - -// -// P_GivePower -// -// [STRIFE] Modifications for new powerups -// -boolean P_GivePower(player_t* player, powertype_t power) -{ - // haleyjd 09/14/10: [STRIFE] moved to top, exception for Shadow Armor - if(player->powers[power] && power != pw_invisibility) - return false; // already got it - - // if giving pw_invisibility and player already has MVIS, no can do. - if(power == pw_invisibility && (player->mo->flags & MF_MVIS)) - return false; - - // villsa [STRIFE] - switch (power) { - case pw_targeter: - { - player->powers[power] = TARGTICS; - P_SetPsprite(player, ps_targcenter, S_TRGT_00); // 10 - P_SetPsprite(player, ps_targleft, S_TRGT_01); // 11 - P_SetPsprite(player, ps_targright, S_TRGT_02); // 12 - - player->psprites[ps_targcenter].sx = (160*FRACUNIT); - player->psprites[ps_targleft ].sy = (100*FRACUNIT); - player->psprites[ps_targcenter].sy = (100*FRACUNIT); - player->psprites[ps_targright ].sy = (100*FRACUNIT); - return true; - } - - case pw_invisibility: - { - // if player already had this power... - if(player->powers[power]) - { - // remove SHADOW, give MVIS. - player->mo->flags &= ~MF_SHADOW; - player->mo->flags |= MF_MVIS; - } - else // give SHADOW - player->mo->flags |= MF_SHADOW; - - // set tics if giving shadow, or renew them if MVIS. - player->powers[power] = INVISTICS; - - return true; - } - - case pw_ironfeet: - { - player->powers[power] = IRONTICS; - return true; - } - - case pw_strength: - { - P_GiveBody(player, 100); - player->powers[power] = 1; - return true; - } - - // villsa [STRIFE] - case pw_allmap: - { - // remember in mapstate - if(gamemap < 40) - player->mapstate[gamemap] = true; - - player->powers[power] = 1; - return true; - } - - // villsa [STRIFE] - case pw_communicator: - { - player->powers[power] = 1; - return true; - } - - case NUMPOWERS: - // This should never actually happen - break; - } - - return true; -} - - -// villsa [STRIFE] -static char pickupmsg[80]; - -// -// P_TouchSpecialThing -// -// [STRIFE] Rewritten for Strife collectables. -// -void P_TouchSpecialThing(mobj_t* special, mobj_t* toucher) -{ - player_t* player; - int i; - fixed_t delta; - int sound; - - delta = special->z - toucher->z; - - if(delta > toucher->height || delta < -8*FRACUNIT) - return; // out of reach - - sound = sfx_itemup; - player = toucher->player; - - // Dead thing touching. - // Can happen with a sliding player corpse. - if(toucher->health <= 0) - return; - - // villsa [STRIFE] damage toucher if special is spectral - // haleyjd 09/21/10: corrected to test for SPECTRE thingtypes specifically - switch(special->type) - { - case MT_SPECTRE_A: - case MT_SPECTRE_B: - case MT_SPECTRE_C: - case MT_SPECTRE_D: - case MT_SPECTRE_E: - case MT_ENTITY: - case MT_SUBENTITY: - P_DamageMobj(toucher, NULL, NULL, 5); - return; - default: - break; - } - - // villsa [STRIFE] - pickupmsg[0] = 0; - - // Identify by sprite. - // villsa [STRIFE] new items - switch(special->sprite) - { - // bullets - case SPR_BLIT: // haleyjd: fixed missing MF_DROPPED check - if(!P_GiveAmmo(player, am_bullets, !(special->flags & MF_DROPPED))) - return; - break; - - // box of bullets - case SPR_BBOX: - if(!P_GiveAmmo(player, am_bullets, 5)) - return; - break; - - // missile - case SPR_MSSL: - if(!P_GiveAmmo(player, am_missiles, 1)) - return; - break; - - // box of missiles - case SPR_ROKT: - if(!P_GiveAmmo(player, am_missiles, 5)) - return; - break; - - // battery - case SPR_BRY1: - if(!P_GiveAmmo(player, am_cell, 1)) - return; - break; - - // cell pack - case SPR_CPAC: - if(!P_GiveAmmo(player, am_cell, 5)) - return; - break; - - // poison bolts - case SPR_PQRL: - if(!P_GiveAmmo(player, am_poisonbolts, 5)) - return; - break; - - // electric bolts - case SPR_XQRL: - if(!P_GiveAmmo(player, am_elecbolts, 5)) - return; - break; - - // he grenades - case SPR_GRN1: - if(!P_GiveAmmo(player, am_hegrenades, 1)) - return; - break; - - // wp grenades - case SPR_GRN2: - if(!P_GiveAmmo(player, am_wpgrenades, 1)) - return; - break; - - // rifle - case SPR_RIFL: - if(!P_GiveWeapon(player, wp_rifle, (special->flags & MF_DROPPED) != 0)) - return; - sound = sfx_wpnup; // haleyjd: SHK-CHK! - break; - - // flame thrower - case SPR_FLAM: - if(!P_GiveWeapon(player, wp_flame, false)) - return; - // haleyjd: gives extra ammo. - P_GiveAmmo(player, am_cell, 3); - sound = sfx_wpnup; // haleyjd: SHK-CHK! - break; - - // missile launcher - case SPR_MMSL: - if(!P_GiveWeapon(player, wp_missile, false)) - return; - sound = sfx_wpnup; // haleyjd: SHK-CHK! - break; - - // grenade launcher - case SPR_GRND: - if(!P_GiveWeapon(player, wp_hegrenade, - (special->flags & MF_DROPPED) != 0)) - return; - sound = sfx_wpnup; // haleyjd: SHK-CHK! - break; - - // mauler - case SPR_TRPD: - if(!P_GiveWeapon(player, wp_mauler, false)) - return; - sound = sfx_wpnup; // haleyjd: SHK-CHK! - break; - - // electric bolt crossbow - case SPR_CBOW: - if(!P_GiveWeapon(player, wp_elecbow, - (special->flags & MF_DROPPED) != 0)) - return; - sound = sfx_wpnup; // haleyjd: SHK-CHK! - break; - - // haleyjd 09/21/10: missed case: THE SIGIL! - case SPR_SIGL: - if(!P_GiveWeapon(player, wp_sigil, (special->flags & MF_DROPPED) != 0)) - { - player->sigiltype = special->frame; - return; - } - - if(netgame) - player->sigiltype = 4; - - player->pendingweapon = wp_sigil; - player->st_update = true; - if(deathmatch) - return; - sound = sfx_wpnup; - break; - - // backpack - case SPR_BKPK: - if(!player->backpack) - { - for(i = 0; i < NUMAMMO; i++) - player->maxammo[i] *= 2; - - player->backpack = true; - } - for(i = 0; i < NUMAMMO; i++) - P_GiveAmmo(player, i, 1); - break; - - // 1 Gold - case SPR_COIN: - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - // 10 Gold - case SPR_CRED: - for(i = 0; i < 10; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - // 25 Gold - case SPR_SACK: - // haleyjd 09/21/10: missed code: if a SPR_SACK object has negative - // health, it will give that much gold - STRIFE-TODO: verify - if(special->health < 0) - { - for(i = special->health; i != 0; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - } - else - { - for(i = 0; i < 25; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - } - break; - - // 50 Gold - case SPR_CHST: - for(i = 0; i < 50; i++) - P_GiveInventoryItem(player, SPR_COIN, MT_MONY_1); - break; - - // Leather Armor - case SPR_ARM1: - if(!P_GiveArmor(player, -2)) - if(!P_GiveInventoryItem(player, special->sprite, special->type)) - pickupmsg[0] = '!'; - break; - - // Metal Armor - case SPR_ARM2: - if(!P_GiveArmor(player, -1)) - if(!P_GiveInventoryItem(player, special->sprite, special->type)) - pickupmsg[0] = '!'; - break; - - // All-map powerup - case SPR_PMAP: - if(!P_GivePower(player, pw_allmap)) - return; - sound = sfx_yeah; - break; - - // The Comm Unit - because you need Blackbird whining in your ear the - // whole time and telling you how lost she is :P - case SPR_COMM: - if(!P_GivePower(player, pw_communicator)) - return; - sound = sfx_yeah; - break; - - // haleyjd 09/21/10: missed case - Shadow Armor; though, I do not know why - // this has a case distinct from generic inventory items... Maybe it started - // out as an auto-use-if-possible item much like regular armor... - case SPR_SHD1: - if(!P_GiveInventoryItem(player, SPR_SHD1, special->type)) - pickupmsg[0] = '!'; - break; - - // villsa [STRIFE] check default items - case SPR_TOKN: - default: - if(special->type >= MT_KEY_BASE && special->type <= MT_NEWKEY5) - { - // haleyjd 09/21/10: Strife player still picks up keys that - // he has already found. (break, not return) - if(!P_GiveCard(player, special->type - MT_KEY_BASE)) - break; - } - else - { - if(!P_GiveInventoryItem(player, special->sprite, special->type)) - pickupmsg[0] = '!'; - } - break; - } - - // villsa [STRIFE] set message - if(!pickupmsg[0]) - { - if(special->info->name) - { - DEH_snprintf(pickupmsg, sizeof(pickupmsg), - "You picked up the %s.", DEH_String(special->info->name)); - } - else - DEH_snprintf(pickupmsg, sizeof(pickupmsg), "You picked up the item."); - } - // use the first character to indicate that the player is full on items - else if(pickupmsg[0] == '!') - { - DEH_snprintf(pickupmsg, sizeof(pickupmsg), "You cannot hold any more."); - player->message = pickupmsg; - return; - } - - if(special->flags & MF_GIVEQUEST) - { - // [STRIFE]: Award quest flag based on the thing's speed. Quest 8 was - // apparently at some point given by the Broken Power Coupling, which is - // why they don't want to award it if you have Quest 6 (which is - // acquired by destroying the Front's working power coupling). BUT, the - // broken coupling object's speed is NOT 8... it is 512*FRACUNIT. For - // strict portability beyond the x86, we need to AND the operand by 31. - if(special->info->speed != 8 || !(player->questflags & QF_QUEST6)) - player->questflags |= 1 << ((special->info->speed - 1) & 31); - } - - - // haleyjd 08/30/10: [STRIFE] No itemcount - //if (special->flags & MF_COUNTITEM) - // player->itemcount++; - - P_RemoveMobj(special); - player->message = pickupmsg; - player->bonuscount += BONUSADD; - - if(player == &players[consoleplayer]) - S_StartSound(NULL, sound); -} - -// villsa [STRIFE] -static char plrkilledmsg[80]; - -// -// KillMobj -// -// [STRIFE] Major modifications for drop types, no tic randomization, etc. -// -void P_KillMobj(mobj_t* source, mobj_t* target) -{ - mobjtype_t item; - mobj_t* mo; - line_t junk; - int i; - - // villsa [STRIFE] corpse and dropoff are removed, but why when these two flags - // are set a few lines later? watcom nonsense perhaps? - target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_BOUNCE|MF_CORPSE|MF_DROPOFF); - - // villsa [STRIFE] unused - /* - if (target->type != MT_SKULL) - target->flags &= ~MF_NOGRAVITY; - */ - - target->flags |= MF_CORPSE|MF_DROPOFF; - target->height = FRACUNIT; // villsa [STRIFE] set to fracunit instead of >>= 2 - - if(source && source->player) - { - // count for intermission - if(target->flags & MF_COUNTKILL) - source->player->killcount++; - - if(target->player) - { - source->player->frags[target->player-players]++; - - // villsa [STRIFE] new messages when fragging players - // haleyjd 20141024: corrected; uses player->allegiance, not mo->miscdata - DEH_snprintf(plrkilledmsg, sizeof(plrkilledmsg), - "%s killed %s", - player_names[source->player->allegiance], - player_names[target->player->allegiance]); - - if(netgame) - players[consoleplayer].message = plrkilledmsg; - } - } - else if(!netgame && (target->flags & MF_COUNTKILL)) - { - // count all monster deaths, - // even those caused by other monsters - players[0].killcount++; - } - - if(target->player) - { - // count environment kills against you - if(!source) - target->player->frags[target->player-players]++; - - if(gamemap == 29 && !netgame) - { - // haleyjd 09/13/10: [STRIFE] Give player the bad ending. - F_StartFinale(); - return; - } - - // villsa [STRIFE] spit out inventory items when killed - if(netgame) - { - int amount = 0; - mobj_t* loot; - int r = 0; - - while(1) - { - if(target->player->inventory[0].amount <= 0) - break; - - item = target->player->inventory[0].type; - if(item == MT_MONY_1) - { - loot = P_SpawnMobj(target->x, target->y, - target->z + (24*FRACUNIT), MT_MONY_25); - - // [STRIFE] TODO - what the hell is it doing here? - loot->health = target->player->inventory[0].amount; - loot->health = -target->player->inventory[0].amount; - - amount = target->player->inventory[0].amount; - } - else - { - loot = P_SpawnMobj(target->x, target->y, - target->z + (24*FRACUNIT), item); - amount = 1; - } - - P_RemoveInventoryItem(target->player, 0, amount); - r = P_Random(); - loot->momx += ((r & 7) - (P_Random() & 7)) << FRACBITS; - loot->momy += ((P_Random() & 7) + 1) << FRACBITS; - loot->flags |= MF_DROPPED; - } - } - - //target->flags &= ~MF_SOLID; - target->player->playerstate = PST_DEAD; - target->player->mo->momz += 5*FRACUNIT; // [STRIFE]: small hop! - P_DropWeapon(target->player); - - if(target->player == &players[consoleplayer] - && automapactive) - { - // don't die in auto map, - // switch view prior to dying - AM_Stop (); - } - - } - - // villsa [STRIFE] some modifications to setting states - if(target->state != &states[S_BURN_23]) - { - if(target->health == -6666) - P_SetMobjState(target, S_DISR_00); // 373 - else - { - // haleyjd [STRIFE] 20160111: Rogue changed check from < to <= - if(target->health <= -target->info->spawnhealth - && target->info->xdeathstate) - P_SetMobjState(target, target->info->xdeathstate); - else - P_SetMobjState(target, target->info->deathstate); - } - } - - // villsa [STRIFE] no death tics randomization - - // Drop stuff. - // villsa [STRIFE] get item from dialog target - item = P_DialogFind(target->type, target->miscdata)->dropitem; - - if(!item) - { - // villsa [STRIFE] drop default items - switch(target->type) - { - case MT_ORACLE: - item = MT_MEAT; - break; - - case MT_PROGRAMMER: - item = MT_SIGIL_A; - break; - - case MT_PRIEST: - item = MT_JUNK; - break; - - case MT_BISHOP: - item = MT_AMINIBOX; - break; - - case MT_PGUARD: - case MT_CRUSADER: - item = MT_ACELL; - break; - - case MT_RLEADER: - item = MT_AAMMOBOX; - break; - - case MT_GUARD1: - case MT_REBEL1: - case MT_SHADOWGUARD: - item = MT_ACLIP; - break; - - case MT_SPECTRE_B: - item = MT_SIGIL_B; - break; - - case MT_SPECTRE_C: - item = MT_SIGIL_C; - break; - - case MT_SPECTRE_D: - item = MT_SIGIL_D; - break; - - case MT_SPECTRE_E: - item = MT_SIGIL_E; - break; - - case MT_COUPLING: - junk.tag = 225; - EV_DoDoor(&junk, vld_close); - - junk.tag = 44; - EV_DoFloor(&junk, lowerFloor); - - GiveVoiceObjective("VOC13", "LOG13", 0); - - item = MT_COUPLING_BROKEN; - players[0].questflags |= (1 << (mobjinfo[MT_COUPLING].speed - 1)); - break; - - default: - return; - } - } - - // handle special case for scripted target's dropped item - switch(item) - { - case MT_TOKEN_SHOPCLOSE: - junk.tag = 222; - EV_DoDoor(&junk, vld_close); - P_NoiseAlert(players[0].mo, players[0].mo); - - M_snprintf(plrkilledmsg, sizeof(plrkilledmsg), - "%s", DEH_String("You're dead! You set off the alarm.")); - if(!deathmatch) - players[consoleplayer].message = plrkilledmsg; - - return; - - case MT_TOKEN_PRISON_PASS: - junk.tag = 223; - EV_DoDoor(&junk, vld_open); - return; - - case MT_TOKEN_DOOR3: - junk.tag = 224; - EV_DoDoor(&junk, vld_open); - return; - - case MT_SIGIL_A: - case MT_SIGIL_B: - case MT_SIGIL_C: - case MT_SIGIL_D: - case MT_SIGIL_E: - for(i = 0; i < MAXPLAYERS; i++) - { - if(!P_GiveWeapon(&players[i], wp_sigil, false)) - { - if(players[i].sigiltype++ > 4) - players[i].sigiltype = 4; - } - - // haleyjd 20110225: fixed these two assignments which Watcom munged - // up in the assembly by pre-incrementing the pointer into players[] - players[i].st_update = true; - players[i].pendingweapon = wp_sigil; - } - return; - - case MT_TOKEN_ALARM: - P_NoiseAlert(players[0].mo, players[0].mo); - - M_snprintf(plrkilledmsg, sizeof(plrkilledmsg), - "%s", DEH_String("You Fool! You've set off the alarm")); - if(!deathmatch) - players[consoleplayer].message = plrkilledmsg; - return; - - default: - break; - } - - // villsa [STRIFE] toss out item - if(!deathmatch || !(mobjinfo[item].flags & MF_NOTDMATCH)) - { - int r; - - mo = P_SpawnMobj(target->x, target->y, target->z + (24*FRACUNIT), item); - r = P_Random(); - mo->momx += ((r & 7) - (P_Random() & 7)) << FRACBITS; - r = P_Random(); - mo->momy += ((r & 7) - (P_Random() & 7)) << FRACBITS; - mo->flags |= (MF_SPECIAL|MF_DROPPED); // special versions of items - } -} - -// -// P_IsMobjBoss -// -// villsa [STRIFE] new function -// -static boolean P_IsMobjBoss(mobjtype_t type) -{ - switch(type) - { - case MT_PROGRAMMER: - case MT_BISHOP: - case MT_RLEADER: - case MT_ORACLE: - case MT_PRIEST: - return true; - - default: - return false; - } -} - - -// -// P_DamageMobj -// Damages both enemies and players -// "inflictor" is the thing that caused the damage -// creature or missile, can be NULL (slime, etc) -// "source" is the thing to target after taking damage -// creature or NULL -// Source and inflictor are the same for melee attacks. -// Source can be NULL for slime, barrel explosions -// and other environmental stuff. -// -// [STRIFE] Extensive changes for spectrals, fire damage, disintegration, and -// a plethora of mobjtype-specific hacks. -// -void P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage) -{ - angle_t ang; - int saved; - player_t* player; - fixed_t thrust; - int temp; - - if(!(target->flags & MF_SHOOTABLE) ) - return; // shouldn't happen... - - if(target->health <= 0) - return; - - player = target->player; - - // villsa [STRIFE] unused - skullfly check (removed) - - // villsa [STRIFE] handle spectral stuff - // notes on projectile health: - // -2 == enemy spectral projectile - // -1 == player spectral projectile - - // haleyjd 20110203: refactored completely - if(inflictor && (inflictor->flags & MF_SPECTRAL)) - { - // players aren't damaged by their own (or others???) sigils - // STRIFE-TODO: verify in deathmatch - if(target->type == MT_PLAYER && inflictor->health == -1) - return; - // enemies aren't damaged by enemy sigil attacks - if((target->flags & MF_SPECTRAL) && inflictor->health == -2) - return; - // Macil2, Oracle, and Spectre C cannot be damaged by Sigil A - switch(target->type) - { - case MT_RLEADER2: - case MT_ORACLE: - case MT_SPECTRE_C: - // haleyjd: added source->player validity check for safety... - if(source->player && source->player->sigiltype < 1) - return; - default: - break; - } - } - - // villsa [STRIFE] new checks for various actors - if(inflictor) - { - // Fire damage inflictors - if(inflictor->type == MT_SFIREBALL || - inflictor->type == MT_C_FLAME || - inflictor->type == MT_PFLAME) - { - temp = damage / 2; - - if(P_IsMobjBoss(target->type)) - damage /= 2; - else if(inflictor->type == MT_PFLAME) - { - damage /= 2; - // robots take very little damage - if(target->flags & MF_NOBLOOD) - damage = temp / 2; - } - } - else - { - switch(inflictor->type) - { - case MT_HOOKSHOT: - // haleyjd 20110203: should use source, not inflictor - ang = R_PointToAngle2( - target->x, - target->y, - source->x, - source->y) >> ANGLETOFINESHIFT; - - target->momx += FixedMul(finecosine[ang], (12750*FRACUNIT) / target->info->mass); - target->momy += FixedMul(finesine[ang], (12750*FRACUNIT) / target->info->mass); - target->reactiontime += 10; - - temp = P_AproxDistance(target->x - source->x, target->y - source->y); - temp /= target->info->mass; - - if(temp < 1) - temp = 1; - - target->momz = (source->z - target->z) / temp; - break; - - case MT_POISARROW: - // don't affect robots - if(target->flags & MF_NOBLOOD) - return; - - // instant kill - damage = target->health + 10; - break; - - default: - // Spectral retaliation, though this may in fact be unreachable - // since non-spectral inflictors are mostly filtered out. - if(target->flags & MF_SPECTRAL - && !(inflictor->flags & MF_SPECTRAL)) - { - P_SetMobjState(target, target->info->missilestate); - return; // take no damage - } - break; - } - } - } - - // villsa [STRIFE] special cases for shopkeepers and macil - if((target->type >= MT_SHOPKEEPER_W && target->type <= MT_SHOPKEEPER_M) - || target->type == MT_RLEADER) - { - if(source) - target->target = source; - - P_SetMobjState(target, target->info->painstate); - return; - } - - // villsa [STRIFE] handle fieldguard damage - if(target->type == MT_FIELDGUARD) - { - // degnin ores are only allowed to damage the fieldguard - if(!inflictor || inflictor->type != MT_DEGNINORE) - return; - - damage = target->health; - } - - if(player && gameskill == sk_baby) - damage >>= 1; // take half damage in trainer mode - - - // Some close combat weapons should not - // inflict thrust and push the victim out of reach, - // thus kick away unless using the chainsaw. - if (inflictor - && !(target->flags & MF_NOCLIP) - && (!source - || !source->player - || source->player->readyweapon != wp_flame)) - { - ang = R_PointToAngle2(inflictor->x, - inflictor->y, - target->x, - target->y); - - thrust = damage * (FRACUNIT>>3) * 100 / target->info->mass; - - // make fall forwards sometimes - if(damage < 40 - && damage > target->health - && target->z - inflictor->z > 64*FRACUNIT - && (P_Random() & 1)) - { - ang += ANG180; - thrust *= 4; - } - - ang >>= ANGLETOFINESHIFT; - target->momx += FixedMul (thrust, finecosine[ang]); - target->momy += FixedMul (thrust, finesine[ang]); - } - - // player specific - if(player) - { - // end of game hell hack - if (target->subsector->sector->special == 11 - && damage >= target->health) - { - damage = target->health - 1; - } - - - // Below certain threshold, - // ignore damage in GOD mode. - // villsa [STRIFE] removed pw_invulnerability check - if(damage < 1000 && (player->cheats & CF_GODMODE)) - return; - - // villsa [STRIFE] flame attacks don't damage player if wearing envirosuit - if(player->powers[pw_ironfeet] && inflictor) - { - if(inflictor->type == MT_SFIREBALL || - inflictor->type == MT_C_FLAME || - inflictor->type == MT_PFLAME) - { - damage = 0; - } - } - - if(player->armortype) - { - if (player->armortype == 1) - saved = damage/3; - else - saved = damage/2; - - if(player->armorpoints <= saved) - { - // armor is used up - saved = player->armorpoints; - player->armortype = 0; - - // villsa [STRIFE] - P_UseInventoryItem(player, SPR_ARM1); - P_UseInventoryItem(player, SPR_ARM2); - } - player->armorpoints -= saved; - damage -= saved; - } - player->health -= damage; // mirror mobj health here for Dave - - // [STRIFE] haleyjd 20130302: bug fix - this is *not* capped here. - //if(player->health < 0) - // player->health = 0; - - player->attacker = source; - player->damagecount += damage; // add damage after armor / invuln - - // haleyjd 20110203 [STRIFE]: target->target set here - if(target != source) - target->target = source; - - if(player->damagecount > 100) - player->damagecount = 100; // teleport stomp does 10k points... - - temp = damage < 100 ? damage : 100; - - if(player == &players[consoleplayer]) - I_Tactile (40,10,40+temp*2); - } - - // do the damage - target->health -= damage; - - // villsa [STRIFE] auto use medkits - if(player && player->health < 50) - { - if(deathmatch || player->cheats & CF_AUTOHEALTH) - { - while(player->health < 50 && P_UseInventoryItem(player, SPR_MDKT)); - while(player->health < 50 && P_UseInventoryItem(player, SPR_STMP)); - } - } - - - if(target->health <= 0) - { - // villsa [STRIFE] grenades hurt... OUCH - if(inflictor && inflictor->type == MT_HEGRENADE) - target->health = -target->info->spawnhealth; - else if(!(target->flags & MF_NOBLOOD)) - { - // villsa [STRIFE] disintegration death - if(inflictor && - (inflictor->type == MT_STRIFEPUFF3 || - inflictor->type == MT_L_LASER || - inflictor->type == MT_TORPEDO || - inflictor->type == MT_TORPEDOSPREAD)) - { - S_StartSound(target, sfx_dsrptr); - target->health = -6666; - } - } - - // villsa [STRIFE] flame death stuff - if(!(target->flags & MF_NOBLOOD) - && inflictor - && (inflictor->type == MT_SFIREBALL || - inflictor->type == MT_C_FLAME || - inflictor->type == MT_PFLAME)) - { - target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SHADOW|MF_MVIS); - if(target->player) - { - target->player->cheats |= CF_ONFIRE; - target->player->powers[pw_invisibility] = false; - target->player->readyweapon = 0; - P_SetPsprite(target->player, ps_weapon, S_WAVE_00); // 02 - P_SetPsprite(target->player, ps_flash, S_NULL); - } - - P_SetMobjState(target, S_BURN_00); // 349 - S_StartSound(target, sfx_burnme); - - return; - } - - P_KillMobj(source, target); - return; - } - - // villsa [STRIFE] set crash state - if(target->health <= 6 && target->info->crashstate) - { - P_SetMobjState(target, target->info->crashstate); - return; - } - - if(damage) - { - // villsa [STRIFE] removed unused skullfly flag - if(P_Random() < target->info->painchance) - { - target->flags |= MF_JUSTHIT; // fight back! - P_SetMobjState (target, target->info->painstate); - } - } - - target->reactiontime = 0; // we're awake now... - - // villsa [STRIFE] new checks for thing types - if (target->type != MT_PROGRAMMER - && (!target->threshold || target->type == MT_ENTITY) - && source && source != target - && source->type != MT_ENTITY - && ((source->flags & MF_ALLY) != (target->flags & MF_ALLY))) - { - // if not intent on another player, - // chase after this one - target->target = source; - target->threshold = BASETHRESHOLD; - - if(target->state == &states[target->info->spawnstate] - && target->info->seestate != S_NULL) - P_SetMobjState (target, target->info->seestate); - } -} - diff --git a/games/NXDoom/src/strife/p_inter.h b/games/NXDoom/src/strife/p_inter.h deleted file mode 100644 index c43fc0156c6..00000000000 --- a/games/NXDoom/src/strife/p_inter.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// -// - - -#ifndef __P_INTER__ -#define __P_INTER__ - -// haleyjd [STRIFE]: Multiple externals added -boolean P_GiveCard(player_t* player, card_t card); -boolean P_GiveBody(player_t* player, int num); -boolean P_GiveArmor(player_t* player, int armortype); -boolean P_GivePower(player_t* player, powertype_t power); -boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int num); -boolean P_GiveWeapon(player_t* player, weapontype_t weapon, boolean dropped); -void P_KillMobj(mobj_t* source, mobj_t* target); - -#endif diff --git a/games/NXDoom/src/strife/p_lights.c b/games/NXDoom/src/strife/p_lights.c deleted file mode 100644 index 7fe509939ed..00000000000 --- a/games/NXDoom/src/strife/p_lights.c +++ /dev/null @@ -1,372 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handle Sector base lighting effects. -// Muzzle flash? -// - - - -#include "z_zone.h" -#include "m_random.h" - -#include "doomdef.h" -#include "p_local.h" - - -// State. -#include "r_state.h" - -// -// FIRELIGHT FLICKER -// - -// -// T_FireFlicker -// -// [STRIFE] -// haleyjd 2011023: Changes to amount and duration of flicker -// -void T_FireFlicker (fireflicker_t* flick) -{ - int amount; - - if (--flick->count) - return; - - amount = (P_Random() & 3) * 8; // [STRIFE] 16 -> 8 - - if (flick->sector->lightlevel - amount < flick->minlight) - flick->sector->lightlevel = flick->minlight; - else - flick->sector->lightlevel = flick->maxlight - amount; - - // [STRIFE] flicker count made random! - flick->count = (P_Random() & 3) + 1; -} - - - -// -// P_SpawnFireFlicker -// -// [STRIFE] -// haleyjd 2011023: Changes to minimum light level and initial duration -// -void P_SpawnFireFlicker (sector_t* sector) -{ - fireflicker_t* flick; - - // Note that we are resetting sector attributes. - // Nothing special about it during gameplay. - sector->special = 0; - - flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); - - P_AddThinker (&flick->thinker); - - flick->thinker.function.acp1 = (actionf_p1) T_FireFlicker; - flick->sector = sector; - flick->maxlight = sector->lightlevel; - flick->minlight = sector->lightlevel - 32; // [STRIFE] changed from min surrounding+16 - flick->count = 2; // [STRIFE]: Initial count 4 -> 2 -} - - - -// -// BROKEN LIGHT FLASHING -// - - -// -// T_LightFlash -// Do flashing lights. -// -// [STRIFE] Verified unmodified -// -void T_LightFlash (lightflash_t* flash) -{ - if (--flash->count) - return; - - if (flash->sector->lightlevel == flash->maxlight) - { - flash->sector->lightlevel = flash->minlight; - flash->count = (P_Random()&flash->mintime)+1; - } - else - { - flash->sector->lightlevel = flash->maxlight; - flash->count = (P_Random()&flash->maxtime)+1; - } -} - - - - -// -// P_SpawnLightFlash -// After the map has been loaded, scan each sector -// for specials that spawn thinkers -// -// [STRIFE] Verified unmodified -// -void P_SpawnLightFlash (sector_t* sector) -{ - lightflash_t* flash; - - // nothing special about it during gameplay - sector->special = 0; - - flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); - - P_AddThinker (&flash->thinker); - - flash->thinker.function.acp1 = (actionf_p1) T_LightFlash; - flash->sector = sector; - flash->maxlight = sector->lightlevel; - - flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); - flash->maxtime = 64; - flash->mintime = 7; - flash->count = (P_Random()&flash->maxtime)+1; -} - - - -// -// STROBE LIGHT FLASHING -// - - -// -// T_StrobeFlash -// -// [STRIFE] Verified unmodified -// -void T_StrobeFlash (strobe_t* flash) -{ - if (--flash->count) - return; - - if (flash->sector->lightlevel == flash->minlight) - { - flash-> sector->lightlevel = flash->maxlight; - flash->count = flash->brighttime; - } - else - { - flash-> sector->lightlevel = flash->minlight; - flash->count =flash->darktime; - } -} - - - -// -// P_SpawnStrobeFlash -// After the map has been loaded, scan each sector -// for specials that spawn thinkers -// -// [STRIFE] Verified unmodified -// -void -P_SpawnStrobeFlash -( sector_t* sector, - int fastOrSlow, - int inSync ) -{ - strobe_t* flash; - - flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); - - P_AddThinker (&flash->thinker); - - flash->sector = sector; - flash->darktime = fastOrSlow; - flash->brighttime = STROBEBRIGHT; - flash->thinker.function.acp1 = (actionf_p1) T_StrobeFlash; - flash->maxlight = sector->lightlevel; - flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); - - if (flash->minlight == flash->maxlight) - flash->minlight = 0; - - // nothing special about it during gameplay - sector->special = 0; - - if (!inSync) - flash->count = (P_Random()&7)+1; - else - flash->count = 1; -} - - -// -// Start strobing lights (usually from a trigger) -// -// [STRIFE] Verified unmodified -// -void EV_StartLightStrobing(line_t* line) -{ - int secnum; - sector_t* sec; - - secnum = -1; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - if (sec->specialdata) - continue; - - P_SpawnStrobeFlash (sec, SLOWDARK, 0); - } -} - - - -// -// TURN LINE'S TAG LIGHTS OFF -// -// [STRIFE] Verified unmodified -// -void EV_TurnTagLightsOff(line_t* line) -{ - int i; - int j; - int min; - sector_t* sector; - sector_t* tsec; - line_t* templine; - - sector = sectors; - - for (j = 0;j < numsectors; j++, sector++) - { - if (sector->tag == line->tag) - { - min = sector->lightlevel; - for (i = 0;i < sector->linecount; i++) - { - templine = sector->lines[i]; - tsec = getNextSector(templine,sector); - if (!tsec) - continue; - if (tsec->lightlevel < min) - min = tsec->lightlevel; - } - sector->lightlevel = min; - } - } -} - - -// -// TURN LINE'S TAG LIGHTS ON -// -// [STRIFE] Verified unmodified -// -void -EV_LightTurnOn -( line_t* line, - int bright ) -{ - int i; - int j; - sector_t* sector; - sector_t* temp; - line_t* templine; - - sector = sectors; - - for (i=0;itag == line->tag) - { - // bright = 0 means to search - // for highest light level - // surrounding sector - if (!bright) - { - for (j = 0;j < sector->linecount; j++) - { - templine = sector->lines[j]; - temp = getNextSector(templine,sector); - - if (!temp) - continue; - - if (temp->lightlevel > bright) - bright = temp->lightlevel; - } - } - sector-> lightlevel = bright; - } - } -} - - -// -// Spawn glowing light -// -// [STRIFE] Verified unmodified -// -void T_Glow(glow_t* g) -{ - switch(g->direction) - { - case -1: - // DOWN - g->sector->lightlevel -= GLOWSPEED; - if (g->sector->lightlevel <= g->minlight) - { - g->sector->lightlevel += GLOWSPEED; - g->direction = 1; - } - break; - - case 1: - // UP - g->sector->lightlevel += GLOWSPEED; - if (g->sector->lightlevel >= g->maxlight) - { - g->sector->lightlevel -= GLOWSPEED; - g->direction = -1; - } - break; - } -} - -// -// [STRIFE] Verified unmodified -// -void P_SpawnGlowingLight(sector_t* sector) -{ - glow_t* g; - - g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); - - P_AddThinker(&g->thinker); - - g->sector = sector; - g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); - g->maxlight = sector->lightlevel; - g->thinker.function.acp1 = (actionf_p1) T_Glow; - g->direction = -1; - - sector->special = 0; -} - diff --git a/games/NXDoom/src/strife/p_local.h b/games/NXDoom/src/strife/p_local.h deleted file mode 100644 index abbb071ba4b..00000000000 --- a/games/NXDoom/src/strife/p_local.h +++ /dev/null @@ -1,311 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Play functions, animation, global header. -// - - -#ifndef __P_LOCAL__ -#define __P_LOCAL__ - -#ifndef __R_LOCAL__ -#include "r_local.h" -#endif - -#define FLOATSPEED (FRACUNIT*5) // villsa [STRIFE] change to 5 (was 4) - - -#define MAXHEALTH 100 -#define VIEWHEIGHT (41*FRACUNIT) - -// mapblocks are used to check movement -// against lines and things -#define MAPBLOCKUNITS 128 -#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) -#define MAPBLOCKSHIFT (FRACBITS+7) -#define MAPBMASK (MAPBLOCKSIZE-1) -#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) - - -// player radius for movement checking -#define PLAYERRADIUS 16*FRACUNIT - -// MAXRADIUS is for precalculated sector block boxes -// the spider demon is larger, -// but we do not have any moving sectors nearby -#define MAXRADIUS 32*FRACUNIT - -#define GRAVITY FRACUNIT -#define MAXMOVE (30*FRACUNIT) - -#define USERANGE (64*FRACUNIT) -#define MELEERANGE (64*FRACUNIT) -#define PLAYERMELEERANGE (80*FRACUNIT) // haleyjd [STRIFE] New constant -#define MISSILERANGE (32*64*FRACUNIT) - -// follow a player exlusively for 3 seconds -#define BASETHRESHOLD 100 - - - -// -// P_TICK -// - -// both the head and tail of the thinker list -extern thinker_t thinkercap; - - -void P_InitThinkers (void); -void P_AddThinker (thinker_t* thinker); -void P_RemoveThinker (thinker_t* thinker); - - -// -// P_PSPR -// -void P_SetupPsprites (player_t* curplayer); -void P_MovePsprites (player_t* curplayer); -void P_DropWeapon (player_t* player); - - -// -// P_USER -// - -// haleyjd 09/15/10: externalized -#define INVERSECOLORMAP 32 - -void P_PlayerThink (player_t* player); -// haleyjd 08/30/10: [STRIFE] Needed externally -void P_Thrust (player_t* player, angle_t angle, fixed_t move); -// villsa [STRIFE] -const char *P_RemoveInventoryItem(player_t *player, int slot, int amount); - - -// -// P_MOBJ -// -#define ONFLOORZ INT_MIN -#define ONCEILINGZ INT_MAX - -// Time interval for item respawning. -#define ITEMQUESIZE 128 - -extern mapthing_t itemrespawnque[ITEMQUESIZE]; -extern int itemrespawntime[ITEMQUESIZE]; -extern int iquehead; -extern int iquetail; - - -void P_RespawnSpecials (void); - -mobj_t* -P_SpawnMobj -( fixed_t x, - fixed_t y, - fixed_t z, - mobjtype_t type ); - -void P_RemoveMobj (mobj_t* th); -mobj_t* P_SubstNullMobj (mobj_t* th); -boolean P_SetMobjState (mobj_t* mobj, statenum_t state); -void P_MobjThinker (mobj_t* mobj); - -void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); -mobj_t* P_SpawnSparkPuff(fixed_t x, fixed_t y, fixed_t z); // villsa [STRIFE] -void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); -mobj_t* P_SpawnMissile (mobj_t* source, mobj_t* dest, mobjtype_t type); -mobj_t* P_SpawnFacingMissile(mobj_t* source, mobj_t* target, mobjtype_t type); // villsa [STRIFE] -mobj_t* P_SpawnPlayerMissile(mobj_t* source, mobjtype_t type); -mobj_t* P_SpawnMortar(mobj_t *source, mobjtype_t type); // villsa [STRIFE] -void P_ExplodeMissile (mobj_t* mo); // villsa [STRIFE] - - -// -// P_ENEMY -// -void P_NoiseAlert (mobj_t* target, mobj_t* emmiter); -void P_DoPunchAlert(mobj_t *puncher, mobj_t *punchee); // villsa [STRIFE] -void A_BodyParts(mobj_t *actor); // haleyjd: [STRIFE] -void A_AlertSpectreC(mobj_t* actor); -void A_FaceTarget (mobj_t* actor); -void P_FreePrisoners(void); -void P_DestroyConverter(void); - -// -// P_MAPUTL -// -typedef struct -{ - fixed_t x; - fixed_t y; - fixed_t dx; - fixed_t dy; - -} divline_t; - -typedef struct -{ - fixed_t frac; // along trace line - boolean isaline; - union { - mobj_t* thing; - line_t* line; - } d; -} intercept_t; - -// Extended MAXINTERCEPTS, to allow for intercepts overrun emulation. - -#define MAXINTERCEPTS_ORIGINAL 128 -#define MAXINTERCEPTS (MAXINTERCEPTS_ORIGINAL + 61) - -extern intercept_t intercepts[MAXINTERCEPTS]; -extern intercept_t* intercept_p; - -typedef boolean (*traverser_t) (intercept_t *in); - -fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); -int P_PointOnLineSide (fixed_t x, fixed_t y, line_t* line); -int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t* line); -void P_MakeDivline (line_t* li, divline_t* dl); -fixed_t P_InterceptVector (divline_t* v2, divline_t* v1); -int P_BoxOnLineSide (fixed_t* tmbox, line_t* ld); - -extern fixed_t opentop; -extern fixed_t openbottom; -extern fixed_t openrange; -extern fixed_t lowfloor; - -void P_LineOpening (line_t* linedef); - -boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); -boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ); - -#define PT_ADDLINES 1 -#define PT_ADDTHINGS 2 -#define PT_EARLYOUT 4 - -extern divline_t trace; - -boolean -P_PathTraverse -( fixed_t x1, - fixed_t y1, - fixed_t x2, - fixed_t y2, - int flags, - boolean (*trav) (intercept_t *)); - -void P_UnsetThingPosition (mobj_t* thing); -void P_SetThingPosition (mobj_t* thing); - - -// -// P_MAP -// - -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -extern boolean floatok; -extern fixed_t tmfloorz; -extern fixed_t tmceilingz; - -extern line_t *ceilingline; -extern line_t *blockingline; // [STRIFE] New global - -extern int numspechit; -extern line_t *spechit[]; - -extern fixed_t attackrange; - -// slopes to top and bottom of target -extern fixed_t topslope; -extern fixed_t bottomslope; - - -boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); -boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y); -boolean P_CheckPositionZ(mobj_t* thing, fixed_t z); // villsa [STRIFE] -boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y); -void P_SlideMove (mobj_t* mo); -boolean P_CheckSight (mobj_t* t1, mobj_t* t2); -void P_UseLines (player_t* player); - -boolean P_ChangeSector (sector_t* sector, boolean crunch); - -extern mobj_t* linetarget; // who got hit (or NULL) - -fixed_t -P_AimLineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance ); - -void -P_LineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance, - fixed_t slope, - int damage ); - -void -P_RadiusAttack -( mobj_t* spot, - mobj_t* source, - int damage ); - - - -// -// P_SETUP -// -extern byte* rejectmatrix; // for fast sight rejection -extern short* blockmaplump; // offsets in blockmap are from here -extern short* blockmap; -extern int bmapwidth; -extern int bmapheight; // in mapblocks -extern fixed_t bmaporgx; -extern fixed_t bmaporgy; // origin of block map -extern mobj_t** blocklinks; // for thing chains - - -// -// P_INTER -// -extern int maxammo[NUMAMMO]; -extern int clipammo[NUMAMMO]; - -void -P_TouchSpecialThing -( mobj_t* special, - mobj_t* toucher ); - -void -P_DamageMobj -( mobj_t* target, - mobj_t* inflictor, - mobj_t* source, - int damage ); - - -// -// P_SPEC -// -#include "p_spec.h" - - -#endif // __P_LOCAL__ diff --git a/games/NXDoom/src/strife/p_map.c b/games/NXDoom/src/strife/p_map.c deleted file mode 100644 index 0aa2862f937..00000000000 --- a/games/NXDoom/src/strife/p_map.c +++ /dev/null @@ -1,1643 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard, Andrey Budko -// -// 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. -// -// DESCRIPTION: -// Movement, collision handling. -// Shooting and aiming. -// - -#include -#include - -#include "deh_misc.h" - -#include "m_bbox.h" -#include "m_random.h" -#include "i_system.h" - -#include "doomdef.h" -#include "m_argv.h" -#include "m_misc.h" -#include "p_local.h" - -#include "s_sound.h" - -// State. -#include "doomstat.h" -#include "r_state.h" -// Data. -#include "sounds.h" - -// Spechit overrun magic value. -// -// This is the value used by PrBoom-plus. I think the value below is -// actually better and works with more demos. However, I think -// it's better for the spechits emulation to be compatible with -// PrBoom-plus, at least so that the big spechits emulation list -// on Doomworld can also be used with Chocolate Doom. - -#define DEFAULT_SPECHIT_MAGIC 0x01C09C98 - -// This is from a post by myk on the Doomworld forums, -// outputted from entryway's spechit_magic generator for -// s205n546.lmp. The _exact_ value of this isn't too -// important; as long as it is in the right general -// range, it will usually work. Otherwise, we can use -// the generator (hacked doom2.exe) and provide it -// with -spechit. - -//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8 - - -fixed_t tmbbox[4]; -mobj_t* tmthing; -int tmflags; -fixed_t tmx; -fixed_t tmy; - - -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -boolean floatok; - -fixed_t tmfloorz; -fixed_t tmceilingz; -fixed_t tmdropoffz; - -// keep track of the line that lowers the ceiling, -// so missiles don't explode against sky hack walls -line_t* ceilingline; - -// haleyjd 20110203: [STRIFE] New global -// "blockingline" tracks the linedef responsible for blocking motion of an mobj -// for purposes of doing impact special activation by missiles. Suspiciously -// similar to the solution used by Raven in Heretic and Hexen. -line_t *blockingline; - -// keep track of special lines as they are hit, -// but don't process them until the move is proven valid - -// fraggle: I have increased the size of this buffer. In the original Doom, -// overrunning past this limit caused other bits of memory to be overwritten, -// affecting demo playback. However, in doing so, the limit was still -// exceeded. So we have to support more than 8 specials. -// -// We keep the original limit, to detect what variables in memory were -// overwritten (see SpechitOverrun()) - -#define MAXSPECIALCROSS 20 -#define MAXSPECIALCROSS_ORIGINAL 8 - -line_t* spechit[MAXSPECIALCROSS]; -int numspechit; - - - -// -// TELEPORT MOVE -// - -// -// PIT_StompThing -// -// [STRIFE] haleyjd 09/15/10: Modified so monsters can telestomp. -// -boolean PIT_StompThing (mobj_t* thing) -{ - fixed_t blockdist; - - if (!(thing->flags & MF_SHOOTABLE) ) - return true; - - blockdist = thing->radius + tmthing->radius; - - if ( abs(thing->x - tmx) >= blockdist - || abs(thing->y - tmy) >= blockdist ) - { - // didn't hit it - return true; - } - - // don't clip against self - if (thing == tmthing) - return true; - - // [STRIFE] monsters DO stomp things, on all levels - // Basically, one thing involved must be a player. - // Monsters can telefrag players, and players can telefrag monsters, but - // monsters cannot telefrag other monsters. - if (!(tmthing->player || thing->player)) - return false; - - P_DamageMobj (thing, tmthing, tmthing, 10000); - - return true; -} - - -// -// P_TeleportMove -// -// [STRIFE] -// haleyjd 09/15/10: Modified to set thing z position. -// -boolean P_TeleportMove(mobj_t* thing, fixed_t x, fixed_t y) -{ - int xl; - int xh; - int yl; - int yh; - int bx; - int by; - - subsector_t* newsubsec; - - // kill anything occupying the position - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector (x,y); - ceilingline = NULL; - - // The base floor/ceiling is from the subsector - // that contains the point. - // Any contacted lines the step closer together - // will adjust them. - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - - // stomp on any things contacted - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockThingsIterator(bx,by,PIT_StompThing)) - return false; - - // the move is ok, - // so link the thing into its new position - P_UnsetThingPosition (thing); - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - thing->z = tmfloorz; // haleyjd 09/15/10: [STRIFE] Rogue added a z-set here - - P_SetThingPosition (thing); - - return true; -} - - -// -// MOVEMENT ITERATOR FUNCTIONS -// - -static void SpechitOverrun(line_t *ld); - -// -// PIT_CheckLine -// Adjusts tmfloorz and tmceilingz as lines are contacted -// -boolean PIT_CheckLine (line_t* ld) -{ - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) - return true; - - if (P_BoxOnLineSide (tmbbox, ld) != -1) - return true; - - // A line has been hit - - // The moving thing's destination position will cross - // the given line. - // If this should not be allowed, return false. - // If the line is special, keep track of it - // to process later if the move is proven ok. - // NOTE: specials are NOT sorted by order, - // so two special lines that are only 8 pixels apart - // could be crossed in either order. - - if (!ld->backsector) - return false; // one sided line - - if (!(tmthing->flags & MF_MISSILE) ) - { - // villsa [STRIFE] include jumpover flag - if ( ld->flags & ML_BLOCKING && - (!(ld->flags & ML_JUMPOVER) || tmfloorz + (32*FRACUNIT) > tmthing->z) ) - return false; // explicitly blocking everything - - // villsa [STRIFE] exclude floaters from blockmonster lines - if ( !tmthing->player && (ld->flags & ML_BLOCKMONSTERS) && - !(tmthing->flags & MF_FLOAT)) - return false; // block monsters only - - // villsa [STRIFE] - if ( ld->flags & ML_BLOCKFLOATERS && tmthing->flags & MF_FLOAT ) - return false; // block floaters only - } - - // set openrange, opentop, openbottom - P_LineOpening (ld); - - // adjust floor / ceiling heights - if (opentop < tmceilingz) - { - tmceilingz = opentop; - ceilingline = ld; - } - - if (openbottom > tmfloorz) - tmfloorz = openbottom; - - if (lowfloor < tmdropoffz) - tmdropoffz = lowfloor; - - // if contacted a special line, add it to the list - if (ld->special) - { - spechit[numspechit] = ld; - numspechit++; - - // fraggle: spechits overrun emulation code from prboom-plus - if (numspechit > MAXSPECIALCROSS_ORIGINAL) - { - SpechitOverrun(ld); - } - } - - return true; -} - -// -// PIT_CheckThing -// -boolean PIT_CheckThing (mobj_t* thing) -{ - fixed_t blockdist; - boolean solid; - int damage; - - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) )) - return true; - - // don't clip against self - if (thing == tmthing) - return true; - - blockdist = thing->radius + tmthing->radius; - - if ( abs(thing->x - tmx) >= blockdist - || abs(thing->y - tmy) >= blockdist ) - { - // didn't hit it - return true; - } - - // villsa [STRIFE] see if it went over / under - if(thing->height + thing->z < tmthing->z) - return true; // overhead - - // villsa [STRIFE] see if it went over / under - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - - // villsa [STRIFE] unused - // check for skulls slamming into things (removed) - - // missiles can hit other things - if (tmthing->flags & MF_MISSILE) - { - // villsa [STRIFE] code to check over/under clipping moved to the beginning of the - // function, so that it applies to everything. - - // villsa [STRIFE] updated to strife version - if (tmthing->target && (tmthing->target->type == thing->type)) - { - // Don't hit same species as originator. - if (thing == tmthing->target) - return true; - - // sdh: Add deh_species_infighting here. We can override the - // "monsters of the same species cant hurt each other" behavior - // through dehacked patches - - if (thing->type != MT_PLAYER && !deh_species_infighting) - { - // Explode, but do no damage. - // Let players missile other players. - return false; - } - } - - if (!(thing->flags & MF_SHOOTABLE)) - { - // didn't do any damage - return !(thing->flags & MF_SOLID); - } - - // haleyjd 09/01/10: [STRIFE] Spectral check: - // Missiles cannot hit SPECTRAL entities unless the missiles are also - // flagged as SPECTRAL. - if (thing->flags & MF_SPECTRAL && !(tmthing->flags & MF_SPECTRAL)) - return true; // keep going - - // damage / explode - // haleyjd 09/01/10: [STRIFE] Modified missile damage formula - damage = ((P_Random()&3)+1)*tmthing->info->damage; - P_DamageMobj (thing, tmthing, tmthing->target, damage); - - // don't traverse any more - return false; - } - - // check for special pickup - if (thing->flags & MF_SPECIAL) - { - solid = (thing->flags & MF_SOLID) != 0; - if (tmthing->player) // villsa [STRIFE] no longer checks MF_PICKUP flag - { - // can remove thing - P_TouchSpecialThing (thing, tmthing); - } - return !solid; - } - - return !(thing->flags & MF_SOLID); -} - - -// -// MOVEMENT CLIPPING -// - -// -// P_CheckPosition -// This is purely informative, nothing is modified -// (except things picked up). -// -// in: -// a mobj_t (can be valid or invalid) -// a position to be checked -// (doesn't need to be related to the mobj_t->x,y) -// -// during: -// special things are touched if MF_PICKUP -// early out on solid lines? -// -// out: -// newsubsec -// floorz -// ceilingz -// tmdropoffz -// the lowest point contacted -// (monsters won't move to a dropoff) -// speciallines[] -// numspeciallines -// -// haleyjd 20110203: -// [STRIFE] Modified to clear blockingline in advance of P_BlockLinesIterator -// -boolean -P_CheckPosition -( mobj_t* thing, - fixed_t x, - fixed_t y ) -{ - int xl; - int xh; - int yl; - int yh; - int bx; - int by; - subsector_t* newsubsec; - - tmthing = thing; - tmflags = thing->flags; - - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - newsubsec = R_PointInSubsector (x,y); - - // [STRIFE] clear blockingline (see P_XYMovement, P_BlockLinesIterator) - blockingline = NULL; - ceilingline = NULL; - - // The base floor / ceiling is from the subsector - // that contains the point. - // Any contacted lines the step closer together - // will adjust them. - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - validcount++; - numspechit = 0; - - if ( tmflags & MF_NOCLIP ) - return true; - - // Check things first, possibly picking things up. - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) - return false; - - // check lines - xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; - - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) - return false; - - return true; -} - - -// -// P_TryMove -// Attempt to move to a new position, -// crossing special lines unless MF_TELEPORT is set. -// -boolean -P_TryMove -( mobj_t* thing, - fixed_t x, - fixed_t y ) -{ - fixed_t oldx; - fixed_t oldy; - int side; - int oldside; - line_t* ld; - - floatok = false; - if (!P_CheckPosition (thing, x, y)) - return false; // solid wall or thing - - if ( !(thing->flags & MF_NOCLIP) ) - { - if (tmceilingz - tmfloorz < thing->height) - return false; // doesn't fit - - floatok = true; - - // villsa [STRIFE] Removed MF_TELEPORT - if (tmceilingz - thing->z < thing->height) - return false; // mobj must lower itself to fit - - // villsa [STRIFE] non-robots are limited to 16 unit step height - if ((thing->flags & MF_NOBLOOD) == 0 && tmfloorz - thing->z > (16*FRACUNIT)) - return false; - if (tmfloorz - thing->z > 24*FRACUNIT) - return false; // too big a step up - - // villsa [STRIFE] special case for missiles - if((thing->flags & MF_MISSILE) && tmfloorz - thing->z > 4*FRACUNIT) - return false; - - // haleyjd 20110204 [STRIFE]: dropoff height changed 24 -> 32 - if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) - && tmfloorz - tmdropoffz > 32*FRACUNIT ) - return false; // don't stand over a dropoff - } - - // the move is ok, - // so link the thing into its new position - P_UnsetThingPosition (thing); - - oldx = thing->x; - oldy = thing->y; - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - thing->x = x; - thing->y = y; - - P_SetThingPosition (thing); - - // if any special lines were hit, do the effect - if (! (thing->flags&MF_NOCLIP) ) // villsa [STRIFE] MF_TELEPORT not used - { - while (numspechit--) - { - // see if the line was crossed - ld = spechit[numspechit]; - side = P_PointOnLineSide (thing->x, thing->y, ld); - oldside = P_PointOnLineSide (oldx, oldy, ld); - if (side != oldside) - { - if (ld->special) - P_CrossSpecialLine (ld-lines, oldside, thing); - } - } - } - - return true; -} - -// -// P_CheckPositionZ -// -// villsa [STRIFE] new function -// Check colliding things on top of one another; ie., 3D Object Clipping -// -boolean P_CheckPositionZ(mobj_t* thing, fixed_t height) -{ - fixed_t x; - fixed_t y; - fixed_t z; - int xl; - int xh; - int yl; - int yh; - int bx; - int by; - subsector_t* newsubsec; - - x = thing->x; - y = thing->y; - z = thing->z; - - thing->z = height; - - tmthing = thing; - tmflags = thing->flags; - tmx = x; - tmy = y; - - tmbbox[BOXTOP] = y + tmthing->radius; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; - - ceilingline = 0; - newsubsec = thing->subsector; - - // The base floor / ceiling is from the subsector - // that contains the point. - // Any contacted lines the step closer together - // will adjust them. - - tmfloorz = tmdropoffz = newsubsec->sector->floorheight; - tmceilingz = newsubsec->sector->ceilingheight; - - if(tmflags & MF_NOCLIP) - return true; - - // Check things first, possibly picking things up. - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - - xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; - - for(bx = xl; bx <= xh; bx++) - { - for(by = yl; by <= yh; by++) - { - if(!P_BlockThingsIterator(bx, by, PIT_CheckThing)) - { - tmthing->z = z; - return false; - } - } - } - - return true; -} - - -// -// P_ThingHeightClip -// Takes a valid thing and adjusts the thing->floorz, -// thing->ceilingz, and possibly thing->z. -// This is called for all nearby monsters -// whenever a sector changes height. -// If the thing doesn't fit, -// the z will be set to the lowest value -// and false will be returned. -// -// [STRIFE] Verified unmodified -// -boolean P_ThingHeightClip (mobj_t* thing) -{ - boolean onfloor; - - onfloor = (thing->z == thing->floorz); - - P_CheckPosition (thing, thing->x, thing->y); - // what about stranding a monster partially off an edge? - - thing->floorz = tmfloorz; - thing->ceilingz = tmceilingz; - - if (onfloor) - { - // walking monsters rise and fall with the floor - thing->z = thing->floorz; - } - else - { - // don't adjust a floating monster unless forced to - if (thing->z+thing->height > thing->ceilingz) - thing->z = thing->ceilingz - thing->height; - } - - if (thing->ceilingz - thing->floorz < thing->height) - return false; - - return true; -} - - - -// -// SLIDE MOVE -// Allows the player to slide along any angled walls. -// -fixed_t bestslidefrac; -fixed_t secondslidefrac; - -line_t* bestslideline; -line_t* secondslideline; - -mobj_t* slidemo; - -fixed_t tmxmove; -fixed_t tmymove; - - - -// -// P_HitSlideLine -// Adjusts the xmove / ymove -// so that the next move will slide along the wall. -// -// [STRIFE] Verified unmodified -// -void P_HitSlideLine (line_t* ld) -{ - int side; - - angle_t lineangle; - angle_t moveangle; - angle_t deltaangle; - - fixed_t movelen; - fixed_t newlen; - - - if (ld->slopetype == ST_HORIZONTAL) - { - tmymove = 0; - return; - } - - if (ld->slopetype == ST_VERTICAL) - { - tmxmove = 0; - return; - } - - side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); - - lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); - - if (side == 1) - lineangle += ANG180; - - moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); - deltaangle = moveangle-lineangle; - - if (deltaangle > ANG180) - deltaangle += ANG180; - // I_Error ("SlideLine: ang>ANG180"); - - lineangle >>= ANGLETOFINESHIFT; - deltaangle >>= ANGLETOFINESHIFT; - - movelen = P_AproxDistance (tmxmove, tmymove); - newlen = FixedMul (movelen, finecosine[deltaangle]); - - tmxmove = FixedMul (newlen, finecosine[lineangle]); - tmymove = FixedMul (newlen, finesine[lineangle]); -} - - -// -// PTR_SlideTraverse -// -// [STRIFE] Modified for smaller step-up height -// -boolean PTR_SlideTraverse (intercept_t* in) -{ - line_t* li; - - if (!in->isaline) - I_Error ("PTR_SlideTraverse: not a line?"); - - li = in->d.line; - - if ( ! (li->flags & ML_TWOSIDED) ) - { - if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) - { - // don't hit the back side - return true; - } - goto isblocking; - } - - // set openrange, opentop, openbottom - P_LineOpening (li); - - if (openrange < slidemo->height) - goto isblocking; // doesn't fit - - if (opentop - slidemo->z < slidemo->height) - goto isblocking; // mobj is too high - - // villsa [STRIFE] change from 24 to 16 - if (openbottom - slidemo->z > 16*FRACUNIT ) - goto isblocking; // too big a step up - - // this line doesn't block movement - return true; - - // the line does block movement, - // see if it is closer than best so far -isblocking: - if (in->frac < bestslidefrac) - { - secondslidefrac = bestslidefrac; - secondslideline = bestslideline; - bestslidefrac = in->frac; - bestslideline = li; - } - - return false; // stop -} - - - -// -// P_SlideMove -// The momx / momy move is bad, so try to slide -// along a wall. -// Find the first line hit, move flush to it, -// and slide along it -// -// This is a kludgy mess. -// -// [STRIFE] Verified unmodified -// -void P_SlideMove (mobj_t* mo) -{ - fixed_t leadx; - fixed_t leady; - fixed_t trailx; - fixed_t traily; - fixed_t newx; - fixed_t newy; - int hitcount; - - slidemo = mo; - hitcount = 0; - -retry: - if (++hitcount == 3) - goto stairstep; // don't loop forever - - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT+1; - - P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, - PT_ADDLINES, PTR_SlideTraverse ); - P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, - PT_ADDLINES, PTR_SlideTraverse ); - P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, - PT_ADDLINES, PTR_SlideTraverse ); - - // move up to the wall - if (bestslidefrac == FRACUNIT+1) - { - // the move most have hit the middle, so stairstep -stairstep: - if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) - P_TryMove (mo, mo->x + mo->momx, mo->y); - return; - } - - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) - { - newx = FixedMul (mo->momx, bestslidefrac); - newy = FixedMul (mo->momy, bestslidefrac); - - if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) - goto stairstep; - } - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT-(bestslidefrac+0x800); - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) - return; - - tmxmove = FixedMul (mo->momx, bestslidefrac); - tmymove = FixedMul (mo->momy, bestslidefrac); - - P_HitSlideLine (bestslideline); // clip the moves - - mo->momx = tmxmove; - mo->momy = tmymove; - - if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove)) - { - goto retry; - } -} - - -// -// P_LineAttack -// -mobj_t* linetarget; // who got hit (or NULL) -mobj_t* shootthing; - -// Height if not aiming up or down -// ???: use slope for monsters? -fixed_t shootz; - -int la_damage; -fixed_t attackrange; - -fixed_t aimslope; - - -// -// PTR_AimTraverse -// Sets linetaget and aimslope when a target is aimed at. -// -// [STRIFE] Verified unmodified -// -boolean -PTR_AimTraverse (intercept_t* in) -{ - line_t* li; - mobj_t* th; - fixed_t slope; - fixed_t thingtopslope; - fixed_t thingbottomslope; - fixed_t dist; - - if (in->isaline) - { - li = in->d.line; - - if ( !(li->flags & ML_TWOSIDED) ) - return false; // stop - - // Crosses a two sided line. - // A two sided line will restrict - // the possible target ranges. - P_LineOpening (li); - - if (openbottom >= opentop) - return false; // stop - - dist = FixedMul (attackrange, in->frac); - - // Return false if there is no back sector. This should never - // be the case if the line is two-sided; however, some WADs - // (eg. ottawau.wad) use this as an "impassible glass" trick - // and rely on Vanilla Doom's (unintentional) support for this. - - if (li->backsector == NULL) - { - return false; - } - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv (openbottom - shootz , dist); - if (slope > bottomslope) - bottomslope = slope; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv (opentop - shootz , dist); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - - return true; // shot continues - } - - // shoot a thing - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - - if (!(th->flags&MF_SHOOTABLE)) - return true; // corpse or something - - // check angles to see if the thing can be aimed at - dist = FixedMul (attackrange, in->frac); - thingtopslope = FixedDiv (th->z+th->height - shootz , dist); - - if (thingtopslope < bottomslope) - return true; // shot over the thing - - thingbottomslope = FixedDiv (th->z - shootz, dist); - - if (thingbottomslope > topslope) - return true; // shot under the thing - - // this thing can be hit! - if (thingtopslope > topslope) - thingtopslope = topslope; - - if (thingbottomslope < bottomslope) - thingbottomslope = bottomslope; - - aimslope = (thingtopslope+thingbottomslope)/2; - linetarget = th; - - return false; // don't go any farther -} - - -// -// PTR_ShootTraverse -// -// [STRIFE] Changes for Spectres and Mauler puff/damage inflictor -// -boolean PTR_ShootTraverse (intercept_t* in) -{ - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t frac; - - line_t* li; - - mobj_t* th; - mobj_t* th2; // villsa [STRIFE] - - fixed_t slope; - fixed_t dist; - fixed_t thingtopslope; - fixed_t thingbottomslope; - - if (in->isaline) - { - li = in->d.line; - - if (li->special) - P_ShootSpecialLine (shootthing, li); - - if ( !(li->flags & ML_TWOSIDED) ) - goto hitline; - - // crosses a two sided line - P_LineOpening (li); - - dist = FixedMul (attackrange, in->frac); - - // Check if backsector is NULL. See comment in PTR_AimTraverse. - - if (li->backsector == NULL) - { - goto hitline; - } - - if (li->frontsector->floorheight != li->backsector->floorheight) - { - slope = FixedDiv (openbottom - shootz , dist); - if (slope > aimslope) - goto hitline; - } - - if (li->frontsector->ceilingheight != li->backsector->ceilingheight) - { - slope = FixedDiv (opentop - shootz , dist); - if (slope < aimslope) - goto hitline; - } - - // shot continues - return true; - - - // hit line -hitline: - // position a bit closer - frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); - x = trace.x + FixedMul (trace.dx, frac); - y = trace.y + FixedMul (trace.dy, frac); - z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); - - if (li->frontsector->ceilingpic == skyflatnum) - { - // don't shoot the sky! - if (z > li->frontsector->ceilingheight) - return false; - - // it's a sky hack wall - if (li->backsector && li->backsector->ceilingpic == skyflatnum) - return false; - } - - // villsa [STRIFE] - if(la_damage > 0) - { - // villsa [STRIFE] Test against Mauler attack range - if(attackrange != 2112*FRACUNIT) - P_SpawnPuff(x, y, z); // Spawn bullet puffs. - else - P_SpawnMobj(x, y, z, MT_STRIFEPUFF3); - } - - // don't go any farther - return false; - } - - // shoot a thing - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - - if (!(th->flags&MF_SHOOTABLE)) - return true; // corpse or something - - // haleyjd 09/18/10: [STRIFE] Corrected - not MVIS, but SPECTRAL. - if(th->flags & MF_SPECTRAL) - return true; // is a spectral entity - - // check angles to see if the thing can be aimed at - dist = FixedMul (attackrange, in->frac); - thingtopslope = FixedDiv (th->z+th->height - shootz , dist); - - if (thingtopslope < aimslope) - return true; // shot over the thing - - thingbottomslope = FixedDiv (th->z - shootz, dist); - - if (thingbottomslope > aimslope) - return true; // shot under the thing - - // hit thing - // position a bit closer - frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); - - x = trace.x + FixedMul (trace.dx, frac); - y = trace.y + FixedMul (trace.dy, frac); - z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); - - // villsa [STRIFE] Check for Mauler attack range - if(attackrange == 2112*FRACUNIT) - { - th2 = P_SpawnMobj(x, y, z, MT_STRIFEPUFF3); - th2->momz = -FRACUNIT; - P_DamageMobj(th, th2, shootthing, la_damage); - return false; - } - - // villsa [STRIFE] disabled check for damage - //if (la_damage) - P_DamageMobj (th, shootthing, shootthing, la_damage); - - // Spawn bullet puffs or blod spots, - // depending on target type. - if (in->d.thing->flags & MF_NOBLOOD) - P_SpawnSparkPuff(x, y, z); // villsa [STRIFE] call spark puff function instead - else - P_SpawnBlood (x,y,z, la_damage); - - // don't go any farther - return false; - -} - - -// -// P_AimLineAttack -// -// [STRIFE] Modified to support player->pitch -// -fixed_t -P_AimLineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance ) -{ - fixed_t x2; - fixed_t y2; - - t1 = P_SubstNullMobj(t1); - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; - - // can't shoot outside view angles - topslope = 100*FRACUNIT/160; - bottomslope = -100*FRACUNIT/160; - - attackrange = distance; - linetarget = NULL; - - P_PathTraverse ( t1->x, t1->y, - x2, y2, - PT_ADDLINES|PT_ADDTHINGS, - PTR_AimTraverse ); - - if (linetarget) - return aimslope; - else // villsa [STRIFE] checks for player pitch - { - if(t1->player) - return (t1->player->pitch << FRACBITS) / 160; - } - - return 0; -} - - -// -// P_LineAttack -// If damage == 0, it is just a test trace -// that will leave linetarget set. -// -// [STRIFE] Modified to check lines only if damage <= 0 (see P_RadiusAttack) -// -void -P_LineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance, - fixed_t slope, - int damage ) -{ - fixed_t x2; - fixed_t y2; - int traverseflags; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - la_damage = damage; - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; - attackrange = distance; - aimslope = slope; - - // villsa [STRIFE] test lines only if damage is <= 0 - if(damage >= 1) - traverseflags = (PT_ADDLINES|PT_ADDTHINGS); - else - traverseflags = PT_ADDLINES; - - P_PathTraverse(t1->x, t1->y, - x2, y2, - traverseflags, - PTR_ShootTraverse); -} - - - -// -// USE LINES -// -// [STRIFE] Verified unmodified -// -mobj_t* usething; - -boolean PTR_UseTraverse (intercept_t* in) -{ - int side; - - if (!in->d.line->special) - { - P_LineOpening (in->d.line); - if (openrange <= 0) - { - S_StartSound (usething, sfx_noway); - - // can't use through a wall - return false; - } - // not a special line, but keep checking - return true ; - } - - side = 0; - if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) - side = 1; - - // return false; // don't use back side - - P_UseSpecialLine (usething, in->d.line, side); - - // can't use for than one special line in a row - return false; -} - - -// -// P_UseLines -// Looks for special lines in front of the player to activate. -// -// [STRIFE] Verified unmodified -// -void P_UseLines (player_t* player) -{ - int angle; - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - usething = player->mo; - - angle = player->mo->angle >> ANGLETOFINESHIFT; - - x1 = player->mo->x; - y1 = player->mo->y; - x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; - y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; - - P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); -} - - -// -// RADIUS ATTACK -// -mobj_t* bombsource; -mobj_t* bombspot; -int bombdamage; - - -// -// PIT_RadiusAttack -// "bombsource" is the creature -// that caused the explosion at "bombspot". -// -// [STRIFE] Modified for Spectral and Inquisitor exclusions -// -boolean PIT_RadiusAttack (mobj_t* thing) -{ - fixed_t dx; - fixed_t dy; - fixed_t dist; - - if (!(thing->flags & MF_SHOOTABLE)) - return true; - - // haleyjd 10/04/10: Spectrals are not damaged by blast radii - if(thing->flags & MF_SPECTRAL) - return true; - - // Boss spider and cyborg - // take no damage from concussion. - // villsa [STRIFE] unused - // - haleyjd: INQUISITOR - - if(thing->type == MT_INQUISITOR) - return true; - - dx = abs(thing->x - bombspot->x); - dy = abs(thing->y - bombspot->y); - - dist = dx>dy ? dx : dy; - dist = (dist - thing->radius) >> FRACBITS; - - if (dist < 0) - dist = 0; - - if (dist >= bombdamage) - return true; // out of range - - if ( P_CheckSight (thing, bombspot) ) - { - // must be in direct path - P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist); - } - - return true; -} - - -// -// P_RadiusAttack -// Source is the creature that caused the explosion at spot. -// -// [STRIFE] Modified to emit "test" tracers which can shatter glass screens -// and windows. -// -void -P_RadiusAttack -( mobj_t* spot, - mobj_t* source, - int damage ) -{ - int x; - int y; - - int xl; - int xh; - int yl; - int yh; - - fixed_t dist; - - dist = (damage+MAXRADIUS)<y + dist - bmaporgy)>>MAPBLOCKSHIFT; - yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; - xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; - xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; - bombspot = spot; - bombsource = source; - bombdamage = damage; - - for (y=yl ; y<=yh ; y++) - for (x=xl ; x<=xh ; x++) - P_BlockThingsIterator (x, y, PIT_RadiusAttack ); - - // villsa [STRIFE] Send out 0 damage tracers to shatter nearby glass. - spot->z += 32*FRACUNIT; - P_LineAttack(spot, 0, dist, 1, 0); - P_LineAttack(spot, ANG90, dist, 1, 0); - P_LineAttack(spot, ANG180, dist, 1, 0); - P_LineAttack(spot, ANG270, dist, 1, 0); - spot->z -= 32*FRACUNIT; -} - - - -// -// SECTOR HEIGHT CHANGING -// After modifying a sectors floor or ceiling height, -// call this routine to adjust the positions -// of all things that touch the sector. -// -// If anything doesn't fit anymore, true will be returned. -// If crunch is true, they will take damage -// as they are being crushed. -// If Crunch is false, you should set the sector height back -// the way it was and call P_ChangeSector again -// to undo the changes. -// -boolean crushchange; -boolean nofit; - - -// -// PIT_ChangeSector -// -// [STRIFE] Changes to crushing behavior -// -boolean PIT_ChangeSector (mobj_t* thing) -{ - mobj_t* mo; - - if (P_ThingHeightClip (thing)) - { - // keep checking - return true; - } - - // crunch bodies to giblets - if (thing->health <= 0) - { - // villsa [STRIFE] do something with the player - if(thing->player && thing->subsector->sector->specialdata) - { - nofit = true; - return false; - } - //P_SetMobjState (thing, S_GIBS); // villsa [STRIFE] unused - - A_BodyParts(thing); // villsa [STRIFE] spit out meat/junk stuff - thing->flags &= ~MF_SOLID; - thing->height = 0; - thing->radius = 0; - - // keep checking - return true; - } - - // crunch dropped items - if (thing->flags & MF_DROPPED) - { - P_RemoveMobj (thing); - - // keep checking - return true; - } - - if (! (thing->flags & MF_SHOOTABLE) ) - { - // assume it is bloody gibs or something - return true; - } - - nofit = true; - - if (crushchange && !(leveltime&3) ) - { - int t; - S_StartSound(thing, sfx_pcrush); // villsa [STRIFE] - P_DamageMobj(thing,NULL,NULL,10); - - // spray blood in a random direction - mo = P_SpawnMobj (thing->x, - thing->y, - thing->z + thing->height/2, MT_BLOOD_DEATH); - - t = P_Random(); - mo->momx = (t - P_Random ()) << 12; - t = P_Random(); - mo->momy = (t - P_Random ()) << 12; - } - - // keep checking (crush other things) - return true; -} - - - -// -// P_ChangeSector -// -// [STRIFE] Verified unmodified -// -boolean -P_ChangeSector -( sector_t* sector, - boolean crunch ) -{ - int x; - int y; - - nofit = false; - crushchange = crunch; - - // re-check heights for all things near the moving sector - for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++) - for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++) - P_BlockThingsIterator (x, y, PIT_ChangeSector); - - return nofit; -} - -// Code to emulate the behavior of Vanilla Doom when encountering an overrun -// of the spechit array. This is by Andrey Budko (e6y) and comes from his -// PrBoom plus port. A big thanks to Andrey for this. - -static void SpechitOverrun(line_t *ld) -{ - static unsigned int baseaddr = 0; - unsigned int addr; - - if (baseaddr == 0) - { - int p; - - // This is the first time we have had an overrun. Work out - // what base address we are going to use. - // Allow a spechit value to be specified on the command line. - - //! - // @category compat - // @arg - // - // Use the specified magic value when emulating spechit overruns. - // - - p = M_CheckParmWithArgs("-spechit", 1); - - if (p > 0) - { - M_StrToInt(myargv[p+1], (int *) &baseaddr); - } - else - { - baseaddr = DEFAULT_SPECHIT_MAGIC; - } - } - - // Calculate address used in doom2.exe - - addr = baseaddr + (ld - lines) * 0x3E; - - switch(numspechit) - { - case 9: - case 10: - case 11: - case 12: - tmbbox[numspechit-9] = addr; - break; - case 13: - nofit = addr; // haleyjd 20110204: nofit/crushchange are in opposite - break; // order in the Strife binary. - case 14: - crushchange = addr; - break; - default: - fprintf(stderr, "SpechitOverrun: Warning: unable to emulate" - "an overrun where numspechit=%i\n", - numspechit); - break; - } -} - diff --git a/games/NXDoom/src/strife/p_maputl.c b/games/NXDoom/src/strife/p_maputl.c deleted file mode 100644 index 78ae34712fd..00000000000 --- a/games/NXDoom/src/strife/p_maputl.c +++ /dev/null @@ -1,1056 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// Copyright(C) 2005, 2006 Andrey Budko -// -// 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. -// -// DESCRIPTION: -// Movement/collision utility functions, -// as used by function in p_map.c. -// BLOCKMAP Iterator functions, -// and some PIT_* functions to use for iteration. -// - - - -#include - - -#include "m_bbox.h" -#include "m_misc.h" - -#include "doomdef.h" -#include "doomstat.h" -#include "p_local.h" - - -// State. -#include "r_state.h" - -// -// P_AproxDistance -// Gives an estimation of distance (not exact) -// -// [STRIFE] Verified unmodified -// -fixed_t -P_AproxDistance -( fixed_t dx, - fixed_t dy ) -{ - dx = abs(dx); - dy = abs(dy); - if (dx < dy) - return dx+dy-(dx>>1); - return dx+dy-(dy>>1); -} - - -// -// P_PointOnLineSide -// Returns 0 or 1 -// -// [STRIFE] Verified unmodified -// -int -P_PointOnLineSide -( fixed_t x, - fixed_t y, - line_t* line ) -{ - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - if (!line->dx) - { - if (x <= line->v1->x) - return line->dy > 0; - - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->v1->y) - return line->dx < 0; - - return line->dx > 0; - } - - dx = (x - line->v1->x); - dy = (y - line->v1->y); - - left = FixedMul ( line->dy>>FRACBITS , dx ); - right = FixedMul ( dy , line->dx>>FRACBITS ); - - if (right < left) - return 0; // front side - return 1; // back side -} - - - -// -// P_BoxOnLineSide -// Considers the line to be infinite -// Returns side 0 or 1, -1 if box crosses the line. -// -// [STRIFE] Verified unmodified -// -int -P_BoxOnLineSide -( fixed_t* tmbox, - line_t* ld ) -{ - int p1 = 0; - int p2 = 0; - - switch (ld->slopetype) - { - case ST_HORIZONTAL: - p1 = tmbox[BOXTOP] > ld->v1->y; - p2 = tmbox[BOXBOTTOM] > ld->v1->y; - if (ld->dx < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - - case ST_VERTICAL: - p1 = tmbox[BOXRIGHT] < ld->v1->x; - p2 = tmbox[BOXLEFT] < ld->v1->x; - if (ld->dy < 0) - { - p1 ^= 1; - p2 ^= 1; - } - break; - - case ST_POSITIVE: - p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); - break; - - case ST_NEGATIVE: - p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); - p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); - break; - } - - if (p1 == p2) - return p1; - return -1; -} - - -// -// P_PointOnDivlineSide -// Returns 0 or 1. -// -// [STRIFE] Verified unmodified -// -int -P_PointOnDivlineSide -( fixed_t x, - fixed_t y, - divline_t* line ) -{ - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - if (!line->dx) - { - if (x <= line->x) - return line->dy > 0; - - return line->dy < 0; - } - if (!line->dy) - { - if (y <= line->y) - return line->dx < 0; - - return line->dx > 0; - } - - dx = (x - line->x); - dy = (y - line->y); - - // try to quickly decide by looking at sign bits - if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) - { - if ( (line->dy ^ dx) & 0x80000000 ) - return 1; // (left is negative) - return 0; - } - - left = FixedMul ( line->dy>>8, dx>>8 ); - right = FixedMul ( dy>>8 , line->dx>>8 ); - - if (right < left) - return 0; // front side - return 1; // back side -} - - - -// -// P_MakeDivline -// -void -P_MakeDivline -( line_t* li, - divline_t* dl ) -{ - dl->x = li->v1->x; - dl->y = li->v1->y; - dl->dx = li->dx; - dl->dy = li->dy; -} - - - -// -// P_InterceptVector -// Returns the fractional intercept point -// along the first divline. -// This is only called by the addthings -// and addlines traversers. -// -// [STRIFE] Verified unmodified -// -fixed_t -P_InterceptVector -( divline_t* v2, - divline_t* v1 ) -{ -#if 1 - fixed_t frac; - fixed_t num; - fixed_t den; - - den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); - - if (den == 0) - return 0; - // I_Error ("P_InterceptVector: parallel"); - - num = - FixedMul ( (v1->x - v2->x)>>8 ,v1->dy ) - +FixedMul ( (v2->y - v1->y)>>8, v1->dx ); - - frac = FixedDiv (num , den); - - return frac; -#else // UNUSED, float debug. - float frac; - float num; - float den; - float v1x; - float v1y; - float v1dx; - float v1dy; - float v2x; - float v2y; - float v2dx; - float v2dy; - - v1x = (float)v1->x/FRACUNIT; - v1y = (float)v1->y/FRACUNIT; - v1dx = (float)v1->dx/FRACUNIT; - v1dy = (float)v1->dy/FRACUNIT; - v2x = (float)v2->x/FRACUNIT; - v2y = (float)v2->y/FRACUNIT; - v2dx = (float)v2->dx/FRACUNIT; - v2dy = (float)v2->dy/FRACUNIT; - - den = v1dy*v2dx - v1dx*v2dy; - - if (den == 0) - return 0; // parallel - - num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; - frac = num / den; - - return frac*FRACUNIT; -#endif -} - - -// -// P_LineOpening -// Sets opentop and openbottom to the window -// through a two sided line. -// OPTIMIZE: keep this precalculated -// -// [STRIFE] Verified unmodified -// -fixed_t opentop; -fixed_t openbottom; -fixed_t openrange; -fixed_t lowfloor; - - -void P_LineOpening (line_t* linedef) -{ - sector_t* front; - sector_t* back; - - if (linedef->sidenum[1] == -1) - { - // single sided line - openrange = 0; - return; - } - - front = linedef->frontsector; - back = linedef->backsector; - - if (front->ceilingheight < back->ceilingheight) - opentop = front->ceilingheight; - else - opentop = back->ceilingheight; - - if (front->floorheight > back->floorheight) - { - openbottom = front->floorheight; - lowfloor = back->floorheight; - } - else - { - openbottom = back->floorheight; - lowfloor = front->floorheight; - } - - openrange = opentop - openbottom; -} - - -// -// THING POSITION SETTING -// - - -// -// P_UnsetThingPosition -// Unlinks a thing from block map and sectors. -// On each position change, BLOCKMAP and other -// lookups maintaining lists ot things inside -// these structures need to be updated. -// -// [STRIFE] Verified unmodified -// -void P_UnsetThingPosition (mobj_t* thing) -{ - int blockx; - int blocky; - - if ( ! (thing->flags & MF_NOSECTOR) ) - { - // inert things don't need to be in blockmap? - // unlink from subsector - if (thing->snext) - thing->snext->sprev = thing->sprev; - - if (thing->sprev) - thing->sprev->snext = thing->snext; - else - thing->subsector->sector->thinglist = thing->snext; - } - - if ( ! (thing->flags & MF_NOBLOCKMAP) ) - { - // inert things don't need to be in blockmap - // unlink from block map - if (thing->bnext) - thing->bnext->bprev = thing->bprev; - - if (thing->bprev) - thing->bprev->bnext = thing->bnext; - else - { - blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; - - if (blockx>=0 && blockx < bmapwidth - && blocky>=0 && blocky bnext; - } - } - } -} - - -// -// P_SetThingPosition -// Links a thing into both a block and a subsector -// based on it's x y. -// Sets thing->subsector properly -// -// [STRIFE] Verified unmodified -// -void -P_SetThingPosition (mobj_t* thing) -{ - subsector_t* ss; - sector_t* sec; - int blockx; - int blocky; - mobj_t** link; - - - // link into subsector - ss = R_PointInSubsector (thing->x,thing->y); - thing->subsector = ss; - - if ( ! (thing->flags & MF_NOSECTOR) ) - { - // invisible things don't go into the sector links - sec = ss->sector; - - thing->sprev = NULL; - thing->snext = sec->thinglist; - - if (sec->thinglist) - sec->thinglist->sprev = thing; - - sec->thinglist = thing; - } - - - // link into blockmap - if ( ! (thing->flags & MF_NOBLOCKMAP) ) - { - // inert things don't need to be in blockmap - blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; - blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; - - if (blockx>=0 - && blockx < bmapwidth - && blocky>=0 - && blocky < bmapheight) - { - link = &blocklinks[blocky*bmapwidth+blockx]; - thing->bprev = NULL; - thing->bnext = *link; - if (*link) - (*link)->bprev = thing; - - *link = thing; - } - else - { - // thing is off the map - thing->bnext = thing->bprev = NULL; - } - } -} - - - -// -// BLOCK MAP ITERATORS -// For each line/thing in the given mapblock, -// call the passed PIT_* function. -// If the function returns false, -// exit with false without checking anything else. -// - - -// -// P_BlockLinesIterator -// The validcount flags are used to avoid checking lines -// that are marked in multiple mapblocks, -// so increment validcount before the first call -// to P_BlockLinesIterator, then make one or more calls -// to it. -// -// haleyjd 20110203: -// [STRIFE] Modified to track blockingline -// -boolean -P_BlockLinesIterator -( int x, - int y, - boolean(*func)(line_t*) ) -{ - int offset; - short* list; - line_t* ld; - - if (x<0 - || y<0 - || x>=bmapwidth - || y>=bmapheight) - { - return true; - } - - offset = y*bmapwidth+x; - - offset = *(blockmap+offset); - - for ( list = blockmaplump+offset ; *list != -1 ; list++) - { - ld = &lines[*list]; - - // [STRIFE]: set blockingline (see P_XYMovement @ p_mobj.c) - blockingline = ld; - - if (ld->validcount == validcount) - continue; // line has already been checked - - ld->validcount = validcount; - - if ( !func(ld) ) - return false; - } - return true; // everything was checked -} - - -// -// P_BlockThingsIterator -// -// [STRIFE] Verified unmodified -// -boolean -P_BlockThingsIterator -( int x, - int y, - boolean(*func)(mobj_t*) ) -{ - mobj_t* mobj; - - if ( x<0 - || y<0 - || x>=bmapwidth - || y>=bmapheight) - { - return true; - } - - LINKED_LIST_CHECK_NO_CYCLE(mobj_t, blocklinks[y*bmapwidth+x], bnext); - - for (mobj = blocklinks[y*bmapwidth+x] ; - mobj ; - mobj = mobj->bnext) - { - if (!func( mobj ) ) - return false; - } - return true; -} - - - -// -// INTERCEPT ROUTINES -// -intercept_t intercepts[MAXINTERCEPTS]; -intercept_t* intercept_p; - -divline_t trace; -boolean earlyout; -int ptflags; - -//static void InterceptsOverrun(int num_intercepts, intercept_t *intercept); - -// -// PIT_AddLineIntercepts. -// Looks for lines in the given block -// that intercept the given trace -// to add to the intercepts list. -// -// A line is crossed if its endpoints -// are on opposite sides of the trace. -// Returns true if earlyout and a solid line hit. -// -// haleyjd 20110204 [STRIFE]: Added Rogue's fix for intercepts overflows -// -boolean -PIT_AddLineIntercepts (line_t* ld) -{ - int s1; - int s2; - fixed_t frac; - divline_t dl; - - // avoid precision problems with two routines - if ( trace.dx > FRACUNIT*16 - || trace.dy > FRACUNIT*16 - || trace.dx < -FRACUNIT*16 - || trace.dy < -FRACUNIT*16) - { - s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); - } - else - { - s1 = P_PointOnLineSide (trace.x, trace.y, ld); - s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); - } - - if (s1 == s2) - return true; // line isn't crossed - - // hit the line - P_MakeDivline (ld, &dl); - frac = P_InterceptVector (&trace, &dl); - - if (frac < 0) - return true; // behind source - - // try to early out the check - if (earlyout - && frac < FRACUNIT - && !ld->backsector) - { - return false; // stop checking - } - - - intercept_p->frac = frac; - intercept_p->isaline = true; - intercept_p->d.line = ld; - intercept_p++; - - // haleyjd 20110204 [STRIFE] - // Evidently Rogue had trouble with intercepts overflows during - // development, as they added this check here which will stop adding - // intercepts if the array would be overflown. - if(intercept_p <= &intercepts[MAXINTERCEPTS_ORIGINAL-2]) - return true; // continue - else - return false; - - // [STRIFE] Not needed? - //InterceptsOverrun(intercept_p - intercepts, intercept_p); -} - - - -// -// PIT_AddThingIntercepts -// -boolean PIT_AddThingIntercepts (mobj_t* thing) -{ - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - int s1; - int s2; - - boolean tracepositive; - - divline_t dl; - - fixed_t frac; - - tracepositive = (trace.dx ^ trace.dy)>0; - - // check a corner to corner crossection for hit - if (tracepositive) - { - x1 = thing->x - thing->radius; - y1 = thing->y + thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y - thing->radius; - } - else - { - x1 = thing->x - thing->radius; - y1 = thing->y - thing->radius; - - x2 = thing->x + thing->radius; - y2 = thing->y + thing->radius; - } - - s1 = P_PointOnDivlineSide (x1, y1, &trace); - s2 = P_PointOnDivlineSide (x2, y2, &trace); - - if (s1 == s2) - return true; // line isn't crossed - - dl.x = x1; - dl.y = y1; - dl.dx = x2-x1; - dl.dy = y2-y1; - - frac = P_InterceptVector (&trace, &dl); - - if (frac < 0) - return true; // behind source - - intercept_p->frac = frac; - intercept_p->isaline = false; - intercept_p->d.thing = thing; - - intercept_p++; - - // haleyjd 20110204 [STRIFE]: As above, protection against intercepts - // overflows, courtesy of Rogue Software. - if(intercept_p <= &intercepts[MAXINTERCEPTS_ORIGINAL-2]) - return true; // keep going - else - return false; - - // haleyjd [STRIFE]: Not needed? - //InterceptsOverrun(intercept_p - intercepts, intercept_p); -} - - -// -// P_TraverseIntercepts -// Returns true if the traverser function returns true -// for all lines. -// -// [STRIFE] Verified unmodified. -// -boolean -P_TraverseIntercepts -( traverser_t func, - fixed_t maxfrac ) -{ - int count; - fixed_t dist; - intercept_t* scan; - intercept_t* in; - - count = intercept_p - intercepts; - - in = 0; // shut up compiler warning - - while (count--) - { - dist = INT_MAX; - for (scan = intercepts ; scanfrac < dist) - { - dist = scan->frac; - in = scan; - } - } - - if (dist > maxfrac) - return true; // checked everything in range - -#if 0 // UNUSED - { - // don't check these yet, there may be others inserted - in = scan = intercepts; - for ( scan = intercepts ; scanfrac > maxfrac) - *in++ = *scan; - intercept_p = in; - return false; - } -#endif - - if ( !func (in) ) - return false; // don't bother going farther - - in->frac = INT_MAX; - } - - return true; // everything was traversed -} - - -#if 0 -// Intercepts Overrun emulation, from PrBoom-plus. -// Thanks to Andrey Budko (entryway) for researching this and his -// implementation of Intercepts Overrun emulation in PrBoom-plus -// which this is based on. - -typedef struct -{ - int len; - void *addr; - boolean int16_array; -} intercepts_overrun_t; - -// Intercepts memory table. This is where various variables are located -// in memory in Vanilla Doom. When the intercepts table overflows, we -// need to write to them. -// -// Almost all of the values to overwrite are 32-bit integers, except for -// playerstarts, which is effectively an array of 16-bit integers and -// must be treated differently. - -// haleyjd 20110204: NB: This array has *not* been updated for Strife, -// because Strife has protection against intercepts overflows. The memory -// layout of the 1.2 and 1.31 EXEs is radically different with respect -// to this area of the BSS segment, so it would have to be redone entirely -// if it were needed. - -static intercepts_overrun_t intercepts_overrun[] = -{ - {4, NULL, false}, - {4, NULL, /* &earlyout, */ false}, - {4, NULL, /* &intercept_p, */ false}, - {4, &lowfloor, false}, - {4, &openbottom, false}, - {4, &opentop, false}, - {4, &openrange, false}, - {4, NULL, false}, - {120, NULL, /* &activeplats, */ false}, - {8, NULL, false}, - {4, &bulletslope, false}, - {4, NULL, /* &swingx, */ false}, - {4, NULL, /* &swingy, */ false}, - {4, NULL, false}, - {40, &playerstarts, true}, - {4, NULL, /* &blocklinks, */ false}, - {4, &bmapwidth, false}, - {4, NULL, /* &blockmap, */ false}, - {4, &bmaporgx, false}, - {4, &bmaporgy, false}, - {4, NULL, /* &blockmaplump, */ false}, - {4, &bmapheight, false}, - {0, NULL, false}, -}; - -// Overwrite a specific memory location with a value. - -static void InterceptsMemoryOverrun(int location, int value) -{ - int i, offset; - int index; - void *addr; - - i = 0; - offset = 0; - - // Search down the array until we find the right entry - - while (intercepts_overrun[i].len != 0) - { - if (offset + intercepts_overrun[i].len > location) - { - addr = intercepts_overrun[i].addr; - - // Write the value to the memory location. - // 16-bit and 32-bit values are written differently. - - if (addr != NULL) - { - if (intercepts_overrun[i].int16_array) - { - index = (location - offset) / 2; - ((short *) addr)[index] = value & 0xffff; - ((short *) addr)[index + 1] = (value >> 16) & 0xffff; - } - else - { - index = (location - offset) / 4; - ((int *) addr)[index] = value; - } - } - - break; - } - - offset += intercepts_overrun[i].len; - ++i; - } -} - -// Emulate overruns of the intercepts[] array. - -static void InterceptsOverrun(int num_intercepts, intercept_t *intercept) -{ - int location; - - if (num_intercepts <= MAXINTERCEPTS_ORIGINAL) - { - // No overrun - - return; - } - - location = (num_intercepts - MAXINTERCEPTS_ORIGINAL - 1) * 12; - - // Overwrite memory that is overwritten in Vanilla Doom, using - // the values from the intercept structure. - // - // Note: the ->d.{thing,line} member should really have its - // address translated into the correct address value for - // Vanilla Doom. - - InterceptsMemoryOverrun(location, intercept->frac); - InterceptsMemoryOverrun(location + 4, intercept->isaline); - InterceptsMemoryOverrun(location + 8, (int) intercept->d.thing); -} -#endif - - -// -// P_PathTraverse -// Traces a line from x1,y1 to x2,y2, -// calling the traverser function for each. -// Returns true if the traverser function returns true -// for all lines. -// -// [STRIFE] Verified unmodified -// -boolean -P_PathTraverse -( fixed_t x1, - fixed_t y1, - fixed_t x2, - fixed_t y2, - int flags, - boolean (*trav) (intercept_t *)) -{ - fixed_t xt1; - fixed_t yt1; - fixed_t xt2; - fixed_t yt2; - - fixed_t xstep; - fixed_t ystep; - - fixed_t partial; - - fixed_t xintercept; - fixed_t yintercept; - - int mapx; - int mapy; - - int mapxstep; - int mapystep; - - int count; - - earlyout = (flags & PT_EARLYOUT) != 0; - - validcount++; - intercept_p = intercepts; - - if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) - x1 += FRACUNIT; // don't side exactly on a line - - if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) - y1 += FRACUNIT; // don't side exactly on a line - - trace.x = x1; - trace.y = y1; - trace.dx = x2 - x1; - trace.dy = y2 - y1; - - x1 -= bmaporgx; - y1 -= bmaporgy; - xt1 = x1>>MAPBLOCKSHIFT; - yt1 = y1>>MAPBLOCKSHIFT; - - x2 -= bmaporgx; - y2 -= bmaporgy; - xt2 = x2>>MAPBLOCKSHIFT; - yt2 = y2>>MAPBLOCKSHIFT; - - if (xt2 > xt1) - { - mapxstep = 1; - partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); - ystep = FixedDiv (y2-y1,abs(x2-x1)); - } - else if (xt2 < xt1) - { - mapxstep = -1; - partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); - ystep = FixedDiv (y2-y1,abs(x2-x1)); - } - else - { - mapxstep = 0; - partial = FRACUNIT; - ystep = 256*FRACUNIT; - } - - yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); - - - if (yt2 > yt1) - { - mapystep = 1; - partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); - xstep = FixedDiv (x2-x1,abs(y2-y1)); - } - else if (yt2 < yt1) - { - mapystep = -1; - partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); - xstep = FixedDiv (x2-x1,abs(y2-y1)); - } - else - { - mapystep = 0; - partial = FRACUNIT; - xstep = 256*FRACUNIT; - } - xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); - - // Step through map blocks. - // Count is present to prevent a round off error - // from skipping the break. - mapx = xt1; - mapy = yt1; - - for (count = 0 ; count < 64 ; count++) - { - if (flags & PT_ADDLINES) - { - if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) - return false; // early out - } - - if (flags & PT_ADDTHINGS) - { - if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) - return false; // early out - } - - if (mapx == xt2 - && mapy == yt2) - { - break; - } - - if ( (yintercept >> FRACBITS) == mapy) - { - yintercept += ystep; - mapx += mapxstep; - } - else if ( (xintercept >> FRACBITS) == mapx) - { - xintercept += xstep; - mapy += mapystep; - } - - } - // go through the sorted list - return P_TraverseIntercepts ( trav, FRACUNIT ); -} - - - diff --git a/games/NXDoom/src/strife/p_mobj.c b/games/NXDoom/src/strife/p_mobj.c deleted file mode 100644 index 038c3edbe80..00000000000 --- a/games/NXDoom/src/strife/p_mobj.c +++ /dev/null @@ -1,1360 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Moving object handling. Spawn functions. -// - -#include - -#include "i_system.h" -#include "z_zone.h" -#include "m_random.h" -#include "doomdef.h" -#include "p_local.h" -#include "sounds.h" -#include "st_stuff.h" -#include "hu_stuff.h" -#include "s_sound.h" -#include "doomstat.h" -#include "d_main.h" // villsa [STRIFE] - - -void G_PlayerReborn (int player); -void P_SpawnMapThing (mapthing_t* mthing); - - -// -// P_SetMobjState -// Returns true if the mobj is still present. -// -// [STRIFE] Verified unmodified -// -int test; - -boolean -P_SetMobjState -( mobj_t* mobj, - statenum_t state ) -{ - state_t* st; - - do - { - if (state == S_NULL) - { - mobj->state = (state_t *) S_NULL; - P_RemoveMobj (mobj); - return false; - } - - st = &states[state]; - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - - // Modified handling. - // Call action functions when the state is set - if (st->action.acp1) - st->action.acp1(mobj); - - state = st->nextstate; - } while (!mobj->tics); - - return true; -} - - -// -// P_ExplodeMissile -// -// [STRIFE] Removed randomization of deathstate tics -// -void P_ExplodeMissile (mobj_t* mo) -{ - mo->momx = mo->momy = mo->momz = 0; - - P_SetMobjState (mo, mobjinfo[mo->type].deathstate); - - // villsa [STRIFE] removed tics randomization - - mo->flags &= ~MF_MISSILE; - - if (mo->info->deathsound) - S_StartSound (mo, mo->info->deathsound); -} - - -// -// P_XYMovement -// -// [STRIFE] Modifications for: -// * No SKULLFLY logic (replaced by BOUNCE flag) -// * Missiles can activate G1/GR line types -// * Player walking logic -// * Air friction for players -// -#define STOPSPEED 0x1000 -#define FRICTION 0xe800 -#define AIRFRICTION 0xfff0 // [STRIFE] - -void P_XYMovement (mobj_t* mo) -{ - fixed_t ptryx; - fixed_t ptryy; - player_t* player; - fixed_t xmove; - fixed_t ymove; - - // villsa [STRIFE] unused - /* - if (!mo->momx && !mo->momy) - { - if (mo->flags & MF_SKULLFLY) - { - // the skull slammed into something - mo->flags &= ~MF_SKULLFLY; - mo->momx = mo->momy = mo->momz = 0; - - P_SetMobjState (mo, mo->info->spawnstate); - } - return; - } - */ - - player = mo->player; - - if (mo->momx > MAXMOVE) - mo->momx = MAXMOVE; - else if (mo->momx < -MAXMOVE) - mo->momx = -MAXMOVE; - - if (mo->momy > MAXMOVE) - mo->momy = MAXMOVE; - else if (mo->momy < -MAXMOVE) - mo->momy = -MAXMOVE; - - xmove = mo->momx; - ymove = mo->momy; - - do - { - if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2) - { - ptryx = mo->x + xmove/2; - ptryy = mo->y + ymove/2; - xmove >>= 1; - ymove >>= 1; - } - else - { - ptryx = mo->x + xmove; - ptryy = mo->y + ymove; - xmove = ymove = 0; - } - - if (!P_TryMove (mo, ptryx, ptryy)) - { - // blocked move - if (mo->player) - { // try to slide along it - P_SlideMove (mo); - } - // villsa [STRIFE] check for bouncy missiles - else if(mo->flags & MF_BOUNCE) - { - mo->momx >>= 3; - mo->momy >>= 3; - - if (P_TryMove(mo, mo->x - xmove, ymove + mo->y)) - mo->momy = -mo->momy; - else - mo->momx = -mo->momx; - - xmove = 0; - ymove = 0; - } - else if (mo->flags & MF_MISSILE) - { - // haley 20110203: [STRIFE] - // This modification allows missiles to activate shoot specials. - // *** BUG: In vanilla Strife the second condition is simply - // if(numspechit). However, numspechit can be negative, and - // when it is, this accesses spechit[-2]. This always causes the - // DOS exe to read from NULL, and the 'special' value there (in - // DOS 6.22 at least) is 0x70, which does nothing. - if(blockingline && blockingline->special) - P_ShootSpecialLine(mo, blockingline); - if(numspechit > 0) - P_ShootSpecialLine(mo, spechit[numspechit-1]); - - // explode a missile - if (ceilingline && - ceilingline->backsector && - ceilingline->backsector->ceilingpic == skyflatnum) - { - // Hack to prevent missiles exploding - // against the sky. - // Does not handle sky floors. - P_RemoveMobj (mo); - return; - } - P_ExplodeMissile (mo); - } - else - mo->momx = mo->momy = 0; - } - } while (xmove || ymove); - - // slow down - if (player && player->cheats & CF_NOMOMENTUM) - { - // debug option for no sliding at all - mo->momx = mo->momy = 0; - return; - } - - // villsa [STRIFE] replace skullfly flag with MF_BOUNCE - if (mo->flags & (MF_MISSILE | MF_BOUNCE) ) - return; // no friction for missiles ever - - // haleyjd 20110224: [STRIFE] players experience friction even in the air, - // although less than when on the ground. With this fix, the 1.2-and-up - // IWAD demo is now in sync! - if (mo->z > mo->floorz) - { - if(player) - { - mo->momx = FixedMul (mo->momx, AIRFRICTION); - mo->momy = FixedMul (mo->momy, AIRFRICTION); - } - return; // no friction when airborne - } - - if (mo->flags & MF_CORPSE) - { - // do not stop sliding - // if halfway off a step with some momentum - if (mo->momx > FRACUNIT/4 - || mo->momx < -FRACUNIT/4 - || mo->momy > FRACUNIT/4 - || mo->momy < -FRACUNIT/4) - { - if (mo->floorz != mo->subsector->sector->floorheight) - return; - } - } - - if (mo->momx > -STOPSPEED - && mo->momx < STOPSPEED - && mo->momy > -STOPSPEED - && mo->momy < STOPSPEED - && (!player - || (player->cmd.forwardmove == 0 - && player->cmd.sidemove == 0 ) ) ) - { - // if in a walking frame, stop moving - // villsa [STRIFE]: different player state (haleyjd - verified 20110202) - if ( player&&(unsigned)((player->mo->state - states) - S_PLAY_01) < 4) - P_SetMobjState (player->mo, S_PLAY_00); - - mo->momx = 0; - mo->momy = 0; - } - else - { - mo->momx = FixedMul (mo->momx, FRICTION); - mo->momy = FixedMul (mo->momy, FRICTION); - } -} - -// -// P_ZMovement -// -// [STRIFE] Modifications for: -// * 3D Object Clipping -// * Different momz handling -// * No SKULLFLY logic (replaced with BOUNCE) -// * Missiles don't hit sky flats -// -void P_ZMovement (mobj_t* mo) -{ - fixed_t dist; - fixed_t delta; - - // check for smooth step up - if (mo->player && mo->z < mo->floorz) - { - mo->player->viewheight -= mo->floorz-mo->z; - - mo->player->deltaviewheight - = (VIEWHEIGHT - mo->player->viewheight)>>3; - } - - // adjust height - // villsa [STRIFE] check for things standing on top of other things - if(!P_CheckPositionZ(mo, mo->z + mo->momz)) - { - if(mo->momz >= 0) - mo->ceilingz = mo->height + mo->z; - else - mo->floorz = mo->z; - } - - //mo->z += mo->momz; // villsa [STRIFE] unused - - if ( mo->flags & MF_FLOAT - && mo->target) - { - // float down towards target if too close - if ( /*!(mo->flags & MF_SKULLFLY) // villsa [STRIFE] unused - &&*/ !(mo->flags & MF_INFLOAT) ) - { - dist = P_AproxDistance (mo->x - mo->target->x, - mo->y - mo->target->y); - - delta =(mo->target->z + (mo->height>>1)) - mo->z; - - if (delta<0 && dist < -(delta*3) ) - mo->z -= FLOATSPEED; - else if (delta>0 && dist < (delta*3) ) - mo->z += FLOATSPEED; - } - } - - // clip movement - if (mo->z <= mo->floorz) - { - // hit the floor - - if (mo->flags & MF_BOUNCE) - { - // the skull slammed into something - // villsa [STRIFE] affect reactiontime - // momz is also shifted by 1 - mo->momz = -mo->momz >> 1; - mo->reactiontime >>= 1; - - // villsa [STRIFE] get terrain type - if(P_GetTerrainType(mo) != FLOOR_SOLID) - mo->flags &= ~MF_BOUNCE; - } - - if (mo->momz < 0) - { - if (mo->player - && mo->momz < -GRAVITY*8) - { - // Squat down. - // Decrease viewheight for a moment - // after hitting the ground (hard), - // and utter appropriate sound. - mo->player->deltaviewheight = mo->momz>>3; - - // villsa [STRIFE] fall damage - // haleyjd 09/18/10: Repaired calculation - if(mo->momz < -20*FRACUNIT) - P_DamageMobj(mo, NULL, mo, mo->momz / -25000); - - // haleyjd 20110224: *Any* fall centers your view, not just - // damaging falls (moved outside the above if). - mo->player->centerview = 1; - S_StartSound (mo, sfx_oof); - } - mo->momz = 0; - } - mo->z = mo->floorz; - - - // cph 2001/05/26 - - // See lost soul bouncing comment above. We need this here for bug - // compatibility with original Doom2 v1.9 - if a soul is charging and - // hit by a raising floor this incorrectly reverses its Y momentum. - // - - // villsa [STRIFE] unused - /* - if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) - mo->momz = -mo->momz; - */ - - // villsa [STRIFE] also check for MF_BOUNCE - if ( (mo->flags & MF_MISSILE) - && !(mo->flags & (MF_NOCLIP|MF_BOUNCE)) ) - { - P_ExplodeMissile (mo); - } - } - else // haleyjd 20110224: else here, not else if - Strife change or what? - { - if (! (mo->flags & MF_NOGRAVITY) ) - { - if (mo->momz == 0) - mo->momz = -GRAVITY*2; - else - mo->momz -= GRAVITY; - } - - if (mo->z + mo->height > mo->ceilingz) - { - // villsa [STRIFE] replace skullfly flag with MF_BOUNCE - if (mo->flags & MF_BOUNCE) - { - // villsa [STRIFE] affect reactiontime - // momz is also shifted by 1 - mo->momz = -mo->momz >> 1; - mo->reactiontime >>= 1; - } - - // hit the ceiling - if (mo->momz > 0) - mo->momz = 0; - - mo->z = mo->ceilingz - mo->height; - - // villsa [STRIFE] also check for MF_BOUNCE - if ( (mo->flags & MF_MISSILE) - && !(mo->flags & (MF_NOCLIP|MF_BOUNCE)) ) - { - // villsa [STRIFE] check against skies - if(mo->subsector->sector->ceilingpic == skyflatnum) - P_RemoveMobj(mo); - else - P_ExplodeMissile (mo); - } - } - } -} - - - -// -// P_NightmareRespawn -// -// [STRIFE] Modifications for: -// * Destination fog z coordinate -// * Restoration of all Strife mapthing flags -// -void -P_NightmareRespawn (mobj_t* mobj) -{ - fixed_t x; - fixed_t y; - fixed_t z; - mobj_t* mo; - mapthing_t* mthing; - - x = mobj->spawnpoint.x << FRACBITS; - y = mobj->spawnpoint.y << FRACBITS; - - // somthing is occupying it's position? - if (!P_CheckPosition (mobj, x, y) ) - return; // no respwan - - // spawn a teleport fog at old spot - // because of removal of the body? - mo = P_SpawnMobj (mobj->x, - mobj->y, - mobj->subsector->sector->floorheight , MT_TFOG); - // initiate teleport sound - S_StartSound (mo, sfx_telept); - - // spawn a teleport fog at the new spot - //ss = R_PointInSubsector (x,y); - - // haleyjd [STRIFE]: Uses ONFLOORZ instead of ss->sector->floorheight - mo = P_SpawnMobj (x, y, ONFLOORZ , MT_TFOG); - - S_StartSound (mo, sfx_telept); - - // spawn the new monster - mthing = &mobj->spawnpoint; - - // spawn it - if (mobj->info->flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; - - // inherit attributes from deceased one - mo = P_SpawnMobj (x,y,z, mobj->type); - mo->spawnpoint = mobj->spawnpoint; - mo->angle = ANG45 * (mthing->angle/45); - - if (mthing->options & MTF_AMBUSH) - mo->flags |= MF_AMBUSH; - if (mthing->options & MTF_STAND) // [STRIFE] Standing mode, for NPCs - mobj->flags |= MF_STAND; - if (mthing->options & MTF_FRIEND) // [STRIFE] Allies - mobj->flags |= MF_ALLY; - if (mthing->options & MTF_TRANSLUCENT) // [STRIFE] Translucent object - mobj->flags |= MF_SHADOW; - if (mthing->options & MTF_MVIS) // [STRIFE] Alt. Translucency - mobj->flags |= MF_MVIS; - - mo->reactiontime = 18; - - // remove the old monster, - P_RemoveMobj (mobj); -} - - -// -// P_MobjThinker -// -// [STRIFE] Modified for: -// * Terrain effects -// * Stonecold cheat -// * Altered skill 5 respawn behavior -// -void P_MobjThinker (mobj_t* mobj) -{ - // momentum movement - if (mobj->momx - || mobj->momy - /*|| (mobj->flags&MF_SKULLFLY)*/ ) // villsa [STRIFE] unused - { - P_XYMovement (mobj); - - // FIXME: decent NOP/NULL/Nil function pointer please. - if (mobj->thinker.function.acv == (actionf_v) (-1)) - return; // mobj was removed - - // villsa [STRIFE] terrain clipping - if(P_GetTerrainType(mobj) == FLOOR_SOLID) - mobj->flags &= ~MF_FEETCLIPPED; - else - mobj->flags |= MF_FEETCLIPPED; - - } - if ( (mobj->z != mobj->floorz && !(mobj->flags & MF_NOGRAVITY)) // villsa [STRIFE] - || mobj->momz ) - { - P_ZMovement (mobj); - - // FIXME: decent NOP/NULL/Nil function pointer please. - if (mobj->thinker.function.acv == (actionf_v) (-1)) - return; // mobj was removed - - // villsa [STRIFE] terrain clipping and sounds - if(P_GetTerrainType(mobj) == FLOOR_SOLID) - mobj->flags &= ~MF_FEETCLIPPED; - else - { - S_StartSound(mobj, sfx_wsplsh); - mobj->flags |= MF_FEETCLIPPED; - } - - } - - - // cycle through states, - // calling action functions at transitions - if (mobj->tics != -1) - { - mobj->tics--; - - // villsa [STRIFE] stonecold cheat - if(stonecold) - { - if(mobj->flags & MF_COUNTKILL) - P_DamageMobj(mobj, mobj, mobj, 10); - } - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState (mobj, mobj->state->nextstate) ) - return; // freed itself - } - else - { - // check for nightmare respawn - if (! (mobj->flags & MF_COUNTKILL) ) - return; - - if (!respawnmonsters) - return; - - mobj->movecount++; - - // haleyjd [STRIFE]: respawn time increased from 12 to 16 - if (mobj->movecount < 16*TICRATE) - return; - - if ( leveltime&31 ) - return; - - if (P_Random () > 4) - return; - - // haleyjd [STRIFE]: NOTDMATCH things don't respawn - if(mobj->flags & MF_NOTDMATCH) - return; - - P_NightmareRespawn (mobj); - } -} - - -// -// P_SpawnMobj -// -// [STRIFE] Modifications to reactiontime and for terrain types. -// -mobj_t* -P_SpawnMobj -( fixed_t x, - fixed_t y, - fixed_t z, - mobjtype_t type ) -{ - mobj_t* mobj; - state_t* st; - mobjinfo_t* info; - - mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); - memset (mobj, 0, sizeof (*mobj)); - info = &mobjinfo[type]; - - mobj->type = type; - mobj->info = info; - mobj->x = x; - mobj->y = y; - mobj->radius = info->radius; - mobj->height = info->height; - mobj->flags = info->flags; - mobj->health = info->spawnhealth; - - // haleyjd 09/25/10: [STRIFE] Doesn't do this; messes up flamethrower - // and a lot of other stuff using reactiontime as a counter. - //if (gameskill != sk_nightmare) - mobj->reactiontime = info->reactiontime; - - mobj->lastlook = P_Random () % MAXPLAYERS; - // do not set the state with P_SetMobjState, - // because action routines can not be called yet - st = &states[info->spawnstate]; - - mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; - - // set subsector and/or block links - P_SetThingPosition (mobj); - - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - - if (z == ONFLOORZ) - { - mobj->z = mobj->floorz; - - // villsa [STRIFE] - if(P_GetTerrainType(mobj) != FLOOR_SOLID) - mobj->flags |= MF_FEETCLIPPED; - - } - else if (z == ONCEILINGZ) - mobj->z = mobj->ceilingz - mobj->info->height; - else - mobj->z = z; - - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; - - P_AddThinker (&mobj->thinker); - - return mobj; -} - - -// -// P_RemoveMobj -// -// [STRIFE] Modifications for item respawn timing -// -mapthing_t itemrespawnque[ITEMQUESIZE]; -int itemrespawntime[ITEMQUESIZE]; -int iquehead; -int iquetail; - -void P_RemoveMobj (mobj_t* mobj) -{ - // villsa [STRIFE] removed invuln/invis. sphere exceptions - if ((mobj->flags & MF_SPECIAL) - && !(mobj->flags & MF_DROPPED)) - { - itemrespawnque[iquehead] = mobj->spawnpoint; - itemrespawntime[iquehead] = leveltime + 30*TICRATE; // [STRIFE] - - // [STRIFE] haleyjd 20130915 - // -random parameter affects the behavior of respawning items here. - if(randomparm && iquehead != iquetail) - { - short type = itemrespawnque[iquehead].type; - short options = itemrespawnque[iquehead].options; - - // swap the type and options of iquehead and iquetail - itemrespawnque[iquehead].type = itemrespawnque[iquetail].type; - itemrespawnque[iquehead].options = itemrespawnque[iquetail].options; - itemrespawnque[iquetail].type = type; - itemrespawnque[iquetail].options = options; - } - - iquehead = (iquehead+1)&(ITEMQUESIZE-1); - - // lose one off the end? - if (iquehead == iquetail) - iquetail = (iquetail+1)&(ITEMQUESIZE-1); - } - - // unlink from sector and block lists - P_UnsetThingPosition (mobj); - - // stop any playing sound - S_StopSound (mobj); - - // free block - P_RemoveThinker ((thinker_t*)mobj); -} - - - - -// -// P_RespawnSpecials -// -// [STRIFE] modification to item respawn time handling -// -void P_RespawnSpecials (void) -{ - fixed_t x; - fixed_t y; - fixed_t z; - - subsector_t* ss; - mobj_t* mo; - mapthing_t* mthing; - - int i; - - // only respawn items in deathmatch - if (deathmatch != 2) - return; - - // nothing left to respawn? - if (iquehead == iquetail) - return; - - // haleyjd [STRIFE]: 30 second wait is not accounted for here, see above. - if (leveltime < itemrespawntime[iquetail]) - return; - - mthing = &itemrespawnque[iquetail]; - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - // spawn a teleport fog at the new spot - ss = R_PointInSubsector (x,y); - mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); - S_StartSound (mo, sfx_itmbk); - - // find which type to spawn - for (i=0 ; i< NUMMOBJTYPES ; i++) - { - if (mthing->type == mobjinfo[i].doomednum) - break; - } - - if (i >= NUMMOBJTYPES) - { - I_Error("P_RespawnSpecials: Failed to find mobj type with doomednum " - "%d when respawning thing. This would cause a buffer overrun " - "in vanilla Strife.", mthing->type); - } - - // spawn it - if (mobjinfo[i].flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; - - mo = P_SpawnMobj (x,y,z, i); - mo->spawnpoint = *mthing; - mo->angle = ANG45 * (mthing->angle/45); - - // pull it from the que - iquetail = (iquetail+1)&(ITEMQUESIZE-1); -} - - - - -// -// P_SpawnPlayer -// Called when a player is spawned on the level. -// Most of the player structure stays unchanged -// between levels. -// -// [STRIFE] Modifications for: -// * stonecold cheat, -workparm -// * default inventory/questflags -// -void P_SpawnPlayer(mapthing_t* mthing) -{ - player_t* p; - fixed_t x; - fixed_t y; - fixed_t z; - mobj_t* mobj; - - if(mthing->type == 0) - return; - - // not playing? - if(!playeringame[mthing->type-1]) - return; - - p = &players[mthing->type-1]; - - if (p->playerstate == PST_REBORN) - G_PlayerReborn (mthing->type-1); - - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - z = ONFLOORZ; - mobj = P_SpawnMobj (x,y,z, MT_PLAYER); - - // set color translations for player sprites - if(mthing->type > 1) - mobj->flags |= (mthing->type-1)<angle = ANG45 * (mthing->angle/45); - mobj->player = p; - mobj->health = p->health; - - p->mo = mobj; - p->playerstate = PST_LIVE; - p->refire = 0; - p->message = NULL; - p->damagecount = 0; - p->bonuscount = 0; - p->extralight = 0; - p->fixedcolormap = 0; - p->viewheight = VIEWHEIGHT; - - // setup gun psprite - P_SetupPsprites(p); - - // villsa [STRIFE] - stonecold = false; - - // villsa [STRIFE] what a nasty hack... - if(gamemap == 10) - p->weaponowned[wp_sigil] = true; - - // villsa [STRIFE] instead of just giving cards in deathmatch mode, also - // set accuracy to 50 and give all quest flags - if(deathmatch) - { - int i; - - p->accuracy = 50; - p->questflags = QF_ALLQUESTS; // 0x7fffffff - - for(i = 0; i < NUMCARDS; i++) - p->cards[i] = true; - } - - // villsa [STRIFE] set godmode? - if(workparm) - p->cheats |= CF_GODMODE; - - if(mthing->type - 1 == consoleplayer) - { - // wake up the status bar - ST_Start (); - // wake up the heads up text - HU_Start (); - } -} - - -// -// P_SpawnMapThing -// The fields of the mapthing should -// already be in host byte order. -// -// [STRIFE] Modifications for: -// * No Lost Souls, item count -// * New mapthing_t flag bits -// * 8-player support -// -void P_SpawnMapThing (mapthing_t* mthing) -{ - int i; - int bit; - mobj_t* mobj; - fixed_t x; - fixed_t y; - fixed_t z; - - // count deathmatch start positions - if (mthing->type == 11) - { - if (deathmatch_p < &deathmatchstarts[10]) - { - memcpy (deathmatch_p, mthing, sizeof(*mthing)); - deathmatch_p++; - } - return; - } - - if (mthing->type <= 0) - { - // Thing type 0 is actually "player -1 start". - // For some reason, Vanilla Doom accepts/ignores this. - - return; - } - - // check for players specially - // haleyjd 20120209: [STRIFE] 8 player starts - if (mthing->type <= 8) - { - // save spots for respawning in network games - playerstarts[mthing->type-1] = *mthing; - if (!deathmatch) - P_SpawnPlayer (mthing); - - return; - } - - // check for appropriate skill level - if (!netgame && (mthing->options & 16) ) - return; - - if (gameskill == sk_baby) - bit = 1; - else if (gameskill == sk_nightmare) - bit = 4; - else - // avoid undefined behavior (left shift by negative value and rhs too big) - // by accurately emulating what doom.exe did: reduce mod 32. - // For more details check: - // https://github.com/chocolate-doom/chocolate-doom/issues/1677 - bit = (int) (1U << ((gameskill - 1) & 0x1F)); - - if (!(mthing->options & bit) ) - return; - - // find which type to spawn - for (i=0 ; i< NUMMOBJTYPES ; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i==NUMMOBJTYPES) - I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)", - mthing->type, - mthing->x, mthing->y); - - // don't spawn keycards and players in deathmatch - if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) - return; - - // don't spawn any monsters if -nomonsters - // villsa [STRIFE] Removed MT_SKULL - if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL)) - return; - - // spawn it - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - - if (mobjinfo[i].flags & MF_SPAWNCEILING) - z = ONCEILINGZ; - else - z = ONFLOORZ; - - mobj = P_SpawnMobj (x,y,z, i); - mobj->spawnpoint = *mthing; - - if (mobj->tics > 0) - mobj->tics = 1 + (P_Random () % mobj->tics); - if (mobj->flags & MF_COUNTKILL) - totalkills++; - - // villsa [STRIFE] unused - /* - if (mobj->flags & MF_COUNTITEM) - totalitems++; - */ - - mobj->angle = ANG45 * (mthing->angle/45); - if (mthing->options & MTF_AMBUSH) - mobj->flags |= MF_AMBUSH; - if (mthing->options & MTF_STAND) // [STRIFE] Standing mode, for NPCs - mobj->flags |= MF_STAND; - if (mthing->options & MTF_FRIEND) // [STRIFE] Allies - mobj->flags |= MF_ALLY; - if (mthing->options & MTF_TRANSLUCENT) // [STRIFE] Translucent object - mobj->flags |= MF_SHADOW; - if (mthing->options & MTF_MVIS) // [STRIFE] Alt. Translucency - mobj->flags |= MF_MVIS; -} - - - -// -// GAME SPAWN FUNCTIONS -// - - -// -// P_SpawnPuff -// -// [STRIFE] Modifications for: -// * No spawn tics randomization -// * Player melee behavior -// - -void -P_SpawnPuff -( fixed_t x, - fixed_t y, - fixed_t z ) -{ - mobj_t* th; - int t; - - t = P_Random(); - z += ((t - P_Random()) << 10); - - // [STRIFE] removed momz and tics randomization - - th = P_SpawnMobj(x, y, z, MT_STRIFEPUFF); // [STRIFE]: new type - - // don't make punches spark on the wall - // [STRIFE] Use a separate melee attack range for the player - if(attackrange == PLAYERMELEERANGE) - P_SetMobjState(th, S_POW2_00); // 141 - - // villsa [STRIFE] unused - /* - if (th->tics < 1) - th->tics = 1; - */ -} - -// -// P_SpawnSparkPuff -// -// villsa [STRIFE] new function -// -mobj_t* P_SpawnSparkPuff(fixed_t x, fixed_t y, fixed_t z) -{ - int t = P_Random(); - return P_SpawnMobj(x, y, ((t - P_Random()) << 10) + z, MT_SPARKPUFF); -} - -// -// P_SpawnBlood -// -// [STRIFE] Modifications for: -// * No spawn tics randomization -// * Different damage ranges for state setting -// -void -P_SpawnBlood -( fixed_t x, - fixed_t y, - fixed_t z, - int damage ) -{ - mobj_t* th; - int temp; - - temp = P_Random(); - z += (temp - P_Random()) << 10; - th = P_SpawnMobj(x, y, z, MT_BLOOD_DEATH); - th->momz = FRACUNIT*2; - - // villsa [STRIFE]: removed tics randomization - - // villsa [STRIFE] different checks for damage range - if(damage >= 10 && damage <= 13) - P_SetMobjState(th, S_BLOD_00); - else if(damage >= 7 && damage < 10) - P_SetMobjState(th, S_BLOD_01); - else if(damage < 7) - P_SetMobjState(th, S_BLOD_02); -} - - - -// -// P_CheckMissileSpawn -// Moves the missile forward a bit -// and possibly explodes it right there. -// -// [STRIFE] Modifications for: -// * No spawn tics randomization -// -void P_CheckMissileSpawn (mobj_t* th) -{ - // villsa [STRIFE] removed tics randomization - - // move a little forward so an angle can - // be computed if it immediately explodes - th->x += (th->momx>>1); - th->y += (th->momy>>1); - th->z += (th->momz>>1); - - if (!P_TryMove (th, th->x, th->y)) - P_ExplodeMissile (th); -} - -// Certain functions assume that a mobj_t pointer is non-NULL, -// causing a crash in some situations where it is NULL. Vanilla -// Doom did not crash because of the lack of proper memory -// protection. This function substitutes NULL pointers for -// pointers to a dummy mobj, to avoid a crash. - -mobj_t *P_SubstNullMobj(mobj_t *mobj) -{ - if (mobj == NULL) - { - static mobj_t dummy_mobj; - - dummy_mobj.x = 0; - dummy_mobj.y = 0; - dummy_mobj.z = 0; - dummy_mobj.flags = 0; - - mobj = &dummy_mobj; - } - - return mobj; -} - -// -// P_SpawnMissile -// -// [STRIFE] Added MVIS inaccuracy -// -mobj_t* -P_SpawnMissile -( mobj_t* source, - mobj_t* dest, - mobjtype_t type ) -{ - mobj_t* th; - angle_t an; - int dist; - - th = P_SpawnMobj (source->x, - source->y, - source->z + 4*8*FRACUNIT, type); - - if (th->info->seesound) - S_StartSound (th, th->info->seesound); - - th->target = source; // where it came from - an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); - - // fuzzy player - if (dest->flags & MF_SHADOW) - { - int t = P_Random(); // haleyjd 20110223: remove order-of-evaluation dependencies - an += (t - P_Random()) << 21; - } - // villsa [STRIFE] check for heavily transparent things - else if(dest->flags & MF_MVIS) - { - int t = P_Random(); - an += (t - P_Random()) << 22; - } - - th->angle = an; - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul (th->info->speed, finecosine[an]); - th->momy = FixedMul (th->info->speed, finesine[an]); - - dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); - dist = dist / th->info->speed; - - if (dist < 1) - dist = 1; - - th->momz = (dest->z - source->z) / dist; - P_CheckMissileSpawn (th); - - return th; -} - -// -// P_SpawnFacingMissile -// -// villsa [STRIFE] new function -// Spawn a missile based on source's angle -// -mobj_t* P_SpawnFacingMissile(mobj_t* source, mobj_t* target, mobjtype_t type) -{ - mobj_t* th; - angle_t an; - fixed_t dist; - - th = P_SpawnMobj(source->x, source->y, source->z + (32*FRACUNIT), type); - - if(th->info->seesound) - S_StartSound(th, th->info->seesound); - - th->target = source; // where it came from - th->angle = source->angle; // haleyjd 09/06/10: fix0red - an = th->angle; - - // fuzzy player - if (target->flags & MF_SHADOW) - { - int t = P_Random(); - an += (t - P_Random()) << 21; - } - // villsa [STRIFE] check for heavily transparent things - else if(target->flags & MF_MVIS) - { - int t = P_Random(); - an += (t - P_Random()) << 22; - } - - an >>= ANGLETOFINESHIFT; - th->momx = FixedMul (th->info->speed, finecosine[an]); - th->momy = FixedMul (th->info->speed, finesine[an]); - - dist = P_AproxDistance (target->x - source->x, target->y - source->y); - dist = dist / th->info->speed; - - if(dist < 1) - dist = 1; - - th->momz = (target->z - source->z) / dist; - P_CheckMissileSpawn (th); - - return th; -} - -// -// P_SpawnPlayerMissile -// -// Tries to aim at a nearby monster -// villsa [STRIFE] now returns a mobj -// * Also modified to allow up/down look, and to account for foot-clipping -// by liquid terrain. -// -mobj_t* P_SpawnPlayerMissile(mobj_t* source, mobjtype_t type) -{ - mobj_t* th; - angle_t an; - - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t slope; - - // see which target is to be aimed at - an = source->angle; - slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); - - if (!linetarget) - { - an += 1<<26; - slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); - - if (!linetarget) - { - an -= 2<<26; - slope = P_AimLineAttack (source, an, 16*64*FRACUNIT); - } - - if (!linetarget) - { - an = source->angle; - - // haleyjd 09/21/10: [STRIFE] Removed, for look up/down support. - //slope = 0; - } - } - - // villsa [STRIFE] - if(linetarget) - source->target = linetarget; - - x = source->x; - y = source->y; - - // villsa [STRIFE] - if(!(source->flags & MF_FEETCLIPPED)) - z = source->z + 32*FRACUNIT; - else - z = source->z + 22*FRACUNIT; - - th = P_SpawnMobj (x,y,z, type); - - if (th->info->seesound) - S_StartSound (th, th->info->seesound); - - th->target = source; - th->angle = an; - th->momx = FixedMul( th->info->speed, - finecosine[an>>ANGLETOFINESHIFT]); - th->momy = FixedMul( th->info->speed, - finesine[an>>ANGLETOFINESHIFT]); - th->momz = FixedMul( th->info->speed, slope); - - P_CheckMissileSpawn (th); - - return th; -} - -// -// P_SpawnMortar -// -// villsa [STRIFE] new function -// Spawn a high-arcing ballistic projectile -// -mobj_t* P_SpawnMortar(mobj_t *source, mobjtype_t type) -{ - mobj_t* th; - angle_t an; - fixed_t slope; - - an = source->angle; - - th = P_SpawnMobj(source->x, source->y, source->z, type); - th->target = source; - th->angle = an; - an >>= ANGLETOFINESHIFT; - - // haleyjd 20110203: corrected order of function calls - th->momx = FixedMul(th->info->speed, finecosine[an]); - th->momy = FixedMul(th->info->speed, finesine[an]); - - P_CheckMissileSpawn(th); - - slope = P_AimLineAttack(source, source->angle, 1024*FRACUNIT); - th->momz = FixedMul(th->info->speed, slope); - - return th; -} diff --git a/games/NXDoom/src/strife/p_mobj.h b/games/NXDoom/src/strife/p_mobj.h deleted file mode 100644 index 3872f9d03aa..00000000000 --- a/games/NXDoom/src/strife/p_mobj.h +++ /dev/null @@ -1,330 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Map Objects, MObj, definition and handling. -// - - -#ifndef __P_MOBJ__ -#define __P_MOBJ__ - -// Basics. -#include "tables.h" -#include "m_fixed.h" - -// We need the thinker_t stuff. -#include "d_think.h" - -// We need the WAD data structure for Map things, -// from the THINGS lump. -#include "doomdata.h" - -// States are tied to finite states are -// tied to animation frames. -// Needs precompiled tables/data structures. -#include "info.h" - - - - - - -// -// NOTES: mobj_t -// -// mobj_ts are used to tell the refresh where to draw an image, -// tell the world simulation when objects are contacted, -// and tell the sound driver how to position a sound. -// -// The refresh uses the next and prev links to follow -// lists of things in sectors as they are being drawn. -// The sprite, frame, and angle elements determine which patch_t -// is used to draw the sprite if it is visible. -// The sprite and frame values are allmost allways set -// from state_t structures. -// The statescr.exe utility generates the states.h and states.c -// files that contain the sprite/frame numbers from the -// statescr.txt source file. -// The xyz origin point represents a point at the bottom middle -// of the sprite (between the feet of a biped). -// This is the default origin position for patch_ts grabbed -// with lumpy.exe. -// A walking creature will have its z equal to the floor -// it is standing on. -// -// The sound code uses the x,y, and subsector fields -// to do stereo positioning of any sound effited by the mobj_t. -// -// The play simulation uses the blocklinks, x,y,z, radius, height -// to determine when mobj_ts are touching each other, -// touching lines in the map, or hit by trace lines (gunshots, -// lines of sight, etc). -// The mobj_t->flags element has various bit flags -// used by the simulation. -// -// Every mobj_t is linked into a single sector -// based on its origin coordinates. -// The subsector_t is found with R_PointInSubsector(x,y), -// and the sector_t can be found with subsector->sector. -// The sector links are only used by the rendering code, -// the play simulation does not care about them at all. -// -// Any mobj_t that needs to be acted upon by something else -// in the play world (block movement, be shot, etc) will also -// need to be linked into the blockmap. -// If the thing has the MF_NOBLOCK flag set, it will not use -// the block links. It can still interact with other things, -// but only as the instigator (missiles will run into other -// things, but nothing can run into a missile). -// Each block in the grid is 128*128 units, and knows about -// every line_t that it contains a piece of, and every -// interactable mobj_t that has its origin contained. -// -// A valid mobj_t is a mobj_t that has the proper subsector_t -// filled in for its xy coordinates and is linked into the -// sector from which the subsector was made, or has the -// MF_NOSECTOR flag set (the subsector_t needs to be valid -// even if MF_NOSECTOR is set), and is linked into a blockmap -// block or has the MF_NOBLOCKMAP flag set. -// Links should only be modified by the P_[Un]SetThingPosition() -// functions. -// Do not change the MF_NO? flags while a thing is valid. -// -// Any questions? -// - -// -// Misc. mobj flags -// -typedef enum -{ - // Call P_SpecialThing when touched. - MF_SPECIAL = 1, - - // Blocks. - MF_SOLID = 2, - - // Can be hit. - MF_SHOOTABLE = 4, - - // Don't use the sector links (invisible but touchable). - MF_NOSECTOR = 8, - - // Don't use the blocklinks (inert but displayable) - MF_NOBLOCKMAP = 16, - - // villsa [STRIFE] Stand around until alerted - MF_STAND = 32, - - // Will try to attack right back. - MF_JUSTHIT = 64, - - // Will take at least one step before attacking. - MF_JUSTATTACKED = 128, - - // On level spawning (initial position), - // hang from ceiling instead of stand on floor. - MF_SPAWNCEILING = 256, - - // Don't apply gravity (every tic), - // that is, object will float, keeping current height - // or changing it actively. - MF_NOGRAVITY = 512, - - // Movement flags. - // This allows jumps from high places. - MF_DROPOFF = 0x400, - - // villsa [STRIFE] For players, count as quest item - MF_GIVEQUEST = 0x800, - - // Player cheat. ??? - MF_NOCLIP = 0x1000, - - // villsa [STRIFE] are feet clipped into water/slude floor? - MF_FEETCLIPPED = 0x2000, - - // Allow moves to any height, no gravity. - // For active floaters, e.g. cacodemons, pain elementals. - MF_FLOAT = 0x4000, - - // villsa [STRIFE] can NPC talk? - MF_NODIALOG = 0x8000, - - // Don't hit same species, explode on block. - // Player missiles as well as fireballs of various kinds. - MF_MISSILE = 0x10000, - - // Dropped by a demon, not level spawned. - // E.g. ammo clips dropped by dying former humans. - MF_DROPPED = 0x20000, - - // Use fuzzy draw (shadow demons or spectres), - // temporary player invisibility powerup. - MF_SHADOW = 0x40000, - - // Flag: don't bleed when shot (use puff), - // barrels and shootable furniture shall not bleed. - MF_NOBLOOD = 0x80000, - - // Don't stop moving halfway off a step, - // that is, have dead bodies slide down all the way. - MF_CORPSE = 0x100000, - - // Floating to a height for a move, ??? - // don't auto float to target's height. - MF_INFLOAT = 0x200000, - - // On kill, count this enemy object - // towards intermission kill total. - // Happy gathering. - MF_COUNTKILL = 0x400000, - - // Not to be activated by sound, deaf monster. - MF_AMBUSH = 0x800000, - - // villsa [STRIFE] flag used for bouncing projectiles - MF_BOUNCE = 0x1000000, - - // Don't spawn this object - // in death match mode (e.g. key cards). - MF_NOTDMATCH = 0x2000000, - - // villsa [STRIFE] friendly towards player with matching flag - MF_ALLY = 0x4000000, - - // villsa [STRIFE] 75% or 25% transparency? -- NEEDS VERIFICATION - MF_MVIS = 0x8000000, - - // villsa [STRIFE] color translation - MF_COLORSWAP1 = 0x10000000, - - // villsa [STRIFE] color translation - MF_COLORSWAP2 = 0x20000000, - - // villsa [STRIFE] color translation - MF_COLORSWAP3 = 0x40000000, - - // villsa [STRIFE] spectral entity, only damaged by spectral missiles - MF_SPECTRAL = 0x80000000, - - // Player sprites in multiplayer modes are modified - // using an internal color lookup table for re-indexing. - // haleyjd 09/06/10: redid for Strife translations - MF_TRANSLATION = (MF_COLORSWAP1|MF_COLORSWAP2|MF_COLORSWAP3), - - // Turns 0x10000000 into 0x01 to get a translation index. - // villsa [STRIFE] change from 26 to 28 - MF_TRANSSHIFT = 28 - -} mobjflag_t; - - -// Map Object definition. -// -// [STRIFE]: Amazingly, only one modification was made to mobj_t over DOOM -// 1.666, and that was the addition of the single-byte allegiance field for -// tracking with which player friendly monsters are allied. -// -typedef struct mobj_s -{ - // List: thinker links. - thinker_t thinker; - - // Info for drawing: position. - fixed_t x; - fixed_t y; - fixed_t z; - - // More list: links in sector (if needed) - struct mobj_s* snext; - struct mobj_s* sprev; - - //More drawing info: to determine current sprite. - angle_t angle; // orientation - spritenum_t sprite; // used to find patch_t and flip value - int frame; // might be ORed with FF_FULLBRIGHT - - // Interaction info, by BLOCKMAP. - // Links in blocks (if needed). - struct mobj_s* bnext; - struct mobj_s* bprev; - - struct subsector_s* subsector; - - // The closest interval over all contacted Sectors. - fixed_t floorz; - fixed_t ceilingz; - - // For movement checking. - fixed_t radius; - fixed_t height; - - // Momentums, used to update position. - fixed_t momx; - fixed_t momy; - fixed_t momz; - - // If == validcount, already checked. - int validcount; - - mobjtype_t type; - mobjinfo_t* info; // &mobjinfo[mobj->type] - - int tics; // state tic counter - state_t* state; - int flags; - int health; - - // Movement direction, movement generation (zig-zagging). - int movedir; // 0-7 - int movecount; // when 0, select a new dir - - // Thing being chased/attacked (or NULL), - // also the originator for missiles. - struct mobj_s* target; - - // Reaction time: if non 0, don't attack yet. - // Used by player to freeze a bit after teleporting. - int reactiontime; - - // If >0, the target will be chased - // no matter what (even if shot) - int threshold; - - // Additional info record for player avatars only. - // Only valid if type == MT_PLAYER - struct player_s* player; - - // Player number last looked for. - int lastlook; - - // For nightmare respawn. - mapthing_t spawnpoint; - - // Thing being chased/attacked for tracers. - struct mobj_s* tracer; - - // [STRIFE] haleyjd 09/05/10: - // * In multiplayer this stores allegiance, for friends and teleport beacons - // * In single-player this tracks dialog state. - byte miscdata; - -} mobj_t; - -// haleyjd [STRIFE] Exported -void P_CheckMissileSpawn (mobj_t* th); - -#endif diff --git a/games/NXDoom/src/strife/p_plats.c b/games/NXDoom/src/strife/p_plats.c deleted file mode 100644 index aeb0eb5aa9a..00000000000 --- a/games/NXDoom/src/strife/p_plats.c +++ /dev/null @@ -1,358 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Plats (i.e. elevator platforms) code, raising/lowering. -// - -#include - -#include "i_system.h" -#include "z_zone.h" -#include "m_random.h" - -#include "doomdef.h" -#include "p_local.h" - -#include "s_sound.h" - -// State. -#include "doomstat.h" -#include "r_state.h" - -// Data. -#include "sounds.h" - - -plat_t* activeplats[MAXPLATS]; - - - -// -// Move a plat up and down -// -void T_PlatRaise(plat_t* plat) -{ - result_e res; - - switch(plat->status) - { - case up: - res = T_MovePlane(plat->sector, plat->speed, plat->high, plat->crush, 0, 1); - - if(plat->type == raiseAndChange - || plat->type == raiseToNearestAndChange) - { - if(!(leveltime&7)) - S_StartSound(&plat->sector->soundorg, sfx_stnmov); - } - - // villsa [STRIFE] - if(plat->type == slowDWUS) - { - if(!(leveltime&7)) - S_StartSound(&plat->sector->soundorg, sfx_stnmov); - } - - - if(res == crushed && (!plat->crush)) - { - plat->count = plat->wait; - plat->status = down; - S_StartSound(&plat->sector->soundorg, sfx_pstart); - } - else - { - if(res == pastdest) - { - plat->count = plat->wait; - plat->status = waiting; - S_StartSound(&plat->sector->soundorg, sfx_pstop); - - switch(plat->type) - { - case blazeDWUS: - case downWaitUpStay: - case raiseAndChange: - case slowDWUS: // villsa [STRIFE] - case raiseToNearestAndChange: - P_RemoveActivePlat(plat); - break; - - default: - break; - } - } - } - break; - - case down: - res = T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, -1); - - // villsa [STRIFE] - if(plat->type == slowDWUS) - { - if(!(leveltime&7)) - S_StartSound(&plat->sector->soundorg, sfx_stnmov); - } - - if(res == pastdest) - { - plat->count = plat->wait; - plat->status = waiting; - S_StartSound(&plat->sector->soundorg,sfx_pstop); - - // villsa [STRIFE] - if(plat->type == upWaitDownStay) - P_RemoveActivePlat(plat); - } - break; - - case waiting: - if(!--plat->count) - { - if(plat->sector->floorheight == plat->low) - plat->status = up; - else - plat->status = down; - S_StartSound(&plat->sector->soundorg,sfx_pstart); - } - - case in_stasis: - break; - } -} - - -// -// EV_DoPlat -// -// Do Platforms "amount" is only used for SOME platforms. -// -int EV_DoPlat(line_t* line, plattype_e type, int amount) -{ - plat_t* plat; - int secnum; - int rtn; - sector_t* sec; - - secnum = -1; - rtn = 0; - - - // Activate all plats that are in_stasis - switch(type) - { - case perpetualRaise: - P_ActivateInStasis(line->tag); - break; - - default: - break; - } - - while((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - sec = §ors[secnum]; - - if (sec->specialdata) - continue; - - // Find lowest & highest floors around sector - rtn = 1; - plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); - P_AddThinker(&plat->thinker); - - plat->type = type; - plat->sector = sec; - plat->sector->specialdata = plat; - plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise; - plat->crush = false; - plat->tag = line->tag; - - switch(type) - { - case raiseToNearestAndChange: - plat->speed = PLATSPEED/2; - sec->floorpic = sides[line->sidenum[0]].sector->floorpic; - plat->high = P_FindNextHighestFloor(sec,sec->floorheight); - plat->wait = 0; - plat->status = up; - - // NO MORE DAMAGE, IF APPLICABLE - sec->special = 0; - - S_StartSound(&sec->soundorg, sfx_stnmov); - break; - - case raiseAndChange: - plat->speed = PLATSPEED/2; - sec->floorpic = sides[line->sidenum[0]].sector->floorpic; - plat->high = sec->floorheight + amount * FRACUNIT; - plat->wait = 0; - plat->status = up; - - S_StartSound(&sec->soundorg, sfx_stnmov); - break; - - // villsa [STRIFE] - case upWaitDownStay: - plat->speed = PLATSPEED * 4; - plat->high = P_FindNextHighestFloor(sec, sec->floorheight); - plat->low = sec->floorheight; - plat->wait = TICRATE * PLATWAIT; - plat->status = up; - S_StartSound(&sec->soundorg, sfx_pstart); - break; - - case downWaitUpStay: - plat->speed = PLATSPEED * 4; - plat->low = P_FindLowestFloorSurrounding(sec); - - if(plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = sec->floorheight; - plat->wait = TICRATE * PLATWAIT; - plat->status = down; - S_StartSound(&sec->soundorg, sfx_pstart); - break; - - // villsa [STRIFE] - case slowDWUS: - plat->speed = PLATSPEED; - plat->low = P_FindLowestFloorSurrounding(sec); - - if(plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = sec->floorheight; - plat->wait = TICRATE * (PLATWAIT * 10); - plat->status = down; - S_StartSound(&sec->soundorg,sfx_pstart); - break; - - case blazeDWUS: - plat->speed = PLATSPEED * 8; - plat->low = P_FindLowestFloorSurrounding(sec); - - if(plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = sec->floorheight; - plat->wait = TICRATE * PLATWAIT; - plat->status = down; - S_StartSound(&sec->soundorg, sfx_pstart); - break; - - case perpetualRaise: - plat->speed = PLATSPEED; - plat->low = P_FindLowestFloorSurrounding(sec); - - if(plat->low > sec->floorheight) - plat->low = sec->floorheight; - - plat->high = P_FindHighestFloorSurrounding(sec); - - if(plat->high < sec->floorheight) - plat->high = sec->floorheight; - - plat->wait = TICRATE * PLATWAIT; - plat->status = P_Random() & 1; - - S_StartSound(&sec->soundorg, sfx_pstart); - break; - } - - P_AddActivePlat(plat); - } - return rtn; -} - - -// -// P_ActivateInStasis -// -void P_ActivateInStasis(int tag) -{ - int i; - - for(i = 0; i < MAXPLATS; i++) - if(activeplats[i] - && (activeplats[i])->tag == tag - && (activeplats[i])->status == in_stasis) - { - (activeplats[i])->status = (activeplats[i])->oldstatus; - (activeplats[i])->thinker.function.acp1 - = (actionf_p1)T_PlatRaise; - } -} - -// -// EV_StopPlat -// -void EV_StopPlat(line_t* line) -{ - int j; - - for(j = 0; j < MAXPLATS; j++) - if (activeplats[j] - && ((activeplats[j])->status != in_stasis) - && ((activeplats[j])->tag == line->tag)) - { - (activeplats[j])->oldstatus = (activeplats[j])->status; - (activeplats[j])->status = in_stasis; - (activeplats[j])->thinker.function.acv = (actionf_v)NULL; - } -} - -// -// P_AddActivePlat -// -void P_AddActivePlat(plat_t* plat) -{ - int i; - - for(i = 0; i < MAXPLATS; i++) - { - if (activeplats[i] == NULL) - { - activeplats[i] = plat; - return; - } - } - - I_Error("P_AddActivePlat: no more plats!"); -} - -// -// P_RemoveActivePlat -// -void P_RemoveActivePlat(plat_t* plat) -{ - int i; - for(i = 0; i < MAXPLATS; i++) - { - if(plat == activeplats[i]) - { - (activeplats[i])->sector->specialdata = NULL; - P_RemoveThinker(&(activeplats[i])->thinker); - activeplats[i] = NULL; - - return; - } - } - - I_Error("P_RemoveActivePlat: can't find plat!"); -} diff --git a/games/NXDoom/src/strife/p_pspr.c b/games/NXDoom/src/strife/p_pspr.c deleted file mode 100644 index f7f2839351e..00000000000 --- a/games/NXDoom/src/strife/p_pspr.c +++ /dev/null @@ -1,1003 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Weapon sprite animation, weapon objects. -// Action functions for weapons. -// - - -#include "doomdef.h" -#include "d_event.h" - -#include "deh_misc.h" - -#include "m_random.h" -#include "p_local.h" -#include "s_sound.h" - -// State. -#include "doomstat.h" - -// Data. -#include "sounds.h" - -#include "p_pspr.h" - -#define LOWERSPEED FRACUNIT*6 -#define RAISESPEED FRACUNIT*6 - -#define WEAPONBOTTOM 128*FRACUNIT -#define WEAPONTOP 32*FRACUNIT - - - -// -// P_SetPsprite -// -// [STRIFE] -// villsa: Removed psprite sx, sy modification via misc1/2 -// -void -P_SetPsprite -( player_t* player, - int position, - statenum_t stnum ) -{ - pspdef_t* psp; - state_t* state; - - psp = &player->psprites[position]; - - do - { - if (!stnum) - { - // object removed itself - psp->state = NULL; - break; - } - - state = &states[stnum]; - psp->state = state; - psp->tics = state->tics; // could be 0 - - // villsa [STRIFE] unused - /*if (state->misc1) - { - // coordinate set - psp->sx = state->misc1 << FRACBITS; - psp->sy = state->misc2 << FRACBITS; - }*/ - - // Call action routine. - // Modified handling. - if (state->action.acp2) - { - state->action.acp2(player, psp); - if (!psp->state) - break; - } - - stnum = psp->state->nextstate; - - } while (!psp->tics); - // an initial state of 0 could cycle through -} - -// haleyjd 09/06/10: [STRIFE] Removed P_CalcSwing - -// -// P_BringUpWeapon -// Starts bringing the pending weapon up -// from the bottom of the screen. -// Uses player -// -// villsa [STRIFE] Modifications for Strife weapons -// -void P_BringUpWeapon (player_t* player) -{ - statenum_t newstate; - - if (player->pendingweapon == wp_nochange) - player->pendingweapon = player->readyweapon; - - if (player->pendingweapon == wp_flame) - S_StartSound (player->mo, sfx_flidl); // villsa [STRIFE] flame sounds - - newstate = weaponinfo[player->pendingweapon].upstate; - - player->psprites[ps_weapon].sy = WEAPONBOTTOM; - P_SetPsprite (player, ps_weapon, newstate); - - // villsa [STRIFE] set various flash states - if(player->pendingweapon == wp_elecbow) - P_SetPsprite(player, ps_flash, S_XBOW_10); // 31 - else if(player->pendingweapon == wp_sigil && player->sigiltype) - P_SetPsprite(player, ps_flash, S_SIGH_00 + player->sigiltype); // 117 - else - P_SetPsprite(player, ps_flash, S_NULL); - - player->pendingweapon = wp_nochange; -} - -// -// P_CheckAmmo -// Returns true if there is enough ammo to shoot. -// If not, selects the next weapon to use. -// -// villsa [STRIFE] Changes to handle Strife weapons -// -boolean P_CheckAmmo (player_t* player) -{ - ammotype_t ammo; - int count; - - ammo = weaponinfo[player->readyweapon].ammo; - - // Minimal amount for one shot varies. - if (player->readyweapon == wp_torpedo) - count = 30; - else if (player->readyweapon == wp_mauler) - count = 20; - else - count = 1; // Regular. - - // Some do not need ammunition anyway. - // Return if current ammunition sufficient. - if (ammo == am_noammo || player->ammo[ammo] >= count) - return true; - - // Out of ammo, pick a weapon to change to. - // Preferences are set here. - - // villsa [STRIFE] new weapon preferences - if (player->weaponowned[wp_mauler] && player->ammo[am_cell] >= 20) - player->pendingweapon = wp_mauler; - - else if(player->weaponowned[wp_rifle] && player->ammo[am_bullets]) - player->pendingweapon = wp_rifle; - - else if (player->weaponowned[wp_elecbow] && player->ammo[am_elecbolts]) - player->pendingweapon = wp_elecbow; - - else if (player->weaponowned[wp_missile] && player->ammo[am_missiles]) - player->pendingweapon = wp_missile; - - else if (player->weaponowned[wp_flame] && player->ammo[am_cell]) - player->pendingweapon = wp_flame; - - else if (player->weaponowned[wp_hegrenade] && player->ammo[am_hegrenades]) - player->pendingweapon = wp_hegrenade; - - else if (player->weaponowned[wp_poisonbow] && player->ammo[am_poisonbolts]) - player->pendingweapon = wp_poisonbow; - - else if (player->weaponowned[wp_wpgrenade] && player->ammo[am_wpgrenades]) - player->pendingweapon = wp_wpgrenade; - - // BUG: This will *never* be selected for an automatic switch because the - // normal Mauler is higher priority and uses less ammo. - else if (player->weaponowned[wp_torpedo] && player->ammo[am_cell] >= 30) - player->pendingweapon = wp_torpedo; - - else - player->pendingweapon = wp_fist; - - - // Now set appropriate weapon overlay. - P_SetPsprite(player, ps_weapon, weaponinfo[player->readyweapon].downstate); - - return false; -} - - -// -// P_FireWeapon. -// -// villsa [STRIFE] Changes for player state and weapons -// -void P_FireWeapon (player_t* player) -{ - statenum_t newstate; - - if (!P_CheckAmmo (player)) - return; - - P_SetMobjState (player->mo, S_PLAY_05); // 292 - newstate = weaponinfo[player->readyweapon].atkstate; - P_SetPsprite (player, ps_weapon, newstate); - - // villsa [STRIFE] exclude these weapons from causing noise - if(player->readyweapon > wp_elecbow && player->readyweapon != wp_poisonbow) - P_NoiseAlert (player->mo, player->mo); -} - - - -// -// P_DropWeapon -// Player died, so put the weapon away. -// -void P_DropWeapon (player_t* player) -{ - P_SetPsprite (player, - ps_weapon, - weaponinfo[player->readyweapon].downstate); -} - - - -// -// A_WeaponReady -// The player can fire the weapon -// or change to another weapon at this time. -// Follows after getting weapon up, -// or after previous attack/fire sequence. -// -void A_WeaponReady( player_t* player, pspdef_t* psp) -{ - statenum_t newstate; - int angle; - - // get out of attack state - if (player->mo->state == &states[S_PLAY_05] || // 292 - player->mo->state == &states[S_PLAY_06]) // 293 - { - P_SetMobjState (player->mo, S_PLAY_00); // 287 - } - - // villsa [STRIFE] check for wp_flame instead of chainsaw - // haleyjd 09/06/10: fixed state (00 rather than 01) - if (player->readyweapon == wp_flame - && psp->state == &states[S_FLMT_00]) // 62 - { - S_StartSound (player->mo, sfx_flidl); - } - - // check for change - // if player is dead, put the weapon away - if (player->pendingweapon != wp_nochange || !player->health) - { - // change weapon - // (pending weapon should allready be validated) - newstate = weaponinfo[player->readyweapon].downstate; - P_SetPsprite (player, ps_weapon, newstate); - return; - } - - // check for fire - // the missile launcher and torpedo do not auto fire - if (player->cmd.buttons & BT_ATTACK) - { - if ( !player->attackdown - || (player->readyweapon != wp_missile - && player->readyweapon != wp_torpedo)) // villsa [STRIFE] replace bfg with torpedo - { - player->attackdown = true; - P_FireWeapon (player); - return; - } - } - else - player->attackdown = false; - - // bob the weapon based on movement speed - angle = (128*leveltime)&FINEMASK; - psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); - angle &= FINEANGLES/2-1; - psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); -} - - - -// -// A_ReFire -// The player can re-fire the weapon -// without lowering it entirely. -// -void A_ReFire -( player_t* player, - pspdef_t* psp ) -{ - - // check for fire - // (if a weaponchange is pending, let it go through instead) - if ( (player->cmd.buttons & BT_ATTACK) - && player->pendingweapon == wp_nochange - && player->health) - { - player->refire++; - P_FireWeapon (player); - } - else - { - player->refire = 0; - P_CheckAmmo (player); - } -} - -// -// A_CheckReload -// -void A_CheckReload(player_t* player, pspdef_t* psp) -{ - P_CheckAmmo(player); - - // villsa [STRIFE] set animating sprite for crossbow - if(player->readyweapon == wp_elecbow) - P_SetPsprite(player, player->readyweapon, S_XBOW_10); -} - - - -// -// A_Lower -// Lowers current weapon, -// and changes weapon at bottom. -// -void -A_Lower -( player_t* player, - pspdef_t* psp ) -{ - psp->sy += LOWERSPEED; - - // Is already down. - if (psp->sy < WEAPONBOTTOM ) - return; - - // Player is dead. - if (player->playerstate == PST_DEAD) - { - psp->sy = WEAPONBOTTOM; - - // don't bring weapon back up - return; - } - - // The old weapon has been lowered off the screen, - // so change the weapon and start raising it - if (!player->health) - { - // Player is dead, so keep the weapon off screen. - P_SetPsprite (player, ps_weapon, S_NULL); - return; - } - - player->readyweapon = player->pendingweapon; - - P_BringUpWeapon (player); -} - - -// -// A_Raise -// -void -A_Raise -( player_t* player, - pspdef_t* psp ) -{ - statenum_t newstate; - - psp->sy -= RAISESPEED; - - if (psp->sy > WEAPONTOP ) - return; - - psp->sy = WEAPONTOP; - - // The weapon has been raised all the way, - // so change to the ready state. - newstate = weaponinfo[player->readyweapon].readystate; - - P_SetPsprite (player, ps_weapon, newstate); -} - - - -// -// A_GunFlash -// -void -A_GunFlash -( player_t* player, - pspdef_t* psp ) -{ - P_SetMobjState (player->mo, S_PLAY_06); - P_SetPsprite (player,ps_flash,weaponinfo[player->readyweapon].flashstate); -} - - - -// -// WEAPON ATTACKS -// - - -// -// A_Punch -// - -void A_Punch(player_t* player, pspdef_t* psp) -{ - angle_t angle; - int damage; - int slope; - int sound; - int stamina; - int t; - - // villsa [STRIFE] new damage formula - // haleyjd 09/19/10: seriously corrected... - stamina = player->stamina; - damage = (P_Random() & ((stamina/10) + 7)) * ((stamina/10) + 2); - - if(player->powers[pw_strength]) - damage *= 10; - - angle = player->mo->angle; - t = P_Random(); - angle += (t - P_Random()) << 18; - slope = P_AimLineAttack (player->mo, angle, PLAYERMELEERANGE); - P_LineAttack (player->mo, angle, PLAYERMELEERANGE, slope, damage); - - // turn to face target - if(linetarget) - { - // villsa [STRIFE] check for non-flesh types - if(linetarget->flags & MF_NOBLOOD) - sound = sfx_mtalht; - else - sound = sfx_meatht; - - S_StartSound (player->mo, sound); - player->mo->angle = R_PointToAngle2 (player->mo->x, - player->mo->y, - linetarget->x, - linetarget->y); - - // villsa [STRIFE] apply flag - player->mo->flags |= MF_JUSTATTACKED; - - // villsa [STRIFE] do punch alert routine - P_DoPunchAlert(player->mo, linetarget); - } - else - S_StartSound (player->mo, sfx_swish); -} - - -// -// A_FireFlameThrower -// -// villsa [STRIFE] new codepointer -// -void A_FireFlameThrower(player_t* player, pspdef_t* psp) -{ - mobj_t* mo; - int t; - - P_SetMobjState(player->mo, S_PLAY_06); - player->ammo[weaponinfo[player->readyweapon].ammo]--; - t = P_Random(); - player->mo->angle += (t - P_Random()) << 18; - - mo = P_SpawnPlayerMissile(player->mo, MT_SFIREBALL); - mo->momz += (5*FRACUNIT); -} - -// -// A_FireMissile -// -// villsa [STRIFE] completly new compared to the original -// -void A_FireMissile(player_t* player, pspdef_t* psp) -{ - angle_t an; - int t; - - // haleyjd 09/19/10: I previously missed an add op that meant it should be - // accuracy * 5, not 4. Checks out with other sources. - an = player->mo->angle; - t = P_Random(); - player->mo->angle += (t - P_Random()) << (19 - (player->accuracy * 5 / 100)); - P_SetMobjState(player->mo, S_PLAY_06); - player->ammo[weaponinfo[player->readyweapon].ammo]--; - P_SpawnPlayerMissile(player->mo, MT_MINIMISSLE); - player->mo->angle = an; -} - -// -// A_FireMauler2 -// -// villsa [STRIFE] - new codepointer -// -void A_FireMauler2(player_t* player, pspdef_t* pspr) -{ - P_SetMobjState(player->mo, S_PLAY_06); - P_DamageMobj(player->mo, player->mo, NULL, 20); - player->ammo[weaponinfo[player->readyweapon].ammo] -= 30; - P_SpawnPlayerMissile(player->mo, MT_TORPEDO); - P_Thrust(player, player->mo->angle + ANG180, 512000); -} - -// -// A_FireGrenade -// -// villsa [STRIFE] - new codepointer -// -void A_FireGrenade(player_t* player, pspdef_t* pspr) -{ - mobjtype_t type; - mobj_t* mo; - state_t* st1; - state_t* st2; - angle_t an; - fixed_t radius; - - // decide on what type of grenade to spawn - if(player->readyweapon == wp_hegrenade) - { - type = MT_HEGRENADE; - } - else if(player->readyweapon == wp_wpgrenade) - { - type = MT_PGRENADE; - } - else - { - type = MT_HEGRENADE; - fprintf(stderr, "Warning: A_FireGrenade used on wrong weapon!\n"); - } - - player->ammo[weaponinfo[player->readyweapon].ammo]--; - - // set flash frame - st1 = &states[(pspr->state - states) + weaponinfo[player->readyweapon].flashstate]; - st2 = &states[weaponinfo[player->readyweapon].atkstate]; - P_SetPsprite(player, ps_flash, st1 - st2); - - player->mo->z += 32*FRACUNIT; // ugh - mo = P_SpawnMortar(player->mo, type); - player->mo->z -= 32*FRACUNIT; // ugh - - // change momz based on player's pitch - mo->momz = FixedMul((player->pitch<info->speed) + (8*FRACUNIT); - S_StartSound(mo, mo->info->seesound); - - radius = mobjinfo[type].radius + player->mo->info->radius; - an = (player->mo->angle >> ANGLETOFINESHIFT); - - mo->x += FixedMul(finecosine[an], radius + (4*FRACUNIT)); - mo->y += FixedMul(finesine[an], radius + (4*FRACUNIT)); - - // shoot grenade from left or right side? - if(&states[weaponinfo[player->readyweapon].atkstate] == pspr->state) - an = (player->mo->angle - ANG90) >> ANGLETOFINESHIFT; - else - an = (player->mo->angle + ANG90) >> ANGLETOFINESHIFT; - - mo->x += FixedMul((15*FRACUNIT), finecosine[an]); - mo->y += FixedMul((15*FRACUNIT), finesine[an]); - - // set bounce flag - mo->flags |= MF_BOUNCE; -} - -// -// A_FireElectricBolt -// villsa [STRIFE] - new codepointer -// - -void A_FireElectricBolt(player_t* player, pspdef_t* pspr) -{ - angle_t an = player->mo->angle; - int t; - - // haleyjd 09/19/10: Use 5 mul on accuracy here as well - t = P_Random(); - player->mo->angle += (t - P_Random()) << (18 - (player->accuracy * 5 / 100)); - player->ammo[weaponinfo[player->readyweapon].ammo]--; - P_SpawnPlayerMissile(player->mo, MT_ELECARROW); - player->mo->angle = an; - S_StartSound(player->mo, sfx_xbow); -} - -// -// A_FirePoisonBolt -// villsa [STRIFE] - new codepointer -// - -void A_FirePoisonBolt(player_t* player, pspdef_t* pspr) -{ - angle_t an = player->mo->angle; - int t; - - // haleyjd 09/19/10: Use 5 mul on accuracy here as well - t = P_Random(); - player->mo->angle += (t - P_Random()) << (18 - (player->accuracy * 5 / 100)); - player->ammo[weaponinfo[player->readyweapon].ammo]--; - P_SpawnPlayerMissile(player->mo, MT_POISARROW); - player->mo->angle = an; - S_StartSound(player->mo, sfx_xbow); -} - -// -// P_BulletSlope -// Sets a slope so a near miss is at aproximately -// the height of the intended target -// -// haleyjd 09/06/10 [STRIFE] Modified with a little target hack... -// -fixed_t bulletslope; - - -void P_BulletSlope (mobj_t *mo) -{ - angle_t an; - - // see which target is to be aimed at - an = mo->angle; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - - if (!linetarget) - { - an += 1<<26; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - if (!linetarget) - { - an -= 2<<26; - bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); - } - } - - // haleyjd 09/06/10: [STRIFE] Somebody added this here, and without it, you - // will get spurious crashing in routines such as P_LookForPlayers! - if(linetarget) - mo->target = linetarget; -} - - -// -// P_GunShot -// -// [STRIFE] Modifications to support accuracy. -// -void -P_GunShot -( mobj_t* mo, - boolean accurate ) -{ - angle_t angle; - int damage; - - angle = mo->angle; - - // villsa [STRIFE] apply player accuracy - // haleyjd 09/18/10: made some corrections: use 5x accuracy; - // eliminated order-of-evaluation dependency - if (!accurate) - { - int t = P_Random(); - angle += (t - P_Random()) << (20 - ((mo->player->accuracy * 5) / 100)); - } - - // haleyjd 09/18/10 [STRIFE] corrected damage formula and moved down to - // preserve proper P_Random call order. - damage = 4 * (P_Random() % 3 + 1); - - P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage); -} - -// -// A_FireRifle -// -// villsa [STRIFE] - new codepointer -// -void A_FireRifle(player_t* player, pspdef_t* pspr) -{ - S_StartSound(player->mo, sfx_rifle); - - if(player->ammo[weaponinfo[player->readyweapon].ammo]) - { - P_SetMobjState(player->mo, S_PLAY_06); // 293 - player->ammo[weaponinfo[player->readyweapon].ammo]--; - P_BulletSlope(player->mo); - P_GunShot(player->mo, !player->refire); - } -} - -// -// A_FireMauler1 -// -// villsa [STRIFE] - new codepointer -// -void A_FireMauler1(player_t* player, pspdef_t* pspr) -{ - int i; - angle_t angle; - int damage; - - // haleyjd 09/18/10: Corrected ammo check to use >= - if(player->ammo[weaponinfo[player->readyweapon].ammo] >= 20) - { - player->ammo[weaponinfo[player->readyweapon].ammo] -= 20; - P_BulletSlope(player->mo); - S_StartSound(player->mo, sfx_pgrdat); - - for(i = 0; i < 20; i++) - { - int t; - damage = 5*(P_Random ()%3+1); - angle = player->mo->angle; - t = P_Random(); - angle += (t - P_Random()) << 19; - t = P_Random(); - P_LineAttack(player->mo, angle, 2112*FRACUNIT, - bulletslope + ((t - P_Random())<<5), damage); - } - } -} - -// -// A_SigilSound -// -// villsa [STRIFE] - new codepointer -// -void A_SigilSound(player_t* player, pspdef_t* pspr) -{ - S_StartSound(player->mo, sfx_siglup); - player->extralight = 2; - -} - -// -// A_FireSigil -// -// villsa [STRIFE] - new codepointer -// -void A_FireSigil(player_t* player, pspdef_t* pspr) -{ - mobj_t* mo; - angle_t an; - int i; - - // keep info on armor because sigil does piercing damage - i = player->armortype; - player->armortype = 0; - - // BUG: setting inflictor causes firing the Sigil to always push the player - // toward the east, no matter what direction he is facing. - P_DamageMobj(player->mo, player->mo, NULL, 4 * (player->sigiltype + 1)); - - // restore armor - player->armortype = i; - - S_StartSound(player->mo, sfx_siglup); - - switch(player->sigiltype) - { - // falling lightning bolts from the sky - case 0: - P_BulletSlope(player->mo); - if(linetarget) - { - // haleyjd 09/18/10: corrected z coordinate - mo = P_SpawnMobj(linetarget->x, linetarget->y, ONFLOORZ, - MT_SIGIL_A_GROUND); - mo->tracer = linetarget; - } - else - { - an = player->mo->angle>>ANGLETOFINESHIFT; - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, - MT_SIGIL_A_GROUND); - mo->momx += FixedMul((28*FRACUNIT), finecosine[an]); - mo->momy += FixedMul((28*FRACUNIT), finesine[an]); - } - mo->health = -1; - mo->target = player->mo; - break; - - // simple projectile - case 1: - P_SpawnPlayerMissile(player->mo, MT_SIGIL_B_SHOT)->health = -1; - break; - - // spread shot - case 2: - player->mo->angle -= ANG90; // starting at 270... - for(i = 0; i < 20; i++) // increment by 1/10 of 90, 20 times. - { - player->mo->angle += (ANG90 / 10); - mo = P_SpawnMortar(player->mo, MT_SIGIL_C_SHOT); - mo->health = -1; - mo->z = player->mo->z + (32*FRACUNIT); - } - player->mo->angle -= ANG90; // subtract off the extra 90 - break; - - // tracer attack - case 3: - P_BulletSlope(player->mo); - if(linetarget) - { - mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_D_SHOT); - mo->tracer = linetarget; - } - else - { - an = player->mo->angle >> ANGLETOFINESHIFT; - mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_D_SHOT); - mo->momx += FixedMul(mo->info->speed, finecosine[an]); - mo->momy += FixedMul(mo->info->speed, finesine[an]); - } - mo->health = -1; - break; - - // mega blast - case 4: - mo = P_SpawnPlayerMissile(player->mo, MT_SIGIL_E_SHOT); - mo->health = -1; - if(!linetarget) - { - an = (unsigned int)player->pitch >> ANGLETOFINESHIFT; - mo->momz += FixedMul(finesine[an], mo->info->speed); - } - break; - - default: - break; - } -} - -// -// A_GunFlashThinker -// -// villsa [STRIFE] - new codepointer -// -void A_GunFlashThinker(player_t* player, pspdef_t* pspr) -{ - if(player->readyweapon == wp_sigil && player->sigiltype) - P_SetPsprite(player, ps_flash, S_SIGH_00 + player->sigiltype); - else - P_SetPsprite(player, ps_flash, S_NULL); - -} - - -// -// ? -// -void A_Light0 (player_t *player, pspdef_t *psp) -{ - player->extralight = 0; -} - -void A_Light1 (player_t *player, pspdef_t *psp) -{ - player->extralight = 1; -} - -void A_Light2 (player_t *player, pspdef_t *psp) -{ - player->extralight = 2; -} - -// -// A_SigilShock -// -// villsa [STRIFE] - new codepointer -// -void A_SigilShock (player_t *player, pspdef_t *psp) -{ - player->extralight = -3; -} - -// -// A_TorpedoExplode -// -// villsa [STRIFE] - new codepointer -// -void A_TorpedoExplode(mobj_t* actor) -{ - int i; - - actor->angle -= ANG180; - - for(i = 0; i < 80; i++) - { - actor->angle += (ANG90 / 20); - P_SpawnMortar(actor, MT_TORPEDOSPREAD)->target = actor->target; - } -} - -// -// A_MaulerSound -// -// villsa [STRIFE] - new codepointer -// -void A_MaulerSound(player_t *player, pspdef_t *psp) -{ - int t; - S_StartSound(player->mo, sfx_proton); - t = P_Random(); - psp->sx += (t - P_Random()) << 10; - t = P_Random(); - psp->sy += (t - P_Random()) << 10; - -} - - -// -// P_SetupPsprites -// Called at start of level for each player. -// -void P_SetupPsprites(player_t* player) -{ - int i; - - // remove all psprites - for(i = 0; i < NUMPSPRITES; i++) - player->psprites[i].state = NULL; - - // spawn the gun - player->pendingweapon = player->readyweapon; - P_BringUpWeapon(player); -} - - - - -// -// P_MovePsprites -// Called every tic by player thinking routine. -// -void P_MovePsprites (player_t* player) -{ - int i; - pspdef_t* psp; - - psp = &player->psprites[0]; - for(i = 0; i < NUMPSPRITES; i++, psp++) - { - // a null state means not active - if(psp->state) - { - // drop tic count and possibly change state - - // a -1 tic count never changes - if(psp->tics != -1) - { - psp->tics--; - if(!psp->tics) - P_SetPsprite (player, i, psp->state->nextstate); - } - } - } - - player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; - player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; - - // villsa [STRIFE] extra stuff for targeter - player->psprites[ps_targleft].sx = - (160*FRACUNIT) - ((100 - player->accuracy) << FRACBITS); - - player->psprites[ps_targright].sx = - ((100 - player->accuracy) << FRACBITS) + (160*FRACUNIT); -} - - diff --git a/games/NXDoom/src/strife/p_pspr.h b/games/NXDoom/src/strife/p_pspr.h deleted file mode 100644 index ec4d13700e6..00000000000 --- a/games/NXDoom/src/strife/p_pspr.h +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Sprite animation. -// - - -#ifndef __P_PSPR__ -#define __P_PSPR__ - -// Basic data types. -// Needs fixed point, and BAM angles. -#include "m_fixed.h" -#include "p_mobj.h" -#include "tables.h" - - -// -// Needs to include the precompiled -// sprite animation tables. -// Header generated by multigen utility. -// This includes all the data for thing animation, -// i.e. the Thing Atrributes table -// and the Frame Sequence table. -#include "info.h" - - - -// -// Frame flags: -// handles maximum brightness (torches, muzzle flare, light sources) -// -#define FF_FULLBRIGHT 0x8000 // flag in thing->frame -#define FF_FRAMEMASK 0x7fff - - - -// -// Overlay psprites are scaled shapes -// drawn directly on the view screen, -// coordinates are given for a 320*200 view screen. -// -typedef enum -{ - ps_weapon, - ps_flash, - ps_targcenter, // villsa [STRIFE] - ps_targleft, // villsa [STRIFE] - ps_targright, // villsa [STRIFE] - NUMPSPRITES - -} psprnum_t; - -typedef struct -{ - state_t* state; // a NULL state means not active - int tics; - fixed_t sx; - fixed_t sy; - -} pspdef_t; - -typedef struct player_s *playerptr; - - -extern fixed_t bulletslope; - - -// haleyjd [STRIFE] Exported -void P_SetPsprite(playerptr player, int position, statenum_t stnum); -void P_BulletSlope(mobj_t *mo); - - -#endif diff --git a/games/NXDoom/src/strife/p_saveg.c b/games/NXDoom/src/strife/p_saveg.c deleted file mode 100644 index f1782c1e511..00000000000 --- a/games/NXDoom/src/strife/p_saveg.c +++ /dev/null @@ -1,2208 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Archiving: SaveGame I/O. -// - - -#include -#include - -#include "dstrings.h" -#include "deh_main.h" -#include "i_system.h" -#include "z_zone.h" -#include "m_misc.h" -#include "p_local.h" -#include "p_saveg.h" - -// State. -#include "doomstat.h" -#include "r_state.h" - -#define SAVEGAME_EOF 0x1d - -// haleyjd 09/28/10: [STRIFE] VERSIONSIZE == 8 -#define VERSIONSIZE 8 - -FILE *save_stream; -int savegamelength; -boolean savegame_error; - -// Get the filename of a temporary file to write the savegame to. After -// the file has been successfully saved, it will be renamed to the -// real file. - -char *P_TempSaveGameFile(void) -{ - static char *filename = NULL; - - if (filename == NULL) - { - filename = M_StringJoin(savegamedir, "temp.dsg", NULL); - } - - return filename; -} - -// Get the filename of the save game file to use for the specified slot. - -char *P_SaveGameFile(int slot) -{ - static char *filename = NULL; - static size_t filename_size; - char basename[32]; - - if (filename == NULL) - { - filename_size = strlen(savegamedir) + 32; - filename = malloc(filename_size); - } - - DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot); - - M_snprintf(filename, filename_size, "%s%s", savegamedir, basename); - - return filename; -} - -// Endian-safe integer read/write functions - -static byte saveg_read8(void) -{ - byte result; - - if (fread(&result, 1, 1, save_stream) < 1) - { - if (!savegame_error) - { - fprintf(stderr, "saveg_read8: Unexpected end of file while " - "reading save game\n"); - - savegame_error = true; - } - } - - return result; -} - -static void saveg_write8(byte value) -{ - if (fwrite(&value, 1, 1, save_stream) < 1) - { - if (!savegame_error) - { - fprintf(stderr, "saveg_write8: Error while writing save game\n"); - - savegame_error = true; - } - } -} - -static short saveg_read16(void) -{ - int result; - - result = saveg_read8(); - result |= saveg_read8() << 8; - - return result; -} - -static void saveg_write16(short value) -{ - saveg_write8(value & 0xff); - saveg_write8((value >> 8) & 0xff); -} - -static int saveg_read32(void) -{ - int result; - - result = saveg_read8(); - result |= saveg_read8() << 8; - result |= saveg_read8() << 16; - result |= saveg_read8() << 24; - - return result; -} - -static void saveg_write32(int value) -{ - saveg_write8(value & 0xff); - saveg_write8((value >> 8) & 0xff); - saveg_write8((value >> 16) & 0xff); - saveg_write8((value >> 24) & 0xff); -} - -// Pad to 4-byte boundaries - -static void saveg_read_pad(void) -{ - unsigned long pos; - int padding; - int i; - - pos = ftell(save_stream); - - padding = (4 - (pos & 3)) & 3; - - for (i=0; ix = saveg_read16(); - - // short y; - str->y = saveg_read16(); - - // short angle; - str->angle = saveg_read16(); - - // short type; - str->type = saveg_read16(); - - // short options; - str->options = saveg_read16(); -} - -static void saveg_write_mapthing_t(mapthing_t *str) -{ - // short x; - saveg_write16(str->x); - - // short y; - saveg_write16(str->y); - - // short angle; - saveg_write16(str->angle); - - // short type; - saveg_write16(str->type); - - // short options; - saveg_write16(str->options); -} - -// -// actionf_t -// - -static void saveg_read_actionf_t(actionf_t *str) -{ - // actionf_p1 acp1; - str->acp1 = saveg_readp(); -} - -static void saveg_write_actionf_t(actionf_t *str) -{ - // actionf_p1 acp1; - saveg_writep(str->acp1); -} - -// -// think_t -// -// This is just an actionf_t. -// - -#define saveg_read_think_t saveg_read_actionf_t -#define saveg_write_think_t saveg_write_actionf_t - -// -// thinker_t -// - -static void saveg_read_thinker_t(thinker_t *str) -{ - // struct thinker_s* prev; - str->prev = saveg_readp(); - - // struct thinker_s* next; - str->next = saveg_readp(); - - // think_t function; - saveg_read_think_t(&str->function); -} - -static void saveg_write_thinker_t(thinker_t *str) -{ - // struct thinker_s* prev; - saveg_writep(str->prev); - - // struct thinker_s* next; - saveg_writep(str->next); - - // think_t function; - saveg_write_think_t(&str->function); -} - -// -// mobj_t -// -// haleyjd 09/28/10: [STRIFE] Changed to match Strife binary mobj_t structure. -// - -static void saveg_read_mobj_t(mobj_t *str) -{ - int pl; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // fixed_t x; - str->x = saveg_read32(); - - // fixed_t y; - str->y = saveg_read32(); - - // fixed_t z; - str->z = saveg_read32(); - - // struct mobj_s* snext; - str->snext = saveg_readp(); - - // struct mobj_s* sprev; - str->sprev = saveg_readp(); - - // angle_t angle; - str->angle = saveg_read32(); - - // spritenum_t sprite; - str->sprite = saveg_read_enum(); - - // int frame; - str->frame = saveg_read32(); - - // struct mobj_s* bnext; - str->bnext = saveg_readp(); - - // struct mobj_s* bprev; - str->bprev = saveg_readp(); - - // struct subsector_s* subsector; - str->subsector = saveg_readp(); - - // fixed_t floorz; - str->floorz = saveg_read32(); - - // fixed_t ceilingz; - str->ceilingz = saveg_read32(); - - // fixed_t radius; - str->radius = saveg_read32(); - - // fixed_t height; - str->height = saveg_read32(); - - // fixed_t momx; - str->momx = saveg_read32(); - - // fixed_t momy; - str->momy = saveg_read32(); - - // fixed_t momz; - str->momz = saveg_read32(); - - // int validcount; - str->validcount = saveg_read32(); - - // mobjtype_t type; - str->type = saveg_read_enum(); - - // mobjinfo_t* info; - str->info = saveg_readp(); - - // int tics; - str->tics = saveg_read32(); - - // state_t* state; - str->state = &states[saveg_read32()]; - - // int flags; - str->flags = saveg_read32(); - - // int health; - str->health = saveg_read32(); - - // int movedir; - str->movedir = saveg_read32(); - - // int movecount; - str->movecount = saveg_read32(); - - // struct mobj_s* target; - str->target = saveg_readp(); - - // int reactiontime; - str->reactiontime = saveg_read32(); - - // int threshold; - str->threshold = saveg_read32(); - - // struct player_s* player; - pl = saveg_read32(); - - if (pl > 0) - { - str->player = &players[pl - 1]; - str->player->mo = str; - } - else - { - str->player = NULL; - } - - // int lastlook; - str->lastlook = saveg_read32(); - - // mapthing_t spawnpoint; - saveg_read_mapthing_t(&str->spawnpoint); - - // struct mobj_s* tracer; - str->tracer = saveg_readp(); - - // byte miscdata; - str->miscdata = saveg_read8(); // [STRIFE] Only change to mobj_t. -} - -static void saveg_write_mobj_t(mobj_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // fixed_t x; - saveg_write32(str->x); - - // fixed_t y; - saveg_write32(str->y); - - // fixed_t z; - saveg_write32(str->z); - - // struct mobj_s* snext; - saveg_writep(str->snext); - - // struct mobj_s* sprev; - saveg_writep(str->sprev); - - // angle_t angle; - saveg_write32(str->angle); - - // spritenum_t sprite; - saveg_write_enum(str->sprite); - - // int frame; - saveg_write32(str->frame); - - // struct mobj_s* bnext; - saveg_writep(str->bnext); - - // struct mobj_s* bprev; - saveg_writep(str->bprev); - - // struct subsector_s* subsector; - saveg_writep(str->subsector); - - // fixed_t floorz; - saveg_write32(str->floorz); - - // fixed_t ceilingz; - saveg_write32(str->ceilingz); - - // fixed_t radius; - saveg_write32(str->radius); - - // fixed_t height; - saveg_write32(str->height); - - // fixed_t momx; - saveg_write32(str->momx); - - // fixed_t momy; - saveg_write32(str->momy); - - // fixed_t momz; - saveg_write32(str->momz); - - // int validcount; - saveg_write32(str->validcount); - - // mobjtype_t type; - saveg_write_enum(str->type); - - // mobjinfo_t* info; - saveg_writep(str->info); - - // int tics; - saveg_write32(str->tics); - - // state_t* state; - saveg_write32(str->state - states); - - // int flags; - saveg_write32(str->flags); - - // int health; - saveg_write32(str->health); - - // int movedir; - saveg_write32(str->movedir); - - // int movecount; - saveg_write32(str->movecount); - - // struct mobj_s* target; - saveg_writep(str->target); - - // int reactiontime; - saveg_write32(str->reactiontime); - - // int threshold; - saveg_write32(str->threshold); - - // struct player_s* player; - if (str->player) - { - saveg_write32(str->player - players + 1); - } - else - { - saveg_write32(0); - } - - // int lastlook; - saveg_write32(str->lastlook); - - // mapthing_t spawnpoint; - saveg_write_mapthing_t(&str->spawnpoint); - - // struct mobj_s* tracer; - saveg_writep(str->tracer); - - // byte miscdata; - saveg_write8(str->miscdata); // [STRIFE] Only change to mobj_t. -} - - -// -// ticcmd_t -// -// haleyjd 09/28/10: [STRIFE] Modified for Strife binary ticcmd_t structure. -// - -static void saveg_read_ticcmd_t(ticcmd_t *str) -{ - // signed char forwardmove; - str->forwardmove = saveg_read8(); - - // signed char sidemove; - str->sidemove = saveg_read8(); - - // short angleturn; - str->angleturn = saveg_read16(); - - // short consistancy; - // STRIFE-FIXME: throwing away top byte of consistancy until - // the true Strife ticcmd_t structure is available. - str->consistancy = (byte)saveg_read16(); - - // byte chatchar; - str->chatchar = saveg_read8(); - - // byte buttons; - str->buttons = saveg_read8(); - - // byte buttons2; - str->buttons2 = saveg_read8(); // [STRIFE] - - // int inventory; - str->inventory = saveg_read32(); // [STRIFE] -} - -static void saveg_write_ticcmd_t(ticcmd_t *str) -{ - // signed char forwardmove; - saveg_write8(str->forwardmove); - - // signed char sidemove; - saveg_write8(str->sidemove); - - // short angleturn; - saveg_write16(str->angleturn); - - // short consistancy; - saveg_write16(str->consistancy); - - // byte chatchar; - saveg_write8(str->chatchar); - - // byte buttons; - saveg_write8(str->buttons); - - // byte buttons2; - saveg_write8(str->buttons2); // [STRIFE] - - // int inventory; - saveg_write32(str->inventory); // [STRIFE] -} - -// -// pspdef_t -// - -static void saveg_read_pspdef_t(pspdef_t *str) -{ - int state; - - // state_t* state; - state = saveg_read32(); - - if (state > 0) - { - str->state = &states[state]; - } - else - { - str->state = NULL; - } - - // int tics; - str->tics = saveg_read32(); - - // fixed_t sx; - str->sx = saveg_read32(); - - // fixed_t sy; - str->sy = saveg_read32(); -} - -static void saveg_write_pspdef_t(pspdef_t *str) -{ - // state_t* state; - if (str->state) - { - saveg_write32(str->state - states); - } - else - { - saveg_write32(0); - } - - // int tics; - saveg_write32(str->tics); - - // fixed_t sx; - saveg_write32(str->sx); - - // fixed_t sy; - saveg_write32(str->sy); -} - -// -// inventory_t -// -// haleyjd 09/28/10: [STRIFE] handle inventory input/output -// - -static void saveg_read_inventory_t(inventory_t *str) -{ - //int sprite; - str->sprite = saveg_read32(); - - //int type; - str->type = saveg_read32(); - - //int amount; - str->amount = saveg_read32(); -} - -static void saveg_write_inventory_t(inventory_t *str) -{ - saveg_write32(str->sprite); - saveg_write32(str->type); - saveg_write32(str->amount); -} - -// -// player_t -// -// haleyjd 09/28/10: [STRIFE] Modified for Strife binary player_t structure. -// - -static void saveg_read_player_t(player_t *str) -{ - int i; - - // mobj_t* mo; - str->mo = saveg_readp(); - - // playerstate_t playerstate; - str->playerstate = saveg_read_enum(); - - // ticcmd_t cmd; - saveg_read_ticcmd_t(&str->cmd); - - // fixed_t viewz; - str->viewz = saveg_read32(); - - // fixed_t viewheight; - str->viewheight = saveg_read32(); - - // fixed_t deltaviewheight; - str->deltaviewheight = saveg_read32(); - - // fixed_t bob; - str->bob = saveg_read32(); - - // int health; - str->health = saveg_read32(); - - // int armorpoints; - str->armorpoints = saveg_read16(); // [STRIFE] 32 -> 16 - - // int armortype; - str->armortype = saveg_read16(); // [STRIFE] 32 -> 16 - - // int powers[NUMPOWERS]; - for (i=0; ipowers[i] = saveg_read32(); - } - - // int sigiltype; - str->sigiltype = saveg_read32(); // [STRIFE] - - // int nukagecount; - str->nukagecount = saveg_read32(); // [STRIFE] - - // int questflags; - str->questflags = saveg_read32(); // [STRIFE] - - // int pitch; - str->pitch = saveg_read32(); // [STRIFE] - - // int centerview; - str->centerview = saveg_read32(); // [STRIFE] - - // inventory_t inventory[NUMINVENTORY]; - for(i = 0; i < NUMINVENTORY; i++) - { - saveg_read_inventory_t(&(str->inventory[i])); // [STRIFE] - } - - // int st_update; - str->st_update = saveg_read32(); // [STRIFE] - - // short numinventory; - str->numinventory = saveg_read16(); // [STRIFE] - - // short inventorycursor; - str->inventorycursor = saveg_read16(); // [STRIFE] - - // short accuracy; - str->accuracy = saveg_read16(); // [STRIFE] - - // short stamina; - str->stamina = saveg_read16(); // [STRIFE] - - // boolean cards[NUMCARDS]; - for (i=0; icards[i] = saveg_read32(); - } - - // boolean backpack; - str->backpack = saveg_read32(); - - // int attackdown; - str->attackdown = saveg_read32(); - - // int usedown; - str->usedown = saveg_read32(); - - // int inventorydown; - str->inventorydown = saveg_read32(); // [STRIFE] - - // int frags[MAXPLAYERS]; - for (i=0; ifrags[i] = saveg_read32(); - } - - // weapontype_t readyweapon; - str->readyweapon = saveg_read_enum(); - - // weapontype_t pendingweapon; - str->pendingweapon = saveg_read_enum(); - - // boolean weaponowned[NUMWEAPONS]; - for (i=0; iweaponowned[i] = saveg_read32(); - } - - // int ammo[NUMAMMO]; - for (i=0; iammo[i] = saveg_read32(); - } - - // int maxammo[NUMAMMO]; - for (i=0; imaxammo[i] = saveg_read32(); - } - - // int cheats; - str->cheats = saveg_read32(); - - // int refire; - str->refire = saveg_read32(); - - // short killcount; - str->killcount = saveg_read16(); // [STRIFE] 32 -> 16 - - // haleyjd 08/30/10 [STRIFE] No itemcount. - // int itemcount; - //str->itemcount = saveg_read32(); - - // haleyjd 08/30/10 [STRIFE] No secretcount. - // int secretcount; - //str->secretcount = saveg_read32(); - - // char* message; - str->message = saveg_readp(); - - // int damagecount; - str->damagecount = saveg_read32(); - - // int bonuscount; - str->bonuscount = saveg_read32(); - - // mobj_t* attacker; - str->attacker = saveg_readp(); - - // int extralight; - str->extralight = saveg_read32(); - - // int fixedcolormap; - str->fixedcolormap = saveg_read32(); - - // int colormap; - [STRIFE] no such field - //str->colormap = saveg_read32(); - - // short allegiance; - str->allegiance = saveg_read16(); // [STRIFE] - - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; ipsprites[i]); - } - - // int mapstate[40]; - for(i = 0; i < 40; ++i) // [STRIFE] - { - str->mapstate[i] = saveg_read32(); - } - - // haleyjd 08/30/10: [STRIFE] No intermission, no didsecret. - // boolean didsecret; - //str->didsecret = saveg_read32(); -} - -static void saveg_write_player_t(player_t *str) -{ - int i; - - // mobj_t* mo; - saveg_writep(str->mo); - - // playerstate_t playerstate; - saveg_write_enum(str->playerstate); - - // ticcmd_t cmd; - saveg_write_ticcmd_t(&str->cmd); - - // fixed_t viewz; - saveg_write32(str->viewz); - - // fixed_t viewheight; - saveg_write32(str->viewheight); - - // fixed_t deltaviewheight; - saveg_write32(str->deltaviewheight); - - // fixed_t bob; - saveg_write32(str->bob); - - // int health; - saveg_write32(str->health); - - // int armorpoints; - saveg_write16(str->armorpoints); // [STRIFE] 32 -> 16 - - // int armortype; - saveg_write16(str->armortype); // [STRIFE] 32 -> 16 - - // int powers[NUMPOWERS]; - for (i=0; ipowers[i]); - } - - // int sigiltype; - saveg_write32(str->sigiltype); // [STRIFE] - - // int nukagecount; - saveg_write32(str->nukagecount); // [STRIFE] - - // int questflags; - saveg_write32(str->questflags); // [STRIFE] - - // int pitch; - saveg_write32(str->pitch); // [STRIFE] - - // int centerview; - saveg_write32(str->centerview); // [STRIFE] - - // inventory_t inventory[NUMINVENTORY]; - for(i = 0; i < NUMINVENTORY; ++i) // [STRIFE] - { - saveg_write_inventory_t(&str->inventory[i]); - } - - // int st_update; - saveg_write32(str->st_update); // [STRIFE] - - // short numinventory; - saveg_write16(str->numinventory); // [STRIFE] - - // short inventorycursor; - saveg_write16(str->inventorycursor); // [STRIFE] - - // short accuracy; - saveg_write16(str->accuracy); // [STRIFE] - - // short stamina; - saveg_write16(str->stamina); // [STRIFE] - - // boolean cards[NUMCARDS]; - for (i=0; icards[i]); - } - - // boolean backpack; - saveg_write32(str->backpack); - - // int attackdown; - saveg_write32(str->attackdown); - - // int usedown; - saveg_write32(str->usedown); - - // int inventorydown; - saveg_write32(str->inventorydown); // [STRIFE] - - // int frags[MAXPLAYERS]; - for (i=0; ifrags[i]); - } - - // weapontype_t readyweapon; - saveg_write_enum(str->readyweapon); - - // weapontype_t pendingweapon; - saveg_write_enum(str->pendingweapon); - - // boolean weaponowned[NUMWEAPONS]; - for (i=0; iweaponowned[i]); - } - - // int ammo[NUMAMMO]; - for (i=0; iammo[i]); - } - - // int maxammo[NUMAMMO]; - for (i=0; imaxammo[i]); - } - - - // int cheats; - saveg_write32(str->cheats); - - // int refire; - saveg_write32(str->refire); - - // short killcount; - saveg_write16(str->killcount); // [STRIFE] 32 -> 16 - - // haleyjd 08/30/10 [STRIFE] No itemcount - // int itemcount; - //saveg_write32(str->itemcount); - - // haleyjd 08/30/10 [STRIFE] No secretcount - // int secretcount; - //saveg_write32(str->secretcount); - - // char* message; - saveg_writep(str->message); - - // int damagecount; - saveg_write32(str->damagecount); - - // int bonuscount; - saveg_write32(str->bonuscount); - - // mobj_t* attacker; - saveg_writep(str->attacker); - - // int extralight; - saveg_write32(str->extralight); - - // int fixedcolormap; - saveg_write32(str->fixedcolormap); - - // int colormap; [STRIFE] no such field - //saveg_write32(str->colormap); - - // short allegiance; - saveg_write16(str->allegiance); // [STRIFE] - - // pspdef_t psprites[NUMPSPRITES]; - for (i=0; ipsprites[i]); - } - - // int mapstate[40]; - for(i = 0; i < 40; ++i) // [STRIFE] - { - saveg_write32(str->mapstate[i]); - } - - // haleyjd 08/30/10: [STRIFE] No intermission, no secret. - // boolean didsecret; - //saveg_write32(str->didsecret); -} - - -// -// ceiling_t -// - -static void saveg_read_ceiling_t(ceiling_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // ceiling_e type; - str->type = saveg_read_enum(); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // fixed_t bottomheight; - str->bottomheight = saveg_read32(); - - // fixed_t topheight; - str->topheight = saveg_read32(); - - // fixed_t speed; - str->speed = saveg_read32(); - - // boolean crush; - str->crush = saveg_read32(); - - // int direction; - str->direction = saveg_read32(); - - // int tag; - str->tag = saveg_read32(); - - // int olddirection; - str->olddirection = saveg_read32(); -} - -static void saveg_write_ceiling_t(ceiling_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // ceiling_e type; - saveg_write_enum(str->type); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // fixed_t bottomheight; - saveg_write32(str->bottomheight); - - // fixed_t topheight; - saveg_write32(str->topheight); - - // fixed_t speed; - saveg_write32(str->speed); - - // boolean crush; - saveg_write32(str->crush); - - // int direction; - saveg_write32(str->direction); - - // int tag; - saveg_write32(str->tag); - - // int olddirection; - saveg_write32(str->olddirection); -} - -// -// vldoor_t -// -// haleyjd 09/28/10: [STRIFE] Modified for Strife binary vldoor_t structure. -// - -static void saveg_read_vldoor_t(vldoor_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // vldoor_e type; - str->type = saveg_read_enum(); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // fixed_t topheight; - str->topheight = saveg_read32(); - - // fixed_t speed; - str->speed = saveg_read32(); - - // int direction; - str->direction = saveg_read32(); - - // int topwait; - str->topwait = saveg_read32(); - - // int topcountdown; - str->topcountdown = saveg_read32(); - - // villsa [STRIFE] new field - sound to play when opening - //int opensound; - str->opensound = saveg_read32(); - - // villsa [STRIFE] new field - sound to play when closing - //int closesound; - str->closesound = saveg_read32(); -} - -static void saveg_write_vldoor_t(vldoor_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // vldoor_e type; - saveg_write_enum(str->type); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // fixed_t topheight; - saveg_write32(str->topheight); - - // fixed_t speed; - saveg_write32(str->speed); - - // int direction; - saveg_write32(str->direction); - - // int topwait; - saveg_write32(str->topwait); - - // int topcountdown; - saveg_write32(str->topcountdown); - - // villsa [STRIFE] new field - sound to play when opening - //int opensound; - saveg_write32(str->opensound); - - // villsa [STRIFE] new field - sound to play when closing - //int closesound; - saveg_write32(str->closesound); -} - -// -// slidedoor_t [STRIFE]: new thinker type -// - -static void saveg_read_slidedoor_t(slidedoor_t *str) -{ - int sector; - int line; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sdt_e type; - str->type = saveg_read_enum(); - - // line_t *line1; - line = saveg_read32(); - str->line1 = &lines[line]; - - // line_t *line2; - line = saveg_read32(); - str->line2 = &lines[line]; - - // int frame; - str->frame = saveg_read32(); - - // int whichDoorIndex; - str->whichDoorIndex = saveg_read32(); - - // int timer; - str->timer = saveg_read32(); - - // sector_t *frontsector; - sector = saveg_read32(); - str->frontsector = §ors[sector]; - - // sd_e status; - str->status = saveg_read_enum(); -} - -static void saveg_write_slidedoor_t(slidedoor_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sdt_e type; - saveg_write_enum(str->type); - - // line_t *line1; - saveg_write32(str->line1 - lines); - - // line_t *line2; - saveg_write32(str->line2 - lines); - - // int frame; - saveg_write32(str->frame); - - // int whichDoorIndex; - saveg_write32(str->whichDoorIndex); - - // int timer; - saveg_write32(str->timer); - - // sector_t *frontsector; - saveg_write32(str->frontsector - sectors); - - // sd_e status; - saveg_write_enum(str->status); -} - -// -// floormove_t -// - -static void saveg_read_floormove_t(floormove_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // floor_e type; - str->type = saveg_read_enum(); - - // boolean crush; - str->crush = saveg_read32(); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // int direction; - str->direction = saveg_read32(); - - // int newspecial; - str->newspecial = saveg_read32(); - - // short texture; - str->texture = saveg_read16(); - - // fixed_t floordestheight; - str->floordestheight = saveg_read32(); - - // fixed_t speed; - str->speed = saveg_read32(); -} - -static void saveg_write_floormove_t(floormove_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // floor_e type; - saveg_write_enum(str->type); - - // boolean crush; - saveg_write32(str->crush); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // int direction; - saveg_write32(str->direction); - - // int newspecial; - saveg_write32(str->newspecial); - - // short texture; - saveg_write16(str->texture); - - // fixed_t floordestheight; - saveg_write32(str->floordestheight); - - // fixed_t speed; - saveg_write32(str->speed); -} - -// -// plat_t -// - -static void saveg_read_plat_t(plat_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // fixed_t speed; - str->speed = saveg_read32(); - - // fixed_t low; - str->low = saveg_read32(); - - // fixed_t high; - str->high = saveg_read32(); - - // int wait; - str->wait = saveg_read32(); - - // int count; - str->count = saveg_read32(); - - // plat_e status; - str->status = saveg_read_enum(); - - // plat_e oldstatus; - str->oldstatus = saveg_read_enum(); - - // boolean crush; - str->crush = saveg_read32(); - - // int tag; - str->tag = saveg_read32(); - - // plattype_e type; - str->type = saveg_read_enum(); -} - -static void saveg_write_plat_t(plat_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // fixed_t speed; - saveg_write32(str->speed); - - // fixed_t low; - saveg_write32(str->low); - - // fixed_t high; - saveg_write32(str->high); - - // int wait; - saveg_write32(str->wait); - - // int count; - saveg_write32(str->count); - - // plat_e status; - saveg_write_enum(str->status); - - // plat_e oldstatus; - saveg_write_enum(str->oldstatus); - - // boolean crush; - saveg_write32(str->crush); - - // int tag; - saveg_write32(str->tag); - - // plattype_e type; - saveg_write_enum(str->type); -} - -// -// lightflash_t -// - -static void saveg_read_lightflash_t(lightflash_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // int count; - str->count = saveg_read32(); - - // int maxlight; - str->maxlight = saveg_read32(); - - // int minlight; - str->minlight = saveg_read32(); - - // int maxtime; - str->maxtime = saveg_read32(); - - // int mintime; - str->mintime = saveg_read32(); -} - -static void saveg_write_lightflash_t(lightflash_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // int count; - saveg_write32(str->count); - - // int maxlight; - saveg_write32(str->maxlight); - - // int minlight; - saveg_write32(str->minlight); - - // int maxtime; - saveg_write32(str->maxtime); - - // int mintime; - saveg_write32(str->mintime); -} - -// -// strobe_t -// - -static void saveg_read_strobe_t(strobe_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // int count; - str->count = saveg_read32(); - - // int minlight; - str->minlight = saveg_read32(); - - // int maxlight; - str->maxlight = saveg_read32(); - - // int darktime; - str->darktime = saveg_read32(); - - // int brighttime; - str->brighttime = saveg_read32(); -} - -static void saveg_write_strobe_t(strobe_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // int count; - saveg_write32(str->count); - - // int minlight; - saveg_write32(str->minlight); - - // int maxlight; - saveg_write32(str->maxlight); - - // int darktime; - saveg_write32(str->darktime); - - // int brighttime; - saveg_write32(str->brighttime); -} - -// -// glow_t -// - -static void saveg_read_glow_t(glow_t *str) -{ - int sector; - - // thinker_t thinker; - saveg_read_thinker_t(&str->thinker); - - // sector_t* sector; - sector = saveg_read32(); - str->sector = §ors[sector]; - - // int minlight; - str->minlight = saveg_read32(); - - // int maxlight; - str->maxlight = saveg_read32(); - - // int direction; - str->direction = saveg_read32(); -} - -static void saveg_write_glow_t(glow_t *str) -{ - // thinker_t thinker; - saveg_write_thinker_t(&str->thinker); - - // sector_t* sector; - saveg_write32(str->sector - sectors); - - // int minlight; - saveg_write32(str->minlight); - - // int maxlight; - saveg_write32(str->maxlight); - - // int direction; - saveg_write32(str->direction); -} - -// -// Write the header for a savegame -// -// haleyjd 09/28/10: [STRIFE] numerous modifications. -// - -void P_WriteSaveGameHeader(char *description) -{ - char name[VERSIONSIZE]; - int i; - - /* - [STRIFE] This is in the "NAME" file in a Strife save directory. - for (i=0; description[i] != '\0'; ++i) - saveg_write8(description[i]); - for (; i> 16) & 0xff); - saveg_write8((leveltime >> 8) & 0xff); - saveg_write8(leveltime & 0xff); -} - -// -// Read the header for a savegame -// - -boolean P_ReadSaveGameHeader(void) -{ - int i; - byte a, b, c; - char vcheck[VERSIONSIZE]; - char read_vcheck[VERSIONSIZE]; - - // skip the description field - /* - for (i=0; ifloorheight >> FRACBITS); - saveg_write16(sec->ceilingheight >> FRACBITS); - saveg_write16(sec->floorpic); - //saveg_write16(sec->ceilingpic); [STRIFE] not saved. - saveg_write16(sec->lightlevel); - saveg_write16(sec->special); // needed? - //saveg_write16(sec->tag); // needed? [STRIFE] not saved. - } - - - // do lines - for (i=0, li = lines ; iflags); - saveg_write16(li->special); - //saveg_write16(li->tag); [STRIFE] not saved. - for (j=0 ; j<2 ; j++) - { - if (li->sidenum[j] == -1) - continue; - - si = &sides[li->sidenum[j]]; - - // [STRIFE] offsets not saved. - //saveg_write16(si->textureoffset >> FRACBITS); - //saveg_write16(si->rowoffset >> FRACBITS); - saveg_write16(si->toptexture); - saveg_write16(si->bottomtexture); - saveg_write16(si->midtexture); - } - } -} - - - -// -// P_UnArchiveWorld -// -void P_UnArchiveWorld (void) -{ - int i; - int j; - sector_t* sec; - line_t* li; - side_t* si; - - // do sectors - for (i=0, sec = sectors ; ifloorheight = saveg_read16() << FRACBITS; - sec->ceilingheight = saveg_read16() << FRACBITS; - sec->floorpic = saveg_read16(); - //sec->ceilingpic = saveg_read16(); [STRIFE] not saved - sec->lightlevel = saveg_read16(); - sec->special = saveg_read16(); // needed? - //sec->tag = saveg_read16(); // needed? [STRIFE] not saved - sec->specialdata = 0; - sec->soundtarget = 0; - } - - // do lines - for (i=0, li = lines ; iflags = saveg_read16(); - li->special = saveg_read16(); - //li->tag = saveg_read16(); [STRIFE] not saved - for (j=0 ; j<2 ; j++) - { - if (li->sidenum[j] == -1) - continue; - si = &sides[li->sidenum[j]]; - // [STRIFE] offsets not saved. - //si->textureoffset = saveg_read16() << FRACBITS; - //si->rowoffset = saveg_read16() << FRACBITS; - si->toptexture = saveg_read16(); - si->bottomtexture = saveg_read16(); - si->midtexture = saveg_read16(); - } - } -} - - - - - -// -// Thinkers -// -typedef enum -{ - tc_end, - tc_mobj - -} thinkerclass_t; - - -// -// P_ArchiveThinkers -// -// [STRIFE] Verified unmodified. -// -void P_ArchiveThinkers (void) -{ - thinker_t* th; - - // save off the current thinkers - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - saveg_write8(tc_mobj); - saveg_write_pad(); - saveg_write_mobj_t((mobj_t *) th); - - continue; - } - - // haleyjd: This may seem mysterious but in the DOOM prebeta, - // different types of things used different thinker functions. - // Those would have all been handled here and this message is - // probably a relic of that old system, not to mention the odd - // name of this function, and use of an enumeration with only - // two values in it. - - // I_Error ("P_ArchiveThinkers: Unknown thinker function"); - } - - // add a terminating marker - saveg_write8(tc_end); -} - - - -// -// P_UnArchiveThinkers -// -void P_UnArchiveThinkers (void) -{ - byte tclass; - thinker_t* currentthinker; - thinker_t* next; - mobj_t* mobj; - - // remove all the current thinkers - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) - { - next = currentthinker->next; - - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - P_RemoveMobj ((mobj_t *)currentthinker); - else - Z_Free (currentthinker); - - currentthinker = next; - } - P_InitThinkers (); - - // read in saved thinkers - while (1) - { - tclass = saveg_read8(); - switch (tclass) - { - case tc_end: - return; // end of list - - case tc_mobj: - saveg_read_pad(); - mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); - saveg_read_mobj_t(mobj); - - // haleyjd 09/29/10: Strife sets the targets of non-allied creatures - // who had a non-NULL target at save time to players[0].mo so that - // they won't fall back asleep. - // - // BUG: As the player may not have been spawned yet, we could be - // setting monsters' targets to the mobj which was spawned by - // P_SetupLevel and then removed just above. Due to a subtle glitch - // in the DOOM engine whereby all things removed in this function - // are leaked until the next time P_SetupLevel is called, this is a - // safe operation - the call to P_InitThinkers above stops any of - // the objects removed, including the player's previous body, from - // being passed to Z_Free. One glitch relying on another! - - if(mobj->target != NULL && (mobj->flags & MF_ALLY) != MF_ALLY) - mobj->target = players[0].mo; - else - mobj->target = NULL; - - // WARNING! Strife does not seem to set tracer! I am leaving it be - // for now because so far no crashes have been observed, and failing - // to set this here will almost certainly crash Choco. - mobj->tracer = NULL; - P_SetThingPosition (mobj); - mobj->info = &mobjinfo[mobj->type]; - // [STRIFE]: doesn't set these - //mobj->floorz = mobj->subsector->sector->floorheight; - //mobj->ceilingz = mobj->subsector->sector->ceilingheight; - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; - P_AddThinker (&mobj->thinker); - break; - - default: - I_Error ("Unknown tclass %i in savegame",tclass); - } - } -} - - -// -// P_ArchiveSpecials -// -enum -{ - tc_ceiling, - tc_door, - tc_floor, - tc_plat, - tc_flash, - tc_strobe, - tc_glow, - tc_slidingdoor, // [STRIFE] - tc_endspecials - -} specials_e; - - - -// -// Things to handle: -// -// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list -// T_VerticalDoor, (vldoor_t: sector_t * swizzle), -// T_SlidingDoor, (slidedoor_t: sector_t *, line_t * x 2 swizzle) [STRIFE] -// T_MoveFloor, (floormove_t: sector_t * swizzle), -// T_LightFlash, (lightflash_t: sector_t * swizzle), -// T_StrobeFlash, (strobe_t: sector_t *), -// T_Glow, (glow_t: sector_t *), -// T_PlatRaise, (plat_t: sector_t *), - active list -// -void P_ArchiveSpecials (void) -{ - thinker_t* th; - int i; - - // save off the current thinkers - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - { - if (th->function.acv == (actionf_v)NULL) - { - for (i = 0; i < MAXCEILINGS;i++) - if (activeceilings[i] == (ceiling_t *)th) - break; - - if (ifunction.acp1 == (actionf_p1)T_MoveCeiling) - { - saveg_write8(tc_ceiling); - saveg_write_pad(); - saveg_write_ceiling_t((ceiling_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_VerticalDoor) - { - saveg_write8(tc_door); - saveg_write_pad(); - saveg_write_vldoor_t((vldoor_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_SlidingDoor) - { - saveg_write8(tc_slidingdoor); - saveg_write_pad(); - saveg_write_slidedoor_t((slidedoor_t *)th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_MoveFloor) - { - saveg_write8(tc_floor); - saveg_write_pad(); - saveg_write_floormove_t((floormove_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_PlatRaise) - { - saveg_write8(tc_plat); - saveg_write_pad(); - saveg_write_plat_t((plat_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_LightFlash) - { - saveg_write8(tc_flash); - saveg_write_pad(); - saveg_write_lightflash_t((lightflash_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_StrobeFlash) - { - saveg_write8(tc_strobe); - saveg_write_pad(); - saveg_write_strobe_t((strobe_t *) th); - continue; - } - - if (th->function.acp1 == (actionf_p1)T_Glow) - { - saveg_write8(tc_glow); - saveg_write_pad(); - saveg_write_glow_t((glow_t *) th); - continue; - } - } - - // add a terminating marker - saveg_write8(tc_endspecials); -} - - -// -// P_UnArchiveSpecials -// -void P_UnArchiveSpecials (void) -{ - byte tclass; - ceiling_t* ceiling; - vldoor_t* door; - slidedoor_t* slidedoor; // haleyjd [STRIFE] - floormove_t* floor; - plat_t* plat; - lightflash_t* flash; - strobe_t* strobe; - glow_t* glow; - - - // read in saved thinkers - while (1) - { - tclass = saveg_read8(); - - switch (tclass) - { - case tc_endspecials: - return; // end of list - - case tc_ceiling: - saveg_read_pad(); - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL); - saveg_read_ceiling_t(ceiling); - ceiling->sector->specialdata = ceiling; - - if (ceiling->thinker.function.acp1) - ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; - - P_AddThinker (&ceiling->thinker); - P_AddActiveCeiling(ceiling); - break; - - case tc_door: - saveg_read_pad(); - door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL); - saveg_read_vldoor_t(door); - door->sector->specialdata = door; - door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor; - P_AddThinker (&door->thinker); - break; - - case tc_slidingdoor: - // haleyjd 09/29/10: [STRIFE] New thinker type for sliding doors - saveg_read_pad(); - slidedoor = Z_Malloc(sizeof(*slidedoor), PU_LEVEL, NULL); - saveg_read_slidedoor_t(slidedoor); - slidedoor->frontsector->specialdata = slidedoor; - slidedoor->thinker.function.acp1 = (actionf_p1)T_SlidingDoor; - P_AddThinker(&slidedoor->thinker); - break; - - case tc_floor: - saveg_read_pad(); - floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL); - saveg_read_floormove_t(floor); - floor->sector->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; - P_AddThinker (&floor->thinker); - break; - - case tc_plat: - saveg_read_pad(); - plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL); - saveg_read_plat_t(plat); - plat->sector->specialdata = plat; - - if (plat->thinker.function.acp1) - plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise; - - P_AddThinker (&plat->thinker); - P_AddActivePlat(plat); - break; - - case tc_flash: - saveg_read_pad(); - flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL); - saveg_read_lightflash_t(flash); - flash->thinker.function.acp1 = (actionf_p1)T_LightFlash; - P_AddThinker (&flash->thinker); - break; - - case tc_strobe: - saveg_read_pad(); - strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL); - saveg_read_strobe_t(strobe); - strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; - P_AddThinker (&strobe->thinker); - break; - - case tc_glow: - saveg_read_pad(); - glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL); - saveg_read_glow_t(glow); - glow->thinker.function.acp1 = (actionf_p1)T_Glow; - P_AddThinker (&glow->thinker); - break; - - default: - I_Error ("P_UnarchiveSpecials:Unknown tclass %i " - "in savegame",tclass); - } - } -} - diff --git a/games/NXDoom/src/strife/p_saveg.h b/games/NXDoom/src/strife/p_saveg.h deleted file mode 100644 index d36f3b0da91..00000000000 --- a/games/NXDoom/src/strife/p_saveg.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Savegame I/O, archiving, persistence. -// - - -#ifndef __P_SAVEG__ -#define __P_SAVEG__ - -#include - -// maximum size of a savegame description - -#define SAVESTRINGSIZE 24 - -// temporary filename to use while saving. - -char *P_TempSaveGameFile(void); - -// filename to use for a savegame slot - -char *P_SaveGameFile(int slot); - -// Savegame file header read/write functions - -boolean P_ReadSaveGameHeader(void); -void P_WriteSaveGameHeader(char *description); - -// Savegame end-of-file read/write functions - -boolean P_ReadSaveGameEOF(void); -void P_WriteSaveGameEOF(void); - -// Persistent storage/archiving. -// These are the load / save game routines. -void P_ArchivePlayers (void); -void P_UnArchivePlayers (boolean userload); -void P_ArchiveWorld (void); -void P_UnArchiveWorld (void); -void P_ArchiveThinkers (void); -void P_UnArchiveThinkers (void); -void P_ArchiveSpecials (void); -void P_UnArchiveSpecials (void); - -extern FILE *save_stream; -extern boolean savegame_error; - - -#endif diff --git a/games/NXDoom/src/strife/p_setup.c b/games/NXDoom/src/strife/p_setup.c deleted file mode 100644 index d6c3057b56c..00000000000 --- a/games/NXDoom/src/strife/p_setup.c +++ /dev/null @@ -1,808 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Do all the WAD I/O, get map description, -// set up initial state and misc. LUTs. -// - - - -#include - -#include "z_zone.h" - -#include "deh_main.h" -#include "i_swap.h" -#include "m_argv.h" -#include "m_bbox.h" - -#include "g_game.h" - -#include "i_system.h" -#include "w_wad.h" - -#include "doomdef.h" -#include "p_local.h" -#include "p_rejectpad.h" - -#include "s_sound.h" - -#include "doomstat.h" - - -void P_SpawnMapThing (mapthing_t* mthing); - - -// -// MAP related Lookup tables. -// Store VERTEXES, LINEDEFS, SIDEDEFS, etc. -// -int numvertexes; -vertex_t* vertexes; - -int numsegs; -seg_t* segs; - -int numsectors; -sector_t* sectors; - -int numsubsectors; -subsector_t* subsectors; - -int numnodes; -node_t* nodes; - -int numlines; -line_t* lines; - -int numsides; -side_t* sides; - -static int totallines; - -// BLOCKMAP -// Created from axis aligned bounding box -// of the map, a rectangular array of -// blocks of size ... -// Used to speed up collision detection -// by spatial subdivision in 2D. -// -// Blockmap size. -int bmapwidth; -int bmapheight; // size in mapblocks -short* blockmap; // int for larger maps -// offsets in blockmap are from here -short* blockmaplump; -// origin of block map -fixed_t bmaporgx; -fixed_t bmaporgy; -// for thing chains -mobj_t** blocklinks; - - -// REJECT -// For fast sight rejection. -// Speeds up enemy AI by skipping detailed -// LineOf Sight calculation. -// Without special effect, this could be -// used as a PVS lookup as well. -// -byte* rejectmatrix; - - -// Maintain single and multi player starting spots. -#define MAX_DEATHMATCH_STARTS 10 - -mapthing_t deathmatchstarts[MAX_DEATHMATCH_STARTS]; -mapthing_t* deathmatch_p; -mapthing_t playerstarts[MAXPLAYERS]; - -// haleyjd 08/24/10: [STRIFE] rift spots for player spawning -mapthing_t riftSpots[MAXRIFTSPOTS]; - - - - -// -// P_LoadVertexes -// -void P_LoadVertexes (int lump) -{ - byte* data; - int i; - mapvertex_t* ml; - vertex_t* li; - - // Determine number of lumps: - // total lump length / vertex record length. - numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t); - - // Allocate zone memory for buffer. - vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0); - - // Load data into cache. - data = W_CacheLumpNum (lump, PU_STATIC); - - ml = (mapvertex_t *)data; - li = vertexes; - - // Copy and convert vertex coordinates, - // internal representation as fixed. - for (i=0 ; ix = SHORT(ml->x)<y = SHORT(ml->y)<v1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; - - li->angle = (SHORT(ml->angle))<<16; - li->offset = (SHORT(ml->offset))<<16; - linedef = SHORT(ml->linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - side = SHORT(ml->side); - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; - - if (ldef-> flags & ML_TWOSIDED) - { - sidenum = ldef->sidenum[side ^ 1]; - - // If the sidenum is out of range, this may be a "glass hack" - // impassible window. Point at side #0 (this may not be - // the correct Vanilla behavior; however, it seems to work for - // OTTAWAU.WAD, which is the one place I've seen this trick - // used). - - if (sidenum < 0 || sidenum >= numsides) - { - sidenum = 0; - } - - li->backsector = sides[sidenum].sector; - } - else - { - li->backsector = 0; - } - } - - W_ReleaseLumpNum(lump); -} - - -// -// P_LoadSubsectors -// -void P_LoadSubsectors (int lump) -{ - byte* data; - int i; - mapsubsector_t* ms; - subsector_t* ss; - - numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t); - subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0); - data = W_CacheLumpNum (lump,PU_STATIC); - - ms = (mapsubsector_t *)data; - memset (subsectors,0, numsubsectors*sizeof(subsector_t)); - ss = subsectors; - - for (i=0 ; inumlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); - } - - W_ReleaseLumpNum(lump); -} - - - -// -// P_LoadSectors -// -void P_LoadSectors (int lump) -{ - byte* data; - int i; - mapsector_t* ms; - sector_t* ss; - - numsectors = W_LumpLength (lump) / sizeof(mapsector_t); - sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0); - memset (sectors, 0, numsectors*sizeof(sector_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - ms = (mapsector_t *)data; - ss = sectors; - for (i=0 ; ifloorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = R_FlatNumForName(ms->floorpic); - ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); - ss->lightlevel = SHORT(ms->lightlevel); - ss->special = SHORT(ms->special); - ss->tag = SHORT(ms->tag); - ss->thinglist = NULL; - } - - W_ReleaseLumpNum(lump); -} - - -// -// P_LoadNodes -// -void P_LoadNodes (int lump) -{ - byte* data; - int i; - int j; - int k; - mapnode_t* mn; - node_t* no; - - numnodes = W_LumpLength (lump) / sizeof(mapnode_t); - nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0); - data = W_CacheLumpNum (lump,PU_STATIC); - - mn = (mapnode_t *)data; - no = nodes; - - for (i=0 ; ix = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); - for (k=0 ; k<4 ; k++) - no->bbox[j][k] = SHORT(mn->bbox[j][k])<type)) - { - case 68: // Arachnotron - case 64: // Archvile - case 88: // Boss Brain - case 89: // Boss Shooter - case 69: // Hell Knight - case 67: // Mancubus - case 71: // Pain Elemental - case 65: // Former Human Commando - case 66: // Revenant - case 84: // Wolf SS - spawn = false; - break; - } - } - if (spawn == false) - break; - */ - - // Do spawn all other stuff. - spawnthing.x = SHORT(mt->x); - spawnthing.y = SHORT(mt->y); - spawnthing.angle = SHORT(mt->angle); - spawnthing.type = SHORT(mt->type); - spawnthing.options = SHORT(mt->options); - - // haleyjd 08/24/2010: Special Strife checks - if(spawnthing.type >= 118 && spawnthing.type < 128) - { - // initialize riftSpots - int riftSpotNum = spawnthing.type - 118; - riftSpots[riftSpotNum] = spawnthing; - riftSpots[riftSpotNum].type = 1; - } - else if(spawnthing.type >= 9001 && spawnthing.type < 9011) - { - // STRIFE-TODO: mystery array of 90xx objects - } - else - P_SpawnMapThing(&spawnthing); - } - - W_ReleaseLumpNum(lump); -} - - -// -// P_LoadLineDefs -// Also counts secret lines for intermissions. -// -void P_LoadLineDefs (int lump) -{ - byte* data; - int i; - maplinedef_t* mld; - line_t* ld; - vertex_t* v1; - vertex_t* v2; - - numlines = W_LumpLength (lump) / sizeof(maplinedef_t); - lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0); - memset (lines, 0, numlines*sizeof(line_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - mld = (maplinedef_t *)data; - ld = lines; - for (i=0 ; iflags = SHORT(mld->flags); - ld->special = SHORT(mld->special); - ld->tag = SHORT(mld->tag); - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else - { - if (FixedDiv (ld->dy , ld->dx) > 0) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - } - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - - if (ld->sidenum[0] != -1) - ld->frontsector = sides[ld->sidenum[0]].sector; - else - ld->frontsector = 0; - - if (ld->sidenum[1] != -1) - ld->backsector = sides[ld->sidenum[1]].sector; - else - ld->backsector = 0; - } - - W_ReleaseLumpNum(lump); -} - - -// -// P_LoadSideDefs -// -void P_LoadSideDefs (int lump) -{ - byte* data; - int i; - mapsidedef_t* msd; - side_t* sd; - - numsides = W_LumpLength (lump) / sizeof(mapsidedef_t); - sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0); - memset (sides, 0, numsides*sizeof(side_t)); - data = W_CacheLumpNum (lump,PU_STATIC); - - msd = (mapsidedef_t *)data; - sd = sides; - for (i=0 ; itextureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<toptexture = R_TextureNumForName(msd->toptexture); - sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); - sd->midtexture = R_TextureNumForName(msd->midtexture); - sd->sector = §ors[SHORT(msd->sector)]; - } - - W_ReleaseLumpNum(lump); -} - - -// -// P_LoadBlockMap -// -void P_LoadBlockMap (int lump) -{ - int i; - int count; - int lumplen; - - lumplen = W_LumpLength(lump); - count = lumplen / 2; - - blockmaplump = Z_Malloc(lumplen, PU_LEVEL, NULL); - W_ReadLump(lump, blockmaplump); - blockmap = blockmaplump + 4; - - // Swap all short integers to native byte ordering. - - for (i=0; ifirstline]; - ss->sector = seg->sidedef->sector; - } - - // count number of lines in each sector - li = lines; - totallines = 0; - for (i=0 ; ifrontsector->linecount++; - - if (li->backsector && li->backsector != li->frontsector) - { - li->backsector->linecount++; - totallines++; - } - } - - // build line tables for each sector - linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0); - - for (i=0; ifrontsector != NULL) - { - sector = li->frontsector; - - sector->lines[sector->linecount] = li; - ++sector->linecount; - } - - if (li->backsector != NULL && li->frontsector != li->backsector) - { - sector = li->backsector; - - sector->lines[sector->linecount] = li; - ++sector->linecount; - } - } - - // Generate bounding boxes for sectors - - sector = sectors; - for (i=0 ; ilinecount; j++) - { - li = sector->lines[j]; - - M_AddToBox (bbox, li->v1->x, li->v1->y); - M_AddToBox (bbox, li->v2->x, li->v2->y); - } - - // set the degenmobj_t to the middle of the bounding box - sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2; - sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2; - - // adjust bounding box to map blocks - block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; - block = block >= bmapheight ? bmapheight-1 : block; - sector->blockbox[BOXTOP]=block; - - block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXBOTTOM]=block; - - block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; - block = block >= bmapwidth ? bmapwidth-1 : block; - sector->blockbox[BOXRIGHT]=block; - - block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; - block = block < 0 ? 0 : block; - sector->blockbox[BOXLEFT]=block; - } - -} - - -static void P_LoadReject(int lumpnum) -{ - int minlength; - int lumplen; - - // Calculate the size that the REJECT lump *should* be. - - minlength = (numsectors * numsectors + 7) / 8; - - // If the lump meets the minimum length, it can be loaded directly. - // Otherwise, we need to allocate a buffer of the correct size - // and pad it with appropriate data. - - lumplen = W_LumpLength(lumpnum); - - if (lumplen >= minlength) - { - rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); - } - else - { - rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix); - W_ReadLump(lumpnum, rejectmatrix); - - PadRejectArray(rejectmatrix + lumplen, minlength - lumplen, totallines); - } -} - -// -// P_SetupLevel -// -void -P_SetupLevel -( int map, - int playermask, - skill_t skill) -{ - int i; - char lumpname[9]; - int lumpnum; - - // haleyjd 20110205 [STRIFE]: removed totalitems and wminfo - totalkills = totalsecret = 0; - - for (i=0 ; idx) - { - if (x==node->x) - return 2; - - if (x <= node->x) - return node->dy > 0; - - return node->dy < 0; - } - - if (!node->dy) - { - if (x==node->y) - return 2; - - if (y <= node->y) - return node->dx < 0; - - return node->dx > 0; - } - - dx = (x - node->x); - dy = (y - node->y); - - left = (node->dy>>FRACBITS) * (dx>>FRACBITS); - right = (dy>>FRACBITS) * (node->dx>>FRACBITS); - - if (right < left) - return 0; // front side - - if (left == right) - return 2; - return 1; // back side -} - - -// -// P_InterceptVector2 -// Returns the fractional intercept point -// along the first divline. -// This is only called by the addthings and addlines traversers. -// -// [STRIFE] Verified unmodified -// -fixed_t -P_InterceptVector2 -( divline_t* v2, - divline_t* v1 ) -{ - fixed_t frac; - fixed_t num; - fixed_t den; - - den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); - - if (den == 0) - return 0; - // I_Error ("P_InterceptVector: parallel"); - - num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + - FixedMul ( (v2->y - v1->y)>>8 , v1->dx); - frac = FixedDiv (num , den); - - return frac; -} - -// -// P_CrossSubsector -// Returns true -// if strace crosses the given subsector successfully. -// -// [STRIFE] Verified unmodified -// -boolean P_CrossSubsector (int num) -{ - seg_t* seg; - line_t* line; - int s1; - int s2; - int count; - subsector_t* sub; - sector_t* front; - sector_t* back; - fixed_t opentop; - fixed_t openbottom; - divline_t divl; - vertex_t* v1; - vertex_t* v2; - fixed_t frac; - fixed_t slope; - -#ifdef RANGECHECK - if (num>=numsubsectors) - I_Error ("P_CrossSubsector: ss %i with numss = %i", - num, - numsubsectors); -#endif - - sub = &subsectors[num]; - - // check lines - count = sub->numlines; - seg = &segs[sub->firstline]; - - for ( ; count ; seg++, count--) - { - line = seg->linedef; - - // allready checked other side? - if (line->validcount == validcount) - continue; - - line->validcount = validcount; - - v1 = line->v1; - v2 = line->v2; - s1 = P_DivlineSide (v1->x, v1->y, &strace); - s2 = P_DivlineSide (v2->x, v2->y, &strace); - - // line isn't crossed? - if (s1 == s2) - continue; - - divl.x = v1->x; - divl.y = v1->y; - divl.dx = v2->x - v1->x; - divl.dy = v2->y - v1->y; - s1 = P_DivlineSide (strace.x, strace.y, &divl); - s2 = P_DivlineSide (t2x, t2y, &divl); - - // line isn't crossed? - if (s1 == s2) - continue; - - // Backsector may be NULL if this is an "impassible - // glass" hack line. - - if (line->backsector == NULL) - { - return false; - } - - // stop because it is not two sided anyway - // might do this after updating validcount? - if ( !(line->flags & ML_TWOSIDED) ) - return false; - - // crosses a two sided line - front = seg->frontsector; - back = seg->backsector; - - // no wall to block sight with? - if (front->floorheight == back->floorheight - && front->ceilingheight == back->ceilingheight) - continue; - - // possible occluder - // because of ceiling height differences - if (front->ceilingheight < back->ceilingheight) - opentop = front->ceilingheight; - else - opentop = back->ceilingheight; - - // because of ceiling height differences - if (front->floorheight > back->floorheight) - openbottom = front->floorheight; - else - openbottom = back->floorheight; - - // quick test for totally closed doors - if (openbottom >= opentop) - return false; // stop - - frac = P_InterceptVector2 (&strace, &divl); - - if (front->floorheight != back->floorheight) - { - slope = FixedDiv (openbottom - sightzstart , frac); - if (slope > bottomslope) - bottomslope = slope; - } - - if (front->ceilingheight != back->ceilingheight) - { - slope = FixedDiv (opentop - sightzstart , frac); - if (slope < topslope) - topslope = slope; - } - - if (topslope <= bottomslope) - return false; // stop - } - // passed the subsector ok - return true; -} - - - -// -// P_CrossBSPNode -// Returns true -// if strace crosses the given node successfully. -// -// [STRIFE] Verified unmodified -// -boolean P_CrossBSPNode (int bspnum) -{ - node_t* bsp; - int side; - - if (bspnum & NF_SUBSECTOR) - { - if (bspnum == -1) - return P_CrossSubsector (0); - else - return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); - } - - bsp = &nodes[bspnum]; - - // decide which side the start point is on - side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp); - if (side == 2) - side = 0; // an "on" should cross both sides - - // cross the starting side - if (!P_CrossBSPNode (bsp->children[side]) ) - return false; - - // the partition plane is crossed here - if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp)) - { - // the line doesn't touch the other side - return true; - } - - // cross the ending side - return P_CrossBSPNode (bsp->children[side^1]); -} - - -// -// P_CheckSight -// Returns true -// if a straight line between t1 and t2 is unobstructed. -// Uses REJECT. -// -// [STRIFE] Verified unmodified -// -boolean -P_CheckSight -( mobj_t* t1, - mobj_t* t2 ) -{ - int s1; - int s2; - int pnum; - int bytenum; - int bitnum; - - // First check for trivial rejection. - - // Determine subsector entries in REJECT table. - s1 = (t1->subsector->sector - sectors); - s2 = (t2->subsector->sector - sectors); - pnum = s1*numsectors + s2; - bytenum = pnum>>3; - bitnum = 1 << (pnum&7); - - // Check in REJECT table. - if (rejectmatrix[bytenum]&bitnum) - { - sightcounts[0]++; - - // can't possibly be connected - return false; - } - - // An unobstructed LOS is possible. - // Now look from eyes of t1 to any part of t2. - sightcounts[1]++; - - validcount++; - - sightzstart = t1->z + t1->height - (t1->height>>2); - topslope = (t2->z+t2->height) - sightzstart; - bottomslope = (t2->z) - sightzstart; - - strace.x = t1->x; - strace.y = t1->y; - t2x = t2->x; - t2y = t2->y; - strace.dx = t2->x - t1->x; - strace.dy = t2->y - t1->y; - - // the head node is the last node output - return P_CrossBSPNode (numnodes-1); -} - - diff --git a/games/NXDoom/src/strife/p_spec.c b/games/NXDoom/src/strife/p_spec.c deleted file mode 100644 index de01eaa44d0..00000000000 --- a/games/NXDoom/src/strife/p_spec.c +++ /dev/null @@ -1,1984 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Implements special effects: -// Texture animation, height or lighting changes -// according to adjacent sectors, respective -// utility functions, etc. -// Line Tag handling. Line and Sector triggers. -// - - -#include - -#include "doomdef.h" -#include "doomstat.h" - -#include "deh_main.h" -#include "i_system.h" -#include "z_zone.h" -#include "m_argv.h" -#include "m_misc.h" -#include "m_random.h" -#include "w_wad.h" - -#include "r_local.h" -#include "p_local.h" - -#include "g_game.h" - -#include "s_sound.h" - -// State. -#include "r_state.h" - -// Data. -#include "sounds.h" - -// [STRIFE] -#include "hu_stuff.h" -#include "p_dialog.h" - - -// -// Animating textures and planes -// There is another anim_t used in wi_stuff, unrelated. -// -typedef struct -{ - boolean istexture; - int picnum; - int basepic; - int numpics; - int speed; - -} anim_t; - -// -// source animation definition -// -typedef struct -{ - int istexture; // if false, it is a flat - char endname[9]; - char startname[9]; - int speed; -} animdef_t; - - -// haleyjd 08/30/10: [STRIFE] MAXANIMS raised from 32 to 40 -#define MAXANIMS 40 - -// -// P_InitPicAnims -// - -// Floor/ceiling animation sequences, -// defined by first and last frame, -// i.e. the flat (64x64 tile) name to -// be used. -// The full animation sequence is given -// using all the flats between the start -// and end entry, in the order found in -// the WAD file. -// -// haleyjd 08/29/10: [STRIFE] Changed animdefs. -// -animdef_t animdefs[] = -{ - { false, "F_SCANR8", "F_SCANR5", 4}, - { false, "F_WATR03", "F_WATR01", 8}, - { false, "F_PWATR3", "F_PWATR1", 11}, - { false, "F_SCANR4", "F_SCANR1", 4}, - { true, "SCAN08", "SCAN05", 4}, - { true, "SWTRMG03", "SWTRMG01", 4}, - { true, "SCAN04", "SCAN01", 4}, - { true, "COMP04", "COMP01", 4}, - { true, "COMP08", "COMP05", 6}, - { true, "COMP12", "COMP09", 11}, - { true, "COMP16", "COMP13", 12}, - { true, "COMP20", "COMP17", 12}, - { true, "COMP24", "COMP21", 12}, - { true, "COMP28", "COMP25", 12}, - { true, "COMP32", "COMP29", 12}, - { true, "COMP37", "COMP33", 12}, - { true, "COMP41", "COMP38", 12}, - { true, "COMP49", "COMP42", 10}, - { true, "BRKGRY16", "BRKGRY13", 10}, - { true, "BRNSCN04", "BRNSCN01", 10}, - { true, "CONCRT12", "CONCRT09", 11}, - { true, "CONCRT25", "CONCRT22", 11}, - { true, "WALPMP02", "WALPMP01", 16}, - { true, "WALTEK17", "WALTEK16", 8}, - { true, "FORCE04", "FORCE01", 4}, - { true, "FORCE08", "FORCE05", 4}, - { true, "FAN02", "FAN01", 4}, - { false, "F_VWATR3", "P_VWATR1", 4}, - { false, "F_HWATR3", "F_HWATR1", 4}, - { false, "F_TELE2", "F_TELE1", 4}, - { false, "F_FAN2", "F_FAN1", 4}, - { false, "F_CONVY2", "F_CONVY1", 4}, - { false, "F_RDALN4", "F_RDALN1", 4}, - { -1, "", "", 0}, -}; - -anim_t anims[MAXANIMS]; -anim_t* lastanim; - -// -// Animating line specials -// -// haleyjd 08/29/10: [STRIFE] MAXLINEANIMS raised from 64 to 96 -#define MAXLINEANIMS 96 - -short numlinespecials = 0; -line_t *linespeciallist[MAXLINEANIMS]; - - - -void P_InitPicAnims (void) -{ - int i; - - - // Init animation - lastanim = anims; - for (i=0 ; animdefs[i].istexture != -1 ; i++) - { - const char *startname, *endname; - - startname = DEH_String(animdefs[i].startname); - endname = DEH_String(animdefs[i].endname); - - if (animdefs[i].istexture) - { - // different episode ? - if (R_CheckTextureNumForName(startname) == -1) - continue; - - lastanim->picnum = R_TextureNumForName(endname); - lastanim->basepic = R_TextureNumForName(startname); - } - else - { - if (W_CheckNumForName(startname) == -1) - continue; - - lastanim->picnum = R_FlatNumForName(endname); - lastanim->basepic = R_FlatNumForName(startname); - } - - lastanim->istexture = animdefs[i].istexture; - lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; - - if (lastanim->numpics < 2) - I_Error ("P_InitPicAnims: bad cycle from %s to %s", - startname, endname); - - lastanim->speed = animdefs[i].speed; - lastanim++; - } - -} - -// villsa [STRIFE] terrain type definitions -typedef struct -{ - const char *flat; - int type; - int num; -} terraintype_t; - -terraintype_t terraintypes[] = -{ - { "F_WATR03", FLOOR_WATER, -1 }, - { "F_WATR02", FLOOR_WATER, -1 }, - { "F_WATR01", FLOOR_WATER, -1 }, - { "F_VWATR3", FLOOR_WATER, -1 }, - { "F_VWATR2", FLOOR_WATER, -1 }, - { "P_VWATR1", FLOOR_WATER, -1 }, - { "F_HWATR3", FLOOR_WATER, -1 }, - { "F_HWATR2", FLOOR_WATER, -1 }, - { "F_HWATR1", FLOOR_WATER, -1 }, - { "F_PWATR3", FLOOR_SLIME, -1 }, - { "F_PWATR2", FLOOR_SLIME, -1 }, - { "F_PWATR1", FLOOR_SLIME, -1 }, - { "END", FLOOR_END, -1 }, -}; - -// -// P_GetTerrainType -// villsa [STRIFE] new function -// - -terraintype_e P_GetTerrainType(mobj_t* mobj) -{ - int i = 0; - subsector_t* ss = mobj->subsector; - - if(mobj->z <= ss->sector->floorheight && - terraintypes[0].type != FLOOR_END) - { - while(ss->sector->floorpic != terraintypes[i].num) - { - if(terraintypes[i+1].type == FLOOR_END) - return FLOOR_SOLID; - - i++; - } - - return terraintypes[i].type; - } - - return FLOOR_SOLID; -} - -// -// P_InitTerrainTypes -// villsa [STRIFE] new function -// Initialize terrain types -// - -void P_InitTerrainTypes(void) -{ - int i = 0; - - if(terraintypes[0].type != FLOOR_END) - { - while(terraintypes[i].type != FLOOR_END) - { - terraintypes[i].num = R_FlatNumForName(terraintypes[i].flat); - i++; - } - } -} - - - -// -// UTILITIES -// - - - -// -// getSide() -// Will return a side_t* -// given the number of the current sector, -// the line number, and the side (0/1) that you want. -// -side_t* -getSide -( int currentSector, - int line, - int side ) -{ - return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; -} - - -// -// getSector() -// Will return a sector_t* -// given the number of the current sector, -// the line number and the side (0/1) that you want. -// -sector_t* -getSector -( int currentSector, - int line, - int side ) -{ - return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; -} - - -// -// twoSided() -// Given the sector number and the line number, -// it will tell you whether the line is two-sided or not. -// -int -twoSided -( int sector, - int line ) -{ - return (sectors[sector].lines[line])->flags & ML_TWOSIDED; -} - - - - -// -// getNextSector() -// Return sector_t * of sector next to current. -// NULL if not two-sided line -// -sector_t* -getNextSector -( line_t* line, - sector_t* sec ) -{ - if (!(line->flags & ML_TWOSIDED)) - return NULL; - - if (line->frontsector == sec) - return line->backsector; - - return line->frontsector; -} - - - -// -// P_FindLowestFloorSurrounding() -// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -fixed_t P_FindLowestFloorSurrounding(sector_t* sec) -{ - int i; - line_t* check; - sector_t* other; - fixed_t floor = sec->floorheight; - - for (i=0 ;i < sec->linecount ; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->floorheight < floor) - floor = other->floorheight; - } - return floor; -} - - - -// -// P_FindHighestFloorSurrounding() -// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS -// -fixed_t P_FindHighestFloorSurrounding(sector_t *sec) -{ - int i; - line_t* check; - sector_t* other; - fixed_t floor = -500*FRACUNIT; - - for (i=0 ;i < sec->linecount ; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->floorheight > floor) - floor = other->floorheight; - } - return floor; -} - - - -// -// P_FindNextHighestFloor -// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS -// Note: this should be doable w/o a fixed array. - -// Thanks to entryway for the Vanilla overflow emulation. - -// 20 adjoining sectors max! -#define MAX_ADJOINING_SECTORS 20 - -fixed_t -P_FindNextHighestFloor -( sector_t* sec, - int currentheight ) -{ - int i; - int h; - int min; - line_t* check; - sector_t* other; - fixed_t height = currentheight; - fixed_t heightlist[MAX_ADJOINING_SECTORS + 2]; - - for (i=0, h=0; i < sec->linecount; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->floorheight > height) - { - // Emulation of memory (stack) overflow - if (h == MAX_ADJOINING_SECTORS + 1) - { - height = other->floorheight; - } - else if (h == MAX_ADJOINING_SECTORS + 2) - { - // Fatal overflow: game crashes at 22 sectors - I_Error("Sector with more than 22 adjoining sectors. " - "Vanilla will crash here"); - } - - heightlist[h++] = other->floorheight; - } - } - - // Find lowest height in list - if (!h) - { - return currentheight; - } - - min = heightlist[0]; - - // Range checking? - for (i = 1; i < h; i++) - { - if (heightlist[i] < min) - { - min = heightlist[i]; - } - } - - return min; -} - -// -// FIND LOWEST CEILING IN THE SURROUNDING SECTORS -// -fixed_t -P_FindLowestCeilingSurrounding(sector_t* sec) -{ - int i; - line_t* check; - sector_t* other; - fixed_t height = INT_MAX; - - for (i=0 ;i < sec->linecount ; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->ceilingheight < height) - height = other->ceilingheight; - } - return height; -} - - -// -// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS -// -fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) -{ - int i; - line_t* check; - sector_t* other; - fixed_t height = 0; - - for (i=0 ;i < sec->linecount ; i++) - { - check = sec->lines[i]; - other = getNextSector(check,sec); - - if (!other) - continue; - - if (other->ceilingheight > height) - height = other->ceilingheight; - } - return height; -} - - - -// -// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO -// -int -P_FindSectorFromLineTag -( line_t* line, - int start ) -{ - int i; - - for (i=start+1;itag) - return i; - - return -1; -} - - - - -// -// Find minimum light from an adjacent sector -// -int -P_FindMinSurroundingLight -( sector_t* sector, - int max ) -{ - int i; - int min; - line_t* line; - sector_t* check; - - min = max; - for (i=0 ; i < sector->linecount ; i++) - { - line = sector->lines[i]; - check = getNextSector(line,sector); - - if (!check) - continue; - - if (check->lightlevel < min) - min = check->lightlevel; - } - return min; -} - - - -// -// EVENTS -// Events are operations triggered by using, crossing, -// or shooting special lines, or by timed thinkers. -// - -// [STRIFE] -static char crosslinestr[90]; - -// -// P_CrossSpecialLine - TRIGGER -// Called every time a thing origin is about -// to cross a line with a non 0 special. -// -void -P_CrossSpecialLine -( int linenum, - int side, - mobj_t* thing ) -{ - line_t* line; - side_t* sidedef; // [STRIFE] - int flag; // [STRIFE] - int ok; - - line = &lines[linenum]; - - // haleyjd 09/21/10: corpses and missiles cannot activate any cross-over - // line types, *except* 182 (which is for the sake of missiles). - if((thing->flags & (MF_MISSILE|MF_CORPSE)) && line->special != 182) - return; - - // Triggers that other things can activate - if (!thing->player) - { - // Things that should NOT trigger specials... - // villsa [STRIFE] unused - // haleyjd: removed dead switch. Strife only excludes missiles and - // corpses, which is handled above. - - ok = 0; - - // [STRIFE] Added several line types. Removed none. - switch(line->special) - { - case 97: // TELEPORT RETRIGGER - case 185: // haleyjd: [STRIFE] Silent Teleport (used for Converter) - case 195: // haleyjd: [STRIFE] Silent Teleport and Change Zombie - case 231: // haleyjd: [STRIFE] WR Teleport (Silent at Source) - case 125: // TELEPORT MONSTERONLY TRIGGER - case 126: // TELEPORT MONSTERONLY RETRIGGER - case 182: // haleyjd: [STRIFE] Break glass - it's a W1 type too! - case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER - case 39: // TELEPORT TRIGGER - case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER - case 4: // RAISE DOOR - ok = 1; - break; - } - if (!ok) - return; - } - - - // Note: could use some const's here. - switch (line->special) - { - // - // TRIGGERS. - // All from here to RETRIGGERS. - // - case 230: - // haleyjd 09/21/10: [STRIFE] W1 Open Door if Quest - sidedef = &sides[line->sidenum[0]]; - flag = (sidedef->rowoffset >> FRACBITS) - 1; - - if(!(thing->player->questflags & (1 << flag))) - break; - // fall-through: - case 2: - // Open Door - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_open); - line->special = 0; - break; - - case 227: - // haleyjd 09/21/10: [STRIFE] W1 Close Door if Quest - sidedef = &sides[line->sidenum[0]]; - flag = (sidedef->rowoffset >> FRACBITS) - 1; - - if(!(thing->player->questflags & (1 << flag))) - break; - // fall-through: - case 3: - // Close Door - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_close); - line->special = 0; - break; - - case 4: - // Raise Door - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_normal); - line->special = 0; - break; - - case 5: - // Raise Floor - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloor); - line->special = 0; - break; - - case 6: - // Fast Ceiling Crush & Raise - [STRIFE] Verified unmodified. - EV_DoCeiling(line,fastCrushAndRaise); - line->special = 0; - break; - - case 8: - // Build Stairs - [STRIFE] Verified unmodified. - EV_BuildStairs(line,build8); - line->special = 0; - break; - - case 10: - // PlatDownWaitUp - [STRIFE] Verified unmodified. - EV_DoPlat(line,downWaitUpStay,0); - line->special = 0; - break; - - case 12: - // Light Turn On - brightest near - [STRIFE] Verified unmodified. - EV_LightTurnOn(line,0); - line->special = 0; - break; - - case 13: - // Light Turn On 255 - [STRIFE] Verified unmodified. - EV_LightTurnOn(line,255); - line->special = 0; - break; - - case 16: - // Close Door 30 - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_close30ThenOpen); - line->special = 0; - break; - - case 17: - // Start Light Strobing - [STRIFE] Verified unmodified. - EV_StartLightStrobing(line); - line->special = 0; - break; - - case 19: - // Lower Floor - [STRIFE] Verified unmodified. - EV_DoFloor(line,lowerFloor); - line->special = 0; - break; - - case 22: - // villsa [STRIFE] Verified unmodified. - // Raise floor to nearest height and change texture - EV_DoPlat(line,raiseToNearestAndChange,0); - line->special = 0; - break; - - case 25: - // Ceiling Crush and Raise - [STRIFE] Verified unmodified. - EV_DoCeiling(line,crushAndRaise); - line->special = 0; - break; - - case 30: - // Raise floor to shortest texture height - [STRIFE] Verified unmodified. - // on either side of lines. - EV_DoFloor(line,raiseToTexture); - line->special = 0; - break; - - case 35: - // Lights Very Dark - [STRIFE] Verified unmodified. - EV_LightTurnOn(line,35); - line->special = 0; - break; - - case 36: - // Lower Floor (TURBO) - [STRIFE] Verified unmodified. - EV_DoFloor(line,turboLower); - line->special = 0; - break; - - case 37: - // LowerAndChange - [STRIFE] Verified unmodified. - EV_DoFloor(line,lowerAndChange); - line->special = 0; - break; - - case 193: - // haleyjd 09/21/10: [STRIFE] W1 Floor Lower to Lowest if Quest - sidedef = &sides[line->sidenum[0]]; - flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t - - // must have the questflag indicated in the line's y offset - if(!(thing->player->questflags & (1 << flag))) - break; - // fall-through: - case 38: - // Lower Floor To Lowest - [STRIFE] Verified unmodified. - EV_DoFloor( line, lowerFloorToLowest ); - line->special = 0; - break; - - case 39: - // TELEPORT! - [STRIFE] Verified unmodified (except for 0 flags param) - EV_Teleport( line, side, thing, TF_NORMAL ); - line->special = 0; - break; - - /*case 40: - // RaiseCeilingLowerFloor - EV_DoCeiling( line, raiseToHighest ); - EV_DoFloor( line, lowerFloorToLowest ); - line->special = 0; - break;*/ - - case 44: - // Ceiling Crush - [STRIFE] Verified unmodified. - EV_DoCeiling( line, lowerAndCrush ); - line->special = 0; - break; - - case 52: - // EXIT! - haleyjd 09/21/10: [STRIFE] Exit to level tag/100 - G_ExitLevel (line->tag / 100); - break; - - case 53: - // Perpetual Platform Raise - [STRIFE] Verified unmodified. - EV_DoPlat(line,perpetualRaise,0); - line->special = 0; - break; - - case 54: - // Platform Stop - [STRIFE] Verified unmodified. - EV_StopPlat(line); - line->special = 0; - break; - - case 56: - // Raise Floor Crush - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloorCrush); - line->special = 0; - break; - - case 57: - // Ceiling Crush Stop - [STRIFE] Verified unmodified. - EV_CeilingCrushStop(line); - line->special = 0; - break; - - case 58: - // [STRIFE] raiseFloor24 was modified into raiseFloor64 - // Raise Floor 64 - EV_DoFloor(line,raiseFloor64); - line->special = 0; - break; - - case 59: - // Raise Floor 24 And Change - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloor24AndChange); - line->special = 0; - break; - - case 104: - // Turn lights off in sector(tag) - [STRIFE] Verified unmodified. - EV_TurnTagLightsOff(line); - line->special = 0; - break; - - case 108: - // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified. - EV_DoDoor (line,vld_blazeRaise); - line->special = 0; - break; - - case 109: - // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified. - EV_DoDoor (line,vld_blazeOpen); - line->special = 0; - break; - - case 100: - // Build Stairs Turbo 16 - [STRIFE] Verified unmodified. - EV_BuildStairs(line,turbo16); - line->special = 0; - break; - - case 197: - // haleyjd 09/21/10: [STRIFE] Blazing Door Close if Has Sigil B - if(thing->player->sigiltype <= 0) - break; - // fall-through: - case 110: - // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified. - EV_DoDoor (line,vld_blazeClose); - line->special = 0; - break; - - case 119: - // Raise floor to nearest surr. floor - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloorToNearest); - line->special = 0; - break; - - case 121: - // villsa [STRIFE] Verified unmodified. - // Blazing PlatDownWaitUpStay - EV_DoPlat(line,blazeDWUS,0); - line->special = 0; - break; - - case 124: - // haleyjd 09/21/10: [STRIFE] W1 Start Finale - // Altered from G_SecretExitLevel. - G_StartFinale(); - break; - - case 125: - // TELEPORT MonsterONLY - [STRIFE] Verified unmodified - // (except for 0 flags parameter) - if (!thing->player) - { - EV_Teleport( line, side, thing, TF_NORMAL ); - line->special = 0; - } - break; - - case 130: - // Raise Floor Turbo - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloorTurbo); - line->special = 0; - break; - - case 141: - // Silent Ceiling Crush & Raise - [STRIFE] Verified unmodified. - EV_DoCeiling(line,silentCrushAndRaise); - line->special = 0; - break; - - case 174: - // villsa [STRIFE] Split Open - EV_DoDoor(line, vld_splitOpen); - line->special = 0; - break; - - case 183: - // villsa [STRIFE] Split Raise Nearest - EV_DoDoor(line, vld_splitRaiseNearest); - line->special = 0; - break; - - case 178: - // haleyjd 09/24/10: [STRIFE] W1 Build Stairs Down 16 - EV_BuildStairs(line, buildDown16); - line->special = 0; - break; - - case 179: - // haleyjd 09/25/10: [STRIFE] W1 Ceiling Lower to Floor - EV_DoCeiling(line, lowerToFloor); - line->special = 0; - break; - - case 182: - // haleyjd 09/21/10: [STRIFE] Break Glass - // 182 is a unique linetype in that it is both a G1 and a W1 linetype, - // but only missiles may activate it as a W1 type. - if(thing->flags & MF_MISSILE) - P_ChangeSwitchTexture(line, 1); // why 1? it will be cleared anyway. - break; - - case 187: - // haleyjd 09/21/10: [STRIFE] W1 Clear Force Fields if Quest - sidedef = &sides[line->sidenum[0]]; - flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t - - // must have the questflag indicated in the line's y offset - if(!(thing->player->questflags & (1 << flag))) - break; - - // Do it! - EV_ClearForceFields(line); - line->special = 0; - break; - - case 188: - // haleyjd 09/21/10: [STRIFE] W1 Open Door if Quest 16 (Gate Mechanism - // Destroyed) - if(!(thing->player->questflags & QF_QUEST16)) - break; - EV_DoDoor(line, vld_open); - line->special = 0; - break; - - case 196: - // haleyjd 09/26/10: [STRIFE] W1 Floor Lower to Lowest if Sigil Type > 0 - if(thing->player->sigiltype > 0) - { - EV_DoFloor(line, lowerFloorToLowest); - line->special = 0; - } - break; - - case 200: - // haleyjd 09/21/10: [STRIFE] W1 Open Door if Sigil Owned - if(!(thing->player->weaponowned[wp_sigil])) - break; - EV_DoDoor(line, vld_open); - line->special = 0; - break; - - case 201: - // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective (First Side Only) - if(side == 1) - break; - // fall-through: - case 202: - // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective (Tag = VOC/LOG #) - // must be consoleplayer - if(thing->player != &players[consoleplayer]) - break; - - // must have comm unit - if(!(thing->player->powers[pw_communicator])) - break; - - // load voice - DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag); - I_StartVoice(crosslinestr); - - // load objective - DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag); - GiveObjective(crosslinestr, 0); - - // Put up a message - thing->player->message = DEH_String("Incoming Message..."); - line->special = 0; - break; - - case 210: - // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective if Flamethrower???? - // I don't think this is actually used anywhere o_O - // must be player 1... - if(thing->player != &players[0]) - break; - - // must have comm unit - if(!(thing->player->powers[pw_communicator])) - break; - - // must have... the flamethrower?! - if(!(thing->player->weaponowned[wp_flame])) - break; - - // load voice - DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag); - I_StartVoice(crosslinestr); - - // load objective - DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag); - GiveObjective(crosslinestr, 0); - - // Put up a message - thing->player->message = DEH_String("Incoming Message from BlackBird..."); - line->special = 0; - break; - - case 212: - // haleyjd 09/25/10: [STRIFE] W1 Floor Lower to Lowest if Have Flamethrower - if(thing->player->weaponowned[wp_flame]) - { - EV_DoFloor(line, lowerFloorToLowest); - line->special = 0; - } - break; - - case 215: - // haleyjd 09/21/10: [STRIFE] W1 Voiced Objective if Quest (Tag/100, Tag%100) - // must be player 1... - if(thing->player != &players[0]) - break; - - // must have comm unit - if(!(thing->player->powers[pw_communicator])) - break; - - if(line->tag != 0) - { - // test for questflag - if(!(thing->player->questflags & (1 << (line->tag % 100 - 1)))) - break; - } - - // start voice - DEH_snprintf(crosslinestr, sizeof(crosslinestr), "voc%i", line->tag/100); - I_StartVoice(crosslinestr); - - // give objective - DEH_snprintf(crosslinestr, sizeof(crosslinestr), "log%i", line->tag/100); - GiveObjective(crosslinestr, 0); - - // Put up a message - thing->player->message = DEH_String("Incoming Message from BlackBird..."); - line->special = 0; - break; - - case 204: - // haleyjd 09/21/10: [STRIFE] W1 Change Music (unused!) - if(thing->player != &players[0]) - break; - S_ChangeMusic(line->tag, 1); - line->special = 0; - break; - - case 228: - // haleyjd 09/21/10: [STRIFE] W1 Entity Voice? - if(!(thing->player->questflags & QF_QUEST24)) // Not killed Macil??? - break; // STRIFE-TODO: verify... - - if(!(thing->player->questflags & QF_QUEST28)) // ????? STRIFE-TODO - I_StartVoice(DEH_String("voc128")); - else - I_StartVoice(DEH_String("voc130")); - - line->special = 0; - break; - - // - // RETRIGGERS. All from here till end. - // - case 72: - // Ceiling Crush - [STRIFE] Verified unmodified. - EV_DoCeiling( line, lowerAndCrush ); - break; - - case 73: - // Ceiling Crush and Raise - [STRIFE] Verified unmodified. - EV_DoCeiling(line,crushAndRaise); - break; - - case 74: - // Ceiling Crush Stop - [STRIFE] Verified unmodified. - EV_CeilingCrushStop(line); - break; - - case 75: - // Close Door - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_close); - break; - - case 76: - // Close Door 30 - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_close30ThenOpen); - break; - - case 77: - // Fast Ceiling Crush & Raise - [STRIFE] Verified unmodified. - EV_DoCeiling(line,fastCrushAndRaise); - break; - - case 79: - // Lights Very Dark - [STRIFE] Verified unmodified. - EV_LightTurnOn(line,35); - break; - - case 80: - // Light Turn On - brightest near - [STRIFE] Verified unmodified. - EV_LightTurnOn(line,0); - break; - - case 81: - // Light Turn On 255 - [STRIFE] Verified unmodified. - EV_LightTurnOn(line,255); - break; - - case 82: - // Lower Floor To Lowest - [STRIFE] Verified unmodified. - EV_DoFloor( line, lowerFloorToLowest ); - break; - - case 83: - // Lower Floor - [STRIFE] Verified unmodified. - EV_DoFloor(line,lowerFloor); - break; - - case 84: - // LowerAndChange - [STRIFE] Verified unmodified. - EV_DoFloor(line,lowerAndChange); - break; - - case 86: - // Open Door - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_open); - break; - - case 87: - // Perpetual Platform Raise - [STRIFE] Verified unmodified. - EV_DoPlat(line,perpetualRaise,0); - break; - - case 88: - // PlatDownWaitUp - [STRIFE] Verified unmodified. - EV_DoPlat(line,downWaitUpStay,0); - break; - - case 89: - // Platform Stop - [STRIFE] Verified unmodified. - EV_StopPlat(line); - break; - - case 216: - // haleyjd 09/21/10: [STRIFE] WR Raise Door if Quest - sidedef = &sides[line->sidenum[0]]; - flag = (sidedef->rowoffset >> FRACBITS) - 1; // note is fixed_t. - - if(!(thing->player->questflags & (1 << flag))) - break; - // fall-through: - case 90: - // Raise Door - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_normal); - break; - - case 91: - // Raise Floor - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloor); - break; - - case 92: - // [STRIFE] raiseFloor24 changed to raiseFloor64 - // Raise Floor 64 - EV_DoFloor(line,raiseFloor64); - break; - - case 93: - // Raise Floor 24 And Change - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloor24AndChange); - break; - - case 94: - // Raise Floor Crush - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloorCrush); - break; - - case 95: - // villsa [STRIFE] Verified unmodified. - // Raise floor to nearest height - // and change texture. - EV_DoPlat(line,raiseToNearestAndChange,0); - break; - - case 96: - // Raise floor to shortest texture height - [STRIFE] Verified unmodified. - // on either side of lines. - EV_DoFloor(line,raiseToTexture); - break; - - case 97: - // TELEPORT! - [STRIFE] Verified unmodified (except for 0 flags param) - EV_Teleport( line, side, thing, TF_NORMAL ); - break; - - case 98: - // Lower Floor (TURBO) - [STRIFE] Verified unmodified. - EV_DoFloor(line,turboLower); - break; - - case 105: - // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified. - EV_DoDoor (line,vld_blazeRaise); - break; - - case 106: - // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified. - EV_DoDoor (line,vld_blazeOpen); - break; - - case 107: - // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified. - EV_DoDoor (line,vld_blazeClose); - break; - - case 120: - // villsa [STRIFE] Verified unmodified. - // Blazing PlatDownWaitUpStay. - EV_DoPlat(line,blazeDWUS,0); - break; - - case 126: - // TELEPORT MonsterONLY. - [STRIFE] Verified unmodified (except for 0 flags param) - if (!thing->player) - EV_Teleport( line, side, thing, TF_NORMAL ); - break; - - case 128: - // Raise To Nearest Floor - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloorToNearest); - break; - - case 129: - // Raise Floor Turbo - [STRIFE] Verified unmodified. - EV_DoFloor(line,raiseFloorTurbo); - break; - - case 186: - // haleyjd [STRIFE] Exit Level to Spot, First Side Only - if(side == 1) - break; - // fall-through: - case 145: - // haleyjd [STRIFE] Exit Level to Spot - thing->momx = thing->momy = thing->momz = 0; - { - int map = line->tag / 100; - int spot = line->tag % 100; - - if(thing->player->weaponowned[wp_sigil]) - { - if(map == 3) - map = 30; - else if(map == 7) - map = 10; - } - - DEH_snprintf(crosslinestr, sizeof(crosslinestr), - "Entering%s", - DEH_String(mapnames[map - 1]) + 8); - thing->player->message = crosslinestr; - - if(netgame && deathmatch) - { - if(levelTimer && levelTimeCount != 0) - { - DEH_snprintf(crosslinestr, sizeof(crosslinestr), - "%d min left", - (levelTimeCount/TICRATE)/60); - break; - } - - // raise switch from floor - EV_DoFloor(line, raiseFloor64); - } - else - { - // normal single-player exit - - // BUG: Here is the opening for a flaming player to cross past - // the exit line and hit a deathmatch switch ;) It's not so much - // that this is incorrect, as that they forgot to add such a - // check to the other kind of exit lines too ;) - if(thing->player->health <= 0) - break; - - G_RiftExitLevel(map, spot, thing->angle); - } - } - break; - - case 175: - // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if < 16 Above Floor - if(thing->z < thing->floorz + 16 * FRACUNIT) - P_NoiseAlert(thing->player->mo, thing->player->mo); - break; - - case 198: - // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if No Guard Uniform - if(P_PlayerHasItem(thing->player, MT_QUEST_GUARD_UNIFORM)) - break; - // fall-through: - case 150: - // haleyjd 09/21/10: [STRIFE] WR Raise Alarm - P_NoiseAlert(thing->player->mo, thing->player->mo); - break; - - case 208: - // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if Have Flamethrower - // O_o - this is definitely unused. Was an entire flamethrower quest - // cut out of the game before release? - if(thing->player->weaponowned[wp_flame]) - P_NoiseAlert(thing->player->mo, thing->player->mo); - break; - - case 206: - // haleyjd 09/21/10: [STRIFE] WR Raise Alarm if Have Chalice - // This *is* used, inside the Tavern in Tarnhill. Oddly there is also - // one just randomly placed outside the entrance to the Power Station. - if(P_PlayerHasItem(thing->player, MT_INV_CHALICE)) - P_NoiseAlert(thing->player->mo, thing->player->mo); - break; - - case 184: - // villsa [STRIFE] plat up wait down stay - if(EV_DoPlat(line, upWaitDownStay, 0)) - P_ChangeSwitchTexture(line, 1); // In P_CrossSpecialLine? Copypasta error? - break; - - case 185: - // haleyjd 09/21/10: [STRIFE] Silent Teleport (used for Converter) - EV_Teleport(line, side, thing, TF_FULLSILENCE); - break; - - case 195: - // haleyjd 09/21/10: [STRIFE] Silent Teleport and Change Zombie - EV_Teleport(line, side, thing, TF_FULLSILENCE); - P_SetMobjState(thing, S_AGRD_00); // 419 - break; - - case 203: - // haleyjd 09/21/10: [STRIFE] WR Change Music - if(thing->player != &players[0]) - break; - S_ChangeMusic(line->tag, 1); - break; - - case 231: - // haleyjd 09/21/10: [STRIFE] WR Teleport (Silent at Source) - EV_Teleport(line, side, thing, TF_SRCSILENCE); - break; - - // haleyjd 09/21/10: Moved one-time-use lines up above with the others. - } -} - - - -// -// P_ShootSpecialLine - IMPACT SPECIALS -// Called when a thing shoots a special line. -// -void -P_ShootSpecialLine -( mobj_t* thing, - line_t* line ) -{ - int ok; - - // Impacts that other things can activate. - if (!thing->player) - { - ok = 0; - switch(line->special) - { - case 46: // OPEN DOOR IMPACT - case 182: // villsa [STRIFE] for windows - ok = 1; - break; - } - if (!ok) - return; - } - - switch(line->special) - { - case 24: - // RAISE FLOOR - [STRIFE] Verified unmodified - EV_DoFloor(line,raiseFloor); - P_ChangeSwitchTexture(line,0); - break; - - case 46: - // OPEN DOOR - [STRIFE] Verified unmodified. - EV_DoDoor(line,vld_open); - P_ChangeSwitchTexture(line,1); - break; - - case 47: - // villsa [STRIFE] Verified unmodified. - // RAISE FLOOR NEAR AND CHANGE - EV_DoPlat(line,raiseToNearestAndChange,0); - P_ChangeSwitchTexture(line,0); - break; - - case 180: - // haleyjd 09/22/10: [STRIFE] G1 Raise Floor 512 & Change - EV_DoFloor(line, raiseFloor512AndChange); - P_ChangeSwitchTexture(line, 0); - break; - - case 182: - // villsa [STRIFE] G1 Break Glass - // haleyjd: note that 182 is also a W1 type in P_CrossSpecialLine, but - // can only be activated in that manner by an MF_MISSILE object. - P_ChangeSwitchTexture(line, 0); - break; - } -} - - - -// -// P_PlayerInSpecialSector -// Called every tic frame -// that the player origin is in a special sector -// -// [STRIFE] Modified for new sector types and changes to old ones. -// -void P_PlayerInSpecialSector (player_t* player) -{ - sector_t* sector; - - sector = player->mo->subsector->sector; - - // Falling, not all the way down yet? - if (player->mo->z != sector->floorheight) - return; - - // Has hitten ground. - switch (sector->special) - { - case 5: - // HELLSLIME DAMAGE - // [STRIFE] +2 to nukagecount - if(!player->powers[pw_ironfeet]) - player->nukagecount += 2; - break; - - case 16: - // [STRIFE] +4 to nukagecount - if(!player->powers[pw_ironfeet]) - player->nukagecount += 4; - break; - - case 4: - case 7: - // [STRIFE] Immediate 5 damage every 31 tics - if(!player->powers[pw_ironfeet]) - if(!(leveltime & 0x1f)) - P_DamageMobj(player->mo, NULL, NULL, 5); - break; - - case 9: - // SECRET SECTOR - //player->secretcount++; [STRIFE] Don't have a secret count. - sector->special = 0; - if(player - players == consoleplayer) - S_StartSound(NULL, sfx_yeah); - break; - - case 11: - // EXIT SUPER DAMAGE! (for E1M8 finale) - player->cheats &= ~CF_GODMODE; - - if (!(leveltime&0x1f)) - P_DamageMobj (player->mo, NULL, NULL, 20); - - if (player->health <= 10) - G_ExitLevel(0); - break; - - case 15: - // haleyjd 08/30/10: [STRIFE] "Instant" Death sector - P_DamageMobj(player->mo, NULL, NULL, 999); - break; - - - case 18: - // haleyjd 08/30/10: [STRIFE] Water current - { - int tagval = sector->tag - 100; - fixed_t force; - angle_t angle; - - if(player->cheats & CF_NOCLIP) - return; - - force = (tagval % 10) << 12; - angle = (tagval / 10) << 29; - - P_Thrust(player, angle, force); - } - break; - - default: - I_Error ("P_PlayerInSpecialSector: " - "unknown special %i", - sector->special); - break; - }; -} - - - - -// -// P_UpdateSpecials -// Animate planes, scroll walls, etc. -// -// [STRIFE] Modifications to support multiple scrolling line types. -// -boolean levelTimer; -int levelTimeCount; - -void P_UpdateSpecials (void) -{ - anim_t* anim; - int pic; - int i; - line_t* line; - - - // LEVEL TIMER - if (levelTimer == true) - { - if(levelTimeCount) // [STRIFE] Does not allow to go negative - levelTimeCount--; - - /* - // [STRIFE] Not done here. Exit lines check this manually instead. - if (!levelTimeCount) - G_ExitLevel(0); - */ - } - - // ANIMATE FLATS AND TEXTURES GLOBALLY - for (anim = anims ; anim < lastanim ; anim++) - { - for (i=anim->basepic ; ibasepic+anim->numpics ; i++) - { - pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); - if (anim->istexture) - texturetranslation[i] = pic; - else - flattranslation[i] = pic; - } - } - - - // ANIMATE LINE SPECIALS - for (i = 0; i < numlinespecials; i++) - { - line = linespeciallist[i]; - switch(line->special) - { - case 48: - // EFFECT FIRSTCOL SCROLL + - sides[line->sidenum[0]].textureoffset += FRACUNIT; - break; - - case 142: - // haleyjd 09/25/10 [STRIFE] Scroll Up Slow - sides[line->sidenum[0]].rowoffset += FRACUNIT; - break; - - case 143: - // haleyjd 09/25/10 [STRIFE] Scroll Down Fast (3 Units/Tic) - sides[line->sidenum[0]].rowoffset -= 3*FRACUNIT; - break; - - case 149: - // haleyjd 09/25/10 [STRIFE] Scroll Down Slow - sides[line->sidenum[0]].rowoffset -= FRACUNIT; - break; - } - } - - - // DO BUTTONS - for (i = 0; i < MAXBUTTONS; i++) - if (buttonlist[i].btimer) - { - buttonlist[i].btimer--; - if (!buttonlist[i].btimer) - { - switch(buttonlist[i].where) - { - case top: - sides[buttonlist[i].line->sidenum[0]].toptexture = - buttonlist[i].btexture; - break; - - case middle: - sides[buttonlist[i].line->sidenum[0]].midtexture = - buttonlist[i].btexture; - break; - - case bottom: - sides[buttonlist[i].line->sidenum[0]].bottomtexture = - buttonlist[i].btexture; - break; - } - S_StartSound(&buttonlist[i].soundorg,sfx_swtchn); - memset(&buttonlist[i],0,sizeof(button_t)); - } - } -} - - -// -// Donut overrun emulation -// -// Derived from the code from PrBoom+. Thanks go to Andrey Budko (entryway) -// as usual :-) -// - -#define DONUT_FLOORHEIGHT_DEFAULT 0x00000000 -#define DONUT_FLOORPIC_DEFAULT 0x16 - -static void DonutOverrun(fixed_t *s3_floorheight, short *s3_floorpic, - line_t *line, sector_t *pillar_sector) -{ - static int first = 1; - static int tmp_s3_floorheight; - static int tmp_s3_floorpic; - - if (first) - { - int p; - - // This is the first time we have had an overrun. - first = 0; - - // Default values - tmp_s3_floorheight = DONUT_FLOORHEIGHT_DEFAULT; - tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; - - //! - // @category compat - // @arg - // - // Use the specified magic values when emulating behavior caused - // by memory overruns from improperly constructed donuts. - // In Vanilla Strife this can differ depending on the operating - // system. The default (if this option is not specified) is to - // emulate the behavior when running under Windows 98. - - p = M_CheckParmWithArgs("-donut", 2); - - if (p > 0) - { - // Dump of needed memory: (fixed_t)0000:0000 and (short)0000:0008 - // - // C:\>debug - // -d 0:0 - // - // DOS 6.22: - // 0000:0000 (57 92 19 00) F4 06 70 00-(16 00) - // DOS 7.1: - // 0000:0000 (9E 0F C9 00) 65 04 70 00-(16 00) - // Win98: - // 0000:0000 (00 00 00 00) 65 04 70 00-(16 00) - // DOSBox under XP: - // 0000:0000 (00 00 00 F1) ?? ?? ?? 00-(07 00) - - M_StrToInt(myargv[p + 1], &tmp_s3_floorheight); - M_StrToInt(myargv[p + 2], &tmp_s3_floorpic); - - if (tmp_s3_floorpic >= numflats) - { - fprintf(stderr, - "DonutOverrun: The second parameter for \"-donut\" " - "switch should be greater than 0 and less than number " - "of flats (%d). Using default value (%d) instead. \n", - numflats, DONUT_FLOORPIC_DEFAULT); - tmp_s3_floorpic = DONUT_FLOORPIC_DEFAULT; - } - } - } - - /* - fprintf(stderr, - "Linedef: %d; Sector: %d; " - "New floor height: %d; New floor pic: %d\n", - line->iLineID, pillar_sector->iSectorID, - tmp_s3_floorheight >> 16, tmp_s3_floorpic); - */ - - *s3_floorheight = (fixed_t) tmp_s3_floorheight; - *s3_floorpic = (short) tmp_s3_floorpic; -} - - -// -// Special Stuff that can not be categorized -// -int EV_DoDonut(line_t* line) -{ - sector_t* s1; - sector_t* s2; - sector_t* s3; - int secnum; - int rtn; - int i; - floormove_t* floor; - fixed_t s3_floorheight; - short s3_floorpic; - - secnum = -1; - rtn = 0; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) - { - s1 = §ors[secnum]; - - // ALREADY MOVING? IF SO, KEEP GOING... - if (s1->specialdata) - continue; - - rtn = 1; - s2 = getNextSector(s1->lines[0],s1); - - // Vanilla Doom does not check if the linedef is one sided. The - // game does not crash, but reads invalid memory and causes the - // sector floor to move "down" to some unknown height. - // DOSbox prints a warning about an invalid memory access. - // - // I'm not sure exactly what invalid memory is being read. This - // isn't something that should be done, anyway. - // Just print a warning and return. - - if (s2 == NULL) - { - fprintf(stderr, - "EV_DoDonut: linedef had no second sidedef! " - "Unexpected behavior may occur in Vanilla Doom. \n"); - break; - } - - for (i = 0; i < s2->linecount; i++) - { - s3 = s2->lines[i]->backsector; - - if (s3 == s1) - continue; - - if (s3 == NULL) - { - // e6y - // s3 is NULL, so - // s3->floorheight is an int at 0000:0000 - // s3->floorpic is a short at 0000:0008 - // Trying to emulate - - fprintf(stderr, - "EV_DoDonut: WARNING: emulating buffer overrun due to " - "NULL back sector. " - "Unexpected behavior may occur in Vanilla Doom.\n"); - - DonutOverrun(&s3_floorheight, &s3_floorpic, line, s1); - } - else - { - s3_floorheight = s3->floorheight; - s3_floorpic = s3->floorpic; - } - - // Spawn rising slime - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - s2->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->type = donutRaise; - floor->crush = false; - floor->direction = 1; - floor->sector = s2; - floor->speed = FLOORSPEED / 2; - floor->texture = s3_floorpic; - floor->newspecial = 0; - floor->floordestheight = s3_floorheight; - - // Spawn lowering donut-hole - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); - P_AddThinker (&floor->thinker); - s1->specialdata = floor; - floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor; - floor->type = lowerFloor; - floor->crush = false; - floor->direction = -1; - floor->sector = s1; - floor->speed = FLOORSPEED / 2; - floor->floordestheight = s3_floorheight; - break; - } - } - return rtn; -} - - - -// -// SPECIAL SPAWNING -// - -// -// P_SpawnSpecials -// After the map has been loaded, scan for specials -// that spawn thinkers -// - - -// Parses command line parameters. -// -// haleyjd 09/25/10: [STRIFE] Modifications for more scrolling line types and -// for initialization of sliding door resources. -// -void P_SpawnSpecials (void) -{ - sector_t* sector; - int i; - - // See if -TIMER was specified. - - if (timelimit > 0 && deathmatch) - { - levelTimer = true; - levelTimeCount = timelimit * 60 * TICRATE; - } - else - { - levelTimer = false; - } - - // Init special SECTORs - [STRIFE] Verified unmodified. - sector = sectors; - for (i=0 ; ispecial) - continue; - - switch (sector->special) - { - case 1: - // FLICKERING LIGHTS - P_SpawnLightFlash (sector); - break; - - case 2: - // STROBE FAST - P_SpawnStrobeFlash(sector,FASTDARK,0); - break; - - case 3: - // STROBE SLOW - P_SpawnStrobeFlash(sector,SLOWDARK,0); - break; - - case 4: - // STROBE FAST/DEATH SLIME - P_SpawnStrobeFlash(sector,FASTDARK,0); - sector->special = 4; - break; - - case 8: - // GLOWING LIGHT - P_SpawnGlowingLight(sector); - break; - case 9: - // SECRET SECTOR - totalsecret++; - break; - - case 10: - // DOOR CLOSE IN 30 SECONDS - P_SpawnDoorCloseIn30 (sector); - break; - - case 12: - // SYNC STROBE SLOW - P_SpawnStrobeFlash (sector, SLOWDARK, 1); - break; - - case 13: - // SYNC STROBE FAST - P_SpawnStrobeFlash (sector, FASTDARK, 1); - break; - - case 14: - // DOOR RAISE IN 5 MINUTES - P_SpawnDoorRaiseIn5Mins (sector, i); - break; - - case 17: - P_SpawnFireFlicker(sector); - break; - } - } - - - // Init line EFFECTs - numlinespecials = 0; - for (i = 0;i < numlines; i++) - { - switch(lines[i].special) - { - case 48: // EFFECT FIRSTCOL SCROLL+ - case 142: - case 143: - case 149: - linespeciallist[numlinespecials] = &lines[i]; - numlinespecials++; - break; - } - } - - // Init other misc stuff - for (i = 0;i < MAXCEILINGS;i++) - activeceilings[i] = NULL; - - for (i = 0;i < MAXPLATS;i++) - activeplats[i] = NULL; - - for (i = 0;i < MAXBUTTONS;i++) - memset(&buttonlist[i],0,sizeof(button_t)); - - // villsa [STRIFE] - P_InitSlidingDoorFrames(); -} diff --git a/games/NXDoom/src/strife/p_spec.h b/games/NXDoom/src/strife/p_spec.h deleted file mode 100644 index 684386afec7..00000000000 --- a/games/NXDoom/src/strife/p_spec.h +++ /dev/null @@ -1,678 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// Implements special effects: -// Texture animation, height or lighting changes -// according to adjacent sectors, respective -// utility functions, etc. -// - - -#ifndef __P_SPEC__ -#define __P_SPEC__ - - -// -// End-level timer (-TIMER option) -// -extern boolean levelTimer; -extern int levelTimeCount; - - -// Define values for map objects -#define MO_TELEPORTMAN 14 - - -// at game start -void P_InitPicAnims (void); - -// villsa [STRIFE] -typedef enum -{ - FLOOR_WATER = 0, - FLOOR_SLIME = 1, - FLOOR_SOLID = 2, - FLOOR_END = -1 -} terraintype_e; - -void P_InitTerrainTypes(void); // villsa [STRIFE] -terraintype_e P_GetTerrainType(mobj_t* mobj); // villsa [STRIFE] - -// at map load -void P_SpawnSpecials (void); - -// every tic -void P_UpdateSpecials (void); - -// when needed -boolean -P_UseSpecialLine -( mobj_t* thing, - line_t* line, - int side ); - -void -P_ShootSpecialLine -( mobj_t* thing, - line_t* line ); - -void -P_CrossSpecialLine -( int linenum, - int side, - mobj_t* thing ); - -void P_PlayerInSpecialSector (player_t* player); - -int -twoSided -( int sector, - int line ); - -sector_t* -getSector -( int currentSector, - int line, - int side ); - -side_t* -getSide -( int currentSector, - int line, - int side ); - -fixed_t P_FindLowestFloorSurrounding(sector_t* sec); -fixed_t P_FindHighestFloorSurrounding(sector_t* sec); - -fixed_t -P_FindNextHighestFloor -( sector_t* sec, - int currentheight ); - -fixed_t P_FindLowestCeilingSurrounding(sector_t* sec); -fixed_t P_FindHighestCeilingSurrounding(sector_t* sec); - -int -P_FindSectorFromLineTag -( line_t* line, - int start ); - -int -P_FindMinSurroundingLight -( sector_t* sector, - int max ); - -sector_t* -getNextSector -( line_t* line, - sector_t* sec ); - - -// -// SPECIAL -// -int EV_DoDonut(line_t* line); -boolean EV_ClearForceFields(line_t* line); // villsa [STRIFE] - - -// -// P_LIGHTS -// -typedef struct -{ - thinker_t thinker; - sector_t* sector; - int count; - int maxlight; - int minlight; - -} fireflicker_t; - - - -typedef struct -{ - thinker_t thinker; - sector_t* sector; - int count; - int maxlight; - int minlight; - int maxtime; - int mintime; - -} lightflash_t; - - - -typedef struct -{ - thinker_t thinker; - sector_t* sector; - int count; - int minlight; - int maxlight; - int darktime; - int brighttime; - -} strobe_t; - - - - -typedef struct -{ - thinker_t thinker; - sector_t* sector; - int minlight; - int maxlight; - int direction; - -} glow_t; - - -#define GLOWSPEED 8 -#define STROBEBRIGHT 5 -#define FASTDARK 15 -#define SLOWDARK 35 - -void P_SpawnFireFlicker (sector_t* sector); -void T_LightFlash (lightflash_t* flash); -void P_SpawnLightFlash (sector_t* sector); -void T_StrobeFlash (strobe_t* flash); - -void -P_SpawnStrobeFlash -( sector_t* sector, - int fastOrSlow, - int inSync ); - -void EV_StartLightStrobing(line_t* line); -void EV_TurnTagLightsOff(line_t* line); - -void -EV_LightTurnOn -( line_t* line, - int bright ); - -void T_Glow(glow_t* g); -void P_SpawnGlowingLight(sector_t* sector); - - - - -// -// P_SWITCH -// -typedef struct -{ - char name1[9]; - char name2[9]; - short episode; - int sound; // villsa [STRIFE] - -} switchlist_t; - - -typedef enum -{ - top, - middle, - bottom - -} bwhere_e; - - -typedef struct -{ - line_t* line; - bwhere_e where; - int btexture; - int btimer; - degenmobj_t *soundorg; - -} button_t; - - - - - // max # of wall switches in a level -#define MAXSWITCHES 80 // villsa [STRIFE] changed from 50 to 80 - - // 4 players, 4 buttons each at once, max. -#define MAXBUTTONS 16 - - // 1 second, in ticks. -#define BUTTONTIME 35 - -extern button_t buttonlist[MAXBUTTONS]; - -void -P_ChangeSwitchTexture -( line_t* line, - int useAgain ); - -void P_InitSwitchList(void); - - -// -// P_PLATS -// -typedef enum -{ - up, - down, - waiting, - in_stasis - -} plat_e; - - - -typedef enum -{ - perpetualRaise, - downWaitUpStay, - slowDWUS, // villsa [STRIFE] - raiseAndChange, - raiseToNearestAndChange, - blazeDWUS, - upWaitDownStay // villsa [STRIFE] - -} plattype_e; - - - -typedef struct -{ - thinker_t thinker; - sector_t* sector; - fixed_t speed; - fixed_t low; - fixed_t high; - int wait; - int count; - plat_e status; - plat_e oldstatus; - boolean crush; - int tag; - plattype_e type; - -} plat_t; - - - -#define PLATWAIT 3 -#define PLATSPEED FRACUNIT -#define MAXPLATS 30 - - -extern plat_t* activeplats[MAXPLATS]; - -void T_PlatRaise(plat_t* plat); - -int -EV_DoPlat -( line_t* line, - plattype_e type, - int amount ); - -void P_AddActivePlat(plat_t* plat); -void P_RemoveActivePlat(plat_t* plat); -void EV_StopPlat(line_t* line); -void P_ActivateInStasis(int tag); - - -// -// P_DOORS -// -typedef enum -{ - vld_normal, - vld_close30ThenOpen, - vld_close, - vld_open, - vld_raiseIn5Mins, - vld_blazeRaise, - vld_blazeOpen, - vld_blazeClose, - vld_shopClose, // villsa [STRIFE] - vld_splitRaiseNearest, // villsa [STRIFE] - vld_splitOpen // villsa [STRIFE] - -} vldoor_e; - - - -typedef struct -{ - thinker_t thinker; - vldoor_e type; - sector_t* sector; - fixed_t topheight; - fixed_t speed; - - // 1 = up, 0 = waiting at top, -1 = down - int direction; - - // tics to wait at the top - int topwait; - // (keep in case a door going down is reset) - // when it reaches 0, start going down - int topcountdown; - - // villsa [STRIFE] new field - sound to play when opening - int opensound; - - // villsa [STRIFE] new field - sound to play when closing - int closesound; - -} vldoor_t; - - - -#define VDOORSPEED FRACUNIT*2 -#define VDOORWAIT 150 - -void -EV_VerticalDoor -( line_t* line, - mobj_t* thing ); - -int -EV_DoDoor -( line_t* line, - vldoor_e type ); - -int -EV_DoLockedDoor -( line_t* line, - vldoor_e type, - mobj_t* thing ); - -void T_VerticalDoor (vldoor_t* door); -void P_SpawnDoorCloseIn30 (sector_t* sec); - -void -P_SpawnDoorRaiseIn5Mins -( sector_t* sec, - int secnum ); - - - -// villsa [STRIFE] resurrected sliding doors -// -// Sliding doors... -// -typedef enum -{ - sd_opening, - sd_waiting, - sd_closing - -} sd_e; - - - -typedef enum -{ - sdt_openOnly, - sdt_closeOnly, - sdt_openAndClose - -} sdt_e; - - - -// villsa [STRIFE] Rogue added a second line_t in the struct -// backsector is removed -typedef struct -{ - thinker_t thinker; - sdt_e type; - line_t* line1; - line_t* line2; - int frame; - int whichDoorIndex; - int timer; - sector_t* frontsector; - sd_e status; - -} slidedoor_t; - -// villsa [STRIFE] no front/back frames -typedef struct -{ - char frame1[9]; - char frame2[9]; - char frame3[9]; - char frame4[9]; - char frame5[9]; - char frame6[9]; - char frame7[9]; - char frame8[9]; - -} slidename_t; - -// villsa [STRIFE] no front/back frames -typedef struct -{ - int frames[8]; - -} slideframe_t; - -// haleyjd 09/29/10: [STRIFE] Externalized for savegames -void T_SlidingDoor(slidedoor_t* door); - - -// how many frames of animation -#define SNUMFRAMES 8 // villsa [STRIFE] changed from 4 to 8 - -#define SDOORWAIT TICRATE*3 -#define SWAITTICS 4 - -// how many diff. types of anims -#define MAXSLIDEDOORS 8 // villsa [STRIFE] changed from 5 to 8 - -void P_InitSlidingDoorFrames(void); -void EV_SlidingDoor(line_t* line, mobj_t* thing); -int EV_RemoteSlidingDoor(line_t* line, mobj_t* thing); - - - -// -// P_CEILNG -// -typedef enum -{ - lowerToFloor, - raiseToHighest, - lowerAndCrush, - crushAndRaise, - fastCrushAndRaise, - silentCrushAndRaise - -} ceiling_e; - - - -typedef struct -{ - thinker_t thinker; - ceiling_e type; - sector_t* sector; - fixed_t bottomheight; - fixed_t topheight; - fixed_t speed; - boolean crush; - - // 1 = up, 0 = waiting, -1 = down - int direction; - - // ID - int tag; - int olddirection; - -} ceiling_t; - - - - - -#define CEILSPEED FRACUNIT -#define CEILWAIT 150 -#define MAXCEILINGS 30 - -extern ceiling_t* activeceilings[MAXCEILINGS]; - -int -EV_DoCeiling -( line_t* line, - ceiling_e type ); - -void T_MoveCeiling (ceiling_t* ceiling); -void P_AddActiveCeiling(ceiling_t* c); -void P_RemoveActiveCeiling(ceiling_t* c); -int EV_CeilingCrushStop(line_t* line); -void P_ActivateInStasisCeiling(line_t* line); - - -// -// P_FLOOR -// -typedef enum -{ - // lower floor to highest surrounding floor - lowerFloor, - - // lower floor to lowest surrounding floor - lowerFloorToLowest, - - // lower floor to highest surrounding floor VERY FAST - turboLower, - - // raise floor to lowest surrounding CEILING - raiseFloor, - - // raise floor to next highest surrounding floor - raiseFloorToNearest, - - // raise floor to shortest height texture around it - raiseToTexture, - - // lower floor to lowest surrounding floor - // and change floorpic - lowerAndChange, - - raiseFloor64, // [STRIFE] changed from 24 to 64 - raiseFloor24AndChange, - raiseFloorCrush, - - // raise to next highest floor, turbo-speed - raiseFloorTurbo, - donutRaise, - raiseFloor512, - - // [STRIFE] New floor type - used for the coolant reactor pit - raiseFloor512AndChange - -} floor_e; - - - - -typedef enum -{ - build8, // slowly build by 8 - turbo16, // quickly build by 16 - buildDown16 // haleyjd 09/24/10: [STRIFE] new stair type -} stair_e; - - - -typedef struct -{ - thinker_t thinker; - floor_e type; - boolean crush; - sector_t* sector; - int direction; - int newspecial; - short texture; - fixed_t floordestheight; - fixed_t speed; - -} floormove_t; - - - -#define FLOORSPEED FRACUNIT - -typedef enum -{ - ok, - crushed, - pastdest - -} result_e; - -result_e -T_MovePlane -( sector_t* sector, - fixed_t speed, - fixed_t dest, - boolean crush, - int floorOrCeiling, - int direction ); - -int -EV_BuildStairs -( line_t* line, - stair_e type ); - -int -EV_DoFloor -( line_t* line, - floor_e floortype ); - -void T_MoveFloor( floormove_t* floor); - -// -// P_TELEPT -// - -// [STRIFE] Teleportation flags - teleflags -// Not to be conflated with telefrags, though they be tangentially related ;) -typedef enum teleflags -{ - TF_NOSRCSND = 0x01, - TF_NODSTSND = 0x02, - TF_NODSTFOG = 0x10, - TF_NOSRCFOG = 0x20, - - TF_NORMAL = 0, - TF_DSTSILENCE = (TF_NODSTSND|TF_NODSTFOG), // 0x12 (18) (Not used) - TF_SRCSILENCE = (TF_NOSRCSND|TF_NOSRCFOG), // 0x21 (33) - TF_FULLSILENCE = (TF_SRCSILENCE|TF_DSTSILENCE) // 0x33 (51) - -} teleflags_e; - -int -EV_Teleport -( line_t* line, - int side, - mobj_t* thing, - teleflags_e flags); - -#endif diff --git a/games/NXDoom/src/strife/p_switch.c b/games/NXDoom/src/strife/p_switch.c deleted file mode 100644 index 849ab2bc07f..00000000000 --- a/games/NXDoom/src/strife/p_switch.c +++ /dev/null @@ -1,1078 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// -// DESCRIPTION: -// Switches, buttons. Two-state animation. Exits. -// - -#include - -#include "i_system.h" -#include "deh_main.h" -#include "doomdef.h" -#include "p_local.h" - -#include "g_game.h" -#include "d_main.h" // villsa [STRIFE] -#include "z_zone.h" // villsa [STRIFE] -#include "w_wad.h" // villsa [STRIFE] -#include "s_sound.h" -#include "m_random.h" // haleyjd [STRIFE] -#include "p_dialog.h" -#include "p_local.h" // haleyjd [STRIFE] -#include "m_bbox.h" // villsa [STRIFE] -#include "m_misc.h" - -// Data. -#include "sounds.h" - -// State. -#include "doomstat.h" -#include "r_state.h" - -// -// CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE -// -// villsa [STRIFE] new switch list -switchlist_t alphSwitchList[] = -{ - { "GLASS01", "GLASS02", 1, sfx_bglass }, - { "GLASS03", "GLASS04", 1, sfx_bglass }, - { "GLASS05", "GLASS06", 1, sfx_bglass }, - { "GLASS07", "GLASS08", 1, sfx_bglass }, - { "GLASS17", "GLASS18", 1, sfx_bglass }, - { "GLASS19", "GLASS20", 1, sfx_bglass }, - { "SWKNOB01", "SWKNOB02", 1, sfx_swknob }, - { "SWLITE01", "SWLITE02", 1, sfx_None }, - { "SWCHN01", "SWCHN02", 1, sfx_pulchn }, - { "COMP01", "COMP04B", 1, sfx_bglass }, - { "COMP05", "COMP12B", 1, sfx_bglass }, - { "COMP09", "COMP12B", 1, sfx_bglass }, - { "COMP12", "COMP04B", 1, sfx_bglass }, - { "COMP13", "COMP12B", 1, sfx_bglass }, - { "COMP17", "COMP20B", 1, sfx_bglass }, - { "COMP21", "COMP28B", 1, sfx_bglass }, - { "WALTEK09", "WALTEKB1", 1, sfx_None }, - { "WALTEK10", "WALTEKB1", 1, sfx_None }, - { "WALTEK15", "WALTEKB1", 1, sfx_None }, - { "SWFORC01", "SWFORC02", 1, sfx_None }, - { "SWEXIT01", "SWEXIT02", 1, sfx_None }, - { "DORSBK01", "DORSBK02", 1, sfx_swston }, - { "SWSLD01", "SWSLD02", 1, sfx_None }, - { "DORWS04", "DORWS05", 1, sfx_swbolt }, - { "SWIRON01", "SWIRON02", 1, sfx_None }, - { "GLASS09", "GLASS10", 2, sfx_bglass }, - { "GLASS11", "GLASS12", 2, sfx_bglass }, - { "GLASS13", "GLASS14", 2, sfx_bglass }, - { "GLASS15", "GLASS16", 2, sfx_bglass }, - { "SWFORC03", "SWFORC04", 2, sfx_None }, - { "SWCIT01", "SWCIT02", 2, sfx_None }, - { "SWTRMG01", "SWTRMG04", 2, sfx_None }, - { "SWMETL01", "SWMETL02", 2, sfx_None }, - { "SWWOOD01", "SWWOOD02", 2, sfx_None }, - { "SWTKBL01", "SWTKBL02", 2, sfx_None }, - { "AZWAL21", "AZWAL22", 2, sfx_None }, - { "SWINDT01", "SWINDT02", 2, sfx_None }, - { "SWRUST01", "SWRUST02", 2, sfx_None }, - { "SWCHAP01", "SWCHAP02", 2, sfx_None }, - { "SWALIN01", "SWALIN02", 2, sfx_None }, - { "SWWALG01", "SWWALG02", 2, sfx_None }, - { "SWWALG03", "SWWALG04", 2, sfx_None }, - { "SWTRAM01", "SWTRAM02", 2, sfx_None }, - { "SWTRAM03", "SWTRAM04", 2, sfx_None }, - { "SWORC01", "SWORC02", 2, sfx_None }, - { "SWBRIK01", "SWBRIK02", 2, sfx_None }, - { "SWIRON03", "SWIRON04", 2, sfx_None }, - { "SWIRON05", "SWIRON06", 2, sfx_None }, - { "SWIRON07", "SWIRON08", 2, sfx_None }, - { "SWCARD01", "SWCARD02", 2, sfx_keycrd }, - { "SWSIGN01", "SWSIGN02", 2, sfx_None }, - { "SWLEV01", "SWLEV02", 2, sfx_None }, - { "SWLEV03", "SWLEV04", 2, sfx_None }, - { "SWLEV05", "SWLEV06", 2, sfx_None }, - { "SWBRN01", "SWBRN02", 2, sfx_keycrd }, - { "SWPIP01", "SWPIP02", 2, sfx_valve }, - { "SWPALM01", "SWPALM02", 2, sfx_swscan }, - { "SWKNOB03", "SWKNOB04", 2, sfx_swknob }, - { "ALTSW01", "ALTSW02", 2, sfx_None }, - { "COMP25", "COMP28B", 2, sfx_bglass }, - { "COMP29", "COMP20B", 2, sfx_bglass }, - { "COMP33", "COMP50", 2, sfx_bglass }, - { "COMP42", "COMP51", 2, sfx_bglass }, - { "GODSCRN1", "GODSCRN2", 2, sfx_difool }, - { "ALIEN04", "ALIEN05", 2, sfx_None }, - { "CITADL04", "CITADL05", 2, sfx_None }, - { "SWITE03", "SWITE04", 2, sfx_None }, - { "SWTELP01", "SWTELP02", 2, sfx_None }, - { "BRNSCN01", "BRNSCN05", 2, sfx_firxpl }, -}; - -int switchlist[MAXSWITCHES * 2]; -int numswitches; -button_t buttonlist[MAXBUTTONS]; - -// -// P_InitSwitchList -// Only called at game initialization. -// -void P_InitSwitchList(void) -{ - int i, slindex, episode; - - // Note that this is called "episode" here but it's actually something - // quite different. As we progress from Shareware->Registered->Doom II - // we support more switch textures. - if (isregistered) - { - episode = 2; - } - else - { - episode = 1; - } - - slindex = 0; - - for (i = 0; i < arrlen(alphSwitchList); i++) - { - if (alphSwitchList[i].episode <= episode) - { - switchlist[slindex++] = - R_TextureNumForName(DEH_String(alphSwitchList[i].name1)); - switchlist[slindex++] = - R_TextureNumForName(DEH_String(alphSwitchList[i].name2)); - } - } - - numswitches = slindex / 2; - switchlist[slindex] = -1; -} - - -// -// P_StartButton -// Start a button counting down till it turns off. -// -void P_StartButton(line_t* line, bwhere_e w, int texture, int time) -{ - int i; - - // See if button is already pressed - for(i = 0; i < MAXBUTTONS; i++) - { - if(buttonlist[i].btimer && buttonlist[i].line == line) - return; - } - - - - for(i = 0; i < MAXBUTTONS; i++) - { - if(!buttonlist[i].btimer) - { - buttonlist[i].line = line; - buttonlist[i].where = w; - buttonlist[i].btexture = texture; - buttonlist[i].btimer = time; - buttonlist[i].soundorg = &line->frontsector->soundorg; - return; - } - } - - I_Error("P_StartButton: no button slots left!"); -} - - -// -// P_SpawnBrokenGlass -// villsa [STRIFE] new function -// -static void P_SpawnBrokenGlass(line_t* line) -{ - fixed_t x1; - fixed_t x2; - fixed_t y1; - fixed_t y2; - int i; - mobj_t* glass; - angle_t an; - - x1 = (line->v2->x + line->v1->x) / 2; - y1 = (line->v2->y + line->v1->y) / 2; - x2 = ((line->frontsector->soundorg.x - x1) / 5) + x1; - y2 = ((line->frontsector->soundorg.y - y1) / 5) + y1; - - for(i = 0; i < 7; i++) - { - glass = P_SpawnMobj(x2, y2, ONFLOORZ, MT_JUNK); - glass->z += (24*FRACUNIT); - glass->flags |= (MF_SHADOW|MF_MVIS); - - P_SetMobjState(glass, P_Random() % 3 + S_SHRD_03); // 284 - - an = ((P_Random() << 13) / 255); - - glass->angle = (an << ANGLETOFINESHIFT); - glass->momx = FixedMul(finecosine[an], (P_Random() & 3) << FRACBITS); - glass->momy = FixedMul(finesine[an], (P_Random() & 3) << FRACBITS); - glass->momz = (P_Random() & 7) << FRACBITS; - glass->tics += (P_Random() + 7) & 7; - } -} - - -// -// Function that changes wall texture. -// Tell it if switch is ok to use again (1=yes, it's a button). -// -void P_ChangeSwitchTexture(line_t* line, int useAgain) -{ - int texTop; - int texMid; - int texBot; - int i; - int sound; - boolean breakglass; // villsa [STRIFE] - switchlist_t* sl; // villsa [STRIFE] - - breakglass = false; // villsa [STRIFE] - - texTop = sides[line->sidenum[0]].toptexture; - texMid = sides[line->sidenum[0]].midtexture; - texBot = sides[line->sidenum[0]].bottomtexture; - - sound = sfx_swtchn; - - // villsa [STRIFE] check for linetype 182 (break glass) - if(line->special == 182) - { - line->flags &= ~ML_BLOCKING; - breakglass = true; - - if(useAgain) - { - // haleyjd 09/21/10: Corrected (>> 16 == next field) - texTop = 0; - texBot = 0; - } - - if(texMid) // haleyjd 09/21/10: Corrected (>> 16 == next field) - useAgain = 0; - - sound = sfx_bglass; - } - - if(!useAgain) - line->special = 0; - - for(i = 0; i < numswitches*2; i++) - { - sl = &alphSwitchList[i / 2]; // villsa [STRIFE] - - if(switchlist[i] == texTop) - { - // villsa [STRIFE] set sound - if(sl->sound) - sound = sl->sound; - - // haleyjd 20141026: [STRIFE]: Rogue fixed wrong sound origin - S_StartSound(&line->frontsector->soundorg, sound); - sides[line->sidenum[0]].toptexture = switchlist[i^1]; - - if(useAgain) - P_StartButton(line,top,switchlist[i],BUTTONTIME); - - if(breakglass) - P_SpawnBrokenGlass(line); - - return; - } - else - { - if(switchlist[i] == texMid) - { - // villsa [STRIFE] set sound - if(sl->sound) - sound = sl->sound; - - // haleyjd 20141026: [STRIFE]: Rogue fixed wrong sound origin - S_StartSound(&line->frontsector->soundorg, sound); - sides[line->sidenum[0]].midtexture = switchlist[i^1]; - - // villsa [STRIFE] affect second side of line - // BUG: will crash if 1S line is marked with TWOSIDED flag! - if(line->flags & ML_TWOSIDED) - sides[line->sidenum[1]].midtexture = switchlist[i^1]; - - if(useAgain) - P_StartButton(line, middle,switchlist[i],BUTTONTIME); - - // villsa [STRIFE]: Mines Transmitter hack - if(sound == sfx_firxpl) - { - breakglass = true; - - // give quest flag 29 to player - players[0].questflags |= QF_QUEST29; - - // give stamina/accuracy items - if(!netgame) - { - P_GiveItemToPlayer(players, SPR_TOKN, MT_TOKEN_STAMINA); - P_GiveItemToPlayer(players, SPR_TOKN, MT_TOKEN_NEW_ACCURACY); - } - - } - - // villsa [STRIFE] - if(breakglass || sound == sfx_bglass) - P_SpawnBrokenGlass(line); - - return; - } - else - { - if(switchlist[i] == texBot) - { - // villsa [STRIFE] set sound - if(sl->sound) - sound = sl->sound; - - // haleyjd 20141026: [STRIFE]: Rogue fixed wrong sound origin - S_StartSound(&line->frontsector->soundorg, sound); - sides[line->sidenum[0]].bottomtexture = switchlist[i^1]; - - if(useAgain) - P_StartButton(line, bottom,switchlist[i],BUTTONTIME); - - if(breakglass) - P_SpawnBrokenGlass(line); - - return; - } - } - } - } -} - -// -// P_MoveWall -// -// villsa [STRIFE] New function. -// Dynamically move a solid line. Unused in Strife -// -static void P_MoveWall(line_t *line, mobj_t *thing) -{ - vertex_t *v2; - vertex_t *v1; - fixed_t x; - fixed_t y; - - v1 = line->v1; - v2 = line->v2; - S_StartSound(thing, sfx_stnmov); - - if (line->dx) - { - if (thing->x >= v1->x) - { - v1->y -= (8 * FRACUNIT); - v2->y -= (8 * FRACUNIT); - } - else - { - v1->y += (8 * FRACUNIT); - v2->y += (8 * FRACUNIT); - } - } - else - { - if (thing->y >= v1->y) - { - v1->x -= (8 * FRACUNIT); - v2->x -= (8 * FRACUNIT); - } - else - { - v1->x += (8 * FRACUNIT); - v2->x += (8 * FRACUNIT); - } - } - - if (v1->x >= v2->x) - { - line->bbox[BOXLEFT] = v2->x; - x = v1->x; - } - else - { - line->bbox[BOXLEFT] = v1->x; - x = v2->x; - } - - line->bbox[BOXRIGHT] = x; - - if (v1->y >= v2->y) - { - line->bbox[BOXBOTTOM] = v2->y; - y = v1->y; - } - else - { - line->bbox[BOXBOTTOM] = v1->y; - y = v2->y; - } - - line->bbox[BOXTOP] = y; -} - -// villsa [STRIFE] -static char usemessage[92]; - -// -// P_UseSpecialLine -// Called when a thing uses a special line. -// Only the front sides of lines are usable. -// -boolean P_UseSpecialLine(mobj_t* thing, line_t* line, int side) -{ - // Err... - // Use the back sides of VERY SPECIAL lines... - if (side) - { - switch(line->special) - { - case 148: // haleyjd [STRIFE] - break; - - default: - return false; - } - } - - // Switches that other things can activate. - if (!thing->player) - { - // never open secret doors - if (line->flags & ML_SECRET) - return false; - - switch(line->special) - { - case 1: // MANUAL DOOR RAISE - case 31: // haleyjd [STRIFE] - case 144: // haleyjd [STRIFE] Manual sliding door - break; - - default: - return false; - break; - } - } - - // do something - switch(line->special) - { - // MANUALS - case 1: // Vertical Door - case 26: // DR ID Card - case 27: // DR Pass Card - case 28: // DR ID Badge - case 31: // Manual door open - case 32: // D1 ID Card - case 33: // D1 ID Badge - case 34: // D1 Pass Card - case 117: // Blazing door raise - case 118: // Blazing door open - case 156: // haleyjd [STRIFE] D1 Brass Key - case 157: // haleyjd [STRIFE] D1 Silver Key - case 158: // haleyjd [STRIFE] D1 Gold Key - case 159: // haleyjd [STRIFE] DR Gold Key - case 160: // haleyjd [STRIFE] DR Silver Key - case 161: // haleyjd [STRIFE] DR Brass Key - case 165: // villsa [STRIFE] That doesn't seem to work - case 166: // haleyjd [STRIFE] DR Hand Print - case 169: // haleyjd [STRIFE] DR Base Key - case 170: // haleyjd [STRIFE] DR Gov's Key - case 190: // haleyjd [STRIFE] DR Order Key - case 205: // villsa [STRIFE] Available in retail only - case 213: // haleyjd [STRIFE] DR Chalice - case 217: // haleyjd [STRIFE] DR Core Key - case 221: // haleyjd [STRIFE] DR Mauler Key - case 224: // haleyjd [STRIFE] DR Chapel Key - case 225: // haleyjd [STRIFE] DR Catacomb Key - case 232: // villsa [STRIFE] DR Oracle Pass - EV_VerticalDoor (line, thing); - break; - - // haleyjd: For the sake of our sanity, I have reordered all the line - // specials from this point down so that they are strictly in numeric - // order, and not divided up in a semi-arbitrary fashion. - - case 7: - // Build Stairs - [STRIFE] Verified unmodified - if (EV_BuildStairs(line,build8)) - P_ChangeSwitchTexture(line,0); - break; - - case 9: - // Change Donut - [STRIFE] Verified unmodified - if (EV_DoDonut(line)) - P_ChangeSwitchTexture(line,0); - break; - - case 11: - // Exit level - [STRIFE] Modified to take tag, etc. - P_ChangeSwitchTexture(line, 1); - if(levelTimer && levelTimeCount) - break; - G_ExitLevel(line->tag); - break; - - case 14: - // Raise Floor 32 and change texture - [STRIFE] Verified unmodified - if (EV_DoPlat(line, raiseAndChange,32)) - P_ChangeSwitchTexture(line,0); - break; - - case 15: - // Raise Floor 24 and change texture - if (EV_DoPlat(line, raiseAndChange,24)) - P_ChangeSwitchTexture(line,0); - break; - - case 18: - // Raise Floor to next highest floor - [STRIFE] Verified unmodified - if (EV_DoFloor(line, raiseFloorToNearest)) - P_ChangeSwitchTexture(line,0); - break; - - case 20: - // Raise Plat next highest floor and change texture - [STRIFE] Verified unmodified - if(EV_DoPlat(line, raiseToNearestAndChange, 0)) - P_ChangeSwitchTexture(line,0); - break; - - case 21: - // PlatDownWaitUpStay - [STRIFE] Verified unmodified - if (EV_DoPlat(line, downWaitUpStay,0)) - P_ChangeSwitchTexture(line,0); - break; - - case 23: - // Lower Floor to Lowest - [STRIFE] Verified unmodified - if (EV_DoFloor(line,lowerFloorToLowest)) - P_ChangeSwitchTexture(line,0); - break; - - case 29: - // Raise Door - [STRIFE] Verified unmodified - if (EV_DoDoor(line,vld_normal)) - P_ChangeSwitchTexture(line,0); - break; - - case 40: - // villsa [STRIFE] Split Open Door - if(EV_DoDoor(line, vld_splitOpen)) - P_ChangeSwitchTexture(line, 0); - break; // haleyjd - - case 41: - // Lower Ceiling to Floor - [STRIFE] Verified unmodified - if (EV_DoCeiling(line,lowerToFloor)) - P_ChangeSwitchTexture(line,0); - break; - - case 42: - // Close Door - [STRIFE] Verified unmodified - if (EV_DoDoor(line,vld_close)) - P_ChangeSwitchTexture(line,1); - break; - - case 43: - // Lower Ceiling to Floor - [STRIFE] Verified unmodified - if (EV_DoCeiling(line,lowerToFloor)) - P_ChangeSwitchTexture(line,1); - break; - - case 45: - // Lower Floor to Surrounding floor height - [STRIFE] Verified unmodified - if (EV_DoFloor(line,lowerFloor)) - P_ChangeSwitchTexture(line,1); - break; - - case 49: - // Ceiling Crush And Raise - [STRIFE] Verified unmodified - if (EV_DoCeiling(line,crushAndRaise)) - P_ChangeSwitchTexture(line,0); - break; - - case 50: - // Close Door - [STRIFE] Verified unmodified - if (EV_DoDoor(line,vld_close)) - P_ChangeSwitchTexture(line,0); - break; - - case 51: - // [STRIFE] Modifed into S1 Start Finale (was Secret Exit) - P_ChangeSwitchTexture(line,0); - G_StartFinale(); - break; - - case 55: - // Raise Floor Crush - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloorCrush)) - P_ChangeSwitchTexture(line,0); - break; - - case 60: - // Lower Floor to Lowest - [STRIFE] Verified unmodified - if (EV_DoFloor(line,lowerFloorToLowest)) - P_ChangeSwitchTexture(line,1); - break; - - case 61: - // Open Door - [STRIFE] Verified unmodified - if (EV_DoDoor(line,vld_open)) - P_ChangeSwitchTexture(line,1); - break; - - case 62: - // PlatDownWaitUpStay - [STRIFE] Verified unmodified - if (EV_DoPlat(line, downWaitUpStay,1)) - P_ChangeSwitchTexture(line,1); - break; - - case 63: - // Raise Door - [STRIFE] Verified unmodified - if (EV_DoDoor(line,vld_normal)) - P_ChangeSwitchTexture(line,1); - break; - - case 64: - // Raise Floor to ceiling - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloor)) - P_ChangeSwitchTexture(line,1); - break; - - case 65: - // Raise Floor Crush - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloorCrush)) - P_ChangeSwitchTexture(line,1); - break; - - case 66: - // Raise Floor 24 and change texture - [STRIFE] Verified unmodified - if (EV_DoPlat(line, raiseAndChange, 24)) - P_ChangeSwitchTexture(line,1); - break; - - case 67: - // Raise Floor 32 and change texture - [STRIFE] Verified unmodified - if (EV_DoPlat(line, raiseAndChange, 32)) - P_ChangeSwitchTexture(line,1); - break; - - case 68: - // Raise Plat to next highest floor and change texture - [STRIFE] Verified unmodified - if (EV_DoPlat(line, raiseToNearestAndChange, 0)) - P_ChangeSwitchTexture(line,1); - break; - - case 69: - // Raise Floor to next highest floor - [STRIFE] Verified unmodified - if (EV_DoFloor(line, raiseFloorToNearest)) - P_ChangeSwitchTexture(line,1); - break; - - case 70: - // Turbo Lower Floor - [STRIFE] Verified unmodified - if (EV_DoFloor(line,turboLower)) - P_ChangeSwitchTexture(line,1); - break; - - case 71: - // Turbo Lower Floor - [STRIFE] Verified unmodified - if (EV_DoFloor(line,turboLower)) - P_ChangeSwitchTexture(line,0); - break; - - case 101: - // Raise Floor - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloor)) - P_ChangeSwitchTexture(line,0); - break; - - case 102: - // Lower Floor to Surrounding floor height - [STRIFE] Verified unmodified - if (EV_DoFloor(line,lowerFloor)) - P_ChangeSwitchTexture(line,0); - break; - - case 103: - // Open Door - [STRIFE] Verified unmodified - if (EV_DoDoor(line,vld_open)) - P_ChangeSwitchTexture(line,0); - break; - - case 111: - // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified - if (EV_DoDoor (line,vld_blazeRaise)) - P_ChangeSwitchTexture(line,0); - break; - - case 112: - // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified - if (EV_DoDoor (line,vld_blazeOpen)) - P_ChangeSwitchTexture(line,0); - break; - - case 113: - // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified - if (EV_DoDoor (line,vld_blazeClose)) - P_ChangeSwitchTexture(line,0); - break; - - case 114: - // Blazing Door Raise (faster than TURBO!) - [STRIFE] Verified unmodified - if (EV_DoDoor (line,vld_blazeRaise)) - P_ChangeSwitchTexture(line,1); - break; - - case 115: - // Blazing Door Open (faster than TURBO!) - [STRIFE] Verified unmodified - if (EV_DoDoor (line,vld_blazeOpen)) - P_ChangeSwitchTexture(line,1); - break; - - case 116: - // Blazing Door Close (faster than TURBO!) - [STRIFE] Verified unmodified - if (EV_DoDoor (line,vld_blazeClose)) - P_ChangeSwitchTexture(line,1); - break; - - case 122: - // Blazing PlatDownWaitUpStay - [STRIFE] Verified unmodified - if(EV_DoPlat(line, blazeDWUS, 0)) - P_ChangeSwitchTexture(line,0); - break; - - case 123: - // Blazing PlatDownWaitUpStay - [STRIFE] Verified unmodified - if(EV_DoPlat(line, blazeDWUS, 0)) - P_ChangeSwitchTexture(line,1); - break; - - case 127: - // Build Stairs Turbo 16 - [STRIFE] Verified unmodified - if (EV_BuildStairs(line,turbo16)) - P_ChangeSwitchTexture(line,0); - break; - - case 131: - // Raise Floor Turbo - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloorTurbo)) - P_ChangeSwitchTexture(line,0); - break; - - case 132: - // Raise Floor Turbo - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloorTurbo)) - P_ChangeSwitchTexture(line,1); - break; - - case 133: // [STRIFE] TODO - which key is it? - case 135: // [STRIFE] TODO - which key is it? - case 137: // [STRIFE] TODO - which key is it? - if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) - P_ChangeSwitchTexture(line,0); - break; - - case 99: // [STRIFE] TODO: which key is it? - case 134: // [STRIFE] TODO: which key is it? - case 136: // [STRIFE] TODO: which key is it? - if (EV_DoLockedDoor (line,vld_blazeOpen,thing)) - P_ChangeSwitchTexture(line,1); - break; - - case 138: - // Light Turn On - [STRIFE] Verified unmodified - EV_LightTurnOn(line,255); - P_ChangeSwitchTexture(line,1); - break; - - case 139: - // Light Turn Off - [STRIFE] Verified unmodified - EV_LightTurnOn(line,35); - P_ChangeSwitchTexture(line,1); - break; - - case 140: - // Raise Floor 512 - [STRIFE] Verified unmodified - if (EV_DoFloor(line,raiseFloor512)) - P_ChangeSwitchTexture(line,0); - break; - - case 144: - // villsa [STRIFE] manual sliding door - EV_SlidingDoor(line, thing); - break; - - case 146: - // haleyjd 09/24/10: [STRIFE] S1 Build Stairs Down 16 (new type) - if(EV_BuildStairs(line, buildDown16)) - P_ChangeSwitchTexture(line, 0); - break; - - case 147: - // haleyjd 09/24/10: [STRIFE] S1 Clear Force Fields - if(EV_ClearForceFields(line)) - P_ChangeSwitchTexture(line, 0); - break; - - case 148: - // haleyjd 09/16/10: [STRIFE] using forcefields hurts - P_DamageMobj(thing, NULL, NULL, 16); - P_Thrust(thing->player, thing->angle + ANG180, 125*FRACUNIT/16); - break; - - case 151: // villsa [STRIFE] BlzOpenDoor Gold key - case 152: // [STRIFE] TODO: which key is it? - case 153: // [STRIFE] TODO: which key is it? - if(EV_DoLockedDoor(line, vld_blazeOpen, thing)) - P_ChangeSwitchTexture(line, 1); - break; - - case 154: - // villsa [STRIFE] plat lower wait rise if have gold key - if(thing->player->cards[key_GoldKey]) - { - if(EV_DoPlat(line, downWaitUpStay, 0)) - P_ChangeSwitchTexture(line, 1); - } - else - { - thing->player->message = DEH_String("You need a gold key"); - S_StartSound(thing, sfx_oof); - } - break; - - case 155: - // villsa [STRIFE] raise plat wait lower - if(EV_DoPlat(line, upWaitDownStay, 0)) - P_ChangeSwitchTexture(line, 1); - break; - - case 162: // [STRIFE] TODO: which key is it? - case 163: // [STRIFE] TODO: which key is it? - case 164: // villsa [STRIFE] BlzOpenDoor Gold key - case 167: // [STRIFE] TODO: which key is it? - if(EV_DoLockedDoor(line, vld_blazeOpen, thing)) - P_ChangeSwitchTexture(line, 0); - break; - - case 168: // [STRIFE] TODO: which key is it? - // haleyjd 09/25/10: [STRIFE] SR Blaze Open Door ???? Key - if(EV_DoLockedDoor(line, vld_blazeOpen, thing)) - P_ChangeSwitchTexture(line, 1); - break; - - case 171: // [STRIFE] TODO: which key is it? - // haleyjd 09/25/10: [STRIFE] S1 Open Door ???? Key - if(EV_DoLockedDoor(line, vld_open, thing)) - P_ChangeSwitchTexture(line, 0); - break; - - case 172: // [STRIFE] TODO: which key is it? - case 173: // [STRIFE] TODO: which key is it? - case 176: // [STRIFE] TODO: which key is it? - case 191: // [STRIFE] TODO: which key is it? - case 192: // [STRIFE] TODO: which key is it? - case 223: // [STRIFE] TODO: which key is it? - if(EV_DoLockedDoor(line, vld_normal, thing)) - P_ChangeSwitchTexture(line, 1); - break; - - case 177: - // villsa [STRIFE] plat lower wait rise if have power3 key - if(thing->player->cards[key_Power3Key]) - { - if(EV_DoPlat(line, downWaitUpStay, 0)) - P_ChangeSwitchTexture(line, 1); - } - else - { - thing->player->message = DEH_String("You don't have the key"); - S_StartSound(thing, sfx_oof); - } - break; - - case 181: - // haleyjd 09/25/10: [STRIFE] S1 Floor Raise 512 & Change - if(EV_DoFloor(line, raiseFloor512AndChange)) - P_ChangeSwitchTexture(line, 0); - break; - - case 189: // [STRIFE] TODO: which key is it??? - // haleyjd 09/25/10: [STRIFE] S1 Split Open Door ???? Key - if(EV_DoLockedDoor(line, vld_splitOpen, thing)) - P_ChangeSwitchTexture(line, 0); - break; - - case 194: - // villsa [STRIFE] S1 Free Prisoners - if(EV_DoDoor(line, vld_open)) - { - P_ChangeSwitchTexture(line, 0); - P_FreePrisoners(); - } - break; - - case 199: - // haleyjd 09/25/10: [STRIFE] S1 Destroy Converter - if(EV_DoCeiling(line, lowerAndCrush)) - { - P_ChangeSwitchTexture(line, 0); - P_DestroyConverter(); - } - break; - - case 207: - // villsa [STRIFE] SR Remote Sliding Door - if(EV_RemoteSlidingDoor(line, thing)) - P_ChangeSwitchTexture(line, 1); - break; // haleyjd - - case 209: - // haleyjd 09/24/10: [STRIFE] S1 Build Stairs Down 16 if Have Chalice - if(!P_PlayerHasItem(thing->player, MT_INV_CHALICE)) - { - DEH_snprintf(usemessage, sizeof(usemessage), "You need the chalice!"); - thing->player->message = usemessage; - S_StartSound(thing, sfx_oof); - break; - } - else if(EV_BuildStairs(line, buildDown16)) - P_ChangeSwitchTexture(line, 0); - break; - - case 211: - // villsa [STRIFE] S1 Play VOC## sound - if(&players[consoleplayer] == thing->player && - thing->player->powers[pw_communicator]) - { - DEH_snprintf(usemessage, sizeof(usemessage), "voc%i", line->tag); - I_StartVoice(usemessage); - line->special = 0; - } - break; - - case 214: - // villsa [STRIFE] S1 slow lift lower wait up stay - if(EV_DoPlat(line, slowDWUS, 1)) - P_ChangeSwitchTexture(line, 1); - break; - - case 219: - // haleyjd 09/25/10: S1 Lower Floor Blue Crystal - if(!thing->player->cards[key_BlueCrystalKey]) - { - thing->player->message = DEH_String("You need the Blue Crystal"); - S_StartSound(thing, sfx_oof); - } - else if(EV_DoFloor(line, lowerFloor)) - P_ChangeSwitchTexture(line, 0); - break; - - case 220: - // haleyjd 09/25/10: S1 Lower Floor Red Crystal - if(!thing->player->cards[key_RedCrystalKey]) - { - thing->player->message = DEH_String("You need the Red Crystal"); - S_StartSound(thing, sfx_oof); - } - else if(EV_DoFloor(line, lowerFloor)) - P_ChangeSwitchTexture(line, 0); - break; - - case 226: - // villsa [STRIFE] S1 Complete Training Area - if(EV_DoFloor(line, lowerFloor)) - { - P_GiveItemToPlayer(thing->player, SPR_TOKN, MT_TOKEN_STAMINA); - P_GiveItemToPlayer(thing->player, SPR_TOKN, MT_TOKEN_NEW_ACCURACY); - P_ChangeSwitchTexture(line, 0); - DEH_snprintf(usemessage, sizeof(usemessage), - "Congratulations! You have completed the training area."); - thing->player->message = usemessage; - } - break; - - case 229: - // villsa [STRIFE] SR Sigil Sliding Door - if(thing->player->sigiltype == 4) - { - if(EV_RemoteSlidingDoor(line, thing)) - P_ChangeSwitchTexture(line, 1); - } - break; // haleyjd - - case 233: - // villsa [STRIFE] objective given after revealing the computer - if(!EV_DoDoor(line, vld_splitOpen)) - return true; - - P_ChangeSwitchTexture(line, 1); - GiveVoiceObjective("voc70", "log70", 0); - - // haleyjd: Strife used sprintf here, not a direct set. - DEH_snprintf(usemessage, sizeof(usemessage), - "Incoming Message from BlackBird..."); - thing->player->message = usemessage; - - break; - - case 234: - // haleyjd 09/24/10: [STRIFE] SR Raise Door if Quest 3 - if(!(thing->player->questflags & QF_QUEST3)) // QUEST3 == Irale - { - // BUG: doesn't make sfx_oof sound like all other message- - // giving door types. I highly doubt this was intentional. - DEH_snprintf(usemessage, sizeof(usemessage), - "That doesn't seem to work!"); - thing->player->message = usemessage; - } - else if(EV_DoDoor(line, vld_normal)) - P_ChangeSwitchTexture(line, 1); - break; - - case 235: - // haleyjd 09/25/10: [STRIFE] S1 Split Open Door if Have Sigil 4 - if(thing->player->sigiltype == 4) - { - if(EV_DoDoor(line, vld_splitOpen)) - P_ChangeSwitchTexture(line, 0); - } - break; - - case 666: - // villsa [STRIFE] SR Move Wall - P_MoveWall(line, thing); - break; - } - - return true; -} - diff --git a/games/NXDoom/src/strife/p_telept.c b/games/NXDoom/src/strife/p_telept.c deleted file mode 100644 index aff3b0c3b12..00000000000 --- a/games/NXDoom/src/strife/p_telept.c +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Teleportation. -// - - - - -#include "doomdef.h" -#include "doomstat.h" - -#include "s_sound.h" - -#include "p_local.h" - - -// Data. -#include "sounds.h" - -// State. -#include "r_state.h" - - - -// -// TELEPORTATION -// -// haleyjd 09/22/10: [STRIFE] Modified to take a flags parameter to control -// silent teleportation. Rogue also removed the check for missiles, and the -// z-set was replaced with one in P_TeleportMove. -// -int -EV_Teleport -( line_t* line, - int side, - mobj_t* thing, - teleflags_e flags) -{ - int i; - int tag; - mobj_t* m; - mobj_t* fog = NULL; - unsigned an; - thinker_t* thinker; - sector_t* sector; - fixed_t oldx; - fixed_t oldy; - fixed_t oldz; - - // haleyjd 20110205 [STRIFE]: this is not checked here - // don't teleport missiles - //if (thing->flags & MF_MISSILE) - // return 0; - - // Don't teleport if hit back of line, - // so you can get out of teleporter. - if (side == 1) - return 0; - - tag = line->tag; - for (i = 0; i < numsectors; i++) - { - if (sectors[ i ].tag == tag ) - { - for (thinker = thinkercap.next; - thinker != &thinkercap; - thinker = thinker->next) - { - // not a mobj - if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - m = (mobj_t *)thinker; - - // not a teleportman - if (m->type != MT_TELEPORTMAN ) - continue; - - sector = m->subsector->sector; - // wrong sector - if (sector-sectors != i ) - continue; - - oldx = thing->x; - oldy = thing->y; - oldz = thing->z; - - if (!P_TeleportMove (thing, m->x, m->y)) - return 0; - - // fraggle: this was changed in final doom, - // problem between normal doom2 1.9 and final doom - // - // Note that although chex.exe is based on Final Doom, - // it does not have this quirk. - // - // haleyjd 20110205 [STRIFE] This code is *not* present, - // because of a z-set which Rogue added to P_TeleportMove. - /* - if (gameversion < exe_final || gameversion == exe_chex) - thing->z = thing->floorz; - */ - - if (thing->player) - thing->player->viewz = thing->z+thing->player->viewheight; - - // spawn teleport fog at source and destination - // haleyjd 09/22/10: [STRIFE] controlled by teleport flags - // BUG: Behavior would be undefined if this function were passed - // any combination of teleflags that has the NO*FOG but not the - // corresponding NO*SND flag - fortunately this is never done - // anywhere in the code. - if(!(flags & TF_NOSRCFOG)) - fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); - if(!(flags & TF_NOSRCSND)) - S_StartSound (fog, sfx_telept); - - an = m->angle >> ANGLETOFINESHIFT; - - if(!(flags & TF_NODSTFOG)) - fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an], - thing->z, MT_TFOG); - if(!(flags & TF_NODSTSND)) - S_StartSound (fog, sfx_telept); - - // don't move for a bit - if (thing->player) - thing->reactiontime = 18; - - thing->angle = m->angle; - thing->momx = thing->momy = thing->momz = 0; - return 1; - } - } - } - return 0; -} - diff --git a/games/NXDoom/src/strife/p_tick.c b/games/NXDoom/src/strife/p_tick.c deleted file mode 100644 index 3c6caa06c21..00000000000 --- a/games/NXDoom/src/strife/p_tick.c +++ /dev/null @@ -1,160 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Archiving: SaveGame I/O. -// Thinker, Ticker. -// - - -#include "z_zone.h" -#include "p_local.h" - -#include "doomstat.h" - - -int leveltime; - -// -// THINKERS -// All thinkers should be allocated by Z_Malloc -// so they can be operated on uniformly. -// The actual structures will vary in size, -// but the first element must be thinker_t. -// - - - -// Both the head and tail of the thinker list. -thinker_t thinkercap; - - -// -// P_InitThinkers -// -// [STRIFE] Verified unmodified -// -void P_InitThinkers (void) -{ - thinkercap.prev = thinkercap.next = &thinkercap; -} - - - - -// -// P_AddThinker -// Adds a new thinker at the end of the list. -// -// [STRIFE] Verified unmodified -// -void P_AddThinker (thinker_t* thinker) -{ - thinkercap.prev->next = thinker; - thinker->next = &thinkercap; - thinker->prev = thinkercap.prev; - thinkercap.prev = thinker; -} - - - -// -// P_RemoveThinker -// Deallocation is lazy -- it will not actually be freed -// until its thinking turn comes up. -// -// [STRIFE] Verified unmodified -// -void P_RemoveThinker (thinker_t* thinker) -{ - // FIXME: NOP. - thinker->function.acv = (actionf_v)(-1); -} - - - -// -// P_AllocateThinker -// Allocates memory and adds a new thinker at the end of the list. -// -void P_AllocateThinker (thinker_t* thinker) -{ -} - -// -// P_RunThinkers -// -// [STRIFE] Verified unmodified -// -void P_RunThinkers (void) -{ - thinker_t *currentthinker, *nextthinker; - - currentthinker = thinkercap.next; - while (currentthinker != &thinkercap) - { - if ( currentthinker->function.acv == (actionf_v)(-1) ) - { - // time to remove it - nextthinker = currentthinker->next; - currentthinker->next->prev = currentthinker->prev; - currentthinker->prev->next = currentthinker->next; - Z_Free (currentthinker); - } - else - { - if (currentthinker->function.acp1) - currentthinker->function.acp1 (currentthinker); - nextthinker = currentthinker->next; - } - - currentthinker = nextthinker; - } -} - -// -// P_Ticker -// -// [STRIFE] Menu pause behavior modified -// -void P_Ticker (void) -{ - int i; - - // run the tic - if (paused) - return; - - // pause if in menu and at least one tic has been run - // haleyjd 09/08/10 [STRIFE]: menuactive -> menupause - if (!netgame - && menupause - && !demoplayback - && players[consoleplayer].viewz != 1) - { - return; - } - - - for (i=0 ; i - -#include "doomdef.h" -#include "d_event.h" -#include "p_local.h" -#include "sounds.h" // villsa [STRIFE] -#include "p_dialog.h" // villsa [STRIFE] -#include "d_main.h" // villsa [STRIFE] -#include "doomstat.h" -#include "deh_str.h" // haleyjd [STRIFE] -#include "z_zone.h" -#include "w_wad.h" -#include "p_pspr.h" -#include "m_misc.h" -#include "m_random.h" -#include "s_sound.h" -#include "p_inter.h" - - - -// Index of the special effects (INVUL inverse) map. -#define LOOKPITCHAMOUNT 6 // villsa [STRIFE] -#define CENTERVIEWAMOUNT (LOOKPITCHAMOUNT + 2) // villsa [STRIFE] -#define LOOKUPMAX 90 // villsa [STRIFE] -#define LOOKDOWNMAX -110 // villsa [STRIFE] - - -void P_DropInventoryItem(player_t* player, int sprite); // villsa [STRIFE] -boolean P_ItemBehavior(player_t* player, int item); // villsa [STRIFE] -static char useinventorymsg[44]; // villsa [STRIFE] - -// -// Movement. -// - -// 16 pixels of bob -#define MAXBOB 0x100000 - -boolean onground; - - -// -// P_Thrust -// Moves the given origin along a given angle. -// -// [STRIFE] Verified unmodified -// -void -P_Thrust -( player_t* player, - angle_t angle, - fixed_t move ) -{ - angle >>= ANGLETOFINESHIFT; - - player->mo->momx += FixedMul(move,finecosine[angle]); - player->mo->momy += FixedMul(move,finesine[angle]); -} - - - - -// -// P_CalcHeight -// Calculate the walking / running height adjustment -// -// [STRIFE] Some odd adjustments, and terrain view height adjustment -// -void P_CalcHeight (player_t* player) -{ - int angle; - fixed_t bob; - - // Regular movement bobbing - // (needs to be calculated for gun swing - // even if not on ground) - // OPTIMIZE: tablify angle - // Note: a LUT allows for effects - // like a ramp with low health. - player->bob = - FixedMul (player->mo->momx, player->mo->momx) - + FixedMul (player->mo->momy,player->mo->momy); - - player->bob >>= 2; - - if (player->bob>MAXBOB) - player->bob = MAXBOB; - - // haleyjd 20110205 [STRIFE]: No CF_NOMOMENTUM check, and Rogue also removed - // the dead code inside. - if (!onground) - { - /* - player->viewz = player->mo->z + VIEWHEIGHT; - - if (player->viewz > player->mo->ceilingz-4*FRACUNIT) - player->viewz = player->mo->ceilingz-4*FRACUNIT; - */ - - player->viewz = player->mo->z + player->viewheight; - return; - } - - angle = (FINEANGLES/20*leveltime)&FINEMASK; - bob = FixedMul ( player->bob/2, finesine[angle]); - - // move viewheight - if (player->playerstate == PST_LIVE) - { - player->viewheight += player->deltaviewheight; - - if (player->viewheight > VIEWHEIGHT) - { - player->viewheight = VIEWHEIGHT; - player->deltaviewheight = 0; - } - - if (player->viewheight < VIEWHEIGHT/2) - { - player->viewheight = VIEWHEIGHT/2; - if (player->deltaviewheight <= 0) - player->deltaviewheight = 1; - } - - if (player->deltaviewheight) - { - player->deltaviewheight += FRACUNIT/4; - if (!player->deltaviewheight) - player->deltaviewheight = 1; - } - } - player->viewz = player->mo->z + player->viewheight + bob; - - // villsa [STRIFE] account for terrain lowering the view - if(player->mo->flags & MF_FEETCLIPPED) - player->viewz -= 13*FRACUNIT; - - if (player->viewz > player->mo->ceilingz-4*FRACUNIT) - player->viewz = player->mo->ceilingz-4*FRACUNIT; - - // haleyjd [STRIFE]: added a floorz clip here - if (player->viewz < player->mo->floorz) - player->viewz = player->mo->floorz; -} - - - -// -// P_MovePlayer -// -// [STRIFE] Adjustments to allow air control, jumping, and up/down look. -// -void P_MovePlayer (player_t* player) -{ - ticcmd_t* cmd; - - cmd = &player->cmd; - - player->mo->angle += (cmd->angleturn<<16); - - // Do not let the player control movement - // if not onground. - onground = (player->mo->z <= player->mo->floorz); - - // villsa [STRIFE] allows player to climb over things by jumping - // haleyjd 20110205: air control thrust should be 256, not cmd->forwardmove - if(!onground) - { - if(cmd->forwardmove) - P_Thrust (player, player->mo->angle, 256); - } - else - { - // villsa [STRIFE] jump button - if (cmd->buttons2 & BT2_JUMP) - { - if(!player->deltaviewheight) - player->mo->momz += 8*FRACUNIT; - } - - // haleyjd 20110205 [STRIFE] Either Rogue or Watcom removed the - // redundant "onground" checks from these if's. - if (cmd->forwardmove) - P_Thrust (player, player->mo->angle, cmd->forwardmove*2048); - - if (cmd->sidemove) - P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048); - } - - // villsa [STRIFE] player walking state set - if ( (cmd->forwardmove || cmd->sidemove) - && player->mo->state == &states[S_PLAY_00] ) - { - P_SetMobjState (player->mo, S_PLAY_01); - } - - // villsa [STRIFE] centerview button - if (cmd->buttons2 & BT2_CENTERVIEW) - player->centerview = 1; - - // villsa [STRIFE] adjust player's pitch when centerviewing - if (player->centerview) - { - if (player->pitch <= 0) - { - if (player->pitch < 0) - player->pitch = player->pitch + CENTERVIEWAMOUNT; - } - else - { - player->pitch = player->pitch - CENTERVIEWAMOUNT; - } - if (abs(player->pitch) < CENTERVIEWAMOUNT) - { - player->pitch = 0; - player->centerview = 0; - } - } - - // villsa [STRIFE] look up action - if (cmd->buttons2 & BT2_LOOKUP) - { - player->pitch += LOOKPITCHAMOUNT; - if (player->pitch > LOOKUPMAX || - player->pitch < LOOKDOWNMAX) - player->pitch -= LOOKPITCHAMOUNT; - } - else - { - // villsa [STRIFE] look down action - if (cmd->buttons2 & BT2_LOOKDOWN) - { - player->pitch -= LOOKPITCHAMOUNT; - if (player->pitch > LOOKUPMAX || - player->pitch < LOOKDOWNMAX) - player->pitch += LOOKPITCHAMOUNT; - } - } - -} - - - -// -// P_DeathThink -// Fall on your face when dying. -// Decrease POV height to floor height. -// -// [STRIFE] Modifications for up/down look. -// -#define ANG5 (ANG90/18) - -void P_DeathThink(player_t* player) -{ - angle_t angle; - angle_t delta; - - P_MovePsprites(player); - - // fall to the ground - if (player->viewheight > 6*FRACUNIT) - player->viewheight -= FRACUNIT; - - if (player->viewheight < 6*FRACUNIT) - player->viewheight = 6*FRACUNIT; - - player->deltaviewheight = 0; - onground = (player->mo->z <= player->mo->floorz); - P_CalcHeight(player); - - if(player->attacker && player->attacker != player->mo) - { - angle = R_PointToAngle2 (player->mo->x, - player->mo->y, - player->attacker->x, - player->attacker->y); - - delta = angle - player->mo->angle; - - if (delta < ANG5 || delta > (unsigned)-ANG5) - { - // Looking at killer, - // so fade damage flash down. - player->mo->angle = angle; - - if (player->damagecount) - player->damagecount--; - } - else if (delta < ANG180) - player->mo->angle += ANG5; - else - player->mo->angle -= ANG5; - } - else if (player->damagecount) - player->damagecount--; - - // villsa [STRIFE] - if(player->pitch <= 90) - player->pitch = player->pitch + 3; - - if(player->cmd.buttons & BT_USE) - player->playerstate = PST_REBORN; -} - - - -// -// P_PlayerThink -// -// [STRIFE] Massive changes/additions: -// * NOCLIP hack removed -// * P_DeathThink moved up -// * Inventory use/dropping -// * Strife weapons logic -// * Dialog -// * Strife powerups and nukage behavior -// * Fire Death/Sigil Shock -// -void P_PlayerThink (player_t* player) -{ - ticcmd_t* cmd; - weapontype_t newweapon; - - // villsa [STRIFE] unused code (see ST_Responder) - /* - // fixme: do this in the cheat code - if (player->cheats & CF_NOCLIP) - player->mo->flags |= MF_NOCLIP; - else - player->mo->flags &= ~MF_NOCLIP; - */ - - // haleyjd 20110205 [STRIFE]: P_DeathThink moved up - if (player->playerstate == PST_DEAD) - { - P_DeathThink (player); - return; - } - - // chain saw run forward - cmd = &player->cmd; - if (player->mo->flags & MF_JUSTATTACKED) - { - cmd->angleturn = 0; - cmd->forwardmove = 0xc800/512; - cmd->sidemove = 0; - player->mo->flags &= ~MF_JUSTATTACKED; - } - - // Move around. - // Reactiontime is used to prevent movement - // for a bit after a teleport. - if (player->mo->reactiontime) - player->mo->reactiontime--; - else - P_MovePlayer (player); - - P_CalcHeight (player); - - if (player->mo->subsector->sector->special) - P_PlayerInSpecialSector (player); - - // villsa [STRIFE] handle inventory input - if(cmd->buttons2 & (BT2_HEALTH|BT2_INVUSE|BT2_INVDROP)) - { - if(!player->inventorydown) - { - if(cmd->buttons2 & BT2_HEALTH) - P_UseInventoryItem(player, SPR_FULL); - else if(cmd->buttons2 & BT2_INVUSE) - P_UseInventoryItem(player, cmd->inventory); - else if(cmd->buttons2 & BT2_INVDROP) - { - P_DropInventoryItem(player, cmd->inventory); - - // haleyjd 20110205: removed incorrect "else" here - // villsa [STRIFE] - if(workparm) - { - int cheat = player->cheats ^ 1; - player->cheats ^= CF_NOCLIP; - - if(cheat & CF_NOCLIP) - { - player->message = DEH_String("No Clipping Mode ON"); - player->mo->flags |= MF_NOCLIP; - } - else - { - player->mo->flags &= ~MF_NOCLIP; - player->message = DEH_String("No Clipping Mode OFF"); - } - } - } - } - - player->inventorydown = true; - } - else - player->inventorydown = false; - - // Check for weapon change. - - // A special event has no other buttons. - if(cmd->buttons & BT_SPECIAL) - cmd->buttons = 0; - - if(cmd->buttons & BT_CHANGE) - { - // The actual changing of the weapon is done - // when the weapon psprite can do it - // (read: not in the middle of an attack). - newweapon = (cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT; - - // villsa [STRIFE] select poison bow - if(newweapon == wp_elecbow) - { - if(player->weaponowned[wp_poisonbow] && player->readyweapon == wp_elecbow) - { - if(player->ammo[weaponinfo[wp_poisonbow].ammo]) - newweapon = wp_poisonbow; - } - } - - // villsa [STRIFE] select wp grenade launcher - if(newweapon == wp_hegrenade) - { - if(player->weaponowned[wp_wpgrenade] && player->readyweapon == wp_hegrenade) - { - if(player->ammo[weaponinfo[wp_wpgrenade].ammo]) - newweapon = wp_wpgrenade; - } - } - - // villsa [STRIFE] select torpedo - if(newweapon == wp_mauler) - { - if(player->weaponowned[wp_torpedo] && player->readyweapon == wp_mauler) - { - // haleyjd 20140924: bug fix - using wrong enum value am_cell - // caused this to check the missile launcher for rocket ammo - if(player->ammo[weaponinfo[wp_torpedo].ammo] >= 30) - newweapon = wp_torpedo; - } - } - - if(player->weaponowned[newweapon] && newweapon != player->readyweapon) - { - // villsa [STRIFE] check weapon if in demo mode or not - if(weaponinfo[newweapon].availabledemo || !isdemoversion) - { - if(player->ammo[weaponinfo[newweapon].ammo]) - player->pendingweapon = newweapon; - else - { - // decide between electric bow or poison arrow - if(newweapon == wp_elecbow && - player->ammo[am_poisonbolts] && - player->readyweapon != wp_poisonbow) - { - player->pendingweapon = wp_poisonbow; - } - // decide between hp grenade launcher or wp grenade launcher - else if(newweapon == wp_hegrenade && - player->ammo[am_wpgrenades] && - player->readyweapon != wp_wpgrenade) - { - player->pendingweapon = wp_wpgrenade; - } - - // villsa [STRIFE] - no check for mauler/torpedo?? - } - } - } - } - - // check for use - if(cmd->buttons & BT_USE) - { - if(!player->usedown) - { - P_DialogStart(player); // villsa [STRIFE] - P_UseLines (player); - player->usedown = true; - } - } - else - player->usedown = false; - - // cycle psprites - P_MovePsprites (player); - - // Counters, time dependend power ups. - - // Strength counts up to diminish fade. - if (player->powers[pw_strength]) - player->powers[pw_strength]++; - - // villsa [STRIFE] targeter powerup - if(player->powers[pw_targeter]) - { - player->powers[pw_targeter]--; - if(player->powers[pw_targeter] == 1) - { - P_SetPsprite(player, ps_targcenter, S_NULL); - P_SetPsprite(player, ps_targleft, S_NULL); - P_SetPsprite(player, ps_targright, S_NULL); - } - else if(player->powers[pw_targeter] - 1 < 5*TICRATE) - { - if(player->powers[pw_targeter] & 32) - { - P_SetPsprite(player, ps_targright, S_NULL); - P_SetPsprite(player, ps_targleft, S_TRGT_01); // 11 - } - else if(player->powers[pw_targeter] & 16) // haleyjd 20110205: missing else - { - P_SetPsprite(player, ps_targright, S_TRGT_02); // 12 - P_SetPsprite(player, ps_targleft, S_NULL); - } - } - } - - if(player->powers[pw_invisibility]) - { - // villsa [STRIFE] remove mvis flag as well - if(!--player->powers[pw_invisibility]) - player->mo->flags &= ~(MF_SHADOW|MF_MVIS); - } - - if(player->powers[pw_ironfeet]) - { - player->powers[pw_ironfeet]--; - - // villsa [STRIFE] gasmask sound - if(!(leveltime & 0x3f)) - S_StartSound(player->mo, sfx_mask); - } - - if(player->powers[pw_allmap] > 1) - player->powers[pw_allmap]--; - - // haleyjd 08/30/10: [STRIFE] - // Nukage count keeps track of exposure to hazardous conditions over time. - // After accumulating 16 total seconds or more of exposure, you will take - // 5 damage roughly once per second until the count drops back under 560 - // tics. - if(player->nukagecount) - { - player->nukagecount--; - if(!(leveltime & 0x1f) && player->nukagecount > 16*TICRATE) - P_DamageMobj(player->mo, NULL, NULL, 5); - } - - if(player->damagecount) - player->damagecount--; - - if(player->bonuscount) - player->bonuscount--; - - // villsa [STRIFE] checks for extralight - if(player->extralight >= 0) - { - if(player->cheats & CF_ONFIRE) - player->fixedcolormap = 1; - else - player->fixedcolormap = 0; - } - else // Sigil shock: - player->fixedcolormap = INVERSECOLORMAP; -} - - -// -// P_RemoveInventoryItem -// villsa [STRIFE] new function -// -const char* P_RemoveInventoryItem(player_t *player, int slot, int amount) -{ - mobjtype_t type; - - player->inventory[slot].amount -= amount; - player->st_update = true; - - type = player->inventory[slot].type; - - if(!player->inventory[slot].amount) - { - // shift everything above it down - // see P_TakeDialogItem for notes on possible bugs - int j; - - for(j = slot + 1; j <= player->numinventory; j++) - { - inventory_t *item1 = &(player->inventory[j - 1]); - inventory_t *item2 = &(player->inventory[j]); - - *item1 = *item2; - } - - player->inventory[player->numinventory].type = NUMMOBJTYPES; - player->inventory[player->numinventory].sprite = -1; - player->numinventory--; - - // update cursor position - if(player->inventorycursor >= player->numinventory) - { - if(player->inventorycursor) - player->inventorycursor--; - } - } - - return mobjinfo[type].name; -} - -// -// P_DropInventoryItem -// villsa [STRIFE] new function -// -void P_DropInventoryItem(player_t* player, int sprite) -{ - int invslot; - inventory_t *item; - mobjtype_t type; - int amount; - - invslot = 0; - amount = 1; - - while(invslot < player->numinventory && sprite != player->inventory[invslot].sprite) - invslot++; - - item = &(player->inventory[invslot]); - type = item->type; - - if(item->amount) - { - angle_t angle; - fixed_t dist; - mobj_t* mo; - mobj_t* mobjitem; - fixed_t x; - fixed_t y; - fixed_t z; - int r; - - if(item->type == MT_MONY_1) - { - if(item->amount >= 50) - { - type = MT_MONY_50; - amount = 50; - } - else if(item->amount >= 25) - { - type = MT_MONY_25; - amount = 25; - } - else if(item->amount >= 10) - { - type = MT_MONY_10; - amount = 10; - } - } - - if(type >= NUMMOBJTYPES) - return; - - angle = player->mo->angle; - r = P_Random(); - angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT; - - if(angle < 7618 && angle >= 6718) - angle = 7618; - - else if(angle < 5570 && angle >= 4670) - angle = 5570; - - else if(angle < 3522 && angle >= 2622) - angle = 3522; - - else if(angle < 1474 && angle >= 574) - angle = 1474; - - mo = player->mo; - dist = mobjinfo[type].radius + mo->info->radius + (4*FRACUNIT); - - x = mo->x + FixedMul(finecosine[angle], dist); - y = mo->y + FixedMul(finesine[angle], dist); - z = mo->z + (10*FRACUNIT); - mobjitem = P_SpawnMobj(x, y, z, type); - mobjitem->flags |= (MF_SPECIAL|MF_DROPPED); - - if(P_CheckPosition(mobjitem, x, y)) - { - mobjitem->angle = (angle << ANGLETOFINESHIFT); - mobjitem->momx = FixedMul(finecosine[angle], (5*FRACUNIT)) + mo->momx; - mobjitem->momy = FixedMul(finesine[angle], (5*FRACUNIT)) + mo->momy; - mobjitem->momz = FRACUNIT; - - P_RemoveInventoryItem(player, invslot, amount); - } - else - P_RemoveMobj(mobjitem); - } -} - -// -// P_TossDegninOre -// villsa [STRIFE] new function -// -boolean P_TossDegninOre(player_t* player) -{ - angle_t angle; - mobj_t* mo; - mobj_t* ore; - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t dist; - - angle = player->mo->angle >> ANGLETOFINESHIFT; - - if(angle < 7618 && angle >= 6718) - angle = 7618; - - else if(angle < 5570 && angle >= 4670) - angle = 5570; - - else if(angle < 3522 && angle >= 2622) - angle = 3522; - - else if(angle < 1474 && angle >= 574) - angle = 1474; - - mo = player->mo; - dist = mobjinfo[MT_DEGNINORE].radius + mo->info->radius + (4*FRACUNIT); - - x = mo->x + FixedMul(finecosine[angle], dist); - y = mo->y + FixedMul(finesine[angle], dist); - z = mo->z + (10*FRACUNIT); - ore = P_SpawnMobj(x, y, z, MT_DEGNINORE); - - if(P_CheckPosition(ore, x, y)) - { - ore->target = mo; - ore->angle = (angle << ANGLETOFINESHIFT); - ore->momx = FixedMul(finecosine[angle], (5*FRACUNIT)); - ore->momy = FixedMul(finesine[angle], (5*FRACUNIT)); - ore->momz = FRACUNIT; - return true; - } - else - P_RemoveMobj(ore); - - return false; -} - -// -// P_SpawnTeleportBeacon -// -// villsa [STRIFE] new function -// haleyjd 20140918: bug fixed to propagate allegiance properly. -// -boolean P_SpawnTeleportBeacon(player_t* player) -{ - angle_t angle; - int r; - mobj_t* mo; - mobj_t* beacon; - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t dist; - - angle = player->mo->angle; - r = P_Random(); - angle = (angle + ((r - P_Random()) << 18)) >> ANGLETOFINESHIFT; - - if(angle < 7618 && angle >= 6718) - angle = 7618; - - else if(angle < 5570 && angle >= 4670) - angle = 5570; - - else if(angle < 3522 && angle >= 2622) - angle = 3522; - - else if(angle < 1474 && angle >= 574) - angle = 1474; - - mo = player->mo; - dist = mobjinfo[MT_BEACON].radius + mo->info->radius + (4*FRACUNIT); - - x = mo->x + FixedMul(finecosine[angle], dist); - y = mo->y + FixedMul(finesine[angle], dist); - z = mo->z + (10*FRACUNIT); - beacon = P_SpawnMobj(x, y, z, MT_BEACON); - - if(P_CheckPosition(beacon, x, y)) - { - beacon->target = mo; - beacon->miscdata = (byte)(player->allegiance); - beacon->angle = (angle << ANGLETOFINESHIFT); - beacon->momx = FixedMul(finecosine[angle], (5*FRACUNIT)); - beacon->momy = FixedMul(finesine[angle], (5*FRACUNIT)); - beacon->momz = FRACUNIT; - P_SetMobjState(beacon, beacon->info->seestate); - return true; - } - else - P_RemoveMobj(beacon); - - return false; -} - -// -// P_UseInventoryItem -// villsa [STRIFE] new function -// -boolean P_UseInventoryItem(player_t* player, int item) -{ - int i; - const char *name; - - if(player->cheats & CF_ONFIRE) - return false; - - for(i = 0; i < player->numinventory; i++) - { - if(item != player->inventory[i].sprite) - continue; - - if(!P_ItemBehavior(player, item)) - return false; - - name = P_RemoveInventoryItem(player, i, 1); - if(name == NULL) - name = "Item"; - - M_snprintf(useinventorymsg, sizeof(useinventorymsg), - "You used the %s.", name); - player->message = useinventorymsg; - - if(player == &players[consoleplayer]) - S_StartSound(NULL, sfx_itemup); - - return true; - } - - return false; -} - -// -// P_ItemBehavior -// villsa [STRIFE] new function -// -boolean P_ItemBehavior(player_t* player, int item) -{ - switch(item) - { - case SPR_ARM1: // 136 - return P_GiveArmor(player, 2); - - case SPR_ARM2: // 137 - return P_GiveArmor(player, 1); - - case SPR_SHD1: // 186 - return P_GivePower(player, pw_invisibility); - - case SPR_MASK: // 187 - return P_GivePower(player, pw_ironfeet); - - case SPR_PMUP: // 191 - if(!player->powers[pw_allmap]) - { - player->message = "The scanner won't work without a map!"; - return false; - } - player->powers[pw_allmap] = PMUPTICS; - return true; // haleyjd 20110228: repaired - - case SPR_STMP: // 180 - return P_GiveBody(player, 10); - - case SPR_MDKT: // 181 - return P_GiveBody(player, 25); - - case SPR_FULL: // 130 - return P_GiveBody(player, 200); - - case SPR_BEAC: // 135 - return P_SpawnTeleportBeacon(player); - - case SPR_TARG: // 108 - return P_GivePower(player, pw_targeter); - } - - return false; -} diff --git a/games/NXDoom/src/strife/r_bsp.c b/games/NXDoom/src/strife/r_bsp.c deleted file mode 100644 index 64b9d5dfe58..00000000000 --- a/games/NXDoom/src/strife/r_bsp.c +++ /dev/null @@ -1,583 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// BSP traversal, handling of LineSegs for rendering. -// - - - - -#include "doomdef.h" - -#include "m_bbox.h" - -#include "i_system.h" - -#include "r_main.h" -#include "r_plane.h" -#include "r_things.h" - -// State. -#include "doomstat.h" -#include "r_state.h" - -//#include "r_local.h" - - - -seg_t* curline; -side_t* sidedef; -line_t* linedef; -sector_t* frontsector; -sector_t* backsector; - -drawseg_t drawsegs[MAXDRAWSEGS]; -drawseg_t* ds_p; - - -void -R_StoreWallRange -( int start, - int stop ); - - - - -// -// R_ClearDrawSegs -// -void R_ClearDrawSegs (void) -{ - ds_p = drawsegs; -} - - - -// -// ClipWallSegment -// Clips the given range of columns -// and includes it in the new clip list. -// -typedef struct -{ - int first; - int last; - -} cliprange_t; - -// We must expand MAXSEGS to the theoretical limit of the number of solidsegs -// that can be generated in a scene by the DOOM engine. This was determined by -// Lee Killough during BOOM development to be a function of the screensize. -// The simplest thing we can do, other than fix this bug, is to let the game -// render overage and then bomb out by detecting the overflow after the -// fact. -haleyjd -//#define MAXSEGS 32 -#define MAXSEGS (SCREENWIDTH / 2 + 1) - -// newend is one past the last valid seg -cliprange_t* newend; -cliprange_t solidsegs[MAXSEGS]; - - - - -// -// R_ClipSolidWallSegment -// Does handle solid walls, -// e.g. single sided LineDefs (middle texture) -// that entirely block the view. -// -void -R_ClipSolidWallSegment -( int first, - int last ) -{ - cliprange_t* next; - cliprange_t* start; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = solidsegs; - while (start->last < first-1) - start++; - - if (first < start->first) - { - if (last < start->first-1) - { - // Post is entirely visible (above start), - // so insert a new clippost. - R_StoreWallRange (first, last); - next = newend; - newend++; - - while (next != start) - { - *next = *(next-1); - next--; - } - next->first = first; - next->last = last; - return; - } - - // There is a fragment above *start. - R_StoreWallRange (first, start->first - 1); - // Now adjust the clip size. - start->first = first; - } - - // Bottom contained in start? - if (last <= start->last) - return; - - next = start; - while (last >= (next+1)->first-1) - { - // There is a fragment between two posts. - R_StoreWallRange (next->last + 1, (next+1)->first - 1); - next++; - - if (last <= next->last) - { - // Bottom is contained in next. - // Adjust the clip size. - start->last = next->last; - goto crunch; - } - } - - // There is a fragment after *next. - R_StoreWallRange (next->last + 1, last); - // Adjust the clip size. - start->last = last; - - // Remove start+1 to next from the clip list, - // because start now covers their area. - crunch: - if (next == start) - { - // Post just extended past the bottom of one post. - return; - } - - - while (next++ != newend) - { - // Remove a post. - *++start = *next; - } - - newend = start+1; -} - - - -// -// R_ClipPassWallSegment -// Clips the given range of columns, -// but does not includes it in the clip list. -// Does handle windows, -// e.g. LineDefs with upper and lower texture. -// -void -R_ClipPassWallSegment -( int first, - int last ) -{ - cliprange_t* start; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = solidsegs; - while (start->last < first-1) - start++; - - if (first < start->first) - { - if (last < start->first-1) - { - // Post is entirely visible (above start). - R_StoreWallRange (first, last); - return; - } - - // There is a fragment above *start. - R_StoreWallRange (first, start->first - 1); - } - - // Bottom contained in start? - if (last <= start->last) - return; - - while (last >= (start+1)->first-1) - { - // There is a fragment between two posts. - R_StoreWallRange (start->last + 1, (start+1)->first - 1); - start++; - - if (last <= start->last) - return; - } - - // There is a fragment after *next. - R_StoreWallRange (start->last + 1, last); -} - - - -// -// R_ClearClipSegs -// -void R_ClearClipSegs (void) -{ - solidsegs[0].first = -0x7fffffff; - solidsegs[0].last = -1; - solidsegs[1].first = viewwidth; - solidsegs[1].last = 0x7fffffff; - newend = solidsegs+2; -} - -// -// R_AddLine -// Clips the given segment -// and adds any visible pieces to the line list. -// -void R_AddLine (seg_t* line) -{ - int x1; - int x2; - angle_t angle1; - angle_t angle2; - angle_t span; - angle_t tspan; - - curline = line; - - // OPTIMIZE: quickly reject orthogonal back sides. - angle1 = R_PointToAngle (line->v1->x, line->v1->y); - angle2 = R_PointToAngle (line->v2->x, line->v2->y); - - // Clip to view edges. - // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW). - span = angle1 - angle2; - - // Back side? I.e. backface culling? - if (span >= ANG180) - return; - - // Global angle needed by segcalc. - rw_angle1 = angle1; - angle1 -= viewangle; - angle2 -= viewangle; - - tspan = angle1 + clipangle; - if (tspan > 2*clipangle) - { - tspan -= 2*clipangle; - - // Totally off the left edge? - if (tspan >= span) - return; - - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2*clipangle) - { - tspan -= 2*clipangle; - - // Totally off the left edge? - if (tspan >= span) - return; - angle2 = 0 - clipangle; - } - - // The seg is in the view range, - // but not necessarily visible. - angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; - angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; - - // Does not cross a pixel? - if (x1 == x2) - return; - - backsector = line->backsector; - - // Single sided line? - if (!backsector) - goto clipsolid; - - // Closed door. - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - goto clipsolid; - - // Window. - if (backsector->ceilingheight != frontsector->ceilingheight - || backsector->floorheight != frontsector->floorheight) - goto clippass; - - // Reject empty lines used for triggers - // and special events. - // Identical floor and ceiling on both sides, - // identical light levels on both sides, - // and no middle texture. - if (backsector->ceilingpic == frontsector->ceilingpic - && backsector->floorpic == frontsector->floorpic - && backsector->lightlevel == frontsector->lightlevel - && curline->sidedef->midtexture == 0) - { - return; - } - - - clippass: - R_ClipPassWallSegment (x1, x2-1); - return; - - clipsolid: - R_ClipSolidWallSegment (x1, x2-1); -} - - -// -// R_CheckBBox -// Checks BSP node/subtree bounding box. -// Returns true -// if some part of the bbox might be visible. -// -int checkcoord[12][4] = -{ - {3,0,2,1}, - {3,0,2,0}, - {3,1,2,0}, - {0}, - {2,0,2,1}, - {0,0,0,0}, - {3,1,3,0}, - {0}, - {2,0,3,1}, - {2,1,3,1}, - {2,1,3,0} -}; - - -boolean R_CheckBBox (fixed_t* bspcoord) -{ - int boxx; - int boxy; - int boxpos; - - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - angle_t angle1; - angle_t angle2; - angle_t span; - angle_t tspan; - - cliprange_t* start; - - int sx1; - int sx2; - - // Find the corners of the box - // that define the edges from current viewpoint. - if (viewx <= bspcoord[BOXLEFT]) - boxx = 0; - else if (viewx < bspcoord[BOXRIGHT]) - boxx = 1; - else - boxx = 2; - - if (viewy >= bspcoord[BOXTOP]) - boxy = 0; - else if (viewy > bspcoord[BOXBOTTOM]) - boxy = 1; - else - boxy = 2; - - boxpos = (boxy<<2)+boxx; - if (boxpos == 5) - return true; - - x1 = bspcoord[checkcoord[boxpos][0]]; - y1 = bspcoord[checkcoord[boxpos][1]]; - x2 = bspcoord[checkcoord[boxpos][2]]; - y2 = bspcoord[checkcoord[boxpos][3]]; - - // check clip list for an open space - angle1 = R_PointToAngle (x1, y1) - viewangle; - angle2 = R_PointToAngle (x2, y2) - viewangle; - - span = angle1 - angle2; - - // Sitting on a line? - if (span >= ANG180) - return true; - - tspan = angle1 + clipangle; - - if (tspan > 2*clipangle) - { - tspan -= 2*clipangle; - - // Totally off the left edge? - if (tspan >= span) - return false; - - angle1 = clipangle; - } - tspan = clipangle - angle2; - if (tspan > 2*clipangle) - { - tspan -= 2*clipangle; - - // Totally off the left edge? - if (tspan >= span) - return false; - - angle2 = 0 - clipangle; - } - - - // Find the first clippost - // that touches the source post - // (adjacent pixels are touching). - angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; - angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; - sx1 = viewangletox[angle1]; - sx2 = viewangletox[angle2]; - - // Does not cross a pixel. - if (sx1 == sx2) - return false; - sx2--; - - start = solidsegs; - while (start->last < sx2) - start++; - - if (sx1 >= start->first - && sx2 <= start->last) - { - // The clippost contains the new span. - return false; - } - - return true; -} - - - -// -// R_Subsector -// Determine floor/ceiling planes. -// Add sprites of things in sector. -// Draw one or more line segments. -// -void R_Subsector (int num) -{ - int count; - seg_t* line; - subsector_t* sub; - -#ifdef RANGECHECK - if (num>=numsubsectors) - I_Error ("R_Subsector: ss %i with numss = %i", - num, - numsubsectors); -#endif - - sscount++; - sub = &subsectors[num]; - frontsector = sub->sector; - count = sub->numlines; - line = &segs[sub->firstline]; - - if (frontsector->floorheight < viewz) - { - floorplane = R_FindPlane (frontsector->floorheight, - frontsector->floorpic, - frontsector->lightlevel); - } - else - floorplane = NULL; - - if (frontsector->ceilingheight > viewz - || frontsector->ceilingpic == skyflatnum) - { - ceilingplane = R_FindPlane (frontsector->ceilingheight, - frontsector->ceilingpic, - frontsector->lightlevel); - } - else - ceilingplane = NULL; - - R_AddSprites (frontsector); - - while (count--) - { - R_AddLine (line); - line++; - } - - // check for solidsegs overflow - extremely unsatisfactory! - if(newend > &solidsegs[32]) - I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); -} - - - - -// -// RenderBSPNode -// Renders all subsectors below a given node, -// traversing subtree recursively. -// Just call with BSP root. -void R_RenderBSPNode (int bspnum) -{ - node_t* bsp; - int side; - - // Found a subsector? - if (bspnum & NF_SUBSECTOR) - { - if (bspnum == -1) - R_Subsector (0); - else - R_Subsector (bspnum&(~NF_SUBSECTOR)); - return; - } - - bsp = &nodes[bspnum]; - - // Decide which side the view point is on. - side = R_PointOnSide (viewx, viewy, bsp); - - // Recursively divide front space. - R_RenderBSPNode (bsp->children[side]); - - // Possibly divide back space. - if (R_CheckBBox (bsp->bbox[side^1])) - R_RenderBSPNode (bsp->children[side^1]); -} - - diff --git a/games/NXDoom/src/strife/r_bsp.h b/games/NXDoom/src/strife/r_bsp.h deleted file mode 100644 index 1723e686147..00000000000 --- a/games/NXDoom/src/strife/r_bsp.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh module, BSP traversal and handling. -// - - -#ifndef __R_BSP__ -#define __R_BSP__ - - - -extern seg_t* curline; -extern side_t* sidedef; -extern line_t* linedef; -extern sector_t* frontsector; -extern sector_t* backsector; - -extern int rw_x; -extern int rw_stopx; - -extern boolean segtextured; - -// false if the back side is the same plane -extern boolean markfloor; -extern boolean markceiling; - -extern boolean skymap; - -extern drawseg_t drawsegs[MAXDRAWSEGS]; -extern drawseg_t* ds_p; - -extern lighttable_t** hscalelight; -extern lighttable_t** vscalelight; -extern lighttable_t** dscalelight; - - -typedef void (*drawfunc_t) (int start, int stop); - - -// BSP? -void R_ClearClipSegs (void); -void R_ClearDrawSegs (void); - - -void R_RenderBSPNode (int bspnum); - - -#endif diff --git a/games/NXDoom/src/strife/r_data.c b/games/NXDoom/src/strife/r_data.c deleted file mode 100644 index e7d70e073b1..00000000000 --- a/games/NXDoom/src/strife/r_data.c +++ /dev/null @@ -1,1010 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Preparation of data for rendering, -// generation of lookups, caching, retrieval by name. -// - -#include - -#include "d_main.h" -#include "deh_main.h" -#include "i_swap.h" -#include "i_system.h" -#include "z_zone.h" -#include "w_wad.h" -#include "doomdef.h" -#include "r_local.h" -#include "p_local.h" -#include "doomstat.h" -#include "m_misc.h" -#include "r_sky.h" -#include "r_data.h" -#include "sounds.h" // villsa [STRIFE] - -// -// Graphics. -// DOOM graphics for walls and sprites -// is stored in vertical runs of opaque pixels (posts). -// A column is composed of zero or more posts, -// a patch or sprite is composed of zero or more columns. -// - - - -// -// Texture definition. -// Each texture is composed of one or more patches, -// with patches being lumps stored in the WAD. -// The lumps are referenced by number, and patched -// into the rectangular texture space using origin -// and possibly other attributes. -// -typedef PACKED_STRUCT ( -{ - short originx; - short originy; - short patch; - //short stepdir; // villsa [STRIFE] removed - //short colormap; // villsa [STRIFE] removed -}) mappatch_t; - - -// -// Texture definition. -// A DOOM wall texture is a list of patches -// which are to be combined in a predefined order. -// -typedef PACKED_STRUCT ( -{ - char name[8]; - int masked; - short width; - short height; - //int obsolete; // villsa [STRIFE] removed - short patchcount; - mappatch_t patches[1]; -}) maptexture_t; - - -// A single patch from a texture definition, -// basically a rectangular area within -// the texture rectangle. -typedef struct -{ - // Block origin (allways UL), - // which has allready accounted - // for the internal origin of the patch. - short originx; - short originy; - int patch; -} texpatch_t; - - -// A maptexturedef_t describes a rectangular texture, -// which is composed of one or more mappatch_t structures -// that arrange graphic patches. - -typedef struct texture_s texture_t; - -struct texture_s -{ - // Keep name for switch changing, etc. - char name[8]; - short width; - short height; - - // Index in textures list - - int index; - - // Next in hash table chain - - texture_t *next; - - // All the patches[patchcount] - // are drawn back to front into the cached texture. - short patchcount; - texpatch_t patches[1]; -}; - - - -int firstflat; -int lastflat; -int numflats; - -int firstpatch; -int lastpatch; -int numpatches; - -int firstspritelump; -int lastspritelump; -int numspritelumps; - -int numtextures; -texture_t** textures; -texture_t** textures_hashtable; - - -int* texturewidthmask; -// needed for texture pegging -fixed_t* textureheight; -int* texturecompositesize; -short** texturecolumnlump; -unsigned short** texturecolumnofs; -byte** texturecomposite; - -// for global animation -int* flattranslation; -int* texturetranslation; - -// needed for pre rendering -fixed_t* spritewidth; -fixed_t* spriteoffset; -fixed_t* spritetopoffset; - -lighttable_t *colormaps; - - -// -// MAPTEXTURE_T CACHING -// When a texture is first needed, -// it counts the number of composite columns -// required in the texture and allocates space -// for a column directory and any new columns. -// The directory will simply point inside other patches -// if there is only one patch in a given column, -// but any columns with multiple patches -// will have new column_ts generated. -// - - - -// -// R_DrawColumnInCache -// Clip and draw a column -// from a patch into a cached post. -// -void -R_DrawColumnInCache -( column_t* patch, - byte* cache, - int originy, - int cacheheight ) -{ - int count; - int position; - byte* source; - - while (patch->topdelta != 0xff) - { - source = (byte *)patch + 3; - count = patch->length; - position = originy + patch->topdelta; - - if (position < 0) - { - count += position; - position = 0; - } - - if (position + count > cacheheight) - count = cacheheight - position; - - if (count > 0) - memcpy (cache + position, source, count); - - patch = (column_t *)( (byte *)patch + patch->length + 4); - } -} - - - -// -// R_GenerateComposite -// Using the texture definition, -// the composite texture is created from the patches, -// and each column is cached. -// -void R_GenerateComposite (int texnum) -{ - byte* block; - texture_t* texture; - texpatch_t* patch; - patch_t* realpatch; - int x; - int x1; - int x2; - int i; - column_t* patchcol; - short* collump; - unsigned short* colofs; - - texture = textures[texnum]; - - block = Z_Malloc (texturecompositesize[texnum], - PU_STATIC, - &texturecomposite[texnum]); - - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - - // Composite the columns together. - for (i=0 , patch = texture->patches; - ipatchcount; - i++, patch++) - { - realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1<0) - x = 0; - else - x = x1; - - if (x2 > texture->width) - x2 = texture->width; - - for ( ; x= 0) - continue; - - patchcol = (column_t *)((byte *)realpatch - + LONG(realpatch->columnofs[x-x1])); - R_DrawColumnInCache (patchcol, - block + colofs[x], - patch->originy, - texture->height); - } - - } - - // Now that the texture has been built in column cache, - // it is purgable from zone memory. - Z_ChangeTag (block, PU_CACHE); -} - - - -// -// R_GenerateLookup -// -void R_GenerateLookup (int texnum) -{ - texture_t* texture; - byte* patchcount; // patchcount[texture->width] - texpatch_t* patch; - patch_t* realpatch; - int x; - int x1; - int x2; - int i; - short* collump; - unsigned short* colofs; - - texture = textures[texnum]; - - // Composited texture not created yet. - texturecomposite[texnum] = 0; - - texturecompositesize[texnum] = 0; - collump = texturecolumnlump[texnum]; - colofs = texturecolumnofs[texnum]; - - // Now count the number of columns - // that are covered by more than one patch. - // Fill in the lump / offset, so columns - // with only a single patch are all done. - patchcount = (byte *) Z_Malloc(texture->width, PU_STATIC, &patchcount); - memset (patchcount, 0, texture->width); - - for (i=0 , patch = texture->patches; - ipatchcount; - i++, patch++) - { - realpatch = W_CacheLumpNum (patch->patch, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1 < 0) - x = 0; - else - x = x1; - - if (x2 > texture->width) - x2 = texture->width; - for ( ; xpatch; - colofs[x] = LONG(realpatch->columnofs[x-x1])+3; - } - } - - for (x=0 ; xwidth ; x++) - { - if (!patchcount[x]) - { - printf ("R_GenerateLookup: column without a patch (%s)\n", - texture->name); - return; - } - // I_Error ("R_GenerateLookup: column without a patch"); - - if (patchcount[x] > 1) - { - // Use the cached block. - collump[x] = -1; - colofs[x] = texturecompositesize[texnum]; - - if (texturecompositesize[texnum] > 0x10000-texture->height) - { - I_Error ("R_GenerateLookup: texture %i is >64k", - texnum); - } - - texturecompositesize[texnum] += texture->height; - } - } - - Z_Free(patchcount); -} - - - - -// -// R_GetColumn -// -byte* -R_GetColumn -( int tex, - int col ) -{ - int lump; - int ofs; - - col &= texturewidthmask[tex]; - lump = texturecolumnlump[tex][col]; - ofs = texturecolumnofs[tex][col]; - - if (lump > 0) - return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs; - - if (!texturecomposite[tex]) - R_GenerateComposite (tex); - - return texturecomposite[tex] + ofs; -} - - -static void GenerateTextureHashTable(void) -{ - texture_t **rover; - int i; - int key; - - textures_hashtable - = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); - - memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); - - // Add all textures to hash table - - for (i=0; iindex = i; - - // Vanilla Doom does a linear search of the texures array - // and stops at the first entry it finds. If there are two - // entries with the same name, the first one in the array - // wins. The new entry must therefore be added at the end - // of the hash chain, so that earlier entries win. - - key = W_LumpNameHash(textures[i]->name) % numtextures; - - rover = &textures_hashtable[key]; - - while (*rover != NULL) - { - rover = &(*rover)->next; - } - - // Hook into hash table - - textures[i]->next = NULL; - *rover = textures[i]; - } -} - - -// -// R_InitTextures -// Initializes the texture list -// with the textures from the world map. -// -void R_InitTextures (void) -{ - maptexture_t* mtexture; - texture_t* texture; - mappatch_t* mpatch; - texpatch_t* patch; - - int i; - int j; - - int* maptex; - int* maptex2; - int* maptex1; - - char name[9]; - char* names; - char* name_p; - - int* patchlookup; - - int nummappatches; - int offset; - int maxoff; - int maxoff2; - int numtextures1; - int numtextures2; - - int* directory; - - int temp1; - int temp2; - int temp3; - - - // Load the patch names from pnames.lmp. - names = W_CacheLumpName (DEH_String("PNAMES"), PU_STATIC); - nummappatches = LONG ( *((int *)names) ); - name_p = names+4; - patchlookup = Z_Malloc(nummappatches*sizeof(*patchlookup), PU_STATIC, NULL); - - for (i = 0; i < nummappatches; i++) - { - M_StringCopy(name, name_p + i * 8, sizeof(name)); - patchlookup[i] = W_CheckNumForName (name); - } - W_ReleaseLumpName(DEH_String("PNAMES")); - - // Load the map texture definitions from textures.lmp. - // The data is contained in one or two lumps, - // TEXTURE1 for shareware, plus TEXTURE2 for commercial. - maptex = maptex1 = W_CacheLumpName (DEH_String("TEXTURE1"), PU_STATIC); - numtextures1 = LONG(*maptex); - maxoff = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE1"))); - directory = maptex+1; - - if (W_CheckNumForName (DEH_String("TEXTURE2")) != -1) - { - maptex2 = W_CacheLumpName (DEH_String("TEXTURE2"), PU_STATIC); - numtextures2 = LONG(*maptex2); - maxoff2 = W_LumpLength (W_GetNumForName (DEH_String("TEXTURE2"))); - } - else - { - maptex2 = NULL; - numtextures2 = 0; - maxoff2 = 0; - } - numtextures = numtextures1 + numtextures2; - - textures = Z_Malloc (numtextures * sizeof(*textures), PU_STATIC, 0); - texturecolumnlump = Z_Malloc (numtextures * sizeof(*texturecolumnlump), PU_STATIC, 0); - texturecolumnofs = Z_Malloc (numtextures * sizeof(*texturecolumnofs), PU_STATIC, 0); - texturecomposite = Z_Malloc (numtextures * sizeof(*texturecomposite), PU_STATIC, 0); - texturecompositesize = Z_Malloc (numtextures * sizeof(*texturecompositesize), PU_STATIC, 0); - texturewidthmask = Z_Malloc (numtextures * sizeof(*texturewidthmask), PU_STATIC, 0); - textureheight = Z_Malloc (numtextures * sizeof(*textureheight), PU_STATIC, 0); - - // Really complex printing shit... - temp1 = W_GetNumForName (DEH_String("S_START")); // P_??????? - temp2 = W_GetNumForName (DEH_String("S_END")) - 1; - temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64); - - // If stdout is a real console, use the classic vanilla "filling - // up the box" effect, which uses backspace to "step back" inside - // the box. If stdout is a file, don't draw the box. - - // haleyjd 20110206 [STRIFE]: box is in devparm only - if (devparm && I_ConsoleStdout()) - { - printf("["); - for (i = 0; i < temp3 + 9; i++) - printf(" "); - printf("]"); - for (i = 0; i < temp3 + 10; i++) - printf("\b"); - } - - for (i=0 ; i maxoff) - I_Error ("R_InitTextures: bad texture directory"); - - mtexture = (maptexture_t *) ( (byte *)maptex + offset); - - texture = textures[i] = - Z_Malloc (sizeof(texture_t) - + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), - PU_STATIC, 0); - - texture->width = SHORT(mtexture->width); - texture->height = SHORT(mtexture->height); - texture->patchcount = SHORT(mtexture->patchcount); - - memcpy (texture->name, mtexture->name, sizeof(texture->name)); - mpatch = &mtexture->patches[0]; - patch = &texture->patches[0]; - - for (j=0 ; jpatchcount ; j++, mpatch++, patch++) - { - patch->originx = SHORT(mpatch->originx); - patch->originy = SHORT(mpatch->originy); - patch->patch = patchlookup[SHORT(mpatch->patch)]; - if (patch->patch == -1) - { - I_Error ("R_InitTextures: Missing patch in texture %s", - texture->name); - } - } - texturecolumnlump[i] = Z_Malloc (texture->width*sizeof(**texturecolumnlump), PU_STATIC,0); - texturecolumnofs[i] = Z_Malloc (texture->width*sizeof(**texturecolumnofs), PU_STATIC,0); - - j = 1; - while (j*2 <= texture->width) - j<<=1; - - texturewidthmask[i] = j-1; - textureheight[i] = texture->height<width)<leftoffset)<topoffset)<name, name, 8) ) - return texture->index; - - texture = texture->next; - } - - return -1; -} - - - -// -// R_TextureNumForName -// Calls R_CheckTextureNumForName, -// aborts with error message. -// -int R_TextureNumForName (const char* name) -{ - int i; - - i = R_CheckTextureNumForName (name); - - if (i==-1) - { - I_Error ("R_TextureNumForName: %s not found", - name); - } - return i; -} - -// -// R_SoundNumForDoor -// -// villsa [STRIFE] - new function -// Set sounds associated with door though why -// on earth is this function placed here? -// -void R_SoundNumForDoor(vldoor_t* door) -{ - int i; - sector_t *sector; - line_t *line; - texture_t *texture; - char name[8]; - char c1; - char c2; - - // set default sounds - door->opensound = sfx_drsmto; - door->closesound = sfx_drsmtc; - - for(sector = door->sector, i = 0; i < sector->linecount; i++) - { - line = sector->lines[i]; - - if(!(line->flags & ML_TWOSIDED)) - continue; - - texture = textures[sides[line->sidenum[0]].toptexture]; - memcpy(name, texture->name, 8); - - if(strncmp(name, "DOR", 3)) - continue; - - c1 = name[3]; - c2 = name[4]; - - // S type - if(c1 == 'S') - { - door->opensound = sfx_drston; - door->closesound = sfx_drston; - return; - } - - // M type - if(c1 == 'M') - { - // L subtype - if(c2 == 'L') - { - door->opensound = sfx_drlmto; - door->closesound = sfx_drlmtc; - } - // S subtype - else if(c2 == 'S') - { - door->opensound = sfx_drsmto; - door->closesound = sfx_drsmtc; - } - return; - } - // W type - else if(c1 == 'W') - { - // L subtype - if(c2 == 'L') - { - door->opensound = sfx_drlwud; - door->closesound = sfx_drlwud; - } - // S subtype - else if(c2 == 'S') - { - door->opensound = sfx_drswud; - door->closesound = sfx_drswud; - } - return; - } - } -} - - - - -// -// R_PrecacheLevel -// Preloads all relevant graphics for the level. -// -int flatmemory; -int texturememory; -int spritememory; - -void R_PrecacheLevel (void) -{ - char* flatpresent; - char* texturepresent; - char* spritepresent; - - int i; - int j; - int k; - int lump; - - texture_t* texture; - thinker_t* th; - spriteframe_t* sf; - - if (demoplayback) - return; - - // Precache flats. - flatpresent = Z_Malloc(numflats, PU_STATIC, NULL); - memset (flatpresent,0,numflats); - - for (i=0 ; isize; - W_CacheLumpNum(lump, PU_CACHE); - } - } - - Z_Free(flatpresent); - - // Precache textures. - texturepresent = Z_Malloc(numtextures, PU_STATIC, NULL); - memset (texturepresent,0, numtextures); - - for (i=0 ; ipatchcount ; j++) - { - lump = texture->patches[j].patch; - texturememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump , PU_CACHE); - } - } - - Z_Free(texturepresent); - - // Precache sprites. - spritepresent = Z_Malloc(numsprites, PU_STATIC, NULL); - memset (spritepresent,0, numsprites); - - for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - spritepresent[((mobj_t *)th)->sprite] = 1; - } - - spritememory = 0; - for (i=0 ; ilump[k]; - spritememory += lumpinfo[lump]->size; - W_CacheLumpNum(lump , PU_CACHE); - } - } - } - - Z_Free(spritepresent); -} - - - - diff --git a/games/NXDoom/src/strife/r_data.h b/games/NXDoom/src/strife/r_data.h deleted file mode 100644 index efeb4f7533e..00000000000 --- a/games/NXDoom/src/strife/r_data.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh module, data I/O, caching, retrieval of graphics -// by name. -// - - -#ifndef __R_DATA__ -#define __R_DATA__ - -#include "r_defs.h" -#include "r_state.h" -#include "p_spec.h" // villsa [STRIFE] - - -extern int numflats; - - -// Retrieve column data for span blitting. -byte* -R_GetColumn -( int tex, - int col ); - - -// I/O, setting up the stuff. -void R_InitData (void); -void R_PrecacheLevel (void); - - -// Retrieval. -// Floor/ceiling opaque texture tiles, -// lookup by name. For animation? -int R_FlatNumForName(const char *name); - - -// Called by P_Ticker for switches and animations, -// returns the texture number for the texture name. -int R_TextureNumForName (const char *name); -int R_CheckTextureNumForName (const char *name); -void R_SoundNumForDoor(vldoor_t* door); // villsa [STRIFE] - -#endif diff --git a/games/NXDoom/src/strife/r_defs.h b/games/NXDoom/src/strife/r_defs.h deleted file mode 100644 index a64ac8424ac..00000000000 --- a/games/NXDoom/src/strife/r_defs.h +++ /dev/null @@ -1,448 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh/rendering module, shared data struct definitions. -// - - -#ifndef __R_DEFS__ -#define __R_DEFS__ - - -// Screenwidth. -#include "doomdef.h" - -// Some more or less basic data types -// we depend on. -#include "m_fixed.h" - -// We rely on the thinker data struct -// to handle sound origins in sectors. -#include "d_think.h" -// SECTORS do store MObjs anyway. -#include "p_mobj.h" - -#include "i_video.h" - -#include "v_patch.h" - - - - -// Silhouette, needed for clipping Segs (mainly) -// and sprites representing things. -#define SIL_NONE 0 -#define SIL_BOTTOM 1 -#define SIL_TOP 2 -#define SIL_BOTH 3 - -#define MAXDRAWSEGS 256 - - - - - -// -// INTERNAL MAP TYPES -// used by play and refresh -// - -// -// Your plain vanilla vertex. -// Note: transformed values not buffered locally, -// like some DOOM-alikes ("wt", "WebView") did. -// -typedef struct -{ - fixed_t x; - fixed_t y; - -} vertex_t; - - -// Forward of LineDefs, for Sectors. -struct line_s; - -// Each sector has a degenmobj_t in its center -// for sound origin purposes. -// I suppose this does not handle sound from -// moving objects (doppler), because -// position is prolly just buffered, not -// updated. -typedef struct -{ - thinker_t thinker; // not used for anything - fixed_t x; - fixed_t y; - fixed_t z; - -} degenmobj_t; - -// -// The SECTORS record, at runtime. -// Stores things/mobjs. -// -typedef struct -{ - fixed_t floorheight; - fixed_t ceilingheight; - short floorpic; - short ceilingpic; - short lightlevel; - short special; - short tag; - - // 0 = untraversed, 1,2 = sndlines -1 - int soundtraversed; - - // thing that made a sound (or null) - mobj_t* soundtarget; - - // mapblock bounding box for height changes - int blockbox[4]; - - // origin for any sounds played by the sector - degenmobj_t soundorg; - - // if == validcount, already checked - int validcount; - - // list of mobjs in sector - mobj_t* thinglist; - - // thinker_t for reversable actions - void* specialdata; - - int linecount; - struct line_s** lines; // [linecount] size - -} sector_t; - - - - -// -// The SideDef. -// - -typedef struct -{ - // add this to the calculated texture column - fixed_t textureoffset; - - // add this to the calculated texture top - fixed_t rowoffset; - - // Texture indices. - // We do not maintain names here. - short toptexture; - short bottomtexture; - short midtexture; - - // Sector the SideDef is facing. - sector_t* sector; - -} side_t; - - - -// -// Move clipping aid for LineDefs. -// -typedef enum -{ - ST_HORIZONTAL, - ST_VERTICAL, - ST_POSITIVE, - ST_NEGATIVE - -} slopetype_t; - - - -typedef struct line_s -{ - // Vertices, from v1 to v2. - vertex_t* v1; - vertex_t* v2; - - // Precalculated v2 - v1 for side checking. - fixed_t dx; - fixed_t dy; - - // Animation related. - short flags; - short special; - short tag; - - // Visual appearance: SideDefs. - // sidenum[1] will be -1 if one sided - short sidenum[2]; - - // Neat. Another bounding box, for the extent - // of the LineDef. - fixed_t bbox[4]; - - // To aid move clipping. - slopetype_t slopetype; - - // Front and back sector. - // Note: redundant? Can be retrieved from SideDefs. - sector_t* frontsector; - sector_t* backsector; - - // if == validcount, already checked - int validcount; - - // thinker_t for reversable actions - void* specialdata; -} line_t; - - - - -// -// A SubSector. -// References a Sector. -// Basically, this is a list of LineSegs, -// indicating the visible walls that define -// (all or some) sides of a convex BSP leaf. -// -typedef struct subsector_s -{ - sector_t* sector; - short numlines; - short firstline; - -} subsector_t; - - - -// -// The LineSeg. -// -typedef struct -{ - vertex_t* v1; - vertex_t* v2; - - fixed_t offset; - - angle_t angle; - - side_t* sidedef; - line_t* linedef; - - // Sector references. - // Could be retrieved from linedef, too. - // backsector is NULL for one sided lines - sector_t* frontsector; - sector_t* backsector; - -} seg_t; - - - -// -// BSP node. -// -typedef struct -{ - // Partition line. - fixed_t x; - fixed_t y; - fixed_t dx; - fixed_t dy; - - // Bounding box for each child. - fixed_t bbox[2][4]; - - // If NF_SUBSECTOR its a subsector. - unsigned short children[2]; - -} node_t; - - - - -// PC direct to screen pointers -//B UNUSED - keep till detailshift in r_draw.c resolved -//extern byte* destview; -//extern byte* destscreen; - - - - - -// -// OTHER TYPES -// - -// This could be wider for >8 bit display. -// Indeed, true color support is posibble -// precalculating 24bpp lightmap/colormap LUT. -// from darkening PLAYPAL to all black. -// Could even us emore than 32 levels. -typedef byte lighttable_t; - - - - -// -// ? -// -typedef struct drawseg_s -{ - seg_t* curline; - int x1; - int x2; - - fixed_t scale1; - fixed_t scale2; - fixed_t scalestep; - - // 0=none, 1=bottom, 2=top, 3=both - int silhouette; - - // do not clip sprites above this - fixed_t bsilheight; - - // do not clip sprites below this - fixed_t tsilheight; - - // Pointers to lists for sprite clipping, - // all three adjusted so [x1] is first value. - short* sprtopclip; - short* sprbottomclip; - short* maskedtexturecol; - -} drawseg_t; - - - -// A vissprite_t is a thing -// that will be drawn during a refresh. -// I.e. a sprite object that is partly visible. -typedef struct vissprite_s -{ - // Doubly linked list. - struct vissprite_s* prev; - struct vissprite_s* next; - - int x1; - int x2; - - // for line side calculation - fixed_t gx; - fixed_t gy; - - // global bottom / top for silhouette clipping - fixed_t gz; - fixed_t gzt; - - // horizontal position of x1 - fixed_t startfrac; - - fixed_t scale; - - // negative if flipped - fixed_t xiscale; - - fixed_t texturemid; - int patch; - - // for color translation and shadow draw, - // maxbright frames as well - lighttable_t* colormap; - - int mobjflags; - -} vissprite_t; - - -// -// Sprites are patches with a special naming convention -// so they can be recognized by R_InitSprites. -// The base name is NNNNFx or NNNNFxFx, with -// x indicating the rotation, x = 0, 1-7. -// The sprite and frame specified by a thing_t -// is range checked at run time. -// A sprite is a patch_t that is assumed to represent -// a three dimensional object and may have multiple -// rotations pre drawn. -// Horizontal flipping is used to save space, -// thus NNNNF2F5 defines a mirrored patch. -// Some sprites will only have one picture used -// for all views: NNNNF0 -// -typedef struct -{ - // If false use 0 for any position. - // Note: as eight entries are available, - // we might as well insert the same name eight times. - boolean rotate; - - // Lump to use for view angles 0-7. - short lump[8]; - - // Flip bit (1 = flip) to use for view angles 0-7. - byte flip[8]; - -} spriteframe_t; - - - -// -// A sprite definition: -// a number of animation frames. -// -typedef struct -{ - int numframes; - spriteframe_t* spriteframes; - -} spritedef_t; - - - -// -// Now what is a visplane, anyway? -// -typedef struct -{ - fixed_t height; - int picnum; - int lightlevel; - int minx; - int maxx; - - // leave pads for [minx-1]/[maxx+1] - - byte pad1; - // Here lies the rub for all - // dynamic resize/change of resolution. - byte top[SCREENWIDTH]; - byte pad2; - byte pad3; - // See above. - byte bottom[SCREENWIDTH]; - byte pad4; - -} visplane_t; - - - - -#endif diff --git a/games/NXDoom/src/strife/r_draw.c b/games/NXDoom/src/strife/r_draw.c deleted file mode 100644 index de6d1d0a979..00000000000 --- a/games/NXDoom/src/strife/r_draw.c +++ /dev/null @@ -1,968 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The actual span/column drawing functions. -// Here find the main potential for optimization, -// e.g. inline assembly, different algorithms. -// - - - - -#include "doomdef.h" -#include "deh_main.h" - -#include "i_system.h" -#include "z_zone.h" -#include "w_wad.h" - -#include "r_local.h" - -// Needs access to LFB (guess what). -#include "v_video.h" - -// State. -#include "doomstat.h" - - -// ? -#define MAXWIDTH 1120 -#define MAXHEIGHT 832 - -// status bar height at bottom of screen -// haleyjd 08/31/10: Verified unmodified. -#define SBARHEIGHT 32 - -// -// All drawing to the view buffer is accomplished in this file. -// The other refresh files only know about ccordinates, -// not the architecture of the frame buffer. -// Conveniently, the frame buffer is a linear one, -// and we need only the base address, -// and the total size == width*height*depth/8., -// - - -byte* viewimage; -int viewwidth; -int scaledviewwidth; -int viewheight; -int viewwindowx; -int viewwindowy; -byte* ylookup[MAXHEIGHT]; -int columnofs[MAXWIDTH]; - -// Color tables for different players, -// translate a limited part to another -// (color ramps used for suit colors). -// -// [STRIFE] Unused. -//byte translations[3][256]; - -// Backing buffer containing the bezel drawn around the screen and -// surrounding background. - -static byte *background_buffer = NULL; - -// haleyjd 08/29/10: [STRIFE] Rogue added the ability to customize the view -// border flat by storing it in the configuration file. -char *back_flat = "F_PAVE01"; - -// -// R_DrawColumn -// Source is the top of the column to scale. -// -lighttable_t* dc_colormap; -int dc_x; -int dc_yl; -int dc_yh; -fixed_t dc_iscale; -fixed_t dc_texturemid; - -// first pixel in a column (possibly virtual) -byte* dc_source; - -// just for profiling -int dccount; - -// -// A column is a vertical slice/span from a wall texture that, -// given the DOOM style restrictions on the view orientation, -// will always have constant z depth. -// Thus a special case loop for very fast rendering can -// be used. It has also been used with Wolfenstein 3D. -// -void R_DrawColumn (void) -{ - int count; - byte* dest; - fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - - // Zero length, column does not exceed a pixel. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) - I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); -#endif - - // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - dest = ylookup[dc_yl] + columnofs[dc_x]; - - // Determine scaling, - // which is the only mapping to be done. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - // Inner loop that does the actual texture mapping, - // e.g. a DDA-lile scaling. - // This is as fast as it gets. - do - { - // Re-map color indices from wall texture column - // using a lighting/special effects LUT. - *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; - - dest += SCREENWIDTH; - frac += fracstep; - - } while (count--); -} - - - -// UNUSED. -// Loop unrolled. -#if 0 -void R_DrawColumn (void) -{ - int count; - byte* source; - byte* dest; - byte* colormap; - - unsigned frac; - unsigned fracstep; - unsigned fracstep2; - unsigned fracstep3; - unsigned fracstep4; - - count = dc_yh - dc_yl + 1; - - source = dc_source; - colormap = dc_colormap; - dest = ylookup[dc_yl] + columnofs[dc_x]; - - fracstep = dc_iscale<<9; - frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; - - fracstep2 = fracstep+fracstep; - fracstep3 = fracstep2+fracstep; - fracstep4 = fracstep3+fracstep; - - while (count >= 8) - { - dest[0] = colormap[source[frac>>25]]; - dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; - dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; - dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]]; - - frac += fracstep4; - - dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; - dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; - dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; - dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; - - frac += fracstep4; - dest += SCREENWIDTH*8; - count -= 8; - } - - while (count > 0) - { - *dest = colormap[source[frac>>25]]; - dest += SCREENWIDTH; - frac += fracstep; - count--; - } -} -#endif - -// haleyjd 09/06/10 [STRIFE] Removed low detail - -// -// Spectre/Invisibility. -// - -// haleyjd 09/06/10: ]STRIFE] replaced fuzzdraw with translucency. - -// -// R_DrawMVisTLColumn -// -// villsa [STRIFE] new function -// Replacement for R_DrawFuzzColumn -// -void R_DrawMVisTLColumn(void) -{ - int count; - byte* dest; - fixed_t frac; - fixed_t fracstep; - - // Adjust borders. Low... - if (!dc_yl) - dc_yl = 1; - - // .. and high. - if (dc_yh == viewheight-1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - - // Zero length. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - { - I_Error ("R_DrawFuzzColumn: %i to %i at %i", - dc_yl, dc_yh, dc_x); - } -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - do - { - byte src = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; - byte col = xlatab[*dest + (src << 8)]; - *dest = col; - dest += SCREENWIDTH; - frac += fracstep; - } while(count--); -} - -// -// R_DrawTLColumn -// -// villsa [STRIFE] new function -// Achieves a second translucency level using the same lookup table, -// via inversion of the colors in the index computation. -// -void R_DrawTLColumn(void) -{ - int count; - byte* dest; - fixed_t frac; - fixed_t fracstep; - - // Adjust borders. Low... - if (!dc_yl) - dc_yl = 1; - - // .. and high. - if (dc_yh == viewheight-1) - dc_yh = viewheight - 2; - - count = dc_yh - dc_yl; - - // Zero length. - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 || dc_yh >= SCREENHEIGHT) - { - I_Error ("R_DrawFuzzColumn2: %i to %i at %i", - dc_yl, dc_yh, dc_x); - } -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - do - { - byte src = dc_colormap[dc_source[(frac>>FRACBITS)&127]]; - byte col = xlatab[(*dest << 8) + src]; - *dest = col; - dest += SCREENWIDTH; - frac += fracstep; - } while(count--); -} - - - -// -// R_DrawTranslatedColumn -// Used to draw player sprites -// with the green colorramp mapped to others. -// Could be used with different translation -// tables, e.g. the lighter colored version -// of the BaronOfHell, the HellKnight, uses -// identical sprites, kinda brightened up. -// -byte* dc_translation; -byte* translationtables; - -void R_DrawTranslatedColumn (void) -{ - int count; - byte* dest; - fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) - { - I_Error ( "R_DrawColumn: %i to %i at %i", - dc_yl, dc_yh, dc_x); - } - -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - // Here we do an additional index re-mapping. - do - { - // Translation tables are used - // to map certain colorramps to other ones, - // used with PLAY sprites. - // Thus the "green" ramp of the player 0 sprite - // is mapped to gray, red, black/indigo. - *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]; - dest += SCREENWIDTH; - frac += fracstep; - } while (count--); -} - -// haleyjd 09/06/10 [STRIFE] Removed low detail - -// -// R_DrawTRTLColumn -// -// villsa [STRIFE] new function -// Combines translucency and color translation. -// -void R_DrawTRTLColumn(void) -{ - int count; - byte* dest; - fixed_t frac; - fixed_t fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if ((unsigned)dc_x >= SCREENWIDTH - || dc_yl < 0 - || dc_yh >= SCREENHEIGHT) - { - I_Error ( "R_DrawColumn: %i to %i at %i", - dc_yl, dc_yh, dc_x); - } -#endif - - dest = ylookup[dc_yl] + columnofs[dc_x]; - - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl-centery)*fracstep; - - // Here we do an additional index re-mapping. - do - { - byte src = dc_colormap[dc_translation[dc_source[frac>>FRACBITS&127]]]; - byte col = xlatab[(*dest << 8) + src]; - *dest = col; - dest += SCREENWIDTH; - frac += fracstep; - } while (count--); -} - - -// -// R_InitTranslationTables -// Creates the translation tables to map -// the green color ramp to gray, brown, red. -// Assumes a given structure of the PLAYPAL. -// Could be read from a lump instead. -// -// haleyjd 08/26/10: [STRIFE] -// * Added loading of XLATAB -// -void R_InitTranslationTables (void) -{ - int i; - byte col1, col2; - - // [STRIFE] Load xlatab. Here's how Rogue did it: - // v7 = W_CacheLumpName("XLATAB", PU_CACHE); // note potential cache bug... - // HIWORD(v8) = (Z_Malloc(131072, PU_STATIC, NULL) + 65535) >> 16; - // LOWORD(v8) = 0; // aligning to a 64K boundary, as if this is Wolf3D. - // xlatab = v8; - // memcpy(v8, v7, 65536); - // As you can see, they copypasta'd id's unnecessary 64K boundary alignment - // from the colormap code. Since this doesn't accomplish anything, and isn't - // strictly portable, all we need to do is this: - - // villsa [STRIFE] 09/26/10: load table through this function instead - V_LoadXlaTable(); - - // villsa [STRIFE] allocate a larger size for translation tables - translationtables = Z_Malloc (256*8, PU_STATIC, 0); - - col1 = 0xFA; - col2 = 0xE0; - - // villsa [STRIFE] setup all translation tables - for(i = 0; i < 256; i++) - { - if(i >= 0x80 && i <= 0x8f) - { - translationtables [i ] = (i & 0x0f) + 64; - translationtables [i+ 256] = (i & 0x0f) - 80; - translationtables [i+2*256] = (i & 0x0f) + 16; - translationtables [i+3*256] = (i & 0x0f) + 48; - translationtables [i+4*256] = (i & 0x0f) + 80; - translationtables [i+5*256] = (i & 0x0f) + 96; - translationtables [i+6*256] = (i & 0x0f) - 112; - } - else if(i >= 0x50 && i<= 0x5f) - { - translationtables [i ] = i; - translationtables [i+ 256] = i; - translationtables [i+2*256] = i; - translationtables [i+3*256] = i; - translationtables [i+4*256] = (i & 0x0f) + 0x80; - translationtables [i+5*256] = (i & 0x0f) + 16; - translationtables [i+6*256] = (i & 0x0f) + 64; - } - else if(i >= 0xd0 && i<= 0xdf) - { - translationtables [i ] = i; - translationtables [i+ 256] = i; - translationtables [i+2*256] = i; - translationtables [i+3*256] = i; - translationtables [i+4*256] = (i & 0x0f) - 80; - translationtables [i+5*256] = (i & 0x0f) + 48; - translationtables [i+6*256] = (i & 0x0f) + 16; - } - else if(i >= 0xc0 && i<= 0xcf) - { - translationtables [i ] = i; - translationtables [i+ 256] = i; - translationtables [i+2*256] = i; - translationtables [i+3*256] = i; - translationtables [i+4*256] = (i & 0x0f) - 96; - translationtables [i+5*256] = (i & 0x0f) + 32; - translationtables [i+6*256] = (i & 0x0f); - // haleyjd 20110213: missing code: - if(!(i & 0x0f)) - translationtables[i+6*256] = 1; - } - else if(i >= 0xf7 && i<= 0xfb) - { - translationtables [i ] = col1; - translationtables [i+ 256] = i; - translationtables [i+2*256] = i; - translationtables [i+3*256] = i; - translationtables [i+4*256] = i; - translationtables [i+5*256] = i; - translationtables [i+6*256] = i; - } - else if(i >= 0xf1 && i<= 0xf6) - { - translationtables [i ] = (i & 0x0f) - 33; - translationtables [i+ 256] = i; - translationtables [i+2*256] = i; - translationtables [i+3*256] = i; - translationtables [i+4*256] = i; - translationtables [i+5*256] = i; - translationtables [i+6*256] = i; - } - else if(i >= 0x20 && i <= 0x3f) // haleyjd 20110213: fixed upper end - { - translationtables [i ] = col2; - translationtables [i+ 256] = col2; - translationtables [i+2*256] = (i & 0x0f) - 48; - translationtables [i+3*256] = (i & 0x0f) - 48; - translationtables [i+4*256] = col2; - translationtables [i+5*256] = col2; - translationtables [i+6*256] = col2; - } - else // Keep all other colors as is. - { - translationtables[i]= - translationtables[i+256]= - translationtables[i+2*256]= - translationtables[i+3*256]= - translationtables[i+4*256]= - translationtables[i+5*256]= - translationtables[i+6*256]=i; - } - - ++col1; - ++col2; - } -} - - - - -// -// R_DrawSpan -// With DOOM style restrictions on view orientation, -// the floors and ceilings consist of horizontal slices -// or spans with constant z depth. -// However, rotation around the world z axis is possible, -// thus this mapping, while simpler and faster than -// perspective correct texture mapping, has to traverse -// the texture at an angle in all but a few cases. -// In consequence, flats are not stored by column (like walls), -// and the inner loop has to step in texture space u and v. -// -int ds_y; -int ds_x1; -int ds_x2; - -lighttable_t* ds_colormap; - -fixed_t ds_xfrac; -fixed_t ds_yfrac; -fixed_t ds_xstep; -fixed_t ds_ystep; - -// start of a 64*64 tile image -byte* ds_source; - -// just for profiling -int dscount; - - -// -// Draws the actual span. -void R_DrawSpan (void) -{ - unsigned int position, step; - byte *dest; - int count; - int spot; - unsigned int xtemp, ytemp; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 - || ds_x1<0 - || ds_x2>=SCREENWIDTH - || (unsigned)ds_y>SCREENHEIGHT) - { - I_Error( "R_DrawSpan: %i to %i at %i", - ds_x1,ds_x2,ds_y); - } -// dscount++; -#endif - - // Pack position and step variables into a single 32-bit integer, - // with x in the top 16 bits and y in the bottom 16 bits. For - // each 16-bit part, the top 6 bits are the integer part and the - // bottom 10 bits are the fractional part of the pixel position. - - position = ((ds_xfrac << 10) & 0xffff0000) - | ((ds_yfrac >> 6) & 0x0000ffff); - step = ((ds_xstep << 10) & 0xffff0000) - | ((ds_ystep >> 6) & 0x0000ffff); - - dest = ylookup[ds_y] + columnofs[ds_x1]; - - // We do not check for zero spans here? - count = ds_x2 - ds_x1; - - do - { - // Calculate current texture index in u,v. - ytemp = (position >> 4) & 0x0fc0; - xtemp = (position >> 26); - spot = xtemp | ytemp; - - // Lookup pixel from flat texture tile, - // re-index using light/colormap. - *dest++ = ds_colormap[ds_source[spot]]; - - position += step; - - } while (count--); -} - - - -// UNUSED. -// Loop unrolled by 4. -#if 0 -void R_DrawSpan (void) -{ - unsigned position, step; - - byte* source; - byte* colormap; - byte* dest; - - unsigned count; - usingned spot; - unsigned value; - unsigned temp; - unsigned xtemp; - unsigned ytemp; - - position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff); - step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff); - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; - - while (count >= 4) - { - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[0] = colormap[source[spot]]; - - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[1] = colormap[source[spot]]; - - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[2] = colormap[source[spot]]; - - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - dest[3] = colormap[source[spot]]; - - count -= 4; - dest += 4; - } - while (count > 0) - { - ytemp = position>>4; - ytemp = ytemp & 4032; - xtemp = position>>26; - spot = xtemp | ytemp; - position += step; - *dest++ = colormap[source[spot]]; - count--; - } -} -#endif - - -// -// Again.. -// -void R_DrawSpanLow (void) -{ - unsigned int position, step; - unsigned int xtemp, ytemp; - byte *dest; - int count; - int spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 - || ds_x1<0 - || ds_x2>=SCREENWIDTH - || (unsigned)ds_y>SCREENHEIGHT) - { - I_Error( "R_DrawSpan: %i to %i at %i", - ds_x1,ds_x2,ds_y); - } -// dscount++; -#endif - - position = ((ds_xfrac << 10) & 0xffff0000) - | ((ds_yfrac >> 6) & 0x0000ffff); - step = ((ds_xstep << 10) & 0xffff0000) - | ((ds_ystep >> 6) & 0x0000ffff); - - count = (ds_x2 - ds_x1); - - // Blocky mode, need to multiply by 2. - ds_x1 <<= 1; - ds_x2 <<= 1; - - dest = ylookup[ds_y] + columnofs[ds_x1]; - - do - { - // Calculate current texture index in u,v. - ytemp = (position >> 4) & 0x0fc0; - xtemp = (position >> 26); - spot = xtemp | ytemp; - - // Lowres/blocky mode does it twice, - // while scale is adjusted appropriately. - *dest++ = ds_colormap[ds_source[spot]]; - *dest++ = ds_colormap[ds_source[spot]]; - - position += step; - - } while (count--); -} - -// -// R_InitBuffer -// Creats lookup tables that avoid -// multiplies and other hazzles -// for getting the framebuffer address -// of a pixel to draw. -// -void -R_InitBuffer -( int width, - int height ) -{ - int i; - - // Handle resize, - // e.g. smaller view windows - // with border and/or status bar. - viewwindowx = (SCREENWIDTH-width) >> 1; - - // Column offset. For windows. - for (i=0 ; i> 1; - - // Preclaculate all row offsets. - for (i=0 ; i -#include - - -#include "doomdef.h" -#include "doomstat.h" // villsa [STRIFE] -#include "d_main.h" - -#include "m_bbox.h" -#include "m_menu.h" - -#include "r_local.h" -#include "r_sky.h" - - - - - -// Fineangles in the SCREENWIDTH wide window. -#define FIELDOFVIEW 2048 - - - -int viewangleoffset; - -// increment every time a check is made -int validcount = 1; - - -lighttable_t* fixedcolormap; - -int centerx; -int centery; - -fixed_t centerxfrac; -fixed_t centeryfrac; -fixed_t projection; - -// just for profiling purposes -int framecount; - -int sscount; -int linecount; -int loopcount; - -fixed_t viewx; -fixed_t viewy; -fixed_t viewz; - -int viewpitch; // villsa [STRIFE] - -angle_t viewangle; - -fixed_t viewcos; -fixed_t viewsin; - -player_t* viewplayer; - -// 0 = high, 1 = low -int detailshift; - -// -// precalculated math tables -// -angle_t clipangle; - -// The viewangletox[viewangle + FINEANGLES/4] lookup -// maps the visible view angles to screen X coordinates, -// flattening the arc to a flat projection plane. -// There will be many angles mapped to the same X. -int viewangletox[FINEANGLES/2]; - -// The xtoviewangleangle[] table maps a screen pixel -// to the lowest viewangle that maps back to x ranges -// from clipangle to -clipangle. -angle_t xtoviewangle[SCREENWIDTH+1]; - -lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; -lighttable_t* scalelightfixed[MAXLIGHTSCALE]; -lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ]; - -// bumped light from gun blasts -int extralight; - - - -void (*colfunc) (void); -void (*basecolfunc) (void); -void (*fuzzcolfunc) (void); -void (*transcolfunc) (void); -void (*spanfunc) (void); - - - -// -// R_AddPointToBox -// Expand a given bbox -// so that it encloses a given point. -// -void -R_AddPointToBox -( int x, - int y, - fixed_t* box ) -{ - if (x< box[BOXLEFT]) - box[BOXLEFT] = x; - if (x> box[BOXRIGHT]) - box[BOXRIGHT] = x; - if (y< box[BOXBOTTOM]) - box[BOXBOTTOM] = y; - if (y> box[BOXTOP]) - box[BOXTOP] = y; -} - - -// -// R_PointOnSide -// Traverse BSP (sub) tree, -// check point against partition plane. -// Returns side 0 (front) or 1 (back). -// -int -R_PointOnSide -( fixed_t x, - fixed_t y, - node_t* node ) -{ - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - if (!node->dx) - { - if (x <= node->x) - return node->dy > 0; - - return node->dy < 0; - } - if (!node->dy) - { - if (y <= node->y) - return node->dx < 0; - - return node->dx > 0; - } - - dx = (x - node->x); - dy = (y - node->y); - - // Try to quickly decide by looking at sign bits. - if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 ) - { - if ( (node->dy ^ dx) & 0x80000000 ) - { - // (left is negative) - return 1; - } - return 0; - } - - left = FixedMul ( node->dy>>FRACBITS , dx ); - right = FixedMul ( dy , node->dx>>FRACBITS ); - - if (right < left) - { - // front side - return 0; - } - // back side - return 1; -} - - -int -R_PointOnSegSide -( fixed_t x, - fixed_t y, - seg_t* line ) -{ - fixed_t lx; - fixed_t ly; - fixed_t ldx; - fixed_t ldy; - fixed_t dx; - fixed_t dy; - fixed_t left; - fixed_t right; - - lx = line->v1->x; - ly = line->v1->y; - - ldx = line->v2->x - lx; - ldy = line->v2->y - ly; - - if (!ldx) - { - if (x <= lx) - return ldy > 0; - - return ldy < 0; - } - if (!ldy) - { - if (y <= ly) - return ldx < 0; - - return ldx > 0; - } - - dx = (x - lx); - dy = (y - ly); - - // Try to quickly decide by looking at sign bits. - if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 ) - { - if ( (ldy ^ dx) & 0x80000000 ) - { - // (left is negative) - return 1; - } - return 0; - } - - left = FixedMul ( ldy>>FRACBITS , dx ); - right = FixedMul ( dy , ldx>>FRACBITS ); - - if (right < left) - { - // front side - return 0; - } - // back side - return 1; -} - - -// -// R_PointToAngle -// To get a global angle from cartesian coordinates, -// the coordinates are flipped until they are in -// the first octant of the coordinate system, then -// the y (<=x) is scaled and divided by x to get a -// tangent (slope) value which is looked up in the -// tantoangle[] table. - -// - - - - -angle_t -R_PointToAngle -( fixed_t x, - fixed_t y ) -{ - x -= viewx; - y -= viewy; - - if ( (!x) && (!y) ) - return 0; - - if (x>= 0) - { - // x >=0 - if (y>= 0) - { - // y>= 0 - - if (x>y) - { - // octant 0 - return tantoangle[ SlopeDiv(y,x)]; - } - else - { - // octant 1 - return ANG90-1-tantoangle[ SlopeDiv(x,y)]; - } - } - else - { - // y<0 - y = -y; - - if (x>y) - { - // octant 8 - return 0 - tantoangle[SlopeDiv(y,x)]; - } - else - { - // octant 7 - return ANG270+tantoangle[ SlopeDiv(x,y)]; - } - } - } - else - { - // x<0 - x = -x; - - if (y>= 0) - { - // y>= 0 - if (x>y) - { - // octant 3 - return ANG180-1-tantoangle[ SlopeDiv(y,x)]; - } - else - { - // octant 2 - return ANG90+ tantoangle[ SlopeDiv(x,y)]; - } - } - else - { - // y<0 - y = -y; - - if (x>y) - { - // octant 4 - return ANG180+tantoangle[ SlopeDiv(y,x)]; - } - else - { - // octant 5 - return ANG270-1-tantoangle[ SlopeDiv(x,y)]; - } - } - } - return 0; -} - - -angle_t -R_PointToAngle2 -( fixed_t x1, - fixed_t y1, - fixed_t x2, - fixed_t y2 ) -{ - viewx = x1; - viewy = y1; - - return R_PointToAngle (x2, y2); -} - - -fixed_t -R_PointToDist -( fixed_t x, - fixed_t y ) -{ - int angle; - fixed_t dx; - fixed_t dy; - fixed_t temp; - fixed_t dist; - fixed_t frac; - - dx = abs(x - viewx); - dy = abs(y - viewy); - - if (dy>dx) - { - temp = dx; - dx = dy; - dy = temp; - } - - // Fix crashes in udm1.wad - - if (dx != 0) - { - frac = FixedDiv(dy, dx); - } - else - { - frac = 0; - } - - angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT; - - // use as cosine - dist = FixedDiv (dx, finesine[angle] ); - - return dist; -} - - - - -// -// R_InitPointToAngle -// -void R_InitPointToAngle (void) -{ - // UNUSED - now getting from tables.c -#if 0 - int i; - long t; - float f; -// -// slope (tangent) to angle lookup -// - for (i=0 ; i<=SLOPERANGE ; i++) - { - f = atan( (float)i/SLOPERANGE )/(3.141592657*2); - t = 0xffffffff*f; - tantoangle[i] = t; - } -#endif -} - - -// -// R_ScaleFromGlobalAngle -// Returns the texture mapping scale -// for the current line (horizontal span) -// at the given angle. -// rw_distance must be calculated first. -// -fixed_t R_ScaleFromGlobalAngle (angle_t visangle) -{ - fixed_t scale; - angle_t anglea; - angle_t angleb; - int sinea; - int sineb; - fixed_t num; - int den; - - // UNUSED -#if 0 -{ - fixed_t dist; - fixed_t z; - fixed_t sinv; - fixed_t cosv; - - sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; - dist = FixedDiv (rw_distance, sinv); - cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; - z = abs(FixedMul (dist, cosv)); - scale = FixedDiv(projection, z); - return scale; -} -#endif - - anglea = ANG90 + (visangle-viewangle); - angleb = ANG90 + (visangle-rw_normalangle); - - // both sines are allways positive - sinea = finesine[anglea>>ANGLETOFINESHIFT]; - sineb = finesine[angleb>>ANGLETOFINESHIFT]; - num = FixedMul(projection,sineb)< num>>16) - { - scale = FixedDiv (num, den); - - if (scale > 64*FRACUNIT) - scale = 64*FRACUNIT; - else if (scale < 256) - scale = 256; - } - else - scale = 64*FRACUNIT; - - return scale; -} - - - -// -// R_InitTables -// -void R_InitTables (void) -{ - // UNUSED: now getting from tables.c -#if 0 - int i; - float a; - float fv; - int t; - - // viewangle tangent table - for (i=0 ; i FRACUNIT*2) - t = -1; - else if (finetangent[i] < -FRACUNIT*2) - t = viewwidth+1; - else - { - t = FixedMul (finetangent[i], focallength); - t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS; - - if (t < -1) - t = -1; - else if (t>viewwidth+1) - t = viewwidth+1; - } - viewangletox[i] = t; - } - - // Scan viewangletox[] to generate xtoviewangle[]: - // xtoviewangle will give the smallest view angle - // that maps to x. - for (x=0;x<=viewwidth;x++) - { - i = 0; - while (viewangletox[i]>x) - i++; - xtoviewangle[x] = (i<>= LIGHTSCALESHIFT; - level = startmap - scale/DISTMAP; - - if (level < 0) - level = 0; - - if (level >= NUMCOLORMAPS) - level = NUMCOLORMAPS-1; - - zlight[i][j] = colormaps + level*256; - } - } -} - - - -// -// R_SetViewSize -// Do not really change anything here, -// because it might be in the middle of a refresh. -// The change will take effect next refresh. -// -boolean setsizeneeded; -int setblocks; -int setdetail; - - -void -R_SetViewSize -( int blocks, - int detail ) -{ - setsizeneeded = true; - setblocks = blocks; - setdetail = detail; -} - - -// -// R_ExecuteSetViewSize -// -void R_ExecuteSetViewSize (void) -{ - fixed_t cosadj; - fixed_t dy; - int i; - int j; - int level; - int startmap; - - setsizeneeded = false; - - if (setblocks == 11) - { - scaledviewwidth = SCREENWIDTH; - viewheight = SCREENHEIGHT; - } - else - { - scaledviewwidth = setblocks*32; - viewheight = (setblocks*168/10)&~7; - } - - detailshift = setdetail; - viewwidth = scaledviewwidth>>detailshift; - - // villsa [STRIFE] calculate centery from player's pitch - centery = (setblocks*players[consoleplayer].pitch); - centery = (unsigned int)(centery/10)+viewheight/2; - - centerx = viewwidth/2; - centerxfrac = centerx< centery, accounts for up/down look - dy = ((i - centery)<>ANGLETOFINESHIFT]); - distscale[i] = FixedDiv (FRACUNIT,cosadj); - } - - // Calculate the light levels to use - // for each level / scale combination. - for (i=0 ; i< LIGHTLEVELS ; i++) - { - startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; - for (j=0 ; j= NUMCOLORMAPS) - level = NUMCOLORMAPS-1; - - scalelight[i][j] = colormaps + level*256; - } - } -} - - - -// -// R_Init -// - - - -void R_Init (void) -{ - R_InitData (); - if(devparm) - printf ("."); - else - D_IntroTick(); // [STRIFE] tick intro - - R_InitPointToAngle (); - if(devparm) - printf ("."); - - R_InitTables (); - // viewwidth / viewheight / detailLevel are set by the defaults - if(devparm) - printf ("."); - - R_SetViewSize (screenblocks, detailLevel); - R_InitPlanes (); - if(devparm) - printf ("."); - - R_InitLightTables (); - if(devparm) - printf ("."); - else - D_IntroTick(); - - R_InitSkyMap (); - if(!devparm) - D_IntroTick(); - - R_InitTranslationTables (); - if(devparm) - printf ("."); - else - D_IntroTick(); - - framecount = 0; -} - - -// -// R_PointInSubsector -// -subsector_t* -R_PointInSubsector -( fixed_t x, - fixed_t y ) -{ - node_t* node; - int side; - int nodenum; - - // single subsector is a special case - if (!numnodes) - return subsectors; - - nodenum = numnodes-1; - - while (! (nodenum & NF_SUBSECTOR) ) - { - node = &nodes[nodenum]; - side = R_PointOnSide (x, y, node); - nodenum = node->children[side]; - } - - return &subsectors[nodenum & ~NF_SUBSECTOR]; -} - -// -// R_SetupPitch -// villsa [STRIFE] new function -// Calculate centery/centeryfrac for player viewpitch -// - -void R_SetupPitch(player_t* player) -{ - int pitchfrac; - int i = 0; - - if(viewpitch != player->pitch) - { - viewpitch = player->pitch; - pitchfrac = (setblocks * player->pitch) / 10; - centery = pitchfrac + viewheight / 2; - centeryfrac = centery << FRACBITS; - - for(i = 0; i < viewheight; i++) - { - yslope[i] = FixedDiv(viewwidth / 2 * FRACUNIT, - abs(((i - centery) << FRACBITS) + (FRACUNIT/2))); - } - } -} - - -// -// R_SetupFrame -// -void R_SetupFrame (player_t* player) -{ - int i; - - R_SetupPitch(player); // villsa [STRIFE] - - viewplayer = player; - viewx = player->mo->x; - viewy = player->mo->y; - viewangle = player->mo->angle + viewangleoffset; - extralight = player->extralight; - - viewz = player->viewz; - - viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; - viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; - - sscount = 0; - - if (player->fixedcolormap) - { - fixedcolormap = - colormaps - + player->fixedcolormap*256*sizeof(lighttable_t); - - walllights = scalelightfixed; - - for (i=0 ; i -#include - -#include "i_system.h" -#include "z_zone.h" -#include "w_wad.h" - -#include "doomdef.h" -#include "doomstat.h" - -#include "r_local.h" -#include "r_sky.h" - - - -planefunction_t floorfunc; -planefunction_t ceilingfunc; - -// -// opening -// - -// Here comes the obnoxious "visplane". -// haleyjd 08/29/10: [STRIFE] MAXVISPLANES increased to 200 -#define MAXVISPLANES 200 -visplane_t visplanes[MAXVISPLANES]; -visplane_t* lastvisplane; -visplane_t* floorplane; -visplane_t* ceilingplane; - -// ? -#define MAXOPENINGS SCREENWIDTH*64 -short openings[MAXOPENINGS]; -short* lastopening; - - -// -// Clip values are the solid pixel bounding the range. -// floorclip starts out SCREENHEIGHT -// ceilingclip starts out -1 -// -short floorclip[SCREENWIDTH]; -short ceilingclip[SCREENWIDTH]; - -// -// spanstart holds the start of a plane span -// initialized to 0 at start -// -int spanstart[SCREENHEIGHT]; -int spanstop[SCREENHEIGHT]; - -// -// texture mapping -// -lighttable_t** planezlight; -fixed_t planeheight; - -fixed_t yslope[SCREENHEIGHT]; -fixed_t distscale[SCREENWIDTH]; -fixed_t basexscale; -fixed_t baseyscale; - -fixed_t cachedheight[SCREENHEIGHT]; -fixed_t cacheddistance[SCREENHEIGHT]; -fixed_t cachedxstep[SCREENHEIGHT]; -fixed_t cachedystep[SCREENHEIGHT]; - - - -// -// R_InitPlanes -// Only at game startup. -// -void R_InitPlanes (void) -{ - // Doh! -} - - -// -// R_MapPlane -// -// Uses global vars: -// planeheight -// ds_source -// basexscale -// baseyscale -// viewx -// viewy -// -// BASIC PRIMITIVE -// -void -R_MapPlane -( int y, - int x1, - int x2 ) -{ - angle_t angle; - fixed_t distance; - fixed_t length; - unsigned index; - -#ifdef RANGECHECK - if (x2 < x1 - || x1 < 0 - || x2 >= viewwidth - || y > viewheight) - { - I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y); - } -#endif - - if (planeheight != cachedheight[y]) - { - cachedheight[y] = planeheight; - distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]); - ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale); - ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale); - } - else - { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; - } - - length = FixedMul (distance,distscale[x1]); - angle = (viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; - ds_xfrac = viewx + FixedMul(finecosine[angle], length); - ds_yfrac = -viewy - FixedMul(finesine[angle], length); - - if (fixedcolormap) - ds_colormap = fixedcolormap; - else - { - index = distance >> LIGHTZSHIFT; - - if (index >= MAXLIGHTZ ) - index = MAXLIGHTZ-1; - - ds_colormap = planezlight[index]; - } - - ds_y = y; - ds_x1 = x1; - ds_x2 = x2; - - // high or low detail - spanfunc (); -} - - -// -// R_ClearPlanes -// At begining of frame. -// -void R_ClearPlanes (void) -{ - int i; - angle_t angle; - - // opening / clipping determination - for (i=0 ; i>ANGLETOFINESHIFT; - - // scale will be unit scale at SCREENWIDTH/2 distance - basexscale = FixedDiv (finecosine[angle],centerxfrac); - baseyscale = -FixedDiv (finesine[angle],centerxfrac); -} - - - - -// -// R_FindPlane -// -visplane_t* -R_FindPlane -( fixed_t height, - int picnum, - int lightlevel ) -{ - visplane_t* check; - - if (picnum == skyflatnum) - { - height = 0; // all skys map together - lightlevel = 0; - } - - for (check=visplanes; checkheight - && picnum == check->picnum - && lightlevel == check->lightlevel) - { - break; - } - } - - - if (check < lastvisplane) - return check; - - if (lastvisplane - visplanes == MAXVISPLANES) - I_Error ("R_FindPlane: no more visplanes"); - - lastvisplane++; - - check->height = height; - check->picnum = picnum; - check->lightlevel = lightlevel; - check->minx = SCREENWIDTH; - check->maxx = -1; - - memset (check->top,0xff,sizeof(check->top)); - - return check; -} - - -// -// R_CheckPlane -// -visplane_t* -R_CheckPlane -( visplane_t* pl, - int start, - int stop ) -{ - int intrl; - int intrh; - int unionl; - int unionh; - int x; - - if (start < pl->minx) - { - intrl = pl->minx; - unionl = start; - } - else - { - unionl = pl->minx; - intrl = start; - } - - if (stop > pl->maxx) - { - intrh = pl->maxx; - unionh = stop; - } - else - { - unionh = pl->maxx; - intrh = stop; - } - - for (x=intrl ; x<= intrh ; x++) - if (pl->top[x] != 0xff) - break; - - if (x > intrh) - { - pl->minx = unionl; - pl->maxx = unionh; - - // use the same one - return pl; - } - - // make a new visplane - lastvisplane->height = pl->height; - lastvisplane->picnum = pl->picnum; - lastvisplane->lightlevel = pl->lightlevel; - - pl = lastvisplane++; - pl->minx = start; - pl->maxx = stop; - - memset (pl->top,0xff,sizeof(pl->top)); - - return pl; -} - - -// -// R_MakeSpans -// -void -R_MakeSpans -( int x, - int t1, - int b1, - int t2, - int b2 ) -{ - while (t1 < t2 && t1<=b1) - { - R_MapPlane (t1,spanstart[t1],x-1); - t1++; - } - while (b1 > b2 && b1>=t1) - { - R_MapPlane (b1,spanstart[b1],x-1); - b1--; - } - - while (t2 < t1 && t2<=b2) - { - spanstart[t2] = x; - t2++; - } - while (b2 > b1 && b2>=t2) - { - spanstart[b2] = x; - b2--; - } -} - - - -// -// R_DrawPlanes -// At the end of each frame. -// -void R_DrawPlanes (void) -{ - visplane_t* pl; - int light; - int x; - int stop; - int angle; - int lumpnum; - -#ifdef RANGECHECK - if (ds_p - drawsegs > MAXDRAWSEGS) - I_Error ("R_DrawPlanes: drawsegs overflow (%td)", - ds_p - drawsegs); - - if (lastvisplane - visplanes > MAXVISPLANES) - I_Error ("R_DrawPlanes: visplane overflow (%td)", - lastvisplane - visplanes); - - if (lastopening - openings > MAXOPENINGS) - I_Error ("R_DrawPlanes: opening overflow (%td)", - lastopening - openings); -#endif - - for (pl = visplanes ; pl < lastvisplane ; pl++) - { - if (pl->minx > pl->maxx) - continue; - - - // sky flat - if (pl->picnum == skyflatnum) - { - dc_iscale = pspriteiscale>>detailshift; - - // Sky is allways drawn full bright, - // i.e. colormaps[0] is used. - // Because of this hack, sky is not affected - // by INVUL inverse mapping. - dc_colormap = colormaps; - dc_texturemid = skytexturemid; - for (x=pl->minx ; x <= pl->maxx ; x++) - { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; - - if (dc_yl <= dc_yh) - { - angle = (viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; - dc_x = x; - dc_source = R_GetColumn(skytexture, angle); - colfunc (); - } - } - continue; - } - - // regular flat - lumpnum = firstflat + flattranslation[pl->picnum]; - ds_source = W_CacheLumpNum(lumpnum, PU_STATIC); - - planeheight = abs(pl->height-viewz); - light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (light >= LIGHTLEVELS) - light = LIGHTLEVELS-1; - - if (light < 0) - light = 0; - - planezlight = zlight[light]; - - pl->top[pl->maxx+1] = 0xff; - pl->top[pl->minx-1] = 0xff; - - stop = pl->maxx + 1; - - for (x=pl->minx ; x<= stop ; x++) - { - R_MakeSpans(x,pl->top[x-1], - pl->bottom[x-1], - pl->top[x], - pl->bottom[x]); - } - - W_ReleaseLumpNum(lumpnum); - } -} diff --git a/games/NXDoom/src/strife/r_plane.h b/games/NXDoom/src/strife/r_plane.h deleted file mode 100644 index 57b50e5bc5e..00000000000 --- a/games/NXDoom/src/strife/r_plane.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh, visplane stuff (floor, ceilings). -// - - -#ifndef __R_PLANE__ -#define __R_PLANE__ - - -#include "r_data.h" - - - -// Visplane related. -extern short* lastopening; - - -typedef void (*planefunction_t) (int top, int bottom); - -extern planefunction_t floorfunc; -extern planefunction_t ceilingfunc_t; - -extern short floorclip[SCREENWIDTH]; -extern short ceilingclip[SCREENWIDTH]; - -extern fixed_t yslope[SCREENHEIGHT]; -extern fixed_t distscale[SCREENWIDTH]; - -void R_InitPlanes (void); -void R_ClearPlanes (void); - -void -R_MapPlane -( int y, - int x1, - int x2 ); - -void -R_MakeSpans -( int x, - int t1, - int b1, - int t2, - int b2 ); - -void R_DrawPlanes (void); - -visplane_t* -R_FindPlane -( fixed_t height, - int picnum, - int lightlevel ); - -visplane_t* -R_CheckPlane -( visplane_t* pl, - int start, - int stop ); - - - -#endif diff --git a/games/NXDoom/src/strife/r_segs.c b/games/NXDoom/src/strife/r_segs.c deleted file mode 100644 index 179565035a2..00000000000 --- a/games/NXDoom/src/strife/r_segs.c +++ /dev/null @@ -1,754 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// All the clipping: columns, horizontal spans, sky columns. -// - - - - - - -#include -#include - -#include "i_system.h" - -#include "doomdef.h" -#include "doomstat.h" - -#include "r_local.h" -#include "r_sky.h" - - -// OPTIMIZE: closed two sided lines as single sided - -// True if any of the segs textures might be visible. -boolean segtextured; - -// False if the back side is the same plane. -boolean markfloor; -boolean markceiling; - -boolean maskedtexture; -int toptexture; -int bottomtexture; -int midtexture; - - -angle_t rw_normalangle; -// angle to line origin -int rw_angle1; - -// -// regular wall -// -int rw_x; -int rw_stopx; -angle_t rw_centerangle; -fixed_t rw_offset; -fixed_t rw_distance; -fixed_t rw_scale; -fixed_t rw_scalestep; -fixed_t rw_midtexturemid; -fixed_t rw_toptexturemid; -fixed_t rw_bottomtexturemid; - -int worldtop; -int worldbottom; -int worldhigh; -int worldlow; - -fixed_t pixhigh; -fixed_t pixlow; -fixed_t pixhighstep; -fixed_t pixlowstep; - -fixed_t topfrac; -fixed_t topstep; - -fixed_t bottomfrac; -fixed_t bottomstep; - - -lighttable_t** walllights; - -short* maskedtexturecol; - - - -// -// R_RenderMaskedSegRange -// -void -R_RenderMaskedSegRange -( drawseg_t* ds, - int x1, - int x2 ) -{ - unsigned index; - column_t* col; - int lightnum; - int texnum; - - // Calculate light table. - // Use different light tables - // for horizontal / vertical / diagonal. Diagonal? - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - curline = ds->curline; - frontsector = curline->frontsector; - backsector = curline->backsector; - texnum = texturetranslation[curline->sidedef->midtexture]; - - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS-1]; - else - walllights = scalelight[lightnum]; - - maskedtexturecol = ds->maskedtexturecol; - - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; - mfloorclip = ds->sprbottomclip; - mceilingclip = ds->sprtopclip; - - // find positioning - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - { - dc_texturemid = frontsector->floorheight > backsector->floorheight - ? frontsector->floorheight : backsector->floorheight; - dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; - } - else - { - dc_texturemid =frontsector->ceilingheightceilingheight - ? frontsector->ceilingheight : backsector->ceilingheight; - dc_texturemid = dc_texturemid - viewz; - } - dc_texturemid += curline->sidedef->rowoffset; - - if (fixedcolormap) - dc_colormap = fixedcolormap; - - // villsa [STRIFE] render as transparent (25% or 75%?) - if(curline->linedef->flags & ML_TRANSPARENT1) - colfunc = fuzzcolfunc; - - // villsa [STRIFE] render as transparent (25% or 75%?) - if(curline->linedef->flags & ML_TRANSPARENT2) - colfunc = R_DrawMVisTLColumn; - - // draw the columns - for (dc_x = x1 ; dc_x <= x2 ; dc_x++) - { - // calculate lighting - if (maskedtexturecol[dc_x] != SHRT_MAX) - { - if (!fixedcolormap) - { - index = spryscale>>LIGHTSCALESHIFT; - - if (index >= MAXLIGHTSCALE ) - index = MAXLIGHTSCALE-1; - - dc_colormap = walllights[index]; - } - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)( - (byte *)R_GetColumn(texnum,maskedtexturecol[dc_x]) -3); - - // villsa [STRIFE] added 0 argument - R_DrawMaskedColumn (col, 0); - maskedtexturecol[dc_x] = SHRT_MAX; - } - spryscale += rw_scalestep; - } - - colfunc = basecolfunc; // villsa [STRIFE] reset draw routines - -} - - - - -// -// R_RenderSegLoop -// Draws zero, one, or two textures (and possibly a masked -// texture) for walls. -// Can draw or mark the starting pixel of floor and ceiling -// textures. -// CALLED: CORE LOOPING ROUTINE. -// -#define HEIGHTBITS 12 -#define HEIGHTUNIT (1<>HEIGHTBITS; - - // no space above wall? - if (yl < ceilingclip[rw_x]+1) - yl = ceilingclip[rw_x]+1; - - if (markceiling) - { - top = ceilingclip[rw_x]+1; - bottom = yl-1; - - if (bottom >= floorclip[rw_x]) - bottom = floorclip[rw_x]-1; - - if (top <= bottom) - { - ceilingplane->top[rw_x] = top; - ceilingplane->bottom[rw_x] = bottom; - } - } - - yh = bottomfrac>>HEIGHTBITS; - - if (yh >= floorclip[rw_x]) - yh = floorclip[rw_x]-1; - - if (markfloor) - { - top = yh+1; - bottom = floorclip[rw_x]-1; - if (top <= ceilingclip[rw_x]) - top = ceilingclip[rw_x]+1; - if (top <= bottom) - { - floorplane->top[rw_x] = top; - floorplane->bottom[rw_x] = bottom; - } - } - - // texturecolumn and lighting are independent of wall tiers - if (segtextured) - { - // calculate texture offset - angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; - texturecolumn = rw_offset-FixedMul(finetangent[angle],rw_distance); - texturecolumn >>= FRACBITS; - // calculate lighting - index = rw_scale>>LIGHTSCALESHIFT; - - if (index >= MAXLIGHTSCALE ) - index = MAXLIGHTSCALE-1; - - dc_colormap = walllights[index]; - dc_x = rw_x; - dc_iscale = 0xffffffffu / (unsigned)rw_scale; - } - else - { - // purely to shut up the compiler - - texturecolumn = 0; - } - - // draw the wall tiers - if (midtexture) - { - // single sided line - dc_yl = yl; - dc_yh = yh; - dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn); - colfunc (); - ceilingclip[rw_x] = viewheight; - floorclip[rw_x] = -1; - } - else - { - // two sided line - if (toptexture) - { - // top wall - mid = pixhigh>>HEIGHTBITS; - pixhigh += pixhighstep; - - if (mid >= floorclip[rw_x]) - mid = floorclip[rw_x]-1; - - if (mid >= yl) - { - dc_yl = yl; - dc_yh = mid; - dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn); - colfunc (); - ceilingclip[rw_x] = mid; - } - else - ceilingclip[rw_x] = yl-1; - } - else - { - // no top wall - if (markceiling) - ceilingclip[rw_x] = yl-1; - } - - if (bottomtexture) - { - // bottom wall - mid = (pixlow+HEIGHTUNIT-1)>>HEIGHTBITS; - pixlow += pixlowstep; - - // no space above wall? - if (mid <= ceilingclip[rw_x]) - mid = ceilingclip[rw_x]+1; - - if (mid <= yh) - { - dc_yl = mid; - dc_yh = yh; - dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn); - colfunc (); - floorclip[rw_x] = mid; - } - else - floorclip[rw_x] = yh+1; - } - else - { - // no bottom wall - if (markfloor) - floorclip[rw_x] = yh+1; - } - - if (maskedtexture) - { - // save texturecol - // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = texturecolumn; - } - } - - rw_scale += rw_scalestep; - topfrac += topstep; - bottomfrac += bottomstep; - } -} - - - - -// -// R_StoreWallRange -// A wall segment will be drawn -// between start and stop pixels (inclusive). -// -void -R_StoreWallRange -( int start, - int stop ) -{ - fixed_t hyp; - fixed_t sineval; - angle_t distangle, offsetangle; - fixed_t vtop; - int lightnum; - - // don't overflow and crash - if (ds_p == &drawsegs[MAXDRAWSEGS]) - return; - -#ifdef RANGECHECK - if (start >=viewwidth || start > stop) - I_Error ("Bad R_RenderWallRange: %i to %i", start , stop); -#endif - - sidedef = curline->sidedef; - linedef = curline->linedef; - - // mark the segment as visible for auto map - linedef->flags |= ML_MAPPED; - - // calculate rw_distance for scale calculation - rw_normalangle = curline->angle + ANG90; - offsetangle = abs((int) rw_normalangle - (int) rw_angle1); - - if (offsetangle > ANG90) - offsetangle = ANG90; - - distangle = ANG90 - offsetangle; - hyp = R_PointToDist (curline->v1->x, curline->v1->y); - sineval = finesine[distangle>>ANGLETOFINESHIFT]; - rw_distance = FixedMul (hyp, sineval); - - - ds_p->x1 = rw_x = start; - ds_p->x2 = stop; - ds_p->curline = curline; - rw_stopx = stop+1; - - // calculate scale at both ends and step - ds_p->scale1 = rw_scale = - R_ScaleFromGlobalAngle (viewangle + xtoviewangle[start]); - - if (stop > start ) - { - ds_p->scale2 = R_ScaleFromGlobalAngle (viewangle + xtoviewangle[stop]); - ds_p->scalestep = rw_scalestep = - (ds_p->scale2 - rw_scale) / (stop-start); - } - else - { - // UNUSED: try to fix the stretched line bug -#if 0 - if (rw_distance < FRACUNIT/2) - { - fixed_t trx,try; - fixed_t gxt,gyt; - - trx = curline->v1->x - viewx; - try = curline->v1->y - viewy; - - gxt = FixedMul(trx,viewcos); - gyt = -FixedMul(try,viewsin); - ds_p->scale1 = FixedDiv(projection, gxt-gyt)<scale2 = ds_p->scale1; - } - - // calculate texture boundaries - // and decide if floor / ceiling marks are needed - worldtop = frontsector->ceilingheight - viewz; - worldbottom = frontsector->floorheight - viewz; - - midtexture = toptexture = bottomtexture = maskedtexture = 0; - ds_p->maskedtexturecol = NULL; - - if (!backsector) - { - // single sided line - midtexture = texturetranslation[sidedef->midtexture]; - // a single sided line is terminal, so it must mark ends - markfloor = markceiling = true; - if (linedef->flags & ML_DONTPEGBOTTOM) - { - vtop = frontsector->floorheight + - textureheight[sidedef->midtexture]; - // bottom of texture at bottom - rw_midtexturemid = vtop - viewz; - } - else - { - // top of texture at top - rw_midtexturemid = worldtop; - } - rw_midtexturemid += sidedef->rowoffset; - - ds_p->silhouette = SIL_BOTH; - ds_p->sprtopclip = screenheightarray; - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->tsilheight = INT_MIN; - } - else - { - // two sided line - ds_p->sprtopclip = ds_p->sprbottomclip = NULL; - ds_p->silhouette = 0; - - if (frontsector->floorheight > backsector->floorheight) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = frontsector->floorheight; - } - else if (backsector->floorheight > viewz) - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; - // ds_p->sprbottomclip = negonearray; - } - - if (frontsector->ceilingheight < backsector->ceilingheight) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = frontsector->ceilingheight; - } - else if (backsector->ceilingheight < viewz) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; - // ds_p->sprtopclip = screenheightarray; - } - - if (backsector->ceilingheight <= frontsector->floorheight) - { - ds_p->sprbottomclip = negonearray; - ds_p->bsilheight = INT_MAX; - ds_p->silhouette |= SIL_BOTTOM; - } - - if (backsector->floorheight >= frontsector->ceilingheight) - { - ds_p->sprtopclip = screenheightarray; - ds_p->tsilheight = INT_MIN; - ds_p->silhouette |= SIL_TOP; - } - - worldhigh = backsector->ceilingheight - viewz; - worldlow = backsector->floorheight - viewz; - - // hack to allow height changes in outdoor areas - if (frontsector->ceilingpic == skyflatnum - && backsector->ceilingpic == skyflatnum) - { - worldtop = worldhigh; - } - - - if (worldlow != worldbottom - || backsector->floorpic != frontsector->floorpic - || backsector->lightlevel != frontsector->lightlevel) - { - markfloor = true; - } - else - { - // same plane on both sides - markfloor = false; - } - - - if (worldhigh != worldtop - || backsector->ceilingpic != frontsector->ceilingpic - || backsector->lightlevel != frontsector->lightlevel) - { - markceiling = true; - } - else - { - // same plane on both sides - markceiling = false; - } - - if (backsector->ceilingheight <= frontsector->floorheight - || backsector->floorheight >= frontsector->ceilingheight) - { - // closed door - markceiling = markfloor = true; - } - - - if (worldhigh < worldtop) - { - // top texture - toptexture = texturetranslation[sidedef->toptexture]; - if (linedef->flags & ML_DONTPEGTOP) - { - // top of texture at top - rw_toptexturemid = worldtop; - } - else - { - vtop = - backsector->ceilingheight - + textureheight[sidedef->toptexture]; - - // bottom of texture - rw_toptexturemid = vtop - viewz; - } - } - if (worldlow > worldbottom) - { - // bottom texture - bottomtexture = texturetranslation[sidedef->bottomtexture]; - - if (linedef->flags & ML_DONTPEGBOTTOM ) - { - // bottom of texture at bottom - // top of texture at top - rw_bottomtexturemid = worldtop; - } - else // top of texture at top - rw_bottomtexturemid = worldlow; - } - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; - - // allocate space for masked texture tables - if (sidedef->midtexture) - { - // masked midtexture - maskedtexture = true; - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; - } - } - - // calculate rw_offset (only needed for textured lines) - segtextured = midtexture | toptexture | bottomtexture | maskedtexture; - - if (segtextured) - { - offsetangle = rw_normalangle-rw_angle1; - - if (offsetangle > ANG180) - offsetangle = 0 - offsetangle; - - if (offsetangle > ANG90) - offsetangle = ANG90; - - sineval = finesine[offsetangle >>ANGLETOFINESHIFT]; - rw_offset = FixedMul (hyp, sineval); - - if (rw_normalangle-rw_angle1 < ANG180) - rw_offset = -rw_offset; - - rw_offset += sidedef->textureoffset + curline->offset; - rw_centerangle = ANG90 + viewangle - rw_normalangle; - - // calculate light table - // use different light tables - // for horizontal / vertical / diagonal - // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - if (!fixedcolormap) - { - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (curline->v1->y == curline->v2->y) - lightnum--; - else if (curline->v1->x == curline->v2->x) - lightnum++; - - if (lightnum < 0) - walllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - walllights = scalelight[LIGHTLEVELS-1]; - else - walllights = scalelight[lightnum]; - } - } - - // if a floor / ceiling plane is on the wrong side - // of the view plane, it is definitely invisible - // and doesn't need to be marked. - - - if (frontsector->floorheight >= viewz) - { - // above view plane - markfloor = false; - } - - if (frontsector->ceilingheight <= viewz - && frontsector->ceilingpic != skyflatnum) - { - // below view plane - markceiling = false; - } - - - // calculate incremental stepping values for texture edges - worldtop >>= 4; - worldbottom >>= 4; - - topstep = -FixedMul (rw_scalestep, worldtop); - topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); - - bottomstep = -FixedMul (rw_scalestep,worldbottom); - bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); - - if (backsector) - { - worldhigh >>= 4; - worldlow >>= 4; - - if (worldhigh < worldtop) - { - pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); - pixhighstep = -FixedMul (rw_scalestep,worldhigh); - } - - if (worldlow > worldbottom) - { - pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); - pixlowstep = -FixedMul (rw_scalestep,worldlow); - } - } - - // render it - if (markceiling) - ceilingplane = R_CheckPlane (ceilingplane, rw_x, rw_stopx-1); - - if (markfloor) - floorplane = R_CheckPlane (floorplane, rw_x, rw_stopx-1); - - R_RenderSegLoop (); - - - // save sprite clipping info - if ( ((ds_p->silhouette & SIL_TOP) || maskedtexture) - && !ds_p->sprtopclip) - { - memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } - - if ( ((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) - && !ds_p->sprbottomclip) - { - memcpy (lastopening, floorclip+start, 2*(rw_stopx-start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; - } - - if (maskedtexture && !(ds_p->silhouette&SIL_TOP)) - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT_MIN; - } - if (maskedtexture && !(ds_p->silhouette&SIL_BOTTOM)) - { - ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = INT_MAX; - } - ds_p++; -} - diff --git a/games/NXDoom/src/strife/r_segs.h b/games/NXDoom/src/strife/r_segs.h deleted file mode 100644 index 8e6a768f454..00000000000 --- a/games/NXDoom/src/strife/r_segs.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh module, drawing LineSegs from BSP. -// - - -#ifndef __R_SEGS__ -#define __R_SEGS__ - - -extern lighttable_t **walllights; - - -void -R_RenderMaskedSegRange -( drawseg_t* ds, - int x1, - int x2 ); - - -#endif diff --git a/games/NXDoom/src/strife/r_sky.c b/games/NXDoom/src/strife/r_sky.c deleted file mode 100644 index 007740a8a1c..00000000000 --- a/games/NXDoom/src/strife/r_sky.c +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Sky rendering. The DOOM sky is a texture map like any -// wall, wrapping around. A 1024 columns equal 360 degrees. -// The default sky map is 256 columns and repeats 4 times -// on a 320 screen? -// -// - - - -// Needed for FRACUNIT. -#include "m_fixed.h" - -// Needed for Flat retrieval. -#include "r_data.h" - - -#include "r_sky.h" - -// -// sky mapping -// -int skyflatnum; -int skytexture; -int skytexturemid; - - - -// -// R_InitSkyMap -// Called whenever the view size changes. -// -void R_InitSkyMap (void) -{ - // haleyjd 10/03/10: [STRIFE] Sky is set here, not in G_DoLoadLevel. - // Also skytexturemid changed from 100 to 199. - skyflatnum = R_FlatNumForName ( SKYFLATNAME ); - skytexturemid = 199*FRACUNIT; -} - diff --git a/games/NXDoom/src/strife/r_sky.h b/games/NXDoom/src/strife/r_sky.h deleted file mode 100644 index fbcfa1ae9bd..00000000000 --- a/games/NXDoom/src/strife/r_sky.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Sky rendering. -// - - -#ifndef __R_SKY__ -#define __R_SKY__ - - - -// SKY, store the number for name. -#define SKYFLATNAME "F_SKY001" // villsa [STRIFE] - -// The sky map is 256*128*4 maps. -#define ANGLETOSKYSHIFT 22 - -extern int skytexture; -extern int skytexturemid; - -// Called whenever the view size changes. -void R_InitSkyMap (void); - -#endif diff --git a/games/NXDoom/src/strife/r_state.h b/games/NXDoom/src/strife/r_state.h deleted file mode 100644 index 2a60e2fe8e1..00000000000 --- a/games/NXDoom/src/strife/r_state.h +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh/render internal state variables (global). -// - - -#ifndef __R_STATE__ -#define __R_STATE__ - -// Need data structure definitions. -#include "d_player.h" -#include "r_data.h" - - - - - - -// -// Refresh internal data structures, -// for rendering. -// - -// needed for texture pegging -extern fixed_t* textureheight; - -// needed for pre rendering (fracs) -extern fixed_t* spritewidth; - -extern fixed_t* spriteoffset; -extern fixed_t* spritetopoffset; - -extern lighttable_t* colormaps; - -extern int viewwidth; -extern int scaledviewwidth; -extern int viewheight; - -extern int firstflat; - -// for global animation -extern int* flattranslation; -extern int* texturetranslation; - - -// Sprite.... -extern int firstspritelump; -extern int lastspritelump; -extern int numspritelumps; - - - -// -// Lookup tables for map data. -// -extern int numsprites; -extern spritedef_t* sprites; - -extern int numvertexes; -extern vertex_t* vertexes; - -extern int numsegs; -extern seg_t* segs; - -extern int numsectors; -extern sector_t* sectors; - -extern int numsubsectors; -extern subsector_t* subsectors; - -extern int numnodes; -extern node_t* nodes; - -extern int numlines; -extern line_t* lines; - -extern int numsides; -extern side_t* sides; - - -// -// POV data. -// -extern fixed_t viewx; -extern fixed_t viewy; -extern fixed_t viewz; - -extern angle_t viewangle; -extern player_t* viewplayer; - - -// ? -extern angle_t clipangle; - -extern int viewangletox[FINEANGLES/2]; -extern angle_t xtoviewangle[SCREENWIDTH+1]; -//extern fixed_t finetangent[FINEANGLES/2]; - -extern fixed_t rw_distance; -extern angle_t rw_normalangle; - - - -// angle to line origin -extern int rw_angle1; - -// Segs count? -extern int sscount; - -extern visplane_t* floorplane; -extern visplane_t* ceilingplane; - - -#endif diff --git a/games/NXDoom/src/strife/r_things.c b/games/NXDoom/src/strife/r_things.c deleted file mode 100644 index e49f7bc104c..00000000000 --- a/games/NXDoom/src/strife/r_things.c +++ /dev/null @@ -1,1067 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh of things, i.e. objects represented by sprites. -// - - - - -#include -#include - - -#include "deh_main.h" -#include "doomdef.h" - -#include "i_swap.h" -#include "i_system.h" -#include "z_zone.h" -#include "w_wad.h" - -#include "r_local.h" - -#include "doomstat.h" - -// haleyjd -#include "p_local.h" - - - -#define MINZ (FRACUNIT*4) -#define BASEYCENTER 100 - -//void R_DrawColumn (void); -//void R_DrawFuzzColumn (void); - - - -typedef struct -{ - int x1; - int x2; - - int column; - int topclip; - int bottomclip; - -} maskdraw_t; - - - -// -// Sprite rotation 0 is facing the viewer, -// rotation 1 is one angle turn CLOCKWISE around the axis. -// This is not the same as the angle, -// which increases counter clockwise (protractor). -// There was a lot of stuff grabbed wrong, so I changed it... -// -fixed_t pspritescale; -fixed_t pspriteiscale; - -lighttable_t** spritelights; - -// constant arrays -// used for psprite clipping and initializing clipping -short negonearray[SCREENWIDTH]; -short screenheightarray[SCREENWIDTH]; - - -// -// INITIALIZATION FUNCTIONS -// - -// variables used to look up -// and range check thing_t sprites patches -spritedef_t* sprites; -int numsprites; - -spriteframe_t sprtemp[29]; -int maxframe; -const char *spritename; - - - - -// -// R_InstallSpriteLump -// Local function for R_InitSprites. -// -void -R_InstallSpriteLump -( int lump, - unsigned frame, - unsigned rotation, - boolean flipped ) -{ - int r; - - if (frame >= 29 || rotation > 8) - I_Error("R_InstallSpriteLump: " - "Bad frame characters in lump %i", lump); - - if ((int)frame > maxframe) - maxframe = frame; - - if (rotation == 0) - { - // the lump should be used for all rotations - if (sprtemp[frame].rotate == false) - I_Error ("R_InitSprites: Sprite %s frame %c has " - "multip rot=0 lump", spritename, 'A'+frame); - - if (sprtemp[frame].rotate == true) - I_Error ("R_InitSprites: Sprite %s frame %c has rotations " - "and a rot=0 lump", spritename, 'A'+frame); - - sprtemp[frame].rotate = false; - for (r=0 ; r<8 ; r++) - { - sprtemp[frame].lump[r] = lump - firstspritelump; - sprtemp[frame].flip[r] = (byte)flipped; - } - return; - } - - // the lump is only used for one rotation - if (sprtemp[frame].rotate == false) - I_Error ("R_InitSprites: Sprite %s frame %c has rotations " - "and a rot=0 lump", spritename, 'A'+frame); - - sprtemp[frame].rotate = true; - - // make 0 based - rotation--; - if (sprtemp[frame].lump[rotation] != -1) - I_Error ("R_InitSprites: Sprite %s : %c : %c " - "has two lumps mapped to it", - spritename, 'A'+frame, '1'+rotation); - - sprtemp[frame].lump[rotation] = lump - firstspritelump; - sprtemp[frame].flip[rotation] = (byte)flipped; -} - - - - -// -// R_InitSpriteDefs -// Pass a null terminated list of sprite names -// (4 chars exactly) to be used. -// Builds the sprite rotation matrixes to account -// for horizontally flipped sprites. -// Will report an error if the lumps are inconsistant. -// Only called at startup. -// -// Sprite lump names are 4 characters for the actor, -// a letter for the frame, and a number for the rotation. -// A sprite that is flippable will have an additional -// letter/number appended. -// The rotation character can be 0 to signify no rotations. -// -void R_InitSpriteDefs (const char** namelist) -{ - const char **check; - int i; - int l; - int frame; - int rotation; - int start; - int end; - int patched; - - // count the number of sprite names - check = namelist; - while (*check != NULL) - check++; - - numsprites = check-namelist; - - if (!numsprites) - return; - - sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); - - start = firstspritelump-1; - end = lastspritelump+1; - - // scan all the lump names for each of the names, - // noting the highest frame letter. - // Just compare 4 characters as ints - for (i=0 ; iname, spritename, 4)) - { - frame = lumpinfo[l]->name[4] - 'A'; - rotation = lumpinfo[l]->name[5] - '0'; - - if (modifiedgame) - patched = W_GetNumForName (lumpinfo[l]->name); - else - patched = l; - - R_InstallSpriteLump (patched, frame, rotation, false); - - if (lumpinfo[l]->name[6]) - { - frame = lumpinfo[l]->name[6] - 'A'; - rotation = lumpinfo[l]->name[7] - '0'; - R_InstallSpriteLump (l, frame, rotation, true); - } - } - } - - // check the frames that were found for completeness - if (maxframe == -1) - { - sprites[i].numframes = 0; - continue; - } - - maxframe++; - - for (frame = 0 ; frame < maxframe ; frame++) - { - switch ((int)sprtemp[frame].rotate) - { - case -1: - // no rotations were found for that frame at all - I_Error ("R_InitSprites: No patches found " - "for %s frame %c", spritename, frame+'A'); - break; - - case 0: - // only the first rotation is needed - break; - - case 1: - // must have all 8 frames - for (rotation=0 ; rotation<8 ; rotation++) - if (sprtemp[frame].lump[rotation] == -1) - I_Error ("R_InitSprites: Sprite %s frame %c " - "is missing rotations", - spritename, frame+'A'); - break; - } - } - - // allocate space for the frames present and copy sprtemp to it - sprites[i].numframes = maxframe; - sprites[i].spriteframes = - Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); - memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); - } - -} - - - - -// -// GAME FUNCTIONS -// -vissprite_t vissprites[MAXVISSPRITES]; -vissprite_t* vissprite_p; -int newvissprite; -int sprbotscreen; // villsa [STRIFE] - - - -// -// R_InitSprites -// Called at program start. -// -void R_InitSprites (const char** namelist) -{ - int i; - - for (i=0 ; itopdelta != 0xff ; ) - { - // calculate unclipped screen coordinates - // for post - topscreen = sprtopscreen + spryscale*column->topdelta; - bottomscreen = topscreen + spryscale*column->length; - - dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; - dc_yh = (bottomscreen-1)>>FRACBITS; - - if (dc_yh >= mfloorclip[dc_x]) - dc_yh = mfloorclip[dc_x]-1; - if (dc_yl <= mceilingclip[dc_x]) - dc_yl = mceilingclip[dc_x]+1; - - // villsa [STRIFE] checks for clipping - if(baseclip) - { - if(dc_yh > baseclip) - dc_yh = baseclip; - } - - if (dc_yl <= dc_yh) - { - dc_source = (byte *)column + 3; - dc_texturemid = basetexturemid - (column->topdelta<topdelta; - - // Drawn by either R_DrawColumn - // or (SHADOW) R_DrawFuzzColumn. - colfunc (); - } - column = (column_t *)( (byte *)column + column->length + 4); - } - - dc_texturemid = basetexturemid; -} - - - -// -// R_DrawVisSprite -// mfloorclip and mceilingclip should also be set. -// -void -R_DrawVisSprite -( vissprite_t* vis, - int x1, - int x2 ) -{ - column_t* column; - int texturecolumn; - fixed_t frac; - patch_t* patch; - int clip; // villsa [STRIFE] - int translation; // villsa [STRIFE] - - patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); - - dc_colormap = vis->colormap; - - // villsa [STRIFE] - // haleyjd 09/06/10: updated MF_TRANSLATION for Strife - translation = vis->mobjflags & MF_TRANSLATION; - - // villsa [STRIFE] unused - /*if (!dc_colormap) - { - // NULL colormap = shadow draw - colfunc = fuzzcolfunc; - }*/ - - // villsa [STRIFE] Handle the two types of translucency - if(vis->mobjflags & MF_SHADOW) - { - if(!translation) - { - if(vis->mobjflags & MF_MVIS) - colfunc = R_DrawMVisTLColumn; - else - colfunc = fuzzcolfunc; - } - else - { - colfunc = R_DrawTRTLColumn; - dc_translation = translationtables - 256 + (translation >> (MF_TRANSSHIFT - 8)); - } - } - else if(vis->mobjflags & MF_MVIS) - { - // haleyjd 20141215: [STRIFE] Objects which are *only* MF_MVIS (players - // using double Shadow Armors, in particular) are totally invisible. - // Upstreamed after discovered in SVE. Note this causes a - // vanilla-accurate glitch with Shadow Acolytes - if they die while - // MF_MVIS is set, A_Fall fails to remove it and their corpse will - // completely disappear (that's also fixed in SVE, but not here). - return; - } - else if(translation) // villsa [STRIFE] new translation tables - { - colfunc = transcolfunc; - dc_translation = translationtables - 256 + (translation >> (MF_TRANSSHIFT - 8)); - } - - dc_iscale = abs(vis->xiscale)>>detailshift; - dc_texturemid = vis->texturemid; - frac = vis->startfrac; - spryscale = vis->scale; - sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); - - // villsa [STRIFE] clip sprite's feet if needed - if(vis->mobjflags & MF_FEETCLIPPED) - { - sprbotscreen = sprtopscreen + FixedMul(spryscale, SHORT(patch->height) << FRACBITS); - clip = (sprbotscreen - FixedMul(10*FRACUNIT, spryscale)) >> FRACBITS; - } - else - clip = 0; - - for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) - { - texturecolumn = frac>>FRACBITS; -#ifdef RANGECHECK - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - I_Error ("R_DrawSpriteRange: bad texturecolumn"); -#endif - column = (column_t *) ((byte *)patch + - LONG(patch->columnofs[texturecolumn])); - R_DrawMaskedColumn (column, clip); // villsa [STRIFE] clip argument - } - - colfunc = basecolfunc; -} - - - -// -// R_ProjectSprite -// Generates a vissprite for a thing -// if it might be visible. -// -void R_ProjectSprite (mobj_t* thing) -{ - fixed_t tr_x; - fixed_t tr_y; - - fixed_t gxt; - fixed_t gyt; - - fixed_t tx; - fixed_t tz; - - fixed_t xscale; - - int x1; - int x2; - - spritedef_t* sprdef; - spriteframe_t* sprframe; - int lump; - - unsigned rot; - boolean flip; - - int index; - - vissprite_t* vis; - - angle_t ang; - fixed_t iscale; - - // transform the origin point - tr_x = thing->x - viewx; - tr_y = thing->y - viewy; - - gxt = FixedMul(tr_x,viewcos); - gyt = -FixedMul(tr_y,viewsin); - - tz = gxt-gyt; - - // thing is behind view plane? - if (tz < MINZ) - return; - - xscale = FixedDiv(projection, tz); - - gxt = -FixedMul(tr_x,viewsin); - gyt = FixedMul(tr_y,viewcos); - tx = -(gyt+gxt); - - // too far off the side? - if (abs(tx)>(tz<<2)) - return; - - // decide which patch to use for sprite relative to player -#ifdef RANGECHECK - if ((unsigned int) thing->sprite >= (unsigned int) numsprites) - I_Error ("R_ProjectSprite: invalid sprite number %i ", - thing->sprite); -#endif - sprdef = &sprites[thing->sprite]; -#ifdef RANGECHECK - if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) - I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", - thing->sprite, thing->frame); -#endif - sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; - - if (sprframe->rotate) - { - // choose a different rotation based on player view - ang = R_PointToAngle (thing->x, thing->y); - rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; - lump = sprframe->lump[rot]; - flip = (boolean)sprframe->flip[rot]; - } - else - { - // use single rotation for all views - lump = sprframe->lump[0]; - flip = (boolean)sprframe->flip[0]; - } - - // calculate edges of the shape - tx -= spriteoffset[lump]; - x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; - - // off the right side? - if (x1 > viewwidth) - return; - - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; - - // off the left side - if (x2 < 0) - return; - - // store information in a vissprite - vis = R_NewVisSprite (); - vis->mobjflags = thing->flags; - vis->scale = xscale<gx = thing->x; - vis->gy = thing->y; - vis->gz = thing->z; - - // villsa [STRIFE] - if(thing->flags & MF_FEETCLIPPED) - vis->gz -= (10*FRACUNIT); - - // villsa [STRIFE] - vis->gzt = vis->gz + spritetopoffset[lump]; - - vis->texturemid = vis->gzt - viewz; - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - iscale = FixedDiv (FRACUNIT, xscale); - - if (flip) - { - vis->startfrac = spritewidth[lump]-1; - vis->xiscale = -iscale; - } - else - { - vis->startfrac = 0; - vis->xiscale = iscale; - } - - if (vis->x1 > x1) - vis->startfrac += vis->xiscale*(vis->x1-x1); - vis->patch = lump; - - // get light level - // villsa [STRIFE] unused - /*if (thing->flags & MF_SHADOW) - { - // shadow draw - vis->colormap = NULL; - } - else */if (fixedcolormap) - { - // fixed map - vis->colormap = fixedcolormap; - } - else if (thing->frame & FF_FULLBRIGHT) - { - // full bright - vis->colormap = colormaps; - } - - else - { - // diminished light - index = xscale>>(LIGHTSCALESHIFT-detailshift); - - if (index >= MAXLIGHTSCALE) - index = MAXLIGHTSCALE-1; - - vis->colormap = spritelights[index]; - } -} - - - - -// -// R_AddSprites -// During BSP traversal, this adds sprites by sector. -// -void R_AddSprites (sector_t* sec) -{ - mobj_t* thing; - int lightnum; - - // BSP is traversed by subsector. - // A sector might have been split into several - // subsectors during BSP building. - // Thus we check whether its already added. - if (sec->validcount == validcount) - return; - - // Well, now it will be done. - sec->validcount = validcount; - - lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; - - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; - else - spritelights = scalelight[lightnum]; - - // Handle all things in sector. - for (thing = sec->thinglist ; thing ; thing = thing->snext) - R_ProjectSprite (thing); -} - - -// -// R_DrawPSprite -// -void R_DrawPSprite (pspdef_t* psp) -{ - fixed_t tx; - int x1; - int x2; - spritedef_t* sprdef; - spriteframe_t* sprframe; - int lump; - boolean flip; - vissprite_t* vis; - vissprite_t avis; - - // decide which patch to use -#ifdef RANGECHECK - if ( (unsigned)psp->state->sprite >= (unsigned int) numsprites) - I_Error ("R_ProjectSprite: invalid sprite number %i ", - psp->state->sprite); -#endif - sprdef = &sprites[psp->state->sprite]; -#ifdef RANGECHECK - if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) - I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", - psp->state->sprite, psp->state->frame); -#endif - sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; - - lump = sprframe->lump[0]; - // [STRIFE] haleyjd 20110629: -flip replaces this. - //flip = (boolean)sprframe->flip[0]; - flip = flipparm; - - // calculate edges of the shape - tx = psp->sx-160*FRACUNIT; - - tx -= spriteoffset[lump]; - x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; - - // off the right side - if (x1 > viewwidth) - return; - - tx += spritewidth[lump]; - x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; - - // off the left side - if (x2 < 0) - return; - - // store information in a vissprite - vis = &avis; - vis->mobjflags = 0; - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - vis->scale = pspritescale<xiscale = -pspriteiscale; - vis->startfrac = spritewidth[lump]-1; - } - else - { - vis->xiscale = pspriteiscale; - vis->startfrac = 0; - } - - // villsa [STRIFE] calculate y offset with view pitch - vis->texturemid = ((BASEYCENTER<sy-spritetopoffset[lump]) - + FixedMul(vis->xiscale, (centery-viewheight/2)<x1 > x1) - vis->startfrac += vis->xiscale*(vis->x1-x1); - - vis->patch = lump; - - if (viewplayer->powers[pw_invisibility] > 4*32 - || (viewplayer->powers[pw_invisibility] & 8)) - { - // shadow draw - vis->colormap = spritelights[MAXLIGHTSCALE-1]; - vis->mobjflags |= MF_SHADOW; - } - else if(viewplayer->powers[pw_invisibility] & 4) - { - vis->mobjflags |= (MF_SHADOW|MF_MVIS); - } - - // When not MVIS, or if SHADOW, behave normally: - if(!(viewplayer->mo->flags & MF_MVIS) || (viewplayer->mo->flags & MF_SHADOW)) - { - if (fixedcolormap) - { - // fixed color - vis->colormap = fixedcolormap; - } - else if (psp->state->frame & FF_FULLBRIGHT) - { - // full bright - vis->colormap = colormaps; - } - else - { - // local light - vis->colormap = spritelights[MAXLIGHTSCALE-1]; - } - } - else - { - // When MVIS, use invulnerability colormap - vis->colormap = colormaps + INVERSECOLORMAP * 256 * sizeof(lighttable_t); - } - - R_DrawVisSprite (vis, vis->x1, vis->x2); -} - - - -// -// R_DrawPlayerSprites -// -void R_DrawPlayerSprites (void) -{ - int i; - int lightnum; - pspdef_t* psp; - - // get light level - lightnum = - (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) - +extralight; - - if (lightnum < 0) - spritelights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - spritelights = scalelight[LIGHTLEVELS-1]; - else - spritelights = scalelight[lightnum]; - - // clip to screen bounds - mfloorclip = screenheightarray; - mceilingclip = negonearray; - - // add all active psprites - for (i=0, psp=viewplayer->psprites; - istate) - R_DrawPSprite (psp); - } -} - - - - -// -// R_SortVisSprites -// -vissprite_t vsprsortedhead; - - -void R_SortVisSprites (void) -{ - int i; - int count; - vissprite_t* ds; - vissprite_t* best; - static vissprite_t unsorted; - fixed_t bestscale; - - count = vissprite_p - vissprites; - - unsorted.next = unsorted.prev = &unsorted; - - if (!count) - return; - - for (ds=vissprites ; dsnext = ds+1; - ds->prev = ds-1; - } - - vissprites[0].prev = &unsorted; - unsorted.next = &vissprites[0]; - (vissprite_p-1)->next = &unsorted; - unsorted.prev = vissprite_p-1; - - // pull the vissprites out by scale - - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i=0 ; inext) - { - if (ds->scale < bestscale) - { - bestscale = ds->scale; - best = ds; - } - } - best->next->prev = best->prev; - best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; - } -} - - - -// -// R_DrawSprite -// -void R_DrawSprite (vissprite_t* spr) -{ - drawseg_t* ds; - short clipbot[SCREENWIDTH]; - short cliptop[SCREENWIDTH]; - int x; - int r1; - int r2; - fixed_t scale; - fixed_t lowscale; - int silhouette; - - for (x = spr->x1 ; x<=spr->x2 ; x++) - clipbot[x] = cliptop[x] = -2; - - // Scan drawsegs from end to start for obscuring segs. - // The first drawseg that has a greater scale - // is the clip seg. - for (ds=ds_p-1 ; ds >= drawsegs ; ds--) - { - // determine if the drawseg obscures the sprite - if (ds->x1 > spr->x2 - || ds->x2 < spr->x1 - || (!ds->silhouette - && !ds->maskedtexturecol) ) - { - // does not cover sprite - continue; - } - - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->scale - || ( lowscale < spr->scale - && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) - { - // masked mid texture? - if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2); - // seg is behind sprite - continue; - } - - - // clip this piece of the sprite - silhouette = ds->silhouette; - - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; - - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; - - if (silhouette == 1) - { - // bottom sil - for (x=r1 ; x<=r2 ; x++) - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == 2) - { - // top sil - for (x=r1 ; x<=r2 ; x++) - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == 3) - { - // both - for (x=r1 ; x<=r2 ; x++) - { - if (clipbot[x] == -2) - clipbot[x] = ds->sprbottomclip[x]; - if (cliptop[x] == -2) - cliptop[x] = ds->sprtopclip[x]; - } - } - - } - - // all clipping has been performed, so draw the sprite - - // check for unclipped columns - for (x = spr->x1 ; x<=spr->x2 ; x++) - { - if (clipbot[x] == -2) - clipbot[x] = viewheight; - - if (cliptop[x] == -2) - cliptop[x] = -1; - } - - mfloorclip = clipbot; - mceilingclip = cliptop; - R_DrawVisSprite (spr, spr->x1, spr->x2); -} - - - - -// -// R_DrawMasked -// -void R_DrawMasked (void) -{ - vissprite_t* spr; - drawseg_t* ds; - - R_SortVisSprites (); - - if (vissprite_p > vissprites) - { - // draw all vissprites back to front - for (spr = vsprsortedhead.next ; - spr != &vsprsortedhead ; - spr=spr->next) - { - - R_DrawSprite (spr); - } - } - - // render any remaining masked mid textures - for (ds=ds_p-1 ; ds >= drawsegs ; ds--) - if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, ds->x1, ds->x2); - - // draw the psprites on top of everything - // but does not draw on side views - if (!viewangleoffset) - R_DrawPlayerSprites (); -} - - - diff --git a/games/NXDoom/src/strife/r_things.h b/games/NXDoom/src/strife/r_things.h deleted file mode 100644 index edb14a54d39..00000000000 --- a/games/NXDoom/src/strife/r_things.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Rendering of moving objects, sprites. -// - - -#ifndef __R_THINGS__ -#define __R_THINGS__ - - - -#define MAXVISSPRITES 128 - -extern vissprite_t vissprites[MAXVISSPRITES]; -extern vissprite_t* vissprite_p; -extern vissprite_t vsprsortedhead; - -// Constant arrays used for psprite clipping -// and initializing clipping. -extern short negonearray[SCREENWIDTH]; -extern short screenheightarray[SCREENWIDTH]; - -// vars for R_DrawMaskedColumn -extern short* mfloorclip; -extern short* mceilingclip; -extern fixed_t spryscale; -extern fixed_t sprtopscreen; - -extern fixed_t pspritescale; -extern fixed_t pspriteiscale; - - -// villsa [STIFE] new argument -void R_DrawMaskedColumn (column_t *column, int baseclip); - - -void R_SortVisSprites (void); - -void R_AddSprites (sector_t* sec); -void R_AddPSprites (void); -void R_DrawSprites (void); -void R_InitSprites (const char** namelist); -void R_ClearSprites (void); -void R_DrawMasked (void); - -void -R_ClipVisSprite -( vissprite_t* vis, - int xl, - int xh ); - - -#endif diff --git a/games/NXDoom/src/strife/s_sound.c b/games/NXDoom/src/strife/s_sound.c deleted file mode 100644 index 1de853fc079..00000000000 --- a/games/NXDoom/src/strife/s_sound.c +++ /dev/null @@ -1,825 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: none -// - -#include -#include -#include - -#include "i_sound.h" -#include "i_system.h" - -#include "deh_str.h" - -#include "doomstat.h" -#include "doomtype.h" - -#include "sounds.h" -#include "s_sound.h" - -#include "m_misc.h" -#include "m_random.h" -#include "m_argv.h" - -#include "p_local.h" -#include "w_wad.h" -#include "z_zone.h" - -// when to clip out sounds -// Does not fit the large outdoor areas. - -#define S_CLIPPING_DIST (1200 * FRACUNIT) - -// Distance tp origin when sounds should be maxed out. -// This should relate to movement clipping resolution -// (see BLOCKMAP handling). -// In the source code release: (160*FRACUNIT). Changed back to the -// Vanilla value of 200 (why was this changed?) - -#define S_CLOSE_DIST (200 * FRACUNIT) - -// The range over which sound attenuates - -#define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS) - -// Stereo separation - -#define S_STEREO_SWING (96 * FRACUNIT) - -#define NORM_PRIORITY 64 -#define NORM_SEP 128 - -typedef struct -{ - // sound information (if null, channel avail.) - sfxinfo_t *sfxinfo; - - // origin of sound - mobj_t *origin; - - // handle of the sound being played - int handle; - - int pitch; - -} channel_t; - -// The set of channels available - -static channel_t *channels; - -// Maximum volume of a sound effect. -// Internal default is max out of 0-15. - -int sfxVolume = 8; - -// Maximum volume of music. - -int musicVolume = 13; - -// haleyjd 08/29/10: [STRIFE] New global variable -// Volume of voice channel. - -int voiceVolume = 15; - -// Internal volume level, ranging from 0-127 - -static int snd_SfxVolume; - -// haleyjd 09/11/10: [STRIFE] Internal voice volume level - -static int snd_VoiceVolume; - -// Whether songs are mus_paused - -static boolean mus_paused; - -// Music currently being played - -static musicinfo_t *mus_playing = NULL; - -// Number of channels to use - -int snd_channels = 8; - -// haleyjd 09/11/10: [STRIFE] Handle of current voice channel. -// This has been implemented at a higher level than it was implemented -// in strife1.exe, as there it relied on a priority system which was -// implicit in the SFX_PlayPatch API of DMX. Here we'll just ignore -// the current voice channel when doing normal sound playing. - -static int i_voicehandle = -1; - -// haleyjd 09/11/10: [STRIFE] whether to play voices or not -int disable_voices = 0; - -// -// Initializes sound stuff, including volume -// Sets channels, SFX and music volume, -// allocates channel buffer, sets S_sfx lookup. -// -// haleyjd 09/11/10: [STRIFE] Added voice volume -// -void S_Init(int sfxVolume, int musicVolume, int voiceVolume) -{ - int i; - - I_SetOPLDriverVer(opl_doom_1_9); - I_PrecacheSounds(S_sfx, NUMSFX); - - S_SetSfxVolume(sfxVolume); - S_SetMusicVolume(musicVolume); - S_SetVoiceVolume(voiceVolume); - - // Allocating the internal channels for mixing - // (the maximum numer of sounds rendered - // simultaneously) within zone memory. - channels = Z_Malloc(snd_channels*sizeof(channel_t), PU_STATIC, 0); - - // Free all channels for use - for (i=0 ; isfxinfo) - { - // stop the sound playing - - if (I_SoundIsPlaying(c->handle)) - { - I_StopSound(c->handle); - } - - // check to see if other channels are playing the sound - - for (i=0; isfxinfo == channels[i].sfxinfo) - { - break; - } - } - - // degrade usefulness of sound data - - c->sfxinfo->usefulness--; - c->sfxinfo = NULL; - } -} - -// -// Per level startup code. -// Kills playing sounds at start of level, -// determines music if any, changes music. -// -// haleyjd 08/31/10: [STRIFE] -// * Removed DOOM music handling and replaced with Strife code. -// -void S_Start(void) -{ - int cnum; - int mnum; - - // kill all playing sounds at start of level - // (trust me - a good idea) - for (cnum=0 ; cnumpriority > channels[cnum].sfxinfo->priority) - return -1; - - S_StopChannel(cnum); - break; - } - } - - // None available - if (cnum == snd_channels) - { - // Look for lower priority - for (cnum=0 ; cnumpriority >= sfxinfo->priority) - { - // haleyjd 09/11/10: [STRIFE] voice has absolute priority - if (isvoice || cnum != i_voicehandle) - break; - } - } - - if (cnum == snd_channels) - { - // FUCK! No lower priority. Sorry, Charlie. - return -1; - } - else - { - // Otherwise, kick out lower priority. - S_StopChannel(cnum); - } - } - - c = &channels[cnum]; - - // channel is decided to be cnum. - c->sfxinfo = sfxinfo; - c->origin = origin; - - return cnum; -} - -// -// Changes volume and stereo-separation variables -// from the norm of a sound effect to be played. -// If the sound is not audible, returns a 0. -// Otherwise, modifies parameters and returns 1. -// -// [STRIFE] -// haleyjd 20110220: changed to eliminate the gamemap == 8 hack that was -// left over from Doom 1's original boss levels. Kind of amazing that Rogue -// was able to catch the smallest things like that. -// -static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, - int *vol, int *sep) -{ - fixed_t approx_dist; - fixed_t adx; - fixed_t ady; - angle_t angle; - - // calculate the distance to sound origin - // and clip it if necessary - adx = abs(listener->x - source->x); - ady = abs(listener->y - source->y); - - // From _GG1_ p.428. Appox. eucledian distance fast. - approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1); - - // [STRIFE] removed gamemap == 8 hack - if (approx_dist > S_CLIPPING_DIST) - { - return 0; - } - - // angle of source to listener - angle = R_PointToAngle2(listener->x, - listener->y, - source->x, - source->y); - - if (angle > listener->angle) - { - angle = angle - listener->angle; - } - else - { - angle = angle + (0xffffffff - listener->angle); - } - - angle >>= ANGLETOFINESHIFT; - - // stereo separation - *sep = 128 - (FixedMul(S_STEREO_SWING, finesine[angle]) >> FRACBITS); - - // volume calculation - // [STRIFE] Removed gamemap == 8 hack - if (approx_dist < S_CLOSE_DIST) - { - *vol = snd_SfxVolume; - } - else - { - // distance effect - *vol = (snd_SfxVolume - * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) - / S_ATTENUATOR; - } - - return (*vol > 0); -} - -void S_StartSound(void *origin_p, int sfx_id) -{ - sfxinfo_t *sfx; - mobj_t *origin; - int rc; - int sep; - int pitch; - int cnum; - int volume; - - origin = (mobj_t *) origin_p; - volume = snd_SfxVolume; - - // check for bogus sound # - if (sfx_id < 1 || sfx_id > NUMSFX) - { - // [STRIFE]: BUG - Note: vanilla had some extremely buggy and dangerous - // code here that tried to print the sprite name of the object playing - // the bad sound. Because it invokes multiple undefined behaviors and - // is of basically no consequence, it has deliberately not been ported. - I_Error("Bad sfx #: %d", sfx_id); - } - - sfx = &S_sfx[sfx_id]; - - // Initialize sound parameters - if (sfx->link) - { - volume += sfx->volume; - - if (volume < 1) - { - return; - } - - if (volume > snd_SfxVolume) - { - volume = snd_SfxVolume; - } - } - - - // Check to see if it is audible, - // and if not, modify the params - if (origin && origin != players[consoleplayer].mo) - { - rc = S_AdjustSoundParams(players[consoleplayer].mo, - origin, - &volume, - &sep); - - if (origin->x == players[consoleplayer].mo->x - && origin->y == players[consoleplayer].mo->y) - { - sep = NORM_SEP; - } - - if (!rc) - { - return; - } - } - else - { - sep = NORM_SEP; - } - pitch = NORM_PITCH; - - // kill old sound [STRIFE] - nope! - //S_StopSound(origin); - - // try to find a channel - cnum = S_GetChannel(origin, sfx, false); // haleyjd: not a voice. - - if (cnum < 0) - { - return; - } - - // increase the usefulness - if (sfx->usefulness++ < 0) - { - sfx->usefulness = 1; - } - - if (sfx->lumpnum < 0) - { - sfx->lumpnum = I_GetSfxLumpNum(sfx); - } - - channels[cnum].handle = I_StartSound(sfx, cnum, volume, sep, pitch); -} - - -// haleyjd 09/11/10: [STRIFE] -// None of this was necessary in the vanilla EXE but Choco's low-level code -// won't play nice with a temporary sfxinfo because it insists that the -// "driver_data" member remain valid from the last time the sound was used, -// even if it has already stopped playing. Thanks to this cuteness I get -// to maintain a dynamic cache of sfxinfo objects! - -typedef struct voiceinfo_s -{ - sfxinfo_t sfx; - struct voiceinfo_s *next; // next on hash chain -} voiceinfo_t; - -#define NUMVOICECHAINS 257 - -// -// Ripped from Eternity. -// -static unsigned int S_voiceHash(const char *str) -{ - const char *c = str; - unsigned int h = 0; - - if(!str) - I_Error("S_voiceHash: cannot hash NULL string!\n"); - - // note: this needs to be case insensitive for lump names - while(*c) - { - h = 5 * h + toupper(*c); - ++c; - } - - return h; -} - -static voiceinfo_t *voices[NUMVOICECHAINS]; - -// -// S_getVoice -// -// Gets an entry from the voice table, if it exists. If it does not, one will be -// created. -// -static voiceinfo_t *S_getVoice(const char *name, int lumpnum) -{ - voiceinfo_t *voice; - unsigned int hashkey = S_voiceHash(name) % NUMVOICECHAINS; - - voice = voices[hashkey]; - - while(voice && strcasecmp(voice->sfx.name, name)) - voice = voice->next; - - if(!voice) - { - voice = calloc(1, sizeof(voiceinfo_t)); - - M_StringCopy(voice->sfx.name, name, sizeof(voice->sfx.name)); - voice->sfx.priority = INT_MIN; // make highest possible priority - voice->sfx.pitch = -1; - voice->sfx.volume = -1; - voice->sfx.numchannels = -1; - voice->sfx.usefulness = -1; - voice->sfx.lumpnum = lumpnum; - - // throw it onto the table. - voice->next = voices[hashkey]; - voices[hashkey] = voice; - } - - return voice; -} - -// -// I_StartVoice -// -// haleyjd 09/11/10: [STRIFE] New function -// Note this was in i_sound.c in Strife itself, but relied on DMX-specific -// features to ensure voice channels had absolute priority. Here we must -// populate a fake sfxinfo_t and send the sound through some of the normal -// routines. But in the end, it still works the same. -// -void I_StartVoice(const char *lumpname) -{ - int lumpnum; - voiceinfo_t *voice; // choco-specific - char lumpnamedup[9]; - - // no voices in deathmatch mode. - if(netgame) - return; - - // STRIFE-TODO: checks if snd_SfxDevice == 83 - // This is probably turning off voice if using PC speaker... - - // user has disabled voices? - if(disable_voices) - return; - - // have a voice playing already? stop it. - if(i_voicehandle >= 0) - S_StopChannel(i_voicehandle); - - // Vanilla STRIFE appears to have stopped any current voice without - // starting a new one if NULL was passed in here, though I cannot - // find an explicit check for NULL in the assembly. Either way, it - // didn't crash, so do a check now: - if(lumpname == NULL) - return; - - // Because of constness problems... - M_StringCopy(lumpnamedup, lumpname, sizeof(lumpnamedup)); - - if((lumpnum = W_CheckNumForName(lumpnamedup)) != -1) - { - // haleyjd: Choco-specific: get a voice structure - voice = S_getVoice(lumpnamedup, lumpnum); - - // get a channel for the voice - i_voicehandle = S_GetChannel(NULL, &voice->sfx, true); - - channels[i_voicehandle].handle - = I_StartSound(&voice->sfx, i_voicehandle, snd_VoiceVolume, NORM_SEP, NORM_PITCH); - } -} - -// -// Stop and resume music, during game PAUSE. -// - -void S_PauseSound(void) -{ - if (mus_playing && !mus_paused) - { - I_PauseSong(); - mus_paused = true; - } -} - -void S_ResumeSound(void) -{ - if (mus_playing && mus_paused) - { - I_ResumeSong(); - mus_paused = false; - } -} - -// -// Updates music & sounds -// - -void S_UpdateSounds(mobj_t *listener) -{ - int audible; - int cnum; - int volume; - int sep; - sfxinfo_t* sfx; - channel_t* c; - - I_UpdateSound(); - - for (cnum=0; cnumsfxinfo; - - if (c->sfxinfo) - { - if (I_SoundIsPlaying(c->handle)) - { - // initialize parameters - volume = snd_SfxVolume; - sep = NORM_SEP; - - if (sfx->link) - { - volume += sfx->volume; - if (volume < 1) - { - S_StopChannel(cnum); - continue; - } - else if (volume > snd_SfxVolume) - { - volume = snd_SfxVolume; - } - } - - // check non-local sounds for distance clipping - // or modify their params - if (c->origin && listener != c->origin) - { - audible = S_AdjustSoundParams(listener, - c->origin, - &volume, - &sep); - - if (!audible) - { - S_StopChannel(cnum); - } - else - { - I_UpdateSoundParams(c->handle, volume, sep); - } - } - } - else - { - // if channel is allocated but sound has stopped, - // free it - S_StopChannel(cnum); - } - } - } -} - -void S_SetMusicVolume(int volume) -{ - if (volume < 0 || volume > 127) - { - I_Error("Attempt to set music volume at %d", - volume); - } - - I_SetMusicVolume(volume); -} - -void S_SetSfxVolume(int volume) -{ - if (volume < 0 || volume > 127) - { - I_Error("Attempt to set sfx volume at %d", volume); - } - - snd_SfxVolume = volume; -} - -// -// S_SetVoiceVolume -// -// haleyjd 09/11/10: [STRIFE] -// Set the internal voice volume level. -// -void S_SetVoiceVolume(int volume) -{ - if (volume < 0 || volume > 127) - { - I_Error("Attempt to set voice volume at %d", volume); - } - - snd_VoiceVolume = volume; -} - -// -// Starts some music with the music id found in sounds.h. -// - -void S_StartMusic(int m_id) -{ - S_ChangeMusic(m_id, false); -} - -void S_ChangeMusic(int musicnum, int looping) -{ - musicinfo_t *music = NULL; - char namebuf[9]; - void *handle; - - if (musicnum <= mus_None || musicnum >= NUMMUSIC) - { - I_Error("Bad music number %d", musicnum); - } - else - { - music = &S_music[musicnum]; - } - - if (mus_playing == music) - { - return; - } - - // shutdown old music - S_StopMusic(); - - // get lumpnum if neccessary - if (!music->lumpnum) - { - M_snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name)); - music->lumpnum = W_GetNumForName(namebuf); - } - - music->data = W_CacheLumpNum(music->lumpnum, PU_STATIC); - - handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum)); - music->handle = handle; - I_PlaySong(handle, looping); - - mus_playing = music; -} - -boolean S_MusicPlaying(void) -{ - return I_MusicIsPlaying(); -} - -void S_StopMusic(void) -{ - if (mus_playing) - { - if (mus_paused) - { - I_ResumeSong(); - } - - I_StopSong(); - I_UnRegisterSong(mus_playing->handle); - W_ReleaseLumpNum(mus_playing->lumpnum); - mus_playing->data = NULL; - mus_playing = NULL; - } -} - diff --git a/games/NXDoom/src/strife/s_sound.h b/games/NXDoom/src/strife/s_sound.h deleted file mode 100644 index 0521a94e1ce..00000000000 --- a/games/NXDoom/src/strife/s_sound.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The not so system specific sound interface. -// - - -#ifndef __S_SOUND__ -#define __S_SOUND__ - -#include "p_mobj.h" -#include "sounds.h" - -// -// Initializes sound stuff, including volume -// Sets channels, SFX and music volume, -// allocates channel buffer, sets S_sfx lookup. -// - -void S_Init(int sfxVolume, int musicVolume, int voiceVolume); - - -// Shut down sound - -void S_Shutdown(void); - - - -// -// Per level startup code. -// Kills playing sounds at start of level, -// determines music if any, changes music. -// - -void S_Start(void); - -// -// Start sound for thing at -// using from sounds.h -// - -void S_StartSound(void *origin, int sound_id); - -// haleyjd 09/11/10: [STRIFE] Start a voice. -void I_StartVoice(const char *lumpname); - -// Stop sound for thing at -void S_StopSound(mobj_t *origin); - - -// Start music using from sounds.h -void S_StartMusic(int music_id); - -// Start music using from sounds.h, -// and set whether looping -void S_ChangeMusic(int music_id, int looping); - -// query if music is playing -boolean S_MusicPlaying(void); - -// Stops the music fer sure. -void S_StopMusic(void); - -// Stop and resume music, during game PAUSE. -void S_PauseSound(void); -void S_ResumeSound(void); - - -// -// Updates music & sounds -// -void S_UpdateSounds(mobj_t *listener); - -void S_SetMusicVolume(int volume); -void S_SetSfxVolume(int volume); -void S_SetVoiceVolume(int volume); // haleyjd 09/11/10: [STRIFE] - -extern int snd_channels; - -extern int disable_voices; - -#endif - diff --git a/games/NXDoom/src/strife/sounds.c b/games/NXDoom/src/strife/sounds.c deleted file mode 100644 index 27a4948f291..00000000000 --- a/games/NXDoom/src/strife/sounds.c +++ /dev/null @@ -1,227 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Created by a sound utility. -// Kept as a sample, DOOM2 sounds. -// - - -#include - - -#include "doomtype.h" -#include "sounds.h" - -// -// Information about all the music -// - -#define MUSIC(name) \ - { name, 0, NULL, NULL } - -// villsa [STRIFE] -musicinfo_t S_music[] = -{ - MUSIC(NULL), - MUSIC("logo"), - MUSIC("action"), - MUSIC("tavern"), - MUSIC("danger"), - MUSIC("fast"), - MUSIC("intro"), - MUSIC("darker"), - MUSIC("strike"), - MUSIC("slide"), - MUSIC("tribal"), - MUSIC("march"), - MUSIC("danger"), - MUSIC("mood"), - MUSIC("castle"), - MUSIC("darker"), - MUSIC("action"), - MUSIC("fight"), - MUSIC("spense"), - MUSIC("slide"), - MUSIC("strike"), - MUSIC("dark"), - MUSIC("tech"), - MUSIC("slide"), - MUSIC("drone"), - MUSIC("panthr"), - MUSIC("sad"), - MUSIC("instry"), - MUSIC("tech"), - MUSIC("action"), - MUSIC("instry"), - MUSIC("drone"), - MUSIC("fight"), - MUSIC("happy"), - MUSIC("end") - - -}; - - -// -// Information about all the sfx -// - -#define SOUND(name, priority) \ - { NULL, name, priority, NULL, -1, -1, 0, 0, -1, NULL } -#define SOUND_LINK(name, priority, link_id, pitch, volume) \ - { NULL, name, priority, &S_sfx[link_id], pitch, volume, 0, 0, -1, NULL } - -// villsa [STRIFE] -sfxinfo_t S_sfx[] = -{ - // S_sfx[0] needs to be a dummy for odd reasons. - SOUND("none", 0), - SOUND("swish", 64), - SOUND("meatht", 64), - SOUND("mtalht", 64), - SOUND("wpnup", 78), - SOUND("rifle", 64), - SOUND("mislht", 64), - SOUND("barexp", 32), - SOUND("flburn", 64), - SOUND("flidl", 118), - SOUND("agrsee", 98), - SOUND("plpain", 96), - SOUND("pcrush", 96), - SOUND("pespna", 98), - SOUND("pespnb", 98), - SOUND("pespnc", 98), - SOUND("pespnd", 98), - SOUND("agrdpn", 98), - SOUND("pldeth", 32), - SOUND("plxdth", 32), - SOUND("slop", 78), - SOUND("rebdth", 98), - SOUND("agrdth", 98), - SOUND("lgfire", 211), - SOUND("smfire", 211), - SOUND("alarm", 210), - SOUND("drlmto", 98), - SOUND("drlmtc", 98), - SOUND("drsmto", 98), - SOUND("drsmtc", 98), - SOUND("drlwud", 98), - SOUND("drswud", 98), - SOUND("drston", 98), - SOUND("bdopn", 98), - SOUND("bdcls", 98), - SOUND("swtchn", 78), - SOUND("swbolt", 98), - SOUND("swscan", 98), - SOUND("yeah", 10), - SOUND("mask", 210), - SOUND("pstart", 100), - SOUND("pstop", 100), - SOUND("itemup", 78), - SOUND("bglass", 200), - SOUND("wriver", 201), - SOUND("wfall", 201), - SOUND("wdrip", 201), - SOUND("wsplsh", 95), - SOUND("rebact", 200), - SOUND("agrac1", 98), - SOUND("agrac2", 98), - SOUND("agrac3", 98), - SOUND("agrac4", 98), - SOUND("ambppl", 218), - SOUND("ambbar", 218), - SOUND("telept", 32), - SOUND("ratact", 99), - SOUND("itmbk", 100), - SOUND("xbow", 99), - SOUND("burnme", 95), - SOUND("oof", 96), - SOUND("wbrldt", 98), - SOUND("psdtha", 109), - SOUND("psdthb", 109), - SOUND("psdthc", 109), - SOUND("rb2pn", 96), - SOUND("rb2dth", 32), - SOUND("rb2see", 98), - SOUND("rb2act", 98), - SOUND("firxpl", 70), - SOUND("stnmov", 100), - SOUND("noway", 78), - SOUND("rlaunc", 64), - SOUND("rflite", 65), - SOUND("radio", 60), - SOUND("pulchn", 98), - SOUND("swknob", 98), - SOUND("keycrd", 98), - SOUND("swston", 98), - SOUND("sntsee", 98), - SOUND("sntdth", 98), - SOUND("sntact", 98), - SOUND("pgrdat", 64), - SOUND("pgrsee", 90), - SOUND("pgrdpn", 96), - SOUND("pgrdth", 32), - SOUND("pgract", 120), - SOUND("proton", 64), - SOUND("protfl", 64), - SOUND("plasma", 64), - SOUND("dsrptr", 30), - SOUND("reavat", 64), - SOUND("revbld", 64), - SOUND("revsee", 90), - SOUND("reavpn", 96), - SOUND("revdth", 32), - SOUND("revact", 120), - SOUND("spisit", 90), - SOUND("spdwlk", 65), - SOUND("spidth", 32), - SOUND("spdatk", 32), - SOUND("chant", 218), - SOUND("static", 32), - SOUND("chain", 70), - SOUND("tend", 100), - SOUND("phoot", 32), - SOUND("explod", 32), - SOUND("sigil", 32), - SOUND("sglhit", 32), - SOUND("siglup", 32), - SOUND("prgpn", 96), - SOUND("progac", 120), - SOUND("lorpn", 96), - SOUND("lorsee", 90), - SOUND("difool", 32), - SOUND("inqdth", 32), - SOUND("inqact", 98), - SOUND("inqsee", 90), - SOUND("inqjmp", 65), - SOUND("amaln1", 99), - SOUND("amaln2", 99), - SOUND("amaln3", 99), - SOUND("amaln4", 99), - SOUND("amaln5", 99), - SOUND("amaln6", 99), - SOUND("mnalse", 64), - SOUND("alnsee", 64), - SOUND("alnpn", 96), - SOUND("alnact", 120), - SOUND("alndth", 32), - SOUND("mnaldt", 32), - SOUND("reactr", 31), - SOUND("airlck", 98), - SOUND("drchno", 98), - SOUND("drchnc", 98), - SOUND("valve", 98) -}; - diff --git a/games/NXDoom/src/strife/sounds.h b/games/NXDoom/src/strife/sounds.h deleted file mode 100644 index 38ed0bfcf8a..00000000000 --- a/games/NXDoom/src/strife/sounds.h +++ /dev/null @@ -1,222 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Created by the sound utility written by Dave Taylor. -// Kept as a sample, DOOM2 sounds. Frozen. -// - -#ifndef __SOUNDS__ -#define __SOUNDS__ - -#include "i_sound.h" - -// the complete set of sound effects -extern sfxinfo_t S_sfx[]; - -// the complete set of music -extern musicinfo_t S_music[]; - -// -// Identifiers for all music in game. -// - -// villsa [STRIFE] -typedef enum -{ - mus_None, - mus_logo, - mus_action, - mus_tavern, - mus_danger, - mus_fast, - mus_intro, - mus_darker, - mus_strike, - mus_slide, - mus_tribal, - mus_march, - mus_danger2, - mus_mood, - mus_castle, - mus_darker2, - mus_action2, - mus_fight, - mus_spense, - mus_slide2, - mus_strike2, - mus_dark, - mus_tech, - mus_slide3, - mus_drone, - mus_panthr, - mus_sad, - mus_instry, - mus_tech2, - mus_action3, - mus_instry2, - mus_drone2, - mus_fight2, - mus_happy, - mus_end, - NUMMUSIC -} musicenum_t; - - -// -// Identifiers for all sfx in game. -// - -typedef enum -{ - sfx_None, - sfx_swish, - sfx_meatht, - sfx_mtalht, - sfx_wpnup, - sfx_rifle, - sfx_mislht, - sfx_barexp, - sfx_flburn, - sfx_flidl, - sfx_agrsee, - sfx_plpain, - sfx_pcrush, - sfx_pespna, - sfx_pespnb, - sfx_pespnc, - sfx_pespnd, - sfx_agrdpn, - sfx_pldeth, - sfx_plxdth, - sfx_slop, - sfx_rebdth, - sfx_agrdth, - sfx_lgfire, - sfx_smfire, - sfx_alarm, - sfx_drlmto, - sfx_drlmtc, - sfx_drsmto, - sfx_drsmtc, - sfx_drlwud, - sfx_drswud, - sfx_drston, - sfx_bdopn, - sfx_bdcls, - sfx_swtchn, - sfx_swbolt, - sfx_swscan, - sfx_yeah, - sfx_mask, - sfx_pstart, - sfx_pstop, - sfx_itemup, - sfx_bglass, - sfx_wriver, - sfx_wfall, - sfx_wdrip, - sfx_wsplsh, - sfx_rebact, - sfx_agrac1, - sfx_agrac2, - sfx_agrac3, - sfx_agrac4, - sfx_ambppl, - sfx_ambbar, - sfx_telept, - sfx_ratact, - sfx_itmbk, - sfx_xbow, - sfx_burnme, - sfx_oof, - sfx_wbrldt, - sfx_psdtha, - sfx_psdthb, - sfx_psdthc, - sfx_rb2pn, - sfx_rb2dth, - sfx_rb2see, - sfx_rb2act, - sfx_firxpl, - sfx_stnmov, - sfx_noway, - sfx_rlaunc, - sfx_rflite, - sfx_radio, - sfx_pulchn, - sfx_swknob, - sfx_keycrd, - sfx_swston, - sfx_sntsee, - sfx_sntdth, - sfx_sntact, - sfx_pgrdat, - sfx_pgrsee, - sfx_pgrdpn, - sfx_pgrdth, - sfx_pgract, - sfx_proton, - sfx_protfl, - sfx_plasma, - sfx_dsrptr, - sfx_reavat, - sfx_revbld, - sfx_revsee, - sfx_reavpn, - sfx_revdth, - sfx_revact, - sfx_spisit, - sfx_spdwlk, - sfx_spidth, - sfx_spdatk, - sfx_chant, - sfx_static, - sfx_chain, - sfx_tend, - sfx_phoot, - sfx_explod, - sfx_sigil, - sfx_sglhit, - sfx_siglup, - sfx_prgpn, - sfx_progac, - sfx_lorpn, - sfx_lorsee, - sfx_difool, - sfx_inqdth, - sfx_inqact, - sfx_inqsee, - sfx_inqjmp, - sfx_amaln1, - sfx_amaln2, - sfx_amaln3, - sfx_amaln4, - sfx_amaln5, - sfx_amaln6, - sfx_mnalse, - sfx_alnsee, - sfx_alnpn, - sfx_alnact, - sfx_alndth, - sfx_mnaldt, - sfx_reactr, - sfx_airlck, - sfx_drchno, - sfx_drchnc, - sfx_valve, - NUMSFX -} sfxenum_t; - -#endif diff --git a/games/NXDoom/src/strife/st_lib.c b/games/NXDoom/src/strife/st_lib.c deleted file mode 100644 index 3ade0955744..00000000000 --- a/games/NXDoom/src/strife/st_lib.c +++ /dev/null @@ -1,326 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The status bar widget code. -// - - -#include -#include - -#include "deh_main.h" -#include "doomdef.h" - -#include "z_zone.h" -#include "v_video.h" - -#include "i_swap.h" -#include "i_system.h" - -#include "w_wad.h" - -#include "st_stuff.h" -#include "st_lib.h" -#include "r_local.h" - - -// -// Hack display negative frags. -// Loads and store the stminus lump. -// -patch_t* sttminus; - -void STlib_init(void) -{ - // haleyjd 08/28/10: [STRIFE] STTMINUS -> STCFN045 - sttminus = (patch_t *) W_CacheLumpName(DEH_String("STCFN045"), PU_STATIC); -} - - -// -// STlib_initNum -// -// haleyjd 09/01/10: [STRIFE] -// * Rogue removed the "on" member of st_number_t. -void -STlib_initNum -( st_number_t* n, - int x, - int y, - patch_t** pl, - int* num, - int width ) -{ - n->x = x; - n->y = y; - n->width = width; - n->num = num; - n->p = pl; -} - - -// -// STlib_drawNum -// -// A fairly efficient way to draw a number -// based on differences from the old number. -// Note: worth the trouble? -// -// haleyjd 09/01/10: [STRIFE] -// * Rogue removed the "refresh" parameter and caching code -// -void -STlib_drawNum -( st_number_t* n) -{ - int numdigits = n->width; - int num = *n->num; - - int w = SHORT(n->p[0]->width) + 1; // [STRIFE] +1 - int x = n->x; - - int neg; - - neg = num < 0; - - if (neg) - { - if (numdigits == 2 && num < -9) - num = -9; - else if (numdigits == 3 && num < -99) - num = -99; - - num = -num; - } - - /* haleyjd 09/01/10: [STRIFE] Widget caching system removed by Rogue - // clear the area - x = n->x - numdigits*w; - - if (n->y - ST_Y < 0) - I_Error("drawNum: n->y - ST_Y < 0"); - - V_CopyRect(x, n->y - ST_Y, st_backing_screen, w*numdigits, h, x, n->y); - */ - - // if non-number, do not draw it - if (num == 1994) - return; - - x = n->x; - - // in the special case of 0, you draw 0 - if (!num) - V_DrawPatch(x - w, n->y, n->p[ 0 ]); - - // draw the new number - while (num && numdigits--) - { - x -= w; - V_DrawPatch(x, n->y, n->p[ num % 10 ]); - num /= 10; - } - - // draw a minus sign if necessary - if (neg) - V_DrawPatch(x - 8, n->y, sttminus); -} - - -// -// STlib_drawNumPositive -// -// haleyjd 09/01/10: [STRIFE] New function. -// * Mostly the same as STlib_drawNum, except doesn't draw negatives. -// -void -STlib_drawNumPositive -( st_number_t* n) -{ - int numdigits = n->width; - int num = *n->num; - - int w = SHORT(n->p[0]->width) + 1; // [STRIFE] +1 - int x = n->x; - - // Don't draw negative values. - if (num < 0) - num = 0; - - // if non-number, do not draw it - if (num == 1994) - return; - - x = n->x; - - // in the special case of 0, you draw 0 - if (!num) - V_DrawPatch(x - w, n->y, n->p[ 0 ]); - - // draw the new number - while (num && numdigits--) - { - x -= w; - V_DrawPatch(x, n->y, n->p[ num % 10 ]); - num /= 10; - } -} - - -// haleyjd 09/01/10: [STRIFE] All other functions were removed. -/* -void -STlib_updateNum -( st_number_t* n, - boolean refresh ) -{ - if (*n->on) STlib_drawNum(n, refresh); -} - - -// -void -STlib_initPercent -( st_percent_t* p, - int x, - int y, - patch_t** pl, - int* num, - boolean* on, - patch_t* percent ) -{ - STlib_initNum(&p->n, x, y, pl, num, on, 3); - p->p = percent; -} - - - - -void -STlib_updatePercent -( st_percent_t* per, - int refresh ) -{ - if (refresh && *per->n.on) - V_DrawPatch(per->n.x, per->n.y, per->p); - - STlib_updateNum(&per->n, refresh); -} - - - -void -STlib_initMultIcon -( st_multicon_t* i, - int x, - int y, - patch_t** il, - int* inum, - boolean* on ) -{ - i->x = x; - i->y = y; - i->oldinum = -1; - i->inum = inum; - i->on = on; - i->p = il; -} - - - -void -STlib_updateMultIcon -( st_multicon_t* mi, - boolean refresh ) -{ - int w; - int h; - int x; - int y; - - if (*mi->on - && (mi->oldinum != *mi->inum || refresh) - && (*mi->inum!=-1)) - { - if (mi->oldinum != -1) - { - x = mi->x - SHORT(mi->p[mi->oldinum]->leftoffset); - y = mi->y - SHORT(mi->p[mi->oldinum]->topoffset); - w = SHORT(mi->p[mi->oldinum]->width); - h = SHORT(mi->p[mi->oldinum]->height); - - if (y - ST_Y < 0) - I_Error("updateMultIcon: y - ST_Y < 0"); - - V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); - } - V_DrawPatch(mi->x, mi->y, mi->p[*mi->inum]); - mi->oldinum = *mi->inum; - } -} - - - -void -STlib_initBinIcon -( st_binicon_t* b, - int x, - int y, - patch_t* i, - boolean* val, - boolean* on ) -{ - b->x = x; - b->y = y; - b->oldval = false; - b->val = val; - b->on = on; - b->p = i; -} - - - -void -STlib_updateBinIcon -( st_binicon_t* bi, - boolean refresh ) -{ - int x; - int y; - int w; - int h; - - if (*bi->on - && (bi->oldval != *bi->val || refresh)) - { - x = bi->x - SHORT(bi->p->leftoffset); - y = bi->y - SHORT(bi->p->topoffset); - w = SHORT(bi->p->width); - h = SHORT(bi->p->height); - - if (y - ST_Y < 0) - I_Error("updateBinIcon: y - ST_Y < 0"); - - if (*bi->val) - V_DrawPatch(bi->x, bi->y, bi->p); - else - V_CopyRect(x, y-ST_Y, st_backing_screen, w, h, x, y); - - bi->oldval = *bi->val; - } - -} -*/ - diff --git a/games/NXDoom/src/strife/st_lib.h b/games/NXDoom/src/strife/st_lib.h deleted file mode 100644 index b2c85a818e9..00000000000 --- a/games/NXDoom/src/strife/st_lib.h +++ /dev/null @@ -1,221 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// The status bar widget code. -// - -#ifndef __STLIB__ -#define __STLIB__ - - -// We are referring to patches. -#include "r_defs.h" - -// -// Typedefs of widgets -// - -// Number widget - -typedef struct -{ - // upper right-hand corner - // of the number (right-justified) - int x; - int y; - - // max # of digits in number - int width; - - // haleyjd 09/01/10: [STRIFE] Removed "oldnum" member - //int oldnum; - - // pointer to current value - int* num; - - // haleyjd 09/01/10: [STRIFE] Removed "on" member - // boolean* on; - - // list of patches for 0-9 - patch_t** p; - - // user data - int data; - -} st_number_t; - - - -// Percent widget ("child" of number widget, -// or, more precisely, contains a number widget.) -typedef struct -{ - // number information - st_number_t n; - - // percent sign graphic - patch_t* p; - -} st_percent_t; - - - -// Multiple Icon widget -typedef struct -{ - // center-justified location of icons - int x; - int y; - - // last icon number - int oldinum; - - // pointer to current icon - int* inum; - - // pointer to boolean stating - // whether to update icon - boolean* on; - - // list of icons - patch_t** p; - - // user data - int data; - -} st_multicon_t; - - - - -// Binary Icon widget - -typedef struct -{ - // center-justified location of icon - int x; - int y; - - // last icon value - boolean oldval; - - // pointer to current icon status - boolean* val; - - // pointer to boolean - // stating whether to update icon - boolean* on; - - - patch_t* p; // icon - int data; // user data - -} st_binicon_t; - - - -// -// Widget creation, access, and update routines -// - -// Initializes widget library. -// More precisely, initialize STMINUS, -// everything else is done somewhere else. -// -void STlib_init(void); - - - -// Number widget routines - -// haleyjd 09/01/10: [STRIFE] Removed "on" parameter. -void -STlib_initNum -( st_number_t* n, - int x, - int y, - patch_t** pl, - int* num, - int width ); - -// haleyjd 09/01/10: [STRIFE] Made globally visible. -void -STlib_drawNum -( st_number_t* n); - -// haleyjd 09/01/10: [STRIFE] New function -void -STlib_drawNumPositive -( st_number_t* n); - -/* haleyjd 09/01/10: [STRIFE] All the below were removed -void -STlib_updateNum -( st_number_t* n, - boolean refresh ); - - -// Percent widget routines -void -STlib_initPercent -( st_percent_t* p, - int x, - int y, - patch_t** pl, - int* num, - boolean* on, - patch_t* percent ); - - -void -STlib_updatePercent -( st_percent_t* per, - int refresh ); - - -// Multiple Icon widget routines -void -STlib_initMultIcon -( st_multicon_t* mi, - int x, - int y, - patch_t** il, - int* inum, - boolean* on ); - - -void -STlib_updateMultIcon -( st_multicon_t* mi, - boolean refresh ); - -// Binary Icon widget routines - -void -STlib_initBinIcon -( st_binicon_t* b, - int x, - int y, - patch_t* i, - boolean* val, - boolean* on ); - -void -STlib_updateBinIcon -( st_binicon_t* bi, - boolean refresh ); -*/ - -#endif diff --git a/games/NXDoom/src/strife/st_stuff.c b/games/NXDoom/src/strife/st_stuff.c deleted file mode 100644 index ae1d4cd90bd..00000000000 --- a/games/NXDoom/src/strife/st_stuff.c +++ /dev/null @@ -1,1605 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Status bar code. -// Does the face/direction indicator animatin. -// Does palette indicators as well (red pain/berserk, bright pickup) -// - - - -#include - -#include "i_system.h" -#include "i_video.h" -#include "z_zone.h" -#include "m_random.h" -#include "w_wad.h" - -#include "deh_main.h" -#include "deh_misc.h" -#include "doomdef.h" -#include "doomkeys.h" - -#include "g_game.h" - -#include "st_stuff.h" -#include "st_lib.h" -#include "r_local.h" - -#include "p_local.h" -#include "p_inter.h" -#include "p_dialog.h" // villsa [STRIFE] - -#include "am_map.h" -#include "m_cheat.h" -#include "m_menu.h" // villsa [STRIFE] -#include "m_misc.h" - -#include "s_sound.h" - -// Needs access to LFB. -#include "v_video.h" -#include "i_swap.h" - -// State. -#include "doomstat.h" -#include "d_main.h" // [STRIFE] - -// Data. -#include "dstrings.h" -#include "sounds.h" -#include "m_controls.h" -#include "hu_lib.h" // [STRIFE] -#include "hu_stuff.h" - -// -// STATUS BAR DATA -// - -// Palette indices. -// For damage/bonus red-/gold-shifts -#define STARTREDPALS 1 -#define STARTBONUSPALS 9 -#define NUMREDPALS 8 -#define NUMBONUSPALS 4 -// Radiation suit, green shift. -#define RADIATIONPAL 13 - -// Location of status bar -#define ST_X 0 - -// Location and size of statistics, -// justified according to widget type. -// Problem is, within which space? STbar? Screen? -// Note: this could be read in by a lump. -// Problem is, is the stuff rendered -// into a buffer, -// or into the frame buffer? - -// AMMO number pos. -// haleyjd 20100901: [STRIFE] Adjusted. -#define ST_AMMOWIDTH 3 -#define ST_AMMOX 311 -#define ST_AMMOY 162 - -// HEALTH number pos. -// haleyjd 20100901: [STRIFE] Adjusted. -#define ST_HEALTHWIDTH 3 -#define ST_HEALTHX 79 -#define ST_HEALTHY 162 - -// [STRIFE] -// Removed: -// * Weapon pos. -// * Frags pos. -// * ARMOR number pos. -// * Key icon positions. - -// Ammunition counter. -// haleyjd 20110213 [STRIFE]: ammo counters for the popup widget -#define ST_POPUPAMMOX 206 -static const int st_yforammo[NUMAMMO] = { 75, 99, 91, 139, 131, 115, 123 }; -static const int st_wforammo[NUMAMMO] = { 3, 3, 2, 3, 3, 2, 3 }; - -// Indicate maximum ammunition. -// Only needed because backpack exists. -// haleyjd 20110213 [STRIFE]: maxammo counters for the popup widget -#define ST_POPUPMAXAMMOX 239 - -// [STRIFE] -// Removed: -// * Doom weapon stuff -// * DETH title (???) - -// Dimensions given in characters. -#define ST_MSGWIDTH 52 - -// haleyjd 20100831: [STRIFE] -// * Removed faces. -// haleyjd 20100901: -// * Removed DOOM pre-beta cruft. -// * Removed deathmatch frags/arms-related stuff. -// * Removed arms panel stuff. -// * Removed unused widgets. -// * Removed more faces, keyboxes, st_randomnumber - -// graphics are drawn to a backing screen and blitted to the real screen -//byte *st_backing_screen; - [STRIFE]: Unused. - -// main player in game -static player_t* plyr; - -// ST_Start() has just been called -static boolean st_firsttime; - -// lump number for PLAYPAL -static int lu_palette; - -// whether left-side main status bar is active -static boolean st_statusbaron; - -// villsa [STRIFE] -static boolean st_dosizedisplay = false; - -// haleyjd 09/01/10: [STRIFE] -// Whether or not a popup is currently displayed -static boolean st_displaypopup = false; - -// villsa [STRIFE] -static int st_popupdisplaytics = 0; - -// villsa [STRIFE] -// Whether or not show popup objective screen -static boolean st_showobjective = false; - -// villsa [STRIFE] -static boolean st_showinvpop = false; - -// villsa [STRIFE] -static boolean st_showkeys = false; - -// villsa [STRIFE] TODO - identify variables -static int st_keypage = -1; -// [unused] static int dword_88490 = 0; - -// haleyjd 09/19/10: [STRIFE] Cached player data -static int st_lastcursorpos; -static int st_lastammo; -static int st_lastarmortype; -static int st_lasthealth; - -// haleyjd 20100901: [STRIFE] sbar -> invback -// main inventory background and other bits -static patch_t* invback; // main bar -static patch_t* stback; // multiplayer background -static patch_t* invtop; // top bit -static patch_t* invpop; // popup frame with text -static patch_t* invpop2; // plain popup frame -static patch_t* invpbak; // popup background w/details -static patch_t* invpbak2; // plain popup background -static patch_t* invcursor; // cursor - -// ammo/weapon/armor patches -static patch_t* invammo[NUMAMMO]; // ammo/weapons -static patch_t* invsigil[5]; // sigil pieces -static patch_t* invarmor[2]; // armor icons - -// names for ammo patches -static const char *invammonames[NUMAMMO] = -{ - "I_BLIT", - "I_XQRL", - "I_PQRL", - "I_BRY1", - "I_ROKT", - "I_GRN1", - "I_GRN2" -}; - -// haleyjd 20100901: [STRIFE] Replaced tallnum, shortnum w/inv fonts -// 0-9, green numbers -static patch_t* invfontg[10]; - -// 0-9, yellow numbers -static patch_t* invfonty[10]; - -// [unused] 3 key-cards, 3 skulls -- [STRIFE] has a lot more keys than 3 :P -//static patch_t* keys[NUMCARDS]; - -// ready-weapon widget -static st_number_t w_ready; // haleyjd [STRIFE]: This is still used. - -// haleyjd: [STRIFE] This is still used but was changed to a st_number_t. -// health widget -static st_number_t w_health; - -// ammo widgets -static st_number_t w_ammo[NUMAMMO]; // haleyjd [STRIFE]: Still used. - -// max ammo widgets -static st_number_t w_maxammo[NUMAMMO]; // haleyjd [STRIFE]: Still used. - -// [unused] number of frags so far in deathmatch -//static int st_fragscount; - - -cheatseq_t cheat_mus = CHEAT("spin", 2); // [STRIFE]: idmus -> spin -cheatseq_t cheat_god = CHEAT("omnipotent", 0); // [STRIFE]: iddqd -> omnipotent -cheatseq_t cheat_ammo = CHEAT("boomstix", 0); // [STRIFE]: idfa -> boomstix -cheatseq_t cheat_noclip = CHEAT("elvis", 0); // [STRIFE]: idclip -> elvis -cheatseq_t cheat_clev = CHEAT("rift", 2); // [STRIFE]: idclev -> rift -cheatseq_t cheat_mypos = CHEAT("gps", 0); // [STRIFE]: idmypos -> gps -cheatseq_t cheat_scoot = CHEAT("scoot", 1); // [STRIFE]: new cheat scoot -cheatseq_t cheat_nuke = CHEAT("stonecold", 0); // [STRIFE]: new cheat stonecold -cheatseq_t cheat_keys = CHEAT("jimmy", 0); // [STRIFE]: new cheat jimmy (all keys) -cheatseq_t cheat_stealth = CHEAT("gripper", 0); // [STRIFE]: new cheat gripper -cheatseq_t cheat_midas = CHEAT("donnytrump", 0); // [STRIFE]: new cheat -cheatseq_t cheat_lego = CHEAT("lego", 0); // [STRIFE]: new cheat -cheatseq_t cheat_dev = CHEAT("dots", 0); // [STRIFE]: new cheat - -// haleyjd 20110224: enumeration for access to powerup cheats -enum -{ - ST_PUMPUP_B, - ST_PUMPUP_I, - ST_PUMPUP_M, - ST_PUMPUP_H, - ST_PUMPUP_P, - ST_PUMPUP_S, - ST_PUMPUP_T, - ST_PUMPUP, - NUM_ST_PUMPUP -}; - -cheatseq_t cheat_powerup[NUM_ST_PUMPUP] = // [STRIFE] -{ - CHEAT("pumpupb", 0), - CHEAT("pumpupi", 0), - CHEAT("pumpupm", 0), - CHEAT("pumpuph", 0), - CHEAT("pumpupp", 0), - CHEAT("pumpups", 0), - CHEAT("pumpupt", 0), - CHEAT("pumpup", 0), -}; - -//cheatseq_t cheat_choppers = CHEAT("idchoppers", 0); [STRIFE] no such thing - -void M_SizeDisplay(int choice); // villsa [STRIFE] - -// -// STATUS BAR CODE -// -void ST_Stop(void); - -// [STRIFE] -static char st_msgbuf[ST_MSGWIDTH]; - -// Respond to keyboard input events, -// intercept cheats. -boolean ST_Responder(event_t* ev) -{ - // haleyjd 09/27/10: made static to ST_Responder - static boolean st_keystate = false; - int i; - - // Filter automap on/off. - if(ev->type == ev_keyup) - { - if((ev->data1 & 0xffff0000) == AM_MSGHEADER) - { - switch(ev->data1) - { - case AM_MSGENTERED: - st_firsttime = true; - break; - - case AM_MSGEXITED: - break; - } - - return false; - } - - // villsa [STRIFE] - if(ev->data1 != key_invpop && - ev->data1 != key_mission && - ev->data1 != key_invkey) - return false; - - // villsa [STRIFE] - if(ev->data1 == key_invpop) - st_showinvpop = false; - else - { - if(ev->data1 == key_mission) - st_showobjective = false; - else - { - if(ev->data1 == key_invkey) - { - st_showkeys = false; - st_keystate = false; - } - } - } - - if(!st_showkeys && !st_showobjective && !st_showinvpop) - { - if(!st_popupdisplaytics) - { - st_displaypopup = false; - if(st_dosizedisplay) - M_SizeDisplay(true); - - st_dosizedisplay = false; - } - } - - return true; - } - - // if a user keypress... - if(ev->type != ev_keydown) - return false; - - // haleyjd 20100927: No input allowed when the player is dead - if(plyr->mo->health <= 0) - return false; - - // keydown events - if(ev->data1 == key_invquery) // inventory query - { - inventory_t *inv = &(plyr->inventory[plyr->inventorycursor]); - if(inv->amount) - { - DEH_snprintf(st_msgbuf, sizeof(st_msgbuf), "%d %s", - inv->amount, - DEH_String(mobjinfo[inv->type].name)); - plyr->message = st_msgbuf; - } - } - - // villsa [STRIFE] - if(ev->data1 == key_invpop || ev->data1 == key_invkey || ev->data1 == key_mission) - { - if(ev->data1 == key_invkey) - { - st_showobjective = false; - st_showinvpop = false; - - if(!st_keystate) - { - st_keystate = true; - if(++st_keypage > 2) - { - st_popupdisplaytics = 0; - st_showkeys = false; - st_displaypopup = false; - st_keypage = -1; - return true; - } - } - - if(netgame) - st_popupdisplaytics = 20; - else - st_popupdisplaytics = 50; - - st_showkeys = true; - } - else - { - if(ev->data1 != key_mission || netgame) - { - if(ev->data1 == key_invpop) - { - st_keypage = -1; - st_popupdisplaytics = false; - st_showkeys = false; - st_showobjective = false; - st_showinvpop = true; - } - } - else - { - st_showkeys = netgame; - st_showinvpop = netgame; - st_keypage = -1; - - st_popupdisplaytics = ev->data2 ^ key_mission; - - st_showobjective = true; - } - } - - if(st_showkeys || st_showobjective || st_showinvpop) - { - st_displaypopup = true; - if(viewheight == SCREENHEIGHT) - { - M_SizeDisplay(false); - st_dosizedisplay = true; - } - } - } - - if(ev->data1 == key_invleft) // inventory move left - { - if(plyr->inventorycursor > 0) - plyr->inventorycursor--; - return true; - } - else if(ev->data1 == key_invright) - { - if(plyr->inventorycursor < plyr->numinventory - 1) - plyr->inventorycursor++; - return true; - } - else if(ev->data1 == key_invhome) - { - plyr->inventorycursor = 0; - return true; - } - else if(ev->data1 == key_invend) - { - if(plyr->numinventory) - plyr->inventorycursor = plyr->numinventory - 1; - else - plyr->inventorycursor = 0; - return true; - } - - // - // [STRIFE] Cheats which are allowed in netgames/demos: - // - - // 'spin' cheat for changing music - if (cht_CheckCheat(&cheat_mus, ev->data2)) - { - char buf[3]; - int musnum; - - plyr->message = DEH_String(STSTR_MUS); - cht_GetParam(&cheat_mus, buf); - - musnum = (buf[0] - '0') * 10 + buf[1] - '0'; - - if (((buf[0]-'0')*10 + buf[1]-'0') > 35) - plyr->message = DEH_String(STSTR_NOMUS); - else - S_ChangeMusic(musnum, 1); - } - // [STRIFE]: "dev" cheat - "DOTS" - else if (cht_CheckCheat(&cheat_dev, ev->data2)) - { - devparm = !devparm; - if (devparm) - plyr->message = DEH_String("devparm ON"); - else - plyr->message = DEH_String("devparm OFF"); - } - - // [STRIFE] Cheats below are not allowed in netgames or demos - if(netgame || !usergame) - return false; - - if (cht_CheckCheat(&cheat_god, ev->data2)) - { - // 'omnipotent' cheat for toggleable god mode - plyr->cheats ^= CF_GODMODE; - if (plyr->cheats & CF_GODMODE) - { - if (plyr->mo) - plyr->mo->health = 100; - - plyr->health = deh_god_mode_health; - plyr->st_update = true; // [STRIFE] - plyr->message = DEH_String(STSTR_DQDON); - } - else - { - plyr->st_update = true; - plyr->message = DEH_String(STSTR_DQDOFF); - } - } - else if (cht_CheckCheat(&cheat_ammo, ev->data2)) - { - // [STRIFE]: "BOOMSTIX" cheat for all normal weapons - plyr->armorpoints = deh_idkfa_armor; - plyr->armortype = deh_idkfa_armor_class; - - for (i = 0; i < NUMWEAPONS; i++) - if(!isdemoversion || weaponinfo[i].availabledemo) - plyr->weaponowned[i] = true; - - // Takes away the Sigil, even if you already had it... - plyr->weaponowned[wp_sigil] = false; - - for (i=0;iammo[i] = plyr->maxammo[i]; - - plyr->message = DEH_String(STSTR_FAADDED); - } - else if(cht_CheckCheat(&cheat_keys, ev->data2)) - { - // villsa [STRIFE]: "JIMMY" cheat for all keys - #define FIRSTKEYSETAMOUNT 16 - - if(plyr->cards[FIRSTKEYSETAMOUNT - 1]) - { - if(plyr->cards[NUMCARDS - 1] || isdemoversion) - { - for(i = 0; i < NUMCARDS; i++) - plyr->cards[i] = false; - - plyr->message = DEH_String("Keys removed"); - } - else - { - for(i = 0; i < NUMCARDS; i++) - plyr->cards[i] = true; - - plyr->message = DEH_String("Cheater Keys Added"); - } - } - else - { - for(i = 0; i < FIRSTKEYSETAMOUNT; i++) - plyr->cards[i] = true; - - plyr->message = DEH_String("Cheater Keys Added"); - } - } - else if (cht_CheckCheat(&cheat_noclip, ev->data2)) - { - // [STRIFE] Removed idspispopd, added NOCLIP flag setting/removal - // Noclip cheat - "ELVIS" (hah-hah :P ) - - plyr->cheats ^= CF_NOCLIP; - - if (plyr->cheats & CF_NOCLIP) - { - plyr->message = DEH_String(STSTR_NCON); - plyr->mo->flags |= MF_NOCLIP; - } - else - { - plyr->message = DEH_String(STSTR_NCOFF); - plyr->mo->flags &= ~MF_NOCLIP; - } - } - else if(cht_CheckCheat(&cheat_stealth, ev->data2)) - { - // villsa [STRIFE]: "GRIPPER" cheat; nothing to do with stealth... - plyr->cheats ^= CF_NOMOMENTUM; - if(plyr->cheats & CF_NOMOMENTUM) - plyr->message = DEH_String("STEALTH BOOTS ON"); - else - plyr->message = DEH_String("STEALTH BOOTS OFF"); - } - - for(i = 0; i < ST_PUMPUP_B + 3; ++i) - { - // [STRIFE]: Handle berserk, invisibility, and envirosuit - if(cht_CheckCheat(&cheat_powerup[i], ev->data2)) - { - if(plyr->powers[i]) - plyr->powers[i] = (i != 1); - else - P_GivePower(plyr, i); - plyr->message = DEH_String(STSTR_BEHOLDX); - } - } - if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_H], ev->data2)) - { - // [STRIFE]: PUMPUPH gives medical inventory items - P_GiveItemToPlayer(plyr, SPR_STMP, MT_INV_MED1); - P_GiveItemToPlayer(plyr, SPR_MDKT, MT_INV_MED2); - P_GiveItemToPlayer(plyr, SPR_FULL, MT_INV_MED3); - plyr->message = DEH_String("you got the stuff!"); - } - if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_P], ev->data2)) - { - // [STRIFE]: PUMPUPP gives backpack - if(!plyr->backpack) - { - for(i = 0; i < NUMAMMO; ++i) - plyr->maxammo[i] = 2 * plyr->maxammo[i]; - } - plyr->backpack = true; - - for(i = 0; i < NUMAMMO; ++i) - P_GiveAmmo(plyr, i, 1); - plyr->message = DEH_String("you got the stuff!"); - } - if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_S], ev->data2)) - { - // [STRIFE]: PUMPUPS gives stamina and accuracy upgrades - P_GiveItemToPlayer(plyr, SPR_TOKN, MT_TOKEN_STAMINA); - P_GiveItemToPlayer(plyr, SPR_TOKN, MT_TOKEN_NEW_ACCURACY); - plyr->message = DEH_String("you got the stuff!"); - } - if(cht_CheckCheat(&cheat_powerup[ST_PUMPUP_T], ev->data2)) - { - // [STRIFE] PUMPUPT gives targeter - P_GivePower(plyr, pw_targeter); - plyr->message = DEH_String("you got the stuff!"); - } - // [STRIFE]: PUMPUP - if (cht_CheckCheat(&cheat_powerup[ST_PUMPUP], ev->data2)) - { - // 'behold' power-up menu - plyr->message = DEH_String(STSTR_BEHOLD); - return false; - } - - if (cht_CheckCheat(&cheat_mypos, ev->data2)) - { - // [STRIFE] 'GPS' for player position - static char buf[ST_MSGWIDTH]; - M_snprintf(buf, sizeof(buf), - "ang=0x%x;x,y=(0x%x,0x%x)", - players[consoleplayer].mo->angle, - players[consoleplayer].mo->x, - players[consoleplayer].mo->y); - plyr->message = buf; - } - - // 'rift' change-level cheat - if (cht_CheckCheat(&cheat_clev, ev->data2)) - { - char buf[3]; - int map; - - cht_GetParam(&cheat_clev, buf); - - map = (buf[0] - '0') * 10 + buf[1] - '0'; - - // haleyjd 20100901: Removed Chex Quest stuff. - // haleyjd 20100915: Removed retail/registered/shareware stuff - - // haleyjd 20130301: different bounds in v1.31 - // Ohmygod - this is not going to work. - if(gameversion == exe_strife_1_31) - { - if ((isdemoversion && (map < 32 || map > 34)) || - (isregistered && (map <= 0 || map > 34))) - return false; - } - else - { - if (map <= 0 || map > 40) - return false; - } - - // So be it. - plyr->message = DEH_String(STSTR_CLEV); - G_RiftExitLevel(map, 0, plyr->mo->angle); - } - else if(cht_CheckCheat(&cheat_scoot, ev->data2)) - { - char buf[3]; - int spot; - - cht_GetParam(&cheat_scoot, buf); - - spot = buf[0] - '0'; - - // BUG: should be <= 9. Shouldn't do anything bad though... - if(spot <= 10) - { - plyr->message = DEH_String("Spawning to spot"); - G_RiftCheat(spot); - return false; - } - } - - // villsa [STRIFE] - if(cht_CheckCheat(&cheat_nuke, ev->data2)) - { - stonecold ^= 1; - plyr->message = DEH_String("Kill 'em. Kill 'em All"); - return false; - } - - // villsa [STRIFE] - if(cht_CheckCheat(&cheat_midas, ev->data2)) - { - plyr->message = DEH_String("YOU GOT THE MIDAS TOUCH, BABY"); - P_GiveItemToPlayer(plyr, SPR_HELT, MT_TOKEN_TOUGHNESS); - } - - // villsa [STRIFE] - // haleyjd 20110224: No sigil in demo version - if(!isdemoversion && cht_CheckCheat(&cheat_lego, ev->data2)) - { - plyr->st_update = true; - if(plyr->weaponowned[wp_sigil]) - { - if(++plyr->sigiltype > 4) - { - plyr->sigiltype = -1; - plyr->pendingweapon = wp_fist; - plyr->weaponowned[wp_sigil] = false; - } - } - else - { - plyr->weaponowned[wp_sigil] = true; - plyr->sigiltype = 0; - } - // BUG: This brings up a bad version of the Sigil (sigiltype -1) which - // causes some VERY interesting behavior, when you type LEGO for the - // sixth time. This shouldn't be done when taking it away, and yet it - // is here... verified with vanilla. - plyr->pendingweapon = wp_sigil; - } - - return false; -} - - -/* -int ST_calcPainOffset(void) -{ - // haleyjd 08/31/10: [STRIFE] Removed. -} -*/ - -// -// This is a not-very-pretty routine which handles -// the face states and their timing. -// the precedence of expressions is: -// dead > evil grin > turned head > straight ahead -// -/* -void ST_updateFaceWidget(void) -{ - // haleyjd 08/31/10: [STRIFE] Removed. -} -*/ - -/* -void ST_updateWidgets(void) -{ - // haleyjd 09/01/10: [STRIFE] Rogue merged this into ST_Ticker below. -} -*/ - -// -// ST_Ticker -// -// haleyjd 09/01/10: [STRIFE] -// * Removed st_clock and st_randomnumber. -// * Merged ST_updateWidgets here. Wasn't inlined, as doesn't exist separately -// in the binary as inlined functions normally do. -// -void ST_Ticker (void) -{ - static int largeammo = 1994; // means "n/a" - - // must redirect the pointer if the ready weapon has changed. - if (weaponinfo[plyr->readyweapon].ammo == am_noammo) - w_ready.num = &largeammo; - else - w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo]; - - w_ready.data = plyr->readyweapon; - - // STRIFE-TODO: Gobbledeegunk. - /* - v2 = dword_88490-- == 1; // no clue yet... - if(v2) - dword_DC7F4 = dword_DC7F0;*/ - - if(st_popupdisplaytics) - { - int tics = st_popupdisplaytics; - - --st_popupdisplaytics; - if(tics == 1) - { - st_displaypopup = false; - st_showkeys = false; - st_keypage = -1; - - if(st_dosizedisplay) - M_SizeDisplay(true); // mondo hack? - - st_dosizedisplay = false; - } - } - - // haleyjd 20100901: [STRIFE] Keys are handled on a popup - // haleyjd 20100831: [STRIFE] No face widget - // haleyjd 20100901: [STRIFE] Armor, weapons, frags, etc. handled elsewhere - - // haleyjd: This is from the PRE-BETA! Left here because it amuses me ;) - // get rid of chat window if up because of message - //if (!--st_msgcounter) - // st_chat = st_oldchat; -} - -static int st_palette = 0; - -// -// ST_doPaletteStuff -// -// haleyjd 20100831: [STRIFE] -// * Changed radsuit palette handling for Strife nukagecount. -// * All other logic verified to be unmodified. -// -void ST_doPaletteStuff(void) -{ - - int palette; - byte* pal; - int cnt; - int bzc; - - cnt = plyr->damagecount; - - if (plyr->powers[pw_strength]) - { - // slowly fade the berzerk out - bzc = 12 - (plyr->powers[pw_strength]>>6); - - if (bzc > cnt) - cnt = bzc; - } - - if (cnt) - { - palette = (cnt+7)>>3; - - if (palette >= NUMREDPALS) - palette = NUMREDPALS-1; - - palette += STARTREDPALS; - } - - else if (plyr->bonuscount) - { - palette = (plyr->bonuscount+7)>>3; - - if (palette >= NUMBONUSPALS) - palette = NUMBONUSPALS-1; - - palette += STARTBONUSPALS; - } - // haleyjd 20100831: [STRIFE] Flash green when in nukage, not when has - // an environment suit (a breathing sound is played to indicate that - // instead). - else if ( plyr->nukagecount > 16*TICRATE || - (plyr->nukagecount & 8)) - palette = RADIATIONPAL; - else - palette = 0; - - // haleyjd 08/31/10: Removed Chex Quest - - if (palette != st_palette) - { - st_palette = palette; - pal = (byte *) W_CacheLumpNum (lu_palette, PU_CACHE)+palette*768; - I_SetPalette (pal); - } - -} - -/* -void ST_drawWidgets(boolean refresh) -{ - haleyjd 09/01/10: [STRIFE] Removed -} -*/ - -// -// ST_drawNumFontY -// -// haleyjd 20100919: [STRIFE] New function -// Draws a small yellow number for inventory etc. -// -void ST_drawNumFontY(int x, int y, int num) -{ - if(!num) - V_DrawPatch(x, y, invfonty[0]); - - while(num) - { - V_DrawPatch(x, y, invfonty[num % 10]); - x -= SHORT(invfonty[0]->width) + 1; - num /= 10; - } -} - -// -// ST_drawNumFontY2 -// -// haleyjd 20100919: [STRIFE] New function -// As above, but turns negative numbers into zero. -// -void ST_drawNumFontY2(int x, int y, int num) -{ - if(!num) - V_DrawPatch(x, y, invfonty[0]); - - if(num < 0) - num = 0; - - while(num) - { - V_DrawPatchDirect(x, y, invfonty[num % 10]); - x -= SHORT(invfonty[0]->width) + 1; - num /= 10; - } -} - -// -// ST_drawLine -// -// haleyjd 20100920: [STRIFE] New function -// Basic horizontal line drawing routine used for the health bars. -// -void ST_drawLine(int x, int y, int len, int color) -{ - byte putcolor = (byte)(color); - byte *drawpos = I_VideoBuffer + y * SCREENWIDTH + x; - int i = 0; - - while(i < len) - { - *drawpos++ = putcolor; - ++i; - } -} - -// -// ST_doRefresh -// -// haleyjd 20100920: Evidence more than suggests that Rogue moved all status bar -// drawing down to this function. -// -void ST_doRefresh(void) -{ - // draw status bar background to off-screen buff - if (st_statusbaron) - { - int firstinventory, icon_x, num_x, i, numdrawn; - - // haleyjd 20100919: No backscreen caching in Strife. - //V_UseBuffer(st_backing_screen); - - // TODO: only sometimes drawing? - - plyr->st_update = false; - - // cache data - st_lastcursorpos = plyr->inventorycursor; - st_lastammo = weaponinfo[plyr->readyweapon].ammo; - st_lastarmortype = plyr->armortype; - st_lasthealth = plyr->health; - st_firsttime = false; - - // draw main status bar - V_DrawPatch(ST_X, ST_Y, invback); - - // draw multiplayer armor backdrop if netgame - // haleyjd 20131031: BUG - vanilla is accessing a NULL pointer here when - // playing back netdemos! It doesn't appear to draw anything, and there - // is no apparent ill effect on gameplay, so the best we can do is check. - if(netgame && stback) - V_DrawPatch(ST_X, 173, stback); - - if(plyr->inventorycursor >= 6) - firstinventory = plyr->inventorycursor - 5; - else - firstinventory = 0; - - // Draw cursor. - if(plyr->numinventory) - { - V_DrawPatch(35 * (plyr->inventorycursor - firstinventory) + 42, - 180, invcursor); - } - - // Draw inventory bar - for(num_x = 68, icon_x = 48, i = firstinventory, numdrawn = 0; - num_x < 278; - num_x += 35, icon_x += 35, i++, numdrawn++) - { - int lumpnum; - patch_t *patch; - char iconname[8]; - - if(plyr->numinventory <= numdrawn) - break; - - DEH_snprintf(iconname, sizeof(iconname), "I_%s", - DEH_String(sprnames[plyr->inventory[i].sprite])); - - lumpnum = W_CheckNumForName(iconname); - if(lumpnum == -1) - patch = W_CacheLumpName(DEH_String("STCFN063"), PU_CACHE); - else - patch = W_CacheLumpNum(lumpnum, PU_STATIC); - - V_DrawPatch(icon_x, 182, patch); - ST_drawNumFontY(num_x, 191, plyr->inventory[i].amount); - } - - // haleyjd 20100919: Draw sigil icon - if(plyr->weaponowned[wp_sigil]) - V_DrawPatch(253, 175, invsigil[plyr->sigiltype]); - - // haleyjd 20100919: Draw ammo - if(st_lastammo < NUMAMMO) - V_DrawPatch(290, 180, invammo[st_lastammo]); - - // haleyjd 20100919: Draw armor - if(plyr->armortype) - { - V_DrawPatch(2, 177, invarmor[plyr->armortype - 1]); - ST_drawNumFontY(20, 191, plyr->armorpoints); - } - - // haleyjd 20100920: Draw life bars. - { - int barlength; - int lifecolor1; - int lifecolor2; - - barlength = plyr->health; - if(barlength > 100) - barlength = 200 - plyr->health; - barlength *= 2; - - if(plyr->health < 11) // Danger, Will Robinson! - lifecolor1 = 64; - else if(plyr->health < 21) // Caution - lifecolor1 = 80; - else // All is well. - lifecolor1 = 96; - - if(plyr->cheats & CF_GODMODE) // Gold, probably a throwback to DOOM. - lifecolor1 = 226; - - lifecolor2 = lifecolor1 + 3; - - // Draw the normal health bars - ST_drawLine(49, 172, barlength, lifecolor1); - ST_drawLine(49, 173, barlength, lifecolor2); - ST_drawLine(49, 175, barlength, lifecolor1); - ST_drawLine(49, 176, barlength, lifecolor2); - - // Draw the > 100 health lines - if(plyr->health > 100) - { - int oldbarlength = barlength; - lifecolor1 = 112; // Shades of blue - lifecolor2 = lifecolor1 + 3; - - // take up the difference not drawn by the first (<= 100) bar - barlength = 200 - barlength; - - ST_drawLine(49 + oldbarlength, 172, barlength, lifecolor1); - ST_drawLine(49 + oldbarlength, 173, barlength, lifecolor2); - ST_drawLine(49 + oldbarlength, 175, barlength, lifecolor1); - ST_drawLine(49 + oldbarlength, 176, barlength, lifecolor2); - } - } // end local-scope block - - // haleyjd 20100919: nope, not in Strife. - //V_RestoreBuffer(); - //V_CopyRect(ST_X, 0, st_backing_screen, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y); - } -} - -// haleyjd [STRIFE]: Removed ST_diffDraw - -void ST_Drawer (boolean fullscreen, boolean refresh) -{ - st_statusbaron = (!fullscreen) || automapactive; - st_firsttime = st_firsttime || refresh; - - // Do red-/gold-shifts from damage/items - ST_doPaletteStuff(); - - // If just after ST_Start(), refresh all - ST_doRefresh(); - // Otherwise, update as little as possible - //ST_diffDraw(); [STRIFE]: nope -} - -// -// ST_calcFrags -// -// haleyjd [STRIFE] New function. -// Calculate frags for display on the frags popup. -// -static int ST_calcFrags(int pnum) -{ - int i; - int result = 0; - - for(i = 0; i < MAXPLAYERS; i++) - { - if(i == pnum) // self-frags - result -= players[pnum].frags[i]; - else - result += players[pnum].frags[i]; - } - - return result; -} - -// -// ST_drawTime -// -// villsa [STRIFE] New function. -// Draws game time on pop up screen -// -static void ST_drawTime(int x, int y, int time) -{ - int hours; - int minutes; - int seconds; - char string[16]; - - // haleyjd 20110213: fixed minutes - hours = time / 3600; - minutes = (time / 60) % 60; - seconds = time % 60; - - DEH_snprintf(string, 16, "%02d:%02d:%02d", hours, minutes, seconds); - HUlib_drawYellowText(x, y, string); -} - -#define ST_KEYSPERPAGE 10 -#define ST_KEYS_X 20 -#define ST_KEYS_Y 63 -#define ST_KEYNAME_X 17 -#define ST_KEYNAME_Y 4 -#define ST_KEYS_YSTEP 17 -#define ST_KEYS_NUMROWS 4 -#define ST_KEYS_COL2X 160 - -// -// ST_drawKeysPopup -// -// haleyjd 20110213: [STRIFE] New function -// This has taken the longest out of almost everything to get working properly. -// -static boolean ST_drawKeysPopup(void) -{ - int x, y, yt, key, keycount; - mobjinfo_t *info; - - V_DrawXlaPatch(0, 56, invpbak2); - V_DrawPatchDirect(0, 56, invpop2); - - if(deathmatch) - { - int pnum; - patch_t *colpatch; - char buffer[128]; - int frags; - - // In deathmatch, the keys popup is replaced by a chart of frag counts - - // first column - y = 64; - yt = 66; - for(pnum = 0; pnum < MAXPLAYERS/2; pnum++) - { - DEH_snprintf(buffer, sizeof(buffer), "stcolor%d", pnum+1); - colpatch = W_CacheLumpName(buffer, PU_CACHE); - V_DrawPatchDirect(28, y, colpatch); - frags = ST_calcFrags(pnum); - DEH_snprintf(buffer, sizeof(buffer), "%s%d", player_names[pnum], frags); - HUlib_drawYellowText(38, yt, buffer); - if(!playeringame[pnum]) - HUlib_drawYellowText(28, pnum*17 + 65, "X"); - y += 17; - yt += 17; - } - - // second column - y = 64; - yt = 66; - for(pnum = MAXPLAYERS/2; pnum < MAXPLAYERS; pnum++) - { - DEH_snprintf(buffer, sizeof(buffer), "stcolor%d", pnum+1); - colpatch = W_CacheLumpName(buffer, PU_CACHE); - V_DrawPatchDirect(158, y, colpatch); - frags = ST_calcFrags(pnum); - DEH_snprintf(buffer, sizeof(buffer), "%s%d", player_names[pnum], frags); - HUlib_drawYellowText(168, yt, buffer); - if(!playeringame[pnum]) - HUlib_drawYellowText(158, pnum*17 - 3, "X"); - y += 17; - yt += 17; - } - } - else - { - // Bounds-check page number - if(st_keypage < 0 || st_keypage > 2) - { - st_keypage = -1; - st_popupdisplaytics = 0; - st_displaypopup = false; - - return false; - } - - // Are there any keys to display on this page? - if(st_keypage > 0) - { - boolean haskeyinrange = false; - - for(key = ST_KEYSPERPAGE * st_keypage, keycount = 0; - keycount < ST_KEYSPERPAGE && key < NUMCARDS; - ++key, ++keycount) - { - if(plyr->cards[key]) - haskeyinrange = true; - } - - if(!haskeyinrange) - { - st_displaypopup = false; - st_showkeys = false; - st_keypage = -1; - - return false; - } - } - - // Draw the keys for the current page - key = ST_KEYSPERPAGE * st_keypage; - keycount = 0; - x = ST_KEYS_X; - y = ST_KEYS_Y; - info = &mobjinfo[MT_KEY_BASE + key]; - - for(; keycount < ST_KEYSPERPAGE && key < NUMCARDS; ++key, ++keycount, ++info) - { - char sprname[8]; - patch_t *patch; - memset(sprname, 0, sizeof(sprname)); - - if(plyr->cards[key]) - { - // Get spawnstate sprite name and load corresponding icon - DEH_snprintf(sprname, sizeof(sprname), "I_%s", - sprnames[states[info->spawnstate].sprite]); - patch = W_CacheLumpName(sprname, PU_CACHE); - V_DrawPatchDirect(x, y, patch); - HUlib_drawYellowText(x + ST_KEYNAME_X, y + ST_KEYNAME_Y, info->name); - } - - if(keycount != ST_KEYS_NUMROWS) - y += ST_KEYS_YSTEP; - else - { - x = ST_KEYS_COL2X; - y = ST_KEYS_Y; - } - } - } - - return true; -} - -// -// ST_DrawExternal -// -// haleyjd 20100901: [STRIFE] New function. -// * Draws external portions of the status bar such the top bar and popups. -// -boolean ST_DrawExternal(void) -{ - int i; - - if(st_statusbaron) - { - V_DrawPatchDirect(0, 160, invtop); - STlib_drawNumPositive(&w_health); - STlib_drawNumPositive(&w_ready); - } - else - { - ammotype_t ammo; - - ST_drawNumFontY2(15, 194, plyr->health); - ammo = weaponinfo[plyr->readyweapon].ammo; - if (ammo != am_noammo) - ST_drawNumFontY2(310, 194, plyr->ammo[ammo]); - } - - if(!st_displaypopup) - return false; - - // villsa [STRIFE] added 20100926 - if(st_showobjective) - { - V_DrawXlaPatch(0, 56, invpbak2); - V_DrawPatchDirect(0, 56, invpop2); - M_DialogDimMsg(24, 74, mission_objective, true); - HUlib_drawYellowText(24, 74, mission_objective); - ST_drawTime(210, 64, leveltime / TICRATE); - } - else - { - int keys = 0; - - // villsa [STRIFE] keys popup - if(st_showkeys || st_popupdisplaytics) - return ST_drawKeysPopup(); - - V_DrawXlaPatch(0, 56, invpbak); - V_DrawPatchDirect(0, 56, invpop); - - for(i = 0; i < NUMCARDS; i++) - { - if(plyr->cards[i]) - keys++; - } - - ST_drawNumFontY2(261, 132, keys); - - if(plyr->weaponowned[wp_elecbow]) - { - V_DrawPatchDirect(38, 86, - W_CacheLumpName(DEH_String("CBOWA0"), PU_CACHE)); - } - if(plyr->weaponowned[wp_rifle]) - { - V_DrawPatchDirect(40, 107, - W_CacheLumpName(DEH_String("RIFLA0"), PU_CACHE)); - } - if(plyr->weaponowned[wp_missile]) - { - V_DrawPatchDirect(39, 131, - W_CacheLumpName(DEH_String("MMSLA0"), PU_CACHE)); - } - if(plyr->weaponowned[wp_hegrenade]) - { - V_DrawPatchDirect(78, 87, - W_CacheLumpName(DEH_String("GRNDA0"), PU_CACHE)); - } - if(plyr->weaponowned[wp_flame]) - { - V_DrawPatchDirect(80, 117, - W_CacheLumpName(DEH_String("FLAMA0"), PU_CACHE)); - } - if(plyr->weaponowned[wp_mauler]) - { - V_DrawPatchDirect(75, 142, - W_CacheLumpName(DEH_String("TRPDA0"), PU_CACHE)); - } - - // haleyjd 20110213: draw ammo - for(i = 0; i < NUMAMMO; i++) - { - STlib_drawNumPositive(&w_ammo[i]); - STlib_drawNumPositive(&w_maxammo[i]); - } - - ST_drawNumFontY2(261, 84, plyr->accuracy); - ST_drawNumFontY2(261, 108, plyr->stamina); - - if(plyr->powers[pw_communicator]) - { - V_DrawPatchDirect(280, 130, - W_CacheLumpName(DEH_String("I_COMM"), PU_CACHE)); - } - } - - return true; -} - -typedef void (*load_callback_t)(const char *lumpname, patch_t **variable); - -// -// ST_loadUnloadGraphics -// -// Iterates through all graphics to be loaded or unloaded, along with -// the variable they use, invoking the specified callback function. -// -// [STRIFE] Altered to load all Strife status bar resources. -// -static void ST_loadUnloadGraphics(load_callback_t callback) -{ - int i; - char namebuf[9]; - - // haleyjd 20100901: [STRIFE] - // Load the numbers, green and yellow - for (i=0;i<10;i++) - { - DEH_snprintf(namebuf, 9, "INVFONG%d", i); - callback(namebuf, &invfontg[i]); - - DEH_snprintf(namebuf, 9, "INVFONY%d", i); - callback(namebuf, &invfonty[i]); - } - - // haleyjd 20100919: load Sigil patches - if(!isdemoversion) - { - for(i = 0; i < 5; i++) - { - DEH_snprintf(namebuf, 9, "I_SGL%d", i+1); - callback(namebuf, &invsigil[i]); - } - } - - // load ammo patches - for(i = 0; i < NUMAMMO; i++) - callback(DEH_String(invammonames[i]), &invammo[i]); - - // load armor patches - callback(DEH_String("I_ARM2"), &invarmor[0]); - callback(DEH_String("I_ARM1"), &invarmor[1]); - - // haleyjd 20100919: [STRIFE] - // * No face, but there is this patch, which appears behind the armor - DEH_snprintf(namebuf, 9, "STBACK0%d", consoleplayer + 1); - if(netgame) - callback(namebuf, &stback); - - // 20100901: - // * Removed all unused DOOM stuff (arms, numbers, %, etc). - - // haleyjd 20100901: [STRIFE]: stbar -> invback, added new patches - // status bar background bits - callback(DEH_String("INVBACK"), &invback); - callback(DEH_String("INVTOP"), &invtop); - callback(DEH_String("INVPOP"), &invpop); - callback(DEH_String("INVPOP2"), &invpop2); - callback(DEH_String("INVPBAK"), &invpbak); - callback(DEH_String("INVPBAK2"), &invpbak2); - callback(DEH_String("INVCURS"), &invcursor); -} - -static void ST_loadCallback(const char *lumpname, patch_t **variable) -{ - *variable = W_CacheLumpName(lumpname, PU_STATIC); -} - -void ST_loadGraphics(void) -{ - ST_loadUnloadGraphics(ST_loadCallback); -} - -void ST_loadData(void) -{ -// static int dword_8848C = 1; // STRIFE-TODO: what is the purpose of this? -// dword_8848C = 0; - - lu_palette = W_GetNumForName (DEH_String("PLAYPAL")); - ST_loadGraphics(); -} - -static void ST_unloadCallback(const char *lumpname, patch_t **variable) -{ - W_ReleaseLumpName(lumpname); - *variable = NULL; -} - -void ST_unloadGraphics(void) -{ - ST_loadUnloadGraphics(ST_unloadCallback); -} - -void ST_unloadData(void) -{ - ST_unloadGraphics(); -} - -// -// ST_initData -// -// haleyjd 20100901: [STRIFE] -// * Removed prebeta cruft, face stuff, keyboxes, and oldwe -// -void ST_initData(void) -{ - st_firsttime = true; - plyr = &players[consoleplayer]; - - st_statusbaron = true; - - st_palette = -1; - - STlib_init(); -} - - - -void ST_createWidgets(void) -{ - int i; - - // ready weapon ammo - STlib_initNum(&w_ready, - ST_AMMOX, - ST_AMMOY, - invfontg, - &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], - ST_AMMOWIDTH); - - // the last weapon type - w_ready.data = plyr->readyweapon; - - // health percentage - STlib_initNum(&w_health, - ST_HEALTHX, - ST_HEALTHY, - invfontg, - &plyr->health, - ST_HEALTHWIDTH); - - // haleyjd 20100831: [STRIFE] - // * No face. - // 20100901: - // * No arms, weaponsowned, frags, armor, keyboxes - - // haleyjd 20110213: Ammo Widgets!!! - for(i = 0; i < NUMAMMO; i++) - { - STlib_initNum(&w_ammo[i], ST_POPUPAMMOX, st_yforammo[i], - invfonty, &plyr->ammo[i], st_wforammo[i]); - - STlib_initNum(&w_maxammo[i], ST_POPUPMAXAMMOX, st_yforammo[i], - invfonty, &plyr->maxammo[i], st_wforammo[i]); - } -} - -static boolean st_stopped = true; - - -void ST_Start (void) -{ - if (!st_stopped) - ST_Stop(); - - ST_initData(); - ST_createWidgets(); - st_stopped = false; -} - -void ST_Stop (void) -{ - if (st_stopped) - return; - - I_SetPalette (W_CacheLumpNum (lu_palette, PU_CACHE)); - - st_stopped = true; -} - -void ST_Init (void) -{ - ST_loadData(); - - // haleyjd 20100919: This is not used by Strife. More memory for voices! - //st_backing_screen = (byte *) Z_Malloc(ST_WIDTH * ST_HEIGHT, PU_STATIC, 0); -} - diff --git a/games/NXDoom/src/strife/st_stuff.h b/games/NXDoom/src/strife/st_stuff.h deleted file mode 100644 index 167888ed743..00000000000 --- a/games/NXDoom/src/strife/st_stuff.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Status bar code. -// Does the face/direction indicator animatin. -// Does palette indicators as well (red pain/berserk, bright pickup) -// - -#ifndef __STSTUFF_H__ -#define __STSTUFF_H__ - -#include "doomtype.h" -#include "d_event.h" -#include "m_cheat.h" - -// Size of statusbar. -// Now sensitive for scaling. -#define ST_HEIGHT 32 -#define ST_WIDTH SCREENWIDTH -#define ST_Y (SCREENHEIGHT - ST_HEIGHT) - - -// -// STATUS BAR -// - -// Called by main loop. -boolean ST_Responder (event_t* ev); - -// Called by main loop. -void ST_Ticker (void); - -// Called by main loop. -void ST_Drawer (boolean fullscreen, boolean refresh); - -// haleyjd 09/01/10: [STRIFE] New function. -// Called by main loop to draw external status bar bits. -// Returns true if a popup is drawing. -boolean ST_DrawExternal(void); - -// Called when the console player is spawned on each level. -void ST_Start (void); - -// Called by startup code. -void ST_Init (void); - - - -extern byte *st_backing_screen; - -extern cheatseq_t cheat_mus; // [STRIFE]: idmus -> spin -extern cheatseq_t cheat_god; // [STRIFE]: iddqd -> omnipotent -extern cheatseq_t cheat_ammo; // [STRIFE]: idfa -> boomstix -extern cheatseq_t cheat_noclip; // [STRIFE]: idclip -> elvis -extern cheatseq_t cheat_clev; // [STRIFE]: idclev -> rift -extern cheatseq_t cheat_mypos; // [STRIFE]: idmypos -> gps -extern cheatseq_t cheat_scoot; // [STRIFE]: new cheat scoot -extern cheatseq_t cheat_nuke; // [STRIFE]: new cheat stonecold -extern cheatseq_t cheat_keys; // [STRIFE]: new cheat jimmy (all keys) -extern cheatseq_t cheat_stealth; // [STRIFE]: new cheat gripper -extern cheatseq_t cheat_midas; // [STRIFE]: new cheat -extern cheatseq_t cheat_lego; // [STRIFE]: new cheat -extern cheatseq_t cheat_dev; // [STRIFE]: new cheat - -extern cheatseq_t cheat_powerup[]; - - -#endif diff --git a/games/NXDoom/src/strife/strife_icon.c b/games/NXDoom/src/strife/strife_icon.c deleted file mode 100644 index 93c43f9ad2f..00000000000 --- a/games/NXDoom/src/strife/strife_icon.c +++ /dev/null @@ -1,2736 +0,0 @@ -static int strife_icon_w = 128; -static int strife_icon_h = 128; - -static const unsigned int strife_icon_data[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0001, - 0xe580463a, 0xe17e476f, 0xdf7e456f, 0xdc7d486e, 0xde7d476c, 0xdd7d466a, - 0xdd794469, 0xdc794367, 0xda7b4466, 0xdb784264, 0xd8764063, 0xda763f61, - 0xd7723d60, 0xd9753e5e, 0xd874405c, 0xd8733e5b, 0xd7703c59, 0xd46e3a58, - 0xd5713b56, 0xd26c3955, 0xd46c3753, 0xd06a3552, 0xcf663350, 0xd169344e, - 0xd167324d, 0xcf63334b, 0xcb60304a, 0xca602e48, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, 0xc75a2944, - 0xc75a2944, 0xc75a2944, 0xc8592945, 0xbc552748, 0xb951284c, 0xaf4d2350, - 0xa94a2253, 0xa4492057, 0x9e452059, 0x993e222d, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xd8804e1a, 0xeb9054e5, 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, - 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, - 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, - 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, - 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, - 0xca5c2dff, 0xc8592bff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, - 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, - 0x873a1ad0, 0x99402614, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xe88d53d2, 0xf39d5fff, 0xf29b5dff, 0xf1995cff, - 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, 0xea8d53ff, 0xe88b51ff, - 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, 0xe08049ff, 0xe07e47ff, - 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, 0xd8733fff, 0xd7713dff, - 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, 0xd06634ff, 0xcf6433ff, - 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xc95b2cff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, 0xa14621ff, 0x99421eff, - 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x86391abc, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xf19a5cfc, 0xf39d5fff, - 0xf29b5dff, 0xf1995cff, 0xee965aff, 0xed9458ff, 0xec9256ff, 0xea9055ff, - 0xea8d53ff, 0xe88b51ff, 0xe78950ff, 0xe5874eff, 0xe3844cff, 0xe2824aff, - 0xe08049ff, 0xe07e47ff, 0xde7b45ff, 0xdd7a44ff, 0xdc7842ff, 0xda7640ff, - 0xd8733fff, 0xd7713dff, 0xd66f3bff, 0xd46d39ff, 0xd36a38ff, 0xd26836ff, - 0xd06634ff, 0xcf6433ff, 0xcd6131ff, 0xcc5f2fff, 0xca5d2eff, 0xca5b2cff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0xc8592aff, 0xc65929ff, 0xbc5427ff, 0xb45025ff, 0xab4b23ff, - 0xa14621ff, 0x99421eff, 0x903e1dff, 0x873a1aff, 0x7d3618ff, 0x793317f3, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xf39e61ff, 0xa9643aff, 0x602d16ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x53210eff, - 0x672b12ff, 0x743015fd, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xac683dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x622911fe, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x663219ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50210eff, 0x4c1e0cff, 0x4c1e0cff, 0x884322ff, 0xe78c53ff, 0xe1854dff, - 0xb5542aff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xaf5027ff, 0x843b1bff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x6b3118ff, 0xe2874fff, 0xe58a51ff, 0xbc5b2fff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0x94421fff, 0x4d1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x532210ff, - 0xd97f48ff, 0xe98e54ff, 0xc56535ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa04822ff, - 0x55230eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0xc8713fff, 0xe99056ff, - 0xce6e3cff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xb15127ff, - 0xb15127ff, 0xb15127ff, 0xb15127ff, 0xa74c24ff, 0x602812ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4d1e0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f200eff, 0x4c1e0cff, 0x4c1e0cff, 0xe48950ff, - 0xf5a062ff, 0xf5a062ff, 0xdc7843ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5e2eff, - 0x5a2610ff, 0x4c1e0cff, 0x4c1e0cff, 0xcf7543ff, 0xf5a062ff, 0xf5a062ff, - 0xe4854dff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x733216ff, 0x4c1e0cff, - 0x4c1e0cff, 0xad5d32ff, 0xf5a062ff, 0xf5a062ff, 0xeb9156ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x8b3d1dff, 0x4c1e0cff, 0x4c1e0cff, 0x793a1dff, - 0xf5a062ff, 0xf5a062ff, 0xf39d60ff, 0xcc5f2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xa34a23ff, 0x4c1e0cff, 0x4c1e0cff, 0x4e1e0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xdc7f48ff, 0xf5a062ff, 0xf5a062ff, 0xd56f3bff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xc2592cff, 0x52210dff, 0x4c1e0cff, 0x4c1e0cff, 0xc2693aff, - 0xf5a062ff, 0xf5a062ff, 0xde7c45ff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xca5d2dff, - 0x632a12ff, 0x4c1e0cff, 0x4c1e0cff, 0x9e4e28ff, 0xf49f62ff, 0xf5a062ff, - 0xe6884fff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0x793418ff, 0x4c1e0cff, - 0x4c1e0cff, 0x6f3217ff, 0xf29b5eff, 0xf5a062ff, 0xee9459ff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, 0xcb5e2eff, - 0xcb5e2eff, 0xcb5e2eff, 0x91411fff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xab4d24ff, 0xd8723eff, 0xd46c38ff, - 0xa34922ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7e3719ff, 0x5c2610ff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xd56e3aff, 0xd7703cff, 0xb05025ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x652a13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xd26836ff, 0xd8743fff, 0xc0582bff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x6f3016ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xce6331ff, 0xda7541ff, - 0xcc612fff, 0x823a1aff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, - 0x7f3819ff, 0x7f3819ff, 0x7f3819ff, 0x773317ff, 0x4e1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, - 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, - 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, 0xc8592aff, 0xc8592aff, - 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, 0x9e4520ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7c3417ff, - 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, 0xc8592aff, 0xc8592aff, - 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0xaa4b23ff, - 0xc8592aff, 0xc8592aff, 0x883b1aff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x93401dff, 0xc8592aff, 0xc8592aff, - 0x9e4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x7c3417ff, 0xc8592aff, 0xc8592aff, 0xb65026ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x632912ff, - 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51210dff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0xa94a23ff, 0xc8592aff, 0xc8592aff, 0x863a1aff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x923f1dff, - 0xc8592aff, 0xc8592aff, 0x9f4520ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x7a3517ff, 0xc8592aff, 0xc8592aff, - 0xb55026ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x632812ff, 0xc8592aff, 0xc8592aff, 0xc8592aff, 0x51200eff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x8d3d1cff, 0xc8592aff, 0xc7582aff, - 0x6a2c13ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x763216ff, 0xc8592aff, 0xc8592aff, 0x813719ff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, - 0xc55829ff, 0xc8592aff, 0x98431fff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x52210dff, 0xbd5427ff, 0xc8592aff, - 0xb04e24ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4d1f0cff, - 0x712f14ff, 0x632912ff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x682b13ff, 0x6d2d14ff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x602811ff, 0x723115ff, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x58240fff, 0x753116ff, 0x54220eff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4f1f0dff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4f1f0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4f1f0dff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, 0x4c1e0cff, - 0x4c1e0cff, 0x4f1f0dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x93756aff, 0x91766aff, 0xa89078ff, 0xb6a07fff, - 0xb6a07fff, 0xb6a07fff, 0xb6a07fff, 0xb6a07fff, 0xb6a07fff, 0xbca88bff, - 0xc7baa6ff, 0xc6b9a5ff, 0xc6b9a5ff, 0xc5b7a4ff, 0xc5b7a4ff, 0xc4b6a2ff, - 0xc3b5a0ff, 0xc3b5a0ff, 0xc2b49fff, 0xbba78bff, 0xb69e7bff, 0xb69d7bff, - 0xb69d7bff, 0xb69d7aff, 0xb59b79ff, 0xb39976ff, 0xb19774ff, 0xaf9572ff, - 0xae9573ff, 0xb3a188ff, 0xb3a38eff, 0xb1a18cff, 0xb0a08aff, 0xae9e88ff, - 0xac9c85ff, 0xab9a84ff, 0xa99883ff, 0xa79580ff, 0xa49179ff, 0x9a7d58ff, - 0x987b56ff, 0x977a55ff, 0x957852ff, 0x937550ff, 0x91734eff, 0x90724dff, - 0x8e704aff, 0x8c6e48ff, 0x8f7556ff, 0x93816aff, 0x917e68ff, 0x907d66ff, - 0x8e7a64ff, 0x8c7963ff, 0x8b7861ff, 0x89755fff, 0x86735cff, 0x86735cff, - 0x7c603eff, 0x775631ff, 0x755430ff, 0x785835ff, 0x7a5b3bff, 0x7d5c41ff, - 0x7f5f46ff, 0x74564aff, 0x5f464bff, 0x674e55ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xf9f9f9ff, 0xedededff, 0xf3f3f3ff, 0xdfdfdfff, 0xdededeff, 0xdcdcdcff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf7f7f7ff, - 0xf2f2f2ff, 0xedededff, 0xcfcfcfff, 0xdcdcdcff, 0xc6c6c6ff, 0xbfbfbfff, - 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa0a0a0ff, 0x9b9b9bff, 0x979797ff, 0x989898ff, 0x9a9a9aff, 0x969696ff, - 0xa0a0a0ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x777ea1ff, 0x7d85adff, 0x858791ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xf9f9f9ff, 0xe5e5e5ff, 0xebebebff, 0xffffffff, 0xf2f2f2ff, - 0xdededeff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfcfcfcff, 0xf7f7f7ff, 0xf1f1f1ff, 0xd2d2d2ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xdcdcdcff, 0xc3c3c3ff, 0xbdbdbdff, 0xbcbcbcff, 0xbababaff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0x9b9b9bff, 0x9c9c9cff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x939393ff, 0x9f9f9fff, 0x9d9d9dff, 0x9b9b9bff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, 0x717693ff, 0x797fa0ff, - 0x84868fff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfafafaff, 0xe7e7e7ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xf2f2f2ff, 0xdcdcdcff, 0xdbdbdbff, 0xd9d9d9ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfcfcfcff, 0xf6f6f6ff, 0xd4d4d4ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xd9d9d9ff, 0xc0c0c0ff, 0xbcbcbcff, - 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, 0xa0a0a0ff, 0xa0a0a0ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x909090ff, - 0x9d9d9dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, 0x646775ff, 0x6a6e84ff, - 0x737893ff, 0x84868dff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfafafaff, 0xe8e8e8ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf1f1f1ff, - 0xdbdbdbff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xd7d7d7ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd4d4d4ff, 0xbfbfbfff, 0xbababaff, 0xb9b9b9ff, 0xb7b7b7ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xa9a9a9ff, 0xa5a5a5ff, - 0xa3a3a3ff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x8d8d8dff, 0x9b9b9bff, 0x9a9a9aff, 0x989898ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x5e5f66ff, - 0x646775ff, 0x6c7085ff, 0x85868cff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, 0xeaeaeaff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xf1f1f1ff, 0xd9d9d9ff, 0xd7d7d7ff, 0xd6d6d6ff, - 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfefefeff, - 0xd9d9d9ff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd0d0d0ff, 0xbdbdbdff, 0xb9b9b9ff, - 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, - 0xa9a9a9ff, 0xa7a7a7ff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x8a8a8aff, - 0x9a9a9aff, 0x989898ff, 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, - 0x575758ff, 0x5e5f66ff, 0x676a77ff, 0x85858aff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfbfbfbff, - 0xecececff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf0f0f0ff, - 0xd7d7d7ff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, 0xffffffff, 0xffffffff, - 0xfefefeff, 0xdbdbdbff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcbcbcbff, 0xbbbbbbff, 0xb7b7b7ff, 0xb5b5b5ff, 0xb5b5b5ff, 0xb7b7b7ff, - 0xb2b2b2ff, 0xaeaeaeff, 0xaaaaaaff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x878787ff, 0x989898ff, 0x979797ff, 0x959595ff, - 0x6f6f6fff, 0x5b5b5bff, 0x575758ff, 0x616269ff, 0x848588ff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, - 0xfbfbfbff, 0xedededff, 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, - 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xefefefff, 0xd6d6d6ff, 0xd4d4d4ff, 0xecececff, - 0xffffffff, 0xfefefeff, 0xddddddff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, - 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, - 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc7c7c7ff, 0xb9b9b9ff, 0xb5b5b5ff, - 0xb5b5b5ff, 0xb7b7b7ff, 0xb2b2b2ff, 0xaeaeaeff, 0xadadadff, 0xacacacff, - 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, - 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x848484ff, - 0x979797ff, 0x959595ff, 0x6f6f6fff, 0x5b5b5bff, 0x5b5b5bff, 0x858587ff, - 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffffffff, 0xfcfcfcff, 0xefefefff, 0xecececff, 0xebebebff, 0xe9e9e9ff, - 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefefefff, - 0xd4d4d4ff, 0xecececff, 0xfefefeff, 0xddddddff, 0xcececeff, 0xccccccff, - 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, 0xc4c4c4ff, 0xe0e0e0ff, - 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, 0xcececeff, 0xc9c9c9ff, - 0xc3c3c3ff, 0xb6b6b6ff, 0xb5b5b5ff, 0xb7b7b7ff, 0xb1b1b1ff, 0xafafafff, - 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, 0xa7a7a7ff, 0xa5a5a5ff, - 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, 0x7b7b7bff, 0x777777ff, - 0x727272ff, 0x6e6e6eff, 0x818181ff, 0x959595ff, 0x6f6f6fff, 0x5e5e5eff, - 0x858585ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, 0x8a8a8aff, 0x888888ff, - 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcfcfcff, 0xf1f1f1ff, 0xeeeeeeff, 0xecececff, - 0xebebebff, 0xe9e9e9ff, 0xe7e7e7ff, 0xe6e6e6ff, 0xe4e4e4ff, 0xebebebff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xeeeeeeff, 0xebebebff, 0xdfdfdfff, 0xcfcfcfff, - 0xcececeff, 0xccccccff, 0xcacacaff, 0xc9c9c9ff, 0xc7c7c7ff, 0xc6c6c6ff, - 0xc4c4c4ff, 0xe0e0e0ff, 0xe0e0e0ff, 0xdcdcdcff, 0xd7d7d7ff, 0xd2d2d2ff, - 0xcececeff, 0xc9c9c9ff, 0xc5c5c5ff, 0xbfbfbfff, 0xb6b6b6ff, 0xb5b5b5ff, - 0xb0b0b0ff, 0xafafafff, 0xadadadff, 0xacacacff, 0xaaaaaaff, 0xa8a8a8ff, - 0xa7a7a7ff, 0xa5a5a5ff, 0x9a9a9aff, 0x898989ff, 0x858585ff, 0x808080ff, - 0x7b7b7bff, 0x777777ff, 0x727272ff, 0x6e6e6eff, 0x696969ff, 0x7e7e7eff, - 0x717171ff, 0x878787ff, 0x909090ff, 0x8f8f8fff, 0x8d8d8dff, 0x8b8b8bff, - 0x8a8a8aff, 0x888888ff, 0x868686ff, 0x858585ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfaf2b8ff, 0xfaf3bcff, - 0xf9f2baff, 0xf9f2baff, 0xf8f0b7ff, 0xf8efb7ff, 0xf7eeb5ff, 0xf7edb4ff, - 0xf6ecb3ff, 0xf8ecaaff, 0xffee97ff, 0xffee96ff, 0xffed95ff, 0xffec94ff, - 0xffec93ff, 0xffeb92ff, 0xffea90ff, 0xffe98fff, 0xffe88eff, 0xf7e49aff, - 0xf0e0a3ff, 0xefdea1ff, 0xefdea1ff, 0xeedd9fff, 0xecda9cff, 0xebd89aff, - 0xe9d698ff, 0xe8d596ff, 0xe6d293ff, 0xf3d67cff, 0xf5d676ff, 0xf3d373ff, - 0xf2d171ff, 0xf0cf6eff, 0xefcc6cff, 0xedca68ff, 0xecc867ff, 0xeac563ff, - 0xe5c367ff, 0xd7bd79ff, 0xd4ba78ff, 0xd2b876ff, 0xd1b674ff, 0xcfb472ff, - 0xceb271ff, 0xccb16fff, 0xcbaf6eff, 0xc9ad6cff, 0xcfac5eff, 0xd8ad4cff, - 0xd6aa4aff, 0xd5a848ff, 0xd3a646ff, 0xd2a545ff, 0xd0a243ff, 0xcfa042ff, - 0xcd9e40ff, 0xcc9d3eff, 0xbd9851ff, 0xb69658ff, 0xb59455ff, 0xb69659ff, - 0xb6965bff, 0xb7965dff, 0xb99761ff, 0xb99863ff, 0xba9966ff, 0xb99967ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcec71ff, 0xffef71ff, 0xffee70ff, 0xffed6eff, 0xffec6cff, 0xffeb6aff, - 0xffe969ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, - 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, - 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, - 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, - 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, - 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, - 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, - 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, - 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, - 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, - 0xffb027ff, 0xfcae26ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfceb6fff, 0xffee70ff, 0xffed6eff, 0xffec6cff, - 0xffeb6aff, 0xffe969ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, - 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, - 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, - 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, - 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, - 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, - 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, - 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, - 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, - 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xfcad25ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcea6eff, 0xffed6eff, - 0xffec6cff, 0xffeb6aff, 0xffe969ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, - 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, - 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, - 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, - 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, - 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, - 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, - 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, - 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, - 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xfcac25ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfce96cff, 0xffec6cff, 0xffeb6aff, 0xffe969ff, 0xffe867ff, 0xffe765ff, - 0xffe663ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, - 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, - 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, - 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, - 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, - 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, - 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, - 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, - 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, - 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, - 0xffae26ff, 0xfcab25ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfce86aff, 0xffeb6aff, 0xffe969ff, 0xffe867ff, - 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, - 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, - 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, - 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, - 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, - 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, - 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, - 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, - 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, - 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xfcab24ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfce768ff, 0xffe969ff, - 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, - 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, - 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, - 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, - 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, - 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, - 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, - 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, - 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, - 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, - 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xfcaa24ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfce567ff, 0xffe867ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, 0xffe460ff, - 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, - 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, - 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, - 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, - 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, - 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, - 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, - 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, - 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, - 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, - 0xffac25ff, 0xfca924ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfce465ff, 0xffe765ff, 0xffe663ff, 0xffe562ff, - 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, - 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, - 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, - 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, - 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, - 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, - 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, - 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, - 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, - 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xfca823ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfce363ff, 0xffe663ff, - 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, - 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, - 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, - 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, - 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, - 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, - 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, - 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, - 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, - 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xfca823ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfce261ff, 0xffe562ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, 0xffe15bff, - 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, - 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, - 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, - 0xffcb3aff, 0xffca38ff, 0xe8bf48ff, 0xbfac62ff, 0x9f9c74ff, 0x90937aff, - 0x828a7fff, 0x7f877dff, 0x7e847aff, 0x7c8277ff, 0x7b7f74ff, 0x7a7d70ff, - 0x797a6dff, 0x77776aff, 0x767567ff, 0x757264ff, 0x737060ff, 0x726d5eff, - 0x706a5aff, 0x6f6757ff, 0x6d6454ff, 0x6c6250ff, 0x6c5f4eff, 0x796647ff, - 0xaf8539ff, 0xfcb42aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, - 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, - 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, - 0xffaa24ff, 0xfca723ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfce260ff, 0xffe460ff, 0xffe35eff, 0xffe25dff, - 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, - 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, - 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, - 0xffcd3cff, 0xffcb3aff, 0xdbbb52ff, 0x959c82ff, 0x7c8e91ff, 0x7a8b8dff, - 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, - 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, - 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, - 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x987336ff, 0xfeb429ff, 0xffb429ff, - 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xfca622ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfce15eff, 0xffe35eff, - 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, - 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, - 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, - 0xffce3dff, 0xffcd3cff, 0xf7c740ff, 0xa6a47aff, 0x7d9194ff, 0x7c8e91ff, - 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, - 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, - 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, - 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x5b4c3eff, - 0xe6a027ff, 0xfeb228ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, - 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, - 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xfca522ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfce05cff, 0xffe25dff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, 0xffdd56ff, - 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, - 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, - 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xedc348ff, 0x939c88ff, 0x7d9194ff, - 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, - 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, - 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, - 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, - 0x594b3fff, 0x58483bff, 0xca8c27ff, 0xeda425ff, 0xfeb128ff, 0xffb127ff, - 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, - 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, - 0xffa723ff, 0xfca522ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcdf5bff, 0xffe15bff, 0xffdf59ff, 0xffde57ff, - 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, - 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, - 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xf6c742ff, 0x919b8aff, - 0x7d9194ff, 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, - 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, - 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, - 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, - 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0xc88b27ff, 0xe49b24ff, - 0xeca124ff, 0xfeaf27ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, - 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, - 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xfca421ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcde59ff, 0xffdf59ff, - 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, - 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, - 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xfecb3bff, - 0x9fa180ff, 0x7d9194ff, 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, - 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, - 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, - 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, - 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, - 0xc88926ff, 0xe49b23ff, 0xe49a23ff, 0xeca024ff, 0xfeae26ff, 0xffae26ff, - 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, - 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xfca321ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcdc57ff, 0xffde57ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, 0xffda50ff, - 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, - 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, - 0xffcb3aff, 0xcdb55dff, 0x7d9194ff, 0x7c8e91ff, 0x7a8b8dff, 0x79888aff, - 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, - 0x6f7572ff, 0x6d726eff, 0x797563ff, 0x9c834eff, 0xa28648ff, 0xa18446ff, - 0xa08244ff, 0x746954ff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, - 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, - 0x554335ff, 0x544031ff, 0xca8b25ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, - 0xed9f23ff, 0xfeac26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, - 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, - 0xffa522ff, 0xfca221ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcdb55ff, 0xffdd56ff, 0xffdc54ff, 0xffdb52ff, - 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, - 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, - 0xffcd3cff, 0xffcb3aff, 0xfac83bff, 0x8b978aff, 0x7c8e91ff, 0x7a8b8dff, - 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, - 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x998452ff, 0xe2a529ff, 0xe4a528ff, - 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, 0x826e4bff, 0x625c53ff, 0x615950ff, - 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, - 0x574538ff, 0x554335ff, 0x544031ff, 0x58412eff, 0xdd9623ff, 0xe49a23ff, - 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xed9f22ff, 0xfeab25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, - 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xfca120ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcda54ff, 0xffdc54ff, - 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, 0xffd54aff, - 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, - 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xd2b657ff, 0x7c8e91ff, - 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, - 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x727268ff, 0xdda42bff, - 0xe4a528ff, 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, 0xe4a227ff, 0x816d48ff, - 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, - 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x9f6e26ff, - 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, - 0xee9e23ff, 0xfea924ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, - 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xfca120ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcd952ff, 0xffdb52ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, 0xffd74bff, - 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, - 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, - 0xa9a271ff, 0x7a8b8dff, 0x79888aff, 0x778586ff, 0x768383ff, 0x75807fff, - 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, - 0x83785cff, 0xe4a528ff, 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, 0xe4a227ff, - 0xe4a127ff, 0x806a46ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, - 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x674a2cff, - 0xb27a25ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xe79922ff, - 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xef9e22ff, 0xfea824ff, 0xffa823ff, - 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, - 0xffa321ff, 0xfca020ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcd850ff, 0xffda50ff, 0xffd94fff, 0xffd84dff, - 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, - 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, - 0xffc937ff, 0xffc835ff, 0x849086ff, 0x79888aff, 0x778586ff, 0x768383ff, - 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, - 0x6c6f6bff, 0x6b6c68ff, 0x736f5fff, 0xe4a427ff, 0xe4a427ff, 0xe4a327ff, - 0xe4a227ff, 0xe4a127ff, 0xe4a127ff, 0x92733eff, 0x5e5349ff, 0x5c5146ff, - 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x694d2fff, - 0xae7827ff, 0xe19923ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, - 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, - 0xf09d21ff, 0xfea623ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, - 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xfc9f1fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcd74eff, 0xffd94fff, - 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, 0xffd244ff, - 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, - 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xf9c437ff, 0x79888aff, 0x778586ff, - 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, 0x6f7572ff, - 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0xbc8f38ff, - 0xe4a327ff, 0xe4a227ff, 0xe4a127ff, 0xe4a127ff, 0xe4a126ff, 0xca912dff, - 0x5e5246ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x674f33ff, - 0xab772aff, 0xe19a23ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe69923ff, - 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, - 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xef9c21ff, 0xfea522ff, 0xffa522ff, - 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xfc9e1fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcd64dff, 0xffd84dff, 0xffd74bff, 0xffd54aff, 0xffd448ff, 0xffd346ff, - 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, - 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xecbd3dff, - 0x778586ff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, 0x707875ff, - 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, - 0x66645dff, 0x716755ff, 0xd3992eff, 0xe4a127ff, 0xe4a127ff, 0xe4a126ff, - 0xe4a026ff, 0xe49f26ff, 0xbf8a2dff, 0x765c3aff, 0x5e4b3aff, 0x735634ff, - 0xaf7b2bff, 0xe19a24ff, 0xe49b23ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, - 0xe69923ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, - 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, - 0xf09920ff, 0xfea322ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, - 0xffa020ff, 0xfc9e1fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcd54bff, 0xffd74bff, 0xffd54aff, 0xffd448ff, - 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, - 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, - 0xffc631ff, 0xebbc3dff, 0x768383ff, 0x75807fff, 0x737d7cff, 0x727a79ff, - 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, - 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x73644eff, 0xce942eff, - 0xe4a126ff, 0xe4a026ff, 0xe49f26ff, 0xe49f25ff, 0xe49e25ff, 0xe49d25ff, - 0xe49c24ff, 0xe49c24ff, 0xe49b24ff, 0xe49b23ff, 0xe49a23ff, 0xe49a23ff, - 0xe59a22ff, 0xe69923ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, - 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, - 0xea961fff, 0xeb951fff, 0xeb941fff, 0xf1981fff, 0xfea221ff, 0xffa221ff, - 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xfc9d1eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcd44aff, 0xffd54aff, - 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, - 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, - 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xf6c035ff, 0x75807fff, 0x737d7cff, - 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, - 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, - 0x615950ff, 0x675a4aff, 0xb38433ff, 0xe49f26ff, 0xe49f25ff, 0xe49e25ff, - 0xe49d25ff, 0xe49c24ff, 0xe49c24ff, 0xe49b24ff, 0xe49b23ff, 0xe49a23ff, - 0xe49a23ff, 0xe59a22ff, 0xe69923ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, - 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, - 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, - 0xf29820ff, 0xfea020ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xfc9c1eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcd249ff, 0xffd448ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, 0xffd041ff, - 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, - 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xfec32fff, - 0x798079ff, 0x727a79ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, 0x6c6f6bff, - 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, - 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x876839ff, - 0xd89727ff, 0xe49d25ff, 0xe49c24ff, 0xe49c24ff, 0xe49b24ff, 0xe49b23ff, - 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, 0xe79922ff, - 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, - 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, - 0xeb941eff, 0xec941fff, 0xec931eff, 0xf3971fff, 0xfe9f20ff, 0xff9f1fff, - 0xff9e1fff, 0xfc9b1eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcd147ff, 0xffd346ff, 0xffd244ff, 0xffd143ff, - 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, - 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, - 0xffc32fff, 0xffc32fff, 0x9b8f64ff, 0x707875ff, 0x6f7572ff, 0x6d726eff, - 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, 0x65615aff, - 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, - 0x5b4e42ff, 0x594b3fff, 0x655039ff, 0xb8812aff, 0xe49c24ff, 0xe49b24ff, - 0xe49b23ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, 0xe69923ff, - 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, - 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, - 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, - 0xf3961eff, 0xfe9d1fff, 0xff9d1fff, 0xfc9b1dff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcd045ff, 0xffd244ff, - 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, - 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, - 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xc2a24dff, 0x6f7572ff, - 0x6d726eff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, 0x66645dff, - 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, - 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, - 0x88622cff, 0xdb9524ff, 0xe49a23ff, 0xe49a23ff, 0xe59a22ff, 0xe59922ff, - 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, 0xe89820ff, - 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, - 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, - 0xee931eff, 0xed921dff, 0xee921dff, 0xf3951eff, 0xfe9c1eff, 0xfc9a1dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfccf43ff, 0xffd143ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, 0xffcd3cff, - 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, - 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, - 0xf7bb31ff, 0x777869ff, 0x6c6f6bff, 0x6b6c68ff, 0x696a64ff, 0x686761ff, - 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, 0x5f564cff, - 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, - 0x554335ff, 0x544031ff, 0x523d2eff, 0x60442aff, 0xba7e24ff, 0xe59a22ff, - 0xe59922ff, 0xe69923ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, 0xe79721ff, - 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, - 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, - 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, - 0xf4941dff, 0xfb981dff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcce42ff, 0xffd041ff, 0xffcf3fff, 0xffce3dff, - 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, - 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, - 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xba9a4aff, 0x6b6c68ff, 0x696a64ff, - 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, 0x615950ff, - 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, - 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, - 0x4f3624ff, 0x926120ff, 0xe39822ff, 0xe79922ff, 0xe69822ff, 0xe79822ff, - 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, 0xe99720ff, - 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, - 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, - 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf2921bff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfccd40ff, 0xffcf3fff, - 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, 0xffc835ff, - 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, - 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xfdbd2dff, - 0x8f7e56ff, 0x686761ff, 0x66645dff, 0x65615aff, 0x635e57ff, 0x625c53ff, - 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, - 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, - 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x71481cff, 0xdb9022ff, - 0xe79822ff, 0xe79721ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, 0xe99720ff, - 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, - 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, - 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xee8e1bff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfccc3eff, 0xffce3dff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, 0xffc937ff, - 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, - 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, - 0xffbe2dff, 0xffbd2dff, 0xf1b431ff, 0x7f7255ff, 0x65615aff, 0x635e57ff, - 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, 0x5b4e42ff, - 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, - 0x513a2aff, 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, - 0x492c1aff, 0x603d1bff, 0xd48a20ff, 0xe89820ff, 0xe99820ff, 0xe89720ff, - 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, 0xeb941eff, - 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, - 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, - 0xf08f1cff, 0xef8e1bff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfccb3cff, 0xffcd3cff, 0xffcb3aff, 0xffca38ff, - 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, - 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, - 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xf2b330ff, - 0x82704fff, 0x625c53ff, 0x615950ff, 0x5f564cff, 0x5e5349ff, 0x5c5146ff, - 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, 0x544031ff, - 0x523d2eff, 0x513a2aff, 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, - 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x5b391bff, 0xd78d20ff, - 0xe89720ff, 0xe99720ff, 0xe99720ff, 0xea961fff, 0xeb951fff, 0xeb941fff, - 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, - 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, - 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xef8d1aff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcca3bff, 0xffcb3aff, - 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, - 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, - 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, - 0xffbb2cff, 0xffba2bff, 0xfab62dff, 0xa38141ff, 0x60574cff, 0x5e5349ff, - 0x5c5146ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, 0x554335ff, - 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, - 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, - 0x442b1aff, 0x5d3b1bff, 0xdf9020ff, 0xe99720ff, 0xea961fff, 0xeb951fff, - 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, 0xed931eff, - 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, - 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf08c1aff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcc839ff, 0xffca38ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, 0xffc631ff, - 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, - 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, - 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, - 0xdda230ff, 0x816840ff, 0x5b4e42ff, 0x594b3fff, 0x58483bff, 0x574538ff, - 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, 0x4e3524ff, - 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, - 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x734a1cff, 0xe9951fff, - 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, 0xec931eff, - 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, - 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, - 0xf28e1bff, 0xf08d1aff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcc737ff, 0xffc937ff, 0xffc835ff, 0xffc733ff, - 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, - 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, - 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, - 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xfeb529ff, 0xc28e31ff, 0x6a543aff, - 0x574538ff, 0x554335ff, 0x544031ff, 0x523d2eff, 0x513a2aff, 0x4f3827ff, - 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, - 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, - 0x3f291aff, 0xa6691dff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, - 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, - 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, - 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf08c19ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcc636ff, 0xffc835ff, - 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, 0xffc32fff, - 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, - 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, - 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, - 0xffb429ff, 0xfbb128ff, 0xc08a2dff, 0x6d5130ff, 0x523d2eff, 0x513a2aff, - 0x4f3827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, - 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, - 0x40291aff, 0x3f291aff, 0x3e281aff, 0x4b311bff, 0xe08d1eff, 0xeb941eff, - 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, - 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, - 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf18c19ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcc534ff, 0xffc733ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, 0xffc32fff, - 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, - 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, - 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, - 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xfcaf27ff, - 0xbd8428ff, 0x674827ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, - 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, - 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, - 0x8f5b1bff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, - 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, - 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, - 0xf38d1aff, 0xf18b19ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcc432ff, 0xffc631ff, 0xffc530ff, 0xffc430ff, - 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, - 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, - 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, - 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xfcad26ff, 0xb87c24ff, 0x5a391eff, - 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, - 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, - 0x3b271aff, 0x3a271aff, 0x49301bff, 0xe8911eff, 0xed931eff, 0xee931eff, - 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, - 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, - 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf28b19ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcc330ff, 0xffc530ff, - 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, 0xffc02eff, - 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, - 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, - 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, - 0xffad26ff, 0xf3a425ff, 0x8e5c1eff, 0x472c1aff, 0x462c1aff, 0x452b1aff, - 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, - 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0xb6721dff, - 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, - 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, - 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf18a19ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcc22fff, 0xffc430ff, 0xffc32fff, 0xffc32fff, 0xffc22fff, 0xffc12eff, - 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, - 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, - 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, - 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, - 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xae731fff, - 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, - 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, - 0x37261aff, 0x81531bff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, - 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, - 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, - 0xf58c19ff, 0xf28a19ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcc12fff, 0xffc32fff, 0xffc32fff, 0xffc22fff, - 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, - 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, - 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, - 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0x925f1eff, 0x432a1aff, 0x412a1aff, 0x40291aff, - 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, - 0x38261aff, 0x37261aff, 0x35251aff, 0x593b1bff, 0xee921dff, 0xee911dff, - 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, - 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, - 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf28919ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcc02eff, 0xffc32fff, - 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, - 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, - 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, - 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, - 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, - 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xef9e22ff, 0x452c1aff, - 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, - 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x38261aff, - 0xea8f1dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, - 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, - 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf38a19ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcc02eff, 0xffc22fff, 0xffc12eff, 0xffc02eff, 0xffc02eff, 0xffbf2dff, - 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, - 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, - 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, - 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, - 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, - 0xffa723ff, 0x5d3d1bff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, - 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, - 0x33241aff, 0x32241bff, 0xe18a1cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, - 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, - 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, - 0xf58b19ff, 0xf38819ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcbf2eff, 0xffc12eff, 0xffc02eff, 0xffc02eff, - 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, - 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, - 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, - 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, - 0xffa823ff, 0xffa723ff, 0xffa723ff, 0x68441bff, 0x3e281aff, 0x3d281aff, - 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, - 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0xd7841bff, 0xf0911cff, - 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, - 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, - 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf48719ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcbe2dff, 0xffc02eff, - 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, - 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, - 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, - 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, - 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0x5b3b1bff, - 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, - 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, - 0xcf7e1cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, - 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, - 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf48718ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcbd2dff, 0xffc02eff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, 0xffbc2cff, - 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, - 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, - 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, - 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, - 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, - 0xf8a022ff, 0x412a1aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, - 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, - 0x2f231bff, 0x2e221bff, 0xdd841cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, - 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, - 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, - 0xf78818ff, 0xf48718ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcbd2dff, 0xffbf2dff, 0xffbe2dff, 0xffbd2dff, - 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, - 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, - 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, - 0xffa622ff, 0xffa522ff, 0xcb8320ff, 0x3b271aff, 0x3a271aff, 0x39261aff, - 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, - 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2f241bff, 0xed8e1cff, 0xf18f1cff, - 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, - 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, - 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf58717ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcbc2cff, 0xffbe2dff, - 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, - 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, - 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, - 0xfcae27ff, 0xf8aa26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, - 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, - 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0x764c1cff, 0x3a271aff, - 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, - 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x4a321bff, - 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, - 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, - 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf58616ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcbb2cff, 0xffbd2dff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, 0xffba2bff, - 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, - 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, - 0xf4a928ff, 0x8e6327ff, 0x543824ff, 0x4e3320ff, 0x7b501fff, 0xd28d23ff, - 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, - 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xb8761eff, - 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, - 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, - 0x2c211bff, 0x85531cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, - 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, - 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, - 0xf88816ff, 0xf68516ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcba2cff, 0xffbc2cff, 0xffbc2cff, 0xffbb2cff, - 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, - 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0x875e27ff, 0x4e3524ff, 0x4d3220ff, 0x4b2f1dff, - 0x4a2d1aff, 0x492c1aff, 0x744b1dff, 0xd18a22ff, 0xffaa24ff, 0xffa924ff, - 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xfda322ff, - 0xa96c1eff, 0x3e291aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, - 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, - 0x2d221bff, 0x2c211bff, 0x2b211bff, 0xc5761bff, 0xf28e1bff, 0xf28e1bff, - 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, - 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, - 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf78516ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb92bff, 0xffbc2cff, - 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, 0xffb72aff, - 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xf3a827ff, 0x4f3624ff, 0x4d3220ff, - 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, 0x452b1aff, - 0x724a1dff, 0xd08921ff, 0xffa723ff, 0xffa723ff, 0xfba422ff, 0xd88b20ff, - 0xa86d1fff, 0x56381bff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, - 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, - 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x2b211bff, 0x5e3e1bff, 0xf28e1bff, - 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, - 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, - 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xf68515ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcb92bff, 0xffbb2cff, 0xffba2bff, 0xffb92bff, 0xffb92bff, 0xffb82aff, - 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, - 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xe59d25ff, - 0x4d3220ff, 0x4b2f1dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, 0x462c1aff, - 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x55361bff, 0x4b301aff, - 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, - 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, - 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x2b211bff, 0x2b221bff, - 0xcb781bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, - 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, - 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, - 0xfa8715ff, 0xf78415ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcb82bff, 0xffba2bff, 0xffb92bff, 0xffb92bff, - 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, - 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xf8a926ff, 0x4f321dff, 0x4a2d1aff, 0x492c1aff, 0x472c1aff, - 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, 0x40291aff, - 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, - 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, - 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x2b211bff, - 0x29211bff, 0x90591bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, - 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, - 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, - 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xf78315ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb72aff, 0xffb92bff, - 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, 0xffb529ff, - 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, - 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0x7e521eff, 0x492c1aff, - 0x472c1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, 0x412a1aff, - 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, 0x3a271aff, - 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, 0x33241aff, - 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, 0x2c211bff, - 0x2b211bff, 0x29211bff, 0x6e471bff, 0xf18d1bff, 0xf28d1aff, 0xf38d1aff, - 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, - 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, - 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xf88315ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcb62aff, 0xffb92bff, 0xffb82aff, 0xffb72aff, 0xffb62aff, 0xffb629ff, - 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, - 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, - 0xd69023ff, 0x482d1aff, 0x462c1aff, 0x452b1aff, 0x442b1aff, 0x432a1aff, - 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, 0x3b271aff, - 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, 0x34251aff, - 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, 0x2d221bff, - 0x2c211bff, 0x2b211bff, 0x29211bff, 0x81511bff, 0xef8c1bff, 0xf28d1aff, - 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, - 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, - 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, - 0xfa8414ff, 0xf88315ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcb62aff, 0xffb82aff, 0xffb72aff, 0xffb62aff, - 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, - 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xa96f1fff, 0x452b1aff, 0x442b1aff, - 0x432a1aff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, 0x3d281aff, - 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, 0x35251aff, - 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, 0x2e221bff, - 0x2d221bff, 0x2c211bff, 0x2b211bff, 0x3f2d1bff, 0xac671bff, 0xf28e1bff, - 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, - 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, - 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, - 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xf98215ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb529ff, 0xffb72aff, - 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, - 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, - 0xb47620ff, 0x52341bff, 0x412a1aff, 0x40291aff, 0x3f291aff, 0x3e281aff, - 0x3d281aff, 0x3b271aff, 0x3a271aff, 0x39261aff, 0x38261aff, 0x37261aff, - 0x35251aff, 0x34251aff, 0x33241aff, 0x32241bff, 0x31231bff, 0x2f231bff, - 0x2e221bff, 0x2d221bff, 0x2c211bff, 0x4a321bff, 0x935c1bff, 0xeb891bff, - 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, - 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, - 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, - 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xf88114ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcb429ff, 0xffb62aff, 0xffb629ff, 0xffb529ff, 0xffb429ff, 0xffb328ff, - 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, - 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, - 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xec9a22ff, 0xb1731eff, 0x8e5b1cff, - 0x83541cff, 0x83531cff, 0x81521cff, 0x81521cff, 0x80521cff, 0x80521cff, - 0x80521cff, 0x7f511cff, 0x7e501cff, 0x7e501cff, 0x7d501cff, 0x7d4f1bff, - 0x7c4f1bff, 0x7f501cff, 0x8f5a1bff, 0xa4641bff, 0xd37e1cff, 0xf28f1bff, - 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, - 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, - 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, - 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, - 0xfb8314ff, 0xf98014ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcb329ff, 0xffb629ff, 0xffb529ff, 0xffb429ff, - 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, - 0xf49e21ff, 0xeb951fff, 0xeb941fff, 0xeb941eff, 0xeb941eff, 0xec941fff, - 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, 0xee911dff, - 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, - 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, - 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, - 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, - 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, - 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfa8014ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb328ff, 0xffb529ff, - 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, - 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, - 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, - 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xf49c21ff, 0xeb941eff, 0xeb941eff, - 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, 0xee921dff, - 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, - 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, - 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, - 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, - 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, - 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfa7f13ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcb228ff, 0xffb429ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, 0xffb127ff, - 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, - 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, - 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, - 0xf59c20ff, 0xec941fff, 0xec931eff, 0xed931eff, 0xee931eff, 0xed921dff, - 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, 0xf0901cff, - 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, - 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, - 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, - 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, - 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, - 0xfd8113ff, 0xfb7f13ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcb128ff, 0xffb328ff, 0xffb328ff, 0xffb228ff, - 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, - 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, - 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, - 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xf59a1fff, 0xed931eff, 0xee931eff, - 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, 0xf0911cff, - 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, - 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, - 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, - 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, - 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, - 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfb7e13ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcb027ff, 0xffb328ff, - 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, - 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, - 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, - 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, - 0xf69a1fff, 0xed921dff, 0xee921dff, 0xee911dff, 0xef921cff, 0xf0921cff, - 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, - 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, - 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, - 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, - 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, - 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfb7f12ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcb027ff, 0xffb228ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, 0xffaf26ff, - 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, - 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, - 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, - 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xf6971eff, 0xee911dff, 0xef921cff, - 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, 0xf28f1bff, - 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, - 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, - 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, - 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, - 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, - 0xfe8012ff, 0xfb7e12ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcb027ff, 0xffb127ff, 0xffb027ff, 0xffb027ff, - 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, - 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, - 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, - 0xf7971eff, 0xf0921cff, 0xf0911cff, 0xf0901cff, 0xf08f1cff, 0xf18f1cff, - 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, - 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, - 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, - 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, - 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, - 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xfc7e12ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcaf26ff, 0xffb027ff, - 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, - 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, - 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, - 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, - 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xf7951eff, 0xf0901cff, 0xf08f1cff, - 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, 0xf38d1aff, - 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, - 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, - 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, - 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, - 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xfc7d11ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcae26ff, 0xffb027ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, 0xffad25ff, - 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, - 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, - 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, - 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, - 0xf7941dff, 0xf18f1cff, 0xf28f1bff, 0xf28e1bff, 0xf28e1bff, 0xf28d1aff, - 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, - 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, - 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, - 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, - 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, - 0xff7e11ff, 0xfc7d11ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcae26ff, 0xffaf26ff, 0xffae26ff, 0xffad26ff, - 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, - 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, - 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, - 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, - 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xf8931bff, 0xf28e1bff, 0xf28e1bff, - 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, 0xf48b19ff, - 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, - 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, - 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, - 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, - 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xfc7c11ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcad25ff, 0xffae26ff, - 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, - 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, - 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, - 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, - 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, - 0xf8921bff, 0xf28d1aff, 0xf38d1aff, 0xf38c1aff, 0xf48d1aff, 0xf58c19ff, - 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, - 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, - 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, - 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, - 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xfc7b10ff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcac25ff, 0xffad26ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, 0xffaa24ff, - 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, - 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, - 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, - 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, - 0xff971cff, 0xff971cff, 0xff961bff, 0xf9911aff, 0xf38c1aff, 0xf48d1aff, - 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, 0xf78919ff, - 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, - 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, - 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, - 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, - 0xff7c10ff, 0xfc7a10ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfcab25ff, 0xffad25ff, 0xffac25ff, 0xffab25ff, - 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, - 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, - 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, - 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, - 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, - 0xfa901aff, 0xf58c19ff, 0xf48b19ff, 0xf58b1aff, 0xf58b19ff, 0xf68a19ff, - 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, - 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, - 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, - 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, - 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xfc7a10ff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfcab24ff, 0xffac25ff, - 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, - 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, - 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, - 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, - 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, - 0xff941bff, 0xff941bff, 0xff931aff, 0xf98e19ff, 0xf58b1aff, 0xf58b19ff, - 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, 0xf88816ff, - 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, - 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, - 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, - 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xfc790fff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfcaa24ff, 0xffab25ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, 0xffa823ff, - 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, - 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, - 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, - 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, - 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, - 0xfa8e18ff, 0xf68a19ff, 0xf78919ff, 0xf78818ff, 0xf78918ff, 0xf78817ff, - 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, - 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, - 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, - 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, - 0xff7a0fff, 0xfc780fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfca924ff, 0xffaa24ff, 0xffaa24ff, 0xffa924ff, - 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, - 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, - 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, - 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, - 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, - 0xff911aff, 0xff9119ff, 0xff9019ff, 0xfa8c18ff, 0xf78818ff, 0xf78918ff, - 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, 0xf98615ff, - 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, - 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, - 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, - 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xfc770fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xfca823ff, 0xffaa24ff, - 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, 0xffa522ff, - 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, - 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, - 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, - 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, - 0xff921aff, 0xff911aff, 0xff9119ff, 0xff9019ff, 0xff8f19ff, 0xff8e18ff, - 0xfb8c17ff, 0xf78817ff, 0xf88816ff, 0xf98716ff, 0xf98616ff, 0xfa8715ff, - 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, - 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, - 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, - 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xff780fff, 0xfc770eff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xfca823ff, 0xffa924ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, 0xffa622ff, - 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, - 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, - 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, - 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, - 0xff931aff, 0xff921aff, 0xff911aff, 0xff9119ff, 0xff9019ff, 0xff8f19ff, - 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, 0xfc8a17ff, 0xf98716ff, 0xf98616ff, - 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, 0xfc8415ff, - 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, - 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, - 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xff780fff, - 0xff780eff, 0xfc760eff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xfca723ff, 0xffa823ff, 0xffa723ff, 0xffa723ff, - 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, 0xffa221ff, - 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, - 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, 0xff991dff, - 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, 0xff941bff, - 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, 0xff9119ff, 0xff9019ff, - 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, 0xff8c17ff, 0xff8b17ff, - 0xfb8817ff, 0xfa8715ff, 0xf98615ff, 0xfa8515ff, 0xfa8414ff, 0xfb8515ff, - 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, - 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, - 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, 0xff790fff, - 0xff780fff, 0xff780eff, 0xff770eff, 0xfc750eff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xec9921ff, 0xffa723ff, - 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, 0xffa321ff, - 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, 0xff9e1fff, - 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, 0xff9a1dff, - 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, 0xff951bff, - 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, 0xff9119ff, - 0xff9019ff, 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, 0xff8c17ff, - 0xff8b17ff, 0xff8a17ff, 0xff8a16ff, 0xfc8716ff, 0xfa8515ff, 0xfa8414ff, - 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, 0xfd8113ff, - 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, 0xff7e11ff, - 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, 0xff7a0fff, - 0xff790fff, 0xff780fff, 0xff780eff, 0xff770eff, 0xff760eff, 0xeb6b0dff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xc9791dea, 0xffa723ff, 0xffa622ff, 0xffa522ff, 0xffa422ff, 0xffa321ff, - 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, 0xff9f1fff, - 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, 0xff9a1dff, - 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, 0xff961bff, - 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, 0xff911aff, - 0xff9119ff, 0xff9019ff, 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, 0xff8d18ff, - 0xff8c17ff, 0xff8b17ff, 0xff8a17ff, 0xff8a16ff, 0xff8916ff, 0xff8816ff, - 0xfc8515ff, 0xfb8515ff, 0xfc8415ff, 0xfb8314ff, 0xfc8214ff, 0xfc8214ff, - 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, 0xff7f12ff, - 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, 0xff7b10ff, - 0xff7a0fff, 0xff790fff, 0xff780fff, 0xff780eff, 0xff770eff, 0xff760eff, - 0xff750dff, 0xc85b10e9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xb4622622, 0xd3821df7, 0xffa522ff, 0xffa422ff, - 0xffa321ff, 0xffa321ff, 0xffa221ff, 0xffa120ff, 0xffa020ff, 0xffa020ff, - 0xff9f1fff, 0xff9e1fff, 0xff9d1fff, 0xff9d1eff, 0xff9c1eff, 0xff9b1eff, - 0xff9a1dff, 0xff9a1dff, 0xff991dff, 0xff981cff, 0xff971cff, 0xff971cff, - 0xff961bff, 0xff951bff, 0xff941bff, 0xff941bff, 0xff931aff, 0xff921aff, - 0xff911aff, 0xff9119ff, 0xff9019ff, 0xff8f19ff, 0xff8e18ff, 0xff8e18ff, - 0xff8d18ff, 0xff8c17ff, 0xff8b17ff, 0xff8a17ff, 0xff8a16ff, 0xff8916ff, - 0xff8816ff, 0xff8715ff, 0xff8715ff, 0xfd8415ff, 0xfb8314ff, 0xfc8214ff, - 0xfc8214ff, 0xfd8113ff, 0xfe8113ff, 0xfe8013ff, 0xfe8012ff, 0xfe7f12ff, - 0xff7f12ff, 0xff7e11ff, 0xff7e11ff, 0xff7d11ff, 0xff7c10ff, 0xff7b10ff, - 0xff7b10ff, 0xff7a0fff, 0xff790fff, 0xff780fff, 0xff780eff, 0xff770eff, - 0xff760eff, 0xff750dff, 0xd25f10f6, 0xaf502020, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xb4631b4b, 0xba671d97, 0xb7661c9b, 0xb7661c9b, 0xb7661c9b, 0xb7661c9b, - 0xb7661c9b, 0xb7641a9b, 0xb7641a9b, 0xb7641a9b, 0xb7641a9b, 0xb7641a9b, - 0xb7631a9b, 0xb7631a9b, 0xb7631a9b, 0xb7631a9b, 0xb763199b, 0xb761199b, - 0xb761199b, 0xb761199b, 0xb761199b, 0xb75f199b, 0xb75f199b, 0xb75f199b, - 0xb75f199b, 0xb75f199b, 0xb75f199b, 0xb75e199b, 0xb75e199b, 0xb75e179b, - 0xb75e179b, 0xb75e179b, 0xb75c179b, 0xb75c179b, 0xb75c179b, 0xb75c179b, - 0xb75c179b, 0xb75a179b, 0xb75a179b, 0xb75a179b, 0xb75a179b, 0xb759159b, - 0xb759159b, 0xb759159b, 0xb759159b, 0xb759159b, 0xb757159b, 0xb757159b, - 0xb757159b, 0xb757159b, 0xb757159b, 0xb757159b, 0xb756159b, 0xb756149b, - 0xb756149b, 0xb756149b, 0xb756149b, 0xb754149b, 0xb754149b, 0xb754149b, - 0xb754149b, 0xb752149b, 0xba531397, 0xb452114b, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; diff --git a/games/NXDoom/src/strife/wi_stuff.c b/games/NXDoom/src/strife/wi_stuff.c deleted file mode 100644 index f8193b19bb1..00000000000 --- a/games/NXDoom/src/strife/wi_stuff.c +++ /dev/null @@ -1,1836 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Intermission screens. -// - -// haleyjd 08/23/2010: There is no intermission in Strife -#if 0 -#include - -#include "z_zone.h" - -#include "m_random.h" - -#include "deh_main.h" -#include "i_swap.h" -#include "i_system.h" - -#include "w_wad.h" - -#include "g_game.h" - -#include "r_local.h" -#include "s_sound.h" - -#include "doomstat.h" - -// Data. -#include "sounds.h" - -// Needs access to LFB. -#include "v_video.h" - -#include "wi_stuff.h" - -// -// Data needed to add patches to full screen intermission pics. -// Patches are statistics messages, and animations. -// Loads of by-pixel layout and placement, offsets etc. -// - - -// -// Different vetween registered DOOM (1994) and -// Ultimate DOOM - Final edition (retail, 1995?). -// This is supposedly ignored for commercial -// release (aka DOOM II), which had 34 maps -// in one episode. So there. -#define NUMEPISODES 4 -#define NUMMAPS 9 - - -// in tics -//U #define PAUSELEN (TICRATE*2) -//U #define SCORESTEP 100 -//U #define ANIMPERIOD 32 -// pixel distance from "(YOU)" to "PLAYER N" -//U #define STARDIST 10 -//U #define WK 1 - - -// GLOBAL LOCATIONS -#define WI_TITLEY 2 -#define WI_SPACINGY 33 - -// SINGPLE-PLAYER STUFF -#define SP_STATSX 50 -#define SP_STATSY 50 - -#define SP_TIMEX 16 -#define SP_TIMEY (SCREENHEIGHT-32) - - -// NET GAME STUFF -#define NG_STATSY 50 -#define NG_STATSX (32 + SHORT(star->width)/2 + 32*!dofrags) - -#define NG_SPACINGX 64 - - -// DEATHMATCH STUFF -#define DM_MATRIXX 42 -#define DM_MATRIXY 68 - -#define DM_SPACINGX 40 - -#define DM_TOTALSX 269 - -#define DM_KILLERSX 10 -#define DM_KILLERSY 100 -#define DM_VICTIMSX 5 -#define DM_VICTIMSY 50 - - - - -typedef enum -{ - ANIM_ALWAYS, - ANIM_RANDOM, - ANIM_LEVEL - -} animenum_t; - -typedef struct -{ - int x; - int y; - -} point_t; - - -// -// Animation. -// There is another anim_t used in p_spec. -// -typedef struct -{ - animenum_t type; - - // period in tics between animations - int period; - - // number of animation frames - int nanims; - - // location of animation - point_t loc; - - // ALWAYS: n/a, - // RANDOM: period deviation (<256), - // LEVEL: level - int data1; - - // ALWAYS: n/a, - // RANDOM: random base period, - // LEVEL: n/a - int data2; - - // actual graphics for frames of animations - patch_t* p[3]; - - // following must be initialized to zero before use! - - // next value of bcnt (used in conjunction with period) - int nexttic; - - // last drawn animation frame - int lastdrawn; - - // next frame number to animate - int ctr; - - // used by RANDOM and LEVEL when animating - int state; - -} anim_t; - - -static point_t lnodes[NUMEPISODES][NUMMAPS] = -{ - // Episode 0 World Map - { - { 185, 164 }, // location of level 0 (CJ) - { 148, 143 }, // location of level 1 (CJ) - { 69, 122 }, // location of level 2 (CJ) - { 209, 102 }, // location of level 3 (CJ) - { 116, 89 }, // location of level 4 (CJ) - { 166, 55 }, // location of level 5 (CJ) - { 71, 56 }, // location of level 6 (CJ) - { 135, 29 }, // location of level 7 (CJ) - { 71, 24 } // location of level 8 (CJ) - }, - - // Episode 1 World Map should go here - { - { 254, 25 }, // location of level 0 (CJ) - { 97, 50 }, // location of level 1 (CJ) - { 188, 64 }, // location of level 2 (CJ) - { 128, 78 }, // location of level 3 (CJ) - { 214, 92 }, // location of level 4 (CJ) - { 133, 130 }, // location of level 5 (CJ) - { 208, 136 }, // location of level 6 (CJ) - { 148, 140 }, // location of level 7 (CJ) - { 235, 158 } // location of level 8 (CJ) - }, - - // Episode 2 World Map should go here - { - { 156, 168 }, // location of level 0 (CJ) - { 48, 154 }, // location of level 1 (CJ) - { 174, 95 }, // location of level 2 (CJ) - { 265, 75 }, // location of level 3 (CJ) - { 130, 48 }, // location of level 4 (CJ) - { 279, 23 }, // location of level 5 (CJ) - { 198, 48 }, // location of level 6 (CJ) - { 140, 25 }, // location of level 7 (CJ) - { 281, 136 } // location of level 8 (CJ) - } - -}; - - -// -// Animation locations for episode 0 (1). -// Using patches saves a lot of space, -// as they replace 320x200 full screen frames. -// - -#define ANIM(type, period, nanims, x, y, nexttic) \ - { (type), (period), (nanims), { (x), (y) }, (nexttic), \ - 0, { NULL, NULL, NULL }, 0, 0, 0, 0 } - - -static anim_t epsd0animinfo[] = -{ - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 224, 104, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 184, 160, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 112, 136, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 72, 112, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 88, 96, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 48, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 192, 40, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 136, 16, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 80, 16, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 64, 24, 0), -}; - -static anim_t epsd1animinfo[] = -{ - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 1), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 2), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 3), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 4), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 5), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 6), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 7), - ANIM(ANIM_LEVEL, TICRATE/3, 3, 192, 144, 8), - ANIM(ANIM_LEVEL, TICRATE/3, 1, 128, 136, 8), -}; - -static anim_t epsd2animinfo[] = -{ - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 168, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 40, 136, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 160, 96, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 104, 80, 0), - ANIM(ANIM_ALWAYS, TICRATE/3, 3, 120, 32, 0), - ANIM(ANIM_ALWAYS, TICRATE/4, 3, 40, 0, 0), -}; - -static int NUMANIMS[NUMEPISODES] = -{ - arrlen(epsd0animinfo), - arrlen(epsd1animinfo), - arrlen(epsd2animinfo), -}; - -static anim_t *anims[NUMEPISODES] = -{ - epsd0animinfo, - epsd1animinfo, - epsd2animinfo -}; - - -// -// GENERAL DATA -// - -// -// Locally used stuff. -// - -// States for single-player -#define SP_KILLS 0 -#define SP_ITEMS 2 -#define SP_SECRET 4 -#define SP_FRAGS 6 -#define SP_TIME 8 -#define SP_PAR ST_TIME - -#define SP_PAUSE 1 - -// in seconds -#define SHOWNEXTLOCDELAY 4 -//#define SHOWLASTLOCDELAY SHOWNEXTLOCDELAY - - -// used to accelerate or skip a stage -static int acceleratestage; - -// wbs->pnum -static int me; - - // specifies current state -static stateenum_t state; - -// contains information passed into intermission -static wbstartstruct_t* wbs; - -static wbplayerstruct_t* plrs; // wbs->plyr[] - -// used for general timing -static int cnt; - -// used for timing of background animation -static int bcnt; - -// signals to refresh everything for one frame -static int firstrefresh; - -static int cnt_kills[MAXPLAYERS]; -static int cnt_items[MAXPLAYERS]; -static int cnt_secret[MAXPLAYERS]; -static int cnt_time; -static int cnt_par; -static int cnt_pause; - -// # of commercial levels -static int NUMCMAPS; - - -// -// GRAPHICS -// - -// You Are Here graphic -static patch_t* yah[3] = { NULL, NULL, NULL }; - -// splat -static patch_t* splat[2] = { NULL, NULL }; - -// %, : graphics -static patch_t* percent; -static patch_t* colon; - -// 0-9 graphic -static patch_t* num[10]; - -// minus sign -static patch_t* wiminus; - -// "Finished!" graphics -static patch_t* finished; - -// "Entering" graphic -static patch_t* entering; - -// "secret" -static patch_t* sp_secret; - - // "Kills", "Scrt", "Items", "Frags" -static patch_t* kills; -static patch_t* secret; -static patch_t* items; -static patch_t* frags; - -// Time sucks. -static patch_t* timepatch; -static patch_t* par; -static patch_t* sucks; - -// "killers", "victims" -static patch_t* killers; -static patch_t* victims; - -// "Total", your face, your dead face -static patch_t* total; -static patch_t* star; -static patch_t* bstar; - -// "red P[1..MAXPLAYERS]" -static patch_t* p[MAXPLAYERS]; - -// "gray P[1..MAXPLAYERS]" -static patch_t* bp[MAXPLAYERS]; - - // Name graphics of each level (centered) -static patch_t** lnames; - -// Buffer storing the backdrop -static patch_t *background; - -// -// CODE -// - -// slam background -void WI_slamBackground(void) -{ - V_DrawPatch(0, 0, background); -} - -// The ticker is used to detect keys -// because of timing issues in netgames. -boolean WI_Responder(event_t* ev) -{ - return false; -} - - -// Draws " Finished!" -void WI_drawLF(void) -{ - int y = WI_TITLEY; - - if (gamemode != commercial || wbs->last < NUMCMAPS) - { - // draw - V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2, - y, lnames[wbs->last]); - - // draw "Finished!" - y += (5*SHORT(lnames[wbs->last]->height))/4; - - V_DrawPatch((SCREENWIDTH - SHORT(finished->width)) / 2, y, finished); - } - else if (wbs->last == NUMCMAPS) - { - // MAP33 - nothing is displayed! - } - else if (wbs->last > NUMCMAPS) - { - // > MAP33. Doom bombs out here with a Bad V_DrawPatch error. - // I'm pretty sure that doom2.exe is just reading into random - // bits of memory at this point, but let's try to be accurate - // anyway. This deliberately triggers a V_DrawPatch error. - - patch_t tmp = { SCREENWIDTH, SCREENHEIGHT, 1, 1, - { 0, 0, 0, 0, 0, 0, 0, 0 } }; - - V_DrawPatch(0, y, &tmp); - } -} - - - -// Draws "Entering " -void WI_drawEL(void) -{ - int y = WI_TITLEY; - - // draw "Entering" - V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2, - y, - entering); - - // draw level - y += (5*SHORT(lnames[wbs->next]->height))/4; - - V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2, - y, - lnames[wbs->next]); - -} - -void -WI_drawOnLnode -( int n, - patch_t* c[] ) -{ - - int i; - int left; - int top; - int right; - int bottom; - boolean fits = false; - - i = 0; - do - { - left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset); - top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset); - right = left + SHORT(c[i]->width); - bottom = top + SHORT(c[i]->height); - - if (left >= 0 - && right < SCREENWIDTH - && top >= 0 - && bottom < SCREENHEIGHT) - { - fits = true; - } - else - { - i++; - } - } while (!fits && i!=2 && c[i] != NULL); - - if (fits && i<2) - { - V_DrawPatch(lnodes[wbs->epsd][n].x, - lnodes[wbs->epsd][n].y, - c[i]); - } - else - { - // DEBUG - printf("Could not place patch on level %d", n+1); - } -} - - - -void WI_initAnimatedBack(void) -{ - int i; - anim_t* a; - - if (gamemode == commercial) - return; - - if (wbs->epsd > 2) - return; - - for (i=0;iepsd];i++) - { - a = &anims[wbs->epsd][i]; - - // init variables - a->ctr = -1; - - // specify the next time to draw it - if (a->type == ANIM_ALWAYS) - a->nexttic = bcnt + 1 + (M_Random()%a->period); - else if (a->type == ANIM_RANDOM) - a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1); - else if (a->type == ANIM_LEVEL) - a->nexttic = bcnt + 1; - } - -} - -void WI_updateAnimatedBack(void) -{ - int i; - anim_t* a; - - if (gamemode == commercial) - return; - - if (wbs->epsd > 2) - return; - - for (i=0;iepsd];i++) - { - a = &anims[wbs->epsd][i]; - - if (bcnt == a->nexttic) - { - switch (a->type) - { - case ANIM_ALWAYS: - if (++a->ctr >= a->nanims) a->ctr = 0; - a->nexttic = bcnt + a->period; - break; - - case ANIM_RANDOM: - a->ctr++; - if (a->ctr == a->nanims) - { - a->ctr = -1; - a->nexttic = bcnt+a->data2+(M_Random()%a->data1); - } - else a->nexttic = bcnt + a->period; - break; - - case ANIM_LEVEL: - // gawd-awful hack for level anims - if (!(state == StatCount && i == 7) - && wbs->next == a->data1) - { - a->ctr++; - if (a->ctr == a->nanims) a->ctr--; - a->nexttic = bcnt + a->period; - } - break; - } - } - - } - -} - -void WI_drawAnimatedBack(void) -{ - int i; - anim_t* a; - - if (gamemode == commercial) - return; - - if (wbs->epsd > 2) - return; - - for (i=0 ; iepsd] ; i++) - { - a = &anims[wbs->epsd][i]; - - if (a->ctr >= 0) - V_DrawPatch(a->loc.x, a->loc.y, a->p[a->ctr]); - } - -} - -// -// Draws a number. -// If digits > 0, then use that many digits minimum, -// otherwise only use as many as necessary. -// Returns new x position. -// - -int -WI_drawNum -( int x, - int y, - int n, - int digits ) -{ - - int fontwidth = SHORT(num[0]->width); - int neg; - int temp; - - if (digits < 0) - { - if (!n) - { - // make variable-length zeros 1 digit long - digits = 1; - } - else - { - // figure out # of digits in # - digits = 0; - temp = n; - - while (temp) - { - temp /= 10; - digits++; - } - } - } - - neg = n < 0; - if (neg) - n = -n; - - // if non-number, do not draw it - if (n == 1994) - return 0; - - // draw the new number - while (digits--) - { - x -= fontwidth; - V_DrawPatch(x, y, num[ n % 10 ]); - n /= 10; - } - - // draw a minus sign if necessary - if (neg) - V_DrawPatch(x-=8, y, wiminus); - - return x; - -} - -void -WI_drawPercent -( int x, - int y, - int p ) -{ - if (p < 0) - return; - - V_DrawPatch(x, y, percent); - WI_drawNum(x, y, p, -1); -} - - - -// -// Display level completion time and par, -// or "sucks" message if overflow. -// -void -WI_drawTime -( int x, - int y, - int t ) -{ - - int div; - int n; - - if (t<0) - return; - - if (t <= 61*59) - { - div = 1; - - do - { - n = (t / div) % 60; - x = WI_drawNum(x, y, n, 2) - SHORT(colon->width); - div *= 60; - - // draw - if (div==60 || t / div) - V_DrawPatch(x, y, colon); - - } while (t / div); - } - else - { - // "sucks" - V_DrawPatch(x - SHORT(sucks->width), y, sucks); - } -} - - -void WI_End(void) -{ - void WI_unloadData(void); - WI_unloadData(); -} - -void WI_initNoState(void) -{ - state = NoState; - acceleratestage = 0; - cnt = 10; -} - -void WI_updateNoState(void) { - - WI_updateAnimatedBack(); - - if (!--cnt) - { - // Don't call WI_End yet. G_WorldDone doesnt immediately - // change gamestate, so WI_Drawer is still going to get - // run until that happens. If we do that after WI_End - // (which unloads all the graphics), we're in trouble. - //WI_End(); - G_WorldDone(); - } - -} - -static boolean snl_pointeron = false; - - -void WI_initShowNextLoc(void) -{ - state = ShowNextLoc; - acceleratestage = 0; - cnt = SHOWNEXTLOCDELAY * TICRATE; - - WI_initAnimatedBack(); -} - -void WI_updateShowNextLoc(void) -{ - WI_updateAnimatedBack(); - - if (!--cnt || acceleratestage) - WI_initNoState(); - else - snl_pointeron = (cnt & 31) < 20; -} - -void WI_drawShowNextLoc(void) -{ - - int i; - int last; - - WI_slamBackground(); - - // draw animated background - WI_drawAnimatedBack(); - - if ( gamemode != commercial) - { - if (wbs->epsd > 2) - { - WI_drawEL(); - return; - } - - last = (wbs->last == 8) ? wbs->next - 1 : wbs->last; - - // draw a splat on taken cities. - for (i=0 ; i<=last ; i++) - WI_drawOnLnode(i, splat); - - // splat the secret level? - if (wbs->didsecret) - WI_drawOnLnode(8, splat); - - // draw flashing ptr - if (snl_pointeron) - WI_drawOnLnode(wbs->next, yah); - } - - // draws which level you are entering.. - if ( (gamemode != commercial) - || wbs->next != 30) - WI_drawEL(); - -} - -void WI_drawNoState(void) -{ - snl_pointeron = true; - WI_drawShowNextLoc(); -} - -int WI_fragSum(int playernum) -{ - int i; - int frags = 0; - - for (i=0 ; i 99) - dm_frags[i][j] = 99; - - if (dm_frags[i][j] < -99) - dm_frags[i][j] = -99; - - stillticking = true; - } - } - dm_totals[i] = WI_fragSum(i); - - if (dm_totals[i] > 99) - dm_totals[i] = 99; - - if (dm_totals[i] < -99) - dm_totals[i] = -99; - } - - } - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - dm_state++; - } - - } - else if (dm_state == 4) - { - if (acceleratestage) - { - S_StartSound(0, sfx_slop); - - if ( gamemode == commercial) - WI_initNoState(); - else - WI_initShowNextLoc(); - } - } - else if (dm_state & 1) - { - if (!--cnt_pause) - { - dm_state++; - cnt_pause = TICRATE; - } - } -} - - - -void WI_drawDeathmatchStats(void) -{ - - int i; - int j; - int x; - int y; - int w; - - int lh; // line height - - lh = WI_SPACINGY; - - WI_slamBackground(); - - // draw animated background - WI_drawAnimatedBack(); - WI_drawLF(); - - // draw stat titles (top line) - V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2, - DM_MATRIXY-WI_SPACINGY+10, - total); - - V_DrawPatch(DM_KILLERSX, DM_KILLERSY, killers); - V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, victims); - - // draw P? - x = DM_MATRIXX + DM_SPACINGX; - y = DM_MATRIXY; - - for (i=0 ; iwidth)/2, - DM_MATRIXY - WI_SPACINGY, - p[i]); - - V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, - y, - p[i]); - - if (i == me) - { - V_DrawPatch(x-SHORT(p[i]->width)/2, - DM_MATRIXY - WI_SPACINGY, - bstar); - - V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2, - y, - star); - } - } - else - { - // V_DrawPatch(x-SHORT(bp[i]->width)/2, - // DM_MATRIXY - WI_SPACINGY, bp[i]); - // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2, - // y, bp[i]); - } - x += DM_SPACINGX; - y += WI_SPACINGY; - } - - // draw stats - y = DM_MATRIXY+10; - w = SHORT(num[0]->width); - - for (i=0 ; imaxkills; - cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; - cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; - - if (dofrags) - cnt_frags[i] = WI_fragSum(i); - } - S_StartSound(0, sfx_barexp); - ng_state = 10; - } - - if (ng_state == 2) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (plrs[i].skills * 100) / wbs->maxkills) - cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills; - else - stillticking = true; - } - - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - ng_state++; - } - } - else if (ng_state == 4) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (plrs[i].sitems * 100) / wbs->maxitems) - cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems; - else - stillticking = true; - } - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - ng_state++; - } - } - else if (ng_state == 6) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (plrs[i].ssecret * 100) / wbs->maxsecret) - cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret; - else - stillticking = true; - } - - if (!stillticking) - { - S_StartSound(0, sfx_barexp); - ng_state += 1 + 2*!dofrags; - } - } - else if (ng_state == 8) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - stillticking = false; - - for (i=0 ; i= (fsum = WI_fragSum(i))) - cnt_frags[i] = fsum; - else - stillticking = true; - } - - if (!stillticking) - { - S_StartSound(0, sfx_pldeth); - ng_state++; - } - } - else if (ng_state == 10) - { - if (acceleratestage) - { - S_StartSound(0, sfx_sgcock); - if ( gamemode == commercial ) - WI_initNoState(); - else - WI_initShowNextLoc(); - } - } - else if (ng_state & 1) - { - if (!--cnt_pause) - { - ng_state++; - cnt_pause = TICRATE; - } - } -} - - - -void WI_drawNetgameStats(void) -{ - int i; - int x; - int y; - int pwidth = SHORT(percent->width); - - WI_slamBackground(); - - // draw animated background - WI_drawAnimatedBack(); - - WI_drawLF(); - - // draw stat titles (top line) - V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width), - NG_STATSY, kills); - - V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width), - NG_STATSY, items); - - V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width), - NG_STATSY, secret); - - if (dofrags) - V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width), - NG_STATSY, frags); - - // draw stats - y = NG_STATSY + SHORT(kills->height); - - for (i=0 ; iwidth), y, p[i]); - - if (i == me) - V_DrawPatch(x-SHORT(p[i]->width), y, star); - - x += NG_SPACINGX; - WI_drawPercent(x-pwidth, y+10, cnt_kills[i]); x += NG_SPACINGX; - WI_drawPercent(x-pwidth, y+10, cnt_items[i]); x += NG_SPACINGX; - WI_drawPercent(x-pwidth, y+10, cnt_secret[i]); x += NG_SPACINGX; - - if (dofrags) - WI_drawNum(x, y+10, cnt_frags[i], -1); - - y += WI_SPACINGY; - } - -} - -static int sp_state; - -void WI_initStats(void) -{ - state = StatCount; - acceleratestage = 0; - sp_state = 1; - cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1; - cnt_time = cnt_par = -1; - cnt_pause = TICRATE; - - WI_initAnimatedBack(); -} - -void WI_updateStats(void) -{ - - WI_updateAnimatedBack(); - - if (acceleratestage && sp_state != 10) - { - acceleratestage = 0; - cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; - cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; - cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; - cnt_time = plrs[me].stime / TICRATE; - cnt_par = wbs->partime / TICRATE; - S_StartSound(0, sfx_barexp); - sp_state = 10; - } - - if (sp_state == 2) - { - cnt_kills[0] += 2; - - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills) - { - cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills; - S_StartSound(0, sfx_barexp); - sp_state++; - } - } - else if (sp_state == 4) - { - cnt_items[0] += 2; - - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems) - { - cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems; - S_StartSound(0, sfx_barexp); - sp_state++; - } - } - else if (sp_state == 6) - { - cnt_secret[0] += 2; - - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret) - { - cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret; - S_StartSound(0, sfx_barexp); - sp_state++; - } - } - - else if (sp_state == 8) - { - if (!(bcnt&3)) - S_StartSound(0, sfx_pistol); - - cnt_time += 3; - - if (cnt_time >= plrs[me].stime / TICRATE) - cnt_time = plrs[me].stime / TICRATE; - - cnt_par += 3; - - if (cnt_par >= wbs->partime / TICRATE) - { - cnt_par = wbs->partime / TICRATE; - - if (cnt_time >= plrs[me].stime / TICRATE) - { - S_StartSound(0, sfx_barexp); - sp_state++; - } - } - } - else if (sp_state == 10) - { - if (acceleratestage) - { - S_StartSound(0, sfx_sgcock); - - if (gamemode == commercial) - WI_initNoState(); - else - WI_initShowNextLoc(); - } - } - else if (sp_state & 1) - { - if (!--cnt_pause) - { - sp_state++; - cnt_pause = TICRATE; - } - } - -} - -void WI_drawStats(void) -{ - // line height - int lh; - - lh = (3*SHORT(num[0]->height))/2; - - WI_slamBackground(); - - // draw animated background - WI_drawAnimatedBack(); - - WI_drawLF(); - - V_DrawPatch(SP_STATSX, SP_STATSY, kills); - WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]); - - V_DrawPatch(SP_STATSX, SP_STATSY+lh, items); - WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]); - - V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, sp_secret); - WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]); - - V_DrawPatch(SP_TIMEX, SP_TIMEY, timepatch); - WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time); - - if (wbs->epsd < 3) - { - V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, par); - WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par); - } - -} - -void WI_checkForAccelerate(void) -{ - int i; - player_t *player; - - // check for button presses to skip delays - for (i=0, player = players ; icmd.buttons & BT_ATTACK) - { - if (!player->attackdown) - acceleratestage = 1; - player->attackdown = true; - } - else - player->attackdown = false; - if (player->cmd.buttons & BT_USE) - { - if (!player->usedown) - acceleratestage = 1; - player->usedown = true; - } - else - player->usedown = false; - } - } -} - - - -// Updates stuff each tick -void WI_Ticker(void) -{ - // counter for general background animation - bcnt++; - - if (bcnt == 1) - { - // intermission music - if ( gamemode == commercial ) - S_ChangeMusic(mus_dm2int, true); - else - S_ChangeMusic(mus_inter, true); - } - - WI_checkForAccelerate(); - - switch (state) - { - case StatCount: - if (deathmatch) WI_updateDeathmatchStats(); - else if (netgame) WI_updateNetgameStats(); - else WI_updateStats(); - break; - - case ShowNextLoc: - WI_updateShowNextLoc(); - break; - - case NoState: - WI_updateNoState(); - break; - } - -} - -typedef void (*load_callback_t)(char *lumpname, patch_t **variable); - -// Common load/unload function. Iterates over all the graphics -// lumps to be loaded/unloaded into memory. - -static void WI_loadUnloadData(load_callback_t callback) -{ - int i, j; - char name[9]; - anim_t *a; - - if (gamemode == commercial) - { - for (i=0 ; iepsd, i); - callback(name, &lnames[i]); - } - - // you are here - callback(DEH_String("WIURH0"), &yah[0]); - - // you are here (alt.) - callback(DEH_String("WIURH1"), &yah[1]); - - // splat - callback(DEH_String("WISPLAT"), &splat[0]); - - if (wbs->epsd < 3) - { - for (j=0;jepsd];j++) - { - a = &anims[wbs->epsd][j]; - for (i=0;inanims;i++) - { - // MONDO HACK! - if (wbs->epsd != 1 || j != 8) - { - // animations - DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i); - callback(name, &a->p[i]); - } - else - { - // HACK ALERT! - a->p[i] = anims[1][4].p[i]; - } - } - } - } - } - - // More hacks on minus sign. - callback(DEH_String("WIMINUS"), &wiminus); - - for (i=0;i<10;i++) - { - // numbers 0-9 - DEH_snprintf(name, 9, "WINUM%d", i); - callback(name, &num[i]); - } - - // percent sign - callback(DEH_String("WIPCNT"), &percent); - - // "finished" - callback(DEH_String("WIF"), &finished); - - // "entering" - callback(DEH_String("WIENTER"), &entering); - - // "kills" - callback(DEH_String("WIOSTK"), &kills); - - // "scrt" - callback(DEH_String("WIOSTS"), &secret); - - // "secret" - callback(DEH_String("WISCRT2"), &sp_secret); - - // french wad uses WIOBJ (?) - if (W_CheckNumForName(DEH_String("WIOBJ")) >= 0) - { - // "items" - if (netgame && !deathmatch) - callback(DEH_String("WIOBJ"), &items); - else - callback(DEH_String("WIOSTI"), &items); - } else { - callback(DEH_String("WIOSTI"), &items); - } - - // "frgs" - callback(DEH_String("WIFRGS"), &frags); - - // ":" - callback(DEH_String("WICOLON"), &colon); - - // "time" - callback(DEH_String("WITIME"), &timepatch); - - // "sucks" - callback(DEH_String("WISUCKS"), &sucks); - - // "par" - callback(DEH_String("WIPAR"), &par); - - // "killers" (vertical) - callback(DEH_String("WIKILRS"), &killers); - - // "victims" (horiz) - callback(DEH_String("WIVCTMS"), &victims); - - // "total" - callback(DEH_String("WIMSTT"), &total); - - for (i=0 ; iepsd == 3) - { - M_StringCopy(name, DEH_String("INTERPIC"), sizeof(name)); - name[8] = '\0'; - } - else - { - DEH_snprintf(name, 9, "WIMAP%d", wbs->epsd); - } - - // Draw backdrop and save to a temporary buffer - - callback(name, &background); -} - -static void WI_loadCallback(char *name, patch_t **variable) -{ - *variable = W_CacheLumpName(name, PU_STATIC); -} - -void WI_loadData(void) -{ - if (gamemode == commercial) - { - NUMCMAPS = 32; - lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS, - PU_STATIC, NULL); - } - else - { - lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS, - PU_STATIC, NULL); - } - - WI_loadUnloadData(WI_loadCallback); - - // These two graphics are special cased because we're sharing - // them with the status bar code - - // your face - star = W_CacheLumpName(DEH_String("STFST01"), PU_STATIC); - - // dead face - bstar = W_CacheLumpName(DEH_String("STFDEAD0"), PU_STATIC); -} - -static void WI_unloadCallback(char *name, patch_t **variable) -{ - W_ReleaseLumpName(name); - *variable = NULL; -} - -void WI_unloadData(void) -{ - WI_loadUnloadData(WI_unloadCallback); - - // We do not free these lumps as they are shared with the status - // bar code. - - // W_ReleaseLumpName("STFST01"); - // W_ReleaseLumpName("STFDEAD0"); -} - -void WI_Drawer (void) -{ - switch (state) - { - case StatCount: - if (deathmatch) - WI_drawDeathmatchStats(); - else if (netgame) - WI_drawNetgameStats(); - else - WI_drawStats(); - break; - - case ShowNextLoc: - WI_drawShowNextLoc(); - break; - - case NoState: - WI_drawNoState(); - break; - } -} - - -void WI_initVariables(wbstartstruct_t* wbstartstruct) -{ - - wbs = wbstartstruct; - -#ifdef RANGECHECKING - if (gamemode != commercial) - { - if ( gamemode == retail ) - RNGCHECK(wbs->epsd, 0, 3); - else - RNGCHECK(wbs->epsd, 0, 2); - } - else - { - RNGCHECK(wbs->last, 0, 8); - RNGCHECK(wbs->next, 0, 8); - } - RNGCHECK(wbs->pnum, 0, MAXPLAYERS); - RNGCHECK(wbs->pnum, 0, MAXPLAYERS); -#endif - - acceleratestage = 0; - cnt = bcnt = 0; - firstrefresh = 1; - me = wbs->pnum; - plrs = wbs->plyr; - - if (!wbs->maxkills) - wbs->maxkills = 1; - - if (!wbs->maxitems) - wbs->maxitems = 1; - - if (!wbs->maxsecret) - wbs->maxsecret = 1; - - if ( gamemode != retail ) - if (wbs->epsd > 2) - wbs->epsd -= 3; -} - -void WI_Start(wbstartstruct_t* wbstartstruct) -{ - WI_initVariables(wbstartstruct); - WI_loadData(); - - if (deathmatch) - WI_initDeathmatchStats(); - else if (netgame) - WI_initNetgameStats(); - else - WI_initStats(); -} -#endif diff --git a/games/NXDoom/src/strife/wi_stuff.h b/games/NXDoom/src/strife/wi_stuff.h deleted file mode 100644 index 88ed1c63612..00000000000 --- a/games/NXDoom/src/strife/wi_stuff.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Intermission. -// - -#ifndef __WI_STUFF__ -#define __WI_STUFF__ - -// haleyjd 08/23/2010: Strife does not have an intermission -#if 0 -//#include "v_video.h" - -#include "doomdef.h" - -// States for the intermission - -typedef enum -{ - NoState = -1, - StatCount, - ShowNextLoc, -} stateenum_t; - -// Called by main loop, animate the intermission. -void WI_Ticker (void); - -// Called by main loop, -// draws the intermission directly into the screen buffer. -void WI_Drawer (void); - -// Setup for an intermission screen. -void WI_Start(wbstartstruct_t* wbstartstruct); - -// Shut down the intermission screen -void WI_End(void); - -#endif -#endif diff --git a/games/NXDoom/src/tables.c b/games/NXDoom/src/tables.c index 698ae98f571..61f0198c3da 100644 --- a/games/NXDoom/src/tables.c +++ b/games/NXDoom/src/tables.c @@ -1,2227 +1,2369 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Lookup tables. -// Do not try to look them up :-). -// In the order of appearance: -// -// int finetangent[4096] - Tangens LUT. -// Should work with BAM fairly well (12 of 16bit, -// effectively, by shifting). -// -// int finesine[10240] - Sine lookup. -// Guess what, serves as cosine, too. -// Remarkable thing is, how to use BAMs with this? -// -// int tantoangle[2049] - ArcTan LUT, -// maps tan(angle) to angle fast. Gotta search. -// -// +/**************************************************************************** + * apps/games/NXDoom/src/tables.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Lookup tables. + * Do not try to look them up :-). + * In the order of appearance: + * + * int finetangent[4096] - Tangens LUT. + * Should work with BAM fairly well (12 of 16bit, + * effectively, by shifting). + * + * int finesine[10240] - Sine lookup. + * Guess what, serves as cosine, too. + * Remarkable thing is, how to use BAMs with this? + * + * int tantoangle[2049] - ArcTan LUT, + * maps tan(angle) to angle fast. Gotta search. + * + ****************************************************************************/ -#include "tables.h" - -// to get a global angle from cartesian coordinates, the coordinates are -// flipped until they are in the first octant of the coordinate system, then -// the y (<=x) is scaled and divided by x to get a tangent (slope) value -// which is looked up in the tantoangle[] table. The +1 size is to handle -// the case when x==y without additional checking. +/**************************************************************************** + * Included Files + ****************************************************************************/ -int SlopeDiv(unsigned int num, unsigned int den) -{ - unsigned ans; - - if (den < 512) - { - return SLOPERANGE; - } - else - { - ans = (num << 3) / (den >> 8); +#include "tables.h" - if (ans <= SLOPERANGE) - { - return ans; - } - else - { - return SLOPERANGE; - } - } -} +/**************************************************************************** + * Public Data + ****************************************************************************/ const fixed_t finetangent[4096] = { - -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683, - -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368, - -5178251,-4882318,-4618375,-4381502,-4167737,-3973855,-3797206,-3635590, - -3487165,-3350381,-3223918,-3106651,-2997613,-2895966,-2800983,-2712030, - -2628549,-2550052,-2476104,-2406322,-2340362,-2277919,-2218719,-2162516, - -2109087,-2058233,-2009771,-1963536,-1919378,-1877161,-1836758,-1798063, - -1760956,-1725348,-1691149,-1658278,-1626658,-1596220,-1566898,-1538632, - -1511367,-1485049,-1459630,-1435065,-1411312,-1388330,-1366084,-1344537, - -1323658,-1303416,-1283783,-1264730,-1246234,-1228269,-1210813,-1193846, - -1177345,-1161294,-1145673,-1130465,-1115654,-1101225,-1087164,-1073455, - -1060087,-1047046,-1034322,-1021901,-1009774,-997931,-986361,-975054, - -964003,-953199,-942633,-932298,-922186,-912289,-902602,-893117, - -883829,-874730,-865817,-857081,-848520,-840127,-831898,-823827, - -815910,-808143,-800521,-793041,-785699,-778490,-771411,-764460, - -757631,-750922,-744331,-737853,-731486,-725227,-719074,-713023, - -707072,-701219,-695462,-689797,-684223,-678737,-673338,-668024, - -662792,-657640,-652568,-647572,-642651,-637803,-633028,-628323, - -623686,-619117,-614613,-610174,-605798,-601483,-597229,-593033, - -588896,-584815,-580789,-576818,-572901,-569035,-565221,-561456, - -557741,-554074,-550455,-546881,-543354,-539870,-536431,-533034, - -529680,-526366,-523094,-519861,-516667,-513512,-510394,-507313, - -504269,-501261,-498287,-495348,-492443,-489571,-486732,-483925, - -481150,-478406,-475692,-473009,-470355,-467730,-465133,-462565, - -460024,-457511,-455024,-452564,-450129,-447720,-445337,-442978, - -440643,-438332,-436045,-433781,-431540,-429321,-427125,-424951, - -422798,-420666,-418555,-416465,-414395,-412344,-410314,-408303, - -406311,-404338,-402384,-400448,-398530,-396630,-394747,-392882, - -391034,-389202,-387387,-385589,-383807,-382040,-380290,-378555, - -376835,-375130,-373440,-371765,-370105,-368459,-366826,-365208, - -363604,-362013,-360436,-358872,-357321,-355783,-354257,-352744, - -351244,-349756,-348280,-346816,-345364,-343924,-342495,-341078, - -339671,-338276,-336892,-335519,-334157,-332805,-331464,-330133, - -328812,-327502,-326201,-324910,-323629,-322358,-321097,-319844, - -318601,-317368,-316143,-314928,-313721,-312524,-311335,-310154, - -308983,-307819,-306664,-305517,-304379,-303248,-302126,-301011, - -299904,-298805,-297714,-296630,-295554,-294485,-293423,-292369, - -291322,-290282,-289249,-288223,-287204,-286192,-285186,-284188, - -283195,-282210,-281231,-280258,-279292,-278332,-277378,-276430, - -275489,-274553,-273624,-272700,-271782,-270871,-269965,-269064, - -268169,-267280,-266397,-265519,-264646,-263779,-262917,-262060, - -261209,-260363,-259522,-258686,-257855,-257029,-256208,-255392, - -254581,-253774,-252973,-252176,-251384,-250596,-249813,-249035, - -248261,-247492,-246727,-245966,-245210,-244458,-243711,-242967, - -242228,-241493,-240763,-240036,-239314,-238595,-237881,-237170, - -236463,-235761,-235062,-234367,-233676,-232988,-232304,-231624, - -230948,-230275,-229606,-228941,-228279,-227621,-226966,-226314, - -225666,-225022,-224381,-223743,-223108,-222477,-221849,-221225, - -220603,-219985,-219370,-218758,-218149,-217544,-216941,-216341, - -215745,-215151,-214561,-213973,-213389,-212807,-212228,-211652, - -211079,-210509,-209941,-209376,-208815,-208255,-207699,-207145, - -206594,-206045,-205500,-204956,-204416,-203878,-203342,-202809, - -202279,-201751,-201226,-200703,-200182,-199664,-199149,-198636, - -198125,-197616,-197110,-196606,-196105,-195606,-195109,-194614, - -194122,-193631,-193143,-192658,-192174,-191693,-191213,-190736, - -190261,-189789,-189318,-188849,-188382,-187918,-187455,-186995, - -186536,-186080,-185625,-185173,-184722,-184274,-183827,-183382, - -182939,-182498,-182059,-181622,-181186,-180753,-180321,-179891, - -179463,-179037,-178612,-178190,-177769,-177349,-176932,-176516, - -176102,-175690,-175279,-174870,-174463,-174057,-173653,-173251, - -172850,-172451,-172053,-171657,-171263,-170870,-170479,-170089, - -169701,-169315,-168930,-168546,-168164,-167784,-167405,-167027, - -166651,-166277,-165904,-165532,-165162,-164793,-164426,-164060, - -163695,-163332,-162970,-162610,-162251,-161893,-161537,-161182, - -160828,-160476,-160125,-159775,-159427,-159079,-158734,-158389, - -158046,-157704,-157363,-157024,-156686,-156349,-156013,-155678, - -155345,-155013,-154682,-154352,-154024,-153697,-153370,-153045, - -152722,-152399,-152077,-151757,-151438,-151120,-150803,-150487, - -150172,-149859,-149546,-149235,-148924,-148615,-148307,-148000, - -147693,-147388,-147084,-146782,-146480,-146179,-145879,-145580, - -145282,-144986,-144690,-144395,-144101,-143808,-143517,-143226, - -142936,-142647,-142359,-142072,-141786,-141501,-141217,-140934, - -140651,-140370,-140090,-139810,-139532,-139254,-138977,-138701, - -138426,-138152,-137879,-137607,-137335,-137065,-136795,-136526, - -136258,-135991,-135725,-135459,-135195,-134931,-134668,-134406, - -134145,-133884,-133625,-133366,-133108,-132851,-132594,-132339, - -132084,-131830,-131576,-131324,-131072,-130821,-130571,-130322, - -130073,-129825,-129578,-129332,-129086,-128841,-128597,-128353, - -128111,-127869,-127627,-127387,-127147,-126908,-126669,-126432, - -126195,-125959,-125723,-125488,-125254,-125020,-124787,-124555, - -124324,-124093,-123863,-123633,-123404,-123176,-122949,-122722, - -122496,-122270,-122045,-121821,-121597,-121374,-121152,-120930, - -120709,-120489,-120269,-120050,-119831,-119613,-119396,-119179, - -118963,-118747,-118532,-118318,-118104,-117891,-117678,-117466, - -117254,-117044,-116833,-116623,-116414,-116206,-115998,-115790, - -115583,-115377,-115171,-114966,-114761,-114557,-114354,-114151, - -113948,-113746,-113545,-113344,-113143,-112944,-112744,-112546, - -112347,-112150,-111952,-111756,-111560,-111364,-111169,-110974, - -110780,-110586,-110393,-110200,-110008,-109817,-109626,-109435, - -109245,-109055,-108866,-108677,-108489,-108301,-108114,-107927, - -107741,-107555,-107369,-107184,-107000,-106816,-106632,-106449, - -106266,-106084,-105902,-105721,-105540,-105360,-105180,-105000, - -104821,-104643,-104465,-104287,-104109,-103933,-103756,-103580, - -103404,-103229,-103054,-102880,-102706,-102533,-102360,-102187, - -102015,-101843,-101671,-101500,-101330,-101159,-100990,-100820, - -100651,-100482,-100314,-100146,-99979,-99812,-99645,-99479, - -99313,-99148,-98982,-98818,-98653,-98489,-98326,-98163, - -98000,-97837,-97675,-97513,-97352,-97191,-97030,-96870, - -96710,-96551,-96391,-96233,-96074,-95916,-95758,-95601, - -95444,-95287,-95131,-94975,-94819,-94664,-94509,-94354, - -94200,-94046,-93892,-93739,-93586,-93434,-93281,-93129, - -92978,-92826,-92675,-92525,-92375,-92225,-92075,-91926, - -91777,-91628,-91480,-91332,-91184,-91036,-90889,-90742, - -90596,-90450,-90304,-90158,-90013,-89868,-89724,-89579, - -89435,-89292,-89148,-89005,-88862,-88720,-88577,-88435, - -88294,-88152,-88011,-87871,-87730,-87590,-87450,-87310, - -87171,-87032,-86893,-86755,-86616,-86479,-86341,-86204, - -86066,-85930,-85793,-85657,-85521,-85385,-85250,-85114, - -84980,-84845,-84710,-84576,-84443,-84309,-84176,-84043, - -83910,-83777,-83645,-83513,-83381,-83250,-83118,-82987, - -82857,-82726,-82596,-82466,-82336,-82207,-82078,-81949, - -81820,-81691,-81563,-81435,-81307,-81180,-81053,-80925, - -80799,-80672,-80546,-80420,-80294,-80168,-80043,-79918, - -79793,-79668,-79544,-79420,-79296,-79172,-79048,-78925, - -78802,-78679,-78557,-78434,-78312,-78190,-78068,-77947, - -77826,-77705,-77584,-77463,-77343,-77223,-77103,-76983, - -76864,-76744,-76625,-76506,-76388,-76269,-76151,-76033, - -75915,-75797,-75680,-75563,-75446,-75329,-75213,-75096, - -74980,-74864,-74748,-74633,-74517,-74402,-74287,-74172, - -74058,-73944,-73829,-73715,-73602,-73488,-73375,-73262, - -73149,-73036,-72923,-72811,-72699,-72587,-72475,-72363, - -72252,-72140,-72029,-71918,-71808,-71697,-71587,-71477, - -71367,-71257,-71147,-71038,-70929,-70820,-70711,-70602, - -70494,-70385,-70277,-70169,-70061,-69954,-69846,-69739, - -69632,-69525,-69418,-69312,-69205,-69099,-68993,-68887, - -68781,-68676,-68570,-68465,-68360,-68255,-68151,-68046, - -67942,-67837,-67733,-67629,-67526,-67422,-67319,-67216, - -67113,-67010,-66907,-66804,-66702,-66600,-66498,-66396, - -66294,-66192,-66091,-65989,-65888,-65787,-65686,-65586, - -65485,-65385,-65285,-65185,-65085,-64985,-64885,-64786, - -64687,-64587,-64488,-64389,-64291,-64192,-64094,-63996, - -63897,-63799,-63702,-63604,-63506,-63409,-63312,-63215, - -63118,-63021,-62924,-62828,-62731,-62635,-62539,-62443, - -62347,-62251,-62156,-62060,-61965,-61870,-61775,-61680, - -61585,-61491,-61396,-61302,-61208,-61114,-61020,-60926, - -60833,-60739,-60646,-60552,-60459,-60366,-60273,-60181, - -60088,-59996,-59903,-59811,-59719,-59627,-59535,-59444, - -59352,-59261,-59169,-59078,-58987,-58896,-58805,-58715, - -58624,-58534,-58443,-58353,-58263,-58173,-58083,-57994, - -57904,-57815,-57725,-57636,-57547,-57458,-57369,-57281, - -57192,-57104,-57015,-56927,-56839,-56751,-56663,-56575, - -56487,-56400,-56312,-56225,-56138,-56051,-55964,-55877, - -55790,-55704,-55617,-55531,-55444,-55358,-55272,-55186, - -55100,-55015,-54929,-54843,-54758,-54673,-54587,-54502, - -54417,-54333,-54248,-54163,-54079,-53994,-53910,-53826, - -53741,-53657,-53574,-53490,-53406,-53322,-53239,-53156, - -53072,-52989,-52906,-52823,-52740,-52657,-52575,-52492, - -52410,-52327,-52245,-52163,-52081,-51999,-51917,-51835, - -51754,-51672,-51591,-51509,-51428,-51347,-51266,-51185, - -51104,-51023,-50942,-50862,-50781,-50701,-50621,-50540, - -50460,-50380,-50300,-50221,-50141,-50061,-49982,-49902, - -49823,-49744,-49664,-49585,-49506,-49427,-49349,-49270, - -49191,-49113,-49034,-48956,-48878,-48799,-48721,-48643, - -48565,-48488,-48410,-48332,-48255,-48177,-48100,-48022, - -47945,-47868,-47791,-47714,-47637,-47560,-47484,-47407, - -47331,-47254,-47178,-47102,-47025,-46949,-46873,-46797, - -46721,-46646,-46570,-46494,-46419,-46343,-46268,-46193, - -46118,-46042,-45967,-45892,-45818,-45743,-45668,-45593, - -45519,-45444,-45370,-45296,-45221,-45147,-45073,-44999, - -44925,-44851,-44778,-44704,-44630,-44557,-44483,-44410, - -44337,-44263,-44190,-44117,-44044,-43971,-43898,-43826, - -43753,-43680,-43608,-43535,-43463,-43390,-43318,-43246, - -43174,-43102,-43030,-42958,-42886,-42814,-42743,-42671, - -42600,-42528,-42457,-42385,-42314,-42243,-42172,-42101, - -42030,-41959,-41888,-41817,-41747,-41676,-41605,-41535, - -41465,-41394,-41324,-41254,-41184,-41113,-41043,-40973, - -40904,-40834,-40764,-40694,-40625,-40555,-40486,-40416, - -40347,-40278,-40208,-40139,-40070,-40001,-39932,-39863, - -39794,-39726,-39657,-39588,-39520,-39451,-39383,-39314, - -39246,-39178,-39110,-39042,-38973,-38905,-38837,-38770, - -38702,-38634,-38566,-38499,-38431,-38364,-38296,-38229, - -38161,-38094,-38027,-37960,-37893,-37826,-37759,-37692, - -37625,-37558,-37491,-37425,-37358,-37291,-37225,-37158, - -37092,-37026,-36959,-36893,-36827,-36761,-36695,-36629, - -36563,-36497,-36431,-36365,-36300,-36234,-36168,-36103, - -36037,-35972,-35907,-35841,-35776,-35711,-35646,-35580, - -35515,-35450,-35385,-35321,-35256,-35191,-35126,-35062, - -34997,-34932,-34868,-34803,-34739,-34675,-34610,-34546, - -34482,-34418,-34354,-34289,-34225,-34162,-34098,-34034, - -33970,-33906,-33843,-33779,-33715,-33652,-33588,-33525, - -33461,-33398,-33335,-33272,-33208,-33145,-33082,-33019, - -32956,-32893,-32830,-32767,-32705,-32642,-32579,-32516, - -32454,-32391,-32329,-32266,-32204,-32141,-32079,-32017, - -31955,-31892,-31830,-31768,-31706,-31644,-31582,-31520, - -31458,-31396,-31335,-31273,-31211,-31150,-31088,-31026, - -30965,-30904,-30842,-30781,-30719,-30658,-30597,-30536, - -30474,-30413,-30352,-30291,-30230,-30169,-30108,-30048, - -29987,-29926,-29865,-29805,-29744,-29683,-29623,-29562, - -29502,-29441,-29381,-29321,-29260,-29200,-29140,-29080, - -29020,-28959,-28899,-28839,-28779,-28719,-28660,-28600, - -28540,-28480,-28420,-28361,-28301,-28241,-28182,-28122, - -28063,-28003,-27944,-27884,-27825,-27766,-27707,-27647, - -27588,-27529,-27470,-27411,-27352,-27293,-27234,-27175, - -27116,-27057,-26998,-26940,-26881,-26822,-26763,-26705, - -26646,-26588,-26529,-26471,-26412,-26354,-26295,-26237, - -26179,-26120,-26062,-26004,-25946,-25888,-25830,-25772, - -25714,-25656,-25598,-25540,-25482,-25424,-25366,-25308, - -25251,-25193,-25135,-25078,-25020,-24962,-24905,-24847, - -24790,-24732,-24675,-24618,-24560,-24503,-24446,-24389, - -24331,-24274,-24217,-24160,-24103,-24046,-23989,-23932, - -23875,-23818,-23761,-23704,-23647,-23591,-23534,-23477, - -23420,-23364,-23307,-23250,-23194,-23137,-23081,-23024, - -22968,-22911,-22855,-22799,-22742,-22686,-22630,-22573, - -22517,-22461,-22405,-22349,-22293,-22237,-22181,-22125, - -22069,-22013,-21957,-21901,-21845,-21789,-21733,-21678, - -21622,-21566,-21510,-21455,-21399,-21343,-21288,-21232, - -21177,-21121,-21066,-21010,-20955,-20900,-20844,-20789, - -20734,-20678,-20623,-20568,-20513,-20457,-20402,-20347, - -20292,-20237,-20182,-20127,-20072,-20017,-19962,-19907, - -19852,-19797,-19742,-19688,-19633,-19578,-19523,-19469, - -19414,-19359,-19305,-19250,-19195,-19141,-19086,-19032, - -18977,-18923,-18868,-18814,-18760,-18705,-18651,-18597, - -18542,-18488,-18434,-18380,-18325,-18271,-18217,-18163, - -18109,-18055,-18001,-17946,-17892,-17838,-17784,-17731, - -17677,-17623,-17569,-17515,-17461,-17407,-17353,-17300, - -17246,-17192,-17138,-17085,-17031,-16977,-16924,-16870, - -16817,-16763,-16710,-16656,-16603,-16549,-16496,-16442, - -16389,-16335,-16282,-16229,-16175,-16122,-16069,-16015, - -15962,-15909,-15856,-15802,-15749,-15696,-15643,-15590, - -15537,-15484,-15431,-15378,-15325,-15272,-15219,-15166, - -15113,-15060,-15007,-14954,-14901,-14848,-14795,-14743, - -14690,-14637,-14584,-14531,-14479,-14426,-14373,-14321, - -14268,-14215,-14163,-14110,-14057,-14005,-13952,-13900, - -13847,-13795,-13742,-13690,-13637,-13585,-13533,-13480, - -13428,-13375,-13323,-13271,-13218,-13166,-13114,-13062, - -13009,-12957,-12905,-12853,-12800,-12748,-12696,-12644, - -12592,-12540,-12488,-12436,-12383,-12331,-12279,-12227, - -12175,-12123,-12071,-12019,-11967,-11916,-11864,-11812, - -11760,-11708,-11656,-11604,-11552,-11501,-11449,-11397, - -11345,-11293,-11242,-11190,-11138,-11086,-11035,-10983, - -10931,-10880,-10828,-10777,-10725,-10673,-10622,-10570, - -10519,-10467,-10415,-10364,-10312,-10261,-10209,-10158, - -10106,-10055,-10004,-9952,-9901,-9849,-9798,-9747, - -9695,-9644,-9592,-9541,-9490,-9438,-9387,-9336, - -9285,-9233,-9182,-9131,-9080,-9028,-8977,-8926, - -8875,-8824,-8772,-8721,-8670,-8619,-8568,-8517, - -8466,-8414,-8363,-8312,-8261,-8210,-8159,-8108, - -8057,-8006,-7955,-7904,-7853,-7802,-7751,-7700, - -7649,-7598,-7547,-7496,-7445,-7395,-7344,-7293, - -7242,-7191,-7140,-7089,-7038,-6988,-6937,-6886, - -6835,-6784,-6733,-6683,-6632,-6581,-6530,-6480, - -6429,-6378,-6327,-6277,-6226,-6175,-6124,-6074, - -6023,-5972,-5922,-5871,-5820,-5770,-5719,-5668, - -5618,-5567,-5517,-5466,-5415,-5365,-5314,-5264, - -5213,-5162,-5112,-5061,-5011,-4960,-4910,-4859, - -4808,-4758,-4707,-4657,-4606,-4556,-4505,-4455, - -4404,-4354,-4303,-4253,-4202,-4152,-4101,-4051, - -4001,-3950,-3900,-3849,-3799,-3748,-3698,-3648, - -3597,-3547,-3496,-3446,-3395,-3345,-3295,-3244, - -3194,-3144,-3093,-3043,-2992,-2942,-2892,-2841, - -2791,-2741,-2690,-2640,-2590,-2539,-2489,-2439, - -2388,-2338,-2288,-2237,-2187,-2137,-2086,-2036, - -1986,-1935,-1885,-1835,-1784,-1734,-1684,-1633, - -1583,-1533,-1483,-1432,-1382,-1332,-1281,-1231, - -1181,-1131,-1080,-1030,-980,-929,-879,-829, - -779,-728,-678,-628,-578,-527,-477,-427, - -376,-326,-276,-226,-175,-125,-75,-25, - 25,75,125,175,226,276,326,376, - 427,477,527,578,628,678,728,779, - 829,879,929,980,1030,1080,1131,1181, - 1231,1281,1332,1382,1432,1483,1533,1583, - 1633,1684,1734,1784,1835,1885,1935,1986, - 2036,2086,2137,2187,2237,2288,2338,2388, - 2439,2489,2539,2590,2640,2690,2741,2791, - 2841,2892,2942,2992,3043,3093,3144,3194, - 3244,3295,3345,3395,3446,3496,3547,3597, - 3648,3698,3748,3799,3849,3900,3950,4001, - 4051,4101,4152,4202,4253,4303,4354,4404, - 4455,4505,4556,4606,4657,4707,4758,4808, - 4859,4910,4960,5011,5061,5112,5162,5213, - 5264,5314,5365,5415,5466,5517,5567,5618, - 5668,5719,5770,5820,5871,5922,5972,6023, - 6074,6124,6175,6226,6277,6327,6378,6429, - 6480,6530,6581,6632,6683,6733,6784,6835, - 6886,6937,6988,7038,7089,7140,7191,7242, - 7293,7344,7395,7445,7496,7547,7598,7649, - 7700,7751,7802,7853,7904,7955,8006,8057, - 8108,8159,8210,8261,8312,8363,8414,8466, - 8517,8568,8619,8670,8721,8772,8824,8875, - 8926,8977,9028,9080,9131,9182,9233,9285, - 9336,9387,9438,9490,9541,9592,9644,9695, - 9747,9798,9849,9901,9952,10004,10055,10106, - 10158,10209,10261,10312,10364,10415,10467,10519, - 10570,10622,10673,10725,10777,10828,10880,10931, - 10983,11035,11086,11138,11190,11242,11293,11345, - 11397,11449,11501,11552,11604,11656,11708,11760, - 11812,11864,11916,11967,12019,12071,12123,12175, - 12227,12279,12331,12383,12436,12488,12540,12592, - 12644,12696,12748,12800,12853,12905,12957,13009, - 13062,13114,13166,13218,13271,13323,13375,13428, - 13480,13533,13585,13637,13690,13742,13795,13847, - 13900,13952,14005,14057,14110,14163,14215,14268, - 14321,14373,14426,14479,14531,14584,14637,14690, - 14743,14795,14848,14901,14954,15007,15060,15113, - 15166,15219,15272,15325,15378,15431,15484,15537, - 15590,15643,15696,15749,15802,15856,15909,15962, - 16015,16069,16122,16175,16229,16282,16335,16389, - 16442,16496,16549,16603,16656,16710,16763,16817, - 16870,16924,16977,17031,17085,17138,17192,17246, - 17300,17353,17407,17461,17515,17569,17623,17677, - 17731,17784,17838,17892,17946,18001,18055,18109, - 18163,18217,18271,18325,18380,18434,18488,18542, - 18597,18651,18705,18760,18814,18868,18923,18977, - 19032,19086,19141,19195,19250,19305,19359,19414, - 19469,19523,19578,19633,19688,19742,19797,19852, - 19907,19962,20017,20072,20127,20182,20237,20292, - 20347,20402,20457,20513,20568,20623,20678,20734, - 20789,20844,20900,20955,21010,21066,21121,21177, - 21232,21288,21343,21399,21455,21510,21566,21622, - 21678,21733,21789,21845,21901,21957,22013,22069, - 22125,22181,22237,22293,22349,22405,22461,22517, - 22573,22630,22686,22742,22799,22855,22911,22968, - 23024,23081,23137,23194,23250,23307,23364,23420, - 23477,23534,23591,23647,23704,23761,23818,23875, - 23932,23989,24046,24103,24160,24217,24274,24331, - 24389,24446,24503,24560,24618,24675,24732,24790, - 24847,24905,24962,25020,25078,25135,25193,25251, - 25308,25366,25424,25482,25540,25598,25656,25714, - 25772,25830,25888,25946,26004,26062,26120,26179, - 26237,26295,26354,26412,26471,26529,26588,26646, - 26705,26763,26822,26881,26940,26998,27057,27116, - 27175,27234,27293,27352,27411,27470,27529,27588, - 27647,27707,27766,27825,27884,27944,28003,28063, - 28122,28182,28241,28301,28361,28420,28480,28540, - 28600,28660,28719,28779,28839,28899,28959,29020, - 29080,29140,29200,29260,29321,29381,29441,29502, - 29562,29623,29683,29744,29805,29865,29926,29987, - 30048,30108,30169,30230,30291,30352,30413,30474, - 30536,30597,30658,30719,30781,30842,30904,30965, - 31026,31088,31150,31211,31273,31335,31396,31458, - 31520,31582,31644,31706,31768,31830,31892,31955, - 32017,32079,32141,32204,32266,32329,32391,32454, - 32516,32579,32642,32705,32767,32830,32893,32956, - 33019,33082,33145,33208,33272,33335,33398,33461, - 33525,33588,33652,33715,33779,33843,33906,33970, - 34034,34098,34162,34225,34289,34354,34418,34482, - 34546,34610,34675,34739,34803,34868,34932,34997, - 35062,35126,35191,35256,35321,35385,35450,35515, - 35580,35646,35711,35776,35841,35907,35972,36037, - 36103,36168,36234,36300,36365,36431,36497,36563, - 36629,36695,36761,36827,36893,36959,37026,37092, - 37158,37225,37291,37358,37425,37491,37558,37625, - 37692,37759,37826,37893,37960,38027,38094,38161, - 38229,38296,38364,38431,38499,38566,38634,38702, - 38770,38837,38905,38973,39042,39110,39178,39246, - 39314,39383,39451,39520,39588,39657,39726,39794, - 39863,39932,40001,40070,40139,40208,40278,40347, - 40416,40486,40555,40625,40694,40764,40834,40904, - 40973,41043,41113,41184,41254,41324,41394,41465, - 41535,41605,41676,41747,41817,41888,41959,42030, - 42101,42172,42243,42314,42385,42457,42528,42600, - 42671,42743,42814,42886,42958,43030,43102,43174, - 43246,43318,43390,43463,43535,43608,43680,43753, - 43826,43898,43971,44044,44117,44190,44263,44337, - 44410,44483,44557,44630,44704,44778,44851,44925, - 44999,45073,45147,45221,45296,45370,45444,45519, - 45593,45668,45743,45818,45892,45967,46042,46118, - 46193,46268,46343,46419,46494,46570,46646,46721, - 46797,46873,46949,47025,47102,47178,47254,47331, - 47407,47484,47560,47637,47714,47791,47868,47945, - 48022,48100,48177,48255,48332,48410,48488,48565, - 48643,48721,48799,48878,48956,49034,49113,49191, - 49270,49349,49427,49506,49585,49664,49744,49823, - 49902,49982,50061,50141,50221,50300,50380,50460, - 50540,50621,50701,50781,50862,50942,51023,51104, - 51185,51266,51347,51428,51509,51591,51672,51754, - 51835,51917,51999,52081,52163,52245,52327,52410, - 52492,52575,52657,52740,52823,52906,52989,53072, - 53156,53239,53322,53406,53490,53574,53657,53741, - 53826,53910,53994,54079,54163,54248,54333,54417, - 54502,54587,54673,54758,54843,54929,55015,55100, - 55186,55272,55358,55444,55531,55617,55704,55790, - 55877,55964,56051,56138,56225,56312,56400,56487, - 56575,56663,56751,56839,56927,57015,57104,57192, - 57281,57369,57458,57547,57636,57725,57815,57904, - 57994,58083,58173,58263,58353,58443,58534,58624, - 58715,58805,58896,58987,59078,59169,59261,59352, - 59444,59535,59627,59719,59811,59903,59996,60088, - 60181,60273,60366,60459,60552,60646,60739,60833, - 60926,61020,61114,61208,61302,61396,61491,61585, - 61680,61775,61870,61965,62060,62156,62251,62347, - 62443,62539,62635,62731,62828,62924,63021,63118, - 63215,63312,63409,63506,63604,63702,63799,63897, - 63996,64094,64192,64291,64389,64488,64587,64687, - 64786,64885,64985,65085,65185,65285,65385,65485, - 65586,65686,65787,65888,65989,66091,66192,66294, - 66396,66498,66600,66702,66804,66907,67010,67113, - 67216,67319,67422,67526,67629,67733,67837,67942, - 68046,68151,68255,68360,68465,68570,68676,68781, - 68887,68993,69099,69205,69312,69418,69525,69632, - 69739,69846,69954,70061,70169,70277,70385,70494, - 70602,70711,70820,70929,71038,71147,71257,71367, - 71477,71587,71697,71808,71918,72029,72140,72252, - 72363,72475,72587,72699,72811,72923,73036,73149, - 73262,73375,73488,73602,73715,73829,73944,74058, - 74172,74287,74402,74517,74633,74748,74864,74980, - 75096,75213,75329,75446,75563,75680,75797,75915, - 76033,76151,76269,76388,76506,76625,76744,76864, - 76983,77103,77223,77343,77463,77584,77705,77826, - 77947,78068,78190,78312,78434,78557,78679,78802, - 78925,79048,79172,79296,79420,79544,79668,79793, - 79918,80043,80168,80294,80420,80546,80672,80799, - 80925,81053,81180,81307,81435,81563,81691,81820, - 81949,82078,82207,82336,82466,82596,82726,82857, - 82987,83118,83250,83381,83513,83645,83777,83910, - 84043,84176,84309,84443,84576,84710,84845,84980, - 85114,85250,85385,85521,85657,85793,85930,86066, - 86204,86341,86479,86616,86755,86893,87032,87171, - 87310,87450,87590,87730,87871,88011,88152,88294, - 88435,88577,88720,88862,89005,89148,89292,89435, - 89579,89724,89868,90013,90158,90304,90450,90596, - 90742,90889,91036,91184,91332,91480,91628,91777, - 91926,92075,92225,92375,92525,92675,92826,92978, - 93129,93281,93434,93586,93739,93892,94046,94200, - 94354,94509,94664,94819,94975,95131,95287,95444, - 95601,95758,95916,96074,96233,96391,96551,96710, - 96870,97030,97191,97352,97513,97675,97837,98000, - 98163,98326,98489,98653,98818,98982,99148,99313, - 99479,99645,99812,99979,100146,100314,100482,100651, - 100820,100990,101159,101330,101500,101671,101843,102015, - 102187,102360,102533,102706,102880,103054,103229,103404, - 103580,103756,103933,104109,104287,104465,104643,104821, - 105000,105180,105360,105540,105721,105902,106084,106266, - 106449,106632,106816,107000,107184,107369,107555,107741, - 107927,108114,108301,108489,108677,108866,109055,109245, - 109435,109626,109817,110008,110200,110393,110586,110780, - 110974,111169,111364,111560,111756,111952,112150,112347, - 112546,112744,112944,113143,113344,113545,113746,113948, - 114151,114354,114557,114761,114966,115171,115377,115583, - 115790,115998,116206,116414,116623,116833,117044,117254, - 117466,117678,117891,118104,118318,118532,118747,118963, - 119179,119396,119613,119831,120050,120269,120489,120709, - 120930,121152,121374,121597,121821,122045,122270,122496, - 122722,122949,123176,123404,123633,123863,124093,124324, - 124555,124787,125020,125254,125488,125723,125959,126195, - 126432,126669,126908,127147,127387,127627,127869,128111, - 128353,128597,128841,129086,129332,129578,129825,130073, - 130322,130571,130821,131072,131324,131576,131830,132084, - 132339,132594,132851,133108,133366,133625,133884,134145, - 134406,134668,134931,135195,135459,135725,135991,136258, - 136526,136795,137065,137335,137607,137879,138152,138426, - 138701,138977,139254,139532,139810,140090,140370,140651, - 140934,141217,141501,141786,142072,142359,142647,142936, - 143226,143517,143808,144101,144395,144690,144986,145282, - 145580,145879,146179,146480,146782,147084,147388,147693, - 148000,148307,148615,148924,149235,149546,149859,150172, - 150487,150803,151120,151438,151757,152077,152399,152722, - 153045,153370,153697,154024,154352,154682,155013,155345, - 155678,156013,156349,156686,157024,157363,157704,158046, - 158389,158734,159079,159427,159775,160125,160476,160828, - 161182,161537,161893,162251,162610,162970,163332,163695, - 164060,164426,164793,165162,165532,165904,166277,166651, - 167027,167405,167784,168164,168546,168930,169315,169701, - 170089,170479,170870,171263,171657,172053,172451,172850, - 173251,173653,174057,174463,174870,175279,175690,176102, - 176516,176932,177349,177769,178190,178612,179037,179463, - 179891,180321,180753,181186,181622,182059,182498,182939, - 183382,183827,184274,184722,185173,185625,186080,186536, - 186995,187455,187918,188382,188849,189318,189789,190261, - 190736,191213,191693,192174,192658,193143,193631,194122, - 194614,195109,195606,196105,196606,197110,197616,198125, - 198636,199149,199664,200182,200703,201226,201751,202279, - 202809,203342,203878,204416,204956,205500,206045,206594, - 207145,207699,208255,208815,209376,209941,210509,211079, - 211652,212228,212807,213389,213973,214561,215151,215745, - 216341,216941,217544,218149,218758,219370,219985,220603, - 221225,221849,222477,223108,223743,224381,225022,225666, - 226314,226966,227621,228279,228941,229606,230275,230948, - 231624,232304,232988,233676,234367,235062,235761,236463, - 237170,237881,238595,239314,240036,240763,241493,242228, - 242967,243711,244458,245210,245966,246727,247492,248261, - 249035,249813,250596,251384,252176,252973,253774,254581, - 255392,256208,257029,257855,258686,259522,260363,261209, - 262060,262917,263779,264646,265519,266397,267280,268169, - 269064,269965,270871,271782,272700,273624,274553,275489, - 276430,277378,278332,279292,280258,281231,282210,283195, - 284188,285186,286192,287204,288223,289249,290282,291322, - 292369,293423,294485,295554,296630,297714,298805,299904, - 301011,302126,303248,304379,305517,306664,307819,308983, - 310154,311335,312524,313721,314928,316143,317368,318601, - 319844,321097,322358,323629,324910,326201,327502,328812, - 330133,331464,332805,334157,335519,336892,338276,339671, - 341078,342495,343924,345364,346816,348280,349756,351244, - 352744,354257,355783,357321,358872,360436,362013,363604, - 365208,366826,368459,370105,371765,373440,375130,376835, - 378555,380290,382040,383807,385589,387387,389202,391034, - 392882,394747,396630,398530,400448,402384,404338,406311, - 408303,410314,412344,414395,416465,418555,420666,422798, - 424951,427125,429321,431540,433781,436045,438332,440643, - 442978,445337,447720,450129,452564,455024,457511,460024, - 462565,465133,467730,470355,473009,475692,478406,481150, - 483925,486732,489571,492443,495348,498287,501261,504269, - 507313,510394,513512,516667,519861,523094,526366,529680, - 533034,536431,539870,543354,546881,550455,554074,557741, - 561456,565221,569035,572901,576818,580789,584815,588896, - 593033,597229,601483,605798,610174,614613,619117,623686, - 628323,633028,637803,642651,647572,652568,657640,662792, - 668024,673338,678737,684223,689797,695462,701219,707072, - 713023,719074,725227,731486,737853,744331,750922,757631, - 764460,771411,778490,785699,793041,800521,808143,815910, - 823827,831898,840127,848520,857081,865817,874730,883829, - 893117,902602,912289,922186,932298,942633,953199,964003, - 975054,986361,997931,1009774,1021901,1034322,1047046,1060087, - 1073455,1087164,1101225,1115654,1130465,1145673,1161294,1177345, - 1193846,1210813,1228269,1246234,1264730,1283783,1303416,1323658, - 1344537,1366084,1388330,1411312,1435065,1459630,1485049,1511367, - 1538632,1566898,1596220,1626658,1658278,1691149,1725348,1760956, - 1798063,1836758,1877161,1919378,1963536,2009771,2058233,2109087, - 2162516,2218719,2277919,2340362,2406322,2476104,2550052,2628549, - 2712030,2800983,2895966,2997613,3106651,3223918,3350381,3487165, - 3635590,3797206,3973855,4167737,4381502,4618375,4882318,5178251, - 5512368,5892567,6329090,6835455,7429880,8137527,8994149,10052327, - 11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304 + -170910304, -56965752, -34178904, -24413316, -18988036, -15535599, + -13145455, -11392683, -10052327, -8994149, -8137527, -7429880, + -6835455, -6329090, -5892567, -5512368, -5178251, -4882318, + -4618375, -4381502, -4167737, -3973855, -3797206, -3635590, + -3487165, -3350381, -3223918, -3106651, -2997613, -2895966, + -2800983, -2712030, -2628549, -2550052, -2476104, -2406322, + -2340362, -2277919, -2218719, -2162516, -2109087, -2058233, + -2009771, -1963536, -1919378, -1877161, -1836758, -1798063, + -1760956, -1725348, -1691149, -1658278, -1626658, -1596220, + -1566898, -1538632, -1511367, -1485049, -1459630, -1435065, + -1411312, -1388330, -1366084, -1344537, -1323658, -1303416, + -1283783, -1264730, -1246234, -1228269, -1210813, -1193846, + -1177345, -1161294, -1145673, -1130465, -1115654, -1101225, + -1087164, -1073455, -1060087, -1047046, -1034322, -1021901, + -1009774, -997931, -986361, -975054, -964003, -953199, + -942633, -932298, -922186, -912289, -902602, -893117, + -883829, -874730, -865817, -857081, -848520, -840127, + -831898, -823827, -815910, -808143, -800521, -793041, + -785699, -778490, -771411, -764460, -757631, -750922, + -744331, -737853, -731486, -725227, -719074, -713023, + -707072, -701219, -695462, -689797, -684223, -678737, + -673338, -668024, -662792, -657640, -652568, -647572, + -642651, -637803, -633028, -628323, -623686, -619117, + -614613, -610174, -605798, -601483, -597229, -593033, + -588896, -584815, -580789, -576818, -572901, -569035, + -565221, -561456, -557741, -554074, -550455, -546881, + -543354, -539870, -536431, -533034, -529680, -526366, + -523094, -519861, -516667, -513512, -510394, -507313, + -504269, -501261, -498287, -495348, -492443, -489571, + -486732, -483925, -481150, -478406, -475692, -473009, + -470355, -467730, -465133, -462565, -460024, -457511, + -455024, -452564, -450129, -447720, -445337, -442978, + -440643, -438332, -436045, -433781, -431540, -429321, + -427125, -424951, -422798, -420666, -418555, -416465, + -414395, -412344, -410314, -408303, -406311, -404338, + -402384, -400448, -398530, -396630, -394747, -392882, + -391034, -389202, -387387, -385589, -383807, -382040, + -380290, -378555, -376835, -375130, -373440, -371765, + -370105, -368459, -366826, -365208, -363604, -362013, + -360436, -358872, -357321, -355783, -354257, -352744, + -351244, -349756, -348280, -346816, -345364, -343924, + -342495, -341078, -339671, -338276, -336892, -335519, + -334157, -332805, -331464, -330133, -328812, -327502, + -326201, -324910, -323629, -322358, -321097, -319844, + -318601, -317368, -316143, -314928, -313721, -312524, + -311335, -310154, -308983, -307819, -306664, -305517, + -304379, -303248, -302126, -301011, -299904, -298805, + -297714, -296630, -295554, -294485, -293423, -292369, + -291322, -290282, -289249, -288223, -287204, -286192, + -285186, -284188, -283195, -282210, -281231, -280258, + -279292, -278332, -277378, -276430, -275489, -274553, + -273624, -272700, -271782, -270871, -269965, -269064, + -268169, -267280, -266397, -265519, -264646, -263779, + -262917, -262060, -261209, -260363, -259522, -258686, + -257855, -257029, -256208, -255392, -254581, -253774, + -252973, -252176, -251384, -250596, -249813, -249035, + -248261, -247492, -246727, -245966, -245210, -244458, + -243711, -242967, -242228, -241493, -240763, -240036, + -239314, -238595, -237881, -237170, -236463, -235761, + -235062, -234367, -233676, -232988, -232304, -231624, + -230948, -230275, -229606, -228941, -228279, -227621, + -226966, -226314, -225666, -225022, -224381, -223743, + -223108, -222477, -221849, -221225, -220603, -219985, + -219370, -218758, -218149, -217544, -216941, -216341, + -215745, -215151, -214561, -213973, -213389, -212807, + -212228, -211652, -211079, -210509, -209941, -209376, + -208815, -208255, -207699, -207145, -206594, -206045, + -205500, -204956, -204416, -203878, -203342, -202809, + -202279, -201751, -201226, -200703, -200182, -199664, + -199149, -198636, -198125, -197616, -197110, -196606, + -196105, -195606, -195109, -194614, -194122, -193631, + -193143, -192658, -192174, -191693, -191213, -190736, + -190261, -189789, -189318, -188849, -188382, -187918, + -187455, -186995, -186536, -186080, -185625, -185173, + -184722, -184274, -183827, -183382, -182939, -182498, + -182059, -181622, -181186, -180753, -180321, -179891, + -179463, -179037, -178612, -178190, -177769, -177349, + -176932, -176516, -176102, -175690, -175279, -174870, + -174463, -174057, -173653, -173251, -172850, -172451, + -172053, -171657, -171263, -170870, -170479, -170089, + -169701, -169315, -168930, -168546, -168164, -167784, + -167405, -167027, -166651, -166277, -165904, -165532, + -165162, -164793, -164426, -164060, -163695, -163332, + -162970, -162610, -162251, -161893, -161537, -161182, + -160828, -160476, -160125, -159775, -159427, -159079, + -158734, -158389, -158046, -157704, -157363, -157024, + -156686, -156349, -156013, -155678, -155345, -155013, + -154682, -154352, -154024, -153697, -153370, -153045, + -152722, -152399, -152077, -151757, -151438, -151120, + -150803, -150487, -150172, -149859, -149546, -149235, + -148924, -148615, -148307, -148000, -147693, -147388, + -147084, -146782, -146480, -146179, -145879, -145580, + -145282, -144986, -144690, -144395, -144101, -143808, + -143517, -143226, -142936, -142647, -142359, -142072, + -141786, -141501, -141217, -140934, -140651, -140370, + -140090, -139810, -139532, -139254, -138977, -138701, + -138426, -138152, -137879, -137607, -137335, -137065, + -136795, -136526, -136258, -135991, -135725, -135459, + -135195, -134931, -134668, -134406, -134145, -133884, + -133625, -133366, -133108, -132851, -132594, -132339, + -132084, -131830, -131576, -131324, -131072, -130821, + -130571, -130322, -130073, -129825, -129578, -129332, + -129086, -128841, -128597, -128353, -128111, -127869, + -127627, -127387, -127147, -126908, -126669, -126432, + -126195, -125959, -125723, -125488, -125254, -125020, + -124787, -124555, -124324, -124093, -123863, -123633, + -123404, -123176, -122949, -122722, -122496, -122270, + -122045, -121821, -121597, -121374, -121152, -120930, + -120709, -120489, -120269, -120050, -119831, -119613, + -119396, -119179, -118963, -118747, -118532, -118318, + -118104, -117891, -117678, -117466, -117254, -117044, + -116833, -116623, -116414, -116206, -115998, -115790, + -115583, -115377, -115171, -114966, -114761, -114557, + -114354, -114151, -113948, -113746, -113545, -113344, + -113143, -112944, -112744, -112546, -112347, -112150, + -111952, -111756, -111560, -111364, -111169, -110974, + -110780, -110586, -110393, -110200, -110008, -109817, + -109626, -109435, -109245, -109055, -108866, -108677, + -108489, -108301, -108114, -107927, -107741, -107555, + -107369, -107184, -107000, -106816, -106632, -106449, + -106266, -106084, -105902, -105721, -105540, -105360, + -105180, -105000, -104821, -104643, -104465, -104287, + -104109, -103933, -103756, -103580, -103404, -103229, + -103054, -102880, -102706, -102533, -102360, -102187, + -102015, -101843, -101671, -101500, -101330, -101159, + -100990, -100820, -100651, -100482, -100314, -100146, + -99979, -99812, -99645, -99479, -99313, -99148, + -98982, -98818, -98653, -98489, -98326, -98163, + -98000, -97837, -97675, -97513, -97352, -97191, + -97030, -96870, -96710, -96551, -96391, -96233, + -96074, -95916, -95758, -95601, -95444, -95287, + -95131, -94975, -94819, -94664, -94509, -94354, + -94200, -94046, -93892, -93739, -93586, -93434, + -93281, -93129, -92978, -92826, -92675, -92525, + -92375, -92225, -92075, -91926, -91777, -91628, + -91480, -91332, -91184, -91036, -90889, -90742, + -90596, -90450, -90304, -90158, -90013, -89868, + -89724, -89579, -89435, -89292, -89148, -89005, + -88862, -88720, -88577, -88435, -88294, -88152, + -88011, -87871, -87730, -87590, -87450, -87310, + -87171, -87032, -86893, -86755, -86616, -86479, + -86341, -86204, -86066, -85930, -85793, -85657, + -85521, -85385, -85250, -85114, -84980, -84845, + -84710, -84576, -84443, -84309, -84176, -84043, + -83910, -83777, -83645, -83513, -83381, -83250, + -83118, -82987, -82857, -82726, -82596, -82466, + -82336, -82207, -82078, -81949, -81820, -81691, + -81563, -81435, -81307, -81180, -81053, -80925, + -80799, -80672, -80546, -80420, -80294, -80168, + -80043, -79918, -79793, -79668, -79544, -79420, + -79296, -79172, -79048, -78925, -78802, -78679, + -78557, -78434, -78312, -78190, -78068, -77947, + -77826, -77705, -77584, -77463, -77343, -77223, + -77103, -76983, -76864, -76744, -76625, -76506, + -76388, -76269, -76151, -76033, -75915, -75797, + -75680, -75563, -75446, -75329, -75213, -75096, + -74980, -74864, -74748, -74633, -74517, -74402, + -74287, -74172, -74058, -73944, -73829, -73715, + -73602, -73488, -73375, -73262, -73149, -73036, + -72923, -72811, -72699, -72587, -72475, -72363, + -72252, -72140, -72029, -71918, -71808, -71697, + -71587, -71477, -71367, -71257, -71147, -71038, + -70929, -70820, -70711, -70602, -70494, -70385, + -70277, -70169, -70061, -69954, -69846, -69739, + -69632, -69525, -69418, -69312, -69205, -69099, + -68993, -68887, -68781, -68676, -68570, -68465, + -68360, -68255, -68151, -68046, -67942, -67837, + -67733, -67629, -67526, -67422, -67319, -67216, + -67113, -67010, -66907, -66804, -66702, -66600, + -66498, -66396, -66294, -66192, -66091, -65989, + -65888, -65787, -65686, -65586, -65485, -65385, + -65285, -65185, -65085, -64985, -64885, -64786, + -64687, -64587, -64488, -64389, -64291, -64192, + -64094, -63996, -63897, -63799, -63702, -63604, + -63506, -63409, -63312, -63215, -63118, -63021, + -62924, -62828, -62731, -62635, -62539, -62443, + -62347, -62251, -62156, -62060, -61965, -61870, + -61775, -61680, -61585, -61491, -61396, -61302, + -61208, -61114, -61020, -60926, -60833, -60739, + -60646, -60552, -60459, -60366, -60273, -60181, + -60088, -59996, -59903, -59811, -59719, -59627, + -59535, -59444, -59352, -59261, -59169, -59078, + -58987, -58896, -58805, -58715, -58624, -58534, + -58443, -58353, -58263, -58173, -58083, -57994, + -57904, -57815, -57725, -57636, -57547, -57458, + -57369, -57281, -57192, -57104, -57015, -56927, + -56839, -56751, -56663, -56575, -56487, -56400, + -56312, -56225, -56138, -56051, -55964, -55877, + -55790, -55704, -55617, -55531, -55444, -55358, + -55272, -55186, -55100, -55015, -54929, -54843, + -54758, -54673, -54587, -54502, -54417, -54333, + -54248, -54163, -54079, -53994, -53910, -53826, + -53741, -53657, -53574, -53490, -53406, -53322, + -53239, -53156, -53072, -52989, -52906, -52823, + -52740, -52657, -52575, -52492, -52410, -52327, + -52245, -52163, -52081, -51999, -51917, -51835, + -51754, -51672, -51591, -51509, -51428, -51347, + -51266, -51185, -51104, -51023, -50942, -50862, + -50781, -50701, -50621, -50540, -50460, -50380, + -50300, -50221, -50141, -50061, -49982, -49902, + -49823, -49744, -49664, -49585, -49506, -49427, + -49349, -49270, -49191, -49113, -49034, -48956, + -48878, -48799, -48721, -48643, -48565, -48488, + -48410, -48332, -48255, -48177, -48100, -48022, + -47945, -47868, -47791, -47714, -47637, -47560, + -47484, -47407, -47331, -47254, -47178, -47102, + -47025, -46949, -46873, -46797, -46721, -46646, + -46570, -46494, -46419, -46343, -46268, -46193, + -46118, -46042, -45967, -45892, -45818, -45743, + -45668, -45593, -45519, -45444, -45370, -45296, + -45221, -45147, -45073, -44999, -44925, -44851, + -44778, -44704, -44630, -44557, -44483, -44410, + -44337, -44263, -44190, -44117, -44044, -43971, + -43898, -43826, -43753, -43680, -43608, -43535, + -43463, -43390, -43318, -43246, -43174, -43102, + -43030, -42958, -42886, -42814, -42743, -42671, + -42600, -42528, -42457, -42385, -42314, -42243, + -42172, -42101, -42030, -41959, -41888, -41817, + -41747, -41676, -41605, -41535, -41465, -41394, + -41324, -41254, -41184, -41113, -41043, -40973, + -40904, -40834, -40764, -40694, -40625, -40555, + -40486, -40416, -40347, -40278, -40208, -40139, + -40070, -40001, -39932, -39863, -39794, -39726, + -39657, -39588, -39520, -39451, -39383, -39314, + -39246, -39178, -39110, -39042, -38973, -38905, + -38837, -38770, -38702, -38634, -38566, -38499, + -38431, -38364, -38296, -38229, -38161, -38094, + -38027, -37960, -37893, -37826, -37759, -37692, + -37625, -37558, -37491, -37425, -37358, -37291, + -37225, -37158, -37092, -37026, -36959, -36893, + -36827, -36761, -36695, -36629, -36563, -36497, + -36431, -36365, -36300, -36234, -36168, -36103, + -36037, -35972, -35907, -35841, -35776, -35711, + -35646, -35580, -35515, -35450, -35385, -35321, + -35256, -35191, -35126, -35062, -34997, -34932, + -34868, -34803, -34739, -34675, -34610, -34546, + -34482, -34418, -34354, -34289, -34225, -34162, + -34098, -34034, -33970, -33906, -33843, -33779, + -33715, -33652, -33588, -33525, -33461, -33398, + -33335, -33272, -33208, -33145, -33082, -33019, + -32956, -32893, -32830, -32767, -32705, -32642, + -32579, -32516, -32454, -32391, -32329, -32266, + -32204, -32141, -32079, -32017, -31955, -31892, + -31830, -31768, -31706, -31644, -31582, -31520, + -31458, -31396, -31335, -31273, -31211, -31150, + -31088, -31026, -30965, -30904, -30842, -30781, + -30719, -30658, -30597, -30536, -30474, -30413, + -30352, -30291, -30230, -30169, -30108, -30048, + -29987, -29926, -29865, -29805, -29744, -29683, + -29623, -29562, -29502, -29441, -29381, -29321, + -29260, -29200, -29140, -29080, -29020, -28959, + -28899, -28839, -28779, -28719, -28660, -28600, + -28540, -28480, -28420, -28361, -28301, -28241, + -28182, -28122, -28063, -28003, -27944, -27884, + -27825, -27766, -27707, -27647, -27588, -27529, + -27470, -27411, -27352, -27293, -27234, -27175, + -27116, -27057, -26998, -26940, -26881, -26822, + -26763, -26705, -26646, -26588, -26529, -26471, + -26412, -26354, -26295, -26237, -26179, -26120, + -26062, -26004, -25946, -25888, -25830, -25772, + -25714, -25656, -25598, -25540, -25482, -25424, + -25366, -25308, -25251, -25193, -25135, -25078, + -25020, -24962, -24905, -24847, -24790, -24732, + -24675, -24618, -24560, -24503, -24446, -24389, + -24331, -24274, -24217, -24160, -24103, -24046, + -23989, -23932, -23875, -23818, -23761, -23704, + -23647, -23591, -23534, -23477, -23420, -23364, + -23307, -23250, -23194, -23137, -23081, -23024, + -22968, -22911, -22855, -22799, -22742, -22686, + -22630, -22573, -22517, -22461, -22405, -22349, + -22293, -22237, -22181, -22125, -22069, -22013, + -21957, -21901, -21845, -21789, -21733, -21678, + -21622, -21566, -21510, -21455, -21399, -21343, + -21288, -21232, -21177, -21121, -21066, -21010, + -20955, -20900, -20844, -20789, -20734, -20678, + -20623, -20568, -20513, -20457, -20402, -20347, + -20292, -20237, -20182, -20127, -20072, -20017, + -19962, -19907, -19852, -19797, -19742, -19688, + -19633, -19578, -19523, -19469, -19414, -19359, + -19305, -19250, -19195, -19141, -19086, -19032, + -18977, -18923, -18868, -18814, -18760, -18705, + -18651, -18597, -18542, -18488, -18434, -18380, + -18325, -18271, -18217, -18163, -18109, -18055, + -18001, -17946, -17892, -17838, -17784, -17731, + -17677, -17623, -17569, -17515, -17461, -17407, + -17353, -17300, -17246, -17192, -17138, -17085, + -17031, -16977, -16924, -16870, -16817, -16763, + -16710, -16656, -16603, -16549, -16496, -16442, + -16389, -16335, -16282, -16229, -16175, -16122, + -16069, -16015, -15962, -15909, -15856, -15802, + -15749, -15696, -15643, -15590, -15537, -15484, + -15431, -15378, -15325, -15272, -15219, -15166, + -15113, -15060, -15007, -14954, -14901, -14848, + -14795, -14743, -14690, -14637, -14584, -14531, + -14479, -14426, -14373, -14321, -14268, -14215, + -14163, -14110, -14057, -14005, -13952, -13900, + -13847, -13795, -13742, -13690, -13637, -13585, + -13533, -13480, -13428, -13375, -13323, -13271, + -13218, -13166, -13114, -13062, -13009, -12957, + -12905, -12853, -12800, -12748, -12696, -12644, + -12592, -12540, -12488, -12436, -12383, -12331, + -12279, -12227, -12175, -12123, -12071, -12019, + -11967, -11916, -11864, -11812, -11760, -11708, + -11656, -11604, -11552, -11501, -11449, -11397, + -11345, -11293, -11242, -11190, -11138, -11086, + -11035, -10983, -10931, -10880, -10828, -10777, + -10725, -10673, -10622, -10570, -10519, -10467, + -10415, -10364, -10312, -10261, -10209, -10158, + -10106, -10055, -10004, -9952, -9901, -9849, + -9798, -9747, -9695, -9644, -9592, -9541, + -9490, -9438, -9387, -9336, -9285, -9233, + -9182, -9131, -9080, -9028, -8977, -8926, + -8875, -8824, -8772, -8721, -8670, -8619, + -8568, -8517, -8466, -8414, -8363, -8312, + -8261, -8210, -8159, -8108, -8057, -8006, + -7955, -7904, -7853, -7802, -7751, -7700, + -7649, -7598, -7547, -7496, -7445, -7395, + -7344, -7293, -7242, -7191, -7140, -7089, + -7038, -6988, -6937, -6886, -6835, -6784, + -6733, -6683, -6632, -6581, -6530, -6480, + -6429, -6378, -6327, -6277, -6226, -6175, + -6124, -6074, -6023, -5972, -5922, -5871, + -5820, -5770, -5719, -5668, -5618, -5567, + -5517, -5466, -5415, -5365, -5314, -5264, + -5213, -5162, -5112, -5061, -5011, -4960, + -4910, -4859, -4808, -4758, -4707, -4657, + -4606, -4556, -4505, -4455, -4404, -4354, + -4303, -4253, -4202, -4152, -4101, -4051, + -4001, -3950, -3900, -3849, -3799, -3748, + -3698, -3648, -3597, -3547, -3496, -3446, + -3395, -3345, -3295, -3244, -3194, -3144, + -3093, -3043, -2992, -2942, -2892, -2841, + -2791, -2741, -2690, -2640, -2590, -2539, + -2489, -2439, -2388, -2338, -2288, -2237, + -2187, -2137, -2086, -2036, -1986, -1935, + -1885, -1835, -1784, -1734, -1684, -1633, + -1583, -1533, -1483, -1432, -1382, -1332, + -1281, -1231, -1181, -1131, -1080, -1030, + -980, -929, -879, -829, -779, -728, + -678, -628, -578, -527, -477, -427, + -376, -326, -276, -226, -175, -125, + -75, -25, 25, 75, 125, 175, + 226, 276, 326, 376, 427, 477, + 527, 578, 628, 678, 728, 779, + 829, 879, 929, 980, 1030, 1080, + 1131, 1181, 1231, 1281, 1332, 1382, + 1432, 1483, 1533, 1583, 1633, 1684, + 1734, 1784, 1835, 1885, 1935, 1986, + 2036, 2086, 2137, 2187, 2237, 2288, + 2338, 2388, 2439, 2489, 2539, 2590, + 2640, 2690, 2741, 2791, 2841, 2892, + 2942, 2992, 3043, 3093, 3144, 3194, + 3244, 3295, 3345, 3395, 3446, 3496, + 3547, 3597, 3648, 3698, 3748, 3799, + 3849, 3900, 3950, 4001, 4051, 4101, + 4152, 4202, 4253, 4303, 4354, 4404, + 4455, 4505, 4556, 4606, 4657, 4707, + 4758, 4808, 4859, 4910, 4960, 5011, + 5061, 5112, 5162, 5213, 5264, 5314, + 5365, 5415, 5466, 5517, 5567, 5618, + 5668, 5719, 5770, 5820, 5871, 5922, + 5972, 6023, 6074, 6124, 6175, 6226, + 6277, 6327, 6378, 6429, 6480, 6530, + 6581, 6632, 6683, 6733, 6784, 6835, + 6886, 6937, 6988, 7038, 7089, 7140, + 7191, 7242, 7293, 7344, 7395, 7445, + 7496, 7547, 7598, 7649, 7700, 7751, + 7802, 7853, 7904, 7955, 8006, 8057, + 8108, 8159, 8210, 8261, 8312, 8363, + 8414, 8466, 8517, 8568, 8619, 8670, + 8721, 8772, 8824, 8875, 8926, 8977, + 9028, 9080, 9131, 9182, 9233, 9285, + 9336, 9387, 9438, 9490, 9541, 9592, + 9644, 9695, 9747, 9798, 9849, 9901, + 9952, 10004, 10055, 10106, 10158, 10209, + 10261, 10312, 10364, 10415, 10467, 10519, + 10570, 10622, 10673, 10725, 10777, 10828, + 10880, 10931, 10983, 11035, 11086, 11138, + 11190, 11242, 11293, 11345, 11397, 11449, + 11501, 11552, 11604, 11656, 11708, 11760, + 11812, 11864, 11916, 11967, 12019, 12071, + 12123, 12175, 12227, 12279, 12331, 12383, + 12436, 12488, 12540, 12592, 12644, 12696, + 12748, 12800, 12853, 12905, 12957, 13009, + 13062, 13114, 13166, 13218, 13271, 13323, + 13375, 13428, 13480, 13533, 13585, 13637, + 13690, 13742, 13795, 13847, 13900, 13952, + 14005, 14057, 14110, 14163, 14215, 14268, + 14321, 14373, 14426, 14479, 14531, 14584, + 14637, 14690, 14743, 14795, 14848, 14901, + 14954, 15007, 15060, 15113, 15166, 15219, + 15272, 15325, 15378, 15431, 15484, 15537, + 15590, 15643, 15696, 15749, 15802, 15856, + 15909, 15962, 16015, 16069, 16122, 16175, + 16229, 16282, 16335, 16389, 16442, 16496, + 16549, 16603, 16656, 16710, 16763, 16817, + 16870, 16924, 16977, 17031, 17085, 17138, + 17192, 17246, 17300, 17353, 17407, 17461, + 17515, 17569, 17623, 17677, 17731, 17784, + 17838, 17892, 17946, 18001, 18055, 18109, + 18163, 18217, 18271, 18325, 18380, 18434, + 18488, 18542, 18597, 18651, 18705, 18760, + 18814, 18868, 18923, 18977, 19032, 19086, + 19141, 19195, 19250, 19305, 19359, 19414, + 19469, 19523, 19578, 19633, 19688, 19742, + 19797, 19852, 19907, 19962, 20017, 20072, + 20127, 20182, 20237, 20292, 20347, 20402, + 20457, 20513, 20568, 20623, 20678, 20734, + 20789, 20844, 20900, 20955, 21010, 21066, + 21121, 21177, 21232, 21288, 21343, 21399, + 21455, 21510, 21566, 21622, 21678, 21733, + 21789, 21845, 21901, 21957, 22013, 22069, + 22125, 22181, 22237, 22293, 22349, 22405, + 22461, 22517, 22573, 22630, 22686, 22742, + 22799, 22855, 22911, 22968, 23024, 23081, + 23137, 23194, 23250, 23307, 23364, 23420, + 23477, 23534, 23591, 23647, 23704, 23761, + 23818, 23875, 23932, 23989, 24046, 24103, + 24160, 24217, 24274, 24331, 24389, 24446, + 24503, 24560, 24618, 24675, 24732, 24790, + 24847, 24905, 24962, 25020, 25078, 25135, + 25193, 25251, 25308, 25366, 25424, 25482, + 25540, 25598, 25656, 25714, 25772, 25830, + 25888, 25946, 26004, 26062, 26120, 26179, + 26237, 26295, 26354, 26412, 26471, 26529, + 26588, 26646, 26705, 26763, 26822, 26881, + 26940, 26998, 27057, 27116, 27175, 27234, + 27293, 27352, 27411, 27470, 27529, 27588, + 27647, 27707, 27766, 27825, 27884, 27944, + 28003, 28063, 28122, 28182, 28241, 28301, + 28361, 28420, 28480, 28540, 28600, 28660, + 28719, 28779, 28839, 28899, 28959, 29020, + 29080, 29140, 29200, 29260, 29321, 29381, + 29441, 29502, 29562, 29623, 29683, 29744, + 29805, 29865, 29926, 29987, 30048, 30108, + 30169, 30230, 30291, 30352, 30413, 30474, + 30536, 30597, 30658, 30719, 30781, 30842, + 30904, 30965, 31026, 31088, 31150, 31211, + 31273, 31335, 31396, 31458, 31520, 31582, + 31644, 31706, 31768, 31830, 31892, 31955, + 32017, 32079, 32141, 32204, 32266, 32329, + 32391, 32454, 32516, 32579, 32642, 32705, + 32767, 32830, 32893, 32956, 33019, 33082, + 33145, 33208, 33272, 33335, 33398, 33461, + 33525, 33588, 33652, 33715, 33779, 33843, + 33906, 33970, 34034, 34098, 34162, 34225, + 34289, 34354, 34418, 34482, 34546, 34610, + 34675, 34739, 34803, 34868, 34932, 34997, + 35062, 35126, 35191, 35256, 35321, 35385, + 35450, 35515, 35580, 35646, 35711, 35776, + 35841, 35907, 35972, 36037, 36103, 36168, + 36234, 36300, 36365, 36431, 36497, 36563, + 36629, 36695, 36761, 36827, 36893, 36959, + 37026, 37092, 37158, 37225, 37291, 37358, + 37425, 37491, 37558, 37625, 37692, 37759, + 37826, 37893, 37960, 38027, 38094, 38161, + 38229, 38296, 38364, 38431, 38499, 38566, + 38634, 38702, 38770, 38837, 38905, 38973, + 39042, 39110, 39178, 39246, 39314, 39383, + 39451, 39520, 39588, 39657, 39726, 39794, + 39863, 39932, 40001, 40070, 40139, 40208, + 40278, 40347, 40416, 40486, 40555, 40625, + 40694, 40764, 40834, 40904, 40973, 41043, + 41113, 41184, 41254, 41324, 41394, 41465, + 41535, 41605, 41676, 41747, 41817, 41888, + 41959, 42030, 42101, 42172, 42243, 42314, + 42385, 42457, 42528, 42600, 42671, 42743, + 42814, 42886, 42958, 43030, 43102, 43174, + 43246, 43318, 43390, 43463, 43535, 43608, + 43680, 43753, 43826, 43898, 43971, 44044, + 44117, 44190, 44263, 44337, 44410, 44483, + 44557, 44630, 44704, 44778, 44851, 44925, + 44999, 45073, 45147, 45221, 45296, 45370, + 45444, 45519, 45593, 45668, 45743, 45818, + 45892, 45967, 46042, 46118, 46193, 46268, + 46343, 46419, 46494, 46570, 46646, 46721, + 46797, 46873, 46949, 47025, 47102, 47178, + 47254, 47331, 47407, 47484, 47560, 47637, + 47714, 47791, 47868, 47945, 48022, 48100, + 48177, 48255, 48332, 48410, 48488, 48565, + 48643, 48721, 48799, 48878, 48956, 49034, + 49113, 49191, 49270, 49349, 49427, 49506, + 49585, 49664, 49744, 49823, 49902, 49982, + 50061, 50141, 50221, 50300, 50380, 50460, + 50540, 50621, 50701, 50781, 50862, 50942, + 51023, 51104, 51185, 51266, 51347, 51428, + 51509, 51591, 51672, 51754, 51835, 51917, + 51999, 52081, 52163, 52245, 52327, 52410, + 52492, 52575, 52657, 52740, 52823, 52906, + 52989, 53072, 53156, 53239, 53322, 53406, + 53490, 53574, 53657, 53741, 53826, 53910, + 53994, 54079, 54163, 54248, 54333, 54417, + 54502, 54587, 54673, 54758, 54843, 54929, + 55015, 55100, 55186, 55272, 55358, 55444, + 55531, 55617, 55704, 55790, 55877, 55964, + 56051, 56138, 56225, 56312, 56400, 56487, + 56575, 56663, 56751, 56839, 56927, 57015, + 57104, 57192, 57281, 57369, 57458, 57547, + 57636, 57725, 57815, 57904, 57994, 58083, + 58173, 58263, 58353, 58443, 58534, 58624, + 58715, 58805, 58896, 58987, 59078, 59169, + 59261, 59352, 59444, 59535, 59627, 59719, + 59811, 59903, 59996, 60088, 60181, 60273, + 60366, 60459, 60552, 60646, 60739, 60833, + 60926, 61020, 61114, 61208, 61302, 61396, + 61491, 61585, 61680, 61775, 61870, 61965, + 62060, 62156, 62251, 62347, 62443, 62539, + 62635, 62731, 62828, 62924, 63021, 63118, + 63215, 63312, 63409, 63506, 63604, 63702, + 63799, 63897, 63996, 64094, 64192, 64291, + 64389, 64488, 64587, 64687, 64786, 64885, + 64985, 65085, 65185, 65285, 65385, 65485, + 65586, 65686, 65787, 65888, 65989, 66091, + 66192, 66294, 66396, 66498, 66600, 66702, + 66804, 66907, 67010, 67113, 67216, 67319, + 67422, 67526, 67629, 67733, 67837, 67942, + 68046, 68151, 68255, 68360, 68465, 68570, + 68676, 68781, 68887, 68993, 69099, 69205, + 69312, 69418, 69525, 69632, 69739, 69846, + 69954, 70061, 70169, 70277, 70385, 70494, + 70602, 70711, 70820, 70929, 71038, 71147, + 71257, 71367, 71477, 71587, 71697, 71808, + 71918, 72029, 72140, 72252, 72363, 72475, + 72587, 72699, 72811, 72923, 73036, 73149, + 73262, 73375, 73488, 73602, 73715, 73829, + 73944, 74058, 74172, 74287, 74402, 74517, + 74633, 74748, 74864, 74980, 75096, 75213, + 75329, 75446, 75563, 75680, 75797, 75915, + 76033, 76151, 76269, 76388, 76506, 76625, + 76744, 76864, 76983, 77103, 77223, 77343, + 77463, 77584, 77705, 77826, 77947, 78068, + 78190, 78312, 78434, 78557, 78679, 78802, + 78925, 79048, 79172, 79296, 79420, 79544, + 79668, 79793, 79918, 80043, 80168, 80294, + 80420, 80546, 80672, 80799, 80925, 81053, + 81180, 81307, 81435, 81563, 81691, 81820, + 81949, 82078, 82207, 82336, 82466, 82596, + 82726, 82857, 82987, 83118, 83250, 83381, + 83513, 83645, 83777, 83910, 84043, 84176, + 84309, 84443, 84576, 84710, 84845, 84980, + 85114, 85250, 85385, 85521, 85657, 85793, + 85930, 86066, 86204, 86341, 86479, 86616, + 86755, 86893, 87032, 87171, 87310, 87450, + 87590, 87730, 87871, 88011, 88152, 88294, + 88435, 88577, 88720, 88862, 89005, 89148, + 89292, 89435, 89579, 89724, 89868, 90013, + 90158, 90304, 90450, 90596, 90742, 90889, + 91036, 91184, 91332, 91480, 91628, 91777, + 91926, 92075, 92225, 92375, 92525, 92675, + 92826, 92978, 93129, 93281, 93434, 93586, + 93739, 93892, 94046, 94200, 94354, 94509, + 94664, 94819, 94975, 95131, 95287, 95444, + 95601, 95758, 95916, 96074, 96233, 96391, + 96551, 96710, 96870, 97030, 97191, 97352, + 97513, 97675, 97837, 98000, 98163, 98326, + 98489, 98653, 98818, 98982, 99148, 99313, + 99479, 99645, 99812, 99979, 100146, 100314, + 100482, 100651, 100820, 100990, 101159, 101330, + 101500, 101671, 101843, 102015, 102187, 102360, + 102533, 102706, 102880, 103054, 103229, 103404, + 103580, 103756, 103933, 104109, 104287, 104465, + 104643, 104821, 105000, 105180, 105360, 105540, + 105721, 105902, 106084, 106266, 106449, 106632, + 106816, 107000, 107184, 107369, 107555, 107741, + 107927, 108114, 108301, 108489, 108677, 108866, + 109055, 109245, 109435, 109626, 109817, 110008, + 110200, 110393, 110586, 110780, 110974, 111169, + 111364, 111560, 111756, 111952, 112150, 112347, + 112546, 112744, 112944, 113143, 113344, 113545, + 113746, 113948, 114151, 114354, 114557, 114761, + 114966, 115171, 115377, 115583, 115790, 115998, + 116206, 116414, 116623, 116833, 117044, 117254, + 117466, 117678, 117891, 118104, 118318, 118532, + 118747, 118963, 119179, 119396, 119613, 119831, + 120050, 120269, 120489, 120709, 120930, 121152, + 121374, 121597, 121821, 122045, 122270, 122496, + 122722, 122949, 123176, 123404, 123633, 123863, + 124093, 124324, 124555, 124787, 125020, 125254, + 125488, 125723, 125959, 126195, 126432, 126669, + 126908, 127147, 127387, 127627, 127869, 128111, + 128353, 128597, 128841, 129086, 129332, 129578, + 129825, 130073, 130322, 130571, 130821, 131072, + 131324, 131576, 131830, 132084, 132339, 132594, + 132851, 133108, 133366, 133625, 133884, 134145, + 134406, 134668, 134931, 135195, 135459, 135725, + 135991, 136258, 136526, 136795, 137065, 137335, + 137607, 137879, 138152, 138426, 138701, 138977, + 139254, 139532, 139810, 140090, 140370, 140651, + 140934, 141217, 141501, 141786, 142072, 142359, + 142647, 142936, 143226, 143517, 143808, 144101, + 144395, 144690, 144986, 145282, 145580, 145879, + 146179, 146480, 146782, 147084, 147388, 147693, + 148000, 148307, 148615, 148924, 149235, 149546, + 149859, 150172, 150487, 150803, 151120, 151438, + 151757, 152077, 152399, 152722, 153045, 153370, + 153697, 154024, 154352, 154682, 155013, 155345, + 155678, 156013, 156349, 156686, 157024, 157363, + 157704, 158046, 158389, 158734, 159079, 159427, + 159775, 160125, 160476, 160828, 161182, 161537, + 161893, 162251, 162610, 162970, 163332, 163695, + 164060, 164426, 164793, 165162, 165532, 165904, + 166277, 166651, 167027, 167405, 167784, 168164, + 168546, 168930, 169315, 169701, 170089, 170479, + 170870, 171263, 171657, 172053, 172451, 172850, + 173251, 173653, 174057, 174463, 174870, 175279, + 175690, 176102, 176516, 176932, 177349, 177769, + 178190, 178612, 179037, 179463, 179891, 180321, + 180753, 181186, 181622, 182059, 182498, 182939, + 183382, 183827, 184274, 184722, 185173, 185625, + 186080, 186536, 186995, 187455, 187918, 188382, + 188849, 189318, 189789, 190261, 190736, 191213, + 191693, 192174, 192658, 193143, 193631, 194122, + 194614, 195109, 195606, 196105, 196606, 197110, + 197616, 198125, 198636, 199149, 199664, 200182, + 200703, 201226, 201751, 202279, 202809, 203342, + 203878, 204416, 204956, 205500, 206045, 206594, + 207145, 207699, 208255, 208815, 209376, 209941, + 210509, 211079, 211652, 212228, 212807, 213389, + 213973, 214561, 215151, 215745, 216341, 216941, + 217544, 218149, 218758, 219370, 219985, 220603, + 221225, 221849, 222477, 223108, 223743, 224381, + 225022, 225666, 226314, 226966, 227621, 228279, + 228941, 229606, 230275, 230948, 231624, 232304, + 232988, 233676, 234367, 235062, 235761, 236463, + 237170, 237881, 238595, 239314, 240036, 240763, + 241493, 242228, 242967, 243711, 244458, 245210, + 245966, 246727, 247492, 248261, 249035, 249813, + 250596, 251384, 252176, 252973, 253774, 254581, + 255392, 256208, 257029, 257855, 258686, 259522, + 260363, 261209, 262060, 262917, 263779, 264646, + 265519, 266397, 267280, 268169, 269064, 269965, + 270871, 271782, 272700, 273624, 274553, 275489, + 276430, 277378, 278332, 279292, 280258, 281231, + 282210, 283195, 284188, 285186, 286192, 287204, + 288223, 289249, 290282, 291322, 292369, 293423, + 294485, 295554, 296630, 297714, 298805, 299904, + 301011, 302126, 303248, 304379, 305517, 306664, + 307819, 308983, 310154, 311335, 312524, 313721, + 314928, 316143, 317368, 318601, 319844, 321097, + 322358, 323629, 324910, 326201, 327502, 328812, + 330133, 331464, 332805, 334157, 335519, 336892, + 338276, 339671, 341078, 342495, 343924, 345364, + 346816, 348280, 349756, 351244, 352744, 354257, + 355783, 357321, 358872, 360436, 362013, 363604, + 365208, 366826, 368459, 370105, 371765, 373440, + 375130, 376835, 378555, 380290, 382040, 383807, + 385589, 387387, 389202, 391034, 392882, 394747, + 396630, 398530, 400448, 402384, 404338, 406311, + 408303, 410314, 412344, 414395, 416465, 418555, + 420666, 422798, 424951, 427125, 429321, 431540, + 433781, 436045, 438332, 440643, 442978, 445337, + 447720, 450129, 452564, 455024, 457511, 460024, + 462565, 465133, 467730, 470355, 473009, 475692, + 478406, 481150, 483925, 486732, 489571, 492443, + 495348, 498287, 501261, 504269, 507313, 510394, + 513512, 516667, 519861, 523094, 526366, 529680, + 533034, 536431, 539870, 543354, 546881, 550455, + 554074, 557741, 561456, 565221, 569035, 572901, + 576818, 580789, 584815, 588896, 593033, 597229, + 601483, 605798, 610174, 614613, 619117, 623686, + 628323, 633028, 637803, 642651, 647572, 652568, + 657640, 662792, 668024, 673338, 678737, 684223, + 689797, 695462, 701219, 707072, 713023, 719074, + 725227, 731486, 737853, 744331, 750922, 757631, + 764460, 771411, 778490, 785699, 793041, 800521, + 808143, 815910, 823827, 831898, 840127, 848520, + 857081, 865817, 874730, 883829, 893117, 902602, + 912289, 922186, 932298, 942633, 953199, 964003, + 975054, 986361, 997931, 1009774, 1021901, 1034322, + 1047046, 1060087, 1073455, 1087164, 1101225, 1115654, + 1130465, 1145673, 1161294, 1177345, 1193846, 1210813, + 1228269, 1246234, 1264730, 1283783, 1303416, 1323658, + 1344537, 1366084, 1388330, 1411312, 1435065, 1459630, + 1485049, 1511367, 1538632, 1566898, 1596220, 1626658, + 1658278, 1691149, 1725348, 1760956, 1798063, 1836758, + 1877161, 1919378, 1963536, 2009771, 2058233, 2109087, + 2162516, 2218719, 2277919, 2340362, 2406322, 2476104, + 2550052, 2628549, 2712030, 2800983, 2895966, 2997613, + 3106651, 3223918, 3350381, 3487165, 3635590, 3797206, + 3973855, 4167737, 4381502, 4618375, 4882318, 5178251, + 5512368, 5892567, 6329090, 6835455, 7429880, 8137527, + 8994149, 10052327, 11392683, 13145455, 15535599, 18988036, + 24413316, 34178904, 56965752, 170910304, }; - const fixed_t finesine[10240] = { - 25,75,125,175,226,276,326,376, - 427,477,527,578,628,678,728,779, - 829,879,929,980,1030,1080,1130,1181, - 1231,1281,1331,1382,1432,1482,1532,1583, - 1633,1683,1733,1784,1834,1884,1934,1985, - 2035,2085,2135,2186,2236,2286,2336,2387, - 2437,2487,2537,2587,2638,2688,2738,2788, - 2839,2889,2939,2989,3039,3090,3140,3190, - 3240,3291,3341,3391,3441,3491,3541,3592, - 3642,3692,3742,3792,3843,3893,3943,3993, - 4043,4093,4144,4194,4244,4294,4344,4394, - 4445,4495,4545,4595,4645,4695,4745,4796, - 4846,4896,4946,4996,5046,5096,5146,5197, - 5247,5297,5347,5397,5447,5497,5547,5597, - 5647,5697,5748,5798,5848,5898,5948,5998, - 6048,6098,6148,6198,6248,6298,6348,6398, - 6448,6498,6548,6598,6648,6698,6748,6798, - 6848,6898,6948,6998,7048,7098,7148,7198, - 7248,7298,7348,7398,7448,7498,7548,7598, - 7648,7697,7747,7797,7847,7897,7947,7997, - 8047,8097,8147,8196,8246,8296,8346,8396, - 8446,8496,8545,8595,8645,8695,8745,8794, - 8844,8894,8944,8994,9043,9093,9143,9193, - 9243,9292,9342,9392,9442,9491,9541,9591, - 9640,9690,9740,9790,9839,9889,9939,9988, - 10038,10088,10137,10187,10237,10286,10336,10386, - 10435,10485,10534,10584,10634,10683,10733,10782, - 10832,10882,10931,10981,11030,11080,11129,11179, - 11228,11278,11327,11377,11426,11476,11525,11575, - 11624,11674,11723,11773,11822,11872,11921,11970, - 12020,12069,12119,12168,12218,12267,12316,12366, - 12415,12464,12514,12563,12612,12662,12711,12760, - 12810,12859,12908,12957,13007,13056,13105,13154, - 13204,13253,13302,13351,13401,13450,13499,13548, - 13597,13647,13696,13745,13794,13843,13892,13941, - 13990,14040,14089,14138,14187,14236,14285,14334, - 14383,14432,14481,14530,14579,14628,14677,14726, - 14775,14824,14873,14922,14971,15020,15069,15118, - 15167,15215,15264,15313,15362,15411,15460,15509, - 15557,15606,15655,15704,15753,15802,15850,15899, - 15948,15997,16045,16094,16143,16191,16240,16289, - 16338,16386,16435,16484,16532,16581,16629,16678, - 16727,16775,16824,16872,16921,16970,17018,17067, - 17115,17164,17212,17261,17309,17358,17406,17455, - 17503,17551,17600,17648,17697,17745,17793,17842, - 17890,17939,17987,18035,18084,18132,18180,18228, - 18277,18325,18373,18421,18470,18518,18566,18614, - 18663,18711,18759,18807,18855,18903,18951,19000, - 19048,19096,19144,19192,19240,19288,19336,19384, - 19432,19480,19528,19576,19624,19672,19720,19768, - 19816,19864,19912,19959,20007,20055,20103,20151, - 20199,20246,20294,20342,20390,20438,20485,20533, - 20581,20629,20676,20724,20772,20819,20867,20915, - 20962,21010,21057,21105,21153,21200,21248,21295, - 21343,21390,21438,21485,21533,21580,21628,21675, - 21723,21770,21817,21865,21912,21960,22007,22054, - 22102,22149,22196,22243,22291,22338,22385,22433, - 22480,22527,22574,22621,22668,22716,22763,22810, - 22857,22904,22951,22998,23045,23092,23139,23186, - 23233,23280,23327,23374,23421,23468,23515,23562, - 23609,23656,23703,23750,23796,23843,23890,23937, - 23984,24030,24077,24124,24171,24217,24264,24311, - 24357,24404,24451,24497,24544,24591,24637,24684, - 24730,24777,24823,24870,24916,24963,25009,25056, - 25102,25149,25195,25241,25288,25334,25381,25427, - 25473,25520,25566,25612,25658,25705,25751,25797, - 25843,25889,25936,25982,26028,26074,26120,26166, - 26212,26258,26304,26350,26396,26442,26488,26534, - 26580,26626,26672,26718,26764,26810,26856,26902, - 26947,26993,27039,27085,27131,27176,27222,27268, - 27313,27359,27405,27450,27496,27542,27587,27633, - 27678,27724,27770,27815,27861,27906,27952,27997, - 28042,28088,28133,28179,28224,28269,28315,28360, - 28405,28451,28496,28541,28586,28632,28677,28722, - 28767,28812,28858,28903,28948,28993,29038,29083, - 29128,29173,29218,29263,29308,29353,29398,29443, - 29488,29533,29577,29622,29667,29712,29757,29801, - 29846,29891,29936,29980,30025,30070,30114,30159, - 30204,30248,30293,30337,30382,30426,30471,30515, - 30560,30604,30649,30693,30738,30782,30826,30871, - 30915,30959,31004,31048,31092,31136,31181,31225, - 31269,31313,31357,31402,31446,31490,31534,31578, - 31622,31666,31710,31754,31798,31842,31886,31930, - 31974,32017,32061,32105,32149,32193,32236,32280, - 32324,32368,32411,32455,32499,32542,32586,32630, - 32673,32717,32760,32804,32847,32891,32934,32978, - 33021,33065,33108,33151,33195,33238,33281,33325, - 33368,33411,33454,33498,33541,33584,33627,33670, - 33713,33756,33799,33843,33886,33929,33972,34015, - 34057,34100,34143,34186,34229,34272,34315,34358, - 34400,34443,34486,34529,34571,34614,34657,34699, - 34742,34785,34827,34870,34912,34955,34997,35040, - 35082,35125,35167,35210,35252,35294,35337,35379, - 35421,35464,35506,35548,35590,35633,35675,35717, - 35759,35801,35843,35885,35927,35969,36011,36053, - 36095,36137,36179,36221,36263,36305,36347,36388, - 36430,36472,36514,36555,36597,36639,36681,36722, - 36764,36805,36847,36889,36930,36972,37013,37055, - 37096,37137,37179,37220,37262,37303,37344,37386, - 37427,37468,37509,37551,37592,37633,37674,37715, - 37756,37797,37838,37879,37920,37961,38002,38043, - 38084,38125,38166,38207,38248,38288,38329,38370, - 38411,38451,38492,38533,38573,38614,38655,38695, - 38736,38776,38817,38857,38898,38938,38979,39019, - 39059,39100,39140,39180,39221,39261,39301,39341, - 39382,39422,39462,39502,39542,39582,39622,39662, - 39702,39742,39782,39822,39862,39902,39942,39982, - 40021,40061,40101,40141,40180,40220,40260,40300, - 40339,40379,40418,40458,40497,40537,40576,40616, - 40655,40695,40734,40773,40813,40852,40891,40931, - 40970,41009,41048,41087,41127,41166,41205,41244, - 41283,41322,41361,41400,41439,41478,41517,41556, - 41595,41633,41672,41711,41750,41788,41827,41866, - 41904,41943,41982,42020,42059,42097,42136,42174, - 42213,42251,42290,42328,42366,42405,42443,42481, - 42520,42558,42596,42634,42672,42711,42749,42787, - 42825,42863,42901,42939,42977,43015,43053,43091, - 43128,43166,43204,43242,43280,43317,43355,43393, - 43430,43468,43506,43543,43581,43618,43656,43693, - 43731,43768,43806,43843,43880,43918,43955,43992, - 44029,44067,44104,44141,44178,44215,44252,44289, - 44326,44363,44400,44437,44474,44511,44548,44585, - 44622,44659,44695,44732,44769,44806,44842,44879, - 44915,44952,44989,45025,45062,45098,45135,45171, - 45207,45244,45280,45316,45353,45389,45425,45462, - 45498,45534,45570,45606,45642,45678,45714,45750, - 45786,45822,45858,45894,45930,45966,46002,46037, - 46073,46109,46145,46180,46216,46252,46287,46323, - 46358,46394,46429,46465,46500,46536,46571,46606, - 46642,46677,46712,46747,46783,46818,46853,46888, - 46923,46958,46993,47028,47063,47098,47133,47168, - 47203,47238,47273,47308,47342,47377,47412,47446, - 47481,47516,47550,47585,47619,47654,47688,47723, - 47757,47792,47826,47860,47895,47929,47963,47998, - 48032,48066,48100,48134,48168,48202,48237,48271, - 48305,48338,48372,48406,48440,48474,48508,48542, - 48575,48609,48643,48676,48710,48744,48777,48811, - 48844,48878,48911,48945,48978,49012,49045,49078, - 49112,49145,49178,49211,49244,49278,49311,49344, - 49377,49410,49443,49476,49509,49542,49575,49608, - 49640,49673,49706,49739,49771,49804,49837,49869, - 49902,49935,49967,50000,50032,50065,50097,50129, - 50162,50194,50226,50259,50291,50323,50355,50387, - 50420,50452,50484,50516,50548,50580,50612,50644, - 50675,50707,50739,50771,50803,50834,50866,50898, - 50929,50961,50993,51024,51056,51087,51119,51150, - 51182,51213,51244,51276,51307,51338,51369,51401, - 51432,51463,51494,51525,51556,51587,51618,51649, - 51680,51711,51742,51773,51803,51834,51865,51896, - 51926,51957,51988,52018,52049,52079,52110,52140, - 52171,52201,52231,52262,52292,52322,52353,52383, - 52413,52443,52473,52503,52534,52564,52594,52624, - 52653,52683,52713,52743,52773,52803,52832,52862, - 52892,52922,52951,52981,53010,53040,53069,53099, - 53128,53158,53187,53216,53246,53275,53304,53334, - 53363,53392,53421,53450,53479,53508,53537,53566, - 53595,53624,53653,53682,53711,53739,53768,53797, - 53826,53854,53883,53911,53940,53969,53997,54026, - 54054,54082,54111,54139,54167,54196,54224,54252, - 54280,54308,54337,54365,54393,54421,54449,54477, - 54505,54533,54560,54588,54616,54644,54672,54699, - 54727,54755,54782,54810,54837,54865,54892,54920, - 54947,54974,55002,55029,55056,55084,55111,55138, - 55165,55192,55219,55246,55274,55300,55327,55354, - 55381,55408,55435,55462,55489,55515,55542,55569, - 55595,55622,55648,55675,55701,55728,55754,55781, - 55807,55833,55860,55886,55912,55938,55965,55991, - 56017,56043,56069,56095,56121,56147,56173,56199, - 56225,56250,56276,56302,56328,56353,56379,56404, - 56430,56456,56481,56507,56532,56557,56583,56608, - 56633,56659,56684,56709,56734,56760,56785,56810, - 56835,56860,56885,56910,56935,56959,56984,57009, - 57034,57059,57083,57108,57133,57157,57182,57206, - 57231,57255,57280,57304,57329,57353,57377,57402, - 57426,57450,57474,57498,57522,57546,57570,57594, - 57618,57642,57666,57690,57714,57738,57762,57785, - 57809,57833,57856,57880,57903,57927,57950,57974, - 57997,58021,58044,58067,58091,58114,58137,58160, - 58183,58207,58230,58253,58276,58299,58322,58345, - 58367,58390,58413,58436,58459,58481,58504,58527, - 58549,58572,58594,58617,58639,58662,58684,58706, - 58729,58751,58773,58795,58818,58840,58862,58884, - 58906,58928,58950,58972,58994,59016,59038,59059, - 59081,59103,59125,59146,59168,59190,59211,59233, - 59254,59276,59297,59318,59340,59361,59382,59404, - 59425,59446,59467,59488,59509,59530,59551,59572, - 59593,59614,59635,59656,59677,59697,59718,59739, - 59759,59780,59801,59821,59842,59862,59883,59903, - 59923,59944,59964,59984,60004,60025,60045,60065, - 60085,60105,60125,60145,60165,60185,60205,60225, - 60244,60264,60284,60304,60323,60343,60363,60382, - 60402,60421,60441,60460,60479,60499,60518,60537, - 60556,60576,60595,60614,60633,60652,60671,60690, - 60709,60728,60747,60766,60785,60803,60822,60841, - 60859,60878,60897,60915,60934,60952,60971,60989, - 61007,61026,61044,61062,61081,61099,61117,61135, - 61153,61171,61189,61207,61225,61243,61261,61279, - 61297,61314,61332,61350,61367,61385,61403,61420, - 61438,61455,61473,61490,61507,61525,61542,61559, - 61577,61594,61611,61628,61645,61662,61679,61696, - 61713,61730,61747,61764,61780,61797,61814,61831, - 61847,61864,61880,61897,61913,61930,61946,61963, - 61979,61995,62012,62028,62044,62060,62076,62092, - 62108,62125,62141,62156,62172,62188,62204,62220, - 62236,62251,62267,62283,62298,62314,62329,62345, - 62360,62376,62391,62407,62422,62437,62453,62468, - 62483,62498,62513,62528,62543,62558,62573,62588, - 62603,62618,62633,62648,62662,62677,62692,62706, - 62721,62735,62750,62764,62779,62793,62808,62822, - 62836,62850,62865,62879,62893,62907,62921,62935, - 62949,62963,62977,62991,63005,63019,63032,63046, - 63060,63074,63087,63101,63114,63128,63141,63155, - 63168,63182,63195,63208,63221,63235,63248,63261, - 63274,63287,63300,63313,63326,63339,63352,63365, - 63378,63390,63403,63416,63429,63441,63454,63466, - 63479,63491,63504,63516,63528,63541,63553,63565, - 63578,63590,63602,63614,63626,63638,63650,63662, - 63674,63686,63698,63709,63721,63733,63745,63756, - 63768,63779,63791,63803,63814,63825,63837,63848, - 63859,63871,63882,63893,63904,63915,63927,63938, - 63949,63960,63971,63981,63992,64003,64014,64025, - 64035,64046,64057,64067,64078,64088,64099,64109, - 64120,64130,64140,64151,64161,64171,64181,64192, - 64202,64212,64222,64232,64242,64252,64261,64271, - 64281,64291,64301,64310,64320,64330,64339,64349, - 64358,64368,64377,64387,64396,64405,64414,64424, - 64433,64442,64451,64460,64469,64478,64487,64496, - 64505,64514,64523,64532,64540,64549,64558,64566, - 64575,64584,64592,64601,64609,64617,64626,64634, - 64642,64651,64659,64667,64675,64683,64691,64699, - 64707,64715,64723,64731,64739,64747,64754,64762, - 64770,64777,64785,64793,64800,64808,64815,64822, - 64830,64837,64844,64852,64859,64866,64873,64880, - 64887,64895,64902,64908,64915,64922,64929,64936, - 64943,64949,64956,64963,64969,64976,64982,64989, - 64995,65002,65008,65015,65021,65027,65033,65040, - 65046,65052,65058,65064,65070,65076,65082,65088, - 65094,65099,65105,65111,65117,65122,65128,65133, - 65139,65144,65150,65155,65161,65166,65171,65177, - 65182,65187,65192,65197,65202,65207,65212,65217, - 65222,65227,65232,65237,65242,65246,65251,65256, - 65260,65265,65270,65274,65279,65283,65287,65292, - 65296,65300,65305,65309,65313,65317,65321,65325, - 65329,65333,65337,65341,65345,65349,65352,65356, - 65360,65363,65367,65371,65374,65378,65381,65385, - 65388,65391,65395,65398,65401,65404,65408,65411, - 65414,65417,65420,65423,65426,65429,65431,65434, - 65437,65440,65442,65445,65448,65450,65453,65455, - 65458,65460,65463,65465,65467,65470,65472,65474, - 65476,65478,65480,65482,65484,65486,65488,65490, - 65492,65494,65496,65497,65499,65501,65502,65504, - 65505,65507,65508,65510,65511,65513,65514,65515, - 65516,65518,65519,65520,65521,65522,65523,65524, - 65525,65526,65527,65527,65528,65529,65530,65530, - 65531,65531,65532,65532,65533,65533,65534,65534, - 65534,65535,65535,65535,65535,65535,65535,65535, - 65535,65535,65535,65535,65535,65535,65535,65534, - 65534,65534,65533,65533,65532,65532,65531,65531, - 65530,65530,65529,65528,65527,65527,65526,65525, - 65524,65523,65522,65521,65520,65519,65518,65516, - 65515,65514,65513,65511,65510,65508,65507,65505, - 65504,65502,65501,65499,65497,65496,65494,65492, - 65490,65488,65486,65484,65482,65480,65478,65476, - 65474,65472,65470,65467,65465,65463,65460,65458, - 65455,65453,65450,65448,65445,65442,65440,65437, - 65434,65431,65429,65426,65423,65420,65417,65414, - 65411,65408,65404,65401,65398,65395,65391,65388, - 65385,65381,65378,65374,65371,65367,65363,65360, - 65356,65352,65349,65345,65341,65337,65333,65329, - 65325,65321,65317,65313,65309,65305,65300,65296, - 65292,65287,65283,65279,65274,65270,65265,65260, - 65256,65251,65246,65242,65237,65232,65227,65222, - 65217,65212,65207,65202,65197,65192,65187,65182, - 65177,65171,65166,65161,65155,65150,65144,65139, - 65133,65128,65122,65117,65111,65105,65099,65094, - 65088,65082,65076,65070,65064,65058,65052,65046, - 65040,65033,65027,65021,65015,65008,65002,64995, - 64989,64982,64976,64969,64963,64956,64949,64943, - 64936,64929,64922,64915,64908,64902,64895,64887, - 64880,64873,64866,64859,64852,64844,64837,64830, - 64822,64815,64808,64800,64793,64785,64777,64770, - 64762,64754,64747,64739,64731,64723,64715,64707, - 64699,64691,64683,64675,64667,64659,64651,64642, - 64634,64626,64617,64609,64600,64592,64584,64575, - 64566,64558,64549,64540,64532,64523,64514,64505, - 64496,64487,64478,64469,64460,64451,64442,64433, - 64424,64414,64405,64396,64387,64377,64368,64358, - 64349,64339,64330,64320,64310,64301,64291,64281, - 64271,64261,64252,64242,64232,64222,64212,64202, - 64192,64181,64171,64161,64151,64140,64130,64120, - 64109,64099,64088,64078,64067,64057,64046,64035, - 64025,64014,64003,63992,63981,63971,63960,63949, - 63938,63927,63915,63904,63893,63882,63871,63859, - 63848,63837,63825,63814,63803,63791,63779,63768, - 63756,63745,63733,63721,63709,63698,63686,63674, - 63662,63650,63638,63626,63614,63602,63590,63578, - 63565,63553,63541,63528,63516,63504,63491,63479, - 63466,63454,63441,63429,63416,63403,63390,63378, - 63365,63352,63339,63326,63313,63300,63287,63274, - 63261,63248,63235,63221,63208,63195,63182,63168, - 63155,63141,63128,63114,63101,63087,63074,63060, - 63046,63032,63019,63005,62991,62977,62963,62949, - 62935,62921,62907,62893,62879,62865,62850,62836, - 62822,62808,62793,62779,62764,62750,62735,62721, - 62706,62692,62677,62662,62648,62633,62618,62603, - 62588,62573,62558,62543,62528,62513,62498,62483, - 62468,62453,62437,62422,62407,62391,62376,62360, - 62345,62329,62314,62298,62283,62267,62251,62236, - 62220,62204,62188,62172,62156,62141,62125,62108, - 62092,62076,62060,62044,62028,62012,61995,61979, - 61963,61946,61930,61913,61897,61880,61864,61847, - 61831,61814,61797,61780,61764,61747,61730,61713, - 61696,61679,61662,61645,61628,61611,61594,61577, - 61559,61542,61525,61507,61490,61473,61455,61438, - 61420,61403,61385,61367,61350,61332,61314,61297, - 61279,61261,61243,61225,61207,61189,61171,61153, - 61135,61117,61099,61081,61062,61044,61026,61007, - 60989,60971,60952,60934,60915,60897,60878,60859, - 60841,60822,60803,60785,60766,60747,60728,60709, - 60690,60671,60652,60633,60614,60595,60576,60556, - 60537,60518,60499,60479,60460,60441,60421,60402, - 60382,60363,60343,60323,60304,60284,60264,60244, - 60225,60205,60185,60165,60145,60125,60105,60085, - 60065,60045,60025,60004,59984,59964,59944,59923, - 59903,59883,59862,59842,59821,59801,59780,59759, - 59739,59718,59697,59677,59656,59635,59614,59593, - 59572,59551,59530,59509,59488,59467,59446,59425, - 59404,59382,59361,59340,59318,59297,59276,59254, - 59233,59211,59190,59168,59146,59125,59103,59081, - 59059,59038,59016,58994,58972,58950,58928,58906, - 58884,58862,58840,58818,58795,58773,58751,58729, - 58706,58684,58662,58639,58617,58594,58572,58549, - 58527,58504,58481,58459,58436,58413,58390,58367, - 58345,58322,58299,58276,58253,58230,58207,58183, - 58160,58137,58114,58091,58067,58044,58021,57997, - 57974,57950,57927,57903,57880,57856,57833,57809, - 57785,57762,57738,57714,57690,57666,57642,57618, - 57594,57570,57546,57522,57498,57474,57450,57426, - 57402,57377,57353,57329,57304,57280,57255,57231, - 57206,57182,57157,57133,57108,57083,57059,57034, - 57009,56984,56959,56935,56910,56885,56860,56835, - 56810,56785,56760,56734,56709,56684,56659,56633, - 56608,56583,56557,56532,56507,56481,56456,56430, - 56404,56379,56353,56328,56302,56276,56250,56225, - 56199,56173,56147,56121,56095,56069,56043,56017, - 55991,55965,55938,55912,55886,55860,55833,55807, - 55781,55754,55728,55701,55675,55648,55622,55595, - 55569,55542,55515,55489,55462,55435,55408,55381, - 55354,55327,55300,55274,55246,55219,55192,55165, - 55138,55111,55084,55056,55029,55002,54974,54947, - 54920,54892,54865,54837,54810,54782,54755,54727, - 54699,54672,54644,54616,54588,54560,54533,54505, - 54477,54449,54421,54393,54365,54337,54308,54280, - 54252,54224,54196,54167,54139,54111,54082,54054, - 54026,53997,53969,53940,53911,53883,53854,53826, - 53797,53768,53739,53711,53682,53653,53624,53595, - 53566,53537,53508,53479,53450,53421,53392,53363, - 53334,53304,53275,53246,53216,53187,53158,53128, - 53099,53069,53040,53010,52981,52951,52922,52892, - 52862,52832,52803,52773,52743,52713,52683,52653, - 52624,52594,52564,52534,52503,52473,52443,52413, - 52383,52353,52322,52292,52262,52231,52201,52171, - 52140,52110,52079,52049,52018,51988,51957,51926, - 51896,51865,51834,51803,51773,51742,51711,51680, - 51649,51618,51587,51556,51525,51494,51463,51432, - 51401,51369,51338,51307,51276,51244,51213,51182, - 51150,51119,51087,51056,51024,50993,50961,50929, - 50898,50866,50834,50803,50771,50739,50707,50675, - 50644,50612,50580,50548,50516,50484,50452,50420, - 50387,50355,50323,50291,50259,50226,50194,50162, - 50129,50097,50065,50032,50000,49967,49935,49902, - 49869,49837,49804,49771,49739,49706,49673,49640, - 49608,49575,49542,49509,49476,49443,49410,49377, - 49344,49311,49278,49244,49211,49178,49145,49112, - 49078,49045,49012,48978,48945,48911,48878,48844, - 48811,48777,48744,48710,48676,48643,48609,48575, - 48542,48508,48474,48440,48406,48372,48338,48304, - 48271,48237,48202,48168,48134,48100,48066,48032, - 47998,47963,47929,47895,47860,47826,47792,47757, - 47723,47688,47654,47619,47585,47550,47516,47481, - 47446,47412,47377,47342,47308,47273,47238,47203, - 47168,47133,47098,47063,47028,46993,46958,46923, - 46888,46853,46818,46783,46747,46712,46677,46642, - 46606,46571,46536,46500,46465,46429,46394,46358, - 46323,46287,46252,46216,46180,46145,46109,46073, - 46037,46002,45966,45930,45894,45858,45822,45786, - 45750,45714,45678,45642,45606,45570,45534,45498, - 45462,45425,45389,45353,45316,45280,45244,45207, - 45171,45135,45098,45062,45025,44989,44952,44915, - 44879,44842,44806,44769,44732,44695,44659,44622, - 44585,44548,44511,44474,44437,44400,44363,44326, - 44289,44252,44215,44178,44141,44104,44067,44029, - 43992,43955,43918,43880,43843,43806,43768,43731, - 43693,43656,43618,43581,43543,43506,43468,43430, - 43393,43355,43317,43280,43242,43204,43166,43128, - 43091,43053,43015,42977,42939,42901,42863,42825, - 42787,42749,42711,42672,42634,42596,42558,42520, - 42481,42443,42405,42366,42328,42290,42251,42213, - 42174,42136,42097,42059,42020,41982,41943,41904, - 41866,41827,41788,41750,41711,41672,41633,41595, - 41556,41517,41478,41439,41400,41361,41322,41283, - 41244,41205,41166,41127,41088,41048,41009,40970, - 40931,40891,40852,40813,40773,40734,40695,40655, - 40616,40576,40537,40497,40458,40418,40379,40339, - 40300,40260,40220,40180,40141,40101,40061,40021, - 39982,39942,39902,39862,39822,39782,39742,39702, - 39662,39622,39582,39542,39502,39462,39422,39382, - 39341,39301,39261,39221,39180,39140,39100,39059, - 39019,38979,38938,38898,38857,38817,38776,38736, - 38695,38655,38614,38573,38533,38492,38451,38411, - 38370,38329,38288,38248,38207,38166,38125,38084, - 38043,38002,37961,37920,37879,37838,37797,37756, - 37715,37674,37633,37592,37551,37509,37468,37427, - 37386,37344,37303,37262,37220,37179,37137,37096, - 37055,37013,36972,36930,36889,36847,36805,36764, - 36722,36681,36639,36597,36556,36514,36472,36430, - 36388,36347,36305,36263,36221,36179,36137,36095, - 36053,36011,35969,35927,35885,35843,35801,35759, - 35717,35675,35633,35590,35548,35506,35464,35421, - 35379,35337,35294,35252,35210,35167,35125,35082, - 35040,34997,34955,34912,34870,34827,34785,34742, - 34699,34657,34614,34571,34529,34486,34443,34400, - 34358,34315,34272,34229,34186,34143,34100,34057, - 34015,33972,33929,33886,33843,33799,33756,33713, - 33670,33627,33584,33541,33498,33454,33411,33368, - 33325,33281,33238,33195,33151,33108,33065,33021, - 32978,32934,32891,32847,32804,32760,32717,32673, - 32630,32586,32542,32499,32455,32411,32368,32324, - 32280,32236,32193,32149,32105,32061,32017,31974, - 31930,31886,31842,31798,31754,31710,31666,31622, - 31578,31534,31490,31446,31402,31357,31313,31269, - 31225,31181,31136,31092,31048,31004,30959,30915, - 30871,30826,30782,30738,30693,30649,30604,30560, - 30515,30471,30426,30382,30337,30293,30248,30204, - 30159,30114,30070,30025,29980,29936,29891,29846, - 29801,29757,29712,29667,29622,29577,29533,29488, - 29443,29398,29353,29308,29263,29218,29173,29128, - 29083,29038,28993,28948,28903,28858,28812,28767, - 28722,28677,28632,28586,28541,28496,28451,28405, - 28360,28315,28269,28224,28179,28133,28088,28042, - 27997,27952,27906,27861,27815,27770,27724,27678, - 27633,27587,27542,27496,27450,27405,27359,27313, - 27268,27222,27176,27131,27085,27039,26993,26947, - 26902,26856,26810,26764,26718,26672,26626,26580, - 26534,26488,26442,26396,26350,26304,26258,26212, - 26166,26120,26074,26028,25982,25936,25889,25843, - 25797,25751,25705,25658,25612,25566,25520,25473, - 25427,25381,25334,25288,25241,25195,25149,25102, - 25056,25009,24963,24916,24870,24823,24777,24730, - 24684,24637,24591,24544,24497,24451,24404,24357, - 24311,24264,24217,24171,24124,24077,24030,23984, - 23937,23890,23843,23796,23750,23703,23656,23609, - 23562,23515,23468,23421,23374,23327,23280,23233, - 23186,23139,23092,23045,22998,22951,22904,22857, - 22810,22763,22716,22668,22621,22574,22527,22480, - 22433,22385,22338,22291,22243,22196,22149,22102, - 22054,22007,21960,21912,21865,21817,21770,21723, - 21675,21628,21580,21533,21485,21438,21390,21343, - 21295,21248,21200,21153,21105,21057,21010,20962, - 20915,20867,20819,20772,20724,20676,20629,20581, - 20533,20485,20438,20390,20342,20294,20246,20199, - 20151,20103,20055,20007,19959,19912,19864,19816, - 19768,19720,19672,19624,19576,19528,19480,19432, - 19384,19336,19288,19240,19192,19144,19096,19048, - 19000,18951,18903,18855,18807,18759,18711,18663, - 18614,18566,18518,18470,18421,18373,18325,18277, - 18228,18180,18132,18084,18035,17987,17939,17890, - 17842,17793,17745,17697,17648,17600,17551,17503, - 17455,17406,17358,17309,17261,17212,17164,17115, - 17067,17018,16970,16921,16872,16824,16775,16727, - 16678,16629,16581,16532,16484,16435,16386,16338, - 16289,16240,16191,16143,16094,16045,15997,15948, - 15899,15850,15802,15753,15704,15655,15606,15557, - 15509,15460,15411,15362,15313,15264,15215,15167, - 15118,15069,15020,14971,14922,14873,14824,14775, - 14726,14677,14628,14579,14530,14481,14432,14383, - 14334,14285,14236,14187,14138,14089,14040,13990, - 13941,13892,13843,13794,13745,13696,13646,13597, - 13548,13499,13450,13401,13351,13302,13253,13204, - 13154,13105,13056,13007,12957,12908,12859,12810, - 12760,12711,12662,12612,12563,12514,12464,12415, - 12366,12316,12267,12218,12168,12119,12069,12020, - 11970,11921,11872,11822,11773,11723,11674,11624, - 11575,11525,11476,11426,11377,11327,11278,11228, - 11179,11129,11080,11030,10981,10931,10882,10832, - 10782,10733,10683,10634,10584,10534,10485,10435, - 10386,10336,10286,10237,10187,10137,10088,10038, - 9988,9939,9889,9839,9790,9740,9690,9640, - 9591,9541,9491,9442,9392,9342,9292,9243, - 9193,9143,9093,9043,8994,8944,8894,8844, - 8794,8745,8695,8645,8595,8545,8496,8446, - 8396,8346,8296,8246,8196,8147,8097,8047, - 7997,7947,7897,7847,7797,7747,7697,7648, - 7598,7548,7498,7448,7398,7348,7298,7248, - 7198,7148,7098,7048,6998,6948,6898,6848, - 6798,6748,6698,6648,6598,6548,6498,6448, - 6398,6348,6298,6248,6198,6148,6098,6048, - 5998,5948,5898,5848,5798,5748,5697,5647, - 5597,5547,5497,5447,5397,5347,5297,5247, - 5197,5146,5096,5046,4996,4946,4896,4846, - 4796,4745,4695,4645,4595,4545,4495,4445, - 4394,4344,4294,4244,4194,4144,4093,4043, - 3993,3943,3893,3843,3792,3742,3692,3642, - 3592,3541,3491,3441,3391,3341,3291,3240, - 3190,3140,3090,3039,2989,2939,2889,2839, - 2788,2738,2688,2638,2587,2537,2487,2437, - 2387,2336,2286,2236,2186,2135,2085,2035, - 1985,1934,1884,1834,1784,1733,1683,1633, - 1583,1532,1482,1432,1382,1331,1281,1231, - 1181,1130,1080,1030,980,929,879,829, - 779,728,678,628,578,527,477,427, - 376,326,276,226,175,125,75,25, - -25,-75,-125,-175,-226,-276,-326,-376, - -427,-477,-527,-578,-628,-678,-728,-779, - -829,-879,-929,-980,-1030,-1080,-1130,-1181, - -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583, - -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985, - -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387, - -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788, - -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190, - -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592, - -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993, - -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394, - -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796, - -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197, - -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597, - -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998, - -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398, - -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798, - -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198, - -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598, - -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997, - -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396, - -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794, - -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193, - -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591, - -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988, - -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386, - -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782, - -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179, - -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575, - -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970, - -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366, - -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760, - -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154, - -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548, - -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941, - -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334, - -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726, - -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118, - -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509, - -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899, - -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289, - -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678, - -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067, - -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455, - -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842, - -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228, - -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614, - -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000, - -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384, - -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768, - -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151, - -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533, - -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915, - -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295, - -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675, - -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054, - -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433, - -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810, - -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186, - -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562, - -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937, - -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311, - -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684, - -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056, - -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427, - -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797, - -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166, - -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534, - -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902, - -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268, - -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633, - -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997, - -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360, - -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722, - -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083, - -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443, - -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801, - -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159, - -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515, - -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871, - -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225, - -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578, - -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930, - -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280, - -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630, - -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978, - -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325, - -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670, - -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015, - -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358, - -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699, - -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040, - -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379, - -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717, - -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053, - -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388, - -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722, - -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055, - -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386, - -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715, - -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043, - -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370, - -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695, - -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019, - -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341, - -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662, - -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982, - -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299, - -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616, - -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931, - -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244, - -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556, - -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866, - -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174, - -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481, - -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787, - -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091, - -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393, - -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693, - -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992, - -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289, - -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585, - -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879, - -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171, - -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462, - -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750, - -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037, - -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323, - -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606, - -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888, - -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168, - -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446, - -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723, - -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998, - -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271, - -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542, - -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811, - -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078, - -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344, - -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608, - -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869, - -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129, - -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387, - -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644, - -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898, - -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150, - -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401, - -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649, - -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896, - -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140, - -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383, - -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624, - -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862, - -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099, - -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334, - -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566, - -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797, - -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026, - -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252, - -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477, - -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699, - -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920, - -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138, - -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354, - -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569, - -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781, - -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991, - -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199, - -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404, - -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608, - -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810, - -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009, - -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206, - -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402, - -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594, - -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785, - -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974, - -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160, - -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345, - -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527, - -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706, - -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884, - -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059, - -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233, - -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404, - -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572, - -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739, - -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903, - -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065, - -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225, - -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382, - -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537, - -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690, - -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841, - -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989, - -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135, - -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279, - -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420, - -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559, - -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696, - -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831, - -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963, - -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092, - -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220, - -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345, - -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468, - -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588, - -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706, - -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822, - -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935, - -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046, - -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155, - -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261, - -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365, - -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466, - -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565, - -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662, - -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756, - -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848, - -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938, - -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025, - -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109, - -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192, - -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271, - -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349, - -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424, - -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496, - -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566, - -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634, - -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699, - -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762, - -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822, - -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880, - -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936, - -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989, - -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040, - -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088, - -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133, - -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177, - -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217, - -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256, - -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292, - -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325, - -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356, - -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385, - -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411, - -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434, - -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455, - -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474, - -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490, - -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504, - -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515, - -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524, - -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530, - -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534, - -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535, - -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534, - -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531, - -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525, - -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516, - -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505, - -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492, - -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476, - -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458, - -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437, - -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414, - -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388, - -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360, - -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329, - -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296, - -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260, - -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222, - -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182, - -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139, - -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094, - -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046, - -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995, - -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943, - -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887, - -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830, - -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770, - -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707, - -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642, - -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575, - -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505, - -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433, - -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358, - -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281, - -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202, - -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120, - -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035, - -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949, - -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859, - -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768, - -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674, - -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578, - -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479, - -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378, - -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274, - -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168, - -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060, - -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949, - -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836, - -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721, - -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603, - -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483, - -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360, - -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236, - -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108, - -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979, - -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847, - -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713, - -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577, - -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438, - -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297, - -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153, - -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007, - -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859, - -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709, - -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556, - -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402, - -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244, - -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085, - -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923, - -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759, - -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593, - -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425, - -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254, - -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081, - -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906, - -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729, - -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549, - -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367, - -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183, - -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997, - -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809, - -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618, - -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426, - -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231, - -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034, - -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835, - -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633, - -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430, - -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225, - -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017, - -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807, - -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595, - -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381, - -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165, - -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947, - -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727, - -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505, - -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280, - -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054, - -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826, - -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595, - -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363, - -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128, - -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892, - -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653, - -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413, - -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171, - -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926, - -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680, - -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432, - -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182, - -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929, - -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675, - -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420, - -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162, - -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902, - -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640, - -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377, - -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112, - -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844, - -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575, - -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305, - -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032, - -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757, - -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481, - -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203, - -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923, - -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642, - -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358, - -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073, - -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786, - -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498, - -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207, - -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915, - -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622, - -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326, - -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029, - -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731, - -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430, - -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128, - -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825, - -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520, - -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213, - -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904, - -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595, - -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283, - -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970, - -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655, - -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339, - -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021, - -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702, - -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382, - -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059, - -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736, - -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411, - -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084, - -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756, - -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427, - -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096, - -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764, - -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430, - -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095, - -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759, - -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421, - -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082, - -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742, - -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400, - -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057, - -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713, - -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368, - -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021, - -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673, - -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324, - -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974, - -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622, - -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269, - -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915, - -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560, - -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204, - -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846, - -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488, - -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128, - -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767, - -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405, - -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042, - -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678, - -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313, - -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947, - -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580, - -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212, - -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843, - -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473, - -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102, - -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730, - -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357, - -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984, - -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609, - -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233, - -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857, - -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480, - -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102, - -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723, - -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343, - -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962, - -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581, - -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199, - -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816, - -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432, - -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048, - -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663, - -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277, - -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890, - -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503, - -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115, - -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727, - -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338, - -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948, - -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557, - -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167, - -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775, - -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383, - -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990, - -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597, - -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204, - -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810, - -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415, - -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020, - -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624, - -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228, - -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832, - -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435, - -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038, - -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640, - -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243, - -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844, - -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446, - -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047, - -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648, - -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248, - -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848, - -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448, - -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048, - -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647, - -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247, - -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846, - -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445, - -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043, - -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642, - -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240, - -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839, - -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437, - -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035, - -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633, - -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231, - -1181,-1130,-1080,-1030,-980,-929,-879,-829, - -779,-728,-678,-628,-578,-527,-477,-427, - -376,-326,-276,-226,-175,-125,-75,-25, - 25,75,125,175,226,276,326,376, - 427,477,527,578,628,678,728,779, - 829,879,929,980,1030,1080,1130,1181, - 1231,1281,1331,1382,1432,1482,1532,1583, - 1633,1683,1733,1784,1834,1884,1934,1985, - 2035,2085,2135,2186,2236,2286,2336,2387, - 2437,2487,2537,2587,2638,2688,2738,2788, - 2839,2889,2939,2989,3039,3090,3140,3190, - 3240,3291,3341,3391,3441,3491,3542,3592, - 3642,3692,3742,3792,3843,3893,3943,3993, - 4043,4093,4144,4194,4244,4294,4344,4394, - 4445,4495,4545,4595,4645,4695,4745,4796, - 4846,4896,4946,4996,5046,5096,5146,5197, - 5247,5297,5347,5397,5447,5497,5547,5597, - 5647,5697,5747,5798,5848,5898,5948,5998, - 6048,6098,6148,6198,6248,6298,6348,6398, - 6448,6498,6548,6598,6648,6698,6748,6798, - 6848,6898,6948,6998,7048,7098,7148,7198, - 7248,7298,7348,7398,7448,7498,7548,7598, - 7648,7697,7747,7797,7847,7897,7947,7997, - 8047,8097,8147,8196,8246,8296,8346,8396, - 8446,8496,8545,8595,8645,8695,8745,8794, - 8844,8894,8944,8994,9043,9093,9143,9193, - 9243,9292,9342,9392,9442,9491,9541,9591, - 9640,9690,9740,9790,9839,9889,9939,9988, - 10038,10088,10137,10187,10237,10286,10336,10386, - 10435,10485,10534,10584,10634,10683,10733,10782, - 10832,10882,10931,10981,11030,11080,11129,11179, - 11228,11278,11327,11377,11426,11476,11525,11575, - 11624,11674,11723,11773,11822,11872,11921,11970, - 12020,12069,12119,12168,12218,12267,12316,12366, - 12415,12464,12514,12563,12612,12662,12711,12760, - 12810,12859,12908,12957,13007,13056,13105,13154, - 13204,13253,13302,13351,13401,13450,13499,13548, - 13597,13647,13696,13745,13794,13843,13892,13941, - 13990,14040,14089,14138,14187,14236,14285,14334, - 14383,14432,14481,14530,14579,14628,14677,14726, - 14775,14824,14873,14922,14971,15020,15069,15118, - 15167,15215,15264,15313,15362,15411,15460,15509, - 15557,15606,15655,15704,15753,15802,15850,15899, - 15948,15997,16045,16094,16143,16191,16240,16289, - 16338,16386,16435,16484,16532,16581,16629,16678, - 16727,16775,16824,16872,16921,16970,17018,17067, - 17115,17164,17212,17261,17309,17358,17406,17455, - 17503,17551,17600,17648,17697,17745,17793,17842, - 17890,17939,17987,18035,18084,18132,18180,18228, - 18277,18325,18373,18421,18470,18518,18566,18614, - 18663,18711,18759,18807,18855,18903,18951,19000, - 19048,19096,19144,19192,19240,19288,19336,19384, - 19432,19480,19528,19576,19624,19672,19720,19768, - 19816,19864,19912,19959,20007,20055,20103,20151, - 20199,20246,20294,20342,20390,20438,20485,20533, - 20581,20629,20676,20724,20772,20819,20867,20915, - 20962,21010,21057,21105,21153,21200,21248,21295, - 21343,21390,21438,21485,21533,21580,21628,21675, - 21723,21770,21817,21865,21912,21960,22007,22054, - 22102,22149,22196,22243,22291,22338,22385,22432, - 22480,22527,22574,22621,22668,22716,22763,22810, - 22857,22904,22951,22998,23045,23092,23139,23186, - 23233,23280,23327,23374,23421,23468,23515,23562, - 23609,23656,23703,23750,23796,23843,23890,23937, - 23984,24030,24077,24124,24171,24217,24264,24311, - 24357,24404,24451,24497,24544,24591,24637,24684, - 24730,24777,24823,24870,24916,24963,25009,25056, - 25102,25149,25195,25241,25288,25334,25381,25427, - 25473,25520,25566,25612,25658,25705,25751,25797, - 25843,25889,25936,25982,26028,26074,26120,26166, - 26212,26258,26304,26350,26396,26442,26488,26534, - 26580,26626,26672,26718,26764,26810,26856,26902, - 26947,26993,27039,27085,27131,27176,27222,27268, - 27313,27359,27405,27450,27496,27542,27587,27633, - 27678,27724,27770,27815,27861,27906,27952,27997, - 28042,28088,28133,28179,28224,28269,28315,28360, - 28405,28451,28496,28541,28586,28632,28677,28722, - 28767,28812,28858,28903,28948,28993,29038,29083, - 29128,29173,29218,29263,29308,29353,29398,29443, - 29488,29533,29577,29622,29667,29712,29757,29801, - 29846,29891,29936,29980,30025,30070,30114,30159, - 30204,30248,30293,30337,30382,30427,30471,30516, - 30560,30604,30649,30693,30738,30782,30826,30871, - 30915,30959,31004,31048,31092,31136,31181,31225, - 31269,31313,31357,31402,31446,31490,31534,31578, - 31622,31666,31710,31754,31798,31842,31886,31930, - 31974,32017,32061,32105,32149,32193,32236,32280, - 32324,32368,32411,32455,32499,32542,32586,32630, - 32673,32717,32760,32804,32847,32891,32934,32978, - 33021,33065,33108,33151,33195,33238,33281,33325, - 33368,33411,33454,33498,33541,33584,33627,33670, - 33713,33756,33799,33843,33886,33929,33972,34015, - 34057,34100,34143,34186,34229,34272,34315,34358, - 34400,34443,34486,34529,34571,34614,34657,34699, - 34742,34785,34827,34870,34912,34955,34997,35040, - 35082,35125,35167,35210,35252,35294,35337,35379, - 35421,35464,35506,35548,35590,35633,35675,35717, - 35759,35801,35843,35885,35927,35969,36011,36053, - 36095,36137,36179,36221,36263,36305,36347,36388, - 36430,36472,36514,36556,36597,36639,36681,36722, - 36764,36805,36847,36889,36930,36972,37013,37055, - 37096,37137,37179,37220,37262,37303,37344,37386, - 37427,37468,37509,37551,37592,37633,37674,37715, - 37756,37797,37838,37879,37920,37961,38002,38043, - 38084,38125,38166,38207,38248,38288,38329,38370, - 38411,38451,38492,38533,38573,38614,38655,38695, - 38736,38776,38817,38857,38898,38938,38979,39019, - 39059,39100,39140,39180,39221,39261,39301,39341, - 39382,39422,39462,39502,39542,39582,39622,39662, - 39702,39742,39782,39822,39862,39902,39942,39982, - 40021,40061,40101,40141,40180,40220,40260,40299, - 40339,40379,40418,40458,40497,40537,40576,40616, - 40655,40695,40734,40773,40813,40852,40891,40931, - 40970,41009,41048,41087,41127,41166,41205,41244, - 41283,41322,41361,41400,41439,41478,41517,41556, - 41595,41633,41672,41711,41750,41788,41827,41866, - 41904,41943,41982,42020,42059,42097,42136,42174, - 42213,42251,42290,42328,42366,42405,42443,42481, - 42520,42558,42596,42634,42672,42711,42749,42787, - 42825,42863,42901,42939,42977,43015,43053,43091, - 43128,43166,43204,43242,43280,43317,43355,43393, - 43430,43468,43506,43543,43581,43618,43656,43693, - 43731,43768,43806,43843,43880,43918,43955,43992, - 44029,44067,44104,44141,44178,44215,44252,44289, - 44326,44363,44400,44437,44474,44511,44548,44585, - 44622,44659,44695,44732,44769,44806,44842,44879, - 44915,44952,44989,45025,45062,45098,45135,45171, - 45207,45244,45280,45316,45353,45389,45425,45462, - 45498,45534,45570,45606,45642,45678,45714,45750, - 45786,45822,45858,45894,45930,45966,46002,46037, - 46073,46109,46145,46180,46216,46252,46287,46323, - 46358,46394,46429,46465,46500,46536,46571,46606, - 46642,46677,46712,46747,46783,46818,46853,46888, - 46923,46958,46993,47028,47063,47098,47133,47168, - 47203,47238,47273,47308,47342,47377,47412,47446, - 47481,47516,47550,47585,47619,47654,47688,47723, - 47757,47792,47826,47861,47895,47929,47963,47998, - 48032,48066,48100,48134,48168,48202,48237,48271, - 48305,48338,48372,48406,48440,48474,48508,48542, - 48575,48609,48643,48676,48710,48744,48777,48811, - 48844,48878,48911,48945,48978,49012,49045,49078, - 49112,49145,49178,49211,49244,49278,49311,49344, - 49377,49410,49443,49476,49509,49542,49575,49608, - 49640,49673,49706,49739,49771,49804,49837,49869, - 49902,49935,49967,50000,50032,50064,50097,50129, - 50162,50194,50226,50259,50291,50323,50355,50387, - 50420,50452,50484,50516,50548,50580,50612,50644, - 50675,50707,50739,50771,50803,50834,50866,50898, - 50929,50961,50993,51024,51056,51087,51119,51150, - 51182,51213,51244,51276,51307,51338,51369,51401, - 51432,51463,51494,51525,51556,51587,51618,51649, - 51680,51711,51742,51773,51803,51834,51865,51896, - 51926,51957,51988,52018,52049,52079,52110,52140, - 52171,52201,52231,52262,52292,52322,52353,52383, - 52413,52443,52473,52503,52534,52564,52594,52624, - 52653,52683,52713,52743,52773,52803,52832,52862, - 52892,52922,52951,52981,53010,53040,53069,53099, - 53128,53158,53187,53216,53246,53275,53304,53334, - 53363,53392,53421,53450,53479,53508,53537,53566, - 53595,53624,53653,53682,53711,53739,53768,53797, - 53826,53854,53883,53912,53940,53969,53997,54026, - 54054,54082,54111,54139,54167,54196,54224,54252, - 54280,54309,54337,54365,54393,54421,54449,54477, - 54505,54533,54560,54588,54616,54644,54672,54699, - 54727,54755,54782,54810,54837,54865,54892,54920, - 54947,54974,55002,55029,55056,55084,55111,55138, - 55165,55192,55219,55246,55274,55300,55327,55354, - 55381,55408,55435,55462,55489,55515,55542,55569, - 55595,55622,55648,55675,55701,55728,55754,55781, - 55807,55833,55860,55886,55912,55938,55965,55991, - 56017,56043,56069,56095,56121,56147,56173,56199, - 56225,56250,56276,56302,56328,56353,56379,56404, - 56430,56456,56481,56507,56532,56557,56583,56608, - 56633,56659,56684,56709,56734,56760,56785,56810, - 56835,56860,56885,56910,56935,56959,56984,57009, - 57034,57059,57083,57108,57133,57157,57182,57206, - 57231,57255,57280,57304,57329,57353,57377,57402, - 57426,57450,57474,57498,57522,57546,57570,57594, - 57618,57642,57666,57690,57714,57738,57762,57785, - 57809,57833,57856,57880,57903,57927,57950,57974, - 57997,58021,58044,58067,58091,58114,58137,58160, - 58183,58207,58230,58253,58276,58299,58322,58345, - 58367,58390,58413,58436,58459,58481,58504,58527, - 58549,58572,58594,58617,58639,58662,58684,58706, - 58729,58751,58773,58795,58818,58840,58862,58884, - 58906,58928,58950,58972,58994,59016,59038,59059, - 59081,59103,59125,59146,59168,59190,59211,59233, - 59254,59276,59297,59318,59340,59361,59382,59404, - 59425,59446,59467,59488,59509,59530,59551,59572, - 59593,59614,59635,59656,59677,59697,59718,59739, - 59759,59780,59801,59821,59842,59862,59883,59903, - 59923,59944,59964,59984,60004,60025,60045,60065, - 60085,60105,60125,60145,60165,60185,60205,60225, - 60244,60264,60284,60304,60323,60343,60363,60382, - 60402,60421,60441,60460,60479,60499,60518,60537, - 60556,60576,60595,60614,60633,60652,60671,60690, - 60709,60728,60747,60766,60785,60803,60822,60841, - 60859,60878,60897,60915,60934,60952,60971,60989, - 61007,61026,61044,61062,61081,61099,61117,61135, - 61153,61171,61189,61207,61225,61243,61261,61279, - 61297,61314,61332,61350,61367,61385,61403,61420, - 61438,61455,61473,61490,61507,61525,61542,61559, - 61577,61594,61611,61628,61645,61662,61679,61696, - 61713,61730,61747,61764,61780,61797,61814,61831, - 61847,61864,61880,61897,61913,61930,61946,61963, - 61979,61995,62012,62028,62044,62060,62076,62092, - 62108,62125,62141,62156,62172,62188,62204,62220, - 62236,62251,62267,62283,62298,62314,62329,62345, - 62360,62376,62391,62407,62422,62437,62453,62468, - 62483,62498,62513,62528,62543,62558,62573,62588, - 62603,62618,62633,62648,62662,62677,62692,62706, - 62721,62735,62750,62764,62779,62793,62808,62822, - 62836,62850,62865,62879,62893,62907,62921,62935, - 62949,62963,62977,62991,63005,63019,63032,63046, - 63060,63074,63087,63101,63114,63128,63141,63155, - 63168,63182,63195,63208,63221,63235,63248,63261, - 63274,63287,63300,63313,63326,63339,63352,63365, - 63378,63390,63403,63416,63429,63441,63454,63466, - 63479,63491,63504,63516,63528,63541,63553,63565, - 63578,63590,63602,63614,63626,63638,63650,63662, - 63674,63686,63698,63709,63721,63733,63745,63756, - 63768,63779,63791,63803,63814,63825,63837,63848, - 63859,63871,63882,63893,63904,63915,63927,63938, - 63949,63960,63971,63981,63992,64003,64014,64025, - 64035,64046,64057,64067,64078,64088,64099,64109, - 64120,64130,64140,64151,64161,64171,64181,64192, - 64202,64212,64222,64232,64242,64252,64261,64271, - 64281,64291,64301,64310,64320,64330,64339,64349, - 64358,64368,64377,64387,64396,64405,64414,64424, - 64433,64442,64451,64460,64469,64478,64487,64496, - 64505,64514,64523,64532,64540,64549,64558,64566, - 64575,64584,64592,64600,64609,64617,64626,64634, - 64642,64651,64659,64667,64675,64683,64691,64699, - 64707,64715,64723,64731,64739,64747,64754,64762, - 64770,64777,64785,64793,64800,64808,64815,64822, - 64830,64837,64844,64852,64859,64866,64873,64880, - 64887,64895,64902,64908,64915,64922,64929,64936, - 64943,64949,64956,64963,64969,64976,64982,64989, - 64995,65002,65008,65015,65021,65027,65033,65040, - 65046,65052,65058,65064,65070,65076,65082,65088, - 65094,65099,65105,65111,65117,65122,65128,65133, - 65139,65144,65150,65155,65161,65166,65171,65177, - 65182,65187,65192,65197,65202,65207,65212,65217, - 65222,65227,65232,65237,65242,65246,65251,65256, - 65260,65265,65270,65274,65279,65283,65287,65292, - 65296,65300,65305,65309,65313,65317,65321,65325, - 65329,65333,65337,65341,65345,65349,65352,65356, - 65360,65363,65367,65371,65374,65378,65381,65385, - 65388,65391,65395,65398,65401,65404,65408,65411, - 65414,65417,65420,65423,65426,65429,65431,65434, - 65437,65440,65442,65445,65448,65450,65453,65455, - 65458,65460,65463,65465,65467,65470,65472,65474, - 65476,65478,65480,65482,65484,65486,65488,65490, - 65492,65494,65496,65497,65499,65501,65502,65504, - 65505,65507,65508,65510,65511,65513,65514,65515, - 65516,65518,65519,65520,65521,65522,65523,65524, - 65525,65526,65527,65527,65528,65529,65530,65530, - 65531,65531,65532,65532,65533,65533,65534,65534, - 65534,65535,65535,65535,65535,65535,65535,65535 + 25, 75, 125, 175, 226, 276, 326, 376, 427, + 477, 527, 578, 628, 678, 728, 779, 829, 879, + 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, + 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, + 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, + 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, + 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, + 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3541, 3592, + 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, + 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, + 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, + 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, + 5447, 5497, 5547, 5597, 5647, 5697, 5748, 5798, 5848, + 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, + 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, + 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, + 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, + 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, + 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, + 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, + 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, + 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, + 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, + 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, + 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, + 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, + 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, + 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, + 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, + 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, + 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, + 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, + 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, + 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, + 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, + 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, + 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, + 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, + 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, + 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, + 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, + 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, + 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, + 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, + 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, + 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, + 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, + 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, + 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, + 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, + 22196, 22243, 22291, 22338, 22385, 22433, 22480, 22527, 22574, + 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, + 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, + 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, + 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, + 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, + 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, + 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, + 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, + 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, + 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, + 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, + 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, + 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, + 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, + 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, + 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, + 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, + 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, + 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30426, + 30471, 30515, 30560, 30604, 30649, 30693, 30738, 30782, 30826, + 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, + 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, + 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, + 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, + 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, + 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, + 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, + 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, + 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, + 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, + 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, + 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, + 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, + 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, + 36305, 36347, 36388, 36430, 36472, 36514, 36555, 36597, 36639, + 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, + 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, + 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, + 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, + 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, + 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, + 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, + 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, + 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, + 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40300, + 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, + 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, + 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, + 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, + 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, + 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, + 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, + 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, + 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, + 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, + 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, + 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, + 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, + 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, + 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, + 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, + 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, + 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, + 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, + 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, + 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, + 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, + 47688, 47723, 47757, 47792, 47826, 47860, 47895, 47929, 47963, + 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, + 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, + 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, + 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, + 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, + 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, + 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50065, + 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, + 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, + 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, + 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, + 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, + 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, + 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, + 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, + 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, + 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, + 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, + 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, + 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, + 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53911, + 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, + 54196, 54224, 54252, 54280, 54308, 54337, 54365, 54393, 54421, + 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, + 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, + 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, + 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, + 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, + 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, + 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, + 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, + 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, + 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, + 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, + 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, + 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, + 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, + 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, + 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, + 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, + 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, + 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, + 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, + 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, + 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, + 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, + 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, + 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, + 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, + 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, + 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, + 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, + 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, + 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, + 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, + 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, + 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, + 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, + 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, + 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, + 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, + 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, + 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, + 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, + 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, + 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, + 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, + 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, + 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, + 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, + 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, + 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, + 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, + 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, + 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, + 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, + 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, + 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, + 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, + 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, + 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, + 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, + 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, + 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, + 64601, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, + 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, + 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, + 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, + 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, + 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, + 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, + 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, + 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, + 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, + 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, + 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, + 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, + 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, + 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, + 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, + 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, + 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, + 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, + 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, + 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, + 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, + 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, + 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65534, 65534, 65534, 65533, 65533, 65532, + 65532, 65531, 65531, 65530, 65530, 65529, 65528, 65527, 65527, + 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, + 65516, 65515, 65514, 65513, 65511, 65510, 65508, 65507, 65505, + 65504, 65502, 65501, 65499, 65497, 65496, 65494, 65492, 65490, + 65488, 65486, 65484, 65482, 65480, 65478, 65476, 65474, 65472, + 65470, 65467, 65465, 65463, 65460, 65458, 65455, 65453, 65450, + 65448, 65445, 65442, 65440, 65437, 65434, 65431, 65429, 65426, + 65423, 65420, 65417, 65414, 65411, 65408, 65404, 65401, 65398, + 65395, 65391, 65388, 65385, 65381, 65378, 65374, 65371, 65367, + 65363, 65360, 65356, 65352, 65349, 65345, 65341, 65337, 65333, + 65329, 65325, 65321, 65317, 65313, 65309, 65305, 65300, 65296, + 65292, 65287, 65283, 65279, 65274, 65270, 65265, 65260, 65256, + 65251, 65246, 65242, 65237, 65232, 65227, 65222, 65217, 65212, + 65207, 65202, 65197, 65192, 65187, 65182, 65177, 65171, 65166, + 65161, 65155, 65150, 65144, 65139, 65133, 65128, 65122, 65117, + 65111, 65105, 65099, 65094, 65088, 65082, 65076, 65070, 65064, + 65058, 65052, 65046, 65040, 65033, 65027, 65021, 65015, 65008, + 65002, 64995, 64989, 64982, 64976, 64969, 64963, 64956, 64949, + 64943, 64936, 64929, 64922, 64915, 64908, 64902, 64895, 64887, + 64880, 64873, 64866, 64859, 64852, 64844, 64837, 64830, 64822, + 64815, 64808, 64800, 64793, 64785, 64777, 64770, 64762, 64754, + 64747, 64739, 64731, 64723, 64715, 64707, 64699, 64691, 64683, + 64675, 64667, 64659, 64651, 64642, 64634, 64626, 64617, 64609, + 64600, 64592, 64584, 64575, 64566, 64558, 64549, 64540, 64532, + 64523, 64514, 64505, 64496, 64487, 64478, 64469, 64460, 64451, + 64442, 64433, 64424, 64414, 64405, 64396, 64387, 64377, 64368, + 64358, 64349, 64339, 64330, 64320, 64310, 64301, 64291, 64281, + 64271, 64261, 64252, 64242, 64232, 64222, 64212, 64202, 64192, + 64181, 64171, 64161, 64151, 64140, 64130, 64120, 64109, 64099, + 64088, 64078, 64067, 64057, 64046, 64035, 64025, 64014, 64003, + 63992, 63981, 63971, 63960, 63949, 63938, 63927, 63915, 63904, + 63893, 63882, 63871, 63859, 63848, 63837, 63825, 63814, 63803, + 63791, 63779, 63768, 63756, 63745, 63733, 63721, 63709, 63698, + 63686, 63674, 63662, 63650, 63638, 63626, 63614, 63602, 63590, + 63578, 63565, 63553, 63541, 63528, 63516, 63504, 63491, 63479, + 63466, 63454, 63441, 63429, 63416, 63403, 63390, 63378, 63365, + 63352, 63339, 63326, 63313, 63300, 63287, 63274, 63261, 63248, + 63235, 63221, 63208, 63195, 63182, 63168, 63155, 63141, 63128, + 63114, 63101, 63087, 63074, 63060, 63046, 63032, 63019, 63005, + 62991, 62977, 62963, 62949, 62935, 62921, 62907, 62893, 62879, + 62865, 62850, 62836, 62822, 62808, 62793, 62779, 62764, 62750, + 62735, 62721, 62706, 62692, 62677, 62662, 62648, 62633, 62618, + 62603, 62588, 62573, 62558, 62543, 62528, 62513, 62498, 62483, + 62468, 62453, 62437, 62422, 62407, 62391, 62376, 62360, 62345, + 62329, 62314, 62298, 62283, 62267, 62251, 62236, 62220, 62204, + 62188, 62172, 62156, 62141, 62125, 62108, 62092, 62076, 62060, + 62044, 62028, 62012, 61995, 61979, 61963, 61946, 61930, 61913, + 61897, 61880, 61864, 61847, 61831, 61814, 61797, 61780, 61764, + 61747, 61730, 61713, 61696, 61679, 61662, 61645, 61628, 61611, + 61594, 61577, 61559, 61542, 61525, 61507, 61490, 61473, 61455, + 61438, 61420, 61403, 61385, 61367, 61350, 61332, 61314, 61297, + 61279, 61261, 61243, 61225, 61207, 61189, 61171, 61153, 61135, + 61117, 61099, 61081, 61062, 61044, 61026, 61007, 60989, 60971, + 60952, 60934, 60915, 60897, 60878, 60859, 60841, 60822, 60803, + 60785, 60766, 60747, 60728, 60709, 60690, 60671, 60652, 60633, + 60614, 60595, 60576, 60556, 60537, 60518, 60499, 60479, 60460, + 60441, 60421, 60402, 60382, 60363, 60343, 60323, 60304, 60284, + 60264, 60244, 60225, 60205, 60185, 60165, 60145, 60125, 60105, + 60085, 60065, 60045, 60025, 60004, 59984, 59964, 59944, 59923, + 59903, 59883, 59862, 59842, 59821, 59801, 59780, 59759, 59739, + 59718, 59697, 59677, 59656, 59635, 59614, 59593, 59572, 59551, + 59530, 59509, 59488, 59467, 59446, 59425, 59404, 59382, 59361, + 59340, 59318, 59297, 59276, 59254, 59233, 59211, 59190, 59168, + 59146, 59125, 59103, 59081, 59059, 59038, 59016, 58994, 58972, + 58950, 58928, 58906, 58884, 58862, 58840, 58818, 58795, 58773, + 58751, 58729, 58706, 58684, 58662, 58639, 58617, 58594, 58572, + 58549, 58527, 58504, 58481, 58459, 58436, 58413, 58390, 58367, + 58345, 58322, 58299, 58276, 58253, 58230, 58207, 58183, 58160, + 58137, 58114, 58091, 58067, 58044, 58021, 57997, 57974, 57950, + 57927, 57903, 57880, 57856, 57833, 57809, 57785, 57762, 57738, + 57714, 57690, 57666, 57642, 57618, 57594, 57570, 57546, 57522, + 57498, 57474, 57450, 57426, 57402, 57377, 57353, 57329, 57304, + 57280, 57255, 57231, 57206, 57182, 57157, 57133, 57108, 57083, + 57059, 57034, 57009, 56984, 56959, 56935, 56910, 56885, 56860, + 56835, 56810, 56785, 56760, 56734, 56709, 56684, 56659, 56633, + 56608, 56583, 56557, 56532, 56507, 56481, 56456, 56430, 56404, + 56379, 56353, 56328, 56302, 56276, 56250, 56225, 56199, 56173, + 56147, 56121, 56095, 56069, 56043, 56017, 55991, 55965, 55938, + 55912, 55886, 55860, 55833, 55807, 55781, 55754, 55728, 55701, + 55675, 55648, 55622, 55595, 55569, 55542, 55515, 55489, 55462, + 55435, 55408, 55381, 55354, 55327, 55300, 55274, 55246, 55219, + 55192, 55165, 55138, 55111, 55084, 55056, 55029, 55002, 54974, + 54947, 54920, 54892, 54865, 54837, 54810, 54782, 54755, 54727, + 54699, 54672, 54644, 54616, 54588, 54560, 54533, 54505, 54477, + 54449, 54421, 54393, 54365, 54337, 54308, 54280, 54252, 54224, + 54196, 54167, 54139, 54111, 54082, 54054, 54026, 53997, 53969, + 53940, 53911, 53883, 53854, 53826, 53797, 53768, 53739, 53711, + 53682, 53653, 53624, 53595, 53566, 53537, 53508, 53479, 53450, + 53421, 53392, 53363, 53334, 53304, 53275, 53246, 53216, 53187, + 53158, 53128, 53099, 53069, 53040, 53010, 52981, 52951, 52922, + 52892, 52862, 52832, 52803, 52773, 52743, 52713, 52683, 52653, + 52624, 52594, 52564, 52534, 52503, 52473, 52443, 52413, 52383, + 52353, 52322, 52292, 52262, 52231, 52201, 52171, 52140, 52110, + 52079, 52049, 52018, 51988, 51957, 51926, 51896, 51865, 51834, + 51803, 51773, 51742, 51711, 51680, 51649, 51618, 51587, 51556, + 51525, 51494, 51463, 51432, 51401, 51369, 51338, 51307, 51276, + 51244, 51213, 51182, 51150, 51119, 51087, 51056, 51024, 50993, + 50961, 50929, 50898, 50866, 50834, 50803, 50771, 50739, 50707, + 50675, 50644, 50612, 50580, 50548, 50516, 50484, 50452, 50420, + 50387, 50355, 50323, 50291, 50259, 50226, 50194, 50162, 50129, + 50097, 50065, 50032, 50000, 49967, 49935, 49902, 49869, 49837, + 49804, 49771, 49739, 49706, 49673, 49640, 49608, 49575, 49542, + 49509, 49476, 49443, 49410, 49377, 49344, 49311, 49278, 49244, + 49211, 49178, 49145, 49112, 49078, 49045, 49012, 48978, 48945, + 48911, 48878, 48844, 48811, 48777, 48744, 48710, 48676, 48643, + 48609, 48575, 48542, 48508, 48474, 48440, 48406, 48372, 48338, + 48304, 48271, 48237, 48202, 48168, 48134, 48100, 48066, 48032, + 47998, 47963, 47929, 47895, 47860, 47826, 47792, 47757, 47723, + 47688, 47654, 47619, 47585, 47550, 47516, 47481, 47446, 47412, + 47377, 47342, 47308, 47273, 47238, 47203, 47168, 47133, 47098, + 47063, 47028, 46993, 46958, 46923, 46888, 46853, 46818, 46783, + 46747, 46712, 46677, 46642, 46606, 46571, 46536, 46500, 46465, + 46429, 46394, 46358, 46323, 46287, 46252, 46216, 46180, 46145, + 46109, 46073, 46037, 46002, 45966, 45930, 45894, 45858, 45822, + 45786, 45750, 45714, 45678, 45642, 45606, 45570, 45534, 45498, + 45462, 45425, 45389, 45353, 45316, 45280, 45244, 45207, 45171, + 45135, 45098, 45062, 45025, 44989, 44952, 44915, 44879, 44842, + 44806, 44769, 44732, 44695, 44659, 44622, 44585, 44548, 44511, + 44474, 44437, 44400, 44363, 44326, 44289, 44252, 44215, 44178, + 44141, 44104, 44067, 44029, 43992, 43955, 43918, 43880, 43843, + 43806, 43768, 43731, 43693, 43656, 43618, 43581, 43543, 43506, + 43468, 43430, 43393, 43355, 43317, 43280, 43242, 43204, 43166, + 43128, 43091, 43053, 43015, 42977, 42939, 42901, 42863, 42825, + 42787, 42749, 42711, 42672, 42634, 42596, 42558, 42520, 42481, + 42443, 42405, 42366, 42328, 42290, 42251, 42213, 42174, 42136, + 42097, 42059, 42020, 41982, 41943, 41904, 41866, 41827, 41788, + 41750, 41711, 41672, 41633, 41595, 41556, 41517, 41478, 41439, + 41400, 41361, 41322, 41283, 41244, 41205, 41166, 41127, 41088, + 41048, 41009, 40970, 40931, 40891, 40852, 40813, 40773, 40734, + 40695, 40655, 40616, 40576, 40537, 40497, 40458, 40418, 40379, + 40339, 40300, 40260, 40220, 40180, 40141, 40101, 40061, 40021, + 39982, 39942, 39902, 39862, 39822, 39782, 39742, 39702, 39662, + 39622, 39582, 39542, 39502, 39462, 39422, 39382, 39341, 39301, + 39261, 39221, 39180, 39140, 39100, 39059, 39019, 38979, 38938, + 38898, 38857, 38817, 38776, 38736, 38695, 38655, 38614, 38573, + 38533, 38492, 38451, 38411, 38370, 38329, 38288, 38248, 38207, + 38166, 38125, 38084, 38043, 38002, 37961, 37920, 37879, 37838, + 37797, 37756, 37715, 37674, 37633, 37592, 37551, 37509, 37468, + 37427, 37386, 37344, 37303, 37262, 37220, 37179, 37137, 37096, + 37055, 37013, 36972, 36930, 36889, 36847, 36805, 36764, 36722, + 36681, 36639, 36597, 36556, 36514, 36472, 36430, 36388, 36347, + 36305, 36263, 36221, 36179, 36137, 36095, 36053, 36011, 35969, + 35927, 35885, 35843, 35801, 35759, 35717, 35675, 35633, 35590, + 35548, 35506, 35464, 35421, 35379, 35337, 35294, 35252, 35210, + 35167, 35125, 35082, 35040, 34997, 34955, 34912, 34870, 34827, + 34785, 34742, 34699, 34657, 34614, 34571, 34529, 34486, 34443, + 34400, 34358, 34315, 34272, 34229, 34186, 34143, 34100, 34057, + 34015, 33972, 33929, 33886, 33843, 33799, 33756, 33713, 33670, + 33627, 33584, 33541, 33498, 33454, 33411, 33368, 33325, 33281, + 33238, 33195, 33151, 33108, 33065, 33021, 32978, 32934, 32891, + 32847, 32804, 32760, 32717, 32673, 32630, 32586, 32542, 32499, + 32455, 32411, 32368, 32324, 32280, 32236, 32193, 32149, 32105, + 32061, 32017, 31974, 31930, 31886, 31842, 31798, 31754, 31710, + 31666, 31622, 31578, 31534, 31490, 31446, 31402, 31357, 31313, + 31269, 31225, 31181, 31136, 31092, 31048, 31004, 30959, 30915, + 30871, 30826, 30782, 30738, 30693, 30649, 30604, 30560, 30515, + 30471, 30426, 30382, 30337, 30293, 30248, 30204, 30159, 30114, + 30070, 30025, 29980, 29936, 29891, 29846, 29801, 29757, 29712, + 29667, 29622, 29577, 29533, 29488, 29443, 29398, 29353, 29308, + 29263, 29218, 29173, 29128, 29083, 29038, 28993, 28948, 28903, + 28858, 28812, 28767, 28722, 28677, 28632, 28586, 28541, 28496, + 28451, 28405, 28360, 28315, 28269, 28224, 28179, 28133, 28088, + 28042, 27997, 27952, 27906, 27861, 27815, 27770, 27724, 27678, + 27633, 27587, 27542, 27496, 27450, 27405, 27359, 27313, 27268, + 27222, 27176, 27131, 27085, 27039, 26993, 26947, 26902, 26856, + 26810, 26764, 26718, 26672, 26626, 26580, 26534, 26488, 26442, + 26396, 26350, 26304, 26258, 26212, 26166, 26120, 26074, 26028, + 25982, 25936, 25889, 25843, 25797, 25751, 25705, 25658, 25612, + 25566, 25520, 25473, 25427, 25381, 25334, 25288, 25241, 25195, + 25149, 25102, 25056, 25009, 24963, 24916, 24870, 24823, 24777, + 24730, 24684, 24637, 24591, 24544, 24497, 24451, 24404, 24357, + 24311, 24264, 24217, 24171, 24124, 24077, 24030, 23984, 23937, + 23890, 23843, 23796, 23750, 23703, 23656, 23609, 23562, 23515, + 23468, 23421, 23374, 23327, 23280, 23233, 23186, 23139, 23092, + 23045, 22998, 22951, 22904, 22857, 22810, 22763, 22716, 22668, + 22621, 22574, 22527, 22480, 22433, 22385, 22338, 22291, 22243, + 22196, 22149, 22102, 22054, 22007, 21960, 21912, 21865, 21817, + 21770, 21723, 21675, 21628, 21580, 21533, 21485, 21438, 21390, + 21343, 21295, 21248, 21200, 21153, 21105, 21057, 21010, 20962, + 20915, 20867, 20819, 20772, 20724, 20676, 20629, 20581, 20533, + 20485, 20438, 20390, 20342, 20294, 20246, 20199, 20151, 20103, + 20055, 20007, 19959, 19912, 19864, 19816, 19768, 19720, 19672, + 19624, 19576, 19528, 19480, 19432, 19384, 19336, 19288, 19240, + 19192, 19144, 19096, 19048, 19000, 18951, 18903, 18855, 18807, + 18759, 18711, 18663, 18614, 18566, 18518, 18470, 18421, 18373, + 18325, 18277, 18228, 18180, 18132, 18084, 18035, 17987, 17939, + 17890, 17842, 17793, 17745, 17697, 17648, 17600, 17551, 17503, + 17455, 17406, 17358, 17309, 17261, 17212, 17164, 17115, 17067, + 17018, 16970, 16921, 16872, 16824, 16775, 16727, 16678, 16629, + 16581, 16532, 16484, 16435, 16386, 16338, 16289, 16240, 16191, + 16143, 16094, 16045, 15997, 15948, 15899, 15850, 15802, 15753, + 15704, 15655, 15606, 15557, 15509, 15460, 15411, 15362, 15313, + 15264, 15215, 15167, 15118, 15069, 15020, 14971, 14922, 14873, + 14824, 14775, 14726, 14677, 14628, 14579, 14530, 14481, 14432, + 14383, 14334, 14285, 14236, 14187, 14138, 14089, 14040, 13990, + 13941, 13892, 13843, 13794, 13745, 13696, 13646, 13597, 13548, + 13499, 13450, 13401, 13351, 13302, 13253, 13204, 13154, 13105, + 13056, 13007, 12957, 12908, 12859, 12810, 12760, 12711, 12662, + 12612, 12563, 12514, 12464, 12415, 12366, 12316, 12267, 12218, + 12168, 12119, 12069, 12020, 11970, 11921, 11872, 11822, 11773, + 11723, 11674, 11624, 11575, 11525, 11476, 11426, 11377, 11327, + 11278, 11228, 11179, 11129, 11080, 11030, 10981, 10931, 10882, + 10832, 10782, 10733, 10683, 10634, 10584, 10534, 10485, 10435, + 10386, 10336, 10286, 10237, 10187, 10137, 10088, 10038, 9988, + 9939, 9889, 9839, 9790, 9740, 9690, 9640, 9591, 9541, + 9491, 9442, 9392, 9342, 9292, 9243, 9193, 9143, 9093, + 9043, 8994, 8944, 8894, 8844, 8794, 8745, 8695, 8645, + 8595, 8545, 8496, 8446, 8396, 8346, 8296, 8246, 8196, + 8147, 8097, 8047, 7997, 7947, 7897, 7847, 7797, 7747, + 7697, 7648, 7598, 7548, 7498, 7448, 7398, 7348, 7298, + 7248, 7198, 7148, 7098, 7048, 6998, 6948, 6898, 6848, + 6798, 6748, 6698, 6648, 6598, 6548, 6498, 6448, 6398, + 6348, 6298, 6248, 6198, 6148, 6098, 6048, 5998, 5948, + 5898, 5848, 5798, 5748, 5697, 5647, 5597, 5547, 5497, + 5447, 5397, 5347, 5297, 5247, 5197, 5146, 5096, 5046, + 4996, 4946, 4896, 4846, 4796, 4745, 4695, 4645, 4595, + 4545, 4495, 4445, 4394, 4344, 4294, 4244, 4194, 4144, + 4093, 4043, 3993, 3943, 3893, 3843, 3792, 3742, 3692, + 3642, 3592, 3541, 3491, 3441, 3391, 3341, 3291, 3240, + 3190, 3140, 3090, 3039, 2989, 2939, 2889, 2839, 2788, + 2738, 2688, 2638, 2587, 2537, 2487, 2437, 2387, 2336, + 2286, 2236, 2186, 2135, 2085, 2035, 1985, 1934, 1884, + 1834, 1784, 1733, 1683, 1633, 1583, 1532, 1482, 1432, + 1382, 1331, 1281, 1231, 1181, 1130, 1080, 1030, 980, + 929, 879, 829, 779, 728, 678, 628, 578, 527, + 477, 427, 376, 326, 276, 226, 175, 125, 75, + 25, -25, -75, -125, -175, -226, -276, -326, -376, + -427, -477, -527, -578, -628, -678, -728, -779, -829, + -879, -929, -980, -1030, -1080, -1130, -1181, -1231, -1281, + -1331, -1382, -1432, -1482, -1532, -1583, -1633, -1683, -1733, + -1784, -1834, -1884, -1934, -1985, -2035, -2085, -2135, -2186, + -2236, -2286, -2336, -2387, -2437, -2487, -2537, -2588, -2638, + -2688, -2738, -2788, -2839, -2889, -2939, -2989, -3039, -3090, + -3140, -3190, -3240, -3291, -3341, -3391, -3441, -3491, -3541, + -3592, -3642, -3692, -3742, -3792, -3843, -3893, -3943, -3993, + -4043, -4093, -4144, -4194, -4244, -4294, -4344, -4394, -4445, + -4495, -4545, -4595, -4645, -4695, -4745, -4796, -4846, -4896, + -4946, -4996, -5046, -5096, -5146, -5197, -5247, -5297, -5347, + -5397, -5447, -5497, -5547, -5597, -5647, -5697, -5748, -5798, + -5848, -5898, -5948, -5998, -6048, -6098, -6148, -6198, -6248, + -6298, -6348, -6398, -6448, -6498, -6548, -6598, -6648, -6698, + -6748, -6798, -6848, -6898, -6948, -6998, -7048, -7098, -7148, + -7198, -7248, -7298, -7348, -7398, -7448, -7498, -7548, -7598, + -7648, -7697, -7747, -7797, -7847, -7897, -7947, -7997, -8047, + -8097, -8147, -8196, -8246, -8296, -8346, -8396, -8446, -8496, + -8545, -8595, -8645, -8695, -8745, -8794, -8844, -8894, -8944, + -8994, -9043, -9093, -9143, -9193, -9243, -9292, -9342, -9392, + -9442, -9491, -9541, -9591, -9640, -9690, -9740, -9790, -9839, + -9889, -9939, -9988, -10038, -10088, -10137, -10187, -10237, -10286, + -10336, -10386, -10435, -10485, -10534, -10584, -10634, -10683, -10733, + -10782, -10832, -10882, -10931, -10981, -11030, -11080, -11129, -11179, + -11228, -11278, -11327, -11377, -11426, -11476, -11525, -11575, -11624, + -11674, -11723, -11773, -11822, -11872, -11921, -11970, -12020, -12069, + -12119, -12168, -12218, -12267, -12316, -12366, -12415, -12464, -12514, + -12563, -12612, -12662, -12711, -12760, -12810, -12859, -12908, -12957, + -13007, -13056, -13105, -13154, -13204, -13253, -13302, -13351, -13401, + -13450, -13499, -13548, -13597, -13647, -13696, -13745, -13794, -13843, + -13892, -13941, -13990, -14040, -14089, -14138, -14187, -14236, -14285, + -14334, -14383, -14432, -14481, -14530, -14579, -14628, -14677, -14726, + -14775, -14824, -14873, -14922, -14971, -15020, -15069, -15118, -15167, + -15215, -15264, -15313, -15362, -15411, -15460, -15509, -15557, -15606, + -15655, -15704, -15753, -15802, -15850, -15899, -15948, -15997, -16045, + -16094, -16143, -16191, -16240, -16289, -16338, -16386, -16435, -16484, + -16532, -16581, -16629, -16678, -16727, -16775, -16824, -16872, -16921, + -16970, -17018, -17067, -17115, -17164, -17212, -17261, -17309, -17358, + -17406, -17455, -17503, -17551, -17600, -17648, -17697, -17745, -17793, + -17842, -17890, -17939, -17987, -18035, -18084, -18132, -18180, -18228, + -18277, -18325, -18373, -18421, -18470, -18518, -18566, -18614, -18663, + -18711, -18759, -18807, -18855, -18903, -18951, -19000, -19048, -19096, + -19144, -19192, -19240, -19288, -19336, -19384, -19432, -19480, -19528, + -19576, -19624, -19672, -19720, -19768, -19816, -19864, -19912, -19959, + -20007, -20055, -20103, -20151, -20199, -20246, -20294, -20342, -20390, + -20438, -20485, -20533, -20581, -20629, -20676, -20724, -20772, -20819, + -20867, -20915, -20962, -21010, -21057, -21105, -21153, -21200, -21248, + -21295, -21343, -21390, -21438, -21485, -21533, -21580, -21628, -21675, + -21723, -21770, -21817, -21865, -21912, -21960, -22007, -22054, -22102, + -22149, -22196, -22243, -22291, -22338, -22385, -22433, -22480, -22527, + -22574, -22621, -22668, -22716, -22763, -22810, -22857, -22904, -22951, + -22998, -23045, -23092, -23139, -23186, -23233, -23280, -23327, -23374, + -23421, -23468, -23515, -23562, -23609, -23656, -23703, -23750, -23796, + -23843, -23890, -23937, -23984, -24030, -24077, -24124, -24171, -24217, + -24264, -24311, -24357, -24404, -24451, -24497, -24544, -24591, -24637, + -24684, -24730, -24777, -24823, -24870, -24916, -24963, -25009, -25056, + -25102, -25149, -25195, -25241, -25288, -25334, -25381, -25427, -25473, + -25520, -25566, -25612, -25658, -25705, -25751, -25797, -25843, -25889, + -25936, -25982, -26028, -26074, -26120, -26166, -26212, -26258, -26304, + -26350, -26396, -26442, -26488, -26534, -26580, -26626, -26672, -26718, + -26764, -26810, -26856, -26902, -26947, -26993, -27039, -27085, -27131, + -27176, -27222, -27268, -27313, -27359, -27405, -27450, -27496, -27542, + -27587, -27633, -27678, -27724, -27770, -27815, -27861, -27906, -27952, + -27997, -28042, -28088, -28133, -28179, -28224, -28269, -28315, -28360, + -28405, -28451, -28496, -28541, -28586, -28632, -28677, -28722, -28767, + -28812, -28858, -28903, -28948, -28993, -29038, -29083, -29128, -29173, + -29218, -29263, -29308, -29353, -29398, -29443, -29488, -29533, -29577, + -29622, -29667, -29712, -29757, -29801, -29846, -29891, -29936, -29980, + -30025, -30070, -30114, -30159, -30204, -30248, -30293, -30337, -30382, + -30426, -30471, -30515, -30560, -30604, -30649, -30693, -30738, -30782, + -30826, -30871, -30915, -30959, -31004, -31048, -31092, -31136, -31181, + -31225, -31269, -31313, -31357, -31402, -31446, -31490, -31534, -31578, + -31622, -31666, -31710, -31754, -31798, -31842, -31886, -31930, -31974, + -32017, -32061, -32105, -32149, -32193, -32236, -32280, -32324, -32368, + -32411, -32455, -32499, -32542, -32586, -32630, -32673, -32717, -32760, + -32804, -32847, -32891, -32934, -32978, -33021, -33065, -33108, -33151, + -33195, -33238, -33281, -33325, -33368, -33411, -33454, -33498, -33541, + -33584, -33627, -33670, -33713, -33756, -33799, -33843, -33886, -33929, + -33972, -34015, -34057, -34100, -34143, -34186, -34229, -34272, -34315, + -34358, -34400, -34443, -34486, -34529, -34571, -34614, -34657, -34699, + -34742, -34785, -34827, -34870, -34912, -34955, -34997, -35040, -35082, + -35125, -35167, -35210, -35252, -35294, -35337, -35379, -35421, -35464, + -35506, -35548, -35590, -35633, -35675, -35717, -35759, -35801, -35843, + -35885, -35927, -35969, -36011, -36053, -36095, -36137, -36179, -36221, + -36263, -36305, -36347, -36388, -36430, -36472, -36514, -36555, -36597, + -36639, -36681, -36722, -36764, -36805, -36847, -36889, -36930, -36972, + -37013, -37055, -37096, -37137, -37179, -37220, -37262, -37303, -37344, + -37386, -37427, -37468, -37509, -37551, -37592, -37633, -37674, -37715, + -37756, -37797, -37838, -37879, -37920, -37961, -38002, -38043, -38084, + -38125, -38166, -38207, -38248, -38288, -38329, -38370, -38411, -38451, + -38492, -38533, -38573, -38614, -38655, -38695, -38736, -38776, -38817, + -38857, -38898, -38938, -38979, -39019, -39059, -39100, -39140, -39180, + -39221, -39261, -39301, -39341, -39382, -39422, -39462, -39502, -39542, + -39582, -39622, -39662, -39702, -39742, -39782, -39822, -39862, -39902, + -39942, -39982, -40021, -40061, -40101, -40141, -40180, -40220, -40260, + -40299, -40339, -40379, -40418, -40458, -40497, -40537, -40576, -40616, + -40655, -40695, -40734, -40773, -40813, -40852, -40891, -40931, -40970, + -41009, -41048, -41087, -41127, -41166, -41205, -41244, -41283, -41322, + -41361, -41400, -41439, -41478, -41517, -41556, -41595, -41633, -41672, + -41711, -41750, -41788, -41827, -41866, -41904, -41943, -41982, -42020, + -42059, -42097, -42136, -42174, -42213, -42251, -42290, -42328, -42366, + -42405, -42443, -42481, -42520, -42558, -42596, -42634, -42672, -42711, + -42749, -42787, -42825, -42863, -42901, -42939, -42977, -43015, -43053, + -43091, -43128, -43166, -43204, -43242, -43280, -43317, -43355, -43393, + -43430, -43468, -43506, -43543, -43581, -43618, -43656, -43693, -43731, + -43768, -43806, -43843, -43880, -43918, -43955, -43992, -44029, -44067, + -44104, -44141, -44178, -44215, -44252, -44289, -44326, -44363, -44400, + -44437, -44474, -44511, -44548, -44585, -44622, -44659, -44695, -44732, + -44769, -44806, -44842, -44879, -44915, -44952, -44989, -45025, -45062, + -45098, -45135, -45171, -45207, -45244, -45280, -45316, -45353, -45389, + -45425, -45462, -45498, -45534, -45570, -45606, -45642, -45678, -45714, + -45750, -45786, -45822, -45858, -45894, -45930, -45966, -46002, -46037, + -46073, -46109, -46145, -46180, -46216, -46252, -46287, -46323, -46358, + -46394, -46429, -46465, -46500, -46536, -46571, -46606, -46642, -46677, + -46712, -46747, -46783, -46818, -46853, -46888, -46923, -46958, -46993, + -47028, -47063, -47098, -47133, -47168, -47203, -47238, -47273, -47308, + -47342, -47377, -47412, -47446, -47481, -47516, -47550, -47585, -47619, + -47654, -47688, -47723, -47757, -47792, -47826, -47860, -47895, -47929, + -47963, -47998, -48032, -48066, -48100, -48134, -48168, -48202, -48236, + -48271, -48304, -48338, -48372, -48406, -48440, -48474, -48508, -48542, + -48575, -48609, -48643, -48676, -48710, -48744, -48777, -48811, -48844, + -48878, -48911, -48945, -48978, -49012, -49045, -49078, -49112, -49145, + -49178, -49211, -49244, -49278, -49311, -49344, -49377, -49410, -49443, + -49476, -49509, -49542, -49575, -49608, -49640, -49673, -49706, -49739, + -49771, -49804, -49837, -49869, -49902, -49935, -49967, -50000, -50032, + -50065, -50097, -50129, -50162, -50194, -50226, -50259, -50291, -50323, + -50355, -50387, -50420, -50452, -50484, -50516, -50548, -50580, -50612, + -50644, -50675, -50707, -50739, -50771, -50803, -50834, -50866, -50898, + -50929, -50961, -50993, -51024, -51056, -51087, -51119, -51150, -51182, + -51213, -51244, -51276, -51307, -51338, -51369, -51401, -51432, -51463, + -51494, -51525, -51556, -51587, -51618, -51649, -51680, -51711, -51742, + -51773, -51803, -51834, -51865, -51896, -51926, -51957, -51988, -52018, + -52049, -52079, -52110, -52140, -52171, -52201, -52231, -52262, -52292, + -52322, -52353, -52383, -52413, -52443, -52473, -52503, -52534, -52564, + -52594, -52624, -52653, -52683, -52713, -52743, -52773, -52803, -52832, + -52862, -52892, -52922, -52951, -52981, -53010, -53040, -53069, -53099, + -53128, -53158, -53187, -53216, -53246, -53275, -53304, -53334, -53363, + -53392, -53421, -53450, -53479, -53508, -53537, -53566, -53595, -53624, + -53653, -53682, -53711, -53739, -53768, -53797, -53826, -53854, -53883, + -53911, -53940, -53969, -53997, -54026, -54054, -54082, -54111, -54139, + -54167, -54196, -54224, -54252, -54280, -54308, -54337, -54365, -54393, + -54421, -54449, -54477, -54505, -54533, -54560, -54588, -54616, -54644, + -54672, -54699, -54727, -54755, -54782, -54810, -54837, -54865, -54892, + -54920, -54947, -54974, -55002, -55029, -55056, -55084, -55111, -55138, + -55165, -55192, -55219, -55246, -55274, -55300, -55327, -55354, -55381, + -55408, -55435, -55462, -55489, -55515, -55542, -55569, -55595, -55622, + -55648, -55675, -55701, -55728, -55754, -55781, -55807, -55833, -55860, + -55886, -55912, -55938, -55965, -55991, -56017, -56043, -56069, -56095, + -56121, -56147, -56173, -56199, -56225, -56250, -56276, -56302, -56328, + -56353, -56379, -56404, -56430, -56456, -56481, -56507, -56532, -56557, + -56583, -56608, -56633, -56659, -56684, -56709, -56734, -56760, -56785, + -56810, -56835, -56860, -56885, -56910, -56935, -56959, -56984, -57009, + -57034, -57059, -57083, -57108, -57133, -57157, -57182, -57206, -57231, + -57255, -57280, -57304, -57329, -57353, -57377, -57402, -57426, -57450, + -57474, -57498, -57522, -57546, -57570, -57594, -57618, -57642, -57666, + -57690, -57714, -57738, -57762, -57785, -57809, -57833, -57856, -57880, + -57903, -57927, -57950, -57974, -57997, -58021, -58044, -58067, -58091, + -58114, -58137, -58160, -58183, -58207, -58230, -58253, -58276, -58299, + -58322, -58345, -58367, -58390, -58413, -58436, -58459, -58481, -58504, + -58527, -58549, -58572, -58594, -58617, -58639, -58662, -58684, -58706, + -58729, -58751, -58773, -58795, -58818, -58840, -58862, -58884, -58906, + -58928, -58950, -58972, -58994, -59016, -59038, -59059, -59081, -59103, + -59125, -59146, -59168, -59190, -59211, -59233, -59254, -59276, -59297, + -59318, -59340, -59361, -59382, -59404, -59425, -59446, -59467, -59488, + -59509, -59530, -59551, -59572, -59593, -59614, -59635, -59656, -59677, + -59697, -59718, -59739, -59759, -59780, -59801, -59821, -59842, -59862, + -59883, -59903, -59923, -59944, -59964, -59984, -60004, -60025, -60045, + -60065, -60085, -60105, -60125, -60145, -60165, -60185, -60205, -60225, + -60244, -60264, -60284, -60304, -60323, -60343, -60363, -60382, -60402, + -60421, -60441, -60460, -60479, -60499, -60518, -60537, -60556, -60576, + -60595, -60614, -60633, -60652, -60671, -60690, -60709, -60728, -60747, + -60766, -60785, -60803, -60822, -60841, -60859, -60878, -60897, -60915, + -60934, -60952, -60971, -60989, -61007, -61026, -61044, -61062, -61081, + -61099, -61117, -61135, -61153, -61171, -61189, -61207, -61225, -61243, + -61261, -61279, -61297, -61314, -61332, -61350, -61367, -61385, -61403, + -61420, -61438, -61455, -61473, -61490, -61507, -61525, -61542, -61559, + -61577, -61594, -61611, -61628, -61645, -61662, -61679, -61696, -61713, + -61730, -61747, -61764, -61780, -61797, -61814, -61831, -61847, -61864, + -61880, -61897, -61913, -61930, -61946, -61963, -61979, -61995, -62012, + -62028, -62044, -62060, -62076, -62092, -62108, -62125, -62141, -62156, + -62172, -62188, -62204, -62220, -62236, -62251, -62267, -62283, -62298, + -62314, -62329, -62345, -62360, -62376, -62391, -62407, -62422, -62437, + -62453, -62468, -62483, -62498, -62513, -62528, -62543, -62558, -62573, + -62588, -62603, -62618, -62633, -62648, -62662, -62677, -62692, -62706, + -62721, -62735, -62750, -62764, -62779, -62793, -62808, -62822, -62836, + -62850, -62865, -62879, -62893, -62907, -62921, -62935, -62949, -62963, + -62977, -62991, -63005, -63019, -63032, -63046, -63060, -63074, -63087, + -63101, -63114, -63128, -63141, -63155, -63168, -63182, -63195, -63208, + -63221, -63235, -63248, -63261, -63274, -63287, -63300, -63313, -63326, + -63339, -63352, -63365, -63378, -63390, -63403, -63416, -63429, -63441, + -63454, -63466, -63479, -63491, -63504, -63516, -63528, -63541, -63553, + -63565, -63578, -63590, -63602, -63614, -63626, -63638, -63650, -63662, + -63674, -63686, -63698, -63709, -63721, -63733, -63745, -63756, -63768, + -63779, -63791, -63803, -63814, -63825, -63837, -63848, -63859, -63871, + -63882, -63893, -63904, -63915, -63927, -63938, -63949, -63960, -63971, + -63981, -63992, -64003, -64014, -64025, -64035, -64046, -64057, -64067, + -64078, -64088, -64099, -64109, -64120, -64130, -64140, -64151, -64161, + -64171, -64181, -64192, -64202, -64212, -64222, -64232, -64242, -64252, + -64261, -64271, -64281, -64291, -64301, -64310, -64320, -64330, -64339, + -64349, -64358, -64368, -64377, -64387, -64396, -64405, -64414, -64424, + -64433, -64442, -64451, -64460, -64469, -64478, -64487, -64496, -64505, + -64514, -64523, -64532, -64540, -64549, -64558, -64566, -64575, -64584, + -64592, -64601, -64609, -64617, -64626, -64634, -64642, -64651, -64659, + -64667, -64675, -64683, -64691, -64699, -64707, -64715, -64723, -64731, + -64739, -64747, -64754, -64762, -64770, -64777, -64785, -64793, -64800, + -64808, -64815, -64822, -64830, -64837, -64844, -64852, -64859, -64866, + -64873, -64880, -64887, -64895, -64902, -64908, -64915, -64922, -64929, + -64936, -64943, -64949, -64956, -64963, -64969, -64976, -64982, -64989, + -64995, -65002, -65008, -65015, -65021, -65027, -65033, -65040, -65046, + -65052, -65058, -65064, -65070, -65076, -65082, -65088, -65094, -65099, + -65105, -65111, -65117, -65122, -65128, -65133, -65139, -65144, -65150, + -65155, -65161, -65166, -65171, -65177, -65182, -65187, -65192, -65197, + -65202, -65207, -65212, -65217, -65222, -65227, -65232, -65237, -65242, + -65246, -65251, -65256, -65260, -65265, -65270, -65274, -65279, -65283, + -65287, -65292, -65296, -65300, -65305, -65309, -65313, -65317, -65321, + -65325, -65329, -65333, -65337, -65341, -65345, -65349, -65352, -65356, + -65360, -65363, -65367, -65371, -65374, -65378, -65381, -65385, -65388, + -65391, -65395, -65398, -65401, -65404, -65408, -65411, -65414, -65417, + -65420, -65423, -65426, -65429, -65431, -65434, -65437, -65440, -65442, + -65445, -65448, -65450, -65453, -65455, -65458, -65460, -65463, -65465, + -65467, -65470, -65472, -65474, -65476, -65478, -65480, -65482, -65484, + -65486, -65488, -65490, -65492, -65494, -65496, -65497, -65499, -65501, + -65502, -65504, -65505, -65507, -65508, -65510, -65511, -65513, -65514, + -65515, -65516, -65518, -65519, -65520, -65521, -65522, -65523, -65524, + -65525, -65526, -65527, -65527, -65528, -65529, -65530, -65530, -65531, + -65531, -65532, -65532, -65533, -65533, -65534, -65534, -65534, -65535, + -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, + -65535, -65535, -65535, -65535, -65534, -65534, -65534, -65533, -65533, + -65532, -65532, -65531, -65531, -65530, -65530, -65529, -65528, -65527, + -65527, -65526, -65525, -65524, -65523, -65522, -65521, -65520, -65519, + -65518, -65516, -65515, -65514, -65513, -65511, -65510, -65508, -65507, + -65505, -65504, -65502, -65501, -65499, -65497, -65496, -65494, -65492, + -65490, -65488, -65486, -65484, -65482, -65480, -65478, -65476, -65474, + -65472, -65470, -65467, -65465, -65463, -65460, -65458, -65455, -65453, + -65450, -65448, -65445, -65442, -65440, -65437, -65434, -65431, -65429, + -65426, -65423, -65420, -65417, -65414, -65411, -65408, -65404, -65401, + -65398, -65395, -65391, -65388, -65385, -65381, -65378, -65374, -65371, + -65367, -65363, -65360, -65356, -65352, -65349, -65345, -65341, -65337, + -65333, -65329, -65325, -65321, -65317, -65313, -65309, -65305, -65300, + -65296, -65292, -65287, -65283, -65279, -65274, -65270, -65265, -65260, + -65256, -65251, -65246, -65242, -65237, -65232, -65227, -65222, -65217, + -65212, -65207, -65202, -65197, -65192, -65187, -65182, -65177, -65171, + -65166, -65161, -65155, -65150, -65144, -65139, -65133, -65128, -65122, + -65117, -65111, -65105, -65099, -65094, -65088, -65082, -65076, -65070, + -65064, -65058, -65052, -65046, -65040, -65033, -65027, -65021, -65015, + -65008, -65002, -64995, -64989, -64982, -64976, -64969, -64963, -64956, + -64949, -64943, -64936, -64929, -64922, -64915, -64908, -64902, -64895, + -64887, -64880, -64873, -64866, -64859, -64852, -64844, -64837, -64830, + -64822, -64815, -64808, -64800, -64793, -64785, -64777, -64770, -64762, + -64754, -64747, -64739, -64731, -64723, -64715, -64707, -64699, -64691, + -64683, -64675, -64667, -64659, -64651, -64642, -64634, -64626, -64617, + -64609, -64601, -64592, -64584, -64575, -64566, -64558, -64549, -64540, + -64532, -64523, -64514, -64505, -64496, -64487, -64478, -64469, -64460, + -64451, -64442, -64433, -64424, -64414, -64405, -64396, -64387, -64377, + -64368, -64358, -64349, -64339, -64330, -64320, -64310, -64301, -64291, + -64281, -64271, -64261, -64252, -64242, -64232, -64222, -64212, -64202, + -64192, -64181, -64171, -64161, -64151, -64140, -64130, -64120, -64109, + -64099, -64088, -64078, -64067, -64057, -64046, -64035, -64025, -64014, + -64003, -63992, -63981, -63971, -63960, -63949, -63938, -63927, -63915, + -63904, -63893, -63882, -63871, -63859, -63848, -63837, -63825, -63814, + -63803, -63791, -63779, -63768, -63756, -63745, -63733, -63721, -63709, + -63698, -63686, -63674, -63662, -63650, -63638, -63626, -63614, -63602, + -63590, -63578, -63565, -63553, -63541, -63528, -63516, -63504, -63491, + -63479, -63466, -63454, -63441, -63429, -63416, -63403, -63390, -63378, + -63365, -63352, -63339, -63326, -63313, -63300, -63287, -63274, -63261, + -63248, -63235, -63221, -63208, -63195, -63182, -63168, -63155, -63141, + -63128, -63114, -63101, -63087, -63074, -63060, -63046, -63032, -63019, + -63005, -62991, -62977, -62963, -62949, -62935, -62921, -62907, -62893, + -62879, -62865, -62850, -62836, -62822, -62808, -62793, -62779, -62764, + -62750, -62735, -62721, -62706, -62692, -62677, -62662, -62648, -62633, + -62618, -62603, -62588, -62573, -62558, -62543, -62528, -62513, -62498, + -62483, -62468, -62453, -62437, -62422, -62407, -62391, -62376, -62360, + -62345, -62329, -62314, -62298, -62283, -62267, -62251, -62236, -62220, + -62204, -62188, -62172, -62156, -62141, -62125, -62108, -62092, -62076, + -62060, -62044, -62028, -62012, -61995, -61979, -61963, -61946, -61930, + -61913, -61897, -61880, -61864, -61847, -61831, -61814, -61797, -61780, + -61764, -61747, -61730, -61713, -61696, -61679, -61662, -61645, -61628, + -61611, -61594, -61577, -61559, -61542, -61525, -61507, -61490, -61473, + -61455, -61438, -61420, -61403, -61385, -61367, -61350, -61332, -61314, + -61297, -61279, -61261, -61243, -61225, -61207, -61189, -61171, -61153, + -61135, -61117, -61099, -61081, -61062, -61044, -61026, -61007, -60989, + -60971, -60952, -60934, -60915, -60897, -60878, -60859, -60841, -60822, + -60803, -60785, -60766, -60747, -60728, -60709, -60690, -60671, -60652, + -60633, -60614, -60595, -60576, -60556, -60537, -60518, -60499, -60479, + -60460, -60441, -60421, -60402, -60382, -60363, -60343, -60323, -60304, + -60284, -60264, -60244, -60225, -60205, -60185, -60165, -60145, -60125, + -60105, -60085, -60065, -60045, -60025, -60004, -59984, -59964, -59944, + -59923, -59903, -59883, -59862, -59842, -59821, -59801, -59780, -59759, + -59739, -59718, -59697, -59677, -59656, -59635, -59614, -59593, -59572, + -59551, -59530, -59509, -59488, -59467, -59446, -59425, -59404, -59382, + -59361, -59340, -59318, -59297, -59276, -59254, -59233, -59211, -59189, + -59168, -59146, -59125, -59103, -59081, -59059, -59038, -59016, -58994, + -58972, -58950, -58928, -58906, -58884, -58862, -58840, -58818, -58795, + -58773, -58751, -58729, -58706, -58684, -58662, -58639, -58617, -58594, + -58572, -58549, -58527, -58504, -58481, -58459, -58436, -58413, -58390, + -58367, -58345, -58322, -58299, -58276, -58253, -58230, -58207, -58183, + -58160, -58137, -58114, -58091, -58067, -58044, -58021, -57997, -57974, + -57950, -57927, -57903, -57880, -57856, -57833, -57809, -57785, -57762, + -57738, -57714, -57690, -57666, -57642, -57618, -57594, -57570, -57546, + -57522, -57498, -57474, -57450, -57426, -57402, -57377, -57353, -57329, + -57304, -57280, -57255, -57231, -57206, -57182, -57157, -57133, -57108, + -57083, -57059, -57034, -57009, -56984, -56959, -56935, -56910, -56885, + -56860, -56835, -56810, -56785, -56760, -56734, -56709, -56684, -56659, + -56633, -56608, -56583, -56557, -56532, -56507, -56481, -56456, -56430, + -56404, -56379, -56353, -56328, -56302, -56276, -56250, -56225, -56199, + -56173, -56147, -56121, -56095, -56069, -56043, -56017, -55991, -55965, + -55938, -55912, -55886, -55860, -55833, -55807, -55781, -55754, -55728, + -55701, -55675, -55648, -55622, -55595, -55569, -55542, -55515, -55489, + -55462, -55435, -55408, -55381, -55354, -55327, -55300, -55274, -55246, + -55219, -55192, -55165, -55138, -55111, -55084, -55056, -55029, -55002, + -54974, -54947, -54920, -54892, -54865, -54837, -54810, -54782, -54755, + -54727, -54699, -54672, -54644, -54616, -54588, -54560, -54533, -54505, + -54477, -54449, -54421, -54393, -54365, -54337, -54308, -54280, -54252, + -54224, -54196, -54167, -54139, -54111, -54082, -54054, -54026, -53997, + -53969, -53940, -53911, -53883, -53854, -53826, -53797, -53768, -53739, + -53711, -53682, -53653, -53624, -53595, -53566, -53537, -53508, -53479, + -53450, -53421, -53392, -53363, -53334, -53304, -53275, -53246, -53216, + -53187, -53158, -53128, -53099, -53069, -53040, -53010, -52981, -52951, + -52922, -52892, -52862, -52832, -52803, -52773, -52743, -52713, -52683, + -52653, -52624, -52594, -52564, -52534, -52503, -52473, -52443, -52413, + -52383, -52353, -52322, -52292, -52262, -52231, -52201, -52171, -52140, + -52110, -52079, -52049, -52018, -51988, -51957, -51926, -51896, -51865, + -51834, -51803, -51773, -51742, -51711, -51680, -51649, -51618, -51587, + -51556, -51525, -51494, -51463, -51432, -51401, -51369, -51338, -51307, + -51276, -51244, -51213, -51182, -51150, -51119, -51087, -51056, -51024, + -50993, -50961, -50929, -50898, -50866, -50834, -50803, -50771, -50739, + -50707, -50675, -50644, -50612, -50580, -50548, -50516, -50484, -50452, + -50420, -50387, -50355, -50323, -50291, -50259, -50226, -50194, -50162, + -50129, -50097, -50065, -50032, -50000, -49967, -49935, -49902, -49869, + -49837, -49804, -49771, -49739, -49706, -49673, -49640, -49608, -49575, + -49542, -49509, -49476, -49443, -49410, -49377, -49344, -49311, -49278, + -49244, -49211, -49178, -49145, -49112, -49078, -49045, -49012, -48978, + -48945, -48911, -48878, -48844, -48811, -48777, -48744, -48710, -48676, + -48643, -48609, -48575, -48542, -48508, -48474, -48440, -48406, -48372, + -48338, -48305, -48271, -48237, -48202, -48168, -48134, -48100, -48066, + -48032, -47998, -47963, -47929, -47895, -47860, -47826, -47792, -47757, + -47723, -47688, -47654, -47619, -47585, -47550, -47516, -47481, -47446, + -47412, -47377, -47342, -47307, -47273, -47238, -47203, -47168, -47133, + -47098, -47063, -47028, -46993, -46958, -46923, -46888, -46853, -46818, + -46783, -46747, -46712, -46677, -46642, -46606, -46571, -46536, -46500, + -46465, -46429, -46394, -46358, -46323, -46287, -46251, -46216, -46180, + -46145, -46109, -46073, -46037, -46002, -45966, -45930, -45894, -45858, + -45822, -45786, -45750, -45714, -45678, -45642, -45606, -45570, -45534, + -45498, -45462, -45425, -45389, -45353, -45316, -45280, -45244, -45207, + -45171, -45135, -45098, -45062, -45025, -44989, -44952, -44915, -44879, + -44842, -44806, -44769, -44732, -44695, -44659, -44622, -44585, -44548, + -44511, -44474, -44437, -44400, -44363, -44326, -44289, -44252, -44215, + -44178, -44141, -44104, -44067, -44029, -43992, -43955, -43918, -43880, + -43843, -43806, -43768, -43731, -43693, -43656, -43618, -43581, -43543, + -43506, -43468, -43430, -43393, -43355, -43317, -43280, -43242, -43204, + -43166, -43128, -43091, -43053, -43015, -42977, -42939, -42901, -42863, + -42825, -42787, -42749, -42711, -42672, -42634, -42596, -42558, -42520, + -42481, -42443, -42405, -42366, -42328, -42290, -42251, -42213, -42174, + -42136, -42097, -42059, -42020, -41982, -41943, -41904, -41866, -41827, + -41788, -41750, -41711, -41672, -41633, -41595, -41556, -41517, -41478, + -41439, -41400, -41361, -41322, -41283, -41244, -41205, -41166, -41127, + -41087, -41048, -41009, -40970, -40931, -40891, -40852, -40813, -40773, + -40734, -40695, -40655, -40616, -40576, -40537, -40497, -40458, -40418, + -40379, -40339, -40299, -40260, -40220, -40180, -40141, -40101, -40061, + -40021, -39982, -39942, -39902, -39862, -39822, -39782, -39742, -39702, + -39662, -39622, -39582, -39542, -39502, -39462, -39422, -39382, -39341, + -39301, -39261, -39221, -39180, -39140, -39100, -39059, -39019, -38979, + -38938, -38898, -38857, -38817, -38776, -38736, -38695, -38655, -38614, + -38573, -38533, -38492, -38451, -38411, -38370, -38329, -38288, -38248, + -38207, -38166, -38125, -38084, -38043, -38002, -37961, -37920, -37879, + -37838, -37797, -37756, -37715, -37674, -37633, -37592, -37550, -37509, + -37468, -37427, -37386, -37344, -37303, -37262, -37220, -37179, -37137, + -37096, -37055, -37013, -36972, -36930, -36889, -36847, -36805, -36764, + -36722, -36681, -36639, -36597, -36556, -36514, -36472, -36430, -36388, + -36347, -36305, -36263, -36221, -36179, -36137, -36095, -36053, -36011, + -35969, -35927, -35885, -35843, -35801, -35759, -35717, -35675, -35633, + -35590, -35548, -35506, -35464, -35421, -35379, -35337, -35294, -35252, + -35210, -35167, -35125, -35082, -35040, -34997, -34955, -34912, -34870, + -34827, -34785, -34742, -34699, -34657, -34614, -34571, -34529, -34486, + -34443, -34400, -34358, -34315, -34272, -34229, -34186, -34143, -34100, + -34057, -34015, -33972, -33929, -33886, -33843, -33799, -33756, -33713, + -33670, -33627, -33584, -33541, -33498, -33454, -33411, -33368, -33325, + -33281, -33238, -33195, -33151, -33108, -33065, -33021, -32978, -32934, + -32891, -32847, -32804, -32760, -32717, -32673, -32630, -32586, -32542, + -32499, -32455, -32411, -32368, -32324, -32280, -32236, -32193, -32149, + -32105, -32061, -32017, -31974, -31930, -31886, -31842, -31798, -31754, + -31710, -31666, -31622, -31578, -31534, -31490, -31446, -31402, -31357, + -31313, -31269, -31225, -31181, -31136, -31092, -31048, -31004, -30959, + -30915, -30871, -30826, -30782, -30738, -30693, -30649, -30604, -30560, + -30515, -30471, -30426, -30382, -30337, -30293, -30248, -30204, -30159, + -30114, -30070, -30025, -29980, -29936, -29891, -29846, -29801, -29757, + -29712, -29667, -29622, -29577, -29533, -29488, -29443, -29398, -29353, + -29308, -29263, -29218, -29173, -29128, -29083, -29038, -28993, -28948, + -28903, -28858, -28812, -28767, -28722, -28677, -28632, -28586, -28541, + -28496, -28451, -28405, -28360, -28315, -28269, -28224, -28179, -28133, + -28088, -28042, -27997, -27952, -27906, -27861, -27815, -27770, -27724, + -27678, -27633, -27587, -27542, -27496, -27450, -27405, -27359, -27313, + -27268, -27222, -27176, -27131, -27085, -27039, -26993, -26947, -26902, + -26856, -26810, -26764, -26718, -26672, -26626, -26580, -26534, -26488, + -26442, -26396, -26350, -26304, -26258, -26212, -26166, -26120, -26074, + -26028, -25982, -25936, -25889, -25843, -25797, -25751, -25705, -25658, + -25612, -25566, -25520, -25473, -25427, -25381, -25334, -25288, -25241, + -25195, -25149, -25102, -25056, -25009, -24963, -24916, -24870, -24823, + -24777, -24730, -24684, -24637, -24591, -24544, -24497, -24451, -24404, + -24357, -24311, -24264, -24217, -24171, -24124, -24077, -24030, -23984, + -23937, -23890, -23843, -23796, -23750, -23703, -23656, -23609, -23562, + -23515, -23468, -23421, -23374, -23327, -23280, -23233, -23186, -23139, + -23092, -23045, -22998, -22951, -22904, -22857, -22810, -22763, -22716, + -22668, -22621, -22574, -22527, -22480, -22432, -22385, -22338, -22291, + -22243, -22196, -22149, -22102, -22054, -22007, -21960, -21912, -21865, + -21817, -21770, -21723, -21675, -21628, -21580, -21533, -21485, -21438, + -21390, -21343, -21295, -21248, -21200, -21153, -21105, -21057, -21010, + -20962, -20915, -20867, -20819, -20772, -20724, -20676, -20629, -20581, + -20533, -20485, -20438, -20390, -20342, -20294, -20246, -20199, -20151, + -20103, -20055, -20007, -19959, -19912, -19864, -19816, -19768, -19720, + -19672, -19624, -19576, -19528, -19480, -19432, -19384, -19336, -19288, + -19240, -19192, -19144, -19096, -19048, -19000, -18951, -18903, -18855, + -18807, -18759, -18711, -18663, -18614, -18566, -18518, -18470, -18421, + -18373, -18325, -18277, -18228, -18180, -18132, -18084, -18035, -17987, + -17939, -17890, -17842, -17793, -17745, -17697, -17648, -17600, -17551, + -17503, -17455, -17406, -17358, -17309, -17261, -17212, -17164, -17115, + -17067, -17018, -16970, -16921, -16872, -16824, -16775, -16727, -16678, + -16629, -16581, -16532, -16484, -16435, -16386, -16338, -16289, -16240, + -16191, -16143, -16094, -16045, -15997, -15948, -15899, -15850, -15802, + -15753, -15704, -15655, -15606, -15557, -15509, -15460, -15411, -15362, + -15313, -15264, -15215, -15167, -15118, -15069, -15020, -14971, -14922, + -14873, -14824, -14775, -14726, -14677, -14628, -14579, -14530, -14481, + -14432, -14383, -14334, -14285, -14236, -14187, -14138, -14089, -14040, + -13990, -13941, -13892, -13843, -13794, -13745, -13696, -13647, -13597, + -13548, -13499, -13450, -13401, -13351, -13302, -13253, -13204, -13154, + -13105, -13056, -13007, -12957, -12908, -12859, -12810, -12760, -12711, + -12662, -12612, -12563, -12514, -12464, -12415, -12366, -12316, -12267, + -12217, -12168, -12119, -12069, -12020, -11970, -11921, -11872, -11822, + -11773, -11723, -11674, -11624, -11575, -11525, -11476, -11426, -11377, + -11327, -11278, -11228, -11179, -11129, -11080, -11030, -10981, -10931, + -10882, -10832, -10782, -10733, -10683, -10634, -10584, -10534, -10485, + -10435, -10386, -10336, -10286, -10237, -10187, -10137, -10088, -10038, + -9988, -9939, -9889, -9839, -9790, -9740, -9690, -9640, -9591, + -9541, -9491, -9442, -9392, -9342, -9292, -9243, -9193, -9143, + -9093, -9043, -8994, -8944, -8894, -8844, -8794, -8745, -8695, + -8645, -8595, -8545, -8496, -8446, -8396, -8346, -8296, -8246, + -8196, -8147, -8097, -8047, -7997, -7947, -7897, -7847, -7797, + -7747, -7697, -7648, -7598, -7548, -7498, -7448, -7398, -7348, + -7298, -7248, -7198, -7148, -7098, -7048, -6998, -6948, -6898, + -6848, -6798, -6748, -6698, -6648, -6598, -6548, -6498, -6448, + -6398, -6348, -6298, -6248, -6198, -6148, -6098, -6048, -5998, + -5948, -5898, -5848, -5798, -5747, -5697, -5647, -5597, -5547, + -5497, -5447, -5397, -5347, -5297, -5247, -5197, -5146, -5096, + -5046, -4996, -4946, -4896, -4846, -4796, -4745, -4695, -4645, + -4595, -4545, -4495, -4445, -4394, -4344, -4294, -4244, -4194, + -4144, -4093, -4043, -3993, -3943, -3893, -3843, -3792, -3742, + -3692, -3642, -3592, -3541, -3491, -3441, -3391, -3341, -3291, + -3240, -3190, -3140, -3090, -3039, -2989, -2939, -2889, -2839, + -2788, -2738, -2688, -2638, -2588, -2537, -2487, -2437, -2387, + -2336, -2286, -2236, -2186, -2135, -2085, -2035, -1985, -1934, + -1884, -1834, -1784, -1733, -1683, -1633, -1583, -1532, -1482, + -1432, -1382, -1331, -1281, -1231, -1181, -1130, -1080, -1030, + -980, -929, -879, -829, -779, -728, -678, -628, -578, + -527, -477, -427, -376, -326, -276, -226, -175, -125, + -75, -25, 25, 75, 125, 175, 226, 276, 326, + 376, 427, 477, 527, 578, 628, 678, 728, 779, + 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, + 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, + 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, + 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, + 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, + 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, + 3542, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, + 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, + 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, + 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, + 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5747, + 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, + 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, + 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, + 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, + 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, + 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, + 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, + 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, + 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, + 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, + 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, + 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, + 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, + 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, + 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, + 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, + 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, + 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, + 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, + 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, + 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, + 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, + 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, + 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, + 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, + 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, + 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, + 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, + 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, + 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, + 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, + 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, + 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, + 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, + 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, + 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, + 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, + 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22432, 22480, + 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, + 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, + 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, + 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, + 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, + 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, + 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, + 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, + 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, + 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, + 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, + 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, + 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, + 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, + 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, + 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, + 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, + 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, + 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, + 30382, 30427, 30471, 30516, 30560, 30604, 30649, 30693, 30738, + 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, + 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, + 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, + 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, + 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, + 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, + 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, + 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, + 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, + 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, + 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, + 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, + 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, + 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, + 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36556, + 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, + 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, + 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, + 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, + 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, + 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, + 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, + 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, + 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, + 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, + 40260, 40299, 40339, 40379, 40418, 40458, 40497, 40537, 40576, + 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, + 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, + 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, + 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, + 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, + 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, + 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, + 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, + 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, + 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, + 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, + 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, + 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, + 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, + 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, + 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, + 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, + 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, + 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, + 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, + 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, + 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47861, 47895, + 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, + 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, + 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, + 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, + 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, + 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, + 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, + 50032, 50064, 50097, 50129, 50162, 50194, 50226, 50259, 50291, + 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, + 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, + 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, + 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, + 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, + 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, + 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, + 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, + 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, + 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, + 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, + 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, + 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, + 53883, 53912, 53940, 53969, 53997, 54026, 54054, 54082, 54111, + 54139, 54167, 54196, 54224, 54252, 54280, 54309, 54337, 54365, + 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, + 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, + 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, + 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, + 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, + 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, + 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, + 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, + 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, + 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, + 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, + 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, + 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, + 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, + 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, + 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, + 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, + 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, + 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, + 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, + 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, + 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, + 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, + 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, + 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, + 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, + 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, + 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, + 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, + 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, + 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, + 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, + 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, + 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, + 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, + 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, + 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, + 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, + 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, + 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, + 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, + 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, + 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, + 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, + 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, + 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, + 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, + 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, + 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, + 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, + 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, + 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, + 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, + 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, + 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, + 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, + 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, + 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, + 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, + 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, + 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, + 64584, 64592, 64600, 64609, 64617, 64626, 64634, 64642, 64651, + 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, + 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, + 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, + 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, + 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, + 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, + 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, + 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, + 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, + 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, + 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, + 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, + 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, + 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, + 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, + 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, + 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, + 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, + 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, + 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, + 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, + 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, + 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, }; -const fixed_t *finecosine = &finesine[FINEANGLES/4]; +const fixed_t *finecosine = &finesine[FINEANGLES / 4]; const angle_t tantoangle[2049] = { - 0,333772,667544,1001315,1335086,1668857,2002626,2336395, - 2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492, - 5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435, - 8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145, - 10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539, - 13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536, - 16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054, - 18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014, - 21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332, - 24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930, - 26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724, - 29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636, - 32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584, - 34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492, - 37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272, - 40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848, - 42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140, - 45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072, - 47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556, - 50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524, - 53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888, - 55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576, - 58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508, - 61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604, - 63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788, - 66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984, - 69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112, - 71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096, - 74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864, - 77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336, - 79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440, - 82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096, - 85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240, - 87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792, - 90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672, - 92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816, - 95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144, - 98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592, - 100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080, - 103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552, - 105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920, - 108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120, - 111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080, - 113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744, - 116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024, - 118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864, - 121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200, - 124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960, - 126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072, - 129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480, - 131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120, - 134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912, - 136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808, - 139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752, - 142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664, - 144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480, - 147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152, - 149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616, - 152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824, - 154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696, - 157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168, - 159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208, - 162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752, - 164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736, - 167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096, - 169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800, - 172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784, - 174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984, - 177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368, - 179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856, - 182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416, - 184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000, - 187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560, - 189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016, - 192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352, - 194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520, - 197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456, - 199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128, - 202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472, - 204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456, - 207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048, - 209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184, - 211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816, - 214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928, - 216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472, - 219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384, - 221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664, - 223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232, - 226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088, - 228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152, - 231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440, - 233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872, - 235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416, - 238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072, - 240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776, - 242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496, - 245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216, - 247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904, - 249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512, - 252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008, - 254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392, - 256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600, - 259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632, - 261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456, - 263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024, - 266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336, - 268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360, - 270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048, - 272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432, - 275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416, - 277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032, - 279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248, - 281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032, - 284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384, - 286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240, - 288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632, - 290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528, - 293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864, - 295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704, - 297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952, - 299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640, - 301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768, - 303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272, - 306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152, - 308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408, - 310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040, - 312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016, - 314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336, - 316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968, - 319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912, - 321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200, - 323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736, - 325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584, - 327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712, - 329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120, - 331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776, - 333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712, - 335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864, - 337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296, - 340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976, - 342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904, - 344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048, - 346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440, - 348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048, - 350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872, - 352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944, - 354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264, - 356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768, - 358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520, - 360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488, - 362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704, - 364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136, - 366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784, - 368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680, - 370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792, - 372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152, - 374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760, - 376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584, - 377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688, - 379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040, - 381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640, - 383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488, - 385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616, - 387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024, - 389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712, - 391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680, - 393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960, - 395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520, - 396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424, - 398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608, - 400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136, - 402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008, - 404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224, - 406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784, - 408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720, - 409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032, - 411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720, - 413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784, - 415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288, - 417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200, - 418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552, - 420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344, - 422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576, - 424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280, - 425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488, - 427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168, - 429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352, - 431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040, - 432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296, - 434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088, - 436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416, - 438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344, - 439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872, - 441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968, - 443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696, - 444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088, - 446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112, - 448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800, - 450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152, - 451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232, - 453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008, - 454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512, - 456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744, - 458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768, - 459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584, - 461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160, - 463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560, - 464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816, - 466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896, - 468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832, - 469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688, - 471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400, - 472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064, - 474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648, - 475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184, - 477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704, - 479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240, - 480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760, - 482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296, - 483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912, - 485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576, - 486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320, - 488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176, - 489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144, - 491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256, - 492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544, - 494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008, - 495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680, - 497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560, - 498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680, - 500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040, - 501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704, - 503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672, - 504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944, - 506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552, - 507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528, - 509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872, - 510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616, - 511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792, - 513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368, - 514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440, - 516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976, - 517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008, - 519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568, - 520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656, - 521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304, - 523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512, - 524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344, - 526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800, - 527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880, - 528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648, - 530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072, - 531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184, - 532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048, - 534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632, - 535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000, - 536870912 + 0, 333772, 667544, 1001315, 1335086, 1668857, + 2002626, 2336395, 2670163, 3003929, 3337694, 3671457, + 4005219, 4338979, 4672736, 5006492, 5340245, 5673995, + 6007743, 6341488, 6675230, 7008968, 7342704, 7676435, + 8010164, 8343888, 8677609, 9011325, 9345037, 9678744, + 10012447, 10346145, 10679838, 11013526, 11347209, 11680887, + 12014558, 12348225, 12681885, 13015539, 13349187, 13682829, + 14016464, 14350092, 14683714, 15017328, 15350936, 15684536, + 16018129, 16351714, 16685291, 17018860, 17352422, 17685974, + 18019518, 18353054, 18686582, 19020100, 19353610, 19687110, + 20020600, 20354080, 20687552, 21021014, 21354466, 21687906, + 22021338, 22354758, 22688168, 23021568, 23354956, 23688332, + 24021698, 24355052, 24688396, 25021726, 25355046, 25688352, + 26021648, 26354930, 26688200, 27021456, 27354702, 27687932, + 28021150, 28354356, 28687548, 29020724, 29353888, 29687038, + 30020174, 30353296, 30686404, 31019496, 31352574, 31685636, + 32018684, 32351718, 32684734, 33017736, 33350722, 33683692, + 34016648, 34349584, 34682508, 35015412, 35348300, 35681172, + 36014028, 36346868, 36679688, 37012492, 37345276, 37678044, + 38010792, 38343524, 38676240, 39008936, 39341612, 39674272, + 40006912, 40339532, 40672132, 41004716, 41337276, 41669820, + 42002344, 42334848, 42667332, 42999796, 43332236, 43664660, + 43997060, 44329444, 44661800, 44994140, 45326456, 45658752, + 45991028, 46323280, 46655512, 46987720, 47319908, 47652072, + 47984212, 48316332, 48648428, 48980500, 49312548, 49644576, + 49976580, 50308556, 50640512, 50972444, 51304352, 51636236, + 51968096, 52299928, 52631740, 52963524, 53295284, 53627020, + 53958728, 54290412, 54622068, 54953704, 55285308, 55616888, + 55948444, 56279972, 56611472, 56942948, 57274396, 57605816, + 57937212, 58268576, 58599916, 58931228, 59262512, 59593768, + 59924992, 60256192, 60587364, 60918508, 61249620, 61580704, + 61911760, 62242788, 62573788, 62904756, 63235692, 63566604, + 63897480, 64228332, 64559148, 64889940, 65220696, 65551424, + 65882120, 66212788, 66543420, 66874024, 67204600, 67535136, + 67865648, 68196120, 68526568, 68856984, 69187360, 69517712, + 69848024, 70178304, 70508560, 70838776, 71168960, 71499112, + 71829224, 72159312, 72489360, 72819376, 73149360, 73479304, + 73809216, 74139096, 74468936, 74798744, 75128520, 75458264, + 75787968, 76117632, 76447264, 76776864, 77106424, 77435952, + 77765440, 78094888, 78424304, 78753688, 79083032, 79412336, + 79741608, 80070840, 80400032, 80729192, 81058312, 81387392, + 81716432, 82045440, 82374408, 82703336, 83032224, 83361080, + 83689896, 84018664, 84347400, 84676096, 85004760, 85333376, + 85661952, 85990488, 86318984, 86647448, 86975864, 87304240, + 87632576, 87960872, 88289128, 88617344, 88945520, 89273648, + 89601736, 89929792, 90257792, 90585760, 90913688, 91241568, + 91569408, 91897200, 92224960, 92552672, 92880336, 93207968, + 93535552, 93863088, 94190584, 94518040, 94845448, 95172816, + 95500136, 95827416, 96154648, 96481832, 96808976, 97136080, + 97463136, 97790144, 98117112, 98444032, 98770904, 99097736, + 99424520, 99751256, 100077944, 100404592, 100731192, 101057744, + 101384248, 101710712, 102037128, 102363488, 102689808, 103016080, + 103342312, 103668488, 103994616, 104320696, 104646736, 104972720, + 105298656, 105624552, 105950392, 106276184, 106601928, 106927624, + 107253272, 107578872, 107904416, 108229920, 108555368, 108880768, + 109206120, 109531416, 109856664, 110181872, 110507016, 110832120, + 111157168, 111482168, 111807112, 112132008, 112456856, 112781648, + 113106392, 113431080, 113755720, 114080312, 114404848, 114729328, + 115053760, 115378136, 115702464, 116026744, 116350960, 116675128, + 116999248, 117323312, 117647320, 117971272, 118295176, 118619024, + 118942816, 119266560, 119590248, 119913880, 120237456, 120560984, + 120884456, 121207864, 121531224, 121854528, 122177784, 122500976, + 122824112, 123147200, 123470224, 123793200, 124116120, 124438976, + 124761784, 125084528, 125407224, 125729856, 126052432, 126374960, + 126697424, 127019832, 127342184, 127664472, 127986712, 128308888, + 128631008, 128953072, 129275080, 129597024, 129918912, 130240744, + 130562520, 130884232, 131205888, 131527480, 131849016, 132170496, + 132491912, 132813272, 133134576, 133455816, 133776992, 134098120, + 134419184, 134740176, 135061120, 135382000, 135702816, 136023584, + 136344272, 136664912, 136985488, 137306016, 137626464, 137946864, + 138267184, 138587456, 138907664, 139227808, 139547904, 139867920, + 140187888, 140507776, 140827616, 141147392, 141467104, 141786752, + 142106336, 142425856, 142745312, 143064720, 143384048, 143703312, + 144022512, 144341664, 144660736, 144979744, 145298704, 145617584, + 145936400, 146255168, 146573856, 146892480, 147211040, 147529536, + 147847968, 148166336, 148484640, 148802880, 149121056, 149439152, + 149757200, 150075168, 150393072, 150710912, 151028688, 151346400, + 151664048, 151981616, 152299136, 152616576, 152933952, 153251264, + 153568496, 153885680, 154202784, 154519824, 154836784, 155153696, + 155470528, 155787296, 156104000, 156420624, 156737200, 157053696, + 157370112, 157686480, 158002768, 158318976, 158635136, 158951216, + 159267232, 159583168, 159899040, 160214848, 160530592, 160846256, + 161161840, 161477376, 161792832, 162108208, 162423520, 162738768, + 163053952, 163369040, 163684080, 163999040, 164313936, 164628752, + 164943504, 165258176, 165572784, 165887312, 166201776, 166516160, + 166830480, 167144736, 167458912, 167773008, 168087040, 168400992, + 168714880, 169028688, 169342432, 169656096, 169969696, 170283216, + 170596672, 170910032, 171223344, 171536576, 171849728, 172162800, + 172475808, 172788736, 173101600, 173414384, 173727104, 174039728, + 174352288, 174664784, 174977200, 175289536, 175601792, 175913984, + 176226096, 176538144, 176850096, 177161984, 177473792, 177785536, + 178097200, 178408784, 178720288, 179031728, 179343088, 179654368, + 179965568, 180276704, 180587744, 180898720, 181209616, 181520448, + 181831184, 182141856, 182452448, 182762960, 183073408, 183383760, + 183694048, 184004240, 184314368, 184624416, 184934400, 185244288, + 185554096, 185863840, 186173504, 186483072, 186792576, 187102000, + 187411344, 187720608, 188029808, 188338912, 188647936, 188956896, + 189265760, 189574560, 189883264, 190191904, 190500448, 190808928, + 191117312, 191425632, 191733872, 192042016, 192350096, 192658096, + 192966000, 193273840, 193581584, 193889264, 194196848, 194504352, + 194811792, 195119136, 195426400, 195733584, 196040688, 196347712, + 196654656, 196961520, 197268304, 197574992, 197881616, 198188144, + 198494592, 198800960, 199107248, 199413456, 199719584, 200025616, + 200331584, 200637456, 200943248, 201248960, 201554576, 201860128, + 202165584, 202470960, 202776256, 203081456, 203386592, 203691632, + 203996592, 204301472, 204606256, 204910976, 205215600, 205520144, + 205824592, 206128960, 206433248, 206737456, 207041584, 207345616, + 207649568, 207953424, 208257216, 208560912, 208864512, 209168048, + 209471488, 209774832, 210078112, 210381296, 210684384, 210987408, + 211290336, 211593184, 211895936, 212198608, 212501184, 212803680, + 213106096, 213408432, 213710672, 214012816, 214314880, 214616864, + 214918768, 215220576, 215522288, 215823920, 216125472, 216426928, + 216728304, 217029584, 217330784, 217631904, 217932928, 218233856, + 218534704, 218835472, 219136144, 219436720, 219737216, 220037632, + 220337952, 220638192, 220938336, 221238384, 221538352, 221838240, + 222138032, 222437728, 222737344, 223036880, 223336304, 223635664, + 223934912, 224234096, 224533168, 224832160, 225131072, 225429872, + 225728608, 226027232, 226325776, 226624240, 226922608, 227220880, + 227519056, 227817152, 228115168, 228413088, 228710912, 229008640, + 229306288, 229603840, 229901312, 230198688, 230495968, 230793152, + 231090256, 231387280, 231684192, 231981024, 232277760, 232574416, + 232870960, 233167440, 233463808, 233760096, 234056288, 234352384, + 234648384, 234944304, 235240128, 235535872, 235831504, 236127056, + 236422512, 236717888, 237013152, 237308336, 237603424, 237898416, + 238193328, 238488144, 238782864, 239077488, 239372016, 239666464, + 239960816, 240255072, 240549232, 240843312, 241137280, 241431168, + 241724960, 242018656, 242312256, 242605776, 242899200, 243192512, + 243485744, 243778896, 244071936, 244364880, 244657744, 244950496, + 245243168, 245535744, 245828224, 246120608, 246412912, 246705104, + 246997216, 247289216, 247581136, 247872960, 248164688, 248456320, + 248747856, 249039296, 249330640, 249621904, 249913056, 250204128, + 250495088, 250785968, 251076736, 251367424, 251658016, 251948512, + 252238912, 252529200, 252819408, 253109520, 253399536, 253689456, + 253979280, 254269008, 254558640, 254848176, 255137632, 255426976, + 255716224, 256005376, 256294432, 256583392, 256872256, 257161024, + 257449696, 257738272, 258026752, 258315136, 258603424, 258891600, + 259179696, 259467696, 259755600, 260043392, 260331104, 260618704, + 260906224, 261193632, 261480960, 261768176, 262055296, 262342320, + 262629248, 262916080, 263202816, 263489456, 263776000, 264062432, + 264348784, 264635024, 264921168, 265207216, 265493168, 265779024, + 266064784, 266350448, 266636000, 266921472, 267206832, 267492096, + 267777264, 268062336, 268347312, 268632192, 268916960, 269201632, + 269486208, 269770688, 270055072, 270339360, 270623552, 270907616, + 271191616, 271475488, 271759296, 272042976, 272326560, 272610048, + 272893440, 273176736, 273459936, 273743040, 274026048, 274308928, + 274591744, 274874432, 275157024, 275439520, 275721920, 276004224, + 276286432, 276568512, 276850528, 277132416, 277414240, 277695936, + 277977536, 278259040, 278540448, 278821728, 279102944, 279384032, + 279665056, 279945952, 280226752, 280507456, 280788064, 281068544, + 281348960, 281629248, 281909472, 282189568, 282469568, 282749440, + 283029248, 283308960, 283588544, 283868032, 284147424, 284426720, + 284705920, 284985024, 285264000, 285542912, 285821696, 286100384, + 286378976, 286657440, 286935840, 287214112, 287492320, 287770400, + 288048384, 288326240, 288604032, 288881696, 289159264, 289436768, + 289714112, 289991392, 290268576, 290545632, 290822592, 291099456, + 291376224, 291652896, 291929440, 292205888, 292482272, 292758528, + 293034656, 293310720, 293586656, 293862496, 294138240, 294413888, + 294689440, 294964864, 295240192, 295515424, 295790560, 296065600, + 296340512, 296615360, 296890080, 297164704, 297439200, 297713632, + 297987936, 298262144, 298536256, 298810240, 299084160, 299357952, + 299631648, 299905248, 300178720, 300452128, 300725408, 300998592, + 301271680, 301544640, 301817536, 302090304, 302362976, 302635520, + 302908000, 303180352, 303452608, 303724768, 303996800, 304268768, + 304540608, 304812320, 305083968, 305355520, 305626944, 305898272, + 306169472, 306440608, 306711616, 306982528, 307253344, 307524064, + 307794656, 308065152, 308335552, 308605856, 308876032, 309146112, + 309416096, 309685984, 309955744, 310225408, 310494976, 310764448, + 311033824, 311303072, 311572224, 311841280, 312110208, 312379040, + 312647776, 312916416, 313184960, 313453376, 313721696, 313989920, + 314258016, 314526016, 314793920, 315061728, 315329408, 315597024, + 315864512, 316131872, 316399168, 316666336, 316933408, 317200384, + 317467232, 317733984, 318000640, 318267200, 318533632, 318799968, + 319066208, 319332352, 319598368, 319864288, 320130112, 320395808, + 320661408, 320926912, 321192320, 321457632, 321722816, 321987904, + 322252864, 322517760, 322782528, 323047200, 323311744, 323576192, + 323840544, 324104800, 324368928, 324632992, 324896928, 325160736, + 325424448, 325688096, 325951584, 326215008, 326478304, 326741504, + 327004608, 327267584, 327530464, 327793248, 328055904, 328318496, + 328580960, 328843296, 329105568, 329367712, 329629760, 329891680, + 330153536, 330415264, 330676864, 330938400, 331199808, 331461120, + 331722304, 331983392, 332244384, 332505280, 332766048, 333026752, + 333287296, 333547776, 333808128, 334068384, 334328544, 334588576, + 334848512, 335108352, 335368064, 335627712, 335887200, 336146624, + 336405920, 336665120, 336924224, 337183200, 337442112, 337700864, + 337959552, 338218112, 338476576, 338734944, 338993184, 339251328, + 339509376, 339767296, 340025120, 340282848, 340540480, 340797984, + 341055392, 341312704, 341569888, 341826976, 342083968, 342340832, + 342597600, 342854272, 343110848, 343367296, 343623648, 343879904, + 344136032, 344392064, 344648000, 344903808, 345159520, 345415136, + 345670656, 345926048, 346181344, 346436512, 346691616, 346946592, + 347201440, 347456224, 347710880, 347965440, 348219872, 348474208, + 348728448, 348982592, 349236608, 349490528, 349744320, 349998048, + 350251648, 350505152, 350758528, 351011808, 351264992, 351518048, + 351771040, 352023872, 352276640, 352529280, 352781824, 353034272, + 353286592, 353538816, 353790944, 354042944, 354294880, 354546656, + 354798368, 355049952, 355301440, 355552800, 355804096, 356055264, + 356306304, 356557280, 356808128, 357058848, 357309504, 357560032, + 357810464, 358060768, 358311008, 358561088, 358811104, 359060992, + 359310784, 359560480, 359810048, 360059520, 360308896, 360558144, + 360807296, 361056352, 361305312, 361554144, 361802880, 362051488, + 362300032, 362548448, 362796736, 363044960, 363293056, 363541024, + 363788928, 364036704, 364284384, 364531936, 364779392, 365026752, + 365274016, 365521152, 365768192, 366015136, 366261952, 366508672, + 366755296, 367001792, 367248192, 367494496, 367740704, 367986784, + 368232768, 368478656, 368724416, 368970080, 369215648, 369461088, + 369706432, 369951680, 370196800, 370441824, 370686752, 370931584, + 371176288, 371420896, 371665408, 371909792, 372154080, 372398272, + 372642336, 372886304, 373130176, 373373952, 373617600, 373861152, + 374104608, 374347936, 374591168, 374834304, 375077312, 375320224, + 375563040, 375805760, 376048352, 376290848, 376533248, 376775520, + 377017696, 377259776, 377501728, 377743584, 377985344, 378227008, + 378468544, 378709984, 378951328, 379192544, 379433664, 379674688, + 379915584, 380156416, 380397088, 380637696, 380878176, 381118560, + 381358848, 381599040, 381839104, 382079072, 382318912, 382558656, + 382798304, 383037856, 383277280, 383516640, 383755840, 383994976, + 384233984, 384472896, 384711712, 384950400, 385188992, 385427488, + 385665888, 385904160, 386142336, 386380384, 386618368, 386856224, + 387093984, 387331616, 387569152, 387806592, 388043936, 388281152, + 388518272, 388755296, 388992224, 389229024, 389465728, 389702336, + 389938816, 390175200, 390411488, 390647680, 390883744, 391119712, + 391355584, 391591328, 391826976, 392062528, 392297984, 392533312, + 392768544, 393003680, 393238720, 393473632, 393708448, 393943168, + 394177760, 394412256, 394646656, 394880960, 395115136, 395349216, + 395583200, 395817088, 396050848, 396284512, 396518080, 396751520, + 396984864, 397218112, 397451264, 397684288, 397917248, 398150080, + 398382784, 398615424, 398847936, 399080320, 399312640, 399544832, + 399776928, 400008928, 400240832, 400472608, 400704288, 400935872, + 401167328, 401398720, 401629984, 401861120, 402092192, 402323136, + 402553984, 402784736, 403015360, 403245888, 403476320, 403706656, + 403936896, 404167008, 404397024, 404626944, 404856736, 405086432, + 405316032, 405545536, 405774912, 406004224, 406233408, 406462464, + 406691456, 406920320, 407149088, 407377760, 407606336, 407834784, + 408063136, 408291392, 408519520, 408747584, 408975520, 409203360, + 409431072, 409658720, 409886240, 410113664, 410340992, 410568192, + 410795296, 411022304, 411249216, 411476032, 411702720, 411929312, + 412155808, 412382176, 412608480, 412834656, 413060736, 413286720, + 413512576, 413738336, 413964000, 414189568, 414415040, 414640384, + 414865632, 415090784, 415315840, 415540800, 415765632, 415990368, + 416215008, 416439552, 416663968, 416888288, 417112512, 417336640, + 417560672, 417784576, 418008384, 418232096, 418455712, 418679200, + 418902624, 419125920, 419349120, 419572192, 419795200, 420018080, + 420240864, 420463552, 420686144, 420908608, 421130976, 421353280, + 421575424, 421797504, 422019488, 422241344, 422463104, 422684768, + 422906336, 423127776, 423349120, 423570400, 423791520, 424012576, + 424233536, 424454368, 424675104, 424895744, 425116288, 425336736, + 425557056, 425777280, 425997408, 426217440, 426437376, 426657184, + 426876928, 427096544, 427316064, 427535488, 427754784, 427974016, + 428193120, 428412128, 428631040, 428849856, 429068544, 429287168, + 429505664, 429724064, 429942368, 430160576, 430378656, 430596672, + 430814560, 431032352, 431250048, 431467616, 431685120, 431902496, + 432119808, 432336992, 432554080, 432771040, 432987936, 433204736, + 433421408, 433637984, 433854464, 434070848, 434287104, 434503296, + 434719360, 434935360, 435151232, 435367008, 435582656, 435798240, + 436013696, 436229088, 436444352, 436659520, 436874592, 437089568, + 437304416, 437519200, 437733856, 437948416, 438162880, 438377248, + 438591520, 438805696, 439019744, 439233728, 439447584, 439661344, + 439875008, 440088576, 440302048, 440515392, 440728672, 440941824, + 441154880, 441367872, 441580736, 441793472, 442006144, 442218720, + 442431168, 442643552, 442855808, 443067968, 443280032, 443492000, + 443703872, 443915648, 444127296, 444338880, 444550336, 444761696, + 444972992, 445184160, 445395232, 445606176, 445817056, 446027840, + 446238496, 446449088, 446659552, 446869920, 447080192, 447290400, + 447500448, 447710432, 447920320, 448130112, 448339776, 448549376, + 448758848, 448968224, 449177536, 449386720, 449595808, 449804800, + 450013664, 450222464, 450431168, 450639776, 450848256, 451056640, + 451264960, 451473152, 451681248, 451889248, 452097152, 452304960, + 452512672, 452720288, 452927808, 453135232, 453342528, 453549760, + 453756864, 453963904, 454170816, 454377632, 454584384, 454791008, + 454997536, 455203968, 455410304, 455616544, 455822688, 456028704, + 456234656, 456440512, 456646240, 456851904, 457057472, 457262912, + 457468256, 457673536, 457878688, 458083744, 458288736, 458493600, + 458698368, 458903040, 459107616, 459312096, 459516480, 459720768, + 459924960, 460129056, 460333056, 460536960, 460740736, 460944448, + 461148064, 461351584, 461554976, 461758304, 461961536, 462164640, + 462367680, 462570592, 462773440, 462976160, 463178816, 463381344, + 463583776, 463786144, 463988384, 464190560, 464392608, 464594560, + 464796448, 464998208, 465199872, 465401472, 465602944, 465804320, + 466005600, 466206816, 466407904, 466608896, 466809824, 467010624, + 467211328, 467411936, 467612480, 467812896, 468013216, 468213440, + 468413600, 468613632, 468813568, 469013440, 469213184, 469412832, + 469612416, 469811872, 470011232, 470210528, 470409696, 470608800, + 470807776, 471006688, 471205472, 471404192, 471602784, 471801312, + 471999712, 472198048, 472396288, 472594400, 472792448, 472990400, + 473188256, 473385984, 473583648, 473781216, 473978688, 474176064, + 474373344, 474570528, 474767616, 474964608, 475161504, 475358336, + 475555040, 475751648, 475948192, 476144608, 476340928, 476537184, + 476733312, 476929376, 477125344, 477321184, 477516960, 477712640, + 477908224, 478103712, 478299104, 478494400, 478689600, 478884704, + 479079744, 479274656, 479469504, 479664224, 479858880, 480053408, + 480247872, 480442240, 480636512, 480830656, 481024736, 481218752, + 481412640, 481606432, 481800128, 481993760, 482187264, 482380704, + 482574016, 482767264, 482960416, 483153472, 483346432, 483539296, + 483732064, 483924768, 484117344, 484309856, 484502240, 484694560, + 484886784, 485078912, 485270944, 485462880, 485654720, 485846464, + 486038144, 486229696, 486421184, 486612576, 486803840, 486995040, + 487186176, 487377184, 487568096, 487758912, 487949664, 488140320, + 488330880, 488521312, 488711712, 488901984, 489092160, 489282240, + 489472256, 489662176, 489851968, 490041696, 490231328, 490420896, + 490610336, 490799712, 490988960, 491178144, 491367232, 491556224, + 491745120, 491933920, 492122656, 492311264, 492499808, 492688256, + 492876608, 493064864, 493253056, 493441120, 493629120, 493817024, + 494004832, 494192544, 494380160, 494567712, 494755136, 494942496, + 495129760, 495316928, 495504000, 495691008, 495877888, 496064704, + 496251424, 496438048, 496624608, 496811040, 496997408, 497183680, + 497369856, 497555936, 497741920, 497927840, 498113632, 498299360, + 498484992, 498670560, 498856000, 499041376, 499226656, 499411840, + 499596928, 499781920, 499966848, 500151680, 500336416, 500521056, + 500705600, 500890080, 501074464, 501258752, 501442944, 501627040, + 501811072, 501995008, 502178848, 502362592, 502546240, 502729824, + 502913312, 503096704, 503280000, 503463232, 503646368, 503829408, + 504012352, 504195200, 504377984, 504560672, 504743264, 504925760, + 505108192, 505290496, 505472736, 505654912, 505836960, 506018944, + 506200832, 506382624, 506564320, 506745952, 506927488, 507108928, + 507290272, 507471552, 507652736, 507833824, 508014816, 508195744, + 508376576, 508557312, 508737952, 508918528, 509099008, 509279392, + 509459680, 509639904, 509820032, 510000064, 510180000, 510359872, + 510539648, 510719328, 510898944, 511078432, 511257856, 511437216, + 511616448, 511795616, 511974688, 512153664, 512332576, 512511392, + 512690112, 512868768, 513047296, 513225792, 513404160, 513582432, + 513760640, 513938784, 514116800, 514294752, 514472608, 514650368, + 514828064, 515005664, 515183168, 515360608, 515537952, 515715200, + 515892352, 516069440, 516246432, 516423328, 516600160, 516776896, + 516953536, 517130112, 517306592, 517482976, 517659264, 517835488, + 518011616, 518187680, 518363648, 518539520, 518715296, 518891008, + 519066624, 519242144, 519417600, 519592960, 519768256, 519943424, + 520118528, 520293568, 520468480, 520643328, 520818112, 520992800, + 521167392, 521341888, 521516320, 521690656, 521864896, 522039072, + 522213152, 522387168, 522561056, 522734912, 522908640, 523082304, + 523255872, 523429376, 523602784, 523776096, 523949312, 524122464, + 524295552, 524468512, 524641440, 524814240, 524986976, 525159616, + 525332192, 525504640, 525677056, 525849344, 526021568, 526193728, + 526365792, 526537760, 526709632, 526881440, 527053152, 527224800, + 527396352, 527567840, 527739200, 527910528, 528081728, 528252864, + 528423936, 528594880, 528765760, 528936576, 529107296, 529277920, + 529448480, 529618944, 529789344, 529959648, 530129856, 530300000, + 530470048, 530640000, 530809888, 530979712, 531149440, 531319072, + 531488608, 531658080, 531827488, 531996800, 532166016, 532335168, + 532504224, 532673184, 532842080, 533010912, 533179616, 533348288, + 533516832, 533685312, 533853728, 534022048, 534190272, 534358432, + 534526496, 534694496, 534862400, 535030240, 535197984, 535365632, + 535533216, 535700704, 535868128, 536035456, 536202720, 536369888, + 536536992, 536704000, 536870912, }; -// Now where did these came from? +/* Now where did these came from? */ + const byte gammatable[5][256] = { + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255}, + { - 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, - 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, - 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, - 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, - 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, - 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96, - 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, - 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, - 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, - 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, - 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, - 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 + 2, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, + 21, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 37, + 38, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 230, 231, 232, 233, 234, 235, 236, 237, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 245, 246, 247, 248, 249, 250, 251, 252, + 252, 253, 254, 255, }, { - 2,4,5,7,8,10,11,12,14,15,16,18,19,20,21,23, - 24,25,26,27,29,30,31,32,33,34,36,37,38,39,40,41, - 42,44,45,46,47,48,49,50,51,52,54,55,56,57,58,59, - 60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76, - 77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92, - 93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108, - 109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124, - 125,126,127,128,129,129,130,131,132,133,134,135,136,137,138,139, - 140,141,142,143,144,145,146,147,148,148,149,150,151,152,153,154, - 155,156,157,158,159,160,161,162,163,163,164,165,166,167,168,169, - 170,171,172,173,174,175,175,176,177,178,179,180,181,182,183,184, - 185,186,186,187,188,189,190,191,192,193,194,195,196,196,197,198, - 199,200,201,202,203,204,205,205,206,207,208,209,210,211,212,213, - 214,214,215,216,217,218,219,220,221,222,222,223,224,225,226,227, - 228,229,230,230,231,232,233,234,235,236,237,237,238,239,240,241, - 242,243,244,245,245,246,247,248,249,250,251,252,252,253,254,255 + 4, 7, 9, 11, 13, 15, 17, 19, 21, 22, 24, 26, 27, 29, + 30, 32, 33, 35, 36, 38, 39, 40, 42, 43, 45, 46, 47, 48, + 50, 51, 52, 54, 55, 56, 57, 59, 60, 61, 62, 63, 65, 66, + 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 153, 154, 155, 156, 157, 158, 159, 160, 160, 161, 162, + 163, 164, 165, 166, 166, 167, 168, 169, 170, 171, 172, 172, 173, 174, + 175, 176, 177, 178, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186, + 187, 188, 188, 189, 190, 191, 192, 193, 193, 194, 195, 196, 197, 197, + 198, 199, 200, 201, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, + 210, 210, 211, 212, 213, 213, 214, 215, 216, 217, 217, 218, 219, 220, + 221, 221, 222, 223, 224, 224, 225, 226, 227, 228, 228, 229, 230, 231, + 231, 232, 233, 234, 235, 235, 236, 237, 238, 238, 239, 240, 241, 241, + 242, 243, 244, 244, 245, 246, 247, 247, 248, 249, 250, 251, 251, 252, + 253, 254, 254, 255, }, { - 4,7,9,11,13,15,17,19,21,22,24,26,27,29,30,32, - 33,35,36,38,39,40,42,43,45,46,47,48,50,51,52,54, - 55,56,57,59,60,61,62,63,65,66,67,68,69,70,72,73, - 74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90, - 91,92,93,94,95,96,97,98,100,101,102,103,104,105,106,107, - 108,109,110,111,112,113,114,114,115,116,117,118,119,120,121,122, - 123,124,125,126,127,128,129,130,131,132,133,133,134,135,136,137, - 138,139,140,141,142,143,144,144,145,146,147,148,149,150,151,152, - 153,153,154,155,156,157,158,159,160,160,161,162,163,164,165,166, - 166,167,168,169,170,171,172,172,173,174,175,176,177,178,178,179, - 180,181,182,183,183,184,185,186,187,188,188,189,190,191,192,193, - 193,194,195,196,197,197,198,199,200,201,201,202,203,204,205,206, - 206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218, - 219,220,221,221,222,223,224,224,225,226,227,228,228,229,230,231, - 231,232,233,234,235,235,236,237,238,238,239,240,241,241,242,243, - 244,244,245,246,247,247,248,249,250,251,251,252,253,254,254,255 + 8, 12, 16, 19, 22, 24, 27, 29, 31, 34, 36, 38, 40, 41, + 43, 45, 47, 49, 50, 52, 53, 55, 57, 58, 60, 61, 63, 64, + 65, 67, 68, 70, 71, 72, 74, 75, 76, 77, 79, 80, 81, 82, + 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 143, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, + 153, 154, 155, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, + 165, 165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 173, 174, 175, + 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, 185, 186, + 186, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, + 197, 197, 198, 199, 200, 200, 201, 202, 202, 203, 204, 205, 205, 206, + 207, 207, 208, 209, 210, 210, 211, 212, 212, 213, 214, 214, 215, 216, + 216, 217, 218, 219, 219, 220, 221, 221, 222, 223, 223, 224, 225, 225, + 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235, + 235, 236, 237, 237, 238, 238, 239, 240, 240, 241, 242, 242, 243, 244, + 244, 245, 246, 246, 247, 247, 248, 249, 249, 250, 251, 251, 252, 253, + 253, 254, 254, 255, }, { - 8,12,16,19,22,24,27,29,31,34,36,38,40,41,43,45, - 47,49,50,52,53,55,57,58,60,61,63,64,65,67,68,70, - 71,72,74,75,76,77,79,80,81,82,84,85,86,87,88,90, - 91,92,93,94,95,96,98,99,100,101,102,103,104,105,106,107, - 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123, - 124,125,126,127,128,129,130,131,132,133,134,135,135,136,137,138, - 139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152, - 153,154,155,155,156,157,158,159,160,160,161,162,163,164,165,165, - 166,167,168,169,169,170,171,172,173,173,174,175,176,176,177,178, - 179,180,180,181,182,183,183,184,185,186,186,187,188,189,189,190, - 191,192,192,193,194,195,195,196,197,197,198,199,200,200,201,202, - 202,203,204,205,205,206,207,207,208,209,210,210,211,212,212,213, - 214,214,215,216,216,217,218,219,219,220,221,221,222,223,223,224, - 225,225,226,227,227,228,229,229,230,231,231,232,233,233,234,235, - 235,236,237,237,238,238,239,240,240,241,242,242,243,244,244,245, - 246,246,247,247,248,249,249,250,251,251,252,253,253,254,254,255 + 16, 23, 28, 32, 36, 39, 42, 45, 48, 50, 53, 55, 57, 60, + 62, 64, 66, 68, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, + 86, 87, 89, 90, 92, 93, 94, 96, 97, 98, 100, 101, 102, 103, + 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 143, 144, 145, 146, + 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, + 159, 159, 160, 161, 162, 163, 163, 164, 165, 166, 166, 167, 168, 169, + 169, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, + 180, 180, 181, 182, 182, 183, 184, 184, 185, 186, 187, 187, 188, 189, + 189, 190, 191, 191, 192, 193, 193, 194, 195, 195, 196, 196, 197, 198, + 198, 199, 200, 200, 201, 202, 202, 203, 203, 204, 205, 205, 206, 207, + 207, 208, 208, 209, 210, 210, 211, 211, 212, 213, 213, 214, 214, 215, + 216, 216, 217, 217, 218, 219, 219, 220, 220, 221, 221, 222, 223, 223, + 224, 224, 225, 225, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, + 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 239, + 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, + 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, + 254, 254, 255, 255, }, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/* to get a global angle from cartesian coordinates, the coordinates are + * flipped until they are in the first octant of the coordinate system, then + * the y (<=x) is scaled and divided by x to get a tangent (slope) value + * which is looked up in the tantoangle[] table. The +1 size is to handle + * the case when x==y without additional checking. + */ +int slope_div(unsigned int num, unsigned int den) +{ + unsigned answer; + + if (den < 512) { - 16,23,28,32,36,39,42,45,48,50,53,55,57,60,62,64, - 66,68,69,71,73,75,76,78,80,81,83,84,86,87,89,90, - 92,93,94,96,97,98,100,101,102,103,105,106,107,108,109,110, - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128, - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156, - 157,158,159,159,160,161,162,163,163,164,165,166,166,167,168,169, - 169,170,171,172,172,173,174,175,175,176,177,177,178,179,180,180, - 181,182,182,183,184,184,185,186,187,187,188,189,189,190,191,191, - 192,193,193,194,195,195,196,196,197,198,198,199,200,200,201,202, - 202,203,203,204,205,205,206,207,207,208,208,209,210,210,211,211, - 212,213,213,214,214,215,216,216,217,217,218,219,219,220,220,221, - 221,222,223,223,224,224,225,225,226,227,227,228,228,229,229,230, - 230,231,232,232,233,233,234,234,235,235,236,236,237,237,238,239, - 239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247, - 247,248,248,249,249,250,250,251,251,252,252,253,254,254,255,255 + return SLOPERANGE; } -}; + else + { + answer = (num << 3) / (den >> 8); + if (answer <= SLOPERANGE) + { + return answer; + } + else + { + return SLOPERANGE; + } + } +} diff --git a/games/NXDoom/src/tables.h b/games/NXDoom/src/tables.h index f72406da4d1..1a30ee74ef2 100644 --- a/games/NXDoom/src/tables.h +++ b/games/NXDoom/src/tables.h @@ -1,96 +1,125 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Lookup tables. -// Do not try to look them up :-). -// In the order of appearance: -// -// int finetangent[4096] - Tangens LUT. -// Should work with BAM fairly well (12 of 16bit, -// effectively, by shifting). -// -// int finesine[10240] - Sine lookup. -// Guess what, serves as cosine, too. -// Remarkable thing is, how to use BAMs with this? -// -// int tantoangle[2049] - ArcTan LUT, -// maps tan(angle) to angle fast. Gotta search. -// - +/**************************************************************************** + * apps/games/NXDoom/src/tables.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 1993-2008 Raven Software + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Lookup tables. + * Do not try to look them up :-). + * In the order of appearance: + * + * int finetangent[4096] - Tangens LUT. + * Should work with BAM fairly well (12 of 16bit, effectively, + * by shifting). + * + * int finesine[10240] - Sine lookup. + * Guess what, serves as cosine, too. + * Remarkable thing is, how to use BAMs with this? + * + * int tantoangle[2049] - ArcTan LUT, + * maps tan(angle) to angle fast. Gotta search. + * + * + * DESCRIPTION: + * System specific interface stuff. + * + ****************************************************************************/ #ifndef __TABLES__ #define __TABLES__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" #include "m_fixed.h" - -#define FINEANGLES 8192 -#define FINEMASK (FINEANGLES-1) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// 0x100000000 to 0x2000 -#define ANGLETOFINESHIFT 19 +#define FINEANGLES 8192 +#define FINEMASK (FINEANGLES - 1) -// Effective size is 10240. -extern const fixed_t finesine[5*FINEANGLES/4]; +/* 0x100000000 to 0x2000 */ -// Re-use data, is just PI/2 pahse shift. -extern const fixed_t *finecosine; +#define ANGLETOFINESHIFT 19 +/* Binary Angle Measurement, BAM. */ -// Effective size is 4096. -extern const fixed_t finetangent[FINEANGLES/2]; +#define ANG45 0x20000000 +#define ANG90 0x40000000 +#define ANG180 0x80000000 +#define ANG270 0xc0000000 +#define ANG_MAX 0xffffffff -// Gamma correction tables. -extern const byte gammatable[5][256]; +#define ANG1 (ANG45 / 45) +#define ANG60 (ANG180 / 3) -// Binary Angle Measument, BAM. +/* Heretic code uses this definition as though it represents one + * degree, but it is not! This is actually ~1.40 degrees. + */ -#define ANG45 0x20000000 -#define ANG90 0x40000000 -#define ANG180 0x80000000 -#define ANG270 0xc0000000 -#define ANG_MAX 0xffffffff +#define ANG1_X 0x01000000 -#define ANG1 (ANG45 / 45) -#define ANG60 (ANG180 / 3) +#define SLOPERANGE 2048 +#define SLOPEBITS 11 +#define DBITS (FRACBITS - SLOPEBITS) -// Heretic code uses this definition as though it represents one -// degree, but it is not! This is actually ~1.40 degrees. +/**************************************************************************** + * Public Types + ****************************************************************************/ -#define ANG1_X 0x01000000 +typedef unsigned int angle_t; -#define SLOPERANGE 2048 -#define SLOPEBITS 11 -#define DBITS (FRACBITS-SLOPEBITS) +/**************************************************************************** + * Public Data + ****************************************************************************/ -typedef unsigned int angle_t; +/* Effective size is 10240. */ + +extern const fixed_t finesine[5 * FINEANGLES / 4]; +/* Reuse data, is just PI/2 pahse shift. */ + +extern const fixed_t *finecosine; + +/* Effective size is 4096. */ + +extern const fixed_t finetangent[FINEANGLES / 2]; + +/* Gamma correction tables. */ + +extern const byte gammatable[5][256]; -// Effective size is 2049; -// The +1 size is to handle the case when x==y -// without additional checking. -extern const angle_t tantoangle[SLOPERANGE+1]; +/* Effective size is 2049; + * The +1 size is to handle the case when x==y without additional checking. + */ +extern const angle_t tantoangle[SLOPERANGE + 1]; -// Utility function, -// called by R_PointToAngle. -int SlopeDiv(unsigned int num, unsigned int den); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +/* Utility function, called by r_point_to_angle. */ -#endif +int slope_div(unsigned int num, unsigned int den); +#endif /* __TABLES__ */ diff --git a/games/NXDoom/src/v_diskicon.c b/games/NXDoom/src/v_diskicon.c index 1631ba7b992..755d281a93a 100644 --- a/games/NXDoom/src/v_diskicon.c +++ b/games/NXDoom/src/v_diskicon.c @@ -1,23 +1,32 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Disk load indicator. -// +/**************************************************************************** + * apps/games/NXDoom/src/v_diskicon.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Disk load indicator. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ -#include "doomtype.h" #include "deh_str.h" +#include "doomtype.h" #include "i_swap.h" #include "i_video.h" #include "m_argv.h" @@ -29,132 +38,148 @@ #include -// Only display the disk icon if more then this much bytes have been read -// during the previous tic. +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Only display the disk icon if more then this much bytes have been read + * during the previous tic. + */ -static const int diskicon_threshold = 20*1024; +static const int diskicon_threshold = 20 * 1024; + +/* Two buffers: disk_data contains the data representing the disk icon + * (raw, not a patch_t) while saved_background is an equivalently-sized + * buffer where we save the background data while the disk is on screen. + */ -// Two buffers: disk_data contains the data representing the disk icon -// (raw, not a patch_t) while saved_background is an equivalently-sized -// buffer where we save the background data while the disk is on screen. static pixel_t *disk_data; static pixel_t *saved_background; static int loading_disk_xoffs = 0; static int loading_disk_yoffs = 0; -// Number of bytes read since the last call to V_DrawDiskIcon(). +/* Number of bytes read since the last call to v_draw_disk_icon(). */ + static size_t recent_bytes_read = 0; static boolean disk_drawn; -static void CopyRegion(pixel_t *dest, int dest_pitch, - pixel_t *src, int src_pitch, - int w, int h) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void copy_region(pixel_t *dest, int dest_pitch, pixel_t *src, + int src_pitch, int w, int h) { - pixel_t *s, *d; - int y; + pixel_t *s, *d; + int y; - s = src; d = dest; - for (y = 0; y < h; ++y) + s = src; + d = dest; + for (y = 0; y < h; ++y) { - memcpy(d, s, w * sizeof(*d)); - s += src_pitch; - d += dest_pitch; + memcpy(d, s, w * sizeof(*d)); + s += src_pitch; + d += dest_pitch; } } -static void SaveDiskData(const char *disk_lump, int xoffs, int yoffs) +static void save_disk_data(const char *disk_lump, int xoffs, int yoffs) { - pixel_t *tmpscreen; - patch_t *disk; + pixel_t *tmpscreen; + patch_t *disk; + + /* Allocate a complete temporary screen where we'll draw the patch. */ - // Allocate a complete temporary screen where we'll draw the patch. - tmpscreen = Z_Malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*tmpscreen), - PU_STATIC, NULL); - memset(tmpscreen, 0, SCREENWIDTH * SCREENHEIGHT * sizeof(*tmpscreen)); - V_UseBuffer(tmpscreen); + tmpscreen = z_malloc(SCREENWIDTH * SCREENHEIGHT * sizeof(*tmpscreen), + PU_STATIC, NULL); + memset(tmpscreen, 0, SCREENWIDTH * SCREENHEIGHT * sizeof(*tmpscreen)); + v_use_buffer(tmpscreen); - // Buffer where we'll save the disk data. + /* Buffer where we'll save the disk data. */ - if (disk_data != NULL) + if (disk_data != NULL) { - Z_Free(disk_data); - disk_data = NULL; + z_free(disk_data); + disk_data = NULL; } - disk_data = Z_Malloc(LOADING_DISK_W * LOADING_DISK_H * sizeof(*disk_data), - PU_STATIC, NULL); + disk_data = z_malloc(LOADING_DISK_W * LOADING_DISK_H * sizeof(*disk_data), + PU_STATIC, NULL); + + /* Draw the patch and save the result to disk_data. */ - // Draw the patch and save the result to disk_data. - disk = W_CacheLumpName(disk_lump, PU_STATIC); - V_DrawPatch(loading_disk_xoffs, loading_disk_yoffs, disk); - CopyRegion(disk_data, LOADING_DISK_W, - tmpscreen + yoffs * SCREENWIDTH + xoffs, SCREENWIDTH, - LOADING_DISK_W, LOADING_DISK_H); - W_ReleaseLumpName(disk_lump); + disk = w_cache_lump_name(disk_lump, PU_STATIC); + v_draw_patch(loading_disk_xoffs, loading_disk_yoffs, disk); + copy_region(disk_data, LOADING_DISK_W, + tmpscreen + yoffs * SCREENWIDTH + xoffs, SCREENWIDTH, + LOADING_DISK_W, LOADING_DISK_H); + w_release_lump_name(disk_lump); + + v_restore_buffer(); + z_free(tmpscreen); +} - V_RestoreBuffer(); - Z_Free(tmpscreen); +static pixel_t *disk_region_pointer(void) +{ + return i_video_buffer + loading_disk_yoffs * SCREENWIDTH + + loading_disk_xoffs; } -void V_EnableLoadingDisk(const char *lump_name, int xoffs, int yoffs) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void v_enable_loading_disk(const char *lump_name, int xoffs, int yoffs) { - loading_disk_xoffs = xoffs; - loading_disk_yoffs = yoffs; + loading_disk_xoffs = xoffs; + loading_disk_yoffs = yoffs; - if (saved_background != NULL) + if (saved_background != NULL) { - Z_Free(saved_background); - saved_background = NULL; + z_free(saved_background); + saved_background = NULL; } - saved_background = Z_Malloc(LOADING_DISK_W * LOADING_DISK_H - * sizeof(*saved_background), - PU_STATIC, NULL); - SaveDiskData(lump_name, xoffs, yoffs); -} - -void V_BeginRead(size_t nbytes) -{ - recent_bytes_read += nbytes; + saved_background = + z_malloc(LOADING_DISK_W * LOADING_DISK_H * sizeof(*saved_background), + PU_STATIC, NULL); + save_disk_data(lump_name, xoffs, yoffs); } -static pixel_t *DiskRegionPointer(void) +void v_begin_read(size_t nbytes) { - return I_VideoBuffer - + loading_disk_yoffs * SCREENWIDTH - + loading_disk_xoffs; + recent_bytes_read += nbytes; } -void V_DrawDiskIcon(void) +void v_draw_disk_icon(void) { - if (disk_data != NULL && recent_bytes_read > diskicon_threshold) + if (disk_data != NULL && recent_bytes_read > diskicon_threshold) { - // Save the background behind the disk before we draw it. - CopyRegion(saved_background, LOADING_DISK_W, - DiskRegionPointer(), SCREENWIDTH, - LOADING_DISK_W, LOADING_DISK_H); - - // Write the disk to the screen buffer. - CopyRegion(DiskRegionPointer(), SCREENWIDTH, - disk_data, LOADING_DISK_W, - LOADING_DISK_W, LOADING_DISK_H); - disk_drawn = true; + /* Save the background behind the disk before we draw it. */ + + copy_region(saved_background, LOADING_DISK_W, disk_region_pointer(), + SCREENWIDTH, LOADING_DISK_W, LOADING_DISK_H); + + /* Write the disk to the screen buffer. */ + + copy_region(disk_region_pointer(), SCREENWIDTH, disk_data, + LOADING_DISK_W, LOADING_DISK_W, LOADING_DISK_H); + disk_drawn = true; } - recent_bytes_read = 0; + recent_bytes_read = 0; } -void V_RestoreDiskBackground(void) +void v_restore_disk_background(void) { - if (disk_drawn) + if (disk_drawn) { - // Restore the background. - CopyRegion(DiskRegionPointer(), SCREENWIDTH, - saved_background, LOADING_DISK_W, - LOADING_DISK_W, LOADING_DISK_H); + /* Restore the background. */ - disk_drawn = false; + copy_region(disk_region_pointer(), SCREENWIDTH, saved_background, + LOADING_DISK_W, LOADING_DISK_W, LOADING_DISK_H); + + disk_drawn = false; } } - diff --git a/games/NXDoom/src/v_diskicon.h b/games/NXDoom/src/v_diskicon.h index 0dee04d1989..4bd9b54aa80 100644 --- a/games/NXDoom/src/v_diskicon.h +++ b/games/NXDoom/src/v_diskicon.h @@ -1,32 +1,46 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Disk load indicator. -// +/**************************************************************************** + * apps/games/NXDoom/src/v_diskicon.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Disk load indicator. + * + ****************************************************************************/ #ifndef __V_DISKICON__ #define __V_DISKICON__ -// Dimensions of the flashing "loading" disk icon +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Dimensions of the flashing "loading" disk icon */ #define LOADING_DISK_W 16 #define LOADING_DISK_H 16 -extern void V_EnableLoadingDisk(const char *lump_name, int xoffs, int yoffs); -extern void V_BeginRead(size_t nbytes); -extern void V_DrawDiskIcon(void); -extern void V_RestoreDiskBackground(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +extern void v_enable_loading_disk(const char *lump_name, int xoffs, + int yoffs); +extern void v_begin_read(size_t nbytes); +extern void v_draw_disk_icon(void); +extern void v_restore_disk_background(void); -#endif +#endif /* __V_DISKICON__ */ diff --git a/games/NXDoom/src/v_patch.h b/games/NXDoom/src/v_patch.h index 767f9e3a288..5bfac559c04 100644 --- a/games/NXDoom/src/v_patch.h +++ b/games/NXDoom/src/v_patch.h @@ -1,50 +1,70 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Refresh/rendering module, shared data struct definitions. -// - +/**************************************************************************** + * apps/games/NXDoom/src/v_patch.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Refresh/rendering module, shared data struct definitions. + * + ****************************************************************************/ #ifndef V_PATCH_H #define V_PATCH_H -// Patches. -// A patch holds one or more columns. -// Patches are used for sprites and all masked pictures, -// and we compose textures from the TEXTURE1/2 lists -// of patches. +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Patches. + * A patch holds one or more columns. + * Patches are used for sprites and all masked pictures, + * and we compose textures from the TEXTURE1/2 lists + * of patches. + */ -typedef PACKED_STRUCT ( +begin_packed_struct struct patch_t { - short width; // bounding box size - short height; - short leftoffset; // pixels to the left of origin - short topoffset; // pixels below the origin - int columnofs[8]; // only [width] used - // the [0] is &columnofs[width] -}) patch_t; - -// posts are runs of non masked source pixels -typedef PACKED_STRUCT ( + short width; /* bounding box size */ + short height; + short leftoffset; /* pixels to the left of origin */ + short topoffset; /* pixels below the origin */ + int columnofs[8]; /* only [width] used the [0] is &columnofs[width] */ +} end_packed_struct; + +typedef struct patch_t patch_t; + +/* posts are runs of non masked source pixels */ + +begin_packed_struct struct post_t { - byte topdelta; // -1 is the last post in a column - byte length; // length data bytes follows -}) post_t; + byte topdelta; /* -1 is the last post in a column */ + byte length; /* length data bytes follows */ +} end_packed_struct; + +typedef struct post_t post_t; -// column_t is a list of 0 or more post_t, (byte)-1 terminated -typedef post_t column_t; +/* column_t is a list of 0 or more post_t, (byte)-1 terminated */ -#endif +typedef post_t column_t; +#endif /* V_PATCH_H */ diff --git a/games/NXDoom/src/v_video.c b/games/NXDoom/src/v_video.c index c35f259f405..55f455ccee8 100644 --- a/games/NXDoom/src/v_video.c +++ b/games/NXDoom/src/v_video.c @@ -1,28 +1,37 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 1993-2008 Raven Software -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Gamma correction LUT stuff. -// Functions to draw patches (by post) directly to screen. -// Functions to blit a block to the screen. -// +/**************************************************************************** + * apps/games/NXDoom/src/v_video.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 1993-2008 Raven Software + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Gamma correction LUT stuff. + * Functions to draw patches (by post) directly to screen. + * Functions to blit a block to the screen. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include #include "i_system.h" @@ -39,985 +48,834 @@ #include "z_zone.h" #include "config.h" -#ifdef HAVE_LIBPNG -#include -#endif -// TODO: There are separate RANGECHECK defines for different games, but this -// is common code. Fix this. -#define RANGECHECK +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Blending table used for fuzzpatch, etc. -// Only used in Heretic/Hexen +#define MOUSE_SPEED_BOX_WIDTH 120 +#define MOUSE_SPEED_BOX_HEIGHT 9 +#define MOUSE_SPEED_BOX_X (SCREENWIDTH - MOUSE_SPEED_BOX_WIDTH - 10) +#define MOUSE_SPEED_BOX_Y 15 -byte *tinttable = NULL; +/**************************************************************************** + * Private Types + ****************************************************************************/ -// villsa [STRIFE] Blending table used for Strife -byte *xlatab = NULL; +/* SCREEN SHOTS */ + +begin_packed_struct struct pcx_t +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + + unsigned short xmin; + unsigned short ymin; + unsigned short xmax; + unsigned short ymax; + + unsigned short hres; + unsigned short vres; + + unsigned char palette[48]; + + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + + char filler[58]; + unsigned char data; /* unbounded */ +} end_packed_struct; -// The screen buffer that the v_video.c code draws to. +typedef struct pcx_t pcx_t; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The screen buffer that the v_video.c code draws to. */ static pixel_t *dest_screen = NULL; -int dirtybox[4]; +/* haleyjd 08/28/10: clipping callback function for patches. + * This is needed for Chocolate Strife, which clips patches to the screen. + */ -// haleyjd 08/28/10: clipping callback function for patches. -// This is needed for Chocolate Strife, which clips patches to the screen. static vpatchclipfunc_t patchclip_callback = NULL; -// -// V_MarkRect -// -void V_MarkRect(int x, int y, int width, int height) -{ - // If we are temporarily using an alternate screen, do not - // affect the update box. - - if (dest_screen == I_VideoBuffer) - { - M_AddToBox (dirtybox, x, y); - M_AddToBox (dirtybox, x + width-1, y + height-1); - } -} - - -// -// V_CopyRect -// -void V_CopyRect(int srcx, int srcy, pixel_t *source, - int width, int height, - int destx, int desty) -{ - pixel_t *src; - pixel_t *dest; - -#ifdef RANGECHECK - if (srcx < 0 - || srcx + width > SCREENWIDTH - || srcy < 0 - || srcy + height > SCREENHEIGHT - || destx < 0 - || destx + width > SCREENWIDTH - || desty < 0 - || desty + height > SCREENHEIGHT) - { - I_Error ("Bad V_CopyRect"); - } -#endif - - V_MarkRect(destx, desty, width, height); - - src = source + SCREENWIDTH * srcy + srcx; - dest = dest_screen + SCREENWIDTH * desty + destx; - - for ( ; height>0 ; height--) - { - memcpy(dest, src, width * sizeof(*dest)); - src += SCREENWIDTH; - dest += SCREENWIDTH; - } -} - -// -// V_SetPatchClipCallback -// -// haleyjd 08/28/10: Added for Strife support. -// By calling this function, you can setup runtime error checking for patch -// clipping. Strife never caused errors by drawing patches partway off-screen. -// Some versions of vanilla DOOM also behaved differently than the default -// implementation, so this could possibly be extended to those as well for -// accurate emulation. -// -void V_SetPatchClipCallback(vpatchclipfunc_t func) +/* Highest seen mouse turn speed. We scale the range of the thermometer + * according to this value, so that it never exceeds the range. Initially + * this is set to a 1:1 setting where 1 pixel = 1 unit of speed. + */ + +static int max_seen_speed = MOUSE_SPEED_BOX_WIDTH - 1; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Blending table used for fuzzpatch, etc. Only used in Heretic/Hexen */ + +byte *tinttable = NULL; + +/* villsa [STRIFE] Blending table used for Strife */ + +byte *xlatab = NULL; + +int dirtybox[4]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void draw_accelerating_box(int speed) { - patchclip_callback = func; -} + int red; + int white; + int yellow; + int original_speed; + int redline_x; + int linelen; -// -// V_DrawPatch -// Masks a column based masked pic to the screen. -// + red = i_get_palette_index(0xff, 0x00, 0x00); + white = i_get_palette_index(0xff, 0xff, 0xff); + yellow = i_get_palette_index(0xff, 0xff, 0x00); -void V_DrawPatch(int x, int y, patch_t *patch) -{ - int count; - int col; - column_t *column; - pixel_t *desttop; - pixel_t *dest; - byte *source; - int w; + /* Calculate the position of the red threshold line when calibrating + * acceleration. This is 1/3 of the way along the box. + */ - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); + redline_x = MOUSE_SPEED_BOX_WIDTH / 3; - // haleyjd 08/28/10: Strife needs silent error checking here. - if(patchclip_callback) + if (speed >= mouse_threshold) { - if(!patchclip_callback(patch, x, y)) - return; + /* Undo acceleration and get back the original mouse speed */ + + original_speed = speed - mouse_threshold; + original_speed = (int)(original_speed / mouse_acceleration); + original_speed += mouse_threshold; + + linelen = (original_speed * redline_x) / mouse_threshold; } + else + { + linelen = (speed * redline_x) / mouse_threshold; + } + + /* Horizontal "thermometer" */ -#ifdef RANGECHECK - if (x < 0 - || x + SHORT(patch->width) > SCREENWIDTH - || y < 0 - || y + SHORT(patch->height) > SCREENHEIGHT) + if (linelen > MOUSE_SPEED_BOX_WIDTH - 1) { - I_Error("Bad V_DrawPatch"); + linelen = MOUSE_SPEED_BOX_WIDTH - 1; + } + + if (linelen < redline_x) + { + v_draw_horiz_line(MOUSE_SPEED_BOX_X + 1, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + linelen, white); + } + else + { + v_draw_horiz_line(MOUSE_SPEED_BOX_X + 1, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + redline_x, white); + v_draw_horiz_line(MOUSE_SPEED_BOX_X + redline_x, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, + linelen - redline_x, yellow); } -#endif - V_MarkRect(x, y, SHORT(patch->width), SHORT(patch->height)); + /* Draw acceleration threshold line */ + + v_draw_vert_line(MOUSE_SPEED_BOX_X + redline_x, MOUSE_SPEED_BOX_Y + 1, + MOUSE_SPEED_BOX_HEIGHT - 2, red); +} - col = 0; - desttop = dest_screen + y * SCREENWIDTH + x; +static void draw_non_accelerating_box(int speed) +{ + int white; + int linelen; - w = SHORT(patch->width); + white = i_get_palette_index(0xff, 0xff, 0xff); - for ( ; col max_seen_speed) { - column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); + max_seen_speed = speed; + } - // step through the posts in a column - while (column->topdelta != 0xff) - { - source = (byte *)column + 3; - dest = desttop + column->topdelta*SCREENWIDTH; - count = column->length; + /* Draw horizontal "thermometer": */ - while (count--) - { - *dest = *source++; - dest += SCREENWIDTH; - } - column = (column_t *)((byte *)column + column->length + 4); + linelen = speed * (MOUSE_SPEED_BOX_WIDTH - 1) / max_seen_speed; + + v_draw_horiz_line(MOUSE_SPEED_BOX_X + 1, + MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, linelen, + white); +} + +static void write_pcx_file(char *filename, pixel_t *data, int width, + int height, byte *palette) +{ + int i; + int length; + pcx_t *pcx; + byte *pack; + + pcx = z_malloc(width * height * 2 + 1000, PU_STATIC, NULL); + + pcx->manufacturer = 0x0a; /* PCX id */ + pcx->version = 5; /* 256 color */ + pcx->encoding = 1; /* uncompressed */ + pcx->bits_per_pixel = 8; /* 256 color */ + pcx->xmin = 0; + pcx->ymin = 0; + pcx->xmax = SHORT(width - 1); + pcx->ymax = SHORT(height - 1); + pcx->hres = SHORT(1); + pcx->vres = SHORT(1); + memset(pcx->palette, 0, sizeof(pcx->palette)); + pcx->reserved = 0; /* PCX spec: reserved byte must be zero */ + pcx->color_planes = 1; /* chunky image */ + pcx->bytes_per_line = SHORT(width); + pcx->palette_type = SHORT(2); /* not a grey scale */ + memset(pcx->filler, 0, sizeof(pcx->filler)); + + /* pack the image */ + + pack = &pcx->data; + + for (i = 0; i < width * height; i++) + { + if ((*data & 0xc0) != 0xc0) + *pack++ = *data++; + else + { + *pack++ = 0xc1; + *pack++ = *data++; } } + + /* write the palette */ + + *pack++ = 0x0c; /* palette ID byte */ + for (i = 0; i < 768; i++) + *pack++ = *palette++; + + /* write output file */ + + length = pack - (byte *)pcx; + m_write_file(filename, pcx, length); + + z_free(pcx); } -// -// V_DrawPatchFlipped -// Masks a column based masked pic to the screen. -// Flips horizontally, e.g. to mirror face. -// +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void V_DrawPatchFlipped(int x, int y, patch_t *patch) +void v_mark_rect(int x, int y, int width, int height) { - int count; - int col; - column_t *column; - pixel_t *desttop; - pixel_t *dest; - byte *source; - int w; - - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); + /* If we are temporarily using an alternate screen, do not affect the + * update box. + */ - // haleyjd 08/28/10: Strife needs silent error checking here. - if(patchclip_callback) + if (dest_screen == i_video_buffer) { - if(!patchclip_callback(patch, x, y)) - return; + m_add_to_box(dirtybox, x, y); + m_add_to_box(dirtybox, x + width - 1, y + height - 1); } +} + +void v_copy_rect(int srcx, int srcy, pixel_t *source, int width, int height, + int destx, int desty) +{ + pixel_t *src; + pixel_t *dest; -#ifdef RANGECHECK - if (x < 0 - || x + SHORT(patch->width) > SCREENWIDTH - || y < 0 - || y + SHORT(patch->height) > SCREENHEIGHT) +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (srcx < 0 || srcx + width > SCREENWIDTH || srcy < 0 || + srcy + height > SCREENHEIGHT || destx < 0 || + destx + width > SCREENWIDTH || desty < 0 || + desty + height > SCREENHEIGHT) { - I_Error("Bad V_DrawPatchFlipped"); + i_error("Bad v_copy_rect"); } #endif - V_MarkRect (x, y, SHORT(patch->width), SHORT(patch->height)); + v_mark_rect(destx, desty, width, height); - col = 0; - desttop = dest_screen + y * SCREENWIDTH + x; + src = source + SCREENWIDTH * srcy + srcx; + dest = dest_screen + SCREENWIDTH * desty + destx; - w = SHORT(patch->width); - - for ( ; col 0; height--) { - column = (column_t *)((byte *)patch + LONG(patch->columnofs[w-1-col])); - - // step through the posts in a column - while (column->topdelta != 0xff ) - { - source = (byte *)column + 3; - dest = desttop + column->topdelta*SCREENWIDTH; - count = column->length; - - while (count--) - { - *dest = *source++; - dest += SCREENWIDTH; - } - column = (column_t *)((byte *)column + column->length + 4); - } + memcpy(dest, src, width * sizeof(*dest)); + src += SCREENWIDTH; + dest += SCREENWIDTH; } } +/* v_set_patch_clip_callback + * + * haleyjd 08/28/10: Added for Strife support. + * By calling this function, you can setup runtime error checking for patch + * clipping. Strife never caused errors by drawing patches partway + * off-screen. + * + * Some versions of vanilla DOOM also behaved differently than the default + * implementation, so this could possibly be extended to those as well for + * accurate emulation. + */ + +void v_set_patch_clip_callback(vpatchclipfunc_t func) +{ + patchclip_callback = func; +} +/* V_DrawPatch + * Masks a column based masked pic to the screen. + */ -// -// V_DrawPatchDirect -// Draws directly to the screen on the pc. -// - -void V_DrawPatchDirect(int x, int y, patch_t *patch) +void v_draw_patch(int x, int y, patch_t *patch) { - V_DrawPatch(x, y, patch); -} + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + int w; -// -// V_DrawTLPatch -// -// Masks a column based translucent masked pic to the screen. -// + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); -void V_DrawTLPatch(int x, int y, patch_t * patch) -{ - int count, col; - column_t *column; - pixel_t *desttop, *dest; - byte *source; - int w; + /* haleyjd 08/28/10: Strife needs silent error checking here. */ - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); + if (patchclip_callback) + { + if (!patchclip_callback(patch, x, y)) return; + } - if (x < 0 - || x + SHORT(patch->width) > SCREENWIDTH - || y < 0 - || y + SHORT(patch->height) > SCREENHEIGHT) +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (x < 0 || x + SHORT(patch->width) > SCREENWIDTH || y < 0 || + y + SHORT(patch->height) > SCREENHEIGHT) { - I_Error("Bad V_DrawTLPatch"); + i_error("Bad V_DrawPatch"); } +#endif - col = 0; - desttop = dest_screen + y * SCREENWIDTH + x; + v_mark_rect(x, y, SHORT(patch->width), SHORT(patch->height)); - w = SHORT(patch->width); - for (; col < w; x++, col++, desttop++) + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + + w = SHORT(patch->width); + + for (; col < w; x++, col++, desttop++) { - column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); - // step through the posts in a column + /* step through the posts in a column */ - while (column->topdelta != 0xff) + while (column->topdelta != 0xff) { - source = (byte *) column + 3; - dest = desttop + column->topdelta * SCREENWIDTH; - count = column->length; + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; - while (count--) + while (count--) { - *dest = tinttable[*dest + ((*source++) << 8)]; - dest += SCREENWIDTH; + *dest = *source++; + dest += SCREENWIDTH; } - column = (column_t *) ((byte *) column + column->length + 4); + + column = (column_t *)((byte *)column + column->length + 4); } } } -// -// V_DrawXlaPatch -// -// villsa [STRIFE] Masks a column based translucent masked pic to the screen. -// +/* v_draw_patch_flipped + * Masks a column based masked pic to the screen. + * Flips horizontally, e.g. to mirror face. + */ -void V_DrawXlaPatch(int x, int y, patch_t * patch) +void v_draw_patch_flipped(int x, int y, patch_t *patch) { - int count, col; - column_t *column; - pixel_t *desttop, *dest; - byte *source; - int w; + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + int w; - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); - if(patchclip_callback) + /* haleyjd 08/28/10: Strife needs silent error checking here. */ + + if (patchclip_callback) + { + if (!patchclip_callback(patch, x, y)) return; + } + +#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK + if (x < 0 || x + SHORT(patch->width) > SCREENWIDTH || y < 0 || + y + SHORT(patch->height) > SCREENHEIGHT) { - if(!patchclip_callback(patch, x, y)) - return; + i_error("Bad v_draw_patch_flipped"); } +#endif + + v_mark_rect(x, y, SHORT(patch->width), SHORT(patch->height)); + + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; - col = 0; - desttop = dest_screen + y * SCREENWIDTH + x; + w = SHORT(patch->width); - w = SHORT(patch->width); - for(; col < w; x++, col++, desttop++) + for (; col < w; x++, col++, desttop++) { - column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + column = + (column_t *)((byte *)patch + LONG(patch->columnofs[w - 1 - col])); - // step through the posts in a column + /* step through the posts in a column */ - while(column->topdelta != 0xff) + while (column->topdelta != 0xff) { - source = (byte *) column + 3; - dest = desttop + column->topdelta * SCREENWIDTH; - count = column->length; + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; - while(count--) + while (count--) { - *dest = xlatab[*dest + ((*source) << 8)]; - source++; - dest += SCREENWIDTH; + *dest = *source++; + dest += SCREENWIDTH; } - column = (column_t *) ((byte *) column + column->length + 4); + + column = (column_t *)((byte *)column + column->length + 4); } } } -// -// V_DrawAltTLPatch -// -// Masks a column based translucent masked pic to the screen. -// +/* v_draw_patch_direct + * Draws directly to the screen on the pc. + */ -void V_DrawAltTLPatch(int x, int y, patch_t * patch) +void v_draw_patch_direct(int x, int y, patch_t *patch) { - int count, col; - column_t *column; - pixel_t *desttop, *dest; - byte *source; - int w; + v_draw_patch(x, y, patch); +} - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); +/* v_draw_tl_patch + * Masks a column based translucent masked pic to the screen. + */ + +void v_draw_tl_patch(int x, int y, patch_t *patch) +{ + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + int w; - if (x < 0 - || x + SHORT(patch->width) > SCREENWIDTH - || y < 0 - || y + SHORT(patch->height) > SCREENHEIGHT) + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); + + if (x < 0 || x + SHORT(patch->width) > SCREENWIDTH || y < 0 || + y + SHORT(patch->height) > SCREENHEIGHT) { - I_Error("Bad V_DrawAltTLPatch"); + i_error("Bad v_draw_tl_patch"); } - col = 0; - desttop = dest_screen + y * SCREENWIDTH + x; + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; - w = SHORT(patch->width); - for (; col < w; x++, col++, desttop++) + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++) { - column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); - // step through the posts in a column + /* step through the posts in a column */ - while (column->topdelta != 0xff) + while (column->topdelta != 0xff) { - source = (byte *) column + 3; - dest = desttop + column->topdelta * SCREENWIDTH; - count = column->length; + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; - while (count--) + while (count--) { - *dest = tinttable[((*dest) << 8) + *source++]; - dest += SCREENWIDTH; + *dest = tinttable[*dest + ((*source++) << 8)]; + dest += SCREENWIDTH; } - column = (column_t *) ((byte *) column + column->length + 4); + + column = (column_t *)((byte *)column + column->length + 4); } } } -// -// V_DrawShadowedPatch -// -// Masks a column based masked pic to the screen. -// +/* v_draw_xla_patch + * villsa [STRIFE] Masks a column based translucent masked pic to the screen. + */ -void V_DrawShadowedPatch(int x, int y, patch_t *patch) +void v_draw_xla_patch(int x, int y, patch_t *patch) { - int count, col; - column_t *column; - pixel_t *desttop, *dest; - byte *source; - pixel_t *desttop2, *dest2; - int w; + int count; + int col; + column_t *column; + pixel_t *desttop, *dest; + byte *source; + int w; - y -= SHORT(patch->topoffset); - x -= SHORT(patch->leftoffset); + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); - if (x < 0 - || x + SHORT(patch->width) > SCREENWIDTH - || y < 0 - || y + SHORT(patch->height) > SCREENHEIGHT) + if (patchclip_callback) { - I_Error("Bad V_DrawShadowedPatch"); + if (!patchclip_callback(patch, x, y)) return; } - col = 0; - desttop = dest_screen + y * SCREENWIDTH + x; - desttop2 = dest_screen + (y + 2) * SCREENWIDTH + x + 2; + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; - w = SHORT(patch->width); - for (; col < w; x++, col++, desttop++, desttop2++) + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++) { - column = (column_t *) ((byte *) patch + LONG(patch->columnofs[col])); + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); - // step through the posts in a column + /* step through the posts in a column */ - while (column->topdelta != 0xff) + while (column->topdelta != 0xff) { - source = (byte *) column + 3; - dest = desttop + column->topdelta * SCREENWIDTH; - dest2 = desttop2 + column->topdelta * SCREENWIDTH; - count = column->length; + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; - while (count--) + while (count--) { - *dest2 = tinttable[((*dest2) << 8)]; - dest2 += SCREENWIDTH; - *dest = *source++; - dest += SCREENWIDTH; - + *dest = xlatab[*dest + ((*source) << 8)]; + source++; + dest += SCREENWIDTH; } - column = (column_t *) ((byte *) column + column->length + 4); + + column = (column_t *)((byte *)column + column->length + 4); } } } -// -// Load tint table from TINTTAB lump. -// +/* v_draw_alt_tl_patch + * Masks a column based translucent masked pic to the screen. + */ -void V_LoadTintTable(void) +void v_draw_alt_tl_patch(int x, int y, patch_t *patch) { - tinttable = W_CacheLumpName("TINTTAB", PU_STATIC); -} + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + int w; -// -// V_LoadXlaTable -// -// villsa [STRIFE] Load xla table from XLATAB lump. -// + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); -void V_LoadXlaTable(void) -{ - xlatab = W_CacheLumpName("XLATAB", PU_STATIC); -} - -// -// V_DrawBlock -// Draw a linear block of pixels into the view buffer. -// - -void V_DrawBlock(int x, int y, int width, int height, pixel_t *src) -{ - pixel_t *dest; - -#ifdef RANGECHECK - if (x < 0 - || x + width >SCREENWIDTH - || y < 0 - || y + height > SCREENHEIGHT) - { - I_Error ("Bad V_DrawBlock"); - } -#endif - - V_MarkRect (x, y, width, height); - - dest = dest_screen + y * SCREENWIDTH + x; - - while (height--) - { - memcpy (dest, src, width * sizeof(*dest)); - src += width; - dest += SCREENWIDTH; - } -} - -void V_DrawFilledBox(int x, int y, int w, int h, int c) -{ - pixel_t *buf, *buf1; - int x1, y1; + if (x < 0 || x + SHORT(patch->width) > SCREENWIDTH || y < 0 || + y + SHORT(patch->height) > SCREENHEIGHT) + { + i_error("Bad v_draw_alt_tl_patch"); + } - buf = I_VideoBuffer + SCREENWIDTH * y + x; + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; - for (y1 = 0; y1 < h; ++y1) + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++) { - buf1 = buf; + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); - for (x1 = 0; x1 < w; ++x1) - { - *buf1++ = c; - } + /* step through the posts in a column */ - buf += SCREENWIDTH; - } -} - -void V_DrawHorizLine(int x, int y, int w, int c) -{ - pixel_t *buf; - int x1; + while (column->topdelta != 0xff) + { + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + count = column->length; - buf = I_VideoBuffer + SCREENWIDTH * y + x; + while (count--) + { + *dest = tinttable[((*dest) << 8) + *source++]; + dest += SCREENWIDTH; + } - for (x1 = 0; x1 < w; ++x1) - { - *buf++ = c; + column = (column_t *)((byte *)column + column->length + 4); + } } } -void V_DrawVertLine(int x, int y, int h, int c) +/* v_draw_shadowed_patch + * Masks a column based masked pic to the screen. + */ + +void v_draw_shadowed_patch(int x, int y, patch_t *patch) { - pixel_t *buf; - int y1; + int count; + int col; + column_t *column; + pixel_t *desttop; + pixel_t *dest; + byte *source; + pixel_t *desttop2; + pixel_t *dest2; + int w; - buf = I_VideoBuffer + SCREENWIDTH * y + x; + y -= SHORT(patch->topoffset); + x -= SHORT(patch->leftoffset); - for (y1 = 0; y1 < h; ++y1) + if (x < 0 || x + SHORT(patch->width) > SCREENWIDTH || y < 0 || + y + SHORT(patch->height) > SCREENHEIGHT) { - *buf = c; - buf += SCREENWIDTH; + i_error("Bad v_draw_shadowed_patch"); } -} -void V_DrawBox(int x, int y, int w, int h, int c) -{ - V_DrawHorizLine(x, y, w, c); - V_DrawHorizLine(x, y+h-1, w, c); - V_DrawVertLine(x, y, h, c); - V_DrawVertLine(x+w-1, y, h, c); -} - -// -// Draw a "raw" screen (lump containing raw data to blit directly -// to the screen) -// - -void V_DrawRawScreen(pixel_t *raw) -{ - memcpy(dest_screen, raw, SCREENWIDTH * SCREENHEIGHT * sizeof(*dest_screen)); -} + col = 0; + desttop = dest_screen + y * SCREENWIDTH + x; + desttop2 = dest_screen + (y + 2) * SCREENWIDTH + x + 2; -// -// V_Init -// -void V_Init (void) -{ - // no-op! - // There used to be separate screens that could be drawn to; these are - // now handled in the upper layers. -} + w = SHORT(patch->width); + for (; col < w; x++, col++, desttop++, desttop2++) + { + column = (column_t *)((byte *)patch + LONG(patch->columnofs[col])); -// Set the buffer that the code draws to. + /* step through the posts in a column */ -void V_UseBuffer(pixel_t *buffer) -{ - dest_screen = buffer; -} + while (column->topdelta != 0xff) + { + source = (byte *)column + 3; + dest = desttop + column->topdelta * SCREENWIDTH; + dest2 = desttop2 + column->topdelta * SCREENWIDTH; + count = column->length; -// Restore screen buffer to the i_video screen buffer. + while (count--) + { + *dest2 = tinttable[((*dest2) << 8)]; + dest2 += SCREENWIDTH; + *dest = *source++; + dest += SCREENWIDTH; + } -void V_RestoreBuffer(void) -{ - dest_screen = I_VideoBuffer; + column = (column_t *)((byte *)column + column->length + 4); + } + } } -// -// SCREEN SHOTS -// +/* Load tint table from TINTTAB lump. */ -typedef PACKED_STRUCT ( +void v_load_tint_table(void) { - char manufacturer; - char version; - char encoding; - char bits_per_pixel; - - unsigned short xmin; - unsigned short ymin; - unsigned short xmax; - unsigned short ymax; - - unsigned short hres; - unsigned short vres; - - unsigned char palette[48]; - - char reserved; - char color_planes; - unsigned short bytes_per_line; - unsigned short palette_type; - - char filler[58]; - unsigned char data; // unbounded -}) pcx_t; - - -// -// WritePCXfile -// - -void WritePCXfile(char *filename, pixel_t *data, - int width, int height, - byte *palette) -{ - int i; - int length; - pcx_t* pcx; - byte* pack; - - pcx = Z_Malloc (width*height*2+1000, PU_STATIC, NULL); - - pcx->manufacturer = 0x0a; // PCX id - pcx->version = 5; // 256 color - pcx->encoding = 1; // uncompressed - pcx->bits_per_pixel = 8; // 256 color - pcx->xmin = 0; - pcx->ymin = 0; - pcx->xmax = SHORT(width-1); - pcx->ymax = SHORT(height-1); - pcx->hres = SHORT(1); - pcx->vres = SHORT(1); - memset (pcx->palette,0,sizeof(pcx->palette)); - pcx->reserved = 0; // PCX spec: reserved byte must be zero - pcx->color_planes = 1; // chunky image - pcx->bytes_per_line = SHORT(width); - pcx->palette_type = SHORT(2); // not a grey scale - memset (pcx->filler,0,sizeof(pcx->filler)); - - // pack the image - pack = &pcx->data; - - for (i=0 ; i SCREENWIDTH || y < 0 || y + height > SCREENHEIGHT) { - // scale up to accommodate aspect ratio correction - w_factor = 5; - h_factor = 6; - - width *= w_factor; - height *= h_factor; - } - else - { - w_factor = 1; - h_factor = 1; + i_error("Bad v_draw_block"); } +#endif - handle = M_fopen(filename, "wb"); - if (!handle) - { - return; - } + v_mark_rect(x, y, width, height); - ppng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, - error_fn, warning_fn); - if (!ppng) - { - fclose(handle); - return; - } + dest = dest_screen + y * SCREENWIDTH + x; - pinfo = png_create_info_struct(ppng); - if (!pinfo) + while (height--) { - fclose(handle); - png_destroy_write_struct(&ppng, NULL); - return; + memcpy(dest, src, width * sizeof(*dest)); + src += width; + dest += SCREENWIDTH; } +} - png_init_io(ppng, handle); - - png_set_IHDR(ppng, pinfo, width, height, - 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); +void v_draw_filled_box(int x, int y, int w, int h, int c) +{ + pixel_t *buf, *buf1; + int x1; + int y1; - pcolor = malloc(sizeof(*pcolor) * 256); - if (!pcolor) - { - fclose(handle); - png_destroy_write_struct(&ppng, &pinfo); - return; - } + buf = i_video_buffer + SCREENWIDTH * y + x; - for (i = 0; i < 256; i++) + for (y1 = 0; y1 < h; ++y1) { - pcolor[i].red = *(palette + 3 * i); - pcolor[i].green = *(palette + 3 * i + 1); - pcolor[i].blue = *(palette + 3 * i + 2); - } - - png_set_PLTE(ppng, pinfo, pcolor, 256); - free(pcolor); + buf1 = buf; - png_write_info(ppng, pinfo); - - rowbuf = malloc(width); - - if (rowbuf) - { - for (i = 0; i < SCREENHEIGHT; i++) + for (x1 = 0; x1 < w; ++x1) { - // expand the row 5x - for (j = 0; j < SCREENWIDTH; j++) - { - memset(rowbuf + j * w_factor, *(data + i*SCREENWIDTH + j), w_factor); - } - - // write the row 6 times - for (j = 0; j < h_factor; j++) - { - png_write_row(ppng, rowbuf); - } + *buf1++ = c; } - free(rowbuf); + buf += SCREENWIDTH; } - - png_write_end(ppng, pinfo); - png_destroy_write_struct(&ppng, &pinfo); - fclose(handle); } -#endif -// -// V_ScreenShot -// - -void V_ScreenShot(const char *format) +void v_draw_horiz_line(int x, int y, int w, int c) { - int i; - char lbmname[16]; // haleyjd 20110213: BUG FIX - 12 is too small! - const char *ext; - - // find a file name to save it to + pixel_t *buf; + int x1; -#ifdef HAVE_LIBPNG - if (png_screenshots) - { - ext = "png"; - } - else -#endif - { - ext = "pcx"; - } + buf = i_video_buffer + SCREENWIDTH * y + x; - for (i=0; i<=99; i++) + for (x1 = 0; x1 < w; ++x1) { - M_snprintf(lbmname, sizeof(lbmname), format, i, ext); - - if (!M_FileExists(lbmname)) - { - break; // file doesn't exist - } + *buf++ = c; } +} - if (i == 100) - { -#ifdef HAVE_LIBPNG - if (png_screenshots) - { - I_Error ("V_ScreenShot: Couldn't create a PNG"); - } - else -#endif - { - I_Error ("V_ScreenShot: Couldn't create a PCX"); - } - } +void v_draw_vert_line(int x, int y, int h, int c) +{ + pixel_t *buf; + int y1; -#ifdef HAVE_LIBPNG - if (png_screenshots) - { - WritePNGfile(lbmname, I_VideoBuffer, - SCREENWIDTH, SCREENHEIGHT, - W_CacheLumpName (DEH_String("PLAYPAL"), PU_CACHE)); - } - else -#endif + buf = i_video_buffer + SCREENWIDTH * y + x; + + for (y1 = 0; y1 < h; ++y1) { - // save the pcx file - WritePCXfile(lbmname, I_VideoBuffer, - SCREENWIDTH, SCREENHEIGHT, - W_CacheLumpName (DEH_String("PLAYPAL"), PU_CACHE)); + *buf = c; + buf += SCREENWIDTH; } } -#define MOUSE_SPEED_BOX_WIDTH 120 -#define MOUSE_SPEED_BOX_HEIGHT 9 -#define MOUSE_SPEED_BOX_X (SCREENWIDTH - MOUSE_SPEED_BOX_WIDTH - 10) -#define MOUSE_SPEED_BOX_Y 15 +void v_draw_box(int x, int y, int w, int h, int c) +{ + v_draw_horiz_line(x, y, w, c); + v_draw_horiz_line(x, y + h - 1, w, c); + v_draw_vert_line(x, y, h, c); + v_draw_vert_line(x + w - 1, y, h, c); +} -// -// V_DrawMouseSpeedBox -// +/* Draw a "raw" screen (lump containing raw data to blit directly + * to the screen) + */ -static void DrawAcceleratingBox(int speed) +void v_draw_raw_screen(pixel_t *raw) { - int red, white, yellow; - int original_speed; - int redline_x; - int linelen; - - red = I_GetPaletteIndex(0xff, 0x00, 0x00); - white = I_GetPaletteIndex(0xff, 0xff, 0xff); - yellow = I_GetPaletteIndex(0xff, 0xff, 0x00); + memcpy(dest_screen, raw, + SCREENWIDTH * SCREENHEIGHT * sizeof(*dest_screen)); +} - // Calculate the position of the red threshold line when calibrating - // acceleration. This is 1/3 of the way along the box. +void v_init(void) +{ + /* no-op! + * There used to be separate screens that could be drawn to; these are + * now handled in the upper layers. + */ +} - redline_x = MOUSE_SPEED_BOX_WIDTH / 3; +/* Set the buffer that the code draws to. */ - if (speed >= mouse_threshold) - { - // Undo acceleration and get back the original mouse speed - original_speed = speed - mouse_threshold; - original_speed = (int) (original_speed / mouse_acceleration); - original_speed += mouse_threshold; +void v_use_buffer(pixel_t *buffer) +{ + dest_screen = buffer; +} - linelen = (original_speed * redline_x) / mouse_threshold; - } - else - { - linelen = (speed * redline_x) / mouse_threshold; - } +/* Restore screen buffer to the i_video screen buffer. */ - // Horizontal "thermometer" - if (linelen > MOUSE_SPEED_BOX_WIDTH - 1) - { - linelen = MOUSE_SPEED_BOX_WIDTH - 1; - } +void v_restore_buffer(void) +{ + dest_screen = i_video_buffer; +} - if (linelen < redline_x) - { - V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, - MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, - linelen, white); - } - else - { - V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, - MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, - redline_x, white); - V_DrawHorizLine(MOUSE_SPEED_BOX_X + redline_x, - MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, - linelen - redline_x, yellow); - } +void v_screenshot(const char *format) +{ + int i; + char lbmname[16]; /* haleyjd 20110213: BUG FIX - 12 is too small! */ + const char *ext; - // Draw acceleration threshold line - V_DrawVertLine(MOUSE_SPEED_BOX_X + redline_x, MOUSE_SPEED_BOX_Y + 1, - MOUSE_SPEED_BOX_HEIGHT - 2, red); -} + /* find a file name to save it to */ -// Highest seen mouse turn speed. We scale the range of the thermometer -// according to this value, so that it never exceeds the range. Initially -// this is set to a 1:1 setting where 1 pixel = 1 unit of speed. -static int max_seen_speed = MOUSE_SPEED_BOX_WIDTH - 1; + ext = "pcx"; -static void DrawNonAcceleratingBox(int speed) -{ - int white; - int linelen; + for (i = 0; i <= 99; i++) + { + snprintf(lbmname, sizeof(lbmname), format, i, ext); - white = I_GetPaletteIndex(0xff, 0xff, 0xff); + if (!m_file_exists(lbmname)) + { + break; /* file doesn't exist */ + } + } - if (speed > max_seen_speed) + if (i == 100) { - max_seen_speed = speed; + i_error("v_screenshot: Couldn't create a PCX"); } - // Draw horizontal "thermometer": - linelen = speed * (MOUSE_SPEED_BOX_WIDTH - 1) / max_seen_speed; + /* save the pcx file */ - V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, - MOUSE_SPEED_BOX_Y + MOUSE_SPEED_BOX_HEIGHT / 2, - linelen, white); + write_pcx_file(lbmname, i_video_buffer, SCREENWIDTH, SCREENHEIGHT, + w_cache_lump_name(("PLAYPAL"), PU_CACHE)); } -void V_DrawMouseSpeedBox(int speed) +void v_draw_mouse_speed_box(int speed) { - int bgcolor, bordercolor, black; + int bgcolor; + int bordercolor; + int black; - // If the mouse is turned off, don't draw the box at all. - if (!usemouse) + /* If the mouse is turned off, don't draw the box at all. */ + + if (!usemouse) { - return; + return; } - // Get palette indices for colors for widget. These depend on the - // palette of the game being played. + /* Get palette indices for colors for widget. These depend on the + * palette of the game being played. + */ - bgcolor = I_GetPaletteIndex(0x77, 0x77, 0x77); - bordercolor = I_GetPaletteIndex(0x55, 0x55, 0x55); - black = I_GetPaletteIndex(0x00, 0x00, 0x00); + bgcolor = i_get_palette_index(0x77, 0x77, 0x77); + bordercolor = i_get_palette_index(0x55, 0x55, 0x55); + black = i_get_palette_index(0x00, 0x00, 0x00); - // Calculate box position + /* Calculate box position */ - V_DrawFilledBox(MOUSE_SPEED_BOX_X, MOUSE_SPEED_BOX_Y, + v_draw_filled_box(MOUSE_SPEED_BOX_X, MOUSE_SPEED_BOX_Y, MOUSE_SPEED_BOX_WIDTH, MOUSE_SPEED_BOX_HEIGHT, bgcolor); - V_DrawBox(MOUSE_SPEED_BOX_X, MOUSE_SPEED_BOX_Y, - MOUSE_SPEED_BOX_WIDTH, MOUSE_SPEED_BOX_HEIGHT, bordercolor); - V_DrawHorizLine(MOUSE_SPEED_BOX_X + 1, MOUSE_SPEED_BOX_Y + 4, + v_draw_box(MOUSE_SPEED_BOX_X, MOUSE_SPEED_BOX_Y, MOUSE_SPEED_BOX_WIDTH, + MOUSE_SPEED_BOX_HEIGHT, bordercolor); + v_draw_horiz_line(MOUSE_SPEED_BOX_X + 1, MOUSE_SPEED_BOX_Y + 4, MOUSE_SPEED_BOX_WIDTH - 2, black); - // If acceleration is used, draw a box that helps to calibrate the - // threshold point. - if (mouse_threshold > 0 && fabs(mouse_acceleration - 1) > 0.01) + /* If acceleration is used, draw a box that helps to calibrate the + * threshold point. + */ + + if (mouse_threshold > 0 && fabs(mouse_acceleration - 1) > 0.01) { - DrawAcceleratingBox(speed); + draw_accelerating_box(speed); } - else + else { - DrawNonAcceleratingBox(speed); + draw_non_accelerating_box(speed); } } - diff --git a/games/NXDoom/src/v_video.h b/games/NXDoom/src/v_video.h index f9c18f9a74a..07ac56730d4 100644 --- a/games/NXDoom/src/v_video.h +++ b/games/NXDoom/src/v_video.h @@ -1,108 +1,181 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Gamma correction LUT. -// Functions to draw patches (by post) directly to screen. -// Functions to blit a block to the screen. -// - +/**************************************************************************** + * apps/games/NXDoom/src/v_video.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Gamma correction LUT. + * Functions to draw patches (by post) directly to screen. + * Functions to blit a block to the screen. + * + ****************************************************************************/ #ifndef __V_VIDEO__ #define __V_VIDEO__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -// Needed because we are refering to patches. +/* Needed because we are referring to patches. */ + #include "v_patch.h" -// -// VIDEO -// +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#define CENTERY (SCREENHEIGHT/2) +#define CENTERY (SCREENHEIGHT / 2) +/**************************************************************************** + * Public Data + ****************************************************************************/ extern int dirtybox[4]; extern byte *tinttable; -// haleyjd 08/28/10: implemented for Strife support -// haleyjd 08/28/10: Patch clipping callback, implemented to support Choco -// Strife. -typedef boolean (*vpatchclipfunc_t)(patch_t *, int, int); -void V_SetPatchClipCallback(vpatchclipfunc_t func); - - -// Allocates buffer screens, call before R_Init. -void V_Init (void); - -// Draw a block from the specified source screen to the screen. - -void V_CopyRect(int srcx, int srcy, pixel_t *source, - int width, int height, - int destx, int desty); - -void V_DrawPatch(int x, int y, patch_t *patch); -void V_DrawPatchFlipped(int x, int y, patch_t *patch); -void V_DrawTLPatch(int x, int y, patch_t *patch); -void V_DrawAltTLPatch(int x, int y, patch_t * patch); -void V_DrawShadowedPatch(int x, int y, patch_t *patch); -void V_DrawXlaPatch(int x, int y, patch_t * patch); // villsa [STRIFE] -void V_DrawPatchDirect(int x, int y, patch_t *patch); - -// Draw a linear block of pixels into the view buffer. - -void V_DrawBlock(int x, int y, int width, int height, pixel_t *src); - -void V_MarkRect(int x, int y, int width, int height); - -void V_DrawFilledBox(int x, int y, int w, int h, int c); -void V_DrawHorizLine(int x, int y, int w, int c); -void V_DrawVertLine(int x, int y, int h, int c); -void V_DrawBox(int x, int y, int w, int h, int c); +/* haleyjd 08/28/10: implemented for Strife support + * haleyjd 08/28/10: Patch clipping callback, implemented to support Choco + * Strife. + */ -// Draw a raw screen lump +/**************************************************************************** + * Public Types + ****************************************************************************/ -void V_DrawRawScreen(pixel_t *raw); - -// Temporarily switch to using a different buffer to draw graphics, etc. - -void V_UseBuffer(pixel_t *buffer); - -// Return to using the normal screen buffer to draw graphics. - -void V_RestoreBuffer(void); - -// Save a screenshot of the current screen to a file, named in the -// format described in the string passed to the function, eg. -// "DOOM%02i.pcx" - -void V_ScreenShot(const char *format); - -// Load the lookup table for translucency calculations from the TINTTAB -// lump. - -void V_LoadTintTable(void); - -// villsa [STRIFE] -// Load the lookup table for translucency calculations from the XLATAB -// lump. - -void V_LoadXlaTable(void); +typedef boolean (*vpatchclipfunc_t)(patch_t *, int, int); -void V_DrawMouseSpeedBox(int speed); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void v_set_patch_clip_callback(vpatchclipfunc_t func); + +/**************************************************************************** + * Name: v_init + * + * Description: + * Allocates buffer screens, call before r_init. + * + ****************************************************************************/ + +void v_init(void); + +/**************************************************************************** + * Name: v_copy_rect + * + * Description: + * Draw a block from the specified source screen to the screen. + * + ****************************************************************************/ + +void v_copy_rect(int srcx, int srcy, pixel_t *source, int width, int height, + int destx, int desty); + +void v_draw_patch(int x, int y, patch_t *patch); +void v_draw_patch_flipped(int x, int y, patch_t *patch); +void v_draw_tl_patch(int x, int y, patch_t *patch); +void v_draw_alt_tl_patch(int x, int y, patch_t *patch); +void v_draw_shadowed_patch(int x, int y, patch_t *patch); +void v_draw_xla_patch(int x, int y, patch_t *patch); /* villsa [STRIFE] */ +void v_draw_patch_direct(int x, int y, patch_t *patch); + +/**************************************************************************** + * Name: v_draw_block + * + * Description: + * Draw a linear block of pixels into the view buffer. + * + ****************************************************************************/ + +void v_draw_block(int x, int y, int width, int height, pixel_t *src); + +void v_mark_rect(int x, int y, int width, int height); + +void v_draw_filled_box(int x, int y, int w, int h, int c); +void v_draw_horiz_line(int x, int y, int w, int c); +void v_draw_vert_line(int x, int y, int h, int c); +void v_draw_box(int x, int y, int w, int h, int c); + +/**************************************************************************** + * Name: v_draw_raw_screen + * + * Description: + * Draw a raw screen lump + * + ****************************************************************************/ + +void v_draw_raw_screen(pixel_t *raw); + +/**************************************************************************** + * Name: v_use_buffer + * + * Description: + * Temporarily switch to using a different buffer to draw graphics, etc. + * + ****************************************************************************/ + +void v_use_buffer(pixel_t *buffer); + +/**************************************************************************** + * Name: v_restore_buffer + * + * Description: + * Return to using the normal screen buffer to draw graphics. + * + ****************************************************************************/ + +void v_restore_buffer(void); + +/**************************************************************************** + * Name: v_screenshot + * + * Description: + * Save a screenshot of the current screen to a file, named in the format + * described in the string passed to the function, eg. "DOOM%02i.pcx" + * + ****************************************************************************/ + +void v_screenshot(const char *format); + +/**************************************************************************** + * Name: v_load_tint_table + * + * Description: + * Load the lookup table for translucency calculations from the TINTTAB + * lump. + * + ****************************************************************************/ + +void v_load_tint_table(void); + +/**************************************************************************** + * Name: v_load_xla_table + * + * Description: + * villsa [STRIFE] + * Load the lookup table for translucency calculations from the XLATAB lump. + * + ****************************************************************************/ + +void v_load_xla_table(void); + +void v_draw_mouse_speed_box(int speed); #endif - diff --git a/games/NXDoom/src/w_checksum.c b/games/NXDoom/src/w_checksum.c index 09d8d2a6ce5..28dbf8d1676 100644 --- a/games/NXDoom/src/w_checksum.c +++ b/games/NXDoom/src/w_checksum.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Generate a checksum of the WAD directory. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_checksum.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Generate a checksum of the WAD directory. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -26,63 +35,79 @@ #include "w_checksum.h" #include "w_wad.h" -static wad_file_t **open_wadfiles = NULL; -static int num_open_wadfiles = 0; +/**************************************************************************** + * Private Data + ****************************************************************************/ -static int GetFileNumber(wad_file_t *handle) +static wad_file_t **g_open_wadfiles = NULL; +static int g_num_open_wadfiles = 0; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int get_file_number(wad_file_t *handle) { - int i; - int result; + int i; + int result; - for (i = 0; i < num_open_wadfiles; ++i) + for (i = 0; i < g_num_open_wadfiles; ++i) { - if (open_wadfiles[i] == handle) + if (g_open_wadfiles[i] == handle) { - return i; + return i; } } - // Not found in list. This is a new file we haven't seen yet. - // Allocate another slot for this file. + /* Not found in list. This is a new file we haven't seen yet. + * Allocate another slot for this file. + */ - open_wadfiles = I_Realloc(open_wadfiles, - sizeof(wad_file_t *) * (num_open_wadfiles + 1)); - open_wadfiles[num_open_wadfiles] = handle; + g_open_wadfiles = i_realloc(g_open_wadfiles, + sizeof(wad_file_t *) * (g_num_open_wadfiles + 1)); + g_open_wadfiles[g_num_open_wadfiles] = handle; - result = num_open_wadfiles; - ++num_open_wadfiles; + result = g_num_open_wadfiles; + ++g_num_open_wadfiles; - return result; + return result; } -static void ChecksumAddLump(sha1_context_t *sha1_context, lumpinfo_t *lump) +static void checksum_add_lump(SHA1_CTX *sha1_context, lumpinfo_t *lump) { - char buf[9]; + char buf[9]; + int fileno; + + fileno = get_file_number(lump->wad_file); - M_StringCopy(buf, lump->name, sizeof(buf)); - SHA1_UpdateString(sha1_context, buf); - SHA1_UpdateInt32(sha1_context, GetFileNumber(lump->wad_file)); - SHA1_UpdateInt32(sha1_context, lump->position); - SHA1_UpdateInt32(sha1_context, lump->size); + m_str_copy(buf, lump->name, sizeof(buf)); + sha1_updatestring(sha1_context, buf); + sha1_updateint32(sha1_context, fileno); + sha1_updateint32(sha1_context, lump->position); + sha1_updateint32(sha1_context, lump->size); } -void W_Checksum(sha1_digest_t digest) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void w_checksum(sha1_digest_t digest) { - sha1_context_t sha1_context; - unsigned int i; + SHA1_CTX sha1_context; + unsigned int i; - SHA1_Init(&sha1_context); + sha1init(&sha1_context); - num_open_wadfiles = 0; + g_num_open_wadfiles = 0; - // Go through each entry in the WAD directory, adding information - // about each entry to the SHA1 hash. + /* Go through each entry in the WAD directory, adding information + * about each entry to the SHA1 hash. + */ - for (i = 0; i < numlumps; ++i) + for (i = 0; i < numlumps; ++i) { - ChecksumAddLump(&sha1_context, lumpinfo[i]); + checksum_add_lump(&sha1_context, lumpinfo[i]); } - SHA1_Final(digest, &sha1_context); + sha1final(digest, &sha1_context); } - diff --git a/games/NXDoom/src/w_checksum.h b/games/NXDoom/src/w_checksum.h index e1ce5b89e87..316239b706c 100644 --- a/games/NXDoom/src/w_checksum.h +++ b/games/NXDoom/src/w_checksum.h @@ -1,27 +1,39 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Generate a checksum of the WAD directory. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_checksum.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Generate a checksum of the WAD directory. + * + ****************************************************************************/ #ifndef W_CHECKSUM_H #define W_CHECKSUM_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" -extern void W_Checksum(sha1_digest_t digest); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -#endif /* #ifndef W_CHECKSUM_H */ +extern void w_checksum(sha1_digest_t digest); +#endif /* W_CHECKSUM_H */ diff --git a/games/NXDoom/src/w_file.c b/games/NXDoom/src/w_file.c index 87fc2c95ade..38b4d9574be 100644 --- a/games/NXDoom/src/w_file.c +++ b/games/NXDoom/src/w_file.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// WAD I/O functions. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_file.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * WAD I/O functions. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -25,60 +34,59 @@ #include "w_file.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ -static wad_file_class_t *wad_file_classes[] = +static wad_file_class_t *wad_file_classes[] = { -#ifdef _WIN32 - &win32_wad_file, -#endif -#ifdef HAVE_MMAP - &posix_wad_file, -#endif - &stdc_wad_file, + &stdc_wad_file, }; -wad_file_t *W_OpenFile(const char *path) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +wad_file_t *w_open_file(const char *path) { - wad_file_t *result; - int i; + wad_file_t *result; + int i; - //! - // @category obscure - // - // Use the OS's virtual memory subsystem to map WAD files - // directly into memory. - // + /* @category obscure + * + * Use the OS's virtual memory subsystem to map WAD files + * directly into memory. + */ - if (!M_CheckParm("-mmap")) + if (!m_check_parm("-mmap")) { - return stdc_wad_file.OpenFile(path); + return stdc_wad_file.open_file(path); } - // Try all classes in order until we find one that works + /* Try all classes in order until we find one that works */ - result = NULL; + result = NULL; - for (i=0; iOpenFile(path); + result = wad_file_classes[i]->open_file(path); - if (result != NULL) + if (result != NULL) { - break; + break; } } - return result; + return result; } -void W_CloseFile(wad_file_t *wad) +void w_close_file(wad_file_t *wad) { - wad->file_class->CloseFile(wad); + wad->file_class->close_file(wad); } -size_t W_Read(wad_file_t *wad, unsigned int offset, - void *buffer, size_t buffer_len) +size_t w_read(wad_file_t *wad, unsigned int offset, void *buffer, + size_t buffer_len) { - return wad->file_class->Read(wad, offset, buffer, buffer_len); + return wad->file_class->read(wad, offset, buffer, buffer_len); } - diff --git a/games/NXDoom/src/w_file.h b/games/NXDoom/src/w_file.h index be8065cc36e..32ac342226b 100644 --- a/games/NXDoom/src/w_file.h +++ b/games/NXDoom/src/w_file.h @@ -1,86 +1,111 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// WAD I/O functions. -// - +/**************************************************************************** + * apps/games/NXDoom/src/w_file.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * WAD I/O functions. + * + ****************************************************************************/ #ifndef __W_FILE__ #define __W_FILE__ -#include +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "doomtype.h" +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ typedef struct _wad_file_s wad_file_t; typedef struct { - // Open a file for reading. - wad_file_t *(*OpenFile)(const char *path); + /* Open a file for reading. */ - // Close the specified file. - void (*CloseFile)(wad_file_t *file); + wad_file_t *(*open_file)(const char *path); - // Read data from the specified position in the file into the - // provided buffer. Returns the number of bytes read. - size_t (*Read)(wad_file_t *file, unsigned int offset, - void *buffer, size_t buffer_len); -} wad_file_class_t; + /* Close the specified file. */ + void (*close_file)(wad_file_t *file); -extern wad_file_class_t stdc_wad_file; - -#ifdef _WIN32 -extern wad_file_class_t win32_wad_file; -#endif - -#ifdef HAVE_MMAP -extern wad_file_class_t posix_wad_file; -#endif + /* Read data from the specified position in the file into the provided + * buffer. Returns the number of bytes read. + */ + size_t (*read)(wad_file_t *file, unsigned int offset, void *buffer, + size_t buffer_len); +} wad_file_class_t; struct _wad_file_s { - // Class of this file. - wad_file_class_t *file_class; + /* Class of this file. */ + + wad_file_class_t *file_class; + + /* If this is NULL, the file cannot be mapped into memory. If this is + * non-NULL, it is a pointer to the mapped file. + */ + + byte *mapped; - // If this is NULL, the file cannot be mapped into memory. If this - // is non-NULL, it is a pointer to the mapped file. - byte *mapped; + /* Length of the file, in bytes. */ - // Length of the file, in bytes. - unsigned int length; + unsigned int length; - // File's location on disk. - const char *path; + /* File's location on disk. */ + + const char *path; }; -// Open the specified file. Returns a pointer to a new wad_file_t -// handle for the WAD file, or NULL if it could not be opened. +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern wad_file_class_t stdc_wad_file; + +#ifdef HAVE_MMAP +extern wad_file_class_t posix_wad_file; +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Open the specified file. Returns a pointer to a new wad_file_t + * handle for the WAD file, or NULL if it could not be opened. + */ -wad_file_t *W_OpenFile(const char *path); +wad_file_t *w_open_file(const char *path); -// Close the specified WAD file. +/* Close the specified WAD file. */ -void W_CloseFile(wad_file_t *wad); +void w_close_file(wad_file_t *wad); -// Read data from the specified file into the provided buffer. The -// data is read from the specified offset from the start of the file. -// Returns the number of bytes read. +/* Read data from the specified file into the provided buffer. The + * data is read from the specified offset from the start of the file. + * Returns the number of bytes read. + */ -size_t W_Read(wad_file_t *wad, unsigned int offset, - void *buffer, size_t buffer_len); +size_t w_read(wad_file_t *wad, unsigned int offset, void *buffer, + size_t buffer_len); -#endif /* #ifndef __W_FILE__ */ +#endif /* __W_FILE__ */ diff --git a/games/NXDoom/src/w_file_posix.c b/games/NXDoom/src/w_file_posix.c deleted file mode 100644 index d4fdc22f9e3..00000000000 --- a/games/NXDoom/src/w_file_posix.c +++ /dev/null @@ -1,176 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// WAD I/O functions. -// - -#include "config.h" - -#ifdef HAVE_MMAP - -#include -#include -#include -#include -#include - -#include "m_misc.h" -#include "w_file.h" -#include "z_zone.h" - -typedef struct -{ - wad_file_t wad; - int handle; -} posix_wad_file_t; - - -static void MapFile(posix_wad_file_t *wad, const char *filename) -{ - void *result; - int protection; - int flags; - - // Mapped area can be read and written to. Ideally - // this should be read-only, as none of the Doom code should - // change the WAD files after being read. However, there may - // be code lurking in the source that does. - - protection = PROT_READ|PROT_WRITE; - - // Writes to the mapped area result in private changes that are - // *not* written to disk. - - flags = MAP_PRIVATE; - - result = mmap(NULL, wad->wad.length, - protection, flags, - wad->handle, 0); - - if (result == NULL || result == (void *)-1) - { - fprintf(stderr, "W_POSIX_OpenFile: Unable to mmap() %s - %s\n", - filename, strerror(errno)); - } - else - { - wad->wad.mapped = result; - } -} - -unsigned int GetFileLength(int handle) -{ - return lseek(handle, 0, SEEK_END); -} - -static wad_file_t *W_POSIX_OpenFile(const char *path) -{ - posix_wad_file_t *result; - int handle; - - handle = open(path, 0); - - if (handle < 0) - { - return NULL; - } - - // Create a new posix_wad_file_t to hold the file handle. - - result = Z_Malloc(sizeof(posix_wad_file_t), PU_STATIC, 0); - result->wad.file_class = &posix_wad_file; - result->wad.length = GetFileLength(handle); - result->wad.path = M_StringDuplicate(path); - result->wad.mapped = NULL; - result->handle = handle; - - // Try to map the file into memory with mmap: - - MapFile(result, path); - - return &result->wad; -} - -static void W_POSIX_CloseFile(wad_file_t *wad) -{ - posix_wad_file_t *posix_wad; - - posix_wad = (posix_wad_file_t *) wad; - - // If mapped, unmap it. - - // Close the file - - if (posix_wad->wad.mapped) - { - munmap(posix_wad->wad.mapped, posix_wad->wad.length); - } - close(posix_wad->handle); - Z_Free(posix_wad); -} - -// Read data from the specified position in the file into the -// provided buffer. Returns the number of bytes read. - -size_t W_POSIX_Read(wad_file_t *wad, unsigned int offset, - void *buffer, size_t buffer_len) -{ - posix_wad_file_t *posix_wad; - byte *byte_buffer; - size_t bytes_read; - int result; - - posix_wad = (posix_wad_file_t *) wad; - - // Jump to the specified position in the file. - - lseek(posix_wad->handle, offset, SEEK_SET); - - // Read into the buffer. - - bytes_read = 0; - byte_buffer = buffer; - - while (buffer_len > 0) { - result = read(posix_wad->handle, byte_buffer, buffer_len); - - if (result < 0) { - perror("W_POSIX_Read"); - break; - } else if (result == 0) { - break; - } - - // Successfully read some bytes - - byte_buffer += result; - buffer_len -= result; - bytes_read += result; - } - - return bytes_read; -} - - -wad_file_class_t posix_wad_file = -{ - W_POSIX_OpenFile, - W_POSIX_CloseFile, - W_POSIX_Read, -}; - - -#endif /* #ifdef HAVE_MMAP */ - diff --git a/games/NXDoom/src/w_file_stdc.c b/games/NXDoom/src/w_file_stdc.c index 90846a4e156..361bf206095 100644 --- a/games/NXDoom/src/w_file_stdc.c +++ b/games/NXDoom/src/w_file_stdc.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// WAD I/O functions. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_file_stdc.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * WAD I/O functions. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -22,75 +31,93 @@ #include "w_file.h" #include "z_zone.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + typedef struct { - wad_file_t wad; - FILE *fstream; + wad_file_t wad; + FILE *fstream; } stdc_wad_file_t; +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static wad_file_t *w_stdc_openfile(const char *path); +static void w_stdc_closefile(wad_file_t *wad); +static size_t w_stdc_read(wad_file_t *wad, unsigned int offset, void *buffer, + size_t buffer_len); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +wad_file_class_t stdc_wad_file = +{ + w_stdc_openfile, + w_stdc_closefile, + w_stdc_read, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static wad_file_t *W_StdC_OpenFile(const char *path) +static wad_file_t *w_stdc_openfile(const char *path) { - stdc_wad_file_t *result; - FILE *fstream; + stdc_wad_file_t *result; + FILE *fstream; - fstream = M_fopen(path, "rb"); + fstream = fopen(path, "rb"); - if (fstream == NULL) + if (fstream == NULL) { - return NULL; + return NULL; } - // Create a new stdc_wad_file_t to hold the file handle. + /* Create a new stdc_wad_file_t to hold the file handle. */ - result = Z_Malloc(sizeof(stdc_wad_file_t), PU_STATIC, 0); - result->wad.file_class = &stdc_wad_file; - result->wad.mapped = NULL; - result->wad.length = M_FileLength(fstream); - result->wad.path = M_StringDuplicate(path); - result->fstream = fstream; + result = z_malloc(sizeof(stdc_wad_file_t), PU_STATIC, 0); + result->wad.file_class = &stdc_wad_file; + result->wad.mapped = NULL; + result->wad.length = m_file_length(fstream); + result->wad.path = m_string_duplicate(path); + result->fstream = fstream; - return &result->wad; + return &result->wad; } -static void W_StdC_CloseFile(wad_file_t *wad) +static void w_stdc_closefile(wad_file_t *wad) { - stdc_wad_file_t *stdc_wad; + stdc_wad_file_t *stdc_wad; - stdc_wad = (stdc_wad_file_t *) wad; + stdc_wad = (stdc_wad_file_t *)wad; - fclose(stdc_wad->fstream); - Z_Free(stdc_wad); + fclose(stdc_wad->fstream); + z_free(stdc_wad); } -// Read data from the specified position in the file into the -// provided buffer. Returns the number of bytes read. +/* Read data from the specified position in the file into the + * provided buffer. Returns the number of bytes read. + */ -size_t W_StdC_Read(wad_file_t *wad, unsigned int offset, - void *buffer, size_t buffer_len) +static size_t w_stdc_read(wad_file_t *wad, unsigned int offset, void *buffer, + size_t buffer_len) { - stdc_wad_file_t *stdc_wad; - size_t result; + stdc_wad_file_t *stdc_wad; + size_t result; - stdc_wad = (stdc_wad_file_t *) wad; + stdc_wad = (stdc_wad_file_t *)wad; - // Jump to the specified position in the file. + /* Jump to the specified position in the file. */ - fseek(stdc_wad->fstream, offset, SEEK_SET); + fseek(stdc_wad->fstream, offset, SEEK_SET); - // Read into the buffer. + /* Read into the buffer. */ - result = fread(buffer, 1, buffer_len, stdc_wad->fstream); + result = fread(buffer, 1, buffer_len, stdc_wad->fstream); - return result; + return result; } - - -wad_file_class_t stdc_wad_file = -{ - W_StdC_OpenFile, - W_StdC_CloseFile, - W_StdC_Read, -}; - - diff --git a/games/NXDoom/src/w_file_win32.c b/games/NXDoom/src/w_file_win32.c deleted file mode 100644 index dba576be33b..00000000000 --- a/games/NXDoom/src/w_file_win32.c +++ /dev/null @@ -1,204 +0,0 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// WAD I/O functions. -// - -#include "config.h" - -#ifdef _WIN32 - -#include -#include - -#define WIN32_LEAN_AND_MEAN -#include - -#include "i_system.h" -#include "m_misc.h" -#include "w_file.h" -#include "z_zone.h" - -// This constant doesn't exist in VC6: - -#ifndef INVALID_SET_FILE_POINTER -#define INVALID_SET_FILE_POINTER 0xffffffff -#endif - -typedef struct -{ - wad_file_t wad; - HANDLE handle; - HANDLE handle_map; -} win32_wad_file_t; - - -static void MapFile(win32_wad_file_t *wad, const char *filename) -{ - wad->handle_map = CreateFileMapping(wad->handle, - NULL, - PAGE_WRITECOPY, - 0, - 0, - NULL); - - if (wad->handle_map == NULL) - { - fprintf(stderr, "W_Win32_OpenFile: Unable to CreateFileMapping() " - "for %s\n", filename); - return; - } - - wad->wad.mapped = MapViewOfFile(wad->handle_map, - FILE_MAP_COPY, - 0, 0, 0); - - if (wad->wad.mapped == NULL) - { - fprintf(stderr, "W_Win32_OpenFile: Unable to MapViewOfFile() for %s\n", - filename); - } -} - -unsigned int GetFileLength(HANDLE handle) -{ - DWORD result; - - result = SetFilePointer(handle, 0, NULL, FILE_END); - - if (result == INVALID_SET_FILE_POINTER) - { - I_Error("W_Win32_OpenFile: Failed to read file length"); - } - - return result; -} - -static wad_file_t *W_Win32_OpenFile(const char *path) -{ - win32_wad_file_t *result; - wchar_t *wpath = NULL; - HANDLE handle; - - // Open the file: - - wpath = M_ConvertUtf8ToWide(path); - - if (wpath == NULL) - { - return NULL; - } - - handle = CreateFileW(wpath, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - free(wpath); - - if (handle == INVALID_HANDLE_VALUE) - { - return NULL; - } - - // Create a new win32_wad_file_t to hold the file handle. - - result = Z_Malloc(sizeof(win32_wad_file_t), PU_STATIC, 0); - result->wad.file_class = &win32_wad_file; - result->wad.length = GetFileLength(handle); - result->wad.path = M_StringDuplicate(path); - result->handle = handle; - - // Try to map the file into memory with mmap: - - MapFile(result, path); - - return &result->wad; -} - -static void W_Win32_CloseFile(wad_file_t *wad) -{ - win32_wad_file_t *win32_wad; - - win32_wad = (win32_wad_file_t *) wad; - - // If mapped, unmap it. - - if (win32_wad->wad.mapped != NULL) - { - UnmapViewOfFile(win32_wad->wad.mapped); - } - - if (win32_wad->handle_map != NULL) - { - CloseHandle(win32_wad->handle_map); - } - - // Close the file - - if (win32_wad->handle != NULL) - { - CloseHandle(win32_wad->handle); - } - - Z_Free(win32_wad); -} - -// Read data from the specified position in the file into the -// provided buffer. Returns the number of bytes read. - -size_t W_Win32_Read(wad_file_t *wad, unsigned int offset, - void *buffer, size_t buffer_len) -{ - win32_wad_file_t *win32_wad; - DWORD bytes_read; - DWORD result; - - win32_wad = (win32_wad_file_t *) wad; - - // Jump to the specified position in the file. - - result = SetFilePointer(win32_wad->handle, offset, NULL, FILE_BEGIN); - - if (result == INVALID_SET_FILE_POINTER) - { - I_Error("W_Win32_Read: Failed to set file pointer to %i", - offset); - } - - // Read into the buffer. - - if (!ReadFile(win32_wad->handle, buffer, buffer_len, &bytes_read, NULL)) - { - I_Error("W_Win32_Read: Error reading from file"); - } - - return bytes_read; -} - - -wad_file_class_t win32_wad_file = -{ - W_Win32_OpenFile, - W_Win32_CloseFile, - W_Win32_Read, -}; - - -#endif /* #ifdef _WIN32 */ - diff --git a/games/NXDoom/src/w_main.c b/games/NXDoom/src/w_main.c index 3496fd1dd69..ce11765471a 100644 --- a/games/NXDoom/src/w_main.c +++ b/games/NXDoom/src/w_main.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Common code to parse command line, identifying WAD files to load. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_main.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Common code to parse command line, identifying WAD files to load. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -28,241 +37,258 @@ #include "w_wad.h" #include "z_zone.h" -// Parse the command line, merging WAD files that are sppecified. -// Returns true if at least one file was added. -boolean W_ParseCommandLine(void) +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct uniquelump +{ + gamemission_t mission; + const char *lumpname; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Lump names that are unique to particular game types. This lets us check + * the user is not trying to play with the wrong executable, eg. + * chocolate-doom -iwad hexen.wad. + */ + +static const struct uniquelump g_unique_lumps[] = +{ + {doom, "POSSA1"}, + {heretic, "IMPXA1"}, + {hexen, "ETTNA1"}, + {strife, "AGRDA1"}, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Parse the command line, merging WAD files that are sppecified. + * Returns true if at least one file was added. + */ + +boolean w_parse_command_line(void) { - boolean modifiedgame = false; - int p; + boolean modifiedgame = false; + int p; - // Merged PWADs are loaded first, because they are supposed to be - // modified IWADs. + /* Merged PWADs are loaded first, because they are supposed to be + * modified IWADs. + */ - //! - // @arg - // @category mod - // - // Simulates the behavior of deutex's -merge option, merging a PWAD - // into the main IWAD. Multiple files may be specified. - // + /* @arg + * @category mod + * + * Simulates the behavior of deutex's -merge option, merging a PWAD + * into the main IWAD. Multiple files may be specified. + */ - p = M_CheckParmWithArgs("-merge", 1); + p = m_check_parm_with_args("-merge", 1); - if (p > 0) + if (p > 0) { - for (p = p + 1; p - // @category mod - // - // Simulates the behavior of NWT's -merge option. Multiple files - // may be specified. + /* @arg + * @category mod + * + * Simulates the behavior of NWT's -merge option. Multiple files + * may be specified. + */ - p = M_CheckParmWithArgs("-nwtmerge", 1); + p = m_check_parm_with_args("-nwtmerge", 1); - if (p > 0) + if (p > 0) { - for (p = p + 1; p - // @category mod - // - // Simulates the behavior of NWT's -af option, merging flats into - // the main IWAD directory. Multiple files may be specified. - // + /* Add flats */ - p = M_CheckParmWithArgs("-af", 1); + /* @arg + * @category mod + * + * Simulates the behavior of NWT's -af option, merging flats into + * the main IWAD directory. Multiple files may be specified. + */ - if (p > 0) + p = m_check_parm_with_args("-af", 1); + + if (p > 0) { - for (p = p + 1; p - // @category mod - // - // Simulates the behavior of NWT's -as option, merging sprites - // into the main IWAD directory. Multiple files may be specified. - // + /* @arg + * @category mod + * + * Simulates the behavior of NWT's -as option, merging sprites + * into the main IWAD directory. Multiple files may be specified. + */ - p = M_CheckParmWithArgs("-as", 1); + p = m_check_parm_with_args("-as", 1); - if (p > 0) + if (p > 0) { - for (p = p + 1; p - // @category mod - // - // Equivalent to "-af -as ". - // + /* @arg + * @category mod + * + * Equivalent to "-af -as ". + */ - p = M_CheckParmWithArgs("-aa", 1); + p = m_check_parm_with_args("-aa", 1); - if (p > 0) + if (p > 0) { - for (p = p + 1; p - // @vanilla - // - // Load the specified PWAD files. Each succeeding argument is - // treated as a PWAD file name until one starts with a dash or the - // argument list is exhausted. - // - - p = M_CheckParmWithArgs ("-file", 1); - if (p) + /* @arg + * @vanilla + * + * Load the specified PWAD files. Each succeeding argument is + * treated as a PWAD file name until one starts with a dash or the + * argument list is exhausted. + */ + + p = m_check_parm_with_args("-file", 1); + if (p) { - // the parms after p are wadfile/lump names, - // until end of parms or another - preceded parm - modifiedgame = true; // homebrew levels - while (++p != myargc && myargv[p][0] != '-') + /* the params after p are wadfile/lump names, + * until end of params or another - preceded param + */ + + modifiedgame = true; /* homebrew levels */ + while (++p != myargc && myargv[p][0] != '-') { - char *filename; + char *filename; - filename = D_TryFindWADByName(myargv[p]); + filename = d_try_find_wad_by_name(myargv[p]); - printf(" adding %s\n", filename); - W_AddFile(filename); - free(filename); + printf(" adding %s\n", filename); + w_add_file(filename); + free(filename); } } -// W_PrintDirectory(); - - return modifiedgame; + return modifiedgame; } -// Load all WAD files from the given directory. -void W_AutoLoadWADs(const char *path) +/* Load all WAD files from the given directory. */ + +void w_auto_load_wads(const char *path) { - glob_t *glob; - const char *filename; + glob_t *glob; + const char *filename; - glob = I_StartMultiGlob(path, GLOB_FLAG_NOCASE|GLOB_FLAG_SORTED, + glob = i_start_multi_glob(path, GLOB_FLAG_NOCASE | GLOB_FLAG_SORTED, "*.wad", "*.lmp", NULL); - for (;;) + for (; ; ) { - filename = I_NextGlob(glob); - if (filename == NULL) + filename = i_next_glob(glob); + if (filename == NULL) { - break; + break; } - printf(" [autoload] merging %s\n", filename); - W_MergeFile(filename); + + printf(" [autoload] merging %s\n", filename); + w_merge_file(filename); } - I_EndGlob(glob); + i_end_glob(glob); } -// Lump names that are unique to particular game types. This lets us check -// the user is not trying to play with the wrong executable, eg. -// chocolate-doom -iwad hexen.wad. -static const struct +void w_check_correct_iwad(gamemission_t mission) { - GameMission_t mission; - const char *lumpname; -} unique_lumps[] = { - { doom, "POSSA1" }, - { heretic, "IMPXA1" }, - { hexen, "ETTNA1" }, - { strife, "AGRDA1" }, -}; + int i; + lumpindex_t lumpnum; -void W_CheckCorrectIWAD(GameMission_t mission) -{ - int i; - lumpindex_t lumpnum; - - for (i = 0; i < arrlen(unique_lumps); ++i) + for (i = 0; i < arrlen(g_unique_lumps); ++i) { - if (mission != unique_lumps[i].mission) + if (mission != g_unique_lumps[i].mission) { - lumpnum = W_CheckNumForName(unique_lumps[i].lumpname); + lumpnum = w_check_num_for_name(g_unique_lumps[i].lumpname); - if (lumpnum >= 0) + if (lumpnum >= 0) { - I_Error("\nYou are trying to use a %s IWAD file with " - "the %s%s binary.\nThis isn't going to work.\n" - "You probably want to use the %s%s binary.", - D_SuggestGameName(unique_lumps[i].mission, - indetermined), - PROGRAM_PREFIX, - D_GameMissionString(mission), - PROGRAM_PREFIX, - D_GameMissionString(unique_lumps[i].mission)); + i_error( + "\nYou are trying to use a %s IWAD file with " + "the %s%s binary.\nThis isn't going to work.\n" + "You probably want to use the %s%s binary.", + d_suggest_game_name( + g_unique_lumps[i].mission, indetermined), + PROGRAM_PREFIX, d_game_mission_string(mission), + PROGRAM_PREFIX, + d_game_mission_string(g_unique_lumps[i].mission)); } } } } - diff --git a/games/NXDoom/src/w_main.h b/games/NXDoom/src/w_main.h index 4565c657fc2..beab3f29bb2 100644 --- a/games/NXDoom/src/w_main.h +++ b/games/NXDoom/src/w_main.h @@ -1,30 +1,43 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Common code to parse command line, identifying WAD files to load. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_main.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Common code to parse command line, identifying WAD files to load. + * + ****************************************************************************/ #ifndef W_MAIN_H #define W_MAIN_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include "d_mode.h" -boolean W_ParseCommandLine(void); -void W_CheckCorrectIWAD(GameMission_t mission); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +boolean w_parse_command_line(void); +void w_check_correct_iwad(gamemission_t mission); -// Autoload all .wad files from the given directory: -void W_AutoLoadWADs(const char *path); +/* Autoload all .wad files from the given directory: */ -#endif /* #ifndef W_MAIN_H */ +void w_auto_load_wads(const char *path); +#endif /* W_MAIN_H */ diff --git a/games/NXDoom/src/w_merge.c b/games/NXDoom/src/w_merge.c index 3d71a9aee96..88a05b4bdde 100644 --- a/games/NXDoom/src/w_merge.c +++ b/games/NXDoom/src/w_merge.c @@ -1,27 +1,36 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handles merging of PWADs, similar to deutex's -merge option -// -// Ideally this should work exactly the same as in deutex, but trying to -// read the deutex source code made my brain hurt. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_merge.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Handles merging of PWADs, similar to deutex's -merge option + * + * Ideally this should work exactly the same as in deutex, but trying to + * read the deutex source code made my brain hurt. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include #include #include #include -#include #include "doomtype.h" #include "i_system.h" @@ -30,26 +39,34 @@ #include "w_wad.h" #include "z_zone.h" -typedef enum -{ - SECTION_NORMAL, - SECTION_FLATS, - SECTION_SPRITES, +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef enum +{ + SECTION_NORMAL, + SECTION_FLATS, + SECTION_SPRITES, } section_t; typedef struct { - lumpinfo_t **lumps; - int numlumps; + lumpinfo_t **lumps; + int numlumps; } searchlist_t; typedef struct { - char sprname[4]; - char frame; - lumpinfo_t *angle_lumps[8]; + char sprname[4]; + char frame; + lumpinfo_t *angle_lumps[8]; } sprite_frame_t; +/**************************************************************************** + * Private Data + ****************************************************************************/ + static searchlist_t iwad; static searchlist_t iwad_sprites; static searchlist_t pwad; @@ -58,665 +75,690 @@ static searchlist_t iwad_flats; static searchlist_t pwad_sprites; static searchlist_t pwad_flats; -// lumps with these sprites must be replaced in the IWAD +/* lumps with these sprites must be replaced in the IWAD */ + static sprite_frame_t *sprite_frames; static int num_sprite_frames; static int sprite_frames_alloced; -// Search in a list to find a lump with a particular name -// Linear search (slow!) -// -// Returns -1 if not found +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static int FindInList(searchlist_t *list, const char *name) +/* Search in a list to find a lump with a particular name + * Linear search (slow!) + * + * Returns -1 if not found + */ + +static int find_in_list(searchlist_t *list, const char *name) { - int i; + int i; - for (i=0; inumlumps; ++i) + for (i = 0; i < list->numlumps; ++i) { - if (!strncasecmp(list->lumps[i]->name, name, 8)) - return i; + if (!strncasecmp(list->lumps[i]->name, name, 8)) return i; } - return -1; + return -1; } -static boolean SetupList(searchlist_t *list, searchlist_t *src_list, - const char *startname, const char *endname, - const char *startname2, const char *endname2) +static boolean setup_list(searchlist_t *list, searchlist_t *src_list, + const char *startname, const char *endname, + const char *startname2, const char *endname2) { - int startlump, endlump; + int startlump; + int endlump; - list->numlumps = 0; - startlump = FindInList(src_list, startname); + list->numlumps = 0; + startlump = find_in_list(src_list, startname); - if (startname2 != NULL && startlump < 0) + if (startname2 != NULL && startlump < 0) { - startlump = FindInList(src_list, startname2); + startlump = find_in_list(src_list, startname2); } - if (startlump >= 0) + if (startlump >= 0) { - endlump = FindInList(src_list, endname); + endlump = find_in_list(src_list, endname); - if (endname2 != NULL && endlump < 0) + if (endname2 != NULL && endlump < 0) { - endlump = FindInList(src_list, endname2); + endlump = find_in_list(src_list, endname2); } - if (endlump > startlump) + if (endlump > startlump) { - list->lumps = src_list->lumps + startlump + 1; - list->numlumps = endlump - startlump - 1; - return true; + list->lumps = src_list->lumps + startlump + 1; + list->numlumps = endlump - startlump - 1; + return true; } } - return false; + return false; } -// Sets up the sprite/flat search lists +/* Sets up the sprite/flat search lists */ -static void SetupLists(void) +static void setup_lists(void) { - // IWAD + /* IWAD */ - if (!SetupList(&iwad_flats, &iwad, "F_START", "F_END", NULL, NULL)) + if (!setup_list(&iwad_flats, &iwad, "F_START", "F_END", NULL, NULL)) { - I_Error("Flats section not found in IWAD"); + i_error("Flats section not found in IWAD"); } - if (!SetupList(&iwad_sprites, &iwad, "S_START", "S_END", NULL, NULL)) + if (!setup_list(&iwad_sprites, &iwad, "S_START", "S_END", NULL, NULL)) { - I_Error("Sprites section not found in IWAD"); + i_error("Sprites section not found in IWAD"); } - - // PWAD - SetupList(&pwad_flats, &pwad, "F_START", "F_END", "FF_START", "FF_END"); - SetupList(&pwad_sprites, &pwad, "S_START", "S_END", "SS_START", "SS_END"); + /* PWAD */ + + setup_list(&pwad_flats, &pwad, "F_START", "F_END", "FF_START", "FF_END"); + setup_list(&pwad_sprites, &pwad, "S_START", "S_END", "SS_START", "SS_END"); } -// Initialize the replace list +/* Initialize the replace list */ -static void InitSpriteList(void) +static void init_sprite_list(void) { - if (sprite_frames == NULL) + if (sprite_frames == NULL) { - sprite_frames_alloced = 128; - sprite_frames = Z_Malloc(sizeof(*sprite_frames) * sprite_frames_alloced, - PU_STATIC, NULL); + sprite_frames_alloced = 128; + sprite_frames = z_malloc( + sizeof(*sprite_frames) * sprite_frames_alloced, + PU_STATIC, NULL + ); } - num_sprite_frames = 0; + num_sprite_frames = 0; } -static boolean ValidSpriteLumpName(char *name) +static boolean valid_sprite_lump_name(char *name) { - if (name[0] == '\0' || name[1] == '\0' - || name[2] == '\0' || name[3] == '\0') + if (name[0] == '\0' || name[1] == '\0' || name[2] == '\0' || + name[3] == '\0') { - return false; + return false; } - // First frame: + /* First frame: */ - if (name[4] == '\0' || !isdigit(name[5])) + if (name[4] == '\0' || !isdigit(name[5])) { - return false; + return false; } - // Second frame (optional): + /* Second frame (optional): */ - if (name[6] != '\0' && !isdigit(name[7])) + if (name[6] != '\0' && !isdigit(name[7])) { - return false; + return false; } - return true; + return true; } -// Find a sprite frame - -static sprite_frame_t *FindSpriteFrame(char *name, int frame) +static sprite_frame_t *find_sprite_frame(char *name, int frame) { - sprite_frame_t *result; - int i; + sprite_frame_t *result; + int i; - // Search the list and try to find the frame + /* Search the list and try to find the frame */ - for (i=0; isprname, name, 4) && cur->frame == frame) + if (!strncasecmp(cur->sprname, name, 4) && cur->frame == frame) { - return cur; + return cur; } } - // Not found in list; Need to add to the list + /* Not found in list; Need to add to the list */ - // Grow list? + /* Grow list? */ - if (num_sprite_frames >= sprite_frames_alloced) + if (num_sprite_frames >= sprite_frames_alloced) { - sprite_frame_t *newframes; - - newframes = Z_Malloc(sprite_frames_alloced * 2 * sizeof(*sprite_frames), - PU_STATIC, NULL); - memcpy(newframes, sprite_frames, - sprite_frames_alloced * sizeof(*sprite_frames)); - Z_Free(sprite_frames); - sprite_frames_alloced *= 2; - sprite_frames = newframes; + sprite_frame_t *newframes; + + newframes = z_malloc( + sprite_frames_alloced * 2 * sizeof(*sprite_frames), + PU_STATIC, NULL + ); + memcpy(newframes, sprite_frames, + sprite_frames_alloced * sizeof(*sprite_frames)); + z_free(sprite_frames); + sprite_frames_alloced *= 2; + sprite_frames = newframes; } - // Add to end of list - - result = &sprite_frames[num_sprite_frames]; - memcpy(result->sprname, name, 4); - result->frame = frame; + /* Add to end of list */ - for (i=0; i<8; ++i) - result->angle_lumps[i] = NULL; + result = &sprite_frames[num_sprite_frames]; + memcpy(result->sprname, name, 4); + result->frame = frame; - ++num_sprite_frames; + for (i = 0; i < 8; ++i) + result->angle_lumps[i] = NULL; - return result; + ++num_sprite_frames; + + return result; } -// Check if sprite lump is needed in the new wad +/* Check if sprite lump is needed in the new wad */ -static boolean SpriteLumpNeeded(lumpinfo_t *lump) +static boolean sprite_lump_needed(lumpinfo_t *lump) { - sprite_frame_t *sprite; - int angle_num; - int i; + sprite_frame_t *sprite; + int angle_num; + int i; - if (!ValidSpriteLumpName(lump->name)) + if (!valid_sprite_lump_name(lump->name)) { - return true; + return true; } - // check the first frame + /* check the first frame */ - sprite = FindSpriteFrame(lump->name, lump->name[4]); - angle_num = lump->name[5] - '0'; + sprite = find_sprite_frame(lump->name, lump->name[4]); + angle_num = lump->name[5] - '0'; - if (angle_num == 0) + if (angle_num == 0) { - // must check all frames + /* must check all frames */ - for (i=0; i<8; ++i) + for (i = 0; i < 8; ++i) { - if (sprite->angle_lumps[i] == lump) - return true; + if (sprite->angle_lumps[i] == lump) return true; } } - else + else { - // check if this lump is being used for this frame + /* check if this lump is being used for this frame */ - if (sprite->angle_lumps[angle_num - 1] == lump) - return true; + if (sprite->angle_lumps[angle_num - 1] == lump) return true; } - - // second frame if any - - // no second frame? - if (lump->name[6] == '\0') - return false; - sprite = FindSpriteFrame(lump->name, lump->name[6]); - angle_num = lump->name[7] - '0'; + /* second frame if any */ + + /* no second frame? */ - if (angle_num == 0) + if (lump->name[6] == '\0') return false; + + sprite = find_sprite_frame(lump->name, lump->name[6]); + angle_num = lump->name[7] - '0'; + + if (angle_num == 0) { - // must check all frames + /* must check all frames */ - for (i=0; i<8; ++i) + for (i = 0; i < 8; ++i) { - if (sprite->angle_lumps[i] == lump) - return true; + if (sprite->angle_lumps[i] == lump) return true; } } - else + else { - // check if this lump is being used for this frame + /* check if this lump is being used for this frame */ - if (sprite->angle_lumps[angle_num - 1] == lump) - return true; + if (sprite->angle_lumps[angle_num - 1] == lump) return true; } - return false; + return false; } -static void AddSpriteLump(lumpinfo_t *lump) +static void add_sprite_lump(lumpinfo_t *lump) { - sprite_frame_t *sprite; - int angle_num; - int i; + sprite_frame_t *sprite; + int angle_num; + int i; - if (!ValidSpriteLumpName(lump->name)) + if (!valid_sprite_lump_name(lump->name)) { - return; + return; } - - // first angle - sprite = FindSpriteFrame(lump->name, lump->name[4]); - angle_num = lump->name[5] - '0'; - - if (angle_num == 0) + /* first angle */ + + sprite = find_sprite_frame(lump->name, lump->name[4]); + angle_num = lump->name[5] - '0'; + + if (angle_num == 0) { - for (i=0; i<8; ++i) - sprite->angle_lumps[i] = lump; + for (i = 0; i < 8; ++i) + sprite->angle_lumps[i] = lump; } - else + else { - sprite->angle_lumps[angle_num - 1] = lump; + sprite->angle_lumps[angle_num - 1] = lump; } - - // second angle - - // no second angle? - - if (lump->name[6] == '\0') - return; - - sprite = FindSpriteFrame(lump->name, lump->name[6]); - angle_num = lump->name[7] - '0'; - - if (angle_num == 0) + + /* second angle */ + + /* no second angle? */ + + if (lump->name[6] == '\0') return; + + sprite = find_sprite_frame(lump->name, lump->name[6]); + angle_num = lump->name[7] - '0'; + + if (angle_num == 0) { - for (i=0; i<8; ++i) - sprite->angle_lumps[i] = lump; + for (i = 0; i < 8; ++i) + sprite->angle_lumps[i] = lump; } - else + else { - sprite->angle_lumps[angle_num - 1] = lump; + sprite->angle_lumps[angle_num - 1] = lump; } } -// Generate the list. Run at the start, before merging +/* Generate the list. Run at the start, before merging */ -static void GenerateSpriteList(void) +static void generate_sprite_list(void) { - int i; + int i; + + init_sprite_list(); - InitSpriteList(); - - // Add all sprites from the IWAD - - for (i=0; iname, "F_START", 8)) - { - current_section = SECTION_FLATS; - } - else if (!strncasecmp(lump->name, "S_START", 8)) - { - current_section = SECTION_SPRITES; - } + case SECTION_NORMAL: + if (!strncasecmp(lump->name, "F_START", 8)) + { + current_section = SECTION_FLATS; + } + else if (!strncasecmp(lump->name, "S_START", 8)) + { + current_section = SECTION_SPRITES; + } - newlumps[num_newlumps++] = lump; + newlumps[num_newlumps++] = lump; - break; + break; - case SECTION_FLATS: + case SECTION_FLATS: - // Have we reached the end of the section? + /* Have we reached the end of the section? */ - if (!strncasecmp(lump->name, "F_END", 8)) + if (!strncasecmp(lump->name, "F_END", 8)) + { + /* Add all new flats from the PWAD to the end + * of the section + */ + + for (n = 0; n < pwad_flats.numlumps; ++n) { - // Add all new flats from the PWAD to the end - // of the section + newlumps[num_newlumps++] = pwad_flats.lumps[n]; + } - for (n=0; nname); + lumpindex = find_in_list(&pwad_flats, lump->name); - if (lumpindex < 0) - { - newlumps[num_newlumps++] = lump; - } + if (lumpindex < 0) + { + newlumps[num_newlumps++] = lump; } + } - break; + break; - case SECTION_SPRITES: + case SECTION_SPRITES: - // Have we reached the end of the section? + /* Have we reached the end of the section? */ - if (!strncasecmp(lump->name, "S_END", 8)) - { - // add all the PWAD sprites + if (!strncasecmp(lump->name, "S_END", 8)) + { + /* add all the PWAD sprites */ - for (n=0; nname, "F_START", 8) - || !strncasecmp(lump->name, "FF_START", 8)) - { - current_section = SECTION_FLATS; - } - else if (!strncasecmp(lump->name, "S_START", 8) - || !strncasecmp(lump->name, "SS_START", 8)) - { - current_section = SECTION_SPRITES; - } - else - { - // Don't include the headers of sections - - newlumps[num_newlumps++] = lump; - } - break; + /* back to normal reading */ - case SECTION_FLATS: + current_section = SECTION_NORMAL; + } + else + { + /* Is this lump holding a sprite to be replaced in the + * PWAD? If so, wait until the end to add it. + */ - // PWAD flats are ignored (already merged) - - if (!strncasecmp(lump->name, "FF_END", 8) - || !strncasecmp(lump->name, "F_END", 8)) + if (sprite_lump_needed(lump)) { - // end of section - current_section = SECTION_NORMAL; + newlumps[num_newlumps++] = lump; } - break; + } + + break; + } + } - case SECTION_SPRITES: + /* Add PWAD lumps */ - // PWAD sprites are ignored (already merged) + current_section = SECTION_NORMAL; - if (!strncasecmp(lump->name, "SS_END", 8) - || !strncasecmp(lump->name, "S_END", 8)) - { - // end of section - current_section = SECTION_NORMAL; - } - break; + for (i = 0; i < pwad.numlumps; ++i) + { + lumpinfo_t *lump = pwad.lumps[i]; + + switch (current_section) + { + case SECTION_NORMAL: + if (!strncasecmp(lump->name, "F_START", 8) || + !strncasecmp(lump->name, "FF_START", 8)) + { + current_section = SECTION_FLATS; + } + else if (!strncasecmp(lump->name, "S_START", 8) || + !strncasecmp(lump->name, "SS_START", 8)) + { + current_section = SECTION_SPRITES; + } + else + { + /* Don't include the headers of sections */ + + newlumps[num_newlumps++] = lump; + } + break; + + case SECTION_FLATS: + + /* PWAD flats are ignored (already merged) */ + + if (!strncasecmp(lump->name, "FF_END", 8) || + !strncasecmp(lump->name, "F_END", 8)) + { + /* end of section */ + + current_section = SECTION_NORMAL; + } + break; + + case SECTION_SPRITES: + + /* PWAD sprites are ignored (already merged) */ + + if (!strncasecmp(lump->name, "SS_END", 8) || + !strncasecmp(lump->name, "S_END", 8)) + { + /* end of section */ + + current_section = SECTION_NORMAL; + } + break; } } - // Switch to the new lumpinfo, and free the old one + /* Switch to the new lumpinfo, and free the old one */ - free(lumpinfo); - lumpinfo = newlumps; - numlumps = num_newlumps; + free(lumpinfo); + lumpinfo = newlumps; + numlumps = num_newlumps; } -void W_PrintDirectory(void) +/* Replace lumps in the given list with lumps from the PWAD */ + +static void w_nwt_add_lumps(searchlist_t *list) { - unsigned int i, n; + int i; - // debug - for (i=0; inumlumps; ++i) { - for (n=0; n<8 && lumpinfo[i]->name[n] != '\0'; ++n) - putchar(lumpinfo[i]->name[n]); - putchar('\n'); + int index; + + index = find_in_list(&pwad, list->lumps[i]->name); + + if (index > 0) + { + memcpy(list->lumps[i], pwad.lumps[index], sizeof(lumpinfo_t)); + } } } -// Merge in a file by name +/**************************************************************************** + * Public Functions + ****************************************************************************/ -void W_MergeFile(const char *filename) +void w_print_directory(void) { - int old_numlumps; + unsigned int i; + unsigned int n; - old_numlumps = numlumps; + /* debug */ - // Load PWAD + for (i = 0; i < numlumps; ++i) + { + for (n = 0; n < 8 && lumpinfo[i]->name[n] != '\0'; ++n) + putchar(lumpinfo[i]->name[n]); + putchar('\n'); + } +} - if (W_AddFile(filename) == NULL) - return; +/* Merge in a file by name */ - // IWAD is at the start, PWAD was appended to the end +void w_merge_file(const char *filename) +{ + int old_numlumps; - iwad.lumps = lumpinfo; - iwad.numlumps = old_numlumps; + old_numlumps = numlumps; - pwad.lumps = lumpinfo + old_numlumps; - pwad.numlumps = numlumps - old_numlumps; - - // Setup sprite/flat lists + /* Load PWAD */ - SetupLists(); + if (w_add_file(filename) == NULL) return; - // Generate list of sprites to be replaced by the PWAD + /* IWAD is at the start, PWAD was appended to the end */ - GenerateSpriteList(); + iwad.lumps = lumpinfo; + iwad.numlumps = old_numlumps; - // Perform the merge + pwad.lumps = lumpinfo + old_numlumps; + pwad.numlumps = numlumps - old_numlumps; - DoMerge(); -} + /* Setup sprite/flat lists */ -// Replace lumps in the given list with lumps from the PWAD + setup_lists(); -static void W_NWTAddLumps(searchlist_t *list) -{ - int i; + /* Generate list of sprites to be replaced by the PWAD */ - // Go through the IWAD list given, replacing lumps with lumps of - // the same name from the PWAD - for (i=0; inumlumps; ++i) - { - int index; + generate_sprite_list(); - index = FindInList(&pwad, list->lumps[i]->name); + /* Perform the merge */ - if (index > 0) - { - memcpy(list->lumps[i], pwad.lumps[index], - sizeof(lumpinfo_t)); - } - } + do_merge(); } -// Merge sprites and flats in the way NWT does with its -af and -as -// command-line options. +/* Merge sprites and flats in the way NWT does with its -af and -as + * command-line options. + */ -void W_NWTMergeFile(const char *filename, int flags) +void w_nwt_merge_file(const char *filename, int flags) { - int old_numlumps; + int old_numlumps; - old_numlumps = numlumps; + old_numlumps = numlumps; - // Load PWAD + /* Load PWAD */ - if (W_AddFile(filename) == NULL) - return; + if (w_add_file(filename) == NULL) return; - // IWAD is at the start, PWAD was appended to the end + /* IWAD is at the start, PWAD was appended to the end */ - iwad.lumps = lumpinfo; - iwad.numlumps = old_numlumps; + iwad.lumps = lumpinfo; + iwad.numlumps = old_numlumps; - pwad.lumps = lumpinfo + old_numlumps; - pwad.numlumps = numlumps - old_numlumps; + pwad.lumps = lumpinfo + old_numlumps; + pwad.numlumps = numlumps - old_numlumps; - // Setup sprite/flat lists + /* Setup sprite/flat lists */ - SetupLists(); + setup_lists(); - // Merge in flats? + /* Merge in flats? */ - if (flags & W_NWT_MERGE_FLATS) + if (flags & W_NWT_MERGE_FLATS) { - W_NWTAddLumps(&iwad_flats); + w_nwt_add_lumps(&iwad_flats); } - // Sprites? + /* Sprites? */ - if (flags & W_NWT_MERGE_SPRITES) + if (flags & W_NWT_MERGE_SPRITES) { - W_NWTAddLumps(&iwad_sprites); + w_nwt_add_lumps(&iwad_sprites); } - - // Discard the PWAD - numlumps = old_numlumps; + /* Discard the PWAD */ + + numlumps = old_numlumps; } -// Simulates the NWT -merge command line parameter. What this does is load -// a PWAD, then search the IWAD sprites, removing any sprite lumps that also -// exist in the PWAD. +/* Simulates the NWT -merge command line parameter. What this does is load + * a PWAD, then search the IWAD sprites, removing any sprite lumps that also + * exist in the PWAD. + */ -void W_NWTDashMerge(const char *filename) +void w_nwt_dash_merge(const char *filename) { - wad_file_t *wad_file; - int old_numlumps; - int i; + wad_file_t *wad_file; + int old_numlumps; + int i; - old_numlumps = numlumps; + old_numlumps = numlumps; - // Load PWAD + /* Load PWAD */ - wad_file = W_AddFile(filename); + wad_file = w_add_file(filename); - if (wad_file == NULL) + if (wad_file == NULL) { - return; + return; } - // IWAD is at the start, PWAD was appended to the end + /* IWAD is at the start, PWAD was appended to the end */ - iwad.lumps = lumpinfo; - iwad.numlumps = old_numlumps; + iwad.lumps = lumpinfo; + iwad.numlumps = old_numlumps; - pwad.lumps = lumpinfo + old_numlumps; - pwad.numlumps = numlumps - old_numlumps; + pwad.lumps = lumpinfo + old_numlumps; + pwad.numlumps = numlumps - old_numlumps; - // Setup sprite/flat lists + /* Setup sprite/flat lists */ - SetupLists(); + setup_lists(); - // Search through the IWAD sprites list. + /* Search through the IWAD sprites list. */ - for (i=0; iname) >= 0) + if (find_in_list(&pwad, iwad_sprites.lumps[i]->name) >= 0) { - // Replace this entry with an empty string. This is what - // nwt -merge does. + /* Replace this entry with an empty string. This is what + * nwt -merge does. + */ - M_StringCopy(iwad_sprites.lumps[i]->name, "", 8); + m_str_copy(iwad_sprites.lumps[i]->name, "", 8); } } - // Discard PWAD - // The PWAD must now be added in again with -file. + /* Discard PWAD + * The PWAD must now be added in again with -file. + */ - numlumps = old_numlumps; + numlumps = old_numlumps; - W_CloseFile(wad_file); + w_close_file(wad_file); } - diff --git a/games/NXDoom/src/w_merge.h b/games/NXDoom/src/w_merge.h index b88c9a3a1ef..ce580afc51b 100644 --- a/games/NXDoom/src/w_merge.h +++ b/games/NXDoom/src/w_merge.h @@ -1,44 +1,56 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handles merging of PWADs, similar to deutex's -merge option -// -// Ideally this should work exactly the same as in deutex, but trying to -// read the deutex source code made my brain hurt. -// +/**************************************************************************** + * apps/games/NXDoom/src/w_merge.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Handles merging of PWADs, similar to deutex's -merge option + * + * Ideally this should work exactly the same as in deutex, but trying to + * read the deutex source code made my brain hurt. + * + ****************************************************************************/ #ifndef W_MERGE_H #define W_MERGE_H -#define W_NWT_MERGE_SPRITES 0x1 -#define W_NWT_MERGE_FLATS 0x2 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -// Add a new WAD and merge it into the main directory +#define W_NWT_MERGE_SPRITES 0x1 +#define W_NWT_MERGE_FLATS 0x2 -void W_MergeFile(const char *filename); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ -// NWT-style merging +/* Add a new WAD and merge it into the main directory */ -void W_NWTMergeFile(const char *filename, int flags); +void w_merge_file(const char *filename); -// Acts the same as NWT's "-merge" option. +/* NWT-style merging */ -void W_NWTDashMerge(const char *filename); +void w_nwt_merge_file(const char *filename, int flags); -// Debug function that prints the WAD directory. +/* Acts the same as NWT's "-merge" option. */ -void W_PrintDirectory(void); +void w_nwt_dash_merge(const char *filename); -#endif /* #ifndef W_MERGE_H */ +/* Debug function that prints the WAD directory. */ +void w_print_directory(void); + +#endif /* W_MERGE_H */ diff --git a/games/NXDoom/src/w_wad.c b/games/NXDoom/src/w_wad.c index 1b091834f79..88c75ada501 100644 --- a/games/NXDoom/src/w_wad.c +++ b/games/NXDoom/src/w_wad.c @@ -1,23 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Handles WAD file header, directory, lump I/O. -// - - - +/**************************************************************************** + * apps/games/NXDoom/src/w_wad.c + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Handles WAD file header, directory, lump I/O. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include @@ -35,595 +41,623 @@ #include "w_wad.h" -typedef PACKED_STRUCT ( +/**************************************************************************** + * Private Types + ****************************************************************************/ + +begin_packed_struct struct wadinfo_t { - // Should be "IWAD" or "PWAD". - char identification[4]; - int numlumps; - int infotableofs; -}) wadinfo_t; + /* Should be "IWAD" or "PWAD". */ + + char identification[4]; + int numlumps; + int infotableofs; +} end_packed_struct; +typedef struct wadinfo_t wadinfo_t; -typedef PACKED_STRUCT ( +begin_packed_struct struct filelump_t { - int filepos; - int size; - char name[8]; -}) filelump_t; + int filepos; + int size; + char name[8]; +} end_packed_struct; -// -// GLOBALS -// +typedef struct filelump_t filelump_t; -// Location of each lump on disk. -lumpinfo_t **lumpinfo; -unsigned int numlumps = 0; +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Hash table for fast lookups */ -// Hash table for fast lookups static lumpindex_t *lumphash; -// Variables for the reload hack: filename of the PWAD to reload, and the -// lumps from WADs before the reload file, so we can resent numlumps and -// load the file again. +/* Variables for the reload hack: filename of the PWAD to reload, and the + * lumps from WADs before the reload file, so we can resent numlumps and + * load the file again. + */ + static wad_file_t *reloadhandle = NULL; static lumpinfo_t *reloadlumps = NULL; static char *reloadname = NULL; static int reloadlump = -1; -// Hash function used for lump names. -unsigned int W_LumpNameHash(const char *s) +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Location of each lump on disk. */ + +lumpinfo_t **lumpinfo; +unsigned int numlumps = 0; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Hash function used for lump names. */ + +unsigned int w_lump_name_hash(const char *s) { - // This is the djb2 string hash function, modded to work on strings - // that have a maximum length of 8. + /* This is the djb2 string hash function, modded to work on strings + * that have a maximum length of 8. + */ - unsigned int result = 5381; - unsigned int i; + unsigned int result = 5381; + unsigned int i; - for (i=0; i < 8 && s[i] != '\0'; ++i) + for (i = 0; i < 8 && s[i] != '\0'; ++i) { - result = ((result << 5) ^ result ) ^ toupper(s[i]); + result = ((result << 5) ^ result) ^ toupper(s[i]); } - return result; + return result; } -// -// LUMP BASED ROUTINES. -// +/* LUMP BASED ROUTINES. */ -// -// W_AddFile -// All files are optional, but at least one file must be -// found (PWAD, if all required lumps are present). -// Files with a .wad extension are wadlink files -// with multiple lumps. -// Other files are single lumps with the base filename -// for the lump name. +/* w_add_file + * + * All files are optional, but at least one file must be found (PWAD, if all + * required lumps are present). + * + * Files with a .wad extension are wadlink files with multiple lumps. + * + * Other files are single lumps with the base filename for the lump name. + */ -wad_file_t *W_AddFile (const char *filename) +wad_file_t *w_add_file(const char *filename) { - wadinfo_t header; - lumpindex_t i; - wad_file_t *wad_file; - int length; - int startlump; - filelump_t *fileinfo; - filelump_t *filerover; - lumpinfo_t *filelumps; - int numfilelumps; - - // If the filename begins with a ~, it indicates that we should use the - // reload hack. - if (filename[0] == '~') + wadinfo_t header; + lumpindex_t i; + wad_file_t *wad_file; + int length; + int startlump; + filelump_t *fileinfo; + filelump_t *filerover; + lumpinfo_t *filelumps; + int numfilelumps; + + /* If the filename begins with a ~, it indicates that we should use the + * reload hack. + */ + + if (filename[0] == '~') { - if (reloadname != NULL) + if (reloadname != NULL) { - I_Error("Prefixing a WAD filename with '~' indicates that the " - "WAD should be reloaded\n" - "on each level restart, for use by level authors for " - "rapid development. You\n" - "can only reload one WAD file, and it must be the last " - "file in the -file list."); + i_error("Prefixing a WAD filename with '~' indicates that the " + "WAD should be reloaded\n" + "on each level restart, for use by level authors for " + "rapid development. You\n" + "can only reload one WAD file, and it must be the last " + "file in the -file list."); } - reloadname = strdup(filename); - reloadlump = numlumps; - ++filename; + reloadname = strdup(filename); + reloadlump = numlumps; + ++filename; } - // Open the file and add to directory - wad_file = W_OpenFile(filename); + /* Open the file and add to directory */ + + wad_file = w_open_file(filename); - if (wad_file == NULL) + if (wad_file == NULL) { - printf (" couldn't open %s\n", filename); - return NULL; + printf(" couldn't open %s\n", filename); + return NULL; } - if (strcasecmp(filename+strlen(filename)-3 , "wad" ) ) + if (strcasecmp(filename + strlen(filename) - 3, "wad")) { - // single lump file + /* single lump file */ - // fraggle: Swap the filepos and size here. The WAD directory - // parsing code expects a little-endian directory, so will swap - // them back. Effectively we're constructing a "fake WAD directory" - // here, as it would appear on disk. + /* fraggle: Swap the filepos and size here. The WAD directory + * parsing code expects a little-endian directory, so will swap + * them back. Effectively we're constructing a "fake WAD directory" + * here, as it would appear on disk. + */ - fileinfo = Z_Malloc(sizeof(filelump_t), PU_STATIC, 0); - fileinfo->filepos = LONG(0); - fileinfo->size = LONG(wad_file->length); + fileinfo = z_malloc(sizeof(filelump_t), PU_STATIC, 0); + fileinfo->filepos = LONG(0); + fileinfo->size = LONG(wad_file->length); - // Name the lump after the base of the filename (without the - // extension). + /* Name the lump after the base of the filename (without the + * extension). + */ - M_ExtractFileBase (filename, fileinfo->name); - numfilelumps = 1; + m_extract_file_base(filename, fileinfo->name); + numfilelumps = 1; } - else + else { - // WAD file - W_Read(wad_file, 0, &header, sizeof(header)); - - if (strncmp(header.identification,"IWAD",4)) - { - // Homebrew levels? - if (strncmp(header.identification,"PWAD",4)) - { - W_CloseFile(wad_file); - I_Error ("Wad file %s doesn't have IWAD " - "or PWAD id\n", filename); - } - - // ???modifiedgame = true; - } - - header.numlumps = LONG(header.numlumps); - - // Vanilla Doom doesn't like WADs with more than 4046 lumps - // https://www.doomworld.com/vb/post/1010985 - if (!strncmp(header.identification,"PWAD",4) && header.numlumps > 4046) - { - W_CloseFile(wad_file); - I_Error ("Error: Vanilla limit for lumps in a WAD is 4046, " - "PWAD %s has %d", filename, header.numlumps); - } - - header.infotableofs = LONG(header.infotableofs); - length = header.numlumps*sizeof(filelump_t); - fileinfo = Z_Malloc(length, PU_STATIC, 0); - - W_Read(wad_file, header.infotableofs, fileinfo, length); - numfilelumps = header.numlumps; + /* WAD file */ + + w_read(wad_file, 0, &header, sizeof(header)); + + if (strncmp(header.identification, "IWAD", 4)) + { + /* Homebrew levels? */ + + if (strncmp(header.identification, "PWAD", 4)) + { + w_close_file(wad_file); + i_error("Wad file %s doesn't have IWAD " + "or PWAD id\n", + filename); + } + + /* ???modifiedgame = true; */ + } + + header.numlumps = LONG(header.numlumps); + + /* Vanilla Doom doesn't like WADs with more than 4046 lumps + * https://www.doomworld.com/vb/post/1010985 + */ + + if (!strncmp(header.identification, "PWAD", 4) && + header.numlumps > 4046) + { + w_close_file(wad_file); + i_error("Error: Vanilla limit for lumps in a WAD is 4046, " + "PWAD %s has %d", + filename, header.numlumps); + } + + header.infotableofs = LONG(header.infotableofs); + length = header.numlumps * sizeof(filelump_t); + fileinfo = z_malloc(length, PU_STATIC, 0); + + w_read(wad_file, header.infotableofs, fileinfo, length); + numfilelumps = header.numlumps; } - // Increase size of numlumps array to accomodate the new file. - filelumps = calloc(numfilelumps, sizeof(lumpinfo_t)); - if (filelumps == NULL) + /* Increase size of numlumps array to accommodate the new file. */ + + filelumps = calloc(numfilelumps, sizeof(lumpinfo_t)); + if (filelumps == NULL) { - W_CloseFile(wad_file); - I_Error("Failed to allocate array for lumps from new file."); + w_close_file(wad_file); + i_error("Failed to allocate array for lumps from new file."); } - startlump = numlumps; - numlumps += numfilelumps; - lumpinfo = I_Realloc(lumpinfo, numlumps * sizeof(lumpinfo_t *)); - filerover = fileinfo; + startlump = numlumps; + numlumps += numfilelumps; + lumpinfo = i_realloc(lumpinfo, numlumps * sizeof(lumpinfo_t *)); + filerover = fileinfo; - for (i = startlump; i < numlumps; ++i) + for (i = startlump; i < numlumps; ++i) { - lumpinfo_t *lump_p = &filelumps[i - startlump]; - lump_p->wad_file = wad_file; - lump_p->position = LONG(filerover->filepos); - lump_p->size = LONG(filerover->size); - lump_p->cache = NULL; - strncpy(lump_p->name, filerover->name, 8); - lumpinfo[i] = lump_p; - - ++filerover; + lumpinfo_t *lump_p = &filelumps[i - startlump]; + lump_p->wad_file = wad_file; + lump_p->position = LONG(filerover->filepos); + lump_p->size = LONG(filerover->size); + lump_p->cache = NULL; + strncpy(lump_p->name, filerover->name, 8); + lumpinfo[i] = lump_p; + + ++filerover; } - Z_Free(fileinfo); + z_free(fileinfo); - if (lumphash != NULL) + if (lumphash != NULL) { - Z_Free(lumphash); - lumphash = NULL; + z_free(lumphash); + lumphash = NULL; } - // If this is the reload file, we need to save some details about the - // file so that we can close it later on when we do a reload. - if (reloadname) + /* If this is the reload file, we need to save some details about the + * file so that we can close it later on when we do a reload. + */ + + if (reloadname) { - reloadhandle = wad_file; - reloadlumps = filelumps; + reloadhandle = wad_file; + reloadlumps = filelumps; } - return wad_file; + return wad_file; } +/* w_check_num_for_name + * Returns -1 if name not found. + */ - -// -// W_NumLumps -// -int W_NumLumps (void) +lumpindex_t w_check_num_for_name(const char *name) { - return numlumps; -} - - + lumpindex_t i; -// -// W_CheckNumForName -// Returns -1 if name not found. -// - -lumpindex_t W_CheckNumForName(const char *name) -{ - lumpindex_t i; + /* Do we have a hash table yet? */ - // Do we have a hash table yet? - - if (lumphash != NULL) + if (lumphash != NULL) { - int hash; + int hash; - // We do! Excellent. + /* We do! Excellent. */ - hash = W_LumpNameHash(name) % numlumps; + hash = w_lump_name_hash(name) % numlumps; - for (i = lumphash[hash]; i != -1; i = lumpinfo[i]->next) + for (i = lumphash[hash]; i != -1; i = lumpinfo[i]->next) { - if (!strncasecmp(lumpinfo[i]->name, name, 8)) + if (!strncasecmp(lumpinfo[i]->name, name, 8)) { - return i; + return i; } } } - else + else { - // We don't have a hash table generate yet. Linear search :-( - // - // scan backwards so patch lump files take precedence + /* We don't have a hash table generate yet. Linear search :-( + * + * scan backwards so patch lump files take precedence + */ - for (i = numlumps - 1; i >= 0; --i) + for (i = numlumps - 1; i >= 0; --i) { - if (!strncasecmp(lumpinfo[i]->name, name, 8)) + if (!strncasecmp(lumpinfo[i]->name, name, 8)) { - return i; + return i; } } } - // TFB. Not found. + /* TFB. Not found. */ - return -1; + return -1; } +/* w_get_num_for_name + * Calls w_check_num_for_name, but bombs out if not found. + */ - - -// -// W_GetNumForName -// Calls W_CheckNumForName, but bombs out if not found. -// -lumpindex_t W_GetNumForName(const char *name) +lumpindex_t w_get_num_for_name(const char *name) { - lumpindex_t i; + lumpindex_t i; - i = W_CheckNumForName (name); + i = w_check_num_for_name(name); - if (i < 0) + if (i < 0) { - I_Error ("W_GetNumForName: %s not found!", name); + i_error("w_get_num_for_name: %s not found!", name); } - - return i; + + return i; } +/* w_lump_length + * Returns the buffer size needed to load the given lump. + */ -// -// W_LumpLength -// Returns the buffer size needed to load the given lump. -// -int W_LumpLength(lumpindex_t lump) +int w_lump_length(lumpindex_t lump) { - if (lump >= numlumps) + if (lump >= numlumps) { - I_Error ("W_LumpLength: %i >= numlumps", lump); + i_error("w_lump_length: %i >= numlumps", lump); } - return lumpinfo[lump]->size; + return lumpinfo[lump]->size; } +/* w_read_lump + * Loads the lump into the given buffer, + * which must be >= w_lump_length(). + */ - -// -// W_ReadLump -// Loads the lump into the given buffer, -// which must be >= W_LumpLength(). -// -void W_ReadLump(lumpindex_t lump, void *dest) +void w_read_lump(lumpindex_t lump, void *dest) { - int c; - lumpinfo_t *l; + int c; + lumpinfo_t *l; - if (lump >= numlumps) + if (lump >= numlumps) { - I_Error ("W_ReadLump: %i >= numlumps", lump); + i_error("w_read_lump: %i >= numlumps", lump); } - l = lumpinfo[lump]; + l = lumpinfo[lump]; - V_BeginRead(l->size); + v_begin_read(l->size); - c = W_Read(l->wad_file, l->position, dest, l->size); + c = w_read(l->wad_file, l->position, dest, l->size); - if (c < l->size) + if (c < l->size) { - I_Error("W_ReadLump: only read %i of %i on lump %i", - c, l->size, lump); + i_error("w_read_lump: only read %i of %i on lump %i", + c, l->size, lump); } } - - - -// -// W_CacheLumpNum -// -// Load a lump into memory and return a pointer to a buffer containing -// the lump data. -// -// 'tag' is the type of zone memory buffer to allocate for the lump -// (usually PU_STATIC or PU_CACHE). If the lump is loaded as -// PU_STATIC, it should be released back using W_ReleaseLumpNum -// when no longer needed (do not use Z_ChangeTag). -// - -void *W_CacheLumpNum(lumpindex_t lumpnum, int tag) +/* w_cache_lump_num + * + * Load a lump into memory and return a pointer to a buffer containing + * the lump data. + * + * 'tag' is the type of zone memory buffer to allocate for the lump + * (usually PU_STATIC or PU_CACHE). If the lump is loaded as + * PU_STATIC, it should be released back using w_release_lump_num + * when no longer needed (do not use z_change_tag). + */ + +void *w_cache_lump_num(lumpindex_t lumpnum, int tag) { - byte *result; - lumpinfo_t *lump; + byte *result; + lumpinfo_t *lump; - if ((unsigned)lumpnum >= numlumps) + if ((unsigned)lumpnum >= numlumps) { - I_Error ("W_CacheLumpNum: %i >= numlumps", lumpnum); + i_error("w_cache_lump_num: %i >= numlumps", lumpnum); } - lump = lumpinfo[lumpnum]; + lump = lumpinfo[lumpnum]; - // Get the pointer to return. If the lump is in a memory-mapped - // file, we can just return a pointer to within the memory-mapped - // region. If the lump is in an ordinary file, we may already - // have it cached; otherwise, load it into memory. + /* Get the pointer to return. If the lump is in a memory-mapped + * file, we can just return a pointer to within the memory-mapped + * region. If the lump is in an ordinary file, we may already + * have it cached; otherwise, load it into memory. + */ - if (lump->wad_file->mapped != NULL) + if (lump->wad_file->mapped != NULL) { - // Memory mapped file, return from the mmapped region. + /* Memory mapped file, return from the mmapped region. */ - result = lump->wad_file->mapped + lump->position; + result = lump->wad_file->mapped + lump->position; } - else if (lump->cache != NULL) + else if (lump->cache != NULL) { - // Already cached, so just switch the zone tag. + /* Already cached, so just switch the zone tag. */ - result = lump->cache; - Z_ChangeTag(lump->cache, tag); + result = lump->cache; + z_change_tag(lump->cache, tag); } - else + else { - // Not yet loaded, so load it now + /* Not yet loaded, so load it now */ - lump->cache = Z_Malloc(W_LumpLength(lumpnum), tag, &lump->cache); - W_ReadLump (lumpnum, lump->cache); - result = lump->cache; + lump->cache = z_malloc(w_lump_length(lumpnum), tag, &lump->cache); + w_read_lump(lumpnum, lump->cache); + result = lump->cache; } - - return result; -} + return result; +} +/* w_cache_lump_name */ -// -// W_CacheLumpName -// -void *W_CacheLumpName(const char *name, int tag) +void *w_cache_lump_name(const char *name, int tag) { - return W_CacheLumpNum(W_GetNumForName(name), tag); + return w_cache_lump_num(w_get_num_for_name(name), tag); } -// -// Release a lump back to the cache, so that it can be reused later -// without having to read from disk again, or alternatively, discarded -// if we run out of memory. -// -// Back in Vanilla Doom, this was just done using Z_ChangeTag -// directly, but now that we have WAD mmap, things are a bit more -// complicated ... -// - -void W_ReleaseLumpNum(lumpindex_t lumpnum) +/* Release a lump back to the cache, so that it can be reused later + * without having to read from disk again, or alternatively, discarded + * if we run out of memory. + * + * Back in Vanilla Doom, this was just done using z_change_tag + * directly, but now that we have WAD mmap, things are a bit more + * complicated ... + */ + +void w_release_lump_num(lumpindex_t lumpnum) { - lumpinfo_t *lump; + lumpinfo_t *lump; - if ((unsigned)lumpnum >= numlumps) + if ((unsigned)lumpnum >= numlumps) { - I_Error ("W_ReleaseLumpNum: %i >= numlumps", lumpnum); + i_error("w_release_lump_num: %i >= numlumps", lumpnum); } - lump = lumpinfo[lumpnum]; + lump = lumpinfo[lumpnum]; - if (lump->wad_file->mapped != NULL) + if (lump->wad_file->mapped != NULL) { - // Memory-mapped file, so nothing needs to be done here. + /* Memory-mapped file, so nothing needs to be done here. */ } - else + else { - Z_ChangeTag(lump->cache, PU_CACHE); + z_change_tag(lump->cache, PU_CACHE); } } -void W_ReleaseLumpName(const char *name) +void w_release_lump_name(const char *name) { - W_ReleaseLumpNum(W_GetNumForName(name)); + w_release_lump_num(w_get_num_for_name(name)); } #if 0 -// -// W_Profile -// -int info[2500][10]; -int profilecount; +/* w_profile */ + +int info[2500][10]; +int profilecount; -void W_Profile (void) +void w_profile(void) { - int i; - memblock_t* block; - void* ptr; - char ch; - FILE* f; - int j; - char name[9]; - - - for (i=0 ; itag < PU_PURGELEVEL) - ch = 'S'; - else - ch = 'P'; - } - info[i][profilecount] = ch; + int i; + memblock_t *block; + void *ptr; + char ch; + FILE *f; + int j; + char name[9]; + + for (i = 0; i < numlumps; i++) + { + ptr = lumpinfo[i].cache; + if (!ptr) + { + ch = ' '; + continue; + } + else + { + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); + if (block->tag < PU_PURGELEVEL) + ch = 'S'; + else + ch = 'P'; + } + + info[i][profilecount] = ch; } - profilecount++; - - f = M_fopen ("waddump.txt","w"); - name[8] = 0; - for (i=0 ; i 0) + /* Generate hash table */ + + if (numlumps > 0) { - lumphash = Z_Malloc(sizeof(lumpindex_t) * numlumps, PU_STATIC, NULL); + lumphash = z_malloc(sizeof(lumpindex_t) * numlumps, PU_STATIC, NULL); - for (i = 0; i < numlumps; ++i) + for (i = 0; i < numlumps; ++i) { - lumphash[i] = -1; + lumphash[i] = -1; } - for (i = 0; i < numlumps; ++i) + for (i = 0; i < numlumps; ++i) { - unsigned int hash; + unsigned int hash; - hash = W_LumpNameHash(lumpinfo[i]->name) % numlumps; + hash = w_lump_name_hash(lumpinfo[i]->name) % numlumps; - // Hook into the hash table + /* Hook into the hash table */ - lumpinfo[i]->next = lumphash[hash]; - lumphash[hash] = i; + lumpinfo[i]->next = lumphash[hash]; + lumphash[hash] = i; } } - // All done! + /* All done! */ } -// The Doom reload hack. The idea here is that if you give a WAD file to -file -// prefixed with the ~ hack, that WAD file will be reloaded each time a new -// level is loaded. This lets you use a level editor in parallel and make -// incremental changes to the level you're working on without having to restart -// the game after every change. -// But: the reload feature is a fragile hack... -void W_Reload(void) +/* The Doom reload hack. The idea here is that if you give a WAD file to + * -file prefixed with the ~ hack, that WAD file will be reloaded each time a + * new level is loaded. This lets you use a level editor in parallel and make + * incremental changes to the level you're working on without having to + * restart the game after every change. But: the reload feature is a fragile + * hack... + */ + +void w_reload(void) { - char *filename; - lumpindex_t i; + char *filename; + lumpindex_t i; - if (reloadname == NULL) + if (reloadname == NULL) { - return; + return; } - // We must free any lumps being cached from the PWAD we're about to reload: - for (i = reloadlump; i < numlumps; ++i) + /* We must free any lumps being cached from the PWAD we're about to reload: + */ + + for (i = reloadlump; i < numlumps; ++i) { - if (lumpinfo[i]->cache != NULL) + if (lumpinfo[i]->cache != NULL) { - Z_Free(lumpinfo[i]->cache); + z_free(lumpinfo[i]->cache); } } - // Reset numlumps to remove the reload WAD file: - numlumps = reloadlump; + /* Reset numlumps to remove the reload WAD file: */ + + numlumps = reloadlump; + + /* Now reload the WAD file. */ + + filename = reloadname; - // Now reload the WAD file. - filename = reloadname; + w_close_file(reloadhandle); + free(reloadlumps); - W_CloseFile(reloadhandle); - free(reloadlumps); + reloadname = NULL; + reloadlump = -1; + reloadhandle = NULL; + w_add_file(filename); + free(filename); - reloadname = NULL; - reloadlump = -1; - reloadhandle = NULL; - W_AddFile(filename); - free(filename); + /* The WAD directory has changed, so we have to regenerate the + * fast lookup hashtable: + */ - // The WAD directory has changed, so we have to regenerate the - // fast lookup hashtable: - W_GenerateHashTable(); + w_generate_hash_table(); } -const char *W_WadNameForLump(const lumpinfo_t *lump) +const char *w_wad_name_for_lump(const lumpinfo_t *lump) { - return M_BaseName(lump->wad_file->path); + return m_base_name(lump->wad_file->path); } -boolean W_IsIWADLump(const lumpinfo_t *lump) +boolean w_is_iwad_lump(const lumpinfo_t *lump) { - return lump->wad_file == lumpinfo[0]->wad_file; + return lump->wad_file == lumpinfo[0]->wad_file; } diff --git a/games/NXDoom/src/w_wad.h b/games/NXDoom/src/w_wad.h index ae5977a27bb..867ac5add0f 100644 --- a/games/NXDoom/src/w_wad.h +++ b/games/NXDoom/src/w_wad.h @@ -1,78 +1,91 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// WAD I/O functions. -// - +/**************************************************************************** + * apps/games/NXDoom/src/w_wad.h + * + * SPDX-License-Identifier: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * WAD I/O functions. + * + ****************************************************************************/ #ifndef __W_WAD__ #define __W_WAD__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include #include "doomtype.h" #include "w_file.h" +/**************************************************************************** + * Public Types + ****************************************************************************/ -// -// TYPES -// - -// -// WADFILE I/O related stuff. -// +/* WADFILE I/O related stuff. */ typedef struct lumpinfo_s lumpinfo_t; typedef int lumpindex_t; struct lumpinfo_s { - char name[8]; - wad_file_t *wad_file; - int position; - int size; - void *cache; - - // Used for hash table lookups - lumpindex_t next; + char name[8]; + wad_file_t *wad_file; + int position; + int size; + void *cache; + + /* Used for hash table lookups */ + + lumpindex_t next; }; +/**************************************************************************** + * Public Data + ****************************************************************************/ extern lumpinfo_t **lumpinfo; extern unsigned int numlumps; -wad_file_t *W_AddFile(const char *filename); -void W_Reload(void); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +wad_file_t *w_add_file(const char *filename); +void w_reload(void); -lumpindex_t W_CheckNumForName(const char *name); -lumpindex_t W_GetNumForName(const char *name); +lumpindex_t w_check_num_for_name(const char *name); +lumpindex_t w_get_num_for_name(const char *name); -int W_LumpLength(lumpindex_t lump); -void W_ReadLump(lumpindex_t lump, void *dest); +int w_lump_length(lumpindex_t lump); +void w_read_lump(lumpindex_t lump, void *dest); -void *W_CacheLumpNum(lumpindex_t lump, int tag); -void *W_CacheLumpName(const char *name, int tag); +void *w_cache_lump_num(lumpindex_t lump, int tag); +void *w_cache_lump_name(const char *name, int tag); -void W_GenerateHashTable(void); +void w_generate_hash_table(void); -extern unsigned int W_LumpNameHash(const char *s); +extern unsigned int w_lump_name_hash(const char *s); -void W_ReleaseLumpNum(lumpindex_t lump); -void W_ReleaseLumpName(const char *name); +void w_release_lump_num(lumpindex_t lump); +void w_release_lump_name(const char *name); -const char *W_WadNameForLump(const lumpinfo_t *lump); -boolean W_IsIWADLump(const lumpinfo_t *lump); +const char *w_wad_name_for_lump(const lumpinfo_t *lump); +boolean w_is_iwad_lump(const lumpinfo_t *lump); -#endif +#endif /* __W_WAD_H__ */ diff --git a/games/NXDoom/src/z_native.c b/games/NXDoom/src/z_native.c index c7f8f3cd55e..3d962bbd02b 100644 --- a/games/NXDoom/src/z_native.c +++ b/games/NXDoom/src/z_native.c @@ -1,506 +1,556 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Zone Memory Allocation. Neat. -// -// This is an implementation of the zone memory API which -// uses native calls to malloc() and free(). -// - +/**************************************************************************** + * apps/games/NXDoom/src/z_native.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Zone Memory Allocation. Neat. + * + * This is an implementation of the zone memory API which + * uses native calls to malloc() and free(). + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include #include -#include "z_zone.h" -#include "i_system.h" #include "doomtype.h" +#include "i_system.h" +#include "z_zone.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ZONEID 0x1d4a11 + +#ifdef TESTING +#define malloc test_malloc +#define free test_free +#endif -#define ZONEID 0x1d4a11 +/**************************************************************************** + * Private Types + ****************************************************************************/ typedef struct memblock_s memblock_t; struct memblock_s { - int id; // = ZONEID - int tag; - int size; - void **user; - memblock_t *prev; - memblock_t *next; + int id; /* = ZONEID */ + int tag; + int size; + void **user; + memblock_t *prev; + memblock_t *next; }; -// Linked list of allocated blocks for each tag type - +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Linked list of allocated blocks for each tag type */ + static memblock_t *allocated_blocks[PU_NUM_TAGS]; #ifdef TESTING - static int test_malloced = 0; +#endif -void *test_malloc(size_t size) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: z_insert_block + * + * Description: + * Add a block into the linked list for its type. + * + ****************************************************************************/ + +static void z_insert_block(memblock_t *block) { - int *result; + block->prev = NULL; + block->next = allocated_blocks[block->tag]; + allocated_blocks[block->tag] = block; - if (test_malloced + size > 2 * 1024 * 1024) + if (block->next != NULL) { - return NULL; + block->next->prev = block; } +} - test_malloced += size; - - result = malloc(size + sizeof(int)); +/**************************************************************************** + * Name: z_insert_block + * + * Description: + * Remove a block from its linked list. + * + ****************************************************************************/ - *result = size; +static void z_remove_block(memblock_t *block) +{ + /* Unlink from list */ - return result + 1; -} + if (block->prev == NULL) + { + /* Start of list */ -void test_free(void *data) -{ - int *i; + allocated_blocks[block->tag] = block->next; + } + else + { + if (block->prev->next != block) + { + i_error("Z_RemoveBlock: Doubly-linked list corrupted!"); + } - i = ((int *) data) - 1; + block->prev->next = block->next; + } - test_malloced -= *i; + if (block->next != NULL) + { + if (block->next->prev != block) + { + i_error("Z_RemoveBlock: Doubly-linked list corrupted!"); + } - free(i); + block->next->prev = block->prev; + } } -#define malloc test_malloc -#define free test_free +/**************************************************************************** + * Name: clear_cache + * + * Description: + * Empty data from the cache list to allocate enough data of the size + * required. + * + * Return: + * Returns true if any blocks were freed. + * + ****************************************************************************/ + +static boolean clear_cache(int size) +{ + memblock_t *block; + memblock_t *next_block; + int remaining; -#endif /* #ifdef TESTING */ + block = allocated_blocks[PU_CACHE]; + if (block == NULL) + { + /* Cache is already empty. */ + + return false; + } -// Add a block into the linked list for its type. + /* Search to the end of the PU_CACHE list. The blocks at the end + * of the list are the ones that have been free for longer and + * are more likely to be unneeded now. + */ -static void Z_InsertBlock(memblock_t *block) -{ - block->prev = NULL; - block->next = allocated_blocks[block->tag]; - allocated_blocks[block->tag] = block; - - if (block->next != NULL) + while (block->next != NULL) { - block->next->prev = block; + block = block->next; } -} - -// Remove a block from its linked list. -static void Z_RemoveBlock(memblock_t *block) -{ - // Unlink from list + /* Search backwards through the list freeing blocks until we have + * freed the amount of memory required. + */ - if (block->prev == NULL) - { - // Start of list + remaining = size; - allocated_blocks[block->tag] = block->next; - } - else + while (remaining > 0) { - if (block->prev->next != block) + if (block == NULL) { - I_Error("Z_RemoveBlock: Doubly-linked list corrupted!"); + break; /* No blocks left to free; we've done our best. */ } - block->prev->next = block->next; - } - if (block->next != NULL) - { - if (block->next->prev != block) + next_block = block->prev; + + z_remove_block(block); + + remaining -= block->size; + + if (block->user) { - I_Error("Z_RemoveBlock: Doubly-linked list corrupted!"); + *block->user = NULL; } - block->next->prev = block->prev; + + free(block); + + block = next_block; } -} -// -// Z_Init -// -void Z_Init (void) -{ - memset(allocated_blocks, 0, sizeof(allocated_blocks)); - printf("zone memory: Using native C allocator.\n"); + return true; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ -// -// Z_Free -// -void Z_Free (void* ptr) +#ifdef TESTING +void *test_malloc(size_t size) { - memblock_t* block; - - block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + int *result; - if (block->id != ZONEID) + if (test_malloced + size > 2 * 1024 * 1024) { - I_Error ("Z_Free: freed a pointer without ZONEID"); + return NULL; } - - if (block->tag != PU_FREE && block->user != NULL) - { - // clear the user's mark - *block->user = NULL; - } + test_malloced += size; - Z_RemoveBlock(block); + result = malloc(size + sizeof(int)); - // Free back to system + *result = size; - free(block); + return result + 1; } -// Empty data from the cache list to allocate enough data of the size -// required. -// -// Returns true if any blocks were freed. - -static boolean ClearCache(int size) +void test_free(void *data) { - memblock_t *block; - memblock_t *next_block; - int remaining; + int *i; - block = allocated_blocks[PU_CACHE]; + i = ((int *)data) - 1; - if (block == NULL) - { - // Cache is already empty. + test_malloced -= *i; - return false; - } + free(i); +} +#endif /* #ifdef TESTING */ - // Search to the end of the PU_CACHE list. The blocks at the end - // of the list are the ones that have been free for longer and - // are more likely to be unneeded now. +/**************************************************************************** + * Name: z_init + ****************************************************************************/ - while (block->next != NULL) - { - block = block->next; - } +void z_init(void) +{ + memset(allocated_blocks, 0, sizeof(allocated_blocks)); + printf("zone memory: Using native C allocator.\n"); +} - //printf("out of memory; cleaning out the cache: %i\n", test_malloced); +/**************************************************************************** + * Name: z_free + ****************************************************************************/ - // Search backwards through the list freeing blocks until we have - // freed the amount of memory required. +void z_free(void *ptr) +{ + memblock_t *block; - remaining = size; + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); - while (remaining > 0) + if (block->id != ZONEID) { - if (block == NULL) - { - // No blocks left to free; we've done our best. - - break; - } - - next_block = block->prev; - - Z_RemoveBlock(block); + i_error("z_free: freed a pointer without ZONEID"); + } - remaining -= block->size; + if (block->tag != PU_FREE && block->user != NULL) + { + /* clear the user's mark */ - if (block->user) - { - *block->user = NULL; - } + *block->user = NULL; + } - free(block); + z_remove_block(block); - block = next_block; - } + /* Free back to system */ - return true; + free(block); } -// -// Z_Malloc -// You can pass a NULL user if the tag is < PU_PURGELEVEL. -// - -void *Z_Malloc(int size, int tag, void *user) +/**************************************************************************** + * Name: z_malloc + * + * Description: + * You can pass a NULL user if the tag is < PU_PURGELEVEL. + * + * Return: + * The translated key code. + * + ****************************************************************************/ + +void *z_malloc(int size, int tag, void *user) { - memblock_t *newblock; - unsigned char *data; - void *result; + memblock_t *newblock; + unsigned char *data; + void *result; - if (tag < 0 || tag >= PU_NUM_TAGS || tag == PU_FREE) + if (tag < 0 || tag >= PU_NUM_TAGS || tag == PU_FREE) { - I_Error("Z_Malloc: attempted to allocate a block with an invalid " - "tag: %i", tag); + i_error("z_malloc: attempted to allocate a block with an invalid " + "tag: %i", + tag); } - if (user == NULL && tag >= PU_PURGELEVEL) + if (user == NULL && tag >= PU_PURGELEVEL) { - I_Error ("Z_Malloc: an owner is required for purgable blocks"); + i_error("z_malloc: an owner is required for purgeable blocks"); } - // Malloc a block of the required size - - newblock = NULL; + /* Malloc a block of the required size */ - while (newblock == NULL) + newblock = NULL; + + while (newblock == NULL) { - newblock = (memblock_t *) malloc(sizeof(memblock_t) + size); + newblock = (memblock_t *)malloc(sizeof(memblock_t) + size); - if (newblock == NULL) + if (newblock == NULL) { - if (!ClearCache(sizeof(memblock_t) + size)) + if (!clear_cache(sizeof(memblock_t) + size)) { - I_Error("Z_Malloc: failed on allocation of %i bytes", size); + i_error("z_malloc: failed on allocation of %i bytes", size); } } } - newblock->tag = tag; - - // Hook into the linked list for this tag type + newblock->tag = tag; + + /* Hook into the linked list for this tag type */ - newblock->id = ZONEID; - newblock->user = user; - newblock->size = size; + newblock->id = ZONEID; + newblock->user = user; + newblock->size = size; - Z_InsertBlock(newblock); + z_insert_block(newblock); - data = (unsigned char *) newblock; - result = data + sizeof(memblock_t); + data = (unsigned char *)newblock; + result = data + sizeof(memblock_t); - if (user != NULL) + if (user != NULL) { - *newblock->user = result; + *newblock->user = result; } - - return result; -} - + return result; +} -// -// Z_FreeTags -// +/**************************************************************************** + * Name: z_free_tags + ****************************************************************************/ -void Z_FreeTags(int lowtag, int hightag) +void z_free_tags(int lowtag, int hightag) { - int i; + int i; - for (i=lowtag; i<= hightag; ++i) + for (i = lowtag; i <= hightag; ++i) { - memblock_t *block; - memblock_t *next; + memblock_t *block; + memblock_t *next; - // Free all in this chain + /* Free all in this chain */ - for (block=allocated_blocks[i]; block != NULL; ) + for (block = allocated_blocks[i]; block != NULL; ) { - next = block->next; + next = block->next; - // Free this block + /* Free this block */ - if (block->user != NULL) + if (block->user != NULL) { - *block->user = NULL; + *block->user = NULL; } - - free(block); - // Jump to the next in the chain + free(block); + + /* Jump to the next in the chain */ - block = next; + block = next; } - // This chain is empty now + /* This chain is empty now */ - allocated_blocks[i] = NULL; + allocated_blocks[i] = NULL; } } +/**************************************************************************** + * Name: z_dump_heap + ****************************************************************************/ - -// -// Z_DumpHeap -// -void Z_DumpHeap(int lowtag, int hightag) +void z_dump_heap(int lowtag, int hightag) { - // broken + /* WARN: broken */ #if 0 - memblock_t* block; - - printf ("zone size: %i location: %p\n", - mainzone->size,mainzone); - - printf ("tag range: %i to %i\n", - lowtag, hightag); - - for (block = mainzone->blocklist.next ; ; block = block->next) + memblock_t *block; + + printf("zone size: %i location: %p\n", mainzone->size, mainzone); + + printf("tag range: %i to %i\n", lowtag, hightag); + + for (block = mainzone->blocklist.next; ; block = block->next) { - if (block->tag >= lowtag && block->tag <= hightag) - printf ("block:%p size:%7i user:%p tag:%3i\n", - block, block->size, block->user, block->tag); - - if (block->next == &mainzone->blocklist) - { - // all blocks have been hit - break; - } - - if ( (byte *)block + block->size != (byte *)block->next) - printf ("ERROR: block size does not touch the next block\n"); - - if ( block->next->prev != block) - printf ("ERROR: next block doesn't have proper back link\n"); - - if (block->tag == PU_FREE && block->next->tag == PU_FREE) - printf ("ERROR: two consecutive free blocks\n"); + if (block->tag >= lowtag && block->tag <= hightag) + printf("block:%p size:%7i user:%p tag:%3i\n", block, + block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + /* all blocks have been hit */ + + break; + } + + if ((byte *)block + block->size != (byte *)block->next) + printf("ERROR: block size does not touch the next block\n"); + + if (block->next->prev != block) + printf("ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + printf("ERROR: two consecutive free blocks\n"); } #endif } +/**************************************************************************** + * Name: z_file_dump_heap + ****************************************************************************/ -// -// Z_FileDumpHeap -// -void Z_FileDumpHeap(FILE *f) +void z_file_dump_heap(FILE *f) { - // broken + /* WARN: broken */ #if 0 - memblock_t* block; - - fprintf (f,"zone size: %i location: %p\n",mainzone->size,mainzone); - - for (block = mainzone->blocklist.next ; ; block = block->next) + memblock_t *block; + + fprintf(f, "zone size: %i location: %p\n", mainzone->size, mainzone); + + for (block = mainzone->blocklist.next; ; block = block->next) { - fprintf (f,"block:%p size:%7i user:%p tag:%3i\n", - block, block->size, block->user, block->tag); - - if (block->next == &mainzone->blocklist) - { - // all blocks have been hit - break; - } - - if ( (byte *)block + block->size != (byte *)block->next) - fprintf (f,"ERROR: block size does not touch the next block\n"); - - if ( block->next->prev != block) - fprintf (f,"ERROR: next block doesn't have proper back link\n"); - - if (block->tag == PU_FREE && block->next->tag == PU_FREE) - fprintf (f,"ERROR: two consecutive free blocks\n"); + fprintf(f, "block:%p size:%7i user:%p tag:%3i\n", block, + block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + /* all blocks have been hit */ + + break; + } + + if ((byte *)block + block->size != (byte *)block->next) + fprintf(f, "ERROR: block size does not touch the next block\n"); + + if (block->next->prev != block) + fprintf(f, "ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + fprintf(f, "ERROR: two consecutive free blocks\n"); } #endif } +/**************************************************************************** + * Name: z_check_heap + ****************************************************************************/ - -// -// Z_CheckHeap -// -void Z_CheckHeap (void) +void z_check_heap(void) { - memblock_t *block; - memblock_t *prev; - int i; + memblock_t *block; + memblock_t *prev; + int i; - // Check all chains + /* Check all chains */ - for (i=0; inext) + for (block = allocated_blocks[i]; block != NULL; block = block->next) { - if (block->id != ZONEID) + if (block->id != ZONEID) { - I_Error("Z_CheckHeap: Block without a ZONEID!"); + i_error("z_check_heap: Block without a ZONEID!"); } - - if (block->prev != prev) + + if (block->prev != prev) { - I_Error("Z_CheckHeap: Doubly-linked list corrupted!"); + i_error("z_check_heap: Doubly-linked list corrupted!"); } - - prev = block; + + prev = block; } } } +/**************************************************************************** + * Name: z_change_tag2 + ****************************************************************************/ - - -// -// Z_ChangeTag -// - -void Z_ChangeTag2(void *ptr, int tag, const char *file, int line) +void z_change_tag2(void *ptr, int tag, const char *file, int line) { - memblock_t* block; - - block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + memblock_t *block; - if (block->id != ZONEID) - I_Error("%s:%i: Z_ChangeTag: block without a ZONEID!", - file, line); + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); - if (tag >= PU_PURGELEVEL && block->user == NULL) - I_Error("%s:%i: Z_ChangeTag: an owner is required " - "for purgable blocks", file, line); + if (block->id != ZONEID) + i_error("%s:%i: z_change_tag: block without a ZONEID!", file, line); - // Remove the block from its current list, and rehook it into - // its new list. + if (tag >= PU_PURGELEVEL && block->user == NULL) + i_error("%s:%i: z_change_tag: an owner is required " + "for purgeable blocks", + file, line); - Z_RemoveBlock(block); - block->tag = tag; - Z_InsertBlock(block); + /* Remove the block from its current list, and rehook it into + * its new list. + */ + + z_remove_block(block); + block->tag = tag; + z_insert_block(block); } -void Z_ChangeUser(void *ptr, void **user) +void z_change_user(void *ptr, void **user) { - memblock_t* block; + memblock_t *block; - block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); - if (block->id != ZONEID) + if (block->id != ZONEID) { - I_Error("Z_ChangeUser: Tried to change user for invalid block!"); + i_error("z_change_user: Tried to change user for invalid block!"); } - block->user = user; - *user = ptr; + block->user = user; + *user = ptr; } +/**************************************************************************** + * Name: z_free_memory + ****************************************************************************/ -// -// Z_FreeMemory -// - -int Z_FreeMemory(void) +int z_free_memory(void) { - // Limited by the system?? - - return -1; + return -1; /* Limited by the system?? */ } -unsigned int Z_ZoneSize(void) +/**************************************************************************** + * Name: z_zone_size + ****************************************************************************/ + +unsigned int z_zone_size(void) { - return 0; + return 0; } - diff --git a/games/NXDoom/src/z_zone.c b/games/NXDoom/src/z_zone.c index c5c2dbf7c15..f5274e334fa 100644 --- a/games/NXDoom/src/z_zone.c +++ b/games/NXDoom/src/z_zone.c @@ -1,20 +1,29 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Zone Memory Allocation. Neat. -// +/**************************************************************************** + * apps/games/NXDoom/src/z_zone.c + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Zone Memory Allocation. Neat. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ #include @@ -24,529 +33,525 @@ #include "z_zone.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ZONE MEMORY ALLOCATION + * + * There is never any space between memblocks, + * and there will never be two contiguous free memblocks. + * The rover can be left pointing at a non-empty block. + * + * It is of no value to free a cacheable block, + * because it will get overwritten automatically if needed. + */ -// -// ZONE MEMORY ALLOCATION -// -// There is never any space between memblocks, -// and there will never be two contiguous free memblocks. -// The rover can be left pointing at a non-empty block. -// -// It is of no value to free a cachable block, -// because it will get overwritten automatically if needed. -// - #define MEM_ALIGN sizeof(void *) -#define ZONEID 0x1d4a11 +#define ZONEID 0x1d4a11 + +#define MINFRAGMENT 64 + +/**************************************************************************** + * Private Types + ****************************************************************************/ typedef struct memblock_s { - int size; // including the header and possibly tiny fragments - void** user; - int tag; // PU_FREE if this is free - int id; // should be ZONEID - struct memblock_s* next; - struct memblock_s* prev; + int size; /* including the header and possibly tiny fragments */ + void **user; + int tag; /* PU_FREE if this is free */ + int id; /* should be ZONEID */ + struct memblock_s *next; + struct memblock_s *prev; } memblock_t; - typedef struct { - // total bytes malloced, including header - int size; - - // start / end cap for linked list - memblock_t blocklist; - - memblock_t* rover; - -} memzone_t; + /* total bytes malloced, including header */ + + int size; + /* start / end cap for linked list */ + memblock_t blocklist; + + memblock_t *rover; +} memzone_t; + +/**************************************************************************** + * Private Data + ****************************************************************************/ static memzone_t *mainzone; static boolean zero_on_free; static boolean scan_on_free; +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: scan_for_block + * + * Description: + * Scan the zone heap for pointers within the specified range, and warn + * about any remaining pointers. + * + ****************************************************************************/ -// -// Z_ClearZone -// -void Z_ClearZone (memzone_t* zone) +static void scan_for_block(void *start, void *end) { - memblock_t* block; - - // set the entire zone to one free block - zone->blocklist.next = - zone->blocklist.prev = - block = (memblock_t *)( (byte *)zone + sizeof(memzone_t) ); - - zone->blocklist.user = (void *)zone; - zone->blocklist.tag = PU_STATIC; - zone->rover = block; - - block->prev = block->next = &zone->blocklist; - - // a free block. - block->tag = PU_FREE; - - block->size = zone->size - sizeof(memzone_t); -} + memblock_t *block; + void **mem; + int i; + int len; + int tag; + block = mainzone->blocklist.next; + while (block->next != &mainzone->blocklist) + { + tag = block->tag; -// -// Z_Init -// -void Z_Init (void) -{ - memblock_t* block; - int size; + if (tag == PU_STATIC || tag == PU_LEVEL || tag == PU_LEVSPEC) + { + /* Scan for pointers on the assumption that pointers are aligned + * on word boundaries (word size depending on pointer size): + */ - mainzone = (memzone_t *)I_ZoneBase (&size); - mainzone->size = size; + mem = (void **)((byte *)block + sizeof(memblock_t)); + len = (block->size - sizeof(memblock_t)) / sizeof(void *); - // set the entire zone to one free block - mainzone->blocklist.next = - mainzone->blocklist.prev = - block = (memblock_t *)( (byte *)mainzone + sizeof(memzone_t) ); + for (i = 0; i < len; ++i) + { + if (start <= mem[i] && mem[i] <= end) + { + fprintf(stderr, + "%p has dangling pointer into freed block " + "%p (%p -> %p)\n", + mem, start, &mem[i], mem[i]); + } + } + } - mainzone->blocklist.user = (void *)mainzone; - mainzone->blocklist.tag = PU_STATIC; - mainzone->rover = block; + block = block->next; + } +} - block->prev = block->next = &mainzone->blocklist; +/**************************************************************************** + * Public Functions + ****************************************************************************/ - // free block - block->tag = PU_FREE; +/**************************************************************************** + * Name: z_init + ****************************************************************************/ - block->size = mainzone->size - sizeof(memzone_t); +void z_init(void) +{ + memblock_t *block; + int size; - // [Deliberately undocumented] - // Zone memory debugging flag. If set, memory is zeroed after it is freed - // to deliberately break any code that attempts to use it after free. - // - zero_on_free = M_ParmExists("-zonezero"); + mainzone = (memzone_t *)i_zone_base(&size); + mainzone->size = size; - // [Deliberately undocumented] - // Zone memory debugging flag. If set, each time memory is freed, the zone - // heap is scanned to look for remaining pointers to the freed block. - // - scan_on_free = M_ParmExists("-zonescan"); -} + /* set the entire zone to one free block */ -// Scan the zone heap for pointers within the specified range, and warn about -// any remaining pointers. -static void ScanForBlock(void *start, void *end) -{ - memblock_t *block; - void **mem; - int i, len, tag; + mainzone->blocklist.next = mainzone->blocklist.prev = block = + (memblock_t *)((byte *)mainzone + sizeof(memzone_t)); - block = mainzone->blocklist.next; + mainzone->blocklist.user = (void *)mainzone; + mainzone->blocklist.tag = PU_STATIC; + mainzone->rover = block; - while (block->next != &mainzone->blocklist) - { - tag = block->tag; + block->prev = block->next = &mainzone->blocklist; - if (tag == PU_STATIC || tag == PU_LEVEL || tag == PU_LEVSPEC) - { - // Scan for pointers on the assumption that pointers are aligned - // on word boundaries (word size depending on pointer size): - mem = (void **) ((byte *) block + sizeof(memblock_t)); - len = (block->size - sizeof(memblock_t)) / sizeof(void *); + block->tag = PU_FREE; /* free block */ - for (i = 0; i < len; ++i) - { - if (start <= mem[i] && mem[i] <= end) - { - fprintf(stderr, - "%p has dangling pointer into freed block " - "%p (%p -> %p)\n", - mem, start, &mem[i], mem[i]); - } - } - } + block->size = mainzone->size - sizeof(memzone_t); - block = block->next; - } + /* [Deliberately undocumented] + * Zone memory debugging flag. If set, memory is zeroed after it is freed + * to deliberately break any code that attempts to use it after free. + */ + + zero_on_free = m_parm_exists("-zonezero"); + + /* [Deliberately undocumented] + * Zone memory debugging flag. If set, each time memory is freed, the zone + * heap is scanned to look for remaining pointers to the freed block. + */ + + scan_on_free = m_parm_exists("-zonescan"); } -// -// Z_Free -// -void Z_Free (void* ptr) +/**************************************************************************** + * Name: z_free + ****************************************************************************/ + +void z_free(void *ptr) { - memblock_t* block; - memblock_t* other; + memblock_t *block; + memblock_t *other; - block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); - if (block->id != ZONEID) - I_Error ("Z_Free: freed a pointer without ZONEID"); + if (block->id != ZONEID) i_error("z_free: freed a pointer without ZONEID"); - if (block->tag != PU_FREE && block->user != NULL) + if (block->tag != PU_FREE && block->user != NULL) { - // clear the user's mark - *block->user = 0; + *block->user = 0; /* clear the user's mark */ } - // mark as free - block->tag = PU_FREE; - block->user = NULL; - block->id = 0; + /* mark as free */ - // If the -zonezero flag is provided, we zero out the block on free - // to break code that depends on reading freed memory. - if (zero_on_free) + block->tag = PU_FREE; + block->user = NULL; + block->id = 0; + + /* If the -zonezero flag is provided, we zero out the block on free + * to break code that depends on reading freed memory. + */ + + if (zero_on_free) { - memset(ptr, 0, block->size - sizeof(memblock_t)); + memset(ptr, 0, block->size - sizeof(memblock_t)); } - if (scan_on_free) + + if (scan_on_free) { - ScanForBlock(ptr, - (byte *) ptr + block->size - sizeof(memblock_t)); + scan_for_block(ptr, (byte *)ptr + block->size - sizeof(memblock_t)); } - other = block->prev; + other = block->prev; - if (other->tag == PU_FREE) + if (other->tag == PU_FREE) { - // merge with previous free block - other->size += block->size; - other->next = block->next; - other->next->prev = other; + /* merge with previous free block */ - if (block == mainzone->rover) - mainzone->rover = other; + other->size += block->size; + other->next = block->next; + other->next->prev = other; - block = other; + if (block == mainzone->rover) mainzone->rover = other; + + block = other; } - other = block->next; - if (other->tag == PU_FREE) + other = block->next; + if (other->tag == PU_FREE) { - // merge the next free block onto the end - block->size += other->size; - block->next = other->next; - block->next->prev = block; + /* merge with previous free block */ + + block->size += other->size; + block->next = other->next; + block->next->prev = block; - if (other == mainzone->rover) - mainzone->rover = block; + if (other == mainzone->rover) mainzone->rover = block; } } +/**************************************************************************** + * Name: z_malloc + * + * Description: + * You can pass a NULL user if the tag is < PU_PURGELEVEL. + * + ****************************************************************************/ + +void *z_malloc(int size, int tag, void *user) +{ + int extra; + memblock_t *start; + memblock_t *rover; + memblock_t *newblock; + memblock_t *base; + void *result; + size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); -// -// Z_Malloc -// You can pass a NULL user if the tag is < PU_PURGELEVEL. -// -#define MINFRAGMENT 64 + /* scan through the block list, looking for the first free block of + * sufficient size, throwing out any purgeable blocks along the way. + */ + /* account for size of block header */ -void* -Z_Malloc -( int size, - int tag, - void* user ) -{ - int extra; - memblock_t* start; - memblock_t* rover; - memblock_t* newblock; - memblock_t* base; - void *result; - - size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); - - // scan through the block list, - // looking for the first free block - // of sufficient size, - // throwing out any purgable blocks along the way. - - // account for size of block header - size += sizeof(memblock_t); - - // if there is a free block behind the rover, - // back up over them - base = mainzone->rover; - - if (base->prev->tag == PU_FREE) - base = base->prev; - - rover = base; - start = base->prev; - - do + size += sizeof(memblock_t); + + /* if there is a free block behind the rover, back up over them */ + + base = mainzone->rover; + + if (base->prev->tag == PU_FREE) base = base->prev; + + rover = base; + start = base->prev; + + do { - if (rover == start) + if (rover == start) { - // scanned all the way around the list - I_Error ("Z_Malloc: failed on allocation of %i bytes", size); + /* scanned all the way around the list */ + + i_error("z_malloc: failed on allocation of %i bytes", size); } - - if (rover->tag != PU_FREE) + + if (rover->tag != PU_FREE) { - if (rover->tag < PU_PURGELEVEL) + if (rover->tag < PU_PURGELEVEL) { - // hit a block that can't be purged, - // so move base past it - base = rover = rover->next; + /* hit a block that can't be purged, so move base past it */ + + base = rover = rover->next; } - else + else { - // free the rover block (adding the size to base) - - // the rover can be the base block - base = base->prev; - Z_Free ((byte *)rover+sizeof(memblock_t)); - base = base->next; - rover = base->next; + /* free the rover block (adding the size to base) the rover can + * be the base block + */ + + base = base->prev; + z_free((byte *)rover + sizeof(memblock_t)); + base = base->next; + rover = base->next; } } - else + else { - rover = rover->next; + rover = rover->next; } + } + while (base->tag != PU_FREE || base->size < size); + + /* found a block big enough */ - } while (base->tag != PU_FREE || base->size < size); + extra = base->size - size; - - // found a block big enough - extra = base->size - size; - - if (extra > MINFRAGMENT) + if (extra > MINFRAGMENT) { - // there will be a free fragment after the allocated block - newblock = (memblock_t *) ((byte *)base + size ); - newblock->size = extra; - - newblock->tag = PU_FREE; - newblock->user = NULL; - newblock->prev = base; - newblock->next = base->next; - newblock->next->prev = newblock; - - base->next = newblock; - base->size = size; + /* there will be a free fragment after the allocated block */ + + newblock = (memblock_t *)((byte *)base + size); + newblock->size = extra; + + newblock->tag = PU_FREE; + newblock->user = NULL; + newblock->prev = base; + newblock->next = base->next; + newblock->next->prev = newblock; + + base->next = newblock; + base->size = size; } - - if (user == NULL && tag >= PU_PURGELEVEL) - I_Error ("Z_Malloc: an owner is required for purgable blocks"); - base->user = user; - base->tag = tag; + if (user == NULL && tag >= PU_PURGELEVEL) + i_error("z_malloc: an owner is required for purgeable blocks"); - result = (void *) ((byte *)base + sizeof(memblock_t)); + base->user = user; + base->tag = tag; - if (base->user) + result = (void *)((byte *)base + sizeof(memblock_t)); + + if (base->user) { - *base->user = result; + *base->user = result; } - // next allocation will start looking here - mainzone->rover = base->next; - - base->id = ZONEID; - - return result; -} + /* next allocation will start looking here */ + + mainzone->rover = base->next; + base->id = ZONEID; + return result; +} + +/**************************************************************************** + * Name: z_free_tags + ****************************************************************************/ -// -// Z_FreeTags -// -void -Z_FreeTags -( int lowtag, - int hightag ) +void z_free_tags(int lowtag, int hightag) { - memblock_t* block; - memblock_t* next; - - for (block = mainzone->blocklist.next ; - block != &mainzone->blocklist ; - block = next) + memblock_t *block; + memblock_t *next; + + for (block = mainzone->blocklist.next; block != &mainzone->blocklist; + block = next) { - // get link before freeing - next = block->next; - - // free block? - if (block->tag == PU_FREE) - continue; - - if (block->tag >= lowtag && block->tag <= hightag) - Z_Free ( (byte *)block+sizeof(memblock_t)); + /* get link before freeing */ + + next = block->next; + + /* free block? */ + + if (block->tag == PU_FREE) continue; + + if (block->tag >= lowtag && block->tag <= hightag) + z_free((byte *)block + sizeof(memblock_t)); } } +/**************************************************************************** + * Name: z_dump_heap + * + * Description: + * Note: TFileDumpHeap( stdout ) ? + * + ****************************************************************************/ - -// -// Z_DumpHeap -// Note: TFileDumpHeap( stdout ) ? -// -void -Z_DumpHeap -( int lowtag, - int hightag ) +void z_dump_heap(int lowtag, int hightag) { - memblock_t* block; - - printf ("zone size: %i location: %p\n", - mainzone->size,mainzone); - - printf ("tag range: %i to %i\n", - lowtag, hightag); - - for (block = mainzone->blocklist.next ; ; block = block->next) + memblock_t *block; + + printf("zone size: %i location: %p\n", mainzone->size, mainzone); + + printf("tag range: %i to %i\n", lowtag, hightag); + + for (block = mainzone->blocklist.next; ; block = block->next) { - if (block->tag >= lowtag && block->tag <= hightag) - printf ("block:%p size:%7i user:%p tag:%3i\n", - block, block->size, block->user, block->tag); - - if (block->next == &mainzone->blocklist) - { - // all blocks have been hit - break; - } - - if ( (byte *)block + block->size != (byte *)block->next) - printf ("ERROR: block size does not touch the next block\n"); - - if ( block->next->prev != block) - printf ("ERROR: next block doesn't have proper back link\n"); - - if (block->tag == PU_FREE && block->next->tag == PU_FREE) - printf ("ERROR: two consecutive free blocks\n"); + if (block->tag >= lowtag && block->tag <= hightag) + printf("block:%p size:%7i user:%p tag:%3i\n", block, + block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + break; /* all blocks have been hit */ + } + + if ((byte *)block + block->size != (byte *)block->next) + printf("ERROR: block size does not touch the next block\n"); + + if (block->next->prev != block) + printf("ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + printf("ERROR: two consecutive free blocks\n"); } } +/**************************************************************************** + * Name: z_file_dump_heap + ****************************************************************************/ -// -// Z_FileDumpHeap -// -void Z_FileDumpHeap (FILE* f) +void z_file_dump_heap(FILE *f) { - memblock_t* block; - - fprintf (f,"zone size: %i location: %p\n",mainzone->size,mainzone); - - for (block = mainzone->blocklist.next ; ; block = block->next) + memblock_t *block; + + fprintf(f, "zone size: %i location: %p\n", mainzone->size, mainzone); + + for (block = mainzone->blocklist.next; ; block = block->next) { - fprintf (f,"block:%p size:%7i user:%p tag:%3i\n", - block, block->size, block->user, block->tag); - - if (block->next == &mainzone->blocklist) - { - // all blocks have been hit - break; - } - - if ( (byte *)block + block->size != (byte *)block->next) - fprintf (f,"ERROR: block size does not touch the next block\n"); - - if ( block->next->prev != block) - fprintf (f,"ERROR: next block doesn't have proper back link\n"); - - if (block->tag == PU_FREE && block->next->tag == PU_FREE) - fprintf (f,"ERROR: two consecutive free blocks\n"); + fprintf(f, "block:%p size:%7i user:%p tag:%3i\n", block, + block->size, block->user, block->tag); + + if (block->next == &mainzone->blocklist) + { + break; /* all blocks have been hit */ + } + + if ((byte *)block + block->size != (byte *)block->next) + fprintf(f, "ERROR: block size does not touch the next block\n"); + + if (block->next->prev != block) + fprintf(f, "ERROR: next block doesn't have proper back link\n"); + + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + fprintf(f, "ERROR: two consecutive free blocks\n"); } } +/**************************************************************************** + * Name: z_check_heap + ****************************************************************************/ - -// -// Z_CheckHeap -// -void Z_CheckHeap (void) +void z_check_heap(void) { - memblock_t* block; - - for (block = mainzone->blocklist.next ; ; block = block->next) + memblock_t *block; + + for (block = mainzone->blocklist.next; ; block = block->next) { - if (block->next == &mainzone->blocklist) - { - // all blocks have been hit - break; - } - - if ( (byte *)block + block->size != (byte *)block->next) - I_Error ("Z_CheckHeap: block size does not touch the next block\n"); - - if ( block->next->prev != block) - I_Error ("Z_CheckHeap: next block doesn't have proper back link\n"); - - if (block->tag == PU_FREE && block->next->tag == PU_FREE) - I_Error ("Z_CheckHeap: two consecutive free blocks\n"); - } -} + if (block->next == &mainzone->blocklist) + { + break; /* all blocks have been hit */ + } + + if ((byte *)block + block->size != (byte *)block->next) + i_error("z_check_heap: block size does not touch the next block\n"); + if (block->next->prev != block) + i_error("z_check_heap: next block doesn't have proper back link\n"); + if (block->tag == PU_FREE && block->next->tag == PU_FREE) + i_error("z_check_heap: two consecutive free blocks\n"); + } +} +/**************************************************************************** + * Name: z_change_tag2 + ****************************************************************************/ -// -// Z_ChangeTag -// -void Z_ChangeTag2(void *ptr, int tag, const char *file, int line) +void z_change_tag2(void *ptr, int tag, const char *file, int line) { - memblock_t* block; - - block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + memblock_t *block; + + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); - if (block->id != ZONEID) - I_Error("%s:%i: Z_ChangeTag: block without a ZONEID!", - file, line); + if (block->id != ZONEID) + i_error("%s:%i: z_change_tag: block without a ZONEID!", file, line); - if (tag >= PU_PURGELEVEL && block->user == NULL) - I_Error("%s:%i: Z_ChangeTag: an owner is required " - "for purgable blocks", file, line); + if (tag >= PU_PURGELEVEL && block->user == NULL) + i_error("%s:%i: z_change_tag: an owner is required " + "for purgeable blocks", + file, line); - block->tag = tag; + block->tag = tag; } -void Z_ChangeUser(void *ptr, void **user) +/**************************************************************************** + * Name: z_change_user + ****************************************************************************/ + +void z_change_user(void *ptr, void **user) { - memblock_t* block; + memblock_t *block; - block = (memblock_t *) ((byte *)ptr - sizeof(memblock_t)); + block = (memblock_t *)((byte *)ptr - sizeof(memblock_t)); - if (block->id != ZONEID) + if (block->id != ZONEID) { - I_Error("Z_ChangeUser: Tried to change user for invalid block!"); + i_error("z_change_user: Tried to change user for invalid block!"); } - block->user = user; - *user = ptr; + block->user = user; + *user = ptr; } +/**************************************************************************** + * Name: z_free_memory + ****************************************************************************/ - -// -// Z_FreeMemory -// -int Z_FreeMemory (void) +int z_free_memory(void) { - memblock_t* block; - int free; - - free = 0; - - for (block = mainzone->blocklist.next ; - block != &mainzone->blocklist; - block = block->next) + memblock_t *block; + int free; + + free = 0; + + for (block = mainzone->blocklist.next; block != &mainzone->blocklist; + block = block->next) { - if (block->tag == PU_FREE || block->tag >= PU_PURGELEVEL) - free += block->size; + if (block->tag == PU_FREE || block->tag >= PU_PURGELEVEL) + free += block->size; } - return free; + return free; } -unsigned int Z_ZoneSize(void) +/**************************************************************************** + * Name: z_zone_size + ****************************************************************************/ + +unsigned int z_zone_size(void) { - return mainzone->size; + return mainzone->size; } - diff --git a/games/NXDoom/src/z_zone.h b/games/NXDoom/src/z_zone.h index 22bd6264318..4df6bb3fb84 100644 --- a/games/NXDoom/src/z_zone.h +++ b/games/NXDoom/src/z_zone.h @@ -1,73 +1,89 @@ -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// -// DESCRIPTION: -// Zone Memory Allocation, perhaps NeXT ObjectiveC inspired. -// Remark: this was the only stuff that, according -// to John Carmack, might have been useful for -// Quake. -// - - +/**************************************************************************** + * apps/games/NXDoom/src/z_zone.h + * + * SPDX-License-Identifer: GPLv2 + * + * Copyright(C) 1993-1996 Id Software, Inc. + * Copyright(C) 2005-2014 Simon Howard + * + * 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. + * + * DESCRIPTION: + * Zone Memory Allocation, perhaps NeXT ObjectiveC inspired. + * + * Remark: this was the only stuff that, according to John Carmack, might + * have been useful for Quake. + * + ****************************************************************************/ #ifndef __Z_ZONE__ #define __Z_ZONE__ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include -// -// ZONE MEMORY -// PU - purge tags. +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This is used to get the local FILE:LINE info from CPP prior to really call + * the function in question. + */ + +#define z_change_tag(p, t) z_change_tag2((p), (t), __FILE__, __LINE__) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* ZONE MEMORY + * PU - purge tags. + */ enum { - PU_STATIC = 1, // static entire execution time - PU_SOUND, // static while playing - PU_MUSIC, // static while playing - PU_FREE, // a free block - PU_LEVEL, // static until level exited - PU_LEVSPEC, // a special thinker in a level - - // Tags >= PU_PURGELEVEL are purgable whenever needed. + PU_STATIC = 1, /* static entire execution time */ + PU_SOUND, /* static while playing */ + PU_MUSIC, /* static while playing */ + PU_FREE, /* a free block */ + PU_LEVEL, /* static until level exited */ + PU_LEVSPEC, /* a special thinker in a level */ + + /* Tags >= PU_PURGELEVEL are purgeable whenever needed. */ - PU_PURGELEVEL, - PU_CACHE, + PU_PURGELEVEL, + PU_CACHE, - // Total number of different tag types + /* Total number of different tag types */ - PU_NUM_TAGS + PU_NUM_TAGS }; - - -void Z_Init (void); -void* Z_Malloc (int size, int tag, void *ptr); -void Z_Free (void *ptr); -void Z_FreeTags (int lowtag, int hightag); -void Z_DumpHeap (int lowtag, int hightag); -void Z_FileDumpHeap (FILE *f); -void Z_CheckHeap (void); -void Z_ChangeTag2 (void *ptr, int tag, const char *file, int line); -void Z_ChangeUser(void *ptr, void **user); -int Z_FreeMemory (void); -unsigned int Z_ZoneSize(void); - -// -// This is used to get the local FILE:LINE info from CPP -// prior to really call the function in question. -// -#define Z_ChangeTag(p,t) \ - Z_ChangeTag2((p), (t), __FILE__, __LINE__) - - -#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void z_init(void); +void *z_malloc(int size, int tag, void *ptr); +void z_free(void *ptr); +void z_free_tags(int lowtag, int hightag); +void z_dump_heap(int lowtag, int hightag); +void z_file_dump_heap(FILE *f); +void z_check_heap(void); +void z_change_tag2(void *ptr, int tag, const char *file, int line); +void z_change_user(void *ptr, void **user); +int z_free_memory(void); +unsigned int z_zone_size(void); + +#endif /* __Z_ZONE__ */ diff --git a/games/NXDoom/textscreen/CMakeLists.txt b/games/NXDoom/textscreen/CMakeLists.txt deleted file mode 100644 index 7e33826d6df..00000000000 --- a/games/NXDoom/textscreen/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -add_library(textscreen STATIC - textscreen.h - txt_conditional.c txt_conditional.h - txt_checkbox.c txt_checkbox.h - txt_desktop.c txt_desktop.h - txt_dropdown.c txt_dropdown.h - txt_fileselect.c txt_fileselect.h - txt_gui.c txt_gui.h - txt_inputbox.c txt_inputbox.h - txt_io.c txt_io.h - txt_main.h - txt_button.c txt_button.h - txt_label.c txt_label.h - txt_radiobutton.c txt_radiobutton.h - txt_scrollpane.c txt_scrollpane.h - txt_separator.c txt_separator.h - txt_spinctrl.c txt_spinctrl.h - txt_sdl.c txt_sdl.h - txt_strut.c txt_strut.h - txt_table.c txt_table.h - txt_utf8.c txt_utf8.h - txt_widget.c txt_widget.h - txt_window.c txt_window.h - txt_window_action.c txt_window_action.h) -target_include_directories(textscreen - INTERFACE "." - PRIVATE "../src/") -if (DEFINED EMSCRIPTEN) - set_target_properties(textscreen PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") - set_target_properties(textscreen PROPERTIES LINK_FLAGS "-s USE_SDL=2") -else() - target_link_libraries(textscreen m SDL2::SDL2) -endif() diff --git a/games/NXDoom/textscreen/Doxyfile b/games/NXDoom/textscreen/Doxyfile deleted file mode 100644 index 84b607a04d5..00000000000 --- a/games/NXDoom/textscreen/Doxyfile +++ /dev/null @@ -1,2451 +0,0 @@ -# Doxyfile 1.8.13 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "libtextscreen" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = . - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = NO - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up -# to that level are automatically included in the table of contents, even if -# they do not have an id attribute. -# Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -TOC_INCLUDE_HEADINGS = 0 - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = YES - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = YES - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = . - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. - -FILE_PATTERNS = *.h - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = NO - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse-libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = NO - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /

}gSyi^VFmA%vEh7VMWN_lTT<&2Mrx zTg`2`S4K1uVlLMYOy%;OPx@;4;PnpxK8QzK6kil&QHaE* z-kzMC4Et_q_sld@s3oPgZG2JWXZl_L`d4oD?JxbxCx^@b;lKWWeDl}-v)}YDeer>O zaE9GF=iy3+KMB_bak$b1l@ikQ>MtH>l0wQnj;IiWlhBJt`-(Frk zeX>|AilVr9{0ReN_8roM$Q2bLNDOToHoIN1Z=5@?s^wyRuianf5{0RGpU2BeMBje< z?ZSKSI3|fn3ZDq!?9uy)Ikk5sQeR2aJN0pG- zemOQk>KaQKr_`~H2#I-O<}&zLW;4w3r0q}`4CXCD?cb#tFNZxpSLBfTgF}1o=DX8B zR@F37jICR-a0tZRUegq=bgf#vkM3vk;{f>pT+p5_)nYI_aLHo{3pKcYd`#f z2h*GS*Z$W3{TKfGp9xW3B(%RND|&(Vzsl)}ulOGxzQ%zu|2O7#W4;Bd8NF;r1qQHe zPcI$$6_K-aXH-11H$@B?g2R=M@wiOd&au#XJpZ3)PDY@E2?ZO@NVvUhKG_n z2WvgV7>RJTT2|G<6;;lG%Bq4snaFc4Bh$L-FtMZ{DR?3TmK1Umv9t2)_9SHIi6{f@ zV^kNDa1aT-=uF>)*QAyyO5BOwnx@#ss8v<=vE$g*o$biM;22^WoK}fvxeFwSp)phM%Uo*DF5l2w7y^LAXeLFq z#Ln#xh{cz*Jau`oAxmbG`N(;TB4SmEZ7m|1#dUh`UZ#s=pNhrmB-@Ca>d9$E#8tIW zmHk_vN-1r(TS7ntN(qs2ekr1AhP2CO!T`{=k(eBF2qEie0~k_+n8QG$zSCo7F(xw= zwU}a;x2eU@0-|$%m`J8Noj)ofDdZ(`QTp%u_TT>}|BIh^e7+st@U#EVM?dw>#rOTO zk9_#_zD+Bt*_l!my2$i)Rg>uxw8K7q#sZ9PO?J1HkVffDq$%xvO7zb0$Jn09JC@yX ztwZCRPuKgRsw(e`Ub0I=2mt6kJ0erDzBKL~13*k#ikPO9l9{HI)XX~;RZUSQJ zgbZLsQ8?!^OkG3~ky0e**m<*C-l(2Kg_vtGrgR)689-)kyt|nOb<5G-p2M;j4@-W+17m7Wqy|ig~x{Ow4nf zN|fgSyMi60IH}=`W<$VSAZEEijY)ipF0qWcd3ORT$qZ78&S6*QFiSC{)Gk){5V38# z7A_Iz@YVSuNfTnq4=95;x>5-{=Uf*6#}>f6&-NFYN@&F17iH!-_;PWCNIJ??j=I@q zhM@)k=S!8;)*F%T$sgSN^}XfvM_(?g@mf#BQ-ZO)k&yu4>}2sh-}==*@ZbK_)64yE z@Q;4t$$#*l|JCpP&TsnXzv#F3Gj`nD?DiYs_09l@gxJ;1a1@-o%QiTHKV*4poe=Cs zqW4sn#6)}O=AHA9=Wm3I#e$sAyk0N}A&BT|S>&)L&s;+Ej$_i8L?r7PB{j`sgF2nH zWTxJ+V|LE5sWN6I8copEWTs>on{fWVHVi3Sjw+EPS>yb&VO^5niqify+M z#!#miigJmFMOh#cSTMts1koe~XB9ht=U%d1nT5S4&1u9Vf=6~(>uO!}0-=z}9lm}l zpq=Rx8X7ZWcGe@di8*sevNcNPL(j{(Sq_s%So~zF_oV3w{rp9W(KBR6wjPIBQERA2 z&1$W9R~eqWR7`saM5kV8mTlJicnj4Au1S~tN!|pmiNE?9pdCO+j$tL!l3@Qf>Lc%w zz|cW*G(#D=e^9y2hJ!3z?#WNSE0^qyhzv|}LVx?adVnJ_5K)og(va9WS1>#33&n$i z+LT(LA}PicV~jDM-V{5KJ9$INH1{t}HT&gug{uBRiAWYXRh9nRaQfAmD9hPGd_1eJ z3Oz9yN1lJM`+v^$D`e_QSmTig%8|{W5A#P%)6o0%2kYGV@*C?%O~4=l{DO z{_($=l3cq;+10KZw|;8<5@hhwqLkPCbY(;2R;Oyu`G34sDa=$wB!4I?$4-n_x|u>* z!)e^syUqmDKtbwFUyrBf*alLdDei3Id^y%~p=VDV^ngd}%@KVz>p#F?a6c`#zRKbu zUQvI(^9x?&-(5a3LB_!qR-(5%NdQniey06Oa;-i=e&X)r-u+><%@XRN*%#Gvu{;gU zF1B@1EzDqhaUMc@@9h2*P&Xh6O%#ph|Mm>Sl3NiRz+E|^Tb{|nP~%n z7=;;}H&ESfH)U1bzkff*HpP(Bp!Kpev+P#?^vM(N{d&F5Qk+>$-}_>Ha&NcWUS3?B zot+V}nf8i+H*s205>+jVt}q)@+&p^*0E@!2bKd*a*=y^w*W3MNZ1=eqmlNL%Ad;@X zh|O->H2ah^BsqKVV7)qNb{EiL(<#(D1CtnX6+vRGx0gA6lo%w%a(RNC;wxS}eeBp} zw(^6sdtFW6m+VV0HPbxOm|d>y594#yhw!%FhqzxY7iHm!#YvY#fDwBnWLKz&zWK4$ z>DkHsNBIQuW?b(sOto!mGut$c|jOTtQZNFtd~bfaU^bhI%<)h$NJ5I>b2ns=gXY*~2cdftMm078sH zM9vWr53H@bCji&XWna7!)i8q>>SEsAhHt?Bh@_O&VsDWQQ@(rzXm^{??22mHF{yI6 zp_Zh9o+4$vV#5^FBQcmM*>jU z8JNwf^+zgV(;oiBM;>5IAg0;hh&D2tTb;u+ghHYt@4G3Zz^2{3!-v-4YX;x+o5Jwt zk4T*36b2H=X#UnGes;+5#~JZqNURQc5Ol;$?tuwo&^?J1d-+nF;%cTc|5swWCWxF_ zwmY$|({k?zWtM9E38HB(5s~`WaKlLL&_lv)JaQU-Q z+1-Tq7-;Znku{V5pPTv3eB)j?RUK8KbLC_h9YZf>#4%>VIvhS+JTM*vJa`K8;WUMM zO-4}fgV9$?4tx+{LixdYdPX?YGlq8!b!e~R--}We4sTob z!2j{jf9LR1iZOeIcRm1py()gX*SF$f2f9eyea(a5k zj(xf8!K!lp_|4_&bai@vb9uhKyihYy^Gt|Pm7WO8YCV8QW2n1EjF^ZyM|}*0MNws8 zBt#4?6*TBS|lJG*y6nLc5% zSlveiB39Llr;m%OEXxXP3}|Aghi&uZ{`*pFHy7us8j~29h^SHkQgze($isD zU_kC=Pa}mU#U{3UiQ%0mPgQlf@Q&$X(>SK(qUajxMOl>V?dEc`xm+z5rOyta5JMv( z>$BH1rP%I8^!#E|cy^q*OC+Kx$-M`!5s{=|syVlCzBB-dK_#ZPVPCQ@oG;n=e3hD# z0o0dIh?t8--t#t_%kw8soFgU@(WJU4JR-C)iCW>ZYz6^>s+`<=bpQ1ah{P9iDY$M? zJzkkV17CNMSyf4rQeMpSo+2qsTT#rOT%i&VR9RfPzys+7JjDDQR=00RFAfEBujVu2 z^-m7x|Bc1sqf;8?iY5fxYZ1NkRC+jpE;PGRJbi?8!(7OB>T!m%z)mN6T{g;+^*nLJ zx!P9m@Cv0*o9Mc)~D*h?7O(0b{$#d|5Lx$N~2ljBtd zf-X7kJsBoK!_%;_PZXwd0Fy)7wUOy0f4x2kwA{t-P6Ycbm3j`#kb&VuNp6<2+Ci0I z(B(SHg2$U}@WI#5{^RfX`jgca+rUr!?O*ugfBHv0`WtV(8q@+@iDk$4N;i4nMI7J% zSAy~%>qE2P-{#-m3%L)4r}0r{BKw5iK3T2oh?{@K2!m0PVbo~@JAkH4Sv*%QlQxl0 z9HF`J89+sQPhWSs8&@>25Br5zbPxM)bMs}8R8nkqFtOnt1rhq?kBDuqb~a$AksS8> zO%^`Rv(fn~g*LR?YIUz#-P>P2t+$ueay=B6Lc3?@s^vWZOQD8=s7FM^NF=dU1C`An zDv{NfxM%+6D=Nw*`=aM-UlBdAFRJyuX19rT<8i^hkhnE7)0D4HQo49{ZU8B!YEiA0 zs}R}@qlez@D5F32o2P0fNf2?dTuo! zJUcTpSguxxC@I(kK$Xe$-m`b?i=tvL5)Yavx!DO|#Pr&u2fkbs)vB#G?SAXc9AH~- z0iaslL#7+n(q^}7_S=W=`z&G(O|2?nzj1}ndwU9vnMz9RJh5w=oup7M)&SVlyOh#u zwa&H`nb)D3Bn2WW%aSNDCFdLfwoRiV_a44Jt*H{TFBhgd;A~ZMX4$#DBO*KBrHPV4 zvnTfKT!u1j_pPa}fS7qob1cebej=G69NN}#*lhQ`Gl!Mc$_!MZsMc*VXc0Qd4m%>8 z2~F%SpCHm=xylrywrO^|Ei)6l5ZV~EX)ggFiKyD?y2?GLH|{UK?~i=-fBK_8z1bb+ zg}?FUlkfh4zw~eZYhU$^U;CvmgAvP^Mm>;|&0azWF5bt1_f>KkcUZWHg-AOUJrxzr z+hRr`U8@ps>wU1l?DTA>f|u!DwUSJ$8O9kJKTp6MH9!$qURUeL^v_3FDfE|+*T1~Mnt%%sbN zW|eCroPz?goeB*>puu6sD&s+t2(b(&X{Jd8fw-ghS?;6>!U4po(|LlKh5dDx*75y2 zQ&S!2`PVBZ&7Ql8kjq5iK#F1J(m4rwJ3?Jow^Y$dRi__1{X>|_Pv_gN^ZE9%H_xL! zTP&BI%uRN_(F6b@24?Jth+R>FLEG#(ix)8G(mDcOTwa*kqAGF)b>hc6t2L#VB*l<) z@ZY-kc-KdJcDdOWK3h4OsS(rh3e&szBD0I3-Pd(hRb^R)woWl-JNx{+R?A}Aeg1}j z@pu2#pZvKip-KPskN?!q|KhLyhu{7U56@0svO;=Y-R!2e%qv^_Y%Z;SU^ZwkdFiAQ~G>|0WH{Rwn51Jj}Sm8BLC##NA=E2<@$g=R}c<#L@V-r1kCsFsM- z$vSt#lTwN)w%!+P4i3<&2!zz{pkswiQpni-VO}u%;q*>V?>R@!?jnRnwPOPu;9rQS zsulo7ZNr2q1p_5QW>3r^G{e5jTp;SC{Z7n9=7{AFi7F9Qg#!ao zrOEbYY9bcf77z&00G7)I5i*mh1!u zH_V*#)pB+D>>LpY6u^pdLChK3DJcMesE@^Z8MG(cv>l#ec8kPGx55`y&#%q8E<}#IB}i4xBsLwX z%Av~zJsfEGlj%1^!PniRsS8QZ5I_K+&i|LEip#{VAkL*%az(jZYf7Ccj#*JwW+FXt zf{@4;A+&8%<6(PmjLzW*Y@J~~)7zDq0~zIUdhcEgO|!cYH4*KI1oKUvh^oZ`01y)N z6<}uag?B|&*R^Vw(y;TWq9)jRJW_T=FtbeN&0gzOSvl`RQ|Gd3X67+d>0L+?qaxW5 zP-YHN2rVLJH@n4RnXfuX8`^fUT>GM$)_!;Uy7Z|me0TZmIHg=mj7`%t&7$(R;VL=r zn3s*FRud1XJI*E2dVu!hMBniNndFZxv04PbBl-E0vA|j@VV1G8U zhgWKN_8I-!?3zFGL;ut7|MGw4JOA*%oDnqBLYBRX74cnV=$hHU-yn9x?~1>vDu|f( zl$!`Dsj4b7jiJqjbZA24FsOABrpP`6p6X2s-cm2pcwZqZ5T%lGklk# zqW35V9M}91n|(j_Mym?v%W(!t%;q+Oa!@8-0RX!K(7B_VhDQ~ZD_wwZtjSEkCgYNRY9KHexD)5?Giw}X|0-fe0Ok%}F$fHrsrKgSdcaHQ^R@$!(81kR%beoT zBHJ+&b3W$@{It*jp*-E6&lRJ4`gMK*o)J@i%v>ZeRD+tdMsV1AfNy z87U3De}GPDF#QDeq*CkHbvd=j@QCg>*rlzigSLqo zfQka;%*-b8wy3JV<@^Y*k;1v{P@I2ckeNN$!Dc__?pt3YJUET4&FKID2S-*FID#1F zGGi7n>~@_AQ{Geu4L9p`@W^>)m*rR_g`Uuw?JUNF57`4`AAr8sNbK@Qyf6H{B6ILl z4`fF`o!H&^#k$#Vcbm&s@3bOGXQIM7ZO9YIvb+|gw4gXciwsY@U{2d zKYK0TpU~`8Wpn<{ez!?#7Gu4AW@e%$AvJBx`;VxanRj(3%zaIsq-sgDy}V3G9zA-< zgekVF>5cb)5E0pzs_F9LoH%gc>`GV`)pEHcS0Iurie4+y4gkc&%$>ljltmT@?ImgY z`gmEbVvJ3_Cu$KuBxy>ElY0PI@3tw$U42;;#r^yD5iz^Hn~JKaq!44>#%1XdF~lTh zO?%EvtA#fMz<<&sfq(k*KKLJf`$yh*?dd*02@)aG92`rxzVoQER?3>6vP zoJBLHpGq<0@%BP%X9($X+bkDFS@2ZYC$u~2ng#moatGKDL02VX_SLf4oM*Wr0O-x@ zTT?3vR)v%_#x3l&*@I$Q5Bt#Pex9b3QUJ4}#G+glt5XS$q_Epww)I}r%pmO=Ra-3z zGuiDM0Pv2IScoah`(;0w&GyOgL=n+@?|lWP+s)+)uw0(Z3IG#y#c|yK+<`H?=Rn!& zmY;f86GV3ISWfSFMY{Imz8JR56xs}EkQjPHjLtJP=R52R0P9T$872VFtkoAo1O0a9 z<{2M8KM{RS7JlH;e$`RzfCGS?7x*-soaBXe2%fjuDckr?IP8wXK+x_X%QSny6Dj;Y zEjuLUPyOgRZ~D%O&|p*)F9$6mt7Vp@FF|$D2 zW^vE$kuoqw%j3i9nGq9I_`nX%$@)};Z!StOBO0p?QnU!5rbFuZEnok|qGJR2^z>x8 zT!m(DW+^2z+c&{ET2_UbZFUWI@LhIH)nZwei_PUTGxgphVzoN8UUd8L8b#DpG<6Ey zqWA7U?9As>Hy7tcQ5I#DRg&3xX20L<0IaMQ%)H%PI_Ju20cJ7OAxYDwyM=zaAI|KOAV)&KC*SI=#tf8!5)`8R*vmod?2=q~=EN#0%7SA-)0 z4C^6uS7#eIP<_az;eY2&qP%Kl%?P=UK6l#dovm}qAlLL_f-^N8qtp^{Pz z9m&CYB2F1gqGD#9gL(J4gvedvkXd6;Nk|Nx*p+6b@57~eSW{K6RRuF6=PC0FQk;&z zw%&;(LUcuS^5A`Duz&VArr6fC^WJ+`RO@1~{P@RyO;sK|d{ma@_Tn+IE6Syrwe`lA zi?UjWb|2e%BJP5|sEAx!Z+b)kFHasI0ufzYJiB=IY*`gW!Ff`Z)ry?2x99ANYI&-v z@4Wq{%U$xWh6-j-lnX?1z9i-+Z@*~TTckWI$wBTz3z1)F0bj3T-AZgb+mJ;p^|0l-ha=h}H5m zhB`F6{E@neAr5X$sH$J^yT3Rz_2%hYX5h=pmy2?-R!O2#lvO4_sOrZ*_N)8NTDZ%zeS2@a!0yHW@(a9Z`o$Z9_uD zMLB92BR~+1QI?elzz~zDE=!Mu%me@_b>-_^Em%~(@Gd1WgM6Q36vV9VKxMhAn|ia^ zu2-w&YMDZtQpVV#D=H@b)LW0e&9KZHodV%2|_NDL}s63G`xom*v`fZ}O8|^};3Dzt}x;ApW;Y)if>gz`m zPIJb2{n!R5$JGBCM`|$6#|4gbdK`7yru^~_E=xqjHc`=@OL)QPel!L;LvIi#71!C7 zPx%;wMtKi$8WYwRF0R?EJv?(Z8TH?0ssLR`JI&LzC-NWh>N^xWj8x*WO=5kDja^^I zdQ#1hRBP`DHXEJY5h#0!n$5TXQ#gB~!~V z;zuxDat0N|>A{9UW@;IFYSTe<2z%&23oy3zvr6+U-8`0R>peBEYK7%NKZ-P7bLPOlCTp&9-Bsnm<_Lovms^x?uZirQwg{0mhpV#f!Zi3fh3%ixic%VsFr;v5<{~C zz;bayp#ift#O;22MnzFBog)4YKGLE z1|x)aUli_P`M{T@FRIJSjjF^n$SRK3IVsdBwmA`WMMchMA9nUW^E3=hQpz@a-SZ+s zBvnZ9Uz>RtJv)7-NowUVYyt# zw$>DO^`)v}3kFaXPDJZA0)VT7sP^2S8HFyzHpO;Pc_RFk-+1TG{n*dMbSRy5vZ}uO zTfXl1eBp=5plcACap&Xr|VW|1ICK~u=GM_I=DL!bNkv8`jXC33xb5vUTR+LKsKxQ**>MgT-^zcE`G?&|Ewc-V5rEFkdF#EQzl)wSm z8H~O6+QH=XSwYz?dt;e93nHjoc8##^wm;g*7uJC z2GdQVqg&KW4qC5v5XacT4s16S)a^Ef;M=99U1X1QsAUE^4hWIF>E_g?57WjdvFrLB zIJwWQk%lbLzyK79P;Fu!-+9wf=ecTQsyX+WAw)gUMC$_CZbUINj*zv^(VY;otxzv6 z3|As)%?wPi4`TBBdyNFVwx@!fKJhf>91JncOj5%Bx{SK}LW5pfCr@l+xHt9fQZ?)f z=Dl!?45rbYgVh8+*Jas#%FE2AdN3e~h@CS@D7m)TFYZL0A0u|o@-XPS5dknE0Rj<% z5wp*S${hJb*;SaF^Adw0%@BT>Wvylair20?*58?5`{enb{mVbyhC?rfFZgXA_}+i} z51gG;qd&~m)5G2^W7X^HI=3m7+SOUj-J3lVdB$U7@tI6VU;ohKZ_WFMq_(@II1%H> zj~mcb4Lg+#RUvZ|-G_;%(yY~uLlq&@;SbC>pDXXzRZ{=~ZK5v-!$j_{ZYmvp)dR}r zP@h3bp}o`!|NO+RGd@Z%wH)sxh_BkY1}6k!zyy61+hGo-@$BG4cu;~GN=Add1#|)m z*e#%--7-oY)hrLY*=mTR!*yT&($UoG`WcwB;HkU8prV-XMW>}Q0c%WDUPk5vnC>?h zfI!Se;i1z@n{5lRZHG9b4Jlu`nKGlOhN#)VGkX=K{XXx0h{!H$=HgJRaZGL74(3Fo#F1~9a#ET+tT?1&sh&ikRRtI{QTc@o7Kl8B_lE-SDQ zjFevMonOdcCbNV9Ng^1;B$8x(ateq@-pqVcONyaw7R%LQx!P|xR_~|#Xbg>+NeT!! z=%w}gFW8SOb}PWNIDP%AU;BH$^$&hIbEb|#u95U4^p^t5TnBUL zks8UikMkU;v5uZCyAbA(ei_CnYmz145KED34=oTS?lq(M+T4>DJuYE;q$l33wDP7;kH4F&zd~2VbPmvw+5- zw{pZFzhN^Q(vMM*^~SOE3h`O7-l+-@85pPyYR1FL-|=HqY*tOw%vL9M5E?McZGUHj ztporJT!>@g=5Do>gSaxwG=mP_5j5OE>uTuI?A zri#Es+1~7G>p?_Ba%#HUUY1o=mJ9D8JGUOZIrP33c_W10?Td&)jBQATkJN317E;|+ zcM;1XY9^m_zaeG|ApigqB4Qgv4Hs21vlxY$nUI<0DJZ6-2ioPiu-40GSa#$kMBpsr zN!eX5ga#3eeZEyO#-?f12Vz{V?<0>A%m_G$jvnS5h@EqrNKC0*tNFvBF+t01yGlF@bSPftZ~ZdB!4UgAvV{x}@wP zoi{?t5KvzfW}VbPUMBJeIkkf8yHXr~DG_OwrZo{U5oKR^_L4Sc*;(3}HWmsCNm(rxdhQk?woS9E z>t*QyQB46*B&b?SnwJ75%Zd<86k}?d);os?G3@~$CP7pul7lBv9qv#Jt!mwdXa*3{ z?KcVQB@7Q6?zb_iz(W?6si+9upu;|_y=FJ$w^y&vN2A5wWdR2;ZR<@o-sz+njjsI0 zgF%%c<;0Ge`&^%qC`+szxG8oNa=Za6Jf)jV5&X|D^BxL>4`qP4xdhx;UhN^JS1~2~ zlJTrRo8N)6a$r}A%mjt5e$mqfw4d-u)DI3E%;<;+z?k}sv-@4=YmP)jMmDX1%rg7l zqOU8%bU}vd+*9wkHjamW0#}U4p%BPK4Ad7xZxOZJZ*N4m|+3}=woc{>io0m@y4UgMzM`eF)ylSnl+Yl>^2%+!+_YF zGbPy}(R3tnmn7Lx1|)W!)Qf70?aBINxX(q|owKUO_)bw&)nXk(onp&G-ceC5h^S)D z$Wn>v^6~XxuPtWYhQ26dY4k0VpQ!#;BE}qtJP_>JON}gwa1?f zO%2GZY4_~0fq^NAc<&^&yUQmM+T&@1$i67RY&W+!F_YN{eJg$5Csy>mrVZwGY67<;M?4_zhYUzllZ5s`dZnOSJ|-~fqI4A$29 z{I1-eJD-HC`3Hw>s`Yxs&TTHAL9Z6Fy?6%zPS+K4!Oo`?B!+5n^5kOor~l&LczUs) z9^uQr@I(L3ANtCB_fM}|-Q0vGe1}BvmS~roKRz?ndWmDcC>BFf5=aLCA2{N7=inyA zCbavrN1ug6v8`3*bX^f~-l1Z%>uZt*i1mJ3@3+%r<&F1$U}!}T7^N7R6dER|3U~JK zbwsMS=P8DAaS8}TEF#Ddm(K2u? z0MKl3sONr3F94v~J`)MK^qol*MYYQ2f{26}V}%%F3)U%D9})j@2%8|8L>p2aH9^Vr z3A+VO$IOncBwirCxXP1ywl>@K2_#OFxaXK#+m#2wu~0t8WWWgg8_#G$V4r%6*|44V z4poy}W$5pr;dJ92tilk5CW8ITFBOnZfMJBFtDDxGFQgVXWf8Sj$=b)RJ+U;v66|=6UNR zU73sFVQ1XfJ(+yU05Bia>_?_SQRlmzSzREAHzXR_nhs-8>8My|{USEiGa506HZ3J695?O9S>E9va=};0u1GmXrqryh z)BR{O2Twcz7`}8Cj_*Y(|1L#GGqBR+dG*LA>-}AaR1xjS2@{`FjGT!`M<3el{vOFW=L)N+Oq>D{72{*`EAnyvvZ+6^^GI|$9z=wh0d%w3kn_#< z20(}76Nn6_M?^P;fvAryBAM28yT2FaVK^4TJ%|EChJ!n`y+D(K<}gT5gidyhz?B0GHt=ZJLB5GJSuVEee6g0&;OhM z;TPXL%pW5L_aFT`f9+rROTQ^1q1ncEt1lGGy`Zu-3})68+fUR+XlLGL)AZXRc@?%G z@0U?F_=U;ommK;Ro_1Fct@AA+1o|?)Ehx{pc;As-~fzqsnY*!ptT|`7pNl^2zxR&6&BA6 ztRhd(Je;ZGKhA&C+0eMwP}X(}%UM!y1zNd6&z~9ahnbCi2T*Ww=Rm|izH@-fV2mm7 zpmHiX$CayR^&?29u6OZ^e+AI<^a-TkLa>ACeHvMa+7_W*}bplgtIm?r^)5} zqDYyh?aK}!EX;3y{{N^NwxocloH-3?JgGu#_s;uY{^A!ghTGd)6@^1@h+NADZw!#JE&jjuJ6SR4RYp5im7*@x!v%?gNp8UTgzk@;r?_40PkJOxgYX=zu)a|-oJfw zI-M-SJH|i=?e@`{Uz;%g)!4$G#WNT|W+E zjt$JFqs|9W;XESJW`95Qr|x)Y+D+4La!xsoF-BF*+%pJsA_JRMIcFtB=TL}9PW^B? z_RWTgG>?NwKAn!%=poYn=CuH9_Pphs*g8Vq-3V^RxiT zwfj2&6yZE}oW_^zFy1>6WftbtKlcCS-}#?^=jY$fFZj)0{p>&aTmRCl{q}S`AY!}O ze(!nU$1s(3iS7K7Y;|?ID6Al#=pg*woxz7y{Pr*7&>tV)HEkP0yuZ6u)ie&{n7;h- zO8_83W_f(-c6-`4o^wt^=R@OS+aDiP)hzXy6OoI}1^{wO-bWW396JE1`Tu?2sVwD} zD#YML^y$z~pLm=<`R&a%I33=HxQUya zPjOR>MhjQ={SQ=E0%tnOkCB;Q;^lqymvK!HK!o$q+jvEpne$v~%u9U=$|WQ;CDpB2 zc$cQ2yugLV0wbYFrwN?{)yP}ZHCatc&b!cX9?hE@0sXb^iSPp6vtkp~WP$|6*yZ}g zEo?pOKM+u9ib5$d(B&LDLroB1Emnm!Z|FPSfb&|iB(P^A*{?A;J3A4{naUoKbhhoe z28dRW(QNmvwzJaHFA}={K4I09QnWcZ~vEn_>bSr zzw;OW$)EgZ|NdVm9j1&P`a?Z+@FkO#?+z*cF~E-I#3CY^nU&7DrL57}pLnL-krq-Y zO&z&T`(^=CRuhO)F4V;40#k{o)PnbF4zz{zm&d_6 z%e`-eWwULOD8yD+j*sui4vb2xsv_pLK;&Ri5bHSh#tbx0G1~`oy`AeeIaAdvf`B2U z=^0a1O<5FxK<1&WsS=q55C|cs#G;ZCq#R@Pp~S^8W+A>jds62A`oH^M|NifOJ^#)> z_ZNTtKmMElS`1<6hw3vAvN6*<-V1-`JfP)A#TeT+u5SlF^`PiyR-yM-W zsMu;Ha)4x6Zy|)4u_BypGzAKxWUDT=n-H6vMg;I7l58K5 z!6ItxigD;c!NbR6uzpOMRJE3b`9(GkD*B9_%}b}P7wY>f+#+GKWwAotmK-{F>D*e& zDyDp0sYpoHw^`Xzb^`!xHv4H)DKrA+!M+r80)>^cU!k=WktwZ#H$9t73SVpuwqhoc z1E)d3X$@xjlvw*8Q?Q{TYvdYp! zl)glaDFX=Pl!cikHa;{PI|#?j!o1-u2)pfex-;4|A%^HfL*$)AJJCaI0gGX|s(O#x z?eXQ0cil^_0DZDrr{uQ2X!5DgAFSWs4)<(X zs4A*hsIdSLfvP(XS6YMiXXB#f#Fc5T1OUQFwAs88PIDASPJ^V;g#dt(ldAgfQkk8h z_g7&_J&Od>TH9WcAFk?_iXGZC_nSK32^hy`|LQUr)CrlMskbx3#Dw5>xohlD1y^cL ztr#j52YRABhzhFt6$zF|V+GX(n^|c0v%99il^pg-)JOz2@+89Il&Qt1q#Dglq;Q)N zp{}N;qDoUWAd7pzVwf&hN6Y2fki&%=K=pdcc{DFznQV$og-H%YlZaTqG7GtiI{{J^ z9KoEk^=kInih`3F5CuU*%!gnWJs>M+MkMvvDkqc5Yvl?Hi$8$^z`y*LfAfF)d;i#yCH}_0 z`WOD~f8(#7%~r8;vV8g0U(=aZMfc^y_d|^QU)+y9-LC1}O0G7NJfB@pImO}?zD z`V_Yq*OW&1J~1Lcq8IM$0}4opGLcvHJYrB3aNY}7RwIifrmTwUtN~mTu5?a=fZ6)d zJSvNpbK1@44OE4J{M6(*7ozQL0II@3=X0Kde=hT!rB#}?NKp|N;{1bFeC4qRkUVq% zK+Y4=W_M?Y5jpdcznKMpmSAAaU{y`y*qw@at8F(vgyNqhtRl^3r=rY>nZNnwP20rn zCRlIAISFU;le7ys4krM}nE@~aCz8`p7j85hA62FAx}5Xf{k<@cV~>c<=5`);BLMT5 zM|XO9Tbl8;%4Jq}m`47xhO%1K#xekynTMeO$U~CJ&Kq(XR7O>B-W#K`@16_-iS0JF zJL}PpkKd|FYAx!ooLKsV$Kx)}Y< z{TDZ{zIy!j_fHRRHaD-3NJSK&dwSoMDJl zKjAGQZ+@O_&@!=J*yP?ndLLMgY6#sY06102`?J)0%Udw|+XsHs5e4ro#w4Xdg#nS7 zPu(Mt`|_)w7$8R}tM(zbO}kZiuOd0iNoLMTpJ{+>4*>;RbvX|v`Ub@9en;pIk8cog(|90ink_m1fg&TnfW7rYhTp}N zLKWB1A0ImZzRRjx_c?3FtST+p^gP}qMibFh(#YdL-UFcXj>z>xheRZ-3d$KAAv*Kx zK*?6M7Y|McmUV>WjB!cM2j}z9jYAjPt>2ZN-Zw2E`H!FaXI)_(4SyXfxZ;R*;WrPp zDC6qlKj)`>n8`jXJr*H6!s6Sd&uFyIZ`o8~UkOT_gXw1TwOaLYQJPmwjSpU%OIH0H zU3OM3t$Nwz&*zUvc*c`{HXh-FG!VOt#s^;5Ksv=f7JnnHT2vd;7M9IiwwJG8T*#JM z-UtfS0I_n$I{VHQ#Xz)5D6BX()!=4kB2;oTsf`ipputI|TIWNqBMs|DaQUlX&0vCm z<)8U8zx7Xi_R}x!sdhgj^L`5zj&hSl7)yW0o6)AVWcmt^%u0P!7^9F#T@dF z!><&O_giV}EmVhZR+UkXq;T>@y>BP8S;)D5#mk&0A*9V@{(F%~XqN8V3<>H(2eq zx@p^+o5o%oW9xi4JUtq`p{jSE{WOik!`p8FG=x=U!#QzI&1OFz)S=mki1CJnGpFG= z_C$_+NW&?QLwb5ZbU*tuf40H76=c3Ny4LVtLla<=Q1hc2a_)5v*LHC{s)PEWHd&++{mL~_n40OwR^Sf{Z| z^yJ(b6Xa48a@G$y zM`03-_Cro7ef5)H73NJIRps&RFGFlYvmH}9_G4(bNUmvj06;z>QXWcPiijMZ9?jGO ziHuB7`2Z#OaD*gt@=vu;%W_iY$2Y%UOy&@gD35&}I@`DVhc_bZ z;k%>;;)gWrxH^VkR5erw{DhZG`9onH1CNA@ z({90YW;gDoC7AGu1?km!q>i;s-5mVBKqfeMvU;ToKlhH(#m#NDiJI3rkxZK7x;0t) zEv;0>b)SeZWy%}+A{TJZ;_Nn;lJ#|(>o`=@y5f8}zEF9zEyEIoXIJBrEqP&^hKmQl z1ct7v+x6APv(kUM)}?FFQaCO?zZ1#jvh11gY5a)G>y>r;$NHCE!<#4XY`pj)leg5h zuXfgg;AMY&mddF`;G~yr^1>ykox`XRtYle`_0u&6<5V7C^>?5Bv)1DS zte)FB@l&Uepm}Ztf6}7o@kf0bO!h1bV7dqvmWb0y)QRu`7nkS3%qp>9IiZ%QdSBNC z!r3?i29_YwJUgAe%@&DSPEc*DFhkG?dF;V}t_h4K=L^LE5z&FFR3=aQ+&7sC+!WS? z)g__6MDYn5_8=lGW3i754FVc~gorBI_r1x|hyK)`O2fBpJyN{6{~|W+@BYJo&~7%L z-Q9`E!^2}_;5??xmc|0AZ{NM2AEM^;$fC2`mMRz-2UMNQM3|=Bmg(5bZcOE*5oHk* z0K~wKaJ$>tW1+YTLqUYhnR^qD<1h?e-&?j+h^@u25yE!61H{;Ft$*#h{_VSm-EPyw zh|W*4cjR%HA$n`F=iR~iNaS5k05BZi=l(Fymo1eyk3;wP)`jRplQXBpL;*l^8j*8> z95@wmJ!IxY=nQ6?cbvjALgTx*f)B0DBM>2vgF5F!Tlkjq70!v7Q)2JE_Z}3OlMgKb zNY27c>-Aid%F;Nfo_uIcq@gO!_GTtQIPdc~4#Uy=;9Nj*L^KSYs@ioPhi*P(hv8`Z zTa0nD{o;5yoVsqmZHREQ-4xh6=cmH~AjA8&oBi#Lv1iXfuSv&p4XhId!HLTB!#6MI zt=wiK0bRa;b9(vPRe)vrD&XQ}c|zo;-&D}Bez?V+Zp&`d;*6~4-6sGdJUu=>Jaw-> z|LU{byFB(PisXb@auVio=u931l)caPbUZyiK0Q9&?l*||{^2pD^c%nR=L*$cq1oSA zg`&(N%xN6@@%8K1cIjuvixqd?tP0N=A8W)^i|jr->QR& zERfHf69A_u$7+^oK%=Vq5M5|;>NzF*`OW^mPN-iOSTD2TzVh!gO|e#$ev}#Y9Gdm~ z=Q#ICsGY;6Kf{Z_>*YhqBtTH`!JJVXxnS}WM8cBEC?Y5#vq1w-wl9W2s4O9BcB+-j zAOe8)FcGc_PAG0WMQJNVYKfplDNwsG;}yWPW(=b#oF>kZiAfYq{Wd8z=N8TaWUfLY zH3(X+4>B0}l&F~Mfr_?uEH!969EBTH{gqhv()Zg)x2&BF2~Y{<5Z%Rluu?A{dnj5>?ZLkjIr>?eh0ix z7r^IVpg1FGaD`#M!tww>MG?vSz-a^$OE{V+ExMX_fK}!)_g^B+%tTHmt3D@_38yL; zyIW*R_XJg?YEPpgXP(@ii4YwqPiwDI;~@~}1-^q+d3Yigcv1CF$_(H;;m7c@hY_A9 zhMXA}XcdA-fO2V|y_k^TM~yaZ7FexIB3#HavoqNxEHN*yI(niWZK$Yfed&4VW@o&O%Ev%Lf|Ao@40vV$Wnl$KnM2cV_cuAExnOZ* zI>kXn961C{V-En^?XCo;0|I2{qjNr|B&x$OFthiONbMRTlBfs^%=1CQ!{G=b-XRj2 z54AloIStOafK;AOyODN3V&gQr5IJ*qI+`fT5qVFhoU_jyLPSJW&Y4Z@Z%zVM3L%mA zu8H1<=wov{9zmhqY|MrOXWjn#UR%3hGB2Z0#&)YBIgiZ6`YyzVT!0e3h|YOa4I+~F z-Z|$(oJP=C^bY_4ga|4|dI7j}axxQt0tBj;trpiboVSm;i#6XIoHW!hnK>A1*96XT zo||Y|m5E?s{V}3*ev+K5G)cm2`U+b}XGfA<14NSIt}x>fc_v*q(E(tHu^6CK5iWC8 zewN8@r3?TgEaf)-pz!(*pVZ*ISO zY6;I+4qib;1uipCW<@dA4!d4CkD$OJB`eVeq2x?@gr;6aXxr9MPa^*T`=Q!(WPX{x zEMfEyVMKn;FR2+xFMpHi>@d5J*}bGXv5bmN&Y|ZQj5Kv{)|4L4__{e#3CC6L=Qp)JU_U3gOIy>zaUdcEz45rDoFucun zR|F&g2ol>i#5Rw;h@_O5+4)GS#^FbD_TqV?A)@2)qzKNDbJVo0l^UudJbLe)Z!r{mWm z;=Mx%(+olYz{v5lk%D=zSug&w{DZPl4mS<0d$vV$-#gNSLKus1_&12`+#Ndq{;=I4Qah+$f+kI43WwRx*5dy*w z39qkI7RD=oZrXX3vLT?#@QF^s3-^F$naqd)Fb*f+VSDr1QfqQfu?3NG5UOfaAm@GX z4g2l>CT@1jSw)Z@%R$Io9B$JG?)%YuA3`YLi&e}}l)N*h zV1?r>wNO>gqllS6VTqklB^S_wf04$q_daa4Tbq28tl*b)S#zhMe`KWLiw5qJW%->y zm?98TX^n`e?4?p0p)LDT#R;D#J9a3zl0Kw>9A+A=dhmwIQg2p6P%J>1{=02LxbIAieUf7iLfmPFE(!)psx56`;A*RBgg?V9sg> zxF$ZC$7q&Ob{RpY)&HlSbyZZALSg!BlZaYZoTk;+d+{hyKSDgi=l)|s0>0Oz^jSwV zg+A;Y@!#H&wYZ2Qdsd(;`E>~oU3S4nl zL{tQ-aXzj>A6A96sG<~k{=5Ln8bGl`DrUClspbQ+wK7C23e+@AU-lywT{u?X)ob*R zb%f-PaHK9SY>3I!X5udg$f0+A+6M7_=x4b)!7cvUrd zHS_oK1!c=P=LI6`nuWHK4kwfRoH$ho2&uaFFyaQEEUc+w&t8Z`}|9r^y$Prp2ERLLWk2`m_pk8oP3(oID5+2Hpe+l(2R`` zW-kwX_wd-X?d#ZJX(WU>F)Opg7@c#p7Ok2LR#nIDk;s#CLw6d-A+sRSyKmnR(cP=p zJ~T);Q}MdPL)m<%Mab)mOx~wao{j?%w(YL^y9k{lBx?waN7L+XW-Krb9T7F{Zs_~& z^whSS5aT#>02%?1C^kD)P7_dXqq%ZFmA!NLVcyzmA}XP2UcR-}wq)N`I8h#oXIj8t z{?6acd359fAZ~V?^Xc$ZeE7VNA&9W3gwT-l+uP498XiQR-hb^v-0bcUAg5%*tK;c( zI3Ane9pQF=G=bLSi<5N!QbUXmSkXS@w@XY-9_=o`B6N`$7IThdB z>^E&YyLKSJn{VI7818RxCxlyAWX!@WmNF5e0>HQ5zDX(VH_g1IkHaYf`mnj;{3K#y ztsii@ECvxDRO5VX?M?OUr}BH72AH<(&SfYtsH*90Y+jv)j)l9^iJbfDXTO!lJ`J7G z1FJ&>U5H4oKRqEKkq1C~nVlVFY({=_bB{=;$9J4Z|6CIe_~Tpqyy)%lLlN}PB-G=x zSpCEmSvM#&gN$0wXe!!&g-c=GD&Yc6&faZj2^#qEZ0PGXGOlR_I8DNzV=yh`Y@E!; zXEpKMMU`MpLm*oJAzdl{2e-Ew)lM>lNW@UiK_4C~sHW6u_b@ zq4|mn+-qTFg?1*TJ%W7UnuuZ?(F5vr9oWJD3`6{BA}1_m~*zr|khs zCq<5^==q4el7+_LT&WNsC>t7Tbq^6KVEIAo$%v;nEH)oR(^5hFv9}P#%II#wl6BTA zREejPFv$e$MRyCc*khh{=wz^fxJuisXG2S@DB^5_Uq67)&kNyljFzs27m)?3Pl`5tql=f_V{VyD}>xIFC6e3u2xR>Key@>waw6m?OF-T$S!B zXExRRM09+v%k-fE!`n>1QK2_zO-d7%!j8(Rp^E>1RuRina9j`w_&%7Uw{3z4IvTn?c2BBhnrhKL>D5b z!5H?c5SxwJb6>7y5qwh8OIM=hlFk-@giG`X;?Vbb96~r{`5RXN z03ZNKL_t)Td;*b%(?iM(sz|Qc-X5PGAKt&6j)GprG%aRCUZ|LE(xSo=+@Y(P7!e|k z{SnE<&7PS7-X4#~qqBvC0B!UD@bvILi;gKz zh@JC9wd|~`jE@mORHraVMC??@$3w4*cXuHYJw3d41==wiEi}y1`#9!f%AGW_wEt+vi(JLNa1$hs;bJ6hGd&v z)9yt0@i2(!IF=C?xe)=(tY1Nh==Xl__u6*z<*)qIdDnh^D`K0{$Z6Q!+~2(VJdeGK zynXkMhhe*kh!kQ|Oa@d{#UchzegE+A_{Ha+Ip;&OC30VV39}e(d-LjaJdWLC+k~54 z<9y>>QK^0Y`R7FR^Pm5mh`PQ<#O-9f@Z13Dhlm`06q7vq!w~zI14wdmA^O;+p_{xd zH5bcu4~VKEAZ_;d0C0MIM>N|ht17EzGY{c3Y90`2R^LM&$$Q^y3jtm-sE+*r=0F+0 zsW>}2@9XAZ<)F6mbHeArh62}>VfuyX_PJX5Md!bMyqR1j)W7I?!?_fjT9|dIt~G+S zBn{d>MfAgD=an^=K40EV@mmYvxXMz;m6Bl&w7&d{v9e`Ggvs3-p3B>tpqxrXU!5GN zFl$bho_KmKo<{%{w|H6lDg-HzXH{>_Dw+#;^4z_Bh4|I#R0K0ESo^6}jodkITUt+D z*^-yqP(fEvvesVDinxORW`#KD%KM;tMi4%v4)`HW&!=t%wA846g|aVh#sCv^t(BLR zDHclPn*st5t*(LAEJsBAF>RR_M0TD~z-$vgPXd*$yIGcHK#LR~=NpJCnNq!YKt+m? zO`Qw65^GhP#k`o$mys$>Puy%2d^w!aKgAtj!GoZZ!c6e$6<5kdQ;wGo4$r%;O@Q4j zP^+{{-qJ>f@d+k}Yv)2}cdffOlj6k)P1VNh!U|Kay=v7rY*{DH; z^KdGZ4Ig}H&7qBRQl3C~W4#NjN*V`1h;cJ5`Z<!Tv~9lG?3ZEsQ|HLBRxj+~FpmYgH!g}HVRR@KmKOi@V=e)VU+HZ|(XoZ5D?-MZLp6yWLcz4ZzTYGFV( z3h113fe5|BwrOJ1ze#n4)>IXz@f-|j2@Dc(GX9P%D2+@egFa_BoVonK*{Jb`C4%bZA&?Mv^!fcr5 zw)=Zm>j*IP{qgWPBteAxSFeK)+uP4n#4aYM(NeT>8gdemESdT-t7>e7l$v(Oncu#9 zAfhk6{7L~r9-R-~hpy`~%hS^nk=x#Xb>W-#9a@BWdyCQE?pyEB2;ord%IN+3_Y+ru zzWVAbJG>UUgsS&J0q*Yt034p4Vko`r;qBMt9Fogv=|$zPR@te?yRk;H4lX3e0Y3#ud3Va)_M=;{LOxc04eqV|32YljZa@C zPdOjAx35+8`2HItlAN9Q3LbN%Z%m`wMvqvcf=JX}&Ajb)S-j1o1_6PNM-G~Ht!2lzez}rijcYz zp;HCe5~11R3xX482@G~GRY>i+IfqPeh6@oPk#i0}-6WJIa?T`5(<_Mx$vNj#fjCbz zSy3@gA~_-jNX3Am@Y4_hl(cRUW>(_GGMt>bt^vaMeZy_fh7jMk!7>Nq{b>ClR*-ys<>nPj0ItyMu1uNE0BB2QMM6+oF%>Uv z$_44q1oaM)%m=3qZbL-StNRiz>i+3ZSLQx{itxZIdpaT_c~n^-z$$MG@NCRBTi~I> z*~5ibp0&yib0(!JI&F}mc%%8BJ2wsUSvt+%424}O_MB4z-~>> z0N_LP0mw&~1pD4O5~iF(3?W2xv1y_2PhiAuu)3sVY;YcZY{oYz3Ghb@b<^n< zyrkzsBHV5^PznnfPX|>QZK$K-$T{yp!MW(jPpOkY&KtC;3c))hav^%r1|X$$Je^WX zqT0sjoc}S%GR0EBhiGcEoJ9eeP4JL>IOZRjP! z6O4y-n}SHpSyhk6Q;ab-(TEPBAZm_L*fb3}WL5=ELswj>rn!{&0g+VMyku}q9!3Q3 z1EB+vPdyi1;v3gT(hIfxKLGus`ft3t9z=NT4s(d>e80+PK8sPp6mQB6Y5p2_+O~#DohyB zg$5B31VF~_NY2d>eZpCU+a@r}>3CFt;HYUgyZyfJPD6k2-py1oN9f4qJTB)wfG}I) zIT11^&Z%v;0Pyhmlu}Op35Y^yMD+Od;E2ri)HxDi0A@}AV7IEIV`wNJLnWsA;#VDW`sd9))w-Y+3-Y_RA&}(?N(}G4Mo)6q`20O?P|}kal+) zn>Gy{ITza<=iEKLMUk;TnMo<}0Dvww$}F5jvMM76 za;|R7ypOZ^`gl44V!PRlJdER*GN;VJyXg!jW>JL%Wn-MTCd%sWfkd< zkFnjv&8{R7Ap#URjlI}cWCJ{F)z9x;tuUwzWiF2>6}7PmB1$!kker!WgpnKy>J*g; z00K#c3l3=cingIlZ| z8umTSh_ps1u_9Vyr9U{=Xse)e3ShYUJdc{bx;@}xV;HP?|I384m`{i(;*@`;AMQO+ zYqJJn6Wj=*a2Cn+U}}1-im#il%sGu_K{FGn5KN}25sN5rt%0$Qd}0XAd<|XRxnA7$ zD9UIHOOn9qGCpHbf-^5?k?Kx_9#yQOAkWi3&bYM|M@&FbmCV46Y;rnDLTVah6)-ZH zB>XVyCwv@2(C4$-%nDbhwV_CkRF;AN3?+yliYnof0Y0Zx+JKa;5=8_%@0VXcEWdC? zCb0)<<<+UP^k!N8vrW?KTYxS$UB2SV)O`i%+TP(>;X*`&q=-U>2IKMwEYX7t2dpry z3iqnoNn|=5Kh_I=LK)3Rxr;wkL5KJOYD|^odcM!$@lCd~EjsdU|>XQ{Ur5YsTXtr^) z8%~F@I~W*SU;`fzaqN$(W*>?zVoF2b_aOxDeSLU`&?16}dS&NGRZrbzHnhgL1;jM= zQdF4~LVM{R;C&3C8TzA$5JK?o)TI!7Y@I_5-dTTX?fDmu@t^MFQ z=A7Z__$Fum*{}V&Ss$p#)8m6B!`T=xj=}j5n{7^GcYHLV z(f!>m0Ho9lbGx~z>1~qp!<(Pm*65p-$nWpJe8~*+qs}Z1}zIHMNJGm8F~|MH=2_m;1jZ*C1a(wxToyE`ODJ^-ktQUJiI>rP$Y z#NZv-PB|nt&)yI>_h0=QfF9p}qvXJ>ViUL+W4jwqPa*;$05J4N8m(xL)yp3M?~Ci0w_4&)I0n% zDKYbqA0VF~Jd20?s2hVW?S#&Gen0Z*i+Fl^Uu0bXKDJX*Aor=cD>4QcF}cIQH4b41fx*uc+)Xufw;B`J~jL@tlLs@gH(KTsBwIuYS4hy6Up z9T)7s*l6L|G`!CBEAr-@Xw^)RI^&x{ihT^KG!dq7nki`BKQA_^xZg|6ulOFZH_ z*kLVFnIYyfa5!@~yH*h{hptt=Gkmyq9fCPp@%hpcS6O})(2cNm9YR>YKb*}c5OGx( zA{Jk|6+x-aDML6*uhtJ_n4I&CXHR)t-1jQx$fdZbvR_znE?^}^FiF>BB|KXQeDomH zPu>jF(2-v6genoj@{G-n!Zreibt9!K6TTnk)7B%iX^A?mMiCcIh+6dx3U&Lp_5rLI z7I-n~sXCH{_*7q_bECaFmY}wAnBV1GL$pNWEswX(e{glGu@IO(9M+28=Su5$_}Q!G zA+;Srky6ijg7cnyHb_GR{7&7kE~Y3`J`B!Onw7L(C%Xj2>#Q>Xi(#7LlA&o_365EU z4)Az50DyIeLw`_(oCN?vaPuk6d8{veN$;x))1f;6K#WuLiKM<89XUj6A{79c^V7py zBaGO~hQ2!;k3)9~;Z05hs0xUEVI&&+BPfjH$qh$;h?$dcvacSS4FKj-FCqxwWBdA7 zegjlb4{s(C7c=YOc`dI-U0W{pX*5E;cz= zm7Ii!Yg|F|*fYzkkL-VGIQFN5)%Zqw`u5vzGt2$$mYnxKB2lxu1r=f0-3RAme|#9a zr#v4vAP9UqzV+u#3fKrB`UNTJ!qb|;+r!$X0KyaUkVX>^1}mN9#_ZH#eq^Qzh2oSxnm2I5)ple^-{@SR%ox-os`rgUjI zHJg2CHfiRXDGdFA$obG(n@-Ljx2!!NT76Zy{9Yl(H9{$p~ShD8mHYqsLE(|o)F z7q1~wgmc#e)pKxpLI+p%-rSom#rdRF23Sn9s_y!#7ySGpSc{kS$|}6pvTE&K|6CgM zg^501ONM;57)KyPn1vu$pq8o~#6rop`%OfX$M@`JM^i&nIw3d*P}Uvr8FZ-6(EoH{ z-_0!+7D_r!6?7#b*Ry63>-JIWKV4!0KlEHr6D0ij?t%44iE8=#Y|~dGO;9~ERr91c zQ4YW&u2v4PxK`g^{P~KVasDIAU<_xyw(S@zo&_%ci__*%G5qTx$u;Yes()OrYyCuC z?{;1`8_;KfS(rQ{mtADF$<5P0Bn3s#^37nT2H*Hgso=kj<%j*oA;vgt3`^caHo z1cqH5yCXSwe}8X(I*!9Q47>de06sn)QcBxRoCqQqo7TR%3(@;v1}@)x{RcC9=-u0I zRUuD079`g++cAx492JgZe@a7#NIpa#qB&a-qWN)~@VwNaX%H#bIR+ns8~aW{jODT0 zG@R4dUw^&bZnm2Zfcg;0d2=RHHH1cT8qA|$9EPFqi6{g=^vCY>w7-3Y4u@d?fZ_DC zKJ<)(Kv&Bk&dIiBMD)#uI1_oBB@lTZ19JwIoJSRn&1NoUIcI<#K!?8XhZKS*gqyop zSaMcz>`z3bawX)15QC>X(o+JZoZ(}#_=g|mW6&NfXUBqW+qWCf6%Vbb2kW~(ZkM+9`CVM&}4IUi!1 z#(wCJwI5W|Y)d%>Dxi{+QQ`?*z1gy87CjxG$hpmSf96WB&-p9Ou4zRrlZAQcj)a6r zr>A!l9He7+AQ#+(A6HhOvNSEAIS(r0E1ToxVAVxkifd4f5N#~2AMPNhcU#Id{+O*0MYM!y5;~YkrrG?pF%tvauH<}fNDf-t;PUBzJR_=HnPz;3Pm<1LuC_yE_lCY{GO2$vqV%7(8 z1$J4t2<7ixVyUD+5h~2G7#z>wZ0P`XV&}n}g*1oD%9Jj)s=DVUwKTK%LBK=n%T<=w zWJRZ?yq0zUHS3V(kZ3c8E+s0b2|!Z4QU)V33u4vlOi`=Puu@CgVQK^*M1fjsezBCX z>ItT5o4F_^C;m7vmmw86HR6fUq(O!A9MUoe<8jGsThtDE)urAxzKI-x2vbJ1pf1fQ z5$UvR6A>UH<7A49wF@;Aq#qQ3XNpH{SoVE;mL>m0M3^BE06FKp54AyJasHDc9@HtQ z8MKNQt|Bm}EmyQCn5UBo7q|KHW_meLxcG$gY-4t6Uv_;Vtee7w>$|`&Z#S5@Ki?1Q8JvGV4V;UP<6&5nZMGs%jnwq$D{T zQQOQ|Y(&mE3lCP0+XL@>bfBm1aelHgk7xWYEGI#^%`D<%k@D1=zWH()akT!#MciqL zaZ6D!uX}VpIOp1yV1g1=nVB>9Ddn8mdGEZpmy3!y)>Ym;6$M5W-BRx~?S{xHr^#kj z0l*Qp4T|vT)Y--nLk5JLvxo%eL}eTkA|jobGa%YEw14KYM+AFrXD>HZ9aHjN9g%7l z01!F5+ox_ILhl^{=FIb^4*--iBITSwHRmjl8VC_RMR-xZv%+100QTvVE0;0DCM0qsx5Q2oUac*=BsJ$ zWpL*7J0W<4P0AyHG&v(B+lDwNK=eL{YRX&^=0bGNkK>@z+F%w@pkV~iaU9!ryV>6u zn;HaEjmM}dj{wlL8&P#WgKEwx#^^&7$-+#|JLmhZQ&2NmxVgP0L{DIupq7IeV&hz} zdle%CKy0_(`@VligvgR3=j`s2Rm}5#}?a+3b;MbMxBA=Iej-_ZJ1Qf|X~03@|b?mz>2?4>awf zO>&d^6LH?F%efF^@Zuez!Qq8Orc>&kuD!`>F45%BU2&kWtXL#KAQuoR4M!EpV?S#w zrU@-c&dkYG?tdlH!MUKS%n1>lBj>&Map?P$#+2FS42Up}Jt6uvI6sZl^>Rn34@C=V z|4ulfloCWg&?s1TDCgvSh%V+l2xs#G&RNb7P)PoW(>^3!y_|S?cKLa-AB8s@oQcE001BWNkl*TR4gPcqye+^50`$W%bp83uPpXwR1GFvvmAy_RF{}rgkM#y213LXCoCZtQ0-$>b%|L-gLf%&%F=hPeZUal zIxo&)CmsPBdeLq57*l3e!lizUVU>Is7tG#onWvkJ?>UL+^*RUdf_E_`%b-wzZp}1C zgqX5d=zB&)=Q~Z&p75I>Lc8+s-W`~Ep00cD?mgqK0zqZt==#Aqk3?v&sR{_J(JNE| zQbQWhksSlY-yrlvre4*wESYoHb)3_DeNk1($s{qHlhGEu56q^)D!dq14nkZh)Upm_ z6#>mYH^<1P9l}zP+ z!^w=3);v@|q^>^*W&p@Ji9{PSnUx)LF5MfbG6SFw;ep?q9T+*OiVuC|&8^pXcc;4X z0?D|Y|E}~t>F2#&2H?rVjg1Obn{>VB{CHU zR~TULi&BgdRc5GuiY5;eCLaLFhn}2^^F>uwBVujACsD~ckqevYwh4W1Pnxy!Ee7+e zDx5Y_|Gm(n<@eW_XG5&G!^#1^#k;Mb+xV+7) z)P%>P0;0eTKzA?Dh9(IewFISC)}dCb3quR{%zK0#!TR?2zu!z%+bC_>;ufh$gICgx ztg!Z~N^Z2MP_vuW9=<|Qb{MSr7-BcRq(Bg29h29ApT$rlgI+%Q$u z0^<71`Rtq@#&M5oX66KdKDdCc?i(S{w?~6kdVB8>^>}(}4D!)rkL&xZh@`wr7k3W( zK7c|>Mc40$sz{@GXGn>OOz#hU7tH)HrZ5|#xA!1CK z5Y4Qa5U~%`PQwYxc;6rEM>+9DqBH~=}-^`gm zeg1-oV;^FiGhc>b7{`%WQnE6(JQ4O=Q!8&|>d90AaGJ&_anxsJQueg9)xuFG@|-RMJa&ZRld7L8)3Y~9FK&f~7m z_1yrge<`^@&UM2f=luEeza9=BzW?!0;&e^R)spATE-R&3IRDvy@RxC!KL7N4)8u5) zn2IBQ7qTa;)4t$+T&}B!(JIVz-W+t_It9y~9y)9CZ1;4&_x%vBuPW-WKyQXXl=6ZI z(Yertel(1foC9!&Q@Gb%8BfPKA7G5jw9Mzj=^Y~FxQIvyiU?_$Y)^7NxX{hl%XGaG zp(8X+%g_e|I6Xh*lwMz75$U@hez=^^={h?{A-E;xl)0|le*%I0?LXuk=j*GTb$xKE zdOg1&z-39pF#hI;KSk8*%ja=CJUzdEeR+9#`HIey?+?dqx;$N99XW6A$08iBAAkSX ztIotDQjaGrwr3@PFvSTF`{4-NNr*YkIn8$LagGQwPp>sBwfW3bUf~=&uF^7bid`^c zIxs$4H$vH2M58$BJbSg<+G~xX+)&wAO0+- zIG;ZQ;PCVzFH>4BIVWqf5plX+0n}7#9^WJ=;5{$(mvh&5b<;XV#5zg-6?|B13D9>Q zs?DFQH(pyV!%f%N$p7o(SUt!=YnVW*sc-D|_tcwvFH_N7s0K8OaNVm4+DHwB2lMx) zQdxi2wvB3|&#eURonU$6A#XzdR$GdXcbt2FINg7xCcL*^Gh8c5S)uuxOi|t3a`$Fk zm3zH{vA5xE?PJs4+kLK_Ze)EGXtEzf1c`PUiCubGL-$_~Nh3ySy$8Dg*L!Klozfh3 z28CK17XWbWL%Pp9$6uWPS625gkp^(5JkdAxIge=yH)k9+f7%{ zy{p>eC+na4Yt=%*&3fOVtBo5*^K~A(rZru3O{c*s+o?zdHsH#`z43wc{!Wrn{nhTM ze7ciQ>^v9ie;eGS?LBFCux~s?&Bxt!S-VH~R-IA6F3G7R<9JgJ7%rgSBHc7MUU!(_ z&bzL$OTis2^WoxXgeDK%K%3U^w)5S6HEk6z_s860#~o&2R`2Q8b6c2|S-ivcBopB@ zUjV?;%VNwnDRd5TVWg_Q>Vfgy>tE!$(C+|y;v@NLl`r^aT^(7pUd?4q|jH=34 zML5nEy9GXUp&L`2r|au*eC~$h`vwLK;o^K44o?7(R))8s+sCI4)_BDsFT&gp$L3*H zlkr~8FX!{CwWOPr5b^xwC!_TP=u$}G^{8ga$$O_N)A_T4_QMI*Nnr)+4Idm1&q$7Q z0#N5X5KXV2o$va?699bv$G=sPoT4g=a0o+TRUi$Aqx0SG{`&vHl6FL9XggnCR7IJ6 z*OLp*cL2IfXU^&A!*58v?*`5pzP>Kg6eeIP6`=Fp|;3ln4RhVi>U`4^yidHKXSUe8~A=stY-V03|@4~RI72O{dn zql$#CGjaOU^Yig|v`d#?zUKMz^>rqq@mYRN9^qS1YAs*pC4GLGo}W+SFbv~XqJ?k) zfUiIQz3CQ^oDW3^p`5BoLRw}P9uH3%vm^dTB^?Pdj7JKqRIIn z!eR+LWk>1|ua==!oZ?rvMI?)CllI#Uhi61m$*TJF{9c4pTvX+JiNi1)k4Mf)IOmu$ zb9;C^zk82Jt{VU}&DShxo+figGrt;0p zvRp4^8i{}q|MUO)zYYE2|M*}2hcAEpySQ8{wlR!PDMr$mabTh|{~_;@vXS`y2hJ ziM+8WswTEKjaxf9LVR4NuW9e)eyBduO+odtsD=RF)NViCRLB75eX9G;N_*Yzu@T+Z zkG~p-!_A+YP|C~?X=Mh%jcH_IIqKaH6x}KnyA--UoMqN^*PK~PSF~{|=ClW!@5LKs zK|>w*hMnQBoUqhH0)$FUN3 zGtZhvxLt5+rmrH02#~OW^y2S|q`{8K$LHF0uhn|SyG8vl@R?{^?5|xKplySLM z^R|>;i68{uiY7xC0U_t8B@NMyhY?h-*UNtHm^ddB=J&%$M5gYn-fZoLp&Lc_59@ze~r$WuN44hE=$5WH(y`slVKBJ=R;bi6sK-Dg$_9_6+kmJu9Xp8 zHv*zE=bWcGA{a3|(*Y14MG6L%{L$VY;5be*Nq{c}J=uoLU#s%lXy3tt+^jGv|B-xE@aLhQl#V zmpb!5y!&1_&*!hI${bsYQ_eBxNE86!dVW#RIWnREfOConABMwIii?T*<7|lTBw`3rlmN62y;dxa3DD;r#U7O@gafAI0R5wVzvz_ zgvzNiGM>2@vn^20NdY(|7M_StOSU9)L%RDa@A~_z8 z0C4{Lvx@jI)J1U^yWpKLm#=U2MTv7lb2mmr1E9=atA#N%ryCntQ#!RmH5<^9^GHtP zvSW>{FLut=gfHP7LI@#TE*Aheo=(AgRYAhb*Pm7OdVZ}>h;W``T4Ek7QPMf@!|(p# z??MQt;{g%lJmq9c_JUzPKMnTr;`JrZmx4~@1c)K@c1BeR<68q4Rhh1r5W24GP5;h0 z#zhPYD$K_IV9Y>OP0KaTSANlyG9sSOm-FR%Jah;+%`r23--~ccOhkY2AN`euZ|7ys zX%P|7TXris*A1r<_@zz(e1E`=2Z*X#;#BPkR|Q1h4V)9pQg*rF;DgP@fixINGN(A5 zFQD3a=bckkyLZ0Bn~};gpAm`TvO+xkFz^RdLB)52io|6Cgb+rPU6Larr^+TIT2KAL z0Ty9-~ZWPeg5O$U?FhYaS)Eq-P*y_cmP)u8R`A| zcg&e{bl%y%!8x17n(cM1)*{8|{Kn30oP9711Cm>=FD>9KoPpVQeSdgL^VI_Gi&BeX zD;AwDm#W8Glg|NQHeM_G-q+(6Tl?ULV0WqPu!6kncnTjTiR`&aCN+F8p=v9MN-4Y@ zIhAH*gYRpx_DHO{Nz}2?Ag+aih-9O}YAft4bA)!xCYW z_u@^zv?o#NP346*Kzd_3RqGuC+}1Sp$EyuPAfZZGeT1(A{7)BxcegOZv_-f z3Qs#|tvww+K;(ul9j?1in{%u2PLjR4*ZT68Vb z+evOS7gfDexXCKru?7KEuo7->=s68_x^-Z_85I|ks^;U}KW}%wcDNrcC;&a`2RHBU z+wpL7g^MDxY!z!Pw%(;&**=joH$*{M|8JdZY*(s)XR2a3aN+_I7RlP?@$vW|`~G~>;# zR`klQ#Y$@4n5w!)OO6lx(y-Y5-|*q_TP%w;z^=G_?8vTqx2@I}??U1L5$E$)AbNiP z19@Kq6Sm7vzcTicR8cm2HeF?ow_1zs`NoGH{>DqccY)M(9HT0{RV2GP@or;p*LaR#4FU=S?`30fuFTATTEjQn6xMJ&asgDUZ&~}@nRCiwx+`nx>~ay|-n0arBT&gHw%@U= zYTs<>A^?#1iU^0}$yJk zEX>?_Xa5bVX_?V^W6vtcI(yF*mLPIQxLA7v;ha|MOG3m|oTnmeiL3@x5IJ)J7tRW1 z=ZW5t;LbcSc&7>}Gh%kRuc$2`AU00 z0A$hj2qQ-Zg(HFwog;r^pHWCXvH{wrK!-Jkr99PGUtC-@ImO*v&@^Y|d#Q3>@k9WC zWxf(Q-<5b+kYcY&@49+=k`MUKYb$w5WIY$$dS>}83&tnnQ z)6+Xyl@FK8CHTBC&YRM zr21v~(3v&I%HuLYJx5qj8k{Qj*1*!ZXJiR!lp_h-_&>h<(V~ipa_J*CtPBlHZbL5DuhGoo1=#6$^ zQQF*)eQ#vKt!=p-lfnXK$?yvm0lrnk7-Capm4xHeP99V_&gA^z_*ACNM2Hl+ zPF3R)4byItZ|^%*F#&8c@{tN6_^wxxc{<~!VWM^>%OWYuaSSZVEDDh0?E8^?SWRF| z?;mRukIofJ$l4QdPU}lcURbGnRFIqjYX*1QULe9CtmMcnajB&^f_J2<(~^nMXLK%D z%sLXT;&jx8OM=3|?~?zBR^<;`UZacCnVeryWl#lH?U1}9bCYQ+P$H)y3<7}OcTFcz z-`@d%Xtq>!MFhyJ3e+KyK*qHXpmGorAnG!K^UnFU-9#b;lANl!hW*vDEZ&FE4~W1e zs+NfylG7Y>UW~+HC4vZ(BMYqP`ax7A+bL}K zM5tU612CNi^u#$cM+m(qC!AElk-zC#yRH|>IYn!-$vNk{xLj3qNtrXh`~Ek`*(%F< zNzR47ADDCS9J+ygF!&wM7uD#xo^$eh9KG+I?{ZpljvX8j(FFu>oEHG>`(9P!!mS6U zx}8s$DtL=V;aHC9LZQmMZf>Sz?>kRqNyV<~M*!s%O@mh6Swxv#=l~JGtsDharTxxN zL@sAumiU|J56=7f{58#&looO>gnmcx7BLf1FlZMyzmDQX0BT0He)X5BZ2;J@q&m;D z_uj0mLN}}`JG|-Cb6Qlz`A%3inP0UX?-clCJQ;!&G164oEIefS$j7#IOggpsjzVJ$9tjb5u99H{qR zK&`oMi#!!xE&?F|Y2z7LyN;EmQ#YCQpNhyD)qro13OCq#JCNGp06sQy^~cl6RJ!X& z6k#dZQ9d}=#pO~XDcbLuGTTQqe2-aK7|g_5?$;!kYNGwK(2Xm5l~>t&d2X06K&P9r%_KD>VYayfrFj6D&CZg9^3;UE9#oa;lfCN%`t1>b5~tYPB3WYr#zhy+y0 zt->kh9CM0YKUS|lv;Hc0^*z3i80Tx6FNde^kf<9Eh{(*sdA_~?z%V|EWX{?7Kt4#0 zIi=xvLPXA-9bTsB9GPx`ImygvnL^k5e&iG-&6U<~mUxZX!tGGOxnTC8L=M1NQ8}L8 z1L%AyRsi02)~X`H5}AdkIV!+u=%Dc;Se?y@T(G+drHMgM_5GoqBiAL3eHe#Ogg|~n zW;idLf1!#%#OZpm1eG>)r%rs!NuY{EWU6 zW)SFtArW0S0zg_O79I{yEq9v8Qy01(PU{{Tx)A{mp(FCIpZ@@>u-YEHWxgOf>w3NK zmg!ZQRTvRDEr1yM1F6s)ocBbIoJVv-W{;Xzq#Bp`0);pVDP9fK_n{lcqpGCo?0sKJ z#nbiGId9seHlaSJ7`na>r)9Z-N?ZUy`{Bv1hN`B-h#mswoa3^LQDz;Mk;e<%O z8vrz?NUj)+)ve#2hqTPab)9)$zCz<|Rz~>3ENp)$hW&Outd+ilZWCMyhv1#V>zAKu zT$*{ZU#Az)G6P10emIOr(_p}S{kpSKA{V*=K;v@FDb3Stin!4AT^QnWQGmngNa&XN z?3}mZ^!4SV^PLMF=fpXi-N)0rA8U-pPk;P95&5+wV$L}&R=oPqSD3^Rf_HJbAiB`? z0Gbjz=R$DAN{Ei`a$XDHx9On}e^K(QZ;Wm6SLh$0O_aVBY3%gLzm{YD?Y{FyWN}YJ zH~5{P;bmZ@zO)tbMkA`!4&8n2GM}#0O2p@DZ)-UgWchPww;v_jYSdrF|z(*di_Q zhF6Ar(m}mKxcgMM(e%Z$d%dcAo%kc^#!aVypqk=r<~9#J7B^iw-UWi*O0ZWOCfr%( zwKDb^D7dl)R$od4pq7VUHb9X!)X<0~xcLm+i&nIa6RiE;+IO~&VcOUgnDlVBruOll z?X7Rg<~PO^dQbRzvsVn?VS!Fv@&zuDj#Ft-}$#T$N+T7(f2}ld6urUv2h+_dcamjk9B7 z7CDZ6B~sPr!8vk-HaoO(-d=ndy2fk2oG~eL$~+FC@BGVoR)s!zBHW+KkXd6YNgcfj z7Z3qpNts2D>rFwV)6-L2mU-{8U05V3GwX2(+6)DSHL*SX>KxKed#7FSqIVTYb!vU&qoT|N8 zI16X;!8xCnsd4V#LJ2HWu+R{QmifBOvniUK3q{_@|#g z9>(D?4k@LSl0B&NJgaKVTy3C=#1rv2j!#cVAWuZY;kg?R%k{#XKmGKFWuE@zw|~AS zG?mmqB8tm3&X?o!_ru|Nx_oV;;l1z1=MMnDIiFv?{`}J)-o5|u{O$wiC}o<6{y3QHW^VS*RcVWZ0rgK=D#9Q4QJQe`bKrO#DK77rCs<*WV+vgzudkIBv3Ai^c zsg~+YQK5-1ETd6{H7RTD1Fc8FMtge`q>MEf9_t|WP9+U*n3)wBEo}LFmNT#ulEZGC z))tesE?*lQ*!@2?ke@9UOVT3J1c>=mgjxXxNjD9XCPj}ZtjxAO*2k}w}$)e9KM}yZf5k&JbN=^ z+pWzzoaj#I+)Sg^@nl`#tC)Rr`feZT9g?AU8`sXI4cn&;8&`eN#&4}`1$fhj@3RNX zGPyxz)~iunvYRonwkj!Y7N$PTa74sk?P-1^(b1b3p5AH<-e&*bvoT7ai}$FL-51zh z7TDZ1ko1>3m+A_q4cJifPU{k{rjIxOdUHEyC1?1pvjhLtzx=P-fBi}C?FgIbdAyG;6j5s#SE;_Ud&VqvTJr`lg`pdSSvc7Y ztm}Fog5mGXA|l7rQ+-0oxs>8OO-6M5@ZArmckf?6{$5s<#pkc*5W@5GGXPv(zk2Vz zr<6G*9>+sJ46iR=L?mZnksp8fPFQkY0I*v}fK8?@e*E-VRo^{7hpv11@+pMw`21c) zKK}g25G?VBV`A%S){anA)h461_(B-V)yT<+tg0|CNkI=o@0_JukPm}`#`)rWSLcGp z1~mEVbp9+kVGP}&8;@Up`rYf7 zpWc1=k%&y%;hY!Y6lc?J6L~YGbIyruv9Vu1e~vN!>2Lq6nu;#hvspkfXU@qvPtKWF z+;Dg@kbs=;$CIjFUp}T7r|b1_dLB11y;&-1b@wIhTk9Zf}J&Hy-c z)=cZ+>HXp9U79aB&h51S@a_lUl;#OkilTtXx{V@q)1Au7sIID-(cM9zhPey|=9(&gYb6j=2l2^W?kUyDlzQ1@*o|baAwOrA96Db@q(uN!s`wpS4g}{MoeR$SwhJ^GV3T=NbY;BRD6S;~ zDCb-+vI&{2D`;_anWr<6GpCUpC-T9$Ae?y1tlw5j*B?|QXA7hh zs?`jk?RAIa2@&Uc5@!DhAbvbFx|c9-5IIs~5&LUexK;_UX_rN0ZJBnG;(PzLO)NpA zDkz(I?oE*Ijo`0_2}@C}HKnmu>4<}kLs*Ishxe`-M>?|os75)oN= zYcMXNnO2Zk_LAjwturZmIT1F}hGHhCS_6`dGe&D{kgh5^J6C803@wgaRj9ZJ06FqL zNKTls2AQH*%RsHW?sfnuw)1>dA?Fc5$bka62H*q$1OXsRX?J9|QIKkQ)<)-hgZn3{ z!eXg?JJrP9Y{t}Vh@khK>wTfVcNx~Z(4E_Vf^RCF$vL(JCBzbDwB|=bNjC5*EXu2n zXzMD>Ns^h@dt^_fDdlyKL+XZ|s7~iEP%bROTh;O1)W5#lx?QX~6C_})YL@EO=qTKgA>Rlv&_^@low3}_puG-F;dVNQ)ie^?e7DWTrv4CW26Y?K z1Z{`DX0bIxp8W@1qpx<@V2dF&y>dwdH0QiKM+IoL#Gu83WEY& z=X8IxnTtr@_qNzogdy4%U}4|`&s~QMnvs|=~v^TMX*WEdvfHY)diY9 zGH(g*K;#g>d(UFR&FTCV!f>bxIe48!WS%C|ux1t#%*>*?EQ?XEWaVei^SsJsKy1QZk-x?R1^9tV;wW7j4Zm%Mx=4p$nnpX3#BB z$a_=z3uk7|)=Zco6*DulouNo2#FB%A?J=nGQ!c^iu-UgDBF9CI7_F+xq7Dm9jzv^6R2L}WJe=MmKwKtJbzM(( z!E;W_RLn}GL~`5xC8X*^T-HByni8X z&ssETjq}6dgsTfV=fyNZ$~g-oBBBEY1tD^(CB#uhkbuaEu&Ts)64jg{0GysbxX{J< z0t!e@!D@d=aa#Qi9AckxQ3S5Lc9nv&o$)y*D-?ovq3aM)g;gLe3#D27mf%C zoC}5DsAB)U$-){6y2ZpBX)wiW&NJt<tZ=2(91O~JLj!=M5lYmf);fSiFlX=4J7-=!wNhS3*Q%0B(}D%N z&zy?m$*M&)6)mhv^rlY_!0^^VSijV-54&iT?8)*7>24lrl%t(>ssjM<-e;ELk+@9X z|LI>8{EbNU_aaj170ki_rooIc=A3vfm=STF=T?bts_Nhz4aMZ`!kP0f^5q+oqbb)3^u z*MNwiFo`okm@V}X9HQEz{L~Gc(=uHEq3aL!y_i#4lMYu)ni710RBT$)GCAjv9Bu1E ziJStY6jPiJr?k~)!dB+2CI*0rDMmBbLtnH}x?4V({MKQ8lJ;m58oH13@9JkN+U zjE8xiQjDBqoG#{0Voas33xqhGKO;~bE9?@O?^aBVIrRO(y)y$aRgsjfr7(9lS`QVd zpbjE}GPCVIs3I(JSyEauD-yj6eLo(=07fEE&1Nr@7Uw$WgY(`a&dZ{zYg1nB7@-ny z0FYS;5gm11j|g#|MJ2|?2y4}R*lIpj?Spg9Y@UEQDYJ839d6lSP``WMb!3VQfV5m? z^(YQqZ+nP$)OX(IJ6dX~sH&McX9+ngAm(aKIST-Wt}_T-*K~+}I5-#P>C$uvy>LpFZg@inwY0dBE^C%IY~Co+ z6kd)@`CP-li++Q}Tzi~VfvO_HjzVq19;6`LM|tggPFZ!brn#`YW8t!O!@TKIP2HP| z6v~3Rag{cCKy+a!KD3({x-i8GIOKzhO!Fl(2S=)cnA+~oL{`G0lCe=_wL8Ca#4MS$ zLuc_9)wRI;P~;PDHCu1|VH*mjkATnn&V9=&Yv4h+Aq4)DSfDrmaQ|p-N)Wv>v@`{A z0S^q=TemPpFtX*kC7EWHN_kayOjIA&f(Wf>q*08Ju!?eR`y~TwMQT&uc!lboZc`Em z8f|{XLj;O>8?>nr72qfsS@8`L&^GGp7C?9?v@pLuC`B9#v-iF&j2ba-_4j*xYi=aL z-}Xdkzbf3so>*#j*$t~4UK@klU0~z(d?K!aLmRiHge7dO9sI`AwJY}VhLMd8grhaG z10RST5V7PnHZ*_TeR5bs9O{FGcXF2-3q}RA@U9SCxpg8UiYQR^;3!p!0ZmwO!;Ate z?Tef9n)0Z{L={98S02qazYsBp9s7bTLa4M(8CLHFsl+Z^t&`fE5Gvdm+6n#3Jfh{? zS0@L(rLBvYvG+n|UuMs6F}PSgkXMY|Ts`bQz-`n;vu!rM!#9xe4Mocw4Q=+a5#JDZ zqOB4}kJX*(E@pH0&~NvGTB)5CRj`W;)m^XynpmV^9Nrw0M$>|_y0=lA?v+0J3+a|S z9m^Zb*)9XyD%nl+k*RSKy4ZSx~ZZ{ms`RV-G`EEEoi^%0Nb)D~mxAa7B8TJaM1V@0-jZ`oY z?D`{fT$ZaRd_E4L>zxmHHNDhQqr#UeD*(uJc`R%$hSJ`7)}5+oQ_| zKa4%Dqd1%TXwIL0{&}9KfAJUpVde3SedvdA7!RtNQw&|#^+Q^&Z3#lO86XH}$;oxS z?*>>sMIT}h&IRu}-wnkMKsKMh&>x)h=dVB4woiqXQwScE<8t+(cP>~tS*7~5BUC6Y zW6n{QDfFWYU5<;YIs)u&<^1G!1`etag2QGJ6Vc|PXK71vN=;l!-<#h@ab&2h>* z0?_I5rC38K$9Odwch`AaiL9KG7;4yBPqh9Cwn)8qgpgTvSzbT=0m>O>%W9LU41EUx zF%|Tc5S=G`kk*w_3|aw7=R3WAnqNO1-~X6%jMG^~=4B~8@qA60+dbvwdeO`XWykY$`JuEHvkBdMxWC30AX@yH@&1dSN_5fO8WmQ13m%*m=HquQyp1Bigd zPSOhhet5E=R1I#-MmHUp%7Gg<`zjV1}j_XRN%W}Y2Ap~8*|Rqj=xrD8xy@P zX12&etwM$-482XiP~2$*Zpi{047DkR8`e7R6{d#u@4E1}%PGBef`>McyrEz0vKih; zy}L16__i`;i(l7USmrilq3sXgUTX}yE*T$q73^Bh2g>g^KA`@R{CzWeyMZzE&;c)oS7u!?pHHEF&3js3^I$-e*1?pZ2@yw-4bo^o=Z~8WENrabr5P?Xo^{ zX1GC>DmO!S5{rtKv>Kuv4@lQwK+!i?{ss8a2T3uwH)?1YRj4~3hC9%rRn+Wt<=AM@ zv{~kx5*!eUXWix?(SmEOKf_}VQ6mj{0ASt=@86hseG8u1NoH<`i1_CIu_Ly$4H~q2 z<2SV#H|SLRDA!e{-)3FDtsdE;cvLIF2XN=T;X`mW?Y)Y5EDpXJ+bDqfMvli&(N%Ju zbINgUM;bN>6_5&5Wwtuk*$B;vI3i|ck<0nDP(@UU5D?scNNDhks1n||16;nnfnCn$ z7KXLDKt%rj@Bi*F4#&f&DYbC6nq}0w(48-W=p5&?Oo(_Ki;vpc2P0ykhu9@c%k?@< zudnBE2p^sg(;Pp2z5Mw7cg9831~Er~)3H~D7@6-{;hfpNAdAG5RrU4qQwXkG^(P`1 zS}rLG06Hg*=x_h#uY>o;Lx+f$*UyM}7(3q$A@nMWsGmRnq#}JERxG;AX+m(EGv{Pa zX$ZaZAB8eeh&;!6^=|~u(P~On z&C3NH0SrVAd~l&d01LC^xG<*UyB}1Tb5s#?;j*F_k-QH!p;T35BGN*zwzxh-=EQNb zV2~82v|R0Yi!qDvK^XoiXvCU=30>!nlg(^osT*Tb2H@5p(?$x_;x6%m+qnv*S6B6PGnXt@k`ja}j%k1qgx=t9>o^TpOOk;`!c z)&BSdB1o^!cg}}po|gG~czQREr!OD>QN-j-uuQM$oGGB0zxG`}j0c5@S?n?E`U3#1 z%AY8rF=j*zowALUghklW-pk8`0brRfCDj43?+?P9;}T<9Vtn`A^Wo`zoG$=yc>dsA zc>VMTqXb(8dwPEN<8R+_j-0a#!MU(Zuk~mk=S6s#&X&DumVu|P58ZHi{rLa>;jf=R zd{0Pmxp24W)LFf$^~*VoVgIBoDP()INdBIf*Lrs^>+zx&(&&pG$~kAE8DHBRRc z2Hy?9SxO5bFQ5M492zcaw8nSuKiJ`xW#Jrs*N1Mj(?obTA4Q}vj5#f7nO3sfM(mH% zMTA3{v{h@s#LHy*kj%;Elm=R;s_%yC#1<^cLB#faB|`B=q_Rm~>FMXoYSzj*Eji7q zMe1%ZzFR2A!0-tItp{6>lJV4&Fk5w>;27OQ)I z;=?~nXb-n8-n+TNU6FX>g0{A>us817$r-UtvTn*@ggYrIHYPwfrO|y|v-v}vbnMN+83{NXnSK=wYEN6&$ROu|AmqkZ+hgN zAKW%0#rlzMuJA+mKD-HixA;j_qcW>Bm`4fLwCP)kx@>H;Zhx)FhYcm$Wxk7he9#l? zL*tF@OX3b1SSF5WJMnSy{ft`9Akur_&h!K|u!8~)jX zz4uSwlsu0UO`$O}(?@;-x;bL#V|wH5^VFId-mnS)9(cTMoCJKl9hXO6+9B@kU+$)F z)oSj6ea9+YYXcu2wx64o&F)RAuC9IXw&jM+=v42Q+s%gMb7n+Qom%BtwOThqiDeTj zsLM$Ul?!r~m3zE$z*s`l57@XRgze{dg>+m!kr4nwpqqz3XE7VF$HoD_!joV;9NW8G z0-iwMJ&oQ6A37v*j%?u1tiqC60d(ktaDM&rNmZw1>4NXOQY*|c$CyvY9uZ?=W*J7z z8Rn(Tv*>_>W00IgvV{+JhUNNN_uDvM%}#73>20*;uJ4Jw)x3{HI~+nd zo(`Oo(Q(aE4p!s3YU2Pv{cz%(a*kRuIk-yDOynCAQ@JUcvozu|mr~?;w#jjQ6gS9( zrIGPzrC;t|qZ*ftNL@d!={c;zmpRQboeqJBd_RV+|NFoBcOitQrxPLe$LFf%bk2F_ zIH$wmSh4C#5kSOo2;IH<0t6fBL=i{`B-75Y)QBF%$zcS+^R* zZa5N=8b*uKnG3OlPMOByS>|Ai6gH3vvjOk`>7|VPia@J8waqmS}W38>w8^+PP?Si&KIs+ci-ZrCo4Es{jCML{J}k zRavI9_nq^>sw0a+ZUOJEA4S+MWTR053^0LSr&L~*%@K;ndmhtM-8&WT)b z&Ks&>5BM_A%#3)wFRPeE1Pqe&eiIz~8~O}_?qO>MMcpP{QvXs!5D6SU>I81IjrRvV zz6Cz3;?DjX@Sola)+XwvY0%=DzV#J&Gs~;$*;W+1iD>F;WIr5S12YMctFKuT#|--{ zc)f8{t99zi$!aY|8yfCo=9DYYtJbd6q|X~YZ?zP7;L59TQ^c)v4ujp?%42#EURdQZ z_YU8(m1SAzb|sAwhHLZi&7)a^Q5aBV1+nxYzEW#iJm)Za|M z?){(Fe6G9xx%PraGM2l%vbOkaJ*n?9=UdXNu_d*2(km7Ry4Jq<2I01`C&LG2`hEPQ zu5=ECP%|)c&aQ;omA+;rN}3sAkuBa3WA_1Mby7`R2ZvPBh=>YuTQbQ&PywZ}-a|wO z$Ow2}0h<^u=VX7w%;v&V*P3k37^~+W*6&X3l*&Gru1WFC>@Yhevf{wQvIx|)$iv% zq24T$T>!MS5!J?as2q~yJR+fUfGEt)l}K*|uopXzB63|4Ip6gMQ_#DtMC?OHM4>+z z`B)JxI@tTJglsvJ?rA6DgD;jVL@Yw9+-)335y?4OU@Snc7=o72FR*@5LHoYP(#CnK zZ3%H+va0m!gVf~ro_1OUgwfs!!Q$N&H!07*naR6wWeIp@rokEbI58YSL4mc_(udN^9W&Pi7639a#LI)BF-@qq5u)O%vlv}>ZyPxPPY#C zo=cK*0w9sAg2pAXuDm6E9`~P)C@HpO)mDZJEVosSBQRwuNn~G8W;? zmXH|Z%*^w=lsF{B>$D)DOAH8}(1hWJZJ<-Pv>%4r~pWekp-ZbW*`DCk%?4w0fn4J=g9n;Q!Fe& zj?Q_|lJ*XODw5aqR0IZ0mVaw#q-~v?lVCPwi1Xn-@k5HgjUp%!Dxn1cFeg>*f(Mm( zy5^ix${~Pvuo_5-c@b=K%-0tJKvd?88!15$k(?*zC1<;wMD+f!shBw_ieMq$d=)Sq{21#dj;!Da;a6ZE17BY z)_GuFCKlpIg=v8x%tZsFoAYhW$3_5VU73x$_hCq|hC0;N!uhar@pM@htkDjHi0TMM z6j9N6XVh4e3@ZS0x<4vaZx6*f%zrpPK|pQO9BuP;n|!dwZWQ%BfazYp+58o$z9a?} z=R0F3-zU_IC^PqE_MVm5?abOu>gSP^)*I|S)wa#K&hQWx0evCoLqD1}ImJvEedwKY zp+Asw^X04Yl1)_pR+5p?I%GSCa2&^FS(asij-2b-r@0z8A)*fs%`tB$QE-Sp^QAsv zCNVZ5z}GKd$8kI!4{@32YoUgZhXWCAmQea2FtW<>=ILroeed1pk3R+PPsgzga-+#PwyyrXBiZrdtv_i&SMu$ zRU#H1SH|h{4H#HooLQE{!Bg-qE(^di$D|5<=N;m8Ud+Q15zN8TbPF+M9|SvGVipn0 zjxRUGkt(Dt0I7aW7G+T)%i&THzQ+$|9{fnZb_0PSrgJ9Gk1@O%&h9_o;hcB54*?$B5;9l$sNzb)9@xd3)~e;g`M~?JVXGMCro13YA`u$u0EJjwi3o6{ayRn?SI4f0g|km`j< z1PX}eCpS?*A`k*IH9@pEjyK^|+fB}^n*~%K0ZXhz_fgu0 z%@3((rEzcmj*`u8%t-r$FA!h+yM7y*qsvX(Q<{@<(=HyP=(b3{9pxb>IMTqFdO_jBgw*$QufSG#j4iAhjdzt;tard5R20KGw@L$@ZDEjKNvl=!) zt)H)L&V;*6_FO-M$f_$Z6hjPerQ21gWN-bg1Tz)CcsCm(qRndu-RQ0PYVGpV2@%R7 z)55c9H*t$`{+>2$$4|B!Mit)vZNyuhL)Gz_FkM=LNpzWj)Y^X1i5`2{Ylc7J)DC9gRrL_8b@$7YuEtAUM&C%v;gc3MO?9>rlg z^-6YAeSd!ofscnV=X`!&L*OEsHef^y+?WU+Le_)NA&#L`J(km=Qar0UjtF=-L;zdn z%Q&4*FF$BrC1>9+m=TOVfSrli=Yn=Tod7Vcv*h$&{MY}jNX|Lsl>Xhn{ojB1@sI!d z@BWRMfSLPDdi}M|7gK%z`ZI@Na*_qdyw1z@-K$YQC)VWxU{9wb0*p_eh!AS=D+<{|J8DS zyS{&o(=m?6`TT92&!?xszo1I~;SYc6CYNsSDXyw^!>}KJ{IT+AtTp}qyK-8V`4U3p zFua}5c}+1G08V2-#AV4uB?Xf?&`2RhkJGzoeWn!2tj|vW&l~*Z24H`TB>SzA!VG=5;WxgWf5IBhd z00&~CpPs*zuo1-L>GLvQu9tIbLjfSAGa{azUpT~RngBo~A>uHdij(9JA|9;F`@w-APLI+&f! zG-p+n@z} zV6@T$)%<{B3hZ%|9zaxJo{@-Tv`A1EAxnF1{J z2#LgTzI-#YI7~#tmZ7L7YA8b0E1=Jj2P=aHf9(K^wc)PS1M!GK|C4bHh!o-kUESyW zM}ISx`2t|$I6219@wvhNJj?FOKah|;}WwF^?-8?o=5kvFXfJ}?E?gts45e)ZFC zZ{r7YSnNg!TftU|?^>!S`+coTrRtPRW8|H~a?s zx46>wc3P?Jg)DLggYtvh@4D5a*|x}g`8kxoR)|vduG;1sco(pG_tcwMWiLGGMjm(T z?)&cAdxUV?Lw9enq20&h-RyMzuK2)c&35vT?`Q#PYc5F8n)S+Gv>to&hg>+c`ya_o;TIt~YBUgmeR;tmxDF2hXTtah3>9RQd4-H9xK zfDaOwi+@#!qsIuCeW!iw5hrlTaQ}?VY#2||(H*CemM zFOqZDs{wHoNq$@B>suJ6ae6W^pL}o_migTbOht3U--64Wi=Jd0Lm2Amby2f5OU}Bk znTe<4san~!jA+4#RXpB**JDyT$`e)j*MmLrm-3*md*! zHwvMs-#mWIxe}7y;x(t)v{Y%AZ@&<8h@%0d~wk}BDV~5C3{MOWQXoPrzGOj;?8!XkhR-p zKZ2W{pPrtdp8SJ6?Cr@6-Qmpi^7?BWr#KwPaT45-U|Zq?`Iy2covUp_$zQAs(iB_TB$4&XCt zgI)G2fT;f2OM;X&C3$*!9;bsxUZgaGN=|F7>+JRGZ*d%kVe%`a5C}q?jsPVZJ`9t& zC$(Ftg)ofcPJS>Q_i?S({MPqMn=B%67;oqc&)vy z6aXNnMO6>SXE!?pz)zpQs3gf{piY29l-8wmu_5}mKE@aKZmivEAxI)o2+6Eu9{k;Z z^WUqup&Ep6xSoGIfBiG;y=)L+7!Mqxe;SocJwn9w`qsP25QjF`47YuZ7sz;rN?R|? z-_Yfj(7boxYCcFkXZ(YXu501C3^VBd@TSPIjTd(}k942l?!Q|%0Ns_SRVS>30dBmA zoe{dN4{ZYDevF5$D)|uHwmww4FI1tsj?LDtG%yM`5d`p9W4k$QQQ@T_Zpnx{H7z3k zRh`4ulvh`M+$9=zpWakNxF?G@tL5EQ-gugowwqd)4Ig*MojadxeMWKB-oEmE3%^s& zmrPph?xJ=5`V9ly`a-zdXz)&bf`7#%96NioO0w^(?ME1jeV9_Ydk5~@`kUKe4?+$% z0Hcjk>I@XxsH{v3`$?g7Hvs#uv;EMGHx^WB+T&EX54wY!X7)~P-D{<9@RF_X@Dw)b zKBWz8fwo~+CyL)M+PxO&?*A8Q{NB^KiU-j4s8p|E$2z3k73XdI`un}w2idXRV)|&n zhdq;}wovvVh|n8Tly~6)DdM}!|E7DjM^IK%Dm?mLH&%7q4vAZrzqhl$|1}-#fgfE< zc>eT5&9F8fv2YkPr{bfEY^ras-`p5_oTlmY$!mdM{^{>k z<@EH-oh>X8etMdQX+Yu-CyT&2sib%~Arcb<(Q0g?etXCq+X|d+Gg>-!R z5zLnBTTaW%)1jKl(&6;UV;ngIs_1-(qk&B)*=$`4st2BhI}j04&WqQrW_EsmN5m}3 zL@_cLTuWLy>6}#G1A8Q!0zeFOV@DH00RV`Qh$OGq_pe+6(q@%Bo?cu~?=Dkq2&%aR zJWWq80FdU3N)E$hCV5R;T`IYh8pMc16dVZk%sEqCukYTDbcEQ#mR8Bdp%KhuQ(V{Y zw!Fw(rYRBCN}uhxEpZUhZ?Eq}^oQf~J{EP=BGvbc!8lHh%@D>zPD`54u4(aEZ}C`P z7gtswQLqsaomHqR*{4C0d@@bcV?mCipvTAOyrd*43llL>h=e7IQezBvpyh{_kcTO@ zeM+-p$0cV*=HOgYW(rnIJYoesxgoZer*nc3-?LLC0`%dbs13bQ!5&S%jIppo^uN^*gI{uJhi}hnBuz3 z*Xt#VHc<2vk%%s90)T0Z#8gt!#Oa`DoqdsSzi#D%6ig+jwQaeo!eysJK#;VyLyYzj zd#-5-!|2I$s?rFS{&Kl!q#=;1;>PiX)t{Un?uxb8E7_5li6v(M3vmS4!pmw3ii!#$ zF-KL^b)}M1wy5eb9{O_tk&AbBjas~|4G=jDs`~cpKRAoke`Gj5hw;GgU(M7cC&{jK zFADDp_TWa}qn@4`h)UpcEt-fZ0I89bpWZ%b3sdn8%Sg0X4-n8TxbK;-x|!P&7AhBh zT(S@#pwZ353m;qbPujsE?K)4%Ow@jtJgWnHz{Hkw4;tl#BncJCea}(&jmCInR$YOwT_6+(UxRp=EQ}EF`>J2Tywh_^3+LFFF5~ob0WjCbz5Q z!Nhdm5mwviuKCQXlelo}v0M&lJ<8Nmc0L8LA*%u(062(* z#LxrZAInI6H{XT!)o?*mO<9mA1Xhu}%xa1NqFTbh%_OIyjtBFYl5*u0Y>_kr;5B76 zjZBs$>kI(s-Ch@#jl}D6^>^@I3R3mX(!ezjJ%`PRVWSB9$L5@LT|9<<7{ts%h=e#1 zW0icUS%^c7Lr!bXDaL_A^aK{rWL6VW%6MOx*?DDHYn>e(VSlc>yB<{4X*2KO5SfFd z^?rpBF<==F`v&AG!KEtWP#%3FM|WH`bP&HHus)nqQ*=dhIktU~2p9-t0OL3!Q4H?Q zw(R4dh{#QT(Px~VNmQoRHFWfWy5}B)RH-7)K+J2hrZs%HBx_Xc*79j*+0!f(ic*Rm z7kU2YE~DIXSp9t3O$W9jiJ80}a^;D8tb2C3_v}Py1}Z77`gA%qfX_?=a|kSoA{ygB z98A{c49rAkM##QB1`Z((y;t&aI3N`kdsA*%`Qk$LD8svm64!3mZKotm#27im7y>hS zUlQVoL@%E{qx*=NUM|;R7{+N*5tST`&$JwiW{dYf&v&b0m3*P>NW^wLPUpy3nhh!ISw2L z#HW%YUsFG!CXD)gnnNrpMI~Hn0D~GT&VaySsO+=jHl7zkhZ2xM4blVYYm*IFdm)^TJEC}2j)P` z#K9lUbo%7HYk$^Ts;h4Zs?H2|Jc&5~J6~g%FRz_WUwcW0k0({c!?!(W3X$BtPV)u! z94IxZCM{y7;U){v!>czAR*@e;IU2F(qzbLpO4zKgcLgwMdsEpo%i^fvw|6im^kpO> z-VHer2yZ-WJ_@&cNU3rtUq#g1)*&KtVSWR+6TGKBo2ulMI0VPy(rQrcCu=X~X?E}L z?>Xl$U%sfwx?T}+I=*ZJTPwxEynK6jsT&_s)zp>anAYoVN=XzeW>}HEye#uH9l|h- zLk55tCnVxwGF2%P_#DS^oKEX3n_tjfidlnI6OOqIj5&%%DrPpFh=`nW;$E-KF47&mdYgO?FZ8YCuEO1hDE5GdB@NjlW|~*~9a64CMAlh# z^n{UewwZy5)w1gTAS6Wa@WPV9RP{)Ym}2G{^HyLp2iLHx7F%=E?I2Xir>7H^v_J3% z1THtsX_}^CoO~O)nd6#4N;$?bPSd(9>$>>&JsuA|j!KP!tAe;?e%Qme0}+Axg!&G<@7b$HtBgaA3rP+HG|36|=b#e?u9LTuc<@o+LTq~O;)98TlmdAYu&Ww!(aF^70~`i#Vf)2H+6FY3P2BGc*R z@cbpOSD#*)+41EERY}Y2{$E_q<47Uqb;)V*&yh5n>2f{${tSQ=f=ZUOa)`u1C8+?1 zO{uk9UaO~A2`t=3Hfhc4QtrmUNQ`+!BJXO}`GR}X08<6e#E=YT;luI%9&7r}aNF!7 z?*PQ_^K`qMfg7&vKZhj#JK6xis>W?QlfQ1Y%4@u6yV0=s1fUx_Z=;GB-0cq!Y4n?I zREM?^;Z0C|ff2AHnpf6Ft@!$#!%@Wgq<#D7H6e|GP4<9zZO}~d`|K)g9zgh*v$1yy zuq__qW1Gf~gbw%dAb3OIz6A_7eqIj}?Gr|t zZ+M8PXb%}FcT!>^1T)%D+3j0Z{d#Ghdix%tKHLBieNsgLP?HSw_AXVl7&p;4S{-~C z7`W+(?c6tA9`Tr+gH7@M*Qlg#q&!H>uK29gdS}nrF1K?Ys8~pWD*A-cP5@pkk3l=& z!W#vL*nDlcCU~DJS{N1R&a@jzu=D10sfh0w_%MoOqr5d!lJ-V-;T^Sy+{NoOK~Nha zm9qFD!{q_!T8$Bk`)kQxv>q&N*JSqb7HwN=QIYJ%E4;TDGjk5%Rx&o=|MujtM>3D{ z7^|r;)>ybk$J#CfDmUlWC!*B8-=(Hi6}TZfAZOk&@2F@SL)@SR^J1523EPcO6TKI6 z6eu$%U(J$JPAgZ|^7aCA^cigrs5W(HZxHG&IXFxBE;-X{gj-|N{Y!ZB?_NGQ7p51P zzC0bgLrv?v%Q>;voJ66{!#OX*PW=2RHqIv@-StN%zww-gH=QxbR z;e<|buTf{c00sakFmceF%v7rRWRC#*8d=tbh=%dNanSYztMJPzEN@y1XvFG!_m(Bk zYeK~5m%-DkISe6A&JvXz%uGd0<@oZ0iKKNg({;Hr^EjQ}&*%5wzA+O5juY&{RGZtf zS8@^^I^`UgaTq8BNeRHbB^uMxbT}T? zp_=!|LH`l~B22Zh9S%>2=P!;p&F62+^<1n_;=ml1>zO%l9NU0#%NZqNj&V5b)o~s= zZ!xmB;LPL_timoq91l;#(c|va3=D?p2t-tux@%^f$ZnF&ERKhQCz&~Q3oCu24p7Vt zB&|lGdFiVY$$7cFaU7@PvzevkDrs>$7-(**nEu$YFpM1H{QlKUJA|Nmn9NsahasTRZsdj@gyQ?VNEa5sJ~c#U zHg~7O>G(n%uIFzE zrxQ?a^uJ{UQ23_(@n0D((B*o;Z9?E?s#V-EY~#Xjv4vamSG|(^{4%_$g1XDZ=5$p! zD_ez8Ujk^QRUNn7ayf1p6gx6`cP{N*wmiv#D#ru2mIHSoXM1AK&IGBk+i?>qKo=F* z5v%>ySWn59P48@b^RkEbOZ!-a{=_XdYrPHHM)^nDnWJ^RIo<_oBW_l255pfGgi}09 zi^MyHaVr^H>Wlk|0<{ygNPr&1%I{itr<=Fmty_-4E}stXWhVgr-F+-{wk_syOVe!K zOwXk%XS1p8-M(4d@c;lI07*naRM>ix$6X*p$A<4z;n=8f{kp2`BcS?@``G5K!?_VDGA=PyeS)JeS1zKe{7$C+tIDx#Uv-h1@H!iZg z%*gBo?CyBKnGQHoyq}Ozh(saH?;dA$vp_jSzl_=o1|m*rt?@dj)%{jf|MHiTndg4H zYm$_U<)Cw>Q+AqfVe!O3F;YsJsxxo>7X+|R&j(dq*4z}>Epa|D6GD=bfq*q<#KXkf zhxF!2F?cv)v(bX;Y=A_-M53muZXH`f#+eae7(y1kTowcH4{2D<5IIJAeVYy7)2Ejh z!rsFZ%~Yk3MBd)cm+R#)4v4TM5z)^thb9SqJFor5Jq{t1_$OG_EUHMvh{MM=3vkW@4(yOh_d^vKuy+S6H%}@u_4}IiKI>>(#mb zW8}76>zd8XS6#n`U6#;{I7C$yVjv{?@eh9+htaPv%@+XV zIP~%fH?_FgeCk%P-LC89a=D!Q)ie%)34eRNY$IXO*l8g`sL4VGm$?`jG>hEBSb|dB z|s^LVL)PU=_D8zMe^{^JIv znt?}Q_~Lhq?X)71;}Fil)U;BF#KCEC>H6+Y2(8F)oIrB&x#k8ni^TEZ^N~i=u3WKw zA>j4}9HAO0hJR+CwsS2re2hNdFkkM|>L2!P-}UUVTTP@rPyp~i55I%o&nmW36A>Sd zIX7G0&2$aAU^wig@x{oeYh7*`y0)20wK<60HP2hwa62Eo$@K;-oc;SiqlePs{cy`3 zYm|4fWZ3zMdre|3D8zQbinV4jMTIWU-p$o)v!vR-<30hRoNx7TZl)@vfh+k5nM` zT@0xYmU`T5V@H25x)~|$?LJ!E-Tu{l*eaR9$FC$-r-H}k{%}7C?|c(#p=5U#@MsnE zL6)_9u2g31!!Nt2cI(vWo+DWa{oVW@n!3MNZ{e-!`f$^c)s%3_tAH7DqfyZYK67wk?Eb|N zmF(xXw;evKaCDxWqfcz8X5z%$enxl?_-?pRVVrI-W-nH9^P$T4KodzK#r036j2r;K zj3fN*pGM6&r`aFw@#)2J|N2(r&p-bhLiqIQ6C!xb695vYz$t{0Ls;gEXJKcNaXP68 z;*1E}_@vp;BmVNsFJ?LnfeGVyER;Oc`TFi5*RG;XSyGbY>4Zo*Eg~{bCsRpj0f0F8 z*a)uke7Rf?hr={Z-Jl)-kX2L-k)CU5nbRtH32|TwKYlsDKF^^$Kem7W;m4nT{F@l! z2ncDuipVgIr6x5!yngjM)CB`^IB*zpUchXl(Epu9DBJNj(8H5;3bX~59I6b|1 z4ElUIU(au!fBc)%%MZ(ZF>{jbV^5nx&Q@vjRKIna6B2vrs>vE056yoR;EbrUg z;XbuwD8#_Qz)Z5gwH(JG2FdAzvh8;0;&a(nD|iX7c?G2L`0UI;AO?s&!RkNC9Rr-x zGaXJM*&_p;4X>(Se)vo-zye&COQrJKXO1BRW~T?MYp&v-$cShbfN7v|iIXtC)zKo}P#ZyJ@-yo2W=i>3Y4!z#&i^ zCJw`LeK)Xidg2iO@gM#^g!ue)@&`RkBNSr+w@QG#&b0)mysljeu7zPbd5)j~$D!D9 znB}yX2_YHS)90UxprUY+ljbZeAX3~CB%7HoS0oO@ZB-PS38<-N zD;Yjc(Lz89Lx6TD%oi8unAs2~Ky zA)xYn3);aLT@>U}kmBIql7SHr!v4fiQ|&Przfs|LsFokWT)Wu@ZZ+v`*JHQbsycy# zzuNPwMwH=Sd!4niwWeyVwF)z%sYTftak0;o5`8ZTxUc{&aV>YRlp=I%S#xxMhvQ_XfX4 z#395GBLHeh{%MZOnJSmu9pn&*LkI)M!J|?+1e7usWe#9w%I-Wz%pt^L=;|`85SRlI zLD@I}*mgs*at9j3Y9U5dDg-M^#O%&5~VVfpPRn`lxOoy0x79j-33~Hw$Y|V70Nv zoza{1IwIWc3W!j#2ULA*=KlcDHYD~G6r`fpH0Z-2eVE2XTE8PPlL`@;Vm0uF?a`P$ zU{tr4tKT#3;&ocBMnvXs7VV;)s-BCB9~|}LD^;WYkgw1+DnXY^=9Y5%i@g_@-vaYF zvX4xV2+_7NGBPnBxl1Y$70pBIuJ#jjuQ{5zoo_N5-{7`U+*3q1Iax`pbBCg`IY~n1-6+{PvHRU zeKqX&Fv^EC=8r`X_85W*H`4XqigWW$djN-Sd1Icw=-e|^@i!ldOYK<)fra3!Hyn){ zRs%I5Q9Y4d4WsuzPi5ii{U4h){XQWDFjY-pmUAkWZ^X##%}rV^C7zL}5vhBMK=}%Y zX2u+e44ZlyF&2v;dvrX1FJ4h(^+`amtnXQ_FPsXR)-l>M8v?<$FxKq)IvyrC}}k?k&^$8Env*NIb8Ow&n9vwW;dm4 zQv_2Lkt{M_&q!Fg#7ngqDw<-+B@~p9+|o}Zd(q?cVAq(cM5wm+9S`0B&^t&^8`>4N!7+ z#}q%|?%*%vI8-Z6h#dS|bX)mAoZR@zw*@c@%x+y&;;}dY0%v6wkqo9VOf5>KB$DrQ zSCG)9(-j-Y9ec}&XbY6M%U&_Fah#|N?=cn8RG*;i2903Hrx$9nQLls){Ko<_adbX` znt6ab5>W{5C1Pfp6EP3tF{K4ekpq=<^(JX01Cu<9h^it6=13fgqr)4jf__UIq0CjU zA?BPUuU;J!RP{tC1a#QXh|MeMr$$1+t7x*6e)D&`XuBH|#L5bQw@rwWYi z{U;90tc$;;?7jx=6j8}Lv#xE%Q_bIejvu0#<$Nuq7!Jh2H0vYsCouz?>4U%8C$sO>)`*CvStYfLQ5CZshS4iwCrT85dZ@kKIJx-O%v93l z?YG8JBnnVSiGUn(TCbP0Z?#&ostF7vCsQE~W*{nHra56G4sp4>E!X#9JcKx=^=ie6 z#d|Un$qsJ2&dlZB97m?;VdW_$Rb8%U=6E{RjR<70o)x~#E=h}dynKKd2KqmWA1qFW|~S2P_nrDR`_-s$7_CB){{1l4lH`b6)JUXOLi z-Nm&dxi=f_xHBy;&^A6uvEWifATz{ANoJ)Tw2gdWdn!0??j+Dz!gd@6+r)Cc> zihB;s-iBhkLBE^-vE82g<*cftHH~+F9`w2Pws8kG=F>)c0yFi71AKV`GIKHAMJA$@ z*Ro$D=A1=T)d);M`%4m4&_0jFOJOT+Rdp>DC%hX=#g1ci_w>3vnJr1M{-?Sy3dUQU z7mHVmcYeNysv4l8k={^vtk`2!YF8l>78`h#B9PtAP6ae^TXY4gwrn8el6_HW>4s`X zXdnW%<=Q)zFCu`s#bP#gl6&A8h|kyi_)>qrth3DZTX)xuSkK~Xi{WveJ#;U4dBws# zOQ@%D?WuViQ>5@~T3!h=6$OPao+3`VVTvwx}kSjA7=DB|J19s z4-yf}?+)ENZ<;fQNE{VWLEOWy=yRF-dI1rK=^#1fb-{|DiWc?ddVRN&Yr46nmD<_; zuZvXQZVobst*px0oag<4I?9@Gm^dH@FHBU$B$fV>8Hm>T+&HpcgENO^o|o6J$)-@bhdAwIvbvkxRK>vHvPJB)`oOb=60 zRPEc_^>jKuKb@9kzFyywXv%U(N`!~QkvO=bKbL0rLL5UF%Um-I<8=7TFTbkl=`e&q zmuqrYNd#EeSC=B>EGc=B2=nq45uaaPLWnm=a!$)SUv?dpdUgT(vL+7W@fiS?%bQnH z9ES1uoR+KP#my`vC6UZ=0M(M09R|l_a?U9Uz}oglNvmQ$Jbh9T$NfYSAP{hf1C0k& zF_B?%R5q*XbxBe2c!FXJ7X}OJ`=C06yB|!OsXO6GP8?zw#{S_}ek!G z&*~(v)e-?rGjpV2^sAlEuj_K|y^p8EGZJGMz)bQ2ikm6`sqxNSYvdAdck**xe~5!0 zn$t8sJwF=|B94a>$Kl`oAOB0a2D9sus&_;SlqfIh*RNky^>i4`Ow<7Mw_kth)dkFi zX2<6*%)CuTiDMicHgBx=YKc%Nb#9}KN~XFl*Wx^-A~}txm+|=IApGI<2>`<|GKXLO z;r}*(dC33}nX>AdB!(jJ??+H(@b=r!W|p(|m3_{#iXN6_95^Lu7Tca{QS?rtW0b=r zDdjau2t-J4KmTl19JOX4#6XCI$HNGqh;X@HFV`y*5kVFMfTL<)0zi@c?b|m4NGU%* zzkIHGi82%)53ZKcV%JPzm~I92-u}wG1%VN*=Wp&@>VL>gM8QyM*e{A~W(%Kw{M($@ z<^1YP#p|K8T+(t4 z1c8`?NLF!I;r#s5-%+txv-$E?0@12>8gbwdf)CmR>K`%~aEL0BmWvZGRkC(|Dfg#1 z5)n_X4+(J`rc++$y!Y|&#Eh_4s{W3Qen)7w@1DXR%ro(KKYbq#2mhRZu;(2YVZa7^ z?lc39$NwBGH!(MUM4Gs5KCH`m#JgGYoxvU6I}7;z zX%lAKQRJ=LvK@SAcH!3dUtK$Vr@_9Hq~rEHtW&8sJ=`tz+`d0;y(=3#WlNW$_mT5L zC(`&x_4v>`@Zs`oLVx>E>1!YGx<0lj>qht;Z>vRKK?&HHJ(S+6Q*;j1PdL4Ho4s~IERulwfP4)Fqp8#t6 z$J(!uJ3Qf$*YW1`U{xwm_3BL&yGcp#k=A?be>#AznL2#H{-`}e6<^@?Ot*KP+6~9e zm$Cl@Y!Q+TmT2}~_j#^6gNobj^kEbs{HGdVK3*3evc~{F{#y@-lYfmIuv)Bb3@#38 zrt8x8#nsHoJGKN!X3{Q{t*v%hiM5ydr3ob(^dpbEAiq)VHcYuuToKGa7F; z%B2p?t1VZc!dz-qxmjof46hCjPoKQNoQ_Y&=g$sn98NC{$r%EN;Cyapd4&*$moHDl z;mJo1KmDXC^6m9?UDHp0_+vwdI0Wao4~OUR@FZ!LoL-)$;wb2@Z-^X*fcT&Pn`g-> zuk$!g<2dEKYED*Kv^lMII6kWitup|Q(@FBWT;HXN`c?H0KmFKl`*e5`k?ZA*NS}ZD z(>h<4>l+gRgPXT`s9qt<^vV;TFcG`4jid!YQxY>91|p($J{Om2)9dARIzIp5U;JxR zOUw24K?C^ol*3@A^Z6CP3fZLo$S@uoZpk6!tj=9R#6o~ZCSnJvoN4v+=`(YD`}$8D zh7ckk9!@{pFX&F34(og_OxL};UVokKe>%|#iOuZ#_M2)^7XUy`Yg(7jpFgz;+%mrt zkx8}+4trQ8$H8jqf&ru~A~r-OqH#I`*iw6LB8GnHB61jr$T=GImZDm=wa$z~nDBJ^ z{0Bg~zW*l44KCcx3*&f@yvi~ob8+k6Or=*8^!Imq`C?}D_M6{-?|suc=j(Z0E`a#M zAODUyeE#tdIp<%0{S^`a#h?CmS?2kA9ma7OMyHa6@#xrqs?6tC075WCh>?k72*deu zIbW`UnF-hV>|zGT28cNf2LRBtK<9*@Ihn2glDbXfU;gp`qe8i$>2MO!oKk-K?ehMc zZve0F3jloi@uy)J0gwZKI-YzFPidX6*APMoA&v(QvGXF3v@S?A9fOCNP>5le@^baa zdmnt7+1GEcBI}?2=8yiei0GgH@|Q52PM>~A^Cc}8QOjBW@Z%Ts;0Wgb=imRkaU6g6 z;fG=g3A4@V>FIPj9{p?n<(FSn?Qr@$j??+_ADC$xBO(psAr6OOI*QNfC9CATTpN_> za}Y;3Izj*!?ik{_TmUS@$ysJ*n%5%TN%KV{5d~uQ)#Zsg4p$tWzi9V3?X_8r0+!Ye@DjAZQFHy%BU;q3cn#!=? zD|`8zN=oyCN^?1XtBD!C$#509a_JDZNvDa-tN)3lWzK2GMDzW@3=qR#)zRHnq4>|~ z(CUB(zw=}E{Xh8lZ+@?`x~&*)(B~~Ut?yb8J5%Rf0Cdag+k@auhrem_i<%qUBy1l+ zweKD5A*z3OK3?>n118QSN}*O-BhVEUmQwmm4Ru#N<1^A~8v=|}aNb*keo#%wQ@ z?PKqI<*@B!1AV{tu&emkkbT##Jd~r`?vHV2BWCbD*YF2b=C)uys6ICjfx7~>xQIV` z^{l!`@mEif+5#54|L1NBA?f zE;zqiKjO}f}vq$uR!OF(E7&>x5vE) zAvO)Z0U;5w5u2KMn_3uxI}1A7qJ#baDrwm-tRykr#_s|?YSZtLF*CUFiFj~=;6wDN zf1md$#*!QP)lBal>Uwfoy$*FY!OpvjxNpV4KyoI+VLIMxAsWTGt>+qxv#1OV&xobxIY@2PAx z-E5@8Y5nyt0LmdShn!YZU9Rtl`1JBq&g<(mI2A_93ZiU^`xvxp32)A1P)*UOu;96|N+`YR%i$L9{w#z-d^0WV}`*SBxi z_iu-nFQcRof|-d(jAQ&f`Ofdm#`Cv7gTe9TOBlxU|NDQ1Fg!oK0Q$bcMEvyhd^$Z# znsZt_l!B4cI-uywgm=Df~1t&-OeMhZof$4o=y`Fcj8I2@du zqk^@vKn)zy{+>&TaTt*nb?tFb;>4cd`3Jp#eoT$JCin zroCB(TWS~+!Ur9peMbQIpeDBcNaOwh@)F4fr1*PHo_((ueTY$id}R--Oc8N`Hguuq z-3eX7qs_>xC1>n2nKRutDez8qZDzb>Yg8*_L{J0Oopo7_tH$qKWHHRbO(#5HJ|;4RgVPNUE!{(?K5Ani_X583L_GsG-@>v-B#Z>$Vf+vec++D z&2$UL9eSO6jVmG|Hr3A8p}2|@k&A!&Tx!I=McFO>!r$AS+EU7Jvs>XVlDi_9i}s9} z*-RyiU(}}Ib1SGClx|1KG3tQ{edOl=1!}q;r!D`xZ0xpBaZZu`xYY(7?olilpAlWMgGJ?gx%-nw$ z0A!9p7NfJ*3;F9<|Z_o?8?U}m;13o|=06%n1TO$f}Ck`iMa2+7>3 zxdlo9y&V7mAOJ~3K~z6^<i_;sF%obIo#5>uPqHYKa&EM|U8 ztVkG#k-XRMkV1FQ;tz3)>#x#5HX3uybvKFEXx7_fsqJeU?xauEelB(5fK#; z9mg@oSVWM%kGNlt$L@fEfEljqnz8_bAujWbh&g9fBVGw{7@|)!MY5zYLTHoEdk zL<~UHh}7R4Q5BJt)gXx&Gln?0!Z(gnL_iY&+;ksU`<{9*d&}#|N**BW-yo+25QqoK zDXnw)5FaQIf}vY3xRqT_i;K96)Q=j3Q!ueG9!wR|>U`Z>oohuHy%9;vwUT>lZcf<( z3Cu*&bbKkj(Q=&*$7azIr(?fkvgh1xbrLof%wEgy@_%+}C;)_ELL|v+wV3hBSpjTa zZCUd$3^9fgxV7o)vLLcIOeu>R5R%(}6A^P**Tu}%EMSnc5E&vFz&tO^90KQ@bIvIn z(mKWf2+W8`q6RAIe5nL@mAvMh{k1Z43k#%W(crUiUDk|<%*j+rX0oWSy%LVSENe?fGZjJz?ii<<+^HZ85x~>U2mmMq=IA8(-Z3ht#jT`#y>N)*R20Tx zm_i(LS{mvvrp-~W_|$lUyk=ixWzTo}z4?sbmJ7v^2a$%+5HXGu#Rxe==fu*{PHJA5 z8GsGbF-}L5+~sL#1N>ZiNgO04$!kpqd#~!!o^A~sM=;In?8a4|)mr!G5@GN1SnufZ zfqx-kv3JwZzZDw^r5m~Vae|C>DdT2ivBUbUr9+tNHaV$r_Mm&T(~LOQX}R9SJGv;s zR8&d{PZR)AI%lkcqx$PwW3g~2*Hh@k?*;qygRuB};SQWZjCnD`Yyu?}K};3Rn2?#7 zW3|T5q>b+o{dup;vMiTj90z717ipYL4H1|qWeGJEmdTMt{Gd-W4ufU^T(76mmZh(wuIJZj z98bq7rIhpHp8bb00^pjnh>imRpnE>4O3pH`xeW^m;e4K3jd`4g_Q{@OfHenTj3F@1 zYXXDgVL&9e@K0;I8yR4!p#jE(BFSm-s>(#0N=!x7L^Nf|qC^Np>oS|cnhTL9FcTh1 z=%b3N<($-3PcAqfA|lR9QZ@gCVzMJeKBl^+v>uPgVHjQXG98Z;V&OaNb%CY!LIfno z28ja_=4Ey-8#BvkCT2vCoY(nEoq)^>c{k=C4=0DU&5V37K};b~HM??K&NxgeV)gji z*T!P1#Ie9fNNKrjeMaYGR&=)_$Cn=vak;#wv`mL%`)YAKsBE!_A&$mTC7VI-^ihJ( zuq0iWS`A-iwTu8^m^j4i>ryx9`u9vlZC=taOd$+J4I{zpPIjhHr#=wX`IIEzj zsaX~!#BoT4Ii)55Dy!B&llvD|^$LLFGyxD$VU&d7fB^I5twpiNaWb=9V_BIa52Gyx z<(rmjL()ps-^a|D1J~Oa;^ZIFz>*TI=$?ou9ELDXvMxDQH3cyshBy-Oa(zc4A5Rph znZke=LhuDyoJ8GXhPc)~Kp|GpLQQp;p29f2|Mq7v=||Vd+^kN#DA&A(Fobbh&abN4 z8v=M+7vh-Lt7olj7AQVelj4B@#BTbi<)y&eaa)B|!d;Pwzo-1QjyC+z3T~6RAYq#% z@3G5zYkc-@PG8zG8>~vTTy~0^QH$*XlRXDvqj6JX=ijp!8YtwyqR)W1x09>N_M&e! z5Qoc4apAgJAl_)oTc$X1Ffvv|vYgiTTZZvK)UK;h4z$fjnIi&uNG1_h2{{4+nl|i+ zi0^n+HIST)44B!y${%LQm2Id*x|Ca2Hjx&7?VhM+l*Eq#cf3$Q_2h8?QZfUg#x5=w zz|@;J0#}zsGh=46t(rn4W>!E$B6bH)z1fc4#ilJ$W;8eR>ufW9s8rKLJ*eDJfyhwZ zbF=_ttnBxnnd|$I-0um=P}Ngzb}aO|k%MR4nR-3$4wQ|sAfg7jLQ)S1Xcf~T+~;04 z=Znr5;f6G}g(-MMPNlJ^dFY-SI_M^GQHPh!wb$>o3!Tx#o155#g(@-(FXZiQ;2msoF2XR zRBhEhV0D+KX|~0ydZxSqZXLre)TN~UA%1_9*Ym=@Gjt0*@o-(vAq;K`zIoT)4k4`Z z_(gI~ONc`VLwyak?S1FBR}Nu19J`)uhgGKeVgNbKX1cE80d(^h; z@9%zjEoF_6LLf6pS%PHKEFz+IzFeRN)cFsejziA*{B|Y^|MEZkS82^z^bp3w(+_#M zrZj*4!{7P#O+^3a|MtHkM~-70rvLK4`yb}>+x7faau!+hvPfRjaz?;UfB4VBFoig% z=5>Bok;~gR)123tn2FeJ$*#+T=d|QB69q8%!ymsOp^2E8Lw0#xMDqFa^LRM^@a0FJljU@klun(; zrrCRlBkX%Uh0 z-~aokmmi+L{3K~r$;csL%8Pg_`Y?GIY0Taz%^en{bO+~xI`CVcD< zjU|6w*LA*Lr^9hN9El?_$I*#n@6Ex$M`gL?x}u;dpA78it98hr>xk z*7@K5|D3(ql59(orlqQ8wgz{Ph`rC0Q&mwtNwomoB5=WV-|+%G0tj649w2?iTR@BS zW55+6%ndY6W@VkqJj32Gx%*mXrm9@1nJrr$v9qK}sXCPs6~`lD4Q8gQ|Ns4A7(yr> z_F+B^AUS1vnOMYJKm{plLs%nZ0l3Ool7s6y24u}>y zpVn)R*Suci^*rByM5OidB01S~kc|NB0&})Nq3v?{008UtRXC4_I}uBiEajw-Bj^1v zDJM?rW_yPcHc5!aPcXI|g~1I|PHS9Voga$o7cs5ZHepS18Rz3L%{~mne6qKDJbqA> zv|bGq*ZLXf#~;iYg6Q;CD9{NU@@h)~IcM@f73t?<&JU)x>TK-#ciZ0e9hpq8kH=o^ z0eb6O#Tz5A>X&~48U$HY3EzOwv@6`|IT3qKd$0Q0yC86v4c4Q}diT8cL+N)t(#?#q z`7v}0qA!OXt%Ff4LrUhv2EpMhl1(jU9=MjFXVj(6@m=%wtV@(L=cE9fGdmJy3!t=t zU+GSFvUb>|pm#X<+8xf)6K5_R8+#CqoMYZ~)>hZQeP4qT0u-t2{@sPd#zF<3g z!8+7`VkZ`Zas_+B!21%g&1a48paTl5xm-}d4t<9=0mxfz^1ez6|1GUhU+NZZ84GXZ zSo#GAR_BI6+{v}Hy`xneg>P9I*f*$J9-iv0`l)|-`U~SnB*Udc6?2 zkKg`AI9c*Qvr?FQ(FT$(3<#*MGAR8JhC>*qFdjHZ<}7Iifbnoo&L1DX70K~>1^_oq zb`Um%Pk-J0Fe1QVXACp=AOHFv{QKYi`Ct9(|K)%9{@?uXzx=bmByybAH|aSVro(Ce zHeSzhxkygJdAYol1JO9g<>Guee)v{Zug^a(%lh>E^zh;1!{IaygXVa;yF_wF|L8wPaxb6$;K%XczcK%;X+3`U?f=F(J^t`p1pLL{`zIW)FQ5LX%qgwT z4}P4_uP-l8pa1GV{AYjukN)Z9`DYcryguf*{_-#Xy||nofBZcno<4r}^Y{Py_y5=b zXn9Yf62chQv#Jim+``J+12mmJ96x*)#%Y+2pa1yV^W%@p@~SF6t)Tkw?Qc}nAWUJL z#EP%woa172B|8Dkrw2ez8Sd_Lzg3uxgZgHvGxS7UmzqInm&>5%J`AJn zjcHw2cmj}&w!R^l8-6s2T0Eo-wS#q*s`}Oq|0Ol!JMeBt@*@wZoA-}#@ zMWvFv?xwEGOWh6xgkLY0WmyjMU{g2ee0<47#OrIkUUH0B6JV;jOFIyzS`&UcK8R$=DU5R%4{13!cAEVxH%ylF0yPlV zo?aF(1+`y)B3ir+nOEnMau*4VpkSiJ#tcGW;TSnt!s-^!i41a{b(sPzP8R)o^L z{$g1My@Pkt>)#xG_Gwrp!9zrpunCO-NqT4SE=7GSG6Y0{sIMLOb!7AS_UB6#5eqIe z&F$NCFKZVNb@^T!&kEZJqDhHcq;Q#--qh;Mj3rruT_B|mpH#DDHt6;~+o>^Po9w|jG4%CG@4<(^n^vLl zZvi)c(@DC`zr?o}qAzEmA4k4JmhO{A`hr7hh1dB`c7-(77qMLYI)8>;+QOSss&|CH zA$WB)TTvVAeDDQb2(1XiFFi;tTslG%l z=}~K1Us&z%=+IYsEnH7`iGRB3J(^RY?63Pxp>8`SZ|s)5)(h+zCjWo_qqi8!n;5cx z@z4MBYFQ(j{g@7CD|795HH?Uk(=L_XMB5fiZO>^KXM5HZAPkd=m`vPa*enC6%8_+C z-Xmg8QACF6Ae`fJMu0FKtJ1;Q8H!wZef(pwLm`^8n0x?4Bcc(xxL(tG<+O5&hKp^J z;p&&toFX8q0y*c1TCBv5TB6P5QDaJ_OJ_8nxJ7BlML{hU$$5|Ds-`)czSLr6nt5@Y zPv8B;Ujg9x>5m9#(Ld%M1=aJ@&nj#!#OZJ%=cnU?s-B;IPH9=suQmzv!|44W!iaQy z_}UNS;}3s>ShxfwD7Gf9{rVsM2jBeWA6{P`RmD={*Yk@i$Lm>`U!Q(F+<$%d)h{_k z=6wGA$Ls6ooNE3N^H<;fnmH|(7aK9!$vlknFdoc_JRR>Efy@g1lJ+N=(BQ(HbIvR& z^WAYGD$1tA=>q_g56t|xfAiPVIM|`Pm>;SlnORgd1lK#~Y?bg~^uw6rl5@<70q}6T zH?6iYomFLBF3yK0b&Km7Q*>2oq#|Ga;x~3`7UA>ji`fq>eU(|5&3=pHG&|>BU!J}9 z<22i2wXX4UxeP-Xf_v+`N{L&zO$eTx^M0^oI3GrGp=Z>E@n8}5eWi81UaptRJdGg) zI|-O4hnyGTxL!cPIlskPH6fDsn_!JI)U4gxXBytnIs&OQJ9x6X%gJXB!| z-t-L1%`Hw-ghs&V62-O83RaElg*hLNA6jmV^Mm~ttJuOgyD);Xjp9^fd$epuK+bv3 zIhR45O-aoWfux*~(4sJGqzX07KF5`F#qSLxq7w_CFX}IDZX6RK+g*EW7z98U1}%A8 zWx!M)QEaTyK4ZPlNZt<{0Bs#$W!)y z2*U^^A@8kGvNokvJMq$O`=&WGOeR)?h_NX!JHwMnozeMbCJ}uvMGb1|G}PdDB!?=f z1Vlgt+}j=;b*V9R3@-ISEG`jyZ8#@HBJ!rvgf1S83k=Z0m@?=PudiFemZ~4e!s0_U z;JWpK5>c_;h$FYQ2@;XxGRM>kDc6nRm|@149Do5pR{vIbXaE< zRcd3=+F9CKJ?I?D9^TqbAKx&#whPwkcr129xaDazFE18N`Tpxp^wz7|CAak@t-c-m z6m1=WmaB!PRi!IZD;$wrYe9E|uI+E`Cfi`iQOc}jXU&EyQnf(0+b2R)S%gr?LLnTH zBB?5>?gy#;7!}_XwcV)v3nSG{#cIN(UdD{QnwpSES<4k@uUMm1mutekq(aMMNumN$ zO>k9MZo>RMc>ucrGTZp1eC5qMsC)2UEt%iD2=#k?F#TRy71YAS{V>}CZ6~`hPPH_& z_)RivNLm*FAh4S4SR>C^x4e5$QHw0Mn8`5S*}1?rd5D(~qE?ZUDhQGFPu!ev!s?u)8A2bLq>EHPYW2A1<4iy9ULjJ>WLhN&=uCWE55Qe%ML^L?kE7&iiSet$I_A02+p&!n)A=p;Q~yBu?aN1C>l`#hj1F zgCp|Zsp>T5;9Xm-Rav5XGCYXZ56TX z>uN&lTI56}92-1ZWE7(0ERvlMHICILNY>KBX1`Nm6)k$##>-TDNlRafa}wvx-=dGEU)qjk zR)5LSumwI0)8Q_z*R(EKSZl(79XE1Zp(5|nk|+#5pbz8W{;Q`Set&uSM4MH=bsV^E zhi=R0Qpwez-D4rOU=BigObZXF8hh(Pp5o%X_u<$c?z$01=RMSK<`$g+h|YnEA@z#a z)dypZ4&wm;mgSmrp2o4+gS6-cEDKcAdReb$TPTkY-^_O(KmYN!#JpZ!s-)%N`0%y; zKFj$jEob}nUSD5w&R>1?RXa`l>1cn-eEM+r)h|=LKL7N6gHG9Vsa0(@&L>rg*B5&u zN~0r;y04;~AIx_z0wOBR!r4d-_DFD!D(w8QiB8FhWaUicEZ5h}HpckKnakL+{#N9i zS-(ZtICcyf3!aKv*GN@!PDIZ7u_mY?asWw-Iv@|@T&0;xlGvOhRcioxSy4Zg6Zf_#gj1EWM z^c1F^V3B2I1EF~5g7;yV$Ok*doiCS^d6*6b%_@@PCHT>Wq1di+X3pa{8=nPKn=qu2 zMnu><=jVepjW4gCR3Qu_krz&g-)9a$~NL=K!!%f+?;1uz0qPN^KcoFf-RRWtzxbRIar$(bSrWo9V(G=$_>Q%=c* zb;8OlMp{pCK_rtPm9kis)5^(=69vMT(~9H*j;fH>t2oEmTj7{flmbHrB1hm-T)ZE2 zJb=jM`LiF!FwAwhE7pXsS4K*+Zfm-j$bn7!#>^HjSg%!3Va>^&DH|H8i0ZESVkZe- zvRIK2R8ef4)liUSqrzP{Ru>{s*smrY(H+jNnm|ntZJT2K zvO3i+!;URc?ba?~yNT~W9&}|J&nH8Ks#3AFgeo^~%U|w=D$Rjl4MiIwQUzx; zH93(Z(syGA%ps3d7*|M6IOnw54qE4_R_`XQrsfuBMum^FOIqu-M(xUOYtja^+tQNl zlIn(UF2Adt0?RE!hor!Qgcg>x$HKjpWp{|tE=YZAGqyYW1s%73LEEjWRcV5_$MAnK zu4Koz+(!m>_|ltv%664Rg_&C;tJm^ap|gp?IuK=z(u1l}p>nm6K(P`Ei>I>y=c;*I z5kWw--eLud{IFvwd)muUQ&GU!2J;EjNt+}YA9nhQ4rrNHw2b2KpvLkT! zd}%KUdDAz>PA#GvZd9qut870-$=j6I5qWgZR#7C^jA77t7d^vM-^h-z+~{&}++<&( zTTX_2Nk7sSD+R^Uz28zG%brwDrMS!S*!r$`qxdVCUqn3(xR6ZVnB23Hw_ zaC!L*fSjUXQ~WrM^C>Rp>&s(zLCLuQMAw&3|@RU<-Py_AOJ~3 zK~xW?hvS3eoDg7`k3@dGzBXT{wWPv)OzSmQ7e@zkg7I)~ZxJHScVC(C*N4%E(L(aZ z`D6{5Mq#if(l8#z!`<=W>*f5sUS0+l%4!I3|1bbx3p%hy1eVDn0^m5`4dc=NpN~KM zF30ts{ImaLIX`{+{$H!=;r{E#AAbMiU;m$Wb{odINe1p8KGe}^@kONdYJwDHMgUG} zT`rY#od7hh>-L}siwfr~IhsLUB*!(|VvC5cPd}CBI=SQh*D+oYUdQ<`pFUikKCR1n zb`MClNte-A?eAslc3M{@E=!C>W)-{(-cHI$&WQ-X^S;^W5D7ehswC^QB`h2DZsA>^m(rFa$6jn;Gis!B*xmjKesLlU4KfKlbW8Jw1yk zAVN&%>jD7Yk9vYu-{nT~h&Wo6mWgSakd0QKIZ^Bh-n{_yaPo!rU!ofZYa zG9v7nuh&-_V1UZ<`nVylT!=4eUDtK}vHcpu;DmLF+3u-r;@*$*@f6pyMKB`bFdb`W z8!bt(K>+L_48s_PV_D8CprfMNjQ!3 zscCjNEjClp&BE-$Flp7l+&z4(Pmpo%QeGEZ`r~?$oQHYC3$)lDM4a!xQqG){EOcHAD)KkpjCh~pFRkuoT92I3pww@z&SN7 zOG?bFoPS2dX+A-hM2kr1$c523tIBye+?iXtfTIoT;~XN!^~#09p;buExJz4ivkuVQos=-EiPKlSWw@=e)Jbu-Ya|E4ca)e*Ot_#%O;pdG+! zlx>?!^H=Mh{f4RnQgKoJ0ZKd9>z709wu9LIlRMqQKKrT{iFE($Pu0E4*X(^;-eLW; z9!gn|{{={II!xJ1ysO1Ww}il2yf$cSEBIKq3alewmGTxh>%xt?NVn5FsMKR8_6~$j zlzwCAzO`0=skOMHac|kOb_!FXy5x4=9_S!gH?9Ny6F{mh815Yx z`}TX{mT}S%wxsho;d|b4(1y+HkPjk)V(&!<7*MQ6^6G!+T}gWDj;Np1(*4>KLP$al zheKcm6KNN&w`m0{Sanx~bkF=g+fVnhuTB6VLEgS6h`U;)Z#T5Nx#7>c#jo{o8mAq0JJOuxiQbBr0H58+LeV;9zdyNdUX21nnjQM$NP z)pvXlt;>R4M$K*A)>M3Yt9fbp?O$~J^gfoYUEd`p{mcL6zih)fG|qMBWi~A=A|38N zx?yD8d+~Vxm8v{{`XlXQ`D{7?FtMLgd19F!wz=Pvoo~wKv%!`i%GE!q93UJAH_77!SjAjLSK%SEMbA zBaDagsDZW|0PJqNA0{9QVYEXl=d_%k$oXIX<-faLUaqf?#@Wen<(x{w82|zoj;oSQDE9g$T#s5g`P>#(Z7kG=^ym%v%)pnliH- zrax4fBHOl7aXO`iA(SO{xl)t`5G-rz&Sch0TFW6%o0-$-g!qM1n>R2uKfU9 zR4oT!9z78`N6VVlnC&Gx7$`jDEb`5Vdvm2T>(8G)JBK~P2oZ9pvgDCL4Qs7>vo$fN znDaVLM;|8PWHc|~eE;>YQ(Rvje@2A+4`20*rsTvq4fC<}>JJ~jQ4xDXKmYjqaXw9l zhcHgVIOm*1czJzP(ZY~Jmvemi{FBy5OXrYTnPr;hFbuus{POyloFAtnlADhYm)ED~ z&p)*_3IVQhD?aAYw_S6I*_spfQ_SHrje!trGU(3enX{}h&+|ObGr54|tUj|n`wu_- z7`!vC-Z&lCb-i3JA-LdaJ4Yz2F*D2QIOZ(pYb57>_3J+q&Ya^opT_yLu9qBFTPit4 z6&{ZFHsS_A^8OY$R8RcOSw(Ej42a77{PQ2i!>PE=naBAUhAF4G5fxIhF^4J$$1og* z!<})u<8ro8Lsea`XA6TYU36P=!{CRhwZw{Y4YaJHDK=JL;di6kX6=Z1y&4l7i5@@w zRPh2dAMfAl&g^%#goZwwzE4xI{}+DE=JE{1d(N>SS+9{+}q}=G;m;_sW-#YaB5J~MZaQX&ihpqnD zRKU7Nm+jl3x=RYIE?wO=@0Rii-N2w)Jyn}kv?pM_Kl0N4Xxh({^u~nnMs@xkc&x3w z_GfApI^%7{hC7_smsyBkV5;rknQp?`7}B>t7Q2#gBjZVDVnN*(0a}IrCBGANKb6A0 zJLDZd6n^=o)Lm{n_Wwo79IN}bJ#elY^1a3Q=}vizg_?YGC7Z0Fe>&bBR^mnsxV_<9 z6HYtBcuxWWc%MC4L;Ln72e@rwbs>nY{#V!^{p*bP=A+sz>ELkHK|$3)*S)HJ52<%t z^ff<}p?>#cD@m~c8nI(#Rt=8Uf~wSc^ahn!NNMc}+^4a=b9-uM?gsH-o5g?kU;k(1 z{4n1EKu)WQm;wq*oQ<3wzC$9;u~yAm20z!cT^APy9|k*;sMv&w4a%jubE%gkYv(v6 z;nWl&Rsxdq<8)Af_3~n0Y=BftYF0ZzE8KtcXPo1Dc~%k5t7Oh;bs<>xH=?uYPCsF; zPkcF;n9?;Zmx6>g*SuMVL2W`7rUU0_^BV*R(4ZM7k~FdtQQeSIo+WMR%J z3==tTC8_fR60PSa*pfANN1iawVVsuNXEkSxsijSBjyOywJGiB|1WFU0Dv$~!a2ogf0_ZS$T?Mbeg2%{ z`tb2c^_ODh#WdsF*l+rkB?6=rFjU>`{U_eRbQSyiRzm8bUYnTCqq$K zcDap&Q@pB3T(1Z?&PS-~dqCp2<{W(pMt~E}AAj*@l5<>)0ywATay>s*Rh2+KKD|gFiceD&A=&&iVuS_$7u0A2iPSWBO=7OR96XvaV}1F)tsXBHga52Tx`zkI8Zl9BL$4A_XJ7$ShA}%IoFC$Pj>{#4$$4*TixjUa9Ks|j%n6ZB58uANJUxE? zbU4h1dA1eF6adR|73N{^#;E`WyXNFPr)WTSa#oA$`TUYo`uf{n)M($(sI=Td8cAl zcFw9U%Q&=MpL1?rXXd0L!#InI1;I;BMUE>{d^ki!!tFdFAo)IzR!!sTJ-J}-br`04 z9>DAQrOJKK4};}jj)%MHcz=C;jMrCk20~j!1p!4kE*C%?%{We{fWAMN5l$Te+5vO6VAn=d=bR8BnL8Vlh`hRrs_}sx z)!Rjz0pB8C_b3N*P<4|+AnIGQa$`>Kb;e(sOc#Ho^5)iW`%0-|dtOA-qhjA9Qowdf zEA?^XJ=ZB*F>>n;QLRm9`Q9|sW=ORja-a%(lhRuYe{JDx7N%`pZcn3tY}@TtW@`!m zvcPR2i>pQ2f$%E03y4rkz0yCuM5IcVPpJT8Lfk4V2LMMU@JopV(GijJD!Dh%7q2fy zjxLst;;j}D_QU9hqcw5AZv`|w;;k+U_H;i`l^L}t)jLW6<673H$+g39V*qUCjWEMpRtewf! z5N?>0N}=K8ysCkAi|O=Vy~?iE@rhlUkK6#ryu~Q^Kju znQQT|nKO%N_RLwFCov54>b(DE@&XcndyKRQ%%9k4cQ1S?=N-GOzi`pOpZ_tirVX73az6V=% z{|bOEjDV=p^kRr5T3MM{MQsRbPWGIl_jGr6PYCO>nEEAi0)>=0=X|<}6X7DjQU z^CB$5D8=+`O10(siiq9^RgLRnYj4hpS!i8V?MD~IKNk>(H@}%~U`4SrVv2D`1}%Y< zCKcWe87AH~C4mK&31 z?-vyj$Z56v0@^df=IL<1US8TEYdJp=xnVvjkuHElo<{p-7lvUzSbIu}d0Y_4M8>uy z*m7UFb2T@du`lP17?O!v5ymN6{*lS?6=0n2I7i!Z+5yK8lON~2E@m@V)wEuj(}(Z= zq7Z6SRalf$T!!(0fmAqi_Ty|VVpRpsi0Fq=Rdc)wD=_4==D4_F1ae`Rai?IEwn*7= zalJe*=ch2vJ`C~tsue0|?`mQCRY4j#@4~2Q70ET>k5lHfUJQf)peZf@>KyqHi~^&= zw(YE!S5-aSeUNf!P|m5?S5-L0#;Uh1Hf07RP_|A>tE2%D#c_&py@X)`LhlKbyb)jg zpd#cD6~O~mV2YXF0Whss6){jPRv|kP0XQwWuO&(s0AotavKnR7ln6ORk!(%!@@+QR z08=9LsBL9#ZB{3u=8Yvn<+3Yj^OeeMe1;sORlGw-W*0L7g8P)W{Z zQ{38R!ez`k{Ikkvf=})@Q3iKApV8EuWQKq%nC2KMfAjb3a zHcqa1fr`%gQ~!~|^cP`3RVe+%RJp|B`~WJP5+ZmRImNhMZG$fCXoy9FR_ifU!7_{A zFgFxJ`Q$nm=({rHoO7PMU(cG>rLa_p5I{7mg0D|#$0gUjhj)vq!~HxN3n#30L172G zLy@e7m({wOytk=#W&qreFmY3Ps4#Ov*c|;28lfwv%Y>`(34kvRAqFO zfH~^&((E2*X)UIvVyIo|jgh!(o3y@$F-Gjrt#y=*n*^gASnL~Xq@+o$kiswmQi1ZM z*kT`UnlaFcWAVmwUBC_6a<8iVg@AyZb9SgVYN9s#yTEOJdiikKCxmD}neGww2!yCw z0vB7iv))H(HwAaXD-g+VF=jj7e`yEFEd;fPe7>hd*hXTvs*Em5ZOf7e*c)v{ZLAQ!}BXGCR=Pz`%|RvzZ!*HpPEA(peH# z&X#%kCH-2}Z8RGY_8TU?p*i<@naZl)#Q!bWugw0SH4omI7i{6Cn}xiS1Pc?A5-7Zl z9uyH$;0Cw4c}m#`fy~{PG;8<&<=zSiAizx_g1-%%J1^*MRAeH03!57*bnmrs8*Zy>`#7IIT9LF~o?DyC_~>Ce+5SY%hv_hkbC_mM zStO@*u_^~to`3#B+f;_>$ebmo9It7;n$bH&M!@@Te(l4!E*AjIwL{{3aA63;o7*S433nVjRY2UKAnl1w|$AwEShfaq(Kn!85QQf71Jj_S?V^ds~%X7aP z*weI}p9zV)Z+$$D2Ad~Gsc7myegW0v?a2wxn*_ zbXDg9ktg!KTgHCLaXvXe#OsR)V~iz4MYv?z8B@;O7p$Cf>wh}$Rn<{35{g($z_;@| zIR{9F8ZeGSQ_R^h@p`$e@#&lIe(9Vu)%$vVwWEd!{Z%1n6J=x0Ii=KsossC%58sRE znld6hoMz6+wwvH3Vk~_2E3+pKI$cIgpBI5z|gGi`xh`VLnfJNW&Vj4RD<)!hQ!#=QDg(9v;Q zHUe31Tj(u5n+d-Au-i}Gq&@wYq@e`0vvVk5o%YK+zv2EvcUNztEcLa8?9P%~bKuqv zyw`SHsY|L~^vK^lLFGBx1T(si;kfxA>CfHGuCT?TtAI*x$+>BI=)Q#7`v`k!xxUSV z=w#-q@2L1UtIMu$)3W#Qjgo9n-Fx?SeaAn&Aq_Tp8dl{Q^u`P9lp)Pr4?Ct-eaf`Q zE$Dm5!*+if#`)%*0DWVIs4?iUAs0KFNhfaVK3w!R!LncFcA*e`eomJgT9F#i`;Qu6 z5qoUuo8}2>X<9URx%QmA_KyznuvNXgzAlVq&@6-6TN}Bs~m4Rx48Xl)B!s1 zmY%W6GjC%}p^x3X6@I>}2{kk5zxe0>#rD=ot{Eb=)xbPV$2Q<8+ne=>E8)g6*2m*r z7!PT=7>E|ht(WJjr$-ki=e-YOS}$q2%%=}wKG^lYJb&UGO(|yP^c^B_Et0tQ~KIke18U9v4>z zB!xz;%32ZRA`Bw){nv=-Lr{ej7sH6RW=5g@mxH{uK}tTH_klS}iqq*~I^M6#C9TWp z!*_^ye*7V)qC;`c1JXF3*30wt`O~ld!9V@w-~T5_o?LkP@pqiopTGZq*5z!TldeU{ zoUNwUVLlAw;pxZU3$q_)axPw8pmZJp0K+ha>6q3_TCd~-lH<7SfD4xU2*7b6ACSCr zj=V2J&=PquSl|XZZ+iXp^4bqJhUw_X>H6~7@au@^!qhszJ`5aViWhrW!#MjeUS2-6 zakou?+Bb`^WUDnjvjORE4?WHY+?9-M$!+BPTDkC*PFEhJ<@K|{lpFG-oPYr!C9`88D z6t8{9Z#sQM#O3vob3A?gg~1k}1Ruuba+yzehvS`9X8nF6oUFB8(ncjq&dv`m1VhL! zm*+1uoa@rRd0n-PHdPVv^Uput2v*HT;+@NxQ_iQmdm`!^X-2?WmSvo#>2R`nn0>?0 zv%e8lIIUL%80J&XiBr5T>vdTz*7O&@{1p+c*JsIji&0d#E@?i@r@MPj(P)TaoY(71 zd#^3+T_hvoFdkrwgQgy0VD;88-`SqRIe-8A-lZ+<5tA3uBuA&kd+q2N06^xXqG1^OBZ3LVu_2cMQd~e`m=1dt zkLHw|b4Z@kx&_&HrJ=t$2z9~A`vZm@(535==sWSqjkkk4(?R3?bch_iK}PM1jN9|$ zdkyF}+0Xa|w=%pr)$fa4ZN^dTm`XcuEFviC?)0r+fCB&^H^asN03ZNKL_t*C2+K?*yJG0$luB*qt17bJpHhv+?`}WFWyE474p&hvGKy~X2 zw-KGoUh|h)X`jz;JTeeVx=)QD}61S_DPo7 z8HB`cQ)L6T`m^1;n-USavIOa0p2tvwwu_#LrZt4Z>(X z2~ExR)D2RnRT7D}zldlek;C0rcVGQ7F6X#j4aI9kdGST0RQX%2Yf?^L!*uk+nAQbU{V-xR!03v*7AlPXJ*J{BYb6}*60rDCq|GX7jIIj$y&#_o7kLa$7MoD-3e_3henCk(_r z=m+Y3RObRZs*v=86gTjKJxJKLUVO)!heZ-yRh_sUx2<5ZNm$NNm`@+R?MXwhXFhO_ zlUc|S5%K!+8Ohmv!h+}Hda)A1e<({dHg!*n#Dc}Luks&NfSKBol%4-en?Fszqn z5sAyWg^pCM|EDn1^tv~XmDVOcI|UF{lX7F7-2 zwMMQF-WJ{^re#gX<6#=dVLAZ7^V8>?qCHDPaH@J;(&2czd-#~vYg#X6yXyN8IY)AS z7-pMTN=`YgnVBLJp2_U&)oX7cYy}qoMS7?nffG~{a>u-&mFpT!#kB9s5 zaF>=#PVxNoqX?I6qMJH6=Zl%7PEkOGTxi>P5u1>+G4^(tAyQKVbv2!@V`+y(&gu*k zOI30TbgtV*$k7T~zLAZUBbL4PU23x#PE7Pq98?x6IJV0B;0nzPNUNR=e? zCPG@7%}NoMbB>Fo$T?CNaifnbo@A2`aiw+xT#IqJ5|I?|zL!fRMr;=d8}#sNOW| zTgZD4L#scc<-(MDu0Am2yjJ>Ry`)Oy5z$ob%4~^9tt%q<){$M6 z5rE|z&^5Ccww&(P%zSq&S1v+})!kQMb{0XB9t+qjX*Vi5px$bsL2VpRuN4t(kTawn zozauo3vNagMVhF`5q3(0-8)XrXb;`Y^d>vKPX*G37NfmD5qsT-NYRrPPpT9a&;B87 zXSG(--*y9-nb7#Xazo*-I&-;|yXzYanAW-w+LKwdkS*J*GC-j04TyRx8h`KQxak}< z3^#(Pkm8oISGzuab*$B5$T_#+!i{hOx44C}uA1WA`9S1r*SAH^Q*!~9H_Lf@37roX zP+Ccos(1tHwC75oUnWGr)vcjc)oooZ?KmWSPo?b12S7^e1%SvUBea?tQ-srcX~8N zjG&rx!WMcbBErCgM5wgA4kB^6Kym&Sf^B;da*7CO%bG9)8kh>wdZ{T8y)dNEURr>k zeM(MCm=5D~;1qMaGOgpJYT>I^n4)vSp0l&KOY(tgIEV`)nJU$mKcrzkAyT}a<9bQ! z)t=MC-3LUvzCKD$?Q~z2J6MC5fjMb}0-RGtqPU!qobv%yE%?{i8O{eKA}Ov0hc#xh zriACXnzs@v4!BAjjYDDDOLd0G5k^z`SxlqxS++eG)Rfs)OEK5UQxlGtXN=I*Z||WEo*@C14FvGE1*3WI-4J!EB>#Tx2VURaZqsXVfu+`-BlnK(XYw z0O&9s$}?Y0ZJxaGLAG#=8k<1QGbfI*7suA5YeK>>OszlR!hj|1Xh3p4jO0C$v)EN( zZfuPz+7zg<*e>Yi;kfB&S#g8ThF*v?9x#lv;UETbMzYct15g7*$?Gt|Fa+nlEp0;> zymL86N6w;ReP#my<;>S*Wl@(CXA>52*@v+7Z=Ro@JmJ1EfjLDxlsZQxr*mUgfOFI` z+G-E%3y_tPpu#z=W|JypzPktS!*o0f=eS;r_P&_J)j$MhcW(Zic2?5@JgGasQ!~uP z_0o=!Y{Fe6s4)Poin1-I#hWXrgJC}qE(RM!G`Z{>H(pr~00G4ElPxRJ@D)v(j_nd5 znl?Da^=ir3JMi1>(rqYF4m-(y7wc~Q#4-e6%P$|Xv?gIj@*H=}M%=SA0DCgX(dZ1%jLCuow zE$X0P(1dy?Hp4$4v9JiQ*E1r`cOP?HjNwwTKzch4MDii1^~%V#uBNa6kE-b=g9?f9>}Q*n4=#608JiJvd7}$$H|A;G!AyeDZgz=PIqlL z=F;mgt5{oz+x1{wiVUX)#v?+J{!2kil>3Fmy7Z>+w^OJv9S|wSMMX48`((&^b7)l+ z=R-LPG$nUeC0h^N`9R(~=U+elU~~K8{IxD3Ze@yd!H+Y?6*3fFt@)^#w`kYuM_=Z-KB;OL=T_Y^Crj?Mx%l9G4S7e4xEY235Y{CZU508%i*p13Dd+353bS+6 zX>rSwXMgp}^Yc7S$HUk^OF6C9wRH}qxIVU8r}p!)vs1o1byC|kRXHbiVIbEw!Vlv# zxiD~wXfy^e`oKq4Tj z9dfy`e5k4@*M(7pa~P)Hbf_wlvQ<=KO&0D=vhH+jUpR@&q?W$V(`bL;g2b{e&o9XY_gdKjB)zCT4a>5cSls{$h0GU~eP zf2)r!5jG_bSNE~z{Q!JNOvf!o5j%af)ev~A+%0Ao1Go0``8Tc6owT}iBDjY%?l)Nh za(2I=(hzJB!NN7!Qk&};4Y#;BB8Oo&dsldK?~MIe>hDgLg*R3NE8NRKV$-!K?7CE& z;$VBawDTQfGhoOjb}<&YQj=Hoe)E1pzB6hx@eX#s1NNVc@5$Y}7OP_8=I(xwA>TI3 zZTFlM8f4M(LF-0tJ1f@KS!ZC`I*s~9*R-{>c509|nX&J&@cOMNDU+cs!l{00r1W?ccOjH}=e6zAb~2xPZP803By>{5o}y`=RUdeRfsy(GOrX*`G3BJq#t>1=Yu`Z? zy2fSAf7tRFq}}hD{Bzw?;f zq~GqF|8>PtDShmcd+)xR7&hn21?a%)x#7>brK3cRmm~H%tH!mkT0VFfjnCWWl_i zpNkLO2T)PbHI^tf^kJ9|IVGeBpdjqW2>{cQjFsj5aJc_yA>h{ait9D4SLH06U3U;R z^FUq~Ky+bJWyvXwQy33%Ij8mF!vsinF3ans&5XwRgbJ6JN9X)_xXbI3(`tW07mihK z&3Zk9s&%1NSgz-GTaNc%xnaCKr;4Z2xLi&jzWwmsUjX2GeLb8$_+k9;?Vl65v|i(K zUM?@25wLn)B`4<9PqPox>BDyb`25q~sjeh)ewYsH<@K_DGUk>KV;JXXvVK2QG%f`_0z|P6{$wb}5mwf06uvWm;rKzyFKB_YYIN zu9sKaK#T`6Ofw?d9OV8q)zcEqcOSK*_84FO=$zLgp|GKqvxc?^8=tS_ zjQ}9v<@u*D98Mp9VaIV*Zi_H;7MA&VkBDxVh{8|5|5wf%$r3BSv=B>53h7n@V7y+` zyh*C-<<*7Y!^Almj7=rySmFlFe$Wu9)+`iG(m7#GMCP2Tb(oRJmx@-C2pedPZBkge zM~I;6hY1v{aau~hFuE}L;gDlw?i(1|LN|8}NISUZEGjuA1zj%B{!t3Q(L35S% zh_Du82DlK4cpkFvZvQTJ|j3T3dlQ)V~)w7$uQdK32k#y+pzQN550 zI^i*POg6pEDZJ6o-|BJS2=4Vg?eAVAealM2ZkS%xecFYd-6W!I?Kl7c0^m1t@HYzh z(jMmjkFj^zkt|ux^~}uO*Ciq{v#NV{@7v)4MF=6KE_z98iGfnhGLB zXsXB1L?aH4fCG|y_oXT`Bi35(W~PDpZLNr`%^ncln^{>A>*DTa_W$26964>w5t*7> zyNm%45An~PRb$Uq+nW;_$_{tHgi>jDDw5Jg#GPZjHQp;F=@?hvS*LqV3f>Ly5qeuc z>OM&k4*IN$+wX?+_a<)WFMIobRMHA+|Epg7s_7s?25l{kgPj2Mfy!p@Eb5XnbES$8 zjOD7vlf#2u;-lZ$@$0J1xEGxjH<-w~xo`!0}hnKt*g_12@z3(XF7kB2)_CkvSw&2fRuU4gVdBv(K!mO((KuU%7 zFE$rApU!>DC{RNr|HtUeRp}Ma!5m7&I zPITIH{D;5$Z|zVF0BOCE_v8l-^BBDVDCVyaT}b(+@t3=3ZZ~uiBX?#`$SH zU4&UwxS!IY>+%TE0=;|~U6||?W?#)taOSlbPfws4*Z0g{wsChUmV2_7ouE~9dHuz% z1Cl==eDaDw4n#PvT4Z3%X}-M7mrrb-jpb&tAXT-Pa!wnOyL|p(e*XUX`#+BJWjsA^ z%Nxh-pa1FqNpXGu@~5;d=TASTwBEk{f{3T*@0p{?ltkE^>~BB+izSDY4TI2m>naH+ zi5t2=&KohH1+bx^@gXA-8Xk#&2t*EW&OXNT{q?INvgkaY=J^ELez^Eg+9fj5Rh!Y0 zM@Ld73bol{GX|p{RDrkIX|V#j0F7xtdyezAuIriw2$$zigt)Hn!s+t-y#iQ8nAUeY zN87WP;=(cJJSK8zqtF~B0RS3?DU2s8>%%zbv#M%bZz60{t6X6?Z@<&J5u747`452V zFwGpd>(`&}39jfok}L3QM8w-sVT2iymjj{1>H`t0w)>A~RbYP~E6K$qqtoRRBCgk0;b>K?{QyTp_9yI+ z&32(o4TR3;HnQ;T>n}i{3OPzMBCt)SvpfP3-@bmaIpz*d1)vJ!d=A6u{p(Ml62_Uxt;<{IOBNr- zFr3!qx-K{Gi85h`&QG7o1#?er*H-`t^TkXr)kIHSm>(c+*RM$4!dU7nCL&foB9SSr zd>D*jQsp6iSJNIywDAg{O0w?VFkim^{oeqwuj-OKwcsHW`( zXp`wJ#hg$ZhS`N7ZMU42AwoVBo`xFT+xgI<=T(tV6_)oe%(0v~J!XUmwv%2>0JjM@ zxo$?7bwRIabTfa-X9s-bVr2Mc%1#V8^oZtIP=)tH5ypW$3;n29%7N~$T_2`=2xi|8wW`O1oOPkIZIqlR;d)ZR?!sa#SGA~=2?RRB zgErxI361Uq$NI?C&>(q=iv85E%Z~5)X1PONMrC({(mGzOXB6l?^8L~Zy>p{d*}5TX zeFzVUKQ*$TWOAY28*BQqtigYAM+WN#&!$hyUmHyaB-kUM4r<8{jm90MtTTXDgI)KU z^w8?=8fV~l&Asdj-paMG;={mGJv!q!9aq@lF|ePv;i0QhngI9m-Ohcpw-06Vm4)x& zE+)JeC3Zz@xwCLcQ9ts!YG`|Fmzl3Xto~3DMHCSf5fK#KRYf0^2zLbp-uJWm1*0(o zYF%}}W-E05`Q3bMKkvdjI!28|z&#Qj+j9Ex;s{+1J=WK1_ocK>un~8N^Y%jnsDa}LOg;7^MjA&B`pO^`wfV96cqf&zyI${ zS*EISc^}5pFrPIa)mKT$bU4-mo}WGmr}g%3SZzr$#U+fVFrCtRGjv&wb`u`vClxm6 z^DtlXP)E3g{E`-0Qu6B1bvd|Yp$YU9${zQ32um0&g)#(6wl*4z8GT(QH} z*cY_>Vq)6o-~2IK>4jBN+?KSh84#E@JGxd)x${9%Oxt1(2XjOm7DN%=mUjRg#@Xt; z6qmTI&gbl#`bMtHHMfNbr}?RG{Q5AG51i9;k_exkzN;p`xZaE&C&Fej0Z>28rX3d* z5FzKxE`9xy=XRQN(?C^yu6Urx%~gaE(2sL*pb(Ku+gf9oN_gS5$!?r;F1TQi{bq06 z`Q>{=T$gKRBiQXm%u$*-*wTq4*I`wvooi_?#kuqt#y_fCW)<2I#Vzabt zPL~|uei#-(hMQaO#LUns=F}}DIz4?Sk~k%E$Jh3Kr@A67umxeZ6q>r_0caRcb&l}< zHJcZ=MITDZYi#Q7|9Lx#`!QJxwl{bg`5xLbT?j6Xq}kclDvNT$q(cCjf?EAkRZoOwv+>?uZF40loApaFx1_;T0aUm3M$Q?)gq$k@ z?>odA9*;gm*u^CE9d^roEe<}iCP8wTSuoP4hm<~f zvAS2XRHyuDcu%9jB5Gfj>0S9qguEwK10HPQB^I%UOB3wFo(~gKavr2VmbMh3c2=jn z=H^a_wwNTX5P-c!1i%>n*@CGeei+rWc}tuh0C(9~Du)oFPW#tRlv+LV*x0RvU3Jmx z7E7&3Wf+5{rqUvw&YD2%EHV8YyFJJCid%}Eb82Qj5kygd<6nJW)SD90`TImrZ1bd& zW90|nq{v99g3O61L2K~tPokY-@O~V*uNkygf|h6=Y!-40nzsi~s44NZM?)38t8@Wa zR=$;yr|zeo+NN$~$SdB(5fOV8%>Yg|~GnitP-op)e>Q#|;$7 z`TRuMTIjuM?%f$9pp09nJ>}&!-qxELl-*$mcf?`QUJnN^&VnX(PQp=CN%W09@qXvcp-Unr2c~FkLUn5>}sIYo=u?P)XHMOQPXz6+)4e zXN1t__T@uYeHVIIogMlRz&Y>3Sas6%-LMzfj8M1NpNPB*As0-DE(}(tYa^d23uhOd z3x0rn91autkYio9MMZ373}MVCYXcxS55r_sYctMU)00_=C=3JGqYGG_(abSFRFJ#J z+wI-{J+DPc)%dxQHOInM#ZM-c?*& zcEKVPqc`Wn95QpND^i}*JLfcDQPYHBc3#HQS%k?45aARtb42u4DK=pu z=a8H#Ys%9BJ54gDJh>{itKvTa9hja-j>JaxByg<6yvsD<9fBsHQ}vFL(r}< zV2N(cgFzK>-dQK0HsSKHTzk)YYkr`GdqWN$H^r$HruoSl+b%WSY-eJ03ZNKL_t*NhU!Tt7dWjYiin&Ks+#*D z+hVF{LIP?hw5CVzezR~2VI0OekxRJQ7q&d>LfguwX)}ftZ6n#T8+kFnisiG%xFG-w z*EnMfoygXH09!b0CTwwo8aEV?e6&|dk#)4=azWC@7_HA~@|Lt-wX~|74=PE8 z*|xyEf>7o<0n|tkRgG~oy#J1E^x{cH{>)ZU)yaEefm%+%hJ} zKdBvTLCVu5f>ItQ6+sn3B68pX%~h=$h8Y0H`642Im{s`p`m6Kp1V-eXAMAG9G5QdC zs>&Q!fYFh&&smZML`AaIiku=jqDD4y-k1-)L!1g*wbTqrg^@fuFY7hMWf)IDS z3rFOXwnY_P$?r690Wb(>A(9_va^CxZua}PnypVX0-_9M@!5=M0=6#yA#p2E=0Bsi7E)k zw5>$0pg&M-x5^t~=g7?`_ZAd@fF#27FuJd6f$9z+*g-1_&aRuo-}kz9wZG=%IgfxyfRQw7l-bV|Xh&zwup1QOap=R0>t#s{0>$xKoE(RCl=zLRfcsRD|yR8OgP zAFzO@Tb9IL`m~prXt@^x@@Vee(W22oQK_^MBi@Mt4jTNOs-v{~ii`{^k)ZGD6#7~l z##ptX2Z3uvI_wd(U08wUBR|I?R%&O@2dSLpc_$>rT*-PLTv4mmxcVoQAFGt0K%MgEoQno=@QlJ}z4gvi+bprlDR&lny!GtkmNmVm8|pR~6aT8#$_6BHMZ`quGx$Isg9apNPDP!c$zG^XR;A;O| zIf`0Ux8;pfnodvI(*ls7DRMw zu@wX&Nm9Ce{?ST#0I(iAWZWX|i5nu!Pv8I6w^RjBB!cp+ddbUyo!q-q zFuRelSuj4-2oS=~b#W()(kju$j{>U?NgKF}v#g0)MRu$E+{4bso9ikp0&#?voNySd zHqJsf`OmQ}{SWLp44R=?d+3CAK?=3-ffh4@TJCjYHS}Ncz^!#2kpc5Y*M539jRm5TTJRx`t6X*DkkrZ=dBX}caDE- zdeD2VRpTI3J4gNZJUekYK)V&_ANbZDTGaYap=~{^&Jw*dy6EnYV`aVd&(3b~`9J>W zzpWSHShsQF6wjZ3K&0jMS5BKBPpTQC)iS=FCm%FL=IDnB0PPs~^!@K8MT;{`(M+1Y z{br6&pMQ&l%k^D^n*~1C6Rov4o}SFPT)#%HSrI{Gy}eH7=hM^YxGr&9`t8-me)ehG z6_Lbg8|SC#{ItA%S#R$-yI>DOv(tzDW<-bNHJL2 z$89w!86r-X&;9FQ`Z6Dex^Tw)S|K8aaS~4DMU!E^4CCqj^%ui)=k25jztfh>8XrbC zjB3Am7;W896=$lSxFNac?|--6-fnNdk_+U6Y%B9-GmBw5lXG!htgr<{=SP*qDej+* z!{A-a6&|Lu*+}AgOJ&`dp9})<#&P@Z_kSJZdj0YcMYCXp2Yhq}#b&2hfe70HUrb$PdunDgFHuH+z)Z=Elhtv5Zyr_lH_jFqtC8l6;V8 zoS&T!?_d7ZTVU_%V~ER}_A^4*yEPvjoI7IEAy-ZWsH?#Aa01Lz7kro{pOIbP)Cc#2 z!^Udr4gJ^`Z#%Ni!;F-wr>DtGm7hao_Hyzk|7f#yp|5>Ws=I2tc-VDU{u+L~r$ZeMs#;ATj}CgO z$6kXT4{DX2bztn`u^X|=qwC>kjqCP^1_poeA8hDgJsPDCc))B&K_U?Cl<;@8GM1h1 zVaX0%gnfk)=sm2vIi8QtRnMi{10?eJ+(<2KHh>HK0e>i&aT+_@i5HJXysYV@OWz}z@RYdwwg6M0_{Wo3@) z92#m!)jS3!F*ikAKEV}P<2aqi%d;|zYP`M2?bb6$OPp1x!;&15=bVjyOL}xR=8QBw<-W{YqrNKJbm}uetk-Di|fsn92Hh(%u$O;MX5VLwLI7?tz_Y3 z&&71Hv&_%!U3E6Kh71++9?@}JtwsbyF-NL>FXwX#IXWT|Lus2(I|M{xW^yhJld5jF zH=9fpsaNp;WQh}S+MEyb(`WnJ)3$84SNkJYBGji%RnMP(5J_=eY#njVlM6ZCvg?6Z zan|=9$a$#k`!X@jaSO~Ue0up!5kzQQul8^X*Q?Q+E+8&f7lzZ*XH~s^{Tc5dx5al4 z$GKs_YL^pq6MD=~pPdg#K{(#tel4hR6W@Czr<_DmQKctk`TV>8LL^DrRApNik;L29 zw_)w3R5=Eb^TVVn%iEV>J{wEgWc{G9ynj&hMrHT7()=PvT$&dyV0NG@2R(|4$ZQ;Mr|fy&@#oG(a-=n-*w z|Dw4DszlGMbhT@e;#PO@ZF#TVcqBrg%mxz4>VeK+=f}BmDvI4mI0;9afA3)$qb&k` zn=&Vx`%vrqVVaQ~$4!K{+Z7OenCu|vhtUrs$7t8KZl<@_pKbL;=PsXqNO9w|ag0WN z1Ek&`Rb~CPZR3Z@2pDBkq~w3&)YRfY3( z(8$+D?Z_(VG3ODILvo<3B1T!k90>79oKz?T#;&Uyui2KMM7*gACniTk&ZL+oxV4LB zmLqK^M^oBs7rmu=jA+R-s5}vEva7uoZkH~t_o710;vA0(HHt;Mpy{?2?C?BY z*{b)={T^LbbGoI?W{8{tnF;OE9hTn}6sh@{8z-%YTQdLDlqlsGTuemF`4i1(D zx*zkP%{#P=>Xn&DEjl!_zB-F4h%}KfDsa7``SaXWUi(R8FP!KW939(I^Q$!D9Y%Fs9uCP9U<*>*mq(Zl;ZwWL)0oHgjX+4acDjQT; zaz2Lc^OMVcEF$ECsuhW9uoPzSVHX{xmQRQK#fI){SUfZ^I>w$B?RvqsWYCX8EYs-w zx=>rpUyp6v2|Do6cF?v7Z}bSE_w zN&PUheM;M1B$i=h2;&sjn*~TpUN{W+3&IS=!K%WLKsbfzRE_y2(R7%-+oBTJTekT( z<2>%)_RJqc08xQP0#TPK!+>JiC$W@vsSq4iffR<>g;2^GR+VkN^{ZQH`e*kH6p>gN zq;367+_oYgMn6nxz187diW`eq^x)z2lTjlo%H@7>)C@PzZ|F3Z*vQr)Df#vG zmX*V0l-n6e!M+Hz7_3z-vq{wuW$X1VgAs&P#XNHxTx+%Je5m=F*%(@FP^t>xT(H3m zB3b=yHH6{8$__*o42D3QTE4k??M?VsmsE5P0huExxDcQa^^mAI#u!pAE^e=YgnpQj zTwIqfbjkH4T@L>uZ|{{_+H>jmb|*WoNXF8f;_>w2=iZ zcqqliIz4p-whN00X-U9-d3Xo*aK;6h{fj`^{^gBbLdhb=44BLsqLH# z2o#2~L@U?r-x0G2t2o5kPKYYv!yuAHn|9?*Iu4~L#Br^SiUOa@!C2%59|n8)(RoMS zn{?R}q-pJ#W)57jPDxgeTiYOqf@NL@SoofaOU)Z2lHz6;Emw{yu60l0xH88SH#?SD zapL_@G9ShF0co6~4};~i1As9$Uw^uq85tezk$|KHr`bl+(xZ3!Z9l87?V$|QJWOZP zO>l|;o1MsPIZn_aJw;eVRp#?E5-rzv<#d>Ys}?;4fOVYmMsoL0CIseO**u0JTU+z* zxoKz0E?s_BVVq7rjMhLi7es>q?5FW&psuT}Ewh}qs&UYQZlQ4=#!0L%glMWFNRga_ zhm0|#^6{VwPv*-f`yUZ;7$+&#V6quLvn@u&WO}PDcXEbr-<vo_uG{uMEwVC*ob zjferN5~dRoE!Q_rX_!tmKY8~}g)O45p2h%RyS?>4RJ`G=oYyHo&WL1A_Ovb{qL!QC zyfClbA6Jp-hfn5+-~?ddi>1@9BEs=7=r!aGWz0&L&M&I^{^id|WU$3McA9H=w!FDU z0+&reY@%5v@PH^Ws<0czBFj?iJJpRsI7zk#;CM>pd|Gc{>9>fE+-?-diJ9$ulcLxt z1XLN4QB0j_@$&Hw>tV=pOx2vyv9z6Q1H*Yqk(o2Pg&YEMyrJ_xoD?)}iyabj7f-UB zN&(WgLRTH4DyIyDG7mr|VK$ec&X*VFv|is-WPN`v3^r%79U>RP0Ej6@08KVXDzu6c zxb4V!7Y64%$2Id=hMK|6( z0uZQnzHiV&yW&Bs3Pl9V?46u%?)77Qc^1pogaiZXSTCvSclSC^z^?6pSR?56KtKD; z1-IR$EmNgKJv5foW?JKDt0Iv3!tLPMnF;hT{NK&E$yrCcZ79$r-|>}KAeDDEde{ZY1i$++8;9;rePeMG2XO)0kM;|_dTQ|9ya&h z$$9HNXzfMk#(;cayu#+w&!-k@sTxgxm6J=$$*HAq^j&n_HIoarLU&^YYrVGEf#!my z`cPFZHxOZ_5bV2hEdZr+v+Vls*o%s~CDn%6k^#2G*WcVzmQJGxcW$ENYS%4{8KH@X zRwEw#7Wqiu_#1nPR8G6hv^?#`M!A5~{x{dih_WqUy^Ouh+hsXXb;|Glc<&WK=R9Jc z+Ljj}MYMOhEaOn|FawS-{NMlE|JXml z>-FvW<iztKXFc?Xw)?F z9w`tJI%g{fHf2o}-&28pv82u3%+_p#3@QHZ_kW$zX6LWoZ?2rk59l0kYbitJH-GgX zIIcFXw-9Oz0j~|Er_VoDG4!@v%hbJviRa-^#v*8ekqVM`-p`j$s`C2Nzx0R-^5KA- z=5294n;e$+FZMen#nKYoWo^1)hHT7eFUoZJG+jR5-hSS0@3!x{FaQ#m(8e&TqQ-+4 zPRwizwUu<-;wv_v)AL@^6*5Wth(6`6*i> z`@tW11md)a@Opjwz@&`Jq{GwaAN?@eQ!f3>uQ=|Yr= zoxH7(!_Wsr^23Paw%a>7=fh+%Ce}w4ZW66wIvHNh_GI6mYRdws&X-Ta>GJy1 zKbzY@Rh%CRE#EzT|GVw>zFc1o@iCoV!hE{D{-VO`@-Cdl>B;mdNHm?E<91uGZ~3js zkLaoj-UlT5_2)mkn)|34hB1t%wu+K7e~1eM09rdYrBr5liPKufA6$CuNA?*Kjpt{M zTPA3VkZb#*HJSbXAW%{g+8q0lR$TWarc4CFZwL>%QF~6eI>ylNkWyIlsJe<1AM$$+ zVfOoU?7c!lcc-Mi*P=Q|4@r2~PKaQ_LVm2C$8UMIp)+}^-e*|fMxTRl!-ac0PSc&&*#I7F>8+W7JHfpkrBf;jq>UM0 zT+&)d_B+9IPwMYvGM(_^Tgvbn8s1&@UMS!9?WDKi;9lUa6_ub50}bmMbS#$yQ^G$E1{;c#!fdGM4!vS*3uJRiK8)kFci zOo{gB0v=No+IoOh3Z9?UW-P!e_4v?UqV0B-N?_+-siubxa{v!s!>*FRW{}#)3U z`^Vw%Mt@`^zrW79ZxHPL9(T$S)!qRw?VTvyyp~0}Gb*+3tq-IqdK8lNMO*G}HG1PN z(o(D4UU%$(M>5H7*~DGTqb@5W-~Xro#)s+Y`#-44 z*Ps5gMOo&<+I~YuB-5tbQ0o2Hf9)ge?ZlLSc$ko=WXqw=DoyHb{|kBV$gS5`tyCVQ ze9pBJfe6Ws^Th_1s%EGZj$6$i=>BR)WFg(ddV7!SGK>@C{5IX*zgQIEEya3wCu0Kszoi~!ZeEMNqubWj!%FYkyeD9*|^sD5@N%H`?JsEb!JiYwJh2i$~ z=lY6pisT$pEvC!uE|%NEH`wg|hUq+>p1N~x{%1Nr87;StNlKX>ENjgwfYZ|_L|krf z!p!Tf2Bf|G@K?f7C8fBfo}D^I001BWNkl2cW85JTrt_!i{K_1`89fqD5UcaEt$qFCRXb)5hDI zAI9^iAF7LE_fDEV+cGFj)I(L$vRiSizRaAka;mX}0dnrskAJnT*X?#K#DJ=)(<0XJ zK8%;ozb(;~i0GEO*Zd`aS5erg1$u*zZYcyPdMfPt^l*iN3?0kaR!sq=!J=-J$;e zB-@Wj_i~P$5`M7gYS;E}WMbVvHF)4wA7Iw~o^f}59-*Hf3}frVjNRx698wyYh~;W_5bJJ|3@rf&$QiYV||#;al54$ zGgha_3OYJ)sntjt}Hq7-vvemn#ujxhYo9m1)hf_yDxv469>IK`zYa zPd^}0TzBc%_Ilc2plJ+r*9+`hkvX&-a6COtr)QCrSIc&gwSj z$8MLz{4p#tt@Pr@(`8$iJnB$$bm%SuCRZM5n9sv>+BNwA5b*Z)CHKCJ!VG9*RB}$U zblbNTY(I>&zf#IsNmb7;-yza^edAm=6xFC7x&%%@bU>(?QG2*40IKB8BQGj!8q1!Y zn3k&v?jeVuIdaZy!r65$2^1{nEa%LXfI4&jj`PznUqq5-#=LH~S5DD|v7SaPaKrrC z!|7t*@%H+Qh*15_2#&mkT=uw%Z0_vpHcN!bgBGJ<6|#X{Bzqu@`fbS`XB_ zH7A920)nhnZig5IfMGfh(?vC@iUAOS93o!7{JDnGHB~|r@1W(;&zDc+gDac|b0yi^ z!6|Wy#-`{kw&h*M%5m)8O3|$Q)wr!DZ6xQ1>1=1yzMd#wP&#-J)dPX3P%izCpwlc; z>#Bsq_F>Jf{s+Q1i;ARFj7H6R7{-(HgZpZ zrjFqJ2+Bo6mj}1~e#$ZShiMnaFrKPBRZ_Cl*kL+5=ik5nTGG-e69#dFy`Da#C1vAQo_K$39&A_ZJ1^s# zk*CM&i ze~!pj?Uo}=g-B_ES@&W0qKbWaRKAUrPI!h4SOVwcLIklxLeqhjP~u&xJ|w#;yWgX@ z1C2d6ETh)To+C6%)^0m3+zDv)TPL}kGu3G(`%9n})SNqzeIcTyI5UT$BWL{+0Ld;u zVa;bLMRexu5)jlKg)Yy-6yfdwm@{H5@wIr&ABYGZVb$>Au^rJuF!Gq72#W!`(cp(i z&N2r_i`^-r(0ex31M1)h1!rlo=-o?>NQl-0+!ck`RWowu`pA(QiWS~nX-8Q343C5t z2pR3zJm84ryr7l%si62|-#$@oL;^a@-m0Fk%SqP{p^pzQyH>TV?$?I)62OBPDZG;~ z=s~)xt(sTp{K#fi%rBQ}#X!%=QqUD$4N65bcz%-J@#jn zBOK0*F^G>gg>USGeBVU#W;Y4rWJeD>%cQu$^(_bPKxGe>hea3=hw*F&4x=%}^~#(i zr6#QgP}LM;5g9@eHy-HY?OzP`YA2@B&z(3$=GbG^4h&fp1z@cV1+C{qR?*Y*cb3d) zvnzA|aN5@E*B`Mc1@WKQUT14X}Pjl%v@98$(f+q4yuN07iN*D zs(zSk$IXBnL*a_QEWk4HPNo9g6)TEIv^sMMLKOOr|5Rbz|GqG z9HVgZVF+&CZtpwQ6}BN{Z~wPV!3tUD2g+Gp&PdH+oQzyp@H7pSlYzQKpnwilRg*dV zqi(t0z;1%Sr&n!A{pAHAvyCbIcx&hRT2 zF4XiKXEdaNoExUIRh+daXSlK)$DSSNT*cT34WtLGk+0Q*QMG$Ef2km`dc-H^cRRjF zT5oE&0CHx*OmRcJOXbWQl43*b?AixJN!DE}Ac84f%^JvYvu7hu@0#vUGrmAXHP2cfawXkLDp?9y`FOw(Vr z`_}oP{6X_RMC69)l$TL*L|)Ps?e#;f&y$Ll@cM@NNB2^lA3d_k?MAC@p?YAhL4Jn?Sqoc+;*rt`=CB!2G-Pj`*3Mnq->C*4pt3^m!^MsrS6@)w4umYfYsh88!r@oUT%-gyk;OXh*u71Mx_HJZZl_cUj zMFiVw?z|u8Gc1_YB0F+(*!l!S4i!Whv3Q5`v!`H0JyjK%pT6U?-uP!#U2E)F12$3V z7TB7SoC`jTs=D&m40G_{$bm>b;1fAOLW+pw!cf-^TS|=9VO~;D=>j)=7*7VJ6k&i( zIBlFbZjv_g9!lU;dj_&&Rf_}^5gj^bum#h+NSN-QJyTt|`8>?$xZJ9RyFbJ2bQ8PI zBzPKH89@$-hWTvARx@IoPN%0f_gid1@+A+G;R}Ql`JvPe#IRcWrU<9FIPnIc$y+bl z5xgCY$ay~x#@VRB5#)S|8hSo^M!%ZoRxoxzTvAS2;z*yorUaB3G;1?`g)ZSP+*nIWHq#I$>dli6R` z2hE;mVTyjJ;079sX)$wDheJ$9i^!J3#7Z$=rv4= zdxuHkt84Er-yylNlW5=dQTGY*2uB6{?!t;BF^6?c;YQsBlT>3b?s2}>)W!THYcr?U z@ItW-7!~)or_)pc?Wme&S3kl95Q=TLQFYoNK>G{Qt-jb>JMJ~Ta(J>>_OuKrQL8KVR6#XmNTfDl(m(!gNa8s;U-Y7`Fw9ybHE) zs~PIm;^@MDZ!4#axFOB-Lcs<7Q&4Zx4+=BLlb zkLPX8Y0ldC=up6YO%X7R!*oU>B)`0W-Ill0(`O>GqWt>x=k~NYcYnCzZAFC3r{B6^ zx_Yp(o_@^KLJ;&|#_H&!RmRDEAC|xUvY|E9?_Pf9NuT$Li9(int z3QlH#vH#T=l7_}NXgH!9#wkpvjau*~xyPEE1{1{}ybC=zKUmeKu3Mq?F?NP;ILKyxp81=BLjH5K~lUPMftx`}huf zt(Nz%mfz-_fBxYQ9Jjcw*%cl}=e^x%i;=U>CL%<1`TScO$C|h!J2gcSVLUxK=Kzp7 znW?EJ0F?87Kq5PIn~1-*aQbpVm{n2>6GjXrbFSKWhUsiMdE~rvjydJ4s=Ka?RZd|# z7l}>qKGMq4*n zREO~t##3D1Ypal)N2KNb*Q$^>`a7+EyE_gkIX}!#^`2(Sgld@1ew>%rUn;%J4O6|s zE=(#(QuO0&4JS^CsNF{6;u!>$N{>^v_0LiTMYScrA*0pThlt@e>h0vM=ae zI0HUlGGU*GjD7LgcJC}k>GkpVz133DYKP^~eWBvetNyPI0bXoQCdQu-X#m?rzXdTYT@m?fosfb5I}jFb^)2*~`lD zt4U95AC)3 zxwvVmh}}mjrScKaL3b})Q5_Yb7IqE}Q_pokvOCF7?*{3;MmybZedrpCu8RXLH|Rn8 zM;pAi`z}XG(YHlOe>pX_4{gQcp7LND+l9&IqikIu>x%Rtce8s)<$ej$-mY`ldh8{w z@dJQ>|L}Kz>-=zf{?3X#bF`F5sw5)3EdWY>K%^Z1t(tw%l2p>R-r~9_C+1|5iZbCF zt+xpxn?;sCeNJ(;IV~dE+4HXTgycj2g@^eR!ia7F)%RcjHLkapAOEN#oRTWv-oDlx zkUIMA#nZekewfameo%$w?H4hKRObJgyv5f7v>kj9O(9K0_ED&&OJ_{8#?4~lBa-{{ zu5Mu5k%%prVwlfqGwOd-+3CJg z+;XobWAa5(dimjxxvWHd{pC;21rxJyip+_(Rl1X-Eh(4JKZbF7{rOK7nd8I2!jh7~ zu5yX+>z}mPCw4xZFdCVGSy(Va2LqbD$E^%}Bnhv{IGVe*W!WDGPH_ zmF4@GtX|A+q6;~1nQ&Pu5;ql*w2h~y@$^(>W!dB)Z0z!3e!|uf zOwI-Kn|*c*Tt6g+$1;qj`N6U;3&6{EgAtFRM+L|eDK-VAK~Bp zkE(`YbYWO;?_hG=Zs$g%VLqj8sR^tW$+_LG_1xyabx^%OHuo;$$6oI4k9;T>$2($M zKI}Y7GcN&^y8%@_qdbhDr=AImOZk2&CD32peJc31c8x;;an`?FTW6v zz;1+qyB1V`hTZA-+cw`O$8`?3qbeSq`415rdU!8d2k9^A?zTa@iEC;d7z7ALCuxPZ_Q*LsUb#1q3M7o+X8yLkEx7 zT8~S=HdD@hE%%{G<3R`OTM`&cQLLYRryjxbP%7a4f^FaEAOHS8c9L$JtR-~L_|%-@ z)92r1C%f==d#yLg53?OjtdJ;bqX>ZW<%N8(AbYb?q6^kE$TTk(kf^B zZk%G;ZZ=p&Bu*Qm^I-r0&Uq_&j4_>_!Z@$XwKj-2MMAPecU-Q{4=xO*+A=Uzsui$; zN^&ktmuCf7-d{_u%@oFYy}p@SyoiJ!4`8zN5kRd^aKGNDrfnIf(|CH4oV2wuCo1A> z8>iPdTx!sSr4BnsL>yyH`H(K}cRIh==sE{p3zwz^PM4SbU_eHfrFAhSy%l-6xs)fz zt4KOszH1h}>Vh?wh}uBzi`8m{*@(v9GQ^s&Sm1Tq*34M?PZsg zv>uOaTFGg?yoBk@MJQkoPtLyu6^lruT<(n1$q%CoQx6uA6tAy8TYWFWl2QfgX17TW z0u*ynaY_|RE|My~^guxEl=>>7<9wbjpH)(Ji3qRPS5P4rpokt#j-UMii1*dG4ga!$ zJVihV<7{@dbzPTbIh{_!Fqpv!0FMw!?v&JkGVRKS(T({+BD};qQW$jzfFi{1> zaXwplr>b{*TlOX)Ip+f)2CI?_LCqFk$x&b7+xy}$%|48Mz(BtuMH@m_e6$H0K{4-E z-uFiGykV%IQnjd~bJ<|jn&_YaB22j^YZ8Wxp~^WDt%Xg+wqGg)t-`U|^@4h~Ju0bc zf=h{6k$&WGEG}CkKFb<03uo?K)P>$=YR0U}C9UZ^IkT{sUbPE7H=t6`+vgbyOA2P}T7Nio4(#?I)y|Q`YWI^;)by zAB_O;=u0hO;*Z8@S+#4`bWU&B+m`pmHx|Y+Avqw%Ozr8)UrQ$L$U&7Noweje@`~tk z8d2#+QuZUFsF<)8s_(v%30l(SNzKN)4EG@-$cB3SXkv5JqwBrE4M3a8HK)CIZ(i5u><#h?nr-AN3B{2C z2!ykSMjHgq0?s;Jn6}ax(em8)aK|ck%xAsw827WcA~Pp0JTTmY9ve%nnrN$ZO!qCU zqq%vfRj|ehIp+mIg@qVFkBY>)LMnW$39nPfEa1d@8G;&XqkL0++$BtStOa#sOjr}0cHgrbroe-0c!w!BtZFx! z-DwN{VxQ!$dfvYZwzBQO=+c^C)kj#&f=)nzP5)}_q_ExIjG6|jCi~2lmN2U*W_xcI z-vinREx`sIFg{Ph>Oojp*_v|ZN73>0tRj|H>_dR!_Tv~+Tx&hljpDO3u@}cf36tZL zuoyf_N;m^zm`>UYHHi?=AsIu+N<-VL0kOo{h{d?b4uA=&v|e9T!MU8h-XRn)#Z^)? zaWF#y26I5$slRTe&fpY?NHk1m03bggk)%{ncKJA8+CeqH+sIV8O{zIv)`!uk2xg5^ zVdiB28N!G}8HWv^h$h1m6&1BF+bj)5*wRj;m5`u}AAA_?EWDE|kwXBEAe`3g zS47LZG5lOQ@GHnURWhfInff^aAoP`Pwy#xH%bj=IVh)i=ShjUBS*8yoqKid&XbVt2 zbXxdoN)eX0t#$hf<4J}6kb|!9ZdTGc?#blhoZ>MDW^bIW7X=$d3pvH*{fia8pj!@0 zB2wrtBcVc=PUV3iA}S#Poxh?5l7lYq*=?ed32Ok(k4UH@tdWHY06As$BzF5{r-cz_ zL@9CYpa7DR?PMZiJp6JN(avdrmDpGBTH0=AIW>=?&0O<6v)ofG)G%Gp#?RWZ~MjwAm(#L^dmRVNg+!q$(+HMhNYd z`YMbF77s#1q5>&drv(#&nrJ%*ixW8oP8&l8);-(|>#LFgUE2r=iJSl^=O|!5&UU!5 zUIMBb7R2-p0IPK8Dm%v6{mOc-Y}K%<5$y#d7pw_WopZJQl?^=3<>{S001BWNklcs{t}Ch^LtL(sA~}zH7fNq_vXNr*4;prY3yvSF5>1mw*)6jg1{229vk#-H+4k+0c~t?)#X56hPSwGZ z7gm5Ui~yQqtf({CTlI^zX4{30+k7B!gx}!gLOvT?8<9G?eMsThKPdxF!8#zbvLVy5|oD+E~gtO6U2 z-JYzh2zN6zH5HNX`+dy9DM4*<4FwUkd8+gt#rclpT-WQlN;Ny`dW>PA0z`GW9RdbC zL2@}7H|l>Sr5KmoezPMofh*G}<-%yMWrI;`7mQ9Z$T?<^q&z9d&Gfx-w&+BI4NS(| zA5P8>+rbO-ie#%+I^V}IZz3e~uIu)7Bzb3MW=P5BV{(mW%YCQS*pra*X_pOz*1DKm z!AFy=TmlP)8TApeEU5Z)WZ!7Aq6clRkP`r@-7=c@DCk>RPhQ1GseRU5r%V3%)>3SH zn-3j7*-Ao6m;W6!s;+}96Bpdbf@1oWT{#!9u}w-LjcS(9i^Hr}+k@YqM%V zz*yg53^~mG;kAIfX>!dpC3lVFJsT4u0O{gFL_lY85U@5RRA~wq(~Nz6*e-iS(wew2 zrP0PFTL>?*ciKS&YWnlo_JQRw*agU0ph4z8KvruDa6Lemtw2nr1*Msv4F%FzcOC-~ zcN8%tcqe0%8*NeZLrT9@>p2l2W6#!{Q5$eDL;efY8jQF2;o+9RG_;0saAfhJ)2zB{SlHB zFC3?J2qh_Y73__(MPjL$XMKN_X#jct@+-0$C|KRPr3wCD|I2@?3UXndr<-#gos*Q9 zSyC_o3lGvT1V?Ns?H73#=~Mj2+r$&J_#!+9MyseEs@Uu_83PVf8`l^VtnYk)&$u z{FiMvXoJNc{CkqZtdF)Pr>7K!WqSLvheZaffnqQOg9vlFeEgkqZSw6%iv?9r`fDhk z9BaphS%l9YJ{NaR3=3MhpR(*8uynDChTaaCUO1+(jOXX^{H%M2rjT33oDcO#?(*?> zI{0$FC)X<>meVW%MBQ34r;UI)%=gtn`}^x&k1Woq88U+)1OVeQk@LF7;!3VvLn2j^ z;=BIs>rcD3ha5Ved^ZAOn68`>c~8y{#|sE7)6E9qO7Ll@Y1;V-%iNlFtoccfoYTlR zvWLsPgJ(jHOA7OFdMY#tb%i(8DymLBAKo#BSzYZG;7&BZeI@6+@hBqm^(&Io;VKf1 z$LDT5w&aoN_7&FPz*0{Phm-3D-}UPLK|pfFKEccMX01FuM{*M8emq)?TuLzp@B72$ z10YITLYSBPZ4bl|^jzzGcX;{;BDdEs`gEsdii_eATubfP9%P+E^3M0Z>-3RZ%;+6N z*mdKI4CS12J}gsQCY3(vV`YYc5-p-FZcv)&!S`d=AId$|h=w>{Ri7fv)AbtyXdsVh zH2mT8^{@Xp)81Bl_TH?ZweWdSKACkpcWsT2v1)|@#thc<&6D%Tu;W7d!A477w^u-vef4eo z-e|slg}Y~Yd_hC6DQ>vRN_{VlFOz=qmM85|cuyV%J8_0(`i+}p|F~DhZS% zEPR($S40Ge^~&a>a)UC_uZg%FK0V5LN-eu~F0Wrsa zuu`knOtm&|8h)$5x`4CtSH?#YP$T0oO4fT?n8!6(nRG}u}0<(EuyOU0D_H zBe=HJb#a2jcO&by*hO44HWq;eU6?S(;X}}as1m>O~1@UqB+HO|(a3ym}t!(#pEkl9n zo$~#ir{_H~fOfE3qY1*+@{frB`~Ub~m5;3xa%IuZ_m!HZzkHeA^ zdM%U$iCX_DIqzI|xO~vRjpWJoVZMg>7MEFPR{&rp)9HrR+r;5`(K26U2;~e5BFlW^ zl>BhO%->T@wsnn#5uJ!Uefk@fLa2^|GdN1mzetWBpxFCcC)(tIQ#^n8aXfwCIE(Of zf8&@^ob8JvlJ6w(TAK>RCJdP|U+maA@Y5!~S(syJ=M9aSSA2iy$D_96m-!mz86P64 zay?;Fv2Hl{;ozJn=fXUTa9k$NQ3Kw0T6t@!BoCyw=E)Y0i(UzIet+_8W6?=+O6ALs ze~OC!TILw0ErCeH4F|*T*)cO8y2&Muyhf;V3eIH{HgF*2qAk z8~`*#J>A-FuV0<_S+)xN@CDN{xvoDxeMF>O6UP{q80M}&_^!Xc{-P3gV2euxX!Z3H%R=(G+F=vK;k@+_o^1mIwQV({C#FV(6^ud z16Dcx!|l#*FSV)oekA9|<5`$rfBDyq-r#Nyx&QlC?iXnyNaQR@M zbFl)nVC{61k&JgP^-6!dIM?02{gl;|P5(P}OCYf7;jj>1tJQ8s>MX>-?9ai-1_j}6MbJr~RRKc%_5 zs-N<4q8d~iI%s=3Fx_qa*QNA$5q6Fk^*ywHbytB=Va{6a5?X9es~m4WIJVB#JwL#H zfn~!qGcm7SAe)V8 z9b8&Ko7J@;^(JPK#)`s@|MZXl&DTX^e3WivjsPS)E9XGc|$*Q?n|8P~hx^Ad84-r3%!+4U+mon;4O|X=b&l%<^XO*pe&;Tk^ zEZkweU^(@^{0G^&cI^U7&1z1vK=IQpWlI9WiarH$D=RB~8q~Z899G~=2;j|Q$ zhmQK3_ab6+Iz-79i*njHoS(`0@-aksneT1pXAzeoz;L|i59Ao{Z(o%mP!pJQqJ@nd zBms*KqDnM;olLL_kL7sz0Eo+UaPF+f*|#V&$ma!NvvaYQN}oD40-DV{(4 z9*L&wSDn||a8aa;NwW0|bzB61c`7y(F<~CzqjD+^rw{${e0%*_I7wmw&U&JU7aLNF z3&-I5v9v?<@k}Y`$I&Z*|<>_fJ!t?D_2UjM^_P!kN znoDQV@SM_kyo{HRahZ~V{jv-@e}2WLs~{}n9@%0mScD@Yj^}4`-gk#=0+F!Xh#aC9 zNg_$pAEQ1*tjYA^h zx*kE(&M_``6OH9+L2r7Bsx6T5_>@(Ucz^rFxvm?J_1uZ*EWS<5)79+KCHHYWKDTj! zn>Ug+vrG@K#$Zlt6n+~vb;ALXx_&U5PBX0ICOy5ZtK^#un((IdYFsm7 zf=y;l+Ic`!O&Q9{WNK$Wu9~a8)9=Ql+3LYW^iyn{?~mon{^7bQ(MqjK&f3Bd7FlIr zwiB}EKnH6d^v>xW0TKvposk)~lH+EOMWtG}G8+GSah5qxSM+C_E)g+ zBAZD`CmKYs>Yj*-fFEXFt7v$0-#f=CFXIgGYfx)g@8jy(mX!rQXG;Ny0$dF8z_KC8 zx4!bV%pTuk0q!*-8UVajtMr|HtnIpEZK18P2`&Dj^cwR=ReuG+))6ARVnAH6_354F z7$RZTPUme$>3ph;f;$uU%8hwJ#|IPMl~^qLNcI zeNG)?NToB`><-QQQayH7xr%Ns1Rn1fn2B^Vnx0*2OKS-berRx#Yn!l8D4ErnWv>j z$$;7}W%F`1elZ|`gk?s;Y=i<}s45I-BiRTLa$x}=a(e!ZsE2xv%Osfsp=r{9q}557 zH5}MUN_mgt6qot_YH)KA%>p$QiNV>ybsdO=`L3Tpm<19ubBwKHNl|%r>?5kKa3Vp( zNBt-2+RF)i4PX|L&|zB*OEK*sTKru~EDV}+$q7l&IRbIs=c6jQe#pzdyqLu(@I;xm ziUkr~BH#(Ujz^vAgzV2X;>!Ep_IDz6e3SDjE*xWwOFjp)tPe5h$Wt#5-C6H@LU*`) z%#Z|0mImbokW*4SHaV(qAKjN6iU@H^Dcs+_mT*302;>+hSf*>1>}j#f%$$Q>i3p8E z;XSB|P-?Dtd0;KairJQ{bHJKLFAjSU;1p7d)9p2dIprKE?>j(DDP}1daY{x(%10mP zeBKPBnHnR+5Q-bpITbeqPC+pdRetO`B+~7-c^_|gImju*uyVCaQn>)R9MwWn+Gb*L zQ5FKMj4c$Ue+%9o4m9m;yj=`Ggr8H*Nuqi2jsAX<;E$c z6n9Vt&gEk=AfW5|;c(VV=exmd5Ba}o)z-*|1|&rE{Wu&i(;FL@h6rYTO}Y%H2Ly_7 z3Cm3_p z$ZPXT)KFEewJMJ`=ubU{OT#zNf{A080BJm)$@#do7ih#Vqz!)Rbq z01rc(&{9Sf<@bl%E23RhUf&cwCFpB4A&Md*k-A~9P6Iha=exo6gC_iGAJrg}>#}3V zX`V$KkJ(RYU$z{C;I0V1SA2Ng%b8_7G*f#f~ zDb}6UTar_CHm!18hdyT0H|BAa(odZ8b?ZlclQ~r_>Gnj<3vvWG0gH|vTG3p4V zxHY(_2Ue00yXk_3Gh8`;A|h&ulZNy!2%I8D9RViTfmdvx0jp+w4najdwOETNi*6de zhpd(It1!+sd$M*%VKqYA3=vv{2syIqw)T*u2yiTKOVJ-ijk06Rpez$1$gfyoE_Wl# z!dz`pHORNsiO1UVt#ogzqf)tkK4Ex!aB6!=^EY-?5PsiYL6ZE!KOK{3klV?=JFUfNzdX*4eQfBaAXwes)H z$zE9layWnJ59j;!OF7vk1;cBN)eX7zW#;ixAy^QA<=Ad0G$!k#&M9z1@>Gh|7>BeI}9(_0Z;SlDlwP#g)0T7otTS0lgy=KCh zCvyGq)b|I~rni2H;$(MSuQPu_jLV#K$gi1mzF+1^B!%f}98Kn=vVNqTP>PMH5_~_L zUw)@|F)q_Qy=r;dA5L92q!>ia_2}Nd{?r=DIfb-L{o&jnPGOl;AfPTI{V<%KZ?8WY=?z4WsG0ccv=qx> zhAD$6w<+Y>WYhDsMum;X=WaZiP388QVnpH6lg?l#XXyGEG(`^)k58YR?_;<**LCB$ zY(Uo2w$m7X`}yAs^YQY5eAf*}5KbvtCp<23x%>Xu^`ky!^ZivVJtFe-@ee75WqJeV z7=t>jwU7Gf(3oy-tvF5H@ytn5^8G-rYiT91F&!25W2<)$IV5uH%(3K7EN>1G>l}=y zi*tUS?ll3193i1|oI+Amp6~P@`F_xaRGKt#zN?UbJim33aUicdFJ!yzfCEG z`DU_yF~TCY@1)=E@?6OctS3oCmmhx5DW;fGT=oO%gmb>RC>ztTTF$9`BG;N8k@Pz2 zX^*pTV>n!f<2l6`V>n(uSl7oyrW}`>3bizarUczciqs9du@I4J<+O6eN{-ICU5H6- zD%oq{y8iU^N#_M3tSbNce$}IYeP98)VQg=`h8H&aGXC_(zene8-+qo^diwY`d2$4R zxZGcFufMDk7IPXCxq4l;Z1wz=UpMd0h@;)t7X=BC^2#LIQ2w43Xh0&qKALL{tn|Fku zI#A}sF?8dp8;@<1%m#3K1J&lhfcr*NX%zi{1pu}=>*1d9xAaRlp>Zo;az3$2m7F61 z2qHsMTu4o&*!+_1n>C-)n>p`pFxbO)v>@(WNN)dmp_Z9S_(5$funua=n@uh{idek- zJ55kKTAr%Z{CEUx5VyFtJnlGCcfVbMBw!nT0KEQzxNpwTt{N1kS0-s~!wuTgtH3*U z*H-Oc{LHQV9d~gJW%WH+b&;rAYh=%QTdN@uVc?cp*SPDk%|~fQ^nkLBL6=ffZIwY* z?38LE!SY>Q^6{|A+KLE z22dLdvkfy9SbOuUF3lc$QwfS~EKRky5qRt;xbOv zw|Tg5CsF+!3x@0~K}u6+zqVSpdD__!wp0d$RfPSoBwjvP5hSzV*Eyk$R|i)PFL6r+b?B~S`PAY zxu<1z{o!4#LkU;P(SVnae?WB0{gpXxf{e8y(d>f9Ju%F8-wns7AJlyxmTA7dwO0yj zqt*6KJ(3K^Cr*h|Sm%B=Ua>6jMWV~g=gjTZ17_L8zIRIP$Fq(H0Oa=iCHI}0eDiJD z#CiY;^BobNfBaL|AGD1e=DP^TWpQ2Sjp1ZBY`(u~`65bl6;XZ1^XEU718K^qFoO&! z4%>C*daAu7A87^lPUX&bhw}#jnD5^>rl`i-!kdLWP6x7-aJB)pKIF%j&*$gQ)9vdr zT_Mxg3NTN_7pf7UtV!07Bo8Jq{cF#k|C~F+iaoo>IQwqEEH0SdzCsgK@!o%&_lOvl zMW+eXyICW3v}@`?L=pQx{@s7hDWo_Hr`zk-X1A2~u}wMKZ}aEn|44B$M?@}jbwH?S z2t-I>33gJ37T;-fIwJEiY z;x^qBeWB{wNGk5g?ZnKy#?}dHyC}Ih-$eNS_SOEfh-g|Co9c>u=bTsiS_zSMz8lX^ zN@lQFM@hmGrfUdOiVFxh-vLpY@94bmM*xV+)RO=D@!))~1+KFCfSfRAE7~gFtC>a# z$5=WjQ9qc-c)A=eAL6paxJcTDnXqPA*hNE;q;4)wNw4-!6CfoU!;@2tzVqEO-C7#E z%5a1^ER+7_={{Yruj4q5<6y6B=aK02^wD*_-!byGy;S_wkl@m4#~pKHD|lV?ogWhF zGZ4&DX$+HytvS2RfG#%cLW66$K|5z*bH-atbNd}_7k;;&(}-@@=TSQ|)<3s=iuQzF zz5Vq}P31sdO{Lh(9b1-pKKB1gpx1uow?hnA^SB>%)$-2IE+Q_@v!5)=m+w&o-uB2B z)Bpe=07*naR5|9dW<^JeGNw?37alx%W=XCVP?UN7bv-7VNDN zBf}S|tsi$F1l!WQom9#0a#h>@9(%C;y}zviyZ>Aif4gn!d7h@o>ua?^>t#>ah zKKe{bm02H2D4i(GTOGF3SqnwVdyHx$0qg9sSORj!LN?ZI1Q6{GDJ!eP?!|_OfoN@S zwbxe4mMF5qAjo5r0k#?jsWtQ_Rk0Y!-YaDHs%P0JS2jTY@<;#Y|NP%nYx7P64b-c! z`@6__?>ja(Xp)pHWrkVStF1{QTx)ZX4yPyeY3h3li4NzNk|(EDbk$*6eg)EW`vL+Q zF;m=T=K4~0?dejaK{gl=Km@JKs?nPqAob%B5mN{vGTpuiOKeTkx&2$Th4n0>1(T_Z zJKvAP;he&fQs5X;ve+{{G5N07EHqi$eaa52g4+~>u=L}BoYTxEbk1UM~ z56W{{iK&e9qV{T4NgOXfAQE!`VRC)hZhU{3Z{Kd;ep34c*cANUs(f=Zin`$-DJ71p z^M2lH*7-2#ytgSYRu?RDLWJ@7Ouk#DH(@DOt5x%f91^vwE?dYU;}}WW({1ZK7GY+s zt^gp+lj)?`8(jUs4I4p&J<*mLK5GYRb@$@_#pK^#?5aDIItM#jK_ljcrEttKbE~^?- ztE)`pPvr`0Y{*tBDl2ECuvml~vq<8U4wnyQYPigIQW$;BZ?eacki<3(ASb0k0m6?wrp~Uq(qWt1?&t? zK+<;{sbySBAy;4@K=il-&Mm=YTtB zKwOUmBopnB$axmF_bc<(ZCl1mO%{^0wb8mRFv*Ot(p({<)ewt|Su!xkWZr@F;D-^KQfoFCEbIU}3zmfzdbG&bUGo6zhJYi&XAowXq!ZlZ`F zE6GB|>(q97^7&h!>P?%qg$*wv-y`D&fJ!SJG|RrG7DE&6lRa(C8ndRNFv|mRP2NMx zRZ%XRvd^{#XQ^Tjw;T6TuUZlBPVRa6E%o>)8KADiUDmw zRc$EhgXD&X1;{RnAVH-ztr(Edw7Asj0EJs*9u1^~vOCGnTNY(gV2vt!AH?{m18*j) zRlbKwFKO8Wi>$Xf-!@y7iHNb~dTKyLW+Kt!G1ru+4e_oF|M9(Dp?M|wA_!`o(s={g zTKClvRhqmO_grGOvLm(iLbUhNcRgnTA)8VkV^}byVzU#G>Gn+@6$>sGwpi3$IEVRO z2L4??Y5}9KGL__I@hZ1P5^N|l*#(?p00c=UF;yEI>_>OPqfOoqV@U{_?{D=v-(<2k znV(vCtv`&A??Ax*U*`}pEK^w}YDd*f78dsX0RcslPO!3|3tczp6sOb>k}E2`M=>l) zxhjN1yZyA^1xM$`@dZSd`M!M!iaM@Yd96$X>j9C4rP!MUWH>yPR2M+(hC@G|m`#+M z;;du2Qm8>2Pa&Xj#FWj#`g`R8t5KcB`gl+Q$^bb5#J6AmMM>rMm%<_`iD=DXqSLaT zZH!SGs+nt}B`{f~VsaRzn(6#Q53p(~U{1N!TPzJ3THU;;>>KSJPYpQ7slaG9Mpd?< zc-@**eY(t(rkd*M#C5~ra!gUxjLDvqOif@;3PaJ)?0oN4uZu*~nJ7twvlSJIe0C3K z!i(E9(Au`EMWtuHl72#RPJ}SW#g*dB*b#cW&HIQkE^2HqnJ^;kyP@k3wfk*WPH83% z#;FL?UCqH#n;-epp@jyE$UI%OrXlD2;VI8KSpC`?6mLmIweg46uex)y2NCC#2pBa{ zJ$E>Sp}0a73BtM_%2k`LUsY!`L6~u}bMK}mFn855PTcsxDv~4yQHDWg$k(||ShjU&?ZKKfTGpRIx zA^<}hL~8w*6eTiwkJ#&@no`KI?W#1y7=uV6(kfQpdZK1u)z$lT*<`N@?RFAaUSwIq zuInYGVipnR#H^pDb)?qQfLOJwh|z95a*QcOjscS0!Wb-qp!^#3qH+q5mvWBN6ICIn zxF9;$bx6*4ec}W$3L^-+uJ4CaDpU)RR&Bhmz=mt9PR<&1bie*06eJqP6ClR0Xl=u67GCd1nBPMQRt`nVU2c`d;p;E|(hY~FPk*#-q(F)bbMath zHwZdFcsv)DEuP2;Qi_XiWVsV=?|yP#n1utUYBb6z>KEvDcUICohuz=`R zoZcpq;^AqqDw#z^;Gple7Tr(;5qV@I28Uu5>8Rm-NllrkSAzyO94~EimDuH@238-p zBr`maW91dsG7%bOrY!fXjs;xT566qaLt;>Vf=(l3O>GorBmi`}dl7;#I_E{ebsZ9k zOzn_GL?mqyzV*fdh{$yPCL$bXVM!?-FCU$CI}J#L%?TTr5zzTwx3a{Mb7+HDCVK*r zn4+DjXC=M zC>(VZQWrVqGfI9zYAZ{>VA;k=t-!*fJ{I4rT8CqZD+Z|=GlVP>boC9gg`uBv`)b<${d{wyQbKBSVP#iW&;8RV-1rEN>X`@s$J9jQZ;l#XjNMAi5( zCrxV7KgG<);$lBVdD-8r1s=ry@3f7Ia|0XO z#GYh)+xo_~r}EGq-%koy+1s%;LhN}i6f~4#2ij=Z*IoU_?XxRJZ^Y}lBTv|r(JlVJ zDVy-oc(7g%Qaee)jY&MeSxZm80UcB~6dI?djC?jtvPVy(AllrR6QVS;v@Dg`lLQ0) zTC~fy6_3q=gcTC?-HZjO?aKNbarKS=8flS6T~S?EvNN=)q%Pt)Ozr)U@YZ z<{UdFmnRwd_6;0oyg@8Lt!ABgGqkVvm{|=jHP63w{56q64OLV+tU_+ zvYE?9(IaZ`Z!21@`&l?^h*nD&MDU;fhyOC;D1c)aPfv%-53TAm%vVL-i12VYarU+s z7qCf+Q{r62DB$DM-~Jm;A%$62M2gEYPX@GY+T7(aMkLn_AQHmjedqfj2R;Ze0}%jr z!)Uc|N}5eYzVG^BIGj>OL^5;NE1|zbB=tmxc}9e8IB<%se;JyzbP#dv|muM&-{j3y9h$Wc@sIijtzchGE7A7@A|5XvE9F&jmx#-J3-e9aqGCdo)#rT2oZ>v`W8j=8 z6NvyiM@TG!Mm3|7SZ08T{42kczjB6W{z>5L^#Y7b0S4(`W^ttcV?R2@rQJU z0HRypeEa76u^$d8#*{+?RQ%PxyjxjE=~#1G;xd2!+kZpOhxsa;-oF0)9>o}>(luEV zU;xPb;rN6(WX z?z9v`tAk517O_v+=(2qRQe239v1Dv+HvoM6{eQ$MDUgp-5=f$y>TC^i-V4BTf8`Xr z95E=&^K^4=|2j9q0!cBFbI+guR{1S@AH#GF7MTM1*_@hMN`-e;tM!Lt*A1>eB0vgL z?jD&Vx*HEEhA?L+rj}yP1L|`pVY=rtD0bt?Iq&9Q^j4)k)Nh!v8>V{EsH=Xm>uRke?LPUHu=wb;i`xTkC6vb^D^4E9_jAU5l zAySjfYK)nD_psQ$vN?nH%g^RD$*VowVG}@z8!7vH$JOT4+~(xTgYG^T8lu7`S^7;PX1w(9g;Dr@=m_bQ&& z7u?dU3M8!dMpt*DUIO_ov4tS8F`4hY!%!YS8)5~8)Pmz(hrcu#2%tF1vY~6o*?M{_ zEu0k9&98fYn#;P?*)?J&SxY;hO0lfnx>}9cwiD_Gv_`g?ElE7Wso~SnOC`Oe3Z!0=GNd! zgD3T2Ynn;f)xWY*KoQdCE59Z3L-M!uhNJ(^vCL0 zt09}1YCnZZdu8MCX*fQ$yPyuwoFCM%U(yl^aSph|Z-DOxM9RdbCC^+Pxvp&lkwvDZ zW<)R9$&hq#0tkxYJzidlfmGE8nwg$OJ!}ec0LY>9Rw8KQA&)}aBh}-7(lQ}A@*N`f z<4Kv$R^$Sq{U!3n%NpELHB0Ut7_f&$kaiLWq!{`0>vNEKq3-b7fJ(|1}FD-oF_3kb|g{loc# zG7;5Z5tqBc$;vZm34BRKwAG-J)omM1pzamw9m)iB4uz>E%a6N8WP`DK25Thk1H@Wx3|oYiLojUDS@b$ICO4>xLsa|MulCrNO3kAvdmn zRl-0{s8`(o>E%ZNxWD~O&O7H*44gs?3&)rb57ZR9i*-1REo>bg+Bs%t*g76DbyGX-yH7l)xTj;T3@ zJ_f0)e^%4c*2*;87Pa}DX!JJOc$0JCR^6ylXL##*#tNGx`{hSDWHkX>xz&ca`!ALQ zcR82~vnYs$6S4!J8neJ^ z^oQ?O@Y3v(O$QFzxbG%PFb5(wtv9Yc`D{Y6UTYHu*>Gy4W%@NWC9WfREju1DmWREl zqShXywzsi$+TjWUh=9$Xp-%O3+86H1BOVq9?i9z3qPQs+TLXr14J#jG!&_SuMa3#Y z%mbvg=mlB=Y&$`29V2Qs;28VkrRxuQNeTkqzWrP_CIOW%1)E_aYI<1~hOr6Fk;r+a z8*8h*tO=FDmAIeUY198ZA+x5w zGiS<)w2K1(&~=^CBvO>DTvc>H%q2pt>C1LcIU!3}*%UgFJzib_G+J4d$Q6P;*AFul z>4sz3i&8X6r#|fC>A4?HAxwq8I^VBZYKzYMltR+ko=86)$@jzItY`}@9SV#v%oC_Y z)=KAF46}t7k_V8}%kLz`u-tSwM~)C3Ip@fwlsH9gPDpLyk%sfl_pA54>pJIq=X-q{ zy?yzM1|N!ub54XcpcK(5+FN6)G98G%drbSq)4^>-b$%LcF%ZL7W3DZ@C zl^DQ{V$1p7fCDBkV(1G{*ty2a$JE!Jsz7YT+@1-#yHV4Mld`?6ZH80yj zwtZU4H~~9~*lqGoxUw`PK&ww249>b{y`AJdLn@8^8U&B@ILTy4 zAh_Cr_XfDRR-ipKSCh!B2j{|*lt)bSdnb4);%VnQrKng(A|=5M)~*?Gty8ybS_~z- zrzycSDrePZFoV*22_T|I@lHKGsI&_>Qx6+te6v&WS6%CnMA*La@7KWR%P ztXg#D6qy`}x8J35$2O5bnzlS43a(~*mMMF;6Nj}Su0a{j6;CsfM++u|+KE{=s%k={n8egMFRQ_(ni?62 zi~DFbM7C9%xf3lV93Klr^qe9RIq*fatssnCx8=}t-52uzR^ehEV2u6Y>|9q{K&N^m269eu=GG|JGEunHsN?B_jo*p1w#$`}&E#$3Xffy>1YE`qH-!qc#Uq!^4nO-`Q_9s5~YY#Ydh z4;q6q02Izz#M)-$lmL=7Ey_8Rs2j!<14rk4=UlhUS8Nfo6_U5unXSY~85YjA;qmxX z$SGmD6@UmLgfPJ^m%W^fOwCcZjxgVI8;y)C<($4oUDpAEK5;t7!fZOKR_KyND%Inx zs!@Hv#$_sDNn+e{Tc{QhWrJriQ*$FqBvrH{AmDs^1CxBC??=pingj`oPZ66@Wf{X0 zS+~Hp^<}=l>b%^!4hj3=$ZX}lq$HJ(BPj)&I_GGl6a#a*!!JtPP*b1{I9SwNm>0av z_cuejBc7gq$ZnI!oFs>jwz)B-1*-vA`e6-{hp419PC@cTv$sGF9xsgt74cTx8K)TL z`?sI6;h+$-JU2H{Z#p?Ir2aV#g72K~5Mj~iF@Utp0?-dfjXe_9#VPvAAaWXMYfLWZ z%4XiUHo@ZQBVs;pJf5dFNin6sDRGMZcyzwU z0)5Ps2F(3f3vE{5Wj|_?c{#6pPLaUn!-X9UC<7)6EI_G0C5je6H0MtPy^fcUDHB1< zLDdfjW{Ybl@(f7{=EXglJBK|09?mc2w436R!W@^o8h5mtn$-;~k`M<#YhgE-n+Amw zL9O({sSRgPGf_2S8wA9cXO%g$>EKm>o}wcA3P+z~)KGih4I&(t*%pDGK*5*ZZx(di zTL6Rz5+J9z#GrC>*A2S7tYaKwn64SpLAX|AaE8ri6YH)7Z<7|(oCXNnw!DH7GPc73 zKv*V@(SQC^L93AS9Of`z^`@w+p*46|>tEek>q1aBN=Xq!h`gxaLdX#SfCJ>Th|Hx% z!4he*3X!PWo{Axalj=%T|Kj_D;wr!r!>Jn%+DH%6eVK3l;q3cE*AJQxx7L)a=!qNY z3hr3e+F39s=0wir0D3N~x^{`J87MT2-Ebgs5f|rs=e)5-6+nRm@5uc0w;>egFW= z{Z;!VMDFqtY8wr@$|wehHw|=Fx^&Q?Jf5otAkKvxxbb1lZbdf z^rt7Mn|Vqlj9xc1L|mpTr$uA5eRoi0Xf?d8+b{S)69=gJ3Tk6Y~(bVZW~$ck-U>p)qn4Q^zU;y%>V3`RM_sS02k2kS)T> zm1r^WMhcfgt;DL?eN+Z*Z)%G|q5K#(Qg5}<-Gob=-ih|6JPsu!v~4s`yMYzFAuY zlu12pe@|T?sC%w+9on%&Rt|Wi&5(Wjz4E|tUBVKg=B+f?xh8eqmI_-XDN?DhO^NWi@D|X&htDvX{1iUfKUQo{{x&i*0RTC;$K;07*naR5_t- ztz5i4MMx#0YVp$TbdViL=$!6I<&za^Ls>t7?Rt~k^j?jU3JwDRm?I}w#3=>KfQ9>C zyKCFKfO!H}`VeI&X@K^rmEf62h3EmJA?wuw`Q6c|&r(VvsNPV!CN>vfyPlAByec$p zcCvr^$A2JlRirD8maO?smP&=xpwOo<-=^C)(mv`+S0|98;cH#RiBqsTng{?dAAeUE z(CW3<{-N)Bbl!J;ld=ZwaXTkD#G))WyhTc`A4rw=AZeMb(`9TRR8@uk98QUxM~g@< zGD{}s$J3MQ)J@}%J;h}MvdXwwJSBM`#f8J-`;mO7G8}Rake2(kY!m%(&`d;K>%Qxe z+~NG9!*E#9K6L9|Vwl=g1ikai?Uhq>1vw9xQ`X{mdKyp9_t#(M`&DDeq3t zpQOlbQuM=dI9~L~d4Kz5zP%pKACX8n0KnTXe?hhC1Bl3Yyc{kc_1O&bEyXE@%8=7b zS6PECG?fSem9W*1N3~Tr=f~3v3%~yK@AYINd4?^(DlymkxKR2K(e%J- zb%f1nwcQFzXPi?c@5^@d^!d-iNjLx?xn3j*$CP4<5t`&LNl7G~o<7I8++TmOw!d@E zS=_wuN9X%?%esF13prn^y?UxfYq&jD z|LaF`t{;!esLMPuHn8(r7US!=GCPO!5fwABv?*t{%{D2~bUPC89i1`)a277=Q3AK- zQ~31|L^~T6d937LiZ$(h<1%h&Vg;yQ%F_ySdO!EBqIjXzYe`)|H|UZ{mfqk@#0e+1hSl(>QF3cxci9R(D4iyf*TMf%Cf| zzxD*Ego(6e@Xp>;>6-XT|hQr0 z_FA`{yKqWj(beAdgY*3|-M04P^;2o3SXc_%ENd|e5WM^NhyMft(7EE>&bMIIq$MN) z3CrAetYer`T(p}NmWdOu#N$XTi9_fQ=l*bBKRW?LQsUCv^WC7!B!)Qv^FR#0hFP^G zmmmHH5x@QQpTl(PkC#HVtV1~GDz&4509ayNjG#}Ap4yy8a^vx-8;?*_{UXbBQ~QK8 zqDmr9&M`+$?7JQ^le&@5^K!omr(}+M@ZCVpT|WE{iBbx}Lat+u%l&Qb@T|AqHBzbd zdeGfH>PklQ-494~IDc@yPjNybq)wRcZ@*AJ$(6Q^iLjUfBrLOD2eIf3kIpORkR<_& z(l_IB7iOOe3$CXm!0N|UY}MvayrcC;*j6EEEmm2{fTbl7*YjyPIFvC-74$d0V=T<> z_c2tsIakV7;BJG%`oZe(Nc}`Z|yx_ zUE?y9G@3Tx#$1v2y#^SDc?4KR)Kovy%5;n?THa2U`pUVE<_chy^fu>zSd(yT%zG0A z*iISc9p?tZJ2$$(+ptO*@wd9Sw+52xwtm-ZEzsEQt9vF-DYl&qsYlQ6I8uJIWqobY zX`4lP9Gfw46<{cs`Bw-JQQ#(TZmR93FY^8Pwlcl6L=Mt0cWOtF%>z4jo@q7 zFjMaluBhvTQLe`P<%28Do zlt#&CPES{K^GdJb6thP@F{cl||Br>Eo}hgh+6)7c>+`i>W8_jb83oQ*KdDKVc`@dABrtzrNpxMj>zkGFL^6wcn2Wg4TsC|>7#yD?Qi^fDFY_I&O$w+vR@%iO(sfwU!O1xy&$(bi#KZZ66700d6Xxmq zRreGHBNX8oYr*d54fVsQ7#mTxnLSqOgiECi)r8bmf@@RQ&T(s8CAvtZ@ z9iM*i-SG9V|8Liir{_;B{Pi#Y?7N;^r&faD_}mXi-Mj8@zof7npFT0ixJ*cRIK4jaSE4 zB4;EK5b}(yL+KWdUgrgNoM@usNFb|hL4*LnVUtzV96V*~>)fDp07;)Ed!yhsG)jRH zx^yZ%z+Cf$N=-xILdK#T=C>C)GU1wX9YyPwi!aP zLxO&{#zNsFx@kGD=MvldI0@;Hqt=i0V5{9)Y)-20c7_ z=+yH{ZPPXbOjEn9#88A~3~WCcw;@xRIb7D&W&)!lhB^@bPEEK@Mw8mA5efAbwpk1_U28fErMF6?2sC4mEsIO>VAmB>J zxgm%aXMLWlnS`}oyVV48=LJ!DZ`zJ(#I(42VAm)VXokZ@ldsKrY`aLPdIr*L>KZSg z^9!d<@19plPxb%P7Pp`8Z&+XNdMZ!4LFqoLaVowW#C5(O%j4NZCOQiSisq!&^zixm zO=}q56)wQ#(J(Sd_6x9#p`@#7h5#yo}JP_uaF?`LMQ-6epqgIT1zKQzl zPS2mps4}GpAaS{~n9sKb{eeZaKt7=)$=qbdpd=wMWT=XqSwuq4pVC{d=Pd6#K?&2^lxOgD8D>9(fQ=_(z`kadnhQqse9 z@wbsPAG98L40OaPg^*InC-JIg)=}azUpGz$03OeZAm`XbS?S^fAbrdWd1Z^-CPElb6b?}wu~KrG)pqaLJDfHbwFedYK1e03aPTm{VvHtUW6Izu~^ zJ?n5eGN&9Ah1w)gmYxkq#VaOC1$)&Otx4en+hEa)4#w4dCwXn9Y-jAol`K4?|mBzv>z$pe0%a>2KO9cw?H;BpAZ3qiAw+T>_93Sxu-EyN!u|CZeePV>cf(QlA45xrMbqT%v2MzD zNilJ9zRMo@{IQ$8y=?R;%ron}%{g!Qcuq3kzNsuDr2v4=d2)_Z@Y)5AklbyD&f@z%@J|JAfWC;{UX!#tB3#sbCO`s zSDfz|aIX$>*05hr0T6GmKkF(eLYlf+>5Fi=zqYzwO(@opskTtgAAdx2>QeCiNeciG zS#DpO;|Z+cwhjTN+qdezNYOei+9i|h6Ohsj^d;y(Qbh3J$aTYTeBv<2aMx4YGF>?Z zz#R*@3FRBBem3Pq@`vNo4|@0w^E6LyDTc7zA9WeIEz@*;^+K~i(qZg5KbcZPCJ|%) zY1$&z-|e~)$@%`^yIx=6A=u3j+YNHEHNx1F@@>=_KPqR zRt%D+ki$xn3X)hvhVG1rAzR3i2G#wml0Gc=ocjnMqURoln7v`ncY|Fif#?Fy<{TQaJa8d*7@$vzY?$sIG^Y@t+tXH6uVs3>Y)(Wedv9i*v(MfUYb|#-V_^O;UlIG{t!$|)Z)To|6>Ir&H~Z{+bbf4*ZDRU>3mNC9 z)8j|Z0itJhQ4wLq;?(2UkB1uKQA!I2B2+UJB3RBMEI|`y5(5P0p_b>BV=J@}FM+XW+yH!v zAuMNf4v|ie-wfkHA6r0ql;~dtDq}7vytCS_ZW@Z+MmT8}9G6qcr&ZcYRT7n>Qk}{hQ>lpx5IIjeg z)6=({f^ejwWT@bLM!$;*v!drj&Y)ccm`yF5Eepz4W+Ns5AjR0~RAW6s;HTrg+QgI^ zVo51GK!x?9*f^)SynfdDx7CrLI+hT&wSlfBnp8yA^NY%XtnpU%j?gHienush1zjJ&A#cQ9fopuY%8+e<0vJNU-gZD>CwSMkPtiga-lvdD_c?t6Ut^SDK@v(# zyg+r?Cfae6jYb}83cN5^6jvvm9qri8sCPMVT3Y7X1#AFG$t*<^BrVsbXwtJe%r4Ca zry@&aSB$o%b6rVVEZe?=k&P)@(@%5;4APYTxfhqztAT26nRJ=~O~vFWl3E&i(}oxZ zR(9CQzb2b^xLhgcO!-}|LcfZHnUN_)Zf*w1DFL#zM*tH(((%i0TMVIf;MH)k{N?$z zy1uJoLPac03?K}g=SOCVW>*&=(yk%5xf*J3A68kk73}P>IH`^cMr1T+4=SikxhIuNRvXGjyRfQ_3I+-^G1!jaVjnB1TCP~Zd4QBP@>S0+ ztzbeu2urlR5s68M)tAXpjYw>!n1v}#Kmu-oy@5?Z#4V5j8-~l@k+eX zMPTPXh+PeKwW01t2|BLJT%z*J^b~9kL~ZxG-ldHdMZXv9Jw`0)t~dJVKJNecpZ*(Q z4lxLGST9gg;zX3>3Qynt2knFxiDCWn^FP>)jL4BAef%mwR*#}A<1L17DI1NqN@o}+ zL|8Acsz`NyJUxA@%Qvp)<@~JZQ0bQ(s%aV8w2>R9h@vitczpcm{iG3wF)YlyeEEcq z5J($eP2=0~UA4m11HcXAFwWNj?nTitnUIPyKOj%ekMo@$MpcD}u(8`+Iz4^4vBCX7=Okhw1+P_t~K^tMCJ-O zsgOBlkf%gBTAGrgFXVh&m+UW!txboXa;}mO5wOwlkoi_I6WJvP!f^}_-~9IU_%SSJ zX1=`qQnNz!33)#-CytT4#?(a}Sky}7aJpyauwHbNB67|--LJy7rnuSOt{I||yMO@%HB4%4A!!n{4DR?*kT-~LsG3hUqtF@`N_oCN@=FaEjyMRI3J6 zYUg&A6Q>Zj^_xHY8xvNF$|7M-FQ0y2dH>`+hb`qvZGKcn`hwZEt)JOdX^jYf^V`3U z+w%JSM~%DD#b38+5q|pS&yieMU-C4B$oWYH1G+D%2B1M%Irf$7NEMN$*qhb ze)_}xhaZj)AJ*4THbPD~g>BWE;QBHiKKw|<+mBOVPV41MMQBO}JD1n0i_EO|&<~SF zTafdaJV6xJ3joZ=JLiVAG^Y8B;-re#^0<_1dtiu+;^jj;Dx zvMx2R1J zfPF4w;kzh6V}#?9*LIF6)wfig)w1}7Gr6V^bNVf!-4Vf({3$n`LF}I1OA>_bTh;eW z*o&BUxr}6$`|Vx3`C=N*3%>o@W{lU;w<;iqdnCys2YoWASVsZlmVjU3|KY#>m;c<7 zv$O*Beke5#t{3G@Ct)6@LrqpB=dUA=;(96SPOAAYx%t=wiJ}>VcaI<4Fez-UT-@{X z&*}?o@!X=BZR}w+ql$4;XK^hz?w-D#@18DSey$IgnVI8uIooYfn-4!s+T%55KT28V4`J^YM{WTrOV_ zV4Uwuw5L-l7m@q?^FIiuaXOLn&p-b?0BDNjN?rApfSyXt*r0{!kgaX5A{B+jaPYF#s#;rV zpT{XKug{Pp1}(b4P>9UV7&7H$c^zAZs8`4_Fvs`b|An;b4Y%dX<;yQxN9#Q4{{8nz zE-bGi>E)L{AW@dp4`We1Cv^cNaxreTmh|I<cTDq=cScTd7A-9jhDXi3t{Z#1f6%JAD&=o_z6+??{DTd&@BN{Sp6$5j$jtT{S0})7JQ>QltNF^nfq*GOu{cP)E9Y6Qh-kg-8s1IbA z4&;Z!-8&?j4krZ|&R>4cp|g;2h!|E*X*%8;QE`)9)hQ#H)uoyctS?$O(O>{jq(pt0 zKK|L?a0*G4GnZF|$Eypm3a3g*OD~`PQ0E}y;f@nqI&M?<4$UstBENR~ZHX zOVtm6-0*^emWpiu0ls111jY8cBWepFN+*7JtNAnKY`$eejlSQFrf!r0Ds0GtN`o*d z*{}R|vF?}6(x*|SS)_V)bJO|eGq|NByJn6y%nSPihCAzT&@wJ znwUd1D9X%xyg5p$Dsj^r8Bcb+t@6IXmbPqlJ5w{cVR(ZjkJ4(2#lWTsykI)6pJE#0cm4R}*RV-+I-U_Z7nrX8}wRciHZht_*}Y6+0R`q$gsZ^^0oQO*W~vFv#=nE^-^u$h>fdU00uK8yR}|5ypXxt zN$bqd?d;iZ{i55?4~@%q8GP**D%N1ajvk1A!pbYp*Y=&exs2F(q|(WYM`2qCMLF0~ z>G$@E8G^El9If8#CZ=-hZb%nGShtA+(<2oA8Wa`M-g)7=73{tjyMJEu$QpgZ-YaP@ zrrCq@n44%9GHCsoOtbz5MD#!ZxBm$_Kg=g0cYJuC!WP4l4K0g@dM%1MMJn?Nl_#gT zVV8#@+CwlKBiaJ!S8C#PdKjlu440gIhID@UL`diyT(ysS)GMdi7Hid}c{)9u9zJS< z{5T!lFs_%E5;ccqcExITg(a{Fkfy`^I3Hhr`9~3+@1DG$zWnm<$@yVAfyi?H?1y<6 z4>~?)^&_avY;||z6t)Wj4(g>;aHg=FLs*o>s--KC!-g1XxO33Fd;3Q1b|(b%qd^f5bTT)CQNdp~=JdQO7d_FyD3nCiG?|%RQAOJ~3K~x3r%I@Tlt?X_Z zykPEuZtu(rEog!D?)$&s6qHL$ZrmftgZcoW$VP&xQHL-D&#a- zZ>({x065=0B9dYx>*cjJe7CDFJ*zu9C~KH-wZsIX!|8FH@AOV;QrL7jl?e%7UO$x# z-I!v`24k%r%$}|(Y=AHrJ9153&B{U$^@O{^PBdTu0Yvkpbn2W^gq+r^@`Eb&&WS_E zhY$1dUX$)qTt(#a@)^6X4#5;;9f;bpZA!>b%b9Y;qmV_^N+tPmuCsqX&eP#;zI)OS z49jbZ>$WZ#YZM-)L+xl&ic~96fW%2y`{R7~ybUBG=OrZ*meB>8G~`xUNw*3_lU%$j z0&0Xx<^qxPl&C?x%tCehm60Fdw+IEm1BxM#{7w%OYr8D&dZ)COS>IwHHk{Cj;7RHt)x&76Q4aIRTYoT5T^H=ekN%~%CsX<{ldj!OHq`rN8^ zyhmtX}*d0pIh}j@4*)vbN0Hnq&a7E(%l_`Rh!OO387g`JvBBR;9 zr4b;@b|8HhQcK2WuZ|9tD}N)L9c~DaZFAa!uClOBJt0l6QwiZhq{X3^>O&^b4asi| z5lOiwZ{GyD87l`!hzvk>-Ea!XWzM8Q8pQ|8D%r2a30M9PwTVPa8r(J3()HzX8&$yS z0527P%L6>!!_?3U3c*{7%ge2KHTFcfGB^~?k5rfx#nSJ~JTDj5P76E%hTf(5YLjdh z-e8RZtK%cwG~n(X0rC!}lglO!sG`z}DvJmqksC4yM}#{%dd~XBUH0M4z1=vsuo*dH zAs)A+nu>W=KadQ_J=g2tfN9Ve=a3ju(_dQNd=P7q;R&N<&ItQwQ#hN*ZE zH+7NfnY7B|7*Yx;YG_4P-iu&_{paI>P$ zx%uvi$Y~aFN}*=A?(B(oVpu~JK_o}zT|z`~`ZHxvv0CK^Wzl&J*ubzZF>G3MId?>) zaXMtLK1`f4liQjWrWlAw>pNM`+S&MFa>Eq2ON!fcxYNE+y}mT&4G@Rvn3t#%VL{pS{_%%*^FZmd^t@ z0K9zpCI1mZa)a~ZFwW!$mwn)JqoMCe)^7GrX(>i6fJ)-AL3)U^bJ7b?+(pr2<lzLTXWu|@%rbf?z$E}Q0Kmawj%Z&e0U4``wh$*fLH4(XSIs%gOKE*9; zONaE7_^0xX`Trp~t;O_R-Yze3Tc-I=EuV;7F$6$FoDTQOtqALRTh2``S&D<~iB|4& z*;p76qc9?|a1JcvG#>A3>N1gY4lOEvY0{6VX5v5e-${SP*H@K`n9-U9;vB zH%tdIM76M8(xs#0J3mwbuLgg65|GO1-L8XcdQC!5!sfr^P`${q!{D2EazuUEl|_# z?!DrKh5VyJb~j`e`(d^tyZ z2%4mB86`bK&y22JV`fY?5GQOGgP)%eahPU}8`NO&@-$mG38#RN6DLwwSp3FC5jTGZJA1gC`m=1AWVp#n!57QyVO;#DkgHrxD#pC^ZMUUQU*vJ+EMgdLU zOANO_(dO7-<{c>IFmT0jN=FF}2@o$YzmOXbcTYs*ym!Osr+FBUemrOfHK$E&TtrgA zB$om+mIgiK`;0kNIMZ|qd=Y^$AUJZl1V-g!&D8-_i=JVeMfmxrzeglcc*{`=+bUe_ zpOU0>_x^iL85Ci+Ej!n%{2T#TVx~UTd%=1|V~QJ;8`uOM`4gzp*7Gi@4j8)rofnby z^)sh<_wHLn^5dMHm2bAZ%yNBh;7I57RK8h-jFO>++JK`YNZs-AUJr%FrfcTV6OO=SLzxPBRkK zvlEEM!+quW7Y_u^Wj$ABX$|9)dIBM0sZZ+YDjx2iI6>l)Dn^bxYUaCgqq=!I5$-qv zc~*ic25mxgZ|E9JN5}j3DQ-2@HHIbO7G*_%aXOJ74tI}LSaNy(#d?-;iW+u^AT*4s z_b6iy3EL${c96x{>e$IpEoh%q6!!2g9_~H)L8Rzwc5vVQa4wIBNtCwr` zN3j=yItDB4SJ6UVQ|fzPj6TvK7lR@ol8~_2OxN@?X%}MyvWfz|+BbtG*f#mWe(qhp zZ@{E8XGts)5>WQtFXV_yI#tR4jwV|RVX#>RHtL~mIk%D!I&3AETp}W(*_(PJ?DO8U z8>B@Ih{&(Odsyi+B3IMzek5GR*HUg2W_18LRA)#v;3)3c3TXglXNRT*Vb0;YN-Hmv z?)EiBFqfrsIf)lU5@^Se?IKyO1sUxiH#XwJ*o-i+bgl-T61fGB;$F*NGp_oawI;wQ zKe-eTP1m34X}ZC6+3#|5?x26iRd0Ydh+x+S5v7|!t3}4<$|gWkhmlg~PE|5x^aj^g zR2LO@q#I`I61n%Or~#ZEGD)E3=FGbAnz!{0aR`=xb=gD2B4)Lh#c2>1>9NopN6;_z zD6#{W$P=_`q@(fHjRRUMrTGxzfPJp)iLY%Q8ZTE*hZXV@U7i)um zs|?64>4LYZeL-`K&^N3>ysfJi!@7E##VEUs$jn|&R^g`^zr~6RF(0`~tx6Yi$`5?@BW?qEY zxwcM0ozClF`R?1_vFJQpjf>99`B}MMI=RhZ=vn$5?1NM>Z*OYMi1hH`M?W22KmQ@e zoU+u<)Pw=y$SHy~T}%;;$f088N(OO$EMxg-iTb98rU-6ouK3Q(d=J9g%6!N~Oq5^dyNt z{@LGfikvom9a9V`Y?(u$QUpW3w|^P7cjr+6h{HG$xouq}OOF-4qdxQ%R4|}_By9_p z{16bC?;h31tMoCrEiWQMl=(y{#pU&jJ*}0$o=;kGi0Frrh}PxO^tpauPN_JNIzLoN zT**Rn#jPJ|Pi(*$jN4*et^IU(`sU9;{cI6YiR@uj52vuL^$IQdUPrVM}QX>m_aL?$AY2=S8f08XNG&j(1e)l-ei+ixG$0 z`6qzL^74tC_v1`{c>n!>xSXFaUw$d;lQnw2-Q;nSl(zMfMLW)s8`8GKZS~VkZq!bu zwtB@p4E!*XbL7XcoVVqy|I@YzMioxOba2i&@AJAzsrb^>nNDKnv@Pnoe0u!&`0+Q< zICh#b5Qgn6%sg22-sv6)f){r|75IxgmF!oJ3@tkHYo|?)4`MjdnhfN^HuB86YX8 z6iyExrV=HjPvr9YtOQH}Szo^tLYXUFc*P#19Y#C81t(5H)iP?X8eezP9PK zt5y!u*f3RrYg*ziki}GkJNG+;KS81W#?(JI*K+NcVA)cICxX!FK5FN)+r+iN?#TbU z9z9Pt1*;cS*O*{7UMTF==0t_E%c5(FQmnSO0`T=z2sBgzt60Wn>h|VhlbuAtXoq-z zA52y9C&caT@&=_uN#BTZFuiM&C|6vr9RoQ(3(yENt_}Hm1PGxE3V_b70B#AH5O#2a zVTn5=hv)c{z6o4pvcMgnM-GoX=9h%{-4IbhH} z5_?h5tUlg;qILC}^o$(+n74-o7_A*2|xs2mB1IBco7E?GO*w4*5_ z0pi`$H}mOXTP`|*Cvu;D|F_kFGn4Q8`(pozW^I>Ar&E)pRBfhv=O<>mrvLP$f&kM z%t@?okY*Pk#%&p+$td|tG z91U;Vbi{F*iQH0ZEaPylC2orr!tz$EF0*P9?5fLrfoup)ew-gZ{E+EdSJb{D%tu80^oPI8 zwKJ$?xkqx&d*=t0kmrO>ZMFoEoSzPeIE+)-*|?ZDLNX!;dwF5K_;FGm6BHs+<>?sd zEvQe0{?Nny)8X!2w#(SgHL339(@)kU&q|w(V)eG(R8-fW<2xd!=!OXa^tKz-7x{5k zXhHY&?ffNdmy{w1hjkTBZWsZfI)OPqkRLckjm3CtTPVi*4RhO;*Qhb{h~s?J?OT|2 zaI1}`>rDoBYWiI(sjVl+aJYLK<|DbGZt<5dKSPdF?S_RF@44RTv&tpA5XgM@sDYFf zRt@XIoW*R)>LNFY6dNfOjKK}Syi&AmW2%nx<#h}qT&gRs?P)bG5Kbv|7Hi}OVWnj> z|6#>Bjt}pq!yUO%n@AD4ynF%>4x7!9w^!-fCu53hJ@=IY(%U#(&5@c!zVr+!rWEd; zzMD>uRbLAt9;#pydM9hF3~W;xnbC_F*B{#~6+KHGj&vn400RSSo&y@ot}=v!s&i-7 zOef(SBHRM8Zl*TxZ^E0yFoe!Yt5y_w<8IRUTDnOWsnvQHsf7x3Nz-i%SbGK8=QYB0 z8-clhvH@{#*eJIS2!Ou|++$yW;;x62>w(g*(DiR~%H*ujZF^n*=WVn%f5aRRz7lh;od8Qn9ieUgWEdJoaq+t7?qj(1KfwFT~w_klHK? zbYOz5Ub|;m<~TJm4&_&&hnwJ4VBTkUDb`CNzCpBNoF`H=6xyIb!HOP+@fzx zznc$47HAaNxB$0^8|ifhfH$7>)hT%OKjp1OeCw&@fokWab=$!qAK_Jumus$|5V4V(kemp2~_VV&e3hVv*ABs)8 z0ALL3wp{cf4C73G)c!_IYqUyDVMD~)ERur1g&QFv=jWfow!Hi9cX3-@KmQRCA3prp zY5tmtrG)h?%;zt^z;%pdt!t37dK~}|!dkqb3fn4f7lmI`4{`tD2O_80DAVyCN?>88 zU8(sQKuRH{I1FRe$m{4ehOHrenGI2Au?YaD!6EM4g19+ zD=YzxBFx|Z?mtQ?g!PgUt`uX~H0@oPy67ALa*5h0!4aS-Xl~FHa@E+@K$)c3D3U8* z&5JQE@-1*x!nWk9YMk%ie-D6ReXZ)6+VbjXnViQ$M5>1t*>q_-z3J>FfnPXUT zf6Sax80X_K9hI2iD#TKBKFmdf)%L7xHxZVzfT$69pQop_a_qc6L;&&r-FJSN*5$Qs zPTP9cEBC{s9Aglf4tIdCU0#{_<NY3;S z8Rv$bK+xS!#a95#F@_X3%^57l?f@XZ9p(tY zg8ia53NTR6hMVb^iT(mCf$0nY)EZSOsl-m-ZAF9|q+c2@a^;^RYNTgLuQpLWMJ2wA z|GrVZbrn!12$!adg%d+zE=hL9WKJYkWex#BNeb0G$&wUWWB-~jl(YlUxY-(>vc2NTe!xC8T&_0k@Xf8d&y9AjR{P#d87I&V}`E9u}%l*G*_{jr|8j9xMIR0CMW!Q zU!Z8y-VH8cbh@5dOqbST@(}D4!0SYh?Sz5s-FO= z^`Jwhy@{RWH`cMZzAVh(EYRi4?tplMdD~{vT&S~zd-wX?>07oALS$Waf-IaQCE?79 z1ZMQNyKKWpE%P*LQr-S;W1R-&&CcHc>^V_sI9zY2dAo)DfCxygLUM#8ovS!YXN#Q6 znw@)*2umtfh`lTNt&#s*Z9KjSWQcX_BSe(c5fQH$#8O1KCza}(vzCZRNR>7%7rST&2nB_lfH)7% z4?ZIYLgd5^ntWR%;gv%oQ|`nn;KnDcs__tMRHy!4_)*XAm>H0xp`a{=ETD4NUo(cnt(b_UV-;IP((mC&iw#M>gcqsykb?9 zf7+K{R&v99tT>nR9<$91r?_QKW7q)m7+X`+V+>iqr)GgS2ANzL_E<%SiBk$;IZIME z4|Ky=@04bcv679;8gK^Os(QPv_6GXf;24Q1JnbSp3<8Z4eunSPvG0G)uP zgxI;gSc6>Mh_b#-qd-Lt_wOoro>HjE@+yyO117N{j+wlqWq~0i&ys95o$tI)u z^r(N&CU6ERk981H;)aDBv@T~GNMb#CEE6%mL1p%@Y4YkC(H@Pi-r5_CbBZB`)en;! zMrJ;L`T1~qL?Y%S49<@LGGfm6E-{lz0ZG8klFg2$Kw7q!Ff+s&Q*8KXNd!eg74x8R zpalfWbQDviE-#Mc2aKQ2$VB^bM0fftFCN>frrBm|Z}VFki*HU~?Ij-U&*?+Tzvi z%w9&}q&&G{OmVBi{9qmB%j8vUnfy3WB}}W(UGJu`*r+A;Zljl-uN7pjd^sUmQan9= zlj4@OC}9&5XNr&~C5016VYyV!j^f5KETu#p$ot+#V9!dZ8%?fR5E~4bf{1I*d07qZ zs)!1KQqOsw2u7RLe2!$i2#|@i(X6u#W%Rh zyr4!fmi|x6KCbeE%gZmE(!1|}SC>TlWDzx0N!z;OOI1_OHB3*CBaod7)cbes`GX(<8ZooD-45-IL<>ARM-H4reeDrXA575z6mHW)zej zCjJa=i|fW<2P{LL?ylJ+HignVNM$tb_k*qW&ySX zvQ+=4h=z@1gf`_- zNJxTGEr73u6jmc)=|3t9#kU0?`Niglky=26=(zwl-7)&y40(&dZDR8FVr^+p5N(94 z-q701YI>1X@b=J!K(WKv-K{pC?;$}uEjC0Ac>_Wu>|&N}X4#HEgDs5?#DXdvTdHi( z8X%rc{BHnoVq6)aqipC!b8V@2!F9U;!Zr`ME#BBMA$w9)MrQ43?%1FNG!0aR~m719uS6AOy=Rmye{ zP`}FpaoF6S%`e=MGw`jK&ul?iDCxXpTQbndr!H$%otPSpr7WVx-J`liAQ0|7MzDu- z@r}qDY&! zq{W|bD%A-Z3^@buduxl^nJ5j9Mk}Ovi#t=L__^a$<2?dI{5SvdpXUZ20G-D@4=gj$ zyP>6y{W>Ch9t`;LQ2Gfr^kNCyR#nM67P3lzm20aLS|T@0$NBV_Q)4*h^eGWZNr2xl z9~KbSU~wyK*p_oGwa59OKYl(wOs5CEZ*jYbfFDP7YAji>>G|h>(EFvj0yTcKU#JeS zxyvLXa^wfyio74tIV|;{B2faILf8opN`?lg2Ee%i3C~|XUClzkCL@+{It%lM-~1(~ zm{bFf6vDDy&ev4NjwzRy1zjso8WPUzs)2pR^g;|P5oOcDytCsl9|7>g4}YPEx^TLD z`AK22R7TTC==}(KGdUgZ-U+8p>3@s;l!fHZ>Cu!ss<4LTth@g(9^5dl%NdFQv^qBJ zF}KXi=sL?5$tDuF<@oUa;lmHxdJgM_oL2>r_CT7SR}=WE%fVX{$h2K*b(K<>j`xSV zC!^oOuq}{(Q{T)uFOsBC6?9nV#~Bb)*t(IPNQ^v46T4u z5>Ayf)f#ki01%e5^-WJPNQx4xIyV3SAOJ~3K~y>bc=-4mKOVyJQjOeRKmEZRpW^(8 z`l{F7_aqk5t$0C;@(;JlLZQVOcW8AXzCjG=gXAu54I zsrJsflHXO5P!)7*jqbCAK+Tlav^uvFOfkb-H8u9Mulx$IVGnI^4gT zjt{S&elH@Y$B)jBK8MMVD^>s4;?mt8X>@bkGv>ry=j#Wo}i&7$c z>5d3%Y&zxnP?ZMl-xMQKvpF`sHU|D_e_d($t1O{8AR35ee~31+2%DTvl`1tMlMOU4 z>^w1S|4uN|auk~*fjLy9q_*rt0_Kvi+sY~+x1*m3lxyxDkz6ZKcGyP=AZ)G$S;A4M zWVY=?*z54*EAodv;l2zhgp8!ca+;`PeCF9RA(Y(Nitr-#UyfirDB6l@9XvPr8_0FA zRKIMh6+#9lD~%}Uhy2_B{y(p1jE!Hv79CXwcU3rYiW>jz>QOAL>3v!TUbpVG*2|O@ zW!98&lyK5Y{KIelN|oTkDN|7p&tE>b&#bfMKjAM<(GBD2;iJlToc9|1R((Cx*Zj*b z|7iVND;?2}_oVT99Uz6}6_9Qkica&<4deBLsU=$zr+d{Dr&g8kOoR)yubGb*)i%c< zoKy~fdi+LLRod2VeQnH#6z|{vfJm>;e~jzp$G`lK*UQT<|M2e+@b2CB%#k@_nKPx7 zG^Rt@4cVfsygw?;s5_|$-#>ke&LKGjOkph<$$WYJ3?j@iw;)$Q->wxfo2_E~j#H>6 z056|^B6L*fA!RGcL*Fc=Ky+R`SKB@k!-#y-Hq{qwWpQtdc>SD_ZA5JCmrFBK-OHnv+ z+^naGzQy{hvs$KPC<-S|IT~J4N}Q@gx8eZS0;aYFBJ%Lzhr|7Q9sMe7_0!+|-?j_1 z$1)lH#`WVCPL_abZMsTIRFNVe4&$6M+EH9*jX+xuHb2hyAASUo%kxie7@Z$DrIcbd zh(N^S<45mDDX)a(9j}*{ZOQLT3M(SszyHyXb68)<`C+;Pkg(>Fb}}x{&JVQ+STAP* zQJ+ZXeF|GxFHq*gw4I??P{&|PHcg_#xnnOOq zQ;Nl$ljD{`D7&#rYbGQ&9_}&EYeU#BxiQTQrnO>;R@Fmhew?S~c6UWg+hQsL6lRWL zzI&QakLqovED&A5ug}$NVecEz(pt)2Ia@~ag%DEMqM|7xr>Ae{(__h%P9U(HKa=yr zcmxDVTS_skiytOG3`o9SGjpi!)|!(#&L_k5gJ^nsas+_Bww7-er;^pW8B^XDEOL7U zb7Q0>HxLgI8(}WYf|YQUZN!R3*bb%S)|Bzhk!E>+s0QR=J4dmyZ1D}NIT5+>ucVCA zI(EC5kaxN^o4=Np!alU`&5rvP_}%B173-i}EA2*s&4^m|W6J)4S~9diOAYE0%ZzhE z_WQo6d60h!ARv3$?OWX{82O5sMMyteDH6@{fQ=DzXV9D}MVaGQ-4Bc~w0414m;2R4 z-)rZwy{SF#nflUG=;duR>SopQ}MC^h}iu4+bgms01^Nh zbr}NIp(&btb*y5_-3}u+bx{4nz1k79K2B8Px4=fK89TiSk=lyH#u$lQ6$|Als1aaltx=57+AJLa!n#;|%#ZW^ zyYG;kYOd?=3Ss3C!gdA#=SM_${_@8>-Bme~I=%H6Is*9dKtw4;=ZE?9s4>mC`and0 z7*=h1ifp{&fVI+<9FemL_1z7nqTL1%fE2eBHs!NvhIJ{0sE(;sP}Ny-LS^d_A}z1a z6^W_dMb$RfAZ#McAAbBx=~=j(l8CAiA}6-PMNNC(mWwKmogXv{$&M`{``$H7R0KF~ zY$&GChURp*f9JAcRc<@ZUw+Pdsa!70`dxEu5e zr8ufw)Q=puur04#kXc zIX^G2pLJ}OvZJ2tO0KvqeNK);!p8CydHVLZ)dZDe)U}(!s%B;gurBA?5&B`25_0SO zz$JdJK0%iq)o&azDQ;n1h;pizj+PPeaR1KvA#5wu6oI&=7-|Zh)h`ayAwTi1T<0v8 zLMWE~nWv*V6CFPzk{jk2*07#4y5=1fThLTw){s5qkbKwjW@==9RS5vRJuQtD?|$%B zjDkwn0gN?=9j$3K+(>GXE}Yq<*LRWPs4|qDMIj=_piCl7_95~+SMHl#th5?D4|+^& zM~g_`Gq2ws#US90E?7Iis@<-RS@~qzG3GRL$I#kx+NULcmEzgg z={j#Wczc+3(`<8h))pncxGMvTGE5NowO?}G@H7`dn^9$ED&_NZowEQCy0TtPpJDXg zU5XHZ;Mdzwyq@kiO1_Ao;8pV>Wi+TeP9jHc(7iIFaJKvsY-la=%`@)#)uB9ZmVLGK45H1!hs$%n=$ekC8F%`?^GwqrL5K$F2al4Qo zbTGh4iAEXt*18~Wi-4pU0EuG|a<)u{mI;zsBw7M%lxwAvs8lg*i;0RgHm3+yI^*0R zkUukXOo(Jh)-vff`BIBb9cT)!b1S8=tJ_^41h>Y=v|`1tg10P$7Ky@ww*(hR(QoO!D8bF%!$LQjeCaN!=|=p zMDG6G_ih-o(Ro<0=GqHuGm)}3F=>Q-6-WAE5=}$bYa~ZCchD$U6fLMhqs6|7IVJre z>R+h8o$#OwB&86ym4?y#QR$$=bgU0W2Wc(jwy+h1)lrWUr;@dnWh{ET#`!L7>y~+v zN$<0trYg-A5pr&MeJ+bRY|D$@SvQPC-Xe23_$@^c!F{rX*r7ySmL(f26{M2XSFa@w z%HA_*7-u9*adUncrej!MdA&>r4R9X-(2p~xux?9cEN9~>uAsCUZa~osR-0)zjP~U% z7eG25*6DH?uY&q1IzQ!rb-Ri6U2OS}^@Pi$3PIA%UH|Oz`WaD+e!RSXCi2b?h;BUG zrMRWI=7}6+Oa17E5hU-KdN;JI<`}C#FqBk< z7&mnjQ09DtLyI7|pv;1R!XlW~%NJUmJspscocF`b*-XD=;E1HKF_O}5`|g4iDRgQ< zkPpW;CRbErnD4=l07!0A;0KZ7w(Pl5MEbr+5uFn{DNth7fB6_zBpRp~ZRiO>j7&`i zBoenJ#c;U$&{ZhKgsYPkVpjl5ai6L1N=N)fO?5b4UVc$rOGMIkuD+ltZhAa7Gdj(g z6VBUoJ!rW?RYHD3A`J)}=3}uB1qJuwdPc(|mp)ZF(~A+EpOuZRWaVsP1bo9)2)Z{x zy%ms0k^W$N@1~Zh$*P4BIk{^DrHeXqZp@ z5@Xm#RU(?|p}ba}g*it1(6Jt|BIhr^RKR(hPo)}j1f)K+s?ky%j>+H1jFK`P$TMJW zW~wf3OHGh1u141MLoI}4J%6!z5r{Y)P5^)-#Q^2ezl^kl@m zM8mq~@Fqm(#}s@l-tOCa-W3X3Z)JfBaAWHr@*3-@>8r{74gAW&CMDE3gKtG&47+&c zuQFDen`)liu+DE%3d~$Qgm%UXZ7{o=J~q8XM`XYZ+!t>uVOEBr><0wR%Gt6=8eC8Z z=G`B8)A$@a2+b%Kc4+EX)F<|bmr}aub4fYMh=hVl8es#!%fWI~0x79;m@}g322|T@&@5KC1yqh=M9kRmOQn`&$ScWDTgA-?Ft_c!R)H7O=6-+3&XMJ5-W1b4Hk+t3}H% z%zET&{iuU~r3!cCEYlY&d=9CqI%5Yp|&w?#@iLQ_$u%B-D-yu7mkXFErF zh_uC+K%Ytr#euKzjn(Y4WRMY&YeujgjX-V+PFm&szy7QL0*zykQO9EzOP1P4OA--Q z-_fuw&W|>R>aF8Y^^8ZL9wx~14V_W+%SsTBUR>zIw1js zZLQgUkW--vou3ZJO6V~3ilHK1DpOT3HpPvcfA{@gq`2wCJI2j9@0@>q{@J>N+E=Ea z1g&&vy{}H1O3E4nxM8XlnWf=y@kg~jVZ}r-aSFq9^5difkoojb46)jXKO5_a_6?Vq zP3ZIfrA}rx5;BGjGX~O(3seU^9Uf8&%gZMudiv(K%j@UY=bulHAC3}W#{A{m@@iT%L3GE5Cr&ZNI34cig;)dz&>08~$Q(VJ(hCEm);FFcsh@_Md!3`FX%X^*f z2Ab`sSL+5n2+;n)D zj`x0?oF89){`VbDQ-y6JG6G;@Sow%lSn; zH;O+h`eC%H<+d@3tYsmQ^V8v^KAOxaC$|6|?%s{_DWw1+DJ&wgUS7Ie=Ui=q6|d5R ze;B3$K*^q43i1Y19}xt5w*OZ$sIVhO6j_zzxfEL{awo(5Dz#qT@Iki)E>{jp$Bhtd zF^QF6EjM}am2m%di*m@U2XgjNor+SCLFax zgvJAE%eBt$73@*oZ|z)b?wyoBeuW5-)gxAA)Sk0qF$wb@)V{pn6VldzfN`gj9tWy| z_dI>Rt$gT3&-+Jcte?RVuie~?glP{_izeap`uX=I#9&LsMphsDG@o?Hr0t_BMufGKTN;;RjX$F0Y?J`)0`mA20v_A|CGExncVBkN;1WXpp;m`j#b1 zikwo4VLm+$^UvpX~hT zhKbY0G5T=^!1eMa#qjX{hm>O6F1qo=ZCNj`xlSiSLPe#=!;#3Ruyy{WSHut_sFw!L zBOtlM>GAmZO3Xt5 zZmfwDmzSSKIIOG6uCjn5Zo2A38Rpeejdvy9E=ZyFTi4ab73O|b*zKea(5T6^f|bIH=MQMlmzsKG zbmDcIqWtJ0*4ZmVb?Wfz+7G$u4)s4R5!(|qZ5B#JR@%kmjbZI|Tfg5v-ZnhDS)=dJfg6qvVqG5$ zDukVcb1&$$qo(}|Ea|&gMJ7e&NE+cmM4S^bC9Ma;lv=NP~^o`jQ-e~MajQxXQfhr?i7z|v{~ESZwm;p6NR<66PtyJ1hC%P88|Lnprnp|dAkyjSo3Oktub=0;cZa*DV!hqJ zIGkcwh12r-j3$n&(lSeqXgT~-Y~m*XLPDaP{8BhIAb`&AG(FnRmZCmW!fGbFbAFuf ziWWH4lykK|j$xB>=?%qi)Glkdlb1e}h>jCoP z+qpDh70H>=z1mr)uz~;!J3qQ%)I(lFeDoGvUOrXefjMdqRJh6=LkI!3T*3n&`eADB z{spYNd-|s3A}Jh_RuD-sGRG7`m$8Gl7*YU!7?^X2BO*CJRO2zzC}>9uJF1l48SP7^ z<2}(3x7Si`u?|@+sY^tr!<~`j-gy0O+fQ|EioOkwnMpsCh^3)Vt-fv`u5^W7Eqvvx*lc&X&Z$1e?l5SqZ%c_} z;+AUQPVtdLxRry$*MlP1_aFI_b#f!RCAAMI5DmEj$pI2MSCb^`!z(H%Fg{OjOx}@Sl1fCUEkbYJo=1tp4A_hZ;uXugY3f^KH?x}2XakxV-FYKP!meOV zrhOAL<&k90zngh{rd#jb?UiO#pO=azE4Q%}_eN>1{3(GyfqUN@#1(?H=xHro(!o`Sg@hx4Sl;^M`pJ6Uy3nop1Ui6R13Q97>6>o6V=A#4{;X*}Fn@^=q>F1Uzze*P)NO*pNW z7f#9fL0L-zIip$IptvrXSuU_UgOlkXE8ks8{Y7I#cUoW;a^^fthpPXr zTauF8{5Xlo^72`h*N=+;03ZNKL_t)9QwjxFX1JL$`;XffxrJ%$J&X2{^0xn;ER$l^zpt91ylq{^vxUeC5 zT~}*p%4;RIBSgrLJ5yB~jz{QrKZt7$#GEj*bI({dR&C&vqPZ?FnY2dehEYW|+GPr* zYEz(f4_+1EIgUzRhjDg(^nTJM$IQ+T%qhy69kLv$|G*9Dl!zauq6raZZ|&4e!uD%% zW{~;#$msnzYwywes&f1}BhFEgyZ(#1MN~J5V&kC8PuADZNNzsfA%LnX)wm!pR1tKp z7;a>*K1CG5cGhYhkPy>Ohgw59u*FdngtA%ow0p9gpM{yz28h$)j#6@dlK+(RYv_DES3C}xxWP%;&&>`O52n8-`&5eKEfLamxSLK7%gb}o z?P1(5K^~b<$aG#Kj0HuMPE-slaK4 zf=Y}lt4)FP9@JD)kjQ~Z43}192O3OKg^sq z;RNIy49bln9EvHUHZz%L6xWLz=V6?Y5>b!V#4T@(C}>#a&3ohu6<1VNZ<-$t;#tXh zk(OMou8Rm~rKul)ImJ!INy14|BImJKh=f%{*wN12f^`T|jvKmv`gS-ztmn_d3EhBz zUgsqy&bZA^i$9hCh;yDX6a5ui&sY$mWXA-SGD}v*T`sAVs=!>CnO358o1c42&w%6* zKqx^m(#!UJrDR4#VXO#vl>w+S#wfrt&Z5TL0Kf_1YMX&3S=fP-A_9CB^lGHU1O_$8 zGTutN%I`yyifesr#WRSk>j(?H44IA6norAMvQf^}0$9n@s5Vi}5j!Ix#vwLOTNO~c z0@=7tp-ft1uSG5P8X$mgI5Svt29Yi?(eRb3*+1@#czZYxn6FY>;Ri(jFkSI(mmK3g!%+_(BS-4C}cj7GDqi?Ftt zUk!?q+r)RoUW{C|MzDj3t?>cafQ7yp+SAqQEhj>z8=!qdxzWbK?{&t<{Fs=5&zHs;Op%j+-x|7Y!8dM#O&G$Av0kBIfyYiI7Andfz@ zZ&g=yH`U@L{uKixga8Q%F@zx!LahcQn7|YPDi92M&QD+h-84{Lx9&YBUwf~$BEsFx z7??lIBVz5`r@C`+mFMPu#ES56H~Z{+bo*{N%+uLVmwvbt*EnV#&!3~8Pmez`lTcl* z&!3#@t#e$Q_0g0Ft5SLw{GpV+1*yA#_Y)dBU!EcbYYa(Z8Q`!#&Et7If04)2?GCQn z$zzjFD9n@civZX6-Eaug)z70f4vh)H7o6SogR!>XohnVx*pks@jGf14A`+RfD`r=i zoc$IiHQMSo_i&hi8UO$o4)?pmy(X8Y<_}X#Shn1O?)}4%}fUxh9wc(v_z z#@Nf(KWI|uDo%u5zsv7n+UI1f5Q{m6f}kJ1|KoCzq9c-vmnMOtz-I~SmmU9b|L9!* z`RBiM-EcTP0Q33j7wZPs@BDb4$Fs2((JDCk#_8KugS* zA#03c`0(4m@5js6U;Yvh?;pR9A%x(?P{nmS!6!M(DKAeYVi3Dw7lRLe5|Kl0J)-ol zB5XiJ>AXutD*Mcu-r>4FAEq>q7hMwVPY=WX&QDh+l6O$kdWE33bQ~1AQ?lGsl)w@c zlfrpOERl<9*j4qzk~5aff3i3)G5{G$AFGk(G$LOmCs1^1ox8_*tiUyhE5{A%>~tY~ z=oGr# zZZfaL8CCXLu&gEwyP5@T1f;cbfem}RQOj1TJ7@lS+i)0YcKnU>^F@!cen~fqYyC9y zVl8uFtUQ*DqBqaa7A&<@BnWR)J~%%pmCWA6K=KWl5O48-xFzEoV~kA2u*fSAUzxq6))DjqVVPqz}u=QgqvcFf^kS7nqr*gasG;+uhbyT6W~pq#db%H z+XRi;Oe>AYLdR1ZJJ^n_(e;g16|{7W?b}dR6E~zkWNrGeFzJQ0=2m(`(ywkwN-o}g zn~r8TXj|q0*#RC?Hf3HofAJ6hUFH&ACC3lDVek5#PyjT5FppPeieX}+ zX}qM$PEwh`Fe0mQ#p&UP;HUGKpAqry;d>?_b400AV(@nl-y`CDeU4#1y!jCQB-Y!* z{v_!U6laP)%u@&je6Osz7(zKyC8)YEKBCH+cm1wlQALcborLsE^}FBxOB91rl9st3 zj+ZZfyvU7k{jQw)oWo0t#aj7!$weNLw@@{g&J(7t-*tl!#4-38fYCSvaQ%Tf3W?u! z`!J8w_&n_I`rR=VR*1knp1)=h*0F2R7 z^f6l{O_!%Rn`SP^8yFZ*B=J6^rApzlxv7+lw3J6g?_ z#SmlccYE6n)ViqaeWR}G;Ei(ztt`3Z{hc;+W3aV*)(spWWRD5cWL)JLA#lklF6VhF z8HxjM`i^XJmec1=*4h(;4!hS@I@(%i*$v=odb3e%Z_ZcNdZ|`yR2^pP{7;$E0&i4} zo8@}T%NAY+Hc{!R%dECq+5i{T{a%OMs>-~m^s+46G_FM0aH*TY!J{L zF#xXoyuQ&bs+xSm;Dc3zweTE3iHA%6$Z62UONj5K^hjKW$lYi_vK(R=^_kj4M&+2C zS%?X?F~C%&XkvB+)#;v#5f{`f(~RFY0fbbD)1abonsyU)_@Z)0%PwVrToIb`jH_~H zxx=7pj@oy&ET5&f!6G@JP4Zi;6ScUJWp}Jn3FWs3jR;M1U6W&Ali#lHncCcv*Mz#_ zGGI2^*&-1hGQ@eLA**R|+T7N=<_miTs~uRwL`u_;8eCTE?Gg}; z{5#3Q2f+0^!3?{8=lWgO@2%^MHNY@lo+!q7d_pur;E58hy%1DUgd~9{QH+Z9pX&y3 z`;k!N{qepZj+}T#BN0iRD8-AP&KzS%rnCtqw9Wxwv23nxsugPg4#t`-*bI3kHw=Cjg1Fo|W9c2{! zGsYa>ytm!p#|!5WwOJW5m4MJHl+15H`G1%w7P0M8MVD^-?)XNw06*m^ug;oSGKVEV z!X-EA;Kg89uzo;X94+!SvJrH{z8m(|^~QCHLPdVly-$-Km0E@Yz)vF@6y}l4rvV^_ zNlc`O;=7;zPU&6d@wphqNOztb^<39=gRvb&Uw}|?Ge}_?$xJwIot7%8Bh6WxR6+n~ zQAgMx@433e#73=bY;jbN(Tje$ZaUckPA=X$XN(JB22R>@HS-1l9uB9&-GcxIUB9zk zKVQ$xEFGtC*<@%`Hn#Edbv%DPzInI5d;96H{~x9}9PW*AIc4*Ti2eQ~+kOmQ#@GN5 z!lYk3V_Y{JnCbHLvFmnj*!$_?$II^SO+OqdyCp1K469w#4v zW|RFg^~^gtb#zTa!{Tg8kR+2a)<}q3wz#7hQiv;)b-n9`ySE!mFJ_R7)0iIc=xL-k^$!$flzu&Yi#jfQ6USmooFGoi@g#UrW}WHfC>l zo!tdMc{UmOmiPBJdyhsV+~}Iu1qo*Iy0OVTv-ZR(<8Y-J$D8Aot;d`>v<07bo$=13 zds{sx%Mib@rEas8u}v<#@hb`0EM`76Hf#N`k~_Atvo+RQHxXqwZf+*XTiKKAsm04o zbSU=0C?sCWkQd@IFQ#P(Dyamh83iZ~epXCU_Pr6o`z_uY-YOm2M^3=D)v5~(h*k>| z6_t{!1K-Ag3UATMU+lJ5H@N~Wiy5`fYEK1z3whwyTeYN<6z_1cEn0T0GR`punGq;+ z+^`1xpoA|v{d-fgSYkEjD>MedNGuTm+I%>%A;JimLdPxj#yZEuLT$6w1;Is(G1iig zoA+?pz@?j`{#9l%LV91#P`EXnS$3a_k-A{H!eac}4!kiXC`C|aVj( zOQL8LULL2sbYm?iXaUz4*XGAwyxmUBA3E0=V~=k?$V@^Ok)N+LKD(~RJev{oUwIP7 z8b&Ips1$=r>Yz1eTuwFD4PC#twiAtdf`E+?K$&tdn=t^ne4r2{4JtV{X;aWAE>RLMR=6GMM@qW7TsvFb7iLJi$N3vi{>3b8N)+T<1N&hTxsjL&S*8plGq3u z*X@qR+O+W*D+5<)xze=5&ou%m3($mDg4P2#pivY_^$3RSSj{K@oHYn*l__vMlS}&I^esR@1nu zls5(7MdLE`#1w-y7V`iprZzXd4u}SgYj!2$j3J4+N#TEr{w^p9seLe?XELog6np{&zGl<^0D(9mt5-*gnCM1%*CAfeiW;Z2s0B+{491KVZIUtYu(}W z==vQR+wYDAJMq)CoG(cLmK8O|SVSxPkEr;G2!fx+=cEU#>6>Xcph%ePE0Lmy;u4Sz z9GanE^$^bRCBlM!jDTpJ!2~Invo;1lU7p0lgqcinYeN7)Kc1CU2yYXoa>c_;s7l9@ zf267V$u1*zM#gq%Oz=~d#YDL$66luOM|Ry%+E6hQkXO^vAcIxWoal;K9MobAm@A%0 zDa?SCL`rlf#&y7n*>HXSjK=iC5zv*8NHm72vt0+w;$DKp1;5Oq7caNH8hGV*(8+j1 za@y`6e+Yi^^CW`haDAS}r+%l>v0dL*$kAj`nwARWAgi^y7F;(Bhx-)MO;i#f<9KF4 zoDf~NGu9Mpvga#^BXim zCR-J+Cva2^T60yNK5z47YAy>Bo~I`nt{Wmuk^z|uL5r%W57V{vodS+@qls6BbIilx zL_}ep5ZD;&T*t$nVyuD(YuB~E?uR6SFX?S06(N?C@N_)%`@4R3INZNW;v~sW5G`UB zfk-*29IMmKL~F&ap$v`6f=Nb2Ma3*|6JQEHMI+jf9FRiHS8JU$Mm}Hy8?8fQjO~rJ zwi~qA1M1?pJe3bLaSnF_?S$QF;7fO{TL#7SUOZq`lYiB8f)#V*9 z$28u<7-qTzb9(Ih-8^06Jjt_;dGBM2^LPe?uHRGi(a*Nuxo#i*+$V}{rw|kvxsUimQ@glXtR~EPWb>L0OBNUkCAJ9 zM-wV8ez}=Hm28R7LVA6SvDR3p*K@gtn=nKzztDoo1E$OnjO?fDS7W>5+Yd>hVQfqi za^vR_ZUh8vFoVUZUuAJrI}t>;d5+3!J6)yVk^z%JgVvVu0W%*?ZHr`uhCYSi3vCF{WmT)N+*<4U2~6l5C|3oY$R z^P4V2S%mTpb_VOhzYyN)O66~|KUT`470W~gNi>6Md4H$fX4p!*2P2g_prOuVAH~-T*W+Jqjg$D3coM0C54) zwED0`8v7!Q8`L3IdU3gFynw4zIzdt;OVd+f`Gr?ulO(W+QC#2uWTI<|lWG0-%v@i4 zwG%UzK@nsbbpZo%#Nds$Y_Zib-_lYjGKJAi^vwX1*FoIM@mvMAgQn3dCR(n{m2yB& zajKig0^l--%qpu=_D6T@8J)w2bg~)EZ{)fN)uL!_3U!UjkS*|8V zFB(iPaEn#GM|H%wLA5|Mw(B9QU-ee9ATk9%E6NB6UFC3k+~2>8VWtrLbRnYg{5k7h zwhJ>!kiB5Y!{IGaVDg&oJ3fCY-|MF<-X2pk^X~4AF?JB^ ziEf}6=JA=C{XAJ~(O79dr0BG@G{ouhoTp#*^zKIrKFpKtdh2?@aIVjvm}66eVs$Pp zxz-fsxVk6S^@r0VU;+ja(N9;OZ2>l_OGy?~x~U|Q1PJrEE;K7Qoq2cnc7OL4lG)X@ zEY9oGFNLF+@U$4kqgWFw{WLO1A~x3cxs#K`N7?JUt~b`r<5|4mWet~=8N4roE@C>I z9{Sy#Y|zoqQl>Bylb6cSxt$yK>j!yx{zzdKa;q^0Uaa#l!=c*4w(MXO!?3^WcKhp7 zH385wg4T`N=vtwW%Ce0M`{@G2G5X`%?~ZRia14b@;ipTUE2aAx{VZk+M3G|(qn1@i zs=PDRj&a+`Js$y>DI*e#NJPw3DJ^PbgTYTaCaK>Y#SRmVjbWnb<#ze$8e`laPZXob zNVFuTvep$2!3_|SfU$0O?1n=(>|MY6^t*q|MECE1(+!8OKmWh38}_HiBq2>1I1Gr_ z=g-sS>2P{Lw9+j&MYe6+4s+p2Ix7!rwO+>i*lAy&qgLVyGazoW$+2Sc)m11@*R>|oG@8@uL$BaO)@AaG z;n7=62i_RnGp@~}imh`S;DA`X-(q_^v5Hx%*p_cgzY!WSEH(P^tTk?(Ao9PGAUW0K zNjC)QTdGEeC}MVGYOVSc5usjj9q(s{?l$WKo9KDec3!-SS?7i>WO$2^v;rGyf}jfZ z#C*<`kET@BOI?OGU~BZx3ynn)s}vsgW_nH;p|`Gh%f`J`{nyvChS&2JGi9+w6k$+# zMYAWN4yCIxoTdBJt&A28==qbxkQqyvX@X4zAmoTBqYBEJSq==p?$4SjvlhC%Rxty& zx_^U)4I^7jVF1dg1bE9aCygE%^;*JBYTLK|hzpZ=`SMl>#&Qo-s++~C$Eu`Y6=EYY zyv0GtO#q8#x@!NHY*?L)K~P2BCxrusom`gX?+;A2%*pugZY2 zAMT8G*XLgfXUWe~iH0vLJNU6EBHw)YZ9Ub|1V7E=Gb*I38+HI7d~WOd)*Np6BF*C^ zIY%2Kx4(Pv z(*+n@*P}7>ct(@7+kU)A_p|wGp)o)IfB$DU>`#wBFvX95^-tuv4~P3SY!*wWRt_gi z&`;Owz2IZ;Qk!4Cd}JmW49mbj_zBVM?;qBXV^LUxHabTv;aL=XK@KEOz|R+oQP@CI zS(agW@Yk9zUk!b*43=cvrNTzI8^qLN;T1`l#e+m4%#(GUXqLt9ppg~zyVK*3f@S&n zI$xi2Uw8@1cS3D1YwVGwrxzuUwGIvXlFrz?Zp_5h87nX8r%%5VAYsvhtn_&Z!2RyU zb)|Oz03ZNKL_t)jmp8>2!(@yz30^a`L}9kp62*BOn=G>&^4u7qA!c+0nd9Z_&qePK z42L)Gve_Zb*Jq0H{PpM6rNS-F_TrwaT&lM6T&1dM0gQ4FUiLtRI>+KZ$V^OkZ@=3e z-(*|-D8~rJFkZd@Ge~ra+JTpY9sQHV>&_HFPEup*W%R?YkU!^XT5r@{Ka`QpbUnA) z2+BZ(lC2tZ|M-LJ20_9$OEfxWw$muDs1jZy@~?l?Bb{ zv4uuo$mQBR!rSz4reY%i#gtBKV0n{*T*L>4d3O>isiqA$yPs>xb%>#v6U zF_yW0`3U%$r`6nWthiL0-mTt`4V@3Owt~aVIBg&qY`5!#e1KLKHDPnLHmaB_uR8&q zS%$_SMY%nIfEX(?AQe4DqEiI_`Fj4h|K>kZQXbAE`^ZFMaVtDsSx;Yn{>$}Uh{02s z<>HQSze__=fNt1PjA6dy`CW`*MpMXs!dp$d?L0o0h3UF(a|Q#z!OtR=eE9*#;L8n@ zY1!faF*RYq2Y<~(c26M%DpA!Vub#AmbH$xVzQFan5)BWnsChWv_rn2=6GeY=3^K;L zJ|{j%=7Z0%i)>8S8nkL)I8y5#kalnhSrq%F7!a_G0F`_mB#cc~VltmYG{)Y)|BW%u zcD+zcWu7OcbQw8lc5G^|yFofR1Poy+|NQQ!Kl9_|%g_G|5%1sq6r+#9M?b|diOeH} zIT`#j_q#hm)P;m5+o#EE1BEVFo~EBFh#P}O;iRxFowv-H@=Hk5^$D|Lfnsp3H_px1 zGXq=K3mvoYnhY9kRk9x8T%JCazKkeBq7+K@Vpj(5hxVqU#5_{nPb%x<1`t zpx|a{}c!y!~MGjl?)N5^OsUzOYkJ5Jc*c%&`8A@Rtgve zUuYnk^`bxpr+2?G#)>d^x}J-MYSBt=ao|u_TM`_qa0n-fU~<8(+ld)r7G)P%XL7(7 zj()#CB`XGsGGY{7Xz*e)o!asHcfUbnr^}OsYZ8T7U^ER1YdYjdK z%$|HiD0!fXk8Tht&lhMxSU_ZLvRnp`h_GpewH2xH;*@NKRkrEgX`r;+I1pd+vm46T z=4{g#v@RFIHOMfV%^@HyvYRvJvqei=nJ;JJ3N&5;xZF>1Q~6%R!p0R}=2Cxs)2T>x z_G*&EU~Gq??L#36O9;57OkNOU&pPrfB5f7r!@2WXFAb4s*@Ql!M6TYM$h zr0pX%4r*l%$9mb}rVPD|qqZ#HDo3hQASUX8ksN!v&Z zJR}uoZmHAKqk>xqZIw-);*)w&7>&`c6pMJ_#WbSD6}CRn%Bg>i+!R{MH?}xb)fh!_ zy5TY^IRwSqoj$5%FndVLUi!u8~H6F!jLq*WxQ@Sv1Q8%ns zI?Hsfjgc)kr`6(yI8(wh7Ja%H{xX;B3|$jJ)+EYfkS@Vk=ei*yFBJS$+)NZqDpkMB zSDs&8f?rTWx9PSZQ1{fBvCeals5@rzyE7Ec@ zl`v=$`AYq(2=J5qlZ)bj`r*(G2iNZk^Qg=8_af$_7_94@-G%AuiEP(d+l|*}VA$Wi zv93FR{iT?}ce|s=7&O^i<^;w#1~$epkx*E>VK3p%)^^6a;AaZ+u)ixn6Ak;q(I5&y z$ixz_D32p0(QtzG%j`-lyz_)Owr~faG0&g=nt}%+M!r6Mglw}=$vD-v5ejQjBSmsl zWv2TI?>iB4qIs$~-V-k}Hgzk6Ux*_=RRoD;D*WUD+eb5D<3x+|_4%HmTY4jB4f5JI@vSBgxnJRpfgkD-(Q zU}i)YqYv}=QurS(C!$%)OH3j0_|pbm6vJq(Ww1b8%stAF3Vy_3T)zWg=XwAzwxck6 zL>Xa;Rl<1wg2q_eOX9r6uHW4;lU!|q*FuCmsF75Ou{6I5b5=QW;b<>IN$L7NXbpPEC)6931Dd+a2Ao8xE&_I4FH9 zML$-bA9*nl(O6?#{Z#o)+uc17ktD87*C(*fnoYrwK_p%F00BY%zLh+x7(CR2ux^^- z6JMaJ7<~+L8{(llDdffen{KNy5~Z!{BdKUw%Tsp!u84W_ujm%4?YvKN42OIQ@CF?a#JqaVwwuI{0E{`A*{N_u_zB()L6q;g+)(kjk~<_jd9 zIJc#%yo3g9J}RnBv(#p{3S6;mV>OXt77k&8xOJyw(NGlc35A5W2cbG*834%m0@QGf zqD`DGPmKuAn0|LCq0s4vB*D{q_h(572V`T4)ODLfgo0hJ{yD=lk(r~Pk`=A%?jF96 zVFu}miHz-PI!d}Ec`s~6`6`J+`&0jf(otSroqfrFpQD|~(aY>YiU{$TrE zn63cOTPHxY_HWXrmD%vq0kSn9_k8WhNL!lsZl1*++h&GjCXpFOqZ!BA!tkrou zGtuGnPFxt%&R}}$dLdFx*K?Rh?Wm&QBL({rNR~YS2&GPcfrwSCb1_CBVxsJ*z)m@h zU}f1l>~PLf$q;q!c5+5L*|*TJ=w0 zHtHmF3rr(jXo-etm`+&378t}Mm|btIt%!+q_nFPx)_Xb(E7dqnU6qF%n>GFmzNWm2 zfJkxn!oL@DfTmK$EucdYF-otKLA-5S)umk9B-aUsCZ?PhVg&{!rjX^avXdl0oMTYq zKvd9Q*(q5fH!J-ohVq|8Vu_&KwW}u_s@NG?rgZDP!v-x$-MqXT2AH-yU>A(vJh`N- zO~%$A^w*NpZ~iel`YJifqw+0+6}M%@;jia8WwQ4M37MCmyD~t>!Yxzne2deKDTUM1$q0c@4)ur`1D&(leI3c;#h%C2*dx$W&A)15+}6NU&;z#pk_= z659xv%BD4zZpSYnpZ%62c)U$Ng?6tc+Hl<@jY_F-dWbiG{kWDL6^GiW(9 zi-~3nsPa~{OWCV6>!$^?^`ct9zh(8K(m>-nB$-I?wsaPhj~^9PkYUNlYjNEsnsl*F z%6FAT`H%kF|G3~w{EBJ1e90@@VKT%M_^Z|D z<{21M5OHWZ9QE5+(%K-$l;6MqO=1Mh*D%kRt7EP%Q_l#{?G6;Y_fyyJUB8cUrVujL zk?XJQG9|vJMI{paM8QiQmd>3i*dh=|iu=2_`@6T+^(OfdgX;!N)^}mLJQdKNVvyjD zsr)K#n-9MY)Ai}&KSMMRKmKV9 zv*>DKm}O>^jU!?q)hEYP=C0p$`{ViZAD%z`{>}T}93MXX{-6FI6ywA9e=I-|ZcYsm z{dnR%g)SM+n$?$(if!@teQ@! zZn$DGs9w_7s6TL#FSFDgFA%1DrMReDv|WIFfs&-lpbnQyk>ML2cf|w|UzJC*4G34a z1I~^fh48fwV{ef#X6fnIq(YhOw3>S;F%j8AUo9=J=*p`$N;&zAdhb>9uZ@TSH7D2 zre@R(_3{z+cMtvkZW_;}r#yfCxxy0-=-SwnSl1Vj$E1Rhh(x!rT(l)8&-KIU;RmUP zDEQL0O4~V}KTFOspqS64)3M*55Gyzq{7gyjk#79%cq)rsBGD6NH+Q!>S4`H2RM2JO zI~-2K{*)C3*9!ZDN!BVePvd#mpZ0fe)kwxXfBIdu5#Mqr*qT>a)ndgpaz!yvn1#eY zUC*hzZRQ-si=FySqo_^PW0jiZS?E&5_WL7XTQJ_ttgi&p%t&4afV9@&(JYdubPyOuHzK1PH)9 zU7x6R9^YIWcY*&P8o?dH!Nd5}`>7rUYmhL|(X;F(2N%FPj_18I-#fMIj6?3G$TU z;Q*L83WU=Qe!j$PW|jpl2C+9VcuOvdf3>x}89Yh^8D^*ta0+Frs|v!_2dWJW+eJ#G0GC^X~Z(Lo%4`m=vs z))f(r&!1&+___L2BoDb5n921A<|yxbd1^)7Cy&0$U^EU>2Af*gU#)Ix*(4&0YObc5 zCe1)u&00!I{i4Hb1iQR)r-db~UjKFBdd*74Tdv_&e}J!UJ8pq>LRL`JQ^b~4jg3=O zE5^qSrEtDKmAKemDmK+=R#s>wxD2dx3SFf*BLW-Kh}_%kh~iEJ|3d#1%}7?nG)xt_uwt1BxrY2a;{HUxn6+d_5xioU1Wlmy|u5%HV@hcYv-hMYX)dDN6 zeeMcV-zz8|mf5+FVnys{WH(Fjx+eFb%joLPR|COo#v z0mil$Tv!ibe_*EJ@W#6S{Q0kqb*|sbhEC#Bfd&yNdZJ*AWq>e^ zM4=mwobuVz^d*EO#MTv3H|+BBRmleHbEYIG3j?TCsw|qh7`7DF%puJC3 zW)9QUxXxy)Ha}j2pXTY@CX?XHWI9N$9o+BkO14)FvjRP_9zA(5IP6Yp`~)$C;KwWh zirUCqWbY+eNwx(d+VaOuKiziXG-6yo$eZG)%RHVb_?W|i(b$53RyRRKHk4z^_5DJ6 zm~cBkDPz3c_)^U@j`O%FtX$0>NY-Xrveup+zE|;Tve+>AD)PW_76s$3}uE9!` zNQo>uo(A;5Rf+aZ`SY*5t(9Z?Yrl0xRFP_M*>P>XPW;-z(?9oTOY!X*V!g@zA$@&D z%qY+p;}9#OQV5nsNtrU11y!#2imClX7OkrMt;B06S;Qj5R+%cz#n5d?GvjG$(Nhh0 zTONceg_TUje1wytwb;tp{?!j7XQk`4v8f+VXXNUi62sG2+17{%O{P*C9aoDfYZ41T z8C47czXUJc06rR0rDg{6YARW>+*(R`GyAh_Y5O$0~GV8mzD2&$J)Y{ZDyXpF*0z?cN zQ*@49KUmkP+=ld96BHh2q8Nkc)$yAM)@>MiCgd12mYFRgQNWZF0D0;|;{Ba)+N!%p z8LliJKbn4jlqw1b2 zk}=X8a>jZguNvou{e3YIh|v>8G)8i3vk_m~9du?}@g$Rfx>;l(TI({DmkM_4Tr=TU zd9ZVo=)323FexWq8%}m-dk&&RNr%%6g z{l4pWqS_Lkp~M-M7dF{tRL+I?@fqPHCj=1ti)`kmyW0~$($TObNdv05cml2N)J z5;2_=NEC~&LIFuB5^~s>_$t2$b^7vhkfhEO@%xm!cK-Yav1hSepUBvVnYLDqmRN~g z*9sg?5!2wN%M%kNY?IjteO54{H}AWwk!L2x^g4;NK$y=IMX0`>mK()pYPTnYIUw6I z1%@;e)=J43ruENUPtoO*4EuZadLU7VN+Da8gdmXXr0+^(;J^&okb*#ktyj1b#ZS`g z4kz2~p`M57TvVVj1Ih$NQ|EiZSU!EYa1^*Jgu*)uXdjv={m2497Uv#K%|* zh+&?Xr7)_!X%-HPj}N7@kn^_SlG#5|jM>9INn#XbR31SIn&0eWpjdzDb8*qB0=E7V zX%}0tA`!9c_sKf~#8!7`%0TODm%o1Lyfg zn6I!R&1Z=IS|-xY><}SGq#EtSlD8m?Cn;qq=fCC6j7XDNVCx{PMtKWZRvF_fq#!d`ii`|bN z+z4Ut#vfC3;Rwo-H$5HzfVgZH=kYnwj&?^h4$;_dKs3>$yoh=9tdwx-EUa&Ld21+A zF$BoDxWF8tO}a=Q5PLbg*0W^Z>fX{$lHcX?mp`~}aQ$v?AG+Zn-M@H8Coo)ocOBns zcnC{7Yyce8kvA`rte9eqVLeN0?I`gjX6+WUc?&2o?c@))A+_emV$NS(+utQ~9c^Tts{&$5_rEESXqoz%cg_vXi8t6xilfZxa$zgR0&kMDfr-J;q7~37 zhH9+HRZ`uMKKM4@6>m@P(|o>|LM+|*lU*FPuvK+rX8wlYBqwKV1)Jnz8llY&vaXjnKq+)*ZgCc|>jujm!NpV&=CouutOs#24H; z=DE!vT<;aD1+2ses|CKucwm{)YRl6mcF`Daj>hUK(Kxua6oK?inVM-!vj=QW4G>EjcAh{J;Npl)HpwsWDnR#LtQO0M!1csev30Dv-#|C zmelt|fhBq{&DX??5OSNy%Nr{FD(%MP%?IBh6oEwe_b+laU;`VEzW8$|1>%sik5fCO>xW9Iw!Kke@xyI}{2ah`}0 z(Oha+Oj3mF60k~n3oYZL!c(?vb1H0-8$+_Pwr#NtWY_HgKr{f-q4vX0-zbVPs;m-0 zJIj%o8b{`ScQ+jGWk(gEcQ@=2z)xqQm>eDe7&v2n%`v>n)>)Rr6hjQ&Za(YH001BW zNklzs8x=Smh4L-4@WC+ybg zr#Hq8-d~nCtWB8p+Sa`d1MgDIr>ZRSNF~NF7WMt=k_7!~ED`(+uko7S&Wx+PxkfM4 z&~Rp5*lF_G{ktE<7_xl9booLt%+r{iYN|d&GAP^&6-L&5<3brx!=hiyCx2NB4@yq} zu#~Th(Kc4(ml2w_WF7sTY|OwI-m(IzIath#+4Ai@oi)6+*kX!|WJ~gazh)(D62q}+ zw%SvWS*40JKQk+i5f^0Lbp5y_t+1}6H&WABEjZll`}yThyLF#I2VX#jE)6nAUeJX= zD7aP()GAw{>V1mFfSG@-_<QB~_Layy#K51$%vZP9Koh5zqQ+#t*S^6Em!q~95XEYB2YsL#v z0|vEg3AI1N7PasdOKW?Xev?3lh&n^Kh=Pg$BbELO*h0VT2>3tzXaANSc`u#;Gav5W zl(3$xgHDDwah~SsIU#E?3g<$~WCRdz`^|SXhOkJMSAh~@W}mFYnTTTuVSfKdf6uzk zbpsmf$8)J`{B+G`IDsj-;O`D^0rC3uDaN@tcCKFu<2vIym4KW}pj>MhYmM#oDR}qx zhtkz`!=8wupP1?T{27$|V~qyr=A#)^GTZFfBxc7%)DOFIpDE6{(Wyjexv_VTKe~R9 zif=kU0YX3Q<#@V0eZD?_!kjjjE{6H^{x?OcUk6BA4a9oob^Wf}9k0)y#^=x7aImfy z6>SkYH2LN$%5Lo*inJNgpgG*XAFof>r;o?`_s2KyFHgT*pFaKgr~j%9Yyk1;I{CjL~b#*GY4iJs)$|$>t9NPHF0Eqpt zGsaGrXUNQvilDg8x<2?RhIw~@-hMZaXFp!D z?qV+C$&Z^W7Z7- zx~|97j?YBW^hi%uJoBvU01W`!ZVtuSxMwa<2FdNsou1Axi=Miu`f8N}k7PnMf^6L^M`swff8x%qa zvs}4uKBnuF&%u@%@;8V^ve<+~^1>t2o1p?NYJP|-vMYe#XJbrpTq8gG>5A4F>o|tw z(+1G*4l*@!{qFwVZzRUpU(eU`=j^#3GQlO)AFfgUzBEnQtTnkE+iiX|*KSXhvM<#F z8!vDaiUczOAraNsuq{NoQs2@nscJNEISaZ`xQK5jBATcwe%j2!Ziu*l14n7x=riyY zk3f;rs@rTC$6!G`a_O`l$S5IZky3+(Js7_1UnPyS!W^*8cY*%NrW_@ z2xiJ0uSrZ-UhjG8$-qsE-*RBGCm6%_R5;J~@Lzxdcq_DNy{DO9F5s6NL@j~W^fvrf ziJUs(l=k^5Ey64Oz*ez@xVW8sD`N0Q7#_A{C84ySK9AKM&DN)RIn(QW8E>^b$ckE1 zBVy2^vBp?t>4;3CZZ%t7+r8yeU+m&mGtSZh^CtPAnXr~EQSD_f2R6Q{FRba__=;uD zEf$7(?hXmA&B5-VUbZ}JCOspB+av#%)M6bOK=h=3O>cKQ0-_}p#tAGgedufe6ZB~Ghm9Lv{NY=E(SzA zJ^mnbsTk(V)5qj!OeE5BCK~pqZg;qR{kgH1yK7$_DAef{OH{CN59kN>L~L$%2!Ng6{7g3O}>BoJ%tugV$Xb065p7F*Pe(j~O(&rPyvI z&!g=xtE*Bs?6PH)*wGuC$BH?{w?1+`nQlYdd4GC5J$#>RpktsI=j+#%%@u48aSMHn zBQfY1=aLOXF>nmFA8^A}veJW%wbt0EtpKp%PBQ8e-D>i_XqWxEF^w@SyjUTt`pQ>Y z*NY)v#R{`E1OQIw&t)jSE-cC%9SxQ&h?<9LO*ia;A*3;LGKWe}(K^iY(bKyhb9slh z>xm*O(rHCkjYVUwPoDrFMh`7>L=68*7@-`G{r*1xm4Y8pot)y@As*}f?#`@6_0=GT zAx2;NLQVCFF>vl#g&tfUO37D3K(v-KmAAZNv7{8`MzQMiM`PT>4}UUWpQp>$ZhzMg$J9*syHY3p@>l;? zH|+1;ewWDPF%%Ajb)77JWadq*qWI$UKULX$qp~iu5L}czkhh#WHQOz z^ajZ^8C!nJ20e0Nu`MwGNhz$70_JMfWq8<^`C(Qu~>+!R`_1iaJ1=2-7 z!zz0sl&FoDq$6+0LnguGV!DD3rgjka)P5J^hL}Z$s!Bu?*r@DzW(2wBf3DI=JA)lyR6vS!!lj5<-e;_?5mNjKv z@4B6o=dK^D>!<58Fn7aV;#|Sl0zV1rZ-H zb^X4??HcQhacFx_&Rs z2N9w2sVaN4j{hZ!W|c8k6xL$fR>@KGm_oFTN!xu4yW^XZsU+Xi@9&s+9-mz|;INlh zPaNa=-GPZ?oSEWud4fb+S41LNiD4GDTZ*Q`q6bYrxfK0$ePUh`(5>xcry$_@`YdiH z(NB;hgF+b>7d^0DKj3M;d@Xbcsm&7sil}@{$QVc}dvjGN`qw%_rg*r2XRIwWNG7WO zUMegmZT*7qq+s#9?Av*pEJ)#1LkV#AGa{l*yPg(M7k_|8sDv_9(<5-%1Ss8nehHqG zEJ>mWG1zWM?;SGJs9U9mIF&Lxm-|%F4QD4d35Yh>T2ExZF<}i@ zIR_Atu!yfM-oWI_YlVms9As<8wanBq)Q#i4f7u*JnspZ83T;>n+AvwuZFl7<>8pi;(jxmWIZ5 zy%0(f!SzF;aRH}x!K4!|*3nL024S914yW|UX+bd8Khr?+e&oPE> z*!R0TKV1cI%jS4qsNprydmcSem`6WdyME9z0P6!+d>SbtgFN@6rhrxwy{8Fr_p*7OxKKh6AE; z-Qc?2bp4uXbSmGx5tvu$NDRJ2RYbMKsg^O#Nj# zwXAiVFQEK(sZlbU%m^CW<*~TM1lFPw|D55RE~w7-ot8 z27us4rYP7=6{;)1T*?A1_%muDEnZtR$qs~>HwX*N^p1&|NN!mN};m!Mgm*Nt4yL$liy4#xsJBUmN; zs0nk%X(os+|Ipg|5KN2tz~1@@Nwl6!A-Y%u^JG-kSHQ^40B!2`92^s011X6 zWm7Q=Ee|FH-w$lvKr!U~oef$*e*gFbr71}~fB9%!H@JQt zpQr0{KkSX|#E@31K!FA&7}6M1<6Hn@uw_;vE+v<*zbx%fnTO-Oyu#^F%W#WZOxj-r zT~fuBB#JVM+xGV};?T{&$)bv>XdY4`8pT{hmwBWDva{86MRT%YS7mRAz(vdyleso3 z_FBQD#6TsKMNkG3l&lv6vXPQ12H%*ENP{9RLdj*;3WZcfmaJ;r!oIe!U);)mUQR%n zvxog+!_4z+BlQmg%E@P}Gt%*-N~*LeVzFVxie)Lj1f2=@ZF%cTsaA4JXazR%7AVcD z&;W)uZ*1ct>b$)w)**-2AOvHqoMLs3g($e~>gTLd;FtPWUc$~P(pD#;QL$WkIZhp0 zym9L#TjGnE)H=nV;2KcVBoAQSOw=o* zRZ(l|1TN!b5Dfqob`UdD^x3MZOlwd!YYUhMqVmv{&9CUwG+1waR#^s8y z8WVw8@VCl|n%dzUG?5MYZu=XfV)xzp_xcx=@LKE&g^<=*VkK*MF4ek@m`z*f)&njS z2ieoBoTlCA%38=*QisG0OQ2gQBgr|-I%G_KPnmEdtk-N$Z_v0j1QA(h-9igfuZnJ3 z|72`QL%e)(GU~9%U=))|`43}Ed86@v`LF(i@*{k1KGrDB>G6BPXN<9~ABgDk^e=#aWv& z>XkP7W#&o~gtzrx{h@I3N(k=)>K^hr74m2|ZVt4KbjhFkhZNDclJw znv^V^nuy&Z^ZaJo5fjbR6<}j7LKJ`alYiNEy&R9@<%x;r@r=ft9)CzyoG9Yq$V`5^ zGCZ5Rn-dcNt*N3g6H#svwx_&kjCIAI9;fTq8hz0B6k`Zp zyBvsY8FFkGEK>bK&lqMt`y)V=6NuI4H)|bZtg%)uLvR8?qz|XZ^1jdG6E?}KOI~(?ZKSQy zKY78UQ5TN@G>_Lx)*^cN{Q11SbS#n5UkqybKc2W40rQ>80HW=>9c~i7hTcLpfHIhumPat^(Lr=0(t(0@%fw;hX$&TqZD;x#=K!m0pX@G*ak^IHCz0xi_c>E zBJRw2id=vPiRH;~PGOp)?HEf)J=~-M<=16>l@d6SerbY*jHbIQM{88=@;|2>hoRX? z>T3)tf~x%xnh9tCjW&G*Mpz;o+-A$?8Fp)E@Zw&P-7AvWp)Pl_rC+*lSYixV5n}*c z;(h~_+ncBfnRRjdeZPI*aN*j)3tc}0m`Y(IeJvxIj3IGzE7GsW)VFpO{;kW;!DU>XTG!np^1E4-? zMbFW=UKO^@OhqcM99&*(hhRanSF?n8|Nb|J)1%-XCAFC;`stk8Q_O>C64rZ)yf793 zbi~!VJY?q8Uy`n0qynW=Io!YB9mHpRxl;hMpDuD4*13fx*!B6N1lN^cG>;bvz9^NK zglkI^v*@Y^N%_cH)R)?bOt>YX!vd8-TVrh&Ey>J1Drt8^SYiyVM$(nPvyL)4c zKwc1z@hVkk47GIKQWU5USkwjNDMp3Lm;4aaB$TS+0PxcYz>8b=GS*CLFubU&yWyBE zDX_*X%Dc?M24bNF7s-VFMT=m+G;9W7fUe&qLxbw0O^__7({G9MB;aGZ#yN+7`wjW(#tklT9Eq z8q*){gCG5Ph1}efCOgbmN>*V^F(QC<9p@Xh^yp7VNGx4Tw>tjhm&z#iJpjl z61|o*A2~DN#wM2HBdUn2ya;7%r1NSP(Tu{1Y#Yb)-(k8+J6Mb@cE?j1BAU+Fj%Y5g zt#yTO!P5U3*JrkQIpPz2FZhWo)GTZ>qZfZv8$uDGiN%_6?z`XqdGtO;kC{q>i1Tz! z3=G6-+etKDz6jydcD;3-7NKb)1t~sUzgxdMDP3#jzn_jRM7@2L^}tN-MaYKO+$8TR zgwJ46Tvi#TOt45#l5r^*M_ow2;><@CJzvX(r3=!APuq3@(Sj2E`mq=^^B9DsFEef^ zpI1rKw|URJa8na2?E-b>seoy2oCMz1X%niEtpyaj2Mde3l^M2&mD{#&FB>P70dN5f zma1QT-4OCc&oI`ag*pU9;Efgy5I23dZ`r*ypH!{#nuxjaCRCcphBMu-0s!*oOVvYi zYQ{QTf5|BPRW~$omzBmyr5`LjsJLj`Q3ceOrnhComp&2moQD5~Pq=;7xBzm{7F`-I zTNc)zAm22j=JGPnW04kN7Vc~Y9jIv~h}NE@Bu%X21stLaFxpn^Y%a5n={4WVr^Orb zhODa+D6}l2=IGzTCwRR%;%YIx9)L)whG1!AB1BY<7l43_&7qL8n^gaIgMjj_=J4h= z&TYc3BGAcRs%L~@x}vo3XSkU#Orth=<2eIgtp;3*DF$-$n)^-4_+`O3i^zfaq*cU|H;s`&FXBi%- zW4P`TDde^oYP3_UMC?jA#)*5We8{+BMfvt_mQM?rZ1SZ;1VCAJ(ga)A%cnZNd4ITn zN5NAJ^23YOyVz)PW_2b8=u(Xn7IaWuTvH6jI5cVRv92$%d6_^?MWL|}--&;RpU%ae zZMb_A{Z#B1WQpedM=C`8Ha`ekYYSgqp(Gk+X5iqx@Gt7H8PT}T7<>QjCpYZERI(UT zbf2uW7=yK)vG(%xvDilYY0SVjSl0<_U&Tsboi?TXBP`s<)Lq%mSa*E$ZrGnxkIu&R zOq6#L4)Zu&#e0%`%MXL#b*Iak_j-ych&OUX8V4 zz9EtrA!;OkVv1X73KNr)es$*E3;Tx5rzIjnvjK|ZU&9(*a2J7P0^b=M7Hw16Lh@5d zO!1r9)_SmnwU^3;HWqOAn+HE{4oe%t1Fj4HB>LW>>Xj&PJpx~BWTF#aFA3#B%QtAZ z_>HnP7i-hS5D2C%nM zLDGY6-s(j0W^W4ot#$lLKMIb@|5kU+nN%#&qYVrD7qPluhq~~sy&zkQAcBh_=oi{{ z!|wQ|;4^-@Pz+@uQHa^+kz?@btQH0hF_e(*GWn=2f`<8$`c*uWDSooxATtZ4t(!?^85tx; zZ8RJXA(N0Ou%v?=vD!vM3S-L$k;upDYdkoXUEUJAg?VN~h`PhJB#FtaSg#i&SgK8l z#X{(0=G%u4Ng0cc2t-5|**N3#cy5ZNd77{on+OXH1;$)z8(MX?z_zQ>d~RlB?p@@- zB=AOdsAmAcP&qXSNgzQ$MJqzEc7R}9ZzL~FC!3CM?9y;RzetT56q-#IdEgKTLbg7y zPCtV{rZU=;&)OZB$2hKwsSZXtG$xBVVT-C4tks2+mIx7GRJXyU zC~k8ZA{y&DPz{XagN4lO8dQSob^-|zMYyI}O<~M2*K|2aO(|+&YXoNSX$Q6yo3iLR zsn#Z&525{MGdZZ;v2}4t$S6t55-ChENL<5k1mQ45B8y$2XGJkRFH$T_B)rZ|>X1iIfJk6+Ju`C%#sDfI%7lM0v2i34A!}%w z@up<1hDn-ZNTudk!I|kzr=~s001BWNkle0OCb8T~5qTwi`_0)O+evUXboQ?V5J^RHW*{gFyte>P_?;4duZ1%`H0pS@MW@= zurF0NMPm#x3vrH#vIcMBwh<>_U9;f1p~0AEUgF9RQ?86D+64W1#>YIGidlFnJ=#aqo1vVEyUn4*MG7Q zA!9Tq$Yy1xDdDI~eF3}J@UmEunyh8~c@@-Nbj4guH??JX;oYX@DQO{z#*}qQ=%ymc zUuv?%?fD*mc!eVl75y4DR_F?pyqV(4&m9+p1YTlER?d+Gt%&JJi<~JkRfwkW;3Mov zBd;WX!VMrpnWl(VU#)DT_7sl-*4dLUHa6x-DiDb1=P8e$wS7sE7b{9Ydq9*BQJXtJ z@CcylC|5l}i=|)b2;#GQDj7A1Xk3F_#b{Q*YY2q};_QXqb=kQFDFh0$fRND`Y=}lg zDG`6RSd1l0SO`575xT`1rr=9%5sXCrT-7;~oM-_MK{;n|OMF9$6HC3+XI^D#R}b2< zIVUQrpRGzGIjBddgr@O&Wmg&0RF)yd2S=T+TT4#^uSz?xCc>`-6o9a7s8r}bT($(( z0e}GbU;pF3l`5IB-P>>ee7YRR)1yx6#S3koF4_Dj8&WR7@wn-drP$C+1Tk$w0JL4# z94IMqZW8{osW6ISS8~#tG`%%z${?Pqf+w?|r&zMU0*LSTw};y(ug)Qm5}`)K0Jx>+`!K4~3WVhY}iPQFY?x4X$=S8FwsC_Kwyj$o*@ zZRG0!FjlVI;JO|8F{o9|>hAT2!`8!EiA^6MF$4bda zl$y~%WhjUgW;C|z_rN?|p0Wgw%#eEV?B}Q+z{FH6T-MtPT|X?B zji9c!t|}dWt7-u;g|GhXUvpwFoS!}?Y}C_uep+UtT#I5$VM%wsLsI5z7N_g_;OAny z7_IMEz)g@4|2MDRl|)cVWpTT~cz$fS5ZOoojYV`sb6o|M_JpLloN9*rd;>ToOkqw0 zm}34AHC^ZFQjSW2q>Jig+ST2#&ki}uRIhTZM2rd^n!@jAU=}Y90O)tOyW0mfYn2k= z=`jnTp|vJzYbaLIV(sDTg3O1ls(cu&VM0mK6qt>3*1CC`ig=r<)DshBWuM02u4NzB z0X@E)@LL79T>VFTZ@<988=gzWUK~)VytaaekV-Gsny@eHgjdcr>-uUHFTXCs=7Ms= zTj!EaF%-Oig)hME+!QN#XOlUlT#(cMDbX`-@}U80ueq!F$J#a8@bX)9l41sL1^Z|$ zGBew#8O4rYiJw#c9>93EbR z$eP9nH%VHhc=*R25QUaQXJ1DEO(r6ArC4GyCMt(RaG$@D?73b#WmN8C#xTVvo zvD_W*4tKAMqzgk1b5v~pBQqP@F^9&sDJo(w>z~YMZH*>}_AyZOZ|(itZ-@vIS;D&B zIJY!>;kpz#o*$?4W5h`(>13|+>@Z)9aTp(ib#gCY86Bch)mNiocWb*!%D~tTfJimZ zi3FqXn0@rM*!Yt?%9$Cgb;&(y^#TgS(!|v(&;Wp+lcQu(dteF@4)05L6+dP?JyDqD z5^GcxM6Qe~w42^oXso?|E1gIV-UmOqZZNJJPagr`_TekZ{=+;yef&KF-n{;5x*W&j zC)r~CaO3*jU zO)w#%5F$XWr6-zZ_>vE>T9t_jlXZYb6^hu;^HN;xg$G;Gd?=7b>pIu(?%#d`h<>_I z2w@)O-R9{M{CI`Zr|AE{!Bg<4%sQ4=xG^S?#}N^y^Aj`0jIj1llvPKeQ1wNCUOq|I zTcc`ZyTNvYpDq-p)mvPW$cz{&l7ZHNlK6mx-0O!uQJ}o(qJb!FZNT-5je$ZSrr~f~ z>9!*Pn537v(37)W#J@0$WZ>7};ca8x(yyR^}nN zSf8v!>>8CUP>iLh=#^y$3Ys*dfYM!+2f6JLG}_;QYgyon1kd1VR==^WP-_T$@mKI_ z!|e-tU@g5#@_uWvC@tx146kp)rvLcjETgde3Rn>|U&;QlY;Im_vR+lIXomy0dggd-(y=W@=uRYZQP5s6L$1#kKR-hyrQ~Pkw&p_N z|M)NeAwN*^&=ELN_EgFHv!0dWSY1OylZV5ys-U>Wx#}4IXFnXcy@s+1k*DChewQgk z{q9!$lJ(djN@6N6Fy}*Dr~;Tcm^p%0rgtU2kT!ty!$hGC(d-WQ!{JWMy5twmPoG2^ ziCeSELiC2D70?J?$SV;O1(JWX&SuwXqCgZL-v2V1UZUCG+_wa)QaiCZn>;`Ln4RR9 zqASow)X&0+&Y(p7;S#*dM|E8vA@WKqIiu`|!r|^M8WX}?`ODXZkf;HuELYQ+DSo7> z-=-Ui4M3c7%K<^WDzBVKqzttq$Sclfbx#~#y}Nn!UQQ)>9SJoqPd}=fKRY*c!=9B} z>u__QkGA8d?;&}-U5=k(9$-7`I%a|#uappkQ1eHPohy#s z%)6WWe%Qv@WiFW#tqSB{LnA8DoueZ@&IjTG#-H z=f@u|r$=2w(tTFf^(wDQkie*NppfdRGm;6%$|NT_J(bxm-wpu7;eL0xXB8C@1!l@Z zfXsY3eJ;jsX@VopAbFJ~I&n4IQnCwwQ2m+l(~8PPc)j_-yb&sKBjNy><)(8griv$9Bz|!{MpLnB9scoZ_Hi{le1S&W>M~Xx z$iyD2Imyv&9CBzV)%7$HHnoVbfNoM@xtx!oG?k-DOTFbdQfV6-C0XS8!$KMgVud_e z>;2$MGoB2PgBNvTuu;}-B++DKJr&Y@TFA`D;gJ9GRp0uUc8nt zFOg+`^!e?!X*8yx=@Nf8wWYEgUQ{hudz@6LTRTkJb-6HA1*d4jOo7rfsWaMIgf_7d zC1?tPqR$^1YjZadtwlCE0Kv8Nv?!K|T5Exg7)cn7bz)L1Md$dW0`6+o4FeD(=Ke&` zVKP(*UBkkkSMJ^{Md}o@80*m3yEk9UiQM)3ZrJN^a@gN7(|CFWG~!O>{U~XKF}*R) z`ziRT8xGl6V>&;gwOzkU*GTD^NiRVlXYyd<`O#R{?{1{kv7B<(?_?Y#?Gy8qcr?}Q z#-=rm$(9-lm42lvTvjTeb)B|rjz+P}+7^l(Qz8KFcL&HW_Qn|Fq)krb zt?P}km#0q}yC6#F%oIt!sf{XFvn-y#>06=y2?$ z3y|6NyFAGe1*gIwSS9|acZdp{fGQ7e?d%ihL1L-g@uf6D@f=V2eNcJcwUQ>bUYla& zV^SCwMY)hr2NtP^XOf^ju@5mnuF;H$$V#JG=ychOT!u9GlC#Rh8EduBL^dXbB(0#j zR8bw1V<5qLkI2&|5k5-gr3*a%7#Su)R_k{4rW5Qa0)QbB8(RT9$IoOeu~X!AF=hP+ zL}Q&^_D#mdm9 zOoPkwYa4J4WHcRZ2EZppKJIYGh*D?E=#1;_gB*P~P!Y+8n8+Asi~}R=f+yurHLZ=+ zI(NcVauQNQ1tKV7I1k994?@$@-_^X}$VmU{W&xBtftyWPz_0Q&K~40Bw+ zM?gPMvY$!extH;Hdl8n(mt96irO1}L7qY#L^=%Y`=;slD$$O$O>~C}1BUi!^ipe$c zMI`4H`XDlY^m@=Sjn!u*m(tqd~33=I8nU}ithfbkGv z<`CvET?`tu-TCRqe2wjHUvuDjzKAO)6LBhKuYL`vvN^|k3*}zIBAUh~@vycNno1kG zimf&U7KpqA84!wG2~kPy7a#~$qTVe>zSy`k2N5mOg*D3SA>V3O08q;%SFw=jg>PoPpBLWe!ajqnw#hmA70Uw(IwI%p|qnC=La{KKflOv0Vwd zj2joB2WBxyL1Qo#&(m3CS(Q?3^lY}w1U?rmlA2SBw{5q}59|t%F&F4G9XQoLvTWF* ztcV+%dD)rd?Oh^G<|yi;%_rl&eb%}G*Rd1Nkci9qyC%M;Ku3^W7||5Cyh!^b_)NUv zfRo`15C=mMfRQw=eT=v%5CwVnjEIZ(2gOo&%(jhLX}K`Pyf%&4v*pBmOg_WI&Yf-r z;D9=RQI*w_a7g!25i1)by_%(86){lp@41wbaD6H<<3W_i1#bjgQd>4kbD**H$eM@E zqL#_3{7Lk|wA6d6x&_=WdqiCR0yd5l)q@d*h-+O7~Qc`G!Qz6TindmjxPK_hN+yiK;7b~PCY??b zjfRj>5DAo$(YU#dwfVYP0C$_X95w2pk=j@+En2s;Tvfw{mb{@rg)N#0|L$-9hM6eZ zn^|pdwk(BbIsY70<>agzcGeAzqI}80MC;wp8c*2uLrRSe0t7#u9)Eyb%t5fOw_UG< zXr#ew8vL>1T7a<*(5AD*>k{ZPHySU;c^qZxtaV^aNazFWy03oquVk(J=^}>X%+T*| zMSM<#2RT}n$6v9o8_!SU`EhAfE5~S!Za{UiNBz=n*rTyhxD&^N*I)m+LMwvO#DxLB*JC=*0l@jxqdVZX=$Kn(Mg{Q{S5$dr6!+*xt6yBt4DVkALKzq@(&^Iywm6r1w6oX9hU z@qEmh4Ac4Zl?%9OB7}L$MnSIMW&OP1XMvcBdtbCRtEXGdW9;?1t~bWsym~9Lw`h#W z8qecJxk`(->)git>XE}dX5WtxyntMCl$AAgrEG3mdCOQ!(*wSJ6hv(EG@j(WTsPdl z{=m$SKm6`+`}*+kK~liSAAWcI^xgYE`4=WZQLM2^eVXTK>W5voJLKnYstDQ1m6|I32S^}Eau4p>s*(R+C}F`L&;=|*$9V35Q#Oc^0_N0)unM)bs;Y< z>Wqir!ppAOzg#JFCCM<(6y0dX^c?P^)(?9Tmjkg55LEcUnI8>B#wMmQjOv1ktpd%X zsI7b=)V9QExXEgY?z>T0(U<98a{NoDt_>Su6-mK5AjNu^mJ|8R$Z4m0%@*Kji&4Y< zF(0#x&AdMc?odea%3ow1eUHVWy8T;@!BFL5uclGU!WDKgCe}kKj_6t1 zWM1SJs9CkJv1T}82JnxuKwK}YV3Yme7a$(O3WF3#DinL)48T_Q=)?yQxl@|l>!f!Q2_Lw%~hOGkP3YKcsyoc(8 zJ(@UzlE$t6jR;D$jtitKbB$8zC9R+$K@16VzUU~k0@jhL5p9*Mn!^hja2pA=JScD_ z+suB1fT#_=Q~8ecTs8|@Oy~1WD}hfuMCkyKTqDzu^U`xQNquS>oqBCmF`6ijT7F29Ap%{pGIS?VnB}& z&EAZk#!UhK;E8-OKO_3)*Z(Gs5;K!HdS_G-QJBXIGl}nZ)lx}8nX%58u1?U$xadW5 zORLj`DN~*`W_r=pR|;fd4q>6Iq?Vg;U6WNvVk+I5mzs`*)y@r1SA(UV+gzue_A^^OWVD5N#tFm=v2-er=ZtO3bRMFgm-X``!0w1{ zDD=djJru2V##%ug-@X3OR7WWReCEsPa{7F|KetW~cg`e{zoKp^Mn>3+enL#e>I<8Re*Tw#tvgl5mYu>;Tca4g ze*D8fRe8Kt?TG6c)TCf~X3jfWYlN<}z_|IJd?b=YIVCZ-iZz(jBG{0I`c%ENWhV^T&4m&HXzj`tkR_k!Iok?)BmB z&F3F}cl`K=Z+`vP#=6fx{ML`7q*?pBHz4pm2D!1Aq3d_H>rbD*OY)5(pomq7nsA8Z z=iuizU;io(DbX6d6*i$3be| zxF|hhl{g}Hiq5X8wp*5G=`!&m<&s=gX5WYwO@pP#XG=aqD=uSw?DHHR5Ls;wD z)8kfKZtFhXd_OFzW{7RC^tvWJuTZtqucTeYP47=fLXr+@mpiR7rfusn*Jj$z_d<+9 z2_o_ub?7G~lAuaNHQZsrqS2XTGA&3SCWHy?`xvt^t|6ubj7b}^NS>}0m?-~0m6dVy zz>&0167Ia0#W*+Dy)Z{Dh?TuvP3O=IB{Y?QZOSTjY*Bo~q+0eeG}aoZX?^W$rSJF; z|NTGz`^8itQ^@99%lbwo?-YVoJnDCcTu^E*D!C^TUAn~M)A<vwV)YtMQF2;OHO=V?4PNTH~O zJ)VuR`Q60}*LHn@_9h#V*vblXm?qh7##a4gW`6kUmzYx3SVK>B!Rd1J)1|IG>Wsx~ zg#yF`O#N`n8TbPT5Qu^X-)|)}H4`X~tHUg04$_dJwX3E;Y*z5@J%nyIB>I&T(7tr2!+@&cyCmXb9EL7%NqA zjP?#mOS4p!udNjre82fVkY;9+xW+U!; z$zbnr|IWHj$}L?#AYwNhIJPIpxP=wYT;nZ)d7e)4LLx69+80D2-`(A?OKm@fE4cm! z4^f{*OVlnAz5V7dGV8$gJ7}b26A4QNh%WFh5BlJqroV(naic=c{^*RY>1QdDE$dAuz6xVg|`nyX5D4!U7iODh|QOf#R0 ze}z7=RixV1YFcf!trusn=LBMln-G{53?Tri9)1bJ7U;XHVHmIGop6N=i(sr1mn@==-e_0iWr*8H43k$f8vI zZ1ZMy9veA}H4pTcb3J$7en}lbD$uX|5*BRCrZwk_!yunj{E6LrJmLgZJ?ti8~F#u&{SJx)Q zm;tB2#6;2JR3NA!2n8aM99ft=I*b;}wygtqOKL;-h$Tod7Qsdy2Vv0zO=$_#3=b`FnU34L!cRW#aaMpO-4m6HeE`|7okdKnL;qef^|}Y zYk)=>O%xAev|1B^DX^GI1FmA#V$Om90P{4Za)!wP1v5F zRA4NmoZq3w1QQW5`0)bD0H8?)GB|ciT0$g9qA~*lfD^d@Y=1rl(JbiP?0w_q-~0Vt z{>9wrYUeXMy%A;Z_OrK_yqBNOlAnk@Z>Fr2yC*d*n&~TDedhS3;)Im~luZA~u?wOR ztf0(7W19uaSh$dA)4;FS6Wu<1$hUG7Nk|}k@^gq(vnZvcSq&M&kZt*L zO)V#>Sk50xmYtllx2;()*5+s_*R_l>Tvu!(UlXnL#dMdY-`}D!&JDR4FS!e3C~s8T zvH+Sw9^qP1FHUp`j43#xiUN^leKPt`x+4X-OW5*#?#|)xEl_45{Amj(Dl1GVshHVmOP>{iR>8r zzIhyswZ#rDGub0XB`}dJ{@iG;oJXNmZ)rAHwNql<-Jn5=94AD8-Qf;J-y_xNICx1~ zD7{+TkIX`^n$C}<2Zb2?Je{BXe4!BJ$NY3ra4JT?IVxqQ?f~eHqX#I;g^}zV2P$xy zXi-L#;?Q(C86#O{3FpM$D6wwH&tvdjb>dClJH}dL4Pqx9Q?xFZM&xA~n8JK{`Vr7r z>*NehY7&+c;=LQh!PhI_T6xCMdh*1^fuZ1eA<_%X`6{tC8_RP-jpkU1m?@y`tW>lR zbH!LS=FIlotn zm-=NVE_OYen~_@RI^M96pMr0)sJN*H2tu* z-7YC%gk{{G{a-S?0KfmU`nRC30MMqV@3or|D=1vXvd~m;MgYKk^YA_nW|l5YzZAmk8}znrN)*3^rntw( zIDzvfB!Y}jk?;}Kk*zR1M=H?}F-d{9TO{dAh-0@3=6E>V>2Qacd5$H63{?wRfFc(I znUX5MJaRCIwLnjuHl>kd05mp5x7^r`$ufwhcR;F*X|-KjKGD^oEzde2W&h_tZUcHmm=%)*}#9{#EFi&UR8Y|)A*`&DJ zoSE$MV}8B_nzW+wvZ~n>K$b~oEe#sc$4F6Y7tjocJ13qk#pWgQy~WqU&trC*1!B{Lhs zJZqp(fj%K3Iz$V`ik-dUFfb)a>fq<|(?Wa{DnZ~iiJ97 zF7k`p1ncq<8~?iL9+wJv$qYS*!-bZfAX=3yJ_A~t46#Q5s0?fWbMzVQhqSUH!U2GK>gNZgK2OZED z%xZ;P+J30))SFqx#R6zLDdw5lehcf<5fy4bpHk3MrO47uL8v4tRxCbNZ)a|b{|ZU5 z!fDIxQo~HfM>03FvZa(oWiSRh*x0h>iioaN*E$j!Nmm453%ZbV;Jc#LEva60D@A5g zIb`A!u1yWLq`P%8kD!V~B@O@XZ~taV1+Dg~nh60EG@Oc<^H%QFcG+GQBjyBTnn^^1 z(!VOEd2H>d(rBO%hW*VNBbYN1{n}a~62;C=wWgWq{@pkGyEn1|#`BYWqjqvoH}VVO z{kZECg+Cq*rOYVBobh}FrbcQ=QgCTny#DZ~RVT9YdYq~D_LEtV+C?I#3j^9;j|{H- zK=jE|UgyTSD2b2@5n`W>3890?6sGY4b+)a-Oa{b$cgTL(EdiMsB>k#;pEVKzDa>KI z=w|!&syV9U^vV)o{zfk758AQ z5%p-yc>avi5K3~R!TUsVU}g|L_8ut9ec1Q3N`DwU$$Zsb)ENCM< zButm_{L~GHZg;pmeVopZ(%jnLyfW6AZh-PFlV&MgPM@dqQL5ryzc)n@euqIB(Fx%w8~7+A$E;pe6+MaMZLT+U`RrPL67TpIwy z+{%q^8wE~fq|vUd>~Yg=am9Av2$>Xk&9Ab9-y3-&oiC;>{w2H=kwOy zu)legEm}heS`eeDBu|&8^W%@OuI4YrziZ-cdMA>)2%5aD>1Q#~hhP4cv@e^#7ve{T zl8xubw%k<%ou=_DYMO|+yM3^>bMVvuTouAzX|!k!TjVMa;Ozj1Ur1wJe$KMh2*m@l z5Xss++;ai3CTjkK1}?L{EdZrQYErj+0-*Pe41948kY@aUIQ##(+AI?wuyd( zDD_O;GHhg~O3eDA6#0veMD16KPzY%Wh`<Bl4|e^2tFIuqUmd;rc}Br{)Fl=~+~2*iu2&f? zO_!s(x!5{qjFG)HUQQIeuw0BFff5o}Z@6QO^AR?VF6pjwiA7+c;t!$J66@ z`mDp&-OVd&oiR4uokn_`(aJG+9hiy=ph%O*&ZSxoO~|Ifk8xSn_73w@K_Vr??shk+ z;RIrRo|z!a_WAMCAM`5CG&^zigGM`+0wC^g9&%~w{PYn3_qVT$H!?s7Gm{Tl1fZ5>pV~i=>-P`lahA4N}LtZtG@Yj*x8K z-DC>h`}`^0u(z%|+`R_CT|CmlEvx6h?uP=Rk7YEC!;OR9$2qCzchp7 z)hfH{=my%zXcf!O#Kz1{KNuOQ~pHLqe_mO@nh&`4X>1qfwtXwmR@i1^a5o zw%KfCX5)HnFukkl;Yoq)>g;g6hIzeDdi^cxr5d|+T&LCRbn>;Aj6`62r6aCU?8z3p z>e6M13=@ehB60G&rwZ1wV*8N0A!w8KOjRZkWtogqh)E7+5MW!^DvH?YF{&TPaz9(^ zppNU6{)5oJ65qU1D6G%-nigD9t+1uuGX<=jftW((lIOkv;(GHf%|#^pCy;M#uFIL* zhvmJQHyS)xyNoSX4Ra+!&$uSS9$zVK$yKV4wA%fm*NWjZy6AxI6&7z=3pbV&r>WavVPFTZf_ z5LmwkWhIYqY|ijzwv)7X%0JQwBzU6)!sr}CIf(QaVV;sPV)3SLI>fpXE5z0$lq!9! zLHGa^W^LzWU7rc&IhGPI-m)x#2qDbl`Iyxq5MjDJWmZOVG>MpA*YCRF#`U}1?SuXp z+x5oS@}&&qX9_-qS=C^19*@i%>5LVzB)j!7K!{ecoB;}K(8zU#2#K{V>X#ge%fx^} zkwk8B^9jX`K;DNiiBwxI5#{a3rAEn2lx*}208Y~hXJd?|D7^;L~sHq9(1ecP8CZLG!=W9ULkepK?GIG@Io|hW8 z6skpe3bfn?Mp-{obu_D+Px`c+<#a$~CYjvjszY4J*e_;~*Y%vRp}WW?XXdDTz$}K>)>r`aaE?m6zL zF~}Ctnt071gUx1u~j);|2;-o-!f=APskFU%}54Kk3|MJU^{& zQfA)WzUp^3qW`k;Vd|6#ehz+|FDKXU<-|mUX*_A&nUx4wIz1dq+!JYA03TyS@|x81>F zk!cqQG!fG~+L9n)#g<}er)1$TB zt9L(_MKYbA#_0lz!jX6^qt;SqqCivr6f`z=7UZVS^*t?$uwpEpFVdzAg<2)Cl~sEQ z`~FJ}3f6x=jN1dQkhh>k@oQ{Drhie)nZ)Wgxjdr&Mh0VD62jozZ)0XQvBY6q@>@1e z@&ITz5^wmbZw_EW$-~09vSCvs*hG2RO)hCYoVnDO^5zU{(1{vv)njx0EhcCp5!;fK zOUZ;Q@D3LF^X;vtt8Lo@CGvP2rv^7vbL(f10<-)_BhKnGWEDimA~nD%Sd7FE?F?#M z?r-b3^99_Y&6WXTEF*%Fn-9T572MXXcg2rc{3SrKD?KD7c58!6%0E1 zEsRpIMT6G%%siex)gs^`GUCcJGb0+~nlMd!(M14Glcu*sg2)QT6mXz%9R)v~9yNN< z2XmfSI)4Tos#Wu)WsHkT2yI)yWxO{VIG@t z&QI0vZo1*7?ze@eaWGw;P>D9k&}Em+27RV^BhM^#=A;lyasl5yyx-lt%Gy^EwXa?| z_-G(17bsCsWrNKOKo-vx9VJ8ze$HwesmGILPML{Zzq@<;GXT`AA!Z)-H?AM#ZO>1i zg76Uv%7t`efW^-l%6Tb!C0yh46?}Q@hJG! z(A20_>ltyNVoNp}xK~0yfM{Lc$7K5I@nuw(WS&|qOy+gSTfhI4zbu*_M7k=IJWmjS z{XA|DBLJ}NhU>CfE1bQQFCc=59w?4!xh%V3FK30iEJ`7CJU?02D_OXvd|3GrGCpge zx4}+px|e@U1n}&)ZIr$jO9x};Db{$6g-z2}_-7QD-~5IZg2y`AWdn2yEk&WqW@F%s zE8n`3w=F&w`S~b$J2EY~7DKa0ae=;3l$MBhP&7djc6`xrC&Cag08e$ z6(vtWnJS_nQg{Qz6Yvi3&+a%EBj_j)|3vojnar7){d~(rL{w)OJ`!1w^IN@!X2 z|7|nBYvX3(VHL~axGT>Ii1X+^YsecWL2TQ2SVi=pDSNz7woH|05z}9tGgMWMyluxH zRF}RQk_P=F8a1=8bYjDt~-c>qN=DihkJYo)Hb~!P79s)8f)&f#>V5*-R|0bB$GEE z7JV<+?`C?KhONQb)@BO+luq8Bo*aGuG#&B-O=P_>&C6IfpJKUAEnM4vmbRX-QUa4H`8XwWcn@ z6}iZ?^l|N;nf3A<@_1&BtMWotvAzqP)tRyHG4|_)_3E;XnfI{H7;|UkY8&OABePqH zF4wCEGxbQ>C_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbF zC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epy ipa2CZKmiI+fC3bt00k&O0SZun0u-PC1t{ --- - -on run argv - set dmgFile to POSIX file (item 1 of argv) - set diskName to item 2 of argv - set appName to item 3 of argv - - tell application "Finder" - --activate - open dmgFile - delay 1 - set theDisk to disk diskName - open POSIX file "/" - - -- window options: - - set bgfile to file "background.png" of theDisk - set win to the front Finder window - tell win - set target to theDisk - set current view to icon view - set sidebar width to 0 - set toolbar visible to false - set statusbar visible to false - set bounds to {200, 200, 717, 545} - end tell - tell icon view options of win - set icon size to 96 - set background picture to bgfile - end tell - - -- hide background file: - - set bgloc to quoted form of POSIX path of (bgfile as text) - do shell script "SetFile -a V " & bgloc - - -- icon positions: - - set position of file "README" of theDisk to {110, 220} - set position of file "Software License" of theDisk to {400, 220} - set position of file appName of theDisk to {110, 80} - set position of file "Applications" of theDisk to {400, 80} - - eject theDisk - end tell -end run - diff --git a/games/NXDoom/pkg/osx/main.m b/games/NXDoom/pkg/osx/main.m deleted file mode 100644 index d9e08032e66..00000000000 --- a/games/NXDoom/pkg/osx/main.m +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright(C) 2005-2014 Simon Howard -// -// 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. -// - -#include -#include "Execute.h" - -int main(int argc, const char *argv[]) -{ - SetProgramLocation(argv[0]); - - return NSApplicationMain (argc, argv); -} - diff --git a/games/NXDoom/pkg/style.html b/games/NXDoom/pkg/style.html deleted file mode 100644 index 4ae291a3c17..00000000000 --- a/games/NXDoom/pkg/style.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - diff --git a/games/NXDoom/pkg/win32/.gitignore b/games/NXDoom/pkg/win32/.gitignore deleted file mode 100644 index dec280709d5..00000000000 --- a/games/NXDoom/pkg/win32/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -staging-* -*.zip diff --git a/games/NXDoom/pkg/win32/GNUmakefile b/games/NXDoom/pkg/win32/GNUmakefile deleted file mode 100644 index da5fea00524..00000000000 --- a/games/NXDoom/pkg/win32/GNUmakefile +++ /dev/null @@ -1,65 +0,0 @@ - -include ../config.make - -TOPLEVEL=../.. - -ifeq ($(TARGET_OS),x64) - POSTFIX=win64 -else - POSTFIX=win32 -endif - -PANDOC_FLAGS = -f gfm -s --template=default.html5 -H ../style.html - -DOOM_ZIP=$(PROGRAM_PREFIX)doom-$(PACKAGE_VERSION)-$(POSTFIX).zip -HERETIC_ZIP=$(PROGRAM_PREFIX)heretic-$(PACKAGE_VERSION)-$(POSTFIX).zip -HEXEN_ZIP=$(PROGRAM_PREFIX)hexen-$(PACKAGE_VERSION)-$(POSTFIX).zip -STRIFE_ZIP=$(PROGRAM_PREFIX)strife-$(PACKAGE_VERSION)-$(POSTFIX).zip -ZIPS=$(DOOM_ZIP) $(HERETIC_ZIP) $(HEXEN_ZIP) $(STRIFE_ZIP) - -DLL_FILES=$(TOPLEVEL)/src/SDL.dll \ - $(TOPLEVEL)/src/SDL_mixer.dll \ - $(TOPLEVEL)/src/SDL_net.dll - -all: $(ZIPS) - -$(ZIPS): - zip -j -r $@ $ 0: - filename = to_process.pop() - for dll in file_dependencies(filename, objdump): - try: - dll = find_dll(dll, dll_paths) - if dll not in result: - result |= {dll} - to_process |= {dll} - except IOError as e: - missing |= {dll} - - return result, missing - -def get_dll_path(): - """Examine command line arguments and determine the DLL search path. - - If the --path argument is provided, paths from this are added. - Furthermore, if --ldflags is provided, this is interpreted as a list of - linker flags and the -L paths are used to find associated paths that are - likely to contain DLLs, with the assumption that autotools usually - installs DLLs to ${prefix}/bin when installing Unix-style libraries into - ${prefix}/lib. - - Returns: - List of filesystem paths to check for DLLs. - """ - result = set(args.dll_path) - - if args.ldflags != '': - for arg in shlex.split(args.ldflags): - if arg.startswith("-L"): - prefix, libdir = os.path.split(arg[2:]) - if libdir != "lib": - continue - bindir = os.path.join(prefix, "bin") - if os.path.exists(bindir): - result |= {bindir} - - return list(result) - -args = parser.parse_args() - -dll_path = get_dll_path() -dll_files, missing = all_dependencies(args.source, args.objdump, dll_path) - -# Exit with failure if DLLs are missing. -if missing: - sys.stderr.write("Missing DLLs not found in path %s:\n" % (dll_path,)) - for filename in missing: - sys.stderr.write("\t%s\n" % filename) - sys.exit(1) - -# Destination may be a full path (rename) or may be a directory to copy into: -# cp foo.exe bar/baz.exe -# cp foo.exe bar/ -if os.path.isdir(args.destination): - dest_dir = args.destination -else: - dest_dir = os.path.dirname(args.destination) - -# Copy .exe and DLLs. -shutil.copy(args.source, args.destination) -for filename in dll_files: - shutil.copy(filename, dest_dir) - diff --git a/games/NXDoom/rpm.spec.in b/games/NXDoom/rpm.spec.in deleted file mode 100644 index 330523104ec..00000000000 --- a/games/NXDoom/rpm.spec.in +++ /dev/null @@ -1,121 +0,0 @@ - -Name: @PACKAGE@ -Summary: @PACKAGE_SHORTDESC@ -Version: @VERSION@ -Release: 1 -Source: https://www.chocolate-doom.org/downloads/@VERSION@/@PACKAGE@-@VERSION@.tar.gz -URL: @PACKAGE_URL@ -Group: Amusements/Games -BuildRoot: /var/tmp/@PACKAGE@-buildroot -License: @PACKAGE_LICENSE@ -Packager: @PACKAGE_MAINTAINER@ <@PACKAGE_BUGREPORT@> -Prefix: %{_prefix} -Autoreq: 0 -Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 - -%prep -rm -rf $RPM_BUILD_ROOT - -%setup -q - -%build -./configure \ - --prefix=/usr \ - --exec-prefix=/usr \ - --bindir=/usr/bin \ - --sbindir=/usr/sbin \ - --sysconfdir=/etc \ - --datadir=/usr/share \ - --includedir=/usr/include \ - --libdir=/usr/lib \ - --libexecdir=/usr/lib \ - --localstatedir=/var/lib \ - --sharedstatedir=/usr/com \ - --mandir=/usr/share/man \ - --infodir=/usr/share/info -make - -%install -%makeinstall - -%clean -rm -rf $RPM_BUILD_ROOT - -%description -%(sed -n "/##/ q; p " < README.md) - -See @PACKAGE_URL@ for more information. - -%package -n @PROGRAM_PREFIX@heretic -Summary: @PACKAGE_SHORTDESC@ (Heretic binaries) -Group: Amusements/Games -Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 - -%files -%{_mandir}/man5/@PROGRAM_PREFIX@doom.cfg.5* -%{_mandir}/man5/default.cfg.5* -%{_mandir}/man6/@PROGRAM_PREFIX@doom.6* -%{_mandir}/man6/@PROGRAM_PREFIX@setup.6* -%{_mandir}/man6/@PROGRAM_PREFIX@server.6* -/usr/share/doc/@PACKAGE@/* -/usr/games/@PROGRAM_PREFIX@doom -/usr/games/@PROGRAM_PREFIX@server -/usr/games/@PROGRAM_PREFIX@doom-setup -/usr/share/icons/hicolor/128x128/apps/* -/usr/share/applications/* - -%description -n @PROGRAM_PREFIX@heretic -%(sed -n "/##/ q; p " < README.md) - -These are the Heretic binaries. - -See @PACKAGE_URL@ for more information. - -%files -n @PROGRAM_PREFIX@heretic -%{_mandir}/man5/@PROGRAM_PREFIX@heretic.cfg.5* -%{_mandir}/man5/heretic.cfg.5* -%{_mandir}/man6/@PROGRAM_PREFIX@heretic.6* -/usr/share/doc/@PROGRAM_PREFIX@heretic/* -/usr/games/@PROGRAM_PREFIX@heretic -/usr/games/@PROGRAM_PREFIX@heretic-setup - -%package -n @PROGRAM_PREFIX@hexen -Summary: @PACKAGE_SHORTDESC@ (Hexen binaries) -Group: Amusements/Games -Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 - -%description -n @PROGRAM_PREFIX@hexen -%(sed -n "/##/ q; p " < README.md) - -These are the Hexen binaries. - -See @PACKAGE_URL@ for more information. - -%files -n @PROGRAM_PREFIX@hexen -%{_mandir}/man5/@PROGRAM_PREFIX@hexen.cfg.5* -%{_mandir}/man5/hexen.cfg.5* -%{_mandir}/man6/@PROGRAM_PREFIX@hexen.6* -/usr/share/doc/@PROGRAM_PREFIX@hexen/* -/usr/games/@PROGRAM_PREFIX@hexen -/usr/games/@PROGRAM_PREFIX@hexen-setup - -%package -n @PROGRAM_PREFIX@strife -Summary: @PACKAGE_SHORTDESC@ (Strife binaries) -Group: Amusements/Games -Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 - -%description -n @PROGRAM_PREFIX@strife -%(sed -n "/##/ q; p " < README.md) - -These are the Strife binaries. - -See @PACKAGE_URL@ for more information. - -%files -n @PROGRAM_PREFIX@strife -%{_mandir}/man5/@PROGRAM_PREFIX@strife.cfg.5* -%{_mandir}/man5/strife.cfg.5* -%{_mandir}/man6/@PROGRAM_PREFIX@strife.6* -/usr/share/doc/@PROGRAM_PREFIX@strife/* -/usr/games/@PROGRAM_PREFIX@strife -/usr/games/@PROGRAM_PREFIX@strife-setup - diff --git a/games/NXDoom/src/CMakeLists.txt b/games/NXDoom/src/CMakeLists.txt deleted file mode 100644 index 336a5241c34..00000000000 --- a/games/NXDoom/src/CMakeLists.txt +++ /dev/null @@ -1,287 +0,0 @@ -foreach(SUBDIR doom heretic hexen strife setup) - add_subdirectory("${SUBDIR}") -endforeach() - -# Common source files used by absolutely everything: - -set(COMMON_SOURCE_FILES - i_main.c - i_system.c i_system.h - m_argv.c m_argv.h - m_misc.c m_misc.h) - -# Dedicated server (chocolate-server): - -set(DEDSERV_FILES - d_dedicated.c - d_iwad.c d_iwad.h - d_mode.c d_mode.h - deh_str.c deh_str.h - i_timer.c i_timer.h - m_config.c m_config.h - net_common.c net_common.h - net_dedicated.c net_dedicated.h - net_io.c net_io.h - net_packet.c net_packet.h - net_sdl.c net_sdl.h - net_query.c net_query.h - net_server.c net_server.h - net_structrw.c net_structrw.h - z_native.c z_zone.h) - -add_executable("${PROGRAM_PREFIX}server" WIN32 ${COMMON_SOURCE_FILES} ${DEDSERV_FILES}) -target_include_directories("${PROGRAM_PREFIX}server" - PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") - -if (DEFINED EMSCRIPTEN) - set(SDL_FLAGS "-s USE_SDL=2") - if(ENABLE_SDL2_MIXER) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL_MIXER=2") - endif() - if(ENABLE_SDL2_NET) - set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL_NET=2") - endif() -else() - set(SDL_LINK_LIBS SDL2::SDL2main SDL2::SDL2) - if(ENABLE_SDL2_MIXER) - list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) - endif() - if(ENABLE_SDL2_NET) - list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) - endif() -endif() - -target_link_libraries("${PROGRAM_PREFIX}server" ${SDL_LINK_LIBS}) -set_target_properties("${PROGRAM_PREFIX}server" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") -set_target_properties("${PROGRAM_PREFIX}server" PROPERTIES LINK_FLAGS "${SDL_FLAGS}") - -# Source files used by the game binaries (chocolate-doom, etc.) - -set(GAME_SOURCE_FILES - aes_prng.c aes_prng.h - d_event.c d_event.h - doomkeys.h - doomtype.h - d_iwad.c d_iwad.h - d_loop.c d_loop.h - d_mode.c d_mode.h - d_ticcmd.h - deh_str.c deh_str.h - gusconf.c gusconf.h - i_cdmus.c i_cdmus.h - i_endoom.c i_endoom.h - i_flmusic.c - i_glob.c i_glob.h - i_input.c i_input.h - i_joystick.c i_joystick.h - i_swap.h - i_musicpack.c - i_oplmusic.c - i_pcsound.c - i_sdlmusic.c - i_sdlsound.c - i_sound.c i_sound.h - i_timer.c i_timer.h - i_video.c i_video.h - i_videohr.c i_videohr.h - i_winmusic.c - midifallback.c midifallback.h - midifile.c midifile.h - mus2mid.c mus2mid.h - m_bbox.c m_bbox.h - m_cheat.c m_cheat.h - m_config.c m_config.h - m_controls.c m_controls.h - m_fixed.c m_fixed.h - net_client.c net_client.h - net_common.c net_common.h - net_dedicated.c net_dedicated.h - net_defs.h - net_gui.c net_gui.h - net_io.c net_io.h - net_loop.c net_loop.h - net_packet.c net_packet.h - net_petname.c net_petname.h - net_query.c net_query.h - net_sdl.c net_sdl.h - net_server.c net_server.h - net_structrw.c net_structrw.h - p_rejectpad.c p_rejectpad.h - sha1.c sha1.h - memio.c memio.h - tables.c tables.h - v_diskicon.c v_diskicon.h - v_video.c v_video.h - v_patch.h - w_checksum.c w_checksum.h - w_main.c w_main.h - w_wad.c w_wad.h - w_file.c w_file.h - w_file_stdc.c - w_file_posix.c - w_file_win32.c - w_merge.c w_merge.h - z_zone.c z_zone.h) - -set(GAME_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}/../") - -if(WIN32) - list(APPEND GAME_SOURCE_FILES - "../win32/win_opendir.c" "../win32/win_opendir.h") - - list(APPEND GAME_INCLUDE_DIRS - "${PROJECT_SOURCE_DIR}/win32/") -endif() - -set(DEHACKED_SOURCE_FILES - deh_defs.h - deh_io.c deh_io.h - deh_main.c deh_main.h - deh_mapping.c deh_mapping.h - deh_text.c) - -# Some games support dehacked patches, some don't: - -set(SOURCE_FILES ${COMMON_SOURCE_FILES} ${GAME_SOURCE_FILES}) -set(SOURCE_FILES_WITH_DEH ${SOURCE_FILES} ${DEHACKED_SOURCE_FILES}) - -set(EXTRA_LIBS ${SDL_LINK_LIBS} textscreen pcsound opl) -if(SampleRate_FOUND) - list(APPEND EXTRA_LIBS SampleRate::samplerate) -endif() -if(PNG_FOUND) - list(APPEND EXTRA_LIBS PNG::PNG) -endif() -if(FluidSynth_FOUND) - list(APPEND EXTRA_LIBS FluidSynth::libfluidsynth) -endif() -if(WIN32) - list(APPEND EXTRA_LIBS winmm shlwapi) -endif() - -if(WIN32) - add_executable("${PROGRAM_PREFIX}doom" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/doom-res.rc") -else() - add_executable("${PROGRAM_PREFIX}doom" ${SOURCE_FILES_WITH_DEH}) -endif() - -target_include_directories("${PROGRAM_PREFIX}doom" PRIVATE ${GAME_INCLUDE_DIRS}) -target_link_libraries("${PROGRAM_PREFIX}doom" doom ${EXTRA_LIBS}) -set_target_properties("${PROGRAM_PREFIX}doom" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") - -if(MSVC) - set_target_properties("${PROGRAM_PREFIX}doom" PROPERTIES - LINK_FLAGS "/MANIFEST:NO") -endif() - -if(WIN32) - add_executable("${PROGRAM_PREFIX}heretic" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/heretic-res.rc") -else() - add_executable("${PROGRAM_PREFIX}heretic" ${SOURCE_FILES_WITH_DEH}) -endif() - -target_include_directories("${PROGRAM_PREFIX}heretic" PRIVATE ${GAME_INCLUDE_DIRS}) -target_link_libraries("${PROGRAM_PREFIX}heretic" heretic ${EXTRA_LIBS}) -set_target_properties("${PROGRAM_PREFIX}heretic" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") - -if(MSVC) - set_target_properties("${PROGRAM_PREFIX}heretic" PROPERTIES - LINK_FLAGS "/MANIFEST:NO") -endif() - -if(WIN32) - add_executable("${PROGRAM_PREFIX}hexen" WIN32 ${SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/hexen-res.rc") -else() - add_executable("${PROGRAM_PREFIX}hexen" ${SOURCE_FILES}) -endif() - -target_include_directories("${PROGRAM_PREFIX}hexen" PRIVATE ${GAME_INCLUDE_DIRS}) -target_link_libraries("${PROGRAM_PREFIX}hexen" hexen ${EXTRA_LIBS}) -set_target_properties("${PROGRAM_PREFIX}hexen" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") - -if(MSVC) - set_target_properties("${PROGRAM_PREFIX}hexen" PROPERTIES - LINK_FLAGS "/MANIFEST:NO") -endif() - -if(WIN32) - add_executable("${PROGRAM_PREFIX}strife" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/strife-res.rc") -else() - add_executable("${PROGRAM_PREFIX}strife" ${SOURCE_FILES_WITH_DEH}) -endif() - -target_include_directories("${PROGRAM_PREFIX}strife" PRIVATE ${GAME_INCLUDE_DIRS}) -target_link_libraries("${PROGRAM_PREFIX}strife" strife ${EXTRA_LIBS}) -set_target_properties("${PROGRAM_PREFIX}strife" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") - -if(MSVC) - set_target_properties("${PROGRAM_PREFIX}strife" PROPERTIES - LINK_FLAGS "/MANIFEST:NO") -endif() - -# Source files needed for chocolate-setup: - -set(SETUP_FILES - deh_str.c deh_str.h - d_mode.c d_mode.h - d_iwad.c d_iwad.h - i_timer.c i_timer.h - m_config.c m_config.h - m_controls.c m_controls.h - net_io.c net_io.h - net_packet.c net_packet.h - net_petname.c net_petname.h - net_sdl.c net_sdl.h - net_query.c net_query.h - net_structrw.c net_structrw.h - z_native.c z_zone.h) - -if(WIN32) - add_executable("${PROGRAM_PREFIX}setup" WIN32 ${SETUP_FILES} ${COMMON_SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/setup-res.rc") -else() - add_executable("${PROGRAM_PREFIX}setup" ${SETUP_FILES} ${COMMON_SOURCE_FILES}) -endif() - -target_include_directories("${PROGRAM_PREFIX}setup" - PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") -target_link_libraries("${PROGRAM_PREFIX}setup" ${SDL_LINK_LIBS} setup textscreen) -set_target_properties("${PROGRAM_PREFIX}setup" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") - -if(WIN32) - target_link_libraries("${PROGRAM_PREFIX}setup" winmm) -endif() - -if(MSVC) - set_target_properties("${PROGRAM_PREFIX}setup" PROPERTIES - LINK_FLAGS "/MANIFEST:NO") -endif() - -if (DEFINED EMSCRIPTEN) - set_target_properties("${PROGRAM_PREFIX}setup" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") - set_target_properties("${PROGRAM_PREFIX}strife" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") - set_target_properties("${PROGRAM_PREFIX}doom" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") - set_target_properties("${PROGRAM_PREFIX}heretic" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") - set_target_properties("${PROGRAM_PREFIX}hexen" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") -endif() - -add_executable(midiread midifile.c z_native.c i_system.c m_argv.c m_misc.c d_iwad.c deh_str.c m_config.c) -target_compile_definitions(midiread PRIVATE "-DTEST") -target_include_directories(midiread PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") -if (DEFINED EMSCRIPTEN) - set_target_properties(midiread PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") - set_target_properties(midiread PROPERTIES LINK_FLAGS "-s USE_SDL=2") -else() - target_link_libraries(midiread SDL2::SDL2) -endif() - -add_executable(mus2mid mus2mid.c memio.c z_native.c i_system.c m_argv.c m_misc.c d_iwad.c deh_str.c m_config.c) -target_compile_definitions(mus2mid PRIVATE "-DSTANDALONE") -target_include_directories(mus2mid PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") -if (DEFINED EMSCRIPTEN) - set_target_properties(mus2mid PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") - set_target_properties(mus2mid PROPERTIES LINK_FLAGS "-s USE_SDL=2") -else() - target_link_libraries(mus2mid SDL2::SDL2) -endif() diff --git a/games/NXDoom/src/Doom.desktop.in b/games/NXDoom/src/Doom.desktop.in deleted file mode 100644 index 1ec35b3715b..00000000000 --- a/games/NXDoom/src/Doom.desktop.in +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=@PACKAGE_SHORTNAME@ Doom -Exec=@PROGRAM_PREFIX@doom -Icon=@PROGRAM_PREFIX@doom -Type=Application -Comment=@PACKAGE_SHORTDESC@ -Categories=Game;ActionGame; -Keywords=first;person;shooter;vanilla; diff --git a/games/NXDoom/src/Doom.metainfo.xml.in b/games/NXDoom/src/Doom.metainfo.xml.in deleted file mode 100644 index 32b9172ead7..00000000000 --- a/games/NXDoom/src/Doom.metainfo.xml.in +++ /dev/null @@ -1,74 +0,0 @@ - - - - @PACKAGE_RDNS@.Doom - @PACKAGE_RDNS@.Doom.desktop - @PACKAGE_SHORTNAME@ Doom -

}gSyi^VFmA%vEh7VMWN_lTT<&2Mrx zTg`2`S4K1uVlLMYOy%;OPx@;4;PnpxK8QzK6kil&QHaE* z-kzMC4Et_q_sld@s3oPgZG2JWXZl_L`d4oD?JxbxCx^@b;lKWWeDl}-v)}YDeer>O zaE9GF=iy3+KMB_bak$b1l@ikQ>MtH>l0wQnj;IiWlhBJt`-(Frk zeX>|AilVr9{0ReN_8roM$Q2bLNDOToHoIN1Z=5@?s^wyRuianf5{0RGpU2BeMBje< z?ZSKSI3|fn3ZDq!?9uy)Ikk5sQeR2aJN0pG- zemOQk>KaQKr_`~H2#I-O<}&zLW;4w3r0q}`4CXCD?cb#tFNZxpSLBfTgF}1o=DX8B zR@F37jICR-a0tZRUegq=bgf#vkM3vk;{f>pT+p5_)nYI_aLHo{3pKcYd`#f z2h*GS*Z$W3{TKfGp9xW3B(%RND|&(Vzsl)}ulOGxzQ%zu|2O7#W4;Bd8NF;r1qQHe zPcI$$6_K-aXH-11H$@B?g2R=M@wiOd&au#XJpZ3)PDY@E2?ZO@NVvUhKG_n z2WvgV7>RJTT2|G<6;;lG%Bq4snaFc4Bh$L-FtMZ{DR?3TmK1Umv9t2)_9SHIi6{f@ zV^kNDa1aT-=uF>)*QAyyO5BOwnx@#ss8v<=vE$g*o$biM;22^WoK}fvxeFwSp)phM%Uo*DF5l2w7y^LAXeLFq z#Ln#xh{cz*Jau`oAxmbG`N(;TB4SmEZ7m|1#dUh`UZ#s=pNhrmB-@Ca>d9$E#8tIW zmHk_vN-1r(TS7ntN(qs2ekr1AhP2CO!T`{=k(eBF2qEie0~k_+n8QG$zSCo7F(xw= zwU}a;x2eU@0-|$%m`J8Noj)ofDdZ(`QTp%u_TT>}|BIh^e7+st@U#EVM?dw>#rOTO zk9_#_zD+Bt*_l!my2$i)Rg>uxw8K7q#sZ9PO?J1HkVffDq$%xvO7zb0$Jn09JC@yX ztwZCRPuKgRsw(e`Ub0I=2mt6kJ0erDzBKL~13*k#ikPO9l9{HI)XX~;RZUSQJ zgbZLsQ8?!^OkG3~ky0e**m<*C-l(2Kg_vtGrgR)689-)kyt|nOb<5G-p2M;j4@-W+17m7Wqy|ig~x{Ow4nf zN|fgSyMi60IH}=`W<$VSAZEEijY)ipF0qWcd3ORT$qZ78&S6*QFiSC{)Gk){5V38# z7A_Iz@YVSuNfTnq4=95;x>5-{=Uf*6#}>f6&-NFYN@&F17iH!-_;PWCNIJ??j=I@q zhM@)k=S!8;)*F%T$sgSN^}XfvM_(?g@mf#BQ-ZO)k&yu4>}2sh-}==*@ZbK_)64yE z@Q;4t$$#*l|JCpP&TsnXzv#F3Gj`nD?DiYs_09l@gxJ;1a1@-o%QiTHKV*4poe=Cs zqW4sn#6)}O=AHA9=Wm3I#e$sAyk0N}A&BT|S>&)L&s;+Ej$_i8L?r7PB{j`sgF2nH zWTxJ+V|LE5sWN6I8copEWTs>on{fWVHVi3Sjw+EPS>yb&VO^5niqify+M z#!#miigJmFMOh#cSTMts1koe~XB9ht=U%d1nT5S4&1u9Vf=6~(>uO!}0-=z}9lm}l zpq=Rx8X7ZWcGe@di8*sevNcNPL(j{(Sq_s%So~zF_oV3w{rp9W(KBR6wjPIBQERA2 z&1$W9R~eqWR7`saM5kV8mTlJicnj4Au1S~tN!|pmiNE?9pdCO+j$tL!l3@Qf>Lc%w zz|cW*G(#D=e^9y2hJ!3z?#WNSE0^qyhzv|}LVx?adVnJ_5K)og(va9WS1>#33&n$i z+LT(LA}PicV~jDM-V{5KJ9$INH1{t}HT&gug{uBRiAWYXRh9nRaQfAmD9hPGd_1eJ z3Oz9yN1lJM`+v^$D`e_QSmTig%8|{W5A#P%)6o0%2kYGV@*C?%O~4=l{DO z{_($=l3cq;+10KZw|;8<5@hhwqLkPCbY(;2R;Oyu`G34sDa=$wB!4I?$4-n_x|u>* z!)e^syUqmDKtbwFUyrBf*alLdDei3Id^y%~p=VDV^ngd}%@KVz>p#F?a6c`#zRKbu zUQvI(^9x?&-(5a3LB_!qR-(5%NdQniey06Oa;-i=e&X)r-u+><%@XRN*%#Gvu{;gU zF1B@1EzDqhaUMc@@9h2*P&Xh6O%#ph|Mm>Sl3NiRz+E|^Tb{|nP~%n z7=;;}H&ESfH)U1bzkff*HpP(Bp!Kpev+P#?^vM(N{d&F5Qk+>$-}_>Ha&NcWUS3?B zot+V}nf8i+H*s205>+jVt}q)@+&p^*0E@!2bKd*a*=y^w*W3MNZ1=eqmlNL%Ad;@X zh|O->H2ah^BsqKVV7)qNb{EiL(<#(D1CtnX6+vRGx0gA6lo%w%a(RNC;wxS}eeBp} zw(^6sdtFW6m+VV0HPbxOm|d>y594#yhw!%FhqzxY7iHm!#YvY#fDwBnWLKz&zWK4$ z>DkHsNBIQuW?b(sOto!mGut$c|jOTtQZNFtd~bfaU^bhI%<)h$NJ5I>b2ns=gXY*~2cdftMm078sH zM9vWr53H@bCji&XWna7!)i8q>>SEsAhHt?Bh@_O&VsDWQQ@(rzXm^{??22mHF{yI6 zp_Zh9o+4$vV#5^FBQcmM*>jU z8JNwf^+zgV(;oiBM;>5IAg0;hh&D2tTb;u+ghHYt@4G3Zz^2{3!-v-4YX;x+o5Jwt zk4T*36b2H=X#UnGes;+5#~JZqNURQc5Ol;$?tuwo&^?J1d-+nF;%cTc|5swWCWxF_ zwmY$|({k?zWtM9E38HB(5s~`WaKlLL&_lv)JaQU-Q z+1-Tq7-;Znku{V5pPTv3eB)j?RUK8KbLC_h9YZf>#4%>VIvhS+JTM*vJa`K8;WUMM zO-4}fgV9$?4tx+{LixdYdPX?YGlq8!b!e~R--}We4sTob z!2j{jf9LR1iZOeIcRm1py()gX*SF$f2f9eyea(a5k zj(xf8!K!lp_|4_&bai@vb9uhKyihYy^Gt|Pm7WO8YCV8QW2n1EjF^ZyM|}*0MNws8 zBt#4?6*TBS|lJG*y6nLc5% zSlveiB39Llr;m%OEXxXP3}|Aghi&uZ{`*pFHy7us8j~29h^SHkQgze($isD zU_kC=Pa}mU#U{3UiQ%0mPgQlf@Q&$X(>SK(qUajxMOl>V?dEc`xm+z5rOyta5JMv( z>$BH1rP%I8^!#E|cy^q*OC+Kx$-M`!5s{=|syVlCzBB-dK_#ZPVPCQ@oG;n=e3hD# z0o0dIh?t8--t#t_%kw8soFgU@(WJU4JR-C)iCW>ZYz6^>s+`<=bpQ1ah{P9iDY$M? zJzkkV17CNMSyf4rQeMpSo+2qsTT#rOT%i&VR9RfPzys+7JjDDQR=00RFAfEBujVu2 z^-m7x|Bc1sqf;8?iY5fxYZ1NkRC+jpE;PGRJbi?8!(7OB>T!m%z)mN6T{g;+^*nLJ zx!P9m@Cv0*o9Mc)~D*h?7O(0b{$#d|5Lx$N~2ljBtd zf-X7kJsBoK!_%;_PZXwd0Fy)7wUOy0f4x2kwA{t-P6Ycbm3j`#kb&VuNp6<2+Ci0I z(B(SHg2$U}@WI#5{^RfX`jgca+rUr!?O*ugfBHv0`WtV(8q@+@iDk$4N;i4nMI7J% zSAy~%>qE2P-{#-m3%L)4r}0r{BKw5iK3T2oh?{@K2!m0PVbo~@JAkH4Sv*%QlQxl0 z9HF`J89+sQPhWSs8&@>25Br5zbPxM)bMs}8R8nkqFtOnt1rhq?kBDuqb~a$AksS8> zO%^`Rv(fn~g*LR?YIUz#-P>P2t+$ueay=B6Lc3?@s^vWZOQD8=s7FM^NF=dU1C`An zDv{NfxM%+6D=Nw*`=aM-UlBdAFRJyuX19rT<8i^hkhnE7)0D4HQo49{ZU8B!YEiA0 zs}R}@qlez@D5F32o2P0fNf2?dTuo! zJUcTpSguxxC@I(kK$Xe$-m`b?i=tvL5)Yavx!DO|#Pr&u2fkbs)vB#G?SAXc9AH~- z0iaslL#7+n(q^}7_S=W=`z&G(O|2?nzj1}ndwU9vnMz9RJh5w=oup7M)&SVlyOh#u zwa&H`nb)D3Bn2WW%aSNDCFdLfwoRiV_a44Jt*H{TFBhgd;A~ZMX4$#DBO*KBrHPV4 zvnTfKT!u1j_pPa}fS7qob1cebej=G69NN}#*lhQ`Gl!Mc$_!MZsMc*VXc0Qd4m%>8 z2~F%SpCHm=xylrywrO^|Ei)6l5ZV~EX)ggFiKyD?y2?GLH|{UK?~i=-fBK_8z1bb+ zg}?FUlkfh4zw~eZYhU$^U;CvmgAvP^Mm>;|&0azWF5bt1_f>KkcUZWHg-AOUJrxzr z+hRr`U8@ps>wU1l?DTA>f|u!DwUSJ$8O9kJKTp6MH9!$qURUeL^v_3FDfE|+*T1~Mnt%%sbN zW|eCroPz?goeB*>puu6sD&s+t2(b(&X{Jd8fw-ghS?;6>!U4po(|LlKh5dDx*75y2 zQ&S!2`PVBZ&7Ql8kjq5iK#F1J(m4rwJ3?Jow^Y$dRi__1{X>|_Pv_gN^ZE9%H_xL! zTP&BI%uRN_(F6b@24?Jth+R>FLEG#(ix)8G(mDcOTwa*kqAGF)b>hc6t2L#VB*l<) z@ZY-kc-KdJcDdOWK3h4OsS(rh3e&szBD0I3-Pd(hRb^R)woWl-JNx{+R?A}Aeg1}j z@pu2#pZvKip-KPskN?!q|KhLyhu{7U56@0svO;=Y-R!2e%qv^_Y%Z;SU^ZwkdFiAQ~G>|0WH{Rwn51Jj}Sm8BLC##NA=E2<@$g=R}c<#L@V-r1kCsFsM- z$vSt#lTwN)w%!+P4i3<&2!zz{pkswiQpni-VO}u%;q*>V?>R@!?jnRnwPOPu;9rQS zsulo7ZNr2q1p_5QW>3r^G{e5jTp;SC{Z7n9=7{AFi7F9Qg#!ao zrOEbYY9bcf77z&00G7)I5i*mh1!u zH_V*#)pB+D>>LpY6u^pdLChK3DJcMesE@^Z8MG(cv>l#ec8kPGx55`y&#%q8E<}#IB}i4xBsLwX z%Av~zJsfEGlj%1^!PniRsS8QZ5I_K+&i|LEip#{VAkL*%az(jZYf7Ccj#*JwW+FXt zf{@4;A+&8%<6(PmjLzW*Y@J~~)7zDq0~zIUdhcEgO|!cYH4*KI1oKUvh^oZ`01y)N z6<}uag?B|&*R^Vw(y;TWq9)jRJW_T=FtbeN&0gzOSvl`RQ|Gd3X67+d>0L+?qaxW5 zP-YHN2rVLJH@n4RnXfuX8`^fUT>GM$)_!;Uy7Z|me0TZmIHg=mj7`%t&7$(R;VL=r zn3s*FRud1XJI*E2dVu!hMBniNndFZxv04PbBl-E0vA|j@VV1G8U zhgWKN_8I-!?3zFGL;ut7|MGw4JOA*%oDnqBLYBRX74cnV=$hHU-yn9x?~1>vDu|f( zl$!`Dsj4b7jiJqjbZA24FsOABrpP`6p6X2s-cm2pcwZqZ5T%lGklk# zqW35V9M}91n|(j_Mym?v%W(!t%;q+Oa!@8-0RX!K(7B_VhDQ~ZD_wwZtjSEkCgYNRY9KHexD)5?Giw}X|0-fe0Ok%}F$fHrsrKgSdcaHQ^R@$!(81kR%beoT zBHJ+&b3W$@{It*jp*-E6&lRJ4`gMK*o)J@i%v>ZeRD+tdMsV1AfNy z87U3De}GPDF#QDeq*CkHbvd=j@QCg>*rlzigSLqo zfQka;%*-b8wy3JV<@^Y*k;1v{P@I2ckeNN$!Dc__?pt3YJUET4&FKID2S-*FID#1F zGGi7n>~@_AQ{Geu4L9p`@W^>)m*rR_g`Uuw?JUNF57`4`AAr8sNbK@Qyf6H{B6ILl z4`fF`o!H&^#k$#Vcbm&s@3bOGXQIM7ZO9YIvb+|gw4gXciwsY@U{2d zKYK0TpU~`8Wpn<{ez!?#7Gu4AW@e%$AvJBx`;VxanRj(3%zaIsq-sgDy}V3G9zA-< zgekVF>5cb)5E0pzs_F9LoH%gc>`GV`)pEHcS0Iurie4+y4gkc&%$>ljltmT@?ImgY z`gmEbVvJ3_Cu$KuBxy>ElY0PI@3tw$U42;;#r^yD5iz^Hn~JKaq!44>#%1XdF~lTh zO?%EvtA#fMz<<&sfq(k*KKLJf`$yh*?dd*02@)aG92`rxzVoQER?3>6vP zoJBLHpGq<0@%BP%X9($X+bkDFS@2ZYC$u~2ng#moatGKDL02VX_SLf4oM*Wr0O-x@ zTT?3vR)v%_#x3l&*@I$Q5Bt#Pex9b3QUJ4}#G+glt5XS$q_Epww)I}r%pmO=Ra-3z zGuiDM0Pv2IScoah`(;0w&GyOgL=n+@?|lWP+s)+)uw0(Z3IG#y#c|yK+<`H?=Rn!& zmY;f86GV3ISWfSFMY{Imz8JR56xs}EkQjPHjLtJP=R52R0P9T$872VFtkoAo1O0a9 z<{2M8KM{RS7JlH;e$`RzfCGS?7x*-soaBXe2%fjuDckr?IP8wXK+x_X%QSny6Dj;Y zEjuLUPyOgRZ~D%O&|p*)F9$6mt7Vp@FF|$D2 zW^vE$kuoqw%j3i9nGq9I_`nX%$@)};Z!StOBO0p?QnU!5rbFuZEnok|qGJR2^z>x8 zT!m(DW+^2z+c&{ET2_UbZFUWI@LhIH)nZwei_PUTGxgphVzoN8UUd8L8b#DpG<6Ey zqWA7U?9As>Hy7tcQ5I#DRg&3xX20L<0IaMQ%)H%PI_Ju20cJ7OAxYDwyM=zaAI|KOAV)&KC*SI=#tf8!5)`8R*vmod?2=q~=EN#0%7SA-)0 z4C^6uS7#eIP<_az;eY2&qP%Kl%?P=UK6l#dovm}qAlLL_f-^N8qtp^{Pz z9m&CYB2F1gqGD#9gL(J4gvedvkXd6;Nk|Nx*p+6b@57~eSW{K6RRuF6=PC0FQk;&z zw%&;(LUcuS^5A`Duz&VArr6fC^WJ+`RO@1~{P@RyO;sK|d{ma@_Tn+IE6Syrwe`lA zi?UjWb|2e%BJP5|sEAx!Z+b)kFHasI0ufzYJiB=IY*`gW!Ff`Z)ry?2x99ANYI&-v z@4Wq{%U$xWh6-j-lnX?1z9i-+Z@*~TTckWI$wBTz3z1)F0bj3T-AZgb+mJ;p^|0l-ha=h}H5m zhB`F6{E@neAr5X$sH$J^yT3Rz_2%hYX5h=pmy2?-R!O2#lvO4_sOrZ*_N)8NTDZ%zeS2@a!0yHW@(a9Z`o$Z9_uD zMLB92BR~+1QI?elzz~zDE=!Mu%me@_b>-_^Em%~(@Gd1WgM6Q36vV9VKxMhAn|ia^ zu2-w&YMDZtQpVV#D=H@b)LW0e&9KZHodV%2|_NDL}s63G`xom*v`fZ}O8|^};3Dzt}x;ApW;Y)if>gz`m zPIJb2{n!R5$JGBCM`|$6#|4gbdK`7yru^~_E=xqjHc`=@OL)QPel!L;LvIi#71!C7 zPx%;wMtKi$8WYwRF0R?EJv?(Z8TH?0ssLR`JI&LzC-NWh>N^xWj8x*WO=5kDja^^I zdQ#1hRBP`DHXEJY5h#0!n$5TXQ#gB~!~V z;zuxDat0N|>A{9UW@;IFYSTe<2z%&23oy3zvr6+U-8`0R>peBEYK7%NKZ-P7bLPOlCTp&9-Bsnm<_Lovms^x?uZirQwg{0mhpV#f!Zi3fh3%ixic%VsFr;v5<{~C zz;bayp#ift#O;22MnzFBog)4YKGLE z1|x)aUli_P`M{T@FRIJSjjF^n$SRK3IVsdBwmA`WMMchMA9nUW^E3=hQpz@a-SZ+s zBvnZ9Uz>RtJv)7-NowUVYyt# zw$>DO^`)v}3kFaXPDJZA0)VT7sP^2S8HFyzHpO;Pc_RFk-+1TG{n*dMbSRy5vZ}uO zTfXl1eBp=5plcACap&Xr|VW|1ICK~u=GM_I=DL!bNkv8`jXC33xb5vUTR+LKsKxQ**>MgT-^zcE`G?&|Ewc-V5rEFkdF#EQzl)wSm z8H~O6+QH=XSwYz?dt;e93nHjoc8##^wm;g*7uJC z2GdQVqg&KW4qC5v5XacT4s16S)a^Ef;M=99U1X1QsAUE^4hWIF>E_g?57WjdvFrLB zIJwWQk%lbLzyK79P;Fu!-+9wf=ecTQsyX+WAw)gUMC$_CZbUINj*zv^(VY;otxzv6 z3|As)%?wPi4`TBBdyNFVwx@!fKJhf>91JncOj5%Bx{SK}LW5pfCr@l+xHt9fQZ?)f z=Dl!?45rbYgVh8+*Jas#%FE2AdN3e~h@CS@D7m)TFYZL0A0u|o@-XPS5dknE0Rj<% z5wp*S${hJb*;SaF^Adw0%@BT>Wvylair20?*58?5`{enb{mVbyhC?rfFZgXA_}+i} z51gG;qd&~m)5G2^W7X^HI=3m7+SOUj-J3lVdB$U7@tI6VU;ohKZ_WFMq_(@II1%H> zj~mcb4Lg+#RUvZ|-G_;%(yY~uLlq&@;SbC>pDXXzRZ{=~ZK5v-!$j_{ZYmvp)dR}r zP@h3bp}o`!|NO+RGd@Z%wH)sxh_BkY1}6k!zyy61+hGo-@$BG4cu;~GN=Add1#|)m z*e#%--7-oY)hrLY*=mTR!*yT&($UoG`WcwB;HkU8prV-XMW>}Q0c%WDUPk5vnC>?h zfI!Se;i1z@n{5lRZHG9b4Jlu`nKGlOhN#)VGkX=K{XXx0h{!H$=HgJRaZGL74(3Fo#F1~9a#ET+tT?1&sh&ikRRtI{QTc@o7Kl8B_lE-SDQ zjFevMonOdcCbNV9Ng^1;B$8x(ateq@-pqVcONyaw7R%LQx!P|xR_~|#Xbg>+NeT!! z=%w}gFW8SOb}PWNIDP%AU;BH$^$&hIbEb|#u95U4^p^t5TnBUL zks8UikMkU;v5uZCyAbA(ei_CnYmz145KED34=oTS?lq(M+T4>DJuYE;q$l33wDP7;kH4F&zd~2VbPmvw+5- zw{pZFzhN^Q(vMM*^~SOE3h`O7-l+-@85pPyYR1FL-|=HqY*tOw%vL9M5E?McZGUHj ztporJT!>@g=5Do>gSaxwG=mP_5j5OE>uTuI?A zri#Es+1~7G>p?_Ba%#HUUY1o=mJ9D8JGUOZIrP33c_W10?Td&)jBQATkJN317E;|+ zcM;1XY9^m_zaeG|ApigqB4Qgv4Hs21vlxY$nUI<0DJZ6-2ioPiu-40GSa#$kMBpsr zN!eX5ga#3eeZEyO#-?f12Vz{V?<0>A%m_G$jvnS5h@EqrNKC0*tNFvBF+t01yGlF@bSPftZ~ZdB!4UgAvV{x}@wP zoi{?t5KvzfW}VbPUMBJeIkkf8yHXr~DG_OwrZo{U5oKR^_L4Sc*;(3}HWmsCNm(rxdhQk?woS9E z>t*QyQB46*B&b?SnwJ75%Zd<86k}?d);os?G3@~$CP7pul7lBv9qv#Jt!mwdXa*3{ z?KcVQB@7Q6?zb_iz(W?6si+9upu;|_y=FJ$w^y&vN2A5wWdR2;ZR<@o-sz+njjsI0 zgF%%c<;0Ge`&^%qC`+szxG8oNa=Za6Jf)jV5&X|D^BxL>4`qP4xdhx;UhN^JS1~2~ zlJTrRo8N)6a$r}A%mjt5e$mqfw4d-u)DI3E%;<;+z?k}sv-@4=YmP)jMmDX1%rg7l zqOU8%bU}vd+*9wkHjamW0#}U4p%BPK4Ad7xZxOZJZ*N4m|+3}=woc{>io0m@y4UgMzM`eF)ylSnl+Yl>^2%+!+_YF zGbPy}(R3tnmn7Lx1|)W!)Qf70?aBINxX(q|owKUO_)bw&)nXk(onp&G-ceC5h^S)D z$Wn>v^6~XxuPtWYhQ26dY4k0VpQ!#;BE}qtJP_>JON}gwa1?f zO%2GZY4_~0fq^NAc<&^&yUQmM+T&@1$i67RY&W+!F_YN{eJg$5Csy>mrVZwGY67<;M?4_zhYUzllZ5s`dZnOSJ|-~fqI4A$29 z{I1-eJD-HC`3Hw>s`Yxs&TTHAL9Z6Fy?6%zPS+K4!Oo`?B!+5n^5kOor~l&LczUs) z9^uQr@I(L3ANtCB_fM}|-Q0vGe1}BvmS~roKRz?ndWmDcC>BFf5=aLCA2{N7=inyA zCbavrN1ug6v8`3*bX^f~-l1Z%>uZt*i1mJ3@3+%r<&F1$U}!}T7^N7R6dER|3U~JK zbwsMS=P8DAaS8}TEF#Ddm(K2u? z0MKl3sONr3F94v~J`)MK^qol*MYYQ2f{26}V}%%F3)U%D9})j@2%8|8L>p2aH9^Vr z3A+VO$IOncBwirCxXP1ywl>@K2_#OFxaXK#+m#2wu~0t8WWWgg8_#G$V4r%6*|44V z4poy}W$5pr;dJ92tilk5CW8ITFBOnZfMJBFtDDxGFQgVXWf8Sj$=b)RJ+U;v66|=6UNR zU73sFVQ1XfJ(+yU05Bia>_?_SQRlmzSzREAHzXR_nhs-8>8My|{USEiGa506HZ3J695?O9S>E9va=};0u1GmXrqryh z)BR{O2Twcz7`}8Cj_*Y(|1L#GGqBR+dG*LA>-}AaR1xjS2@{`FjGT!`M<3el{vOFW=L)N+Oq>D{72{*`EAnyvvZ+6^^GI|$9z=wh0d%w3kn_#< z20(}76Nn6_M?^P;fvAryBAM28yT2FaVK^4TJ%|EChJ!n`y+D(K<}gT5gidyhz?B0GHt=ZJLB5GJSuVEee6g0&;OhM z;TPXL%pW5L_aFT`f9+rROTQ^1q1ncEt1lGGy`Zu-3})68+fUR+XlLGL)AZXRc@?%G z@0U?F_=U;ommK;Ro_1Fct@AA+1o|?)Ehx{pc;As-~fzqsnY*!ptT|`7pNl^2zxR&6&BA6 ztRhd(Je;ZGKhA&C+0eMwP}X(}%UM!y1zNd6&z~9ahnbCi2T*Ww=Rm|izH@-fV2mm7 zpmHiX$CayR^&?29u6OZ^e+AI<^a-TkLa>ACeHvMa+7_W*}bplgtIm?r^)5} zqDYyh?aK}!EX;3y{{N^NwxocloH-3?JgGu#_s;uY{^A!ghTGd)6@^1@h+NADZw!#JE&jjuJ6SR4RYp5im7*@x!v%?gNp8UTgzk@;r?_40PkJOxgYX=zu)a|-oJfw zI-M-SJH|i=?e@`{Uz;%g)!4$G#WNT|W+E zjt$JFqs|9W;XESJW`95Qr|x)Y+D+4La!xsoF-BF*+%pJsA_JRMIcFtB=TL}9PW^B? z_RWTgG>?NwKAn!%=poYn=CuH9_Pphs*g8Vq-3V^RxiT zwfj2&6yZE}oW_^zFy1>6WftbtKlcCS-}#?^=jY$fFZj)0{p>&aTmRCl{q}S`AY!}O ze(!nU$1s(3iS7K7Y;|?ID6Al#=pg*woxz7y{Pr*7&>tV)HEkP0yuZ6u)ie&{n7;h- zO8_83W_f(-c6-`4o^wt^=R@OS+aDiP)hzXy6OoI}1^{wO-bWW396JE1`Tu?2sVwD} zD#YML^y$z~pLm=<`R&a%I33=HxQUya zPjOR>MhjQ={SQ=E0%tnOkCB;Q;^lqymvK!HK!o$q+jvEpne$v~%u9U=$|WQ;CDpB2 zc$cQ2yugLV0wbYFrwN?{)yP}ZHCatc&b!cX9?hE@0sXb^iSPp6vtkp~WP$|6*yZ}g zEo?pOKM+u9ib5$d(B&LDLroB1Emnm!Z|FPSfb&|iB(P^A*{?A;J3A4{naUoKbhhoe z28dRW(QNmvwzJaHFA}={K4I09QnWcZ~vEn_>bSr zzw;OW$)EgZ|NdVm9j1&P`a?Z+@FkO#?+z*cF~E-I#3CY^nU&7DrL57}pLnL-krq-Y zO&z&T`(^=CRuhO)F4V;40#k{o)PnbF4zz{zm&d_6 z%e`-eWwULOD8yD+j*sui4vb2xsv_pLK;&Ri5bHSh#tbx0G1~`oy`AeeIaAdvf`B2U z=^0a1O<5FxK<1&WsS=q55C|cs#G;ZCq#R@Pp~S^8W+A>jds62A`oH^M|NifOJ^#)> z_ZNTtKmMElS`1<6hw3vAvN6*<-V1-`JfP)A#TeT+u5SlF^`PiyR-yM-W zsMu;Ha)4x6Zy|)4u_BypGzAKxWUDT=n-H6vMg;I7l58K5 z!6ItxigD;c!NbR6uzpOMRJE3b`9(GkD*B9_%}b}P7wY>f+#+GKWwAotmK-{F>D*e& zDyDp0sYpoHw^`Xzb^`!xHv4H)DKrA+!M+r80)>^cU!k=WktwZ#H$9t73SVpuwqhoc z1E)d3X$@xjlvw*8Q?Q{TYvdYp! zl)glaDFX=Pl!cikHa;{PI|#?j!o1-u2)pfex-;4|A%^HfL*$)AJJCaI0gGX|s(O#x z?eXQ0cil^_0DZDrr{uQ2X!5DgAFSWs4)<(X zs4A*hsIdSLfvP(XS6YMiXXB#f#Fc5T1OUQFwAs88PIDASPJ^V;g#dt(ldAgfQkk8h z_g7&_J&Od>TH9WcAFk?_iXGZC_nSK32^hy`|LQUr)CrlMskbx3#Dw5>xohlD1y^cL ztr#j52YRABhzhFt6$zF|V+GX(n^|c0v%99il^pg-)JOz2@+89Il&Qt1q#Dglq;Q)N zp{}N;qDoUWAd7pzVwf&hN6Y2fki&%=K=pdcc{DFznQV$og-H%YlZaTqG7GtiI{{J^ z9KoEk^=kInih`3F5CuU*%!gnWJs>M+MkMvvDkqc5Yvl?Hi$8$^z`y*LfAfF)d;i#yCH}_0 z`WOD~f8(#7%~r8;vV8g0U(=aZMfc^y_d|^QU)+y9-LC1}O0G7NJfB@pImO}?zD z`V_Yq*OW&1J~1Lcq8IM$0}4opGLcvHJYrB3aNY}7RwIifrmTwUtN~mTu5?a=fZ6)d zJSvNpbK1@44OE4J{M6(*7ozQL0II@3=X0Kde=hT!rB#}?NKp|N;{1bFeC4qRkUVq% zK+Y4=W_M?Y5jpdcznKMpmSAAaU{y`y*qw@at8F(vgyNqhtRl^3r=rY>nZNnwP20rn zCRlIAISFU;le7ys4krM}nE@~aCz8`p7j85hA62FAx}5Xf{k<@cV~>c<=5`);BLMT5 zM|XO9Tbl8;%4Jq}m`47xhO%1K#xekynTMeO$U~CJ&Kq(XR7O>B-W#K`@16_-iS0JF zJL}PpkKd|FYAx!ooLKsV$Kx)}Y< z{TDZ{zIy!j_fHRRHaD-3NJSK&dwSoMDJl zKjAGQZ+@O_&@!=J*yP?ndLLMgY6#sY06102`?J)0%Udw|+XsHs5e4ro#w4Xdg#nS7 zPu(Mt`|_)w7$8R}tM(zbO}kZiuOd0iNoLMTpJ{+>4*>;RbvX|v`Ub@9en;pIk8cog(|90ink_m1fg&TnfW7rYhTp}N zLKWB1A0ImZzRRjx_c?3FtST+p^gP}qMibFh(#YdL-UFcXj>z>xheRZ-3d$KAAv*Kx zK*?6M7Y|McmUV>WjB!cM2j}z9jYAjPt>2ZN-Zw2E`H!FaXI)_(4SyXfxZ;R*;WrPp zDC6qlKj)`>n8`jXJr*H6!s6Sd&uFyIZ`o8~UkOT_gXw1TwOaLYQJPmwjSpU%OIH0H zU3OM3t$Nwz&*zUvc*c`{HXh-FG!VOt#s^;5Ksv=f7JnnHT2vd;7M9IiwwJG8T*#JM z-UtfS0I_n$I{VHQ#Xz)5D6BX()!=4kB2;oTsf`ipputI|TIWNqBMs|DaQUlX&0vCm z<)8U8zx7Xi_R}x!sdhgj^L`5zj&hSl7)yW0o6)AVWcmt^%u0P!7^9F#T@dF z!><&O_giV}EmVhZR+UkXq;T>@y>BP8S;)D5#mk&0A*9V@{(F%~XqN8V3<>H(2eq zx@p^+o5o%oW9xi4JUtq`p{jSE{WOik!`p8FG=x=U!#QzI&1OFz)S=mki1CJnGpFG= z_C$_+NW&?QLwb5ZbU*tuf40H76=c3Ny4LVtLla<=Q1hc2a_)5v*LHC{s)PEWHd&++{mL~_n40OwR^Sf{Z| z^yJ(b6Xa48a@G$y zM`03-_Cro7ef5)H73NJIRps&RFGFlYvmH}9_G4(bNUmvj06;z>QXWcPiijMZ9?jGO ziHuB7`2Z#OaD*gt@=vu;%W_iY$2Y%UOy&@gD35&}I@`DVhc_bZ z;k%>;;)gWrxH^VkR5erw{DhZG`9onH1CNA@ z({90YW;gDoC7AGu1?km!q>i;s-5mVBKqfeMvU;ToKlhH(#m#NDiJI3rkxZK7x;0t) zEv;0>b)SeZWy%}+A{TJZ;_Nn;lJ#|(>o`=@y5f8}zEF9zEyEIoXIJBrEqP&^hKmQl z1ct7v+x6APv(kUM)}?FFQaCO?zZ1#jvh11gY5a)G>y>r;$NHCE!<#4XY`pj)leg5h zuXfgg;AMY&mddF`;G~yr^1>ykox`XRtYle`_0u&6<5V7C^>?5Bv)1DS zte)FB@l&Uepm}Ztf6}7o@kf0bO!h1bV7dqvmWb0y)QRu`7nkS3%qp>9IiZ%QdSBNC z!r3?i29_YwJUgAe%@&DSPEc*DFhkG?dF;V}t_h4K=L^LE5z&FFR3=aQ+&7sC+!WS? z)g__6MDYn5_8=lGW3i754FVc~gorBI_r1x|hyK)`O2fBpJyN{6{~|W+@BYJo&~7%L z-Q9`E!^2}_;5??xmc|0AZ{NM2AEM^;$fC2`mMRz-2UMNQM3|=Bmg(5bZcOE*5oHk* z0K~wKaJ$>tW1+YTLqUYhnR^qD<1h?e-&?j+h^@u25yE!61H{;Ft$*#h{_VSm-EPyw zh|W*4cjR%HA$n`F=iR~iNaS5k05BZi=l(Fymo1eyk3;wP)`jRplQXBpL;*l^8j*8> z95@wmJ!IxY=nQ6?cbvjALgTx*f)B0DBM>2vgF5F!Tlkjq70!v7Q)2JE_Z}3OlMgKb zNY27c>-Aid%F;Nfo_uIcq@gO!_GTtQIPdc~4#Uy=;9Nj*L^KSYs@ioPhi*P(hv8`Z zTa0nD{o;5yoVsqmZHREQ-4xh6=cmH~AjA8&oBi#Lv1iXfuSv&p4XhId!HLTB!#6MI zt=wiK0bRa;b9(vPRe)vrD&XQ}c|zo;-&D}Bez?V+Zp&`d;*6~4-6sGdJUu=>Jaw-> z|LU{byFB(PisXb@auVio=u931l)caPbUZyiK0Q9&?l*||{^2pD^c%nR=L*$cq1oSA zg`&(N%xN6@@%8K1cIjuvixqd?tP0N=A8W)^i|jr->QR& zERfHf69A_u$7+^oK%=Vq5M5|;>NzF*`OW^mPN-iOSTD2TzVh!gO|e#$ev}#Y9Gdm~ z=Q#ICsGY;6Kf{Z_>*YhqBtTH`!JJVXxnS}WM8cBEC?Y5#vq1w-wl9W2s4O9BcB+-j zAOe8)FcGc_PAG0WMQJNVYKfplDNwsG;}yWPW(=b#oF>kZiAfYq{Wd8z=N8TaWUfLY zH3(X+4>B0}l&F~Mfr_?uEH!969EBTH{gqhv()Zg)x2&BF2~Y{<5Z%Rluu?A{dnj5>?ZLkjIr>?eh0ix z7r^IVpg1FGaD`#M!tww>MG?vSz-a^$OE{V+ExMX_fK}!)_g^B+%tTHmt3D@_38yL; zyIW*R_XJg?YEPpgXP(@ii4YwqPiwDI;~@~}1-^q+d3Yigcv1CF$_(H;;m7c@hY_A9 zhMXA}XcdA-fO2V|y_k^TM~yaZ7FexIB3#HavoqNxEHN*yI(niWZK$Yfed&4VW@o&O%Ev%Lf|Ao@40vV$Wnl$KnM2cV_cuAExnOZ* zI>kXn961C{V-En^?XCo;0|I2{qjNr|B&x$OFthiONbMRTlBfs^%=1CQ!{G=b-XRj2 z54AloIStOafK;AOyODN3V&gQr5IJ*qI+`fT5qVFhoU_jyLPSJW&Y4Z@Z%zVM3L%mA zu8H1<=wov{9zmhqY|MrOXWjn#UR%3hGB2Z0#&)YBIgiZ6`YyzVT!0e3h|YOa4I+~F z-Z|$(oJP=C^bY_4ga|4|dI7j}axxQt0tBj;trpiboVSm;i#6XIoHW!hnK>A1*96XT zo||Y|m5E?s{V}3*ev+K5G)cm2`U+b}XGfA<14NSIt}x>fc_v*q(E(tHu^6CK5iWC8 zewN8@r3?TgEaf)-pz!(*pVZ*ISO zY6;I+4qib;1uipCW<@dA4!d4CkD$OJB`eVeq2x?@gr;6aXxr9MPa^*T`=Q!(WPX{x zEMfEyVMKn;FR2+xFMpHi>@d5J*}bGXv5bmN&Y|ZQj5Kv{)|4L4__{e#3CC6L=Qp)JU_U3gOIy>zaUdcEz45rDoFucun zR|F&g2ol>i#5Rw;h@_O5+4)GS#^FbD_TqV?A)@2)qzKNDbJVo0l^UudJbLe)Z!r{mWm z;=Mx%(+olYz{v5lk%D=zSug&w{DZPl4mS<0d$vV$-#gNSLKus1_&12`+#Ndq{;=I4Qah+$f+kI43WwRx*5dy*w z39qkI7RD=oZrXX3vLT?#@QF^s3-^F$naqd)Fb*f+VSDr1QfqQfu?3NG5UOfaAm@GX z4g2l>CT@1jSw)Z@%R$Io9B$JG?)%YuA3`YLi&e}}l)N*h zV1?r>wNO>gqllS6VTqklB^S_wf04$q_daa4Tbq28tl*b)S#zhMe`KWLiw5qJW%->y zm?98TX^n`e?4?p0p)LDT#R;D#J9a3zl0Kw>9A+A=dhmwIQg2p6P%J>1{=02LxbIAieUf7iLfmPFE(!)psx56`;A*RBgg?V9sg> zxF$ZC$7q&Ob{RpY)&HlSbyZZALSg!BlZaYZoTk;+d+{hyKSDgi=l)|s0>0Oz^jSwV zg+A;Y@!#H&wYZ2Qdsd(;`E>~oU3S4nl zL{tQ-aXzj>A6A96sG<~k{=5Ln8bGl`DrUClspbQ+wK7C23e+@AU-lywT{u?X)ob*R zb%f-PaHK9SY>3I!X5udg$f0+A+6M7_=x4b)!7cvUrd zHS_oK1!c=P=LI6`nuWHK4kwfRoH$ho2&uaFFyaQEEUc+w&t8Z`}|9r^y$Prp2ERLLWk2`m_pk8oP3(oID5+2Hpe+l(2R`` zW-kwX_wd-X?d#ZJX(WU>F)Opg7@c#p7Ok2LR#nIDk;s#CLw6d-A+sRSyKmnR(cP=p zJ~T);Q}MdPL)m<%Mab)mOx~wao{j?%w(YL^y9k{lBx?waN7L+XW-Krb9T7F{Zs_~& z^whSS5aT#>02%?1C^kD)P7_dXqq%ZFmA!NLVcyzmA}XP2UcR-}wq)N`I8h#oXIj8t z{?6acd359fAZ~V?^Xc$ZeE7VNA&9W3gwT-l+uP498XiQR-hb^v-0bcUAg5%*tK;c( zI3Ane9pQF=G=bLSi<5N!QbUXmSkXS@w@XY-9_=o`B6N`$7IThdB z>^E&YyLKSJn{VI7818RxCxlyAWX!@WmNF5e0>HQ5zDX(VH_g1IkHaYf`mnj;{3K#y ztsii@ECvxDRO5VX?M?OUr}BH72AH<(&SfYtsH*90Y+jv)j)l9^iJbfDXTO!lJ`J7G z1FJ&>U5H4oKRqEKkq1C~nVlVFY({=_bB{=;$9J4Z|6CIe_~Tpqyy)%lLlN}PB-G=x zSpCEmSvM#&gN$0wXe!!&g-c=GD&Yc6&faZj2^#qEZ0PGXGOlR_I8DNzV=yh`Y@E!; zXEpKMMU`MpLm*oJAzdl{2e-Ew)lM>lNW@UiK_4C~sHW6u_b@ zq4|mn+-qTFg?1*TJ%W7UnuuZ?(F5vr9oWJD3`6{BA}1_m~*zr|khs zCq<5^==q4el7+_LT&WNsC>t7Tbq^6KVEIAo$%v;nEH)oR(^5hFv9}P#%II#wl6BTA zREejPFv$e$MRyCc*khh{=wz^fxJuisXG2S@DB^5_Uq67)&kNyljFzs27m)?3Pl`5tql=f_V{VyD}>xIFC6e3u2xR>Key@>waw6m?OF-T$S!B zXExRRM09+v%k-fE!`n>1QK2_zO-d7%!j8(Rp^E>1RuRina9j`w_&%7Uw{3z4IvTn?c2BBhnrhKL>D5b z!5H?c5SxwJb6>7y5qwh8OIM=hlFk-@giG`X;?Vbb96~r{`5RXN z03ZNKL_t)Td;*b%(?iM(sz|Qc-X5PGAKt&6j)GprG%aRCUZ|LE(xSo=+@Y(P7!e|k z{SnE<&7PS7-X4#~qqBvC0B!UD@bvILi;gKz zh@JC9wd|~`jE@mORHraVMC??@$3w4*cXuHYJw3d41==wiEi}y1`#9!f%AGW_wEt+vi(JLNa1$hs;bJ6hGd&v z)9yt0@i2(!IF=C?xe)=(tY1Nh==Xl__u6*z<*)qIdDnh^D`K0{$Z6Q!+~2(VJdeGK zynXkMhhe*kh!kQ|Oa@d{#UchzegE+A_{Ha+Ip;&OC30VV39}e(d-LjaJdWLC+k~54 z<9y>>QK^0Y`R7FR^Pm5mh`PQ<#O-9f@Z13Dhlm`06q7vq!w~zI14wdmA^O;+p_{xd zH5bcu4~VKEAZ_;d0C0MIM>N|ht17EzGY{c3Y90`2R^LM&$$Q^y3jtm-sE+*r=0F+0 zsW>}2@9XAZ<)F6mbHeArh62}>VfuyX_PJX5Md!bMyqR1j)W7I?!?_fjT9|dIt~G+S zBn{d>MfAgD=an^=K40EV@mmYvxXMz;m6Bl&w7&d{v9e`Ggvs3-p3B>tpqxrXU!5GN zFl$bho_KmKo<{%{w|H6lDg-HzXH{>_Dw+#;^4z_Bh4|I#R0K0ESo^6}jodkITUt+D z*^-yqP(fEvvesVDinxORW`#KD%KM;tMi4%v4)`HW&!=t%wA846g|aVh#sCv^t(BLR zDHclPn*st5t*(LAEJsBAF>RR_M0TD~z-$vgPXd*$yIGcHK#LR~=NpJCnNq!YKt+m? zO`Qw65^GhP#k`o$mys$>Puy%2d^w!aKgAtj!GoZZ!c6e$6<5kdQ;wGo4$r%;O@Q4j zP^+{{-qJ>f@d+k}Yv)2}cdffOlj6k)P1VNh!U|Kay=v7rY*{DH; z^KdGZ4Ig}H&7qBRQl3C~W4#NjN*V`1h;cJ5`Z<!Tv~9lG?3ZEsQ|HLBRxj+~FpmYgH!g}HVRR@KmKOi@V=e)VU+HZ|(XoZ5D?-MZLp6yWLcz4ZzTYGFV( z3h113fe5|BwrOJ1ze#n4)>IXz@f-|j2@Dc(GX9P%D2+@egFa_BoVonK*{Jb`C4%bZA&?Mv^!fcr5 zw)=Zm>j*IP{qgWPBteAxSFeK)+uP4n#4aYM(NeT>8gdemESdT-t7>e7l$v(Oncu#9 zAfhk6{7L~r9-R-~hpy`~%hS^nk=x#Xb>W-#9a@BWdyCQE?pyEB2;ord%IN+3_Y+ru zzWVAbJG>UUgsS&J0q*Yt034p4Vko`r;qBMt9Fogv=|$zPR@te?yRk;H4lX3e0Y3#ud3Va)_M=;{LOxc04eqV|32YljZa@C zPdOjAx35+8`2HItlAN9Q3LbN%Z%m`wMvqvcf=JX}&Ajb)S-j1o1_6PNM-G~Ht!2lzez}rijcYz zp;HCe5~11R3xX482@G~GRY>i+IfqPeh6@oPk#i0}-6WJIa?T`5(<_Mx$vNj#fjCbz zSy3@gA~_-jNX3Am@Y4_hl(cRUW>(_GGMt>bt^vaMeZy_fh7jMk!7>Nq{b>ClR*-ys<>nPj0ItyMu1uNE0BB2QMM6+oF%>Uv z$_44q1oaM)%m=3qZbL-StNRiz>i+3ZSLQx{itxZIdpaT_c~n^-z$$MG@NCRBTi~I> z*~5ibp0&yib0(!JI&F}mc%%8BJ2wsUSvt+%424}O_MB4z-~>> z0N_LP0mw&~1pD4O5~iF(3?W2xv1y_2PhiAuu)3sVY;YcZY{oYz3Ghb@b<^n< zyrkzsBHV5^PznnfPX|>QZK$K-$T{yp!MW(jPpOkY&KtC;3c))hav^%r1|X$$Je^WX zqT0sjoc}S%GR0EBhiGcEoJ9eeP4JL>IOZRjP! z6O4y-n}SHpSyhk6Q;ab-(TEPBAZm_L*fb3}WL5=ELswj>rn!{&0g+VMyku}q9!3Q3 z1EB+vPdyi1;v3gT(hIfxKLGus`ft3t9z=NT4s(d>e80+PK8sPp6mQB6Y5p2_+O~#DohyB zg$5B31VF~_NY2d>eZpCU+a@r}>3CFt;HYUgyZyfJPD6k2-py1oN9f4qJTB)wfG}I) zIT11^&Z%v;0Pyhmlu}Op35Y^yMD+Od;E2ri)HxDi0A@}AV7IEIV`wNJLnWsA;#VDW`sd9))w-Y+3-Y_RA&}(?N(}G4Mo)6q`20O?P|}kal+) zn>Gy{ITza<=iEKLMUk;TnMo<}0Dvww$}F5jvMM76 za;|R7ypOZ^`gl44V!PRlJdER*GN;VJyXg!jW>JL%Wn-MTCd%sWfkd< zkFnjv&8{R7Ap#URjlI}cWCJ{F)z9x;tuUwzWiF2>6}7PmB1$!kker!WgpnKy>J*g; z00K#c3l3=cingIlZ| z8umTSh_ps1u_9Vyr9U{=Xse)e3ShYUJdc{bx;@}xV;HP?|I384m`{i(;*@`;AMQO+ zYqJJn6Wj=*a2Cn+U}}1-im#il%sGu_K{FGn5KN}25sN5rt%0$Qd}0XAd<|XRxnA7$ zD9UIHOOn9qGCpHbf-^5?k?Kx_9#yQOAkWi3&bYM|M@&FbmCV46Y;rnDLTVah6)-ZH zB>XVyCwv@2(C4$-%nDbhwV_CkRF;AN3?+yliYnof0Y0Zx+JKa;5=8_%@0VXcEWdC? zCb0)<<<+UP^k!N8vrW?KTYxS$UB2SV)O`i%+TP(>;X*`&q=-U>2IKMwEYX7t2dpry z3iqnoNn|=5Kh_I=LK)3Rxr;wkL5KJOYD|^odcM!$@lCd~EjsdU|>XQ{Ur5YsTXtr^) z8%~F@I~W*SU;`fzaqN$(W*>?zVoF2b_aOxDeSLU`&?16}dS&NGRZrbzHnhgL1;jM= zQdF4~LVM{R;C&3C8TzA$5JK?o)TI!7Y@I_5-dTTX?fDmu@t^MFQ z=A7Z__$Fum*{}V&Ss$p#)8m6B!`T=xj=}j5n{7^GcYHLV z(f!>m0Ho9lbGx~z>1~qp!<(Pm*65p-$nWpJe8~*+qs}Z1}zIHMNJGm8F~|MH=2_m;1jZ*C1a(wxToyE`ODJ^-ktQUJiI>rP$Y z#NZv-PB|nt&)yI>_h0=QfF9p}qvXJ>ViUL+W4jwqPa*;$05J4N8m(xL)yp3M?~Ci0w_4&)I0n% zDKYbqA0VF~Jd20?s2hVW?S#&Gen0Z*i+Fl^Uu0bXKDJX*Aor=cD>4QcF}cIQH4b41fx*uc+)Xufw;B`J~jL@tlLs@gH(KTsBwIuYS4hy6Up z9T)7s*l6L|G`!CBEAr-@Xw^)RI^&x{ihT^KG!dq7nki`BKQA_^xZg|6ulOFZH_ z*kLVFnIYyfa5!@~yH*h{hptt=Gkmyq9fCPp@%hpcS6O})(2cNm9YR>YKb*}c5OGx( zA{Jk|6+x-aDML6*uhtJ_n4I&CXHR)t-1jQx$fdZbvR_znE?^}^FiF>BB|KXQeDomH zPu>jF(2-v6genoj@{G-n!Zreibt9!K6TTnk)7B%iX^A?mMiCcIh+6dx3U&Lp_5rLI z7I-n~sXCH{_*7q_bECaFmY}wAnBV1GL$pNWEswX(e{glGu@IO(9M+28=Su5$_}Q!G zA+;Srky6ijg7cnyHb_GR{7&7kE~Y3`J`B!Onw7L(C%Xj2>#Q>Xi(#7LlA&o_365EU z4)Az50DyIeLw`_(oCN?vaPuk6d8{veN$;x))1f;6K#WuLiKM<89XUj6A{79c^V7py zBaGO~hQ2!;k3)9~;Z05hs0xUEVI&&+BPfjH$qh$;h?$dcvacSS4FKj-FCqxwWBdA7 zegjlb4{s(C7c=YOc`dI-U0W{pX*5E;cz= zm7Ii!Yg|F|*fYzkkL-VGIQFN5)%Zqw`u5vzGt2$$mYnxKB2lxu1r=f0-3RAme|#9a zr#v4vAP9UqzV+u#3fKrB`UNTJ!qb|;+r!$X0KyaUkVX>^1}mN9#_ZH#eq^Qzh2oSxnm2I5)ple^-{@SR%ox-os`rgUjI zHJg2CHfiRXDGdFA$obG(n@-Ljx2!!NT76Zy{9Yl(H9{$p~ShD8mHYqsLE(|o)F z7q1~wgmc#e)pKxpLI+p%-rSom#rdRF23Sn9s_y!#7ySGpSc{kS$|}6pvTE&K|6CgM zg^501ONM;57)KyPn1vu$pq8o~#6rop`%OfX$M@`JM^i&nIw3d*P}Uvr8FZ-6(EoH{ z-_0!+7D_r!6?7#b*Ry63>-JIWKV4!0KlEHr6D0ij?t%44iE8=#Y|~dGO;9~ERr91c zQ4YW&u2v4PxK`g^{P~KVasDIAU<_xyw(S@zo&_%ci__*%G5qTx$u;Yes()OrYyCuC z?{;1`8_;KfS(rQ{mtADF$<5P0Bn3s#^37nT2H*Hgso=kj<%j*oA;vgt3`^caHo z1cqH5yCXSwe}8X(I*!9Q47>de06sn)QcBxRoCqQqo7TR%3(@;v1}@)x{RcC9=-u0I zRUuD079`g++cAx492JgZe@a7#NIpa#qB&a-qWN)~@VwNaX%H#bIR+ns8~aW{jODT0 zG@R4dUw^&bZnm2Zfcg;0d2=RHHH1cT8qA|$9EPFqi6{g=^vCY>w7-3Y4u@d?fZ_DC zKJ<)(Kv&Bk&dIiBMD)#uI1_oBB@lTZ19JwIoJSRn&1NoUIcI<#K!?8XhZKS*gqyop zSaMcz>`z3bawX)15QC>X(o+JZoZ(}#_=g|mW6&NfXUBqW+qWCf6%Vbb2kW~(ZkM+9`CVM&}4IUi!1 z#(wCJwI5W|Y)d%>Dxi{+QQ`?*z1gy87CjxG$hpmSf96WB&-p9Ou4zRrlZAQcj)a6r zr>A!l9He7+AQ#+(A6HhOvNSEAIS(r0E1ToxVAVxkifd4f5N#~2AMPNhcU#Id{+O*0MYM!y5;~YkrrG?pF%tvauH<}fNDf-t;PUBzJR_=HnPz;3Pm<1LuC_yE_lCY{GO2$vqV%7(8 z1$J4t2<7ixVyUD+5h~2G7#z>wZ0P`XV&}n}g*1oD%9Jj)s=DVUwKTK%LBK=n%T<=w zWJRZ?yq0zUHS3V(kZ3c8E+s0b2|!Z4QU)V33u4vlOi`=Puu@CgVQK^*M1fjsezBCX z>ItT5o4F_^C;m7vmmw86HR6fUq(O!A9MUoe<8jGsThtDE)urAxzKI-x2vbJ1pf1fQ z5$UvR6A>UH<7A49wF@;Aq#qQ3XNpH{SoVE;mL>m0M3^BE06FKp54AyJasHDc9@HtQ z8MKNQt|Bm}EmyQCn5UBo7q|KHW_meLxcG$gY-4t6Uv_;Vtee7w>$|`&Z#S5@Ki?1Q8JvGV4V;UP<6&5nZMGs%jnwq$D{T zQQOQ|Y(&mE3lCP0+XL@>bfBm1aelHgk7xWYEGI#^%`D<%k@D1=zWH()akT!#MciqL zaZ6D!uX}VpIOp1yV1g1=nVB>9Ddn8mdGEZpmy3!y)>Ym;6$M5W-BRx~?S{xHr^#kj z0l*Qp4T|vT)Y--nLk5JLvxo%eL}eTkA|jobGa%YEw14KYM+AFrXD>HZ9aHjN9g%7l z01!F5+ox_ILhl^{=FIb^4*--iBITSwHRmjl8VC_RMR-xZv%+100QTvVE0;0DCM0qsx5Q2oUac*=BsJ$ zWpL*7J0W<4P0AyHG&v(B+lDwNK=eL{YRX&^=0bGNkK>@z+F%w@pkV~iaU9!ryV>6u zn;HaEjmM}dj{wlL8&P#WgKEwx#^^&7$-+#|JLmhZQ&2NmxVgP0L{DIupq7IeV&hz} zdle%CKy0_(`@VligvgR3=j`s2Rm}5#}?a+3b;MbMxBA=Iej-_ZJ1Qf|X~03@|b?mz>2?4>awf zO>&d^6LH?F%efF^@Zuez!Qq8Orc>&kuD!`>F45%BU2&kWtXL#KAQuoR4M!EpV?S#w zrU@-c&dkYG?tdlH!MUKS%n1>lBj>&Map?P$#+2FS42Up}Jt6uvI6sZl^>Rn34@C=V z|4ulfloCWg&?s1TDCgvSh%V+l2xs#G&RNb7P)PoW(>^3!y_|S?cKLa-AB8s@oQcE001BWNkl*TR4gPcqye+^50`$W%bp83uPpXwR1GFvvmAy_RF{}rgkM#y213LXCoCZtQ0-$>b%|L-gLf%&%F=hPeZUal zIxo&)CmsPBdeLq57*l3e!lizUVU>Is7tG#onWvkJ?>UL+^*RUdf_E_`%b-wzZp}1C zgqX5d=zB&)=Q~Z&p75I>Lc8+s-W`~Ep00cD?mgqK0zqZt==#Aqk3?v&sR{_J(JNE| zQbQWhksSlY-yrlvre4*wESYoHb)3_DeNk1($s{qHlhGEu56q^)D!dq14nkZh)Upm_ z6#>mYH^<1P9l}zP+ z!^w=3);v@|q^>^*W&p@Ji9{PSnUx)LF5MfbG6SFw;ep?q9T+*OiVuC|&8^pXcc;4X z0?D|Y|E}~t>F2#&2H?rVjg1Obn{>VB{CHU zR~TULi&BgdRc5GuiY5;eCLaLFhn}2^^F>uwBVujACsD~ckqevYwh4W1Pnxy!Ee7+e zDx5Y_|Gm(n<@eW_XG5&G!^#1^#k;Mb+xV+7) z)P%>P0;0eTKzA?Dh9(IewFISC)}dCb3quR{%zK0#!TR?2zu!z%+bC_>;ufh$gICgx ztg!Z~N^Z2MP_vuW9=<|Qb{MSr7-BcRq(Bg29h29ApT$rlgI+%Q$u z0^<71`Rtq@#&M5oX66KdKDdCc?i(S{w?~6kdVB8>^>}(}4D!)rkL&xZh@`wr7k3W( zK7c|>Mc40$sz{@GXGn>OOz#hU7tH)HrZ5|#xA!1CK z5Y4Qa5U~%`PQwYxc;6rEM>+9DqBH~=}-^`gm zeg1-oV;^FiGhc>b7{`%WQnE6(JQ4O=Q!8&|>d90AaGJ&_anxsJQueg9)xuFG@|-RMJa&ZRld7L8)3Y~9FK&f~7m z_1yrge<`^@&UM2f=luEeza9=BzW?!0;&e^R)spATE-R&3IRDvy@RxC!KL7N4)8u5) zn2IBQ7qTa;)4t$+T&}B!(JIVz-W+t_It9y~9y)9CZ1;4&_x%vBuPW-WKyQXXl=6ZI z(Yertel(1foC9!&Q@Gb%8BfPKA7G5jw9Mzj=^Y~FxQIvyiU?_$Y)^7NxX{hl%XGaG zp(8X+%g_e|I6Xh*lwMz75$U@hez=^^={h?{A-E;xl)0|le*%I0?LXuk=j*GTb$xKE zdOg1&z-39pF#hI;KSk8*%ja=CJUzdEeR+9#`HIey?+?dqx;$N99XW6A$08iBAAkSX ztIotDQjaGrwr3@PFvSTF`{4-NNr*YkIn8$LagGQwPp>sBwfW3bUf~=&uF^7bid`^c zIxs$4H$vH2M58$BJbSg<+G~xX+)&wAO0+- zIG;ZQ;PCVzFH>4BIVWqf5plX+0n}7#9^WJ=;5{$(mvh&5b<;XV#5zg-6?|B13D9>Q zs?DFQH(pyV!%f%N$p7o(SUt!=YnVW*sc-D|_tcwvFH_N7s0K8OaNVm4+DHwB2lMx) zQdxi2wvB3|&#eURonU$6A#XzdR$GdXcbt2FINg7xCcL*^Gh8c5S)uuxOi|t3a`$Fk zm3zH{vA5xE?PJs4+kLK_Ze)EGXtEzf1c`PUiCubGL-$_~Nh3ySy$8Dg*L!Klozfh3 z28CK17XWbWL%Pp9$6uWPS625gkp^(5JkdAxIge=yH)k9+f7%{ zy{p>eC+na4Yt=%*&3fOVtBo5*^K~A(rZru3O{c*s+o?zdHsH#`z43wc{!Wrn{nhTM ze7ciQ>^v9ie;eGS?LBFCux~s?&Bxt!S-VH~R-IA6F3G7R<9JgJ7%rgSBHc7MUU!(_ z&bzL$OTis2^WoxXgeDK%K%3U^w)5S6HEk6z_s860#~o&2R`2Q8b6c2|S-ivcBopB@ zUjV?;%VNwnDRd5TVWg_Q>Vfgy>tE!$(C+|y;v@NLl`r^aT^(7pUd?4q|jH=34 zML5nEy9GXUp&L`2r|au*eC~$h`vwLK;o^K44o?7(R))8s+sCI4)_BDsFT&gp$L3*H zlkr~8FX!{CwWOPr5b^xwC!_TP=u$}G^{8ga$$O_N)A_T4_QMI*Nnr)+4Idm1&q$7Q z0#N5X5KXV2o$va?699bv$G=sPoT4g=a0o+TRUi$Aqx0SG{`&vHl6FL9XggnCR7IJ6 z*OLp*cL2IfXU^&A!*58v?*`5pzP>Kg6eeIP6`=Fp|;3ln4RhVi>U`4^yidHKXSUe8~A=stY-V03|@4~RI72O{dn zql$#CGjaOU^Yig|v`d#?zUKMz^>rqq@mYRN9^qS1YAs*pC4GLGo}W+SFbv~XqJ?k) zfUiIQz3CQ^oDW3^p`5BoLRw}P9uH3%vm^dTB^?Pdj7JKqRIIn z!eR+LWk>1|ua==!oZ?rvMI?)CllI#Uhi61m$*TJF{9c4pTvX+JiNi1)k4Mf)IOmu$ zb9;C^zk82Jt{VU}&DShxo+figGrt;0p zvRp4^8i{}q|MUO)zYYE2|M*}2hcAEpySQ8{wlR!PDMr$mabTh|{~_;@vXS`y2hJ ziM+8WswTEKjaxf9LVR4NuW9e)eyBduO+odtsD=RF)NViCRLB75eX9G;N_*Yzu@T+Z zkG~p-!_A+YP|C~?X=Mh%jcH_IIqKaH6x}KnyA--UoMqN^*PK~PSF~{|=ClW!@5LKs zK|>w*hMnQBoUqhH0)$FUN3 zGtZhvxLt5+rmrH02#~OW^y2S|q`{8K$LHF0uhn|SyG8vl@R?{^?5|xKplySLM z^R|>;i68{uiY7xC0U_t8B@NMyhY?h-*UNtHm^ddB=J&%$M5gYn-fZoLp&Lc_59@ze~r$WuN44hE=$5WH(y`slVKBJ=R;bi6sK-Dg$_9_6+kmJu9Xp8 zHv*zE=bWcGA{a3|(*Y14MG6L%{L$VY;5be*Nq{c}J=uoLU#s%lXy3tt+^jGv|B-xE@aLhQl#V zmpb!5y!&1_&*!hI${bsYQ_eBxNE86!dVW#RIWnREfOConABMwIii?T*<7|lTBw`3rlmN62y;dxa3DD;r#U7O@gafAI0R5wVzvz_ zgvzNiGM>2@vn^20NdY(|7M_StOSU9)L%RDa@A~_z8 z0C4{Lvx@jI)J1U^yWpKLm#=U2MTv7lb2mmr1E9=atA#N%ryCntQ#!RmH5<^9^GHtP zvSW>{FLut=gfHP7LI@#TE*Aheo=(AgRYAhb*Pm7OdVZ}>h;W``T4Ek7QPMf@!|(p# z??MQt;{g%lJmq9c_JUzPKMnTr;`JrZmx4~@1c)K@c1BeR<68q4Rhh1r5W24GP5;h0 z#zhPYD$K_IV9Y>OP0KaTSANlyG9sSOm-FR%Jah;+%`r23--~ccOhkY2AN`euZ|7ys zX%P|7TXris*A1r<_@zz(e1E`=2Z*X#;#BPkR|Q1h4V)9pQg*rF;DgP@fixINGN(A5 zFQD3a=bckkyLZ0Bn~};gpAm`TvO+xkFz^RdLB)52io|6Cgb+rPU6Larr^+TIT2KAL z0Ty9-~ZWPeg5O$U?FhYaS)Eq-P*y_cmP)u8R`A| zcg&e{bl%y%!8x17n(cM1)*{8|{Kn30oP9711Cm>=FD>9KoPpVQeSdgL^VI_Gi&BeX zD;AwDm#W8Glg|NQHeM_G-q+(6Tl?ULV0WqPu!6kncnTjTiR`&aCN+F8p=v9MN-4Y@ zIhAH*gYRpx_DHO{Nz}2?Ag+aih-9O}YAft4bA)!xCYW z_u@^zv?o#NP346*Kzd_3RqGuC+}1Sp$EyuPAfZZGeT1(A{7)BxcegOZv_-f z3Qs#|tvww+K;(ul9j?1in{%u2PLjR4*ZT68Vb z+evOS7gfDexXCKru?7KEuo7->=s68_x^-Z_85I|ks^;U}KW}%wcDNrcC;&a`2RHBU z+wpL7g^MDxY!z!Pw%(;&**=joH$*{M|8JdZY*(s)XR2a3aN+_I7RlP?@$vW|`~G~>;# zR`klQ#Y$@4n5w!)OO6lx(y-Y5-|*q_TP%w;z^=G_?8vTqx2@I}??U1L5$E$)AbNiP z19@Kq6Sm7vzcTicR8cm2HeF?ow_1zs`NoGH{>DqccY)M(9HT0{RV2GP@or;p*LaR#4FU=S?`30fuFTATTEjQn6xMJ&asgDUZ&~}@nRCiwx+`nx>~ay|-n0arBT&gHw%@U= zYTs<>A^?#1iU^0}$yJk zEX>?_Xa5bVX_?V^W6vtcI(yF*mLPIQxLA7v;ha|MOG3m|oTnmeiL3@x5IJ)J7tRW1 z=ZW5t;LbcSc&7>}Gh%kRuc$2`AU00 z0A$hj2qQ-Zg(HFwog;r^pHWCXvH{wrK!-Jkr99PGUtC-@ImO*v&@^Y|d#Q3>@k9WC zWxf(Q-<5b+kYcY&@49+=k`MUKYb$w5WIY$$dS>}83&tnnQ z)6+Xyl@FK8CHTBC&YRM zr21v~(3v&I%HuLYJx5qj8k{Qj*1*!ZXJiR!lp_h-_&>h<(V~ipa_J*CtPBlHZbL5DuhGoo1=#6$^ zQQF*)eQ#vKt!=p-lfnXK$?yvm0lrnk7-Capm4xHeP99V_&gA^z_*ACNM2Hl+ zPF3R)4byItZ|^%*F#&8c@{tN6_^wxxc{<~!VWM^>%OWYuaSSZVEDDh0?E8^?SWRF| z?;mRukIofJ$l4QdPU}lcURbGnRFIqjYX*1QULe9CtmMcnajB&^f_J2<(~^nMXLK%D z%sLXT;&jx8OM=3|?~?zBR^<;`UZacCnVeryWl#lH?U1}9bCYQ+P$H)y3<7}OcTFcz z-`@d%Xtq>!MFhyJ3e+KyK*qHXpmGorAnG!K^UnFU-9#b;lANl!hW*vDEZ&FE4~W1e zs+NfylG7Y>UW~+HC4vZ(BMYqP`ax7A+bL}K zM5tU612CNi^u#$cM+m(qC!AElk-zC#yRH|>IYn!-$vNk{xLj3qNtrXh`~Ek`*(%F< zNzR47ADDCS9J+ygF!&wM7uD#xo^$eh9KG+I?{ZpljvX8j(FFu>oEHG>`(9P!!mS6U zx}8s$DtL=V;aHC9LZQmMZf>Sz?>kRqNyV<~M*!s%O@mh6Swxv#=l~JGtsDharTxxN zL@sAumiU|J56=7f{58#&looO>gnmcx7BLf1FlZMyzmDQX0BT0He)X5BZ2;J@q&m;D z_uj0mLN}}`JG|-Cb6Qlz`A%3inP0UX?-clCJQ;!&G164oEIefS$j7#IOggpsjzVJ$9tjb5u99H{qR zK&`oMi#!!xE&?F|Y2z7LyN;EmQ#YCQpNhyD)qro13OCq#JCNGp06sQy^~cl6RJ!X& z6k#dZQ9d}=#pO~XDcbLuGTTQqe2-aK7|g_5?$;!kYNGwK(2Xm5l~>t&d2X06K&P9r%_KD>VYayfrFj6D&CZg9^3;UE9#oa;lfCN%`t1>b5~tYPB3WYr#zhy+y0 zt->kh9CM0YKUS|lv;Hc0^*z3i80Tx6FNde^kf<9Eh{(*sdA_~?z%V|EWX{?7Kt4#0 zIi=xvLPXA-9bTsB9GPx`ImygvnL^k5e&iG-&6U<~mUxZX!tGGOxnTC8L=M1NQ8}L8 z1L%AyRsi02)~X`H5}AdkIV!+u=%Dc;Se?y@T(G+drHMgM_5GoqBiAL3eHe#Ogg|~n zW;idLf1!#%#OZpm1eG>)r%rs!NuY{EWU6 zW)SFtArW0S0zg_O79I{yEq9v8Qy01(PU{{Tx)A{mp(FCIpZ@@>u-YEHWxgOf>w3NK zmg!ZQRTvRDEr1yM1F6s)ocBbIoJVv-W{;Xzq#Bp`0);pVDP9fK_n{lcqpGCo?0sKJ z#nbiGId9seHlaSJ7`na>r)9Z-N?ZUy`{Bv1hN`B-h#mswoa3^LQDz;Mk;e<%O z8vrz?NUj)+)ve#2hqTPab)9)$zCz<|Rz~>3ENp)$hW&Outd+ilZWCMyhv1#V>zAKu zT$*{ZU#Az)G6P10emIOr(_p}S{kpSKA{V*=K;v@FDb3Stin!4AT^QnWQGmngNa&XN z?3}mZ^!4SV^PLMF=fpXi-N)0rA8U-pPk;P95&5+wV$L}&R=oPqSD3^Rf_HJbAiB`? z0Gbjz=R$DAN{Ei`a$XDHx9On}e^K(QZ;Wm6SLh$0O_aVBY3%gLzm{YD?Y{FyWN}YJ zH~5{P;bmZ@zO)tbMkA`!4&8n2GM}#0O2p@DZ)-UgWchPww;v_jYSdrF|z(*di_Q zhF6Ar(m}mKxcgMM(e%Z$d%dcAo%kc^#!aVypqk=r<~9#J7B^iw-UWi*O0ZWOCfr%( zwKDb^D7dl)R$od4pq7VUHb9X!)X<0~xcLm+i&nIa6RiE;+IO~&VcOUgnDlVBruOll z?X7Rg<~PO^dQbRzvsVn?VS!Fv@&zuDj#Ft-}$#T$N+T7(f2}ld6urUv2h+_dcamjk9B7 z7CDZ6B~sPr!8vk-HaoO(-d=ndy2fk2oG~eL$~+FC@BGVoR)s!zBHW+KkXd6YNgcfj z7Z3qpNts2D>rFwV)6-L2mU-{8U05V3GwX2(+6)DSHL*SX>KxKed#7FSqIVTYb!vU&qoT|N8 zI16X;!8xCnsd4V#LJ2HWu+R{QmifBOvniUK3q{_@|#g z9>(D?4k@LSl0B&NJgaKVTy3C=#1rv2j!#cVAWuZY;kg?R%k{#XKmGKFWuE@zw|~AS zG?mmqB8tm3&X?o!_ru|Nx_oV;;l1z1=MMnDIiFv?{`}J)-o5|u{O$wiC}o<6{y3QHW^VS*RcVWZ0rgK=D#9Q4QJQe`bKrO#DK77rCs<*WV+vgzudkIBv3Ai^c zsg~+YQK5-1ETd6{H7RTD1Fc8FMtge`q>MEf9_t|WP9+U*n3)wBEo}LFmNT#ulEZGC z))tesE?*lQ*!@2?ke@9UOVT3J1c>=mgjxXxNjD9XCPj}ZtjxAO*2k}w}$)e9KM}yZf5k&JbN=^ z+pWzzoaj#I+)Sg^@nl`#tC)Rr`feZT9g?AU8`sXI4cn&;8&`eN#&4}`1$fhj@3RNX zGPyxz)~iunvYRonwkj!Y7N$PTa74sk?P-1^(b1b3p5AH<-e&*bvoT7ai}$FL-51zh z7TDZ1ko1>3m+A_q4cJifPU{k{rjIxOdUHEyC1?1pvjhLtzx=P-fBi}C?FgIbdAyG;6j5s#SE;_Ud&VqvTJr`lg`pdSSvc7Y ztm}Fog5mGXA|l7rQ+-0oxs>8OO-6M5@ZArmckf?6{$5s<#pkc*5W@5GGXPv(zk2Vz zr<6G*9>+sJ46iR=L?mZnksp8fPFQkY0I*v}fK8?@e*E-VRo^{7hpv11@+pMw`21c) zKK}g25G?VBV`A%S){anA)h461_(B-V)yT<+tg0|CNkI=o@0_JukPm}`#`)rWSLcGp z1~mEVbp9+kVGP}&8;@Up`rYf7 zpWc1=k%&y%;hY!Y6lc?J6L~YGbIyruv9Vu1e~vN!>2Lq6nu;#hvspkfXU@qvPtKWF z+;Dg@kbs=;$CIjFUp}T7r|b1_dLB11y;&-1b@wIhTk9Zf}J&Hy-c z)=cZ+>HXp9U79aB&h51S@a_lUl;#OkilTtXx{V@q)1Au7sIID-(cM9zhPey|=9(&gYb6j=2l2^W?kUyDlzQ1@*o|baAwOrA96Db@q(uN!s`wpS4g}{MoeR$SwhJ^GV3T=NbY;BRD6S;~ zDCb-+vI&{2D`;_anWr<6GpCUpC-T9$Ae?y1tlw5j*B?|QXA7hh zs?`jk?RAIa2@&Uc5@!DhAbvbFx|c9-5IIs~5&LUexK;_UX_rN0ZJBnG;(PzLO)NpA zDkz(I?oE*Ijo`0_2}@C}HKnmu>4<}kLs*Ishxe`-M>?|os75)oN= zYcMXNnO2Zk_LAjwturZmIT1F}hGHhCS_6`dGe&D{kgh5^J6C803@wgaRj9ZJ06FqL zNKTls2AQH*%RsHW?sfnuw)1>dA?Fc5$bka62H*q$1OXsRX?J9|QIKkQ)<)-hgZn3{ z!eXg?JJrP9Y{t}Vh@khK>wTfVcNx~Z(4E_Vf^RCF$vL(JCBzbDwB|=bNjC5*EXu2n zXzMD>Ns^h@dt^_fDdlyKL+XZ|s7~iEP%bROTh;O1)W5#lx?QX~6C_})YL@EO=qTKgA>Rlv&_^@low3}_puG-F;dVNQ)ie^?e7DWTrv4CW26Y?K z1Z{`DX0bIxp8W@1qpx<@V2dF&y>dwdH0QiKM+IoL#Gu83WEY& z=X8IxnTtr@_qNzogdy4%U}4|`&s~QMnvs|=~v^TMX*WEdvfHY)diY9 zGH(g*K;#g>d(UFR&FTCV!f>bxIe48!WS%C|ux1t#%*>*?EQ?XEWaVei^SsJsKy1QZk-x?R1^9tV;wW7j4Zm%Mx=4p$nnpX3#BB z$a_=z3uk7|)=Zco6*DulouNo2#FB%A?J=nGQ!c^iu-UgDBF9CI7_F+xq7Dm9jzv^6R2L}WJe=MmKwKtJbzM(( z!E;W_RLn}GL~`5xC8X*^T-HByni8X z&ssETjq}6dgsTfV=fyNZ$~g-oBBBEY1tD^(CB#uhkbuaEu&Ts)64jg{0GysbxX{J< z0t!e@!D@d=aa#Qi9AckxQ3S5Lc9nv&o$)y*D-?ovq3aM)g;gLe3#D27mf%C zoC}5DsAB)U$-){6y2ZpBX)wiW&NJt<tZ=2(91O~JLj!=M5lYmf);fSiFlX=4J7-=!wNhS3*Q%0B(}D%N z&zy?m$*M&)6)mhv^rlY_!0^^VSijV-54&iT?8)*7>24lrl%t(>ssjM<-e;ELk+@9X z|LI>8{EbNU_aaj170ki_rooIc=A3vfm=STF=T?bts_Nhz4aMZ`!kP0f^5q+oqbb)3^u z*MNwiFo`okm@V}X9HQEz{L~Gc(=uHEq3aL!y_i#4lMYu)ni710RBT$)GCAjv9Bu1E ziJStY6jPiJr?k~)!dB+2CI*0rDMmBbLtnH}x?4V({MKQ8lJ;m58oH13@9JkN+U zjE8xiQjDBqoG#{0Voas33xqhGKO;~bE9?@O?^aBVIrRO(y)y$aRgsjfr7(9lS`QVd zpbjE}GPCVIs3I(JSyEauD-yj6eLo(=07fEE&1Nr@7Uw$WgY(`a&dZ{zYg1nB7@-ny z0FYS;5gm11j|g#|MJ2|?2y4}R*lIpj?Spg9Y@UEQDYJ839d6lSP``WMb!3VQfV5m? z^(YQqZ+nP$)OX(IJ6dX~sH&McX9+ngAm(aKIST-Wt}_T-*K~+}I5-#P>C$uvy>LpFZg@inwY0dBE^C%IY~Co+ z6kd)@`CP-li++Q}Tzi~VfvO_HjzVq19;6`LM|tggPFZ!brn#`YW8t!O!@TKIP2HP| z6v~3Rag{cCKy+a!KD3({x-i8GIOKzhO!Fl(2S=)cnA+~oL{`G0lCe=_wL8Ca#4MS$ zLuc_9)wRI;P~;PDHCu1|VH*mjkATnn&V9=&Yv4h+Aq4)DSfDrmaQ|p-N)Wv>v@`{A z0S^q=TemPpFtX*kC7EWHN_kayOjIA&f(Wf>q*08Ju!?eR`y~TwMQT&uc!lboZc`Em z8f|{XLj;O>8?>nr72qfsS@8`L&^GGp7C?9?v@pLuC`B9#v-iF&j2ba-_4j*xYi=aL z-}Xdkzbf3so>*#j*$t~4UK@klU0~z(d?K!aLmRiHge7dO9sI`AwJY}VhLMd8grhaG z10RST5V7PnHZ*_TeR5bs9O{FGcXF2-3q}RA@U9SCxpg8UiYQR^;3!p!0ZmwO!;Ate z?Tef9n)0Z{L={98S02qazYsBp9s7bTLa4M(8CLHFsl+Z^t&`fE5Gvdm+6n#3Jfh{? zS0@L(rLBvYvG+n|UuMs6F}PSgkXMY|Ts`bQz-`n;vu!rM!#9xe4Mocw4Q=+a5#JDZ zqOB4}kJX*(E@pH0&~NvGTB)5CRj`W;)m^XynpmV^9Nrw0M$>|_y0=lA?v+0J3+a|S z9m^Zb*)9XyD%nl+k*RSKy4ZSx~ZZ{ms`RV-G`EEEoi^%0Nb)D~mxAa7B8TJaM1V@0-jZ`oY z?D`{fT$ZaRd_E4L>zxmHHNDhQqr#UeD*(uJc`R%$hSJ`7)}5+oQ_| zKa4%Dqd1%TXwIL0{&}9KfAJUpVde3SedvdA7!RtNQw&|#^+Q^&Z3#lO86XH}$;oxS z?*>>sMIT}h&IRu}-wnkMKsKMh&>x)h=dVB4woiqXQwScE<8t+(cP>~tS*7~5BUC6Y zW6n{QDfFWYU5<;YIs)u&<^1G!1`etag2QGJ6Vc|PXK71vN=;l!-<#h@ab&2h>* z0?_I5rC38K$9Odwch`AaiL9KG7;4yBPqh9Cwn)8qgpgTvSzbT=0m>O>%W9LU41EUx zF%|Tc5S=G`kk*w_3|aw7=R3WAnqNO1-~X6%jMG^~=4B~8@qA60+dbvwdeO`XWykY$`JuEHvkBdMxWC30AX@yH@&1dSN_5fO8WmQ13m%*m=HquQyp1Bigd zPSOhhet5E=R1I#-MmHUp%7Gg<`zjV1}j_XRN%W}Y2Ap~8*|Rqj=xrD8xy@P zX12&etwM$-482XiP~2$*Zpi{047DkR8`e7R6{d#u@4E1}%PGBef`>McyrEz0vKih; zy}L16__i`;i(l7USmrilq3sXgUTX}yE*T$q73^Bh2g>g^KA`@R{CzWeyMZzE&;c)oS7u!?pHHEF&3js3^I$-e*1?pZ2@yw-4bo^o=Z~8WENrabr5P?Xo^{ zX1GC>DmO!S5{rtKv>Kuv4@lQwK+!i?{ss8a2T3uwH)?1YRj4~3hC9%rRn+Wt<=AM@ zv{~kx5*!eUXWix?(SmEOKf_}VQ6mj{0ASt=@86hseG8u1NoH<`i1_CIu_Ly$4H~q2 z<2SV#H|SLRDA!e{-)3FDtsdE;cvLIF2XN=T;X`mW?Y)Y5EDpXJ+bDqfMvli&(N%Ju zbINgUM;bN>6_5&5Wwtuk*$B;vI3i|ck<0nDP(@UU5D?scNNDhks1n||16;nnfnCn$ z7KXLDKt%rj@Bi*F4#&f&DYbC6nq}0w(48-W=p5&?Oo(_Ki;vpc2P0ykhu9@c%k?@< zudnBE2p^sg(;Pp2z5Mw7cg9831~Er~)3H~D7@6-{;hfpNAdAG5RrU4qQwXkG^(P`1 zS}rLG06Hg*=x_h#uY>o;Lx+f$*UyM}7(3q$A@nMWsGmRnq#}JERxG;AX+m(EGv{Pa zX$ZaZAB8eeh&;!6^=|~u(P~On z&C3NH0SrVAd~l&d01LC^xG<*UyB}1Tb5s#?;j*F_k-QH!p;T35BGN*zwzxh-=EQNb zV2~82v|R0Yi!qDvK^XoiXvCU=30>!nlg(^osT*Tb2H@5p(?$x_;x6%m+qnv*S6B6PGnXt@k`ja}j%k1qgx=t9>o^TpOOk;`!c z)&BSdB1o^!cg}}po|gG~czQREr!OD>QN-j-uuQM$oGGB0zxG`}j0c5@S?n?E`U3#1 z%AY8rF=j*zowALUghklW-pk8`0brRfCDj43?+?P9;}T<9Vtn`A^Wo`zoG$=yc>dsA zc>VMTqXb(8dwPEN<8R+_j-0a#!MU(Zuk~mk=S6s#&X&DumVu|P58ZHi{rLa>;jf=R zd{0Pmxp24W)LFf$^~*VoVgIBoDP()INdBIf*Lrs^>+zx&(&&pG$~kAE8DHBRRc z2Hy?9SxO5bFQ5M492zcaw8nSuKiJ`xW#Jrs*N1Mj(?obTA4Q}vj5#f7nO3sfM(mH% zMTA3{v{h@s#LHy*kj%;Elm=R;s_%yC#1<^cLB#faB|`B=q_Rm~>FMXoYSzj*Eji7q zMe1%ZzFR2A!0-tItp{6>lJV4&Fk5w>;27OQ)I z;=?~nXb-n8-n+TNU6FX>g0{A>us817$r-UtvTn*@ggYrIHYPwfrO|y|v-v}vbnMN+83{NXnSK=wYEN6&$ROu|AmqkZ+hgN zAKW%0#rlzMuJA+mKD-HixA;j_qcW>Bm`4fLwCP)kx@>H;Zhx)FhYcm$Wxk7he9#l? zL*tF@OX3b1SSF5WJMnSy{ft`9Akur_&h!K|u!8~)jX zz4uSwlsu0UO`$O}(?@;-x;bL#V|wH5^VFId-mnS)9(cTMoCJKl9hXO6+9B@kU+$)F z)oSj6ea9+YYXcu2wx64o&F)RAuC9IXw&jM+=v42Q+s%gMb7n+Qom%BtwOThqiDeTj zsLM$Ul?!r~m3zE$z*s`l57@XRgze{dg>+m!kr4nwpqqz3XE7VF$HoD_!joV;9NW8G z0-iwMJ&oQ6A37v*j%?u1tiqC60d(ktaDM&rNmZw1>4NXOQY*|c$CyvY9uZ?=W*J7z z8Rn(Tv*>_>W00IgvV{+JhUNNN_uDvM%}#73>20*;uJ4Jw)x3{HI~+nd zo(`Oo(Q(aE4p!s3YU2Pv{cz%(a*kRuIk-yDOynCAQ@JUcvozu|mr~?;w#jjQ6gS9( zrIGPzrC;t|qZ*ftNL@d!={c;zmpRQboeqJBd_RV+|NFoBcOitQrxPLe$LFf%bk2F_ zIH$wmSh4C#5kSOo2;IH<0t6fBL=i{`B-75Y)QBF%$zcS+^R* zZa5N=8b*uKnG3OlPMOByS>|Ai6gH3vvjOk`>7|VPia@J8waqmS}W38>w8^+PP?Si&KIs+ci-ZrCo4Es{jCML{J}k zRavI9_nq^>sw0a+ZUOJEA4S+MWTR053^0LSr&L~*%@K;ndmhtM-8&WT)b z&Ks&>5BM_A%#3)wFRPeE1Pqe&eiIz~8~O}_?qO>MMcpP{QvXs!5D6SU>I81IjrRvV zz6Cz3;?DjX@Sola)+XwvY0%=DzV#J&Gs~;$*;W+1iD>F;WIr5S12YMctFKuT#|--{ zc)f8{t99zi$!aY|8yfCo=9DYYtJbd6q|X~YZ?zP7;L59TQ^c)v4ujp?%42#EURdQZ z_YU8(m1SAzb|sAwhHLZi&7)a^Q5aBV1+nxYzEW#iJm)Za|M z?){(Fe6G9xx%PraGM2l%vbOkaJ*n?9=UdXNu_d*2(km7Ry4Jq<2I01`C&LG2`hEPQ zu5=ECP%|)c&aQ;omA+;rN}3sAkuBa3WA_1Mby7`R2ZvPBh=>YuTQbQ&PywZ}-a|wO z$Ow2}0h<^u=VX7w%;v&V*P3k37^~+W*6&X3l*&Gru1WFC>@Yhevf{wQvIx|)$iv% zq24T$T>!MS5!J?as2q~yJR+fUfGEt)l}K*|uopXzB63|4Ip6gMQ_#DtMC?OHM4>+z z`B)JxI@tTJglsvJ?rA6DgD;jVL@Yw9+-)335y?4OU@Snc7=o72FR*@5LHoYP(#CnK zZ3%H+va0m!gVf~ro_1OUgwfs!!Q$N&H!07*naR6wWeIp@rokEbI58YSL4mc_(udN^9W&Pi7639a#LI)BF-@qq5u)O%vlv}>ZyPxPPY#C zo=cK*0w9sAg2pAXuDm6E9`~P)C@HpO)mDZJEVosSBQRwuNn~G8W;? zmXH|Z%*^w=lsF{B>$D)DOAH8}(1hWJZJ<-Pv>%4r~pWekp-ZbW*`DCk%?4w0fn4J=g9n;Q!Fe& zj?Q_|lJ*XODw5aqR0IZ0mVaw#q-~v?lVCPwi1Xn-@k5HgjUp%!Dxn1cFeg>*f(Mm( zy5^ix${~Pvuo_5-c@b=K%-0tJKvd?88!15$k(?*zC1<;wMD+f!shBw_ieMq$d=)Sq{21#dj;!Da;a6ZE17BY z)_GuFCKlpIg=v8x%tZsFoAYhW$3_5VU73x$_hCq|hC0;N!uhar@pM@htkDjHi0TMM z6j9N6XVh4e3@ZS0x<4vaZx6*f%zrpPK|pQO9BuP;n|!dwZWQ%BfazYp+58o$z9a?} z=R0F3-zU_IC^PqE_MVm5?abOu>gSP^)*I|S)wa#K&hQWx0evCoLqD1}ImJvEedwKY zp+Asw^X04Yl1)_pR+5p?I%GSCa2&^FS(asij-2b-r@0z8A)*fs%`tB$QE-Sp^QAsv zCNVZ5z}GKd$8kI!4{@32YoUgZhXWCAmQea2FtW<>=ILroeed1pk3R+PPsgzga-+#PwyyrXBiZrdtv_i&SMu$ zRU#H1SH|h{4H#HooLQE{!Bg-qE(^di$D|5<=N;m8Ud+Q15zN8TbPF+M9|SvGVipn0 zjxRUGkt(Dt0I7aW7G+T)%i&THzQ+$|9{fnZb_0PSrgJ9Gk1@O%&h9_o;hcB54*?$B5;9l$sNzb)9@xd3)~e;g`M~?JVXGMCro13YA`u$u0EJjwi3o6{ayRn?SI4f0g|km`j< z1PX}eCpS?*A`k*IH9@pEjyK^|+fB}^n*~%K0ZXhz_fgu0 z%@3((rEzcmj*`u8%t-r$FA!h+yM7y*qsvX(Q<{@<(=HyP=(b3{9pxb>IMTqFdO_jBgw*$QufSG#j4iAhjdzt;tard5R20KGw@L$@ZDEjKNvl=!) zt)H)L&V;*6_FO-M$f_$Z6hjPerQ21gWN-bg1Tz)CcsCm(qRndu-RQ0PYVGpV2@%R7 z)55c9H*t$`{+>2$$4|B!Mit)vZNyuhL)Gz_FkM=LNpzWj)Y^X1i5`2{Ylc7J)DC9gRrL_8b@$7YuEtAUM&C%v;gc3MO?9>rlg z^-6YAeSd!ofscnV=X`!&L*OEsHef^y+?WU+Le_)NA&#L`J(km=Qar0UjtF=-L;zdn z%Q&4*FF$BrC1>9+m=TOVfSrli=Yn=Tod7Vcv*h$&{MY}jNX|Lsl>Xhn{ojB1@sI!d z@BWRMfSLPDdi}M|7gK%z`ZI@Na*_qdyw1z@-K$YQC)VWxU{9wb0*p_eh!AS=D+<{|J8DS zyS{&o(=m?6`TT92&!?xszo1I~;SYc6CYNsSDXyw^!>}KJ{IT+AtTp}qyK-8V`4U3p zFua}5c}+1G08V2-#AV4uB?Xf?&`2RhkJGzoeWn!2tj|vW&l~*Z24H`TB>SzA!VG=5;WxgWf5IBhd z00&~CpPs*zuo1-L>GLvQu9tIbLjfSAGa{azUpT~RngBo~A>uHdij(9JA|9;F`@w-APLI+&f! zG-p+n@z} zV6@T$)%<{B3hZ%|9zaxJo{@-Tv`A1EAxnF1{J z2#LgTzI-#YI7~#tmZ7L7YA8b0E1=Jj2P=aHf9(K^wc)PS1M!GK|C4bHh!o-kUESyW zM}ISx`2t|$I6219@wvhNJj?FOKah|;}WwF^?-8?o=5kvFXfJ}?E?gts45e)ZFC zZ{r7YSnNg!TftU|?^>!S`+coTrRtPRW8|H~a?s zx46>wc3P?Jg)DLggYtvh@4D5a*|x}g`8kxoR)|vduG;1sco(pG_tcwMWiLGGMjm(T z?)&cAdxUV?Lw9enq20&h-RyMzuK2)c&35vT?`Q#PYc5F8n)S+Gv>to&hg>+c`ya_o;TIt~YBUgmeR;tmxDF2hXTtah3>9RQd4-H9xK zfDaOwi+@#!qsIuCeW!iw5hrlTaQ}?VY#2||(H*CemM zFOqZDs{wHoNq$@B>suJ6ae6W^pL}o_migTbOht3U--64Wi=Jd0Lm2Amby2f5OU}Bk znTe<4san~!jA+4#RXpB**JDyT$`e)j*MmLrm-3*md*! zHwvMs-#mWIxe}7y;x(t)v{Y%AZ@&<8h@%0d~wk}BDV~5C3{MOWQXoPrzGOj;?8!XkhR-p zKZ2W{pPrtdp8SJ6?Cr@6-Qmpi^7?BWr#KwPaT45-U|Zq?`Iy2covUp_$zQAs(iB_TB$4&XCt zgI)G2fT;f2OM;X&C3$*!9;bsxUZgaGN=|F7>+JRGZ*d%kVe%`a5C}q?jsPVZJ`9t& zC$(Ftg)ofcPJS>Q_i?S({MPqMn=B%67;oqc&)vy z6aXNnMO6>SXE!?pz)zpQs3gf{piY29l-8wmu_5}mKE@aKZmivEAxI)o2+6Eu9{k;Z z^WUqup&Ep6xSoGIfBiG;y=)L+7!Mqxe;SocJwn9w`qsP25QjF`47YuZ7sz;rN?R|? z-_Yfj(7boxYCcFkXZ(YXu501C3^VBd@TSPIjTd(}k942l?!Q|%0Ns_SRVS>30dBmA zoe{dN4{ZYDevF5$D)|uHwmww4FI1tsj?LDtG%yM`5d`p9W4k$QQQ@T_Zpnx{H7z3k zRh`4ulvh`M+$9=zpWakNxF?G@tL5EQ-gugowwqd)4Ig*MojadxeMWKB-oEmE3%^s& zmrPph?xJ=5`V9ly`a-zdXz)&bf`7#%96NioO0w^(?ME1jeV9_Ydk5~@`kUKe4?+$% z0Hcjk>I@XxsH{v3`$?g7Hvs#uv;EMGHx^WB+T&EX54wY!X7)~P-D{<9@RF_X@Dw)b zKBWz8fwo~+CyL)M+PxO&?*A8Q{NB^KiU-j4s8p|E$2z3k73XdI`un}w2idXRV)|&n zhdq;}wovvVh|n8Tly~6)DdM}!|E7DjM^IK%Dm?mLH&%7q4vAZrzqhl$|1}-#fgfE< zc>eT5&9F8fv2YkPr{bfEY^ras-`p5_oTlmY$!mdM{^{>k z<@EH-oh>X8etMdQX+Yu-CyT&2sib%~Arcb<(Q0g?etXCq+X|d+Gg>-!R z5zLnBTTaW%)1jKl(&6;UV;ngIs_1-(qk&B)*=$`4st2BhI}j04&WqQrW_EsmN5m}3 zL@_cLTuWLy>6}#G1A8Q!0zeFOV@DH00RV`Qh$OGq_pe+6(q@%Bo?cu~?=Dkq2&%aR zJWWq80FdU3N)E$hCV5R;T`IYh8pMc16dVZk%sEqCukYTDbcEQ#mR8Bdp%KhuQ(V{Y zw!Fw(rYRBCN}uhxEpZUhZ?Eq}^oQf~J{EP=BGvbc!8lHh%@D>zPD`54u4(aEZ}C`P z7gtswQLqsaomHqR*{4C0d@@bcV?mCipvTAOyrd*43llL>h=e7IQezBvpyh{_kcTO@ zeM+-p$0cV*=HOgYW(rnIJYoesxgoZer*nc3-?LLC0`%dbs13bQ!5&S%jIppo^uN^*gI{uJhi}hnBuz3 z*Xt#VHc<2vk%%s90)T0Z#8gt!#Oa`DoqdsSzi#D%6ig+jwQaeo!eysJK#;VyLyYzj zd#-5-!|2I$s?rFS{&Kl!q#=;1;>PiX)t{Un?uxb8E7_5li6v(M3vmS4!pmw3ii!#$ zF-KL^b)}M1wy5eb9{O_tk&AbBjas~|4G=jDs`~cpKRAoke`Gj5hw;GgU(M7cC&{jK zFADDp_TWa}qn@4`h)UpcEt-fZ0I89bpWZ%b3sdn8%Sg0X4-n8TxbK;-x|!P&7AhBh zT(S@#pwZ353m;qbPujsE?K)4%Ow@jtJgWnHz{Hkw4;tl#BncJCea}(&jmCInR$YOwT_6+(UxRp=EQ}EF`>J2Tywh_^3+LFFF5~ob0WjCbz5Q z!Nhdm5mwviuKCQXlelo}v0M&lJ<8Nmc0L8LA*%u(062(* z#LxrZAInI6H{XT!)o?*mO<9mA1Xhu}%xa1NqFTbh%_OIyjtBFYl5*u0Y>_kr;5B76 zjZBs$>kI(s-Ch@#jl}D6^>^@I3R3mX(!ezjJ%`PRVWSB9$L5@LT|9<<7{ts%h=e#1 zW0icUS%^c7Lr!bXDaL_A^aK{rWL6VW%6MOx*?DDHYn>e(VSlc>yB<{4X*2KO5SfFd z^?rpBF<==F`v&AG!KEtWP#%3FM|WH`bP&HHus)nqQ*=dhIktU~2p9-t0OL3!Q4H?Q zw(R4dh{#QT(Px~VNmQoRHFWfWy5}B)RH-7)K+J2hrZs%HBx_Xc*79j*+0!f(ic*Rm z7kU2YE~DIXSp9t3O$W9jiJ80}a^;D8tb2C3_v}Py1}Z77`gA%qfX_?=a|kSoA{ygB z98A{c49rAkM##QB1`Z((y;t&aI3N`kdsA*%`Qk$LD8svm64!3mZKotm#27im7y>hS zUlQVoL@%E{qx*=NUM|;R7{+N*5tST`&$JwiW{dYf&v&b0m3*P>NW^wLPUpy3nhh!ISw2L z#HW%YUsFG!CXD)gnnNrpMI~Hn0D~GT&VaySsO+=jHl7zkhZ2xM4blVYYm*IFdm)^TJEC}2j)P` z#K9lUbo%7HYk$^Ts;h4Zs?H2|Jc&5~J6~g%FRz_WUwcW0k0({c!?!(W3X$BtPV)u! z94IxZCM{y7;U){v!>czAR*@e;IU2F(qzbLpO4zKgcLgwMdsEpo%i^fvw|6im^kpO> z-VHer2yZ-WJ_@&cNU3rtUq#g1)*&KtVSWR+6TGKBo2ulMI0VPy(rQrcCu=X~X?E}L z?>Xl$U%sfwx?T}+I=*ZJTPwxEynK6jsT&_s)zp>anAYoVN=XzeW>}HEye#uH9l|h- zLk55tCnVxwGF2%P_#DS^oKEX3n_tjfidlnI6OOqIj5&%%DrPpFh=`nW;$E-KF47&mdYgO?FZ8YCuEO1hDE5GdB@NjlW|~*~9a64CMAlh# z^n{UewwZy5)w1gTAS6Wa@WPV9RP{)Ym}2G{^HyLp2iLHx7F%=E?I2Xir>7H^v_J3% z1THtsX_}^CoO~O)nd6#4N;$?bPSd(9>$>>&JsuA|j!KP!tAe;?e%Qme0}+Axg!&G<@7b$HtBgaA3rP+HG|36|=b#e?u9LTuc<@o+LTq~O;)98TlmdAYu&Ww!(aF^70~`i#Vf)2H+6FY3P2BGc*R z@cbpOSD#*)+41EERY}Y2{$E_q<47Uqb;)V*&yh5n>2f{${tSQ=f=ZUOa)`u1C8+?1 zO{uk9UaO~A2`t=3Hfhc4QtrmUNQ`+!BJXO}`GR}X08<6e#E=YT;luI%9&7r}aNF!7 z?*PQ_^K`qMfg7&vKZhj#JK6xis>W?QlfQ1Y%4@u6yV0=s1fUx_Z=;GB-0cq!Y4n?I zREM?^;Z0C|ff2AHnpf6Ft@!$#!%@Wgq<#D7H6e|GP4<9zZO}~d`|K)g9zgh*v$1yy zuq__qW1Gf~gbw%dAb3OIz6A_7eqIj}?Gr|t zZ+M8PXb%}FcT!>^1T)%D+3j0Z{d#Ghdix%tKHLBieNsgLP?HSw_AXVl7&p;4S{-~C z7`W+(?c6tA9`Tr+gH7@M*Qlg#q&!H>uK29gdS}nrF1K?Ys8~pWD*A-cP5@pkk3l=& z!W#vL*nDlcCU~DJS{N1R&a@jzu=D10sfh0w_%MoOqr5d!lJ-V-;T^Sy+{NoOK~Nha zm9qFD!{q_!T8$Bk`)kQxv>q&N*JSqb7HwN=QIYJ%E4;TDGjk5%Rx&o=|MujtM>3D{ z7^|r;)>ybk$J#CfDmUlWC!*B8-=(Hi6}TZfAZOk&@2F@SL)@SR^J1523EPcO6TKI6 z6eu$%U(J$JPAgZ|^7aCA^cigrs5W(HZxHG&IXFxBE;-X{gj-|N{Y!ZB?_NGQ7p51P zzC0bgLrv?v%Q>;voJ66{!#OX*PW=2RHqIv@-StN%zww-gH=QxbR z;e<|buTf{c00sakFmceF%v7rRWRC#*8d=tbh=%dNanSYztMJPzEN@y1XvFG!_m(Bk zYeK~5m%-DkISe6A&JvXz%uGd0<@oZ0iKKNg({;Hr^EjQ}&*%5wzA+O5juY&{RGZtf zS8@^^I^`UgaTq8BNeRHbB^uMxbT}T? zp_=!|LH`l~B22Zh9S%>2=P!;p&F62+^<1n_;=ml1>zO%l9NU0#%NZqNj&V5b)o~s= zZ!xmB;LPL_timoq91l;#(c|va3=D?p2t-tux@%^f$ZnF&ERKhQCz&~Q3oCu24p7Vt zB&|lGdFiVY$$7cFaU7@PvzevkDrs>$7-(**nEu$YFpM1H{QlKUJA|Nmn9NsahasTRZsdj@gyQ?VNEa5sJ~c#U zHg~7O>G(n%uIFzE zrxQ?a^uJ{UQ23_(@n0D((B*o;Z9?E?s#V-EY~#Xjv4vamSG|(^{4%_$g1XDZ=5$p! zD_ez8Ujk^QRUNn7ayf1p6gx6`cP{N*wmiv#D#ru2mIHSoXM1AK&IGBk+i?>qKo=F* z5v%>ySWn59P48@b^RkEbOZ!-a{=_XdYrPHHM)^nDnWJ^RIo<_oBW_l255pfGgi}09 zi^MyHaVr^H>Wlk|0<{ygNPr&1%I{itr<=Fmty_-4E}stXWhVgr-F+-{wk_syOVe!K zOwXk%XS1p8-M(4d@c;lI07*naRM>ix$6X*p$A<4z;n=8f{kp2`BcS?@``G5K!?_VDGA=PyeS)JeS1zKe{7$C+tIDx#Uv-h1@H!iZg z%*gBo?CyBKnGQHoyq}Ozh(saH?;dA$vp_jSzl_=o1|m*rt?@dj)%{jf|MHiTndg4H zYm$_U<)Cw>Q+AqfVe!O3F;YsJsxxo>7X+|R&j(dq*4z}>Epa|D6GD=bfq*q<#KXkf zhxF!2F?cv)v(bX;Y=A_-M53muZXH`f#+eae7(y1kTowcH4{2D<5IIJAeVYy7)2Ejh z!rsFZ%~Yk3MBd)cm+R#)4v4TM5z)^thb9SqJFor5Jq{t1_$OG_EUHMvh{MM=3vkW@4(yOh_d^vKuy+S6H%}@u_4}IiKI>>(#mb zW8}76>zd8XS6#n`U6#;{I7C$yVjv{?@eh9+htaPv%@+XV zIP~%fH?_FgeCk%P-LC89a=D!Q)ie%)34eRNY$IXO*l8g`sL4VGm$?`jG>hEBSb|dB z|s^LVL)PU=_D8zMe^{^JIv znt?}Q_~Lhq?X)71;}Fil)U;BF#KCEC>H6+Y2(8F)oIrB&x#k8ni^TEZ^N~i=u3WKw zA>j4}9HAO0hJR+CwsS2re2hNdFkkM|>L2!P-}UUVTTP@rPyp~i55I%o&nmW36A>Sd zIX7G0&2$aAU^wig@x{oeYh7*`y0)20wK<60HP2hwa62Eo$@K;-oc;SiqlePs{cy`3 zYm|4fWZ3zMdre|3D8zQbinV4jMTIWU-p$o)v!vR-<30hRoNx7TZl)@vfh+k5nM` zT@0xYmU`T5V@H25x)~|$?LJ!E-Tu{l*eaR9$FC$-r-H}k{%}7C?|c(#p=5U#@MsnE zL6)_9u2g31!!Nt2cI(vWo+DWa{oVW@n!3MNZ{e-!`f$^c)s%3_tAH7DqfyZYK67wk?Eb|N zmF(xXw;evKaCDxWqfcz8X5z%$enxl?_-?pRVVrI-W-nH9^P$T4KodzK#r036j2r;K zj3fN*pGM6&r`aFw@#)2J|N2(r&p-bhLiqIQ6C!xb695vYz$t{0Ls;gEXJKcNaXP68 z;*1E}_@vp;BmVNsFJ?LnfeGVyER;Oc`TFi5*RG;XSyGbY>4Zo*Eg~{bCsRpj0f0F8 z*a)uke7Rf?hr={Z-Jl)-kX2L-k)CU5nbRtH32|TwKYlsDKF^^$Kem7W;m4nT{F@l! z2ncDuipVgIr6x5!yngjM)CB`^IB*zpUchXl(Epu9DBJNj(8H5;3bX~59I6b|1 z4ElUIU(au!fBc)%%MZ(ZF>{jbV^5nx&Q@vjRKIna6B2vrs>vE056yoR;EbrUg z;XbuwD8#_Qz)Z5gwH(JG2FdAzvh8;0;&a(nD|iX7c?G2L`0UI;AO?s&!RkNC9Rr-x zGaXJM*&_p;4X>(Se)vo-zye&COQrJKXO1BRW~T?MYp&v-$cShbfN7v|iIXtC)zKo}P#ZyJ@-yo2W=i>3Y4!z#&i^ zCJw`LeK)Xidg2iO@gM#^g!ue)@&`RkBNSr+w@QG#&b0)mysljeu7zPbd5)j~$D!D9 znB}yX2_YHS)90UxprUY+ljbZeAX3~CB%7HoS0oO@ZB-PS38<-N zD;Yjc(Lz89Lx6TD%oi8unAs2~Ky zA)xYn3);aLT@>U}kmBIql7SHr!v4fiQ|&Przfs|LsFokWT)Wu@ZZ+v`*JHQbsycy# zzuNPwMwH=Sd!4niwWeyVwF)z%sYTftak0;o5`8ZTxUc{&aV>YRlp=I%S#xxMhvQ_XfX4 z#395GBLHeh{%MZOnJSmu9pn&*LkI)M!J|?+1e7usWe#9w%I-Wz%pt^L=;|`85SRlI zLD@I}*mgs*at9j3Y9U5dDg-M^#O%&5~VVfpPRn`lxOoy0x79j-33~Hw$Y|V70Nv zoza{1IwIWc3W!j#2ULA*=KlcDHYD~G6r`fpH0Z-2eVE2XTE8PPlL`@;Vm0uF?a`P$ zU{tr4tKT#3;&ocBMnvXs7VV;)s-BCB9~|}LD^;WYkgw1+DnXY^=9Y5%i@g_@-vaYF zvX4xV2+_7NGBPnBxl1Y$70pBIuJ#jjuQ{5zoo_N5-{7`U+*3q1Iax`pbBCg`IY~n1-6+{PvHRU zeKqX&Fv^EC=8r`X_85W*H`4XqigWW$djN-Sd1Icw=-e|^@i!ldOYK<)fra3!Hyn){ zRs%I5Q9Y4d4WsuzPi5ii{U4h){XQWDFjY-pmUAkWZ^X##%}rV^C7zL}5vhBMK=}%Y zX2u+e44ZlyF&2v;dvrX1FJ4h(^+`amtnXQ_FPsXR)-l>M8v?<$FxKq)IvyrC}}k?k&^$8Env*NIb8Ow&n9vwW;dm4 zQv_2Lkt{M_&q!Fg#7ngqDw<-+B@~p9+|o}Zd(q?cVAq(cM5wm+9S`0B&^t&^8`>4N!7+ z#}q%|?%*%vI8-Z6h#dS|bX)mAoZR@zw*@c@%x+y&;;}dY0%v6wkqo9VOf5>KB$DrQ zSCG)9(-j-Y9ec}&XbY6M%U&_Fah#|N?=cn8RG*;i2903Hrx$9nQLls){Ko<_adbX` znt6ab5>W{5C1Pfp6EP3tF{K4ekpq=<^(JX01Cu<9h^it6=13fgqr)4jf__UIq0CjU zA?BPUuU;J!RP{tC1a#QXh|MeMr$$1+t7x*6e)D&`XuBH|#L5bQw@rwWYi z{U;90tc$;;?7jx=6j8}Lv#xE%Q_bIejvu0#<$Nuq7!Jh2H0vYsCouz?>4U%8C$sO>)`*CvStYfLQ5CZshS4iwCrT85dZ@kKIJx-O%v93l z?YG8JBnnVSiGUn(TCbP0Z?#&ostF7vCsQE~W*{nHra56G4sp4>E!X#9JcKx=^=ie6 z#d|Un$qsJ2&dlZB97m?;VdW_$Rb8%U=6E{RjR<70o)x~#E=h}dynKKd2KqmWA1qFW|~S2P_nrDR`_-s$7_CB){{1l4lH`b6)JUXOLi z-Nm&dxi=f_xHBy;&^A6uvEWifATz{ANoJ)Tw2gdWdn!0??j+Dz!gd@6+r)Cc> zihB;s-iBhkLBE^-vE82g<*cftHH~+F9`w2Pws8kG=F>)c0yFi71AKV`GIKHAMJA$@ z*Ro$D=A1=T)d);M`%4m4&_0jFOJOT+Rdp>DC%hX=#g1ci_w>3vnJr1M{-?Sy3dUQU z7mHVmcYeNysv4l8k={^vtk`2!YF8l>78`h#B9PtAP6ae^TXY4gwrn8el6_HW>4s`X zXdnW%<=Q)zFCu`s#bP#gl6&A8h|kyi_)>qrth3DZTX)xuSkK~Xi{WveJ#;U4dBws# zOQ@%D?WuViQ>5@~T3!h=6$OPao+3`VVTvwx}kSjA7=DB|J19s z4-yf}?+)ENZ<;fQNE{VWLEOWy=yRF-dI1rK=^#1fb-{|DiWc?ddVRN&Yr46nmD<_; zuZvXQZVobst*px0oag<4I?9@Gm^dH@FHBU$B$fV>8Hm>T+&HpcgENO^o|o6J$)-@bhdAwIvbvkxRK>vHvPJB)`oOb=60 zRPEc_^>jKuKb@9kzFyywXv%U(N`!~QkvO=bKbL0rLL5UF%Um-I<8=7TFTbkl=`e&q zmuqrYNd#EeSC=B>EGc=B2=nq45uaaPLWnm=a!$)SUv?dpdUgT(vL+7W@fiS?%bQnH z9ES1uoR+KP#my`vC6UZ=0M(M09R|l_a?U9Uz}oglNvmQ$Jbh9T$NfYSAP{hf1C0k& zF_B?%R5q*XbxBe2c!FXJ7X}OJ`=C06yB|!OsXO6GP8?zw#{S_}ek!G z&*~(v)e-?rGjpV2^sAlEuj_K|y^p8EGZJGMz)bQ2ikm6`sqxNSYvdAdck**xe~5!0 zn$t8sJwF=|B94a>$Kl`oAOB0a2D9sus&_;SlqfIh*RNky^>i4`Ow<7Mw_kth)dkFi zX2<6*%)CuTiDMicHgBx=YKc%Nb#9}KN~XFl*Wx^-A~}txm+|=IApGI<2>`<|GKXLO z;r}*(dC33}nX>AdB!(jJ??+H(@b=r!W|p(|m3_{#iXN6_95^Lu7Tca{QS?rtW0b=r zDdjau2t-J4KmTl19JOX4#6XCI$HNGqh;X@HFV`y*5kVFMfTL<)0zi@c?b|m4NGU%* zzkIHGi82%)53ZKcV%JPzm~I92-u}wG1%VN*=Wp&@>VL>gM8QyM*e{A~W(%Kw{M($@ z<^1YP#p|K8T+(t4 z1c8`?NLF!I;r#s5-%+txv-$E?0@12>8gbwdf)CmR>K`%~aEL0BmWvZGRkC(|Dfg#1 z5)n_X4+(J`rc++$y!Y|&#Eh_4s{W3Qen)7w@1DXR%ro(KKYbq#2mhRZu;(2YVZa7^ z?lc39$NwBGH!(MUM4Gs5KCH`m#JgGYoxvU6I}7;z zX%lAKQRJ=LvK@SAcH!3dUtK$Vr@_9Hq~rEHtW&8sJ=`tz+`d0;y(=3#WlNW$_mT5L zC(`&x_4v>`@Zs`oLVx>E>1!YGx<0lj>qht;Z>vRKK?&HHJ(S+6Q*;j1PdL4Ho4s~IERulwfP4)Fqp8#t6 z$J(!uJ3Qf$*YW1`U{xwm_3BL&yGcp#k=A?be>#AznL2#H{-`}e6<^@?Ot*KP+6~9e zm$Cl@Y!Q+TmT2}~_j#^6gNobj^kEbs{HGdVK3*3evc~{F{#y@-lYfmIuv)Bb3@#38 zrt8x8#nsHoJGKN!X3{Q{t*v%hiM5ydr3ob(^dpbEAiq)VHcYuuToKGa7F; z%B2p?t1VZc!dz-qxmjof46hCjPoKQNoQ_Y&=g$sn98NC{$r%EN;Cyapd4&*$moHDl z;mJo1KmDXC^6m9?UDHp0_+vwdI0Wao4~OUR@FZ!LoL-)$;wb2@Z-^X*fcT&Pn`g-> zuk$!g<2dEKYED*Kv^lMII6kWitup|Q(@FBWT;HXN`c?H0KmFKl`*e5`k?ZA*NS}ZD z(>h<4>l+gRgPXT`s9qt<^vV;TFcG`4jid!YQxY>91|p($J{Om2)9dARIzIp5U;JxR zOUw24K?C^ol*3@A^Z6CP3fZLo$S@uoZpk6!tj=9R#6o~ZCSnJvoN4v+=`(YD`}$8D zh7ckk9!@{pFX&F34(og_OxL};UVokKe>%|#iOuZ#_M2)^7XUy`Yg(7jpFgz;+%mrt zkx8}+4trQ8$H8jqf&ru~A~r-OqH#I`*iw6LB8GnHB61jr$T=GImZDm=wa$z~nDBJ^ z{0Bg~zW*l44KCcx3*&f@yvi~ob8+k6Or=*8^!Imq`C?}D_M6{-?|suc=j(Z0E`a#M zAODUyeE#tdIp<%0{S^`a#h?CmS?2kA9ma7OMyHa6@#xrqs?6tC075WCh>?k72*deu zIbW`UnF-hV>|zGT28cNf2LRBtK<9*@Ihn2glDbXfU;gp`qe8i$>2MO!oKk-K?ehMc zZve0F3jloi@uy)J0gwZKI-YzFPidX6*APMoA&v(QvGXF3v@S?A9fOCNP>5le@^baa zdmnt7+1GEcBI}?2=8yiei0GgH@|Q52PM>~A^Cc}8QOjBW@Z%Ts;0Wgb=imRkaU6g6 z;fG=g3A4@V>FIPj9{p?n<(FSn?Qr@$j??+_ADC$xBO(psAr6OOI*QNfC9CATTpN_> za}Y;3Izj*!?ik{_TmUS@$ysJ*n%5%TN%KV{5d~uQ)#Zsg4p$tWzi9V3?X_8r0+!Ye@DjAZQFHy%BU;q3cn#!=? zD|`8zN=oyCN^?1XtBD!C$#509a_JDZNvDa-tN)3lWzK2GMDzW@3=qR#)zRHnq4>|~ z(CUB(zw=}E{Xh8lZ+@?`x~&*)(B~~Ut?yb8J5%Rf0Cdag+k@auhrem_i<%qUBy1l+ zweKD5A*z3OK3?>n118QSN}*O-BhVEUmQwmm4Ru#N<1^A~8v=|}aNb*keo#%wQ@ z?PKqI<*@B!1AV{tu&emkkbT##Jd~r`?vHV2BWCbD*YF2b=C)uys6ICjfx7~>xQIV` z^{l!`@mEif+5#54|L1NBA?f zE;zqiKjO}f}vq$uR!OF(E7&>x5vE) zAvO)Z0U;5w5u2KMn_3uxI}1A7qJ#baDrwm-tRykr#_s|?YSZtLF*CUFiFj~=;6wDN zf1md$#*!QP)lBal>Uwfoy$*FY!OpvjxNpV4KyoI+VLIMxAsWTGt>+qxv#1OV&xobxIY@2PAx z-E5@8Y5nyt0LmdShn!YZU9Rtl`1JBq&g<(mI2A_93ZiU^`xvxp32)A1P)*UOu;96|N+`YR%i$L9{w#z-d^0WV}`*SBxi z_iu-nFQcRof|-d(jAQ&f`Ofdm#`Cv7gTe9TOBlxU|NDQ1Fg!oK0Q$bcMEvyhd^$Z# znsZt_l!B4cI-uywgm=Df~1t&-OeMhZof$4o=y`Fcj8I2@du zqk^@vKn)zy{+>&TaTt*nb?tFb;>4cd`3Jp#eoT$JCin zroCB(TWS~+!Ur9peMbQIpeDBcNaOwh@)F4fr1*PHo_((ueTY$id}R--Oc8N`Hguuq z-3eX7qs_>xC1>n2nKRutDez8qZDzb>Yg8*_L{J0Oopo7_tH$qKWHHRbO(#5HJ|;4RgVPNUE!{(?K5Ani_X583L_GsG-@>v-B#Z>$Vf+vec++D z&2$UL9eSO6jVmG|Hr3A8p}2|@k&A!&Tx!I=McFO>!r$AS+EU7Jvs>XVlDi_9i}s9} z*-RyiU(}}Ib1SGClx|1KG3tQ{edOl=1!}q;r!D`xZ0xpBaZZu`xYY(7?olilpAlWMgGJ?gx%-nw$ z0A!9p7NfJ*3;F9<|Z_o?8?U}m;13o|=06%n1TO$f}Ck`iMa2+7>3 zxdlo9y&V7mAOJ~3K~z6^<i_;sF%obIo#5>uPqHYKa&EM|U8 ztVkG#k-XRMkV1FQ;tz3)>#x#5HX3uybvKFEXx7_fsqJeU?xauEelB(5fK#; z9mg@oSVWM%kGNlt$L@fEfEljqnz8_bAujWbh&g9fBVGw{7@|)!MY5zYLTHoEdk zL<~UHh}7R4Q5BJt)gXx&Gln?0!Z(gnL_iY&+;ksU`<{9*d&}#|N**BW-yo+25QqoK zDXnw)5FaQIf}vY3xRqT_i;K96)Q=j3Q!ueG9!wR|>U`Z>oohuHy%9;vwUT>lZcf<( z3Cu*&bbKkj(Q=&*$7azIr(?fkvgh1xbrLof%wEgy@_%+}C;)_ELL|v+wV3hBSpjTa zZCUd$3^9fgxV7o)vLLcIOeu>R5R%(}6A^P**Tu}%EMSnc5E&vFz&tO^90KQ@bIvIn z(mKWf2+W8`q6RAIe5nL@mAvMh{k1Z43k#%W(crUiUDk|<%*j+rX0oWSy%LVSENe?fGZjJz?ii<<+^HZ85x~>U2mmMq=IA8(-Z3ht#jT`#y>N)*R20Tx zm_i(LS{mvvrp-~W_|$lUyk=ixWzTo}z4?sbmJ7v^2a$%+5HXGu#Rxe==fu*{PHJA5 z8GsGbF-}L5+~sL#1N>ZiNgO04$!kpqd#~!!o^A~sM=;In?8a4|)mr!G5@GN1SnufZ zfqx-kv3JwZzZDw^r5m~Vae|C>DdT2ivBUbUr9+tNHaV$r_Mm&T(~LOQX}R9SJGv;s zR8&d{PZR)AI%lkcqx$PwW3g~2*Hh@k?*;qygRuB};SQWZjCnD`Yyu?}K};3Rn2?#7 zW3|T5q>b+o{dup;vMiTj90z717ipYL4H1|qWeGJEmdTMt{Gd-W4ufU^T(76mmZh(wuIJZj z98bq7rIhpHp8bb00^pjnh>imRpnE>4O3pH`xeW^m;e4K3jd`4g_Q{@OfHenTj3F@1 zYXXDgVL&9e@K0;I8yR4!p#jE(BFSm-s>(#0N=!x7L^Nf|qC^Np>oS|cnhTL9FcTh1 z=%b3N<($-3PcAqfA|lR9QZ@gCVzMJeKBl^+v>uPgVHjQXG98Z;V&OaNb%CY!LIfno z28ja_=4Ey-8#BvkCT2vCoY(nEoq)^>c{k=C4=0DU&5V37K};b~HM??K&NxgeV)gji z*T!P1#Ie9fNNKrjeMaYGR&=)_$Cn=vak;#wv`mL%`)YAKsBE!_A&$mTC7VI-^ihJ( zuq0iWS`A-iwTu8^m^j4i>ryx9`u9vlZC=taOd$+J4I{zpPIjhHr#=wX`IIEzj zsaX~!#BoT4Ii)55Dy!B&llvD|^$LLFGyxD$VU&d7fB^I5twpiNaWb=9V_BIa52Gyx z<(rmjL()ps-^a|D1J~Oa;^ZIFz>*TI=$?ou9ELDXvMxDQH3cyshBy-Oa(zc4A5Rph znZke=LhuDyoJ8GXhPc)~Kp|GpLQQp;p29f2|Mq7v=||Vd+^kN#DA&A(Fobbh&abN4 z8v=M+7vh-Lt7olj7AQVelj4B@#BTbi<)y&eaa)B|!d;Pwzo-1QjyC+z3T~6RAYq#% z@3G5zYkc-@PG8zG8>~vTTy~0^QH$*XlRXDvqj6JX=ijp!8YtwyqR)W1x09>N_M&e! z5Qoc4apAgJAl_)oTc$X1Ffvv|vYgiTTZZvK)UK;h4z$fjnIi&uNG1_h2{{4+nl|i+ zi0^n+HIST)44B!y${%LQm2Id*x|Ca2Hjx&7?VhM+l*Eq#cf3$Q_2h8?QZfUg#x5=w zz|@;J0#}zsGh=46t(rn4W>!E$B6bH)z1fc4#ilJ$W;8eR>ufW9s8rKLJ*eDJfyhwZ zbF=_ttnBxnnd|$I-0um=P}Ngzb}aO|k%MR4nR-3$4wQ|sAfg7jLQ)S1Xcf~T+~;04 z=Znr5;f6G}g(-MMPNlJ^dFY-SI_M^GQHPh!wb$>o3!Tx#o155#g(@-(FXZiQ;2msoF2XR zRBhEhV0D+KX|~0ydZxSqZXLre)TN~UA%1_9*Ym=@Gjt0*@o-(vAq;K`zIoT)4k4`Z z_(gI~ONc`VLwyak?S1FBR}Nu19J`)uhgGKeVgNbKX1cE80d(^h; z@9%zjEoF_6LLf6pS%PHKEFz+IzFeRN)cFsejziA*{B|Y^|MEZkS82^z^bp3w(+_#M zrZj*4!{7P#O+^3a|MtHkM~-70rvLK4`yb}>+x7faau!+hvPfRjaz?;UfB4VBFoig% z=5>Bok;~gR)123tn2FeJ$*#+T=d|QB69q8%!ymsOp^2E8Lw0#xMDqFa^LRM^@a0FJljU@klun(; zrrCRlBkX%Uh0 z-~aokmmi+L{3K~r$;csL%8Pg_`Y?GIY0Taz%^en{bO+~xI`CVcD< zjU|6w*LA*Lr^9hN9El?_$I*#n@6Ex$M`gL?x}u;dpA78it98hr>xk z*7@K5|D3(ql59(orlqQ8wgz{Ph`rC0Q&mwtNwomoB5=WV-|+%G0tj649w2?iTR@BS zW55+6%ndY6W@VkqJj32Gx%*mXrm9@1nJrr$v9qK}sXCPs6~`lD4Q8gQ|Ns4A7(yr> z_F+B^AUS1vnOMYJKm{plLs%nZ0l3Ool7s6y24u}>y zpVn)R*Suci^*rByM5OidB01S~kc|NB0&})Nq3v?{008UtRXC4_I}uBiEajw-Bj^1v zDJM?rW_yPcHc5!aPcXI|g~1I|PHS9Voga$o7cs5ZHepS18Rz3L%{~mne6qKDJbqA> zv|bGq*ZLXf#~;iYg6Q;CD9{NU@@h)~IcM@f73t?<&JU)x>TK-#ciZ0e9hpq8kH=o^ z0eb6O#Tz5A>X&~48U$HY3EzOwv@6`|IT3qKd$0Q0yC86v4c4Q}diT8cL+N)t(#?#q z`7v}0qA!OXt%Ff4LrUhv2EpMhl1(jU9=MjFXVj(6@m=%wtV@(L=cE9fGdmJy3!t=t zU+GSFvUb>|pm#X<+8xf)6K5_R8+#CqoMYZ~)>hZQeP4qT0u-t2{@sPd#zF<3g z!8+7`VkZ`Zas_+B!21%g&1a48paTl5xm-}d4t<9=0mxfz^1ez6|1GUhU+NZZ84GXZ zSo#GAR_BI6+{v}Hy`xneg>P9I*f*$J9-iv0`l)|-`U~SnB*Udc6?2 zkKg`AI9c*Qvr?FQ(FT$(3<#*MGAR8JhC>*qFdjHZ<}7Iifbnoo&L1DX70K~>1^_oq zb`Um%Pk-J0Fe1QVXACp=AOHFv{QKYi`Ct9(|K)%9{@?uXzx=bmByybAH|aSVro(Ce zHeSzhxkygJdAYol1JO9g<>Guee)v{Zug^a(%lh>E^zh;1!{IaygXVa;yF_wF|L8wPaxb6$;K%XczcK%;X+3`U?f=F(J^t`p1pLL{`zIW)FQ5LX%qgwT z4}P4_uP-l8pa1GV{AYjukN)Z9`DYcryguf*{_-#Xy||nofBZcno<4r}^Y{Py_y5=b zXn9Yf62chQv#Jim+``J+12mmJ96x*)#%Y+2pa1yV^W%@p@~SF6t)Tkw?Qc}nAWUJL z#EP%woa172B|8Dkrw2ez8Sd_Lzg3uxgZgHvGxS7UmzqInm&>5%J`AJn zjcHw2cmj}&w!R^l8-6s2T0Eo-wS#q*s`}Oq|0Ol!JMeBt@*@wZoA-}#@ zMWvFv?xwEGOWh6xgkLY0WmyjMU{g2ee0<47#OrIkUUH0B6JV;jOFIyzS`&UcK8R$=DU5R%4{13!cAEVxH%ylF0yPlV zo?aF(1+`y)B3ir+nOEnMau*4VpkSiJ#tcGW;TSnt!s-^!i41a{b(sPzP8R)o^L z{$g1My@Pkt>)#xG_Gwrp!9zrpunCO-NqT4SE=7GSG6Y0{sIMLOb!7AS_UB6#5eqIe z&F$NCFKZVNb@^T!&kEZJqDhHcq;Q#--qh;Mj3rruT_B|mpH#DDHt6;~+o>^Po9w|jG4%CG@4<(^n^vLl zZvi)c(@DC`zr?o}qAzEmA4k4JmhO{A`hr7hh1dB`c7-(77qMLYI)8>;+QOSss&|CH zA$WB)TTvVAeDDQb2(1XiFFi;tTslG%l z=}~K1Us&z%=+IYsEnH7`iGRB3J(^RY?63Pxp>8`SZ|s)5)(h+zCjWo_qqi8!n;5cx z@z4MBYFQ(j{g@7CD|795HH?Uk(=L_XMB5fiZO>^KXM5HZAPkd=m`vPa*enC6%8_+C z-Xmg8QACF6Ae`fJMu0FKtJ1;Q8H!wZef(pwLm`^8n0x?4Bcc(xxL(tG<+O5&hKp^J z;p&&toFX8q0y*c1TCBv5TB6P5QDaJ_OJ_8nxJ7BlML{hU$$5|Ds-`)czSLr6nt5@Y zPv8B;Ujg9x>5m9#(Ld%M1=aJ@&nj#!#OZJ%=cnU?s-B;IPH9=suQmzv!|44W!iaQy z_}UNS;}3s>ShxfwD7Gf9{rVsM2jBeWA6{P`RmD={*Yk@i$Lm>`U!Q(F+<$%d)h{_k z=6wGA$Ls6ooNE3N^H<;fnmH|(7aK9!$vlknFdoc_JRR>Efy@g1lJ+N=(BQ(HbIvR& z^WAYGD$1tA=>q_g56t|xfAiPVIM|`Pm>;SlnORgd1lK#~Y?bg~^uw6rl5@<70q}6T zH?6iYomFLBF3yK0b&Km7Q*>2oq#|Ga;x~3`7UA>ji`fq>eU(|5&3=pHG&|>BU!J}9 z<22i2wXX4UxeP-Xf_v+`N{L&zO$eTx^M0^oI3GrGp=Z>E@n8}5eWi81UaptRJdGg) zI|-O4hnyGTxL!cPIlskPH6fDsn_!JI)U4gxXBytnIs&OQJ9x6X%gJXB!| z-t-L1%`Hw-ghs&V62-O83RaElg*hLNA6jmV^Mm~ttJuOgyD);Xjp9^fd$epuK+bv3 zIhR45O-aoWfux*~(4sJGqzX07KF5`F#qSLxq7w_CFX}IDZX6RK+g*EW7z98U1}%A8 zWx!M)QEaTyK4ZPlNZt<{0Bs#$W!)y z2*U^^A@8kGvNokvJMq$O`=&WGOeR)?h_NX!JHwMnozeMbCJ}uvMGb1|G}PdDB!?=f z1Vlgt+}j=;b*V9R3@-ISEG`jyZ8#@HBJ!rvgf1S83k=Z0m@?=PudiFemZ~4e!s0_U z;JWpK5>c_;h$FYQ2@;XxGRM>kDc6nRm|@149Do5pR{vIbXaE< zRcd3=+F9CKJ?I?D9^TqbAKx&#whPwkcr129xaDazFE18N`Tpxp^wz7|CAak@t-c-m z6m1=WmaB!PRi!IZD;$wrYe9E|uI+E`Cfi`iQOc}jXU&EyQnf(0+b2R)S%gr?LLnTH zBB?5>?gy#;7!}_XwcV)v3nSG{#cIN(UdD{QnwpSES<4k@uUMm1mutekq(aMMNumN$ zO>k9MZo>RMc>ucrGTZp1eC5qMsC)2UEt%iD2=#k?F#TRy71YAS{V>}CZ6~`hPPH_& z_)RivNLm*FAh4S4SR>C^x4e5$QHw0Mn8`5S*}1?rd5D(~qE?ZUDhQGFPu!ev!s?u)8A2bLq>EHPYW2A1<4iy9ULjJ>WLhN&=uCWE55Qe%ML^L?kE7&iiSet$I_A02+p&!n)A=p;Q~yBu?aN1C>l`#hj1F zgCp|Zsp>T5;9Xm-Rav5XGCYXZ56TX z>uN&lTI56}92-1ZWE7(0ERvlMHICILNY>KBX1`Nm6)k$##>-TDNlRafa}wvx-=dGEU)qjk zR)5LSumwI0)8Q_z*R(EKSZl(79XE1Zp(5|nk|+#5pbz8W{;Q`Set&uSM4MH=bsV^E zhi=R0Qpwez-D4rOU=BigObZXF8hh(Pp5o%X_u<$c?z$01=RMSK<`$g+h|YnEA@z#a z)dypZ4&wm;mgSmrp2o4+gS6-cEDKcAdReb$TPTkY-^_O(KmYN!#JpZ!s-)%N`0%y; zKFj$jEob}nUSD5w&R>1?RXa`l>1cn-eEM+r)h|=LKL7N6gHG9Vsa0(@&L>rg*B5&u zN~0r;y04;~AIx_z0wOBR!r4d-_DFD!D(w8QiB8FhWaUicEZ5h}HpckKnakL+{#N9i zS-(ZtICcyf3!aKv*GN@!PDIZ7u_mY?asWw-Iv@|@T&0;xlGvOhRcioxSy4Zg6Zf_#gj1EWM z^c1F^V3B2I1EF~5g7;yV$Ok*doiCS^d6*6b%_@@PCHT>Wq1di+X3pa{8=nPKn=qu2 zMnu><=jVepjW4gCR3Qu_krz&g-)9a$~NL=K!!%f+?;1uz0qPN^KcoFf-RRWtzxbRIar$(bSrWo9V(G=$_>Q%=c* zb;8OlMp{pCK_rtPm9kis)5^(=69vMT(~9H*j;fH>t2oEmTj7{flmbHrB1hm-T)ZE2 zJb=jM`LiF!FwAwhE7pXsS4K*+Zfm-j$bn7!#>^HjSg%!3Va>^&DH|H8i0ZESVkZe- zvRIK2R8ef4)liUSqrzP{Ru>{s*smrY(H+jNnm|ntZJT2K zvO3i+!;URc?ba?~yNT~W9&}|J&nH8Ks#3AFgeo^~%U|w=D$Rjl4MiIwQUzx; zH93(Z(syGA%ps3d7*|M6IOnw54qE4_R_`XQrsfuBMum^FOIqu-M(xUOYtja^+tQNl zlIn(UF2Adt0?RE!hor!Qgcg>x$HKjpWp{|tE=YZAGqyYW1s%73LEEjWRcV5_$MAnK zu4Koz+(!m>_|ltv%664Rg_&C;tJm^ap|gp?IuK=z(u1l}p>nm6K(P`Ei>I>y=c;*I z5kWw--eLud{IFvwd)muUQ&GU!2J;EjNt+}YA9nhQ4rrNHw2b2KpvLkT! zd}%KUdDAz>PA#GvZd9qut870-$=j6I5qWgZR#7C^jA77t7d^vM-^h-z+~{&}++<&( zTTX_2Nk7sSD+R^Uz28zG%brwDrMS!S*!r$`qxdVCUqn3(xR6ZVnB23Hw_ zaC!L*fSjUXQ~WrM^C>Rp>&s(zLCLuQMAw&3|@RU<-Py_AOJ~3 zK~xW?hvS3eoDg7`k3@dGzBXT{wWPv)OzSmQ7e@zkg7I)~ZxJHScVC(C*N4%E(L(aZ z`D6{5Mq#if(l8#z!`<=W>*f5sUS0+l%4!I3|1bbx3p%hy1eVDn0^m5`4dc=NpN~KM zF30ts{ImaLIX`{+{$H!=;r{E#AAbMiU;m$Wb{odINe1p8KGe}^@kONdYJwDHMgUG} zT`rY#od7hh>-L}siwfr~IhsLUB*!(|VvC5cPd}CBI=SQh*D+oYUdQ<`pFUikKCR1n zb`MClNte-A?eAslc3M{@E=!C>W)-{(-cHI$&WQ-X^S;^W5D7ehswC^QB`h2DZsA>^m(rFa$6jn;Gis!B*xmjKesLlU4KfKlbW8Jw1yk zAVN&%>jD7Yk9vYu-{nT~h&Wo6mWgSakd0QKIZ^Bh-n{_yaPo!rU!ofZYa zG9v7nuh&-_V1UZ<`nVylT!=4eUDtK}vHcpu;DmLF+3u-r;@*$*@f6pyMKB`bFdb`W z8!bt(K>+L_48s_PV_D8CprfMNjQ!3 zscCjNEjClp&BE-$Flp7l+&z4(Pmpo%QeGEZ`r~?$oQHYC3$)lDM4a!xQqG){EOcHAD)KkpjCh~pFRkuoT92I3pww@z&SN7 zOG?bFoPS2dX+A-hM2kr1$c523tIBye+?iXtfTIoT;~XN!^~#09p;buExJz4ivkuVQos=-EiPKlSWw@=e)Jbu-Ya|E4ca)e*Ot_#%O;pdG+! zlx>?!^H=Mh{f4RnQgKoJ0ZKd9>z709wu9LIlRMqQKKrT{iFE($Pu0E4*X(^;-eLW; z9!gn|{{={II!xJ1ysO1Ww}il2yf$cSEBIKq3alewmGTxh>%xt?NVn5FsMKR8_6~$j zlzwCAzO`0=skOMHac|kOb_!FXy5x4=9_S!gH?9Ny6F{mh815Yx z`}TX{mT}S%wxsho;d|b4(1y+HkPjk)V(&!<7*MQ6^6G!+T}gWDj;Np1(*4>KLP$al zheKcm6KNN&w`m0{Sanx~bkF=g+fVnhuTB6VLEgS6h`U;)Z#T5Nx#7>c#jo{o8mAq0JJOuxiQbBr0H58+LeV;9zdyNdUX21nnjQM$NP z)pvXlt;>R4M$K*A)>M3Yt9fbp?O$~J^gfoYUEd`p{mcL6zih)fG|qMBWi~A=A|38N zx?yD8d+~Vxm8v{{`XlXQ`D{7?FtMLgd19F!wz=Pvoo~wKv%!`i%GE!q93UJAH_77!SjAjLSK%SEMbA zBaDagsDZW|0PJqNA0{9QVYEXl=d_%k$oXIX<-faLUaqf?#@Wen<(x{w82|zoj;oSQDE9g$T#s5g`P>#(Z7kG=^ym%v%)pnliH- zrax4fBHOl7aXO`iA(SO{xl)t`5G-rz&Sch0TFW6%o0-$-g!qM1n>R2uKfU9 zR4oT!9z78`N6VVlnC&Gx7$`jDEb`5Vdvm2T>(8G)JBK~P2oZ9pvgDCL4Qs7>vo$fN znDaVLM;|8PWHc|~eE;>YQ(Rvje@2A+4`20*rsTvq4fC<}>JJ~jQ4xDXKmYjqaXw9l zhcHgVIOm*1czJzP(ZY~Jmvemi{FBy5OXrYTnPr;hFbuus{POyloFAtnlADhYm)ED~ z&p)*_3IVQhD?aAYw_S6I*_spfQ_SHrje!trGU(3enX{}h&+|ObGr54|tUj|n`wu_- z7`!vC-Z&lCb-i3JA-LdaJ4Yz2F*D2QIOZ(pYb57>_3J+q&Ya^opT_yLu9qBFTPit4 z6&{ZFHsS_A^8OY$R8RcOSw(Ej42a77{PQ2i!>PE=naBAUhAF4G5fxIhF^4J$$1og* z!<})u<8ro8Lsea`XA6TYU36P=!{CRhwZw{Y4YaJHDK=JL;di6kX6=Z1y&4l7i5@@w zRPh2dAMfAl&g^%#goZwwzE4xI{}+DE=JE{1d(N>SS+9{+}q}=G;m;_sW-#YaB5J~MZaQX&ihpqnD zRKU7Nm+jl3x=RYIE?wO=@0Rii-N2w)Jyn}kv?pM_Kl0N4Xxh({^u~nnMs@xkc&x3w z_GfApI^%7{hC7_smsyBkV5;rknQp?`7}B>t7Q2#gBjZVDVnN*(0a}IrCBGANKb6A0 zJLDZd6n^=o)Lm{n_Wwo79IN}bJ#elY^1a3Q=}vizg_?YGC7Z0Fe>&bBR^mnsxV_<9 z6HYtBcuxWWc%MC4L;Ln72e@rwbs>nY{#V!^{p*bP=A+sz>ELkHK|$3)*S)HJ52<%t z^ff<}p?>#cD@m~c8nI(#Rt=8Uf~wSc^ahn!NNMc}+^4a=b9-uM?gsH-o5g?kU;k(1 z{4n1EKu)WQm;wq*oQ<3wzC$9;u~yAm20z!cT^APy9|k*;sMv&w4a%jubE%gkYv(v6 z;nWl&Rsxdq<8)Af_3~n0Y=BftYF0ZzE8KtcXPo1Dc~%k5t7Oh;bs<>xH=?uYPCsF; zPkcF;n9?;Zmx6>g*SuMVL2W`7rUU0_^BV*R(4ZM7k~FdtQQeSIo+WMR%J z3==tTC8_fR60PSa*pfANN1iawVVsuNXEkSxsijSBjyOywJGiB|1WFU0Dv$~!a2ogf0_ZS$T?Mbeg2%{ z`tb2c^_ODh#WdsF*l+rkB?6=rFjU>`{U_eRbQSyiRzm8bUYnTCqq$K zcDap&Q@pB3T(1Z?&PS-~dqCp2<{W(pMt~E}AAj*@l5<>)0ywATay>s*Rh2+KKD|gFiceD&A=&&iVuS_$7u0A2iPSWBO=7OR96XvaV}1F)tsXBHga52Tx`zkI8Zl9BL$4A_XJ7$ShA}%IoFC$Pj>{#4$$4*TixjUa9Ks|j%n6ZB58uANJUxE? zbU4h1dA1eF6adR|73N{^#;E`WyXNFPr)WTSa#oA$`TUYo`uf{n)M($(sI=Td8cAl zcFw9U%Q&=MpL1?rXXd0L!#InI1;I;BMUE>{d^ki!!tFdFAo)IzR!!sTJ-J}-br`04 z9>DAQrOJKK4};}jj)%MHcz=C;jMrCk20~j!1p!4kE*C%?%{We{fWAMN5l$Te+5vO6VAn=d=bR8BnL8Vlh`hRrs_}sx z)!Rjz0pB8C_b3N*P<4|+AnIGQa$`>Kb;e(sOc#Ho^5)iW`%0-|dtOA-qhjA9Qowdf zEA?^XJ=ZB*F>>n;QLRm9`Q9|sW=ORja-a%(lhRuYe{JDx7N%`pZcn3tY}@TtW@`!m zvcPR2i>pQ2f$%E03y4rkz0yCuM5IcVPpJT8Lfk4V2LMMU@JopV(GijJD!Dh%7q2fy zjxLst;;j}D_QU9hqcw5AZv`|w;;k+U_H;i`l^L}t)jLW6<673H$+g39V*qUCjWEMpRtewf! z5N?>0N}=K8ysCkAi|O=Vy~?iE@rhlUkK6#ryu~Q^Kju znQQT|nKO%N_RLwFCov54>b(DE@&XcndyKRQ%%9k4cQ1S?=N-GOzi`pOpZ_tirVX73az6V=% z{|bOEjDV=p^kRr5T3MM{MQsRbPWGIl_jGr6PYCO>nEEAi0)>=0=X|<}6X7DjQU z^CB$5D8=+`O10(siiq9^RgLRnYj4hpS!i8V?MD~IKNk>(H@}%~U`4SrVv2D`1}%Y< zCKcWe87AH~C4mK&31 z?-vyj$Z56v0@^df=IL<1US8TEYdJp=xnVvjkuHElo<{p-7lvUzSbIu}d0Y_4M8>uy z*m7UFb2T@du`lP17?O!v5ymN6{*lS?6=0n2I7i!Z+5yK8lON~2E@m@V)wEuj(}(Z= zq7Z6SRalf$T!!(0fmAqi_Ty|VVpRpsi0Fq=Rdc)wD=_4==D4_F1ae`Rai?IEwn*7= zalJe*=ch2vJ`C~tsue0|?`mQCRY4j#@4~2Q70ET>k5lHfUJQf)peZf@>KyqHi~^&= zw(YE!S5-aSeUNf!P|m5?S5-L0#;Uh1Hf07RP_|A>tE2%D#c_&py@X)`LhlKbyb)jg zpd#cD6~O~mV2YXF0Whss6){jPRv|kP0XQwWuO&(s0AotavKnR7ln6ORk!(%!@@+QR z08=9LsBL9#ZB{3u=8Yvn<+3Yj^OeeMe1;sORlGw-W*0L7g8P)W{Z zQ{38R!ez`k{Ikkvf=})@Q3iKApV8EuWQKq%nC2KMfAjb3a zHcqa1fr`%gQ~!~|^cP`3RVe+%RJp|B`~WJP5+ZmRImNhMZG$fCXoy9FR_ifU!7_{A zFgFxJ`Q$nm=({rHoO7PMU(cG>rLa_p5I{7mg0D|#$0gUjhj)vq!~HxN3n#30L172G zLy@e7m({wOytk=#W&qreFmY3Ps4#Ov*c|;28lfwv%Y>`(34kvRAqFO zfH~^&((E2*X)UIvVyIo|jgh!(o3y@$F-Gjrt#y=*n*^gASnL~Xq@+o$kiswmQi1ZM z*kT`UnlaFcWAVmwUBC_6a<8iVg@AyZb9SgVYN9s#yTEOJdiikKCxmD}neGww2!yCw z0vB7iv))H(HwAaXD-g+VF=jj7e`yEFEd;fPe7>hd*hXTvs*Em5ZOf7e*c)v{ZLAQ!}BXGCR=Pz`%|RvzZ!*HpPEA(peH# z&X#%kCH-2}Z8RGY_8TU?p*i<@naZl)#Q!bWugw0SH4omI7i{6Cn}xiS1Pc?A5-7Zl z9uyH$;0Cw4c}m#`fy~{PG;8<&<=zSiAizx_g1-%%J1^*MRAeH03!57*bnmrs8*Zy>`#7IIT9LF~o?DyC_~>Ce+5SY%hv_hkbC_mM zStO@*u_^~to`3#B+f;_>$ebmo9It7;n$bH&M!@@Te(l4!E*AjIwL{{3aA63;o7*S433nVjRY2UKAnl1w|$AwEShfaq(Kn!85QQf71Jj_S?V^ds~%X7aP z*weI}p9zV)Z+$$D2Ad~Gsc7myegW0v?a2wxn*_ zbXDg9ktg!KTgHCLaXvXe#OsR)V~iz4MYv?z8B@;O7p$Cf>wh}$Rn<{35{g($z_;@| zIR{9F8ZeGSQ_R^h@p`$e@#&lIe(9Vu)%$vVwWEd!{Z%1n6J=x0Ii=KsossC%58sRE znld6hoMz6+wwvH3Vk~_2E3+pKI$cIgpBI5z|gGi`xh`VLnfJNW&Vj4RD<)!hQ!#=QDg(9v;Q zHUe31Tj(u5n+d-Au-i}Gq&@wYq@e`0vvVk5o%YK+zv2EvcUNztEcLa8?9P%~bKuqv zyw`SHsY|L~^vK^lLFGBx1T(si;kfxA>CfHGuCT?TtAI*x$+>BI=)Q#7`v`k!xxUSV z=w#-q@2L1UtIMu$)3W#Qjgo9n-Fx?SeaAn&Aq_Tp8dl{Q^u`P9lp)Pr4?Ct-eaf`Q zE$Dm5!*+if#`)%*0DWVIs4?iUAs0KFNhfaVK3w!R!LncFcA*e`eomJgT9F#i`;Qu6 z5qoUuo8}2>X<9URx%QmA_KyznuvNXgzAlVq&@6-6TN}Bs~m4Rx48Xl)B!s1 zmY%W6GjC%}p^x3X6@I>}2{kk5zxe0>#rD=ot{Eb=)xbPV$2Q<8+ne=>E8)g6*2m*r z7!PT=7>E|ht(WJjr$-ki=e-YOS}$q2%%=}wKG^lYJb&UGO(|yP^c^B_Et0tQ~KIke18U9v4>z zB!xz;%32ZRA`Bw){nv=-Lr{ej7sH6RW=5g@mxH{uK}tTH_klS}iqq*~I^M6#C9TWp z!*_^ye*7V)qC;`c1JXF3*30wt`O~ld!9V@w-~T5_o?LkP@pqiopTGZq*5z!TldeU{ zoUNwUVLlAw;pxZU3$q_)axPw8pmZJp0K+ha>6q3_TCd~-lH<7SfD4xU2*7b6ACSCr zj=V2J&=PquSl|XZZ+iXp^4bqJhUw_X>H6~7@au@^!qhszJ`5aViWhrW!#MjeUS2-6 zakou?+Bb`^WUDnjvjORE4?WHY+?9-M$!+BPTDkC*PFEhJ<@K|{lpFG-oPYr!C9`88D z6t8{9Z#sQM#O3vob3A?gg~1k}1Ruuba+yzehvS`9X8nF6oUFB8(ncjq&dv`m1VhL! zm*+1uoa@rRd0n-PHdPVv^Uput2v*HT;+@NxQ_iQmdm`!^X-2?WmSvo#>2R`nn0>?0 zv%e8lIIUL%80J&XiBr5T>vdTz*7O&@{1p+c*JsIji&0d#E@?i@r@MPj(P)TaoY(71 zd#^3+T_hvoFdkrwgQgy0VD;88-`SqRIe-8A-lZ+<5tA3uBuA&kd+q2N06^xXqG1^OBZ3LVu_2cMQd~e`m=1dt zkLHw|b4Z@kx&_&HrJ=t$2z9~A`vZm@(535==sWSqjkkk4(?R3?bch_iK}PM1jN9|$ zdkyF}+0Xa|w=%pr)$fa4ZN^dTm`XcuEFviC?)0r+fCB&^H^asN03ZNKL_t*C2+K?*yJG0$luB*qt17bJpHhv+?`}WFWyE474p&hvGKy~X2 zw-KGoUh|h)X`jz;JTeeVx=)QD}61S_DPo7 z8HB`cQ)L6T`m^1;n-USavIOa0p2tvwwu_#LrZt4Z>(X z2~ExR)D2RnRT7D}zldlek;C0rcVGQ7F6X#j4aI9kdGST0RQX%2Yf?^L!*uk+nAQbU{V-xR!03v*7AlPXJ*J{BYb6}*60rDCq|GX7jIIj$y&#_o7kLa$7MoD-3e_3henCk(_r z=m+Y3RObRZs*v=86gTjKJxJKLUVO)!heZ-yRh_sUx2<5ZNm$NNm`@+R?MXwhXFhO_ zlUc|S5%K!+8Ohmv!h+}Hda)A1e<({dHg!*n#Dc}Luks&NfSKBol%4-en?Fszqn z5sAyWg^pCM|EDn1^tv~XmDVOcI|UF{lX7F7-2 zwMMQF-WJ{^re#gX<6#=dVLAZ7^V8>?qCHDPaH@J;(&2czd-#~vYg#X6yXyN8IY)AS z7-pMTN=`YgnVBLJp2_U&)oX7cYy}qoMS7?nffG~{a>u-&mFpT!#kB9s5 zaF>=#PVxNoqX?I6qMJH6=Zl%7PEkOGTxi>P5u1>+G4^(tAyQKVbv2!@V`+y(&gu*k zOI30TbgtV*$k7T~zLAZUBbL4PU23x#PE7Pq98?x6IJV0B;0nzPNUNR=e? zCPG@7%}NoMbB>Fo$T?CNaifnbo@A2`aiw+xT#IqJ5|I?|zL!fRMr;=d8}#sNOW| zTgZD4L#scc<-(MDu0Am2yjJ>Ry`)Oy5z$ob%4~^9tt%q<){$M6 z5rE|z&^5Ccww&(P%zSq&S1v+})!kQMb{0XB9t+qjX*Vi5px$bsL2VpRuN4t(kTawn zozauo3vNagMVhF`5q3(0-8)XrXb;`Y^d>vKPX*G37NfmD5qsT-NYRrPPpT9a&;B87 zXSG(--*y9-nb7#Xazo*-I&-;|yXzYanAW-w+LKwdkS*J*GC-j04TyRx8h`KQxak}< z3^#(Pkm8oISGzuab*$B5$T_#+!i{hOx44C}uA1WA`9S1r*SAH^Q*!~9H_Lf@37roX zP+Ccos(1tHwC75oUnWGr)vcjc)oooZ?KmWSPo?b12S7^e1%SvUBea?tQ-srcX~8N zjG&rx!WMcbBErCgM5wgA4kB^6Kym&Sf^B;da*7CO%bG9)8kh>wdZ{T8y)dNEURr>k zeM(MCm=5D~;1qMaGOgpJYT>I^n4)vSp0l&KOY(tgIEV`)nJU$mKcrzkAyT}a<9bQ! z)t=MC-3LUvzCKD$?Q~z2J6MC5fjMb}0-RGtqPU!qobv%yE%?{i8O{eKA}Ov0hc#xh zriACXnzs@v4!BAjjYDDDOLd0G5k^z`SxlqxS++eG)Rfs)OEK5UQxlGtXN=I*Z||WEo*@C14FvGE1*3WI-4J!EB>#Tx2VURaZqsXVfu+`-BlnK(XYw z0O&9s$}?Y0ZJxaGLAG#=8k<1QGbfI*7suA5YeK>>OszlR!hj|1Xh3p4jO0C$v)EN( zZfuPz+7zg<*e>Yi;kfB&S#g8ThF*v?9x#lv;UETbMzYct15g7*$?Gt|Fa+nlEp0;> zymL86N6w;ReP#my<;>S*Wl@(CXA>52*@v+7Z=Ro@JmJ1EfjLDxlsZQxr*mUgfOFI` z+G-E%3y_tPpu#z=W|JypzPktS!*o0f=eS;r_P&_J)j$MhcW(Zic2?5@JgGasQ!~uP z_0o=!Y{Fe6s4)Poin1-I#hWXrgJC}qE(RM!G`Z{>H(pr~00G4ElPxRJ@D)v(j_nd5 znl?Da^=ir3JMi1>(rqYF4m-(y7wc~Q#4-e6%P$|Xv?gIj@*H=}M%=SA0DCgX(dZ1%jLCuow zE$X0P(1dy?Hp4$4v9JiQ*E1r`cOP?HjNwwTKzch4MDii1^~%V#uBNa6kE-b=g9?f9>}Q*n4=#608JiJvd7}$$H|A;G!AyeDZgz=PIqlL z=F;mgt5{oz+x1{wiVUX)#v?+J{!2kil>3Fmy7Z>+w^OJv9S|wSMMX48`((&^b7)l+ z=R-LPG$nUeC0h^N`9R(~=U+elU~~K8{IxD3Ze@yd!H+Y?6*3fFt@)^#w`kYuM_=Z-KB;OL=T_Y^Crj?Mx%l9G4S7e4xEY235Y{CZU508%i*p13Dd+353bS+6 zX>rSwXMgp}^Yc7S$HUk^OF6C9wRH}qxIVU8r}p!)vs1o1byC|kRXHbiVIbEw!Vlv# zxiD~wXfy^e`oKq4Tj z9dfy`e5k4@*M(7pa~P)Hbf_wlvQ<=KO&0D=vhH+jUpR@&q?W$V(`bL;g2b{e&o9XY_gdKjB)zCT4a>5cSls{$h0GU~eP zf2)r!5jG_bSNE~z{Q!JNOvf!o5j%af)ev~A+%0Ao1Go0``8Tc6owT}iBDjY%?l)Nh za(2I=(hzJB!NN7!Qk&};4Y#;BB8Oo&dsldK?~MIe>hDgLg*R3NE8NRKV$-!K?7CE& z;$VBawDTQfGhoOjb}<&YQj=Hoe)E1pzB6hx@eX#s1NNVc@5$Y}7OP_8=I(xwA>TI3 zZTFlM8f4M(LF-0tJ1f@KS!ZC`I*s~9*R-{>c509|nX&J&@cOMNDU+cs!l{00r1W?ccOjH}=e6zAb~2xPZP803By>{5o}y`=RUdeRfsy(GOrX*`G3BJq#t>1=Yu`Z? zy2fSAf7tRFq}}hD{Bzw?;f zq~GqF|8>PtDShmcd+)xR7&hn21?a%)x#7>brK3cRmm~H%tH!mkT0VFfjnCWWl_i zpNkLO2T)PbHI^tf^kJ9|IVGeBpdjqW2>{cQjFsj5aJc_yA>h{ait9D4SLH06U3U;R z^FUq~Ky+bJWyvXwQy33%Ij8mF!vsinF3ans&5XwRgbJ6JN9X)_xXbI3(`tW07mihK z&3Zk9s&%1NSgz-GTaNc%xnaCKr;4Z2xLi&jzWwmsUjX2GeLb8$_+k9;?Vl65v|i(K zUM?@25wLn)B`4<9PqPox>BDyb`25q~sjeh)ewYsH<@K_DGUk>KV;JXXvVK2QG%f`_0z|P6{$wb}5mwf06uvWm;rKzyFKB_YYIN zu9sKaK#T`6Ofw?d9OV8q)zcEqcOSK*_84FO=$zLgp|GKqvxc?^8=tS_ zjQ}9v<@u*D98Mp9VaIV*Zi_H;7MA&VkBDxVh{8|5|5wf%$r3BSv=B>53h7n@V7y+` zyh*C-<<*7Y!^Almj7=rySmFlFe$Wu9)+`iG(m7#GMCP2Tb(oRJmx@-C2pedPZBkge zM~I;6hY1v{aau~hFuE}L;gDlw?i(1|LN|8}NISUZEGjuA1zj%B{!t3Q(L35S% zh_Du82DlK4cpkFvZvQTJ|j3T3dlQ)V~)w7$uQdK32k#y+pzQN550 zI^i*POg6pEDZJ6o-|BJS2=4Vg?eAVAealM2ZkS%xecFYd-6W!I?Kl7c0^m1t@HYzh z(jMmjkFj^zkt|ux^~}uO*Ciq{v#NV{@7v)4MF=6KE_z98iGfnhGLB zXsXB1L?aH4fCG|y_oXT`Bi35(W~PDpZLNr`%^ncln^{>A>*DTa_W$26964>w5t*7> zyNm%45An~PRb$Uq+nW;_$_{tHgi>jDDw5Jg#GPZjHQp;F=@?hvS*LqV3f>Ly5qeuc z>OM&k4*IN$+wX?+_a<)WFMIobRMHA+|Epg7s_7s?25l{kgPj2Mfy!p@Eb5XnbES$8 zjOD7vlf#2u;-lZ$@$0J1xEGxjH<-w~xo`!0}hnKt*g_12@z3(XF7kB2)_CkvSw&2fRuU4gVdBv(K!mO((KuU%7 zFE$rApU!>DC{RNr|HtUeRp}Ma!5m7&I zPITIH{D;5$Z|zVF0BOCE_v8l-^BBDVDCVyaT}b(+@t3=3ZZ~uiBX?#`$SH zU4&UwxS!IY>+%TE0=;|~U6||?W?#)taOSlbPfws4*Z0g{wsChUmV2_7ouE~9dHuz% z1Cl==eDaDw4n#PvT4Z3%X}-M7mrrb-jpb&tAXT-Pa!wnOyL|p(e*XUX`#+BJWjsA^ z%Nxh-pa1FqNpXGu@~5;d=TASTwBEk{f{3T*@0p{?ltkE^>~BB+izSDY4TI2m>naH+ zi5t2=&KohH1+bx^@gXA-8Xk#&2t*EW&OXNT{q?INvgkaY=J^ELez^Eg+9fj5Rh!Y0 zM@Ld73bol{GX|p{RDrkIX|V#j0F7xtdyezAuIriw2$$zigt)Hn!s+t-y#iQ8nAUeY zN87WP;=(cJJSK8zqtF~B0RS3?DU2s8>%%zbv#M%bZz60{t6X6?Z@<&J5u747`452V zFwGpd>(`&}39jfok}L3QM8w-sVT2iymjj{1>H`t0w)>A~RbYP~E6K$qqtoRRBCgk0;b>K?{QyTp_9yI+ z&32(o4TR3;HnQ;T>n}i{3OPzMBCt)SvpfP3-@bmaIpz*d1)vJ!d=A6u{p(Ml62_Uxt;<{IOBNr- zFr3!qx-K{Gi85h`&QG7o1#?er*H-`t^TkXr)kIHSm>(c+*RM$4!dU7nCL&foB9SSr zd>D*jQsp6iSJNIywDAg{O0w?VFkim^{oeqwuj-OKwcsHW`( zXp`wJ#hg$ZhS`N7ZMU42AwoVBo`xFT+xgI<=T(tV6_)oe%(0v~J!XUmwv%2>0JjM@ zxo$?7bwRIabTfa-X9s-bVr2Mc%1#V8^oZtIP=)tH5ypW$3;n29%7N~$T_2`=2xi|8wW`O1oOPkIZIqlR;d)ZR?!sa#SGA~=2?RRB zgErxI361Uq$NI?C&>(q=iv85E%Z~5)X1PONMrC({(mGzOXB6l?^8L~Zy>p{d*}5TX zeFzVUKQ*$TWOAY28*BQqtigYAM+WN#&!$hyUmHyaB-kUM4r<8{jm90MtTTXDgI)KU z^w8?=8fV~l&Asdj-paMG;={mGJv!q!9aq@lF|ePv;i0QhngI9m-Ohcpw-06Vm4)x& zE+)JeC3Zz@xwCLcQ9ts!YG`|Fmzl3Xto~3DMHCSf5fK#KRYf0^2zLbp-uJWm1*0(o zYF%}}W-E05`Q3bMKkvdjI!28|z&#Qj+j9Ex;s{+1J=WK1_ocK>un~8N^Y%jnsDa}LOg;7^MjA&B`pO^`wfV96cqf&zyI${ zS*EISc^}5pFrPIa)mKT$bU4-mo}WGmr}g%3SZzr$#U+fVFrCtRGjv&wb`u`vClxm6 z^DtlXP)E3g{E`-0Qu6B1bvd|Yp$YU9${zQ32um0&g)#(6wl*4z8GT(QH} z*cY_>Vq)6o-~2IK>4jBN+?KSh84#E@JGxd)x${9%Oxt1(2XjOm7DN%=mUjRg#@Xt; z6qmTI&gbl#`bMtHHMfNbr}?RG{Q5AG51i9;k_exkzN;p`xZaE&C&Fej0Z>28rX3d* z5FzKxE`9xy=XRQN(?C^yu6Urx%~gaE(2sL*pb(Ku+gf9oN_gS5$!?r;F1TQi{bq06 z`Q>{=T$gKRBiQXm%u$*-*wTq4*I`wvooi_?#kuqt#y_fCW)<2I#Vzabt zPL~|uei#-(hMQaO#LUns=F}}DIz4?Sk~k%E$Jh3Kr@A67umxeZ6q>r_0caRcb&l}< zHJcZ=MITDZYi#Q7|9Lx#`!QJxwl{bg`5xLbT?j6Xq}kclDvNT$q(cCjf?EAkRZoOwv+>?uZF40loApaFx1_;T0aUm3M$Q?)gq$k@ z?>odA9*;gm*u^CE9d^roEe<}iCP8wTSuoP4hm<~f zvAS2XRHyuDcu%9jB5Gfj>0S9qguEwK10HPQB^I%UOB3wFo(~gKavr2VmbMh3c2=jn z=H^a_wwNTX5P-c!1i%>n*@CGeei+rWc}tuh0C(9~Du)oFPW#tRlv+LV*x0RvU3Jmx z7E7&3Wf+5{rqUvw&YD2%EHV8YyFJJCid%}Eb82Qj5kygd<6nJW)SD90`TImrZ1bd& zW90|nq{v99g3O61L2K~tPokY-@O~V*uNkygf|h6=Y!-40nzsi~s44NZM?)38t8@Wa zR=$;yr|zeo+NN$~$SdB(5fOV8%>Yg|~GnitP-op)e>Q#|;$7 z`TRuMTIjuM?%f$9pp09nJ>}&!-qxELl-*$mcf?`QUJnN^&VnX(PQp=CN%W09@qXvcp-Unr2c~FkLUn5>}sIYo=u?P)XHMOQPXz6+)4e zXN1t__T@uYeHVIIogMlRz&Y>3Sas6%-LMzfj8M1NpNPB*As0-DE(}(tYa^d23uhOd z3x0rn91autkYio9MMZ373}MVCYXcxS55r_sYctMU)00_=C=3JGqYGG_(abSFRFJ#J z+wI-{J+DPc)%dxQHOInM#ZM-c?*& zcEKVPqc`Wn95QpND^i}*JLfcDQPYHBc3#HQS%k?45aARtb42u4DK=pu z=a8H#Ys%9BJ54gDJh>{itKvTa9hja-j>JaxByg<6yvsD<9fBsHQ}vFL(r}< zV2N(cgFzK>-dQK0HsSKHTzk)YYkr`GdqWN$H^r$HruoSl+b%WSY-eJ03ZNKL_t*NhU!Tt7dWjYiin&Ks+#*D z+hVF{LIP?hw5CVzezR~2VI0OekxRJQ7q&d>LfguwX)}ftZ6n#T8+kFnisiG%xFG-w z*EnMfoygXH09!b0CTwwo8aEV?e6&|dk#)4=azWC@7_HA~@|Lt-wX~|74=PE8 z*|xyEf>7o<0n|tkRgG~oy#J1E^x{cH{>)ZU)yaEefm%+%hJ} zKdBvTLCVu5f>ItQ6+sn3B68pX%~h=$h8Y0H`642Im{s`p`m6Kp1V-eXAMAG9G5QdC zs>&Q!fYFh&&smZML`AaIiku=jqDD4y-k1-)L!1g*wbTqrg^@fuFY7hMWf)IDS z3rFOXwnY_P$?r690Wb(>A(9_va^CxZua}PnypVX0-_9M@!5=M0=6#yA#p2E=0Bsi7E)k zw5>$0pg&M-x5^t~=g7?`_ZAd@fF#27FuJd6f$9z+*g-1_&aRuo-}kz9wZG=%IgfxyfRQw7l-bV|Xh&zwup1QOap=R0>t#s{0>$xKoE(RCl=zLRfcsRD|yR8OgP zAFzO@Tb9IL`m~prXt@^x@@Vee(W22oQK_^MBi@Mt4jTNOs-v{~ii`{^k)ZGD6#7~l z##ptX2Z3uvI_wd(U08wUBR|I?R%&O@2dSLpc_$>rT*-PLTv4mmxcVoQAFGt0K%MgEoQno=@QlJ}z4gvi+bprlDR&lny!GtkmNmVm8|pR~6aT8#$_6BHMZ`quGx$Isg9apNPDP!c$zG^XR;A;O| zIf`0Ux8;pfnodvI(*ls7DRMw zu@wX&Nm9Ce{?ST#0I(iAWZWX|i5nu!Pv8I6w^RjBB!cp+ddbUyo!q-q zFuRelSuj4-2oS=~b#W()(kju$j{>U?NgKF}v#g0)MRu$E+{4bso9ikp0&#?voNySd zHqJsf`OmQ}{SWLp44R=?d+3CAK?=3-ffh4@TJCjYHS}Ncz^!#2kpc5Y*M539jRm5TTJRx`t6X*DkkrZ=dBX}caDE- zdeD2VRpTI3J4gNZJUekYK)V&_ANbZDTGaYap=~{^&Jw*dy6EnYV`aVd&(3b~`9J>W zzpWSHShsQF6wjZ3K&0jMS5BKBPpTQC)iS=FCm%FL=IDnB0PPs~^!@K8MT;{`(M+1Y z{br6&pMQ&l%k^D^n*~1C6Rov4o}SFPT)#%HSrI{Gy}eH7=hM^YxGr&9`t8-me)ehG z6_Lbg8|SC#{ItA%S#R$-yI>DOv(tzDW<-bNHJL2 z$89w!86r-X&;9FQ`Z6Dex^Tw)S|K8aaS~4DMU!E^4CCqj^%ui)=k25jztfh>8XrbC zjB3Am7;W896=$lSxFNac?|--6-fnNdk_+U6Y%B9-GmBw5lXG!htgr<{=SP*qDej+* z!{A-a6&|Lu*+}AgOJ&`dp9})<#&P@Z_kSJZdj0YcMYCXp2Yhq}#b&2hfe70HUrb$PdunDgFHuH+z)Z=Elhtv5Zyr_lH_jFqtC8l6;V8 zoS&T!?_d7ZTVU_%V~ER}_A^4*yEPvjoI7IEAy-ZWsH?#Aa01Lz7kro{pOIbP)Cc#2 z!^Udr4gJ^`Z#%Ni!;F-wr>DtGm7hao_Hyzk|7f#yp|5>Ws=I2tc-VDU{u+L~r$ZeMs#;ATj}CgO z$6kXT4{DX2bztn`u^X|=qwC>kjqCP^1_poeA8hDgJsPDCc))B&K_U?Cl<;@8GM1h1 zVaX0%gnfk)=sm2vIi8QtRnMi{10?eJ+(<2KHh>HK0e>i&aT+_@i5HJXysYV@OWz}z@RYdwwg6M0_{Wo3@) z92#m!)jS3!F*ikAKEV}P<2aqi%d;|zYP`M2?bb6$OPp1x!;&15=bVjyOL}xR=8QBw<-W{YqrNKJbm}uetk-Di|fsn92Hh(%u$O;MX5VLwLI7?tz_Y3 z&&71Hv&_%!U3E6Kh71++9?@}JtwsbyF-NL>FXwX#IXWT|Lus2(I|M{xW^yhJld5jF zH=9fpsaNp;WQh}S+MEyb(`WnJ)3$84SNkJYBGji%RnMP(5J_=eY#njVlM6ZCvg?6Z zan|=9$a$#k`!X@jaSO~Ue0up!5kzQQul8^X*Q?Q+E+8&f7lzZ*XH~s^{Tc5dx5al4 z$GKs_YL^pq6MD=~pPdg#K{(#tel4hR6W@Czr<_DmQKctk`TV>8LL^DrRApNik;L29 zw_)w3R5=Eb^TVVn%iEV>J{wEgWc{G9ynj&hMrHT7()=PvT$&dyV0NG@2R(|4$ZQ;Mr|fy&@#oG(a-=n-*w z|Dw4DszlGMbhT@e;#PO@ZF#TVcqBrg%mxz4>VeK+=f}BmDvI4mI0;9afA3)$qb&k` zn=&Vx`%vrqVVaQ~$4!K{+Z7OenCu|vhtUrs$7t8KZl<@_pKbL;=PsXqNO9w|ag0WN z1Ek&`Rb~CPZR3Z@2pDBkq~w3&)YRfY3( z(8$+D?Z_(VG3ODILvo<3B1T!k90>79oKz?T#;&Uyui2KMM7*gACniTk&ZL+oxV4LB zmLqK^M^oBs7rmu=jA+R-s5}vEva7uoZkH~t_o710;vA0(HHt;Mpy{?2?C?BY z*{b)={T^LbbGoI?W{8{tnF;OE9hTn}6sh@{8z-%YTQdLDlqlsGTuemF`4i1(D zx*zkP%{#P=>Xn&DEjl!_zB-F4h%}KfDsa7``SaXWUi(R8FP!KW939(I^Q$!D9Y%Fs9uCP9U<*>*mq(Zl;ZwWL)0oHgjX+4acDjQT; zaz2Lc^OMVcEF$ECsuhW9uoPzSVHX{xmQRQK#fI){SUfZ^I>w$B?RvqsWYCX8EYs-w zx=>rpUyp6v2|Do6cF?v7Z}bSE_w zN&PUheM;M1B$i=h2;&sjn*~TpUN{W+3&IS=!K%WLKsbfzRE_y2(R7%-+oBTJTekT( z<2>%)_RJqc08xQP0#TPK!+>JiC$W@vsSq4iffR<>g;2^GR+VkN^{ZQH`e*kH6p>gN zq;367+_oYgMn6nxz187diW`eq^x)z2lTjlo%H@7>)C@PzZ|F3Z*vQr)Df#vG zmX*V0l-n6e!M+Hz7_3z-vq{wuW$X1VgAs&P#XNHxTx+%Je5m=F*%(@FP^t>xT(H3m zB3b=yHH6{8$__*o42D3QTE4k??M?VsmsE5P0huExxDcQa^^mAI#u!pAE^e=YgnpQj zTwIqfbjkH4T@L>uZ|{{_+H>jmb|*WoNXF8f;_>w2=iZ zcqqliIz4p-whN00X-U9-d3Xo*aK;6h{fj`^{^gBbLdhb=44BLsqLH# z2o#2~L@U?r-x0G2t2o5kPKYYv!yuAHn|9?*Iu4~L#Br^SiUOa@!C2%59|n8)(RoMS zn{?R}q-pJ#W)57jPDxgeTiYOqf@NL@SoofaOU)Z2lHz6;Emw{yu60l0xH88SH#?SD zapL_@G9ShF0co6~4};~i1As9$Uw^uq85tezk$|KHr`bl+(xZ3!Z9l87?V$|QJWOZP zO>l|;o1MsPIZn_aJw;eVRp#?E5-rzv<#d>Ys}?;4fOVYmMsoL0CIseO**u0JTU+z* zxoKz0E?s_BVVq7rjMhLi7es>q?5FW&psuT}Ewh}qs&UYQZlQ4=#!0L%glMWFNRga_ zhm0|#^6{VwPv*-f`yUZ;7$+&#V6quLvn@u&WO}PDcXEbr-<vo_uG{uMEwVC*ob zjferN5~dRoE!Q_rX_!tmKY8~}g)O45p2h%RyS?>4RJ`G=oYyHo&WL1A_Ovb{qL!QC zyfClbA6Jp-hfn5+-~?ddi>1@9BEs=7=r!aGWz0&L&M&I^{^id|WU$3McA9H=w!FDU z0+&reY@%5v@PH^Ws<0czBFj?iJJpRsI7zk#;CM>pd|Gc{>9>fE+-?-diJ9$ulcLxt z1XLN4QB0j_@$&Hw>tV=pOx2vyv9z6Q1H*Yqk(o2Pg&YEMyrJ_xoD?)}iyabj7f-UB zN&(WgLRTH4DyIyDG7mr|VK$ec&X*VFv|is-WPN`v3^r%79U>RP0Ej6@08KVXDzu6c zxb4V!7Y64%$2Id=hMK|6( z0uZQnzHiV&yW&Bs3Pl9V?46u%?)77Qc^1pogaiZXSTCvSclSC^z^?6pSR?56KtKD; z1-IR$EmNgKJv5foW?JKDt0Iv3!tLPMnF;hT{NK&E$yrCcZ79$r-|>}KAeDDEde{ZY1i$++8;9;rePeMG2XO)0kM;|_dTQ|9ya&h z$$9HNXzfMk#(;cayu#+w&!-k@sTxgxm6J=$$*HAq^j&n_HIoarLU&^YYrVGEf#!my z`cPFZHxOZ_5bV2hEdZr+v+Vls*o%s~CDn%6k^#2G*WcVzmQJGxcW$ENYS%4{8KH@X zRwEw#7Wqiu_#1nPR8G6hv^?#`M!A5~{x{dih_WqUy^Ouh+hsXXb;|Glc<&WK=R9Jc z+Ljj}MYMOhEaOn|FawS-{NMlE|JXml z>-FvW<iztKXFc?Xw)?F z9w`tJI%g{fHf2o}-&28pv82u3%+_p#3@QHZ_kW$zX6LWoZ?2rk59l0kYbitJH-GgX zIIcFXw-9Oz0j~|Er_VoDG4!@v%hbJviRa-^#v*8ekqVM`-p`j$s`C2Nzx0R-^5KA- z=5294n;e$+FZMen#nKYoWo^1)hHT7eFUoZJG+jR5-hSS0@3!x{FaQ#m(8e&TqQ-+4 zPRwizwUu<-;wv_v)AL@^6*5Wth(6`6*i> z`@tW11md)a@Opjwz@&`Jq{GwaAN?@eQ!f3>uQ=|Yr= zoxH7(!_Wsr^23Paw%a>7=fh+%Ce}w4ZW66wIvHNh_GI6mYRdws&X-Ta>GJy1 zKbzY@Rh%CRE#EzT|GVw>zFc1o@iCoV!hE{D{-VO`@-Cdl>B;mdNHm?E<91uGZ~3js zkLaoj-UlT5_2)mkn)|34hB1t%wu+K7e~1eM09rdYrBr5liPKufA6$CuNA?*Kjpt{M zTPA3VkZb#*HJSbXAW%{g+8q0lR$TWarc4CFZwL>%QF~6eI>ylNkWyIlsJe<1AM$$+ zVfOoU?7c!lcc-Mi*P=Q|4@r2~PKaQ_LVm2C$8UMIp)+}^-e*|fMxTRl!-ac0PSc&&*#I7F>8+W7JHfpkrBf;jq>UM0 zT+&)d_B+9IPwMYvGM(_^Tgvbn8s1&@UMS!9?WDKi;9lUa6_ub50}bmMbS#$yQ^G$E1{;c#!fdGM4!vS*3uJRiK8)kFci zOo{gB0v=No+IoOh3Z9?UW-P!e_4v?UqV0B-N?_+-siubxa{v!s!>*FRW{}#)3U z`^Vw%Mt@`^zrW79ZxHPL9(T$S)!qRw?VTvyyp~0}Gb*+3tq-IqdK8lNMO*G}HG1PN z(o(D4UU%$(M>5H7*~DGTqb@5W-~Xro#)s+Y`#-44 z*Ps5gMOo&<+I~YuB-5tbQ0o2Hf9)ge?ZlLSc$ko=WXqw=DoyHb{|kBV$gS5`tyCVQ ze9pBJfe6Ws^Th_1s%EGZj$6$i=>BR)WFg(ddV7!SGK>@C{5IX*zgQIEEya3wCu0Kszoi~!ZeEMNqubWj!%FYkyeD9*|^sD5@N%H`?JsEb!JiYwJh2i$~ z=lY6pisT$pEvC!uE|%NEH`wg|hUq+>p1N~x{%1Nr87;StNlKX>ENjgwfYZ|_L|krf z!p!Tf2Bf|G@K?f7C8fBfo}D^I001BWNkl2cW85JTrt_!i{K_1`89fqD5UcaEt$qFCRXb)5hDI zAI9^iAF7LE_fDEV+cGFj)I(L$vRiSizRaAka;mX}0dnrskAJnT*X?#K#DJ=)(<0XJ zK8%;ozb(;~i0GEO*Zd`aS5erg1$u*zZYcyPdMfPt^l*iN3?0kaR!sq=!J=-J$;e zB-@Wj_i~P$5`M7gYS;E}WMbVvHF)4wA7Iw~o^f}59-*Hf3}frVjNRx698wyYh~;W_5bJJ|3@rf&$QiYV||#;al54$ zGgha_3OYJ)sntjt}Hq7-vvemn#ujxhYo9m1)hf_yDxv469>IK`zYa zPd^}0TzBc%_Ilc2plJ+r*9+`hkvX&-a6COtr)QCrSIc&gwSj z$8MLz{4p#tt@Pr@(`8$iJnB$$bm%SuCRZM5n9sv>+BNwA5b*Z)CHKCJ!VG9*RB}$U zblbNTY(I>&zf#IsNmb7;-yza^edAm=6xFC7x&%%@bU>(?QG2*40IKB8BQGj!8q1!Y zn3k&v?jeVuIdaZy!r65$2^1{nEa%LXfI4&jj`PznUqq5-#=LH~S5DD|v7SaPaKrrC z!|7t*@%H+Qh*15_2#&mkT=uw%Z0_vpHcN!bgBGJ<6|#X{Bzqu@`fbS`XB_ zH7A920)nhnZig5IfMGfh(?vC@iUAOS93o!7{JDnGHB~|r@1W(;&zDc+gDac|b0yi^ z!6|Wy#-`{kw&h*M%5m)8O3|$Q)wr!DZ6xQ1>1=1yzMd#wP&#-J)dPX3P%izCpwlc; z>#Bsq_F>Jf{s+Q1i;ARFj7H6R7{-(HgZpZ zrjFqJ2+Bo6mj}1~e#$ZShiMnaFrKPBRZ_Cl*kL+5=ik5nTGG-e69#dFy`Da#C1vAQo_K$39&A_ZJ1^s# zk*CM&i ze~!pj?Uo}=g-B_ES@&W0qKbWaRKAUrPI!h4SOVwcLIklxLeqhjP~u&xJ|w#;yWgX@ z1C2d6ETh)To+C6%)^0m3+zDv)TPL}kGu3G(`%9n})SNqzeIcTyI5UT$BWL{+0Ld;u zVa;bLMRexu5)jlKg)Yy-6yfdwm@{H5@wIr&ABYGZVb$>Au^rJuF!Gq72#W!`(cp(i z&N2r_i`^-r(0ex31M1)h1!rlo=-o?>NQl-0+!ck`RWowu`pA(QiWS~nX-8Q343C5t z2pR3zJm84ryr7l%si62|-#$@oL;^a@-m0Fk%SqP{p^pzQyH>TV?$?I)62OBPDZG;~ z=s~)xt(sTp{K#fi%rBQ}#X!%=QqUD$4N65bcz%-J@#jn zBOK0*F^G>gg>USGeBVU#W;Y4rWJeD>%cQu$^(_bPKxGe>hea3=hw*F&4x=%}^~#(i zr6#QgP}LM;5g9@eHy-HY?OzP`YA2@B&z(3$=GbG^4h&fp1z@cV1+C{qR?*Y*cb3d) zvnzA|aN5@E*B`Mc1@WKQUT14X}Pjl%v@98$(f+q4yuN07iN*D zs(zSk$IXBnL*a_QEWk4HPNo9g6)TEIv^sMMLKOOr|5Rbz|GqG z9HVgZVF+&CZtpwQ6}BN{Z~wPV!3tUD2g+Gp&PdH+oQzyp@H7pSlYzQKpnwilRg*dV zqi(t0z;1%Sr&n!A{pAHAvyCbIcx&hRT2 zF4XiKXEdaNoExUIRh+daXSlK)$DSSNT*cT34WtLGk+0Q*QMG$Ef2km`dc-H^cRRjF zT5oE&0CHx*OmRcJOXbWQl43*b?AixJN!DE}Ac84f%^JvYvu7hu@0#vUGrmAXHP2cfawXkLDp?9y`FOw(Vr z`_}oP{6X_RMC69)l$TL*L|)Ps?e#;f&y$Ll@cM@NNB2^lA3d_k?MAC@p?YAhL4Jn?Sqoc+;*rt`=CB!2G-Pj`*3Mnq->C*4pt3^m!^MsrS6@)w4umYfYsh88!r@oUT%-gyk;OXh*u71Mx_HJZZl_cUj zMFiVw?z|u8Gc1_YB0F+(*!l!S4i!Whv3Q5`v!`H0JyjK%pT6U?-uP!#U2E)F12$3V z7TB7SoC`jTs=D&m40G_{$bm>b;1fAOLW+pw!cf-^TS|=9VO~;D=>j)=7*7VJ6k&i( zIBlFbZjv_g9!lU;dj_&&Rf_}^5gj^bum#h+NSN-QJyTt|`8>?$xZJ9RyFbJ2bQ8PI zBzPKH89@$-hWTvARx@IoPN%0f_gid1@+A+G;R}Ql`JvPe#IRcWrU<9FIPnIc$y+bl z5xgCY$ay~x#@VRB5#)S|8hSo^M!%ZoRxoxzTvAS2;z*yorUaB3G;1?`g)ZSP+*nIWHq#I$>dli6R` z2hE;mVTyjJ;079sX)$wDheJ$9i^!J3#7Z$=rv4= zdxuHkt84Er-yylNlW5=dQTGY*2uB6{?!t;BF^6?c;YQsBlT>3b?s2}>)W!THYcr?U z@ItW-7!~)or_)pc?Wme&S3kl95Q=TLQFYoNK>G{Qt-jb>JMJ~Ta(J>>_OuKrQL8KVR6#XmNTfDl(m(!gNa8s;U-Y7`Fw9ybHE) zs~PIm;^@MDZ!4#axFOB-Lcs<7Q&4Zx4+=BLlb zkLPX8Y0ldC=up6YO%X7R!*oU>B)`0W-Ill0(`O>GqWt>x=k~NYcYnCzZAFC3r{B6^ zx_Yp(o_@^KLJ;&|#_H&!RmRDEAC|xUvY|E9?_Pf9NuT$Li9(int z3QlH#vH#T=l7_}NXgH!9#wkpvjau*~xyPEE1{1{}ybC=zKUmeKu3Mq?F?NP;ILKyxp81=BLjH5K~lUPMftx`}huf zt(Nz%mfz-_fBxYQ9Jjcw*%cl}=e^x%i;=U>CL%<1`TScO$C|h!J2gcSVLUxK=Kzp7 znW?EJ0F?87Kq5PIn~1-*aQbpVm{n2>6GjXrbFSKWhUsiMdE~rvjydJ4s=Ka?RZd|# z7l}>qKGMq4*n zREO~t##3D1Ypal)N2KNb*Q$^>`a7+EyE_gkIX}!#^`2(Sgld@1ew>%rUn;%J4O6|s zE=(#(QuO0&4JS^CsNF{6;u!>$N{>^v_0LiTMYScrA*0pThlt@e>h0vM=ae zI0HUlGGU*GjD7LgcJC}k>GkpVz133DYKP^~eWBvetNyPI0bXoQCdQu-X#m?rzXdTYT@m?fosfb5I}jFb^)2*~`lD zt4U95AC)3 zxwvVmh}}mjrScKaL3b})Q5_Yb7IqE}Q_pokvOCF7?*{3;MmybZedrpCu8RXLH|Rn8 zM;pAi`z}XG(YHlOe>pX_4{gQcp7LND+l9&IqikIu>x%Rtce8s)<$ej$-mY`ldh8{w z@dJQ>|L}Kz>-=zf{?3X#bF`F5sw5)3EdWY>K%^Z1t(tw%l2p>R-r~9_C+1|5iZbCF zt+xpxn?;sCeNJ(;IV~dE+4HXTgycj2g@^eR!ia7F)%RcjHLkapAOEN#oRTWv-oDlx zkUIMA#nZekewfameo%$w?H4hKRObJgyv5f7v>kj9O(9K0_ED&&OJ_{8#?4~lBa-{{ zu5Mu5k%%prVwlfqGwOd-+3CJg z+;XobWAa5(dimjxxvWHd{pC;21rxJyip+_(Rl1X-Eh(4JKZbF7{rOK7nd8I2!jh7~ zu5yX+>z}mPCw4xZFdCVGSy(Va2LqbD$E^%}Bnhv{IGVe*W!WDGPH_ zmF4@GtX|A+q6;~1nQ&Pu5;ql*w2h~y@$^(>W!dB)Z0z!3e!|uf zOwI-Kn|*c*Tt6g+$1;qj`N6U;3&6{EgAtFRM+L|eDK-VAK~Bp zkE(`YbYWO;?_hG=Zs$g%VLqj8sR^tW$+_LG_1xyabx^%OHuo;$$6oI4k9;T>$2($M zKI}Y7GcN&^y8%@_qdbhDr=AImOZk2&CD32peJc31c8x;;an`?FTW6v zz;1+qyB1V`hTZA-+cw`O$8`?3qbeSq`415rdU!8d2k9^A?zTa@iEC;d7z7ALCuxPZ_Q*LsUb#1q3M7o+X8yLkEx7 zT8~S=HdD@hE%%{G<3R`OTM`&cQLLYRryjxbP%7a4f^FaEAOHS8c9L$JtR-~L_|%-@ z)92r1C%f==d#yLg53?OjtdJ;bqX>ZW<%N8(AbYb?q6^kE$TTk(kf^B zZk%G;ZZ=p&Bu*Qm^I-r0&Uq_&j4_>_!Z@$XwKj-2MMAPecU-Q{4=xO*+A=Uzsui$; zN^&ktmuCf7-d{_u%@oFYy}p@SyoiJ!4`8zN5kRd^aKGNDrfnIf(|CH4oV2wuCo1A> z8>iPdTx!sSr4BnsL>yyH`H(K}cRIh==sE{p3zwz^PM4SbU_eHfrFAhSy%l-6xs)fz zt4KOszH1h}>Vh?wh}uBzi`8m{*@(v9GQ^s&Sm1Tq*34M?PZsg zv>uOaTFGg?yoBk@MJQkoPtLyu6^lruT<(n1$q%CoQx6uA6tAy8TYWFWl2QfgX17TW z0u*ynaY_|RE|My~^guxEl=>>7<9wbjpH)(Ji3qRPS5P4rpokt#j-UMii1*dG4ga!$ zJVihV<7{@dbzPTbIh{_!Fqpv!0FMw!?v&JkGVRKS(T({+BD};qQW$jzfFi{1> zaXwplr>b{*TlOX)Ip+f)2CI?_LCqFk$x&b7+xy}$%|48Mz(BtuMH@m_e6$H0K{4-E z-uFiGykV%IQnjd~bJ<|jn&_YaB22j^YZ8Wxp~^WDt%Xg+wqGg)t-`U|^@4h~Ju0bc zf=h{6k$&WGEG}CkKFb<03uo?K)P>$=YR0U}C9UZ^IkT{sUbPE7H=t6`+vgbyOA2P}T7Nio4(#?I)y|Q`YWI^;)by zAB_O;=u0hO;*Z8@S+#4`bWU&B+m`pmHx|Y+Avqw%Ozr8)UrQ$L$U&7Noweje@`~tk z8d2#+QuZUFsF<)8s_(v%30l(SNzKN)4EG@-$cB3SXkv5JqwBrE4M3a8HK)CIZ(i5u><#h?nr-AN3B{2C z2!ykSMjHgq0?s;Jn6}ax(em8)aK|ck%xAsw827WcA~Pp0JTTmY9ve%nnrN$ZO!qCU zqq%vfRj|ehIp+mIg@qVFkBY>)LMnW$39nPfEa1d@8G;&XqkL0++$BtStOa#sOjr}0cHgrbroe-0c!w!BtZFx! z-DwN{VxQ!$dfvYZwzBQO=+c^C)kj#&f=)nzP5)}_q_ExIjG6|jCi~2lmN2U*W_xcI z-vinREx`sIFg{Ph>Oojp*_v|ZN73>0tRj|H>_dR!_Tv~+Tx&hljpDO3u@}cf36tZL zuoyf_N;m^zm`>UYHHi?=AsIu+N<-VL0kOo{h{d?b4uA=&v|e9T!MU8h-XRn)#Z^)? zaWF#y26I5$slRTe&fpY?NHk1m03bggk)%{ncKJA8+CeqH+sIV8O{zIv)`!uk2xg5^ zVdiB28N!G}8HWv^h$h1m6&1BF+bj)5*wRj;m5`u}AAA_?EWDE|kwXBEAe`3g zS47LZG5lOQ@GHnURWhfInff^aAoP`Pwy#xH%bj=IVh)i=ShjUBS*8yoqKid&XbVt2 zbXxdoN)eX0t#$hf<4J}6kb|!9ZdTGc?#blhoZ>MDW^bIW7X=$d3pvH*{fia8pj!@0 zB2wrtBcVc=PUV3iA}S#Poxh?5l7lYq*=?ed32Ok(k4UH@tdWHY06As$BzF5{r-cz_ zL@9CYpa7DR?PMZiJp6JN(avdrmDpGBTH0=AIW>=?&0O<6v)ofG)G%Gp#?RWZ~MjwAm(#L^dmRVNg+!q$(+HMhNYd z`YMbF77s#1q5>&drv(#&nrJ%*ixW8oP8&l8);-(|>#LFgUE2r=iJSl^=O|!5&UU!5 zUIMBb7R2-p0IPK8Dm%v6{mOc-Y}K%<5$y#d7pw_WopZJQl?^=3<>{S001BWNklcs{t}Ch^LtL(sA~}zH7fNq_vXNr*4;prY3yvSF5>1mw*)6jg1{229vk#-H+4k+0c~t?)#X56hPSwGZ z7gm5Ui~yQqtf({CTlI^zX4{30+k7B!gx}!gLOvT?8<9G?eMsThKPdxF!8#zbvLVy5|oD+E~gtO6U2 z-JYzh2zN6zH5HNX`+dy9DM4*<4FwUkd8+gt#rclpT-WQlN;Ny`dW>PA0z`GW9RdbC zL2@}7H|l>Sr5KmoezPMofh*G}<-%yMWrI;`7mQ9Z$T?<^q&z9d&Gfx-w&+BI4NS(| zA5P8>+rbO-ie#%+I^V}IZz3e~uIu)7Bzb3MW=P5BV{(mW%YCQS*pra*X_pOz*1DKm z!AFy=TmlP)8TApeEU5Z)WZ!7Aq6clRkP`r@-7=c@DCk>RPhQ1GseRU5r%V3%)>3SH zn-3j7*-Ao6m;W6!s;+}96Bpdbf@1oWT{#!9u}w-LjcS(9i^Hr}+k@YqM%V zz*yg53^~mG;kAIfX>!dpC3lVFJsT4u0O{gFL_lY85U@5RRA~wq(~Nz6*e-iS(wew2 zrP0PFTL>?*ciKS&YWnlo_JQRw*agU0ph4z8KvruDa6Lemtw2nr1*Msv4F%FzcOC-~ zcN8%tcqe0%8*NeZLrT9@>p2l2W6#!{Q5$eDL;efY8jQF2;o+9RG_;0saAfhJ)2zB{SlHB zFC3?J2qh_Y73__(MPjL$XMKN_X#jct@+-0$C|KRPr3wCD|I2@?3UXndr<-#gos*Q9 zSyC_o3lGvT1V?Ns?H73#=~Mj2+r$&J_#!+9MyseEs@Uu_83PVf8`l^VtnYk)&$u z{FiMvXoJNc{CkqZtdF)Pr>7K!WqSLvheZaffnqQOg9vlFeEgkqZSw6%iv?9r`fDhk z9BaphS%l9YJ{NaR3=3MhpR(*8uynDChTaaCUO1+(jOXX^{H%M2rjT33oDcO#?(*?> zI{0$FC)X<>meVW%MBQ34r;UI)%=gtn`}^x&k1Woq88U+)1OVeQk@LF7;!3VvLn2j^ z;=BIs>rcD3ha5Ved^ZAOn68`>c~8y{#|sE7)6E9qO7Ll@Y1;V-%iNlFtoccfoYTlR zvWLsPgJ(jHOA7OFdMY#tb%i(8DymLBAKo#BSzYZG;7&BZeI@6+@hBqm^(&Io;VKf1 z$LDT5w&aoN_7&FPz*0{Phm-3D-}UPLK|pfFKEccMX01FuM{*M8emq)?TuLzp@B72$ z10YITLYSBPZ4bl|^jzzGcX;{;BDdEs`gEsdii_eATubfP9%P+E^3M0Z>-3RZ%;+6N z*mdKI4CS12J}gsQCY3(vV`YYc5-p-FZcv)&!S`d=AId$|h=w>{Ri7fv)AbtyXdsVh zH2mT8^{@Xp)81Bl_TH?ZweWdSKACkpcWsT2v1)|@#thc<&6D%Tu;W7d!A477w^u-vef4eo z-e|slg}Y~Yd_hC6DQ>vRN_{VlFOz=qmM85|cuyV%J8_0(`i+}p|F~DhZS% zEPR($S40Ge^~&a>a)UC_uZg%FK0V5LN-eu~F0Wrsa zuu`knOtm&|8h)$5x`4CtSH?#YP$T0oO4fT?n8!6(nRG}u}0<(EuyOU0D_H zBe=HJb#a2jcO&by*hO44HWq;eU6?S(;X}}as1m>O~1@UqB+HO|(a3ym}t!(#pEkl9n zo$~#ir{_H~fOfE3qY1*+@{frB`~Ub~m5;3xa%IuZ_m!HZzkHeA^ zdM%U$iCX_DIqzI|xO~vRjpWJoVZMg>7MEFPR{&rp)9HrR+r;5`(K26U2;~e5BFlW^ zl>BhO%->T@wsnn#5uJ!Uefk@fLa2^|GdN1mzetWBpxFCcC)(tIQ#^n8aXfwCIE(Of zf8&@^ob8JvlJ6w(TAK>RCJdP|U+maA@Y5!~S(syJ=M9aSSA2iy$D_96m-!mz86P64 zay?;Fv2Hl{;ozJn=fXUTa9k$NQ3Kw0T6t@!BoCyw=E)Y0i(UzIet+_8W6?=+O6ALs ze~OC!TILw0ErCeH4F|*T*)cO8y2&Muyhf;V3eIH{HgF*2qAk z8~`*#J>A-FuV0<_S+)xN@CDN{xvoDxeMF>O6UP{q80M}&_^!Xc{-P3gV2euxX!Z3H%R=(G+F=vK;k@+_o^1mIwQV({C#FV(6^ud z16Dcx!|l#*FSV)oekA9|<5`$rfBDyq-r#Nyx&QlC?iXnyNaQR@M zbFl)nVC{61k&JgP^-6!dIM?02{gl;|P5(P}OCYf7;jj>1tJQ8s>MX>-?9ai-1_j}6MbJr~RRKc%_5 zs-N<4q8d~iI%s=3Fx_qa*QNA$5q6Fk^*ywHbytB=Va{6a5?X9es~m4WIJVB#JwL#H zfn~!qGcm7SAe)V8 z9b8&Ko7J@;^(JPK#)`s@|MZXl&DTX^e3WivjsPS)E9XGc|$*Q?n|8P~hx^Ad84-r3%!+4U+mon;4O|X=b&l%<^XO*pe&;Tk^ zEZkweU^(@^{0G^&cI^U7&1z1vK=IQpWlI9WiarH$D=RB~8q~Z899G~=2;j|Q$ zhmQK3_ab6+Iz-79i*njHoS(`0@-aksneT1pXAzeoz;L|i59Ao{Z(o%mP!pJQqJ@nd zBms*KqDnM;olLL_kL7sz0Eo+UaPF+f*|#V&$ma!NvvaYQN}oD40-DV{(4 z9*L&wSDn||a8aa;NwW0|bzB61c`7y(F<~CzqjD+^rw{${e0%*_I7wmw&U&JU7aLNF z3&-I5v9v?<@k}Y`$I&Z*|<>_fJ!t?D_2UjM^_P!kN znoDQV@SM_kyo{HRahZ~V{jv-@e}2WLs~{}n9@%0mScD@Yj^}4`-gk#=0+F!Xh#aC9 zNg_$pAEQ1*tjYA^h zx*kE(&M_``6OH9+L2r7Bsx6T5_>@(Ucz^rFxvm?J_1uZ*EWS<5)79+KCHHYWKDTj! zn>Ug+vrG@K#$Zlt6n+~vb;ALXx_&U5PBX0ICOy5ZtK^#un((IdYFsm7 zf=y;l+Ic`!O&Q9{WNK$Wu9~a8)9=Ql+3LYW^iyn{?~mon{^7bQ(MqjK&f3Bd7FlIr zwiB}EKnH6d^v>xW0TKvposk)~lH+EOMWtG}G8+GSah5qxSM+C_E)g+ zBAZD`CmKYs>Yj*-fFEXFt7v$0-#f=CFXIgGYfx)g@8jy(mX!rQXG;Ny0$dF8z_KC8 zx4!bV%pTuk0q!*-8UVajtMr|HtnIpEZK18P2`&Dj^cwR=ReuG+))6ARVnAH6_354F z7$RZTPUme$>3ph;f;$uU%8hwJ#|IPMl~^qLNcI zeNG)?NToB`><-QQQayH7xr%Ns1Rn1fn2B^Vnx0*2OKS-berRx#Yn!l8D4ErnWv>j z$$;7}W%F`1elZ|`gk?s;Y=i<}s45I-BiRTLa$x}=a(e!ZsE2xv%Osfsp=r{9q}557 zH5}MUN_mgt6qot_YH)KA%>p$QiNV>ybsdO=`L3Tpm<19ubBwKHNl|%r>?5kKa3Vp( zNBt-2+RF)i4PX|L&|zB*OEK*sTKru~EDV}+$q7l&IRbIs=c6jQe#pzdyqLu(@I;xm ziUkr~BH#(Ujz^vAgzV2X;>!Ep_IDz6e3SDjE*xWwOFjp)tPe5h$Wt#5-C6H@LU*`) z%#Z|0mImbokW*4SHaV(qAKjN6iU@H^Dcs+_mT*302;>+hSf*>1>}j#f%$$Q>i3p8E z;XSB|P-?Dtd0;KairJQ{bHJKLFAjSU;1p7d)9p2dIprKE?>j(DDP}1daY{x(%10mP zeBKPBnHnR+5Q-bpITbeqPC+pdRetO`B+~7-c^_|gImju*uyVCaQn>)R9MwWn+Gb*L zQ5FKMj4c$Ue+%9o4m9m;yj=`Ggr8H*Nuqi2jsAX<;E$c z6n9Vt&gEk=AfW5|;c(VV=exmd5Ba}o)z-*|1|&rE{Wu&i(;FL@h6rYTO}Y%H2Ly_7 z3Cm3_p z$ZPXT)KFEewJMJ`=ubU{OT#zNf{A080BJm)$@#do7ih#Vqz!)Rbq z01rc(&{9Sf<@bl%E23RhUf&cwCFpB4A&Md*k-A~9P6Iha=exo6gC_iGAJrg}>#}3V zX`V$KkJ(RYU$z{C;I0V1SA2Ng%b8_7G*f#f~ zDb}6UTar_CHm!18hdyT0H|BAa(odZ8b?ZlclQ~r_>Gnj<3vvWG0gH|vTG3p4V zxHY(_2Ue00yXk_3Gh8`;A|h&ulZNy!2%I8D9RViTfmdvx0jp+w4najdwOETNi*6de zhpd(It1!+sd$M*%VKqYA3=vv{2syIqw)T*u2yiTKOVJ-ijk06Rpez$1$gfyoE_Wl# z!dz`pHORNsiO1UVt#ogzqf)tkK4Ex!aB6!=^EY-?5PsiYL6ZE!KOK{3klV?=JFUfNzdX*4eQfBaAXwes)H z$zE9layWnJ59j;!OF7vk1;cBN)eX7zW#;ixAy^QA<=Ad0G$!k#&M9z1@>Gh|7>BeI}9(_0Z;SlDlwP#g)0T7otTS0lgy=KCh zCvyGq)b|I~rni2H;$(MSuQPu_jLV#K$gi1mzF+1^B!%f}98Kn=vVNqTP>PMH5_~_L zUw)@|F)q_Qy=r;dA5L92q!>ia_2}Nd{?r=DIfb-L{o&jnPGOl;AfPTI{V<%KZ?8WY=?z4WsG0ccv=qx> zhAD$6w<+Y>WYhDsMum;X=WaZiP388QVnpH6lg?l#XXyGEG(`^)k58YR?_;<**LCB$ zY(Uo2w$m7X`}yAs^YQY5eAf*}5KbvtCp<23x%>Xu^`ky!^ZivVJtFe-@ee75WqJeV z7=t>jwU7Gf(3oy-tvF5H@ytn5^8G-rYiT91F&!25W2<)$IV5uH%(3K7EN>1G>l}=y zi*tUS?ll3193i1|oI+Amp6~P@`F_xaRGKt#zN?UbJim33aUicdFJ!yzfCEG z`DU_yF~TCY@1)=E@?6OctS3oCmmhx5DW;fGT=oO%gmb>RC>ztTTF$9`BG;N8k@Pz2 zX^*pTV>n!f<2l6`V>n(uSl7oyrW}`>3bizarUczciqs9du@I4J<+O6eN{-ICU5H6- zD%oq{y8iU^N#_M3tSbNce$}IYeP98)VQg=`h8H&aGXC_(zene8-+qo^diwY`d2$4R zxZGcFufMDk7IPXCxq4l;Z1wz=UpMd0h@;)t7X=BC^2#LIQ2w43Xh0&qKALL{tn|Fku zI#A}sF?8dp8;@<1%m#3K1J&lhfcr*NX%zi{1pu}=>*1d9xAaRlp>Zo;az3$2m7F61 z2qHsMTu4o&*!+_1n>C-)n>p`pFxbO)v>@(WNN)dmp_Z9S_(5$funua=n@uh{idek- zJ55kKTAr%Z{CEUx5VyFtJnlGCcfVbMBw!nT0KEQzxNpwTt{N1kS0-s~!wuTgtH3*U z*H-Oc{LHQV9d~gJW%WH+b&;rAYh=%QTdN@uVc?cp*SPDk%|~fQ^nkLBL6=ffZIwY* z?38LE!SY>Q^6{|A+KLE z22dLdvkfy9SbOuUF3lc$QwfS~EKRky5qRt;xbOv zw|Tg5CsF+!3x@0~K}u6+zqVSpdD__!wp0d$RfPSoBwjvP5hSzV*Eyk$R|i)PFL6r+b?B~S`PAY zxu<1z{o!4#LkU;P(SVnae?WB0{gpXxf{e8y(d>f9Ju%F8-wns7AJlyxmTA7dwO0yj zqt*6KJ(3K^Cr*h|Sm%B=Ua>6jMWV~g=gjTZ17_L8zIRIP$Fq(H0Oa=iCHI}0eDiJD z#CiY;^BobNfBaL|AGD1e=DP^TWpQ2Sjp1ZBY`(u~`65bl6;XZ1^XEU718K^qFoO&! z4%>C*daAu7A87^lPUX&bhw}#jnD5^>rl`i-!kdLWP6x7-aJB)pKIF%j&*$gQ)9vdr zT_Mxg3NTN_7pf7UtV!07Bo8Jq{cF#k|C~F+iaoo>IQwqEEH0SdzCsgK@!o%&_lOvl zMW+eXyICW3v}@`?L=pQx{@s7hDWo_Hr`zk-X1A2~u}wMKZ}aEn|44B$M?@}jbwH?S z2t-I>33gJ37T;-fIwJEiY z;x^qBeWB{wNGk5g?ZnKy#?}dHyC}Ih-$eNS_SOEfh-g|Co9c>u=bTsiS_zSMz8lX^ zN@lQFM@hmGrfUdOiVFxh-vLpY@94bmM*xV+)RO=D@!))~1+KFCfSfRAE7~gFtC>a# z$5=WjQ9qc-c)A=eAL6paxJcTDnXqPA*hNE;q;4)wNw4-!6CfoU!;@2tzVqEO-C7#E z%5a1^ER+7_={{Yruj4q5<6y6B=aK02^wD*_-!byGy;S_wkl@m4#~pKHD|lV?ogWhF zGZ4&DX$+HytvS2RfG#%cLW66$K|5z*bH-atbNd}_7k;;&(}-@@=TSQ|)<3s=iuQzF zz5Vq}P31sdO{Lh(9b1-pKKB1gpx1uow?hnA^SB>%)$-2IE+Q_@v!5)=m+w&o-uB2B z)Bpe=07*naR5|9dW<^JeGNw?37alx%W=XCVP?UN7bv-7VNDN zBf}S|tsi$F1l!WQom9#0a#h>@9(%C;y}zviyZ>Aif4gn!d7h@o>ua?^>t#>ah zKKe{bm02H2D4i(GTOGF3SqnwVdyHx$0qg9sSORj!LN?ZI1Q6{GDJ!eP?!|_OfoN@S zwbxe4mMF5qAjo5r0k#?jsWtQ_Rk0Y!-YaDHs%P0JS2jTY@<;#Y|NP%nYx7P64b-c! z`@6__?>ja(Xp)pHWrkVStF1{QTx)ZX4yPyeY3h3li4NzNk|(EDbk$*6eg)EW`vL+Q zF;m=T=K4~0?dejaK{gl=Km@JKs?nPqAob%B5mN{vGTpuiOKeTkx&2$Th4n0>1(T_Z zJKvAP;he&fQs5X;ve+{{G5N07EHqi$eaa52g4+~>u=L}BoYTxEbk1UM~ z56W{{iK&e9qV{T4NgOXfAQE!`VRC)hZhU{3Z{Kd;ep34c*cANUs(f=Zin`$-DJ71p z^M2lH*7-2#ytgSYRu?RDLWJ@7Ouk#DH(@DOt5x%f91^vwE?dYU;}}WW({1ZK7GY+s zt^gp+lj)?`8(jUs4I4p&J<*mLK5GYRb@$@_#pK^#?5aDIItM#jK_ljcrEttKbE~^?- ztE)`pPvr`0Y{*tBDl2ECuvml~vq<8U4wnyQYPigIQW$;BZ?eacki<3(ASb0k0m6?wrp~Uq(qWt1?&t? zK+<;{sbySBAy;4@K=il-&Mm=YTtB zKwOUmBopnB$axmF_bc<(ZCl1mO%{^0wb8mRFv*Ot(p({<)ewt|Su!xkWZr@F;D-^KQfoFCEbIU}3zmfzdbG&bUGo6zhJYi&XAowXq!ZlZ`F zE6GB|>(q97^7&h!>P?%qg$*wv-y`D&fJ!SJG|RrG7DE&6lRa(C8ndRNFv|mRP2NMx zRZ%XRvd^{#XQ^Tjw;T6TuUZlBPVRa6E%o>)8KADiUDmw zRc$EhgXD&X1;{RnAVH-ztr(Edw7Asj0EJs*9u1^~vOCGnTNY(gV2vt!AH?{m18*j) zRlbKwFKO8Wi>$Xf-!@y7iHNb~dTKyLW+Kt!G1ru+4e_oF|M9(Dp?M|wA_!`o(s={g zTKClvRhqmO_grGOvLm(iLbUhNcRgnTA)8VkV^}byVzU#G>Gn+@6$>sGwpi3$IEVRO z2L4??Y5}9KGL__I@hZ1P5^N|l*#(?p00c=UF;yEI>_>OPqfOoqV@U{_?{D=v-(<2k znV(vCtv`&A??Ax*U*`}pEK^w}YDd*f78dsX0RcslPO!3|3tczp6sOb>k}E2`M=>l) zxhjN1yZyA^1xM$`@dZSd`M!M!iaM@Yd96$X>j9C4rP!MUWH>yPR2M+(hC@G|m`#+M z;;du2Qm8>2Pa&Xj#FWj#`g`R8t5KcB`gl+Q$^bb5#J6AmMM>rMm%<_`iD=DXqSLaT zZH!SGs+nt}B`{f~VsaRzn(6#Q53p(~U{1N!TPzJ3THU;;>>KSJPYpQ7slaG9Mpd?< zc-@**eY(t(rkd*M#C5~ra!gUxjLDvqOif@;3PaJ)?0oN4uZu*~nJ7twvlSJIe0C3K z!i(E9(Au`EMWtuHl72#RPJ}SW#g*dB*b#cW&HIQkE^2HqnJ^;kyP@k3wfk*WPH83% z#;FL?UCqH#n;-epp@jyE$UI%OrXlD2;VI8KSpC`?6mLmIweg46uex)y2NCC#2pBa{ zJ$E>Sp}0a73BtM_%2k`LUsY!`L6~u}bMK}mFn855PTcsxDv~4yQHDWg$k(||ShjU&?ZKKfTGpRIx zA^<}hL~8w*6eTiwkJ#&@no`KI?W#1y7=uV6(kfQpdZK1u)z$lT*<`N@?RFAaUSwIq zuInYGVipnR#H^pDb)?qQfLOJwh|z95a*QcOjscS0!Wb-qp!^#3qH+q5mvWBN6ICIn zxF9;$bx6*4ec}W$3L^-+uJ4CaDpU)RR&Bhmz=mt9PR<&1bie*06eJqP6ClR0Xl=u67GCd1nBPMQRt`nVU2c`d;p;E|(hY~FPk*#-q(F)bbMath zHwZdFcsv)DEuP2;Qi_XiWVsV=?|yP#n1utUYBb6z>KEvDcUICohuz=`R zoZcpq;^AqqDw#z^;Gple7Tr(;5qV@I28Uu5>8Rm-NllrkSAzyO94~EimDuH@238-p zBr`maW91dsG7%bOrY!fXjs;xT566qaLt;>Vf=(l3O>GorBmi`}dl7;#I_E{ebsZ9k zOzn_GL?mqyzV*fdh{$yPCL$bXVM!?-FCU$CI}J#L%?TTr5zzTwx3a{Mb7+HDCVK*r zn4+DjXC=M zC>(VZQWrVqGfI9zYAZ{>VA;k=t-!*fJ{I4rT8CqZD+Z|=GlVP>boC9gg`uBv`)b<${d{wyQbKBSVP#iW&;8RV-1rEN>X`@s$J9jQZ;l#XjNMAi5( zCrxV7KgG<);$lBVdD-8r1s=ry@3f7Ia|0XO z#GYh)+xo_~r}EGq-%koy+1s%;LhN}i6f~4#2ij=Z*IoU_?XxRJZ^Y}lBTv|r(JlVJ zDVy-oc(7g%Qaee)jY&MeSxZm80UcB~6dI?djC?jtvPVy(AllrR6QVS;v@Dg`lLQ0) zTC~fy6_3q=gcTC?-HZjO?aKNbarKS=8flS6T~S?EvNN=)q%Pt)Ozr)U@YZ z<{UdFmnRwd_6;0oyg@8Lt!ABgGqkVvm{|=jHP63w{56q64OLV+tU_+ zvYE?9(IaZ`Z!21@`&l?^h*nD&MDU;fhyOC;D1c)aPfv%-53TAm%vVL-i12VYarU+s z7qCf+Q{r62DB$DM-~Jm;A%$62M2gEYPX@GY+T7(aMkLn_AQHmjedqfj2R;Ze0}%jr z!)Uc|N}5eYzVG^BIGj>OL^5;NE1|zbB=tmxc}9e8IB<%se;JyzbP#dv|muM&-{j3y9h$Wc@sIijtzchGE7A7@A|5XvE9F&jmx#-J3-e9aqGCdo)#rT2oZ>v`W8j=8 z6NvyiM@TG!Mm3|7SZ08T{42kczjB6W{z>5L^#Y7b0S4(`W^ttcV?R2@rQJU z0HRypeEa76u^$d8#*{+?RQ%PxyjxjE=~#1G;xd2!+kZpOhxsa;-oF0)9>o}>(luEV zU;xPb;rN6(WX z?z9v`tAk517O_v+=(2qRQe239v1Dv+HvoM6{eQ$MDUgp-5=f$y>TC^i-V4BTf8`Xr z95E=&^K^4=|2j9q0!cBFbI+guR{1S@AH#GF7MTM1*_@hMN`-e;tM!Lt*A1>eB0vgL z?jD&Vx*HEEhA?L+rj}yP1L|`pVY=rtD0bt?Iq&9Q^j4)k)Nh!v8>V{EsH=Xm>uRke?LPUHu=wb;i`xTkC6vb^D^4E9_jAU5l zAySjfYK)nD_psQ$vN?nH%g^RD$*VowVG}@z8!7vH$JOT4+~(xTgYG^T8lu7`S^7;PX1w(9g;Dr@=m_bQ&& z7u?dU3M8!dMpt*DUIO_ov4tS8F`4hY!%!YS8)5~8)Pmz(hrcu#2%tF1vY~6o*?M{_ zEu0k9&98fYn#;P?*)?J&SxY;hO0lfnx>}9cwiD_Gv_`g?ElE7Wso~SnOC`Oe3Z!0=GNd! zgD3T2Ynn;f)xWY*KoQdCE59Z3L-M!uhNJ(^vCL0 zt09}1YCnZZdu8MCX*fQ$yPyuwoFCM%U(yl^aSph|Z-DOxM9RdbCC^+Pxvp&lkwvDZ zW<)R9$&hq#0tkxYJzidlfmGE8nwg$OJ!}ec0LY>9Rw8KQA&)}aBh}-7(lQ}A@*N`f z<4Kv$R^$Sq{U!3n%NpELHB0Ut7_f&$kaiLWq!{`0>vNEKq3-b7fJ(|1}FD-oF_3kb|g{loc# zG7;5Z5tqBc$;vZm34BRKwAG-J)omM1pzamw9m)iB4uz>E%a6N8WP`DK25Thk1H@Wx3|oYiLojUDS@b$ICO4>xLsa|MulCrNO3kAvdmn zRl-0{s8`(o>E%ZNxWD~O&O7H*44gs?3&)rb57ZR9i*-1REo>bg+Bs%t*g76DbyGX-yH7l)xTj;T3@ zJ_f0)e^%4c*2*;87Pa}DX!JJOc$0JCR^6ylXL##*#tNGx`{hSDWHkX>xz&ca`!ALQ zcR82~vnYs$6S4!J8neJ^ z^oQ?O@Y3v(O$QFzxbG%PFb5(wtv9Yc`D{Y6UTYHu*>Gy4W%@NWC9WfREju1DmWREl zqShXywzsi$+TjWUh=9$Xp-%O3+86H1BOVq9?i9z3qPQs+TLXr14J#jG!&_SuMa3#Y z%mbvg=mlB=Y&$`29V2Qs;28VkrRxuQNeTkqzWrP_CIOW%1)E_aYI<1~hOr6Fk;r+a z8*8h*tO=FDmAIeUY198ZA+x5w zGiS<)w2K1(&~=^CBvO>DTvc>H%q2pt>C1LcIU!3}*%UgFJzib_G+J4d$Q6P;*AFul z>4sz3i&8X6r#|fC>A4?HAxwq8I^VBZYKzYMltR+ko=86)$@jzItY`}@9SV#v%oC_Y z)=KAF46}t7k_V8}%kLz`u-tSwM~)C3Ip@fwlsH9gPDpLyk%sfl_pA54>pJIq=X-q{ zy?yzM1|N!ub54XcpcK(5+FN6)G98G%drbSq)4^>-b$%LcF%ZL7W3DZ@C zl^DQ{V$1p7fCDBkV(1G{*ty2a$JE!Jsz7YT+@1-#yHV4Mld`?6ZH80yj zwtZU4H~~9~*lqGoxUw`PK&ww249>b{y`AJdLn@8^8U&B@ILTy4 zAh_Cr_XfDRR-ipKSCh!B2j{|*lt)bSdnb4);%VnQrKng(A|=5M)~*?Gty8ybS_~z- zrzycSDrePZFoV*22_T|I@lHKGsI&_>Qx6+te6v&WS6%CnMA*La@7KWR%P ztXg#D6qy`}x8J35$2O5bnzlS43a(~*mMMF;6Nj}Su0a{j6;CsfM++u|+KE{=s%k={n8egMFRQ_(ni?62 zi~DFbM7C9%xf3lV93Klr^qe9RIq*fatssnCx8=}t-52uzR^ehEV2u6Y>|9q{K&N^m269eu=GG|JGEunHsN?B_jo*p1w#$`}&E#$3Xffy>1YE`qH-!qc#Uq!^4nO-`Q_9s5~YY#Ydh z4;q6q02Izz#M)-$lmL=7Ey_8Rs2j!<14rk4=UlhUS8Nfo6_U5unXSY~85YjA;qmxX z$SGmD6@UmLgfPJ^m%W^fOwCcZjxgVI8;y)C<($4oUDpAEK5;t7!fZOKR_KyND%Inx zs!@Hv#$_sDNn+e{Tc{QhWrJriQ*$FqBvrH{AmDs^1CxBC??=pingj`oPZ66@Wf{X0 zS+~Hp^<}=l>b%^!4hj3=$ZX}lq$HJ(BPj)&I_GGl6a#a*!!JtPP*b1{I9SwNm>0av z_cuejBc7gq$ZnI!oFs>jwz)B-1*-vA`e6-{hp419PC@cTv$sGF9xsgt74cTx8K)TL z`?sI6;h+$-JU2H{Z#p?Ir2aV#g72K~5Mj~iF@Utp0?-dfjXe_9#VPvAAaWXMYfLWZ z%4XiUHo@ZQBVs;pJf5dFNin6sDRGMZcyzwU z0)5Ps2F(3f3vE{5Wj|_?c{#6pPLaUn!-X9UC<7)6EI_G0C5je6H0MtPy^fcUDHB1< zLDdfjW{Ybl@(f7{=EXglJBK|09?mc2w436R!W@^o8h5mtn$-;~k`M<#YhgE-n+Amw zL9O({sSRgPGf_2S8wA9cXO%g$>EKm>o}wcA3P+z~)KGih4I&(t*%pDGK*5*ZZx(di zTL6Rz5+J9z#GrC>*A2S7tYaKwn64SpLAX|AaE8ri6YH)7Z<7|(oCXNnw!DH7GPc73 zKv*V@(SQC^L93AS9Of`z^`@w+p*46|>tEek>q1aBN=Xq!h`gxaLdX#SfCJ>Th|Hx% z!4he*3X!PWo{Axalj=%T|Kj_D;wr!r!>Jn%+DH%6eVK3l;q3cE*AJQxx7L)a=!qNY z3hr3e+F39s=0wir0D3N~x^{`J87MT2-Ebgs5f|rs=e)5-6+nRm@5uc0w;>egFW= z{Z;!VMDFqtY8wr@$|wehHw|=Fx^&Q?Jf5otAkKvxxbb1lZbdf z^rt7Mn|Vqlj9xc1L|mpTr$uA5eRoi0Xf?d8+b{S)69=gJ3Tk6Y~(bVZW~$ck-U>p)qn4Q^zU;y%>V3`RM_sS02k2kS)T> zm1r^WMhcfgt;DL?eN+Z*Z)%G|q5K#(Qg5}<-Gob=-ih|6JPsu!v~4s`yMYzFAuY zlu12pe@|T?sC%w+9on%&Rt|Wi&5(Wjz4E|tUBVKg=B+f?xh8eqmI_-XDN?DhO^NWi@D|X&htDvX{1iUfKUQo{{x&i*0RTC;$K;07*naR5_t- ztz5i4MMx#0YVp$TbdViL=$!6I<&za^Ls>t7?Rt~k^j?jU3JwDRm?I}w#3=>KfQ9>C zyKCFKfO!H}`VeI&X@K^rmEf62h3EmJA?wuw`Q6c|&r(VvsNPV!CN>vfyPlAByec$p zcCvr^$A2JlRirD8maO?smP&=xpwOo<-=^C)(mv`+S0|98;cH#RiBqsTng{?dAAeUE z(CW3<{-N)Bbl!J;ld=ZwaXTkD#G))WyhTc`A4rw=AZeMb(`9TRR8@uk98QUxM~g@< zGD{}s$J3MQ)J@}%J;h}MvdXwwJSBM`#f8J-`;mO7G8}Rake2(kY!m%(&`d;K>%Qxe z+~NG9!*E#9K6L9|Vwl=g1ikai?Uhq>1vw9xQ`X{mdKyp9_t#(M`&DDeq3t zpQOlbQuM=dI9~L~d4Kz5zP%pKACX8n0KnTXe?hhC1Bl3Yyc{kc_1O&bEyXE@%8=7b zS6PECG?fSem9W*1N3~Tr=f~3v3%~yK@AYINd4?^(DlymkxKR2K(e%J- zb%f1nwcQFzXPi?c@5^@d^!d-iNjLx?xn3j*$CP4<5t`&LNl7G~o<7I8++TmOw!d@E zS=_wuN9X%?%esF13prn^y?UxfYq&jD z|LaF`t{;!esLMPuHn8(r7US!=GCPO!5fwABv?*t{%{D2~bUPC89i1`)a277=Q3AK- zQ~31|L^~T6d937LiZ$(h<1%h&Vg;yQ%F_ySdO!EBqIjXzYe`)|H|UZ{mfqk@#0e+1hSl(>QF3cxci9R(D4iyf*TMf%Cf| zzxD*Ego(6e@Xp>;>6-XT|hQr0 z_FA`{yKqWj(beAdgY*3|-M04P^;2o3SXc_%ENd|e5WM^NhyMft(7EE>&bMIIq$MN) z3CrAetYer`T(p}NmWdOu#N$XTi9_fQ=l*bBKRW?LQsUCv^WC7!B!)Qv^FR#0hFP^G zmmmHH5x@QQpTl(PkC#HVtV1~GDz&4509ayNjG#}Ap4yy8a^vx-8;?*_{UXbBQ~QK8 zqDmr9&M`+$?7JQ^le&@5^K!omr(}+M@ZCVpT|WE{iBbx}Lat+u%l&Qb@T|AqHBzbd zdeGfH>PklQ-494~IDc@yPjNybq)wRcZ@*AJ$(6Q^iLjUfBrLOD2eIf3kIpORkR<_& z(l_IB7iOOe3$CXm!0N|UY}MvayrcC;*j6EEEmm2{fTbl7*YjyPIFvC-74$d0V=T<> z_c2tsIakV7;BJG%`oZe(Nc}`Z|yx_ zUE?y9G@3Tx#$1v2y#^SDc?4KR)Kovy%5;n?THa2U`pUVE<_chy^fu>zSd(yT%zG0A z*iISc9p?tZJ2$$(+ptO*@wd9Sw+52xwtm-ZEzsEQt9vF-DYl&qsYlQ6I8uJIWqobY zX`4lP9Gfw46<{cs`Bw-JQQ#(TZmR93FY^8Pwlcl6L=Mt0cWOtF%>z4jo@q7 zFjMaluBhvTQLe`P<%28Do zlt#&CPES{K^GdJb6thP@F{cl||Br>Eo}hgh+6)7c>+`i>W8_jb83oQ*KdDKVc`@dABrtzrNpxMj>zkGFL^6wcn2Wg4TsC|>7#yD?Qi^fDFY_I&O$w+vR@%iO(sfwU!O1xy&$(bi#KZZ66700d6Xxmq zRreGHBNX8oYr*d54fVsQ7#mTxnLSqOgiECi)r8bmf@@RQ&T(s8CAvtZ@ z9iM*i-SG9V|8Liir{_;B{Pi#Y?7N;^r&faD_}mXi-Mj8@zof7npFT0ixJ*cRIK4jaSE4 zB4;EK5b}(yL+KWdUgrgNoM@usNFb|hL4*LnVUtzV96V*~>)fDp07;)Ed!yhsG)jRH zx^yZ%z+Cf$N=-xILdK#T=C>C)GU1wX9YyPwi!aP zLxO&{#zNsFx@kGD=MvldI0@;Hqt=i0V5{9)Y)-20c7_ z=+yH{ZPPXbOjEn9#88A~3~WCcw;@xRIb7D&W&)!lhB^@bPEEK@Mw8mA5efAbwpk1_U28fErMF6?2sC4mEsIO>VAmB>J zxgm%aXMLWlnS`}oyVV48=LJ!DZ`zJ(#I(42VAm)VXokZ@ldsKrY`aLPdIr*L>KZSg z^9!d<@19plPxb%P7Pp`8Z&+XNdMZ!4LFqoLaVowW#C5(O%j4NZCOQiSisq!&^zixm zO=}q56)wQ#(J(Sd_6x9#p`@#7h5#yo}JP_uaF?`LMQ-6epqgIT1zKQzl zPS2mps4}GpAaS{~n9sKb{eeZaKt7=)$=qbdpd=wMWT=XqSwuq4pVC{d=Pd6#K?&2^lxOgD8D>9(fQ=_(z`kadnhQqse9 z@wbsPAG98L40OaPg^*InC-JIg)=}azUpGz$03OeZAm`XbS?S^fAbrdWd1Z^-CPElb6b?}wu~KrG)pqaLJDfHbwFedYK1e03aPTm{VvHtUW6Izu~^ zJ?n5eGN&9Ah1w)gmYxkq#VaOC1$)&Otx4en+hEa)4#w4dCwXn9Y-jAol`K4?|mBzv>z$pe0%a>2KO9cw?H;BpAZ3qiAw+T>_93Sxu-EyN!u|CZeePV>cf(QlA45xrMbqT%v2MzD zNilJ9zRMo@{IQ$8y=?R;%ron}%{g!Qcuq3kzNsuDr2v4=d2)_Z@Y)5AklbyD&f@z%@J|JAfWC;{UX!#tB3#sbCO`s zSDfz|aIX$>*05hr0T6GmKkF(eLYlf+>5Fi=zqYzwO(@opskTtgAAdx2>QeCiNeciG zS#DpO;|Z+cwhjTN+qdezNYOei+9i|h6Ohsj^d;y(Qbh3J$aTYTeBv<2aMx4YGF>?Z zz#R*@3FRBBem3Pq@`vNo4|@0w^E6LyDTc7zA9WeIEz@*;^+K~i(qZg5KbcZPCJ|%) zY1$&z-|e~)$@%`^yIx=6A=u3j+YNHEHNx1F@@>=_KPqR zRt%D+ki$xn3X)hvhVG1rAzR3i2G#wml0Gc=ocjnMqURoln7v`ncY|Fif#?Fy<{TQaJa8d*7@$vzY?$sIG^Y@t+tXH6uVs3>Y)(Wedv9i*v(MfUYb|#-V_^O;UlIG{t!$|)Z)To|6>Ir&H~Z{+bbf4*ZDRU>3mNC9 z)8j|Z0itJhQ4wLq;?(2UkB1uKQA!I2B2+UJB3RBMEI|`y5(5P0p_b>BV=J@}FM+XW+yH!v zAuMNf4v|ie-wfkHA6r0ql;~dtDq}7vytCS_ZW@Z+MmT8}9G6qcr&ZcYRT7n>Qk}{hQ>lpx5IIjeg z)6=({f^ejwWT@bLM!$;*v!drj&Y)ccm`yF5Eepz4W+Ns5AjR0~RAW6s;HTrg+QgI^ zVo51GK!x?9*f^)SynfdDx7CrLI+hT&wSlfBnp8yA^NY%XtnpU%j?gHienush1zjJ&A#cQ9fopuY%8+e<0vJNU-gZD>CwSMkPtiga-lvdD_c?t6Ut^SDK@v(# zyg+r?Cfae6jYb}83cN5^6jvvm9qri8sCPMVT3Y7X1#AFG$t*<^BrVsbXwtJe%r4Ca zry@&aSB$o%b6rVVEZe?=k&P)@(@%5;4APYTxfhqztAT26nRJ=~O~vFWl3E&i(}oxZ zR(9CQzb2b^xLhgcO!-}|LcfZHnUN_)Zf*w1DFL#zM*tH(((%i0TMVIf;MH)k{N?$z zy1uJoLPac03?K}g=SOCVW>*&=(yk%5xf*J3A68kk73}P>IH`^cMr1T+4=SikxhIuNRvXGjyRfQ_3I+-^G1!jaVjnB1TCP~Zd4QBP@>S0+ ztzbeu2urlR5s68M)tAXpjYw>!n1v}#Kmu-oy@5?Z#4V5j8-~l@k+eX zMPTPXh+PeKwW01t2|BLJT%z*J^b~9kL~ZxG-ldHdMZXv9Jw`0)t~dJVKJNecpZ*(Q z4lxLGST9gg;zX3>3Qynt2knFxiDCWn^FP>)jL4BAef%mwR*#}A<1L17DI1NqN@o}+ zL|8Acsz`NyJUxA@%Qvp)<@~JZQ0bQ(s%aV8w2>R9h@vitczpcm{iG3wF)YlyeEEcq z5J($eP2=0~UA4m11HcXAFwWNj?nTitnUIPyKOj%ekMo@$MpcD}u(8`+Iz4^4vBCX7=Okhw1+P_t~K^tMCJ-O zsgOBlkf%gBTAGrgFXVh&m+UW!txboXa;}mO5wOwlkoi_I6WJvP!f^}_-~9IU_%SSJ zX1=`qQnNz!33)#-CytT4#?(a}Sky}7aJpyauwHbNB67|--LJy7rnuSOt{I||yMO@%HB4%4A!!n{4DR?*kT-~LsG3hUqtF@`N_oCN@=FaEjyMRI3J6 zYUg&A6Q>Zj^_xHY8xvNF$|7M-FQ0y2dH>`+hb`qvZGKcn`hwZEt)JOdX^jYf^V`3U z+w%JSM~%DD#b38+5q|pS&yieMU-C4B$oWYH1G+D%2B1M%Irf$7NEMN$*qhb ze)_}xhaZj)AJ*4THbPD~g>BWE;QBHiKKw|<+mBOVPV41MMQBO}JD1n0i_EO|&<~SF zTafdaJV6xJ3joZ=JLiVAG^Y8B;-re#^0<_1dtiu+;^jj;Dx zvMx2R1J zfPF4w;kzh6V}#?9*LIF6)wfig)w1}7Gr6V^bNVf!-4Vf({3$n`LF}I1OA>_bTh;eW z*o&BUxr}6$`|Vx3`C=N*3%>o@W{lU;w<;iqdnCys2YoWASVsZlmVjU3|KY#>m;c<7 zv$O*Beke5#t{3G@Ct)6@LrqpB=dUA=;(96SPOAAYx%t=wiJ}>VcaI<4Fez-UT-@{X z&*}?o@!X=BZR}w+ql$4;XK^hz?w-D#@18DSey$IgnVI8uIooYfn-4!s+T%55KT28V4`J^YM{WTrOV_ zV4Uwuw5L-l7m@q?^FIiuaXOLn&p-b?0BDNjN?rApfSyXt*r0{!kgaX5A{B+jaPYF#s#;rV zpT{XKug{Pp1}(b4P>9UV7&7H$c^zAZs8`4_Fvs`b|An;b4Y%dX<;yQxN9#Q4{{8nz zE-bGi>E)L{AW@dp4`We1Cv^cNaxreTmh|I<cTDq=cScTd7A-9jhDXi3t{Z#1f6%JAD&=o_z6+??{DTd&@BN{Sp6$5j$jtT{S0})7JQ>QltNF^nfq*GOu{cP)E9Y6Qh-kg-8s1IbA z4&;Z!-8&?j4krZ|&R>4cp|g;2h!|E*X*%8;QE`)9)hQ#H)uoyctS?$O(O>{jq(pt0 zKK|L?a0*G4GnZF|$Eypm3a3g*OD~`PQ0E}y;f@nqI&M?<4$UstBENR~ZHX zOVtm6-0*^emWpiu0ls111jY8cBWepFN+*7JtNAnKY`$eejlSQFrf!r0Ds0GtN`o*d z*{}R|vF?}6(x*|SS)_V)bJO|eGq|NByJn6y%nSPihCAzT&@wJ znwUd1D9X%xyg5p$Dsj^r8Bcb+t@6IXmbPqlJ5w{cVR(ZjkJ4(2#lWTsykI)6pJE#0cm4R}*RV-+I-U_Z7nrX8}wRciHZht_*}Y6+0R`q$gsZ^^0oQO*W~vFv#=nE^-^u$h>fdU00uK8yR}|5ypXxt zN$bqd?d;iZ{i55?4~@%q8GP**D%N1ajvk1A!pbYp*Y=&exs2F(q|(WYM`2qCMLF0~ z>G$@E8G^El9If8#CZ=-hZb%nGShtA+(<2oA8Wa`M-g)7=73{tjyMJEu$QpgZ-YaP@ zrrCq@n44%9GHCsoOtbz5MD#!ZxBm$_Kg=g0cYJuC!WP4l4K0g@dM%1MMJn?Nl_#gT zVV8#@+CwlKBiaJ!S8C#PdKjlu440gIhID@UL`diyT(ysS)GMdi7Hid}c{)9u9zJS< z{5T!lFs_%E5;ccqcExITg(a{Fkfy`^I3Hhr`9~3+@1DG$zWnm<$@yVAfyi?H?1y<6 z4>~?)^&_avY;||z6t)Wj4(g>;aHg=FLs*o>s--KC!-g1XxO33Fd;3Q1b|(b%qd^f5bTT)CQNdp~=JdQO7d_FyD3nCiG?|%RQAOJ~3K~x3r%I@Tlt?X_Z zykPEuZtu(rEog!D?)$&s6qHL$ZrmftgZcoW$VP&xQHL-D&#a- zZ>({x065=0B9dYx>*cjJe7CDFJ*zu9C~KH-wZsIX!|8FH@AOV;QrL7jl?e%7UO$x# z-I!v`24k%r%$}|(Y=AHrJ9153&B{U$^@O{^PBdTu0Yvkpbn2W^gq+r^@`Eb&&WS_E zhY$1dUX$)qTt(#a@)^6X4#5;;9f;bpZA!>b%b9Y;qmV_^N+tPmuCsqX&eP#;zI)OS z49jbZ>$WZ#YZM-)L+xl&ic~96fW%2y`{R7~ybUBG=OrZ*meB>8G~`xUNw*3_lU%$j z0&0Xx<^qxPl&C?x%tCehm60Fdw+IEm1BxM#{7w%OYr8D&dZ)COS>IwHHk{Cj;7RHt)x&76Q4aIRTYoT5T^H=ekN%~%CsX<{ldj!OHq`rN8^ zyhmtX}*d0pIh}j@4*)vbN0Hnq&a7E(%l_`Rh!OO387g`JvBBR;9 zr4b;@b|8HhQcK2WuZ|9tD}N)L9c~DaZFAa!uClOBJt0l6QwiZhq{X3^>O&^b4asi| z5lOiwZ{GyD87l`!hzvk>-Ea!XWzM8Q8pQ|8D%r2a30M9PwTVPa8r(J3()HzX8&$yS z0527P%L6>!!_?3U3c*{7%ge2KHTFcfGB^~?k5rfx#nSJ~JTDj5P76E%hTf(5YLjdh z-e8RZtK%cwG~n(X0rC!}lglO!sG`z}DvJmqksC4yM}#{%dd~XBUH0M4z1=vsuo*dH zAs)A+nu>W=KadQ_J=g2tfN9Ve=a3ju(_dQNd=P7q;R&N<&ItQwQ#hN*ZE zH+7NfnY7B|7*Yx;YG_4P-iu&_{paI>P$ zx%uvi$Y~aFN}*=A?(B(oVpu~JK_o}zT|z`~`ZHxvv0CK^Wzl&J*ubzZF>G3MId?>) zaXMtLK1`f4liQjWrWlAw>pNM`+S&MFa>Eq2ON!fcxYNE+y}mT&4G@Rvn3t#%VL{pS{_%%*^FZmd^t@ z0K9zpCI1mZa)a~ZFwW!$mwn)JqoMCe)^7GrX(>i6fJ)-AL3)U^bJ7b?+(pr2<lzLTXWu|@%rbf?z$E}Q0Kmawj%Z&e0U4``wh$*fLH4(XSIs%gOKE*9; zONaE7_^0xX`Trp~t;O_R-Yze3Tc-I=EuV;7F$6$FoDTQOtqALRTh2``S&D<~iB|4& z*;p76qc9?|a1JcvG#>A3>N1gY4lOEvY0{6VX5v5e-${SP*H@K`n9-U9;vB zH%tdIM76M8(xs#0J3mwbuLgg65|GO1-L8XcdQC!5!sfr^P`${q!{D2EazuUEl|_# z?!DrKh5VyJb~j`e`(d^tyZ z2%4mB86`bK&y22JV`fY?5GQOGgP)%eahPU}8`NO&@-$mG38#RN6DLwwSp3FC5jTGZJA1gC`m=1AWVp#n!57QyVO;#DkgHrxD#pC^ZMUUQU*vJ+EMgdLU zOANO_(dO7-<{c>IFmT0jN=FF}2@o$YzmOXbcTYs*ym!Osr+FBUemrOfHK$E&TtrgA zB$om+mIgiK`;0kNIMZ|qd=Y^$AUJZl1V-g!&D8-_i=JVeMfmxrzeglcc*{`=+bUe_ zpOU0>_x^iL85Ci+Ej!n%{2T#TVx~UTd%=1|V~QJ;8`uOM`4gzp*7Gi@4j8)rofnby z^)sh<_wHLn^5dMHm2bAZ%yNBh;7I57RK8h-jFO>++JK`YNZs-AUJr%FrfcTV6OO=SLzxPBRkK zvlEEM!+quW7Y_u^Wj$ABX$|9)dIBM0sZZ+YDjx2iI6>l)Dn^bxYUaCgqq=!I5$-qv zc~*ic25mxgZ|E9JN5}j3DQ-2@HHIbO7G*_%aXOJ74tI}LSaNy(#d?-;iW+u^AT*4s z_b6iy3EL${c96x{>e$IpEoh%q6!!2g9_~H)L8Rzwc5vVQa4wIBNtCwr` zN3j=yItDB4SJ6UVQ|fzPj6TvK7lR@ol8~_2OxN@?X%}MyvWfz|+BbtG*f#mWe(qhp zZ@{E8XGts)5>WQtFXV_yI#tR4jwV|RVX#>RHtL~mIk%D!I&3AETp}W(*_(PJ?DO8U z8>B@Ih{&(Odsyi+B3IMzek5GR*HUg2W_18LRA)#v;3)3c3TXglXNRT*Vb0;YN-Hmv z?)EiBFqfrsIf)lU5@^Se?IKyO1sUxiH#XwJ*o-i+bgl-T61fGB;$F*NGp_oawI;wQ zKe-eTP1m34X}ZC6+3#|5?x26iRd0Ydh+x+S5v7|!t3}4<$|gWkhmlg~PE|5x^aj^g zR2LO@q#I`I61n%Or~#ZEGD)E3=FGbAnz!{0aR`=xb=gD2B4)Lh#c2>1>9NopN6;_z zD6#{W$P=_`q@(fHjRRUMrTGxzfPJp)iLY%Q8ZTE*hZXV@U7i)um zs|?64>4LYZeL-`K&^N3>ysfJi!@7E##VEUs$jn|&R^g`^zr~6RF(0`~tx6Yi$`5?@BW?qEY zxwcM0ozClF`R?1_vFJQpjf>99`B}MMI=RhZ=vn$5?1NM>Z*OYMi1hH`M?W22KmQ@e zoU+u<)Pw=y$SHy~T}%;;$f088N(OO$EMxg-iTb98rU-6ouK3Q(d=J9g%6!N~Oq5^dyNt z{@LGfikvom9a9V`Y?(u$QUpW3w|^P7cjr+6h{HG$xouq}OOF-4qdxQ%R4|}_By9_p z{16bC?;h31tMoCrEiWQMl=(y{#pU&jJ*}0$o=;kGi0Frrh}PxO^tpauPN_JNIzLoN zT**Rn#jPJ|Pi(*$jN4*et^IU(`sU9;{cI6YiR@uj52vuL^$IQdUPrVM}QX>m_aL?$AY2=S8f08XNG&j(1e)l-ei+ixG$0 z`6qzL^74tC_v1`{c>n!>xSXFaUw$d;lQnw2-Q;nSl(zMfMLW)s8`8GKZS~VkZq!bu zwtB@p4E!*XbL7XcoVVqy|I@YzMioxOba2i&@AJAzsrb^>nNDKnv@Pnoe0u!&`0+Q< zICh#b5Qgn6%sg22-sv6)f){r|75IxgmF!oJ3@tkHYo|?)4`MjdnhfN^HuB86YX8 z6iyExrV=HjPvr9YtOQH}Szo^tLYXUFc*P#19Y#C81t(5H)iP?X8eezP9PK zt5y!u*f3RrYg*ziki}GkJNG+;KS81W#?(JI*K+NcVA)cICxX!FK5FN)+r+iN?#TbU z9z9Pt1*;cS*O*{7UMTF==0t_E%c5(FQmnSO0`T=z2sBgzt60Wn>h|VhlbuAtXoq-z zA52y9C&caT@&=_uN#BTZFuiM&C|6vr9RoQ(3(yENt_}Hm1PGxE3V_b70B#AH5O#2a zVTn5=hv)c{z6o4pvcMgnM-GoX=9h%{-4IbhH} z5_?h5tUlg;qILC}^o$(+n74-o7_A*2|xs2mB1IBco7E?GO*w4*5_ z0pi`$H}mOXTP`|*Cvu;D|F_kFGn4Q8`(pozW^I>Ar&E)pRBfhv=O<>mrvLP$f&kM z%t@?okY*Pk#%&p+$td|tG z91U;Vbi{F*iQH0ZEaPylC2orr!tz$EF0*P9?5fLrfoup)ew-gZ{E+EdSJb{D%tu80^oPI8 zwKJ$?xkqx&d*=t0kmrO>ZMFoEoSzPeIE+)-*|?ZDLNX!;dwF5K_;FGm6BHs+<>?sd zEvQe0{?Nny)8X!2w#(SgHL339(@)kU&q|w(V)eG(R8-fW<2xd!=!OXa^tKz-7x{5k zXhHY&?ffNdmy{w1hjkTBZWsZfI)OPqkRLckjm3CtTPVi*4RhO;*Qhb{h~s?J?OT|2 zaI1}`>rDoBYWiI(sjVl+aJYLK<|DbGZt<5dKSPdF?S_RF@44RTv&tpA5XgM@sDYFf zRt@XIoW*R)>LNFY6dNfOjKK}Syi&AmW2%nx<#h}qT&gRs?P)bG5Kbv|7Hi}OVWnj> z|6#>Bjt}pq!yUO%n@AD4ynF%>4x7!9w^!-fCu53hJ@=IY(%U#(&5@c!zVr+!rWEd; zzMD>uRbLAt9;#pydM9hF3~W;xnbC_F*B{#~6+KHGj&vn400RSSo&y@ot}=v!s&i-7 zOef(SBHRM8Zl*TxZ^E0yFoe!Yt5y_w<8IRUTDnOWsnvQHsf7x3Nz-i%SbGK8=QYB0 z8-clhvH@{#*eJIS2!Ou|++$yW;;x62>w(g*(DiR~%H*ujZF^n*=WVn%f5aRRz7lh;od8Qn9ieUgWEdJoaq+t7?qj(1KfwFT~w_klHK? zbYOz5Ub|;m<~TJm4&_&&hnwJ4VBTkUDb`CNzCpBNoF`H=6xyIb!HOP+@fzx zznc$47HAaNxB$0^8|ifhfH$7>)hT%OKjp1OeCw&@fokWab=$!qAK_Jumus$|5V4V(kemp2~_VV&e3hVv*ABs)8 z0ALL3wp{cf4C73G)c!_IYqUyDVMD~)ERur1g&QFv=jWfow!Hi9cX3-@KmQRCA3prp zY5tmtrG)h?%;zt^z;%pdt!t37dK~}|!dkqb3fn4f7lmI`4{`tD2O_80DAVyCN?>88 zU8(sQKuRH{I1FRe$m{4ehOHrenGI2Au?YaD!6EM4g19+ zD=YzxBFx|Z?mtQ?g!PgUt`uX~H0@oPy67ALa*5h0!4aS-Xl~FHa@E+@K$)c3D3U8* z&5JQE@-1*x!nWk9YMk%ie-D6ReXZ)6+VbjXnViQ$M5>1t*>q_-z3J>FfnPXUT zf6Sax80X_K9hI2iD#TKBKFmdf)%L7xHxZVzfT$69pQop_a_qc6L;&&r-FJSN*5$Qs zPTP9cEBC{s9Aglf4tIdCU0#{_<NY3;S z8Rv$bK+xS!#a95#F@_X3%^57l?f@XZ9p(tY zg8ia53NTR6hMVb^iT(mCf$0nY)EZSOsl-m-ZAF9|q+c2@a^;^RYNTgLuQpLWMJ2wA z|GrVZbrn!12$!adg%d+zE=hL9WKJYkWex#BNeb0G$&wUWWB-~jl(YlUxY-(>vc2NTe!xC8T&_0k@Xf8d&y9AjR{P#d87I&V}`E9u}%l*G*_{jr|8j9xMIR0CMW!Q zU!Z8y-VH8cbh@5dOqbST@(}D4!0SYh?Sz5s-FO= z^`Jwhy@{RWH`cMZzAVh(EYRi4?tplMdD~{vT&S~zd-wX?>07oALS$Waf-IaQCE?79 z1ZMQNyKKWpE%P*LQr-S;W1R-&&CcHc>^V_sI9zY2dAo)DfCxygLUM#8ovS!YXN#Q6 znw@)*2umtfh`lTNt&#s*Z9KjSWQcX_BSe(c5fQH$#8O1KCza}(vzCZRNR>7%7rST&2nB_lfH)7% z4?ZIYLgd5^ntWR%;gv%oQ|`nn;KnDcs__tMRHy!4_)*XAm>H0xp`a{=ETD4NUo(cnt(b_UV-;IP((mC&iw#M>gcqsykb?9 zf7+K{R&v99tT>nR9<$91r?_QKW7q)m7+X`+V+>iqr)GgS2ANzL_E<%SiBk$;IZIME z4|Ky=@04bcv679;8gK^Os(QPv_6GXf;24Q1JnbSp3<8Z4eunSPvG0G)uP zgxI;gSc6>Mh_b#-qd-Lt_wOoro>HjE@+yyO117N{j+wlqWq~0i&ys95o$tI)u z^r(N&CU6ERk981H;)aDBv@T~GNMb#CEE6%mL1p%@Y4YkC(H@Pi-r5_CbBZB`)en;! zMrJ;L`T1~qL?Y%S49<@LGGfm6E-{lz0ZG8klFg2$Kw7q!Ff+s&Q*8KXNd!eg74x8R zpalfWbQDviE-#Mc2aKQ2$VB^bM0fftFCN>frrBm|Z}VFki*HU~?Ij-U&*?+Tzvi z%w9&}q&&G{OmVBi{9qmB%j8vUnfy3WB}}W(UGJu`*r+A;Zljl-uN7pjd^sUmQan9= zlj4@OC}9&5XNr&~C5016VYyV!j^f5KETu#p$ot+#V9!dZ8%?fR5E~4bf{1I*d07qZ zs)!1KQqOsw2u7RLe2!$i2#|@i(X6u#W%Rh zyr4!fmi|x6KCbeE%gZmE(!1|}SC>TlWDzx0N!z;OOI1_OHB3*CBaod7)cbes`GX(<8ZooD-45-IL<>ARM-H4reeDrXA575z6mHW)zej zCjJa=i|fW<2P{LL?ylJ+HignVNM$tb_k*qW&ySX zvQ+=4h=z@1gf`_- zNJxTGEr73u6jmc)=|3t9#kU0?`Niglky=26=(zwl-7)&y40(&dZDR8FVr^+p5N(94 z-q701YI>1X@b=J!K(WKv-K{pC?;$}uEjC0Ac>_Wu>|&N}X4#HEgDs5?#DXdvTdHi( z8X%rc{BHnoVq6)aqipC!b8V@2!F9U;!Zr`ME#BBMA$w9)MrQ43?%1FNG!0aR~m719uS6AOy=Rmye{ zP`}FpaoF6S%`e=MGw`jK&ul?iDCxXpTQbndr!H$%otPSpr7WVx-J`liAQ0|7MzDu- z@r}qDY&! zq{W|bD%A-Z3^@buduxl^nJ5j9Mk}Ovi#t=L__^a$<2?dI{5SvdpXUZ20G-D@4=gj$ zyP>6y{W>Ch9t`;LQ2Gfr^kNCyR#nM67P3lzm20aLS|T@0$NBV_Q)4*h^eGWZNr2xl z9~KbSU~wyK*p_oGwa59OKYl(wOs5CEZ*jYbfFDP7YAji>>G|h>(EFvj0yTcKU#JeS zxyvLXa^wfyio74tIV|;{B2faILf8opN`?lg2Ee%i3C~|XUClzkCL@+{It%lM-~1(~ zm{bFf6vDDy&ev4NjwzRy1zjso8WPUzs)2pR^g;|P5oOcDytCsl9|7>g4}YPEx^TLD z`AK22R7TTC==}(KGdUgZ-U+8p>3@s;l!fHZ>Cu!ss<4LTth@g(9^5dl%NdFQv^qBJ zF}KXi=sL?5$tDuF<@oUa;lmHxdJgM_oL2>r_CT7SR}=WE%fVX{$h2K*b(K<>j`xSV zC!^oOuq}{(Q{T)uFOsBC6?9nV#~Bb)*t(IPNQ^v46T4u z5>Ayf)f#ki01%e5^-WJPNQx4xIyV3SAOJ~3K~y>bc=-4mKOVyJQjOeRKmEZRpW^(8 z`l{F7_aqk5t$0C;@(;JlLZQVOcW8AXzCjG=gXAu54I zsrJsflHXO5P!)7*jqbCAK+Tlav^uvFOfkb-H8u9Mulx$IVGnI^4gT zjt{S&elH@Y$B)jBK8MMVD^>s4;?mt8X>@bkGv>ry=j#Wo}i&7$c z>5d3%Y&zxnP?ZMl-xMQKvpF`sHU|D_e_d($t1O{8AR35ee~31+2%DTvl`1tMlMOU4 z>^w1S|4uN|auk~*fjLy9q_*rt0_Kvi+sY~+x1*m3lxyxDkz6ZKcGyP=AZ)G$S;A4M zWVY=?*z54*EAodv;l2zhgp8!ca+;`PeCF9RA(Y(Nitr-#UyfirDB6l@9XvPr8_0FA zRKIMh6+#9lD~%}Uhy2_B{y(p1jE!Hv79CXwcU3rYiW>jz>QOAL>3v!TUbpVG*2|O@ zW!98&lyK5Y{KIelN|oTkDN|7p&tE>b&#bfMKjAM<(GBD2;iJlToc9|1R((Cx*Zj*b z|7iVND;?2}_oVT99Uz6}6_9Qkica&<4deBLsU=$zr+d{Dr&g8kOoR)yubGb*)i%c< zoKy~fdi+LLRod2VeQnH#6z|{vfJm>;e~jzp$G`lK*UQT<|M2e+@b2CB%#k@_nKPx7 zG^Rt@4cVfsygw?;s5_|$-#>ke&LKGjOkph<$$WYJ3?j@iw;)$Q->wxfo2_E~j#H>6 z056|^B6L*fA!RGcL*Fc=Ky+R`SKB@k!-#y-Hq{qwWpQtdc>SD_ZA5JCmrFBK-OHnv+ z+^naGzQy{hvs$KPC<-S|IT~J4N}Q@gx8eZS0;aYFBJ%Lzhr|7Q9sMe7_0!+|-?j_1 z$1)lH#`WVCPL_abZMsTIRFNVe4&$6M+EH9*jX+xuHb2hyAASUo%kxie7@Z$DrIcbd zh(N^S<45mDDX)a(9j}*{ZOQLT3M(SszyHyXb68)<`C+;Pkg(>Fb}}x{&JVQ+STAP* zQJ+ZXeF|GxFHq*gw4I??P{&|PHcg_#xnnOOq zQ;Nl$ljD{`D7&#rYbGQ&9_}&EYeU#BxiQTQrnO>;R@Fmhew?S~c6UWg+hQsL6lRWL zzI&QakLqovED&A5ug}$NVecEz(pt)2Ia@~ag%DEMqM|7xr>Ae{(__h%P9U(HKa=yr zcmxDVTS_skiytOG3`o9SGjpi!)|!(#&L_k5gJ^nsas+_Bww7-er;^pW8B^XDEOL7U zb7Q0>HxLgI8(}WYf|YQUZN!R3*bb%S)|Bzhk!E>+s0QR=J4dmyZ1D}NIT5+>ucVCA zI(EC5kaxN^o4=Np!alU`&5rvP_}%B173-i}EA2*s&4^m|W6J)4S~9diOAYE0%ZzhE z_WQo6d60h!ARv3$?OWX{82O5sMMyteDH6@{fQ=DzXV9D}MVaGQ-4Bc~w0414m;2R4 z-)rZwy{SF#nflUG=;duR>SopQ}MC^h}iu4+bgms01^Nh zbr}NIp(&btb*y5_-3}u+bx{4nz1k79K2B8Px4=fK89TiSk=lyH#u$lQ6$|Als1aaltx=57+AJLa!n#;|%#ZW^ zyYG;kYOd?=3Ss3C!gdA#=SM_${_@8>-Bme~I=%H6Is*9dKtw4;=ZE?9s4>mC`and0 z7*=h1ifp{&fVI+<9FemL_1z7nqTL1%fE2eBHs!NvhIJ{0sE(;sP}Ny-LS^d_A}z1a z6^W_dMb$RfAZ#McAAbBx=~=j(l8CAiA}6-PMNNC(mWwKmogXv{$&M`{``$H7R0KF~ zY$&GChURp*f9JAcRc<@ZUw+Pdsa!70`dxEu5e zr8ufw)Q=puur04#kXc zIX^G2pLJ}OvZJ2tO0KvqeNK);!p8CydHVLZ)dZDe)U}(!s%B;gurBA?5&B`25_0SO zz$JdJK0%iq)o&azDQ;n1h;pizj+PPeaR1KvA#5wu6oI&=7-|Zh)h`ayAwTi1T<0v8 zLMWE~nWv*V6CFPzk{jk2*07#4y5=1fThLTw){s5qkbKwjW@==9RS5vRJuQtD?|$%B zjDkwn0gN?=9j$3K+(>GXE}Yq<*LRWPs4|qDMIj=_piCl7_95~+SMHl#th5?D4|+^& zM~g_`Gq2ws#US90E?7Iis@<-RS@~qzG3GRL$I#kx+NULcmEzgg z={j#Wczc+3(`<8h))pncxGMvTGE5NowO?}G@H7`dn^9$ED&_NZowEQCy0TtPpJDXg zU5XHZ;Mdzwyq@kiO1_Ao;8pV>Wi+TeP9jHc(7iIFaJKvsY-la=%`@)#)uB9ZmVLGK45H1!hs$%n=$ekC8F%`?^GwqrL5K$F2al4Qo zbTGh4iAEXt*18~Wi-4pU0EuG|a<)u{mI;zsBw7M%lxwAvs8lg*i;0RgHm3+yI^*0R zkUukXOo(Jh)-vff`BIBb9cT)!b1S8=tJ_^41h>Y=v|`1tg10P$7Ky@ww*(hR(QoO!D8bF%!$LQjeCaN!=|=p zMDG6G_ih-o(Ro<0=GqHuGm)}3F=>Q-6-WAE5=}$bYa~ZCchD$U6fLMhqs6|7IVJre z>R+h8o$#OwB&86ym4?y#QR$$=bgU0W2Wc(jwy+h1)lrWUr;@dnWh{ET#`!L7>y~+v zN$<0trYg-A5pr&MeJ+bRY|D$@SvQPC-Xe23_$@^c!F{rX*r7ySmL(f26{M2XSFa@w z%HA_*7-u9*adUncrej!MdA&>r4R9X-(2p~xux?9cEN9~>uAsCUZa~osR-0)zjP~U% z7eG25*6DH?uY&q1IzQ!rb-Ri6U2OS}^@Pi$3PIA%UH|Oz`WaD+e!RSXCi2b?h;BUG zrMRWI=7}6+Oa17E5hU-KdN;JI<`}C#FqBk< z7&mnjQ09DtLyI7|pv;1R!XlW~%NJUmJspscocF`b*-XD=;E1HKF_O}5`|g4iDRgQ< zkPpW;CRbErnD4=l07!0A;0KZ7w(Pl5MEbr+5uFn{DNth7fB6_zBpRp~ZRiO>j7&`i zBoenJ#c;U$&{ZhKgsYPkVpjl5ai6L1N=N)fO?5b4UVc$rOGMIkuD+ltZhAa7Gdj(g z6VBUoJ!rW?RYHD3A`J)}=3}uB1qJuwdPc(|mp)ZF(~A+EpOuZRWaVsP1bo9)2)Z{x zy%ms0k^W$N@1~Zh$*P4BIk{^DrHeXqZp@ z5@Xm#RU(?|p}ba}g*it1(6Jt|BIhr^RKR(hPo)}j1f)K+s?ky%j>+H1jFK`P$TMJW zW~wf3OHGh1u141MLoI}4J%6!z5r{Y)P5^)-#Q^2ezl^kl@m zM8mq~@Fqm(#}s@l-tOCa-W3X3Z)JfBaAWHr@*3-@>8r{74gAW&CMDE3gKtG&47+&c zuQFDen`)liu+DE%3d~$Qgm%UXZ7{o=J~q8XM`XYZ+!t>uVOEBr><0wR%Gt6=8eC8Z z=G`B8)A$@a2+b%Kc4+EX)F<|bmr}aub4fYMh=hVl8es#!%fWI~0x79;m@}g322|T@&@5KC1yqh=M9kRmOQn`&$ScWDTgA-?Ft_c!R)H7O=6-+3&XMJ5-W1b4Hk+t3}H% z%zET&{iuU~r3!cCEYlY&d=9CqI%5Yp|&w?#@iLQ_$u%B-D-yu7mkXFErF zh_uC+K%Ytr#euKzjn(Y4WRMY&YeujgjX-V+PFm&szy7QL0*zykQO9EzOP1P4OA--Q z-_fuw&W|>R>aF8Y^^8ZL9wx~14V_W+%SsTBUR>zIw1js zZLQgUkW--vou3ZJO6V~3ilHK1DpOT3HpPvcfA{@gq`2wCJI2j9@0@>q{@J>N+E=Ea z1g&&vy{}H1O3E4nxM8XlnWf=y@kg~jVZ}r-aSFq9^5difkoojb46)jXKO5_a_6?Vq zP3ZIfrA}rx5;BGjGX~O(3seU^9Uf8&%gZMudiv(K%j@UY=bulHAC3}W#{A{m@@iT%L3GE5Cr&ZNI34cig;)dz&>08~$Q(VJ(hCEm);FFcsh@_Md!3`FX%X^*f z2Ab`sSL+5n2+;n)D zj`x0?oF89){`VbDQ-y6JG6G;@Sow%lSn; zH;O+h`eC%H<+d@3tYsmQ^V8v^KAOxaC$|6|?%s{_DWw1+DJ&wgUS7Ie=Ui=q6|d5R ze;B3$K*^q43i1Y19}xt5w*OZ$sIVhO6j_zzxfEL{awo(5Dz#qT@Iki)E>{jp$Bhtd zF^QF6EjM}am2m%di*m@U2XgjNor+SCLFax zgvJAE%eBt$73@*oZ|z)b?wyoBeuW5-)gxAA)Sk0qF$wb@)V{pn6VldzfN`gj9tWy| z_dI>Rt$gT3&-+Jcte?RVuie~?glP{_izeap`uX=I#9&LsMphsDG@o?Hr0t_BMufGKTN;;RjX$F0Y?J`)0`mA20v_A|CGExncVBkN;1WXpp;m`j#b1 zikwo4VLm+$^UvpX~hT zhKbY0G5T=^!1eMa#qjX{hm>O6F1qo=ZCNj`xlSiSLPe#=!;#3Ruyy{WSHut_sFw!L zBOtlM>GAmZO3Xt5 zZmfwDmzSSKIIOG6uCjn5Zo2A38Rpeejdvy9E=ZyFTi4ab73O|b*zKea(5T6^f|bIH=MQMlmzsKG zbmDcIqWtJ0*4ZmVb?Wfz+7G$u4)s4R5!(|qZ5B#JR@%kmjbZI|Tfg5v-ZnhDS)=dJfg6qvVqG5$ zDukVcb1&$$qo(}|Ea|&gMJ7e&NE+cmM4S^bC9Ma;lv=NP~^o`jQ-e~MajQxXQfhr?i7z|v{~ESZwm;p6NR<66PtyJ1hC%P88|Lnprnp|dAkyjSo3Oktub=0;cZa*DV!hqJ zIGkcwh12r-j3$n&(lSeqXgT~-Y~m*XLPDaP{8BhIAb`&AG(FnRmZCmW!fGbFbAFuf ziWWH4lykK|j$xB>=?%qi)Glkdlb1e}h>jCoP z+qpDh70H>=z1mr)uz~;!J3qQ%)I(lFeDoGvUOrXefjMdqRJh6=LkI!3T*3n&`eADB z{spYNd-|s3A}Jh_RuD-sGRG7`m$8Gl7*YU!7?^X2BO*CJRO2zzC}>9uJF1l48SP7^ z<2}(3x7Si`u?|@+sY^tr!<~`j-gy0O+fQ|EioOkwnMpsCh^3)Vt-fv`u5^W7Eqvvx*lc&X&Z$1e?l5SqZ%c_} z;+AUQPVtdLxRry$*MlP1_aFI_b#f!RCAAMI5DmEj$pI2MSCb^`!z(H%Fg{OjOx}@Sl1fCUEkbYJo=1tp4A_hZ;uXugY3f^KH?x}2XakxV-FYKP!meOV zrhOAL<&k90zngh{rd#jb?UiO#pO=azE4Q%}_eN>1{3(GyfqUN@#1(?H=xHro(!o`Sg@hx4Sl;^M`pJ6Uy3nop1Ui6R13Q97>6>o6V=A#4{;X*}Fn@^=q>F1Uzze*P)NO*pNW z7f#9fL0L-zIip$IptvrXSuU_UgOlkXE8ks8{Y7I#cUoW;a^^fthpPXr zTauF8{5Xlo^72`h*N=+;03ZNKL_t)9QwjxFX1JL$`;XffxrJ%$J&X2{^0xn;ER$l^zpt91ylq{^vxUeC5 zT~}*p%4;RIBSgrLJ5yB~jz{QrKZt7$#GEj*bI({dR&C&vqPZ?FnY2dehEYW|+GPr* zYEz(f4_+1EIgUzRhjDg(^nTJM$IQ+T%qhy69kLv$|G*9Dl!zauq6raZZ|&4e!uD%% zW{~;#$msnzYwywes&f1}BhFEgyZ(#1MN~J5V&kC8PuADZNNzsfA%LnX)wm!pR1tKp z7;a>*K1CG5cGhYhkPy>Ohgw59u*FdngtA%ow0p9gpM{yz28h$)j#6@dlK+(RYv_DES3C}xxWP%;&&>`O52n8-`&5eKEfLamxSLK7%gb}o z?P1(5K^~b<$aG#Kj0HuMPE-slaK4 zf=Y}lt4)FP9@JD)kjQ~Z43}192O3OKg^sq z;RNIy49bln9EvHUHZz%L6xWLz=V6?Y5>b!V#4T@(C}>#a&3ohu6<1VNZ<-$t;#tXh zk(OMou8Rm~rKul)ImJ!INy14|BImJKh=f%{*wN12f^`T|jvKmv`gS-ztmn_d3EhBz zUgsqy&bZA^i$9hCh;yDX6a5ui&sY$mWXA-SGD}v*T`sAVs=!>CnO358o1c42&w%6* zKqx^m(#!UJrDR4#VXO#vl>w+S#wfrt&Z5TL0Kf_1YMX&3S=fP-A_9CB^lGHU1O_$8 zGTutN%I`yyifesr#WRSk>j(?H44IA6norAMvQf^}0$9n@s5Vi}5j!Ix#vwLOTNO~c z0@=7tp-ft1uSG5P8X$mgI5Svt29Yi?(eRb3*+1@#czZYxn6FY>;Ri(jFkSI(mmK3g!%+_(BS-4C}cj7GDqi?Ftt zUk!?q+r)RoUW{C|MzDj3t?>cafQ7yp+SAqQEhj>z8=!qdxzWbK?{&t<{Fs=5&zHs;Op%j+-x|7Y!8dM#O&G$Av0kBIfyYiI7Andfz@ zZ&g=yH`U@L{uKixga8Q%F@zx!LahcQn7|YPDi92M&QD+h-84{Lx9&YBUwf~$BEsFx z7??lIBVz5`r@C`+mFMPu#ES56H~Z{+bo*{N%+uLVmwvbt*EnV#&!3~8Pmez`lTcl* z&!3#@t#e$Q_0g0Ft5SLw{GpV+1*yA#_Y)dBU!EcbYYa(Z8Q`!#&Et7If04)2?GCQn z$zzjFD9n@civZX6-Eaug)z70f4vh)H7o6SogR!>XohnVx*pks@jGf14A`+RfD`r=i zoc$IiHQMSo_i&hi8UO$o4)?pmy(X8Y<_}X#Shn1O?)}4%}fUxh9wc(v_z z#@Nf(KWI|uDo%u5zsv7n+UI1f5Q{m6f}kJ1|KoCzq9c-vmnMOtz-I~SmmU9b|L9!* z`RBiM-EcTP0Q33j7wZPs@BDb4$Fs2((JDCk#_8KugS* zA#03c`0(4m@5js6U;Yvh?;pR9A%x(?P{nmS!6!M(DKAeYVi3Dw7lRLe5|Kl0J)-ol zB5XiJ>AXutD*Mcu-r>4FAEq>q7hMwVPY=WX&QDh+l6O$kdWE33bQ~1AQ?lGsl)w@c zlfrpOERl<9*j4qzk~5aff3i3)G5{G$AFGk(G$LOmCs1^1ox8_*tiUyhE5{A%>~tY~ z=oGr# zZZfaL8CCXLu&gEwyP5@T1f;cbfem}RQOj1TJ7@lS+i)0YcKnU>^F@!cen~fqYyC9y zVl8uFtUQ*DqBqaa7A&<@BnWR)J~%%pmCWA6K=KWl5O48-xFzEoV~kA2u*fSAUzxq6))DjqVVPqz}u=QgqvcFf^kS7nqr*gasG;+uhbyT6W~pq#db%H z+XRi;Oe>AYLdR1ZJJ^n_(e;g16|{7W?b}dR6E~zkWNrGeFzJQ0=2m(`(ywkwN-o}g zn~r8TXj|q0*#RC?Hf3HofAJ6hUFH&ACC3lDVek5#PyjT5FppPeieX}+ zX}qM$PEwh`Fe0mQ#p&UP;HUGKpAqry;d>?_b400AV(@nl-y`CDeU4#1y!jCQB-Y!* z{v_!U6laP)%u@&je6Osz7(zKyC8)YEKBCH+cm1wlQALcborLsE^}FBxOB91rl9st3 zj+ZZfyvU7k{jQw)oWo0t#aj7!$weNLw@@{g&J(7t-*tl!#4-38fYCSvaQ%Tf3W?u! z`!J8w_&n_I`rR=VR*1knp1)=h*0F2R7 z^f6l{O_!%Rn`SP^8yFZ*B=J6^rApzlxv7+lw3J6g?_ z#SmlccYE6n)ViqaeWR}G;Ei(ztt`3Z{hc;+W3aV*)(spWWRD5cWL)JLA#lklF6VhF z8HxjM`i^XJmec1=*4h(;4!hS@I@(%i*$v=odb3e%Z_ZcNdZ|`yR2^pP{7;$E0&i4} zo8@}T%NAY+Hc{!R%dECq+5i{T{a%OMs>-~m^s+46G_FM0aH*TY!J{L zF#xXoyuQ&bs+xSm;Dc3zweTE3iHA%6$Z62UONj5K^hjKW$lYi_vK(R=^_kj4M&+2C zS%?X?F~C%&XkvB+)#;v#5f{`f(~RFY0fbbD)1abonsyU)_@Z)0%PwVrToIb`jH_~H zxx=7pj@oy&ET5&f!6G@JP4Zi;6ScUJWp}Jn3FWs3jR;M1U6W&Ali#lHncCcv*Mz#_ zGGI2^*&-1hGQ@eLA**R|+T7N=<_miTs~uRwL`u_;8eCTE?Gg}; z{5#3Q2f+0^!3?{8=lWgO@2%^MHNY@lo+!q7d_pur;E58hy%1DUgd~9{QH+Z9pX&y3 z`;k!N{qepZj+}T#BN0iRD8-AP&KzS%rnCtqw9Wxwv23nxsugPg4#t`-*bI3kHw=Cjg1Fo|W9c2{! zGsYa>ytm!p#|!5WwOJW5m4MJHl+15H`G1%w7P0M8MVD^-?)XNw06*m^ug;oSGKVEV z!X-EA;Kg89uzo;X94+!SvJrH{z8m(|^~QCHLPdVly-$-Km0E@Yz)vF@6y}l4rvV^_ zNlc`O;=7;zPU&6d@wphqNOztb^<39=gRvb&Uw}|?Ge}_?$xJwIot7%8Bh6WxR6+n~ zQAgMx@433e#73=bY;jbN(Tje$ZaUckPA=X$XN(JB22R>@HS-1l9uB9&-GcxIUB9zk zKVQ$xEFGtC*<@%`Hn#Edbv%DPzInI5d;96H{~x9}9PW*AIc4*Ti2eQ~+kOmQ#@GN5 z!lYk3V_Y{JnCbHLvFmnj*!$_?$II^SO+OqdyCp1K469w#4v zW|RFg^~^gtb#zTa!{Tg8kR+2a)<}q3wz#7hQiv;)b-n9`ySE!mFJ_R7)0iIc=xL-k^$!$flzu&Yi#jfQ6USmooFGoi@g#UrW}WHfC>l zo!tdMc{UmOmiPBJdyhsV+~}Iu1qo*Iy0OVTv-ZR(<8Y-J$D8Aot;d`>v<07bo$=13 zds{sx%Mib@rEas8u}v<#@hb`0EM`76Hf#N`k~_Atvo+RQHxXqwZf+*XTiKKAsm04o zbSU=0C?sCWkQd@IFQ#P(Dyamh83iZ~epXCU_Pr6o`z_uY-YOm2M^3=D)v5~(h*k>| z6_t{!1K-Ag3UATMU+lJ5H@N~Wiy5`fYEK1z3whwyTeYN<6z_1cEn0T0GR`punGq;+ z+^`1xpoA|v{d-fgSYkEjD>MedNGuTm+I%>%A;JimLdPxj#yZEuLT$6w1;Is(G1iig zoA+?pz@?j`{#9l%LV91#P`EXnS$3a_k-A{H!eac}4!kiXC`C|aVj( zOQL8LULL2sbYm?iXaUz4*XGAwyxmUBA3E0=V~=k?$V@^Ok)N+LKD(~RJev{oUwIP7 z8b&Ips1$=r>Yz1eTuwFD4PC#twiAtdf`E+?K$&tdn=t^ne4r2{4JtV{X;aWAE>RLMR=6GMM@qW7TsvFb7iLJi$N3vi{>3b8N)+T<1N&hTxsjL&S*8plGq3u z*X@qR+O+W*D+5<)xze=5&ou%m3($mDg4P2#pivY_^$3RSSj{K@oHYn*l__vMlS}&I^esR@1nu zls5(7MdLE`#1w-y7V`iprZzXd4u}SgYj!2$j3J4+N#TEr{w^p9seLe?XELog6np{&zGl<^0D(9mt5-*gnCM1%*CAfeiW;Z2s0B+{491KVZIUtYu(}W z==vQR+wYDAJMq)CoG(cLmK8O|SVSxPkEr;G2!fx+=cEU#>6>Xcph%ePE0Lmy;u4Sz z9GanE^$^bRCBlM!jDTpJ!2~Invo;1lU7p0lgqcinYeN7)Kc1CU2yYXoa>c_;s7l9@ zf267V$u1*zM#gq%Oz=~d#YDL$66luOM|Ry%+E6hQkXO^vAcIxWoal;K9MobAm@A%0 zDa?SCL`rlf#&y7n*>HXSjK=iC5zv*8NHm72vt0+w;$DKp1;5Oq7caNH8hGV*(8+j1 za@y`6e+Yi^^CW`haDAS}r+%l>v0dL*$kAj`nwARWAgi^y7F;(Bhx-)MO;i#f<9KF4 zoDf~NGu9Mpvga#^BXim zCR-J+Cva2^T60yNK5z47YAy>Bo~I`nt{Wmuk^z|uL5r%W57V{vodS+@qls6BbIilx zL_}ep5ZD;&T*t$nVyuD(YuB~E?uR6SFX?S06(N?C@N_)%`@4R3INZNW;v~sW5G`UB zfk-*29IMmKL~F&ap$v`6f=Nb2Ma3*|6JQEHMI+jf9FRiHS8JU$Mm}Hy8?8fQjO~rJ zwi~qA1M1?pJe3bLaSnF_?S$QF;7fO{TL#7SUOZq`lYiB8f)#V*9 z$28u<7-qTzb9(Ih-8^06Jjt_;dGBM2^LPe?uHRGi(a*Nuxo#i*+$V}{rw|kvxsUimQ@glXtR~EPWb>L0OBNUkCAJ9 zM-wV8ez}=Hm28R7LVA6SvDR3p*K@gtn=nKzztDoo1E$OnjO?fDS7W>5+Yd>hVQfqi za^vR_ZUh8vFoVUZUuAJrI}t>;d5+3!J6)yVk^z%JgVvVu0W%*?ZHr`uhCYSi3vCF{WmT)N+*<4U2~6l5C|3oY$R z^P4V2S%mTpb_VOhzYyN)O66~|KUT`470W~gNi>6Md4H$fX4p!*2P2g_prOuVAH~-T*W+Jqjg$D3coM0C54) zwED0`8v7!Q8`L3IdU3gFynw4zIzdt;OVd+f`Gr?ulO(W+QC#2uWTI<|lWG0-%v@i4 zwG%UzK@nsbbpZo%#Nds$Y_Zib-_lYjGKJAi^vwX1*FoIM@mvMAgQn3dCR(n{m2yB& zajKig0^l--%qpu=_D6T@8J)w2bg~)EZ{)fN)uL!_3U!UjkS*|8V zFB(iPaEn#GM|H%wLA5|Mw(B9QU-ee9ATk9%E6NB6UFC3k+~2>8VWtrLbRnYg{5k7h zwhJ>!kiB5Y!{IGaVDg&oJ3fCY-|MF<-X2pk^X~4AF?JB^ ziEf}6=JA=C{XAJ~(O79dr0BG@G{ouhoTp#*^zKIrKFpKtdh2?@aIVjvm}66eVs$Pp zxz-fsxVk6S^@r0VU;+ja(N9;OZ2>l_OGy?~x~U|Q1PJrEE;K7Qoq2cnc7OL4lG)X@ zEY9oGFNLF+@U$4kqgWFw{WLO1A~x3cxs#K`N7?JUt~b`r<5|4mWet~=8N4roE@C>I z9{Sy#Y|zoqQl>Bylb6cSxt$yK>j!yx{zzdKa;q^0Uaa#l!=c*4w(MXO!?3^WcKhp7 zH385wg4T`N=vtwW%Ce0M`{@G2G5X`%?~ZRia14b@;ipTUE2aAx{VZk+M3G|(qn1@i zs=PDRj&a+`Js$y>DI*e#NJPw3DJ^PbgTYTaCaK>Y#SRmVjbWnb<#ze$8e`laPZXob zNVFuTvep$2!3_|SfU$0O?1n=(>|MY6^t*q|MECE1(+!8OKmWh38}_HiBq2>1I1Gr_ z=g-sS>2P{Lw9+j&MYe6+4s+p2Ix7!rwO+>i*lAy&qgLVyGazoW$+2Sc)m11@*R>|oG@8@uL$BaO)@AaG z;n7=62i_RnGp@~}imh`S;DA`X-(q_^v5Hx%*p_cgzY!WSEH(P^tTk?(Ao9PGAUW0K zNjC)QTdGEeC}MVGYOVSc5usjj9q(s{?l$WKo9KDec3!-SS?7i>WO$2^v;rGyf}jfZ z#C*<`kET@BOI?OGU~BZx3ynn)s}vsgW_nH;p|`Gh%f`J`{nyvChS&2JGi9+w6k$+# zMYAWN4yCIxoTdBJt&A28==qbxkQqyvX@X4zAmoTBqYBEJSq==p?$4SjvlhC%Rxty& zx_^U)4I^7jVF1dg1bE9aCygE%^;*JBYTLK|hzpZ=`SMl>#&Qo-s++~C$Eu`Y6=EYY zyv0GtO#q8#x@!NHY*?L)K~P2BCxrusom`gX?+;A2%*pugZY2 zAMT8G*XLgfXUWe~iH0vLJNU6EBHw)YZ9Ub|1V7E=Gb*I38+HI7d~WOd)*Np6BF*C^ zIY%2Kx4(Pv z(*+n@*P}7>ct(@7+kU)A_p|wGp)o)IfB$DU>`#wBFvX95^-tuv4~P3SY!*wWRt_gi z&`;Owz2IZ;Qk!4Cd}JmW49mbj_zBVM?;qBXV^LUxHabTv;aL=XK@KEOz|R+oQP@CI zS(agW@Yk9zUk!b*43=cvrNTzI8^qLN;T1`l#e+m4%#(GUXqLt9ppg~zyVK*3f@S&n zI$xi2Uw8@1cS3D1YwVGwrxzuUwGIvXlFrz?Zp_5h87nX8r%%5VAYsvhtn_&Z!2RyU zb)|Oz03ZNKL_t)jmp8>2!(@yz30^a`L}9kp62*BOn=G>&^4u7qA!c+0nd9Z_&qePK z42L)Gve_Zb*Jq0H{PpM6rNS-F_TrwaT&lM6T&1dM0gQ4FUiLtRI>+KZ$V^OkZ@=3e z-(*|-D8~rJFkZd@Ge~ra+JTpY9sQHV>&_HFPEup*W%R?YkU!^XT5r@{Ka`QpbUnA) z2+BZ(lC2tZ|M-LJ20_9$OEfxWw$muDs1jZy@~?l?Bb{ zv4uuo$mQBR!rSz4reY%i#gtBKV0n{*T*L>4d3O>isiqA$yPs>xb%>#v6U zF_yW0`3U%$r`6nWthiL0-mTt`4V@3Owt~aVIBg&qY`5!#e1KLKHDPnLHmaB_uR8&q zS%$_SMY%nIfEX(?AQe4DqEiI_`Fj4h|K>kZQXbAE`^ZFMaVtDsSx;Yn{>$}Uh{02s z<>HQSze__=fNt1PjA6dy`CW`*MpMXs!dp$d?L0o0h3UF(a|Q#z!OtR=eE9*#;L8n@ zY1!faF*RYq2Y<~(c26M%DpA!Vub#AmbH$xVzQFan5)BWnsChWv_rn2=6GeY=3^K;L zJ|{j%=7Z0%i)>8S8nkL)I8y5#kalnhSrq%F7!a_G0F`_mB#cc~VltmYG{)Y)|BW%u zcD+zcWu7OcbQw8lc5G^|yFofR1Poy+|NQQ!Kl9_|%g_G|5%1sq6r+#9M?b|diOeH} zIT`#j_q#hm)P;m5+o#EE1BEVFo~EBFh#P}O;iRxFowv-H@=Hk5^$D|Lfnsp3H_px1 zGXq=K3mvoYnhY9kRk9x8T%JCazKkeBq7+K@Vpj(5hxVqU#5_{nPb%x<1`t zpx|a{}c!y!~MGjl?)N5^OsUzOYkJ5Jc*c%&`8A@Rtgve zUuYnk^`bxpr+2?G#)>d^x}J-MYSBt=ao|u_TM`_qa0n-fU~<8(+ld)r7G)P%XL7(7 zj()#CB`XGsGGY{7Xz*e)o!asHcfUbnr^}OsYZ8T7U^ER1YdYjdK z%$|HiD0!fXk8Tht&lhMxSU_ZLvRnp`h_GpewH2xH;*@NKRkrEgX`r;+I1pd+vm46T z=4{g#v@RFIHOMfV%^@HyvYRvJvqei=nJ;JJ3N&5;xZF>1Q~6%R!p0R}=2Cxs)2T>x z_G*&EU~Gq??L#36O9;57OkNOU&pPrfB5f7r!@2WXFAb4s*@Ql!M6TYM$h zr0pX%4r*l%$9mb}rVPD|qqZ#HDo3hQASUX8ksN!v&Z zJR}uoZmHAKqk>xqZIw-);*)w&7>&`c6pMJ_#WbSD6}CRn%Bg>i+!R{MH?}xb)fh!_ zy5TY^IRwSqoj$5%FndVLUi!u8~H6F!jLq*WxQ@Sv1Q8%ns zI?Hsfjgc)kr`6(yI8(wh7Ja%H{xX;B3|$jJ)+EYfkS@Vk=ei*yFBJS$+)NZqDpkMB zSDs&8f?rTWx9PSZQ1{fBvCeals5@rzyE7Ec@ zl`v=$`AYq(2=J5qlZ)bj`r*(G2iNZk^Qg=8_af$_7_94@-G%AuiEP(d+l|*}VA$Wi zv93FR{iT?}ce|s=7&O^i<^;w#1~$epkx*E>VK3p%)^^6a;AaZ+u)ixn6Ak;q(I5&y z$ixz_D32p0(QtzG%j`-lyz_)Owr~faG0&g=nt}%+M!r6Mglw}=$vD-v5ejQjBSmsl zWv2TI?>iB4qIs$~-V-k}Hgzk6Ux*_=RRoD;D*WUD+eb5D<3x+|_4%HmTY4jB4f5JI@vSBgxnJRpfgkD-(Q zU}i)YqYv}=QurS(C!$%)OH3j0_|pbm6vJq(Ww1b8%stAF3Vy_3T)zWg=XwAzwxck6 zL>Xa;Rl<1wg2q_eOX9r6uHW4;lU!|q*FuCmsF75Ou{6I5b5=QW;b<>IN$L7NXbpPEC)6931Dd+a2Ao8xE&_I4FH9 zML$-bA9*nl(O6?#{Z#o)+uc17ktD87*C(*fnoYrwK_p%F00BY%zLh+x7(CR2ux^^- z6JMaJ7<~+L8{(llDdffen{KNy5~Z!{BdKUw%Tsp!u84W_ujm%4?YvKN42OIQ@CF?a#JqaVwwuI{0E{`A*{N_u_zB()L6q;g+)(kjk~<_jd9 zIJc#%yo3g9J}RnBv(#p{3S6;mV>OXt77k&8xOJyw(NGlc35A5W2cbG*834%m0@QGf zqD`DGPmKuAn0|LCq0s4vB*D{q_h(572V`T4)ODLfgo0hJ{yD=lk(r~Pk`=A%?jF96 zVFu}miHz-PI!d}Ec`s~6`6`J+`&0jf(otSroqfrFpQD|~(aY>YiU{$TrE zn63cOTPHxY_HWXrmD%vq0kSn9_k8WhNL!lsZl1*++h&GjCXpFOqZ!BA!tkrou zGtuGnPFxt%&R}}$dLdFx*K?Rh?Wm&QBL({rNR~YS2&GPcfrwSCb1_CBVxsJ*z)m@h zU}f1l>~PLf$q;q!c5+5L*|*TJ=w0 zHtHmF3rr(jXo-etm`+&378t}Mm|btIt%!+q_nFPx)_Xb(E7dqnU6qF%n>GFmzNWm2 zfJkxn!oL@DfTmK$EucdYF-otKLA-5S)umk9B-aUsCZ?PhVg&{!rjX^avXdl0oMTYq zKvd9Q*(q5fH!J-ohVq|8Vu_&KwW}u_s@NG?rgZDP!v-x$-MqXT2AH-yU>A(vJh`N- zO~%$A^w*NpZ~iel`YJifqw+0+6}M%@;jia8WwQ4M37MCmyD~t>!Yxzne2deKDTUM1$q0c@4)ur`1D&(leI3c;#h%C2*dx$W&A)15+}6NU&;z#pk_= z659xv%BD4zZpSYnpZ%62c)U$Ng?6tc+Hl<@jY_F-dWbiG{kWDL6^GiW(9 zi-~3nsPa~{OWCV6>!$^?^`ct9zh(8K(m>-nB$-I?wsaPhj~^9PkYUNlYjNEsnsl*F z%6FAT`H%kF|G3~w{EBJ1e90@@VKT%M_^Z|D z<{21M5OHWZ9QE5+(%K-$l;6MqO=1Mh*D%kRt7EP%Q_l#{?G6;Y_fyyJUB8cUrVujL zk?XJQG9|vJMI{paM8QiQmd>3i*dh=|iu=2_`@6T+^(OfdgX;!N)^}mLJQdKNVvyjD zsr)K#n-9MY)Ai}&KSMMRKmKV9 zv*>DKm}O>^jU!?q)hEYP=C0p$`{ViZAD%z`{>}T}93MXX{-6FI6ywA9e=I-|ZcYsm z{dnR%g)SM+n$?$(if!@teQ@! zZn$DGs9w_7s6TL#FSFDgFA%1DrMReDv|WIFfs&-lpbnQyk>ML2cf|w|UzJC*4G34a z1I~^fh48fwV{ef#X6fnIq(YhOw3>S;F%j8AUo9=J=*p`$N;&zAdhb>9uZ@TSH7D2 zre@R(_3{z+cMtvkZW_;}r#yfCxxy0-=-SwnSl1Vj$E1Rhh(x!rT(l)8&-KIU;RmUP zDEQL0O4~V}KTFOspqS64)3M*55Gyzq{7gyjk#79%cq)rsBGD6NH+Q!>S4`H2RM2JO zI~-2K{*)C3*9!ZDN!BVePvd#mpZ0fe)kwxXfBIdu5#Mqr*qT>a)ndgpaz!yvn1#eY zUC*hzZRQ-si=FySqo_^PW0jiZS?E&5_WL7XTQJ_ttgi&p%t&4afV9@&(JYdubPyOuHzK1PH)9 zU7x6R9^YIWcY*&P8o?dH!Nd5}`>7rUYmhL|(X;F(2N%FPj_18I-#fMIj6?3G$TU z;Q*L83WU=Qe!j$PW|jpl2C+9VcuOvdf3>x}89Yh^8D^*ta0+Frs|v!_2dWJW+eJ#G0GC^X~Z(Lo%4`m=vs z))f(r&!1&+___L2BoDb5n921A<|yxbd1^)7Cy&0$U^EU>2Af*gU#)Ix*(4&0YObc5 zCe1)u&00!I{i4Hb1iQR)r-db~UjKFBdd*74Tdv_&e}J!UJ8pq>LRL`JQ^b~4jg3=O zE5^qSrEtDKmAKemDmK+=R#s>wxD2dx3SFf*BLW-Kh}_%kh~iEJ|3d#1%}7?nG)xt_uwt1BxrY2a;{HUxn6+d_5xioU1Wlmy|u5%HV@hcYv-hMYX)dDN6 zeeMcV-zz8|mf5+FVnys{WH(Fjx+eFb%joLPR|COo#v z0mil$Tv!ibe_*EJ@W#6S{Q0kqb*|sbhEC#Bfd&yNdZJ*AWq>e^ zM4=mwobuVz^d*EO#MTv3H|+BBRmleHbEYIG3j?TCsw|qh7`7DF%puJC3 zW)9QUxXxy)Ha}j2pXTY@CX?XHWI9N$9o+BkO14)FvjRP_9zA(5IP6Yp`~)$C;KwWh zirUCqWbY+eNwx(d+VaOuKiziXG-6yo$eZG)%RHVb_?W|i(b$53RyRRKHk4z^_5DJ6 zm~cBkDPz3c_)^U@j`O%FtX$0>NY-Xrveup+zE|;Tve+>AD)PW_76s$3}uE9!` zNQo>uo(A;5Rf+aZ`SY*5t(9Z?Yrl0xRFP_M*>P>XPW;-z(?9oTOY!X*V!g@zA$@&D z%qY+p;}9#OQV5nsNtrU11y!#2imClX7OkrMt;B06S;Qj5R+%cz#n5d?GvjG$(Nhh0 zTONceg_TUje1wytwb;tp{?!j7XQk`4v8f+VXXNUi62sG2+17{%O{P*C9aoDfYZ41T z8C47czXUJc06rR0rDg{6YARW>+*(R`GyAh_Y5O$0~GV8mzD2&$J)Y{ZDyXpF*0z?cN zQ*@49KUmkP+=ld96BHh2q8Nkc)$yAM)@>MiCgd12mYFRgQNWZF0D0;|;{Ba)+N!%p z8LliJKbn4jlqw1b2 zk}=X8a>jZguNvou{e3YIh|v>8G)8i3vk_m~9du?}@g$Rfx>;l(TI({DmkM_4Tr=TU zd9ZVo=)323FexWq8%}m-dk&&RNr%%6g z{l4pWqS_Lkp~M-M7dF{tRL+I?@fqPHCj=1ti)`kmyW0~$($TObNdv05cml2N)J z5;2_=NEC~&LIFuB5^~s>_$t2$b^7vhkfhEO@%xm!cK-Yav1hSepUBvVnYLDqmRN~g z*9sg?5!2wN%M%kNY?IjteO54{H}AWwk!L2x^g4;NK$y=IMX0`>mK()pYPTnYIUw6I z1%@;e)=J43ruENUPtoO*4EuZadLU7VN+Da8gdmXXr0+^(;J^&okb*#ktyj1b#ZS`g z4kz2~p`M57TvVVj1Ih$NQ|EiZSU!EYa1^*Jgu*)uXdjv={m2497Uv#K%|* zh+&?Xr7)_!X%-HPj}N7@kn^_SlG#5|jM>9INn#XbR31SIn&0eWpjdzDb8*qB0=E7V zX%}0tA`!9c_sKf~#8!7`%0TODm%o1Lyfg zn6I!R&1Z=IS|-xY><}SGq#EtSlD8m?Cn;qq=fCC6j7XDNVCx{PMtKWZRvF_fq#!d`ii`|bN z+z4Ut#vfC3;Rwo-H$5HzfVgZH=kYnwj&?^h4$;_dKs3>$yoh=9tdwx-EUa&Ld21+A zF$BoDxWF8tO}a=Q5PLbg*0W^Z>fX{$lHcX?mp`~}aQ$v?AG+Zn-M@H8Coo)ocOBns zcnC{7Yyce8kvA`rte9eqVLeN0?I`gjX6+WUc?&2o?c@))A+_emV$NS(+utQ~9c^Tts{&$5_rEESXqoz%cg_vXi8t6xilfZxa$zgR0&kMDfr-J;q7~37 zhH9+HRZ`uMKKM4@6>m@P(|o>|LM+|*lU*FPuvK+rX8wlYBqwKV1)Jnz8llY&vaXjnKq+)*ZgCc|>jujm!NpV&=CouutOs#24H; z=DE!vT<;aD1+2ses|CKucwm{)YRl6mcF`Daj>hUK(Kxua6oK?inVM-!vj=QW4G>EjcAh{J;Npl)HpwsWDnR#LtQO0M!1csev30Dv-#|C zmelt|fhBq{&DX??5OSNy%Nr{FD(%MP%?IBh6oEwe_b+laU;`VEzW8$|1>%sik5fCO>xW9Iw!Kke@xyI}{2ah`}0 z(Oha+Oj3mF60k~n3oYZL!c(?vb1H0-8$+_Pwr#NtWY_HgKr{f-q4vX0-zbVPs;m-0 zJIj%o8b{`ScQ+jGWk(gEcQ@=2z)xqQm>eDe7&v2n%`v>n)>)Rr6hjQ&Za(YH001BW zNklzs8x=Smh4L-4@WC+ybg zr#Hq8-d~nCtWB8p+Sa`d1MgDIr>ZRSNF~NF7WMt=k_7!~ED`(+uko7S&Wx+PxkfM4 z&~Rp5*lF_G{ktE<7_xl9booLt%+r{iYN|d&GAP^&6-L&5<3brx!=hiyCx2NB4@yq} zu#~Th(Kc4(ml2w_WF7sTY|OwI-m(IzIath#+4Ai@oi)6+*kX!|WJ~gazh)(D62q}+ zw%SvWS*40JKQk+i5f^0Lbp5y_t+1}6H&WABEjZll`}yThyLF#I2VX#jE)6nAUeJX= zD7aP()GAw{>V1mFfSG@-_<QB~_Layy#K51$%vZP9Koh5zqQ+#t*S^6Em!q~95XEYB2YsL#v z0|vEg3AI1N7PasdOKW?Xev?3lh&n^Kh=Pg$BbELO*h0VT2>3tzXaANSc`u#;Gav5W zl(3$xgHDDwah~SsIU#E?3g<$~WCRdz`^|SXhOkJMSAh~@W}mFYnTTTuVSfKdf6uzk zbpsmf$8)J`{B+G`IDsj-;O`D^0rC3uDaN@tcCKFu<2vIym4KW}pj>MhYmM#oDR}qx zhtkz`!=8wupP1?T{27$|V~qyr=A#)^GTZFfBxc7%)DOFIpDE6{(Wyjexv_VTKe~R9 zif=kU0YX3Q<#@V0eZD?_!kjjjE{6H^{x?OcUk6BA4a9oob^Wf}9k0)y#^=x7aImfy z6>SkYH2LN$%5Lo*inJNgpgG*XAFof>r;o?`_s2KyFHgT*pFaKgr~j%9Yyk1;I{CjL~b#*GY4iJs)$|$>t9NPHF0Eqpt zGsaGrXUNQvilDg8x<2?RhIw~@-hMZaXFp!D z?qV+C$&Z^W7Z7- zx~|97j?YBW^hi%uJoBvU01W`!ZVtuSxMwa<2FdNsou1Axi=Miu`f8N}k7PnMf^6L^M`swff8x%qa zvs}4uKBnuF&%u@%@;8V^ve<+~^1>t2o1p?NYJP|-vMYe#XJbrpTq8gG>5A4F>o|tw z(+1G*4l*@!{qFwVZzRUpU(eU`=j^#3GQlO)AFfgUzBEnQtTnkE+iiX|*KSXhvM<#F z8!vDaiUczOAraNsuq{NoQs2@nscJNEISaZ`xQK5jBATcwe%j2!Ziu*l14n7x=riyY zk3f;rs@rTC$6!G`a_O`l$S5IZky3+(Js7_1UnPyS!W^*8cY*%NrW_@ z2xiJ0uSrZ-UhjG8$-qsE-*RBGCm6%_R5;J~@Lzxdcq_DNy{DO9F5s6NL@j~W^fvrf ziJUs(l=k^5Ey64Oz*ez@xVW8sD`N0Q7#_A{C84ySK9AKM&DN)RIn(QW8E>^b$ckE1 zBVy2^vBp?t>4;3CZZ%t7+r8yeU+m&mGtSZh^CtPAnXr~EQSD_f2R6Q{FRba__=;uD zEf$7(?hXmA&B5-VUbZ}JCOspB+av#%)M6bOK=h=3O>cKQ0-_}p#tAGgedufe6ZB~Ghm9Lv{NY=E(SzA zJ^mnbsTk(V)5qj!OeE5BCK~pqZg;qR{kgH1yK7$_DAef{OH{CN59kN>L~L$%2!Ng6{7g3O}>BoJ%tugV$Xb065p7F*Pe(j~O(&rPyvI z&!g=xtE*Bs?6PH)*wGuC$BH?{w?1+`nQlYdd4GC5J$#>RpktsI=j+#%%@u48aSMHn zBQfY1=aLOXF>nmFA8^A}veJW%wbt0EtpKp%PBQ8e-D>i_XqWxEF^w@SyjUTt`pQ>Y z*NY)v#R{`E1OQIw&t)jSE-cC%9SxQ&h?<9LO*ia;A*3;LGKWe}(K^iY(bKyhb9slh z>xm*O(rHCkjYVUwPoDrFMh`7>L=68*7@-`G{r*1xm4Y8pot)y@As*}f?#`@6_0=GT zAx2;NLQVCFF>vl#g&tfUO37D3K(v-KmAAZNv7{8`MzQMiM`PT>4}UUWpQp>$ZhzMg$J9*syHY3p@>l;? zH|+1;ewWDPF%%Ajb)77JWadq*qWI$UKULX$qp~iu5L}czkhh#WHQOz z^ajZ^8C!nJ20e0Nu`MwGNhz$70_JMfWq8<^`C(Qu~>+!R`_1iaJ1=2-7 z!zz0sl&FoDq$6+0LnguGV!DD3rgjka)P5J^hL}Z$s!Bu?*r@DzW(2wBf3DI=JA)lyR6vS!!lj5<-e;_?5mNjKv z@4B6o=dK^D>!<58Fn7aV;#|Sl0zV1rZ-H zb^X4??HcQhacFx_&Rs z2N9w2sVaN4j{hZ!W|c8k6xL$fR>@KGm_oFTN!xu4yW^XZsU+Xi@9&s+9-mz|;INlh zPaNa=-GPZ?oSEWud4fb+S41LNiD4GDTZ*Q`q6bYrxfK0$ePUh`(5>xcry$_@`YdiH z(NB;hgF+b>7d^0DKj3M;d@Xbcsm&7sil}@{$QVc}dvjGN`qw%_rg*r2XRIwWNG7WO zUMegmZT*7qq+s#9?Av*pEJ)#1LkV#AGa{l*yPg(M7k_|8sDv_9(<5-%1Ss8nehHqG zEJ>mWG1zWM?;SGJs9U9mIF&Lxm-|%F4QD4d35Yh>T2ExZF<}i@ zIR_Atu!yfM-oWI_YlVms9As<8wanBq)Q#i4f7u*JnspZ83T;>n+AvwuZFl7<>8pi;(jxmWIZ5 zy%0(f!SzF;aRH}x!K4!|*3nL024S914yW|UX+bd8Khr?+e&oPE> z*!R0TKV1cI%jS4qsNprydmcSem`6WdyME9z0P6!+d>SbtgFN@6rhrxwy{8Fr_p*7OxKKh6AE; z-Qc?2bp4uXbSmGx5tvu$NDRJ2RYbMKsg^O#Nj# zwXAiVFQEK(sZlbU%m^CW<*~TM1lFPw|D55RE~w7-ot8 z27us4rYP7=6{;)1T*?A1_%muDEnZtR$qs~>HwX*N^p1&|NN!mN};m!Mgm*Nt4yL$liy4#xsJBUmN; zs0nk%X(os+|Ipg|5KN2tz~1@@Nwl6!A-Y%u^JG-kSHQ^40B!2`92^s011X6 zWm7Q=Ee|FH-w$lvKr!U~oef$*e*gFbr71}~fB9%!H@JQt zpQr0{KkSX|#E@31K!FA&7}6M1<6Hn@uw_;vE+v<*zbx%fnTO-Oyu#^F%W#WZOxj-r zT~fuBB#JVM+xGV};?T{&$)bv>XdY4`8pT{hmwBWDva{86MRT%YS7mRAz(vdyleso3 z_FBQD#6TsKMNkG3l&lv6vXPQ12H%*ENP{9RLdj*;3WZcfmaJ;r!oIe!U);)mUQR%n zvxog+!_4z+BlQmg%E@P}Gt%*-N~*LeVzFVxie)Lj1f2=@ZF%cTsaA4JXazR%7AVcD z&;W)uZ*1ct>b$)w)**-2AOvHqoMLs3g($e~>gTLd;FtPWUc$~P(pD#;QL$WkIZhp0 zym9L#TjGnE)H=nV;2KcVBoAQSOw=o* zRZ(l|1TN!b5Dfqob`UdD^x3MZOlwd!YYUhMqVmv{&9CUwG+1waR#^s8y z8WVw8@VCl|n%dzUG?5MYZu=XfV)xzp_xcx=@LKE&g^<=*VkK*MF4ek@m`z*f)&njS z2ieoBoTlCA%38=*QisG0OQ2gQBgr|-I%G_KPnmEdtk-N$Z_v0j1QA(h-9igfuZnJ3 z|72`QL%e)(GU~9%U=))|`43}Ed86@v`LF(i@*{k1KGrDB>G6BPXN<9~ABgDk^e=#aWv& z>XkP7W#&o~gtzrx{h@I3N(k=)>K^hr74m2|ZVt4KbjhFkhZNDclJw znv^V^nuy&Z^ZaJo5fjbR6<}j7LKJ`alYiNEy&R9@<%x;r@r=ft9)CzyoG9Yq$V`5^ zGCZ5Rn-dcNt*N3g6H#svwx_&kjCIAI9;fTq8hz0B6k`Zp zyBvsY8FFkGEK>bK&lqMt`y)V=6NuI4H)|bZtg%)uLvR8?qz|XZ^1jdG6E?}KOI~(?ZKSQy zKY78UQ5TN@G>_Lx)*^cN{Q11SbS#n5UkqybKc2W40rQ>80HW=>9c~i7hTcLpfHIhumPat^(Lr=0(t(0@%fw;hX$&TqZD;x#=K!m0pX@G*ak^IHCz0xi_c>E zBJRw2id=vPiRH;~PGOp)?HEf)J=~-M<=16>l@d6SerbY*jHbIQM{88=@;|2>hoRX? z>T3)tf~x%xnh9tCjW&G*Mpz;o+-A$?8Fp)E@Zw&P-7AvWp)Pl_rC+*lSYixV5n}*c z;(h~_+ncBfnRRjdeZPI*aN*j)3tc}0m`Y(IeJvxIj3IGzE7GsW)VFpO{;kW;!DU>XTG!np^1E4-? zMbFW=UKO^@OhqcM99&*(hhRanSF?n8|Nb|J)1%-XCAFC;`stk8Q_O>C64rZ)yf793 zbi~!VJY?q8Uy`n0qynW=Io!YB9mHpRxl;hMpDuD4*13fx*!B6N1lN^cG>;bvz9^NK zglkI^v*@Y^N%_cH)R)?bOt>YX!vd8-TVrh&Ey>J1Drt8^SYiyVM$(nPvyL)4c zKwc1z@hVkk47GIKQWU5USkwjNDMp3Lm;4aaB$TS+0PxcYz>8b=GS*CLFubU&yWyBE zDX_*X%Dc?M24bNF7s-VFMT=m+G;9W7fUe&qLxbw0O^__7({G9MB;aGZ#yN+7`wjW(#tklT9Eq z8q*){gCG5Ph1}efCOgbmN>*V^F(QC<9p@Xh^yp7VNGx4Tw>tjhm&z#iJpjl z61|o*A2~DN#wM2HBdUn2ya;7%r1NSP(Tu{1Y#Yb)-(k8+J6Mb@cE?j1BAU+Fj%Y5g zt#yTO!P5U3*JrkQIpPz2FZhWo)GTZ>qZfZv8$uDGiN%_6?z`XqdGtO;kC{q>i1Tz! z3=G6-+etKDz6jydcD;3-7NKb)1t~sUzgxdMDP3#jzn_jRM7@2L^}tN-MaYKO+$8TR zgwJ46Tvi#TOt45#l5r^*M_ow2;><@CJzvX(r3=!APuq3@(Sj2E`mq=^^B9DsFEef^ zpI1rKw|URJa8na2?E-b>seoy2oCMz1X%niEtpyaj2Mde3l^M2&mD{#&FB>P70dN5f zma1QT-4OCc&oI`ag*pU9;Efgy5I23dZ`r*ypH!{#nuxjaCRCcphBMu-0s!*oOVvYi zYQ{QTf5|BPRW~$omzBmyr5`LjsJLj`Q3ceOrnhComp&2moQD5~Pq=;7xBzm{7F`-I zTNc)zAm22j=JGPnW04kN7Vc~Y9jIv~h}NE@Bu%X21stLaFxpn^Y%a5n={4WVr^Orb zhODa+D6}l2=IGzTCwRR%;%YIx9)L)whG1!AB1BY<7l43_&7qL8n^gaIgMjj_=J4h= z&TYc3BGAcRs%L~@x}vo3XSkU#Orth=<2eIgtp;3*DF$-$n)^-4_+`O3i^zfaq*cU|H;s`&FXBi%- zW4P`TDde^oYP3_UMC?jA#)*5We8{+BMfvt_mQM?rZ1SZ;1VCAJ(ga)A%cnZNd4ITn zN5NAJ^23YOyVz)PW_2b8=u(Xn7IaWuTvH6jI5cVRv92$%d6_^?MWL|}--&;RpU%ae zZMb_A{Z#B1WQpedM=C`8Ha`ekYYSgqp(Gk+X5iqx@Gt7H8PT}T7<>QjCpYZERI(UT zbf2uW7=yK)vG(%xvDilYY0SVjSl0<_U&Tsboi?TXBP`s<)Lq%mSa*E$ZrGnxkIu&R zOq6#L4)Zu&#e0%`%MXL#b*Iak_j-ych&OUX8V4 zz9EtrA!;OkVv1X73KNr)es$*E3;Tx5rzIjnvjK|ZU&9(*a2J7P0^b=M7Hw16Lh@5d zO!1r9)_SmnwU^3;HWqOAn+HE{4oe%t1Fj4HB>LW>>Xj&PJpx~BWTF#aFA3#B%QtAZ z_>HnP7i-hS5D2C%nM zLDGY6-s(j0W^W4ot#$lLKMIb@|5kU+nN%#&qYVrD7qPluhq~~sy&zkQAcBh_=oi{{ z!|wQ|;4^-@Pz+@uQHa^+kz?@btQH0hF_e(*GWn=2f`<8$`c*uWDSooxATtZ4t(!?^85tx; zZ8RJXA(N0Ou%v?=vD!vM3S-L$k;upDYdkoXUEUJAg?VN~h`PhJB#FtaSg#i&SgK8l z#X{(0=G%u4Ng0cc2t-5|**N3#cy5ZNd77{on+OXH1;$)z8(MX?z_zQ>d~RlB?p@@- zB=AOdsAmAcP&qXSNgzQ$MJqzEc7R}9ZzL~FC!3CM?9y;RzetT56q-#IdEgKTLbg7y zPCtV{rZU=;&)OZB$2hKwsSZXtG$xBVVT-C4tks2+mIx7GRJXyU zC~k8ZA{y&DPz{XagN4lO8dQSob^-|zMYyI}O<~M2*K|2aO(|+&YXoNSX$Q6yo3iLR zsn#Z&525{MGdZZ;v2}4t$S6t55-ChENL<5k1mQ45B8y$2XGJkRFH$T_B)rZ|>X1iIfJk6+Ju`C%#sDfI%7lM0v2i34A!}%w z@up<1hDn-ZNTudk!I|kzr=~s001BWNkle0OCb8T~5qTwi`_0)O+evUXboQ?V5J^RHW*{gFyte>P_?;4duZ1%`H0pS@MW@= zurF0NMPm#x3vrH#vIcMBwh<>_U9;f1p~0AEUgF9RQ?86D+64W1#>YIGidlFnJ=#aqo1vVEyUn4*MG7Q zA!9Tq$Yy1xDdDI~eF3}J@UmEunyh8~c@@-Nbj4guH??JX;oYX@DQO{z#*}qQ=%ymc zUuv?%?fD*mc!eVl75y4DR_F?pyqV(4&m9+p1YTlER?d+Gt%&JJi<~JkRfwkW;3Mov zBd;WX!VMrpnWl(VU#)DT_7sl-*4dLUHa6x-DiDb1=P8e$wS7sE7b{9Ydq9*BQJXtJ z@CcylC|5l}i=|)b2;#GQDj7A1Xk3F_#b{Q*YY2q};_QXqb=kQFDFh0$fRND`Y=}lg zDG`6RSd1l0SO`575xT`1rr=9%5sXCrT-7;~oM-_MK{;n|OMF9$6HC3+XI^D#R}b2< zIVUQrpRGzGIjBddgr@O&Wmg&0RF)yd2S=T+TT4#^uSz?xCc>`-6o9a7s8r}bT($(( z0e}GbU;pF3l`5IB-P>>ee7YRR)1yx6#S3koF4_Dj8&WR7@wn-drP$C+1Tk$w0JL4# z94IMqZW8{osW6ISS8~#tG`%%z${?Pqf+w?|r&zMU0*LSTw};y(ug)Qm5}`)K0Jx>+`!K4~3WVhY}iPQFY?x4X$=S8FwsC_Kwyj$o*@ zZRG0!FjlVI;JO|8F{o9|>hAT2!`8!EiA^6MF$4bda zl$y~%WhjUgW;C|z_rN?|p0Wgw%#eEV?B}Q+z{FH6T-MtPT|X?B zji9c!t|}dWt7-u;g|GhXUvpwFoS!}?Y}C_uep+UtT#I5$VM%wsLsI5z7N_g_;OAny z7_IMEz)g@4|2MDRl|)cVWpTT~cz$fS5ZOoojYV`sb6o|M_JpLloN9*rd;>ToOkqw0 zm}34AHC^ZFQjSW2q>Jig+ST2#&ki}uRIhTZM2rd^n!@jAU=}Y90O)tOyW0mfYn2k= z=`jnTp|vJzYbaLIV(sDTg3O1ls(cu&VM0mK6qt>3*1CC`ig=r<)DshBWuM02u4NzB z0X@E)@LL79T>VFTZ@<988=gzWUK~)VytaaekV-Gsny@eHgjdcr>-uUHFTXCs=7Ms= zTj!EaF%-Oig)hME+!QN#XOlUlT#(cMDbX`-@}U80ueq!F$J#a8@bX)9l41sL1^Z|$ zGBew#8O4rYiJw#c9>93EbR z$eP9nH%VHhc=*R25QUaQXJ1DEO(r6ArC4GyCMt(RaG$@D?73b#WmN8C#xTVvo zvD_W*4tKAMqzgk1b5v~pBQqP@F^9&sDJo(w>z~YMZH*>}_AyZOZ|(itZ-@vIS;D&B zIJY!>;kpz#o*$?4W5h`(>13|+>@Z)9aTp(ib#gCY86Bch)mNiocWb*!%D~tTfJimZ zi3FqXn0@rM*!Yt?%9$Cgb;&(y^#TgS(!|v(&;Wp+lcQu(dteF@4)05L6+dP?JyDqD z5^GcxM6Qe~w42^oXso?|E1gIV-UmOqZZNJJPagr`_TekZ{=+;yef&KF-n{;5x*W&j zC)r~CaO3*jU zO)w#%5F$XWr6-zZ_>vE>T9t_jlXZYb6^hu;^HN;xg$G;Gd?=7b>pIu(?%#d`h<>_I z2w@)O-R9{M{CI`Zr|AE{!Bg<4%sQ4=xG^S?#}N^y^Aj`0jIj1llvPKeQ1wNCUOq|I zTcc`ZyTNvYpDq-p)mvPW$cz{&l7ZHNlK6mx-0O!uQJ}o(qJb!FZNT-5je$ZSrr~f~ z>9!*Pn537v(37)W#J@0$WZ>7};ca8x(yyR^}nN zSf8v!>>8CUP>iLh=#^y$3Ys*dfYM!+2f6JLG}_;QYgyon1kd1VR==^WP-_T$@mKI_ z!|e-tU@g5#@_uWvC@tx146kp)rvLcjETgde3Rn>|U&;QlY;Im_vR+lIXomy0dggd-(y=W@=uRYZQP5s6L$1#kKR-hyrQ~Pkw&p_N z|M)NeAwN*^&=ELN_EgFHv!0dWSY1OylZV5ys-U>Wx#}4IXFnXcy@s+1k*DChewQgk z{q9!$lJ(djN@6N6Fy}*Dr~;Tcm^p%0rgtU2kT!ty!$hGC(d-WQ!{JWMy5twmPoG2^ ziCeSELiC2D70?J?$SV;O1(JWX&SuwXqCgZL-v2V1UZUCG+_wa)QaiCZn>;`Ln4RR9 zqASow)X&0+&Y(p7;S#*dM|E8vA@WKqIiu`|!r|^M8WX}?`ODXZkf;HuELYQ+DSo7> z-=-Ui4M3c7%K<^WDzBVKqzttq$Sclfbx#~#y}Nn!UQQ)>9SJoqPd}=fKRY*c!=9B} z>u__QkGA8d?;&}-U5=k(9$-7`I%a|#uappkQ1eHPohy#s z%)6WWe%Qv@WiFW#tqSB{LnA8DoueZ@&IjTG#-H z=f@u|r$=2w(tTFf^(wDQkie*NppfdRGm;6%$|NT_J(bxm-wpu7;eL0xXB8C@1!l@Z zfXsY3eJ;jsX@VopAbFJ~I&n4IQnCwwQ2m+l(~8PPc)j_-yb&sKBjNy><)(8griv$9Bz|!{MpLnB9scoZ_Hi{le1S&W>M~Xx z$iyD2Imyv&9CBzV)%7$HHnoVbfNoM@xtx!oG?k-DOTFbdQfV6-C0XS8!$KMgVud_e z>;2$MGoB2PgBNvTuu;}-B++DKJr&Y@TFA`D;gJ9GRp0uUc8nt zFOg+`^!e?!X*8yx=@Nf8wWYEgUQ{hudz@6LTRTkJb-6HA1*d4jOo7rfsWaMIgf_7d zC1?tPqR$^1YjZadtwlCE0Kv8Nv?!K|T5Exg7)cn7bz)L1Md$dW0`6+o4FeD(=Ke&` zVKP(*UBkkkSMJ^{Md}o@80*m3yEk9UiQM)3ZrJN^a@gN7(|CFWG~!O>{U~XKF}*R) z`ziRT8xGl6V>&;gwOzkU*GTD^NiRVlXYyd<`O#R{?{1{kv7B<(?_?Y#?Gy8qcr?}Q z#-=rm$(9-lm42lvTvjTeb)B|rjz+P}+7^l(Qz8KFcL&HW_Qn|Fq)krb zt?P}km#0q}yC6#F%oIt!sf{XFvn-y#>06=y2?$ z3y|6NyFAGe1*gIwSS9|acZdp{fGQ7e?d%ihL1L-g@uf6D@f=V2eNcJcwUQ>bUYla& zV^SCwMY)hr2NtP^XOf^ju@5mnuF;H$$V#JG=ychOT!u9GlC#Rh8EduBL^dXbB(0#j zR8bw1V<5qLkI2&|5k5-gr3*a%7#Su)R_k{4rW5Qa0)QbB8(RT9$IoOeu~X!AF=hP+ zL}Q&^_D#mdm9 zOoPkwYa4J4WHcRZ2EZppKJIYGh*D?E=#1;_gB*P~P!Y+8n8+Asi~}R=f+yurHLZ=+ zI(NcVauQNQ1tKV7I1k994?@$@-_^X}$VmU{W&xBtftyWPz_0Q&K~40Bw+ zM?gPMvY$!extH;Hdl8n(mt96irO1}L7qY#L^=%Y`=;slD$$O$O>~C}1BUi!^ipe$c zMI`4H`XDlY^m@=Sjn!u*m(tqd~33=I8nU}ithfbkGv z<`CvET?`tu-TCRqe2wjHUvuDjzKAO)6LBhKuYL`vvN^|k3*}zIBAUh~@vycNno1kG zimf&U7KpqA84!wG2~kPy7a#~$qTVe>zSy`k2N5mOg*D3SA>V3O08q;%SFw=jg>PoPpBLWe!ajqnw#hmA70Uw(IwI%p|qnC=La{KKflOv0Vwd zj2joB2WBxyL1Qo#&(m3CS(Q?3^lY}w1U?rmlA2SBw{5q}59|t%F&F4G9XQoLvTWF* ztcV+%dD)rd?Oh^G<|yi;%_rl&eb%}G*Rd1Nkci9qyC%M;Ku3^W7||5Cyh!^b_)NUv zfRo`15C=mMfRQw=eT=v%5CwVnjEIZ(2gOo&%(jhLX}K`Pyf%&4v*pBmOg_WI&Yf-r z;D9=RQI*w_a7g!25i1)by_%(86){lp@41wbaD6H<<3W_i1#bjgQd>4kbD**H$eM@E zqL#_3{7Lk|wA6d6x&_=WdqiCR0yd5l)q@d*h-+O7~Qc`G!Qz6TindmjxPK_hN+yiK;7b~PCY??b zjfRj>5DAo$(YU#dwfVYP0C$_X95w2pk=j@+En2s;Tvfw{mb{@rg)N#0|L$-9hM6eZ zn^|pdwk(BbIsY70<>agzcGeAzqI}80MC;wp8c*2uLrRSe0t7#u9)Eyb%t5fOw_UG< zXr#ew8vL>1T7a<*(5AD*>k{ZPHySU;c^qZxtaV^aNazFWy03oquVk(J=^}>X%+T*| zMSM<#2RT}n$6v9o8_!SU`EhAfE5~S!Za{UiNBz=n*rTyhxD&^N*I)m+LMwvO#DxLB*JC=*0l@jxqdVZX=$Kn(Mg{Q{S5$dr6!+*xt6yBt4DVkALKzq@(&^Iywm6r1w6oX9hU z@qEmh4Ac4Zl?%9OB7}L$MnSIMW&OP1XMvcBdtbCRtEXGdW9;?1t~bWsym~9Lw`h#W z8qecJxk`(->)git>XE}dX5WtxyntMCl$AAgrEG3mdCOQ!(*wSJ6hv(EG@j(WTsPdl z{=m$SKm6`+`}*+kK~liSAAWcI^xgYE`4=WZQLM2^eVXTK>W5voJLKnYstDQ1m6|I32S^}Eau4p>s*(R+C}F`L&;=|*$9V35Q#Oc^0_N0)unM)bs;Y< z>Wqir!ppAOzg#JFCCM<(6y0dX^c?P^)(?9Tmjkg55LEcUnI8>B#wMmQjOv1ktpd%X zsI7b=)V9QExXEgY?z>T0(U<98a{NoDt_>Su6-mK5AjNu^mJ|8R$Z4m0%@*Kji&4Y< zF(0#x&AdMc?odea%3ow1eUHVWy8T;@!BFL5uclGU!WDKgCe}kKj_6t1 zWM1SJs9CkJv1T}82JnxuKwK}YV3Yme7a$(O3WF3#DinL)48T_Q=)?yQxl@|l>!f!Q2_Lw%~hOGkP3YKcsyoc(8 zJ(@UzlE$t6jR;D$jtitKbB$8zC9R+$K@16VzUU~k0@jhL5p9*Mn!^hja2pA=JScD_ z+suB1fT#_=Q~8ecTs8|@Oy~1WD}hfuMCkyKTqDzu^U`xQNquS>oqBCmF`6ijT7F29Ap%{pGIS?VnB}& z&EAZk#!UhK;E8-OKO_3)*Z(Gs5;K!HdS_G-QJBXIGl}nZ)lx}8nX%58u1?U$xadW5 zORLj`DN~*`W_r=pR|;fd4q>6Iq?Vg;U6WNvVk+I5mzs`*)y@r1SA(UV+gzue_A^^OWVD5N#tFm=v2-er=ZtO3bRMFgm-X``!0w1{ zDD=djJru2V##%ug-@X3OR7WWReCEsPa{7F|KetW~cg`e{zoKp^Mn>3+enL#e>I<8Re*Tw#tvgl5mYu>;Tca4g ze*D8fRe8Kt?TG6c)TCf~X3jfWYlN<}z_|IJd?b=YIVCZ-iZz(jBG{0I`c%ENWhV^T&4m&HXzj`tkR_k!Iok?)BmB z&F3F}cl`K=Z+`vP#=6fx{ML`7q*?pBHz4pm2D!1Aq3d_H>rbD*OY)5(pomq7nsA8Z z=iuizU;io(DbX6d6*i$3be| zxF|hhl{g}Hiq5X8wp*5G=`!&m<&s=gX5WYwO@pP#XG=aqD=uSw?DHHR5Ls;wD z)8kfKZtFhXd_OFzW{7RC^tvWJuTZtqucTeYP47=fLXr+@mpiR7rfusn*Jj$z_d<+9 z2_o_ub?7G~lAuaNHQZsrqS2XTGA&3SCWHy?`xvt^t|6ubj7b}^NS>}0m?-~0m6dVy zz>&0167Ia0#W*+Dy)Z{Dh?TuvP3O=IB{Y?QZOSTjY*Bo~q+0eeG}aoZX?^W$rSJF; z|NTGz`^8itQ^@99%lbwo?-YVoJnDCcTu^E*D!C^TUAn~M)A<vwV)YtMQF2;OHO=V?4PNTH~O zJ)VuR`Q60}*LHn@_9h#V*vblXm?qh7##a4gW`6kUmzYx3SVK>B!Rd1J)1|IG>Wsx~ zg#yF`O#N`n8TbPT5Qu^X-)|)}H4`X~tHUg04$_dJwX3E;Y*z5@J%nyIB>I&T(7tr2!+@&cyCmXb9EL7%NqA zjP?#mOS4p!udNjre82fVkY;9+xW+U!; z$zbnr|IWHj$}L?#AYwNhIJPIpxP=wYT;nZ)d7e)4LLx69+80D2-`(A?OKm@fE4cm! z4^f{*OVlnAz5V7dGV8$gJ7}b26A4QNh%WFh5BlJqroV(naic=c{^*RY>1QdDE$dAuz6xVg|`nyX5D4!U7iODh|QOf#R0 ze}z7=RixV1YFcf!trusn=LBMln-G{53?Tri9)1bJ7U;XHVHmIGop6N=i(sr1mn@==-e_0iWr*8H43k$f8vI zZ1ZMy9veA}H4pTcb3J$7en}lbD$uX|5*BRCrZwk_!yunj{E6LrJmLgZJ?ti8~F#u&{SJx)Q zm;tB2#6;2JR3NA!2n8aM99ft=I*b;}wygtqOKL;-h$Tod7Qsdy2Vv0zO=$_#3=b`FnU34L!cRW#aaMpO-4m6HeE`|7okdKnL;qef^|}Y zYk)=>O%xAev|1B^DX^GI1FmA#V$Om90P{4Za)!wP1v5F zRA4NmoZq3w1QQW5`0)bD0H8?)GB|ciT0$g9qA~*lfD^d@Y=1rl(JbiP?0w_q-~0Vt z{>9wrYUeXMy%A;Z_OrK_yqBNOlAnk@Z>Fr2yC*d*n&~TDedhS3;)Im~luZA~u?wOR ztf0(7W19uaSh$dA)4;FS6Wu<1$hUG7Nk|}k@^gq(vnZvcSq&M&kZt*L zO)V#>Sk50xmYtllx2;()*5+s_*R_l>Tvu!(UlXnL#dMdY-`}D!&JDR4FS!e3C~s8T zvH+Sw9^qP1FHUp`j43#xiUN^leKPt`x+4X-OW5*#?#|)xEl_45{Amj(Dl1GVshHVmOP>{iR>8r zzIhyswZ#rDGub0XB`}dJ{@iG;oJXNmZ)rAHwNql<-Jn5=94AD8-Qf;J-y_xNICx1~ zD7{+TkIX`^n$C}<2Zb2?Je{BXe4!BJ$NY3ra4JT?IVxqQ?f~eHqX#I;g^}zV2P$xy zXi-L#;?Q(C86#O{3FpM$D6wwH&tvdjb>dClJH}dL4Pqx9Q?xFZM&xA~n8JK{`Vr7r z>*NehY7&+c;=LQh!PhI_T6xCMdh*1^fuZ1eA<_%X`6{tC8_RP-jpkU1m?@y`tW>lR zbH!LS=FIlotn zm-=NVE_OYen~_@RI^M96pMr0)sJN*H2tu* z-7YC%gk{{G{a-S?0KfmU`nRC30MMqV@3or|D=1vXvd~m;MgYKk^YA_nW|l5YzZAmk8}znrN)*3^rntw( zIDzvfB!Y}jk?;}Kk*zR1M=H?}F-d{9TO{dAh-0@3=6E>V>2Qacd5$H63{?wRfFc(I znUX5MJaRCIwLnjuHl>kd05mp5x7^r`$ufwhcR;F*X|-KjKGD^oEzde2W&h_tZUcHmm=%)*}#9{#EFi&UR8Y|)A*`&DJ zoSE$MV}8B_nzW+wvZ~n>K$b~oEe#sc$4F6Y7tjocJ13qk#pWgQy~WqU&trC*1!B{Lhs zJZqp(fj%K3Iz$V`ik-dUFfb)a>fq<|(?Wa{DnZ~iiJ97 zF7k`p1ncq<8~?iL9+wJv$qYS*!-bZfAX=3yJ_A~t46#Q5s0?fWbMzVQhqSUH!U2GK>gNZgK2OZED z%xZ;P+J30))SFqx#R6zLDdw5lehcf<5fy4bpHk3MrO47uL8v4tRxCbNZ)a|b{|ZU5 z!fDIxQo~HfM>03FvZa(oWiSRh*x0h>iioaN*E$j!Nmm453%ZbV;Jc#LEva60D@A5g zIb`A!u1yWLq`P%8kD!V~B@O@XZ~taV1+Dg~nh60EG@Oc<^H%QFcG+GQBjyBTnn^^1 z(!VOEd2H>d(rBO%hW*VNBbYN1{n}a~62;C=wWgWq{@pkGyEn1|#`BYWqjqvoH}VVO z{kZECg+Cq*rOYVBobh}FrbcQ=QgCTny#DZ~RVT9YdYq~D_LEtV+C?I#3j^9;j|{H- zK=jE|UgyTSD2b2@5n`W>3890?6sGY4b+)a-Oa{b$cgTL(EdiMsB>k#;pEVKzDa>KI z=w|!&syV9U^vV)o{zfk758AQ z5%p-yc>avi5K3~R!TUsVU}g|L_8ut9ec1Q3N`DwU$$Zsb)ENCM< zButm_{L~GHZg;pmeVopZ(%jnLyfW6AZh-PFlV&MgPM@dqQL5ryzc)n@euqIB(Fx%w8~7+A$E;pe6+MaMZLT+U`RrPL67TpIwy z+{%q^8wE~fq|vUd>~Yg=am9Av2$>Xk&9Ab9-y3-&oiC;>{w2H=kwOy zu)legEm}heS`eeDBu|&8^W%@OuI4YrziZ-cdMA>)2%5aD>1Q#~hhP4cv@e^#7ve{T zl8xubw%k<%ou=_DYMO|+yM3^>bMVvuTouAzX|!k!TjVMa;Ozj1Ur1wJe$KMh2*m@l z5Xss++;ai3CTjkK1}?L{EdZrQYErj+0-*Pe41948kY@aUIQ##(+AI?wuyd( zDD_O;GHhg~O3eDA6#0veMD16KPzY%Wh`<Bl4|e^2tFIuqUmd;rc}Br{)Fl=~+~2*iu2&f? zO_!s(x!5{qjFG)HUQQIeuw0BFff5o}Z@6QO^AR?VF6pjwiA7+c;t!$J66@ z`mDp&-OVd&oiR4uokn_`(aJG+9hiy=ph%O*&ZSxoO~|Ifk8xSn_73w@K_Vr??shk+ z;RIrRo|z!a_WAMCAM`5CG&^zigGM`+0wC^g9&%~w{PYn3_qVT$H!?s7Gm{Tl1fZ5>pV~i=>-P`lahA4N}LtZtG@Yj*x8K z-DC>h`}`^0u(z%|+`R_CT|CmlEvx6h?uP=Rk7YEC!;OR9$2qCzchp7 z)hfH{=my%zXcf!O#Kz1{KNuOQ~pHLqe_mO@nh&`4X>1qfwtXwmR@i1^a5o zw%KfCX5)HnFukkl;Yoq)>g;g6hIzeDdi^cxr5d|+T&LCRbn>;Aj6`62r6aCU?8z3p z>e6M13=@ehB60G&rwZ1wV*8N0A!w8KOjRZkWtogqh)E7+5MW!^DvH?YF{&TPaz9(^ zppNU6{)5oJ65qU1D6G%-nigD9t+1uuGX<=jftW((lIOkv;(GHf%|#^pCy;M#uFIL* zhvmJQHyS)xyNoSX4Ra+!&$uSS9$zVK$yKV4wA%fm*NWjZy6AxI6&7z=3pbV&r>WavVPFTZf_ z5LmwkWhIYqY|ijzwv)7X%0JQwBzU6)!sr}CIf(QaVV;sPV)3SLI>fpXE5z0$lq!9! zLHGa^W^LzWU7rc&IhGPI-m)x#2qDbl`Iyxq5MjDJWmZOVG>MpA*YCRF#`U}1?SuXp z+x5oS@}&&qX9_-qS=C^19*@i%>5LVzB)j!7K!{ecoB;}K(8zU#2#K{V>X#ge%fx^} zkwk8B^9jX`K;DNiiBwxI5#{a3rAEn2lx*}208Y~hXJd?|D7^;L~sHq9(1ecP8CZLG!=W9ULkepK?GIG@Io|hW8 z6skpe3bfn?Mp-{obu_D+Px`c+<#a$~CYjvjszY4J*e_;~*Y%vRp}WW?XXdDTz$}K>)>r`aaE?m6zL zF~}Ctnt071gUx1u~j);|2;-o-!f=APskFU%}54Kk3|MJU^{& zQfA)WzUp^3qW`k;Vd|6#ehz+|FDKXU<-|mUX*_A&nUx4wIz1dq+!JYA03TyS@|x81>F zk!cqQG!fG~+L9n)#g<}er)1$TB zt9L(_MKYbA#_0lz!jX6^qt;SqqCivr6f`z=7UZVS^*t?$uwpEpFVdzAg<2)Cl~sEQ z`~FJ}3f6x=jN1dQkhh>k@oQ{Drhie)nZ)Wgxjdr&Mh0VD62jozZ)0XQvBY6q@>@1e z@&ITz5^wmbZw_EW$-~09vSCvs*hG2RO)hCYoVnDO^5zU{(1{vv)njx0EhcCp5!;fK zOUZ;Q@D3LF^X;vtt8Lo@CGvP2rv^7vbL(f10<-)_BhKnGWEDimA~nD%Sd7FE?F?#M z?r-b3^99_Y&6WXTEF*%Fn-9T572MXXcg2rc{3SrKD?KD7c58!6%0E1 zEsRpIMT6G%%siex)gs^`GUCcJGb0+~nlMd!(M14Glcu*sg2)QT6mXz%9R)v~9yNN< z2XmfSI)4Tos#Wu)WsHkT2yI)yWxO{VIG@t z&QI0vZo1*7?ze@eaWGw;P>D9k&}Em+27RV^BhM^#=A;lyasl5yyx-lt%Gy^EwXa?| z_-G(17bsCsWrNKOKo-vx9VJ8ze$HwesmGILPML{Zzq@<;GXT`AA!Z)-H?AM#ZO>1i zg76Uv%7t`efW^-l%6Tb!C0yh46?}Q@hJG! z(A20_>ltyNVoNp}xK~0yfM{Lc$7K5I@nuw(WS&|qOy+gSTfhI4zbu*_M7k=IJWmjS z{XA|DBLJ}NhU>CfE1bQQFCc=59w?4!xh%V3FK30iEJ`7CJU?02D_OXvd|3GrGCpge zx4}+px|e@U1n}&)ZIr$jO9x};Db{$6g-z2}_-7QD-~5IZg2y`AWdn2yEk&WqW@F%s zE8n`3w=F&w`S~b$J2EY~7DKa0ae=;3l$MBhP&7djc6`xrC&Cag08e$ z6(vtWnJS_nQg{Qz6Yvi3&+a%EBj_j)|3vojnar7){d~(rL{w)OJ`!1w^IN@!X2 z|7|nBYvX3(VHL~axGT>Ii1X+^YsecWL2TQ2SVi=pDSNz7woH|05z}9tGgMWMyluxH zRF}RQk_P=F8a1=8bYjDt~-c>qN=DihkJYo)Hb~!P79s)8f)&f#>V5*-R|0bB$GEE z7JV<+?`C?KhONQb)@BO+luq8Bo*aGuG#&B-O=P_>&C6IfpJKUAEnM4vmbRX-QUa4H`8XwWcn@ z6}iZ?^l|N;nf3A<@_1&BtMWotvAzqP)tRyHG4|_)_3E;XnfI{H7;|UkY8&OABePqH zF4wCEGxbQ>C_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbF zC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epy ipa2CZKmiI+fC3bt00k&O0SZun0u-PC1t{ +-- + +on run argv + set dmgFile to POSIX file (item 1 of argv) + set diskName to item 2 of argv + set appName to item 3 of argv + + tell application "Finder" + --activate + open dmgFile + delay 1 + set theDisk to disk diskName + open POSIX file "/" + + -- window options: + + set bgfile to file "background.png" of theDisk + set win to the front Finder window + tell win + set target to theDisk + set current view to icon view + set sidebar width to 0 + set toolbar visible to false + set statusbar visible to false + set bounds to {200, 200, 717, 545} + end tell + tell icon view options of win + set icon size to 96 + set background picture to bgfile + end tell + + -- hide background file: + + set bgloc to quoted form of POSIX path of (bgfile as text) + do shell script "SetFile -a V " & bgloc + + -- icon positions: + + set position of file "README" of theDisk to {110, 220} + set position of file "Software License" of theDisk to {400, 220} + set position of file appName of theDisk to {110, 80} + set position of file "Applications" of theDisk to {400, 80} + + eject theDisk + end tell +end run + diff --git a/games/NXDoom/pkg/osx/main.m b/games/NXDoom/pkg/osx/main.m new file mode 100644 index 00000000000..d9e08032e66 --- /dev/null +++ b/games/NXDoom/pkg/osx/main.m @@ -0,0 +1,24 @@ +// +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// + +#include +#include "Execute.h" + +int main(int argc, const char *argv[]) +{ + SetProgramLocation(argv[0]); + + return NSApplicationMain (argc, argv); +} + diff --git a/games/NXDoom/pkg/style.html b/games/NXDoom/pkg/style.html new file mode 100644 index 00000000000..4ae291a3c17 --- /dev/null +++ b/games/NXDoom/pkg/style.html @@ -0,0 +1,48 @@ + + + + + diff --git a/games/NXDoom/pkg/win32/.gitignore b/games/NXDoom/pkg/win32/.gitignore new file mode 100644 index 00000000000..dec280709d5 --- /dev/null +++ b/games/NXDoom/pkg/win32/.gitignore @@ -0,0 +1,2 @@ +staging-* +*.zip diff --git a/games/NXDoom/pkg/win32/GNUmakefile b/games/NXDoom/pkg/win32/GNUmakefile new file mode 100644 index 00000000000..da5fea00524 --- /dev/null +++ b/games/NXDoom/pkg/win32/GNUmakefile @@ -0,0 +1,65 @@ + +include ../config.make + +TOPLEVEL=../.. + +ifeq ($(TARGET_OS),x64) + POSTFIX=win64 +else + POSTFIX=win32 +endif + +PANDOC_FLAGS = -f gfm -s --template=default.html5 -H ../style.html + +DOOM_ZIP=$(PROGRAM_PREFIX)doom-$(PACKAGE_VERSION)-$(POSTFIX).zip +HERETIC_ZIP=$(PROGRAM_PREFIX)heretic-$(PACKAGE_VERSION)-$(POSTFIX).zip +HEXEN_ZIP=$(PROGRAM_PREFIX)hexen-$(PACKAGE_VERSION)-$(POSTFIX).zip +STRIFE_ZIP=$(PROGRAM_PREFIX)strife-$(PACKAGE_VERSION)-$(POSTFIX).zip +ZIPS=$(DOOM_ZIP) $(HERETIC_ZIP) $(HEXEN_ZIP) $(STRIFE_ZIP) + +DLL_FILES=$(TOPLEVEL)/src/SDL.dll \ + $(TOPLEVEL)/src/SDL_mixer.dll \ + $(TOPLEVEL)/src/SDL_net.dll + +all: $(ZIPS) + +$(ZIPS): + zip -j -r $@ $ 0: + filename = to_process.pop() + for dll in file_dependencies(filename, objdump): + try: + dll = find_dll(dll, dll_paths) + if dll not in result: + result |= {dll} + to_process |= {dll} + except IOError as e: + missing |= {dll} + + return result, missing + +def get_dll_path(): + """Examine command line arguments and determine the DLL search path. + + If the --path argument is provided, paths from this are added. + Furthermore, if --ldflags is provided, this is interpreted as a list of + linker flags and the -L paths are used to find associated paths that are + likely to contain DLLs, with the assumption that autotools usually + installs DLLs to ${prefix}/bin when installing Unix-style libraries into + ${prefix}/lib. + + Returns: + List of filesystem paths to check for DLLs. + """ + result = set(args.dll_path) + + if args.ldflags != '': + for arg in shlex.split(args.ldflags): + if arg.startswith("-L"): + prefix, libdir = os.path.split(arg[2:]) + if libdir != "lib": + continue + bindir = os.path.join(prefix, "bin") + if os.path.exists(bindir): + result |= {bindir} + + return list(result) + +args = parser.parse_args() + +dll_path = get_dll_path() +dll_files, missing = all_dependencies(args.source, args.objdump, dll_path) + +# Exit with failure if DLLs are missing. +if missing: + sys.stderr.write("Missing DLLs not found in path %s:\n" % (dll_path,)) + for filename in missing: + sys.stderr.write("\t%s\n" % filename) + sys.exit(1) + +# Destination may be a full path (rename) or may be a directory to copy into: +# cp foo.exe bar/baz.exe +# cp foo.exe bar/ +if os.path.isdir(args.destination): + dest_dir = args.destination +else: + dest_dir = os.path.dirname(args.destination) + +# Copy .exe and DLLs. +shutil.copy(args.source, args.destination) +for filename in dll_files: + shutil.copy(filename, dest_dir) + diff --git a/games/NXDoom/rpm.spec.in b/games/NXDoom/rpm.spec.in new file mode 100644 index 00000000000..330523104ec --- /dev/null +++ b/games/NXDoom/rpm.spec.in @@ -0,0 +1,121 @@ + +Name: @PACKAGE@ +Summary: @PACKAGE_SHORTDESC@ +Version: @VERSION@ +Release: 1 +Source: https://www.chocolate-doom.org/downloads/@VERSION@/@PACKAGE@-@VERSION@.tar.gz +URL: @PACKAGE_URL@ +Group: Amusements/Games +BuildRoot: /var/tmp/@PACKAGE@-buildroot +License: @PACKAGE_LICENSE@ +Packager: @PACKAGE_MAINTAINER@ <@PACKAGE_BUGREPORT@> +Prefix: %{_prefix} +Autoreq: 0 +Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 + +%prep +rm -rf $RPM_BUILD_ROOT + +%setup -q + +%build +./configure \ + --prefix=/usr \ + --exec-prefix=/usr \ + --bindir=/usr/bin \ + --sbindir=/usr/sbin \ + --sysconfdir=/etc \ + --datadir=/usr/share \ + --includedir=/usr/include \ + --libdir=/usr/lib \ + --libexecdir=/usr/lib \ + --localstatedir=/var/lib \ + --sharedstatedir=/usr/com \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info +make + +%install +%makeinstall + +%clean +rm -rf $RPM_BUILD_ROOT + +%description +%(sed -n "/##/ q; p " < README.md) + +See @PACKAGE_URL@ for more information. + +%package -n @PROGRAM_PREFIX@heretic +Summary: @PACKAGE_SHORTDESC@ (Heretic binaries) +Group: Amusements/Games +Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 + +%files +%{_mandir}/man5/@PROGRAM_PREFIX@doom.cfg.5* +%{_mandir}/man5/default.cfg.5* +%{_mandir}/man6/@PROGRAM_PREFIX@doom.6* +%{_mandir}/man6/@PROGRAM_PREFIX@setup.6* +%{_mandir}/man6/@PROGRAM_PREFIX@server.6* +/usr/share/doc/@PACKAGE@/* +/usr/games/@PROGRAM_PREFIX@doom +/usr/games/@PROGRAM_PREFIX@server +/usr/games/@PROGRAM_PREFIX@doom-setup +/usr/share/icons/hicolor/128x128/apps/* +/usr/share/applications/* + +%description -n @PROGRAM_PREFIX@heretic +%(sed -n "/##/ q; p " < README.md) + +These are the Heretic binaries. + +See @PACKAGE_URL@ for more information. + +%files -n @PROGRAM_PREFIX@heretic +%{_mandir}/man5/@PROGRAM_PREFIX@heretic.cfg.5* +%{_mandir}/man5/heretic.cfg.5* +%{_mandir}/man6/@PROGRAM_PREFIX@heretic.6* +/usr/share/doc/@PROGRAM_PREFIX@heretic/* +/usr/games/@PROGRAM_PREFIX@heretic +/usr/games/@PROGRAM_PREFIX@heretic-setup + +%package -n @PROGRAM_PREFIX@hexen +Summary: @PACKAGE_SHORTDESC@ (Hexen binaries) +Group: Amusements/Games +Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 + +%description -n @PROGRAM_PREFIX@hexen +%(sed -n "/##/ q; p " < README.md) + +These are the Hexen binaries. + +See @PACKAGE_URL@ for more information. + +%files -n @PROGRAM_PREFIX@hexen +%{_mandir}/man5/@PROGRAM_PREFIX@hexen.cfg.5* +%{_mandir}/man5/hexen.cfg.5* +%{_mandir}/man6/@PROGRAM_PREFIX@hexen.6* +/usr/share/doc/@PROGRAM_PREFIX@hexen/* +/usr/games/@PROGRAM_PREFIX@hexen +/usr/games/@PROGRAM_PREFIX@hexen-setup + +%package -n @PROGRAM_PREFIX@strife +Summary: @PACKAGE_SHORTDESC@ (Strife binaries) +Group: Amusements/Games +Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0 + +%description -n @PROGRAM_PREFIX@strife +%(sed -n "/##/ q; p " < README.md) + +These are the Strife binaries. + +See @PACKAGE_URL@ for more information. + +%files -n @PROGRAM_PREFIX@strife +%{_mandir}/man5/@PROGRAM_PREFIX@strife.cfg.5* +%{_mandir}/man5/strife.cfg.5* +%{_mandir}/man6/@PROGRAM_PREFIX@strife.6* +/usr/share/doc/@PROGRAM_PREFIX@strife/* +/usr/games/@PROGRAM_PREFIX@strife +/usr/games/@PROGRAM_PREFIX@strife-setup + diff --git a/games/NXDoom/src/.gitignore b/games/NXDoom/src/.gitignore new file mode 100644 index 00000000000..a3127e6bd85 --- /dev/null +++ b/games/NXDoom/src/.gitignore @@ -0,0 +1,22 @@ +Makefile +Makefile.in +.deps +*.rc +chocolate-doom +chocolate-heretic +chocolate-hexen +chocolate-server +chocolate-strife +chocolate-doom-setup +chocolate-heretic-setup +chocolate-hexen-setup +chocolate-strife-setup +chocolate-setup +*.cfg +*.exe +*.desktop +*.txt +!CMakeLists.txt +*.metainfo.xml +tags +TAGS diff --git a/games/NXDoom/src/CMakeLists.txt b/games/NXDoom/src/CMakeLists.txt new file mode 100644 index 00000000000..336a5241c34 --- /dev/null +++ b/games/NXDoom/src/CMakeLists.txt @@ -0,0 +1,287 @@ +foreach(SUBDIR doom heretic hexen strife setup) + add_subdirectory("${SUBDIR}") +endforeach() + +# Common source files used by absolutely everything: + +set(COMMON_SOURCE_FILES + i_main.c + i_system.c i_system.h + m_argv.c m_argv.h + m_misc.c m_misc.h) + +# Dedicated server (chocolate-server): + +set(DEDSERV_FILES + d_dedicated.c + d_iwad.c d_iwad.h + d_mode.c d_mode.h + deh_str.c deh_str.h + i_timer.c i_timer.h + m_config.c m_config.h + net_common.c net_common.h + net_dedicated.c net_dedicated.h + net_io.c net_io.h + net_packet.c net_packet.h + net_sdl.c net_sdl.h + net_query.c net_query.h + net_server.c net_server.h + net_structrw.c net_structrw.h + z_native.c z_zone.h) + +add_executable("${PROGRAM_PREFIX}server" WIN32 ${COMMON_SOURCE_FILES} ${DEDSERV_FILES}) +target_include_directories("${PROGRAM_PREFIX}server" + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") + +if (DEFINED EMSCRIPTEN) + set(SDL_FLAGS "-s USE_SDL=2") + if(ENABLE_SDL2_MIXER) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_MIXER=2") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL_MIXER=2") + endif() + if(ENABLE_SDL2_NET) + set(SDL_FLAGS "${SDL_FLAGS} -s USE_SDL_NET=2") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL_NET=2") + endif() +else() + set(SDL_LINK_LIBS SDL2::SDL2main SDL2::SDL2) + if(ENABLE_SDL2_MIXER) + list(APPEND SDL_LINK_LIBS SDL2_mixer::SDL2_mixer) + endif() + if(ENABLE_SDL2_NET) + list(APPEND SDL_LINK_LIBS SDL2_net::SDL2_net) + endif() +endif() + +target_link_libraries("${PROGRAM_PREFIX}server" ${SDL_LINK_LIBS}) +set_target_properties("${PROGRAM_PREFIX}server" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") +set_target_properties("${PROGRAM_PREFIX}server" PROPERTIES LINK_FLAGS "${SDL_FLAGS}") + +# Source files used by the game binaries (chocolate-doom, etc.) + +set(GAME_SOURCE_FILES + aes_prng.c aes_prng.h + d_event.c d_event.h + doomkeys.h + doomtype.h + d_iwad.c d_iwad.h + d_loop.c d_loop.h + d_mode.c d_mode.h + d_ticcmd.h + deh_str.c deh_str.h + gusconf.c gusconf.h + i_cdmus.c i_cdmus.h + i_endoom.c i_endoom.h + i_flmusic.c + i_glob.c i_glob.h + i_input.c i_input.h + i_joystick.c i_joystick.h + i_swap.h + i_musicpack.c + i_oplmusic.c + i_pcsound.c + i_sdlmusic.c + i_sdlsound.c + i_sound.c i_sound.h + i_timer.c i_timer.h + i_video.c i_video.h + i_videohr.c i_videohr.h + i_winmusic.c + midifallback.c midifallback.h + midifile.c midifile.h + mus2mid.c mus2mid.h + m_bbox.c m_bbox.h + m_cheat.c m_cheat.h + m_config.c m_config.h + m_controls.c m_controls.h + m_fixed.c m_fixed.h + net_client.c net_client.h + net_common.c net_common.h + net_dedicated.c net_dedicated.h + net_defs.h + net_gui.c net_gui.h + net_io.c net_io.h + net_loop.c net_loop.h + net_packet.c net_packet.h + net_petname.c net_petname.h + net_query.c net_query.h + net_sdl.c net_sdl.h + net_server.c net_server.h + net_structrw.c net_structrw.h + p_rejectpad.c p_rejectpad.h + sha1.c sha1.h + memio.c memio.h + tables.c tables.h + v_diskicon.c v_diskicon.h + v_video.c v_video.h + v_patch.h + w_checksum.c w_checksum.h + w_main.c w_main.h + w_wad.c w_wad.h + w_file.c w_file.h + w_file_stdc.c + w_file_posix.c + w_file_win32.c + w_merge.c w_merge.h + z_zone.c z_zone.h) + +set(GAME_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}/../") + +if(WIN32) + list(APPEND GAME_SOURCE_FILES + "../win32/win_opendir.c" "../win32/win_opendir.h") + + list(APPEND GAME_INCLUDE_DIRS + "${PROJECT_SOURCE_DIR}/win32/") +endif() + +set(DEHACKED_SOURCE_FILES + deh_defs.h + deh_io.c deh_io.h + deh_main.c deh_main.h + deh_mapping.c deh_mapping.h + deh_text.c) + +# Some games support dehacked patches, some don't: + +set(SOURCE_FILES ${COMMON_SOURCE_FILES} ${GAME_SOURCE_FILES}) +set(SOURCE_FILES_WITH_DEH ${SOURCE_FILES} ${DEHACKED_SOURCE_FILES}) + +set(EXTRA_LIBS ${SDL_LINK_LIBS} textscreen pcsound opl) +if(SampleRate_FOUND) + list(APPEND EXTRA_LIBS SampleRate::samplerate) +endif() +if(PNG_FOUND) + list(APPEND EXTRA_LIBS PNG::PNG) +endif() +if(FluidSynth_FOUND) + list(APPEND EXTRA_LIBS FluidSynth::libfluidsynth) +endif() +if(WIN32) + list(APPEND EXTRA_LIBS winmm shlwapi) +endif() + +if(WIN32) + add_executable("${PROGRAM_PREFIX}doom" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/doom-res.rc") +else() + add_executable("${PROGRAM_PREFIX}doom" ${SOURCE_FILES_WITH_DEH}) +endif() + +target_include_directories("${PROGRAM_PREFIX}doom" PRIVATE ${GAME_INCLUDE_DIRS}) +target_link_libraries("${PROGRAM_PREFIX}doom" doom ${EXTRA_LIBS}) +set_target_properties("${PROGRAM_PREFIX}doom" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") + +if(MSVC) + set_target_properties("${PROGRAM_PREFIX}doom" PROPERTIES + LINK_FLAGS "/MANIFEST:NO") +endif() + +if(WIN32) + add_executable("${PROGRAM_PREFIX}heretic" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/heretic-res.rc") +else() + add_executable("${PROGRAM_PREFIX}heretic" ${SOURCE_FILES_WITH_DEH}) +endif() + +target_include_directories("${PROGRAM_PREFIX}heretic" PRIVATE ${GAME_INCLUDE_DIRS}) +target_link_libraries("${PROGRAM_PREFIX}heretic" heretic ${EXTRA_LIBS}) +set_target_properties("${PROGRAM_PREFIX}heretic" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") + +if(MSVC) + set_target_properties("${PROGRAM_PREFIX}heretic" PROPERTIES + LINK_FLAGS "/MANIFEST:NO") +endif() + +if(WIN32) + add_executable("${PROGRAM_PREFIX}hexen" WIN32 ${SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/hexen-res.rc") +else() + add_executable("${PROGRAM_PREFIX}hexen" ${SOURCE_FILES}) +endif() + +target_include_directories("${PROGRAM_PREFIX}hexen" PRIVATE ${GAME_INCLUDE_DIRS}) +target_link_libraries("${PROGRAM_PREFIX}hexen" hexen ${EXTRA_LIBS}) +set_target_properties("${PROGRAM_PREFIX}hexen" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") + +if(MSVC) + set_target_properties("${PROGRAM_PREFIX}hexen" PROPERTIES + LINK_FLAGS "/MANIFEST:NO") +endif() + +if(WIN32) + add_executable("${PROGRAM_PREFIX}strife" WIN32 ${SOURCE_FILES_WITH_DEH} "${CMAKE_CURRENT_BINARY_DIR}/strife-res.rc") +else() + add_executable("${PROGRAM_PREFIX}strife" ${SOURCE_FILES_WITH_DEH}) +endif() + +target_include_directories("${PROGRAM_PREFIX}strife" PRIVATE ${GAME_INCLUDE_DIRS}) +target_link_libraries("${PROGRAM_PREFIX}strife" strife ${EXTRA_LIBS}) +set_target_properties("${PROGRAM_PREFIX}strife" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") + +if(MSVC) + set_target_properties("${PROGRAM_PREFIX}strife" PROPERTIES + LINK_FLAGS "/MANIFEST:NO") +endif() + +# Source files needed for chocolate-setup: + +set(SETUP_FILES + deh_str.c deh_str.h + d_mode.c d_mode.h + d_iwad.c d_iwad.h + i_timer.c i_timer.h + m_config.c m_config.h + m_controls.c m_controls.h + net_io.c net_io.h + net_packet.c net_packet.h + net_petname.c net_petname.h + net_sdl.c net_sdl.h + net_query.c net_query.h + net_structrw.c net_structrw.h + z_native.c z_zone.h) + +if(WIN32) + add_executable("${PROGRAM_PREFIX}setup" WIN32 ${SETUP_FILES} ${COMMON_SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/setup-res.rc") +else() + add_executable("${PROGRAM_PREFIX}setup" ${SETUP_FILES} ${COMMON_SOURCE_FILES}) +endif() + +target_include_directories("${PROGRAM_PREFIX}setup" + PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") +target_link_libraries("${PROGRAM_PREFIX}setup" ${SDL_LINK_LIBS} setup textscreen) +set_target_properties("${PROGRAM_PREFIX}setup" PROPERTIES COMPILE_FLAGS "${SDL_FLAGS}") + +if(WIN32) + target_link_libraries("${PROGRAM_PREFIX}setup" winmm) +endif() + +if(MSVC) + set_target_properties("${PROGRAM_PREFIX}setup" PROPERTIES + LINK_FLAGS "/MANIFEST:NO") +endif() + +if (DEFINED EMSCRIPTEN) + set_target_properties("${PROGRAM_PREFIX}setup" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") + set_target_properties("${PROGRAM_PREFIX}strife" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") + set_target_properties("${PROGRAM_PREFIX}doom" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") + set_target_properties("${PROGRAM_PREFIX}heretic" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") + set_target_properties("${PROGRAM_PREFIX}hexen" PROPERTIES LINK_FLAGS "${SDL_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_FUNCTIONS=_main,ccall,cwrap,FS,ENV,PATH,ERRNO_CODES") +endif() + +add_executable(midiread midifile.c z_native.c i_system.c m_argv.c m_misc.c d_iwad.c deh_str.c m_config.c) +target_compile_definitions(midiread PRIVATE "-DTEST") +target_include_directories(midiread PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") +if (DEFINED EMSCRIPTEN) + set_target_properties(midiread PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") + set_target_properties(midiread PROPERTIES LINK_FLAGS "-s USE_SDL=2") +else() + target_link_libraries(midiread SDL2::SDL2) +endif() + +add_executable(mus2mid mus2mid.c memio.c z_native.c i_system.c m_argv.c m_misc.c d_iwad.c deh_str.c m_config.c) +target_compile_definitions(mus2mid PRIVATE "-DSTANDALONE") +target_include_directories(mus2mid PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../") +if (DEFINED EMSCRIPTEN) + set_target_properties(mus2mid PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") + set_target_properties(mus2mid PROPERTIES LINK_FLAGS "-s USE_SDL=2") +else() + target_link_libraries(mus2mid SDL2::SDL2) +endif() diff --git a/games/NXDoom/src/Doom.desktop.in b/games/NXDoom/src/Doom.desktop.in new file mode 100644 index 00000000000..1ec35b3715b --- /dev/null +++ b/games/NXDoom/src/Doom.desktop.in @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=@PACKAGE_SHORTNAME@ Doom +Exec=@PROGRAM_PREFIX@doom +Icon=@PROGRAM_PREFIX@doom +Type=Application +Comment=@PACKAGE_SHORTDESC@ +Categories=Game;ActionGame; +Keywords=first;person;shooter;vanilla; diff --git a/games/NXDoom/src/Doom.metainfo.xml.in b/games/NXDoom/src/Doom.metainfo.xml.in new file mode 100644 index 00000000000..32b9172ead7 --- /dev/null +++ b/games/NXDoom/src/Doom.metainfo.xml.in @@ -0,0 +1,74 @@ + + + + @PACKAGE_RDNS@.Doom + @PACKAGE_RDNS@.Doom.desktop + @PACKAGE_SHORTNAME@ Doom +